summaryrefslogtreecommitdiffstats
path: root/.travis.yml
blob: f2095d01825f1b65abeb8b990620d358b8cf870a (plain)
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
sudo: required
language: c
addons:
  apt:
    packages:
      - tcl-dev
      - libx11-dev
matrix:
  include:
    - os: linux
      dist: trusty
      compiler: clang
      env:
        - BUILD_DIR=unix
    - os: linux
      dist: trusty
      compiler: clang
      env:
        - CFGOPT=--disable-shared
        - BUILD_DIR=unix
    - os: linux
      dist: trusty
      compiler: gcc
      env:
        - BUILD_DIR=unix
    - os: linux
      dist: trusty
      compiler: gcc
      env:
        - CFGOPT=--disable-shared
        - BUILD_DIR=unix
    - os: linux
      dist: trusty
      compiler: gcc-4.9
      addons:
        apt:
          sources:
            - ubuntu-toolchain-r-test
          packages:
            - g++-4.9
      env:
        - BUILD_DIR=unix
    - os: linux
      dist: trusty
      compiler: gcc-5
      addons:
        apt:
          sources:
            - ubuntu-toolchain-r-test
          packages:
            - g++-5
      env:
        - BUILD_DIR=unix
    - os: linux
      dist: trusty
      compiler: gcc-6
      addons:
        apt:
          sources:
            - ubuntu-toolchain-r-test
          packages:
            - g++-6
      env:
        - BUILD_DIR=unix
    - os: linux
      dist: trusty
      compiler: gcc-7
      addons:
        apt:
          sources:
            - ubuntu-toolchain-r-test
          packages:
            - g++-7
      env:
        - BUILD_DIR=unix
before_install:
  - export ERROR_ON_FAILURES=1
  - cd ${BUILD_DIR}
install:
  - test -n "$NO_DIRECT_CONFIGURE" || ./configure ${CFGOPT}
script:
  - make
  # The styles=develop avoids some weird problems on OSX
  #- test -n "$NO_DIRECT_TEST" || make test styles=develop
tle Tcl is a high-level, general-purpose, interpreted, dynamic programming language. It was designed with the goal of being very simple but powerful.
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat
-rw-r--r--ChangeLog15702
-rw-r--r--ChangeLog.19992738
-rw-r--r--ChangeLog.20001868
-rw-r--r--ChangeLog.20013023
-rw-r--r--ChangeLog.20024741
-rw-r--r--ChangeLog.20033349
-rw-r--r--ChangeLog.20044619
-rw-r--r--ChangeLog.20053822
-rw-r--r--README16
-rw-r--r--changes1271
-rw-r--r--compat/fixstrtod.c8
-rw-r--r--compat/gettod.c8
-rw-r--r--compat/memcmp.c40
-rw-r--r--compat/opendir.c117
-rw-r--r--compat/strftime.c515
-rw-r--r--compat/string.h2
-rw-r--r--compat/strncasecmp.c44
-rw-r--r--compat/strstr.c29
-rw-r--r--compat/strtod.c62
-rw-r--r--compat/strtol.c39
-rw-r--r--compat/strtoll.c109
-rw-r--r--compat/strtoul.c70
-rw-r--r--compat/strtoull.c259
-rw-r--r--compat/tclErrno.h97
-rw-r--r--compat/tmpnam.c40
-rw-r--r--compat/waitpid.c92
-rw-r--r--doc/Access.32
-rw-r--r--doc/AddErrInfo.3279
-rw-r--r--doc/Alloc.310
-rw-r--r--doc/AllowExc.38
-rw-r--r--doc/AppInit.310
-rw-r--r--doc/AssocData.314
-rw-r--r--doc/Async.316
-rw-r--r--doc/BackgdErr.333
-rw-r--r--doc/Backslash.38
-rw-r--r--doc/BoolObj.3106
-rw-r--r--doc/ByteArrObj.36
-rw-r--r--doc/CallDel.36
-rw-r--r--doc/ChnlStack.320
-rw-r--r--doc/CmdCmplt.34
-rw-r--r--doc/Concat.38
-rw-r--r--doc/CrtChannel.3375
-rw-r--r--doc/CrtChnlHdlr.36
-rw-r--r--doc/CrtCloseHdlr.34
-rw-r--r--doc/CrtCommand.329
-rw-r--r--doc/CrtFileHdlr.314
-rw-r--r--doc/CrtMathFnc.391
-rw-r--r--doc/CrtObjCmd.351
-rw-r--r--doc/CrtSlave.367
-rw-r--r--doc/CrtTimerHdlr.39
-rw-r--r--doc/CrtTrace.343
-rw-r--r--doc/DString.328
-rw-r--r--doc/DetachPids.316
-rw-r--r--doc/DictObj.3234
-rw-r--r--doc/DoOneEvent.38
-rw-r--r--doc/DoWhenIdle.34
-rw-r--r--doc/DoubleObj.365
-rw-r--r--doc/DumpActiveMemory.35
-rw-r--r--doc/Encoding.3241
-rw-r--r--doc/Ensemble.3186
-rw-r--r--doc/Environment.320
-rw-r--r--doc/Eval.347
-rw-r--r--doc/Exit.336
-rw-r--r--doc/ExprLong.324
-rw-r--r--doc/ExprLongObj.36
-rw-r--r--doc/FileSystem.31074
-rw-r--r--doc/FindExec.34
-rw-r--r--[-rwxr-xr-x]doc/GetCwd.34
-rw-r--r--doc/GetHostName.32
-rw-r--r--doc/GetIndex.339
-rw-r--r--doc/GetInt.355
-rw-r--r--doc/GetOpnFl.322
-rw-r--r--doc/GetStdChan.33
-rw-r--r--doc/GetTime.357
-rw-r--r--[-rwxr-xr-x]doc/GetVersion.31
-rw-r--r--doc/Hash.3141
-rw-r--r--doc/Init.37
-rw-r--r--doc/InitStubs.310
-rw-r--r--doc/IntObj.3199
-rw-r--r--doc/Interp.320
-rw-r--r--doc/Limit.3194
-rw-r--r--doc/LinkVar.3122
-rw-r--r--doc/ListObj.327
-rw-r--r--doc/Macintosh.3109
-rw-r--r--doc/Namespace.3165
-rw-r--r--doc/Notifier.3141
-rw-r--r--doc/Object.374
-rw-r--r--doc/ObjectType.3147
-rw-r--r--doc/OpenFileChnl.382
-rw-r--r--doc/OpenTcp.327
-rw-r--r--doc/Panic.324
-rw-r--r--doc/ParseCmd.3104
-rw-r--r--doc/PkgRequire.333
-rw-r--r--doc/Preserve.34
-rw-r--r--doc/PrintDbl.328
-rw-r--r--doc/RecEvalObj.316
-rw-r--r--doc/RecordEval.316
-rw-r--r--doc/RegConfig.3112
-rw-r--r--doc/RegExp.3183
-rw-r--r--doc/SaveResult.385
-rw-r--r--doc/SetChanErr.3153
-rw-r--r--doc/SetErrno.312
-rw-r--r--doc/SetResult.387
-rw-r--r--doc/SetVar.360
-rw-r--r--doc/Signal.312
-rw-r--r--doc/Sleep.35
-rw-r--r--doc/SourceRCFile.35
-rw-r--r--doc/SplitList.324
-rw-r--r--doc/SplitPath.38
-rw-r--r--doc/StaticPkg.38
-rw-r--r--doc/StdChannels.335
-rw-r--r--doc/StrMatch.329
-rw-r--r--doc/StringObj.3142
-rw-r--r--doc/SubstObj.317
-rw-r--r--doc/TCL_MEM_DEBUG.337
-rw-r--r--doc/Tcl.n75
-rw-r--r--doc/Tcl_Main.322
-rw-r--r--doc/Thread.392
-rw-r--r--doc/ToUpper.32
-rw-r--r--doc/TraceCmd.355
-rw-r--r--doc/TraceVar.3103
-rw-r--r--doc/Translate.324
-rw-r--r--doc/UniCharIsAlpha.33
-rw-r--r--doc/UpVar.321
-rw-r--r--doc/Utf.398
-rw-r--r--doc/WrongNumArgs.311
-rw-r--r--doc/after.n10
-rw-r--r--doc/append.n9
-rw-r--r--doc/apply.n96
-rw-r--r--doc/array.n48
-rw-r--r--doc/bgerror.n41
-rw-r--r--doc/binary.n489
-rw-r--r--doc/catch.n66
-rw-r--r--doc/chan.n736
-rw-r--r--doc/clock.n1089
-rw-r--r--doc/close.n8
-rw-r--r--doc/concat.n34
-rw-r--r--doc/dde.n63
-rw-r--r--doc/dict.n370
-rw-r--r--doc/encoding.n20
-rw-r--r--doc/error.n48
-rw-r--r--doc/eval.n50
-rw-r--r--doc/exec.n197
-rw-r--r--doc/exit.n10
-rw-r--r--doc/expr.n351
-rw-r--r--doc/fblocked.n2
-rw-r--r--doc/fconfigure.n50
-rw-r--r--doc/fcopy.n93
-rw-r--r--doc/file.n245
-rw-r--r--doc/fileevent.n12
-rw-r--r--doc/filename.n148
-rw-r--r--doc/flush.n2
-rw-r--r--doc/for.n2
-rw-r--r--doc/foreach.n29
-rw-r--r--doc/format.n94
-rw-r--r--doc/gets.n2
-rw-r--r--doc/glob.n104
-rw-r--r--doc/global.n6
-rw-r--r--doc/history.n22
-rw-r--r--doc/http.n271
-rw-r--r--doc/if.n3
-rw-r--r--doc/incr.n8
-rw-r--r--doc/info.n160
-rw-r--r--doc/interp.n402
-rw-r--r--doc/join.n4
-rw-r--r--doc/lappend.n17
-rw-r--r--doc/lassign.n55
-rw-r--r--doc/library.n48
-rw-r--r--doc/lindex.n55
-rw-r--r--doc/linsert.n18
-rw-r--r--doc/list.n11
-rw-r--r--doc/llength.n4
-rw-r--r--doc/load.n29
-rw-r--r--doc/lrange.n27
-rw-r--r--doc/lrepeat.n39
-rw-r--r--doc/lreplace.n55
-rw-r--r--doc/lreverse.n31
-rw-r--r--doc/lsearch.n221
-rw-r--r--[-rwxr-xr-x]doc/lset.n53
-rw-r--r--doc/lsort.n67
-rw-r--r--doc/man.macros201
-rw-r--r--doc/mathfunc.n271
-rw-r--r--doc/mathop.n299
-rw-r--r--doc/memory.n34
-rw-r--r--doc/msgcat.n93
-rw-r--r--doc/namespace.n325
-rw-r--r--doc/open.n105
-rw-r--r--doc/package.n195
-rw-r--r--doc/packagens.n5
-rw-r--r--doc/pid.n2
-rw-r--r--doc/pkgMkIndex.n60
-rw-r--r--doc/platform.n66
-rw-r--r--doc/platform_shell.n57
-rw-r--r--doc/proc.n22
-rw-r--r--doc/puts.n7
-rw-r--r--doc/pwd.n3
-rw-r--r--doc/re_syntax.n1254
-rw-r--r--doc/read.n4
-rw-r--r--doc/refchan.n340
-rw-r--r--doc/regexp.n96
-rw-r--r--doc/registry.n57
-rw-r--r--doc/regsub.n107
-rw-r--r--doc/resource.n154
-rw-r--r--doc/return.n234
-rw-r--r--doc/safe.n58
-rw-r--r--doc/scan.n169
-rw-r--r--doc/seek.n4
-rw-r--r--doc/set.n7
-rw-r--r--doc/socket.n15
-rw-r--r--doc/source.n40
-rw-r--r--doc/split.n14
-rw-r--r--doc/string.n145
-rw-r--r--doc/subst.n72
-rw-r--r--doc/switch.n94
-rw-r--r--doc/tclsh.145
-rw-r--r--doc/tcltest.n651
-rw-r--r--doc/tclvars.n302
-rw-r--r--doc/tell.n4
-rw-r--r--doc/time.n2
-rw-r--r--doc/tm.n293
-rw-r--r--doc/trace.n244
-rw-r--r--doc/unknown.n28
-rw-r--r--doc/unload.n162
-rw-r--r--doc/unset.n7
-rw-r--r--doc/update.n5
-rw-r--r--doc/uplevel.n13
-rw-r--r--doc/upvar.n32
-rw-r--r--doc/vwait.n2
-rw-r--r--generic/README4
-rw-r--r--generic/regc_color.c1253
-rw-r--r--generic/regc_cvec.c176
-rw-r--r--generic/regc_lex.c1830
-rw-r--r--generic/regc_locale.c203
-rw-r--r--generic/regc_nfa.c2631
-rw-r--r--generic/regcomp.c3572
-rw-r--r--generic/regcustom.h137
-rw-r--r--generic/rege_dfa.c1223
-rw-r--r--generic/regerror.c148
-rw-r--r--generic/regex.h159
-rw-r--r--generic/regexec.c1830
-rw-r--r--generic/regfree.c47
-rw-r--r--generic/regfronts.c92
-rw-r--r--generic/regguts.h398
-rw-r--r--generic/tcl.decls924
-rw-r--r--generic/tcl.h2424
-rw-r--r--generic/tclAlloc.c509
-rw-r--r--generic/tclAsync.c203
-rw-r--r--generic/tclBasic.c7584
-rw-r--r--generic/tclBinary.c2351
-rw-r--r--generic/tclCkalloc.c891
-rw-r--r--generic/tclClock.c2239
-rw-r--r--generic/tclCmdAH.c2570
-rw-r--r--generic/tclCmdIL.c4697
-rw-r--r--generic/tclCmdMZ.c6448
-rw-r--r--generic/tclCompCmds.c6481
-rw-r--r--generic/tclCompExpr.c3208
-rw-r--r--generic/tclCompile.c3758
-rw-r--r--generic/tclCompile.h1199
-rw-r--r--generic/tclConfig.c392
-rw-r--r--generic/tclDTrace.d30
-rw-r--r--generic/tclDate.c4361
-rw-r--r--generic/tclDecls.h5695
-rw-r--r--generic/tclDictObj.c3176
-rw-r--r--generic/tclEncoding.c2354
-rw-r--r--generic/tclEnv.c551
-rw-r--r--generic/tclEvent.c1301
-rw-r--r--generic/tclExecute.c10605
-rw-r--r--generic/tclFCmd.c779
-rw-r--r--generic/tclFileName.c2923
-rw-r--r--generic/tclFileSystem.h121
-rw-r--r--generic/tclGet.c344
-rw-r--r--generic/tclGetDate.y1725
-rw-r--r--generic/tclHash.c713
-rw-r--r--generic/tclHistory.c103
-rw-r--r--generic/tclIO.c8844
-rw-r--r--generic/tclIO.h356
-rw-r--r--generic/tclIOCmd.c1728
-rw-r--r--generic/tclIOGT.c1538
-rw-r--r--generic/tclIORChan.c3189
-rw-r--r--generic/tclIOSock.c50
-rw-r--r--generic/tclIOUtil.c6838
-rw-r--r--generic/tclIndexObj.c535
-rw-r--r--generic/tclInitScript.h110
-rw-r--r--generic/tclInt.decls644
-rw-r--r--generic/tclInt.h4753
-rw-r--r--generic/tclIntDecls.h1935
-rw-r--r--generic/tclIntPlatDecls.h722
-rw-r--r--generic/tclInterp.c4168
-rw-r--r--generic/tclLink.c519
-rw-r--r--generic/tclListObj.c2152
-rw-r--r--generic/tclLiteral.c855
-rw-r--r--generic/tclLoad.c839
-rw-r--r--generic/tclLoadNone.c103
-rw-r--r--generic/tclMain.c582
-rw-r--r--generic/tclMath.h25
-rw-r--r--generic/tclNamesp.c6976
-rw-r--r--generic/tclNotify.c629
-rw-r--r--generic/tclObj.c3909
-rw-r--r--generic/tclPanic.c56
-rw-r--r--generic/tclParse.c2393
-rw-r--r--generic/tclParseExpr.c2083
-rw-r--r--generic/tclPathObj.c2836
-rw-r--r--generic/tclPipe.c588
-rw-r--r--generic/tclPkg.c1581
-rw-r--r--generic/tclPkgConfig.c135
-rw-r--r--generic/tclPlatDecls.h172
-rw-r--r--generic/tclPort.h25
-rw-r--r--generic/tclPosixStr.c773
-rw-r--r--generic/tclPreserve.c328
-rw-r--r--generic/tclProc.c3089
-rw-r--r--generic/tclRegexp.c570
-rw-r--r--generic/tclRegexp.h35
-rw-r--r--generic/tclResolve.c450
-rw-r--r--generic/tclResult.c1272
-rw-r--r--generic/tclScan.c1007
-rwxr-xr-xgeneric/tclStrToD.c5001
-rw-r--r--generic/tclStringObj.c2269
-rw-r--r--generic/tclStubInit.c502
-rw-r--r--generic/tclStubLib.c148
-rw-r--r--generic/tclTest.c5696
-rw-r--r--generic/tclTestObj.c615
-rw-r--r--generic/tclTestProcBodyObj.c127
-rw-r--r--generic/tclThread.c354
-rw-r--r--[-rwxr-xr-x]generic/tclThreadAlloc.c732
-rw-r--r--generic/tclThreadJoin.c313
-rw-r--r--generic/tclThreadStorage.c597
-rw-r--r--generic/tclThreadTest.c599
-rw-r--r--generic/tclTimer.c851
-rw-r--r--generic/tclTomMath.decls222
-rw-r--r--generic/tclTomMath.h836
-rw-r--r--generic/tclTomMathDecls.h819
-rw-r--r--generic/tclTomMathInt.h2
-rw-r--r--generic/tclTomMathInterface.c311
-rw-r--r--generic/tclTrace.c3230
-rw-r--r--generic/tclUniData.c6
-rw-r--r--generic/tclUtf.c925
-rw-r--r--generic/tclUtil.c3817
-rw-r--r--generic/tclVar.c6591
-rw-r--r--generic/tommath.h1
-rw-r--r--library/auto.tcl122
-rw-r--r--library/clock.tcl4688
-rw-r--r--library/dde/pkgIndex.tcl4
-rw-r--r--library/history.tcl2
-rw-r--r--library/http/http.tcl857
-rw-r--r--library/http/pkgIndex.tcl10
-rw-r--r--library/init.tcl278
-rw-r--r--library/ldAout.tcl231
-rw-r--r--library/msgcat/msgcat.tcl108
-rw-r--r--library/msgcat/pkgIndex.tcl4
-rwxr-xr-xlibrary/msgs/af.msg49
-rwxr-xr-xlibrary/msgs/af_za.msg6
-rwxr-xr-xlibrary/msgs/ar.msg54
-rwxr-xr-xlibrary/msgs/ar_in.msg6
-rwxr-xr-xlibrary/msgs/ar_jo.msg39
-rwxr-xr-xlibrary/msgs/ar_lb.msg39
-rwxr-xr-xlibrary/msgs/ar_sy.msg39
-rwxr-xr-xlibrary/msgs/be.msg52
-rwxr-xr-xlibrary/msgs/bg.msg52
-rwxr-xr-xlibrary/msgs/bn.msg49
-rwxr-xr-xlibrary/msgs/bn_in.msg6
-rwxr-xr-xlibrary/msgs/ca.msg50
-rwxr-xr-xlibrary/msgs/cs.msg54
-rwxr-xr-xlibrary/msgs/da.msg52
-rwxr-xr-xlibrary/msgs/de.msg54
-rwxr-xr-xlibrary/msgs/de_at.msg35
-rwxr-xr-xlibrary/msgs/de_be.msg53
-rwxr-xr-xlibrary/msgs/el.msg52
-rwxr-xr-xlibrary/msgs/en_au.msg7
-rwxr-xr-xlibrary/msgs/en_be.msg7
-rwxr-xr-xlibrary/msgs/en_bw.msg6
-rwxr-xr-xlibrary/msgs/en_ca.msg7
-rwxr-xr-xlibrary/msgs/en_gb.msg7
-rwxr-xr-xlibrary/msgs/en_hk.msg8
-rwxr-xr-xlibrary/msgs/en_ie.msg7
-rwxr-xr-xlibrary/msgs/en_in.msg8
-rwxr-xr-xlibrary/msgs/en_nz.msg7
-rwxr-xr-xlibrary/msgs/en_ph.msg8
-rwxr-xr-xlibrary/msgs/en_sg.msg6
-rwxr-xr-xlibrary/msgs/en_za.msg6
-rwxr-xr-xlibrary/msgs/en_zw.msg6
-rwxr-xr-xlibrary/msgs/eo.msg54
-rwxr-xr-xlibrary/msgs/es.msg52
-rwxr-xr-xlibrary/msgs/es_ar.msg6
-rwxr-xr-xlibrary/msgs/es_bo.msg6
-rwxr-xr-xlibrary/msgs/es_cl.msg6
-rwxr-xr-xlibrary/msgs/es_co.msg6
-rwxr-xr-xlibrary/msgs/es_cr.msg6
-rwxr-xr-xlibrary/msgs/es_do.msg6
-rwxr-xr-xlibrary/msgs/es_ec.msg6
-rwxr-xr-xlibrary/msgs/es_gt.msg6
-rwxr-xr-xlibrary/msgs/es_hn.msg6
-rwxr-xr-xlibrary/msgs/es_mx.msg6
-rwxr-xr-xlibrary/msgs/es_ni.msg6
-rwxr-xr-xlibrary/msgs/es_pa.msg6
-rwxr-xr-xlibrary/msgs/es_pe.msg6
-rwxr-xr-xlibrary/msgs/es_pr.msg6
-rwxr-xr-xlibrary/msgs/es_py.msg6
-rwxr-xr-xlibrary/msgs/es_sv.msg6
-rwxr-xr-xlibrary/msgs/es_uy.msg6
-rwxr-xr-xlibrary/msgs/es_ve.msg6
-rwxr-xr-xlibrary/msgs/et.msg52
-rwxr-xr-xlibrary/msgs/eu.msg47
-rwxr-xr-xlibrary/msgs/eu_es.msg7
-rwxr-xr-xlibrary/msgs/fa.msg47
-rwxr-xr-xlibrary/msgs/fa_in.msg52
-rwxr-xr-xlibrary/msgs/fa_ir.msg9
-rwxr-xr-xlibrary/msgs/fi.msg50
-rwxr-xr-xlibrary/msgs/fo.msg47
-rwxr-xr-xlibrary/msgs/fo_fo.msg7
-rwxr-xr-xlibrary/msgs/fr.msg52
-rwxr-xr-xlibrary/msgs/fr_be.msg7
-rwxr-xr-xlibrary/msgs/fr_ca.msg7
-rwxr-xr-xlibrary/msgs/fr_ch.msg7
-rwxr-xr-xlibrary/msgs/ga.msg47
-rwxr-xr-xlibrary/msgs/ga_ie.msg7
-rwxr-xr-xlibrary/msgs/gl.msg47
-rwxr-xr-xlibrary/msgs/gl_es.msg6
-rwxr-xr-xlibrary/msgs/gv.msg47
-rwxr-xr-xlibrary/msgs/gv_gb.msg6
-rwxr-xr-xlibrary/msgs/he.msg52
-rwxr-xr-xlibrary/msgs/hi.msg39
-rwxr-xr-xlibrary/msgs/hi_in.msg6
-rwxr-xr-xlibrary/msgs/hr.msg50
-rwxr-xr-xlibrary/msgs/hu.msg54
-rwxr-xr-xlibrary/msgs/id.msg47
-rwxr-xr-xlibrary/msgs/id_id.msg6
-rwxr-xr-xlibrary/msgs/is.msg50
-rwxr-xr-xlibrary/msgs/it.msg54
-rwxr-xr-xlibrary/msgs/it_ch.msg6
-rwxr-xr-xlibrary/msgs/ja.msg44
-rwxr-xr-xlibrary/msgs/kl.msg47
-rwxr-xr-xlibrary/msgs/kl_gl.msg7
-rwxr-xr-xlibrary/msgs/ko.msg55
-rwxr-xr-xlibrary/msgs/ko_kr.msg8
-rwxr-xr-xlibrary/msgs/kok.msg39
-rwxr-xr-xlibrary/msgs/kok_in.msg6
-rwxr-xr-xlibrary/msgs/kw.msg47
-rwxr-xr-xlibrary/msgs/kw_gb.msg6
-rwxr-xr-xlibrary/msgs/lt.msg52
-rwxr-xr-xlibrary/msgs/lv.msg52
-rwxr-xr-xlibrary/msgs/mk.msg52
-rwxr-xr-xlibrary/msgs/mr.msg39
-rwxr-xr-xlibrary/msgs/mr_in.msg6
-rwxr-xr-xlibrary/msgs/ms.msg47
-rwxr-xr-xlibrary/msgs/ms_my.msg6
-rwxr-xr-xlibrary/msgs/mt.msg27
-rwxr-xr-xlibrary/msgs/nb.msg52
-rwxr-xr-xlibrary/msgs/nl.msg50
-rwxr-xr-xlibrary/msgs/nl_be.msg7
-rwxr-xr-xlibrary/msgs/nn.msg52
-rwxr-xr-xlibrary/msgs/pl.msg52
-rwxr-xr-xlibrary/msgs/pt.msg50
-rwxr-xr-xlibrary/msgs/pt_br.msg7
-rwxr-xr-xlibrary/msgs/ro.msg52
-rwxr-xr-xlibrary/msgs/ru.msg52
-rwxr-xr-xlibrary/msgs/ru_ua.msg6
-rwxr-xr-xlibrary/msgs/sh.msg52
-rwxr-xr-xlibrary/msgs/sk.msg52
-rwxr-xr-xlibrary/msgs/sl.msg52
-rwxr-xr-xlibrary/msgs/sq.msg54
-rwxr-xr-xlibrary/msgs/sr.msg52
-rwxr-xr-xlibrary/msgs/sv.msg52
-rwxr-xr-xlibrary/msgs/sw.msg49
-rwxr-xr-xlibrary/msgs/ta.msg39
-rwxr-xr-xlibrary/msgs/ta_in.msg6
-rwxr-xr-xlibrary/msgs/te.msg47
-rwxr-xr-xlibrary/msgs/te_in.msg8
-rwxr-xr-xlibrary/msgs/th.msg54
-rwxr-xr-xlibrary/msgs/tr.msg50
-rwxr-xr-xlibrary/msgs/uk.msg52
-rwxr-xr-xlibrary/msgs/vi.msg50
-rwxr-xr-xlibrary/msgs/zh.msg55
-rwxr-xr-xlibrary/msgs/zh_cn.msg7
-rwxr-xr-xlibrary/msgs/zh_hk.msg28
-rwxr-xr-xlibrary/msgs/zh_sg.msg8
-rwxr-xr-xlibrary/msgs/zh_tw.msg8
-rw-r--r--library/opt/optparse.tcl10
-rw-r--r--library/opt/pkgIndex.tcl2
-rw-r--r--library/package.tcl262
-rw-r--r--library/parray.tcl5
-rwxr-xr-xlibrary/reg/pkgIndex.tcl8
-rw-r--r--library/safe.tcl1680
-rw-r--r--library/tclIndex10
-rw-r--r--library/tcltest/pkgIndex.tcl4
-rw-r--r--library/tcltest/tcltest.tcl82
-rw-r--r--library/tm.tcl380
-rw-r--r--library/tzdata/Africa/Abidjan6
-rw-r--r--library/tzdata/Africa/Accra20
-rw-r--r--library/tzdata/Africa/Addis_Ababa7
-rw-r--r--library/tzdata/Africa/Algiers39
-rwxr-xr-xlibrary/tzdata/Africa/Asmara8
-rw-r--r--library/tzdata/Africa/Asmera5
-rw-r--r--library/tzdata/Africa/Bamako8
-rw-r--r--library/tzdata/Africa/Bangui6
-rw-r--r--library/tzdata/Africa/Banjul8
-rw-r--r--library/tzdata/Africa/Bissau7
-rw-r--r--library/tzdata/Africa/Blantyre6
-rw-r--r--library/tzdata/Africa/Brazzaville6
-rw-r--r--library/tzdata/Africa/Bujumbura6
-rw-r--r--library/tzdata/Africa/Cairo128
-rw-r--r--library/tzdata/Africa/Casablanca32
-rw-r--r--library/tzdata/Africa/Ceuta258
-rw-r--r--library/tzdata/Africa/Conakry8
-rw-r--r--library/tzdata/Africa/Dakar7
-rw-r--r--library/tzdata/Africa/Dar_es_Salaam8
-rw-r--r--library/tzdata/Africa/Djibouti6
-rw-r--r--library/tzdata/Africa/Douala6
-rw-r--r--library/tzdata/Africa/El_Aaiun7
-rw-r--r--library/tzdata/Africa/Freetown36
-rw-r--r--library/tzdata/Africa/Gaborone8
-rw-r--r--library/tzdata/Africa/Harare6
-rw-r--r--library/tzdata/Africa/Johannesburg11
-rw-r--r--library/tzdata/Africa/Kampala9
-rw-r--r--library/tzdata/Africa/Khartoum39
-rw-r--r--library/tzdata/Africa/Kigali6
-rw-r--r--library/tzdata/Africa/Kinshasa6
-rw-r--r--library/tzdata/Africa/Lagos6
-rw-r--r--library/tzdata/Africa/Libreville6
-rw-r--r--library/tzdata/Africa/Lome6
-rw-r--r--library/tzdata/Africa/Luanda7
-rw-r--r--library/tzdata/Africa/Lubumbashi6
-rw-r--r--library/tzdata/Africa/Lusaka6
-rw-r--r--library/tzdata/Africa/Malabo7
-rw-r--r--library/tzdata/Africa/Maputo6
-rw-r--r--library/tzdata/Africa/Maseru8
-rw-r--r--library/tzdata/Africa/Mbabane6
-rw-r--r--library/tzdata/Africa/Mogadishu8
-rw-r--r--library/tzdata/Africa/Monrovia8
-rw-r--r--library/tzdata/Africa/Nairobi9
-rw-r--r--library/tzdata/Africa/Ndjamena8
-rw-r--r--library/tzdata/Africa/Niamey8
-rw-r--r--library/tzdata/Africa/Nouakchott8
-rw-r--r--library/tzdata/Africa/Ouagadougou6
-rw-r--r--library/tzdata/Africa/Porto-Novo7
-rw-r--r--library/tzdata/Africa/Sao_Tome7
-rw-r--r--library/tzdata/Africa/Timbuktu5
-rw-r--r--library/tzdata/Africa/Tripoli31
-rw-r--r--library/tzdata/Africa/Tunis39
-rw-r--r--library/tzdata/Africa/Windhoek222
-rw-r--r--library/tzdata/America/Adak276
-rw-r--r--library/tzdata/America/Anchorage276
-rw-r--r--library/tzdata/America/Anguilla6
-rw-r--r--library/tzdata/America/Antigua7
-rw-r--r--library/tzdata/America/Araguaina57
-rw-r--r--library/tzdata/America/Argentina/Buenos_Aires67
-rw-r--r--library/tzdata/America/Argentina/Catamarca68
-rw-r--r--library/tzdata/America/Argentina/ComodRivadavia5
-rw-r--r--library/tzdata/America/Argentina/Cordoba67
-rw-r--r--library/tzdata/America/Argentina/Jujuy67
-rw-r--r--library/tzdata/America/Argentina/La_Rioja69
-rw-r--r--library/tzdata/America/Argentina/Mendoza68
-rw-r--r--library/tzdata/America/Argentina/Rio_Gallegos68
-rw-r--r--library/tzdata/America/Argentina/Salta66
-rw-r--r--library/tzdata/America/Argentina/San_Juan69
-rw-r--r--library/tzdata/America/Argentina/San_Luis68
-rw-r--r--library/tzdata/America/Argentina/Tucuman69
-rw-r--r--library/tzdata/America/Argentina/Ushuaia68
-rw-r--r--library/tzdata/America/Aruba7
-rw-r--r--library/tzdata/America/Asuncion259
-rwxr-xr-xlibrary/tzdata/America/Atikokan12
-rw-r--r--library/tzdata/America/Atka5
-rw-r--r--library/tzdata/America/Bahia65
-rw-r--r--library/tzdata/America/Bahia_Banderas222
-rw-r--r--library/tzdata/America/Barbados15
-rw-r--r--library/tzdata/America/Belem35
-rw-r--r--library/tzdata/America/Belize60
-rwxr-xr-xlibrary/tzdata/America/Blanc-Sablon12
-rw-r--r--library/tzdata/America/Boa_Vista40
-rw-r--r--library/tzdata/America/Bogota9
-rw-r--r--library/tzdata/America/Boise281
-rw-r--r--library/tzdata/America/Buenos_Aires5
-rw-r--r--library/tzdata/America/Cambridge_Bay252
-rw-r--r--library/tzdata/America/Campo_Grande257
-rw-r--r--library/tzdata/America/Cancun216
-rw-r--r--library/tzdata/America/Caracas9
-rw-r--r--library/tzdata/America/Catamarca5
-rw-r--r--library/tzdata/America/Cayenne7
-rw-r--r--library/tzdata/America/Cayman7
-rw-r--r--library/tzdata/America/Chicago369
-rw-r--r--library/tzdata/America/Chihuahua221
-rw-r--r--library/tzdata/America/Coral_Harbour5
-rw-r--r--library/tzdata/America/Cordoba5
-rw-r--r--library/tzdata/America/Costa_Rica15
-rw-r--r--library/tzdata/America/Cuiaba257
-rw-r--r--library/tzdata/America/Curacao7
-rw-r--r--library/tzdata/America/Danmarkshavn39
-rw-r--r--library/tzdata/America/Dawson256
-rw-r--r--library/tzdata/America/Dawson_Creek64
-rw-r--r--library/tzdata/America/Denver291
-rw-r--r--library/tzdata/America/Detroit272
-rw-r--r--library/tzdata/America/Dominica6
-rw-r--r--library/tzdata/America/Edmonton284
-rw-r--r--library/tzdata/America/Eirunepe40
-rw-r--r--library/tzdata/America/El_Salvador10
-rw-r--r--library/tzdata/America/Ensenada5
-rw-r--r--library/tzdata/America/Fort_Wayne5
-rw-r--r--library/tzdata/America/Fortaleza48
-rw-r--r--library/tzdata/America/Glace_Bay273
-rw-r--r--library/tzdata/America/Godthab246
-rw-r--r--library/tzdata/America/Goose_Bay337
-rw-r--r--library/tzdata/America/Grand_Turk249
-rw-r--r--library/tzdata/America/Grenada6
-rw-r--r--library/tzdata/America/Guadeloupe6
-rw-r--r--library/tzdata/America/Guatemala14
-rw-r--r--library/tzdata/America/Guayaquil7
-rw-r--r--library/tzdata/America/Guyana9
-rw-r--r--library/tzdata/America/Halifax361
-rw-r--r--library/tzdata/America/Havana285
-rw-r--r--library/tzdata/America/Hermosillo21
-rw-r--r--library/tzdata/America/Indiana/Indianapolis234
-rw-r--r--library/tzdata/America/Indiana/Knox285
-rw-r--r--library/tzdata/America/Indiana/Marengo236
-rwxr-xr-xlibrary/tzdata/America/Indiana/Petersburg247
-rwxr-xr-xlibrary/tzdata/America/Indiana/Tell_City234
-rw-r--r--library/tzdata/America/Indiana/Vevay213
-rwxr-xr-xlibrary/tzdata/America/Indiana/Vincennes234
-rwxr-xr-xlibrary/tzdata/America/Indiana/Winamac240
-rw-r--r--library/tzdata/America/Indianapolis5
-rw-r--r--library/tzdata/America/Inuvik249
-rw-r--r--library/tzdata/America/Iqaluit250
-rw-r--r--library/tzdata/America/Jamaica28
-rw-r--r--library/tzdata/America/Jujuy5
-rw-r--r--library/tzdata/America/Juneau276
-rw-r--r--library/tzdata/America/Kentucky/Louisville314
-rw-r--r--library/tzdata/America/Kentucky/Monticello279
-rw-r--r--library/tzdata/America/Knox_IN5
-rw-r--r--library/tzdata/America/Kralendijk5
-rw-r--r--library/tzdata/America/La_Paz8
-rw-r--r--library/tzdata/America/Lima16
-rw-r--r--library/tzdata/America/Los_Angeles317
-rw-r--r--library/tzdata/America/Louisville5
-rw-r--r--library/tzdata/America/Lower_Princes5
-rw-r--r--library/tzdata/America/Maceio52
-rw-r--r--library/tzdata/America/Managua21
-rw-r--r--library/tzdata/America/Manaus39
-rw-r--r--library/tzdata/America/Marigot5
-rw-r--r--library/tzdata/America/Martinique9
-rw-r--r--library/tzdata/America/Matamoros219
-rw-r--r--library/tzdata/America/Mazatlan222
-rw-r--r--library/tzdata/America/Mendoza5
-rw-r--r--library/tzdata/America/Menominee274
-rw-r--r--library/tzdata/America/Merida216
-rw-r--r--library/tzdata/America/Metlakatla275
-rw-r--r--library/tzdata/America/Mexico_City228
-rw-r--r--library/tzdata/America/Miquelon234
-rwxr-xr-xlibrary/tzdata/America/Moncton342
-rw-r--r--library/tzdata/America/Monterrey218
-rw-r--r--library/tzdata/America/Montevideo261
-rw-r--r--library/tzdata/America/Montreal366
-rw-r--r--library/tzdata/America/Montserrat6
-rw-r--r--library/tzdata/America/Nassau279
-rw-r--r--library/tzdata/America/New_York369
-rw-r--r--library/tzdata/America/Nipigon264
-rw-r--r--library/tzdata/America/Nome276
-rw-r--r--library/tzdata/America/Noronha48
-rw-r--r--library/tzdata/America/North_Dakota/Beulah279
-rw-r--r--library/tzdata/America/North_Dakota/Center279
-rwxr-xr-xlibrary/tzdata/America/North_Dakota/New_Salem279
-rw-r--r--library/tzdata/America/Ojinaga222
-rw-r--r--library/tzdata/America/Panama7
-rw-r--r--library/tzdata/America/Pangnirtung252
-rw-r--r--library/tzdata/America/Paramaribo10
-rw-r--r--library/tzdata/America/Phoenix17
-rw-r--r--library/tzdata/America/Port-au-Prince41
-rw-r--r--library/tzdata/America/Port_of_Spain6
-rw-r--r--library/tzdata/America/Porto_Acre5
-rw-r--r--library/tzdata/America/Porto_Velho35
-rw-r--r--library/tzdata/America/Puerto_Rico10
-rw-r--r--library/tzdata/America/Rainy_River264
-rw-r--r--library/tzdata/America/Rankin_Inlet248
-rw-r--r--library/tzdata/America/Recife48
-rw-r--r--library/tzdata/America/Regina58
-rwxr-xr-xlibrary/tzdata/America/Resolute249
-rw-r--r--library/tzdata/America/Rio_Branco36
-rw-r--r--library/tzdata/America/Rosario5
-rw-r--r--library/tzdata/America/Santa_Isabel284
-rw-r--r--library/tzdata/America/Santarem36
-rw-r--r--library/tzdata/America/Santiago291
-rw-r--r--library/tzdata/America/Santo_Domingo21
-rw-r--r--library/tzdata/America/Sao_Paulo258
-rw-r--r--library/tzdata/America/Scoresbysund246
-rw-r--r--library/tzdata/America/Shiprock5
-rw-r--r--library/tzdata/America/Sitka275
-rw-r--r--library/tzdata/America/St_Barthelemy5
-rw-r--r--library/tzdata/America/St_Johns371
-rw-r--r--library/tzdata/America/St_Kitts6
-rw-r--r--library/tzdata/America/St_Lucia7
-rw-r--r--library/tzdata/America/St_Thomas6
-rw-r--r--library/tzdata/America/St_Vincent7
-rw-r--r--library/tzdata/America/Swift_Current29
-rw-r--r--library/tzdata/America/Tegucigalpa12
-rw-r--r--library/tzdata/America/Thule224
-rw-r--r--library/tzdata/America/Thunder_Bay272
-rw-r--r--library/tzdata/America/Tijuana285
-rw-r--r--library/tzdata/America/Toronto365
-rw-r--r--library/tzdata/America/Tortola6
-rw-r--r--library/tzdata/America/Vancouver320
-rw-r--r--library/tzdata/America/Virgin5
-rw-r--r--library/tzdata/America/Whitehorse256
-rw-r--r--library/tzdata/America/Winnipeg316
-rw-r--r--library/tzdata/America/Yakutat276
-rw-r--r--library/tzdata/America/Yellowknife252
-rw-r--r--library/tzdata/Antarctica/Casey8
-rw-r--r--library/tzdata/Antarctica/Davis10
-rw-r--r--library/tzdata/Antarctica/DumontDUrville8
-rw-r--r--library/tzdata/Antarctica/Macquarie102
-rw-r--r--library/tzdata/Antarctica/Mawson7
-rw-r--r--library/tzdata/Antarctica/McMurdo257
-rw-r--r--library/tzdata/Antarctica/Palmer254
-rw-r--r--library/tzdata/Antarctica/Rothera6
-rw-r--r--library/tzdata/Antarctica/South_Pole5
-rw-r--r--library/tzdata/Antarctica/Syowa6
-rw-r--r--library/tzdata/Antarctica/Vostok6
-rw-r--r--library/tzdata/Arctic/Longyearbyen5
-rw-r--r--library/tzdata/Asia/Aden6
-rw-r--r--library/tzdata/Asia/Almaty56
-rw-r--r--library/tzdata/Asia/Amman248
-rw-r--r--library/tzdata/Asia/Anadyr72
-rw-r--r--library/tzdata/Asia/Aqtau58
-rw-r--r--library/tzdata/Asia/Aqtobe57
-rw-r--r--library/tzdata/Asia/Ashgabat31
-rw-r--r--library/tzdata/Asia/Ashkhabad5
-rw-r--r--library/tzdata/Asia/Baghdad59
-rw-r--r--library/tzdata/Asia/Bahrain7
-rw-r--r--library/tzdata/Asia/Baku242
-rw-r--r--library/tzdata/Asia/Bangkok7
-rw-r--r--library/tzdata/Asia/Beirut270
-rw-r--r--library/tzdata/Asia/Bishkek57
-rw-r--r--library/tzdata/Asia/Brunei7
-rw-r--r--library/tzdata/Asia/Calcutta5
-rw-r--r--library/tzdata/Asia/Choibalsan51
-rw-r--r--library/tzdata/Asia/Chongqing19
-rw-r--r--library/tzdata/Asia/Chungking5
-rw-r--r--library/tzdata/Asia/Colombo13
-rw-r--r--library/tzdata/Asia/Dacca5
-rw-r--r--library/tzdata/Asia/Damascus280
-rw-r--r--library/tzdata/Asia/Dhaka14
-rw-r--r--library/tzdata/Asia/Dili10
-rw-r--r--library/tzdata/Asia/Dubai6
-rw-r--r--library/tzdata/Asia/Dushanbe29
-rw-r--r--library/tzdata/Asia/Gaza276
-rw-r--r--library/tzdata/Asia/Harbin22
-rw-r--r--library/tzdata/Asia/Ho_Chi_Minh9
-rw-r--r--library/tzdata/Asia/Hong_Kong75
-rw-r--r--library/tzdata/Asia/Hovd51
-rw-r--r--library/tzdata/Asia/Irkutsk71
-rw-r--r--library/tzdata/Asia/Istanbul5
-rw-r--r--library/tzdata/Asia/Jakarta13
-rw-r--r--library/tzdata/Asia/Jayapura8
-rw-r--r--library/tzdata/Asia/Jerusalem148
-rw-r--r--library/tzdata/Asia/Kabul7
-rw-r--r--library/tzdata/Asia/Kamchatka71
-rw-r--r--library/tzdata/Asia/Karachi16
-rw-r--r--library/tzdata/Asia/Kashgar20
-rw-r--r--library/tzdata/Asia/Kathmandu7
-rw-r--r--library/tzdata/Asia/Katmandu5
-rw-r--r--library/tzdata/Asia/Kolkata10
-rw-r--r--library/tzdata/Asia/Krasnoyarsk70
-rw-r--r--library/tzdata/Asia/Kuala_Lumpur13
-rw-r--r--library/tzdata/Asia/Kuching24
-rw-r--r--library/tzdata/Asia/Kuwait6
-rw-r--r--library/tzdata/Asia/Macao5
-rw-r--r--library/tzdata/Asia/Macau46
-rw-r--r--library/tzdata/Asia/Magadan70
-rw-r--r--library/tzdata/Asia/Makassar9
-rw-r--r--library/tzdata/Asia/Manila15
-rw-r--r--library/tzdata/Asia/Muscat6
-rw-r--r--library/tzdata/Asia/Nicosia257
-rw-r--r--library/tzdata/Asia/Novokuznetsk71
-rw-r--r--library/tzdata/Asia/Novosibirsk71
-rw-r--r--library/tzdata/Asia/Omsk70
-rw-r--r--library/tzdata/Asia/Oral58
-rw-r--r--library/tzdata/Asia/Phnom_Penh9
-rw-r--r--library/tzdata/Asia/Pontianak13
-rw-r--r--library/tzdata/Asia/Pyongyang11
-rw-r--r--library/tzdata/Asia/Qatar7
-rw-r--r--library/tzdata/Asia/Qyzylorda58
-rw-r--r--library/tzdata/Asia/Rangoon9
-rw-r--r--library/tzdata/Asia/Riyadh6
-rw-r--r--library/tzdata/Asia/Saigon5
-rw-r--r--library/tzdata/Asia/Sakhalin72
-rw-r--r--library/tzdata/Asia/Samarkand32
-rw-r--r--library/tzdata/Asia/Seoul18
-rw-r--r--library/tzdata/Asia/Shanghai23
-rw-r--r--library/tzdata/Asia/Singapore14
-rw-r--r--library/tzdata/Asia/Taipei46
-rw-r--r--library/tzdata/Asia/Tashkent32
-rw-r--r--library/tzdata/Asia/Tbilisi60
-rw-r--r--library/tzdata/Asia/Tehran105
-rw-r--r--library/tzdata/Asia/Tel_Aviv5
-rw-r--r--library/tzdata/Asia/Thimbu5
-rw-r--r--library/tzdata/Asia/Thimphu7
-rw-r--r--library/tzdata/Asia/Tokyo16
-rw-r--r--library/tzdata/Asia/Ujung_Pandang5
-rw-r--r--library/tzdata/Asia/Ulaanbaatar51
-rw-r--r--library/tzdata/Asia/Ulan_Bator5
-rw-r--r--library/tzdata/Asia/Urumqi19
-rw-r--r--library/tzdata/Asia/Vientiane9
-rw-r--r--library/tzdata/Asia/Vladivostok70
-rw-r--r--library/tzdata/Asia/Yakutsk70
-rw-r--r--library/tzdata/Asia/Yekaterinburg70
-rw-r--r--library/tzdata/Asia/Yerevan245
-rw-r--r--library/tzdata/Atlantic/Azores349
-rw-r--r--library/tzdata/Atlantic/Bermuda259
-rw-r--r--library/tzdata/Atlantic/Canary248
-rw-r--r--library/tzdata/Atlantic/Cape_Verde9
-rw-r--r--library/tzdata/Atlantic/Faeroe5
-rwxr-xr-xlibrary/tzdata/Atlantic/Faroe245
-rw-r--r--library/tzdata/Atlantic/Jan_Mayen5
-rw-r--r--library/tzdata/Atlantic/Madeira350
-rw-r--r--library/tzdata/Atlantic/Reykjavik70
-rw-r--r--library/tzdata/Atlantic/South_Georgia6
-rw-r--r--library/tzdata/Atlantic/St_Helena7
-rw-r--r--library/tzdata/Atlantic/Stanley252
-rw-r--r--library/tzdata/Australia/ACT5
-rw-r--r--library/tzdata/Australia/Adelaide273
-rw-r--r--library/tzdata/Australia/Brisbane23
-rw-r--r--library/tzdata/Australia/Broken_Hill275
-rw-r--r--library/tzdata/Australia/Canberra5
-rw-r--r--library/tzdata/Australia/Currie273
-rw-r--r--library/tzdata/Australia/Darwin15
-rwxr-xr-xlibrary/tzdata/Australia/Eucla25
-rw-r--r--library/tzdata/Australia/Hobart281
-rw-r--r--library/tzdata/Australia/LHI5
-rw-r--r--library/tzdata/Australia/Lindeman28
-rw-r--r--library/tzdata/Australia/Lord_Howe244
-rw-r--r--library/tzdata/Australia/Melbourne272
-rw-r--r--library/tzdata/Australia/NSW5
-rw-r--r--library/tzdata/Australia/North5
-rw-r--r--library/tzdata/Australia/Perth25
-rw-r--r--library/tzdata/Australia/Queensland5
-rw-r--r--library/tzdata/Australia/South5
-rw-r--r--library/tzdata/Australia/Sydney272
-rw-r--r--library/tzdata/Australia/Tasmania5
-rw-r--r--library/tzdata/Australia/Victoria5
-rw-r--r--library/tzdata/Australia/West5
-rw-r--r--library/tzdata/Australia/Yancowinna5
-rw-r--r--library/tzdata/Brazil/Acre5
-rw-r--r--library/tzdata/Brazil/DeNoronha5
-rw-r--r--library/tzdata/Brazil/East5
-rw-r--r--library/tzdata/Brazil/West5
-rw-r--r--library/tzdata/CET265
-rw-r--r--library/tzdata/CST6CDT278
-rw-r--r--library/tzdata/Canada/Atlantic5
-rw-r--r--library/tzdata/Canada/Central5
-rw-r--r--library/tzdata/Canada/East-Saskatchewan5
-rw-r--r--library/tzdata/Canada/Eastern5
-rw-r--r--library/tzdata/Canada/Mountain5
-rw-r--r--library/tzdata/Canada/Newfoundland5
-rw-r--r--library/tzdata/Canada/Pacific5
-rw-r--r--library/tzdata/Canada/Saskatchewan5
-rw-r--r--library/tzdata/Canada/Yukon5
-rw-r--r--library/tzdata/Chile/Continental5
-rw-r--r--library/tzdata/Chile/EasterIsland5
-rw-r--r--library/tzdata/Cuba5
-rw-r--r--library/tzdata/EET251
-rw-r--r--library/tzdata/EST5
-rw-r--r--library/tzdata/EST5EDT278
-rw-r--r--library/tzdata/Egypt5
-rw-r--r--library/tzdata/Eire5
-rw-r--r--library/tzdata/Etc/GMT5
-rw-r--r--library/tzdata/Etc/GMT+05
-rw-r--r--library/tzdata/Etc/GMT+15
-rw-r--r--library/tzdata/Etc/GMT+105
-rw-r--r--library/tzdata/Etc/GMT+115
-rw-r--r--library/tzdata/Etc/GMT+125
-rw-r--r--library/tzdata/Etc/GMT+25
-rw-r--r--library/tzdata/Etc/GMT+35
-rw-r--r--library/tzdata/Etc/GMT+45
-rw-r--r--library/tzdata/Etc/GMT+55
-rw-r--r--library/tzdata/Etc/GMT+65
-rw-r--r--library/tzdata/Etc/GMT+75
-rw-r--r--library/tzdata/Etc/GMT+85
-rw-r--r--library/tzdata/Etc/GMT+95
-rw-r--r--library/tzdata/Etc/GMT-05
-rw-r--r--library/tzdata/Etc/GMT-15
-rw-r--r--library/tzdata/Etc/GMT-105
-rw-r--r--library/tzdata/Etc/GMT-115
-rw-r--r--library/tzdata/Etc/GMT-125
-rw-r--r--library/tzdata/Etc/GMT-135
-rw-r--r--library/tzdata/Etc/GMT-145
-rw-r--r--library/tzdata/Etc/GMT-25
-rw-r--r--library/tzdata/Etc/GMT-35
-rw-r--r--library/tzdata/Etc/GMT-45
-rw-r--r--library/tzdata/Etc/GMT-55
-rw-r--r--library/tzdata/Etc/GMT-65
-rw-r--r--library/tzdata/Etc/GMT-75
-rw-r--r--library/tzdata/Etc/GMT-85
-rw-r--r--library/tzdata/Etc/GMT-95
-rw-r--r--library/tzdata/Etc/GMT05
-rw-r--r--library/tzdata/Etc/Greenwich5
-rw-r--r--library/tzdata/Etc/UCT5
-rw-r--r--library/tzdata/Etc/UTC5
-rw-r--r--library/tzdata/Etc/Universal5
-rw-r--r--library/tzdata/Etc/Zulu5
-rw-r--r--library/tzdata/Europe/Amsterdam310
-rw-r--r--library/tzdata/Europe/Andorra237
-rw-r--r--library/tzdata/Europe/Athens268
-rw-r--r--library/tzdata/Europe/Belfast5
-rw-r--r--library/tzdata/Europe/Belgrade250
-rw-r--r--library/tzdata/Europe/Berlin274
-rw-r--r--library/tzdata/Europe/Bratislava5
-rw-r--r--library/tzdata/Europe/Brussels316
-rw-r--r--library/tzdata/Europe/Bucharest268
-rw-r--r--library/tzdata/Europe/Budapest284
-rw-r--r--library/tzdata/Europe/Chisinau272
-rw-r--r--library/tzdata/Europe/Copenhagen264
-rw-r--r--library/tzdata/Europe/Dublin359
-rw-r--r--library/tzdata/Europe/Gibraltar328
-rwxr-xr-xlibrary/tzdata/Europe/Guernsey5
-rw-r--r--library/tzdata/Europe/Helsinki248
-rwxr-xr-xlibrary/tzdata/Europe/Isle_of_Man5
-rw-r--r--library/tzdata/Europe/Istanbul304
-rwxr-xr-xlibrary/tzdata/Europe/Jersey5
-rw-r--r--library/tzdata/Europe/Kaliningrad84
-rw-r--r--library/tzdata/Europe/Kiev251
-rw-r--r--library/tzdata/Europe/Lisbon351
-rw-r--r--library/tzdata/Europe/Ljubljana5
-rw-r--r--library/tzdata/Europe/London372
-rw-r--r--library/tzdata/Europe/Luxembourg313
-rw-r--r--library/tzdata/Europe/Madrid294
-rw-r--r--library/tzdata/Europe/Malta299
-rw-r--r--library/tzdata/Europe/Mariehamn5
-rw-r--r--library/tzdata/Europe/Minsk251
-rw-r--r--library/tzdata/Europe/Monaco315
-rw-r--r--library/tzdata/Europe/Moscow83
-rw-r--r--library/tzdata/Europe/Nicosia5
-rw-r--r--library/tzdata/Europe/Oslo271
-rw-r--r--library/tzdata/Europe/Paris314
-rwxr-xr-xlibrary/tzdata/Europe/Podgorica5
-rw-r--r--library/tzdata/Europe/Prague272
-rw-r--r--library/tzdata/Europe/Riga258
-rw-r--r--library/tzdata/Europe/Rome301
-rw-r--r--library/tzdata/Europe/Samara73
-rw-r--r--library/tzdata/Europe/San_Marino5
-rw-r--r--library/tzdata/Europe/Sarajevo5
-rw-r--r--library/tzdata/Europe/Simferopol253
-rw-r--r--library/tzdata/Europe/Skopje5
-rw-r--r--library/tzdata/Europe/Sofia259
-rw-r--r--library/tzdata/Europe/Stockholm250
-rw-r--r--library/tzdata/Europe/Tallinn255
-rw-r--r--library/tzdata/Europe/Tirane263
-rw-r--r--library/tzdata/Europe/Tiraspol5
-rw-r--r--library/tzdata/Europe/Uzhgorod254
-rw-r--r--library/tzdata/Europe/Vaduz245
-rw-r--r--library/tzdata/Europe/Vatican5
-rw-r--r--library/tzdata/Europe/Vienna271
-rw-r--r--library/tzdata/Europe/Vilnius251
-rwxr-xr-xlibrary/tzdata/Europe/Volgograd70
-rw-r--r--library/tzdata/Europe/Warsaw296
-rw-r--r--library/tzdata/Europe/Zagreb5
-rw-r--r--library/tzdata/Europe/Zaporozhye252
-rw-r--r--library/tzdata/Europe/Zurich250
-rw-r--r--library/tzdata/GB5
-rw-r--r--library/tzdata/GB-Eire5
-rw-r--r--library/tzdata/GMT5
-rw-r--r--library/tzdata/GMT+05
-rw-r--r--library/tzdata/GMT-05
-rw-r--r--library/tzdata/GMT05
-rw-r--r--library/tzdata/Greenwich5
-rw-r--r--library/tzdata/HST5
-rw-r--r--library/tzdata/Hongkong5
-rw-r--r--library/tzdata/Iceland5
-rw-r--r--library/tzdata/Indian/Antananarivo8
-rw-r--r--library/tzdata/Indian/Chagos7
-rw-r--r--library/tzdata/Indian/Christmas6
-rw-r--r--library/tzdata/Indian/Cocos6
-rw-r--r--library/tzdata/Indian/Comoro6
-rw-r--r--library/tzdata/Indian/Kerguelen6
-rw-r--r--library/tzdata/Indian/Mahe6
-rw-r--r--library/tzdata/Indian/Maldives7
-rw-r--r--library/tzdata/Indian/Mauritius10
-rw-r--r--library/tzdata/Indian/Mayotte6
-rw-r--r--library/tzdata/Indian/Reunion6
-rw-r--r--library/tzdata/Iran5
-rw-r--r--library/tzdata/Israel5
-rw-r--r--library/tzdata/Jamaica5
-rw-r--r--library/tzdata/Japan5
-rw-r--r--library/tzdata/Kwajalein5
-rw-r--r--library/tzdata/Libya5
-rw-r--r--library/tzdata/MET265
-rw-r--r--library/tzdata/MST5
-rw-r--r--library/tzdata/MST7MDT278
-rw-r--r--library/tzdata/Mexico/BajaNorte5
-rw-r--r--library/tzdata/Mexico/BajaSur5
-rw-r--r--library/tzdata/Mexico/General5
-rw-r--r--library/tzdata/NZ5
-rw-r--r--library/tzdata/NZ-CHAT5
-rw-r--r--library/tzdata/Navajo5
-rw-r--r--library/tzdata/PRC5
-rw-r--r--library/tzdata/PST8PDT278
-rw-r--r--library/tzdata/Pacific/Apia10
-rw-r--r--library/tzdata/Pacific/Auckland285
-rw-r--r--library/tzdata/Pacific/Chatham257
-rw-r--r--library/tzdata/Pacific/Chuuk6
-rw-r--r--library/tzdata/Pacific/Easter275
-rw-r--r--library/tzdata/Pacific/Efate26
-rw-r--r--library/tzdata/Pacific/Enderbury8
-rw-r--r--library/tzdata/Pacific/Fakaofo6
-rw-r--r--library/tzdata/Pacific/Fiji14
-rw-r--r--library/tzdata/Pacific/Funafuti6
-rw-r--r--library/tzdata/Pacific/Galapagos7
-rw-r--r--library/tzdata/Pacific/Gambier6
-rw-r--r--library/tzdata/Pacific/Guadalcanal6
-rw-r--r--library/tzdata/Pacific/Guam8
-rw-r--r--library/tzdata/Pacific/Honolulu10
-rw-r--r--library/tzdata/Pacific/Johnston5
-rw-r--r--library/tzdata/Pacific/Kiritimati8
-rw-r--r--library/tzdata/Pacific/Kosrae8
-rw-r--r--library/tzdata/Pacific/Kwajalein8
-rw-r--r--library/tzdata/Pacific/Majuro7
-rw-r--r--library/tzdata/Pacific/Marquesas6
-rw-r--r--library/tzdata/Pacific/Midway10
-rw-r--r--library/tzdata/Pacific/Nauru9
-rw-r--r--library/tzdata/Pacific/Niue8
-rw-r--r--library/tzdata/Pacific/Norfolk7
-rw-r--r--library/tzdata/Pacific/Noumea12
-rw-r--r--library/tzdata/Pacific/Pago_Pago10
-rw-r--r--library/tzdata/Pacific/Palau6
-rw-r--r--library/tzdata/Pacific/Pitcairn7
-rw-r--r--library/tzdata/Pacific/Pohnpei6
-rw-r--r--library/tzdata/Pacific/Ponape5
-rw-r--r--library/tzdata/Pacific/Port_Moresby7
-rw-r--r--library/tzdata/Pacific/Rarotonga32
-rw-r--r--library/tzdata/Pacific/Saipan9
-rw-r--r--library/tzdata/Pacific/Samoa5
-rw-r--r--library/tzdata/Pacific/Tahiti6
-rw-r--r--library/tzdata/Pacific/Tarawa6
-rw-r--r--library/tzdata/Pacific/Tongatapu14
-rw-r--r--library/tzdata/Pacific/Truk5
-rw-r--r--library/tzdata/Pacific/Wake6
-rw-r--r--library/tzdata/Pacific/Wallis6
-rw-r--r--library/tzdata/Pacific/Yap5
-rw-r--r--library/tzdata/Poland5
-rw-r--r--library/tzdata/Portugal5
-rw-r--r--library/tzdata/ROC5
-rw-r--r--library/tzdata/ROK5
-rw-r--r--library/tzdata/Singapore5
-rw-r--r--library/tzdata/SystemV/AST45
-rw-r--r--library/tzdata/SystemV/AST4ADT5
-rw-r--r--library/tzdata/SystemV/CST65
-rw-r--r--library/tzdata/SystemV/CST6CDT5
-rw-r--r--library/tzdata/SystemV/EST55
-rw-r--r--library/tzdata/SystemV/EST5EDT5
-rw-r--r--library/tzdata/SystemV/HST105
-rw-r--r--library/tzdata/SystemV/MST75
-rw-r--r--library/tzdata/SystemV/MST7MDT5
-rw-r--r--library/tzdata/SystemV/PST85
-rw-r--r--library/tzdata/SystemV/PST8PDT5
-rw-r--r--library/tzdata/SystemV/YST95
-rw-r--r--library/tzdata/SystemV/YST9YDT5
-rw-r--r--library/tzdata/Turkey5
-rw-r--r--library/tzdata/UCT5
-rw-r--r--library/tzdata/US/Alaska5
-rw-r--r--library/tzdata/US/Aleutian5
-rw-r--r--library/tzdata/US/Arizona5
-rw-r--r--library/tzdata/US/Central5
-rw-r--r--library/tzdata/US/East-Indiana5
-rw-r--r--library/tzdata/US/Eastern5
-rw-r--r--library/tzdata/US/Hawaii5
-rw-r--r--library/tzdata/US/Indiana-Starke5
-rw-r--r--library/tzdata/US/Michigan5
-rw-r--r--library/tzdata/US/Mountain5
-rw-r--r--library/tzdata/US/Pacific5
-rw-r--r--library/tzdata/US/Pacific-New5
-rw-r--r--library/tzdata/US/Samoa5
-rw-r--r--library/tzdata/UTC5
-rw-r--r--library/tzdata/Universal5
-rw-r--r--library/tzdata/W-SU5
-rw-r--r--library/tzdata/WET251
-rw-r--r--library/tzdata/Zulu5
-rw-r--r--library/word.tcl142
-rw-r--r--libtommath/LICENSE4
-rw-r--r--libtommath/bn.ilg6
-rw-r--r--libtommath/bn.ind82
-rw-r--r--libtommath/bn.pdfbin0 -> 340921 bytes
-rw-r--r--libtommath/bn.tex1835
-rw-r--r--libtommath/bn_error.c43
-rw-r--r--libtommath/bn_fast_mp_invmod.c144
-rw-r--r--libtommath/bn_fast_mp_montgomery_reduce.c168
-rw-r--r--libtommath/bn_fast_s_mp_mul_digs.c103
-rw-r--r--libtommath/bn_fast_s_mp_mul_high_digs.c94
-rw-r--r--libtommath/bn_fast_s_mp_sqr.c110
-rw-r--r--libtommath/bn_mp_2expt.c44
-rw-r--r--libtommath/bn_mp_abs.c39
-rw-r--r--libtommath/bn_mp_add.c49
-rw-r--r--libtommath/bn_mp_add_d.c109
-rw-r--r--libtommath/bn_mp_addmod.c37
-rw-r--r--libtommath/bn_mp_and.c53
-rw-r--r--libtommath/bn_mp_clamp.c40
-rw-r--r--libtommath/bn_mp_clear.c40
-rw-r--r--libtommath/bn_mp_clear_multi.c30
-rw-r--r--libtommath/bn_mp_cmp.c39
-rw-r--r--libtommath/bn_mp_cmp_d.c40
-rw-r--r--libtommath/bn_mp_cmp_mag.c51
-rw-r--r--libtommath/bn_mp_cnt_lsb.c49
-rw-r--r--libtommath/bn_mp_copy.c64
-rw-r--r--libtommath/bn_mp_count_bits.c41
-rw-r--r--libtommath/bn_mp_div.c288
-rw-r--r--libtommath/bn_mp_div_2.c64
-rw-r--r--libtommath/bn_mp_div_2d.c93
-rw-r--r--libtommath/bn_mp_div_3.c75
-rw-r--r--libtommath/bn_mp_div_d.c110
-rw-r--r--libtommath/bn_mp_dr_is_modulus.c39
-rw-r--r--libtommath/bn_mp_dr_reduce.c90
-rw-r--r--libtommath/bn_mp_dr_setup.c28
-rw-r--r--libtommath/bn_mp_exch.c30
-rw-r--r--libtommath/bn_mp_expt_d.c53
-rw-r--r--libtommath/bn_mp_exptmod.c108
-rw-r--r--libtommath/bn_mp_exptmod_fast.c316
-rw-r--r--libtommath/bn_mp_exteuclid.c78
-rw-r--r--libtommath/bn_mp_fread.c63
-rw-r--r--libtommath/bn_mp_fwrite.c48
-rw-r--r--libtommath/bn_mp_gcd.c101
-rw-r--r--libtommath/bn_mp_get_int.c41
-rw-r--r--libtommath/bn_mp_grow.c53
-rw-r--r--libtommath/bn_mp_init.c42
-rw-r--r--libtommath/bn_mp_init_copy.c28
-rw-r--r--libtommath/bn_mp_init_multi.c55
-rw-r--r--libtommath/bn_mp_init_set.c28
-rw-r--r--libtommath/bn_mp_init_set_int.c27
-rw-r--r--libtommath/bn_mp_init_size.c44
-rw-r--r--libtommath/bn_mp_invmod.c39
-rw-r--r--libtommath/bn_mp_invmod_slow.c171
-rw-r--r--libtommath/bn_mp_is_square.c105
-rw-r--r--libtommath/bn_mp_jacobi.c101
-rw-r--r--libtommath/bn_mp_karatsuba_mul.c163
-rw-r--r--libtommath/bn_mp_karatsuba_sqr.c117
-rw-r--r--libtommath/bn_mp_lcm.c56
-rw-r--r--libtommath/bn_mp_lshd.c63
-rw-r--r--libtommath/bn_mp_mod.c44
-rw-r--r--libtommath/bn_mp_mod_2d.c51
-rw-r--r--libtommath/bn_mp_mod_d.c23
-rw-r--r--libtommath/bn_mp_montgomery_calc_normalization.c55
-rw-r--r--libtommath/bn_mp_montgomery_reduce.c114
-rw-r--r--libtommath/bn_mp_montgomery_setup.c55
-rw-r--r--libtommath/bn_mp_mul.c62
-rw-r--r--libtommath/bn_mp_mul_2.c78
-rw-r--r--libtommath/bn_mp_mul_2d.c81
-rw-r--r--libtommath/bn_mp_mul_d.c75
-rw-r--r--libtommath/bn_mp_mulmod.c36
-rw-r--r--libtommath/bn_mp_n_root.c128
-rw-r--r--libtommath/bn_mp_neg.c36
-rw-r--r--libtommath/bn_mp_or.c46
-rw-r--r--libtommath/bn_mp_prime_fermat.c58
-rw-r--r--libtommath/bn_mp_prime_is_divisible.c46
-rw-r--r--libtommath/bn_mp_prime_is_prime.c79
-rw-r--r--libtommath/bn_mp_prime_miller_rabin.c99
-rw-r--r--libtommath/bn_mp_prime_next_prime.c166
-rw-r--r--libtommath/bn_mp_prime_rabin_miller_trials.c48
-rw-r--r--libtommath/bn_mp_prime_random_ex.c121
-rw-r--r--libtommath/bn_mp_radix_size.c83
-rw-r--r--libtommath/bn_mp_radix_smap.c20
-rw-r--r--libtommath/bn_mp_rand.c51
-rw-r--r--libtommath/bn_mp_read_radix.c88
-rw-r--r--libtommath/bn_mp_read_signed_bin.c37
-rw-r--r--libtommath/bn_mp_read_unsigned_bin.c51
-rw-r--r--libtommath/bn_mp_reduce.c96
-rw-r--r--libtommath/bn_mp_reduce_2k.c57
-rw-r--r--libtommath/bn_mp_reduce_2k_l.c58
-rw-r--r--libtommath/bn_mp_reduce_2k_setup.c43
-rw-r--r--libtommath/bn_mp_reduce_2k_setup_l.c40
-rw-r--r--libtommath/bn_mp_reduce_is_2k.c48
-rw-r--r--libtommath/bn_mp_reduce_is_2k_l.c40
-rw-r--r--libtommath/bn_mp_reduce_setup.c30
-rw-r--r--libtommath/bn_mp_rshd.c68
-rw-r--r--libtommath/bn_mp_set.c25
-rw-r--r--libtommath/bn_mp_set_int.c44
-rw-r--r--libtommath/bn_mp_shrink.c36
-rw-r--r--libtommath/bn_mp_signed_bin_size.c23
-rw-r--r--libtommath/bn_mp_sqr.c54
-rw-r--r--libtommath/bn_mp_sqrmod.c37
-rw-r--r--libtommath/bn_mp_sqrt.c142
-rw-r--r--libtommath/bn_mp_sub.c55
-rw-r--r--libtommath/bn_mp_sub_d.c89
-rw-r--r--libtommath/bn_mp_submod.c38
-rw-r--r--libtommath/bn_mp_to_signed_bin.c29
-rw-r--r--libtommath/bn_mp_to_signed_bin_n.c27
-rw-r--r--libtommath/bn_mp_to_unsigned_bin.c44
-rw-r--r--libtommath/bn_mp_to_unsigned_bin_n.c27
-rw-r--r--libtommath/bn_mp_toom_mul.c280
-rw-r--r--libtommath/bn_mp_toom_sqr.c222
-rw-r--r--libtommath/bn_mp_toradix.c71
-rw-r--r--libtommath/bn_mp_toradix_n.c84
-rw-r--r--libtommath/bn_mp_unsigned_bin_size.c24
-rw-r--r--libtommath/bn_mp_xor.c47
-rw-r--r--libtommath/bn_mp_zero.c32
-rw-r--r--libtommath/bn_prime_tab.c57
-rw-r--r--libtommath/bn_reverse.c35
-rw-r--r--libtommath/bn_s_mp_add.c105
-rw-r--r--libtommath/bn_s_mp_exptmod.c248
-rw-r--r--libtommath/bn_s_mp_mul_digs.c86
-rw-r--r--libtommath/bn_s_mp_mul_high_digs.c77
-rw-r--r--libtommath/bn_s_mp_sqr.c80
-rw-r--r--libtommath/bn_s_mp_sub.c85
-rw-r--r--libtommath/bncore.c32
-rw-r--r--libtommath/booker.pl265
-rw-r--r--libtommath/callgraph.txt11913
-rw-r--r--libtommath/changes.txt403
-rw-r--r--libtommath/demo/demo.c736
-rw-r--r--libtommath/demo/timing.c315
-rw-r--r--libtommath/dep.pl123
-rw-r--r--libtommath/etc/2kprime.12
-rw-r--r--libtommath/etc/2kprime.c75
-rw-r--r--libtommath/etc/drprime.c59
-rw-r--r--libtommath/etc/drprimes.2825
-rw-r--r--libtommath/etc/drprimes.txt9
-rw-r--r--libtommath/etc/makefile50
-rw-r--r--libtommath/etc/makefile.icc67
-rw-r--r--libtommath/etc/makefile.msvc23
-rw-r--r--libtommath/etc/mersenne.c140
-rw-r--r--libtommath/etc/mont.c41
-rw-r--r--libtommath/etc/pprime.c396
-rw-r--r--libtommath/etc/prime.1024414
-rw-r--r--libtommath/etc/prime.512205
-rw-r--r--libtommath/etc/timer.asm37
-rw-r--r--libtommath/etc/tune.c138
-rw-r--r--libtommath/gen.pl17
-rw-r--r--libtommath/logs/README13
-rw-r--r--libtommath/logs/add.log16
-rw-r--r--libtommath/logs/addsub.pngbin0 -> 6253 bytes
-rw-r--r--libtommath/logs/expt.log7
-rw-r--r--libtommath/logs/expt.pngbin0 -> 6604 bytes
-rw-r--r--libtommath/logs/expt_2k.log5
-rw-r--r--libtommath/logs/expt_2kl.log4
-rw-r--r--libtommath/logs/expt_dr.log7
-rw-r--r--libtommath/logs/graphs.dem17
-rw-r--r--libtommath/logs/index.html24
-rw-r--r--libtommath/logs/invmod.log0
-rw-r--r--libtommath/logs/invmod.pngbin0 -> 4917 bytes
-rw-r--r--libtommath/logs/mult.log84
-rw-r--r--libtommath/logs/mult.pngbin0 -> 6769 bytes
-rw-r--r--libtommath/logs/mult_kara.log84
-rw-r--r--libtommath/logs/sqr.log84
-rw-r--r--libtommath/logs/sqr_kara.log84
-rw-r--r--libtommath/logs/sub.log16
-rw-r--r--libtommath/makefile186
-rw-r--r--libtommath/makefile.bcc44
-rw-r--r--libtommath/makefile.cygwin_dll51
-rw-r--r--libtommath/makefile.icc116
-rw-r--r--libtommath/makefile.msvc40
-rw-r--r--libtommath/makefile.shared102
-rw-r--r--libtommath/mess.sh4
-rw-r--r--libtommath/mtest/logtab.h19
-rw-r--r--libtommath/mtest/mpi-config.h85
-rw-r--r--libtommath/mtest/mpi-types.h15
-rw-r--r--libtommath/mtest/mpi.c3979
-rw-r--r--libtommath/mtest/mpi.h225
-rw-r--r--libtommath/mtest/mtest.c304
-rw-r--r--libtommath/pics/design_process.sxdbin0 -> 6950 bytes
-rw-r--r--libtommath/pics/design_process.tifbin0 -> 79042 bytes
-rw-r--r--libtommath/pics/expt_state.sxdbin0 -> 6869 bytes
-rw-r--r--libtommath/pics/expt_state.tifbin0 -> 87540 bytes
-rw-r--r--libtommath/pics/makefile35
-rw-r--r--libtommath/pics/primality.tifbin0 -> 85512 bytes
-rw-r--r--libtommath/pics/radix.sxdbin0 -> 6181 bytes
-rw-r--r--libtommath/pics/sliding_window.sxdbin0 -> 6787 bytes
-rw-r--r--libtommath/pics/sliding_window.tifbin0 -> 53880 bytes
-rw-r--r--libtommath/poster.out0
-rw-r--r--libtommath/poster.pdfbin0 -> 37822 bytes
-rw-r--r--libtommath/poster.tex35
-rw-r--r--libtommath/pre_gen/mpi.c9048
-rw-r--r--libtommath/pretty.build66
-rw-r--r--libtommath/tombc/grammar.txt35
-rw-r--r--libtommath/tommath.h579
-rw-r--r--libtommath/tommath.out139
-rw-r--r--libtommath/tommath.pdfbin0 -> 1194158 bytes
-rw-r--r--libtommath/tommath.src6350
-rw-r--r--libtommath/tommath.tex6691
-rw-r--r--libtommath/tommath_class.h995
-rw-r--r--libtommath/tommath_superclass.h72
-rw-r--r--license.terms2
-rw-r--r--mac/AppleScript.html312
-rw-r--r--mac/Background.doc90
-rwxr-xr-xmac/MW_TclAppleScriptHeader.h7
-rw-r--r--mac/MW_TclAppleScriptHeader.pch34
-rw-r--r--mac/MW_TclBuildLibHeader.h7
-rw-r--r--mac/MW_TclBuildLibHeader.pch33
-rwxr-xr-xmac/MW_TclHeader.h7
-rw-r--r--mac/MW_TclHeader.pch31
-rw-r--r--mac/MW_TclHeaderCommon.h52
-rw-r--r--mac/MW_TclStaticHeader.h7
-rw-r--r--mac/MW_TclStaticHeader.pch33
-rwxr-xr-xmac/MW_TclTestHeader.h7
-rwxr-xr-xmac/MW_TclTestHeader.pch39
-rw-r--r--mac/README79
-rw-r--r--mac/bugs.doc42
-rw-r--r--mac/libmoto.doc37
-rw-r--r--mac/morefiles.doc72
-rw-r--r--mac/porting.notes21
-rw-r--r--mac/tclMac.h26
-rw-r--r--mac/tclMacAETE.r56
-rw-r--r--mac/tclMacAlloc.c410
-rw-r--r--mac/tclMacAppInit.c211
-rw-r--r--mac/tclMacApplication.r113
-rw-r--r--mac/tclMacBOAAppInit.c255
-rw-r--r--mac/tclMacBOAMain.c302
-rw-r--r--mac/tclMacChan.c1273
-rwxr-xr-xmac/tclMacCommonPch.h69
-rw-r--r--mac/tclMacDNR.c21
-rw-r--r--mac/tclMacEnv.c534
-rw-r--r--mac/tclMacExit.c331
-rw-r--r--mac/tclMacFCmd.c1650
-rw-r--r--mac/tclMacFile.c1348
-rw-r--r--mac/tclMacInit.c805
-rw-r--r--mac/tclMacInt.h75
-rw-r--r--mac/tclMacInterupt.c287
-rw-r--r--mac/tclMacLibrary.c246
-rw-r--r--mac/tclMacLibrary.r207
-rw-r--r--mac/tclMacLoad.c378
-rw-r--r--mac/tclMacMath.h143
-rw-r--r--mac/tclMacNotify.c579
-rw-r--r--mac/tclMacOSA.c2956
-rw-r--r--mac/tclMacOSA.r76
-rw-r--r--mac/tclMacPanic.c170
-rw-r--r--mac/tclMacPort.h277
-rw-r--r--mac/tclMacProjects.sea.hqx3759
-rw-r--r--mac/tclMacResource.c2220
-rw-r--r--mac/tclMacResource.r42
-rw-r--r--mac/tclMacSock.c2788
-rw-r--r--mac/tclMacTclCode.r35
-rw-r--r--mac/tclMacTest.c211
-rw-r--r--mac/tclMacThrd.c869
-rw-r--r--mac/tclMacThrd.h18
-rw-r--r--mac/tclMacTime.c433
-rw-r--r--mac/tclMacUnix.c423
-rw-r--r--mac/tclMacUtil.c512
-rw-r--r--mac/tcltkMacBuildSupport.sea.hqx3970
-rw-r--r--macosx/GNUmakefile (renamed from macosx/Makefile)45
-rw-r--r--macosx/README75
-rw-r--r--macosx/Tcl-Common.xcconfig40
-rw-r--r--macosx/Tcl-Debug.xcconfig20
-rw-r--r--macosx/Tcl-Info.plist.in6
-rw-r--r--macosx/Tcl-Release.xcconfig20
-rw-r--r--macosx/Tcl.pbproj/default.pbxuser2
-rw-r--r--macosx/Tcl.pbproj/jingham.pbxuser2
-rw-r--r--macosx/Tcl.pbproj/project.pbxproj53
-rw-r--r--macosx/Tcl.xcode/default.pbxuser198
-rw-r--r--macosx/Tcl.xcode/project.pbxproj2792
-rw-r--r--macosx/Tcl.xcodeproj/default.pbxuser200
-rw-r--r--macosx/Tcl.xcodeproj/project.pbxproj3035
-rw-r--r--macosx/Tclsh-Info.plist.in6
-rw-r--r--macosx/configure.ac11
-rw-r--r--macosx/tclMacOSXBundle.c131
-rw-r--r--macosx/tclMacOSXFCmd.c696
-rw-r--r--macosx/tclMacOSXNotify.c1425
-rw-r--r--tests/all.tcl16
-rw-r--r--tests/append.test5
-rw-r--r--tests/appendComp.test21
-rw-r--r--tests/apply.test324
-rw-r--r--tests/assocd.test43
-rw-r--r--tests/async.test148
-rw-r--r--tests/basic.test501
-rw-r--r--tests/binary.test1090
-rw-r--r--tests/case.test16
-rw-r--r--tests/chan.test229
-rw-r--r--tests/chanio.test7705
-rw-r--r--tests/clock.test36920
-rw-r--r--tests/cmdAH.test809
-rw-r--r--tests/cmdIL.test480
-rw-r--r--tests/cmdInfo.test16
-rw-r--r--tests/cmdMZ.test206
-rw-r--r--tests/compExpr-old.test508
-rw-r--r--tests/compExpr.test177
-rw-r--r--tests/compile.test338
-rw-r--r--tests/concat.test12
-rw-r--r--tests/config.test60
-rw-r--r--tests/dcall.test31
-rw-r--r--tests/dict.test1205
-rw-r--r--tests/dstring.test150
-rw-r--r--tests/encoding.test92
-rw-r--r--tests/env.test44
-rw-r--r--tests/error.test98
-rw-r--r--tests/eval.test37
-rw-r--r--tests/event.test125
-rw-r--r--tests/exec.test53
-rw-r--r--tests/execute.test196
-rw-r--r--tests/expr-old.test536
-rw-r--r--tests/expr.test6826
-rw-r--r--tests/fCmd.test2479
-rw-r--r--tests/fileName.test868
-rw-r--r--tests/fileSystem.test804
-rw-r--r--tests/for-old.test12
-rw-r--r--tests/for.test130
-rw-r--r--tests/foreach.test29
-rw-r--r--tests/format.test108
-rw-r--r--tests/get.test115
-rw-r--r--tests/history.test235
-rw-r--r--tests/http.test72
-rw-r--r--tests/httpd32
-rw-r--r--tests/httpold.test12
-rw-r--r--tests/if.test82
-rw-r--r--tests/incr-old.test20
-rw-r--r--tests/incr.test127
-rw-r--r--tests/indexObj.test71
-rw-r--r--tests/info.test1221
-rw-r--r--tests/init.test46
-rw-r--r--tests/interp.test1168
-rw-r--r--tests/io.test651
-rw-r--r--tests/ioCmd.test3174
-rw-r--r--tests/ioUtil.test34
-rw-r--r--tests/iogt.test25
-rw-r--r--tests/join.test12
-rw-r--r--tests/lindex.test298
-rw-r--r--tests/link.test139
-rw-r--r--tests/linsert.test2
-rw-r--r--tests/list.test6
-rw-r--r--tests/listObj.test48
-rw-r--r--tests/llength.test12
-rw-r--r--tests/load.test35
-rw-r--r--tests/lrange.test8
-rw-r--r--tests/lrepeat.test77
-rw-r--r--tests/lreplace.test6
-rw-r--r--tests/lsearch.test105
-rw-r--r--tests/lset.test397
-rw-r--r--[-rwxr-xr-x]tests/lsetComp.test2
-rw-r--r--tests/macFCmd.test200
-rw-r--r--tests/macOSXFCmd.test181
-rw-r--r--tests/macOSXLoad.test33
-rw-r--r--tests/main.test139
-rw-r--r--tests/mathop.test1338
-rw-r--r--tests/misc.test25
-rw-r--r--tests/msgcat.test91
-rw-r--r--tests/namespace-old.test47
-rw-r--r--tests/namespace.test1408
-rw-r--r--[-rwxr-xr-x]tests/notify.test0
-rw-r--r--tests/obj.test290
-rw-r--r--tests/opt.test37
-rw-r--r--tests/osa.test46
-rw-r--r--tests/parse.test629
-rw-r--r--tests/parseExpr.test1051
-rw-r--r--tests/parseOld.test9
-rw-r--r--tests/pid.test30
-rw-r--r--tests/pkg.test295
-rw-r--r--tests/pkgMkIndex.test48
-rw-r--r--tests/platform.test8
-rw-r--r--tests/proc-old.test40
-rw-r--r--tests/proc.test125
-rw-r--r--tests/pwd.test21
-rw-r--r--tests/reg.test1457
-rw-r--r--tests/regexp.test318
-rw-r--r--tests/regexpComp.test168
-rw-r--r--tests/registry.test258
-rw-r--r--tests/rename.test118
-rw-r--r--tests/resource.test363
-rw-r--r--tests/result.test43
-rw-r--r--tests/safe.test197
-rw-r--r--tests/scan.test98
-rw-r--r--tests/security.test15
-rw-r--r--tests/set-old.test2
-rw-r--r--tests/set.test39
-rw-r--r--tests/socket.test279
-rw-r--r--tests/source.test194
-rw-r--r--tests/split.test12
-rw-r--r--tests/stack.test86
-rw-r--r--tests/string.test393
-rw-r--r--tests/stringComp.test27
-rw-r--r--tests/stringObj.test129
-rw-r--r--tests/subst.test30
-rw-r--r--tests/switch.test759
-rw-r--r--[-rwxr-xr-x]tests/tcltest.test180
-rw-r--r--tests/thread.test54
-rw-r--r--tests/timer.test53
-rw-r--r--tests/tm.test245
-rw-r--r--tests/trace.test216
-rw-r--r--tests/unixFCmd.test155
-rw-r--r--tests/unixFile.test21
-rw-r--r--tests/unixInit.test225
-rw-r--r--tests/unixNotfy.test90
-rw-r--r--tests/unknown.test12
-rw-r--r--tests/unload.test219
-rw-r--r--tests/uplevel.test12
-rw-r--r--tests/upvar.test271
-rw-r--r--tests/utf.test97
-rw-r--r--tests/util.test3610
-rw-r--r--tests/var.test186
-rw-r--r--tests/while-old.test14
-rw-r--r--tests/while.test40
-rw-r--r--tests/winConsole.test6
-rw-r--r--tests/winDde.test472
-rw-r--r--tests/winFCmd.test578
-rw-r--r--tests/winFile.test198
-rw-r--r--tests/winNotify.test43
-rw-r--r--tests/winPipe.test185
-rw-r--r--tests/winTime.test4
-rw-r--r--[-rwxr-xr-x]tools/checkLibraryDoc.tcl0
-rw-r--r--[-rwxr-xr-x]tools/configure2215
-rw-r--r--tools/configure.in3
-rw-r--r--tools/cvtEOL.tcl32
-rwxr-xr-xtools/findBadExternals.tcl53
-rwxr-xr-xtools/fix_tommath_h.tcl98
-rw-r--r--tools/genStubs.tcl604
-rw-r--r--tools/genWinImage.tcl155
-rw-r--r--tools/index.tcl2
-rw-r--r--tools/installData.tcl50
-rwxr-xr-xtools/loadICU.tcl619
-rwxr-xr-xtools/makeTestCases.tcl1180
-rw-r--r--tools/man2help.tcl7
-rw-r--r--tools/man2help2.tcl153
-rw-r--r--tools/man2html.tcl171
-rw-r--r--tools/man2html1.tcl32
-rw-r--r--tools/man2html2.tcl465
-rw-r--r--tools/man2tcl.c250
-rw-r--r--tools/mkdepend.tcl420
-rw-r--r--tools/tcl.hpj.in4
-rw-r--r--tools/tcl.wse.in76
-rw-r--r--tools/tclSplash.bmpbin162030 -> 162030 bytes
-rwxr-xr-xtools/tclZIC.tcl1375
-rw-r--r--tools/tclmin.wse4
-rwxr-xr-xtools/tcltk-man2html.tcl1107
-rw-r--r--tools/uniClass.tcl4
-rw-r--r--tools/uniParse.tcl6
-rw-r--r--unix/Makefile.in1199
-rw-r--r--unix/README222
-rw-r--r--unix/aclocal.m42
-rwxr-xr-xunix/configure22045
-rw-r--r--unix/configure.in495
-rw-r--r--unix/dltest/Makefile.in77
-rw-r--r--unix/dltest/README4
-rw-r--r--unix/dltest/pkga.c61
-rw-r--r--unix/dltest/pkgb.c79
-rw-r--r--unix/dltest/pkgc.c75
-rw-r--r--unix/dltest/pkgd.c72
-rw-r--r--unix/dltest/pkge.c25
-rw-r--r--unix/dltest/pkgf.c51
-rw-r--r--unix/dltest/pkgua.c332
-rwxr-xr-xunix/install-sh22
-rwxr-xr-xunix/installManPage131
-rwxr-xr-xunix/ldAix38
-rw-r--r--unix/tcl.m41280
-rw-r--r--unix/tcl.spec52
-rw-r--r--unix/tclAppInit.c96
-rw-r--r--unix/tclConfig.h.in505
-rw-r--r--unix/tclConfig.sh.in17
-rw-r--r--unix/tclLoadAix.c953
-rw-r--r--unix/tclLoadAout.c534
-rw-r--r--unix/tclLoadDl.c167
-rw-r--r--unix/tclLoadDld.c199
-rw-r--r--unix/tclLoadDyld.c8
-rw-r--r--unix/tclLoadNext.c148
-rw-r--r--unix/tclLoadOSF.c138
-rw-r--r--unix/tclLoadShl.c146
-rw-r--r--unix/tclUnixChan.c1920
-rw-r--r--unix/tclUnixCompat.c778
-rw-r--r--unix/tclUnixEvent.c57
-rw-r--r--unix/tclUnixFCmd.c1695
-rw-r--r--unix/tclUnixFile.c860
-rw-r--r--unix/tclUnixInit.c1470
-rw-r--r--unix/tclUnixNotfy.c680
-rw-r--r--unix/tclUnixPipe.c707
-rw-r--r--unix/tclUnixPort.h187
-rw-r--r--unix/tclUnixSock.c147
-rw-r--r--unix/tclUnixTest.c370
-rw-r--r--unix/tclUnixThrd.c580
-rw-r--r--unix/tclUnixTime.c355
-rw-r--r--unix/tclXtNotify.c352
-rw-r--r--unix/tclXtTest.c57
-rw-r--r--win/Makefile.in342
-rw-r--r--win/README10
-rw-r--r--win/README.binary141
-rw-r--r--[-rwxr-xr-x]win/buildall.vc.bat95
-rw-r--r--win/cat.c13
-rw-r--r--win/coffbase.txt10
-rwxr-xr-xwin/configure5953
-rw-r--r--win/configure.in158
-rw-r--r--win/makefile.bc94
-rw-r--r--win/makefile.vc525
-rw-r--r--win/nmakehlp.c266
-rw-r--r--win/rules.vc333
-rw-r--r--win/stub16.c65
-rw-r--r--win/tcl.dsp56
-rw-r--r--win/tcl.hpj.in4
-rw-r--r--win/tcl.m492
-rw-r--r--win/tcl.rc8
-rw-r--r--win/tclAppInit.c282
-rw-r--r--win/tclWin32Dll.c760
-rw-r--r--win/tclWinChan.c934
-rw-r--r--win/tclWinConsole.c636
-rw-r--r--win/tclWinDde.c1900
-rw-r--r--win/tclWinError.c23
-rw-r--r--win/tclWinFCmd.c1230
-rw-r--r--win/tclWinFile.c2973
-rw-r--r--win/tclWinInit.c667
-rw-r--r--win/tclWinInt.h89
-rw-r--r--win/tclWinLoad.c191
-rw-r--r--win/tclWinMtherr.c55
-rw-r--r--win/tclWinNotify.c288
-rw-r--r--win/tclWinPipe.c1447
-rw-r--r--win/tclWinPort.h171
-rw-r--r--win/tclWinReg.c550
-rw-r--r--win/tclWinSerial.c1992
-rw-r--r--win/tclWinSock.c1935
-rw-r--r--win/tclWinTest.c727
-rw-r--r--win/tclWinThrd.c708
-rw-r--r--win/tclWinTime.c1003
-rw-r--r--win/tclsh.rc10
1596 files changed, 413072 insertions, 165406 deletions
diff --git a/ChangeLog b/ChangeLog
index 6237d99..0b0a621 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,37 +1,68 @@
2011-08-15 Jan Nijtmans <nijtmans@users.sf.net>
- * win/tcl.m4: [Bug 3388350] mingw64 compiler warnings
+ * win/tclWinPort.h: [Bug 3388350] mingw64 compiler warnings
+ * win/tclWinPipe.c
+ * win/tclWinSock.c
* win/configure.in
* win/configure
- * win/tclMtherr.c
- * win/tclWinPort.h
- * win/tclWinChan.c
+ * generic/tclPosixStr.c
+ * generic/tclStrToD.c
+
+2011-08-12 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclPathObj.c: [Bug 3389764] Eliminate possibility that dup
+ of a "path" value can create reference cycle.
+
+2011-08-09 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tclWinConsole.c: [Bug 3388350] mingw64 compiler warnings
* win/tclWinDde.c
* win/tclWinPipe.c
- * win/tclWinReg.c
* win/tclWinSerial.c
- * win/tclWinSock.c
- * win/tclWinTest.c
- * win/tclWinTime.c
- * generic/tclPosixStr.c
- * unix/tcl.m4: Quoting and AC_DEFINE fixes (All backported from
- * unix/configure Tcl 8.5
+
+2011-08-05 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclStrToD.c: Plugged a memory leak in double->string
+ conversion. [Bug 3386975]
+
+2011-07-28 Don Porter <dgp@users.sourceforge.net>
+
+ * library/tzdata/Asia/Anadyr: Update to Olson's tzdata2011h
+ * library/tzdata/Asia/Irkutsk:
+ * library/tzdata/Asia/Kamchatka:
+ * library/tzdata/Asia/Krasnoyarsk:
+ * library/tzdata/Asia/Magadan:
+ * library/tzdata/Asia/Novokuznetsk:
+ * library/tzdata/Asia/Novosibirsk:
+ * library/tzdata/Asia/Omsk:
+ * library/tzdata/Asia/Sakhalin:
+ * library/tzdata/Asia/Vladivostok:
+ * library/tzdata/Asia/Yakutsk:
+ * library/tzdata/Asia/Yekaterinburg:
+ * library/tzdata/Europe/Kaliningrad:
+ * library/tzdata/Europe/Moscow:
+ * library/tzdata/Europe/Samara:
+ * library/tzdata/Europe/Volgograd:
+ * library/tzdata/America/Kralendijk: (new)
+ * library/tzdata/America/Lower_Princes: (new)
2011-07-21 Jan Nijtmans <nijtmans@users.sf.net>
* win/tclWinPort.h: [Bug 3372130] Fix hypot math function with MSVC10
+2011-07-19 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclUtil.c: [Bug 3371644] Repair failure to properly handle
+ * tests/util.test: (length == -1) scanning in TclConvertElement().
+
2011-07-15 Don Porter <dgp@users.sourceforge.net>
* generic/tclCompile.c: Avoid segfaults when RecordByteCodeStats()
is called in a deleted interp.
-2011-07-13 Don Porter <dgp@users.sourceforge.net>
+2011-07-08 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclProc.c: [Bug 3366265] Buffer for storing the command
- * tests/indexObj.test: name formatted as a list element is allocated
- * tests/proc.test: one byte too small, causing buffer overflow
- when the proc with the empty name raises a "wrong num args" error.
+ * doc/http.n: [FRQ 3358415]: State what RFC defines HTTP/1.1.
2011-07-03 Donal K. Fellows <dkf@users.sf.net>
@@ -39,11505 +70,9534 @@
stat'; that was always the time of the last metadata change, not the
time of creation.
-2011-06-22 Andreas Kupries <andreask@activestate.com>
-
- * library/platform/pkgIndex.tcl: Updated to platform 1.0.10. Added
- * library/platform/platform.tcl: handling of the DEB_HOST_MULTIARCH
- location change for libc.
-
-2011-05-07 Miguel Sofer <msofer@users.sf.net>
-
- * generic/tclInt.h: fix USE_TCLALLOC so that it can be enabled
- * unix/Makefile.in: without editing the Makefile
-
-2011-04-21 Don Porter <dgp@users.sourceforge.net>
-
- * generic/tclCompile.c: Make sure SetFooFromAny routines react
- * generic/tclIndexObj.c: reasonably when passed a NULL interp.
- * generic/tclNamesp.c:
- * generic/tclObj.c:
-
-2011-04-21 Jan Nijtmans <nijtmans@users.sf.net>
-
- * generic/tcl.h: fix for [Bug 3288345]: Wrong Tcl_StatBuf
- * generic/tclInt.h: used on MinGW. Make sure that all _WIN32
- * generic/tclIOUtil.c: compilers use exactly the same layout
- * win/tclWinFile.c: for Tcl_StatBuf - the one used by MSVC6 -
- * win/configure.in: in all situations.
- * win/configure:
-
-2011-04-20 Andreas Kupries <andreask@activestate.com>
-
- * tests/info.test: Fixed the shift in line numbers used for
- testing 'info frame' introduced by checkin [79367df0f0]
- (Mar 2, 2011).
-
-2011-04-13 Miguel Sofer <msofer@users.sf.net>
-
- * generic/tclVar.c: fix for [Bug 2662380], crash caused by
- appending to a variable with a write trace that unsets it.
-
-2011-04-04 Don Porter <dgp@users.sourceforge.net>
-
- * README: Updated README files, repairing broken URLs and
- * macosx/README: removing other bits that were clearly wrong.
- * unix/README: Still could use more eyeballs on the detailed build
- * win/README: advice on various plaforms. [Bug 3202030]
-
-2011-03-25 Jan Nijtmans <nijtmans@users.sf.net>
-
- * generic/tclHash.c: [Bug 3007895]: Tcl_(Find|Create)HashEntry
- stub entries can never be called. They still cannot be called
- (no change in functionality), but at least they now do
- exactly the same as the Tcl_(Find|Create)HashEntry macro's,
- so the confusion addressed in this Bug report is gone.
- Merged --cherrypick from Tcl8.5 (2010-12-31,e75735ef76)
-
-2011-03-24 Donal K. Fellows <dkf@users.sf.net>
-
- * generic/tclFCmd.c (TclFileAttrsCmd): Ensure that any reference to
- temporary index tables is squelched immediately rather than hanging
- around to trip us up in the future.
-
-2011-03-16 Jan Nijtmans <nijtmans@users.sf.net>
-
- * unix/configure, unix/tcl.m4: SHLIB_LD_LIBS='${LIBS}' for OSF1-V*.
- Add /usr/lib64 to set of auto-search dirs. [Bug 1230554]
- (SC_PATH_X): Correct syntax error when xincludes not found.
- Backported from Tcl 8.5
- * generic/tclCkalloc.c: [Bug #3197864] pointer truncation on Win64
- TCL_MEM_DEBUG builds
-
-2010-03-11 Jan Nijtmans <nijtmans@users.sf.net>
-
- * win/tclWin32Dll.c: #ifdef protections to permit builds with
- * win/tclWinChan.c: mingw on amd64 systems. Thanks to "mescalinum"
- * win/tclWinFCmd.c: for reporting and testing.
- Merged --cherrypick from Tcl8.5 (2010-09-08,48191d3979)
-
-2011-03-11 Jan Nijtmans <nijtmans@users.sf.net>
-
- * win/tcl.m4: handle --enable-64bit=ia64 for gcc.
- * win/configure: (autoconf-2.13)
- * win/tclWin32Dll.c: [Patch 3059922]: fixes for mingw64 - gcc4.5.1
- Merged --cherrypick from Tcl8.5 (2011-01-17, 6e410a115b)
-
-2011-03-08 Jan Nijtmans <nijtmans@users.sf.net>
-
- * generic/tclBasic.c: Fix gcc warnings: variable set but not used
-
-2011-03-06 Don Porter <dgp@users.sourceforge.net>
+2011-07-02 Kevin B. Kenny <kennykb@acm.org>
- * generic/tclBasic.c: More replacements of Tcl_UtfBackslash() calls
- * generic/tclCmdMZ.c: with TclParseBackslash() where possible.
- * generic/tclCompExpr.c:
- * generic/tclCompile.c:
- * generic/tclUtil.c (TclFindElement): Guard escape sequence scans
- to not overrun the string end. [Bug 3192636]
-
-2011-03-05 Don Porter <dgp@users.sourceforge.net>
-
- * generic/tclParse.c (TclParseBackslash): Correct trunction checks in
- * tests/parse.test: \x and \u substitutions. [Bug 3200987]
-
-2011-01-25 Jan Nijtmans <nijtmans@users.sf.net>
-
- * generic/tclCkalloc.c: [Bug 3129448]: Possible over-allocation on 64-bit
- * generic/tclHash.c: platforms, part 2, backported strcpy->memcpy
- * generic/tclProc.c change but not change in any struct.
+ * generic/tclStrToD.c:
+ * generic/tclTomMath.decls:
+ * generic/tclTomMathDecls.h:
+ * macosx/Tcl.xcode/project.pbxproj:
+ * macosx/Tcl.xcodeproj/project.pbxproj:
+ * tests/util.test:
+ * unix/Makefile.in:
+ * win/Makefile.in:
+ * win/Makefile.vc:
+ Fix a bug where bignum->double conversion is "round up" and
+ not "round to nearest" (causing expr double(1[string repeat 0 23])
+ not to be 1e+23). [Bug 3349507]
-2011-01-14 Jan Nijtmans <nijtmans@users.sf.net>
+2011-06-30 Reinhard Max <max@suse.de>
- * win/tclWinDde.c: Fix gcc-4.5.2 error: lvalue required as ...
- * win/tclWinReg.c: (backported from 8.5/8.6)
+ * unix/configure.in: Add a volatile declaration to the test for
+ TCL_STACK_GROWS_UP to prevent gcc 4.6 from producing invalid
+ results due to aggressive optimisation.
-2010-12-05 Jan Nijtmans <nijtmans@users.sf.net>
+2011-06-23 Don Porter <dgp@users.sourceforge.net>
- * generic/tclCmdMZ.c: [Bug 3127687] Triggers FORTIFY_SOURCE
- buffer overflow detection
+ *** 8.5.10 TAGGED FOR RELEASE ***
-2010-11-03 Jeff Hobbs <jeffh@ActiveState.com>
+ * changes: Update for 8.5.10 release.
- Backported from 8.6 (see 2010-08-04).
- * win/tclWin32Dll.c (asciiProcs, unicodeProcs):
- * win/tclWinLoad.c (TclpDlopen): 'load' use LoadLibraryEx with
- * win/tclWinInt.h (TclWinProcs): LOAD_WITH_ALTERED_SEARCH_PATH to
- prefer dependent DLLs in same dir as loaded DLL.
+2011-06-22 Andreas Kupries <andreask@activestate.com>
-2010-10-31 Jan Nijtmans <nijtmans@users.sf.net>
+ * library/platform/pkgIndex.tcl: Updated to platform 1.0.10. Added
+ * library/platform/platform.tcl: handling of the DEB_HOST_MULTIARCH
+ * unix/Makefile.in: location change for libc.
+ * win/Makefile.in:
- * win/tcl.m4 Add -D_CRT_SECURE_NO_DEPRECATE and
- -D_CRT_NONSTDC_NO_DEPRECATE, reducing the number of
- deprecation warnings on later VC++ versions.
- * win/rules.vc Better VCVERSION determination
- * win/configure (regenerated with autoconf 2.13)
- All changes backported from Tcl8.5/8.6
+ * generic/tclInt.h: Fixed the inadvertently committed disabling of
+ stack checks, see my 2010-11-15 commit.
-2010-10-23 Jan Nijtmans <nijtmans@users.sf.net>
+2011-06-21 Don Porter <dgp@users.sourceforge.net>
- * tools/uniParse.tcl: [Bug 3085863]: tclUniData 9 years old
- * tools/uniClass.tcl: Upgrade everything to Unicode 6.0, except
- * tests/utf.test: non-BMP characters > 0xFFFF
- * generic/tclUniData.c: (re-generated)
- * generic/regc_locale.c:(re-generated)
- * generic/regcomp.c: fix comment/signatures referencing regc_locale
- * win/rules.vc Update for VS10
+ * changes: Update for 8.5.10 release.
-2010-09-24 Andreas Kupries <andreask@activestate.com>
+ * library/tcltest/tcltest.tcl (loadIntoSlaveInterpreter):
+ * library/tcltest/pkgIndex.tcl: Backport tcltest 2.3.3 for release
+ * unix/Makefile.in: with Tcl 8.5.*.
+ * win/Makefile.in:
- * tclWinsock.c: [Bug 3056775]: Fixed race condition between thread
- and internal co-thread access of a socket's structure because of
- the thread not using the socketListLock in TcpAccept(). Added
- documentation on how the module works to the top.
+ * tests/init.test: Update test files to use new command.
+ * tests/pkg.test:
-2010-09-01 Andreas Kupries <andreask@activestate.com>
+ * generic/tclLink.c: Prevent multiple links to a single Tcl
+ variable when calling Tcl_LinkVar(). [Bug 3317466]
- * generic/tclExecute.c: [Bug 3057639]. Applied patch by Jeff to
- * generic/tclVar.c: make the behaviour of lappend in bytecompiled
- * tests/append.test: mode consistent with direct-eval and 'append'
- * tests/appendComp.test: generally. Added tests (append*-9.*)
- showing the difference.
+2011-06-13 Don Porter <dgp@users.sourceforge.net>
-2010-07-25 Jan Nijtmans <nijtmans@users.sf.net>
+ * generic/tclStrToD.c: [Bug 3315098] Mem leak fix from Gustaf Neumann.
- * generic/tclInt.h: [Bug 3030870] make itcl 3.x built with pre-8.6
- * generic/tclBasic.c: work in 8.6 revert tclInt.h to what it was
- before, and relax the relation between Tcl_CallFrame and
- CallFrame.
+2011-06-02 Don Porter <dgp@users.sourceforge.net>
-2010-07-18 Jan Nijtmans <nijtmans@users.sf.net>
+ * generic/tclBasic.c: Removed TclCleanupLiteralTable(), and old
+ * generic/tclInt.h: band-aid routine put in place while a fix
+ * generic/tclLiteral.c: for [Bug 994838] took shape. No longer needed.
- * generic/tcl.h: [Bug 3031278] fixed merge problem in previous
- commit.
+2011-06-02 Donal K. Fellows <dkf@users.sf.net>
-2010-07-17 Jan Nijtmans <nijtmans@users.sf.net>
+ * generic/tclInt.h (TclInvalidateNsCmdLookup): [Bug 3185407]: Extend
+ the set of epochs that are potentially bumped when a command is
+ created, for a slight performance drop (in some circumstances) and
+ improved semantics.
- * generic/tcl.h: [Bug 3030870] make itcl 3.x built with pre-8.6
- * generic/tclInt.h: work in 8.6
+2011-06-01 Jan Nijtmans <nijtmans@users.sf.net>
-2010-07-16 Jan Nijtmans <nijtmans@users.sf.net>
+ * generic/tclUtil.c: Fix for [Bug 3309871]: Valgrind finds:
+ invalid read in TclMaxListLength()
- * generic/tcl.h: (Backport) take over definitions of _WIN32,
- DLLIMPORT, DLLEXPORT and TCL_LL_MODIFIER macros from Tcl8.5/8.6
+2011-05-25 Don Porter <dgp@users.sourceforge.net>
-2010-06-28 Jan Nijtmans <nijtmans@users.sf.net>
+ * library/msgcat/msgcat.tcl: Backport improvements to msgcat
+ * library/msgcat/pkgIndex.tcl: package. Bump to 1.4.4
+ * unix/Makefile.in
+ * win/Makefile.in
- * generic/tclPosixStr.c: [Bug 3019634] errno.h and tclWinPort.h
- have conflicting definitions.
+2011-05-24 Venkat Iyer <venkat@comit.com>
-2010-06-09 Andreas Kupries <andreask@activestate.com>
+ * library/tzdata/Africa/Cairo: Update to Olson tzdata2011g
- * library/platform/platform.tcl: Added OSX Intel 64bit
- * library/platform/pkgIndex.tcl: Package updated to version 1.0.9.
+2011-05-17 Andreas Kupries <andreask@activestate.com>
-2010-05-07 Andreas Kupries <andreask@activestate.com>
+ * generic/tclCompile.c (TclFixupForwardJump): Tracked down and fixed
+ * generic/tclBasic.c (TclArgumentBCEnter): the cause of a violation
+ of my assertion that 'ePtr->nline == objc' in TclArgumentBCEnter.
+ When a bytecode was grown during jump fixup the pc -> command line
+ mapping was not updated. When things aligned just wrong the mapping
+ would direct command A to the data for command B, with a different
+ number of arguments.
- * library/platform/platform.tcl: Fix cpu name for Solaris/Intel 64bit.
- * library/platform/pkgIndex.tcl: Package updated to version 1.0.8.
+2011-05-10 Don Porter <dgp@users.sourceforge.net>
-2010-04-29 Andreas Kupries <andreask@activestate.com>
+ * generic/tclInt.h: New internal routines TclScanElement() and
+ * generic/tclUtil.c: TclConvertElement() are rewritten guts of
+ machinery to produce string rep of lists. The new routines avoid
+ and correct [Bug 3173086]. See comments for much more detail.
- * library/platform/platform.tcl: Another stab at getting the /lib,
- * library/platform/pkgIndex.tcl: /lib64 difference right for
- linux. Package updated to version 1.0.7.
+ * generic/tclDictObj.c: Update all callers.
+ * generic/tclIndexObj.c:
+ * generic/tclListObj.c:
+ * generic/tclUtil.c:
+ * tests/list.test:
-2010-04-18 Donal K. Fellows <dkf@users.sf.net>
+2011-05-09 Don Porter <dgp@users.sourceforge.net>
- * doc/unset.n: [Bug 2988940]: Fix typo.
+ * generic/tclListObj.c: Revise empty string tests so that we avoid
+ potentially expensive string rep generations, especially for dicts.
-2010-04-14 Andreas Kupries <andreask@activestate.com>
+2011-05-07 Miguel Sofer <msofer@users.sf.net>
- * library/platform/platform.tcl: Linux platform identification:
- * library/platform/pkgIndex.tcl: Check /lib64 for existence of
- files matching libc* before accepting it as base directory. This
- can happen on weirdly installed 32bit systems which have an empty
- or partially filled /lib64 without an actual libc. Bumped to
- version 1.0.6.
+ * generic/tclInt.h: fix USE_TCLALLOC so that it can be enabled
+ * unix/Makefile.in: without editing the Makefile
-2010-04-06 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+2011-05-05 Don Porter <dgp@users.sourceforge.net>
- * generic/tclCmdMZ.c (Tcl_RegexpObjCmd): fixed object leak.
+ * generic/tclListObj.c: Stop generating string rep of dict when
+ converting to list. Tolerate NULL interps more completely.
-2010-04-02 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+2011-05-03 Don Porter <dgp@users.sourceforge.net>
- * generic/tclStringObj.c: (SetStringFromAny): avoid trampling
- over the tclEmptyStringRep->bytes as it is thread-shared
- (thx to Gustaf Neumann for the (hard) work of locating this one).
+ * generic/tclUtil.c: Tighten Tcl_SplitList().
+ * generic/tclListObj.c: Tighten SetListFromAny().
+ * generic/tclDictObj.c: Tighten SetDictFromAny().
-2010-03-01 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
+2011-05-02 Don Porter <dgp@users.sourceforge.net>
- * unix/tclUnixChan.c: [backported] Refrain from a possibly lengthy
- reverse-DNS lookup on 0.0.0.0 when calling [fconfigure -sockname]
- on an universally-bound (default) server socket.
+ * generic/tclCmdMZ.c: Revised TclFindElement() interface. The
+ * generic/tclDictObj.c: final argument had been bracePtr, the address
+ * generic/tclListObj.c: of a boolean var, where the caller can be told
+ * generic/tclParse.c: whether or not the parsed list element was
+ * generic/tclUtil.c: enclosed in braces. In practice, no callers
+ really care about that. What the callers really want to know is
+ whether the list element value exists as a literal substring of the
+ string being parsed, or whether a call to TclCopyAndCollpase() is
+ needed to produce the list element value. Now the final argument
+ is changed to do what callers actually need. This is a better fit
+ for the calls in tclParse.c, where now a good deal of post-processing
+ checking for "naked backslashes" is no longer necessary.
+ ***POTENTIAL INCOMPATIBILITY***
+ For any callers calling in via the internal stubs table who really
+ do use the final argument explicitly to check for the enclosing brace
+ scenario. Simply looking for the braces where they must be is the
+ revision available to those callers, and it will backport cleanly.
-2010-02-22 Jan Nijtmans <nijtmans@users.sf.net>
+ * tests/parse.test: Tests for expanded literals quoting detection.
- * generic/tclExecute.c: Fix [Bug 2954959] expr abs(-0.0) is -0.0
- * tests/expr.test Added some test cases, backported from 8.5
+ * generic/tclCompCmds.c: New TclFindElement() is also a better
+ fit for the [switch] compiler.
-2010-02-11 Andreas Kupries <andreask@activestate.com>
+ * generic/tclInt.h: Replace TclCountSpaceRuns() with
+ * generic/tclListObj.c: TclMaxListLength() which is the function we
+ * generic/tclUtil.c: actually want.
+ * generic/tclCompCmds.c:
- * generic/tclCompile.c: [Bug 2949302]: Fixed leak of support
- structures for [info frame] which occured when bytecode
- compilation fails.
+ * generic/tclCompCmds.c: Rewrite of parts of the switch compiler to
+ better use the powers of TclFindElement() and do less parsing on
+ its own.
-2010-02-01 Donal K. Fellows <dkf@users.sf.net>
+2011-04-28 Don Porter <dgp@users.sourceforge.net>
- * generic/regexec.c (ccondissect, crevdissect): [Bug 2942697]: Rework
- these functions so that certain pathological patterns are matched much
- more rapidly. Many thanks to Tom Lane for dianosing this issue and
- providing an initial patch.
+ * generic/tclInt.h: New utility routines:
+ * generic/tclParse.c: TclIsSpaceProc() and
+ * generic/tclUtil.c: TclCountSpaceRuns()
-2009-11-16 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
-
- * generic/tclEncoding.c: (Backport) Fix [Bug 2891556] and improve
- * tests/econding.test: test to detect similar manifestations in the
- future.
+ * generic/tclCmdMZ.c: Use new routines to replace calls to
+ * generic/tclListObj.c: isspace() and their /* INTL */ risk.
+ * generic/tclStrToD.c:
+ * generic/tclUtf.c:
+ * unix/tclUnixFile.c:
-2009-11-12 Andreas Kupries <andreask@activestate.com>
-
- * generic/tclIO.c (CopyData): [Bug 2895565]. Dropped bogosity
- * tests/io.test: which used the number of _written_ bytes or
- character to update the counters for the read bytes/characters.
- New test io-53.11. This is a backward port from the 8.5 branch.
-
-2009-11-10 Pat Thoyts <patthoyts@users.sourceforge.net>
-
- * tests/fCmd.test: Fixed a number of issues for Vista
- * tests/registry.test: and Win7 that are due to restricted
- * tests/tcltest.test: permissions under UAC.
- * tests/winFCmd.test:
-
-2009-11-10 Stuart Cassoff <stwo@users.sf.net>
+2011-04-27 Don Porter <dgp@users.sourceforge.net>
- * win/README: [bug 2459744]: Removed outdated Msys + Mingw info.
-
-2009-11-10 Andreas Kupries <andreask@activestate.com>
-
- * generic/tclObj.c: Plug memory leak in TclContinuationsEnter().
- [Bug 2895323]. Backport from Tcl 8.5 branch, change by Don Porter.
-
-2009-11-09 Andreas Kupries <andreask@activestate.com>
-
- * generic/tclBasic.c (TclEvalObjEx): Moved the #280 decrement of
- refCount for the file path out of the branch after the whole
- conditional, closing a memory leak. Added clause on structure type
- to prevent seg.faulting. Backport from valgrinding the Tcl 8.5
- branch.
+ * generic/tclListObj.c: FreeListInternalRep() cleanup.
- * tests/info.test: Resolve ambiguous resolution of variable
- "res". Backport from 8.5
-
-2009-10-23 Andreas Kupries <andreask@activestate.com>
-
- * generic/tclCompCmds.c: [Bug 2881263] (TclCompileForeachCmd,
- TclCompileLindexCmd): Fixed. Moved the use of
- DefineLineInformation after all regular variable declarations, so
- that an empty statement (-UTIP_280) doesn't confuse c89 compilers.
-
- * library/platform/pkgIndex.tcl: Backported the platform packages
- * library/platform/platform.tcl: from head and8.5 into the 8.4
- * library/platform/shell.tcl: branch. Updated makefiles to install
- * unix/Makfile.in: the packages.
- * win/Makefile.in:
-
- * generic/tclIO.c (FlushChannel): Skip OutputProc for low-level
- 0-length writes. When closing pipes which have already been closed
- not skipping leads to spurious SIG_PIPE signals. Reported by
- Mikhail Teterin <mi+thun@aldan.algebra.com>.
-
-2009-10-21 Donal K. Fellows <dkf@users.sf.net>
-
- * generic/tclPosixStr.c: [Bug 2882561]: Work around oddity on Haiku OS
- where SIGSEGV and SIGBUS are the same value.
-
-2009-10-18 Joe Mistachkin <joe@mistachkin.com>
-
- * tests/thread.test (thread-4.[345]): [Bug 1565466]: Correct tests to
- save their error state before the final call to threadReap just in case
- it triggers an "invalid thread id" error. This error can occur if one
- or more of the target threads has exited prior to the attempt to send
- it an asynchronous exit command.
+ * generic/tclBinary.c: Backport fix for [Bug 2857044].
+ * generic/tclDictObj.c: All freeIntRepProcs set typePtr to NULL.
+ * generic/tclEncoding.c:
+ * generic/tclIndexObj.c:
+ * generic/tclListObj.c:
+ * generic/tclNamesp.c:
+ * generic/tclObj.c:
+ * generic/tclPathObj.c:
+ * generic/tclProc.c:
+ * generic/tclRegexp.c:
+ * generic/tclStringObj.c:
+ * generic/tclVar.c:
-2009-10-04 Daniel Steffen <das@users.sourceforge.net>
+2011-04-21 Don Porter <dgp@users.sourceforge.net>
- * macosx/tclMacOSXBundle.c: Workaround CF memory managment bug in
- * unix/tclUnixInit.c: Mac OS X 10.4 & earlier. [Bug 2569449]
+ * generic/tclInt.h: Use macro to set List intreps.
+ * generic/tclListObj.c:
-2009-09-28 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclCmdIL.c: Limits on list length were too strict.
+ * generic/tclInt.h: Revised panics to errors where possible.
+ * generic/tclListObj.c:
- * generic/tclAlloc.c: Cleaned up various routines in the
- * generic/tclCkalloc.c: call stacks for memory allocation to
- * generic/tclParse.c: guarantee that any size values computed
- * generic/tclThreadAlloc.c: are within the domains of the routines
- they get passed to. [Bugs 2557696 and 2557796].
+ * generic/tclCompile.c: Make sure SetFooFromAny routines react
+ * generic/tclIO.c: reasonably when passed a NULL interp.
+ * generic/tclIndexObj.c:
+ * generic/tclListObj.c:
+ * generic/tclNamesp.c:
+ * generic/tclObj.c:
+ * generic/tclProc.c:
+ * macosx/tclMacOSXFCmd.c:
-2009-09-18 Don Porter <dgp@users.sourceforge.net>
+2011-04-21 Jan Nijtmans <nijtmans@users.sf.net>
- * generic/tclCmdMZ.c (Tcl_SubstObj): Pass 'length' values to
- recursive parsing calls to convert O(N^2) operations of [subst]
- to O(N).
+ * generic/tcl.h: fix for [Bug 3288345]: Wrong Tcl_StatBuf
+ * generic/tclInt.h: used on MinGW. Make sure that all _WIN32
+ * win/tclWinFile.c: compilers use exactly the same layout
+ * win/configure.in: for Tcl_StatBuf - the one used by MSVC6 -
+ * win/configure: in all situations.
-2009-08-25 Andreas Kupries <andreask@activestate.com>
+2011-04-20 Andreas Kupries <andreask@activestate.com>
- * generic/tclBasic.c (Tcl_CreateInterp, Tcl_EvalTokensStandard,
- (EvalTokensStandard, Tcl_EvalEx, EvalEx, TclAdvanceContinuations,
- (TclEvalObjEx):
- * generic/tclCmdMZ.c (Tcl_SwitchObjCmd, ListLines):
- * generic/tclCompCmds.c (*):
- * generic/tclCompile.c (TclSetByteCodeFromAny, TclInitCompileEnv,
- (TclFreeCompileEnv, TclCompileScript):
- * generic/tclCompile.h (CompileEnv):
- * generic/tclInt.h (ContLineLoc, Interp):
- * generic/tclObj.c (ThreadSpecificData, ContLineLocFree,
- (TclThreadFinalizeObjects, TclInitObjSubsystem,
- (TclContinuationsEnter, TclContinuationsEnterDerived,
- (TclContinuationsCopy, TclContinuationsGet, TclFreeObj):
- * generic/tclProc.c (TclCreateProc):
- * generic/tclVar.c (TclPtrSetVar):
- * tests/info.test (info-30.0-22):
+ * generic/tclFCmd.c (TclFileAttrsCmd): Added commands to reset the
+ typePtr of the Tcl_Obj* whose int-rep was just purged. Required to
+ prevent a dangling IndexRep* to reused, smashing the heap. See
+ also the entries at 2011-04-16 and 2011-03-24 for the history of
+ the problem.
- Extended parser, compiler, and execution with code and attendant
- data structures tracking the positions of continuation lines which
- are not visible in script's, to properly account for them while
- counting lines for #280, during direct and compiled execution.
+2011-04-19 Don Porter <dgp@users.sourceforge.net>
-2009-08-17 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclConfig.c: Reduce internals access in the implementation
+ of [<foo>::pkgconfig list].
- * generic/tclFileName.c: Correct result from [glob */test] when *
- * tests/fileName.test: matches something like ~foo. [Bug 2837800]
+2011-04-18 Don Porter <dgp@users.sourceforge.net>
-2009-07-23 Joe Mistachkin <joe@mistachkin.com>
+ * generic/tclCmdIL.c: Use ListRepPtr(.) and other cleanup.
+ * generic/tclConfig.c:
+ * generic/tclListObj.c:
- * generic/tclNotify.c: Fix for [Bug 2820349].
+ * generic/tclInt.h: Define and use macros that test whether
+ * generic/tclBasic.c: a Tcl list value is canonical.
+ * generic/tclUtil.c:
-2009-07-14 Andreas Kupries <andreask@activestate.com>
+2011-04-16 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclBasic.c (DeleteInterpProc,TclArgumentBCEnter,
- (TclArgumentBCRelease, TclArgumentGet):
- * generic/tclCompile.c (EnterCmdWordIndex, TclCleanupByteCode,
- (TclInitCompileEnv, TclCompileScript):
- * generic/tclCompile.h (ExtCmdLoc):
- * generic/tclExecute.c (TclExecuteByteCode):
- * generic/tclInt.h (ExtIndex, CFWordBC):
- * tests/info.test (info-39.0):
+ * generic/tclFCmd.c (TclFileAttrsCmd): Tidied up the memory management
+ a bit to try to ensure that the dynamic and static cases don't get
+ confused while still promoting caching where possible. Added a panic
+ to trap problems in the case where an extension is misusing the API.
- Backport of some changes made to the Tcl head, to handle literal
- sharing better. The code here is much simpler (trimmed down)
- compared to the head as the 8.4 branch is not bytecode compiling
- whole files, and doesn't compile eval'd code either.
-
- Reworked the handling of literal command arguments in bytecode to
- be saved (compiler) and used (execution) per command (See the
- TCL_INVOKE_STK* instructions), and not per the whole bytecode.
- This removes the problems with location data caused by literal
- sharing in proc bodies. Simplified the associated datastructures
- (ExtIndex is gone, as is the function EnterCmdWordIndex).
+2011-04-13 Don Porter <dgp@users.sourceforge.net>
-2009-06-13 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclUtil.c: [Bug 3285375]: Rewrite of Tcl_Concat*()
+ routines to prevent segfaults on buffer overflow. Build them out of
+ existing primitives already coded to handle overflow properly. Uses
+ the new TclTrim*() routines.
- * generic/tclCompile.c: The value stashed in iPtr->compiledProcPtr
- * generic/tclProc.c: when compiling a proc survives too long. We
- * tests/execute.test: only need it there long enough for the right
- TclInitCompileEnv() call to re-stash it into envPtr->procPtr. Once
- that is done, the CompileEnv controls. If we let the value of
- iPtr->compiledProcPtr linger, though, then any other bytecode compile
- operation that takes place will also have its CompileEnv initialized
- with it, and that's not correct. The value is meant to control the
- compile of the proc body only, not other compile tasks that happen
- along. Thanks to Carlos Tasada for discovering and reporting the
- problem. [Bug 2802881].
+ * generic/tclCmdMZ.c: New internal utility routines TclTrimLeft()
+ * generic/tclInt.h: and TclTrimRight(). Refactor the
+ * generic/tclUtil.c: [string trim*] implementations to use them.
-2009-04-28 Jeff Hobbs <jeffh@ActiveState.com>
+2011-04-13 Miguel Sofer <msofer@users.sf.net>
- * unix/tcl.m4, unix/configure (SC_CONFIG_CFLAGS): harden the check
- to add _r to CC on AIX with threads.
+ * generic/tclVar.c: [Bug 2662380]: Fix crash caused by appending to a
+ variable with a write trace that unsets it.
-2009-04-27 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
+2011-04-12 Don Porter <dgp@users.sourceforge.net>
- * generic/tclInt.h: Backport fix for [Bug 1028264]: WSACleanup() too
- * generic/tclEvent.c: early. The fix introduces "late exit handlers"
- * win/tclWinSock.c: for similar late process-wide cleanups.
+ * generic/tclStringObj.c: [Bug 3285472]: Repair corruption in
+ * tests/string.test: [string reverse] when string rep invalidation
+ failed to also reset the bytes allocated for string rep to zero.
-2009-04-27 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
+2011-04-12 Venkat Iyer <venkat@comit.com>
- * win/tclWinSock.c: Backport fix for [Bug 2446662]: resync Win
- behavior on RST with that of unix (EOF).
+ * library/tzdata/Atlantic/Stanley: Update to Olson tzdata2011f
-2009-04-22 Andreas Kupries <andreask@activestate.com>
+2011-04-06 Miguel Sofer <msofer@users.sf.net>
- * generic/tclStringObj.c (UpdateStringOfString): Added cast to fix
- signed/unsigned mismatch breaking win32 symbol/debug build.
+ * generic/tclExecute.c (TclCompEvalObj): Earlier return if Tip280
+ gymnastics not needed.
-2009-04-15 Don Porter <dgp@users.sourceforge.net>
+2011-04-05 Venkat Iyer <venkat@comit.com>
- * generic/tclStringObj.c: AppendUnicodeToUnicodeRep failed
- to set stringPtr->allocated to 0, leading to crashes.
+ * library/tzdata/Africa/Casablanca: Update to Olson's tzdata2011e
+ * library/tzdata/America/Santiago:
+ * library/tzdata/Pacific/Easter:
+ * library/tzdata/America/Metlakatla: (new)
+ * library/tzdata/America/North_Dakota/Beulah: (new)
+ * library/tzdata/America/Sitka: (new)
-2009-04-14 Stuart Cassoff <stwo@users.sourceforge.net>
+2011-04-04 Don Porter <dgp@users.sourceforge.net>
- * unix/tcl.m4: Removed -Wno-implicit-int from CFLAGS_WARNING.
+ * README: Updated README files, repairing broken URLs and
+ * macosx/README: removing other bits that were clearly wrong.
+ * unix/README: Still could use more eyeballs on the detailed build
+ * win/README: advice on various plaforms. [Bug 3202030]
-2009-04-08 Don Porter <dgp@users.sourceforge.net>
+2011-04-02 Kevin B. Kenny <kennykb@acm.org>
- * library/tcltest/tcltest.tcl: Fixed unsafe [eval]s in the tcltest
- * library/tcltest/pkgIndex.tcl: package. [Bug 2570363]
+ * generic/tclStrToD.c (QuickConversion): Replaced another couple of
+ 'double' declarations with 'volatile double' to work around
+ misrounding issues in mingw-gcc 3.4.5.
-2009-04-07 Don Porter <dgp@users.sourceforge.net>
+2011-03-24 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclStringObj.c: Completed backports of fixes for
- [Bug 2494093] and [Bug 2553906].
+ * generic/tclFCmd.c (TclFileAttrsCmd): Ensure that any reference to
+ temporary index tables is squelched immediately rather than hanging
+ around to trip us up in the future.
-2009-03-30 Don Porter <dgp@users.sourceforge.net>
+2011-03-21 Jan Nijtmans <nijtmans@users.sf.net>
- * doc/Alloc.3: Size argument is "unsigned int". [Bug 2556263]
+ * unix/tclLoadDl.c: [Bug #3216070]: Loading extension libraries
+ * unix/tclLoadDyld.c: from embedded Tcl applications.
- * generic/tclStringObj.c: Added protections from invalid memory
- * generic/tclTestObj.c: accesses when we append (some part of)
- * tests/stringObj.test: a Tcl_Obj to itself. Added the
- appendself and appendself2 subcommands to the [teststringobj] testing
- command and added tests to the test suite. [Bug 2603158]
+2011-03-16 Jan Nijtmans <nijtmans@users.sf.net>
-2009-03-27 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclCkalloc.c: [Bug #3197864]: pointer truncation on Win64
+ TCL_MEM_DEBUG builds
- * tests/fileName.test: Tests for [Bug 2710920] to guard against
- its appearance.
+2011-03-16 Don Porter <dgp@users.sourceforge.net>
-2009-03-20 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclBasic.c: Some rewrites to eliminate calls to
+ * generic/tclParse.c: isspace() and their /* INTL */ risk.
+ * generic/tclProc.c:
- * generic/tclStringObj.c: Test stringObj-6.9 checks that
- * tests/stringObj.test: Tcl_AppendStringsToObj() no longer
- crashes when operating on a pure unicode value. [Bug 2597185]
+2011-03-16 Jan Nijtmans <nijtmans@users.sf.net>
- * generic/tclExecute.c (INST_CONCAT1): Panic when appends overflow
- the max length of a Tcl value. [Bug 2669109]
+ * unix/tcl.m4: Make SHLIB_LD_LIBS='${LIBS}' the default and
+ * unix/configure: set to "" on per-platform necessary basis.
+ Backported from TEA, but kept all original platform code which was
+ removed from TEA.
-2009-03-18 Don Porter <dgp@users.sourceforge.net>
+2011-03-14 Kevin B. Kenny <kennykb@acm.org>
- * win/tclWinFile.c (TclpObjNormalizePath): Corrected Tcl_Obj leak.
- Thanks to Joe Mistachkin for detection and patch. [Bug 2688184].
+ * tools/tclZIC.tcl (onDayOfMonth): Allow for leading zeroes
+ in month and day so that tzdata2011d parses correctly.
+ * library/tzdata/America/Havana:
+ * library/tzdata/America/Juneau:
+ * library/tzdata/America/Santiago:
+ * library/tzdata/Europe/Istanbul:
+ * library/tzdata/Pacific/Apia:
+ * library/tzdata/Pacific/Easter:
+ * library/tzdata/Pacific/Honolulu: tzdata2011d
-2009-02-20 Don Porter <dgp@users.sourceforge.net>
- * generic/tclPathObj.c: Fixed mistaken logic in TclFSGetPathType()
- * tests/fileName.test: that assumed (not "absolute" => "relative").
- This is a false assumption on Windows, where "volumerelative" is
- another possibility. [Bug 2571597].
+ * unix/configure.in: [Bug 3205320]: stack space detection defeated by inlining
+ * unix/configure: (autoconf-2.59)
-2008-02-06 Daniel Steffen <das@users.sourceforge.net>
+2011-03-09 Don Porter <dgp@users.sourceforge.net>
- * generic/tcl.h (Darwin): workaround conflict between deprecated tcl
- panic macro and panic() function declaration in <mach/mach.h> header.
+ * generic/tclNamesp.c: Tighten the detector of nested [namespace code]
+ * tests/namespace.test: quoting that the quoted scripts function
+ properly even in a namespace that contains a custom "namespace"
+ command. [Bug 3202171]
-2009-02-05 Don Porter <dgp@users.sourceforge.net>
+ * doc/tclvars.n: Formatting fix. Thanks to Pat Thotys.
- * generic/tclStringObj.c: Added overflow protections to the
- AppendUtfToUtfRep routine to either avoid invalid arguments and
- crashes, or to replace them with controlled panics. [Bug 2561794]
+2011-03-08 Jan Nijtmans <nijtmans@users.sf.net>
-2009-02-04 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclBasic.c: Fix gcc warnings: variable set but not used
- * generic/tclStringObj.c (SetUnicodeObj): Corrected failure of
- Tcl_SetUnicodeObj() to panic on a shared object. [Bug 2561488]. Also
- factored out common code to reduce duplication.
+2011-03-08 Don Porter <dgp@users.sourceforge.net>
-2009-01-09 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclInt.h: Remove TclMarkList() routine, an experimental
+ * generic/tclUtil.c: dead-end from the 8.5 alpha days.
- * generic/tclStringObj.c (STRING_SIZE): Corrected failure to limit
- memory allocation requests to the sizes that can be supported by
- Tcl's memory allocation routines. [Bug 2494093].
+ * generic/tclResult.c (ResetObjResult): Correct failure to clear
+ invalid intrep. Thanks to Colin McDonald. [Bug 3202905]
-2009-01-08 Don Porter <dgp@users.sourceforge.net>
+2011-03-06 Don Porter <dgp@users.sourceforge.net>
- * generic/tclStringObj.c (STRING_UALLOC): Added missing parens
- required to get correct results out of things like
- STRING_UALLOC(num + append). [Bug 2494093].
+ * generic/tclBasic.c: More replacements of Tcl_UtfBackslash() calls
+ * generic/tclCompile.c: with TclParseBackslash() where possible.
+ * generic/tclParse.c:
+ * generic/tclUtil.c:
-2008-12-04 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclUtil.c (TclFindElement): Guard escape sequence scans
+ to not overrun the string end. [Bug 3192636]
- * generic/tclIOUtil.c (Tcl_FSGetNormalizedPath): Added another
- flag value TCLPATH_NEEDNORM to mark those intreps which need more
- complete normalization attention for correct results. [Bug 2385549]
+2011-03-05 Don Porter <dgp@users.sourceforge.net>
-2008-12-03 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclParse.c (TclParseBackslash): Correct trunction checks in
+ * tests/parse.test: \x and \u substitutions. [Bug 3200987]
- * generic/tclFileName.c (TclDoGlob): One of the
- Tcl_FSMatchInDirectory() calls did not have its return code
- checked. Some VFS drivers can return TCL_ERROR, and when that's
- not checked, the error message gets converted into a list of
- matching files returned by [glob], with ridiculous results.
+2011-01-26 Donal K. Fellows <dkf@users.sf.net>
-2008-12-01 Don Porter <dgp@users.sourceforge.net>
+ * doc/RegExp.3: [Bug 3165108]: Corrected documentation of description
+ of subexpression info in Tcl_RegExpInfo structure.
- * generic/tclIO.c (TclFinalizeIOSubsystem): Revised latest commit to
- something that doesn't crash the test suite.
+2011-01-25 Jan Nijtmans <nijtmans@users.sf.net>
-2008-11-25 Andreas Kupries <andreask@activestate.com>
+ * generic/tclCkalloc.c: [Bug 3129448]: Possible over-allocation on
+ * generic/tclHash.c: 64-bit platforms, part 2, backported
+ * generic/tclProc.c: strcpy->memcpy change but not change in any
+ struct.
- * generic/tclIO.c (TclFinalizeIOSubsystem): Applied backport of
- Alexandre Ferrieux's patch for [Bug 2270477] to prevent infinite
- looping during finalization of channels not bound to
- interpreters.
+2011-01-19 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
-2008-11-23 Andreas Kupries <andreask@activestate.com>
+ * generic/tclExecute.c: [Bug 3138178]: Backport of Miguel's 2010-09-22
+ fix on 8.6 branch (decache stack info wherever ::errorInfo may be
+ updated, for trace sanity).
- * generic/tclIO.c: Backport of fix for [Bug 2333466].
+2011-01-19 Jan Nijtmans <nijtmans@users.sf.net>
-2008-11-04 Jeff Hobbs <jeffh@ActiveState.com>
+ * tools/genStubs.tcl: Make sure to use CONST/VOID in stead of
+ * generic/tclIntDecls.h: const/void when appropriate. This allows to
+ * generic/tclIntPlatDecls.h:use const/void in the *.decls file always,
+ * generic/tclTomMathDecls.h:genStubs will do the right thing.
- * generic/tclPort.h: remove the ../{win,unix}/ header dirs as the
- build system already has it, and it confuses builds when used with
- private headers installed.
+2011-01-18 Jan Nijtmans <nijtmans@users.sf.net>
-2008-09-25 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclBasic.c: Various mismatches between Tcl_Panic
+ * generic/tclCompCmds.c: format string and its arguments,
+ * generic/tclCompExpr.c: discovered thanks to [Bug 3159920]
+ * generic/tclPreserve.c: (Backported)
+ * generic/tclTest.c:
- * doc/global.n: Correct false claim about [info locals].
+2011-01-17 Jan Nijtmans <nijtmans@users.sf.net>
-2008-08-14 Don Porter <dgp@users.sourceforge.net>
+ * win/tcl.m4: handle --enable-64bit=ia64 for gcc. BACKPORT.
+ * win/configure: (autoconf-2.59)
+ * win/tclWin32Dll.c: [Patch 3059922]: fixes for mingw64 - gcc4.5.1
+ * generic/tclIOCmd.c: [Bug 3148192]: Commands "read/puts" incorrectly
+ * tests/chanio.test: interpret parameters. Improved error-message
+ * tests/io.test regarding legacy form.
+ * tests/ioCmd.test
- * tests/fileName.test: Revise new tests for portability to case
- insensitive filesystems.
+2011-01-15 Kevin B. Kenny <kennykb@users.sf.net>
-2008-08-14 Daniel Steffen <das@users.sourceforge.net>
+ * doc/tclvars.n:
+ * generic/tclStrToD.c:
+ * generic/tclUtil.c (Tcl_PrintDouble):
+ * tests/util.test (util-16.*): Restored full Tcl 8.4 compatibility
+ for the formatting of floating point numbers when $::tcl_precision
+ is not zero. Added compatibility tests to make sure that excess
+ trailing zeroes are suppressed for all eight major code paths.
+ [Bug 3157475]
- * generic/tclCompile.h: add support for debug logging of DTrace
- * generic/tclBasic.c: 'proc', 'cmd' and 'inst' probes (does
- _not_ require a platform with DTrace).
+2011-01-13 Miguel Sofer <msofer@users.sf.net>
- * unix/Makefile.in: ensure Makefile shell is /bin/bash for
- * unix/configure.in (SunOS): DTrace-enabled build on Solaris.
- (followup to 2008-06-12) [Bug 2016584]
+ * generic/tclExecute.c (GrowEvaluationStack): Off-by-one error in
+ sizing the new allocation - was ok in comment but wrong in the code.
+ Triggered by [Bug 3142026] which happened to require exactly one more
+ than what was in existence. BACKPORT.
- * unix/tcl.m4 (SC_PATH_X): check for libX11.dylib in addition to
- libX11.so et al.
+2011-01-03 Jan Nijtmans <nijtmans@users.sf.net>
- * unix/configure: autoconf-2.13
+ * tools/genStubs.tcl: Fix "make genstubs", which was broken
+ since 2010-11-30, the TclDoubleDigits backport.
-2008-08-13 Don Porter <dgp@users.sourceforge.net>
+2010-12-31 Jan Nijtmans <nijtmans@users.sf.net>
- * generic/tclFileName.c: Fix for errors handling -types {}
- * tests/fileName.test: option to [glob]. [Bug 1750300]
- Thanks to Matthias Kraft and George Peter Staplin.
+ * generic/tclHash.c: [Bug 3007895]: Tcl_(Find|Create)HashEntry
+ stub entries can never be called. They still cannot be called
+ (no change in functionality), but at least they now do
+ exactly the same as the Tcl_(Find|Create)HashEntry macro's,
+ so the confusion addressed in this Bug report is gone.
+ (Backported from Tcl 8.6)
-2008-08-11 Andreas Kupries <andreask@activestate.com>
+2010-12-17 Stuart Cassoff <stwo@users.sourceforge.net>
- * generic/tclProc.c (Tcl_ProcObjCmd): Fixed memory leak triggered
- * tests/proc.test: by procbody::test::proc. See [Bug 2043636].
- Added a test case demonstrating the leak before the fix. Fixed a
- few spelling errors in test descriptions as well.
+ * unix/Makefile.in: Remove unwanted/obsolete 'ddd' target.
-2008-07-28 Andreas Kupries <andreask@activestate.com>
+2010-12-17 Stuart Cassoff <stwo@users.sourceforge.net>
- * generic/tclBasic.c: Added missing release of extended command
- word index when deleting an interpreter (DeleteInterpProc). Added
- missing ref count when creating an empty string as path (EvalEx).
+ * unix/Makefile.in: [Bug 2446711]: Remove 'allpatch' target.
- * generic/tclCompile.c (TclInitCompileEnv): Made same change to
- control flow as in TclEvalObjEx. Not needed while uplevel and
- siblings go through the eval-direct code path, however if that
- changes (like it did in 8.5+) better to have this in place instead
- of re-searching why certain places are without absolute locations.
+2010-12-17 Stuart Cassoff <stwo@users.sourceforge.net>
- * tests/info.test: Added tests 38.*, exactly testing the tracking
- of location for uplevel scripts, and made the testsuite fully
- usable with and without -singleproc 1.
+ * unix/Makefile.in: Use 'rpmbuild', not 'rpm' [Bug 2537626].
-2008-07-25 Daniel Steffen <das@users.sourceforge.net>
+2010-12-13 Jan Nijtmans <nijtmans@users.sf.net>
- * tests/info.test: Add !singleTestInterp constraint to various tests;
- (info-22.8, info-23.0): switch to glob matching to avoid sensitivity
- to tcltest.tcl line number changes. [Bug 1605269]
+ * unix/tcl.m4: Cross-compile support for Win and UNIX (backported)
+ * unix/configure: (autoconf-2.59)
+ * win/tcl.m4:
+ * win/configure.in:
+ * win/configure: (autoconf-2.59)
-2008-07-24 Andreas Kupries <andreask@activestate.com>
+2010-12-12 Stuart Cassoff <stwo@users.sourceforge.net>
- * tests/info.test: Tests 38.* added, exactly testing the tracking
- of location for uplevel scripts.
+ * unix/tcl.m4: Better building on OpenBSD.
+ * unix/configure: (autoconf-2.59)
-2008-07-23 Andreas Kupries <andreask@activestate.com>
+2010-12-10 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
- * generic/tclBasic.c: Modified TclArgumentGet to reject pure lists
- * generic/tclCmdIL.c: immediately, without search. Reworked setup
- * generic/tclCompile.c: of eoFramePtr, doesn't need the line
- * tests/info.test: information, more sensible to have everything
- on line 1 when eval'ing a pure list. Updated the users of the line
- information to special case this based on the frame type (i.e.
- TCL_LOCATION_EVAL_LIST). Added a testcase demonstrating the new
- behaviour.
+ * generic/tclIO.c: [backport] Make sure [fcopy -size ... -command ...] always
+ * tests/io.test: calls the callback asynchronously, even for size zero.
-2008-07-22 Andreas Kupries <andreask@activestate.com>
+2010-12-03 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/tclBasic.c: Added missing function comments.
+ * generic/tclUtil.c (TclReToGlob): add extra check for multiple
+ inner *s that leads to poor recursive glob matching, defer to
+ original RE instead. tclbench RE var backtrack.
- * generic/tclCompile.c: Made the new TclEnterCmdWordIndex
- * generic/tclCompile.h: static.
+2010-12-01 Kevin B. Kenny <kennykb@acm.org>
- * generic/tclBasic.c: Reworked the handling of bytecode literals
- * generic/tclCompile.c: for #280 to fix the abysmal performance
- * generic/tclCompile.h: for deep recursion, replaced the linear
- * generic/tclExecute.c: search through the whole stack with
- * generic/tclInt.h: another hashtable and simplified the data
- structure used by the compiler (array instead of hashtable).
- Incidentially this also fixes the memory leak reported via [Bug
- 2024937].
+ * generic/tclStrToD.c (SetPrecisionLimits, TclDoubleDigits):
+ Added meaningless initialization of 'i', 'ilim' and 'ilim1'
+ to silence warnings from the C compiler about possible use of
+ uninitialized variables, Added a panic to the 'switch' that
+ assigns them, to assert that the 'default' case is impossible.
+ [Bug 3124675]
-2008-07-21 Andreas Kupries <andreask@activestate.com>
+2010-11-30 Andreas Kupries <andreask@activestate.com>
- * generic/tclBasic.c: Extended the existing TIP #280 system (info
- * generic/tclCmdAH.c: frame), added the ability to track the
- * generic/tclCompCmds.c: absolute location of literal procedure
- * generic/tclCompile.c: arguments, and making this information
- * generic/tclCompile.h: available to uplevel, eval, and
- * generic/tclInterp.c: siblings. This allows proper tracking of
- * generic/tclInt.h: absolute location through custom (Tcl-coded)
- * generic/tclNamesp.c: control structures based on uplevel, etc.
- * generic/tclProc.c:
+ * generic/tclInt.decls: Backport of Kevin B. Kenny's work on
+ * generic/tclInt.h: the Tcl Head, with help from Jeff Hobbs.
+ * generic/tclStrToD.c:
+ * generic/tclTest.c:
+ * generic/tclTomMath.decls:
+ * generic/tclUtil.c:
+ * tests/util.test:
+ * unix/Makefile.in:
+ * win/Makefile.in:
+ * win/makefile.vc: Rewrite of Tcl_PrintDouble and TclDoubleDigits
+ that (a) fixes a severe performance problem with floating point
+ shimmering reported by Karl Lehenbauer, (b) allows TclDoubleDigits
+ to generate the digit strings for 'e' and 'f' format, so that it
+ can be used for tcl_precision != 0 (and possibly later for [format]),
+ (c) fixes [Bug 3120139] by making TclPrintDouble inherently
+ locale-independent, (d) adds test cases to util.test for
+ correct rounding in difficult cases of TclDoubleDigits where fixed-
+ precision results are requested. (e) adds test cases to util.test for
+ the controversial aspects of [Bug 3105247]. As a side effect, two
+ more modules from libtommath (bn_mp_set_int.c and bn_mp_init_set_int.c)
+ are brought into the build, since the new code uses them.
-2008-07-07 Andreas Kupries <andreask@activestate.com>
+ * generic/tclIntDecls.h:
+ * generic/tclStubInit.c:
+ * generic/tclTomMathDecls.h: Regenerated.
- * generic/tclCmdIL.c (InfoFrameCmd): Fixed unsafe idiom of setting
- the interp result found by Don Porter.
+2010-11-30 Jeff Hobbs <jeffh@ActiveState.com>
-2008-07-04 Joe English <jenglish@users.sourceforge.net>
+ * generic/tclInt.decls, generic/tclInt.h, generic/tclIntDecls.h:
+ * generic/tclStubInit.c: TclFormatInt restored at slot 24
+ * generic/tclUtil.c (TclFormatInt): restore TclFormatInt func from
+ 2005-07-05 macro-ization. Benchmarks indicate it is faster, as a
+ key int->string routine (e.g. int-indexed arrays).
- * generic/tclEncoding.c(UtfToUtfProc): Avoid unwanted sign extension
- when converting incomplete UTF-8 sequences. See [Bug 1908443] for
- details.
+2010-11-23 Andreas Kupries <andreask@activestate.com>
-2008-07-03 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclVar.c (VarHashInvalidateEntry): Removed obsolete
+ patch for AIX defining this macro as function. This is not
+ necessary anymore. See ChangeLog entry 2010-07-28 (Bug 3037525)
+ for the actual bug and fix the patch was a workaround for.
- * library/package.tcl: Removed [file readable] testing from
- [tclPkgUnknown] and friends. We find out soon enough whether a
- file is readable when we try to [source] it, and not testing
- before allows us to workaround the bugs on some common filesystems
- where [file readable] lies to us. [Patch 1969717]
+2010-11-19 Jan Nijtmans <nijtmans@users.sf.net>
-2008-06-28 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclInterp.c: fix gcc warning: passing argument 3 of
+ 'Tcl_GetIndexFromObj' discards qualifiers from pointer target type
+ * generic/tclWinInit.c: fix gcc warning: dereferencing pointer
+ 'oemId' does break strict-aliasing rules
+ * win/tclWin32Dll.c: fix gcc warnings: unused variable 'registration'
+ * win/tclWinChan.c:
+ * win/tclWinFCmd.c:
+ * win/configure.in: Allow cross-compilation by default. (backported)
+ * win/tcl.m4: Use -pipe for gcc on win32 (backported)
+ * win/configure: (regenerated)
- * generic/tclIOUtil.c: Plug memory leak in latest commit. Thanks
- Rolf Ade for detecting and Dan Steffen for the fix [Bug 2004654].
+2010-11-18 Donal K. Fellows <dkf@users.sf.net>
-2008-06-23 Don Porter <dgp@users.sourceforge.net>
+ * doc/file.n: [Bug 3111298]: Typofix.
- * generic/tclIOUtil.c: Fixed bug in Tcl_GetTranslatedPath() when
- operating on the "Special path" variant of the "path" Tcl_ObjType
- intrep. A full normalization was getting done, in particular, coercing
- relative paths to absolute, contrary to what the function of
- producing the "translated path" is supposed to do. [Bug 1972879].
+2010-11-16 Jan Nijtmans <nijtmans@users.sf.net>
-2008-06-20 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclPlatDecls.h: [Bug 3110161]: Extensions using TCHAR don't
+ compile on VS2005 SP1
- * tests/binary.test: Corrected flawed tests revealed by a -debug 1
- * tests/io.test: -singleproc 1 test suite run.
+2010-11-15 Andreas Kupries <andreask@activestate.com>
-2008-06-18 Don Porter <dgp@users.sourceforge.net>
+ * doc/interp.n: [Bug 3081184]: TIP #378 backport.
+ * doc/tclvars.n: Performance fix for TIP #280.
+ * generic/tclBasic.c:
+ * generic/tclExecute.c:
+ * generic/tclInt.h:
+ * generic/tclInterp.c:
+ * tests/info.test:
+ * tests/interp.test:
- * generic/tclParseExpr.c: Disabled attempts to support [expr]
- functions named eq(...) or ne(...). Any attempts to use such
- functions were panicking. [Bug 1971879].
+2010-11-03 Kevin B. Kenny <kennykb@acm.org>
-2008-06-16 Andreas Kupries <andreask@activestate.com>
+ * generic/tclCompCmds.c (TclCompileCatchCmd):
+ * tests/compile.test (compile-3.6): [Bug 3098302]: Reworked the
+ compilation of the [catch] command so as to avoid placing any code
+ that might throw an exception (specifically, any initial substitutions
+ or any stores to result or options variables) between the BEGIN_CATCH
+ and END_CATCH but outside the exception range. Added a test case that
+ panics on a stack smash if the change is not made.
- * generic/tclCmdIL.c (InfoFrameCmd): Backport of fix made on the
- * tests/info.test: head branch :: Moved the code looking up the
- information for key 'proc' out of the TCL_LOCATION_BC branch to
- after the switch, this is common to all frame types. Updated the
- testsuite to match. This was exposed by the 2008-06-08 commit
- (Miguel), switching uplevel from direct eval to compilation. Fixes
- [Bug 1987851].
+2010-11-01 Stuart Cassoff <stwo@users.sourceforge.net>
-2008-06-12 Andreas Kupries <andreask@activestate.com>
+ * library/safe.tcl: Improved handling of non-standard module
+ * tests/safe.test: path lists, empty path lists in particular.
- * generic/tclCmdIL.c (InfoFrameCmd): TIP #280 conditional
- feature. Added checks to validate HashEntry and HashTable
- information gotten from Command structures. This seems to be
- needed to handle structures managed by Itcl.
+2010-11-01 Kevin B. Kenny <kennykb@acm.org>
-2008-06-12 Daniel Steffen <das@users.sourceforge.net>
+ * library/tzdata/Asia/Hong_Kong:
+ * library/tzdata/Pacific/Apia:
+ * library/tzdata/Pacific/Fiji: Olson's tzdata2010o.
- * unix/Makefile.in: add complete deps on tclDTrace.h.
+2010-10-23 Jan Nijtmans <nijtmans@users.sf.net>
- * unix/Makefile.in: clean generated tclDTrace.h file.
- * unix/configure.in (SunOS): fix static DTrace-enabled build.
+ * tools/uniParse.tcl: [Bug 3085863]: tclUniData 9 years old
+ * tools/uniClass.tcl: Upgrade everything to Unicode 6.0, except
+ * tests/utf.test: non-BMP characters > 0xFFFF
+ * generic/tclUniData.c: (re-generated)
+ * generic/regc_locale.c:(re-generated)
+ * generic/regcomp.c: fix comment
+ * win/rules.vc Update for VS10
- * unix/tcl.m4 (SunOS-5.11): fix 64bit amd64 support with gcc & Sun cc.
- * unix/configure: autoconf-2.13
+2010-10-09 Miguel Sofer <msofer@users.sf.net>
-2008-05-26 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclExecute.c: fix overallocation of exec stack in TEBC
+ (mixing numwords and numbytes)
- * tests/io.test (io-53.9): need to close chan before removing file.
+2010-10-01 Jeff Hobbs <jeffh@ActiveState.com>
-2008-05-23 Andreas Kupries <andreask@activestate.com>
+ * generic/tclExecute.c (EvalStatsCmd): change 'evalstats' to
+ return data to interp by default, or if given an arg, use that as
+ filename to output to (accepts 'stdout' and 'stderr').
+ Fix output to print used inst count data.
+ * generic/tclCkalloc.c: change TclDumpMemoryInfo sig to allow
+ * generic/tclInt.decls: objPtr as well as FILE* as output.
+ * generic/tclIntDecls.h:
- * win/tclWinChan.c (FileWideSeekProc): Accepted a patch by
- Alexandre Ferrieux <ferrieux@users.sourceforge.net> to fix the
- [Bug 1965787]. 'tell' now works for locations > 2 GB as well
- instead of going negative.
+2010-09-24 Andreas Kupries <andreask@activestate.com>
- * generic/tclIO.c (Tcl_SetChannelBufferSize): Accepted a patch by
- * tests/io.test: Alexandre Ferrieux <ferrieux@users.sourceforge.net>
- to fix the [Bug 1969953]. Buffersize outside of the supported
- range are now clipped to nearest boundary instead of ignored.
+ * tclWinsock.c: [Bug 3056775]: Fixed race condition between thread
+ and internal co-thread access of a socket's structure because of
+ the thread not using the socketListLock in TcpAccept(). Added
+ documentation on how the module works to the top.
-2008-04-26 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+2010-09-23 Don Porter <dgp@users.sourceforge.net>
- * generic/tclAsync.c: Tcl_AsyncDelete(): panic if attempt
- to locate handler token fails. Happens when some other
- thread attempts to delete somebody else's token.
+ * generic/tclCmdAH.c: Fix cases where value returned by
+ * generic/tclEvent.c: Tcl_GetReturnOptions() was leaked.
+ * generic/tclMain.c: Thanks to Jeff Hobbs for discovery of the
+ anti-pattern to seek and destroy.
- Also, panic early if we find out the wrong thread attempting
- to delete the async handler (common trap). As, only the one
- that created the handler is allowed to delete it.
+2010-09-19 Donal K. Fellows <dkf@users.sf.net>
-2008-04-17 Andreas Kupries <andreask@activestate.com>
+ * doc/file.n (file readlink): [Bug 3070580]: Typofix.
- *** 8.4.19 TAGGED FOR RELEASE ***
+2010-09-10 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclCompExpr.c (CompileMathFuncCall): Added
- * tests/compExpr.test (compExpr-5.10): Tcl_ResetResult before
- appending error message, to clear out possible sharing. Added test
- case demonstrating the crash (abort on shared object) without the
- fix.
+ * doc/regsub.n: [Bug 3063568]: Fix for gotcha in example due to Tcl's
+ special handling of backslash-newline. Makes example slightly less
+ pure, but more useful.
-2008-04-15 Andreas Kupries <andreask@activestate.com>
+2010-09-08 Andreas Kupries <andreask@activestate.com>
- * generic/tclIO.c (CopyData): Applied another patch by Alexandre
- * io.test (io-53.8a): Ferrieux <ferrieux@users.sourceforge.net>,
- to shift EOF handling to the async part of the command if a
- callback is specified, should the channel be at EOF already when
- fcopy is called. Testcase by myself.
+ *** 8.5.9 TAGGED FOR RELEASE ***
-2008-04-14 Kevin B. Kenny <kennykb@acm.org>
+ * doc/tm.n: Added underscore to the set of characters accepted in
+ module names. This is true for quite some time in the code, this
+ change catches up the documentation.
- * unix/tclUnixTime.c (TclpGetClicks, Tcl_GetTime): Removed
- obsolete use of 'struct timezone' in the call to 'gettimeofday'.
- [Bug 1942197].
-
-2008-04-14 Don Porter <dgp@users.sourceforge.net>
+2010-09-08 Don Porter <dgp@users.sourceforge.net>
- * generic/tclExecute.c: Plug memory leak introduced in the
- 2008-03-07 commit. [Bug 1940433]
+ * changes: Update for 8.5.9 release.
-2008-04-11 Don Porter <dgp@users.sourceforge.net>
+ * win/tclWin32Dll.c: #ifdef protections to permit builds with
+ * win/tclWinChan.c: mingw on amd64 systems. Thanks to "mescalinum"
+ * win/tclWinFCmd.c: for reporting and testing.
- * README: Bump version number to 8.4.19
- * generic/tcl.h:
- * tools/tcl.wse.in:
- * unix/configure.in:
- * unix/tcl.spec:
- * win/README.binary:
- * win/configure.in:
+2010-09-06 Stuart Cassoff <stwo@users.sourceforge.net>
- * unix/configure: autoconf-2.13
- * win/configure:
+ * unix/configure.in, generic/tclIOUtil.c (Tcl_Stat): Updated so that
+ we do not assume that all unix systems have the POSIX blkcnt_t type,
+ since OpenBSD apparently does not. Backported from HEAD (2010-02-16).
+ * unix/configure: autoconf-2.59
- * changes: updates for 8.4.19 release.
+2010-09-02 Andreas Kupries <andreask@activestate.com>
-2008-04-10 Andreas Kupries <andreask@activestate.com>
+ * doc/glob.n: Fixed documentation ambiguity regarding the handling
+ of -join.
- * generic/tclIOCmd.c (Tcl_FcopyObjCmd): Keeping check for negative
- values, changed to not be an error, but behave like the special
- value -1 (copy all, default).
+ * library/safe.tcl (::safe::AliasGlob): Fixed another problem, the
+ option -join does not stop option processing in the core builtin,
+ so the emulation must not do that either.
- * tests/iocmd.test (iocmd-15.{12,13}): Removed.
+2010-09-01 Andreas Kupries <andreas_kupries@users.sourceforge.net>
- * tests/io.test (io-52.5{,a,b}): Reverted last change, added
- comment regarding the meaning of -1, added two more testcases for
- other negative values, and input wrapped to negative.
+ * library/safe.tcl (::safe::AliasGlob): Moved the command
+ extending the actual glob command with a -directory flag to when
+ we actually have a proper untranslated path,
-2008-04-09 Andreas Kupries <andreask@activestate.com>
+2010-09-01 Don Porter <dgp@users.sourceforge.net>
- * tests/io.test (io-52.5): Removed '-size -1' from test, does not
- seem to have any bearing, and was an illegal value. Test case is
- not affected by the value of -size, test flag restoration and that
- everything was properly copied.
+ * changes: Update for 8.5.9 release.
- * generic/tclIOCmd.c (Tcl_FcopyObjCmd): Added checking of -size
- * tests/ioCmd.test (iocmd-15.{13,14}): value to reject negative
- values, and values overflowing 32-bit signed. [Bug 1557855]. Basic
- patch by Alexandre Ferrieux <ferrieux@users.sourceforge.net>, with
- modifications from me to separate overflow from true negative
- value. Extended testsuite.
+2010-09-01 Andreas Kupries <andreask@activestate.com>
-2008-04-08 Andreas Kupries <andreask@activestate.com>
+ * generic/tclExecute.c: [Bug 3057639]. Applied patch by Jeff to
+ * generic/tclVar.c: make the behaviour of lappend in bytecompiled
+ * tests/append.test: mode consistent with direct-eval and 'append'
+ * tests/appendComp.test: generally. Added tests (append*-9.*)
+ showing the difference.
+ ***POTENTIAL INCOMPATIBILITY***
- * tests/io.test (io-53.8,53.9,53.10): Backported das' fix of typo
- and quoting for spaces in builddir path.
-
-2008-04-07 Andreas Kupries <andreask@activestate.com>
+2010-09-01 Donal K. Fellows <dkf@users.sf.net>
- * tests/io.test (io-53.10): Testcase for bi-directionaly fcopy.
- * generic/tclIO.c: Additional changes to data structures for fcopy
- * generic/tclIO.h: and channels to perform proper cleanup in case
- of a channel having two background copy operations running as is
- now possible.
+ * tools/tcltk-man2html.tcl: Improve handling of cross-links for
+ options between Ttk manual pages.
- * generic/tclIO.c (BUSY_STATE, CheckChannelErrors,
- TclCopyChannel): New macro, and the places using it. This change
- allows for bi-directional fcopy on channels. [Bug 1350564].
- Thanks to Alexandre Ferrieux <ferrieux@users.sourceforge.net>
- for the patch.
+ * doc/Tcl.n: Avoid nroff hazards when generating documentation.
- * tests/io.test (io-53.9): Made test cleanup robust against the
- possibility of slow process shutdown on Windows. Backported from
- Kevin Kenny's change to the same test on the 8.5 and head
- branches.
+2010-08-31 Andreas Kupries <andreask@activestate.com>
-2008-04-04 Andreas Kupries <andreask@activestate.com>
+ * win/tcl.m4: Applied patch by Jeff fixing issues with the
+ manifest handling on Win64.
+ * win/configure: Regenerated.
- * tests/io.test (io-53.9): Added testcase for [Bug 780533], based
- on Alexandre's test script. Also fixed problem with timer in
- preceding test, was not canceled properly in the ok case.
+2010-08-29 Donal K. Fellows <dkf@users.sf.net>
-2008-04-03 Andreas Kupries <andreask@activestate.com>
+ * doc/dict.n: [Bug 3046999]: Corrected cross reference to array
+ manpage to refer to (correct) existing subcommand.
- * generic/tclIO.c (CopyData): Applied patch [Bug 1932639] to
- * tests/io.test: prevent fcopy from calling -command synchronously
- the first time. Thanks to Alexandre Ferrieux
- <ferrieux@users.sourceforge.net> for report and patch.
+2010-08-26 Jeff Hobbs <jeffh@ActiveState.com>
-2008-04-02 Andreas Kupries <andreask@activestate.com>
+ * unix/configure, unix/tcl.m4: SHLIB_LD_LIBS='${LIBS}' for OSF1-V*.
+ Add /usr/lib64 to set of auto-search dirs. [Bug 1230554]
+ (SC_PATH_X): Correct syntax error when xincludes not found.
- * generic/tclIO.c (CopyData): Applied patch for the fcopy problem
- [Bug 780533], with many thanks to Alexandre Ferrieux
- <ferrieux@users.sourceforge.net> for tracking it down and
- providing a solution. Still have to convert his test script into
- a proper test case.
+ * win/Makefile.in (VC_MANIFEST_EMBED_DLL VC_MANIFEST_EMBED_EXE):
+ * win/configure, win/configure.in, win/tcl.m4: SC_EMBED_MANIFEST
+ macro and --enable-embedded-manifest configure arg added to
+ support manifest embedding where we know the magic. Help prevents
+ DLL hell with MSVC8+.
-2008-03-27 Daniel Steffen <das@users.sourceforge.net>
+2010-08-24 Don Porter <dgp@users.sourceforge.net>
- * unix/tcl.m4 (SunOS-5.1x): fix 64bit support for Sun cc. [Bug 1921166]
+ * changes: Update for 8.5.9 release.
- * unix/dltest/Makefile.in: support use of LDFLAGS in SHLIB_LD.
+2010-08-23 Kevin B. Kenny <kennykb@acm.org>
- * unix/configure: autoconf-2.13
+ * library/tzdata/Africa/Cairo:
+ * library/tzdata/Asia/Gaza: Olson's tzdata2010l.
-2008-03-24 Pat Thoyts <patthoyts@users.sourceforge.net>
+2010-08-19 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclBinary.c: bug #1923966 - crash in binary format
- * tests/binary.test: Added tests for the above crash condition.
+ * generic/tclTrace.c (TraceExecutionObjCmd, TraceCommandObjCmd)
+ (TraceVariableObjCmd): [Patch 3048354]: Use memcpy() instead of
+ strcpy() to avoid buffer overflow; we have the correct length of data
+ to copy anyway since we've just allocated the target buffer.
-2008-03-11 Daniel Steffen <das@users.sourceforge.net>
+2010-08-15 Donal K. Fellows <dkf@users.sf.net>
- * macosx/tclMacOSXNotify.c: avoid using CoreFoundation after fork() on
- Darwin 9 even when TclpCreateProcess() uses vfork().
+ * generic/tclProc.c (ProcWrongNumArgs): [Bug 3045010]: Make the
+ handling of passing the wrong number of arguments to [apply] somewhat
+ less verbose when a lambda term is present.
-2008-03-07 Don Porter <dgp@users.sourceforge.net>
+2010-08-12 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclExecute.c (Tcl_ExprObj): Revised expression bytecode
- compiling so that bytecodes invalid due to changing context or due
- to the difference between expressions and scripts are not reused.
- [Bug 1899164].
+ * generic/tclCmdMZ.c (Tcl_RegexpObjCmd): [Bug 2826551, Patch 2948425]:
+ Backport of updates to make handling of RE line anchors correct.
- * generic/tclTest.c: Backport the [testexprlongobj] testing command.
+2010-08-11 Jeff Hobbs <jeffh@ActiveState.com>
- * tests/execute.test (execute-6.8): Added tests checking that
- bytecode is invalidates in the right situations.
+ * unix/ldAix: Remove ancient (pre-4.2) AIX support
+ * unix/configure: regen with ac-2.59
+ * unix/configure.in, unix/tclConfig.sh.in, unix/Makefile.in:
+ * unix/tcl.m4 (AIX): Remove the need for ldAIX, replace with
+ -bexpall/-brtl. Remove TCL_EXP_FILE (export file) and other baggage
+ that went with it. Remove pre-4 AIX build support.
-2008-03-03 Reinhard Max <max@suse.de>
+2010-08-10 Jeff Hobbs <jeffh@ActiveState.com>
- * unix/tclUnixChan.c: Fix mark and space parity on Linux, which
- uses CMSPAR instead of PAREXT.
+ * generic/tclUtil.c (TclByteArrayMatch): Patterns may not be
+ null-terminated, so account for that.
-2008-02-27 Pat Thoyts <patthoyts@users.sourceforge.net>
+2010-08-05 Don Porter <dgp@users.sourceforge.net>
- * library/http/pkgIndex.tcl: Backported 2.5.5 changes from
- * library/http/http.tcl: 8.5 version.
- * doc/http.n: Document the meta accessor.
+ * changes: Update for 8.5.9 release.
-2008-02-26 Jeff Hobbs <jeffh@ActiveState.com>
+2010-08-04 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/tclIOCmd.c (Tcl_GetsObjCmd): do not reuse resultObj as
- it may be shared (crash condition).
+ * unix/tclUnixFCmd.c: Adjust license header as per
+ ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
-2008-02-22 Pat Thoyts <patthoyts@users.sourceforge.net>
+ * license.terms: Fix DFARs note for number-adjusted rights clause
- * library/http/pkgIndex.tcl: Set version 2.5.4
- * library/http/http.tcl: Fix for bug #1818565. Always check that
- the state array exists in the http::status command.
+ * win/tclWin32Dll.c (asciiProcs, unicodeProcs):
+ * win/tclWinLoad.c (TclpDlopen): 'load' use LoadLibraryEx with
+ * win/tclWinInt.h (TclWinProcs): LOAD_WITH_ALTERED_SEARCH_PATH to
+ prefer dependent DLLs in same dir as loaded DLL.
+ ***POTENTIAL INCOMPATIBILITY***
-2008-02-06 Don Porter <dgp@users.sourceforge.net>
+ * win/Makefile.in (%.${OBJEXT}): better implicit rules support
- *** 8.4.18 TAGGED FOR RELEASE ***
+2010-08-04 Don Porter <dgp@users.sourceforge.net>
- * README: Bump version number to 8.4.18
- * generic/tcl.h:
+ * generic/tcl.h: Bump to 8.5.9 for release.
+ * library/init.tcl:
* tools/tcl.wse.in:
* unix/configure.in:
* unix/tcl.spec:
- * win/README.binary:
* win/configure.in:
+ * README:
- * unix/configure: autoconf-2.13
+ * unix/configure: autoconf-2.59
* win/configure:
- * changes: updates for 8.4.18 release.
-
-2008-02-02 Daniel Steffen <das@users.sourceforge.net>
-
- * unix/configure.in (Darwin): correct Info.plist year substitution in
- non-framework builds.
-
- * unix/configure: autoconf-2.13
-
-2008-01-30 Miguel Sofer <msofer@users.sf.net>
-
- * generic/tclInterp.c (Tcl_GetAlias): fix for [Bug 1882373]
-
-2008-01-13 Jeff Hobbs <jeffh@ActiveState.com>
-
- * win/tclWinSerial.c (SerialCloseProc, TclWinOpenSerialChannel):
- use critical section for read & write side. [Bug 1353846] (newman)
-
-2007-12-31 Don Porter <dgp@users.sourceforge.net>
-
- *** 8.4.17 TAGGED FOR RELEASE ***
-
- * changes: updates for 8.4.17 release.
- * doc/filename.n: Typo
-
-2007-12-18 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
-
- * generic/regguts.h, generic/regc_color.c, generic/regc_nfa.c:
- Fixes for problems created when processing regular expressions that
- generate very large automata. An enormous number of thanks to Will
- Drewry <wad@google.com>, Tavis Ormandy <taviso@google.com>, and Tom
- Lane <tgl@sss.pgh.pa.us> from the Postgresql crowd for their help in
- tracking these problems down. [Bug 1810264]
-
-2007-12-14 Jeff Hobbs <jeffh@ActiveState.com>
+ * changes: Update for 8.5.9 release.
- * win/README: updated notes
-
-2007-12-14 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
-
- * unix/tclUnixCompat.c (TclpGetHostByName): Really applied
- the change noted on 2007-11-13 by dkf below.
+2010-08-04 Andreas Kupries <andreask@activestate.com>
-2007-12-13 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclIORChan.c: [Bug 3034840]: Fixed reference counting
+ * tests/ioCmd.test: in InvokeTclMethod and callers.
- * generic/tclIOUtil.c (TclGetOpenMode): Only set the O_APPEND flag
- * tests/ioUtil.test (ioUtil-4.1): on a channel for the 'a'
- mode and not for 'a+'. [Bug 1773127] (backport from HEAD)
+2010-08-03 Andreas Kupries <andreask@activestate.com>
-2007-12-05 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * tests/var.test (var-19.1): [Bug 3037525]: Added test demonstrating
+ the local hashtable deletion crash and fix.
- * generic/tclCmdIL.c (Tcl_LsearchObjCmd): Prevent shimmering crash
- when -exact and -integer/-real are mixed. [Bug 1844789]
+ * tests/info.test (info-39.1, test_info_frame): Changed absolute to
+ relative frame adressing to handle difference between testing with
+ -singleproc 1 vs. the default -singleproc 0. Plus comment fix. The
+ test and issue are not relevant to the trunk, forward porting is not
+ required.
-2007-11-28 Jeff Hobbs <jeffh@ActiveState.com>
+2010-08-03 Don Porter <dgp@users.sourceforge.net>
- * win/tclWinSock.c (Tcl_GetHostName): update to previous fix to
- set hostname length appropriately, clean up check overall.
+ * changes: Update for 8.5.9 release.
-2007-11-27 Don Porter <dgp@users.sourceforge.net>
+2010-08-02 Kevin B. Kenny <kennykb@users.sf.net>
- * win/tclWinSock.c: Add missing encoding conversion of the
- [info hostname] value from the system encoding to Tcl's internal
- encoding. This is important now that ICANN no longer limits host
- names to ASCII. [Bug 1823552]
+ * library/tzdata/America/Bahia_Banderas:
+ * library/tzdata/Pacific/Chuuk:
+ * library/tzdata/Pacific/Pohnpei:
+ * library/tzdata/Africa/Cairo:
+ * library/tzdata/Europe/Helsinki:
+ * library/tzdata/Pacific/Ponape:
+ * library/tzdata/Pacific/Truk:
+ * library/tzdata/Pacific/Yap: Olson's tzdata2010k.
-2007-11-26 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+2010-07-28 Miguel Sofer <msofer@users.sf.net>
- * generic/tclThread.c: Back-port locking changes from Tcl8.5
- in Tcl_Mutex/ConditionFinlize. Now we properly master-lock
- the finalization of sync primitives.
+ * generic/tclVar.c: [Bug 3037525]: lose fickle optimisation in
+ TclDeleteVars (used for runtime-created locals) that caused crashes.
-2007-11-15 Don Porter <dgp@users.sourceforge.net>
+2010-07-25 Jan Nijtmans <nijtmans@users.sf.net>
- * generic/regc_nfa.c: Fixed infinite loop in the regexp compiler
- * generic/regcomp.c: [Bug 1810038]. Corrected looping logic in
- * tests/regexp.test: fixempties() to avoid wasting time walking a
- list of dead states [Bug 1832612]. Convert optst() from expensive
- no-op to a cheap no-op. Improve newline usage in debug output.
+ * generic/tclInt.h: [Bug 3030870]: Make itcl 3.x built with pre-8.6
+ * generic/tclBasic.c: work in 8.6 revert tclInt.h to what it was
+ before, and relax the relation between Tcl_CallFrame and CallFrame.
-2007-11-13 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+2010-07-17 Jan Nijtmans <nijtmans@users.sf.net>
- * unix/tclUnixCompat.c (TclpGetHostByName): The six-argument form of
- getaddressbyname_r() uses the fifth argument to indicate whether the
- lookup succeeded or not on at least one platform. [Bug 1618235]
+ * generic/tcl.h: [Bug 3030870]: Make itcl 3.x built with pre-8.6
+ * generic/tclInt.h: work in 8.6
-2007-10-30 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+2010-07-02 Donal K. Fellows <dkf@users.sf.net>
- * generic/regc_lex.c (lexescape): Ensure that backreference numbers
- can't overflow a signed int in a way that breaks things. [Bug 1810264]
+ * generic/tclExecute.c (IllegalExprOperandType): [Bug 3024379]: Made
+ sure that errors caused by an argument to an operator being outside
+ the domain of the operator all result in ::errorCode being ARITH
+ DOMAIN and not NONE.
-2007-10-15 Miguel Sofer <msofer@users.sf.net>
+2010-07-02 Jan Nijtmans <nijtmans@users.sf.net>
- * generic/tclParse.c (Tcl_ParseBraces): fix for possible read
- after the end of buffer, [Bug 1813528] (Joe Mistachkin).
+ * generic/tclIntDecls.h: [Bug 803489]: Tcl_FindNamespace problem in
+ the Stubs table.
-2007-10-03 Miguel Sofer <msofer@users.sf.net>
+2010-07-01 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclObj.c (Tcl_FindCommandFromObj): fix finding a deleted
- command; cannot trigger this from Tcl itself, but crash reported
- on xotcl. This check is new to 8.4 but exists in 8.5, so this is a
- backport or something. Thanks Gustaf Neumann.
+ * doc/mathop.n: [Bug 3023165]: Fix typo that was preventing proper
+ rendering of the exclusive-or operator.
-2007-10-02 Jeff Hobbs <jeffh@ActiveState.com>
-
- * generic/tcl.h (Tcl_DecrRefCount): Update change from 2006-05-29
- to make macro more warning-robust in unbraced if code.
+2010-06-28 Jan Nijtmans <nijtmans@users.sf.net>
-2007-10-02 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclPosixStr.c: [Bug 3019634]: errno.h and tclWinPort.h have
+ conflicting definitions.
- * README: Bump version number to 8.4.17
- * generic/tcl.h:
- * tools/tcl.wse.in:
- * unix/configure.in:
- * unix/tcl.spec:
- * win/README.binary:
- * win/configure.in:
+2010-06-22 Donal K. Fellows <dkf@users.sf.net>
- * unix/configure: autoconf-2.13
- * win/configure:
+ * generic/tclCmdIL.c (Tcl_LsetObjCmd): [Bug 3019351]: Corrected wrong
+ args message.
-2007-09-20 Don Porter <dgp@users.sourceforge.net>
+2010-06-18 Donal K. Fellows <dkf@users.sf.net>
- *** 8.4.16 TAGGED FOR RELEASE ***
+ * library/init.tcl (auto_execok): [Bug 3017997]: Add .cmd to the
+ default list of extensions that we can execute interactively.
- * doc/load.n: Backport corrected example.
+2010-06-16 Jan Nijtmans <nijtmans@users.sf.net>
-2007-09-19 Don Porter <dgp@users.sourceforge.net>
+ * tools/loadICU.tcl: [Bug 3016135]: Traceback using clock format
+ * library/msgs/he.msg: with locale of he_IL
- * unix/Makefile.in: Update `make dist` so that tclDTrace.d is
- included in the source code distribution.
-
- * generic/tclPkg.c: Backport fix for [1573844] to the
- * tests/pkg.test: TCL_TIP268 sections.
+2010-06-09 Andreas Kupries <andreask@activestate.com>
-2007-09-18 Don Porter <dgp@users.sourceforge.net>
+ * library/platform/platform.tcl: Added OSX Intel 64bit
+ * library/platform/pkgIndex.tcl: Package updated to version 1.0.9.
+ * unix/Makefile.in:
+ * win/Makefile.in:
- * changes: updates for 8.4.16 release.
+2010-05-26 Donal K. Fellows <dkf@users.sf.net>
-2007-09-15 Daniel Steffen <das@users.sourceforge.net>
+ * doc/socket.n: [Bug 3007442]: Server sockets never took a host
+ argument, so the list of options must precede the port argument.
- * unix/tcl.m4 (SunOS-5.1x): replace direct use of '/usr/ccs/bin/ld'
- in SHLIB_LD by 'cc' compiler driver.
- * unix/configure: autoconf-2.13
+2010-05-25 Jan Nijtmans <nijtmans@users.sf.net>
-2007-09-14 Daniel Steffen <das@users.sourceforge.net>
+ * unix/tclUnixPort.h: [Bug 2991415]: tclport.h #included before
+ * win/tclWinPort.h: limits.h
+ * generic/tclInt.h:
- * generic/tclDTrace.d (new file): add DTrace provider for Tcl; allows
- * generic/tclCompile.h: tracing of proc and command entry &
- * generic/tclBasic.c: return, bytecode execution, object
- * generic/tclExecute.c: allocation and more; with essentially
- * generic/tclInt.h: zero cost when tracing is inactive;
- * generic/tclObj.c: enable with --enable-dtrace configure
- * generic/tclProc.c: arg (disabled by default, will only
- * unix/Makefile.in: enable if DTrace is present).
- * unix/configure.in: [Patch 1793984]
+2010-05-21 Jan Nijtmans <nijtmans@users.sf.net>
- * macosx/Makefile: enable DTrace support.
+ * tools/installData.tcl: Make sure that copyDir only receives
+ normalized paths. Backported from trunk.
+ * generic/tclPlatDecls.h: Fix <tchar.h> inclusion for CYGWIN.
+ Backported from trunk (although for trunk this was moved to
+ tclWinPort.h)
+ * generic/tclPathObj.c: Fix Tcl_SetStringObj usage for CYGWIN. This
+ function can only be used with unshared objects. This causes a crash
+ on CYGWIN. (backported from trunk)
+ * generic/tclFileName.c: Don't declare cygwin_conv_to_win32_path here
+ * win/tclWinChan.c: Fix various minor other gcc warnings, like
+ * win/tclWinConsole.c: signed<->unsigned mismatch. Backported from
+ * win/tclWinDde.c: trunk.
+ * win/tclWinNotify.c:
+ * generic/tclStrToD.c: [Bug 3005233]: fix for build on OpenBSD vax
- * unix/configure: autoconf-2.13
+2010-05-19 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
-2007-09-11 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclDictObj.c: Backport of fix for [Bug 3004007], EIAS
+ * tests/dict.test: violation in list-dict conversions.
- * library/tcltest/tcltest.tcl: Accept underscores and colons in
- * library/tcltest/pkgIndex.tcl: constraint names. Properly handle
- constraint expressions that return non-numeric boolean results like
- "false". Bump to tcltest 2.2.9. [Bug 1772989; RFE 1071322]
+2010-05-07 Andreas Kupries <andreask@activestate.com>
-2007-09-11 Pat Thoyts <patthoyts@users.sourceforge.net>
+ * library/platform/platform.tcl: Fix cpu name for Solaris/Intel 64bit.
+ * library/platform/pkgIndex.tcl: Package updated to version 1.0.8.
+ * unix/Makefile.in:
+ * win/Makefile.in:
- * win/makefile.vc: AMD64 target fixes for symbols builds.
- * win/rules.vc:
+2010-04-30 Don Porter <dgp@users.sourceforge.net>
-2007-09-10 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclBinary.c (UpdateStringOfByteArray): [Bug 2994924]: Add
+ panic when the generated string representation would grow beyond Tcl's
+ size limits.
- * generic/tclLink.c (Tcl_UpdateLinkedVar): guard against var being
- unlinked. [Bug 1740631] (maros)
+2010-04-29 Andreas Kupries <andreask@activestate.com>
-2007-08-25 Kevin Kenny <kennykb@acm.org>
+ * library/platform/platform.tcl: Another stab at getting the /lib,
+ * library/platform/pkgIndex.tcl: /lib64 difference right for linux.
+ * unix/Makefile.in: Package updated to version 1.0.7.
+ * win/Makefile.in:
- * generic/tclClock.c (FormatClock): Claimed additional space for
- the %c format code to avoid a buffer overrun when formatting
- (for example) a Friday in February in the Portuguese locale.
- [Bug 1751117]
+2010-04-29 Kevin B. Kenny <kennykb@acm.org>
+
+ * library/tzdata/Antarctica/Macquarie:
+ * library/tzdata/Africa/Casablanca:
+ * library/tzdata/Africa/Tunis:
+ * library/tzdata/America/Santiago:
+ * library/tzdata/America/Argentina/San_Luis:
+ * library/tzdata/Antarctica/Casey:
+ * library/tzdata/Antarctica/Davis:
+ * library/tzdata/Asia/Anadyr:
+ * library/tzdata/Asia/Damascus:
+ * library/tzdata/Asia/Dhaka:
+ * library/tzdata/Asia/Gaza:
+ * library/tzdata/Asia/Kamchatka:
+ * library/tzdata/Asia/Karachi:
+ * library/tzdata/Asia/Taipei:
+ * library/tzdata/Europe/Samara:
+ * library/tzdata/Pacific/Apia:
+ * library/tzdata/Pacific/Easter:
+ * library/tzdata/Pacific/Fiji: Olson's tzdata2010i.
-2007-08-24 Miguel Sofer <msofer@users.sf.net>
-
- * generic/tclCompile.c: replaced copy loop that tripped some
- compilers with memmove [Bug 1780870]
+2010-04-19 Jan Nijtmans <nijtmans@users.sf.net>
-2007-08-14 Don Porter <dgp@users.sourceforge.net>
+ * win/tclWinPort.h: [Patch 2986105]: Conditionally defining
+ * win/tclWinFile.c: strcasecmp/strncasecmp
- * tests/trace.test: Backport some tests.
-
-2007-08-14 Daniel Steffen <das@users.sourceforge.net>
+2010-04-18 Donal K. Fellows <dkf@users.sf.net>
- * unix/tclLoadDyld.c: use dlfcn API on Mac OS X 10.4 and later; fix
- issues with loading from memory on intel and 64bit; add debug messages.
+ * doc/unset.n: [Bug 2988940]: Fix typo.
- * tests/load.test: add test load-10.1 for loading from vfs.
+2010-04-14 Andreas Kupries <andreask@activestate.com>
-2007-08-07 Daniel Steffen <das@users.sourceforge.net>
+ * library/platform/platform.tcl: Linux platform identification:
+ * library/platform/pkgIndex.tcl: Check /lib64 for existence of
+ * unix/Makefile.in: files matching libc* before accepting it as
+ * win/Makefile.in: base directory. This can happen on weirdly
+ installed 32bit systems which have an empty or partially filled
+ /lib64 without an actual libc. Bumped to version 1.0.6.
- * generic/tclEnv.c: improve environ handling on Mac OS X (adapted
- * unix/tclUnixPort.h: from Apple changes in Darwin tcl-64).
+2010-04-03 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
- * unix/Makefile.in: add support for compile flags specific to
- object files linked directly into executables.
+ * generic/tclStringObj.c: (SetStringFromAny): avoid trampling
+ over the tclEmptyStringRep as it is thread-shared.
- * unix/configure.in (Darwin): only use -seg1addr flag when prebinding;
- use -mdynamic-no-pic flag for object files linked directly into exes;
- support overriding TCL_PACKAGE_PATH in environment.
+ * generic/tclThreadStorage.c (ThreadStorageGetHashTable):
+ avoid accessing shared table index w/o mutex protection
+ if VALGRIND defined on compilation time. This rules out
+ helgrind complains about potential race-conditions at
+ that place.
- * unix/configure: autoconf-2.13
+ Thanks to Gustaf Neumann for the (hard) work.
-2007-07-19 Don Porter <dgp@users.sourceforge.net>
+2010-03-31 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclParse.c: In contexts where interp and parsePtr->interp
- might be different, be sure to use the latter for error reporting.
+ * doc/package.n: [Bug 2980210]: Document the arguments taken by
+ the [package present] command correctly.
-2007-07-05 Don Porter <dgp@users.sourceforge.net>
+2010-03-30 Andreas Kupries <andreask@activestate.com>
- * library/init.tcl (unknown): Corrected inconsistent error message
- in interactive [unknown] when empty command is invoked. [Bug 1743676]
+ * generic/tclIORChan.c (ReflectClose, ReflectInput, ReflectOutput,
+ ReflectSeekWide, ReflectWatch, ReflectBlock, ReflectSetOption,
+ ReflectGetOption, ForwardProc): [Bug 2978773]: Preserve
+ ReflectedChannel* structures across handler invokations, to avoid
+ crashes when the handler implementation induces nested callbacks
+ and destruction of the channel deep inside such a nesting.
-2007-06-30 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+2010-03-30 Don Porter <dgp@users.sourceforge.net>
- * generic/tclBinary.c (Tcl_BinaryObjCmd): De-fang an instance of the
- shared-result anti-pattern. [Bug 1716704]
+ * generic/tclObj.c (Tcl_GetCommandFromObj): [Bug 2979402]: Reorder
+ the validity tests on internal rep of a "cmdName" value to avoid
+ invalid reads reported by valgrind.
-2007-06-30 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+2010-03-29 Don Porter <dgp@users.sourceforge.net>
- * generic/tclThread.c: Prevent RemeberSyncObj() from growing the sync
- object lists by reusing already free'd slots, if possible.
- See discussion on Bug 1726873 for more information.
+ * generic/tclStringObj.c: Fix array overrun in test format-1.12
+ caught by valgrind testing.
-2007-06-29 Daniel Steffen <das@users.sourceforge.net>
+2010-03-25 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclAlloc.c: on Darwin, ensure memory allocated by
- * generic/tclThreadAlloc.c: the custom TclpAlloc()s is aligned to
- 16 byte boundaries (as is the case with the Darwin system malloc).
+ * unix/tclUnixFCmd.c (TclUnixCopyFile): [Bug 2976504]: Corrected
+ number of arguments to fstatfs() call.
-2007-06-27 Don Porter <dgp@users.sourceforge.net>
+2010-03-24 Don Porter <dgp@users.sourceforge.net>
- * generic/tclCmdMZ.c: Corrected broken trace reversal logic in
- * generic/tclTest.c: TclCheckInterpTraces that led to infinite loop
- * tests/basic.test: when multiple Tcl_CreateTrace traces were set
- and one of them did not fire due to level restrictions. [Bug 1743941].
+ * generic/tclResult.c: [Bug 2383005]: Revise [return -errorcode] so
+ * tests/result.test: that it rejects illegal non-list values.
-2007-06-23 Daniel Steffen <das@users.sourceforge.net>
+2010-03-20 Donal K. Fellows <dkf@users.sf.net>
- * macosx/tclMacOSXNotify.c (AtForkChild): don't call CoreFoundation
- APIs after fork() on systems where that would lead to an abort().
+ * generic/tclIO.c (CopyData): Allow the total number of bytes copied
+ by [fcopy] to exceed 2GB. Can happen when no -size parameter given.
-2007-06-10 Jeff Hobbs <jeffh@ActiveState.com>
+2010-03-18 Don Porter <dgp@users.sourceforge.net>
- * README: updated links. [Bug 1715081]
+ * generic/tclListObj.c: [Bug 2971669]: Prevent in overflow trouble in
+ * generic/tclTestObj.c: ListObjReplace operations. Thanks to kbk for
+ * tests/listObj.test: fix and test.
-2007-06-06 Daniel Steffen <das@users.sourceforge.net>
+2010-03-12 Jan Nijtmans <nijtmans@users.sf.net>
- * unix/configure.in (Darwin): add plist for tclsh; link the
- * unix/Makefile.in (Darwin): Tcl and tclsh plists into their
- * macosx/Tclsh-Info.plist.in (new): binaries in all cases.
+ * win/makefile.vc: Fix [Bug 2967340]: Static build failure
+ * win/.cvsignore
- * unix/tcl.m4 (Darwin): fix CF checks in fat 32&64bit builds.
- * unix/configure: autoconf-2.13
+2010-03-09 Andreas Kupries <andreask@activestate.com>
-2007-06-05 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclIORChan.c: [Bug 2936225]: Thanks to Alexandre Ferrieux
+ * doc/refchan.n: <ferrieux@users.sourceforge.net> for debugging
+ * tests/ioCmd.test: and fixing the problem. It is the write-side
+ equivalent to the bug fixed 2009-08-06.
- * tests/result.test (result-6.2): Add test for [Bug 1649062] so that
- 8.4 and 8.5 both test the same outcome and we verify compatibility.
+2010-03-09 Don Porter <dgp@users.sourceforge.net>
-2007-05-30 Don Porter <dgp@users.sourceforge.net>
+ * library/tzdata/America/Matamoros: New locale
+ * library/tzdata/America/Ojinaga: New locale
+ * library/tzdata/America/Santa_Isabel: New locale
+ * library/tzdata/America/Asuncion:
+ * library/tzdata/America/Tijuana:
+ * library/tzdata/Antarctica/Casey:
+ * library/tzdata/Antarctica/Davis:
+ * library/tzdata/Antarctica/Mawson:
+ * library/tzdata/Asia/Dhaka:
+ * library/tzdata/Pacific/Fiji:
+ Olson tzdata2010c.
- * README: Bump version number to 8.4.16
- * generic/tcl.h:
- * tools/tcl.wse.in:
- * unix/configure.in:
- * unix/tcl.spec:
- * win/README.binary:
- * win/configure.in:
+2010-03-01 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
- * unix/configure: autoconf-2.13
- * win/configure:
+ * unix/tclUnixChan.c: [backported] Refrain from a possibly lengthy
+ reverse-DNS lookup on 0.0.0.0 when calling [fconfigure -sockname]
+ on an universally-bound (default) server socket.
-2007-05-29 Jeff Hobbs <jeffh@ActiveState.com>
+2010-02-27 Donal K. Fellows <dkf@users.sf.net>
- * unix/tclUnixThrd.c (Tcl_JoinThread): fix for 64-bit handling of
- pthread_join exit return code storage. [Bug 1712723]
+ * generic/tclCmdMZ.c (StringFirstCmd, StringLastCmd): [Bug 2960021]:
+ Only search for the needle in the haystack when the needle isn't
+ larger than the haystack. Prevents an odd crash from sometimes
+ happening when things get mixed up (a common programming error).
-2007-05-24 Don Porter <dgp@users.sourceforge.net>
+2010-02-21 Jan Nijtmans <nijtmans@users.sf.net>
- *** 8.4.15 TAGGED FOR RELEASE ***
+ * generic/tclBasic.c: Fix [Bug 2954959] expr abs(0.0) is -0.0
+ * tests/expr.test
- * generic/tclIO.c: Backport memleak fix in TclFinalizeIOSubsystem.
+2010-02-19 Stuart Cassoff <stwo@users.sourceforge.net>
-2007-05-17 Don Porter <dgp@users.sourceforge.net>
+ * tcl.m4: Correct compiler/linker flags for threaded builds on OpenBSD
+ * configure: (regenerated).
- * tests/fCmd.test: Backport the notNetworkFilesystem constraint.
+2010-02-19 Donal K. Fellows <dkf@users.sf.net>
-2007-05-15 Don Porter <dgp@users.sourceforge.net>
+ * unix/installManPage: [Bug 2954638]: Correct behaviour of manual page
+ installer. Also added armouring to check that assumptions about the
+ initial state are actually valid (e.g., look for existing input file).
- * generic/tclNamesp.c: Plugged memory leak related to
- [namespace delete ::]. [Bug 1716782]
+2010-02-11 Donal K. Fellows <dkf@users.sf.net>
- * changes: updates for 8.4.15 release.
+ * generic/tclIOCmd.c (Tcl_OpenObjCmd): [Bug 2949740]: Make sure that
+ we do not try to put a NULL pipeline channel into binary mode.
- * win/tclWinReg.c: Bump to registry 1.1.5 to account
- * library/reg/pkgIndex.tcl: for [Bug 1682211] fix.
+2010-02-07 Jan Nijtmans <nijtmans@users.sf.net>
-2007-05-10 Don Porter <dgp@users.sourceforge.net>
+ * tools/genStubs.tcl Backport various formatting (spacing)
+ * generic/tcl*.decls changes from HEAD, so diffing
+ * generic/tcl*Decls.h between 8.5.x and 8.6 shows the
+ * generic/tclStubInit.c real structural differences again.
+ (any signature change not backported!)
- * generic/tclInt.h: TclFinalizeThreadAlloc() is always defined,
- so make sure it is also always declared.
+2010-02-03 Donal K. Fellows <dkf@users.sf.net>
- [Tcl Bug 1706140]
+ * generic/tclVar.c (Tcl_ArrayObjCmd): More corrections for the 'unset'
+ subcommand.
- * generic/tclCmdMZ.c (Trace*Proc): Update Tcl_VarTraceProcs so
- * generic/tclLink.c (LinkTraceProc): that they call
- * generic/tclUtil.c (TclPrecTraceProc): Tcl_InterpDeleted() for
- themselves, and do not rely on (frequently buggy) setting of the
- TCL_INTERP_DESTROYED flag by the trace core.
+2010-02-02 Andreas Kupries <andreask@activestate.com>
- * generic/tclVar.c: Update callers of CallVarTraces to not
- pass in the TCL_INTERP_DESTROYED flag. Also apply filters so that
- public routines only pass documented flag values down to lower level
- routines.
+ * generic/tclCompile.c: [Bug 2933089]: A literal sharing problem with
+ * generic/tclCompile.h: 'info frame' affects not only 8.6 but 8.5 as
+ * generic/tclExecute.h: well. Backported the fix done in 8.6, without
+ * tests/info.test: changes. New testcase info-39.1.
- * generic/tclVar.c (CallVarTraces): The setting of the
- TCL_INTERP_DESTROYED flag is now done entirely within the
- CallVarTraces routine, the only place it can be done right.
+2010-02-02 Donal K. Fellows <dkf@users.sf.net>
-2007-04-30 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tclVar.c (Tcl_ArrayObjCmd): [Bug 2939073]: Stop the [array
+ unset] command from having dangling pointer problems when an unset
+ trace deletes the element that is going to be processed next. Many
+ thanks to Alexandre Ferrieux for the bulk of this fix.
- * unix/Makefile.in: add 'tclsh' dependency to install targets that rely
- on tclsh, fixes parallel 'make install' from empty build dir.
+2010-02-01 Donal K. Fellows <dkf@users.sf.net>
-2007-04-29 Daniel Steffen <das@users.sourceforge.net>
+ * generic/regexec.c (ccondissect, crevdissect): [Bug 2942697]: Rework
+ these functions so that certain pathological patterns are matched much
+ more rapidly. Many thanks to Tom Lane for dianosing this issue and
+ providing an initial patch.
- * unix/tclUnixFCmd.c: add workaround for crashing bug in fts_open()
- * unix/tclUnixInit.c: without FTS_NOSTAT on 64bit Darwin 8 or earlier.
+2010-02-01 Jan Nijtmans <nijtmans@users.sf.net>
- * unix/tclLoadDyld.c (TclpLoadMemory): fix (void*) arithmetic.
+ * generic/tclInt.decls: Various CYGWIN-related fixes
+ * generic/tclInt.h: backported from HEAD. Still
+ * generic/tclIntPlatDecls.h: configure script not modified,
+ * generic/tclPort.h: so CYGWIN build is still
+ * generic/tclTest.c: disabled. Reason: although the
+ * win/cat.c: build succeeds with those changes,
+ * win/tclWinDde.c: many tests still fail.
+ * win/tclWinError.c:
+ * win/tclWinFile.c:
+ * win/tclWinPipe.c:
+ * win/tclWinPort.h:
+ * win/tclWinReg.c:
+ * win/tclWinSerial.c:
+ * win/tclWinSock.c:
+ * win/tclWinTest.c:
+ * win/tclWinThrd.c:
- * macosx/tclMacOSXNotify.c: fix warnings.
+2010-01-29 Jan Nijtmans <nijtmans@users.sf.net>
- * macosx/README: sync whitespace/formatting with HEAD.
- * macosx/tclMacOSXBundle.c:
- * macosx/tclMacOSXNotify.c:
- * unix/tclLoadDyld.c:
+ * generic/tcl.h: Use correct TCL_LL_MODIFIER for CYGWIN.
+ Formatting (all backported from HEAD)
+ * generic/rege_dfa.c: Fix macro conflict on CYGWIN: don't use
+ "small".
+ * generic/tclTest.c: Fix gcc 4.4 warning: ignoring return value of
+ * unix/tclUnixPipe.c: 'write'
+ * unix/tclUnixNotify.c:
- * macosx/Makefile: fix/add copyright and license refs.
- * macosx/tclMacOSXBundle.c:
- * macosx/Tcl-Info.plist.in:
+2010-01-19 Donal K. Fellows <dkf@users.sf.net>
- * unix/Makefile.in (dist): copy license.terms to dist macosx dir.
- * unix/configure.in: install license.terms into Tcl.framework.
- * unix/configure: autoconf-2.13
-
-2007-04-21 Kevin B. Kenny <kennyb@acm.org>
-
- * generic/tclClock.c: Restored Cygwin buildability [Bug 1387154]
- * generic/tclInt.decls: Yet another round of attempting
- * generic/tclInt.h: to get the correct type signature
- * unix/tclUnixPort.h: for TclpLocaltime and TclpGmtime.
- * unix/tclUnixTime.c: CONST TclpTime_t is a 'time_t *CONST'
- * win/tclWinTime.c: and not a 'CONST time_t*' [Bug 1677275]
- * generic/tclIntDecls.h:
- * generic/tclIntPlatDecls.h: Regenerated.
-
-2007-03-24 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+ * doc/dict.n: [Bug 2929546]: Clarify just what [dict with] and [dict
+ update] are doing with variables.
- * win/tclWinThrd.c: Thread exit handler marks the current
- thread as un-initialized. This allows exit handlers that
- are registered later to re-initialize this subsystem in
- case they need to use some sync primitives (cond variables)
- from this file again.
+2010-01-18 Andreas Kupries <andreask@activestate.com>
-2007-03-19 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclIO.c (CreateScriptRecord): [Bug 2918110]: Initialize
+ the EventScriptRecord (esPtr) fully before handing it to
+ Tcl_CreateChannelHandler for registration. Otherwise a reflected
+ channel calling 'chan postevent' (== Tcl_NotifyChannel) in its
+ 'watchProc' will cause the function 'TclChannelEventScriptInvoker'
+ to be run on an uninitialized structure.
- * generic/tclEvent.c (Tcl_CreateThread): Replaced some calls to
- * generic/tclPkg.c (CheckVersion): Tcl_Alloc() with calls to
- * unix/tclUnixTime.c (SetTZIfNecessary): ckalloc(), which better
- * win/tclAppInit.c (setargv): supports memory debugging.
+2010-01-18 Donal K. Fellows <dkf@users.sf.net>
-2007-03-17 Kevin Kenny <kennykb@acm.org>
-
- * win/tclWinReg.c (GetKeyNames): Size the buffer for enumerating
- key names correctly, so that Unicode names exceeding 127 chars
- can be retrieved without crashing. [Bug 1682211]
- * tests/registry.test (registry-4.9): Added test case for the
- above bug.
+ * generic/tclStringObj.c (Tcl_AppendFormatToObj): [Bug 2932421]: Stop
+ the [format] command from causing argument objects to change their
+ internal representation when not needed. Thanks to Alexandre Ferrieux
+ for this fix.
-2007-03-13 Don Porter <dgp@users.sourceforge.net>
+2010-01-06 Jan Nijtmans <nijtmans@users.sf.net>
- * generic/tclExecute.c (INST_FOREACH_STEP4): Re-fetch pointers for
- * tests/foreach.test (foreach-10.1): the value list each iteration
- of the loop as defense against shimmers. [Bug 1671087]
+ * generic/tclCompExpr.c: Warning: array subscript has type 'char'
+ * generic/tclPkg.c:
+ * libtommath/bn_mp_read_radix.c:
+ * unix/tclUnixCompat.c: Fix gcc warning: signed and unsigned type
+ in conditional expression.
+ * unix/tcl.m4: Add support for Haiku and CYGWIN dynamical loading
+ * unix/configure: (regenerated)
+ * unix/Makefile.in:
+ * unix/.cvsignore:
+ * tests/stack.test: Reduced minimum required C-stack size to 2034:
+ CYGWIN has this stack size and the test runs fine!
+ * generic/tclEnv.c: Fix environment tests under CYGWIN
+ * generic/tclPort.h:
+ * tests/env.test:
- * generic/tclVar.c (TclArraySet): Re-fetch pointers for the list
- * tests/var.test (var-17.1): argument of [array set] each time
- through the loop as defense against possible shimmer issues.
- [Bug 1669489].
+2010-01-05 Don Porter <dgp@users.sourceforge.net>
-2007-03-10 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * generic/tclPathObj.c (TclPathPart): [Bug 2918610]: Correct
+ * tests/fileName.test (filename-14.31): inconsistency between the
+ string rep and the intrep of a path value created by [file rootname].
+ Thanks to Vitaly Magerya for reporting.
- * generic/tclCmdIL.c (Tcl_LsortObjCmd): Handle tricky case with loss
- * tests/cmdIL.test (cmdIL-1.29):of list rep during sorting due
- to shimmering. [Bug 1675116]
+2010-01-03 Donal K. Fellows <dkf@users.sf.net>
-2007-03-07 Daniel Steffen <das@users.sourceforge.net>
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): [Bug 1636685]: Use the configuration
+ for modern FreeBSD suggested by the FreeBSD porter.
- * macosx/tclMacOSXNotify.c: add spinlock debugging and sanity checks.
+2009-12-30 Donal K. Fellows <dkf@users.sf.net>
- * unix/tcl.m4 (Darwin): s/CFLAGS/CPPFLAGS/ in macosx-version-min check.
- * unix/configure: autoconf-2.13
+ * library/safe.tcl (AliasSource): [Bug 2923613]: Make the safer
+ * tests/safe.test (safe-8.9): [source] handle a [return] at the
+ end of the file correctly.
-2007-03-01 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+2009-12-29 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclCompCmds.c (TclCompileForeachCmd): Prevent an unexpected
- * tests/foreach.test (foreach-9.1): infinite loop when the
- variable list is empty and the foreach is compiled. [Bug 1671138]
+ * generic/tclInterp.c (Tcl_MakeSafe): [Bug 2895741]: Make sure that
+ the min() and max() functions are supported in safe interpreters.
-2007-02-22 Andreas Kupries <andreask@activestate.com>
+2009-12-28 Donal K. Fellows <dkf@users.sf.net>
- * tests/pkg.test: Added tests for the case of an alpha package
- satisfying a require for the regular package, demonstrating a
- corner case specified in TIP#280. More notes in the comments to
- the test.
+ * unix/configure.in: [Bug 942170]: Detect the st_blocks field of
+ * generic/tclCmdAH.c (StoreStatData): 'struct stat' correctly.
+ * generic/tclIOUtil.c (Tcl_Stat, Tcl_FSStat):
+ * generic/tclTest.c (PretendTclpStat):
-2007-02-20 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclInterp.c (TimeLimitCallback): [Bug 2891362]: Ensure that
+ * tests/interp.test (interp-34.13): the granularity ticker is
+ reset when we check limits because of the time limit event firing.
- * doc/tcltest.n: Typo fix. [Bug 1663539]
+2009-12-27 Donal K. Fellows <dkf@users.sf.net>
-2007-02-19 Jeff Hobbs <jeffh@ActiveState.com>
+ * doc/namespace.n (SCOPED SCRIPTS): [Bug 2921538]: Updated example to
+ not be quite so ancient.
- * generic/tclIOUtil.c (Tcl_FSEvalFile): safe incr of objPtr ref.
+2009-12-23 Donal K. Fellows <dkf@users.sf.net>
- * unix/tcl.m4: use SHLIB_SUFFIX=".so" on HP-UX ia64 arch.
- * unix/configure: autoconf-2.13
+ * library/safe.tcl (AliasSource, AliasExeName): [Bug 2913625]: Stop
+ information about paths from leaking through [info script] and [info
+ nameofexecutable].
-2007-02-12 Andreas Kupries <andreask@activestate.com>
+2009-12-16 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclEncoding.c (EscapeFromUtfProc): Applied patch
- supplied by Mo DeJong to fix [Bug 1516109]. Backport from Tcl
- 8.5. Mo's description: Clear the TCL_ENCODING_END flag when end
- bytes are written. This fix keep this method from writing escape
- bytes for an encoding like iso2022-jp multiple times when the
- escape byte overlap with the end of the IO buffer.
- * tests/io.test: Add test case for escape byte overlap case.
+ * library/safe.tcl (::safe::AliasGlob): Upgrade to correctly support a
+ larger fraction of [glob] functionality, while being stricter about
+ directory management.
-2007-02-04 Daniel Steffen <das@users.sourceforge.net>
+ * doc/tm.n: [Bug 1911342]: Formatting rewrite to avoid bogus crosslink
+ to the list manpage when generating HTML.
- * unix/configure.in: add caching to -pipe check.
- * unix/configure: autoconf-2.13
+ * library/msgcat/msgcat.tcl (Init): [Bug 2913616]: Do not use platform
+ tests that are not needed and which don't work in safe interpreters.
-2007-01-30 Jeff Hobbs <jeffh@ActiveState.com>
+2009-12-12 Donal K. Fellows <dkf@users.sf.net>
- * win/Makefile.in (install-private-headers): added target
+ * generic/tclTest.c (TestconcatobjCmd): [Bug 2895367]: Stop memory
+ leak when testing. We don't need extra noise of this sort when
+ tracking down real problems!
-2007-01-29 Don Porter <dgp@users.sourceforge.net>
+2009-12-10 Andreas Kupries <andreask@activestate.com>
- * doc/fcopy.n: Typo fix. [Bug 1630627]
+ * generic/tclObj.c (TclContinuationsEnter): [Bug 2895323]: Updated
+ comments to describe when the function can be entered for the same
+ Tcl_Obj* multiple times. This is a continuation of the 2009-11-10
+ entry where a memory leak was plugged, but where not sure if that was
+ just a band-aid to paper over some other error. It isn't, this is a
+ legal situation.
-2007-01-25 Daniel Steffen <das@users.sourceforge.net>
+2009-12-09 Andreas Kupries <andreask@activestate.com>
- * unix/tcl.m4: integrate CPPFLAGS into CFLAGS as late as possible
- * unix/configure.in: and move (rather than duplicate) -isysroot flags
- from CFLAGS to CPPFLAGS to avoid errors about multiple -isysroot flags
- from some older gcc builds.
+ * library/safe.tcl: Backport of the streamlined safe base from
+ * tests/safe.test: head to the 8.5 branch (See head changelog entries
+ 2009-11-05, 2009-11-06, 2009-12-03).
- * unix/configure: autoconf-2.13
+2009-12-07 Don Porter <dgp@users.sourceforge.net>
-2007-01-22 Andreas Kupries <andreask@activestate.com>
+ * generic/tclStrToD.c: [Bug 2902010]: Correct conditional compile
+ directives to better detect the toolchain that needs extra work for
+ proper underflow treatment instead of merely detecting the MIPS
+ platform.
- * compat/memcmp.c (memcmp): Fixed the VOID / CONST typo introduced
- by the last checkin.
+2009-12-02 Jan Nijtmans <nijtmans@users.sf.net>
-2007-01-22 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * tools/genStubs.tcl: Add support for win32 CALLBACK functions (needed
+ for Tk bugfix).
- * compat/memcmp.c (memcmp): Reworked so that arithmetic is never
- performed upon void pointers, since that is illegal. [Bug 1631017]
+2009-11-30 Donal K. Fellows <dkf@users.sf.net>
-2006-01-19 Daniel Steffen <das@users.sourceforge.net>
+ * doc/Tcl.n: [Bug 2901433]: Improved description of expansion to
+ mention that it is using list syntax.
- * macosx/tclMacOSXNotify.c: accommodate changes to prototypes of
- OSSpinLock(Un)Lock API.
-
- * tests/env.test: add extra system env vars that need to be preserved
- on some Mac OS X versions for testsuite to work.
+2009-11-27 Donal K. Fellows <dkf@users.sf.net>
- * unix/tcl.m4: ensure CPPFLAGS env var is used when set. [Bug 1586861]
- (Darwin): add -isysroot and -mmacosx-version-min flags to CPPFLAGS when
- present in CFLAGS to avoid discrepancies between what headers configure
- sees during preprocessing tests and compiling tests.
+ * doc/BoolObj.3, doc/CrtChannel.3, doc/DictObj.3, doc/DoubleObj.3:
+ * doc/Ensemble.3, doc/Environment.3, doc/FileSystem.3, doc/Hash.3:
+ * doc/IntObj.3, doc/Limit.3, doc/ObjectType.3, doc/PkgRequire.3:
+ * doc/SetChanErr.3, doc/SetResult.3: [Patch 2903921]: Many small
+ spelling fixes from Larry Virden.
- * unix/configure: autoconf-2.13
+2009-11-25 Stuart Cassoff <stwo@users.sf.net>
-2006-12-19 Daniel Steffen <das@users.sourceforge.net>
+ * unix/configure.in: [Patch 2892871]: Remove unneeded
+ * unix/tcl.m4: AC_STRUCT_TIMEZONE and use
+ * unix/tclConfig.h.in: AC_CHECK_MEMBERS([struct stat.st_blksize])
+ * unix/tclUnixFCmd.c: instead of AC_STRUCT_ST_BLKSIZE.
+ * unix/configure: Regenerated with autoconf-2.59.
- * unix/tclUnixThrd.c (TclpInetNtoa): fix for 64 bit.
+2009-11-16 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
- * unix/tcl.m4 (Darwin): --enable-64bit: verify linking with 64bit -arch
- flag succeeds before enabling 64bit build.
- * unix/configure: autoconf-2.13
+ * generic/tclEncoding.c: Fix [Bug 2891556] and improve test to detect
+ * tests/decoding.test: similar manifestations in the future.
+
+2009-11-12 Don Porter <dgp@users.sourceforge.net>
-2006-12-14 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ *** 8.5.8 TAGGED FOR RELEASE ***
- * doc/string.n: Fix example. [Bug 1615277]
+ * changes: Update for 8.5.8 release.
-2006-12-05 Andreas Kupries <andreask@activestate.com>
+ * generic/tclClock.c (TclClockInit): Do not create [clock] support
+ commands in safe interps.
- * tests/pkg.test: Backport to 8.4 (Don Porter's work):
- * generic/tclPkg.c: When no requirements are supplied to a [package
- require $pkg] and [package unknown] is invoked to find a satisfying
- package, pass the requirement argument "0-" (which means all versions
- are acceptable). This permits a registered [package unknown] command
- to call [package vsatisfies $testVersion {*}$args] without any special
- handling of the empty $args case. This fixes/avoids a bug in
- [::tcl::tm::UnknownHandler] that was causing old TM versions to be
- provided in preference to newer TM versions. Thanks to Julian Noble
- for discovering the issue.
+ * tests/io.test: New test io-53.11 to test for [Bug 2895565].
-2006-12-04 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+2009-11-12 Andreas Kupries <andreask@activestate.com>
- * doc/file.n: Fix confusing wording for [file pathtype]. [Bug 1606454]
+ * generic/tclIO.c (CopyData): [Bug 2895565]: Dropped bogosity which
+ used the number of _written_ bytes or character to update the counters
+ for the read bytes/characters. See last entry for the test case.
-2006-11-28 Andreas Kupries <andreask@activestate.com>
+2009-11-11 Pat Thoyts <patthoyts@users.sourceforge.net>
- * generic/tclBasic.c: TIP #280 implementation, conditional on the
- * generic/tclCmdAH.c: define TCL_TIP280.
- * generic/tclCmdIL.c:
- * generic/tclCmdMZ.c:
- * generic/tclCompCmds.c:
- * generic/tclCompExpr.c:
- * generic/tclCompile.c:
- * generic/tclCompile.h:
- * generic/tclExecute.c:
- * generic/tclIOUtil.c:
- * generic/tclInt.h:
- * generic/tclInterp.c:
- * generic/tclNamesp.c:
- * generic/tclObj.c:
- * generic/tclProc.c:
- * tests/compile.test:
- * tests/info.test:
- * tests/platform.test:
- * tests/safe.test:
+ * tests/fCmd.test: Fixed a number of issues for Vista and Win7
+ * tests/registry.test: that are due to restricted permissions.
+ * tests/winFCmd.test:
-2006-11-27 Kevin Kenny <kennykb@acm.org>
+2009-11-11 Don Porter <dgp@users.sourceforge.net>
- * unix/tclUnixChan.c (TclUnixWaitForFile):
- * tests/event.test (event-14.*): Corrected a bug where
- TclUnixWaitForFile would present select() with the wrong mask on an
- LP64 machine if a fd number exceeds 32. Thanks to Jean-Luc Fontaine
- for reporting and diagnosing [Bug 1602208]
+ * library/http/http.tcl: [Bug 2891171]: Update the URL syntax
+ check to RFC 3986 compliance on the subject of non-encoded question
+ mark characters.
-2006-11-26 Daniel Steffen <das@users.sourceforge.net>
+ * library/http/pkgIndex.tcl: Bump to http 2.7.5 to avoid any
+ * unix/Makefile.in: confusion with snapshot "releases"
+ * win/Makefile.in: that might be in ActiveTcl, etc.
- * unix/tcl.m4 (Linux): --enable-64bit support. [Patch 1597389]
- * unix/configure: autoconf-2.13 [Bug 1230558]
+2009-11-11 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
-2006-11-07 Andreas Kupries <andreask@activestate.com>
+ * generic/tclIO.c: Backported fix for [Bug 2888099] (close discards
+ ENOSPC error) by saving the errno from the first of two
+ FlushChannel()s. Uneasy to test; might need specific channel drivers.
+ Four-hands with aku.
- * unix/tclUnixFCmd.c (CopyFile): Added code to fall back to a
- hardwired default block size should the filesystem report a bogus
- value. [Bug 1586470]
+2009-11-10 Don Porter <dgp@users.sourceforge.net>
-2006-11-03 Miguel Sofer <msofer@users.sf.net>
+ * generic/tclBasic.c: Plug another leak in TCL_EVAL_DIRECT
+ evaluation.
- * generic/tclBasic.c (TEOVI): fix for possible leak of a Command in
- the presence of execution traces that delete it.
+ * generic/tclObj.c: Plug memory leak in TclContinuationsEnter().
+ [Bug 2895323]
- * generic/tclBasic.c (TEOVI):
- * tests/trace.test (trace-21.11): fix for [Bug 1590232], execution
- traces may cause a second command resolution in the wrong
- namespace.
+2009-11-09 Stuart Cassoff <stwo@users.sf.net>
-2006-11-01 Daniel Steffen <das@users.sourceforge.net>
+ * win/README: [bug 2459744]: Removed outdated Msys + Mingw info.
- * generic/tclEnv.c (Darwin): mark _environ symbol as unexported.
+2009-11-09 Don Porter <dgp@users.sourceforge.net>
-2006-10-31 Pat Thoyts <patthoyts@users.sourceforge.net>
+ * generic/tclBasic.c (TclEvalObjEx): Plug memory leak in
+ TCL_EVAL_DIRECT evaluation.
- * rules.vc: Fix [Bug 1582769] build with VC2003 and correct i386 arch
+ * tests/info.test: Resolve ambiguous resolution of variable "res".
-2006-10-23 Don Porter <dgp@users.sourceforge.net>
+2009-11-03 Don Porter <dgp@users.sourceforge.net>
- * README: Bump version number to 8.4.15
- * generic/tcl.h:
+ * generic/tcl.h: Bump to 8.5.8 for release.
+ * library/init.tcl:
* tools/tcl.wse.in:
* unix/configure.in:
* unix/tcl.spec:
- * win/README.binary:
* win/configure.in:
+ * README:
- * unix/configure: autoconf-2.13
+ * unix/configure: autoconf-2.59
* win/configure:
-2006-10-18 Pat Thoyts <patthoyts@users.sourceforge.net>
-
- *** 8.4.14 TAGGED FOR RELEASE ***
+ * changes: Update for 8.5.8 release.
- * win/nmakehlp.c: Ensure builds with VC6 without Platform SDK.
- * win/rules.vc: Pickup MACHINE from environment.
+2009-11-03 Andreas Kupries <andreask@activestate.com>
-2006-10-17 Don Porter <dgp@users.sourceforge.net>
+ * library/safe.tcl (::safe::InterpSetConfig): [Bug 2854929]: Added
+ code to recursively find deeper paths which may contain modules.
+ Required to handle modules with names like 'platform::shell', which
+ translate into 'platform/shell-X.tm', i.e arbitrarily deep
+ subdirectories.
- * generic/tclIOUtil.c: Cleaned up some code flagged by a
- * generic/tclInt.h: `make checkexports` test.
- * win/tclWin32Dll.c:
- * win/tclWinFile.c:
+2009-11-03 Kevin B. Kenny <kennykb@acm.org>
-2006-10-16 Daniel Steffen <das@users.sourceforge.net>
-
- * changes: updates for 8.4.14 release.
-
- * macosx/Makefile: don't redo prebinding of non-prebound binaires.
-
-2006-10-11 Andreas Kupries <andreask@activestate.com>
-
- * generic/tclPkg.c (Tcl_PkgRequireEx): Corrected crash when argument
- version==NULL passed in. Backport of the fix for the same problem in
- 8.5.
-
-2006-10-10 Don Porter <dgp@users.sourceforge.net>
-
- * changes: changes updated for 8.4.14 release.
-
-2006-10-06 Jeff Hobbs <jeffh@ActiveState.com>
-
- * tests/http.test: update tests to handle strictness change.
+ * library/tzdata/Asia/Novokuznetsk: New tzdata locale for Kemerovo
+ oblast', which now keeps Novosibirsk time and not Kranoyarsk time.
+ * library/tzdata/Asia/Damascus: Syrian DST changes.
+ * library/tzdata/Asia/Hong_Kong: Hong Kong historic DST corrections.
+ Olson tzdata2009q.
-2006-10-06 Pat Thoyts <patthoyts@users.sourceforge.net>
+2009-11-03 Pat Thoyts <patthoyts@users.sourceforge.net>
- * win/rules.vc: avoid /RTCc flag with MSVC8. [Bug 1571954]
+ * tests/tcltest.test: Backport permissions fix for Win7.
-2006-10-05 Jeff Hobbs <jeffh@ActiveState.com>
+2009-10-31 Donal K. Fellows <dkf@users.sf.net>
- * library/http/http.tcl (http::geturl): only do geturl url rfc 3986
- validity checking if $::http::strict is true (default false for 8.4).
- [Bug 1560506]
-
- * generic/tcl.h: note limitation on changing Tcl_UniChar size
- * generic/tclEncoding.c (UtfToUnicodeProc, UnicodeToUtfProc):
- * tests/encoding.test (encoding-16.1): fix alignment issues in
- unicode <> utf conversion procs. [Bug 1122671]
+ * generic/tclBasic.c (ExprRoundFunc): [Bug 2889593]: Correctly report
+ the expected number of arguments when generating an error for round().
-2006-10-05 Miguel Sofer <msofer@users.sf.net>
+2009-10-29 Don Porter <dgp@users.sourceforge.net>
- * generic/tclVar.c (Tcl_LappendObjCmd):
- * tests/append.test(4.21-22): fix for longstanding [Bug 1570718],
- lappending nothing to non-list. Reported by lvirden
+ * generic/tcl.h: [Bug 2800740]: Changed the typedef for the
+ mp_digit type from:
+ typedef unsigned long mp_digit;
+ to:
+ typedef unsigned int mp_digit;
+ For 32-bit builds where "long" and "int" are two names for the same
+ thing, this is no change at all. For 64-bit builds, though, this
+ causes the dp[] array of an mp_int to be made up of 32-bit elements
+ instead of 64-bit elements. This is a huge improvement because details
+ elsewhere in the mp_int implementation cause only 28 bits of each
+ element to be actually used storing number data. Without this change
+ bignums are over 50% wasted space on 64-bit systems.
-2006-10-02 Don Porter <dgp@users.sourceforge.net>
+ ***POTENTIAL INCOMPATIBILITY***
+ For 64-bit builds, callers of routines with (mp_digit) or (mp_digit *)
+ arguments *will*, and callers of routines with (mp_int *) arguments
+ *may* suffer both binary and stubs incompatibilities with Tcl releases
+ 8.5.0 - 8.5.7. Such possibilities should be checked, and if such
+ incompatibilities are present, suitable [package require] requirements
+ on the Tcl release should be put in place to keep such built code
+ [load]-ing only in Tcl interps that are compatible.
+
+2009-10-29 Kevin B. Kenny <kennykb@acm.org>
+
+ * library/clock.tcl (LocalizeFormat):
+ * tests/clock.test (clock-67.1): [Bug 2819334]:
+ Corrected a problem where '%%' followed by a letter in a format group
+ could expand recursively: %%R would turn into %%H:%M:%S.
+
+2009-10-28 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclLiteral.c: Backport fix for [Bug 2888044].
+
+2009-10-28 Kevin B. Kenny <kennykb@acm.org>
+
+ * tests/fileName.test (fileName-20.[78]): Corrected poor test
+ hygiene (failure to save and restore the working directory) that
+ caused these two tests to fail on Windows (and [Bug 2806250] to be
+ reopened).
+
+2009-10-27 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclPathObj.c: [Bug 2884203]: Missing refcount on cached
+ normalized path caused crashes.
+
+2009-10-27 Kevin B. Kenny <kennykb@acm.org>
+
+ * library/clock.tcl (ParseClockScanFormat): [Bug 2886852]:
+ Corrected a problem where [clock scan] didn't load the timezone soon
+ enough when processing a time format that lacked a complete date.
+ * tests/clock.test (clock-66.1):
+ Added a test case for the above bug.
+ * library/tzdata/America/Argentina/Buenos_Aires:
+ * library/tzdata/America/Argentina/Cordoba:
+ * library/tzdata/America/Argentina/San_Luis:
+ * library/tzdata/America/Argentina/Tucuman:
+ New DST rules for Argentina. (Olson's tzdata2009p.)
+
+2009-10-24 Kevin B. Kenny <kennykb@acm.org>
+
+ * library/clock.tcl (ProcessPosixTimeZone):
+ Corrected a regression in the fix to [Bug 2207436] that caused [clock]
+ to apply EU daylight saving time rules in the US. Thanks to Karl
+ Lehenbauer for reporting this regression.
+ * tests/clock.test (clock-52.4):
+ Added a regression test for the above regression.
+ * library/tzdata/Asia/Dhaka:
+ * library/tzdata/Asia/Karachi:
+ New DST rules for Bangladesh and Pakistan. (Olson's tzdata2009o.)
- * generic/tclFileName.c (TclGlob): Prevent doubling of directory
- separators by [glob]. [Bug 1569042]
+2009-10-23 Andreas Kupries <andreask@activestate.com>
-2006-10-01 Pat Thoyts <patthoyts@users.sourceforge.net>
+ * generic/tclIO.c (FlushChannel): Skip OutputProc for low-level
+ 0-length writes. When closing pipes which have already been closed not
+ skipping leads to spurious SIG_PIPE signals. Reported by Mikhail
+ Teterin <mi+thun@aldan.algebra.com>.
- * win/tclWinFile.c: Handle possible missing define.
- * win/tclWinFile.c: Backported fix for [Bug 1420432] (cannot set
- * tests/cmdAH.test: mtime for directories on windows).
+2009-10-21 Donal K. Fellows <dkf@users.sf.net>
-2006-09-30 Miguel Sofer <msofer@users.sf.net>
+ * generic/tclPosixStr.c: [Bug 2882561]: Work around oddity on Haiku OS
+ where SIGSEGV and SIGBUS are the same value.
- * generic/tclUtil.c (Tcl_SplitList): optimisation, [Patch 1344747]
- by dgp.
+2009-10-19 Don Porter <dgp@users.sourceforge.net>
-2006-09-26 Pat Thoyts <patthoyts@users.sourceforge.net>
+ * generic/tclIO.c: Revised ReadChars and FilterInputBytes
+ routines to permit reads to continue up to the string limits of Tcl
+ values. Before revisions, large read attempts could panic when as
+ little as half the limiting value length was reached. [Patch 2107634]
+ Thanks to Sean Morrison and Bob Parker for their roles in the fix.
- * win/makefile.vc: Updated MSVC build to properly deal with
- * win/nmakehlp.c: MSVC8 and AMD64 target. Backport from 8.5
- * win/rules.vc:
- * generic/tcl.h: Fixed stat definition for MSVC8 AMD64.
- * win/tclWinSock.c: Casting type police.
- * win/tclWinTime.c:
+2009-10-18 Joe Mistachkin <joe@mistachkin.com>
-2006-09-26 Don Porter <dgp@users.sourceforge.net>
+ * tests/thread.test (thread-4.[345]): [Bug 1565466]: Correct tests to
+ save their error state before the final call to threadReap just in
+ case it triggers an "invalid thread id" error. This error can occur
+ if one or more of the target threads has exited prior to the attempt
+ to send it an asynchronous exit command.
- * generic/tcl.h: As 2006-09-22 commit from Donal K. Fellows
- demonstrates, "#define NULL 0" is just wrong, and as a quotable chat
- figure observed, "If NULL isn't defined, we're not using a C compiler."
- Improper fallback definition of NULL removed.
+ * doc/memory.n: [Bug 988703]: Add mechanism for finding what Tcl_Objs
+ * generic/tclCkalloc.c (MemoryCmd): are allocated when built for
+ * generic/tclInt.decls: memory debugging. This was previously
+ * generic/tclInt.h: backported from Tcl 8.6 with the corrections to
+ * generic/tclObj.c (ObjData, TclFinalizeThreadObjects): fix [Bug
+ 2871908]. However, there were key elements missing. These changes make
+ things consistent between branches.
-2006-09-25 Andreas Kupries <andreask@activestate.com>
+2009-10-17 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclIO.c (Tcl_StackChannel): Fixed [SF Tcl Bug 1564642], aka
- coverity #51. Extended loop condition, added checking for NULL to
- prevent seg.fault.
+ * generic/tclVar.c (TclDeleteCompiledLocalVars, UnsetVarStruct)
+ (TclDeleteNamespaceVars):
+ * generic/tclTrace.c (Tcl_UntraceVar2): [Bug 2629338]: Stop traces
+ that are deleted part way through (a feature used by tdom) from
+ causing freed memory to be accessed.
-2006-09-25 Andreas Kupries <andreask@activestate.com>
+2009-10-08 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclBasic.c: Reverted exposure of patchlevel in registered
- core version when TIP#268 features are activated. Better compatibility
- with existing packages. Like Tk.
+ * generic/tclDictObj.c (DictIncrCmd): [Bug 2874678]: Don't leak any
+ bignums when doing [dict incr] with a value.
+ * tests/dict.test (dict-19.3): Memory leak detection code.
-2006-09-24 Miguel Sofer <msofer@users.sf.net>
+2009-10-07 Andreas Kupries <andreask@activestate.com>
- * generic/tclParse.c (Tcl_ParseCommand): also return an error if
- start==NULL and numBytes<0. This is coverity's bug #20
+ * generic/tclObj.c: [Bug 2871908]: Plug memory leaks of the
+ objThreadMap and lineCLPtr hashtables. Also make the names of the
+ continuation line information initialization and finalization
+ functions more consistent. Patch supplied by Joe Mistachkin
+ <joe@mistachkin.com>.
- * generic/tclStringObj.c (STRING_SIZE): fix allocation for 0-length
- strings. This is coverity's bugs #54-5
-
-2006-09-22 Andreas Kupries <andreask@activestate.com>
+ * generic/tclIORChan.c (ErrnoReturn): Replace the hardwired constant
+ 11 with the proper errno define, EAGAIN. What was I thinking? The
+ BSD's have a different errno assignment and break with the hardwired
+ number. Reported by emiliano on the chat.
- * generic/tclInt.h: Moved TIP#268's field 'packagePrefer' to the end
- of the structure, for better backward compatibility.
+2009-10-06 Don Porter <dgp@users.sourceforge.net>
-2006-09-22 Andreas Kupries <andreask@activestate.com>
+ * generic/tclTomMathInt.h (new): Public header tclTomMath.h had
+ * generic/tclTomMath.h: dependence on private headers, breaking use
+ * generic/tommath.h: by extensions [Bug 1941434].
- * generic/tclPkg.c (Tcl_PkgRequireEx): Changes handling of the return
- information from 'Tcl_PkgRequireProc'. Keep the interpreter result
- empty. Backport of fix for problem found while testing #268 under 8.5.
- More details in the comments.
+2009-10-05 Don Porter <dgp@users.sourceforge.net>
-2006-09-22 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * changes: Update for 8.5.8 release.
- * generic/tclThreadTest.c (TclCreateThread): Use NULL instead of 0 as
- end-of-strings marker to Tcl_AppendResult; the difference matters on
- 64-bit machines. [Bug 1562528]
+2009-10-04 Daniel Steffen <das@users.sourceforge.net>
-2006-09-21 Andreas Kupries <andreask@activestate.com>
+ * macosx/tclMacOSXBundle.c: Workaround CF memory managment bug in
+ * unix/tclUnixInit.c: Mac OS X 10.4 & earlier. [Bug 2569449]
- * generic/tcl.decls: Implemented TIP #268, conditionally.
- * generic/tclBasic.c: Define TCL_TIP268 to activate the new
- * generic/tclDecls.h: features.
- * generic/tclInt.h:
- * generic/tclPkg.c:
- * generic/tclStubInit.c:
- * generic/tclTest.c:
- * library/init.tcl
- * library/package.tcl:
- * tests/pkg.test:
- * tests/platform.test:
- * tests/safe.test:
- * doc/PkgRequire.3:
+2009-10-02 Kevin B. Kenny <kennykb@acm.org>
-2006-09-15 Jeff Hobbs <jeffh@ActiveState.com>
+ * library/tzdata/Africa/Cairo:
+ * library/tzdata/Asia/Gaza:
+ * library/tzdata/Asia/Karachi:
+ * library/tzdata/Pacific/Apia: Olson's tzdata2009n.
- * library/http/http.tcl: Change " " -> "+" url encoding mapping
- * library/http/pkgIndex.tcl: to " " -> "%20" as per RFC 3986.
- * tests/http.test (http-5.1): bump http to 2.5.3 for 8.4.14
+2009-09-29 Don Porter <dgp@users.sourceforge.net>
-2006-09-12 Andreas Kupries <andreask@activestate.com>
+ * generic/tclAlloc.c: Cleaned up various routines in the
+ * generic/tclCkalloc.c: call stacks for memory allocation to
+ * generic/tclInt.h: guarantee that any size values computed
+ * generic/tclThreadAlloc.c: are within the domains of the routines
+ they get passed to. [Bugs 2557696 and 2557796].
- * unix/configure.in (HAVE_MTSAFE_GETHOST*): Modified to recognize
- HP-UX 11.00 and beyond as having mt-safe implementations of the
- gethost functions.
- * unix/configure: Regenerated, using autoconf 2.13
+2009-09-11 Don Porter <dgp@users.sourceforge.net>
- * unix/tclUnixCompat.c (PadBuffer): Fixed bug in calculation of the
- increment needed to align the pointer, and added documentation
- explaining why the macro is implemented as it is.
+ * library/http/http.tcl: Bump to http 2.7.4 to account for
+ * library/http/pkgIndex.tcl: [Bug 2849860] fix.
+ * unix/Makefile.in:
+ * win/Makefile.in:
-2006-09-11 Andreas Kupries <andreask@activestate.com>
+2009-09-10 Donal K. Fellows <dkf@users.sf.net>
- * tests/msgcat.test: Bumped version in auxiliary files as well.
- * doc/msgcat.n:
+ * library/http/http.tcl (http::Event): [Bug 2849860]: Handle charset
+ names in double quotes; some servers like generating them like that.
-2006-09-11 Daniel Steffen <das@users.sourceforge.net>
+2009-09-01 Don Porter <dgp@users.sourceforge.net>
- * unix/tclUnixCompat.c: make compatLock static and only declare it
- when it will actually be used; #ifdef parts of TSD that are not always
- needed; adjust #ifdefs to cover all possible cases; fix whitespace.
-
-2006-09-10 Don Porter <dgp@users.sourceforge.net>
-
- * library/msgcat/msgcat.tcl: Bump to version msgcat 1.3.4 to account
- * library/msgcat/pkgIndex.tcl: for modifications.
-
-2006-09-10 Daniel Steffen <das@users.sourceforge.net>
+ * library/tcltest/tcltest.tcl: Bump to tcltest 2.3.2 after revision
+ * library/tcltest/pkgIndex.tcl: to verbose error message.
+ * unix/Makefile.in:
+ * win/Makefile.in:
- * library/msgcat/msgcat.tcl (msgcat::Init): on Darwin, add fallback of
- * tests/msgcat.test: default msgcat locale to
- * unix/tclUnixInit.c (TclpSetVariables): current CFLocale
- identifier if available (via private ::tcl::mac::locale global, set at
- interp init when on Mac OS X 10.3 or later with CoreFoundation).
+2009-08-27 Don Porter <dgp@users.sourceforge.net>
- * unix/tcl.m4: add caching to new SC_TCL_* macros for MT-safe wrappers
- * unix/configure: autoconf-2.13
+ * generic/tclStringObj.c: [Bug 2845535]: A few more string
+ overflow cases in [format].
-2006-09-08 Andreas Kupries <andreask@activestate.com>
+2009-08-25 Andreas Kupries <andreask@activestate.com>
- * unix/tclUnixCompat.c: Fixed conditions for CopyArray/CopyString, and
- CopyHostent. Also fixed bad var names in TclpGetHostByName.
+ * generic/tclBasic.c (Tcl_CreateInterp, Tcl_EvalTokensStandard)
+ (EvalTokensStandard, Tcl_EvalEx, EvalEx, TclAdvanceContinuations)
+ (TclEvalObjEx):
+ * generic/tclCmdMZ.c (Tcl_SwitchObjCmd, TclListLines):
+ * generic/tclCompCmds.c (*):
+ * generic/tclCompile.c (TclSetByteCodeFromAny, TclInitCompileEnv)
+ (TclFreeCompileEnv, TclCompileScript):
+ * generic/tclCompile.h (CompileEnv):
+ * generic/tclInt.h (ContLineLoc, Interp):
+ * generic/tclObj.c (ThreadSpecificData, ContLineLocFree)
+ (TclThreadFinalizeObjects, TclInitObjSubsystem, TclContinuationsEnter)
+ (TclContinuationsEnterDerived, TclContinuationsCopy)
+ (TclContinuationsGet, TclFreeObj):
+ * generic/tclParse.c (TclSubstTokens, Tcl_SubstObj):
+ * generic/tclProc.c (TclCreateProc):
+ * generic/tclVar.c (TclPtrSetVar):
+ * tests/info.test (info-30.0-24):
-2006-09-08 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+ Extended parser, compiler, and execution with code and attendant data
+ structures tracking the positions of continuation lines which are not
+ visible in script Tcl_Obj*'s, to properly account for them while
+ counting lines for #280.
- * unix/tclUnixCompat.c: Added fallback to gethostbyname() and
- gethostbyaddr() if the implementation is known to be MT-safe
- (currently for Darwin 6 or later only).
+2009-08-24 Daniel Steffen <das@users.sourceforge.net>
- * unix/configure.in: Assume gethostbyname() and gethostbyaddr() are
- MT-safe starting with Darwin 6 (Mac OSX 10.2).
+ * macosx/tclMacOSXNotify.c: Fix multiple issues with nested event
+ loops when CoreFoundation notifier is running in embedded mode. (Fixes
+ problems in TkAqua Cocoa reported by Youness Alaoui on tcl-mac)
- * unix/configure: Regenerated with autoconf V2.13
+2009-08-21 Don Porter <dgp@users.sourceforge.net>
-2006-09-07 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+ * generic/tclFileName.c: Correct regression in [Bug 2837800] fix.
+ * tests/fileName.test:
- * unix/tclUnixFCmd.c: Removed some false tests added (and left by
- mistake) by fixing [Bug 999544]
+2009-08-20 Don Porter <dgp@users.sourceforge.net>
- * unix/tclUnixCompat.c: Added fallback to MT-unsafe library calls if
- TCL_THREADS is not defined. Fixed alignment of arrays copied by
- CopyArrayi() to be on the sizeof(char *) boundary.
+ * generic/tclFileName.c: [Bug 2837800]: Get the correct result from
+ [glob */test] when * matches something like ~foo.
-2006-09-07 Andreas Kupries <andreask@activestate.com>
+ * generic/tclPathObj.c: [Bug 2806250]: Prevent the storage of strings
+ starting with ~ in the "tail" part (normPathPtr field) of the path
+ intrep when PATHFLAGS != 0. This establishes the assumptions relied
+ on elsewhere that the name stored there is a relative path. Also
+ refactored to make an AppendPath() routine instead of the cut/paste
+ stanzas that were littered throughout.
- * unix/configure: Regenerated using autoconf 2.13.
+2009-08-20 Donal K. Fellows <dkf@users.sf.net>
-2006-09-07 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+ * generic/tclCmdIL.c (Tcl_LsortObjCmd): Plug memory leak.
- * unix/tclUnixChan.c Rewritten MT-safe wrappers to
- * unix/tclUnixCompat.c return ptrs to TSD storage
- * unix/tclUnixFCmd.c making them all look like their
- * unix/tclUnixPort.h MT-unsafe pendants API-wise.
- * unix/tclUnixSock.c
+2009-08-18 Don Porter <dgp@users.sourceforge.net>
-2006-09-06 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+ * generic/tclPathObj.c: [Bug 2837800]: Added NULL check to prevent
+ * tests/fileName.test: crashes during [glob].
- * unix/tclUnixChan.c: Added TCL_THREADS ifdef'ed usage
- * unix/tclUnixFCmd.c: of MT-safe calls like:
- * unix/tclUnixSock.c: getpwuid, getpwnam, getgrgid, getgrnam,
- * unix/tclUnixPort.h: gethostbyname and gethostbyaddr.
- * unix/Makefile.in: See Tcl Bug: 999544
- * unix/configure.in:
- * unix/tcl.m4:
- * unix/configure: Regenerated.
+2009-08-06 Andreas Kupries <andreask@activestate.com>
- * unix/tclUnixCompat.c: New file containing MT-safe implementation of
- some library calls.
+ * doc/refchan.n [Bug 2827000]: Extended the implementation of
+ * generic/tclIORChan.c: reflective channels (TIP 219, method 'read'),
+ * tests/ioCmd.test: enabling handlers to signal EAGAIN to indicate 'no
+ data, but not at EOF either', and other system errors. Updated
+ documentation, extended testsuite (New test cases iocmd*-23.{9,10}).
-2006-09-04 Don Porter <dgp@users.sourceforge.net>
+2009-08-02 Donal K. Fellows <dkf@users.sf.net>
- * tests/main.text (Tcl_Main-4.4): Test corrected to not be
- timing sensitive to the Bug 1481986 fix. [Bug 1550858]
+ * unix/tclUnixFCmd.c (GetOwnerAttribute, SetOwnerAttribute)
+ (GetGroupAttribute, SetGroupAttribute): [Bug 1942222]: Stop calling
+ * unix/tclUnixFile.c (TclpGetUserHome): endpwent() and endgrent();
+ they've been unnecessary for ages.
-2006-09-04 Jeff Hobbs <jeffh@ActiveState.com>
+2009-07-31 Don Porter <dgp@users.sourceforge.net>
- * doc/package.n: correct package example
+ * generic/tclStringObj.c: [Bug 2830354]: Corrected failure to
+ * tests/format.test: grow buffer when format spec request
+ large width floating point values. Thanks to Clemens Misch.
-2006-08-30 Jeff Hobbs <jeffh@ActiveState.com>
+2009-07-24 Andreas Kupries <andreask@activestate.com>
- * win/tclWinChan.c: [Bug 819667] Improve logic for identifying COM
- ports.
+ * generic/tclIO.c (Tcl_GetChannelHandle): [Bug 2826248]: Do not crash
+ * generic/tclPipe.c (FileForRedirect): for getHandleProc == NULL, this
+ is allowed. Provide a nice error message in the bypass area. Updated
+ caller to check the bypass for a mesage. Bug reported by Andy
+ Sonnenburg <andy22286@users.sourceforge.net>. Backported from CVS
+ head.
- * win/tclWinFCmd.c: [Bug 1548263] Added test for NULL return
- * generic/tclIOUtil.c: from Tcl_FSGetNormalizedPath which was
- causing segv's
+2009-07-23 Joe Mistachkin <joe@mistachkin.com>
- * generic/tclFileName.c (TclDoGlob): match incr with existing decr.
+ * generic/tclNotify.c: [Bug 2820349]: Ensure that queued events are
+ freed once processed.
- * unix/Makefile.in: add valgrindshell target and update default
- VALGRINDARGS. User can override, or add to it with VALGRIND_OPTS env
- var.
+2009-07-21 Kevin B. Kenny <kennykb@acm.org>
- * generic/tclBasic.c (Tcl_CreateInterp): init iPtr->threadId
+ * library/tzdata/Asia/Dhaka:
+ * library/tzdata/Indian/Mauritius: Olson's tzdata2009k.
- * generic/tclIOGT.c (ExecuteCallback):
- * generic/tclPkg.c (Tcl_PkgRequireEx): replace Tcl_GlobalEval(Obj)
- with more efficient Tcl_Eval(Obj)Ex
+2009-07-20 Donal K. Fellows <dkf@users.sf.net>
-2006-08-22 Andreas Kupries <andreask@activestate.com>
+ * generic/tclCmdMZ.c (StringIsCmd): Reorganize so that [string is] is
+ more efficient when parsing things that are correct, at a cost of
+ making the empty string test slightly more costly. With this, the cost
+ of doing [string is integer -strict $x] matches [catch {expr {$x+0}}]
+ in the successful case, and greatly outstrips it in the failing case.
- * unix/tclUnixNotfy.c (Tcl_WaitForEvent): Fixed broken if syntax
- committed 2006-08-21 by Daniel. The broken syntax is visible to all
- unix platforms, but not on OSX for machines which HAVE_COREFOUNDATION.
+2009-07-16 Don Porter <dgp@users.sourceforge.net>
-2006-08-21 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclCmdIL.c: Removed unused variables.
+ * generic/tclCompile.c:
+ * generic/tclVar.c:
+ * unix/tclUnixChan.c:
- * generic/tclIOUtil.c: Revisions to complete the thread finalization
- of the cwdPathPtr. [Bug 1536142]
+ * generic/tclScan.c: Typo in ACCEPT_NAN configuration.
-2006-08-21 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tclStrToD.c: [Bug 2819200]: Set floating point control
+ register on MIPS systems so that the gradual underflow expected by Tcl
+ is in effect.
- * macosx/tclMacOSXNotify.c (Tcl_WaitForEvent): if the run loop is
- already running (e.g. if Tcl_WaitForEvent was called recursively),
- re-run it in a custom run loop mode containing only the source for the
- notifier thread, otherwise wakeups from other sources added to the
- common run loop modes might get lost; sync panic msg changes from
- HEAD.
+2009-07-14 Andreas Kupries <andreask@activestate.com>
- * unix/tclUnixNotfy.c (Tcl_WaitForEvent): on 64-bit Darwin,
- pthread_cond_timedwait() appears to have a bug that causes it to wait
- forever when passed an absolute time which has already been exceeded
- by the system time; as a workaround, when given a very brief timeout,
- just do a poll on that platform. [Bug 1457797]
+ * generic/tclBasic.c (DeleteInterpProc,TclArgumentBCEnter,
+ (TclArgumentBCRelease, TclArgumentGet):
+ * generic/tclCompile.c (EnterCmdWordIndex, TclCleanupByteCode,
+ (TclInitCompileEnv, TclCompileScript):
+ * generic/tclCompile.h (ExtCmdLoc):
+ * generic/tclExecute.c (TclExecuteByteCode):
+ * generic/tclInt.h (ExtIndex, CFWordBC):
+ * tests/info.test (info-39.0):
- * unix/tclUnixPort.h (Darwin): override potentially faulty configure
- detection of termios availability in all cases, since termios is known
- to be present on all Mac OS X releases since 10.0. [Bug 497147]
+ Backport of some changes made to the Tcl head, to handle literal
+ sharing better. The code here is much simpler (trimmed down) compared
+ to the head as the 8.5 branch is not bytecode compiling whole files,
+ and doesn't compile eval'd code either.
-2006-08-18 Daniel Steffen <das@users.sourceforge.net>
+ Reworked the handling of literal command arguments in bytecode to be
+ saved (compiler) and used (execution) per command (see the
+ TCL_INVOKE_STK* instructions), and not per the whole bytecode. This
+ removes the problems with location data caused by literal sharing in
+ proc bodies. Simplified the associated datastructures (ExtIndex is
+ gone, as is the function EnterCmdWordIndex).
- * unix/tcl.m4 (Darwin): add support for --enable-64bit on x86_64, for
- universal builds including x86_64, for 64-bit CoreFoundation on
- Leopard and for use of -mmacosx-version-min instead of
- MACOSX_DEPLOYMENT_TARGET.
- * unix/configure: autoconf-2.13
+2009-07-01 Pat Thoyts <patthoyts@users.sourceforge.net>
- * generic/tcl.h: add fixes for building on Leopard and support
- * unix/tclUnixPort.h: for 64-bit CoreFoundation on Leopard.
+ * win/tclWinInt.h: [Bug 2806622]: Handle the GetUserName API call
+ * win/tclWin32Dll.c: via the tclWinProcs indirection structure. This
+ * win/tclWinInit.c: fixes a problem obtaining the username when the
+ USERNAME environment variable is unset.
- * unix/tclUnixPort.h: on Darwin x86_64, disable use of vfork as it
- causes execve to fail intermittently. (rdar://4685553)
-
- * macosx/README: updates for x86_64 support and Xcode 2.4.
+2009-06-15 Don Porter <dgp@users.sourceforge.net>
- * unix/tclUnixChan.c (TclUnixWaitForFile): with timeout < 0, if
- select() returns early (e.g. due to a signal), call it again instead
- of returning a timeout result. Fixes intermittent event-13.8 failures.
+ * generic/tclStringObj.c: sprintf() -> Tcl_ObjPrintf() conversion.
-2006-08-09 Don Porter <dgp@users.sourceforge.net>
+2009-06-13 Don Porter <dgp@users.sourceforge.net>
- * generic/tclEncoding.c: Replace buffer copy in for loop with
- call to memcpy(). Thanks to afredd. [Patch 1530262]
+ * generic/tclCompile.c: The value stashed in iPtr->compiledProcPtr
+ * generic/tclProc.c: when compiling a proc survives too long. We
+ * tests/execute.test: only need it there long enough for the right
+ TclInitCompileEnv() call to re-stash it into envPtr->procPtr. Once
+ that is done, the CompileEnv controls. If we let the value of
+ iPtr->compiledProcPtr linger, though, then any other bytecode compile
+ operation that takes place will also have its CompileEnv initialized
+ with it, and that's not correct. The value is meant to control the
+ compile of the proc body only, not other compile tasks that happen
+ along. Thanks to Carlos Tasada for discovering and reporting the
+ problem. [Bug 2802881].
-2006-08-03 Daniel Steffen <das@users.sourceforge.net>
+2009-06-10 Don Porter <dgp@users.sourceforge.net>
- * unix/tclUnixPipe.c (TclpCreateProcess): for USE_VFORK: ensure
- standard channels are initialized before vfork() so that the child
- doesn't potentially corrupt global state in the parent's address
- space.
+ * generic/tclStringObj.c: Revised [format] to not overflow the
+ integer calculations computing the length of the %ll formats of
+ really big integers. Also added protections so that [format]s that
+ would produce results overflowing the maximum string length of Tcl
+ values throw a normal Tcl error instead of a panic. [Bug 2801413]
-2006-07-30 Kevin Kenny <kennykb@acm.org>
+2006-06-09 Kevin B. Kenny <kennykb@acm.org>
- * tests/clock.test: Allowed UTC as a synonym for GMT in two tests that
- indirectly invoke 'strftime' with the result of 'gmtime' to fix a
- bogus test failure on FreeBSD systems. [Bug 1513489]
-
-2006-07-30 Joe English <jenglish@users.sourceforge.net>
+ * generic/tclGetDate.y: Fixed a thread safety bug in the generated
+ * library/clock.tcl: Bison parser (needed a %pure-parser
+ * tests/clock.test: declaration to avoid static variables).
+ Discovered that the %pure-parser declaration
+ allowed for returning the Bison error message
+ to the Tcl caller in the event of a syntax
+ error, so did so.
+ * generic/tclDate.c: bison 2.3
- * doc/AppInit.3: Fix typo [Bug 1496886]
+2006-06-08 Kevin B. Kenny <kennykb@acm.org>
-2006-07-20 Daniel Steffen <das@users.sourceforge.net>
+ * library/tzdata/Asia/Dhaka: New DST rule for Bangladesh.
+ (Olson's tzdata2009i.)
- * macosx/tclMacOSXNotify.c (Tcl_InitNotifier, Tcl_WaitForEvent):
- create notifier thread lazily upon first call to Tcl_WaitForEvent()
- rather than in Tcl_InitNotifier(). Allows calling exeve() in processes
- where the event loop has not yet been run (Darwin's execve() fails in
- processes with more than one thread), in particular allows embedders
- to call fork() followed by execve(), previously the pthread_atfork()
- child handler's call to Tcl_InitNotifier() would immediately recreate
- the notifier thread in the child after a fork.
+2009-06-02 Don Porter <dgp@users.sourceforge.net>
- * macosx/tclMacOSXNotify.c (Tcl_InitNotifier): add support for
- * unix/tclUnixFCmd.c (DoRenameFile, CopyFileAtts): weakly importing
- * unix/tclUnixInit.c (TclpSetInitialEncodings): symbols not
- available on OSX 10.2 or 10.3, enables binaires built on later OSX
- versions to run on earlier ones.
- * macosx/README: document how to enable weak-linking; cleanup.
- * unix/tclUnixPort.h: add support for weak-linking; conditionalize
- AvailabilityMacros.h inclusion; only disable realpath on 10.2 or
- earlier when threads are enabled.
- * unix/tclLoadDyld.c (TclpLoadMemoryGetBuffer): change runtime Darwin
- * unix/tclUnixInit.c (TclpInitPlatform): release check to use
- global initialized once
- * unix/tclUnixFCmd.c (DoRenameFile, TclpObjNormalizePath): add runtime
- Darwin release check to determine if realpath is threadsafe.
- * unix/configure.in: add check on Darwin for compiler support of weak
- * unix/tcl.m4: import and for AvailabilityMacros.h header; move
- Darwin specific checks & defines that are only relevant to the tcl
- build out of tcl.m4; restrict framework option to Darwin; cleanup
- quoting.
- * unix/configure: autoconf-2.13
+ * generic/tclExecute.c: Replace dynamically-initialized table with
+ a table of static constants in the lookup table for exponent operator
+ computations that fit in a 64 bit integer result.
- * unix/tclLoadDyld.c (TclpLoadMemory):
- * unix/tclUnixPipe.c (TclpCreateProcess): fix signed-with-unsigned
- comparison and other warnings from gcc4 -Wextra.
+ * generic/tclExecute.c: Corrected implementations and selection
+ logic of the INST_EXPON instruction to fix [Bug 2798543].
-2006-07-13 Andreas Kupries <andreask@activestate.com>
+2009-06-01 Don Porter <dgp@users.sourceforge.net>
- * unix/tclUnixPort.h: Added the inclusion of <AvailabilityMacros.h>.
- The missing header caused the upcoming #if conditions to wrongly
- exclude realpath, causing file normalize to ignore symbolic links in
- the path.
+ * tests/expr.test: Added many tests demonstrating the broken
+ cases of [Bug 2798543].
-2006-07-11 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+2009-05-30 Kevin B. Kenny <kennykb@acm.org>
- * generic/tclAsync.c: Made Tcl_AsyncDelete() more tolerant when called
- after all thread TSD has been garbage-collected.
+ * library/tzdata/Africa/Cairo:
+ * library/tzdata/Asia/Amman: Olson's tzdata2009h.
-2006-07-10 Jeff Hobbs <jeffh@ActiveState.com>
+2009-05-29 Andreas Kupries <andreask@activestate.com>
- * generic/tclIO.c (Tcl_CreateChannel): allow Tcl std channel
- inheritance to be #defined out (default remains in).
+ * library/platform/platform.tcl: Fixed handling of cpu ia64,
+ * library/platform/pkgIndex.tcl: taking ia64_32 into account
+ * unix/Makefile.in: now. Bumped version to 1.0.5. Updated the
+ * win/Makefile.in: installation commands.
-2006-06-15 Don Porter <dgp@users.sourceforge.net>
+2009-05-07 Miguel Sofer <msofer@users.sf.net>
- * changes: changes to start prep for an 8.4.14 release.
+ * generic/tclObj.c (Tcl_GetCommandFromObj): fix for bug [2785893],
+ insure that a command in a deleted namespace cannot be found
+ through a cached name.
-2006-06-14 Daniel Steffen <das@users.sourceforge.net>
+2009-05-06 Don Porter <dgp@users.sourceforge.net>
- * unix/tclUnixPort.h (Darwin): support for MAC_OS_X_VERSION_MAX_ALLOWED
- define from AvailabilityMacros.h: override configure detection and only
- use API available in the indicated OS version or earlier.
+ * generic/tclCmdMZ.c: Improve overflow error message from
+ [string repeat]. [Bug 2582327]
-2006-06-14 Pat Thoyts <patthoyts@users.sourceforge.net>
+2009-04-28 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/regerror.c: Enable building Tcl with Microsoft's latest
- * generic/tcl.h: compiler offering (VS2005). We have to handle
- * generic/tclDate.c: a number of oddities as they have deprecated
- * tests/env.test: most of the standard C library and now
- * win/makefile.vc: generate manifest files to be linked into the
- * win/nmakehlp.c: binaries. [Bug 1424909]
- * win/rules.vc:
- * win/tclWinTime.c:
+ * unix/tcl.m4, unix/configure (SC_CONFIG_CFLAGS): harden the check
+ to add _r to CC on AIX with threads.
-2006-06-13 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+2009-04-27 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
- * unix/tclLoadDl.c (TclpDlopen): Workaround for a compiler bug in Sun
- Forte 6. [Bug 1503729]
+ * generic/tclInt.h: Backport fix for [Bug 1028264]: WSACleanup() too early.
+ * generic/tclEvent.c: The fix introduces "late exit handlers"
+ * win/tclWinSock.c: for similar late process-wide cleanups.
-2006-06-06 Don Porter <dgp@users.sourceforge.net>
+2009-04-27 Alexandre Ferrieux <ferrieux@users.sourceforge.net>
- * doc/GetStdChan.3: Added recommendation that each call to
- Tcl_SetStdChannel() be accompanied by a call to Tcl_RegisterChannel().
+ * win/tclWinSock.c: Backport fix for [Bug 2446662]: resync Win
+ behavior on RST with that of unix (EOF).
-2006-05-31 Jeff Hobbs <jeffh@ActiveState.com>
+2009-04-27 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclNamesp.c (NamespaceInscopeCmd): revert [Bug 1400572]
- fix of 2006-01-09 for [namespace inscope] as it seems to mess with
- itcl scope decoding. Leaving namespace-29.6 test failure until final
- cause it determined.
+ * doc/concat.n (EXAMPLES): [Bug 2780680]: Rewrote so that the spacing
+ of result messages is correct. (The exact way they were wrong was
+ different when rendered through groff or as HTML, but it was still
+ wrong both ways.)
-2006-05-29 Jeff Hobbs <jeffh@ActiveState.com>
+2009-04-24 Stuart Cassoff <stwo@users.sf.net>
- * generic/tcl.h (Tcl_DecrRefCount): use if/else construct to allow
- placement in unbraced outer if/else conditions. (jcw)
+ * unix/Makefile.in: [Patch 2769530]: Don't chmod/exec installManPage.
-2006-05-27 Daniel Steffen <das@users.sourceforge.net>
+2009-04-15 Don Porter <dgp@users.sourceforge.net>
- * macosx/tclMacOSXNotify.c: implemented pthread_atfork() handler that
- * unix/tcl.m4 (Darwin): recreates CoreFoundation state and notifier
- thread in the child after a fork(). Note that pthread_atfork() is
- available starting with Tiger only. Because vfork() is used by the core
- on Darwin, [exec]/[open] are not affected by this fix, only extensions
- or embedders that call fork() directly (such as TclX). However, this
- only makes fork() safe from corefoundation tcl with --disable-threads;
- as on all platforms, forked children may deadlock in threaded tcl due
- to the potential for stale locked mutexes in the child. [Patch 923072]
- * unix/configure: autoconf-2.59
+ *** 8.5.7 TAGGED FOR RELEASE ***
-2006-05-24 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+ * generic/tclStringObj.c: AppendUnicodeToUnicodeRep failed
+ to set stringPtr->allocated to 0, leading to crashes.
- * unix/tcl.m4 (SC_CONFIG_SYSTEM): Fixed quoting of command script to
- awk; it was a rarely used branch, but it was wrong. [Bug 1494160]
+ * changes: Update for 8.5.7 release.
-2006-05-13 Don Porter <dgp@users.sourceforge.net>
+2009-04-14 Stuart Cassoff <stwo@users.sourceforge.net>
- * generic/tclFileName.c (TclDoGlob): Disabled the partial
- normalization done by the recursive glob routine, since changing the
- precise string of the pathname broke [glob] on some Tcl_Filesystems.
- [Bug 943995]
+ * unix/tcl.m4: Removed -Wno-implicit-int from CFLAGS_WARNING.
- * generic/tclProc.c (ProcCompileProc): When a bump of the compile
- epoch forces the re-compile of a proc body, take care not to
- overwrite any Proc struct that may be referred to on the active
- call stack. This fixes [Bug 1482718]. Note that the fix will not be
- effective for code that calls the private routine TclProcCompileProc()
- directly.
+2008-04-14 Kevin B. Kenny <kennykb@acm.org>
-2006-05-05 Don Porter <dgp@users.sourceforge.net>
+ * library/tzdata/Asia/Karachi: Updated rules for Pakistan Summer
+ Time (Olson's tzdata2009f)
- * generic/tclMain.c (Tcl_Main): Corrected flaw that required
- * tests/main.test: (Tcl_Main-4.5): processing of one interactive
- command before passing control to the loop routine registered with
- Tcl_SetMainLoop() [Bug 1481986]
+2009-04-10 Don Porter <dgp@users.sourceforge.net>
-2006-05-04 Don Porter <dgp@users.sourceforge.net>
+ * changes: Update for 8.5.7 release.
- * README: Bump version number to 8.4.14
- * generic/tcl.h:
+ * generic/tcl.h: Bump to 8.5.7 for release.
+ * library/init.tcl:
* tools/tcl.wse.in:
* unix/configure.in:
* unix/tcl.spec:
- * win/README.binary:
* win/configure.in:
+ * README:
- * unix/configure: autoconf-2.13
+ * unix/configure: autoconf-2.59
* win/configure:
- * generic/tclExecute.c (ExprSrandFunc): Restore acceptance of wide
- * tests/expr-old.test: integer values by srand() [Bug 1480509]
+ * generic/tclStringObj.c (UpdateStringOfString): Fix bug detected
+ by compiler warning about undefined "dst".
-2006-04-12 Don Porter <dgp@users.sourceforge.net>
+ * tests/httpd: Backport new tests for http 2.7.3.
+ * tests/http.tcl:
- *** 8.4.13 TAGGED FOR RELEASE ***
+2009-04-10 Daniel Steffen <das@users.sourceforge.net>
- * changes: updates for another RC.
+ * unix/tclUnixChan.c: TclUnixWaitForFile(): use FD_* macros
+ * macosx/tclMacOSXNotify.c: to manipulate select masks (Cassoff).
+ [Bug 1960647]
-2006-04-11 Don Porter <dgp@users.sourceforge.net>
+ * unix/tclLoadDyld.c: use RTLD_GLOBAL instead of RTLD_LOCAL.
+ [Bug 1961211]
- * generic/tclCmdMZ.c: Stop some interference between enter traces
- * tests/trace.test: and enterstep traces. [Bug 1458266]
+ * macosx/tclMacOSXNotify.c: revise CoreFoundation notifier to allow
+ embedding into applications that
+ already have a CFRunLoop running and
+ want to run the tcl event loop via
+ Tcl_ServiceModeHook(TCL_SERVICE_ALL).
-2006-04-10 Don Porter <dgp@users.sourceforge.net>
+ * macosx/tclMacOSXNotify.c: add CFRunLoop based Tcl_Sleep() and
+ * unix/tclUnixChan.c: TclUnixWaitForFile() implementations
+ * unix/tclUnixEvent.c: and disable select() based ones in
+ CoreFoundation builds.
- * changes: updates for another RC.
+ * unix/tclUnixNotify.c: simplify, sync with tclMacOSXNotify.c.
-2006-04-06 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclInt.decls: add TclMacOSXNotifierAddRunLoopMode()
+ * generic/tclIntPlatDecls.h: internal API, regen.
+ * generic/tclStubInit.c:
- * generic/tclRegexp.c (FinalizeRegexp): full reset data to indicate
- readiness for reinitialization.
+ * unix/configure.in (Darwin): use Darwin SUSv3 extensions if
+ available; remove /Network locations
+ from default tcl package search path
+ (NFS mounted locations and thus slow).
+ * unix/configure: autoconf-2.59
+ * unix/tclConfig.h.in: autoheader-2.59
-2006-04-06 Don Porter <dgp@users.sourceforge.net>
+ * macosx/tclMacOSXBundle.c: on Mac OS X 10.4 and later, replace
+ deprecated NSModule API by dlfcn API.
- * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct): It seems there
- * tests/indexObj.test: are extensions that rely on the prior behavior
- * doc/GetIndex.3: that the empty string cannot succeed as a
- unique prefix matcher, so I'm restoring Donal Fellows's solution.
- Added mention of this detail to the documentation. [Bug 1464039]
+2009-04-09 Kevin B. Kenny <kennykb@acm.org>
-2006-04-06 Daniel Steffen <das@users.sourceforge.net>
+ * tools/tclZIC.tcl: Always emit Unix-style line terminators.
+ * library/tzdata: Olson's tzdata2009e.
- * unix/tcl.m4: removed TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
- define on Darwin. [Bug 1457515]
- * unix/configure: autoconf-2.13
+2009-04-09 Don Porter <dgp@users.sourceforge.net>
-2006-04-05 Don Porter <dgp@users.sourceforge.net>
-
- * library/reg/pkgIndex.tcl: Long overlooked bump to registry
- * win/tclWinReg.c: package version 1.1.4 (should have
- been done for the Tcl 8.4.8 release!)
-
- * library/dde/pkgIndex.tcl: Long overlooked bump to dde package
- * win/tclWinDde.c: version 1.2.4 (should have been done
- for the Tcl 8.4.8 release!)
-
-2006-04-05 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * library/http/http.tcl: Backport http 2.7.3 from HEAD for
+ * library/http/pkgIndex.tcl: bundling with the Tcl 8.5.7 release.
+ * unix/Makefile.in:
+ * win/Makefile.in:
- * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct): Allow empty
- strings to be matched by the Tcl_GetIndexFromObj machinery, in the
- same manner as any other key. [Bug 1464039]
+2009-04-08 Andreas Kupries <andreask@activestate.com>
-2006-04-04 Don Porter <dgp@users.sourceforge.net>
+ * library/platform/platform.tcl: Extended the darwin sections to
+ * library/platform/pkgIndex.tcl: add a kernel version number to
+ * unix/Makefile.in: the identifier for anything from Leopard (10.5)
+ * win/Makefile.in: on up. Extended patterns for same. Extended cpu
+ * doc/platform.n: recognition for 64bit Tcl running on a 32bit
+ kernel on a 64bit processor (By Daniel Steffen). Bumped version to
+ 1.0.4. Updated Makefiles.
- * generic/tclPkg.c: Revised Bug 1162286 fix from 2005-11-08 to be
- * tests/pkg.test: even more forgiving of package version
- mismatch errors in [package ifneeded] commands, not even logging any
- warning messages. This further reduces the
- ***POTENTIAL INCOMPATIBILITY*** noted for that change.
+2009-04-08 Don Porter <dgp@users.sourceforge.net>
-2006-04-03 Andreas Kupries <andreask@activestate.com>
+ * library/tcltest/tcltest.tcl: Converted [eval]s (some unsafe!) to
+ * library/tcltest/pkgIndex.tcl: {*} in tcltest package. [Bug 2570363]
+ * unix/Makefile.in: => tcltest 2.3.1
+ * win/Makefile.in:
- * generic/tclIO.c (ReadChars): Added check, panic and commentary to a
- piece of code which relies on BUFFER_PADDING to create enough space at
- the beginning of each buffer for the insertion of partial multibyte
- data at the beginning of a buffer. Commentary explains why this code
- is OK, and the panic is as a precaution if someone twiddled the
- BUFFER_PADDING into uselessness.
+2009-04-07 Don Porter <dgp@users.sourceforge.net>
- * generic/tclIO.c (ReadChars): Temporarily suppress the use of
- TCL_ENCODING_END set when EOF was reached while the buffer we are
- converting is not truly the last buffer in the queue. Together with
- the Utf bug below it was possible to completely wreck the buffer data
- structures, eventually crashing Tcl. [Bug 1462248]
+ * generic/tclStringObj.c: Completed backports of fixes for
+ [Bug 2494093] and [Bug 2553906].
- * generic/tclEncoding.c (UtfToUtfProc): Stop accessing memory beyond
- the end of the input buffer when TCL_ENCODING_END is set and the last
- bytes of the buffer start a multi-byte sequence. This bug contributed
- to [Bug 1462248].
+2009-03-30 Don Porter <dgp@users.sourceforge.net>
-2006-03-28 Jeff Hobbs <jeffh@ActiveState.com>
+ * doc/Alloc.3: Size argument is "unsigned int". [Bug 2556263]
- * win/configure, win/tcl.m4: define MACHINE for gcc builds as well.
- Needed by Tk for manifest generation.
+ * generic/tclStringObj.c: Added protections from invalid memory
+ * generic/tclTestObj.c: accesses when we append (some part of)
+ * tests/stringObj.test: a Tcl_Obj to itself. Added the
+ appendself and appendself2 subcommands to the [teststringobj] testing
+ command and added tests to the test suite. [Bug 2603158]
- * win/tclWinConsole.c: revert 2005-11-03 [Patch 1256872] change to add
- win32 unicode console support as it broke the ability to modify the
- encoding to the console.
+2009-03-27 Don Porter <dgp@users.sourceforge.net>
-2006-03-28 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tclPathObj.c (TclPathPart): TclPathPart() was computing
+ * tests/fileName.test: the wrong results for both [file dirname] and
+ [file tail] on "path" arguments with the PATHFLAGS != 0 intrep and
+ with an empty string for the "joined-on" part. [Bug 2710920]
- * unix/tclUnixFCmd.c (TclpObjNormalizePath): deal with *BSD/Darwin
- realpath() converting relative paths into absolute paths. [Bug 1064247]
+2009-03-20 Don Porter <dgp@users.sourceforge.net>
-2006-03-28 Vince Darley <vincentdarley@sourceforge.net>
+ * generic/tclStringObj.c: Test stringObj-6.9 checks that
+ * tests/stringObj.test: Tcl_AppendStringsToObj() no longer
+ crashes when operating on a pure unicode value. [Bug 2597185]
- * generic/tclIOUtil.c: fix to nativeFilesystemRecord comparisons
- (lesser part of [Bug 1064247])
+ * generic/tclExecute.c (INST_CONCAT1): Panic when appends overflow
+ the max length of a Tcl value. [Bug 2669109]
-2006-03-27 Pat Thoyts <patthoyts@users.sourceforge.net>
+2009-03-18 Don Porter <dgp@users.sourceforge.net>
- * win/tclWinTest.c: Fixes for [Bug 1456373] (mingw-gcc issue)
+ * win/tclWinFile.c (TclpObjNormalizePath): Corrected Tcl_Obj leak.
+ Thanks to Joe Mistachkin for detection and patch. [Bug 2688184].
-2006-03-23 Don Porter <dgp@users.sourceforge.net>
+2009-03-15 Donal K. Fellows <dkf@users.sf.net>
- * tests/expr.test: Nan self-inquality test silenced. [Bug 761471]
+ * generic/tclPosixStr.c (Tcl_SignalId,Tcl_SignalMsg): [Patch 1513655]:
+ Added support for SIGINFO, which is present on BSD platforms.
-2006-03-22 Don Porter <dgp@users.sourceforge.net>
+2009-02-20 Don Porter <dgp@users.sourceforge.net>
- * changes: updates for another RC.
+ * generic/tclPathObj.c: Fixed mistaken logic in TclFSGetPathType()
+ * tests/fileName.test: that assumed (not "absolute" => "relative").
+ This is a false assumption on Windows, where "volumerelative" is
+ another possibility. [Bug 2571597].
-2006-03-18 Vince Darley <vincentdarley@sourceforge.net>
+2009-02-17 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/tclTest.c:
- * win/tclWinFile.c:
- * win/tclWinTest.c:
- * tests/fCmd.test:
- * tests/winFCmd.test:
- * tests/tcltest.test: Backport of [file writable] fixes for Windows
- from HEAD. [Bug 1193497]
+ * win/tcl.m4, win/configure: Check if cl groks _WIN64 already to
+ avoid CC manipulation that can screw up later configure checks.
+ Use 'd'ebug runtime in 64-bit builds.
-2006-03-16 Andreas Kupries <andreask@activestate.com>
+2009-02-05 Don Porter <dgp@users.sourceforge.net>
- * doc/open.n: Documented the changed behaviour of 'a'ppend mode.
-
- * tests/io.test (io-43.1 io-44.[1234]): Rewritten to be
- self-contained with regard to setup and cleanup. [Bug 681793]
+ * generic/tclStringObj.c: Added overflow protections to the
+ AppendUtfToUtfRep routine to either avoid invalid arguments and
+ crashes, or to replace them with controlled panics. [Bug 2561794]
- * generic/tclIOUtil.c (TclGetOpenMode): Added the flag O_APPEND to the
- list of POSIX modes used when opening a file for 'a'ppend. This
- enables the proper automatic seek-to-end-on-write by the OS. See [Bug
- 680143] for longer discussion.
+2009-02-04 Don Porter <dgp@users.sourceforge.net>
- * tests/ioCmd.test (iocmd-13.7.*): Extended the testsuite to check the
- new handling of 'a'.
+ * generic/tclStringObj.c (SetUnicodeObj): Corrected failure of
+ Tcl_SetUnicodeObj() to panic on a shared object. [Bug 2561488]. Also
+ factored out common code to reduce duplication.
-2006-03-15 Andreas Kupries <andreask@activestate.com>
+ * generic/tclCmdMZ.c: Prevent crashes due to int overflow of the
+ length of the result of [string repeat]. [Bug 2561746]
- * tests/socket.test: Extended the timeout in socket-11.11 from 10 to
- 40 seconds to allow for really slow machines. Also extended
- actual/expected results with value of variable 'done' to make it
- clearer when a test fails due to a timeout. [Bug 792159]
+2009-01-29 Donal K. Fellows <dkf@users.sf.net>
-2006-03-14 Andreas Kupries <andreask@activestate.com>
+ * generic/tclNamesp.c (Tcl_FindCommand): [Bug 2519474]: Ensure that
+ the path is not searched when the TCL_NAMESPACE_ONLY flag is given.
- * generic/tclPipe.c (TclCreatePipeline): Modified the processing of
- pipebars to fail if the last bar is followed only by redirections.
- [Bug 768659]
+2009-01-22 Kevin B. Kenny <kennykb@acm.org>
-2006-03-14 Andreas Kupries <andreask@activestate.com>
+ * unix/tcl.m4: Corrected a typo ($(SHLIB_VERSION) should be
+ ${SHLIB_VERSION}).
+ * unix/configure: Autoconf 2.59
- * doc/fconfigure.n: Clarified that -translation is binary is reported
- as lf when queried, because it is identical to lf, except for the
- special additional behaviour when setting it. [Bug 666770]
+2009-01-21 Andreas Kupries <andreask@activestate.com>
-2006-03-14 Andreas Kupries <andreask@activestate.com>
+ * generic/tclIORChan.c (ReflectClose): Fix for [Bug 2458202].
+ Closing a channel may supply NULL for the 'interp'. Test for
+ finalization needs to be different, and one place has to pull the
+ interp out of the channel instead.
- * win/tclWinPipe.c (Tcl_WaitPid): Backport of fix made to the head by
- David Gravereaux in 2004. See ChangeLog entry 2004-01-19. [Bug 1381436]
+2009-01-19 Kevin B. Kenny <kennykb@acm.org>
- Fixed a thread-safety problem with the process list. The delayed cut
- operation after the wait was going stale by being outside the list
- lock. It now cuts within the lock and does a locked splice for when it
- needs to instead. [Bug 859820]
+ * unix/Makefile.in: Added a CONFIG_INSTALL_DIR parameter so that
+ * unix/tcl.m4: distributors can control where tclConfig.sh goes.
+ Made the installation of 'ldAix' conditional
+ upon actually being on an AIX system. Allowed for downstream
+ packagers to customize SHLIB_VERSION on BSD-derived systems.
+ Thanks to Stuart Cassoff for [Patch 907924].
+ * unix/configure: Autoconf 2.59
-2006-03-13 Don Porter <dgp@users.sourceforge.net>
+2009-01-09 Don Porter <dgp@users.sourceforge.net>
- * generic/tclEncoding.c: Report error when an escape encoding
- is missing one of its sub-encodings [Bug 506653]
+ * generic/tclStringObj.c (STRING_SIZE): Corrected failure to limit
+ memory allocation requests to the sizes that can be supported by
+ Tcl's memory allocation routines. [Bug 2494093].
- * unix/configure.in: Revert change from 2005-07-26 that sometimes
- * unix/configure: added $prefix/share to the tcl_pkgPath.
- See [Patch 1231015]. autoconf-2.13.
+2009-01-08 Don Porter <dgp@users.sourceforge.net>
-2006-03-10 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+ * generic/tclStringObj.c (STRING_UALLOC): Added missing parens
+ required to get correct results out of things like
+ STRING_UALLOC(num + append). [Bug 2494093].
- -- Summary of changes fixing [Bug 1437595] --
+2009-01-06 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclEvent.c: Cosmetic touches and identation
- * generic/tclInt.h: Added TclpFinalizeSockets() call.
+ * generic/tclDictObj.c (DictIncrCmd): Corrected twiddling in internals
+ of dictionaries so that literals can't get destroyed.
- * generic/tclIO.c: Calls TclpFinalizeSockets() as part of the
- TclFinalizeIOSubsystem().
+ * tests/expr.test, tests/string.test: Eliminate non-ASCII characters.
+ [Bugs 2006884, 2006879]
- * unix/tclUnixSock: Added no-op TclpFinalizeSockets().
-
- * mac/tclMacSock.c:
- * win/tclWinPipe.c
- * win/tclWinSock.c: Finalization of the sockets/pipes is now solely
- done in TclpFinalizeSockets() and TclpFinalizePipes() and not over the
- thread-exit handler, because the order of actions the Tcl generic core
- will impose may result in cores/hangs if the thread exit handler tears
- down corresponding subsystem(s) too early.
+2009-01-03 Kevin B. Kenny <kennykb@acm.org>:
-2006-03-10 Vince Darley <vincentdarley@sourceforge.net>
+ * library/clock.tcl (tcl::clock::add): Fixed error message formatting
+ in the case where [clock add] is presented with a bad switch.
+ * tests/clock.test (clock-65.1) Added a test case for the above
+ problem [Bug 2481670].
- * win/tclWin32Dll.c:
- * win/tclWinInt.h:
- * win/tclWinFile.c: backported some fixes from HEAD relating to 'file
- readable' and 'file writable', but main 'file writable' bug still
- outstanding.
+2008-12-21 Don Porter <dgp@users.sourceforge.net>
-2006-03-07 Don Porter <dgp@users.sourceforge.net>
+ *** 8.5.6 TAGGED FOR RELEASE ***
- * README: Bump version number to 8.4.13 and update
- * changes: changes to start prep for an 8.4.13 release.
- * generic/tcl.h:
+ * generic/tcl.h: Bump to 8.5.6 for release.
+ * library/init.tcl:
* tools/tcl.wse.in:
- * unix/configure{.in}:
+ * unix/configure.in:
* unix/tcl.spec:
- * win/README.binary:
- * win/configure{.in}:
-
- * tests/parse.test: Missing constraint
-
-2006-03-06 Don Porter <dgp@users.sourceforge.net>
-
- * generic/tclBasic.c: Revised handling of TCL_EVAL_* flags to
- * tests/parse.test: simplify TclEvalObjvInternal and to correct
- the auto-loading of alias targets (parse-8.12). [Bug 1444291]
-
-2006-03-02 Jeff Hobbs <jeffh@ActiveState.com>
-
- * win/Makefile.in: convert _NATIVE paths to use / to avoid ".\"
- path-as-escape issue.
-
- * unix/tcl.m4, win/tcl.m4: []-quote ac_defun functions.
-
-2006-03-02 Pat Thoyts <patthoyts@users.sourceforge.net>
-
- * unix/tcl.m4: Fix for [Tk Bug 1334613] to sort out shared library
- * unix/configure: issues on NetBSD. Regenerated configure script.
-
-2006-02-28 Don Porter <dgp@users.sourceforge.net>
-
- * generic/tclBasic.c: Corrections to be sure that TCL_EVAL_GLOBAL
- * tests/parse.test: evaluations act the same as [uplevel #0]
- * tests/trace.test: evaluations, even when execution traces or
- invocations of [::unknown] are present. [Bug 1439836]
-
-2006-02-16 Don Porter <dgp@users.sourceforge.net>
-
- * generic/tclIndexObj.c: Disallow the "ambiguous" error message
- * tests/indexObj.test: when TCL_EXACT matching is requested.
-
-2006-02-15 Don Porter <dgp@users.sourceforge.net>
-
- * generic/tclIO.c: Made several routines tolerant of
- * generic/tclIOUtil.c: interp == NULL arguments. [Bug 1380662]
-
-2006-02-09 Don Porter <dgp@users.sourceforge.net>
-
- * tests/main.test (Tcl_Main-6.7): Improved robustness of command
- auto-completion test. [Bug 1422736]
-
-2006-01-25 Donal K. Fellows <donal.k.fellows@man.ac.uk>
-
- * unix/tclUnixInit.c (TclpInitPlatform): Improved conditions on when
- to update the FP rounding mode on FreeBSD, taken from FreeBSD port.
+ * win/configure.in:
+ * README:
-2006-01-23 Miguel Sofer <msofer@users.sf.net>
+ * unix/configure: autoconf-2.59
+ * win/configure:
- * generic/tclStringObj.c (Tcl_GetRange):
- * tests/stringTest (string-12.21):fixed incorrect handling of internal
- rep in Tcl_GetRange. Thanks to twylite and Peter Spjuth. [Bug 1410553]
+ * changes: Update for 8.5.6 release.
-2006-01-16 Reinhard Max <max@suse.de>
+ * library/tclIndex: Removed reference to no-longer-extant procedure
+ 'tclLdAout'.
+ * doc/library.n: Corrected mention of 'auto_exec' to 'auto_execok'.
+ [Patch 2114900] thanks to Stu Cassoff <stwo@users.sf.net>
+ Backport of 2008-11-26 commit from Kevin Kenny.
- * generic/tclPipe.c (FileForRedirect): Prevent nameString from being
- freed without having been initialized.
- * tests/exec.test: Added a test for the above.
-
-2006-01-12 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+ * win/tclWinThrd.c (TclpThreadCreate): We need to initialize the
+ thread id variable to 0 as on 64 bit windows this is a pointer sized
+ field while windows only fills it with a 32 bit value. The result is
+ an inability to join the threads as the ids cannot be matched.
+ Backport of 2008-10-13 commit from Pat Thoyts.
- * generic/tclIOUtil.c (Tcl_FSGetInternalRep): fixed potential
- overwriting of already freed memory which caused all kinds of (rare
- but reproducible) coredumps all over the place.
+2008-12-15 Donal K. Fellows <donal.k.fellows@man.ac.uk>
-2006-01-11 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclExecute.c (TEBC:INST_DICT_GET): Make sure that the result
+ is empty when generating an error message. [Bug 2431847]
- * tests/error.test (error-7.0): Test the timing of write traces on
- ::errorInfo. [Bug 1397843]
+2008-12-12 Jan Nijtmans <nijtmans@users.sf.net>
-2006-01-10 Daniel Steffen <das@users.sourceforge.net>
+ * library/clock.tcl (ProcessPosixTimeZone): Fix time change in Eastern
+ Europe (not 3:00 but 4:00 local time) [Bug 2207436]
- * unix/configure: add caching, use AC_CACHE_CHECK instead of
- * unix/configure.in: AC_CACHE_VAL where possible, consistent message
- * unix/tcl.m4: quoting, sync relevant tclconfig/tcl.m4 and HEAD
- changes and gratuitous formatting differences, fix SC_CONFIG_MANPAGES
- with default argument, Darwin improvements to SC_LOAD_*CONFIG.
-
-2006-01-09 Don Porter <dgp@users.sourceforge.net>
+2008-12-11 Andreas Kupries <andreask@activestate.com>
- * generic/tclNamesp.c (NamespaceInscopeCmd): [namespace inscope]
- * tests/namespace.test: commands were not reported by [info level].
- [Bug 1400572]
+ * generic/tclIO.c (SetChannelFromAny and related): Modified the
+ * tests/io.test: internal representation of the tclChannelType to
+ contain not only the ChannelState pointer, but also a reference to the
+ interpreter it was made in. Invalidate and recompute the internal
+ representation when it is used in a different interpreter (like
+ cmdName intrep's). Added testcase. [Bug 2407783]
-2005-12-20 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+2008-12-11 Jan Nijtmans <nijtmans@users.sf.net>
- * generic/tclThreadAlloc.c (Tcl_GetMemoryInfo): Format values as longs
- and not ints, so they are less likely to wrap on 64-bit machines.
+ * library/clock.tcl (ProcessPosixTimeZone): Fallback to European time
+ zone DST rules, when the timezone is between 0 and -12. [Bug 2207436]
+ * tests/clock.test (clock-52.[23]): Test cases.
-2005-12-19 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+2008-12-10 Kevin B. Kenny <kennykb@acm.org>
- * doc/Tcl.n: Clarify what is going on in variable substitution
- following thread on comp.lang.tcl.
+ * library/tzdata/*: Update from Olson's tzdata2008i.
-2005-12-14 Daniel Steffen <das@users.sourceforge.net>
+2008-12-04 Don Porter <dgp@users.sourceforge.net>
- * generic/tclIOUtil.c: workaround gcc warning "comparison is always
- * generic/tclTest.c: false due to limited range of data type".
+ * generic/tclPathObj.c (Tcl_FSGetNormalizedPath): Added another
+ flag value TCLPATH_NEEDNORM to mark those intreps which need more
+ complete normalization attention for correct results. [Bug 2385549]
- * unix/configure.in: run check for fts API on all platforms, since
- Linux glibc2 and *BSDs also have this and using fts is more efficient
- than recursive opendir/readdir (sync with HEAD).
- * unix/configure: regen.
+2008-12-03 Don Porter <dgp@users.sourceforge.net>
-2005-12-12 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclFileName.c (DoGlob): One of the Tcl_FSMatchInDirectory
+ calls did not have its return code checked. This caused error messages
+ returned by some Tcl_Filesystem drivers to be swallowed.
- * unix/tcl.m4, unix/configure: Fix sh quoting error reported in
- bash-3.1+ [Bug 1377619] (schafer)
+2008-12-02 Andreas Kupries <andreask@activestate.com>
-2005-12-12 Reinhard Max <max@suse.de>
+ * generic/tclIO.c (TclFinalizeIOSubsystem): Replaced Alexandre
+ Ferrieux's first patch for [Bug 2270477] with a gentler version, also
+ supplied by him.
- * generic/tclExecute.c (ExprAbsFunc): fixed the abs(MIN_INT) case so
- that it doesn't break on compilers that don't assume integers to wrap
- around (e.g. gcc-4.1.0).
+2008-12-01 Don Porter <dgp@users.sourceforge.net>
-2005-12-09 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+ * generic/tclParse.c: Backport fix for [Bug 2251175].
- * tests/lsearch.test (lsearch-10.8..10): If the -start is off the end,
- * generic/tclCmdIL.c (Tcl_LsearchObjCmd): searching should find
- nothing at all. [Bug 1374778]
+2008-11-30 Kevin B. Kenny <kennykb@acm.org>
-2005-12-05 Daniel Steffen <das@users.sourceforge.net>
+ * library/clock.tcl (format, ParseClockScanFormat): Added a [string
+ map] to get rid of namespace delimiters before caching a scan or
+ format procedure. [Bug 2362156]
+ * tests/clock.test (clock-64.[12]): Added test cases for the bug that
+ was tickled by a namespace delimiter inside a format string.
- *** 8.4.12 TAGGED FOR RELEASE ***
+2008-11-25 Andreas Kupries <andreask@activestate.com>
- * unix/tclUnixPort.h (Darwin): fix incorrect __DARWIN_UNIX03 configure
- overrides that were originally copied from Darwin CVS (rdar://3693001).
+ * generic/tclIO.c (TclFinalizeIOSubsystem): Applied Alexandre
+ Ferrieux's patch for [Bug 2270477] to prevent infinite looping during
+ finalization of channels not bound to interpreters.
-2005-12-05 Don Porter <dgp@users.sourceforge.net>
+2008-08-23 Andreas Kupries <andreask@activestate.com>
- * unix/configure.in: Revised fix for [Bug 1034337] from Daniel
- * unix/tclUnixFCmd.c: Steffen. Uses fts_*() routines.
- * unix/configure: autoconf-2.13
- * changes: Update changes for 8.4.12 release
+ * generic/tclIO.c: Backport of fix for [Bug 2333466].
-2005-12-04 Daniel Steffen <das@users.sourceforge.net>
+2008-11-18 Jan Nijtmans <nijtmans@users.sf.net>
- * README: refer to macosx/README instead of mac/README.
- * mac/README: add note that mac classic port is no longer supported.
+ * generic/tcl.decls: Fix signature and implementation of
+ * generic/tclDecls.h: Tcl_HashStats, such that it conforms
+ * generic/tclHash.c: to the documentation. [Bug 2308236]
+ * doc/Hash.3:
-2005-12-03 Jeff Hobbs <jeffh@ActiveState.com>
+2008-11-13 Jan Nijtmans <nijtmans@users.sf.net>
- * README: correct 2 urls
+ * generic/tclInt.h: Rename static function FSUnloadTempFile to
+ * generic/tclIOUtil.c: TclFSUnloadTempFile, needed in tclLoad.c
-2005-12-01 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclLoad.c: Fixed [Bug 2269431]: load of shared
+ objects leaves temporary files on windows
- * changes: Update changes for 8.4.12 release
+2008-11-10 Andreas Kupries <andreask@activestate.com>
-2005-12-01 Daniel Steffen <das@users.sourceforge.net>
+ * doc/platform_shell.n: Fixed [Bug 2255235], reported by Ulrich
+ * library/platform/pkgIndex.tcl: Ring <uring@users.sourceforge.net>.
+ * library/platform/shell.tcl: Updated the LOCATE command in the
+ * library/tm.tcl: package 'platform::shell' to handle the new form
+ * unix/Makefile.in: of 'provide' commands generated by tm.tcl. Bumped
+ * win/Makefile.in: package to version 1.1.4. Added cross-references
+ to the relevant parts of the code to avoid future desynchronization.
- * unix/tcl.m4 (Darwin): fixed error when MACOSX_DEPLOYMENT_TARGET unset
- * unix/configure: regen.
+2008-11-04 Jeff Hobbs <jeffh@ActiveState.com>
-2005-11-29 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclPort.h: remove the ../win/ header dir as the build system
+ already has it, and it confuses builds when used with private headers
+ installed.
- * win/tcl.m4: Add build support for Windows-x64 builds.
- * win/configure: --enable-64bit now accepts =amd64|ia64 for
- * win/Makefile.in: Windows 64-bit build variants (default: amd64)
- * win/makefile.vc: [Bug 1369597]
+2008-10-24 Pat Thoyts <patthoyts@users.sourceforge.net>
-2005-11-29 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * library/http/http.tcl: Backported a fix for reading HTTP-like
+ protocols that used to work and were broken with http 2.7. Now http
+ 2.7.2
- * generic/tclObj.c (Tcl_GetWideIntFromObj): Add more efficient
- conversion to wides from normal ints. [Bug 1310081]
+2008-10-23 Don Porter <dgp@users.sourceforge.net>
- * generic/tclCmdIL.c (Tcl_LsearchObjCmd): Allow [lsearch -regexp] to
- process REs that contain backreferences. This expensive mode of
- operation is only used if the RE would otherwise cause a compilation
- failure. [Bug 1366683]
+ * generic/tcl.h: Bump version number to 8.5.6b1 to distinguish
+ * library/init.tcl: CVS development snapshots from the 8.5.5 and
+ * unix/configure.in: 8.5.6 releases.
+ * unix/tcl.spec:
+ * win/configure.in:
+ * tools/tcl.wse.in:
+ * README
-2005-11-28 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * unix/configure: autoconf (2.59)
+ * win/configure:
- * win/tclWinSock.c (CreateSocket): Applied [Patch 1353853] to prevent
- reads of uninitialized variables during cleanup.
+2008-10-19 Don Porter <dgp@users.sourceforge.net>
-2005-11-27 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tclProc.c: Reset -level and -code values to defaults
+ after they are used. [Bug 2152286]
- * unix/tcl.m4 (Darwin): add 64bit support, check for Tiger copyfile(),
- add CFLAGS to SHLIB_LD to support passing -isysroot in env(CFLAGS) to
- configure (flag can't be present twice, so can't be in both CFLAGS and
- LDFLAGS during configure), don't use -prebind when deploying on 10.4,
- define TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING (rdar://3171542).
- (SC_ENABLE_LANGINFO, SC_TIME_HANDLER): add/fix caching, fix obsolete
- autoconf macros. Sync with tk/unix/tcl.m4, sync whitespace with HEAD.
+2008-10-16 Don Porter <dgp@users.sourceforge.net>
- * unix/configure.in: fix obsolete autoconf macros, sync gratuitous
- formatting/ordering differences with tk/unix/configure.in.
+ * library/init.tcl: Revised [unknown] so that it carefully
+ preserves the state of the ::errorInfo and ::errorCode variables at
+ the start of auto-loading and restores that state before the
+ autoloaded command is evaluated. [Bug 2140628]
- * unix/Makefile.in: add CFLAGS to tclsh/tcltest link to make
- executable linking the same as during configure (needed to avoid
- loosing any linker relevant flags in CFLAGS, in particular flags that
- can't be in LDFLAGS). Avoid concurrent linking of tclsh and compiling
- of tclTestInit.o or xtTestInit.o during parallel make.
- (checkstubs, checkdoc, checkexports): dependency and Darwin fixes
+2008-10-10 Don Porter <dgp@users.sourceforge.net>
- * unix/tclLoadDyld.c (TclpDlopen): [Bug 1204237] use
- NSADDIMAGE_OPTION_WITH_SEARCHING on second NSAddImage only.
- (TclGuessPackageName): should not be MODULE_SCOPE.
- (TclpLoadMemory): ppc64 and endian (i386) fixes, add support for
- loading universal (fat) bundles from memory.
+ *** 8.5.5 TAGGED FOR RELEASE ***
- * unix/tclUnixPort.h:
- * unix/tclUnixFCmd.c: add support for new Tiger copyfile() API to
- enable copying of xattrs & ACLs by [file copy].
+ * generic/tcl.h: Bump to 8.5.5 for release.
+ * library/init.tcl:
+ * tools/tcl.wse.in:
+ * unix/configure.in:
+ * unix/tcl.spec:
+ * win/configure.in:
- * generic/tcl.h: add Darwin specifc configure overrides for TCL_WIDE
- defines to support fat compiles of ppc and ppc64 at the same time,
- (replaces Darwin CVS fix by emoy, rdar://3693001).
- add/correct location of version numbers in macosx files.
+ * unix/configure: autoconf-2.59
+ * win/configure:
- * generic/tclInt.h: clarify fat compile comment.
+ * changes: Update for 8.5.5 release.
- * unix/tclUnixPort.h: add Darwin specifc configure overrides to
- support fat compiles, where configure runs only once for multiple
- architectures (replaces Darwin CVS fix by emoy, rdar://3693001).
+2008-10-08 Don Porter <dgp@users.sourceforge.net>
- * macosx/tclMacOSXBundle.c:
- * macosx/tclMacOSXNotify.c:
- * unix/tclUnixNotfy.c: fix #include order to support compile time
- * unix/tclUnixPort.h: override of HAVE_COREFOUNDATION in
- tclUnixPort.h when building for ppc64
+ * generic/tclTrace.c: Corrected handling of errors returned by
+ variable traces so that the errorInfo value contains the original
+ error message. [Bug 2151707]
- * macosx/Tcl.pbproj/default.pbxuser (new file):
- * macosx/Tcl.pbproj/jingham.pbxuser:
- * macosx/Tcl.pbproj/project.pbxproj: sync with HEAD.
+ * generic/tclVar.c: Revised implementation of TclObjVarErrMsg so
+ that error message construction does not disturb an existing
+ iPtr->errorInfo that may be in progress.
- * macosx/README: clarification/cleanup, sync with HEAD, document
- universal (fat) builds via CFLAGS (i.e. all of ppc ppc64 i386 at once).
+2008-10-06 Jan Nijtmans <nijtmans@users.sf.net>
- * macosx/Makefile: add support for reusing configure cache, build
- target fixes, remove GENERIC_FLAGS override now handled by tcl.m4.
+ * tclWinTest.c: Fix compiler warning when compiling this file with
+ mingw gcc:
+ tclWinTest.c:706: warning: dereferencing type-punned pointer will
+ break strict-aliasing rules
+ * generic/tclLoad.c: Make sure that any library which doesn't have an
+ unloadproc is only really unloaded when no library code is executed
+ yet. [Bug 2059262]
- * generic/tclIOUtil.c:
- * generic/tclRegexp.c:
- * generic/tclVar.c: declare globals used only in own file as static
- (sync with HEAD).
+2008-10-06 Joe Mistachkin <joe@mistachkin.com>
- * generic/rege_dfa.c (getvacant):
- * generic/regexec.c (cfind):
- * generic/tclCompExpr.c (CompileSubExpr):
- * unix/tclUnixChan.c (TclUnixWaitForFile): initialise variables to
- silence gcc 4 warnings.
+ * tools/man2tcl.c: Added missing line from patch by Harald Oehlmann.
+ [Bug 1934200]
- * generic/regguts.h: only #define NDEBUG if not already #defined.
+2008-10-05 Kevin B. Kenny <kennykb@acm.org>
- * macosx/tclMacOSXNotify.c: sync whitespace & comments with HEAD
+ * libtommath/bn_mp_sqrt.c (bn_mp_sqrt): Handle the case where a
+ * tests/expr.test (expr-47.13): number's square root is
+ between n<<DIGIT_BIT and n<<DIGIT_BIT+1. [Bug 2143288]
+ Thanks to Malcolm Boffey (malcolm.boffey@virgin.net) for the patch.
- * unix/configure: regen.
+2008-10-02 Joe Mistachkin <joe@mistachkin.com>
-2005-11-20 Joe English <jenglish@users.sourceforge.net>
+ * tools/man2help2.tcl: Integrated patches from Harald Oehlmann.
+ * tools/man2tcl.c: [Bug 1934200, 1934272]
- * generic/tclStubLib.c: Don't set tclStubsPtr to 0 when
- Tcl_PkgRequireEx() fails [Fix for [Bug 1091431] "Tcl_InitStubs failure
- crashes wish"]
+2008-09-27 Donal K. Fellows <donal.k.fellows@man.ac.uk>
-2005-11-18 Miguel Sofer <msofer@users.sf.net>
+ * generic/tclCmdIL.c (Tcl_LrepeatObjCmd): Improve the handling of the
+ case where the combination of number of elements and repeat count
+ causes the resulting list to be too large. [Bug 2130992]
- * tests/trace.test (trace-34.5): [Bug 1047286], added a second test
- illustrating the role of "ns in callStack" in the ns's visibility
- during deletion traces.
+2008-09-25 Don Porter <dgp@users.sourceforge.net>
- * generic/tclBasic.c (Tcl_DeleteCommandFromToken):
- * generic/tclCmdMZ.c (TraceCommandProc):
- * generic/tclInt.h (NS_KILLED):
- * generic/tclNamesp.c (Tcl_DeleteNamespace
- * tests/namespace.test (namespace-7.3-6):
- * tests/trace.test (trace-20.13-16): fix [Bugs 1355942/1355342].
+ * doc/global.n: Correct false claim about [info locals].
-2005-11-18 Jeff Hobbs <jeffh@ActiveState.com>
+2008-09-17 Don Porter <dgp@users.sourceforge.net>
- * generic/tclIO.c (TclFinalizeIOSubsystem): preserve statePtr until we
- netrieve next statePtr from it.
+ * generic/tclInt.h: Correct the TclGetLongFromObj,
+ TclGetIntFromObj, and TclGetIntForIndexM macros so that they
+ retrieve the internalRep.longValue field instead of casting the
+ internalRep.otherValuePtr field to type long.
-2005-11-18 Don Porter <dgp@users.sourceforge.net>
+2008-09-17 Miguel Sofer <msofer@users.sf.net>
- * generic/tclPkg.c: Revised Bug 1162286 fix from 2005-11-08 to be
- * tests/pkg.test: more forgiving of package version mismatch
- errors in [package ifneeded] commands. This reduces the
- ***POTENTIAL INCOMPATIBILITY*** noted for that change.
+ * library/init.tcl: export min and max commands from the mathfunc
+ namespace [Bug 2116053]
-2005-11-18 Andreas Kupries <andreask@activestate.com>
+2008-09-10 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * generic/tclIO.c (TclFinalizeIOSubsystem): Applied Pat Thoyts' patch
- for [Bug 1359094]. This moves the retrieval of the next channel state
- to the end of the loop, as the called closeproc may close other
- channels, i.e., modify the list we are iterating, invalidating any
- pointer retrieved earlier.
+ * generic/tclListObj.c (Tcl_ListObjGetElements): Make this list->dict
+ transformation - encountered when using [foreach] with dicts - not as
+ expensive as it was before. Spotted by Kieran Elby and reported on
+ tcl-core.
-2005-11-18 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+2008-09-07 Miguel Sofer <msofer@users.sf.net>
- * library/http/http.tcl (http::geturl): Improved syntactic validation
- of URLs, and better error messages in some cases. [Bug 1358369]
+ * doc/namespace.n: fix [Bug 2098441]
-2005-11-16 Don Porter <dgp@users.sourceforge.net>
+2008-08-28 Don Porter <dgp@users.sourceforge.net>
- * README: Bump version number to 8.4.12
- * generic/tcl.h:
- * tools/tcl.wse.in:
- * unix/configure.in:
+ * generic/tcl.h: Bump version number to 8.5.5b1 to distinguish
+ * library/init.tcl: CVS development snapshots from the 8.5.4 and
+ * unix/configure.in: 8.5.5 releases.
* unix/tcl.spec:
- * win/README.binary:
* win/configure.in:
+ * tools/tcl.wse.in:
+ * README
- * unix/configure: autoconf-2.13
+ * unix/configure: autoconf (2.59)
* win/configure:
-2005-11-15 Don Porter <dgp@users.sourceforge.net>
-
- * changes: Update changes for 8.4.12 release
-
-2005-11-15 Kevin B. Kenny <kennykb@acm.org>
-
- * tests/cmdAH.test: Backported the fix for [Bug 926016] because of
- * win/tclWinFile.c: a repeated bug report in 8.4 [Bug 1353840].
- Windows [file mtime] will now return seconds from the Posix epoch
- correctly (except for FAT32 file systems after a DST change without a
- reboot - for which there is no help). A side effect is that file times
- will appear different in Tcl from the way they do in Windows Explorer
- or a 'dir' listing, because the Microsoft tools get the DST state
- wrong in the listings.
-
-2005-11-09 Kevin B. Kenny <kennykb@acm.org>
-
- * generic/tclTimer.c: Changed [after] so that it behaves correctly
- * tests/timer.test: with negative arguments. [Bug 1350293]
-
-2005-11-08 Jeff Hobbs <jeffh@ActiveState.com>
-
- * unix/tclUnixFCmd.c (MAX_READDIR_UNLINK_THRESHOLD): reduce to 130
- based on errors seen on OS X 10.3 with lots of links in a dir. [Bug
- 1034337 followup]
-
-2005-11-08 Don Porter <dgp@users.sourceforge.net>
+2008-08-22 Don Porter <dgp@users.sourceforge.net>
- * tests/expr.test: Portable tests expr-46.13-18 [Bug 1341368]
+ * generic/tclUtil.c (TclReToGlob): Added missing set of the
+ *exactPtr value to really fix [Bug 2065115]. Also avoid possible
+ DString overflow.
+ * tests/regexpComp.test: Correct duplicate test names.
- * generic/tclPkg.c: Corrected inconsistencies in the value returned
- * tests/pkg.test: by Tcl_PkgRequire(Ex) so that the returned
- values will always agree with what is stored in the package database.
- This way repeated calls to Tcl_PkgRequire(Ex) have the same results.
- Thanks to Hemang Lavana. [Bug 1162286]
- ***POTENTIAL INCOMPATIBILITY***: Incompatible with those existing
- packages that are accustomed to the [package] command forgiving
- their bugs.
+2008-08-21 Jeff Hobbs <jeffh@ActiveState.com>
- * tests/namespace.test (25.7,8): Backport test of knownBug.
+ * tests/regexp.test, tests/regexpComp.test: correct re2glob ***=
+ * generic/tclUtil.c (TclReToGlob): translation from exact
+ to anywhere-in-string match. [Bug 2065115]
-2005-11-08 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+2008-08-20 Daniel Steffen <das@users.sourceforge.net>
- * generic/tclCmdMZ.c (TclTraceVariableObjCmd, TraceVarProc): Applied
- Miguel's fix for [Bug 1348775]. It is not quite as elegant as the one
- applied to the HEAD, but it is easier to use it rather than fully
- backporting.
+ * generic/tclTest.c (TestconcatobjCmd): fix use of internal-only
+ TclInvalidateStringRep macro.
+ [Bug 2057479]
-2005-11-07 Miguel Sofer <msofer@users.sf.net>
+2008-08-17 Miguel Sofer <msofer@users.sf.net>
- * tests/trace.test (trace-13.2-4): added tests to detect leak, see
- [Bug 1348775].
+ * generic/tclTest.c (TestconcatobjCmd):
+ * generic/tclUtil.c (Tcl_ConcatObj):
+ * tests/util.test (util-4.7):
+ fix [Bug 1447328]; the original "fix" turned Tcl_ConcatObj() into
+ a hairy monster. This was exposed by [Bug 2055782]. Additionally,
+ Tcl_ConcatObj could corrupt its input under certain conditions!
-2005-11-04 Don Porter <dgp@users.sourceforge.net>
+ *** NASTY BUG FIXED ***
- * unix/tcl.m4: Added code to enable [load] on LynxOS. Thanks to
- heidibr@users.sf.net for the patch. [Bug 1163896]
+2008-08-14 Don Porter <dgp@users.sourceforge.net>
- * unix/configure: autoconf-2.13.
+ *** 8.5.4 TAGGED FOR RELEASE ***
-2005-11-04 Pat Thoyts <patthoyts@users.sourceforge.net>
+ * tests/fileName.test: Revise new tests for portability to case
+ insensitive filesystems.
- * win/tclWinPipe.c: Applied [Patch 1267871] by Matt Newman which
- * win/tclWinPort.h: provides extended error code support.
- * tests/exec.test: Wrote some tests for this feature.
+2008-08-14 Daniel Steffen <das@users.sourceforge.net>
-2005-11-04 Kevin Kenny <kennykb@acm.org>
+ * generic/tclCompile.h: Add support for debug logging of DTrace
+ * generic/tclBasic.c: 'proc', 'cmd' and 'inst' probes (does
+ _not_ require a platform with DTrace).
- * generic/tclGetDate.y: Added abbreviations for the Korean timezone.
- * generic/tclDate.c: Regenerated.
+ * generic/tclCmdIL.c (TclInfoFrame): Check fPtr->line before
+ dereferencing as line info may
+ not exists when TclInfoFrame()
+ is called from a DTrace probe.
- * compat/strftime.c: Fixed a problem where the name of the time zone
- was double-converted from system encoding to UTF-8. Thanks to the
- anonymous submitter of [Bug 1317477] for the report and the patch.
+ * tests/msgcat.test: Fix for ::tcl::mac::locale with
+ @modifier (HEAD backport 2008-06-01).
-2005-11-04 Miguel Sofer <msofer@users.sf.net>
+ * tests/fCmd.test (fCmd-6.23): Made result matching robust when test
+ workdir and /tmp are not on same FS.
- * generic/tclInt.h:
- * generic/tclNamesp.c:
- * generic/tclVar.c: fix for [Bugs 1338280/1337229]. Thanks Don.
+ * unix/Makefile.in: Ensure Makefile shell is /bin/bash for
+ * unix/configure.in (SunOS): DTrace-enabled build on Solaris.
+ (followup to 2008-06-12) [Bug 2016584]
- * tests/trace.test: fix duplicate test numbers
+ * unix/tcl.m4 (SC_PATH_X): Check for libX11.dylib in addition to
+ libX11.so et al.
-2005-11-03 Don Porter <dgp@users.sourceforge.net>
+ * unix/configure: autoconf-2.59
- * generic/tclUnixInit.c (TclpSetInitialEncodings): Modified so
- that multiple calls can continue to atttempt to properly set the
- system encoding. Needed for Tclkit to properly support non-default
- encodings. Thanks to Yaroslav Schekin. [Bug 1201171]
+2008-08-13 Don Porter <dgp@users.sourceforge.net>
-2005-11-03 Pat Thoyts <patthoyts@users.sourceforge.net>
+ * generic/tclFileName.c: Fix for errors handling -types {}
+ * tests/fileName.test: option to [glob]. [Bug 1750300]
+ Thanks to Matthias Kraft and George Peter Staplin.
- * win/tclWin32Dll.c: Backported Anton Kovalenko's [Patch 1256872]
- * win/tclWinConsole.c: to give unicode console support on
- * win/tclWinInt.h: suitable systems (eg: NT/XP)
+2008-08-12 Don Porter <dgp@users.sourceforge.net>
-2005-11-01 Don Porter <dgp@users.sourceforge.net>
+ * changes: Update for 8.5.4 release.
- * generic/tclCmdMZ.c (TclCheckExecutionTraces): Corrected mistaken
- assumption that all command traces are set at the script level.
- Report/fix from Jacques H. de Villiers. [Bug 1337941]
+2008-08-11 Pat Thoyts <patthoyts@users.sourceforge.net>
- * tests/expr-old.test (expr-32.52): Use int(.) to restrict result
- of left shift to the C long range.
+ * library/http/http.tcl: Remove 8.5 requirement.
+ * library/http/pkgIndex.tcl:
+ * unix/Makefile.in:
+ * win/Makefile.in:
+ * win/makefile.vc:
-2005-10-29 Mo DeJong <mdejong@users.sourceforge.net>
+2008-08-11 Andreas Kupries <andreask@activestate.com>
- * tests/expr.test: Fix problems in new round() tests that lead to
- correct result only on 32 bit long systems. [Bug 1341368]
+ * library/tm.tcl: Added a 'package provide' command to the generated
+ ifneeded scripts of Tcl Modules, for early detection of conflicts
+ between the version specified through the file name and a 'provide'
+ command in the module implementation, if any. Note that this change
+ also now allows Tcl Modules to not provide a 'provide' command at all,
+ and declaring their version only through their filename.
-2005-10-29 Miguel Sofer <msofer@users.sf.net>
+ * generic/tclProc.c (Tcl_ProcObjCmd): Fixed memory leak triggered
+ * tests/proc.test: by procbody::test::proc. See [Bug 2043636]. Added a
+ test case demonstrating the leak before the fix. Fixed a few spelling
+ errors in test descriptions as well.
- * generic/tclCmdMZ.c (TraceVarProc): [Bug 1337229], partial fix.
- Ensure that a second call with TCL_TRACE_DESTROYED does not lead to a
- second call to Tcl_EventuallyFree(). It is still true that that second
- call should not happen, so the bug is not completely fixed.
- * tests/trace.test (test-18.3-4): added tests for [Bugs 1337229 and
- 1338280].
+2008-08-11 Don Porter <dgp@users.sourceforge.net>
-2005-10-27 Mo DeJong <mdejong@users.sourceforge.net>
+ * library/http/http.tcl: Bump http version to 2.7.1 to account
+ * library/http/pkgIndex.tcl: for [Bug 2046486] bug fix. This
+ * unix/Makefile.in: release of http now requires a
+ * win/Makefile.in: dependency on Tcl 8.5 to be able to
+ * win/makefile.bc: use the unsigned formats in the
+ * win/makefile.vc: [binary scan] command.
- * generic/tclExecute.c (ExprRoundFunc): Fix typo where number before
- rounding is compared with smallest integer instead of number after
- rounding. This fix does not change the results of any tests.
- * tests/expr.test: Add round() tests for cases near the min and max
- int values.
- * tests/util.test: Remove pointless warning code about testobj command
+2008-08-11 Pat Thoyts <patthoyts@users.sourceforge.net>
-2005-10-23 Miguel Sofer <msofer@users.sf.net>
+ * library/http/http.tcl: crc field from zlib data should be treated as
+ unsigned for 64bit support [Bug 2046846]
- * generic/tclBasic.c:
- * generic/tclBinary.c:
- * generic/tclCmdAH.c:
- * generic/tclCmdIL.c:
- * generic/tclCmdMZ.c:
- * generic/tclExecute.c:
- * generic/tclLink.c:
- * generic/tclMain.c:
- * generic/tclProc.c:
- * generic/tclScan.c:
- * generic/tclTest.c:
- * generic/tclVar.c:
- * mac/tclMacInit.c:
- * unix/tclUnixInit.c:
- * win/tclWinInit.c: Ensure that the core never calls TclPtrSetVar,
- Tcl_SetVar2Ex, Tcl_ObjSetVar2 or Tcl_SetObjErrorCode with a 0-ref new
- value. It is not possible to handle error returns correctly in that
- case [Bug 1334947], one has the choice of leaking the object in some
- cases, or else risk crashing in some others.
+2008-08-08 Don Porter <dgp@users.sourceforge.net>
-2005-10-22 Miguel Sofer <msofer@users.sf.net>
+ * generic/tcl.h: Bump to 8.5.4 for release.
+ * library/init.tcl:
+ * tools/tcl.wse.in:
+ * unix/configure.in:
+ * unix/tcl.spec:
+ * win/configure.in:
- * generic/tclExecute.c (INST_CONCAT): disable the optimisation for
- wide integers. [Bug 1251791]
+ * unix/configure: autoconf-2.59
+ * win/configure:
-2005-10-14 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+ * changes: Update for 8.5.4 release.
- * generic/tclIO.c (Tcl_ClearChannelHandlers): removed change dated
- 2005-10-04 below. Look into [Bug 1323992] for detailed discussion.
+2008-08-08 Kevin Kenny <kennykb@acm.org>
-2005-10-13 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * library/tzdata/CET:
+ * library/tzdata/MET:
+ * library/tzdata/Africa/Casablanca:
+ * library/tzdata/America/Eirunepe:
+ * library/tzdata/America/Santarem:
+ * library/tzdata/America/Rio_Branco:
+ * library/tzdata/America/Argentina/San_Luis:
+ * library/tzdata/Asia/Karachi:
+ * library/tzdata/Europe/Belgrade:
+ * library/tzdata/Europe/Berlin:
+ * library/tzdata/Europe/Budapest:
+ * library/tzdata/Europe/Sofia:
+ * library/tzdata/Indian/Mauritius: Olson's tzdata2008e.
- * generic/tclCmdAH.c (Tcl_FormatObjCmd): Stop [format] from seeing
- the difference between ints and wides. [Bug 1284178]
+2008-08-06 Don Porter <dgp@users.sourceforge.net>
-2005-10-13 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+ * generic/tclVar.c (TclLookupSimpleVar): Retrieve the number of
+ locals in the localCache from the CallFrame and not from the Proc
+ which may have been mangled by a (broken?) recompile. Backport from
+ the HEAD.
- * generic/tclIO.c (Tcl_ClearChannelHandlers): temporary
- ifdef TCL_THREADS changes done to de-activate pending
- event processing when channel is being closed/cutted.
+2008-08-04 Don Porter <dgp@users.sourceforge.net>
-2005-10-10 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclExecute.c: Stopped faulty double-logging of errors to
+ * tests/execute.test: stack trace when a compile epoch bump triggers
+ fallback to direct evaluation of commands in a compiled script.
+ [Bug 2037338]
- * generic/tclInt.h: ensure MODULE_SCOPE decl
+2008-07-30 Don Porter <dgp@users.sourceforge.net>
-2005-10-07 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclBasic.c: Corrected the timing of when the flag
+ TCL_ALLOW_EXCEPTIONS is tested.
- * unix/tclUnixFCmd.c (TraverseUnixTree): Adjust 2004-11-11 change to
- * tests/fCmd.test (fCmd-20.2): account for NFS special
- files with a readdir rewind threshold. [Bug 1034337]
+2008-07-29 Miguel Sofer <msofer@users.sf.net>
-2005-10-05 Andreas Kupries <andreask@activestate.com>
+ * generic/tclExecute.c: fix [Bug 2030670] that cause
+ TclStackRealloc to panic on rare corner cases. Thx ajpasadyn for
+ diagnose and patch.
- * generic/tclPipe.c (TclCreatePipeline): Fixed [Bug 1109294]. Applied
- the patch provided by David Gravereaux.
+2008-07-28 Andreas Kupries <andreask@activestate.com>
- * doc/CrtChannel.3: Fixed [Bug 1104682], by application of David
- Welton's patch for it, and added a note about wideSeekProc.
+ * generic/tclBasic.c: Added missing ref count when creating an empty
+ string as path (TclEvalEx). In 8.4 the missing code caused panics in
+ the testsuite. It doesn't in 8.5. I am guessing that the code path
+ with the missing the incr-refcount is not invoked any longer. Because
+ the bug in itself is certainly the same.
-2005-10-05 Jeff Hobbs <jeffh@ActiveState.com>
+2008-07-25 Daniel Steffen <das@users.sourceforge.net>
- * tests/env.test (env-6.1):
- * win/tclWinPort.h: define USE_PUTENV_FOR_UNSET 1
- * generic/tclEnv.c (TclSetEnv, TclUnsetEnv): add
- USE_PUTENV_FOR_UNSET to existing USE_PUTENV define to account for
- various systems that have putenv(), but can't unset env vars with it.
- Note difference between Windows and Linux for actually unsetting the
- env var (use of '=').
- Correct the resizing of the environ array. We assume that we are in
- full ownership, but that's not correct. [Bug 979640]
+ * tests/info.test (info-37.0): Add !singleTestInterp constraint;
+ (info-22.8, info-23.0): switch to glob matching to avoid sensitivity
+ to tcltest.tcl line number changes, remove knownBug constraint, fix
+ expected result. [Bug 1605269]
-2005-10-04 Jeff Hobbs <jeffh@ActiveState.com>
+2008-07-25 Andreas Kupries <andreask@activestate.com>
- * win/tclWinSerial.c (SerialSetOptionProc): free argv [Bug 1067708]
+ * tests/info.test: Tests 38.* added, exactly testing the tracking of
+ location for uplevel scripts.
- * tests/http.test: Do not URI encode -._~ according to
- * library/http/http.tcl (init): RFC3986. [Bug 1182373] (aho)
+ * generic/tclCompile.c (TclInitCompileEnv): Reorganized the
+ initialization of the #280 location information to match the flow in
+ TclEvalObjEx to get more absolute contexts.
- * generic/tclIOUtil.c (TclFSNormalizeAbsolutePath): make static
- * generic/tclEncoding.c (TclFindEncodings): make static
+ * generic/tclBasic.c (TclEvalObjEx): Moved the pure-list optimization
+ out of the eval-direct code path to be done always, i.e. even when a
+ compile is requested. This way we do not loose the association between
+ #280 location information and the list elements, if any.
- * unix/tclLoadShl.c (TclpDlopen): use DYNAMIC_PATH on second
- shl_load only. [Bug 1204237]
+2008-07-23 Andreas Kupries <andreask@activestate.com>
-2005-10-04 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+ * tests/info.test: Reordered the tests to have monotonously
+ increasing numbers.
- * generic/tclIO.c (Tcl_ClearChannelHandlers): now deletes any
- outstanding timer for the channel. Also, prevents events still
- in the event queue from triggering on the current channel.
+ * generic/tclBasic.c: Modified TclArgumentGet to reject pure lists
+ * generic/tclCmdIL.c: immediately, without search. Reworked setup
+ * generic/tclCompile.c: of eoFramePtr, doesn't need the line
+ * tests/info.test: information, more sensible to have everything on
+ line 1 when eval'ing a pure list. Updated the users of the line
+ information to special case this based on the frame type (i.e.
+ TCL_LOCATION_EVAL_LIST). Added a testcase demonstrating the new
+ behaviour.
- * generic/tclTimer.c (Tcl_DeleteTimerHandler): bail out early
- if passed NULL argument.
+2008-07-22 Andreas Kupries <andreask@activestate.com>
-2005-09-30 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclBasic.c: Added missing function comments.
- * generic/tclMain.c: Separate encoding conversion of command line
- arguments from list formatting. [Bug 1306162]
+ * generic/tclCompile.c: Made the new TclEnterCmdWordIndex
+ * generic/tclCompile.h: static, and ansified.
-2005-09-27 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * generic/tclBasic.c: Reworked the handling of bytecode literals
+ * generic/tclCompile.c: for #280 to fix the abysmal performance
+ * generic/tclCompile.h: for deep recursion, replaced the linear
+ * generic/tclExecute.c: search through the whole stack with another
+ * generic/tclInt.h: hashtable and simplified the data structure used
+ by the compiler (array instead of hashtable). Incidentially this also
+ fixes the memory leak reported via [Bug 2024937].
- * generic/tclBinary.c (FormatNumber): Factorize out copying of double
- values to a helper to work around ugly broken compiler problems. [Bug
- 1116542]
+2008-07-21 Don Porter <dgp@users.sourceforge.net>
-2005-09-15 Miguel Sofer <msofer@users.sf.net>
+ * tests/encoding.test: Make failing tests pass again. [Bug 1972867]
- * doc/ParseCmd.3: copy/paste fix [Bug 1292427]
+2008-07-21 Andreas Kupries <andreask@activestate.com>
-2005-09-15 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * generic/tclBasic.c: Extended the existing TIP #280 system (info
+ * generic/tclCmdAH.c: frame), added the ability to track the
+ * generic/tclCompCmds.c: absolute location of literal procedure
+ * generic/tclCompile.c: arguments, and making this information
+ * generic/tclCompile.h: available to uplevel, eval, and
+ * generic/tclInterp.c: siblings. This allows proper tracking of
+ * generic/tclInt.h: absolute location through custom (Tcl-coded)
+ * generic/tclNamesp.c: control structures based on uplevel, etc.
+ * generic/tclProc.c:
- * unix/tcl.m4 (SC_TCL_EARLY_FLAGS): Added extra hack to allow Tcl to
- transparently open large files on RHEL 3. [Bug 1287638]
+2008-07-21 Pat Thoyts <patthoyts@users.sourceforge.net>
- * unix/configure: autoconf-2.13
+ * generic/tclFCmd.c: Inodes on windows are unreliable [Bug 2015723]
-2005-09-07 Don Porter <dgp@users.sourceforge.net>
+2008-07-20 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * generic/tclUtf.c (Tcl_UniCharToUtf): Corrected handling of negative
- * tests/utf.test (utf-1.5): Tcl_UniChar input value. Incorrect
- handling was producing byte sequences outside of Tcl's legal internal
- encoding. [Bug 1283976]
+ * generic/tclDictObj.c (SetDictFromAny): Make the list->dict
+ transformation a bit more efficient; modern dicts are ordered and so
+ we can round-trip through lists without needing the string rep at all.
+ * generic/tclListObj.c (SetListFromAny): Make the dict->list
+ transformation not lossy of internal representations and hence more
+ efficient. [Bug 2008248] (ajpasadyn) but using a more efficient patch.
-2005-08-29 Kevin Kenny <kennykb@acm.org>
+2008-07-15 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * generic/tclBasic.c (ExprMathFunc): Restored "round away from zero"
- * tests/expr.test (expr-46.*): behaviour to the "round"
- function. Added test cases for the behavior, including the awkward
- case of a number whose fractional part is 1/2-1/2ulp. [Bug 1275043]
+ * doc/DictObj.3: Fix error in example. [Bug 2016740]
-2005-08-25 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+2008-07-08 Don Porter <dgp@users.sourceforge.net>
- * generic/tclListObj.c (UpdateStringOfList): Stop uncontrolled and
- unsafe crashes from happening when working with very large string
- representations. [Bug 1267380]
+ * generic/tclGet.c: Corrected out of date comments.
-2005-08-17 Jeff Hobbs <jeffh@ActiveState.com>
+2008-07-07 Andreas Kupries <andreask@activestate.com>
- * generic/tclFCmd.c (TclFileMakeDirsCmd): fix to race condition in
- file mkdir (backport from head 2005-06-13) [Bug 1217375]
+ * generic/tclCmdIL.c (InfoFrameCmd): Fixed unsafe idiom of setting the
+ interp result found by Don Porter.
-2005-08-16 Kevin Kenny <kennykb@acm.org>
+2008-07-07 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * generic/tclEvent.c (Tcl_Finalize): Pushed Tcl_FinalizeLoad and
- Tcl_ResetFilesystem down after Tcl_FinalizeThreadAlloc because
- unloading DLLs can't happen while they still own TSD keys.
- (This is a backport of changes made in the HEAD on 2005-08-10.)
+ * doc/regexp.n, doc/regsub.n: Correct examples. [Bug 1982642]
-2005-08-05 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+2008-07-04 Joe English <jenglish@users.sourceforge.net>
- * unix/tclUnixInit.c (localeTable): Solaris uses a non-standard name
- for the cp1251 charset. Thanks to Victor Wagner for reporting this.
- [Bug 1252475]
+ * generic/tclEncoding.c(UtfToUtfProc): Avoid unwanted sign extension
+ when converting incomplete UTF-8 sequences. See [Bug 1908443] for
+ details.
-2005-08-05 Kevin Kenny <kennykb@users.sourceforge.net>
+2008-07-03 Andreas Kupries <andreask@activestate.com>
- * generic/tclExecute.c (TclExecuteByteCode): Fixed a corner case
- * tests/expr.test (expr-38.1): where applying abs to
- MIN_INT failed to promote the result to a wide integer. [Bug 1241572]
+ * generic/tclIORChan.c (InvokeTclMethod): Fixed the memory leak
+ reported in [Bug 1987821]. Thanks to Miguel for the rpeort and Don
+ Porter for tracking the cause down.
-2005-08-04 Don Porter <dgp@users.sourceforge.net>
+2008-07-03 Don Porter <dgp@users.sourceforge.net>
- * generic/tclObj.c: Simplified routines that manage the typeTable.
+ * library/package.tcl: Removed [file readable] testing from
+ [tclPkgUnknown] and friends. We find out soon enough whether a file is
+ readable when we try to [source] it, and not testing before allows us
+ to workaround the bugs on some common filesystems where [file
+ readable] lies to us. [Patch 1969717]
-2005-08-03 Don Porter <dgp@users.sourceforge.net>
+2008-06-29 Don Porter <dgp@users.sourceforge.net>
- * generic/tclCompExpr.c: Untangled some dependencies in the
- * generic/tclEvent.c: order of finalization routines.
- * generic/tclInt.h: [Bug 1251399]
- * generic/tclObj.c:
+ *** 8.5.3 TAGGED FOR RELEASE ***
-2005-07-30 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tcl.h: Bump to 8.5.3 for release.
+ * library/init.tcl:
+ * tools/tcl.wse.in:
+ * unix/configure.in:
+ * unix/tcl.spec:
+ * win/configure.in:
- * unix/configure, unix/tcl.m4: revert 2005-07-28 change.
+ * unix/configure: autoconf-2.59
+ * win/configure:
- * unix/tclLoadDyld.c (TclpDlopen, TclpLoadMemory): workarounds for
- bugs/changes in behaviour in Mac OS X 10.4 Tiger, sync formatting
- changes from HEAD.
+ * doc/ObjectType.3: Updated documentation of the Tcl_ObjType
+ struct to match expectations of Tcl 8.5 [Bug 1917650].
-2005-07-29 Donal K. Fellows <dkf@users.sf.net>
+ * generic/tclPathObj.c: Plug memory leak in [Bug 1999176] fix. Thanks
+ Rolf Ade for detecting.
- * generic/tclCmdIL.c (InfoGlobalsCmd): Even in high-speed mode, still
- have to take care with non-existant variables. [Bug 1247135]
+2008-06-28 Don Porter <dgp@users.sourceforge.net>
-2005-07-28 Mo DeJong <mdejong@users.sourceforge.net>
+ * generic/tclPathObj.c: Plug memory leak in [Bug 1972879] fix. Thanks
+ Rolf Ade for detecting and Dan Steffen for the fix [Bug 2004654].
- * win/README: Update link to msys_mingw8.zip. Remove old Cygwin +
- Mingw info, people should just build with the msys + mingw
- configuration.
+2008-06-26 Andreas Kupries <andreask@activestate.com>
-2005-07-28 Jeff Hobbs <jeffh@ActiveState.com>
+ * unix/Makefile.in: Followup to my change of 2008-06-25, make code
+ generated by the Makefile and put into the installd tm.tcl conditional
+ on interpreter safeness as well. Thanks to Daniel Steffen for
+ reminding me of that code.
- * unix/configure, unix/tcl.m4: defined TCL_LOAD_FROM_MEMORY on Darwin
- only for SHARED_BUILD
+2008-06-25 Don Porter <dgp@users.sourceforge.net>
-2005-07-28 Donal K. Fellows <dkf@users.sf.net>
+ * changes: Update for 8.5.3 release.
- * generic/tclPipe.c (TclCreatePipeline): Arrange for POSIX systems to
- * unix/tclUnixPipe.c (TclpOpenFile): use the O_APPEND flag for
- * tests/exec.test (exec-19.1): files opened in a pipeline
- like ">>this". Note that Windows cannot support such access; there is
- no equivalent flag on the handle that can be set at the kernel-call
- level. The test is unix-specific in every way. [Bug 1245953]
+2008-06-25 Andreas Kupries <andreask@activestate.com>
-2005-07-26 Mo DeJong <mdejong@users.sourceforge.net>
+ * library/tm.tcl: Modified the handling of Tcl Modules and of the
+ * library/safe.tcl: Safe Base to interact nicely with each other,
+ * library/init.tcl: enabling requiring Tcl Modules in safe
+ * tests/safe.test: interpreters. Fixes [Bug 1999119].
- * unix/configure: Regen.
- * unix/configure.in: Check for a $prefix/share directory and add it
- the the package if found. This will check for Tcl packages in
- /usr/local/share when Tcl is configured with the default dist install.
- [Patch 1231015]
+2008-06-25 Pat Thoyts <patthoyts@users.sourceforge.net>
-2005-07-26 Don Porter <dgp@users.sourceforge.net>
+ * win/rules.vc: Backported fix for dde/registry versions and
+ * win/makefile.vc: the staticpkg build option
- * doc/tclvars.n: Improved $errorCode documentation. [RFE 776921]
+2008-06-24 Don Porter <dgp@users.sourceforge.net>
- * generic/tclBasic.c (Tcl_CallWhenDeleted): Converted to use
- per-thread counter, rather than a process global one that required
- mutex protection. [RFE 1077194]
+ * generic/tclPathObj.c: Fixed some internals management in the "path"
+ Tcl_ObjType for the empty string value. Problem led to a crash in the
+ command [glob -dir {} a]. [Bug 1999176].
- * generic/tclNamesp.c (TclTeardownNamespace): Re-ordering so that
- * tests/trace.test (trace-34.4): command delete traces fire
- while the command still exists. [Bug 1047286]
+2008-06-23 Don Porter <dgp@users.sourceforge.net>
-2005-07-24 Mo DeJong <mdejong@users.sourceforge.net>
+ * generic/tclPathObj.c: Fixed bug in Tcl_GetTranslatedPath() when
+ operating on the "Special path" variant of the "path" Tcl_ObjType
+ intrep. A full normalization was getting done, in particular, coercing
+ relative paths to absolute, contrary to what the function of
+ producing the "translated path" is supposed to do. [Bug 1972879]
- * unix/tcl.m4 (SC_PROG_TCLSH, SC_BUILD_TCLSH):
- * win/tcl.m4 (SC_PROG_TCLSH, SC_BUILD_TCLSH):
- Split confused search for tclsh on PATH and build and install
- locations into two macros. SC_PROG_TCLSH searches just the PATH.
- SC_BUILD_TCLSH determines the name of the tclsh executable in the Tcl
- build directory. [Bug 1160114], [Patch 1244153]
+2008-06-19 Don Porter <dgp@users.sourceforge.net>
-2005-07-22 Don Porter <dgp@users.sourceforge.net>
+ * changes: Update for 8.5.3 release.
- * library/auto.tcl: Updates to the Tcl script library to make
- * library/history.tcl: use of Tcl 8.4 feautures. Thanks to
- * library/init.tcl: Patrick Fradin for prompting on this.
- * library/package.tcl: [Patch 1237755]
- * library/safe.tcl:
- * library/word.tcl:
+ * generic/tclInterp.c: Fixed completely boneheaded mistake that
+ * tests/interp.test: [interp bgerror $slave] and [$slave bgerror]
+ would always act like [interp bgerror {}]. [Bug 1999035]
-2005-07-07 Jeff Hobbs <jeffh@ActiveState.com>
+ * tests/chanio.test: Corrected flawed tests revealed by a -debug 1
+ * tests/event.test: -singleproc 1 test suite run.
+ * tests/io.test:
- * unix/tcl.m4, unix/configure: Backported [Bug 1095909], removing
- * unix/tclUnixPort.h: any use of readdir_r as it is not
- * unix/tclUnixThrd.c: necessary and just confuses things.
+2008-06-19 Don Porter <dgp@users.sourceforge.net>
-2005-07-05 Don Porter <dgp@users.sourceforge.net>
+ * changes: Updates for 8.5.3 release.
- * generic/tclCmdAH.c: New "encoding" Tcl_ObjType (not registered)
- * generic/tclEncoding.c: that permits longer lifetimes of the
- * generic/tclInt.h: Tcl_Encoding values kept as intreps of
- Tcl_Obj's. Reduces the need for repeated reading of encoding
- definition files from the filesystem. [Bug 1077262]
+2008-06-17 Andreas Kupries <andreask@activestate.com>
- * generic/tclNamesp.c: Allow for [namespace import] of a command
- * tests/namespace.test: over a previous [namespace import] of itself
- without throwing an error. [RFE 1230597]
+ * generic/tclClock.c (ClockConvertlocaltoutcObjCmd): Removed left
+ over debug output.
-2005-07-01 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+2008-06-17 Andreas Kupries <andreask@activestate.com>
- * unix/tclUnixNotfy.c: protect against spurious wake-ups while waiting
- on the condition variable when tearing down the notifier thread. [Bug
- 1222872]
+ * doc/tm.n: Followup to changelog entry 2008-03-18 regarding
+ ::tcl::tm::Defaults. Updated the documentation to not only mention
+ the new (underscored) form of environment variable names, but make
+ it the encouraged form as well. See [Bug 1914604].
-2005-06-27 Don Porter <dgp@users.sourceforge.net>
+2008-06-17 Kevin Kenny <kennykb@acm.org>
- *** 8.4.11 TAGGED FOR RELEASE ***
+ * generic/tclClock.c (ConvertLocalToUTC):
+ * tests/clock.test (clock-63.1): Fixed a bug where the
+ internal ConvertLocalToUTC command segfaulted if passed a
+ dictionary without the 'localSeconds' key. To the best of
+ my knowledge, the bug was not observable in the [clock]
+ command itself.
- * library/auto.tcl: Reverted to Revision 1.12.2.3 (Tcl 8.4.9).
- Restores the (buggy) behavior of [auto_reset] that fails to clear
- away auto-loaded commands from non-global namespaces. Fixing this
- bug exposed an unknown number of buggy files out there (including at
- least portions of the Tk script library) that cannot tolerate double
- [source]-ing. The burden of fixing these exposed bugs will not be
- forced on package/extension/application authors until Tcl 8.5.
+2008-06-16 Andreas Kupries <andreask@activestate.com>
-2005-06-24 Kevin Kenny <kennykb@acm.org>
+ * generic/tclCmdIL.c (TclInfoFrame): Backport of fix made on the
+ * tests/info.test: head branch :: Moved the code looking up the
+ information for key 'proc' out of the TCL_LOCATION_BC branch to
+ after the switch, this is common to all frame types. Updated the
+ testsuite to match. This was exposed by the 2008-06-08 commit
+ (Miguel), switching uplevel from direct eval to compilation. Fixes
+ [Bug 1987851].
- * generic/tclEvent.c (Tcl_Finalize):
- * generic/tclInt.h:
- * generic/tclPreserve.c (TclFinalizePreserve): Changed the
- finalization logic so that Tcl_Preserve finalizes after exit
- handlers run; a lot of code called from Tk's exit handlers
- presumes tha Tcl_Preserve will still work even from an exit
- handler. Also, made the assertion check that no exit handlers
- are created in Tcl_Finalize conditional on TCL_MEM_DEBUG to
- avoid spurious panics in the "stable" release.
+2008-06-12 Daniel Steffen <das@users.sourceforge.net>
-2005-06-24 Don Porter <dgp@users.sourceforge.net>
+ * unix/Makefile.in: add complete deps on tclDTrace.h.
- * library/auto.tcl: Make file safe to re-[source] without
- destroying registered auto_mkindex_parser hooks.
+ * unix/Makefile.in: clean generated tclDTrace.h file.
+ * unix/configure.in (SunOS): fix static DTrace-enabled build.
-2005-06-23 Daniel Steffen <das@users.sourceforge.net>
+ * unix/tcl.m4 (SunOS-5.11): fix 64bit amd64 support with gcc & Sun cc.
+ * unix/configure: autoconf-2.59
- * tools/tcltk-man2html.tcl: fixed useversion glob pattern to accept
- multi-digit patchlevels.
+ * macosx/Tcl.xcodeproj/project.pbxproj: add debug configs with gcov,
+ and with corefoundation disabled; updates and cleanup for Xcode 3.1 and
+ for Leopard.
+ * macosx/Tcl.xcode/project.pbxproj: sync Tcl.xcodeproj changes.
+ * macosx/README: document new build configs.
-2005-06-23 Kevin Kenny <kennykb@acm.org>
+2008-05-26 Jeff Hobbs <jeffh@ActiveState.com>
- * win/tclWinChan.c: More rewriting of __asm__ blocks that
- * win/tclWinFCmd.c: implement SEH in GCC, because mingw's
- gcc 3.4.2 is not as forgiving of violations committed by
- the old code and caused panics. [Bug 1225957]
+ * tests/io.test (io-53.9): need to close chan before removing file.
-2005-06-23 Daniel Steffen <das@users.sourceforge.net>
+2008-05-23 Andreas Kupries <andreask@activestate.com>
- * unix/Makefile.in (install-private-headers): rewrite tclPort.h when
- installing private headers to remove ../unix relative #include path to
- tclUnixPort.h (which is incorrect at the installed location).
+ * win/tclWinChan.c (FileWideSeekProc): Accepted a patch by
+ Alexandre Ferrieux <ferrieux@users.sourceforge.net> to fix the
+ [Bug 1965787]. 'tell' now works for locations > 2 GB as well
+ instead of going negative.
-2005-06-22 Kevin Kenny <kennykb@acm.org>
+ * generic/tclIO.c (Tcl_SetChannelBufferSize): Accepted a patch by
+ * tests/io.test: Alexandre Ferrieux <ferrieux@users.sourceforge.net>
+ * tests/chanio.test: to fix the [Bug 1969953]. Buffersize outside
+ of the supported range are now clipped to nearest boundary instead
+ of ignored.
- * generic/tclInt.h: Changed the finalization
- * generic/tclEvent.c (Tcl_Finalize): logic to defer the
- * generic/tclIO.c (TclFinalizeIOSubsystem): shutdown of the pipe
- * unix/tclUnixPipe.c (TclFinalizePipes): management until after
- * win/tclWinPipe.c (TclFinalizePipes): all channels have been
- closed, in order to avoid a situation where the Windows
- PipeCloseProc2 would re-establish the exit handler after exit
- handlers had already run, corrupting the heap. [Bug 1225727]
- Corrected a read of uninitialized memory in PipeCloseProc2, which (at
- least on certain configurations) caused a great number of tests to
- either fail or hang. [Bug 1225044]
+2008-05-22 Don Porter <dgp@users.sourceforge.net>
-2005-06-22 Andreas Kupries <andreask@activestate.com>
+ * generic/tclNamesp.c (Tcl_LogCommandInfo): Restored ability to
+ handle the argument value length = -1. Thanks to Chris Darroch for
+ discovering the bug and providing the fix. [Bug 1968245].
- * generic/tclInt.h: Followup to change made on 2005-06-18 by Daniel
- Steffen. There are compilers (*) who error out on the redefinition of
- WORDS_BIGENDIAN. We have to undef the previous definition (on the
- command line) first to make this acceptable. (*): AIX native.
+2008-05-21 Don Porter <dgp@users.sourceforge.net>
-2005-06-22 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclParse.c (ParseComment): The new TclParseAllWhiteSpace
+ * tests/parse.test (parse-15.60): routine has no mechanism to
+ return the "incomplete" status of "\\\n" so calling this routine
+ anywhere that can be reached within a Tcl_ParseCommand call is a
+ mistake. In particular, ParseComment must not use it. [Bug 1968882]
- * win/tclWinFile.c: Potential buffer overflow. [Bug 1225571]
- Thanks to Pat Thoyts for discovery and fix.
+2008-05-21 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * tests/safe.test: Backport performance improvement from
- reduced $::auto_path.
+ * generic/tclNamesp.c (Tcl_SetNamespaceUnknownHandler): Corrected odd
+ logic for handling installation of namespace unknown handlers which
+ could lead too very strange things happening in the error case.
-2005-06-21 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-05-16 Miguel Sofer <msofer@users.sf.net>
- * tests/winDde.test: Added some waits to the dde server script to
- let event processing run after we create the dde server and before
- we exit the server process. This avoids 'server did not respond'
- errors.
+ * generic/tclCompile.c: Fix crash with tcl_traceExec. Found and
+ fixed by Alexander Pasadyn [Bug 1964803].
-2005-06-21 Kevin Kenny <kennykb@acm.org>
+2008-05-07 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * generic/tclFileName.c: Corrected a problem where a directory name
- containing a colon can crash the process on Windows [Bug 1194458]
- * tests/fileName.test: Added test for [file split] and [file join]
- with a name containing a colon.
- * win/tclWinPipe.c: Reverted davygrvy's changes of 2005-04-19;
- they cause multiple failures in io.test. [Bug 1225044, still open]
+ * generic/tclCompCmds.c (TclCompileDictAppendCmd): Fix silly
+ off-by-one error that caused a crash every time a compiled 'dict
+ append' with more than one value argument was used. Found by Colin
+ McCormack.
-2005-06-21 Don Porter <dgp@users.sourceforge.net>
+2008-04-26 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
- * generic/tclBasic.c: Made the walk of the active trace list aware
- * generic/tclCmdMZ.c: of the direction of trace scanning, so the
- * generic/tclInt.h: proper correction can be made. [Bug 1224585]
- * tests/trace.test (trace-34.2,3):
+ * generic/tclAsync.c: Tcl_AsyncDelete(): panic if attempt to locate
+ handler token fails. Happens when some other thread attempts to delete
+ somebody else's token.
- * generic/tclBasic.c (Tcl_DeleteTrace): Added missing walk of the
- * tests/trace.test (trace-34.1): list of active traces to
- cleanup references to traces being deleted. [Bug 1201035]
+ Also, panic early if we find out the wrong thread attempting to delete
+ the async handler (common trap). As, only the one that created the
+ handler is allowed to delete it.
-2005-06-20 Don Porter <dgp@users.sourceforge.net>
+2008-04-24 Andreas Kupries <andreask@activestate.com>
- * doc/FileSystem.3: added missing Tcl_GlobTypeData documentation [Bug
- 935853]
+ * tests/ioCmd.test: Extended testsuite for reflected channel
+ implementation. Added test cases about how it handles if the rug is
+ pulled out from under a channel (= killing threads, interpreters
+ containing the tcl command for a channel, and channel sitting in a
+ different interpreter/thread.)
-2005-06-18 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tclIORChan.c: Fixed the bugs exposed by the new testcases,
+ redone most of the cleanup and exit handling.
- * generic/tclInt.h: ensure WORDS_BIGENDIAN is defined correctly with
- fat compiles on Darwin (i.e. ppc and i386 at the same time), the
- configure AC_C_BIGENDIAN check is not sufficient in this case because
- a single run of the compiler builds for two architectures with
- different endianness.
+2008-04-15 Andreas Kupries <andreask@activestate.com>
- * unix/tcl.m4 (Darwin): add -headerpad_max_install_names to LDFLAGS to
- ensure we can always relocate binaries with install_name_tool.
+ * generic/tclIO.c (CopyData): Applied another patch by Alexandre
+ * io.test (io-53.8a): Ferrieux <ferrieux@users.sourceforge.net>,
+ * chanio.test (chan-io-53.8a): to shift EOF handling to the async
+ part of the command if a callback is specified, should the channel
+ be at EOF already when fcopy is called. Testcase by myself.
- * unix/configure: autoconf-2.13
+2008-04-14 Kevin B. Kenny <kennykb@acm.org>
-2005-06-18 Don Porter <dgp@users.sourceforge.net>
+ * unix/tclUnixTime.c (NativeGetTime): Removed obsolete use of
+ 'struct timezone' in the call to 'gettimeofday'. [Bug 1942197].
+ * tests/clock.test (clock-33.5, clock-33.5a, clock-33.8, clock-33.8a):
+ Added comments to the test that it can fail on a heavily loaded
+ system.
- * changes: Update changes for 8.4.11 release
+2008-04-11 Don Porter <dgp@users.sourceforge.net>
- * README: Bump version number to 8.4.11
- * generic/tcl.h:
- * tools/tcl.wse.in:
- * unix/configure.in:
+ * generic/tcl.h: Bump version number to 8.5.3b1 to distinguish
+ * library/init.tcl: CVS development snapshots from the 8.5.2 and
+ * unix/configure.in: 8.5.3 releases.
* unix/tcl.spec:
- * win/README.binary:
* win/configure.in:
+ * README
- * unix/configure: autoconf
+ * unix/configure: autoconf (2.59)
* win/configure:
-2005-06-18 Donal K. Fellows <donal.k.fellows@man.ac.uk>
-
- * generic/tclCmdAH.c (Tcl_FormatObjCmd): Fix for [Bug 1154163]; only
- * tests/format.test: insert 'l' modifier when it is needed.
-
-2005-06-07 Donal K. Fellows <donal.k.fellows@man.ac.uk>
-
- * unix/tclUnixNotfy.c (Tcl_FinalizeNotifier): Add dummy variable
- so threaded build compiles.
-
-2005-06-06 Kevin B. Kenny <kennykb@acm.org>
-
- * win/tclWin32Dll.c: Corrected another buglet in the assembly code for
- stack probing on Win32/gcc. [Bug 1213678]
-
-2005-06-03 Daniel Steffen <das@users.sourceforge.net>
-
- *** 8.4.10 TAGGED FOR RELEASE ***
+2008-04-10 Andreas Kupries <andreask@activestate.com>
- * unix/tclLoadDyld.c: fixed header conflict when building this file
- with USE_TCL_STUBS.
+ * generic/tclIOCmd.c (Tcl_FcopyObjCmd): Keeping check for negative
+ values, changed to not be an error, but behave like the special
+ value -1 (copy all, default).
- * macosx/Makefile: fixed 'embedded' target.
+ * tests/iocmd.test (iocmd-15.{12,13}): Removed.
-2005-06-02 Jeff Hobbs <jeffh@ActiveState.com>
+ * tests/io.test (io-52.5{,a,b}): Reverted last change, added
+ * tests/chanio.test (chan-io-52.5{,a,b}): comment regarding the
+ meaning of -1, added two more testcases for other negative values,
+ and input wrapped to negative.
- * unix/Makefile.in (html): add BUILD_HTML_FLAGS optional var
- * tools/tcltk-man2html.tcl: add a --useversion to prevent
- confusion when multiple Tcl source dirs exist.
+2008-04-09 Andreas Kupries <andreask@activestate.com>
- * changes: updated for 8.4.10 release (porter)
+ * tests/chanio.test (chan-io-52.5): Removed '-size -1' from test,
+ * tests/io.test (io-52.5): does not seem to have any bearing, and
+ was an illegal value.
-2005-05-31 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+ * generic/tclIOCmd.c (Tcl_FcopyObjCmd): Added checking of -size
+ * tests/ioCmd.test (iocmd-15.{13,14}): value to reject negative
+ values, and values overflowing 32-bit signed. [Bug 1557855]. Basic
+ patch by Alexandre Ferrieux <ferrieux@users.sourceforge.net>, with
+ modifications from me to separate overflow from true negative
+ value. Extended testsuite.
- * unix/tclUnixNotfy.c: the notifier thread is now created as
- joinable thread and it is properly joined in Tcl_FinalizeNotifier.
- This is an attempt to fix [Bug 1082283]
+2008-04-08 Andreas Kupries <andreask@activestate.com>
-2005-05-29 Jeff Hobbs <jeffh@ActiveState.com>
+ * tests/io.test (io-53.8): Fixed ordering of vwait and after
+ cancel. cancel has to be done after the vwait completes.
- * win/tclWinThrd.c (TclpFinalizeThreadData): move tlsKey defn
- to top of file and clarify name (was 'key'). [Bug 1204064]
+2008-04-09 Daniel Steffen <das@users.sourceforge.net>
-2005-05-27 Jeff Hobbs <jeffh@ActiveState.com>
+ * tests/chanio.test (chan-io-53.8,53.9,53.10): fix typo & quoting for
+ * tests/io.test (io-53.8,53.9,53.10): spaces in builddir path
- * README: Bumped patchlevel to 8.4.10
- * generic/tcl.h:
- * tools/tcl.wse.in:
- * unix/tcl.spec, unix/configure, unix/configure.in:
- * win/configure, win/configure.in:
+2008-04-07 Andreas Kupries <andreask@activestate.com>
-2005-05-26 Daniel Steffen <das@users.sourceforge.net>
+ * tests/io.test (io-53.10): Testcase for bi-directionaly fcopy.
+ * tests/chanio.test:
+ * generic/tclIO.c: Additional changes to data structures for fcopy
+ * generic/tclIO.h: and channels to perform proper cleanup in case
+ of a channel having two background copy operations running as is
+ now possible.
- * macosx/Makefile: moved & corrected EMBEDDED_BUILD check.
+ * tests/io.test (io-53.10): Testcase for bi-directionaly fcopy.
+ * generic/tclIO.c: Additional changes to data structures for fcopy
+ and channels to perform proper cleanup in case of a channel having
+ two background copy operations running as is now possible.
- * unix/configure.in: corrected framework finalization to softlink
- stub library to Versions/8.x subdir instead of Versions/Current.
- * unix/configure: autoconf-2.13
+2008-04-07 Andreas Kupries <andreask@activestate.com>
-2005-05-25 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclIO.c (BUSY_STATE, CheckChannelErrors,
+ TclCopyChannel): New macro, and the places using it. This change
+ allows for bi-directional fcopy on channels. [Bug 1350564]. Thanks
+ to Alexandre Ferrieux <ferrieux@users.sourceforge.net> for the
+ patch.
- * generic/tclCmdMZ.c (Tcl_TimeObjCmd): add necessary cast
+2008-04-07 Reinhard Max <max@suse.de>
- * unix/configure, unix/configure.in: ensure false Tcl.framework is
- only created with --enable-framework
+ * generic/tclStringObj.c (Tcl_AppendFormatToObj): Fix [format {% d}]
+ so that it behaves the same way as in 8.4 and as C's printf().
+ * tests/format.test: Add a test for '% d' and '%+d'.
-2005-05-24 Daniel Steffen <das@users.sourceforge.net>
+2008-04-05 Kevin B. Kenny <kennykb@acm.org>
- * tests/env.test: added DYLD_FRAMEWORK_PATH to the list of env vars
- that need to be handled specially.
+ * tests/chanio.test (chan-io-53.9):
+ * tests/io.test (io-53.9): Made test cleanup robust against the
+ possibility of slow process shutdown on Windows.
+
+ * win/tcl.m4: Added -D_CRT_SECURE_NO_DEPRECATE and
+ -DCRT_NONSTDC_NO_DEPRECATE to the MSVC compilation flags so that
+ the compilation doesn't barf on perfectly reasonable Posix system
+ calls.
+ * win/configure: Manually patched (don't have the right autoconf
+ to hand).
+
+ * win/tclWinFile.c: (WinSymLinkDirectory): Fixed a problem that
+ Tcl was creating an NTFS junction point (IO_REPARSE_TAG_MOUNT_POINT)
+ but filling in the union member for a Vista symbolic link. We had
+ gotten away with this error because the union member
+ (SymbolicLinkReparseBuffer) was misdefined in this file and in the
+ 'winnt.h' in early versions of MinGW. MinGW 3.4.2 has the correct
+ definition of SymbolicLinkReparseBuffer, exposing the mismatch,
+ and making tests cmdAH-19.4.1, fCmd-28.*, and filename-11.* fail.
- * macosx/Makefile:
- * macosx/README:
- * macosx/Tcl-Info.plist.in (new file):
- * unix/Makefile.in:
- * unix/configure.in:
- * unix/tcl.m4:
- * unix/tclUnixInit.c: moved all Darwin framework build support from
- macosx/Makefile into the standard unix configure/make buildsystem, the
- macosx/Makefile is no longer required to build Tcl.framework (but its
- functionality is still available for backwards compatibility).
- * unix/configure: autoconf-2.13
+2008-04-04 Andreas Kupries <andreask@activestate.com>
- * generic/tclIOUtil.c (TclLoadFile):
- * generic/tclInt.h:
- * unix/tcl.m4:
- * unix/tclLoadDyld.c: added support for [load]ing .bundle binaries in
- addition to .dylib's: .bundle's can be [unload]ed (unlike .dylib's),
- and can be [load]ed from memory, e.g. directly from VFS without
- needing to be written out to a temporary location first. [Bug 1202209]
- * unix/configure: autoconf-2.13
+ * tests/io.test (io-53.9): Added testcase for [Bug 780533], based
+ * tests/chanio.test: on Alexandre's test script. Also fixed
+ problem with timer in preceding test, was not canceled properly in
+ the ok case.
- * generic/tclCmdMZ.c (Tcl_TimeObjCmd): change [time] called with a
- count > 1 to return a string with a float value instead of a rounded
- off integer. [Bug 1202178]
+2008-04-04 Andreas Kupries <andreask@activestate.com>
-2005-05-20 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+ * generic/tclIORChan.c (ReflectOutput): Allow zero return from
+ write when input was zero-length anyway. Otherwise keept it an
+ error, and separate the message from 'written too much'.
- * generic/tclParseExpr.c: removed unreferenced stack variable "errMsg"
- probably included by fixing [Bug 1201589] (see below).
+ * tests/ioCmd.test (iocmd-24.6): Testcase updated for changed
+ message.
-2005-05-20 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclIORChan.c (ReflectClose): Added missing removal of
+ the now closed channel from the reflection map. Before we could
+ crash the system by invoking 'chan postevent' on a closed
+ reflected channel, dereferencing the dangling pointer in the map.
- * generic/tclParseExpr.c: Corrected parser to recognize all
- boolean literals accepted by Tcl_GetBoolean, including prefixes like
- "y" and "f", and to allow "eq" and "ne" as function names in the
- proper context. [Bug 1201589]
+ * tests/ioCmd.test (iocmd-31.8): Testcase for the above.
-2005-05-19 Daniel Steffen <das@users.sourceforge.net>
+2008-04-03 Andreas Kupries <andreask@activestate.com>
- * macosx/tclMacOSXNotify.c (Tcl_InitNotifier): fixed crashing
- CFRelease of runLoopSource in Tcl_InitNotifier (reported by Zoran):
- CFRunLoopAddSource doesn't CFRetain, so can only CFRelease the
- runLoopSource in Tcl_FinalizeNotifier.
+ * generic/tclIO.c (CopyData): Applied patch [Bug 1932639] to
+ * tests/io.test: prevent fcopy from calling -command synchronously
+ * tests/chanio.test: the first time. Thanks to Alexandre Ferrieux
+ <ferrieux@users.sourceforge.net> for report and patch.
-2005-05-14 Daniel Steffen <das@users.sourceforge.net>
+2008-04-02 Andreas Kupries <andreask@activestate.com>
- * macosx/tclMacOSXBundle.c:
- * unix/tclUnixInit.c:
- * unix/tcl.m4 (Darwin): made use of CoreFoundation API configurable
- and added test of CoreFoundation availablility to allow building on
- ppc64, replaced HAVE_CFBUNDLE by HAVE_COREFOUNDATION; test for
- availability of Tiger or later OSSpinLockLock API.
+ * generic/tclIO.c (CopyData): Applied patch for the fcopy problem
+ [Bug 780533], with many thanks to Alexandre Ferrieux
+ <ferrieux@users.sourceforge.net> for tracking it down and
+ providing a solution. Still have to convert his test script into a
+ proper test case.
- * unix/tclUnixNotfy.c:
- * unix/Makefile.in:
- * macosx/tclMacOSXNotify.c (new file): when CoreFoundation is
- available, use new CFRunLoop based notifier: allows easy integration
- with other event loops on Mac OS X, in particular the TkAqua Carbon
- event loop is now integrated via a standard tcl event source (instead
- of TkAqua upon loading having to finalize the exsting notifier and
- replace it with its custom version). [Patch 1202052]
+2008-04-01 Andreas Kupries <andreask@activestate.com>
- * tests/unixNotfy.test: don't run unthreaded tests on Darwin since
- notifier may be using threads even in unthreaded core.
+ * generic/tclStrToD.c: Applied patch for [Bug 1839067] (fp
+ * unix/tcl.m4: rounding setup on solaris x86, native cc), provided
+ * unix/configure: by Michael Schlenker. configure regen'd.
- * unix/tclUnixPort.h:
- * unix/tcl.m4 (Darwin): test for thread-unsafe realpath durning
- configure, as Darwin 7 and later realpath is threadsafe.
+2008-04-01 Don Porter <dgp@users.sourceforge.net>
- * macosx/tclMacOSXBundle.c:
- * unix/tclLoadDyld.c:
- * unix/tclUnixInit.c: fixed gcc 4.0 warnings.
+ * generic/tclStubLib.c (Tcl_InitStubs): Added missing error message.
+ * generic/tclPkg.c (Tcl_PkgInitStubsCheck):
- * unix/configure: autoconf-2.13
+2008-03-30 Kevin Kenny <kennykb@acm.org>
-2005-05-10 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclInt.h (TclIsNaN):
+ * unix/configure.in: Added code to the configurator to check for
+ a standard isnan() macro and use it if one
+ is found. This change avoids bugs where
+ the test of ((d) != (d)) is optimized away
+ by an overaggressive compiler. [Bug 1783544]
+ * generic/tclObj.c: Added missing #include <math.h> needed to
+ locate isnan() after the above change.
- * tests/string.test: string-10.[21-30]
- * generic/tclCmdMZ.c (Tcl_StringObjCmd): add extra checks to
- prevent possible UMR in unichar cmp function for string map.
+ * unix/configure: autoconf-2.61
-2005-05-06 Jeff Hobbs <jeffh@ActiveState.com>
+ * tests/mathop.test (mathop-25.9, mathop-25.14): Modified tests
+ to deal with (slightly buggy) math libraries in which pow()
+ returns an incorrectly rounded result. [Bug 1808174]
- * unix/tcl.m4, unix/configure: correct Solaris 10 (5.10) check and
- add support for x86_64 Solaris cc builds.
+2008-03-26 Don Porter <dgp@users.sourceforge.net>
-2005-04-29 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ *** 8.5.2 TAGGED FOR RELEASE ***
- * doc/FileSystem.3: Backport of doc fix. [Bug 1172401]
+ * generic/tcl.h: Bump to 8.5.2 for release.
+ * library/init.tcl:
+ * tools/tcl.wse.in:
+ * unix/configure.in:
+ * unix/tcl.spec:
+ * win/configure.in:
-2005-04-27 Don Porter <dgp@users.sourceforge.net>
+ * unix/configure: autoconf-2.59
+ * win/configure:
- * library/init.tcl: Corrected flaw in interactive command
- * tests/main.test: auto-completion. [Bug 1191409]
+ * changes: Updated for 8.5.2 release.
+
+2008-03-28 Donal K. Fellows <dkf@users.sf.net>
+
+ * tests/fCmd.test: Substantial rewrite to use many more tcltest
+ features. Great reduction in quantity of [catch] gymnastics. Several
+ buggy tests fixed, including one where the result of the previous test
+ was being checked!
+
+2008-03-27 Kevin B. Kenny <kennykb@acm.org>
+
+ * library/tzdata/America/Marigot:
+ * library/tztata/America/St_Barthelemy:
+ * library/tzdata/America/Argentina/San_Luis:
+ * library/tzdata/Asia/Ho_Chi_Minh:
+ * library/tzdata/Asia/Kolkata: (new files)
+ * library/tzdata/America/Caracas:
+ * library/tzdata/America/Havana:
+ * library/tzdata/America/Santiago:
+ * library/tzdata/America/Argentina/Buenos_Aires:
+ * library/tzdata/America/Argentina/Catamarca:
+ * library/tzdata/America/Argentina/Cordoba:
+ * library/tzdata/America/Argentina/Jujuy:
+ * library/tzdata/America/Argentina/La_Rioja:
+ * library/tzdata/America/Argentina/Mendoza:
+ * library/tzdata/America/Argentina/Rio_Gallegos:
+ * library/tzdata/America/Argentina/San_Juan:
+ * library/tzdata/America/Argentina/Tucuman:
+ * library/tzdata/America/Argentina/Ushuaia:
+ * library/tzdata/Asia/Baghdad:
+ * library/tzdata/Asia/Calcutta:
+ * library/tzdata/Asia/Damascus:
+ * library/tzdata/Asia/Saigon:
+ * library/tzdata/Pacific/Easter:
+ Changes up to and including Olson's tzdata2008b.
- * tests/unixInit.test (7.1): Alternative fix for the
- 2005-04-22 commit.
+2008-03-27 Daniel Steffen <das@users.sourceforge.net>
-2005-04-25 Daniel Steffen <das@users.sourceforge.net>
+ * unix/tcl.m4 (SunOS-5.1x): fix 64bit support for Sun cc. [Bug 1921166]
- * compat/string.h: fixed memchr() protoype for __APPLE__ so that we
- build on Mac OS X 10.1 again.
+ * unix/configure: autoconf-2.59
- * generic/tclNotify.c (TclFinalizeNotifier): fixed notifier not being
- finalized in unthreaded core (was testing for notifier initialization
- in current thread by checking thread id != 0 but thread id is always 0
- in untreaded core).
+2008-03-26 Don Porter <dgp@users.sourceforge.net>
- * unix/tclUnixNotfy.c (Tcl_WaitForEvent): sync with HEAD: only declare
- and use timeout var in unthreaded core.
+ * changes: Updated for 8.5.2 release.
- * unix/Makefile.in: added @PLAT_SRCS@ to SRCS and split out
- NOTIFY_SRCS from UNIX_SRCS for parity with UNIX_OBJS & NOTIFY_OBJS.
+2008-03-24 Pat Thoyts <patthoyts@users.sourceforge.net>
- * unix/configure.in: only run check for broken strstr implementation
- if AC_REPLACE_FUNCS(strstr) hasn't already determined that strstr is
- unavailable, otherwise compat/strstr.o will be used twice (resulting
- in duplicate symbol link errors on Mac OS X 10.1)
+ * generic/tclBinary.c: [Bug 1923966] - crash in binary format
+ * tests/binary.test: Added tests for the above crash condition.
- * unix/tcl.m4 (Darwin): added configure checks for recently added
- linker flags -single_module and -search_paths_first to allow building
- with older tools (and on Mac OS X 10.1), use -single_module in
- SHLIB_LD and not just T{CL,K}_SHLIB_LD_EXTRAS, added unexporting from
- Tk of symbols from libtclstub to avoid duplicate symbol warnings,
- added PLAT_SRCS definition for Mac OS X.
- (SC_MISSING_POSIX_HEADERS): added caching of dirent.h check.
- (SC_TCL_64BIT_FLAGS): fixed 'checking for off64_t' message output.
+2008-03-21 Donal K. Fellows <dkf@users.sf.net>
- * unix/configure: autoconf-2.13
+ * doc/switch.n: Clarified documentation in respect of two-argument
+ invokation. [Bug 1899962]
-2005-04-22 Don Porter <dgp@users.sourceforge.net>
+ * tests/switch.test: Added more tests of regexp-mode compilation of
+ the [switch] command. [Bug 1854435]
- * generic/tclCmdMZ.c: Corrected intrep-dependence of
- * tests/string.test: [string is boolean] [Bug 1187123]
+2008-03-20 Donal K. Fellows <dkf@users.sf.net>
-2005-04-22 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tcl.h, generic/tclThreadAlloc.c: Tidied up the declarations
+ of Tcl_GetMemoryInfo so that it is always defined. Will panic when
+ called against a Tcl that was previously built without it at all,
+ which is OK because that also indicates a serious mismatch between
+ memory configuration options.
- * tests/unixInit.test (7.1): fixed failure when running tests with
- -tmpdir arg not set to working dir.
+2008-03-19 Donal K. Fellows <dkf@users.sf.net>
-2005-04-20 Don Porter <dgp@users.sourceforge.net>
+ * generic/tcl.h, generic/tclThreadAlloc.c (Tcl_GetMemoryInfo): Make
+ sure this function is available when direct linking. [Bug 1868171]
- * generic/tclGet.c (Tcl_GetInt): Corrected error that did not
- * generic/tclObj.c (Tcl_GetIntFromObj): permit 0x80000000 to be
- recognized as an integer on TCL_WIDE_INT_IS_LONG systems [Bug 1090869]
+ * tests/reg.test (reg-33.14): Marked nonPortable because some
+ environments have small default stack sizes. [Bug 1905562]
-2005-04-19 Jeff Hobbs <jeffh@ActiveState.com>
+2008-03-18 Andreas Kupries <andreask@activestate.com>
- * tests/winPipe.test (winpipe-6.2): remove -blocking 1 as this one
- can truly block.
+ * library/tm.tcl (::tcl::tm::UnknownHandler): Changed 'source' to
+ 'source -encoding utf-8'. This fixes a portability problem of Tcl
+ Modules pointed out by Don Porter. By using plain 'source' we were at
+ the mercy of 'encoding system', making modules less portable than they
+ could be. The exact scenario: A writes a TM in some weird encoding
+ which is A's system encoding, distributes it, and somewhere else it
+ cannot be read/used because the system encoding is different. Forcing
+ the use of utf-8 makes the module portable.
-2005-04-19 David Gravereaux <davygrvy@pobox.com>
+ ***INCOMPATIBILITY*** for all Tcl Modules already written in non-utf-8
+ compatible encodings.
- * win/tclWinPipe.c: The pipe channel driver now respects the -blocking
- option when closing. The windows pipe driver now has the same behavior
- as the UNIX side. This change is to avoid a hung shell when exiting
- due to open pipes that refuse to close in a graceful manner.
- * doc/open.n: Added a note about -blocking 0 and lack of exit status
- as it had never been documented. [Bug 947693]
+2008-03-18 Don Porter <dgp@users.sourceforge.net>
- ***POTENTIAL INCOMPATIBILITY***
+ * generic/tclExecute.c: Patch from Miguel Sofer to correct the
+ alignment of memory allocated by GrowEvaluationStack(). [Bug 1914503]
- Scripts that use async pipes on windows, must (like the UNIX side) set
- -blocking to 1 before calling [close] to receive the exit status.
+2008-03-18 Andreas Kupries <andreask@activestate.com>
- * tests/winPipe.test (winpipe-6.1/2): added 'fconfigure $f -blocking
- 1' so the exit status can be acquired.
+ * library/tm.tcl (::tcl::tm::Defaults): Modified handling of
+ environment variables. See [Bug 1914604]. Solution slightly different
+ than proposed in the report. Using the underscored form TCLX_y_TM_PATH
+ even if TCLX.y_TM_PATH exists. Also using a loop to cut prevent code
+ replication.
-2005-04-13 David Gravereaux <davygrvy@pobox.com>
+2008-03-16 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclIO.c (Tcl_SetChannelBufferSize): Lowest size limit
- * tests/io.test: changed from ten bytes to one byte. Need for
- * tests/iogt.test: this change was proven by Ross Cartlidge
- <rossc@cisco.com> where [read stdin 1] was grabbing 10 bytes followed
- by starting a child process that was intended to continue reading from
- stdin. Even with -buffersize set to one, nine chars were getting lost
- by the buffersize over reading for the native read() caused by [read].
+ * generic/tclCompCmds.c (TclCompileDictForCmd): Correct the handling
+ of stack space calculation (the jump pattern used was confusing the
+ simple-minded code doing the calculations). [Bug 1903325]
-2005-04-12 Kevin B. Kenny <kennykb@acm.org>
+ * doc/lreplace.n: Clarified documentation of what happens with
+ negative indices. [Bug 1905809] Added example, tidied up formatting.
- * compat/strstr.c: Added default definition of NULL to accommodate
- building on systems with badly broken headers. [Bug 1175161]
+2008-03-14 Don Porter <dgp@users.sourceforge.net>
-2005-04-09 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tclBasic.c (OldMathFuncProc): Same workaround protection
+ from bad TclStackAlloc() alignment. Thanks George Peter Staplin.
- * macosx/README: updated requirements for OS & developer tool versions
- + other small fixes/cleanup.
+ * generic/tclCmdIL.c (Tcl_LsortObjCmd): Use ckalloc() to allocate
+ SortElement arrays instead of TclStackAlloc() which isn't getting
+ alignment right. Workaround for [Bug 1914503].
- * unix/tcl.m4 (Darwin): added -single_module linker flag to
- TCL_SHLIB_LD_EXTRAS and TK_SHLIB_LD_EXTRAS.
- * unix/configure: autoconf-2.13
+2008-03-14 Reinhard Max <max@suse.de>
-2005-04-05 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+ * generic/tclTest.c: Ignore the return value of write() when we are
+ * unix/tclUnixPipe.c: about to exit anyways.
- Set of changes correcting huge memory waste (not a leak) when a thread
- exits. This has been introduced in 8.4.7 within an attempt to
- correctly cleanup after ourselves when Tcl library is being unloaded
- with the Tcl_Finalize() call.
+2008-03-13 Daniel Steffen <das@users.sourceforge.net>
- This fixes the [Bug 1178445].
+ * unix/configure.in: Use backslash-quoting instead of double-quoting
+ * unix/tcl.m4: for lib paths in tclConfig.sh. [Bug 1913622]
+ * unix/configure: autoconf-2.59
- * generic/tclInt.h: added prototypes for TclpFreeAllocCache() and
- TclFreeAllocCache()
+2008-03-13 Don Porter <dgp@users.sourceforge.net>
- * generic/tclThreadAlloc.c: modified TclFinalizeThreadAlloc() to
- explicitly call TclpFreeAllocCache with the NULL-ptr as argument
- signalling cleanup of private tsd key used only by the threading
- allocator.
+ * changes: Updated for 8.5.2 release.
- * unix/tclUnixThrd.c: fixed TclpFreeAllocCache() to recognize when
- being called with NULL argument. This is a signal for it to clean up
- the tsd key associated with the threading allocator.
+ * generic/tclStrToD.c: Resolve identifier conflict over "pow10" with
+ libm in Cygwin and DJGPP. Thanks to Gordon Schumacher and Philip
+ Moore. [Patch 1800636]
- * win/tclWinThrd.c: renamed TclWinFreeAllocCache to TclpFreeAllocCache
- and fixed to recognize when being called with NULL argument. This is a
- signal for it to clean up the tsd key associated with the threading
- allocator.
+2008-03-12 Daniel Steffen <das@users.sourceforge.net>
-2005-04-05 Don Porter <dgp@users.sourceforge.net>
+ * macosx/Tcl.xcodeproj/project.pbxproj: Add support for Xcode 3.1
+ * macosx/Tcl.xcodeproj/default.pbxuser: CODE_SIGN_IDENTITY and
+ * macosx/Tcl-Common.xcconfig: 'xcodebuild install'.
- * generic/tclExecute.c (ExprSrandFunc): Replaced incursions into the
- * generic/tclUtil.c (TclGetIntForIndex): intreps of numeric types with
- simpler calls of Tcl_GetIntFromObj and Tcl_GetLongFromObj, now that
- those routines are better behaved wrt shimmering. [Patch 1177129]
+2008-03-12 Andreas Kupries <andreask@activestate.com>
-2005-03-29 Jeff Hobbs <jeffh@ActiveState.com>
+ * doc/info.n: Replaced {expand} with {*}.
- * win/tcl.m4, win/configure: do not require cygpath in macros to
- allow msys alone as an alternative.
+2008-03-12 Jeff Hobbs <jeffh@ActiveState.com>
- * win/tclWinTime.c (TclpGetDate): use time_t for 'time' [Bug 1163422]
+ * unix/Makefile.in (install-libraries): Bump http to 2.7
+ * win/Makefile.in (install-libraries): Added -myaddr option to allow
+ * library/http/http.tcl (http::geturl): control of selected socket
+ * library/http/pkgIndex.tcl: interface. [Bug 559898]
+ * doc/http.n, tests/http.test: Added -keepalive and
+ -protocol 1.1 with chunked transfer encoding support. [Bug 1063703,
+ 1470377, 219225] (default keepalive is 0)
+ Added ability to override Host in -headers. [Bug 928154]
+ Added -strict option to control URL validation on per-call basis.
+ [Bug 1560506]
-2005-03-18 Don Porter <dgp@users.sourceforge.net>
+2008-03-11 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/tclCompCmds.c (TclCompileIncrCmd): Corrected checks for
- immediate operand usage to permit leading space and sign characters.
- Restores more efficient bytecode for [incr x -1] that got lost in the
- CONST string reforms of Tcl 8.4. [Bug 1165671]
+ * library/http/http.tcl (http::geturl): Add -method option to support
+ * tests/http.test (http-3.1): http PUT and DELETE requests.
+ * doc/http.n: [Bug 1599901, 862554]
- * generic/tclBasic.c (Tcl_EvalEx,TclEvalTokensStandard):
- * generic/tclCmdMZ.c (Tcl_SubstObj):
- * tests/basic.test (basic-46.4): Restored recursion limit
- * tests/parse.test (parse-19.*): testing in nested command
- substitutions within direct script evaluation (Tcl_EvalEx) that got
- lost in the parser reforms of Tcl 8.1. Added tests for correct
- behavior. [Bug 1115904]
+ * library/http/http.tcl: Whitespace changes, code cleanup. Allow http
+ to be re-sourced without overwriting http state.
-2005-03-15 Vince Darley <vincentdarley@users.sourceforge.net>
+2008-03-11 Daniel Steffen <das@users.sourceforge.net>
- * generic/tclFileName.c:
- * win/tclWinFile.c:
- * tests/winFCMd.test: fix to 'file pathtype' and 'file norm' failures
- on reserved filenames like 'COM1:', etc.
+ * generic/tclEncoding.c (LoadEscapeEncoding): Avoid leaking escape
+ sub-encodings, fixes encoding-11.1 failing after iso2022-jp loaded.
+ [Bug 1893053]
-2005-03-15 Kevin B. Kenny <kennykb@acm.org>
+ * macosx/tclMacOSXNotify.c: Avoid using CoreFoundation after fork() on
+ Darwin 9 even when TclpCreateProcess() uses vfork().
- * generic/tclClock.c:
- * generic/tclDate.c:
- * generic/tclGetDate.y:
- * generic/tclInt.decls:
- * unix/tclUnixTime.c:
- * win/tclWinTime.c: Replaced 'unsigned long' variable holding
- times with 'Tcl_WideInt', to cope with systems on which a time_t is
- wider than a long (Win64) [Bug 1163422]
- * generic/tclIntDecls.h: Regen
+ * macosx/Tcl.xcodeproj/project.pbxproj: Add support for Xcode 3.1 and
+ * macosx/Tcl.xcodeproj/default.pbxuser: configs for building with
+ * macosx/Tcl-Common.xcconfig: gcc-4.2 and llvm-gcc-4.2.
-2005-03-15 Pat Thoyts <patthoyts@users.sourceforge.net>
+ * unix/tclUnixPort.h: Workaround vfork() problems
+ in llvm-gcc-4.2.1 -O4 build.
- * unix/tcl.m4: Make it work on OpenBSD again. Imported patch
- from the OpenBSD ports tree.
+ * unix/tclUnixPort.h: Move MODULE_SCOPE compat define
+ to top [Bug 1911102].
-2005-03-10 Don Porter <dgp@users.sourceforge.net>
+ * macosx/GNUmakefile: Fix quoting to allow paths to
+ * macosx/Tcl-Common.xcconfig: ${builddir} and ${INSTALL_ROOT}
+ * unix/Makefile.in: to contain spaces.
+ * unix/configure.in:
+ * unix/install-sh:
+ * unix/tcl.m4:
+ * tests/ioCmd.test:
- * generic/tclCmdMZ.c (TclCheckInterpTraces): Corrected mistaken
- cast of ClientData to (TraceCommandInfo *) when not warranted. Thanks
- to Yuri Victorovich for the report. [Bug 1153871]
+ * unix/configure: autoconf-2.59
-2005-03-08 Jeff Hobbs <jeffh@ActiveState.com>
+ * unix/Makefile.in (install-strip): Strip non-global symbols from
+ dynamic library.
- * win/makefile.vc: clarify necessary defined vars that can come
- from MSVC or the Platform SDK.
+ * unix/tclUnixNotfy.c: Fix warning.
-2005-02-24 Don Porter <dgp@users.sourceforge.net>
+ * tests/exec.test (exec-9.7): Reduce timing sensitivity
+ * tests/socket.test (socket-2.11): (esp. on multi-proc machines).
- * library/tcltest/tcltest.tcl: Better use of [glob -types] to avoid
- * tests/tcltest.test: failed attempts to [source] a directory, and
- similar matters. Thanks to "mpettigr". [Bug 1119798]
+ * tests/fCmd.test (fCmd-9.4): Skip on Darwin 9 (xfail).
- * library/tcltest/pkgIndex.tcl: Bump to tcltest 2.2.8
+2008-03-11 Miguel Sofer <msofer@users.sf.net>
-2005-02-23 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * generic/tclVar.c (TclDeleteNamespaceVars):
+ * tests/var.test (var-8.2): Unset traces on vars should be called with
+ a FQ named during namespace deletion. This was causing infinite loops
+ when unset traces recreated the var, as reported by Julian Noble. [Bug
+ 1911919]
- * doc/CrtChannel.3 (THREADACTIONPROC): Formatting fix. [Bug 1149605]
+2008-03-10 Don Porter <dgp@users.sourceforge.net>
-2005-02-17 Jeff Hobbs <jeffh@ActiveState.com>
+ * changes: Updated for 8.5.2 release.
- * win/tclWinFCmd.c (TraverseWinTree): use wcslen on wchar, not
- Tcl_UniCharLen.
+ * doc/http.n: Revised to indicate that [package require http 2.5.5]
+ is needed to get all the documented commands ([http::meta]).
-2005-02-16 Miguel Sofer <msofer@users.sf.net>
+ * generic/tclEvent.c (TclDefaultBgErrorHandlerObjCmd): Added error
+ * tests/event.test (event-5.*): checking to protect against callers
+ passing invalid return options dictionaries. [Bug 1901113]
- * doc/variable.n: fix for [Bug 1124160], variables are detected by
- [info vars] but not by [info locals].
+ * generic/tclBasic.c (ExprAbsFunc): Revised so that the abs()
+ * tests/expr.test: function and the [::tcl::mathfunc::abs]
+ command do not return the value of -0, or equivalent values with more
+ alarming string reps like -1e-350. [Bug 1893815]
-2005-02-10 Jeff Hobbs <jeffh@ActiveState.com>
+2008-03-07 Andreas Kupries <andreask@activestate.com>
- * unix/Makefile.in: remove SHLIB_LD_FLAGS (only for AIX, inlined
- * unix/tcl.m4: into SHLIB_LD). Combine AIX-* and AIX-5
- * unix/configure: branches in SC_CONFIG_CFLAGS.
- Correct gcc builds for AIX-4+ and HP-UX-11.
+ * generic/tclResult.c (ReleaseKeys): Workaround for [Bug 1904907].
+ Reset the return option keys to NULL to allow full re-initialization
+ by GetKeys(). This introduces a memory leak for the key objects, but
+ gets us around a crash in the finalization of reflected channels when
+ handling returns, either at compile- or runtime. In both cases we
+ access the keys after they have been released by their thread exit
+ handler. A proper fix is entangled with the untangling of the
+ finalization ordering and attendant issues. For now we choose the
+ lesser evil.
-2005-02-10 Miguel Sofer <msofer@users.sf.net>
+2008-03-07 Don Porter <dgp@users.sourceforge.net>
- * generic/tclBasic.c (Tcl_EvalObjEx):
- * tests/basic.test (basic-26.2): preserve the arguments passed to TEOV
- in the pure-list branch, in case the list shimmers away. Fix for [Bug
- 1119369], reported by Peter MacDonald.
+ * generic/tclExecute.c (Tcl_ExprObj): Revised expression bytecode
+ compiling so that bytecodes invalid due to changing context or due to
+ the difference between expressions and scripts are not reused. [Bug
+ 1899164]
-2005-02-10 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * generic/tclCmdAH.c: Revised direct evaluation implementation of
+ [expr] so that [expr $e] caches compiled bytecodes for the expression
+ as the intrep of $e.
- * doc/binary.n: Made the documentation of sign bit masking and
- [binary scan] consistent. [Bug 1117017]
+ * tests/execute.test (execute-6.*): More tests checking that
+ script bytecode is invalidated in the right situations.
-2005-02-01 Don Porter <dgp@users.sourceforge.net>
+2008-03-07 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * generic/tclExecute.c (TclCompEvalObj): Removed stray statement
- left behind in prior code reorganization.
+ * win/configure.in: Add AC_HEADER_STDC to support msys/win64.
-2005-01-28 Jeff Hobbs <jeffh@ActiveState.com>
+2008-03-06 Donal K. Fellows <dkf@users.sf.net>
- * unix/configure, unix/tcl.m4: add solaris 64-bit gcc build
- support. [Bug 1021871]
+ * doc/namespace.n: Minor tidying up. [Bug 1909019]
-2005-01-27 Jeff Hobbs <jeffh@ActiveState.com>
+2008-03-04 Don Porter <dgp@users.sourceforge.net>
- * generic/tclBasic.c (Tcl_ExprBoolean, Tcl_ExprDouble)
- (Tcl_ExprLong): Fix to recognize Tcl_WideInt type. [Bug 1109484]
+ * tests/execute.test (6.3,4): Added tests for [Bug 1899164].
-2005-01-27 Andreas Kupries <andreask@activestate.com>
+2008-03-03 Reinhard Max <max@suse.de>
- TIP#218 IMPLEMENTATION
+ * unix/tclUnixChan.c: Fix mark and space parity on Linux, which uses
+ CMSPAR instead of PAREXT.
- * generic/tclDecls.h: Regenerated from tcl.decls.
- * generic/tclStubInit.c:
+2008-03-02 Miguel Sofer <msofer@users.sf.net>
- * doc/CrtChannel.3: Documentation of extended API,
- * generic/tcl.decls: extended testsuite, and
- * generic/tcl.h: implementation. Removal of old
- * generic/tclIO.c: driver-specific TclpCut/Splice
- * generic/tclInt.h: functions. Replaced with generic
- * tests/io.test: thread-action calls through the
- * unix/tclUnixChan.c: new hooks. Update of all builtin
- * unix/tclUnixPipe.c: channel drivers to version 4.
- * unix/tclUnixSock.c: Windows drivers extended to
- * win/tclWinChan.c: manage thread state in a thread
- * win/tclWinConsole.c: action handler.
- * win/tclWinPipe.c:
- * win/tclWinSerial.c:
- * win/tclWinSock.c:
- * mac/tclMacChan.c:
+ * generic/tclNamesp.c (GetNamespaceFromObj):
+ * tests/interp.test (interp-28.2): Spoil the intrep of an nsNameType
+ obj when the reference crosses interpreter boundaries.
-2005-01-25 Don Porter <dgp@users.sourceforge.net>
+2008-02-29 Don Porter <dgp@users.sourceforge.net>
- * library/auto.tcl: Updated [auto_reset] to clear auto-loaded
- procs in namespaces other than :: [Bug 1101670].
+ * generic/tclResult.c (Tcl_SetReturnOptions): Revised the refcount
+ management of Tcl_SetReturnOptions to become that of a conventional
+ Consumer routine. Thanks to Peter Spjuth for pointing out the
+ difficulties calling Tcl_SetReturnOptions with non-0-count value for
+ options.
+ * generic/tclExecute.c (INST_RETURN_STK): Revised the one caller
+ within Tcl itself which passes a non-0-count value to
+ Tcl_SetReturnOptions().
-2005-01-25 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tclBasic.c (Tcl_AppendObjToErrorInfo): Revised the
+ refcount management of Tcl_AppendObjToErrorInfo to become that of a
+ conventional Consumer routine. This preserves the ease of use for the
+ overwhelming common callers who pass in a 0-count value, but makes the
+ proper call with a non-0-count value less surprising.
+ * generic/tclEvent.c (TclDefaultBgErrorHandlerObjCmd): Revised the
+ one caller within Tcl itself which passes a non-0-count value to
+ Tcl_AppendObjToErrorInfo().
- * unix/tcl.m4 (Darwin): fixed bug with static build linking to dynamic
- library in /usr/lib etc instead of linking to static library earlier
- in search path. [Bug 956908]
- Removed obsolete references to Rhapsody.
- * unix/configure: autoconf-2.13
+2008-02-28 Joe English <jenglish@users.sourceforge.net>
-2005-01-19 Mo DeJong <mdejong@users.sourceforge.net>
+ * unix/tclPort.h, unix/tclCompat.h, unix/tclUnixChan.h: Reduce scope
+ of <sys/filio.h> and <sys/ioctl.h> #includes. [Patch 1903339]
- * win/tclWinChan.c (FileCloseProc): Invoke TclpCutFileChannel() to
- remove a FileInfo from the thread local list before deallocating it.
- This should have been done via an earlier call to Tcl_CutChannel, but
- I was running into a crash in the next call to Tcl_CutChannel during
- the IO finalization stage.
+2008-02-28 Joe English <jenglish@users.sourceforge.net>
-2005-01-17 Vince Darley <vincentdarley@users.sourceforge.net>
+ * unix/tclUnixChan.c, unix/tclUnixNotfy.c, unix/tclUnixPipe.c:
+ Consolidate all code conditionalized on -DUSE_FIONBIO into one place.
+ * unix/tclUnixPort.h, unix/tclUnixCompat.c: New routine
+ TclUnixSetBlockingMode() [Patch 1903339].
- * tests/winFCmd.test: made test independent of current drive. [Bug
- 1066528]
+2008-02-28 Don Porter <dgp@users.sourceforge.net>
-2005-01-10 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * generic/tclBasic.c (TclEvalObjvInternal): Plug memory leak when
+ an enter trace deletes or changes the command, prompting a reparsing.
+ Don't let the second pass lose commandPtr value allocated during the
+ first pass.
- * unix/tclUnixFCmd.c (CopyFile): Convert u_int to unsigned to make
- clashes with types in standard C headers less of a problem. [Bug
- 1098829]
+ * generic/tclCompExpr.c (ParseExpr): Plug memory leak in error
+ message generation.
-2005-01-06 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * generic/tclStringObj.c (Tcl_AppendFormatToObj): [format %llx $big]
+ leaked an mp_int.
- * library/http/http.tcl (http::mapReply): Significant performance
- enhancement by using [string map] instead of [regsub]/[subst], and
- update version requirement to Tcl8.4. [Bug 1020491]
+ * generic/tclCompCmds.c (TclCompileReturnCmd): The 2007-10-18 commit
+ to optimize compiled [return -level 0 $x] [RFE 1794073] introduced a
+ memory leak of the return options dictionary. Fixing that.
-2005-01-05 Donal K. Fellows <donal.k.fellows@man.ac.uk>
-
- * unix/tclUnixInit.c (localeTable): Add encoding mappings for some
- Chinese locales. [Bug 1084595]
-
- * doc/lsearch.n: Convert to other form of emacs mode control
- comment to prevent problems with old versions of man. [Bug 1085127]
+2008-02-27 Pat Thoyts <patthoyts@users.sourceforge.net>
-2004-12-29 Jeff Hobbs <jeffh@ActiveState.com>
+ * library/http/http.tcl: [Bug 705956] - fix inverted logic when
+ cleaning up socket error in geturl.
- * win/tcl.m4, win/configure: update MSVC CFLAGS_OPT to -O2, remove
- -Gs (included in -O2) and -GD (outdated). Use "link -lib" instead
- of "lib" binary and remove -YX for MSVC7 portability. Add
- -fomit-frame-pointer for gcc OPT compiles. [Bug 1092952, 1091967]
+2008-02-27 Kevin B. Kenny <kennykb@acm.org>
-2004-12-13 Kevin B. Kenny <kennykb@acm.org>
+ * doc/clock.n: Corrected minor indentation gaffe in the penultimate
+ paragraph. [Bug 1898025]
+ * generic/tclClock.c (ParseClockFormatArgs): Changed to check that the
+ clock value is in the range of a 64-bit integer. [Bug 1862555]
+ * library/clock.tcl (::tcl::clock::format, ::tcl::clock::scan,
+ (::tcl::clock::add, ::tcl::clock::LocalizeFormat): Fixed bugs in
+ caching of localized strings that caused weird results when localized
+ date/time formats were used. [Bug 1902423]
+ * tests/clock.test (clock-61.*, clock-62.1): Regression tests for [Bug
+ 1862555] and [Bug 1902423].
- * doc/clock.n: Clarify that the [clock scan] command does not accept
- the full range of ISO8601 point-in-time formats. [Bug 1075433]
+2008-02-26 Joe English <jenglish@users.sourceforge.net>
-2004-12-09 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * generic/tclIOUtil.c, unix/tclUnixPort.h, unix/tclUnixChan.c:
+ Remove dead/unused portability-related #defines and unused conditional
+ code. See [Patch 1901828] for discussion.
- * doc/Async.3: Reword for better grammar, better nroff and get the
- flag name right. (Reported by David Welton.)
+2008-02-26 Joe English <jenglish@users.sourceforge.net>
-2004-12-06 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclIORChan.c (enum MethodName),
+ * generic/tclCompExpr.c (enum Marks): More stray trailing ","s
- *** 8.4.9 TAGGED FOR RELEASE ***
+2008-02-26 Joe English <jenglish@users.sourceforge.net>
- * unix/tclUnixNotfy.c (NotifierThreadProc): init numFdBits [Bug
- 1079286]
+ * unix/configure.in(socklen_t test): Define socklen_t as "int" if
+ missing, not "unsigned". Use AC_TRY_COMPILE instead of
+ AC_EGREP_HEADER.
+ * unix/configure: regenerated.
-2004-12-02 Jeff Hobbs <jeffh@ActiveState.com>
+2008-02-26 Joe English <jenglish@users.sourceforge.net>
- * changes: updated for 8.4.9 release
+ * generic/tclCompile.h: Remove stray trailing "," from enum
+ InstOperandType definition (C99ism).
-2004-12-02 Vince Darley <vincentdarley@users.sourceforge.net>
+2008-02-26 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/tclIOUtil.c: fix and new tests for [Bug 1074671] to
- * tests/fileSystem.test: ensure tilde paths are not returned specially
- by 'glob'.
+ * generic/tclUtil.c (TclReToGlob): Fix the handling of the last star
+ * tests/regexpComp.test: possibly being escaped in
+ determining right anchor. [Bug 1902436]
-2004-12-01 Don Porter <dgp@users.sourceforge.net>
+2008-02-26 Pat Thoyts <patthoyts@users.sourceforge.net>
- * library/auto.tcl (tcl_findLibrary): Disabled use of [file normalize]
- that caused trouble with freewrap. [Bug 1072136]
+ * library/http/pkgIndex.tcl: Set version 2.5.5
+ * library/http/http.tcl: It is better to do the [eof] check after
+ trying to read from the socket. No clashes found in testing. Added
+ http::meta command to access the http headers. [Bug 1868845]
-2004-11-26 Don Porter <dgp@users.sourceforge.net>
+2008-02-22 Pat Thoyts <patthoyts@users.sourceforge.net>
- * tests/reg.test (reg-32.*): Added missing testregexp constraints.
+ * library/http/pkgIndex.tcl: Set version 2.5.4
+ * library/http/http.tcl: Always check that the state array exists
+ in the http::status command. [Bug 1818565]
- * library/auto.tcl (tcl_findLibrary): Made sure the uniquifying
- operations on the search path does not also normalize. [Bug 1072136]
+2008-02-13 Don Porter <dgp@users.sourceforge.net>
-2004-11-26 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * generic/tcl.h: Bump version number to 8.5.2b1 to distinguish
+ * library/init.tcl: CVS development snapshots from the 8.5.1 and
+ * unix/configure.in: 8.5.2 releases.
+ * unix/tcl.spec:
+ * win/configure.in:
+ * README
- * doc/dde.n: Resynchonized the documentation with itself and fixed
- some formatting errors.
+ * unix/configure: autoconf (2.59)
+ * win/configure:
-2004-11-25 Zoran Vasiljevic <vasiljevic@users.sf.net>
+2008-02-12 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * doc/Notify.3:
- * doc/Thread.3: Added doc fixes and hints from [Bug 1068077].
+ * generic/tclCompCmds.c (TclCompileSwitchCmd): Corrected logic for
+ * tests/switch.test (switch-10.15): handling -nocase compilation; the
+ -exact -nocase option cannot be compiled currently. [Bug 1891827]
-2004-11-25 Reinhard Max <max@suse.de>
+ * unix/README: Documented missing configure flags. [Bug 1799011]
- * tests/tcltest.test: The order in which [glob] returns the file names
- * tests/fCmd.test: is undefined, so tests should not depend on it.
+2008-02-06 Kevin B. Kenny <kennykb@acm.org>
-2004-11-24 Don Porter <dgp@users.sourceforge.net>
+ * doc/clock.n (%N): Corrected an error in the explanation of the %N
+ format group.
+ * generic/tclClock.c (ClockParseformatargsObjCmd):
+ * library/clock.tcl (::tcl::clock::format):
+ * tests/clock.test (clock-1.0, clock-1.4):
+ Performance enhancements in [clock format] (moving the analysis of
+ $args into C code, holding on to Tcl_Objs with resolved command names,
+ [lassign] in place of [foreach], avoiding [namespace which] for
+ command resolution).
- * unix/tcl.m4 (SC_ENABLE_THREADS): Corrected failure to determine
- the number of arguments for readdir_r on SunOS systems. [Bug 1071701]
+2008-02-04 Don Porter <dgp@users.sourceforge.net>
- * unix/configure: autoconf-2.13
+ *** 8.5.1 TAGGED FOR RELEASE ***
-2004-11-24 Jeff Hobbs <jeffh@ActiveState.com>
+ * changes: Updated for 8.5.1 release.
- * README: Bumped patchlevel to 8.4.9
- * generic/tcl.h:
+ * generic/tcl.h: Bump to 8.5.1 for release.
+ * library/init.tcl:
* tools/tcl.wse.in:
- * unix/tcl.spec, unix/configure, unix/configure.in:
- * win/configure, win/configure.in:
-
-2004-11-24 Kevin B. Kenny <kennykb@acm.org>
-
- * unix/tcl.m4 (SC_ENABLE_THREADS): Corrected bad check for 3-argument
- readdir_r(). [Bug 1001325]
- * unix/configure: Regenerated.
- * unix/tclUnixNotfy.c: Corrected all uses of 'select' to manage their
- masks using the FD_CLR, FD_ISSET, FD_SET, and FD_ZERO macros rather
- than bit-whacking that failed under Solaris-Sparc-64. [Bug 1071807]
-
-2004-11-23 Don Porter <dgp@users.sourceforge.net>
-
- * generic/tclCmdIL.c (InfoVarsCmd): Corrected segfault in new
- * tests/info.test (info-19.6): trivial matching branch [Bug 1072654]
-
-2004-11-23 Vince Darley <vincentdarley@users.sourceforge.net>
-
- * generic/tclPathObj.c: fix and new test for [Bug 1043129] in
- * tests/fileSystem.test: the treatment of backslashes in file join on
- Windows.
-
-2004-11-22 Mo DeJong <mdejong@users.sourceforge.net>
-
- * unix/configure: Regen.
- * unix/tcl.m4 (SC_TCL_64BIT_FLAGS): Define HAVE_TYPE_OFF64_T only when
- off64_t, open64(), and lseek64() are defined. IRIX 5.3 is known to not
- include an open64 function. [Bug 1030465]
-
-2004-11-22 Mo DeJong <mdejong@users.sourceforge.net>
-
- * unix/configure: Regen.
- * unix/tcl.m4 (SC_ENABLE_THREADS): Check for a 2 argument version of
- readdir_r that is known to exists under IRIX 5.3.
- * unix/tclUnixThrd.c (TclpReaddir): Use either 2 arg or 3 arg version
- of readdir_r. [Bug 1001325]
-
-2004-11-19 Reinhard Max <max@suse.de>
-
- *** 8.4.8 TAGGED FOR RELEASE ***
-
- * unix/installManPage: Classic sed doesn't support | in REs.
-
-2004-11-19 Daniel Steffen <das@users.sourceforge.net>
-
- * macosx/Makefile:
* unix/configure.in:
- * unix/tclUnixInit.c (MacOSXGetLibraryPath): changed detection of tcl
- framework build when determining tclLibPath from overloaded
- TCL_LIBRARY to configuration define TCL_FRAMEWORK. [Bug 1068088]
-
- * unix/configure: autoconf-2.13
+ * unix/tcl.spec:
+ * win/configure.in:
- * tests/unixInit.test (7.1): fixed failure when running tests
- with -tmpdir arg not set to working dir.
+ * unix/configure: autoconf-2.59
+ * win/configure:
-2004-11-18 Don Porter <dgp@users.sourceforge.net>
+2008-02-04 Miguel Sofer <msofer@users.sf.net>
- * changes: Final updates for Tcl 8.4.8 release.
+ * generic/tclExecute.c (INST_CONCAT1): Fix optimisation for in-place
+ concatenation (was going over String type)
-2004-11-18 Reinhard Max <max@suse.de>
+2008-02-02 Daniel Steffen <das@users.sourceforge.net>
- * unix/tcl.m4 (SC_CONFIG_MANPAGES): Applied an improved version of
- * unix/configure.in: [Patch 996085], that introduces
- * unix/Makefile.in: --enable-man-suffix.
+ * unix/configure.in (Darwin): Correct Info.plist year substitution in
+ non-framework builds.
- * unix/installManPage: added
- * unix/mkLinks.tcl: removed
- * unix/mkLinks: removed
+ * unix/configure: autoconf-2.59
-2004-11-16 Jeff Hobbs <jeffh@ActiveState.com>
+2008-01-30 Miguel Sofer <msofer@users.sf.net>
- * unix/tclUnixChan.c (TtySetOptionProc): fixed crash configuring
- -ttycontrol on a channel. [Bug 1067708]
+ * generic/tclInterp.c (Tcl_GetAlias): Fix for [Bug 1882373], thanks go
+ to an00na.
-2004-11-16 Andreas Kupries <andreask@activestate.com>
+2008-01-30 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * win/makefile.vc: Fixed bug in installation of http 2.5.
- * win/makefile.bc: Was installed into directory http2.4.
- * win/Makefile.in: This has been corrected.
- * unix/Makefile.in:
- * tools/tcl.wse.in:
- * tools/tclmin.wse:
+ * tools/tcltk-man2html.tcl: Reworked manual page scraper to do a
+ proper job of handling references to Ttk options. [Tk Bug 1876493]
-2004-11-16 Don Porter <dgp@users.sourceforge.net>
+2008-01-29 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * library/auto.tcl: Updated [tcl_findLibrary] search path to
- include the $::auto_path. [RFE 695441]
+ * doc/man.macros (SO, SE): Adjusted macros so that it is possible for
+ Ttk to have its "standard options" on a manual page that is not called
+ "options". [Tk Bug 1876493]
-2004-11-16 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+2008-01-25 Don Porter <dgp@users.sourceforge.net>
- * doc/tclvars.n: Mention global variables set by tclsh and wish so
- they are easier to find. [Patch 1065732]
+ * changes: Updated for 8.5.1 release.
-2004-11-15 Don Porter <dgp@users.sourceforge.net>
+2008-01-23 Don Porter <dgp@users.sourceforge.net>
- * generic/tclCmdMZ.c (Tcl_TraceObjCmd): Fixed Bug 1065378 which failed
- * tests/trace.test (trace-33.1): to permit a variable trace
- created with [trace variable] to be destroyed with [trace remove].
- Thanks to Keith Vetter for the report.
+ * generic/tclInt.h: New macro TclGrowParseTokenArray() to
+ * generic/tclCompCmds.c: simplify code that might need to grow
+ * generic/tclCompExpr.c: an array of Tcl_Tokens in the parsePtr
+ * generic/tclParse.c: field of a Tcl_Parse. Replaces the
+ TclExpandTokenArray() routine via replacing:
+ int needed = parsePtr->numTokens + growth;
+ while (needed > parsePtr->tokensAvailable) {
+ TclExpandTokenArray(parsePtr);
+ }
+ with:
+ TclGrowParseTokenArray(parsePtr, growth);
+ This revision merged over from dgp-refactor branch.
-2004-11-12 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclCompile.h: Demote TclCompEvalObj() from internal stubs to
+ * generic/tclInt.decls: a MODULE_SCOPE routine declared in
+ tclCompile.h.
- * library/init.tcl: Made [unknown] robust in the case that either
- of the variables ::errorInfo or ::errorCode gets unset. [Bug 1063707]
+ * generic/tclIntDecls.h: make genstubs
+ * generic/tclStubInit.c:
-2004-11-12 Jeff Hobbs <jeffh@ActiveState.com>
+2008-01-22 Don Porter <dgp@users.sourceforge.net>
- * generic/tclEncoding.c (TableFromUtfProc): correct crash
- condition when TCL_UTF_MAX == 6. [Bug 1004065]
+ * generic/tclTimer.c (AfterProc): Replace Tcl_EvalEx() with
+ Tcl_EvalObjEx() to evaluate [after] callbacks. Part of trend to favor
+ compiled execution over direct evaluation.
-2004-11-12 Daniel Steffen <das@users.sourceforge.net>
+2008-01-22 Miguel Sofer <msofer@users.sf.net>
- * doc/clock.n:
- * doc/registry.n:
- * doc/upvar.n: fixed *roff errors uncovered by running 'make html'.
+ * generic/tclCmdIl.c (Tcl_LreverseObjCmd):
+ * tests/cmdIL.test (cmdIL-7.7): Fix crash on reversing an empty list.
+ [Bug 1876793]
- * tools/tcltk-man2html.tcl: added faked support for bullet point
- lists, i.e. *nroff ".IP \(bu" syntax.
- Synced other changes from HEAD.
+2008-01-20 Jeff Hobbs <jeffh@ActiveState.com>
-2004-11-11 Daniel Steffen <das@users.sourceforge.net>
+ * unix/README: Minor typo fixes [Bug 1853072]
- * tests/fCmd.test:
- * unix/tclUnixFCmd.c (TraverseUnixTree): added option to rewind() the
- readdir() loop whenever the source hierarchy has been modified by
- traverseProc (e.g. by deleting files); this is required to ensure
- complete traversal of the source hierarchy on certain filesystems like
- HFS+. Added test for failing recursive delete on Mac OS X that was due
- to this. [Bug 1034337]
+ * generic/tclIO.c (TclGetsObjBinary): Operate on topmost channel.
+ [Bug 1869405] (Ficicchia)
- * generic/tclListObj.c (Tcl_ListObjReplace): use memmove() instead of
- manual copy loop to shift list elements. Decreases time spent in
- Tcl_ListObjReplace() from 5.2% to 1.7% of overall runtime of tclbench
- on a ppc 7455 (i.e. 200% speed increase). [Patch 1064243]
+2008-01-17 Don Porter <dgp@users.sourceforge.net>
- * generic/tclHash.c: hoisted some constant pointer dereferences out of
- loops to eliminate redundant loads that the gcc optimizer didn't deal
- with. Decreases time spend in Tcl_FindHashEntry() by 10% over a full
- run of the tcl testuite on a ppc 7455. [Patch 1064243]
+ * generic/tclCompExpr.c: Revision to preserve parsed intreps of
+ numeric and boolean literals when compiling expressions with (optimize
+ == 1).
- * tests/fileName.test:
- * tests/fileSystem.test:
- * tests/io.test:
- * tests/tcltest.test: fixed bugs causing failures when running tests
- with -tmpdir arg not set to working dir.
+2008-01-15 Miguel Sofer <msofer@users.sf.net>
- * macosx/Makefile: corrected path to html help inside framework.
- Prevent parallel make from building several targets at the same time.
+ * generic/tclCompExpr.c: Add an 'optimize' argument to
+ * generic/tclCompile.c: TclCompileExpr() to profit from better
+ * generic/tclCompile.h: literal management according to usage.
+ * generic/tclExecute.c:
-2004-11-09 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * generic/tclCompExpr.c: Fix literal leak in exprs [Bug 1869989] (dgp)
+ * generic/tclExecute.c:
+ * tests/compExpr.test:
- * doc/catch.n: Clarify documentation on return codes. [Bug 1062647]
+ * doc/proc.n: Changed wording for access to non-local variables; added
+ mention to [namespace upvar]. Lame attempt at dealing with
+ documentation. [Bug 1872708]
-2004-11-02 Don Porter <dgp@users.sourceforge.net>
+2008-01-15 Miguel Sofer <msofer@users.sf.net>
- * changes: Updates for Tcl 8.4.8 release.
+ * generic/tclBasic.c: Replacing 'operator' by 'op' in the def of
+ * generic/tclCompExpr.c: struct TclOpCmdClientData to accommodate C++
+ * generic/tclCompile.h: compilers. [Bug 1855644]
-2004-11-02 Don Porter <dgp@users.sourceforge.net>
+2008-01-13 Jeff Hobbs <jeffh@ActiveState.com>
- * library/tcltest/tcltest.tcl: Corrected some misleading
- * tests/tcltest.test (tcltest-26.1,2): displays of ::errorInfo and
- ::errorCode information when the -setup, -body, and/or -cleanup scripts
- return an unexpected return code. Thanks to Robert Seeger for the
- fix. [RFE 1017151]
+ * win/tclWinSerial.c (SerialCloseProc, TclWinOpenSerialChannel): Use
+ critical section for read & write side. [Bug 1353846] (newman)
-2004-11-02 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+2008-01-11 Miguel Sofer <msofer@users.sf.net>
- * generic/tclExecute.c (TclExecuteByteCode): NaN-equality fix from
- Miguel Sofer. [Bug 761471]
+ * unix/tclUnixThrd.c (TclpThreadGetStackSize): Restore stack checking
+ functionality in freebsd. [Bug 1850424]
- * doc/CrtChannel.3 (Tcl_GetChannelMode): Add synopsis. [Bug 1058446]
+ * unix/tclUnixThrd.c (TclpThreadGetStackSize): Fix for crash in
+ freebsd. [Bug 1860425]
-2004-10-31 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+2008-01-10 Don Porter <dgp@users.sourceforge.net>
- * generic/tclCmdIL.c (InfoGlobalsCmd):
- * tests/info.test (info-8.4): Strip leading global-namespace
- specifiers from the pattern argument. [Bug 1057461]
+ * generic/tclStringObj.c (Tcl_AppendFormatToObj): Correct failure to
+ * tests/format.test: account for big.used == 0 corner case in the
+ %ll(idox) format directives. [Bug 1867855]
-2004-10-30 Miguel Sofer <msofer@users.sf.net>
+2008-01-09 George Peter Staplin <georgeps@xmission.com>
- * generic/tclCmdAH.c (Tcl_CatchObjCmd): removed erroneous comment [Bug
- 1029518]
+ * doc/vwait.n: Add a missing be to fix a typo.
-2004-10-29 Don Porter <dgp@users.sourceforge.net>
+2008-01-04 Jeff Hobbs <jeffh@ActiveState.com>
- * library/tcltest/tcltest.tcl: Correct reaction to errors in the
- obsolete processCmdLineArgsHook. [Bug 1055673]
- * library/tcltest/pkgIndex.tcl: Bump to tcltest 2.2.7
+ * tools/tcltk-man2html.tcl (make-man-pages): Make man page title use
+ more specific info on lhs to improve tabbed browser view titles.
-2004-10-28 Andreas Kupries <andreask@activestate.com>
+2008-01-02 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclAlloc.c: Fixed [Bug 1030548], a threaded debug
- * generic/tclThreadAlloc.c: build on Windows now works again. Had to
- * win/tclWinThrd.c: touch Unix as well. Basic patch by Kevin,
- * unix/tclUnixThrd.c: with modifications by myself.
+ * doc/binary.n: Fixed documentation bug reported on tcl-core, and
+ reordered documentation to discourage people from using the hex
+ formatter that is hardly ever useful.
-2004-10-28 Don Porter <dgp@users.sourceforge.net>
+2008-01-02 Don Porter <dgp@users.sourceforge.net>
- * README: Bumped patch level to 8.4.8 to prepare for
- * generic/tcl.h: next patch release.
- * tools/tcl.wse.in:
- * unix/configure.in:
+ * generic/tcl.h: Bump version number to 8.5.1b1 to distinguish
+ * library/init.tcl: CVS development snapshots from the 8.5.0 and
+ * unix/configure.in: 8.5.1 releases.
* unix/tcl.spec:
- * win/README.binary:
* win/configure.in:
+ * README
- * unix/configure: autoconf (2.13)
+ * unix/configure: autoconf (2.59)
* win/configure:
-2004-10-28 Kevin B. Kenny <kennykb@acm.org>
-
- * generic/tclInt.decls:
- * unix/tclUnixTime.c (TclpGmtime, TclpLocaltime):
- * win/tclWinTime.c (TclpGmtime, TclpLocaltime): Changed type
- signatures of TclpGmtime and TclpLocaltime to accept CONST TclpTime_t
- throughout, to avoid any possible confusion in pedantic compilers.
- [Bug 1001319]
- * generic/tclIntDecls.h:
- * generic/tclIntPlatDecls.h: Regenerated.
-
-2004-10-27 Don Porter <dgp@users.sourceforge.net>
-
- * generic/tclCmdAH.c (Tcl_FormatObjCmd): Restored missing line
- from yesterday's 868489 backport that caused failed alloc's on LP64
- systems.
-
- * tests/appendComp.test: Backport test suite fixes of errors
- * tests/autoMkindex.test: revealed by -singleproc 1 -debug 1
- * tests/exec.test: options to make test.
- * tests/execute.test:
- * tests/interp.test:
- * tests/io.test:
- * tests/namespace.test:
- * tests/regexpComp.test:
- * tests/stringComp.test:
- * tests/unixInit.test:
- * tests/winPipe.test:
-
-2004-10-26 Kevin B. Kenny <kennykb@acm.org>
-
- * generic/tclCmdAH.c (Tcl_FormatObjCmd): Backport a missing bit of the
- [Bug 868489] fix.
- * generic/tclObj.c (SetBooleanFromAny): Backport fix for [Bug 1026125]
- * tests/format.test (format-19.1): Additional regression test for
- [Bug 868489].
-
-2004-10-26 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+2007-12-31 Donal K. Fellows <dkf@users.sf.net>
- * doc/*.n: Backporting of documentation updates.
+ * doc/dict.n: Clarified meaning of dictionary values following
+ discussion on comp.lang.tcl.
-2004-10-26 Don Porter <dgp@users.sourceforge.net>
+2007-12-26 Miguel Sofer <msofer@users.sf.net>
- * tests/subst.test (subst-12.3-5): More tests for [Bug 1036649]
+ * generic/tclCmdIL.c: More [lsort] data handling streamlines. The
+ function MergeSort is gone, essentially inlined into Tcl_LsortObjCmd.
+ It is not a straight inlining, two loops over all lists elements where
+ merged in the process: the linked list elements are now built and
+ merged into the temporary sublists in the same pass.
- * tests/compile.test (compile-12.4): Backport test for [Bug 1001997]
- * tests/timer.test (timer-10.1): Backport test for [Bug 1016167]
- * tests/tcltest.test (tcltest-12.3,4): Backport setup corrections.
- * tests/error.test (error-6.3,4,7,9): Backport of some tests.
- * tests/basic.test (basic-49.*):
- * tests/namespace.test (namespace-8.7):
- * tests/init.test (init-2.8): Updated to not rely on http package.
+2007-12-25 Miguel Sofer <msofer@users.sf.net>
- * generic/tclThreadTest.c (ThreadEventProc): Corrected subtle bug
- where the returned (char *) from Tcl_GetStringResult(interp) continued
- to be used without copying or refcounting, while activity on the
- interp continued.
+ * generic/tclCmdIL.c: More [lsort] data handling streamlines. Extra
+ mem reqs of latest patches removed, restored to previous mem profile.
+ Improved -unique handling, now eliminating repeated elems immediately
+ instead of marking them to avoid reinsertion at the end.
-2004-10-14 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+2007-12-23 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/tclUtil.c (TclMatchIsTrivial): Detect degenerate cases of
- glob matching that let us avoid scanning through hash tables.
- * generic/tclCmdIL.c (InfoCommandsCmd, InfoGlobalsCmd, InfoProcsCmd):
- (InfoVarsCmd): Use this to speed up some [info] subcommands.
+ * generic/tclCompCmds.c (TclCompileRegexpCmd): TCL_REG_NOSUB cannot
+ * tests/regexp.test (regexp-22.2): be used because it
+ * tests/regexpComp.test: [Bug 1857126] disallows backrefs.
-2004-10-08 Jeff Hobbs <jeffh@ActiveState.com>
+2007-12-21 Miguel Sofer <msofer@users.sf.net>
- * win/tclWinFile.c (NativeIsExec): correct result of 'file executable'
- to not be case sensitive. [Bug 954263]
+ * generic/tclCmdIL.c: Speed patch for lsort [Patch 1856994].
-2004-10-05 Don Porter <dgp@users.sourceforge.net>
+2007-12-21 Miguel Sofer <msofer@users.sf.net>
- * generic/tclNamesp.c (Tcl_PopCallFrame): Removed Bug 1038021
- workaround. That bug is now fixed.
+ * generic/tclCmdIL.c (Tcl_LsortObjCmd, Tcl_LsearchObjCmd): Avoid
+ calling SelectObjFromSublist when there are no sublists.
-2004-09-30 Don Porter <dgp@users.sourceforge.net>
+2007-12-21 Miguel Sofer <msofer@users.sf.net>
- * generic/tclNamespace.c (TclTeardownNamespace): Tcl_Obj-ified the
- * tests/namespace.test (namespace-8.5,6): save/restore of
- ::errorInfo and ::errorCode during global namespace teardown. Revised
- the comment to clarify why this is done, and added tests that will
- fail if this is not done.
+ * generic/tclCmdIL.c (Tcl_LsortObjCmd): Preallocate a listObj of
+ sufficient length for the sorted list instead of growing it. Second
+ commit replaces calls to Tcl_ListObjAppenElement with direct access to
+ the internal rep.
- * generic/tclResult.c (TclTransferResult): Added safety checks so
- that unexpected undefined ::errorInfo or ::errorCode will not lead to
- a segfault.
+2007-12-19 Don Porter <dgp@users.sourceforge.net>
- * generic/tclVar.c (CallVarTraces): Save/restore the flag values
- * tests/var.test (var-16.1): that define part of the interpreter
- state during variable traces. [Bug 1038021]
+ *** 8.5.0 TAGGED FOR RELEASE ***
-2004-09-30 Miguel Sofer <msofer@users.sf.net>
+ * changes: Updated for 8.5.0 release.
- * tests/subst.test (12.2): test correction.
+2007-12-19 Jeff Hobbs <jeffh@ActiveState.com>
-2004-09-29 Miguel Sofer <msofer@users.sf.net>
+ * generic/tclCompCmds.c (TclCompileSwitchCmd): update switch -regexp
+ * tests/switch.test-14.*: compilation to pass
+ the cflags to INST_REGEXP (changed on 12-07). Added tests for
+ switch -regexp compilation (need more). [Bug 1854399]
- * generic/tclBasic.c (Tcl_EvalEx):
- * tests/subst.test (12.1-2): fix for buffer overflow in [subst], [Bug
- 1036649]
+2007-12-18 Don Porter <dgp@users.sourceforge.net>
-2004-09-23 Mo DeJong <mdejong@users.sourceforge.net>
+ * changes: Updated for 8.5.0 release.
- * unix/dltest/Makefile.in (clean): Fixup make clean rule so that it
- does not delete all files when SHLIB_SUFFIX is set to the empty string
- in a static build. [Bug 1016726]
-
-2004-09-18 Donal K. Fellows <donal.k.fellows@man.ac.uk>
-
- * generic/tclExecute.c (TEBC-INST_LSHIFT,INST_RSHIFT): Ensure that
- large shifts end up shifting correctly. [Bug 868467]
-
-2004-09-15 Daniel Steffen <das@users.sourceforge.net>
-
- * tests/load.test (load-2.3): adopted fix for failure on darwin from
- HEAD.
-
-2004-09-14 Don Porter <dgp@users.sourceforge.net>
-
- * generic/tclObj.c (Tcl_GetIntFromObj): Corrected flaw in returning
- the int value of a wideInteger. [Bug 1027690]
-
-2004-09-10 Donal K. Fellows <donal.k.fellows@man.ac.uk>
-
- * generic/tclObj.c (SetIntOrWideFromAny): Rewritten integral value
- parsing code so that values do not flip so easily between numeric
- representations. Thanks to KBK for this! [Bug 868489]
-
- * generic/tclIO.c (Tcl_Seek): Make sure wide seeks do not fail to set
- ::errorCode on error. [Bug 1025359]
-
-2004-09-10 Andreas Kupries <andreask@activestate.com>
-
- * generic/tcl.h: Micro formatting fixes.
- * generic/tclIOGT.c: Channel version fixed, must be 3, to have
- wideseekProc. Thanks to David Graveraux <davygrvy@pobox.com>.
-
-2004-09-11 Don Porter <dgp@users.sourceforge.net>
-
- * generic/tclNamespace.c (TclGetNamespaceForQualName): Resolved
- longstanding inconsistency in the treatment of the TCL_NAMESPACE_ONLY
- flag revealed by testing the 2004-09-09 commits against Itcl.
- TCL_NAMESPACE_ONLY now acts as specified in the pre-function
- comment, forcing resolution in the passed in context namespace. It has
- been incorrectly forcing resolution in the interp's current namespace.
-
-2004-09-10 Miguel Sofer <msofer@users.sf.net>
-
- * generic/tclExecute.c (INST_CONCAT1): added a peephole optimisation
- for concatting an empty string. This enables replacing the idiom 'K $x
- [set x {}]' by '$x[set x {}]' for fastest execution.
-
-2004-09-09 Don Porter <dgp@users.sourceforge.net>
-
- * generic/tclNamesp.c (Tcl_ForgetImport): Corrected faulty logic that
- * tests/namespace.test: relied exclusively on string matching and
- failed in the presence of [rename]s. [Bug 560297]
- Also corrected faulty prevention of [namespace import] cycles. [Bug
- 1017299]
-
-2004-09-08 Kevin B. Kenny <kennykb@acm.org>
+2007-12-18 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * compat/strftime.c (_conv): Corrected a problem where hour 0 would
- format as a blank format group with %k.
- * tests/clock.test (clock-41.1): Added regression test case for %k at
- the zero hour.
+ * generic/regguts.h, generic/regc_color.c, generic/regc_nfa.c:
+ Fixes for problems created when processing regular expressions that
+ generate very large automata. An enormous number of thanks to Will
+ Drewry <wad_at_google.com>, Tavis Ormandy <taviso_at_google.com>,
+ and Tom Lane <tgl_at_sss.pgh.pa.us> from the Postgresql crowd for
+ their help in tracking these problems down. [Bug 1810264]
-2004-09-07 Kevin B. Kenny <kennykb@acm.org>
+2007-12-17 Don Porter <dgp@users.sourceforge.net>
- * generic/tclTimer.c: Removed a premature optimisation that attempted
- to store the assoc data in the client data; the optimisation caused a
- bug that [after] would overwrite its imports. [Bug 1016167]
+ * changes: Updated for 8.5.0 release.
-2004-09-02 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+2007-12-17 Miguel Sofer <msofer@users.sf.net>
- * doc/lsearch.n: Clarified meaning of -dictionary. [Bug 759545]
+ * generic/tclAlloc.c:
+ * generic/tclExecute.c:
+ * generic/tclInt.h:
+ * generic/tclThreadAlloc.c: Fix alignment for memory returned by
+ TclStackAlloc; insure that all memory allocators align to 16-byte
+ boundaries on 64 bit platforms [Bug 1851832, 1851524]
-2004-09-01 Jeff Hobbs <jeffh@ActiveState.com>
+2007-12-14 Jeff Hobbs <jeffh@ActiveState.com>
- * win/tclWinReg.c (BroadcastValue): WIN64 cast corrections
+ * generic/tclIOUtil.c (FsAddMountsToGlobResult): fix the tail
+ conversion of vfs mounts. [Bug 1602539]
- * win/tclWinDde.c (DdeClientWindowProc):
- (DdeServicesOnAck, DdeEnumWindowsCallback): WIN64 corrections
+ * win/README: updated notes
- * win/tclWin32Dll.c (TclWinCPUID): need _asm for WIN64 (Itanium),
- until we have it, just return unknown. [Bug 1020445]
+2007-12-14 Pat Thoyts <patthoyts@users.sourceforge.net>
-2004-08-30 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * tests/winFile.test: Fixed tests for win2k with long machine name
- * generic/tclCmdMZ.c (Tcl_StringObjCmd): Stop [string map] from
- crashing when its map and input string are the same object.
+2007-12-14 Pat Thoyts <patthoyts@users.sourceforge.net>
-2004-08-27 Daniel Steffen <das@users.sourceforge.net>
+ * win/nmakehlp.c: Support compilation with MSVC9 for AMD64.
+ * win/makefile.vc:
- * tests/env.test: macosx fixes.
+2007-12-13 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
-2004-08-19 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * doc/trace.n: Clarified documentation of enterstep and leavestep
+ traces, including adding example. [Bug 614282, 1701540, 1755984]
- * generic/tclScan.c (Tcl_ScanObjCmd, ValidateFormat): Ensure that the
- %ld conversion works correctly on 64-bit platforms. [Bug 1011860]
+2007-12-12 Don Porter <dgp@users.sourceforge.net>
-2004-08-16 Miguel Sofer <msofer@users.sf.net>
+ * doc/IntObj.3: Update docs for the Tcl_GetBignumAndClearObj() ->
+ Tcl_TakeBignumFromObj() revision [TIP 298]. Added docs for the
+ Tcl_InitBignumFromDouble() routine. [Bug 1446971].
- * doc/SetVar.3:
- * generic/tclTest.c (TestseterrorcodeCmd):
- * generic/tclVar.c (TclPtrSetVar):
- * tests/result.test (result-4.*, result-5.*): [Bug 1008314]
- detected and fixed by dgp.
+ * changes: Updated for 8.5.0 release.
-2004-08-13 Don Porter <dgp@users.sourceforge.net>
+2007-12-10 Jeff Hobbs <jeffh@ActiveState.com>
- * library/msgcat/msgcat.tcl: Added checks to prevent [mclocale]
- * tests/msgcat.test: from registering filesystem paths to possibly
- malicious code to be evaluated by a later [mcload].
- * library/msgcat/pkgIndex.tcl: Bump to msgcat 1.3.3
+ * generic/tclUtil.c (TclReToGlob): reduce escapes in conversion
+ when not necessary
-2004-08-10 Zoran Vasiljevic <vasiljevic@users.sf.net>
+ * generic/tclInt.decls: move TclByteArrayMatch and TclReToGlob
+ * generic/tclIntDecls.h: to tclInt.h from stubs.
+ * generic/tclStubInit.c: Add flags var to TclByteArrayMatch for
+ * generic/tclInt.h: future extensibility
+ * generic/tcl.h: define TCL_MATCH_EXACT doc for Tcl_StringCaseMatch.
+ * doc/StrMatch.3: It is compatible with existing usage.
+ * generic/tclExecute.c (INST_STR_MATCH): flag for TclByteArrayMatch
+ * generic/tclUtil.c (TclByteArrayMatch, TclStringMatchObj):
+ * generic/tclRegexp.c (Tcl_RegExpExecObj):
+ * generic/tclCmdMZ.c (StringMatchCmd): Use TclStringMatchObj
+ * tests/string.test (11.9.* 11.10.*): more tests
- * unix/tclUnixThrd.c (TclpThreadCreate): changed handling of the
- returned thread ID since broken on 64-bit systems (Cray). Thanks to
- Rob Ratcliff for reporting the bug.
+2007-12-10 Joe English <jenglish@users.sourceforge.net>
-2004-07-30 Don Porter <dgp@users.sourceforge.net>
+ * doc/string.n, doc/UniCharIsAlpha.3: Fix markup errors.
+ * doc/CrtCommand.3, doc/CrtMathFnc.3, doc/FileSystem.3,
+ * doc/GetStdChan.3, doc/OpenFileChnl.3, doc/SetChanErr.3,
+ * doc/eval.n, doc/filename.n: Consistency: Move "KEYWORDS" section
+ after "SEE ALSO".
- * generic/tclEvent.c (Tcl_Finalize): Re-organized Tcl_Finalize so
- that Tcl_ExitProc's that call Tcl_Finalize recursively do not cause
- deadlock. [Patch 999084, fixes Tk Bug 714956]
+2007-12-10 Daniel Steffen <das@users.sourceforge.net>
-2004-07-30 Daniel Steffen <das@users.sourceforge.net>
+ * tools/genStubs.tcl: fix numerous issues handling 'macosx',
+ 'aqua' or 'x11' entries interleaved
+ with 'unix' entries [Bug 1834288]; add
+ genStubs::export command
+ [Tk FR 1716117]; cleanup formatting.
- * unix/configure:
- * unix/tcl.m4 (SC_CONFIG_CFLAGS): Darwin: instead of setting PLAT_OBJS
- to explict object files in tcl.m4, refer to MAC_OSX_OBJS makefile var.
- * unix/Makefile.in: added MAC_OSX_OBJS variable.
+ * generic/tcl.decls: use new genstubs 'export' command to
+ * generic/tclInt.decls: mark exported symbols not in stubs
+ * generic/tclTomMath.decls: table [Tk FR 1716117]; cleanup
+ formatting.
-2004-07-28 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclDecls.h: regen with new genStubs.tcl.
+ * generic/tclIntDecls.h: [Bug 1834288]
+ * generic/tclIntPlatDecls.h:
+ * generic/tclPlatDecls.h:
+ * generic/tclStubInit.c:
- * generic/tclMain.c (Tcl_Main, StdinProc): Append newline only to
- * tests/basic.test (basic-46.1): incomplete scripts as part
- of multi-line script construction. Do not add an extra trailing
- newline to the complete script. [Bug 833150]
+2007-12-09 Jeff Hobbs <jeffh@ActiveState.com>
-2004-07-26 Jeff Hobbs <jeffh@ActiveState.com>
+ * tests/io.test, tests/chanio.test (io-73.1): Make sure to invalidate
+ * generic/tclIO.c (SetChannelFromAny): internal rep only after
+ validating channel rep. [Bug 1847044]
- *** 8.4.7 TAGGED FOR RELEASE ***
+2007-12-08 Donal K. Fellows <dkf@users.sf.net>
- * tests/io.test (io-61.1): create file in binary mode for x-plat.
+ * doc/expr.n, doc/mathop.n: Improved the documentation of the
+ operators. [Bug 1823622]
-2004-07-25 Pat Thoyts <patthoyts@users.sourceforge.net>
+ * generic/tclBasic.c (builtInCmds): Corrected list of hidden and
+ * doc/interp.n (SAFE INTERPRETERS): exposed commands so that the
+ documentation and reality now match. [Bug 1662436]
- * generic/tclThreadAlloc.c: Moved the tclInt.h include to provide
- Tcl_Panic which is now required for non-threaded build.
+2007-12-07 Jeff Hobbs <jeffh@ActiveState.com>
-2004-07-22 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclExecute.c (TclExecuteByteCode INST_REGEXP):
+ * generic/tclCompCmds.c (TclCompileRegexpCmd): Pass correct RE
+ compile flags at compile time, and use TCL_REG_NOSUB.
- * tests/eofchar.data (removed): Test io-61.1 now generates its own
- * tests/io.test: file of test data as needed.
+ * generic/tclIOCmd.c (FinalizeIOCmdTSD, Tcl_PutsObjCmd): cache
+ stdout channel object for [puts $str] calls.
-2004-07-21 Don Porter <dgp@users.sourceforge.net>
- * win/tclWinDde.c: Bump to dde 1.2.3 to cover changes
- * library/dde/pkgIndex.tcl: committed on 2004-06-14.
+2007-12-06 Don Porter <dgp@users.sourceforge.net>
- * changes: Updated for Tcl 8.4.7 release.
+ * README: Remove mention of dead comp.lang.tcl.announce
+ newsgroup. [Bug 1846433].
-2004-07-20 Jeff Hobbs <jeffh@ActiveState.com>
+ * unix/README: Mention the stub library created by `make` and warn
+ about the effect of embedded paths in the installed binaries.
+ Thanks to Larry Virden. [Bug 1794084]
- * generic/tclEvent.c: Correct threaded obj allocator to
- * generic/tclInt.h: fully cleanup on exit and allow for
- * generic/tclThreadAlloc.c: reinitialization. [Bug 736426]
- * unix/tclUnixThrd.c: (mistachkin, kenny)
- * win/tclWinThrd.c:
+ * doc/AddErrInfo.3: Documentation for the new routines in TIP 270.
+ * doc/Interp.3:
+ * doc/StringObj.3:
-2004-07-20 Daniel Steffen <das@users.sourceforge.net>
+2007-12-06 Don Porter <dgp@users.sourceforge.net>
- * unix/tcl.m4: fixed Darwin autoconf breakage caused by recent CFLAGS
- reordering.
- * unix/configure: regen
+ * doc/namespace.n: Documentation for zero-argument form of
+ [namespace import] (TIP 261) [Bug 1596416]
- * unix/tclConfig.sh.in: replaced EXTRA_CFLAGS with CFLAGS.
- * unix/dltest/Makefile.in: replaced EXTRA_CFLAGS with DEFS.
+2007-12-06 Jeff Hobbs <jeffh@ActiveState.com>
- * macosx/tclMacOSXBundle.c: dynamically acquire address for
- CFBundleOpenBundleResourceMap symbol, since it is only present in
- full CoreFoundation on Mac OS X and not in CFLite on pure Darwin.
+ * generic/tclInt.h: add TclGetChannelFromObj decl
+ (TclMatchIsTrivial): simplify TclMatchIsTrivial to remove ] check.
-2004-07-19 Jeff Hobbs <jeffh@ActiveState.com>
+2007-12-06 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * unix/Makefile.in, unix/tcl.m4: move (C|LD)FLAGS after their
- * unix/configure.in, unix/configure: _DEFAULT to allow for env setting
- to override m4 switches.
- Consolidate header checks to limit redundancy in configure.
- (CFLAGS_WARNING): Remove -Wconversion, add -fno-strict-aliasing for
- gcc builds (need to suppress 3.x type puning warnings).
- (SC_ENABLE_THREADS): Set m4 to force threaded build when built against
- a threaded Tcl core.
- Reorder configure.in for better 64-bit build configuration, replacing
- EXTRA_CFLAGS with CFLAGS. [Bug 874058]
-2004-07-19 Zoran Vasiljevic <vasiljevic@users.sf.net>
+ * generic/tclBasic.c (Tcl_CreateInterp): Simplify the setting up of
+ * generic/tclIOCmd.c (TclInitChanCmd): the [chan] ensemble. This
+ * library/init.tcl: gets rid of quite a bit of
+ code and makes it possible to understand the whole with less effort.
- * win/tclwinThrd.c: redefined MASTER_LOCK to call TclpMasterLock.
- Fixes [Bug 987967]
+ * generic/tclCompCmds.c (TclCompileEnsemble): Ensure that the right
+ number of tokens are copied. [Bug 1845320]
-2004-07-16 Andreas Kupries <andreask@activestate.com>
+ * generic/tclNamesp.c (TclMakeEnsemble): Added missing release of a
+ DString. [Bug 1845397]
- * generic/tclIOCmd.c (Tcl_FcopyObjCmd): Corrected a typo in the
- generation of error messages and simplified by reusing data in a
- variable instead of retrieving the string again. Fixes [Bug 835289]
+2007-12-05 Jeff Hobbs <jeffh@ActiveState.com>
- * doc/OpenFileChnl.3: Added description of the behaviour of
- Tcl_ReadChars when its 'charsToRead' argument is set to -1. Fixes [Bug
- 934511]
+ * generic/tclIO.h: Create Tcl_Obj for Tcl channels to reduce
+ * generic/tclIO.c: overhead in lookup by Tcl_GetChannel. New
+ * generic/tclIOCmd.c: TclGetChannelFromObj for internal use.
+ * generic/tclIO.c (WriteBytes, WriteChars): add opt check to avoid
+ EOL translation when not linebuffered or using lf. [Bug 1845092]
- * doc/CrtCommand.3: Added note that the arguments given to the command
- proc of a Tcl_CreateCommand are in utf8 since Tcl 8.1. Closing [Patch
- 414778]
+2007-12-05 Miguel Sofer <msofer@users.sf.net>
- * doc/ChnlStack.3: Removed the declaration that the interp argument to
- Tcl_(un)StackChannel can be NULL. This fixes [Bug 881220], reported by
- Marco Maggi <marcomaggi@users.sourceforge.net>.
+ * tests/stack.test: made the tests for stack overflow not care
+ about which mechanism caused the error (interp's recursion limit
+ or C-stack depth detector).
- * tests/socket.test: Accepted two new testcases by Stuart Casoff
- <stwo@users.sourceforge.net> checking that -server and -async don't go
- together [Bug 796534]
+2007-12-05 Jeff Hobbs <jeffh@ActiveState.com>
- * unix/tclUnixNotfy.c (NotifierThreadProc): Accepted Joe Mistachkin's
- patch for [Bug 990500], properly closing the notifier thread when its
- exits.
+ * win/configure, win/tcl.m4 (LIBS_GUI): mingw needs -lole32
+ -loleaut32 but not msvc for Tk's [send]. [Bug 1844749]
-2004-07-15 Andreas Kupries <andreask@activestate.com>
+2007-12-05 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * unix/tclUnixThrd.c (TclpFinalizeMutex): Accepted Joe Mistachkin's
- patch for [Bug 990453], closing leakage of mutexes. They were not
- destroyed properly upon finalization.
+ * generic/tclCmdIL.c (Tcl_LsearchObjCmd): Prevent shimmering crash
+ when -exact and -integer/-real are mixed. [Bug 1844789]
-2004-07-15 Zoran Vasiljevic <vasiljevic@users.sf.net>
+2007-12-03 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclEvent.c (NewThreadProc): Backout of changes to fix [Bug
- 770053]. See SF bugreport for more info.
+ * unix/tclUnixChan.c (CreateSocketAddress): Add extra #ifdef-fery to
+ make code compile on BSD 5. [Bug 1618235, again]
- * generic/tclNotify.c (TclFinalizeNotifier): Added conditional
- notifier finalization based on the fact that an TclInitNotifier has
- been called for the current thread. This fixes [Bug 770053] again.
- Hopefully this time w/o unwanted side-effects.
+2007-12-03 Don Porter <dgp@users.sourceforge.net>
-2004-07-14 Andreas Kupries <andreask@activestate.com>
+ * library/tcltest/tcltest.tcl: Bump tcltest to version 2.3.0 so that
+ * library/tcltest/pkgIndex.tcl: we release a stable tcltest with a
+ * unix/Makefile.in: stable Tcl.
+ * win/Makefile.in:
- * generic/tclIO.h (CHANNEL_INCLOSE): New flag. Set in Tcl_Close
- * generic/tclIO.c (Tcl_UnregisterChannel): while the close callbacks
- * generic/tclIO.c (Tcl_Close): are run. Checked in
- Tcl_Close and Tcl_Unregister to prevent recursive call of [close] in
- the close-callbacks. This is a possible error made by implementors of
- virtual filesystems based on 'tclvfs', thinking that they have to
- close the channel in the close handler for the filesystem.
+2007-12-03 Jeff Hobbs <jeffh@ActiveState.com>
-2004-07-14 Andreas Kupries <andreask@activestate.com>
+ * win/configure, win/tcl.m4 (LIBS_GUI): remove ole32.lib oleaut32.lib
- * generic/tclIO.c:
- * generic/tclIO.h:
- Not reverting, but #ifdef'ing the changes from May 19, 2004 out of the
- core. This removes the ***POTENTIAL INCOMPATIBILITY*** for channel
- drivers it introduced. This has become possible due to Expect gaining
- a BlockModeProc and now handling blockingg and non-blocking modes
- correctly. Thus [Bug 943274] is still fixed if a recent enough version
- of Expect is used.
+2007-12-03 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * doc/CrtChannel.3: Added warning about usage of a channel without a
- BlockModeProc.
+ * generic/tclCompCmds.c (TclCompileSwitchCmd): Adjusted the [switch]
+ * generic/tclCmdMZ.c (Tcl_SwitchObjCmd): command so that when
+ passed two arguments, no check for options are performed. This is OK
+ since in the two-arg case, detecting an option would definitely lead
+ to a syntax error. [Patch 1836519]
-2004-07-15 Andreas Kupries <andreask@pliers.activestate.com>
+2007-11-29 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/tclIOCmd.c (Tcl_PutsObjCmd): Added length check to the old
- depreceated newline syntax, to ensure that only "nonewline" is
- accepted. [Bug 985869] (mistachkin)
+ * win/makefile.vc: add ws2_32.lib to baselibs
+ * win/configure, win/tcl.m4: add ws2_32.lib / -lws2_32 to build.
+ * win/tclWinSock.c: remove dyn loading of winsock, assume that it is
+ always available now.
-2004-07-13 Jeff Hobbs <jeffh@ActiveState.com>
+2007-11-29 Don Porter <dgp@users.sourceforge.net>
- * README, generic/tcl.h, tools/tcl.wse.in: bumped to
- * unix/configure, unix/configure.in, unix/tcl.spec: patchlevel
- * win/README.binary, win/configure, win/configure.in: 8.4.7
+ * generic/tclWinSock.c (InitializeHostName): Correct error in
+ buffer length tracking. After gethostname() writes into a buffer,
+ convert only the written string to internal encoding, not the whole
+ buffer.
-2004-07-13 Zoran Vasiljevic <vasiljevic@users.sf.net>
+2007-11-28 Don Porter <dgp@users.sourceforge.net>
- * generic/tclEvent.c (NewThreadProc): Fixed broken build on Windows
- caused by missing TCL_THREAD_CREATE_RETURN. This is backported from
- HEAD. Thnx to Kevin Kenny for spotting this.
+ * generic/tclConfig.c: Corrected failure of the [::foo::pkgconfig]
+ command to clean up registered configuration data when the query
+ command is deleted from the interp. [Bug 983501]
-2004-07-03 Miguel Sofer <msofer@users.sf.net>
+ * generic/tclNamesp.c (Tcl_SetEnsembleMappingDict): Added checks
+ that the dict value passed in is in the format required to make the
+ internals of ensembles work. [Bug 1436096]
- * generic/tclExecute.c (ExprRoundFunc):
- * tests/expr-old.test (39.1): added support for wide integers to
- round(); [Bug 908375], reported by Hemang Lavana.
+ * generic/tclIO.c: Simplify test and improve accuracy of error
+ message in latest changes.
-2004-07-02 Jeff Hobbs <jeffh@ActiveState.com>
+2007-11-28 Pat Thoyts <patthoyts@users.sourceforge.net>
- * generic/regcomp.c (stid): correct minor pointer size error
+ * generic/tclIO.c: -eofchar must support no eofchar.
- * generic/tclPipe.c (TclCreatePipeline): Add 2>@1 as a special
- * tests/exec.test: case redir of stderr to the result output.
+2007-11-27 Miguel Sofer <msofer@users.sf.net>
-2004-07-02 Vince Darley <vincentdarley@users.sourceforge.net>
+ * generic/tclBasic.c: remove unneeded call in Tcl_CreateInterp, add
+ comments.
- * tests/fileSystem.test: new tests backported
- * win/tclWin32Dll.c: compilation fix for VC++5.2
+2007-11-27 Don Porter <dgp@users.sourceforge.net>
-2004-06-29 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * win/tclWinSock.c: Add mising encoding conversion of the [info
+ hostname] value from the system encoding to Tcl's internal encoding.
- * library/safe.tcl: Make sure that the temporary variable is
- local to the namespace and not inadvertently global. [Bug 981733]
+ * doc/chan.n: "Fix" the limitation on channel -eofchar
+ * doc/fconfigure.n: values to single byte characters by documenting
+ * generic/tclIO.c: it and making it fail loudly. Thanks to Stuart
+ * tests/chan.test: Cassoff for contributing the fix. [Bug 800753]
-2004-06-22 Zoran Vasiljevic <vasiljevic@users.sf.net>
+2007-11-26 Miguel Sofer <msofer@users.sf.net>
- * generic/tclEvent.c:
+ * generic/tclBasic.c:
* generic/tclInt.h:
- * unix/tclUnixNotfy.c:
- * unix/tclUnixThrd.c:
- * win/tclWinThrd.c: See bug report for more information about what it
- does. [Bug 770053]
-
- * tests/unixNotfy.test: rewritten to use tcltest::threadReap to
- gracefully wait for the test thread to exit. Otherwise we got a race
- condition with main thread exiting before the test thread. This
- exposed the long-standing Tcl lib issue with resource
- garbage-collection on application exit.
-
-2004-06-21 Mo DeJong <mdejong@users.sourceforge.net>
-
- * win/tclWin32Dll.c (DllMain, _except_dllmain_detach_handler)
- (TclpCheckStackSpace, _except_checkstackspace_handler, TclWinCPUID)
- (_except_TclWinCPUID_detach_handler):
- * win/tclWinChan.c (Tcl_MakeFileChannel)
- (_except_makefilechannel_handler):
- * win/tclWinFCmd.c (DoRenameFile, _except_dorenamefile_handler)
- (DoCopyFile, _except_docopyfile_handler):
- Rework pushing of exception handler function pointer so that compiling
- with gcc -O3 works. Remove empty function call to avoid compiler
- warning. Mark the DllMain function as noinline to avoid compiler error
- from duplicated asm labels in generated code.
-
-2004-06-14 Pat Thoyts <patthoyts@users.sourceforge.net>
-
- * tests/winDde.test: Fixed -async test
- * win/tclWinDde.c: Backported the fix from 8.5 to avoid hanging in the
- presence of applications that do not process Window messages.
-
-2004-06-10 Andreas Kupries <andreask@activestate.com>
-
- * generic/tclDecls.h: Regenerated on a unix box. The Win/DOS
- * generic/tclIntDecls.h: EOLs from the last regen screwed up
- * generic/tclIntPlatDecls.h: compilation with an older gcc.
- * generic/tclPlatDecls.h:
- * generic/tclStubInit.c:
-
-2004-06-10 Zoran Vasiljevic <vasiljevic@users.sf.net>
-
- * generic/tclIOUtil.c: partially corrected [Bug 932314]. Also,
- corrected return values of Tcl_FSChdir() to reflect those of the
- underlying platform-specific call. Originally, return codes were mixed
- with those of Tcl.
-
-2004-06-08 Miguel Sofer <msofer@users.sf.net>
-
- * generic/tclCompile.c: handle warning [Bug 969066]
-
-2004-06-05 Kevin B. Kenny <kennykb@acm.org>
-
- * generic/tcl.h: Corrected Tcl_WideInt declarations so that the mingw
- build works again.
- * generic/tclDecls.h: Changes to the tests for
- * generic/tclInt.decls: clock frequency in Tcl_WinTime
- * generic/tclIntDecls.h: so that any clock frequency is
- * generic/tclIntPlatDecls.h: accepted provided that all
- * generic/tclPlatDecls.h: CPU's in the system share a
- * generic/tclStubInit.c: common chip, and hence,
- * tests/platform.test (platform-1.3): presumably, a common clock.
- * win/tclWin32Dll.c (TclWinCPUID): This change necessitated a
- * win/tclWinTest.c (TestwincpuidCmd) small burst of assembly code
- * win/tclWinTime.c (Tcl_GetTime): to read CPU ID information,
- which was added as TclWinCPUID in the internal Stubs. To test this
- code in the common case of a single-processor machine, a
- 'testwincpuid' command was added to tclWinTest.c, and a test case in
- platform.test. Thanks to Jeff Godfrey and Richard Suchenwirth for
- reporting this bug. [Bug 976722]
-
-2004-05-27 Kevin B. Kenny <kennykb@acm.org>
-
- * tests/clock.test: Added a single test for the presence of %G in
- [clock format], and conditioned out the clock-10.x series if they're
- all going to fail because of a broken strftime() call. [Bug 961714]
-
-2004-05-27 Reinhard Max <max@suse.de>
-
- * generic/tclEncoding.c:
- * tests/encoding.test: added support and tests for translating
- embedded null characters between real nullbytes and the internal
- representation on input/output. [Bug 949905]
-
-2004-05-26 Don Porter <dgp@users.sourceforge.net>
-
- * library/tcltest/tcltest.tcl: Correction to debug prints and testing
- * library/tcltest/pkgIndex.tcl: if TCLTEST_OPTIONS value. Corrected
- * tests/tcltest.test: double increment of numTestFiles in
- -singleproc 1 configurations. Updated tcltest-19.1 to tcltest 2.1
- behavior. Corrected tcltest-25.3 to not falsely report a failure in
- tcltest.test. Bumped to tcltest 2.2.6. [Bugs 960560, 960926]
-
-2004-05-25 Jeff Hobbs <jeffh@ActiveState.com>
-
- * doc/http.n (http::config): add -urlencoding option (default utf-8)
- * library/http/http.tcl: that specifies encoding conversion of
- * library/http/pkgIndex.tcl: args for http::formatQuery. Previously
- * tests/http.test: undefined, RFC 2718 says it should be
- utf-8. 'http::config -urlencoding {}' returns previous behavior,
- which will throw errors processing non-latin-1 chars. Bumped http
- package to 2.5.0.
-
-2004-05-25 Kevin Kenny <kennykb@acm.org>
-
- * tests/winFCmd.test: Correct test for the presence of a CD-ROM so
- that it doesn't misdetect some other sort of filesystem with a
- write-protected root as being a CD-ROM drive. [Bug 918267]
-
-2004-05-24 Jeff Hobbs <jeffh@ActiveState.com>
+ * unix/tclUnixInit.c:
+ * unix/tclUnixThrd.c: Fix stack checking via workaround for bug in
+ glibc's pthread_attr_get_np, patch from [Bug 1815573]. Many thanks to
+ Sergei Golovan (aka Teo) for detecting the bug and helping diagnose
+ and develop the fix.
- * generic/tclExecute.c (VerifyExprObjType): use GET_WIDE_OR_INT to
- properly have tclIntType used for smaller values. This corrects TclX
- bug 896727 and any other 3rd party extension that created math
- functions but was not yet WIDE_INT aware in them.
+2007-11-24 Donal K. Fellows <dkf@users.sf.net>
-2004-05-24 Miguel Sofer <msofer@users.sf.net>
+ * generic/tclCompCmds.c (TclCompileDictAppendCmd): Fix bug in [dict
+ append] compiler which caused strange stack corruption. [Bug 1837392]
- * doc/set.n: accurate description of name resolution process,
- referring to namespace.n for details [Bug 959180]
+2007-11-23 Andreas Kupries <andreask@activestate.com>
-2004-05-22 Miguel Sofer <msofer@users.sf.net>
+ * generic/tclIORChan.c: Fixed a problem with reflected channels. 'chan
+ postevent' is defined to work only from within the interpreter
+ containing the handler command. Sensible, we want only handler
+ commands to use it. It identifies the channel by handle. The channel
+ moves to a different interpreter or thread. The interpreter containing
+ the handler command doesn't know the channel any longer. 'chan
+ postevent' fails, not finding the channel any longer. Uhm.
- * generic/tclVar.c (TclObjUnsetVar2): backported fix [Bug 735335] and
- new (in tcl8.4) exteriorisations of [Bug 736729] due to the use of
- tclNsVarNameType obj types. The consequences of [Bug 736729] should be
- the same as in tcl8.3 and previous versions. The use of
- tclNsVarNameType objs is still disabled, pending a decision by the
- release manager.
+ Fixed by creating a second per-interpreter channel table, just for
+ reflected channels, where each interpreter remembers for which
+ reflected channels it has the handler command. This info does not move
+ with the channel itself. The table is updated by 'chan create', and
+ used by 'chan postevent'.
-2004-05-19 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * tests/ioCmd.test: Updated the testsuite.
- * win/tclWinFile.c (TclpMatchInDirectory): fix for an issue where
- there was a sneak path from Tcl_DStringFree to SetErrorCode(0). The
- result was that the error code could be reset between a call to
- FindFirstFile and the check of its status return, leading to a bizarre
- error return of {POSIX unknown {No error}}. (Found in unplanned test -
- no incident logged at SourceForge.)
+2007-11-23 Jeff Hobbs <jeffh@ActiveState.com>
-2004-05-19 Andreas Kupries <andreask@activestate.com>
+ * generic/tclVar.c (Tcl_ArrayObjCmd): handle the right data for
+ * tests/var.test (var-14.2): [array names $var -glob $ptn]
- * generic/tclIO.c: Fixed [SF Tcl Bug 943274]. This is the same problem
- * generic/tclIO.h: as [SF Tcl Bug 462317], see ChangeLog entry
- 2001-09-26. The fix done at that time is incomplete. It is possible to
- get around it if the actual read operation is defered and not executed
- in the event handler itself. Instead of tracking if we are in an read
- caused by a synthesized fileevent we now track if the OS has delivered
- a true event = actual data and bypass the driver if a read finds that
- there is no actual data waiting. The flag is cleared by a short or
- full read. [[this bug amended 2004-07-14]]
+2007-11-23 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
-2004-05-18 Kevin B. Kenny <kennykb@acm.org>
+ * generic/tclCmdMZ.c (String*Cmd, TclInitStringCmd): Rebuilt [string]
+ * generic/tclCompCmds.c (TclCompileString*Cmd): as an ensemble.
- * compat/strftime.c (_fmt, ISO8601Week):
- * doc/clock.n:
- * tests/clock.test: Major rework to the handling of ISO8601 week
- numbers. Now passes all the %G and %V test cases on Windows, Linux and
- Solaris [Bugs 500285, 500389, and 852944]
+2007-11-22 Donal K. Fellows <dkf@users.sf.net>
-2004-05-17 Kevin B. Kenny <kennykb.@acm.org>
+ * generic/tclDictObj.c (Dict*Cmd,TclInitDictCmd): Rebuilt the [dict]
+ * generic/tclCompCmds.c (TclCompileDict*Cmd): command as an ensemble.
- * generic/tclInt.decls: Restored TclpTime_t kludge to all places
- * generic/tclIntPlatDecls.h: where it appeared before the changes of
- * unix/tclUnixPort.h 14 May, because use of native time_t in
- * unix/tclUnixTime.h its place requires the 8.5 header
- * win/tclWinTime.h: reforms. [Bug 955146]
+2007-11-22 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
-2004-05-17 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd): Rewrote the [string] and
+ * generic/tclDictObj.c (Tcl_DictObjCmd): [dict] implementations to be
+ ready for conversion to ensembles.
- * doc/OpenFileChnl.3: Documented type of 'offset' argument to Tcl_Seek
- was wrong. [Bug 953374]
+ * tests/string.test (string-12.22): Flag shimmering bug found in
+ [string range].
-2004-05-14 Kevin B. Kenny <kennykb@acm.org>
+2007-11-21 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclInt.decls: Promoted TclpLocaltime and TclpGmtime
- * generic/tclIntDecls.h: from Unix-specific stubs to the generic
- * generic/tclIntPlatDecls.h: internal Stubs table. Reran 'genstubs'
- * generic/tclStubInit.c:
- * unix/tclUnixPort.h:
+ * generic/tclCompCmds.c (TclCompileEnsemble): Rewrote the ensemble
+ compiler to remove many of the limitations. Can now compile scripts
+ that use unique prefixes of subcommands, and which have mappings of a
+ command to multiple words (provided the first is a compilable command
+ of course).
- * generic/tclClock.c: Changed a buggy 'GMT' timezone specification to
- the correct 'GMT0'. [Bug 922848]
+2007-11-21 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * unix/tclUnixThrd.c: Moved TclpGmtime and TclpLocaltime to
- unix/tclUnixTime.c where they belong.
+ * generic/tclNamesp.c (TclMakeEnsemble): Factor out the code to set up
+ a core ensemble from a table of information about subcommands, ready
+ for reuse within the core.
- * unix/tclUnixTime.c (TclpGmtime, TclpLocaltime, TclpGetTimeZone,
- (ThreadSafeGMTime[removed], ThreadSafeLocalTime[removed],
- (SetTZIfNecessary, CleanupMemory): Restructured to make sure that the
- same mutex protects all calls to localtime, gmtime, and tzset. Added a
- check in front of those calls to make sure that the TZ env var hasn't
- changed since the last call to tzset, and repeat tzset if necessary.
- [Bug 940278] Removed a buggy test of the Daylight Saving Time
- information in 'gettimeofday' in favor of applying 'localtime' to a
- known value. [Bug 922848]
+ * generic/various: Start to return more useful Error codes, currently
+ mainly on assorted lookup failures.
- * tests/clock.test (clock-3.14): Added test to make sure that changes
- to $env(TZ) take effect immediately.
+2007-11-20 Donal K. Fellows <dkf@users.sf.net>
- * win/tclWinTime.c (TclpLocaltime, TclpGmtime): Added porting layer
- for 'localtime' and 'gmtime' calls.
+ * generic/tclDictObj.c: Changed the underlying implementation of the
+ hash table used in dictionaries to additionally keep all entries in
+ the hash table in a linked list, which is only ever added to at the
+ end. This makes iteration over all entries in the dictionary in
+ key insertion order a trivial operation, and so cleans up a great deal
+ of complexity relating to dictionary representation and stability of
+ iteration order.
-2004-05-10 David Gravereaux <davygrvy@pobox.com>
+ ***POTENTIAL INCOMPATIBILITY***
+ For any code that depended on the (strange) old iteration order.
- * win/tclWinPipe.c (BuildCommandLine): Append a space when the path
- got primed.
- (TclpCreateProcess): When under NT, with no console, and executing a
- DOS application, the path priming does not need an ending space as
- BuildCommandLine() will append one for us.
+ * generic/tclConfig.c (QueryConfigObjCmd): Correct usage of
+ Tcl_WrongNumArgs.
-2004-05-07 Miguel Sofer <msofer@users.sf.net>
+2007-11-19 Don Porter <dgp@users.sourceforge.net>
- * doc/unset.n: added upvar.n to the "see also" list
+ *** 8.5b3 TAGGED FOR RELEASE ***
-2004-05-05 David Gravereaux <davygrvy@pobox.com>
+ * README: Bump version number to 8.5b3.
+ * generic/tcl.h:
+ * library/init.tcl:
+ * tools/tcl.wse.in:
+ * unix/configure.in:
+ * unix/tcl.spec:
+ * win/configure.in:
- * generic/tclEvent.c: TclSetLibraryPath's use of caching the stringrep
- of the pathPtr object to TclGetLibraryPath called from another thread
- was ineffective if the original's stringrep had been invalidated as
- what happens when it gets muted to a list.
+ * unix/configure: autoconf (2.59)
+ * win/configure:
- * generic/tclEncoding.c: Added FreeEncoding(systemEncoding) in
- TclFinalizeEncodingSubsystem because its ref count was incremented in
- TclInitEncodingSubsystem.
+ * changes: Updated for 8.5b3 release.
- * win/tclWin32Dll.c: Structured Exception Handling added around
- Tcl_Finalize called from DllMain's DLL_PROCESS_DETACH. We can't be
- 100% assured that Tcl is being unloaded by the OS in a stable
- condition and we need to protect the exit handlers should the stack be
- in a hosed state. AT&T style assembly for SEH under MinGW included,
- too. [Patch 858493]
+2007-11-19 Kevin Kenny <kennykb@users.sourceforge.net>
- Also added DisableThreadLibraryCalls() for the DLL_PROCESS_ATTACH
- case. We're not interested in knowing about DLL_THREAD_ATTACH, so
- disable the notices.
+ * library/tzdata/Africa/Cairo:
+ * library/tzdata/America/Campo_Grande:
+ * library/tzdata/America/Caracas:
+ * library/tzdata/America/Cuiaba:
+ * library/tzdata/America/Havana:
+ * library/tzdata/America/Sao_Paulo:
+ * library/tzdata/Asia/Damascus:
+ * library/tzdata/Asia/Gaza:
+ * library/tzdata/Asia/Tehran: Olson's tzdata2007i imported.
- * generic/tclInt.h:
- * generic/tclThread.c:
- * generic/tclEvent.c:
- * unix/tclUnixThrd.c:
- * win/tclWinThrd.c: Provisions made so masterLock, initLock,
- allocLock and joinLock mutexes can be recovered during Tcl_Finalize.
+2007-11-18 Daniel Steffen <das@users.sourceforge.net>
- * win/tclWinSock.c:
- (SocketThreadExitHandler): Don't call TerminateThread when
- WaitForSingleObject returns a timeout. Tcl_Finalize called from
- DllMain will pause all threads. Trust that the thread will get the
- close notice at a later time if it does ever wake up before being
- cleaned up by the system anyway.
- (SocketEventProc): connect errors should fire both the readable and
- writable handlers because this is how it works on UNIX. [Bug 794839]
+ * generic/tclExecute.c (TclExecuteByteCode:INST_EXIST_*): Fix read
+ traces not firing on non-existent array elements. [Bug 1833522]
- * win/coffbase.txt: Added the tls extension to the list of preferred
- load addresses.
+2007-11-16 Donal K. Fellows <donal.k.fellows@man.ac.uk>
-2004-05-05 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclCmdIL.c (TclInitInfoCmd): Rename the implementation
+ commands for [info] to be something more "expected".
- * tests/unixInit.test (unixInit-2.10): Test correction for Mac OSX.
- Be sure to consistently compare normalized path names. Thanks to
- Steven Abner (tauvan). [Bug 948177]
+ * generic/tclCompCmds.c (TclCompileInfoExistsCmd): Compiler for the
+ [info exists] subcommand.
+ (TclCompileEnsemble): Cleaned up version of ensemble compiler that was
+ in TclCompileInfoCmd, but which is now much more generally applicable.
-2004-05-05 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * generic/tclInt.h (ENSEMBLE_COMPILE): Added flag to allow for cleaner
+ turning on and off of ensemble bytecode compilation.
- * doc/CrtObjCmd.3: Remove reference to Tcl_RenameCommand; there is no
- such API. [Bug 848440]
+ * generic/tclCompile.c (TclCompileScript): Add the cmdPtr to the list
+ of arguments passed to command compilers.
-2004-05-04 Jeff Hobbs <jeffh@ActiveState.com>
+2007-11-15 Don Porter <dgp@users.sourceforge.net>
- * generic/tclIOUtil.c (Tcl_FSChdir): Work-around crash condition
- * tests/winFCmd.test (winFCmd-16.12): triggered when $HOME is
- volumerelative (ie 'C:').
+ * generic/regc_nfa.c: Fixed infinite loop in the regexp compiler.
+ [Bug 1810038]
- * tests/fileName.test (filename-12.9): use C:/ instead of the first
- item in file volumes - that's usually A:/, which for most will have
- nothing in it.
+ * generic/regc_nfa.c: Corrected looping logic in fixempties() to
+ avoid wasting time walking a list of dead states. [Bug 1832612]
-2004-05-04 Don Porter <dgp@users.sourceforge.net>
+2007-11-15 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * tests/tcltest.test: Test corrections for Mac OSX. Thanks to Steven
- Abner (tauvan). [Bug 947440]
+ * generic/tclNamesp.c (NamespaceEnsembleCmd): Must pass a non-NULL
+ interp to Tcl_SetEnsemble* functions.
-2004-05-03 Andreas Kupries <andreask@activestate.com>
+ * doc/re_syntax.n: Try to make this easier to read. It's still a very
+ difficult manual page!
- Applied [SF Tcl Patch 868853], fixing a mem leak in TtySetOptionProc.
- Report and Patch provided by Stuart Cassoff <stwo@users.sf.net>.
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): Allow people to turn off the -rpath
+ option to their linker if they so desire. This is a configuration only
+ recommended for (some) vendors. Relates to [Patch 1231022].
-2004-05-03 Kevin Kenny <kennykb@acm.org>
+2007-11-15 Pat Thoyts <patthoyts@users.sourceforge.net>
- * win/tclWin32Dll.c (TclpCheckStackSpace):
- * tests/stack.test (stack-3.1): Fix for undetected stack overflow in
- TclReExec on Windows. [Bug 947070]
+ * win/tclWin32Dll.c: Prefer UINT_PTR to DWORD_PTR when casting pointers
+ to integer types for greater portability. [Bug 1831253]
-2004-05-03 Don Porter <dgp@users.sourceforge.net>
+2007-11-15 Daniel Steffen <das@users.sourceforge.net>
- * library/init.tcl: Corrected unique prefix matching of
- interactive command completion in [unknown]. [Bug 946952]
+ * macosx/Tcl.xcodeproj/project.pbxproj: add new chanio.test.
+ * macosx/Tcl.xcode/project.pbxproj:
-2004-05-02 Miguel Sofer <msofer@users.sf.net>
+2007-11-14 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * generic/tclProc.c (TclObjInvokeProc):
- * tests/proc.test (proc-3.6): fix for bad quoting of multi-word proc
- names in error messages [Bug 942757]
+ * generic/tclCompile.c (TclCompileScript): Ensure that we get our count
+ in our INST_START_CMD calls right, even when there's a failure to
+ compile a command directly.
-2004-04-23 Andreas Kupries <andreask@activestate.com>
+ * generic/tclNamesp.c (Tcl_SetEnsembleSubcommandList)
+ (Tcl_SetEnsembleMappingDict): Special code to make sure that
+ * generic/tclCmdIL.c (TclInitInfoCmd): [info exists] is compiled right
+ while not allowing changes to the ensemble to cause havok.
- * generic/tclIO.c (Tcl_SetChannelOption): Fixed [Bug 930851]. When
- changing the eofchar we have to zap the related flags to prevent them
- from prematurely aborting the next read.
+ * generic/tclCompCmds.c (TclCompileInfoCmd): Simple compiler for the
+ [info] command that only handles [info exists].
-2004-04-07 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclExecute.c (TclExecuteByteCode:INST_EXIST_*): New
+ instructions to allow the testing of whether a variable exists.
- * win/configure:
- * win/configure.in: define TCL_LIB_FLAG, TCL_BUILD_LIB_SPEC,
- TCL_LIB_SPEC and TCL_PACKAGE_PATH in tclConfig.sh.
+2007-11-14 Andreas Kupries <andreask@activestate.com>
-2004-04-06 Don Porter <dgp@users.sourceforge.net>
+ * tests/chanio.test: New file. This is essentially a duplicate of
+ 'io.test', with all channel commands converted to their 'chan xxx'
+ notation.
+ * tests/io.test: Fixed typo in test description.
- * tests/unixInit.test (unixInit-3.1): Default encoding on Darwin
- systems is utf-8. Thanks to Steven Abner (tauvan). [Bug 928808]
+2007-11-14 Donal K. Fellows <donal.k.fellows@man.ac.uk>
-2004-04-06 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * generic/regc*.c: Eliminate multi-char collating element code
+ completely. Simplifies the code quite a bit. If people still want the
+ full code, it will remain on the 8.4 branch. [Bug 1831425]
- * tests/cmdAH.test (cmdAH-18.2): Added constraint because
- access(...,X_OK) is defined to be permitted to be meaningless when
- running as root, and OSX exhibits this. [Bug 929892]
+2007-11-13 Jeff Hobbs <jeffh@ActiveState.com>
-2004-04-02 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclCompCmds.c (TclCompileRegexpCmd): clean up comments, only
+ free dstring on OK from TclReToGlob.
+ (TclCompileSwitchCmd): simplify TclReToGlob usage.
- * tests/tcltest.test: Corrected constraint typos: "nonRoot" ->
- "notRoot". Thanks to Steven Abner (tauvan). [Bug 928353]
+2007-11-14 Donal K. Fellows <dkf@users.sf.net>
-2004-03-31 Don Porter <dgp@users.sourceforge.net>
+ * generic/regc*.c: #ifdef/comment out the code that deals with
+ multi-character collating elements, which have never been supported.
+ Cuts the memory consumption of the RE compiler. [Bug 1831425]
- * doc/msgcat.n: Clarified message catalog file encodings. [Bug 811457]
- * library/msgcat/msgcat.tcl ([mcset], [ConvertLocale], [Init]):
- Corrected [mcset] to be able to successfully set a translation to
- the empty string. [mcset $loc $src {}] was incorrectly set the $loc
- translation of $src back to $src. Also changed [ConvertLocale] to
- minimally require a non-empty "language" part in the locale value. If
- not, an error raised prompts [Init] to keep looking for a valid locale
- value, or ultimately fall back on the "C" locale. [Bug 811461]
- * library/msgcat/pkgIndex.tcl: Bump to msgcat 1.3.2.
+2007-11-13 Donal K. Fellows <dkf@users.sf.net>
-2004-03-31 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * generic/tclCompCmds.c (TclCompileSwitchCmd, TclCompileRegexpCmd):
+ Extend [switch] compiler to handle regular expressions as long as
+ things are not too complex. Fix [regexp] compiler so that non-trivial
+ literal regexps get fed to INST_REGEXP.
- * generic/tclObj.c (HashObjKey): Make sure this hashes the whole
- string rep of the object, instead of missing the last character.
+ * doc/mathop.n: Clarify definitions of some operations.
-2004-03-29 Jeff Hobbs <jeffh@ActiveState.com>
+2007-11-13 Miguel Sofer <msofer@users.sf.net>
- * generic/tclInt.h:
- * generic/tclEncoding.c (TclFindEncodings, Tcl_FindExecutable):
- * mac/tclMacInit.c (TclpInitLibraryPath): Correct handling of UTF
- * unix/tclUnixInit.c (TclpInitLibraryPath): data that is actually
- * win/tclWinFile.c (TclpFindExecutable): "clean", allowing the
- * win/tclWinInit.c (TclpInitLibraryPath): loading of Tcl from paths
- that contain multi-byte chars on Windows [Bug 920667]
+ * unix/tclUnixInit.c: the TCL_NO_STACK_CHECK was being incorrectly
+ undefined here; this should be set (or not) in the compile options, it
+ is used elsewhere and needs to be consistent.
-2004-03-28 Miguel Sofer <msofer@users.sf.net>
+2007-11-13 Pat Thoyts <patthoyts@users.sourceforge.net>
- * generic/tclCompile.c (TclCompileScript): corrected possible segfault
- when a compilation returns TCL_OUTLINE_COMPILE after having grown the
- compile environment. [Bug 925121]
+ * unix/tcl.m4: Added autoconf goo to detect and make use of
+ * unix/configure.in: getaddrinfo and friends.
+ * unix/configure: (regenerated)
-2004-03-21 Jeff Hobbs <jeffh@ActiveState.com>
+2007-11-13 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * win/tclWinInt.h: define VER_PLATFORM_WIN32_CE if not already set.
- * win/tclWinInit.c (TclpSetInitialEncodings): recognize WIN32_CE
- as a unicode (WCHAR) platform.
+ * unix/tclUnixCompat.c (TclpGetHostByName): The six-argument form of
+ getaddressbyname_r() uses the fifth argument to indicate whether the
+ lookup succeeded or not on at least one platform. [Bug 1618235]
-2004-03-15 Miguel Sofer <msofer@users.sf.net>
+2007-11-13 Don Porter <dgp@users.sourceforge.net>
- * generic/tclCompile.c (TclCompileScript):
- * tests/compile.test (compile-3.5): corrected wrong test and behaviour
- in the earlier fix for [Bug 705406]; Don Porter reported this as [Bug
- 735055], and provided the solution. Fixed in HEAD on 2003-05-09, but
- backport to 8-4-branch was wrongly omitted; re-reported as [Bug
- 916795] by Roy Terry, diagnosed by dgp.
+ * generic/regcomp.c: Convert optst() from expensive no-op to a
+ cheap no-op.
-2004-03-08 Vince Darley <vincentdarley@users.sourceforge.net>
+2007-11-13 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * generic/tclFileName.c: Fix to 'glob -path' near the root
- * tests/fileName.test: of the filesystem. [Bug 910525]
+ * unix/tclUnixChan.c (CreateSocketAddress): Rewrote to use the
+ thread-safe version of gethostbyname() by forward-porting the code used
+ in 8.4, and added rudimentary support for getaddrinfo() (not enabled by
+ default, as no autoconf-ery written). Part of fix for [Bug 1618235].
-2004-03-01 Don Porter <dgp@users.sourceforge.net>
+2007-11-12 Jeff Hobbs <jeffh@ActiveState.com>
- *** 8.4.6 TAGGED FOR RELEASE ***
+ * generic/tclGet.c (Tcl_Get, Tcl_GetInt): revert use of TclGet* macros
+ due to compiler warning. These cases won't save time either.
- * unix/tcl.m4 (SC_CONFIG_CFLAGS): Allow 64-bit enabling on
- IRIX64-6.5* systems. [Bug 218561]
- * unix/configure: autoconf-2.13
+ * generic/tclUtil.c (TclReToGlob): add more comments, set interp result
+ if specified on error.
- * generic/tclCmdMZ.c (TclCheckInterpTraces): The TIP 62
- * generic/tclTest.c (TestcmdtraceCmd): implementation introduced a
- * tests/basic.test (basic-39.10): bug by testing the CallFrame
- level instead of the iPtr->numLevels level when deciding what traces
- created by Tcl_Create(Obj)Trace to call. Added test to expose the
- error, and made fix. [Request 462580]
+2007-11-12 Miguel Sofer <msofer@users.sf.net>
-2004-02-26 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tclBasic.c: New macro TclResetResult, new iPtr flag
+ * generic/tclExecute.c: bit INTERP_RESULT_UNCLEAN: shortcut for
+ * generic/tclInt.h: Tcl_ResetResult for the "normal" case:
+ * generic/tclProc.c: TCL_OK, no return options, no errorCode
+ * generic/tclResult.c: nor errorInfo, return at normal level.
+ * generic/tclStubLib.c: [Patch 1830184]
+ * generic/tclUtil.c:
- * macosx/Makefile: fixed copyright year in Tcl.framework Info.plist
+ THIS PATCH WAS REVERTED: initial (mis)measurements overstated the
+ perfomance wins, which turn out to be tiny. Not worth the complication.
-2004-02-25 Don Porter <dgp@users.sourceforge.net>
+2007-11-11 Jeff Hobbs <jeffh@ActiveState.com>
- * tests/basic.test: Made several tests more robust to the
- * tests/cmdMZ.test: list-quoting of path names that might
- * tests/exec.test: contain Tcl-special chars like { or [.
- * tests/io.test: Should help us sort out Tcl Bug 554068.
- * tests/pid.test:
- * tests/socket.test:
- * tests/source.test:
- * tests/unixInit.test:
+ * generic/tclCompCmds.c, generic/tclCompile.c, generic/tclCompile.h:
+ * generic/tclExecute.c, generic/tclInt.decls, generic/tclIntDecls.h:
+ * generic/tclRegexp.c, generic/tclRegexp.h: Add INST_REGEXP and fully
+ * generic/tclStubInit.c, generic/tclUtil.c: compiled [regexp] for the
+ * tests/regexpComp.test: [Bug 1830166] simple cases. Also added
+ TclReToGlob function to convert RE to glob patterns and use these in
+ the possible cases.
-2004-02-25 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+2007-11-11 Miguel Sofer <msofer@users.sf.net>
- * unix/tclUnixChan.c (TcpGetOptionProc): Stop memory leak with very
- long hostnames. [Bug 888777]
+ * generic/tclResult.c (ResetObjResult): clarify the logic.
-2004-02-25 David Gravereaux <davygrvy@pobox.com>
+ * generic/tclBasic.c: Increased usage of macros to detect
+ * generic/tclBinary.c: and take advantage of objTypes. Added
+ * generic/tclClock.c: macros TclGet(Int|Long)FromObj,
+ * generic/tclCmdAH.c: TclGetIntForIndexM & TclListObjLength,
+ * generic/tclCmdIL.c: modified TclListObjGetElements.
+ * generic/tclCmdMZ.c:
+ * generic/tclCompCmds.c: The TclGetInt* macros are only a
+ * generic/tclCompExpr.c: shortcut on platforms where 'long' is
+ * generic/tclCompile.c: 'int'; it may be worthwhile to extend
+ * generic/tclDictObj.c: their functionality to other cases.
+ * generic/tclExecute.c:
+ * generic/tclGet.c: As this patch touches many files it has
+ * generic/tclIO.c: been recorded as [Patch 1830038] in
+ * generic/tclIOCmd.c: order to facilitate reviewing.
+ * generic/tclIOGT.c:
+ * generic/tclIndexObj.c:
+ * generic/tclInt.h:
+ * generic/tclInterp.c:
+ * generic/tclListObj.c:
+ * generic/tclLiteral.c:
+ * generic/tclNamesp.c:
+ * generic/tclObj.c:
+ * generic/tclParse.c:
+ * generic/tclProc.c:
+ * generic/tclRegexp.c:
+ * generic/tclResult.c:
+ * generic/tclScan.c:
+ * generic/tclStringObj.c:
+ * generic/tclUtil.c:
+ * generic/tclVar.c:
- * tests/winPipe.test:
- * win/tclWinPipe.c: backport of BuildCommandLine changes to mirror
- msvcrt's parse_cmdline() rules of quoting.
+2007-11-11 Daniel Steffen <das@users.sourceforge.net>
-2004-02-19 Mo DeJong <mdejong@users.sourceforge.net>
+ * unix/tclUnixTime.c (TclpWideClicksToNanoseconds): Fix issues with
+ * generic/tclInt.h: int64_t overflow.
- * win/tclWinInit.c (AppendEnvironment): Use the tail component of the
- passed in lib path instead of just blindly using lib+4. That worked
- when lib was "lib/..." but fails for other values. Thanks go to
- Patrick Samson for pointing this out.
+ * generic/tclBasic.c: Fix stack check failure case if stack grows up
+ * unix/tclUnixInit.c: Simplify non-crosscompiled case.
-2004-02-17 Don Porter <dgp@users.sourceforge.net>
+ * unix/configure: autoconf-2.59
+ * unix/tclConfig.h.in: autoheader-2.59
- * doc/tcltest.n:
- * library/tcltest/tcltest.tcl: Changed -verbose default value to
- {body error} so that detailed information on unexpected errors in
- tests is provided by default, even after the fix for [Bug 725253]
+2007-11-10 Miguel Sofer <msofer@users.sf.net>
-2004-02-17 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclExecute.c: Fast path for INST_LIST_INDEX when the index is
+ not a list.
- (reverted due to test failures on Solaris, but not Win/Lin :/)
- * generic/tclIOUtil.c: backport of rewrite of generic file
- normalization code to cope with links followed by '..'. [Bug 849514],
- and parts of [859251]
+ * generic/tclBasic.c:
+ * unix/configure.in:
+ * unix/tclUnixInit.c: Detect stack grwoth direction at compile time,
+ only fall to runtime detection when crosscompiling.
- * tests/unixInit.test: unixInit-7.1
- * unix/tclUnixInit.c (TclpInitPlatform): ensure the std fds exist to
- prevent crash condition [Bug 772288]
+ * unix/configure: autoconf 2.61
-2004-02-16 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclBasic.c:
+ * generic/tclInt.h:
+ * tests/interp.test:
+ * unix/tclUnixInit.c:
+ * win/tclWin32Dll.c: Restore simpler behaviour for stack checking, not
+ adaptive to stack size changes after a thread is launched. Consensus is
+ that "nobody does that", and so it is not worth the cost. Improved
+ failure comments (mistachkin).
- * generic/tclCmdMZ.c (TclTraceExecutionObjCmd)
- (TclTraceCommandObjCmd): fix possible mem leak in trace info.
+2007-11-10 Kevin Kenny <kennykb@acm.org>
-2004-02-12 Jeff Hobbs <jeffh@ActiveState.com>
+ * win/tclWin32Dll.c: Rewrote the Windows stack checking algorithm to
+ use information from VirtualQuery to determine the bound of the stack.
+ This change fixes a bug where the guard page of the stack was never
+ restored after an overflow. It also eliminates a nasty piece of
+ assembly code for structured exception handling on mingw. It introduces
+ an assumption that the stack is a single memory arena returned from
+ VirtualAlloc, but the code in MSVCRT makes the same assumption, so it
+ should be fairly safe.
- * README: update patchlevel to 8.4.6
- * generic/tcl.h:
- * tools/tcl.wse.in:
- * unix/configure, unix/configure.in, unix/tcl.spec:
- * win/README.binary, win/configure, win/configure.in:
+2007-11-10 Miguel Sofer <msofer@users.sf.net>
- * unix/tcl.m4: update HP-11 build libs setup
+ * generic/tclBasic.c:
+ * generic/tclInt.h:
+ * unix/tclUnixInit.c:
+ * unix/tclUnixPort.h:
+ * win/tclWin32Dll.c: Modify the stack checking algorithm to recheck in
+ case of failure. The working assumptions are now that (a) a thread's
+ stack is never moved, and (b) a thread's stack can grow but not shrink.
+ Port to windows - could be more efficient, but is already cheaper than
+ it was.
-2004-02-06 Don Porter <dgp@users.sourceforge.net>
+2007-11-09 Miguel Sofer <msofer@users.sf.net>
- * doc/clock.n: Removed reference to non-existent [file ctime].
+ * generic/tclResult.c (ResetObjResult): new shortcut.
-2004-02-04 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclAsync.c:
+ * generic/tclBasic.c:
+ * generic/tclExecute.c:
+ * generic/tclInt.h:
+ * generic/tclUnixInit.c:
+ * generic/tclUnixPort.h: New fields in interp (ekeko!) to cache TSD
+ data that is accessed at each command invocation, access macros to
+ replace Tcl_AsyncReady and TclpCheckStackSpace by much faster variants.
+ [Patch 1829248]
- * library/tcltest/tcltest.tcl: Corrected references to
- non-existent $name variable in [cleanupTests]. [Bug 833637]
+2007-11-09 Jeff Hobbs <jeffh@ActiveState.com>
-2004-02-03 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclInt.decls, generic/tclIntDecls.h: Use unsigned char for
+ * generic/tclExecute.c, generic/tclUtil.c: TclByteArrayMatch and
+ don't allow a nocase option. [Bug 1828296]
+ For INST_STR_MATCH, ignore pattern type for TclByteArrayMatch case.
- * library/tcltest/tcltest.tcl: Corrected parsing of single
- command line argument (option with missing value) [Bug 833910]
- * library/tcltest/pkgIndex.tcl: Bump to version 2.2.5.
+ * generic/tclBinary.c (Tcl_GetByteArrayFromObj): check type before
+ func jump (perf).
-2004-02-02 David Gravereaux <davygrvy@pobox.com>
+2007-11-07 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/tclIO.c (Tcl_Ungets): fixes improper filling of the channel
- buffer. [Bug 405995]
+ * generic/tclStubInit.c: Added TclByteArrayMatch
+ * generic/tclInt.decls: for efficient glob
+ * generic/tclIntDecls.h: matching of ByteArray
+ * generic/tclUtil.c (TclByteArrayMatch): Tcl_Objs, used in
+ * generic/tclExecute.c (TclExecuteByteCode): INST_STR_MATCH. [Bug
+ 1827996]
-2004-01-13 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclIO.c (TclGetsObjBinary): Add an efficient binary path for
+ [gets].
+ (DoWriteChars): Special case for 1-byte channel write.
- * generic/tclFileName.c (Tcl_GlobObjCmd): Latest changes to
- management of the interp result by Tcl_GetIndexFromObj() exposed
- improper interp result management in the [glob] command procedure.
- Corrected by adopting the Tcl_SetObjResult(Tcl_NewStringObj) pattern.
- This stopped a segfault in test filename-11.36.
+2007-11-06 Miguel Sofer <msofer@users.sf.net>
-2004-01-13 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * generic/tclEncoding.c: Version of the embedded iso8859-1 encoding
+ handler that is faster (functions to do the encoding know exactly what
+ they're doing instead of pulling it from a table, though the table
+ itself has to be retained for use by shift encodings that depend on
+ iso8859-1). [Patch 1826906], committing for dkf.
- * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct, Tcl_WrongNumArgs):
- Create fresh objects instead of using the one currently in the
- interpreter, which isn't guaranteed to be fresh and unshared. The
- cost for the core will be minimal because of the object cache, and
- this fixes. [Bug 875395]
+2007-11-05 Andreas Kupries <andreask@activestate.com>
-2004-01-09 Vince Darley <vincentdarley@users.sourceforge.net>
+ * generic/tclConfig.c (Tcl_RegisterConfig): Modified to not extend the
+ config database if the encoding provided by the user is not found
+ (venc == NULL). Scripts expecting the data will error out, however we
+ neither crash nor provide bogus information. See [Bug 983509] for more
+ discussion.
- * generic/tclIOUtil.c: fix to infinite loop in TclFinalizeFilesystem.
- [Bug 873311]
+ * unix/tclUnixChan.c (TtyGetOptionProc): Accepted [Patch 1823576]
+ provided by Stuart Cassof <stwo@users.sourceforge.net>. The patch adds
+ the necessary utf/external conversions to the handling of the arguments
+ of option -xchar which will allow the use of \0 and similar characters.
-2003-12-17 Daniel Steffen <das@users.sourceforge.net>
+2007-11-03 Miguel Sofer <msofer@users.sf.net>
- * generic/tclBinary.c (DeleteScanNumberCache): fixed crashing bug when
- numeric scan-value cache contains NULL value.
+ * generic/tclTest.c (TestSetCmd2):
+ * generic/tclVar.c (TclObjLookupVarEx):
+ * tests/set.test (set-5.1): Fix error branch when array name looks
+ like array element (code not normally exercised).
-2003-12-17 Zoran Vasiljevic <zv@archiware.com>
+2007-11-01 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * generic/tclIOUtil.c: fixed 2 memory (object) leaks. This fixes [Bug
- 839519]
+ * tools/tcltk-man2html.tcl (output-directive): Convert .DS/.DE pairs
+ into tables since that is now all that they are used for.
-2003-12-12 Vince Darley <vincentdarley@users.sourceforge.net>
+ * doc/RegExp.3: Clarified documentation of RE flags. [Bug 1167840]
- * generic/tclCmdAH.c: fix to normalization of non-existent user name
- ('file normalize ~nobody') [Bug 858937]
+ * doc/refchan.n: Adjust internal name to be consistent with the file
+ name for reduced user confusion. After comment by Dan Steffen.
-2003-12-09 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd, UniCharIsAscii): Remember, the
+ NUL character is in ASCII too. [Bug 1808258]
- * unix/tclUnixPort.h: #ifdef'd out declarations of errno which
- * tools/man2tcl.c: are known to cause problems with recent
- glibc. [Bug 852369]
+ * doc/file.n: Clarified use of [file normalize]. [Bug 1185154]
-2003-12-03 Don Porter <dgp@users.sourceforge.net>
+2007-10-30 Don Porter <dgp@users.sourceforge.net>
- * generic/tcl.h: Bumped patch level to 8.4.5.1 to distinguish
- * unix/configure.in: CVS snapshots from 8.4.5 release.
+ * generic/tcl.h: Bump version number to 8.5b2.1 to distinguish
+ * library/init.tcl: CVS development snapshots from the 8.5b2
+ * unix/configure.in: release.
* unix/tcl.spec:
* win/configure.in:
- * unix/configure: autoconf (2.13)
+ * unix/configure: autoconf (2.59)
* win/configure:
-2003-12-02 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+2007-10-30 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * generic/tclBinary.c (DeleteScanNumberCache, ScanNumber): Made
- the numeric scan-value cache have proper references to the objects
- within it so strange patterns of writes won't cause references to
- freed objects. Thanks to Paul Obermeier for the report. [Bug 851747]
+ * doc/expr.n, doc/mathfunc.n: Improve documentation to try to make
+ clearer what is going on.
-2003-12-01 Miguel Sofer <msofer@users.sf.net>
+ * doc/interp.n: Shorten the basic descriptive text for some interp
+ subcommands so Solaris nroff doesn't truncate them. [Bug 1822268]
- * doc/lset.n: fix typo [Bug 852224]
+2007-10-30 Donal K. Fellows <dkf@users.sf.net>
-2003-11-21 Don Porter <dgp@users.sourceforge.net>
+ * tools/tcltk-man2html.tcl (output-widget-options): Enhance the HTML
+ generator so that it can produce multi-line option descriptions.
- *** 8.4.5 TAGGED FOR RELEASE ***
+2007-10-28 Miguel Sofer <msofer@users.sf.net>
- * tests/windFCmd.test (winFCmd-16.10): Corrected failure to
- initialize variable $dd that caused test suite failure.
+ * generic/tclUtil.c (Tcl_ConcatObj): optimise for some of the
+ concatenees being empty objs. [Bug 1447328]
-2003-11-20 Miguel Sofer <msofer@users.sf.net>
+2007-10-28 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclVar.c: fix flag bit collision between LOOKUP_FOR_UPVAR
- and TCL_PARSE_PART1 (deprecated) [Bug 835020]
+ * generic/tclEncoding.c (TclInitEncodingSubsystem): Hard code the
+ iso8859-1 encoding, as it's needed for more than just text (especially
+ binary encodings...) Note that other encodings rely on the encoding
+ being a table encoding (!) so we can't use more efficient encoding
+ mapping functions.
-2003-11-20 Vince Darley <vincentdarley@users.sourceforge.net>
+2007-10-27 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclIOUtil.c:
- * tests/winFCmd.test: fix to [Bug 845778] - Infinite recursion on [cd]
- (Windows only bug).
+ * generic/regc_lex.c (lexescape): Close off one of the problems
+ mentioned in [Bug 1810264].
-2003-11-18 Jeff Hobbs <jeffh@ActiveState.com>
+2007-10-27 Miguel Sofer <msofer@users.sf.net>
- * changes: updated for 8.4.5 release
+ * generic/tclNamesp.c (Tcl_FindCommand): insure that FQ command names
+ are searched from the global namespace, ie, bypassing resolvers of the
+ current namespace. [Bug 1114355]
-2003-11-17 Don Porter <dgp@users.sourceforge.net>
+ * doc/apply.n: fixed example [Bug 1811791]
+ * doc/namespace.n: improved example [Bug 1788984]
+ * doc/AddErrInfo.3: typo [Bug 1715087]
+ * doc/CrtMathFnc.3: fixed Tcl_ListMathFuncs entry [Bug 1672219]
- * generic/regcomp.c: Backported regexp bug fixes and tests. Thanks
- * generic/tclTest.c: to Pavel Goran and Vince Darley.
- * tests/reg.test: [Bugs 230589, 504785, 505048, 703709, 840258]
+ * generic/tclCompile.h:
+ * generic/tclInt.h: moved declaration of TclSetCmdNameObj from
+ tclCompile.h to tclInt.h, reverting linker [Bug 1821159] caused by
+ commit of 2007-10-11 (both I and gcc missed one dep).
-2003-11-12 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclVar.c: try to preserve Tcl_Objs when doing variable
+ lookups by name, partially addressing [Bug 1793601].
- * tests/cmdMZ.test (cmdMZ-1.4): change to nonPortable as more
- systems are using permissions caching, and this isn't really a Tcl
- controlled issue.
+2007-10-27 Donal K. Fellows <dkf@users.sf.net>
-2003-11-11 Jeff Hobbs <jeffh@ActiveState.com>
+ * tools/tcltk-man2html.tcl (make-man-pages, htmlize-text)
+ (process-text): Make the man->HTML scraper work better.
- * unix/configure:
- * unix/tcl.m4: improve AIX --enable-64bit handling
+2007-10-26 Don Porter <dgp@users.sourceforge.net>
-2003-11-10 Don Porter <dgp@users.sourceforge.net>
+ *** 8.5b2 TAGGED FOR RELEASE ***
- * tests/unixInit.test (unixInit-2.10): re-enabled.
- * unix/tclUnixInit.c (TclpInitLibraryPath): Alternative fix
- * win/tclWinInit.c (TclpInitLibraryPath): for [Bug 832657]
- that should not run afoul of startup constraints.
+ * changes: Updated for 8.5b2 release.
- * library/dde/pkgIndex.tcl: Added safeguards so that registry
- * library/reg/pkgIndex.tcl: and dde packages are not offered
- * win/tclWinDde.c: on non-Windows platforms. Bumped to
- * win/tclWinReg.c: registry 1.1.3 and dde 1.2.2.
+ * doc/*.1: Revert doc changes that broke
+ * doc/*.3: `make html` so we can get the release
+ * doc/*.n: out the door.
-2003-11-06 Jeff Hobbs <jeffh@ActiveState.com>
+ * README: Bump version number to 8.5b2.
+ * generic/tcl.h:
+ * library/init.tcl:
+ * tools/tcl.wse.in:
+ * unix/configure.in:
+ * unix/tcl.spec:
+ * win/configure.in:
- * tests/unixInit.test (unixInit-2.10): mark as knownBug
- * generic/tclEncoding.c (TclFindEncodings): revert patch from
- 2003-11-05. It wasn't valid in the sensitive startup init phase
- and broke Windows from working at all.
+ * unix/configure: autoconf (2.59)
+ * win/configure:
-2003-11-07 Daniel Steffen <das@users.sourceforge.net>
+2007-10-26 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * macosx/Makefile: optimized builds define NDEBUG to turn off
- ThreadAlloc range checking.
+ * tools/man2help2.tcl, tools/man2tcl.c: Made some of the tooling code
+ to do man->other formats work better with current manpage set. Long
+ way still to go.
-2003-11-05 Don Porter <dgp@users.sourceforge.net>
+2007-10-25 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
- * generic/tclEncoding.c (TclFindEncodings): Normalize the path
- of the executable before passing to TclpInitLibraryPath() to avoid
- buggy handling of paths containing "..". [Bug 832657]
- * tests/unixInit.test (unixInit-2.10): New test for fixed bug.
+ * generic/tclThread.c: Added TclpMasterLock/Unlock arround calls to
+ ForgetSyncObject in Tcl_MutexFinalize and Tcl_ConditionFinalize to
+ prevent from garbling the internal lists that track sync objects. [Bug
+ 1726873]
-2003-11-04 Daniel Steffen <das@users.sourceforge.net>
+2007-10-24 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * macosx/Makefile: added 'test' target.
+ * tools/man2html2.tcl (macro): Added support for converting the new
+ macros into HTML.
-2003-10-31 Vince Darley <vincentdarley@users.sourceforge.net>
+ * doc/man.macros (QW,PQ,QR,MT): New macros that hide the ugly mess
+ needed to get proper GOOBE quoting in the manual pages.
+ * doc/*.n, doc/*.3, doc/*.1: Lots of changes to take advantage of the
+ new macros.
- * generic/tclTest.c: fix test suite memory leak (backport error)
- * unix/tclUnixFile.c: ensure translated path (required for correct
- error messages) is freed in both code paths.
+2007-10-20 Miguel Sofer <msofer@users.sf.net>
-2003-10-23 Andreas Kupries <andreask@activestate.com>
+ * generic/tclCompile.c: Fix comments.
+ * generic/tclExecute.c:
- * unix/tclUnixChan.c (Tcl_MakeFileChannel): Applied [Patch 813606]
- fixing [Bug 813087]. Detection of sockets was off for Mac OS X which
- implements pipes as local sockets. The new code ensures that only IP
- sockets are detected as such.
+2007-10-18 David Gravereaux <davygrvy@pobox.com>
-2003-10-22 Andreas Kupries <andreask@activestate.com>
+ * tools/mkdepend.tcl: sort the dep list for a more humanly readable
+ output.
- * win/tclWinSock.c (TcpWatchProc): Watch for FD_CLOSE too when asked
- for writable events by the generic layer.
- (SocketEventProc): Generate a writable event too when a close is
- detected.
+2007-10-18 Don Porter <dgp@users.sourceforge.net>
- Together the changes fix [Bug 599468].
+ * generic/tclResult.c (TclMergeReturnOptions): Make sure any -code
+ values get pulled out of the dictionary, even if they are integer
+ valued.
-2003-10-22 Andreas Kupries <andreask@activestate.com>
+ * generic/tclCompCmds.c (TclCompileReturnCmd): Added code to more
+ optimally compile [return -level 0 $x] to "push $x". [RFE 1794073]
- * generic/tclIOUtil.c (FsListMounts, FsAddMountsToGlobResult): New
- functions. See below for context.
- (Tcl_FSMatchInDirectory): Modified to call on the new functions
- (above) to handle the mountpoints in the glob'bed directory correctly.
- Part of the patch by Vincent Darley to solve the [Bug 800106] for the
- 8.4.x series.
+ * compat/tmpnam.c (removed): The routine tmpnam() is no longer
+ * unix/Makefile.in: called by Tcl source code. Remove autogoo the
+ * unix/configure.in: supplied a replacement version on systems
+ * win/tcl.dsp: where the routine was not available. [RFE
+ 1811848]
- * generic/tcl.h (TCL_GLOB_TYPE_MOUNT): New definition. Part of the
- patch by Vincent Darley to solve [Bug 800106] for the 8.4.x series.
+ * unix/configure: autoconf-2.59
-2003-10-22 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tcl.h: Remove TCL_LL_MODIFIER_SIZE. [RFE 1811837]
- * generic/tclCmdAH.c (Tcl_FileObjCmd): Changed FILE_ prefix for option
- enumeration to FCMD_ to prevent collision with symbols defined by
- Cygwin/Mingw32 on NT. [Bug 822528]
+2007-10-17 David Gravereaux <davygrvy@pobox.com>
-2003-10-21 Daniel Steffen <das@users.sourceforge.net>
+ * tools/mkdepend.tcl: Improved defense from malformed object list
+ infile.
- * tools/tcltk-man2html.tcl: fixed incorrect html generated for .IP/.TP
- lists, now use <DL><DT>...<DD>...<P><DT>...<DD>...</DL> instead of
- illegal <DL><P><DT>...<DD>...<P><DT>...<DD>...</DL>. Added skipping of
- directives directly after .TP to avoid them being used as item
- descriptions, e.g. .TP\n.VS in clock.n.
+2007-10-17 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
-2003-10-21 Andreas Kupries <andreask@activestate.com>
+ * tools/man2html2.tcl: Convert .DS/.DE into HTML tables, not
+ preformatted text.
- * win/tclWinPipe.c (BuildCommandLine): Applied the patch coming with
- [Bug 805605] to the code, fixing the incorrect use of ispace noted by
- Ronald Dauster <ronaldd@users.sourceforge.net>.
+2007-10-17 Kevin B. Kenny <kennykb@acm.org>
-2003-10-14 David Gravereaux <davygrvy@pobox.com>
+ * generic/tclCompExpr.c: Moved a misplaced declaration that blocked
+ compilation on VC++.
+ * generic/tclExecute.c: Silenced several VC++ compiler warnings about
+ converting 'long' to 'unsigned short'.
- * win/tclAppInit.c (sigHandler): Punt gracefully if exitToken has
- already been destroyed.
+2007-10-16 David Gravereaux <davygrvy@pobox.com>
-2003-10-13 Vince Darley <vincentdarley@users.sourceforge.net>
+ * win/makefile.vc: removed old dependency cruft that is no longer
+ needed.
- * generic/tclCmdMZ.c:
- * tests/regexp.test: fix to [Bug 823524] in regsub; added three new
- tests.
+2007-10-15 Don Porter <dgp@users.sourceforge.net>
-2003-10-12 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclIOCmd.c: Revise [open] so that it interprets leading
+ zero strings passed as the "permissions" argument as octal numbers,
+ even if Tcl itself no longer parses integers in that way.
- * unix/tclUnixTest.c (TestalarmCmd): don't bother checking return
- value of alarm. [Bug 664755] (english)
+ * unix/tclUnixFCmd.c: Revise the "-permissions" [file attribute] so
+ that it interprets leading zero strings as octal numbers, even if Tcl
+ itself no longer parses integers in that way.
-2003-10-08 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclCompExpr.c: Corrections to code that produces
+ * generic/tclUtil.c: extended "bad octal" error messages.
- * generic/tclBasic.c: Save and restore the iPtr->flag bits that
- control the state of errorCode and errorInfo management when calling
- "leave" execution traces, so that all error information of the traced
- command is still available whether traced or not. Thanks to Yahalom
- Emet. [Bug 760947]
+ * tests/cmdAH.test: Test revisions so that tests pass whether or
+ * tests/cmdIL.test: not Tcl parses leading zero strings as octal.
+ * tests/compExpr-old.test:
+ * tests/compExpr.test:
+ * tests/compile.test:
+ * tests/expr-old.test:
+ * tests/expr.test:
+ * tests/incr.test:
+ * tests/io.test:
+ * tests/lindex.test:
+ * tests/link.test:
+ * tests/mathop.test:
+ * tests/parseExpr.test:
+ * tests/set.test:
+ * tests/string.test:
+ * tests/stringComp.test:
-2003-10-08 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+2007-10-15 David Gravereaux <davygrvy@pobox.com>
- * generic/tclTest.c (TestNumUtfCharsCmd): Command to allow finer
- access to Tcl_NumUtfChars for testing.
- * generic/tclUtf.c (Tcl_NumUtfChars): Corrected string length
- determining when the length parameter is negative; the terminator is a
- zero byte, not (necessarily) a \u0000 character. [Bug 769812]
+ * tools/mkdepend.tcl: Produces usable output. Include path problem
+ * win/makefile.vc: fixed. Never fight city hall when it comes to
+ levels of quoting issues.
-2003-10-07 Don Porter <dgp@users.sourceforge.net>
+2007-10-15 Miguel Sofer <msofer@users.sf.net>
- * tests/exec.test: Corrected temporary file management
- * tests/fileSystem.test: issues uncovered by -debug 1 test
- * tests/io.test: operations. Also backported some
- * tests/ioCmd.test: other fixes from the HEAD.
- * tests/pid.test: [Bugs 675605, 675655, 675659]
- * tests/socket.test:
- * tests/source.test:
+ * generic/tclParse.c (Tcl_ParseBraces): fix for possible read after
+ the end of buffer. [Bug 1813528] (Joe Mistachkin)
- * tests/fCmd.test: Run tests with the [temporaryDirectory] as
- the current directory, so that tests can depend on ability to write
- files. [Bug 575837]
+2007-10-14 David Gravereaux <davygrvy@pobox.com>
- * doc/OpenFileChnl.3: Updated Tcl_Tell and Tcl_Seek documentation
- to reflect that they now return Tcl_WideInt (TIP 72) [Bug 787537]
+ * tools/mkdepend.tcl (new): Initial stab at generating automatic
+ * win/makefile.vc: dependencies.
- * tests/io.test: Corrected several tests that failed when paths
- * tests/ioCmd.test: included regexp-special chars. [Bug 775394]
+2007-10-12 Pat Thoyts <patthoyts@users.sourceforge.net>
-2003-10-06 Don Porter <dgp@users.sourceforge.net>
+ * win/makefile.vc: Mine all version information from headers.
+ * win/rules.vc: Sync tcl and tk and bring extension versions
+ * win/nmakehlp.c: closer together. Try and avoid using tclsh to do
+ substitutions as we may cross compile.
+ * win/coffbase.txt: Added offsets for snack dlls.
- * tests/regexp.test: Matched [makeFile] with [removeFile].
- * tests/regexpComp.test: [Bug 675652]
+2007-10-11 David Gravereaux <davygrvy@pobox.com>
- * tests/fCmd.test (fCmd-8.2): Test only that tilde-substitution
- happens, not for any particular result. [Bug 685991]
+ * win/makefile.vc: Fixed my bad spelling mistakes from years back.
+ Dedependency, duh! Rather funny.
- * unix/tcl.m4 (SC_PATH_TCLCONFIG): Corrected search path so
- that alpha and beta releases of Tcl are not favored. [Bug 608698]
+2007-10-11 Don Porter <dgp@users.sourceforge.net>
- * tests/reg.test: Corrected duplicate test names.
- * tests/resource.test: [Bugs 710370, 710358]
+ * generic/tclCmdMZ.c: Correct [string is (wide)integer] failure
+ * tests/string.test: to report correct failindex values for
+ non-decimal integer strings. [Bug 1805887]
- * tests/cmdMZ.test: Updated [package require tcltest] lines to
- * tests/fileSystem.test: indiciate that these test files
- * tests/notify.test: use features of tcltest 2. [Bug 706114]
- * tests/parseExpr.test:
- * tests/unixNotfy.test:
+ * compat/strtoll.c (removed): The routines strtoll() and strtoull()
+ * compat/strtoull.c (removed): are no longer called by the Tcl source
+ * generic/tcl.h: code. (Their functionality has been replaced
+ * unix/Makefile.in: by TclParseNumber().) Remove outdated comments
+ * unix/configure.in: and mountains of configury autogoo that
+ * unix/tclUnixPort.h: allegedly support the mythical systems where
+ * win/Makefile.in: these routines might not have been available.
+ * win/makefile.bc:
+ * win/makefile.vc:
+ * win/tclWinPort.h:
-2003-10-06 Vince Darley <vincentdarley@users.sourceforge.net>
+ * unix/configure: autoconf-2.59
- * generic/tclFileName.c:
- * generic/tclIOUtil.c: backport of volumerelative file normalization
- and 'file join' inconsistency fixes [Bug 767834, 813273].
+2007-10-11 Miguel Sofer <msofer@users.sf.net>
-2003-10-04 Chengye Mao <chengye.geo@yahoo.com>
+ * generic/tclObj.c: remove superfluous #include of tclCompile.h
- * win/tclWinPipe.c: fixed a bug in BuildCommandLine.
- This bug built a command line with a missing space between
- tclpipe.dll and the following arguments. It caused error
- in Windows 98 when exec command.com (e.g. dir) [Bug 789040]
+2007-10-08 George Peter Staplin <georgeps@xmission.com>
-2003-10-03 Don Porter <dgp@users.sourceforge.net>
+ * doc/Hash.3: Correct the valid usage of the flags member for the
+ Tcl_HashKeyType. It should be 0 or more of the flags mentioned.
- * generic/tclBasic.c: Fixed error in ref count management of command
- * generic/tclCmdMZ.c: and execution traces that caused access to
- freed memory in trace-32.1. [Bug 811483]
+2007-10-02 Jeff Hobbs <jeffh@ActiveState.com>
-2003-10-03 Vince Darley <vincentdarley@users.sourceforge.net>
+ * generic/tcl.h (Tcl_DecrRefCount): Update change from 2006-05-29 to
+ make macro more warning-robust in unbraced if code.
- * tests/fileName.test:
- * tests/winFCmd.test:
- * doc/FileSystem.3: backported various test and documentation changes
- from HEAD. Backport of actual code fixes to follow.
+2007-10-02 Don Porter <dgp@users.sourceforge.net>
-2003-10-02 Don Porter <dgp@users.sourceforge.net>
+ [core-stabilizer-branch]
- * README: Bumped patch level to 8.4.5 to prepare
- * generic/tcl.h: for next patch release.
+ * README: Bump version number to 8.5.0
+ * generic/tcl.h:
+ * library/init.tcl:
* tools/tcl.wse.in:
* unix/configure.in:
* unix/tcl.spec:
- * win/README.binary:
* win/configure.in:
- * unix/configure: autoconf (2.13)
+ * unix/configure: autoconf (2.59)
* win/configure:
- * library/http/http.tcl: Bumped to http 2.4.5
- * library/http/pkgIndex.tcl:
-
-2003-10-01 Daniel Steffen <das@users.sourceforge.net>
-
- * macosx/Makefile: fixed redo prebinding bug when DESTDIR="".
- * mac/tclMacResource.c: fixed possible NULL dereference (bdesgraupes).
-
-2003-09-29 Don Porter <dgp@users.sourceforge.net>
+2007-10-02 Andreas Kupries <andreask@activestate.com>
- * generic/tclBasic.c (CallCommandTraces): Added safety bit
- * tests/trace.test: masking to prevent any of the bit values
- TCL_TRACE_*_EXEC from leaking into the flags field of any Command
- struct. This does not fix [Bug 811483] but helps to contain some of
- its worst symptoms. Also backported the corrections to test trace-28.4
- from Vince Darley.
+ * library/tclIndex: Added 'tcl::tm::path' to the tclIndex. This fixes
+ [Bug 1806422] reported by Don Porter.
-2003-09-29 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+2007-09-25 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * library/http/http.tcl (geturl): Correctly check the type of
- boolean-valued options. [Bug 811170]
+ * generic/tclProc.c (Tcl_DisassembleObjCmd): Define a command,
+ ::tcl::unsupported::disassemble, which can disassemble procedures,
+ lambdas and general scripts.
+ * generic/tclCompile.c (TclDisassembleByteCodeObj): Split apart the
+ code to print disassemblies of bytecode so that there is reusable code
+ that spits it out in a Tcl_Obj and then that code is used when doing
+ tracing.
- * unix/tcl.m4 (SC_ENABLE_FRAMEWORK): Added note to make it clearer
- that this is an OSX feature, not a general Unix feature. [Bug 619440]
+2007-09-20 Don Porter <dgp@users.sourceforge.net>
-2003-09-28 David Gravereaux <davygrvy@pobox.com>
+ *** 8.5b1 TAGGED FOR RELEASE ***
- * win/tclWinPipe.c: The windows port of expect can call
- TclWinAddProcess before any of the other pipe functions. Added a
- missing PipeInit() call to make sure the initialization happens.
+ * changes: updates for 8.5b1 release.
-2003-09-25 Daniel Steffen <das@users.sourceforge.net>
+2007-09-19 Don Porter <dgp@users.sourceforge.net>
- * macosx/Makefile: ensure SYMROOT exists if OBJROOT is overridden on
- command line. Replaced explict use of /usr/bin by ${BINDIR}.
-
-2003-09-23 Don Porter <dgp@users.sourceforge.net>
+ * README: Bump version number to 8.5b1
+ * generic/tcl.h: Merge from core-stabilizer-branch.
+ * library/init.tcl: Stabilizing toward 8.5b1 release now done on
+ * tools/tcl.wse.in: the HEAD. core-stabilizer-branch is now
+ * unix/configure.in: suspended.
+ * unix/tcl.spec:
+ * win/configure.in:
- * generic/tclCmdMZ.c: Fixed [Bug 807243] where
- * tests/trace.test (trace-31,32.*): the introspection results
- of both [trace info command] and [trace info execution] were getting
- co-mingled. Thanks to Mark Saye for the report.
+2007-09-19 Pat Thoyts <patthoyts@users.sourceforge.net>
- * library/init.tcl (auto_load, auto_import): Expanded Eric Melski's
- 2000-01-28 fix for [Bug 218871] to all potentially troubled uses of
- [info commands] on input data, where glob-special characters could
- cause problems.
+ * generic/tclStubLib.: Replaced isdigit with internal implementation.
-2003-09-19 Miguel Sofer <msofer@users.sf.net>
+2007-09-18 Don Porter <dgp@users.sourceforge.net>
- * generic/tclExecute.c: adding (DE)CACHE_STACK_INFO() pairs to protect
- all calls that may cause traces on ::errorInfo or ::errorCode to
- corrupt the stack [Bug 804681]
+ * generic/tclStubLib.c: Remove C library calls from Tcl_InitStubs() so
+ * win/makefile.vc: that we don't need the C library linked in to
+ libtclStub.
-2003-09-10 Don Porter <dgp@users.sourceforge.net>
+2007-09-17 Pat Thoyts <patthoyts@users.sourceforge.net>
- * library/opt/optparse.tcl: Overlooked dependence of opt 0.4.4
- * library/opt/pkgIndex.tcl: on Tcl 8.2. Bumped to opt 0.4.4.1.
+ * win/makefile.vc: Add crt flags for tclStubLib now it uses C-library
+ functions.
-2003-09-01 Zoran Vasiljevic <zoran@archiware.com>
+2007-09-17 Joe English <jenglish@users.sourceforge.net>
- * generic/tclIOUtil.c: backported fix from HEAD [Bug 788780]
+ * tcl.m4: use '${CC} -shared' instead of 'ld -Bshareable' to build
+ shared libraries on current NetBSDs. [Bug 1749251]
+ * unix/configure: regenerated (autoconf-2.59).
-2003-08-27 Don Porter <dgp@users.sourceforge.net>
+2007-09-17 Don Porter <dgp@users.sourceforge.net>
- * generic/tclUtil.c: Corrected [Bug 411825] and other bugs in
- TclNeedSpace() where non-breaking space (\u00A0) and backslash-escaped
- spaces were handled incorrectly.
- * tests/util.test: Added new tests util-8.[2-6].
+ * unix/Makefile.in: Update `make dist` so that tclDTrace.d is
+ included in the source code distribution.
-2003-08-06 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tcl.h: Revised Tcl_InitStubs() to restore Tcl 8.4
+ * generic/tclPkg.c: source compatibility with callers of
+ * generic/tclStubLib.c: Tcl_InitStubs(interp, TCL_VERSION, 1). [Bug
+ 1578344]
- * win/tclWinInit.c: recognize amd64 and ia32_on_win64 cpus and
- Windows CE platform.
+2007-09-17 Donal K. Fellows <donal.k.fellows@man.ac.uk>
-2003-08-06 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclTrace.c (Tcl_TraceObjCmd, TraceExecutionObjCmd)
+ (TraceCommandObjCmd, TraceVariableObjCmd): Generate literal values
+ * generic/tclNamesp.c (NamespaceCodeCmd): more efficiently using
+ * generic/tclFCmd.c (CopyRenameOneFile): TclNewLiteralStringObj
+ * generic/tclEvent.c (TclSetBgErrorHandler): macro.
- * library/msgcat/msgcat.tcl: Added escape so that non-Windows
- * library/msgcat/pkgIndex.tcl: platforms do not try to use the
- registry package. This can save a costly and pointless package
- search. Bumped to 1.3.1. Thanks to Dave Bodenstab. [Bug 781609]
+2007-09-15 Daniel Steffen <das@users.sourceforge.net>
-2003-08-05 Miguel Sofer <msofer@users.sf.net>
+ * unix/tcl.m4: replace all direct references to compiler by ${CC} to
+ enable CC overriding at configure & make time; run
+ check for visibility "hidden" with all compilers;
+ quoting fixes from TEA tcl.m4.
+ (SunOS-5.1x): replace direct use of '/usr/ccs/bin/ld' in SHLIB_LD by
+ 'cc' compiler driver.
+ * unix/configure: autoconf-2.59
- * generic/tclExecute.c (INST_INVOKE, INST_EVAL, INST_PUSH_RESULT):
- added a Tcl_ResetResult(interp) at each point where the interp's
- result is pushed onto the stack, to avoid keeping an extra reference
- that may cause costly Tcl_Obj duplication. Detected by Franco Violi,
- analyzed by Peter Spjuth and Donal Fellows. [Bug 781585]
+2007-09-14 Donal K. Fellows <donal.k.fellows@man.ac.uk>
-2003-07-24 Reinhard Max <max@suse.de>
+ * generic/tclBasic.c (Tcl_CreateObjCommand): Only invalidate along the
+ namespace path once; that is enough. [Bug 1519940]
- * library/package.tcl: Fixed a typo that broke pkg_mkIndex -verbose.
+2007-09-14 Daniel Steffen <das@users.sourceforge.net>
- * tests/pkgMkIndex.test: Added a test for [pkg_mkIndex -verbose].
+ * generic/tclDTrace.d (new file): Add DTrace provider for Tcl; allows
+ * generic/tclCompile.h: tracing of proc and command entry &
+ * generic/tclBasic.c: return, bytecode execution, object
+ * generic/tclExecute.c: allocation and more; with
+ * generic/tclInt.h: essentially zero cost when tracing
+ * generic/tclObj.c: is inactive; enable with
+ * generic/tclProc.c: --enable-dtrace configure arg
+ * unix/Makefile.in: (disabled by default, will only
+ * unix/configure.in: enable if DTrace is present). [Patch
+ 1793984]
+
+ * macosx/GNUmakefile: Enable DTrace support.
+ * macosx/Tcl-Common.xcconfig:
+ * macosx/Tcl.xcodeproj/project.pbxproj:
+
+ * generic/tclCmdIL.c: Factor out core of InfoFrameCmd() into
+ internal TclInfoFrame() for use by DTrace
+ probes.
-2003-07-23 Daniel Steffen <das@users.sourceforge.net>
+ * unix/configure: autoconf-2.59
+ * unix/tclConfig.h.in: autoheader-2.59
- * unix/Makefile.in: changes to html-tcl & html-tk targets for
- compatibility with non-gnu makes.
+2007-09-12 Don Porter <dgp@users.sourceforge.net>
- * unix/Makefile.in: added macosx/README to dist target.
+ * unix/Makefile.in: Perform missing updates of the tcltest Tcl
+ * win/Makefile.in: Module installed filename that should have
+ been part of the bump to tcltest 2.3b1. Thanks Larry Virden.
-2003-07-23 Pat Thoyts <patthoyts@users.sourceforge.net>
+2007-09-12 Pat Thoyts <patthoyts@users.sourceforge.net>
- * win/tclWinReg.c (OpenSubKey): Backported fix for [Bug 775976] which
- causes the registry set command to fail when built with VC7.
- * library/reg/pkgIndex.tcl: Incremented the version to 1.1.2.
+ * win/makefile.vc, win/rules.vc, win/nmakehlp.c: Use nmakehlp to
+ substitute values for tclConfig.sh (helps cross-compiling).
-2003-07-21 Jeff Hobbs <jeffh@ActiveState.com>
+2007-09-11 Don Porter <dgp@users.sourceforge.net>
- *** 8.4.4 TAGGED FOR RELEASE ***
+ * library/tcltest/tcltest.tcl: Accept underscores and colons in
+ * library/tcltest/pkgIndex.tcl: constraint names. Properly handle
+ constraint expressions that return non-numeric boolean results like
+ "false". Bump to tcltest 2.3b1. [Bug 1772989; RFE 1071322]
+ * tests/info.test: Disable fragile tests.
- * changes: updated for 8.4.4 release
+ * doc/package.n: Restored the functioning of [package require
+ * generic/tclPkg.c: -exact] to be compatible with Tcl 8.4. [Bug
+ * tests/pkg.test: 1578344]
-2003-07-18 Daniel Steffen <das@users.sourceforge.net>
+2007-09-11 Miguel Sofer <msofer@users.sf.net>
- * macosx/Makefile: added option to allow installing manpages in
- addition to default html help.
+ * generic/tclCompCmds.c (TclCompileDictCmd-update):
+ * generic/tclCompile.c (tclInstructionTable):
+ * generic/tclExecute.c (INST_DICT_UPDATE_END): fix stack management in
+ compiled [dict update]. [Bug 1786481]
-2003-07-18 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ ***POTENTIAL INCOMPATIBILITY***
+ Scripts that were precompiled on earlier versions of 8.5 and use [dict
+ update] will crash. Workaround: recompile.
- * doc/Utf.3: Tightened up documentation of Tcl_UtfNext and Tcl_UtfPrev
- to better match the behaviour. [Bug 769895]
+2007-09-11 Kevin B. Kenny <kennykb@acm.org>
-2003-07-18 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclExecute.c: Corrected an off-by-one error in the setting
+ of MaxBaseWide for certain powers. [Bug 1767293 - problem reported in
+ comments when bug was reopened]
- * generic/tclIOUtil.c: correct MT-safety issues with filesystem
- records. [Bug 753315] (vasiljevic)
+2007-09-10 Jeff Hobbs <jeffh@ActiveState.com>
- * library/http/pkgIndex.tcl: merged to v2.4.4 from head
- * library/http/http.tcl: add support for user:pass info in URL.
- * tests/http.test: [Bug 759888] (shiobara)
+ * generic/tclLink.c (Tcl_UpdateLinkedVar): guard against var being
+ unlinked. [Bug 1740631] (maros)
-2003-07-18 Don Porter <dgp@users.sourceforge.net>
+2007-09-10 Miguel Sofer <msofer@users.sf.net>
- * generic/tclBasic.c: Corrected several instances of unsafe
- * generic/tclCompile.c: truncation of UTF-8 strings that might break
- * generic/tclProc.c: apart a multi-byte character. [Bug 760872]
- * library/init.tcl:
- * tests/init.test:
-
- * doc/tcltest.n: Restored the [Eval] proc to replace
- * library/tcltest/tcltest.tcl: the [::puts] command when either the
- -output or -error option for [test] is in use, in order to capture
- data written to the output or error channels for comparison against
- what is expected. This is easier to document and agrees better with
- most user expectations than the previous attempt to replace [puts]
- only in the caller's namespace. Documentation made more precise on the
- subject. [Bug 706359]
-
- * doc/AddErrInfo.3: Improved consistency of documentation by using
- * doc/CrtTrace.3: "null" everywhere to refer to the character
- * doc/Encoding.3: '\0', and using "NULL" everywhere to refer to
- * doc/Eval.3: the value of a pointer that points to nowhere.
- * doc/GetIndex.3: Also dropped references to ASCII that are no
- * doc/Hash.3: longer true, and standardized on the
- * doc/LinkVar.3: hyphenated spelling of "null-terminated".
- * doc/Macintosh.3:
- * doc/OpenFileChnl.3:
- * doc/SetVar.3:
- * doc/StringObj.3:
- * doc/Utf.3:
+ * generic/tclCompile.c: fix tclInstructionTable entry for
+ dictUpdateEnd
- * doc/CrtSlave.3 (Tcl_MakeSafe): Removed warning about possible
- deprecation (no TIP on that).
+ * generic/tclExecute.c: remove unneeded setting of 'cleanup' variable
+ before jumping to checkForCatch.
-2003-07-17 Daniel Steffen <das@users.sourceforge.net>
+2007-09-10 Don Porter <dgp@users.sourceforge.net>
- * macosx/Makefile: added var to allow overriding of tclsh used during
- html help building (Landon Fuller).
+ * doc/package.n: Restored the document parallel syntax of the
+ * generic/tclPkg.c: [package present] and [package require]
+ * tests/pkg.test: commands. [Bug 1723675]
-2003-07-16 Mumit Khan <khan@nanotech.wisc.edu>
+2007-09-09 Don Porter <dgp@users.sourceforge.net>
- * generic/tclIOUtil.c (SetFsPathFromAny): Add Cygwin specific code to
- convert POSIX filename to native format.
- * generic/tclFileName.c (Tcl_TranslateFileName): And remove from here.
- (TclDoGlob): Adjust for cygwin and append / for dirs instead of \
- * win/tclWinFile.c (TclpObjChdir): Use chdir on Cygwin. [Patch 679315]
+ * generic/tclInt.h: Removed the "nsName" Tcl_ObjType from the
+ * generic/tclNamesp.c: registered set. Revised the management of the
+ * generic/tclObj.c: intrep of that Tcl_ObjType. Revised the
+ * tests/obj.test: TclGetNamespaceFromObj() routine to return
+ TCL_ERROR and write a consistent error message when a namespace is not
+ found. [Bug 1588842. Patch 1686862]
-2003-07-16 Jeff Hobbs <jeffh@ActiveState.com>
+ ***POTENTIAL INCOMPATIBILITY***
+ For callers of Tcl_GetObjType() on the name "nsName".
- * library/safe.tcl (FileInAccessPath): normalize paths before
- comparison. [Bug 759607] (myers)
+ * generic/tclExecute.c: Update TclGetNamespaceFromObj() callers.
+ * generic/tclProc.c:
- * unix/tclUnixNotfy.c (NotifierThreadProc): correct size of found and
- word vars from int to long. [Bug 767578] (hgo)
+ * tests/apply.test: Updated tests to expect new consistent
+ * tests/namespace-old.test: error message when a namespace is not
+ * tests/namespace.test: found.
+ * tests/upvar.test:
-2003-07-16 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclCompCmds.c: Use the new INST_REVERSE instruction
+ * tests/mathop.test: to correct the compiled versions of math
+ operator commands. [Bug 1724437]
- * doc/CrtSlave.3 (Tcl_MakeSafe): Updated documentation to strongly
- discourage use. IMHO code outside the core that uses this function is
- a bug... [Bug 655300]
+ * generic/tclCompile.c: New bytecode instruction INST_REVERSE to
+ * generic/tclCompile.h: reverse the order of N items at the top of
+ * generic/tclExecute.c: stack.
-2003-07-16 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclCompCmds.c (TclCompilePowOpCmd): Make a separate
+ routine to compile ** to account for its different associativity.
- * generic/tcl.h: Add recognition of -DTCL_UTF_MAX=6 on the
- * generic/regcustom.h: make line to support UCS-4 mode. No config arg
- at this time, as it is not the recommended build mode.
+2007-09-08 Miguel Sofer <msofer@users.sf.net>
- * generic/tclPreserve.c: In Result and Preserve'd routines, do not
- * generic/tclUtil.c: assume that ckfree == free, as that is not
- * generic/tclResult.c: always true. [Bug 756791] (fuller)
+ * generic/tclVar.c (Tcl_SetVar2, TclPtrSetVar): [Bug 1710710] fixed
+ correctly, reverted fix of 2007-05-01.
-2003-07-16 Mo DeJong <mdejong@users.sourceforge.net>
+2007-09-08 Donal K. Fellows <dkf@users.sf.net>
- * win/Makefile.in: Don't define TCL_DBGX symbol for every compile.
- Instead, define TCL_PIPE_DLL only when compiling tclWinPipe.c. This
- will break other build systems, so they will need to remove the
- TCL_DBGX define and replace it with a define for TCL_PIPE_DLL.
- * win/makefile.vc: Ditto.
- * win/tclWinPipe.c (TclpCreateProcess): Remove PREFIX_IDENT and
- DEBUG_IDENT from top of file. Use TCL_PIPE_DLL passed in from build
- env instead of trying to construct the dll name from already defined
- symbols. This approach is more flexible and better in the long run.
+ * generic/tclDictObj.c (DictUpdateCmd, DictWithCmd): Plug a hole that
+ * generic/tclExecute.c (TEBC,INST_DICT_UPDATE_END): allowed a careful
+ * tests/dict.test (dict-21.16,21.17,22.11): attacker to craft a dict
+ containing a recursive link to itself, violating one of Tcl's
+ fundamental datatype assumptions and causing a stack crash when the
+ dict was converted to a string. [Bug 1786481]
-2003-07-16 Don Porter <dgp@users.sourceforge.net>
+2007-09-07 Don Porter <dgp@users.sourceforge.net>
- * generic/tclFileName.c (Tcl_GlobObjCmd): [Bug 771840]
- * generic/tclIOUtil.c (Tcl_FSConvertToPathType):[Bug 771947]
- * unix/tclUnixFCmd.c (GetModeFromPermString): [Bug 771949]
- Silence compiler warnings about unreached lines.
+ * generic/tclEvent.c ([::tcl::Bgerror]): Corrections to Tcl's
+ * tests/event.test: default [interp bgerror] handler so that when
+ it falls back to a hidden [bgerror] in a safe interp, it gets the
+ right error context data. [Bug 1790274]
- * library/tcltest/tcltest.tcl (ProcessFlags): Corrected broken call
- * library/tcltest/pkgIndex.tcl: to [lrange]. Bumped to
- version 2.2.4. [Bug 772333]
+2007-09-07 Miguel Sofer <msofer@users.sf.net>
-2003-07-15 Mo DeJong <mdejong@users.sourceforge.net>
+ * generic/tclProc.c (TclInitCompiledLocals): the refCount of resolved
+ variables was being managed without checking if they were Var or
+ VarInHash: itcl [Bug 1790184]
- * unix/dltest/pkga.c (Pkga_EqObjCmd): Fix typo that was causing a
- crash in load.test.
+2007-09-06 Don Porter <dgp@users.sourceforge.net>
-2003-07-15 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclResult.c (Tcl_GetReturnOptions): Take care that a
+ * tests/init.test: non-TCL_ERROR code doesn't cause existing
+ -errorinfo, -errorcode, and -errorline entries to be omitted.
+ * generic/tclEvent.c: With -errorInfo no longer lost, generate more
+ complete ::errorInfo when calling [bgerror] after a non-TCL_ERROR
+ background exception.
- * doc/array.n: Added some examples from David Welton [Patch 763312]
+2007-09-06 Don Porter <dgp@users.sourceforge.net>
-2003-07-15 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclInterp.c (Tcl_Init): Removed constraint on ability
+ to define a custom [tclInit] before calling Tcl_Init(). Until now the
+ custom command had to be a proc. Now it can be any command.
- * doc/http.n: Updated SYNOPSIS to match actual syntax of commands.
- [Bug 756112]
+ * generic/tclInt.decls: New internal routine TclBackgroundException()
+ * generic/tclEvent.c: that for the first time permits non-TCL_ERROR
+ exceptions to trigger [interp bgerror] handling. Closes a gap in TIP
+ 221. When falling back to [bgerror] (which is designed only to handle
+ TCL_ERROR), convert exceptions into errors complaining about the
+ exception.
- * unix/dltest/pkga.c: Updated to not use Tcl_UtfNcmp and counted
- strings instead of strcmp (not defined in any #include'd header) and
- presumed NULL-terminated strings.
+ * generic/tclInterp.c: Convert Tcl_BackgroundError() callers to call
+ * generic/tclIO.c: TclBackgroundException().
+ * generic/tclIOCmd.c:
+ * generic/tclTimer.c:
- * README: Bumped patch level to 8.4.4 in anticipation
- * generic/tcl.h: of another patch release.
- * tools/tcl.wse.in:
- * unix/configure.in:
- * unix/tcl.spec:
- * win/README.binary:
- * win/configure.in:
+ * generic/tclIntDecls.h: make genstubs
+ * generic/tclStubInit.c:
- * unix/configure: autoconf (2.13)
- * win/configure:
+2007-09-06 Daniel Steffen <das@users.sourceforge.net>
- * generic/tclCompCmds.c (TclCompileIfCmd): Prior fix of Bug 711371
- on 2003-04-07 introduced a buffer overflow. Corrected. [Bug 771613]
+ * macosx/Tcl.xcode/project.pbxproj: discontinue unmaintained support
+ * macosx/Tcl.xcode/default.pbxuser: for Xcode 1.5; replace by Xcode2
+ project for use on Tiger (with Tcl.xcodeproj to be used on Leopard).
-2003-07-15 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * macosx/Tcl.xcodeproj/project.pbxproj: updates for Xcode 2.5 and 3.0.
+ * macosx/Tcl.xcodeproj/default.pbxuser:
+ * macosx/Tcl.xcode/project.pbxproj:
+ * macosx/Tcl.xcode/default.pbxuser:
+ * macosx/Tcl-Common.xcconfig:
- * generic/tclCmdIL.c (SortCompare): Cleared up confusing error
- message. [Bug 771539]
+ * macosx/README: document project changes.
-2003-07-15 Daniel Steffen <das@users.sourceforge.net>
+2007-09-05 Don Porter <dgp@users.sourceforge.net>
- * macosx/Makefile: Rewrote buildsystem for Mac OS X framework build to
- be purely make driven; in order to become independent of Apple's
- closed-source IDE and build tool. The changes are intended to be
- transparent to the Makefile user, all existing make targets and cmd
- line variable overrides should continue to work. Changed build to only
- include tcl specific html help in Tcl.framework, the tk specific html
- help is now included in Tk.framework.
+ * generic/tclBasic.c: Removed support for the unmaintained
+ * generic/tclExecute.c: -DTCL_GENERIC_ONLY configuration. [Bug
+ * unix/Makefile.in: 1264623]
- * macosx/Tcl.pbproj/project.pbxproj:
- * macosx/Tcl.pbproj/jingham.pbxuser: Changed to purely call through to
- the make driven buildsystem; Tcl.framework is no longer assembled by
- ProjectBuilder. Set default SYMROOT in target options to simplify
- setting up PB (manually setting common build folder for tcl & tk no
- longer needed).
+2007-09-04 Don Porter <dgp@users.sourceforge.net>
- * tools/tcltk-man2html.tcl: Added options to allow building only the
- tcl or tk html help files; the default behaviour with none of the new
- options is to build both, as before.
+ * unix/Makefile.in: It's unreliable to count on the release
+ manager to remember to `make genstubs` before `make dist`. Let the
+ Makefile remember the dependency for us.
- * unix/Makefile.in: Added targets for building only the tcl or tk help.
+ * unix/Makefile.in: Corrections to `make dist` dependencies to be
+ sure that macosx/configure gets generated whenever it does not exist.
- * macosx/README (new): Tcl specific excerpts of tk/macosx/README.
+2007-09-03 Kevin B, Kenny <kennykb@acm.org>
- * generic/tcl.h: Updated reminder comment about editing
- macosx/Tcl.pbproj/project.pbxproj when version number changes.
+ * library/tzdata/Africa/Cairo:
+ * library/tzdata/America/Grand_Turk:
+ * library/tzdata/America/Port-au-Prince:
+ * library/tzdata/America/Indiana/Petersburg:
+ * library/tzdata/America/Indiana/Tell_City:
+ * library/tzdata/America/Indiana/Vincennes:
+ * library/tzdata/Antarctica/McMurdo:
+ * library/tzdata/Australia/Adelaide:
+ * library/tzdata/Australia/Broken_Hill:
+ * library/tzdata/Australia/Currie:
+ * library/tzdata/Australia/Hobart:
+ * library/tzdata/Australia/Lord_Howe:
+ * library/tzdata/Australia/Melbourne:
+ * library/tzdata/Australia/Sydney:
+ * library/tzdata/Pacific/Auckland:
+ * library/tzdata/Pacific/Chatham: Olson's tzdata2007g.
-2003-07-11 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclListObj.c (TclLindexFlat):
+ * tests/lindex.test (lindex-17.[01]): Added code to detect the error
+ when a script does [lindex {} end foo]; an overaggressive optimisation
+ caused this call to return an empty object rather than an error.
- * tests/binary.test (binary-46.*): Tests to help enforce the current
- behaviour.
- * doc/binary.n: Documented that [binary format a] and [binary scan a]
- do encoding conversion by dropping high bytes, unlike the rest of
- the core. [Bug 735364]
+2007-09-03 Daniel Steffen <das@users.sourceforge.net>
-2003-07-11 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclObj.c (TclInitObjSubsystem): restore registration of the
+ "wideInt" Tcl_ObjType for compatibility with 8.4 extensions that
+ access the tclWideIntType Tcl_ObjType; add setFromAnyProc for
+ tclWideIntType.
- * library/package.tcl: Corrected [pkg_mkIndex] bug reported on
- comp.lang.tcl. The indexer was searching for newly indexed packages
- instead of newly provided packages.
+2007-09-02 Donal K. Fellows <dkf@users.sf.net>
-2003-07-04 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * doc/lsearch.n: Added note that order of results with the -all option
+ is that of the input list. It always was, but this makes it crystal.
- * doc/expr.n: Tighten up the wording of some operations. [Bug 758488]
+2007-08-30 Don Porter <dgp@users.sourceforge.net>
- * tests/cmdAH.test: Made tests of [file mtime] work better on FAT
- filesystems. [Patch 760768] Also a little general cleanup.
+ * generic/tclCompile.c: Added fflush() calls following all callers of
+ * generic/tclExecute.c: TclPrintByteCodeObj() so that tcl_traceCompile
+ output is less likely to get mangled when writes to stdout interleave
+ with other code.
-2003-06-25 Mo DeJong <mdejong@users.sourceforge.net>
+2007-08-28 Don Porter <dgp@users.sourceforge.net>
- * unix/configure: Regen.
- * unix/tcl.m4 (SC_CONFIG_CFLAGS): Add -ieee when compiling with cc and
- add -mieee when compiling with gcc under OSF1-V5 "Tru64" systems. [Bug
- 748957]
+ * generic/tclCompExpr.c: Use a table lookup in ParseLexeme() to
+ determine lexemes with single-byte representations.
-2003-06-24 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclBasic.c: Used unions to better clarify overloading of
+ * generic/tclCompExpr.c: the fields of the OpCmdInfo and
+ * generic/tclCompile.h: TclOpCmdClientData structs.
- * doc/encoding.n: Corrected the docs to say that [source] uses the
- system encoding, which it always did anyway (since 8.1) [Bug 742100]
+2007-08-27 Don Porter <dgp@users.sourceforge.net>
-2003-06-23 Vince Darley <vincentdarley@users.sourceforge.net>
+ * generic/tclCompExpr.c: Call TclCompileSyntaxError() when
+ expression syntax errors are found when compiling expressions. With
+ this in place, convert TclCompileExpr to return void, since there's no
+ longer any need to report TCL_ERROR.
+ * generic/tclCompile.c: Update callers.
+ * generic/tclExecute.c:
- * generic/tclFCmd.c: fix to bad error message when trying to do 'file
- copy foo ""'. [Bug 756951]
- * tests/fCmd.test: added two new tests for the bug.
+ * generic/tclCompCmds.c: New routine TclCompileSyntaxError()
+ * generic/tclCompile.h: to directly compile bytecodes that report a
+ * generic/tclCompile.c: syntax error, rather than (ab)use a call to
+ TclCompileReturnCmd. Also, undo the most recent commit that papered
+ over some issues with that (ab)use. New routine produces a new opcode
+ INST_SYNTAX, which is a minor variation of INST_RETURN_IMM. Also a bit
+ of constification.
- * doc/FileSystem.3: documentation fix [Bug 720634]
+ * generic/tclCompile.c: Move the deallocation of local LiteralTable
+ * generic/tclCompExpr.c: entries into TclFreeCompileEnv().
+ * generic/tclExecute.c: Update callers.
-2003-06-18 Miguel Sofer <msofer@users.sf.net>
+ * generic/tclCompExpr.c: Force numeric and boolean literals in
+ expressions to register with their intreps intact, even if that means
+ overwriting existing intreps in already registered literals.
- * generic/tclNamesp.c (Tcl_Export): removed erroneous comments [Bug
- 756744]
+2007-08-25 Kevin B. Kenny <kennykb@acm.org>
-2003-06-17 Vince Darley <vincentdarley@users.sourceforge.net>
+ * generic/tclExecute.c (TclExecuteByteCode): Added code to handle
+ * tests/expr.test (expr-23.48-53) integer exponentiation
+ that results in 32- and 64-bit integer results, avoiding calls to wide
+ integer exponentiation routines in this common case. [Bug 1767293]
- * generic/tclCmdMZ.c:
- * tests/regexp.test: fixing of bugs related to regexp and regsub
- matching of empty strings. Addition of a number of new tests.
+ * library/clock.tcl (ParseClockScanFormat): Modified code to allow
+ * tests/clock.test (clock-60.*): case-insensitive matching
+ of time zone and month names. [Bug 1781282]
-2003-06-10 Miguel Sofer <msofer@users.sf.net>
+2007-08-24 Don Porter <dgp@users.sourceforge.net>
- * generic/tclBasic.c:
- * generic/tclExecute.c: let TclEvalObjvInternal call TclInterpReady
- instead of relying on its callers to do so; fix for the part of [Bug
- 495830] that is new in 8.4.
- * tests/interp.test: Added tests 18.9 (knownbug) and 18.10
+ * generic/tclCompExpr.c: Register literals found in expressions
+ * tests/compExpr.test: to restore literal sharing. Preserve numeric
+ intreps when literals are created for the first time. Correct memleak
+ in ExecConstantExprTree() and add test for the leak.
-2003-06-09 Don Porter <dgp@users.sourceforge.net>
+2007-08-24 Miguel Sofer <msofer@users.sf.net>
- * tests/string.test (string-4.15): Added test for [string first] bug
- reported in Tcl 8.3, where test for all-single-byte-encoded strings
- was not reliable.
+ * generic/tclCompile.c: replaced copy loop that tripped some compilers
+ with memmove. [Bug 1780870]
-2003-06-04 Joe Mistachkin <joe@mistachkin.com>
+2007-08-23 Don Porter <dgp@users.sourceforge.net>
- * tools/man2help.tcl: Added duplicate help section checking and
- * tools/index.tcl: corrected a comment typo for the getTopics proc
- in index.tcl. [Bug 748700]
+ * library/init.tcl ([auto_load_index]): Delete stray "]" that created
+ an expr syntax error (masked by a [catch]).
-2003-05-23 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclCompCmds.c (TclCompileReturnCmd): Added crash protection
+ to handle callers other than TclCompileScript() failing to meet the
+ initialization assumptions of the TIP 280 code in CompileWord().
- * generic/tclObj.c (tclCmdNameType): Converted internal rep
- management of the cmdName Tcl_ObjType the opposite way, to always use
- the twoPtrValue instead of always using the otherValuePtr. Previous
- fix on 2003-05-12 broke several extensions that wanted to poke around
- with the twoPtrValue.ptr2 value of a cmdName Tcl_Obj, like TclBlend
- and e4graph. [Bug 726018] Thanks to George Petasis for the bug report
- and Jacob Levy for testing assistance.
+ * generic/tclCompExpr.c: Suppress the attempt to convert to
+ numeric when pre-compiling a constant expresion indicates an error.
-2003-05-22 Daniel Steffen <das@users.sourceforge.net>
+2007-08-22 Miguel Sofer <msofer@users.sf.net>
- *** 8.4.3 TAGGED FOR RELEASE ***
+ * generic/tclExecute.c (TEBC): disable the new shortcut to frequent
+ INSTs for debug builds. REVERTED (collision with alternative fix)
- * macosx/tclMacOSXBundle.c: fixed a problem that caused only the first
- call to Tcl_MacOSXOpenVersionedBundleResources() for a given bundle
- identifier to succeed. This caused the tcl runtime library not to be
- found in all interps created after the inital one.
+2007-08-21 Don Porter <dgp@users.sourceforge.net>
-2003-05-20 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclMain.c: Corrected the logic of dropping the last
+ * tests/main.test: newline from an interactively typed command.
+ [Bug 1775878]
- * changes: updated for 8.4.3
+2007-08-21 Pat Thoyts <patthoyts@users.sourceforge.net>
- * unix/Makefile.in: do not run autoconf during 'make dist' as the
- configure is now a CVS-maintained file and should be up-to-date.
+ * tests/thread.test: thread-4.4: clear ::errorInfo in the thread as a
+ message is left here from init.tcl on windows due to no tcl_pkgPath.
-2003-05-19 Daniel Steffen <das@users.sourceforge.net>
+2007-08-20 Miguel Sofer <msofer@users.sf.net>
- * macosx/Tcl.pbproj/project.pbxproj: changed tclConfig.sh location in
- versioned framework subdirectories to be identical to location in
- framework toplevel; fixed stub library symbolic links to be Tcl
- version specific.
+ * generic/tclExecute.c (INST_SUB): fix usage of the new macro for
+ overflow detection in sums, adapt to subtraction. Lengthy comment
+ added.
-2003-05-16 Daniel Steffen <das@users.sourceforge.net>
+2007-08-19 Donal K. Fellows <dkf@users.sf.net>
- * macosx/Tcl.pbproj/project.pbxproj: updated copyright year.
+ * generic/tclExecute.c (Overflowing, TclIncrObj, TclExecuteByteCode):
+ Encapsulate Miguel's last change in a more mnemonic macro.
-2003-05-15 Jeff Hobbs <jeffh@ActiveState.com>
+2007-08-19 Miguel Sofer <msofer@users.sf.net>
- * win/tclWinFile.c (TclpMatchInDirectory): revert glob code to r1.44
- as 2003-04-14 optimizations broke Windows98 glob'ing.
+ * generic/tclExecute.c: changed the check for overflow in sums,
+ reducing objsize, number of branches and cache misses (according to
+ cachegrind). Non-overflow for s=a+b:
+ previous
+ ((a >= 0 || b >= 0 || s < 0) && (s >= 0 || b < 0 || a < 0))
+ now
+ (((a^s) >= 0) || ((a^b) < 0))
+ This expresses: "a and s have the same sign or else a and b have
+ different sign".
- * README: bumped version to 8.4.3
- * generic/tcl.h:
- * macosx/Tcl.pbproj/project.pbxproj:
- * tools/tcl.wse.in:
- * unix/configure:
- * unix/configure.in:
- * unix/tcl.spec:
- * win/README.binary:
- * win/configure:
- * win/configure.in:
+2007-08-19 Donal K. Fellows <dkf@users.sf.net>
- * doc/socket.n: nroff font handling correction.
+ * doc/interp.n (RESOURCE LIMITS): Added text to better explain why
+ time limits are described using absolute times. [Bug 1752148]
- * library/encoding/gb2312-raw.enc (new): This is the original
- gb2312.enc renamed to allow for it to still be used. This is needed by
- Tk (unix) because X fonts with gb2312* charsets really do want the
- original gb2312 encoding. [Bug 557030]
+2007-08-16 Miguel Sofer <msofer@users.sf.net>
-2003-05-14 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclVar.c: improved localVarNameType caching to leverage
+ the new availability of Tcl_Obj in variable names, avoiding string
+ comparisons to verify that the cached value is usable.
- * generic/tclCmdAH.c (Tcl_FormatObjCmd): Values which can't be
- anything but wide shouldn't be demoted to long. [consequence of HEAD
- fixes for Bug 699060]
+ * generic/tclExecute.c: check the two most frequent instructions
+ before the switch. Reduces both runtime and obj size a tiny bit.
-2003-05-14 Jeff Hobbs <jeffh@ActiveState.com>
+2007-08-16 Don Porter <dgp@users.sourceforge.net>
- * library/encoding/gb2312.enc: copy euc-cn.enc over original
- gb2312.enc. gb2312.enc appeared to not work as expected, and most uses
- of gb2312 really mean euc-cn (which may be the cause of the problem).
- [Bug 557030]
+ * generic/tclCompExpr.c: Added a "constant" field to the OpNode
+ struct (again "free" due to alignment requirements) to mark those
+ subexpressions that are completely known at compile time. Enhanced
+ CompileExprTree() and its callers to precompute these constant
+ subexpressions at compile time. This resolves the issue raised in [Bug
+ 1564517].
- * generic/tclEnv.c (TclUnsetEnv): Another putenv() copy behavior
- problem repaired when compiling on windows and using microsoft's
- runtime. [Bug 736421] (gravereaux)
+2007-08-15 Donal K. Fellows <donal.k.fellows@man.ac.uk>
-2003-05-13 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclIOUtil.c (TclGetOpenModeEx): Only set the O_APPEND flag
+ * tests/ioUtil.test (ioUtil-4.1): on a channel for the 'a'
+ mode and not for 'a+'. [Bug 1773127]
- * generic/tclIOUtil.c: add decl for FsThrExitProc to suppress warnings
+2007-08-14 Miguel Sofer <msofer@users.sf.net>
-2003-05-13 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclExecute.c (INST_INVOKE*): peephole opt, do not get the
+ interp's result if it will be pushed/popped.
- * generic/tclEvent.c (Tcl_Finalize): Removed unused variable to reduce
- compiler warnings. [Bug 664745]
+2007-08-14 Don Porter <dgp@users.sourceforge.net>
-2003-05-13 Joe Mistachkin <joe@mistachkin.com>
+ * generic/tclBasic.c: Use fully qualified variable names for
+ * tests/thread.test: ::errorInfo and ::errorCode so that string
+ * tests/trace.test: reported to variable traces are fully
+ qualified in agreement with Tcl 8.4 operations.
- * generic/tcl.decls: Changed Tcl_JoinThread parameter name from "id"
- * generic/tclDecls.h: to "threadId". [Bug 732477]
- * unix/tclUnixThrd.c:
- * win/tclWinThrd.c:
- * mac/tclMacThrd.c:
+2007-08-14 Daniel Steffen <das@users.sourceforge.net>
-2003-05-13 Daniel Steffen <das@users.sourceforge.net>
+ * unix/tclLoadDyld.c: use dlfcn API on Mac OS X 10.4 and later; fix
+ issues with loading from memory on intel and 64bit; add debug messages
- * generic/tcl.decls:
- * macosx/tclMacOSXBundle.c: added extended version of the
- Tcl_MacOSXOpenBundleResources() API taking an extra version number
- argument: Tcl_MacOSXOpenVersionedBundleResources(). This is needed to
- be able to access bundle resources in versioned frameworks such as Tcl
- and Tk, otherwise if multiple versions were installed, only the latest
- version's resources could be accessed. [Bug 736774]
+ * tests/load.test: add test load-10.1 for loading from vfs.
- * unix/tclUnixInit.c (Tcl_MacOSXGetLibraryPath): use new versioned
- bundle resource API to get tcl runtime library for TCL_VERSION.
- [Bug 736774]
+ * unix/dltest/pkga.c: whitespace & comment cleanup, remove
+ * unix/dltest/pkgb.c: unused pkgf.c.
+ * unix/dltest/pkgc.c:
+ * unix/dltest/pkge.c:
+ * unix/dltest/pkgf.c (removed):
+ * unix/dltest/pkgua.c:
+ * macosx/Tcl.xcodeproj/project.pbxproj:
- * generic/tclPlatDecls.h:
- * generic/tclStubInit.c: regen.
+2007-08-13 Don Porter <dgp@users.sourceforge.net>
- * unix/tclUnixPort.h: worked around the issue of realpath() not being
- thread-safe on Mac OS X by defining NO_REALPATH for threaded builds on
- Mac OS X. [Bug 711232]
+ * generic/tclExecute.c: Provide DECACHE/CACHE protection to the
+ * tests/trace.test: Tcl_LogCommandInfo() call. [Bug 1773040]
-2003-05-12 Don Porter <dgp@users.sourceforge.net>
+2007-08-12 Miguel Sofer <msofer@users.sf.net>
- * generic/tclInterp.c: (AliasObjCmd): Added refCounting of the words
- * tests/interp.test (interp-33.1): of the target of an interp
- alias during its execution. Also added test. [Bug 730244].
+ * generic/tclCmdMZ.c (Tcl_SplitObjCmd): use TclNewStringObj macro
+ instead of calling the function.
- * generic/tclBasic.c (TclInvokeObjectCommand): objv[argc] is no
- longer set to NULL (Tcl_CreateObjCommand docs already say that it
- should not be accessed).
+ * generic/tcl_Obj.c (TclAllocateFreeObjects): remove unneeded memset
+ to 0 of all allocated objects.
- * generic/tclObj.c (tclCmdNameType): Corrected variable use of the
- otherValuePtr or the twoPtrValue.ptr1 fields to store a
- (ResolvedCmdName *) as the internal rep. [Bug 726018].
+2007-08-10 Miguel Sofer <msofer@users.sf.net>
- * doc/Eval.3: Corrected prototype for Tcl_GlobalEvalObj [Bug 727622].
+ * generic/tclInt.h: remove redundant ops in TclNewStringObj macro.
-2003-05-12 Miguel Sofer <msofer@users.sf.net>
+2007-08-10 Miguel Sofer <msofer@users.sf.net>
- * generic/tclVar.c (TclObjLookupVar): [Bug 735335] temporary fix,
- disabling usage of tclNsVarNameType.
- * tests/var.test (var-15.1): test for [Bug 735335]
+ * generic/tclInt.h: fix the TclSetVarNamespaceVar macro, was causing a
+ leak.
-2003-05-10 Zoran Vasiljevic <zoran@archiware.com>
+2007-08-10 Don Porter <dgp@users.sourceforge.net>
- * unix/tclUnixThrd.c: corrected [Bug 723502]
+ * generic/tclCompExpr.c: Revise CompileExprTree() to use the
+ OpNode mark field scheme of tree traversal. This eliminates the need
+ to use magic values in the left and right fields for that purpose.
+ Also stop abusing the left field within ParseExpr() to store the
+ number of arguments in a parsed function call. CompileExprTree() now
+ determines that for itself at compile time. Then reorder code to
+ eliminate duplication.
-2003-05-10 Jeff Hobbs <jeffh@ActiveState.com>
+2007-08-09 Miguel Sofer <msofer@users.sf.net>
- * generic/tclIOUtil.c: ensure cd is thread-safe.
- [Bug 710642] (vasiljevic)
+ * generic/tclProc.c (TclCreateProc): better comments on the required
+ varflag values when loading precompiled procs.
- * win/tclWinSerial.c (SerialCloseProc): correct mem leak on closing a
- Windows serial port [Bug 718002] (schroedter)
+ * generic/tclExecute.c (INST_STORE_ARRAY):
+ * tests/trace.test (trace-2.6): whole array write traces on compiled
+ local variables were not firing. [Bug 1770591]
- * generic/tclCmdMZ.c (Tcl_StringObjCmd): prevent string repeat crash
- when overflow sizes were given (throws error). [Bug 714106]
+2007-08-08 Jeff Hobbs <jeffh@ActiveState.com>
-2003-05-09 Joe Mistachkin <joe@mistachkin.com>
+ * generic/tclProc.c (InitLocalCache): reference firstLocalPtr via
+ procPtr. codePtr->procPtr == NULL exposed by tbcload.
- * generic/tclThreadAlloc.c (TclFreeAllocCache): Fixed memory leak
- caused by treating cachePtr as a TLS index [Bug 731754].
+2007-08-08 Don Porter <dgp@users.sourceforge.net>
- * win/tclAppInit.c (Tcl_AppInit): Fixed memory leaks caused by not
- freeing the memory allocated by setargv and the async handler created
- by Tcl_AppInit. An exit handler has been created that takes care of
- both leaks. In addition, Tcl_AppInit now uses ckalloc instead of
- Tcl_Alloc to allow for easier leak tracking and to be more consistent
- with the rest of the Tcl core [Bugs 733156, 733221].
+ * generic/tclExecute.c: Corrected failure to compile/link in the
+ -DNO_WIDE_TYPE configuration.
- * tools/encoding/txt2enc.c (main): Fixed memory leak caused by failing
- to free the memory used by the toUnicode array of strings [Bug 733221]
+ * generic/tclExecute.c: Corrected improper use of bignum arguments to
+ * tests/expr.test: *SHIFT operations. [Bug 1770224]
-2003-05-05 Don Porter <dgp@users.sourceforge.net>
+2007-08-07 Miguel Sofer <msofer@users.sf.net>
- * library/tcltest/tcltest.tcl: The -returnCodes option to [test]
- failed to recognize the symbolic name "ok" for return code 0.
+ * generic/tclInt.h: remove comments refering to VAR_SCALAR, as that
+ flag bit does not exist any longer.
+ * generic/tclProc.c (InitCompiledLocals): removed optimisation for
+ non-resolved case, as the function is never called in that case.
+ Renamed the function to InitResolvedLocals to calrify the point.
-2003-05-05 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclInt.decls: Exporting via stubs to help xotcl adapt to
+ * generic/tclInt.h: VarReform.
+ * generic/tclIntDecls.h:
+ * generic/tclStubInit.c:
- * generic/tclBasic.c (Tcl_HideCommand): Fixed error message grammar
- and spelling.
+2007-08-07 Daniel Steffen <das@users.sourceforge.net>
-2003-04-29 Vince Darley <vincentdarley@users.sourceforge.net>
+ * generic/tclEnv.c: improve environ handling on Mac OS X (adapted
+ * unix/tclUnixPort.h: from Apple changes in Darwin tcl-64).
- * generic/tclFileName.c: fix to bug reported privately by Jeff where,
- for example, 'glob -path {[tcl]} *' gets confused by the leading
- special character (which is escaped internally), and instead lists
- files in '/'. Bug only occurs on Windows where '\' is also a
- directory separator. (Bug has been around at least since Tcl 8.3.)
- * tests/fileName.test: added test for the above bug.
+ * unix/Makefile.in: add support for compile flags specific to
+ object files linked directly into executables.
-2003-04-25 Don Porter <dgp@users.sourceforge.net>
+ * unix/configure.in (Darwin): only use -seg1addr flag when prebinding;
+ use -mdynamic-no-pic flag for object files linked directly into exes;
+ support overriding TCL_PACKAGE_PATH/TCL_MODULE_PATH in environment.
- * generic/tclBasic.c: Tcl_EvalObjv() failed to honor the
- TCL_EVAL_GLOBAL flag when resolving command names. Tcl_EvalEx passed a
- string rep including leading whitespace and comments to
- TclEvalObjvInternal().
+ * unix/configure: autoconf-2.59
-2003-04-25 Andreas Kupries <andreask@activestate.com>
+2007-08-06 Don Porter <dgp@users.sourceforge.net>
- * win/tclWinThrd.c: Applied [Patch 727271]. This patch changes the
- code to catch any errors returned by the windows functions handling
- TLS ASAP instead of waiting to get some mysterious crash later on due
- to bogus pointers. Patch provided by Joe Mistachkin.
+ * tests/parseExpr.test: Update source file name of expr parser code.
- This is a stop-gap measure to deal with the low number of ?TLS slots
- provided by some of the variants of Windows (60-80).
+ * generic/tclCompExpr.c: Added a "mark" field to the OpNode
+ struct, which is used to guide tree traversal. This field costs
+ nothing since alignement requirements used the memory already.
+ Rewrote ConvertTreeToTokens() to use the new field, which permitted
+ consolidation of utility routines CopyTokens() and
+ GenerateTokensForLiteral().
-2003-04-21 Don Porter <dgp@users.sourceforge.net>
+2007-08-06 Kevin B. Kenny <kennykb@users.sf.net>
- * library/tcltest/tcltest.tcl: When the return code of a test does
- not meet expectations, report that as the reason for test failure,
- and do not attempt to check the test result for correctness. [Bug
- 725253]
+ * generic/tclGetDate.y: Added a cast to the definition of YYFREE to
+ silence compiler warnings.
+ * generic/tclDate.c: Regenerated
+ * win/tclWinTest.c: Added a cast to GetSecurityDescriptorDacl call
+ to silence compiler warnings.
-2003-04-18 Jeff Hobbs <jeffh@ActiveState.com>
+2007-08-04 Miguel Sofer <msofer@users.sf.net>
- * generic/tclExecute.c (ExprCallMathFunc): remove incorrect
- extraneous cast from Tcl_WideAsDouble.
+ * generic/tclInt.decls: Exporting via stubs to help itcl adapt to
+ * generic/tclInt.h: VarReform. Added localCache initialization
+ * generic/tclIntDecls.h: to TclInitCompiledLocals (which only exists
+ * generic/tclProc.c: for itcl).
+ * generic/tclStubInit.c:
+ * generic/tclVar.c:
-2003-04-18 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+2007-08-01 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * doc/open.n: Moved serial port options from [fconfigure]
- * doc/fconfigure.n: to [open] as it is up to the creator of a
- channel to describe the channel's special
- config options. [Bug 679010]
+ * library/word.tcl: Rewrote for greater efficiency. [Bug 1764318]
-2003-04-16 Don Porter <dgp@users.sourceforge.net>
+2007-08-01 Pat Thoyts <patthoyts@users.sourceforge.net>
- * generic/tcl.h Made changes so that the "wideInt" Tcl_ObjType
- * generic/tclObj.c is defined on all platforms, even those where
- * generic/tclPort.h TCL_WIDE_INT_IS_LONG is defined. Also made
- the Tcl_Value struct have a wideValue field on all platforms. This is
- a ***POTENTIAL INCOMPATIBILITY*** for TCL_WIDE_INT_IS_LONG platforms
- because that struct changes size. This is the same TIP 72
- incompatibility that was seen on other platforms at the 8.4.0 release,
- when this change should have happened as well. [Bug 713562]
+ * generic/tclInt.h: Added a TclOffset macro ala Tk_Offset to
+ * generic/tclVar.c: abstract out 'offsetof' which may not be
+ * generic/tclExceute.c: defined (eg: msvc6).
- * generic/tclInt.h: New internal macros TclGetWide() and
- TclGetLongFromWide() to deal with both forms of the "wideInt"
- Tcl_ObjType, so that conditional TCL_WIDE_INT_IS_LONG code
- is confined to the header file.
+2007-08-01 Miguel Sofer <msofer@users.sf.net>
- * generic/tclCmdAH.c: Replaced most coding that was conditional
- * generic/tclCmdIL.c: on TCL_WIDE_INT_IS_LONG with code that
- * generic/tclExecute.c: works across platforms, sometimes using
- * generic/tclTest.c: the new macros above to do it.
- * generic/tclUtil.c:
- * generic/tclVar.c:
+ * generic/tclVar.c (TclCleanupVar): fix [Bug 1765225], thx Larry
+ Virden.
-2003-04-17 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+2007-07-31 Miguel Sofer <msofer@users.sf.net>
- * doc/socket.n: Added a paragraph to remind people to specify
- their encodings when using sockets. [Bug 630621]
+ * doc/Hash.3:
+ * generic/tclHash.c:
+ * generic/tclObj.c:
+ * generic/tclThreadStorage.c: (changes part of the patch below)
+ Stop Tcl_CreateHashVar from resetting hPtr->clientData to NULL after
+ calling the allocEntryProc for a custom table.
-2003-04-16 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tcl.h:
+ * generic/tclBasic.c:
+ * generic/tclCmdIL.c:
+ * generic/tclCompCmds.c:
+ * generic/tclCompile.c:
+ * generic/tclCompile.h:
+ * generic/tclExecute.c:
+ * generic/tclHash.c:
+ * generic/tclInt.decls:
+ * generic/tclInt.h:
+ * generic/tclIntDecls.h:
+ * generic/tclLiteral.c:
+ * generic/tclNamesp.c:
+ * generic/tclObj.c:
+ * generic/tclProc.c:
+ * generic/tclThreadStorage.c:
+ * generic/tclTrace.c:
+ * generic/tclVar.c: VarReform [Patch 1750051]
+
+ *** POTENTIAL INCOMPATIBILITY *** (tclInt.h and tclCompile.h)
+ Extensions that access internals defined in tclInt.h and/or
+ tclCompile.h may lose both binary and source compatibility. The
+ relevant changes are:
+ 1. 'struct Var' is completely changed, all acceses to its internals
+ (either direct or via the TclSetVar* and TclIsVar* macros) will
+ malfunction. Var flag values and semantics changed too.
+ 2. 'struct Bytecode' has an additional field that has to be
+ initialised to NULL
+ 3. 'struct Namespace' is larger, as the varTable is now one pointer
+ larger than a Tcl_HashTable. Direct access to its fields will
+ malfunction.
+ 4. 'struct CallFrame' grew one more field (the second such growth with
+ respect to Tcl8.4).
+ 5. API change for the functions TclFindCompiledLocal, TclDeleteVars
+ and many internal functions in tclVar.c
+
+ Additionally, direct access to variable hash tables via the standard
+ Tcl_Hash* interface is to be considered as deprecated. It still works
+ in the present version, but will be broken by further specialisation
+ of these hash tables. This concerns especially the table of array
+ elements in an array, as well as the varTable field in the Namespace
+ struct.
+
+2007-07-31 Miguel Sofer <msofer@users.sf.net>
+
+ * unix/configure.in: allow use of 'inline' in Tcl sources. [Patch
+ * win/configure.in: 1754128]
+ * win/makefile.vc: Regen with autoconf 2.61
+
+2007-07-31 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * unix/tclUnixInit.c (TclpSetVariables): Use the thread-safe getpwuid
+ replacement to fill the tcl_platform(user) field as it is not subject
+ to spoofing. [Bug 681877]
+
+ * unix/tclUnixCompat.c: Simplify the #ifdef logic.
+
+ * unix/tclUnixChan.c (FileWatchProc): Fix test failures.
+
+2007-07-30 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * unix/tclUnixChan.c (SET_BITS, CLEAR_BITS): Added macros to make this
+ file clearer.
+
+2007-07-24 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclBasic.c (TEOvI, GetCommandSource):
+ * generic/tclExecute.c (TEBC, TclGetSrcInfoForCmd):
+ * generic/tclInt.h:
+ * generic/tclTrace.c (TclCheck(Interp|Execution)Traces):
+ Removed the need for TEBC to inspect the command before calling TEOvI,
+ leveraging the TIP 280 infrastructure. Moved the generation of a
+ correct nul-terminated command string away from the trace code, back
+ into TEOvI/GetCommandSource.
- * doc/CrtMathFnc.3: Functions also have to deal with wide ints,
- but this was not documented. [Bug 709720]
+2007-07-20 Andreas Kupries <andreask@activestate.com>
-2003-04-15 Kevin Kenny <kennykb@acm.org>
+ * library/platform/platform.tcl: Fixed bug in 'platform::patterns'
+ * library/platform/pkgIndex.tcl: where identifiers not matching
+ * unix/Makefile.in: the special linux and solaris forms would not
+ * win/Makefile.in: get 'tcl' as an acceptable platform added to
+ * doc/platform.n: the result. Bumped package to version 1.0.3 and
+ * doc/platform_shell.n: updated documentation and Makefiles. Also
+ fixed bad version info in the documentation of platform::shell.
- * win/tclWinTime.c: Corrected use of types to make compilation
- compatible with VC++5.
+2007-07-19 Don Porter <dgp@users.sourceforge.net>
-2003-04-14 Kevin Kenny <kennykb@acm.org>
+ * generic/tclParse.c: In contexts where interp and parsePtr->interp
+ might be different, be sure to use the latter for error reporting.
+ Also pulled the interp argument back out of ParseTokens() since we
+ already had a parsePtr->interp to work with.
- * win/tclWinFile.c: added conditionals to restore compilation on
- VC++6, which was broken by recent changes.
+2007-07-18 Don Porter <dgp@users.sourceforge.net>
-2003-04-14 Vince Darley <vincentdarley@users.sourceforge.net>
+ * generic/tclCompExpr.c: Removed unused arguments and variables
- Merged various bug fixes from current cvs head:
+2007-07-17 Don Porter <dgp@users.sourceforge.net>
- * tests/cmdAH.test: better fix to test suite problem if /home is a
- symlink [Bug 703264]
+ * generic/tclCompExpr.c (ParseExpr): While adding comments to
+ explain the operations of ParseExpr(), made significant revisions to
+ the code so it would be easier to explain, and in the process made the
+ code simpler and clearer as well.
- * generic/tclIOUtil.c: fix bad error message with 'cd ""' [Bug 704917]
- * win/tclWinFile.c:
- * win/tclWin32Dll.c:
- * win/tclWinInt.h: allow Tcl to differentiate between reparse points
- which are symlinks and mounted volumes, and correctly handle the
- latter. This involves some elaborate code to find the actual drive
- letter (if possible) corresponding to a mounted volume. [Bug 697862]
- * tests/fileSystem.test: add constraints to stop tests running in
- ordinary tcl interpreter. [Bug 705675]
- * generic/tclIOUtil.c: Some re-arrangement of code to bring it closer
- to CVS HEAD. No functional changes.
+2007-07-15 Don Porter <dgp@users.sourceforge.net>
- * tests/fCmd.test:
- * win/tclWinFile.c: added some filesystem optimisation to the
- 'glob' implementation, and some new tests.
+ * generic/tclCompExpr.c: More commentary.
+ * tests/parseExpr.test: Several tests of syntax error messages
+ to check that when expression substrings are truncated they leave
+ visible the context relevant to the reported error.
- * tests/winFile.test:
- * tests/ioUtil.test:
- * tests/unixFCmd.test: renumbered tests with duplicate numbers. [Bug
- 710361]
+2007-07-12 Don Porter <dgp@users.sourceforge.net>
-2003-04-12 Kevin Kenny <kennykb@acm.org>
+ * generic/tclCompExpr.c: Factored out, corrected, and commented
+ common code for reporting syntax errors in LEAF elements.
- * tests/clock.test: Renumbered test cases to avoid duplicates [Bug
- 710310].
- * tests/winTime.test:
- * win/tclWinTest.c (TestwinclockCmd, TestwinsleepCmd):
- * win/tclWinTime.c (Tcl_WinTime, UpdateTimeEachSecond,
- (ResetCounterSamples, AccumulateSample, SAMPLES, TimeInfo): Made
- substantial changes to the phase-locked loop (replaced an IIR filter
- with an FIR one) in a quest for improved loop stability (Bug not
- logged at SF, but cited in private communication from Jeff Hobbs).
+2007-07-11 Miguel Sofer <msofer@users.sf.net>
-2003-04-11 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclCompCmds.c (TclCompileWhileCmd):
+ * generic/tclCompile.c (TclCompileScript):
+ Corrected faulty avoidance of INST_START_CMD when the first opcode in
+ a script is within a loop (as produced by 'while 1'), so that the
+ corresponding command is properly counted. [Bug 1752146]
+
+2007-07-11 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCompExpr.c: Added a "parseOnly" flag argument to
+ ParseExpr() to indicate whether the caller is Tcl_ParseExpr(), with an
+ end goal of filling a Tcl_Parse with Tcl_Tokens representing the
+ parsed expression, or TclCompileExpr() with the goal of compiling and
+ executing the expression. In the latter case, more aggressive
+ conversion of QUOTED and BRACED lexeme to literals is done. In the
+ former case, all such conversion is avoided, since Tcl_Token
+ production would revert it anyway. This enables simplifications to the
+ GenerateTokensForLiteral() routine as well.
+
+2007-07-10 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCompExpr.c: Added a field for operator precedence
+ to be stored directly in the parse tree. There's no memory cost to
+ this addition, since that memory would have been lost to alignment
+ issues anyway. Also, converted precedence definitions and lookup
+ tables to use symbolic constants instead of raw number for improved
+ readability, and continued extending/improving/correcting comments.
+ Removed some unused counter variables. Renamed some variables for
+ clarity and replaced some cryptic logic with more readable macros.
+
+2007-07-09 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCompExpr.c: Revision so that the END lexeme never
+ gets inserted into the parse tree. Later tree traversal never reaches
+ it since its location in the tree is not variable. Starting and
+ stopping with the START lexeme (node 0) is sufficient. Also finished
+ lexeme code commentary.
+
+ * generic/tclCompExpr.c: Added missing creation and return of
+ the Tcl_Parse fields that indicate error conditions. [Bug 1749987]
+
+2007-07-05 Don Porter <dgp@users.sourceforge.net>
- * generic/tclCmdMZ.c (Tcl_StringObjCmd,STR_IS_INT): Corrected
- inconsistent results of [string is integer] observed on systems
- where sizeof(long) != sizeof(int). [Bug 718878]
- * tests/string.test: Added tests for Bug 718878.
- * doc/string.n: Clarified that [string is integer] accepts
- 32-bit integers.
+ * library/init.tcl (unknown): Corrected inconsistent error message
+ in interactive [unknown] when empty command is invoked. [Bug 1743676]
-2003-04-11 Andreas Kupries <andreask@activestate.com>
+2007-07-05 Miguel Sofer <msofer@users.sf.net>
- * generic/tclIO.c (UpdateInterest): When dropping interest in
- TCL_READABLE now dropping interest in TCL_EXCEPTION too. This fixes a
- bug where Expect detects eof on a file prematurely on Solaris 2.6 and
- higher. A much more complete explanation is in the code itself (40
- lines of comments for a one-line change :)
+ * generic/tclNamesp.c (SetNsNameFromAny):
+ * generic/tclObj.c (SetCmdNameFromAny): Avoid unnecessary
+ ckfree/ckalloc when the old structs can be reused.
-2003-04-10 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+2007-07-04 Miguel Sofer <msofer@users.sf.net>
- * doc/binary.n: Fixed typo in [binary format w] desc. [Bug 718543]
+ * generic/tclNamesp.c: Fix case where a FQ cmd or ns was being cached
+ * generic/tclObj.c: in a different interp, tkcon. [Bug 1747512]
-2003-04-08 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+2007-07-03 Don Porter <dgp@users.sourceforge.net>
- * generic/tclCmdAH.c (Tcl_ErrorObjCmd): Strings are only empty if they
- have zero length, not if their first byte is zero, so fix test
- guarding Tcl_AddObjErrorInfo to take this into account. [Bug reported
- by Don Porter; no bug-id.]
+ * generic/tclCompExpr.c: Revised #define values so that there
+ is now more expansion room to define more BINARY operators.
-2003-04-07 Don Porter <dgp@users.sourceforge.net>
+2007-07-02 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclCompCmds.c (TclCompileIfCmd): Corrected string limits of
- arguments interpolated in error messages. [Bug 711371]
+ * generic/tclHash.c (CompareStringKeys): Always use the strcmp()
+ version; the operation is functionally equivalent, the speed is
+ identical (up to measurement limitations), and yet the code is
+ simpler. [FRQ 951168]
- * generic/tclCmdMZ.c (TraceExecutionProc): Added missing
- Tcl_DiscardResult() call to avoid memory leak.
+2007-07-02 Don Porter <dgp@users.sourceforge.net>
-2003-04-07 Donal K. Fellows <zzcgudf@ernie.mvc.mcc.ac.uk>
+ * generic/tcl.h: Removed TCL_PRESERVE_BINARY_COMPATIBILITY and
+ * generic/tclHash.c: any code enabled when it is set to 0. We will
+ * generic/tclStubInit.c: always want to preserve binary compat
+ of the structs that appear in the interface through the 8.* series of
+ releases, so it's pointless to drag around this never-enabled
+ alternative.
- * generic/tclObj.c (tclWideIntType, TclInitObjSubsystem):
- (SetBooleanFromAny): Make sure that tclWideIntType is defined and
- somewhat sensible everywhere. [Bug 713562]
+ * generic/tclIO.c: Removed dead code.
+ * unix/tclUnixChan.c:
-2003-04-02 Mo DeJong <mdejong@users.sourceforge.net>
+ * generic/tclCompExpr.c: Removed dead code, old implementations
+ * generic/tclEvent.c: of expr parsing and compiling, including the
+ * generic/tclInt.h: routine TclFinalizeCompilation().
- * win/configure: Regen.
- * win/configure.in: Set stub lib flag based on new LIBFLAGSUFFIX
- variable.
- * win/tcl.m4 (SC_CONFIG_CFLAGS): Set new LIBFLAGSUFFIX that works like
- LIBSUFFIX, it is used when creating library names. The previous
- implementation would generate -ltclstub85 instead of -ltclstub85s when
- configured with --disable-shared.
+2007-06-30 Donal K. Fellows <dkf@users.sf.net>
-2003-04-01 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclCmdIL.c (Tcl_LsortObjCmd): Plug a memory leak caused by a
+ missing Tcl_DecrRefCount on an error path. [Bug 1717186]
- * tests/README: Direct [source] of *.test files is no longer
- recommended. The tests/*.test files should only be evaluated under the
- control of the [runAllTests] command in tests/all.tcl.
+2007-06-30 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
-2003-03-27 Miguel Sofer <msofer@users.sf.net>
+ * generic/tclThread.c: Prevent RemeberSyncObj() from growing the sync
+ object lists by reusing already free'd slots, if possible. See
+ discussion on Bug 1726873 for more information.
- * tests/encoding.test:
- * tests/proc-old.test:
- * tests/set-old.test: Altered test numers to eliminate duplicates,
- [Bugs 710313, 710320, 710352]
+2007-06-29 Donal K. Fellows <dkf@users.sf.net>
-2003-03-27 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * doc/DictObj.3 (Tcl_DictObjDone): Improved documentation of this
+ function to make it clearer how to use it. [Bug 1710795]
- * tests/parseOld.test: Altered test numers to eliminate duplicates.
- * tests/parse.test: [Bugs 710365, 710369]
- * tests/expr-old.test:
- * tests/expr.test:
+2007-06-29 Daniel Steffen <das@users.sourceforge.net>
- * tests/utf.test: Altered test numers to eliminate duplicates.
- * tests/trace.test: [Bugs 710322, 710327, 710349, 710363]
- * tests/lsearch.test:
- * tests/list.test:
- * tests/info.test:
- * tests/incr-old.test:
- * tests/if-old.test:
- * tests/format.test:
- * tests/foreach.test:
+ * generic/tclAlloc.c: on Darwin, ensure memory allocated by
+ * generic/tclThreadAlloc.c: the custom TclpAlloc()s is aligned to
+ 16 byte boundaries (as is the case with the Darwin system malloc).
-2003-03-26 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclGetDate.y: use ckalloc/ckfree instead of malloc/free.
+ * generic/tclDate.c: bison 1.875e
- * doc/tcltest.n:
- * library/tcltest/tcltest.tcl: Added reporting during [configure
- -debug 1] operations to warn about multiple uses of the same test
- name. [FR 576693] Replaced [regexp] and [regsub] with [string map]
- where possible. Thanks to David Welton. [Bugs 667456,667558]
- * library/tcltest/pkgIndex.tcl: Bumped to tcltest 2.2.3
+ * generic/tclBasic.c (TclEvalEx): fix warnings.
- * tests/msgcat.test (msgcat-2.2.1): changed test name to avoid
- duplication. [Bug 710356]
+ * macosx/Tcl.xcodeproj/project.pbxproj: better support for renamed tcl
+ * macosx/Tcl.xcodeproj/default.pbxuser: source dir; add 10.5 SDK build
+ * macosx/Tcl-Common.xcconfig: config; remove tclMathOp.c.
- * unix/dltest/pkg?.c: Changed all Tcl_InitStubs calls to pass argument
- exact = 0, so that rebuilds are not required when Tcl bumps to a new
- version. [Bug 701926]
+ * macosx/README: document Tcl.xcodeproj changes.
-2003-03-24 Miguel Sofer <msofer@users.sf.net>
+2007-06-28 Don Porter <dgp@users.sourceforge.net>
- * generic/tclVar.c:
- * tests/var.test: fixing ObjMakeUpvar's lookup algorithm for the
- created local variable, [Bugs 631741] (Chris Darroch) and [696893]
- (David Hilker).
+ * generic/tclBasic.c: Removed dead code, including the
+ * generic/tclExecute.c: entire file tclMathOp.c.
+ * generic/tclInt.h:
+ * generic/tclMathOp.c (removed):
+ * generic/tclTestObj.c:
+ * win/tclWinFile.c:
-2003-03-22 Kevin Kenny <kennykb@acm.org>
+ * unix/Makefile.in: Updated to reflect deletion of tclMathOp.c.
+ * win/Makefile.in:
+ * win/makefile.bc:
+ * win/makefile.vc:
- * library/dde/pkgIndex.tcl:
- * library/reg/pkgIndex.tcl: Fixed a bug where [package require dde] or
- [package require registry] attempted to load the release version of
- the DLL into a debug build. [Bug 708218] Thanks to Joe Mistachkin for
- the patch.
- * win/makefile.vc: Added quoting around the script name in the 'test'
- target; Joe Mistachkin insists that he has a configuration that fails
- to launch tcltest without it, and it appears harmless otherwise.
-
-2003-03-20 Don Porter <dgp@users.sourceforge.net>
-
- * generic/tclInt.h (tclOriginalNotifier):
- * generic/tclStubInit.c (tclOriginalNotifier):
- * mac/tclMacNotify.c (Tcl_SetTimer,Tcl_WaitForEvent):
- * unix/tclUnixNotfy.c (Tcl_SetTimer,Tcl_WaitForEvent,
- (Tcl_CreateFileHandler,Tcl_DeleteFileHandler):
- * win/tclWinNotify.c (Tcl_SetTimer,Tcl_WaitForEvent): Some linkers
- apparently use a different representation for a pointer to a function
- within the same compilation unit and a pointer to a function in a
- different compilation unit. This causes checks like those in the
- original notifier procedures to fall into infinite loops. The fix is
- to store pointers to the original notifier procedures in a struct
- defined in the same compilation unit as the stubs tables, and compare
- against those values. [Bug 707174]
-
- * generic/tclInt.h: Removed definition of ParseValue struct that is no
- longer used.
-
-2003-03-19 Miguel Sofer <msofer@users.sf.net>
+2007-06-28 Pat Thoyts <patthoyts@users.sourceforge.net>
- * generic/tclCompile.c:
- * tests/compile.test: bad command count on TCL_OUT_LINE_COMPILE
- [Bug 705406] (Don Porter).
+ * generic/tclBasic.c: Silence constness warnings for TclStackFree
+ * generic/tclCompCmds.c: when building with msvc.
+ * generic/tclFCmd.c:
+ * generic/tclIOCmd.c:
+ * generic/tclTrace.c:
-2003-03-19 Don Porter <dgp@users.sourceforge.net>
+2007-06-28 Miguel Sofer <msofer@users.sf.net>
- * doc/Eval.3 (Tcl_EvalObjEx): Corrected CONST and
- * doc/ParseCmd.3 (Tcl_EvalTokensStandard): return type errors in
- documentation. [Bug 683994]
+ * generic/tclVar.c (UnsetVarStruct): fix possible segfault.
-2003-03-18 Kevin Kenny <kennykb@users.sourceforge.net>
+2007-06-27 Don Porter <dgp@users.sourceforge.net>
- * tests/registry.test: Changed the conditionals to avoid an abort if
- [testlocale] is missing, as when running the test in tclsh rather than
- tcltest. [Bug 705677]
+ * generic/tclTrace.c: Corrected broken trace reversal logic in
+ * generic/tclTest.c: TclCheckInterpTraces that led to infinite loop
+ * tests/trace.test: when multiple Tcl_CreateTrace traces were set
+ and one of them did not fire due to level restrictions. [Bug 1743931]
-2003-03-18 Daniel Steffen <das@users.sourceforge.net>
+2007-06-26 Don Porter <dgp@users.sourceforge.net>
- * tools/tcltk-man2html.tcl: added support for building 'make html'
- from inside distribution directories named with 8.x.x version numbers.
- tcltk-man2html now uses the latest tcl8.x.x resp. tk8.x.x directories
- found inside its --srcdir argument.
+ * generic/tclBasic.c (TclEvalEx): Moved some arrays from the C
+ stack to the Tcl stack.
-2003-03-18 Vince Darley <vincentdarley@users.sourceforge.net>
+2007-06-26 Miguel Sofer <msofer@users.sf.net>
- * tests/cmdAH.test: fix test suite problem if /home is a symlink
- * generic/tclIOUtil.c: fix bad error message with 'cd ""'
- * win/tclWinFile.c: allow Tcl to differentiate between reparse points
- which are symlinks and mounted drives.
+ * generic/tclVar.c (UnsetVarStruct): more streamlining.
- These changes fix [Bugs 703264, 704917, 697862] respectively.
+2007-06-25 Don Porter <dgp@users.sourceforge.net>
-2003-03-17 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclExecute.c: Safety checks to avoid crashes in the
+ TclStack* routines when called with an incompletely initialized
+ interp. [Bug 1743302]
- * doc/lsearch.n: Altered documentation of -ascii options so
- * doc/lsort.n: they don't specify that they operate on
- ASCII strings, which they never did
- anyway. [Bug 703807]
+2007-06-25 Miguel Sofer <msofer@users.sf.net>
-2003-03-14 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclVar.c (UnsetVarStruct): fixing incomplete change, more
+ streamlining.
- * generic/tclCmdAH.c (Tcl_FileObjCmd): Remove assumption that file
- times and longs are the same size. [Bug 698146]
- (Tcl_FormatObjCmd): Stop surprising type conversions from
- happening when working with integer and wide values. [Bug 699060]
+2007-06-24 Miguel Sofer <msofer@users.sf.net>
- * generic/tclCmdAH.c (Tcl_FormatObjCmd): Only add the modifier that
- indicates we've got a wide int when we're formatting in an integer
- style. Stops some libc's from going mad. [Bug 702622]
- Also tidied whitespace.
+ * generic/tclVar.c (TclDeleteCompiledLocalVars): removed inlining that
+ ended up not really optimising (limited benchmarks). Now calling
+ UnsetVarStruct (streamlined old code is #ifdef'ed out, in case better
+ benchmarks do show a difference).
-2003-03-13 Kevin Kenny <kennykb@users.sourceforge.net>
+ * generic/tclVar.c (UnsetVarStruct): fixed a leak introduced in last
+ commit.
- * win/makefile.vc: Backed the version to 8.4 on the 8.4 branch. (I
- just loathe sticky tags).
+2007-06-23 Miguel Sofer <msofer@users.sf.net>
-2003-03-12 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclVar.c (UnsetVarStruct, TclDeleteVars): made the logic
+ slightly clearer, eliminated some duplicated code.
- * generic/tcl.h: Removed TCL_PREFIX_IDENT and TCL_DEBUG_IDENT
- * win/tclWinPipe.c: from tcl.h -- they are not part of Tcl's
- public interface. Put them in win/tclWinPipe.c where they are used.
+ *** POTENTIAL INCOMPATIBILITY *** (tclInt.h and Var struct users)
+ The core never builds VAR_LINK variable to have traces. Such a
+ "monster", should one exist, will now have its unset traces called
+ *before* it is unlinked.
- * generic/tclCmdMZ.c (Tcl_SubstObj): Corrected and added test for
- * tests/subst.test (subst-2.4): Tcl_SubstObj's incorrect
- halting of substitution at the first \x00 byte. [Bug 685106]
+2007-06-23 Daniel Steffen <das@users.sourceforge.net>
- * generic/tclInterp.c (Tcl_InterpObjCmd): Corrected and added
- * tests/interp.test (interp-2.13): test for option
- parsing beyond objc for [interp create --]. Thanks to Marco Maggi.
- [Bug 702383]
+ * macosx/tclMacOSXNotify.c (AtForkChild): don't call CoreFoundation
+ APIs after fork() on systems where that would lead to an abort().
-2003-03-11 Kevin Kenny <kennykb@users.sourceforge.net>
+2007-06-22 Don Porter <dgp@users.sourceforge.net>
- * win/makefile.vc: Added two missing uses of $(DBGX) so that
- tclpip8x.dll loads without panicking on Win9x.
+ * generic/tclExecute.c: Revised TclStackRealloc() signature to better
+ * generic/tclInt.h: parallel (and fall back on) Tcl_Realloc.
-2003-03-08 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclNamesp.c (TclResetShadowesCmdRefs): Replaced
+ ckrealloc based allocations with TclStackRealloc allocations.
- * doc/tcltest.n: Added missing "-body" to example. Thanks to
- Helmut Giese. [Bug 700011]
+ * generic/tclCmdIL.c: More conversions to use TclStackAlloc.
+ * generic/tclScan.c:
-2003-03-06 Don Porter <dgp@users.sourceforge.net>
+2007-06-21 Don Porter <dgp@users.sourceforge.net>
- * generic/TclUtf.c (Tcl_UniCharNcasecmp): Corrected failure to
- * tests/utf.test (utf-25.*): properly compare Unicode strings of
- different case in a case insensitive manner. [Bug 699042]
+ * generic/tclBasic.c: Move most instances of the Tcl_Parse struct
+ * generic/tclCompExpr.c: off the C stack and onto the Tcl stack. This
+ * generic/tclCompile.c: is a rather large struct (> 3kB).
+ * generic/tclParse.c:
-2003-03-03 Jeff Hobbs <jeffh@ActiveState.com>
+2007-06-21 Miguel Sofer <msofer@users.sf.net>
- *** 8.4.2 TAGGED FOR RELEASE ***
+ * generic/tclBasic.c (TEOvI): Made sure that leave traces
+ * generic/tclExecute.c (INST_INVOKE): that were created during
+ * tests/trace.test (trace-36.2): execution of an originally
+ untraced command do not fire [Bug 1740962], partial fix.
-2003-03-03 Daniel Steffen <das@users.sourceforge.net>
+2007-06-21 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- Mac OS Classic specific fixes:
- * generic/tclIOUtil.c (TclNewFSPathObj): on TCL_PLATFORM_MAC,
- skip potential directory separator at the beginning of addStrRep.
- * mac/tclMacChan.c (OpenFileChannel, CommonWatch): followup
- fixes to cut and splice implementation for file channels.
- * mac/tclMacFile.c (TclpUtime): pass native path to utime().
- * mac/tclMacFile.c (TclpObjLink): correctly implemented creation
- of alias files via new static proc CreateAliasFile().
- * mac/tclMacPort.h: define S_ISLNK macro to fix stat'ing of links.
- * mac/tclMacUtil.c (FSpLocationFromPathAlias): fix to enable
- stat'ing of broken links.
+ * generic/tcl.h, generic/tclCompile.h, generic/tclCompile.c: Remove
+ references in comments to obsolete {expand} notation. [Bug 1740859]
-2003-03-03 Kevin Kenny <kennykb@users.sourceforge.net>
+2007-06-20 Miguel Sofer <msofer@users.sf.net>
- * win/Makefile.vc: corrected bug introduced by 'g' for debug builds.
+ * generic/tclVar.c: streamline namespace vars deletion: only compute
+ the variable's full name if the variable is traced.
-2003-03-03 Don Porter <dgp@users.sourceforge.net>
+2007-06-20 Don Porter <dgp@users.sourceforge.net>
- * library/dde/pkgIndex.tcl: dde bumped to version 1.2.1 for
- * win/tclWinDde.c: bundled release with Tcl 8.4.2
+ * generic/tclInt.decls: Revised the interfaces of the routines
+ * generic/tclExecute.c: TclStackAlloc and TclStackFree to make them
+ easier for callers to use (or more precisely, harder to misuse).
+ TclStackFree now takes a (void *) argument which is the pointer
+ intended to be freed. TclStackFree will panic if that's not actually
+ the memory the call will free. TSA/TSF also now tolerate receiving
+ (interp == NULL), in which case they simply fall back to be calls to
+ Tcl_Alloc/Tcl_Free.
- * library/reg/pkgIndex.tcl: registry bumped to version 1.1.1 for
- * win/tclWinReg.c: bundled release with Tcl 8.4.2
+ * generic/tclIntDecls.h: make genstubs
- * library/opt/pkgIndex.tcl: updated package index to version 0.4.4
+ * generic/tclBasic.c: Updated callers
+ * generic/tclCmdAH.c:
+ * generic/tclCmdIL.c:
+ * generic/tclCompCmds.c:
+ * generic/tclCompExpr.c:
+ * generic/tclCompile.c:
+ * generic/tclFCmd.c:
+ * generic/tclFileName.c:
+ * generic/tclIOCmd.c:
+ * generic/tclIndexObj.c:
+ * generic/tclInterp.c:
+ * generic/tclNamesp.c:
+ * generic/tclProc.c:
+ * generic/tclTrace.c:
+ * unix/tclUnixPipe.c:
-2003-02-28 Jeff Hobbs <jeffh@ActiveState.com>
+2007-06-20 Jeff Hobbs <jeffh@ActiveState.com>
- * win/configure:
- * win/configure.in: check for 'g' for debug build type, not 'd'.
- * win/rules.vc (DBGX): correct to use 'g' for nmake win makefile
- to match the cygwin makefile for debug builds. [Bug 635107]
+ * tools/tcltk-man2html.tcl: revamp of html doc output to use CSS,
+ standardized headers, subheaders, dictionary sorting of names.
-2003-02-28 Vince Darley <vincentdarley@users.sourceforge.net>
+2007-06-18 Jeff Hobbs <jeffh@ActiveState.com>
- * doc/file.n: subcommand is 'file volumes' not 'file volume'
+ * tools/tcltk-man2html.tcl: clean up copyright merging and output.
+ clean up coding constructs.
-2003-02-27 Jeff Hobbs <jeffh@ActiveState.com>
+2007-06-18 Miguel Sofer <msofer@users.sf.net>
- * generic/tclIOUtil.c (MakeFsPathFromRelative): removed dead code
- check of typePtr (darley).
+ * generic/tclCmdIL.c (InfoFrameCmd):
+ * generic/tclCmdMZ.c (Tcl_SwitchObjCmd):
+ * generic/tclCompile.c (TclInitCompileEnv):
+ * generic/tclProc.c (Tcl_ProcObjCmd, SetLambdaFromAny): Moved the
+ CmdFrame off the C stack and onto the Tcl stack.
- * tests/winTime.test: added note about PCI hardware dependency
- issues with high performance clock.
+ * generic/tclExecute.c (TEBC): Moved the CmdFrame off the C stack and
+ onto the Tcl stack, between the catch and the execution stacks
-2003-02-27 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+2007-06-18 Don Porter <dgp@users.sourceforge.net>
- * tests/lsearch.test (lsearch-10.7):
- * generic/tclCmdIL.c (Tcl_LsearchObjCmd): Stopped -start option from
- causing an option when used with an empty list. [Bug 694232]
+ * generic/tclBasic.c (TclEvalEx,TclEvalObjEx): Moved the CmdFrame off
+ the C stack and onto the Tcl stack.
-2003-02-26 Chengye Mao <chengye.geo@yahoo.com>
+2007-06-17 Donal K. Fellows <dkf@users.sf.net>
- * win/tclWinInit.c: fixed a bug in TclpSetVariables by initializing
- dwUserNameLen with the sizeof(szUserName) before calling GetUserName.
- Don't know if this bug has been recorded: it caused crash in starting
- Tcl or wish in Windows.
+ * generic/tclProc.c (TclObjInterpProcCore): Minor fixes to make
+ * generic/tclExecute.c (TclExecuteByteCode): compilation debugging
+ builds work again. [Bug 1738542]
-2003-02-26 Jeff Hobbs <jeffh@ActiveState.com>
+2007-06-16 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclCmdMZ.c (TraceCommandProc): Fix mem leak when
- deleting a command that had trace on it. [Bug 693564] (sofer)
+ * generic/tclProc.c (TclObjInterpProcCore): Use switch instead of a
+ chain of if's for a modest performance gain and a little more clarity.
-2003-02-25 Don Porter <dgp@users.sourceforge.net>
+2007-06-15 Miguel Sofer <msofer@users.sf.net>
- * doc/pkgMkIndex.n: Modified [pkg_mkIndex] to use -nocase matching
- * library/package.tcl: of -load patterns, to better accomodate
- common user errors due to confusion between [package names] names
- and [info loaded] names.
+ * generic/tclCompCmds.c: Simplified [variable] compiler and executor.
+ * generic/tclExecute.c: Missed updates to "there is always a valid
+ frame".
-2003-02-25 Andreas Kupries <andreask@activestate.com>
+ * generic/tclCompile.c: reverted TclEvalObjvInternal and INST_INVOKE
+ * generic/tclExecute.c: to essentially what they were previous to the
+ * generic/tclBasic.c: commit of 2007-04-03 [Patch 1693802] and the
+ subsequent optimisations, as they break the new trace tests described
+ below.
- * tests/pid.test: See below [Bug 678412].
- * tests/io.test: Made more robust against spaces in paths [Bug 678400]
+ * generic/trace.test: added tests 36 to 38 for dynamic trace creation
+ and addition. These tests expose a change in dynamics due to a recent
+ round of optimisations. The "correct" behaviour is not described in
+ docs nor TIP 62.
-2003-02-25 Miguel Sofer <msofer@users.sf.net>
+2007-06-14 Miguel Sofer <msofer@users.sf.net>
- * tests/execute.test: cleaning up testobj's at the end, to avoid leak
- warning by valgrind.
+ * generic/tclInt.decls: Modif to the internals of TclObjInterpProc
+ * generic/tclInt.h: to reduce stack consumption and improve task
+ * generic/tclIntDecls.h: separation. Changes the interface of
+ * generic/tclProc.c: TclObjInterpProcCore (patching TclOO
+ simultaneously).
-2003-02-22 Zoran Vasiljevic <zoran@archiwrae.com>
+ * generic/tclProc.c (TclObjInterpProcCore): simplified obj management
+ in wrongNumArgs calls.
- * generic/tclEvent.c (Tcl_FinalizeThread): Fix [Bug 571002]
+2007-06-14 Don Porter <dgp@users.sourceforge.net>
-2003-02-21 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclCompile.c: SetByteCodeFromAny() can no longer return any
+ * generic/tclExecute.c: code other than TCL_OK, so remove code that
+ * generic/tclProc.c: formerly handled exceptional codes.
- * tests/binary.test (binary-44.[34]):
- * generic/tclBinary.c (ScanNumber): Fixed problem with unwanted
- sign-bit propagation when scanning wide ints. [Bug 690774]
+2007-06-13 Miguel Sofer <msofer@users.sf.net>
-2003-02-21 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tclExecute.c (TclCompEvalObj): missed update to "there is
+ always a valid frame".
- * mac/tclMacChan.c (TclpCutFileChannel, TclpSpliceFileChannel):
- Implemented missing cut and splice procs for file channels.
+ * generic/tclProc.c (TclObjInterpProcCore): call TEBC directly instead
+ of going through TclCompEvalObj - no need to check the compilation's
+ freshness, this has already been done. This improves speed and should
+ also provide some relief to [Bug 1066755].
-2003-02-21 Don Porter <dgp@users.sourceforge.net>
+2007-06-12 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * library/package.tcl (tclPkgUnknown): Minor performance tweaks to
- reduce the number of [file] invocations. Meant to improve startup
- times, at least a little bit. [Patch 687906]
+ * generic/tclBasic.c (Tcl_CreateInterp): Turn the [info] command into
+ * generic/tclCmdIL.c (TclInitInfoCmd): an ensemble, making it easier
+ for third-party code to plug into.
-2003-02-20 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tclIndexObj.c (Tcl_WrongNumArgs):
+ * generic/tclNamesp.c, generic/tclInt.h (tclEnsembleCmdType): Make
+ Tcl_WrongNumArgs do replacement correctly with ensembles and other
+ sorts of complex replacement strategies.
- * unix/tcl.m4:
- * unix/tclUnixPipe.c: (macosx) use vfork() instead of fork() to create
- new processes, as recommended by Apple (vfork can be up to 100 times
- faster thank fork on macosx).
- * unix/configure: regen.
+2007-06-11 Miguel Sofer <msofer@users.sf.net>
-2003-02-20 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclExecute.c: comments added to explain iPtr->numLevels
+ management.
- * generic/tclEncoding.c (LoadTableEncoding):
- * library/encoding/cp932.enc: Correct jis round-trip encoding
- * library/encoding/euc-jp.enc: by adding 'R' type to .enc files.
- * library/encoding/iso2022-jp.enc: [Patch 689341] (koboyasi, taguchi)
- * library/encoding/jis0208.enc:
- * library/encoding/shiftjis.enc:
- * tests/encoding.test:
+ * generic/tclNamesp.c: tweaks to Tcl_GetCommandFromObj and
+ * generic/tclObj.c: TclGetNamespaceFromObj; modified the usage of
+ structs ResolvedCmdName and ResolvedNsname so that the field refNsPtr
+ is NULL for fully qualified names.
- * unix/tclUnixChan.c (Tcl_MakeTcpClientChannel): add
- MakeTcpClientChannelMode that takes actual mode flags to avoid
- hang on OS X (may be OS X bug, but patch works x-plat).
- [Bug 689835] (steffen)
+2007-06-10 Miguel Sofer <msofer@users.sf.net>
-2003-02-20 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclBasic.c: Further TEOvI split, creating a new
+ * generic/tclCompile.h: TclEvalObjvKnownCommand() function to handle
+ * generic/tclExecute.c: commands that are already known and are not
+ traced. INST_INVOKE now calls into this function instead of inlining
+ parts of TEOvI. Same perf, better isolation.
- * doc/regsub.n: Typo fix [Bug 688943]
+ ***POTENTIAL INCOMPAT*** There is a subtle issue with the timing of
+ execution traces that is changed here - first change appeared in my
+ commit of 2007-04-03 [Patch 1693802], which caused some divergence
+ between compiled and non-compiled code.
+ ***THIS CHANGE IS UNDER REVIEW***
-2003-02-19 Jeff Hobbs <jeffh@ActiveState.com>
+2007-06-10 Jeff Hobbs <jeffh@ActiveState.com>
- * unix/tclUnixThrd.c (TclpReaddir):
- * unix/tclUnixPort.h: update to Bug 689100 patch to ensure that
- there is a defined value of MAXNAMLEN (aka NAME_MAX in POSIX) and
- that we have some buffer allocated.
+ * README: updated links. [Bug 1715081]
-2003-02-19 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tclExecute.c (TclExecuteByteCode): restore support for
+ INST_CALL_BUILTIN_FUNC1 and INST_CALL_FUNC1 bytecodes to support 8.4-
+ precompiled sources (math functions). [Bug 1720895]
- * generic/tclStringObj.c: restored Tcl_SetObjLength() side-effect of
- always invalidating unicode rep (if the obj has a string rep). Added
- hasUnicode flag to String struct, allows decoupling of validity of
- unicode rep from buffer size allocated to it (improves memory
- allocation efficiency). [Bugs 686782, 671138, 635200]
+2007-06-10 Miguel Sofer <msofer@users.sf.net>
- * macosx/Tcl.pbproj/project.pbxproj:
- * macosx/Makefile: reworked embedded build to no longer require
- relinking but to use install_name_tool instead to change the
- install_names for embedded frameworks. [Bug 644510]
+ * generic/tclInt.h:
+ * generic/tclNamesp.c:
+ * generic/tclObj.c:
+ * generic/tclvar.c: new macros TclGetCurrentNamespace() and
+ TclGetGlobalNamespace(); Tcl_GetCommandFromObj and
+ TclGetNamespaceFromObj rewritten to make the logic clearer; slightly
+ faster too.
+
+2007-06-09 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c (INST_INVOKE): isolated two vars to the small
+ block where they are actually used.
+
+ * generic/tclObj.c (Tcl_GetCommandFromObj): rewritten to make the
+ logic clearer; slightly faster too.
+
+ * generic/tclBasic.c: Split TEOv in two, by separating a processor
+ for non-TCL_OK returns. Also split TEOvI in a full version that
+ handles non-existing and traced commands, and a separate shorter
+ version for the regular case.
+
+ * generic/tclBasic.c: Moved the generation of command strings for
+ * generic/tclTrace.c: traces: previously in Tcl_EvalObjv(), now in
+ TclCheck[Interp|Execution]Traces(). Also insured that the strings are
+ properly NUL terminated at the correct length. [Bug 1693986]
+
+ ***POTENTIAL INCOMPATIBILITY in internal API***
+ The functions TclCheckInterpTraces() and TclCheckExecutionTraces() (in
+ internal stubs) used to be noops if the command string was NULL, this
+ is not true anymore: if the command string is NULL, they generate an
+ appropriate string from (objc,objv) and use it to call the traces. The
+ caller might as well not call them with a NULL string if he was
+ expecting a noop.
+
+ * generic/tclBasic.c: Extend usage of TclLimitReady() and
+ * generic/tclExecute.c: (new) TclLimitExceeded() macros.
+ * generic/tclInt.h:
+ * generic/tclInterp.c:
- * macosx/Tcl.pbproj/project.pbxproj: preserve mod dates when running
- 'make install' to build framework (avoids bogus rebuilds of dependent
- frameworks because tcl headers appear changed).
+ * generic/tclInt.h: New TclCleanupCommandMacro for core usage.
+ * generic/tclBasic.c:
+ * generic/tclExecute.c:
+ * generic/tclObj.c:
- * tests/ioCmd.test (iocmd-1.8): fix failure when system encoding is
- utf-8: use iso8859-1 encoding explicitly.
+2007-06-09 Daniel Steffen <das@users.sourceforge.net>
-2003-02-18 Miguel Sofer <msofer@users.sf.net>
+ * macosx/Tcl.xcodeproj/project.pbxproj: add new Tclsh-Info.plist.in.
- * generic/tclCompile.c (TclCompileExprWords): remove unused variable
- "range" [Bug 664743]
- * generic/tclExecute.c (ExprSrandFunc): remove unused variable
- "result" [Bug 664743]
- * generic/tclStringObj.c (UpdateStringOfString): remove unused
- variable "length" [Bug 664751]
- * tests/execute.test (execute-7.30): fix for [Bug 664775]
+2007-06-08 Donal K. Fellows <dkf@users.sf.net>
-2003-02-18 Andreas Kupries <andreask@activestate.com>
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd): Changed [string first] and
+ * doc/string.n: [string last] so that they have clearer descriptions
+ for those people who know the adage about needles and haystacks. This
+ follows suggestions on comp.lang.tcl...
- * unix/tcl.m4: [Bug 651811] Added definition of _XOPEN_SOURCE and
- linkage of 'xnet' library to HP 11 branch. This kills a lot of
- socket-related failures in the testsuite when Tcl was compiled in 64
- bit mode (both PA-RISC 2.0W, and IA 64).
+2007-06-06 Miguel Sofer <msofer@users.sf.net>
- * unix/configure: Regenerated.
+ * generic/tclParse.c: fix for uninit read. [Bug 1732414]
-2003-02-18 Jeff Hobbs <jeffh@ActiveState.com>
+2007-06-06 Daniel Steffen <das@users.sourceforge.net>
- * generic/tclIO.c (HaveVersion): correctly decl static
+ * macosx/Tcl.xcodeproj/project.pbxproj: add settings for Fix&Continue.
- * unix/tclUnixThrd.c (TclpReaddir): reduce size of name string in
- tsd to NAME_MAX instead of PATH_MAX. [Bug 689100] (waters)
+ * unix/configure.in (Darwin): add plist for tclsh; link the
+ * unix/Makefile.in (Darwin): Tcl and tclsh plists into
+ * macosx/Tclsh-Info.plist.in (new): their binaries in all cases.
+ * macosx/Tcl-Common.xcconfig:
-2003-02-18 Mo DeJong <mdejong@users.sourceforge.net>
+ * unix/tcl.m4 (Darwin): fix CF checks in fat 32&64bit builds.
+ * unix/configure: autoconf-2.59
- * unix/configure: Regen.
- * unix/tcl.m4 (SC_ENABLE_THREADS): Make sure -lpthread gets passed on
- the link line when checking for the pthread_attr_setstacksize symbol.
+2007-06-05 Don Porter <dgp@users.sourceforge.net>
-2003-02-18 Vince Darley <vincentdarley@users.sourceforge.net>
+ * generic/tclBasic.c: Added interp flag value ERR_LEGACY_COPY to
+ * generic/tclInt.h: control the timing with which the global
+ * generic/tclNamesp.c: variables ::errorCode and ::errorInfo get
+ * generic/tclProc.c: updated after an error. This keeps more
+ * generic/tclResult.c: precise compatibility with Tcl 8.4.
+ * tests/result.test (result-6.2): [Bug 1649062]
- * generic/tclTest.c: cleanup of new 'simplefs' test code, and better
- documentation.
+2007-06-05 Miguel Sofer <msofer@users.sf.net>
-2003-02-17 Miguel Sofer <msofer@users.sf.net>
+ * generic/tclInt.h:
+ * generic/tclExecute.c: Tcl-stack reform, [Patch 1701202]
- * generic/tclBasic.c (TclRenameCommand): fixing error in previous
- commit.
+2007-06-03 Daniel Steffen <das@users.sourceforge.net>
-2003-02-17 Jeff Hobbs <jeffh@ActiveState.com>
+ * unix/Makefile.in: add datarootdir to silence autoconf-2.6x warning.
- * generic/tclExecute.c (TclExecuteByteCode INST_STR_MATCH):
- * generic/tclCmdMZ.c (Tcl_StringObjCmd STR_MATCH):
- * generic/tclUtf.c (TclUniCharMatch):
- * generic/tclInt.decls: add private TclUniCharMatch function that
- * generic/tclIntDecls.h: does string match on counted unicode
- * generic/tclStubInit.c: strings. Tcl_UniCharCaseMatch has the
- * tests/string.test: failing that it can't handle strings or
- * tests/stringComp.test: patterns with embedded NULLs. Added
- tests that actually try strings/pats with NULLs. TclUniCharMatch
- should be TIPed and made public in the next minor version rev.
+2007-05-30 Don Porter <dgp@users.sourceforge.net>
-2003-02-17 Miguel Sofer <msofer@users.sf.net>
+ * generic/tclBasic.c: Removed code that dealt with
+ * generic/tclCompile.c: TCL_TOKEN_EXPAND_WORD tokens representing
+ * generic/tclCompile.h: expanded literal words. These sections were
+ mostly in place to enable [info frame] to discover line information in
+ expanded literals. Since the parser now generates a token for each
+ post-expansion word referring to the right location in the original
+ script string, [info frame] gets all the data it needs.
- * generic/tclBasic.c (TclRenameCommand): 'oldFullName' object was not
- being freed on all function exits, causing a memory leak. [Bug 684756]
+ * generic/tclInt.h: Revised the parser so that it never produces
+ * generic/tclParse.c: TCL_TOKEN_EXPAND_WORD tokens when parsing an
+ * tests/parse.test: expanded literal word; that is, something like
+ {*}{x y z}. Instead, generate the series of TCL_TOKEN_SIMPLE_WORD
+ tokens to represent the words that expansion of the literal string
+ produces. [RFE 1725186]
-2003-02-17 Mo DeJong <mdejong@users.sourceforge.net>
+2007-05-29 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/tclIO.c (Tcl_GetsObj): Minor change so that eol is only
- assigned at the top of the TCL_TRANSLATE_AUTO case block. The other
- cases assign eol so this does not change any functionality.
+ * unix/tclUnixThrd.c (Tcl_JoinThread): fix for 64-bit handling of
+ pthread_join exit return code storage. [Bug 1712723]
-2003-02-17 Kevin Kenny <kennykb@users.sourceforge.net>
+2007-05-22 Don Porter <dgp@users.sourceforge.net>
- * tests/notify.test: Removed Windows line terminators. [Bug 687913].
+ [core-stabilizer-branch]
-2003-02-15 Miguel Sofer <msofer@users.sf.net>
+ * unix/configure: autoconf-2.59 (FC6 fork)
+ * win/configure:
- * generic/tclBasic.c (Tcl_EvalEx):
- * generic/tclCompExpr.c (CompileSubExpr):
- * generic/tclCompile.c (TclCompileScript):
- * generic/tclParse.c (Tcl_ParseCommand, ParseTokens):
- * generic/tclParseExpr.c (ParsePrimaryExpr):
- * tests/basic.test (47.1):
- * tests/main.test (3.4):
- * tests/misc.test (1.2):
- * tests/parse.test (6.18):
- * tests/parseExpr.test (15.35):
- * tests/subst.test (8.6): Don Porter's fix for bad parsing of
- nested scripts [Bug 681841].
-
-2003-02-15 Kevin Kenny <kennykb@users.sourceforge.net>
-
- * tests/notify.test (new-file):
- * generic/tclTest.c (TclTest_Init, EventtestObjCmd, EventtestProc,
- (EventTestDeleteProc):
- * generic/tclNotify.c (Tcl_DeleteEvents): Fixed Tcl_DeleteEvents
- not to get a pointer smash when deleting the last event in the
- queue. Added test code in 'tcltest' and a new file of test cases
- 'notify.test' to exercise this functionality; several of the new
- test cases fail for the original code and pass for the corrected
- code. [Bug 673714]
-
- * unix/tclUnixTest.c (TestfilehandlerCmd): Corrected a couple
- of typos in error messages. [Bug 596027]
-
-2003-02-14 Jeff Hobbs <jeffh@ActiveState.com>
-
- * README: Bumped to version 8.4.2.
+ * README: Bump version number to 8.5b1
* generic/tcl.h:
+ * library/init.tcl:
* tools/tcl.wse.in:
- * unix/configure:
* unix/configure.in:
- * unix/tcl.m4:
* unix/tcl.spec:
- * win/README.binary:
- * win/configure:
* win/configure.in:
- * macosx/Tcl.pbproj/project.pbxproj:
-
- * generic/tclStringObj.c (Tcl_GetCharLength): perf tweak
-
- * unix/tcl.m4: correct HP-UX ia64 --enable-64bit build flags
-
-2003-02-14 Kevin Kenny <kennykb@users.sourceforge.net>
-
- * win/tclWinTime.c: Added code to test and compensate for forward
- leaps of the performance counter. See the MSDN Knowledge Base article
- Q274323 for the hardware problem that makes this necessary on certain
- machines.
- * tests/winTime.test: Revised winTime-2.1 - it had a tolerance of
- thousands of seconds, rather than milliseconds. (What's six orders of
- magnitude among friends?
-
- Both the above changes are triggered by a problem reported at
- http://aspn.activestate.com/ASPN/Mail/Message/ActiveTcl/1536811
- although the developers find it difficult to believe that it accounts
- for the observed behavior and suspect a fault in the RTC chip.
-
-2003-02-13 Kevin Kenny <kennykb@users.sourceforge.net>
-
- * win/tclWinInit.c: Added conversion from the system encoding to
- tcl_platform(user), so that it works with non-ASCII7 user names. [Bug
- 685926]
-
- * doc/tclsh.1: Added language to describe the handling of the
- end-of-file character \u001a embedded in a script file. [Bug 685485]
-
-2003-02-11 Vince Darley <vincentdarley@users.sourceforge.net>
-
- * tests/fileName.test:
- * unix/tclUnixFile.c: fix for [Bug 685445] when using 'glob -l' on
- broken symbolic links. Added two new tests for this bug.
-
-2003-02-11 Kevin Kenny <kennykb@users.sourceforge.net>
-
- * tests/http.test: Corrected a problem where http-4.14 would fail when
- run in an environment with a proxy server. Replaced references to
- scriptics.com by tcl.tk.
-
-2003-02-11 Jeff Hobbs <jeffh@ActiveState.com>
-
- * tests/lsearch.test:
- * generic/tclCmdIL.c (Tcl_LsearchObjCmd): protect against the case
- that lsearch -regepx list and pattern objects are equal.
-
- * tests/stringObj.test:
- * generic/tclStringObj.c (Tcl_GetCharLength): correct ascii char
- opt of 2002-11-11 to not stop early on \x00. [Bug 684699]
-
- * tests.parse.test: remove excess EOF whitespace
-
- * generic/tclParse.c (CommandComplete): more paranoid check to
- break on (p >= end) instead of just (p == end).
-
-2003-02-11 Miguel Sofer <msofer@users.sf.net>
- * generic/tclParse.c (CommandComplete):
- * tests/parse.test: fix for [Bug 684744], by Don Porter.
-
-2003-02-11 Jeff Hobbs <jeffh@ActiveState.com>
-
- * generic/tclIOUtil.c (Tcl_FSJoinPath, Tcl_FSGetNormalizedPath):
- (UpdateStringOfFsPath): revert the cwdLen == 0 check and instead
- follow a different code path in Tcl_FSJoinPath.
- (Tcl_FSConvertToPathType, Tcl_FSGetNormalizedPath):
- (Tcl_FSGetFileSystemForPath): Update string rep of path objects
- before freeing the internal object. (darley)
-
- * tests/fileSystem.test: added test 8.3
- * generic/tclIOUtil.c (Tcl_FSGetNormalizedPath):
- (UpdateStringOfFsPath): handle the cwdLen == 0 case
-
- * unix/tclUnixFile.c (TclpMatchInDirectory): simplify the hidden
- file match check.
-
-2003-02-10 Mo DeJong <mdejong@users.sourceforge.net>
+2007-05-18 Don Porter <dgp@users.sourceforge.net>
+ * unix/configure: autoconf-2.59 (FC6 fork)
* win/configure:
- * win/configure.in: Generate error when attempting to build under
- Cygwin. The Cygwin port of Tcl/Tk does not build and people are filing
- bug reports under the mistaken impression that someone is actually
- maintaining the Cygwin port. A post to comp.lang.tcl asking someone to
- volunteer as an area maintainer has generated no results. Closing
- [Bugs 680840, 630199, 634772] and marking as "Won't fix".
-
-2003-02-10 Donal K. Fellows <fellowsd@cs.man.ac.uk>
-
- * doc/append.n: Return value was not documented. [Bug 683188]
-
-2003-02-10 Vince Darley <vincentdarley@users.sourceforge.net>
-
- * doc/FileSystem.3:
- * generic/tclIOUtil.c:
- * generic/tclInt.h:
- * tests/fileSystem.test:
- * unix/tclUnixFCmd.c:
- * unix/tclUnixFile.c:
- * win/tclWinFile.c: further filesystem optimization, applying
- [Patch 682500]. In particular, these code examples are faster now:
- foreach f $flist { if {[file exists $f]} {file stat $f arr;...}}
- foreach f [glob -dir $dir *] { # action and/or recursion on $f }
- cd $dir
- foreach f [glob *] { # action and/or recursion on $f }
- cd ..
-
- * generic/tclTest.c: Fix for [Bug 683181] where test suite left files
- in 'tmp'.
-
-2003-02-08 Jeff Hobbs <jeffh@ActiveState.com>
-
- * library/safe.tcl: code cleanup of eval and string comp use.
-
-2003-02-07 Vince Darley <vincentdarley@users.sourceforge.net>
-
- * win/tclWinFCmd.c: cleanup long lines
- * win/tclWinFile.c: sped up pure 'glob' by a factor of 2.5 ('foreach f
- [glob *] { file exists $f }' is still slow)
- * tests/fileSystem.text:
- * tests/fileName.test: added new tests to ensure correct behaviour in
- optimized filesystem code.
-2003-02-07 Vince Darley <vincentdarley@users.sourceforge.net>
-
- * generic/tclTest.c:
- * tests/fileSystem.text: fixed test 7.2 to avoid a possible crash, and
- not change the pwd.
-
- * tests/http.text: added comment to test 4.15, that it may fail if you
- use a proxy server.
-
-2003-02-06 Mo DeJong <mdejong@users.sourceforge.net>
-
- * generic/tclCompCmds.c (TclCompileIncrCmd):
- * tests/incr.test: Don't include the text "(increment expression)" in
- the errorInfo generated by the compiled version of the incr command
- since it does not match the message generated by the non-compiled
- version of incr. It is also not possible to match this error output
- under Jacl, which does not support a compiler.
-
-2003-02-06 Mo DeJong <mdejong@users.sourceforge.net>
+ * README: Bump version number to 8.5a7
+ * generic/tcl.h:
+ * library/init.tcl:
+ * tools/tcl.wse.in:
+ * unix/configure.in:
+ * unix/tcl.spec:
+ * win/configure.in:
- * generic/tclExecute.c (TclExecuteByteCode): When an error is
- encountered reading the increment value during a compiled call to
- incr, add a "(reading increment)" error string to the errorInfo
- variable. This makes the errorInfo variable set by the compiled incr
- command match the value set by the non-compiled version.
- * tests/incr-old.test: Change errorInfo result for the compiled incr
- command case to match the modified implementation.
- * tests/incr.test: Add tests to make sure the compiled and
- non-compiled errorInfo messages are the same.
+ * generic/tclParse.c: Disable and remove the ALLOW_EXPAND sections
+ * tests/info.test: that continued to support the deprecated
+ * tests/mathop.test: {expand} syntax. Updated the few remaining
+ users of that syntax in the test suite.
-2003-02-06 Don Porter <dgp@users.sourceforge.net>
+2007-05-17 Donal K. Fellows <dkf@users.sf.net>
- * library/tcltest/tcltest.tcl: Filename arguments to [outputChannel]
- and [errorChannel] (also -outfile and -errfile) were [open]ed but
- never [closed]. Also, [cleanupTests] could remove output or error
- files. [Bug 676978].
- * library/tcltest/pkgIndex.tcl: Bumped to version 2.2.2.
+ * generic/tclExecute.c (TclLimitReady): Created a macro version of
+ Tcl_LimitReady just for TEBC, to reduce the amount of times that the
+ bytecode engine calls out to external functions on the critical path.
+ * generic/tclInterp.c (Tcl_LimitReady): Added note to remind anyone
+ doing maintenance that there is a macro version to update.
-2003-02-05 Mo DeJong <mdejong@users.sourceforge.net>
+2007-05-17 Daniel Steffen <das@users.sourceforge.net>
- * tests/interp.test:
- * tests/set-old.test: Run test cases that depend on hash order through
- lsort so that the tests also pass under Jacl. Does not change test
- results under Tcl.
+ * generic/tcl.decls: workaround 'make checkstubs' failures from
+ tclStubLib.c MODULE_SCOPE revert. [Bug 1716117]
-2003-02-04 Vince Darley <vincentdarley@users.sourceforge.net>
+2007-05-16 Joe English <jenglish@users.sourceforge.net>
- * generic/tclIOUtil.c:
- * generic/tclEvent.c:
- * generic/tclInt.h:
- * mac/tclMacFCmd.c:
- * unix/tclUnixFCmd.c:
- * win/tclWin32Dll.c:
- * win/tclWinFCmd.c:
- * win/tclWinInit.c:
- * win/tclWinInt.h:
- * tests/fileSystem.test: fix to finalization/unloading/encoding issues
- to make filesystem much less dependent on encodings for its cleanup,
- and therefore allow it to be finalized later in the exit process. This
- fixes fileSystem.test-7.1. Also fixed one more bug in setting of
- modification dates of files which have undergone cross-platform
- copies. [Patch 676271]
-
- * tests/basic.test:
- * tests/exec.test:
- * tests/fileName.test:
- * tests/io.test: fixed some test failures when tests are run from a
- directory containing spaces.
+ * generic/tclStubLib.c: Change Tcl_InitStubs(), tclStubsPtr, and the
+ auxilliary stubs table pointers back to public visibility.
- * tests/fileSystem.test:
- * generic/tclTest.c: added regression test for the modification
- date setting of cross-platform file copies.
+ These symbols need to be exported so that stub-enabled extensions may
+ be statically linked into an extended tclsh or Big Wish with a
+ dynamically-linked libtcl. [Bug 1716117]
-2003-02-03 Kevin Kenny <kennykb@users.sourceforge.net>
+2007-05-15 Don Porter <dgp@users.sourceforge.net>
- * generic/tclBasic.c: Changed [trace add command] so that 'rename'
- callbacks get fully qualified names of the command. [Bug 651271].
- ***POTENTIAL INCOMPATIBILITY***
- * tests/trace.test: Modified the test cases for [trace add command] to
- expect fully qualified names on the 'rename' callbacks. Added a case
- for renaming a proc within a namespace.
- * doc/trace.n: Added language about use of fully qualified names in
- trace callbacks.
-
-2003-02-01 Kevin Kenny <kennykb@users.sourceforge.net>
-
- * generic/tclCompCmds.c: Removed an unused variable that caused
- compiler warnings on SGI. [Bug 664379]
+ * win/configure: autoconf-2.59 (FC6 fork)
- * generic/tclLoad.c: Changed the code so that if Tcl_StaticPackage is
- called to report the same package as being loaded in two interps, it
- shows up in [info loaded {}] in both of them (previously, it didn't
- appear in the static package list in the second.
-
- * tests/load.test Added regression test for the above bug. [Bug
- 670042]
-
- * generic/tclClock.c: Fixed a bug that incorrectly allowed [clock
- clicks {}] and [clock clicks -] to be accepted as if they were [clock
- clicks -milliseconds].
-
- * tests/clock.test: Added regression tests for the above bug. [Bug
- 675356]
-
- * tests/unixNotfy.test: Added cleanup of working files [Bug 675609]
-
- * doc/Tcl.n: Added headings to the eleven paragraphs, to improve
- formatting in the tools that attempt to extract tables of contents
- from the manual pages. [Bug 627455]
-
- * generic/tclClock.c: Expanded mutex protection around the setting of
- env(TZ) and the thread-unsafe call to tzset(). [Bug 656660]
-
-2003-01-31 Don Porter <dgp@users.sourceforge.net>
-
- * tests/tcltest.test: Cleaned up management of file/directory
- creation/deletion to improve "-debug 1" output. [Bug 675614] The
- utility [slave] command failed to properly [list]-quote a constructed
- [open] command, causing failure when the pathname contained
- whitespace. [Bug 678415]
-
- * tests/main.test: Stopped main.test from deleting existing file.
- Test suite should not delete files that already exist. [Bug 675660]
-
-2003-01-28 Don Porter <dgp@users.sourceforge.net>
-
- * tests/main.test: Constrain tests that do not work on Windows. [Bug
- 674387]
-
-2003-01-28 Vince Darley <vincentdarley@users.sourceforge.net>
-
- * generic/tclIOUtil.c: fix to setting modification date in
- TclCrossFilesystemCopy. Also added 'panic' in
- Tcl_FSGetFileSystemForPath under illegal calling circumstances which
- lead to hard-to-track-down bugs.
-
- * generic/tclTest.c: added test suite code to allow exercising a
- vfs-crash-on-exit bug in Tcl's finalization caused by the encodings
- being cleaned up before unloading occurs.
- * tests/fileSystem.test: added new 'knownBug' test 7.1 to demonstrate
- the crash on exit.
-
-2003-01-28 Mo DeJong <mdejong@users.sourceforge.net>
-
- * generic/tcl.h: Add TCL_PREFIX_IDENT and TCL_DEBUG_IDENT, used only
- by TclpCreateProcess.
- * unix/Makefile.in: Define TCL_DBGX.
- * win/Makefile.in: Define TCL_DBGX.
- * win/tclWinPipe.c (TclpCreateProcess): Check that the Tcl pipe dll
- actually exists in the Tcl bin directory and panic if it is not
- found. Incorporate TCL_DBGX into the Tcl pipe dll name. This fixes a
- really mysterious error that would show up when exec'ing a 16 bit
- application under Win95 or Win98 when Tcl was compiled with symbols.
- The error seemed to indicate that the executable could not be found,
- but it was actually the Tcl pipe dll that could not be found.
-
-2003-01-26 Mo DeJong <mdejong@users.sourceforge.net>
-
- * win/README: Update msys+mingw URL to release 6. This version bundles
- gcc 3.
-
-2003-01-26 Mo DeJong <mdejong@users.sourceforge.net>
-
- * win/configure: Regen.
- * win/configure.in: Add test that checks to see if the compiler can
- cast to a union type.
- * win/tclWinTime.c: Squelch compiler warning about union initializer
- by casting to union type when compiling with gcc.
-
-2003-01-25 Mo DeJong <mdejong@users.sourceforge.net>
-
- * generic/tclIO.c (Tcl_CutChannel, Tcl_SpliceChannel): Invoke
- TclpCutFileChannel and TclpSpliceFileChannel.
- * generic/tclInt.h: Declare TclpCutFileChannel and
- TclpSpliceFileChannel.
- * unix/tclUnixChan.c (FileCloseProc, TclpOpenFileChannel,
- (Tcl_MakeFileChannel, TclpCutFileChannel,
- (TclpSpliceFileChannel): Implement thread load data cut and splice for
- file channels. This avoids an invalid memory ref when compiled with
- -DDEPRECATED.
- * win/tclWinChan.c (FileCloseProc, TclpCutFileChannel,
- (TclpSpliceFileChannel): Implement thread load data cut and splice for
- file channels. This avoids an invalid memory ref that was showing up
- in the thread extension.
+ * library/reg/pkgIndex.tcl: Bump to registry 1.2.1 to account for
+ * win/configure.in: [Bug 1682211] fix.
+ * win/makefile.bc:
+ * win/tclWinReg.c:
-2003-01-25 Mo DeJong <mdejong@users.sourceforge.net>
-
- * win/tclWin32Dll.c (TclpCheckStackSpace, squelch_warnings):
- * win/tclWinChan.c (Tcl_MakeFileChannel, squelch_warnings):
- * win/tclWinFCmd.c (DoRenameFile, DoCopyFile, squelch_warnings):
- Re-implement inline ASM SEH handlers for gcc. The esp and ebp
- registers are now saved on the stack instead of in global variables so
- that the code is thread safe. Add additional checks when TCL_MEM_DEBUG
- is defined to be sure the values were recovered from the stack
- properly. Remove squelch_warnings functions and add a dummy call in
- the handler methods to squelch compiler warnings.
+2007-05-11 Pat Thoyts <patthoyts@users.sourceforge.net>
-2003-01-25 Mo DeJong <mdejong@users.sourceforge.net>
+ * generic/tclInt.h: Removed TclEvalObjEx and TclGetSrcInfoForPc from
+ tclInt.h now they are in the internal stubs table.
- * win/configure:
- * win/configure.in: Define HAVE_ALLOCA_GCC_INLINE when we detect that
- no alloca function is found in malloc.h and we are compiling with
- GCC. Remove HAVE_NO_ALLOC_DECL define.
- * win/tclWin32Dll.c (TclpCheckStackSpace): Don't define alloca as a
- cdecl function. Doing this caused a tricky runtime bug because the
- _alloca function expects the size argument to be passed in a register
- and not on the stack. To fix this problem, we use inline ASM when
- compiling with gcc to invoke _alloca with the size argument loaded
- into a register.
+2007-05-09 Don Porter <dgp@users.sourceforge.net>
-2003-01-24 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclInt.h: TclFinalizeThreadAlloc() is always defined, so
+ make sure it is also always declared (with MODULE_SCOPE).
- * win/tclWinDde.c (Dde_Init): clarified use of tsdPtr.
- (DdeServerProc): better refcount handling of returnPackagePtr.
+2007-05-09 Daniel Steffen <das@users.sourceforge.net>
- * generic/tclEvent.c (Tcl_Finalize): revert finalize change on
- 2002-12-04 to correct the issue with extensions that have TSD needing
- to finalize that before they are unloaded. This issue needs further
- clarification.
+ * generic/tclInt.h: fix warning when building threaded with -DPURIFY.
- * tests/unixFCmd.test: only do groups check on unix
+ * macosx/Tcl.xcodeproj/project.pbxproj: add 'DebugUnthreaded' &
+ * macosx/Tcl.xcodeproj/default.pbxuser: 'DebugLeaks' configs and env
+ var settings needed to run the 'leaks' tool.
-2003-01-24 Vince Darley <vincentdarley@users.sourceforge.net>
+2007-05-07 Don Porter <dgp@users.sourceforge.net>
- * generic/tclStringObj.c: proper fixes for Tcl_SetObjLength and
- Tcl_AttemptSetObjectLength dealing with string objects with both
- pure-unicode and normal internal representations. Previous fix didn't
- handle all cases correctly.
- * generic/tclIO.c: Add 'Tcl_GetString()' to ensure the object has a
- valid 'objPtr->bytes' field before manipulating it directly.
+ [Tcl Bug 1706140]
- This fixes [Bug 635200] and [Bug 671138], but may reduce performance
- of Unicode string handling in some cases. A further patch will be
- applied to address this, once the code is known to be correct.
+ * generic/tclLink.c (LinkTraceProc): Update Tcl_VarTraceProcs so
+ * generic/tclNamesp.c (Error*Read): they call Tcl_InterpDeleted()
+ * generic/tclTrace.c (Trace*Proc): for themselves, and do not
+ * generic/tclUtil.c (TclPrecTraceProc): rely on (frequently buggy)
+ setting of the TCL_INTERP_DESTROYED flag by the trace core.
-2003-01-24 Mo DeJong <mdejong@users.sourceforge.net>
+ * generic/tclVar.c: Update callers of TclCallVarTraces to not pass
+ in the TCL_INTERP_DESTROYED flag. Also apply filters so that public
+ routines only pass documented flag values down to lower level routines
- * win/configure: Regen.
- * win/configure.in: Add test to see if alloca is undefined in
- malloc.h.
- * win/tclWin32Dll.c (TclpCheckStackSpace): Rework the SEH exception
- handler logic to avoid using the stack since alloca will modify the
- stack. This was causing a nasty bug that would set the exception
- handler to 0 because it tried to pop the previous exception handler
- off the top of the stack.
+ * generic/tclTrace.c (TclCallVarTraces): The setting of the
+ TCL_INTERP_DESTROYED flag is now done entirely within the
+ TclCallVarTraces routine, the only place it can be done right.
-2003-01-23 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+2007-05-06 Donal K. Fellows <dkf@users.sf.net>
- * doc/lset.n: Fixed fault in return values from lset in documentation
- examples [Bug 658463] and tidied up a bit at the same time.
+ * generic/tclInt.h (ExtraFrameInfo): Create a new mechanism for
+ * generic/tclCmdIL.c (InfoFrameCmd): conveying what information needs
+ to be added to the results of [info frame] to replace the hack that
+ was there before.
+ * generic/tclProc.c (Tcl_ApplyObjCmd): Use the new mechanism for the
+ [apply] command, the only part of Tcl itself that needs it (so far).
-2003-01-21 Joe English <jenglish@users.sourceforge.net>
- * doc/namespace.n (namespace inscope): Clarified documentation
- [Patch 670110]
+ * generic/tclInt.decls (TclEvalObjEx, TclGetSrcInfoForPc): Expose
+ these two functions through the internal stubs table, necessary for
+ extensions that need to integrate deeply with TIP#280.
-2003-01-21 Mo DeJong <mdejong@users.sourceforge.net>
+2007-05-05 Donal K. Fellows <dkf@users.sf.net>
- * win/configure: Regen.
- * win/tcl.m4 (SC_CONFIG_CFLAGS): Set SHLIB_SUFFIX so that
- TCL_SHLIB_SUFFIX will be set to a useful value in the generated
- tclConfig.sh. Set SHLIB_LD_LIBS to "" or '${LIBS}' based on the
- --enable-shared flag. This matches the UNIX implementation.
+ * win/tclWinFile.c (TclpGetUserHome): Squelch type-pun warnings in
+ * win/tclWinInit.c (TclpSetVariables): Win-specific code not found
+ * win/tclWinReg.c (AppendSystemError): during earlier work on Unix.
-2003-01-18 Jeff Hobbs <jeffh@ActiveState.com>
+2007-05-04 Kevin B. Kenny <kennykb@acm.org>
- * generic/tclCkalloc.c: change %ud to %u as appropriate.
+ * generic/tclIO.c (TclFinalizeIOSubsystem): Added an initializer to
+ silence a spurious gcc warning about use of an uninitialized
+ variable.
+ * tests/encoding.test: Modified so that encoding tests happen in a
+ private namespace, to avoid polluting the global one. This problem was
+ discovered when running the test suite '-singleproc 1 -skip exec.test'
+ because the 'path' variable in encoding.test conflicted with the one
+ in io.test.
+ * tests/io.test: Made more of the working variables private to the
+ namespace.
+
+2007-05-02 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclTest.c (SimpleMatchInDirectory): Corrected a refcount
+ imbalance that affected the filesystem-[147]* tests in the test suite.
+ Thanks to Don Porter for the patch. [Bug 1710707]
+ * generic/tclPathObj.c (Tcl_FSJoinPath, Tcl_FSGetNormalizedPath):
+ Corrected several memory leaks that caused refcount imbalances
+ resulting in memory leaks on Windows. Thanks to Joe Mistachkin for the
+ patch.
+
+2007-05-01 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclVar.c (TclPtrSetVar): fixed leak whenever newvaluePtr had
+ refCount 0 and was used for appending (but not lappending). Thanks to
+ mistachkin and kbk. [Bug 1710710]
+
+2007-05-01 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclIO.c (DeleteChannelTable): Made changes so that
+ DeleteChannelTable tries to close all open channels, not just the
+ first. [Bug 1710285]
+ * generic/tclThread.c (TclFinalizeSynchronization): Make sure that TSD
+ blocks get freed on non-threaded builds. [Bug 1710825]
+ * tests/utf.test (utf-25.1--utf-25.4): Modified tests to clean up
+ after the 'testobj' extension to avoid spurious reports of memory
+ leaks.
+
+2007-05-01 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCmdMZ.c (STR_MAP): When [string map] has a pure dict map,
+ a missing Tcl_DictObjDone() call led to a memleak. [Bug 1710709]
-2003-01-17 Mo DeJong <mdejong@users.sourceforge.net>
+2007-04-30 Daniel Steffen <das@users.sourceforge.net>
- * win/tclWinDde.c (DdeServerProc): Deallocate the Tcl_Obj returned by
- ExecuteRemoteObject if it was not saved in a connection object.
+ * unix/Makefile.in: add 'tclsh' dependency to install targets that
+ rely on tclsh, fixes parallel 'make install' from empty build dir.
-2003-01-17 Mo DeJong <mdejong@users.sourceforge.net>
+2007-04-30 Andreas Kupries <andreask@gactivestate.com>
- * generic/tcl.h: Revert earlier change that defined TCL_WIDE_INT_TYPE
- as long long and TCL_LL_MODIFIER as L when compiling with mingw. This
- change ended up causing some test case failures when compiling with
- mingw.
- * generic/tclObj.c (UpdateStringOfWideInt): Describe the warning
- generated by mingw and why it needs to be ignored so that someone is
- not tempted to "fix" this problem again in the future.
+ * generic/tclIO.c (FixLevelCode): Corrected reference count
+ mismanagement of newlevel, newcode. Changed to allocate the Tcl_Obj's
+ as late as possible, and only when actually needed. [Bug 1705778, leak
+ K29]
-2003-01-16 Vince Darley <vincentdarley@users.sourceforge.net>
+2007-04-30 Kevin B. Kenny <kennykb@acm.org>
- * generic/tclStringObj.c: Tcl_SetObjLength fix for when the object has
- a unicode string rep. Fixes [Bug 635200]
- * tests/stringObj.test: removed 'knownBug' constraint from test 14.1
- now that this bug is fixed.
+ * generic/tclProc.c (Tcl_ProcObjCmd, SetLambdaFromAny): Corrected
+ reference count mismanagement on the name of the source file in the
+ TIP 280 code. [Bug 1705778, leak K02 among other manifestations]
- * generic/tclInt.h:
- * generic/tclBasic.c:
- * generic/tclCmdMZ.z:
- * tests/trace.test: execution and command tracing bug fixes and
- cleanup. In particular fixed [Bugs 655645, 615043, 571385]
- - fixed some subtle cleanup problems with tracing. This required
- replacing Tcl_Preserve/Tcl_Release with a more robust refCount
- approach. Solves at least one known crash caused by memory
- corruption.
- - fixed some confusion in the code between new style traces (Tcl
- 8.4) and the very limited 'Tcl_CreateTrace' which existed before.
- - made behaviour consistent with documentation (several tests even
- contradicted the documentation before).
- - fixed some minor error message details
- - added a number of new tests
-
-2003-01-16 Jeff Hobbs <jeffh@ActiveState.com>
-
- * win/tclWinSerial.c (SerialOutputProc): add casts for bytesWritten to
- allow strict compilation (no warnings).
-
- * tests/winDde.test:
- * win/tclWinDde.c (Tcl_DdeObjCmd): Prevent crash when empty service
- name is passed to 'dde eval' and goto errorNoResult in request and
- poke error cases to free up any allocated data.
-
-2003-01-16 Mo DeJong <mdejong@users.sourceforge.net>
-
- * win/tclWin32Dll.c (squelch_warnings): Squelch compiler warnings from
- SEH ASM code.
- * win/tclWinChan.c (squelch_warnings): Squelch compiler warnings from
- SEH ASM code.
- * win/tclWinDde.c: Add casts to avoid compiler warnings. Pass pointer
- to DWORD instead of int to avoid compiler warnings.
- * win/tclWinFCmd.c (squelch_warnings): Add casts and fixup decls to
- avoid compiler warnings. Squelch compiler warnings from SEH ASM code.
- * win/tclWinFile.c: Add casts and fixup decls to avoid compiler
- warnings. Remove unused variable.
- * win/tclWinNotify.c: Declare as DWORD instead of int to avoid
- compiler warning.
- * win/tclWinReg.c: Add casts to avoid compiler warning. Fix assignment
- in if expression bug.
- * win/tclWinSerial.c: Add casts to avoid compiler warnings. Remove
- unused variable.
- * win/tclWinSock.c: Add casts and fixup decls to avoid compiler
- warnings.
-
-2003-01-14 Jeff Hobbs <jeffh@ActiveState.com>
-
- * generic/tclClock.c (FormatClock): corrected typo that incorrectly
- conditionally defined savedTZEnv and savedTimeZone.
-
-2003-01-13 Mo DeJong <mdejong@users.sourceforge.net>
-
- Fix mingw build problems and compiler warnings.
-
- * generic/tcl.h: Add if defined(__MINGW32__) check to code that sets
- the TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER.
- * generic/tclClock.c (FormatClock): Don't define savedTimeZone and
- savedTZEnv if we are not going to use them.
- * generic/tclEnv.c: Add cast to avoid warning.
- * win/tclWinChan.c: Use DWORD instead of int to avoid compiler warning
- * win/tclWinThrd.c: Only define allocLock, allocLockPtr, and dataKey
- when TCL_THREADS is defined. This avoid a compiler warning about
- unused variables.
-
-2003-01-12 Mo DeJong <mdejong@users.sourceforge.net>
-
- * win/README: Update msys + mingw URL, the new release includes the
- released 1.0.8 version of msys which includes a number of bug fixes.
-
-2003-01-12 Mo DeJong <mdejong@users.sourceforge.net>
-
- * win/configure: Regen.
- * win/tcl.m4 (SC_CONFIG_CFLAGS): Pull in addition of shell32.lib to
- LIBS_GUI that was added to the Tk tcl.m4 but never made it back into
- the Tcl version.
-
-2003-01-12 Mo DeJong <mdejong@users.sourceforge.net>
-
- * generic/tcl.h: Skip Tcl's define of CHAR, SHORT, and LONG when
- HAVE_WINNT_IGNORE_VOID is defined. This avoids a bunch of compiler
- warnings when building with Cygwin or Mingw.
- * win/configure: Regen.
- * win/configure.in: Define HAVE_WINNT_IGNORE_VOID when we detect a
- winnt.h that still defines CHAR, SHORT, and LONG when VOID has already
- been defined.
- * win/tcl.m4 (SC_LOAD_TCLCONFIG): Subst the TCL_DEFS loaded from
- tclConfig.sh so that Tcl defines can make it into the Tk Makefile.
-
-2003-01-12 Mo DeJong <mdejong@users.sourceforge.net>
-
- * win/configure: Regen.
- * win/configure.in: Check for typedefs like LPFN_ACCEPT in winsock2.h
- and define HAVE_NO_LPFN_DECLS if not found.
- * win/tclWinSock.c: Define LPFN_* typedefs if HAVE_NO_LPFN_DECLS is
- defined. This fixes the build under Mingw and Cygwin, it was broken by
- the changes made on 2002-11-26.
-
-2003-01-10 Vince Darley <vincentdarley@users.sourceforge.net>
+2007-04-25 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclIOUtil.c:
- * win/tclWinInt.h:
- * win/tclWinInit.c: fix to new WinTcl crash on exit with vfs,
- introduced on 2002-12-06. Encodings must be cleaned up after the
- filesystem.
+ *** 8.5a6 TAGGED FOR RELEASE ***
- * win/makefile.vc: fix to minor VC++ 5.2 syntax problem
+ * generic/tclProc.c (TclObjInterpProcCore): Only allocate objects for
+ error message generation when associated with argument names that are
+ really used. [Bug 1705778, leak K15]
-2003-01-09 Don Porter <dgp@users.sourceforge.net>
+2007-04-25 Kevin B. Kenny <kennykb@acm.org>
- * generic/tclCompCmds.c (TclCompilerReturnCmd): Corrected off-by-one
- problem with recent commit. [Bug 633204]
+ * generic/tclIOUtil.c (Tcl_FSChdir): Changed the memory management so
+ that the path returned from Tcl_FSGetNativePath is not duplicated
+ before being stored as the current directory, to avoid a memory leak.
+ [Bug 1705778, leak K01 among other manifestations]
-2003-01-09 Vince Darley <vincentdarley@users.sourceforge.net>
+2007-04-25 Don Porter <dgp@users.sourceforge.net>
- * generic/tclFileName.c: remove unused variable 'macSpecialCase' [Bug
- 664749]
+ * generic/tclCompExpr.c (ParseExpr): Revised to be sure that an
+ error return doesn't prevent all literals getting placed on the
+ litList to be returned to the caller for freeing. Corrects some
+ memleaks. [Bug 1705778, leak K23]
- * generic/tclIOUtil.c:
- * generic/tclInt.h:
- * unix/tclUnixFile.c:
- * mac/tclMacFile.c:
- * win/tclWinFile.c:
- * win/tclWinInt.h:
- * win/tclWin32Dll.c:
- * tests/cmdAH.test: fix to non-ascii chars in paths when setting mtime
- and atime through 'file (a|m)time $path $time'. [Bug 634151]
+2007-04-25 Daniel Steffen <das@users.sourceforge.net>
-2003-01-08 Don Porter <dgp@users.sourceforge.net>
+ * unix/Makefile.in (dist): add macosx/*.xcconfig files to src dist;
+ copy license.terms to dist macosx dir; fix autoheader bits.
- * generic/tclExecute.c (TclExprFloatError): Use the IS_NAN macro for
- greater clarity of code.
+2007-04-24 Miguel Sofer <msofer@users.sf.net>
-2003-01-07 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclListObj.c: reverting [Patch 738900] (committed on
+ 2007-04-20). Causes some Tk test breakage of unknown importance, but
+ the impact of the patch itself is likely to be so small that it does
+ not warrant investigation at this time.
- * generic/tclCompCmds.c (TclCompileReturnCmd):
- * tests/compile.test: Corrects failure of bytecompiled [catch
- {return}] to have result TCL_RETURN (not TCL_OK) [Bug 633204]. This
- patch is a workaround for 8.4.X. A new opcode INST_RETURN is a better
- long term solution for 8.5 and later.
+2007-04-24 Donal K. Fellows <dkf@users.sf.net>
-2003-01-04 David Gravereaux <davygrvy@pobox.com>
+ * generic/tclDictObj.c (DictKeysCmd): Rewrote so that the lock on the
+ internal representation of a dict is only set when necessary. [Bug
+ 1705778, leak K04]
+ (DictFilterCmd): Added code to drop the lock in the trivial match
+ case. [Bug 1705778, leak K05]
- * win/makefile.vc:
- * win/rules.vc: Fixed INSTALLDIR macro problem that blanked itself by
- accident causing the install target to put the tree at the root of the
- drive built on. Whoops..
+2007-04-24 Kevin B. Kenny <kennykb@acm.org>
- Renamed the 'linkexten' option to be 'staticpkg'. Added 'thrdalloc' to
- allow the switching _on_ of the thread allocator. Under testing, I
- found it not to be benificial under windows for the purpose of the
- application I was using it for. It was more important for this app
- that resources for tcl threads be returned to the system rather than
- saved/moved to the global recycler. Be extra clean or extra fast for
- the default threaded build? Let's move to clean and allow it to be
- switched on for users who find it benificial for their use of threads.
+ * generic/tclBinary.c: Addressed several code paths where the error
+ return from the 'binary format' command leaked the result buffer.
+ * generic/tclListObj.c (TclLsetFlat): Fixed a bug where the new list
+ under construction was leaked in the error case. [Bug 1705778, leaks
+ K13 and K14]
-2002-12-18 David Gravereaux <davygrvy@pobox.com>
+2007-04-24 Jeff Hobbs <jeffh@ActiveState.com>
- * win/makefile.vc: some uses of xcopy swapped to the @$(CPY) macro.
- Reported by Joe Mistachkin <joe@mistachkin.com>.
+ * unix/Makefile.in (dist): add platform library package to src dist
-2002-12-17 Jeff Hobbs <jeffh@ActiveState.com>
+2007-04-24 Don Porter <dgp@users.sourceforge.net>
- * generic/tclNotify.c (TclFinalizeNotifier, Tcl_SetServiceMode):
- (Tcl_ThreadAlert): Check that the stub functions are non-NULL before
- calling them. They could be set to NULL by Tcl_SetNotifier.
+ * generic/tclCompExpr.c (ParseExpr): Memory leak in error case; the
+ literal Tcl_Obj was not getting freed. [Bug 1705778, leak #1 (new)]
-2002-12-16 David Gravereaux <davygrvy@pobox.com>
+ * generic/tclNamesp.c (Tcl_DeleteNamespace): Corrected flaw in the
+ flag marking scheme to be sure that global namespaces are freed when
+ their interp is deleted. [Bug 1705778]
- * generic/tclPipe.c (TclCleanupChildren):
- * tests/winPipe.test:
- * win/tclWinPipe.c (Tcl_WaitPid):
- * win/tclWinTest.c: Gave Tcl_WaitPid the ability to return a Win32
- exception code translated into a posix style SIG*. This allows [close]
- to report "CHILDKILLED" without the meaning getting lost in a
- truncated exit code. In TclCleanupChildren(), TclpGetPid() had to get
- moved to before Tcl_WaitPid() as the the handle is removed from the
- list taking away the ability to get the process id after the wait is
- done. This shouldn't effect the unix implimentaion unless waitpid is
- called with a pid of zero, meaning "any". I don't think it is..
+2007-04-24 Kevin B. Kenny <kennykb@acm.org>
-2002-12-13 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclExecute.c (TclExecuteByteCode): Plugged six memory leaks
+ in bignum arithmetic.
+ * generic/tclIOCmd.c (Tcl_ReadObjCmd): Plugged a leak of the buffer
+ object if the physical read returned an error and the bypass area had
+ no message.
+ * generic/tclIORChan.c (TclChanCreateObjCmd): Plugged a leak of the
+ return value from the "initialize" method of a channel handler.
+ (All of the above under [Bug 1705778])
- * unix/configure.in: Updated configure of CVS snapshots to reflect
- * win/configure.in: the 8.4.1.1 patchlevel.
+2007-04-23 Daniel Steffen <das@users.sourceforge.net>
- * unix/configure: autoconf
- * win/configure autoconf
+ * generic/tclCkalloc.c: fix warnings from gcc build configured with
+ * generic/tclCompile.c: --enable-64bit --enable-symbols=all.
+ * generic/tclExecute.c:
-2002-12-11 Don Porter <dgp@users.sourceforge.net>
+ * unix/tclUnixFCmd.c: add workaround for crashing bug in fts_open()
+ * unix/tclUnixInit.c: without FTS_NOSTAT on 64bit Darwin 8 or earlier.
- * generic/tclProc.c (ProcessProcResultCode): Fix failure to propagate
- negative return codes up the call stack. [Bug 647307]
- * tests/proc.test (proc-6.1): Test for Bug 647307
+ * unix/tclLoadDyld.c (TclpLoadMemory): fix (void*) arithmetic.
- * generic/tclParseExpr.c (TclParseInteger): Return 1 for the
- string "0x" (recognize leading "0" as an integer). [Bug 648441].
- * tests/parseExpr.test (parseExpr-19.1): Test for Bug 648441.
+ * macosx/Tcl-Common.xcconfig: enable more warnings.
-2002-12-09 Jeff Hobbs <jeffh@ActiveState.com>
+ * macosx/Tcl.xcodeproj/project.pbxproj: add 'DebugMemCompile' build
+ configuration that calls configure with --enable-symbols=all; override
+ configure check for __attribute__((__visibility__("hidden"))) in Debug
+ configuration to restore availability of ZeroLink.
- * win/tclWinThrd.c (TclpMasterUnlock):
- * generic/tclThread.c (TclFinalizeThreadData): TclpMasterUnlock must
- exist and be called unconditional of TCL_THREADS. [Bug 651139]
+ * macosx/tclMacOSXNotify.c: fix warnings.
-2002-12-08 David Gravereaux <davygrvy@pobox.com>
+ * macosx/tclMacOSXFCmd.c: const fixes.
- * win/tclWinSock.c (SocketThreadExitHandler, InitSockets): Check that
- the tsdPtr is valid before dereferencing as we call it from the exit
- handler, too [Bug 650353]. Another WSAStartup() loaded version
- comparison byte swap issue fixed. Although 0x0101 byte swapped is
- still 0x0101, properly claiming which is major/minor is more correct.
+ * macosx/Tcl-Common.xcconfig: fix whitespace.
+ * macosx/Tcl-Debug.xcconfig:
+ * macosx/Tcl-Release.xcconfig:
+ * macosx/README:
-2002-12-06 Jeff Hobbs <jeffh@ActiveState.com>
+ * macosx/GNUmakefile: fix/add copyright and license refs.
+ * macosx/tclMacOSXBundle.c:
+ * macosx/Tcl-Info.plist.in:
+ * macosx/Tcl.xcode/project.pbxproj:
+ * macosx/Tcl.xcodeproj/project.pbxproj:
- * generic/tclStubInit.c: regen
- * generic/tclIntPlatDecls.h: regen
- * generic/tclInt.decls: added TclWinResetInterface
+ * unix/configure.in: install license.terms into Tcl.framework.
+ * unix/configure: autoconf-2.59
- * win/tclWin32Dll.c (TclWinResetInterfaces):
- * win/tclWinInit.c (TclpSetInitialEncodings, WinEncodingsCleanup):
- add exit handler that resets the encoding information to a state where
- we can reuse Tcl. Following these changes, it is possible to reuse Tcl
- (following Tcl_FindExecutable or Tcl_CreateInterp) following a
- Tcl_Finalize.
+2007-04-23 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclVar.c (UnsetVarStruct): Make sure the
+ TCL_INTERP_DESTROYED flags gets passed to unset trace routines so they
+ can respond appropriately. [Bug 1705778, leak #9]
+
+2007-04-23 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompile.c (TclFreeCompileEnv): Tip 280's new field
+ extCmdMapPtr was not being freed. [Bug 1705778, leak #1]
+
+2007-04-23 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclCompCmds.c (TclCompileUpvarCmd): Plugged a memory leak in
+ 'upvar' when compiling (a) upvar outside a proc, (b) upvar with a
+ syntax error, or (c) upvar where the frame index is not known at
+ compile time.
+ * generic/tclCompExpr.c (ParseExpr): Plugged a memory leak when
+ parsing expressions that contain syntax errors.
+ * generic/tclEnv.c (ReplaceString): Clear memory correctly when
+ growing the cache to avoid reads of uninitialised data.
+ * generic/tclIORChan.c (TclChanCreateObjCmd, FreeReflectedChannel):
+ Plugged two memory leaks.
+ * generic/tclStrToD.c (AccumulateDecimalDigit): Fixed a mistake where
+ we'd run beyond the end of the 'pow10_wide' array if a number begins
+ with a string of more than 'maxpow10_wide' zeroes.
+ * generic/tclTest.c (Testregexpobjcmd): Removed an invalid access
+ beyond the end of 'objv' in 'testregexp -about'.
+ All of these issues reported under [Bug 1705778] - detected with the
+ existing test suite, no new regression tests required.
+
+2007-04-22 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclVar.c (TclDeleteNamespaceVars): fixed access to freed
+ memory detected by valgrind: Tcl_GetCurrentNamespace was being
+ called after freeing root CallFrame (on interp deletion).
+
+2007-04-20 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclListObj.c (SetListFromAny): avoid discarding internal
+ reps of objects converted to singleton lists. [Patch 738900]
+
+2007-04-20 Kevin B. Kenny <kennykb@acm.org>
+
+ * doc/clock.n: Corrected a silly error (transposed 'uppercase' and
+ 'lowercase' in clock.n. [Bug 1656002]
+ Clarified that [clock scan] does not recognize a locale's alternative
+ calendar.
+ Deleted an entirely superfluous (and also incorrect) remark about the
+ effect of Daylight Saving Time on relative times in [clock scan]. [Bug
+ 1582951]
+ * library/clock.tcl: Corrected an error in skipping over the %Ey field
+ on input.
+ * library/msgs/ja.msg:
+ * tools/loadICU.tcl: Corrected several localisation faults in the
+ Japanese locale (most notably, incorrect dates for the Emperors'
+ eras). [Bug 1637471]. Many thanks to SourceForge user 'nyademo' for
+ pointing this out and developing a fix.
+ * generic/tclPathObj.c: Corrected a 'const'ness fault that caused
+ bitter complaints from MSVC.
+ * tests/clock.test (clock-40.1, clock-58.1, clock-59.1): Corrected a
+ test case that depended on ":localtime" being able to handle dates
+ prior to the Posix epoch. [Bug 1618445] Added a test case for the
+ dates of the Japanese emperors. [Bug 1637471] Added a regression test
+ for military time zone input conversion. [Bug 1586828]
+ * generic/tclGetDate.y (MilitaryTable): Fixed an ancient bug where the
+ military NZA time zones had the signs reversed. [Bug 1586828]
+ * generic/tclDate.c: Regenerated.
+ * doc/Notifier.3: Documented Tcl_SetNotifier and Tcl_ServiceModeHook.
+ Quite against my better judgment. [Bug 414933]
+ * generic/tclBasic.c, generic/tclCkalloc.c, generic/tclClock.c:
+ * generic/tclCmdIL.c, generic/tclCmdMZ.c, generic/tclFCmd.c:
+ * generic/tclFileName.c, generic/tclInterp.c, generic/tclIO.c:
+ * generic/tclIOUtil.c, generic/tclNamesp.c, generic/tclObj.c:
+ * generic/tclPathObj.c, generic/tclPipe.c, generic/tclPkg.c:
+ * generic/tclResult.c, generic/tclTest.c, generic/tclTestObj.c:
+ * generic/tclVar.c, unix/tclUnixChan.c, unix/tclUnixTest.c:
+ * win/tclWinLoad.c, win/tclWinSerial.c: Replaced commas in varargs
+ with string concatenation where possible. [Patch 1515234]
+ * library/tzdata/America/Tegucigalpa:
+ * library/tzdata/Asia/Damascus: Olson's tzdata 2007e.
+
+2007-04-19 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * generic/regcomp.c, generic/regc_cvec.c, generic/regc_lex.c,
+ * generic/regc_locale.c: Improve the const-correctness of the RE
+ compiler.
- * generic/tclIOUtil.c (TclFinalizeFilesystem): reset statics to their
- original values on finalize to allow reuse of the library.
+2007-04-18 Miguel Sofer <msofer@users.sf.net>
-2002-12-04 David Gravereaux <davygrvy@pobox.com>
+ * generic/tclExecute.c (INST_LSHIFT): fixed a mistake introduced in
+ version 1.266 ('=' became '=='), which effectively turned the block
+ that handles native shifts into dead code. This explains why the
+ testsuite did not pick this mistake. Rewrote to make the intention
+ clear.
- * win/tclWinPipe.c: reverted back to -r1.27 due to numerous test
- failures that need to be resolved first. The idea was good, but the
- details aren't.
+ * generic/tclInt.h (TclDecrRefCount): change the order of the
+ branches, use empty 'if ; else' to handle use in unbraced outer
+ if/else conditions (as already done in tcl.h)
-2002-12-04 David Gravereaux <davygrvy@pobox.com>
+ * generic/tclExecute.c: slight changes in Tcl_Obj management.
- * win/tclWinPipe.c (Tcl_WaitPid): When a process exits with an
- exception, pass this notice on to the caller with a SIG* code rather
- than truncating the exit code and missing the meaning. This allows
- TclCleanupChildren() to report "CHILDKILLED".
+2007-04-17 Kevin B. Kenny <kennykb@acm.org>
- This has a different behavior than unix in that closing the read pipe
- to a process sends the SIGPIPE signal which is returned as a SIGPIPE
- exit status. On windows, we send the process a CTRL_BREAK_EVENT and
- get back a CONTROL_C_EXIT which is documented to mean a SIGINT which
- seems wrong as a system, but is the correct exit status.
+ * library/clock.tcl: Fixed the naming of
+ ::tcl::clock::ReadZoneinfoFile because (yoicks!) it was in the global
+ namespace.
+ * doc/clock.n: Clarified the cases in which legacy time zone is
+ recognized. [Bug 1656002]
-2002-12-04 Vince Darley <vincentdarley@users.sourceforge.net>
+2007-04-17 Miguel Sofer <msofer@users.sf.net>
- * generic/tclIOUtil.c: fix to redirected 'load' in virtual filesystem
- for some Unix systems.
+ * generic/tclExecute.c: fixed checkInterp logic [Bug 1702212]
- * generic/tclEvent.c: the filesystem must be cleaned up before the
- encoding subsystem because it needs access to encodings. Fixes crash
- on exit observed in embedded applications.
+2007-04-16 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * generic/tclTestObj.c: patch omitted from previous change of
- 2002-11-13
+ * various (including generic/tclTest.c): Complete the purge of K&R
+ function definitions from manually-written code.
-2002-12-03 Jeff Hobbs <jeffh@ActiveState.com>
+2007-04-15 Kevin B. Kenny <kennykb@acm.org>
- * generic/tclStubLib.c (Tcl_InitStubs): prevent the cached check of
- tclStubsPtr to allow for repeated load/unload of the Tcl dll by
- hosting apps. [Bug 615304]
+ * generic/tclCompCmds.c: added a cast to silence a compiler error on
+ VC2005.
+ * library/clock.tcl: Restored unique-prefix matching of keywords on
+ the [clock] command. [Bug 1690041]
+ * tests/clock.test: Added rudimentary test cases for unique-prefix
+ matching of keywords.
-2002-12-03 David Gravereaux <davygrvy@pobox.com>
+2007-04-14 Miguel Sofer <msofer@users.sf.net>
- * win/tclAppInit.c (sigHandler): Protect from trying to close a NULL
- handle.
+ * generic/tclExecute.c: removed some code at INST_EXPAND_SKTOP that
+ duplicates functionality already present at checkForCatch.
- * win/tclWinPipe.c (PipeClose2Proc, TclpCreateProcess): Send a real
- Win32 signal (CTRL_C_EVENT) when the read channel is brought down to
- alert the child to close on its side. Start the process with
- CREATE_NEW_PROCESS_GROUP to allow the ability to send these signals.
- The following test case now brings down the child without the use of
- an external [kill] command.
+2007-04-12 Miguel Sofer <msofer@users.sf.net>
- % set p [open "|[info name]" w+]
- file8d5380
- % pid $p
- 2876
- % close $p <- now doesn't block in Tcl_WaitPid()
- %
+ * generic/tclExecute.c: new macros OBJ_AT_TOS, OBJ_UNDER_TOS,
+ OBJ_AT_DEPTH(n) and CURR_DEPTH that remove all direct references to
+ tosPtr from TEBC (after initialisation and the code at the label
+ cleanupV_pushObjResultPtr).
- * win/tclWinPipe.c (PipeClose2Proc): Changed CTRL_C_EVENT to
- CTRL_BREAK_EVENT as it can't be ignored by the child and proved to
- work on [open "|netstat 1" w+] where CTRL_C_EVENT didn't.
+2007-04-11 Miguel Sofer <msofer@users.sf.net>
-2002-11-27 David Gravereaux <davygrvy@pobox.com>
+ * generic/tclCompCmds.c: moved all exceptDepth management to the
+ macros - the decreasing half was managed by hand.
- * win/tclWinPort.h: Don't turn off winsock prototypes! TclX didn't
- like it. Even though the core doesn't use the prototypes, do offer
- them.
+2007-04-10 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * win/tclWinSock.c: Removed shutdown() from the function table as it
- wasn't referenced anywhere and cleaned-up some casting that that
- wasn't needed.
+ * generic/tclInt.h (TclNewLiteralStringObj): New macro to make
+ allocating literal string objects (i.e. objects whose value is a
+ constant string) easier and more efficient, by allowing the omission
+ of the length argument. Based on [Patch 1529526] (afredd)
+ * generic/*.c: Make use of this (in many files).
- * win/tclWinSock.c: WSAStartup() loaded version comparison error which
- resulted in 2.0 looking less than 1.1.
+2007-04-08 Miguel Sofer <msofer@users.sf.net>
- * win/tclWinChan.c (Tcl_MakeFileChannel): return of DuplicateHandle()
- incorrectly used [Bug 618852].
+ * generic/tclCompile (tclInstructionTable): Fixed bugs in description
+ of dict instructions.
-2002-11-26 Jeff Hobbs <jeffh@ActiveState.com>
+2007-04-07 Miguel Sofer <msofer@users.sf.net>
- * generic/tclEncoding.c (TclFinalizeEncodingSubsystem): properly
- cleanup all encodings by using Tcl_FirstHashEntry in the while loop.
+ * generic/tclCompile (tclInstructionTable): Fixed bug in description
+ of INST_START_COMMAND.
- * unix/Makefile.in (valgrind): add simple valgrind target
+ * generic/tclExecute.c (TEBC): Small code reduction.
- * tests/exec.test: unset path var to allow singleproc testing
+2007-04-06 Miguel Sofer <msofer@users.sf.net>
- * generic/tclInterp.c (AliasCreate): preserve/release interps to
- prevent possible FMR error in bad alias cases.
+ * generic/tclExecute.c (TEBC):
+ * generic/tclNamespace.c (NsEnsembleImplementationCmd):
+ * generic/tclProc.c (InitCompiledLocals, ObjInterpProcEx)
+ (TclObjInterpProcCore, ProcCompileProc): Code reordering to reduce
+ branching and improve branch prediction (assume that forward branches
+ are typically not taken).
-2002-11-26 David Gravereaux <davygrvy@pobox.com>
+2007-04-03 Miguel Sofer <msofer@users.sf.net>
- * win/tclWinPort.h:
- * win/tclWinSock.c: This patch does two things:
+ * generic/tclExecute.c: INST_INVOKE optimisation. [Patch 1693802]
- 1) Cleans-up the winsock typedefs by using the typedefs provided by
- winsock2.h. This has no effect on how winsock is initialized; just
- makes the source code easier to read. [Patch 561305, 561301]
+2007-04-03 Don Porter <dgp@users.sourceforge.net>
- 2) Revamps how the socket message handler thread is brought up and
- down to allow for cleaner exits without the use of TerminateThread().
- TerminateThread is evil. No attempt has been made to resolve [Bug
- 593810] which may need a new channel driver version for adding a
- registering function within the transfered thread to init the handler
- thread. IOW, initialization of the TSD structure is getting bypassed
- through the thread extension's [thread::transfer] command.
+ * generic/tclNamesp.c: Revised ErrorCodeRead and ErrorInfoRead trace
+ routines so they guarantee the ::errorCode and ::errorInfo variable
+ always appear to exist. [Bug 1693252]
-2002-11-26 David Gravereaux <davygrvy@pobox.com>
+2007-04-03 Miguel Sofer <msofer@users.sf.net>
- * win/tclWinConsole.c:
- * win/tclWinPipe.c:
- * win/tclWinSerial.c:
- * win/tclWinSock.c:
- * win/tclWinThrd.c:
- * win/tclWinTime.c: General cleanup of all worker threads used by the
- channel drivers. Eliminates the normal case where the worker thread is
- terminated ('cept the winsock one). Instead, use kernel events to
- signal a clean exit. Only when the worker thread is blocked on an I/O
- call is the thread terminated. Essentially, this makes all other
- channel worker threads behave like the PipeReaderThread() function for
- it's cleaner exit behavior. This appears to fix [Bug 597924] but needs
- 3rd party confirmation to close the issue.
+ * generic/tclInt.decls: Moved TclGetNamespaceFromObj() to the
+ * generic/tclInt.h: internal stubs table; regen.
+ * generic/tclIntDecls.h:
+ * generic/tclStubInit.c:
-2002-11-26 Mo DeJong <mdejong@users.sourceforge.net>
+2007-04-02 Miguel Sofer <msofer@users.sf.net>
- * win/README: Update msys build env URL. This release #4 build both
- tcl and tk without problems.
+ * generic/tclBasic.c: Added bytecode compilers for the variable
+ * generic/tclCompCmds.c: linking commands: 'global', 'variable',
+ * generic/tclCompile.h: 'upvar', 'namespace upvar' [Patch 1688593]
+ * generic/tclExecute.c:
+ * generic/tclInt.h:
+ * generic/tclVar.c:
-2002-11-22 Jeff Hobbs <jeffh@ActiveState.com>
+2007-04-02 Don Porter <dgp@users.sourceforge.net>
- * library/init.tcl: code cleanup to reduce use of
- * library/opt/optparse.tcl: string compare
+ * generic/tclBasic.c: Replace arrays on the C stack and ckalloc
+ * generic/tclExecute.c: calls with TclStackAlloc calls to use memory
+ * generic/tclFCmd.c: on Tcl's evaluation stack.
+ * generic/tclFileName.c:
+ * generic/tclIOCmd.c:
+ * generic/tclIndexObj.c:
+ * generic/tclInterp.c:
+ * generic/tclNamesp.c:
+ * generic/tclTrace.c:
+ * unix/tclUnixPipe.c:
- * tests/interp.test: interp-14.4
- * generic/tclInterp.c (TclPreventAliasLoop): prevent seg fault when
- creating an alias command over the interp name. [Bug 641195]
+2007-04-01 Donal K. Fellows <dkf@users.sf.net>
-2002-11-18 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclCompile.c (TclCompileScript, TclPrintInstruction):
+ * generic/tclExecute.c (TclExecuteByteCode): Changed the definition of
+ INST_START_CMD so that it knows how many commands start at the current
+ location. This makes the interpreter command counter correct without
+ requiring a large number of instructions to be issued. (See my change
+ from 2007-01-19 for what triggered this.)
- * generic/tclUtil.c (SetEndOffsetFromAny): handle integer offset
- after the "end-" prefix.
+2007-03-30 Don Porter <dgp@users.sourceforge.net>
- * generic/get.test:
- * generic/string.test:
- * generic/tclObj.c (SetIntFromAny, SetWideIntFromAny):
- * generic/tclGet.c (TclGetLong, Tcl_GetInt): simplify sign handling
- before calling strtoul(l). [Bug 634856]
+ * generic/tclCompile.c:
+ * generic/tclCompExpr.c:
+ * generic/tclCompCmds.c: Replace arrays on the C stack and
+ ckalloc calls with TclStackAlloc calls to use memory on Tcl's
+ evaluation stack.
-2002-11-18 David Gravereaux <davygrvy@pobox.com>
+ * generic/tclCmdMZ.c: Revised [string to* $s $first $last]
+ implementation to reduce number of allocs/copies.
- * win/tclWinThrd.c (Tcl_CreateThread/TclpThreadExit): Fixed improper
- compiler macros that missed the VC++ compiler. This resulted in VC++
- builds using CreateThread()/ExitThread() in place of the proper
- _beginthreadex()/_endthreadex(). This was a large error and am
- surprised I missed seeing it earlier.
+ * tests/string.test: More [string reverse] tests.
-2002-11-13 Jeff Hobbs <jeffh@ActiveState.com>
+2007-03-30 Miguel Sofer <msofer@users.sf.net>
- * generic/regexpComp.test: added tests 22.*
- * generic/tclCompCmds.c (TclCompileRegexpCmd): add left and right
- anchoring (^ and $) recognition and check starting or ending .* to
- extend the number of REs that can be compiled to string match or
- string equal.
+ * generic/tclExecute.c: optimise the lookup of elements of indexed
+ arrays.
-2002-11-13 Vince Darley <vincentdarley@users.sourceforge.net>
+2007-03-29 Miguel Sofer <msofer@users.sf.net>
- * generic/tclCmdMZ.c:
- * tests/trace.test: applied patch from Hemang Levana to fix [Bug
- 615043] in execution traces with 'return -code error'.
+ * generic/tclProc.c (Tcl_ApplyObjCmd):
+ * tests/apply.test (9.3): Fixed Tcl_Obj leak on error return; an
+ unneeded ref to lambdaPtr was being set and not released on an error
+ return path.
- * generic/tclTestObj.c:
- * tests/stringObj.test: added 'knownBug' test for [Bug 635200]
- * generic/tclStringObj.c: corrected typos in comments
+2007-03-28 Don Porter <dgp@users.sourceforge.net>
- * generic/tclFileName.c:
- * tests/fileName.test: applied patch for bug reported against tclvfs
- concerning handling of Windows serial ports like 'com1', 'lpt3' by the
- virtual filesystem code.
+ * generic/tclCmdMZ.c (STR_REVERSE): Implement the actual [string
+ reverse] command in terms of the new TclStringObjReverse() routine.
- * doc/RegExp.3: clarification of the 'extendMatch' return values.
+ * generic/tclInt.h (TclStringObjReverse): New internal routine
+ * generic/tclStringObj.c (TclStringObjReverse): that implements the
+ [string reverse] operation, making use of knowledge/surgery of the
+ String intrep to minimize the number of allocs and copies needed to do
+ the job.
-2002-11-11 Jeff Hobbs <jeffh@ActiveState.com>
+2007-03-27 Don Porter <dgp@users.sourceforge.net>
- * generic/tclUtil.c (Tcl_Backslash): use TclUtfToUniChar.
- (Tcl_StringCaseMatch): use TclUtfToUniChar and add further
- optimizations for the one-byte/char case.
+ * generic/tclCmdMZ.c (STR_MAP): Replace ckalloc calls with
+ TclStackAlloc calls.
- * generic/tclUtf.c: make use of TclUtfToUniChar macro throughout the
- functions, and add extra optimization to Tcl_NumUtfChars for
- one-byte/char case.
+2007-03-24 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
- * generic/tclVar.c (DisposeTraceResult, CallVarTraces): add proper
- static declarations.
+ * win/tclWinThrd.c: Thread exit handler marks the current thread as
+ un-initialized. This allows exit handlers that are registered later to
+ re-initialize this subsystem in case they need to use some sync
+ primitives (cond variables) from this file again.
- * generic/tclStringObj.c (Tcl_GetCharLength): optimize for the ascii
- char case.
- (Tcl_GetUniChar): remove unnecessary use of Tcl_UtfToUniChar.
- (FillUnicodeRep): Use TclUtfToUniChar.
+2007-03-23 Miguel Sofer <msofer@users.sf.net>
- * generic/tclHash.c (HashStringKey): move string++ lower to save an
- instruction.
+ * generic/tclBasic.c (DeleteInterpProc): pop the root frame pointer
+ before deleting the global namespace [Bug 1658572]
- * generic/tclExecute.c (TclExecuteByteCode): improve INST_STR_CMP to
- use memcmp in the one-byte/char case, also use direct index for
- INST_STR_INDEX in that case.
+2007-03-23 Kevin B. Kenny <kennykb@acm.org>
- * generic/tclEncoding.c (UtfToUtfProc, UtfToUnicodeProc):
- (TableFromUtfProc, EscapeFromUtfProc): Use TclUtfToUniChar.
- (UnicodeToUtfProc, TableToUtfProc): add 1-byte char optimizations
- for Tcl_UniCharToUtf call. These improve encoded channel conversion
- speeds by up to 20%.
+ * win/Makefile.in: Added code to keep a Cygwin path name from leaking
+ into LIBRARY_DIR when doing 'make test' or 'make runtest'.
- * tests/split.test: added 1-char string split tests
- * generic/tclCmdMZ.c (Tcl_SplitObjCmd): Use TclUtfToUniChar. Also
- added a special case for single-ascii-char splits.
- (Tcl_StringObjCmd): Use TclUtfToUniChar. For STR_RANGE, support
- getting ranges of ByteArrays (reverts change from 2000-05-26).
- (TraceExecutionProc) add proper static declaration.
+2007-03-22 Don Porter <dgp@users.sourceforge.net>
- * generic/tclInt.h: add macro version of Tcl_UtfToUniChar
- (TclUtfToUniChar) that does the one-byte utf-char check without
- calling Tcl_UtfToUniChar, for use by the core. This brings notable
- speedups for primarily ascii string handling.
+ * generic/tclCmdAH.c (Tcl_ForeachObjCmd): Replaced arrays on the
+ C stack and ckalloc calls with TclStackAlloc calls to use memory on
+ Tcl's evaluation stack.
- * generic/tcl.h (TCL_PATCH_LEVEL): bump to 8.4.1.1 for patchlevel
- only. This interim number will only be reflected by [info patchlevel]
+ * generic/tclExecute.c: Revised GrowEvaluationStack to take an
+ argument specifying the growth required by the caller, so that a
+ single reallocation / copy is the most that will ever be needed even
+ when required growth is large.
-2002-11-11 Kevin Kenny <kennykb@acm.org>
+2007-03-21 Don Porter <dgp@users.sourceforge.net>
- * doc/Tcl.n: Corrected indentation of the new language. Oops.
+ * generic/tclExecute.c: More ckalloc -> ckrealloc conversions.
+ * generic/tclLiteral.c:
+ * generic/tclNamesp.c:
+ * generic/tclParse.c:
+ * generic/tclPreserve.c:
+ * generic/tclStringObj.c:
+ * generic/tclUtil.c:
-2002-11-10 Kevin Kenny <kennykb@acm.org>
+2007-03-20 Don Porter <dgp@users.sourceforge.net>
- * doc/Tcl.n: Added language to the Endekalogue to make it clear that
- substitutions always take place from left to right. [Bug 635644]
+ * generic/tclEnv.c: Some more ckalloc -> ckrealloc replacements.
+ * generic/tclLink.c:
-2002-11-06 Mo DeJong <mdejong@users.sourceforge.net>
+2007-03-20 Kevin B. Kenny <kennykb@acm.org>
- * changes: Note TclInExit TclInThreadExit changes.
- * generic/tclEvent.c (TclInExit, TclInThreadExit):
- Split out functionality of TclInExit to make it clear which one should
- be called in each situation.
- * generic/tclInt.decls: Declare TclInThreadExit.
- * generic/tclIntDecls.h: Regen.
- * generic/tclStubInit.c: Regen.
- * mac/tclMacChan.c (StdIOClose):
- * unix/tclUnixChan.c (FileCloseProc):
- * win/tclWinChan.c (FileCloseProc):
- * win/tclWinConsole.c (ConsoleCloseProc):
- * win/tclWinPipe.c (TclpCloseFile):
- * win/tclWinSerial.c (SerialCloseProc): Invoke the new TclInThreadExit
- method instead of TclInExit.
+ * generic/tclDate.c: Rebuilt, despite Donal Fellows's comment when
+ committing it that no rebuild was required.
+ * generic/tclGetDate.y: According to Donal Fellows, "Introduce modern
+ formatting standards; no need for rebuild of tclDate.c."
-2002-11-06 Mo DeJong <mdejong@users.sourceforge.net>
+ * library/tzdata/America/Cambridge_Bay:
+ * library/tzdata/America/Havana:
+ * library/tzdata/America/Inuvik:
+ * library/tzdata/America/Iqaluit:
+ * library/tzdata/America/Pangnirtung:
+ * library/tzdata/America/Rankin_Inlet:
+ * library/tzdata/America/Resolute:
+ * library/tzdata/America/Yellowknife:
+ * library/tzdata/Asia/Choibalsan:
+ * library/tzdata/Asia/Dili:
+ * library/tzdata/Asia/Hovd:
+ * library/tzdata/Asia/Jakarta:
+ * library/tzdata/Asia/Jayapura:
+ * library/tzdata/Asia/Makassar:
+ * library/tzdata/Asia/Pontianak:
+ * library/tzdata/Asia/Ulaanbaatar:
+ * library/tzdata/Europe/Istanbul: Upgraded to Olson's tzdata2007d.
- * unix/configure: Regen.
- * unix/tcl.m4 (SC_CONFIG_CFLAGS): Generate a fatal configure error if
- no ar program can be found on the path. [Bug 582039]
- * win/configure: Regen.
- * win/configure.in: Check that AR, RANLIB, and RC are found on the
- path when building with gcc.
+ * generic/tclListObj.c (TclLsetList, TclLsetFlat):
+ * tests/lset.test: Changes to deal with shared internal representation
+ for lists passed to the [lset] command. Thanks to Don Porter for
+ fixing this issue. [Bug 1677512]
-2002-11-03 David Gravereaux <davygrvy@pobox.com>
+2007-03-19 Don Porter <dgp@users.sourceforge.net>
- * win/tclAppInit.c: Calls Registry_Init() and Dde_Init() when
- STATIC_BUILD and TCL_USE_STATIC_PACKAGES macros are set.
+ * generic/tclCompile.c: Revise the various expansion routines for
+ CompileEnv fields to use ckrealloc() where appropriate.
- * win/makefile.vc:
- * win/rules.vc: linkexten option now sets the TCL_USE_STATIC_PACKAGES
- macro which also adds the registry and dde object files to the link
- of the shell. [Patch 479697] Also factored some additional macros
- that will be helpful for extension authors. Version grepping of tcl.h
- will need to be added to complete this.
+ * generic/tclBinary.c (Tcl_SetByteArrayLength): Replaced ckalloc() /
+ memcpy() sequence with ckrealloc() call.
- * win/buildall.vc.bat: Added more descriptive commentary.
+ * generic/tclBasic.c (Tcl_CreateMathFunc): Replaced some calls to
+ * generic/tclEvent.c (Tcl_CreateThread): Tcl_Alloc() with calls
+ * generic/tclObj.c (UpdateStringOfBignum): to ckalloc(), which
+ * unix/tclUnixTime.c (SetTZIfNecessary): better supports memory
+ * win/tclAppInit.c (setargv): debugging.
-2002-11-01 David Gravereaux <davygrvy@pobox.com>
+2007-03-19 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * win/tclWinReg.c: Changed the Tcl_PkgProvide() line to declare the
- registry extension at version 1.1 from 1.0.
+ * doc/regsub.n: Corrected example so that it doesn't recommend
+ potentially unsafe practice. Many thanks to Konstantin Kushnir
+ <chpock@gmail.com> for reporting this.
-2002-10-31 Andreas Kupries <andreask@activestate.com>
+2007-03-17 Kevin B. Kenny <kennykb@acm.org>
- * library/word.tcl: Changed $tcl_platform to $::tcl_platform to avoid
- possible scope trouble.
+ * win/tclWinReg.c (GetKeyNames): Size the buffer for enumerating key
+ names correctly, so that Unicode names exceeding 127 chars can be
+ retrieved without crashing. [Bug 1682211]
+ * tests/registry.test (registry-4.9): Added test case for the above
+ bug.
-2002-10-29 Vince Darley <vincentdarley@users.sourceforge.net>
+2007-03-15 Mo DeJong <mdejong@users.sourceforge.net>
- * win/tclWinInt.h:
- * win/tclWin32Dll.c: added comments about certain NULL function
- pointers which will be filled in when Tcl_FindExecutable is called, so
- that users don't report invalid bugs on this topic. (No code changes
- at all).
+ * generic/tclIOUtil.c (Tcl_Stat): Reimplement workaround to avoid gcc
+ warning by using local variables. When the macro argument is of type
+ long long instead of long, the incorrect warning is not generated.
-2002-10-29 Daniel Steffen <das@users.sourceforge.net>
+2007-03-15 Mo DeJong <mdejong@users.sourceforge.net>
- * unix/tclLoadDyld.c (TclpFindSymbol): pass all dyld error messages
- upstream [Bug 627546].
+ * win/Makefile.in: Fully qualify LIBRARY_DIR so that `make test` does
+ not depend on working dir.
-2002-10-28 Andreas Kupries <andreask@activestate.com>
+2007-03-15 Mo DeJong <mdejong@users.sourceforge.net>
- * library/dde/pkgIndex.tcl:
- * library/reg/pkgIndex.tcl: Changed the hardwired debug suffix (d) to
- the correct suffix (g).
+ * tests/parse.test: Add two backslash newline parse tests.
-2002-10-28 Don Porter <dgp@users.sourceforge.net>
+2007-03-12 Don Porter <dgp@users.sourceforge.net>
- * library/auto.tcl: Converted the Mac-specific [package unknown]
- * library/init.tcl: behavior to use a chaining mechanism to extend
- * library/package.tcl: the default [tclPkgUnknown]. [Bug 627660]
- * library/tclIndex: [Patch 624509] (steffen)
+ * generic/tclExecute.c (INST_FOREACH_STEP4): Make private copy of
+ * tests/foreach.test (foreach-10.1): value list to be assigned to
+ variables so that shimmering of that list doesn't lead to invalid
+ pointers. [Bug 1671087]
-2002-10-26 David Gravereaux <davygrvy@pobox.com>
+ * generic/tclEvent.c (HandleBgErrors): Make efficient private copy
+ * tests/event.test (event-5.3): of the command prefix for the interp's
+ background error handling command to avoid panics due to pointers to
+ memory invalid after shimmering. [Bug 1670155]
- * win/makefile.vc: xcopy on NT 4.0 doesn't support the /Y switch
- (overwrite). Added logic to handle this. [Bug 618019]
+ * generic/tclNamesp.c (NsEnsembleImplementationCmd): Make efficient
+ * tests/namespace.test (namespace-42.8): private copy of the
+ command prefix as we invoke the command appropriate to a particular
+ subcommand of a particular ensemble to avoid panic due to shimmering
+ of the List intrep. [Bug 1670091]
-2002-10-23 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclVar.c (TclArraySet): Make efficient private copy of
+ * tests/var.test (var-17.1): the "list" argument to [array set] to
+ avoid crash due to shimmering invalidating pointers. [Bug 1669489]
- * generic/tclInt.h: Removed definitions of obsolete HistoryEvent and
- HistoryRev structures (the history mechanism has been written in Tcl
- for some time now).
+2007-03-12 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
-2002-10-22 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclCmdIL.c (Tcl_LsortObjCmd): Fix problems with declaration
+ positioning and memory leaks. [Bug 1679072]
- *** 8.4.1 TAGGED FOR RELEASE ***
+2007-03-11 Donal K. Fellows <dkf@users.sf.net>
- * changes: updated for 8.4.1 release
+ * generic/tclCmdIL.c (Tcl_LreverseObjCmd): Ensure that a list is
+ correctly reversed even if its internal representation is shared
+ without the object itself being shared. [Bug 1675044]
- * win/Makefile.in: removed @MEM_DEBUG_FLAGS@ subst.
- * win/configure: regen
- * win/configure.in: removed SC_ENABLE_MEMDEBUG call
- * win/tcl.m4: replaced SC_ENABLE_MEMDEBUG with a more intelligent
- SC_ENABLE_SYMBOLS that takes yes|no|mem|compile|all as options now.
+2007-03-10 Miguel Sofer <msofer@users.sf.net>
-2002-10-22 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tclCmdIL (Tcl_LsortObjCmd): changed fix to [Bug 1675116] to
+ use the cheaper TclListObjCopy() instead of Tcl_DuplicateObj().
- * library/auto.tcl (tcl_findLibrary):
- * library/package.tcl (tclPkgUnknown): on macosx, search inside the
- Resources/Scripts subdirectory of any potential package directory
- * macosx/Tcl.pbproj/project.pbxproj: add standard Frameworks dirs to
- TCL_PACKAGE_PATH make argument.
- * unix/tclUnixInit.c (TclpSetVariables): on macosx, add embedded
- framework dirs to tcl_pkgPath: @executable_path/../Frameworks and
- @executable_path/../PrivateFrameworks (if they exist), as well as the
- dirs in DYLD_FRAMEWORK_PATH (if set). [Patch 624509] use standard
- MAXPATHLEN instead of literal 1024
+2007-03-09 Andreas Kupries <andreask@activestate.com>
-2002-10-22 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * library/platform/shell.tcl: Made more robust if an older platform
+ * library/platform/pkgIndex.tcl: package is present in the inspected
+ * unix/Makefile.in: shell. Package forget it to prevent errors. Bumped
+ * win/Makefile.in: package version to 1.1.3, and updated the Makefiles
+ installing it as Tcl Module.
- * doc/StringObj.3, doc/Object.3: Documented that Tcl_Obj's
- standard string form is a modified UTF-8; apparently, this was not
- mentioned anywhere in the main docs, and lead to [Bug 624919].
+2007-03-09 Donal K. Fellows <donal.k.fellows@man.ac.uk>
-2002-10-21 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tclCmdIL.c (Tcl_LsortObjCmd): Handle tricky case with loss
+ * tests/cmdIL.test (cmdIL-1.29): of list rep during sorting due
+ to shimmering. [Bug 1675116]
- * macosx/Tcl.pbproj/project.pbxproj: bumped version to 8.4.1
- * generic/tcl.h: Added reminder comment to edit
- macosx/Tcl.pbproj/project.pbxproj when version number changes.
+2007-03-09 Kevin B. Kenny <kennykb@acm.org>
-2002-10-18 Jeff Hobbs <jeffh@ActiveState.com>
+ * library/clock.tcl (ReadZoneinfoFile): Added Y2038 compliance to the
+ code for version-2 'zoneinfo' files.
+ * tests/clock.test (clock-56.3): Added a test case for Y2038 and
+ 'zoneinfo'. Modified test initialisation to use the
+ 'loadTestedCommands' function of tcltest to bring in the correct path
+ for the registry library.
- * library/reg/pkgIndex.tcl:
- * win/configure:
- * win/configure.in:
- * win/Makefile.in:
- * win/makefile.vc:
- * win/makefile.bc: Updated to reg1.1
+2007-03-08 Don Porter <dgp@users.sourceforge.net>
- * doc/registry.n: Added support for broadcasting changes to the
- * tests/registry.test: registry Environment. Noted proper code in ths
- * win/tclWinReg.c: docs. [Patch 625453]
+ * generic/tclListObj.c (TclLsetList): Rewrite so that the routine
+ itself does not do any direct intrep surgery. Better isolates those
+ things into the implementation of the "list" Tcl_ObjType.
- * unix/Makefile.in (dist): add any mac/tcl*.sea.hqx files
+2007-03-08 Donal K. Fellows <donal.k.fellows@man.ac.uk>
-2002-10-17 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclListObj.c (TclLindexList, TclLindexFlat): Moved these
+ functions to tclListObj.c from tclCmdIL.c to mirror the way that the
+ equivalent functions for [lset]'s guts are arranged.
- * generic/tclVar.c: Fixed code that check for proper # of args to
- * tests/var.test: [array names]. Added test. [Bug 624755]
+2007-03-08 Kevin B. Kenny <kennykb@acm.org>
-2002-10-16 Jeff Hobbs <jeffh@ActiveState.com>
+ * library/clock.tcl: Further tweaks to the Windows time zone table
+ (restoring missing Mexican time zones). Added rudimentary handling of
+ version-2 'zoneinfo' files. Update US DST rules so that zones such as
+ 'EST5EDT' get the correct transition dates.
+ * tests/clock.test: Added rudimentary test cases for 'zoneinfo'
+ parsing. Adjusted several tests that depended on obsolete US DST
+ transition rules.
- * win/configure: add workaround for cygwin windres
- * win/tcl.m4 (SC_CONFIG_CFLAGS): problem. [Patch 624010] (howell)
+2007-03-07 Daniel Steffen <das@users.sourceforge.net>
-2002-10-15 Jeff Hobbs <jeffh@ActiveState.com>
+ * macosx/tclMacOSXNotify.c: add spinlock debugging and sanity checks.
- * README: added archives.tcl.tk note
+ * macosx/Tcl.xcodeproj/project.pbxproj: ensure gcc version used by
+ * macosx/Tcl.xcodeproj/default.pbxuser: Xcode and configure/make are
+ * macosx/Tcl-Common.xcconfig: consistent and independent of
+ gcc_select default and CC env var; fixes for Xcode 3.0.
- * unix/configure:
- * unix/tcl.m4: Correct AIX-5 ppc build flags. Correct HP 11 64-bit gcc
- building. [Patch 601051] (martin)
+ * unix/tcl.m4 (Darwin): s/CFLAGS/CPPFLAGS/ in macosx-version-min check
+ * unix/configure: autoconf-2.59
-2002-10-15 Vince Darley <vincentdarley@users.sourceforge.net>
+2007-03-07 Don Porter <dgp@users.sourceforge.net>
- * generic/tclCmdMZ.c:
- * tests/trace.test: applied patch from Hemang Levana to fix [Bug
- 615043] in execution traces with idle tasks firing.
+ * generic/tclCmdIL.c (TclLindex*): Rewrites to make efficient
+ private copies of the list and indexlist arguments, so we can operate
+ on the list elements directly with no fear of shimmering effects.
+ Replaces defensive coding schemes that are otherwise required. End
+ result is that TclLindexList is entirely a wrapper around
+ TclLindexFlat, which is now the core engine of all [lindex]
+ operations.
-2002-10-14 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclObj.c (Tcl_AppendAllObjTypes): Converted to simpler
+ list validity test.
- * generic/tclEnv.c (Tcl_PutEnv): correct possible mem leak.
- [Patch 623269] (brouwers)
+2007-03-07 Donal K. Fellows <donal.k.fellows@man.ac.uk>
-2002-10-11 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclRegexp.c (TclRegAbout): Generate information about a
+ regexp as a Tcl_Obj instead of as a string, which is more efficient.
- * generic/tcl.h: Need a different strategy through the maze of
- #defines to let people building with Cygwin build correctly. Also
- made some comments less misleading...
+2007-03-07 Kevin B. Kenny <kennykb@acm.org>
-2002-10-10 Jeff Hobbs <jeffh@ActiveState.com>
+ * library/clock.tcl: Adjusted Windows time zone table to handle new US
+ DST rules by locale rather than as Posix time zone spec.
+ * tests/clock.test (clock-39.6, clock-49.2, testclock::registry):
+ Adjusted tests to simulate new US rules.
+ * library/tzdata/America/Indiana/Winamac:
+ * library/tzdata/Europe/Istanbul:
+ * library/tzdata/Pacific/Easter:
+ Olson's tzdata2007c.
- * README: fixed minor nits [Bug 607776] (virden)
+2007-03-05 Andreas Kupries <andreask@activestate.com>
- * win/configure:
- * win/tcl.m4: enable USE_THREAD_ALLOC (new threaded allocator) by
- default in cygwin configure on Windows.
+ * library/platform/shell.tcl (::platform::shell::RUN): In the case of
+ * library/platform/pkgIndex.tcl: a failure put the captured stderr
+ * unix/Makefile.in: into the error message to aid in debugging. Bumped
+ * win/Makefile.in: package version to 1.1.2, and updated the makefiles
+ installing it as Tcl Module.
-2002-10-10 Don Porter <dgp@users.sourceforge.net>
+2007-03-03 Donal K. Fellows <dkf@users.sf.net>
- * doc/Tcl.n: Clarified that namespace separators are legal in
- the variable names during $-subtitution. [Bug 615139]
+ * generic/tclLink.c (LinkedVar): Added macro to conceal at least some
+ of the pointer hackery.
- * doc/regexp.n: Typo correction. Thanks Ronnie Brunner. [Bug 606826]
+2007-03-02 Don Porter <dgp@users.sourceforge.net>
-2002-10-10 Vince Darley <vincentdarley@users.sourceforge.net>
+ * generic/tclCmdIL.c (Tcl_LreverseObjCmd): Added missing
+ TclInvalidateStringRep() call when we directly manipulate the intrep
+ of an unshared "list" Tcl_Obj. [Bug 1672585]
- * unix/tclLoadAout.c
- * unix/tclLoadDl.c
- * unix/tclLoadDld.c
- * unix/tclLoadDyld.c
- * unix/tclLoadNext.c
- * unix/tclLoadOSF.c
- * unix/tclLoadShl.c
- * win/tclWinLoad.c: allow either full paths or simply dll names to be
- specified when loading files (the latter will be looked up by the OS
- on your PATH/LD_LIBRARY_PATH as appropriate). Fixes [Bug 611108]
+ * generic/tclCmdIL.c (Tcl_JoinObjCmd): Revised [join] implementation
+ to append Tcl_Obj's instead of strings. [RFE 1669420]
-2002-10-09 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclCmdIL.c (Info*Cmd): Code simplifications and
+ optimizations.
- * unix/README: doc'ed --enable-symbols options.
- * unix/Makefile.in: removed @MEM_DEBUG_FLAGS@ subst.
- * unix/configure: regen
- * unix/configure.in: removed SC_ENABLE_MEMDEBUG call
- * unix/tcl.m4: replaced SC_ENABLE_MEMDEBUG with a more intelligent
- SC_ENABLE_SYMBOLS that takes yes|no|mem|compile|all as options now.
+2007-03-02 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
-2002-10-09 Kevin B. Kenny <kennykb@acm.org>
+ * generic/tclCompile.c (TclPrintInstruction): Added a scheme to allow
+ * generic/tclCompile.h (AuxDataPrintProc): aux-data to be printed
+ * generic/tclCompCmds.c (Print*Info): out for debugging. For
+ this to work, immediate operands referring to aux-data must be
+ identified as such in the instruction descriptor table using
+ OPERAND_AUX4 (all are always 4 bytes).
- * win/tclWinTime.c: Added code to set an exit handler that terminates
- the thread that calibrates the performance counter, so that the thread
- won't outlive unloading the Tcl DLL. [Bug 620735].
+ * generic/tclExecute.c (TclExecuteByteCode): Rewrote the compiled
+ * generic/tclCompCmds.c (TclCompileDictCmd): [dict update] so that it
+ * generic/tclCompile.h (DictUpdateInfo): stores critical
+ * tests/dict.test (dict-21.{14,15}): non-varying data in an
+ aux-data value instead of a (shimmerable) literal. [Bug 1671001]
-2002-10-09 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+2007-03-01 Don Porter <dgp@users.sourceforge.net>
- * doc/binary.n: More clarification of [binary scan]'s behaviour.
+ * generic/tclCmdIL.c (Tcl_LinsertObjCmd): Code simplifications
+ and optimizations.
-2002-10-09 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tclCmdIL.c (Tcl_LreplaceObjCmd): Code simplifications
+ and optimizations.
- * generic/tclIntDecls.h: fixed botched regen.
+ * generic/tclCmdIL.c (Tcl_LrangeObjCmd): Rewrite in the same
+ spirit; avoid shimmer effects rather than react to them.
-2002-10-09 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tclCmdAH.c (Tcl_ForeachObjCmd): Stop throwing away
+ * tests/foreach.test (foreach-1.14): useful error information when
+ loop variable sets fail.
- * generic/tclInt.decls: made TclSetPreInitScript() declaration
- generic as it is used on mac & aqua as well.
- * generic/tclIntDecls.h:
- * generic/tclStubInit.c: regen.
- * generic/tclCompile.h: added prototype for TclCompileVariableCmd.
+ * generic/tclCmdIL.c (Tcl_LassignObjCmd): Rewrite to make an
+ efficient private copy of the list argument, so we can operate on the
+ list elements directly with no fear of shimmering effects. Replaces
+ defensive coding schemes that are otherwise required.
- * mac/tclMacPort.h: removed incorrect <fcntl.h> definitions and
- obsolete <stat.h> definitions.
- * mac/tclMacChan.c: removed obsolete GetOpenMode() and replaced
- associated constants with the <fcntl.h> analogues (they existing defs
- were inconsistent with <fcntl.h> which was causing havoc when
- Tcl_GetOpenMode was used instead of private GetOpenMode).
+ * generic/tclCmdAH.c (Tcl_ForeachObjCmd): Rewrite to make
+ efficient private copies of the variable and value lists, so we can
+ operate on them without any special shimmer defense coding schemes.
- * mac/tclMacFCmd.c: removed GenerateUniqueName(), use equivalent (and
- identically named) routine from MoreFiles instead.
+2007-03-01 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * mac/tclMacLoad.c: CONSTification, fixes to Vince's last changes.
+ * generic/tclCompCmds.c (TclCompileForeachCmd): Prevent an unexpected
+ * tests/foreach.test (foreach-9.1): infinite loop when the
+ variable list is empty and the foreach is compiled. [Bug 1671138]
- * mac/tclMacFile.c:
- * mac/tclMacTest.c:
- * mac/tclMacUnix.c: CONSTification.
+2007-02-26 Andreas Kupries <andreask@activestate.com>
- * mac/tclMacOSA.c: CONSTification, sprintf fixes, UH 3.4.x changes;
- fix for missing autoname token from TclOSACompileCmd. (bdesgraupes)
- * mac/AppleScript.html(AppleScript delete): doc fix. (bdesgraupes)
+ * generic/tclIORChan.c (FreeReflectedChannel): Added the missing
+ refcount release between NewRC and FreeRC for the channel handle
+ object, spotted by Don Porter. [Bug 1667990]
- * mac/tcltkMacBuildSupport.sea.hqx: updated MoreFiles to 1.5.3,
- updated build instructions for 8.4.
- * mac/tclMacProjects.sea.hqx: rebuilt archive.
+2007-02-26 Don Porter <dgp@users.sourceforge.net>
-2002-10-09 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclCmdAH.c (Tcl_ForeachObjCmd): Removed surplus
+ copying of the objv array that used to be a workaround for [Bug
+ 404865]. That bug is long fixed.
- * doc/Alloc.3: Added a note to mention that attempting to allocate a
- zero-length block can return NULL. [Tk Bug 619544]
+2007-02-24 Don Porter <dgp@users.sourceforge.net>
-2002-10-04 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclBasic.c: Use new interface in Tcl_EvalObjEx so that the
+ recounting logic of the List internal rep need not be repeated there.
+ Better encapsulation of internal details.
- * doc/binary.n: Doc improvements [Patch 616480]
+ * generic/tclInt.h: New internal routine TclListObjCopy() used
+ * generic/tclListObj.c: to efficiently do the equivalent of [lrange
+ $list 0 end]. After some experience with this, might be a good
+ candidate for exposure as a public interface. It's useful for callers
+ of Tcl_ListObjGetElements() who want to control the ongoing validity
+ of the returned objv pointer.
- * tests/fCmd.test, tests/winFCmd.test:
- * tools/eolFix.tcl, tools/genStubs.tcl: [file exist] -> [file exists]
- Thanks to David Welton.
+2007-02-22 Andreas Kupries <andreask@activestate.com>
-2002-10-03 Don Porter <dgp@users.sourceforge.net>
+ * tests/pkg.test: Added tests for the case of an alpha package
+ satisfying a require for the regular package, demonstrating a corner
+ case specified in TIP#280. More notes in the comments to the test.
- * doc/tcltest.n: fixed typo [Bug 618018]. Thanks to "JJM".
+2007-02-20 Jan Nijtmans <nijtmans@users.sf.net>
-2002-10-03 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclInt.decls: Added "const" specifiers in TclSockGetPort
+ * generic/tclIntDecls.h: regenerated
+ * generic/*.c:
+ * unix/tclUnixChan.c
+ * unix/tclUnixPipe.c
+ * win/tclWinPipe.c
+ * win/tclWinSock.c: Added many "const" specifiers in implementation.
- * tools/man2help2.tcl:
- * tests/http.test, tests/httpd, tests/httpold.test:
- * tests/env.test, tests/binary.test, tests/autoMkindex.test:
- * library/init.tcl, library/http/http.tcl: [info exist] should really
- be [info exists]. [Bug 602566]
+2007-02-20 Don Porter <dgp@users.sourceforge.net>
- * doc/lsearch.n: Better specification of what happens when -sorted is
- mixed with other options. [Bug 617816]
+ * doc/tcltest.n: Typo fix. [Bug 1663539]
-2002-10-01 Jeff Hobbs <jeffh@ActiveState.com>
+2007-02-20 Pat Thoyts <patthoyts@users.sourceforge.net>
- * generic/tclProc.c (TclCreateProc): mask out VAR_UNDEFINED for
- precompiled locals to support 8.3 precompiled code.
- (Tcl_ProcObjCmd): correct 2002-09-26 fix to look for tclProcBodyType.
+ * generic/tclFileName.c: Handle extended paths on Windows NT and
+ * generic/tclPathObj.c: above. These have a \\?\ prefix. [Bug
+ * win/tclWinFile.c: 1479814]
+ * tests/winFCmd.test: Tests for extended path handling.
-2002-10-01 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+2007-02-19 Jeff Hobbs <jeffh@ActiveState.com>
- * doc/socket.n: Mentioned that ports may be specified as serivce names
- as well as integers. [Bug 616843]
+ * unix/tcl.m4: use SHLIB_SUFFIX=".so" on HP-UX ia64 arch.
+ * unix/configure: autoconf-2.59
-2002-09-30 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclIOUtil.c (Tcl_FSEvalFileEx): safe incr of objPtr ref.
- * generic/tclCompCmds.c (TclCompileRegexpCmd): correct the checking
- for bad re's that didn't terminate the re string. Resultant compiles
- were correct, but much slower than necessary.
+2007-02-18 Donal K. Fellows <dkf@users.sf.net>
-2002-09-29 David Gravereaux <davygrvy@pobox.com>
+ * doc/chan.n, doc/clock.n, doc/eval.n, doc/exit.n, doc/expr.n:
+ * doc/interp.n, doc/open.n, doc/platform_shell.n, doc/pwd.n:
+ * doc/refchan.n, doc/regsub.n, doc/scan.n, doc/tclvars.n, doc/tm.n:
+ * doc/unload.n: Apply [Bug 1610310] to fix typos. Thanks to Larry
+ Virden for spotting them.
- * win/tclAppInit.c: Added proper exiting conditions using Win32
- console signals. This handles the existing lack of a Ctrl+C exit to
- call exit handlers when built for thread support. Also, properly
- handles exits from other conditions such as CTRL_CLOSE_EVENT,
- CTRL_LOGOFF_EVENT, and CTRL_SHUTDOWN_EVENT signals. In all cases, exit
- handlers will be called. [Bug 219355]
+ * doc/interp.n: Partial fix of [Bug 1662436]; rest requires some
+ policy decisions on what should and shouldn't be safe commands from
+ the "new in 8.5" set.
- * win/makefile.vc: Added missing tclThreadAlloc.c to the build rules
- and defines USE_THREAD_ALLOC when TCL_THREADS is defined to get the
- new behavior by default.
+2007-02-13 Kevin B. Kenny <kennykb@acm.org>
-2002-09-27 Don Porter <dgp@users.sourceforge.net>
+ * tools/fix_tommath_h.tcl: Further tweaking for the x86-64. The change
+ is to make 'mp_digit' be an 'unsigned int' on that platform; since
+ we're using only 32 bits of it, there's no reason to make it a 64-bit
+ 'unsigned long.'
+ * generic/tclTomMath.h: Regenerated.
- * README: Bumped to version 8.4.1 to avoid confusion
- * generic/tcl.h: of CVS snapshots with the actual 8.4.0
- * tools/tcl.wse.in: release.
- * unix/configure.in:
- * unix/tcl.spec:
- * win/configure.in:
+2007-02-13 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * unix/configure: autoconf
- * win/configure:
+ * doc/re_syntax.n: Corrected description of 'print' class [Bug
+ 1614687] and enhanced description of 'graph' class.
-2002-09-26 Jeff Hobbs <jeffh@ActiveState.com>
+2007-02-12 Kevin B. Kenny <kennykb@acm.org>
- * unix/configure: regen.
- * unix/tcl.m4: improve AIX-4/5 64bit compilation support.
+ * tools/fix_tommath_h.tcl: Added code to patch out a check for
+ __x86_64__ that caused Tommath to use __attributes(TI)__ for the
+ mp_word type. Tetra-int's simply fail on too many gcc-glibc-OS
+ combinations to be ready for shipment today, even if they work for
+ some of us. This change allows reversion of das's change of 2006-08-18
+ that accomplised the same thing on Darwin. [Bugs 1601380, 1603737,
+ 1609936, 1656265]
+ * generic/tclTomMath.h: Regenerated.
+ * library/tzdata/Africa/Asmara:
+ * library/tzdata/Africa/Asmera:
+ * library/tzdata/America/Nassau:
+ * library/tzdata/Atlantic/Faeroe:
+ * library/tzdata/Atlantic/Faroe:
+ * library/tzdata/Australia/Eucla:
+ * library/tzdata/Pacific/Easter: Rebuilt from Olson's tzdata2007b.
- * generic/tclProc.c (Tcl_ProcObjCmd): correct overeager optimization
- of noop proc to handle the precompiled case. (sofer)
+2007-02-09 Joe Mistachkin <joe@mistachkin.com>
- * unix/ldAix (nmopts): add -X32_64 to make it work for 32 or 64bit
- mode compilation.
+ * win/nmakehlp.c: Properly cleanup after nmakehlp, including the
+ * win/makefile.vc: vcX0.pch file.
- * library/encoding/koi8-u.enc: removed extraneous spaces that confused
- encoding reader. [Bug 615115]
+2007-02-08 Jeff Hobbs <jeffh@ActiveState.com>
- * unix/Makefile.in: generate source dists with -src designator and do
- not generate .Z anymore (just .gz and .zip).
+ * unix/tclUnixInit.c (TclpCheckStackSpace): do stack size checks with
+ unsigned size_t to correctly validate stackSize in the 2^31+ range.
+ [Bug 1654104]
-2002-09-18 Mumit Khan <khan@nanotech.wisc.edu>
+2007-02-08 Don Porter <dgp@users.sourceforge.net>
- Added basic Cygwin support.
+ * generic/tclNamesp.c: Corrected broken logic in Tcl_DeleteNamespace
+ * tests/namespace.test: introduced in Patch 1577278 that caused
+ [namespace delete ::] to be effective only at level #0. New test
+ namespace-7.7 should prevent similar error in the future [Bug 1655305]
- * win/tcl.m4 (SC_PATH_TCLCONFIG): Support one-tree build.
- (SC_PATH_TKCONFIG): Likewise.
- (SC_PROG_TCLSH): Likewise.
- (SC_CONFIG_CFLAGS): Assume real Cygwin port and remove -mno-cygwin
- flags. Add -mwin32 to extra_cflags and extra_ldflags. Remove ``-e
- _WinMain@16'' from LDFLAGS_WINDOW.
- * win/configure.in: Allow Cygwin build.
- (SEH test): Define to be 1 instead of empty value.
- (EXCEPTION_DISPOSITION): Add test.
- * win/configure: Regenerate.
+2007-02-06 Don Porter <dgp@users.sourceforge.net>
- * generic/tcl.h: Don't explicitly define __WIN32__ for Cygwin, let the
- user decide whether to use Windows or POSIX personality.
- (TCL_WIDE_INT_TYPE, TCL_LL_MODIFIER, struct Tcl_StatBuf): Define for
- Cygwin.
- * generic/tclEnv.c (Tcl_CygwinPutenv): putenv replacement for Cygwin.
- * generic/tclFileName.c (Tcl_TranslateFileName): Convert POSIX to
- native format.
- (TclDoGlob): Likewise.
- * generic/tclPlatDecls.h (TCHAR): Define for Cygwin.
- * win/tclWinPort.h (putenv, TclpSysAlloc, TclpSysFree)
- (TclpSysRealloc): Define for Cygwin.
+ * generic/tclNamesp.c: Corrected broken implementation of the
+ * tests/namespace.test: TclMatchIsTrivial optimization on [namespace
+ children $namespace $pattern].
-2002-09-26 Daniel Steffen <das@users.sourceforge.net>
+2007-02-04 Daniel Steffen <das@users.sourceforge.net>
- * macosx/Makefile: preserve environment value of INSTALL_ROOT. When
- embedding only use deployment build. Force relink before embedded
- build to ensure new linker flags are picked up.
+ * unix/tcl.m4: use gcc4's __attribute__((__visibility__("hidden"))) if
+ available to define MODULE_SCOPE effective on all platforms.
+ * unix/configure.in: add caching to -pipe and zoneinfo checks.
+ * unix/configure: autoconf-2.59
+ * unix/tclConfig.h.in: autoheader-2.59
- * macosx/Tcl.pbproj/project.pbxproj: add symbolic links to debug lib,
- stub libs and tclConfig.sh in framework toplevel. Configure target
- dependency fix. Fix to 'clean' action. Added private tcl headers to
- framework. Install tclsh symbolic link. Html doc build works when no
- installed tclsh available. Made html doc structure in framework more
- like in Apple frameworks.
+2007-02-03 Joe Mistachkin <joe@mistachkin.com>
-2002-09-24 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * win/rules.vc: Fix platform specific file copy macros for downlevel
+ Windows.
- * unix/tcl.m4 (SC_TCL_64BIT_FLAGS): Yet more robust 64-bit value
- detection to close [Bug 613117] on more systems.
+2007-01-29 Don Porter <dgp@users.sourceforge.net>
- * generic/tclCompile.c (TclPrintSource): More CONSTifying.
- * generic/tclExecute.c (EvalStatsCmd): Object-ify to reduce warnings.
- Thanks to 'CoderX2' on the chat for bringing this to my attention...
+ * generic/tclResult.c: Added optimization case to TclTransferResult to
+ cover common case where there's big savings over the fully general
+ path. Thanks to Peter MacDonald. [Bug 1626518]
- * unix/tcl.m4: Forgot to define TCL_WIDE_INT_IS_LONG at the
- appropriate moment. I believe this is the cause of [Bug 613117]
+ * generic/tclLink.c: Broken linked float logic corrected. Thanks to
+ Andy Goth. [Bug 1602538]
- * doc/lset.n: Changed 'list' to 'varName' for consistency with lappend
- documentation. Thanks to Glenn Jackman [Bug 611719]
+ * doc/fcopy.n: Typo fix. [Bug 1630627]
-2002-09-22 Don Porter <dgp@users.sourceforge.net>
+2007-01-28 Daniel Steffen <das@users.sourceforge.net>
- * library/tcltest/tcltest.tcl: Corrected [puts -nonewline] within
- test bodies. Thanks to Harald Kirsch. [Bug 612786, Patch 612788] Also
- corrected reporting of body return code. Thanks to David Taback [Bug
- 611922]
- * library/tcltest/pkgIndex.tcl: Bump to version 2.2.1.
- * tests/tcltest.test: added tests for these bugs.
+ * macosx/Tcl.xcodeproj/project.pbxproj: extract build settings that
+ * macosx/Tcl.xcodeproj/default.pbxuser: were common to multiple
+ * macosx/Tcl-Common.xcconfig (new file): configurations into external
+ * macosx/Tcl-Debug.xcconfig (new file): xcconfig files; add extra
+ * macosx/Tcl-Release.xcconfig (new file): configurations for building
+ with SDKs and 64bit; convert legacy jam-based 'Tcl' target to native
+ target with single script phase; correct syntax of build setting
+ references to use $() throughout.
-2002-09-15 Mo DeJong <mdejong@users.sourceforge.net>
+ * macosx/README: document new Tcl.xcodeproj configurations; other
+ minor updates/corrections.
- * unix/configure: Regen.
- * unix/tcl.m4 (SC_CONFIG_CFLAGS): Add PEEK_XCLOSEIM define under
- Linux. This is used by Tk to double check that an X input context is
- cleaned up before it is closed.
+ * generic/tcl.h: update location of version numbers in macosx files.
-2002-09-12 David Gravereaux <davygrvy@pobox.com>
+ * macosx/Tcl.xcode/project.pbxproj: restore 'tcltest' target to
+ * macosx/Tcl.xcode/default.pbxuser: working order by replicating
+ applicable changes to Tcl.xcodeproj since 2006-07-20.
- * win/coffbase.txt: Added BLT to the virtual base address listings
- table should BLT's build tools decide to use it.
+2007-01-25 Daniel Steffen <das@users.sourceforge.net>
-2002-09-12 Daniel Steffen <das@users.sourceforge.net>
+ * unix/tcl.m4: integrate CPPFLAGS into CFLAGS as late as possible and
+ move (rather than duplicate) -isysroot flags from CFLAGS to CPPFLAGS
+ to avoid errors about multiple -isysroot flags from some older gcc
+ builds.
- * generic/tcl.h:
- * mac/tclMacApplication.r:
- * mac/tclMacLibrary.r:
- * mac/tclMacResource.r: unified use of the two equivalent resource
- compiler header inclusion defines RC_INVOKED and RESOURCE_INCLUDED,
- now use RC_INVOKED throughout.
+ * unix/configure: autoconf-2.59
-2002-09-10 Mo DeJong <mdejong@users.sourceforge.net>
+2007-01-22 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * unix/README: Add note about building extensions with the same
- compiler Tcl was built with. [Tk Bug 592096]
+ * compat/memcmp.c (memcmp): Reworked so that arithmetic is never
+ performed upon void pointers, since that is illegal. [Bug 1631017]
-2002-09-10 Daniel Steffen <das@users.sourceforge.net>
+2007-01-19 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * macosx/Tcl.pbproj/project.pbxproj: disabled building html
- documentation during embedded build.
+ * generic/tclCompile.c (TclCompileScript): Reduce the frequency with
+ which we issue INST_START_CMD, making bytecode both more compact and
+ somewhat faster. The optimized case is where we would otherwise be
+ issuing a sequence of those instructions; in those cases, it is only
+ ever the first one encountered that could possibly trigger.
-2002-09-10 Daniel Steffen <das@users.sourceforge.net>
+2007-01-19 Joe Mistachkin <joe@mistachkin.com>
- * unix/Makefile.in: added DYLIB_INSTALL_DIR variable for macosx and
- set it to default value ${LIB_RUNTIME_DIR}
- * unix/tcl.m4 (Darwin): use DYLIB_INSTALL_DIR instead of
- LIB_RUNTIME_DIR in the -install_name argument to ld.
- * unix/configure: regen.
+ * tools/man2tcl.c: Include stdlib.h for exit() and improve comment
+ detection.
+ * win/nmakehlp.c: Update usage.
+ * win/makefile.vc: Properly build man2tcl.c for MSVC8.
- * macosx/Tcl.pbproj/project.pbxproj:
- * macosx/Makefile: added support for building Tcl as an embedded
- framework, i.e. using an dyld install_name containing
- @executable_path/../Frameworks via the new DYLIB_INSTALL_DIR
- unix/Makefile variable.
+2007-01-19 Daniel Steffen <das@users.sourceforge.net>
-2002-09-10 Jeff Hobbs <jeffh@ActiveState.com>
+ * macosx/tclMacOSXFCmd.c (TclMacOSXSetFileAttribute): on some versions
+ of Mac OS X, truncate() fails on resource forks, in that case use
+ open() with O_TRUNC instead.
- *** 8.4.0 TAGGED FOR RELEASE ***
+ * macosx/tclMacOSXNotify.c: accommodate changes to prototypes of
+ OSSpinLock(Un)Lock API.
-2002-09-06 Don Porter <dgp@users.sourceforge.net>
+ * macosx/Tcl.xcodeproj/project.pbxproj: ensure HOME and USER env vars
+ * macosx/Tcl.xcodeproj/default.pbxuser: are defined when running
+ testsuite from Xcode.
- * doc/file.n: Format correction, and clarified [file normalize]
- returns an absolute path.
+ * tests/env.test: add extra system env vars that need to be preserved
+ on some Mac OS X versions for testsuite to work.
- * doc/tcltest.n: Added examples section, as long promised.
+ * unix/Makefile.in: Move libtommath defines into configure.in to
+ * unix/configure.in: avoid replicating them across multiple
+ * macosx/Tcl.xcodeproj/project.pbxproj: buildsystems.
-2002-09-06 Reinhard Max <max@suse.de>
+ * unix/tcl.m4: ensure CPPFLAGS env var is used when set. [Bug 1586861]
+ (Darwin): add -isysroot and -mmacosx-version-min flags to CPPFLAGS
+ when present in CFLAGS to avoid discrepancies between what headers
+ configure sees during preprocessing tests and compiling tests.
- * tests/tcltest.test: Added nonRoot flag to tests 8.3, 8.4, and 8.12.
+ * unix/configure: autoconf-2.59
+ * unix/tclConfig.h.in: autoheader-2.59
-2002-09-05 Don Porter <dgp@users.sourceforge.net>
+2007-01-18 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * doc/tcltest.n: Clarified phrasing.
+ * generic/tclCompile.c (TclCompileScript): Make sure that when parsing
+ an expanded literal fails, a correct bytecode sequence is still
+ issued. [Bug 1638414]. Also make sure that the start of the expansion
+ bytecode sequence falls inside the span of bytecodes for a command.
+ * tests/compile.test (compile-16.24): Added test for [Bug 1638414]
- * generic/tclBasic.c (TclRenameCommand,CallCommandTraces):
- * tests/trace.test (trace-27.1): Corrected memory leak when a rename
- trace deleted the command being traced. Test added. Thanks to Hemang
- Lavana for the fix. [Bug 604609]
+2007-01-17 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclVar.c (TclDeleteVars): Corrected logic for setting the
- TCL_INTERP_DESTROYED flag when calling variable traces. [Tk Bug 605121]
+ * generic/tclIO.c: Added macros to make usage of ChannelBuffers
+ clearer.
-2002-09-04 Miguel Sofer <msofer@users.sourceforge.net>
+2007-01-11 Joe English <jenglish@users.sourceforge.net>
- * generic/tclVar.c (DeleteArray): leak plug [Bug 604239]. Thanks to
- dkf and dgp for the long and difficult discussion in the chat.
+ * win/tcl.m4(CFLAGS_WARNING): Remove "-Wconversion". This was removed
+ from unix/tcl.m4 2004-07-16 but not from here.
+ * win/configure: Regenerated.
-2002-09-03 Jeff Hobbs <jeffh@ActiveState.com>
+2007-01-11 Pat Thoyts <patthoyts@users.sourceforge.net>
- * generic/tclVar.c (Tcl_UpVar2): code cleanup to not use goto
+ * win/makefile.vc: Fixes to work better on Win98. Read version numbers
+ * win/nmakehlp.c: from package index file to avoid keeping numbers in
+ * win/rules.vc: the makefile where they may become de-synchronized.
- * unix/configure: remove -pthread from LIBS on FreeBSD in thread
- * unix/tcl.m4: enabled build. [Bug 602849]
+2007-01-10 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
-2002-09-03 Miguel Sofer <msofer@users.sourceforge.net>
+ * generic/regcomp.c (compile, freev): Define a strategy for
+ * generic/regexec.c (exec): managing the internal
+ * generic/regguts.h (AllocVars, FreeVars): vars of the RE engine to
+ * generic/regcustom.h (AllocVars, FreeVars): reduce C stack usage.
+ This will make Tcl as a whole much less likely to run out of stack
+ space...
- * generic/tclInterp.c (AliasCreate): a Tcl_Obj was leaked on error
- return from TclPreventAliasLoop.
+2007-01-09 Donal K. Fellows <donal.k.fellows@man.ac.uk>
-2002-09-03 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tclCompCmds.c (TclCompileLindexCmd):
+ * tests/lindex.test (lindex-9.2): Fix silly bug that ended up
+ sometimes compiling list arguments in the wrong order. [Bug 1631364]
- * macosx/Tcl.pbproj/project.pbxproj: Bumped version number to 8.4.0
- and updated copyright info.
+2007-01-03 Kevin B. Kenny <kennykb@acm.org>
-2002-09-03 Miguel Sofer <msofer@users.sourceforge.net>
+ * generic/tclDate.c: Regenerated to recover a lost fix from patthoyts.
+ [Bug 1618523]
- * generic/tclVar.c (Tcl_UpVar2): a Tcl_Obj was being leaked on error
- return from TclGetFrame.
+2006-12-26 Mo DeJong <mdejong@users.sourceforge.net>
-2002-09-03 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclIO.c (Tcl_GetsObj): Avoid checking for for the LF in a
+ possible CRLF sequence when EOF has already been found.
- * changes: Updated changes for 8.4.0 release.
+2006-12-26 Mo DeJong <mdejong@users.sourceforge.net>
-2002-09-02 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclEncoding.c (EscapeFromUtfProc): Clear the
+ TCL_ENCODING_END flag when end bytes are written. This fix keep this
+ method from writing escape bytes for an encoding like iso2022-jp
+ multiple times when the escape byte overlap with the end of the IO
+ buffer.
+ * tests/io.test: Add test for escape byte overlap issue.
- * unix/tclUnixFile.c (TclpObjLink): removed unnecessary/unfreed
- extra native char*.
+2006-12-19 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * unix/tclUnixChan.c (Tcl_MakeTcpClientChannel): make sure to init
- flags field of TcpState ptr to 0.
+ * unix/tclUnixThrd.c (Tcl_GetAllocMutex, TclpNewAllocMutex): Add
+ intermediate variables to shut up unwanted warnings. [Bug 1618838]
- * unix/configure:
- * unix/tcl.m4: added 64-bit gcc compilation support on HP-11.
- [Patch 601051] (martin)
+2006-12-19 Daniel Steffen <das@users.sourceforge.net>
- * README: Bumped version number to 8.4.0
- * generic/tcl.h:
- * tools/tcl.wse.in:
- * unix/configure:
- * unix/configure.in:
- * unix/tcl.spec:
- * win/README.binary:
- * win/configure:
- * win/configure.in:
+ * unix/tclUnixThrd.c (TclpInetNtoa): fix for 64 bit.
- * generic/tclInterp.c (SlaveCreate): make sure that the memory and
- checkmem commands are initialized in non-safe slave interpreters when
- TCL_MEM_DEBUG is used. [Bug 583445]
+ * unix/tcl.m4 (Darwin): --enable-64bit: verify linking with 64bit
+ -arch flag succeeds before enabling 64bit build.
+ * unix/configure: autoconf-2.59
- * win/tclWinConsole.c (ConsoleCloseProc): only wait on writable pipe
- if there was something to write. This may prevent infinite wait on
- exit.
+2006-12-17 Daniel Steffen <das@users.sourceforge.net>
+
+ * tests/macOSXLoad.test (new file): add testing of .bundle loading and
+ * tests/load.test: unloading on Darwin (in addition
+ * tests/unload.test: to existing tests of .dylib
+ loading).
+ * macosx/Tcl.xcodeproj/project.pbxproj: add building of dltest
+ binaries so that testsuite run from Xcode can use them; fix testsuite
+ run script
+ * unix/configure.in: add support for building dltest binaries as
+ * unix/dltest/Makefile.in: .bundle (in addition to .dylib) on Darwin.
+ * unix/Makefile.in: add stub lib dependency to dltest target.
+ * unix/configure: autoconf-2.59
- * tests/exec.test: marked exec-18.1 unixOnly until the Windows
- incompatability (in the test, not the core) can be resolved.
+ * tests/append.test: fix cleanup failure when all tests are skipped.
- * tests/http.test (http-3.11): added close $fp that was causing an
- error on Windows because the file was not closed before deleting.
+ * tests/chan.test (chan-16.9): cleanup chan event handler to avoid
+ causing error in event.test when running testsuite with -singleproc 1.
- * unix/tclUnixInit.c (Tcl_MacOSXGetLibraryPath): made this static
- function only appear when HAVE_CFBUNDLE is defined.
+ * tests/info.test: add !singleTestInterp constraint to tests that fail
+ when running testsuite with -singleproc 1. [Bug 1605269]
-2002-08-31 Daniel Steffen <das@users.sourceforge.net>
+2006-12-14 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * unix/tcl.m4: added TK_SHLIB_LD_EXTRAS analogue of existing
- TCL_SHLIB_LD_EXTRAS for linker settings only used when linking Tk.
+ * doc/string.n: Fix example. [Bug 1615277]
- * unix/configure: regen
+2006-12-12 Don Porter <dgp@users.sourceforge.net>
-2002-08-31 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tclCompExpr.c: Now that the new internal structs are
+ in use to support operator commands, might as well make them the
+ default for [expr] as well and avoid passing every parsed expression
+ through the inefficient Tcl_Token array format. This addresses most
+ issues in [RFE 1517602]. Assuming no performance disasters result from
+ this, much dead code supporting the other implementation might now be
+ removed.
- *** macosx-8-4-branch merged into the mainline [Patch 602770] ***
+ * generic/tclBasic.c: Final step routing all direct evaluation forms
+ * generic/tclCompExpr.c: of the operator commands through TEBC,
+ * generic/tclCompile.h: dropping all the routines in tclMathOp.c.
+ * generic/tclMathOp.c: Still needs Engineering Manual attention.
- * generic/tcl.decls: added new macosx specific entry to stubs table.
+2006-12-11 Don Porter <dgp@users.sourceforge.net>
- * tools/genStubs.tcl: added generation of platform guards for macosx.
- This is a little more complex than it seems, because MacOS X IS "unix"
- plus a little bit, for the purposes of Tcl. BUT unfortunately, Tk uses
- "unix" to mean X11. So added platform keys for macosx (the little
- added to "unix"), "aqua" and "x11" to distinguish these for Tk.
+ * generic/tclBasic.c: Another step with all sorting operator
+ * generic/tclCompExpr.c: commands now routing through TEBC via
+ * generic/tclCompile.h: TclSortingOpCmd().
- * generic/tcl.h: added a #ifnded RESOURCE_INCLUDED so that tcl.h can
- be passed to the resource compiler.
+2006-12-08 Don Porter <dgp@users.sourceforge.net>
- * generic/tcl.h:
- * generic/tclNotify.c: added a few Notifier procs, to be able to
- modify more bits of the Tcl notifier dynamically. Required to get Mac
- OS X Tk to live on top of the Tcl Unix threaded notifier. Changes the
- size of the Tcl_NotifierProcs structure, but doesn't move any elements
- around.
+ * generic/tclBasic.c: Another step down the path of re-using
+ * generic/tclCompExpr.c: TclExecuteByteCode to implement the TIP 174
+ * generic/tclCompile.h: commands instead of using a mass of code
+ * generic/tclMathOp.c: duplication. Now all operator commands that
+ * tests/mathop.test: demand exactly one operation are implemented
+ via TclSingleOpCmd and a call to TEBC.
- * unix/tclUnixNotfy.c: moved the call to Tcl_ConditionNotify till
- AFTER we are done mucking with the pointer swap. Fixes cases where the
- thread waiting on the condition wakes & accesses the waitingListPtr
- before it gets reset, causing a hang.
+ * generic/tclCompExpr.c: Revised implementation of TclInvertOpCmd to
+ * generic/tclMathOp.c: perform a bytecode compile / execute sequence.
+ This demonstrates a path toward avoiding mountains of code duplication
+ in tclMathOp.c and tclExecute.c.
- * library/auto.tcl (tcl_findLibrary): added checking the directories
- in the tcl_pkgPath for library files on macosx to enable support of
- the standard Mac OSX library locations
+ * generic/tclCompile.h: Change TclExecuteByteCode() from static to
+ * generic/tclExecute.c: MODULE_SCOPE so all files including
+ tclCompile.h may call it.
- * unix/Makefile.in:
- * unix/configure.in:
- * unix/tcl.m4: added MAC_OSX_DIR. Added PLAT_OBJS to the OBJS: there
- are some MacOS X specific files now for Tcl, and when I get he
- resource & applescript stuff ported over, and restore support for
- FindFiles, etc, there will be a few more. Added LD_LIBRARY_PATH_VAR
- configure variable to avoid having to set all possible LD_LIBRARY_PATH
- analogues on all platforms. LD_LIBRARY_PATH_VAR is "LD_LIBRARY_PATH"
- by default, "LIBPATH" on AIX, "SHLIB_PATH" on HPUX and
- "DYLD_LIBRARY_PATH" on Mac OSX. Added configure option to package Tcl
- as a framework on Mac OSX.
-
- * macosx/tclMacOSXBundle.c (new): support for finding Tcl extension
- packaged as 'bundles' in the standard Mac OSX library locations.
-
- * unix/tclUnixInit.c: added support for findig the tcl script library
- inside Tcl packaged as a framework on Mac OSX.
-
- * macosx/Tcl.pbproj/jingham.pbxuser (new):
- * macosx/Tcl.pbproj/project.pbxproj (new): project for Apple's
- ProjectBuilder IDE.
-
- * macosx/Makefile (new): simple makefile for building the project from
- the command line via the ProjectBuilder tool 'pbxbuild'.
-
- * unix/configure:
- * generic/tclStubInit.c:
- * generic/tclPlatDecls.h: regen
+ * generic/tclMathOp.c: More revisions to make tests pass.
+ * tests/mathop.test:
-2002-08-29 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+2006-12-08 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * win/tclWinThrd.c (TclpFinalizeThreadData, TclWinFreeAllocCache):
- Applied patch for [Bug 599428] (sofer)
+ * generic/tclNamesp.c (TclTeardownNamespace): Ensure that dying
+ namespaces unstitch themselves from their referents. [Bug 1571056]
+ (NsEnsembleImplementationCmd): Silence GCC warning.
-2002-08-28 David Gravereaux <davygrvy@pobox.com>
+ * tests/mathop.test: Full tests for & | and ^ operators
- * generic/tclEnv.c:
- * unix/configure.in:
- * win/tclWinPort.h: putenv() on some systems copies the buffer rather
- than taking reference to it. This causes memory leaks and is know to
- effect mswindows (msvcrt) and NetBSD 1.5.2. This patch tests for this
- behavior and turns on -DHAVE_PUTENV_THAT_COPIES=1 when approriate.
- Thanks to David Welton for assistance. [Bug 414910]
+2006-12-08 Daniel Steffen <das@users.sourceforge.net>
- * unix/configure: regen'd
+ * library/tcltest/tcltest.tcl: use [info frame] for "-verbose line".
-2002-08-28 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+2006-12-07 Don Porter <dgp@users.sourceforge.net>
- * doc/eval.n: Added mention of list command and corrected "SEE ALSO".
+ * generic/tclCompCmds.c: Additional commits correct most
+ * generic/tclExecute.c: failing tests illustrating bugs
+ * generic/tclMathOp.c: uncovered in [Patch 1578137].
- * unix/configure.in: Cache handling of ac_cv_type_socklen_t was wrong.
- [Bug 600931] reported by John Ellson. Fixed by putting the brackets
- where they belong.
+ * generic/tclBasic.c: Biggest source of TIP 174 failures was that
+ the commands were not [namespace export]ed from the ::tcl::mathop
+ namespace. More bits from [Patch 1578137] correct that.
-2002-08-26 Miguel Sofer <msofer@users.sourceforge.net>
+ * tests/mathop.test: Commmitted several new tests from Peter Spjuth
+ found in [Patch 1578137]. Many failures now demonstrate issues to fix
+ in the TIP 174 implementation.
- * generic/tclCompCmds.c: fix for [Bug 599788] (error in element name
- causing segfault), reported by Tom Wilkason. Fixed by copying the
- tokens instead of the source string.
+2006-12-07 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
-2002-08-26 Miguel Sofer <msofer@users.sourceforge.net>
+ * tests/mathop.test: Added tests for ! ~ eq operators.
+ * generic/tclMathOp.c (TclInvertOpCmd): Add in check for non-integral
+ numeric values.
+ * generic/tclCompCmds.c (CompileCompareOpCmd): Factor out the code
+ generation for the chained comparison operators.
- * generic/tclThreadAlloc.c: small optimisation, reducing the new
- allocator's overhead.
+2006-12-07 Pat Thoyts <patthoyts@users.sourceforge.net>
-2002-08-23 Miguel Sofer <msofer@users.sourceforge.net>
+ * tests/exec.test: Fixed line endings (caused win32 problems).
- * generic/tclObj.c (USE_THREAD_ALLOC): fixed leak [Bug 597936]. Thanks
- to Zoran Vasiljevic.
+2006-12-06 Don Porter <dgp@users.sourceforge.net>
-2002-08-23 Miguel Sofer <msofer@users.sourceforge.net>
+ * generic/tclCompCmds.c: Revised and consolidated into utility
+ * tests/mathop.test: routines some of routines that compile
+ the new TIP 174 commands. This corrects some known bugs. More to come.
- * generic/tclThreadAlloc.c (USE_THREAD_ALLOC): moving objects between
- caches as a block, instead of one-by-one.
+2006-12-06 Kevin B. Kenny <kennykb@acm.org>
-2002-08-22 Miguel Sofer <msofer@users.sourceforge.net>
+ * tests/expr.test (expr-47.12): Improved error reporting in hopes of
+ having more information to pursue [Bug 1609936].
- * generic/tclBasic.c:
- * generic/tclCmdMZ.c: fix for freed memory r/w in delete traces [Bug
- 589863], patch by Hemang Lavana.
+2006-12-05 Andreas Kupries <andreask@activestate.com>
-2002-08-20 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+ TIP#291 IMPLEMENTATION
- * win/Makefile.in (CFLAGS):
- * unix/Makefile.in (MEM_DEBUG_FLAGS): Added usage of @MEM_DEBUG_FLAGS@.
- * win/configure.in:
- * unix/configure.in: Added usage of SC_ENABLE_MEMDEBUG.
- * win/tcl.m4:
- * unix/tcl.m4: Added macro SC_ENABLE_MEMDEBUG. Allows a user of
- configure to (de)activate memory validation and debugging
- (TCL_MEM_DEBUG). No need to modify the makefile anymore.
+ * generic/tclBasic.c: Define tcl_platform element for pointerSize.
+ * doc/tclvars.n:
-2002-08-20 Don Porter <dgp@users.sourceforge.net>
+ * win/Makefile.in: Added installation instructions for the platform
+ * win/makefile.vc: package. Added the platform package.
+ * win/makefile.bc:
+ * unix/Makefile.in:
- * generic/tclCkalloc.c: CONSTified MemoryCmd and CheckmemCmd.
+ * tests/platform.test:
+ * tests/safe.test:
- * README: Bumped version number to 8.4b3 to distinguish
- * generic/tcl.h: HEAD from the 8.4b2 release.
- * tools/tcl.wse.in:
- * unix/configure.in:
- * unix/tcl.spec:
- * win/README.binary:
- * win/configure.in:
+ * library/platform/platform.tcl:
+ * library/platform/shell.tcl:
+ * library/platform/pkgIndex.tcl:
- * unix/configure: autoconf
- * win/configure:
+ * doc/platform.n:
+ * doc/platform_shell.n:
- * library/http/http.tcl: Corrected installation directory of
- * library/msgcat/msgcat.tcl: the package tcltest 2.2. Added
- * library/opt/optparse.tcl: comments in other packages to remind
- * library/tcltest/tcltest.tcl: that installation directories need
- * unix/Makefile.in: updates to match increasing version
- * win/Makefile.in: numbers. [Bug 597450]
- * win/makefile.bc:
- * win/makefile.vc:
+2006-12-05 Don Porter <dgp@users.sourceforge.net>
-2002-08-19 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+ * generic/tclPkg.c: When no requirements are supplied to a
+ * tests/pkg.test: [package require $pkg] and [package unknown]
+ is invoked to find a satisfying package, pass the requirement argument
+ "0-" (which means all versions are acceptable). This permits a
+ registered [package unknown] command to call [package vsatisfies
+ $testVersion {*}$args] without any special handling of the empty $args
+ case. This fixes/avoids a bug in [::tcl::tm::UnknownHandler] that was
+ causing old TM versions to be provided in preference to newer TM
+ versions. Thanks to Julian Noble for discovering the issue.
- * unix/tclUnixTest.c (TestfilehandlerCmd): Changed
- readable/writable to the more common readable|writable.
- Fixes [Bug 596034] (lvirden)
+2006-12-04 Donal K. Fellows <dkf@users.sf.net>
-2002-08-16 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ TIP#267 IMPLEMENTATION
- * tests/fCmd.test: Added test to make sure that the cause of the
- problem is detectable with an unpatched Tcl.
- * doc/ObjectType.3: Added note on the root cause of this problem to
- the documentation, since it is possible for user code to trigger this
- sort of behaviour too.
- * generic/tclIOUtil.c (SetFsPathFromAny): Objects should only have
- their old representation deleted when we know that we are about to
- install a new one. This stops a weird TclX bug under Linux with
- certain kinds of memory debugging enabled which essentally came down
- to a double-free of a string.
+ * generic/tclIOCmd.c (Tcl_ExecObjCmd): Added -ignorestderr option,
+ * tests/exec.test, doc/exec.n: loosely from [Patch 1476191]
-2002-08-14 Miguel Sofer <msofer@users.sourceforge.net>
+2006-12-04 Don Porter <dgp@users.sourceforge.net>
- * generic/tclInt.h:
- * generic/tclObj.c: (code cleanup) factored the parts in the macros
- TclNewObj() / TclDecrRefCount() into a common part for all memory
- allocators and two new macros TclAllocObjStorage() /
- TclFreeObjStorage() that are specific to each allocator and fully
- describe the differences. Removed allocator-specific code from
- tclObj.c by using the macros.
+ * generic/tclCompExpr.c: Added implementation for the
+ CompileExprTree() routine that can produce expression bytecode
+ directly from internal structures with no need to pass through the
+ Tcl_Token array representation. Still disabled by default. #undef
+ USE_EXPR_TOKENS to try it out.
-2002-08-12 Miguel Sofer <msofer@users.sourceforge.net>
+2006-12-03 Don Porter <dgp@users.sourceforge.net>
- * generic/tclCmdMZ.c: fixing UMR in delete traces, [Bug 589863].
+ * generic/tclCompExpr.c: Added expr parsing routines that
+ produce a different set of internal structures representing the parsed
+ expression, as well as routines that go on to convert those structures
+ into the traditional Tcl_Token array format. Use of these routines is
+ currently disabled. #undef PARSE_DIRECT_EXPR_TOKENS to enable them.
+ These routines will only become really useful when more routines that
+ compile directly from the new internal structures are completed.
-2002-08-08 David Gravereaux <davygrvy@pobox.com>
+2006-12-02 Donal K. Fellows <dkf@users.sf.net>
- * tools/man2help.tcl: Fixed $argv handling bug where if -bitmap wasn't
- specified $argc was off by one.
+ * doc/file.n: Clarification of [file pathtype] docs. [Bug 1606454]
-2002-08-08 Miguel Sofer <msofer@users.sourceforge.net>
+2006-12-01 Kevin B. Kenny <kennykb@acm.org>
- * tests/uplevel.test: added 6.1 to test [uplevel] with shadowed
- commands [Bug 524383]
+ * libtommath/bn_mp_add.c: Corrected the effects of a
+ * libtommath/bn_mp_div.c: bollixed 'cvs merge' operation
+ * libtommath/bncore.c: that inadvertently committed some
+ * libtommath/tommath_class.h: half-developed code.
- * tests/subst.test: added 5.8-10 as further tests for [Bug 495207]
+ TIP#299 IMPLEMENTATION
-2002-08-08 Don Porter <dgp@users.sourceforge.net>
+ * doc/mathfunc.n: Added isqrt() function to docs
+ * generic/tclBasic.c: Added isqrt() math function (ExprIsqrtFunc)
+ * tests/expr.test (expr-47.*): Added tests for isqrt()
+ * tests/info.test (info-20.2): Added isqrt() to expected math funcs.
- * tests/README: Noted removal of defs.tcl.
+2006-12-01 Don Porter <dgp@users.sourceforge.net>
-2002-08-08 Jeff Hobbs <jeffh@ActiveState.com>
+ * tests/chan.test: Correct timing sensitivity in new test. [Bug
+ 1606860]
- * doc/lsearch.n: corrected lsearch docs to use -inline in examples.
+ TIP#287 IMPLEMENTATION
- *** 8.4b2 TAGGED FOR RELEASE ***
+ * doc/chan.n: New subcommand [chan pending].
+ * generic/tclBasic.c: Thanks to Michael Cleverly for proposal
+ * generic/tclInt.h: and implementation.
+ * generic/tclIOCmd.c:
+ * library/init.tcl:
+ * tests/chan.test:
+ * tests/ioCmd.test:
- * tests/fCmd.test:
- * tests/unixFCmd.test: updated tests for new link copy behavior.
- * generic/tclFCmd.c (CopyRenameOneFile): changed the behavior to
- follow links to endpoints and copy that file/directory instead of just
- copying the surface link. This means that trying to copy a link that
- has no endpoint (danling link) is an error. [Patch 591647] (darley)
- (CopyRenameOneFile): this is currently disabled by default until
- further issues with such behavior (like relative links) can be handled
- correctly.
+ TIP#298 IMPLEMENTATION
- * tests/README: slight wording improvements
+ * generic/tcl.decls: Tcl_GetBignumAndClearObj -> Tcl_TakeBignumFromObj
+ * generic/tclObj.c:
-2002-08-07 Miguel Sofer <msofer@users.sourceforge.net>
+ * generic/tclDecls.h: make genstubs
+ * generic/tclStubInit.c:
- * docs/BoolObj.3: added description of valid string reps for a boolean
- object [Bug 584794]
- * generic/tclObj.c: optimised Tcl_GetBooleanFromObj and
- SetBooleanFromAny to avoid parsing the string rep when it can be
- avoided [Bugs 584650, 472576]
+ * generic/tclExecute.c: Update callers.
+ * generic/tclMathOp.c:
-2002-08-07 Miguel Sofer <msofer@users.sourceforge.net>
+2006-11-30 Kevin B. Kenny <kennykb@acm.org>
- * generic/tclCompile.h:
- * generic/tclObj.c: making tclCmdNameType static [Bug 584567] (dgp)
+ * library/tzdata: Olson's tzdata2006p.
+ * libtommath/bn_mp_sqrt.c: Fixed a bug where the initial approximation
+ to the square root could be on the wrong side, causing failure of
+ convergence.
-2002-08-07 Miguel Sofer <msofer@users.sourceforge.net>
+2006-11-29 Don Porter <dgp@users.sourceforge.net>
- * generic/tclObj.c (Tcl_NewObj): added conditional code for
- USE_THREAD_ALLOC; objects allocated through Tcl_NewObj() were
- otherwise being leaked. [Bug 587488] reported by Sven Sass.
+ * generic/tclBasic.c (Tcl_AppendObjToErrorInfo): Added
+ Tcl_DecrRefCount() on the objPtr argument to plug memory leaks. This
+ makes the routine a consumer, which makes it easiest to use.
-2002-08-06 Daniel Steffen <das@users.sourceforge.net>
+2006-11-28 Andreas Kupries <andreask@activestate.com>
- * generic/tclInt.decls:
- * unix/tclUnixThrd.c: Added stubs and implementations for non-threaded
- build for the tclUnixThrd.c procs TclpReaddir, TclpLocaltime,
- TclpGmtime and TclpInetNtoa. Fixes link errors in stubbed & threaded
- extensions that include tclUnixPort.h and use any of the procs
- readdir, localtime, gmtime or inet_ntoa (e.g. TclX 8.4) [Bug 589526]
- * generic/tclIntPlatDecls.h:
- * generic/tclStubInit.c: Regen.
-
-2002-08-05 Don Porter <dgp@users.sourceforge.net>
-
- * library/tcltest/tcltest.tcl: The setup and cleanup scripts are now
- * library/tcltest/pkgIndex.tcl: skipped when a test is skipped, fixing
- * tests/tcltest.test: [Bug 589859]. Test for bug added, and
- corrected tcltest package bumped to version 2.2.
-
- * generic/tcl.decls: Restored Tcl_Concat to return (char *). Like
- * generic/tclDecls.h: Tcl_Merge, it transfers ownership of a dynamic
- * generic/tclUtil.c: allocated string to the caller.
-
-2002-08-04 Don Porter <dgp@users.sourceforge.net>
-
- * doc/CmdCmplt.3: Applied Patch 585105 to fully CONST-ify
- * doc/Concat.3: all remaining public interfaces of Tcl.
- * doc/CrtCommand.3: Notably, the parser no longer writes on
- * doc/CrtSlave.3: the string it is parsing, so it is no
- * doc/CrtTrace.3: longer necessary for Tcl_Eval() to be
- * doc/Eval.3: given a writable string. Also, the
- * doc/ExprLong.3: refactoring of the Tcl_*Var* routines
- * doc/LinkVar.3: by Miguel Sofer is included, so that the
- * doc/ParseCmd.3: "part1" argument for them no longer needs
- * doc/SetVar.3: to be writable either.
- * doc/TraceVar.3:
- * doc/UpVar.3: Compatibility support has been enhanced so
- * generic/tcl.decls: that a #define of USE_NON_CONST will remove
- * generic/tcl.h: all possible source incompatibilities with
- * generic/tclBasic.c: the 8.3 version of the header file(s).
- * generic/tclCmdMZ.c: The new #define of USE_COMPAT_CONST now does
- * generic/tclCompCmds.c:what USE_NON_CONST used to do -- disable
- * generic/tclCompExpr.c:only those new CONST's that introduce
- * generic/tclCompile.c: irreconcilable incompatibilities.
+ * generic/tclBasic.c: TIP #280 implementation.
+ * generic/tclCmdAH.c:
+ * generic/tclCmdIL.c:
+ * generic/tclCmdMZ.c:
+ * generic/tclCompCmds.c:
+ * generic/tclCompExpr.c:
+ * generic/tclCompile.c:
* generic/tclCompile.h:
- * generic/tclDecls.h: Several bugs are also fixed by this patch.
- * generic/tclEnv.c: [Bugs 584051,580433] [Patches 585105,582429]
- * generic/tclEvent.c:
- * generic/tclInt.decls:
+ * generic/tclExecute.c:
+ * generic/tclIOUtil.c:
* generic/tclInt.h:
- * generic/tclIntDecls.h:
* generic/tclInterp.c:
- * generic/tclLink.c:
+ * generic/tclNamesp.c:
* generic/tclObj.c:
- * generic/tclParse.c:
- * generic/tclParseExpr.c:
* generic/tclProc.c:
- * generic/tclTest.c:
- * generic/tclUtf.c:
- * generic/tclUtil.c:
- * generic/tclVar.c:
- * mac/tclMacTest.c:
- * tests/expr-old.test:
- * tests/parseExpr.test:
- * unix/tclUnixTest.c:
- * unix/tclXtTest.c:
- * win/tclWinTest.c:
-
-2002-08-01 Miguel Sofer <msofer@users.sourceforge.net>
-
- * generic/tclExecute.c: bugfix (reading freed memory). Testsuite
- passed on linux/i386, compile-13.1 hung on linux/alpha.
-
-2002-08-01 Miguel Sofer <msofer@users.sourceforge.net>
-
- * generic/tclExecute.c: added a reference count for the complete
- execution stack, instead of Tcl_Preserve/Tcl_Release.
+ * tests/compile.test:
+ * tests/info.test:
+ * tests/platform.test:
+ * tests/safe.test:
-2002-08-01 Mo DeJong <mdejong@users.sourceforge.net>
+2006-11-27 Kevin B. Kenny <kennykb@acm.org>
- * generic/tclCkalloc.c (TclFinalizeMemorySubsystem): Don't lock the
- ckalloc mutex before invoking the Tcl_DumpActiveMemory function since
- it also locks the same mutex. This code is only executed when "memory
- onexit filename" has been executed and Tcl is compiled with
- -DTCL_MEM_DEBUG.
+ * unix/tclUnixChan.c (TclUnixWaitForFile):
+ * tests/event.test (event-14.*): Corrected a bug where
+ TclUnixWaitForFile would present select() with the wrong mask on an
+ LP64 machine if a fd number exceeds 32. Thanks to Jean-Luc Fontaine
+ for reporting and diagnosing [Bug 1602208].
-2002-08-01 Reinhard Max <max@suse.de>
+2006-11-27 Don Porter <dgp@users.sourceforge.net>
- * win/tclWinPort.h: The windows headers don't provide socklen_t, so we
- have to do it.
+ * generic/tclExecute.c (TclIncrObj): Correct failure to detect
+ floating-point increment values. Thanks to William Coleda [Bug
+ 1602991]
-2002-07-31 Miguel Sofer <msofer@users.sourceforge.net>
+2006-11-26 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclInt.h (USE_THREAD_ALLOC): for unshared objects,
- TclDecrRefCount now frees the internal rep before the string rep -
- just like the non-macro Tcl_DecrRefCount/TclFreeObj [Bug 524802]. For
- the other allocators the fix was done on 2002-03-06.
+ * tests/mathop.test, doc/mathop.n: More bits and pieces of the TIP#174
+ implementation. Note that the test suite is not yet complete.
-2002-07-31 Miguel Sofer <msofer@users.sourceforge.net>
+2006-11-26 Daniel Steffen <das@users.sourceforge.net>
- * generic/tclInterp.c: signed/unsigned comparison warning fixed
- (Vince Darley).
+ * unix/tcl.m4 (Linux): --enable-64bit support. [Patch 1597389]
+ * unix/configure: autoconf-2.59 [Bug 1230558]
-2002-07-31 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+2006-11-25 Donal K. Fellows <dkf@users.sf.net>
- * unix/tcl.m4 (SC_BUGGY_STRTOD): Enabled caching of test results.
+ TIP#174 IMPLEMENTATION
- * unix/tcl.m4 (SC_BUGGY_STRTOD): Solaris 2.8 still has a buggy
- strtod() implementation; make sure we detect it.
+ * generic/tclMathOp.c (new file): Completed the implementation of the
+ interpreted versions of all the tcl::mathop commands. Moved to a new
+ file to make tclCompCmds.c more focused in purpose.
- * tests/expr.test (expr-22.*): Marked as non-portable because it seems
- that these tests have an annoying tendency to fail in unexpected ways.
- [Bugs 584825, 584950, 585986]
+2006-11-23 Donal K. Fellows <dkf@users.sf.net>
-2002-07-30 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+ * generic/tclCompCmds.c (Tcl*OpCmd, TclCompile*OpCmd):
+ * generic/tclBasic.c (Tcl_CreateInterp): Partial implementation of
+ TIP#174; the commands are compiled, but (mostly) not interpreted yet.
- * tests/io.test:
- * generic/tclIO.c (WriteChars): Added flag to break out of loop if
- nothing of the input is consumed at all, to prevent infinite looping
- of called with a non-UTF-8 string. Fixes [Bug 584603] partially.
- Added new test "io-60.1". Might need additional changes to Tcl_Main so
- that unprintable results are printed as binary data.
+2006-11-22 Donal K. Fellows <dkf@users.sf.net>
-2002-07-29 Mo DeJong <mdejong@users.sourceforge.net>
+ TIP#269 IMPLEMENTATION
- * unix/Makefile.in: Use CC_SEARCH_FLAGS instead of LD_SEARCH_FLAGS
- when linking with ${CC}.
- * unix/configure: Regen.
- * unix/configure.in: Don't subst CC_SEARCH_FLAGS or LD_SEARCH_FLAGS
- since this is now done in tcl.m4.
- * unix/tcl.m4 (SC_CONFIG_CFLAGS): Document and set CC_SEARCH_FLAGS
- whenever LD_SEARCH_FLAGS is set. [Patch 588290]
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd): Implementation of the [string
+ * tests/string.test (string-25.*): is list] command, based on
+ * doc/string.n: work by Joe Mistachkin, with
+ enhancements by Donal Fellows for better failindex behaviour.
-2002-07-29 Reinhard Max <max@suse.de>
+2006-11-22 Don Porter <dgp@users.sourceforge.net>
- * unix/tcl.m4 (SC_SERIAL_PORT): Fixed detection for cases when
- configure's stdin is not a tty.
+ * tools/genWinImage.tcl (removed): Removed two files used in
+ * win/README.binary (removed): production of binary distributions
+ for Windows, a task we no longer perform. [Bug 1476980]
+ * generic/tcl.h: Remove mention of win/README.binary in comment
- * unix/tclUnixPort.h:
- * generic/tclIOSock.c: Changed size_t to socklen_t in
- socket-related function calls.
+ * generic/tcl.h: Moved TCL_REG_BOSONLY #define from tcl.h to
+ * generic/tclInt.h: tclInt.h. Only know user is Expect, which
+ already #include's tclInt.h. No need to continue greater exposure.
+ [Bug 926500]
- * unix/configure.in: Added test and fallback definition
- for socklen_t.
+2006-11-20 Donal K. Fellows <dkf@users.sf.net>
- * unix/configure: generated.
+ * generic/tclBasic.c (Tcl_CreateInterp, TclHideUnsafeCommands):
+ * library/init.tcl: Refactored the [chan] command's guts so that it
+ does not use aliases to global commands, making the code more robust.
-2002-07-29 Miguel Sofer <msofer@users.sourceforge.net>
+2006-11-17 Don Porter <dgp@users.sourceforge.net>
- * generic/tclObj.c: fixed a comment
+ * generic/tclExecute.c (INST_EXPON): Corrected crash on
+ [expr 2**(1<<63)]. Was operating on cleared bignum Tcl_Obj.
- * generic/tcl.h:
- * generic/tclBasic.c:
- * generic/tclInterp.c: added the new flag TCL_EVAL_INVOKE to the
- interface of the Tcl_Eval* functions, removing the
- TCL_EVAL_NO_TRACEBACK added yesterday: alias invocations not only
- require no tracebacks, but also look up the command name in the global
- scope - see new test interp-9.4
- * tests/interp.test: added 9.3 to test for safety of aliases to hidden
- commands, 9.4 to test for correct command lookup scope.
-
-2002-07-29 Donal K. Fellows <fellowsd@cs.man.ac.uk>
-
- * generic/regc_locale.c (cclass): [[:xdigit:]] is only a defined
- concept on western characters, so should not allow any unicode digit,
- and hence number of ranges in [[:xdigit:]] is fixed.
- * tests/reg.test: Added test to detect the bug.
- * generic/regc_cvec.c (newcvec): Corrected initial size value in
- character vector structure. [Bug 578363] Many thanks to
- pvgoran@users.sf.net for tracking this down.
-
-2002-07-28 Miguel Sofer <msofer@users.sourceforge.net>
+2006-11-16 Donal K. Fellows <dkf@users.sf.net>
- * generic/tcl.h:
- * generic/tclBasic.c: added the new flag TCL_EVAL_NO_TRACEBACK to the
- interface of the Tcl_Eval* functions. Modified the error message for
- too many nested evaluations.
- * generic/tclInterp.h: changed the Alias struct to be of variable
- length and store the prefix arguments directly (instead of a pointer
- to a Tcl_Obj list). Made AliasObjCmd call Tcl_EvalObjv instead of
- TclObjInvoke - thus making aliases trigger execution traces. [Bug
- 582522]
- * tests/interp.test:
- * tests/stack.test: adapted to the new error message.
- * tests/trace.test: added tests for aliases firing the exec traces.
+ * doc/apply.n, doc/chan.n: Added examples.
-2002-07-27 Mo DeJong <mdejong@users.sourceforge.net>
+2006-11-15 Don Porter <dgp@users.sourceforge.net>
- * unix/Makefile.in: Revert fix for Tcl bug 529801 since it was
- incorrect and broke the build on other systems. Fix [Bug 587299]. Add
- MAJOR_VERSION, MINOR_VERSION, PATCH_LEVEL, SHLIB_LD_FLAGS,
- SHLIB_LD_LIBS, CC_SEARCH_FLAGS, LD_SEARCH_FLAGS, and LIB_FILE
- variables to support more generic library build/install rules.
- * unix/configure: Regen.
- * unix/configure.in: Move AC_PROG_RANLIB into tcl.m4. Move shared
- build test and setting of MAKE_LIB and MAKE_STUB_LIB into tcl.m4. Move
- subst of a number of variables into tcl.m4 where they are defined.
- * unix/tcl.m4 (SC_ENABLE_SYMBOLS, SC_CONFIG_CFLAGS):
- Subst vars where they are defined. Add MAKE_LIB, MAKE_STUB_LIB,
- INSTALL_LIB, and INSTALL_STUB_LIB rules to deal with the ugly details
- of running ranlib on static libs at build and install time. Replace
- TCL_SHLIB_LD_EXTRAS with SHLIB_LD_FLAGS and use it when building a
- shared library.
- * unix/tclConfig.sh.in: Add TCL_CC_SEARCH_FLAGS.
+ TIP#270 IMPLEMENTATION
-2002-07-26 Miguel Sofer <msofer@users.sourceforge.net>
+ * generic/tcl.decls: New public routines Tcl_ObjPrintf,
+ * generic/tclStringObj.c: Tcl_AppendObjToErrorInfo, Tcl_Format,
+ * generic/tclInt.h: Tcl_AppendLimitedToObj,
+ Tcl_AppendFormatToObj and Tcl_AppendPrintfToObj. Former internal
+ versions removed.
- * generic/tclExecute.c: fixed Tcl_Obj leak in code corresponding to
- the macro NEXT_INST_V(x, 0, 1). [Bug 587495]
+ * generic/tclDecls.h: make genstubs
+ * generic/tclStubInit.c:
-2002-07-26 Miguel Sofer <msofer@users.sourceforge.net>
+ * generic/tclBasic.c: Updated callers.
+ * generic/tclCkalloc.c:
+ * generic/tclCmdAH.c:
+ * generic/tclCmdIL.c:
+ * generic/tclCmdMZ.c:
+ * generic/tclCompExpr.c:
+ * generic/tclCompile.c:
+ * generic/tclDictObj.c:
+ * generic/tclExecute.c:
+ * generic/tclIORChan.c:
+ * generic/tclIOUtil.c:
+ * generic/tclMain.c:
+ * generic/tclNamesp.c:
+ * generic/tclObj.c:
+ * generic/tclPkg.c:
+ * generic/tclProc.c:
+ * generic/tclStrToD.c:
+ * generic/tclTimer.c:
+ * generic/tclUtil.c:
+ * unix/tclUnixFCmd.c:
- * generic/tclVar.c (TclObjLookupVar): leak fix and improved comments.
+ * tools/genStubs.tcl: Updated script to no longer produce the
+ _ANSI_ARGS_ wrapper in generated declarations. Also revised to accept
+ variadic prototypes with more than one fixed argument. (This is
+ possible since TCL_VARARGS and its limitations are no longer in use).
+ * generic/tcl.h: Some reordering so that macro definitions do
+ not interfere with the now _ANSI_ARGS_-less stub declarations.
-2002-07-26 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclDecls.h: make genstubs
+ * generic/tclIntDecls.h:
+ * generic/tclIntPlatDecls.h:
+ * generic/tclPlatDecls.h:
+ * generic/tclTomMathDecls.h:
- * generic/tclVar.c (TclLookupVar): removed early returns that
- prevented the parens from being restored. also removed goto label as
- it was not necessary.
+2006-11-15 Donal K. Fellows <dkf@users.sf.net>
-2002-07-24 Miguel Sofer <msofer@users.sourceforge.net>
+ * doc/ChnlStack.3, doc/CrtObjCmd.3, doc/GetIndex.3, doc/OpenTcp.3:
+ * doc/chan.n, doc/fconfigure.n, doc/fcopy.n, doc/foreach.n:
+ * doc/history.n, doc/http.n, doc/library.n, doc/lindex.n:
+ * doc/lrepeat.n, doc/lreverse.n, doc/pkgMkIndex.n, doc/re_syntax.n:
+ Convert \fP to \fR so that man-page scrapers have an easier time.
- * generic/tclExecute.c:
- * tests/expr-old.test: fix for erroneous error messages in [expr],
- [Bug 587140] reported by Martin Lemburg.
+2006-11-14 Don Porter <dgp@users.sourceforge.net>
-2002-07-25 Joe English <jenglish@users.sourceforge.net>
+ TIP#261 IMPLEMENTATION
- * generic/tclProc.c: fix for [Tk Bug 219218] "error handling with
- bgerror in Tk"
+ * generic/tclNamesp.c: [namespace import] with 0 arguments
+ introspects the list of imported commands.
-2002-07-24 Miguel Sofer <msofer@users.sourceforge.net>
+2006-11-13 Kevin B. Kenny <kennykb@users.sourceforge.net>
- * generic/tclExecute.c: restoring full TCL_COMPILE_DEBUG
- functionality.
+ * generic/tclThreadStorage.c (Tcl_InitThreadStorage):
+ (Tcl_FinalizeThreadStorage): Silence a compiler warning about
+ presenting a volatile pointer to 'memset'.
-2002-07-24 Don Porter <dgp@users.sourceforge.net>
+2006-11-13 Don Porter <dgp@users.sourceforge.net>
- * tests/unixInit.test: relaxed unixInit-3.1 to accept iso8859-15 as a
- valid C encoding. [Bug 575336]
+ * generic/tclIO.c: When [gets] on a binary channel needs to use
+ the "iso8859-1" encoding, save a copy of that encoding per-thread to
+ avoid repeated freeing and re-loading of it from the file system. This
+ replaces the cached copy of this encoding that the platform
+ initialization code used to keep in pre-8.5 releases.
-2002-07-24 Miguel Sofer <msofer@users.sourceforge.net>
+2006-11-13 Daniel Steffen <das@users.sourceforge.net>
- * generic/tclExecute.c: restoring the tcl_traceCompile functionality
- while I repair tcl_traceExec. The core now compiles and runs also
- under TCL_COMPILE_DEBUG, but execution in the bytecode engine can
- still not be traced.
+ * generic/tclCompExpr.c: Fix gcc warnings about 'cast to/from
+ * generic/tclEncoding.c: pointer from/to integer of different
+ * generic/tclEvent.c: size' on 64-bit platforms by casting
+ * generic/tclExecute.c: to intermediate types
+ * generic/tclHash.c: intptr_t/uintptr_t via new PTR2INT(),
+ * generic/tclIO.c: INT2PTR(), PTR2UINT() and UINT2PTR()
+ * generic/tclInt.h: macros. [Patch 1592791]
+ * generic/tclProc.c:
+ * generic/tclTest.c:
+ * generic/tclThreadStorage.c:
+ * generic/tclTimer.c:
+ * generic/tclUtil.c:
+ * unix/configure.in:
+ * unix/tclUnixChan.c:
+ * unix/tclUnixPipe.c:
+ * unix/tclUnixPort.h:
+ * unix/tclUnixTest.c:
+ * unix/tclUnixThrd.c:
-2002-07-24 Daniel Steffen <das@users.sourceforge.net>
+ * unix/configure: autoconf-2.59
+ * unix/tclConfig.h.in: autoheader-2.59
- * unix/Makefile.in:
- * unix/configure.in: corrected fix for [Bug 529801]: ranlib only
- needed for static builds on Mac OS X.
- * unix/configure: Regen.
- * unix/tclLoadDyld.c: fixed small bugs introduced by Vince,
- implemented library unloading correctly (needs OS X 10.2).
+2006-11-12 Donal K. Fellows <dkf@users.sf.net>
-2002-07-23 Joe English <jenglish@users.sourceforge.net>
+ * generic/tclInt.h, generic/tclInt.decls: Transfer TclPtrMakeUpvar and
+ TclObjLookupVar to the internal stubs table.
- * doc/OpenFileChnl.3: (Updates from Larry Virden)
- * doc/open.n:
- * doc/tclsh.1: Fix section numbers in Unix man page references.
- * doc/lset.n: In EXAMPLES section, include command to set the initial
- value used in subsequent examples.
- * doc/http.n: Package version updated to 2.4.
+2006-11-10 Daniel Steffen <das@users.sourceforge.net>
-2002-07-23 Mo DeJong <mdejong@users.sourceforge.net>
+ * tests/fCmd.test (fCmd-6.26): fix failure when env(HOME) path
+ contains symlinks.
- * unix/configure: Regen.
- * unix/tcl.m4 (SC_CONFIG_CFLAGS): Enable 64 bit compilation when using
- the native compiler on a 64 bit version of IRIX. [Bug 219220]
+ * macosx/Tcl.xcodeproj/project.pbxproj: remove tclParseExpr.c; when
+ running testsuite from inside Xcdoe, skip stack-3.1 (it only fails
+ under those circumstances).
-2002-07-23 Mo DeJong <mdejong@users.sourceforge.net>
+ * unix/tcl.m4 (Darwin): suppress linker arch warnings when building
+ universal for both 32 & 64 bit and no 64bit CoreFoundation is
+ available; sync with tk tcl.m4 change.
+ * unix/configure.in: whitespace.
+ * unix/configure: autoconf-2.59
- * unix/Makefile.in: Combine ranlib tests and avoid printing unless
- ranlib is actually run.
+2006-11-09 Don Porter <dgp@users.sourceforge.net>
-2002-07-23 Mo DeJong <mdejong@users.sourceforge.net>
+ * generic/tclParseExpr.c (removed): Moved all the code of
+ * generic/tclCompExpr.c: tclParseExpr.c into tclCompExpr.c.
+ * unix/Makefile.in: This sets the stage for expr compiling to work
+ * win/Makefile.in: directly with the full parse tree structures,
+ * win/makefile.bc: and not have to pass through the information
+ * win/makefile.vc: lossy format of an array of Tcl_Tokens.
+ * win/tcl.dsp:
- * unix/tcl.m4 (SC_PATH_X): Set XINCLUDES to "" instead of "# no
- special path needed" or "# no include files found" when x headers
- cannot be located.
+2006-11-09 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
-2002-07-22 Vince Darley <vincentdarley@users.sourceforge.net>
+ TIP#272 IMPLEMENTATION
- * generic/tclIOUtil.c: made tclNativeFilesystem static (since 07-19
- changes removed its usage elsewhere), and added comments about its
- usage.
- * generic/tclLoad.c:
- * generic/tcl.h:
- * generic/tcl.decls:
- * doc/FileSystem.3: converted last load-related ClientData parameter
- to Tcl_LoadHandle opaque structure, removing a couple of casts in the
- process.
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd): Implementation of the
+ * tests/string.test, tests/stringComp.test: [string reverse] command
+ * doc/string.n: from TIP#272.
- * generic/tclInt.h: removed tclNativeFilesystem declaration since it
- is now static again.
+ * generic/tclCmdIL.c (Tcl_LreverseObjCmd): Implementation of the
+ * generic/tclBasic.c, generic/tclInt.h: [lreverse] command from
+ * tests/cmdIL.test (cmdIL-7.*): TIP#272.
+ * doc/lreverse.n:
-2002-07-22 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+2006-11-08 Donal K. Fellows <dkf@users.sf.net>
- * tests/expr.test (expr-22.*): Added tests to help detect the
- corrected handling.
- * generic/tclExecute.c (IllegalExprOperandType): Improved error
- message generated when attempting to manipulate Inf and NaN values.
- * generic/tclParseExpr.c (GetLexeme): Allowed parser to recognise
- 'Inf' as a floating-point number. [Bug 218000]
+ * generic/tclIO.c, generic/tclPkg.c: Style & clarity rewrites.
-2002-07-21 Don Porter <dgp@users.sourceforge.net>
+2006-11-07 Andreas Kupries <andreask@activestate.com>
- * tclIOUtil.c: Silence compiler warning. [Bug 584408].
+ * unix/tclUnixFCmd.c (CopyFile): Added code to fall back to a
+ hardwired default block size should the filesystem report a bogus
+ value. [Bug 1586470]
-2002-07-19 Vince Darley <vincentdarley@users.sourceforge.net>
+2006-11-04 Don Porter <dgp@users.sourceforge.net>
- * generic/tclIOUtil.c: fix to GetFilesystemRecord
- * win/tclWinFile.c:
- * unix/tclUnixFile.c: fix to subtle problem with links shown up by
- latest tclkit builds.
+ * generic/tclStringObj.c: Changed Tcl_ObjPrintf() response to an
+ invalid format specifier string. No longer panics; now produces an
+ error message as output.
-2002-07-19 Mo DeJong <mdejong@users.sourceforge.net>
+ TIP#274 IMPLEMENTATION
- * unix/configure:
- * unix/configure.in:
- * win/configure:
- * win/configure.in: Add AC_PREREQ(2.13) in an attempt to make it more
- clear that the configure scripts must be generated with autoconf
- version 2.13. [Bug 583573]
+ * generic/tclParseExpr.c: Exponentiation operator is now right
+ * tests/expr.test: associative. [Patch 1556802]
-2002-07-19 Vince Darley <vincentdarley@users.sourceforge.net>
+2006-11-03 Miguel Sofer <msofer@users.sf.net>
- * unix/Makefile.in: fix to build on MacOS X [Bug 529801], bug report
- and fix from jcw.
+ * generic/tclBasic.c (TEOVI): fix por possible leak of a Command in
+ the presence of execution traces that delete it.
-2002-07-19 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclBasic.c (TEOVI):
+ * tests/trace.test (trace-21.11): fix for [Bug 1590232], execution
+ traces may cause a second command resolution in the wrong namespace.
+
+2006-11-03 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * tests/event.test (event-11.5): Rewrote tests to stop Tcl from
+ * tests/io.test (multiple tests): opening sockets that are
+ * tests/ioCmd.test (iocmd-15.1,16,17): reachable from outside hosts
+ * tests/iogt.test (__echo_srv__.tcl): where not necessary. This is
+ * tests/socket.test (multiple tests): noticably annoying on some
+ * tests/unixInit.test (unixInit-1.2): systems (e.g., Windows).
+
+2006-11-02 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Tcl.xcodeproj/project.pbxproj: check autoconf/autoheader exit
+ status and stop build if they fail.
+
+2006-11-02 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/ParseCmd.3, doc/Tcl.n, doc/eval.n, doc/exec.n:
+ * doc/fconfigure.n, doc/interp.n, doc/unknown.n:
+ * library/auto.tcl, library/init.tcl, library/package.tcl:
+ * library/safe.tcl, library/tm.tcl, library/msgcat/msgcat.tcl:
+ * tests/all.tcl, tests/basic.test, tests/cmdInfo.test:
+ * tests/compile.test, tests/encoding.test, tests/execute.test:
+ * tests/fCmd.test, tests/http.test, tests/init.test:
+ * tests/interp.test, tests/io.test, tests/ioUtil.test:
+ * tests/iogt.test, tests/namespace-old.test, tests/namespace.test:
+ * tests/parse.test, tests/pkg.test, tests/pkgMkIndex.test:
+ * tests/proc.test, tests/reg.test, tests/trace.test:
+ * tests/upvar.test, tests/winConsole.test, tests/winFCmd.test:
+ * tools/tclZIC.tcl:
+ * generic/tclParse.c (Tcl_ParseCommand): Replace {expand} with {*}
+ officially (TIP #293). Leave -DALLOW_EXPAND=0|1 option to keep
+ {expand} syntax for transition users. [Bug 1589629]
+
+2006-11-02 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * generic/tclBasic.c, generic/tclInterp.c, generic/tclProc.c: Silence
+ warnings from gcc over signed/unsigned and TclStackAlloc().
+ * generic/tclCmdMZ.c: Update to more compact and clearer coding style.
+
+2006-11-02 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCmdAH.c: Further revisions to produce the routines
+ * generic/tclInt.h: TclFormat() and TclAppendFormatToObj() that
+ * generic/tclNamesp.c: accept (objc, objv) arguments rather than
+ * generic/tclStringObj.c: any varargs stuff.
+
+ * generic/tclBasic.c: Further revised TclAppendPrintToObj() and
+ * generic/tclCkalloc.c: TclObjPrintf() routines to panic when unable
+ * generic/tclCmdAH.c: to complete their formatting operations,
+ * generic/tclCmdIL.c: rather than report an error message. This
+ * generic/tclCmdMZ.c: means an interp argument for error message
+ * generic/tclDictObj.c: recording is no longer needed, further
+ * generic/tclExecute.c: simplifying the interface for callers.
+ * generic/tclIORChan.c:
+ * generic/tclIOUtil.c:
+ * generic/tclInt.h:
+ * generic/tclMain.c:
+ * generic/tclNamesp.c:
+ * generic/tclParseExpr.c:
+ * generic/tclPkg.c:
+ * generic/tclProc.c:
+ * generic/tclStringObj.c:
+ * generic/tclTimer.c:
+ * generic/tclUtil.c:
+ * unix/tclUnixFCmd.c:
- * win/tclWinSerial.c (no_timeout): Made this variable static.
+2006-11-02 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * generic/tclExecute.c, generic/tclCompile.c, generic/tclBasic.c:
- * generic/tclCompile.h (builtinFuncTable, instructionTable): Added
- prefix to these symbols because they are visible outside the Tcl
- library.
+ * tests/winPipe.test (winpipe-4.[2345]): Made robust when run in
+ directory with spaces in its name.
- * generic/tclCompExpr.c (operatorTable):
- * unix/tclUnixTime.c (tmKey):
- * generic/tclIOUtil.c (theFilesystemEpoch, filesystemWantToModify,
- (filesystemIteratorsInProgress, filesystemOkToModify): Made these
- variables static.
+ * generic/tclCmdAH.c: Clean up uses of cast NULLs.
- * unix/tclUnixFile.c: Renamed nativeFilesystem to
- * win/tclWinFile.c: tclNativeFilesystem and declared
- * generic/tclIOUtil.c: it properly in tclInt.h
- * generic/tclInt.h:
+ * generic/tclInterp.c (AliasObjCmd): Added more explanatory comments.
- * generic/tclUtf.c (totalBytes): Made this array static and const.
+ * generic/tclBasic.c (TclEvalObjvInternal): Rewrote so that comments
+ are relevant and informative once more. Also made the unknown handler
+ processing use the Tcl execution stack for working space, and not the
+ general heap.
- * generic/tclParse.c (typeTable): Made this array static and const.
- (Tcl_ParseBraces): Simplified error handling case so that scans are
- only performed when needed, and flags are simpler too.
+2006-11-01 Daniel Steffen <das@users.sourceforge.net>
- * license.terms: Added AS to list of copyright holders; it's only fair
- for the current gatekeepers to be listed here!
+ * unix/tclUnixPort.h: ensure MODULE_SCOPE is defined before use, so
+ that tclPort.h can once again be included without tclInt.h.
- * tests/cmdMZ.test: Renamed constraint for clarity. [Bug 583427]
- Added tests for the [time] command, which was previously only
- indirectly tested!
+ * generic/tclEnv.c (Darwin): mark _environ symbol as unexported even
+ when MODULE_SCOPE != __private_extern__.
-2002-07-18 Vince Darley <vincentdarley@users.sourceforge.net>
+2006-10-31 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclBasic.c: Refactored and renamed the routines
+ * generic/tclCkalloc.c: TclObjPrintf, TclFormatObj, and
+ * generic/tclCmdAH.c: TclFormatToErrorInfo to a new set of routines
+ * generic/tclCmdIL.c: TclAppendPrintfToObj, TclAppendFormatToObj,
+ * generic/tclCmdMZ.c: TclObjPrintf, and TclObjFormat, with the
+ * generic/tclDictObj.c: intent of making the latter list, plus
+ * generic/tclExecute.c: TclAppendLimitedToObj and
+ * generic/tclIORChan.c: TclAppendObjToErrorInfo, public via a revised
+ * generic/tclIOUtil.c: TIP 270.
* generic/tclInt.h:
- * generic/tcl.h:
- * */*Load*.c: added comments on changes of 07/17 and replaced
- clientData with Tcl_LoadHandle in all locations.
-
- * generic/tclFCmd.c:
- * tests/fileSystem.test: fixed a 'knownBug' with 'file
- attributes ""'
- * tests/winFCmd.test:
- * tests/winPipe.test:
- * tests/fCmd.test:
- * tessts/winFile.test: added 'pcOnly' constraint to some tests to make
- for more useful 'tests skipped' log from running all tests on
- non-Windows platforms.
-
-2002-07-17 Miguel Sofer <msofer@users.sourceforge.net>
-
- * generic/tclBasic.c (CallCommandTraces): delete traces now receive
- the FQ old name of the command. [Bug 582532] (Don Porter)
+ * generic/tclMain.c:
+ * generic/tclNamesp.c:
+ * generic/tclParseExpr.c:
+ * generic/tclPkg.c:
+ * generic/tclProc.c:
+ * generic/tclStringObj.c:
+ * generic/tclTimer.c:
+ * generic/tclUtil.c:
+ * unix/tclUnixFCmd.c:
-2002-07-18 Vince Darley <vincentdarley@users.sourceforge.net>
+2006-10-31 Miguel Sofer <msofer@users.sf.net>
- * tests/ioUtil.test: added constraints to 1.4,2.4 so they don't run
- outside of tcltest. [Bugs 583276,583277]
+ * generic/tclBasic.c, generic/tcl.h, generic/tclInterp.c:
+ * generic/tclNamesp.c: removing the flag bit TCL_EVAL_NOREWRITE, the
+ last remnant of the callObjc/v fiasco. It is not needed, as it is now
+ always set and checked or'ed with TCL_EVAL_INVOKE.
-2002-07-17 Miguel Sofer <msofer@users.sourceforge.net>
+2006-10-31 Pat Thoyts <patthoyts@users.sourceforge.net>
- * generic/tclVar.c (DupParsedVarName): nasty bug fixed, reported by
- Vince Darley.
+ * win/rules.vc: Fix for [Bug 1582769] - options conflict with VC2003.
-2002-07-17 Miguel Sofer <msofer@users.sourceforge.net>
+2006-10-31 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclVar.c (TclPtrIncrVar): missing CONST in declarations,
- inconsistent with tclInt.h. Thanks to Vince Darley for reporting, boo
- to gcc for not complaining.
+ * generic/tclBasic.c, generic/tclNamesp.c, generic/tclProc.c:
+ * generic/tclInt.h: Removed the callObjc and callObjv fields from the
+ Interp structure. They did not function correctly and made other parts
+ of the core amazingly complex, resulting in a substantive change to
+ [info level] behaviour. [Bug 1587618]
+ * library/clock.tcl: Removed use of [info level 0] for calculating the
+ command name as used by the user and replace with a literal. What's
+ there now is sucky, but at least appears to be right to most users.
+ * tests/namespace.test (namespace-42.7,namespace-47.1): Reverted
+ changes to these tests.
+ * tests/info.test (info-9.11,info-9.12): Added knownBug constraint
+ since these tests require a different behaviour of [info level] than
+ is possible because of other dependencies.
-2002-07-17 Vince Darley <vincentdarley@users.sourceforge.net>
+2006-10-30 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/tclInt.h:
- * generic/tclIOUtil.c:
- * generic/tclLoadNone.c:
- * unix/tclLoadAout.c:
- * unix/tclLoadDl.c:
- * unix/tclLoadDld.c:
- * unix/tclLoadDyld.c:
- * unix/tclLoadNext.c:
- * unix/tclLoadOSF.c:
- * unix/tclLoadShl.c:
- * mac/tclMacLoad.c:
- * win/tclWinLoad.c: modified to move more functionality to the generic
- code and avoid duplication. Partial replacement of internal uses of
- clientData with opaque Tcl_LoadHandle. A little further work still
- needed, but significant changes are done.
-
-2002-07-17 D. Richard Hipp <drh@hwaci.com>
-
- * library/msgcat/msgcat.tcl: fix a comment that was causing problems
- for programs (ex: mktclapp) that embed the initialization scripts in
- strings.
-
-2002-07-17 Miguel Sofer <msofer@users.sourceforge.net>
+ * tools/tcltk-man2html.tcl (option-toc): handle any kind of options
+ defined toc section (needed for ttk docs)
- * generic/tclInt.decls:
- * generic/tclIntDecls.h:
- * generic/tclStubInit.c:
- * generic/tclVar.c: removing the now redundant functions to access
- indexed variables: Tcl(Get|Set|Incr)IndexedScalar() and
- Tcl(Get|Set|Incr)ElementOfIndexedArray().
+2006-10-30 Miguel Sofer <msofer@users.sf.net>
-2002-07-17 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclBasic.c (TEOVI): insured that the interp's callObjc/v
+ fields are restored after traces run, as they be spoiled. This was
+ causing a segfault in tcllib's profiler tests.
- * generic/tclExecute.c (TclExecuteByteCode): Minor fixes to make this
- file compile with SunPro CC...
+2006-10-30 Don Porter <dgp@users.sourceforge.net>
-2002-07-17 Miguel Sofer <msofer@users.sourceforge.net>
+ * generic/tclExecute.c (INST_MOD): Corrected improper testing of the
+ * tests/expr.test: sign of bignums when applying Tcl's
+ division rules. Thanks to Peter Spjuth. [Bug 1585704]
- * generic/tclExecute.c: modified to do variable lookup explicitly, and
- then either inlining the variable access or else calling the new
- TclPtr(Set|Get|Incr)Var functions in tclVar.c
- * generic/tclInt.h: declare some functions previously local to
- tclVar.c for usage by TEBC.
- * generic/tclVar.c: removed local declarations; moved all special
- accessor functions for indexed variables to the end of the file - they
- are unused and ready for removal, but left there for the time being as
- they are in the internal stubs table.
+2006-10-29 Miguel Sofer <msofer@users.sf.net>
- ** WARNING FOR BYTECODE MAINTAINERS **
- TCL_COMPILE_DEBUG is currently not functional; will be fixed ASAP.
+ * generic/tclNamesp.c (EnsembleImplementationCmd):
+ * tests/namespace.test (47.7-8): reverted a wrong "optimisation" that
+ completely broke snit; added two tests.
-2002-07-16 Mo DeJong <mdejong@users.sourceforge.net>
+2006-10-28 Donal K. Fellows <dkf@users.sf.net>
- * unix/Makefile.in:
- * win/Makefile.in: Add a more descriptive warning in the event `make
- genstubs` needs to be rerun.
+ * generic/tclProc.c (ObjInterpProcEx, TclObjInterpProcCore): Split the
+ core of procedures to make it easier to build procedure-like code
+ without going through horrible contortions. This is the last critical
+ component to make advanced OO systems workable as simple loadable
+ extensions. TOIPC is now in the internal stub table.
+ (MakeProcError, MakeLambdaError): Refactored ProcessProcResultCode to
+ be simpler, some of which goes to TclObjInterpProcCore, and the rest
+ of which is now in these far simpler routines which just do errorInfo
+ stack generation for different types of procedure-like entity.
+ * tests/apply.test (apply-5.1): Updated to expect the more informative
+ form of message.
-2002-07-16 Mo DeJong <mdejong@users.sourceforge.net>
+2006-10-27 Donal K. Fellows <dkf@users.sf.net>
- * unix/Makefile.in: Use dltest.marker file to keep track of when the
- dltest package is up to date. This fixes [Bug 575768] since tcltest is
- no longer linked every time.
- * unix/dltest/Makefile.in: Create ../dltest.marker after a successful
- `make all` run in dltest.
+ * generic/tclVar.c (HasLocalVars): New macro to make various bits and
+ pieces cleaner.
-2002-07-16 Mo DeJong <mdejong@users.sourceforge.net>
+ * generic/tclNamesp.c (TclSetNsPath): Expose SetNsPath() through
+ internal stubs table with semi-external name.
- * unix/configure: Regen.
- * unix/configure.in: Remove useless subst of TCL_BIN_DIR.
+ * generic/tclInt.h (CallFrame): Add a field for handling context data
+ for extensions (like object systems) that should be tied to a call
+ frame (and not a command or interpreter).
-2002-07-15 Miguel Sofer <msofer@users.sourceforge.net>
+ * generic/tclBasic.c (TclRenameCommand): Change to take CONST args;
+ they were only ever used in a constant way anyway, so this appears to
+ be a spot that was missed during TIP#27 work.
- * generic/tclVar.c: inaccurate comment fixed
+2006-10-26 Miguel Sofer <msofer@users.sf.net>
-2002-07-15 Miguel Sofer <msofer@users.sourceforge.net>
+ * generic/tclProc.c (SetLambdaFromAny): minor change, eliminate
+ redundant call to Tcl_GetString (thanks aku).
- * generic/tclBasic.c (Tcl_AddObjErrorInfo):
- * generic/tclExecute.c (TclUpdateReturnInfo):
- * generic/tclInt.h:
- * generic/tclProc.c:
- Added two Tcl_Obj to the ExecEnv structure to hold the fully qualified
- names "::errorInfo" and "::errorCode" to cache the addresses of the
- corresponding variables. The two most frequent setters of these
- variables now profit from the new variable name caching.
+ * generic/tclInterp.c (ApplyObjCmd):
+ * generic/tclNamesp.c (EnsembleImplementationCmd): replaced ckalloc
+ (heap) with TclStackAlloc (execution stack).
-2002-07-15 Miguel Sofer <msofer@users.sourceforge.net>
+2006-10-24 Miguel Sofer <msofer@users.sf.net>
- * generic/tclVar.c: refactorisation to reuse already looked-up Var
- pointers; definition of three new Tcl_Obj types to cache variable name
- parsing and lookup for later reuse; modification of internal functions
- to profit from the caching.
+ * tests/info.test (info-9.11-12): tests for [Bug 1577492]
+ * tests/apply.test (apply-4.3-5): tests for [Bug 1574835]
- * generic/tclInt.decls:
- * generic/tclInt.h:
- * generic/tclIntDecls.h:
- * generic/tclNamesp.c: adding CONST qualifiers to variable names
- passed to Tcl_FindNamespaceVar and to variable resolvers; adding CONST
- qualifier to the 'msg' argument to TclLookupVar. Needed to avoid code
- duplication in the new tclVar.c code.
+ * generic/tclProc.c (ObjInterpProcEx): disable itcl hacks for calls
+ from ApplyObjCmd (islambda==1), as they mess apply's error messages
+ [Bug 1583266]
- * tests/set-old.test:
- * tests/var.test: slight modification of error messages due to the
- modifications in the tclVar.c code.
+2006-10-23 Miguel Sofer <msofer@users.sf.net>
-2002-07-15 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclProc.c (ApplyObjCmd): fix wrong#args for apply by using
+ the ensemble rewrite engine. [Bug 1574835]
+ * generic/tclInterp.c (AliasObjCmd): previous commit missed usage of
+ TCL_EVAL_NOREWRITE for aliases.
- * tests/unixInit.test: Improved constraints to protect /tmp. [Bug
- 581403]
+ * generic/tclBasic.c (TclEvalObjvInternal): removed redundant check
+ for ensembles. [Bug 1577628]
-2002-07-15 Vince Darley <vincentdarley@users.sourceforge.net>
+ * library/clock.tcl (format, scan): corrected wrong # args messages to
+ * tests/clock.test (3.1, 34.1): make use of the new rewrite
+ capabilities of [info level]
- * tests/winFCmd.test: renamed 'win2000' and 'notWin2000' to more
- appropriate constraint names.
- * win/tclWinFile.c: updated comments to reflect 07-11 changes.
- * win/tclWinFCmd.c: made ConvertFileNameFormat static again, since no
- longer used in tclWinFile.c
- * mac/tclMacFile.c: completed TclpObjLink implementation which was
- previously lacking.
- * generic/tclIOUtil.c: comment cleanup and code speedup.
+ * generic/tcl.h: Lets TEOV update the iPtr->callObj[cv] new
+ * generic/tclBasic.c: fields, except when the flag bit
+ * generic/tclInt.h: TCL_EVAL_NOREWRITE is present. These values
+ * generic/tclNamesp.c: are used by Tcl_PushCallFrame to initialise
+ * generic/tclProc.c: the frame's obj[cv] fields, and allows
+ * tests/namespace.test: [info level] to know and use ensemble
+ rewrites. [Bug 1577492]
-2002-07-14 Don Porter <dgp@users.sourceforge.net>
+ ***POTENTIAL INCOMPATIBILITY***
+ The return value from [info level 0] on interp alias calls is changed:
+ previously returned the target command (including curried values), now
+ returns the source - what was actually called.
+
+2006-10-23 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tcl.h: Modified the Tcl call stack so there is
+ * generic/tclBasic.c: always a valid CallFrame, even at level 0
+ * generic/tclCmdIL.c: [Patch 1577278]. Most of the changes
+ * generic/tclInt.h: involve removing tests for a NULL
+ * generic/tclNamesp.c: iPtr->(var)framePtr. There is now a
+ * generic/tclObj.c: CallFrame pushed at interp creation with a
+ * generic/tclProc.c: pointer to it stored in iPtr->rootFramePtr.
+ * generic/tclTrace.c: A second unused field in Interp is
+ * generic/tclVar.c: hijacked to enable further functionality,
+ currently unused (but with several FRQs depending on it).
- * generic/tclInt.h: Removed declarations that duplicated entries
- in the (internal) stub table.
+ ***POTENTIAL INCOMPATIBILITY***
+ Any user that includes tclInt.h and needs to determine if it is
+ running at level 0 should change (iPtr->varFramePtr == NULL) to
+ (iPtr->varFramePtr == iPtr->rootFramePtr).
- * library/tcltest/tcltest.tcl: Corrected errors in handling of
- configuration options -constraints and -limitconstraints.
+2006-10-23 Don Porter <dgp@users.sourceforge.net>
- * README: Bumped HEAD to version 8.4b2 so we can
- * generic/tcl.h: distinguish it from the 8.4b1 release.
+ * README: Bump version number to 8.5a6
+ * generic/tcl.h:
* tools/tcl.wse.in:
- * unix/configure*:
+ * unix/configure.in:
* unix/tcl.spec:
* win/README.binary:
- * win/configure*:
-
-2002-07-11 Vince Darley <vincentdarley@users.sourceforge.net>
-
- * doc/file.n:
- * win/tclWinFile.c: on Win 95/98/ME the long form of the path is used
- as a normalized form. This is required because short forms are not a
- robust representation. The file normalization function has been sped
- up, but more performance gains might be possible, if speed is still an
- issue on these platforms.
-
-2002-07-11 Don Porter <dgp@users.sourceforge.net>
-
- * library/tcltest/tcltest.tcl: Corrected reaction to existing but
- false ::tcl_interactive.
-
- * doc/Hash.3: Overlooked CONST documentation update.
-
-2002-07-11 Donal K. Fellows <fellowsd@cs.man.ac.uk>
-
- * generic/tclCkalloc.c: ckalloc() and friends take the block size as
- an unsigned, so we should use %ud when reporting it in fprintf() and
- panic().
+ * win/configure.in:
-2002-07-11 Miguel Sofer <msofer@users.sourceforge.net>
+ * unix/configure: autoconf-2.59
+ * win/configure:
- * generic/tclCompile.c: now setting local vars undefined at compile
- time, instead of waiting until the proc is initialized.
- * generic/tclProc.c: use macro TclSetVarUndefined instead of directly
- setting the flag.
+2006-10-21 Miguel Sofer <msofer@users.sf.net>
-2002-07-11 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tcl.h, generic/tclHash.c: Tcl_FindHashEntry now calls
+ Tcl_CreateHashEntry with a newPtr set to NULL: this would have caused
+ a segfault previously and eliminates duplicated code. A macro has been
+ added to tcl.h (only used when TCL_PRESERVE_BINARY_COMPATABALITY is
+ not set - i.e., not by default).
- * tests/cmdAH.test: [file attr -perm] is Unix-only, so add [catch]
- when not inside a suitably-protected test.
+2006-10-20 Reinhard Max <max@tclers.tk>
-2002-07-10 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * unix/configure.in: Added autodetection for OS-supplied timezone
+ * unix/Makefile.in: files and configure switches to override the
+ * unix/configure: detected default.
- * tests/unixFCmd.test, tests/fileName.test:
- * tests/fCmd.test: Removed [exec] of Unix utilities that have
- equivalents in standard Tcl. [Bug 579268] Also simplified some of
- unixFCmd.test while I was at it.
+2006-10-20 Daniel Steffen <das@users.sourceforge.net>
-2002-07-10 Don Porter <dgp@users.sourceforge.net>
+ *** 8.5a5 TAGGED FOR RELEASE ***
- * tests/tcltest.test: Greatly reduced the number of [exec]s, using
- slave interps instead.
- * library/tcltest/tcltest.tcl: Fixed bug uncovered in the conversion
- where a message was written to stdout instead of [outputChannel].
+ * tools/tcltk-man2html.tcl: add support for alpha & beta versions to
+ useversion glob pattern. [Bug 1579941]
- * tests/basic.test: Cleaned up, constrained, and reduced the
- * tests/compile.test: amount of [exec] usage in the test suite.
- * tests/encoding.test:
- * tests/env.test:
- * tests/event.test:
- * tests/exec.test:
- * tests/io.test:
- * tests/ioCmd.test:
- * tests/regexp.test:
- * tests/regexpComp.test:
- * tests/socket.test:
- * tests/tcltest.test:
- * tests/unixInit.test:
- * tests/winDde.test:
- * tests/winPipe.test:
+2006-10-18 Don Porter <dgp@users.sourceforge.net>
-2002-07-10 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * changes: 8.5a5 release date set
- * tests/cmdAH.test: Removed [exec] of Unix utilities. [Bug 579211]
+ * doc/Encoding.3: Missing doc updates (mostly Table of
+ * doc/Ensemble.3: Contents) exposed by `make checkdoc`
+ * doc/FileSystem.3:
+ * doc/GetTime.3:
+ * doc/PkgRequire.3:
- * tests/expr.test: Added tests to make sure that this works.
- * generic/tclExecute.c (ExprCallMathFunc): Functions should also be
- able to return wide-ints. [Bug 579284]
+2006-10-17 Miguel Sofer <msofer@users.sf.net>
-2002-07-08 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+ * generic/tclInterp.c (ApplyObjCmd): fixed bad error in 2006-10-12
+ commit: interp released too early. Spotted by mistachkin.
- * tests/socket.test: Fixed [Bug 578164]. The original reason for the
- was a DNS outage while running the testsuite. Changed [info hostname]
- to 127.0.0.1 to bypass DNS, knowing that we operate on the local
- host.
+2006-10-16 Miguel Sofer <msofer@users.sf.net>
-2002-07-08 Don Porter <dgp@users.sourceforge.net>
+ * tclProc.c (SetLambdaFromAny):
+ * tests/apply.test (9.1-9.2): plugged intrep leak [Bug 1578454],
+ found by mjanssen.
- * doc/tcltest.n: Fixed incompatibility in [viewFile].
- * library/tcltest/tcltest.tcl: Corrected docs. Bumped to 2.2.1.
- * library/tcltest/pkgIndex.tcl: [Bug 578163]
+2006-10-16 Andreas Kupries <andreask@activestate.com>
-2002-07-08 Vince Darley <vincentdarley@users.sourceforge.net>
+ * generic/tclBasic.c: Moved TIP#219 cleanup to DeleteInterpProc.
- * tests/cmdAH.test:
- * tests/fCmd.test:
- * tests/fileName.test: tests which rely on 'file link' need a
- constraint so they don't run on older Windows OS. [Bug 578158]
- * generic/tclIOUtil.c:
- * generic/tcl.h:
- * generic/tclInt.h:
- * generic/tclTest.c:
- * mac/tclMacChan.c:
- * unix/tclUnixChan.c:
- * win/tclWinChan.c:
- * doc/FileSystem.3: cleaned up internal handling of
- Tcl_FSOpenFileChannel to remove duplicate code, and make writing
- external vfs's clearer and easier. No functionality change. Also
- clarify that objects with refCount zero should not be passed in to the
- Tcl_FS API, and prevent segfaults from occuring on such user errors.
- [Bug 578617]
-
-2002-07-06 Don Porter <dgp@users.sourceforge.net>
-
- * tests/pkgMkIndex.test: Constrained tests of [load] package indexing
- to those platforms where the testing shared libraries have been built.
- [Bug 578166].
-
-2002-07-05 Don Porter <dgp@users.sourceforge.net>
-
- * changes: added recent changes
-
-2002-07-05 Reinhard Max <max@suse.de>
-
- * generic/tclClock.c (FormatClock): Convert the format string to
- UTF8 before calling TclpStrftime, so that non-ASCII characters don't
- get mangled when the result string is being converted back.
- * tests/clock.test: Added a test for that.
-
-2002-07-05 Donal K. Fellows <fellowsd@cs.man.ac.uk>
-
- * unix/Makefile.in (ro-test,ddd,GDB,DDD): Created new targets to allow
- running the test suite with a read-only current directory, running
- under ddd instead of gdb, and factored out some executable names for
- broken sites (like mine) where gdb and ddd are installed with
- non-standard names...
-
- * tests/httpold.test: Altered test names to httpold-* to avoid clashes
- with http.test, and stopped tests from failing when the current
- directory is not writable...
-
- * tests/event.test: Stop these tests from failing
- * tests/ioUtil.test: when the current directory is
- * tests/regexp.test: not writable...
- * tests/regexpComp.test:
- * tests/source.test:
- * tests/unixFile.test:
- * tests/unixNotfy.test:
-
- * tests/unixFCmd.test: Trying to make these test-files
- * tests/macFCmd.test: not bomb out with an error when
- * tests/http.test: the current directory is not
- * tests/fileName.test: writable...
- * tests/env.test:
-
-2002-07-05 Jeff Hobbs <jeffh@ActiveState.com>
-
- *** 8.4b1 TAGGED FOR RELEASE ***
+2006-10-16 Daniel Steffen <das@users.sourceforge.net>
-2002-07-04 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * changes: updates for 8.5a5 release.
- * tests/cmdMZ.test (cmdMZ-1.4):
- * tests/cmdAH.test: More fixing of writable-current-dir assumption.
- [Bug 575824]
+ * unix/tclUnixThrd.c (TclpThreadGetStackSize): Darwin: fix for main
+ thread, where pthread_get_stacksize_np() returns incorrect info.
-2002-07-04 Miguel Sofer <msofer@users.sourceforge.net>
+ * macosx/GNUmakefile: don't redo prebinding of non-prebound binaires.
- * tests/basic.test: Same issue as below; fixed [Bug 575817]
+2006-10-16 Don Porter <dgp@users.sourceforge.net>
-2002-07-04 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+ * generic/tclPkg.c (ExactRequirement): Plugged memory leak. Also
+ changed Tcl_Alloc()/Tcl_Free() calls to ckalloc()/ckfree() for easier
+ memory debugging in the future. [Bug 1568373]
- * tests/socket.test:
- * tests/winPipe.test:
- * tests/pid.test: Fixed [Bug 575848]. See below for a description the
- general problem.
+ * library/tcltest/tcltest.tcl: Revise tcltest bump to 2.3a1.
+ * library/tcltest/pkgIndex.tcl: This permits more features to be
+ * unix/Makefile.in: added to tcltest before we reach version 2.3.0
+ * win/Makefile.in: best timed to match the release of Tcl 8.5.0.
+ * win/makefile.vc: This also serves as a demo of TIP 268 features
- All the bugs below are instances of the same problem: The testsuite
- assumes [pwd] = [temporaryDirectory] and writable.
+2006-10-13 Colin McCormack <coldstore@users.sf.net>
- * tests/iogt.test: Fixed [Bug 575860]
- * tests/io.test: Fixed [Bug 575862]
- * tests/exec.test:
- * tests/ioCmd.test: Fixed [Bug 575836]
+ * win/tclWinFile.c: corrected erroneous attempt to protect against
+ NULL return from Tcl_FSGetNormalizedPath per [Bug 1548263] causing
+ [Bug 1575837].
+ * win/tclWinFile.c: alfredd supplied patch to fix [Bug 1575837]
-2002-07-03 Don Porter <dgp@users.sourceforge.net>
+2006-10-13 Daniel Steffen <das@users.sourceforge.net>
- * tests/pkg1/direct1.tcl: removed
- * tests/pkg1/pkgIndex.tcl: removed
- * tests/pkgMkIndex.test: Imported auxilliary files from tests/pkg1
- into the test file pkgMkIndex.test itself. Formatting fixes.
+ * unix/tclUnixThrd.c (TclpThreadGetStackSize): on Darwin, use
+ * unix/tcl.m4: pthread_get_stacksize_np() API to get thread stack size
+ * unix/configure: autoconf-2.59
+ * unix/tclConfig.h.in: autoheader-2.59
- * unix/Makefile.in: removed tests/pkg/* from `make dist`
+2006-10-12 Miguel Sofer <msofer@users.sf.net>
- * tests/pkg/circ1.tcl: removed
- * tests/pkg/circ2.tcl: removed
- * tests/pkg/circ3.tcl: removed
- * tests/pkg/global.tcl: removed
- * tests/pkg/import.tcl: removed
- * tests/pkg/pkg1.tcl: removed
- * tests/pkg/pkg2_a.tcl: removed
- * tests/pkg/pkg2_b.tcl: removed
- * tests/pkg/pkg3.tcl: removed
- * tests/pkg/pkg4.tcl: removed
- * tests/pkg/pkg5.tcl: removed
- * tests/pkg/pkga.tcl: removed
- * tests/pkg/samename.tcl: removed
- * tests/pkg/simple.tcl: removed
- * tests/pkg/spacename.tcl: removed
- * tests/pkg/std.tcl: removed
- * tests/pkgMkIndex.test: Fixed [Bug 575857] where this test file
- expected to be able to write to [file join [testsDirectory] pkg]. Part
- of the fix was to import several auxilliary files into the test file
- itself.
+ * generic/tclInterp.c (ApplyObjCmd):
+ * tests/interp.test (interp-14.5-10): made [interp alias] use the
+ ensemble rewrite machinery to produce better error messages [Bug
+ 1576006]
- * tests/main.test: Cheap fix for [Bugs 575851, 575858]. Avoid
- * tests/tcltest.test: non-writable . by [cd [temporaryDirectory]].
+2006-10-12 David Gravereaux <davygrvy@pobox.com>
- * library/auto.tcl: Fix [tcl_findLibrary] to be sure it sets $varName
- only if a successful library script is found. [Bug 577033]
+ * win/nmakehlp.c: Replaced all wnsprintf() calls with snprintf().
+ wnsprintf was not in my shwlapi header file (VC++6)
-2002-07-03 Miguel Sofer <msofer@users.sourceforge.net>
+2006-10-11 Don Porter <dgp@users.sourceforge.net>
- * generic/tclCompCmds.c (TclCompileCatchCmd): return
- TCL_OUT_LINE_COMPILE instead of TCL_ERROR: let the failure happen at
- runtime so that it can be caught [Bug 577015].
+ * generic/tclPkg.c (Tcl_PackageRequireEx): Corrected crash when
+ argument version=NULL passed in.
-2002-07-02 Joe English <jenglish@users.sourceforge.net>
+2006-10-10 Don Porter <dgp@users.sourceforge.net>
- * doc/tcltest.n: Markup fixes, spellcheck.
+ * changes: Updates for 8.5a5 release.
-2002-07-02 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclNamespace.c (TclTeardownNamespace): After the
+ commandPathSourceList of a namespace is cleared, set the
+ commandPathSourceList to NULL so we don't try to walk the list a
+ second time, possibly after it is freed. [Bug 1566526]
+ * tests/namespace.test (namespace-51.16): Added test.
- * doc/tcltest.n: more refinements of the documentation.
+2006-10-09 Miguel Sofer <msofer@users.sf.net>
- * library/tcltest/tcltest.tcl: Added trace to be sure the stdio
- constraint is updated whenever the [interpreter] changes.
+ * doc/UpVar.3: brough the docs in accordance to the code. Ever since
+ 8.0, Tcl_UpVar(2)? accepts TCL_NAMESPACE_ONLY as a flag value, and
+ var-3.4 tests for proper behaviour. The docs only allowed 0 and
+ TCL_GLOBAL_ONLY. [Bug 1574099]
- * doc/tcltest.n: Reverted [makeFile] and [viewFile] to
- * library/tcltest/tcltest.tcl: their former behavior, and documented
- * tests/cmdAH.test: it. Corrected misspelling of hook
- * tests/event.test: procedure. Restored tests.
- * tests/http.test:
- * tests/io.test:
+2006-10-09 Miguel Sofer <msofer@users.sf.net>
- * library/tcltest/tcltest.tcl: Simplified logic of [GetMatchingFiles]
- and [GetMatchingDirectories], removing special case processing.
+ * tests/*.test: updated all tests to refer explicitly to the global
+ variables ::errorInfo, ::errorCode, ::env and ::tcl_platform: many
+ were relying on the alternative lookup in the global namespace, that
+ feature is tested specifically in namespace and variable tests.
- * doc/tcltest.n: More documentation updates. Reference sections are
- complete. Only examples need adding.
+ The modified testfiles are: apply.test, basic.test, case.test,
+ cmdIL.test, cmdMZ.test, compExpr-old.test, error.test, eval.test,
+ event.test, expr.test, fileSystem.test, for.test, http.test, if.test,
+ incr-old.test, incr.test, interp.test, io.test, ioCmd.test, load.test,
+ misc.test, namespace.test, parse.test, parseOld.test, pkg.test,
+ proc-old.test, set.test, switch.test, tcltest.test, thread.test,
+ var.test, while-old.test, while.test.
-2002-07-02 Vince Darley <vincentdarley@users.sourceforge.net>
+2006-10-06 Pat Thoyts <patthoyts@users.sourceforge.net>
- * tests/fCmd.test:
- * generic/tclCmdAH.c: clearer error msgs for 'file link', as per the
- man page.
+ * win/rules.vc: [Bug 1571954] avoid /RTCc flag with MSVC8
-2002-07-01 Joe English <jenglish@users.sourceforge.net>
+2006-10-06 Pat Thoyts <patthoyts@users.sourceforge.net>
- * doc/Access.3:
- * doc/AddErrInfo.3:
- * doc/Alloc.3:
- * doc/Backslash.3:
- * doc/CrtChannel.3:
- * doc/CrtSlave.3:
- * doc/Encoding.3:
- * doc/Eval.3:
- * doc/FileSystem.3:
- * doc/Notifier.3:
- * doc/OpenFileChnl.3:
- * doc/ParseCmd.3:
- * doc/RegExp.3:
- * doc/Tcl_Main.3:
- * doc/Thread.3:
- * doc/TraceCmd.3:
- * doc/Utf.3:
- * doc/WrongNumArgs.3:
- * doc/binary.n:
- * doc/clock.n:
- * doc/expr.n:
- * doc/fconfigure.n:
- * doc/glob.n:
- * doc/http.n:
- * doc/interp.n:
- * doc/lsearch.n:
- * doc/lset.n:
- * doc/msgcat.n:
- * doc/packagens.n:
- * doc/pkgMkIndex.n:
- * doc/registry.n:
- * doc/resource.n:
- * doc/safe.n:
- * doc/scan.n:
- * doc/tclvars.n: Spell-check, fixed typos (Updates from Larry Virden)
+ * doc/binary.n: TIP #275: Support unsigned values in binary
+ * generic/tclBinary.c: command. Tests and documentation updated.
+ * tests/binary.test:
-2002-07-01 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+2006-10-05 Andreas Kupries <andreask@activestate.com>
- * unix/tcl.m4 (SC_CONFIG_CFLAGS): Made Solaris use gcc for linking
- when building with gcc to resolve problems with undefined symbols
- being present when tcl library used with non-gcc linker at later
- stage. Symbols were compiler-generated, so it is the compiler's
- business to define them. [Bug 541181]
+ * library/tm.tcl: Fixed bug in TIP #189 implementation, now allowing
+ '_' in module names.
-2002-07-01 Don Porter <dgp@users.sourceforge.net>
+2006-10-05 Jeff Hobbs <jeffh@ActiveState.com>
- * doc/tcltest.n: more work in progress updating tcltest docs.
+ * library/http/http.tcl (http::geturl): only do geturl url rfc 3986
+ validity checking if $::http::strict is true (default true for 8.5).
+ [Bug 1560506]
- * library/tcltest/tcltest.tcl: Change [configure -match] to stop
- treating an empty list as a list of the single pattern "*". Changed
- the default value to [list *] so default operation remains the same.
+ * generic/tcl.h: note limitation on changing Tcl_UniChar size
+ * generic/tclEncoding.c (UtfToUnicodeProc, UnicodeToUtfProc):
+ * tests/encoding.test (encoding-16.1): fix alignment issues in
+ unicode <> utf conversion procs. [Bug 1122671]
- * tests/pkg/samename.tcl: restored. Needed by pkgMkIndex.test.
+2006-10-05 Miguel Sofer <msofer@users.sf.net>
- * library/tcltest/tcltest.tcl: restored writeability testing of
- -tmpdir, augmented by a special exception for the deafault value.
+ * generic/tclVar.c (Tcl_LappendObjCmd):
+ * tests/append.test(4.21-22): fix for longstanding [Bug 1570718],
+ lappending nothing to non-list. Reported by lvirden
-2002-07-01 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+2006-10-04 Kevin B. Kenny <kennykb@acm.org>
- * doc/concat.n: Documented the *real* behaviour of [concat]!
+ * tzdata/: Olson's tzdata2006m.
-2002-06-30 Don Porter <dgp@users.sourceforge.net>
+2006-10-01 Kevin B. Kenny <kennykb@acm.org>
- * doc/tcltest.n: more work in progress updating tcltest docs.
+ * tests/clock.test (clock-49.2): Removed a locale dependency that
+ caused a spurious failure in the German locale. [Bug 1567956]
- * tests/README: Updated the instructions on running and
- * tests/cmdMZ.test: adding to the test suite. Also updated
- * tests/encoding.test: several tests, mostly to correctly create
- * tests/fCmd.test: and destroy any temporary files in the
- * tests/info.test: [temporaryDirectory] of tcltest.
- * tests/interp.test:
+2006-10-01 Miguel Sofer <msofer@users.sf.net>
- * library/tcltest/tcltest.tcl: Stopped checking for writeability of
- -tmpdir value because no default directory can be guaranteed to be
- writeable.
+ * doc/Eval.3 (TclEvalObjv): added note on refCount management for the
+ elements of objv. [Bug 730244]
- * tests/autoMkindex.tcl: removed.
- * tests/pkg/samename.tcl: removed.
- * tests/pkg/magicchar.tcl: removed.
- * tests/pkg/magicchar2.tcl: removed.
- * tests/autoMkindex.test: Updated auto_mkIndex tests to use [makeFile]
- and [removeFile] so tests are done in [temporaryDirecotry] where write
- access is guaranteed.
+2006-10-01 Pat Thoyts <patthoyts@users.sourceforge.net>
- * library/tcltest/tcltest.tcl: Fixed [makeFile] and [viewFile] to
- * tests/cmdAH.test: accurately reflect a file's contents.
- * tests/event.test: Updated tests that depended on buggy
- * tests/http.test: behavior. Also added warning messages
- * tests/io.test: to "-debug 1" operations to debug test
- * tests/iogt.test: calls to (make|remove)(File|Directory).
-
- * unix/mkLinks: `make mklinks` on 6-27 commits.
+ * win/tclWinFile.c: Handle possible missing define.
-2002-06-28 Miguel Sofer <msofer@users.sourceforge.net>
+ * win/tclWinFile.c (TclpUtime): [Bug 1420432] file mtime fails for
+ * tests/cmdAH.test: directories on windows
- * generic/tclCompile.h: modified the macro TclEmitPush to not call its
- first argument repeatedly or pass it to other macros, [Bug 575194]
- reported by Peter Spjuth.
+ * tests/winFile.test: Handle Msys environment a little differently in
+ getuser function. [Bug 1567956]
-2002-06-28 Don Porter <dgp@users.sourceforge.net>
+2006-09-30 Miguel Sofer <msofer@users.sf.net>
- * docs/tcltest.n: Doc revisions in progress.
- * library/tcltest/tcltest.tcl: Corrected -testdir default value. Was
- not reliable, and disagreed with docs! Thanks to Hemang Lavana. [Bug
- 575150]
+ * generic/tclUtil.c (Tcl_SplitList): optimisation, [Patch 1344747] by
+ dgp.
-2002-06-28 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclInt.decls:
+ * generic/tclInt.h:
+ * generic/tclIntDecls.h:
+ * generic/tclObj.c:
+ * generic/tclStubInit.c: added an internal function TclObjBeingDeleted
+ to provide info as to the reason for the loss of an internal rep. [FR
+ 1512138]
- * unix/tclUnixThrd.c: Renamed the Tcl_Platform* #defines to
- * unix/tclUnixPipe.c: TclOS* because they are only used
- * unix/tclUnixFile.c: internally. Also stopped double-#def
- * unix/tclUnixFCmd.c: of TclOSlstat [Bug 566099, post-rename]
- * unix/tclUnixChan.c:
- * unix/tclUnixPort.h:
+ * generic/tclCompile.c:
+ * generic/tclHistory.c:
+ * generic/tclInt.h:
+ * generic/tclProc.c: made Tcl_RecordAndEvalObj not call "history" if
+ it has been redefined to an empty proc, in order to reduce the noise
+ when debugging [FR 1190441]. Moved TclCompileNoOp from tclProc.c to
+ tclCompile.c
- * doc/string.n: Improved documentation for [string last] along lines
- described in [Bug 574799] so it indicates that the supplied index
- marks the end of the search space.
+2006-09-28 Andreas Kupries <andreask@activestate.com>
-2002-06-27 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclPkg.c (CompareVersions): Bugfix. Check string lengths
+ * tests/pkg.test: before comparison. The shorter string is the smaller
+ number. Added testcases as well. Interestingly all existing test cases
+ for vcompare compared numbers of the same length with each other. [Bug
+ 1563836]
- * doc/dde.n: Work in progress updating the documentation
- * doc/http.n: of the packages that come bundled with
- * doc/msgcat.n: the Tcl source distribution, notably tcltest.
- * doc/registry.n:
- * doc/tcltest.n:
+2006-09-28 Miguel Sofer <msofer@users.sf.net>
- * library/tcltest/tcltest.tcl: Made sure that the TCLTEST_OPTIONS
- environment variablle configures tcltest at package load time.
+ * generic/tclIO.c (Tcl_GetsObj): added two test'n'panic guards for
+ possible NULL derefs, [Bug 1566382] and coverity #33.
-2002-06-26 Vince Darley <vincentdarley@users.sourceforge.net>
+2006-09-27 Don Porter <dgp@users.sourceforge.net>
- * tests/fileSystem.test:
- * generic/tclIOUtil.c: fix to handling of empty paths "" which are not
- claimed by any filesystem [Bug 573758]. Ensure good error messages are
- given in all cases.
- * tests/cmdAH.test:
- * unix/tclUnixFCmd.c: fix to bug reported as part of [Patch 566669].
- Thanks to Taguchi, Takeshi for the report.
+ * generic/tclExecute.c: Corrected error in INST_LSHIFT in the
+ * tests/expr.test: calculation done to determine whether a shift
+ in the (long int) type is possible. The calculation had literal value
+ "1" where it needed a value "1L" to compute the correct result. Error
+ detected via testing with the math::bigfloat package [Bug 1567222]
-2002-06-26 Reinhard Max <max@suse.de>
+ * generic/tclPkg.c (CompareVersion): Flatten strcmp() results to
+ {-1, 0, 1} to match expectations of CompareVersion() callers.
- * unix/tclUnixTime.c: Make [clock format] respect locale settings.
- * tests/clock.test: [Bug 565880]. ***POTENTIAL INCOMPATIBILITY***
+2006-09-27 Miguel Sofer <msofer@users.sf.net>
-2002-06-26 Miguel Sofer <msofer@users.sourceforge.net>
+ * generic/regc_color.c (singleton):
+ * generic/regc_cvec.c (addmcce):
+ * generic/regcomp.c (compile, dovec): the static function addmcce does
+ nothing when called with two NULL pointers; the only call is by
+ compile with two NULL pointers (regcomp.c #includes regc_cvec.c).
+ Large parts (all?) the code for mcce (multi character collating
+ element) that we do not use is ifdef'ed out with the macro
+ REGEXP_MCCE_ENABLE.
+ This silences coverity bugs 7, 16, 80
- * doc/CrtInterp.3:
- * doc/StringObj.3: clarifications by Don Porter, [Bugs 493995, 500930]
+ * generic/regc_color.c (uncolorchain):
+ * generic/regc_nfa.c (freearc): changed tests and asserts to
+ equivalent formulation, designed to avoid an explicit comparison to
+ NULL and satisfy coverity that 6 and 9 are not bugs.
-2002-06-24 Don Porter <dgp@users.sourceforge.net>
+2006-09-27 Andreas Kupries <andreask@activestate.com>
- * library/tcltest/tcltest.tcl: Corrected suppression of -verbose skip
- * tests/tcltest.test: and start by [test -output]. Also
- corrected test suite errors exposed by corrected code. [Bug 564656]
+ * tests/pkg.test: Added test for version comparison at the 32bit
+ boundary. [Bug 1563836]
-2002-06-25 Reinhard Max <max@suse.de>
+ * generic/tclPkg.c: Rewrote CompareVersion to perform string
+ comparison instead of numeric. This breaks through the 32bit limit on
+ version numbers. See code for details (handling of leading zeros,
+ signs, etc.). un-CONSTed some arguments of CompareVersions,
+ RequirementSatisfied, and AllRequirementsSatisfied. The new compare
+ modifies the string (temporary string terminators). All callers use
+ heap-allocated ver-intreps, so we are good with that. [Bug 1563836]
- * unix/tcl.m4: New macro SC_CONFIG_MANPAGES.
- * unix/configure.in: Added support for symlinks and compression
- * unix/Makefile.in: when installing the manpages. [Patch 518052]
- * unix/mkLinks.tcl: Default is still hardlinks and no compression.
+2006-09-27 Miguel Sofer <msofer@users.sf.net>
- * unix/mkLinks: generated
- * unix/configure:
+ * generic/tclFileName.c (TclGlob): added a panic for a call with
+ TCL_GLOBMODE_TAILS and pathPrefix==NULL. This would cause a segfault,
+ as found by coverity #26.
- * unix/README: Added documentation for the new features.
+2006-09-26 Kevin B. Kenny <kennykb@acm.org>
- * unix/tcl.m4 (SC_PATH_TCLCONFIG): Replaced ${exec_prefix}/lib by
- ${libdir}.
+ * doc/Encoding.3: Added covariant 'const' qualifier for the
+ * generic/tcl.decls: Tcl_EncodingType argument to
+ * generic/tclEncoding.c: Tcl_CreateEncoding. [Further TIP#27 work.]
+ * generic/tclDecls.h: Reran 'make genstubs'.
-2002-06-25 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+2006-09-26 Pat Thoyts <patthoyts@users.sourceforge.net>
- * generic/tclUtil.c (TclGetIntForIndex): Fix of critical [Bug 533364]
- generated when the index is bad and the result is a shared object. The
- T_ASTO(T_GOR, ...) idiom likely exists elsewhere though. Also removed
- some cruft that just complicated things to no advantage.
- (SetEndOffsetFromAny): Same fix, though this wasn't on the path
- excited by the bug.
+ * win/makefile.vc: Additional compiler flags and amd64 support.
+ * win/nmakehlp.c:
+ * win/rules.vc:
-2002-06-24 Don Porter <dgp@users.sourceforge.net>
+2006-09-26 Don Porter <dgp@users.sourceforge.net>
- * library/tcltest/tcltest.tcl: Implementation of TIP 101. Adds
- * tests/parseOld.test: and exports a [configure] command
- * tests/tcltest.test: from tcltest.
+ * generic/tcl.h: As 2006-09-22 commit from Donal K. Fellows
+ demonstrates, "#define NULL 0" is just wrong, and as a quotable chat
+ figure observed, "If NULL isn't defined, we're not using a C compiler"
+ Improper fallback definition of NULL removed.
-2002-06-22 Don Porter <dgp@users.sourceforge.net>
+2006-09-25 Pat Thoyts <patthoyts@users.sourceforge.net>
- * changes: updated changes file for 8.4b1 release.
+ * generic/tcl.h: More fixing which struct stat to refer to.
+ * generic/tclGetDate.y: Some casts from time_t to int required.
+ * generic/tclTimer.c: Tcl_Time structure members are longs.
+ * win/makefile.vc: Support for varying compiler options
+ * win/rules.vc: and build to platform-specific subdirs.
- * library/tcltest/tcltest.tcl: Corrections to tcltest and the
- * tests/basic.test: Tcl test suite so that a test
- * tests/cmdInfo.test: with options -constraints knownBug
- * tests/compile.test: -limitConstraints 1 only tests the
- * tests/encoding.test: knownBug tests. Mostly involves
- * tests/env.test: replacing direct access to the
- * tests/event.test: testConstraints array with calls
- * tests/exec.test: to the testConstraint command
- * tests/execute.test: (which requires tcltest version 2)
- * tests/fCmd.test:
- * tests/format.test:
- * tests/http.test:
- * tests/httpold.test:
- * tests/ioUtil.test:
- * tests/link.test:
- * tests/load.test:
- * tests/namespace.test:
- * tests/pkgMkIndex.test:
- * tests/reg.test:
- * tests/result.test:
- * tests/scan.test:
- * tests/stack.test:
+2006-09-25 Andreas Kupries <andreask@activestate.com>
-2002-06-22 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclIO.c (Tcl_StackChannel): Fixed [Bug 1564642], aka
+ coverity #51. Extended loop condition, added checking for NULL to
+ prevent seg.fault.
- * tools/tcl.wse.in (Disk Label), unix/tcl.spec (version):
- * win/README.binary, README, win/configure.in, unix/configure.in:
- * generic/tcl.h (TCL_RELEASE_*, TCL_PATCH_LEVEL): Bump to beta1.
+2006-09-25 Andreas Kupries <andreask@activestate.com>
-2002-06-21 Joe English <jenglish@users.sourceforge.net>
+ * doc/package.n: Fixed nits reported by Daniel Steffen in the TIP#268
+ changes.
- * generic/tclCompExpr.c:
- * generic/tclParseExpr.c: LogSyntaxError() should reset the
- interpreter result [Bug 550142 "Tcl_ExprObj -> abort"]
+2006-09-25 Kevin B. Kenny <kennykb@acm.org>
-2002-06-21 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclNotify.c (Tcl_DeleteEvents): Simplified the code in hopes
+ of making the invariants clearer and proving to Coverity that the
+ event queue memory is managed correctly.
- * unix/Makefile.in: Updated all package install directories to
- * win/Makefile.in: match current Major.minor versions of the
- * win/makefile.bc: packages. Added tcltest package to
- * win/makefile.vc: installation on Windows.
+2006-09-25 Donal K. Fellows <dkf@users.sf.net>
- * library/init.tcl: Corrected comments and namespace style issues.
- Thanks to Bruce Stephens. [Bug 572025]
+ * generic/tclNotify.c (Tcl_DeleteEvents): Make it clear what happens
+ when the event queue is mismanaged. [Bug 1564677], coverity bug #10.
-2002-06-21 Vince Darley <vincentdarley@users.sourceforge.net>
+2006-09-24 Miguel Sofer <msofer@users.sf.net>
- * tests/cmdAH.test: Added TIP#99 implementation of 'file
- * tests/fCmd.test: link'. Supports creation of symbolic and
- * tests/fileName.test: hard links in the native filesystems and
- * tests/fileSystem.test: in vfs's, when the individual filesystem
- * generic/tclTest.c: supports the concept.
- * generic/tclCmdAH.c:
- * generic/tclIOUtil.c:
- * generic/tcl.h:
- * generic/tcl.decls:
- * doc/FileSystem.3:
- * doc/file.n:
- * mac/tclMacFile.c:
- * unix/tclUnixFile.c:
- * win/tclWinFile.c: Also enhanced speed of 'file normalize' on Windows
+ * generic/tclParse.c (Tcl_ParseCommand): also return an error if
+ start==NULL and numBytes<0. This is coverity's bug #20
-2002-06-20 Miguel Sofer <msofer@users.sourceforge.net>
+ * generic/tclStringObj.c (STRING_SIZE): fix allocation for 0-length
+ strings. This is coverity's bugs #54-5
- * generic/tclBasic.c (TclEvalObjvInternal): fix for [Bug 571385] in
- the implementation of TIP#62 (command tracing). Vince Darley, Hemang
- Lavana & Don Porter: thanks.
+2006-09-22 Andreas Kupries <andreask@activestate.com>
-2002-06-20 Miguel Sofer <msofer@users.sourceforge.net>
+ * generic/tclInt.h: Moved TIP#268's field 'packagePrefer' to the end
+ of the structure, for better backward compatibility.
- * generic/tclExecute.c (TclCompEvalObj): clarified and simplified the
- logic for compilation/recompilation.
+2006-09-22 Andreas Kupries <andreask@activestate.com>
-2002-06-19 Joe English <jenglish@users.sourceforge.net>
+ TIP#268 IMPLEMENTATION
- * doc/file.n: Fixed indentation. No substantive changes.
+ * generic/tclDecls.h: Regenerated from tcl.decls.
+ * generic/tclStubInit.c:
-2002-06-19 Jeff Hobbs <jeffh@ActiveState.com>
+ * doc/PkgRequire.3: Documentation of extended API, extended testsuite.
+ * doc/package.n:
+ * tests/pkg.test:
- * generic/tclCmdMZ.c (Tcl_RegexpObjCmd): get the resultPtr again as
- the Tcl_ObjSetVar2 may cause the result to change.
- [Patch 558324] (watson)
+ * generic/tcl.decls: Implementation.
+ * generic/tclBasic.c:
+ * generic/tclConfig.c:
+ * generic/tclInt.h:
+ * generic/tclPkg.c:
+ * generic/tclTest.c:
+ * generic/tclTomMathInterface.c:
+ * library/init.tcl:
+ * library/package.tcl:
+ * library/tm.tcl:
-2002-06-19 Miguel Sofer <msofer@users.sourceforge.net>
+2006-09-22 Donal K. Fellows <donal.k.fellows@man.ac.uk>
- * generic/tclExecute.c (TEBC): removing unused "for(;;)" loop;
- improved comments; re-indentation.
+ * generic/tclThreadTest.c (TclCreateThread): Use NULL instead of 0 as
+ end-of-strings marker to Tcl_AppendResult; the difference matters on
+ 64-bit machines. [Bug 1562528]
-2002-06-18 Miguel Sofer <msofer@users.sourceforge.net>
+2006-09-21 Don Porter <dgp@users.sourceforge.net>
- * generic/tclExecute.c (TEBC):
- - elimination of duplicated code in the non-immediate INST_INCR
- instructions.
- - elimination of 103 (!) TclDecrRefCount macros. The different
- instructions now jump back to a common "DecrRefCount zone" at the
- top of the loop. The macro "ADJUST_PC" was replaced by two macros
- "NEXT_INST_F" and "NEXT_INST_V" that take three params
- (pcAdjustment, # of stack objects to discard, resultObjPtr handling
- flag). The only instructions that retain a TclDecrRefCount are
- INST_POP (for speed), the common code for the non-immediate
- INST_INCR, INST_FOREACH_STEP and the two INST_LSET.
+ * generic/tclUtil.c: Dropped ParseInteger() routine. TclParseNumber
+ covers the task just fine.
- The object size of tclExecute.o was reduced by approx 20% since the
- start of the consolidation drive, while making room for some peep-hole
- optimisation at runtime.
+2006-09-19 Donal K. Fellows <dkf@users.sf.net>
-2002-06-18 Miguel Sofer <msofer@users.sourceforge.net>
+ * generic/tclEvent.c (Tcl_VwaitObjCmd): Rewrite so that an exceeded
+ limit trapped in a vwait cannot cause a dangerous dangling trace.
- * generic/tclExecute.c (TEBC, INST_DONE): small bug in the panic code
- for tcl-stack corruption.
+2006-09-19 Don Porter <dgp@users.sourceforge.net>
-2002-06-17 David Gravereaux <davygrvy@pobox.com>
+ * generic/tclExecute.c (INST_EXPON): Native type overflow detection
+ * tests/expr.test: was completely broken. Falling back on use of
+ bignums for all non-trivial ** calculations until
+ native-type-constrained special cases can be done carefully and
+ correctly. [Bug 1561260]
- Trims to support the removal of RESOURCE_INCLUDED from rc scripts from
- [FRQ 565088].
+2006-09-15 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/tcl.h: moved the #ifndef RC_INVOKED start block up in the
- file. rc scripts don't need to know thread mutexes.
+ * library/http/http.tcl: Change " " -> "+" url encoding mapping
+ * library/http/pkgIndex.tcl: to " " -> "%20" as per RFC 3986.
+ * tests/http.test (http-5.1): bump http to 2.5.3
+ * unix/Makefile.in:
+ * win/Makefile.in:
- * win/tcl.rc:
- * win/tclsh.rc: removed the #define RESOURCE_INCLUDED to let the
- built-in -DRC_INVOKED to the work.
+2006-09-12 Andreas Kupries <andreask@activestate.com>
-2002-06-17 Jeff Hobbs <jeffh@ActiveState.com>
+ * unix/configure.in (HAVE_MTSAFE_GETHOST*): Modified to recognize
+ HP-UX 11.00 and beyond as having mt-safe implementations of the
+ gethost functions.
+ * unix/configure: Regenerated, using autoconf 2.59
- * doc/CrtTrace.3: Added TIP#62 implementation of command
- * doc/trace.n: execution tracing [FRQ 462580] (lavana).
- * generic/tcl.h: This includes enter/leave tracing as well
- * generic/tclBasic.c: as inter-procedure stepping.
- * generic/tclCmdMZ.c:
- * generic/tclCompile.c:
- * generic/tclExecute.c:
- * generic/tclInt.decls:
- * generic/tclInt.h:
- * generic/tclIntDecls.h:
- * generic/tclStubInit.c:
- * generic/tclVar.c:
- * tests/trace.test:
+ * unix/tclUnixCompat.c (PadBuffer): Fixed bug in calculation of the
+ increment needed to align the pointer, and added documentation
+ explaining why the macro is implemented as it is.
-2002-06-17 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+2006-09-11 Pat Thoyts <patthoyts@users.sourceforge.net>
- * win/tclWinPipe.c (BuildCommandLine): Fixed [bug 554068] ([exec] on
- windows did not treat { in filenames well.). Bug reported by Vince
- Darley <vincentdarley@users.sourceforge.net>, patch provided by Vince
- too.
+ * win/rules.vc: Updated to install http, tcltest and msgcat as
+ * win/makefile.vc: Tcl Modules (as per Makefile.in).
+ * win/makefile.vc: Added tommath_(super)class headers.
-2002-06-17 Joe English <jenglish@users.sourceforge.net>
+2006-09-11 Andreas Kupries <andreask@activestate.com>
- * generic/tcl.h: #ifdef logic for K&R C backwards compatibility
- changed to assume modern C by default. See [FRQ 565088] for full
- details.
+ * unix/Makefile.in (install-libraries): Fixed typo tcltest 2.3.9 ->
+ 2.3.0.
-2002-06-17 Don Porter <dgp@users.sourceforge.net>
+2006-09-11 Daniel Steffen <das@users.sourceforge.net>
- * doc/msgcat.n: Corrected en_UK references to en_GB. UK is not a
- country designation recognized in ISO 3166.
+ * unix/tclUnixCompat.c: make compatLock static and only declare it
+ when it will actually be used; #ifdef parts of TSD that are not always
+ needed; adjust #ifdefs to cover all possible cases; fix whitespace.
- * library/msgcat/msgcat.tcl: More Windows Registry locale codes from
- Bruno Haible.
+2006-09-11 Andreas Kupries <andreask@activestate.com>
+ * tests/msgcat.test: Bumped version in auxiliary files as well.
* doc/msgcat.n:
- * library/msgcat/msgcat.tcl:
- * library/msgcat/pkgIndex.tcl:
- * tests/msgcat.test: Revised locale initialization to interpret
- environment variable locale values according to XPG4, and to recognize
- the LC_ALL and LC_MESSAGES values over that of LANG. Also added many
- Windows Registry locale values to those recognized by msgcat. Revised
- tests and docs. Bumped to version 1.3. Thanks to Bruno Haible for the
- report and assistance crafting the solution. [Bug 525522, 525525]
-2002-06-16 Miguel Sofer <msofer@users.sourceforge.net>
+2006-09-11 Kevin B. Kenny <kennykb@acm.org>
- * generic/tclCompile.c (TclCompileTokens): a better algorithm for the
- previous bug fix.
+ * unix/Makefile.in: Bumped msgcat version to 1.4.2 to be
+ * win/Makefile.in: consistent with dgp's commits of 2006-09-10.
-2002-06-16 Miguel Sofer <msofer@users.sourceforge.net>
+2006-09-11 Don Porter <dgp@users.sourceforge.net>
- * generic/tclCompile.c (TclCompileTokens):
- * tests/compile.test: [Bug 569438] in the processing of dollar
- variables; report by Georgios Petasis.
+ * library/msgcat/msgcat.tcl: Removed some unneeded [uplevel]s.
-2002-06-16 Miguel Sofer <msofer@users.sourceforge.net>
+2006-09-10 Don Porter <dgp@users.sourceforge.net>
- * generic/tclExecute.c: bug in the consolidation of the INCR_..._STK
- instructions; the bug could not be exercised as the (faulty)
- instruction INST_INCR_ARRAY_STK was never compiled-in (related to [Bug
- 569438]).
+ * generic/tclExecute.c: Corrected INST_EXPON flaw that treated
+ * tests/expr.test: $x**1 as $x**3. [Bug 1555371]
-2002-06-14 Miguel Sofer <msofer@users.sourceforge.net>
+ * doc/tcltest.n: Bump to version tcltest 2.3.0 to
+ * library/tcltest/pkgIndex.tcl: account for new "-verbose line"
+ * library/tcltest/tcltest.tcl: feature.
+ * unix/Makefile.in:
+ * win/Makefile.in:
+ * win/makefile.bc:
+ * win/makefile.vc:
- * generic/tclExecute.c (TclExecuteByteCode): runtime peep-hole
- optimisation of variables (INST_STORE, INST_INCR) and commands
- (INST_INVOKE); faster check for the existence of a catch.
- (TclExecuteByteCode): runtime peep-hole optimisation of comparisons.
- (TclExecuteByteCode): runtime peep-hole optimisation of INST_FOREACH -
- relies on peculiarities of the code produced by the bytecode compiler.
+ * library/msgcat/msgcat.tcl: Bump to version msgcat 1.4.2 to
+ * library/msgcat/pkgIndex.tcl: account for modifications.
-2002-06-14 David Gravereaux <davygrvy@pobox.com>
+2006-09-10 Daniel Steffen <das@users.sourceforge.net>
- * win/rules.vc: The test for compiler optimizations was in error.
- Thanks goes to Roy Terry <royterry@earthlink.net> for his assistance
- with this.
+ * library/msgcat/msgcat.tcl (msgcat::Init): on Darwin, add fallback of
+ * tests/msgcat.test: default msgcat locale to
+ * unix/tclUnixInit.c (TclpSetVariables): current CFLocale
+ identifier if available (via private ::tcl::mac::locale global, set at
+ interp init when on Mac OS X 10.3 or later with CoreFoundation).
-2002-06-14 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * library/tcltest/tcltest.tcl: add 'line' verbose level: prints source
+ * doc/tcltest.n: file line information of failing tests.
- * doc/trace.n, tests/trace.test:
- * generic/tclCmdMZ.c (Tcl_TraceObjCmd,TclTraceCommandObjCmd)
- (TclTraceVariableObjCmd): Changed references to "trace list" to "trace
- info" as mandated by TIP#102.
+ * macosx/Tcl.xcodeproj/project.pbxproj: add new tclUnixCompat.c file;
+ revise tests target to use new tcltest 'line' verbose level.
-2002-06-13 Miguel Sofer <msofer@users.sourceforge.net>
+ * unix/configure.in: add descriptions to new AC_DEFINEs for MT-safe.
+ * unix/tcl.m4: add caching to new SC_TCL_* macros for MT-safe wrappers
+ * unix/configure: autoconf-2.59
+ * unix/tclConfig.h.in: autoheader-2.59
- * generic/tclExecute.c (TclExecuteByteCode): consolidated code for the
- conditional branch instructions.
+2006-09-08 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
-2002-06-13 Miguel Sofer <msofer@users.sourceforge.net>
+ * unix/tclUnixCompat.c: Added fallback to gethostbyname() and
+ gethostbyaddr() if the implementation is known to be MT-safe
+ (currently for Darwin 6 or later only).
- * generic/tclExecute.c (TclExecuteByteCode): fixed the previous
- patch - wouldn't compile with TCL_COMPILE_DEBUG set.
+ * unix/configure.in: Assume gethostbyname() and gethostbyaddr() are
+ MT-safe starting with Darwin 6 (Mac OSX 10.2).
-2002-06-13 Miguel Sofer <msofer@users.sourceforge.net>
+ * unix/configure: Regenerated with autoconf V2.59
- * generic/tclExecute.c (TclExecuteByteCode): consolidated the handling
- of exception returns to INST_INVOKE and INST_EVAL, as well as most of
- the code for INST_CONTINUE and INST_BREAK, in the new jump target
- "processExceptionReturn".
+2006-09-08 Andreas Kupries <andreask@activestate.com>
-2002-06-13 Miguel Sofer <msofer@users.sourceforge.net>
+ * unix/tclUnixCompat.c: Fixed conditions for CopyArray/CopyString, and
+ CopyHostent. Also fixed bad var names in TclpGetHostByName.
- * generic/tclExecute.c (TclExecuteByteCode): consolidated variable
- handling opcodes, replaced redundant code with some 'goto'. All
- store/append/lappend opcodes on the same data type now share the main
- code; same with incr opcodes.
- * generic/tclVar.c: added the bit TCL_TRACE_READS to the possible
- flags to Tcl_SetVar2Ex - it causes read traces to be fired prior to
- setting the variable. This is used in the core for [lappend].
+2006-09-07 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
- ***NOTE*** the usage of TCL_TRACE_READS in Tcl_(Obj)?GetVar.* is not
- documented; there, it causes the call to create the variable if it
- does not exist. The new usage in Tcl_(Obj)?SetVar.* remains
- undocumented too ...
+ * unix/tclUnixCompat.c: Added fallback to MT-unsafe library calls if
+ TCL_THREADS is not defined.
+ Fixed alignment of arrays copied by CopyArray() to be on the
+ sizeof(char *) boundary.
-2002-06-13 Vince Darley <vincentdarley@users.sourceforge.net>
+2006-09-07 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
- * tests/fCmd.test:
- * tests/winFile.test:
- * tests/fileSystem.test:
- * generic/tclTest.c:
- * generic/tclCmdAH.c:
- * generic/tclIOUtil.c:
- * doc/FileSystem.3:
- * mac/tclMacFile.c:
- * unix/tclUnixFile.c:
- * win/tclWinFile.c: fixed up further so both compiles and actually
- works with VC++ 5 or 6.
- * win/tclWinInt.h:
- * win/tclWin32Dll.c: cleaned up code and vfs tests and added tests for
- the internal changes of 2002-06-12, to see whether WinTcl on NTFS can
- coexist peacefully with links in the filesystem. Added new test
- command 'testfilelink' to enable the newer code to be tested.
- * tests/fCmd.test: (made certain tests of 'testfilelink' not run on
- unix).
+ * unix/tclUnixChan.c: Rewritten MT-safe wrappers to return ptrs to
+ * unix/tclUnixCompat.c: TSD storage making them all look like their
+ * unix/tclUnixFCmd.c: MT-unsafe pendants API-wise.
+ * unix/tclUnixPort.h:
+ * unix/tclUnixSock.c:
-2002-06-12 Miguel Sofer <msofer@users.sourceforge.net>
+2006-09-06 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
- * tclBasic.c (Tcl_DeleteTrace): fixed [Bug 568123] (thanks to
- Hemang Lavana)
+ * unix/tclUnixChan.c: Added TCL_THREADS ifdef'ed usage of MT-safe
+ * unix/tclUnixFCmd.c: calls like: getpwuid, getpwnam, getgrgid,
+ * unix/tclUnixSock.c: getgrnam, gethostbyname and gethostbyaddr.
+ * unix/tclUnixPort.h: See [Bug 999544]
+ * unix/Makefile.in:
+ * unix/configure.in:
+ * unix/tcl.m4:
+ * unix/configure: Regenerated.
-2002-06-12 Jeff Hobbs <jeffh@ActiveState.com>
+ * unix/tclUnixCompat.c: New file containing MT-safe implementation of
+ some library calls.
- * win/tclWinFile.c: corrected the symbolic link handling code to
- allow it to compile. Added real definition of REPARSE_DATA_BUFFER
- (found in winnt.h). Most of the added definitions appear to have
- correct, cross-Win-version equivalents in winnt.h and should be
- removed, but just making things "work" for now.
+2006-09-04 Don Porter <dgp@users.sourceforge.net>
-2002-06-12 Vince Darley <vincentdarley@users.sourceforge.net>
+ * generic/tclCompExpr.c: Removed much complexity that is no
+ longer needed.
- * generic/tclIOUtil.c:
- * generic/tcl.decls:
- * generic/tclDecls.h: made code for Tcl_FSNewNativePath agree with man
- pages.
+ * tests/main.text (Tcl_Main-4.4): Test corrected to not be
+ timing sensitive to the Bug 1481986 fix. [Bug 1550858]
- * doc/FileSystem.3: clarified the circumstances under which certain
- functions are called in the presence of symlinks.
+2006-09-04 Jeff Hobbs <jeffh@ActiveState.com>
- * win/tclWinFile.c:
- * win/tclWinPort.h:
- * win/tclWinInt.h:
- * win/tclWinFCmd.c: Fix for Windows to allow 'file lstat', 'file
- type', 'glob -type l', 'file copy', 'file delete', 'file normalize',
- and all VFS code to work correctly in the presence of symlinks
- (previously Tcl's behaviour was not very well defined). This also
- fixes possible serious problems in all versions of WinTcl where 'file
- delete' on a NTFS symlink could delete the original, not the symlink.
- Note: symlinks cannot yet be created in pure Tcl.
+ * doc/package.n: correct package example
-2002-06-11 Miguel Sofer <msofer@users.sourceforge.net>
+2006-08-31 Don Porter <dgp@users.sourceforge.net>
- * generic/tclBasic.c:
- * generic/tclCompCmds.c:
- * generic/tclInt.h: reverted the new compilation functions; replaced
- by a more general approach described below.
+ * generic/tclCompExpr.c: Corrected flawed logic for disabling
+ the INST_TRY_CVT_TO_NUMERIC instruction at the end of an expression
+ when function arguments contain operators. [Bug 1541274]
- * generic/tclCompCmds.c:
- * generic/tclCompile.c: made *all* compiled variable access attempts
- create an indexed variable - even get or incr without previous set.
- This allows indexed access to local variables that are created and set
- at runtime, for example by [global], [upvar], [variable], [regexp],
- [regsub].
+ * tests/expr-old.test: The remaining failing tests reported in
+ * tests/expr.test: [Bug 1381715] are all new in Tcl 8.5, so
+ there's really no issue of compatibility with Tcl 8.4 result to deal
+ with. Fixed by updating tests to expect 8.5 results.
-2002-06-11 Miguel Sofer <msofer@users.sourceforge.net>
+2006-08-29 Don Porter <dgp@users.sourceforge.net>
- * doc/global.n:
- * doc/info.n:
- * test/info.test:
- * generic/tclCmdIL.c: fix for [Bug 567386], [info locals] was
- reporting some linked variables.
+ * generic/tclParseExpr.c: Dropped the old expr parser.
- * generic/tclBasic.c:
- * generic/tclCompCmds.c:
- * generic/tclInt.h: added compile functions for [global], [variable]
- and [upvar]. They just declare the new local variables, the commands
- themselves are not compiled-in. This gives a notably faster read
- access to these linked variables.
+2006-08-30 Jeff Hobbs <jeffh@ActiveState.com>
-2002-06-11 Miguel Sofer <msofer@users.sourceforge.net>
+ * generic/tclBasic.c (Tcl_CreateInterp): init iPtr->threadId
- * generic/tclExecute.c: optimised algorithm for exception range
- lookup; part of [Patch 453709].
+ * win/tclWinChan.c [Bug 819667] Improve logic for identifying COM
+ ports.
-2002-06-10 Vince Darley <vincentdarley@users.sourceforge.net>
+ * generic/tclIOGT.c (ExecuteCallback):
+ * generic/tclPkg.c (Tcl_PkgRequireEx): replace Tcl_GlobalEval(Obj)
+ with more efficient Tcl_Eval(Obj)Ex
- * unix/tclUnixFCmd.c: fixed [Bug 566669]
- * generic/tclIOUtil.c: improved and sped up handling of native paths
- (duplication and conversion to normalized paths), particularly on
- Windows.
- * modified part of above commit, due to problems on Linux. Will
- re-examine bug report and evaluate more closely.
+ * unix/Makefile.in (valgrindshell): add valgrindshell target and
+ update default VALGRINDARGS. User can override, or add to it with
+ VALGRIND_OPTS env var.
-2002-06-07 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclFileName.c (DoGlob): match incrs with decrs.
- * tests/tcltest.test: More corrections to test suite so that tests of
- failing [test]s don't show up themselves as failing tests.
+2006-08-29 Don Porter <dgp@users.sourceforge.net>
-2002-06-07 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclParseExpr.c: Use the "parent" field of orphan
+ ExprNodes to store the closure of left pointers. This lets us avoid
+ repeated re-scanning leftward for the left boundary of subexpressions,
+ which in worst case led to near O(N^2) runtime.
- * generic/tclExecute.c: Tidied up headers in relation to float.h to
- cut the cruft and ensure DBL_MAX is defined since doubles seem to be
- the same size everywhere; if the assumption isn't true, the variant
- platforms had better have run configure...
+2006-08-29 Joe Mistachkin <joe@mistachkin.com>
- * unix/tclUnixPort.h (EOVERFLOW): Added code to define it if it wasn't
- previously defined. Also some other general tidying and adding of
- comments. [Bugs 563122, 564595]
- * compat/tclErrno.h: Added definition for EOVERFLOW copied from
- Solaris headers; I've been unable to find any uses of EFTYPE, which
- was the error code previously occupying the slot, in Tcl, or any
- definition of it in the Solaris headers.
+ * unix/tclUnixInit.c: Fixed the issue (typo) that was causing
+ * unix/tclUnixThrd.c (TclpThreadGetStackSize): stack.test to fail on
+ FreeBSD (and possibly other Unix platforms).
-2002-06-06 Mo DeJong <mdejong@users.sourceforge.net>
+2006-08-29 Colin McCormack <coldstore@users.sourceforge.net>
- * unix/dltest/Makefile.in: Remove hard coded CFLAGS=-g and add
- CFLAGS_DEBUG, CFLAGS_OPTIMIZE, and CFLAGS_DEFAULT varaibles. [Bug
- 565488]
+ * generic/tclIOUtil.c: Added test for NULL return from
+ * generic/tclPathObj.c: Tcl_FSGetNormalizedPath which was causing
+ * unix/tclUnixFile.c: segv's per [Bug 1548263]
+ * win/tclWinFCmd.c:
+ * win/tclWinFile.c:
-2002-06-06 Don Porter <dgp@users.sourceforge.net>
+2006-08-28 Kevin B. Kenny <kennykb@acm.org>
- * tests/tcltest.test: Corrections to test suite so that tests of
- failing [test]s don't show up themselves as failing tests.
+ * library/tzdata/America/Havana: Regenerated from Olson's
+ * library/tzdata/America/Tegucigalpa: tzdata2006k.
+ * library/tzdata/Asia/Gaza:
- * tests/io.test: Fixed up namespace variable resolution issues
- revealed by running test suite with "-singleproc 1".
+2006-08-28 Don Porter <dgp@users.sourceforge.net>
- * doc/tcltest.n:
- * library/tcltest/tcltest.tcl:
- * tests/tcltest.test: Several updates to tcltest.
- 1) changed to lazy initialization of test constraints
- 2) deprecated [initConstraintsHook]
- 3) repaired badly broken [limitConstraints].
- 4) deprecated [threadReap] and [mainThread]
- [Patch 512214, Bug 558742, Bug 461000, Bug 534903]
+ * generic/tclStringObj.c: Revised ObjPrintfVA to take care to
+ * generic/tclParseExpr.c: copy only whole characters when doing
+ %s formatting. This relieves callers of TclObjPrintf() and
+ TclFormatToErrorInfo() from needing to fix arguments to character
+ boundaries. Tcl_ParseExpr() simplified by taking advantage. [Bug
+ 1547786]
-2002-06-06 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tclStringObj.c: Corrected TclFormatObj's failure to
+ count up the number of arguments required by examining the format
+ string. [Bug 1547681]
- * unix/tclUnixThrd.c (TclpReaddir, TclpLocaltime, TclpGmtime):
- added mutex wrapped calls to readdir, localtime & gmtime in case their
- thread-safe *_r counterparts are not available.
- * unix/tcl.m4: added configure check for readdir_r
- * unix/tcl.m4 (Darwin): set TCL_DEFAULT_ENCODING to utf-8 on MacOSX
- (where posix file apis expect utf-8, not iso8859-1).
- * unix/configure: regen
- * unix/Makefile.in: set DYLD_LIBRARY_PATH in parallel to
- LD_LIBRARY_PATH for MacOSX dynamic linker.
- * generic/tclEnv.c (TclSetEnv): fix env var setting on MacOSX. Adapted
- from [Patch 524352] (jkbonfield).
+2006-08-27 Joe Mistachkin <joe@mistachkin.com>
-2002-06-05 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclClock.c (ClockClicksObjCmd): Fix nested macro breakage
+ with TCL_MEM_DEBUG enabled. [Bug 1547662]
- * doc/Tcl_Main.3: Documented $tcl_rcFileName and added more
- clarifications about the intended use of Tcl_Main(). [Bug 505651]
+2006-08-26 Miguel Sofer <msofer@users.sf.net>
-2002-06-05 Daniel Steffen <das@users.sourceforge.net>
+ * doc/namespace.n:
+ * generic/tclNamesp.c:
+ * tests/upvar.test: bugfix, docs clarification and new tests for
+ [namespace upvar] as follow up to [Bug 1546833], reported by Will
+ Duquette.
- * generic/tclFileName.c (TclGlob): mac specific fix to recent changes
- in 'glob -tails' handling.
- * mac/tclMacPort.h:
- * mac/tclMacChan.c: fixed TIP#91 bustage.
- * mac/tclMacResource.c (Tcl_MacConvertTextResource): added utf
- conversion of text resource contents.
- * tests/macFCmd.test (macFCmd-1.2): allow CWIE creator.
+2006-08-24 Kevin B. Kenny <kennykb@acm.org>
-2002-06-04 Don Porter <dgp@users.sourceforge.net>
+ * library/tzdata: Regenerated, including several new files, from
+ Olson's tzdata2006j.
+ * library/clock.tcl:
+ * tests/clock.test: Removed an early testing hack that allowed loading
+ 'registry' from the build tree rather than an installed one. This is a
+ workaround for [Bug 15232730], which remains open because it's a
+ symptom of a deeper underlying problem.
- * library/tcltest/tcltest.tcl:
- * tests/init.test:
- * tests/tcltest.test: Added more TIP 85 tests from Arjen Markus.
- Converted tcltest.test to use a private namespace. Fixed bugs in
- [tcltest::Eval] revealed by calling [tcltest::test] from a non-global
- namespace, and namespace errors in init.test.
+2006-08-23 Don Porter <dgp@users.sourceforge.net>
-2002-06-04 Mo DeJong <mdejong@users.sourceforge.net>
+ * generic/tclParseExpr.c: Minimal collection of new tests
+ * tests/parseExpr.test: testing the error messages of the new
+ expr parser. Several bug fixes and code simplifications that appeared
+ during that effort.
- * win/README: Update msys+mingw URL.
+2006-08-21 Don Porter <dgp@users.sourceforge.net>
-2002-06-03 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclIOUtil.c: Revisions to complete the thread finalization
+ of the cwdPathPtr. [Bug 1536142]
- * doc/tcltest.n:
- * library/tcltest/tcltest.tcl:
- * library/tcltest/pkgIndex.tcl:
- * tests/tcltest.test: Implementation of TIP 85. Allows tcltest users
- to add new legal values of the -match option to [test], associating
- each with a Tcl command that does the matching of expected results
- with actual results of tests. Thanks to Arjen Markus. => tcltest 2.1
- [Patch 521362]
+ * generic/tclParseExpr.c: Revised mistaken call to
+ TclCheckBadOctal(), so both [expr 08] and [expr 08z] have same
+ additional info in error message.
-2002-06-03 Miguel Sofer <msofer@users.sourceforge.net>
+ * tests/compExpr-old.test: Update existing tests to not fail with
+ * tests/compExpr.test: the new expr parser.
+ * tests/compile.test:
+ * tests/expr-old.test:
+ * tests/expr.test:
+ * tests/for.test:
+ * tests/if.test:
+ * tests/parseExpr.test:
+ * tests/while.test:
- * doc/namespace.n: added description of [namepace forget] behaviour
- for unqualified patterns [Bug 559268]
+2006-08-21 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
-2002-06-03 Miguel Sofer <msofer@users.sourceforge.net>
+ * win/Makefile.in (gdb): Make this target work so that debugging an
+ msys build is possible.
- * generic/tclExecute.c: reverting an accidental modification in the
- last commit.
+2006-08-21 Daniel Steffen <das@users.sourceforge.net>
-2002-06-03 Miguel Sofer <msofer@users.sourceforge.net>
+ * macosx/tclMacOSXNotify.c (Tcl_WaitForEvent): if the run loop is
+ already running (e.g. if Tcl_WaitForEvent was called recursively),
+ re-run it in a custom run loop mode containing only the source for the
+ notifier thread, otherwise wakeups from other sources added to the
+ common run loop modes might get lost.
- * doc/Tcl.n: clarify the empty variable name issue ([Bug 549285]
- reported by Tom Krehbiel, patch by Don Porter).
+ * unix/tclUnixNotfy.c (Tcl_WaitForEvent): on 64-bit Darwin,
+ pthread_cond_timedwait() appears to have a bug that causes it to wait
+ forever when passed an absolute time which has already been exceeded
+ by the system time; as a workaround, when given a very brief timeout,
+ just do a poll on that platform. [Bug 1457797]
-2002-05-31 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclClock.c (ClockClicksObjCmd): add support for Darwin
+ * generic/tclCmdMZ.c (Tcl_TimeObjCmd): nanosecond resolution timer
+ * generic/tclInt.h: to [clock clicks] and [time]
+ * unix/configure.in (Darwin): when TCL_WIDE_CLICKS defined
+ * unix/tclUnixTime.c (TclpGetWideClicks, TclpWideClicksToNanoseconds):
+ * unix/configure: autoconf-2.59
+ * unix/tclConfig.h.in: autoheader-2.59
- * library/package.tcl: Fixed leak of slave interp in [pkg_mkIndex].
- Thanks to Helmut for report. [Bug 550534]
+ * unix/tclUnixPort.h (Darwin): override potentially faulty configure
+ detection of termios availability in all cases, since termios is known
+ to be present on all Mac OS X releases since 10.0. [Bug 497147]
- * tests/io.test:
- * tests/main.test: Use the "stdio" constraint to control whether an
- [open "|[interpreter]"] is attempted.
-
- * generic/tclExecute.c (TclMathInProgress,TclExecuteByteCode
- (ExprCallMathFunc):
- * generic/tclInt.h (TclMathInProgress):
- * unix/Makefile.in (tclMtherr.*):
- * unix/configure.in (NEED_MATHERR):
- * unix/tclAppInit.c (matherr):
- * unix/tclMtherr.c (removed file):
- * win/tclWinMtherr.c (_matherr): Removed internal routine
- TclMathInProgress and Unix implementation of matherr(). These are now
- obsolete, dealing with very old versions of the C math library.
- Windows version is retained in case Borland compilers require it, but
- it is inactive. Thanks to Joe English. [Bug 474335, Patch 555635]
- * unix/configure: regen
-
-2002-05-30 Miguel Sofer <msofer@users.sourceforge.net>
+2006-08-18 Daniel Steffen <das@users.sourceforge.net>
- * generic/tclCompExpr.c:
- * generic/tclCompile.c:
- * generic/tclCompile.h: removed exprIsJustVarRef and
- exprIsComparison from the ExprInfo and CompileEnv structs. These were
- set, but not used since dec 1999 [Bug 562383].
+ * unix/tcl.m4 (Darwin): add support for --enable-64bit on x86_64, for
+ universal builds including x86_64, for 64-bit CoreFoundation on
+ Leopard and for use of -mmacosx-version-min instead of
+ MACOSX_DEPLOYMENT_TARGET
+ * unix/configure: autoconf-2.59
+ * unix/tclConfig.h.in: autoheader-2.59
-2002-05-30 Vince Darley <vincentdarley@users.sourceforge.net>
+ * generic/tcl.h: add fixes for building on Leopard and
+ * unix/tclUnixPort.h: support for 64-bit CoreFoundation on Leopard
+ * macosx/tclMacOSXFCmd.c:
- * generic/tclFileName.c (TclGlob): fix to longstanding 'knownBug' in
- fileName tests 15.2-15.4, and fix to a new Tcl 8.4 bug in certain uses
- of 'glob -tails'.
- * tests/fileName.test: removed 'knownBug' flag from some tests, added
- some new tests for above bugs.
+ * unix/tclUnixPort.h: on Darwin x86_64, disable use of vfork as it
+ causes execve to fail intermittently. (rdar://4685553)
-2002-05-29 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclTomMath.h: on Darwin 64-bit, for now disable use of
+ 128-bit arithmetic through __attribute__ ((mode(TI))), as it leads to
+ link errors due to missing fallbacks. (rdar://4685527)
- * unix/configure: regen'ed
- * unix/configure.in: replaced bigendian check with autoconf standard
- AC_C_BIG_ENDIAN, which defined WORDS_BIGENDIAN on bigendian systems.
- * generic/tclUtf.c (Tcl_UniCharNcmp):
- * generic/tclInt.h (TclUniCharNcmp): use WORDS_BIGENDIAN instead of
- TCL_OPTIMIZE_UNICODE_COMPARE to enable memcmp alternative.
+ * macosx/Tcl.xcodeproj/project.pbxproj: add x86_64 to universal build,
+ switch native release targets to use DWARF with dSYM, Xcode 3.0
+ changes
+ * macosx/README: updates for x86_64 and Xcode 2.4.
- * generic/tclExecute.c (TclExecuteByteCode INST_STR_CMP):
- * generic/tclCmdMZ.c (Tcl_StringObjCmd): changed the case for choosing
- the Tcl_UniCharNcmp compare to when both objs are of StringType, as
- benchmarks show that is the optimal check (both bigendian and
- littleendian systems).
+ * macosx/Tcl.xcodeproj/default.pbxuser: add test suite target that
+ * macosx/Tcl.xcodeproj/project.pbxproj: runs the tcl test suite at
+ build time and shows clickable test suite errors in the GUI build
+ window.
-2002-05-29 Don Porter <dgp@users.sourceforge.net>
+ * tests/macOSXFCmd.test: fix use of deprecated resource fork paths.
- * generic/tclMain.c: Removed "dummy" reference to Tcl_LinkVar. It is
- no longer needed since Tcl_Main() now actually calls Tcl_LinkVar().
- Thanks to Joe English for pointing that out.
+ * unix/tclUnixInit.c (TclpInitLibraryPath): move code that is only
+ needed when TCL_LIBRARY is defined to run only in that case.
-2002-05-29 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclLink.c (LinkTraceProc): fix 64-bit signed-with-unsigned
+ comparison warning from gcc4 -Wextra.
- * generic/tclExecute.c (TclExecuteByteCode):
- * generic/tclCmdMZ.c (Tcl_StringObjCmd): Use the macro version.
- * generic/tclInt.h (TclUniCharNcmp): Optimised still further with a
- macro for use in sensitive places like tclExecute.c
+ * unix/tclUnixChan.c (TclUnixWaitForFile): with timeout < 0, if
+ select() returns early (e.g. due to a signal), call it again instead
+ of returning a timeout result. Fixes intermittent event-13.8 failures.
- * generic/tclUtf.c (Tcl_UniCharNcmp): Use new flag to figure out when
- we can use an optimal comparison scheme, and default to the old scheme
- in other cases which is at least safe.
- * unix/configure.in (TCL_OPTIMIZE_UNICODE_COMPARE): New optional flag
- that indicates when we can use memcmp() to compare Unicode strings
- (i.e. when the high-byte of a Tcl_UniChar precedes the low-byte.)
+2006-08-17 Don Porter <dgp@users.sourceforge.net>
-2002-05-29 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclCompile.c: Revised the new set of expression
+ * generic/tclParseExpr.c: parse error messages.
- * generic/tclInt.decls:
- * generic/tclIntDecls.h:
- * generic/tclStubInit.c:
- * generic/tclUtf.c: added TclpUtfNcmp2 private command that mirrors
- Tcl_UtfNcmp, but takes n in bytes, not utf-8 chars. This provides a
- faster alternative for comparing utf strings internally.
- (Tcl_UniCharNcmp, Tcl_UniCharNcasecmp): removed the explicit end of
- string check as it wasn't correct for the function (by doc and logic).
-
- * generic/tclCmdMZ.c (Tcl_StringObjCmd): reworked the string equal
- comparison code to use TclpUtfNcmp2 as well as short-circuit for equal
- objects or unequal length strings in the equal case. Removed the use
- of goto and streamlined the other parts.
-
- * generic/tclExecute.c (TclExecuteByteCode): added check for object
- equality in the comparison instructions. Added short-circuit for !=
- length strings in INST_EQ, INST_NEQ and INST_STR_CMP. Reworked
- INST_STR_CMP to use TclpUtfNcmp2 where appropriate, and only use
- Tcl_UniCharNcmp when at least one of the objects is a Unicode obj with
- no utf bytes.
-
- * generic/tclCompCmds.c (TclCompileStringCmd): removed error creation
- in code that no longer throws an error.
+2006-08-16 Don Porter <dgp@users.sourceforge.net>
- * tests/string.test:
- * tests/stringComp.test: added more string comparison checks.
+ * generic/tclParseExpr.c: Replace PrecedenceOf() function with
+ prec[] static array.
- * tests/clock.test: better qualified 9.1 constraint check for %s.
+2006-08-14 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
-2002-05-28 Jeff Hobbs <jeffh@ActiveState.com>
+ * library/clock.tcl (::tcl::clock::add): Added missing braces to
+ clockval validation code. Pointed out on comp.lang.tcl.
- * generic/tclThreadAlloc.c (TclpRealloc, TclpFree): protect against
- the case when NULL is based.
+2006-08-11 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * tests/clock.test: added clock-9.1
- * compat/strftime.c:
- * generic/tclClock.c:
- * generic/tclInt.decls:
- * generic/tclIntDecls.h:
- * unix/tclUnixTime.c: fix for Windows msvcrt mem leak caused by using
- an env(TZ) setting trick for in clock format -gmt 1. This also makes
- %s seem to work correctly with -gmt 1 as well as making it a lot
- faster by avoid the env(TZ) hack. TclpStrftime now takes useGMT as an
- arg. [Bug 559376]
-
-2002-05-28 Vince Darley <vincentdarley@users.sourceforge.net>
-
- * generic/tclIOUtil.c: fixes to Tcl_FSLoadFile when called on a file
- inside a vfs. This should avoid leaving temporary files sitting around
- on exit. [Bug 545579]
-
-2002-05-27 Donal K. Fellows <fellowsd@cs.man.ac.uk>
-
- * win/tclWinError.c: Added comment on conversion of
- ERROR_NEGATIVE_SEEK because that is a mapping that really belongs, and
- not a catch-all case.
- * win/tclWinPort.h (EOVERFLOW): Should be either EFBIG or EINVAL
- * generic/tclPosixStr.c (Tcl_ErrnoId, Tcl_ErrnoMsg): EOVERFLOW can
- potentially be a synonym for EINVAL.
-
-2002-05-24 Donal K. Fellows <fellowsd@cs.man.ac.uk>
-
- === Changes due to TIP#91 ===
-
- * win/tclWinPort.h: Added declaration of EOVERFLOW.
- * doc/CrtChannel.3: Added documentation of wideSeekProc.
- * generic/tclIOGT.c (TransformSeekProc, TransformWideSeekProc):
- Adapted to use the new channel mechanism.
- * unix/tclUnixChan.c (FileSeekProc, FileWideSeekProc): Renamed
- FileSeekProc to FileWideSeekProc and created new FileSeekProc which
- has the old-style interface and which errors out with EOVERFLOW when
- the returned file position can't fit into the return type (int for
- historical reasons.)
- * win/tclWinChan.c (FileSeekProc, FileWideSeekProc): Renamed
- FileSeekProc to FileWideSeekProc and created new FileSeekProc which
- has the old-style interface and which errors out with EOVERFLOW when
- the returned file position can't fit into the return type (int for
- historical reasons.)
- * mac/tclMacChan.c (FileSeek): Reverted to old interface; Macs lack
- large-file support because I can't see how to add it.
- * generic/tclIO.c (Tcl_Seek, Tcl_Tell): Given these functions
- knowledge of the new arrangement of channel types.
- (Tcl_ChannelVersion): Added recognition of new version code.
- (HaveVersion): New function to do version checking.
- (Tcl_ChannelBlockModeProc, Tcl_ChannelFlushProc)
- (Tcl_ChannelHandlerProc): Made these functions use HaveVersion for
- ease of future maintainability.
- (Tcl_ChannelBlockModeProc): Obvious lookup function.
- * generic/tcl.h (Tcl_ChannelType): New wideSeekProc field, and
- seekProc type restored to old interpretation.
- (TCL_CHANNEL_VERSION_3): New channel version.
-
-2002-05-24 Andreas Kupries <andreas_kupries@users.sourceforge.net>
-
- * tests/winPipe.test: Applied patch for [Bug 549617]. Patch and bug
- report by Kevin Kenny <kennykb@users.sourceforge.net>.
-
- * win/tclWinSock.c (TcpWatchProc): Fixed [Bug 557878]. We are not
- allowed to mess with the watch mask if the socket is a server socket.
- I believe that the original reporter is George Peter Staplin.
-
-2002-05-21 Mo DeJong <mdejong@users.sourceforge.net>
-
- * unix/configure: Regen.
- * unix/configure.in: Invoke SC_ENABLE_SHARED before calling
- SC_CONFIG_CFLAGS so that the SHARED_BUILD variable can be checked
- inside SC_CONFIG_CFLAGS.
- * unix/tcl.m4 (SC_CONFIG_CFLAGS): Pass -non_shared instead of -shared
- to ld when configured with --disable-shared under OSF. [Bug 540390]
-
-2002-05-20 Daniel Steffen <das@users.sourceforge.net>
-
- * generic/tclInt.h: added prototype for TclpFilesystemPathType().
- * mac/tclMacChan.c: use MSL provided creator type if available instead
- of the default 'MPW '.
-
-2002-05-16 Joe English <jenglish@users.sf.net>
-
- * doc/CrtObjCmd.3: Added Tcl_GetCommandFromObj, Tcl_GetCommandFullName
- [Bugs 547987, 414921]
-
-2002-05-14 Donal K. Fellows <fellowsd@cs.man.ac.uk>
-
- * unix/tclUnixChan.c (TtyOutputProc): #if/#endif-ed this function out
- to stop compiler warnings. Also much general tidying of comments in
- this file and removal of whitespace from blank lines.
-
-2002-05-13 Donal K. Fellows <fellowsd@cs.man.ac.uk>
-
- * unix/tclUnixChan.c (SETBREAK): Solaris thinks ioctl() takes a signed
- second argument, and Linux thinks ioctl() takes an unsigned second
- argument. So need a longer definition of this macro to get neither to
- spew warnings...
-
-2002-05-13 Vince Darley <vincentdarley@users.sourceforge.net>
-
- * generic/tclEvent.c:
- * generic/tclIOUtil.c:
- * generic/tclInt.h: clean up all memory allocated by the filesystem,
- via introduction of 'TclFinalizeFilesystem'. Move TclFinalizeLoad into
- TclFinalizeFilesystem so we can be sure it is called at just the right
- time. Fix bad comment also. [Bug 555078 and 'fs' part of 543549]
- * win/tclWinChan.c: fix comment referring to wrong function.
+ * generic/tclNamesp.c: Improvements in buffer management to make
+ namespace creation faster. Plus selected other minor improvements to
+ code quality. [Patch 1352382]
-2002-05-10 Don Porter <dgp@users.sourceforge.net>
+2006-08-10 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * tests/load.test:
- * tests/safe.test:
- * tests/tcltest.test: Corrected some list-quoting issues and other
- matters that cause tests to fail when the patch includes special
- characters. Report from Vince Darley. [Bug 554068].
+ Misc patches to make code more efficient. [Bug 1530474] (afredd)
+ * generic/*.c, macosx/tclMacOSXNotify.c, unix/tclUnixNotfy.c,
+ * win/tclWinThrd.c: Tidy up invokations of Tcl_Panic() to promote
+ string constant sharing and consistent style.
+ * generic/tclBasic.c (Tcl_CreateInterp): More efficient handling of
+ * generic/tclClock.c (TclClockInit): registration of commands not
+ in global namespace.
+ * generic/tclVar.c (Tcl_UnsetObjCmd): Remove unreachable clause.
-2002-05-08 David Gravereaux <davygrvy@pobox.com>
+2006-08-09 Don Porter <dgp@users.sourceforge.net>
- * doc/file.n:
- * tools/man2tcl.c:
- * tools/man2help2.tcl: Thanks to Peter Spjuth <peter.spjuth@space.se>,
- again. My prior fix for single-quote macro mis-understanding was
- wrong. Reverted to reimpliment the 'macro2' proc which handles
- single-quote macros and restored file.n text arrangement to avoid
- single-quotes on the first line. Sorry for all the confusion.
+ * generic/tclEncoding.c: Replace buffer copy in for loop with
+ call to memcpy(). Thanks to afredd. [Patch 1530262]
-2002-05-08 David Gravereaux <davygrvy@pobox.com>
+2006-08-09 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * tools/man2tcl.c:
- * tools/man2help2.tcl: Proper source of macro error mis-understanding
- single-quote as the leading macro command found and repaired.
+ * generic/tclCmdIL.c (Tcl_LassignObjCmd): Make the wrong#args message
+ a bit more consistent with those used elsewhere. [Bug 1534628]
- * doc/file.n: Reverted to prior state before I messed with it.
+ * generic/tclDictObj.c (DictForCmd): Stop crash when attempting to
+ iterate over an invalid dictionary. [Bug 1531184]
-2002-05-08 Don Porter <dgp@users.sourceforge.net>
+ * doc/ParseCmd.3, doc/expr.n, doc/set.n, doc/subst.n, doc/switch.n:
+ * doc/tclvars.n: Ensure that uses of [expr] in documentation examples
+ are also good style (with braces) unless otherwise necessary. [Bug
+ 1526581]
- * library/tcltest/tcltest.tcl: Corrected [uplevel] quoting when
- [source]-ing test script in subdirectories.
- * tests/fileName.test:
- * tests/load.test:
- * tests/main.test:
- * tests/tcltest.test:
- * tests/unixInit.test: Fixes to test suite when there's a space in the
- working path. Thanks to Kevin Kenny.
-
-2002-05-07 David Gravereaux <davygrvy@pobox.com>
-
- -- Changes from Peter Spjuth <peter.spjuth@space.se>
- * tools/man2tcl.c: Increased line buffer size and a bail-out if that
- should ever be over-run.
- * tools/man2help.tcl: Include Courier New font in rtf header.
- * tools/man2help2.tcl: Improved handling of CS/CE fields. Use Courier
- New for code samples and indent better.
-
- * doc/file.n:
- * doc/TraceCmd.3: winhelp conversion tools where understanding a ' as
- the first character on a line to be an unknown macro. Not knowing how
- to repair tools/man2tcl.c, I decided to rearrange the text in the docs
- instead.
-
-2002-05-07 Vince Darley <vincentdarley@users.sourceforge.net>
-
- * generic/tclFileName.c: fix to similar segfault when using
- 'glob -types nonsense -dir dirname -join * *'. [Bug 553320]
-
- * doc/FileSystem.3: further documentation on vfs.
- * tests/cmdAH.test:
- * tests/fileSystem.test:
- * tests/pkgMkindex.test: Fix to testsuite bugs when running out of
- directory whose name contains '{' or '['.
-
-2002-05-07 Miguel Sofer <msofer@users.sourceforge.net>
-
- * tests/basic.test: Fix for [Bug 549607]
- * tests/encoding.test: Fix for [Bug 549610]
- These are testsuite bugs that caused failures when the filename
- contained spaces. Report & fix by Kevin Kenny.
-
-2002-05-02 Vince Darley <vincentdarley@users.sourceforge.net>
-
- * generic/tclFileName.c: fix to freeing a bad object (i.e. segfault)
- when using 'glob -types nonsense -dir dirname'.
- * generic/tclWinFile.c: fix to [Bug 551306], also wrapped some long
- lines.
- * tests/fileName.test: added several tests for the above bugs.
- * doc/FileSystem.3: clarified documentation on refCount requirements
- of the object returned by the path type function.
- * generic/tclIOUtil.c:
- * win/tclWinFile.c:
- * unix/tclUnixFile.c:
- * mac/tclMacFile.c: moved TclpFilesystemPathType to the platform
- specific directories, so we can add missing platform-specific
- implementations. On Windows, 'file system' now returns useful results
- like "native NTFS", "native FAT" for that system. Unix and MacOS still
- only return "native".
- * doc/file.n: clarified documentation.
- * tests/winFile.test: test for 'file system' returning correct values.
- * tests/fileSystem.test: test for 'file system' returning correct
- values. Clean up after failed previous test run.
+2006-08-03 Daniel Steffen <das@users.sourceforge.net>
-2002-04-26 Jeff Hobbs <jeffh@ActiveState.com>
+ * unix/tclUnixPipe.c (TclpCreateProcess): for USE_VFORK: ensure
+ standard channels are initialized before vfork() so that the child
+ doesn't potentially corrupt global state in the parent's address space
+
+ * tests/compExpr-old.test: add 'oldExprParser' constraint to all tests
+ * tests/compExpr.test: that depend on the exact format of the
+ * tests/compile.test: error messages of the pre-2006-07-05
+ * tests/expr-old.test: expression parser. The constraint is on by
+ * tests/expr.test: default (i.e those tests still fail), but
+ * tests/for.test: can be turned off by passing '-constraints
+ * tests/if.test: newExprParser' to tcltest, which will skip
+ * tests/parseExpr.test: the 196 failing tests in the testsuite that
+ * tests/while.test: are caused by the new expression parser
+ error messages.
- * unix/configure:
- * unix/tcl.m4: change HP-11 SHLIB_LD_LIBS from "" to ${LIBS} so that
- the .sl knows its dependent libs.
+2006-07-31 Kevin B. Kenny <kennykb@acm.org>
-2002-04-26 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclClock.c (ConvertLocalToUTCUsingC): Corrected a regression
+ that caused dates before 1969 to be one day off in the :localtime time
+ zone if TZ is not set. [Bug 1531530]
- * tests/obj.test (obj-11.[56]): Test conversion to boolean more
- thoroughly.
- * generic/tclObj.c (SetBooleanFromAny): Was not calling an integer
- parsing function on native 64-bit platforms! [Bug 548686]
+2006-07-30 Kevin B. Kenny <kennykb@acm.org>
-2002-04-24 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclClock.c (GetJulianDayFromEraYearMonthDay): Corrected
+ several errors in converting dates before the Common Era [Bug 1426279]
+ * library/clock.tcl: Corrected syntax errors in generated code for %EC
+ %Ey, and %W format groups [Bug 1505383]. Corrected a bug in cache
+ management for format strings containing [glob] metacharacters [Bug
+ 1494664]. Corrected several errors in formatting/scanning of years
+ prior to the Common Era, and added the missing %EE format group to
+ indicate the era.
+ * tools/makeTestCases.tcl: Added code to make sure that %U and %V
+ format groups are included in the tests. (The code depends on %U and
+ %V formatting working correctly when 'makeTestCases.tcl' is run,
+ rather than making a completely independent check.) Added tests for
+ [glob] metacharacters in strings. Added tests for years prior to the
+ Common Era.
+ * tests/clock.test: Rebuilt with new test cases for all the above.
- * generic/tclInt.h: corrected TclRememberJoinableThread decl to use
- VOID instead of void.
- * generic/tclThreadJoin.c: noted that this code isn't needed on Unix.
+2006-07-30 Joe English <jenglish@users.sourceforge.net>
-2002-04-23 Jeff Hobbs <jeffh@ActiveState.com>
+ * doc/AppInit.3: Fix typo [Bug 1496886]
- * doc/exec.n:
- * doc/tclvars.n: doc updates [Patch 509426] (gravereaux)
+2006-07-26 Don Porter <dgp@users.sourceforge.net>
-2002-04-24 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tclExecute.c: Corrected flawed overflow detection in
+ * tests/expr.test: INST_EXPON that caused [expr 2**64] to return
+ 0 instead of the same value as [expr 1<<64].
- * mac/tclMacResource.r: added check of TCLTK_NO_LIBRARY_TEXT_RESOURCES
- #define to allow disabling the inclusion of the tcl library code in
- the resource fork of Tcl executables and shared libraries.
+2006-07-24 Don Porter <dgp@users.sourceforge.net>
-2002-04-23 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * win/tclWinSock.c: Correct un-initialized Tcl_DString. Thanks to
+ afredd. [Bug 1518166]
- * doc/TraceCmd.3: New file that documents Tcl_CommandTraceInfo,
- Tcl_TraceCommand and Tcl_UntraceCommand [Bug 414927]
+2006-07-21 Miguel Sofer <msofer@users.sf.net>
-2002-04-22 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclExecute.c:
+ * tests/execute.test (execute-9.1): dgp's fix for [Bug 1522803].
- * generic/tclAlloc.c:
- * generic/tclInt.h:
- * generic/tclThreadAlloc.c (new):
- * unix/Makefile.in:
- * unix/tclUnixThrd.c:
- * win/Makefile.in:
- * win/tclWinInt.h:
- * win/tclWinThrd.c: added new threaded allocator contributed by AOL
- that significantly reduces lock contention when multiple threads are
- in use. Only Windows and Unix implementations are ready, and the
- Windows one may need work. It is only used by default on Unix for now,
- and requires that USE_THREAD_ALLOC be defined (--enable-threads on
- Unix will define this).
+2006-07-20 Daniel Steffen <das@users.sourceforge.net>
- * generic/tclIOUtil.c (Tcl_FSRegister, Tcl_FSUnregister): corrected
- calling of Tcl_ConditionWait to ensure that there would be a condition
- to wait upon.
+ * macosx/tclMacOSXNotify.c (Tcl_InitNotifier, Tcl_WaitForEvent):
+ create notifier thread lazily upon first call to Tcl_WaitForEvent()
+ rather than in Tcl_InitNotifier(). Allows calling exeve() in processes
+ where the event loop has not yet been run (Darwin's execve() fails in
+ processes with more than one thread), in particular allows embedders
+ to call fork() followed by execve(), previously the pthread_atfork()
+ child handler's call to Tcl_InitNotifier() would immediately recreate
+ the notifier thread in the child after a fork.
- * generic/tclCmdAH.c (Tcl_FileObjCmd): added cast in FILE_SIZE.
+ * macosx/tclMacOSXFCmd.c (TclMacOSXCopyFileAttributes): add support
+ * macosx/tclMacOSXNotify.c (Tcl_InitNotifier): for weakly
+ * unix/tclUnixInit.c (Tcl_GetEncodingNameFromEnvironment): importing
+ symbols not available on OSX 10.2 or 10.3, enables binaires built on
+ later OSX versions to run on earlier ones.
+ * macosx/Tcl.xcodeproj/project.pbxproj: enable weak-linking; turn on
+ extra warnings.
+ * macosx/README: document how to enable weak-linking; cleanup.
+ * unix/tclUnixPort.h: add support for weak-linking; conditionalize
+ AvailabilityMacros.h inclusion; only disable realpath on 10.2 or
+ earlier when threads are enabled.
+ * unix/tclLoadDyld.c (TclpLoadMemoryGetBuffer): change runtime Darwin
+ * unix/tclUnixInit.c (TclpInitPlatform): release check to use
+ global initialized
+ once
+ * unix/tclUnixFCmd.c (DoRenameFile, TclpObjNormalizePath): add runtime
+ Darwin release check to determine if realpath is threadsafe.
+ * unix/configure.in: add check on Darwin for compiler support of weak
+ * unix/tcl.m4: import and for AvailabilityMacros.h header; move
+ Darwin specific checks & defines that are only relevant to the tcl
+ build out of tcl.m4; restrict framework option to Darwin; clean up
+ quoting and help messages.
+ * unix/configure: autoconf-2.59
+ * unix/tclConfig.h.in: autoheader-2.59
- * win/tclWinFCmd.c (DoDeleteFile): check return of setattr API calls
- in file deletion for correct Win32 API handling.
+ * generic/regc_locale.c (cclass):
+ * generic/tclExecute.c (TclExecuteByteCode):
+ * generic/tclIOCmd.c (Tcl_ExecObjCmd):
+ * generic/tclListObj.c (NewListIntRep):
+ * generic/tclObj.c (Tcl_GetLongFromObj, Tcl_GetWideIntFromObj)
+ (FreeBignum, Tcl_SetBignumObj):
+ * generic/tclParseExpr.c (Tcl_ParseExpr):
+ * generic/tclStrToD.c (TclParseNumber):
+ * generic/tclStringObj.c (TclAppendFormattedObjs):
+ * unix/tclLoadDyld.c (TclpLoadMemory):
+ * unix/tclUnixPipe.c (TclpCreateProcess): fix signed-with-unsigned
+ comparison and other warnings from gcc4 -Wextra.
- * win/Makefile.in: correct dependencies for shell, gdb, runtest
- targets.
+2006-07-13 Andreas Kupries <andreask@activestate.com>
- * doc/clock.n:
- * compat/strftime.c (_fmt): change strftime to correctly handle
- localized %c, %x and %X on Windows. Added some notes about how the
- other values could be further localized.
+ * unix/tclUnixPort.h: Added the inclusion of <AvailabilityMacros.h>.
+ The missing header caused the upcoming #if conditions to wrongly
+ exclude realpath, causing file normalize to ignore symbolic links in
+ the path.
-2002-04-19 Don Porter <dgp@users.sourceforge.net>
+2006-07-11 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
- * generic/tclMain.c (Tcl_Main): Free the memory allocated for the
- startup script path. [Bug 543549]
+ * generic/tclAsync.c: Made Tcl_AsyncDelete() more tolerant when called
+ after all thread TSD has been garbage-collected.
- * library/msgcat/msgcat.tcl: [mcmax] wasn't using the caller's
- namespace when determining the max translated length. Also made
- revisions for better use of namespace variables and more efficient
- [uplevel]s.
+2006-07-05 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclParseExpr.c: Completely new expression parser that
+ builds a parse tree instead of operating with deep recursion. This
+ corrects reports of stack-blowing crashes parsing long expressions
+ [Bug 906201] and replaces a fundamentally O(N^2) algorithm with an
+ O(N) one [RFE 903765]. The new parser is better able to generate error
+ messages that clearly report both the nature and context of the syntax
+ error [Bugs 1029267, 1381715]. For now, the code for the old parser is
+ still present and can be activated with a "#define OLD_EXPR_PARSER
+ 1". This is for the sake of a clean implementation patch, and for ease
+ of benchmarking. The new parser is non-recursive, so much lighter in
+ stack consumption, but it does use more heap, so there may be cases
+ where parsing of long expressions that succeeded with the old parser
+ will lead to out of memory panics with the new one. There are still
+ more improvements possible on that point, though significant progress
+ may require changes to the Tcl_Token specifications documented for the
+ public Tcl_Parse*() routines.
+ ***POTENTIAL INCOMPATIBILITY*** for any callers that rely on the exact
+ (usually terrible) error messages generated by the old parser. This
+ includes a large number of tests in the test suite.
+
+ * generic/tclInt.h: Replaced TclParseWhiteSpace() with
+ * generic/tclParse.c: TclParseAllWhiteSpace() which is what
+ * generic/tclParseExpr.c: all the callers really needed.
+ Breaking whitespace runs at newlines is useful only to the command
+ parsing function, and it can call the file scoped routine
+ ParseWhiteSpace() to do that.
+
+ * tests/expr-old.test: Removed knownBug constraints that masked
+ * tests/expr.test: failures due to revised error messages.
+ * tests/parseExpr.test:
- * doc/msgcat.n:
- * library/msgcat/msgcat.tcl:
- * library/msgcat/pkgIndex.tcl: Added [mcload] to the export list of
- msgcat; bumped to 1.2.3. [Bug 544727]
+2006-06-20 Don Porter <dgp@users.sourceforge.net>
-2002-04-20 Daniel Steffen <das@users.sourceforge.net>
+ * generic/tclIOUtil.c: Changed default configuration to
+ * generic/tclInt.decls: #undef USE_OBSOLETE_FS_HOOKS which disables
+ * generic/tclTest.c: access to the Tcl 8.3 internal routines for
+ hooking into filesystem operations. Everyone ought to have migrated to
+ Tcl_Filesystems by now.
+ ***POTENTIAL INCOMPATIBILITY*** for any code still stuck in the
+ pre-Tcl_Filesystem era.
- * generic/tclInt.decls:
- * generic/tclIntPlatDecls.h:
+ * generic/tclIntDecls.h: make genstubs
* generic/tclStubInit.c:
- * mac/tclMacFCmd.c:
- * mac/tclMacFile.c:
- * mac/tclMacUtil.c: Modified TclpObjNormalizePath to be alias file
- aware, and replaced various calls to FSpLocationFrom*Path by calls to
- new alias file aware versions FSpLLocationFrom*Path. The alias file
- aware routines don't resolve the last component of a path if it is an
- alias. This allows [file copy/delete] etc. to act correctly on alias
- files. (c.f. discussion in [Bug 511666])
-
-2002-04-19 Donal K. Fellows <fellowsd@cs.man.ac.uk>
-
- * tests/lindex.test (lindex-3.7):
- * generic/tclUtil.c (TclGetIntForIndex): Stopped indexes from hitting
- wide ints. [Bug 526717]
-
-2002-04-18 Miguel Sofer <msofer@users.sourceforge.net>
-
- * generic/tclNamesp.c:
- * tests/info.test: [Bug 545325] info level didn't report namespace
- eval, bug report by Richard Suchenwirth.
-
-2002-04-18 Don Porter <dgp@users.sourceforge.net>
- * doc/subst.n: Clarified documentation on handling unusual return
- codes during substitution, and on variable substitutions implied by
- command substitution, and vice versa. [Bug 536838]
+ * generic/tclStrToD.c: Removed dead code that permitted disabling of
+ recognition of the new 0b and 0o numeric formats.
-2002-04-18 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclExecute.c: Removed dead code that implemented alternative
+ * generic/tclObj.c: design where numeric values did not
+ automatically narrow to the smallest Tcl_ObjType required to hold them
- * generic/tclCmdIL.c (InfoBodyCmd):
- * tests/info.test (info-2.6): Proc bodies without string reps would
- report as empty [Bug 545644]
+ * generic/tclCmdAH.c: Removed dead code that was old implementation
+ of [format].
- * generic/tclCmdMZ.c (Tcl_SubstObj): More clarification for comment on
- behaviour when substitutions are not well-formed, prompted by [Bug
- 536831]; alas, removing the ill-defined behaviour is a lot of work.
-
-2002-04-18 Miguel Sofer <msofer@users.sourceforge.net>
-
- * generic/tclExecute.c:
- * tests/expr-old.test: fix for [Bug 542588] (Phil Ehrens), where "too
- large integers" were reported as "floating-point value" in [expr]
- error messages.
-
-2002-04-17 Jeff Hobbs <jeffh@ActiveState.com>
-
- * generic/tclEncoding.c (EscapeFromUtfProc):
- * generic/tclIO.c (WriteChars, Tcl_Close): corrected the handling of
- outputting end escapes for escape-based encodings.
- [Bug 526524] (yamamoto)
-
-2002-04-17 Don Porter <dgp@users.sourceforge.net>
-
- * doc/tcltest.n: Removed [saveState] and [restoreState] from tcltest
- 2 documentation, effectively deprecating them. [Bug 495660]
- * library/tcltest/tcltest.tcl: Made separate export for commands kept
- only for tcltest 1 compatibility.
-
- * tests/iogt.test: Revised to run tests in a namespace, rather than
- use the useless and buggy [saveState] and [restoreState] commands of
- tcltest. Updated to use tcltest 2 as well. [Patch 544911]
+2006-06-14 Daniel Steffen <das@users.sourceforge.net>
-2002-04-16 Don Porter <dgp@users.sourceforge.net>
+ * unix/tclUnixPort.h (Darwin): support MAC_OS_X_VERSION_MAX_ALLOWED
+ define from AvailabilityMacros.h: override configure detection and
+ only use API available in the indicated OS version or earlier.
- * tests/io.test: Revised to run tests in a namespace, rather than use
- the useless and buggy [saveState] and [restoreState] commands of
- tcltest. Updated to use tcltest 2 as well. [Patch 544546]
+2006-06-14 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
-2002-04-15 Miguel Sofer <msofer@users.sourceforge.net>
+ * doc/format.n, doc/scan.n: Added examples for converting between
+ characters and their numeric interpretations following user prompting.
- * generic/tclProc.c:
- * tests/proc-old.test: Improved stack trace for TCL_BREAK and
- TCL_CONTINUE returns from procs. [Bug 536955] (dgp)
+2006-06-13 Donal K. Fellows <dkf@users.sf.net>
- * generic/tclExecute.c:
- * tests/compile.test: made bytecodes check for a catch before
- returning; the compiled [return] is otherwise non-catchable. [Bug
- 542142] reported by Andreas Kupries.
-
-2002-04-15 Don Porter <dgp@users.sourceforge.net>
-
- * tests/socket.test: Increased timeout values so that tests have time
- to successfully complete even on slow/busy machines. [Bug 523470]
-
- * doc/tcltest.n:
- * library/tcltest/tcltest.tcl:
- * tests/tcltest.test: Revised [tcltest::test] to return errors when
- called with invalid syntax and to accept exactly two arguments as
- documented. Improved error messages. [Bug 497446, Patch 513983]
- ***POTENTIAL INCOMPATIBILITY***: Incompatible with previous
- tcltest 2.* releases, found only in alpha releases of Tcl 8.4.
-
-2002-04-11 Jeff Hobbs <jeffh@ActiveState.com>
-
- * generic/tclNotify.c (TclFinalizeNotifier): remove remaining
- unserviced events on finalization.
-
- * win/tcl.m4: Enabled COFF as well as CV style debug info with
- --enable-symbols to allow Dr. Watson users to see function info. More
- info on debugging levels can be obtained at:
- http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp
+ * unix/tclLoadDl.c (TclpDlopen): Workaround for a compiler bug in Sun
+ Forte 6. [Bug 1503729]
- * tests/ioCmd.test: fixed iocmd-8.15 to have mac and unixPc variants.
-
- * generic/tclParse.c (Tcl_ParseVar): conditionally incr obj refcount
- to prevent possible mem leak.
-
-2002-04-08 Daniel Steffen <das@users.sourceforge.net>
-
- * generic/tcl.h: no <sys/types.h> on mac.
- * mac/tclMacFile.c: minor fixes to Vince's changes from 03-24.
- * mac/tclMacOSA.c:
- * mac/tclMacResource.c: added missing Tcl_UtfToExternalDString
- conversions of resource file names.
- * mac/tclMacSock.c (TcpGetOptionProc): fixed bug introduced by Andreas
- on 02-25; changed strcmp's to strncmp's so that option comparison
- behaves like on other platforms.
- * mac/tcltkMacBuildSupport.sea.hqx (CW Pro6 changes): added support to
- allow Tk to hookup C library stderr/stdout to TkConsole.
- * tests/basic.test:
- * tests/cmdAH.test:
- * tests/encoding.test:
- * tests/fileSystem.test:
- * tests/ioCmd.test: fixed tests failing on mac: check for existence of
- [exec], changed some result strings.
-
-2002-04-06 Jeff Hobbs <jeffh@ActiveState.com>
-
- * unix/tclUnixFCmd.c (Realpath): added a little extra code to
- initialize a realpath arg when compiling in PURIFY mode in order to
- prevent spurious purify warnings. We should really create our own
- realpath implementation, but this will at least quiet purify for now.
-
-2002-04-05 Don Porter <dgp@users.sourceforge.net>
-
- * generic/tclCmdMZ.c (Tcl_SubstObj):
- * tests/subst.test: Corrected [subst] so that return codes TCL_BREAK
- and TCL_CONTINUE returned by variable substitution have the same
- effect as when those codes are returned by command substitution. [Bug
- 536879]
-
-2002-04-03 Jeff Hobbs <jeffh@ActiveState.com>
-
- * library/tcltest/tcltest.tcl: added getMatchingFiles back (alias
- to GetMatchingFiles), which was a public function in tcltest 1.0.
-
-2002-04-01 Vince Darley <vincentdarley@users.sourceforge.net>
-
- * generic/tclEnv.c:
- * generic/tclIOUtil.c: invalidate filesystem cache when the user
- changes env(HOME). Fixes [Bug 535621]. Also cleaned up some of the
- documentation.
- * tests/fileSystem.test: added test for bug just fixed.
-
-2002-04-01 Kevin Kenny <kennykb@acm.org>
-
- * win/tclWinTime.c (Tcl_GetTime): made the checks of clock frequency
- more permissive to cope with the fact that Win98SE is observed to
- return 1.19318 in place of 1.193182 for the performance counter
- frequency.
-
-2002-03-29 Jeff Hobbs <jeffh@ActiveState.com>
-
- * generic/tclCmdMZ.c (Tcl_TraceObjCmd, TraceVarProc)
- (TraceCommandProc, TclTraceCommandObjCmd): corrected potential
- double-free of traces on variables by flagging in Trace*Proc that it
- will free the var in case the eval wants to delete the var trace as
- well. [Bug 536937]
- Also converted Tcl_UntraceVar -> Tcl_UntraceVar2 and Tcl_Eval to
- Tcl_EvalEx in Trace*Proc for slight efficiency improvement.
-
-2002-03-29 Don Porter <dgp@users.sourceforge.net>
-
- * doc/AllowExc.3:
- * generic/tclBasic.c (Tcl_EvalObjv,Tcl_EvalEx,Tcl_EvalObjEx):
- * generic/tclCompile.h (TclCompEvalObj):
- * generic/tclExecute.c (TclCompEvalObj,TclExecuteByteCode):
- * tests/basic.test: Corrected problems with Tcl_AllowExceptions having
- influence over the wrong scope of Tcl_*Eval* calls. Patch from Miguel
- Sofer. Report from Jean-Claude Wippler. [Bug 219181]
-
-2002-03-28 Don Porter <dgp@users.sourceforge.net>
-
- * generic/tclVar.c: Refactored CallTraces to collect repeated handling
- of its returned value into CallTraces itself.
-
-2002-03-28 David Gravereaux <davygrvy@pobox.com>
-
- * tools/feather.bmp:
- * tools/man2help.tcl:
- * tools/man2help2.tcl:
- * win/makefile.vc: More winhelp target fixups. Added a feather bitmap
- to the non-scrollable area and changed the color to be yellow from a
- plain white. The colors can be whatever we want them to be, but
- thought I would start with something bold. [Bug 527941]
-
- * doc/SetVar.3:
- * doc/TraceVar.3:
- * doc/UpVar.3: .AP macro syntax repair.
-
-2002-03-27 David Gravereaux <davygrvy@pobox.com>
-
- * tools/man2help.tcl:
- * win/makefile.vc: winhelp target now copies all needed files from
- tools/ to a workarea under $(OUT_DIR) and builds it from there. No
- build cruft is left in tools/ anymore. All paths used in man2help.tcl
- are now relative to where the script is. [Bug 527941]
-
-2002-03-27 David Gravereaux <davygrvy@pobox.com>
-
- * win/.cvsignore:
- * win/buildall.vc.bat:
- * win/coffbase.txt:
- * win/makefile.vc:
- * win/nmakehlp.c (new):
- * win/rules.vc: First draft fix for [Bug 527941]. More changes need to
- done to the makehelp target to get to stop leaving build files in the
- tools/ directory. This does not address the syntax errors in the man
- files. Having the contents of tcl.hpj(.in) inside makefile.vc allows
- for version numbers to be replaced with macros.
+2006-06-06 Don Porter <dgp@users.sourceforge.net>
- The new nmakehlp.c is built by rules.vc in preprocessing and removes
- the need to use tricky shell syntax that wasn't compatible on Win9x
- systems. Clean targets made Win9x complient. This is a first draft
- repair for [Bug 533862].
+ * doc/GetStdChan.3: Added recommendation that each call to
+ Tcl_SetStdChannel() be accompanied by a call to Tcl_RegisterChannel().
-2002-03-28 Miguel Sofer <msofer@users.sourceforge.net>
+2006-06-05 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * generic/tclBasic.c (Tcl_EvalEx): passing the correct commandSize
- to TclEvalObjvInternal. [Bug 219362], fix by David Knoll.
+ * doc/Alloc.3: Added documentation of promise that Tcl_Realloc(NULL,x)
+ is the same as Tcl_Alloc(x), as discussed in comp.lang.tcl. Also fixed
+ nonsense sentence to say something meaningful.
-2002-03-28 Miguel Sofer <msofer@users.sourceforge.net>
+2006-05-29 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/tclBasic.c (Tcl_EvalEx):
- * tests/basic.test: avoid exceptional returns at level 0
- [Bug 219181]
+ * generic/tcl.h (Tcl_DecrRefCount): use if/else construct to allow
+ placement in unbraced outer if/else conditions. (jcw)
-2002-03-27 Don Porter <dgp@users.sourceforge.net>
+2006-05-27 Daniel Steffen <das@users.sourceforge.net>
- * doc/tcltest.n ([mainThread]):
- * library/tcltest/tcltest.tcl:
- * tests/tcltest.test: Major code cleanup to deal with whitespace,
- coding conventions, and namespace issues, with several minor bugs
- fixed in the process.
+ * macosx/tclMacOSXNotify.c: implemented pthread_atfork() handler that
+ * unix/tcl.m4 (Darwin): recreates CoreFoundation state and
+ notifier thread in the child after a fork(). Note that pthread_atfork
+ is available starting with Tiger only. Because vfork() is used by the
+ core on Darwin, [exec]/[open] are not affected by this fix, only
+ extensions or embedders that call fork() directly (such as TclX).
+ However, this only makes fork() safe from corefoundation tcl with
+ --disable-threads; as on all platforms, forked children may deadlock
+ in threaded tcl due to the potential for stale locked mutexes in the
+ child. [Patch 923072]
- * tests/main.test: Added missing [after cancel]s.
+ * unix/configure: autoconf-2.59
+ * unix/tclConfig.h.in: autoheader-2.59
-2002-03-25 Don Porter <dgp@users.sourceforge.net>
+2006-05-24 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * tests/main.test: Removed workarounds for Bug 495977.
+ * unix/tcl.m4 (SC_CONFIG_SYSTEM): Fixed quoting of command script to
+ awk; it was a rarely used branch, but it was wrong. [Bug 1494160]
- * library/tcltest/tcltest.tcl: Keep the value of $::auto_path
- unchanged, so that the tcltest package can test code that depends
- on auto-loading. If a testing application needs $::auto_path pruned,
- it should do that itself. [Bug 495726]
- Improve the processing of the -constraints option to [test] so that
- constraint lists can have arbitrary whitespace, and non-lists don't
- blow things up. [Bug 495977]
- Corrected faulty variable initialization. [Bug 534845]
+2006-05-23 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
-2002-03-25 Miguel Sofer <msofer@users.sourceforge.net>
+ * doc/chan.n, doc/refchan.n: Tighten up the documentation to follow a
+ slightly more consistent style with regard to argument capitalization.
- * doc/CrtTrace.3: small doc correction
- * generic/tclBasic.c (Tcl_DeleteTrace): Allow NULL callback on
- trace deletions [Bug 534728] (Hemang Lavana).
+2006-05-13 Don Porter <dgp@users.sourceforge.net>
-2002-03-24 Miguel Sofer <msofer@users.sourceforge.net>
+ * generic/tclProc.c (ProcCompileProc): When a bump of the compile
+ epoch forces the re-compile of a proc body, take care not to overwrite
+ any Proc struct that may be referred to on the active call stack. This
+ fixes [Bug 1482718]. Note that the fix will not be effective for code
+ that calls the private routine TclProcCompileProc() directly.
- * generic/tclBasic.c (Tcl_EvalObjv): replaced obscure, incorrect
- code as described in [Bug 533907] (Don Porter).
+2006-05-13 Daniel Steffen <das@users.sourceforge.net>
-2002-03-24 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclEvent.c (HandleBgErrors): fix leak. [Coverity issue 86]
- * library/tcltest/tcltest.tcl: Use [interpreter] to set/query the
- executable currently running the tcltest package. [Bug 454050]
+2006-05-05 Don Porter <dgp@users.sourceforge.net>
- * library/tcltest/tcltest.tcl: Allow non-proc commands to be used
- as the customization hooks. [Bug 495662]
+ * generic/tclMain.c (Tcl_Main): Corrected flaw that required
+ * tests/main.test: (Tcl_Main-4.5): processing of one interactive
+ command before passing control to the loop routine registered with
+ Tcl_SetMainLoop(). [Bug 1481986]
-2002-03-24 Vince Darley <vincentdarley@users.sourceforge.net>
+2006-05-04 Don Porter <dgp@users.sourceforge.net>
- * generic/tclFilename.c:
- * generic/tclFCmd.c:
- * generic/tclTest.c:
+ * README: Bump version number to 8.5a5
* generic/tcl.h:
- * generic/tclIOUtil.c:
- * win/tclWinFile.c:
- * win/tclWinFCmd.c:
- * win/tclWinPipe.c:
- * unix/tclUnixFile.c:
- * unix/tclUnixFCmd.c:
- * mac/tclMacFile.c:
- * doc/FileSystem.3:
- * doc/file.n:
- * tests/cmdAH.test:
- * tests/fileName.test:
- * tests/fileSystem.test: (new file)
- * tests/winFCmd.test: fix [Bug 511666] and [Bug 511658], and improved
- documentation of some aspects of the filesystem, particularly
- 'Tcl_FSMatchInDirectory' which now might match a single file/directory
- only, and 'file normalize' which wasn't very clear before. Removed
- inconsistency betweens docs and the Tcl_Filesystem structure. Also
- fixed [Bug 523217] and corrected file normalization on Unix so that it
- expands symbolic links. Added some new tests of the filesystem code
- (in the new file 'fileSystem.test'), and some extra tests for correct
- handling of symbolic links. Fix to [Bug 530960] which shows up on
- Win98. Made comparison with ".com" case insensitive in tclWinPipe.c
-
- ***POTENTIAL INCOMPATIBILITY***: But only between alpha releases
- (users of the new Tcl_Filesystem lookup table in Tcl 8.4a4 need to
- handle the new way in which Tcl may call Tcl_FSMatchInDirectory, and
- 'file normalize' on unix now behaves correctly). Only known impact is
- with the 'tclvfs' extension.
-
-2002-03-22 Miguel Sofer <msofer@users.sourceforge.net>
-
- * tests/basic.test (basic-46.1): adding test for [Bug 533758], fixed
- earlier today.
-
-2002-03-22 Jeff Hobbs <jeffh@ActiveState.com>
-
- * win/tclWinInt.h: moved undef of TCL_STORAGE_CLASS. [Bug 478579]
-
-2002-03-22 Miguel Sofer <msofer@users.sourceforge.net>
-
- * generic/tclBasic.c (Tcl_EvalObjEx):
- * generic/tclExecute.c (TclCompEvalObj): fixed the errorInfo for
- return codes other than (TCL_OK, TCL_ERROR) to runLevel 0 [Bug
- 533758]. Removed the static RecordTracebackInfo(), as its
- functionality is easily replicated by Tcl_LogCommandInfo. Bug and
- redundancy noted by Don Porter.
-
-2002-03-21 Donal K. Fellows <fellowsd@cs.man.ac.uk>
-
- * doc/expr.n: Improved documentation for ceil and floor [Bug 530535]
-
-2002-03-20 Don Porter <dgp@users.sourceforge.net>
-
- * doc/SetVar.3:
- * doc/TraceVar.3:
- * doc/UpVar.3:
- * generic/tcl.h (Tcl_VarTraceProc):
- * generic/tcl.decls (Tcl_GetVar2, Tcl_SetVar2, Tcl_TraceVar2)
- (Tcl_UnsetVar2, Tcl_UntraceVar2, Tcl_UpVar2, Tcl_VarTraceInfo2)
- (Tcl_GetVar2Ex, TclSetVar2Ex):
- * generic/tclCmdMZ.c (TraceVarProc):
- * generic/tclEnv.c (EnvTraceProc):
- * generic/tclEvent.c (VwaitVarProc):
- * generic/tclInt.decls (TclLookupVar,TclPrecTraceProc):
- * generic/tclLink.c (LinkTraceProc):
- * generic/tclUtil.c (TclPrecTraceProc):
- * generic/tclVar.c (CallTraces, MakeUpvar, VarErrMsg, TclLookupVar,
- (Tcl_GetVar2, Tcl_SetVar2, Tcl_TraceVar2, Tcl_UnsetVar2)
- (Tcl_UntraceVar2, Tcl_UpVar2, Tcl_VarTraceInfo2, Tcl_GetVar2Ex)
- (TclSetVar2Ex): Updated interfaces of generic/tclVar.c according to
- TIP 27. In particular, the "part2" arguments were CONSTified.
- [Patch 532642]
- * generic/tclDecls.h:
- * generic/tclIntDecls.h: make genstubs
-
-2002-03-15 Donal K. Fellows <fellowsd@cs.man.ac.uk>
-
- * tests/compile.test (compile-12.3): Test to detect bug 530320.
- * generic/tclCompile.c (TclCompileTokens): Fixed buffer overrun
- reported in bug 530320.
-
-2002-03-14 Mo DeJong <mdejong@users.sourceforge.net>
-
- * win/configure: Regen.
- * win/configure.in: Add configure time test for SEH support in the
- compiler.
- * win/tclWin32Dll.c (ESP, EBP, TclpCheckStackSpace,
- (_except_checkstackspace_handler):
- * win/tclWinChan.c (ESP, EBP, Tcl_MakeFileChannel,
- (_except_makefilechannel_handler):
- * win/tclWinFCmd.c (ESP, EBP, DoRenameFile, DoCopyFile,
- (_except_dorenamefile_handler, _except_docopyfile_handler): Implement
- SEH support under gcc using inline asm. Tcl and Tk should now compile
- with Mingw 1.1. [Patch 525746]
+ * tools/tcl.wse.in:
+ * unix/configure.in:
+ * unix/tcl.spec:
+ * win/README.binary:
+ * win/configure.in:
-2002-03-14 Mo DeJong <mdejong@users.sourceforge.net>
+ * unix/configure: autoconf-2.59
+ * win/configure:
- * win/tclWinFCmd.c (DoRenameFile, DoCopyFile): Handle an SEH exception
- with EXCEPTION_EXECUTE_HANDLER instead of restarting the faulting
- instruction with EXCEPTION_CONTINUE_EXECUTION. Bug 466102 provides an
- example of how restarting could send Tcl into an infinite loop. [Patch
- 525746]
+ * generic/tclBasic.c (ExprSrandFunc): Restore acceptance of wide/big
+ * doc/mathfunc.n: integer values by srand(). [Bug 1480509]
-2002-03-11 Mo DeJong <mdejong@users.sourceforge.net>
+2006-04-26 Don Porter <dgp@users.sourceforge.net>
- * win/tclWinFCmd.c (DoRenameFile, DoCopyFile, DoDeleteFile,
- (DoRemoveJustDirectory): Make sure we don't pass NULL or "" as a path
- name to Win32 API functions since this was crashing under Windows 98.
+ *** 8.5a4 TAGGED FOR RELEASE ***
-2002-03-11 Don Porter <dgp@users.sourceforge.net>
+ * changes: Updates for another RC.
- * library/tcltest/tcltest.tcl:
- * library/tcltest/pkgIndex.tcl: Bumped tcltest package to 2.0.2.
+ * generic/tclBinary.c: Revised the handling of the Q and q format
+ * generic/tclInt.h: specifiers for [binary] to account for the
+ * generic/tclStrToD.c: "middle endian" floating point format used in
+ Nokia N770.
-2002-03-11 Mo DeJong <mdejong@users.sourceforge.net>
+2006-04-25 Don Porter <dgp@users.sourceforge.net>
- * library/tcltest/tcltest.tcl (getMatchingFiles): Pass a proper list
- to foreach to avoid munging a Windows patch like D:\Foo\Bar into
- D:FooBar before the glob.
+ * doc/DoubleObj.3: More doc updates for TIP 237.
+ * doc/expr.n:
+ * doc/format.n:
+ * doc/mathfunc.n:
+ * doc/scan.n:
+ * doc/string.n:
-2002-03-11 Mo DeJong <mdejong@users.sourceforge.net>
+ * generic/tclScan.c: [scan $s %u] is documented to accept only
+ * tests/scan.test: decimal formatted integers. Fixed to match.
- * generic/tclEncoding.c: Fix typo in comment.
- * generic/tclIO.c (DoReadChars, ReadBytes, ReadChars): Use NULL value
- instead of pointer set to NULL to make things more clear. Reorder
- arguments so that they match the function signatures. Cleanup little
- typos and add more descriptive comment.
+2006-04-19 Kevin B. Kenny <kennykb@acm.org>
-2002-03-08 Mo DeJong <mdejong@users.sourceforge.net>
+ * generic/tclStrToD.c: Added code to support the "middle endian"
+ floating point format used in the Nokia N770's software-based floating
+ point. Thanks to Bruce Johnson for reporting this bug, originally on
+ http://wiki.tcl.tk/15408.
+ * library/clock.tcl: Fixed a bug with Daylight Saving Time and Posix
+ time zone specifiers reported by Martin Lemburg in
+ http://groups.google.com/group/comp.lang.tcl/browse_thread/thread/9a8b15a4dfc0b7a0
+ (and not at SourceForge).
+ * tests/clock.test: Added test case for the above bug.
- * win/README: Update to indicate that Mingw 1.1 is required to build
- Tcl. Add section describing new msys based build process. Update
- Cygwin build instructions so users know where to find Mingw 1.1.
+2006-04-18 Donal K. Fellows <dkf@users.sf.net>
-2002-03-08 Jeff Hobbs <jeffh@ActiveState.com>
+ * doc/IntObj.3: Minor review fixes, including better documentation of
+ the behaviour of Tcl_GetBignumAndClearObj.
- * win/tclWinFCmd.c (DoCopyFile): correctly set retval to TCL_OK.
+2006-04-17 Don Porter <dgp@users.sourceforge.net>
-2002-03-07 Mo DeJong <mdejong@users.sourceforge.net>
+ * doc/IntObj.3: Documentation changes to account for TIP 237 changes.
+ * doc/Object.3: [Bug 1446971]
- * win/tclWin32Dll.c (TclpCheckStackSpace):
- * win/tclWinFCmd.c (DoRenameFile, DoCopyFile): Replace hard coded
- constants with Win32 symbolic names. Move control flow statements out
- of __try blocks since the documentation indicates it is frowned upon.
+2006-04-12 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
-2002-03-07 Don Porter <dgp@users.sourceforge.net>
+ * generic/regc_locale.c (cclass): Redefined the meaning of [:print:]
+ to be exactly UNICODE letters, numbers, punctuation, symbols and
+ spaces (*not* whitespace). [Bug 1376892]
- * doc/interp.n:
- * generic/tclInterp.c (Tcl_InterpObjCmd,SlaveObjCmd,
- (SlaveRecursionLimit):
- * generic/tclTest.c:
- * tests/interp.test: Added the [interp recursionlimit] command to
- set/query the recursion limit of an interpreter. Proposal and
- implementation from Stephen Trier. [TIP 87, Patch 522849]
+2006-04-11 Don Porter <dgp@users.sourceforge.net>
-2002-03-06 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclTrace.c: Stop some interference between enter traces
+ * tests/trace.test: and enterstep traces. [Bug 1458266]
- * generic/tcl.h, tools/tcl.wse.in, unix/configure.in,
- * unix/tcl.spec, win/README.binary, win/configure.in, README:
- Bumped patchlevel; this might need to change in the future, but it
- will help us distinguish between the CVS version and the most
- recent released version.
+2006-04-07 Don Porter <dgp@users.sourceforge.net>
-2002-03-06 Miguel Sofer <msofer@users.sourceforge.net>
+ * generic/tclPathObj.c: Yet another revised fix for the [Bug 1379287]
+ * tests/fileSystem.test: family of path normalization bugs.
- * generic/tclInt.h: for unshared objects, TclDecrRefCount now frees
- the internal rep before the string rep - just like the non-macro
- Tcl_DecrRefCount/TclFreeObj [Bug 524802].
+2006-04-06 Jeff Hobbs <jeffh@ActiveState.com>
-2002-03-06 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * generic/tclRegexp.c (FinalizeRegexp): full reset data to indicate
+ readiness for reinitialization.
- * doc/lsearch.n: Documentation of new features, plus examples.
- * tests/lsearch.test: Tests of new features.
- * generic/tclCmdIL.c (Tcl_LsearchObjCmd): TIP#80 support. See
- http://purl.org/tcl/tip/80 for details.
+2006-04-06 Don Porter <dgp@users.sourceforge.net>
-2002-03-05 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct): It seems there
+ * tests/indexObj.test: are extensions that rely on the prior behavior
+ * doc/GetIndex.3: that the empty string cannot succeed as a
+ unique prefix matcher, so I'm restoring Donal Fellows's solution.
+ Added mention of this detail to the documentation. [Bug 1464039]
- *** 8.4a4 TAGGED FOR RELEASE ***
+ * tests/compExpr-old.test: Updated testmathfunctions constraint
+ * tests/compExpr.test: to post-TIP-232 world.
+ * tests/expr-old.test:
+ * tests/expr.test:
+ * tests/info.test:
- * unix/tclUnixChan.c: initial remedy for [Bug 525783] flush problem
- introduced by TIP #35. This may not satisfy true serial channels, but
- it restores the correct flushing of std* channels on exit.
+ * tests/indexObj.test: Corrected other test errors revealed by
+ * tests/upvar.test: testing outside the tcltest application.
- * unix/README: added --enable-langinfo doc.
+ * generic/tclPathObj.c: Revised fix for the [Bug 1379287] family of
+ path normalization bugs.
- * unix/tcl.spec:
- * tools/tcl.wse.in: fixed URL refs to use www.tcl.tk or SF.
+2006-04-06 Daniel Steffen <das@users.sourceforge.net>
-2002-03-04 Jeff Hobbs <jeffh@ActiveState.com>
+ * unix/tcl.m4: removed TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
+ define on Darwin. [Bug 1457515]
+ * unix/configure: autoconf-2.59
+ * unix/tclConfig.h.in: autoheader-2.59
- * README:
- * mac/README:
- * unix/Makefile.in:
- * unix/README:
- * win/README:
- * win/README.binary: updated to use www.tcl.tk URL.
+2006-04-05 Don Porter <dgp@users.sourceforge.net>
- * unix/Makefile.in: added older ChangeLogs to dist target.
+ * win/tclWinInit.c: More careful calls to Tcl_DStringSetLength()
+ * win/tclWinSock.c: to avoid creating invalid DString states. Bump
+ * win/tclWinDde.c: to version 1.3.2. [RFE 1366195]
+ * library/dde/pkgIndex.tcl:
- * tests/io.test:
- * tests/encoding.test: corrected iso2022 encoding results.
- added encoding-24.*
- * generic/tclEncoding.c (EscapeFromUtfProc): corrected output of
- escape codes as per RFC 1468. [Patch 474358] (taguchi)
- (TclFinalizeEncodingSubsystem): corrected potential double-free
- when encodings were finalized on exit. [Bug 219314, 524674]
+ * library/reg/pkgIndex.tcl: Bump to registry 1.2 because
+ * win/tclWinReg.c: Registry_Unload() is a new public routine
+ * win/Makefile.in: compared to the 1.1.* releases.
-2002-03-01 Jeff Hobbs <jeffh@ActiveState.com>
+ * win/configure.in: Bump package version numbers.
+ * win/configure: autoconf 2.59
- * library/encoding/iso2022-jp.enc:
- * library/encoding/iso2022.enc:
- * tools/encoding/iso2022-jp.esc:
- * tools/encoding/iso2022.esc: gave <ESC>$B precedence over <ESC>$@,
- based on comments (point 1) in [Bug 219283] (RFC 1468)
+2006-04-05 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * tests/encoding.test: added encoding-23.* tests
- * generic/tclIO.c (FilterInputBytes): reset the TCL_ENCODING_START
- flags in the ChannelState when using 'gets'. [Bug 523988]
- Also reduced the value of ENCODING_LINESIZE from 30 to 20 as this
- seems to improve the performance of 'gets' according to tclbench.
+ * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct): Allow empty
+ strings to be matched by the Tcl_GetIndexFromObj machinery, in the
+ same manner as any other key. [Bug 1464039]
-2002-02-28 Jeff Hobbs <jeffh@ActiveState.com>
+2006-04-03 Andreas Kupries <andreask@activestate.com>
- * generic/tclCmdMZ.c (TraceCommandProc): ensure that TraceCommandInfo
- structure was also deleted when a command was deleted to prevent a
- mem leak.
+ * generic/tclIO.c (ReadChars): Added check, panic and commentary to a
+ piece of code which relies on BUFFER_PADDING to create enough space at
+ the beginning of each buffer for the insertion of partial multibyte
+ data at the beginning of a buffer. Commentary explains why this code
+ is OK, and the panic is as a precaution if someone twiddled the
+ BUFFER_PADDING into uselessness.
- * generic/tclBasic.c (Tcl_CreateObjTrace): set tracePtr->flags
- correctly.
+ * generic/tclIO.c (ReadChars): Temporarily suppress the use of
+ TCL_ENCODING_END set when EOF was reached while the buffer we are
+ converting is not truly the last buffer in the queue. Together with
+ the Utf bug below it was possible to completely wreck the buffer data
+ structures, eventually crashing Tcl. [Bug 1462248]
- * generic/tclTimer.c (TimerExitProc): remove remaining events in
- tls on thread exit.
+ * generic/tclEncoding.c (UtfToUtfProc): Stop accessing memory beyond
+ the end of the input buffer when TCL_ENCODING_END is set and the last
+ bytes of the buffer start a multi-byte sequence. This bug contributed
+ to [Bug 1462248].
-2002-02-28 Miguel Sofer <msofer@users.sourceforge.net>
+2006-03-30 Miguel Sofer <msofer@users.sf.net>
- * generic/tclNamesp.c: allow cached fully-qualified namespace names to
- be usable from different namespaces within the same interpreter
- without forcing a new lookup [Patch 458872].
+ * generic/tclExecute.c: remove unused var and silence gcc warning
-2002-02-28 Miguel Sofer <msofer@users.sourceforge.net>
+2006-03-29 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/tclExecute.c: Replaced a few direct stack accesses with the
- POP_OBJECT() macro [Bug 507181] (Don Porter).
+ * win/Makefile.in: convert _NATIVE paths to use / to avoid ".\"
+ path-as-escape issue.
-2002-02-27 Don Porter <dgp@users.sourceforge.net>
+2006-03-29 Don Porter <dgp@users.sourceforge.net>
- * doc/GetIndex.3:
- * generic/tcl.decls (Tcl_GetIndexFromObjStruct):
- * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct): Revised the
- prototype of the Tcl_GetIndexFromObjStruct to take its struct
- table as a (CONST VOID *) argument, better describing what it is,
- maintaining source compatibility, and adding CONST correctness
- according to TIP 27. Thanks to Joe English for an elegant
- solution. [Bug 520304]
+ * changes: Updates for another RC.
- * generic/tclDecls.h: make genstubs
+ * generic/tclPathObj.c: More fixes for path normalization when /../
+ * tests/fileSystem.test: tries to go beyond root.[Bug 1379287]
- * generic/tclMain.c (Tcl_Main,StdinProc): Corrected some reference
- count management errors on the interactive command Tcl_Obj found by
- Purify. Thanks to Jeff Hobbs for the report and assistance.
+ * generic/tclExecute.c: Revised INST_MOD implementation to do
+ calculations in native types as much as possible, moving to mp_ints
+ only when necessary.
-2002-02-27 Jeff Hobbs <jeffh@ActiveState.com>
+2006-03-28 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/tclBasic.c (Tcl_EvalTokensStandard): corrected mem leak
- in error case.
+ * win/tclWinPipe.c (TclpCreateProcess): change panics to Tcl errors
+ and do proper refcounting of noe objPtr. [Bug 1194429]
- * generic/tclTest.c (TestStatProc[123]): correct harmless UMRs.
+ * unix/tcl.m4, win/tcl.m4: []-quote AC_DEFUN functions.
- * generic/tclLink.c (Tcl_LinkVar): correct mem leak in error case.
+2006-03-28 Daniel Steffen <das@users.sourceforge.net>
-2002-02-27 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+ * macosx/Tcl.xcode/default.pbxuser: add '-singleproc 1' cli arg to
+ * macosx/Tcl.xcodeproj/default.pbxuser: tcltest to ease test debugging
- * tests/socket.test (2.7): Accepted and applied patch for [Bug 523470]
- provided by Don Porter <dgp@users.sourceforge.net> to avoid timing
- problems in that test.
+ * macosx/Tcl.xcode/project.pbxproj: removed $prefix/share from
+ * macosx/Tcl.xcodeproj/project.pbxproj: TCL_PACKAGE_PATH as per change
+ to unix/configure.in of 2006-03-13.
- * unix/tclUnixChan.c (TclpOpenFileChannel): Added code to regonize
- "/dev/tty" (by name) and to not handle it as tty / serial line. This
- is the controlling terminal and is special. Setting it into raw mode
- as is done for other tty's is a bad idea. This is a hackish fix for
- expect [Bug 520624]. The fix has limitation: Tcl_MakeFileChannel
- handles tty's specially too, but is unable to recognize /dev/tty as it
- only gets a file descriptor, and no name for it.
+ * unix/tclUnixFCmd.c (TclpObjNormalizePath): deal with *BSD/Darwin
+ realpath() converting relative paths into absolute paths [Bug 1064247]
-2002-02-26 Jeff Hobbs <jeffh@ActiveState.com>
+2006-03-28 Vince Darley <vincentdarley@sourceforge.net>
- * generic/tclCmdAH.c (StoreStatData): corrected mem leak.
+ * generic/tclIOUtil.c: fix to nativeFilesystemRecord comparisons
+ (lesser part of [Bug 1064247])
- * generic/tclCmdMZ.c (Tcl_RegsubObjCmd): prevent obj leak in remedial
- regsub case.
+2006-03-27 Pat Thoyts <patthoyts@users.sourceforge.net>
- * generic/tclFileName.c (Tcl_TranslateFileName): decr refcount for
- error case to prevent mem leak.
+ * win/tclWinTest.c: Fixes for [Bug 1456373] (mingw-gcc issue)
- * generic/tclVar.c (Tcl_ArrayObjCmd): removed extra obj allocation.
+2006-03-27 Andreas Kupries <andreask@activestate.com>
- * unix/tclUnixSock.c (Tcl_GetHostName): added an extra gethostbyname
- check to guard against failure with truncated names returned by uname.
+ * doc/CrtChannel.3: Added TCL_CHANNEL_VERSION_5, made it the
+ * generic/tcl.h: version where the "truncateProc" is defined at,
+ * generic/tclIO.c: and moved all channel drivers of Tcl to v5.
+ * generic/tclIOGT.c, generic/tclIORChan.c, unix/tclUnixChan.c:
+ * unix/tclUnixPipe.c, win/tclWinChan.c, win/tclWinConsole.c:
+ * win/tclWinPipe.c, win/tclWinSerial.c, win/tclWinSock.c:
- * unix/configure:
- * unix/tcl.m4 (SC_SERIAL_PORT): added sys/modem.h check and defined
- _XOPEN_SOURCE_EXTENDED for HP-11 to get updated header decls.
+2006-03-27 Don Porter <dgp@users.sourceforge.net>
- * unix/tclUnixChan.c: added Unix implementation of TIP #35, serial
- port support. [Patch 438509] (schroedter)
+ * generic/tclExecute.c: Merge INST_MOD computation in with the
+ INST_?SHIFT instructions, which also operate only on two integral
+ values. Also corrected flaw that made INST_BITNOT of wide values
+ require mp_int calculations. Also corrected type that missed optimized
+ handling of the tclBooleanType by the TclGetBooleanFromObj macro.
-2002-02-26 Miguel Sofer <msofer@users.sourceforge.net>
+ * changes: Updates for another RC.
- * generic/tclCmpCmds.c: (bugfix to the bugfix, hopefully the last)
- Bugfix to the new [for] compiling code: was setting a exceptArray
- parameter using another param which wasn't yet initialised, thus
- filling it with noise.
+2006-03-25 Don Porter <dgp@users.sourceforge.net>
-2002-02-25 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+ * generic/tclExecute.c: Corrections to INST_EXPON detection of
+ overflow to use mp_int calculations.
- * mac/tclMacSock.c (TcpGetOptionProc): Changed to recognize the option
- "-error". Essentially ignores the option, always returning an empty
- string.
+2006-03-24 Kevin B. Kenny <kennykb@acm.org>
-2002-02-25 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclExecute.c (TclExecuteByteCode): Added a couple of missing
+ casts to 'int' that were affecting compilablity on VC6.
- * doc/Alloc.3:
- * doc/LinkVar.3:
- * doc/ObjectType.3:
- * doc/PkgRequire.3:
- * doc/Preserve.3:
- * doc/TCL_MEM_DEBUG.3: Updated documentation to describe the ckalloc,
- ckfree, ckrealloc, attemptckalloc, and attemptckrealloc macros, and
- to accurately describe when and how they are used. [Bug 497459] (dgp)
+2006-03-24 Don Porter <dgp@users.sourceforge.net>
- * generic/tclHash.c (AllocArrayEntry, AllocStringEntry): Before
- invoking ckalloc when creating a Tcl_HashEntry, check that the amount
- of memory being allocated is at least as large as
- sizeof(Tcl_HashEntry). The previous code was allocating memory regions
- that were one or two bytes short. [Bug 521950] (dejong)
+ * generic/tclEncoding.c: Reverted latest change [Bug 506653] since it
+ reportedly killed test performance on Windows.
-2002-02-25 Miguel Sofer <msofer@users.sourceforge.net>
+ * generic/tclExecute.c: Revised INST_EXPON implementation to do
+ calculations in native types as much as possible, moving to mp_ints
+ only when necessary.
- * generic/tclBasic.c (Tcl_EvalEx): avoiding a buffer overrun reported
- by Joe English, and restoring tcl7.6 behaviour for [subst]: badly
- terminated nested scripts will raise an error and not be evaluated.
- [Bug 495207]
+2006-03-23 Don Porter <dgp@users.sourceforge.net>
-2002-02-25 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclExecute.c: Merged INST_EXPON handling in with the other
+ binary operators that operate on all number types (INST_ADD, etc.).
- * unix/tclUnixPort.h: corrected strtoll prototype mismatch on Tru64.
- * compat/strtod.c (strtod): simplified #includes
- * compat/strtol.c (strtol): gather result in a long before returning
- as a long: necessary on platforms where sizeof(int) != sizeof(long).
+ * tests/env.test: With case preserved (see 2006-03-21 commit) be sure
+ to do case-insensitive filtering. [Bug 1457065]
-2002-02-25 Daniel Steffen <das@users.sourceforge.net>
+2006-03-23 Reinhard Max <max@suse.de>
- * unix/tclLoadDyld.c: updated to use Mac OS X 10.1 dyld APIs that have
- more libdl-like semantics. [Bug 514392]
+ * unix/tcl.spec: Cleaned up and completed the spec file. An RPM can
+ now be built from the tcl source distribution with "rpmbuild -tb
+ <tarball>"
-2002-02-25 Miguel Sofer <msofer@users.sourceforge.net>
+2006-03-22 Reinhard Max <max@suse.de>
- * generic/tclCompCmds: fixing a bug in patch dated 2002-02-22, in the
- code for [for] and [while]. Under certain conditions, for long bodies,
- the exception range parameters were badly computed. Tests forthcoming:
- I still can't reproduce the conditions in the testsuite (!), although
- the bug (with assorted segfault or panic!) can be triggered from the
- console or with the new parse.bench in tclbench.
+ * tests/stack.test: Run the stack tests in subshells, so that they are
+ reported as failed tests rather than bugs in the test suite if the
+ recursion causes a segfault.
-2002-02-25 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+2006-03-21 Don Porter <dgp@users.sourceforge.net>
- * compat/strtoul.c, compat/strtol.c, compat/strtod.c: Added UCHAR,
- CONST and #includes to clean up GCC output.
+ * changes: Updates for another RC.
-2002-02-23 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclStrToD.c: One of the branches of AccumulateDecimalDigit
+ * tests/parseExpr.test: did not. [Bug 1451233]
- * compat/strtoull.c (strtoull):
- * compat/strtoll.c (strtoll):
- * compat/strtoul.c (strtoul): Fixed failure to handle leading sign
- symbols '+' and '-' and '0X' and raise overflow errors. [Bug 440916]
- Also corrects prototype and errno problems.
+ * tests/env.test: Preserve case of saved env vars. [Bug 1409272]
-2002-02-23 Mo DeJong <mdejong@users.sourceforge.net>
+2006-03-21 Daniel Steffen <das@users.sourceforge.net>
- * configure: Regen.
- * unix/tcl.m4 (SC_CONFIG_CFLAGS): Link with -n32 instead of -32 when
- building on IRIX64-6.* system. [Bug 521707]
+ * generic/tclInt.decls: implement globbing for HFS creator & type
+ * macosx/tclMacOSXFCmd.c:codes and 'hidden' flag, as documented in
+ * tests/macOSXFCmd.test: glob.n; objectified OSType handling in [glob]
+ * unix/tclUnixFile.c: and [file attributes]; fix globbing for
+ hidden files with pattern==NULL arg. [Bug 823329]
+ * generic/tclIntPlatDecls.h:
+ * generic/tclStubInit.c: make genstubs
-2002-02-22 Don Porter <dgp@users.sourceforge.net>
+2006-03-20 Andreas Kupries <andreask@activestate.com>
- * generic/tclInt.h:
- * generic/tclObj.c: renamed global variable emptyString ->
- tclEmptyString because it is no longer static.
- * generic/tclPkg.c: Fix for panic when library is loaded on a
- platform without backlinking without proper use of stubs. [Bug 476537]
+ * win/Makefile.in (install-libraries): Generate tcl8/8.4 directory
+ under Windows as well (cygwin Makefile). Related entry: 2006-03-07,
+ dgp. This moved the installation of http from 8.2 to 8.4, partially. A
+ fix of the required directory creation was done for unix on Mar 10,
+ without entry in the Changelog. This entry is for the fix of the
+ directory creation under Windows.
-2002-02-22 Jeff Hobbs <jeffh@ActiveState.com>
+ * unix/installManPage: There is always one even more broken "sed".
+ Moved the # comment starting character in the sed script to the
+ beginning of their respective lines. The AIX sed will not recognize
+ them as comments otherwise :( The actual text stays indented for
+ better association with the commands they belong to.
- * tests/regexpComp.test: updated regexp-11.[1-4] to match changes
- in regexp.test for new regsub syntax
+2006-03-20 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * unix/configure:
- * unix/tcl.m4: added --enable-64bit support for AIX-4 (using -q64
- flag) when using IBM's xlc compiler.
+ * tests/cmdAH.test, tests/fCmd.test, tests/unixFCmd.test:
+ * tests/winFCmd.test: Cleanup of some test constraint handling, and a
+ few other minor issues.
- * tests/safe.test: updated safe-8.5 and safe-8.7
- * library/safe.tcl (CheckFileName): removed the limit on
- sourceable file names (was only *.tcl or tclIndex files with no
- more than one dot and 14 chars). There is enough internal
- protection in a safe interpreter already. Fixes [Tk Bug 521560].
+2006-03-18 Vince Darley <vincentdarley@sourceforge.net>
-2002-02-22 Miguel Sofer <msofer@users.sourceforge.net>
+ * generic/tclFileName.c:
+ * doc/FileSystem.3:
+ * tests/fileName.test: Fix to [Bug 1084705] so that 'glob -nocomplain'
+ finally agrees with its documentation and doesn't swallow genuine
+ errors.
- * generic/tclCompCmds: [FR 465811]. Optimising [if], [for] and
- [while] for constant conditions; in addition, [for] and [while] are
- now compiled with the "loop rotation" optimisation (thanks to Kevin
- Kenny).
+ ***POTENTIAL INCOMPATIBILITY*** for scripts that assumed '-nocomplain'
+ removes the need for 'catch' to deal with non-understood path names.
-2002-02-22 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ Small optimisation to implementation of pattern==NULL case of TclGlob,
+ and clarification to the documentation. [Tclvfs bug 1405317]
- --- TIP#76 CHANGES ---
- * generic/tclCmdMZ.c (Tcl_RegsubObjCmd): Final-argument-less
- [regsub] returns the modified string.
- * doc/regsub.n: Updated docs.
- * tests/regexp.test: Updated and added tests.
+2006-03-18 Vince Darley <vincentdarley@sourceforge.net>
- * compat/strtoll.c (strtoll):
- * compat/strtoull.c (strtoull):
- * unix/tclUnixPort.h:
- * win/tclWinPort.h: Const-ing 64-bit compatability declarations.
- Note that the return pointer is non-const because it is entirely
- legal for the functions to be called from somewhere that owns the
- string being passed. Fixes problem reported by Larry Virden.
+ * tests/fCmd.test: added knownBug test case for [Bug 1394972]
-2002-02-21 David Gravereaux <davygrvy@pobox.com>
+ * tests/winFCmd.test:
+ * tests/tcltest.test: corrected tests to better account for behaviour
+ of writable/non-writable directories on Windows 2000/XP. This, with
+ the previous patches, closes [Bug 1193497]
- * win/mkd.bat (removed):
- * win/coffbase.txt (new):
- * win/makefile.bc:
- * win/makefile.vc: Changed the 'setup' target to stop using the
- mkd.bat file and just make the directory right in the rule. Same
- change to makefile.bc. configure.in nor Makefile.in use it.
+2006-03-17 Andreas Kupries <andreask@activestate.com>
- coffbase.txt will be the master list for our "prefered base addresses"
- set by the linker. This should improve load-time (NT only) by avoiding
- relocations. Submissions to the list by extension authors are
- encouraged.
+ * doc/chan.n: Updated with documentation for the commands 'chan
+ create' and 'chan postevent' (TIP #219).
- Added a 'tidy' target to compliment 'clean' and 'hose' to remove just
- the outputs. Also removed the $(winlibs) macro as it wasn't being
- used.
+ * doc/refchan.n: New file. Documentation of the command handler API
+ for reflected channels (TIP #219).
- Stuff left to do:
- 1) get the winhelp target to stop building in the tools/ directory.
- 2) stop using rmd.bat
- 3) add more dependacy rules.
+2006-03-17 Joe Mistachkin <joe@mistachkin.com>
- * win/tclAppInit.c: Reverted back to -r1.6, as the header file change
- to tclPort.h won't allow for easy embedded support outside of the
- source dist. Thanks to Don Porter for pointing this out to me.
+ * unix/tclUnixPort.h: Include pthread.h prior to pthread_np.h [Bug
+ 1444692]
-2002-02-21 David Gravereaux <davygrvy@pobox.com>
+ * win/tclWinTest.c: Corrected typo of 'initializeMutex' that prevented
+ successful compilation.
- * win/makefile.vc:
- * win/rules.vc: Added a new "loimpact" option that sets the
- -ws:aggressive linker option. Off by default. It's said to keep the
- heap use low at the expense of alloc speed.
+2006-03-16 Andreas Kupries <andreask@activestate.com>
- * win/tclAppInit.c: Changed #include "tcl.h" to be tclPort.h to remove
- the raw windows.h include. tclPort.h brings in windows.h already and
- lessens the pre-compiled-header mush and the randomly useless #pragma
- comment (lib,...) references throughout the big windows.h tree (as
- observed at high linker warning levels).
+ * doc/open.n: Documented the changed behaviour of 'a'ppend mode.
-2002-02-21 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * tests/io.test (io-43.1 io-44.[1234]): Rewritten to be self-contained
+ with regard to setup and cleanup. [Bug 681793]
- * generic/tcl.h: Better guessing of LP64/ILP32 architecture, but
- now sensitive to presence of (suitable) <limits.h>
+ * generic/tclIOUtil.c (TclGetOpenMode): Added the flag O_APPEND to the
+ list of POSIX modes used when opening a file for 'a'ppend. This
+ enables the proper automatic seek-to-end-on-write by the OS. See [Bug
+ 680143] for longer discussion.
-2002-02-20 Don Porter <dgp@users.sourceforge.net>
+ * tests/ioCmd.test (iocmd-13.7.*): Extended the testsuite to check the
+ new handling of 'a'.
- * generic/tcl.decls (Tcl_RegExpRange,Tcl_GetIndexFromObjStruct):
- Overlooked a few source incompatibilities. Now using CONST84.
- * generic/tclDecls.h: make genstubs
- * generic/tcl.h (Tcl_CmdObjTraceProc): silence warning from Sun
- Workshop compiler.
+2006-03-15 Andreas Kupries <andreask@activestate.com>
-2002-02-20 David Gravereaux <davygrvy@pobox.com>
+ * tests/socket.test: Extended the timeout in socket-11.11 from 10 to
+ 40 seconds to allow for really slow machines. Also extended
+ actual/expected results with value of variable 'done' to make it
+ clearer when a test fails due to a timeout. [Bug 792159]
- * win/buildall.vc.bat:
- * win/makefile.vc:
- * win/rules.vc: General clean-ups. Added compiler and linker tests for
- a) the pentium 0x0F errata, b) optimizing (not all have this), and c)
- linker v6 section alignment confusion. All these are tested first to
- make sure any D4002 or LNK1117 warnings aren't displayed. The pentium
- 0x0F errata is a recommended switch. The v5 linker's section alignment
- default is 512, but the v6 linker was changed to 4096 in an attempt to
- speed loading on Win98. I changed the default to always be 512 across
- both linkers, unless linking statically, then 4096 is used for the
- claimed speed effect. Using a 512 alignment saves 12k bytes of dead
- space in the DLL.
+2006-03-15 Vince Darley <vincentdarley@sourceforge.net>
- Added IA64 B-stepping errata switch when the compiler supports it.
+ * win/fCmd.test: add proper test constraints so the new tests don't
+ run on Unix.
- Added profiling to $(lflags) when requested and also removed the
- explict -entry option as the default works fine as is.
+2006-03-14 Andreas Kupries <andreask@activestate.com>
- Removed win/tclWinInit.c from the special case section to let it use
- the common implicit rule as the $(EXTFLAGS) macro it had was never
- referenced anywhere.
+ * generic/tclPipe.c (TclCreatePipeline): Modified the processing of
+ pipebars to fail if the last bar is followed only by redirections.
+ [Bug 768659]
-2002-02-20 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+2006-03-14 Andreas Kupries <andreask@activestate.com>
- * generic/tcl.h: Added code to guess the correct settings for
- TCL_WIDE_INT_IS_LONG and TCL_WIDE_INT_TYPE when configure doesn't tell
- us them, as can happen with extensions.
+ * doc/fconfigure.n: Clarified that -translation is binary is reported
+ as lf when queried, because it is identical to lf, except for the
+ special additional behaviour when setting it. [Bug 666770]
-2002-02-19 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+2006-03-14 Andreas Kupries <andreask@activestate.com>
- * doc/format.n: Updated docs to list the specification.
- * generic/tclCmdAH.c (Tcl_FormatObjCmd): Made behaviour on 64-bit
- platforms correctly meet the specification, that %d works with the
- native word-sized integer, instead of trying to guess (wrongly) from
- the value being passed.
+ * doc/clock.n: Removed double-quotes around section title NAME; not
+ needed.
+ * unix/installManpage: Reverted part to handle double-quotes in
+ section NAME, chokes older sed installations.
-2002-02-19 Don Porter <dgp@users.sourceforge.net>
+2006-03-14 Andreas Kupries <andreask@activestate.com>
- * changes: First draft of updated changes for 8.4a4 release.
+ * library/tm.tcl (::tcl::tm::Defaults): Fixed handling of environment
+ variable TCLX.y_TM_PATH, bad variable reference. Thanks to Julian
+ Noble. [Bug 1448251]
-2002-02-15 Jeff Hobbs <jeffh@ActiveState.com>
+2006-03-14 Vince Darley <vincentdarley@sourceforge.net>
- * unix/tclUnixPort.h: add strtoll/strtoull declarations for platforms
- that do not define them.
+ * win/tclWinFile.c: updated patch to deal with 'file writable' issues
+ on Windows XP/2000.
+ * generic/tclTest.c:
+ * unix/tclUnixTest.c:
+ * win/tclWinTest.c:
+ * tests/fCmd.test: updated test suite to deal with correct permissions
+ setting and differences between XP/2000 and 95/98 3 tests still fail;
+ to be dealt with shortly
- * generic/tclIndexObj.c (STRING_AT): removed ptrdiff_t cast and use of
- VOID* in default case (GNU-ism).
+2006-03-13 Don Porter <dgp@users.sourceforge.net>
-2002-02-15 Kevin Kenny <kennykb@acm.org>
+ * generic/tclEncoding.c: Report error when an escape encoding is
+ missing one of its sub-encodings. [Bug 506653]
- * compat/strtoll.c:
- * compat/strtoul.c:
- * compat/strtoull.c:
- * generic/tclIOUtil.c:
- * generic/tclPosixStr.c:
- * generic/tclTest.c:
- * generic/tclTestObj.c:
- * tests/get.test:
- * win/Makefile.vc: Further tweaks to the TIP 72 patch to make it
- compile under VC++.
-
-2002-02-15 Andreas Kupries <andreas_kupries@users.sourceforge.net>
-
- * tclExecute.c:
- * tclIOGT.c:
- * tclIndexObj.c: Touchups to the TIP 72 patch to make it compileable
- under Windows again. The changes are not complete, there is one nasty
- regarding _stati64
-
-2002-02-15 Donal K. Fellows <fellowsd@cs.man.ac.uk>
-
- +----------------------+
- | TIP #72 IMPLEMENTED. |
- +----------------------+
-
- There are a lot of changes from this TIP, so please see
- http://tip.tcl.tk/72.html for discussion of backward-compatability
- issues, but the main ones modifications are in:
-
- * generic/tcl.h: New types.
- * generic/tcl.decls: New public functions.
- * generic/tclExecute.c: 64-bit aware bytecode engine.
- * generic/tclBinary.c: 64-bit handling in [binary] command.
- * generic/tclScan.c: 64-bit handling in [scan] command.
- * generic/tclCmdAH.c: 64-bit handling in [file] and [format]
- commands.
- * generic/tclBasic.c: New "wordSize" entry in ::tcl_platform.
- * generic/tclFCmd.c: Large-file support (with many consequences.)
- * generic/tclIO.c: Large-file support (with many consequences.)
- * compat/strtoll.c, compat/strtoull.c: New support functions.
- * unix/tcl.m4, unix/configure: 64-bit support and greatly enhanced
- cacheing.
-
- Most other changes, including all those in doc/* and test/* as well as
- the majority in the platform directories, follow on from these.
-
- Also coming out of the woodwork:
- * generic/tclIndex.c: Better support for Cray PVP.
- * win/tclWinMtherr.c: Better Borland support.
-
- Note that, in a number of places through the Unix part of the platform
- support, there are Tcl_Platform* references. These are expanded into
- the correct way to call that particular underlying function, i.e. with
- or without a '64' suffix, and should be used by people working on the
- core in preference to the API functions they overlay so that the code
- remains portable depending on the presence or absence of 64-bit
- support on the underlying platform.
-
- ***POTENTIAL INCOMPATIBILITY***: Extracted from the TIP
-
- SUMMARY OF INCOMPATIBILITIES AND FIXES
- ======================================
-
- The behaviour of expressions containing constants that appear positive
- but which have a negative internal representation will change, as
- these will now usually be interpreted as wide integers. This is always
- fixable by replacing the constant with int(constant).
-
- Extensions creating new channel types will need to be altered as
- different types are now in use in those areas. The change to the
- declaration of Tcl_FSStat and Tcl_FSLstat (which are the new preferred
- API in any case) are less serious as no non-alpha releases have been
- made yet with those API functions.
-
- Scripts that are lax about the use of the l modifier in format and
- scan will probably need to be rewritten. This should be very uncommon
- though as previously it had absolutely no effect.
-
- Extensions that create new math functions that take more than one
- argument will need to be recompiled (the size of Tcl_Value changes),
- and functions that accept arguments of any type (TCL_EITHER) will need
- to be rewritten to handle wide integer values. (I do not expect this
- to affect many extensions at all.)
-
-2002-02-14 Andreas Kupries <andreas_kupries@users.sourceforge.net>
-
- * generic/tclIOCmd.c (Tcl_GetsObjCmd): Trivial fix for [Bug 517503], a
- memory leak reported by Miguel Sofer <msofer@users.sourceforge.net>.
- The leak happens if an error occurs for "set var [gets $chan]" and
- leak one empty object.
-
-2002-02-12 David Gravereaux <davygrvy@pobox.com>
-
- * djgpp/ (new directory)
- * djgpp/Makefile (new):
- * unix/tclAppInit.c:
- * unix/tclMtherr.c:
- * unix/tclUnixFCmd.c:
- * unix/tclUnixFile.c:
- * unix/tclUnixInit.c:
- * unix/tclUnixPort.h: Early stage of DJGPP support for building Tcl
- on DOS. Dynamic loading isn't working, yet. Requires watt32 for the
- TCP/IP stack. No autoconf, yet. Barely tested, but makes a working exe
- that runs Tcl in protected-mode, flat memory. [exec] and pipes will
- need the most work as multi-tasking on DOS has to be carefully.
+ * unix/configure.in: Revert change from 2005-07-26 that sometimes
+ * unix/configure: added $prefix/share to the tcl_pkgPath. See
+ [Patch 1231015]. autoconf-2.59.
-2002-02-10 Kevin Kenny <kennykb@acm.org>
+2006-03-10 Miguel Sofer <msofer@users.sf.net>
- * doc/CrtObjCmd.3:
- * doc/CrtTrace.3:
- * generic/tcl.decls:
- * generic/tcl.h:
- * generic/tclBasic.c:
- * generic/tclInt.h:
- * generic/tclTest.c:
- * tests/basic.test: Added Tcl_CreateObjTrace,
- Tcl_GetCommandInfoFromToken and Tcl_SetCommandInfoFromToken.
- (TIPs #32 and #79.)
+ * generic/tclProc.c (ObjInterpProcEx):
+ * tests/apply.test (apply-5.1): Fix [apply] error messages so that
+ they quote the lambda expression. [Bug 1447355]
- * generic/tclDecls.h:
- * generic/tclStubInit.c: Regenerated Stubs tables.
+2006-03-10 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
-2002-02-08 Jeff Hobbs <jeffh@ActiveState.com>
+ -- Summary of changes fixing [Bug 1437595] --
- * unix/configure:
- * unix/tcl.m4: added -pthread for FreeBSD to EXTRA_CFLAGS and
- LDFLAGS. Also triggered nodots only for FreeBSD-3.
- Added AC_DEFINE(_POSIX_PTHREAD_SEMANTICS) for Solaris.
+ * generic/tclEvent.c: Cosmetic touches and identation
+ * generic/tclInt.h: Added TclpFinalizeSockets() call.
- * unix/tclUnixPort.h:
- * unix/tclUnixThrd.c: added thread-safe versions of readdir,
- localtime, gmtime and inet_ntoa for threaded build. (jgdavidson)
+ * generic/tclIO.c: Calls TclpFinalizeSockets() as part of the
+ TclFinalizeIOSubsystem().
- * generic/tclScan.c (Tcl_ScanObjCmd): prevented ckfree being
- called on a pointer to NULL.
+ * unix/tclUnixSock.c: Added no-op TclpFinalizeSockets().
-2002-02-07 Don Porter <dgp@users.sourceforge.net>
+ * win/tclWinPipe.c, win/tclWinSock.c: Finalization of sockets/pipes is
+ now solely done in TclpFinalizeSockets() and TclpFinalizePipes() and
+ not over the thread-exit handler, because the order of actions the Tcl
+ generic core will impose may result in cores/hangs if the thread exit
+ handler tears down corresponding subsystem(s) too early.
- * doc/DString.3:
- * doc/Encoding.3:
- * doc/GetCwd.3:
- * doc/SplitPath.3:
- * doc/Translate.3:
- * doc/Utf.3:
- * generic/tcl.decls:
- * generic/tcl.h:
- * generic/tclEncoding.c:
- * generic/tclEnv.c:
- * generic/tclFileName.c:
- * generic/tclIOUtil.c:
- * generic/tclUtf.c:
- * generic/tclUtil.c:
- * mac/tclMacInit.c:
- * unix/tclUnixFile.c:
- * unix/tclUnixInit.c:
- * unix/tclUnixPipe.c:
- * win/tclWin32Dll.c:
- * win/tclWinFCmd.c:
- * win/tclWinFile.c:
- * win/tclWinInit.c: Partial TIP 27 rollback. Following routines
- restored to return (char *): Tcl_DStringAppend,
- Tcl_DStringAppendElement, Tcl_JoinPath, Tcl_TranslateFileName,
- Tcl_ExternalToUtfDString, Tcl_UtfToExternalDString,
- Tcl_UniCharToUtfDString, Tcl_GetCwd, Tcl_WinTCharToUtf. Also
- restored Tcl_WinUtfToTChar to return (TCHAR *) and
- Tcl_UtfToUniCharDString to return (Tcl_UniChar *). Modified
- some callers. This change recognizes that Tcl_DStrings are
- de-facto white-box objects.
+2006-03-10 Vince Darley <vincentdarley@sourceforge.net>
- * generic/tclDecls.h:
- * generic/tclPlatDecls.h: make genstubs
+ * win/tclWinFile.c: previous patch breaks tests, so removed.
- * generic/tclCmdMZ.c: corrected use of C++-style comment.
+2006-03-09 Vince Darley <vincentdarley@sourceforge.net>
-2002-02-06 Jeff Hobbs <jeffh@ActiveState.com>
+ * win/tclWinFile.c: fix to 'file writable' in certain XP directories.
+ Thanks to fvogel and jfg. [Patch 1344540] Modified patch to make use
+ of existing use of getSecurityProc.
- * tests/scan.test:
- * generic/tclScan.c (Tcl_ScanObjCmd): corrected scan 0x... %x handling
- that didn't accept the 0x as a prelude to a base 16 number. [Bug
- 495213]
+2006-03-08 Don Porter <dgp@users.sourceforge.net>
- * generic/tclCompCmds.c (TclCompileRegexpCmd): made early check
- for bad RE to stop checking further.
+ * generic/tclExecute.c: Complete missing bit of TIP 215 implementation
+ * tests/incr.test:
- * generic/tclCmdMZ.c (Tcl_RegsubObjCmd): added special case to
- search for simple 'string map' style regsub calls.
- Delayed creation of resultPtr object until an initial match is
- made, as the input string object can then be reused for no matches.
- (Tcl_StringObjCmd): optimization improvements to the STR_MAP
- algorithm for zero-length and nocase cases.
+2006-03-07 Joe English <jenglish@users.sourceforge.net>
- * tests/regexp.test:
- * tests/regexpComp.test: extra code coverage tests.
+ * unix/tcl.m4: Set SHLIB_LD_FLAGS='${LIBS}' on NetBSD, as per the
+ other *BSD variants. [Bug 1334613]
+ * unix/configure: Regenerated.
- * tests/string.test: added 10.18 and 10.19 extra tests.
+2006-03-07 Don Porter <dgp@users.sourceforge.net>
- * generic/regc_locale.c (casecmp): slight performance improvement.
+ * changes: Update in prep. for 8.5a4 release.
-2002-02-05 Don Porter <dgp@users.sourceforge.net>
+ * unix/Makefile.in: Package http 2.5.2 requires Tcl 8.4, so the
+ * win/Makefile.in: *.tm installation has to be placed in an "8.4"
+ directory, not an "8.2" directory.
- * library/http/http.tcl:
- * library/http/pkgIndex.tcl: Corrected use of http::error when
- ::error was intended. Bump to http 2.4.2.
+2006-03-06 Don Porter <dgp@users.sourceforge.net>
-2002-02-04 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+ * generic/tclBasic.c: Revised handling of TCL_EVAL_* flags to
+ * tests/parse.test: simplify TclEvalObjvInternal and to correct
+ the auto-loading of alias targets (parse-8.12). [Bug 1444291]
- * unix/tclUnixChan.c (FileOutputProc): Fixed [bug 465765] reported by
- Dale Talcott <daletalcott@users.sourceforge.net>. Avoid writing
- nothing into a file as STREAM based implementations will consider this
- a EOF (if the file is a pipe). Not done in the generic layer as this
- type of writing is actually useful to check the state of a socket.
+2006-03-03 Don Porter <dgp@users.sourceforge.net>
- * doc/open.n: Fixed [Bug 511540], added cross-reference to 'pid' as
- the command to use to retrieve the pid of a command pipeline created
- via 'open'.
+ * generic/tclPathObj.c: Revised yesterday's fix for [Bug 1379287] to
+ work on Windows.
-2002-02-01 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclObj.c: Compatibility support for existing code that
+ calls Tcl_GetObjType("boolean").
- * generic/tclCmdMZ.c (Tcl_RegexpObjCmd): handle quirky about case
- earlier to avoid shimmering problem.
+2006-03-02 Don Porter <dgp@users.sourceforge.net>
-2002-02-01 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+ * generic/tclPathObj.c: Fix for failed normalization of paths
+ * tests/fileSystem.test: with /../ that lead back to the root
+ of the filesystem, like /foo/.. [Bug 1379287]
- * tests/io.test: io-39.22 split into two tests, one platform
- dependent, the other not. -eofchar is not empty on the windows
- platform.
+2006-03-01 Reinhard Max <max@suse.de>
-2002-02-01 Vince Darley <vincentdarley@users.sourceforge.net>
+ * unix/installManPage: Fix the script for manpages that have quotes
+ around the .SH arguments, as doctools produces them. [Bug 1292145]
+ Some minor cleanups and improvements.
- * generic/tclTest.c: fix to picky windows compiler problem with the
- 'MainLoop' function declaration.
+2006-02-28 Don Porter <dgp@users.sourceforge.net>
-2002-01-31 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+ * generic/tclBasic.c: Corrections to be sure that TCL_EVAL_GLOBAL
+ * tests/namespace.test: evaluations act the same as [uplevel #0]
+ * tests/parse.test: evaluations, even when execution traces or
+ * tests/trace.test: invocations of [::unknown] are present. [Bug
+ 1439836]
- * win/tclWinFCmd.c: TIP 27: Applied patch fixing CONST warnings on
- behalf of Don Porter <dgp@users.sourceforge.net>.
+2006-02-22 Don Porter <dgp@users.sourceforge.net>
-2002-01-30 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclBasic.c: Corrected a few bugs in how [namespace
+ * tests/namespace.test: unknown] interacts with TCL_EVAL_* flags.
+ [Patch 958222]
- * generic/tcl.decls:
- * generic/tcl.h:
- * generic/tclInt.h: For each interface identified in the TIP 27
- changes below as a POTENTIAL INCOMPATIBILITY, the source of the
- incompatibility has been parameterized so that it can be removed. When
- compiling extension code against the Tcl header files, use the
- compiler flag -DUSE_NON_CONST to remove the irresolvable source
- incompatibilities introduced by the TIP 27 changes. Resolvable changes
- are left for extension authors to resolve.
- * generic/tclDecls.h: make genstubs
+2006-02-17 Don Porter <dgp@users.sourceforge.net>
-2002-01-30 Vince Darley <vincentdarley@users.sourceforge.net>
+ * generic/tclIORChan.c: Revised error message generation and handling
+ * tests/ioCmd.test: of exceptional return codes in the channel
+ reflection layer. [Bug 1372348]
- * doc/FileSystem.3: added documentation for 3 public functions which
- had been overlooked. Fixes [Bug 507701]
- * unix/mkLinks: make mklinks
+2006-02-16 Don Porter <dgp@users.sourceforge.net>
-2002-01-29 Jeff Hobbs <jeffh@ActiveState.com>
+ * generic/tclIndexObj.c: Disallow the "ambiguous" error message
+ * tests/indexObj.test: when TCL_EXACT matching is requested.
+ * tests/ioCmd.test:
- * tests/regexpComp.test:
- * generic/tclCompCmds.c (TclCompileRegexpCmd): enhanced to support
- -nocase and -- options.
+2006-02-15 Don Porter <dgp@users.sourceforge.net>
-2002-01-28 Mo DeJong <mdejong@users.sourceforge.net>
+ * generic/tclIO.c: Made several routines tolerant of
+ * generic/tclIORChan.c: interp == NULL arguments. [Bug 1380662]
+ * generic/tclIOUtil.c:
- * unix/tcl.m4 (SC_LOAD_TCLCONFIG):
- * win/tcl.m4 (SC_LOAD_TCLCONFIG): Set TCL_LIB_SPEC, TCL_STUB_LIB_SPEC,
- and TCL_STUB_LIB_PATH to the values of TCL_BUILD_LIB_SPEC,
- TCL_BUILD_STUB_LIB_SPEC, and TCL_BUILD_STUB_LIB_PATH when tclConfig.sh
- is loaded from the build directory. A Tcl extension should make use of
- the non-build versions of these variables since they will work in both
- cases. This modification was described in TIP #34.
+2006-02-09 Don Porter <dgp@users.sourceforge.net>
-2002-01-28 Jeff Hobbs <jeffh@ActiveState.com>
+ TIP#215 IMPLEMENTATION
- * win/tclWinReg.c (regConnectRegistryProc,RecursiveDeleteKey)
- (DeleteKey,GetKeyNames,GetType,GetValue,OpenSubKey,SetValue):
- redid the CONSTification as previous changes caused failing tests.
+ * doc/incr.n: Revised [incr] to auto-initialize when varName
+ * generic/tclExecute.c: argument is unset. [Patch 1413115]
+ * generic/tclVar.c:
+ * tests/compile.test:
+ * tests/incr-old.test:
+ * tests/incr.test:
+ * tests/set.test:
+
+ * tests/main.test (Tcl_Main-6.7): Improved robustness of
+ command auto-completion test. [Bug 1422736]
+
+2006-02-08 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/Encoding.3, doc/encoding.n: Updates due to review at request of
+ Don Porter. Mostly minor changes.
+
+2006-02-08 Don Porter <dgp@users.sourceforge.net>
+
+ TIP#258 IMPLEMENTATION
+
+ * doc/Encoding.3: New subcommand [encoding dirs].
+ * doc/encoding.n: New routine Tcl_GetEncodingNameFromEnvironment
+ * generic/tcl.decls: Made public:
+ * generic/tclBasic.c: TclGetEncodingFromObj
+ * generic/tclCmdAH.c: -> Tcl_GetEncodingFromObj
+ * generic/tclEncoding.c:TclGetEncodingSearchPath
+ * generic/tclInt.decls: -> Tcl_GetEncodingSearchPath
+ * generic/tclInt.h: TclSetEncodingSearchPath
+ * generic/tclTest.c: -> Tcl_SetEncodingSearchPath
+ * library/init.tcl: Removed commands:
+ * tests/cmdAH.test: [tcl::unsupported::EncodingDirs]
+ * tests/encoding.test: [testencoding path] (Tcltest)
+ * unix/tclUnixInit.c: [Patch 1413934]
+ * win/tclWinInit.c:
- * tests/regexpComp.test (new):
- * generic/tclInt.h:
- * generic/tclBasic.c: added TclCompileRegexpCmd entry
- * generic/tclCompCmds.c (TclCompileStringCmd): corrected to return
- TCL_OUT_LINE_COMPILE instead of TCL_ERROR for parsing errors, so
- it only throws the error for runtime compile, in case the user
- modifies 'string'.
- (TclCompileRegexpCmd): first try at a byte-compiled regexp
- command. It handles static strings and ^$ bounded static strings.
- (TclCompileAppendCmd): made TclPushVarName call always use
- TCL_CREATE_VAR as numWords is always > 2 at that point.
+ * generic/tclDecls.h: make genstubs
+ * generic/tclIntDecls.h:
+ * generic/tclStubInit.c:
- * generic/tclExecute.c (TclExecuteByteCode:INST_LIST): correct
- possibly dangerous decr in macro call.
+2006-02-01 Miguel Sofer <msofer@users.sf.net>
- * win/tclWinInit.c (TclpFindVariable): CONSTification touch-up
+ * generic/tclProc.c: minor improvements to [apply]
+ * tests/apply.test: new tests; apply-5.1 currently fails to indicate
+ missing work in error reporting
- * win/tclWinReg.c (OpenSubKey): corrected bug introduced in
- CONSTification that dropped pointer reference.
+2006-02-01 Don Porter <dgp@users.sourceforge.net>
- * ChangeLog.2000 (new file):
- * ChangeLog: broke changes from 2000 into ChangeLog.2000 to reduce
- size of the main ChangeLog.
+ TIP#194 IMPLEMENTATION
-2002-01-28 David Gravereaux <davygrvy@pobox.com>
+ * doc/apply.n: (New file) New command [apply]. [Patch 944803]
+ * doc/uplevel.n:
+ * generic/tclBasic.c:
+ * generic/tclInt.h:
+ * generic/tclProc.c:
+ * tests/apply.test: (New file)
+ * tests/proc-old.test:
+ * tests/proc.test:
- * generic/tclPlatDecls.h: Added preprocessor logic to force a typedef
- of TCHAR when __STDC__ is defined when using the uncommon -Za compiler
- switch with the microsoft compiler.
+ TIP#181 IMPLEMENTATION
-2002-01-27 Don Porter <dgp@users.sourceforge.net>
+ * doc/Namespace.3: New command [namespace unknown]. New public C
+ * doc/namespace.n: routines Tcl_(Get|Set)NamespaceUnknownHandler.
+ * doc/unknown.n: [Patch 958222]
+ * generic/tcl.decls:
+ * generic/tclBasic.c:
+ * generic/tclInt.h:
+ * generic/tclNamesp.c:
+ * tests/namespace.test:
- * doc/package.n: Documented global namespace context for script
- evaluation by [package require].
+ * generic/tclDecls.h: make genstubs
+ * generic/tclStubInit.c:
-2002-01-27 Daniel Steffen <das@users.sourceforge.net>
+ TIP#250 IMPLEMENTATION
- * generic/tclInt.decls:
- * generic/tclIntPlatDecls.h:
- * mac/tclMacChan.c:
- * mac/tclMacFCmd.c:
- * mac/tclMacFile.c:
- * mac/tclMacInit.c:
- * mac/tclMacLoad.c:
- * mac/tclMacResource.c:
- * mac/tclMacSock.c: TIP 27 CONSTification induced changes
-
- * tests/event.test:
- * tests/main.test: added catches/constraints to test that use features
- that don't exist on the mac.
-
-2002-01-25 Mo DeJong <mdejong@users.sourceforge.net>
-
- Make -eofchar and -translation options read only for server sockets.
- [Bug 496733]
-
- * generic/tclIO.c (Tcl_GetChannelOption, Tcl_SetChannelOption):
- Instead of returning nothing for the -translation option on a server
- socket, always return "auto". Return the empty string enclosed in
- quotes for the -eofchar option on a server socket. Fixup -eofchar
- usage message so that it matches the implementation.
- * tests/io.test: Add -eofchar tests and -translation tests to ensure
- options are read only on server sockets.
- * tests/socket.test: Update tests to account for -eofchar and
- -translation option changes.
-
-2002-01-25 Don Porter <dgp@users.sourceforge.net>
-
- * compat/strstr.c (strstr):
- * generic/tclCmdAH.c (Tcl_FormatObjCmd):
- * generic/tclCmdIL.c (InfoNameOfExecutableCmd):
- * generic/tclEnv.c (ReplaceString):
- * generic/tclFileName.c (ExtractWinRoot):
- * generic/tclIO.c (FlushChannel,Tcl_BadChannelOption):
- * generic/tclStringObj.c (AppendUnicodeToUtfRep):
- * generic/tclThreadTest.c (TclCreateThread):
- * generic/tclUtf.c (Tcl_UtfPrev):
- * mac/tclMacFCmd.c (TclpObjListVolumes):
- * mac/tclMacResource.c (TclMacRegisterResourceFork)
- (BuildResourceForkList):
- * win/tclWinInit.c (AppendEnvironment): Sought out and eliminated
- instances of CONST-casting that are no longer needed after the
- TIP 27 effort.
-
- * Following is [Patch 501006]
- * generic/tclInt.decls (Tcl_AddInterpResolvers, Tcl_Export)
- (Tcl_FindNamespace, Tcl_GetInterpResolvers, Tcl_ForgetImport)
- (Tcl_Import, Tcl_RemoveInterpResolvers):
- * generic/tclNamesp.c (Tcl_Export, Tcl_Import, Tcl_ForgetImport)
- (Tcl_FindNamespace):
- * generic/tclResolve.c (Tcl_AddInterpResolvers,Tcl_GetInterpResolvers,
- (Tcl_RemoveInterpResolvers): Updated APIs in generic/tclResolve.c and
- generic/tclNamesp.c according to the guidelines of TIP 27.
- * generic/tclIntDecls.h: make genstubs
-
- * Following is [Patch 505630]
- * doc/AddErrorInfo.3:
- * generic/tcl.decls (Tcl_LogCommandInfo):
- * generic/tclBasic.c (Tcl_LogCommandInfo): Updated interfaces
- of generic/tclBasic.cc according to TIP 27.
- * generic/tclDecls.h: make genstubs
-
- * Following is [Patch 506818]
- * doc/Hash.3:
- * generic/tcl.decls (Tcl_HashStats):
- * generic/tclHash.c (Tcl_HashStats): Updated APIs of generic/tclHash.c
- according to guidelines of TIP 27.
- * generic/tclDecls.h: make genstubs
- * generic/tclVar.c (Tcl_ArrayObjCmd): Updated callers.
-
- * Following is [Patch 506807]
- * doc/ObjectType.3:
- * generic/tcl.decls (Tcl_GetObjType):
- * generic/tclObj.c (Tcl_GetObjType): Updated APIs of generic/tclObj.c
- according to guidelines of TIP 27.
- * generic/tclDecls.h: make genstubs
-
- * Following is [Patch 507304]
- * doc/Encoding.3:
- * generic/tcl.decls (Tcl_WinUtfToTChar,Tcl_WinTCharToUtf):
- * win/tclWin32Dll.c (Tcl_WinUtfToTChar,Tcl_WinTCharToUtf):
- Updated interfaces in win/tclWin32Dll.c according to TIP 27.
- * generic/tclPlatDecls.h: make genstubs
- * generic/tclIOUtil.c (TclpNativeToNormalized):
- * win/tclWinFCmd.c (TclpObjNormalizePath):
- * win/tclWinFile.c (TclpFindExecutable,TclpMatchInDirectory)
- (NativeIsExec,NativeStat):
- * win/tclWinLoad.c (TclpLoadFile):
- * win/tclWinPipe.c (TclpOpenFile,ApplicationType):
- * win/tclWinReg.c (regConnectRegistryProc,RecursiveDeleteKey,DeleteKey)
- (GetKeyNames,GetType,GetValue,OpenSubKey,SetValue):
- * win/tclWinSerial.c (SerialSetOptionProc): Update callers.
-
- * Following is [Patch 505072]
- * doc/Concat.3:
- * doc/Encoding.3:
- * doc/Filesystem.3:
- * doc/Macintosh.3:
- * doc/OpenFileChnl.3
- * doc/SetResult.3:
- * doc/SetVar.3:
- * doc/SplitList.3:
- * doc/SplitPath.3:
- * doc/Translate.3:
- * generic/tcl.h (Tcl_FSMatchInDirectoryProc):
- * generic/tclInt.h (TclpMatchInDirectory):
- * generic/tcl.decls (Tcl_Concat,Tcl_GetStringResult,Tcl_GetVar,
- (Tcl_GetVar2,Tcl_JoinPath,Tcl_Merge,Tcl_OpenCommandChannel,Tcl_SetVar)
- (Tcl_SetVar2,Tcl_SplitList,Tcl_SplitPath,Tcl_TranslateFileName)
- (Tcl_ExternalToUtfDString,Tcl_GetEncodingName,Tcl_UtfToExternalDString)
- (Tcl_GetDefaultEncodingDir,Tcl_SetDefaultEncodingDir)
- (Tcl_FSMatchInDirectory,Tcl_MacEvalResource,Tcl_MacFindResource):
- * generic/tclInt.decls (TclCreatePipeline,TclGetEnv,TclpGetCwd,
- (TclpCreateProcess):
- * mac/tclMacFile.c (TclpGetCwd):
- * generic/tclEncoding.c (Tcl_GetDefaultEncodingDir)
- (Tcl_SetDefaultEncodingDir,Tcl_GetEncodingName)
- (Tcl_ExternalToUtfDString,Tcl_UtfToExternalDString, OpenEncodingFile)
- (LoadEscapeEncoding):
- * generic/tclFileName.c (DoTildeSubst,Tcl_JoinPath,Tcl_SplitPath,
- (Tcl_TranslateFileName):
- * generic/tclIOUtil.c (Tcl_FSMatchInDirectory):
- * generic/tclPipe.c (FileForRedirect,TclCreatePipeline)
- (Tcl_OpenCommandChannel):
- * generic/tclResult.c (Tcl_GetStringResult):
- * generic/tclUtil.c (Tcl_Concat,Tcl_SplitList,Tcl_Merge):
- * generic/tclVar.c (Tcl_GetVar,Tcl_GetVar2,Tcl_SetVar,Tcl_SetVar2):
- * mac/tclMacResource.c (Tcl_MacEvalResource,Tcl_MacFindResource):
- Updated interfaces of generic/tclEncoding, generic/tclFilename.c,
- generic/tclIOUtil.c, generic/tclPipe.c, generic/tclResult.c,
- generic/tclUtil.c, generic/tclVar.c and mac/tclMacResource.c according
- to TIP 27. Tcl_TranslateFileName rewritten as wrapper around
- VFS-aware version.
- ***POTENTIAL INCOMPATIBILITY***
- Includes source incompatibilities: argv arguments of Tcl_Concat,
- Tcl_JoinPath, Tcl_OpenCommandChannel, Tcl_Merge; argvPtr arguments of
- Tcl_SplitList and Tcl_SplitPath.
- * generic/tclDecls.h:
- * generic/tclIntDecls.h: make genstubs
-
- * generic/tclCkalloc.c (MemoryCmd):
- * generic/tclClock.c (FormatClock):
- * generic/tclCmdAH.c (Tcl_CaseObjCmd,Tcl_EncodingObjCmd,Tcl_FileObjCmd):
- * generic/tclCmdIL.c (InfoLibraryCmd,InfoPatchLevelCmd,
- (InfoTclVersionCmd):
- * generic/tclCompCmds.c (TclCompileForeachCmd):
- * generic/tclCompCmds.h (TclCompileForeachCmd):
- * generic/tclCompile.c (TclFindCompiledLocal):
- * generic/tclEnv.c (TclSetupEnv,TclSetEnv,Tcl_PutEnv,TclGetEnv,
- (EnvTraceProc):
- * generic/tclEvent.c (Tcl_BackgroundError):
- * generic/tclIO.c (Tcl_BadChannelOption,Tcl_SetChannelOption):
- * generic/tclIOCmd.c (Tcl_ExecObjCmd,Tcl_OpenObjCmd):
- * generic/tclIOSock.c (TclSockGetPort):
- * generic/tclIOUtil.c (SetFsPathFromAny):
- * generic/tclLink.c (LinkTraceProc):
- * generic/tclMain.c (Tcl_Main):
- * generic/tclNamesp.c (TclTeardownNamespace):
- * generic/tclProc.c (TclCreateProc):
- * generic/tclTest.c (TestregexpObjCmd,TesttranslatefilenameCmd,
- (TestchmodCmd,GetTimesCmd,TestsetCmd,TestOpenFileChannelProc1,
- (TestOpenFileChannelProc2,TestOpenFileChannelProc3,AsyncHandlerProc,
- (TestpanicCmd):
- * generic/tclThreadTest.c (ThreadErrorProc,ThreadEventProc):
- * generic/tclUtil.c (TclPrecTraceProc):
- * mac/tclMacFCmd.c (GetFileSpecs):
- * mac/tclMacFile.c (TclpMatchInDirectory):
- * mac/tclMacInit.c (TclpInitLibraryPath,Tcl_SourceRCFile):
- * mac/tclMacOSA.c (tclOSAStore,tclOSALoad):
- * mac/tclMacResource.c (Tcl_MacEvalResource):
- * unix/tclUnixFCmd.c (TclpObjNormalizePath):
- * unix/tclUnixFile.c (TclpMatchInDirectory,TclpGetUserHome,TclpGetCwd,
- (TclpReadLink):
- * unix/tclUnixInit.c (TclpInitLibraryPath,TclpSetVariables,
- (Tcl_SourceRCFile):
- * unix/tclUnixPipe.c (TclpOpenFile,TclpCreateTempFile,
- (TclpCreateProcess):
- * win/tclWinFile.c (TclpGetCwd,TclpMatchInDirectory):
- * win/tclWinInit.c (TclpInitLibraryPath,Tcl_SourceRCFile,
- (TclpSetVariables):
- * win/tclWinPipe.c (TclpCreateProcess): Updated callers.
-
-2002-01-24 Don Porter <dgp@users.sourceforge.net>
-
- * generic/tclIOUtil.c (SetFsPathFromAny): Corrected tilde-substitution
- of pathnames where > 1 separator follows the ~. [Bug 504950]
-
-2002-01-24 Jeff Hobbs <jeffh@ActiveState.com>
+ * doc/namespace.n: New command [namespace upvar]. [Patch 1275435]
+ * generic/tclInt.h:
+ * generic/tclNamesp.c:
+ * generic/tclVar.c:
+ * tests/namespace.test:
+ * tests/upvar.test:
- * library/http/pkgIndex.tcl:
- * library/http/http.tcl: don't add port in default case to handle
- broken servers. http bumped to 2.4.1 [Bug 504508]
-
-2002-01-23 Andreas Kupries <andreas_kupries@users.sourceforge.net>
-
- * unix/mkLinks: Regenerated.
- * doc/CrtChannel.3:
- * doc/ChnlStack.3: Moved documentation for 'Tcl_GetTopChannel' from
- 'CrtChannel' to 'ChnlStack'. Added documentation of
- 'Tcl_GetStackedChannel'. [Bug 506147] reported by Mark Patton
- <msp@users.sourceforge.net>
-
-2002-01-23 Don Porter <dgp@users.sourceforge.net>
-
- * win/tclWinFile.c (NativeAccess,NativeStat,NativeIsExec,
- (TclpGetUserHome):
- * win/tclWinPort.h (TclWinSerialReopen):
- * win/tclWinSerial.c (TclWinSerialReopen):
- * win/tclWinSock.c (Tcl_OpenTcpServer): Corrections to earlier TIP
- #27 changes. Thanks to Andreas Kupries for the feedback.
- * generic/tclPlatDecls.h: make genstubs
-
- * doc/GetHostName.3:
- * doc/GetOpnFl.3:
- * doc/OpenTcp.3:
- * tcl.decls (Tcl_GetHostName,Tcl_GetOpenFile,Tcl_OpenTcpClient,
- (Tcl_OpenTclServer):
- * mac/tclMacSock.c (CreateSocket,Tcl_OpenTcpClient,Tcl_OpenTcpServer,
- (Tcl_GetHostName,GetHostFromString):
- * unix/tclUnixChan.c (CreateSocket,CreateSocketAddress,
- (Tcl_OpenTcpClient,Tcl_OpenTcpServer,Tcl_GetOpenFile):
- * unix/tclUnixSock.c (Tcl_GetHostName):
- * win/tclWinSock.c (CreateSocket,CreateSocketAddress,
- (Tcl_OpenTcpClient,Tcl_OpenTcpServer,Tcl_GetHostName):
- Updated socket interfaces according to TIP 27.
- * generic/tclCmdIL.c (InfoHostnameCmd): Updated callers.
- * generic/tclDecls.h: make genstubs
-
-2002-01-21 David Gravereaux <davygrvy@pobox.com>
-
- * generic/tclLoadNone.c: TclpLoadFile() didn't match proto of typedef
- Tcl_FSLoadFileProc. OK'd by vincentdarley. [Patch 502488]
-
-2002-01-21 Andreas Kupries <andreas_kupries@users.sourceforge.net>
-
- * generic/tclIO.c (WriteChars): Fix for [Bug 506297], reported by
- Martin Forssen <ruric@users.sourceforge.net>. The encoding chosen in
- the script exposing the bug writes out three intro characters when
- TCL_ENCODING_START is set, but does not consume any input as
- TCL_ENCODING_END is cleared. As some output was generated the
- enclosing loop calls UtfToExternal again, again with START set. Three
- more characters in the out and still no use of input ... To break this
- infinite loop we remove TCL_ENCODING_START from the set of flags after
- the first call (no condition is required, the later calls remove an
- unset flag, which is a no-op). This causes the subsequent calls to
- UtfToExternal to consume and convert the actual input.
-
-2002-01-21 Don Porter <dgp@users.sourceforge.net>
-
- * generic/tclTest.c: Converted declarations of TestReport file system
- to more portable form. [Bug 501417].
-
- * generic/tcl.decls (Tcl_TraceCommand,Tcl_UntraceCommand,
- (Tcl_CommandTraceInfo):
- * generic/tclCmdMZ.c (Tcl_TraceCommand,Tcl_UntraceCommand,
- (Tcl_CommandTraceInfo): Updated APIs in generic/tclCmdMZ.c
- according to the guidelines of TIP 27.
- * generic/tclDecls.h: make genstubs
-
-2002-01-18 Don Porter <dgp@users.sourceforge.net>
+2006-01-26 Donal K. Fellows <dkf@users.sf.net>
- * win/tclWinChan.c:
- * win/tclWinFCmd.c:
- * win/tclWinFile.c: Overlooked callers of Tcl_FSGetNativePath
+ * doc/dict.n: Fixed silly bug in example. Thanks to Heiner Marxen
+ <heiner.marxen@unsel.de> for catching this! [Bug 1415725]
- * win/tclWinDde.c:
- * win/tclWinReg.c: Overlooked callers of Tcl_GetIndexFromObj
+2006-01-26 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
-2002-01-18 Daniel Steffen <das@users.sourceforge.net>
+ * unix/tclUnixChan.c (TclpOpenFileChannel): Tidy up and comment the
+ mess to do with setting up serial channels. This (deliberately) breaks
+ a broken FreeBSD port, indicates what we're really doing, and reduces
+ the amount of conditional compilation sections for better maintenance.
- * generic/tclThreadTest.c:
- * mac/tclMacChan.c:
- * mac/tclMacFCmd.c:
- * mac/tclMacFile.c:
- * mac/tclMacLoad.c:
- * mac/tclMacResource.c: TIP 27 CONSTification broke the mac build in a
- number of places.
+2006-01-25 Donal K. Fellows <dkf@users.sf.net>
-2002-01-17 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+ * unix/tclUnixInit.c (TclpInitPlatform): Improved conditions on when
+ to update the FP rounding mode on FreeBSD, taken from FreeBSD port.
- * generic/tclIOCmd.c (Tcl_GetsObjCmd): Fixed [Bug 504642] as reported
- by Brian Griffin <bgriffin@users.sourceforge.net>, using his patch.
- Before the patch the generic I/O layer held an unannounced reference
- to the interp result to store the read line into. This unfortunately
- has disastrous results if the channel driver executes a Tcl script to
- perform its operation, this freeing the interp result. In that case we
- are dereferencing essentially a dangling reference. It is not truly
- dangling because the object is in the free list, but this only causes
- us to smash the free list and have the error occur later somewhere
- else. The patch simply creates a new object for the line and later
- sets it into the interp result when we are done with reading.
+2006-01-23 Donal K. Fellows <dkf@users.sf.net>
-2002-01-16 Mo DeJong <mdejong@users.sourceforge.net>
+ * tests/string.test (string-12.21): Added test for [Bug 1410553] based
+ on original bug report.
- * unix/tcl.m4 (SC_LOAD_TCLCONFIG):
- * win/tcl.m4 (SC_LOAD_TCLCONFIG): Subst TCL_DBGX into
- TCL_STUB_LIB_FILE and TCL_STUB_LIB_FLAG variables so that an extension
- does not need to subst TCL_DBGX into its makefile. [Tk Bug 504356]
+2006-01-23 Miguel Sofer <msofer@users.sf.net>
-2002-01-16 Don Porter <dgp@users.sourceforge.net>
+ * generic/tclStringObj.c: fixed incorrect handling of internal rep in
+ Tcl_GetRange. Thanks to twylite and Peter Spjuth. [Bug 1410553]
- * doc/FileSystem.3:
- * doc/GetCwd.3:
- * doc/GetIndex.3:
- * generic/tcl.decls (Tcl_GetIndexFromObj, Tcl_GetIndexFromObjStruct,
- (Tcl_GetCwd, Tcl_FSFileAttrStrings, Tcl_FSGetNativePath,
- (Tcl_FSGetTranslatedStringPath):
- * generic/tcl.h (Tcl_FSFileAttrStringsProc):
- * generic/tclFCmd.c (TclFileAttrsCmd):
- * generic/tclIOUtil.c (Tcl_GetCwd,NativeFileAttrStrings,
- (Tcl_FSFileAttrStrings,Tcl_FSGetTranslatedStringPath,
- (Tcl_FSGetNativePath):
- * generic/tclIndexObj.c (Tcl_GetIndexFromObj,Tcl_GetIndexFromObjStruct):
- More TIP 27 updates in tclIOUtil.c and tclIndexObj.c that were
- overlooked before. [Patch 504671]
- ***POTENTIAL INCOMPATIBILITY***
- Includes a source incompatibility in the tablePtr arguments of the
- Tcl_GetIndexFromObj* routines.
- * generic/tclDecls.h: make genstubs
-
- * generic/tclBinary.c (Tcl_BinaryObjCmd):
- * generic/tclClock.c (Tcl_ClockObjCmd):
- * generic/tclCmdAH.c (Tcl_EncodingObjCmd, Tcl_FileObjCmd):
- * generic/tclCmdIL.c (Tcl_InfoObjCmd,Tcl_LsearchObjCmd,Tcl_LsortObjCmd):
- * generic/tclCmdMZ.c (Tcl_TraceObjCmd,Tcl_RegexpObjCmd,Tcl_RegsubObjCmd,
- (Tcl_StringObjCmd,Tcl_SubstObjCmd,Tcl_SwitchObjCmd,
- (TclTraceCommandObjCmd,TclTraceVariableObjCmd):
- * generic/tclCompCmds.c (TclCompileStringCmd):
- * generic/tclEvent.c (Tcl_UpdateObjCmd):
- * generic/tclFileName.c (Tcl_GlobObjCmd):
- * generic/tclIO.c (Tcl_FileEventObjCmd):
- * generic/tclIOCmd.c (Tcl_SeekObjCmd,Tcl_ExecObjCmd,Tcl_SocketObjCmd,
- (Tcl_FcopyObjCmd):
- * generic/tclInterp.c (Tcl_InterpObjCmd,SlaveObjCmd):
- * generic/tclNamesp.c (Tcl_NamespaceObjCmd):
- * generic/tclPkg.c (Tcl_PackageObjCmd):
- * generic/tclTest.c (Tcltest_Init,TestencodingObjCmd,TestgetplatformCmd,
- (TestlocaleCmd,TestregexpObjCmd,TestsaveresultCmd,
- (TestGetIndexFromObjStructObjCmd,TestReportFileAttrStrings):
- * generic/tclTestObj.c (TestindexObjCmd,TeststringObjCmd):
- * generic/tclTimer.c (Tcl_AfterObjCmd):
- * generic/tclVar.c (Tcl_ArrayObjCmd):
- * mac/tclMacFCmd.c (SetFileFinderAttributes):
- * unix/tclUnixChan.c (TclpOpenFileChannel):
- * unix/tclUnixFCmd.c (tclpFileAttrStrings):
- * unix/tclUnixFile.c (TclpObjAccess,TclpObjChdir,TclpObjStat,
- (TclpObjLstat):
- * win/tclWinFCmd.c (tclpFileAttrStrings): Updated callers.
-
- * doc/RegExp.3:
- * doc/Utf.3:
- * generic/tcl.decls:
- * generic/tclInt.decls:
- * generic/tclRegexp.c:
- * generic/tclUtf.c: Updated APIs in generic/tclUtf.c and
- generic/tclRegexp.c according to the guidelines of TIP 27.
- [Patch 471509]
-
- * generic/regc_locale.c (element,cclass):
- * generic/tclCmdMZ.c (Tcl_StringObjCmd):
- * generic/tclFileName.c (TclpGetNativePathType,SplitMacPath):
- * generic/tclIO.c (ReadChars):
- * mac/tclMacLoad.c (TclpLoadFile):
- * win/tclWinFile.c (TclpGetUserHome): Updated callers.
-
- * generic/tclDecls.h:
- * generic/tclIntDecls.h: make genstubs
-
- * doc/ParseCmd.3 (Tcl_ParseVar):
- * generic/tcl.decls (Tcl_ParseVar):
- * generic/tclParse.c (Tcl_ParseVar):
- * generic/tclTest.c (TestparsevarObjCmd): Updated APIs in
- generic/tclParse.c according to the guidelines of TIP 27. Updated
- callers. [Patch 501046]
- * generic/tclDecls.h: make genstubs
-
- * generic/tcl.decls (Tcl_RecordAndEval):
- * generic/tclDecls.h: make genstubs
- * generic/tclHistory.c (Tcl_RecordAndEval): Updated APIs in
- generic/tclHistory.c according to the guidelines of TIP 27.
- [Patch 504091]
-
- * doc/CrtSlave.3:
- * generic/tcl.decls (Tcl_CreateAlias, Tcl_CreateAliasObj,
- (Tcl_CreateSlave, Tcl_GetAlias, Tcl_GetAliasObj, Tcl_GetSlave):
- * generic/tclInterp.c (Tcl_CreateAlias, Tcl_CreateAliasObj,
- (Tcl_CreateSlave, Tcl_GetAlias, Tcl_GetAliasObj, Tcl_GetSlave):
- Updated APIs in the file generic/tclInterp.c according to the
- guidelines of TIP 27. [Patch 501371]
- ***POTENTIAL INCOMPATIBILITY***
- Includes a source incompatibility in the targetCmdPtr arguments of
- the Tcl_GetAlias* routines.
-
- * generic/tclDecls.h: make genstubs
-
-2002-01-15 Don Porter <dgp@users.sourceforge.net>
-
- * doc/SetErrno.3 (Tcl_ErrnoMsg): Corrected documentation for
- Tcl_ErrnoMsg; it takes an integer argument. Thanks to Georgios
- Petasis. [Bug 468183]
-
- * doc/AddErrInfo.3 (Tcl_PosixError):
- * doc/Eval.3 (Tcl_EvalFile):
- * doc/FileSystem.c (Tcl_FSOpenFileChannel,Tcl_FSOpenFileChannelProc):
- * doc/OpenFileChnl.3 (Tcl_OpenFileChannel):
- * doc/SetErrno.3 (Tcl_ErrnoId,Tcl_ErrnoMsg):
- * doc/Signal.3 (Tcl_SignalId,Tcl_SignalMsg):
- * generic/tcl.decls (Tcl_ErrnoId,TclErrnoMsg,Tcl_EvalFile,
- (Tcl_OpenFileChannel,Tcl_PosixError,Tcl_SignalId,Tcl_SignalMsg,
- (Tcl_FSOpenFileChannel):
- * generic/tcl.h (Tcl_FSOpenFileChannelProc):
- * generic/tclIO.c (FlushChannel):
- * generic/tclIOUtil.c (Tcl_OpenFileChannel,Tcl_EvalFile,TclGetOpenMode,
- (Tcl_PosixError,Tcl_FSOpenFileChannel):
- * generic/tclInt.decls (TclGetOpenMode):
- * generic/tclInt.h (TclOpenFileChannelProc_,TclGetOpenMode,
- (TclpOpenFileChannel):
- * generic/tclPipe.c (TclCleanupChildren):
- * generic/tclPosixStr.c (Tcl_ErrnoId,Tcl_ErrnoMsg,Tcl_SignalId,
- (Tcl_SignalMsg):
- * generic.tclTest.c (PretendTclpOpenFileChannel,
- (TestOpenFileChannelProc1,TestOpenFileChannelProc2,
- (TestOpenFileChannelProc3,TestReportOpenFileChannel):
- * mac/tclMacChan.c (TclpOpenFileChannel):
- * unix/tclUnixChan.c (TclpOpenFileChannel):
- * win/tclWinChan.c (TclpOpenFileChannel): Updated APIs in
- generic/tclIOUtil.c and generic/tclPosixStr.c according to the
- guidelines of TIP 27. Updated callers. [Patch 499196]
-
- * generic/tclDecls.h:
- * generic/tclIntDecls.h: make genstubs
-
- * doc/CrtChannel.3:
- * doc/OpenFileChnl.3:
- * generic/tcl.decls:
- * generic/tclIO.h:
- * generic/tclIO.c (DoWrite, Tcl_RegisterChannel, Tcl_GetChannel,
- (Tcl_CreateChannel, Tcl_GetChannelName, CloseChannel, Tcl_Write,
- (Tcl_WriteRaw, Tcl_Ungets, Tcl_BadChannelOption, Tcl_GetChannelOption,
- (Tcl_SetChannelOption, Tcl_GetChannelNamesEx, Tcl_ChannelName):
- Updated APIs in the file generic/tclIO.c according to the guidelines
- of TIP 27. Several minor documentation corrections as well. [Patch
- 503565]
- * generic/tclDecls.h: make genstubs
-
- * generic/tcl.h (Tcl_DriverOutputProc, Tcl_DriverGetOptionProc,
- (Tcl_DriverSetOptionProc):
- * generic/tclIOGT.c (TransformOutputProc, TransformGetOptionProc,
- (TransformSetOptionProc):
- * mac/tclMacChan.c (FileOutput, StdIOOutput):
- * man/tclMacSock.c (TcpGetOptionProc, TcpOutput):
- * unix/tclUnixChan.c (FileOutputProc, TcpGetOptionProc, TcpOutputProc,
- (TtyGetOptionProc, TtySetOptionProc):
- * unix/tclUnixPipe.c (PipeOuputProc):
- * win/tclWinChan.c (FileOutputProc):
- * win/tclWinConsole.c (ConsleOutputProc):
- * win/tclWinPipe.c (PipeOuputProc):
- * win/tclWinSerial.c (SerialOutputProc, SerialGetOptionProc,
- (SerialSetOptionProc):
- * win/tclWinSock.c (TcpGetOptionProc, TcpOutput): Updated channel
- driver interface according to the guidelines of TIP 27. See also [Bug
- 500348].
-
- * doc/CrtChannel.3:
- * generic/tcl.h:
- * generic/tclIO.c:
- * generic/tclIO.h:
- * generic/tclInt.h:
- * tools/checkLibraryDoc.tcl:
- Moved Tcl_EolTranslation enum declaration from generic/tcl.h to
- generic/tclInt.h (renamed to TclEolTranslation). It is not used
- anywhere in Tcl's public interface.
+ * generic/tclProc.c: fixed args handling for precompiled bodies [Bug
+ 1412695]; thanks to Uwe Traum.
-2002-01-14 Don Porter <dgp@users.sourceforge.net>
+2006-01-16 Reinhard Max <max@suse.de>
- * doc/GetIndex.3:
- * doc/WrongNumArgs.3:
- * generic/tcl.decls (Tcl_GetIndexFromObj, Tcl_GetIndexFromObjStruct,
- (Tcl_WrongNumArgs):
- * generic/tclIndexObj.c (Tcl_GetIndexFromObj, Tcl_GetIndexFromObjStruct,
- (Tcl_WrongNumArgs): Updated APIs in the file generic/tclIndexObj.c
- according to the guidelines of TIP 27. [Patch 501491]
- * generic/tclDecls.h: make genstubs
+ * generic/tclPipe.c (FileForRedirect): Prevent nameString from being
+ freed without having been initialized.
+ * tests/exec.test: Added a test for the above.
-2002-01-11 Mo DeJong <mdejong@users.sourceforge.net>
+2006-01-12 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
- * unix/configure: Regen.
- * unix/configure.in:
- * win/configure: Regen.
- * win/configure.in: Use ${libdir} instead of ${exec_prefix}/lib
- to properly support the --libdir option to configure. [Bug 489370]
-
-2002-01-11 Andreas Kupries <andreas_kupries@users.sourceforge.net>
-
- * win/tclWinSerial.c (SerialSetOptionProc): Applied patch for [Bug
- 500348] supplied by Rolf Schroedter <schroedter@users.sf.net>. The
- function modified the contents of the the 'value' string and now does
- not do this anymore. This is a followup to the change made on
- 2001-12-17.
-
-2002-01-11 David Gravereaux <davygrvy@pobox.com>
-
- * win/makefile.vc: Removed -GD compiler option. It was intended for
- future use, but MS is again changing the future at their whim. The
- D4002 warning was harmless though, but someone using VC .NET logged it
- as a concern. [Bug 501565]
-
-2002-01-11 Mo DeJong <mdejong@users.sourceforge.net>
-
- * unix/Makefile.in: Burn Tcl build directory into tcltest executable
- to avoid crashes caused by ld loading a previously installed version
- of the tcl shared library. [Bug 218110]
-
-2002-01-10 Don Porter <dgp@users.sourceforge.net>,
- Kevin Kenny <kennykb@users.sourceforge.net>
-
- * unix/tclLoadDld.c (TclpLoadFile): syntax error: unbalanced parens.
- Kevin notes that it's far from clear that this file is ever included
- in an actual build; Linux without dlopen appears to be a nonexistent
- configuration.
-
-2002-01-08 Don Porter <dgp@users.sourceforge.net>,
- Kevin Kenny <kennykb@users.sourceforge.net>
-
- * doc/StaticPkg.3 (Tcl_StaticPackage):
- * generic/tcl.decls (Tcl_StaticPackage):
- * generic/tclDecls.h (Tcl_StaticPackage):
- * generic/tclInt.decls (TclGuessPackageName):
- * generic/tclInt.h (TclGuessPackageName):
- * generic/tclLoad.c (Tcl_StaticPackage):
- * generic/tclLoadNone.c (TclGuessPackageName):
- * mac/tclMacLoad.c (TclGuessPackageName):
- * unix/tclLoadAout.c (TclGuessPackageName):
- * unix/tclLoadDl.c (TclGuessPackageName):
- * unix/tclLoadDld.c (TclGuessPackageName):
- * unix/tclLoadDyld.c (TclGuessPackageName):
- * unix/tclLoadNext.c (TclGuessPackageName):
- * unix/tclLoadOSF.c (TclGuessPackageName):
- * unix/tclLoadShl.c (TclGuessPackageName):
- * win/tclWinLoad.c (TclGuessPackageName): Updated APIs in the files
- */tcl*Load*.c according to the guidelines of TIP 27. [Patch 501096]
-
-2002-01-09 Don Porter <dgp@users.sourceforge.net>
-
- * generic/tclTest.c (MainLoop):
- * tests/main.test (Tcl_Main-1.{3,4,5,6}): Corrected some non-portable
- tests from the new Tcl_Main changes. Thanks to Kevin Kenny.
-
-2002-01-07 Don Porter <dgp@users.sourceforge.net>
-
- * generic/tclEvent.c (TclInExit):
- * generic/tclIOUtil.c (SetFsPathFromAbsoluteNormalized,
- (SetFsPathFromAny,Tcl_FSNewNativePath,DupFsPathInternalRep):
- * generic/tclListObj.c (TclLsetList,TclLsetFlat): Added some type
- casts to satisfy picky compilers.
-
- * generic/tclMain.c: Bug fix: neglected the NULL case in
- TclGetStartupScriptFileName(). Broke Tk/wish.
-
-2002-01-05 Don Porter <dgp@users.sourceforge.net>
-
- * doc/Tcl_Main.3:
- * generic/tclMain.c: Substantial rewrite and expanded documentation
- of Tcl_Main to correct a number of bugs and flaws:
-
- * Interactive Tcl_Main can now enter a main loop, exit that
- loop and continue interactive operations. The loop may even
- exit in the midst of interactive command typing without loss
- of the partial command. [Bugs 486453, 474131]
- * Tcl_Main now gracefully handles deletion of its master
- interpreter.
- * Interactive Tcl_Main can now operate with non-blocking stdin
- * Interactive Tcl_Main can now detect EOF on stdin even in
- mid-command. [Bug 491341]
- * Added VFS-aware internal routines for managing the startup
- script selection.
- * Tcl variable 'tcl_interactive' is now linked to C variable
- 'tty' so that one can disable/enable interactive prompts at
- the script level when there is no startup script. This is
- meant for use by the test suite.
- * Consistent use of the Tcl libraries standard channels as
- returned by Tcl_GetStdChannel(); as opposed to the channels
- named 'stdin', 'stdout', and 'stderr' in the master interp,
- which can be different or unavailable.
- * Tcl_Main now calls Tcl_Exit() if evaluation of [exit] in the
- master interpreter returns, assuring Tcl_Main does not
- return.
- * Documented Tcl_Main's absence from public stub table
- * Documented that Tcl_Main does not return.
- * Documented Tcl variables set by Tcl_Main.
- * All prompts are done from a single procedure, Prompt.
- * Use of Tcl_Obj-enabled interfaces everywhere.
-
- * generic/tclInt.decls (TclGetStartupScriptPath,
- (TclSetStartupScriptPath): New internal VFS-aware routines for
- managing the startup script of Tcl_Main.
- * generic/tclIntDecls.h:
- * generic/tclStubInit.c: make genstubs
+ * generic/tclPathObj.c (Tcl_FSGetInternalRep): backported patch from
+ core-8-4-branch. A freed pointer has been overwritten causing all
+ sorts of coredumps.
- * generic/tclTest.c (TestsetmainloopCmd,TestexitmainloopCmd,
- (Tcltest_Init,TestinterpdeleteCmd):
- * tests/main.test (new): Added new file to test suite that thoroughly
- tests generic/tclMain.c; added some new test commands for testing
- Tcl_SetMainLoop().
+2006-01-12 Vince Darley <vincentdarley@sourceforge.net>
-2002-01-04 Don Porter <dgp@users.sourceforge.net>
+ * win/tclWinFile.c: fix to sharing violation [Bug 1366227]
- * doc/Alloc.3:
- * doc/Concat.3:
- * doc/CrtMathFnc.3:
- * doc/Hash.3:
- * doc/Interp.3:
- * doc/LinkVar.3:
- * doc/ObjectType.3:
- * doc/PkgRequire.3:
- * doc/Preserve.3:
- * doc/SetResult.3:
- * doc/SplitList.3:
- * doc/SplitPath.3:
- * doc/TCL_MEM_DEBUG.3: Updated documentation to describe the ckalloc,
- ckfree, ckrealloc, attemptckalloc, and attemptckrealloc macros, and to
- accurately describe when and how they are used. [Bug 497459]
+2006-01-11 Don Porter <dgp@users.sourceforge.net>
- * generic/tclThreadJoin.c (TclRememberJoinableThread,TclJoinThread):
- Replaced Tcl_Alloc and Tcl_Free calls with ckalloc and ckfree so that
- memory debugging is supported.
+ * generic/tclBasic.c: Moved Tcl_LogCommandInfo from tclBasic.c to
+ * generic/tclNamesp.c: tclNamesp.c to get access to identifier with
+ * tests/error.test (error-7.0): file scope. Added check for traces on
+ ::errorInfo, and when present fall back to contruction of the stack
+ trace in the variable so that write trace notification timings are
+ compatible with earlier Tcl releases. This reduces, but does not
+ completely eliminate the ***POTENTIAL INCOMPATIBILITY*** created by
+ the 2004-10-15 commit. [Bug 1397843]
-2002-01-04 Daniel Steffen <das@users.sourceforge.net>
+2006-01-10 Daniel Steffen <das@users.sourceforge.net>
- * mac/tclMacTime.c (TclpGetTZName): fix for daylight savings TZName
- bug
+ * unix/configure: add caching, use AC_CACHE_CHECK instead of
+ * unix/configure.in: AC_CACHE_VAL where possible, consistent message
+ * unix/tcl.m4: quoting, sync relevant tclconfig/tcl.m4 changes
+ and gratuitous formatting differences, fix SC_CONFIG_MANPAGES with
+ default argument, Darwin improvements to SC_LOAD_*CONFIG.
-2002-01-03 Don Porter <dgp@users.sourceforge.net>
+2006-01-09 Don Porter <dgp@users.sourceforge.net>
- * doc/FileSystem.3:
- * generic/tclIOUtil.c: Updated some old uses of "fileName" to new VFS
- terminology, "pathPtr".
+ * generic/tclNamesp.c (NamespaceInscopeCmd): [namespace inscope]
+ * tests/namespace.test: commands were not reported by [info level].
+ [Bug 1400572]
-2002-01-03 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+2006-01-09 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
- * tests/basic.test (basic-39.4): Greatly simplified test while still
- leaving it so that it crashes when run without the fix to the
- [foreach] implementation.
- * generic/tclCmdAH.c (Tcl_ForeachObjCmd): Stopped [Bug 494348] from
- happening by not trying to be so clever with cacheing; if nothing
- untoward is happening anyway, the less efficient technique will only
- add a few instruction cycles (one function call and a few
- derefs/assigns per list per iteration, with no change in the number of
- tests) and if something odd *is* going on, the code is now far more
- robust.
+ * generic/tclTrace.c: Stop exporting the guts of the trace command;
+ nothing outside this file needs to see it. [Bug 971336]
- * tests/basic.test (basic-39.4): Reproducable script from [Bug 494348]
+2006-01-05 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
-2002-01-02 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+ * unix/tcl.m4 (TCL_CONFIG_SYSTEM): Factor out the code to determine
+ the operating system version number, as it was replicated in several
+ places.
- * tests/util.test (Wrapper_Tcl_StringMatch,util-5.*): Rewrote so the
- test is performed with the right internal function since [string
- match] no longer uses Tcl_StringCaseMatch internally.
+2006-01-04 David Gravereaux <davygrvy@pobox.com>
- * tests/string.test (string-11.51):
- * generic/tclUtf.c (Tcl_UniCharCaseMatch):
- * generic/tclUtil.c (Tcl_StringCaseMatch): Fault with matching
- case-insensitive non-ASCII patterns containing upper case characters.
- [Bug 233257]
+ * win/tclAppInit.c: WIN32 native console signal handler removed. This
+ was found to be interfering with TWAPI extension one. IMO, special
+ services such as signal handlers should best be done with extensions
+ to the core after discussions on c.l.t. about Roy Terry's tclsh
+ children of a real windows service shell.
******************************************************************
+ *** CHANGELOG ENTRIES FOR 2005 IN "ChangeLog.2005" ***
+ *** CHANGELOG ENTRIES FOR 2004 IN "ChangeLog.2004" ***
+ *** CHANGELOG ENTRIES FOR 2003 IN "ChangeLog.2003" ***
+ *** CHANGELOG ENTRIES FOR 2002 IN "ChangeLog.2002" ***
*** CHANGELOG ENTRIES FOR 2001 IN "ChangeLog.2001" ***
*** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000" ***
*** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" ***
diff --git a/ChangeLog.1999 b/ChangeLog.1999
index a7483a0..3bf4e9a 100644
--- a/ChangeLog.1999
+++ b/ChangeLog.1999
@@ -15,7 +15,7 @@
* unix/Makefile.in: added -srcdir=... for 'make html'
- * doc/Hash.3: fixed reference to ckfree [Bug: 3912]
+ * doc/Hash.3: fixed reference to ckfree [Bug 3912]
* doc/RegExp.3: fixed calling params for Tcl_RegExecFromObj
* doc/open.n: fixed minor formatting errors
* doc/string.n: fixed minor formatting errors
@@ -24,12 +24,12 @@
* tests/cmdIL.test:
* generic/tclCmdIL.c: added -unique option to lsort
- * generic/tclThreadTest.c: changed thread ids to longs [Bug: 3902]
+ * generic/tclThreadTest.c: changed thread ids to longs [Bug 3902]
- * mac/tclMacOSA.c: fixed applescript for I18N [Bug: 3644]
+ * mac/tclMacOSA.c: fixed applescript for I18N [Bug 3644]
* win/mkd.bat:
- * win/rmd.bat: removed necessity of tag.txt [Bug: 3874]
+ * win/rmd.bat: removed necessity of tag.txt [Bug 3874]
* win/tclWinThrd.c: changed CreateThread to _beginthreadex and
ExitThread to _endthreadex
@@ -47,43 +47,43 @@
* mac/tclMacFile.c:
* unix/tclUnixFile.c:
* win/tclWinFile.c: enhanced the glob command with the new options
- -types -path -directory and -join. Deprecated TclpMatchFiles with
+ -types -path -directory and -join. Deprecated TclpMatchFiles with
TclpMatchFilesTypes, extended TclGlob and TclDoGlob and added
- GlobTypeData structure. [Bug: 2363]
+ GlobTypeData structure. [Bug 2363]
1999-12-10 Jeff Hobbs <hobbs@scriptics.com>
* tests/var.test:
- * generic/tclCompile.c: fixed problem where setting to {} array
- would intermittently not work. (Fontaine) [Bug: 3339]
+ * generic/tclCompile.c: fixed problem where setting to {} array would
+ intermittently not work. [Bug 3339] (Fontaine)
* generic/tclCmdMZ.c:
- * generic/tclExecute.c: optimized INST_TRY_CVT_TO_NUMERIC to
- recognize boolean objects. (Spjuth) [Bug: 2815]
+ * generic/tclExecute.c: optimized INST_TRY_CVT_TO_NUMERIC to recognize
+ boolean objects. [Bug 2815] (Spjuth)
* tests/info.test:
* tests/parseOld.test:
* generic/tclCmdAH.c:
* generic/tclProc.c: changed Tcl_UplevelObjCmd (uplevel) and
- Tcl_EvalObjCmd (eval) to use TCL_EVAL_DIRECT in the single arg
- case as well, to take advantage of potential pure list input
- optimization. This means that it won't get byte compiled though,
- which should be acceptable.
- * generic/tclBasic.c: made Tcl_EvalObjEx pure list object aware in
- the TCL_EVAL_DIRECT case for efficiency.
- * generic/tclUtil.c: made Tcl_ConcatObj pure list object aware,
- and return a list object in that case [Bug: 2098 2257]
+ Tcl_EvalObjCmd (eval) to use TCL_EVAL_DIRECT in the single arg case as
+ well, to take advantage of potential pure list input optimization.
+ This means that it won't get byte compiled though, which should be
+ acceptable.
+ * generic/tclBasic.c: made Tcl_EvalObjEx pure list object aware in the
+ TCL_EVAL_DIRECT case for efficiency.
+ * generic/tclUtil.c: made Tcl_ConcatObj pure list object aware, and
+ return a list object in that case [Bug 2098 2257]
* generic/tclMain.c: changed Tcl_Main to not constantly reuse the
commandPtr object (interactive case) as it could be shared. (Fellows)
* unix/configure.in:
* unix/tcl.m4:
- * unix/tclUnixPipe.c: removed checking for compatible vfork
- function and use of the vfork function. Modern VM systems rarely
- suffer any performance degradation when fork is used, and it
- solves multiple problems with vfork. Users that still want vfork
- can add -Dfork=vfork to the compile flags. [Bug: 942 2228 1312]
+ * unix/tclUnixPipe.c: removed checking for compatible vfork function
+ and use of the vfork function. Modern VM systems rarely suffer any
+ performance degradation when fork is used, and it solves multiple
+ problems with vfork. Users that still want vfork can add -Dfork=vfork
+ to the compile flags. [Bug 942 2228 1312]
1999-12-09 Jeff Hobbs <hobbs@scriptics.com>
@@ -96,44 +96,44 @@
* win/tclWinFCmd.c:
* win/tclWinInit.c:
* win/tclWinPipe.c:
- * win/tclWinSock.c: removed all code that supported Win32s. It
- was no longer officially supported, and likely didn't work anyway.
+ * win/tclWinSock.c: removed all code that supported Win32s. It was no
+ longer officially supported, and likely didn't work anyway.
* win/makefile.vc: removed 16 bit stuff, cleaned up.
* win/tcl16.rc:
* win/tclWin16.c:
- * win/winDumpExts.c: these files have been removed from the
- source tree (no longer necessary to build)
+ * win/winDumpExts.c: these files have been removed from the source
+ tree (no longer necessary to build)
1999-12-07 Jeff Hobbs <hobbs@scriptics.com>
- * tests/io.test: removed 'knownBug' tests that were for
- unsupported0, which is now fcopy (that already has tests)
+ * tests/io.test: removed 'knownBug' tests that were for unsupported0,
+ which is now fcopy (that already has tests)
* mac/tclMacPort.h: added utime.h include
* generic/tclDate.c:
- * unix/Makefile.in: fixed make gendate to swap const with CONST
- so it uses the Tcl defined CONST type [Bug: 3521]
+ * unix/Makefile.in: fixed make gendate to swap const with CONST so it
+ uses the Tcl defined CONST type [Bug 3521]
- * generic/tclIO.c: removed panic that could occur in FlushChannel
- when a "blocking" channel would receive EAGAIN, instead treating
- it the same as non-blocking. [Bug: 3773]
+ * generic/tclIO.c: removed panic that could occur in FlushChannel when
+ a "blocking" channel would receive EAGAIN, instead treating it the
+ same as non-blocking. [Bug 3773]
- * generic/tclUtil.c: fixed Tcl_ScanCountedElement to not step
- beyond the end of the counted string [Bug: 3336]
+ * generic/tclUtil.c: fixed Tcl_ScanCountedElement to not step beyond
+ the end of the counted string. [Bug 3336]
1999-12-03 Jeff Hobbs <hobbs@scriptics.com>
* doc/load.n: added note about NT's buggy handling of './' with
LoadLibrary
- * library/http2.1/http.tcl: fixed error handling in http::Event
- [Bug: 3752]
+ * library/http2.1/http.tcl: fixed error handling in http::Event. [Bug
+ 3752]
* tests/env.test: removed knownBug limitation from working test
- * tests/all.tcl: ensured that ::tcltest::testsDirectory would be
- set to an absolute path
+ * tests/all.tcl: ensured that ::tcltest::testsDirectory would be set
+ to an absolute path
* tests/expr-old.test:
* tests/parseExpr.test:
@@ -144,86 +144,82 @@
* generic/tclParseExpr.c:
* generic/tclUtil.c:
* generic/tclExecute.c: added TclCheckBadOctal routine to enhance
- error message checking for when users use invalid octal numbers
- (like 08), as well as replumbed the Expr*Funcs with a new
- VerifyExprObjType to simplify type handling. [Bug: 2467]
+ error message checking for when users use invalid octal numbers (like
+ 08), as well as replumbed the Expr*Funcs with a new VerifyExprObjType
+ to simplify type handling. [Bug 2467]
* tests/expr.test:
- * generic/tclCompile.c: fixed 'bad code length' error for
- 'expr + {[incr]}' case, with new test case [Bug: 3736]
- and seg fault on 'expr + {[error]}' (different cause) that
- was caused by a correct optimization that didn't correctly
- track how it was modifying the source string in the opt.
- The optimization was removed, which means that:
+ * generic/tclCompile.c: fixed 'bad code length' error for 'expr +
+ {[incr]}' case, with new test case [Bug 3736] and seg fault on 'expr
+ + {[error]}' (different cause) that was caused by a correct
+ optimization that didn't correctly track how it was modifying the
+ source string in the opt. The optimization was removed, which means
+ that:
expr 1 + {[string length abc]}
- will be not be compiled inline as before, but this should be
- written:
+ will be not be compiled inline as before, but this should be written:
expr {1 + [string length abc]}
- which will be compiled inline for speed. This prevents
+ which will be compiled inline for speed. This prevents:
expr 1 + {[mindless error]}
- from seg faulting, and only affects optimizations for
- degenerate cases [Bug: 3737]
+ from seg faulting, and only affects optimizations for degenerate cases
+ [Bug 3737]
1999-12-01 Scott Redman <redman@scriptics.com>
- * generic/tcl.decls :
- * generic/tclMain.c :
- * unix/tclAppInit.c:
+ * generic/tcl.decls:
+ * generic/tclMain.c:
+ * unix/tclAppInit.c:
* win/tclAppInit.c: Added two new internal functions,
- TclSetStartupScriptFileName() and TclGetStartupScriptFileName()
- and added hooks into the main() code for supporting TclPro and
- other "big" shells more easily without requiring a copy of the
- main() code.
-
+ TclSetStartupScriptFileName() and TclGetStartupScriptFileName() and
+ added hooks into the main() code for supporting TclPro and other "big"
+ shells more easily without requiring a copy of the main() code.
+
* generic/tclEncoding.c:
- * generic/tclEvent.c: Moved encoding-related startup code from
+ * generic/tclEvent.c: Moved encoding-related startup code from
tclEvent.c into the more appropriate tclEncoding.c.
-
+
1999-11-30 Jeff Hobbs <hobbs@scriptics.com>
* generic/tclIO.c: fix from Kupries for Tcl_UnstackChannel that
correctly handles resetting translation and encoding.
- * generic/tclLoad.c: #def'd out the unloading of DLLs at finalize
- time for Unix in TclFinalizeLoad. [Bug: 2560 3373] Should be
- parametrized to allow for user to specify unload or not.
+ * generic/tclLoad.c: #def'd out the unloading of DLLs at finalize time
+ for Unix in TclFinalizeLoad. [Bug 2560 3373] Should be parametrized
+ to allow for user to specify unload or not.
- * win/tclWinTime.c: fixed handling of %Z on NT for time zones
- that don't have DST.
+ * win/tclWinTime.c: fixed handling of %Z on NT for time zones that
+ don't have DST.
1999-11-29 Jeff Hobbs <hobbs@scriptics.com>
* library/dde1.1/pkgIndex.tcl:
- * library/reg1.0/pkgIndex.tcl: added supported for debugged
- versions of the libraries
+ * library/reg1.0/pkgIndex.tcl: added supported for debugged versions
+ of the libraries
* unix/tclUnixPipe.c: fixed PipeBlockModeProc to properly set
- isNonBlocking flag on pipe. [Bug: 1356 710]
+ isNonBlocking flag on pipe. [Bug 1356 710]
removed spurious fcntl call from PipeBlockModeProc
* tests/scan.test:
- * generic/tclScan.c: fixed scan where %[..] didn't match anything
- and added test case [Bug: 3700]
+ * generic/tclScan.c: fixed scan where %[..] didn't match anything and
+ added test case. [Bug 3700]
1999-11-24 Jeff Hobbs <hobbs@scriptics.com>
* doc/open.n:
* win/tclWinSerial.c: adopted patch from Schroedter to handle
- fconfigure $sock -lasterror on Windows. [RFE: 3368]
+ fconfigure $sock -lasterror on Windows. [RFE 3368]
- * generic/tclCmdIL.c: made SORTMODE_INTEGER work with Longs
- [Bug: 3652]
+ * generic/tclCmdIL.c: made SORTMODE_INTEGER work with Longs [Bug 3652]
1999-11-23 Scott Stanton <stanton@scriptics.com>
- * library/tcltest1.0/tcltest.tcl: Fixed bug where tcltest output
- went to stdout instead of the specified output file in some
- cases.
+ * library/tcltest1.0/tcltest.tcl: Fixed bug where tcltest output went
+ to stdout instead of the specified output file in some cases.
1999-11-19 Jeff Hobbs <hobbs@scriptics.com>
- * generic/tclProc.c: backed out change from 1999-11-18 as it
- could affect return string from upvar as well.
+ * generic/tclProc.c: backed out change from 1999-11-18 as it could
+ affect return string from upvar as well.
* tools/tcl.wse.in: added tcltest1.0 library to distribution list
@@ -234,49 +230,49 @@
1999-11-18 Jeff Hobbs <hobbs@scriptics.com>
* unix/tcl.m4: added defined for _THREAD_SAFE in --enable-threads
- case; added check for pthread_mutex_init in libc; in AIX case,
- with --enable-threads ${CC}_r is used; fixed flags when using gcc
- on SCO
+ case; added check for pthread_mutex_init in libc; in AIX case, with
+ --enable-threads ${CC}_r is used; fixed flags when using gcc on SCO
- * generic/tclProc.c: corrected error reporting for default case
- at the global level for uplevel command.
+ * generic/tclProc.c: corrected error reporting for default case at the
+ global level for uplevel command.
- * generic/tclIOSock.c: changed int to size_t type for len
- in TclSockMinimumBuffers.
+ * generic/tclIOSock.c: changed int to size_t type for len in
+ TclSockMinimumBuffers.
- * generic/tclCkalloc.c: fixed Tcl_DbCkfree to return a value
- on NULL input. [Bug: 3400]
+ * generic/tclCkalloc.c: fixed Tcl_DbCkfree to return a value on NULL
+ input. [Bug 3400]
- * generic/tclStringObj.c: fixed support for passing in negative
- length to Tcl_SetUnicodeObj, et al handling routines. [Bug: 3380]
+ * generic/tclStringObj.c: fixed support for passing in negative length
+ to Tcl_SetUnicodeObj, et al handling routines. [Bug 3380]
* doc/scan.n:
* tests/scan.test:
- * generic/tclScan.c: finished support for inline scan by
- supporting XPG identifiers.
+ * generic/tclScan.c: finished support for inline scan by supporting
+ XPG identifiers.
* doc/http.n:
- * library/http2.1/http.tcl: added register and unregister
- commands to http:: package (better support for tls/SSL),
- as well as -type argument to http::geturl. [RFE: 2617]
+ * library/http2.1/http.tcl: added register and unregister commands to
+ http:: package (better support for tls/SSL), as well as -type argument
+ to http::geturl. [RFE 2617]
- * generic/tclBasic.c: removed extra decr of numLevels in
- Tcl_EvalObjEx that could cause seg fault. (mjansen@wendt.de)
+ * generic/tclBasic.c: removed extra decr of numLevels in Tcl_EvalObjEx
+ that could cause seg fault. (mjansen@wendt.de)
* generic/tclEvent.c: fixed possible lack of MutexUnlock in
- Tcl_DeleteExitHandler [Bug: 3545]
+ Tcl_DeleteExitHandler. [Bug 3545]
- * unix/tcl.m4: Added better pthreads library check and inclusion
- of _THREAD_SAFE in --enable-threads case
+ * unix/tcl.m4: Added better pthreads library check and inclusion of
+ _THREAD_SAFE in --enable-threads case
Added support for gcc config on SCO
* doc/glob.n: added note about ..../ glob behavior on Win9*
- * doc/tcltest.n: fixed minor example errors [Bug: 3551]
+ * doc/tcltest.n: fixed minor example errors. [Bug 3551]
1999-11-17 Brent Welch <welch@scriptics.com>
- * library/http2.1/http.tcl: Correctly fixed the -timeout
- problem mentioned in the 10-29 change. Also added error
- handling for failed writes on the socket during the protocol.
+
+ * library/http2.1/http.tcl: Correctly fixed the -timeout problem
+ mentioned in the 10-29 change. Also added error handling for failed
+ writes on the socket during the protocol.
1999-11-09 Jeff Hobbs <hobbs@scriptics.com>
@@ -291,54 +287,53 @@
* generic/tclParse.c: added code in Tcl_ParseBraces to test for
possible unbalanced open brace in a comment
- * library/init.tcl: removed the installed binary directory from
- the auto_path variable
+ * library/init.tcl: removed the installed binary directory from the
+ auto_path variable
- * tools/tcl.wse.in: updated to 8.3a1, fixed install of twind.tcl
- and koi8-r.enc files
+ * tools/tcl.wse.in: updated to 8.3a1, fixed install of twind.tcl and
+ koi8-r.enc files
* unix/tcl.m4: added recognition of pthreads library for AIX
1999-10-29 Brent Welch <welch@scriptics.com>
- * generic/tclInt.h: Modified the TclNewObj and TclDecrRefCount
- in two ways. First, in the case of TCL_THREADS, we do not use
- the special Tcl_Obj allocator because that is a source of
- lock contention. Second, general code cleanup to eliminate
- duplicated code. In particular, TclDecrRefCount now uses
- TclFreeObj instead of duplicating that code, so it is now
- identical to Tcl_DecrRefCount.
-
- * generic/tclObj.c: Changed Tcl_NewObj so it uses the
- TclNewObj macro instead of duplicating the code. Adjusted
- TclFreeObj so it understands the TCL_THREADS case described
- above.
-
- * library/http2.1/http.tcl: Fixed a bug in the handling of
- the state(status) variable when the -timeout flag is specified.
- Previously it was possible to leave the status undefined
- instead of empty, which caused errors in http::status
+
+ * generic/tclInt.h: Modified the TclNewObj and TclDecrRefCount in two
+ ways. First, in the case of TCL_THREADS, we do not use the special
+ Tcl_Obj allocator because that is a source of lock contention. Second,
+ general code cleanup to eliminate duplicated code. In particular,
+ TclDecrRefCount now uses TclFreeObj instead of duplicating that code,
+ so it is now identical to Tcl_DecrRefCount.
+
+ * generic/tclObj.c: Changed Tcl_NewObj so it uses the TclNewObj macro
+ instead of duplicating the code. Adjusted TclFreeObj so it understands
+ the TCL_THREADS case described above.
+
+ * library/http2.1/http.tcl: Fixed a bug in the handling of the
+ state(status) variable when the -timeout flag is specified. Previously
+ it was possible to leave the status undefined instead of empty, which
+ caused errors in http::status
1999-10-28 Jeff Hobbs <hobbs@scriptics.com>
* unix/aclocal.m4: made it just include tcl.m4
- * library/tcltest1.0/tcltest.tcl: updated makeFile to return
- full pathname of file created
+ * library/tcltest1.0/tcltest.tcl: updated makeFile to return full
+ pathname of file created
* generic/tclStringObj.c: fixed Tcl_AppendStringsToObjVA so it only
- iterates once over the va_list (avoiding a memcpy of it,
- which is not portable).
+ iterates once over the va_list (avoiding a memcpy of it, which is not
+ portable).
* generic/tclEnv.c: fixed possible ABR error in environ array
* tests/scan.test:
- * generic/tclScan.c: added support for use of inline scan,
- XPG3 currently not included
+ * generic/tclScan.c: added support for use of inline scan, XPG3
+ currently not included
* tests/incr.test:
* tests/set.test:
- * generic/tclCompCmds.c: fixed improper bytecode handling of
- 'eval {set array($unknownvar) 5}' (also for incr) [Bug: 3184]
+ * generic/tclCompCmds.c: fixed improper bytecode handling of 'eval
+ {set array($unknownvar) 5}' (also for incr). [Bug 3184]
* win/tclWinTest.c: added testvolumetype command, as atime is
completely ignored for Windows FAT file systems
@@ -346,67 +341,67 @@
* unix/tclUnixPort.h: added utime.h to includes
* doc/file.n:
* tests/cmdAH.test:
- * generic/tclCmdAH.c: added time arguments to atime and mtime
- file command methods (support 'touch' functionality)
+ * generic/tclCmdAH.c: added time arguments to atime and mtime file
+ command methods (support 'touch' functionality)
1999-10-20 Jeff Hobbs <hobbs@scriptics.com>
- * unix/tclUnixNotfy.c: fixed event/io threading problems by
- making triggerPipe non-blocking [Bug: 2792]
+ * unix/tclUnixNotfy.c: fixed event/io threading problems by making
+ triggerPipe non-blocking. [Bug 2792]
* library/tcltest1.0/tcltest.tcl:
* generic/tclThreadTest.c: fixed mem leaks in threads
- * generic/tclResult.c: fixed Tcl_AppendResultVA so it only
- iterates once over the va_list (avoiding a memcpy of it,
- which is not portable).
+ * generic/tclResult.c: fixed Tcl_AppendResultVA so it only iterates
+ once over the va_list (avoiding a memcpy of it, which is not
+ portable).
* generic/regc_color.c: fixed mem leak and assertion, from HS
- * generic/tclCompile.c: removed savedChar trick that appeared to
- be causing a segv when the literal table was released
+ * generic/tclCompile.c: removed savedChar trick that appeared to be
+ causing a segv when the literal table was released
* tests/string.test:
- * generic/tclCmdMZ.c: fixed [string index] to return ByteArrayObj
- when indexing into one (test case string-5.16) [Bug: 2871]
+ * generic/tclCmdMZ.c: fixed [string index] to return ByteArrayObj when
+ indexing into one (test case string-5.16). [Bug 2871]
- * library/http2.1/http.tcl: protected gets with catch [Bug: 2665]
+ * library/http2.1/http.tcl: protected gets with catch. [Bug 2665]
1999-10-19 Jennifer Hom <jenn@scriptics.com>
* tests/tcltest.test:
* doc/tcltest.n:
- * library/tcltest1.0/tcltest.tcl: Removed the extra return at the
- end of the tcltest.tcl file, added version information about tcl.
+ * library/tcltest1.0/tcltest.tcl: Removed the extra return at the end
+ of the tcltest.tcl file, added version information about tcl.
Applied patches sent in by Andreas Kupries to add helper procs for
debug output, add 3 new flags (-testsdir, -load, -loadfile), and
- internally refactors common code for dealing with paths into
- separate procedures. [Bug: 2838, 2842]
+ internally refactors common code for dealing with paths into separate
+ procedures. [Bug 2838, 2842]
Merged code from core-8-2-1 branch that changes the checks for the
- value of tcl_interactive to also incorporate a check for the
- existence of the variable.
+ value of tcl_interactive to also incorporate a check for the existence
+ of the variable.
* tests/autoMkindex.test:
- * tests/pkgMkIndex.test: Explicitly cd to
- ::tcltest::testsDirectory at the beginning of the test run
+ * tests/pkgMkIndex.test: Explicitly cd to ::tcltest::testsDirectory at
+ the beginning of the test run
- * tests/basic.test: Use version information defined in tcltest
- instead of hardcoded version number
+ * tests/basic.test: Use version information defined in tcltest instead
+ of hardcoded version number
- * tests/socket.test: package require tcltest before attempting to
- use variable defined in tcltest namespace
+ * tests/socket.test: package require tcltest before attempting to use
+ variable defined in tcltest namespace
+
+ * tests/unixInit.test:
+ * tests/unixNotfy.test: Added explicit exits needed to avoid problems
+ when the tests area run in wish.
- * tests/unixInit.test:
- * tests/unixNotfy.test: Added explicit exits needed to avoid
- problems when the tests area run in wish.
-
1999-10-12 Jim Ingham <jingham@scriptics.com>
* mac/tclMacLoad.c: Stupid bug - we converted the filename to
external, but used the unconverted version.
- * mac/tclMacFCmd.c: Fix a merge error in the bug fix for [Bug: 2869]
+ * mac/tclMacFCmd.c: Fix a merge error in the bug fix for [Bug 2869]
1999-10-12 Jeff Hobbs <hobbs@scriptics.com>
@@ -423,21 +418,20 @@
* generic/tclRegexp.c:
* generic/tclTest.c:
* tests/reg.test: updated to Henry Spencer's new regexp engine
- (mid-Sept 99). Should greatly reduce stack space reqs.
+ (mid-Sept 99). Should greatly reduce stack space reqs.
* library/tcltest1.0/pkgIndex.tcl: fixed procs in pkgIndex.tcl file
* generic/tclEnv.c: fixed mem leak with putenv and DStrings
* doc/Encoding.3: corrected docs
* tests/basic.test: updated test cases for 8.3
- * tests/encoding.test: fixed test case that change system
- encoding to a double-byte one (this causes a bogus mem read
- error for purify)
+ * tests/encoding.test: fixed test case that change system encoding to
+ a double-byte one (this causes a bogus mem read error for purify)
* unix/Makefile.in: purify has to use -best-effort to instrument
* unix/tclAppInit.c: identified potential mem leak when compiling
tcltest (not critical)
- * unix/tclUnixPipe.c: fixed mem leak in TclpCreateProcess when
- doing alloc between vfork and execvp.
+ * unix/tclUnixPipe.c: fixed mem leak in TclpCreateProcess when doing
+ alloc between vfork and execvp.
* unix/tclUnixTest.c: fixed mem leak in findexecutable test command
1999-10-05 Jeff Hobbs <hobbs@scriptics.com>
@@ -452,127 +446,126 @@
* library/http2.1/http.tcl: fixed possible use of global c var.
* win/tclWinReg.c: fixed registry command to properly 'get'
- HKEY_PERFORMANCE_DATA root key data. Needs more work.
-
+ HKEY_PERFORMANCE_DATA root key data. Needs more work.
+
* generic/tclNamesp.c:
* generic/tclVar.c:
* generic/tclCmdIL.c: fixed comment typos
- * mac/tclMacFCmd.c: fixed filename stuff to support UTF-8 [Bug: 2869]
+ * mac/tclMacFCmd.c: fixed filename stuff to support UTF-8. [Bug 2869]
- * win/tclWinSerial.c: changed SerialSetOptionProc to return
- TCL_OK by default. (patch from Rolf Schroedter)
+ * win/tclWinSerial.c: changed SerialSetOptionProc to return TCL_OK by
+ default. (patch from Rolf Schroedter)
1999-09-21 Jennifer Hom <jenn@scriptics.com>
- * library/tcltest1.0/tcltest.tcl: Applied patches sent in by
- Andreas Kupries to fix typos in comments and ::tcltest::grep,
- fix hook redefinition problems, and change "string compare" to
- "string equal." [Bug: 2836, 2837, 2839, 2840]
+ * library/tcltest1.0/tcltest.tcl: Applied patches sent in by Andreas
+ Kupries to fix typos in comments and ::tcltest::grep, fix hook
+ redefinition problems, and change "string compare" to "string equal".
+ [Bug 2836, 2837, 2839, 2840]
1999-09-20 Jeff Hobbs <hobbs@scriptics.com>
* tests/env.test:
- * unix/Makefile.in: added support for AIX LIBPATH env var [Bug: 2793]
+ * unix/Makefile.in: added support for AIX LIBPATH env var. [Bug 2793]
removed second definition of INCLUDE_INSTALL_DIR (the one that
- referenced @includedir@) [Bug: 2805]
- * unix/dltest/Makefile.in: added -lc to LIBS [Bug: 2794]
+ referenced @includedir@) [Bug 2805]
+ * unix/dltest/Makefile.in: added -lc to LIBS. [Bug 2794]
1999-09-16 Jeff Hobbs <hobbs@scriptics.com>
- * tests/timer.test: changed after delay in timer test 6.29 from
- 1 to 10. [Bug: 2796]
+ * tests/timer.test: changed after delay in timer test 6.29 from 1 to
+ 10. [Bug 2796]
* tests/pkg.test:
* generic/tclPkg.c: fixed package version check to disallow 1.2..3
- [Bug: 2539]
-
- * unix/Makefile.in: fixed gendate target - this never worked
- since RCS was intro'd.
- * generic/tclGetDate.y: updated to reflect previous changes
- to tclDate.c (leap year calc) and added CEST and UCT time zone
- recognition. Fixed 4 missing UCHAR() casts. [Bug: 2717, 954,
- 1245, 1249]
-
- * generic/tclCkalloc.c: changed Tcl_DumpActiveMemory to really
- dump to stderr and close it [Bug: 725] and changed Tcl_Ckrealloc
- and Tcl_Ckfree to not bomb when NULL was passed in [Bug: 1719]
- and changed Tcl_Alloc, et al to not panic when a alloc request
- for zero came through and NULL was returned (valid on AIX, Tru64)
- [Bug: 2795, etc]
+ [Bug 2539]
+
+ * unix/Makefile.in: fixed gendate target - this never worked since RCS
+ was intro'd.
+ * generic/tclGetDate.y: updated to reflect previous changes to
+ tclDate.c (leap year calc) and added CEST and UCT time zone
+ recognition. Fixed 4 missing UCHAR() casts. [Bug 2717, 954, 1245,
+ 1249]
+
+ * generic/tclCkalloc.c: changed Tcl_DumpActiveMemory to really dump to
+ stderr and close it [Bug 725] and changed Tcl_Ckrealloc and
+ Tcl_Ckfree to not bomb when NULL was passed in [Bug 1719] and changed
+ Tcl_Alloc, et al to not panic when a alloc request for zero came
+ through and NULL was returned (valid on AIX, Tru64) [Bug 2795, etc]
* tests/clock.test:
* doc/clock.n:
- * generic/tclClock.c: added -milliseconds switch to clock clicks
- to guarantee that the return value of clicks is in the millisecs
- granularity [Bug: 2682, 1332]
+ * generic/tclClock.c: added -milliseconds switch to clock clicks to
+ guarantee that the return value of clicks is in the millisecs
+ granularity. [Bug 2682, 1332]
1999-09-15 Jeff Hobbs <hobbs@scriptics.com>
- * generic/tclIOCmd.c: fixed potential core dump in conjunction
- with stacked channels with result obj manipulation in
- Tcl_ReadChars [Bug: 2623]
+ * generic/tclIOCmd.c: fixed potential core dump in conjunction with
+ stacked channels with result obj manipulation in Tcl_ReadChars. [Bug
+ 2623]
* tests/format.test:
- * generic/tclCmdAH.c: fixed translation of %0#s in format [Bug: 2605]
+ * generic/tclCmdAH.c: fixed translation of %0#s in format. [Bug 2605]
- * doc/msgcat.n: fixed \\ bug in example [Bug: 2548]
+ * doc/msgcat.n: fixed \\ bug in example. [Bug 2548]
* unix/tcl.m4:
- * unix/aclocal.m4: added fix for FreeBSD-[1-2] recognition
- [Bug: 2070] and fix for IRIX SHLIB_LB_LIBS. [Bug: 2610]
+ * unix/aclocal.m4: added fix for FreeBSD-[1-2] recognition [Bug 2070]
+ and fix for IRIX SHLIB_LB_LIBS. [Bug 2610]
* doc/array.n:
* tests/var.test:
* tests/set.test:
- * generic/tclVar.c: added an array unset operation, with docs
- and tests. Variation of [Bug: 1775]. Added fix in TclArraySet
- to check when trying to set in a non-existent namespace. [Bug: 2613]
+ * generic/tclVar.c: added an array unset operation, with docs and
+ tests. Variation of [Bug 1775]. Added fix in TclArraySet to check
+ when trying to set in a non-existent namespace. [Bug 2613]
1999-09-14 Jeff Hobbs <hobbs@scriptics.com>
* tests/linsert.test:
* doc/linsert.n:
- * generic/tclCmdIL.c: fixed end-int interpretation of linsert
- to correctly calculate value for end, added test and docs [Bug: 2693]
+ * generic/tclCmdIL.c: fixed end-int interpretation of linsert to
+ correctly calculate value for end, added test and docs. [Bug 2693]
* doc/regexp.n:
* doc/regsub.n:
* tests/regexp.test:
- * generic/tclCmdMZ.c: add -start switch to regexp and regsub
- with docs and tests
+ * generic/tclCmdMZ.c: add -start switch to regexp and regsub with docs
+ and tests
* doc/switch.n: added proper use of comments to example.
- * generic/tclCmdMZ.c: changed switch to complain when an error
- occurs that seems to be due to a misplaced comment.
+ * generic/tclCmdMZ.c: changed switch to complain when an error occurs
+ that seems to be due to a misplaced comment.
- * generic/tclCmdMZ.c: fixed illegal ref for \[0-9] substitutions
- in regsub [Bug: 2723]
+ * generic/tclCmdMZ.c: fixed illegal ref for \[0-9] substitutions in
+ regsub. [Bug 2723]
- * generic/tclCmdMZ.c: changed [string equal] to return an Int
- type object (was a Boolean)
+ * generic/tclCmdMZ.c: changed [string equal] to return an Int type
+ object (was a Boolean)
1999-09-01 Jennifer Hom <jenn@scriptics.com>
- * library/tcltest1.0/tcltest.tcl: Process command-line arguments
- only ::tcltest doesn't have a child namespace (requires that
- command-line args are processed in that namespace)
+ * library/tcltest1.0/tcltest.tcl: Process command-line arguments only
+ ::tcltest doesn't have a child namespace (requires that command-line
+ args are processed in that namespace)
1999-09-01 Jeff Hobbs <hobbs@scriptics.com>
- * generic/tclParseExpr.c: changed '"' to '\"' to make FreeBSD
- happy [Bug: 2625]
- * generic/tclProc.c: moved static buf to better location and
- changed static msg that would overflow in ProcessProcResultCode
- [Bug: 2483] and added Tcl_DStringFree to Tcl_ProcObjCmd.
- Also reworked size of static buffers.
+ * generic/tclParseExpr.c: changed '"' to '\"' to make FreeBSD happy.
+ [Bug 2625]
+ * generic/tclProc.c: moved static buf to better location and changed
+ static msg that would overflow in ProcessProcResultCode [Bug 2483]
+ and added Tcl_DStringFree to Tcl_ProcObjCmd. Also reworked size of
+ static buffers.
* tests/stringObj.test: added test 9.11
- * generic/tclStringObj.c: changed Tcl_AppendObjToObj to
- properly handle the 1-byte dest and mixed src case where
- both had had Unicode string len checks made on them. [Bug: 2678]
+ * generic/tclStringObj.c: changed Tcl_AppendObjToObj to properly
+ handle the 1-byte dest and mixed src case where both had had Unicode
+ string len checks made on them. [Bug 2678]
* unix/aclocal.m4:
- * unix/tcl.m4: adjusted fix from 8-21 to add -bnoentry to the
- AIX-* case and readjusted the range
+ * unix/tcl.m4: adjusted fix from 8-21 to add -bnoentry to the AIX-*
+ case and readjusted the range
1999-08-31 Jennifer Hom <jenn@scriptics.com>
@@ -588,79 +581,76 @@
* tests/exec.test:
* tests/io.test:
* tests/event.test:
- * tests/tcltest.test: Added 'exit' calls to scripts that the tests
+ * tests/tcltest.test: Added 'exit' calls to scripts that the tests
themselves write, and removed accidental checkin of knownBugThreaded
constraints for Solaris and Linux.
-
- * library/tcltest1.0/tcltest.tcl: Modified tcltest so that
- variables are only initialized to their default values if they did
- not previously exist.
+
+ * library/tcltest1.0/tcltest.tcl: Modified tcltest so that variables
+ are only initialized to their default values if they did not
+ previously exist.
1999-08-26 Jennifer Hom <jenn@scriptics.com>
* tests/tcltest.test:
- * library/tcltest1.0/tcltest.tcl: Added a -args flag that sets a
- variable named ::tcltest::parameters based on whatever's being
- sent in as the argument to the -args flag.
+ * library/tcltest1.0/tcltest.tcl: Added a -args flag that sets a
+ variable named ::tcltest::parameters based on whatever's being sent in
+ as the argument to the -args flag.
1999-08-23 Jennifer Hom <jenn@scriptics.com>
- * tests/tcltest.test: Added additional tests for -tmpdir, marked
- all tests that use exec as unixOrPc.
+ * tests/tcltest.test: Added additional tests for -tmpdir, marked all
+ tests that use exec as unixOrPc.
* tests/encoding.test:
- * tests/interp.test:
+ * tests/interp.test:
* tests/macFCmd.test:
* tests/parseOld.test:
- * tests/regexp.test: Applied patches from Jim Ingham to add
- encoding to a Mac only interp test, change an error message in
- macFCmd.tet, put a comment in parseOld.test, fix tests using the
- testencoding path command, and put unixOrPc constraints on tests
- that use exec.
+ * tests/regexp.test: Applied patches from Jim Ingham to add encoding
+ to a Mac only interp test, change an error message in macFCmd.tet, put
+ a comment in parseOld.test, fix tests using the testencoding path
+ command, and put unixOrPc constraints on tests that use exec.
1999-08-21 Jeff Hobbs <hobbs@scriptics.com>
- * unix/aclocal.m4: Changed AIX-4.[2-9] check to AIX-4.[1-9]
- [Bug: 1909]
+ * unix/aclocal.m4: Changed AIX-4.[2-9] check to AIX-4.[1-9] [Bug 1909]
1999-08-20 Jeff Hobbs <hobbs@scriptics.com>
- * generic/tclPosixStr.c: fixed typo [Bug: 2592]
+ * generic/tclPosixStr.c: fixed typo. [Bug 2592]
- * doc/*: fixed various nroff bugs in man pages [Bug: 2503 2588]
+ * doc/*: fixed various nroff bugs in man pages. [Bug 2503 2588]
1999-08-19 Jeff Hobbs <hobbs@scriptics.com>
- * win/README.binary: fixed version info and some typos [Bug: 2561]
-
+ * win/README.binary: fixed version info and some typos. [Bug 2561]
+
* doc/interp.n: updated list of commands available in a safe
- interpreter [Bug: 2526]
+ interpreter. [Bug 2526]
* generic/tclIO.c: changed Tcl_GetChannelNames* to use style guide
headers (pleases HP cc)
1999-08-18 Jeff Hobbs <hobbs@scriptics.com>
- * doc/Eval.3: fixed doc on input args [Bug: 2114]
+ * doc/Eval.3: fixed doc on input args. [Bug 2114]
* doc/OpenFileChnl.3:
* doc/file.n:
* tests/cmdAH.test:
* tclIO.c:
* tclCmdAH.c: added "file channels ?pattern?" tcl command, with
- associated Tcl_GetChannelNames and Tcl_GetChannelNamesEx public
- C APIs (added to tcl.decls as well), with docs and tests.
+ associated Tcl_GetChannelNames and Tcl_GetChannelNamesEx public C APIs
+ (added to tcl.decls as well), with docs and tests.
* tests/expr.test:
- * generic/tclCompile.c: add TCL_TOKEN_VARIABLE to the part types
- that cause differed compilation for exprs, to correct the expr
- double-evaluation problem for vars. Added test cases.
- Related to [Bug: 732]
-
- * unix/Makefile.in: changed the dependency structure so that
- install-* is dependent on * (ie - install-binaries is dependent
- on binaries).
-
+ * generic/tclCompile.c: add TCL_TOKEN_VARIABLE to the part types that
+ cause differed compilation for exprs, to correct the expr
+ double-evaluation problem for vars. Added test cases. Related to [Bug
+ 732]
+
+ * unix/Makefile.in: changed the dependency structure so that install-*
+ is dependent on * (ie - install-binaries is dependent on binaries).
+
* library/auto.tcl:
* library/init.tcl:
* library/ldAout.tcl:
@@ -668,14 +658,13 @@
* library/safe.tcl:
* library/word.tcl:
* library/http2.1/http.tcl:
- * library/msgcat1.0/msgcat.tcl: updated libraries to better
- Tcl style guide (no more string comparisons with == or !=, spacing
- changes).
+ * library/msgcat1.0/msgcat.tcl: updated libraries to better Tcl style
+ guide (no more string comparisons with == or !=, spacing changes).
1999-08-05 Jim Ingham <jingham@cygnus.com>
* mac/tclMacProjects.sea.hqx: Rearrange the projects so that the build
- directory is separate from the sources. Much more convenient!
+ directory is separate from the sources. Much more convenient!
1999-08-13 Scott Redman <redman@scriptics.com>
@@ -683,18 +672,18 @@
1999-08-12 Scott Stanton <stanton@scriptics.com>
- * win/Makefile.in: Added COMPILE_DEBUG_FLAGS macro to make it
- easier to turn on compiler tracing.
+ * win/Makefile.in: Added COMPILE_DEBUG_FLAGS macro to make it easier
+ to turn on compiler tracing.
- * tests/parse.test:
- * generic/tclParse.c: Fixed bug in Tcl_EvalEx where the termOffset
- was not being updated in cases where the evaluation returned a non
- TCL_OK error code. [Bug: 2535]
+ * tests/parse.test:
+ * generic/tclParse.c: Fixed bug in Tcl_EvalEx where the termOffset was
+ not being updated in cases where the evaluation returned a non TCL_OK
+ error code. [Bug 2535]
1999-08-12 Scott Redman <redman@scriptics.com>
- * win/tclWinSerial.c: Applied patch from Petteri Kettunen to
- remove compiler warning.
+ * win/tclWinSerial.c: Applied patch from Petteri Kettunen to remove
+ compiler warning.
1999-08-10 Scott Redman <redman@scriptics.com>
@@ -707,12 +696,12 @@
Windows (and he fixed the bug in the Unix thread implementation).
1999-08-09 Brent Welch <welch@scriptics.com>
-
+
* generic/tcl.decls:
* generic/tclAlloc.c:
* generic/tclCkalloc.c:
* generic/tclCmdIL.c:
- * generic/tclDecls.h:
+ * generic/tclDecls.h:
* generic/tclIO.c:
* generic/tclInt.decls:
* generic/tclIntDecls.h:
@@ -720,12 +709,11 @@
* generic/tclVar.c:
* mac/tclMacThrd.c:
* unix/tclUnixThrd.c:
- * win/tclWinThrd.c: Added use of Tcl_GetAllocMutex to tclAlloc.c
- and tclCkalloc.c so they can be linked against alternate thread
- packages. Added Tcl_GetChannelNames to tclIO.c. Added
- TclVarTraceExists hook so "info exists" triggers read traces
- exactly like it did in Tcl 7.6. Stubs table changes to reflect new
- internal and external APIs.
+ * win/tclWinThrd.c: Added use of Tcl_GetAllocMutex to tclAlloc.c and
+ tclCkalloc.c so they can be linked against alternate thread packages.
+ Added Tcl_GetChannelNames to tclIO.c. Added TclVarTraceExists hook so
+ "info exists" triggers read traces exactly like it did in Tcl 7.6.
+ Stubs table changes to reflect new internal and external APIs.
1999-08-09 Jeff Hobbs <hobbs@scriptics.com>
@@ -733,36 +721,36 @@
machines and int overflow testing.
* tests/tcltest.test: fixed minor error in 8.2 result (from dgp)
- * doc/Object.3: clarified Tcl_DecrRefCount docs [Bug: 1952]
- * doc/array.n: clarified array pattern docs [Bug: 1330]
- * doc/clock.n: fixed clock docs [Bug: 693]
+ * doc/Object.3: clarified Tcl_DecrRefCount docs. [Bug 1952]
+ * doc/array.n: clarified array pattern docs. [Bug 1330]
+ * doc/clock.n: fixed clock docs. [Bug 693]
* doc/lindex.n: clarified to account for new end-int behavior.
- * doc/string.n: fixed formatting errors [Bug: 2188 2189]
- * doc/tclvars.n: fixed doc error [Bug: 2042]
- * library/init.tcl: fixed path handling in auto_execok (it could
- miss including the normal path on some Windows machines) [Bug: 1276]
+ * doc/string.n: fixed formatting errors. [Bug 2188 2189]
+ * doc/tclvars.n: fixed doc error. [Bug 2042]
+ * library/init.tcl: fixed path handling in auto_execok (it could miss
+ including the normal path on some Windows machines). [Bug 1276]
1999-08-05 Jeff Hobbs <hobbs@scriptics.com>
- * doc/tclvars.n: Made it clear that tcl_pkgPath was not set
- for Windows (already mentioned in init.tcl) [Bug: 2455]
- * generic/tclLiteral.c: fixed reference to bytes that might
- not be null terminated (using objPtr->bytes, which is) [Bug: 2496]
- * library/http2.1/http.tcl: Made use of "i" in init section use
- local var and start at 0 (was 1). [Bug: 2502]
+ * doc/tclvars.n: Made it clear that tcl_pkgPath was not set for
+ Windows (already mentioned in init.tcl). [Bug 2455]
+ * generic/tclLiteral.c: fixed reference to bytes that might not be
+ null terminated (using objPtr->bytes, which is). [Bug 2496]
+ * library/http2.1/http.tcl: Made use of "i" in init section use local
+ var and start at 0 (was 1). [Bug 2502]
1999-08-04 Scott Stanton <stanton@scriptics.com>
* tests/reg.test: Added test for REG_EXPECT bug fixed by Henry's
patch.
- * generic/regc_nfa.c:
- * generic/regcomp.c:
+ * generic/regc_nfa.c:
+ * generic/regcomp.c:
* generic/rege_dfa.c:
- * generic/regexec.c:
+ * generic/regexec.c:
* generic/regguts.h: Applied patches supplied by Henry Spencer to
greatly enhance the performance of certain classes of regular
- expressions. [Bug: 2440, 2447]
+ expressions. [Bug 2440, 2447]
1999-08-03 Scott Redman <redman@scriptics.com>
@@ -773,7 +761,7 @@
* unix/configure.in:
* win/configure.in: Change beta level to b2.
-
+
* generic/tcl.h:
* generic/tcl.decls:
* generic/tclDecls.h:
@@ -782,104 +770,101 @@
* generic/tclIntDecls.h:
* generic/tclRegexp.h:
* generic/tclStubInit.c: Move some exported public and internal
- functions to the stub tables. Removed functions that are in the
- stub tables (from this and previous changes) from the original
- header files.
+ functions to the stub tables. Removed functions that are in the stub
+ tables (from this and previous changes) from the original header
+ files.
1999-08-01 Scott Redman <redman@scriptics.com>
- * win/tclWinSock.c: Added comment block to SocketThread()
- function. Added code to avoid calling TerminateThread(), but
- instead to send a message to the socket event window to tell it to
- terminate its thread.
+ * win/tclWinSock.c: Added comment block to SocketThread() function.
+ Added code to avoid calling TerminateThread(), but instead to send a
+ message to the socket event window to tell it to terminate its thread.
1999-07-30 Jennifer Hom <jenn@scriptics.com>
* tests/tcltest.test:
- * library/tcltest1.0/tcltest.tcl: Exit with non-zero status if
- there were problems with the way the test suite was started
- (e.g. wrong # arguments).
+ * library/tcltest1.0/tcltest.tcl: Exit with non-zero status if there
+ were problems with the way the test suite was started (e.g. wrong #
+ arguments).
1999-07-30 Jeff Hobbs <hobbs@scriptics.com>
- * generic/tclInt.decls: added declaractions necessary for the
- Tcl test code to work wth stubs [Bug: 2445]
+ * generic/tclInt.decls: added declaractions necessary for the Tcl test
+ code to work wth stubs. [Bug 2445]
-1999-07-30 <redman@scriptics.com>
+1999-07-30 Scott Redman <redman@scriptics.com>
* win/tclWinPipe.c:
- * win/Makefile.in: Fixing launching of 16-bit apps on Win9x from
- wish. The command line was primed with tclpip82.dll, but it was
- ignored. Fixed that, then fixed the gmake makefile to build
- tclpip82.dll as an executable.
+ * win/Makefile.in: Fixing launching of 16-bit apps on Win9x from wish.
+ The command line was primed with tclpip82.dll, but it was ignored.
+ Fixed that, then fixed the gmake makefile to build tclpip82.dll as an
+ executable.
- * win/tclWinSock.c: Applied small patch to get thread-specific
- data after initializing the socket driver.
+ * win/tclWinSock.c: Applied small patch to get thread-specific data
+ after initializing the socket driver.
- * unix/tclUnixThrd.c: Applied patch to fix threads on Irix 6.5.
- Patch from James Dennett. [Bug: 2450]
+ * unix/tclUnixThrd.c: Applied patch to fix threads on Irix 6.5. Patch
+ from James Dennett. [Bug 2450]
- * tests/info.test: Enable test for tclParse.c change (info
- complete).
-
-1999-07-30 <hobbs@scriptics.com>
+ * tests/info.test: Enable test for tclParse.c change (info complete).
+
+1999-07-30 Jeff Hobbs <hobbs@scriptics.com>
- * tclIO.c: added fix for Kupries' trf patch [Bug: 2386]
+ * tclIO.c: added fix for Kupries' trf patch. [Bug 2386]
* tclParse.c: fixed bug in info complete regarding nested square
- brackets [Bug: 2382, 2466]
-
-1999-07-29 <redman@scriptics.com>
+ brackets. [Bug 2382, 2466]
+
+1999-07-29 Scott Redman <redman@scriptics.com>
* win/tclWinChan.c: Allow tcl to open CON and NUL, even for std
- channels. Checking for bad/unusable std channels was moved to Tk
- since its only purpose was to check whether to use the Tk Console
- Window for the std channels. [Bug: 2393 2392 2209 2458]
+ channels. Checking for bad/unusable std channels was moved to Tk since
+ its only purpose was to check whether to use the Tk Console Window for
+ the std channels. [Bug 2393 2392 2209 2458]
* unix/mkLinks.tcl: Applied patch to avoid linking pack.n to
- pack-old.n. Patch from Don Porter. [Bug: 2469]
+ pack-old.n. Patch from Don Porter. [Bug 2469]
+
+ * doc/Encoding.n: Applied patch to fix typo in .SH NAME line. Patch
+ from Don Porter. [Bug 2451]
- * doc/Encoding.n: Applied patch to fix typo in .SH NAME line.
- Patch from Don Porter. [Bug: 2451]
-
- * win/tclWinSock.c: Free Win32 Event handles when destroying
- the socket helper thread.
+ * win/tclWinSock.c: Free Win32 Event handles when destroying the
+ socket helper thread.
-1999-07-28 <jenn@scriptics.com>
+1999-07-28 Jennifer Hom <jenn@scriptics.com>
* tests/tcltest.test:
* library/tcltest1.0/tcltest.tcl: Fixed the condition under which
- ::tcltest::PrintError had an infinite loop problem and added a
- test case for it. Added an optional argument to
- ::tcltest::getMatchingFiles telling it where to search for test
- files.
+ ::tcltest::PrintError had an infinite loop problem and added a test
+ case for it. Added an optional argument to ::tcltest::getMatchingFiles
+ telling it where to search for test files.
-1999-07-27 <redman@scriptics.com>
+1999-07-27 Scott Redman <redman@scriptics.com>
- * tools/tclSplash.bmp: Updated Windows installer bitmap
- to ready Tcl/Tk Version 8.2.
+ * tools/tclSplash.bmp: Updated Windows installer bitmap to ready
+ Tcl/Tk Version 8.2.
-1999-07-26 <redman@scriptics.com>
+1999-07-26 Scott Redman <redman@scriptics.com>
- * tests/tcltest.test: Need to close the new core file, there
- seems to be a hang in threaded WinNT if the file isn't closed.
- Open issue, need to fix that hang.
+ * tests/tcltest.test: Need to close the new core file, there seems to
+ be a hang in threaded WinNT if the file isn't closed. Open issue, need
+ to fix that hang.
- * tests/httpold.test: Add time delay in response from Http server
- so that test cases can properly detect timeout conditions with
- threads enabled on multi-CPU WinNT.
+ * tests/httpold.test: Add time delay in response from Http server so
+ that test cases can properly detect timeout conditions with threads
+ enabled on multi-CPU WinNT.
- * tests/winFCmd.test: Test case winFcmd-1.33 was looking for
- c:\windows, which may not exist. Instead, create a new directory
- on c:\ and use it for the test.
+ * tests/winFCmd.test: Test case winFcmd-1.33 was looking for
+ c:\windows, which may not exist. Instead, create a new directory on
+ c:\ and use it for the test.
* win/tclWinConsole.c:
* win/tclWinPipe.c:
- * win/tclWinSock.c: Fix terminating helper threads by holding any
- mutexes from the primary thread while waiting for the helper
- thread to terminate. Without these changes, the test suite hangs
- on WinNT with 2 CPUs and threads enabled. Open issue, seems to be
- a sporadic hang on dual CPU systems still (very rare).
+ * win/tclWinSock.c: Fix terminating helper threads by holding any
+ mutexes from the primary thread while waiting for the helper thread to
+ terminate. Without these changes, the test suite hangs on WinNT with 2
+ CPUs and threads enabled. Open issue, seems to be a sporadic hang on
+ dual CPU systems still (very rare).
1999-07-26 Jennifer Hom <jenn@scriptics.com>
@@ -888,92 +873,91 @@
* doc/tcltest.n: Cleaned up code in ::tcltest::PrintError, revised
documentation, and added tests for the tcltest package.
-1999-07-23 <redman@scriptics.com>
+1999-07-23 Scott Redman <redman@scriptics.com>
* tests/info.test:
- * generic/tclParse.c: Removed patch for info command, breaks test
- cases on Unix. Patch was bad and needs to be redone
- properly. [Bug: 2382]
+ * generic/tclParse.c: Removed patch for info command, breaks test
+ cases on Unix. Patch was bad and needs to be redone properly. [Bug
+ 2382]
-1999-07-22 <redman@scriptics.com>
+1999-07-22 Scott Redman <redman@scriptics.com>
* Changed version to 8.2b2.
- * win/tclWinSock.c: Fixed hang with threads enabled, fixed
- semaphores with threads disabled.
+ * win/tclWinSock.c: Fixed hang with threads enabled, fixed semaphores
+ with threads disabled.
* win/safe.test: Fixed safe-6.3 with threads enabled.
-
- * win/Makefile.in: Fixed calling of tcltest to fix safe.test
- failures due to path TCL_LIBRARY path.
- * win/tclWinPort.h: Block out include of sys/*.h in order to
- build extensions with MetroWerks compiler for Win32. [Bug: 2385]
-
+ * win/Makefile.in: Fixed calling of tcltest to fix safe.test failures
+ due to path TCL_LIBRARY path.
+
+ * win/tclWinPort.h: Block out include of sys/*.h in order to build
+ extensions with MetroWerks compiler for Win32. [Bug 2385]
+
* generic/tclCmdMZ.c:
* generic/tclIO.c: Fix ANSI-style prototypes based on patch from
- Ulrich Ring. [Bug: 2391]
-
- * unix/Makefile.in: Need to make install-sh executable before
- calling (with chmod +x). [Bug: 2413]
-
+ Ulrich Ring. [Bug 2391]
+
+ * unix/Makefile.in: Need to make install-sh executable before calling
+ (with chmod +x). [Bug 2413]
+
* tests/var.test:
- * generic/tclVar.c: Fixed bug that caused a seg. fault when using
- "array set a(b) {}", which is a bad array name anyway. Now the
- "array set" command will return an error in this case. Added test
- case and fixed existing test. [Bug: 2427]
+ * generic/tclVar.c: Fixed bug that caused a seg. fault when using
+ "array set a(b) {}", which is a bad array name anyway. Now the "array
+ set" command will return an error in this case. Added test case and
+ fixed existing test. [Bug 2427]
-1999-07-21 <redman@scriptics.com>
+1999-07-21 Scott Redman <redman@scriptics.com>
* tests/info.test:
- * generic/tclParse.c: Applied patch to fix "info complete"
- for the string {[a [b]}. Patch from Peter Spjuth. [Bug: 2382]
+ * generic/tclParse.c: Applied patch to fix "info complete" for the
+ string {[a [b]}. Patch from Peter Spjuth. [Bug 2382]
* doc/Utf.3:
* generic/tcl.decls:
* generic/tclDecls.h:
* generic/tclUtf.c: Changed function declarations in
non-platform-specific public APIs to use "unsigned long" instead of
- "size_t", which may not be defined on certain compilers (rather
- than include sys/types.h, which may not exist).
-
+ "size_t", which may not be defined on certain compilers (rather than
+ include sys/types.h, which may not exist).
+
* unix/Makefile.in: Added the Windows configure script to the
distribution file list, already shipping configure.in and the .m4
files, but needed the configure script itself.
-
+
* win/makefile.vc: Changed version number of DDE package in VC++
makefile to use 1.1 instead of 1.0.
* doc/open.n: Added documentation of \\.\comX notation for opening
serial ports on Windows (alternative to comX:).
-
+
* tests/ioCmd.test:
* doc/open.n:
* win/tclWinSerial.c: Applied patch from Rolf Schroedter to add
- -pollinterval option to fconfigure to modify the maxblocktime used
- in the fileevent polling. Added documentation and fixed the test
- case as well.
-
- * win/tclWinSock.c: Modified 8.1.0 version of the Win32 socket
- driver to move the handling of the socket event window in a
- separate thread. It also turned out that Win95 & Win98 were, in
- some cases, getting multiple FD_ACCEPTs but only handling one.
- Added a count for the FD_ACCEPT to take care of this. Tested on
- NT4 SP3, NT4 SP4, Win95, and Win98.
- [Bug: 2178 2256 2259 2329 2323 2355]
-
-1999-07-21 <jpeek@scriptics.com>
+ -pollinterval option to fconfigure to modify the maxblocktime used in
+ the fileevent polling. Added documentation and fixed the test case as
+ well.
+
+ * win/tclWinSock.c: Modified 8.1.0 version of the Win32 socket driver
+ to move the handling of the socket event window in a separate thread.
+ It also turned out that Win95 & Win98 were, in some cases, getting
+ multiple FD_ACCEPTs but only handling one. Added a count for the
+ FD_ACCEPT to take care of this. Tested on NT4 SP3, NT4 SP4, Win95, and
+ Win98. [Bug 2178 2256 2259 2329 2323 2355]
+
+1999-07-21 Jerry Peek <jpeek@scriptics.com>
* README: Small tweaks to clean up typos and wording.
1999-07-20 Melissa Hirschl <hershey@matisse.scriptics.com>
- * generic/tclInitScript.h:
- * unix/tclUnixInit.c: merged code with 8.0.5. We now use an
+ * generic/tclInitScript.h:
+ * unix/tclUnixInit.c: merged code with 8.0.5. We now use an
intermediate global tcl var "tclDefaultLibrary" to keep the
- "tcl_library" var from being set by the default value in the
- Makefile. Also fixed a bug in which caused the value of
- TCL_LIBRARY env var to be ignored.
+ "tcl_library" var from being set by the default value in the Makefile.
+ Also fixed a bug in which caused the value of TCL_LIBRARY env var to
+ be ignored.
* unix/tclWinInit.c: just updated some comments.
1999-07-19 Melissa Hirschl <hershey@matisse.scriptics.com>
@@ -981,119 +965,115 @@
* library/http2.1/http.tcl: updated -useragent text to say version
2.1.
-1999-07-16 <redman@scriptics.com>
+1999-07-16 Scott Redman <redman@scriptics.com>
* generic/tcl.decls:
* generic/tclDecls.h:
- * generic/tclStubInit.c: Add Tcl_SetNotifier to stub table.
- [Bug: 2364]
-
+ * generic/tclStubInit.c: Add Tcl_SetNotifier to stub table. [Bug 2364]
+
* unix/aclocal.m4:
- * unix/tcl.m4: Add check for Alpha/Linux to correct the IEEE
- floating flag to the compiler, should be -mieee. Patch from Don
- Porter.
-
- * tools/tcl.hpj.in: Change version number of .cnt file referenced
- in .HPJ file.
-
-1999-07-15 <redman@scriptics.com>
-
+ * unix/tcl.m4: Add check for Alpha/Linux to correct the IEEE floating
+ flag to the compiler, should be -mieee. Patch from Don Porter.
+
+ * tools/tcl.hpj.in: Change version number of .cnt file referenced in
+ .HPJ file.
+
+1999-07-15 Scott Redman <redman@scriptics.com>
+
* tools/tcl.wse.in: Fixed naming of target files for Windows.
-1999-07-14 <jpeek@scriptics.com>
+1999-07-14 Jerry Peek <jpeek@scriptics.com>
* doc/re_syntax.n: Deleted sentence as suggested by Scott S.
-1999-07-12 <jpeek@scriptics.com>
+1999-07-12 Jerry Peek <jpeek@scriptics.com>
- * doc/re_syntax.n: Removed two notes to myself (oops), cleaned
- up wording, fixed changebars, made two examples easier to read.
+ * doc/re_syntax.n: Removed two notes to myself (oops), cleaned up
+ wording, fixed changebars, made two examples easier to read.
-1999-07-11 <redman@scriptics.com>
+1999-07-11 Scott Redman <redman@scriptics.com>
- * win/makefile.vc: Since the makefile.vc should continue to work
- while we're working out bugs/issues in the new TEA-style
+ * win/makefile.vc: Since the makefile.vc should continue to work while
+ we're working out bugs/issues in the new TEA-style
autoconf/configure/gmake build mechanism for Windows, the version
- numbers of the Tcl libraries need to remain in sync. Modified the
+ numbers of the Tcl libraries need to remain in sync. Modified the
version numbers in the makefile to reflect the change to 8.2b1.
-1999-07-09 <redman@scriptics.com>
+1999-07-09 Scott Redman <redman@scriptics.com>
- * win/configure.in: Eval DLLSUFFIX, LIBSUFFIX, and EXESUFFIX in
- the configure script so that substitutions get expanded before
- being placed in the Makefile. The "d" portion for debug libraries
- and DLLs was not being set properly.
-
-1999-07-08 <stanton@scriptics.com>
+ * win/configure.in: Eval DLLSUFFIX, LIBSUFFIX, and EXESUFFIX in the
+ configure script so that substitutions get expanded before being
+ placed in the Makefile. The "d" portion for debug libraries and DLLs
+ was not being set properly.
- * tests/string.test:
- * generic/tclCmdMZ.c: Fixed bug in string range bounds checking
- code.
+1999-07-08 Scott Stanton <stanton@scriptics.com>
+
+ * tests/string.test:
+ * generic/tclCmdMZ.c: Fixed bug in string range bounds checking code.
1999-07-08 Jennifer Hom <jenn@scriptics.com>
* doc/tcltest.n:
* library/tcltest1.0/tcltest.tcl: Removed -asidefromdir and
- -relateddir flags, removed unused ::tcltest::dotests proc, cleaned
- up implementation of core file checking, and fixed the code that
- checks for 1-letter flag abbreviations.
+ -relateddir flags, removed unused ::tcltest::dotests proc, cleaned up
+ implementation of core file checking, and fixed the code that checks
+ for 1-letter flag abbreviations.
-1999-07-08 <stanton@scriptics.com>
+1999-07-08 Scott Stanton <stanton@scriptics.com>
- * win/Makefile.in: Added tcltest target so runtest works
- properly. Added missing names to the clean/distclean targets.
+ * win/Makefile.in: Added tcltest target so runtest works properly.
+ Added missing names to the clean/distclean targets.
- * tests/reg.test:
- * generic/rege_dfa.c: Applied fix supplied by Henry Spencer for
- bug in DFA state caching under lookahead conditions. [Bug: 2318]
+ * tests/reg.test:
+ * generic/rege_dfa.c: Applied fix supplied by Henry Spencer for bug in
+ DFA state caching under lookahead conditions. [Bug 2318]
-1999-07-07 <stanton@scriptics.com>
+1999-07-07 Scott Stanton <stanton@scriptics.com>
* doc/fconfigure.n: Clarified default buffering behavior for the
- standard channels. [Bug: 2335]
+ standard channels. [Bug 2335]
-1999-07-06 <redman@scriptics.com>
+1999-07-06 Scott Redman <redman@scriptics.com>
- * win/tclWinSerial.c: New implementation of serial port driver
- from Rolf Shroedter (Rolf.Schroedter@dlr.de) that allows more than
- one byte to be read from the port. Implemented using polling
- instead of threads, there is a max. 10ms latency between checking the
- port for file events. [Bug: 1980 2217]
+ * win/tclWinSerial.c: New implementation of serial port driver from
+ Rolf Shroedter (Rolf.Schroedter@dlr.de) that allows more than one byte
+ to be read from the port. Implemented using polling instead of
+ threads, there is a max. 10ms latency between checking the port for
+ file events. [Bug 1980 2217]
-1999-07-06 <welch@scriptics.com>
+1999-07-06 Brent Welch <welch@scriptics.com>
- * library/http2.0/http.tcl: Fixed the -timeout option so it
- handles timeouts that occur during connection attempts to
- hosts that are down (the only case that really matters!)
+ * library/http2.0/http.tcl: Fixed the -timeout option so it handles
+ timeouts that occur during connection attempts to hosts that are down
+ (the only case that really matters!)
-1999-07-03 <welch@scriptics.com>
+1999-07-03 Brent Welch <welch@scriptics.com>
* doc/ChnlStack.3:
* generic/tcl.decls:
- * generic/tclIO.c: Added a new variant of the "Trf patch"
- from Andreas Kupres that adds new C APIs Tcl_StackChannel,
- Tcl_UnstackChannel, and Tcl_GetStackedChannel.
+ * generic/tclIO.c: Added a new variant of the "Trf patch" from Andreas
+ Kupres that adds new C APIs Tcl_StackChannel, Tcl_UnstackChannel, and
+ Tcl_GetStackedChannel.
-1999-07-03 <welch@scriptics.com>
+1999-07-03 Brent Welch <welch@scriptics.com>
* generic/tclNotify.c:
* unix/tclUnixNotfy.c:
* unix/tclXtTest.c:
* unix/tclXtNotify.c:
* win/tclWinNotify.c:
- * mac/tclMacNotify.c: Added Tcl_SetNotifier and the associated
- hook points in the notifiers to be able to replace the notifier
- calls at runtime The Xt notifier and test program use this hook.
+ * mac/tclMacNotify.c: Added Tcl_SetNotifier and the associated hook
+ points in the notifiers to be able to replace the notifier calls at
+ runtime. The Xt notifier and test program use this hook.
-1999-07-03 <welch@scriptics.com>
+1999-07-03 Brent Welch <welch@scriptics.com>
- * generic/tclParse.c: Changed parsing of variable names to
- allow empty array names. Now "$(foo)" is a variable reference!
- Previous you had to use something like $::(foo), which is slower.
- This change is requested by Jean-Luc Fontaine for his STOOOP
- package.
+ * generic/tclParse.c: Changed parsing of variable names to allow empty
+ array names. Now "$(foo)" is a variable reference! Previous you had to
+ use something like $::(foo), which is slower. This change is requested
+ by Jean-Luc Fontaine for his STOOOP package.
-1999-07-01 <redman@scriptics.com>
+1999-07-01 Scott Redman <redman@scriptics.com>
* generic/tclCmdAH.c:
* generic/tclFCmd.c: Call TclStat instead of TclpStat in order to
@@ -1104,30 +1084,27 @@
* library/tcltest1.0/pkgIndex.tcl:
* library/tcltest1.0/tcltest.tcl:
* doc/tcltest.n:
- * tests/all.tcl: Added -preservecore, -limitconstraints, -help,
- -file, -notfile, -relateddir and -asidefromdir flags to the
- tcltest package along with exported proc
- ::tcltest::getMatchingFiles. The documentation was modified to
- match and all.tcl was modified to use the new functionality
- instead of implementing -file itself.
+ * tests/all.tcl: Added -preservecore, -limitconstraints, -help, -file,
+ -notfile, -relateddir and -asidefromdir flags to the tcltest package
+ along with exported proc ::tcltest::getMatchingFiles. The
+ documentation was modified to match and all.tcl was modified to use
+ the new functionality instead of implementing -file itself.
-1999-06-28 <redman@scriptics.com>
+1999-06-28 Scott Redman <redman@scriptics.com>
* generic/tclIndexObj.c:
* doc/GetIndex.3:
* tests/binary.test:
- * tests/winDde.test: Applied patch from Peter Hardie (with
- changes) to fix problem with Tcl_GetIndexFromObj() when the key
- being passed is the empty string. It used to match "" and return
- TCL_OK, but it should have returned TCL_ERROR instead. Added test
- case to "binary" and "dde" commands to check the behavior. Added
- documentation note as well.
+ * tests/winDde.test: Applied patch from Peter Hardie (with changes) to
+ fix problem with Tcl_GetIndexFromObj() when the key being passed is
+ the empty string. It used to match "" and return TCL_OK, but it should
+ have returned TCL_ERROR instead. Added test case to "binary" and "dde"
+ commands to check the behavior. Added documentation note as well.
-1999-06-26 <redman@scriptics.com>
+1999-06-26 Scott Redman <redman@scriptics.com>
- * win/tclWinDde.c: Applied patch from Peter Hardie to add poke
- command to dde. Also rev'd version of dde package to 1.1.
- [Bug: 1738]
+ * win/tclWinDde.c: Applied patch from Peter Hardie to add poke command
+ to dde. Also rev'd version of dde package to 1.1. [Bug 1738]
1999-06-25 Jennifer Hom <jenn@scriptics.com>
@@ -1136,25 +1113,24 @@
* library/tcltest1.0/pkgIndex.tcl:
* library/tcltest1.0/tcltest.tcl:
* library/tcltest1.0: Added initial implementation of the Tcl test
- harness package. This package was based on the defs.tcl file that
- was part of the tests directory. Reversed the way that tests were
+ harness package. This package was based on the defs.tcl file that was
+ part of the tests directory. Reversed the way that tests were
evaluated to fix a problem with false passes.
* doc/tcltest.n: Added documentation for the tcltest package.
* tests/README:
* tests/defs.tcl:
- * tests/all.tcl: Modified all test files (tests/*.test) and
- all.tcl to use the new tcltest package and removed references to
- the defs.tcl file. Modified the README file to point to the man
- page for tcltest.
-
-1999-06-25 <stanton@scriptics.com>
-
- * tests/reg.test:
+ * tests/all.tcl: Modified all test files (tests/*.test) and all.tcl to
+ use the new tcltest package and removed references to the defs.tcl
+ file. Modified the README file to point to the man page for tcltest.
+
+1999-06-25 Scott Stanton <stanton@scriptics.com>
+
+ * tests/reg.test:
* generic/regexec.c: Fixed bugs in non-greedy quantifiers.
-1999-06-23 <jpeek@scriptics.com>
+1999-06-23 Jerry Peek <jpeek@scriptics.com>
* doc/re_syntax.n:
* doc/switch.n:
@@ -1162,59 +1138,59 @@
* doc/RegExp.3:
* doc/regexp.n:
* doc/regsub.n: Moved information about syntax of 8.1 regular
- expressions from regexp(n) manpage into new re_syntax(n) page.
- Added pointers from other manpages to new re_syntax(n) page.
+ expressions from regexp(n) manpage into new re_syntax(n) page. Added
+ pointers from other manpages to new re_syntax(n) page.
-1999-06-23 <stanton@scriptics.com>
+1999-06-23 Scott Stanton <stanton@scriptics.com>
* unix/Makefile.in: Changed install-doc to install-man.
- * tools/uniParse.tcl:
- * tools/uniClass.tcl:
- * tools/README:
- * tests/string.test:
- * generic/regc_locale.c:
- * generic/tclUniData.c:
- * generic/tclUtf.c:
+ * tools/uniParse.tcl:
+ * tools/uniClass.tcl:
+ * tools/README:
+ * tests/string.test:
+ * generic/regc_locale.c:
+ * generic/tclUniData.c:
+ * generic/tclUtf.c:
* doc/string.n: Updated Unicode character tables to reflect latest
- Unicode 2.1 data. Also rationalized "regexp" and "string is"
+ Unicode 2.1 data. Also rationalized "regexp" and "string is"
definitions of character classes.
-1999-06-21 <stanton@scriptics.com>
+1999-06-21 Scott Stanton <stanton@scriptics.com>
* unix/tclUnixThrd.c (TclpThreadCreate): Fixed memory leak where
- thread attributes were not being released. [Bug: 2254]
+ thread attributes were not being released. [Bug 2254]
-1999-06-17 <stanton@scriptics.com>
+1999-06-17 Scott Stanton <stanton@scriptics.com>
- * tests/regexp.test:
- * generic/tclCmdMZ.c:
- * generic/tclCmdIL.c: Changed to use new regexp interfaces. Added
+ * tests/regexp.test:
+ * generic/tclCmdMZ.c:
+ * generic/tclCmdIL.c: Changed to use new regexp interfaces. Added
-expanded, -line, -linestop, and -lineanchor switches to regsub.
- * doc/RegExp.3: Documented the new regexp interfaces and
- the compile/execute flags.
-
- * generic/tclTest.c:
+ * doc/RegExp.3: Documented the new regexp interfaces and the
+ compile/execute flags.
+
+ * generic/tclTest.c:
* generic/tclRegexp.h:
- * generic/tclRegexp.c:
- * generic/tcl.h:
- * generic/tcl.decls: Renamed Tcl_RegExpMatchObj to
- Tcl_RegExpExecObj and added a new Tcl_RegExpMatchObj that is
- equivalent to Tcl_RegExpMatch. Added public macros for the regexp
- compile/execute flags. Changed to store either an object pointer
- or a string pointer in the TclRegexp structure. Changed to avoid
- adding a reference to the object or copying the string.
+ * generic/tclRegexp.c:
+ * generic/tcl.h:
+ * generic/tcl.decls: Renamed Tcl_RegExpMatchObj to Tcl_RegExpExecObj
+ and added a new Tcl_RegExpMatchObj that is equivalent to
+ Tcl_RegExpMatch. Added public macros for the regexp compile/execute
+ flags. Changed to store either an object pointer or a string pointer
+ in the TclRegexp structure. Changed to avoid adding a reference to the
+ object or copying the string.
* generic/regcomp.c: lint
- * tests/reg.test:
- * generic/regex.h:
+ * tests/reg.test:
+ * generic/regex.h:
* generic/regc_lex.c: Added REG_BOSONLY flag to allow Expect to
iterate through a string an only find matches that start at the
current position within the string.
-1999-06-16 <wart@scriptics.com>
+1999-06-16 Michael Thomas <wart@scriptics.com>
* unix/configure.in:
* unix/Makefile.in:
@@ -1224,15 +1200,15 @@
1999-06-16 Melissa Hirschl <hershey@matisse.scriptics.com>
- * generic/tclVar.c (Tcl_VariableObjCmd): fixed premature increment
- in loop that was causing out-of-bounds reads on array "varName".
+ * generic/tclVar.c (Tcl_VariableObjCmd): fixed premature increment in
+ loop that was causing out-of-bounds reads on array "varName".
-1999-06-16 <stanton@scriptics.com>
+1999-06-16 Scott Stanton <stanton@scriptics.com>
* tests/execute.test:
- * generic/tclExecute.c (TclExecuteByteCode): Fixed crash caused by
- a bug in INST_LOAD_SCALAR1 where the scalar index was read as
- a signed 1 byte value instead of unsigned. [Bug: 2243]
+ * generic/tclExecute.c (TclExecuteByteCode): Fixed crash caused by a
+ bug in INST_LOAD_SCALAR1 where the scalar index was read as a signed 1
+ byte value instead of unsigned. [Bug 2243]
1999-06-14 Melissa Hirschl <hershey@matisse.scriptics.com>
@@ -1242,118 +1218,116 @@
* win/Makefile.in
* win/makefile.vc
* generic/tclStringObj.c:
- Merged String and Unicode object types. Added new functions to
- the puplic API: Tcl_NewUnicodeObj, Tcl_SetUnicodeObj,
- Tcl_GetUnicode, Tcl_GetUniChar, Tcl_GetCharLength, Tcl_GetRange,
+ Merged String and Unicode object types. Added new functions to the
+ puplic API: Tcl_NewUnicodeObj, Tcl_SetUnicodeObj, Tcl_GetUnicode,
+ Tcl_GetUniChar, Tcl_GetCharLength, Tcl_GetRange,
Tcl_AppendUnicodeToObj.
-1999-06-09 <stanton@scriptics.com>
+1999-06-09 Scott Stanton <stanton@scriptics.com>
- * generic/tclUnicodeObj.c: Lots of cleanup and simplification.
- Fixed several memory bugs. Added TclAppendUnicodeToObj.
+ * generic/tclUnicodeObj.c: Lots of cleanup and simplification. Fixed
+ several memory bugs. Added TclAppendUnicodeToObj.
* generic/tclInt.h: Added declarations for various Unicode string
- functions.
-
- * generic/tclRegexp.c:
- * generic/tclCmdMZ.c: Changed to use new Unicode string interfaces
- for better performance.
-
- * generic/tclRegexp.h:
- * generic/tclRegexp.c:
- * generic/tcl.h:
- * generic/tcl.decls: Added Tcl_RegExpMatchObj and
- Tcl_RegExpGetInfo calls to access lower level regexp API. These
- features are needed by Expect. This is a preliminary
- implementation pending final review and cleanup.
+ functions.
+
+ * generic/tclRegexp.c:
+ * generic/tclCmdMZ.c: Changed to use new Unicode string interfaces for
+ better performance.
+
+ * generic/tclRegexp.h:
+ * generic/tclRegexp.c:
+ * generic/tcl.h:
+ * generic/tcl.decls: Added Tcl_RegExpMatchObj and Tcl_RegExpGetInfo
+ calls to access lower level regexp API. These features are needed by
+ Expect. This is a preliminary implementation pending final review and
+ cleanup.
* generic/tclCmdMZ.c:
- * tests/string.test: Fixed bug where string map failed on null
- strings.
+ * tests/string.test: Fixed bug where string map failed on null strings
- * generic/regexec.c:
+ * generic/regexec.c:
* unix/tclUnixNotfy.c: lint
* tools/genStubs.tcl: Changed to always write output in LF mode.
-1999-06-08 <stanton@scriptics.com>
+1999-06-08 Scott Stanton <stanton@scriptics.com>
- * win/tclWinSock.c: Rolled back to the 8.1.0 implementation
- because of serious problems with the new driver. Basically no
- incoming socket connections would be reported to a server port.
- The 8.1.1 code needs to be redesigned and fixed correctly.
+ * win/tclWinSock.c: Rolled back to the 8.1.0 implementation because of
+ serious problems with the new driver. Basically no incoming socket
+ connections would be reported to a server port. The 8.1.1 code needs
+ to be redesigned and fixed correctly.
1999-06-07 Melissa Hirschl <hershey@matisse.scriptics.com>
- * tests/string.test:
+ * tests/string.test:
* generic/tclVar.c (Tcl_SetVar2Ex):
* generic/tclStringObj.c (Tcl_AppendObjToObj):
- * generic/tclCmdMZ.c (Tcl_StringObjCmd): optimized the string
- index, string length, string range, and append command in cases
- where the object's internal rep is a bytearray. Objects with
- other internal reps are converted to have the new unicode internal
- rep.
-
- * unix/Makefile.in:
- * win/Makefile.in:
- * win/Makefile.vc:
- * tests/unicode.test:
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd): optimized the string index,
+ string length, string range, and append command in cases where the
+ object's internal rep is a bytearray. Objects with other internal reps
+ are converted to have the new unicode internal rep.
+
+ * unix/Makefile.in:
+ * win/Makefile.in:
+ * win/Makefile.vc:
+ * tests/unicode.test:
* generic/tclInt.h:
* generic/tclObj.c:
* generic/tclUnicodeObj.c: added a new object type to store the
unicode representation of a string.
* generic/tclTestObj.c: added the objtype option to the testobj
- command. This option returns the name of the type of internal rep
- an object has.
+ command. This option returns the name of the type of internal rep an
+ object has.
-1999-06-04 <stanton@scriptics.com>
+1999-06-04 Scott Stanton <stanton@scriptics.com>
- * win/configure.in:
+ * win/configure.in:
* win/Makefile.in: Windows build now handles static/dynamic
- debug/nodebug builds and supports the standard targets using
- Cygwin user tools plus GNU make and autoconf.
+ debug/nodebug builds and supports the standard targets using Cygwin
+ user tools plus GNU make and autoconf.
-1999-06-03 <stanton@scriptics.com>
+1999-06-03 Scott Stanton <stanton@scriptics.com>
- * generic/tclCmdMZ.c (Tcl_StringObjCmd):
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd):
* tests/string.test: Fixed bug where string equal/compare -nocase
- reported wrong result on null strings. [Bug: 2138]
+ reported wrong result on null strings. [Bug 2138]
-1999-06-02 <stanton@scriptics.com>
+1999-06-02 Scott Stanton <stanton@scriptics.com>
- * generic/tclUtf.c (Tcl_UtfNcasecmp): Fixed incorrect computation
- of relative ordering. [Bug: 2135]
+ * generic/tclUtf.c (Tcl_UtfNcasecmp): Fixed incorrect computation of
+ relative ordering. [Bug 2135]
-1999-06-01 <stanton@scriptics.com>
+1999-06-01 Scott Stanton <stanton@scriptics.com>
* unix/configure.in: Fixed various small configure.in patches
- submitted by Jan Nijtmans. [Bug: 2121]
-
- * tests/reg.test:
- * generic/regc_color.c:
- * generic/regc_cvec.c:
- * generic/regc_lex.c:
- * generic/regc_locale.c:
- * generic/regc_nfa.c:
- * generic/regcomp.c:
- * generic/regcustom.h:
- * generic/rege_dfa.c:
- * generic/regerror.c:
- * generic/regerrs.h:
- * generic/regex.h:
- * generic/regexec.c:
- * generic/regfree.c:
- * generic/regfronts.c:
- * generic/regguts.h:
- * generic/tclCmdMZ.c:
- * generic/tclRegexp.c:
- * generic/tclRegexp.h:
+ submitted by Jan Nijtmans. [Bug 2121]
+
+ * tests/reg.test:
+ * generic/regc_color.c:
+ * generic/regc_cvec.c:
+ * generic/regc_lex.c:
+ * generic/regc_locale.c:
+ * generic/regc_nfa.c:
+ * generic/regcomp.c:
+ * generic/regcustom.h:
+ * generic/rege_dfa.c:
+ * generic/regerror.c:
+ * generic/regerrs.h:
+ * generic/regex.h:
+ * generic/regexec.c:
+ * generic/regfree.c:
+ * generic/regfronts.c:
+ * generic/regguts.h:
+ * generic/tclCmdMZ.c:
+ * generic/tclRegexp.c:
+ * generic/tclRegexp.h:
* generic/tclTest.c: Applied Henry Spencer's latest regexp patches
- that fix an infinite loop bug and add support for testing whether
- a string could match with additional input. [Bug: 2117]
+ that fix an infinite loop bug and add support for testing whether a
+ string could match with additional input. [Bug 2117]
-1999-05-28 <stanton@scriptics.com>
+1999-05-28 Scott Stanton <stanton@scriptics.com>
* generic/tclObj.c: Changed to eliminate use of isupper/tolower in
favor of the Unicode versions.
@@ -1362,427 +1336,409 @@
* win/configure.in: Added preliminary TEA implementation.
* win/tclWinDde.c: Fixed bug where dde calls were being passed an
- invalid dde handle because Initialize had not been called.
- [Bug: 2124]
+ invalid dde handle because Initialize had not been called. [Bug 2124]
-1999-05-26 <redman@scriptic.com>
+1999-05-26 Scott Redman <redman@scriptic.com>
- * generic/tclThreadTest.c: Fixed race condition in testthread
- code that showed up in the WinNT test suite intermittently.
+ * generic/tclThreadTest.c: Fixed race condition in testthread code
+ that showed up in the WinNT test suite intermittently.
- * win/tclWinSock.c: Fixed a hang in the WinNT socket driver, wake
- up the socket thread every 100ms to check for events on the
- sockets that did not wake up the thread (race condition).
+ * win/tclWinSock.c: Fixed a hang in the WinNT socket driver, wake up
+ the socket thread every 100ms to check for events on the sockets that
+ did not wake up the thread (race condition).
-1999-05-24 <stanton@scriptics.com>
+1999-05-24 Scott Stanton <stanton@scriptics.com>
- * tools/genStubs.tcl: Changed to allow a list of platforms instead
- of just one at a time.
+ * tools/genStubs.tcl: Changed to allow a list of platforms instead of
+ just one at a time.
- * generic/tcl.decls:
- * generic/tclCmdMZ.c:
- * generic/tclDecls.h:
- * generic/tclInt.decls:
- * generic/tclIntDecls.h:
- * generic/tclPort.h:
- * generic/tclStubInit.c:
+ * generic/tcl.decls:
+ * generic/tclCmdMZ.c:
+ * generic/tclDecls.h:
+ * generic/tclInt.decls:
+ * generic/tclIntDecls.h:
+ * generic/tclPort.h:
+ * generic/tclStubInit.c:
* generic/tclStubLib.c: Various header file related changes and other
lint to try to get the Mac builds working.
-1999-05-21 <redman@scriptics.com>
+1999-05-21 Scott Redman <redman@scriptics.com>
- * win/tclWinPipe.c: Fix bug when launching command.com on
- Win95/98. Need to wait for the procInfo.hProcess of the process that
- was created, not the hProcess of the current process. [Bug: 2105]
+ * win/tclWinPipe.c: Fix bug when launching command.com on Win95/98.
+ Need to wait for the procInfo.hProcess of the process that was
+ created, not the hProcess of the current process. [Bug 2105]
-1999-05-20 <redman@scriptics.com>
+1999-05-20 Scott Redman <redman@scriptics.com>
- * library/init.tcl: Add the directory where the executable is, and
- the ../lib directory relative to that, to the auto_path variable.
-
-1999-05-19 <stanton@scriptics.com>
+ * library/init.tcl: Add the directory where the executable is, and the
+ ../lib directory relative to that, to the auto_path variable.
+
+1999-05-19 Scott Stanton <stanton@scriptics.com>
Merged in various changes submitted by Jeff Hobbs:
-
- * generic/tcl.decls:
- * generic/tclUtf.c: Added Tcl_UniCharIs* functions for control,
- graph, print, and punct classes.
+
+ * generic/tcl.decls:
+ * generic/tclUtf.c: Added Tcl_UniCharIs* functions for control, graph,
+ print, and punct classes.
* generic/tclUtil.c:
* doc/StrMatch.3: Added Tcl_StringCaseMatch() implementation to
support case-insensitive globbing.
-
- * doc/string.n:
- * unix/mkLinks:
- * tests/string.test:
- * generic/tclCmdMZ.c: Added additional character class tests,
- added -nocase switch to "string match", changed string first/last
- to use offsets.
-1999-05-19 <redman@scriptics.com>
+ * doc/string.n:
+ * unix/mkLinks:
+ * tests/string.test:
+ * generic/tclCmdMZ.c: Added additional character class tests, added
+ -nocase switch to "string match", changed string first/last to use
+ offsets.
+
+1999-05-19 Scott Redman <redman@scriptics.com>
* generic/tcl.h: Add extern "C" block around entire header file for
- C++ compilers to fix linkage issues. Submitted by Don Porter and
- Paul Duffin.
+ C++ compilers to fix linkage issues. Submitted by Don Porter and Paul
+ Duffin.
- * generic/tclRegexp.c: Fix bug when the regexp cache is empty
- and an empty pattern is used in regexp ( such as {} or "" ).
+ * generic/tclRegexp.c: Fix bug when the regexp cache is empty and an
+ empty pattern is used in regexp ( such as {} or "" ).
-1999-05-18 <stanton@scriptics.com>
+1999-05-18 Scott Stanton <stanton@scriptics.com>
- * win/tclWinChan.c: Modified initialization code to avoid
- inherenting closed or invalid channels. If the standard input is
- anything other than a console, file, serial port, or pipe, then we
- fall back to the standard Tk window console.
+ * win/tclWinChan.c: Modified initialization code to avoid inherenting
+ closed or invalid channels. If the standard input is anything other
+ than a console, file, serial port, or pipe, then we fall back to the
+ standard Tk window console.
-1999-05-14 <stanton@scriptics.com>
+1999-05-14 Scott Stanton <stanton@scriptics.com>
- * generic/tclCmdAH.c (Tcl_ForObjCmd): Fixed crash caused by
- failure to reset the result before evaluating the test
- expression.
+ * generic/tclCmdAH.c (Tcl_ForObjCmd): Fixed crash caused by failure to
+ reset the result before evaluating the test expression.
-1999-05-14 <surles@scriptics.com>
+1999-05-14 Bryan Surles <surles@scriptics.com>
- * generic/tclBasic.c (Tcl_CreateInterp): Added introspection
- variable for threaded interps. If the interp was compiled with
- threads enabled, the tcl_platform(threaded) variable will exist.
+ * generic/tclBasic.c (Tcl_CreateInterp): Added introspection variable
+ for threaded interps. If the interp was compiled with threads enabled,
+ the tcl_platform(threaded) variable will exist.
-1999-05-14 <redman@scriptics.com>
+1999-05-14 Scott Redman <redman@scriptics.com>
* generic/tclDate.c: Applied patch to fix 100-year and 400-year
- boundaries in leap year code, from Isaac Hollander. [Bug: 2066]
+ boundaries in leap year code, from Isaac Hollander. [Bug 2066]
-1999-05-13 <stanton@scriptics.com>
+1999-05-13 Scott Stanton <stanton@scriptics.com>
* unix/Makefile.in:
* unix/tclAppInit.c: Minor cleanup related to Xt notifier.
-
- * unix/tclUnixInit.c (TclpSetInitialEncodings): Tcl now looks for
- an encoding subfield in the LANG/LC_ALL variables in cases where
- the locale is not found in the locale table. Ensure that
- setlocale() is called at least once so X11 will initialize
- properly. Also, forces the LC_NUMERIC locale to be "C" so numeric
- processing in scripts is not affected by the current locale
- setting. [Bug: 1989]
- * generic/tclRegexp.c: Increased per-thread regexp cache to 30
- slots. This seems to be about the right number for larger
- applications like exmh. [Bug: 1063]
+ * unix/tclUnixInit.c (TclpSetInitialEncodings): Tcl now looks for an
+ encoding subfield in the LANG/LC_ALL variables in cases where the
+ locale is not found in the locale table. Ensure that setlocale() is
+ called at least once so X11 will initialize properly. Also, forces the
+ LC_NUMERIC locale to be "C" so numeric processing in scripts is not
+ affected by the current locale setting. [Bug 1989]
+
+ * generic/tclRegexp.c: Increased per-thread regexp cache to 30 slots.
+ This seems to be about the right number for larger applications like
+ exmh. [Bug 1063]
-1999-05-12 <stanton@scriptics.com>
+1999-05-12 Scott Stanton <stanton@scriptics.com>
* doc/tclsh.1: Updated references to rc script names to accurately
reflect the platform differences on Windows.
- * tests/regexp.test:
- * generic/tclInt.h:
- * generic/tclBasic.c:
+ * tests/regexp.test:
+ * generic/tclInt.h:
+ * generic/tclBasic.c:
* generic/tclRegexp.h:
- * generic/tclRegexp.c: Replaced the per-interpreter regexp cache
- with a per-thread cache. Changed the Regexp object to take
- advantage of this extra cache. Added a reference count to the
- TclRegexp type so regexps can be shared by multiple objects.
- Removed the per-interp regexp cache from the interpreter. Now
- regexps can be used with no need for an interpreter. [Bug: 1063]
-
- * win/tclWinInit.c (TclpSetVariables): Avoid calling GetUserName
- if the value can be determined from the USERNAME environment
- variable. GetUserName is very slow.
-
-1999-05-07 <stanton@scriptics.com>
-
- * win/winDumpExts.c:
- * win/makefile.vc: Removed incorrect patch. [Bug: 1998]
-
+ * generic/tclRegexp.c: Replaced the per-interpreter regexp cache with
+ a per-thread cache. Changed the Regexp object to take advantage of
+ this extra cache. Added a reference count to the TclRegexp type so
+ regexps can be shared by multiple objects. Removed the per-interp
+ regexp cache from the interpreter. Now regexps can be used with no
+ need for an interpreter. [Bug 1063]
+
+ * win/tclWinInit.c (TclpSetVariables): Avoid calling GetUserName if
+ the value can be determined from the USERNAME environment variable.
+ GetUserName is very slow.
+
+1999-05-07 Scott Stanton <stanton@scriptics.com>
+
+ * win/winDumpExts.c:
+ * win/makefile.vc: Removed incorrect patch. [Bug 1998]
+
* generic/tcl.decls: Replaced const with CONST.
- * generic/tclResult.c (Tcl_AppendResultVA):
+ * generic/tclResult.c (Tcl_AppendResultVA):
* generic/tclStringObj.c (Tcl_AppendStringsToObjVA): Fixed to copy
arglist using memcpy instead of assignment so it works properly on
- OS/390. [Bug: 1997]
+ OS/390. [Bug 1997]
* generic/tclLoadNone.c: Updated to use current interfaces, added
- TclpUnloadFile. [Bug: 2003]
+ TclpUnloadFile. [Bug 2003]
- * win/winDumpExts.c:
- * win/makefile.vc: Changed to emit library name in defs
- file. [Bug: 1998]
+ * win/winDumpExts.c:
+ * win/makefile.vc: Changed to emit library name in defs file. [Bug
+ 1998]
- * unix/configure.in: Added fix for OS/390. [Bug: 1976]
+ * unix/configure.in: Added fix for OS/390. [Bug 1976]
-1999-05-06 <stanton@scriptics.com>
+1999-05-06 Scott Stanton <stanton@scriptics.com>
- * tests/string.test:
- * generic/tclCmdMZ.c:
+ * tests/string.test:
+ * generic/tclCmdMZ.c:
* doc/string.n: Fixed bug in string equal/compare code when using
- -length option. Cleaned up docs a bit more.
-
- * tests/http.test: Unset "data" array before running tests to
- avoid failures due to previous tests.
-
- * doc/string.n:
- * tests/cmdIL.test:
- * tests/cmdMZ.test:
- * tests/error.test:
- * tests/ioCmd.test:
- * tests/lindex.test:
- * tests/linsert.test:
- * tests/lrange.test:
- * tests/lreplace.test:
- * tests/string.test:
- * tests/cmdIL.test:
- * generic/tclUtil.c:
- * generic/tclCmdMZ.c: Replaced "string icompare/iequal" with
- -nocase and -length switches to "string compare/equal". Added a
- -nocase option to "string map". Changed index syntax to allow
- integer or end?-integer? instead of a full expression. This is
- much simpler with safeTcl scripts since it avoids double
- substitution issues.
-
- * doc/Utf.3:
- * generic/tclStubInit.c:
- * generic/tclDecls.h:
+ -length option. Cleaned up docs a bit more.
+
+ * tests/http.test: Unset "data" array before running tests to avoid
+ failures due to previous tests.
+
+ * doc/string.n:
+ * tests/cmdIL.test:
+ * tests/cmdMZ.test:
+ * tests/error.test:
+ * tests/ioCmd.test:
+ * tests/lindex.test:
+ * tests/linsert.test:
+ * tests/lrange.test:
+ * tests/lreplace.test:
+ * tests/string.test:
+ * tests/cmdIL.test:
+ * generic/tclUtil.c:
+ * generic/tclCmdMZ.c: Replaced "string icompare/iequal" with -nocase
+ and -length switches to "string compare/equal". Added a -nocase option
+ to "string map". Changed index syntax to allow integer or
+ end?-integer? instead of a full expression. This is much simpler with
+ safeTcl scripts since it avoids double substitution issues.
+
+ * doc/Utf.3:
+ * generic/tclStubInit.c:
+ * generic/tclDecls.h:
* generic/tclUtf.c:
* generic/tcl.decls: Added Tcl_UtfNcmp and Tcl_UtfNcasecmp.
-1999-05-05 <stanton@scriptics.com>
+1999-05-05 Scott Stanton <stanton@scriptics.com>
* win/makefile.vc: Added encoding directory to install-libraries
target.
-1999-05-03 <stanton@scriptics.com>
-
- * doc/string.n:
- * tests/cmdMZ.test:
- * tests/string.test:
- * generic/tclCmdMZ.c (Tcl_StringObjCmd): Changed "string length"
- to avoid regenerating the string rep of a ByteArray object.
-
- * tests/cmdIL.test:
- * tests/cmdMZ.test:
- * tests/error.test:
+1999-05-03 Scott Stanton <stanton@scriptics.com>
+
+ * doc/string.n:
+ * tests/cmdMZ.test:
+ * tests/string.test:
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd): Changed "string length" to
+ avoid regenerating the string rep of a ByteArray object.
+
+ * tests/cmdIL.test:
+ * tests/cmdMZ.test:
+ * tests/error.test:
* tests/lindex.test:
- * tests/linsert.test:
- * tests/lrange.test:
- * tests/lreplace.test:
- * tests/string.test:
- * generic/tclCmdMZ.c (Tcl_StringObjCmd):
- * generic/tclUtil.c (TclGetIntForIndex): Applied Jeff Hobbs's
- string patch which includes the following changes [Bug: 1845]:
-
- - string compare now takes optional length arg (for strncmp
- behavior)
-
- - added string equal (just a few lines of code blended
- in with string compare)
-
- - added string icompare/iequal for case-insensitive comparisons
-
- - string index's index can now be ?end[+-]?expression
- I made this change in the private TclGetIntForIndex,
- which means that the list commands also benefit, as
- well as string range, et al.
-
- - added [string repeat string count]
- Repeats given string number of times
-
- - added string replace, string equiv to lreplace
- (quasi opposite of string range):
- string replace first last ?string?
- Example of use, replacing end of string with ...
- should the string be more than 16 chars long:
- string replace $string 16 end "..."
- This just returns the string len < 16, so it
- will only affect the long strings.
-
- - added optional first and last args to string to*
- This allows you to just affect certain regions of
- a string with the command (like just capping the
- first letter). I found the original totitle to
- be too draconian to be useful.
-
- - added [string map charMap string]
- where charMap is a {from to from to} list that equates to
- what one might get from [array get]. Each and
- can be multiple chars (or none at all). For Tcl/CGI users,
- this is a MAJOR speed booster.
-
- * generic/tclParse.c (Tcl_ParseCommand): Changed to avoid
- modifying eval'ed strings that are already null terminated.
- [Bug: 1793]
-
- * tests/binary.test:
- * generic/tclBinary.c (DupByteArrayInternalRep): Fixed bug where
- type was not being set in duplicated object. [Bug: 1975, 2047]
-
-1999-04-30 <stanton@scriptics.com>
-
+ * tests/linsert.test:
+ * tests/lrange.test:
+ * tests/lreplace.test:
+ * tests/string.test:
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd):
+ * generic/tclUtil.c (TclGetIntForIndex): Applied Jeff Hobbs's string
+ patch which includes the following changes [Bug 1845]:
+ - string compare now takes optional length arg (for strncmp behavior)
+ - added string equal (just a few lines of code blended in with string
+ compare)
+ - added string icompare/iequal for case-insensitive comparisons
+ - string index's index can now be ?end[+-]?expression
+ I made this change in the private TclGetIntForIndex, which means
+ that the list commands also benefit, as well as string range, et al.
+ - added [string repeat string count]
+ Repeats given string number of times
+ - added string replace, string equiv to lreplace
+ (quasi opposite of string range):
+ string replace first last ?string?
+ Example of use, replacing end of string with ... should the string
+ be more than 16 chars long:
+ string replace $string 16 end "..."
+ This just returns the string len < 16, so it will only affect the
+ long strings.
+ - added optional first and last args to string to*
+ This allows you to just affect certain regions of a string with the
+ command (like just capping the first letter). I found the original
+ totitle to be too draconian to be useful.
+ - added [string map charMap string]
+ where charMap is a {from to from to} list that equates to what one
+ might get from [array get]. Each and can be multiple chars (or none
+ at all). For Tcl/CGI users, this is a MAJOR speed booster.
+
+ * generic/tclParse.c (Tcl_ParseCommand): Changed to avoid modifying
+ eval'ed strings that are already null terminated. [Bug 1793]
+
+ * tests/binary.test:
+ * generic/tclBinary.c (DupByteArrayInternalRep): Fixed bug where type
+ was not being set in duplicated object. [Bug 1975, 2047]
+
+1999-04-30 Scott Stanton <stanton@scriptics.com>
+
* Changed version to 8.1.1.
-
-1999-04-30 <stanton@scriptics.com>
+
+1999-04-30 Scott Stanton <stanton@scriptics.com>
* Merged changes from 8.1.0 branch:
* generic/tclParse.c: Fixed memory leak in CommandComplete.
- * generic/tclPlatDecls.h:
- * generic/tclIntPlatDecls.h:
- * generic/tclIntDecls.h:
- * generic/tclDecls.h:
+ * generic/tclPlatDecls.h:
+ * generic/tclIntPlatDecls.h:
+ * generic/tclIntDecls.h:
+ * generic/tclDecls.h:
* tools/genStubs.tcl: Added 'extern "C" {}' block around the stub
- table pointer declaration so the stub library can be used from
- C++. [Bug: 1934]
+ table pointer declaration so the stub library can be used from C++.
+ [Bug 1934]
* Lots of documentation and other release engineering fixes.
-1999-04-28 <stanton@scriptics.com>
+1999-04-28 Scott Stanton <stanton@scriptics.com>
- * mac/tclMacResource.c:
- * generic/tclListObj.c:
- * generic/tclObj.c:
+ * mac/tclMacResource.c:
+ * generic/tclListObj.c:
+ * generic/tclObj.c:
* generic/tclStringObj.c: Changed to avoid freeing the string
- representation before freeing the internal rep. This helps with
- debugging since the string rep will still be valid when the free
- proc is invoked.
+ representation before freeing the internal rep. This helps with
+ debugging since the string rep will still be valid when the free proc
+ is invoked.
-1999-04-27 <stanton@scriptics.com>
+1999-04-27 Scott Stanton <stanton@scriptics.com>
- * generic/tclLiteral.c (TclHideLiteral): Fixed so hidden literals
- get duplicated to avoid accidental sharing in the global object
- table.
+ * generic/tclLiteral.c (TclHideLiteral): Fixed so hidden literals get
+ duplicated to avoid accidental sharing in the global object table.
-1999-04-23 <stanton@scriptics.com>
+1999-04-23 Scott Stanton <stanton@scriptics.com>
- * generic/tclStubInit.c:
+ * generic/tclStubInit.c:
* tools/genStubs.tcl: Changed to avoid the need for forward
declarations in stub initializers.
-1999-04-23 <stanton@scriptics.com>
+1999-04-23 Scott Stanton <stanton@scriptics.com>
* library/encoding/koi8-r.enc:
* tools/encoding/koi8-r.txt: Added support for the koi8-r Cyrillic
- encoding. [Bug: 1771]
+ encoding. [Bug 1771]
-1999-04-22 <stanton@scriptics.com>
+1999-04-22 Scott Stanton <stanton@scriptics.com>
* win/tclWinFCmd.c:
- * win/tclWin32Dll.c: Changed uses of "try" to "__try", since that
- is the actual keyword. This eliminates the need for some -D flags
- from the makefile.
+ * win/tclWin32Dll.c: Changed uses of "try" to "__try", since that is
+ the actual keyword. This eliminates the need for some -D flags from
+ the makefile.
- * generic/tclPort.h: Added include of tcl.h since it defines
- various Windows macros that are needed before deciding which
- platform porting file to use.
+ * generic/tclPort.h: Added include of tcl.h since it defines various
+ Windows macros that are needed before deciding which platform porting
+ file to use.
* generic/tclEvent.c: lint
- * win/tclWinInit.c (TclpInitPlatform): Added call to TclWinInit
- when building a static library since DllMain will not be invoked.
- This could break old code that explicitly called TclWinInit, but
- should be simpler in the long run.
+ * win/tclWinInit.c (TclpInitPlatform): Added call to TclWinInit when
+ building a static library since DllMain will not be invoked. This
+ could break old code that explicitly called TclWinInit, but should be
+ simpler in the long run.
1999-04-22 Scott Stanton <stanton@scriptics.com>
- * generic/tclInt.h:
- * generic/tclInt.decls:
- * generic/tclCompile.c: Added TclSetByteCodeFromAny that takes a
- hook procedure to invoke after compilation but before the byte
- codes are emitted. This makes it possible to do postprocessing on
- the compiled byte codes before the ByteCode is generated.
+ * generic/tclInt.h:
+ * generic/tclInt.decls:
+ * generic/tclCompile.c: Added TclSetByteCodeFromAny that takes a hook
+ procedure to invoke after compilation but before the byte codes are
+ emitted. This makes it possible to do postprocessing on the compiled
+ byte codes before the ByteCode is generated.
+
+ * generic/tclLiteral.c: Added TclHideLiteral and TclAddLiteralObj to
+ make it possible to create local unshared literal objects.
- * generic/tclLiteral.c: Added TclHideLiteral and TclAddLiteralObj
- to make it possible to create local unshared literal objects.
-
* win/tclWinInit.c:
* unix/tclUnixInit.c: Changed initial search path to match that
found used by tcl_findLibrary.
-1999-04-22 <redman@scriptics.com>
+1999-04-22 Scott Redman <redman@scriptics.com>
* win/tclWinPort.h:
- * win/tclWinSock.c: Added code to use WinSock 2.0 API on NT to
- avoid creating a window to handle sockets. API not available on
- Win95 and needs to be fixed on Win98, until then continue to use
- the older (window-based) scheme on those two OSes.
-
-1999-04-15 <stanton@scriptics.com>
+ * win/tclWinSock.c: Added code to use WinSock 2.0 API on NT to avoid
+ creating a window to handle sockets. API not available on Win95 and
+ needs to be fixed on Win98, until then continue to use the older
+ (window-based) scheme on those two OSes.
+
+1999-04-15 Scott Stanton <stanton@scriptics.com>
* Merged 8.1 back into the main trunk
-1999-04-13 <stanton@scriptics.com>
+1999-04-13 Scott Stanton <stanton@scriptics.com>
* library/encoding/gb2312.enc:
* library/encoding/euc-cn.enc:
* tools/encoding/gb2312.txt:
* tools/encoding/cp950.txt:
* tools/encoding/Makefile: Restored the double byte definition of
- GB2312 and added the EUC-CN encoding. EUC-CN is a variant of
- GB2312 that shifts the characters into bytes with the high bit set
- and includes ASCII as a subset. [Bug: 632]
+ GB2312 and added the EUC-CN encoding. EUC-CN is a variant of GB2312
+ that shifts the characters into bytes with the high bit set and
+ includes ASCII as a subset. [Bug 632]
-1999-04-13 <redman@scriptics.com>
+1999-04-13 Scott Redman <redman@scriptics.com>
- * win/tclWinSock.c: Apply patch to allow write access to a socket
- if FD_WRITE is sent but FD_CONNECT is not. Some strange problem
- with either Win32 or a socket driver. [Bug: 1664 1776]
+ * win/tclWinSock.c: Apply patch to allow write access to a socket if
+ FD_WRITE is sent but FD_CONNECT is not. Some strange problem with
+ either Win32 or a socket driver. [Bug 1664 1776]
-1999-04-09 <redman@scriptics.com>
+1999-04-09 Scott Redman <redman@scriptics.com>
- * unix/tclUnixNotfy.c: Fixed notifier deadlock situation when the
- pipe used to talk back notifier thread is filled with data. When
- calling the write() function to feed data down that pipe, unlock
- the notifierMutex to allow the notifier to wake up again. Found
- as a result of the focus.test for Tk hanging. [Bug: 1700]
+ * unix/tclUnixNotfy.c: Fixed notifier deadlock situation when the pipe
+ used to talk back notifier thread is filled with data. When calling
+ the write() function to feed data down that pipe, unlock the
+ notifierMutex to allow the notifier to wake up again. Found as a
+ result of the focus.test for Tk hanging. [Bug 1700]
-1999-04-06 <stanton@scriptics.com>
+1999-04-06 Scott Stanton <stanton@scriptics.com>
* tests/unixNotfy.test: Fixed hang in tests when built with thread
- support.
+ support.
- * tests/httpold.test: Fixed broken test that didn't wait long
- enough for events to arrive.
+ * tests/httpold.test: Fixed broken test that didn't wait long enough
+ for events to arrive.
* tests/unixInit.test: Fixed race condition in test.
-
- * tests/unixInit.test:
+
+ * tests/unixInit.test:
* tests/fileName.test: Minor test nits.
* unix/tclUnixInit.c (TclpSetInitialEncodings): Fixed bad initial
encoding string.
-1999-04-06 <surles@scriptics.com>
+1999-04-06 Bryan Surles <surles@scriptics.com>
- * generic/tclVar.c:
- * generic/tclEnv.c: Moved the "array set" C level code into a
- common routine (TclArraySet). The TclSetupEnv routine now uses
- this API to create an env array w/ no elements.
+ * generic/tclVar.c:
+ * generic/tclEnv.c: Moved the "array set" C level code into a common
+ routine (TclArraySet). The TclSetupEnv routine now uses this API to
+ create an env array w/ no elements.
* generic/tclEnv.c:
* generic/tclWinInit.h:
* generic/tclUnixInit.h:
- * generic/tclInt.h: Made the Env module I18N compliant. Changed the
+ * generic/tclInt.h: Made the Env module I18N compliant. Changed the
FindVariable routine to TclpFindVariable, that now does a case
- insensitive string comparison on Windows, and not on UNIX. [Bug:
- 1299, 1500]
+ insensitive string comparison on Windows, and not on UNIX. [Bug 1299,
+ 1500]
-1999-04-05 <stanton@scriptics.com>
+1999-04-05 Scott Stanton <stanton@scriptics.com>
* tests/io.test: Minor test cleanup.
- * generic/tclEncoding.c (Tcl_CreateEncoding): Minor lint to make
- it easier to compile on Digital-unix. [Bug: 1659]
+ * generic/tclEncoding.c (Tcl_CreateEncoding): Minor lint to make it
+ easier to compile on Digital-unix. [Bug 1659]
- * unix/configure.in:
+ * unix/configure.in:
* unix/tclUnixPort.h: Applied patch for OS/390 to handle lack of
- sys/param.h. [Bug: 1725]
+ sys/param.h. [Bug 1725]
+
+ * unix/configure.in: Fixed BSD/OS 4.* configuration to support shared
+ libraries properly. [Bug 1730]
- * unix/configure.in: Fixed BSD/OS 4.* configuration to support
- shared libraries properly. [Bug: 1730]
-
-1999-04-05 <redman@scriptics.com>
+1999-04-05 Scott Redman <redman@scriptics.com>
- * win/tclWinDde.c: decrease timeout value for DDE calls to 30k
- [Bug: 1639]
+ * win/tclWinDde.c: decrease timeout value for DDE calls to 30k. [Bug
+ 1639]
* generic/tcl.decls:
* generic/tcl.h:
@@ -1792,109 +1748,106 @@
* generic/tclIntDecls.h:
* generic/tclStubInit.c:
* generic/tclUtil.c: Added more functions to the Tcl stubs table,
- including all Tcl_ functions not already in it (except Cmd
- functions) and Tcl_GetCwd() and Tcl_Chdir() (new functions).
-
+ including all Tcl_ functions not already in it (except Cmd functions)
+ and Tcl_GetCwd() and Tcl_Chdir() (new functions).
+
* tests/safe.test:
* doc/safe.n:
* generic/tclBasic.c:
- * library/safe.tcl: The encoding command is not safe as-is, so
- create a safe alias to mask out the "encoding system <name>" but
- allow all other uses including "encoding system". Added test cases
- and updated the man page for Safe Tcl.
-
-1999-04-05 <stanton@scriptics.com>
-
- * tests/winTime.test:
- * win/tclWinTime.c: Fixed crash in clock command that occurred
- when manipulating negative time values in timezones east of
- GMT. [Bug: 1142, 1458]
-
- * tests/platform.test:
+ * library/safe.tcl: The encoding command is not safe as-is, so create
+ a safe alias to mask out the "encoding system <name>" but allow all
+ other uses including "encoding system". Added test cases and updated
+ the man page for Safe Tcl.
+
+1999-04-05 Scott Stanton <stanton@scriptics.com>
+
+ * tests/winTime.test:
+ * win/tclWinTime.c: Fixed crash in clock command that occurred when
+ manipulating negative time values in timezones east of GMT. [Bug
+ 1142, 1458]
+
+ * tests/platform.test:
* tests/fileName.test: Fixed broken tests.
-
+
* generic/tclFileName.c: Moved global regexps into thread local
storage.
- * tests/socket.test: Changed so tests don't reuse sockets,
- since Windows is slow to release sockets.
+ * tests/socket.test: Changed so tests don't reuse sockets, since
+ Windows is slow to release sockets.
- * win/tclWinConsole.c:
- * win/tclWinPipe.c:
- * win/tclWinSerial.c: Fixed race condition where background
- threads were terminated while they still held a lock in the
- notifier.
+ * win/tclWinConsole.c:
+ * win/tclWinPipe.c:
+ * win/tclWinSerial.c: Fixed race condition where background threads
+ were terminated while they still held a lock in the notifier.
-1999-04-02 <stanton@scriptics.com>
+1999-04-02 Scott Stanton <stanton@scriptics.com>
* tests/http.test: Fixed bad test initialization code.
* generic/tclThreadTest.c (ThreadExitProc): Fixed bug where static
- memory was being returned instead of a dynamically allocated
- result in error cases.
+ memory was being returned instead of a dynamically allocated result in
+ error cases.
-1999-04-02 <redman@scriptics.com>
+1999-04-02 Scott Redman <redman@scriptics.com>
* doc/dde.n:
* tools/tcl.wse.in:
* win/makefile.vc:
* win/pkgIndex.tcl:
- * win/tclWinDde.c: Add new DDE package, code removed from Tk now
- separated into its own package. Changed DDE-based send code into
- "dde eval" command. Can be loaded into tclsh (not just wish).
- Windows only.
-
-1999-04-02 <stanton@scriptics.com>
-
- * tests/expr.test:
- * tests/for-old.test:
- * tests/for.test:
- * tests/foreach.test:
- * tests/format.test:
- * tests/httpold.test:
- * tests/if.test:
- * tests/init.test:
- * tests/interp.test:
- * tests/while.test: Added some tests for known bugs (marked with
+ * win/tclWinDde.c: Add new DDE package, code removed from Tk now
+ separated into its own package. Changed DDE-based send code into "dde
+ eval" command. Can be loaded into tclsh (not just wish). Windows only.
+
+1999-04-02 Scott Stanton <stanton@scriptics.com>
+
+ * tests/expr.test:
+ * tests/for-old.test:
+ * tests/for.test:
+ * tests/foreach.test:
+ * tests/format.test:
+ * tests/httpold.test:
+ * tests/if.test:
+ * tests/init.test:
+ * tests/interp.test:
+ * tests/while.test: Added some tests for known bugs (marked with
knownBug constraint), and cleaned up a few bad tests.
- * generic/regc_locale.c:
- * generic/regcustom.h:
- * generic/tcl.decls:
- * generic/tclCmdIL.c:
- * generic/tclCmdMZ.c:
- * generic/tclInt.h:
- * generic/tclRegexp.c:
- * generic/tclScan.c:
+ * generic/regc_locale.c:
+ * generic/regcustom.h:
+ * generic/tcl.decls:
+ * generic/tclCmdIL.c:
+ * generic/tclCmdMZ.c:
+ * generic/tclInt.h:
+ * generic/tclRegexp.c:
+ * generic/tclScan.c:
* generic/tclTest.c:
- * generic/tclUtf.c:
- * win/tclWinFCmd.c:
- * win/tclWinFile.c: Made various Unicode utility functions
- public. The following functions were made public and added to the
- stubs table:
+ * generic/tclUtf.c:
+ * win/tclWinFCmd.c:
+ * win/tclWinFile.c: Made various Unicode utility functions public. The
+ following functions were made public and added to the stubs table:
Tcl_UtfToUniCharDString, Tcl_UniCharToUtfDString,
Tcl_UniCharLen, Tcl_UniCharNcmp, Tcl_UniCharIsAlnum,
Tcl_UniCharIsAlpha, Tcl_UniCharIsDigit, Tcl_UniCharIsLower,
Tcl_UniCharIsSpace, Tcl_UniCharIsUpper, Tcl_UniCharIsWordChar
-1999-04-01 <stanton@scriptics.com>
+1999-04-01 Scott Stanton <stanton@scriptics.com>
- * tests/registry.test:
- * win/tclWinReg.c: Internationalized the registry code. It now
- uses Unicode interfaces on NT. [Bug: 1197]
+ * tests/registry.test:
+ * win/tclWinReg.c: Internationalized the registry code. It now uses
+ Unicode interfaces on NT. [Bug 1197]
- * tests/parse.test:
+ * tests/parse.test:
* generic/tclParse.c: Fixed crash due to multiple frees in parser
- during error cleanup when parsing commands with more tokens than
- will fit in the static area of the parse structure. [Bug: 1681]
+ during error cleanup when parsing commands with more tokens than will
+ fit in the static area of the parse structure. [Bug 1681]
* generic/tclInt.h: Removed duplicate declarations.
- * generic/tclInt.decls:
- * generic/tcl.decls: Added Tcl_WinUtfToTChar and Tcl_WinTCharToUtf
- to the tclPlat table.
+ * generic/tclInt.decls:
+ * generic/tcl.decls: Added Tcl_WinUtfToTChar and Tcl_WinTCharToUtf to
+ the tclPlat table.
-1999-04-01 <redman@scriptics.com>
+1999-04-01 Scott Redman <redman@scriptics.com>
* generic/tcl.decls:
* generic/tcl.h:
@@ -1904,44 +1857,44 @@
* tools/genStubs.tcl:
* unix/Makefile.in:
* win/makefile.vc: Applied patch from Jan Nijtmans to fix Ultrix
- multiple symbol definition problem. Now, even Tcl includes a copy
- of the Tcl stub library. Also fixed TCL_MEM_DEBUG mode (for Tk).
+ multiple symbol definition problem. Now, even Tcl includes a copy of
+ the Tcl stub library. Also fixed TCL_MEM_DEBUG mode (for Tk).
-1999-03-31 <redman@scriptics.com>
+1999-03-31 Scott Redman <redman@scriptics.com>
- * win/tclWinConsole.c: WinNT has a bug when reading a single
- character from the console. Rewrote the code for the console to
- read an entire line at a time using the reader thread.
+ * win/tclWinConsole.c: WinNT has a bug when reading a single character
+ from the console. Rewrote the code for the console to read an entire
+ line at a time using the reader thread.
-1999-03-30 <stanton@scriptics.com>
+1999-03-30 Scott Stanton <stanton@scriptics.com>
- * unix/Makefile.in: Removed trailing backslash that broke the
- "depend" target.
+ * unix/Makefile.in: Removed trailing backslash that broke the "depend"
+ target.
* unix/tclUnixInit.c (TclpSetInitialEncodings): Changed to avoid
- calling setlocale(). We now look directly at env(LANG) and
- env(LC_CTYPE) instead. [Bug: 1636]
+ calling setlocale(). We now look directly at env(LANG) and
+ env(LC_CTYPE) instead. [Bug 1636]
- * generic/tclFileName.c:
- * generic/tclDecls.h:
+ * generic/tclFileName.c:
+ * generic/tclDecls.h:
* generic/tcl.decls: Removed CONST from Tcl_JoinPath and
- Tcl_TranslateFileName because it changes the signature of
- Tcl_JoinPath in an incompatible manner.
+ Tcl_TranslateFileName because it changes the signature of Tcl_JoinPath
+ in an incompatible manner.
- * generic/tclInt.h:
- * generic/tclLoad.c (TclFinalizeLoad):
+ * generic/tclInt.h:
+ * generic/tclLoad.c (TclFinalizeLoad):
* generic/tclEvent.c (Tcl_Finalize): Defer unloading of loadable
- modules until all exit handlers have been invoked.
- [Bug: 998, 1273, 1573, 1593]
+ modules until all exit handlers have been invoked. [Bug 998, 1273,
+ 1573, 1593]
-1999-03-29 <stanton@scriptics.com>
+1999-03-29 Scott Stanton <stanton@scriptics.com>
- * generic/tclFileName.c:
- * generic/tclDecls.h:
+ * generic/tclFileName.c:
+ * generic/tclDecls.h:
* generic/tcl.decls: Added CONST to Tcl_JoinPath and
Tcl_TranslateFileName.
-1999-03-29 <redman@scriptics.com>
+1999-03-29 Scott Redman <redman@scriptics.com>
* tools/genStubs.tcl:
* unix/configure.in:
@@ -1952,207 +1905,203 @@
* generic/tclDecls.h:
* generic/tclIntDecls.h:
* generic/tclPlatDecls.h:
- * generic/tclIntPlatDecls.h: Removed the stub functions and
- changed the stub macros to just use the name without params. Pass
- &tclStubs into the interp (don't use tclStubsPtr because of
- collisions with the stubs on Solaris).
-
-1999-03-27 <redman@scriptics.com>
+ * generic/tclIntPlatDecls.h: Removed the stub functions and changed
+ the stub macros to just use the name without params. Pass &tclStubs
+ into the interp (don't use tclStubsPtr because of collisions with the
+ stubs on Solaris).
- * win/makefile.bc: Removed makefile for Borland compiler, no
- longer supported.
+1999-03-27 Scott Redman <redman@scriptics.com>
-1999-03-26 <redman@scriptics.com>
+ * win/makefile.bc: Removed makefile for Borland compiler, no longer
+ supported.
+
+1999-03-26 Scott Redman <redman@scriptics.com>
* win/tclWinSerial.c:
* win/tclWinConsole.c:
- * win/tclWinPipe.c: Don't close the Win32 handle for a channel if
- it's a stdio handle (GetStdHandle()) during shutdown of a thread
- to prevent it from destroying the stdio of other threads.
+ * win/tclWinPipe.c: Don't close the Win32 handle for a channel if it's
+ a stdio handle (GetStdHandle()) during shutdown of a thread to prevent
+ it from destroying the stdio of other threads.
+
+1999-03-26 Suresh Ankolekar <suresh@scriptics.com>
-1999-03-26 <suresh@scriptics.com>
+ * unix/configure.in: --nameble-shared is now the default and build Tcl
+ as a shared library; specify --disable-shared to build a static Tcl
+ library and shell.
- * unix/configure.in
- --nameble-shared is now the default and build Tcl as a shared
- library; specify --disable-shared to build a static Tcl library
- and shell.
+1999-03-25 Scott Stanton <stanton@scriptics.com>
-1999-03-25 <stanton@scriptics.com>
+ * tests/interp.test:
+ * generic/tclInterp.c (AliasObjCmd): Changed so aliases are invoked at
+ current scope in the target interpreter instead of at the global
+ scope. This was an incompatibility introduced in 8.1 that is being
+ removed. [Bug 1153, 1556]
- * tests/interp.test:
- * generic/tclInterp.c (AliasObjCmd): Changed so aliases are
- invoked at current scope in the target interpreter instead of at
- the global scope. This was an incompatibility introduced in 8.1
- that is being removed. [Bug: 1153, 1556]
-
* library/encoding/big5.enc:
* library/encoding/gb2312.enc:
* tools/encoding/big5.enc:
- * tools/encoding/gb2312.enc: Added ASCII to big5 and gb2312
- encodings. [Bug: 632]
-
+ * tools/encoding/gb2312.enc: Added ASCII to big5 and gb2312 encodings.
+ [Bug 632]
+
* generic/tclPkg.c (Tcl_PkgRequireEx): Fixed broken clientData
initialization in package code.
- * unix/Makefile.in (dist): Added tcl.decls and tclInt.decls to
- source distribution. [Bug: 1571]
+ * unix/Makefile.in (dist): Added tcl.decls and tclInt.decls to source
+ distribution. [Bug 1571]
* doc/Thread.3: Updated documentation of Tcl_MutexLock to indicate
- that the recursive locking behavior is undefined. On Windows, it
- does not block, on Unix it deadlocks. [Bug: 1275]
+ that the recursive locking behavior is undefined. On Windows, it does
+ not block, on Unix it deadlocks. [Bug 1275]
-1999-03-24 <stanton@scriptics.com>
+1999-03-24 Scott Stanton <stanton@scriptics.com>
- * tests/execute.test:
+ * tests/execute.test:
* generic/tclExecute.c (TclExecuteByteCode): Fixed expression code
- that incorrectly returned floating point values for integers if
- the internal rep happened to be a double. Now we check to see if
- the object has a string rep that looks like an integer before
- using the double internal rep. [Bug: 1516]
+ that incorrectly returned floating point values for integers if the
+ internal rep happened to be a double. Now we check to see if the
+ object has a string rep that looks like an integer before using the
+ double internal rep. [Bug 1516]
-1999-03-24 <redman@scriptics.com>
+1999-03-24 Scott Redman <redman@scriptics.com>
* generic/tclAlloc.c:
* generic/tclEncoding.c:
* generic/tclProc.c:
* unix/tclUnixTime.c:
- * win/tclWinSerial.c: Fixed compilation warnings/errors for VC++
- 5.0 and 6.0 and HP-UX native compiler without -Aa or -Ae.
- [Bug: 1323 1518 1324 1583 1585 1586]
+ * win/tclWinSerial.c: Fixed compilation warnings/errors for VC++ 5.0
+ and 6.0 and HP-UX native compiler without -Aa or -Ae. [Bug 1323 1518
+ 1324 1583 1585 1586]
- * win/tclWinSock.c: Make sockets thread-safe on Windows. The
- current implementation uses windows to handle events on the
- socket, one for each thread (thread local storage). Previously,
- there was only one window shared between threads, which didn't
- work. [Bug: 1326]
+ * win/tclWinSock.c: Make sockets thread-safe on Windows. The current
+ implementation uses windows to handle events on the socket, one for
+ each thread (thread local storage). Previously, there was only one
+ window shared between threads, which didn't work. [Bug 1326]
-1999-03-23 <stanton@scriptics.com>
+1999-03-23 Scott Stanton <stanton@scriptics.com>
- * tools/tcl.wse: Fixed file association to look in the right place
- for the wish icon. [Bug: 1544]
+ * tools/tcl.wse: Fixed file association to look in the right place for
+ the wish icon. [Bug 1544]
- * tests/winNotify.test:
- * tests/ioCmd.test:
+ * tests/winNotify.test:
+ * tests/ioCmd.test:
* tests/event.test: Changed to use new style conditionals.
* tests/encoding.test: Fixed nonportable test.
- * unix/dltest/configure.in:
- * unix/dltest/Makefile.in: Added missing DBGX macros. [Bug: 1564]
+ * unix/dltest/configure.in:
+ * unix/dltest/Makefile.in: Added missing DBGX macros. [Bug 1564]
- * tests/winNotify.test:
- * mac/tclMacNotify.c:
- * win/tclWinNotify.c:
+ * tests/winNotify.test:
+ * mac/tclMacNotify.c:
+ * win/tclWinNotify.c:
* unix/tclUnixNotfy.c:
- * generic/tclNotify.c: Added a new Tcl_ServiceModeHook interface
- that is invoked whenever the service mode changes. This is needed
- to allow the Windows notifier to create a communication window the
- first time Tcl is about to enter an external modal event loop
- instead of at startup time. This will avoid the various problems
- that people have been seeing where the system hangs when tclsh
- is running outside of the event loop. [Bug: 783]
-
- * generic/tclInt.h:
+ * generic/tclNotify.c: Added a new Tcl_ServiceModeHook interface that
+ is invoked whenever the service mode changes. This is needed to allow
+ the Windows notifier to create a communication window the first time
+ Tcl is about to enter an external modal event loop instead of at
+ startup time. This will avoid the various problems that people have
+ been seeing where the system hangs when tclsh is running outside of
+ the event loop. [Bug 783]
+
+ * generic/tclInt.h:
* generic/tcl.decls: Renamed TclpAlertNotifier back to
- Tcl_AlertNotifier since it is part of the public notifier driver
- API.
+ Tcl_AlertNotifier since it is part of the public notifier driver API.
+
+1999-03-23 Scott Redman <redman@scriptics.com>
-1999-03-23 <redman@scriptics.com>
+ * win/tclWinSerial.c: Fixed problem with fileevent on the serial port
+ and nonblocking mode. Gets no longer hangs, fileevents fire whenever
+ there is any character data on the port.
- * win/tclWinSerial.c: Fixed problem with fileevent on the serial
- port and nonblocking mode. Gets no longer hangs, fileevents fire
- whenever there is any character data on the port.
-
* tests/winConsole.test:
- * win/tclWinConsole.c: Fixed problem with fileevents and gets from
- a console stdin. Previously, fileevents were firing before an
- entire line was available for reading, which meant that when you
- did a gets or read, it blocked (even in nonblocking mode). Now, it
- should work the same as Unix: fileevents fire when an entire line
- is ready, and gets and read do not block in non-blocking mode.
- Added an interactive test case to check for this.
+ * win/tclWinConsole.c: Fixed problem with fileevents and gets from a
+ console stdin. Previously, fileevents were firing before an entire
+ line was available for reading, which meant that when you did a gets
+ or read, it blocked (even in nonblocking mode). Now, it should work
+ the same as Unix: fileevents fire when an entire line is ready, and
+ gets and read do not block in non-blocking mode. Added an interactive
+ test case to check for this.
-1999-03-22 <stanton@scriptics.com>
+1999-03-22 Scott Stanton <stanton@scriptics.com>
- * tests/reg.test:
+ * tests/reg.test:
* generic/regc_color.c: Applied regexp bug fix from Henry Spencer.
-1999-03-19 <redman@scriptics.com>
+1999-03-19 Scott Redman <redman@scriptics.com>
- * generic/tclCmdIL.c: Fixed the initialization of an array so that
- the Sun 5.0 C compiler wouldn't complain.
+ * generic/tclCmdIL.c: Fixed the initialization of an array so that the
+ Sun 5.0 C compiler wouldn't complain.
- * unix/configure.in: Added support for --enable-64bit. For now,
- this is only supported on Solaris 7 64bit (SunOS 5.7) using the Sun
+ * unix/configure.in: Added support for --enable-64bit. For now, this
+ is only supported on Solaris 7 64bit (SunOS 5.7) using the Sun
compiler (not gcc).
-
-1999-03-18 <stanton@scriptics.com>
- * win/tclWinChan.c (TclpOpenFileChannel, Tcl_MakeFileChannel):
- Changed to only test for console or comm handles when the type is
- FILE_TYPE_CHAR to avoid useless tests on simple files. Also
- reordered tests so consoles are tested first as this is more
- common.
+1999-03-18 Scott Stanton <stanton@scriptics.com>
+
+ * win/tclWinChan.c (TclpOpenFileChannel, Tcl_MakeFileChannel): Changed
+ to only test for console or comm handles when the type is
+ FILE_TYPE_CHAR to avoid useless tests on simple files. Also reordered
+ tests so consoles are tested first as this is more common.
* win/makefile.vc: Regularized usage of mkd and rmd and rm.
- * library/encoding/shiftjis.enc:
+ * library/encoding/shiftjis.enc:
* tools/encoding/shiftjis.txt: Missing/incorrect characters in
- shift-jis table. [Bug: 1008, 1526]
+ shift-jis table. [Bug 1008, 1526]
* generic/tclInt.decls:
* generic/tcl.decls: Eliminated use of "string" and "list" from
- argument lists to avoid conflicts with C++ STL. [Bug: 1181]
+ argument lists to avoid conflicts with C++ STL. [Bug 1181]
* win/tclWinFile.c (TclpMatchFiles): Changed to ignore the
- FS_CASE_IS_PRESERVED bit and always return exactly what we get
- from the system.
+ FS_CASE_IS_PRESERVED bit and always return exactly what we get from
+ the system.
-1999-03-17 <stanton@GASPODE>
+1999-03-17 Scott Stanton <stanton@GASPODE>
- * win/README.binary:
- * win/README:
- * unix/configure.in:
- * generic/tcl.h:
+ * win/README.binary:
+ * win/README:
+ * unix/configure.in:
+ * generic/tcl.h:
* README: Updated version to 8.1b3.
-1999-03-14 <stanton@GASPODE>
+1999-03-14 Scott Stanton <stanton@GASPODE>
- * win/tclWinConsole.c:
- * win/tclWinPipe.c:
+ * win/tclWinConsole.c:
+ * win/tclWinPipe.c:
* win/tclWinSerial.c: Changed so channel drivers wait for the
reader/writer threads to exit before returning during a close
- operation. This ensures that the main thread is the last thread
- to exit, so the process return value is set properly.
-
- * generic/tclIntDecls.h:
- * generic/tclIntPlatDecls.h:
- * generic/tclIntPlatStubs.c:
- * generic/tclIntStubs.c:
- * generic/tclPlatDecls.h:
- * generic/tclPlatStubs.c:
- * generic/tclStubInit.c:
+ operation. This ensures that the main thread is the last thread to
+ exit, so the process return value is set properly.
+
+ * generic/tclIntDecls.h:
+ * generic/tclIntPlatDecls.h:
+ * generic/tclIntPlatStubs.c:
+ * generic/tclIntStubs.c:
+ * generic/tclPlatDecls.h:
+ * generic/tclPlatStubs.c:
+ * generic/tclStubInit.c:
* generic/tclStubs.c: Fixed bad eol characters.
-
- * generic/tclInt.decls: Changed "const" to "CONST" in
- declarations for better portability.
+
+ * generic/tclInt.decls: Changed "const" to "CONST" in declarations for
+ better portability.
* generic/tcl.decls: Renamed panic and panicVA to Tcl_Panic and
Tcl_PanicVA in the stub files.
- * generic/tclInterp.c (Tcl_MakeSafe): Remove tcl_platform(user)
- from safe interps.
+ * generic/tclInterp.c (Tcl_MakeSafe): Remove tcl_platform(user) from
+ safe interps.
-1999-03-11 <stanton@GASPODE>
+1999-03-11 Scott Stanton <stanton@GASPODE>
* unix/Makefile.in:
* unix/configure.in: Include compat files in the stub library in
- addition to the main library. Compat files are now built for
- dynamic use in all cases.
-
+ addition to the main library. Compat files are now built for dynamic
+ use in all cases.
+
* generic/tcl.h: Changed magic number so it doesn't match the plus
patch, at Jan's request.
-
+
* unix/tclConfig.sh.in:
* unix/dltest/Makefile.in:
* unix/dltest/configure.in:
@@ -2161,65 +2110,62 @@
* unix/dltest/pkgc.c:
* unix/dltest/pkgd.c:
* unix/dltest/pkge.c:
- * unix/dltest/pkgf.c: Changed package tests to build against the
- stubs library.
+ * unix/dltest/pkgf.c: Changed package tests to build against the stubs
+ library.
-1999-03-10 <stanton@GASPODE>
+1999-03-10 Scott Stanton <stanton@GASPODE>
- * generic/tcl.h:
- * generic/tcl.decls: Changed Tcl_ReleaseType from an enum to
- macros so it can be used in .rc files.
- Added Tcl_GetString.
+ * generic/tcl.h:
+ * generic/tcl.decls: Changed Tcl_ReleaseType from an enum to macros so
+ it can be used in .rc files. Added Tcl_GetString.
* mac/tclMacNotify.c:
* generic/tclNotify.c:
- * generic/tclInt.h:
- * win/tclWinNotify.c:
+ * generic/tclInt.h:
+ * win/tclWinNotify.c:
* generic/tcl.h: Renamed Tcl_AlertNotifier to TclpAlertNotifier.
- * generic/tclInt.decls: Added TclWinAddProcess to make it possible
- for expect to use Tcl_WaitForPid(). This patch is from Gordon
- Chaffee.
+ * generic/tclInt.decls: Added TclWinAddProcess to make it possible for
+ expect to use Tcl_WaitForPid(). This patch is from Gordon Chaffee.
- * mac/tclMacPort.h:
- * win/tclWinInit.c:
- * unix/tclUnixPort.h:
- * generic/tclAsync.c: Added TclpAsyncMark to fix bug in async
- handling on Windows where async events don't wake up the event
- loop. This patch comes from Gordon Chaffee.
+ * mac/tclMacPort.h:
+ * win/tclWinInit.c:
+ * unix/tclUnixPort.h:
+ * generic/tclAsync.c: Added TclpAsyncMark to fix bug in async handling
+ on Windows where async events don't wake up the event loop. This patch
+ comes from Gordon Chaffee.
* generic/tcl.decls: Fixed declarations of reserved slots.
-
-1999-03-10 <redman@scriptic.com>
+
+1999-03-10 Scott Redman <redman@scriptic.com>
* generic/tclCompile.h: Ensure that the ByteCode struct is binary
compatible with the version in 8.0.6.
* generic/tcl.h:
- * generic/tclBasic.c: Add Tcl_GetVersion() function to the public
- C API to allow programs to check the version number of the Tcl
- library at runtime. Also added an enum to clarify the release
- level (alpha, beta, final).
+ * generic/tclBasic.c: Add Tcl_GetVersion() function to the public C
+ API to allow programs to check the version number of the Tcl library
+ at runtime. Also added an enum to clarify the release level (alpha,
+ beta, final).
-1999-03-09 <stanton@GASPODE>
+1999-03-09 Scott Stanton <stanton@GASPODE>
* Integrated changes from Tcl 8.0 including:
stubs mechanism
configure patches from Jan Nijtmans
rename of panic to Tcl_Panic
-
-1999-03-08 <lfb@scriptics.com>
- * win/tclWin32Dll.c: Removed Dll instance from thread-local
- storage.
+1999-03-08 Lee Bernhard <lfb@scriptics.com>
+
+ * win/tclWin32Dll.c: Removed Dll instance from thread-local storage.
-1999-03-08 <stanton@GASPODE>
-
- * generic/tcl.h: Moved Tcl_Mutex, etc. macros above the inclusion
- of tclDecls.h to avoid macro conflicts.
+1999-03-08 Scott Stanton <stanton@GASPODE>
+
+ * generic/tcl.h: Moved Tcl_Mutex, etc. macros above the inclusion of
+ tclDecls.h to avoid macro conflicts.
* generic/tclInt.h:
- * generic/regc_color.c:
+ * generic/regc_color.c:
* generic/regcomp.c:
* generic/tclCmdIL.c:
* generic/tclCmdAH.c:
@@ -2228,20 +2174,20 @@
* generic/tclStringObj.c:
* unix/tclUnixNotfy.c: Cleaned up various compiler warnings,
eliminated UCHAR bugs.
-
+
* unix/tclUnixNotfy.c:
* unix/tclUnixThrd.c:
* generic/tclThreadTest.c:
* mac/tclMacThrd.c: Changed TclpCondition*() to Tcl_Condition*().
-
+
* INTEGRATED PATCHES FROM 8.0.6:
* generic/tcl.decls:
* generic/tcl.h:
- * generic/tclBasic.c:
+ * generic/tclBasic.c:
* generic/tclDecls.h:
* generic/tclInt.decls:
- * generic/tclInt.h:
+ * generic/tclInt.h:
* generic/tclIntDecls.h:
* generic/tclIntPlatDecls.h:
* generic/tclIntPlatStubs.c:
@@ -2255,199 +2201,194 @@
* unix/configure.in:
* unix/Makefile.in:
* unix/tclConfig.sh.in:
- * win/makefile.vc:
- * win/tclWinPort.h: Added Tcl stubs implementation. There are
- now two new macros USE_TCL_STUBS and USE_TCL_STUB_PROCS that
- enable use of stubs and disable stub macros respectively. All of
- the public and private function declarations from tcl.h and
- tclInt.h have moved into the *.decls files and the *Stubs.c and
- *Decls.h files are generated using the genStubs.tcl script.
+ * win/makefile.vc:
+ * win/tclWinPort.h: Added Tcl stubs implementation. There are now two
+ new macros USE_TCL_STUBS and USE_TCL_STUB_PROCS that enable use of
+ stubs and disable stub macros respectively. All of the public and
+ private function declarations from tcl.h and tclInt.h have moved into
+ the *.decls files and the *Stubs.c and *Decls.h files are generated
+ using the genStubs.tcl script.
* unix/Makefile.in:
- * unix/configure.in:
+ * unix/configure.in:
* unix/ldAix: Enhanced AIX shared library support.
* win/tclWinSock.c: Removed a bunch of extraneous PASCAL FAR
attributes from internal functions.
- * win/tclWinReg.c: Changed registry package to use stubs mechanism
- so it no longer depends on the specific version of Tcl.
+ * win/tclWinReg.c: Changed registry package to use stubs mechanism so
+ it no longer depends on the specific version of Tcl.
- * doc/AddErrInfo.3:
- * doc/Eval.3:
- * doc/PkgRequire.3:
- * doc/SetResult.3:
- * doc/StringObj.3:
+ * doc/AddErrInfo.3:
+ * doc/Eval.3:
+ * doc/PkgRequire.3:
+ * doc/SetResult.3:
+ * doc/StringObj.3:
* generic/tcl.h:
- * generic/tclBasic.c:
+ * generic/tclBasic.c:
* generic/tclPanic.c:
* generic/tclStringObj.c:
* generic/tclUtil.c:
- * unix/mkLinks: Added va_list versions of all VARARGS
- functions so they can be invoked from the stub functions.
+ * unix/mkLinks: Added va_list versions of all VARARGS functions so
+ they can be invoked from the stub functions.
- * doc/package.n:
- * doc/PkgRequire.3:
+ * doc/package.n:
+ * doc/PkgRequire.3:
* generic/tclPkg.c: Added Tcl_PkgProvideEx, Tcl_RequireEx,
- Tcl_PresentEx, and Tcl_PkgPresent. Added "package present"
- command.
+ Tcl_PresentEx, and Tcl_PkgPresent. Added "package present" command.
- * generic/tclFileName.c:
- * mac/tclMacFile.c:
- * mac/tclMacShLib.exp:
- * unix/tclUnixFile.c:
- * win/tclWinFile.c: Changed so TclGetUserHome is defined on
- all platforms, even though it is currently a noop on mac and
- windows, and renamed it to TclpGetUserHome.
+ * generic/tclFileName.c:
+ * mac/tclMacFile.c:
+ * mac/tclMacShLib.exp:
+ * unix/tclUnixFile.c:
+ * win/tclWinFile.c: Changed so TclGetUserHome is defined on all
+ platforms, even though it is currently a noop on mac and windows, and
+ renamed it to TclpGetUserHome.
* generic/tclPanic.c:
* generic/panic.c: Renamed panic to Tcl_Panic.
-
-1999-02-25 <redman@scriptics.com>
+
+1999-02-25 Scott Redman <redman@scriptics.com>
* win/makefile.vc: Added tclWinConsole.c and tclWinSerial.c
-
- * win/tclWinConsole.c: New code to properly deal with fileevents
- and nonblocking mode on consoles.
-
- * win/tclWinSerial.c: New code to properly deal with fileevents
- and nonblocking mode on serial ports.
-
- * win/tclWinPipe.c:
+
+ * win/tclWinConsole.c: New code to properly deal with fileevents and
+ nonblocking mode on consoles.
+
+ * win/tclWinSerial.c: New code to properly deal with fileevents and
+ nonblocking mode on serial ports.
+
+ * win/tclWinPipe.c:
* win/tclWinPort.h: Exported functions to allow creation of pipe
channels from tclWinChan.c
* win/tclWinChan.c: Check the type of a channel, including for the
- standard (stdin/stdout/stderr), and use the correct channel type
- to create the channel (file, serial, console, or pipe).
+ standard (stdin/stdout/stderr), and use the correct channel type to
+ create the channel (file, serial, console, or pipe).
-1999-02-11 <stanton@GASPODE>
+1999-02-11 Scott Stanton <stanton@GASPODE>
- * README:
- * generic/tcl.h:
- * win/README.binary:
- * win/README:
- * unix/configure.in:
+ * README:
+ * generic/tcl.h:
+ * win/README.binary:
+ * win/README:
+ * unix/configure.in:
* mac/README: Updated version numbers to 8.1b2.
-1999-02-10 <stanton@GASPODE>
+1999-02-10 Scott Stanton <stanton@GASPODE>
- * library/auto.tcl: Fixed auto_mkindex so it handles .tbc files.
- Did some general cleanup to handle bad eval statements that didn't
- use "list".
+ * library/auto.tcl: Fixed auto_mkindex so it handles .tbc files. Did
+ some general cleanup to handle bad eval statements that didn't use
+ "list".
* unix/mkLinks:
* doc/SetVar.3:
* generic/tcl.h:
- * generic/tclVar.c: Restored Tcl_ObjGetVar2 and Tcl_ObjSetVar2
- from 8.0. Renamed Tcl_Get/SetObjVar2 to Tcl_GetVar2Ex and
- Tcl_SetVar2Ex.
+ * generic/tclVar.c: Restored Tcl_ObjGetVar2 and Tcl_ObjSetVar2 from
+ 8.0. Renamed Tcl_Get/SetObjVar2 to Tcl_GetVar2Ex and Tcl_SetVar2Ex.
-1999-02-10 <stanton@GASPODE>
+1999-02-10 Scott Stanton <stanton@GASPODE>
- INTEGRATED PATCHES FROM 8.0.5b2:
+ INTEGRATED PATCHES FROM 8.0.5b2:
* test/winPipe.test: Changed to remove echoArgs.tcl temporary file
when done.
-
+
* tests/cmdAH.test:
* generic/tclFileName.c (TclGetExtension): Changed behavior so the
split happens at the last period in the name instead of the first
- period of the last run of periods. So, "foo..o" is split into
- "foo." and ".o" now. [Bug: 1126]
-
- * win/makefile.vc: Added better support for paths with spaces in
- the name. Added .lib and support .dlls to the install-binaries
- target. Added generate of a pkgIndex.tcl script to the
- install-libraries target.
-
- * win/tclAppInit.c:
- * unix/tclAppInit.c:
- * mac/tclMacAppInit.c:
- * generic/tclTest.c: Changed some EXTERN declarations to extern
- since they are not defining exported interfaces. This avoids
- generating useless declspec() attributes and makes the windows
- makefile simpler.
-
- * generic/tcl.h: Moved Tcl_AppInit declaration to end and cleared
- out TCL_STORAGE_CLASS so it is not declared with a declspec().
+ period of the last run of periods. So, "foo..o" is split into "foo."
+ and ".o" now. [Bug 1126]
+
+ * win/makefile.vc: Added better support for paths with spaces in the
+ name. Added .lib and support .dlls to the install-binaries target.
+ Added generate of a pkgIndex.tcl script to the install-libraries
+ target.
+
+ * win/tclAppInit.c:
+ * unix/tclAppInit.c:
+ * mac/tclMacAppInit.c:
+ * generic/tclTest.c: Changed some EXTERN declarations to extern since
+ they are not defining exported interfaces. This avoids generating
+ useless declspec() attributes and makes the windows makefile simpler.
+
+ * generic/tcl.h: Moved Tcl_AppInit declaration to end and cleared out
+ TCL_STORAGE_CLASS so it is not declared with a declspec().
* tests/interp.test:
* generic/tclInterp.c (DeleteAlias): Changed to use
- Tcl_DeleteCommandFromToken so we handle renames properly. This
- avoids senseless panic. [Bug: 736]
+ Tcl_DeleteCommandFromToken so we handle renames properly. This avoids
+ senseless panic. [Bug 736]
- * unix/tclUnixChan.c:
- * win/tclWinSock.c:
+ * unix/tclUnixChan.c:
+ * win/tclWinSock.c:
* doc/socket.n: Applied Gordon Chaffee's patch to handle failures
- during asynchronous socket connection operations. This adds a new
- "-error" fconfgure option to socket channels. [Bug: 893]
+ during asynchronous socket connection operations. This adds a new
+ "-error" fconfgure option to socket channels. [Bug 893]
* generic/tclProc.c:
* generic/tclNamesp.c:
- * generic/tclInt.h:
- * generic/tclCmdIL.c:
- * generic/tclBasic.c:
- * generic/tclVar.c: Applied patch from Viktor Dukhovni to
- rationalize TCL_LEAVE_ERR_MSG behavior when creating variables.
-
- * generic/tclVar.c: Fixed bug in namespace tail computation.
- Fixed bug where upvar could resurrect a namespace variable whose
- namespace had been deleted.
+ * generic/tclInt.h:
+ * generic/tclCmdIL.c:
+ * generic/tclBasic.c:
+ * generic/tclVar.c: Applied patch from Viktor Dukhovni to rationalize
+ TCL_LEAVE_ERR_MSG behavior when creating variables.
+
+ * generic/tclVar.c: Fixed bug in namespace tail computation. Fixed bug
+ where upvar could resurrect a namespace variable whose namespace had
+ been deleted.
* generic/tclCompile.c (TclCompileExprCmd): Eliminated yet another
bogus optimization in expression compilation.
- * unix/configure.in: Added branch for BSD/OS-4* to shared library
- case statement. [Bug: 975]
- Fixed to correctly handle IRIX 6.5 n32 library support. [Bug: 1117]
-
- * win/winDumpExts.c: Patched to be pickier about stripping
- @'s. [Bug: 920]
+ * unix/configure.in: Added branch for BSD/OS-4* to shared library case
+ statement. [Bug 975]
+ Fixed to correctly handle IRIX 6.5 n32 library support. [Bug 1117]
- * library/http2.0/http.tcl: Added catch around eof test in
- CopyDone since the user may have already called http::reset.
- [Bug: 1108]
+ * win/winDumpExts.c: Patched to be pickier about stripping @'s. [Bug
+ 920]
- * unix/configure.in: Changed Linux and IRIX to set SHLIB_LIBS to
- LIBS so shared libraries are linked with the system
- libraries. [Bug: 1018]
+ * library/http2.0/http.tcl: Added catch around eof test in CopyDone
+ since the user may have already called http::reset. [Bug 1108]
+
+ * unix/configure.in: Changed Linux and IRIX to set SHLIB_LIBS to LIBS
+ so shared libraries are linked with the system libraries. [Bug 1018]
* generic/tclCompile.c (CompileExprWord): Fixed exception stack
- overflow bug caused by missing statement. [Bug: 928]
+ overflow bug caused by missing statement. [Bug 928]
- * generic/tclIOCmd.c:
- * generic/tclBasic.c: Objectified the "open" command. [Bug: 1113]
+ * generic/tclIOCmd.c:
+ * generic/tclBasic.c: Objectified the "open" command. [Bug 1113]
- * generic/tclPosixStr.c (Tcl_ErrnoId, Tcl_ErrnoMsg): When using
- egcs, ENOTSUP and EOPNOTSUPP are the same, so now we handle that
- case. [Bug: 1137]
+ * generic/tclPosixStr.c (Tcl_ErrnoId, Tcl_ErrnoMsg): When using egcs,
+ ENOTSUP and EOPNOTSUPP are the same, so now we handle that case. [Bug
+ 1137]
* library/init.tcl: Various small changes requested by Jan Nijtmans.
- - If the variable $tcl_library contains the empty string, this
- empty string will be put in $auto_path. This is not useful at all,
- it only slows down later package processing.
- - If the variable tcl_pkgPath is not set, the "unset __dir"
- fails. Thich makes init.tcl totally unusable. Better put a "catch"
- around it.
- - In the function tcl_findLibraries, the "string match" function
- only works correctly if $tcl_patchLevel is in one of the forms
- "?.?a?", "?.?b?" or "?.?.?". Could a "regexp" be used instead,
- then it allows anything to be appended to the patchLevel
- string. And it is more efficient.
- - The tclPkgSetup function assumes that if $type != "load" then
- the type must be "source". This needn't be true. Some users want
- to add their own setup types.
- [RFE: 1138] [Bug: 978]
-
- * win/tclWinReg.c:
+ - If the variable $tcl_library contains the empty string, this empty
+ string will be put in $auto_path. This is not useful at all, it only
+ slows down later package processing.
+ - If the variable tcl_pkgPath is not set, the "unset __dir" fails.
+ Thich makes init.tcl totally unusable. Better put a "catch" around
+ it.
+ - In the function tcl_findLibraries, the "string match" function only
+ works correctly if $tcl_patchLevel is in one of the forms "?.?a?",
+ "?.?b?" or "?.?.?". Could a "regexp" be used instead, then it allows
+ anything to be appended to the patchLevel string. And it is more
+ efficient.
+ - The tclPkgSetup function assumes that if $type != "load" then the
+ type must be "source". This needn't be true. Some users want to add
+ their own setup types.
+ [RFE 1138] [Bug 978]
+
+ * win/tclWinReg.c:
* doc/registry.n: Added support for HKEY_PERFORMANCE_DATA and
- HKEY_DYN_DATA keys. [Bug: 1109]
+ HKEY_DYN_DATA keys. [Bug 1109]
- * win/tclWinInit.c (TclPlatformInit): Added code to ensure
- tcl_pkgPath is set to "" when no registry entry is found. [Bug: 978]
+ * win/tclWinInit.c (TclPlatformInit): Added code to ensure tcl_pkgPath
+ is set to "" when no registry entry is found. [Bug 978]
-1999-02-01 <stanton@GASPODE>
+1999-02-01 Scott Stanton <stanton@GASPODE>
* generic/tclBasic.c:
* generic/tclCmdAH.c:
@@ -2464,208 +2405,204 @@
* generic/tclProc.c:
* generic/tclTest.c:
* generic/tclTimer.c:
- * generic/tcl.h: Made eval interfaces compatible with 8.0 by
- renaming Tcl_EvalObj to Tcl_EvalObjEx, renaming Tcl_Eval2 to
- Tcl_EvalEx and restoring Tcl_EvalObj and Tcl_GlobalEvalObj
- interfaces so they match Tcl 8.0.
+ * generic/tcl.h: Made eval interfaces compatible with 8.0 by renaming
+ Tcl_EvalObj to Tcl_EvalObjEx, renaming Tcl_Eval2 to Tcl_EvalEx and
+ restoring Tcl_EvalObj and Tcl_GlobalEvalObj interfaces so they match
+ Tcl 8.0.
-1999-01-28 <stanton@GASPODE>
+1999-01-28 Scott Stanton <stanton@GASPODE>
* Merged Tcl 8.0.5b1 changes.
-
+
* generic/tclUtil.c (Tcl_DStringSetLength): Changed so the buffer
- overallocates in a manner similar to Tcl_DStringAppend. This
- should improve performance for TclUniCharToUtfDString.
+ overallocates in a manner similar to Tcl_DStringAppend. This should
+ improve performance for TclUniCharToUtfDString.
1998-12-11 === Tcl 8.1b1 Release ===
-
-1998-12-10 <stanton@GASPODE>
+
+1998-12-10 Scott Stanton <stanton@GASPODE>
* Fixed lots of files that used TCL_THREAD instead of TCL_THREADS.
-
+
* generic/tclEncoding.c (Tcl_FreeEncoding): Moved most of the code
into a static FreeEncoding routine that does not grab the
- encodingMutex to avoid deadlocks/races when called from other
- routines that already have the mutex.
+ encodingMutex to avoid deadlocks/races when called from other routines
+ that already have the mutex.
-1998-12-09 <stanton@GASPODE>
+1998-12-09 Scott Stanton <stanton@GASPODE>
- * library/msgcat1.0/msgcat.tcl: Fixed bad export list, fixed so
- all locale strings are converted to lower case, including file
- names.
+ * library/msgcat1.0/msgcat.tcl: Fixed bad export list, fixed so all
+ locale strings are converted to lower case, including file names.
- * generic/regcomp.c (makescan): Fixed bug in longest match case
- that caused anchored patterns to fail. [Bug: 897]
+ * generic/regcomp.c (makescan): Fixed bug in longest match case that
+ caused anchored patterns to fail. [Bug 897]
-1998-12-08 <stanton@GASPODE>
+1998-12-08 Scott Stanton <stanton@GASPODE>
- * library/msgcat1.0/msgcat.tcl: changed mc to invoke mcunknown in
- the calling context, changed locale lookups to be case insensitive
+ * library/msgcat1.0/msgcat.tcl: changed mc to invoke mcunknown in the
+ calling context, changed locale lookups to be case insensitive
-1998-12-07 <stanton@GASPODE>
+1998-12-07 Scott Stanton <stanton@GASPODE>
* generic/tclAlloc.c (TclpRealloc): Fixed a memory allocation bug
- where big blocks that were reallocated into a different heap
- location were not being placed into the bigBlocks list. [Bug: 933]
+ where big blocks that were reallocated into a different heap location
+ were not being placed into the bigBlocks list. [Bug 933]
* tests/msgcat.test: Added message catalog test suite.
* library/msgcat1.0/msgcat.tcl: minor bug fixes, integrated latest
changes from Mark Harrison.
-1998-12-04 <stanton@GASPODE>
+1998-12-04 Scott Stanton <stanton@GASPODE>
- * library/msgcat1.0/msgcat.tcl: Changed code to conform to Tcl
- coding standards. Changed to use file join for portability.
+ * library/msgcat1.0/msgcat.tcl: Changed code to conform to Tcl coding
+ standards. Changed to use file join for portability.
* library/msgcat1.0: Added initial implementaion of Tcl message
catalog package contributed by Mark Harrison.
-1998-12-03 <stanton@GASPODE>
+1998-12-03 Scott Stanton <stanton@GASPODE>
- * win/tclWinPipe.c (BuildCommandLine): Fixed bug that kept
- arguments containing spaces from being properly quoted.
+ * win/tclWinPipe.c (BuildCommandLine): Fixed bug that kept arguments
+ containing spaces from being properly quoted.
* tests/defs: Changed so auto_path is set to only contain the Tcl
- library directory. This keeps the tests from accidentally picking
- up stuff in installed packages.
+ library directory. This keeps the tests from accidentally picking up
+ stuff in installed packages.
- * generic/tclUtil.c (Tcl_StringMatch): Changed to match 8.0
- behavior in corner case where there is no closing bracket.
+ * generic/tclUtil.c (Tcl_StringMatch): Changed to match 8.0 behavior
+ in corner case where there is no closing bracket.
-1998-12-02 <stanton@GASPODE>
+1998-12-02 Scott Stanton <stanton@GASPODE>
- * win/tclWinPipe.c (TclpCreateCommandChannel): Changed
- reader/writer threads to have THREAD_PRIORITY_HIGHEST so they will
- have a chance to run whenever there is something to do.
+ * win/tclWinPipe.c (TclpCreateCommandChannel): Changed reader/writer
+ threads to have THREAD_PRIORITY_HIGHEST so they will have a chance to
+ run whenever there is something to do.
* generic/tclIO.c (WriteBytes, WriteChars): Fixed so extraneous
flushes do not happen in line mode.
- (TranslateOutputEOL): Made translation more efficient in line mode
- and fixed a buffer overflow bug in CRLF translation. [Bug: 887]
+ (TranslateOutputEOL): Made translation more efficient in line mode and
+ fixed a buffer overflow bug in CRLF translation. [Bug 887]
-1998-12-02 <welch@SAGE>
+1998-12-02 Brent Welch <welch@SAGE>
* Updated patchlevel to 8.1b1
-1998-12-02 <stanton@GASPODE>
+1998-12-02 Scott Stanton <stanton@GASPODE>
- * generic/regc_color.c (subcolor): Added check for error case to
- avoid an out of bounds array reference.
+ * generic/regc_color.c (subcolor): Added check for error case to avoid
+ an out of bounds array reference.
* generic/tclCmdAH.c (Tcl_EncodingObjCmd): Changed to avoid using
Tcl_DStringResult because it is not binary clean.
- * generic/tclParse.c (Tcl_ParseCommand): Fixed bug in comment
- parsing where a trailing comment looked like an incomplete
- command.
+ * generic/tclParse.c (Tcl_ParseCommand): Fixed bug in comment parsing
+ where a trailing comment looked like an incomplete command.
-1998-12-02 <welch@SAGE>
+1998-12-02 Brent Welch <welch@SAGE>
* Merged changes from 8.0.4, especially the new pkg_mkIndex
-1998-12-01 <stanton@GASPODE>
+1998-12-01 Scott Stanton <stanton@GASPODE>
- * generic/tclIO.c (Tcl_ReadChars): Added a call to UpdateInterest
- so we don't block when there is data sitting in the buffers.
+ * generic/tclIO.c (Tcl_ReadChars): Added a call to UpdateInterest so
+ we don't block when there is data sitting in the buffers.
- * generic/tclTest.c (TestevalobjvObjCmd): Updated for EvalObjv
- change.
+ * generic/tclTest.c (TestevalobjvObjCmd): Updated for EvalObjv change.
* tests/parse.test: Updated tests for EvalObjv change.
- * generic/tclParse.c (EvalObjv, Tcl_EvalObjv): Changed
- Tcl_EvalObjv interface to remove string and length arguments,
- preserved original interface as EvalObjv for internal use.
+ * generic/tclParse.c (EvalObjv, Tcl_EvalObjv): Changed Tcl_EvalObjv
+ interface to remove string and length arguments, preserved original
+ interface as EvalObjv for internal use.
- * generic/tcl.h: Changed Tcl_EvalObjv interface to remove string
- and length arguments.
+ * generic/tcl.h: Changed Tcl_EvalObjv interface to remove string and
+ length arguments.
- * doc/Eval.3: Updated documentation for Tcl_EvalObjv to remove
- string and length arguments.
+ * doc/Eval.3: Updated documentation for Tcl_EvalObjv to remove string
+ and length arguments.
* generic/tclCompCmds.c (TclCompileForeachCmd): Fixed code that
corrupted the exceptDepth value in the compile environment when
- foreach failed to compile inline. [Bug: 884]
+ foreach failed to compile inline. [Bug 884]
- * library/encoding/euc-kr.enc:
- * library/encoding/ksc5601.enc:
- * tools/encoding/ksc5601.txt:
- * unix/tclUnixInit.c: Added support for Korean EUC.
+ * library/encoding/euc-kr.enc:
+ * library/encoding/ksc5601.enc:
+ * tools/encoding/ksc5601.txt:
+ * unix/tclUnixInit.c: Added support for Korean EUC.
* win/tclWinChan.c (TclpGetDefaultStdChannel): added check for a
failure during Tcl_MakeFileChannel.
-1998-11-30 <stanton@GASPODE>
+1998-11-30 Scott Stanton <stanton@GASPODE>
- * unix/tclUnixNotfy.c (Tcl_WaitForEvent): Fixed hang that occurs
- when trying to close a pipe that is currently being waited on by
- the notifier thread. [Bug: 607]
+ * unix/tclUnixNotfy.c (Tcl_WaitForEvent): Fixed hang that occurs when
+ trying to close a pipe that is currently being waited on by the
+ notifier thread. [Bug 607]
* unix/tclUnixFCmd.c (GetPermissionsAttribute): Increase size of
- returnString buffer to avoid overflow. [Bug: 584]
+ returnString buffer to avoid overflow. [Bug 584]
- * generic/tclThreadTest.c (TclThreadSend): Fixed memory leak due
- to use of TCL_VOLATILE instead of TCL_DYNAMIC.
+ * generic/tclThreadTest.c (TclThreadSend): Fixed memory leak due to
+ use of TCL_VOLATILE instead of TCL_DYNAMIC.
* generic/tclThread.c (TclRememberSyncObject): Fixed memory leak
caused by failure to reuse condition variables.
- * unix/tclUnixNotfy.c: (Tcl_AlertNotifier, Tcl_WaitForEvent,
- NotifierThreadProc, Tcl_InitNotifier): Fixed race condition caused
- by incorrect use of condition variables when sending messages
- between threads.. [Bug: 607]
+ * unix/tclUnixNotfy.c (Tcl_AlertNotifier, Tcl_WaitForEvent,
+ (NotifierThreadProc, Tcl_InitNotifier): Fixed race condition caused by
+ incorrect use of condition variables when sending messages between
+ threads. [Bug 607]
* generic/tclTestObj.c (TeststringobjCmd): MAX_STRINGS was off by one
so the strings array was too small.
* generic/tclCkalloc.c (Tcl_DbCkfree): Moved mutex lock so
- ValidateMemory is done inside the mutex to avoid a race condition
- when validate_memory is enabled. [Bug: 880]
+ ValidateMemory is done inside the mutex to avoid a race condition when
+ validate_memory is enabled. [Bug 880]
-1998-11-23 <stanton@GASPODE>
+1998-11-23 Scott Stanton <stanton@GASPODE>
* regexec.c: more performance tuning from Henry Spencer.
-1998-11-17 <stanton@GASPODE>
+1998-11-17 Scott Stanton <stanton@GASPODE>
- * tclScan.c: moved "scan" implementation out of tclCmdMZ.c and
- added Unicode support. This required a complete reimplementation
- of the command to avoid using scanf(), which isn't Unicode aware.
- Two new features were added in the process: %n to return the
- current number of characters consumed, and XPG3-style %n$ argument
- order specifiers similar to those provided by the "format"
- command. [Bug: 833]
+ * tclScan.c: moved "scan" implementation out of tclCmdMZ.c and added
+ Unicode support. This required a complete reimplementation of the
+ command to avoid using scanf(), which isn't Unicode aware. Two new
+ features were added in the process: %n to return the current number of
+ characters consumed, and XPG3-style %n$ argument order specifiers
+ similar to those provided by the "format" command. [Bug 833]
- * tclAlloc.c: changed so allocated memory is always 8-byte aligned
- to improve memory performance and to ensure that it will work on
- systems that don't like accessing 4-byte aligned values
- (e.g. Solaris and HP-UX). [Bug: 834]
+ * tclAlloc.c: changed so allocated memory is always 8-byte aligned to
+ improve memory performance and to ensure that it will work on systems
+ that don't like accessing 4-byte aligned values (e.g. Solaris and
+ HP-UX). [Bug 834]
-1998-11-06 <stanton@GASPODE>
+1998-11-06 Scott Stanton <stanton@GASPODE>
- * tclVar.c (TclGetIndexedScalar): Fixed bug 796, var name was
- getting lost before being passed to CallTraces.
+ * tclVar.c (TclGetIndexedScalar): Fixed bug 796, var name was getting
+ lost before being passed to CallTraces.
-1998-10-21 <stanton@GASPODE>
+1998-10-21 Scott Stanton <stanton@GASPODE>
* added "encoding" command
-
+
* Moved internal regexp declarations from tclInt.h to tclRegexp.h
* integrated regexp updates from Henry Spencer
-1998-10-15 <stanton@GASPODE>
+1998-10-15 Scott Stanton <stanton@GASPODE>
* tclUtf.c: added Unicode character table support
* tclInt.h: added TclUniCharIsWordChar
- * tclCmdMZ.c (Tcl_StringObjCmd): added "totitle" subcommand,
- changed "wordend" and "wordstart" to properly handle Unicode word
- characters and connector punctuation
+ * tclCmdMZ.c (Tcl_StringObjCmd): added "totitle" subcommand, changed
+ "wordend" and "wordstart" to properly handle Unicode word characters
+ and connector punctuation
-1998-10-05 <stanton@GASPODE>
+1998-10-05 Scott Stanton <stanton@GASPODE>
* auto.tcl, package.tcl: fixed SCCS strings
@@ -2682,17 +2619,16 @@
* tclExecute.c: fixed off-by-one copying error, fixed merge bugs
- * tclEvent.c: changed so USE_TCLALLOC is tested for value instead
- of definition
+ * tclEvent.c: changed so USE_TCLALLOC is tested for value instead of
+ definition
* tclCompCmds.c: replaced SCCS strings, added warnings around code
that modifies strings in place
* interp.test: added test for interp deleting itself
-1998-09-30 <stanton@GASPODE>
+1998-09-30 Scott Stanton <stanton@GASPODE>
* makefile.vc: fixed so TCL_LIBRARY is set before running tcltest
* tclWin32Dll.c: removed TclpFinalize, cleanup of merges
-
diff --git a/ChangeLog.2000 b/ChangeLog.2000
index 70d491f..2ebdd23 100644
--- a/ChangeLog.2000
+++ b/ChangeLog.2000
@@ -1,12 +1,11 @@
2000-12-14 Don Porter <dgp@users.sourceforge.net>
* generic/tclExecute.c:
- * tests/expr-old.test: Re-wrote Tcl's [expr rand()] and
- [expr srand($seed)] implementations, fixing a range error
- on some 64-bit platforms. Added tests that detect the bug.
- The rewrite changes the seed -> sequence map on 64-bit
- platforms, only for seed >= 2^31, a slight incompatibility.
- [Bug 121072, Patch 102781]
+ * tests/expr-old.test: Re-wrote Tcl's [expr rand()] and [expr
+ srand($seed)] implementations, fixing a range error on some 64-bit
+ platforms. Added tests that detect the bug. The rewrite changes the
+ seed -> sequence map on 64-bit platforms, only for seed >= 2^31, a
+ slight incompatibility. [Bug 121072, Patch 102781]
2000-12-10 Don Porter <dgp@users.sourceforge.net>
@@ -14,217 +13,209 @@
* library/msgcat/msgcat.tcl:
* library/msgcat/pkgIndex.tcl:
* library/opt/optparse.tcl:
- * library/opt/pkgIndex.tcl: Where [uplevel] is used in a proc
- to evaluate a Tcl built-in command in the caller's context,
- the built-in commands are now fully namespace-qualified. This
- prevents problems when the caller context is in a namespace where
- the built-in command name has been used by a command in the
- namespace. (For example, [::ns::set] might be called instead
- of the intended [::set]). [Bug #119422, Patch #102545]
+ * library/opt/pkgIndex.tcl: Where [uplevel] is used in a proc to
+ evaluate a Tcl built-in command in the caller's context, the built-in
+ commands are now fully namespace-qualified. This prevents problems
+ when the caller context is in a namespace where the built-in command
+ name has been used by a command in the namespace. (For example,
+ [::ns::set] might be called instead of the intended [::set]). [Bug
+ 119422, Patch 102545]
-2000-12-09 jeff hobbs <jhobbs@interwoven.com>
+2000-12-09 Jeff Hobbs <jhobbs@interwoven.com>
* win/tclWinTime.c (CalibrationThread): added lint return value to
- prevent compiler warning. [Bug #125005]
+ prevent compiler warning. [Bug 125005]
* docs/scan.n:
* tests/scan.test:
- * generic/tclScan.c (Tcl_ScanObjCmd): changed %o and %x to use
- strtoul instead of strtol to correctly preserve scan<>format
- conversion of large integers. [Patch #102663, Bug #124600]
+ * generic/tclScan.c (Tcl_ScanObjCmd): changed %o and %x to use strtoul
+ instead of strtol to correctly preserve scan<>format conversion of
+ large integers. [Patch 102663, Bug 124600]
* generic/tclExecute.c (TclExecuteByteCode): Commited patch fixing
- handling of {!<boolean>} in expressions. [Patch #102702]
+ handling of {!<boolean>} in expressions. [Patch 102702]
-2000-12-08 jeff hobbs <jhobbs@interwoven.com>
+2000-12-08 Jeff Hobbs <jhobbs@interwoven.com>
- * library/init.tcl: Added support for PATHEXT variable in
- auto_execok, recognizing the proper set of executable extensions
- on Windows. [Patch #102719]
+ * library/init.tcl: Added support for PATHEXT variable in auto_execok,
+ recognizing the proper set of executable extensions on Windows. [Patch
+ 102719]
2000-12-08 Andreas Kupries <a.kupries@westend.com>
- * generic/tclEncoding.c (LoadTableEncoding): Changed dangerous
- code to something less critical. This fixes bug 119417, part A
- without affecting the speed when loading encodings.
+ * generic/tclEncoding.c (LoadTableEncoding): Changed dangerous code to
+ something less critical. This fixes [Bug 119417], part A without
+ affecting the speed when loading encodings.
2000-12-08 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * doc/open.n: Added xref to fconfigure and advice on the opening
- of binary files. Should help prevent a recurrence of bugs like
- #124558
+ * doc/open.n: Added xref to fconfigure and advice on the opening of
+ binary files. Should help prevent a recurrence of bugs like [Bug
+ 124558]
-2000-12-07 jeff hobbs <jhobbs@interwoven.com>
+2000-12-07 Jeff Hobbs <jhobbs@interwoven.com>
* generic/tcl.h: added note about need to updated
library/dde/pkgIndex.tcl with minor version increment.
- * library/dde/pkgIndex.tcl: updated to use 84 version to reflect
- the makefile. Should probably be updated to use its real version
- at some point. [Patch #102560, Bug #119421]
+ * library/dde/pkgIndex.tcl: updated to use 84 version to reflect the
+ makefile. Should probably be updated to use its real version at some
+ point. [Patch 102560, Bug 119421]
-2000-12-06 eric melski <ericm@ajubasolutions.com>
+2000-12-06 Eric Melski <ericm@ajubasolutions.com>
* generic/tcl.h (attemptckalloc): Fixed typo for #define of
- attemptckalloc (was defined to Tcl_AttempDbCkalloc, should have
- been Tcl_AttemptDbCkalloc). [Bug: 124384]
+ attemptckalloc (was defined to Tcl_AttempDbCkalloc, should have been
+ Tcl_AttemptDbCkalloc). [Bug 124384]
- * generic/tclCkalloc.c: Added
- TCL_MEM_DEBUG versions of Tcl_AttemptDbCkrealloc and
- Tcl_AttemptDbCkalloc. [Bug: 124384].
+ * generic/tclCkalloc.c: Added TCL_MEM_DEBUG versions of
+ Tcl_AttemptDbCkrealloc and Tcl_AttemptDbCkalloc. [Bug 124384].
2000-11-24 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * generic/tclExecute.c (TclExecuteByteCode): Logical negation "!"
- can now handle string booleans, provided those values are placed
- in variables.
+ * generic/tclExecute.c (TclExecuteByteCode): Logical negation "!" can
+ now handle string booleans, provided those values are placed in
+ variables.
- * tests/expr.test (expr-13.17): Check that [expr {!$var}] can
- negate the string-versions of booleans "yes", "false", etc.
+ * tests/expr.test (expr-13.17): Check that [expr {!$var}] can negate
+ the string-versions of booleans "yes", "false", etc.
* library/tcltest/tcltest.tcl (getMatchingFiles,
- getMatchingDirectories):
- * tools/man2html.tcl (doDir):
- * tools/man2help.tcl (doDir):
- * library/package.tcl (tclPkgUnknown,tclMacPkgSearch):
+ (getMatchingDirectories):
+ * tools/man2html.tcl (doDir):
+ * tools/man2help.tcl (doDir):
+ * library/package.tcl (tclPkgUnknown,tclMacPkgSearch):
* library/safe.tcl (AddSubDirs): [glob] uses -directory instead of
- unsafe [file join] to fix Bug #123313
+ unsafe [file join]. [Bug 123313]
* generic/tclIndexObj.c:
* generic/tclTestObj.c (TestindexobjCmd): Changed internal
- representation of index objects to fix Bug #119082; fix
- shouldn't be visible to outside world...
+ representation of index objects to fix [Bug 119082]; fix shouldn't be
+ visible to outside world...
- * generic/tclTest.c (TestGetIndexFromObjStructObjCmd):
- * tests/indexObj.test: (indexObj-6.*) Added to test for presence
- of Bug #119082.
+ * generic/tclTest.c (TestGetIndexFromObjStructObjCmd):
+ * tests/indexObj.test: (indexObj-6.*) Added to test for presence of
+ [Bug 119082].
2000-11-23 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * generic/tclCmdIL.c (Tcl_LsortObjCmd): Fixed memory leak from Bug
- #119398
+ * generic/tclCmdIL.c (Tcl_LsortObjCmd): Fixed memory leak from [Bug
+ 119398]
* library/init.tcl (unknown): Added specific level parameters to
- all uplevel invokations to boost performance; didn't dare touch
- the "namespace inscope" stuff though, since it looks sensitive
- to me! Should fix Bug #123217, though testing is tricky...
+ all uplevel invokations to boost performance; didn't dare touch
+ the "namespace inscope" stuff though, since it looks sensitive
+ to me! Should fix [Bug 123217], though testing is tricky...
2000-11-21 Andreas Kupries <a.kupries@westend.com>
- * All of the changes below are described in TIP #7 ~ Specification
- and result from the application of the patch contained
- therein. Creator of the patch is Kevin Kenny
- <kennykb@crd.ge.com>. The patch used here is actually a bit
- different. Two MS specific constant values (format FOOui64) were
- replaced with a more portable formatting of the values and an
- additional cast to LONGLONG. My cross-compiling gcc was unable to
- process the original form. The SF Id of the patch is 102459.
-
- * tclWinTime.c: Add to the static data a set of variables that
- manage the phase-locked techniques, including a
- ''CRITICAL_SECTION'' to guard them so that multi-threaded code
- is stable.
-
- * tclWinTime.c: Modify ''TclpGetSeconds'' to call ''TclpGetTime''
- and return the 'seconds' portion of the result. This change is
- necessary to make sure that the two times are consistent near
- the rollover from one second to another.
+ All of the changes below are described in TIP #7 ~ Specification and
+ result from the application of the patch contained therein. Creator of
+ the patch is Kevin Kenny <kennykb@crd.ge.com>. The patch used here is
+ actually a bit different. Two MS specific constant values (format
+ FOOui64) were replaced with a more portable formatting of the values
+ and an additional cast to LONGLONG. My cross-compiling gcc was unable
+ to process the original form. [Patch 102459]
+
+ * tclWinTime.c: Add to the static data a set of variables that manage
+ the phase-locked techniques, including a ''CRITICAL_SECTION'' to guard
+ them so that multi-threaded code is stable.
+
+ * tclWinTime.c: Modify ''TclpGetSeconds'' to call ''TclpGetTime'' and
+ return the 'seconds' portion of the result. This change is necessary
+ to make sure that the two times are consistent near the rollover from
+ one second to another.
* tclWinTime.c: Modify ''TclpGetClicks'' to use TclpGetTime to
- determine the click count as a number of microseconds.
-
- * tclWinTime.c: Modify ''TclpGetTime'' to return the time as
- M*Q+B, where Q is the result of ''QueryPerformanceCounter'', and
- M and B are variables maintained by the phase-locked loop to
- keep the result as close as possible to the system clock. The
- ''TclpGetTime'' call will also launch the phase-lock management
- in a separate thread the first time that it is invoked. If the
- performance counter is unavailable, or if its frequency is not
- one of the two common 8254-compatible rates, then
- ''TclpGetTime'' will return the result of ''ftime'' as it does
- in Tcl 8.3.2.
-
- * tclWinTime.c: Add the clock calibration procedure. The
- calibration is somewhat complex; to save space, the reader is
- referred to the reference implementation for the details of how
- the time base and frequency are maintained.
-
- * tclWinNotify.c: Modify ''Tcl_Sleep'' to test that the process
- has, in fact, slept for the requisite time by calling
- ''TclpGetTime'' and comparing with the desired time. Otherwise,
- roundoff errors may cause the process to awaken early.
-
- * tclWinTest.c: Add a ''testwinclock'' command. This command
- returns a four element list comprising the seconds and
- microseconds portions of the system clock and the seconds and
- microseconds portions of the Tcl clock.
-
- * winTime.test: Add to the test suite a test that makes sure that
- the Tcl clock stays within 1.1 ms of the system clock over the
- duration of the test.
+ determine the click count as a number of microseconds.
+
+ * tclWinTime.c: Modify ''TclpGetTime'' to return the time as M*Q+B,
+ where Q is the result of ''QueryPerformanceCounter'', and M and B are
+ variables maintained by the phase-locked loop to keep the result as
+ close as possible to the system clock. The ''TclpGetTime'' call will
+ also launch the phase-lock management in a separate thread the first
+ time that it is invoked. If the performance counter is unavailable, or
+ if its frequency is not one of the two common 8254-compatible rates,
+ then ''TclpGetTime'' will return the result of ''ftime'' as it does in
+ Tcl 8.3.2.
+
+ * tclWinTime.c: Add the clock calibration procedure. The calibration
+ is somewhat complex; to save space, the reader is referred to the
+ reference implementation for the details of how the time base and
+ frequency are maintained.
+
+ * tclWinNotify.c: Modify ''Tcl_Sleep'' to test that the process has,
+ in fact, slept for the requisite time by calling ''TclpGetTime'' and
+ comparing with the desired time. Otherwise, roundoff errors may cause
+ the process to awaken early.
+
+ * tclWinTest.c: Add a ''testwinclock'' command. This command returns a
+ four element list comprising the seconds and microseconds portions of
+ the system clock and the seconds and microseconds portions of the Tcl
+ clock.
+
+ * winTime.test: Add to the test suite a test that makes sure that the
+ Tcl clock stays within 1.1 ms of the system clock over the duration of
+ the test.
2000-11-21 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * doc/global.n:
- * doc/upvar.n:
- * doc/variable.n: Improved documentation to mention that variables
- so created are listed in [info locals] and added a few more
- cross-links between these commands. Fixes bug #119387
+ * doc/global.n:
+ * doc/upvar.n:
+ * doc/variable.n: Improved documentation to mention that variables so
+ created are listed in [info locals] and added a few more cross-links
+ between these commands. [Bug 119387]
2000-11-17 Donal K. Fellows <fellowsd@cs.man.ac.uk>
* tests/safe.test: (safe-4.3):
- * generic/tclVar.c (TclLookupVar): Changed again. Now passes all
- the tests, though one needed modifying since it required the
- wrong answer. (Why on earth do we have inline modification of
- argument strings? This sort of thing is horrendous to debug and
- doesn't work well in a multithreaded environment!) Fixes bug
- 119192.
+ * generic/tclVar.c (TclLookupVar): Changed again. Now passes all the
+ tests, though one needed modifying since it required the wrong answer.
+ (Why on earth do we have inline modification of argument strings? This
+ sort of thing is horrendous to debug and doesn't work well in a
+ multithreaded environment!) [Bug 119192]
- * tests/var.test: (var-1.19) If my attempts to fix the problem
- aren't right yet, my attempts to describe it look pretty good to
- me...
+ * tests/var.test: (var-1.19) If my attempts to fix the problem aren't
+ right yet, my attempts to describe it look pretty good to me...
2000-11-16 Andreas Kupries <a.kupries@westend.com>
* win/tclWinPort.h (line 69): Changed reference to winsock2.h into
- winsock.h. This was a leftover from a foray into using winsock
- version 2 (History lesson from Scott Redman and Jeff
- Hobbs). This code was no problem when compiling Tcl itself, but
- could trip extensions. Fixes bug 122568.
+ winsock.h. This was a leftover from a foray into using winsock version
+ 2 (History lesson from Scott Redman and Jeff Hobbs). This code was no
+ problem when compiling Tcl itself, but could trip extensions. [Bug
+ 122568]
-2000-11-15 jeff hobbs <jeff.hobbs@acm.org>
+2000-11-15 Jeff Hobbs <jeff.hobbs@acm.org>
- * unix/Makefile.in: removed bp.c references (hasn't existed in a
- long time). Corrected 'make dist' to make dist with unversioned
- library directories (same as out of cvs), so make install works
- correctly with either source tree.
+ * unix/Makefile.in: removed bp.c references (hasn't existed in a long
+ time). Corrected 'make dist' to make dist with unversioned library
+ directories (same as out of cvs), so make install works correctly with
+ either source tree.
-2000-11-15 jeff hobbs <jeff.hobbs@acm.org>
+2000-11-15 Jeff Hobbs <jeff.hobbs@acm.org>
- * generic/tclVar.c (TclLookupVar): reverted fix below as it broke
- all other array unset error reporting. Bug-119192 is still
- open.
+ * generic/tclVar.c (TclLookupVar): reverted fix below as it broke all
+ other array unset error reporting. Bug 119192 is still open.
2000-11-15 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * generic/tclVar.c (TclLookupVar): Changed references to part2 to
- use elName instead in various error message generating spots, so
- as to fix Bug-119192.
+ * generic/tclVar.c (TclLookupVar): Changed references to part2 to use
+ elName instead in various error message generating spots. [Bug 119192]
2000-11-03 David Gravereaux <davygrvy@ajubasolutions.com>
- * win/.cvsignore: Removed 'configure' from the glob list now
- that it's included.
+ * win/.cvsignore: Removed 'configure' from the glob list now that it's
+ included.
2000-11-03 Jeff Hobbs <hobbs@ajubasolutions.com>
8.4a2 RELEASE
- * unix/Makefile.in (install-libraries, dist):
+ * unix/Makefile.in (install-libraries, dist):
* win/makefile.vc (install-libraries):
- * win/Makefile.in (install-libraries): updated to install
- unversioned library directories into versioned directories.
+ * win/Makefile.in (install-libraries): updated to install unversioned
+ library directories into versioned directories.
* tools/tcl.wse.in: updated for unversioning of library dirs
@@ -234,31 +225,31 @@
* generic/tclStubInit.c:
* generic/tclDecls.h:
- * generic/tcl.decls: added Tcl_SetMainLoop proc that allows people
- to set a main loop that will run for tclsh.
+ * generic/tcl.decls: added Tcl_SetMainLoop proc that allows people to
+ set a main loop that will run for tclsh.
* generic/tcl.h: added Tcl_MainLoopProc typedef
* generic/tclMain.c (Tcl_SetMainLoop, StdinProc, Prompt): new
- StdinProc and Prompt static procs and Tcl_SetMainLoop stubs proc.
- The first two handle a fileevent based prompt (taken from
- tkMain.c). Tcl_SetMainLoop enables the interactive setting of a
- main loop procedure. This enables Tk to be a loadable package.
+ StdinProc and Prompt static procs and Tcl_SetMainLoop stubs proc. The
+ first two handle a fileevent based prompt (taken from tkMain.c).
+ Tcl_SetMainLoop enables the interactive setting of a main loop
+ procedure. This enables Tk to be a loadable package.
2000-11-02 David Gravereaux <davygrvy@ajubasolutions.com>
- * generic/tclEvent.c: tclLibraryPath Tcl_Obj didn't have a way
- to share its data among threads. This caused Tcl_Init() to
- always fail in threads. Added a way to pass the data around
- with a global char*. [BUG: 5301]
+ * generic/tclEvent.c: tclLibraryPath Tcl_Obj didn't have a way to
+ share its data among threads. This caused Tcl_Init() to always fail in
+ threads. Added a way to pass the data around with a global char*.
+ [BUG: 5301]
2000-11-02 Jeff Hobbs <hobbs@ajubasolutions.com>
* unix/configure:
* unix/dltest/configure:
* win/configure:
- * tools/configure: checked in configure scripts so people doing
- CVS checkouts aren't required to have autoconf. Changes to
- configure.in in the future will require the corresponding
- configure script to also be re-autoconf'ed and checked in.
+ * tools/configure: checked in configure scripts so people doing CVS
+ checkouts aren't required to have autoconf. Changes to configure.in in
+ the future will require the corresponding configure script to also be
+ re-autoconf'ed and checked in.
* win/makefile.vc:
* win/tcl.m4: makefile fixes for Win64 support
@@ -270,14 +261,14 @@
* unix/tcl.m4: removed use of -lbsd and -ldl for AIX-5.
- * tests/subst.test: added tests for non-zero return code handling
- by subst.
+ * tests/subst.test: added tests for non-zero return code handling by
+ subst.
* generic/tclParse.c (Tcl_EvalEx): corrected handling of non-zero,
- non-error return code cases for subst. [BUG: 119829]
+ non-error return code cases for subst. [Bug 119829]
- * generic/tclVar.c (TclVarTraceExists): Corrected excessive mem
- use when info exists was called on a non-existent array element.
- [BUG: 119213, 119336]
+ * generic/tclVar.c (TclVarTraceExists): Corrected excessive mem use
+ when info exists was called on a non-existent array element. [Bug
+ 119213, 119336]
2000-10-30 David Gravereaux <davygrvy@ajubasolutions.com>
@@ -290,8 +281,8 @@
2000-10-30 Jeff Hobbs <hobbs@ajubasolutions.com>
- * unix/tclUnixInit.c: added default encoding map from
- "ja_JP.eucJP" to "euc-jp". (takahashi)
+ * unix/tclUnixInit.c: added default encoding map from "ja_JP.eucJP" to
+ "euc-jp". (takahashi)
* tests/clock.test: corrected clock-2.* test numbering
@@ -306,68 +297,67 @@
* unix/configure.in:
* unix/tcl.m4: added support for AIX-5.
- * generic/tclIO.c (Tcl_NotifyChannel): removed #ifdef around code
- for old channel structures, placed preserve/release around statePtr
- * generic/tclIO.c (CloseChannel): the statePtr for a channel was
- not being freed when the last channel in a stack was freed,
- causing a mem leak.
+ * generic/tclIO.c (Tcl_NotifyChannel): removed #ifdef around code for
+ old channel structures, placed preserve/release around statePtr
+ * generic/tclIO.c (CloseChannel): the statePtr for a channel was not
+ being freed when the last channel in a stack was freed, causing a mem
+ leak.
* unix/tclUnixChan.c: updated channel types to strict
- TCL_CHANNEL_VERSION_2 style to avoid compiler warnings. They work
+ TCL_CHANNEL_VERSION_2 style to avoid compiler warnings. They work
either way, but this avoids compiler warnings (that worries people).
2000-10-27 Jennifer Hom <jenn@ajubasolutions.com>
- * library/tcltest1.0/tcltest.tcl: Removed a cd into the test
- directory in runAllTests that screwed up the temporary directory
- setting, effectively preventing users from running tests on
- multiple platforms at the same time.
+ * library/tcltest1.0/tcltest.tcl: Removed a cd into the test directory
+ in runAllTests that screwed up the temporary directory setting,
+ effectively preventing users from running tests on multiple platforms
+ at the same time.
2000-10-26 David Gravereaux <davygrvy@ajubasolutions.com>
- * win/tclWinFile.c (TclpMatchFilesTypes): NULL was being set to
- "attr" which was a DWORD. Changed NULL to zero because a 'void *'
- can't be set to a DWORD to avoid the compiler warning.
+ * win/tclWinFile.c (TclpMatchFilesTypes): NULL was being set to "attr"
+ which was a DWORD. Changed NULL to zero because a 'void *' can't be
+ set to a DWORD to avoid the compiler warning.
2000-10-24 Jennifer Hom <jenn@ajubasolutions.com>
* tests/all.tcl: Removed support for tcltest 1.0.
-
+
* tests/tcltest.test:
* library/tcltest1.0/tcltest.tcl:
* library/tcltest1.0/pkgIndex.tcl:
* docs/tcltest.n: Moved tcltest2 code so that it's the standard
- version of tcltest. Removed all tcltest2 files
- (tests/tcltest2.test, library/tcltest1.0/tcltest2.tcl,
- docs/tcltest2.n).
+ version of tcltest. Removed all tcltest2 files (tests/tcltest2.test,
+ library/tcltest1.0/tcltest2.tcl, docs/tcltest2.n).
2000-10-20 Jeff Hobbs <hobbs@ajubasolutions.com>
* win/tclWinFile.c (TclpMatchFilesTypes): made the stat call only
- occur when necessary (for 'glob' command). Significantly speeds
- up glob command from 8.3. [BUG: 6216]
+ occur when necessary (for 'glob' command). Significantly speeds up
+ glob command from 8.3. [BUG: 6216]
2000-10-19 Jennifer Hom <jenn@ajubasolutions.com>
* library/tcltest1.0/tcltest2.tcl:
* tests/tcltest2
- * doc/tcltest2.n: Code and documentation cleanup. Modified
- -verbose to take list of keywords as well as string of letters.
- Removed Tcl version information from tcltest. Removed
- tcltest::grep from tcltest package. Added optional 3rd directory
- argument to makeFile/makeDirectory and removeFile/removeDirectory.
+ * doc/tcltest2.n: Code and documentation cleanup. Modified -verbose to
+ take list of keywords as well as string of letters. Removed Tcl
+ version information from tcltest. Removed tcltest::grep from tcltest
+ package. Added optional 3rd directory argument to
+ makeFile/makeDirectory and removeFile/removeDirectory.
* tests/basic.test: Changed references to tcltest::tclVersion to
hardcoded numbers.
- * generic/tcl.h: Changed reference to tcltest2.tcl and tcltest.tcl
- in comments to tests/basic.test.
+ * generic/tcl.h: Changed reference to tcltest2.tcl and tcltest.tcl in
+ comments to tests/basic.test.
2000-10-06 David Gravereaux <davygrvy@ajubasolutions.com>
- * win/tclWinChan.c: moved Win2K bug case test with GetStdHandle()
- from TclpGetDefaultStdChannel into Tcl_MakeFileChannel to enable
- a more general method in detecting invalid OS handles rather than
- just a specific known case. [BUG: 5971]
+ * win/tclWinChan.c: moved Win2K bug case test with GetStdHandle() from
+ TclpGetDefaultStdChannel into Tcl_MakeFileChannel to enable a more
+ general method in detecting invalid OS handles rather than just a
+ specific known case. [BUG: 5971]
2000-10-06 Jeff Hobbs <hobbs@ajubasolutions.com>
@@ -383,10 +373,10 @@
* library/tcltest1.0/tcltest2.tcl:
* tests/tcltest2.test:
- * doc/tcltest2.n: Modified the new form of the test command to
- accept both attribute-value pairs and command line options.
- Updated the tests and the documentation for this new format.
- Also changed the option names for the test command.
+ * doc/tcltest2.n: Modified the new form of the test command to accept
+ both attribute-value pairs and command line options. Updated the tests
+ and the documentation for this new format. Also changed the option
+ names for the test command.
2000-09-29 Jeff Hobbs <hobbs@scriptics.com>
@@ -394,24 +384,24 @@
space parity on Windows (Eason) [Bug 6057].
* win/Makefile.in: commented use of TESTFLAGS
- * unix/Makefile.in: added TESTFLAGS to test target to
- conform with Windows makefile and TEA style.
+ * unix/Makefile.in: added TESTFLAGS to test target to conform with
+ Windows makefile and TEA style.
* tests/stack.test: prevented possible crash on systems with low
- default stacksize (Tru64, AIX) in infinite recursion test. A
- solution to check remaining stack space in the core is best, but
- hard to do in a cross-platform manner.
+ default stacksize (Tru64, AIX) in infinite recursion test. A solution
+ to check remaining stack space in the core is best, but hard to do in
+ a cross-platform manner.
- * generic/tclIOGT.c (FLUSH_DELAY): renamed DELAY define to
- FLUSH_DELAY to avoid defn conflict using Tru64's cc.
+ * generic/tclIOGT.c (FLUSH_DELAY): renamed DELAY define to FLUSH_DELAY
+ to avoid defn conflict using Tru64's cc.
2000-09-28 Jeff Hobbs <hobbs@ajubasolutions.com>
* tools/tcl.wse.in: added tclPlatDecls.h and tkPlatDecls.h to the
Windows .exe install.
- * tests/fCmd.test (fCmd-6.20): corrected test to remove
- c:/tcl8975@ after creating it.
+ * tests/fCmd.test (fCmd-6.20): corrected test to remove c:/tcl8975@
+ after creating it.
* tests/fileName.test: cleaned up the testing of glob patterns for
c:/globTest (Windows) to directly create/remove directory.
@@ -421,13 +411,13 @@
* generic/tcl.decls:
* generic/tclIO.c: updated Tcl_IsChannelShared,
Tcl_IsChannelRegistered, Tcl_CutChannel, Tcl_SpliceChannel,
- Tcl_IsChannelExisting, and Tcl_ClearChannelHandlers to conform to
- the new stacked channel implementation. Their stub slots were
- also moved to give preference to the new 8.3.2 stub functions.
- This will cause an incompatability with 8.4a1 only.
+ Tcl_IsChannelExisting, and Tcl_ClearChannelHandlers to conform to the
+ new stacked channel implementation. Their stub slots were also moved
+ to give preference to the new 8.3.2 stub functions. This will cause an
+ incompatability with 8.4a1 only.
(StopCopy): fixed a bug introduced by a partial fix in 8.3.2 that
didn't set nonBlocking correctly when resetting the flags for the
- write side. [Bug: 6261]
+ write side. [Bug: 6261]
* doc/ChnlStack.3:
* doc/CrtChannel.3:
@@ -451,7 +441,7 @@
* win/tclWinPipe.c:
* win/tclWinSerial.c:
* win/tclWinSock.c: Up-port of changes made in 8.3.2 to 8.4a2 code
- base. Most of these changes relate to the rewrite of the stacked
+ base. Most of these changes relate to the rewrite of the stacked
channel implementation, with a few config related fixes.
Following is an asynchronous include of the applicable ChangeLog
@@ -467,67 +457,66 @@
* doc/CrtChannel.3: updated the docs to be aware of the
TCL_CHANNEL_VERSION_2 style of Tcl channels.
- * generic/tclIO.c (Tcl_CreateChannel): added assertion to verify
- that the new channel versioning will be binary compatible with
- older channel drivers.
+ * generic/tclIO.c (Tcl_CreateChannel): added assertion to verify that
+ the new channel versioning will be binary compatible with older
+ channel drivers.
2000-08-05 Jeff Hobbs <hobbs@scriptics.com>
- * generic/tclIOGT.c (TclChannelTransform): fixed segfault that
- would occur when transforming a channel with a proc that did not
- yet exist. (Kupries)
+ * generic/tclIOGT.c (TclChannelTransform): fixed segfault that would
+ occur when transforming a channel with a proc that did not yet exist.
+ (Kupries)
* generic/tclTest.c (TestChannelCmd): added some lint init'ing of
statePtr and chan vars.
2000-07-26 Jeff Hobbs <hobbs@scriptics.com>
- * merged core-8-3-1-io-rewrite back into core-8-3-1-branch.
- The core-8-3-1-io-rewrite branch should now be considered defunct.
+ Merged core-8-3-1-io-rewrite back into core-8-3-1-branch. The
+ core-8-3-1-io-rewrite branch should now be considered defunct.
* generic/tclStubInit.c:
* generic/tclDecls.h:
* generic/tcl.decls:
* generic/tcl.h:
- * generic/tclIO.c: moved the Tcl_Channel* macros from tcl.h to
- tclIO.c and made them proper stubbed functions. These are:
- Tcl_ChannelName, Tcl_ChannelVersion, Tcl_ChannelBlockModeProc,
- Tcl_ChannelCloseProc, Tcl_ChannelClose2Proc, Tcl_ChannelInputProc,
- Tcl_ChannelOutputProc, Tcl_ChannelSeekProc, Tcl_ChannelSetOptionProc,
+ * generic/tclIO.c: moved the Tcl_Channel* macros from tcl.h to tclIO.c
+ and made them proper stubbed functions. These are: Tcl_ChannelName,
+ Tcl_ChannelVersion, Tcl_ChannelBlockModeProc, Tcl_ChannelCloseProc,
+ Tcl_ChannelClose2Proc, Tcl_ChannelInputProc, Tcl_ChannelOutputProc,
+ Tcl_ChannelSeekProc, Tcl_ChannelSetOptionProc,
Tcl_ChannelGetOptionProc, Tcl_ChannelWatchProc,
- Tcl_ChannelGetHandleProc, Tcl_ChannelFlushProc,
- and Tcl_ChannelHandlerProc. These should be used to access the
+ Tcl_ChannelGetHandleProc, Tcl_ChannelFlushProc, and
+ Tcl_ChannelHandlerProc. These should be used to access the
Tcl_ChannelType structure instead of direct pointer dereferencing.
- * tests/iogt.test: added RCS string, marked tests 2.* to be
- unixOnly due to underlying system differences.
+ * tests/iogt.test: added RCS string, marked tests 2.* to be unixOnly
+ due to underlying system differences.
2000-07-25 Andreas Kupries <a.kupries@westend.com>
* tests/iogt.test: (line 866f) New tests iogt-6.[01], highlighting
- buffering trouble when stacking and unstacking transformations.
- iogt-6.0 is solved, see the changes below. iogt-6.1 remains, for
- now, due to the perceived complexity of solutions.
+ buffering trouble when stacking and unstacking transformations.
+ iogt-6.0 is solved, see the changes below. iogt-6.1 remains, for now,
+ due to the perceived complexity of solutions.
- * generic/tclIO.h: (line 139f) struct Channel, added a buffer
- queue, to hold data pushed back when stacking a transformation.
+ * generic/tclIO.h: (line 139f) struct Channel, added a buffer queue,
+ to hold data pushed back when stacking a transformation.
* generic/tclIO.c:
- (line 91f, line 7434f) New internal function 'CopyBuffer'.
- Derived from 'CopyAndTranslateBuffer', with translation
- removed.
- (line 1025f, line 1212f): Initialization of new queue.
- (line 1164f, Tcl_StackChannel): Pushback of input queue.
- (line 1293f, Tcl_UnstackChannel): Discard input and pushback.
- (line 3748f, Tcl_ReadRaw): Modified to use data in the push back
- area before going to the driver. Uses 'CopyBuffer', s.a.
- (line 4702f, GetInput): Modified to use data in the push back
- area before going to the driver.
- (line 4867f, Tcl_Seek): Modified to take pushback of the topmost
- channel in a stack into account.
- (line 5620f, Tcl_InputBuffered): See above. Added
- 'Tcl_ChannelBuffered'. Analogue to 'Tcl_InputBuffered' but for
- the buffer area in the channel.
+ (line 91f, line 7434f) New internal function 'CopyBuffer'. Derived
+ from 'CopyAndTranslateBuffer', with translation removed.
+ (line 1025f, line 1212f): Initialization of new queue.
+ (line 1164f, Tcl_StackChannel): Pushback of input queue.
+ (line 1293f, Tcl_UnstackChannel): Discard input and pushback.
+ (line 3748f, Tcl_ReadRaw): Modified to use data in the push back area
+ before going to the driver. Uses 'CopyBuffer', s.a.
+ (line 4702f, GetInput): Modified to use data in the push back area
+ before going to the driver.
+ (line 4867f, Tcl_Seek): Modified to take pushback of the topmost
+ channel in a stack into account.
+ (line 5620f, Tcl_InputBuffered): See above. Added
+ 'Tcl_ChannelBuffered'. Analog to 'Tcl_InputBuffered' but for the
+ buffer area in the channel.
* generic/tcl.decls: New public API 'Tcl_ChannelBuffered'. S.a.
@@ -541,21 +530,21 @@
* generic/tclIntDecls.h:
* generic/tclInt.decls: commented out internal decls for
TclTestChannelCmd and TclTestChannelEventCmd as they were moved to
- tclTest.c. Added new decls for TclChannelEventScriptInvoker and
+ tclTest.c. Added new decls for TclChannelEventScriptInvoker and
TclChannelTransform.
* generic/tclIO.c (CloseChannel): stopped masking out of the
- TCL_READABLE|TCL_WRITABLE bits from the state flags in
- CloseChannel, instead adding extra intelligence to
- CheckChannelErrors with a new CHANNEL_RAW_MODE bit for special
- behavior when called from Raw channel APIs.
+ TCL_READABLE|TCL_WRITABLE bits from the state flags in CloseChannel,
+ instead adding extra intelligence to CheckChannelErrors with a new
+ CHANNEL_RAW_MODE bit for special behavior when called from Raw channel
+ APIs.
2000-07-13 Jeff Hobbs <hobbs@scriptics.com>
- * generic/tclIO.c (StackSetBlockMode): moved set of chanPtr
- outside of blockModeProc check to avoid infinite loop when
- blockModeProc was NULL (Kupries). updated TransformSeekProc to
- not call Tcl_Seek directly (Kupries).
+ * generic/tclIO.c (StackSetBlockMode): moved set of chanPtr outside of
+ blockModeProc check to avoid infinite loop when blockModeProc was
+ NULL. Updated TransformSeekProc to not call Tcl_Seek directly
+ (Kupries).
* win/tclWinChan.c: updated fileChannelType to v2 channel struct
* win/tclWinConsole.c: updated consoleChannelType to v2 channel struct
@@ -565,85 +554,82 @@
2000-07-11 Brent Welch <welch@ajubasolutions.com>
- * win/tclConfig.sh.in (TCL_LIBS): Cleaned up unix-specific
- autoconf variables.
+ * win/tclConfig.sh.in (TCL_LIBS): Cleaned up unix-specific autoconf
+ variables.
2000-07-11 Jeff Hobbs <hobbs@scriptics.com>
- * tests/iogt.test: made tests [345].0 not run by default as they
- were failing in the new design, but I'm not convinced that the
- returned result isn't correct.
+ * tests/iogt.test: made tests [345].0 not run by default as they were
+ failing in the new design, but I'm not convinced that the returned
+ result isn't correct.
* generic/tclDecls.h:
* generic/tclStubInit.c:
- * generic/tcl.decls: added Tcl_GetTopChannel C API that returns
- the current top channel of a channel stack. Tcl_GetChannel was
- changed earlier to return the bottommost channel of a stack
- because that is the one that is guaranteed to stay around the
- longest, and this was needed to compensate for certain
- operations that want to look at the state of the main channel.
- Most channel APIs already compensate for grabbing the top, so it
- shouldn't be needed often.
+ * generic/tcl.decls: added Tcl_GetTopChannel C API that returns the
+ current top channel of a channel stack. Tcl_GetChannel was changed
+ earlier to return the bottommost channel of a stack because that is
+ the one that is guaranteed to stay around the longest, and this was
+ needed to compensate for certain operations that want to look at the
+ state of the main channel. Most channel APIs already compensate for
+ grabbing the top, so it shouldn't be needed often.
* generic/tclIO.c (Tcl_StackChannel, Tcl_UnstackChannel): Added
- flushing of buffers (Kupries), removed use of DownChannel macro,
- added Tcl_GetTopChannel public API to get to the top channel of
- the channel stack (necessary for TLS). Rewrote Tcl_NotifyChannel
- for new channel design (Kupries). Did some code cleanup in the
- transform code. tclIO.c must still be broken into bits (separate
- out test code and giot code, create tclIO.h).
+ flushing of buffers (Kupries), removed use of DownChannel macro, added
+ Tcl_GetTopChannel public API to get to the top channel of the channel
+ stack (necessary for TLS). Rewrote Tcl_NotifyChannel for new channel
+ design (Kupries). Did some code cleanup in the transform code.
+ tclIO.c must still be broken into bits (separate out test code and
+ giot code, create tclIO.h).
2000-07-10 Andreas Kupries <a.kupries@westend.com>
* tests/iogt.test: Reverted some earlier changes as a fix by Jeff
- revived the original and correct behaviour. IOW, the tests showed
- a genuine error and I didn't see it :(.
+ revived the original and correct behaviour. IOW, the tests showed a
+ genuine error and I didn't see it :(.
- * generic/tclIO.c (Tcl_Read|Write_Raw): Changed to directly use
- the drivers and not DoRead|DoWrite. The latter use the buffering
- system, encoding and eol-translation and this wreaks havoc with
- the data going through the transformations. Both procedures use
- CheckForchannelErrors and let it believe that there is no
- background copy in progress or else stacked channels could not
- be used for that.
+ * generic/tclIO.c (Tcl_Read|Write_Raw): Changed to directly use the
+ drivers and not DoRead|DoWrite. The latter use the buffering system,
+ encoding and eol-translation and this wreaks havoc with the data going
+ through the transformations. Both procedures use CheckForchannelErrors
+ and let it believe that there is no background copy in progress or
+ else stacked channels could not be used for that.
* generic/tclIO.c (TclCopyChannel, CopyData): Moved access to the
- topmost channel from the first to the second procedure to make
- the decision about that at the last possible time (Callbacks can
- change the stacking).
+ topmost channel from the first to the second procedure to make the
+ decision about that at the last possible time (Callbacks can change
+ the stacking).
test suite: failures of iogt-[345].0
-
+
2000-07-06 Jeff Hobbs <hobbs@scriptics.com>
- * tests/iogt.test: new tests for stacked channel stuff based off
- new 'testchannel transform|unstack' code (Kupries IOGT extension).
+ * tests/iogt.test: new tests for stacked channel stuff based off new
+ 'testchannel transform|unstack' code (Kupries IOGT extension).
* generic/tcl.decls:
* generic/tcl.h:
* generic/tclDecls.h:
* generic/tclStubsInit.c:
- * generic/tclIO.c: complete rewrite of Tcl Channel code for
- stacked channels. Channels are now designed to work in a more
- stacked fashion with a shared ChannelState data structure.
+ * generic/tclIO.c: complete rewrite of Tcl Channel code for stacked
+ channels. Channels are now designed to work in a more stacked fashion
+ with a shared ChannelState data structure.
2000-06-02 Jeff Hobbs <hobbs@scriptics.com>
* generic/tclIO.c (CloseChannel): removed the &ing out of
- (TCL_READABLE|TCL_WRITABLE) from the flags, as CloseChannel does
- this on the next pass through for the top channel, and it appeared
- to be causing hangs by not allowing the final flush.
+ (TCL_READABLE|TCL_WRITABLE) from the flags, as CloseChannel does this
+ on the next pass through for the top channel, and it appeared to be
+ causing hangs by not allowing the final flush.
2000-06-01 Jeff Hobbs <hobbs@scriptics.com>
- * generic/tclIO.c (CloseChannel): Rewrote CloseChannel code to
- unstack a channel during the close process. Fixed a refcount bug
- in Tcl_UnstackChannel. [Bug: 5623]
- (CloseChannel): further extended CloseChannel in the stacked case
- to effect certain operations on the next channel that would have
- been done in Tcl_Close. Also added CHANNEL_CLOSED and removed
- (TCL_READABLE|TCL_WRITABLE) bits from chanPtr->flags. Changed
- final reset of the WatchProc to check the chanDownPtr's (next)
- interestMask.
+ * generic/tclIO.c (CloseChannel): Rewrote CloseChannel code to unstack
+ a channel during the close process. Fixed a refcount bug in
+ Tcl_UnstackChannel. [Bug: 5623]
+ (CloseChannel): further extended CloseChannel in the stacked case to
+ effect certain operations on the next channel that would have been
+ done in Tcl_Close. Also added CHANNEL_CLOSED and removed
+ (TCL_READABLE|TCL_WRITABLE) bits from chanPtr->flags. Changed final
+ reset of the WatchProc to check the chanDownPtr's (next) interestMask.
******************************************************
** END OF ASYNCHRONOUS UP-PORT LOG (8.3.2 -> 8.4a2) **
@@ -651,49 +637,46 @@
2000-09-20 Jeff Hobbs <hobbs@scriptics.com>
- * tests/socket.test: removed doTestsWithRemoteServer constraint
- from socket-12.*. It requires 'exec', not a remote server.
- Cleaned up some coding errors.
+ * tests/socket.test: removed doTestsWithRemoteServer constraint from
+ socket-12.*. It requires 'exec', not a remote server. Cleaned up some
+ coding errors.
2000-09-20 Jennifer Hom <jenn@ajubasolutions.com>
* library/tcltest1.0/pkgIndex.tcl: Updated to load tcltest 2.0.
- * library/tcltest1.0/tcltest2.tcl: New version of tcltest.
- Cleanup of command line parsing: allows users to specify command
- line arguments through an environment variable named
- TCLTEST_OPTIONS [RFE: 3748], does not respond to incorrect
- arguments, and forces usage of entire flag name when using command
- line arguments. Defines accessor procs for all tcltest
- variables. Allows users to use 'return' in test scripts. Allow
- users to specify whether test files should be sourced or run in a
- separate process. 'all.tcl' code moved to tcltest package.
- 'test' proc modified to use attribute-value pairs. Allow users to
+ * library/tcltest1.0/tcltest2.tcl: New version of tcltest.
+ Cleanup of command line parsing: allows users to specify command line
+ arguments through an environment variable named TCLTEST_OPTIONS [RFE:
+ 3748], does not respond to incorrect arguments, and forces usage of
+ entire flag name when using command line arguments. Defines accessor
+ procs for all tcltest variables. Allows users to use 'return' in test
+ scripts. Allow users to specify whether test files should be sourced
+ or run in a separate process. 'all.tcl' code moved to tcltest package.
+ 'test' proc modified to use attribute-value pairs. Allow users to
specify what return codes, output, and errors can be compared and
- whether these values should be compared using regexp, glob, or
- exact matching. makeDirectory & removeDirectory now operate with
- respect to temporaryDirectory [Bug: 6001]. Test results from
- tests run in slave interpreters are now included in test totals
- [Bug: 1493]. Test files that return error values are now reported.
-
- * tests/all.tcl: Added code to check for the tcltest version
- loaded; modified to figure out which tests to run based on the
- tcltest version loaded.
+ whether these values should be compared using regexp, glob, or exact
+ matching. makeDirectory & removeDirectory now operate with respect to
+ temporaryDirectory [Bug: 6001]. Test results from tests run in slave
+ interpreters are now included in test totals [Bug: 1493]. Test files
+ that return error values are now reported.
+ * tests/all.tcl: Added code to check for the tcltest version loaded;
+ modified to figure out which tests to run based on the tcltest version
+ loaded.
* tests/tcltest.test: Modified to explicitly load version 1.0 of
tcltest.
- * tests/tcltest2.test: New test suite for tcltest; includes all of
- the old tests plus new ones reflecting changes made for version
- 2.0.
- * tests/cmdAH.test: Added singleTestInterp constraint to
- cmdAH-31.2; this test does not run if tests aren't sourced into a
- single interpreter.
- * tests/socket.test: Fixed two tests that were referencing
- variables outside of scope.
-
+ * tests/tcltest2.test: New test suite for tcltest; includes all of the
+ old tests plus new ones reflecting changes made for version 2.0.
+ * tests/cmdAH.test: Added singleTestInterp constraint to cmdAH-31.2;
+ this test does not run if tests aren't sourced into a single
+ interpreter.
+ * tests/socket.test: Fixed two tests that were referencing variables
+ outside of scope.
+
* tools/tcl.wse.in: Added code to install tcltest2.tcl.
- * doc/tcltest2.n: New documentation for tcltest version 2.0.
- Removes documentation for tcltest namespace variables. Adds
- documentation for new tcltest procs.
+ * doc/tcltest2.n: New documentation for tcltest version 2.0. Removes
+ documentation for tcltest namespace variables. Adds documentation for
+ new tcltest procs.
* unix/mkLinks: Added code to link to tcltest2.n.
@@ -702,15 +685,15 @@
2000-09-19 Eric Melski <ericm@ajubasolutions.com>
- * generic/tclCmdMZ.c (Tcl_RegexpObjCmd): When using -all, all
- attempts after the first to match the regexp against the string
- should include the TCL_REG_NOTBOL flag, to avoid erroneously
- matching ^ in the middle of the string. Added code to set this
- flag after the first pass through the matching loop. [Bug: 6284].
+ * generic/tclCmdMZ.c (Tcl_RegexpObjCmd): When using -all, all attempts
+ after the first to match the regexp against the string should include
+ the TCL_REG_NOTBOL flag, to avoid erroneously matching ^ in the middle
+ of the string. Added code to set this flag after the first pass
+ through the matching loop. [Bug: 6284].
2000-09-19 David Gravereaux <davygrvy@ajubasolutions.com>
- * doc/Eval.3: Added a note about the script argument to Tcl_Eval()
+ * doc/Eval.3: Added a note about the script argument to Tcl_Eval()
should be in UTF-8 or risk implied conversion errors when possible
combinations of upper ascii can be valid UTF-8 special codes.
@@ -726,24 +709,24 @@
* doc/Alloc.3: Added entries for Tcl_AttemptAlloc, Tcl_AttempRealloc.
* doc/StringObj.3: Added entry for Tcl_AttemptSetObjLength.
-
+
* generic/tclDecls.h:
* generic/tclStubInit.c: Regen'ed stubs files from new tcl.decls.
* generic/tcl.decls: Added stubs for the Tcl_Attempt* memory
allocators and for Tcl_AttemptSetObjLength.
- * generic/tcl.h: Added #define's for attemptckalloc,
- attemptckrealloc, which map to the Tcl_Attempt* memory allocators.
+ * generic/tcl.h: Added #define's for attemptckalloc, attemptckrealloc,
+ which map to the Tcl_Attempt* memory allocators.
* generic/tclCkalloc.c: Added non-panic'ing versions of Tcl_Alloc,
Tcl_Realloc, etc.; these are called Tcl_AttemptAlloc,
- Tcl_AttemptRealloc, etc. These are used by
- Tcl_AttemptSetObjLength and the string obj append functions.
+ Tcl_AttemptRealloc, etc. These are used by Tcl_AttemptSetObjLength and
+ the string obj append functions.
* generic/tclStringObj.c: Modified string growth algorithm to use
- doubling algorithm as long as possible, and only fall back when
- that fails. Added Tcl_AttemptSetObjLength, and modified
+ doubling algorithm as long as possible, and only fall back when that
+ fails. Added Tcl_AttemptSetObjLength, and modified
AppendUnicodeToUnicodeRep, AppendUtfToUtfRep, and
Tcl_AppendStringsToObjVA to support this.
@@ -753,11 +736,11 @@
project conversion backups.
* win/tclWinPipe.c: Stage-1 bug fix for TR#2460 "exec leaks memory".
- Added more logic around the close-down of the pipe reader thread so
- as to avoid, at all cost, a TerminateThread. Most cases with exec
- are fixed, but I don't consider 2460 done yet. Closing down the
- read side of a pipe before the child process, doesn't really fit
- the windows model. [BUG: 2460]
+ Added more logic around the close-down of the pipe reader thread so as
+ to avoid, at all cost, a TerminateThread. Most cases with exec are
+ fixed, but I don't consider 2460 done yet. Closing down the read side
+ of a pipe before the child process, doesn't really fit the windows
+ model. [BUG: 2460]
2000-09-07 Jeff Hobbs <hobbs@scriptics.com>
@@ -771,14 +754,14 @@
* win/tclWinLoad.c (TclpLoadFile): added special message for
ERROR_PROC_NOT_FOUND exception in loading a dll.
- * win/tclWinError.c: changed ERROR_PROC_NOT_FOUND to map from
- ESRCH (POSIX: no such process) to EINVAL because there is no good
- mapping for "procedure not found".
+ * win/tclWinError.c: changed ERROR_PROC_NOT_FOUND to map from ESRCH
+ (POSIX: no such process) to EINVAL because there is no good mapping
+ for "procedure not found".
* README:
* generic/tcl.h:
* library/tcltest1.0/tcltest.tcl:
- * tools/tcl.wse.in:
+ * tools/tcl.wse.in:
* tools/tcltk-man2html.tcl:
* unix/configure.in:
* unix/tcl.spec:
@@ -795,8 +778,8 @@
appends.
* doc/source.n:
- * doc/Eval.3: added extra note about how to safe use ^Z in code,
- as it is now a cross-platform (was just Windows) EOF char.
+ * doc/Eval.3: added extra note about how to safe use ^Z in code, as it
+ is now a cross-platform (was just Windows) EOF char.
2000-09-05 Jeff Hobbs <hobbs@scriptics.com>
@@ -810,26 +793,26 @@
2000-08-29 Eric Melski <ericm@ajubasolutions.com>
- * generic/tclStringObj.c: Applied patch from Gerhard Hintermayer
- to provide a more conservative string growth algorithm for strings
- larger than one megabyte; this allows more efficient use of memory
- for very large strings.
+ * generic/tclStringObj.c: Applied patch from Gerhard Hintermayer to
+ provide a more conservative string growth algorithm for strings larger
+ than one megabyte; this allows more efficient use of memory for very
+ large strings.
2000-08-25 Eric Melski <ericm@ajubasolutions.com>
* tests/trace.test: Extended array tracing tests.
- * doc/trace.n: Clarified information about when array traces will
- be fired.
+ * doc/trace.n: Clarified information about when array traces will be
+ fired.
* generic/tclVar.c (Tcl_ArrayObjCmd): Corrected call to CallTraces
- (for TCL_TRACE_ARRAY) to only be called when the variable is
- either an array or is undefined, to ensure that array traces do
- not fire for scalar variables.
+ (for TCL_TRACE_ARRAY) to only be called when the variable is either an
+ array or is undefined, to ensure that array traces do not fire for
+ scalar variables.
2000-08-24 Eric Melski <ericm@ajubasolutions.com>
-
- * doc/man.macros: Tweaked tab settings for .SO (Standard Options)
+
+ * doc/man.macros: Tweaked tab settings for .SO (Standard Options)
sections, based on suggestion from Peter Spjuth.
2000-08-24 Mo DeJong <mdejong@redhat.com>
@@ -838,23 +821,22 @@
* unix/configure.in:
* unix/tcl.m4 (SC_ENABLE_GCC): Remove --enable-gcc option.
* win/README: Add note about building with Cygwin.
- * win/configure.in:
- * win/tcl.m4 (SC_ENABLE_GCC): Remove --enable-gcc option.
- Remove quick hack that provided cross compile support for
- windows builds.
+ * win/configure.in:
+ * win/tcl.m4 (SC_ENABLE_GCC): Remove --enable-gcc option. Remove quick
+ hack that provided cross compile support for windows builds.
2000-08-24 Eric Melski <ericm@ajubasolutions.com>
- Overall change: Added support for command rename/delete traces
- and new trace syntax, from patch from Vince Darley. Added support
- for array traces for variables. [RFE: 5048, 5967].
+ Overall change: Added support for command rename/delete traces and new
+ trace syntax, from patch from Vince Darley. Added support for array
+ traces for variables. [RFE: 5048, 5967].
* doc/trace.n: Updated documentation for new syntax; flagged old
- syntax as deprecated; added documentation for command
- rename/delete traces and variable array traces.
+ syntax as deprecated; added documentation for command rename/delete
+ traces and variable array traces.
- * tests/trace.test: Updated tests for new trace syntax; new tests
- for command rename/delete traces; new tests for array traces.
+ * tests/trace.test: Updated tests for new trace syntax; new tests for
+ command rename/delete traces; new tests for array traces.
* generic/tclVar.c: Support for new trace syntax; support for
TCL_TRACE_ARRAY.
@@ -863,17 +845,17 @@
* generic/tclDecls.h:
* generic/tcl.decls: Stub functions for command rename/delete traces.
- * generic/tcl.h:
+ * generic/tcl.h:
* generic/tclInt.h:
* generic/tclBasic.c: Support for command traces.
- * generic/tclCmdMZ.c (TclTraceVariableObjCmd): Patched to support
- new [trace] syntax:
+ * generic/tclCmdMZ.c (TclTraceVariableObjCmd): Patched to support new
+ [trace] syntax:
trace {add|remove|list} {variable|command} name ops command
Added support for command traces (rename, delete operations).
- Added support for TCL_TRACE_ARRAY at Tcl level (array operation
- for variable traces).
-
+ Added support for TCL_TRACE_ARRAY at Tcl level (array operation for
+ variable traces).
+
2000-08-20 Eric Melski <ericm@ajubasolutions.com>
* generic/tclVar.c: Added check for non-arrays for [array statistics]
@@ -885,11 +867,11 @@
tclPlatDecls.h can't be parsed due to a missing definition of TCHAR.
Added a check to include it when not defined.
- ***POSSIBLE OBSCURE BUG*** could be caused when the compile flags
- for the core happen to be different than a project who uses these
- publics regarding -D_MBCS and -D_UNICODE. This added check might
- have to be revisited later with a better understanding of the
- reprocusions. I think TCHAR should be replaced with it's expansion.
+ ***POSSIBLE OBSCURE BUG*** could be caused when the compile flags for
+ the core happen to be different than a project who uses these publics
+ regarding -D_MBCS and -D_UNICODE. This added check might have to be
+ revisited later with a better understanding of the reprocusions. I
+ think TCHAR should be replaced with it's expansion.
2000-08-18 David Gravereaux <davygrvy@ajubasolutions.com>
@@ -899,13 +881,13 @@
2000-08-15 Eric Melski <ericm@ajubasolutions.com>
* library/tcltest1.0/tcltest.tcl: Set debug level in
- tcltest::restoreState to 2, for consistancy with the debug level
- in tcltest::saveState [Bug: 4505].
+ tcltest::restoreState to 2, for consistancy with the debug level in
+ tcltest::saveState [Bug: 4505].
2000-08-14 Eric Melski <ericm@ajubasolutions.com>
- * win/makefile.vc:
- * win/Makefile.in:
+ * win/makefile.vc:
+ * win/Makefile.in:
* unix/Makefile.in: Added tclPlatDecls.h to the list of installed
headers, for more complete stubs support. [Bug: 5241].
@@ -913,47 +895,44 @@
platform-specific stubs declarations (Tcl_WinTCharToUtf, etc)
[Bug: 5241].
- * README: Updated link for instructions on compiling Tcl from
- sources to point to correct location
- (http://dev.scriptics.com/doc/... instead of
- http://dev.scriptics.com/support/...).
+ * README: Updated link for instructions on compiling Tcl from sources
+ to point to correct location (http://dev.scriptics.com/doc/... instead
+ of http://dev.scriptics.com/support/...).
2000-08-11 Eric Melski <ericm@ajubasolutions.com>
* generic/tclEnv.c (TclUnsetEnv): Changed declaration of length
- variable from "unsigned int" to "int", to match usage when passed
- to TclpFindVariable [Bug: 6126].
+ variable from "unsigned int" to "int", to match usage when passed to
+ TclpFindVariable [Bug: 6126].
2000-08-10 Eric Melski <ericm@ajubasolutions.com>
- * library/msgcat1.0/pkgIndex.tcl: Bumped version number to 1.2
- [Bug: 6100].
+ * library/msgcat1.0/pkgIndex.tcl: Bumped version number to 1.2 [Bug:
+ 6100].
- * library/msgcat1.0/msgcat.tcl: Removed erroneous [package forget]
- in msgcat namespace initializer. Bumped version number to 1.2
- [Bug: 6100].
+ * library/msgcat1.0/msgcat.tcl: Removed erroneous [package forget] in
+ msgcat namespace initializer. Bumped version number to 1.2 [Bug: 6100]
2000-08-10 David Gravereaux <davygrvy@ajubasolutions.com>
- * generic/tclObj.c: r1.15 accidentally changed a global mutex
- name tclObjMutex to ObjMutex. Put the correct name back.
+ * generic/tclObj.c: r1.15 accidentally changed a global mutex name
+ tclObjMutex to ObjMutex. Put the correct name back.
2000-08-07 Eric Melski <ericm@ajubasolutions.com>
* tests/indexObj.test: Added tests using the [testwrongnumargs]
command to test Tcl_WrongNumArgs.
- * generic/tclTest.c (TestWrongNumArgsObjCmd): Added test function
- for the Tcl_WrongNumArgs function.
+ * generic/tclTest.c (TestWrongNumArgsObjCmd): Added test function for
+ the Tcl_WrongNumArgs function.
- * generic/tclIndexObj.c (Tcl_WrongNumArgs): Corrected algorithm to
- not insert a space before the message component when objc == 0
- [Bug: 6078].
+ * generic/tclIndexObj.c (Tcl_WrongNumArgs): Corrected algorithm to not
+ insert a space before the message component when objc == 0 [Bug: 6078]
2000-07-27 Mo DeJong <mdejong@redhat.com>
- * win/configure.in: TCL_STUB_LIB_FLAG should not
- include ${TCL_DBGX} in win/tclConfig.sh, fix that.
+ * win/configure.in: TCL_STUB_LIB_FLAG should not include ${TCL_DBGX}
+ in win/tclConfig.sh, fix that.
2000-07-25 David Gravereaux <davygrvy@ajubasolutions.com>
@@ -965,30 +944,30 @@
* generic/tclTest.c:
* mac/tclMacPort.h:
* unix/tclUnixPort.h:
- * win/tclWinInit.c: Thread-safe rewrite for tclAsync.c. Added
- notifier alerting on all platforms as it was only working on Win
- before. Removed older Win hacks that would end-up waking the
- wrong notifier in the presence of a threaded build. All tests
- pass as before. New test cases will be added soon for the new
- behavior. [BUG: 5791]
+ * win/tclWinInit.c: Thread-safe rewrite for tclAsync.c. Added notifier
+ alerting on all platforms as it was only working on Win before.
+ Removed older Win hacks that would end-up waking the wrong notifier in
+ the presence of a threaded build. All tests pass as before. New test
+ cases will be added soon for the new behavior. [BUG: 5791]
2000-07-25 Eric Melski <ericm@ajubasolutions.com>
- * generic/tclVar.c (CallTraces): Added check for VAR_TRACE_ACTIVE
- on the array containing the variable before executing traces on
- that array, to conform with normal variable traces and the
- documentation, which states that while executing a trace, other
- traces on that variable are disabled. [Bug: 6049].
+ * generic/tclVar.c (CallTraces): Added check for VAR_TRACE_ACTIVE on
+ the array containing the variable before executing traces on that
+ array, to conform with normal variable traces and the documentation,
+ which states that while executing a trace, other traces on that
+ variable are disabled. [Bug: 6049].
- * win/tclWinPipe.c (BuildCommandLine): Added Tcl_DStringFree call
- to prevent potential memory leaks [Bug: 6041].
+ * win/tclWinPipe.c (BuildCommandLine): Added Tcl_DStringFree call to
+ prevent potential memory leaks [Bug: 6041].
2000-07-24 Eric Melski <ericm@ajubasolutions.com>
- * doc/msgcat.n: Added documentation about the selection of the
- default locale on Windows.
+ * doc/msgcat.n: Added documentation about the selection of the default
+ locale on Windows.
2000-07-23 Joe English <jenglish@flightlab.com>
+
* doc/AddErrInfo.3:
* doc/ChnlStack.3:
* doc/Exit.3:
@@ -1006,13 +985,13 @@
2000-07-21 Eric Melski <ericm@ajubasolutions.com>
- * generic/tclStubInit.c:
- * generic/tclObj.c:
- * generic/tclInt.h:
- * generic/tclHash.c:
- * generic/tclDecls.h:
- * generic/tcl.h:
- * generic/tcl.decls:
+ * generic/tclStubInit.c:
+ * generic/tclObj.c:
+ * generic/tclInt.h:
+ * generic/tclHash.c:
+ * generic/tclDecls.h:
+ * generic/tcl.h:
+ * generic/tcl.decls:
* doc/Hash.3: Reapplied patch from Paul Duffin to extend hash tables
to allow custom key types, such as Tcl_Obj *'s, and others.
@@ -1022,41 +1001,41 @@
2000-07-21 Mo DeJong <mdejong@redhat.com>
* win/configure.in: Define ${prefix} and ${exec_prefix} like
- unix/configure.in. Fix or add TCL_SRC_DIR, TCL_STUB_LIB_FILE,
+ unix/configure.in. Fix or add TCL_SRC_DIR, TCL_STUB_LIB_FILE,
TCL_STUB_LIB_FLAG, TCL_BUILD_STUB_LIB_SPEC, TCL_STUB_LIB_SPEC,
TCL_BUILD_STUB_LIB_PATH, TCL_STUB_LIB_PATH.
2000-07-20 Eric Melski <ericm@ajubasolutions.com>
- * generic/tclStubInit.c:
- * generic/tclObj.c:
- * generic/tclInt.h:
- * generic/tclHash.c:
- * generic/tclDecls.h:
- * generic/tcl.h:
- * generic/tcl.decls:
- * doc/Hash.3: Reverted patch from Paul Duffin to extend hash tables
- to allow custom key types, such as Tcl_Obj *'s, and others; it
- seems to break Tk.
+ * generic/tclStubInit.c:
+ * generic/tclObj.c:
+ * generic/tclInt.h:
+ * generic/tclHash.c:
+ * generic/tclDecls.h:
+ * generic/tcl.h:
+ * generic/tcl.decls:
+ * doc/Hash.3: Reverted patch from Paul Duffin to extend hash tables to
+ allow custom key types, such as Tcl_Obj *'s, and others; it seems to
+ break Tk.
2000-07-19 Eric Melski <ericm@ajubasolutions.com>
- * generic/tclStubInit.c:
- * generic/tclObj.c:
- * generic/tclInt.h:
- * generic/tclHash.c:
- * generic/tclDecls.h:
- * generic/tcl.h:
- * generic/tcl.decls:
- * doc/Hash.3: Applied patch from Paul Duffin to extend hash tables
- to allow custom key types, such as Tcl_Obj *'s, and others.
+ * generic/tclStubInit.c:
+ * generic/tclObj.c:
+ * generic/tclInt.h:
+ * generic/tclHash.c:
+ * generic/tclDecls.h:
+ * generic/tcl.h:
+ * generic/tcl.decls:
+ * doc/Hash.3: Applied patch from Paul Duffin to extend hash tables to
+ allow custom key types, such as Tcl_Obj *'s, and others.
* tests/pkgMkIndex.test: Added tests for pkg_compareExtension.
- * library/package.tcl: Enhanced pkg_compareExtension to handle
- Unixes which tack the version number on to the end of library
- names (eg, foo.so.1.2); such filenames will be correctly matched.
- (Patch from Vince Darley).
+ * library/package.tcl: Enhanced pkg_compareExtension to handle Unixes
+ which tack the version number on to the end of library names (eg,
+ foo.so.1.2); such filenames will be correctly matched. (Patch from
+ Vince Darley).
* win/makefile.vc: Applied patch from Don Porter to provide better
nmake support for NT/Alpha [RFE: 5938].
@@ -1065,50 +1044,47 @@
* unix/configure.in:
* unix/tcl.m4:
- * win/tcl.m4: Properly quote arguments to m4 macros. This allows
- Tcl to work with the new version of autoconf.
+ * win/tcl.m4: Properly quote arguments to m4 macros. This allows Tcl
+ to work with the new version of autoconf.
2000-07-18 Eric Melski <ericm@ajubasolutions.com>
* tests/opt.test: Removed references to Lfirst, Lrest functions.
- * library/opt0.4/optparse.tcl: Applied patch from Chris Nelson,
- which replaces the [Lfirst] function with an inline [lindex ... 0]
- and [Lrest] with [lrange ... 1 end], for better performance.
- [RFE: 6019]
-
+ * library/opt0.4/optparse.tcl: Applied patch from Chris Nelson, which
+ replaces the [Lfirst] function with an inline [lindex ... 0] and
+ [Lrest] with [lrange ... 1 end], for better performance. [RFE: 6019]
2000-07-18 Eric Melski <ericm@scriptics.com>
- * compat/string.h: Fixed function prototypes for strpbrk and
- strtok [Bug: 6020].
+ * compat/string.h: Fixed function prototypes for strpbrk and strtok
+ [Bug: 6020].
2000-07-17 David Gravereaux <davygrvy@ajubasolutions.com>
- * win/tclWinChan.c: Win2K OS bug with
- GetStdHandle(STD_OUTPUT_HANDLE) giving the wrong answer. This
- made TclpGetDefaultStdChannel grab what it thought was a valid
- native stdout handle. Added a new WriteFile() test to make sure
- it's really valid. This OS bug doesn't affect the shells. Only
- -subsystem:windows (aka WinMain) application that dynamically
- load tclXX.dll [BUG: 5971]
+ * win/tclWinChan.c: Win2K OS bug with GetStdHandle(STD_OUTPUT_HANDLE)
+ giving the wrong answer. This made TclpGetDefaultStdChannel grab what
+ it thought was a valid native stdout handle. Added a new WriteFile()
+ test to make sure it's really valid. This OS bug doesn't affect the
+ shells. Only -subsystem:windows (aka WinMain) application that
+ dynamically load tclXX.dll [BUG: 5971]
2000-07-17 Eric Melski <ericm@scriptics.com>
- * library/msgcat1.0/msgcat.tcl:
- * doc/msgcat.n:
- * tests/msgcat.test: Applied patches from Chris Nelson, to provide
- the mcmset function, which allows the translator to set multiple
- string translations in a single function call, rather than
- requiring many calls to mcset. [RFE: 6000, 5993]. In addition,
- these patches correct mcload to use utf-8 encoding on when reading
- message catalog files, and provides for better default behavior
- for determining the locale on a Windows system.
+ * library/msgcat1.0/msgcat.tcl:
+ * doc/msgcat.n:
+ * tests/msgcat.test: Applied patches from Chris Nelson, to provide the
+ mcmset function, which allows the translator to set multiple string
+ translations in a single function call, rather than requiring many
+ calls to mcset. [RFE: 6000, 5993]. In addition, these patches correct
+ mcload to use utf-8 encoding on when reading message catalog files,
+ and provides for better default behavior for determining the locale on
+ a Windows system.
2000-07-17 Mo DeJong <mdejong@redhat.com>
- * unix/tcl.m4 (SC_ENABLE_GCC): Don't set CC=gcc
- before running AC_PROG_CC if CC is already set.
+ * unix/tcl.m4 (SC_ENABLE_GCC): Don't set CC=gcc before running
+ AC_PROG_CC if CC is already set.
2000-07-13 André Pönitz <poenitz@mathematik.tu-chemnitz.de>
@@ -1124,31 +1100,30 @@
2000-07-07 Mo DeJong <mdejong@redhat.com>
- * win/configure.in: Fix definition of
- TCL_SRC_DIR so that it matches the Unix version.
+ * win/configure.in: Fix definition of TCL_SRC_DIR so that it matches
+ the Unix version.
* win/tclConfig.sh.in: Removed duplicate variables.
2000-07-06 Eric Melski <ericm@scriptics.com>
- * tests/msgcat.test:
- * library/msgcat1.0/msgcat.tcl: Applied patch from Christian
- Krone, to provide extended args support for msgcat::unknown, which
- is used for strings without a known translation in the current
- locale [Bug: 5984].
+ * tests/msgcat.test:
+ * library/msgcat1.0/msgcat.tcl: Applied patch from Christian Krone, to
+ provide extended args support for msgcat::unknown, which is used for
+ strings without a known translation in the current locale [Bug: 5984].
2000-06-29 Eric Melski <ericm@scriptics.com>
* doc/msgcat.n: Doc's for mcmax function.
- * library/msgcat1.0/msgcat.tcl: Applied patches from Laurent
- Duperval, to add mcmax function, which computes the length of the
- longest of several translated strings. Bumped version number to 1.1.
+ * library/msgcat1.0/msgcat.tcl: Applied patches from Laurent Duperval,
+ to add mcmax function, which computes the length of the longest of
+ several translated strings. Bumped version number to 1.1.
2000-06-27 Eric Melski <ericm@scriptics.com>
- * tests/stringObj.test: Tweaked tests to avoid hardcoded
- high-ASCII characters (which will fail in multibyte locales);
- instead used \uXXXX syntax. [Bug: 3842].
+ * tests/stringObj.test: Tweaked tests to avoid hardcoded high-ASCII
+ characters (which will fail in multibyte locales); instead used \uXXXX
+ syntax. [Bug: 3842].
2000-06-26 Eric Melski <ericm@scriptics.com>
@@ -1157,17 +1132,17 @@
2000-06-23 Eric Melski <ericm@scriptics.com>
- * doc/Hash.3: Added documentation patch for Tcl_Obj *'s as keys in
- Tcl hash tables [RFE: 5934].
+ * doc/Hash.3: Added documentation patch for Tcl_Obj *'s as keys in Tcl
+ hash tables [RFE: 5934].
- * generic/tcl.h:
- * generic/tclHash.c: Applied patch from [RFE: 5934], which extends
- Tcl hash tables to allow Tcl_Obj *'s as the key.
+ * generic/tcl.h:
+ * generic/tclHash.c: Applied patch from [RFE: 5934], which extends Tcl
+ hash tables to allow Tcl_Obj *'s as the key.
2000-06-20 Eric Melski <ericm@ajubasolutions.com>
* tests/opt.test:
- * library/opt0.4/optparse.tcl: Applied patch from [Bug: 5922], which
+ * library/opt0.4/optparse.tcl: Applied patch from [Bug: 5922], which
corrected an incorrect use of [string match].
* unix/tclConfig.sh.in:
@@ -1183,23 +1158,23 @@
* win/tcl.m4:
* win/configure.in:
- * win/Makefile.in: Applied patch from [RFE: 5844], to extend
- support for mingw compile environment on Windows.
+ * win/Makefile.in: Applied patch from [RFE: 5844], to extend support
+ for mingw compile environment on Windows.
* win/tclWinDde.c:
* win/tclWinInit.c:
* win/tclWinNotify.c:
* win/tclWinPipe.c:
* win/tclWinReg.c:
- * win/tclWinThrd.c: Applied patch from [Bug: 5794], to fix
- compiler warnings when using mingw on Windows.
+ * win/tclWinThrd.c: Applied patch from [Bug: 5794], to fix compiler
+ warnings when using mingw on Windows.
2000-05-31 Jeff Hobbs <hobbs@scriptics.com>
* tests/set-old.test:
* doc/unset.n:
- * generic/tclVar.c (Tcl_UnsetObjCmd): added -nocomplain and --
- options to unset, to allow for a silent unset operation.
+ * generic/tclVar.c (Tcl_UnsetObjCmd): added -nocomplain and -- options
+ to unset, to allow for a silent unset operation.
2000-05-31 Eric Melski <ericm@scriptics.com>
@@ -1216,68 +1191,66 @@
8.4a1 RELEASE
- * generic/tclExecute.c (TclExecuteByteCode INST_STR_CMP): added
- test of iResult return from memcmp, as memcmp isn't required to
- return only -1,0,1.
+ * generic/tclExecute.c (TclExecuteByteCode INST_STR_CMP): added test
+ of iResult return from memcmp, as memcmp isn't required to return only
+ -1,0,1.
2000-06-03 Jeff Hobbs <hobbs@scriptics.com>
- * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct): Corrected
- caching of the index ptr to account for offsets != sizeof(char *).
- [Bug: 5153]
+ * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct): Corrected caching
+ of the index ptr to account for offsets != sizeof(char *). [Bug: 5153]
2000-05-29 Sandeep Tamhankar <sandeep@scriptics.com>
* tests/http.test
* doc/http.n
- * library/http2.3/http.tcl: Fixed bug 5741, where unsuccessful
- geturl calls sometimes leaked memory and resources (sockets).
- Also, switched around some of the logic so that http::wait never
- throws an exception. This is because in an asynchronous geturl,
- the command callback will probably end up doing all the error
- handling anyway, and in an asynchronous situation, the user
- expects to check the state when the transaction completes, as
- opposed to being thrown an exception. For the http package, this
- menas the user can check http::status for "error" and http::error
- for the error message after doing the http::wait.
+ * library/http2.3/http.tcl: Fixed bug 5741, where unsuccessful geturl
+ calls sometimes leaked memory and resources (sockets). Also, switched
+ around some of the logic so that http::wait never throws an exception.
+ This is because in an asynchronous geturl, the command callback will
+ probably end up doing all the error handling anyway, and in an
+ asynchronous situation, the user expects to check the state when the
+ transaction completes, as opposed to being thrown an exception. For
+ the http package, this menas the user can check http::status for
+ "error" and http::error for the error message after doing the
+ http::wait.
2000-05-27 Jeff Hobbs <hobbs@scriptics.com>
* tests/info.test:
* doc/info.n:
* generic/tclIOUtil.c (Tcl_EvalFile):
- * generic/tclCmdIL.c (InfoScriptCmd): added ability to set the
- info script return value [info script ?newFileName?]. This will
- be beneficial for virtual file system programs. [Bug: 4225]
+ * generic/tclCmdIL.c (InfoScriptCmd): added ability to set the info
+ script return value [info script ?newFileName?]. This will be
+ beneficial for virtual file system programs. [Bug: 4225]
2000-05-26 Jeff Hobbs <hobbs@scriptics.com>
* generic/tclCmdMZ.c (Tcl_RegsubObjCmd): reworked to operate in
Unicode, tweaked for performance.
(Tcl_StringObjCmd) changed STR_FIRST/STR_LAST error message to
- something more understandable, reworked STR_FIRST, STR_LAST,
- STR_MAP, STR_MATCH, STR_RANGE, STR_REPLACE to operate in Unicode.
- Removed inneffectual STR_RANGE "special" ByteArray support.
- Optimized STR_MAP algorithm, especially optimized for one-pair case.
- Fixed possible mem overrun in STR_INDEX bytearray case.
-
+ something more understandable, reworked STR_FIRST, STR_LAST, STR_MAP,
+ STR_MATCH, STR_RANGE, STR_REPLACE to operate in Unicode. Removed
+ inneffectual STR_RANGE "special" ByteArray support. Optimized STR_MAP
+ algorithm, especially optimized for one-pair case. Fixed possible mem
+ overrun in STR_INDEX bytearray case.
+
* generic/tclCompExpr.c: changed INST_STREQ -> INST_STR_EQ,
INST_STRNEQ -> INST_STR_NEQ
* generic/tclCompile.c: added streq, strneq, strcmp, strlen &
strmatch to the compiled stats instructionTable
* generic/tclCompile.h: added instructions INST_STR_CMP,
INST_STR_INDEX, INST_STR_MATCH
- * generic/tclCompCmds.c: added byte compiler support for
- [string compare|match|index].
- * generic/tclExecute.c:
- Changed INST_STR_(N)EQ to return an Int object and not bother
- trying to reuse the top stack object.
- Added INST_STR_CMP, INST_STR_INDEX, INST_STR_MATCH bytecode ops.
- Extended evalstats output info with Tcl_IsShared stat info.
+ * generic/tclCompCmds.c: added byte compiler support for [string
+ compare|match|index].
+ * generic/tclExecute.c: Changed INST_STR_(N)EQ to return an Int object
+ and not bother trying to reuse the top stack object. Added
+ INST_STR_CMP, INST_STR_INDEX, INST_STR_MATCH bytecode ops. Extended
+ evalstats output info with Tcl_IsShared stat info.
* generic/tclInt.h:
- * generic/tclObj.c (Tcl_DbIsShared): added support for checking
- result of Tcl_IsShared in evalstats (TCL_COMPILE_STATS).
+ * generic/tclObj.c (Tcl_DbIsShared): added support for checking result
+ of Tcl_IsShared in evalstats (TCL_COMPILE_STATS).
* generic/tclStringObj.c (Tcl_AppendUnicodeToObj): removed dead code.
(AppendUnicodeToUnicodeRep) removed overallocation by extra
@@ -1289,31 +1262,30 @@
2000-05-23 Eric Melski <ericm@scriptics.com>
- * generic/tclInt.h: Added function prototypes for
- TclCompileStringCmd and TclCompileReturnCmd.
+ * generic/tclInt.h: Added function prototypes for TclCompileStringCmd
+ and TclCompileReturnCmd.
* generic/tclCompile.h: Added definition of INST_STRLEN opcode and
updated LAST_INST_OPCODE value.
- * generic/tclBasic.c: Added information about TclCompileStringCmd
- and TclCompileReturnCmd to BuiltInCmds table.
+ * generic/tclBasic.c: Added information about TclCompileStringCmd and
+ TclCompileReturnCmd to BuiltInCmds table.
* generic/tclExecute.c (TclExecuteByteCode): Added support for the
INST_STRLEN opcode.
- * generic/tclCompCmds.c
- (TclCompileStringCmd): Basic implementation of byte-compiled
- [string] command. Not all subcommands are implemented; those
- that are not an out-line compiled.
+ * generic/tclCompCmds.c (TclCompileStringCmd): Basic implementation of
+ byte-compiled [string] command. Not all subcommands are implemented;
+ those that are not an out-line compiled.
(TclCompileReturnCmd): Byte-compiled implementation of [return]
- command. Only "simple" returns are byte-compiled; in particular,
- if the -code, -errorinfo or -errorcode flags are used, the command
- is not byte-compiled.
+ command. Only "simple" returns are byte-compiled; in particular, if
+ the -code, -errorinfo or -errorcode flags are used, the command is not
+ byte-compiled.
2000-05-22 Jeff Hobbs <hobbs@scriptics.com>
- * doc/scan.n:
+ * doc/scan.n:
* doc/array.n: minor doc fixes [Bug: 5396]
* generic/tclEnv.c: cast cleanup [Bug: 5624]
@@ -1331,9 +1303,9 @@
* generic/tclStubInit.c:
* generic/tclIntDecls.h:
- * generic/tclInt.decls: removed TclTestChannel*Cmd from internal
- stubs table and added TclChannelEventScriptInvoker to the internal
- stubs table so it can be used from the test code.
+ * generic/tclInt.decls: removed TclTestChannel*Cmd from internal stubs
+ table and added TclChannelEventScriptInvoker to the internal stubs
+ table so it can be used from the test code.
2000-05-18 Eric Melski <ericm@scriptics.com>
@@ -1342,9 +1314,9 @@
* generic/tclDate.c: Regenerated from tclGetDate.y.
- * generic/tclGetDate.y: Tweaked grammar to properly handle the
- "ago" keyword when it follows multiple relative unit specifiers,
- as in "2 days 2 hours ago". [Bug: 5497].
+ * generic/tclGetDate.y: Tweaked grammar to properly handle the "ago"
+ keyword when it follows multiple relative unit specifiers, as in "2
+ days 2 hours ago". [Bug: 5497]
2000-05-18 Jeff Hobbs <hobbs@scriptics.com>
@@ -1354,9 +1326,9 @@
* generic/tclClock.c (FormatClock): correct code to handle locale
specific return values from strftime, if any. [Bug: 3345]
- * unix/tclUnixInit.c (TclpSetInitialEncodings): attempt to
- correct setlocale calls for XIM support and locale issues.
- [BUG: 5422 3345 4236 2522 2521]
+ * unix/tclUnixInit.c (TclpSetInitialEncodings): attempt to correct
+ setlocale calls for XIM support and locale issues. [BUG: 5422 3345
+ 4236 2522 2521]
2000-05-17 Jeff Hobbs <hobbs@scriptics.com>
@@ -1373,32 +1345,32 @@
2000-05-10 Jeff Hobbs <hobbs@scriptics.com>
- * generic/tclPosixStr.c (Tcl_SignalMsg): clarified #defines for
- Linux on Sparc to compile correctly. [Bug: 5364]
+ * generic/tclPosixStr.c (Tcl_SignalMsg): clarified #defines for Linux
+ on Sparc to compile correctly. [Bug: 5364]
* doc/namespace.n:
* tests/namespace.test:
- * generic/tclNamesp.c (Tcl_NamespaceObjCmd): added 'namespace
- exists' command. [Bug: 4665]
+ * generic/tclNamesp.c (Tcl_NamespaceObjCmd): added 'namespace exists'
+ command. [Bug: 4665]
* doc/source.n:
* doc/Eval.3:
* tests/source.test:
- * generic/tclIOUtil.c (Tcl_EvalFile): added explicit \32 (^Z)
- eofchar (affects Tcl_EvalFile in C, "source" in Tcl). This was
- implicit on Windows already, and is now cross-platform to allow
- for scripted documents.
+ * generic/tclIOUtil.c (Tcl_EvalFile): added explicit \32 (^Z) eofchar
+ (affects Tcl_EvalFile in C, "source" in Tcl). This was implicit on
+ Windows already, and is now cross-platform to allow for scripted
+ documents.
2000-05-09 Andreas Kupries <a.kupries@westend.com>
operating as proxy for David Gravereaux <davygrvy@pobox.com>
-
+
* win/tclWinThrd.c (TclpInitLock, TclpMasterLock): Added missing
- initialization of joinLock.
+ initialization of joinLock.
2000-05-09 Eric Melski <ericm@scriptics.com>
- * tests/lsearch.test:
- * doc/lsearch.n:
+ * tests/lsearch.test:
+ * doc/lsearch.n:
* generic/tclCmdIL.c (Tcl_LsearchObjCmd): Extended [lsearch] to
support sorted list searching and typed list searching. [RFE: 4098].
@@ -1408,19 +1380,19 @@
* tests/expr.test:
* tests/expr-old.test: added tests for 'eq' and 'ne'
* generic/tclExecute.c:
- * generic/tclCompile.h: added INST_STREQ and INST_STRNEQ opcodes
- that do strict string comparisons.
+ * generic/tclCompile.h: added INST_STREQ and INST_STRNEQ opcodes that
+ do strict string comparisons.
* generic/tclCompExpr.c: added 'eq' and 'ne' string comparison
operators.
- * generic/tclParseExpr.c (GetLexeme): added 'eq' and 'ne' expr
- parse terms (string (in)equality check).
+ * generic/tclParseExpr.c (GetLexeme): added 'eq' and 'ne' expr parse
+ terms (string (in)equality check).
* generic/tclCmdIL.c (Tcl_LinsertObjCmd): made use of
- Tcl_DuplicateObj where code was otherwise duplicated. Made
- special case of inserting one element at the end work again (where
- index == len).
- (Tcl_LreplaceObjCmd): moved Tcl_DuplicateObj call lower and
- cleaned up use of other arguments.
+ Tcl_DuplicateObj where code was otherwise duplicated. Made special
+ case of inserting one element at the end work again (where index ==
+ len).
+ (Tcl_LreplaceObjCmd): moved Tcl_DuplicateObj call lower and cleaned
+ up use of other arguments.
* generic/tclObj.c (Tcl_DuplicateObj): simplified code to call
TclInitStringRep, which the code was just duplicating in part.
@@ -1437,16 +1409,15 @@
2000-05-08 Eric Melski <ericm@scriptics.com>
- * tests/set-old.test:
- * doc/array.n:
+ * tests/set-old.test:
+ * doc/array.n:
* generic/tclVar.c: Added [array statistics] command [RFE: 4557]
2000-05-06 Andreas Kupries <a.kupries@westend.com>
operating as proxy for David Gravereaux <davygrvy@pobox.com>
- * tclThreadJoin.c: Fixed several places with missing a & in
- arguments to calls of Tcl_Mutex(Un)lock and
- Tcl_ConditionNotify functions.
+ * tclThreadJoin.c: Fixed several places with missing a & in arguments
+ to calls of Tcl_Mutex(Un)lock and Tcl_ConditionNotify functions.
2000-05-02 Jeff Hobbs <hobbs@scriptics.com>
@@ -1480,72 +1451,70 @@
2000-05-02 Andreas Kupries <a.kupries@westend.com>
- * Overall changes:
+ Overall changes:
(1) Implementation of joinable threads for all platforms.
- (2) Additional API's for channels. Required to allow the
- thread extension to move channels between threads.
+ (2) Additional API's for channels. Required to allow the thread
+ extension to move channels between threads.
* generic/tcl.decls (lines 1360f): Added Tcl_JoinThread,
- Tcl_IsChannelShared, Tcl_IsChannelRegistered, Tcl_CutChannel,
- Tcl_SpliceChannel, Tcl_IsChannelExisting and
- Tcl_ClearChannelHandlers (slots 394 to 400).
+ Tcl_IsChannelShared, Tcl_IsChannelRegistered, Tcl_CutChannel,
+ Tcl_SpliceChannel, Tcl_IsChannelExisting and Tcl_ClearChannelHandlers
+ (slots 394 to 400).
* generic/tclIO.c: Implemented Tcl_IsChannelRegistered,
- Tcl_IsChannelShared, Tcl_CutChannel, Tcl_SpliceChannel,
- Tcl_IsChannelExisting and Tcl_ClearChannelHandlers.
- Tcl_CutChannel uses code from CloseChannel. Replaced this code
- by a call to Tcl_CutChannel. Replaced several code fragments
- adding channels to the channel list with calls to
- Tcl_SpliceChannel. Removed now unused variables from
- CloseChannel and Tcl_UnstackChannel. Tcl_ClearChannelHandlers
- uses code from Tcl_Close. Replaced this code by a call to
- Tcl_ClearChannelHandlers. Removed now unused variables from
- Tcl_Close. Added the subcommands 'cut', 'forgetch', 'splice' and
- 'isshared' to the test code
- (TclTestChannelCmd).
+ Tcl_IsChannelShared, Tcl_CutChannel, Tcl_SpliceChannel,
+ Tcl_IsChannelExisting and Tcl_ClearChannelHandlers. Tcl_CutChannel
+ uses code from CloseChannel. Replaced this code by a call to
+ Tcl_CutChannel. Replaced several code fragments adding channels to
+ the channel list with calls to Tcl_SpliceChannel. Removed now unused
+ variables from CloseChannel and Tcl_UnstackChannel.
+ Tcl_ClearChannelHandlers uses code from Tcl_Close. Replaced this code
+ by a call to Tcl_ClearChannelHandlers. Removed now unused variables
+ from Tcl_Close. Added the subcommands 'cut', 'forgetch', 'splice' and
+ 'isshared' to the test code (TclTestChannelCmd).
* unix/tclUnixThread.c: Implemented Tcl_JoinThread using the
- pthread-functionality.
+ pthread-functionality.
* win/tclWinThrd.c: Fixed several small typos in comments.
- Implemented Tcl_JoinThread using a platform independent
- emulation layer (see generic/tclThreadJoin.c below). Added
- 'joinLock' to serialize Tcl_CreateThread and TclpExitThread to
- prevent a race for joinable threads.
+ Implemented Tcl_JoinThread using a platform independent emulation
+ layer (see generic/tclThreadJoin.c below). Added 'joinLock' to
+ serialize Tcl_CreateThread and TclpExitThread to prevent a race for
+ joinable threads.
* mac/tclMacThrd.c: Implemented Tcl_JoinThread using a platform
- independent emulation layer (see generic/tclThreadJoin.c
- below). Due to the cooperative nature of threading on this
- platform the race mentioned above is not present.
+ independent emulation layer (see generic/tclThreadJoin.c below). Due
+ to the cooperative nature of threading on this platform the race
+ mentioned above is not present.
- * generic/tclThreadJoin.c: New file. Contains a platform
- independent emulation layer helping in the implementation of
- joinable threads for the win and mac platforms.
+ * generic/tclThreadJoin.c: New file. Contains a platform independent
+ emulation layer helping in the implementation of joinable threads for
+ the win and mac platforms.
* generic/tclInt.h: Added declarations for TclJoinThread,
- TclRememberJoinableThread and TclSignalExitThread. These
- procedures define the API of the emulation layer for joinable
- threads (see generic/tclThreadJoin.c above).
+ TclRememberJoinableThread and TclSignalExitThread. These procedures
+ define the API of the emulation layer for joinable threads (see
+ generic/tclThreadJoin.c above).
* win/Makefile.in:
* win/makefile.vc: Added generic/tclTheadJoin.o to the rules.
- * mac/: I don't know to which file generic/tclTheadJoin.o has to
- be added to so that it compiles. Sorry.
+ * mac/: I don't know to which file generic/tclTheadJoin.o has to be
+ added to so that it compiles. Sorry.
- * unix/tclUnixChan.c: #ifdef'd the thread-local list of file
- channels as it prevents us from transfering channels. To restore
- this we may need an extended interface to drivers in the
- future. Target: 9.0. Found while testing the new transfer of
- channels. The information in this list for a channel was left
- behind and then crashed the system during finalization.
+ * unix/tclUnixChan.c: #ifdef'd the thread-local list of file channels
+ as it prevents us from transfering channels. To restore this we may
+ need an extended interface to drivers in the future. Target:
+ 9.0. Found while testing the new transfer of channels. The information
+ in this list for a channel was left behind and then crashed the system
+ during finalization.
* generic/tclThreadTest.c: Added -joinable flag to 'testthread
- create'. Added subcommand 'testthread join'.
+ create'. Added subcommand 'testthread join'.
* doc/CrtChannel.3: Added documentation for Tcl_IsChannelRegistered,
- Tcl_IsChannelShared, Tcl_CutChannel, Tcl_SpliceChannel,
- Tcl_IsChannelExisting and Tcl_ClearChannelHandlers.
+ Tcl_IsChannelShared, Tcl_CutChannel, Tcl_SpliceChannel,
+ Tcl_IsChannelExisting and Tcl_ClearChannelHandlers.
* doc/Thread.3: Added documentation for Tcl_JoinThread.
@@ -1563,8 +1532,8 @@
2000-04-26 Eric Melski <ericm@scriptics.com>
- * doc/memory.n: Man page for Tcl "memory" command, which is
- created when TCL_MEM_DEBUG is defined at compile time.
+ * doc/memory.n: Man page for Tcl "memory" command, which is created
+ when TCL_MEM_DEBUG is defined at compile time.
* doc/TCL_MEM_DEBUG.3: Man page with overall information about
TCL_MEM_DEBUG usage.
@@ -1577,13 +1546,13 @@
* unix/mkLinks: Regen'd with new mkLinks.tcl.
* unix/mkLinks.tcl: Fixed indentation, made link setup more
- intelligent (only do one existance test per man page, instead of
- one per function).
+ intelligent (only do one existance test per man page, instead of one
+ per function).
* doc/library.n: Fixed .SH NAME macro to include each function
- documented on the page, so that mkLinks will know about the
- functions listed there, and so that the Windows help file index
- will get set up correctly [Bug: 1898, 5273].
+ documented on the page, so that mkLinks will know about the functions
+ listed there, and so that the Windows help file index will get set up
+ correctly [Bug: 1898, 5273].
2000-04-26 Jeff Hobbs <hobbs@scriptics.com>
@@ -1613,42 +1582,41 @@
2000-04-25 Eric Melski <ericm@scriptics.com>
- * unix/mkLinks:
+ * unix/mkLinks:
* doc/AddErrInfo.3: Added information about Tcl_LogCommandInfo
[Bug: 1818].
2000-04-24 Eric Melski <ericm@scriptics.com>
- * unix/mkLinks:
+ * unix/mkLinks:
* doc/OpenFileChnl.3: Added man entry for Tcl_Ungets [Bug: 1834].
- * unix/mkLinks:
+ * unix/mkLinks:
* doc/SourceRCFile.3: Man page for Tcl_SourceRCFile [Bug: 1833].
- * unix/mkLinks:
+ * unix/mkLinks:
* doc/ParseCmd.3: Added documentation for Tcl_ParseVar [Bug: 1828].
2000-04-24 Jeff Hobbs <hobbs@scriptics.com>
* unix/tclUnixNotfy.c (Tcl_FinalizeNotifier, NotifierThreadProc):
- added write of 'q' into triggerPipe for notifier in threaded case,
- so that Tcl doesn't hang when children are still running [Bug: 4139]
+ added write of 'q' into triggerPipe for notifier in threaded case, so
+ that Tcl doesn't hang when children are still running [Bug: 4139]
* unix/tclUnixThrd.c (Tcl_MutexLock): minor comment fixes.
2000-04-23 Jim Ingham <jingham@cygnus.com>
These changes make some error handling marginally better for Mac
- sockets. It is still somewhat flakey, however.
-
- * mac/tclMacSock.c (TcpClose): Add timeouts to the close - these
- don't seem to be honored, however.
- Use a separate PB for the release, since an async connect socket
- will still be using the original buffer.
- Make sure TCPRelease returns noErr before freeing the recvBuff.
- If the call returns an error, then the buffer is not right.
- * mac/tclMacSock.c (CreateSocket): Add timeouts to the async
- create. These don't seem to trigger, however. Sigh...
+ sockets. It is still somewhat flakey, however.
+
+ * mac/tclMacSock.c (TcpClose): Add timeouts to the close - these don't
+ seem to be honored, however. Use a separate PB for the release, since
+ an async connect socket will still be using the original buffer. Make
+ sure TCPRelease returns noErr before freeing the recvBuff. If the call
+ returns an error, then the buffer is not right.
+ * mac/tclMacSock.c (CreateSocket): Add timeouts to the async create.
+ These don't seem to trigger, however. Sigh...
* mac/tclMacSock.c (WaitForSocketEvent): If an TCP_ASYNC_CONNECT
socket errors out, then return EWOULDBLOCK & error out.
* mac/tclMacSock.c (NotifyRoutine): Added a NotifyRoutine for
@@ -1662,20 +1630,20 @@
2000-04-21 Sandeep Tamhankar <sandeep@scriptics.com>
* library/http2.1/http.tcl: Fixed a newly introduced bug where if
- there's a -command callback and something goes wrong, geturl threw
- an exception, called the callback, and unset the token. I changed
- it so that it will not call the callback when throwing an
- exception (so the caller only finds out about a given error from
- one place). Also, fixed http::ncode so that it actually gives you
- back the http return code (i.e. 200, 404, etc.) instead of the
- first digit of the version of HTTP being used (i.e. 1).
+ there's a -command callback and something goes wrong, geturl threw an
+ exception, called the callback, and unset the token. I changed it so
+ that it will not call the callback when throwing an exception (so the
+ caller only finds out about a given error from one place). Also,
+ fixed http::ncode so that it actually gives you back the http return
+ code (i.e. 200, 404, etc.) instead of the first digit of the version
+ of HTTP being used (i.e. 1).
2000-04-21 Brent Welch <welch@scriptics.com>
* library/http2.1/http.tcl: More thrashing with the "server closes
- without reading post data" scenario. Reverted to the previous
- filevent configuratiuon, which seems to work better with small
- amounts of post data.
+ without reading post data" scenario. Reverted to the previous filevent
+ configuratiuon, which seems to work better with small amounts of post
+ data.
2000-04-20 Jeff Hobbs <hobbs@scriptics.com>
@@ -1688,15 +1656,15 @@
* library/dde1.1/pkgIndex.tcl:
* library/reg1.0/pkgIndex.tcl:
* win/tclWinChan.c:
- * win/tclWinThrd.c: converted CRLF to LF the */tcl.hpj.in files
- were not converted, as it confuses hcw locally. [Bug: 5096]
+ * win/tclWinThrd.c: converted CRLF to LF the */tcl.hpj.in files were
+ not converted, as it confuses hcw locally. [Bug: 5096]
* win/Makefile.in: expanded cleanup target for help files
* doc/Thread.3: minor macro cleanup
- * generic/tclFileName.c (SplitUnixPath): added support for QNX
- node ids.
+ * generic/tclFileName.c (SplitUnixPath): added support for QNX node
+ ids.
2000-04-18 Jeff Hobbs <hobbs@scriptics.com>
@@ -1716,9 +1684,8 @@
* unix/Makefile.in: added install-strip target; bindir, libdir,
mandir, includedir vars; tclLoadDyld.c target [Bug: 2527]
- * unix/tclUnixChan.c (CreateSocket): force a socket back into
- blocking mode (default state) after a -async connect succeeds.
- [Bug: 4388]
+ * unix/tclUnixChan.c (CreateSocket): force a socket back into blocking
+ mode (default state) after a -async connect succeeds. [Bug: 4388]
* generic/tclEvent.c (TclInitSubsystems): Moved tclLibraryPath to
thread-local storage to prevent thread-related race condition.
@@ -1732,23 +1699,23 @@
* win/Makefile.in:
* win/tcl.rc:
* win/tclsh.rc:
- * win/tclsh.ico: Modified copyright dates in Windows resource
- files. Added an icon for tclsh.exe.
+ * win/tclsh.ico: Modified copyright dates in Windows resource files.
+ Added an icon for tclsh.exe.
2000-04-17 Brent Welch <welch@scriptics.com>
* generic/tcl.h, generic/tclThreadTest.c, unix/tclUnixThrd.c,
- win/tclWinThread.c, mac/tclMacThread.c:
- Added Tcl_CreateThreadType and TCL_RETURN_THREAD_TYPE
- macros for declaring the NewThread callback proc.
+ * win/tclWinThread.c, mac/tclMacThread.c: Added Tcl_CreateThreadType
+ and TCL_RETURN_THREAD_TYPE macros for declaring the NewThread callback
+ proc.
2000-04-14 Jeff Hobbs <hobbs@scriptics.com>
* unix/tclUnixChan.c (TtyParseMode): Only allow setting mark/space
parity on platforms that support it [Bug: 5089]
- * generic/tclBasic.c (Tcl_GetVersion): adjusted use of major/minor
- to not conflict with global decl on some systems [Bug: 2882]
+ * generic/tclBasic.c (Tcl_GetVersion): adjusted use of major/minor to
+ not conflict with global decl on some systems [Bug: 2882]
* doc/AppInit.3:
* doc/Async.3:
@@ -1798,17 +1765,17 @@
* generic/tcl.h: Fixed Tcl_CreateThread declaration.
* library/tcltest1.0/tcltest.tcl: Fixed the "mainThread"
initialization to work with either testthread or the thread extension
- * unix/tclUnixThrd.c: Fixed compiler warning when compiling
- with -DTCL_THREADS
+ * unix/tclUnixThrd.c: Fixed compiler warning when compiling with
+ -DTCL_THREADS
2000-04-10 Eric Melski <ericm@scriptics.com>
- * win/tclWinPipe.c (TclpCreateTempFile): Added conversion of
- contents string from UTF to native encoding [Bug: 4030].
+ * win/tclWinPipe.c (TclpCreateTempFile): Added conversion of contents
+ string from UTF to native encoding [Bug: 4030].
* tests/regexp.test: Added tests for infinite looping in [regexp
-all].
-
+
* generic/tclCmdMZ.c: Fixed infinite loop bug with [regexp -all]
[Bug: 4981].
@@ -1817,14 +1784,13 @@
2000-04-09 Brent Welch <welch@scriptics.com>
- * lib/httpd2.1/http.tcl: Worked on the "server closes before
- reading post data" case, which unfortunately causes different
- error cases on Solaris, which can read the reply, and Linux
- and Windows, which cannot read anything. This is all in the
- loop-back case - client and server on the same host. Also
- unified the error handling so the "ioerror" status goes away
- and errors are reflected in a more uniform way. Updated the
- man page to document the behavior.
+ * lib/httpd2.1/http.tcl: Worked on the "server closes before reading
+ post data" case, which unfortunately causes different error cases on
+ Solaris, which can read the reply, and Linux and Windows, which cannot
+ read anything. This is all in the loop-back case - client and server
+ on the same host. Also unified the error handling so the "ioerror"
+ status goes away and errors are reflected in a more uniform way.
+ Updated the man page to document the behavior.
2000-04-09 Jeff Hobbs <hobbs@scriptics.com>
@@ -1834,70 +1800,68 @@
* generic/tclBasic.c (Tcl_SetCommandInfo): comment fix
* unix/tclUnixThrd.c (Tcl_CreateThread): moved TCL_THREADS ifdef
- inside of func as it is declared for non-threads builds as well.
- In the non-threads case, it always returns TCL_ERROR (couldn't
- create thread).
+ inside of func as it is declared for non-threads builds as well. In
+ the non-threads case, it always returns TCL_ERROR (couldn't create
+ thread).
2000-04-08 Andreas Kupries <a.kupries@westend.com>
* Overall change: Definition of a public API for the creation of
- new threads.
+ new threads.
* generic/tclInt.h (line 1802f): Removed the definition of
'TclpThreadCreate'. (line 793f) Removed the definition of
'Tcl_ThreadCreateProc'.
* generic/tcl.h (line 388f): Readded the definition of
- 'Tcl_ThreadCreateProc'. Added Win32 stuff send in by David
- Graveraux <davygrvy@bigfoot.com> to that too (__stdcall,
- ...). Added macros for the default stacksize and allowed flags.
+ 'Tcl_ThreadCreateProc'. Added Win32 stuff send in by David Graveraux
+ <davygrvy@bigfoot.com> to that too (__stdcall, ...). Added macros for
+ the default stacksize and allowed flags.
* generic/tcl.decls (line 1356f): Added definition of
- 'Tcl_CreateThread', slot 393 of the stub table. Two new
- arguments in the public API, for stacksize and flags.
+ 'Tcl_CreateThread', slot 393 of the stub table. Two new arguments in
+ the public API, for stacksize and flags.
* win/tclWinThrd.c:
* mac/tclMacThrd.c: Renamed TclpThreadCreate to Tcl_CreateThread,
- added handling of the stacksize. Flags are currently ignored.
+ added handling of the stacksize. Flags are currently ignored.
- * unix/tclUnixThrd.c: See above, but handles joinable
- flag. Ignores the specified stacksize if the macro
- HAVE_PTHREAD_ATTR_SETSTACKSIZE is not defined.
+ * unix/tclUnixThrd.c: See above, but handles joinable flag. Ignores
+ the specified stacksize if the macro HAVE_PTHREAD_ATTR_SETSTACKSIZE is
+ not defined.
* generic/tclThreadTest.c (line 363): See below.
- * unix/tclUnixNotfy.c (line 210): Adapted to the changes
- above. Uses default stacksize and no flags now.
+ * unix/tclUnixNotfy.c (line 210): Adapted to the changes above. Uses
+ default stacksize and no flags now.
* unic/tcl.m4 (line 382f): Added a check for
- 'pthread_attr_setstacksize' to detect platforms not implementing
- this feature of pthreads. If it is implemented, configure will
- define the macro HAVE_PTHREAD_ATTR_SETSTACKSIZE (See
- unix/tclUnixThrd.c too).
+ 'pthread_attr_setstacksize' to detect platforms not implementing this
+ feature of pthreads. If it is implemented, configure will define the
+ macro HAVE_PTHREAD_ATTR_SETSTACKSIZE (See unix/tclUnixThrd.c too).
- * doc/Thread.3: Added Tcl_CreateThread and its arguments to the
- list of described functions. Removed stuff about not providing a
- public C-API for thread-creation.
+ * doc/Thread.3: Added Tcl_CreateThread and its arguments to the list
+ of described functions. Removed stuff about not providing a public
+ C-API for thread-creation.
2000-04-07 Jeff Hobbs <hobbs@scriptics.com>
- * doc/binary.n: clarified docs on sign extension in binary scan
- [Bug: 3466]
+ * doc/binary.n: clarified docs on sign extension in binary scan [Bug:
+ 3466]
* library/tcltest1.0/tcltest.tcl (initConstraints): removed win32s
references (no longer supported)
- * tests/fCmd.test: marked test 8.1 knownBug because it is
- dangerous on poorly configured systems [Bug: 3881]
- and added 8.2 to keep essence of 8.1 tested.
+ * tests/fCmd.test: marked test 8.1 knownBug because it is dangerous on
+ poorly configured systems [Bug: 3881] and added 8.2 to keep essence of
+ 8.1 tested.
2000-04-05 Andreas Kupries <a.kupries@westend.com>
- * generic/tclIO.c (Tcl_UnstackChannel, line 1831): Forcing
- interest mask to the correct value after an unstack and
- re-initialization of the notifier via the watchProc. Without this
- the first fileevent after an unstack will come through and be
- processed, but no more. [Bug: ??].
+ * generic/tclIO.c (Tcl_UnstackChannel, line 1831): Forcing interest
+ mask to the correct value after an unstack and re-initialization of
+ the notifier via the watchProc. Without this the first fileevent after
+ an unstack will come through and be processed, but no more. [Bug: ??].
2000-03-04 Brent Welch <welch@scriptics.com>
@@ -1909,18 +1873,18 @@
2000-03-29 Sandeep Tamhankar <sandeep@scriptics.com>
- * library/http2.1/http.tcl: For the -querychannel option,
- fconfigure the socket to be binary so that we don't translate
- anything while reading the data. This is because we determine the
- content length of the data on the channel by using seek (to the end
- of the file) and tell on the file handle, and we need the
- content-length to match the amount of data actually sent, and
- translation can affect the number of bytes posted.
+ * library/http2.1/http.tcl: For the -querychannel option, fconfigure
+ the socket to be binary so that we don't translate anything while
+ reading the data. This is because we determine the content length of
+ the data on the channel by using seek (to the end of the file) and
+ tell on the file handle, and we need the content-length to match the
+ amount of data actually sent, and translation can affect the number of
+ bytes posted.
2000-04-03 Andreas Kupries <a.kupries@westend.com>
- * Overall change: Definition of public API's for the finalization
- of conditions and mutexes. [Bug: 4199].
+ * Overall change: Definition of public API's for the finalization of
+ conditions and mutexes. [Bug: 4199].
* generic/tclInt.h: Removed definitions of TclFinalizeMutex and
TclFinalizeCondition.
@@ -1928,27 +1892,26 @@
* generic/tcl.decls: Added declarations of Tcl_MutexFinalize and
Tcl_ConditionFinalize.
- * generic/tclThread.c: Renamed TclFinalizeMutex to
- Tcl_MutexFinalize. Renamed TclFinalizeCondition to
- Tcl_ConditionFinalize.
+ * generic/tclThread.c: Renamed TclFinalizeMutex to Tcl_MutexFinalize.
+ Renamed TclFinalizeCondition to Tcl_ConditionFinalize.
* generic/tclNotify.c: Changed usage of TclFinalizeMutex to
Tcl_MutexFinalize.
- * unix/tclUnixNotfy.c:
+ * unix/tclUnixNotfy.c:
* generic/tclThreadTest.c: Changed usages of TclFinalizeCondition to
Tcl_ConditionFinalize.
* generic/tcl.h: Added empty macros for Tcl_MutexFinalize and
- Tcl_ConditionFinalize, to be used when the core is compiled
- without threads.
+ Tcl_ConditionFinalize, to be used when the core is compiled without
+ threads.
* doc/Thread.3: Added description the new API's.
2000-04-03 Jeff Hobbs <hobbs@scriptics.com>
- * generic/tclCmdIL.c (InfoVarsCmd): checked for non-NULL procPtr
- to prevent itcl info override crash [Bug: 4064]
+ * generic/tclCmdIL.c (InfoVarsCmd): checked for non-NULL procPtr to
+ prevent itcl info override crash [Bug: 4064]
* tests/foreach.test:
* tests/namespace.test:
@@ -1967,27 +1930,27 @@
2000-04-03 Eric Melski <ericm@scriptics.com>
- * unix/tclUnixFCmd.c (SetGroupAttribute):
- * unix/tclUnixFCmd.c (SetOwnerAttribute): Added (uid_t) and (gid_t)
+ * unix/tclUnixFCmd.c (SetGroupAttribute):
+ * unix/tclUnixFCmd.c (SetOwnerAttribute): Added (uid_t) and (gid_t)
casts to avoid compiler warnings.
2000-03-31 Eric Melski <ericm@scriptics.com>
* generic/tclGet.c (Tcl_GetDouble): Added additional conditions to
- error test (previously only errno was checked, but the return
- value of strtod() should be checked as well). [Bug: 4118].
+ error test (previously only errno was checked, but the return value of
+ strtod() should be checked as well). [Bug: 4118]
- * tests/exec.test: Added test for proper conversion of UTF data
- when used with "<< $dataWithUTF" on exec's.
+ * tests/exec.test: Added test for proper conversion of UTF data when
+ used with "<< $dataWithUTF" on exec's.
* unix/tclUnixPipe.c (TclpCreateTempFile): Added
- Tcl_UtfToExternalDString call, so that if there is UTF content in
- the string it will be properly converted to the system encoding
- before being written [Bug: 4030].
+ Tcl_UtfToExternalDString call, so that if there is UTF content in the
+ string it will be properly converted to the system encoding before
+ being written [Bug: 4030].
(TclpCreateTempFile): Added a check on the return value of tmpnam;
some systems (Linux, for example) will start to return NULL after
- tmpnam has been called TMP_MAX times; not checking for this can
- have bad results (overwriting temp files, core dumps, etc.)
+ tmpnam has been called TMP_MAX times; not checking for this can have
+ bad results (overwriting temp files, core dumps, etc.)
2000-03-30 Jeff Hobbs <hobbs@scriptics.com>
@@ -2000,8 +1963,8 @@
* win/tclWin32Dll.c: removed TclWinSynchSpawn (vestige of Win32s
support).
- * win/tclWinReg.c: made use of TclWinGetPlatformId instead of
- getting info again
+ * win/tclWinReg.c: made use of TclWinGetPlatformId instead of getting
+ info again
* win/tclWinPort.h:
* win/Makefile.in:
@@ -2019,16 +1982,15 @@
2000-03-29 Sandeep Tamhankar <sandeep@scriptics.com>
- * library/http2.1/http.tcl: Removed an unnecessary fileevent
- statement from the error processing part of the Write method.
- Also, fixed two potential memory leaks in wait and reset, in which
- the state array wasn't being unset before throwing an exception.
- Prior to this version, Brent checked in a fix to catch a
- fileevent statement that was sometimes causing a stack trace when
- geturl was called with -timeout. I believe Brent's fix is
- necessary because TLS closes bad sockets for secure connections,
- and the fileevent was trying to act on a socket that no longer
- existed.
+ * library/http2.1/http.tcl: Removed an unnecessary fileevent statement
+ from the error processing part of the Write method. Also, fixed two
+ potential memory leaks in wait and reset, in which the state array
+ wasn't being unset before throwing an exception. Prior to this
+ version, Brent checked in a fix to catch a fileevent statement that
+ was sometimes causing a stack trace when geturl was called with
+ -timeout. I believe Brent's fix is necessary because TLS closes bad
+ sockets for secure connections, and the fileevent was trying to act on
+ a socket that no longer existed.
2000-03-27 Jeff Hobbs <hobbs@scriptics.com>
@@ -2036,118 +1998,115 @@
* tests/namespace.test:
* generic/tclNamesp.c (Tcl_Export): added a uniq'ing test to the
- export list so only one instance of each export pattern would
- exist in the list.
+ export list so only one instance of each export pattern would exist in
+ the list.
- * generic/tclExecute.c (TclExecuteByteCode): optimized case for
- the empty string in ==/!= comparisons
+ * generic/tclExecute.c (TclExecuteByteCode): optimized case for the
+ empty string in ==/!= comparisons
2000-03-27 Eric Melski <ericm@scriptics.com>
- * unix/tclUnixChan.c: Added (off_t) type casts in lseek() call
- [Bug: 4409].
+ * unix/tclUnixChan.c: Added (off_t) type casts in lseek() call [Bug:
+ 4409].
- * unix/tclLoadAout.c:
- * unix/tclUnixPipe.c: Added (off_t) type casts in lseek() calls
- [Bug: 4410].
+ * unix/tclLoadAout.c:
+ * unix/tclUnixPipe.c: Added (off_t) type casts in lseek() calls [Bug:
+ 4410].
2000-03-22 Sandeep Tamhankar <sandeep@scriptics.com>
- * library/http2.1/http.tcl: Fixed a bug where string query data
- that was bigger than queryblocksize would get duplicate characters
- at block boundaries.
+ * library/http2.1/http.tcl: Fixed a bug where string query data that
+ was bigger than queryblocksize would get duplicate characters at block
+ boundaries.
2000-03-22 Sandeep Tamhankar <sandeep@scriptics.com>
- * library/http2.1/http.tcl: Fixed bug 4463, where we were getting
- a stack trace if we tried to publish a project to a good host but
- a port where there was no server listening. It turned out the
- problem was a stray fileevent that needed to be cleared. Also,
- fixed a bug where http::code could stack trace if called on a bad
- token (one which didn't represent a successful geturl) by adding
- an http element to the state array in geturl.
+ * library/http2.1/http.tcl: Fixed bug 4463, where we were getting a
+ stack trace if we tried to publish a project to a good host but a port
+ where there was no server listening. It turned out the problem was a
+ stray fileevent that needed to be cleared. Also, fixed a bug where
+ http::code could stack trace if called on a bad token (one which
+ didn't represent a successful geturl) by adding an http element to the
+ state array in geturl.
2000-03-21 Eric Melski <ericm@scriptics.com>
* tests/clock.test: Modified some tests that were not robust with
- respect to the time zone in which they were run and were thus
- failing.
+ respect to the time zone in which they were run and were thus failing.
- * doc/clock.n: Clarified meaning of -gmt with respect to -base
- when used with [clock scan] (-gmt does not affect the
- interpretation of -base).
+ * doc/clock.n: Clarified meaning of -gmt with respect to -base when
+ used with [clock scan] (-gmt does not affect the interpretation of
+ -base).
2000-03-19 Sandeep Tamhankar <sandeep@scriptics.com>
- * library/http2.1/http.tcl: geturl used to throw an exception when
- the connection failed; I accidentally returned a token with the
- error info, breaking backwards compatibility. I changed it back
- to throwing an exception, but unsetting the state array first
- (thus still eliminating the original memory leak problem).
+ * library/http2.1/http.tcl: geturl used to throw an exception when the
+ connection failed; I accidentally returned a token with the error
+ info, breaking backwards compatibility. I changed it back to throwing
+ an exception, but unsetting the state array first (thus still
+ eliminating the original memory leak problem).
2000-03-19 Sandeep Tamhankar <sandeep@scriptics.com>
* library/http2.1/http.tcl: Added -querychannel option and altered
some of Brent's modifications to allow asynchronous posts (via
- -command). Also modified -queryprogress so that it calls the
- query callback as <callback> <token> <total size> <current size>
- to be consistent with -progress. Added -queryblocksize option
- with default 8192 bytes for post blocksize. Fixed a bunch of
- potential memory leaks for the case when geturl receives bad args
- or can't open a socket, etc. Overall, the package really rocks
- now.
+ -command). Also modified -queryprogress so that it calls the query
+ callback as <callback> <token> <total size> <current size> to be
+ consistent with -progress. Added -queryblocksize option with default
+ 8192 bytes for post blocksize. Fixed a bunch of potential memory leaks
+ for the case when geturl receives bad args or can't open a socket,
+ etc. Overall, the package really rocks now.
* doc/http.n: Added -queryblocksize, -querychannel, and
- -queryprogress. Also, changed the description of -blocksize,
- which states that the -progress callback will be called for each
- block, to now qualify that with an "if -progress is specified".
+ -queryprogress. Also, changed the description of -blocksize, which
+ states that the -progress callback will be called for each block, to
+ now qualify that with an "if -progress is specified".
* tests/http.test: Added a querychannel test for synchronous and
asynchronous posts, altered the queryprogress test such that the
- callback conforms to the -progress format. Also, had to use the
- -queryblocksize option to do the post 16K at a time to match
- Brent's expected results (and to test that -queryblocksize works).
+ callback conforms to the -progress format. Also, had to use the
+ -queryblocksize option to do the post 16K at a time to match Brent's
+ expected results (and to test that -queryblocksize works).
2000-03-15 Brent Welch <welch@scriptics.com>
* library/http2.1/http.tcl: Added -queryprogress callback to
- http::geturl and also changed it so that writing the post data
- is event driven if the queryprogress callback or a timeout is given.
- This allows a timeout to occur when writing lots of post data.
- The queryprogress callback is called after each block of query
- data is posted. It has the same signature as the -progress callback.
+ http::geturl and also changed it so that writing the post data is
+ event driven if the queryprogress callback or a timeout is given.
+ This allows a timeout to occur when writing lots of post data. The
+ queryprogress callback is called after each block of query data is
+ posted. It has the same signature as the -progress callback.
2000-03-06 Eric Melski <ericm@scriptics.com>
* library/package.tcl: Applied patch from Bug: 2570; rather than
setting geometry of slave interp to 0x0 when Tk was loaded, it now
- does "wm withdraw .". Both remove the main window from the
- display, but the former caused some internal structures to get
- initialized to zero, which caused crashes with some extensions.
+ does "wm withdraw .". Both remove the main window from the display,
+ but the former caused some internal structures to get initialized to
+ zero, which caused crashes with some extensions.
2000-03-02 Jeff Hobbs <hobbs@scriptics.com>
- * library/package.tcl (tclPkgUnknown): extended to allow
- recognizes changes in the auto_path while sourcing in other
- pkgIndex.tcl files
+ * library/package.tcl (tclPkgUnknown): extended to allow recognizes
+ changes in the auto_path while sourcing in other pkgIndex.tcl files
* doc/FindExec.3: fixed doc for declaration of Tcl_FindExecutable
[Bug: 4275]
- * generic/tclFileName.c (Tcl_TranslateFileName): Applied patch
- from Newman to significantly speedup file split/join on Windows
- (replaces regexp with custom parser). [Bug: 2867]
+ * generic/tclFileName.c (Tcl_TranslateFileName): Applied patch from
+ Newman to significantly speedup file split/join on Windows (replaces
+ regexp with custom parser). [Bug: 2867]
- * win/README.binary: change mailing lists from @consortium.org
- to @scriptics.com [Bug: 4173]
+ * win/README.binary: change mailing lists from @consortium.org to
+ @scriptics.com [Bug: 4173]
2000-02-28 Eric Melski <ericm@scriptics.com>
* tests/clock.test: Added test for ISO bases < 100000
* generic/tclDate.c: (generated on Solaris)
- * generic/tclGetDate.y: Changed condition for deciding if a number
- is an ISO 8601 base from number >= 100000 to numberOfDigits >= 6.
+ * generic/tclGetDate.y: Changed condition for deciding if a number is
+ an ISO 8601 base from number >= 100000 to numberOfDigits >= 6.
Previously it would fail to recognize 000000 as an ISO base.
2000-02-14 Eric Melski <ericm@scriptics.com>
@@ -2166,42 +2125,41 @@
* doc/load.n: added notes about dll load errors on Windows
* unix/README:
- * unix/Makefile.in (dist): removed porting.notes and porting.old
- from distribution and CVS. The information was very outdated. Now
- refer to http://dev.scriptics.com/services/support/platforms.html
+ * unix/Makefile.in (dist): removed porting.notes and porting.old from
+ distribution and CVS. The information was very outdated. Now refer to
+ http://dev.scriptics.com/services/support/platforms.html
* tests/unixInit.test: fixed japanese LANG encoding test [Bug: 3549]
* unix/configure.in:
- * unix/tcl.m4: correct CFLAG_WARNING setting,
- fixed gcc config for AIX,
- added -export-dynamic to LDFLAGS for FreeBSD-3+ [Bug: 2998]
+ * unix/tcl.m4: correct CFLAG_WARNING setting, fixed gcc config for
+ AIX, added -export-dynamic to LDFLAGS for FreeBSD-3+ [Bug: 2998]
* win/tclWinLoad.c (TclpLoadFile): improved error message for load
failures, could perhaps be even more intelligent.
2000-02-09 Jim Ingham <jingham@cygnus.com>
- * mac/tclMacSock.c: Don't panic when you get an error closing an async
- socket. This doesn't seem to hurt anything, and we return the error so
+ * mac/tclMacSock.c: Don't panic when you get an error closing an async
+ socket. This doesn't seem to hurt anything, and we return the error so
the caller can do the right thing.
New Files:
* mac/MW_TclHeader.h:
* mac/MW_TclTestHeader.h:
* mac/MW_TclTestHeader.pch:
- * mac/MW_TclAppleScriptHeader.h: More convenient to use .h prefix files
- in the preference panels...
+ * mac/MW_TclAppleScriptHeader.h: More convenient to use .h prefix
+ files in the preference panels...
The above are curtesy of Daniel Steffen (steffen@math.mq.edu.au)
2000-02-08 Eric Melski <ericm@scriptics.com>
* tests/clock.test: Added tests for "next monthname" constructs.
- * generic/tclDate.c:
+ * generic/tclDate.c:
* generic/tclGetDate.y (Message): Added a grammar rule for "next
- monthname" so that we can handle "next january" and similar
- constructs (bug #4146).
+ monthname" so that we can handle "next january" and similar constructs
+ (bug #4146).
2000-02-08 Jeff Hobbs <hobbs@scriptics.com>
@@ -2228,35 +2186,35 @@
* tests/httpold.test: changed test script to source in the httpd
server procs from httpd instead of having its own set.
- * tests/httpd: improved query support in test httpd to handle fix
- in http.tcl. [Bug: 4089 change 2000-02-01]
+ * tests/httpd: improved query support in test httpd to handle fix in
+ http.tcl. [Bug: 4089 change 2000-02-01]
- * unix/README: fixed notes about --enable-shared and add note
- about --disable-shared.
+ * unix/README: fixed notes about --enable-shared and add note about
+ --disable-shared.
2000-02-07 Eric Melski <ericm@scriptics.com>
- * tests/package.test:
- * library/tclIndex:
+ * tests/package.test:
+ * library/tclIndex:
* library/package.tcl: Renamed ::package namespace to ::pkg.
2000-02-03 Eric Melski <ericm@scriptics.com>
* doc/Package.n:
- * doc/packagens.n: Renamed Package.n -> packagens.n because Windows
+ * doc/packagens.n: Renamed Package.n -> packagens.n because Windows
can't deal with case-sensitive names.
2000-02-02 Jeff Hobbs <hobbs@scriptics.com>
* tests/regexp.test: added tests for -all and -inline switches
* doc/regexp.n: added docs for -all and -inline switches
- * generic/tclCmdMZ.c (Tcl_RegexpObjCmd): added extra comments for
- new -all and -inline switches to regexp command
+ * generic/tclCmdMZ.c (Tcl_RegexpObjCmd): added extra comments for new
+ -all and -inline switches to regexp command
2000-02-01 Eric Melski <ericm@scriptics.com>
- * library/init.tcl: Applied patch from rfe 1734 regarding
- auto_load errors not setting error message and errorInfo properly.
+ * library/init.tcl: Applied patch from rfe 1734 regarding auto_load
+ errors not setting error message and errorInfo properly.
2000-02-01 Jeff Hobbs <hobbs@scriptics.com>
@@ -2271,13 +2229,13 @@
2000-01-31 Eric Melski <ericm@scriptics.com>
- * tests/package.test:
- * library/tclIndex:
- * library/package.tcl: Added ::package namespace and
- ::package::create function.
+ * tests/package.test:
+ * library/tclIndex:
+ * library/package.tcl: Added ::package namespace and ::package::create
+ function.
- * library/init.tcl: Fixed problem with auto_load and determining
- if commands were loaded.
+ * library/init.tcl: Fixed problem with auto_load and determining if
+ commands were loaded.
* library/auto.tcl: "Fixed" issues with $ in files to be auto indexed.
@@ -2289,66 +2247,66 @@
2000-01-28 Eric Melski <ericm@scriptics.com>
- * tests/pkg/magicchar2.tcl:
+ * tests/pkg/magicchar2.tcl:
* tests/autoMkindex.test: Test for auto loader fix (bug #2480).
* library/init.tcl: auto_load was using [info commands $name] to
- determine if a given command was available; if the command name
- had * or [] it, this would fail because info commands uses
- glob-style matching. This is fixed. (Bug #2480).
+ determine if a given command was available; if the command name had *
+ or [] it, this would fail because info commands uses glob-style
+ matching. This is fixed. (Bug #2480).
- * tests/pkg/spacename.tcl:
+ * tests/pkg/spacename.tcl:
* tests/pkgMkIndex.test: Tests for fix for bug #2360.
- * library/package.tcl: Fixed to extract only the first element of
- the list returned by auto_qualify (bug #2360).
+ * library/package.tcl: Fixed to extract only the first element of the
+ list returned by auto_qualify (bug #2360).
- * tests/pkg/magicchar.tcl:
+ * tests/pkg/magicchar.tcl:
* tests/autoMkindex.test: Test for fix for bug #2611.
* library/auto.tcl: Fixed the regular expression that performs $
- escaping before sourcing a file to index. It was erroneously
- adding \ escapes even to $'s that were already escaped,
- effectively "un-escaping" those $'s. (bug #2611).
+ escaping before sourcing a file to index. It was erroneously adding \
+ escapes even to $'s that were already escaped, effectively
+ "un-escaping" those $'s. (bug #2611).
2000-01-27 Eric Melski <ericm@scriptics.com>
- * tests/autoMkindex.test:
- * library/auto.tcl: Applied patch (with slight modification) from
- bug #2701: auto_mkIndex uses platform dependent file paths.
- Added test for fix.
+ * tests/autoMkindex.test:
+ * library/auto.tcl: Applied patch (with slight modification) from bug
+ #2701: auto_mkIndex uses platform dependent file paths. Added test for
+ fix.
2000-01-27 Jennifer Hom <jenn@scriptics.com>
* library/tcltest1.0/tcltest.tcl: Changed NormalizePath to
- normalizePath and exported it as a public proc. This proc
- creates an absolute path given the name of the variable containing
- the path to modify. The path is modified in place.
+ normalizePath and exported it as a public proc. This proc creates an
+ absolute path given the name of the variable containing the path to
+ modify. The path is modified in place.
* library/tcltest1.0/pkgIndex.tcl: Added normalizePath.
* tests/all.tcl: Changed code to use normalizePath.
2000-01-27 Eric Melski <ericm@scriptics.com>
* tests/pkg/samename.tcl: test file for bug #1983
-
- * tests/pkgMkIndex.test:
- * doc/pkgMkIndex.n:
+
+ * tests/pkgMkIndex.test:
+ * doc/pkgMkIndex.n:
* library/package.tcl: Per rfe #4097, optimized creation of direct
- load packages to bypass computing the list of commands added by
- the new package. Also made direct loading the default, and added
- a -lazy option.
+ load packages to bypass computing the list of commands added by the
+ new package. Also made direct loading the default, and added a -lazy
+ option.
Fixed bug #1983, dealing with pkg_mkIndex incorrectly handling
- situations with two procs by the same name but in different
- namespaces (ie, foo::baz and bar::baz).
+ situations with two procs by the same name but in different namespaces
+ (ie, foo::baz and bar::baz).
2000-01-26 Eric Melski <ericm@scriptics.com>
* generic/tclNamesp.c: Undid fix for #956, which broke backwards
compatibility.
- * doc/variable.n:
- * doc/trace.n:
- * doc/namespace.n:
+ * doc/variable.n:
+ * doc/trace.n:
+ * doc/namespace.n:
* doc/info.n: Added further information about differences between
"namespace which" and "info exists".
@@ -2357,18 +2315,18 @@
2000-01-25 Jeff Hobbs <hobbs@scriptics.com>
- * unix/tcl.m4: modified EXTRA_CFLAGS to add -DHAVE_TZSET for
- OSF1-V* and ULTRIX-4.* when not using gcc. Also added higher min
- stack size for OSF1-V* when building with threads. [Bug: 4063]
+ * unix/tcl.m4: modified EXTRA_CFLAGS to add -DHAVE_TZSET for OSF1-V*
+ and ULTRIX-4.* when not using gcc. Also added higher min stack size
+ for OSF1-V* when building with threads. [Bug: 4063]
* generic/tclClock.c (FormatClock): inlined resultPtr, as it
conflicted with var creation for HAVE_TZSET #def [Bug: 4063]
- * generic/tclCmdIL.c (Tcl_LsortObjCmd): fixed potential leak
- when calling lsort -command with bad command [Bug: 4067]
+ * generic/tclCmdIL.c (Tcl_LsortObjCmd): fixed potential leak when
+ calling lsort -command with bad command [Bug: 4067]
- * generic/tclFileName.c (Tcl_JoinPath): added support for special
- QNX node id prefixes in pathnames [Bug: 4053]
+ * generic/tclFileName.c (Tcl_JoinPath): added support for special QNX
+ node id prefixes in pathnames [Bug: 4053]
* doc/ListObj.3: clarified Tcl_ListObjGetElements docs [Bug: 4080]
@@ -2378,18 +2336,18 @@
2000-01-23 Jeff Hobbs <hobbs@scriptics.com>
- * library/init.tcl (auto_execok): added 'start' to list of
- recognized built-in commands for COMSPEC on NT. [Bug: 2858]
+ * library/init.tcl (auto_execok): added 'start' to list of recognized
+ built-in commands for COMSPEC on NT. [Bug: 2858]
* unix/tclUnixPort.h: moved include of <utime.h> lower since some
systems (UTS) require sys/types.h to be included first [Bug: 4031]
- * unix/tclUnixChan.c (CreateSocketAddress): changed comparison
- with -1 to 0xFFFFFFFF, to ensure 32 bit comparison even on 64 bit
- systems. [Bug: 3878]
+ * unix/tclUnixChan.c (CreateSocketAddress): changed comparison with -1
+ to 0xFFFFFFFF, to ensure 32 bit comparison even on 64 bit systems.
+ [Bug: 3878]
- * generic/tclFileName.c: improved guessing of path separator
- for the Mac. (Darley)
+ * generic/tclFileName.c: improved guessing of path separator for the
+ Mac. (Darley)
* generic/tclInt.h:
* generic/tcl.decls: moved Tcl_ProcObjCmd to stubs table [Bug: 3827]
@@ -2398,7 +2356,7 @@
2000-01-21 Eric Melski <ericm@scriptics.com>
- * unix/mkLinks:
+ * unix/mkLinks:
* doc/GetHostName.3: Man page for Tcl_GetHostName (bug #1817).
* doc/lreplace.n: Corrected man page with respect to treatment of
@@ -2412,24 +2370,24 @@
* generic/tclNamesp.c: Added check for undefined variables in
NamespaceWhichCmd (bug #956).
- * tests/var.test: Added tests for corrected variable behavior
- (bug #981).
+ * tests/var.test: Added tests for corrected variable behavior (bug
+ #981).
* doc/upvar.n: Expanded explanation of upvar behavior with respect to
- variable traces. (bugs 3917 1433 2110).
+ variable traces. (bugs 3917 1433 2110).
* generic/tclVar.c: Changed behavior of variable command when name
refers to an element in an array (ie, "variable foo(x)") to always
- return an error, regardless of existance of that element in the
- array (now behavior is consistant with docs too) (bug #981).
+ return an error, regardless of existance of that element in the array
+ (now behavior is consistant with docs too) (bug #981).
2000-01-20 Jeff Hobbs <hobbs@scriptics.com>
- * generic/tclCmdIL.c (InfoBodyCmd): made [info body] return a
- string if the body has been bytecompiled.
+ * generic/tclCmdIL.c (InfoBodyCmd): made [info body] return a string
+ if the body has been bytecompiled.
* generic/tclBasic.c (Tcl_EvalObjEx): added pedantic check for
- originating proc body of bytecompiled code, #def'd out as the
- change for [info body] should make it unnecessary
+ originating proc body of bytecompiled code, #def'd out as the change
+ for [info body] should make it unnecessary
* unix/tclUnixNotfy.c (Tcl_InitNotifier): added cast for tsdPtr
@@ -2442,20 +2400,19 @@
* doc/vwait.n: added notes about requirement for vwait var being
globally scoped [Bug: 3329]
- * library/word.tcl: changed tcl_(non)wordchars settings to use
- new unicode regexp char class escapes instead of char sequences
+ * library/word.tcl: changed tcl_(non)wordchars settings to use new
+ unicode regexp char class escapes instead of char sequences
2000-01-14 Eric Melski <ericm@scriptics.com>
* tests/var.test: Added a test for the array multiple delete
protection in Tcl_UnsetVar2.
- * generic/tclVar.c: Added protection in Tcl_UnsetVar2 against
- attempts to multiply delete arrays when unsetting them (bug
- #3453). This could happen if there was an unset trace on an array
- element and the trace proc made a global or upvar link to the
- array, and then the array was unset at the global level. See the
- bug reference for more information.
+ * generic/tclVar.c: Added protection in Tcl_UnsetVar2 against attempts
+ to multiply delete arrays when unsetting them (bug #3453). This could
+ happen if there was an unset trace on an array element and the trace
+ proc made a global or upvar link to the array, and then the array was
+ unset at the global level. See the bug reference for more information.
* unix/tclUnixTime.c: New clock format format.
@@ -2480,14 +2437,14 @@
2000-01-13 Eric Melski <ericm@scriptics.com>
- * tests/cmdIL.test: Added tests for lsort -dictionary with
- characters that occur between Z and a in ASCII.
+ * tests/cmdIL.test: Added tests for lsort -dictionary with characters
+ that occur between Z and a in ASCII.
* generic/tclCmdIL.c: Modified DictionaryCompare function (used by
lsort -dictionary) to do upper/lower case equivalency before doing
- character comparisons, instead of after. This fixes bug #1357, in
- which lsort -dictionary [list ` AA c CC] and lsort -dictionary
- [list AA c ` CC] gave different (and both wrong) results.
+ character comparisons, instead of after. This fixes bug #1357, in
+ which lsort -dictionary [list ` AA c CC] and lsort -dictionary [list
+ AA c ` CC] gave different (and both wrong) results.
2000-01-12 Eric Melski <ericm@scriptics.com>
@@ -2497,23 +2454,22 @@
* doc/tests/clock.test: Added numerous tests for clock scan.
- * doc/generic/tclGetDate.y: Fixed some shift/reduce conflicts in
- clock grammar.
+ * doc/generic/tclGetDate.y: Fixed some shift/reduce conflicts in clock
+ grammar.
- * doc/doc/clock.n: Added documentation for new supported clock
- scan formats and additional explanation of daylight savings time
- correction algorithm.
+ * doc/doc/clock.n: Added documentation for new supported clock scan
+ formats and additional explanation of daylight savings time correction
+ algorithm.
2000-01-12 Jeff Hobbs <hobbs@scriptics.com>
* doc/file.n:
* tests/unixFCmd.test:
- * unix/tclUnixFCmd.c: added support for symbolic permissions
- setting in SetPermissionsAttribute (file attr $file -perm ...)
- [Bug: 3970]
+ * unix/tclUnixFCmd.c: added support for symbolic permissions setting
+ in SetPermissionsAttribute (file attr $file -perm ...) [Bug: 3970]
- * generic/tclClock.c: fixed support for 64bit handling of clock
- values [Bug: 1806]
+ * generic/tclClock.c: fixed support for 64bit handling of clock values
+ [Bug: 1806]
* generic/tclThreadTest.c: upped a buffer size to hold double
@@ -2526,20 +2482,20 @@
* tests/expr.test:
* unix/Makefile.in:
* unix/configure.in:
- * unix/tcl.m4: recognize strtod bug on Tru64 v5.0 [Bug: 3378]
- and added tests to prevent unnecessary chmod +x in sources while
+ * unix/tcl.m4: recognize strtod bug on Tru64 v5.0 [Bug: 3378] and
+ added tests to prevent unnecessary chmod +x in sources while
installing, as well as more intelligent setsockopt/gethostbyname
checks [Bug: 3366, 3389]
- * unix/tclUnixThrd.c: added compile time support (through use of
- the TCL_THREAD_STACK_MIN define) for increasing the default stack
- size for a thread. [Bug: 3797, 1966]
+ * unix/tclUnixThrd.c: added compile time support (through use of the
+ TCL_THREAD_STACK_MIN define) for increasing the default stack size for
+ a thread. [Bug: 3797, 1966]
2000-01-11 Eric Melski <ericm@scriptics.com>
- * generic/tclGetDate.y: Added comments for the Convert function.
- Added a fix for daylight savings time handling for relative time
- spans of days, weeks or fortnights. (bug 3441, 3868).
+ * generic/tclGetDate.y: Added comments for the Convert function. Added
+ a fix for daylight savings time handling for relative time spans of
+ days, weeks or fortnights. (bug 3441, 3868).
* generic/tclDate.c: Fixed compiler warning issues.
@@ -2548,8 +2504,8 @@
* compat/waitpid.c: use pid_t type instead of int [Bug: 3999]
* tests/utf.test: fixed test that allowed \8 as octal value
- * generic/tclUtf.c: changed Tcl_UtfBackslash to not allow
- non-octal digits (8,9) in \ooo substs. [Bug: 3975]
+ * generic/tclUtf.c: changed Tcl_UtfBackslash to not allow non-octal
+ digits (8,9) in \ooo substs. [Bug: 3975]
* generic/tcl.h: noted need to change win/tcl.m4 and
tools/tclSplash.bmp for minor version changes
@@ -2579,5 +2535,5 @@
2000-01-07 Eric Melski <ericm@scriptics.com>
* generic/tclClock.c: Changed switch in Tcl_ClockObjCmd to use
- enumerated values instead of constants. (ie, COMMAND_SCAN instead
- of 3).
+ enumerated values instead of constants. (ie, COMMAND_SCAN instead of
+ 3).
diff --git a/ChangeLog.2001 b/ChangeLog.2001
index 2c8b4d7..6579651 100644
--- a/ChangeLog.2001
+++ b/ChangeLog.2001
@@ -1,20 +1,20 @@
2001-12-28 Jeff Hobbs <jeffh@ActiveState.com>
- * library/init.tcl: make sure env(COMSPEC) on Windows is executed
- with the right case, as it may otherwise fail inexplicably.
+ * library/init.tcl: make sure env(COMSPEC) on Windows is executed with
+ the right case, as it may otherwise fail inexplicably.
2001-12-28 Don Porter <dgp@users.sourceforge.net>
- * generic/tclCkalloc.c (MemoryCmd, TclFinalizeMemorySubsystem):
- Added the [memory onexit] command, intended to replace [checkmem].
+ * generic/tclCkalloc.c (MemoryCmd, TclFinalizeMemorySubsystem): Added
+ the [memory onexit] command, intended to replace [checkmem].
- * doc/DumpActiveMemory.3:
+ * doc/DumpActiveMemory.3:
* doc/memory.n: Updated documentation for [memory] and related
- matters. [Bug 487677]
+ matters. [Bug 487677]
* mac/tclMacBOAMain.c (Tcl_Main, CheckmemCmd): Removed all the
- machinery for the [checkmem] command that is completely duplicated
- by code in generic/tclCkalloc.c.
+ machinery for the [checkmem] command that is completely duplicated by
+ code in generic/tclCkalloc.c.
* generic/tclBinary.c:
* generic/tclListObj.c:
@@ -27,12 +27,11 @@
* mac/tclMacInit.c:
* mac/tclMacTclCode.r: synced up tclInit features to unix/win:
- implemented TclSetPreInitScript support, use of existing tclInit
- proc if defined, check of default encoding dir if set. Changed
- script library resource names to lowercase (i.e. same as
- corresponding files). Used Tcl_JoinPath instead of string append.
- Check that system encoding could be loaded before utf translating
- the LibraryPath.
+ implemented TclSetPreInitScript support, use of existing tclInit proc
+ if defined, check of default encoding dir if set. Changed script
+ library resource names to lowercase (i.e. same as corresponding
+ files). Used Tcl_JoinPath instead of string append. Check that system
+ encoding could be loaded before utf translating the LibraryPath.
* mac/tclMacApplication.r:
* mac/tclMacLibrary.r:
* mac/tclMacOSA.r:
@@ -41,147 +40,138 @@
2001-12-21 Mo DeJong <mdejong@users.sourceforge.net>
* unix/tcl.m4 (SC_PATH_TCLCONFIG, SC_PATH_TKCONFIG):
- Search for config file using exec_prefix instead of
- prefix when no --with-tcl or --with-tk argument is used. [Bug 492418]
+ Search for config file using exec_prefix instead of prefix when no
+ --with-tcl or --with-tk argument is used. [Bug 492418]
2001-12-21 Daniel Steffen <das@users.sourceforge.net>
- * unix/tcl.m4: fixed incorrect SHLIB_LD_LIBS
- setting for MacOSX / Darwin.
+ * unix/tcl.m4: fixed incorrect SHLIB_LD_LIBS setting for MacOSX /
+ Darwin.
* unix/configure: Regen.
- * unix/mkLinks.tcl: improved case-insensitive
- filesystem support.
+ * unix/mkLinks.tcl: improved case-insensitive filesystem support.
* unix/mkLinks: Regen.
2001-12-19 Don Porter <dgp@users.sourceforge.net>
- * unix/Makefile.in (dist): corrected use of eolFix.tcl on
- working files. It should operate on distributed files. [Bug 495120]
+ * unix/Makefile.in (dist): corrected use of eolFix.tcl on working
+ files. It should operate on distributed files. [Bug 495120]
2001-12-19 David Gravereaux <davygrvy@pobox.com>
- * tools/tcl.wse.in: Fix for #495120. tcl.wse.in was
- stored in cvs with improper <eol>. This resulted in
- corrupted <eol> when checked-out on translating CVS
- clients such as windows (CRCRLF) and mac (CRCR).
+ * tools/tcl.wse.in: Fix for [Bug 495120]. tcl.wse.in was stored in cvs
+ with improper <eol>. This resulted in corrupted <eol> when checked-out
+ on translating CVS clients such as windows (CRCRLF) and mac (CRCR).
2001-12-19 Mo DeJong <mdejong@users.sourceforge.net>
* unix/configure:
- * unix/tcl.m4 (SC_CONFIG_CFLAGS): Update
- SunOS 5.[0-6] target so that correct linker
- options are passed to gcc or ld. [Tk Bug 220863]
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): Update SunOS 5.[0-6] target so that
+ correct linker options are passed to gcc or ld. [Tk Bug 220863]
2001-12-19 Mo DeJong <mdejong@users.sourceforge.net>
- * unix/README: Update to account for changes
- in the unix/dltest directory, the way autoconf
- is run, and the new "make shell" target.
+ * unix/README: Update to account for changes in the unix/dltest
+ directory, the way autoconf is run, and the new "make shell" target.
2001-12-19 Mo DeJong <mdejong@users.sourceforge.net>
- * unix/Makefile.in: Rename dltest to dlpkgs to
- fix problem where lib files were not getting
- built because dltest/ directory already existed.
+ * unix/Makefile.in: Rename dltest to dlpkgs to fix problem where lib
+ files were not getting built because dltest/ directory already
+ existed.
2001-12-19 Jeff Hobbs <jeffh@ActiveState.com>
- * win/tclWinSerial.c (SerialCheckProc): corrected time
- calculations to be unsigned. (schroedter)
+ * win/tclWinSerial.c (SerialCheckProc): corrected time calculations to
+ be unsigned. (schroedter)
2001-12-18 Mo DeJong <mdejong@users.sourceforge.net>
- * unix/Makefile.in: Define new dltest target that
- simply does a cd to dltest/ before running make.
- There is no need for the separate configure
- script that was previously being used.
+ * unix/Makefile.in: Define new dltest target that simply does a cd to
+ dltest/ before running make. There is no need for the separate
+ configure script that was previously being used.
* unix/configure: Regen.
* unix/configure.in: Subst into dltest/Makefile.
- * unix/dltest/Makefile.in: Define LIBS using
- DL_LIBS, LIBS, and MATH_LIBS variables instead
- of TCL_LIBS variable from tclConfig.sh.
- * unix/dltest/README: Update readme to account for new
- configure free implementation.
+ * unix/dltest/Makefile.in: Define LIBS using DL_LIBS, LIBS, and
+ MATH_LIBS variables instead of TCL_LIBS variable from tclConfig.sh.
+ * unix/dltest/README: Update readme to account for new configure free
+ implementation.
* unix/dltest/configure: Removed.
* unix/dltest/configure.in: Removed.
2001-12-18 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * generic/tcl.h (TCL_STUB_MAGIC): Added cast to force type to be
- an int and get rid of a persistent and pointless warning with
- SunPro compiler.
+ * generic/tcl.h (TCL_STUB_MAGIC): Added cast to force type to be an
+ int and get rid of a persistent and pointless warning with SunPro
+ compiler.
- * generic/tclCkalloc.c (Tcl_AttemptDbCkalloc,Tcl_AttemptDbCkrealloc):
+ * generic/tclCkalloc.c (Tcl_AttemptDbCkalloc,Tcl_AttemptDbCkrealloc):
* generic/tcl.decls (Tcl_AttemptDbCkalloc,Tcl_AttemptDbCkrealloc):
- Made the file parameters to these functions into CONST char *,
- like they always should have been to match the other Tcl*Db* API
- functions.
+ Made the file parameters to these functions into CONST char *, like
+ they always should have been to match the other Tcl*Db* API functions.
-2001-12-17 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+2001-12-17 Andreas Kupries <andreas_kupries@users.sourceforge.net>
- * Applied #219311 on behalf of Rolf Schroedter
- <schroedter@users.sourceforge.net> to prevent fcopy on serial
- ports from flooding the event queue.
+ * Applied [Bug 219311] on behalf of Rolf Schroedter
+ <schroedter@users.sourceforge.net> to prevent fcopy on serial ports
+ from flooding the event queue.
2001-12-11 Miguel Sofer <msofer@users.sourceforge.net>
* doc/CrtInterp.3:
- * generic/tclBasic.c: docs and comments corrections [Bug 493412]
- Bug & patch by Don Porter.
+ * generic/tclBasic.c: docs and comments corrections. [Bug 493412]
+ Bug & patch by Don Porter.
2001-12-14 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * win/tclWinNotify.c (Tcl_FinalizeNotifier): Stop Tcl on Windows
- from crashing when shutdown from a non-Tcl thread. Fixes Bug
- #217982 [orig. 5804] reported by Hugh Vu and Gene Leache. I'm
- not convinced that the shutdown process is right even with this,
- but it was definitely wrong without...
+ * win/tclWinNotify.c (Tcl_FinalizeNotifier): Stop Tcl on Windows from
+ crashing when shutdown from a non-Tcl thread. Fixes [Bug 217982]
+ [orig. 5804] reported by Hugh Vu and Gene Leache. I'm not convinced
+ that the shutdown process is right even with this, but it was
+ definitely wrong without...
-2001-12-13 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+2001-12-13 Andreas Kupries <andreas_kupries@users.sourceforge.net>
- * win/tclWinSock.c (TcpGetOptionProc): Fix for tcl bug item
- #478565 reported by an unknown person. Bypasses all calls to
- "gethostbyaddr" for address "0.0.0.0" to prevent delays on
- Win/NT.
+ * win/tclWinSock.c (TcpGetOptionProc): Fix for [Bug 478565] reported
+ by an unknown person. Bypasses all calls to "gethostbyaddr" for
+ address "0.0.0.0" to prevent delays on Win/NT.
2001-12-12 Jeff Hobbs <jeffh@ActiveState.com>
- * doc/Preserve.3: doc'd TCL_DYNAMIC use. [Patch #483989] (porter)
+ * doc/Preserve.3: doc'd TCL_DYNAMIC use. [Patch 483989] (porter)
-2001-12-12 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+2001-12-12 Andreas Kupries <andreas_kupries@users.sourceforge.net>
- * generic/tclIO.c (Tcl_GetsObj): Applied patch for bug #491341 as
- provided by Don Porter <dgp@users.sourceforge.net>. Fixes the
- assumption of having an empty Tcl_Obj to work with.
+ * generic/tclIO.c (Tcl_GetsObj): Applied patch for [Bug 491341] as
+ provided by Don Porter <dgp@users.sourceforge.net>. Fixes the
+ assumption of having an empty Tcl_Obj to work with.
2001-12-11 Miguel Sofer <msofer@users.sourceforge.net>
* generic/tclCompCmds.c:
* generic/tclCompile.c:
- * generic/tclExecute.c: consistency patch, to make all
- instructions that pop a variable number of Tcl_Obj's off the
- execution stack take the number of popped objects as first
- operand. Modified *only* the new instructions
- INST_LIST_INDEX_MULTI and INST_LSET_FLAT, so this has no effect
- on bytecodes generated up to tcl8.4a3 inclusive.
+ * generic/tclExecute.c: consistency patch, to make all instructions
+ that pop a variable number of Tcl_Obj's off the execution stack take
+ the number of popped objects as first operand. Modified *only* the new
+ instructions INST_LIST_INDEX_MULTI and INST_LSET_FLAT, so this has no
+ effect on bytecodes generated up to tcl8.4a3 inclusive.
- * generic/tclExecute.c: fix debug messages in INST_LSET_LIST.
+ * generic/tclExecute.c: fix debug messages in INST_LSET_LIST.
* generic/tclCompCmds.c (TclCompileLindexCmd):
- * generic/tclCompExpr.c (CompileMathFuncCall): removed the last
- two overestimates of the necessary stack depth for bytecodes in
- the fix of [Bug 483611].
+ * generic/tclCompExpr.c (CompileMathFuncCall): removed the last two
+ overestimates of the necessary stack depth for bytecodes in the fix of
+ [Bug 483611]
-2001-12-10 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+2001-12-10 Andreas Kupries <andreas_kupries@users.sourceforge.net>
- * unix/tclUnixPipe.c (TclpCreateProcess): Applied Don Porter's
- patch fixing bug #437489.
+ * unix/tclUnixPipe.c (TclpCreateProcess): Applied Don Porter's patch
+ fixing [Bug 437489].
2001-12-10 Miguel Sofer <msofer@users.sourceforge.net>
* generic/tclEvent.c:
- * tests/event.test: fix background error reporting in the absence
- of a bgerror proc [Bug 219142].
+ * tests/event.test: fix background error reporting in the absence of a
+ bgerror proc [Bug 219142].
2001-12-10 Don Porter <dgp@users.sourceforge.net>
@@ -198,7 +188,7 @@
* doc/Utf.3:
* doc/file.n:
* doc/tclsh.1: Several typo and formatting corrections discovered
- during conversion to TMML. Thanks to Joe English. [Patch 490514]
+ during conversion to TMML. Thanks to Joe English. [Patch 490514]
* unix/mkLinks: 'make mklinks'
2001-12-10 Miguel Sofer <msofer@users.sourceforge.net>
@@ -208,14 +198,14 @@
* generic/tclCompile.c:
* generic/tclCompile.h:
* generic/tclExecute.c:
- * generic/tclProc.c: fixed the calculation of the maximal stack
- depth required by bytecodes [Bug 483611].
+ * generic/tclProc.c: fixed the calculation of the maximal stack depth
+ required by bytecodes. [Bug 483611]
2001-12-07 Miguel Sofer <msofer@users.sourceforge.net>
- * generic/tclVar.c:
+ * generic/tclVar.c:
* tests/trace.test: restored consistency in refCount accounting by
- array traces [Bug #4484339], submitted by Don Porter.
+ array traces [Bug 4484339], submitted by Don Porter.
2001-12-06 Donal K. Fellows <fellowsd@cs.man.ac.uk>
@@ -225,19 +215,19 @@
* generic/tclParseExpr.c (ParsePrimaryExpr): Rewrote to give even
better syntax errors in the fairly common case of an identifier
without decorations by guessing based on the currently available
- functions. Also made messages consistent between memdebug and
- ordinary builds.
+ functions. Also made messages consistent between memdebug and ordinary
+ builds.
2001-12-05 Miguel Sofer <msofer@users.sourceforge.net>
- * generic/tclVar.c:
- * tests/trace.test: new algorithm for [array get], safe when there
- are traces that modify the array [Bug #449893].
+ * generic/tclVar.c:
+ * tests/trace.test: new algorithm for [array get], safe when there are
+ traces that modify the array. [Bug 449893]
2001-12-04 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * tests/compExpr-old.test, tests/compExpr.test, tests/compile.test:
- * tests/expr-old.test, tests/expr.test, tests/for.test:
+ * tests/compExpr-old.test, tests/compExpr.test, tests/compile.test:
+ * tests/expr-old.test, tests/expr.test, tests/for.test:
* tests/while.test, tests/if.test: Rewrite to handle more specific
syntax errors.
* tests/parseExpr.test: Rewrite to get rid of dup test numbers and
@@ -246,26 +236,25 @@
argument to help explain what the syntax error is.
(Tcl_ParseExpr, ParseCondExpr, ParsePrimaryExpr): Added detail
messages.
- (UNKNOWN_CHAR): New lexeme for characters that are always illegal
- in expressions outside strings.
+ (UNKNOWN_CHAR): New lexeme for characters that are always illegal in
+ expressions outside strings.
2001-12-03 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * doc/expr.n: Various documentation improvements in relation to
- the function calls. Includes fix for Bug #487704 submitted by
- Devin Eyre.
+ * doc/expr.n: Various documentation improvements in relation to the
+ function calls. Includes fix for [Bug 487704] submitted by Devin Eyre.
2001-12-03 David Gravereaux <davygrvy@pobox.com>
* win/makefile.vc: Some install target bugs repaired along with
$(TCLSTUBLIB) added to the dependencies rather than implicit through
- the dde and reg extensions which don't happen to always require it
- for some build types.
+ the dde and reg extensions which don't happen to always require it for
+ some build types.
2001-11-30 Miguel Sofer <msofer@users.sourceforge.net>
- * generic/tclVar.c: Tcl_Preserve'ing VarTrace structures to avoid
- memory corruption. Patch for [Bug: 484334] provided by Don Porter
+ * generic/tclVar.c: Tcl_Preserve'ing VarTrace structures to avoid
+ memory corruption. Patch for [Bug 484334] provided by Don Porter
2001-11-29 Miguel Sofer <msofer@users.sourceforge.net>
@@ -275,16 +264,15 @@
2001-11-29 Miguel Sofer <msofer@users.sourceforge.net>
* tests/namespace.test: added namespace-41.2, a simpler test for
- [Bug: 231259]
+ [Bug 231259]
2001-11-29 Donal K. Fellows <fellowsd@cs.man.ac.uk>
* generic/tclBinary.c (BINARY_SCAN_MAX_CACHE, Tcl_BinaryObjCmd,
- ScanNumber): Added caching scheme to reduce number of object
- allocations when doing scans of large repetitive binary strings.
- See comments in file for reasoning behind implementation.
- Suggested by Miguel Sofer in Patch #429916, but independently
- implemented.
+ (ScanNumber): Added caching scheme to reduce number of object
+ allocations when doing scans of large repetitive binary strings. See
+ comments in file for reasoning behind implementation. Suggested by
+ Miguel Sofer in [Patch 429916], but independently implemented.
2001-11-28 Donal K. Fellows <fellowsd@cs.man.ac.uk>
@@ -293,8 +281,8 @@
2001-11-27 D. Richard Hipp <drh@hwaci.com>
- * win/tclWinFCmd.c: Fix a coredump in the filename normalizer
- code for Win95/98.
+ * win/tclWinFCmd.c: Fix a coredump in the filename normalizer code for
+ Win95/98.
2001-11-27 David Gravereaux <davygrvy@pobox.com>
@@ -305,37 +293,36 @@
2001-11-27 Donal K. Fellows <fellowsd@cs.man.ac.uk>
* tests/cmdAH.test (cmdAH-24.2): Made test less sensitive to OS
- preemption, but perfection isn't practical [Bug 463189, reported
- by Don Porter.]
+ preemption, but perfection isn't practical. [Bug 463189, reported by
+ Don Porter]
- * tests/switch.test (switch-9.*): Added tests to exercise more of
- the argument checking. (switch-7.2,switch-7.3): Test changed
- behaviour slightly.
- * generic/tclCmdMZ.c (Tcl_SwitchObjCmd): Reworked argument parsing
- to be stricter about what it accepts. This should make uses of
- the [switch] command be more maintainable. [Bug 475397, reported
- by Don Porter.]
+ * tests/switch.test (switch-9.*): Added tests to exercise more of the
+ argument checking. (switch-7.2,switch-7.3): Test changed behaviour
+ slightly.
+ * generic/tclCmdMZ.c (Tcl_SwitchObjCmd): Reworked argument parsing to
+ be stricter about what it accepts. This should make uses of the
+ [switch] command be more maintainable. [Bug 475397, reported by Don
+ Porter]
2001-11-26 Don Porter <dgp@users.sourceforge.net>
- * generic/tclIntPlatDecls.h: 'make genstubs' after changes
- in 2001-11-23 commit from Daniel Steffen.
+ * generic/tclIntPlatDecls.h: 'make genstubs' after changes in
+ 2001-11-23 commit from Daniel Steffen.
2001-11-24 Mo DeJong <mdejong@users.sourceforge.net>
- * unix/Makefile.in: Add comments to better describe
- TCL_EXE and when it should be available.
- * win/Makefile.in: Add TCL_EXE variable to be used
- by rules like `make genstubs`. Don't set TCL_LIBRARY
- before running `make genstubs` since we will be running
- with a tclsh from the PATH not the one we build.
+ * unix/Makefile.in: Add comments to better describe TCL_EXE and when
+ it should be available.
+ * win/Makefile.in: Add TCL_EXE variable to be used by rules like `make
+ genstubs`. Don't set TCL_LIBRARY before running `make genstubs` since
+ we will be running with a tclsh from the PATH not the one we build.
2001-11-24 Mo DeJong <mdejong@users.sourceforge.net>
* win/configure: Regen.
- * win/tcl.m4 (SC_CONFIG_CFLAGS): Add comctl32.lib
- to wish link libs. This change was originally added
- to Tk on 2001-11-09 but was not committed to Tcl.
+ * win/tcl.m4 (SC_CONFIG_CFLAGS): Add comctl32.lib to wish link libs.
+ This change was originally added to Tk on 2001-11-09 but was not
+ committed to Tcl.
2001-11-23 Daniel Steffen <das@users.sourceforge.net>
@@ -346,17 +333,17 @@
* unix/mkLinks.tcl:
* unix/tclLoadDyld.c:
* unix/tclMtherr.c: Mac OSX support: build system, dynamic code loading
- and support for case-insensitive filesystems in mkLinks (patch #435258)
+ and support for case-insensitive filesystems in mkLinks. [Patch 435258]
2001-11-23 Daniel Steffen <das@users.sourceforge.net>
- Up-port to 8.4 of mac code changes for 8.3.3 & various new
- changes for 8.4, some already backported to 8.3.4 (patch #435658)
+ Up-port to 8.4 of mac code changes for 8.3.3 & various new changes for
+ 8.4, some already backported to 8.3.4. [Patch 435658]
* generic/tclObj.c: added #include to fix missing prototype errors
* generic/tcl.h: MAC_TCL: addition of ConditionalMacros.h and use of
- DLLIMPORT and DLLEXPORT like on other platforms. ( => no longer need
+ DLLIMPORT and DLLEXPORT like on other platforms. ( => no longer need
the .exp files and can remove use of #pragma export that never worked
well)
removed line continuation in #if clause as this breaks the mac
@@ -364,10 +351,10 @@
* mac/tclMacFile.c: fixed bug in permission checking code
- * mac/tclMacLoad.c: corrected utf8 handling, comparison of
- package names to code fragment names changed to only match on the
- length of package name, this allows for fragment names with version
- numbers appended
+ * mac/tclMacLoad.c: corrected utf8 handling, comparison of package
+ names to code fragment names changed to only match on the length of
+ package name, this allows for fragment names with version numbers
+ appended.
* mac/tclMacInt.h:
* generic/tclInt.h:
@@ -402,7 +389,7 @@
platforms, removed use of #pragma export.
* mac/tcltkMacBuildSupport.sea.hqx: new archive of mac build support
- files & suggested build environment directory hierarchy:
+ files & suggested build environment directory hierarchy:
'Building MacTclTk' & 'CW Pro6 changes' readme's.
projects for MoreFiles 1.5.2 static & shared libraries.
project & sources for 'pseudoCarbonSupport', see below.
@@ -430,13 +417,13 @@
Highly experimental "pseudoCarbon" support for Tcl only on OS 8/9:
binaries in "Build:(Carbon):" link against CarbonLib instead of
InterfaceLib, however the actual code has not been carbonized! i.e. it
- will not run on OSX and may not even run properly with CarbonLib.
+ will not run on OSX and may not even run properly with CarbonLib.
This should in principle allow you to build & test OS9 CFM Carbon
- binaries that need to link with Tcl.shlb. On OSX you can use the
+ binaries that need to link with Tcl.shlb. On OSX you can use the
native Tcl.framework, but you have to build a MachO binary as there
is no CFM glue lib for Tcl.framework.
- the library pseudoCarbonSupport.shlb manually loads the symbols
- from InterfaceLib that are not in CarbonLib but are needed by the
+ the library pseudoCarbonSupport.shlb manually loads the symbols from
+ InterfaceLib that are not in CarbonLib but are needed by the
uncarbonized code in Tcl.shlb and TclShell.
* generic/tclMain.c: MAC_TCL: workaround for broken/non-standard isatty
@@ -461,10 +448,10 @@
strings; updated version strings to standard usage; added support for
'(Support Libraries)' subfolder for shared runtime libraries in
unmerged binaries; commented out demo setting of "Tcl Environment
- Variables"; reorganized resources among these files to avoid
- multiple copies in applications and shared libraries, the script
- libraries are now no longer duplicated in Tclsh but are only included
- in the resources of Tcl.shlb.
+ Variables"; reorganized resources among these files to avoid multiple
+ copies in applications and shared libraries, the script libraries are
+ now no longer duplicated in Tclsh but are only included in the
+ resources of Tcl.shlb.
* mac/tclMacChan.c:
* mac/tclMacSock.c: cast for *BlockMode
@@ -497,52 +484,51 @@
* mac/tclMacUnix.c: added missing (Tcl_Obj ***) cast to
Tcl_ListObjGetElements call
- * mac/tclMacAlloc.c: modernized TclpSysAlloc() to use temporary
- memory instead of system heap memory when available (MacOS
- >= 7.5 and possibly earlier, use of system heap has been
- discouraged for a long time and has many disadvantages, e.g. memory
- isn't paged out, and errors can very easily bring the system down);
- fixed crashing bug in TclpSysRealloc() and CleanUpExitProc() where
- memory was being accessed after having been deallocated; fixed
- memory leak in (de)allocation code (for every block ever allocated
- with TclpSysAlloc, a Ptr was leaked), if temporary memory is
- available, don't track allocated memory, instead use
- RecoverHandle() to get Handle from Ptr, otherwise use doubly linked
- list to correctly track memory and free all allocated memory; added
- new option for ConfigureMemory: MEMORY_DONT_USE_TEMPMEM, disables
- use of temporary memory even when it would be available, only
- necessary when writing e.g. a driver (using tcl??); increased
- fraction of application heap reserved for OS routines to 512K
-
- * compat/strftime.c:
+ * mac/tclMacAlloc.c: modernized TclpSysAlloc() to use temporary memory
+ instead of system heap memory when available (MacOS >= 7.5 and
+ possibly earlier, use of system heap has been discouraged for a long
+ time and has many disadvantages, e.g. memory isn't paged out, and
+ errors can very easily bring the system down); fixed crashing bug in
+ TclpSysRealloc() and CleanUpExitProc() where memory was being accessed
+ after having been deallocated; fixed memory leak in (de)allocation
+ code (for every block ever allocated with TclpSysAlloc, a Ptr was
+ leaked), if temporary memory is available, don't track allocated
+ memory, instead use RecoverHandle() to get Handle from Ptr, otherwise
+ use doubly linked list to correctly track memory and free all
+ allocated memory; added new option for ConfigureMemory:
+ MEMORY_DONT_USE_TEMPMEM, disables use of temporary memory even when it
+ would be available, only necessary when writing e.g. a driver (using
+ tcl??); increased fraction of application heap reserved for OS
+ routines to 512K
+
+ * compat/strftime.c:
* mac/tclMacTime.c:
* mac/tclMacPort.h:
- * generic/tclInt.decls:
+ * generic/tclInt.decls:
* generic/tclIntPlatDecls.h:
- * generic/tclStubInit.c: timezone support for mac via
- TclpGetTZName() like on windows, using an inverse timezone table
- adapted from tclDate.c to map gmtoffset in seconds gotten from
- the MacOS APIs to a timezone string, as there is no good way to get
- this info from MacOS. I had to make up some unusual timezones and
- arbitrarily decide on the most standard of the multiple choices
- available for every timezone.
-
- * generic/tclExecute.c: workaround for a MSL bug/misfeature: for
- very small floats, MSL can return errno ERANGE but a
- non-zero value ( < LDBL_MIN however)
-
- * mac/tclMacAppInit.c: support for WASTE text library using
- temporary memory, setting has no effect if WASTE is not used.
-
+ * generic/tclStubInit.c: timezone support for mac via TclpGetTZName()
+ like on windows, using an inverse timezone table adapted from
+ tclDate.c to map gmtoffset in seconds gotten from the MacOS APIs to a
+ timezone string, as there is no good way to get this info from MacOS.
+ I had to make up some unusual timezones and arbitrarily decide on the
+ most standard of the multiple choices available for every timezone.
+
+ * generic/tclExecute.c: workaround for a MSL bug/misfeature: for very
+ small floats, MSL can return errno ERANGE but a non-zero value (<
+ LDBL_MIN however)
+
+ * mac/tclMacAppInit.c: support for WASTE text library using temporary
+ memory, setting has no effect if WASTE is not used.
+
* mac/tclMacPanic.c: removed duplicate code from generic/tclPanic.c
and added that file to projects instead.
* tests/all.tcl: set tcltest::singleProcess 1 as multiple processes
are not available on the mac.
-
- * tests/cmdAH.test: access time not available on the mac, skip the
+
+ * tests/cmdAH.test: access time not available on the mac, skip the
atime touch test
-
+
* tests/appendComp.test:
* tests/cmdMZ.test:
* tests/compile.test:
@@ -550,20 +536,20 @@
* tests/fileName.test:
* tests/lset.test:
* tests/namespace.test:
- * tests/tcltest.test: added missing cleanups/tests/catches that
- caused tests to fail on the mac.
+ * tests/tcltest.test: added missing cleanups/tests/catches that caused
+ tests to fail on the mac.
* doc/tclvars.n: doc bug, env(PWD) should be env(HOME) [Bug 463834]
-
+
2001-11-21 Don Porter <dgp@users.sourceforge.net>
* tests/trace.test (trace-8.8): Corrected test for Bug 219393.
* generic/tclBasic.c (Tcl_DeleteCommandFromToken,CallCommandTraces):
* generic/tclCmdMZ>c (Tcl_UntraceCommand): Added Tcl_Preserve and
- Tcl_Release calls to prevent deletion of CommandTrace structures
- until all callers are done using them, preventing memory corruption.
- [Bug 453805]
+ Tcl_Release calls to prevent deletion of CommandTrace structures until
+ all callers are done using them, preventing memory corruption. [Bug
+ 453805]
2001-11-20 Kevin B. Kenny <kennykb@users.sourceforge.net>
@@ -575,7 +561,7 @@
* generic/tclUtil.c (TclpGetTime):
* generic/tclTest.c (GetTimesCmd):
* generic/tclTimer.c (Tcl_CreateTimerHandler, TimerSetupProc,
- TimerCheckProc, TimerHandlerEventProc):
+ (TimerCheckProc, TimerHandlerEventProc):
* mac/tclMacNotify.c (Tcl_SetTimer):
* mac/tclMacShLib.exp (Tcl_GetTime):
* mac/tclMacTime.c (Tcl_GetTime):
@@ -586,72 +572,72 @@
* win/tclWinNotify.c (Tcl_Sleep):
* win/tclWinTest.c (TestwinclockCmd):
* win/tclWinTime.c (TclpGetSeconds, TclpGetClicks, Tcl_GetTime):
- Changed all uses of TclpGetTime to Tcl_GetTime. Added Tcl_GetTime
- to the Stubs table and the library documentation. Added a
- TclpGetTime in tclUtil.c for backward compatibility of
- extensions. [Patch #483500, TIP#73]
+ Changed all uses of TclpGetTime to Tcl_GetTime. Added Tcl_GetTime to
+ the Stubs table and the library documentation. Added a TclpGetTime in
+ tclUtil.c for backward compatibility of extensions. [Patch 483500,
+ TIP#73]
* generic/tclCmdMZ.c (Tcl_TimeObjCmd): Corrected an error in the
[time] command that caused incorrect results to be returned if the
- total duration of all iterations exceeded 2**31 microseconds.
- [Bug #478847]
+ total duration of all iterations exceeded 2**31 microseconds. [Bug
+ 478847]
* generic/tclInt.decls:
* generic/tclInt.h:
* generic/tclStubInit.h: Reran 'make genstubs'
-
+
2001-11-20 Miguel Sofer <msofer@users.sourceforge.net>
* generic/tclBasic.c
- * generic/tclCompile.h:
+ * generic/tclCompile.h:
* generic/tclExecute.c: moving all code relative to bytecodes from
tclBasic.c to tclExecute.c - the functions RecordTracebackInfo and
Tcl_ExprObj went to tclExecute.c, and new interface function was
defined (TclCompEvalObj).
- The final objective of this sequence of moves is to provide a
- clean, clear-cut interface between Tcl's core and the
- compiler/engine subsystem.
+ The final objective of this sequence of moves is to provide a clean,
+ clear-cut interface between Tcl's core and the compiler/engine
+ subsystem.
2001-11-20 Miguel Sofer <msofer@users.sourceforge.net>
* generic/tclBasic.c
- * generic/tclCompile.h:
+ * generic/tclCompile.h:
* generic/tclExecute.c: factoring out of common code in tclBasic.c
- (new function TclInterpReady defined: it resets the interp's
- result, then checks that it hasn't been deleted and that the
- nesting level is acceptable). Passed the responsibility of calling
- it to the *callers* of TclEvalObjvInternal.
+ (new function TclInterpReady defined: it resets the interp's result,
+ then checks that it hasn't been deleted and that the nesting level is
+ acceptable). Passed the responsibility of calling it to the *callers*
+ of TclEvalObjvInternal.
2001-11-20 Miguel Sofer <msofer@users.sourceforge.net>
* generic/tclBasic.c
* generic/tclExecute.c: a better variant of the previous-to-last
- commit (restoring numLevels computations). The managing of the
- levels now has to be done by the *callers* of TclEvalObjvInternal
+ commit (restoring numLevels computations). The managing of the levels
+ now has to be done by the *callers* of TclEvalObjvInternal
2001-11-20 Miguel Sofer <msofer@users.sourceforge.net>
* generic/tclExecute.c: missing variable declaration under
- TCL_COMPILE_DEBUG.
+ TCL_COMPILE_DEBUG.
2001-11-20 Miguel Sofer <msofer@users.sourceforge.net>
* generic/tclExecute.c:
- * generic/tclProc.c: restoring the computations of iPtr->numLevels
- to the original logic (previous to buggy modifs on 2001-11-16).
+ * generic/tclProc.c: restoring the computations of iPtr->numLevels to
+ the original logic (previous to buggy modifs on 2001-11-16).
2001-11-20 Jeff Hobbs <jeffh@ActiveState.com>
* tools/eolFix.tcl (new-file):
* unix/Makefile.in: added EOL correction for Windows bat files to
- dist target. [Bug #219409] (davygrvy)
+ dist target. [Bug 219409] (davygrvy)
- * unix/tclUnixInit.c (TclpSetInitialEncodings): update of patch
- from 2001-11-16 that uses the old Tcl encoding check mechanism as
- a fallback to the original. Also added a TCL_DEFAULT_ENCODING
- #define (defaults to iso8859-1). Tcl will first try setlocale and
- nl_langinfo, and if that fails, guess based on certain LANG|LC_*
- env vars. [Patch #418645]
+ * unix/tclUnixInit.c (TclpSetInitialEncodings): update of patch from
+ 2001-11-16 that uses the old Tcl encoding check mechanism as a
+ fallback to the original. Also added a TCL_DEFAULT_ENCODING #define
+ (defaults to iso8859-1). Tcl will first try setlocale and nl_langinfo,
+ and if that fails, guess based on certain LANG|LC_* env vars. [Patch
+ 418645]
2001-11-19 David Gravereaux <davygrvy@pobox.com>
@@ -667,42 +653,42 @@
* win/tclWinFCmd.c:
* win/tclWin32Dll.c:
* doc/file.n:
- * tests/winFCmd.test: improved speed of file normalization
- for Win95/98, and clarified docs on differences in file
- normalization between NT/2000 and the older operating systems.
- Added test to ensure normalization is correct.
-
+ * tests/winFCmd.test: improved speed of file normalization for
+ Win95/98, and clarified docs on differences in file normalization
+ between NT/2000 and the older operating systems. Added test to ensure
+ normalization is correct.
+
2001-11-19 Miguel Sofer <msofer@users.sourceforge.net>
* generic/tclBasic.c:
* generic/tclParse.c: Code reorganisation. Moved all evaluation
- functions from tclParse.c to tclBasic.c, so that now tclParse.c
- deals exclusively with parsing and all evaluations are done by
- code in tclBasic.c. The functions moved are: TclEvalObjvInternal,
+ functions from tclParse.c to tclBasic.c, so that now tclParse.c deals
+ exclusively with parsing and all evaluations are done by code in
+ tclBasic.c. The functions moved are: TclEvalObjvInternal,
Tcl_EvalObjv, Tcl_LogCommandInfo, Tcl_EvalTokensStandard,
Tcl_EvalTokens, Tcl_EvalEx, Tcl_Eval, Tcl_EvalObj and
- Tcl_GlobalEvalObj.
+ Tcl_GlobalEvalObj.
2001-11-19 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * tests/trace.test (trace-8.8): Added adapted version of Bug
- #219393 as new test; the test won't reliably show up the old
- problem unless it is being run under something like Purify, but
- something is better than nothing...
+ * tests/trace.test (trace-8.8): Added adapted version of [Bug 219393]
+ as new test; the test won't reliably show up the old problem unless it
+ is being run under something like Purify, but something is better than
+ nothing...
* generic/tclVar.c (Tcl_TraceVar2, Tcl_UntraceVar2): Added missing
mask bits for trace result type and a check for a nonsense flag
combination.
- * generic/tclCmdMZ.c (TraceVarProc): Added missing test for NULL
- when deleting a trace that doesn't cause an error.
+ * generic/tclCmdMZ.c (TraceVarProc): Added missing test for NULL when
+ deleting a trace that doesn't cause an error.
* doc/TraceVar.3: Added documentation for change due to TIP#68.
- * generic/tclCmdMZ.c (TraceVarInfo): Removed problematic errMsg
- field from structure.
+ * generic/tclCmdMZ.c (TraceVarInfo): Removed problematic errMsg field
+ from structure.
(TraceVarProc): Removed references to errMsg field and changed
handling of errors so that they returned a Tcl_Obj* containing the
- error string. This minimizes the number of calls to the memory
+ error string. This minimizes the number of calls to the memory
management subsystem.
(TclTraceCommandObjCmd, TraceCommandProc): Removed references to
errMsg field which was never used in command traces in any case.
@@ -710,14 +696,14 @@
errMsg field and made variable traces register with
TCL_TRACE_RESULT_OBJECT bit set.
- * generic/tcl.h (TCL_TRACE_RESULT_DYNAMIC,TCL_TRACE_RESULT_OBJECT):
- New constants to define how to handle the strings returned from
- trace callbacks [TIP#68]
+ * generic/tcl.h (TCL_TRACE_RESULT_DYNAMIC,TCL_TRACE_RESULT_OBJECT):
+ New constants to define how to handle the strings returned from trace
+ callbacks [TIP#68]
* generic/tclVar.c (CallTraces, Tcl_GetVar2Ex, TclGetIndexedScalar,
- TclGetElementOfIndexedArray, Tcl_SetVar2Ex, TclSetIndexedScalar,
- TclSetElementOfIndexedArray, Tcl_UnsetVar2, Tcl_ArrayObjCmd,
- TclDeleteVars, TclDeleteCompiledLocalVars, DeleteArray,
- TclVarTraceExists): Support for those new trace flags.
+ (TclGetElementOfIndexedArray, Tcl_SetVar2Ex, TclSetIndexedScalar,
+ (TclSetElementOfIndexedArray, Tcl_UnsetVar2, Tcl_ArrayObjCmd,
+ (TclDeleteVars, TclDeleteCompiledLocalVars, DeleteArray,
+ (TclVarTraceExists): Support for those new trace flags.
2001-11-19 Miguel Sofer <msofer@users.sourceforge.net>
@@ -725,14 +711,14 @@
2001-11-16 Kevin B. Kenny <kennykb@users.sourceforge.net>
- * generic/tclListObj.c: removed a C++-style comment that
- was inadvertently left in the source code.
+ * generic/tclListObj.c: removed a C++-style comment that was
+ inadvertently left in the source code.
2001-11-16 Jeff Hobbs <jeffh@ActiveState.com>
- * tests/interp.test:
- * generic/tclInterp.c (SlaveObjCmd): Corrected argument checking
- for '$interp alias|aliases|issafe'. [Patch #479560] (thoyts, hobbs)
+ * tests/interp.test:
+ * generic/tclInterp.c (SlaveObjCmd): Corrected argument checking for
+ '$interp alias|aliases|issafe'. [Patch 479560] (thoyts, hobbs)
* unix/tclUnixInit.c: added HAVE_LANGINFO code block.
* unix/configure: regened
@@ -740,17 +726,17 @@
* unix/tcl.m4: made SHLIB_LD_LIBS='${LIBS}' for FreeBSD* (meyer)
Added modified version of Wagner patch to make use of nl_langinfo
where possible to determine Unix platform encoding, instead of the
- inflexible built-in system. This is used by default when
- possible, and can be disabled with --enable-langinfo=no.
- [Patch #418645] (hobbs, wagner)
+ inflexible built-in system. This is used by default when possible, and
+ can be disabled with --enable-langinfo=no. [Patch 418645] (hobbs,
+ wagner)
2001-11-16 Miguel Sofer <msofer@users.sourceforge.net>
* generic/tclCompile.h:
* generic/tclExecute.c:
- * generic/tclObj.c: moved Tcl_GetCommandFromObj and all defining
- code for tclCmdNameType objects to tclObj.c (from tclExecute.c).
- This code has nothing to do with bytecodes.
+ * generic/tclObj.c: moved Tcl_GetCommandFromObj and all defining code
+ for tclCmdNameType objects to tclObj.c (from tclExecute.c). This code
+ has nothing to do with bytecodes.
2001-11-16 Miguel Sofer <msofer@users.sourceforge.net>
@@ -760,18 +746,17 @@
* generic/tclParse.c:
* generic/tclProc.c:
* tests/stack.test: consolidation of duplicated code (in
- TclExecuteByteCode and EvalObjv); renaming of EvalObjv to
- TclEvalObjv as it is not static anymore; restored consistency of
- level counts between compiled and directly evaled code.
- [Bug 480896]
+ TclExecuteByteCode and EvalObjv); renaming of EvalObjv to TclEvalObjv
+ as it is not static anymore; restored consistency of level counts
+ between compiled and directly evaled code. [Bug 480896]
2001-11-12 David Gravereaux <davygrvy@pobox.com>
* win/makefile.vc:
* win/rules.vc: Small bug fixes.
- * win/README: added some docs pointing to the docs in makefile.vc
- for it's use.
+ * win/README: added some docs pointing to the docs in makefile.vc for
+ it's use.
2001-10-17 Kevin B. Kenny <kennykb@users.sourceforge.net>
@@ -806,17 +791,17 @@
* tests/obj.test:
* tests/string.test:
* tests/stringComp.test:
- Reference implementation of TIP's #22, #33 and #45. Adds the
- ability of the [lindex] command to have multiple index arguments,
- and adds the [lset] command. Both commands are byte-code compiled.
- [Patch #471874] (work by Kenny, commited by Hobbs)
+ Reference implementation of TIP's #22, #33 and #45. Adds the ability
+ of the [lindex] command to have multiple index arguments, and adds the
+ [lset] command. Both commands are byte-code compiled. [Patch 471874]
+ (work by Kenny, commited by Hobbs)
2001-11-12 David Gravereaux <davygrvy@pobox.com>
* win/buildall.vc.bat(new):
* win/makefile.vc: Small fix with deriving the "OriginalFilename"
- string in the .rc scripts. Added a quick batchfile for building
- the entire thing.
+ string in the .rc scripts. Added a quick batchfile for building the
+ entire thing.
2001-11-12 Jeff Hobbs <jeffh@ActiveState.com>
@@ -827,8 +812,8 @@
2001-11-10 Mo DeJong <mdejong@users.sourceforge.net>
* unix/Makefile.in:
- * win/Makefile.in: Add "make gdb" target. This target
- can run tclsh inside either gdb or insight.
+ * win/Makefile.in: Add "make gdb" target. This target can run tclsh
+ inside either gdb or insight.
2001-11-10 David Gravereaux <davygrvy@pobox.com>
@@ -837,20 +822,19 @@
* win/mkd.bat:
* win/rmd.bat: Changes from Llyod Lim for better stability.
- [Patch #456759]
+ [Patch 456759]
2001-11-09 David Gravereaux <davygrvy@pobox.com>
* win/makefile.vc:
- * win/tcl.dsp: winhelp target fixes for non-NT systems. It
- seems NMAKE under these remembers changed directories during
- commands. A new tcltest feature from Peter Spjuth
- <peter.spjuth@space.se> to specify a pattern file from the
- commandline and redirecting output to a file when not under
- NT with it's scrollback console. Then it replays it, piped
- through more. Added 2 new static "configurations" to tcl.dsp.
- I could keep adding more, but I think we should leave it up to
- the user for customizing it.
+ * win/tcl.dsp: winhelp target fixes for non-NT systems. It seems
+ NMAKE under these remembers changed directories during commands. A new
+ tcltest feature from Peter Spjuth <peter.spjuth@space.se> to specify a
+ pattern file from the commandline and redirecting output to a file
+ when not under NT with it's scrollback console. Then it replays it,
+ piped through more. Added 2 new static "configurations" to tcl.dsp.
+ I could keep adding more, but I think we should leave it up to the
+ user for customizing it.
Sticky-points left: 'profile' option.
@@ -860,9 +844,9 @@
* doc/StdChannels.3:
* doc/file.n:
* doc/tcltest.n:
- * tools/man2help.tcl:
+ * tools/man2help.tcl:
* tools/man2help2.tcl: fixed winhelp generation problems
- [Patch #480268]
+ [Patch 480268]
* unix/configure:
* unix/tcl.m4: added -lc to AIX libs, fixed path to ldAix
@@ -870,68 +854,64 @@
2001-11-09 Don Porter <dgp@users.sourceforge.net>
* tests/var.test:
- * generic/tclVar.c: Corrected bug in [global] when dealing
- with variable names matching :*. [Bug 480176]
+ * generic/tclVar.c: Corrected bug in [global] when dealing with
+ variable names matching :*. [Bug 480176]
2001-11-08 Mo DeJong <mdejong@users.sourceforge.net>
- Fixup stack size under OSF1. [Tcl patch 474790]
+ Fixup stack size under OSF1. [Patch 474790]
* unix/configure: Regen.
- * unix/tcl.m4: Add HAVE_PTHREAD_ATTR_SETSTACKSIZE define
- to EXTRA_CFLAGS to adjust initial stack size.
+ * unix/tcl.m4: Add HAVE_PTHREAD_ATTR_SETSTACKSIZE define to
+ EXTRA_CFLAGS to adjust initial stack size.
2001-11-08 Mo DeJong <mdejong@users.sourceforge.net>
- Enable thread support under FreeBSD. [Tcl bug 473708]
+ Enable thread support under FreeBSD. [Bug 473708]
* unix/configure: Regen.
- * unix/tcl.m4 (SC_ENABLE_THREADS): Check for pthread functions
- in libc_r and enable thread support if found.
- * unix/dltest/Makefile.in: Set SHLIB_LD_LIBS and use it in
- the Makefile to properly link a shared library.
+ * unix/tcl.m4 (SC_ENABLE_THREADS): Check for pthread functions in
+ libc_r and enable thread support if found.
+ * unix/dltest/Makefile.in: Set SHLIB_LD_LIBS and use it in the
+ Makefile to properly link a shared library.
2001-11-08 Mo DeJong <mdejong@users.sourceforge.net>
* unix/Makefile.in:
- * unix/dltest/Makefile.in:
- Avoid adding libc to the LIBS variable since it
- is not needed when linking with CC. If required
- when linking with LD it should be done on a case
- by case basis in tcl.m4.
+ * unix/dltest/Makefile.in: Avoid adding libc to the LIBS variable
+ since it is not needed when linking with CC. If required when linking
+ with LD it should be done on a case by case basis in tcl.m4.
2001-11-08 David Gravereaux <davygrvy@pobox.com>
* win/rules.vc:
- * win/makefile.vc: Fixed install target to adjust for the
- different build types. Added a 'linkexten' option to link the
- win extensions inside the shell when built static. Placed
- win/tclAppInit.c patch in SF patch DB for approval. 'profile'
- option not hooked in yet. Everything else know is done.
+ * win/makefile.vc: Fixed install target to adjust for the different
+ build types. Added a 'linkexten' option to link the win extensions
+ inside the shell when built static. Placed win/tclAppInit.c patch in
+ SF patch DB for approval. 'profile' option not hooked in yet.
+ Everything else know is done.
* win/tcl.dsp(new):
* win/tcl.dsw(new): Simple MsDev stub project files that calls
- makefile.vc. Will help run Tcl in the debugger easier without
+ makefile.vc. Will help run Tcl in the debugger easier without
confusing MsDev for where the .pdb files are.
2001-11-07 Mo DeJong <mdejong@users.sourceforge.net>
* unix/Makefile.in:
- * win/Makefile.in:
- Print a message indicating that the user should
- run "make genstubs" when the generated tclStubInit.c
- file is out of date. We can't regenerate automatically
- since there may be no tclsh on the system and that
- would cause bootstrap problems. [Tcl bug 465874]
+ * win/Makefile.in: Print a message indicating that the user should run
+ "make genstubs" when the generated tclStubInit.c file is out of date.
+ We can't regenerate automatically since there may be no tclsh on the
+ system and that would cause bootstrap problems. [Bug 465874]
2001-11-07 Mo DeJong <mdejong@users.sourceforge.net>
- Define TCL_INCLUDE_SPEC in tclConfig.sh. It should be
- included by extensions that need to find Tcl include
- headers in the install location. The user can override
- the include install dir with --includedir so we need
- to record this information for extensions. [Tcl bug 421835]
-
+ Define TCL_INCLUDE_SPEC in tclConfig.sh. It should be included by
+ extensions that need to find Tcl include headers in the install
+ location. The user can override the include install dir with
+ --includedir so we need to record this information for extensions.
+ [Bug 421835]
+
* unix/configure: Regen.
* unix/configure.in: Define TCL_INCLUDE_SPEC.
* unix/tclConfig.sh.in: Define TCL_INCLUDE_SPEC.
@@ -942,45 +922,41 @@
2001-11-07 David Gravereaux <davygrvy@pobox.com>
* win/rules.vc:
- * win/makefile.vc: Dropped the NOMSVCRT macro and put it on the
- option list instead. It makes more sense to me this way as
- NOMSVCRT=0 would only be the valid setting. Fixed the dde and reg
- extension for building static. Improved, but not perfected, the
- winhelp target.
+ * win/makefile.vc: Dropped the NOMSVCRT macro and put it on the option
+ list instead. It makes more sense to me this way as NOMSVCRT=0 would
+ only be the valid setting. Fixed the dde and reg extension for
+ building static. Improved, but not perfected, the winhelp target.
2001-11-07 Mo DeJong <mdejong@users.sourceforge.net>
- * win/README: Change minimum VC++ version to 5.X since
- 4.X is known not to work.
- Indicate that Mingw is required and building with Cygwin
- gcc is not supported. Include instructions that indicate
- how to install Mingw and what URLs folks should use to
- download the supported version of Mingw.
+ * win/README: Change minimum VC++ version to 5.X since 4.X is known
+ not to work.
+ Indicate that Mingw is required and building with Cygwin gcc is not
+ supported. Include instructions that indicate how to install Mingw and
+ what URLs folks should use to download the supported version of Mingw.
* win/configure: Regen.
- * win/configure.in: Error out if user tries to compile the
- Windows version of Tcl with Cygwin gcc. Users should compile
- with Mingw gcc instead.
+ * win/configure.in: Error out if user tries to compile the Windows
+ version of Tcl with Cygwin gcc. Users should compile with Mingw gcc
+ instead.
2001-11-06 Andreas Kupries <andreas_kupries@users.sourceforge.net>
- * generic/tclIO.c (ReadChars): Fixed bug #478856 reported by
- Stuart Cassoff <stwo@users.sourceforge.net>. The bug caused loss
- of fileevents when [read]ing less data from the channel than
- buffered. Due to an empty input buffer the flag
- CHANNEL_NEED_MORE_DATA was set but never reset, causing the I/O
- system to wait for more data instead of using a timer to
- synthesize fileevents and to flush the pending data out of the
- buffers.
+ * generic/tclIO.c (ReadChars): Fixed [Bug 478856] reported by Stuart
+ Cassoff <stwo@users.sourceforge.net>. The bug caused loss of
+ fileevents when [read]ing less data from the channel than buffered.
+ Due to an empty input buffer the flag CHANNEL_NEED_MORE_DATA was set
+ but never reset, causing the I/O system to wait for more data instead
+ of using a timer to synthesize fileevents and to flush the pending
+ data out of the buffers.
2001-11-06 David Gravereaux <davygrvy@pobox.com>
* win/rules.vc (new):
* win/makefile.vc: Complete over/under rewrite to support numerous
- build options all from the commandline itself without needing to
- edit the makefile. Now requires vcvars32.bat to be run prior to
- running nmake for bootstraping the environment. Fully doc'd usage
- for it is in makefile.vc. Commentary welcome. Sticky points left
- are:
+ build options all from the commandline itself without needing to edit
+ the makefile. Now requires vcvars32.bat to be run prior to running
+ nmake for bootstraping the environment. Fully doc'd usage for it is in
+ makefile.vc. Commentary welcome. Sticky points left are:
1) winhelp target shows errors in the converting script.
2) .rc scripts aren't getting the right #defines to build the correct
@@ -992,158 +968,153 @@
2001-11-04 Vince Darley <vincentdarley@users.sourceforge.net>
- * library/init.tcl: made filesystem fallback proc
- ::tcl::CopyDirectory more robust to vagaries of non-native
- filesystems.
-
+ * library/init.tcl: made filesystem fallback proc ::tcl::CopyDirectory
+ more robust to vagaries of non-native filesystems.
+
2001-11-02 Vince Darley <vincentdarley@users.sourceforge.net>
* doc/file.n:
- * generic/tclIOUtil.c: updated documentation and comments
- to clarify behaviour of 'file copy' wrt soft links.
-
+ * generic/tclIOUtil.c: updated documentation and comments to clarify
+ behaviour of 'file copy' wrt soft links.
+
2001-10-29 Vince Darley <vincentdarley@users.sourceforge.net>
- * win/tclWinFile.c: fix to '-types {f r}' bug in
- TclpMatchInDirectory (which could cause a UMR, as well as
- returning wrong results). Also improved API for 'stat'
- to resolve [Bug#219258].
+ * win/tclWinFile.c: fix to '-types {f r}' bug in TclpMatchInDirectory
+ (which could cause a UMR, as well as returning wrong results). Also
+ improved API for 'stat' to resolve [Bug 219258].
* win/tclWin32Dll.c
- * win/tclWinInt.h: addition of improved stat API to internal
- lookup table.
+ * win/tclWinInt.h: addition of improved stat API to internal lookup
+ table.
* tests/fileName.test: two new tests for the above bug.
* generic/tclIOUtil.c: some cleanup of comments and #ifdefs
-
+
2001-10-29 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * unix/tclUnixFile.c (TclpMatchInDirectory): Argument to access()
- was entryPtr->d_name instead of nativeEntry which failed when
- trying to check access for files in other than the current
- directory. [Bug 475941, reported by Georgios Petasis]
+ * unix/tclUnixFile.c (TclpMatchInDirectory): Argument to access() was
+ entryPtr->d_name instead of nativeEntry which failed when trying to
+ check access for files in other than the current directory. [Bug
+ 475941, reported by Georgios Petasis]
2001-10-25 Donal K. Fellows <fellowsd@cs.man.ac.uk>
* unix/tclUnixChan.c: Added stateUpdated member to struct TtyState.
- (TtyCloseProc,TtySetOptionProc,TtyInit): Use stateUpdated member
- of TtyState to decide whether it is necessary to reset a serial
- port when Tcl closes it. Blindly resetting can cause Tcl to be
- sent an unexpected SIGTSTP when it is executing in the background
- [Bug 471374, reported by Chris Nelson]
+ (TtyCloseProc,TtySetOptionProc,TtyInit): Use stateUpdated member of
+ TtyState to decide whether it is necessary to reset a serial port when
+ Tcl closes it. Blindly resetting can cause Tcl to be sent an
+ unexpected SIGTSTP when it is executing in the background [Bug 471374,
+ reported by Chris Nelson]
-2001-10-22 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+2001-10-22 Andreas Kupries <andreas_kupries@users.sourceforge.net>
- * doc/ObjectType.3: Minor documentation fix, reported by David
- N. Welton <davidw@users.sourceforge.net> directly to me.
+ * doc/ObjectType.3: Minor documentation fix, reported by David N.
+ Welton <davidw@users.sourceforge.net> directly to me.
2001-10-22 Vince Darley <vincentdarley@users.sourceforge.net>
- * win/tclWinFCmd.c: fix to stop test suite from hanging process
- under some versions of WinNT. [Bug #466102] (Kevin Kenny)
-
+ * win/tclWinFCmd.c: fix to stop test suite from hanging process under
+ some versions of WinNT. [Bug 466102] (Kevin Kenny)
+
2001-10-18 Jeff Hobbs <jeffh@ActiveState.com>
- * tests/clock.test (clock-8.1):
- * generic/tclDate.c (RelativeMonth):
- * generic/tclGetDate.y (RelativeMonth): corrected off-by-one-day
- error in clock scan with relative months and years during swing
- hours. [Bug #413397, Patch #414024] (lavana)
+ * tests/clock.test (clock-8.1):
+ * generic/tclDate.c (RelativeMonth):
+ * generic/tclGetDate.y (RelativeMonth): corrected off-by-one-day error
+ in clock scan with relative months and years during swing hours. [Bug
+ 413397, Patch 414024] (lavana)
2001-10-18 Vince Darley <vincentdarley@users.sourceforge.net>
- * generic/tclIOUtil.c: fix to bug in Tcl_FSChdir shown up
- by recent tclkit builds.
+ * generic/tclIOUtil.c: fix to bug in Tcl_FSChdir shown up by recent
+ tclkit builds.
2001-10-17 Jeff Hobbs <jeffh@ActiveState.com>
* unix/tclUnixPipe.c (PipeInputProc, PipeOutputProc): do immediate
- retry when error is returned with errno == EINTR.
- [Bug #415131] (leger)
+ retry when error is returned with errno == EINTR. [Bug 415131] (leger)
2001-10-16 Jeff Hobbs <jeffh@ActiveState.com>
- * unix/tclLoadAout.c (TclGuessPackageName): removed unused vars
- and fixed warnings. [Bug #446622] (lim)
+ * unix/tclLoadAout.c (TclGuessPackageName): removed unused vars and
+ fixed warnings. [Bug 446622] (lim)
2001-10-15 Miguel Sofer <msofer@users.sourceforge.net>
* generic/tclProc.c: changing a memcmp to strncmp to avoid a memory
- error detected by purify (thanks Jeff); modify style to agrre with
- the style guide.
-
-2001-10-15 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+ error detected by purify (thanks Jeff); modify style to agrre with the
+ style guide.
+
+2001-10-15 Andreas Kupries <andreas_kupries@users.sourceforge.net>
* generic/tclInt.decls (TclExpandCodeArray,TclGetInstructionTable):
- Added to internal stubs table. Tclcompiler (Tclpro project)
- needs them if used as loadable package under Windows. Changed
- signatures. We don't want to describe compiler internal
- structures in "tclInt.h".
+ Added to internal stubs table. Tclcompiler (Tclpro project) needs them
+ if used as loadable package under Windows. Changed signatures. We
+ don't want to describe compiler internal structures in "tclInt.h".
* generic/tclCompile.h: S.a. Removed function declarations.
* generic/tclCompile.c: S.a. Adapted to changed signatures.
2001-10-15 Jeff Hobbs <jeffh@ActiveState.com>
- * unix/configure:
- * unix/configure.in:
- * win/configure:
- * win/configure.in:
- * win/tcl.m4: reworked to be a little cleaner in comparison to
- each other, and to AC_SUBST even empty vars for win/tclConfig.sh
+ * unix/configure:
+ * unix/configure.in:
+ * win/configure:
+ * win/configure.in:
+ * win/tcl.m4: reworked to be a little cleaner in comparison to each
+ other, and to AC_SUBST even empty vars for win/tclConfig.sh
* generic/tclFileName.c: minor code cleanup
- * generic/tcl.h: moved #define of WIN32 to tcl.h where __WIN32__
- is defined and added #ifndef check.
+ * generic/tcl.h: moved #define of WIN32 to tcl.h where __WIN32__ is
+ defined and added #ifndef check.
* doc/open.n: moved all fconfigure option docs to fconfigure.n
* doc/fconfigure.n: added serial config options
* win/tclWinChan.c:
* win/tclWinPort.h:
- * win/tclWinSerial.c: added TIP #35 Windows enhancements for
- serial configuration. [Patch #438509] (schroedter)
+ * win/tclWinSerial.c: added TIP #35 Windows enhancements for serial
+ configuration. [Patch 438509] (schroedter)
2001-10-15 Vince Darley <vincentdarley@users.sourceforge.net>
* generic/tclFCmd.c: fix to memory leak in TclFileDeleteCmd on
certain error conditions.
* doc/FileSystem.3: fix to typo.
-
+
2001-10-12 Jeff Hobbs <jeffh@ActiveState.com>
* library/encoding/ebcdic.enc:
* tools/encoding/ebcdic.txt: EBCDIC charset mapping.
- [Patch #219323] (nijtmans)
+ [Patch 219323] (nijtmans)
* library/encoding/tis-620.enc:
* tools/encoding/tis-620.txt: TIS-620 charset mapping.
- [Patch #467423] (poonlap)
+ [Patch 467423] (poonlap)
* tests/http.test: added removeFile for outdata
- * tests/ioCmd.test: added catch around file removal, as Windows
- file locking throws errors.
+ * tests/ioCmd.test: added catch around file removal, as Windows file
+ locking throws errors.
* tests/socket.test (socket-7.2): corrected to work on Win2K.
2001-10-12 Miguel Sofer <msofer@users.sourceforge.net>
-
+
* tests/compile.test: new tests for [Bug 467523]; they are only
effective if TCL_MEM_DEBUG was set during compilation.
2001-10-11 Miguel Sofer <msofer@users.sourceforge.net>
-
+
* generic/tclLiteral.c (TclReleaseLiteral): insured that
self-referential bytecodes are properly cleaned up on interpreter
deletion [Bug 467523] (Ronnie Brunner)
2001-10-10 David Gravereaux <davygrvy@pobox.com>
- * win/tclWinPort.h: #include <winsock2.h> needed to get moved
- to after #include <windows.h> or wierd misunderstandings took
- place when -D_WIN32_WINNT=0x0400 is set for outside code that
- requires knowledge of Tcl innards. General header macro magic
- applied liberally...
+ * win/tclWinPort.h: #include <winsock2.h> needed to get moved to
+ after #include <windows.h> or wierd misunderstandings took place when
+ -D_WIN32_WINNT=0x0400 is set for outside code that requires knowledge
+ of Tcl innards. General header macro magic applied liberally...
2001-10-10 Don Porter <dgp@users.sourceforge.net>
@@ -1151,20 +1122,20 @@
2001-10-09 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/tclFileName.c (Tcl_SplitPath): corrected mem leak
- intro'd with VFS code where the result obj from Tcl_FSSplitPath
- was not getting freed.
+ * generic/tclFileName.c (Tcl_SplitPath): corrected mem leak intro'd
+ with VFS code where the result obj from Tcl_FSSplitPath was not
+ getting freed.
2001-10-09 Miguel Sofer <msofer@users.sourceforge.net>
-
- * generic/tclLiteral.c: (TclReleaseLiteral) reverted previous
- patch for [Bug 467523] - cure is worse than the illness.
+
+ * generic/tclLiteral.c: (TclReleaseLiteral) reverted previous patch
+ for [Bug 467523] - cure is worse than the illness.
2001-10-05 Miguel Sofer <msofer@users.sourceforge.net>
-
+
* generic/tclLiteral.c: (TclReleaseLiteral) insured that
self-referential bytecodes are properly cleaned up on interpreter
- deletion [Bug 467523] (Ronnie Brunner)
+ deletion. [Bug 467523] (Ronnie Brunner)
2001-10-04 Jeff Hobbs <jeffh@ActiveState.com>
@@ -1217,18 +1188,18 @@
* tools/encoding/macIceland.txt:
* tools/encoding/macRoman.txt:
* tools/encoding/macTurkish.txt:
- Updated encodings with latest mappings from www.unicode.org. This
- did not include some Mac encodings that have special multi-unichar
- translations now (like symbols, dingbats and japanese). Also does
- not include big5, gb or euc* as those have different formats in
- the latest Unicode version that need new conversion tools. Not
- all related .enc files changed as some had been updates separately.
+ Updated encodings with latest mappings from www.unicode.org. This did
+ not include some Mac encodings that have special multi-unichar
+ translations now (like symbols, dingbats and japanese). Also does not
+ include big5, gb or euc* as those have different formats in the latest
+ Unicode version that need new conversion tools. Not all related .enc
+ files changed as some had been updates separately.
2001-10-03 Jeff Hobbs <jeffh@ActiveState.com>
* generic/tclEvent.c (Tcl_FinalizeThread): moved freeing of
- tclLibraryPath to before the thread exit handlers are called.
- Slight modification to change on 2001-09-24.
+ tclLibraryPath to before the thread exit handlers are called. Slight
+ modification to change on 2001-09-24.
2001-10-01 Jeff Hobbs <jeffh@ActiveState.com>
@@ -1245,45 +1216,44 @@
* generic/tclCmdIL.c:
* generic/tclCmdMZ.c:
* generic/tclParseExpr.c: removed unnecessary inclusion of
- tclCompile.h and made a small modification in (InfoBodyCmd) to
- improve the isolation of the compiler/engine subsystem.
+ tclCompile.h and made a small modification in (InfoBodyCmd) to improve
+ the isolation of the compiler/engine subsystem.
2001-09-29 Vince Darley <vincentdarley@users.sourceforge.net>
* generic/tclIOUtil.c:
- * doc/FileSystem.3: corrected and clarified documentation
- for 'Tcl_FSListVolumes(Proc)'. No code changes.
-
+ * doc/FileSystem.3: corrected and clarified documentation for
+ 'Tcl_FSListVolumes(Proc)'. No code changes.
+
2001-09-28 Miguel Sofer <msofer@users.sourceforge.net>
- * doc/FindExec.3: added a comment not to change the working
- directory before calling Tcl_GetNameOfExecutable [Bug 219215]
+ * doc/FindExec.3: added a comment not to change the working directory
+ before calling Tcl_GetNameOfExecutable. [Bug 219215]
2001-09-28 Kevin Kenny <kennykb@users.sourceforge.net>
- * generic/tclIO.c: added two more '(ClientData)' casts
- on calls to Tcl_Preserve and Tcl_Release -- ones that
- Vince apparently missed.
-
+ * generic/tclIO.c: added two more '(ClientData)' casts on calls to
+ Tcl_Preserve and Tcl_Release -- ones that Vince apparently missed.
+
2001-09-28 Donal K. Fellows <fellowsd@cs.man.ac.uk>
* doc/lsort.n: Improved doc...
* generic/tclCmdIL.c (Tcl_LsortObjCmd, SortCompare): Made
- offset-from-end indexing work, and factored out some "magic
- numbers" for easier understanding. [Bug #465674]
+ offset-from-end indexing work, and factored out some "magic numbers"
+ for easier understanding. [Bug 465674]
* tests/cmdIL.test (cmdIL-1.26): Added test for offset-from-end
indexing for lsort.
2001-09-28 Vince Darley <vincentdarley@users.sourceforge.net>
* win/tclWinFCmd.c:
- * unix/tclUnixFCmd.c: fix to performance issue reported
- by jcw in which 'access("")' is called unnecessarily when
- normalizing any absolute path.
+ * unix/tclUnixFCmd.c: fix to performance issue reported by jcw in
+ which 'access("")' is called unnecessarily when normalizing any
+ absolute path.
* generic/tclIO.c: added '(ClientData)' cast to calls to
- Tcl_(Preserve|Release) newly introduced, fixing compile
- error on Windows.
-
+ Tcl_(Preserve|Release) newly introduced, fixing compile error on
+ Windows.
+
2001-09-27 Don Porter <dgp@users.sourceforge.net>
* doc/FileSystem.3 (Tcl_FSLoadFile):
@@ -1305,70 +1275,67 @@
* unix/tclLoadShl.c (TclpLoadFile):
* win/tclWinLoad.c (TclpLoadFile):
* win/tclWinFCmd.c (DoRemoveJustDirectory): More CONST poisoning
- fixes from the 2001-09-24 TIP 27 changes. CONST-ified
- Tcl_FSLoadFile and TclpLoadFile. Report and patch from Kevin
- Kenny. [Bug 465833]
+ fixes from the 2001-09-24 TIP 27 changes. CONST-ified Tcl_FSLoadFile
+ and TclpLoadFile. Report and patch from Kevin Kenny. [Bug 465833]
- * generic/tclIO.c (ChannelTimerProc): Added Tcl_Preserve()
- and Tcl_Release() to fix segfault introduced by the 2001-09-26
- changes. [Bug 465494]
+ * generic/tclIO.c (ChannelTimerProc): Added Tcl_Preserve() and
+ Tcl_Release() to fix segfault introduced by the 2001-09-26 changes.
+ [Bug 465494]
- * doc/TCL_MEM_DEBUG.3: Updated out-of-date reference to
- #define GUARD_SIZE.
+ * doc/TCL_MEM_DEBUG.3: Updated out-of-date reference to #define
+ GUARD_SIZE.
* doc/UpVar.3 (Tcl_UpVar,Tcl_UpVar2):
* generic/tcl.decls (Tcl_UpVar,Tcl_UpVar2):
* generic/tclInt.decls (TclFindProc,TclGetFrame):
* generic/tclInt.h (TclFindProc,TclGetFrame,TclLookupVar,
- TclPrecTraceProc,TclProcInterpProc}):
+ (TclPrecTraceProc,TclProcInterpProc}):
* generic/tclProc.c (TclGetFrame,TclFindProc):
* generic/tclVar.c (Tcl_UpVar,Tcl_UpVar2,MakeUpvar): Updated APIs in
- generic/tclProc.c and generic/tclVar.c according to the guidelines
- of TIP 27. [Patch 465442]
+ generic/tclProc.c and generic/tclVar.c according to the guidelines of
+ TIP 27. [Patch 465442]
* generic/tclDecls.h:
* generic/tclIntDecls.h: make genstubs
-2001-09-26 Andreas Kupries <andreas_kupries@users.sourceforge.net>
-
- * doc/fileevent.n: Accepted [Patch #465279] adding an example to
- the fileevent manpage. Minor modifications to get a better
- formatting. Report and patch by David N. Welton
- <davidw@users.sourceforge.net>.
-
- * The changes below fix [Bug #462317] where Expect tried to read
- more than was in the buffers and then blocked in the OS call as
- its pty channel driver provides no blockmodeproc through which
- the OS could be notified of blocking-behaviour. Because of this
- the general I/O core has to take more care than usual to
- preserve the semantics of non-blocking channels.
-
- The problem was reported by "Kevin O'Gorman"
- <kevin@kosmanor.com>.
-
- * generic/tclIO.c (Tcl_ReadRaw): Do not read from the driver if
- the channel is non-blocking and the fileevent causing the read
- was generated by a timer. We do not know if there is data
- available from the OS. Instead of going to the OS for more and
- potentially blocking we simply signal EWOULDBLOCK to the higher
- levels to cause the system to wait for true fileevents.
- (GetInput): Same as before.
- (ChannelTimerProc): Added set and clear of CHANNEL_TIMER_FEV.
-
- * generic/tclIO.h (CHANNEL_TIMER_FEV): New flag for channels. Is
- set if a fileevent was generated by a timer, the channel is not
- blocking and the driver did not provide a blockmodeproc. In that
- case the I/O core has to be especially careful about going to
- the driver for more data.
+2001-09-26 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * doc/fileevent.n: Accepted [Patch 465279] adding an example to the
+ fileevent manpage. Minor modifications to get a better formatting.
+ Report and patch by David N. Welton <davidw@users.sourceforge.net>.
+
+ * The changes below fix [Bug 462317] where Expect tried to read more
+ than was in the buffers and then blocked in the OS call as its pty
+ channel driver provides no blockmodeproc through which the OS could be
+ notified of blocking-behaviour. Because of this the general I/O core
+ has to take more care than usual to preserve the semantics of
+ non-blocking channels.
+
+ The problem was reported by "Kevin O'Gorman" <kevin@kosmanor.com>.
+
+ * generic/tclIO.c (Tcl_ReadRaw): Do not read from the driver if the
+ channel is non-blocking and the fileevent causing the read was
+ generated by a timer. We do not know if there is data available from
+ the OS. Instead of going to the OS for more and potentially blocking
+ we simply signal EWOULDBLOCK to the higher levels to cause the system
+ to wait for true fileevents.
+ (GetInput): Same as before.
+ (ChannelTimerProc): Added set and clear of CHANNEL_TIMER_FEV.
+
+ * generic/tclIO.h (CHANNEL_TIMER_FEV): New flag for channels. Is set
+ if a fileevent was generated by a timer, the channel is not blocking
+ and the driver did not provide a blockmodeproc. In that case the I/O
+ core has to be especially careful about going to the driver for more
+ data.
2001-09-26 Don Porter <dgp@users.sourceforge.net>
* doc/SplitPath.3 (Tcl_GetPathType):
* generic/tcl.decls (Tcl_GetPathType):
* generic/tclFileName.c (Tcl_GetPathType):
- * win/tclWinFile.c (TclpMatchInDirectory, NativeStat): Vince
- Darley reports the 2001-09-24 TIP 27 changes left the win
- directory CONST poisoned. These changes should fix that.
+ * win/tclWinFile.c (TclpMatchInDirectory, NativeStat): Vince Darley
+ reports the 2001-09-24 TIP 27 changes left the win directory CONST
+ poisoned. These changes should fix that.
* generic/tclDecls.h: make genstubs
@@ -1378,17 +1345,17 @@
* generic/tclInt.h (TclGetLong deleted):
* generic/tcl.decls:
* generic/tclInt.decls:
- * generic/tclGet.c: Updated APIs in generic/tclGet.c
- according to the guidelines of TIP 27. [Patch 464674]
+ * generic/tclGet.c: Updated APIs in generic/tclGet.c according to the
+ guidelines of TIP 27. [Patch 464674]
- * generic/tclDecls.h:
+ * generic/tclDecls.h:
* generic/tclIntDecls.h: make genstubs
2001-09-25 Miguel Sofer <msofer@users.sourceforge.net>
* generic/tclVar.c: removed comments referring to unused flag
- TCL_PARSE_PART1.
-
+ TCL_PARSE_PART1.
+
2001-09-24 Don Porter <dgp@users.sourceforge.net>
* doc/Concat.3:
@@ -1400,37 +1367,34 @@
* generic/tclEncoding.c (OpenEncodingFile):
* generic/tclMain.c (Tcl_Main):
* generic/tclUtil.c:
- * unix/tclLoadDl.c (TclpLoadFile): Updated APIs in
- generic/tclUtil.c according to the guidelines of TIP 27.
- [Patch 464553]
+ * unix/tclLoadDl.c (TclpLoadFile): Updated APIs in generic/tclUtil.c
+ according to the guidelines of TIP 27. [Patch 464553]
- * generic/tclDecls.h:
+ * generic/tclDecls.h:
* generic/tclIntDecls.h: make genstubs
2001-09-24 Andreas Kupries <andreas_kupries@users.sourceforge.net>
- * The change below fixes [Bug #464380]. The bug was reported by
- Ronnie Brunner <rbrunner@users.sourceforge.net>. He also
- provided the patch.
-
- * generic/tclEvent.c (Tcl_Finalize): Moved release of
- 'tclLibraryPath' to Tcl_FinalizeThread.
- (Tcl_FinalizeThread): See above, new place for release of
- 'tclLibraryPath'.
+ The change below fixes [Bug 464380]. The bug was reported by Ronnie
+ Brunner <rbrunner@users.sourceforge.net>. He also provided the patch.
+
+ * generic/tclEvent.c (Tcl_Finalize): Moved release of 'tclLibraryPath'
+ to Tcl_FinalizeThread.
+ (Tcl_FinalizeThread): See above, new place for release of
+ 'tclLibraryPath'.
2001-09-24 Donal K. Fellows <fellowsd@cs.man.ac.uk>
* tools/encoding/cp1252.txt: File was missing part of the encoding
- [euro, ZCaron and zcaron].
+ [euro, ZCaron and zcaron].
- * doc/OpenFileChnl.3: Add docs for Tcl_OutputBuffered; remove some
- old changebars.
+ * doc/OpenFileChnl.3: Add docs for Tcl_OutputBuffered; remove some old
+ changebars.
2001-09-21 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/tclExecute.c (TclExecuteByteCode): corrected
- INST_STR_CMP else case for strings to pass true utf char length
- to Tcl_UtfNCmp.
+ * generic/tclExecute.c (TclExecuteByteCode): corrected INST_STR_CMP
+ else case for strings to pass true utf char length to Tcl_UtfNCmp.
2001-09-20 Jeff Hobbs <jeffh@ActiveState.com>
@@ -1439,30 +1403,30 @@
* win/tclWinSock.c (SocketThread): corrected pointer cast for _WIN64.
* win/tclWinNotify.c: removed unnecessary winsock include (it is
- already in from tclWinPort.h).
+ already in from tclWinPort.h).
- * win/tclWinPort.h: changed winsock.h include to winsock2.h.
- Reverses change from 2000-11-16, but is necessary for WIN64.
- Extensions should comply with defined OS words, or use #ifndef.
+ * win/tclWinPort.h: changed winsock.h include to winsock2.h. Reverses
+ change from 2000-11-16, but is necessary for WIN64. Extensions should
+ comply with defined OS words, or use #ifndef.
2001-09-20 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * tests/socket.test: removed dependence on being run from same dir
- as remote.tcl, which only now needs to be in the same dir as
- this file. [Bug #219326]
+ * tests/socket.test: removed dependence on being run from same dir as
+ remote.tcl, which only now needs to be in the same dir as this file.
+ [Bug 219326]
2001-09-19 Jeff Hobbs <jeffh@ActiveState.com>
* generic/tclTest.c (TestcmdtokenCmd): corrected pointer
- storage/retrieval for 64bit machines.
+ storage/retrieval for 64bit machines.
* generic/tclCmdAH.c (Tcl_FormatObjCmd):
- * generic/tclScan.c (Tcl_ScanObjCmd): corrected handling of format
- and scan on 64-bit machines. [Bug #412696] (rmax)
+ * generic/tclScan.c (Tcl_ScanObjCmd): corrected handling of format and
+ scan on 64-bit machines. [Bug 412696] (rmax)
* unix/configure: regen'ed
- * unix/tcl.m4: added --enable-64bit support for HP-11 with the
- 64-bit kernel.
+ * unix/tcl.m4: added --enable-64bit support for HP-11 with the 64-bit
+ kernel.
* tests/basic.test:
* tests/cmdInfo.test: improved skip reporting of missing commands
@@ -1471,10 +1435,10 @@
* tests/winPipe.test: removed obsolete cat16 tests
- * generic/tclExecute.c (TclExecuteByteCode): fixed invalid usage
- of valuePtr in TRACE_WITH_OBJ in INST_EVAL_STK case. [Bug #462594]
- Changed INST_STR_CMP instruction to promote to Unicode strings
- only when one of the strings is already of Unicode type.
+ * generic/tclExecute.c (TclExecuteByteCode): fixed invalid usage of
+ valuePtr in TRACE_WITH_OBJ in INST_EVAL_STK case. [Bug 462594] Changed
+ INST_STR_CMP instruction to promote to Unicode strings only when one
+ of the strings is already of Unicode type.
* generic/tclExecute.c (TclExecuteByteCode):
* generic/tclCompile.c (instructionTable):
@@ -1486,77 +1450,75 @@
* tests/{for.test,foreach.test,if.test,while.test}:
* generic/tclCompCmds.c (TclCompileForCmd, TclCompileForeachCmd,
TclCompileIfCmd, TclCompileWhileCmd): Corrected the overaggressive
- compiling of loop bodies enclosed in ""s. [Bug #219166] (msofer)
+ compiling of loop bodies enclosed in ""s. [Bug 219166] (msofer)
2001-09-19 Miguel Sofer <msofer@users.sourceforge.net>
-
- * generic/tclExecute.c: insured that execution stack errors are
- also detected at abnormal returns.
+
+ * generic/tclExecute.c: insured that execution stack errors are also
+ detected at abnormal returns.
2001-09-19 Donal K. Fellows <fellowsd@cs.man.ac.uk>
* doc/socket.n: Added documentation to mention what happens when a
- server socket is created with port=0. Removed an old change bar,
- and no new change bar because Tcl has always behaved this way as
- it is really a poorly-documented standards-defined OS feature.
+ server socket is created with port=0. Removed an old change bar, and
+ no new change bar because Tcl has always behaved this way as it is
+ really a poorly-documented standards-defined OS feature.
* tests/util.test (util-8.1): Test derived from code to detect the
- problem, but the test always works in the C locale, so beware if
- you are maintaining the code.
- * generic/tclUtil.c (TclNeedSpace): Rewrote to be UTF-8 aware.
- [Bug 411825, but not that patch which would have added extra
- spaces if there was a real non-ASCII space involved. ]
+ problem, but the test always works in the C locale, so beware if you
+ are maintaining the code.
+ * generic/tclUtil.c (TclNeedSpace): Rewrote to be UTF-8 aware. [Bug
+ 411825, but not that patch which would have added extra spaces if
+ there was a real non-ASCII space involved.]
-2001-09-18 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+2001-09-18 Andreas Kupries <andreas_kupries@users.sourceforge.net>
* generic/tclIOCmd.c (Tcl_PutsObjCmd): Rewritten to have saner and
- faster argument handling. Fixes bug #123552. Patch provided by
- Donal K. Fellows <fellowsd@cs.man.ac.uk>: #402564.
+ faster argument handling. [Bug 123552], [Patch 402564] (fellows)
2001-09-18 Don Porter <dgp@users.sourceforge.net>
* unix/configure: Regen.
- * unix/tcl.m4 (SC_CONFIG_CFLAGS): On Linux, disable inlining when
- one of the compat/*.c routines is to be linked in. [Patch 440891]
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): On Linux, disable inlining when one
+ of the compat/*.c routines is to be linked in. [Patch 440891]
2001-09-17 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/tcl.h: removed forced #define USE_TCLALLOC 1 for
- Windows. This means the native system allocator will be used by
- default. This should be binary and source compatible with
- extensions, as Tcl_Alloc is a properly stubbed function.
+ * generic/tcl.h: removed forced #define USE_TCLALLOC 1 for Windows.
+ This means the native system allocator will be used by default. This
+ should be binary and source compatible with extensions, as Tcl_Alloc
+ is a properly stubbed function.
2001-09-17 Miguel Sofer <msofer@users.sourceforge.net>
-
- * generic/tclExecute.c: corrected small bug in [Patch 456668] -
- the varFramePtr was not restored in one possible exit.
+
+ * generic/tclExecute.c: corrected small bug in [Patch 456668] - the
+ varFramePtr was not restored in one possible exit.
2001-09-17 Miguel Sofer <msofer@users.sourceforge.net>
-
+
* doc/tclvars.n:
* generic/tclCompile.c:
* generic/tclCompile.h:
* generic/tclExecute.c:
* generic/tclProc.c: disabled all compile and execution tracing
- functionality in standard builds; TCL_COMPILE_DEBUG is now
- necessary to enable it. [Bug 451858]
+ functionality in standard builds; TCL_COMPILE_DEBUG is now necessary
+ to enable it. [Bug 451858]
2001-09-14 Andreas Kupries <andreas_kupries@users.sourceforge.net>
- * doc/gets.n:
- * doc/read.n:
- * doc/puts.n:
- * doc/flush.n:
- * doc/fconfigure.n:
- * doc/flush.n:
- * doc/eof.n:
- * doc/seek.n:
- * doc/tell.n:
- * doc/close.n:
- * doc/fileevent.n: Added references to the Tcl standard
- channels. Item [219250], reported by David LeBlanc
- <whisper@oz.net>. Thanks to Christopher Nelson
- <chris@pinebush.com> for doing editorial work.
+ * doc/gets.n:
+ * doc/read.n:
+ * doc/puts.n:
+ * doc/flush.n:
+ * doc/fconfigure.n:
+ * doc/flush.n:
+ * doc/eof.n:
+ * doc/seek.n:
+ * doc/tell.n:
+ * doc/close.n:
+ * doc/fileevent.n: Added references to the Tcl standard channels. Item
+ [219250], reported by David LeBlanc <whisper@oz.net>. Thanks to
+ Christopher Nelson <chris@pinebush.com> for doing editorial work.
2001-09-13 Andreas Kupries <andreas_kupries@users.sourceforge.net>
@@ -1565,56 +1527,52 @@
* win/makefile.bc:
* win/makefile.vc:
* library/dde/pkgIndex.tcl: Fixed version numbers from bogus tcl
- versions to independent versions for dde and registry packages.
+ versions to independent versions for dde and registry packages.
2001-09-13 Jeff Hobbs <jeffh@ActiveState.com>
* tests/regexp.test (regexp-20.1):
* generic/tclCmdMZ.c (Tcl_RegsubObjCmd): had to adjust fix from
- 2001-08-06 to actually duplicate the objects in certain cases.
- This is really a place where feather would have been essential.
- [Bug #461322]
+ 2001-08-06 to actually duplicate the objects in certain cases. This is
+ really a place where feather would have been essential. [Bug 461322]
* generic/tclUtf.c (Tcl_UtfPrev): corrected to return the proper
- location when the middle of a UTF-8 byte was passed in.
- [Tk Bug #450504]
+ location when the middle of a UTF-8 byte was passed in [Tk Bug 450504]
* ChangeLog.1999:
* ChangeLog: broke changes from 199x into ChangeLog.1999 to reduce
- size of the main ChangeLog.
+ size of the main ChangeLog.
2001-09-13 Andreas Kupries <andreas_kupries@users.sourceforge.net>
* tests/ioCmd.test: Changed the computation of the result for
- iocmd-8.1[123] so that the tests work for single- and
- multi-process execution of the testsuite. Depending on the
- choice of the user stdout is a tty or not and thus reports
- different channel options. Fixes [460993] reported by Don
- Porter.
+ iocmd-8.1[123] so that the tests work for single- and multi-process
+ execution of the testsuite. Depending on the choice of the user stdout
+ is a tty or not and thus reports different channel options. Fixes
+ [460993] reported by Don Porter.
2001-09-13 Miguel Sofer <msofer@users.sourceforge.net>
- * doc/ParseCmd.3:
+ * doc/ParseCmd.3:
* generic/tcl.decls:
* generic/tclCmdMZ.c (Tcl_SubstObjCmd):
* generic/tclDecls.h:
* generic/tclParse.c:
* generic/tclStubInit.c:
- * tests/parse.test: Deprecate the use of Tcl_EvalTokens, replaced
- by the new Tcl_EvalTokensStandard. The new function performs the
- same duties but adheres to the standard return convention for Tcl
+ * tests/parse.test: Deprecate the use of Tcl_EvalTokens, replaced by
+ the new Tcl_EvalTokensStandard. The new function performs the same
+ duties but adheres to the standard return convention for Tcl
evaluations; the deprecated function could only return TCL_OK or
- TCL_ERROR, which caused [Bug 219384] and [Bug 455151].
- This patch implements [TIP 56].
-
+ TCL_ERROR, which caused [Bug 219384] and [Bug 455151]. This patch
+ implements [TIP 56].
+
2001-09-12 Mo DeJong <mdejong@users.sourceforge.net>
* unix/configure: Regen.
- * unix/tcl.m4: Invert the logic that checks for $GCC.
- Instead of checking for "$GCC" = "no" we check for
- "$GCC" != "yes" or simply swap the true and false
- blocks of code in an if statement. That way if
- GCC is set to "" everything will still work. [Bug 460991]
+ * unix/tcl.m4: Invert the logic that checks for $GCC. Instead of
+ checking for "$GCC" = "no" we check for "$GCC" != "yes" or simply swap
+ the true and false blocks of code in an if statement. That way if GCC
+ is set to "" everything will still work. [Bug 460991]
2001-09-12 Don Porter <msofer@users.sourceforge.net>
@@ -1622,8 +1580,8 @@
* tests/lsearch.test:
* tests/namespace.test:
* tests/rename.test:
- * tests/split.test: Corrected tests to better isolate tests in
- one file from influencing tests in other files. [Bug 460591]
+ * tests/split.test: Corrected tests to better isolate tests in one
+ file from influencing tests in other files. [Bug 460591]
2001-09-12 Miguel Sofer <msofer@users.sourceforge.net>
@@ -1633,181 +1591,170 @@
2001-09-11 Andreas Kupries <andreas_kupries@users.sourceforge.net>
* doc/OpenFileChnl.3: Added documentation for Tcl_WriteRaw and
- Tcl_ReadRaw [#414929].
-
- * doc/CrtChannel.3: Added documentation for Tcl_ChannelBuffered
- and Tcl_GetTopChannel [#414929].
+ Tcl_ReadRaw [Bug 414929].
+
+ * doc/CrtChannel.3: Added documentation for Tcl_ChannelBuffered and
+ Tcl_GetTopChannel [Bug 414929].
- * The changes below are a fix for [219253].
+ * The changes below are a fix for [Bug 219253].
* tests/socket.test: Removed _most_ instances of hardwired port
- numbers for listening sockets. Remaining are the ports in all
- tests with constraint 'doTestsWithRemoteServer'. These seem to
- be designed for a more controlled environment and are usually
- skipped when running the testsuite.
+ numbers for listening sockets. Remaining are the ports in all tests
+ with constraint 'doTestsWithRemoteServer'. These seem to be designed
+ for a more controlled environment and are usually skipped when running
+ the testsuite.
- * tests/io.test: Removed all instances of hardwired port numbers
- for listening sockets.
+ * tests/io.test: Removed all instances of hardwired port numbers for
+ listening sockets.
2001-09-10 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/tclEvent.c (TclInExit): Corrected handling of tsd in
- late stages of finalization. [Bug #419449] (darley)
+ * generic/tclEvent.c (TclInExit): Corrected handling of tsd in late
+ stages of finalization. [Bug 419449] (darley)
* tests/stack.test:
* generic/tclInterp.c (AliasObjCmd): Check the numLevels to ensure
- that we aren't hitting some alias loop condition. [Bug #443184]
+ that we aren't hitting some alias loop condition. [Bug 443184]
2001-09-10 Mo DeJong <mdejong@users.sourceforge.net>
* unix/configure: Regen.
- * unix/tcl.m4 (SC_CONFIG_CFLAGS): Don't include . characters
- in the Tcl library name when building on FreeBSD 3.X and later
- systems. [Patch 450725]
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): Don't include . characters in the
+ Tcl library name when building on FreeBSD 3.X and later systems.
+ [Patch 450725]
2001-09-10 Andreas Kupries <andreas_kupries@users.sourceforge.net>
* doc/tclsh.1:
- * doc/Tcl_Main.3:
- * doc/CrtChannel.3:
- * doc/OpenFileChnl.3:
+ * doc/Tcl_Main.3:
+ * doc/CrtChannel.3:
+ * doc/OpenFileChnl.3:
* doc/GetStdChan.3: Enhanced the manpages with cross-references to
- the new manpage and more explanations how these functions deal
- with the standard channels in various situations.
+ the new manpage and more explanations how these functions deal with
+ the standard channels in various situations.
- * doc/StdChannels.3: New manpage describing handling of the
- standard channels by the Tcl library [402725].
+ * doc/StdChannels.3: New manpage describing handling of the standard
+ channels by the Tcl library. [Bug 402725]
2001-09-10 Don Porter <dgp@users.sourceforge.net>
- * unix/mkLinks (Tcl_FSLink): Updated to reflect 2001-08-23
- file system changes.
+ * unix/mkLinks (Tcl_FSLink): Updated to reflect 2001-08-23 file system
+ changes.
* unix/tclLoadShl.c: Added #include of tclInt.h; access to Tcl
- internals, notably TclpUnloadFile(), is required. Thanks to
- Bob Techentin for report and patch. [Bug 459305]
+ internals, notably TclpUnloadFile(), is required. Thanks to Bob
+ Techentin for report and patch. [Bug 459305]
* generic/tclInitScript.h (initScript):
* win/tclWinInit.c (TCL_REGISTRY_KEY, TclpSetVariables): Removed
- vestiges of Tcl's old initialization from registry variables.
- [Bug 455645]
+ vestiges of Tcl's old initialization from registry variables. [Bug
+ 455645]
2001-09-10 Andreas Kupries <andreas_kupries@users.sourceforge.net>
- * generic/tclInt.decls: Also added 'TclWinFlushDirtyChannels' to
- the internal platform specific stub table.
+ * generic/tclInt.decls: Also added 'TclWinFlushDirtyChannels' to the
+ internal platform specific stub table.
* win/tclWinFile.c (TclpObjStat): Now added the call to
- 'TclWinFlushDirtyChannels' to this function. I don't know where
- my head was last thursday (2001-09-06), but the call was
- actually added to 'TclpObjChdir', i.e. the implementation of
- [cd]. Corrected this now. Thanks to Vince Darley for spotting
- this.
+ 'TclWinFlushDirtyChannels' to this function. I don't know where my
+ head was last thursday (2001-09-06), but the call was actually added
+ to 'TclpObjChdir', i.e. the implementation of [cd]. Corrected this
+ now. Thanks to Vince Darley for spotting this.
2001-09-10 Miguel Sofer <msofer@users.sourceforge.net>
* generic/tclProc.c:
- * tests/proc.test: made [proc] bytecompile a no-op for procs
- defined with _args_ as single argument and an empty body.
- [FQ 451441]
-
+ * tests/proc.test: made [proc] bytecompile a no-op for procs defined
+ with _args_ as single argument and an empty body. [FRQ 451441]
+
2001-09-09 Mo DeJong <mdejong@users.sourceforge.net>
* unix/Makefile.in:
- * win/Makefile.in: Use () around variable name
- instead of {}. Use TCLTEST variable directly
- instead of depending on the tcltest alias.
+ * win/Makefile.in: Use () around variable name instead of {}. Use
+ TCLTEST variable directly instead of depending on the tcltest alias.
2001-09-09 David Gravereaux <davygrvy@pobox.com>
* generic/tcl.h:
- * generic/tclPlatDecls.h: Reminder from David Cuthbert <dacut@kanga.org>
- that I hadn't finished the Borland compatibility stuff.
- [Patch: 436116]
+ * generic/tclPlatDecls.h: Reminder from David Cuthbert
+ <dacut@kanga.org> that I hadn't finished the Borland compatibility
+ stuff. [Patch 436116]
2001-09-09 Mo DeJong <mdejong@users.sourceforge.net>
- * tests/cmdAH.test: Modify cmdAH-20.5 and cmdAH-24.8
- to display the file atime or mtime results if
- the test fails.
+ * tests/cmdAH.test: Modify cmdAH-20.5 and cmdAH-24.8 to display the
+ file atime or mtime results if the test fails.
2001-09-08 David Gravereaux <davygrvy@pobox.com>
* win/mkd.bat:
- * win/rmd.bat: made these text files, text files again.
- [Patch: 451333]
+ * win/rmd.bat: made these text files, text files again. [Patch 451333]
2001-09-08 Mo DeJong <mdejong@users.sourceforge.net>
* win/mkd.bat:
- * win/rmd.bat:
- Apply binary property (cvs admin -kb) to files and convert
- to CRLF linefeed format to fix the VC++ build. [Bug #219409]
+ * win/rmd.bat: Apply binary property (cvs admin -kb) to files and
+ convert to CRLF linefeed format to fix the VC++ build. [Bug 219409]
2001-09-08 Vince Darley <vincentdarley@users.sourceforge.net>
- * generic/tclInt.h:
+ * generic/tclInt.h:
* generic/tclFCmd.c:
* doc/FileSystem.3:
- * generic/tclIOUtil.c: removed Tcl_FSCopyFile fallback
- to channel copying, since the channels will not have
- access to interpreters and the channel copying currently
- requires an interp. Code which required cross-platform
- copies always has interpreters, so that solves the problem.
- Fixes bug in TclKit.
-
+ * generic/tclIOUtil.c: removed Tcl_FSCopyFile fallback to channel
+ copying, since the channels will not have access to interpreters and
+ the channel copying currently requires an interp. Code which required
+ cross-platform copies always has interpreters, so that solves the
+ problem. Fixes bug in TclKit.
+
2001-09-07 David Gravereaux <davygrvy@pobox.com>
- * win/tcl.m4: Added -link50compat option so a VC6 linker makes
- a VC5 (pre sp3) compatible import library.
- [Bug: 219257]
+ * win/tcl.m4: Added -link50compat option so a VC6 linker makes a VC5
+ (pre sp3) compatible import library. [Bug 219257]
2001-09-07 Mo DeJong <mdejong@users.sourceforge.net>
* win/tclWinThrd.c (TclpThreadExit): Cast status argument to
- _endthreadex to unsigned instead of DWORD to match the Win32
- function prototype.
+ _endthreadex to unsigned instead of DWORD to match the Win32 function
+ prototype.
2001-09-06 Andreas Kupries <andreas_kupries@users.sourceforge.net>
- * All the changes below serve to fix bug [219148] which reports a
- 80x performance hit for file I/O on Win* systems. On my system
- it was closer to a 120x hit. Problem report by Uwe Traum <no
- email address available>.
+ * All the changes below serve to fix bug [219148] which reports a 80x
+ performance hit for file I/O on Win* systems. On my system it was
+ closer to a 120x hit. Problem report by Uwe Traum <no email address
+ available>.
- The fix goes like this: The obstacle is 'FlushFileBuffers',
- executed whenever Tcl writes data to the OS, as Tcl has to wait
- for the disk to complete I/O, and disks are slow. We remove that
- obstacle. This opens another problem, [file size] reports back
- wrong numbers. So for [file size] we add the call back in. As
- optimization we keep track of the channels which were written to
- and flush only these.
+ The fix goes like this: The obstacle is 'FlushFileBuffers', executed
+ whenever Tcl writes data to the OS, as Tcl has to wait for the disk to
+ complete I/O, and disks are slow. We remove that obstacle. This opens
+ another problem, [file size] reports back wrong numbers. So for [file
+ size] we add the call back in. As optimization we keep track of the
+ channels which were written to and flush only these.
* win/tclWinFile.c (TclpObjStat): Added a call to
- 'TclWinFlushDirtyChannels'. This ensures that [file size] and
- related commands report the correct size of a file even if Tcl
- has recently written to it. Unixoid OS's always report the
- correct size even for files with pending data, but Win*
- syssystem don't. They only report what is actually on disk.
+ 'TclWinFlushDirtyChannels'. This ensures that [file size] and related
+ commands report the correct size of a file even if Tcl has recently
+ written to it. Unixoid OS's always report the correct size even for
+ files with pending data, but Win* syssystem don't. They only report
+ what is actually on disk.
- * win/tclWinInt.h: Added declaration of
- 'TclWinFlushDirtyChannels', making it available to other parts
- of the tcl core.
+ * win/tclWinInt.h: Added declaration of 'TclWinFlushDirtyChannels',
+ making it available to other parts of the tcl core.
* win/tclWinChan.c (TclWinFlushDirtyChannels): New, internal,
- procedure. Goes through the list of open file channels and
- forces the OS to flush its file buffers for all which were
- written to since the last call of this function. This is an
- expensive operation as Tcl has to wait for the OS to complete
- actual writes to the disk.
+ procedure. Goes through the list of open file channels and forces the
+ OS to flush its file buffers for all which were written to since the
+ last call of this function. This is an expensive operation as Tcl has
+ to wait for the OS to complete actual writes to the disk.
- (FileInfo): Added dirty flag required by the procedure above.
+ (FileInfo): Added dirty flag required by the procedure above.
- (FileOutputProc): Removed flushing of file buffers, setting the
- dirty flag instead. This means that the previously incurred
- delays do not happen anymore.
+ (FileOutputProc): Removed flushing of file buffers, setting the dirty
+ flag instead. This means that the previously incurred delays do not
+ happen anymore.
- (TclWinOpenFileChannel): Added initialization of 'dirty' flag.
+ (TclWinOpenFileChannel): Added initialization of 'dirty' flag.
2001-09-06 Jeff Hobbs <jeffh@ActiveState.com>
@@ -1815,48 +1762,48 @@
* tests/http.test:
* library/http/pkgIndex.tcl:
* library/http/http.tcl (geturl): correctly get charset parameter
- and convert text according to specified encoding (if known). RFC
- iso8859-1 is used by default. Also recognize Content-encoding to
- see if we should do binary translation. Added a CYA -binary
- switch for the cases that were missed. [Bug #219211 #219399]
+ and convert text according to specified encoding (if known). RFC
+ iso8859-1 is used by default. Also recognize Content-encoding to see
+ if we should do binary translation. Added a CYA -binary switch for the
+ cases that were missed. [Bugs 219211, 219399]
* tests/ioUtil.test: changed to make better use of constraints and
remove knownBug constraints that weren't valid.
2001-09-06 Don Porter <dgp@users.sourceforge.net>
- * tests/unixInit.test (unixInit-3.2): Updated test to support
- newer HP-UX releases that properly report euc-jp as the system
- encoding for Japanese. Bug report and patch verification by Bob
- Techentin. [Bug 453883]
+ * tests/unixInit.test (unixInit-3.2): Updated test to support newer
+ HP-UX releases that properly report euc-jp as the system encoding for
+ Japanese. Bug report and patch verification by Bob Techentin. [Bug
+ 453883]
* doc/http.n:
* library/http/*.tcl:
* tools/tcl.wse.in:
* tools/tclmin.wse:
* unix/Makefile.in:
- * win/{Mm}akefile.*: Updated http package to version 2.4,
- reflecting the new features just added.
+ * win/{Mm}akefile.*: Updated http package to version 2.4, reflecting
+ the new features just added.
2001-09-06 Vince Darley <vincentdarley@users.sourceforge.net>
- * generic/tclTest.c: tests of old-fs hooks no longer cause problems
- in threaded builds. Also removed unused unload proc.
+ * generic/tclTest.c: tests of old-fs hooks no longer cause problems in
+ threaded builds. Also removed unused unload proc.
* generic/tcl.decls:
- * generic/tclIOUtilc: added Tcl_FSMountsChanged so that a vfs
- can inform the filesystem that the filesystem epoch must be
- changed (since cached filesystems may now be incorrect). Fixes
- problem running tclvfs extension.
- * library/tcltest/tcltest.tcl: if tests aren't in a native
- filesystem, then don't use pipes to run them. [Bug 458741]
-
+ * generic/tclIOUtilc: added Tcl_FSMountsChanged so that a vfs can
+ inform the filesystem that the filesystem epoch must be changed (since
+ cached filesystems may now be incorrect). Fixes problem running tclvfs
+ extension.
+ * library/tcltest/tcltest.tcl: if tests aren't in a native filesystem,
+ then don't use pipes to run them. [Bug 458741]
+
2001-09-06 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * generic/tcl.decls (479 generic):
- * generic/tclIO.c (Tcl_Seek,Tcl_Tell,Tcl_OutputBuffered): Added
- public function to return the size of the output buffer and
- reworked other channel functions to use this shared functionality
- and that of Tcl_InputBuffered() too. [TIP#49, Rolf Schroedter]
+ * generic/tcl.decls (479 generic):
+ * generic/tclIO.c (Tcl_Seek,Tcl_Tell,Tcl_OutputBuffered): Added public
+ function to return the size of the output buffer and reworked other
+ channel functions to use this shared functionality and that of
+ Tcl_InputBuffered() too. [TIP#49, Rolf Schroedter]
2001-09-05 David Gravereaux <davygrvy@pobox.com>
@@ -1864,39 +1811,36 @@
support.
* win/tclWinPipe.c:
- * win/tclWinPort.h: More Borland compatibility fixes. Changed
- EDQUOT #define from 49 to 69. Borland had a clash as it was already
- using this number. Upon advice from Helmut Giese, EDQUOT has been
- found in other header files #defined as 69.
- [Patch: 436116]
+ * win/tclWinPort.h: More Borland compatibility fixes. Changed EDQUOT
+ #define from 49 to 69. Borland had a clash as it was already using
+ this number. Upon advice from Helmut Giese, EDQUOT has been found in
+ other header files #defined as 69. [Patch 436116]
* win/.cvsignore: A few more glob patterns added.
* win/makefile.bc (new): Borland lives once more! rejoice..
* generic/tclAlloc.c: Small Borland compatibility fix.
- * win/tclWinTime.c: More Borland compatibility fixes.
- [Patch: 436116]
+ * win/tclWinTime.c: More Borland compatibility fixes. [Patch 436116]
2001-09-05 Vince Darley <vincentdarley@users.sourceforge.net>
- * tests/winFCmd.test: made notWin2000 constraint false if not
- running on Windows at all.
-
+ * tests/winFCmd.test: made notWin2000 constraint false if not running
+ on Windows at all.
+
2001-09-04 David Gravereaux <davygrvy@pobox.com>
- * win/tclWinThrd.c: Revisited _beginthreadex() stuff. Instead
- of assuming a c-runtime implimentation of _beginthreadex normal,
- I reversed the logic to not assume, and use when is by explicitly
+ * win/tclWinThrd.c: Revisited _beginthreadex() stuff. Instead of
+ assuming a c-runtime implimentation of _beginthreadex normal, I
+ reversed the logic to not assume, and use when is by explicitly
needing to add runtimes that support it such as Borland.
* generic/tcl.h:
- * generic/tclPlatDecls.h: Borland compatibility change so
- ClientData was properly typed as a void* and TCHAR would not be
- defined twice.
+ * generic/tclPlatDecls.h: Borland compatibility change so ClientData
+ was properly typed as a void* and TCHAR would not be defined twice.
- * generic/tcl.h: Removed a small mistake from before. Changes to
- the EXTERN macro for proper Borland compatibility will have to see
- a TIP. What's this with the MS compiler:
+ * generic/tcl.h: Removed a small mistake from before. Changes to the
+ EXTERN macro for proper Borland compatibility will have to see a TIP.
+ What's this with the MS compiler:
__declspec(dllexport) int func (int a, int b);
@@ -1908,115 +1852,110 @@
2001-09-04 Don Porter <dgp@users.sourceforge.net>
- * compat/strtod.c (strtod): Fixed failure to handle expressions
- like 3eq2 and failure to set errno on overflow. [Bug 440894]
+ * compat/strtod.c (strtod): Fixed failure to handle expressions like
+ 3eq2 and failure to set errno on overflow. [Bug 440894]
2001-09-04 Miguel Sofer <msofer@users.sourceforge.net>
* generic/tclProc.c:
- * tests/proc.test: made [proc] check that formal args have
- simple names [Bug 458548]
+ * tests/proc.test: made [proc] check that formal args have simple
+ names. [Bug 458548]
2001-09-04 Vince Darley <vincentdarley@users.sourceforge.net>
- Minor bug fixes in filesystem, plus small vfs changes as a
- result of enabling the test filesystem to work properly.
+ Minor bug fixes in filesystem, plus small vfs changes as a result of
+ enabling the test filesystem to work properly.
* tests/fileName.test: ensure new test cleans up after itself
- * doc/filename.n:
- * generic/tclFileName.c: improved Mac path handling and document
- why [Bug: 421842] on Windows handling of UNC paths is not valid.
- Documentation and code now much clearer on what is and is not a
- UNC path.
+ * doc/filename.n:
+ * generic/tclFileName.c: improved Mac path handling and document why
+ [Bug 421842] on Windows handling of UNC paths is not valid.
+ Documentation and code now much clearer on what is and is not a UNC
+ path.
* doc/FileSystem.3:
* unix/tclUnixPipe.c:
* generic/tclFCmd.c:
- * generic/tclIOUtil.c: fixed error message, fixed [Bug: 453512]
- about dangerous use of tmpnam, replaced with mkstemp.
- Documented all the changes.
- * generic/tclTest.c: made test vfs fully functional as a
- 'reporting filesystem'.
+ * generic/tclIOUtil.c: fixed error message, fixed [Bug 453512] about
+ dangerous use of tmpnam, replaced with mkstemp. Documented all the
+ changes.
+ * generic/tclTest.c: made test vfs fully functional as a 'reporting
+ filesystem'.
* generic/tcl.stubs:
* generic/tcl.h:
- * generic/tclInt.h:
+ * generic/tclInt.h:
* generic/tclIOUtil.c:
* doc/file.n:
- * various platform-specific 'TclpLoadFile': fixed comments about
- unload behaviour, and completed objectification of loading.
- Required change to Tcl_Filesystem lookup table, so incompatible
- with 8.4a3, but not older versions of Tcl. The change also
- allows 'link' and 'reporting' filesystems to function correctly
- when loading files. Implementation of 'file delete -force'
- copes with case where cwd is inside the directory. Moved
- overlooked Tcl_FSGetPathType from internal to external API.
- Made sure filesystems which are registered and then unregistered
- are only freed when all references to them are gone.
+ * various platform-specific 'TclpLoadFile': fixed comments about
+ unload behaviour, and completed objectification of loading. Required
+ change to Tcl_Filesystem lookup table, so incompatible with 8.4a3, but
+ not older versions of Tcl. The change also allows 'link' and
+ 'reporting' filesystems to function correctly when loading files.
+ Implementation of 'file delete -force' copes with case where cwd is
+ inside the directory. Moved overlooked Tcl_FSGetPathType from internal
+ to external API. Made sure filesystems which are registered and then
+ unregistered are only freed when all references to them are gone.
Documented changes.
- * unix/tclUnixFCmd.c: when deleting directories recursively,
- make sure permissions are ok. Together with the above, this
- fixes [Bug: 219139]
- * tests/winFCmd.test: differentiated test results for win2k
- versus not. This fixes [Bug: 219239]
- * tests/fCmd.test: added tests for 'file delete -force' where
- the cwd is inside, and when permissions are inadequate.
-
+ * unix/tclUnixFCmd.c: when deleting directories recursively, make sure
+ permissions are ok. Together with the above, this fixes [Bug 219139]
+ * tests/winFCmd.test: differentiated test results for win2k versus
+ not. This fixes [Bug: 219239]
+ * tests/fCmd.test: added tests for 'file delete -force' where the cwd
+ is inside, and when permissions are inadequate.
+
2001-09-04 Miguel Sofer <msofer@users.sourceforge.net>
- * generic/tclCompile.c: fixed incorrect operands for INST_LIST
- [Bug: 458241] (David Cuthbert, dacut@users.sourceforge.net)
+ * generic/tclCompile.c: fixed incorrect operands for INST_LIST [Bug
+ 458241] (David Cuthbert, dacut@users.sourceforge.net)
2001-09-03 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/tclExecute.c (TclExecuteByteCode): fixed missing comma
- in debug macro.
+ * generic/tclExecute.c (TclExecuteByteCode): fixed missing comma in
+ debug macro.
2001-09-03 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * doc/ExprLongObj.3: Fixed error in documentation of argument type
- to Tcl_ExprObj [Bug: 457435]
+ * doc/ExprLongObj.3: Fixed error in documentation of argument type to
+ Tcl_ExprObj [Bug 457435]
2001-09-02 David Gravereaux <davygrvy@pobox.com>
* win/tclWinThrd.c: Portability fix for Cygwin who's c-runtime,
not surprisingly, doesn't have the MSVCRT specific _beginthreadex /
- _endthreadex pair. This might have to be revisited for proper
- Borland, lcc32, Watcom and other support as well.
- [Patch: 444255]
+ _endthreadex pair. This might have to be revisited for proper Borland,
+ lcc32, Watcom and other support as well. [Patch 444255]
* win/tclWinThrd.c: Moved FinalizeConditionEvent() proto to within
the main #ifdef TCL_THREADS block to avoid mingw warning about it
being there but unused.
- * win/makefile.vc: Added -Zl (zee el) to tclStubLib.c compile line
- to make sure the tclstub84.lib static library is built without
- requiring a specific C-runtime library at link-time for the end-use
- developer. It has been noted on c.l.t that this trips many first
- time users trying to make extensions.
- [Patch: 403533]
+ * win/makefile.vc: Added -Zl (zee el) to tclStubLib.c compile line to
+ make sure the tclstub84.lib static library is built without requiring
+ a specific C-runtime library at link-time for the end-use developer.
+ It has been noted on c.l.t that this trips many first time users
+ trying to make extensions. [Patch 403533]
2001-08-31 Jeff Hobbs <jeffh@ActiveState.com>
* generic/tclInt.h: added TclCompileListCmd header
* generic/tclBasic.c: added TclCompileListCmd compile proc
- * generic/tclCompCmds.c (TclCompileListCmd): function to compile
- the 'list' command at parse time.
- * generic/tclExecute.c (TclExecuteByteCode): definition of
- INST_LIST bytecode.
+ * generic/tclCompCmds.c (TclCompileListCmd): function to compile the
+ 'list' command at parse time.
+ * generic/tclExecute.c (TclExecuteByteCode): definition of INST_LIST
+ bytecode.
- * doc/StringObj.3: added words of warning to use Tcl_ResetResult
- with the Tcl_Append* functions.
+ * doc/StringObj.3: added words of warning to use Tcl_ResetResult with
+ the Tcl_Append* functions.
* tests/compile.test: added compile-11.* interp result checks
- * generic/tclUtil.c (TclGetIntForIndex): added Tcl_ResetResult
- before Tcl_AppendStringsToObj to prevent shared object crash when
- called from bcc instruction. The Tcl_Append* calls that append to
- the result object that are invoked by bcc insts must remember to
- call Tcl_ResetResult because the bcc doesn't do this for us.
- [Bug #456892]
+ * generic/tclUtil.c (TclGetIntForIndex): added Tcl_ResetResult before
+ Tcl_AppendStringsToObj to prevent shared object crash when called from
+ bcc instruction. The Tcl_Append* calls that append to the result
+ object that are invoked by bcc insts must remember to call
+ Tcl_ResetResult because the bcc doesn't do this for us. [Bug 456892]
2001-08-30 Jeff Hobbs <jeffh@ActiveState.com>
- * generic/tclIndexObj.c: fixed some casting problems that upset
- Crays. [Bug #419528] (andreasen)
+ * generic/tclIndexObj.c: fixed some casting problems that upset Crays.
+ [Bug 419528] (andreasen)
2001-08-30 Don Porter <dgp@users.sourceforge.net>
@@ -2024,120 +1963,116 @@
2001-08-30 Miguel Sofer <msofer@users.sourceforge.net>
- * generic/tclExecute.c: allow cached fully-qualified command names
- to be usable from different namespaces within the same interpreter
- without forcing a new lookup. This speeds up scripts that pass
- command names in variables ("this" in some OO packages).
- [Patch 456668].
+ * generic/tclExecute.c: allow cached fully-qualified command names to
+ be usable from different namespaces within the same interpreter
+ without forcing a new lookup. This speeds up scripts that pass command
+ names in variables ("this" in some OO packages). [Patch 456668]
2001-08-30 Vince Darley <vincentdarley@users.sourceforge.net>
- Further fs updates. After examining the most common Tcl
- extensions (TclX, BLT, Tk, TclPro, Mktclapp), it has been
- determined that only TclpGetCwd and the Access/Stat/Open
- insert/delete hooks of the internal fs functions are ever used.
- The remaining functions from Tcl's internal interfaces have
- therefore been removed, since Tcl now exports a more suitable
- public API (Tcl_FS...)
-
+ Further fs updates. After examining the most common Tcl extensions
+ (TclX, BLT, Tk, TclPro, Mktclapp), it has been determined that only
+ TclpGetCwd and the Access/Stat/Open insert/delete hooks of the
+ internal fs functions are ever used. The remaining functions from
+ Tcl's internal interfaces have therefore been removed, since Tcl now
+ exports a more suitable public API (Tcl_FS...)
+
* generic/tclInt.stubs:
- * generic/tclInt.h: updated for removed internal functions.
- Some new internal functions have been put in tclInt.h (and
- not exported in the stub table because good public equivalents
- exist).
- * generic/tclTest.c: some test functions used the internal private
- APIs. These tests have been retained, but modified to use
- public APIs. Also objectified the internal filesystem tests.
- * win/tclWinFile.c: removed TclpStat, TclpAccess and refactored
- code to use NativeAccess, NativeStat. This should speed up
- stat, access and glob commands.
- * win/tclWinFCmd.c: removed all TclpCopy/Rename/Delete
- File/Directory string-based procedures which aren't used any more.
- Improved efficiency of some other procedures. Ensure that filename
- conversions with a NULL interp do not crash Tcl.
+ * generic/tclInt.h: updated for removed internal functions. Some new
+ internal functions have been put in tclInt.h (and not exported in the
+ stub table because good public equivalents exist).
+ * generic/tclTest.c: some test functions used the internal private
+ APIs. These tests have been retained, but modified to use public APIs.
+ Also objectified the internal filesystem tests.
+ * win/tclWinFile.c: removed TclpStat, TclpAccess and refactored code
+ to use NativeAccess, NativeStat. This should speed up stat, access and
+ glob commands.
+ * win/tclWinFCmd.c: removed all TclpCopy/Rename/Delete File/Directory
+ string-based procedures which aren't used any more. Improved
+ efficiency of some other procedures. Ensure that filename conversions
+ with a NULL interp do not crash Tcl.
* mac/tclMacFCmd.c: wrapped long lines and cleaned up
- TclpObjNormalizePath, removed all TclpCopy/Rename/Delete
+ TclpObjNormalizePath, removed all TclpCopy/Rename/Delete
File/Directory string-based procedures which aren't used any more.
* mac/tclMacFile.c: removed obsolete TclpStat, TclpAccess, TclpChdir,
etc.
* unix/tclUnixFCmd.c: removed use of TclpAccess, removed all
TclpCopy/Rename/Delete File/Directory string-based procedures which
aren't used any more.
- * unix/tclUnixFile.c: removed obsolete TclpStat, TclpAccess, TclpChdir,
- etc.
+ * unix/tclUnixFile.c: removed obsolete TclpStat, TclpAccess,
+ TclpChdir, etc.
* tcl(Unix|Mac|Win)Chan.c: objectified TclpOpenFileChannel.
* various 'load' implementations all objectified.
* generic/tclFileName.c: removed redundant code.
* generic/tclIOUtil.c: removed TclStat, TclAccess, TclpListVolumes.
- Fix to MatchInDirectory at the root of a volume. Also improved
- some documentation, and improved default path joining behaviour
- for virtual filesystems, especially regarding '~'.
+ Fix to MatchInDirectory at the root of a volume. Also improved some
+ documentation, and improved default path joining behaviour for virtual
+ filesystems, especially regarding '~'.
* tests/fileName.test: added tests to check for bugs fixed above.
* doc/FileName.3: improved documentation
-
+
2001-08-30 David Gravereaux <davygrvy@pobox.com>
* generic/tclAsync.c:
* generic/tclEvent.c:
* generic/tclInt.h: Improper cleanup of asyncMutex in tclAsync.c
- repaired. TclFinalizeSynchronization() was trying to remove a
- registered mutex that was dumped earlier when the TSD it was stored
- in was cleared. This was only surfacing on *nix. Windows was being
- masked by mutexes not actually being returned to the system! That
- was repaired in a previous patch. Needed to add a private
+ repaired. TclFinalizeSynchronization() was trying to remove a
+ registered mutex that was dumped earlier when the TSD it was stored in
+ was cleared. This was only surfacing on *nix. Windows was being masked
+ by mutexes not actually being returned to the system! That was
+ repaired in a previous patch. Needed to add a private
TclFinalizeAsync() to tclAsync.c and called from Tcl_FinalizeThread().
- Pheww.. Is this done yet?
- [Bug: 414419] requested by Rob Ratcliff <rrr6399@futuretek.com>
+ Pheww.. Is this done yet? [Bug 414419] requested by Rob Ratcliff
+ <rrr6399@futuretek.com>
2001-08-28 Jeff Hobbs <jeffh@ActiveState.com>
* generic/tclCompCmds.c (TclPushVarName): noted 'static' defn.
- [Bug #453872]
+ [Bug 453872]
2001-08-26 Don Porter <dgp@users.sourceforge.net>
* library/auto.tcl (tcl_findLibrary):
* tests/unixInit.test (unixInit-2.{1,9}):
* unix/tclUnixInit.c (TclpInitLibraryPath):
- * win/tclWinInit.c (TclpInitLibraryPath): Corrected
- inconsistency between the search path for script libraries and
- the directory name $DISTNAME into which distributions built
- by 'make test' unpack. [Bug 455642]
+ * win/tclWinInit.c (TclpInitLibraryPath): Corrected inconsistency
+ between the search path for script libraries and the directory name
+ $DISTNAME into which distributions built by 'make test' unpack. [Bug
+ 455642]
2001-08-24 Jeff Hobbs <jeffh@ActiveState.com>
* tests/stringComp.test: added string-1.3
* generic/tclCompCmds.c (TclCompileStringCmd): changed to return
TCL_OUT_LINE_COMPILE instead of TCL_ERROR when compiling and an
- unknown string method is called. This is necessary as the string
+ unknown string method is called. This is necessary as the string
command may be never called, or not until 'string' is redefined.
2001-08-24 Vince Darley <vincentdarley@users.sourceforge.net>
* doc/glob.n: documented windows-style path issue with glob.
- [Bug: 219392]
+ [Bug 219392]
* doc/filename.n: documented windows path/file length limitation.
- [Bug: 454597]
+ [Bug 454597]
2001-08-24 Don Porter <dgp@users.sourceforge.net>
- * tests/unixInit.test (unixInit-2.9): Corrected expected result
- to match Tcl's quirky construction of its init library path.
+ * tests/unixInit.test (unixInit-2.9): Corrected expected result to
+ match Tcl's quirky construction of its init library path.
2001-08-23 Andreas Kupries <andreas_kupries@users.sourceforge.net>
- * win/tclWinPipe.c (BuildCommandLine): Fixed tcl Bug
- [432499]. Part of the code used the non-absolute path to the
- executable to determine quoting. This failed if the absolute
- path contained spaces, but the application name itself not. This
- bug caused no trouble on Win NT 5, but does for other variants
- in the Win* family. Report and fix due to Ken Poole
- <kenpoole@users.sourceforge.net>.
+ * win/tclWinPipe.c (BuildCommandLine): Fixed [Bug 432499]. Part of the
+ code used the non-absolute path to the executable to determine
+ quoting. This failed if the absolute path contained spaces, but the
+ application name itself not. This bug caused no trouble on Win NT 5,
+ but does for other variants in the Win* family. Report and fix due to
+ Ken Poole <kenpoole@users.sourceforge.net>.
2001-08-23 Jeff Hobbs <jeffh@ActiveState.com>
* unix/configure:
- * unix/tcl.m4: added QNX-6 build support. [Bug #219410] (loverso)
+ * unix/tcl.m4: added QNX-6 build support. [Bug 219410] (loverso)
* unix/tclUnixFCmd.c:
* generic/tclIOUtil.c:
@@ -2145,97 +2080,93 @@
2001-08-23 Vince Darley <vincentdarley@users.sourceforge.net>
- Variety of small filesystem and vfs issues fixed or improved.
- The new fs code allows many new opportunities for efficiency
- improvements through the objectified API. The main changes
- integrated here are such efficiency improvements. Some
- limitations of the original implementation have also now been
- lifted. Meanwhile a variety of fs bugs (some old, some new)
- have also been fixed.
-
- * generic/tclFileName.c: Made Tcl_FSSplitPath more efficient,
- and removed some static string-based procedures which are no
- longer used. Much more objectification. Tcl_FSJoinPath
- is now very efficient and more aware of virtual filesystems.
- Clarified where the Mac-specific code attempts to interpret
- Unix-style paths. Modified TclDoGlob to use lstat not
- access to fix [Bug: 434876, L. Virden]
+ Variety of small filesystem and vfs issues fixed or improved. The new
+ fs code allows many new opportunities for efficiency improvements
+ through the objectified API. The main changes integrated here are such
+ efficiency improvements. Some limitations of the original
+ implementation have also now been lifted. Meanwhile a variety of fs
+ bugs (some old, some new) have also been fixed.
+
+ * generic/tclFileName.c: Made Tcl_FSSplitPath more efficient, and
+ removed some static string-based procedures which are no longer used.
+ Much more objectification. Tcl_FSJoinPath is now very efficient and
+ more aware of virtual filesystems. Clarified where the Mac-specific
+ code attempts to interpret Unix-style paths. Modified TclDoGlob to use
+ lstat not access to fix [Bug 434876] (L. Virden)
+
* tcl(Win|Unix|Mac)FCmd.c:
* tcl(Win|Unix|Mac)File.c: replaced TclpListVolumes with
- TclpObjListVolumes with different signature, updated code due
- to more efficient signature of Tcl_FSGetTranslatedPath. Used
- cached native paths where possible to improve efficiency --
- this was completed on MacOS, but on Unix and Win the traversal
- functions make the task much more complex, so there are still
- some improvements possible there. Removed unused
- TclpNormalizePath which had been left in tclWinFCmd.c.
- Objectified all 'file attributes' functions. Fixed the new
- [Bug:451571, Bruce Stephens] which is most obvious on Unix,
- but could occur on MacOS or Windows. This bug actually existed
- in Tcl 8.3.x but was only made obvious by the recent filesystem
- overhaul when the code was exercised more heavily.
- * tests/fileName.test: Three new tests to exercise the above bug,
- and make sure it is fixed correctly.
- * unix/tclUnixFile.c: avoid panic in glob when a link
- doesn't point anywhere. It would probably be good to define
- exactly what Tcl should do in circumstances like these, and
- make sure mac/win/unix all behave accordingly. [Bug: 417111,
- Hemang Lavana]. Also fixed misleading/obsolete comment in the code.
- * generic/tcl.stubs: changed signature of Tcl_FSGetTranslatedPath
- and added Tcl_FSGetTranslatedStringPath.
+ TclpObjListVolumes with different signature, updated code due to more
+ efficient signature of Tcl_FSGetTranslatedPath. Used cached native
+ paths where possible to improve efficiency -- this was completed on
+ MacOS, but on Unix and Win the traversal functions make the task much
+ more complex, so there are still some improvements possible there.
+ Removed unused TclpNormalizePath which had been left in tclWinFCmd.c.
+ Objectified all 'file attributes' functions. Fixed the new [Bug
+ 451571, Bruce Stephens] which is most obvious on Unix, but could occur
+ on MacOS or Windows. This bug actually existed in Tcl 8.3.x but was
+ only made obvious by the recent filesystem overhaul when the code was
+ exercised more heavily.
+ * tests/fileName.test: Three new tests to exercise the above bug, and
+ make sure it is fixed correctly.
+ * unix/tclUnixFile.c: avoid panic in glob when a link doesn't point
+ anywhere. It would probably be good to define exactly what Tcl should
+ do in circumstances like these, and make sure mac/win/unix all behave
+ accordingly. [Bug 417111] (Hemang Lavana). Also fixed
+ misleading/obsolete comment in the code.
+ * generic/tcl.stubs: changed signature of Tcl_FSGetTranslatedPath and
+ added Tcl_FSGetTranslatedStringPath.
These changes allow further optimisations in the FS code.
- * generic/tcl.h: changed signature of Tcl_FSListVolumes so that
- it doesn't require a Tcl interpreter plus result. Renamed
- Tcl_FSReadLink to Tcl_FSLink with additional argument so
- we can support making links in the future. [Patch: 450340]
- * generic/tclInt.h:
- added declaration for TclpObjListVolumes. Objectified
- internal call signatures for 'file attributes' functions, and
- added an internal objectified get path type function.
- * generic/tclIOUtil.c: added the moved function TclpListVolumes
- which calls platform specific code (needed for backwards
- compatibility), and improved efficiency of parts of the FS
- (particularly file normalization). Much less copying and
- memory allocation is required now. added new GetPathType
- so that changes in 'file volumes' can actually affect files'
- types, and objectified more code. Made current code work
- with test suite artificially changing current platform.
+ * generic/tcl.h: changed signature of Tcl_FSListVolumes so that it
+ doesn't require a Tcl interpreter plus result. Renamed Tcl_FSReadLink
+ to Tcl_FSLink with additional argument so we can support making links
+ in the future. [Patch: 450340]
+ * generic/tclInt.h: added declaration for TclpObjListVolumes.
+ Objectified internal call signatures for 'file attributes' functions,
+ and added an internal objectified get path type function.
+ * generic/tclIOUtil.c: added the moved function TclpListVolumes which
+ calls platform specific code (needed for backwards compatibility), and
+ improved efficiency of parts of the FS (particularly file
+ normalization). Much less copying and memory allocation is required
+ now. added new GetPathType so that changes in 'file volumes' can
+ actually affect files' types, and objectified more code. Made current
+ code work with test suite artificially changing current platform.
Added 'static' keywords where required.
* generic/tclIO.c:
- * generic/tclTest.c: Added 'static' keywords, fixing
- [Bug: 453872, Bob Techentin]
- * generic/tclCmdAH.c: file command implementation updated for
- API changes, removed unnecessary special-case SplitPath static
- function, since it no longer helps prevent code duplication.
- Moved setting of interpreter result to each individual location
- that actually required it, to avoid very large code separation
- between reading and setting the result.
- * doc/FileSystem.3: updated documentation for the new or
- changed APIs, and clarified some issues.
+ * generic/tclTest.c: Added 'static' keywords, fixing [Bug 453872] (Bob
+ Techentin)
+ * generic/tclCmdAH.c: file command implementation updated for API
+ changes, removed unnecessary special-case SplitPath static function,
+ since it no longer helps prevent code duplication. Moved setting of
+ interpreter result to each individual location that actually required
+ it, to avoid very large code separation between reading and setting
+ the result.
+ * doc/FileSystem.3: updated documentation for the new or changed APIs,
+ and clarified some issues.
* doc/SplitPath.3: added pointer to newer APIs in FileSystem.3
- * doc/filename.n: clarified current implementation of tilde
- support on Mac/Win. [Bug:453514, Sergey Kuzmin]
- * doc/glob.n: improved documentation for '-directory' and '-path'
+ * doc/filename.n: clarified current implementation of tilde support on
+ Mac/Win. [Bug 453514] (Sergey Kuzmin)
+ * doc/glob.n: improved documentation for '-directory' and '-path'
options.
-
- There are now many private, obsolete, platform-specific 'Tclp'
- string-based filesystem APIs which could be removed. We should
- check whether any of these are used by extensions and, at least
- in Tcl 9, remove them.
-
- The above changes signify a ***POTENTIAL INCOMPATIBILITY***
- with 8.4a3, since signatures of two functions in the new API
- have changed, but not with older versions of Tcl.
+
+ There are now many private, obsolete, platform-specific 'Tclp'
+ string-based filesystem APIs which could be removed. We should check
+ whether any of these are used by extensions and, at least in Tcl 9,
+ remove them.
+
+ The above changes signify a ***POTENTIAL INCOMPATIBILITY*** with
+ 8.4a3, since signatures of two functions in the new API have changed,
+ but not with older versions of Tcl.
2001-08-23 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * generic/tclBinary.c (FormatNumber): Extract a long from the
- object and not an int, to stop [binary format] from being unable
- to format some input numbers on architectures where sizeof(int) is
- less than sizeof(long) (particularly Alpha.) [tiprender Bug #441861]
+ * generic/tclBinary.c (FormatNumber): Extract a long from the object
+ and not an int, to stop [binary format] from being unable to format
+ some input numbers on architectures where sizeof(int) is less than
+ sizeof(long) (particularly Alpha). [tiprender Bug 441861]
- * tests/format.test: Converted conditional execution of tests into
- a test constraint.
+ * tests/format.test: Converted conditional execution of tests into a
+ test constraint.
2001-08-22 Jeff Hobbs <jeffh@ActiveState.com>
@@ -2243,90 +2174,88 @@
* win/makefile.vc: updated install target for dde1.2
* doc/dde.n: fixed dde man page (which was totally incorrect).
* tests/winDde.test:
- * win/tclWinDde.c (Tcl_DdeObjCmd): added -binary option to dde
- request command to allow for returning binary data. [Bug #227482]
+ * win/tclWinDde.c (Tcl_DdeObjCmd): added -binary option to dde request
+ command to allow for returning binary data. [Bug 227482]
Updated dde to 1.2
- * tests/tcltest.test: added unixExecs constraint to files that
- used 'grep' in the test. [Bug #453143]
+ * tests/tcltest.test: added unixExecs constraint to files that used
+ 'grep' in the test. [Bug 453143]
+
+ * library/tcltest/tcltest.tcl: fixed stdio constraint test. [Patch
+ 454050] (stanton)
+ Simplified unixExecs constraint test.
- * library/tcltest/tcltest.tcl: fixed stdio constraint test.
- [Patch #454050] (stanton)
- Simplified unixExecs constraint test.
-
2001-08-22 Don Porter <dgp@users.sourceforge.net>
- * tests/ioUtil.test (ioUtil-3.*): Corrected errors in tests
- revealed by fix of overagressive compiler. [Bug 451200]
+ * tests/ioUtil.test (ioUtil-3.*): Corrected errors in tests revealed
+ by fix of overagressive compiler. [Bug 451200]
2001-08-21 Miguel Sofer <msofer@users.sourceforge.net>
* generic/tclCompCmds.c:
- * tests/compile.test: Fixed overagressive compilation of [catch]:
- it was catching errors at substitution time. [Bug #219184]
-
+ * tests/compile.test: Fixed overagressive compilation of [catch]: it
+ was catching errors at substitution time. [Bug 219184]
+
2001-08-21 Jeff Hobbs <jeffh@ActiveState.com>
- * tests/tcltest.test (tcltest-12.2): fixed test that would break
- when env vars weren't Tcl list friendly [Patch #454046] (stanton)
+ * tests/tcltest.test (tcltest-12.2): fixed test that would break when
+ env vars weren't Tcl list friendly [Patch 454046] (stanton)
2001-08-20 Jeff Hobbs <jeffh@ActiveState.com>
- * library/http/http.tcl (geturl): added port number to Host:
- header to comply with HTTP/1.1 spec (RFC 2068). [Bug #452217]
+ * library/http/http.tcl (geturl): added port number to Host: header to
+ comply with HTTP/1.1 spec (RFC 2068). [Bug 452217]
2001-08-16 David Gravereaux <davygrvy@pobox.com>
* tools/tcl.wse.in:
* tools/tcl.hpj.in:
* win/tcl.hpj.in: Removed -kb storage in CVS to ensure these text
- files are checked-out in the translation mode CVS is in. Setting
- these as binary as part of an effort to make sure they are always
- in CRLF, no matter what the CVS translation, is bypassing how CVS
- works and is confusing.
+ files are checked-out in the translation mode CVS is in. Setting these
+ as binary as part of an effort to make sure they are always in CRLF,
+ no matter what the CVS translation, is bypassing how CVS works and is
+ confusing.
- * tools/genStubs.tcl: Removed LF-only output. Having to reconvert
- back to CRLF before committing to CVS was giving me a headache.
- [Bug: 451333]
+ * tools/genStubs.tcl: Removed LF-only output. Having to reconvert
+ back to CRLF before committing to CVS was giving me a headache. [Bug
+ 451333]
* win/makefile.vc: replaced $(WINDIR) with $(include32) for the
- .rc.res inference rule. winver.h wasn't getting included.
- [Bug: 445630]
+ .rc.res inference rule. winver.h wasn't getting included. [Bug 445630]
2001-08-14 Miguel Sofer <msofer@users.sourceforge.net>
* generic/tclBasic.c: make the intial maxNestingDepth of an
- interpreter be MAX_NESTING_DEPTH instead of a hardwired value
- [Bug: 232564]
+ interpreter be MAX_NESTING_DEPTH instead of a hardwired value. [Bug
+ 232564]
2001-08-13 Miguel Sofer <msofer@users.sourceforge.net>
- * tests/trace.test: Corrected test numbers [Bug: 449794]
+ * tests/trace.test: Corrected test numbers. [Bug 449794]
2001-08-12 Mo DeJong <mdejong@redhat.com>
* unix/configure: Regen.
* unix/configure.in:
- * unix/tcl.m4: Use GCC variable set by AC_PROG_CC instead
- of defining our own using_gcc variable.
+ * unix/tcl.m4: Use GCC variable set by AC_PROG_CC instead of defining
+ our own using_gcc variable.
2001-08-11 Vince Darley <vincentdarley@users.sourceforge.net>
Variety of small issues introduced by the vfs code fixed:
* generic/tclIOUtil.c: uninitialised read.
- * generic/tclFCmd.c: possible memory leak in file delete
- with error condition.
+ * generic/tclFCmd.c: possible memory leak in file delete with error
+ condition.
2001-08-10 Miguel Sofer <msofer@users.sourceforge.net>
- * generic/tclVar.c:
+ * generic/tclVar.c:
* tests/trace.test: Insure that [array] traces work correctly for
- undefined variables [Bug: 449094]
+ undefined variables. [Bug 449094]
2001-08-09 Mo DeJong <mdejong@redhat.com>
- * unix/Makefile.in: Delete the unused getcwd.o
- target. This fixes bug #440942.
+ * unix/Makefile.in: Delete the unused getcwd.o target. [Bug 440942]
2001-08-08 Don Porter <dgp@users.sourceforge.net>
@@ -2340,8 +2269,8 @@
* library/reg/pkgIndex.tcl:
* library/tcltest/tcltest.tcl:
* library/tcltest/pkgIndex.tcl: Added checks for package dependencies.
- Bumped patchlevels of changed packages: http 2.3.2, msgcat 1.2.2,
- opt 0.4.3, tcltest 2.0.1. [Patch 448931]
+ Bumped patchlevels of changed packages: http 2.3.2, msgcat 1.2.2,
+ opt 0.4.3, tcltest 2.0.1. [Patch 448931]
* README:
* generic/tcl.h:
@@ -2351,9 +2280,9 @@
* unix/tcl.spec:
* win/README.binary:
* win/configure:
- * win/configure.in: Bumped up patchlevel to 8.4a4 to distinguish
- CVS snapshots from the 8.4a3 release. This does not necessarily
- mean there will be an 8.4a4 release. [Bug 448938].
+ * win/configure.in: Bumped up patchlevel to 8.4a4 to distinguish CVS
+ snapshots from the 8.4a3 release. This does not necessarily mean there
+ will be an 8.4a4 release. [Bug 448938]
2001-08-06 Jeff Hobbs <jeffh@ActiveState.com>
@@ -2361,64 +2290,63 @@
* changes:
* README:
- * mac/README:
+ * mac/README:
* unix/README:
* win/README.binary: updated for 8.4a3 release
- * generic/tclFileName.c (Tcl_FSSplitPath): update to Tcl style
- guide.
+ * generic/tclFileName.c (Tcl_FSSplitPath): update to Tcl style guide.
- * generic/tclFCmd.c (FileCopyRename): fixed mem leak in
- introduction of vfs code where a new Tcl_Obj wasn't freed.
+ * generic/tclFCmd.c (FileCopyRename): fixed mem leak in introduction
+ of vfs code where a new Tcl_Obj wasn't freed.
- * generic/tclCmdMZ.c (Tcl_RegexpObjCmd, Tcl_RegsubObjCmd):
- reordered the retrieval of arguments to avoid shimmering bug when
- the pattern and string referenced the same object.
+ * generic/tclCmdMZ.c (Tcl_RegexpObjCmd, Tcl_RegsubObjCmd): reordered
+ the retrieval of arguments to avoid shimmering bug when the pattern
+ and string referenced the same object.
* unix/configure: regenerated
- * unix/tcl.m4: added GNU (HURD) configuration target. (brinkmann)
- [Patch: #442974]
+ * unixE/tcl.m4: added GNU (HURD) configuration target.
+ [Patch 442974] (brinkmann)
* win/README: made note of URL for Windows compilation notes
- * win/tclWinThrd.c (TclpFinalizeMutex, TclpFinalizeCondition):
- added DeleteCriticalSection calls for cleanup [Patch: #419683]
+ * win/tclWinThrd.c (TclpFinalizeMutex, TclpFinalizeCondition): added
+ DeleteCriticalSection calls for cleanup [Patch 419683]
* unix/tclUnixPipe.c (TclpCreateTempFile): fixed use of tmpnam,
- which is dangerous. [Patch: #442636] (lim)
+ which is dangerous. [Patch 442636] (lim)
The use of tmpnam in TclpTempFileName must still be changed.
* tests/http.test (http-4.14): fixed variable error return.
- [Bug: 424252]
+ [Bug 424252]
2001-08-03 Jeff Hobbs <jeffh@ActiveState.com>
* win/configure: regenerated
* win/tcl.m4: fixed DLLSUFFIX definition to always be ${DBGX}.dll.
- This is necessary for TEA compliant builds that build shared
- against a static-built Tcl.
+ This is necessary for TEA compliant builds that build shared against a
+ static-built Tcl.
* win/Makefile.in ($(TCLSH)): added $(TCL_STUB_LIB_FILE) to build
target, otherwise it wouldn't get generated in a static build.
2001-08-06 Andreas Kupries <andreas_kupries@users.sourceforge.net>
- * generic/tclIOCmd.c (Tcl_GetsObjCmd): Applied patch from SF item
- [442665] to fix the bug reported by it. The function can corrupt
- a freed object if it is called with objc == 3. This is because
- it retrieves resultPtr and does not increment its reference
- count, but then calls Tcl_ObjSetVar2, which causes the retrieved
- resultPtr object to be released.
-
+ * generic/tclIOCmd.c (Tcl_GetsObjCmd): Applied patch from [Bug 442665]
+ to fix the bug reported by it. The function can corrupt a freed object
+ if it is called with objc == 3. This is because it retrieves resultPtr
+ and does not increment its reference count, but then calls
+ Tcl_ObjSetVar2, which causes the retrieved resultPtr object to be
+ released.
+
2001-08-06 Don Porter <dgp@users.sourceforge.net>
- * doc/tclsh.1: Added note that the tclsh program is frequently
- installed with the Tcl version numer as part of the name.
- [Patch 402725]
+ * doc/tclsh.1: Added note that the tclsh program is frequently
+ installed with the Tcl version numer as part of the name. [Patch
+ 402725]
* generic/tclPkg.c:
- * tests/pkg.test: [package forget] now forgets all of the
- package arguments it receives, not stopping when a package is
- not found. [Bug 415273]
+ * tests/pkg.test: [package forget] now forgets all of the package
+ arguments it receives, not stopping when a package is not found. [Bug
+ 415273]
2001-08-02 Jeff Hobbs <jeffh@ActiveState.com>
@@ -2428,141 +2356,133 @@
2001-08-02 Mo DeJong <mdejong@redhat.com>
* generic/tclPlatDecls.h:
- * win/tclWinPort.h:
- Revert <tchar.h> related changes made to improve
- Cygwin support on 2001-07-18. This change ended
- up breaking the VC++ build because of conflicts
- between Windows APIs and internal Tk APIs.
+ * win/tclWinPort.h: Revert <tchar.h> related changes made to improve
+ Cygwin support on 2001-07-18. This change ended up breaking the VC++
+ build because of conflicts between Windows APIs and internal Tk APIs.
2001-08-01 Jeff Hobbs <jeffh@ActiveState.com>
* unix/tclUnixFCmd.c: minor casts to eliminate warnings. (lim)
- [Patch: #440218]
+ [Patch 440218]
- * tests/parseOld.test: changed some tests that required
- testwordend to exist to skip in a proper tcltest manner.
- [Bug: #442663]
+ * tests/parseOld.test: changed some tests that required testwordend to
+ exist to skip in a proper tcltest manner. [Bug 442663]
- * library/http/http.tcl (http::mapReply): the regsub'ing of \n and
- \t to escape them was unnecessary.
+ * library/http/http.tcl (http::mapReply): the regsub'ing of \n and \t
+ to escape them was unnecessary.
2001-07-31 Vince Darley <vincentdarley@users.sourceforge.net>
Changes from TIP#17 "Redo Tcl's filesystem"
The following files were impacted:
- * doc/Access.3:
- * doc/FileSystem.3:
- * doc/OpenFileChnl.3:
- * doc/file.n:
- * doc/glob.n:
- * generic/tcl.decls:
- * generic/tcl.h:
- * generic/tclCmdAH.c:
- * generic/tclCmdIL.c:
- * generic/tclCmdMZ.c:
- * generic/tclDate.c:
- * generic/tclDecls.h:
- * generic/tclEncoding.c:
- * generic/tclFCmd.c:
- * generic/tclFileName.c:
- * generic/tclGetDate.y:
- * generic/tclIO.c:
- * generic/tclIOCmd.c:
- * generic/tclIOUtil.c:
- * generic/tclInt.decls:
- * generic/tclInt.h:
- * generic/tclIntDecls.h:
- * generic/tclLoad.c:
- * generic/tclStubInit.c:
- * generic/tclTest.c:
- * generic/tclUtil.c:
- * library/init.tcl:
- * mac/tclMacFCmd.c:
- * mac/tclMacFile.c:
- * mac/tclMacInit.c:
- * mac/tclMacPort.h:
- * mac/tclMacResource.c:
- * mac/tclMacTime.c:
- * tests/cmdAH.test:
- * tests/event.test:
- * tests/fCmd.test:
- * tests/fileName.test:
- * tests/io.test:
- * tests/ioCmd.test:
- * tests/proc-old.test:
- * tests/registry.test:
- * tests/unixFCmd.test:
- * tests/winDde.test:
- * tests/winFCmd.test:
- * unix/mkLinks:
- * unix/tclUnixFCmd.c:
- * unix/tclUnixFile.c:
- * unix/tclUnixInit.c:
- * unix/tclUnixPipe.c:
- * win/tclWinFCmd.c:
- * win/tclWinFile.c:
- * win/tclWinInit.c:
- * win/tclWinPipe.c
+ * doc/Access.3:
+ * doc/FileSystem.3:
+ * doc/OpenFileChnl.3:
+ * doc/file.n:
+ * doc/glob.n:
+ * generic/tcl.decls:
+ * generic/tcl.h:
+ * generic/tclCmdAH.c:
+ * generic/tclCmdIL.c:
+ * generic/tclCmdMZ.c:
+ * generic/tclDate.c:
+ * generic/tclDecls.h:
+ * generic/tclEncoding.c:
+ * generic/tclFCmd.c:
+ * generic/tclFileName.c:
+ * generic/tclGetDate.y:
+ * generic/tclIO.c:
+ * generic/tclIOCmd.c:
+ * generic/tclIOUtil.c:
+ * generic/tclInt.decls:
+ * generic/tclInt.h:
+ * generic/tclIntDecls.h:
+ * generic/tclLoad.c:
+ * generic/tclStubInit.c:
+ * generic/tclTest.c:
+ * generic/tclUtil.c:
+ * library/init.tcl:
+ * mac/tclMacFCmd.c:
+ * mac/tclMacFile.c:
+ * mac/tclMacInit.c:
+ * mac/tclMacPort.h:
+ * mac/tclMacResource.c:
+ * mac/tclMacTime.c:
+ * tests/cmdAH.test:
+ * tests/event.test:
+ * tests/fCmd.test:
+ * tests/fileName.test:
+ * tests/io.test:
+ * tests/ioCmd.test:
+ * tests/proc-old.test:
+ * tests/registry.test:
+ * tests/unixFCmd.test:
+ * tests/winDde.test:
+ * tests/winFCmd.test:
+ * unix/mkLinks:
+ * unix/tclUnixFCmd.c:
+ * unix/tclUnixFile.c:
+ * unix/tclUnixInit.c:
+ * unix/tclUnixPipe.c:
+ * win/tclWinFCmd.c:
+ * win/tclWinFile.c:
+ * win/tclWinInit.c:
+ * win/tclWinPipe.c:
2001-07-24 Mo DeJong <mdejong@redhat.com>
- * win/tclWinThrd.c (Tcl_CreateThread): Close Windows
- HANDLE returned by _beginthreadex. The MS documentation
- states that this handle is not closed by a later call to
- _endthreadex.
+ * win/tclWinThrd.c (Tcl_CreateThread): Close Windows HANDLE returned
+ by _beginthreadex. The MS documentation states that this handle is not
+ closed by a later call to _endthreadex.
2001-07-21 Don Porter <dgp@users.sourceforge.net>
* doc/pkgMkindex.n:
- * library/package.tcl: Corrected documentation and usage
- message of [pkg_mkIndex].
+ * library/package.tcl: Corrected documentation and usage message of
+ [pkg_mkIndex].
2001-07-18 Mo DeJong <mdejong@redhat.com>
- * generic/tclPlatDecls.h: Define TCHAR by including
- windows.h instead of tchar.h since Cygwin does not
- support the tchar.h header. Include CHECK_UNICODE_CALLS
- logic from tclWinPort.h.
- * win/tclWinPort.h: Remove CHECK_UNICODE_CALLS logic.
- Remove include of windows.h since this now done it
- tclPlatDecls.h.
+ * generic/tclPlatDecls.h: Define TCHAR by including windows.h instead
+ of tchar.h since Cygwin does not support the tchar.h header. Include
+ CHECK_UNICODE_CALLS logic from tclWinPort.h.
+ * win/tclWinPort.h: Remove CHECK_UNICODE_CALLS logic. Remove include
+ of windows.h since this now done it tclPlatDecls.h.
* win/tclWinReg.c: Remove duplicate include of windows.h.
2001-07-18 Andreas Kupries <andreas_kupries@users.sourceforge.net>
- * generic/tclIO.c: Aftermath to [SF #427196]. Squash empty buffers
- if they are smaller than the requested buffersize, to prevent
- reusage of old buffers and to honor changes in the requested
- buffersize made by the user.
+ * generic/tclIO.c: Aftermath to [Bug 427196]. Squash empty buffers if
+ they are smaller than the requested buffersize, to prevent reusage of
+ old buffers and to honor changes in the requested buffersize made by
+ the user.
2001-07-17 Mo DeJong <mdejong@redhat.com>
- * win/tclWinFile.c (TclpReadlink): Add Cygwin specific definition
- for the TclpReadlink function. This method implements reading of
- symbolic links when build with Cygwin.
+ * win/tclWinFile.c (TclpReadlink): Add Cygwin specific definition for
+ the TclpReadlink function. This method implements reading of symbolic
+ links when build with Cygwin.
2001-07-17 Mo DeJong <mdejong@redhat.com>
- * win/tclWinPort.h: Add Cygwin specific defines for environ
- and timezone variables.
+ * win/tclWinPort.h: Add Cygwin specific defines for environ and
+ timezone variables.
2001-07-17 Andreas Kupries <andreas_kupries@users.sourceforge.net>
- * generic/tclIO.c (GetInput): Fixed [SF #427196]. Memory was
- overwritten because a buffer was used after a change of the
- requested buffersize together with that requested buffersize and
- not its actual size, which was smaller. Note that the continous
- reuse of the smaller buffer negatively impacts performance. The
- system never allocates a buffer with the newly requested bigger
- buffersize.
+ * generic/tclIO.c (GetInput): Fixed [Bug 427196]. Memory was
+ overwritten because a buffer was used after a change of the requested
+ buffersize together with that requested buffersize and not its actual
+ size, which was smaller. Note that the continous reuse of the smaller
+ buffer negatively impacts performance. The system never allocates a
+ buffer with the newly requested bigger buffersize.
2001-07-16 Mo DeJong <mdejong@redhat.com>
- * generic/tcl.h: Define __WIN32__ when
- __CYGWIN__ or __MINGW32__ is defined.
- * generic/tclAlloc.c: Define caddr_t when
- compiling with VC++ or mingw. This type is
- already defined when compiling with Cygwin.
+ * generic/tcl.h: Define __WIN32__ when __CYGWIN__ or __MINGW32__ is
+ defined.
+ * generic/tclAlloc.c: Define caddr_t when compiling with VC++ or
+ mingw. This type is already defined when compiling with Cygwin.
2001-07-16 Mo DeJong <mdejong@redhat.com>
@@ -2571,9 +2491,9 @@
* win/tclWinPort.h:
* win/tclWinSerial.c:
* win/tclWinThrd.c:
- Remove unnecessary #includes of dos.h, direct.h,
- and tchar.h. This will help the Cygwin porting
- effort since these headers do not exist under Cygwin.
+ Remove unnecessary #includes of dos.h, direct.h, and tchar.h. This
+ will help the Cygwin porting effort since these headers do not exist
+ under Cygwin.
2001-07-16 Jeff Hobbs <jeffh@ActiveState.com>
@@ -2581,74 +2501,70 @@
just the TerminateThread call and waiting for termination. (jsmith)
* generic/tclCmdMZ.c: Removed extra copy of the SCAN_* macros
- #defined in generic/tclScan.c. (porter) [Bug 441230]
+ #defined in generic/tclScan.c. [Bug 441230] (porter)
2001-07-12 Donal K. Fellows <fellowsd@cs.man.ac.uk>
* tests/unixInit.test (unixInit-2.8): Added extra constraint,
- notInstalledInTmp, to stop this test from damaging installations
- in /tmp; not much fun to have to reinstall the Tcl library every
- time you run the test suite!
+ notInstalledInTmp, to stop this test from damaging installations in
+ /tmp; not much fun to have to reinstall the Tcl library every time you
+ run the test suite!
- * tests/subst.test (subst-10.*): Updated tests to check new
- behaviour for 'break' in command substitutions.
+ * tests/subst.test (subst-10.*): Updated tests to check new behaviour
+ for 'break' in command substitutions.
(subst-1.2,subst-7.1): Error messages changed.
* doc/SubstObj.3: New file, to document Tcl_SubstObj.
- * doc/subst.n: Improved and updated documentation for 'subst' to
- help support the changed behaviour.
+ * doc/subst.n: Improved and updated documentation for 'subst' to help
+ support the changed behaviour.
* generic/tcl.decls (generic-437): Declaration for Tcl_SubstObj
* generic/tcl.h (TCL_SUBST_*): Added flags for Tcl_SubstObj.
- * generic/tclCmdMZ.c (Tcl_SubstObj,Tcl_SubstObjCmd): Divided into
- two parts to allow people to access the innards of 'subst' and
- changed the behaviour when command substitutions do a 'break' to
- be different from 'continue'. Also now works with objects, which
- allows for some nifty optimisations with variable substitutions
- and a slight improvement with command substitutions. [TIP#36]
+ * generic/tclCmdMZ.c (Tcl_SubstObj,Tcl_SubstObjCmd): Divided into two
+ parts to allow people to access the innards of 'subst' and changed the
+ behaviour when command substitutions do a 'break' to be different from
+ 'continue'. Also now works with objects, which allows for some nifty
+ optimisations with variable substitutions and a slight improvement
+ with command substitutions. [TIP#36]
2001-07-10 Mo DeJong <mdejong@redhat.com>
* unix/Makefile.in: Add AR variable for use in STLIB_LD.
* unix/configure: Regen.
- * unix/configure.in: Use STLIB_LD when defining MAKE_LIB
- and MAKE_STUB_LIB. Subst RANLIB and AR.
- * unix/tcl.m4 (SC_CONFIG_CFLAGS): Add doc comment about
- STLIB_LD command. Check ${AR} env var when setting
- STLIB_LD and delay evaluation until make time.
+ * unix/configure.in: Use STLIB_LD when defining MAKE_LIB and
+ MAKE_STUB_LIB. Subst RANLIB and AR.
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): Add doc comment about STLIB_LD
+ command. Check ${AR} env var when setting STLIB_LD and delay
+ evaluation until make time.
* win/configure: Regen.
- * win/tcl.m4 (SC_CONFIG_CFLAGS): Delay evaluation of
- ${AR} in STLIB_LD and add flags to better match the
- Unix implementation. Don't bother defining AR when
- using VC++ since it is not used.
+ * win/tcl.m4 (SC_CONFIG_CFLAGS): Delay evaluation of ${AR} in STLIB_LD
+ and add flags to better match the Unix implementation. Don't bother
+ defining AR when using VC++ since it is not used.
2001-07-06 Mo DeJong <mdejong@redhat.com>
* win/configure: Regen.
- * win/tcl.m4 (SC_CONFIG_CFLAGS): Pass -e _WinMain@16 in
- addition to the -mwindows flag to work around a problem
- with ld when it incorrectly use main() as the executable
- entry point when both WinMain() and main() are available.
+ * win/tcl.m4 (SC_CONFIG_CFLAGS): Pass -e _WinMain@16 in addition to
+ the -mwindows flag to work around a problem with ld when it
+ incorrectly use main() as the executable entry point when both
+ WinMain() and main() are available.
2001-07-06 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * tests/cmdAH.test: Added leading zero to file modes to work
- around fault in HPUX strtol() which ignores the base parameter
- [Bug #438808]
+ * tests/cmdAH.test: Added leading zero to file modes to work around
+ fault in HPUX strtol() which ignores the base parameter. [Bug 438808]
2001-07-05 Mo DeJong <mdejong@redhat.com>
- * win/Makefile.in: Subst DEPARG directly instead
- of relying on a variable. This will make Cygwin
- builds faster since an extra exec will be avoided.
+ * win/Makefile.in: Subst DEPARG directly instead of relying on a
+ variable. This will make Cygwin builds faster since an extra exec will
+ be avoided.
* win/configure: Regen.
* win/configure.in: Subst DEPARG.
- * win/tcl.m4 (SC_CONFIG_CFLAGS): Move AC_MSG_CHECKING
- after the AC_CHECK_PROG so that status messages do
- not get mixed together. Set DEPARG based on the
- results of the cygpath check so that we avoid using
- an extra exec when it is not needed. Use ac_cv_cygwin
- status flag instead of looking at the output of
- gcc -v, which works in the case where -mno-cygwin is
- set in the CFLAGS.
+ * win/tcl.m4 (SC_CONFIG_CFLAGS): Move AC_MSG_CHECKING after the
+ AC_CHECK_PROG so that status messages do not get mixed together. Set
+ DEPARG based on the results of the cygpath check so that we avoid
+ using an extra exec when it is not needed. Use ac_cv_cygwin status
+ flag instead of looking at the output of gcc -v, which works in the
+ case where -mno-cygwin is set in the CFLAGS.
2001-07-04 Jeff Hobbs <jeffh@ActiveState.com>
@@ -2663,32 +2579,30 @@
* win/Makefile.in: Remove PATHTYPE variable.
* win/configure: Regen.
* win/configure.in: Don't subst PATHTYPE.
- * win/tcl.m4 (SC_CONFIG_CFLAGS): Remove PATHTYPE
- variable. Set CYGPATH to "cygpath -w" if the
- cygpath executable is found on the path. This
- approach works for native Cygwin builds and
- cross compiles.
+ * win/tcl.m4 (SC_CONFIG_CFLAGS): Remove PATHTYPE variable. Set CYGPATH
+ to "cygpath -w" if the cygpath executable is found on the path. This
+ approach works for native Cygwin builds and cross compiles.
2001-07-03 Jeff Hobbs <jeffh@ActiveState.com>
* tests/var.test:
* generic/tclVar.c (Tcl_VariableObjCmd): added patch to check for
- number of args. [Patch #426038]
+ number of args. [Patch 426038]
* generic/tclVar.c (Tcl_GetVar2Ex): added ability to recognize
- TCL_TRACE_READS flags to cause creation of part1 in TclLookupVar
- to make sure newly created array will get read traces triggered
- appropriately. This is called by Tcl_ObjGetVar2, Tcl_GetVar, and
+ TCL_TRACE_READS flags to cause creation of part1 in TclLookupVar to
+ make sure newly created array will get read traces triggered
+ appropriately. This is called by Tcl_ObjGetVar2, Tcl_GetVar, and
Tcl_GetVar2.
- (TclSetIndexedScalar, TclSetElementOfIndexedArray): added read
- trace triggering for lappend case.
- (Tcl_LappendObjCmd): pass TCL_TRACE_READS to Tcl_ObjGetVar2 to
- trigger possible read traces for new arrays.
+ (TclSetIndexedScalar, TclSetElementOfIndexedArray): added read trace
+ triggering for lappend case.
+ (Tcl_LappendObjCmd): pass TCL_TRACE_READS to Tcl_ObjGetVar2 to trigger
+ possible read traces for new arrays.
* generic/tclExecute.c (TclExecuteByteCode): added TCL_TRACE_READS
- flag to INST_LAPPEND(_ARRAY)_STK case to trigger read traces for
- newly created arrays. Removed unnecessary #ifdef for
- TCL_COMPILE_DEBUG in INST_LOAD_SCALAR1 case.
+ flag to INST_LAPPEND(_ARRAY)_STK case to trigger read traces for newly
+ created arrays. Removed unnecessary #ifdef for TCL_COMPILE_DEBUG in
+ INST_LOAD_SCALAR1 case.
* tests/append.test:
* tests/appendComp.test: added tests for read trace triggering for
@@ -2696,98 +2610,96 @@
2001-07-03 Mo DeJong <mdejong@redhat.com>
- * tests/clock.test (clock-2.5): Adjust test so that it passes
- when the time slice is 60 msecs, now passes under Windows 98.
+ * tests/clock.test (clock-2.5): Adjust test so that it passes when the
+ time slice is 60 msecs, now passes under Windows 98.
2001-07-03 Mo DeJong <mdejong@redhat.com>
- * win/tcl.m4 (SC_CONFIG_CFLAGS): Don't pass the v flag
- to ${AR} when using gcc, verbose output is not needed.
+ * win/tcl.m4 (SC_CONFIG_CFLAGS): Don't pass the v flag to ${AR} when
+ using gcc, verbose output is not needed.
2001-07-03 Don Porter <dgp@users.sourceforge.net>
* tests/unixInit.test (unixInit-2.8): Changed test back to using
- installation layout, adding comments explaining why the test writes
- to the directories it does, and checks to avoid destroying other
- files in /tmp.
+ installation layout, adding comments explaining why the test writes to
+ the directories it does, and checks to avoid destroying other files in
+ /tmp.
2001-07-03 Donal K. Fellows <fellowsd@cs.man.ac.uk>
* tests/unixInit.test (unixInit-1.2): Fixed faults reported in
- Bug#438070 - well, at least enough to work on Solaris - and added
+ [Bug 438070] - well, at least enough to work on Solaris - and added
comments that should make what is going on in the test clearer.
2001-07-02 Jeff Hobbs <jeffh@ActiveState.com>
* tests/util.test: added util-4.6
- * generic/tclUtil.c (Tcl_ConcatObj): Corrected walking backwards
- over utf-8 chars. [Bug #227512]
+ * generic/tclUtil.c (Tcl_ConcatObj): Corrected walking backwards over
+ utf-8 chars. [Bug 227512]
2001-07-02 Don Porter <dgp@users.sourceforge.net>
- * tests/unixInit.test (unixInit-2.8): Corrected test for all
- absolute pathnames in library path when executable is installed
- near root directory to use correct development directory layout.
- [Bug 438014]
+ * tests/unixInit.test (unixInit-2.8): Corrected test for all absolute
+ pathnames in library path when executable is installed near root
+ directory to use correct development directory layout. [Bug 438014]
- * tests/unixInit.test (unixInit-2.9):
+ * tests/unixInit.test (unixInit-2.9):
* unix/tclUnixInit.c (TclpInitLibraryPath):
* win/tclWinInit.c (TclpInitLibraryPath): Corrected buggy
- construction of search path entries relative to executable.
- Added test for bad construction. [Bug 438014]
+ construction of search path entries relative to executable. Added test
+ for bad construction. [Bug 438014]
2001-06-28 Miguel Sofer <msofer@users.sourceforge.net>
- * generic/tclNamesp.c: Correction to faulty patch from [Bug: 231259]
+ * generic/tclNamesp.c: Correction to faulty patch from [Bug 231259]
2001-06-28 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * tests/unixInit.test (unixInit-1.2): Modified so as not to
- require a local echo service, which fails on many systems which
- have that turned off for security reasons...
+ * tests/unixInit.test (unixInit-1.2): Modified so as not to require a
+ local echo service, which fails on many systems which have that turned
+ off for security reasons...
2001-06-27 Jeff Hobbs <jeffh@ActiveState.com>
* generic/tclInt.h:
* generic/tclObj.c:
* unix/Makefile.in: added a -DPURIFY mode that makes Tcl_Obj's
- allocated and free singularly (instead of in alloc in blocks and
- never free) to allow checkers like Purify to operate better.
+ allocated and free singularly (instead of in alloc in blocks and never
+ free) to allow checkers like Purify to operate better.
* library/encoding/koi8-u.enc: added koi8-u (Ukranian variant)
encoding.
* tests/subst.test:
- * generic/tclUtf.c (Tcl_UtfBackslash): Corrected backslash
- handling of multibyte utf-8 chars. [Bug #217987]
+ * generic/tclUtf.c (Tcl_UtfBackslash): Corrected backslash handling of
+ multibyte utf-8 chars. [Bug 217987]
- * generic/tclCmdIL.c (InfoProcsCmd): fixed potential mem leak in
- info procs that created objects without using them.
+ * generic/tclCmdIL.c (InfoProcsCmd): fixed potential mem leak in info
+ procs that created objects without using them.
* generic/tclCompCmds.c (TclCompileStringCmd): fixed mem leak when
string command failed to parse the subcommand.
* doc/interp.n:
- * doc/unknown.n: updated notes about what is in a safe interp.
- [Bug #218605]
+ * doc/unknown.n: updated notes about what is in a safe interp. [Bug
+ 218605]
2001-06-27 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * tests/event.test (event-11.5): Removed hard-coded port number
- which could fail on some systems. [Bug #436727]
+ * tests/event.test (event-11.5): Removed hard-coded port number which
+ could fail on some systems. [Bug 436727]
2001-06-26 Mo DeJong <mdejong@redhat.com>
* unix/Makefile.in:
- * win/Makefile.in: Add `make shell` target. This target
- will set the proper env vars before invoking tclsh
- from the build directory.
+ * win/Makefile.in: Add `make shell` target. This target will set the
+ proper env vars before invoking tclsh from the build directory.
2001-06-26 Mo DeJong <mdejong@redhat.com>
- * win/Makefile.in: Use : to separate VPATH entries. This
- works for both Cygwin builds and cross builds, the VPSEP
- variable is simply unneeded complexity.
+ * win/Makefile.in: Use : to separate VPATH entries. This works for
+ both Cygwin builds and cross builds, the VPSEP variable is simply
+ unneeded complexity.
* win/configure: Regen.
* win/configure.in: Don't subst VPSEP.
* win/tcl.m4 (SC_CONFIG_CFLAGS): Remove VPSEP variable.
@@ -2795,17 +2707,17 @@
2001-06-26 Mo DeJong <mdejong@redhat.com>
* unix/configure: Regen.
- * unix/configure.in: Fix last checkin by removing
- export since that only works in bash.
+ * unix/configure.in: Fix last checkin by removing export since that
+ only works in bash.
* win/configure: Regen.
* win/configure.in: Ditto.
2001-06-26 Mo DeJong <mdejong@redhat.com>
* unix/configure: Regen.
- * unix/configure.in: Set CFLAGS to "" if the user
- did not set CFLAGS in the env. This keeps AC_PROG_CC
- from adding "-g -O2" to the CFLAGS by default.
+ * unix/configure.in: Set CFLAGS to "" if the user did not set CFLAGS
+ in the env. This keeps AC_PROG_CC from adding "-g -O2" to the CFLAGS
+ by default.
* win/configure: Regen.
* win/configure.in: Ditto.
@@ -2813,28 +2725,27 @@
* win/configure: Regen.
* win/configure.in: Use RC_DEFINE flag from tcl.m4.
- * win/tcl.m4 (SC_CONFIG_CFLAGS): Set RC_DEFINE
- flag based on the compiler in use.
-
+ * win/tcl.m4 (SC_CONFIG_CFLAGS): Set RC_DEFINE flag based on the
+ compiler in use.
+
2001-06-25 Mo DeJong <mdejong@redhat.com>
- * win/tcl.m4 (SC_CONFIG_CFLAGS): Link to the
- imm32 library when building with mingw gcc.
+ * win/tcl.m4 (SC_CONFIG_CFLAGS): Link to the imm32 library when
+ building with mingw gcc.
2001-06-25 Mo DeJong <mdejong@redhat.com>
* win/configure: Regen.
- * win/tcl.m4 (SC_CONFIG_CFLAGS): When building with
- gcc, don't attempt to link with LD or support dllwrap.
- Simply require a recent version of Cygwin gcc or Mingw
- gcc that supports -shared. When linking, use gcc instead
- of ld since gcc automatically includes libs like -lmsvcrt.
+ * win/tcl.m4 (SC_CONFIG_CFLAGS): When building with gcc, don't attempt
+ to link with LD or support dllwrap. Simply require a recent version of
+ Cygwin gcc or Mingw gcc that supports -shared. When linking, use gcc
+ instead of ld since gcc automatically includes libs like -lmsvcrt.
2001-06-22 Mo DeJong <mdejong@redhat.com>
* win/configure: Regen.
- * win/configure.in: Add resource compiler fix from
- 8.3.3 to fix compiling with mingw.
+ * win/configure.in: Add resource compiler fix from 8.3.3 to fix
+ compiling with mingw.
2001-06-22 Mo DeJong <mdejong@redhat.com>
@@ -2843,63 +2754,61 @@
2001-06-22 Mo DeJong <mdejong@redhat.com>
- * unix/Makefile.in: Set CFLAGS to @CFLAGS@ and @CFLAGS_DEFAULT@.
- Set LDFLAGS to @LDFLAGS@ and @LDFLAGS_DEFAULT@. Add LDFLAGS_DEBUG
- and LDFLAGS_OPTIMIZE to match the way CFLAGS_DEFAULT works.
- This will support user set CFLAGS or LDFLAGS at configure time.
+ * unix/Makefile.in: Set CFLAGS to @CFLAGS@ and @CFLAGS_DEFAULT@. Set
+ LDFLAGS to @LDFLAGS@ and @LDFLAGS_DEFAULT@. Add LDFLAGS_DEBUG and
+ LDFLAGS_OPTIMIZE to match the way CFLAGS_DEFAULT works. This will
+ support user set CFLAGS or LDFLAGS at configure time.
* unix/configure: Regen.
* unix/configure.in: Don't set CFLAGS to CFLAGS_DEFAULT, instead
- subst CFLAGS_DEFAULT into the Makefile. Add AC_SUBST for CFLAGS_DEFAULT,
- LDFLAGS_DEFAULT, LDFLAGS_DEBUG, and LDFLAGS_OPTIMIZE.
- * unix/tcl.m4 (SC_ENABLE_SYMBOLS): Modify LDFLAGS_DEFAULT so that
- it uses a Makefile variable just like CFLAGS_DEFAULT.
- * win/Makefile.in: Set CFLAGS to @CFLAGS@ and @CFLAGS_DEFAULT@.
- Set LDFLAGS to @LDFLAGS@ and @LDFLAGS_DEFAULT@.
- This will support user set CFLAGS or LDFLAGS at configure time.
+ subst CFLAGS_DEFAULT into the Makefile. Add AC_SUBST for
+ CFLAGS_DEFAULT, LDFLAGS_DEFAULT, LDFLAGS_DEBUG, and LDFLAGS_OPTIMIZE.
+ * unix/tcl.m4 (SC_ENABLE_SYMBOLS): Modify LDFLAGS_DEFAULT so that it
+ uses a Makefile variable just like CFLAGS_DEFAULT.
+ * win/Makefile.in: Set CFLAGS to @CFLAGS@ and @CFLAGS_DEFAULT@. Set
+ LDFLAGS to @LDFLAGS@ and @LDFLAGS_DEFAULT@. This will support user set
+ CFLAGS or LDFLAGS at configure time.
* win/configure: Regen.
* win/configure.in: Don't set CFLAGS or LDFLAGS, instead subst
CFLAGS_DEFAULT and LDFLAGS_DEFAULT into the Makefile.
- * win/tcl.m4 (SC_ENABLE_SYMBOLS): Modify LDFLAGS_DEFAULT so that
- it uses a Makefile variable just like CFLAGS_DEFAULT.
+ * win/tcl.m4 (SC_ENABLE_SYMBOLS): Modify LDFLAGS_DEFAULT so that it
+ uses a Makefile variable just like CFLAGS_DEFAULT.
2001-06-22 Mo DeJong <mdejong@redhat.com>
* win/configure:
- * win/tcl.m4 (SC_CONFIG_CFLAGS): Don't set LDFLAGS_DEBUG
- to -g or LDFLAGS_OPTIMIZE to -O when compiling with gcc.
- These flags are not needed and can cause problems with
- the Cygwin version of ld.
+ * win/tcl.m4 (SC_CONFIG_CFLAGS): Don't set LDFLAGS_DEBUG to -g or
+ LDFLAGS_OPTIMIZE to -O when compiling with gcc. These flags are not
+ needed and can cause problems with the Cygwin version of ld.
2001-06-18 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * tests/unixInit.test (unixInit-1.2,unixInit-2.8): Added test for
- code described below, and fixed a couple of errors that caused
- problems during testing; the code to determine the installedTcl
- constraint was wrong, and test unixInit-2.8 assumed that /tmp/lib
- was free for use and could be deleted, which clashed nastily with
- my installation and made other tests fail unnecessarily!
+ * tests/unixInit.test (unixInit-1.2,unixInit-2.8): Added test for code
+ described below, and fixed a couple of errors that caused problems
+ during testing; the code to determine the installedTcl constraint was
+ wrong, and test unixInit-2.8 assumed that /tmp/lib was free for use
+ and could be deleted, which clashed nastily with my installation and
+ made other tests fail unnecessarily!
* unix/tclUnixChan.c (TtyInit,TclpOpenFileChannel,
- Tcl_MakeFileChannel,TclpGetDefaultStdChannel): Alterations so that
- the standard channels - stdin, stdout and stderr - have the
- correct type and fconfigure options. This required making the
- initialisation of serial lines a little more sophisticated to
- make the console behave correctly in interactive mode... [Bug
- #219137 and duplicates]
+ (Tcl_MakeFileChannel,TclpGetDefaultStdChannel): Alterations so that
+ the standard channels - stdin, stdout and stderr - have the correct
+ type and fconfigure options. This required making the initialisation
+ of serial lines a little more sophisticated to make the console behave
+ correctly in interactive mode... [Bug 219137 and duplicates]
2001-06-16 Don Porter <dgp@users.sourceforge.net>
* generic/tclInt.decls:
- * generic/tclInt.h:
+ * generic/tclInt.h:
* generic/tclPanic.c (Tcl_PanicVA):
* mac/tclMacAppInit.c (main):
* mac/tclMacPanic.c (TclpPanic):
* unix/tclUnixPort.h:
- * win/tclWinPort.h: Replaced TclMacSetPanic with TclpPanic
- for setting a platform-specific panic handler. TclpPanic
- is NULL on Unix and Windows. Fixes broken wish on Mac due
- to earlier patches. [Patch 415648]
-
+ * win/tclWinPort.h: Replaced TclMacSetPanic with TclpPanic for setting
+ a platform-specific panic handler. TclpPanic is NULL on Unix and
+ Windows. Fixes broken wish on Mac due to earlier patches. [Patch
+ 415648]
+
* generic/tclIntPlatDecls.h:
* generic/tclStubInit.c: `make gentubs` after above changes.
@@ -2912,9 +2821,9 @@
2001-06-12 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * tests/regexp.test (regexp-18.12):
+ * tests/regexp.test (regexp-18.12):
* generic/tclCmdMZ.c (Tcl_RegexpObjCmd): Fixed so that submatches
- that do not match always have index pair {-1 -1} [Bug #219232]
+ that do not match always have index pair {-1 -1} [Bug 219232]
2001-06-08 Don Porter <dgp@users.sourceforge.net>
@@ -2927,11 +2836,10 @@
* mac/tclMacAppInit.c (main):
* mac/tclMacBOAAppInit.c (main):
* mac/tclMacPanic.c: Modified special Mac implementations of
- Tcl_*Panic* to be exact copies of the generic implementations.
- Added TclMacSetPanic. The generic implementations should be
- used directly, rather than copies, but that requires further
- changes by someone familiar with the Mac build systems.
- [Patch 415648]
+ Tcl_*Panic* to be exact copies of the generic implementations. Added
+ TclMacSetPanic. The generic implementations should be used directly,
+ rather than copies, but that requires further changes by someone
+ familiar with the Mac build systems. [Patch 415648]
* generic/tclDecls.h:
* generic/tclIntPlatDecls.h:
@@ -2939,24 +2847,24 @@
* doc/Panic.3:
* unix/mkLinks: New file documenting Tcl_*Panic* public interfaces,
- followed by `make mklinks`. [Patch 415648, Bug 219170, Bug 414936]
+ followed by `make mklinks`. [Patch 415648, Bug 219170, Bug 414936]
2001-06-03 Jeff Hobbs <jeffh@ActiveState.com>
* generic/tclUtil.c (Tcl_DStringAppendElement): patch to save an
- extra strlen call. [Bug #428572]
+ extra strlen call. [Bug 428572]
2001-05-30 Donal K. Fellows <fellowsd@cs.man.ac.uk>
* generic/tclExecute.c (TclExecuteByteCode): Added two casts to
- INST_STR_CMP implementation to get rid of a couple warnings from
- the SUNWspro C compiler.
-
- * generic/tclBasic.c (Tcl_GetMathFuncInfo,Tcl_ListMathFuncs):
- * generic/tclCmdIL.c (Tcl_InfoObjCmd,InfoFunctionsCmd):
- * generic/tcl.decls (generic table, positions 435+436):
- * tests/info.test:
- * doc/CrtMathFnc.3:
+ INST_STR_CMP implementation to get rid of a couple warnings from the
+ SUNWspro C compiler.
+
+ * generic/tclBasic.c (Tcl_GetMathFuncInfo,Tcl_ListMathFuncs):
+ * generic/tclCmdIL.c (Tcl_InfoObjCmd,InfoFunctionsCmd):
+ * generic/tcl.decls (generic table, positions 435+436):
+ * tests/info.test:
+ * doc/CrtMathFnc.3:
* doc/info.n: Changes due to TIP #15 "Functions to List and Detail
Math Functions"
@@ -2968,32 +2876,31 @@
* generic/regc_locale.c: updated character class range data for
Unicode v3.1.0 compliance.
- * generic/tclUniData.c: regenerated from Unicode v3.1.0 data file
- (new as of 2001-05-16). This brings Tcl to current unicode
- compliance.
+ * generic/tclUniData.c: regenerated from Unicode v3.1.0 data file (new
+ as of 2001-05-16). This brings Tcl to current unicode compliance.
* tests/utf.test: added tests to check unicode 3 compliance
* unix/Makefile.in (tclUtf.o): added tclUniData.c dependency.
- * tools/uniClass.tcl: added comments to output format and the
- script for clarification.
+ * tools/uniClass.tcl: added comments to output format and the script
+ for clarification.
- * tools/uniParse.tcl: corrected filename output and GetDelta macro
- to use 'info' as param (was 'infO')
+ * tools/uniParse.tcl: corrected filename output and GetDelta macro to
+ use 'info' as param (was 'infO')
2001-05-26 Donal K. Fellows <fellowsd@cs.man.ac.uk>
* generic/tclVar.c (tclArraySearchType,SetArraySearchObj,
- ParseSearchId): Added code to speed up array searching by reducing
+ (ParseSearchId): Added code to speed up array searching by reducing
the amount of parsing needed for searchIds.
- * generic/tclObj.c (TclInitObjSubsystem):
- * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct):
- * generic/tclNamesp.c (TclInitNamespaceSubsystem):
+ * generic/tclObj.c (TclInitObjSubsystem):
+ * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct):
+ * generic/tclNamesp.c (TclInitNamespaceSubsystem):
* generic/tclInt.h: Moved some Tcl_ObjType initialisation to
- TclInitObjSubsystem to be with the bulk of the rest.
- [Patch 424851] Committed by Miguel Sofer <mig@utdt.edu>
+ TclInitObjSubsystem to be with the bulk of the rest. [Patch 424851]
+ Committed by Miguel Sofer <mig@utdt.edu>
2001-05-23 Jeff Hobbs <jeffh@ActiveState.com>
@@ -3015,31 +2922,29 @@
* library/encoding/iso8859-8.enc:
* library/encoding/iso8859-10.enc (new):
* library/encoding/iso8859-13.enc (new):
- * library/encoding/iso8859-14.enc (new): updated encoding tables
- based on http://www.unicode.org/Public/MAPPINGS/. (kuhn)
+ * library/encoding/iso8859-14.enc (new): updated encoding tables based
+ on http://www.unicode.org/Public/MAPPINGS/. (kuhn)
2001-05-23 Mo DeJong <mdejong@redhat.com>
- * unix/tcl.m4 (SC_PATH_TCLCONFIG): Fix comments,
- and typo in cached variable name.
+ * unix/tcl.m4 (SC_PATH_TCLCONFIG): Fix comments, and typo in cached
+ variable name.
2001-05-23 Mo DeJong <mdejong@redhat.com>
- * unix/tcl.m4 (SC_LOAD_TKCONFIG):
- Remove use of undefined TCLCONFIG variable and
- call AC_MSG_RESULT to print the checking result.
+ * unix/tcl.m4 (SC_LOAD_TKCONFIG): Remove use of undefined TCLCONFIG
+ variable and call AC_MSG_RESULT to print the checking result.
* win/tcl.m4: Ditto.
2001-05-22 Jeff Hobbs <jeffh@ActiveState.com>
* generic/tclObj.c (TclAllocateFreeObjects): simplified
- objSizePlusPadding to use sizeof(Tcl_Obj) (max)
- Corrected use of tclObjsAlloced/Freed/Shared in TCL_MEM_DEBUG
- compile.
+ objSizePlusPadding to use sizeof(Tcl_Obj) (max) Corrected use of
+ tclObjsAlloced/Freed/Shared in TCL_MEM_DEBUG compile.
2001-05-22 Miguel Sofer <msofer@users.sourceforge.net>
- * generic/tclExecute.c: removed Tcl_DuplicateObj in INST_DUP
+ * generic/tclExecute.c: removed Tcl_DuplicateObj in INST_DUP
2001-05-21 Jeff Hobbs <jeffh@ActiveState.com>
@@ -3047,13 +2952,13 @@
getting affected by Windows env handling of empty valued elements.
* unix/tcl.m4: added more common install directories in which to
- search for *Config.sh [Bug #419812]
+ search for *Config.sh. [Bug 419812]
- * tests/cmdMZ.test (cmdMZ-1.4): added notLinux constraint to test
- to prevent failure message on Linux due to OS caching bug.
+ * tests/cmdMZ.test (cmdMZ-1.4): added notLinux constraint to test to
+ prevent failure message on Linux due to OS caching bug.
- * tests/httpd (httpdRespond): added response to timeout value in
- query string.
+ * tests/httpd (httpdRespond): added response to timeout value in query
+ string.
* tests/http.test: removed unused notLinux constraint setting
@@ -3063,61 +2968,58 @@
2001-05-19 Andreas Kupries <andreas_kupries@users.sourceforge.net>
* Note that "tclbench" (see project "tcllib") was extended with
- performance benchmarks for [fcopy] too.
+ performance benchmarks for [fcopy] too.
* doc/fcopy.n: Updated to reflect the extended behaviour of 'fcopy'.
- * tests/io.test: Added tests 'io-52.9', 'io-52.10' and 'io-52.11'
- to test the handling of encodings by 'fcopy' / 'TclCopychannel'
- [Bug #209210].
+ * tests/io.test: Added tests 'io-52.9', 'io-52.10' and 'io-52.11' to
+ test the handling of encodings by 'fcopy' / 'TclCopychannel'. [Bug
+ 209210]
- * generic/tclIO.c: Split of both 'Tcl_ReadChars' and
- 'Tcl_WriteChars' into a public error checking and an internal
- working part. The public functions now use the new internal
- ones. The new functions are 'DoReadChars' and 'DoWriteChars'.
- Extended 'CopyData' to use the new functions 'DoXChars' when
- required by the encodings on the input and output channels
- [Bug #209210].
+ * generic/tclIO.c: Split of both 'Tcl_ReadChars' and 'Tcl_WriteChars'
+ into a public error checking and an internal working part. The public
+ functions now use the new internal ones. The new functions are
+ 'DoReadChars' and 'DoWriteChars'. Extended 'CopyData' to use the new
+ functions 'DoXChars' when required by the encodings on the input and
+ output channels. [Bug 209210]
2001-05-16 Jeff Hobbs <jeffh@ActiveState.com>
- * library/history.tcl (tcl::HistAdd): prevent empty calls from
- being added to the history (arndt)
+ * library/history.tcl (tcl::HistAdd): prevent empty calls from being
+ added to the history (arndt)
- * tests/error.test: updated error-1.3 message to account for
- string index being compiled at toplevel.
+ * tests/error.test: updated error-1.3 message to account for string
+ index being compiled at toplevel.
* tests/appendComp.test:
* tests/stringComp.test: new files for extended bytecode testing
* generic/tclBasic.c: added new CompileProc invocations to basic
command initialization.
* generic/tclCompCmds.c: added new compile commands for append,
- lappend, lindex and llength. Refactored set and incr compile
- commands to use new TclPushVarName function for handling the
- varname component during compilation (also used by append and
- lappend). Changed string compile command to compile toplevel code
- as well (when possible).
+ lappend, lindex and llength. Refactored set and incr compile commands
+ to use new TclPushVarName function for handling the varname component
+ during compilation (also used by append and lappend). Changed string
+ compile command to compile toplevel code as well (when possible).
* generic/tclCompile.c: added new instruction enums
* generic/tclCompile.h: added debug info for new instructions
- * generic/tclExecute.c (TclExecuteByteCode): moved elemPtr to
- toplevel var (oft-used). Added definitions for new bytecode
- instructions INST_LIST_INDEX, INST_LIST_LENGTH, INST_APPEND_SCALAR1,
+ * generic/tclExecute.c (TclExecuteByteCode): moved elemPtr to toplevel
+ var (oft-used). Added definitions for new bytecode instructions
+ INST_LIST_INDEX, INST_LIST_LENGTH, INST_APPEND_SCALAR1,
INST_APPEND_SCALAR4, INST_APPEND_ARRAY1, INST_APPEND_ARRAY4,
INST_APPEND_ARRAY_STK, INST_APPEND_STK, INST_LAPPEND_SCALAR1,
INST_LAPPEND_SCALAR4, INST_LAPPEND_ARRAY1, INST_LAPPEND_ARRAY4,
INST_LAPPEND_ARRAY_STK, INST_LAPPEND_STK.
Refactored repititious code for reuse with INST_LOAD_STK (same as
- INST_LOAD_SCALAR_STK), INST_STORE_STK (same as
- INST_STORE_SCALAR_STK).
+ INST_LOAD_SCALAR_STK), INST_STORE_STK (same as INST_STORE_SCALAR_STK).
Updated INST_STR_CMP with style of fix of 2001-04-06 Fellows
- [Bug #219201] as that fix only affected the runtime eval'ed
- "string" (string compare is normally byte-compiled now). We
- may want to back these out for speed in the future, noting the
- problems with \x00 comparisons in the docs.
+ [Bug 219201] as that fix only affected the runtime eval'ed "string"
+ (string compare is normally byte-compiled now). We may want to back
+ these out for speed in the future, noting the problems with \x00
+ comparisons in the docs.
* generic/tclInt.h: declarations for new compile commands.
* generic/tclVar.c: change TclGetIndexedScalar,
TclGetElementOfIndexedArray, TclSetElementOfIndexedArray and
- TclSetIndexedScalar to use flags. The Set functions now support
+ TclSetIndexedScalar to use flags. The Set functions now support
TCL_APPEND_ELEMENT and TCL_LIST_ELEMENT as well.
* generic/tclInt.decls:
* generic/tclIntDecls.h: minor signature changes for above.
@@ -3126,7 +3028,7 @@
2001-05-16 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * doc/console.n: Deleted. Put it in the wrong source tree! D'oh!
+ * doc/console.n: Deleted. Put it in the wrong source tree! D'oh!
2001-05-15 Jeff Hobbs <jeffh@ActiveState.com>
@@ -3136,8 +3038,8 @@
* generic/tclStringObj.c (Tcl_GetUnicodeFromObj): new function to
parallel Tcl_GetStringFromObj (fix of an API oversight).
- * unix/tclUnixPipe.c: updated pipeChannelType to
- TCL_CHANNEL_VERSION_2 type specification.
+ * unix/tclUnixPipe.c: updated pipeChannelType to TCL_CHANNEL_VERSION_2
+ type specification.
* tests/fileName.test: corrected tests not to fail on win when a
C:/test dir exists.
@@ -3146,82 +3048,80 @@
2001-05-15 Miguel Sofer <msofer@users.sourceforge.net>
- * tests/lindex.test: added test for nested braces [Patch: 423617]
+ * tests/lindex.test: added test for nested braces [Patch 423617]
2001-05-15 Miguel Sofer <msofer@users.sourceforge.net>
- * generic/tclInt.h
- * generic/tclNamesp.c: invalidate all bytecodes in a namespace if
- a new command shadows a bytecoded command.
- * tests/namespace.test
- Patched from [Bug: 231259]
+ * generic/tclInt.h:
+ * generic/tclNamesp.c: invalidate all bytecodes in a namespace if a
+ new command shadows a bytecoded command.
+ * tests/namespace.test:
+ Patched from [Bug 231259]
2001-05-15 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * doc/console.n: Created. It seems very odd to me that the
- console implementation is part of the Tcl distribution and not
- part of Tk, but given the location of the source, the
- documentation must obviously match up...
+ * doc/console.n: Created. It seems very odd to me that the console
+ implementation is part of the Tcl distribution and not part of Tk, but
+ given the location of the source, the documentation must obviously
+ match up...
2001-05-14 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * generic/tclCmdMZ.c (Tcl_StringObjCmd):
- * tests/string.test (string-4.14): Negative string indices should
- not be added as offsets to the result of [string first] but
- instead be treated as referring to the start of the string.
- [Bug: 423581]
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd):
+ * tests/string.test (string-4.14): Negative string indices should not
+ be added as offsets to the result of [string first] but instead be
+ treated as referring to the start of the string. [Bug 423581]
2001-05-11 Mo DeJong <mdejong@redhat.com>
- * unix/Makefile.in: Add a LDFLAGS variable to the
- Makefile instead of directly substing @LDFLAGS@.
+ * unix/Makefile.in: Add a LDFLAGS variable to the Makefile instead of
+ directly substing @LDFLAGS@.
* unix/configure: Regen.
- * unix/tcl.m4: Fix CFLAGS_DEFAULT so that the name
- of a Makefile variable is passed as @CFLAGS@.
- * win/Makefile.in: Move the setting of CFLAGS
- higher up in the Makefile.
+ * unix/tcl.m4: Fix CFLAGS_DEFAULT so that the name of a Makefile
+ variable is passed as @CFLAGS@.
+ * win/Makefile.in: Move the setting of CFLAGS higher up in the
+ Makefile.
* win/configure: Regen.
- * win/configure.in: Use dnl to comment out macros
- so that they are not accidently expanded.
- * win/tcl.m4: Fix CFLAGS_DEFAULT so that the name
- of a Makefile variable is passed as @CFLAGS@.
+ * win/configure.in: Use dnl to comment out macros so that they are not
+ accidently expanded.
+ * win/tcl.m4: Fix CFLAGS_DEFAULT so that the name of a Makefile
+ variable is passed as @CFLAGS@.
2001-05-07 Miguel Sofer <msofer@users.sourceforge.net>
* generic/tclExecute.c: insure different rand() seeds in different
- threads [Bug 416643]
+ threads. [Bug 416643]
2001-05-03 Jeff Hobbs <jeffh@ActiveState.com>
* tests/tcltest.test: removed extraneous 'c' (doh!) [Bug: 414031]
- * tools/tcltk-man2html.tcl: removed use of 'exec' for portability
- and fixed up code.
+ * tools/tcltk-man2html.tcl: removed use of 'exec' for portability and
+ fixed up code.
2001-05-03 Don Porter <dgp@users.sourceforge.net>
* doc/library.n:
* library/init.tcl:
- * tests/autoMkindex.t*: Modified [auto_import] to apply
- pattern matching in the [namespace import] style. [Bug 420186]
- ***POTENTIAL INCOMPATIBILITY*** for any callers of [auto_import]
- from outside Tcl that expect the pattern matching to be like that
- of [string match].
+ * tests/autoMkindex.t*: Modified [auto_import] to apply pattern
+ matching in the [namespace import] style. [Bug 420186]
+ ***POTENTIAL INCOMPATIBILITY*** for any callers of [auto_import] from
+ outside Tcl that expect the pattern matching to be like that of
+ [string match].
2001-05-03 Miguel Sofer <msofer@users.sourceforge.net>
- * generic/tclParse.c:
- * tests/namespace.test: Insure consistent behaviour of the
- [unknown] command: when a command is unknown, it is always
- processed by [::unknown], ignoring any namespace proc which
- happens to be called "unknown" [Patch #421166, Bug #420507]
+ * generic/tclParse.c:
+ * tests/namespace.test: Insure consistent behaviour of the [unknown]
+ command: when a command is unknown, it is always processed by
+ [::unknown], ignoring any namespace proc which happens to be called
+ "unknown" [Patch 421166, Bug 420507]
2001-05-02 Don Porter <dgp@users.sourceforge.net>
- * tools/genStubs.tcl: Add a package require of Tcl 8
- at the beginning of the script so that the script
- will print a descriptive error message when run
- in an old Tcl 7 shell.
+ * tools/genStubs.tcl: Add a package require of Tcl 8 at the beginning
+ of the script so that the script will print a descriptive error
+ message when run in an old Tcl 7 shell.
2001-04-27 Kevin Kenny <kennykb@crd.ge.com>
@@ -3229,10 +3129,10 @@
* generic/tclInt.h:
* generic/tclCmdIL.c:
* generic/tclProc.c:
- * generic/tclVar.c: Added another collection of missing CONSTs
- related to TclGetNamespaceForQualName.
+ * generic/tclVar.c: Added another collection of missing CONSTs related
+ to TclGetNamespaceForQualName.
* generic/tclIntDecls.h: Regenerated.
-
+
2001-04-25 Mo DeJong <mdejong@redhat.com>
* unix/configure: Regen.
@@ -3245,9 +3145,9 @@
2001-04-25 Mo DeJong <mdejong@redhat.com>
* unix/configure: Regen.
- * unix/configure.in: Use $@ in MAKE_LIB and MAKE_STUB_LIB
- commands instead of using a delayed subst variable. Replace
- instances of STUB_LIB_FILE with TCL_STUB_LIB_FILE.
+ * unix/configure.in: Use $@ in MAKE_LIB and MAKE_STUB_LIB commands
+ instead of using a delayed subst variable. Replace instances of
+ STUB_LIB_FILE with TCL_STUB_LIB_FILE.
2001-04-25 Mo DeJong <mdejong@redhat.com>
@@ -3259,19 +3159,20 @@
2001-04-25 Donal K. Fellows <fellowsd@cs.man.ac.uk>
* tools/encoding/iso8859-15.txt:
- * library/encoding/iso8859-15.enc: Oops! Got the full encoding
- wrong. Should be fixed now...
+ * library/encoding/iso8859-15.enc: Oops! Got the full encoding wrong.
+ Should be fixed now...
* tools/encoding/iso8859-15.txt:
* library/encoding/iso8859-15.enc:
- * tools/tcl.wse.in: Added ISO 8859-15 (a.k.a. Latin-1 + Euro
- currency symbol) support.
+ * tools/tcl.wse.in: Added ISO 8859-15 (a.k.a. Latin-1 + Euro currency
+ symbol) support.
* generic/tclNamesp.c:
- * generic/tclBasic.c (TclRenameCommand): Missing CONST from
- several declarations relating to use of TclGetNamespaceForQualName
+ * generic/tclBasic.c (TclRenameCommand): Missing CONST from several
+ declarations relating to use of TclGetNamespaceForQualName
2001-04-24 Kevin B. Kenny <kennykb@acm.org>
+
* doc/AssocData.3:
* doc/CrtCommand.3:
* doc/CrtMathFnc.3:
@@ -3285,18 +3186,18 @@
* generic/tcl.h:
* generic/tclInt.decls:
* generic/tclInt.h: (TIP #27) Another round of CONST changes, this
- time adding CONST to the API's exported from tclBasic.c.
- [Patch #415179]
- ***POTENTIAL INCOMPATIBILITY*** from 8.4a2, in which Vince
- Darley's changes to command tracing were added. A const has been
- added to the type signature of one of the parameters to
- Tcl_CommandTraceProc.
+ time adding CONST to the API's exported from tclBasic.c. [Patch
+ 415179]
+ ***POTENTIAL INCOMPATIBILITY*** from 8.4a2, in which Vince Darley's
+ changes to command tracing were added. A const has been added to the
+ type signature of one of the parameters to Tcl_CommandTraceProc.
2001-04-10 Kevin B. Kenny <kennykb@acm.org>
+
* unix/tclUnixTime.c: Altered code to use memcpy instead of
structure assigments in an effort to achieve better K&R
compatibility.
-
+
2001-04-10 Kevin B. Kenny <kennykb@acm.org>
* unix/tclUnixTime.c: Fixed silly typo in calls to 'gmtime' and
@@ -3304,125 +3205,122 @@
2001-04-09 Kevin B. Kenny <kennykb@acm.org>
- * unix/tclLoadShl.c: Added DYNAMIC_PATH to the load flags so that
- the SHLIB_PATH will be searched for other libraries. [Bug #219140]
-
+ * unix/tclLoadShl.c: Added DYNAMIC_PATH to the load flags so that the
+ SHLIB_PATH will be searched for other libraries. [Bug 219140]
+
2001-04-09 Kevin B. Kenny <kennykb@acm.org>
- * unix/tcl.m4: Added _REENTRANT to Solaris build so that thread
- safe library routines are included.
+ * unix/tcl.m4: Added _REENTRANT to Solaris build so that thread safe
+ library routines are included.
* unix/configure: Re-ran 'autoconf' with changed tcl.m4
* tclUnixTime.c: Modified for thread safety of 'gmtime' and
- 'localtime' system calls [Bugs #219136 and #232558]
-
+ 'localtime' system calls. [Bugs 219136 and 232558]
+
2001-04-09 Donal K. Fellows <fellowsd@cs.man.ac.uk>
* tests/expr.test (expr-21.*): Tests to check below fix.
* generic/tclParseExpr.c (GetLexeme): Now recognises the
non-numeric boolean literals for what they are. It no longer makes
sense for anyone to create functions with the same name as one of
- them, but this was true in 7.* as well [Bug #217777; finally!]
+ them, but this was true in 7.* as well [Bug 217777; finally!]
2001-04-07 Miguel Sofer <msofer@users.sourceforge.net>
- * generic/tclExecute.c: Avoid panic when there are extra items in
- the tcl stack [Bug #406709, Patch #414470]
+ * generic/tclExecute.c: Avoid panic when there are extra items in the
+ tcl stack. [Bug 406709, Patch 414470]
* tests/foreach.test: test to exercise the patch
2001-04-07 Miguel Sofer <msofer@users.sourceforge.net>
* doc/namespace.n: document correct functionality
* generic/tclNamesp.c: corrected behaviour of [namespace code]
- (Bug #219385, Patch #403530)
+ [Bug 219385, Patch 403530]
* library/init.tcl:
* tests/namespace-old.test: test correct functionality
* tests/namespace.test: test correct functionality
2001-04-07 Andreas Kupries <andreas_kupries@users.sourceforge.net>
- * unix/Makefile.in (checkdoc): New target, checking the
- definitions as found in the compiled library against the
- manpages to find undocumented public functionality.
+ * unix/Makefile.in (checkdoc): New target, checking the definitions as
+ found in the compiled library against the manpages to find
+ undocumented public functionality.
* unix/mkLinks: Updated to include the new manpage.
* doc/UniCharIsAlpha.3: New manpage documenting the Unicode
- character classification APIs [Bug #218720].
+ character classification APIs. [Bug 218720]
2001-04-07 Andreas Kupries <andreas_kupries@users.sourceforge.net>
* unix/mkLinks: Updated to incorporate the changes below.
* doc/StringObj.3: Added 'Tcl_AttemptSetObjLength' to the NAME
- section. [Bug #414435].
+ section. [Bug 414435]
- * doc/Alloc.3: Added both 'Tcl_AttemptAlloc' and
- 'Tcl_AttemptRealloc' to the NAME section. [Bug #414435].
+ * doc/Alloc.3: Added both 'Tcl_AttemptAlloc' and 'Tcl_AttemptRealloc'
+ to the NAME section. [Bug 414435]
* doc/Utf.3: Added both 'Tcl_UniCharCaseMatch' and
- 'Tcl_UniCharNcasecmp' to the NAME section. [Bug #414435].
+ 'Tcl_UniCharNcasecmp' to the NAME section. [Bug 414435]
2001-04-06 Don Porter <dgp@users.sourceforge.net>
* library/init.tcl:
- * tests/init.test: Modified processing of $::errorInfo by
- [unknown] when the auto-loaded command throws an error to better
- cover the tracks of auto-loading. [Bug 219280, Patch 403551]
+ * tests/init.test: Modified processing of $::errorInfo by [unknown]
+ when the auto-loaded command throws an error to better cover the
+ tracks of auto-loading. [Bug 219280, Patch 403551]
2001-04-06 Donal K. Fellows <fellowsd@cs.man.ac.uk>
* doc/read.n: Added section on "USE WITH SERIAL PORTS" to resolve
- [Bug #219402]
+ [Bug 219402]
* tests/string.test (string-2.30): Test for this case
* generic/tclCmdMZ.c (Tcl_StringObjCmd, STR_COMPARE branch): Fixed
problem caused by Utf-rep of \x00 being more than Utf-rep of \x01
- fooling memcmp by forcing everything through Utf-based
- comparisons. Added optimizations for case where objects have a
- string/unicode-rep or a bytearray-rep (i.e. where we can perform
- comparisons on fixed-size units.) [Bug #219201]
+ fooling memcmp by forcing everything through Utf-based comparisons.
+ Added optimizations for case where objects have a string/unicode-rep
+ or a bytearray-rep (i.e. where we can perform comparisons on
+ fixed-size units). [Bug 219201]
* generic/tclUtf.c (Tcl_UtfNcmp): Corrected seriously erroneous
comment.
2001-04-05 Andreas Kupries <andreas_kupries@users.sourceforge.net>
- * doc/Macintosh.3: Removed duplicates from .SH line
- [Bug #413983].
+ * doc/Macintosh.3: Removed duplicates from .SH line. [Bug 413983]
2001-04-05 Donal K. Fellows <fellowsd@cs.man.ac.uk>
* generic/tclCmdMZ.c (Tcl_StringObjCmd): Fixed so will compile
- with K&R compilers [Patch #413844, Bug #413847]
+ with K&R compilers. [Patch 413844, Bug 413847]
2001-04-04 Don Porter <dgp@users.sourceforge.net>
* generic/tclMain.c: Patch from Kevin Kenny to restore support of
- pre-ANSI compilers. [Bug 413846, Patch 413842]
+ pre-ANSI compilers. [Bug 413846, Patch 413842]
2001-04-04 Andreas Kupries <andreas_kupries@users.sourceforge.net>
* unix/mkLinks: Updated to contain the new manpage.
- * doc/Environment.3: New manpage, describes Tcl_PutEnv
- [Bug #219171].
+ * doc/Environment.3: New manpage, describes Tcl_PutEnv. [Bug 219171]
- * doc/Macintosh.3: New manpage describing the macintosh specific
- parts of the public API [Bug #219169].
+ * doc/Macintosh.3: New manpage describing the macintosh specific parts
+ of the public API. [Bug 219169]
2001-04-04 Jeff Hobbs <jeffh@ActiveState.com>
* unix/configure:
* unix/tcl.m4: extended test of termios vs. termio vs. sgtty to
better detect result on Linux and when certain configure
- redirections are being used. (max) [Patch #402923; Bug #227412,
- #219194]
+ redirections are being used. [Patch 402923; Bug 227412, 219194] (max)
2001-04-04 Andreas Kupries <andreas_kupries@users.sourceforge.net>
* generic/tclTest.c:
* tests/io.tests: TIP #10 followup correcting a problem with the
- original patch because of the lack of 'testthread id' for a
- non-threaded compilation.
+ original patch because of the lack of 'testthread id' for a
+ non-threaded compilation.
2001-04-04 Kevin Kenny <kennykb@acm.org>
@@ -3440,24 +3338,24 @@
* generic/tclObj.c:
* generic/tclPkg.c:
* generic/tclStringObj.c:
- * generic/tclStubLib.c:
- (TIP#27) Changed a number of Tcl API's to accept "CONST char*"
- in place of simple "char*". (kennykb) [Patch #404026]
+ * generic/tclStubLib.c: (TIP#27) Changed a number of Tcl API's to
+ accept "CONST char*" in place of simple "char*". (kennykb) [Patch
+ 404026]
2001-04-04 Jeff Hobbs <jeffh@ActiveState.com>
* generic/tclListObj.c (Tcl_SetListObj): set objPtr->length = 0 in
empty object case to maintain sanctity of Tcl_Obj bytes/length
- pairing. (porter) [Patch #405998]
+ pairing. [Patch 405998] (porter)
2001-04-03 Andreas Kupries <andreas_kupries@users.sourceforge.net>
* unix/mkLinks: Added 'Signal.3', 'Tcl_WaitPid'.
- * doc/DetachPids.3: Added description of 'Tcl_WaitPid' [Bug #219173].
+ * doc/DetachPids.3: Added description of 'Tcl_WaitPid' [Bug 219173].
* doc/Signal.3: New man page describing the public API procedures
- 'Tcl_SignalId' and 'Tcl_SignalMsg' [Bug #219172].
+ 'Tcl_SignalId' and 'Tcl_SignalMsg'. [Bug 219172]
2001-04-02 Jeff Hobbs <jeffh@ActiveState.com>
@@ -3466,7 +3364,7 @@
* win/README.binary: further notes corrections.
* win/configure:
- * win/tcl.m4 (SHLIB_LD): added -incremental:no. [Bug #219381]
+ * win/tcl.m4 (SHLIB_LD): added -incremental:no. [Bug 219381]
2001-04-01 Jeff Hobbs <jeffh@ActiveState.com>
@@ -3474,8 +3372,8 @@
* mac/README:
* win/README:
* win/README.binary:
- * unix/README: updated patchlevel information to 8.4a3 and
- updated links and notes.
+ * unix/README: updated patchlevel information to 8.4a3 and updated
+ links and notes.
* generic/tcl.h:
* tools/tcl.wse.in:
@@ -3489,18 +3387,17 @@
* generic/tclCkalloc.c (TclFinalizeMemorySubsystem): set curTagPtr
to NULL to allow for reuse.
- * generic/tclEvent.c (Tcl_Finalize): moved the tsdPtr
- initialization inside the subsystemsInitialized check to prevent
- it potentially getting called twice during finalization. (wu)
- [Patch #403532, Bug #219391]
+ * generic/tclEvent.c (Tcl_Finalize): moved the tsdPtr initialization
+ inside the subsystemsInitialized check to prevent it potentially
+ getting called twice during finalization.
+ [Patch 403532, Bug 219391] (wu)
* generic/tclThreadTest.c (Tcl_ThreadObjCmd): cast fixes
- * generic/tclTest.c (TestChannelCmd): added cast to mollify
- Windows debug build.
+ * generic/tclTest.c (TestChannelCmd): added cast to mollify Windows
+ debug build.
* win/tclWinSock.c (SocketEventProc): Fixed race condition in
- readability of socket on Windows.
- [Patch #410674, Bug #219205 #219333]
+ readability of socket on Windows. [Patch 410674, Bug 219205, 219333]
* win/tcl.m4: added imm32.lib to LIBS_GUI for Tk IME support.
@@ -3512,38 +3409,36 @@
2001-03-30 Andreas Kupries <andreas_kupries@users.sourceforge.net>
* All of the changes below belong to TIP #10 [Tcl I/O Enhancement:
- Thread-Aware Channels]. See also [Patch #403358] at SF.
+ Thread-Aware Channels]. See also [Patch 403358] at SF.
* generic/tclIO.h (struct ChannelState, line 236f): Extended the
- structure with a new field of type 'Tcl_ThreadId' to hold the id
- of the thread currently managing all channels with this state.
+ structure with a new field of type 'Tcl_ThreadId' to hold the id of
+ the thread currently managing all channels with this state.
- Note: This structure is shared by all channels in a stack of
- transformations.
+ Note: This structure is shared by all channels in a stack of
+ transformations.
- * generic/tclIO.c (Tcl_CreateChannel, lines 1058-1065): Modified
- to store the Id of the current thread in the 'ChannelState' of
- the new channel.
+ * generic/tclIO.c (Tcl_CreateChannel, lines 1058-1065): Modified to
+ store the Id of the current thread in the 'ChannelState' of the new
+ channel.
- * generic/tclIO.c (Tcl_SpliceChannel, lines 2265-2270): Modified
- in the same manner as 'Tcl_CreateChannel' as the channel will be
- managed by the current thread afterward.
+ * generic/tclIO.c (Tcl_SpliceChannel, lines 2265-2270): Modified in
+ the same manner as 'Tcl_CreateChannel' as the channel will be managed
+ by the current thread afterward.
* generic/tclIO.c (Tcl_GetChannelThread, lines 1478-1503):
- * generic/tcl.decls (Tcl_GetChannelThread, lines 1504-1506): New
- API function to retrieve the Id of the managing thread from a
- channel. Implementation and declaration.
+ * generic/tcl.decls (Tcl_GetChannelThread, lines 1504-1506): New API
+ function to retrieve the Id of the managing thread from a channel.
+ Implementation and declaration.
* generic/tclTest.c (TestChannelCmd, lines 4520-4532): Added
- subcommand 'mthread' to query a channel about its managing
- thread.
+ subcommand 'mthread' to query a channel about its managing thread.
2001-03-29 Mo DeJong <mdejong@redhat.com>
- * tests/interp.test: Print out warning when
- testinterpdelete command is not defined.
- Add tests that checks to make sure a
- child interp inherits the parent's cwd.
+ * tests/interp.test: Print out warning when testinterpdelete command
+ is not defined. Add tests that checks to make sure a child interp
+ inherits the parent's cwd.
2001-03-29 Jeff Hobbs <jeffh@gimlet.activestate.com>
@@ -3553,35 +3448,34 @@
* unix/tclUnixPipe.c (TclpCreateTempFile): prevent potential race
condition and security leak in tmp filename creation.
- (max) [Patch #402924]
+ [Patch 402924] (max)
* unix/configure:
* unix/tcl.m4: corrected IRIX-5.x config to not use -n32.
- (english) [Patch #403626]
+ [Patch 403626] (english)
- * unix/tclUnixThrd.c (Tcl_ConditionWait): fixed handling of
- timeout for threads (corrects excessive CPU usage issue for Tk on
- Unix in threaded Tcl environment). (ruppert) [Bug #411603]
+ * unix/tclUnixThrd.c (Tcl_ConditionWait): fixed handling of timeout
+ for threads (corrects excessive CPU usage issue for Tk on Unix in
+ threaded Tcl environment). [Bug 411603] (ruppert)
2001-03-29 Donal K. Fellows <fellowsd@cs.man.ac.uk>
* doc/lsort.n: Added some notes that clarify the behaviour of
- [lsort] as well as a whole bunch of examples. [Bug #219202]
+ [lsort] as well as a whole bunch of examples. [Bug 219202]
2001-03-27 Jeff Hobbs <jeffh@gimlet.activestate.com>
- * doc/Alloc.3: corrected docs to note that Tcl_Attempt* return
- char *'s, not ints. [Bug #411388]
+ * doc/Alloc.3: corrected docs to note that Tcl_Attempt* return char
+ *'s, not ints. [Bug 411388]
* tests/regexp.test (regexp-19.1):
- * generic/tclCmdMZ.c (Tcl_RegsubObjCmd): fixed handling of nulls
- in subspec value.
+ * generic/tclCmdMZ.c (Tcl_RegsubObjCmd): fixed handling of nulls in
+ subspec value.
2001-03-26 Don Porter <dgp@users.sourceforge.net>
- * generic/tclDecls.h (Tcl_InitCustomHashTable): Correction to
- patch from 2001-01-18; tclDecls.h was not generated using
- 'make genstubs'.
+ * generic/tclDecls.h (Tcl_InitCustomHashTable): Correction to patch
+ from 2001-01-18; tclDecls.h was not generated using 'make genstubs'.
2001-03-26 Donal K. Fellows <fellowsd@cs.man.ac.uk>
@@ -3590,11 +3484,11 @@
2001-03-23 Jeff Hobbs <jeffh@activestate.com>
- * generic/tclVar.c (Tcl_ArrayObjCmd): Corrected retrieval of
- resultPtr to prevent possible corruption.
+ * generic/tclVar.c (Tcl_ArrayObjCmd): Corrected retrieval of resultPtr
+ to prevent possible corruption.
* generic/tclNamesp.c (Tcl_Import): Correctly freed a DString.
- (lavana) [Patch #403755]
+ [Patch 403755] (lavana)
2001-03-15 Donal K. Fellows <fellowsd@cs.man.ac.uk>
@@ -3603,134 +3497,131 @@
2001-03-14 Don Porter <dgp@users.sourceforge.net>
- * library/package.tcl (pkg_mkIndex): Added patch from Vince
- Darley to make [pkg_mkIndex -verbose] even more verbose.
- [Bug 219349, Patch 403529]
+ * library/package.tcl (pkg_mkIndex): Added patch from Vince Darley to
+ make [pkg_mkIndex -verbose] even more verbose. [Bug 219349, Patch
+ 403529]
2001-03-13 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * doc/info.n: Improved documentation for [info hostname].
- [Bug #403840]
+ * doc/info.n: Improved documentation for [info hostname]. [Bug 403840]
* generic/tclVar.c (Tcl_UnsetObjCmd): Made command behave as
- documented [issue remaining from bug #405769]
+ documented [issue remaining from Bug 405769]
- * generic/tclCmdMZ.c (Tcl_StringObjCmd): A missing
- {return TCL_OK;} was causing memory corruption. [Bug #408002]
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd): A missing {return TCL_OK;}
+ was causing memory corruption. [Bug 408002]
* generic/tclExecute.c (TclDeleteExecEnv, GrowEvaluationStack,
- TclExecuteByteCode): Added some casts to ClientData that are
+ (TclExecuteByteCode): Added some casts to ClientData that are
apparently needed on some architectures.
2001-03-12 Donal K. Fellows <fellowsd@cs.man.ac.uk>
* tests/string.test: Fixed some test numberings and added a test.
- [Patch #403229]
+ [Patch 403229]
2001-03-06 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * generic/tclVar.c (Tcl_UnsetObjCmd): Rewrote argument parser to
- avoid a read off the end of the argument array that could occur
- when executing something like [unset -nocomplain] was executed.
- Improved the error message given when too few arguments are given
- (-nocomplain should obviously be *before* --, not after it) and
- also modified the test suite to take account of that and the
- documentation to use the same improvement. [Bug 405769]
+ * generic/tclVar.c (Tcl_UnsetObjCmd): Rewrote argument parser to avoid
+ a read off the end of the argument array that could occur when
+ executing something like [unset -nocomplain] was executed. Improved
+ the error message given when too few arguments are given (-nocomplain
+ should obviously be *before* --, not after it) and also modified the
+ test suite to take account of that and the documentation to use the
+ same improvement. [Bug 405769]
2001-03-02 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * generic/tclExecute.c (TclExecuteByteCode): Fixed bug that could
- pass pointers to freed memory to command implementations, which
- most obviously caused some weird behaviour with [info level], but
- could have caused problems with user code and command traces too.
- [Bug 404865, Patch 405436]
+ * generic/tclExecute.c (TclExecuteByteCode): Fixed bug that could pass
+ pointers to freed memory to command implementations, which most
+ obviously caused some weird behaviour with [info level], but could
+ have caused problems with user code and command traces too. [Bug
+ 404865, Patch 405436]
2001-02-23 msofer <msofer@users.sourceforge.net>
+
* no changes; fixing up the missing comment in the previous one.
Sorry.
2001-02-23 msofer <msofer@ant.utdt>
- * /cvsroot/tcl/tcl/tests/execute.test:
- added test for evaluation of an expression in a variable; evals once
- by compiling, second time using the previous compilation
+ * /cvsroot/tcl/tcl/tests/execute.test: added test for evaluation of an
+ expression in a variable; evals once by compiling, second time using
+ the previous compilation
2001-02-18 Kevin B. Kenny <kennykb@acm.org>
* doc/clock.n: Updated documentation to reflect the addition of
- compat/strftime.c, including the correct formatting of
- ISO-8601:1988 fiscal week number (%V).
-
+ compat/strftime.c, including the correct formatting of ISO-8601:1988
+ fiscal week number (%V).
+
2001-02-15 Donal K. Fellows <fellowsd@cs.man.ac.uk>
* generic/tclCmdMZ.c (Tcl_SplitObjCmd): Improved efficiency of
- splitting strings into individual characters by adding hash so
- that only one Tcl_Obj per character is created. Improves
- performance of splitting of short strings and makes a huge
- difference to splitting of long strings, such as is done in the
- mime package in tcllib. [Bug #131523]
+ splitting strings into individual characters by adding hash so that
+ only one Tcl_Obj per character is created. Improves performance of
+ splitting of short strings and makes a huge difference to splitting of
+ long strings, such as is done in the mime package in tcllib. [Bug
+ 131523]
2001-01-31 Don Porter <dgp@users.sourceforge.net>
- * win/makefile.vc (install-libraries): Corrected misdirected
- install directory for the msgcat 1.2 package.
+ * win/makefile.vc (install-libraries): Corrected misdirected install
+ directory for the msgcat 1.2 package.
2001-01-30 Don Porter <dgp@users.sourceforge.net>
- * generic/tclIO.c (CopyData): Moved code that updates the count
- of how many bytes are left to copy. Corrects bug that when
- writing occurs in the background, the copy loop could be
- escaped without updating the count, causing CopyData() to try
- to copy more bytes than the toRead value originally passed to
- TclCopyChannel(), leading to hangs and misreporting of number
- of bytes copied. [Bug 118203, Patch 103432]
+ * generic/tclIO.c (CopyData): Moved code that updates the count of how
+ many bytes are left to copy. Corrects bug that when writing occurs in
+ the background, the copy loop could be escaped without updating the
+ count, causing CopyData() to try to copy more bytes than the toRead
+ value originally passed to TclCopyChannel(), leading to hangs and
+ misreporting of number of bytes copied. [Bug 118203, Patch 103432]
2001-01-18 Andreas Kupries <a.kupries@westend.com>
- * Everything below belongs together, it fixes bug #123153.
+ Everything below belongs together, it fixes [Bug 123153]
- * generic/tcl.h (line 342): A bit more explanation about the
- default value for TCL_PRESERVE_BINARY_COMPATABILITY.
+ * generic/tcl.h (line 342): A bit more explanation about the default
+ value for TCL_PRESERVE_BINARY_COMPATABILITY.
- * generic/tcl.h (line 1208): Define the macro 'Tcl_InitHashTable'
- only when TCL_PRESERVE_BINARY_COMPATIBILITY is not set
- as it kills binary compatibility to 8.3 and earlier
- versions. This is the main part of the patch/change.
+ * generic/tcl.h (line 1208): Define the macro 'Tcl_InitHashTable' only
+ when TCL_PRESERVE_BINARY_COMPATIBILITY is not set as it kills binary
+ compatibility to 8.3 and earlier versions. This is the main part of
+ the patch/change.
* generic/tcl.decls (line 1469):
* generic/tclHash.c (Tcl_InitHashTable):
* generic/tclHash.c (Tcl_InitHashTableEx):
* generic/tclObj.c (Tcl_InitObjHashTable): Changed
- 'Tcl_InitHashTableEx' to 'Tcl_InitCustomHashTable'. This change
- is more of an estethical nature, replacing the ubiquitous 'Ex'
- suffix with a more meaningful name. The introduced binary
- incompatibility is deemed acceptable as it is between alpha
- versions. Updated callers.
+ 'Tcl_InitHashTableEx' to 'Tcl_InitCustomHashTable'. This change is
+ more of an estethical nature, replacing the ubiquitous 'Ex' suffix
+ with a more meaningful name. The introduced binary incompatibility is
+ deemed acceptable as it is between alpha versions. Updated callers.
* doc/Hash.3:
* unix/mkLinks: Changed 'Tcl_InitHashTableEx' to
- 'Tcl_InitCustomHashTable'.
+ 'Tcl_InitCustomHashTable'.
2001-01-10 Donal K. Fellows <fellowsd@cs.man.ac.uk>
- * tests/winPipe.test (winpipe-1.20):
- * tests/winDde.test (createChildProcess):
- * tests/pkgMkIndex.test (pkgtest::createIndex): Removed
- assumption that paths contain no spaces which causes problems with
- both [eval] and [open |...] due to the well-known differences
- between lists and strings. Fixes bug #119406
+ * tests/winPipe.test (winpipe-1.20):
+ * tests/winDde.test (createChildProcess):
+ * tests/pkgMkIndex.test (pkgtest::createIndex): Removed assumption
+ that paths contain no spaces which causes problems with both [eval]
+ and [open |...] due to the well-known differences between lists and
+ strings. Fixes [Bug 119406]
2001-01-04 Don Porter <dgp@users.sourceforge.net>
* tests/unixInit.test:
* unix/tclUnixInit.c (TclpInitLibraryPath):
- * win/tclWinInit.c (TclpInitLibraryPath): Several entries in
- the library path ($tcl_libPath) are determined relative to the
- absolute path of the executable. When the executable is
- installed in or near the root directory of the file system,
- relative pathnames were being incorrectly generated, and in
- the worst case, memory access violations were crashing the program.
- [Bug 119416, Patch 102972]
+ * win/tclWinInit.c (TclpInitLibraryPath): Several entries in the
+ library path ($tcl_libPath) are determined relative to the absolute
+ path of the executable. When the executable is installed in or near
+ the root directory of the file system, relative pathnames were being
+ incorrectly generated, and in the worst case, memory access violations
+ were crashing the program. [Bug 119416, Patch 102972]
******************************************************************
*** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000" ***
diff --git a/ChangeLog.2002 b/ChangeLog.2002
new file mode 100644
index 0000000..30b8b17
--- /dev/null
+++ b/ChangeLog.2002
@@ -0,0 +1,4741 @@
+2002-12-18 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc: some uses of xcopy swapped to the @$(CPY) macro.
+ Reported by Joe Mistachkin <joe@mistachkin.com>.
+
+2002-12-17 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclNotify.c (TclFinalizeNotifier, Tcl_SetServiceMode):
+ (Tcl_ThreadAlert): Check that the stub functions are non-NULL before
+ calling them. They could be set to NULL by Tcl_SetNotifier.
+
+2002-12-16 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tclPipe.c (TclCleanupChildren):
+ * tests/winPipe.test:
+ * win/tclWinPipe.c (Tcl_WaitPid):
+ * win/tclWinTest.c: Gave Tcl_WaitPid the ability to return a Win32
+ exception code translated into a posix style SIG*. This allows [close]
+ to report "CHILDKILLED" without the meaning getting lost in a
+ truncated exit code. In TclCleanupChildren(), TclpGetPid() had to get
+ moved to before Tcl_WaitPid() as the the handle is removed from the
+ list taking away the ability to get the process id after the wait is
+ done. This shouldn't effect the unix implimentaion unless waitpid is
+ called with a pid of zero, meaning "any". I don't think it is..
+
+2002-12-13 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/configure.in: Updated configure of CVS snapshots to reflect
+ * win/configure.in: the 8.4.1.1 patchlevel.
+
+ * unix/configure: autoconf
+ * win/configure autoconf
+
+2002-12-11 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclProc.c (ProcessProcResultCode): Fix failure to propagate
+ negative return codes up the call stack. [Bug 647307]
+ * tests/proc.test (proc-6.1): Test for Bug 647307
+
+ * generic/tclParseExpr.c (TclParseInteger): Return 1 for the string
+ "0x" (recognize leading "0" as an integer). [Bug 648441]
+ * tests/parseExpr.test (parseExpr-19.1): Test for Bug 648441.
+
+2002-12-09 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tclWinThrd.c (TclpMasterUnlock):
+ * generic/tclThread.c (TclFinalizeThreadData): TclpMasterUnlock must
+ exist and be called unconditional of TCL_THREADS. [Bug 651139]
+
+2002-12-08 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinSock.c (SocketThreadExitHandler, InitSockets): Check
+ that the tsdPtr is valid before dereferencing as we call it from the
+ exit handler, too [Bug 650353]. Another WSAStartup() loaded version
+ comparison byte swap issue fixed. Although 0x0101 byte swapped is
+ still 0x0101, properly claiming which is major/minor is more correct.
+
+2002-12-06 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclStubInit.c: regen
+ * generic/tclIntPlatDecls.h: regen
+ * generic/tclInt.decls: added TclWinResetInterface
+
+ * win/tclWin32Dll.c (TclWinResetInterfaces):
+ * win/tclWinInit.c (TclpSetInitialEncodings, WinEncodingsCleanup):
+ add exit handler that resets the encoding information to a state where
+ we can reuse Tcl. Following these changes, it is possible to reuse Tcl
+ (following Tcl_FindExecutable or Tcl_CreateInterp) following a
+ Tcl_Finalize.
+
+ * generic/tclIOUtil.c (TclFinalizeFilesystem): reset statics to their
+ original values on finalize to allow reuse of the library.
+
+2002-12-04 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinPipe.c: reverted back to -r1.27 due to numerous test
+ failures that need to be resolved first. The idea was good, but the
+ details aren't.
+
+2002-12-04 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinPipe.c (Tcl_WaitPid): When a process exits with an
+ exception, pass this notice on to the caller with a SIG* code rather
+ than truncating the exit code and missing the meaning. This allows
+ TclCleanupChildren() to report "CHILDKILLED".
+
+ This has a different behavior than unix in that closing the read pipe
+ to a process sends the SIGPIPE signal which is returned as a SIGPIPE
+ exit status. On windows, we send the process a CTRL_BREAK_EVENT and
+ get back a CONTROL_C_EXIT which is documented to mean a SIGINT which
+ seems wrong as a system, but is the correct exit status.
+
+2002-12-04 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclIOUtil.c: fix to redirected 'load' in virtual filesystem
+ for some Unix systems.
+
+ * generic/tclEvent.c: the filesystem must be cleaned up before the
+ encoding subsystem because it needs access to encodings. Fixes crash
+ on exit observed in embedded applications.
+
+ * generic/tclTestObj.c: patch omitted from previous change of
+ 2002-11-13
+
+2002-12-03 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclStubLib.c (Tcl_InitStubs): prevent the cached check of
+ tclStubsPtr to allow for repeated load/unload of the Tcl dll by
+ hosting apps. [Bug 615304]
+
+2002-12-03 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclAppInit.c (sigHandler): Protect from trying to close a NULL
+ handle.
+
+ * win/tclWinPipe.c (PipeClose2Proc, TclpCreateProcess): Send a real
+ Win32 signal (CTRL_C_EVENT) when the read channel is brought down to
+ alert the child to close on its side. Start the process with
+ CREATE_NEW_PROCESS_GROUP to allow the ability to send these signals.
+ The following test case now brings down the child without the use of
+ an external [kill] command.
+
+ % set p [open "|[info name]" w+]
+ file8d5380
+ % pid $p
+ 2876
+ % close $p <- now doesn't block in Tcl_WaitPid()
+ %
+
+ * win/tclWinPipe.c (PipeClose2Proc): Changed CTRL_C_EVENT to
+ CTRL_BREAK_EVENT as it can't be ignored by the child and proved to
+ work on [open "|netstat 1" w+] where CTRL_C_EVENT didn't.
+
+2002-11-27 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinPort.h: Don't turn off winsock prototypes! TclX didn't
+ like it. Even though the core doesn't use the prototypes, do offer
+ them.
+
+ * win/tclWinSock.c: Removed shutdown() from the function table as it
+ wasn't referenced anywhere and cleaned-up some casting that that
+ wasn't needed.
+
+ * win/tclWinSock.c: WSAStartup() loaded version comparison error which
+ resulted in 2.0 looking less than 1.1.
+
+ * win/tclWinChan.c (Tcl_MakeFileChannel): return of DuplicateHandle()
+ incorrectly used. [Bug 618852]
+
+2002-11-26 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclEncoding.c (TclFinalizeEncodingSubsystem): properly
+ cleanup all encodings by using Tcl_FirstHashEntry in the while loop.
+
+ * unix/Makefile.in (valgrind): add simple valgrind target
+
+ * tests/exec.test: unset path var to allow singleproc testing
+
+ * generic/tclInterp.c (AliasCreate): preserve/release interps to
+ prevent possible FMR error in bad alias cases.
+
+2002-11-26 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinPort.h:
+ * win/tclWinSock.c: This patch does two things:
+
+ 1) Cleans-up the winsock typedefs by using the typedefs provided by
+ winsock2.h. This has no effect on how winsock is initialized; just
+ makes the source code easier to read. [Patch 561305 561301]
+
+ 2) Revamps how the socket message handler thread is brought up and
+ down to allow for cleaner exits without the use of TerminateThread().
+ TerminateThread is evil. No attempt has been made to resolve [Bug
+ 593810] which may need a new channel driver version for adding a
+ registering function within the transfered thread to init the handler
+ thread. IOW, initialization of the TSD structure is getting bypassed
+ through the thread extension's [thread::transfer] command.
+
+2002-11-26 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinConsole.c:
+ * win/tclWinPipe.c:
+ * win/tclWinSerial.c:
+ * win/tclWinSock.c:
+ * win/tclWinThrd.c:
+ * win/tclWinTime.c: General cleanup of all worker threads used by the
+ channel drivers. Eliminates the normal case where the worker thread is
+ terminated ('cept the winsock one). Instead, use kernel events to
+ signal a clean exit. Only when the worker thread is blocked on an I/O
+ call is the thread terminated. Essentially, this makes all other
+ channel worker threads behave like the PipeReaderThread() function for
+ it's cleaner exit behavior. This appears to fix [Bug 597924] but needs
+ 3rd party confirmation to close the issue.
+
+2002-11-26 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/README: Update msys build env URL. This release #4 build both
+ tcl and tk without problems.
+
+2002-11-22 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/init.tcl: code cleanup to reduce use of
+ * library/opt/optparse.tcl: string compare
+
+ * tests/interp.test: interp-14.4
+ * generic/tclInterp.c (TclPreventAliasLoop): prevent seg fault when
+ creating an alias command over the interp name. [Bug 641195]
+
+2002-11-18 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclUtil.c (SetEndOffsetFromAny): handle integer offset
+ after the "end-" prefix.
+
+ * generic/get.test:
+ * generic/string.test:
+ * generic/tclObj.c (SetIntFromAny, SetWideIntFromAny):
+ * generic/tclGet.c (TclGetLong, Tcl_GetInt): simplify sign handling
+ before calling strtoul(l). [Bug 634856]
+
+2002-11-18 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinThrd.c (Tcl_CreateThread/TclpThreadExit): Fixed improper
+ compiler macros that missed the VC++ compiler. This resulted in VC++
+ builds using CreateThread()/ExitThread() in place of the proper
+ _beginthreadex()/_endthreadex(). This was a large error and am
+ surprised I missed seeing it earlier.
+
+2002-11-13 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/regexpComp.test: added tests 22.*
+ * generic/tclCompCmds.c (TclCompileRegexpCmd): add left and right
+ anchoring (^ and $) recognition and check starting or ending .* to
+ extend the number of REs that can be compiled to string match or
+ string equal.
+
+2002-11-13 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclCmdMZ.c:
+ * tests/trace.test: applied patch from Hemang Levana to fix [Bug
+ 615043] in execution traces with 'return -code error'.
+
+ * generic/tclTestObj.c:
+ * tests/stringObj.test: added 'knownBug' test for [Bug 635200]
+ * generic/tclStringObj.c: corrected typos in comments
+
+ * generic/tclFileName.c:
+ * tests/fileName.test: applied patch for bug reported against tclvfs
+ concerning handling of Windows serial ports like 'com1', 'lpt3' by the
+ virtual filesystem code.
+
+ * doc/RegExp.3: clarification of the 'extendMatch' return values.
+
+2002-11-11 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclUtil.c (Tcl_Backslash): use TclUtfToUniChar.
+ (Tcl_StringCaseMatch): use TclUtfToUniChar and add further
+ optimizations for the one-byte/char case.
+
+ * generic/tclUtf.c: make use of TclUtfToUniChar macro throughout the
+ functions, and add extra optimization to Tcl_NumUtfChars for
+ one-byte/char case.
+
+ * generic/tclVar.c (DisposeTraceResult, CallVarTraces): add proper
+ static declarations.
+
+ * generic/tclStringObj.c (Tcl_GetCharLength): optimize for the ascii
+ char case.
+ (Tcl_GetUniChar): remove unnecessary use of Tcl_UtfToUniChar.
+ (FillUnicodeRep): Use TclUtfToUniChar.
+
+ * generic/tclHash.c (HashStringKey): move string++ lower to save an
+ instruction.
+
+ * generic/tclExecute.c (TclExecuteByteCode): improve INST_STR_CMP to
+ use memcmp in the one-byte/char case, also use direct index for
+ INST_STR_INDEX in that case.
+
+ * generic/tclEncoding.c (UtfToUtfProc, UtfToUnicodeProc):
+ (TableFromUtfProc, EscapeFromUtfProc): Use TclUtfToUniChar.
+ (UnicodeToUtfProc, TableToUtfProc): add 1-byte char optimizations for
+ Tcl_UniCharToUtf call. These improve encoded channel conversion speeds
+ by up to 20%.
+
+ * tests/split.test: added 1-char string split tests
+ * generic/tclCmdMZ.c (Tcl_SplitObjCmd): Use TclUtfToUniChar. Also
+ added a special case for single-ascii-char splits.
+ (Tcl_StringObjCmd): Use TclUtfToUniChar. For STR_RANGE, support
+ getting ranges of ByteArrays (reverts change from 2000-05-26).
+ (TraceExecutionProc) add proper static declaration.
+
+ * generic/tclInt.h: add macro version of Tcl_UtfToUniChar
+ (TclUtfToUniChar) that does the one-byte utf-char check without
+ calling Tcl_UtfToUniChar, for use by the core. This brings notable
+ speedups for primarily ascii string handling.
+
+ * generic/tcl.h (TCL_PATCH_LEVEL): bump to 8.4.1.1 for patchlevel
+ only. This interim number will only be reflected by [info patchlevel].
+
+2002-11-11 Kevin Kenny <kennykb@acm.org>
+
+ * doc/Tcl.n: Corrected indentation of the new language. Oops.
+
+2002-11-10 Kevin Kenny <kennykb@acm.org>
+
+ * doc/Tcl.n: Added language to the Endekalogue to make it clear that
+ substitutions always take place from left to right. [Bug 635644]
+
+2002-11-06 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * changes: Note TclInExit TclInThreadExit changes.
+ * generic/tclEvent.c (TclInExit, TclInThreadExit): Split out
+ functionality of TclInExit to make it clear which one should be called
+ in each situation.
+ * generic/tclInt.decls: Declare TclInThreadExit.
+ * generic/tclIntDecls.h: Regen.
+ * generic/tclStubInit.c: Regen.
+ * mac/tclMacChan.c (StdIOClose):
+ * unix/tclUnixChan.c (FileCloseProc):
+ * win/tclWinChan.c (FileCloseProc):
+ * win/tclWinConsole.c (ConsoleCloseProc):
+ * win/tclWinPipe.c (TclpCloseFile):
+ * win/tclWinSerial.c (SerialCloseProc): Invoke the new TclInThreadExit
+ method instead of TclInExit.
+
+2002-11-06 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): Generate a fatal configure error if
+ no ar program can be found on the path. [Bug 582039]
+ * win/configure: Regen.
+ * win/configure.in: Check that AR, RANLIB, and RC are found on the
+ path when building with gcc.
+
+2002-11-03 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclAppInit.c: Calls Registry_Init() and Dde_Init() when
+ STATIC_BUILD and TCL_USE_STATIC_PACKAGES macros are set.
+
+ * win/makefile.vc:
+ * win/rules.vc: linkexten option now sets the TCL_USE_STATIC_PACKAGES
+ macro which also adds the registry and dde object files to the link
+ of the shell. [Patch 479697] Also factored some additional macros that
+ will be helpful for extension authors. Version grepping of tcl.h will
+ need to be added to complete this.
+
+ * win/buildall.vc.bat: Added more descriptive commentary.
+
+2002-11-01 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinReg.c: Changed the Tcl_PkgProvide() line to declare the
+ registry extension at version 1.1 from 1.0.
+
+2002-10-31 Andreas Kupries <andreask@activestate.com>
+
+ * library/word.tcl: Changed $tcl_platform to $::tcl_platform to avoid
+ possible scope trouble.
+
+2002-10-29 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * win/tclWinInt.h:
+ * win/tclWin32Dll.c: added comments about certain NULL function
+ pointers which will be filled in when Tcl_FindExecutable is called, so
+ that users don't report invalid bugs on this topic. (No code changes
+ at all).
+
+2002-10-29 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tclLoadDyld.c (TclpFindSymbol): pass all dyld error messages
+ upstream [Bug 627546].
+
+2002-10-28 Andreas Kupries <andreask@activestate.com>
+
+ * library/dde/pkgIndex.tcl:
+ * library/reg/pkgIndex.tcl: Changed the hardwired debug suffix (d) to
+ the correct suffix (g).
+
+2002-10-28 Don Porter <dgp@users.sourceforge.net>
+
+ * library/auto.tcl: Converted the Mac-specific [package unknown]
+ * library/init.tcl: behavior to use a chaining mechanism to extend
+ * library/package.tcl: the default [tclPkgUnknown]. [Bug 627660]
+ * library/tclIndex: [Patch 624509] (steffen)
+
+2002-10-26 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc: xcopy on NT 4.0 doesn't support the /Y switch
+ (overwrite). Added logic to handle this. [Bug 618019]
+
+2002-10-23 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclInt.h: Removed definitions of obsolete HistoryEvent and
+ HistoryRev structures (the history mechanism has been written in Tcl
+ for some time now.)
+
+2002-10-22 Jeff Hobbs <jeffh@ActiveState.com>
+
+ *** 8.4.1 TAGGED FOR RELEASE ***
+
+ * changes: updated for 8.4.1 release
+
+ * win/Makefile.in: removed @MEM_DEBUG_FLAGS@ subst.
+ * win/configure: regen
+ * win/configure.in: removed SC_ENABLE_MEMDEBUG call
+ * win/tcl.m4: replaced SC_ENABLE_MEMDEBUG with a more intelligent
+ SC_ENABLE_SYMBOLS that takes yes|no|mem|compile|all as options now.
+
+2002-10-22 Daniel Steffen <das@users.sourceforge.net>
+
+ * library/auto.tcl (tcl_findLibrary):
+ * library/package.tcl (tclPkgUnknown): on macosx, search inside the
+ Resources/Scripts subdirectory of any potential package directory.
+ * macosx/Tcl.pbproj/project.pbxproj: add standard Frameworks dirs to
+ TCL_PACKAGE_PATH make argument.
+ * unix/tclUnixInit.c (TclpSetVariables): on macosx, add embedded
+ framework dirs to tcl_pkgPath: @executable_path/../Frameworks and
+ @executable_path/../PrivateFrameworks (if they exist), as well as the
+ dirs in DYLD_FRAMEWORK_PATH (if set). [Patch 624509]
+ use standard MAXPATHLEN instead of literal 1024
+
+2002-10-22 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/StringObj.3, doc/Object.3: Documented that Tcl_Obj's standard
+ string form is a modified UTF-8; apparently, this was not mentioned
+ anywhere in the main docs, and lead to [Bug 624919].
+
+2002-10-21 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Tcl.pbproj/project.pbxproj: bumped version to 8.4.1
+ * generic/tcl.h: Added reminder comment to edit
+ macosx/Tcl.pbproj/project.pbxproj when version number changes.
+
+2002-10-18 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/reg/pkgIndex.tcl:
+ * win/configure:
+ * win/configure.in:
+ * win/Makefile.in:
+ * win/makefile.vc:
+ * win/makefile.bc: Updated to reg1.1
+
+ * doc/registry.n: Added support for broadcasting changes to the
+ * tests/registry.test: registry Environment. Noted proper code in the
+ * win/tclWinReg.c: docs. [Patch 625453]
+
+ * unix/Makefile.in (dist): add any mac/tcl*.sea.hqx files
+
+2002-10-17 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclVar.c: Fixed code that check for proper # of args to
+ * tests/var.test: [array names]. Added test. [Bug 624755]
+
+2002-10-16 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/configure: add workaround for cygwin windres
+ * win/tcl.m4 (SC_CONFIG_CFLAGS): problem. [Patch 624010] (howell)
+
+2002-10-15 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * README: added archives.tcl.tk note
+
+ * unix/configure:
+ * unix/tcl.m4: Correct AIX-5 ppc build flags. Correct HP 11 64-bit gcc
+ building. [Patch 601051] (martin)
+
+2002-10-15 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclCmdMZ.c:
+ * tests/trace.test: applied patch from Hemang Levana to fix [Bug
+ 615043] in execution traces with idle tasks firing.
+
+2002-10-14 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclEnv.c (Tcl_PutEnv): correct possible mem leak. [Patch
+ 623269] (brouwers)
+
+2002-10-11 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tcl.h: Need a different strategy through the maze of
+ #defines to let people building with Cygwin build correctly. Also made
+ some comments less misleading...
+
+2002-10-10 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * README: fixed minor nits [Bug 607776] (virden)
+
+ * win/configure:
+ * win/tcl.m4: enable USE_THREAD_ALLOC (new threaded allocator) by
+ default in cygwin configure on Windows.
+
+2002-10-10 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/Tcl.n: Clarified that namespace separators are legal in the
+ variable names during $-subtitution. [Bug 615139]
+
+ * doc/regexp.n: Typo correction. Thanks Ronnie Brunner. [Bug 606826]
+
+2002-10-10 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * unix/tclLoadAout.c
+ * unix/tclLoadDl.c
+ * unix/tclLoadDld.c
+ * unix/tclLoadDyld.c
+ * unix/tclLoadNext.c
+ * unix/tclLoadOSF.c
+ * unix/tclLoadShl.c
+ * win/tclWinLoad.c: allow either full paths or simply dll names to be
+ specified when loading files (the latter will be looked up by the OS
+ on your PATH/LD_LIBRARY_PATH as appropriate). Fixes [Bug 611108]
+
+2002-10-09 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/README: doc'ed --enable-symbols options.
+ * unix/Makefile.in: removed @MEM_DEBUG_FLAGS@ subst.
+ * unix/configure: regen
+ * unix/configure.in: removed SC_ENABLE_MEMDEBUG call
+ * unix/tcl.m4: replaced SC_ENABLE_MEMDEBUG with a more intelligent
+ SC_ENABLE_SYMBOLS that takes yes|no|mem|compile|all as options now.
+
+2002-10-09 Kevin B. Kenny <kennykb@acm.org>
+
+ * win/tclWinTime.c: Added code to set an exit handler that terminates
+ the thread that calibrates the performance counter, so that the thread
+ won't outlive unloading the Tcl DLL. [Bug 620735]
+
+2002-10-09 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/binary.n: More clarification of [binary scan]'s behaviour.
+
+2002-10-09 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tclIntDecls.h: fixed botched regen.
+
+2002-10-09 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tclInt.decls: made TclSetPreInitScript() declaration
+ generic as it is used on mac & aqua as well.
+ * generic/tclIntDecls.h:
+ * generic/tclStubInit.c: regen.
+ * generic/tclCompile.h: added prototype for TclCompileVariableCmd.
+
+ * mac/tclMacPort.h: removed incorrect <fcntl.h> definitions and
+ obsolete <stat.h> definitions.
+ * mac/tclMacChan.c: removed obsolete GetOpenMode() and replaced
+ associated constants with the <fcntl.h> analogues (they existing defs
+ were inconsistent with <fcntl.h> which was causing havoc when
+ Tcl_GetOpenMode was used instead of private GetOpenMode).
+
+ * mac/tclMacFCmd.c: removed GenerateUniqueName(), use equivalent (and
+ identically named) routine from MoreFiles instead.
+
+ * mac/tclMacLoad.c: CONSTification, fixes to Vince's last changes.
+
+ * mac/tclMacFile.c:
+ * mac/tclMacTest.c:
+ * mac/tclMacUnix.c: CONSTification.
+
+ * mac/tclMacOSA.c: CONSTification, sprintf fixes, UH 3.4.x changes;
+ fix for missing autoname token from TclOSACompileCmd. (bdesgraupes)
+ * mac/AppleScript.html(AppleScript delete): doc fix. (bdesgraupes)
+
+ * mac/tcltkMacBuildSupport.sea.hqx: updated MoreFiles to 1.5.3,
+ updated build instructions for 8.4.
+ * mac/tclMacProjects.sea.hqx: rebuilt archive.
+
+2002-10-09 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/Alloc.3: Added a note to mention that attempting to allocate a
+ zero-length block can return NULL. [Tk Bug 619544]
+
+2002-10-04 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/binary.n: Doc improvements [Patch 616480]
+
+ * tests/fCmd.test, tests/winFCmd.test:
+ * tools/eolFix.tcl, tools/genStubs.tcl: [file exist] -> [file exists]
+ Thanks to David Welton.
+
+2002-10-03 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/tcltest.n: fixed typo [Bug 618018]. Thanks to "JJM".
+
+2002-10-03 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tools/man2help2.tcl:
+ * tests/http.test, tests/httpd, tests/httpold.test:
+ * tests/env.test, tests/binary.test, tests/autoMkindex.test:
+ * library/init.tcl, library/http/http.tcl: [info exist] should really
+ be [info exists]. [Bug 602566]
+
+ * doc/lsearch.n: Better specification of what happens when -sorted is
+ mixed with other options. [Bug 617816]
+
+2002-10-01 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclProc.c (TclCreateProc): mask out VAR_UNDEFINED for
+ precompiled locals to support 8.3 precompiled code.
+ (Tcl_ProcObjCmd): correct 2002-09-26 fix to look for tclProcBodyType.
+
+2002-10-01 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/socket.n: Mentioned that ports may be specified as serivce names
+ as well as integers. [Bug 616843]
+
+2002-09-30 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclCompCmds.c (TclCompileRegexpCmd): correct the checking
+ for bad re's that didn't terminate the re string. Resultant compiles
+ were correct, but much slower than necessary.
+
+2002-09-29 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclAppInit.c: Added proper exiting conditions using Win32
+ console signals. This handles the existing lack of a Ctrl+C exit to
+ call exit handlers when built for thread support. Also, properly
+ handles exits from other conditions such as CTRL_CLOSE_EVENT,
+ CTRL_LOGOFF_EVENT, and CTRL_SHUTDOWN_EVENT signals. In all cases,
+ exit handlers will be called. [Bug 219355]
+
+ * win/makefile.vc: Added missing tclThreadAlloc.c to the build rules
+ and defines USE_THREAD_ALLOC when TCL_THREADS is defined to get the
+ new behavior by default.
+
+2002-09-27 Don Porter <dgp@users.sourceforge.net>
+
+ * README: Bumped to version 8.4.1 to avoid confusion of
+ * generic/tcl.h: CVS snapshots with the actual 8.4.0 release.
+ * tools/tcl.wse.in:
+ * unix/configure.in:
+ * unix/tcl.spec:
+ * win/configure.in:
+
+ * unix/configure: autoconf
+ * win/configure:
+
+2002-09-26 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/configure: regen.
+ * unix/tcl.m4: improve AIX-4/5 64bit compilation support.
+
+ * generic/tclProc.c (Tcl_ProcObjCmd): correct overeager optimization
+ of noop proc to handle the precompiled case. (sofer)
+
+ * unix/ldAix (nmopts): add -X32_64 to make it work for 32 or 64bit
+ mode compilation.
+
+ * library/encoding/koi8-u.enc: removed extraneous spaces that confused
+ encoding reader. [Bug 615115]
+
+ * unix/Makefile.in: generate source dists with -src designator and do
+ not generate .Z anymore (just .gz and .zip).
+
+2002-09-18 Mumit Khan <khan@nanotech.wisc.edu>
+
+ Added basic Cygwin support.
+
+ * win/tcl.m4 (SC_PATH_TCLCONFIG): Support one-tree build.
+ (SC_PATH_TKCONFIG): Likewise.
+ (SC_PROG_TCLSH): Likewise.
+ (SC_CONFIG_CFLAGS): Assume real Cygwin port and remove -mno-cygwin
+ flags. Add -mwin32 to extra_cflags and extra_ldflags. Remove ``-e
+ _WinMain@16'' from LDFLAGS_WINDOW.
+ * win/configure.in: Allow Cygwin build.
+ (SEH test): Define to be 1 instead of empty value.
+ (EXCEPTION_DISPOSITION): Add test.
+ * win/configure: Regenerate.
+
+ * generic/tcl.h: Don't explicitly define __WIN32__ for Cygwin, let the
+ user decide whether to use Windows or POSIX personality.
+ (TCL_WIDE_INT_TYPE, TCL_LL_MODIFIER, struct Tcl_StatBuf): Define for
+ Cygwin.
+ * generic/tclEnv.c (Tcl_CygwinPutenv): putenv replacement for Cygwin.
+ * generic/tclFileName.c (Tcl_TranslateFileName): Convert POSIX to
+ native format.
+ (TclDoGlob): Likewise.
+ * generic/tclPlatDecls.h (TCHAR): Define for Cygwin.
+ * win/tclWinPort.h (putenv, TclpSysAlloc, TclpSysFree,
+ (TclpSysRealloc): Define for Cygwin.
+
+2002-09-26 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Makefile: preserve environment value of INSTALL_ROOT. When
+ embedding only use deployment build. Force relink before embedded
+ build to ensure new linker flags are picked up.
+
+ * macosx/Tcl.pbproj/project.pbxproj: add symbolic links to debug lib,
+ stub libs and tclConfig.sh in framework toplevel. Configure target
+ dependency fix. Fix to 'clean' action. Added private tcl headers to
+ framework. Install tclsh symbolic link. Html doc build works when no
+ installed tclsh available. Made html doc structure in framework more
+ like in Apple frameworks.
+
+2002-09-24 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * unix/tcl.m4 (SC_TCL_64BIT_FLAGS): Yet more robust 64-bit value
+ detection to close [Bug 613117] on more systems.
+
+ * generic/tclCompile.c (TclPrintSource): More CONSTifying.
+ * generic/tclExecute.c (EvalStatsCmd): Object-ify to reduce warnings.
+ Thanks to 'CoderX2' on the chat for bringing this to my attention...
+
+ * unix/tcl.m4: Forgot to define TCL_WIDE_INT_IS_LONG at the
+ appropriate moment. I believe this is the cause of [Bug 613117]
+
+ * doc/lset.n: Changed 'list' to 'varName' for consistency with lappend
+ documentation. Thanks to Glenn Jackman [Bug 611719]
+
+2002-09-22 Don Porter <dgp@users.sourceforge.net>
+
+ * library/tcltest/tcltest.tcl: Corrected [puts -nonewline] within
+ test bodies. Thanks to Harald Kirsch. [Bug 612786, Patch 612788] Also
+ corrected reporting of body return code. Thanks to David Taback [Bug
+ 611922]
+ * library/tcltest/pkgIndex.tcl: Bump to version 2.2.1.
+ * tests/tcltest.test: added tests for these bugs.
+
+2002-09-15 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): Add PEEK_XCLOSEIM define under
+ Linux. This is used by Tk to double check that an X input context is
+ cleaned up before it is closed.
+
+2002-09-12 David Gravereaux <davygrvy@pobox.com>
+
+ * win/coffbase.txt: Added BLT to the virtual base address listings
+ table should BLT's build tools decide to use it.
+
+2002-09-12 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tcl.h:
+ * mac/tclMacApplication.r:
+ * mac/tclMacLibrary.r:
+ * mac/tclMacResource.r: unified use of the two equivalent resource
+ compiler header inclusion defines RC_INVOKED and RESOURCE_INCLUDED,
+ now use RC_INVOKED throughout.
+
+2002-09-10 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/README: Add note about building extensions with the same
+ compiler Tcl was built with. [Tk Bug 592096]
+
+2002-09-10 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Tcl.pbproj/project.pbxproj: disabled building html
+ documentation during embedded build.
+
+2002-09-10 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/Makefile.in: added DYLIB_INSTALL_DIR variable for macosx and
+ set it to default value ${LIB_RUNTIME_DIR}
+ * unix/tcl.m4 (Darwin): use DYLIB_INSTALL_DIR instead of
+ LIB_RUNTIME_DIR in the -install_name argument to ld.
+ * unix/configure: regen.
+
+ * macosx/Tcl.pbproj/project.pbxproj:
+ * macosx/Makefile: added support for building Tcl as an embedded
+ framework, i.e. using an dyld install_name containing
+ @executable_path/../Frameworks via the new DYLIB_INSTALL_DIR
+ unix/Makefile variable.
+
+2002-09-10 Jeff Hobbs <jeffh@ActiveState.com>
+
+ *** 8.4.0 TAGGED FOR RELEASE ***
+
+2002-09-06 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/file.n: Format correction, and clarified [file normalize]
+ returns an absolute path.
+
+ * doc/tcltest.n: Added examples section, as long promised.
+
+2002-09-06 Reinhard Max <max@suse.de>
+
+ * tests/tcltest.test: Added nonRoot flag to tests 8.3, 8.4, and 8.12.
+
+2002-09-05 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/tcltest.n: Clarified phrasing.
+
+ * generic/tclBasic.c (TclRenameCommand,CallCommandTraces):
+ * tests/trace.test (trace-27.1): Corrected memory leak when a rename
+ trace deleted the command being traced. Test added. Thanks to Hemang
+ Lavana for the fix. [Bug 604609]
+
+ * generic/tclVar.c (TclDeleteVars): Corrected logic for setting the
+ TCL_INTERP_DESTROYED flag when calling variable traces. [Tk Bug 605121]
+
+2002-09-04 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclVar.c (DeleteArray): leak plug [Bug 604239]. Thanks to
+ dkf and dgp for the long and difficult discussion in the chat.
+
+2002-09-03 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclVar.c (Tcl_UpVar2): code cleanup to not use goto
+
+ * unix/configure: remove -pthread from LIBS on FreeBSD in thread
+ * unix/tcl.m4: enabled build. [Bug 602849]
+
+2002-09-03 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclInterp.c (AliasCreate): a Tcl_Obj was leaked on error
+ return from TclPreventAliasLoop.
+
+2002-09-03 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Tcl.pbproj/project.pbxproj: Bumped version number to 8.4.0
+ and updated copyright info.
+
+2002-09-03 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclVar.c (Tcl_UpVar2): a Tcl_Obj was being leaked on error
+ return from TclGetFrame.
+
+2002-09-03 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: Updated changes for 8.4.0 release.
+
+2002-09-02 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tclUnixFile.c (TclpObjLink): removed unnecessary/unfreed extra
+ native char*.
+
+ * unix/tclUnixChan.c (Tcl_MakeTcpClientChannel): make sure to init
+ flags field of TcpState ptr to 0.
+
+ * unix/configure:
+ * unix/tcl.m4: added 64-bit gcc compilation support on HP-11.
+ [Patch 601051] (martin)
+
+ * README: Bumped version number to 8.4.0
+ * generic/tcl.h:
+ * tools/tcl.wse.in:
+ * unix/configure:
+ * unix/configure.in:
+ * unix/tcl.spec:
+ * win/README.binary:
+ * win/configure:
+ * win/configure.in:
+
+ * generic/tclInterp.c (SlaveCreate): make sure that the memory and
+ checkmem commands are initialized in non-safe slave interpreters when
+ TCL_MEM_DEBUG is used. [Bug 583445]
+
+ * win/tclWinConsole.c (ConsoleCloseProc): only wait on writable pipe
+ if there was something to write. This may prevent infinite wait on
+ exit.
+
+ * tests/exec.test: marked exec-18.1 unixOnly until the Windows
+ incompatability (in the test, not the core) can be resolved.
+
+ * tests/http.test (http-3.11): added close $fp that was causing an
+ error on Windows because the file was not closed before deleting.
+
+ * unix/tclUnixInit.c (Tcl_MacOSXGetLibraryPath): made this static
+ function only appear when HAVE_CFBUNDLE is defined.
+
+2002-08-31 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tcl.m4: added TK_SHLIB_LD_EXTRAS analogue of existing
+ TCL_SHLIB_LD_EXTRAS for linker settings only used when linking Tk.
+
+ * unix/configure: regen
+
+2002-08-31 Daniel Steffen <das@users.sourceforge.net>
+
+ *** macosx-8-4-branch merged into the mainline [Patch 602770] ***
+
+ * generic/tcl.decls: added new macosx specific entry to stubs table.
+
+ * tools/genStubs.tcl: added generation of platform guards for
+ macosx. This is a little more complex than it seems, because MacOS X
+ IS "unix" plus a little bit, for the purposes of Tcl. BUT
+ unfortunately, Tk uses "unix" to mean X11. So added platform keys for
+ macosx (the little added to "unix"), "aqua" and "x11" to distinguish
+ these for Tk.
+
+ * generic/tcl.h: added a #ifnded RESOURCE_INCLUDED so that tcl.h can
+ be passed to the resource compiler.
+
+ * generic/tcl.h:
+ * generic/tclNotify.c: added a few Notifier procs, to be able to
+ modify more bits of the Tcl notifier dynamically. Required to get Mac
+ OS X Tk to live on top of the Tcl Unix threaded notifier. Changes the
+ size of the Tcl_NotifierProcs structure, but doesn't move any elements
+ around.
+
+ * unix/tclUnixNotfy.c: moved the call to Tcl_ConditionNotify till
+ AFTER we are done mucking with the pointer swap. Fixes cases where the
+ thread waiting on the condition wakes & accesses the waitingListPtr
+ before it gets reset, causing a hang.
+
+ * library/auto.tcl (tcl_findLibrary): added checking the directories
+ in the tcl_pkgPath for library files on macosx to enable support of
+ the standard Mac OSX library locations.
+
+ * unix/Makefile.in:
+ * unix/configure.in:
+ * unix/tcl.m4: added MAC_OSX_DIR. Added PLAT_OBJS to the OBJS: there
+ are some MacOS X specific files now for Tcl, and when I get the
+ resource & applescript stuff ported over, and restore support for
+ FindFiles, etc, there will be a few more. Added LD_LIBRARY_PATH_VAR
+ configure variable to avoid having to set all possible LD_LIBRARY_PATH
+ analogues on all platforms. LD_LIBRARY_PATH_VAR is "LD_LIBRARY_PATH"
+ by default, "LIBPATH" on AIX, "SHLIB_PATH" on HPUX and
+ "DYLD_LIBRARY_PATH" on Mac OSX. Added configure option to package Tcl
+ as a framework on Mac OSX.
+
+ * macosx/tclMacOSXBundle.c (new): support for finding Tcl extension
+ packaged as 'bundles' in the standard Mac OSX library locations.
+
+ * unix/tclUnixInit.c: added support for findig the tcl script library
+ inside Tcl packaged as a framework on Mac OSX.
+
+ * macosx/Tcl.pbproj/jingham.pbxuser (new):
+ * macosx/Tcl.pbproj/project.pbxproj (new): project for Apple's
+ ProjectBuilder IDE.
+
+ * macosx/Makefile (new): simple makefile for building the project from
+ the command line via the ProjectBuilder tool 'pbxbuild'.
+
+ * unix/configure:
+ * generic/tclStubInit.c:
+ * generic/tclPlatDecls.h: regen
+
+2002-08-29 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * win/tclWinThrd.c (TclpFinalizeThreadData, TclWinFreeAllocCache):
+ Applied patch for [Bug 599428], provided by Miguel Sofer
+ <msofer@users.sourceforge.net>.
+
+2002-08-28 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tclEnv.c:
+ * unix/configure.in:
+ * win/tclWinPort.h: putenv() on some systems copies the buffer rather
+ than taking reference to it. This causes memory leaks and is know to
+ effect mswindows (msvcrt) and NetBSD 1.5.2 . This patch tests for this
+ behavior and turns on -DHAVE_PUTENV_THAT_COPIES=1 when approriate.
+ Thanks to David Welton for assistance. [Bug 414910]
+
+ * unix/configure: regen'd
+
+2002-08-28 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/eval.n: Added mention of list command and corrected "SEE ALSO".
+
+ * unix/configure.in: Cache handling of ac_cv_type_socklen_t was wrong.
+ [Bug 600931] reported by John Ellson. Fixed by putting the brackets
+ where they belong.
+
+2002-08-26 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclCompCmds.c: fix for [Bug 599788] (error in element name
+ causing segfault), reported by Tom Wilkason. Fixed by copying the
+ tokens instead of the source string.
+
+2002-08-26 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclThreadAlloc.c: small optimisation, reducing the new
+ allocator's overhead.
+
+2002-08-23 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclObj.c (USE_THREAD_ALLOC): fixed leak [Bug 597936]. Thanks
+ to Zoran Vasiljevic.
+
+2002-08-23 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclThreadAlloc.c (USE_THREAD_ALLOC): moving objects between
+ caches as a block, instead of one-by-one.
+
+2002-08-22 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclBasic.c:
+ * generic/tclCmdMZ.c: fix for freed memory r/w in delete traces [Bug
+ 589863], patch by Hemang Lavana.
+
+2002-08-20 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * win/Makefile.in (CFLAGS):
+ * unix/Makefile.in (MEM_DEBUG_FLAGS): Added usage of @MEM_DEBUG_FLAGS@.
+ * win/configure.in:
+ * unix/configure.in: Added usage of SC_ENABLE_MEMDEBUG.
+ * win/tcl.m4:
+ * unix/tcl.m4: Added macro SC_ENABLE_MEMDEBUG. Allows a user of
+ configure to (de)activate memory validation and debugging
+ (TCL_MEM_DEBUG). No need to modify the makefile anymore.
+
+2002-08-20 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCkalloc.c: CONSTified MemoryCmd and CheckmemCmd.
+
+ * README: Bumped version number to 8.4b3 to distinguish
+ * generic/tcl.h: HEAD from the 8.4b2 release.
+ * tools/tcl.wse.in:
+ * unix/configure.in:
+ * unix/tcl.spec:
+ * win/README.binary:
+ * win/configure.in:
+
+ * unix/configure: autoconf
+ * win/configure:
+
+ * library/http/http.tcl: Corrected installation directory of
+ * library/msgcat/msgcat.tcl: the package tcltest 2.2. Added
+ * library/opt/optparse.tcl: comments in other packages to remind
+ * library/tcltest/tcltest.tcl: that installation directories need
+ * unix/Makefile.in: updates to match increasing version
+ * win/Makefile.in: numbers. [Bug 597450]
+ * win/makefile.bc:
+ * win/makefile.vc:
+
+2002-08-19 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * unix/tclUnixTest.c (TestfilehandlerCmd): Changed readable/writable
+ to the more common readable|writable. Fixes [Bug 596034] reported by
+ Larry Virden <lvirden@users.sourceforge.net>.
+
+2002-08-16 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/fCmd.test: Added test to make sure that the cause of the
+ problem is detectable with an unpatched Tcl.
+ * doc/ObjectType.3: Added note on the root cause of this problem to
+ the documentation, since it is possible for user code to trigger this
+ sort of behaviour too.
+ * generic/tclIOUtil.c (SetFsPathFromAny): Objects should only have
+ their old representation deleted when we know that we are about to
+ install a new one. This stops a weird TclX bug under Linux with
+ certain kinds of memory debugging enabled which essentally came down
+ to a double-free of a string.
+
+2002-08-14 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclInt.h:
+ * generic/tclObj.c: (code cleanup) factored the parts in the macros
+ TclNewObj() / TclDecrRefCount() into a common part for all
+ memory allocators and two new macros TclAllocObjStorage() /
+ TclFreeObjStorage() that are specific to each allocator and fully
+ describe the differences. Removed allocator-specific code from
+ tclObj.c by using the macros.
+
+2002-08-12 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclCmdMZ.c: fixing UMR in delete traces, [Bug 589863].
+
+2002-08-08 David Gravereaux <davygrvy@pobox.com>
+
+ * tools/man2help.tcl: Fixed $argv handling bug where if -bitmap wasn't
+ specified $argc was off by one.
+
+2002-08-08 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * tests/uplevel.test: added 6.1 to test [uplevel] with shadowed
+ commands [Bug 524383]
+
+ * tests/subst.test: added 5.8-10 as further tests for [Bug 495207]
+
+2002-08-08 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/README: Noted removal of defs.tcl.
+
+2002-08-08 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/lsearch.n: corrected lsearch docs to use -inline in examples.
+
+ *** 8.4b2 TAGGED FOR RELEASE ***
+
+ * tests/fCmd.test:
+ * tests/unixFCmd.test: updated tests for new link copy behavior.
+ * generic/tclFCmd.c (CopyRenameOneFile): changed the behavior to
+ follow links to endpoints and copy that file/directory instead of just
+ copying the surface link. This means that trying to copy a link that
+ has no endpoint (danling link) is an error. [Patch 591647] (darley)
+ (CopyRenameOneFile): this is currently disabled by default until
+ further issues with such behavior (like relative links) can be
+ handled correctly.
+
+ * tests/README: slight wording improvements
+
+2002-08-07 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * docs/BoolObj.3: added description of valid string reps for a
+ boolean object. [Bug 584794]
+ * generic/tclObj.c: optimised Tcl_GetBooleanFromObj and
+ SetBooleanFromAny to avoid parsing the string rep when it can be
+ avoided. [Bugs 584650, 472576]
+
+2002-08-07 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclCompile.h:
+ * generic/tclObj.c: making tclCmdNameType static ([Bug 584567], Don
+ Porter).
+
+2002-08-07 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclObj.c (Tcl_NewObj): added conditional code for
+ USE_THREAD_ALLOC; objects allocated through Tcl_NewObj() were
+ otherwise being leaked. [Bug 587488] reported by Sven Sass.
+
+2002-08-06 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tclInt.decls:
+ * unix/tclUnixThrd.c: Added stubs and implementations for
+ non-threaded build for the tclUnixThrd.c procs TclpReaddir,
+ TclpLocaltime, TclpGmtime and TclpInetNtoa. Fixes link errors in
+ stubbed & threaded extensions that include tclUnixPort.h and use any
+ of the procs readdir, localtime, gmtime or inet_ntoa (e.g. TclX 8.4)
+ [Bug 589526]
+ * generic/tclIntPlatDecls.h:
+ * generic/tclStubInit.c: Regen.
+
+2002-08-05 Don Porter <dgp@users.sourceforge.net>
+
+ * library/tcltest/tcltest.tcl: The setup and cleanup scripts are now
+ * library/tcltest/pkgIndex.tcl: skipped when a test is skipped, fixing
+ * tests/tcltest.test: [Bug 589859]. Test for bug added, and
+ corrected tcltest package bumped to version 2.2.
+
+ * generic/tcl.decls: Restored Tcl_Concat to return (char *). Like
+ * generic/tclDecls.h: Tcl_Merge, it transfers ownership of a dynamic
+ * generic/tclUtil.c: allocated string to the caller.
+
+2002-08-04 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/CmdCmplt.3: Applied Patch 585105 to fully CONST-ify all
+ * doc/Concat.3: remaining public interfaces of Tcl. Notably,
+ * doc/CrtCommand.3: the parser no longer writes on the string it
+ * doc/CrtSlave.3: is parsing, so it is no longer necessary for
+ * doc/CrtTrace.3: Tcl_Eval() to be given a writable string. Also
+ * doc/Eval.3: the refactoring of the Tcl_*Var* routines by
+ * doc/ExprLong.3: by Miguel Sofer is included, so that the
+ * doc/LinkVar.3: "part1" argument for them no longer needs to
+ * doc/ParseCmd.3: be writable either.
+ * doc/SetVar.3:
+ * doc/TraceVar.3:
+ * doc/UpVar.3: Compatibility support has been enhanced so
+ * generic/tcl.decls: that a #define of USE_NON_CONST will remove
+ * generic/tcl.h: all possible source incompatibilities with the
+ * generic/tclBasic.c: 8.3 version of the header file(s). The new
+ * generic/tclCmdMZ.c: #define of USE_COMPAT_CONST now does what
+ * generic/tclCompCmds.c:USE_NON_CONST used to do -- disable only those
+ * generic/tclCompExpr.c:new CONST's that introduce irreconcilable
+ * generic/tclCompile.c: incompatibilities.
+ * generic/tclCompile.h:
+ * generic/tclDecls.h: Several bugs are also fixed by this patch.
+ * generic/tclEnv.c: [Bugs 584051,580433] [Patches 585105,582429]
+ * generic/tclEvent.c:
+ * generic/tclInt.decls:
+ * generic/tclInt.h:
+ * generic/tclIntDecls.h:
+ * generic/tclInterp.c:
+ * generic/tclLink.c:
+ * generic/tclObj.c:
+ * generic/tclParse.c:
+ * generic/tclParseExpr.c:
+ * generic/tclProc.c:
+ * generic/tclTest.c:
+ * generic/tclUtf.c:
+ * generic/tclUtil.c:
+ * generic/tclVar.c:
+ * mac/tclMacTest.c:
+ * tests/expr-old.test:
+ * tests/parseExpr.test:
+ * unix/tclUnixTest.c:
+ * unix/tclXtTest.c:
+ * win/tclWinTest.c:
+
+2002-08-01 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c: bugfix (reading freed memory). Testsuite
+ passed on linux/i386, compile-13.1 hung on linux/alpha.
+
+2002-08-01 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c: added a reference count for the complete
+ execution stack, instead of Tcl_Preserve/Tcl_Release.
+
+2002-08-01 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tclCkalloc.c (TclFinalizeMemorySubsystem): Don't lock the
+ ckalloc mutex before invoking the Tcl_DumpActiveMemory function since
+ it also locks the same mutex. This code is only executed when "memory
+ onexit filename" has been executed and Tcl is compiled with
+ -DTCL_MEM_DEBUG.
+
+2002-08-01 Reinhard Max <max@suse.de>
+
+ * win/tclWinPort.h: The windows headers don't provide socklen_t, so we
+ have to do it.
+
+2002-07-31 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclInt.h (USE_THREAD_ALLOC): for unshared objects,
+ TclDecrRefCount now frees the internal rep before the string rep -
+ just like the non-macro Tcl_DecrRefCount/TclFreeObj [Bug 524802]. For
+ the other allocators the fix was done on 2002-03-06.
+
+2002-07-31 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclInterp.c: signed/unsigned comparison warning fixed
+ (Vince Darley).
+
+2002-07-31 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * unix/tcl.m4 (SC_BUGGY_STRTOD): Enabled caching of test results.
+
+ * unix/tcl.m4 (SC_BUGGY_STRTOD): Solaris 2.8 still has a buggy
+ strtod() implementation; make sure we detect it.
+
+ * tests/expr.test (expr-22.*): Marked as non-portable because it seems
+ that these tests have an annoying tendency to fail in unexpected ways.
+ [Bugs 584825, 584950, 585986]
+
+2002-07-30 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * tests/io.test:
+ * generic/tclIO.c (WriteChars): Added flag to break out of loop if
+ nothing of the input is consumed at all, to prevent infinite looping
+ of called with a non-UTF-8 string. Fixes Bug 584603 (partially). Added
+ new test "io-60.1". Might need additional changes to Tcl_Main so that
+ unprintable results are printed as binary data.
+
+2002-07-29 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/Makefile.in: Use CC_SEARCH_FLAGS instead of LD_SEARCH_FLAGS
+ when linking with ${CC}.
+ * unix/configure: Regen.
+ * unix/configure.in: Don't subst CC_SEARCH_FLAGS or LD_SEARCH_FLAGS
+ since this is now done in tcl.m4.
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): Document and set CC_SEARCH_FLAGS
+ whenever LD_SEARCH_FLAGS is set. [Patch 588290]
+
+2002-07-29 Reinhard Max <max@suse.de>
+
+ * unix/tcl.m4 (SC_SERIAL_PORT): Fixed detection for cases when
+ configure's stdin is not a tty.
+
+ * unix/tclUnixPort.h:
+ * generic/tclIOSock.c: Changed size_t to socklen_t in
+ socket-related function calls.
+
+ * unix/configure.in: Added test and fallback definition
+ for socklen_t.
+
+ * unix/configure: generated.
+
+2002-07-29 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclObj.c: fixed a comment
+
+ * generic/tcl.h:
+ * generic/tclBasic.c:
+ * generic/tclInterp.c: added the new flag TCL_EVAL_INVOKE to the
+ interface of the Tcl_Eval* functions, removing the
+ TCL_EVAL_NO_TRACEBACK added yesterday: alias invocations not only
+ require no tracebacks, but also look up the command name in the global
+ scope - see new test interp-9.4
+ * tests/interp.test: added 9.3 to test for safety of aliases to hidden
+ commands, 9.4 to test for correct command lookup scope.
+
+2002-07-29 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/regc_locale.c (cclass): [[:xdigit:]] is only a defined
+ concept on western characters, so should not allow any unicode digit,
+ and hence number of ranges in [[:xdigit:]] is fixed.
+ * tests/reg.test: Added test to detect the bug.
+ * generic/regc_cvec.c (newcvec): Corrected initial size value in
+ character vector structure. [Bug 578363] Many thanks to
+ pvgoran@users.sf.net for tracking this down.
+
+2002-07-28 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tcl.h:
+ * generic/tclBasic.c: added the new flag TCL_EVAL_NO_TRACEBACK to the
+ interface of the Tcl_Eval* functions. Modified the error message for
+ too many nested evaluations.
+ * generic/tclInterp.h: changed the Alias struct to be of variable
+ length and store the prefix arguments directly (instead of a pointer
+ to a Tcl_Obj list). Made AliasObjCmd call Tcl_EvalObjv instead of
+ TclObjInvoke - thus making aliases trigger execution traces [Bug
+ 582522].
+ * tests/interp.test:
+ * tests/stack.test: adapted to the new error message.
+ * tests/trace.test: added tests for aliases firing the exec traces.
+
+2002-07-27 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/Makefile.in: Revert fix for Tcl bug 529801 since it was
+ incorrect and broke the build on other systems. Fix [Bug 587299]. Add
+ MAJOR_VERSION, MINOR_VERSION, PATCH_LEVEL, SHLIB_LD_FLAGS,
+ SHLIB_LD_LIBS, CC_SEARCH_FLAGS, LD_SEARCH_FLAGS, and LIB_FILE
+ variables to support more generic library build/install rules.
+ * unix/configure: Regen.
+ * unix/configure.in: Move AC_PROG_RANLIB into tcl.m4. Move shared
+ build test and setting of MAKE_LIB and MAKE_STUB_LIB into tcl.m4. Move
+ subst of a number of variables into tcl.m4 where they are defined.
+ * unix/tcl.m4 (SC_ENABLE_SYMBOLS, SC_CONFIG_CFLAGS): Subst vars where
+ they are defined. Add MAKE_LIB, MAKE_STUB_LIB, INSTALL_LIB, and
+ INSTALL_STUB_LIB rules to deal with the ugly details of running ranlib
+ on static libs at build and install time. Replace TCL_SHLIB_LD_EXTRAS
+ with SHLIB_LD_FLAGS and use it when building a shared library.
+ * unix/tclConfig.sh.in: Add TCL_CC_SEARCH_FLAGS.
+
+2002-07-26 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c: fixed Tcl_Obj leak in code corresponding to
+ the macro NEXT_INST_V(x, 0, 1) [Bug 587495].
+
+2002-07-26 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclVar.c (TclObjLookupVar): leak fix and improved comments.
+
+2002-07-26 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclVar.c (TclLookupVar): removed early returns that
+ prevented the parens from being restored. Also removed goto label as
+ it was not necessary.
+
+2002-07-24 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c:
+ * tests/expr-old.test: fix for erroneous error messages in [expr],
+ [Bug 587140] reported by Martin Lemburg.
+
+2002-07-25 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/tclProc.c: fix for [Tk Bug 219218] "error handling with
+ bgerror in Tk"
+
+2002-07-24 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c: restoring full TCL_COMPILE_DEBUG
+ functionality.
+
+2002-07-24 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/unixInit.test: relaxed unixInit-3.1 to accept iso8859-15 as a
+ valid C encoding. [Bug 575336]
+
+2002-07-24 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c: restoring the tcl_traceCompile functionality
+ while I repair tcl_traceExec. The core now compiles and runs also
+ under TCL_COMPILE_DEBUG, but execution in the bytecode engine can
+ still not be traced.
+
+2002-07-24 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/Makefile.in:
+ * unix/configure.in: corrected fix for [Bug 529801]: ranlib only
+ needed for static builds on Mac OS X.
+ * unix/configure: Regen.
+ * unix/tclLoadDyld.c: fixed small bugs introduced by Vince,
+ implemented library unloading correctly (needs OS X 10.2).
+
+2002-07-23 Joe English <jenglish@users.sourceforge.net>
+
+ * doc/OpenFileChnl.3: (Updates from Larry Virden)
+ * doc/open.n:
+ * doc/tclsh.1: Fix section numbers in Unix man page references.
+ * doc/lset.n: In EXAMPLES section, include command to set the initial
+ value used in subsequent examples.
+ * doc/http.n: Package version updated to 2.4.
+
+2002-07-23 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): Enable 64 bit compilation when using
+ the native compiler on a 64 bit version of IRIX. [Bug 219220]
+
+2002-07-23 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/Makefile.in: Combine ranlib tests and avoid printing unless
+ ranlib is actually run.
+
+2002-07-23 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/tcl.m4 (SC_PATH_X): Set XINCLUDES to "" instead of "# no
+ special path needed" or "# no include files found" when x headers
+ cannot be located.
+
+2002-07-22 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclIOUtil.c: made tclNativeFilesystem static (since 07-19
+ changes removed its usage elsewhere), and added comments about its
+ usage.
+ * generic/tclLoad.c:
+ * generic/tcl.h:
+ * generic/tcl.decls:
+ * doc/FileSystem.3: converted last load-related ClientData parameter
+ to Tcl_LoadHandle opaque structure, removing a couple of casts in the
+ process.
+
+ * generic/tclInt.h: removed tclNativeFilesystem declaration since it
+ is now static again.
+
+2002-07-22 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/expr.test (expr-22.*): Added tests to help detect the
+ corrected handling.
+ * generic/tclExecute.c (IllegalExprOperandType): Improved error
+ message generated when attempting to manipulate Inf and NaN values.
+ * generic/tclParseExpr.c (GetLexeme): Allowed parser to recognise
+ 'Inf' as a floating-point number. [Bug 218000]
+
+2002-07-21 Don Porter <dgp@users.sourceforge.net>
+
+ * tclIOUtil.c: Silence compiler warning. [Bug 584408].
+
+2002-07-19 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclIOUtil.c: fix to GetFilesystemRecord
+ * win/tclWinFile.c:
+ * unix/tclUnixFile.c: fix to subtle problem with links shown up by
+ latest tclkit builds.
+
+2002-07-19 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure:
+ * unix/configure.in:
+ * win/configure:
+ * win/configure.in: Add AC_PREREQ(2.13) in an attempt to make it more
+ clear that the configure scripts must be generated with autoconf
+ version 2.13. [Bug 583573]
+
+2002-07-19 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * unix/Makefile.in: fix to build on MacOS X [Bug 529801], bug report
+ and fix from jcw.
+
+2002-07-19 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * win/tclWinSerial.c (no_timeout): Made this variable static.
+
+ * generic/tclExecute.c, generic/tclCompile.c, generic/tclBasic.c:
+ * generic/tclCompile.h (builtinFuncTable, instructionTable): Added
+ prefix to these symbols because they are visible outside the Tcl
+ library.
+
+ * generic/tclCompExpr.c (operatorTable):
+ * unix/tclUnixTime.c (tmKey):
+ * generic/tclIOUtil.c (theFilesystemEpoch, filesystemWantToModify,
+ filesystemIteratorsInProgress, filesystemOkToModify): Made these
+ variables static.
+
+ * unix/tclUnixFile.c: Renamed nativeFilesystem to
+ * win/tclWinFile.c: tclNativeFilesystem and declared
+ * generic/tclIOUtil.c: it properly in tclInt.h
+ * generic/tclInt.h:
+
+ * generic/tclUtf.c (totalBytes): Made this array static and const.
+
+ * generic/tclParse.c (typeTable): Made this array static and const.
+ (Tcl_ParseBraces): Simplified error handling case so that scans are
+ only performed when needed, and flags are simpler too.
+
+ * license.terms: Added AS to list of copyright holders; it's only
+ fair for the current gatekeepers to be listed here!
+
+ * tests/cmdMZ.test: Renamed constraint for clarity. [Bug 583427]
+ Added tests for the [time] command, which was previously only
+ indirectly tested!
+
+2002-07-18 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclInt.h:
+ * generic/tcl.h:
+ * */*Load*.c: added comments on changes of 07/17 and replaced
+ clientData with Tcl_LoadHandle in all locations.
+
+ * generic/tclFCmd.c:
+ * tests/fileSystem.test: fixed a 'knownBug' with 'file attributes ""'
+ * tests/winFCmd.test:
+ * tests/winPipe.test:
+ * tests/fCmd.test:
+ * tessts/winFile.test: added 'pcOnly' constraint to some tests to make
+ for more useful 'tests skipped' log from running all tests on
+ non-Windows platforms.
+
+2002-07-17 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclBasic.c (CallCommandTraces): delete traces now receive
+ the FQ old name of the command. [Bug 582532] (Don Porter)
+
+2002-07-18 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/ioUtil.test: added constraints to 1.4,2.4 so they don't run
+ outside of tcltest. [Bugs 583276, 583277]
+
+2002-07-17 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclVar.c (DupParsedVarName): nasty bug fixed, reported by
+ Vince Darley.
+
+2002-07-17 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclVar.c (TclPtrIncrVar): missing CONST in declarations,
+ inconsistent with tclInt.h. Thanks to Vince Darley for reporting, boo
+ to gcc for not complaining.
+
+2002-07-17 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclInt.h:
+ * generic/tclIOUtil.c:
+ * generic/tclLoadNone.c:
+ * unix/tclLoadAout.c:
+ * unix/tclLoadDl.c:
+ * unix/tclLoadDld.c:
+ * unix/tclLoadDyld.c:
+ * unix/tclLoadNext.c:
+ * unix/tclLoadOSF.c:
+ * unix/tclLoadShl.c:
+ * mac/tclMacLoad.c:
+ * win/tclWinLoad.c: modified to move more functionality to the generic
+ code and avoid duplication. Partial replacement of internal uses of
+ clientData with opaque Tcl_LoadHandle. A little further work still
+ needed, but significant changes are done.
+
+2002-07-17 D. Richard Hipp <drh@hwaci.com>
+
+ * library/msgcat/msgcat.tcl: fix a comment that was causing problems
+ for programs (ex: mktclapp) that embed the initialization scripts in
+ strings.
+
+2002-07-17 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclInt.decls:
+ * generic/tclIntDecls.h:
+ * generic/tclStubInit.c:
+ * generic/tclVar.c: removing the now redundant functions to access
+ indexed variables: Tcl(Get|Set|Incr)IndexedScalar() and
+ Tcl(Get|Set|Incr)ElementOfIndexedArray().
+
+2002-07-17 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclExecute.c (TclExecuteByteCode): Minor fixes to make this
+ file compile with SunPro CC...
+
+2002-07-17 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c: modified to do variable lookup explicitly, and
+ then either inlining the variable access or else calling the new
+ TclPtr(Set|Get|Incr)Var functions in tclVar.c
+ * generic/tclInt.h: declare some functions previously local to
+ tclVar.c for usage by TEBC.
+ * generic/tclVar.c: removed local declarations; moved all special
+ accessor functions for indexed variables to the end of the file -
+ they are unused and ready for removal, but left there for the time
+ being as they are in the internal stubs table.
+
+ ** WARNING FOR BYTECODE MAINTAINERS **
+ TCL_COMPILE_DEBUG is currently not functional; will be fixed ASAP.
+
+2002-07-16 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/Makefile.in:
+ * win/Makefile.in: Add a more descriptive warning in the event `make
+ genstubs` needs to be rerun.
+
+2002-07-16 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/Makefile.in: Use dltest.marker file to keep track of when the
+ dltest package is up to date. This fixes [Bug 575768] since tcltest is
+ no longer linked every time.
+ * unix/dltest/Makefile.in: Create ../dltest.marker after a successful
+ `make all` run in dltest.
+
+2002-07-16 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/configure.in: Remove useless subst of TCL_BIN_DIR.
+
+2002-07-15 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclVar.c: inaccurate comment fixed
+
+2002-07-15 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclBasic.c (Tcl_AddObjErrorInfo):
+ * generic/tclExecute.c (TclUpdateReturnInfo):
+ * generic/tclInt.h:
+ * generic/tclProc.c:
+ Added two Tcl_Obj to the ExecEnv structure to hold the fully qualified
+ names "::errorInfo" and "::errorCode" to cache the addresses of the
+ corresponding variables. The two most frequent setters of these
+ variables now profit from the new variable name caching.
+
+2002-07-15 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclVar.c: refactorisation to reuse already looked-up Var
+ pointers; definition of three new Tcl_Obj types to cache variable name
+ parsing and lookup for later reuse; modification of internal functions
+ to profit from the caching.
+
+ * generic/tclInt.decls:
+ * generic/tclInt.h:
+ * generic/tclIntDecls.h:
+ * generic/tclNamesp.c: adding CONST qualifiers to variable names
+ passed to Tcl_FindNamespaceVar and to variable resolvers; adding CONST
+ qualifier to the 'msg' argument to TclLookupVar. Needed to avoid code
+ duplication in the new tclVar.c code.
+
+ * tests/set-old.test:
+ * tests/var.test: slight modification of error messages due to the
+ modifications in the tclVar.c code.
+
+2002-07-15 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/unixInit.test: Improved constraints to protect /tmp. [Bug
+ 581403]
+
+2002-07-15 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/winFCmd.test: renamed 'win2000' and 'notWin2000' to more
+ appropriate constraint names.
+ * win/tclWinFile.c: updated comments to reflect 07-11 changes.
+ * win/tclWinFCmd.c: made ConvertFileNameFormat static again, since no
+ longer used in tclWinFile.c
+ * mac/tclMacFile.c: completed TclpObjLink implementation which was
+ previously lacking.
+ * generic/tclIOUtil.c: comment cleanup and code speedup.
+
+2002-07-14 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclInt.h: Removed declarations that duplicated entries
+ in the (internal) stub table.
+
+ * library/tcltest/tcltest.tcl: Corrected errors in handling of
+ configuration options -constraints and -limitconstraints.
+
+ * README: Bumped HEAD to version 8.4b2 so we can
+ * generic/tcl.h: distinguish it from the 8.4b1 release.
+ * tools/tcl.wse.in:
+ * unix/configure*:
+ * unix/tcl.spec:
+ * win/README.binary:
+ * win/configure*:
+
+2002-07-11 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * doc/file.n:
+ * win/tclWinFile.c: on Win 95/98/ME the long form of the path is used
+ as a normalized form. This is required because short forms are not a
+ robust representation. The file normalization function has been sped
+ up, but more performance gains might be possible, if speed is still an
+ issue on these platforms.
+
+2002-07-11 Don Porter <dgp@users.sourceforge.net>
+
+ * library/tcltest/tcltest.tcl: Corrected reaction to existing but
+ false ::tcl_interactive.
+
+ * doc/Hash.3: Overlooked CONST documentation update.
+
+2002-07-11 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclCkalloc.c: ckalloc() and friends take the block size as
+ an unsigned, so we should use %ud when reporting it in fprintf() and
+ panic().
+
+2002-07-11 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclCompile.c: now setting local vars undefined at compile
+ time, instead of waiting until the proc is initialized.
+ * generic/tclProc.c: use macro TclSetVarUndefined instead of directly
+ setting the flag.
+
+2002-07-11 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/cmdAH.test: [file attr -perm] is Unix-only, so add [catch]
+ when not inside a suitably-protected test.
+
+2002-07-10 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/unixFCmd.test, tests/fileName.test:
+ * tests/fCmd.test: Removed [exec] of Unix utilities that have
+ equivalents in standard Tcl. [Bug 579268] Also simplified some of
+ unixFCmd.test while I was at it.
+
+2002-07-10 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/tcltest.test: Greatly reduced the number of [exec]s, using
+ slave interps instead.
+ * library/tcltest/tcltest.tcl: Fixed bug uncovered in the conversion
+ where a message was written to stdout instead of [outputChannel].
+
+ * tests/basic.test: Cleaned up, constrained, and reduced the
+ * tests/compile.test: amount of [exec] usage in the test suite.
+ * tests/encoding.test:
+ * tests/env.test:
+ * tests/event.test:
+ * tests/exec.test:
+ * tests/io.test:
+ * tests/ioCmd.test:
+ * tests/regexp.test:
+ * tests/regexpComp.test:
+ * tests/socket.test:
+ * tests/tcltest.test:
+ * tests/unixInit.test:
+ * tests/winDde.test:
+ * tests/winPipe.test:
+
+2002-07-10 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/cmdAH.test: Removed [exec] of Unix utilities. [Bug 579211]
+
+ * tests/expr.test: Added tests to make sure that this works.
+ * generic/tclExecute.c (ExprCallMathFunc): Functions should also be
+ able to return wide-ints. [Bug 579284]
+
+2002-07-08 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * tests/socket.test: Fixed [Bug 578164]. The original reason for the
+ was a DNS outage while running the testsuite. Changed [info hostname]
+ to 127.0.0.1 to bypass DNS, knowing that we operate on the local host.
+
+2002-07-08 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/tcltest.n: Fixed incompatibility in [viewFile].
+ * library/tcltest/tcltest.tcl: Corrected docs. Bumped to 2.2.1.
+ * library/tcltest/pkgIndex.tcl: [Bug 578163]
+
+2002-07-08 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/cmdAH.test:
+ * tests/fCmd.test:
+ * tests/fileName.test: tests which rely on 'file link' need a
+ constraint so they don't run on older Windows OS. [Bug 578158]
+ * generic/tclIOUtil.c:
+ * generic/tcl.h:
+ * generic/tclInt.h:
+ * generic/tclTest.c:
+ * mac/tclMacChan.c:
+ * unix/tclUnixChan.c:
+ * win/tclWinChan.c:
+ * doc/FileSystem.3: cleaned up internal handling of
+ Tcl_FSOpenFileChannel to remove duplicate code, and make writing
+ external vfs's clearer and easier. No functionality change. Also
+ clarify that objects with refCount zero should not be passed in to the
+ Tcl_FS API, and prevent segfaults from occuring on such user errors.
+ [Bug 578617]
+
+2002-07-06 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/pkgMkIndex.test: Constrained tests of [load] package indexing
+ to those platforms where the testing shared libraries have been built.
+ [Bug 578166]
+
+2002-07-05 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: added recent changes
+
+2002-07-05 Reinhard Max <max@suse.de>
+
+ * generic/tclClock.c (FormatClock): Convert the format string to UTF8
+ before calling TclpStrftime, so that non-ASCII characters don't get
+ mangled when the result string is being converted back.
+ * tests/clock.test: Added a test for that.
+
+2002-07-05 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * unix/Makefile.in (ro-test,ddd,GDB,DDD): Created new targets to
+ allow running the test suite with a read-only current directory,
+ running under ddd instead of gdb, and factored out some executable
+ names for broken sites (like mine) where gdb and ddd are installed
+ with non-standard names...
+
+ * tests/httpold.test: Altered test names to httpold-* to avoid clashes
+ with http.test, and stopped tests from failing when the current
+ directory is not writable...
+
+ * tests/event.test: Stop these tests from failing when the
+ * tests/ioUtil.test: current directory is not writable...
+ * tests/regexp.test:
+ * tests/regexpComp.test:
+ * tests/source.test:
+ * tests/unixFile.test:
+ * tests/unixNotfy.test:
+
+ * tests/unixFCmd.test: Trying to make these test-files not
+ * tests/macFCmd.test: bomb out with an error when the
+ * tests/http.test: current directory is not writable...
+ * tests/fileName.test:
+ * tests/env.test:
+
+2002-07-05 Jeff Hobbs <jeffh@ActiveState.com>
+
+ *** 8.4b1 TAGGED FOR RELEASE ***
+
+2002-07-04 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/cmdMZ.test (cmdMZ-1.4):
+ * tests/cmdAH.test: More fixing of writable-current-dir assumption.
+ [Bug 575824]
+
+2002-07-04 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * tests/basic.test: Same issue as below; fixed [Bug 575817]
+
+2002-07-04 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * tests/socket.test:
+ * tests/winPipe.test:
+ * tests/pid.test: Fixed [Bug 575848]. See below for a description the
+ general problem.
+
+ * All the bugs below are instances of the same problem: The testsuite
+ assumes [pwd] = [temporaryDirectory] and writable.
+
+ * tests/iogt.test: Fixed [Bug 575860].
+ * tests/io.test: Fixed [Bug 575862].
+ * tests/exec.test:
+ * tests/ioCmd.test: Fixed [Bug 575836].
+
+2002-07-03 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/pkg1/direct1.tcl: removed
+ * tests/pkg1/pkgIndex.tcl: removed
+ * tests/pkgMkIndex.test: Imported auxilliary files from tests/pkg1
+ into the test file pkgMkIndex.test itself. Formatting fixes.
+
+ * unix/Makefile.in: removed tests/pkg/* from `make dist`
+
+ * tests/pkg/circ1.tcl: removed
+ * tests/pkg/circ2.tcl: removed
+ * tests/pkg/circ3.tcl: removed
+ * tests/pkg/global.tcl: removed
+ * tests/pkg/import.tcl: removed
+ * tests/pkg/pkg1.tcl: removed
+ * tests/pkg/pkg2_a.tcl: removed
+ * tests/pkg/pkg2_b.tcl: removed
+ * tests/pkg/pkg3.tcl: removed
+ * tests/pkg/pkg4.tcl: removed
+ * tests/pkg/pkg5.tcl: removed
+ * tests/pkg/pkga.tcl: removed
+ * tests/pkg/samename.tcl: removed
+ * tests/pkg/simple.tcl: removed
+ * tests/pkg/spacename.tcl: removed
+ * tests/pkg/std.tcl: removed
+ * tests/pkgMkIndex.test: Fixed [Bug 575857] where this test file
+ expected to be able to write to [file join [testsDirectory] pkg]. Part
+ of the fix was to import several auxilliary files into the test file
+ itself.
+
+ * tests/main.test: Cheap fix for [Bugs 575851, 575858]. Avoid
+ * tests/tcltest.test: non-writable . by [cd [temporaryDirectory]].
+
+ * library/auto.tcl: Fix [tcl_findLibrary] to be sure it sets $varName
+ only if a successful library script is found. [Bug 577033]
+
+2002-07-03 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclCompCmds.c (TclCompileCatchCmd): return
+ TCL_OUT_LINE_COMPILE instead of TCL_ERROR: let the failure happen at
+ runtime so that it can be caught [Bug 577015].
+
+2002-07-02 Joe English <jenglish@users.sourceforge.net>
+
+ * doc/tcltest.n: Markup fixes, spellcheck.
+
+2002-07-02 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/tcltest.n: more refinements of the documentation.
+
+ * library/tcltest/tcltest.tcl: Added trace to be sure the stdio
+ constraint is updated whenever the [interpreter] changes.
+
+ * doc/tcltest.n: Reverted [makeFile] and [viewFile] to
+ * library/tcltest/tcltest.tcl: their former behavior, and documented
+ * tests/cmdAH.test: it. Corrected misspelling of hook
+ * tests/event.test: procedure. Restored tests.
+ * tests/http.test:
+ * tests/io.test:
+
+ * library/tcltest/tcltest.tcl: Simplified logic of [GetMatchingFiles]
+ and [GetMatchingDirectories], removing special case processing.
+
+ * doc/tcltest.n: More documentation updates. Reference sections are
+ complete. Only examples need adding.
+
+2002-07-02 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/fCmd.test:
+ * generic/tclCmdAH.c: clearer error msgs for 'file link', as per the
+ man page.
+
+2002-07-01 Joe English <jenglish@users.sourceforge.net>
+
+ * doc/Access.3:
+ * doc/AddErrInfo.3:
+ * doc/Alloc.3:
+ * doc/Backslash.3:
+ * doc/CrtChannel.3:
+ * doc/CrtSlave.3:
+ * doc/Encoding.3:
+ * doc/Eval.3:
+ * doc/FileSystem.3:
+ * doc/Notifier.3:
+ * doc/OpenFileChnl.3:
+ * doc/ParseCmd.3:
+ * doc/RegExp.3:
+ * doc/Tcl_Main.3:
+ * doc/Thread.3:
+ * doc/TraceCmd.3:
+ * doc/Utf.3:
+ * doc/WrongNumArgs.3:
+ * doc/binary.n:
+ * doc/clock.n:
+ * doc/expr.n:
+ * doc/fconfigure.n:
+ * doc/glob.n:
+ * doc/http.n:
+ * doc/interp.n:
+ * doc/lsearch.n:
+ * doc/lset.n:
+ * doc/msgcat.n:
+ * doc/packagens.n:
+ * doc/pkgMkIndex.n:
+ * doc/registry.n:
+ * doc/resource.n:
+ * doc/safe.n:
+ * doc/scan.n:
+ * doc/tclvars.n: Spell-check, fixed typos (Updates from Larry Virden).
+
+2002-07-01 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): Made Solaris use gcc for linking
+ when building with gcc to resolve problems with undefined symbols
+ being present when tcl library used with non-gcc linker at later
+ stage. Symbols were compiler-generated, so it is the compiler's
+ business to define them. [Bug 541181]
+
+2002-07-01 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/tcltest.n: more work in progress updating tcltest docs.
+
+ * library/tcltest/tcltest.tcl: Change [configure -match] to stop
+ treating an empty list as a list of the single pattern "*". Changed
+ the default value to [list *] so default operation remains the same.
+
+ * tests/pkg/samename.tcl: restored. needed by pkgMkIndex.test.
+
+ * library/tcltest/tcltest.tcl: restored writeability testing of
+ -tmpdir, augmented by a special exception for the deafault value.
+
+2002-07-01 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/concat.n: Documented the *real* behaviour of [concat]!
+
+2002-06-30 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/tcltest.n: more work in progress updating tcltest docs.
+
+ * tests/README: Updated the instructions on running and
+ * tests/cmdMZ.test: adding to the test suite. Also updated
+ * tests/encoding.test: several tests, mostly to correctly create
+ * tests/fCmd.test: and destroy any temporary files in the
+ * tests/info.test: [temporaryDirectory] of tcltest.
+ * tests/interp.test:
+
+ * library/tcltest/tcltest.tcl: Stopped checking for writeability of
+ -tmpdir value because no default directory can be guaranteed to be
+ writeable.
+
+ * tests/autoMkindex.tcl: removed.
+ * tests/pkg/samename.tcl: removed.
+ * tests/pkg/magicchar.tcl: removed.
+ * tests/pkg/magicchar2.tcl: removed.
+ * tests/autoMkindex.test: Updated auto_mkIndex tests to use [makeFile]
+ and [removeFile] so tests are done in [temporaryDirecotry] where write
+ access is guaranteed.
+
+ * library/tcltest/tcltest.tcl: Fixed [makeFile] and [viewFile] to
+ * tests/cmdAH.test: accurately reflect a file's contents.
+ * tests/event.test: Updated tests that depended on buggy
+ * tests/http.test: behavior. Also added warning messages
+ * tests/io.test: to "-debug 1" operations to debug test
+ * tests/iogt.test: calls to (make|remove)(File|Directory)
+
+ * unix/mkLinks: `make mklinks` on 6-27 commits.
+
+2002-06-28 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclCompile.h: modified the macro TclEmitPush to not call its
+ first argument repeatedly or pass it to other macros, [Bug 575194]
+ reported by Peter Spjuth.
+
+2002-06-28 Don Porter <dgp@users.sourceforge.net>
+
+ * docs/tcltest.n: Doc revisions in progress.
+ * library/tcltest/tcltest.tcl: Corrected -testdir default value. Was
+ not reliable, and disagreed with docs! Thanks to Hemang Lavana. [Bug
+ 575150]
+
+2002-06-28 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * unix/tclUnixThrd.c: Renamed the Tcl_Platform* #defines to TclOS*
+ * unix/tclUnixPipe.c: because they are only used internally. Also
+ * unix/tclUnixFile.c: stopped double-#def of TclOSlstat [Bug 566099,
+ * unix/tclUnixFCmd.c: post-rename]
+ * unix/tclUnixChan.c:
+ * unix/tclUnixPort.h:
+
+ * doc/string.n: Improved documentation for [string last] along lines
+ described in [Bug 574799] so it indicates that the supplied index
+ marks the end of the search space.
+
+2002-06-27 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/dde.n: Work in progress updating the documentation
+ * doc/http.n: of the packages that come bundled with
+ * doc/msgcat.n: the Tcl source distribution, notably tcltest.
+ * doc/registry.n:
+ * doc/tcltest.n:
+
+ * library/tcltest/tcltest.tcl: Made sure that the TCLTEST_OPTIONS
+ environment variablle configures tcltest at package load time.
+
+2002-06-26 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/fileSystem.test:
+ * generic/tclIOUtil.c: fix to handling of empty paths "" which are not
+ claimed by any filesystem [Bug 573758]. Ensure good error messages
+ are given in all cases.
+ * tests/cmdAH.test:
+ * unix/tclUnixFCmd.c: fix to bug reported as part of [Patch 566669].
+ Thanks to Taguchi, Takeshi for the report.
+
+2002-06-26 Reinhard Max <max@suse.de>
+
+ * unix/tclUnixTime.c: Make [clock format] respect locale settings.
+ * tests/clock.test: [Bug 565880]. ***POTENTIAL INCOMPATIBILITY***
+
+2002-06-26 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * doc/CrtInterp.3:
+ * doc/StringObj.3: clarifications by Don Porter, [Bug 493995] and [Bug
+ 500930].
+
+2002-06-24 Don Porter <dgp@users.sourceforge.net>
+
+ * library/tcltest/tcltest.tcl: Corrected suppression of -verbose skip
+ * tests/tcltest.test: and start by [test -output]. Also
+ corrected test suite errors exposed by corrected code. [Bug 564656]
+
+2002-06-25 Reinhard Max <max@suse.de>
+
+ * unix/tcl.m4: New macro SC_CONFIG_MANPAGES.
+ * unix/configure.in: Added support for symlinks and compression when
+ * unix/Makefile.in: installing the manpages. [Patch 518052]
+ * unix/mkLinks.tcl: Default is still hardlinks and no compression.
+
+ * unix/mkLinks: generated
+ * unix/configure:
+
+ * unix/README: Added documentation for the new features.
+
+ * unix/tcl.m4 (SC_PATH_TCLCONFIG): Replaced ${exec_prefix}/lib by
+ ${libdir}.
+
+2002-06-25 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclUtil.c (TclGetIntForIndex): Fix of critical [Bug 533364]
+ generated when the index is bad and the result is a shared object. The
+ T_ASTO(T_GOR, ...) idiom likely exists elsewhere though. Also removed
+ some cruft that just complicated things to no advantage.
+ (SetEndOffsetFromAny): Same fix, though this wasn't on the path
+ excited by the bug.
+
+2002-06-24 Don Porter <dgp@users.sourceforge.net>
+
+ * library/tcltest/tcltest.tcl: Implementation of TIP 101. Adds abd
+ * tests/parseOld.test: exports a [configure] command from
+ * tests/tcltest.test: tcltest.
+
+2002-06-22 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: updated changes file for 8.4b1 release.
+
+ * library/tcltest/tcltest.tcl: Corrections to tcltest and the Tcl
+ * tests/basic.test: test suite so that a test with options
+ * tests/cmdInfo.test: -constraints knownBug
+ * tests/compile.test: -limitConstraints 1 only tests the
+ * tests/encoding.test: knownBug tests. Mostly involves
+ * tests/env.test: replacing direct access to the
+ * tests/event.test: testConstraints array with calls to
+ * tests/exec.test: the testConstraint command (which
+ * tests/execute.test: requires tcltest version 2)
+ * tests/fCmd.test:
+ * tests/format.test:
+ * tests/http.test:
+ * tests/httpold.test:
+ * tests/ioUtil.test:
+ * tests/link.test:
+ * tests/load.test:
+ * tests/namespace.test:
+ * tests/pkgMkIndex.test:
+ * tests/reg.test:
+ * tests/result.test:
+ * tests/scan.test:
+ * tests/stack.test:
+
+2002-06-22 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tools/tcl.wse.in (Disk Label), unix/tcl.spec (version):
+ * win/README.binary, README, win/configure.in, unix/configure.in:
+ * generic/tcl.h (TCL_RELEASE_*, TCL_PATCH_LEVEL): Bump to beta1.
+
+2002-06-21 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/tclCompExpr.c:
+ * generic/tclParseExpr.c: LogSyntaxError() should reset the
+ interpreter result [Bug 550142 "Tcl_ExprObj -> abort"]
+
+2002-06-21 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/Makefile.in: Updated all package install directories
+ * win/Makefile.in: to match current Major.minor versions
+ * win/makefile.bc: of the packages. Added tcltest package
+ * win/makefile.vc: to installation on Windows.
+
+ * library/init.tcl: Corrected comments and namespace style issues.
+ Thanks to Bruce Stephens. [Bug 572025]
+
+2002-06-21 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/cmdAH.test: Added TIP#99 implementation of 'file
+ * tests/fCmd.test: link'. Supports creation of symbolic and
+ * tests/fileName.test: hard links in the native filesystems and
+ * tests/fileSystem.test: in vfs's, when the individual filesystem
+ * generic/tclTest.c: supports the concept.
+ * generic/tclCmdAH.c:
+ * generic/tclIOUtil.c:
+ * generic/tcl.h:
+ * generic/tcl.decls:
+ * doc/FileSystem.3:
+ * doc/file.n:
+ * mac/tclMacFile.c:
+ * unix/tclUnixFile.c:
+ * win/tclWinFile.c: Also enhanced speed of 'file normalize' on
+ Windows.
+
+2002-06-20 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclBasic.c (TclEvalObjvInternal): fix for [Bug 571385] in
+ the implementation of TIP#62 (command tracing). Vince Darley, Hemang
+ Lavana & Don Porter: thanks.
+
+2002-06-20 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c (TclCompEvalObj): clarified and simplified the
+ logic for compilation/recompilation.
+
+2002-06-19 Joe English <jenglish@users.sourceforge.net>
+
+ * doc/file.n: Fixed indentation. No substantive changes.
+
+2002-06-19 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclCmdMZ.c (Tcl_RegexpObjCmd): get the resultPtr again as
+ the Tcl_ObjSetVar2 may cause the result to change. [Patch 558324]
+ (watson)
+
+2002-06-19 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c (TEBC): removing unused "for(;;)" loop;
+ improved comments; re-indentation.
+
+2002-06-18 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c (TEBC):
+ - elimination of duplicated code in the non-immediate INST_INCR
+ instructions.
+ - elimination of 103 (!) TclDecrRefCount macros. The different
+ instructions now jump back to a common "DecrRefCount zone" at the
+ top of the loop. The macro "ADJUST_PC" was replaced by two macros
+ "NEXT_INST_F" and "NEXT_INST_V" that take three params
+ (pcAdjustment, # of stack objects to discard, resultObjPtr handling
+ flag). The only instructions that retain a TclDecrRefCount are
+ INST_POP (for speed), the common code for the non-immediate
+ INST_INCR, INST_FOREACH_STEP and the two INST_LSET.
+
+ The object size of tclExecute.o was reduced by approx 20% since the
+ start of the consolidation drive, while making room for some peep-hole
+ optimisation at runtime.
+
+2002-06-18 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c (TEBC, INST_DONE): small bug in the panic code
+ for tcl-stack corruption.
+
+2002-06-17 David Gravereaux <davygrvy@pobox.com>
+
+ Trims to support the removal of RESOURCE_INCLUDED from rc scripts from
+ [FRQ 565088].
+
+ * generic/tcl.h: moved the #ifndef RC_INVOKED start block up in the
+ file. rc scripts don't need to know thread mutexes.
+
+ * win/tcl.rc:
+ * win/tclsh.rc: removed the #define RESOURCE_INCLUDED to let the
+ built-in -DRC_INVOKED to the work.
+
+2002-06-17 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/CrtTrace.3: Added TIP#62 implementation of command
+ * doc/trace.n: execution tracing [FRQ 462580] (lavana).
+ * generic/tcl.h: This includes enter/leave tracing as well
+ * generic/tclBasic.c: as inter-procedure stepping.
+ * generic/tclCmdMZ.c:
+ * generic/tclCompile.c:
+ * generic/tclExecute.c:
+ * generic/tclInt.decls:
+ * generic/tclInt.h:
+ * generic/tclIntDecls.h:
+ * generic/tclStubInit.c:
+ * generic/tclVar.c:
+ * tests/trace.test:
+
+2002-06-17 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * win/tclWinPipe.c (BuildCommandLine): Fixed [Bug 554068] ([exec] on
+ windows did not treat { in filenames well.). Bug reported by Vince
+ Darley <vincentdarley@users.sourceforge.net>, patch provided by Vince
+ too.
+
+2002-06-17 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/tcl.h: #ifdef logic for K&R C backwards compatibility
+ changed to assume modern C by default. See [FRQ 565088] for full
+ details.
+
+2002-06-17 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/msgcat.n: Corrected en_UK references to en_GB. UK is not a
+ country designation recognized in ISO 3166.
+
+ * library/msgcat/msgcat.tcl: More Windows Registry locale codes from
+ Bruno Haible.
+
+ * doc/msgcat.n:
+ * library/msgcat/msgcat.tcl:
+ * library/msgcat/pkgIndex.tcl:
+ * tests/msgcat.test: Revised locale initialization to interpret
+ environment variable locale values according to XPG4, and to recognize
+ the LC_ALL and LC_MESSAGES values over that of LANG. Also added many
+ Windows Registry locale values to those recognized by msgcat. Revised
+ tests and docs. Bumped to version 1.3. Thanks to Bruno Haible for the
+ report and assistance crafting the solution. [Bug 525522, 525525]
+
+2002-06-16 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclCompile.c (TclCompileTokens): a better algorithm for the
+ previous bug fix.
+
+2002-06-16 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclCompile.c (TclCompileTokens):
+ * tests/compile.test: [Bug 569438] in the processing of dollar
+ variables; report by Georgios Petasis.
+
+2002-06-16 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c: bug in the consolidation of the INCR_..._STK
+ instructions; the bug could not be exercised as the (faulty)
+ instruction INST_INCR_ARRAY_STK was never compiled-in (related to [Bug
+ 569438]).
+
+2002-06-14 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c (TclExecuteByteCode): runtime peep-hole
+ optimisation of variables (INST_STORE, INST_INCR) and commands
+ (INST_INVOKE); faster check for the existence of a catch.
+ (TclExecuteByteCode): runtime peep-hole optimisation of comparisons.
+ (TclExecuteByteCode): runtime peep-hole optimisation of INST_FOREACH -
+ relies on peculiarities of the code produced by the bytecode compiler.
+
+2002-06-14 David Gravereaux <davygrvy@pobox.com>
+
+ * win/rules.vc: The test for compiler optimizations was in error.
+ Thanks goes to Roy Terry <royterry@earthlink.net> for his assistance
+ with this.
+
+2002-06-14 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/trace.n, tests/trace.test:
+ * generic/tclCmdMZ.c (Tcl_TraceObjCmd,TclTraceCommandObjCmd)
+ (TclTraceVariableObjCmd): Changed references to "trace list" to
+ "trace info" as mandated by TIP#102.
+
+2002-06-13 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c (TclExecuteByteCode): consolidated code for the
+ conditional branch instructions.
+
+2002-06-13 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c (TclExecuteByteCode): fixed the previous patch;
+ wouldn't compile with TCL_COMPILE_DEBUG set.
+
+2002-06-13 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c (TclExecuteByteCode): consolidated the handling
+ of exception returns to INST_INVOKE and INST_EVAL, as well as most of
+ the code for INST_CONTINUE and INST_BREAK, in the new jump target
+ "processExceptionReturn".
+
+2002-06-13 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c (TclExecuteByteCode): consolidated variable
+ handling opcodes, replaced redundant code with some 'goto'. All
+ store/append/lappend opcodes on the same data type now share the main
+ code; same with incr opcodes.
+ * generic/tclVar.c: added the bit TCL_TRACE_READS to the possible
+ flags to Tcl_SetVar2Ex - it causes read traces to be fired prior to
+ setting the variable. This is used in the core for [lappend].
+
+ ***NOTE*** the usage of TCL_TRACE_READS in Tcl_(Obj)?GetVar.* is not
+ documented; there, it causes the call to create the variable if it
+ does not exist. The new usage in Tcl_(Obj)?SetVar.* remains
+ undocumented too ...
+
+2002-06-13 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/fCmd.test:
+ * tests/winFile.test:
+ * tests/fileSystem.test:
+ * generic/tclTest.c:
+ * generic/tclCmdAH.c:
+ * generic/tclIOUtil.c:
+ * doc/FileSystem.3:
+ * mac/tclMacFile.c:
+ * unix/tclUnixFile.c:
+ * win/tclWinFile.c: fixed up further so both compiles and actually
+ works with VC++ 5 or 6.
+ * win/tclWinInt.h:
+ * win/tclWin32Dll.c: cleaned up code and vfs tests and added tests for
+ the internal changes of 2002-06-12, to see whether WinTcl on NTFS can
+ coexist peacefully with links in the filesystem. Added new test
+ command 'testfilelink' to enable the newer code to be tested.
+ * tests/fCmd.test: (made certain tests of 'testfilelink' not run on
+ unix).
+
+2002-06-12 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * tclBasic.c (Tcl_DeleteTrace): fixed [Bug 568123] (thanks to Hemang
+ Lavana)
+
+2002-06-12 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tclWinFile.c: corrected the symbolic link handling code to allow
+ it to compile. Added real definition of REPARSE_DATA_BUFFER (found in
+ winnt.h). Most of the added definitions appear to have correct,
+ cross-Win-version equivalents in winnt.h and should be removed, but
+ just making things "work" for now.
+
+2002-06-12 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclIOUtil.c:
+ * generic/tcl.decls:
+ * generic/tclDecls.h: made code for Tcl_FSNewNativePath agree with man
+ pages.
+
+ * doc/FileSystem.3: clarified the circumstances under which certain
+ functions are called in the presence of symlinks.
+
+ * win/tclWinFile.c:
+ * win/tclWinPort.h:
+ * win/tclWinInt.h:
+ * win/tclWinFCmd.c: Fix for Windows to allow 'file lstat', 'file
+ type', 'glob -type l', 'file copy', 'file delete', 'file normalize',
+ and all VFS code to work correctly in the presence of symlinks
+ (previously Tcl's behaviour was not very well defined). This also
+ fixes possible serious problems in all versions of WinTcl where 'file
+ delete' on a NTFS symlink could delete the original, not the symlink.
+ Note: symlinks cannot yet be created in pure Tcl.
+
+2002-06-11 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclBasic.c:
+ * generic/tclCompCmds.c:
+ * generic/tclInt.h: reverted the new compilation functions; replaced
+ by a more general approach described below.
+
+ * generic/tclCompCmds.c:
+ * generic/tclCompile.c: made *all* compiled variable access attempts
+ create an indexed variable - even get or incr without previous set.
+ This allows indexed access to local variables that are created and set
+ at runtime, for example by [global], [upvar], [variable], [regexp],
+ [regsub].
+
+2002-06-11 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * doc/global.n:
+ * doc/info.n:
+ * test/info.test:
+ * generic/tclCmdIL.c: fix for [Bug 567386], [info locals] was
+ reporting some linked variables.
+
+ * generic/tclBasic.c:
+ * generic/tclCompCmds.c:
+ * generic/tclInt.h: added compile functions for [global], [variable]
+ and [upvar]. They just declare the new local variables, the commands
+ themselves are not compiled-in. This gives a notably faster read
+ access to these linked variables.
+
+2002-06-11 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c: optimised algorithm for exception range
+ lookup; part of [Patch 453709].
+
+2002-06-10 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * unix/tclUnixFCmd.c: fixed [Bug 566669]
+ * generic/tclIOUtil.c: improved and sped up handling of native paths
+ (duplication and conversion to normalized paths), particularly on
+ Windows.
+ * modified part of above commit, due to problems on Linux. Will
+ re-examine bug report and evaluate more closely.
+
+2002-06-07 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/tcltest.test: More corrections to test suite so that tests of
+ failing [test]s don't show up themselves as failing tests.
+
+2002-06-07 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclExecute.c: Tidied up headers in relation to float.h to
+ cut the cruft and ensure DBL_MAX is defined since doubles seem to be
+ the same size everywhere; if the assumption isn't true, the variant
+ platforms had better have run configure...
+
+ * unix/tclUnixPort.h (EOVERFLOW): Added code to define it if it
+ wasn't previously defined. Also some other general tidying and adding
+ of comments. [Bugs 563122, 564595]
+ * compat/tclErrno.h: Added definition for EOVERFLOW copied from
+ Solaris headers; I've been unable to find any uses of EFTYPE, which
+ was the error code previously occupying the slot, in Tcl, or any
+ definition of it in the Solaris headers.
+
+2002-06-06 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/dltest/Makefile.in: Remove hard coded CFLAGS=-g and add
+ CFLAGS_DEBUG, CFLAGS_OPTIMIZE, and CFLAGS_DEFAULT varaibles. [Bug
+ 565488]
+
+2002-06-06 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/tcltest.test: Corrections to test suite so that tests of
+ failing [test]s don't show up themselves as failing tests.
+
+ * tests/io.test: Fixed up namespace variable resolution issues
+ revealed by running test suite with "-singleproc 1".
+
+ * doc/tcltest.n:
+ * library/tcltest/tcltest.tcl:
+ * tests/tcltest.test: Several updates to tcltest.
+ 1) changed to lazy initialization of test constraints
+ 2) deprecated [initConstraintsHook]
+ 3) repaired badly broken [limitConstraints].
+ 4) deprecated [threadReap] and [mainThread]
+ [Patch 512214, Bug 558742, Bug 461000, Bug 534903]
+
+2002-06-06 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tclUnixThrd.c (TclpReaddir, TclpLocaltime, TclpGmtime): added
+ mutex wrapped calls to readdir, localtime & gmtime in case their
+ thread-safe *_r counterparts are not available.
+ * unix/tcl.m4: added configure check for readdir_r
+ * unix/tcl.m4 (Darwin): set TCL_DEFAULT_ENCODING to utf-8 on MacOSX
+ (where posix file apis expect utf-8, not iso8859-1).
+ * unix/configure: regen
+ * unix/Makefile.in: set DYLD_LIBRARY_PATH in parallel to
+ LD_LIBRARY_PATH for MacOSX dynamic linker.
+ * generic/tclEnv.c (TclSetEnv): fix env var setting on MacOSX (adapted
+ from [Patch 524352] by jkbonfield).
+
+2002-06-05 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/Tcl_Main.3: Documented $tcl_rcFileName and added more
+ clarifications about the intended use of Tcl_Main(). [Bug 505651]
+
+2002-06-05 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tclFileName.c (TclGlob): mac specific fix to recent changes
+ in 'glob -tails' handling.
+ * mac/tclMacPort.h:
+ * mac/tclMacChan.c: fixed TIP#91 bustage.
+ * mac/tclMacResource.c (Tcl_MacConvertTextResource): added utf
+ conversion of text resource contents.
+ * tests/macFCmd.test (macFCmd-1.2): allow CWIE creator.
+
+2002-06-04 Don Porter <dgp@users.sourceforge.net>
+
+ * library/tcltest/tcltest.tcl:
+ * tests/init.test:
+ * tests/tcltest.test: Added more TIP 85 tests from Arjen Markus.
+ Converted tcltest.test to use a private namespace. Fixed bugs in
+ [tcltest::Eval] revealed by calling [tcltest::test] from a non-global
+ namespace, and namespace errors in init.test.
+
+2002-06-04 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/README: Update msys+mingw URL.
+
+2002-06-03 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/tcltest.n:
+ * library/tcltest/tcltest.tcl:
+ * library/tcltest/pkgIndex.tcl:
+ * tests/tcltest.test: Implementation of TIP 85. Allows tcltest users
+ to add new legal values of the -match option to [test], associating
+ each with a Tcl command that does the matching of expected results
+ with actual results of tests. Thanks to Arjen Markus. => tcltest 2.1
+ [Patch 521362]
+
+2002-06-03 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * doc/namespace.n: added description of [namepace forget] behaviour
+ for unqualified patterns. [Bug 559268]
+
+2002-06-03 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c: reverting an accidental modification in the
+ last commit.
+
+2002-06-03 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * doc/Tcl.n: clarify the empty variable name issue ([Bug 549285]
+ reported by Tom Krehbiel, patch by Don Porter).
+
+2002-05-31 Don Porter <dgp@users.sourceforge.net>
+
+ * library/package.tcl: Fixed leak of slave interp in [pkg_mkIndex].
+ Thanks to Helmut for report. [Bug 550534]
+
+ * tests/io.test:
+ * tests/main.test: Use the "stdio" constraint to control whether an
+ [open "|[interpreter]"] is attempted.
+
+ * generic/tclExecute.c (TclMathInProgress,TclExecuteByteCode
+ (ExprCallMathFunc):
+ * generic/tclInt.h (TclMathInProgress):
+ * unix/Makefile.in (tclMtherr.*):
+ * unix/configure.in (NEED_MATHERR):
+ * unix/tclAppInit.c (matherr):
+ * unix/tclMtherr.c (removed file):
+ * win/tclWinMtherr.c (_matherr): Removed internal routine
+ TclMathInProgress and Unix implementation of matherr(). These are now
+ obsolete, dealing with very old versions of the C math library.
+ Windows version is retained in case Borland compilers require it, but
+ it is inactive. Thanks to Joe English. [Bug 474335, Patch 555635]
+
+ * unix/configure: regen
+
+2002-05-30 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclCompExpr.c:
+ * generic/tclCompile.c:
+ * generic/tclCompile.h: removed exprIsJustVarRef and
+ exprIsComparison from the ExprInfo and CompileEnv structs. These
+ were set, but not used since dec 1999 [Bug 562383].
+
+2002-05-30 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclFileName.c (TclGlob): fix to longstanding 'knownBug' in
+ fileName tests 15.2-15.4, and fix to a new Tcl 8.4 bug in certain uses
+ of 'glob -tails'.
+ * tests/fileName.test: removed 'knownBug' flag from some tests, added
+ some new tests for above bugs.
+
+2002-05-29 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/configure: regen'ed
+ * unix/configure.in: replaced bigendian check with autoconf standard
+ AC_C_BIG_ENDIAN, which defined WORDS_BIGENDIAN on bigendian systems.
+ * generic/tclUtf.c (Tcl_UniCharNcmp):
+ * generic/tclInt.h (TclUniCharNcmp): use WORDS_BIGENDIAN instead of
+ TCL_OPTIMIZE_UNICODE_COMPARE to enable memcmp alternative.
+
+ * generic/tclExecute.c (TclExecuteByteCode INST_STR_CMP):
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd): changed the case for choosing
+ the Tcl_UniCharNcmp compare to when both objs are of StringType, as
+ benchmarks show that is the optimal check (both bigendian and
+ littleendian systems).
+
+2002-05-29 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclMain.c: Removed "dummy" reference to Tcl_LinkVar. It is
+ no longer needed since Tcl_Main() now actually calls Tcl_LinkVar().
+ Thanks to Joe English for pointing that out.
+
+2002-05-29 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclExecute.c (TclExecuteByteCode):
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd): Use the macro version.
+ * generic/tclInt.h (TclUniCharNcmp): Optimised still further with a
+ macro for use in sensitive places like tclExecute.c
+
+ * generic/tclUtf.c (Tcl_UniCharNcmp): Use new flag to figure out when
+ we can use an optimal comparison scheme, and default to the old scheme
+ in other cases which is at least safe.
+ * unix/configure.in (TCL_OPTIMIZE_UNICODE_COMPARE): New optional flag
+ that indicates when we can use memcmp() to compare Unicode strings
+ (i.e. when the high-byte of a Tcl_UniChar precedes the low-byte.)
+
+2002-05-29 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclInt.decls:
+ * generic/tclIntDecls.h:
+ * generic/tclStubInit.c:
+ * generic/tclUtf.c: added TclpUtfNcmp2 private command that
+ mirrors Tcl_UtfNcmp, but takes n in bytes, not utf-8 chars. This
+ provides a faster alternative for comparing utf strings internally.
+ (Tcl_UniCharNcmp, Tcl_UniCharNcasecmp): removed the explicit end of
+ string check as it wasn't correct for the function (by doc and logic).
+
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd): reworked the string equal
+ comparison code to use TclpUtfNcmp2 as well as short-circuit for
+ equal objects or unequal length strings in the equal case.
+ Removed the use of goto and streamlined the other parts.
+
+ * generic/tclExecute.c (TclExecuteByteCode): added check for object
+ equality in the comparison instructions. Added short-circuit for !=
+ length strings in INST_EQ, INST_NEQ and INST_STR_CMP. Reworked
+ INST_STR_CMP to use TclpUtfNcmp2 where appropriate, and only use
+ Tcl_UniCharNcmp when at least one of the objects is a Unicode obj with
+ no utf bytes.
+
+ * generic/tclCompCmds.c (TclCompileStringCmd): removed error creation
+ in code that no longer throws an error.
+
+ * tests/string.test:
+ * tests/stringComp.test: added more string comparison checks.
+
+ * tests/clock.test: better qualified 9.1 constraint check for %s.
+
+2002-05-28 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclThreadAlloc.c (TclpRealloc, TclpFree): protect
+ against the case when NULL is based.
+
+ * tests/clock.test: added clock-9.1
+ * compat/strftime.c:
+ * generic/tclClock.c:
+ * generic/tclInt.decls:
+ * generic/tclIntDecls.h:
+ * unix/tclUnixTime.c: fix for Windows msvcrt mem leak caused by using
+ an env(TZ) setting trick for in clock format -gmt 1. This also makes
+ %s seem to work correctly with -gmt 1 as well as making it a lot
+ faster by avoid the env(TZ) hack. TclpStrftime now takes useGMT as an
+ arg. [Bug 559376]
+
+2002-05-28 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclIOUtil.c: fixes to Tcl_FSLoadFile when called on a file
+ inside a vfs. This should avoid leaving temporary files sitting
+ around on exit. [Bug 545579]
+
+2002-05-27 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * win/tclWinError.c: Added comment on conversion of
+ ERROR_NEGATIVE_SEEK because that is a mapping that really belongs,
+ and not a catch-all case.
+ * win/tclWinPort.h (EOVERFLOW): Should be either EFBIG or EINVAL
+ * generic/tclPosixStr.c (Tcl_ErrnoId, Tcl_ErrnoMsg): EOVERFLOW can
+ potentially be a synonym for EINVAL.
+
+2002-05-24 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ === Changes due to TIP#91 ===
+
+ * win/tclWinPort.h: Added declaration of EOVERFLOW.
+ * doc/CrtChannel.3: Added documentation of wideSeekProc.
+ * generic/tclIOGT.c (TransformSeekProc, TransformWideSeekProc):
+ Adapted to use the new channel mechanism.
+ * unix/tclUnixChan.c (FileSeekProc, FileWideSeekProc): Renamed
+ FileSeekProc to FileWideSeekProc and created new FileSeekProc which
+ has the old-style interface and which errors out with EOVERFLOW when
+ the returned file position can't fit into the return type (int for
+ historical reasons).
+ * win/tclWinChan.c (FileSeekProc, FileWideSeekProc): Renamed
+ FileSeekProc to FileWideSeekProc and created new FileSeekProc which
+ has the old-style interface and which errors out with EOVERFLOW when
+ the returned file position can't fit into the return type (int for
+ historical reasons).
+ * mac/tclMacChan.c (FileSeek): Reverted to old interface; Macs lack
+ large-file support because I can't see how to add it.
+ * generic/tclIO.c (Tcl_Seek, Tcl_Tell): Given these functions
+ knowledge of the new arrangement of channel types.
+ (Tcl_ChannelVersion): Added recognition of new version code.
+ (HaveVersion): New function to do version checking.
+ (Tcl_ChannelBlockModeProc, Tcl_ChannelFlushProc)
+ (Tcl_ChannelHandlerProc): Made these functions use HaveVersion for
+ ease of future maintainability.
+ (Tcl_ChannelBlockModeProc): Obvious lookup function.
+ * generic/tcl.h (Tcl_ChannelType): New wideSeekProc field, and
+ seekProc type restored to old interpretation.
+ (TCL_CHANNEL_VERSION_3): New channel version.
+
+2002-05-24 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * tests/winPipe.test: Applied patch for [Bug 549617]. Patch and bug
+ report by Kevin Kenny <kennykb@users.sourceforge.net>.
+
+ * win/tclWinSock.c (TcpWatchProc): Fixed [Bug 557878]. We are not
+ allowed to mess with the watch mask if the socket is a server socket.
+ I believe that the original reporter is George Peter Staplin.
+
+2002-05-21 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/configure.in: Invoke SC_ENABLE_SHARED before calling
+ SC_CONFIG_CFLAGS so that the SHARED_BUILD variable can be checked
+ inside SC_CONFIG_CFLAGS.
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): Pass -non_shared instead of -shared
+ to ld when configured with --disable-shared under OSF. [Bug 540390]
+
+2002-05-20 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tclInt.h: added prototype for TclpFilesystemPathType().
+ * mac/tclMacChan.c: use MSL provided creator type if available instead
+ of the default 'MPW '.
+
+2002-05-16 Joe English <jenglish@users.sf.net>
+
+ * doc/CrtObjCmd.3: Added Tcl_GetCommandFromObj, Tcl_GetCommandFullName
+ [Bugs 547987, 414921]
+
+2002-05-14 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * unix/tclUnixChan.c (TtyOutputProc): #if/#endif-ed this function out
+ to stop compiler warnings. Also much general tidying of comments in
+ this file and removal of whitespace from blank lines.
+
+2002-05-13 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * unix/tclUnixChan.c (SETBREAK): Solaris thinks ioctl() takes a signed
+ second argument, and Linux thinks ioctl() takes an unsigned second
+ argument. So need a longer definition of this macro to get neither to
+ spew warnings...
+
+2002-05-13 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclEvent.c:
+ * generic/tclIOUtil.c:
+ * generic/tclInt.h: clean up all memory allocated by the filesystem,
+ via introduction of 'TclFinalizeFilesystem'.
+ Move TclFinalizeLoad into TclFinalizeFilesystem so we can be sure it
+ is called at just the right time.
+ Fix bad comment also. [Bug 555078 and 'fs' part of 543549]
+ * win/tclWinChan.c: fix comment referring to wrong function.
+
+2002-05-10 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/load.test:
+ * tests/safe.test:
+ * tests/tcltest.test: Corrected some list-quoting issues and other
+ matters that cause tests to fail when the patch includes special
+ characters. Report from Vince Darley. [Bug 554068]
+
+2002-05-08 David Gravereaux <davygrvy@pobox.com>
+
+ * doc/file.n:
+ * tools/man2tcl.c:
+ * tools/man2help2.tcl: Thanks to Peter Spjuth
+ <peter.spjuth@space.se>, again. My prior fix for single-quote macro
+ mis-understanding was wrong. Reverted to reimpliment the 'macro2' proc
+ which handles single-quote macros and restored file.n text arrangement
+ to avoid single-quotes on the first line. Sorry for all the confusion.
+
+2002-05-08 David Gravereaux <davygrvy@pobox.com>
+
+ * tools/man2tcl.c:
+ * tools/man2help2.tcl: Proper source of macro error misunderstanding
+ single-quote as the leading macro command found and repaired.
+
+ * doc/file.n: Reverted to prior state before I messed with it.
+
+2002-05-08 Don Porter <dgp@users.sourceforge.net>
+
+ * library/tcltest/tcltest.tcl: Corrected [uplevel] quoting when
+ [source]-ing test script in subdirectories.
+ * tests/fileName.test:
+ * tests/load.test:
+ * tests/main.test:
+ * tests/tcltest.test:
+ * tests/unixInit.test: Fixes to test suite when there's a space in the
+ working path. Thanks to Kevin Kenny.
+
+2002-05-07 David Gravereaux <davygrvy@pobox.com>
+
+ -- Changes from Peter Spjuth <peter.spjuth@space.se>
+ * tools/man2tcl.c: Increased line buffer size and a bail-out if that
+ should ever be over-run.
+ * tools/man2help.tcl: Include Courier New font in rtf header.
+ * tools/man2help2.tcl: Improved handling of CS/CE fields. Use Courier
+ New for code samples and indent better.
+
+ * doc/file.n:
+ * doc/TraceCmd.3: winhelp conversion tools where understanding
+ a ' as the first character on a line to be an unknown macro.
+ Not knowing how to repair tools/man2tcl.c, I decided to rearrange
+ the text in the docs instead.
+
+2002-05-07 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclFileName.c: fix to similar segfault when using 'glob
+ -types nonsense -dir dirname -join * *'. [Bug 553320]
+
+ * doc/FileSystem.3: further documentation on vfs.
+ * tests/cmdAH.test:
+ * tests/fileSystem.test:
+ * tests/pkgMkindex.test: Fix to testsuite bugs when running out of
+ directory whose name contains '{' or '['.
+
+2002-05-07 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * tests/basic.test: Fix for [Bug 549607]
+ * tests/encoding.test: Fix for [Bug 549610]
+ These are testsuite bugs that caused failures when the filename
+ contained spaces. Report & fix by Kevin Kenny.
+
+2002-05-02 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclFileName.c: fix to freeing a bad object (i.e. segfault)
+ when using 'glob -types nonsense -dir dirname'.
+ * generic/tclWinFile.c: fix to [Bug 551306], also wrapped some long
+ lines.
+ * tests/fileName.test: added several tests for the above bugs.
+ * doc/FileSystem.3: clarified documentation on refCount requirements
+ of the object returned by the path type function.
+ * generic/tclIOUtil.c:
+ * win/tclWinFile.c:
+ * unix/tclUnixFile.c:
+ * mac/tclMacFile.c: moved TclpFilesystemPathType to the platform-
+ specific directories, so we can add missing platform-specific
+ implementations. On Windows, 'file system' now returns useful results
+ like "native NTFS", "native FAT" for that system. Unix and MacOS still
+ only return "native".
+ * doc/file.n: clarified documentation.
+ * tests/winFile.test: test for 'file system' returning correct values.
+ * tests/fileSystem.test: test for 'file system' returning correct
+ values. Clean up after failed previous test run.
+
+2002-04-26 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/configure:
+ * unix/tcl.m4: change HP-11 SHLIB_LD_LIBS from "" to ${LIBS} so that
+ the .sl knows its dependent libs.
+
+2002-04-26 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/obj.test (obj-11.[56]): Test conversion to boolean more
+ thoroughly.
+ * generic/tclObj.c (SetBooleanFromAny): Was not calling an integer
+ parsing function on native 64-bit platforms! [Bug 548686]
+
+2002-04-24 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclInt.h: corrected TclRememberJoinableThread decl to use
+ VOID instead of void.
+ * generic/tclThreadJoin.c: noted that this code isn't needed on Unix.
+
+2002-04-23 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/exec.n:
+ * doc/tclvars.n: doc updates [Patch 509426] (gravereaux)
+
+2002-04-24 Daniel Steffen <das@users.sourceforge.net>
+
+ * mac/tclMacResource.r: added check of TCLTK_NO_LIBRARY_TEXT_RESOURCES
+ #define to allow disabling the inclusion of the tcl library code in
+ the resource fork of Tcl executables and shared libraries.
+
+2002-04-23 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/TraceCmd.3: New file that documents Tcl_CommandTraceInfo,
+ Tcl_TraceCommand and Tcl_UntraceCommand [Bug 414927]
+
+2002-04-22 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclAlloc.c:
+ * generic/tclInt.h:
+ * generic/tclThreadAlloc.c (new):
+ * unix/Makefile.in:
+ * unix/tclUnixThrd.c:
+ * win/Makefile.in:
+ * win/tclWinInt.h:
+ * win/tclWinThrd.c: added new threaded allocator contributed by AOL
+ that significantly reduces lock contention when multiple threads are
+ in use. Only Windows and Unix implementations are ready, and the
+ Windows one may need work. It is only used by default on Unix for now,
+ and requires that USE_THREAD_ALLOC be defined (--enable-threads on
+ Unix will define this).
+
+ * generic/tclIOUtil.c (Tcl_FSRegister, Tcl_FSUnregister): corrected
+ calling of Tcl_ConditionWait to ensure that there would be a condition
+ to wait upon.
+
+ * generic/tclCmdAH.c (Tcl_FileObjCmd): added cast in FILE_SIZE.
+
+ * win/tclWinFCmd.c (DoDeleteFile): check return of setattr API calls
+ in file deletion for correct Win32 API handling.
+
+ * win/Makefile.in: correct dependencies for shell, gdb, runtest
+ targets.
+
+ * doc/clock.n:
+ * compat/strftime.c (_fmt): change strftime to correctly handle
+ localized %c, %x and %X on Windows. Added some notes about how the
+ other values could be further localized.
+
+2002-04-19 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclMain.c (Tcl_Main): Free the memory allocated for the
+ startup script path. [Bug 543549]
+
+ * library/msgcat/msgcat.tcl: [mcmax] wasn't using the caller's
+ namespace when determining the max translated length. Also made
+ revisions for better use of namespace variables and more efficient
+ [uplevel]s.
+
+ * doc/msgcat.n:
+ * library/msgcat/msgcat.tcl:
+ * library/msgcat/pkgIndex.tcl: Added [mcload] to the export list of
+ msgcat; bumped to 1.2.3. [Bug 544727]
+
+2002-04-20 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tclInt.decls:
+ * generic/tclIntPlatDecls.h:
+ * generic/tclStubInit.c:
+ * mac/tclMacFCmd.c:
+ * mac/tclMacFile.c:
+ * mac/tclMacUtil.c: Modified TclpObjNormalizePath to be alias file
+ aware, and replaced various calls to FSpLocationFrom*Path by calls to
+ new alias file aware versions FSpLLocationFrom*Path. The alias file
+ aware routines don't resolve the last component of a path if it is an
+ alias. This allows [file copy/delete] etc. to act correctly on alias
+ files. (c.f. discussion in [Bug 511666])
+
+2002-04-19 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/lindex.test (lindex-3.7):
+ * generic/tclUtil.c (TclGetIntForIndex): Stopped indexes from hitting
+ wide ints. [Bug 526717]
+
+2002-04-18 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclNamesp.c:
+ * tests/info.test: [Bug 545325] info level didn't report namespace
+ eval, bug report by Richard Suchenwirth.
+
+2002-04-18 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/subst.n: Clarified documentation on handling unusual return
+ codes during substitution, and on variable substitutions implied by
+ command substitution, and vice versa. [Bug 536838]
+
+2002-04-18 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclCmdIL.c (InfoBodyCmd):
+ * tests/info.test (info-2.6): Proc bodies without string reps would
+ report as empty. [Bug 545644]
+
+ * generic/tclCmdMZ.c (Tcl_SubstObj): More clarification for comment on
+ behaviour when substitutions are not well-formed, prompted by [Bug
+ 536831]; alas, removing the ill-defined behaviour is a lot of work.
+
+2002-04-18 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c:
+ * tests/expr-old.test: fix for [Bug 542588] (Phil Ehrens), where "too
+ large integers" were reported as "floating-point value" in [expr]
+ error messages.
+
+2002-04-17 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclEncoding.c (EscapeFromUtfProc):
+ * generic/tclIO.c (WriteChars, Tcl_Close): corrected the handling of
+ outputting end escapes for escape-based encodings.
+ [Bug 526524] (yamamoto)
+
+2002-04-17 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/tcltest.n: Removed [saveState] and [restoreState] from tcltest
+ 2 documentation, effectively deprecating them. [Bug 495660]
+ * library/tcltest/tcltest.tcl: Made separate export for commands kept
+ only for tcltest 1 compatibility.
+
+ * tests/iogt.test: Revised to run tests in a namespace, rather than
+ use the useless and buggy [saveState] and [restoreState] commands of
+ tcltest. Updated to use tcltest 2 as well. [Patch 544911]
+
+2002-04-16 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/io.test: Revised to run tests in a namespace, rather than use
+ the useless and buggy [saveState] and [restoreState] commands of
+ tcltest. Updated to use tcltest 2 as well. [Patch 544546]
+
+2002-04-15 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclProc.c:
+ * tests/proc-old.test: Improved stack trace for TCL_BREAK and
+ TCL_CONTINUE returns from procs. Patch by Don Porter [Bug 536955].
+
+ * generic/tclExecute.c:
+ * tests/compile.test: made bytecodes check for a catch before
+ returning; the compiled [return] is otherwise non-catchable. [Bug
+ 542142] reported by Andreas Kupries.
+
+2002-04-15 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/socket.test: Increased timeout values so that tests have
+ time to successfully complete even on slow/busy machines. [Bug 523470]
+
+ * doc/tcltest.n:
+ * library/tcltest/tcltest.tcl:
+ * tests/tcltest.test: Revised [tcltest::test] to return errors when
+ called with invalid syntax and to accept exactly two arguments as
+ documented. Improved error messages. [Bug 497446, Patch 513983]
+ ***POTENTIAL INCOMPATIBILITY***: Incompatible with previous tcltest
+ 2.* releases, found only in alpha releases of Tcl 8.4.
+
+2002-04-11 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclNotify.c (TclFinalizeNotifier): remove remaining
+ unserviced events on finalization.
+
+ * win/tcl.m4: Enabled COFF as well as CV style debug info with
+ --enable-symbols to allow Dr. Watson users to see function info. More
+ info on debugging levels can be obtained at:
+ http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp
+
+ * tests/ioCmd.test: fixed iocmd-8.15 to have mac and unixPc variants.
+
+ * generic/tclParse.c (Tcl_ParseVar): conditionally incr obj refcount
+ to prevent possible mem leak.
+
+2002-04-08 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tcl.h: no <sys/types.h> on mac.
+ * mac/tclMacFile.c: minor fixes to Vince's changes from 03-24.
+ * mac/tclMacOSA.c:
+ * mac/tclMacResource.c: added missing Tcl_UtfToExternalDString
+ conversions of resource file names.
+ * mac/tclMacSock.c (TcpGetOptionProc): fixed bug introduced by Andreas
+ on 02-25; changed strcmp's to strncmp's so that option comparison
+ behaves like on other platforms.
+ * mac/tcltkMacBuildSupport.sea.hqx (CW Pro6 changes): added support to
+ allow Tk to hookup C library stderr/stdout to TkConsole.
+ * tests/basic.test:
+ * tests/cmdAH.test:
+ * tests/encoding.test:
+ * tests/fileSystem.test:
+ * tests/ioCmd.test: fixed tests failing on mac: check for existence of
+ [exec], changed some result strings.
+
+2002-04-06 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tclUnixFCmd.c (Realpath): added a little extra code to
+ initialize a realpath arg when compiling in PURIFY mode in order to
+ prevent spurious purify warnings. We should really create our own
+ realpath implementation, but this will at least quiet purify for now.
+
+2002-04-05 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCmdMZ.c (Tcl_SubstObj):
+ * tests/subst.test: Corrected [subst] so that return codes TCL_BREAK
+ and TCL_CONTINUE returned by variable substitution have the same
+ effect as when those codes are returned by command substitution. [Bug
+ 536879]
+
+2002-04-03 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/tcltest/tcltest.tcl: added getMatchingFiles back (alias to
+ GetMatchingFiles), which was a public function in tcltest 1.0.
+
+2002-04-01 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclEnv.c:
+ * generic/tclIOUtil.c: invalidate filesystem cache when the user
+ changes env(HOME). Fixes [Bug 535621]. Also cleaned up some of the
+ documentation.
+ * tests/fileSystem.test: added test for bug just fixed.
+
+2002-04-01 Kevin Kenny <kennykb@acm.org>
+
+ * win/tclWinTime.c (Tcl_GetTime): made the checks of clock frequency
+ more permissive to cope with the fact that Win98SE is observed to
+ return 1.19318 in place of 1.193182 for the performance counter
+ frequency.
+
+2002-03-29 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclCmdMZ.c (Tcl_TraceObjCmd, TraceVarProc)
+ (TraceCommandProc, TclTraceCommandObjCmd): corrected potential
+ double-free of traces on variables by flagging in Trace*Proc that it
+ will free the var in case the eval wants to delete the var trace as
+ well. [Bug 536937] Also converted Tcl_UntraceVar -> Tcl_UntraceVar2
+ and Tcl_Eval to Tcl_EvalEx in Trace*Proc for slight efficiency
+ improvement.
+
+2002-03-29 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/AllowExc.3:
+ * generic/tclBasic.c (Tcl_EvalObjv,Tcl_EvalEx,Tcl_EvalObjEx):
+ * generic/tclCompile.h (TclCompEvalObj):
+ * generic/tclExecute.c (TclCompEvalObj,TclExecuteByteCode):
+ * tests/basic.test: Corrected problems with Tcl_AllowExceptions having
+ influence over the wrong scope of Tcl_*Eval* calls. Patch from Miguel
+ Sofer. Report from Jean-Claude Wippler. [Bug 219181]
+
+2002-03-28 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclVar.c: Refactored CallTraces to collect repeated handling
+ of its returned value into CallTraces itself.
+
+2002-03-28 David Gravereaux <davygrvy@pobox.com>
+
+ * tools/feather.bmp:
+ * tools/man2help.tcl:
+ * tools/man2help2.tcl:
+ * win/makefile.vc: More winhelp target fixups. Added a feather bitmap
+ to the non-scrollable area and changed the color to be yellow from a
+ plain white. The colors can be whatever we want them to be, but
+ thought I would start with something bold. [Bug 527941]
+
+ * doc/SetVar.3:
+ * doc/TraceVar.3:
+ * doc/UpVar.3: .AP macro syntax repair.
+
+2002-03-27 David Gravereaux <davygrvy@pobox.com>
+
+ * tools/man2help.tcl:
+ * win/makefile.vc: winhelp target now copies all needed files from
+ tools/ to a workarea under $(OUT_DIR) and builds it from there. No
+ build cruft is left in tools/ anymore. All paths used in man2help.tcl
+ are now relative to where the script is. [Bug 527941]
+
+2002-03-27 David Gravereaux <davygrvy@pobox.com>
+
+ * win/.cvsignore:
+ * win/buildall.vc.bat:
+ * win/coffbase.txt:
+ * win/makefile.vc:
+ * win/nmakehlp.c (new):
+ * win/rules.vc: First draft fix for [Bug 527941]. More changes need
+ to done to the makehelp target to get to stop leaving build files in
+ the tools/ directory. This does not address the syntax errors in the
+ man files. Having the contents of tcl.hpj(.in) inside makefile.vc
+ allows for version numbers to be replaced with macros.
+
+ The new nmakehlp.c is built by rules.vc in preprocessing and removes
+ the need to use tricky shell syntax that wasn't compatible on Win9x
+ systems. Clean targets made Win9x complient. This is a first draft
+ repair for [Bug 533862].
+
+2002-03-28 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclBasic.c (Tcl_EvalEx): passing the correct commandSize to
+ TclEvalObjvInternal. [Bug 219362], fix by David Knoll.
+
+2002-03-28 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclBasic.c (Tcl_EvalEx):
+ * tests/basic.test: avoid exceptional returns at level 0. [Bug 219181]
+
+2002-03-27 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/tcltest.n ([mainThread]):
+ * library/tcltest/tcltest.tcl:
+ * tests/tcltest.test: Major code cleanup to deal with whitespace,
+ coding conventions, and namespace issues, with several minor bugs
+ fixed in the process.
+
+ * tests/main.test: Added missing [after cancel]s.
+
+2002-03-25 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/main.test: Removed workarounds for Bug 495977.
+
+ * library/tcltest/tcltest.tcl: Keep the value of $::auto_path
+ unchanged, so that the tcltest package can test code that depends on
+ auto-loading. If a testing application needs $::auto_path pruned, it
+ should do that itself. [Bug 495726]
+ Improve the processing of the -constraints option to [test] so that
+ constraint lists can have arbitrary whitespace, and non-lists don't
+ blow things up. [Bug 495977]
+ Corrected faulty variable initialization. [Bug 534845]
+
+2002-03-25 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * doc/CrtTrace.3: small doc correction
+ * generic/tclBasic.c (Tcl_DeleteTrace): Allow NULL callback on trace
+ deletions. [Bug 534728] (Hemang Lavana)
+
+2002-03-24 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclBasic.c (Tcl_EvalObjv): replaced obscure, incorrect code
+ as described in [Bug 533907] (Don Porter).
+
+2002-03-24 Don Porter <dgp@users.sourceforge.net>
+
+ * library/tcltest/tcltest.tcl: Use [interpreter] to set/query the
+ executable currently running the tcltest package. [Bug 454050]
+
+ * library/tcltest/tcltest.tcl: Allow non-proc commands to be used as
+ the customization hooks. [Bug 495662]
+
+2002-03-24 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclFilename.c:
+ * generic/tclFCmd.c:
+ * generic/tclTest.c:
+ * generic/tcl.h:
+ * generic/tclIOUtil.c:
+ * win/tclWinFile.c:
+ * win/tclWinFCmd.c:
+ * win/tclWinPipe.c:
+ * unix/tclUnixFile.c:
+ * unix/tclUnixFCmd.c:
+ * mac/tclMacFile.c:
+ * doc/FileSystem.3:
+ * doc/file.n:
+ * tests/cmdAH.test:
+ * tests/fileName.test:
+ * tests/fileSystem.test: (new file)
+ * tests/winFCmd.test: fix [Bug 511666] and [Bug 511658], and improved
+ documentation of some aspects of the filesystem, particularly
+ 'Tcl_FSMatchInDirectory' which now might match a single file/directory
+ only, and 'file normalize' which wasn't very clear before. Removed
+ inconsistency betweens docs and the Tcl_Filesystem structure. Also
+ fixed [Bug 523217] and corrected file normalization on Unix so that
+ it expands symbolic links. Added some new tests of the filesystem
+ code (in the new file 'fileSystem.test'), and some extra tests for
+ correct handling of symbolic links. Fix to [Bug 530960] which shows up
+ on Win98. Made comparison with ".com" case insensitive in tclWinPipe.c
+
+ ***POTENTIAL INCOMPATIBILITY***: But only between alpha releases
+ (users of the new Tcl_Filesystem lookup table in Tcl 8.4a4 need to
+ handle the new way in which Tcl may call Tcl_FSMatchInDirectory, and
+ 'file normalize' on unix now behaves correctly). Only known impact is
+ with the 'tclvfs' extension.
+
+2002-03-22 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * tests/basic.test (basic-46.1): adding test for [Bug 533758], fixed
+ earlier today.
+
+2002-03-22 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tclWinInt.h: moved undef of TCL_STORAGE_CLASS. [Bug 478579]
+
+2002-03-22 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclBasic.c (Tcl_EvalObjEx):
+ * generic/tclExecute.c (TclCompEvalObj): fixed the errorInfo for
+ return codes other than (TCL_OK, TCL_ERROR) to runLevel 0.[Bug 533758]
+ Removed the static RecordTracebackInfo(), as its functionality is
+ easily replicated by Tcl_LogCommandInfo. Bug and redundancy noted by
+ Don Porter.
+
+2002-03-21 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/expr.n: Improved documentation for ceil and floor. [Bug 530535]
+
+2002-03-20 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/SetVar.3:
+ * doc/TraceVar.3:
+ * doc/UpVar.3:
+ * generic/tcl.h (Tcl_VarTraceProc):
+ * generic/tcl.decls (Tcl_GetVar2, Tcl_SetVar2, Tcl_TraceVar2,
+ (Tcl_UnsetVar2, Tcl_UntraceVar2, Tcl_UpVar2, Tcl_VarTraceInfo2,
+ (Tcl_GetVar2Ex, TclSetVar2Ex):
+ * generic/tclCmdMZ.c (TraceVarProc):
+ * generic/tclEnv.c (EnvTraceProc):
+ * generic/tclEvent.c (VwaitVarProc):
+ * generic/tclInt.decls (TclLookupVar,TclPrecTraceProc):
+ * generic/tclLink.c (LinkTraceProc):
+ * generic/tclUtil.c (TclPrecTraceProc):
+ * generic/tclVar.c (CallTraces, MakeUpvar, VarErrMsg, TclLookupVar,
+ (Tcl_GetVar2, Tcl_SetVar2, Tcl_TraceVar2, Tcl_UnsetVar2,
+ (Tcl_UntraceVar2, Tcl_UpVar2, Tcl_VarTraceInfo2, Tcl_GetVar2Ex,
+ (TclSetVar2Ex): Updated interfaces of generic/tclVar.c according to
+ TIP 27. In particular, the "part2" arguments were CONSTified. [Patch
+ 532642]
+ * generic/tclDecls.h:
+ * generic/tclIntDecls.h: make genstubs
+
+2002-03-15 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/compile.test (compile-12.3): Test to detect bug 530320.
+ * generic/tclCompile.c (TclCompileTokens): Fixed buffer overrun
+ reported in bug 530320.
+
+2002-03-14 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/configure: Regen.
+ * win/configure.in: Add configure time test for SEH support in the
+ compiler.
+ * win/tclWin32Dll.c (ESP, EBP, TclpCheckStackSpace,
+ (_except_checkstackspace_handler):
+ * win/tclWinChan.c (ESP, EBP, Tcl_MakeFileChannel,
+ (_except_makefilechannel_handler):
+ * win/tclWinFCmd.c (ESP, EBP, DoRenameFile, DoCopyFile,
+ (_except_dorenamefile_handler, _except_docopyfile_handler):
+ Implement SEH support under gcc using inline asm. Tcl and Tk should
+ now compile with Mingw 1.1. [Patch 525746]
+
+2002-03-14 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tclWinFCmd.c (DoRenameFile, DoCopyFile): Handle an SEH exception
+ with EXCEPTION_EXECUTE_HANDLER instead of restarting the faulting
+ instruction with EXCEPTION_CONTINUE_EXECUTION. [Bug 466102] provides
+ an example of how restarting could send Tcl into an infinite loop.
+ [Patch 525746]
+
+2002-03-11 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tclWinFCmd.c (DoRenameFile, DoCopyFile, DoDeleteFile,
+ (DoRemoveJustDirectory): Make sure we don't pass NULL or "" as a path
+ name to Win32 API functions since this was crashing under Windows 98.
+
+2002-03-11 Don Porter <dgp@users.sourceforge.net>
+
+ * library/tcltest/tcltest.tcl:
+ * library/tcltest/pkgIndex.tcl: Bumped tcltest package to 2.0.2.
+
+2002-03-11 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * library/tcltest/tcltest.tcl (getMatchingFiles): Pass a proper list
+ to foreach to avoid munging a Windows patch like D:\Foo\Bar into
+ D:FooBar before the glob.
+
+2002-03-11 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tclEncoding.c: Fix typo in comment.
+ * generic/tclIO.c (DoReadChars, ReadBytes, ReadChars): Use NULL value
+ instead of pointer set to NULL to make things more clear. Reorder
+ arguments so that they match the function signatures. Cleanup little
+ typos and add more descriptive comment.
+
+2002-03-08 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/README: Update to indicate that Mingw 1.1 is required to build
+ Tcl. Add section describing new msys based build process. Update
+ Cygwin build instructions so users know where to find Mingw 1.1.
+
+2002-03-08 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tclWinFCmd.c (DoCopyFile): correctly set retval to TCL_OK.
+
+2002-03-07 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tclWin32Dll.c (TclpCheckStackSpace):
+ * win/tclWinFCmd.c (DoRenameFile, DoCopyFile): Replace hard coded
+ constants with Win32 symbolic names. Move control flow statements out
+ of __try blocks since the documentation indicates it is frowned upon.
+
+2002-03-07 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/interp.n:
+ * generic/tclInterp.c (Tcl_InterpObjCmd, SlaveObjCmd,
+ (SlaveRecursionLimit):
+ * generic/tclTest.c:
+ * tests/interp.test: Added the [interp recursionlimit] command to
+ set/query the recursion limit of an interpreter. Proposal and
+ implementation from Stephen Trier. [TIP 87, Patch 522849]
+
+2002-03-06 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tcl.h, tools/tcl.wse.in, unix/configure.in,
+ * unix/tcl.spec, win/README.binary, win/configure.in, README:
+ Bumped patchlevel; this might need to change in the future, but it
+ will help us distinguish between the CVS version and the most recent
+ released version.
+
+2002-03-06 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclInt.h: for unshared objects, TclDecrRefCount now frees
+ the internal rep before the string rep - just like the non-macro
+ Tcl_DecrRefCount/TclFreeObj. [Bug 524802]
+
+2002-03-06 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/lsearch.n: Documentation of new features, plus examples.
+ * tests/lsearch.test: Tests of new features.
+ * generic/tclCmdIL.c (Tcl_LsearchObjCmd): TIP#80 support. See
+ http://purl.org/tcl/tip/80 for details.
+
+2002-03-05 Jeff Hobbs <jeffh@ActiveState.com>
+
+ *** 8.4a4 TAGGED FOR RELEASE ***
+
+ * unix/tclUnixChan.c: initial remedy for [Bug 525783] flush problem
+ introduced by TIP #35. This may not satisfy true serial channels, but
+ it restores the correct flushing of std* channels on exit.
+
+ * unix/README: added --enable-langinfo doc.
+
+ * unix/tcl.spec:
+ * tools/tcl.wse.in: fixed URL refs to use www.tcl.tk or SF.
+
+2002-03-04 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * README:
+ * mac/README:
+ * unix/Makefile.in:
+ * unix/README:
+ * win/README:
+ * win/README.binary: updated to use www.tcl.tk URL.
+
+ * unix/Makefile.in: added older ChangeLogs to dist target.
+
+ * tests/io.test:
+ * tests/encoding.test: corrected iso2022 encoding results.
+ added encoding-24.*
+ * generic/tclEncoding.c (EscapeFromUtfProc): corrected output of
+ escape codes as per RFC 1468. [Patch 474358] (taguchi)
+ (TclFinalizeEncodingSubsystem): corrected potential double-free
+ when encodings were finalized on exit. [Bugs 219314, 524674]
+
+2002-03-01 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/encoding/iso2022-jp.enc:
+ * library/encoding/iso2022.enc:
+ * tools/encoding/iso2022-jp.esc:
+ * tools/encoding/iso2022.esc: gave <ESC>$B precedence over <ESC>$@,
+ based on comments (point 1) in [Bug 219283] (rfc 1468)
+
+ * tests/encoding.test: added encoding-23.* tests
+ * generic/tclIO.c (FilterInputBytes): reset the TCL_ENCODING_START
+ flags in the ChannelState when using 'gets'. [Bug 523988]
+ Also reduced the value of ENCODING_LINESIZE from 30 to 20 as this
+ seems to improve the performance of 'gets' according to tclbench.
+
+2002-02-28 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclCmdMZ.c (TraceCommandProc): ensure that TraceCommandInfo
+ structure was also deleted when a command was deleted to prevent a
+ mem leak.
+
+ * generic/tclBasic.c (Tcl_CreateObjTrace): set tracePtr->flags
+ correctly.
+
+ * generic/tclTimer.c (TimerExitProc): remove remaining events in
+ tls on thread exit.
+
+2002-02-28 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclNamesp.c: allow cached fully-qualified namespace names to
+ be usable from different namespaces within the same interpreter
+ without forcing a new lookup [Patch 458872].
+
+2002-02-28 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclExecute.c: Replaced a few direct stack accesses with the
+ POP_OBJECT() macro [Bug 507181] (Don Porter).
+
+2002-02-27 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/GetIndex.3:
+ * generic/tcl.decls (Tcl_GetIndexFromObjStruct):
+ * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct): Revised the
+ prototype of the Tcl_GetIndexFromObjStruct to take its struct table as
+ a (CONST VOID *) argument, better describing what it is, maintaining
+ source compatibility, and adding CONST correctness according to TIP
+ 27. Thanks to Joe English for an elegant solution. [Bug 520304]
+
+ * generic/tclDecls.h: make genstubs
+
+ * generic/tclMain.c (Tcl_Main,StdinProc): Corrected some reference
+ count management errors on the interactive command Tcl_Obj found by
+ Purify. Thanks to Jeff Hobbs for the report and assistance.
+
+2002-02-27 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclBasic.c (Tcl_EvalTokensStandard): corrected mem leak in
+ error case.
+
+ * generic/tclTest.c (TestStatProc[123]): correct harmless UMRs.
+
+ * generic/tclLink.c (Tcl_LinkVar): correct mem leak in error case.
+
+2002-02-27 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * tests/socket.test (2.7): Accepted and applied patch for [Bug 523470]
+ provided by Don Porter <dgp@users.sourceforge.net> to avoid timing
+ problems in that test.
+
+ * unix/tclUnixChan.c (TclpOpenFileChannel): Added code to regonize
+ "/dev/tty" (by name) and to not handle it as tty / serial line. This
+ is the controlling terminal and is special. Setting it into raw mode
+ as is done for other tty's is a bad idea. This is a hackish fix for
+ expect [Bug 520624]. The fix has limitation: Tcl_MakeFileChannel
+ handles tty's specially too, but is unable to recognize /dev/tty as it
+ only gets a file descriptor, and no name for it.
+
+2002-02-26 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclCmdAH.c (StoreStatData): corrected mem leak.
+
+ * generic/tclCmdMZ.c (Tcl_RegsubObjCmd): prevent obj leak in
+ remedial regsub case.
+
+ * generic/tclFileName.c (Tcl_TranslateFileName): decr refcount for
+ error case to prevent mem leak.
+
+ * generic/tclVar.c (Tcl_ArrayObjCmd): removed extra obj allocation.
+
+ * unix/tclUnixSock.c (Tcl_GetHostName): added an extra
+ gethostbyname check to guard against failure with truncated
+ names returned by uname.
+
+ * unix/configure:
+ * unix/tcl.m4 (SC_SERIAL_PORT): added sys/modem.h check and defined
+ _XOPEN_SOURCE_EXTENDED for HP-11 to get updated header decls.
+
+ * unix/tclUnixChan.c: added Unix implementation of TIP #35, serial
+ port support. [Patch 438509] (schroedter)
+
+2002-02-26 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclCmpCmds.c: (bugfix to the bugfix, hopefully the last)
+ Bugfix to the new [for] compiling code: was setting a exceptArray
+ parameter using another param which wasn't yet initialised, thus
+ filling it with noise.
+
+2002-02-25 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * mac/tclMacSock.c (TcpGetOptionProc): Changed to recognize the option
+ "-error". Essentially ignores the option, always returning an empty
+ string.
+
+2002-02-25 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/Alloc.3:
+ * doc/LinkVar.3:
+ * doc/ObjectType.3:
+ * doc/PkgRequire.3:
+ * doc/Preserve.3:
+ * doc/TCL_MEM_DEBUG.3: Updated documentation to describe the ckalloc,
+ ckfree, ckrealloc, attemptckalloc, and attemptckrealloc macros, and
+ to accurately describe when and how they are used. [Bug 497459] (dgp)
+
+ * generic/tclHash.c (AllocArrayEntry, AllocStringEntry):
+ Before invoking ckalloc when creating a Tcl_HashEntry,
+ check that the amount of memory being allocated is
+ at least as large as sizeof(Tcl_HashEntry). The previous
+ code was allocating memory regions that were one
+ or two bytes short. [Bug 521950] (dejong)
+
+2002-02-25 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclBasic.c (Tcl_EvalEx): avoiding a buffer overrun
+ reported by Joe English, and restoring tcl7.6 behaviour for
+ [subst]: badly terminated nested scripts will raise an error
+ and not be evaluated. [Bug 495207]
+
+2002-02-25 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/tclUnixPort.h: corrected strtoll prototype mismatch on Tru64.
+ * compat/strtod.c (strtod): simplified #includes
+ * compat/strtol.c (strtol): gather result in a long before returning
+ as a long: necessary on platforms where sizeof(int) != sizeof(long).
+
+2002-02-25 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tclLoadDyld.c: updated to use Mac OS X 10.1 dyld APIs that
+ have more libdl-like semantics. [Bug 514392]
+
+2002-02-25 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclCompCmds: fixing a bug in patch dated 2002-02-22, in the
+ code for [for] and [while]. Under certain conditions, for long bodies,
+ the exception range parameters were badly computed. Tests forthcoming:
+ I still can't reproduce the conditions in the testsuite (!), although
+ the bug (with assorted segfault or panic!) can be triggered from the
+ console or with the new parse.bench in tclbench.
+
+2002-02-25 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * compat/strtoul.c, compat/strtol.c, compat/strtod.c: Added UCHAR,
+ CONST and #includes to clean up GCC output.
+
+2002-02-23 Don Porter <dgp@users.sourceforge.net>
+
+ * compat/strtoull.c (strtoull):
+ * compat/strtoll.c (strtoll):
+ * compat/strtoul.c (strtoul): Fixed failure to handle leading
+ sign symbols '+' and '-' and '0X' and raise overflow errors.
+ [Bug 440916] Also corrects prototype and errno problems.
+
+2002-02-23 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * configure: Regen.
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): Link with -n32 instead of -32 when
+ building on IRIX64-6.* system. [Bug 521707]
+
+2002-02-22 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclInt.h:
+ * generic/tclObj.c: renamed global variable emptyString ->
+ tclEmptyString because it is no longer static.
+ * generic/tclPkg.c: Fix for panic when library is loaded on a
+ platform without backlinking without proper use of stubs. [Bug 476537]
+
+2002-02-22 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/regexpComp.test: updated regexp-11.[1-4] to match changes in
+ regexp.test for new regsub syntax
+
+ * unix/configure:
+ * unix/tcl.m4: added --enable-64bit support for AIX-4 (using -q64
+ flag) when using IBM's xlc compiler.
+
+ * tests/safe.test: updated safe-8.5 and safe-8.7
+ * library/safe.tcl (CheckFileName): removed the limit on
+ sourceable file names (was only *.tcl or tclIndex files with no more
+ than one dot and 14 chars). There is enough internal protection in a
+ safe interpreter already. [Tk Bug 521560]
+
+2002-02-22 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclCompCmds: [FR 465811]. Optimising [if], [for] and [while]
+ for constant conditions; in addition, [for] and [while] are now
+ compiled with the "loop rotation" optimisation (thanks to Kevin
+ Kenny).
+
+2002-02-22 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ --- TIP#76 CHANGES ---
+ * generic/tclCmdMZ.c (Tcl_RegsubObjCmd): Final-argument-less
+ [regsub] returns the modified string.
+ * doc/regsub.n: Updated docs.
+ * tests/regexp.test: Updated and added tests.
+
+ * compat/strtoll.c (strtoll):
+ * compat/strtoull.c (strtoull):
+ * unix/tclUnixPort.h:
+ * win/tclWinPort.h: Const-ing 64-bit compatability declarations. Note
+ that the return pointer is non-const because it is entirely legal for
+ the functions to be called from somewhere that owns the string being
+ passed. Fixes problem reported by Larry Virden.
+
+2002-02-21 David Gravereaux <davygrvy@pobox.com>
+
+ * win/mkd.bat (removed):
+ * win/coffbase.txt (new):
+ * win/makefile.bc:
+ * win/makefile.vc: Changed the 'setup' target to stop using the
+ mkd.bat file and just make the directory right in the rule. Same
+ change to makefile.bc. Neither configure.in nor Makefile.in use it.
+
+ coffbase.txt will be the master list for our "prefered base addresses"
+ set by the linker. This should improve load-time (NT only) by avoiding
+ relocations. Submissions to the list by extension authors are
+ encouraged.
+
+ Added a 'tidy' target to compliment 'clean' and 'hose' to remove just
+ the outputs. Also removed the $(winlibs) macro as it wasn't being
+ used.
+
+ Stuff left to do:
+ 1) get the winhelp target to stop building in the tools/ directory.
+ 2) stop using rmd.bat
+ 3) add more dependacy rules.
+
+ * win/tclAppInit.c: Reverted back to -r1.6, as the header file change
+ to tclPort.h won't allow for easy embedded support outside of the
+ source dist. Thanks to Don Porter for pointing this out to me.
+
+2002-02-21 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc:
+ * win/rules.vc: Added a new "loimpact" option that sets the
+ -ws:aggressive linker option. Off by default. It's said to keep the
+ heap use low at the expense of alloc speed.
+
+ * win/tclAppInit.c: Changed #include "tcl.h" to be tclPort.h to remove
+ the raw windows.h include. tclPort.h brings in windows.h already and
+ lessens the pre-compiled-header mush and the randomly useless #pragma
+ comment (lib,...) references throughout the big windows.h tree (as
+ observed at high linker warning levels).
+
+2002-02-21 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tcl.h: Better guessing of LP64/ILP32 architecture, but now
+ sensitive to presence of (suitable) <limits.h>
+
+2002-02-20 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tcl.decls (Tcl_RegExpRange,Tcl_GetIndexFromObjStruct):
+ Overlooked a few source incompatibilities. Now using CONST84.
+ * generic/tclDecls.h: make genstubs
+ * generic/tcl.h (Tcl_CmdObjTraceProc): silence warning from Sun
+ Workshop compiler.
+
+2002-02-20 David Gravereaux <davygrvy@pobox.com>
+
+ * win/buildall.vc.bat:
+ * win/makefile.vc:
+ * win/rules.vc: General clean-ups. Added compiler and linker tests for
+ a) the pentium 0x0F errata, b) optimizing (not all have this), and c)
+ linker v6 section alignment confusion. All these are tested first to
+ make sure any D4002 or LNK1117 warnings aren't displayed. The pentium
+ 0x0F errata is a recommended switch. The v5 linker's section alignment
+ default is 512, but the v6 linker was changed to 4096 in an attempt to
+ speed loading on Win98. I changed the default to always be 512 across
+ both linkers, unless linking statically, then 4096 is used for the
+ claimed speed effect. Using a 512 alignment saves 12k bytes of dead
+ space in the DLL.
+
+ Added IA64 B-stepping errata switch when the compiler supports it.
+
+ Added profiling to $(lflags) when requested and also removed the
+ explict -entry option as the default works fine as is.
+
+ Removed win/tclWinInit.c from the special case section to let it use
+ the common implicit rule as the $(EXTFLAGS) macro it had was never
+ referenced anywhere.
+
+2002-02-20 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tcl.h: Added code to guess the correct settings for
+ TCL_WIDE_INT_IS_LONG and TCL_WIDE_INT_TYPE when configure doesn't tell
+ us them, as can happen with extensions.
+
+2002-02-19 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/format.n: Updated docs to list the specification.
+ * generic/tclCmdAH.c (Tcl_FormatObjCmd): Made behaviour on 64-bit
+ platforms correctly meet the specification, that %d works with the
+ native word-sized integer, instead of trying to guess (wrongly)
+ from the value being passed.
+
+2002-02-19 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: First draft of updated changes for 8.4a4 release.
+
+2002-02-15 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tclUnixPort.h: add strtoll/strtoull declarations for
+ platforms that do not define them.
+
+ * generic/tclIndexObj.c (STRING_AT): removed ptrdiff_t cast and
+ use of VOID* in default case (GNU-ism).
+
+2002-02-15 Kevin Kenny <kennykb@acm.org>
+
+ * compat/strtoll.c:
+ * compat/strtoul.c:
+ * compat/strtoull.c:
+ * generic/tclIOUtil.c:
+ * generic/tclPosixStr.c:
+ * generic/tclTest.c:
+ * generic/tclTestObj.c:
+ * tests/get.test:
+ * win/Makefile.vc: Further tweaks to the TIP 72 patch to make it
+ compile under VC++.
+
+2002-02-15 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * tclExecute.c:
+ * tclIOGT.c:
+ * tclIndexObj.c: Touchups to the TIP 72 patch to make it compileable
+ under Windows again. The changes are not complete, there is one nasty
+ regarding _stati64
+
+2002-02-15 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ +----------------------+
+ | TIP #72 IMPLEMENTED. |
+ +----------------------+
+
+ There are a lot of changes from this TIP, so please see
+ http://purl.org/tcl/tip/72.html for discussion of
+ backward-compatability issues, but the main ones modifications are in:
+
+ * generic/tcl.h: New types.
+ * generic/tcl.decls: New public functions.
+ * generic/tclExecute.c: 64-bit aware bytecode engine.
+ * generic/tclBinary.c: 64-bit handling in [binary] command.
+ * generic/tclScan.c: 64-bit handling in [scan] command.
+ * generic/tclCmdAH.c: 64-bit handling in [file] and [format]
+ commands.
+ * generic/tclBasic.c: New "wordSize" entry in ::tcl_platform.
+ * generic/tclFCmd.c: Large-file support (with many consequences.)
+ * generic/tclIO.c: Large-file support (with many consequences.)
+ * compat/strtoll.c, compat/strtoull.c: New support functions.
+ * unix/tcl.m4, unix/configure: 64-bit support and greatly enhanced
+ cacheing.
+
+ Most other changes, including all those in doc/* and test/* as well as
+ the majority in the platform directories, follow on from these.
+
+ Also coming out of the woodwork:
+ * generic/tclIndex.c: Better support for Cray PVP.
+ * win/tclWinMtherr.c: Better Borland support.
+
+ Note that, in a number of places through the Unix part of the platform
+ support, there are Tcl_Platform* references. These are expanded into
+ the correct way to call that particular underlying function, i.e. with
+ or without a '64' suffix, and should be used by people working on the
+ core in preference to the API functions they overlay so that the code
+ remains portable depending on the presence or absence of 64-bit
+ support on the underlying platform.
+
+ ***POTENTIAL INCOMPATIBILITY***: Extracted from the TIP
+
+ SUMMARY OF INCOMPATIBILITIES AND FIXES
+ ======================================
+
+ The behaviour of expressions containing constants that appear positive
+ but which have a negative internal representation will change, as
+ these will now usually be interpreted as wide integers. This is always
+ fixable by replacing the constant with int(constant).
+
+ Extensions creating new channel types will need to be altered as
+ different types are now in use in those areas. The change to the
+ declaration of Tcl_FSStat and Tcl_FSLstat (which are the new preferred
+ API in any case) are less serious as no non-alpha releases have been
+ made yet with those API functions.
+
+ Scripts that are lax about the use of the l modifier in format and
+ scan will probably need to be rewritten. This should be very uncommon
+ though as previously it had absolutely no effect.
+
+ Extensions that create new math functions that take more than one
+ argument will need to be recompiled (the size of Tcl_Value changes),
+ and functions that accept arguments of any type (TCL_EITHER) will need
+ to be rewritten to handle wide integer values. (I do not expect this
+ to affect many extensions at all.)
+
+2002-02-14 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * generic/tclIOCmd.c (Tcl_GetsObjCmd): Trivial fix for [Bug 517503], a
+ memory leak reported by Miguel Sofer <msofer@users.sf.net>. The leak
+ happens if an error occurs for "set var [gets $chan]" and leak one
+ empty object.
+
+2002-02-12 David Gravereaux <davygrvy@pobox.com>
+
+ * djgpp/ (new directory)
+ * djgpp/Makefile (new):
+ * unix/tclAppInit.c:
+ * unix/tclMtherr.c:
+ * unix/tclUnixFCmd.c:
+ * unix/tclUnixFile.c:
+ * unix/tclUnixInit.c:
+ * unix/tclUnixPort.h: Early stage of DJGPP support for building Tcl
+ on DOS. Dynamic loading isn't working, yet. Requires watt32 for the
+ TCP/IP stack. No autoconf, yet. Barely tested, but makes a working exe
+ that runs Tcl in protected-mode, flat memory. [exec] and pipes will
+ need the most work as multi-tasking on DOS has to be carefully.
+
+2002-02-10 Kevin Kenny <kennykb@acm.org>
+
+ * doc/CrtObjCmd.3:
+ * doc/CrtTrace.3:
+ * generic/tcl.decls:
+ * generic/tcl.h:
+ * generic/tclBasic.c:
+ * generic/tclInt.h:
+ * generic/tclTest.c:
+ * tests/basic.test: Added Tcl_CreateObjTrace,
+ Tcl_GetCommandInfoFromToken and Tcl_SetCommandInfoFromToken.
+ (TIPs #32 and #79.)
+
+ * generic/tclDecls.h:
+ * generic/tclStubInit.c: Regenerated Stubs tables.
+
+2002-02-08 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/configure:
+ * unix/tcl.m4: added -pthread for FreeBSD to EXTRA_CFLAGS and
+ LDFLAGS. Also triggered nodots only for FreeBSD-3. Added
+ AC_DEFINE(_POSIX_PTHREAD_SEMANTICS) for Solaris.
+
+ * unix/tclUnixPort.h:
+ * unix/tclUnixThrd.c: added thread-safe versions of readdir,
+ localtime, gmtime and inet_ntoa for threaded build. (jgdavidson)
+
+ * generic/tclScan.c (Tcl_ScanObjCmd): prevented ckfree being called on
+ a pointer to NULL.
+
+2002-02-07 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/DString.3:
+ * doc/Encoding.3:
+ * doc/GetCwd.3:
+ * doc/SplitPath.3:
+ * doc/Translate.3:
+ * doc/Utf.3:
+ * generic/tcl.decls:
+ * generic/tcl.h:
+ * generic/tclEncoding.c:
+ * generic/tclEnv.c:
+ * generic/tclFileName.c:
+ * generic/tclIOUtil.c:
+ * generic/tclUtf.c:
+ * generic/tclUtil.c:
+ * mac/tclMacInit.c:
+ * unix/tclUnixFile.c:
+ * unix/tclUnixInit.c:
+ * unix/tclUnixPipe.c:
+ * win/tclWin32Dll.c:
+ * win/tclWinFCmd.c:
+ * win/tclWinFile.c:
+ * win/tclWinInit.c: Partial TIP 27 rollback. Following routines
+ restored to return (char *): Tcl_DStringAppend,
+ Tcl_DStringAppendElement, Tcl_JoinPath, Tcl_TranslateFileName,
+ Tcl_ExternalToUtfDString, Tcl_UtfToExternalDString,
+ Tcl_UniCharToUtfDString, Tcl_GetCwd, Tcl_WinTCharToUtf. Also restored
+ Tcl_WinUtfToTChar to return (TCHAR *) and Tcl_UtfToUniCharDString to
+ return (Tcl_UniChar *). Modified some callers. This change recognizes
+ that Tcl_DStrings are de-facto white-box objects.
+
+ * generic/tclDecls.h:
+ * generic/tclPlatDecls.h: make genstubs
+
+ * generic/tclCmdMZ.c: corrected use of C++-style comment.
+
+2002-02-06 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/scan.test:
+ * generic/tclScan.c (Tcl_ScanObjCmd): corrected scan 0x... %x handling
+ that didn't accept the 0x as a prelude to a base 16 number. [Bug
+ 495213]
+
+ * generic/tclCompCmds.c (TclCompileRegexpCmd): made early check for
+ bad RE to stop checking further.
+
+ * generic/tclCmdMZ.c (Tcl_RegsubObjCmd): added special case to search
+ for simple 'string map' style regsub calls. Delayed creation of
+ resultPtr object until an initial match is made, as the input string
+ object can then be reused for no matches.
+ (Tcl_StringObjCmd): optimization improvements to the STR_MAP
+ algorithm for zero-length and nocase cases.
+
+ * tests/regexp.test:
+ * tests/regexpComp.test: extra code coverage tests.
+
+ * tests/string.test: added 10.18 and 10.19 extra tests.
+
+ * generic/regc_locale.c (casecmp): slight performance improvement.
+
+2002-02-05 Don Porter <dgp@users.sourceforge.net>
+
+ * library/http/http.tcl:
+ * library/http/pkgIndex.tcl: Corrected use of http::error when
+ ::error was intended. Bump to http 2.4.2.
+
+2002-02-04 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * unix/tclUnixChan.c (FileOutputProc): Fixed [bug 465765] reported by
+ Dale Talcott <daletalcott@users.sourceforge.net>. Avoid writing
+ nothing into a file as STREAM based implementations will consider this
+ a EOF (if the file is a pipe). Not done in the generic layer as this
+ type of writing is actually useful to check the state of a socket.
+
+ * doc/open.n: Fixed [Bug 511540], added cross-reference to 'pid' as
+ the command to use to retrieve the pid of a command pipeline created
+ via 'open'.
+
+2002-02-01 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclCmdMZ.c (Tcl_RegexpObjCmd): handle quirky about case
+ earlier to avoid shimmering problem.
+
+2002-02-01 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * tests/io.test: io-39.22 split into two tests, one platform
+ dependent, the other not. -eofchar is not empty on the windows
+ platform.
+
+2002-02-01 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclTest.c: fix to picky windows compiler problem with the
+ 'MainLoop' function declaration.
+
+2002-01-31 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * win/tclWinFCmd.c: TIP 27: Applied patch fixing CONST warnings on
+ behalf of Don Porter <dgp@users.sourceforge.net>.
+
+2002-01-30 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tcl.decls:
+ * generic/tcl.h:
+ * generic/tclInt.h: For each interface identified in the TIP 27
+ changes below as a POTENTIAL INCOMPATIBILITY, the source of the
+ incompatibility has been parameterized so that it can be removed. When
+ compiling extension code against the Tcl header files, use the
+ compiler flag -DUSE_NON_CONST to remove the irresolvable source
+ incompatibilities introduced by the TIP 27 changes. Resolvable changes
+ are left for extension authors to resolve.
+ * generic/tclDecls.h: make genstubs
+
+2002-01-30 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * doc/FileSystem.3: added documentation for 3 public functions which
+ had been overlooked. [Bug 507701]
+ * unix/mkLinks: make mklinks
+
+2002-01-29 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/regexpComp.test:
+ * generic/tclCompCmds.c (TclCompileRegexpCmd): enhanced to support
+ -nocase and -- options.
+
+2002-01-28 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/tcl.m4 (SC_LOAD_TCLCONFIG):
+ * win/tcl.m4 (SC_LOAD_TCLCONFIG): Set TCL_LIB_SPEC, TCL_STUB_LIB_SPEC,
+ and TCL_STUB_LIB_PATH to the values of TCL_BUILD_LIB_SPEC,
+ TCL_BUILD_STUB_LIB_SPEC, and TCL_BUILD_STUB_LIB_PATH when tclConfig.sh
+ is loaded from the build directory. A Tcl extension should make use of
+ the non-build versions of these variables since they will work in both
+ cases. This modification was described in TIP 34.
+
+2002-01-28 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tclWinReg.c (regConnectRegistryProc,RecursiveDeleteKey)
+ (DeleteKey,GetKeyNames,GetType,GetValue,OpenSubKey,SetValue):
+ redid the CONSTification as previous changes caused failing tests.
+
+ * tests/regexpComp.test (new):
+ * generic/tclInt.h:
+ * generic/tclBasic.c: added TclCompileRegexpCmd entry
+ * generic/tclCompCmds.c (TclCompileStringCmd): corrected to return
+ TCL_OUT_LINE_COMPILE instead of TCL_ERROR for parsing errors, so
+ it only throws the error for runtime compile, in case the user
+ modifies 'string'.
+ (TclCompileRegexpCmd): first try at a byte-compiled regexp command. It
+ handles static strings and ^$ bounded static strings.
+ (TclCompileAppendCmd): made TclPushVarName call always use
+ TCL_CREATE_VAR as numWords is always > 2 at that point.
+
+ * generic/tclExecute.c (TclExecuteByteCode:INST_LIST): correct
+ possibly dangerous decr in macro call.
+
+ * win/tclWinInit.c (TclpFindVariable): CONSTification touch-up
+
+ * win/tclWinReg.c (OpenSubKey): corrected bug introduced in
+ CONSTification that dropped pointer reference.
+
+ * ChangeLog.2000 (new file):
+ * ChangeLog: broke changes from 2000 into ChangeLog.2000 to reduce
+ size of the main ChangeLog.
+
+2002-01-28 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tclPlatDecls.h: Added preprocessor logic to force a
+ typedef of TCHAR when __STDC__ is defined when using the uncommon
+ -Za compiler switch with the microsoft compiler.
+
+2002-01-27 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/package.n: Documented global namespace context for script
+ evaluation by [package require].
+
+2002-01-27 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tclInt.decls:
+ * generic/tclIntPlatDecls.h:
+ * mac/tclMacChan.c:
+ * mac/tclMacFCmd.c:
+ * mac/tclMacFile.c:
+ * mac/tclMacInit.c:
+ * mac/tclMacLoad.c:
+ * mac/tclMacResource.c:
+ * mac/tclMacSock.c: TIP 27 CONSTification induced changes
+
+ * tests/event.test:
+ * tests/main.test: added catches/constraints to test that
+ use features that don't exist on the mac.
+
+2002-01-25 Mo DeJong <mdejong@users.sourceforge.net>
+
+ Make -eofchar and -translation options read only for server sockets.
+ [Bug 496733]
+
+ * generic/tclIO.c (Tcl_GetChannelOption, Tcl_SetChannelOption):
+ Instead of returning nothing for the -translation option on a server
+ socket, always return "auto". Return the empty string enclosed in
+ quotes for the -eofchar option on a server socket. Fixup -eofchar
+ usage message so that it matches the implementation.
+ * tests/io.test: Add -eofchar tests and -translation tests to ensure
+ options are read only on server sockets.
+ * tests/socket.test: Update tests to account for -eofchar and
+ -translation option changes.
+
+2002-01-25 Don Porter <dgp@users.sourceforge.net>
+
+ * compat/strstr.c (strstr):
+ * generic/tclCmdAH.c (Tcl_FormatObjCmd):
+ * generic/tclCmdIL.c (InfoNameOfExecutableCmd):
+ * generic/tclEnv.c (ReplaceString):
+ * generic/tclFileName.c (ExtractWinRoot):
+ * generic/tclIO.c (FlushChannel,Tcl_BadChannelOption):
+ * generic/tclStringObj.c (AppendUnicodeToUtfRep):
+ * generic/tclThreadTest.c (TclCreateThread):
+ * generic/tclUtf.c (Tcl_UtfPrev):
+ * mac/tclMacFCmd.c (TclpObjListVolumes):
+ * mac/tclMacResource.c (TclMacRegisterResourceFork,
+ (BuildResourceForkList):
+ * win/tclWinInit.c (AppendEnvironment): Sought out and eliminated
+ instances of CONST-casting that are no longer needed after the
+ TIP 27 effort.
+
+ * Following is [Patch 501006]
+ * generic/tclInt.decls (Tcl_AddInterpResolvers, Tcl_Export,
+ (Tcl_FindNamespace, Tcl_GetInterpResolvers, Tcl_ForgetImport,
+ (Tcl_Import, Tcl_RemoveInterpResolvers):
+ * generic/tclNamesp.c (Tcl_Export, Tcl_Import, Tcl_ForgetImport,
+ (Tcl_FindNamespace):
+ * generic/tclResolve.c (Tcl_AddInterpResolvers,Tcl_GetInterpResolvers,
+ (Tcl_RemoveInterpResolvers): Updated APIs in generic/tclResolve.c and
+ generic/tclNamesp.c according to the guidelines of TIP 27.
+ * generic/tclIntDecls.h: make genstubs
+
+ * Following is [Patch 505630]
+ * doc/AddErrorInfo.3:
+ * generic/tcl.decls (Tcl_LogCommandInfo):
+ * generic/tclBasic.c (Tcl_LogCommandInfo): Updated interfaces
+ of generic/tclBasic.cc according to TIP 27.
+ * generic/tclDecls.h: make genstubs
+
+ * Following is [Patch 506818]
+ * doc/Hash.3:
+ * generic/tcl.decls (Tcl_HashStats):
+ * generic/tclHash.c (Tcl_HashStats): Updated APIs of generic/tclHash.c
+ according to guidelines of TIP 27.
+ * generic/tclDecls.h: make genstubs
+ * generic/tclVar.c (Tcl_ArrayObjCmd): Updated callers.
+
+ * Following is [Patch 506807]
+ * doc/ObjectType.3:
+ * generic/tcl.decls (Tcl_GetObjType):
+ * generic/tclObj.c (Tcl_GetObjType): Updated APIs of generic/tclObj.c
+ according to guidelines of TIP 27.
+ * generic/tclDecls.h: make genstubs
+
+ * Following is [Patch 507304]
+ * doc/Encoding.3:
+ * generic/tcl.decls (Tcl_WinUtfToTChar,Tcl_WinTCharToUtf):
+ * win/tclWin32Dll.c (Tcl_WinUtfToTChar,Tcl_WinTCharToUtf):
+ Updated interfaces in win/tclWin32Dll.c according to TIP 27.
+ * generic/tclPlatDecls.h: make genstubs
+ * generic/tclIOUtil.c (TclpNativeToNormalized):
+ * win/tclWinFCmd.c (TclpObjNormalizePath):
+ * win/tclWinFile.c (TclpFindExecutable,TclpMatchInDirectory,
+ (NativeIsExec,NativeStat):
+ * win/tclWinLoad.c (TclpLoadFile):
+ * win/tclWinPipe.c (TclpOpenFile,ApplicationType):
+ * win/tclWinReg.c (regConnectRegistryProc,RecursiveDeleteKey,DeleteKey,
+ (GetKeyNames,GetType,GetValue,OpenSubKey,SetValue):
+ * win/tclWinSerial.c (SerialSetOptionProc): Update callers.
+
+ * Following is [Patch 505072]
+ * doc/Concat.3:
+ * doc/Encoding.3:
+ * doc/Filesystem.3:
+ * doc/Macintosh.3:
+ * doc/OpenFileChnl.3
+ * doc/SetResult.3:
+ * doc/SetVar.3:
+ * doc/SplitList.3:
+ * doc/SplitPath.3:
+ * doc/Translate.3:
+ * generic/tcl.h (Tcl_FSMatchInDirectoryProc):
+ * generic/tclInt.h (TclpMatchInDirectory):
+ * generic/tcl.decls (Tcl_Concat,Tcl_GetStringResult,Tcl_GetVar,
+ (Tcl_GetVar2,Tcl_JoinPath,Tcl_Merge,Tcl_OpenCommandChannel,Tcl_SetVar,
+ (Tcl_SetVar2,Tcl_SplitList,Tcl_SplitPath,Tcl_TranslateFileName,
+ (Tcl_ExternalToUtfDString,Tcl_GetEncodingName,Tcl_UtfToExternalDString,
+ (Tcl_GetDefaultEncodingDir,Tcl_SetDefaultEncodingDir,
+ (Tcl_FSMatchInDirectory,Tcl_MacEvalResource,Tcl_MacFindResource):
+ * generic/tclInt.decls (TclCreatePipeline,TclGetEnv,TclpGetCwd,
+ (TclpCreateProcess):
+ * mac/tclMacFile.c (TclpGetCwd):
+ * generic/tclEncoding.c (Tcl_GetDefaultEncodingDir,
+ (Tcl_SetDefaultEncodingDir,Tcl_GetEncodingName,
+ (Tcl_ExternalToUtfDString,Tcl_UtfToExternalDString, OpenEncodingFile,
+ (LoadEscapeEncoding):
+ * generic/tclFileName.c (DoTildeSubst,Tcl_JoinPath,Tcl_SplitPath,
+ (Tcl_TranslateFileName):
+ * generic/tclIOUtil.c (Tcl_FSMatchInDirectory):
+ * generic/tclPipe.c (FileForRedirect,TclCreatePipeline,
+ (Tcl_OpenCommandChannel):
+ * generic/tclResult.c (Tcl_GetStringResult):
+ * generic/tclUtil.c (Tcl_Concat,Tcl_SplitList,Tcl_Merge):
+ * generic/tclVar.c (Tcl_GetVar,Tcl_GetVar2,Tcl_SetVar,Tcl_SetVar2):
+ * mac/tclMacResource.c (Tcl_MacEvalResource,Tcl_MacFindResource):
+ Updated interfaces of generic/tclEncoding, generic/tclFilename.c,
+ generic/tclIOUtil.c, generic/tclPipe.c, generic/tclResult.c,
+ generic/tclUtil.c, generic/tclVar.c and mac/tclMacResource.c according
+ to TIP 27. Tcl_TranslateFileName rewritten as wrapper around VFS-aware
+ version.
+ ***POTENTIAL INCOMPATIBILITY***
+ Includes source incompatibilities: argv arguments of Tcl_Concat,
+ Tcl_JoinPath, Tcl_OpenCommandChannel, Tcl_Merge; argvPtr arguments of
+ Tcl_SplitList and Tcl_SplitPath.
+ * generic/tclDecls.h:
+ * generic/tclIntDecls.h: make genstubs
+
+ * generic/tclCkalloc.c (MemoryCmd):
+ * generic/tclClock.c (FormatClock):
+ * generic/tclCmdAH.c (Tcl_CaseObjCmd,Tcl_EncodingObjCmd,Tcl_FileObjCmd):
+ * generic/tclCmdIL.c (InfoLibraryCmd,InfoPatchLevelCmd,
+ (InfoTclVersionCmd):
+ * generic/tclCompCmds.c (TclCompileForeachCmd):
+ * generic/tclCompCmds.h (TclCompileForeachCmd):
+ * generic/tclCompile.c (TclFindCompiledLocal):
+ * generic/tclEnv.c (TclSetupEnv,TclSetEnv,Tcl_PutEnv,TclGetEnv,
+ (EnvTraceProc):
+ * generic/tclEvent.c (Tcl_BackgroundError):
+ * generic/tclIO.c (Tcl_BadChannelOption,Tcl_SetChannelOption):
+ * generic/tclIOCmd.c (Tcl_ExecObjCmd,Tcl_OpenObjCmd):
+ * generic/tclIOSock.c (TclSockGetPort):
+ * generic/tclIOUtil.c (SetFsPathFromAny):
+ * generic/tclLink.c (LinkTraceProc):
+ * generic/tclMain.c (Tcl_Main):
+ * generic/tclNamesp.c (TclTeardownNamespace):
+ * generic/tclProc.c (TclCreateProc):
+ * generic/tclTest.c (TestregexpObjCmd,TesttranslatefilenameCmd,
+ (TestchmodCmd,GetTimesCmd,TestsetCmd,TestOpenFileChannelProc1,
+ (TestOpenFileChannelProc2,TestOpenFileChannelProc3,AsyncHandlerProc,
+ (TestpanicCmd):
+ * generic/tclThreadTest.c (ThreadErrorProc,ThreadEventProc):
+ * generic/tclUtil.c (TclPrecTraceProc):
+ * mac/tclMacFCmd.c (GetFileSpecs):
+ * mac/tclMacFile.c (TclpMatchInDirectory):
+ * mac/tclMacInit.c (TclpInitLibraryPath,Tcl_SourceRCFile):
+ * mac/tclMacOSA.c (tclOSAStore,tclOSALoad):
+ * mac/tclMacResource.c (Tcl_MacEvalResource):
+ * unix/tclUnixFCmd.c (TclpObjNormalizePath):
+ * unix/tclUnixFile.c (TclpMatchInDirectory,TclpGetUserHome,TclpGetCwd,
+ (TclpReadLink):
+ * unix/tclUnixInit.c (TclpInitLibraryPath,TclpSetVariables,
+ (Tcl_SourceRCFile):
+ * unix/tclUnixPipe.c (TclpOpenFile,TclpCreateTempFile,
+ (TclpCreateProcess):
+ * win/tclWinFile.c (TclpGetCwd,TclpMatchInDirectory):
+ * win/tclWinInit.c (TclpInitLibraryPath,Tcl_SourceRCFile,
+ (TclpSetVariables):
+ * win/tclWinPipe.c (TclpCreateProcess): Updated callers.
+
+2002-01-24 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclIOUtil.c (SetFsPathFromAny): Corrected tilde-substitution
+ of pathnames where > 1 separator follows the ~. [Bug 504950]
+
+2002-01-24 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/http/pkgIndex.tcl:
+ * library/http/http.tcl: don't add port in default case to handle
+ broken servers. http bumped to 2.4.1 [Bug 504508]
+
+2002-01-23 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * unix/mkLinks: Regenerated.
+ * doc/CrtChannel.3:
+ * doc/ChnlStack.3: Moved documentation for 'Tcl_GetTopChannel' from
+ 'CrtChannel' to 'ChnlStack'. Added documentation of
+ 'Tcl_GetStackedChannel'. [Bug 506147] reported by Mark Patton
+ <msp@users.sourceforge.net>.
+
+2002-01-23 Don Porter <dgp@users.sourceforge.net>
+
+ * win/tclWinFile.c (NativeAccess,NativeStat,NativeIsExec,
+ (TclpGetUserHome):
+ * win/tclWinPort.h (TclWinSerialReopen):
+ * win/tclWinSerial.c (TclWinSerialReopen):
+ * win/tclWinSock.c (Tcl_OpenTcpServer): Corrections to earlier TIP 27
+ changes. Thanks to Andreas Kupries for the feedback.
+ * generic/tclPlatDecls.h: make genstubs
+
+ * doc/GetHostName.3:
+ * doc/GetOpnFl.3:
+ * doc/OpenTcp.3:
+ * tcl.decls (Tcl_GetHostName,Tcl_GetOpenFile,Tcl_OpenTcpClient,
+ (Tcl_OpenTclServer):
+ * mac/tclMacSock.c (CreateSocket,Tcl_OpenTcpClient,Tcl_OpenTcpServer,
+ (Tcl_GetHostName,GetHostFromString):
+ * unix/tclUnixChan.c (CreateSocket,CreateSocketAddress,
+ (Tcl_OpenTcpClient,Tcl_OpenTcpServer,Tcl_GetOpenFile):
+ * unix/tclUnixSock.c (Tcl_GetHostName):
+ * win/tclWinSock.c (CreateSocket,CreateSocketAddress,
+ (Tcl_OpenTcpClient,Tcl_OpenTcpServer,Tcl_GetHostName):
+ Updated socket interfaces according to TIP 27.
+ * generic/tclCmdIL.c (InfoHostnameCmd): Updated callers.
+ * generic/tclDecls.h: make genstubs
+
+2002-01-21 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tclLoadNone.c: TclpLoadFile() didn't match proto of typedef
+ Tcl_FSLoadFileProc. OK'd by vincentdarley. [Patch 502488]
+
+2002-01-21 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * generic/tclIO.c (WriteChars): Fix for [Bug 506297], reported by
+ Martin Forssen <ruric@users.sourceforge.net>. The encoding chosen in
+ the script exposing the bug writes out three intro characters when
+ TCL_ENCODING_START is set, but does not consume any input as
+ TCL_ENCODING_END is cleared. As some output was generated the
+ enclosing loop calls UtfToExternal again, again with START set. Three
+ more characters in the out and still no use of input ... To break this
+ infinite loop we remove TCL_ENCODING_START from the set of flags after
+ the first call (no condition is required, the later calls remove an
+ unset flag, which is a no-op). This causes the subsequent calls to
+ UtfToExternal to consume and convert the actual input.
+
+2002-01-21 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclTest.c: Converted declarations of TestReport file system
+ to more portable form. [Bug 501417]
+
+ * generic/tcl.decls (Tcl_TraceCommand,Tcl_UntraceCommand,
+ (Tcl_CommandTraceInfo):
+ * generic/tclCmdMZ.c (Tcl_TraceCommand,Tcl_UntraceCommand,
+ (Tcl_CommandTraceInfo): Updated APIs in generic/tclCmdMZ.c according
+ to the guidelines of TIP 27.
+ * generic/tclDecls.h: make genstubs
+
+2002-01-18 Don Porter <dgp@users.sourceforge.net>
+
+ * win/tclWinChan.c:
+ * win/tclWinFCmd.c:
+ * win/tclWinFile.c: Overlooked callers of Tcl_FSGetNativePath
+
+ * win/tclWinDde.c:
+ * win/tclWinReg.c: Overlooked callers of Tcl_GetIndexFromObj
+
+2002-01-18 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tclThreadTest.c:
+ * mac/tclMacChan.c:
+ * mac/tclMacFCmd.c:
+ * mac/tclMacFile.c:
+ * mac/tclMacLoad.c:
+ * mac/tclMacResource.c: TIP 27 CONSTification broke the mac build in a
+ number of places.
+
+2002-01-17 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * generic/tclIOCmd.c (Tcl_GetsObjCmd): Fixed [Bug 504642] as reported
+ by Brian Griffin <bgriffin@users.sourceforge.net>, using his
+ patch. Before the patch the generic I/O layer held an unannounced
+ reference to the interp result to store the read line into. This
+ unfortunately has disastrous results if the channel driver executes a
+ tcl script to perform its operation, this freeing the interp
+ result. In that case we are dereferencing essentially a dangling
+ reference. It is not truly dangling because the object is in the free
+ list, but this only causes us to smash the free list and have the
+ error occur later somewhere else. The patch simply creates a new
+ object for the line and later sets it into the interp result when we
+ are done with reading.
+
+2002-01-16 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/tcl.m4 (SC_LOAD_TCLCONFIG):
+ * win/tcl.m4 (SC_LOAD_TCLCONFIG): Subst TCL_DBGX into
+ TCL_STUB_LIB_FILE and TCL_STUB_LIB_FLAG variables so that an extension
+ does not need to subst TCL_DBGX into its makefile. [Tk Bug 504356]
+
+2002-01-16 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/FileSystem.3:
+ * doc/GetCwd.3:
+ * doc/GetIndex.3:
+ * generic/tcl.decls (Tcl_GetIndexFromObj, Tcl_GetIndexFromObjStruct,
+ (Tcl_GetCwd, Tcl_FSFileAttrStrings, Tcl_FSGetNativePath,
+ (Tcl_FSGetTranslatedStringPath):
+ * generic/tcl.h (Tcl_FSFileAttrStringsProc):
+ * generic/tclFCmd.c (TclFileAttrsCmd):
+ * generic/tclIOUtil.c (Tcl_GetCwd,NativeFileAttrStrings,
+ (Tcl_FSFileAttrStrings,Tcl_FSGetTranslatedStringPath,
+ (Tcl_FSGetNativePath):
+ * generic/tclIndexObj.c (Tcl_GetIndexFromObj,
+ (Tcl_GetIndexFromObjStruct):
+ More TIP 27 updates in tclIOUtil.c and tclIndexObj.c that were
+ overlooked before. [Patch 504671]
+ ***POTENTIAL INCOMPATIBILITY***
+ Includes a source incompatibility in the tablePtr arguments of the
+ Tcl_GetIndexFromObj* routines.
+ * generic/tclDecls.h: make genstubs
+
+ * generic/tclBinary.c (Tcl_BinaryObjCmd):
+ * generic/tclClock.c (Tcl_ClockObjCmd):
+ * generic/tclCmdAH.c (Tcl_EncodingObjCmd, Tcl_FileObjCmd):
+ * generic/tclCmdIL.c (Tcl_InfoObjCmd,Tcl_LsearchObjCmd,Tcl_LsortObjCmd):
+ * generic/tclCmdMZ.c (Tcl_TraceObjCmd,Tcl_RegexpObjCmd,Tcl_RegsubObjCmd,
+ (Tcl_StringObjCmd,Tcl_SubstObjCmd,Tcl_SwitchObjCmd,
+ (TclTraceCommandObjCmd,TclTraceVariableObjCmd):
+ * generic/tclCompCmds.c (TclCompileStringCmd):
+ * generic/tclEvent.c (Tcl_UpdateObjCmd):
+ * generic/tclFileName.c (Tcl_GlobObjCmd):
+ * generic/tclIO.c (Tcl_FileEventObjCmd):
+ * generic/tclIOCmd.c (Tcl_SeekObjCmd,Tcl_ExecObjCmd,Tcl_SocketObjCmd,
+ (Tcl_FcopyObjCmd):
+ * generic/tclInterp.c (Tcl_InterpObjCmd,SlaveObjCmd):
+ * generic/tclNamesp.c (Tcl_NamespaceObjCmd):
+ * generic/tclPkg.c (Tcl_PackageObjCmd):
+ * generic/tclTest.c (Tcltest_Init,TestencodingObjCmd,TestgetplatformCmd,
+ (TestlocaleCmd,TestregexpObjCmd,TestsaveresultCmd,
+ (TestGetIndexFromObjStructObjCmd,TestReportFileAttrStrings):
+ * generic/tclTestObj.c (TestindexObjCmd,TeststringObjCmd):
+ * generic/tclTimer.c (Tcl_AfterObjCmd):
+ * generic/tclVar.c (Tcl_ArrayObjCmd):
+ * mac/tclMacFCmd.c (SetFileFinderAttributes):
+ * unix/tclUnixChan.c (TclpOpenFileChannel):
+ * unix/tclUnixFCmd.c (tclpFileAttrStrings):
+ * unix/tclUnixFile.c (TclpObjAccess,TclpObjChdir,TclpObjStat,
+ (TclpObjLstat):
+ * win/tclWinFCmd.c (tclpFileAttrStrings): Updated callers.
+
+ * doc/RegExp.3:
+ * doc/Utf.3:
+ * generic/tcl.decls:
+ * generic/tclInt.decls:
+ * generic/tclRegexp.c:
+ * generic/tclUtf.c: Updated APIs in generic/tclUtf.c and
+ generic/tclRegexp.c according to the guidelines of TIP 27.
+ [Patch 471509]
+
+ * generic/regc_locale.c (element,cclass):
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd):
+ * generic/tclFileName.c (TclpGetNativePathType,SplitMacPath):
+ * generic/tclIO.c (ReadChars):
+ * mac/tclMacLoad.c (TclpLoadFile):
+ * win/tclWinFile.c (TclpGetUserHome): Updated callers.
+
+ * generic/tclDecls.h:
+ * generic/tclIntDecls.h: make genstubs
+
+ * doc/ParseCmd.3 (Tcl_ParseVar):
+ * generic/tcl.decls (Tcl_ParseVar):
+ * generic/tclParse.c (Tcl_ParseVar):
+ * generic/tclTest.c (TestparsevarObjCmd): Updated APIs in
+ generic/tclParse.c according to the guidelines of TIP 27. Updated
+ callers. [Patch 501046]
+ * generic/tclDecls.h: make genstubs
+
+ * generic/tcl.decls (Tcl_RecordAndEval):
+ * generic/tclDecls.h: make genstubs
+ * generic/tclHistory.c (Tcl_RecordAndEval): Updated APIs in
+ generic/tclHistory.c according to the guidelines of TIP 27.
+ [Patch 504091]
+
+ * doc/CrtSlave.3:
+ * generic/tcl.decls (Tcl_CreateAlias, Tcl_CreateAliasObj,
+ (Tcl_CreateSlave, Tcl_GetAlias, Tcl_GetAliasObj, Tcl_GetSlave):
+ * generic/tclInterp.c (Tcl_CreateAlias, Tcl_CreateAliasObj,
+ (Tcl_CreateSlave, Tcl_GetAlias, Tcl_GetAliasObj, Tcl_GetSlave):
+ Updated APIs in the file generic/tclInterp.c according to the
+ guidelines of TIP 27. [Patch 501371]
+ ***POTENTIAL INCOMPATIBILITY***
+ Includes a source incompatibility in the targetCmdPtr arguments of the
+ Tcl_GetAlias* routines.
+
+ * generic/tclDecls.h: make genstubs
+
+2002-01-15 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/SetErrno.3 (Tcl_ErrnoMsg): Corrected documentation for
+ Tcl_ErrnoMsg; it takes an integer argument. Thanks to Georgios
+ Petasis. [Bug 468183]
+
+ * doc/AddErrInfo.3 (Tcl_PosixError):
+ * doc/Eval.3 (Tcl_EvalFile):
+ * doc/FileSystem.c (Tcl_FSOpenFileChannel,Tcl_FSOpenFileChannelProc):
+ * doc/OpenFileChnl.3 (Tcl_OpenFileChannel):
+ * doc/SetErrno.3 (Tcl_ErrnoId,Tcl_ErrnoMsg):
+ * doc/Signal.3 (Tcl_SignalId,Tcl_SignalMsg):
+ * generic/tcl.decls (Tcl_ErrnoId,TclErrnoMsg,Tcl_EvalFile,
+ (Tcl_OpenFileChannel,Tcl_PosixError,Tcl_SignalId,Tcl_SignalMsg,
+ (Tcl_FSOpenFileChannel):
+ * generic/tcl.h (Tcl_FSOpenFileChannelProc):
+ * generic/tclIO.c (FlushChannel):
+ * generic/tclIOUtil.c (Tcl_OpenFileChannel,Tcl_EvalFile,TclGetOpenMode,
+ (Tcl_PosixError,Tcl_FSOpenFileChannel):
+ * generic/tclInt.decls (TclGetOpenMode):
+ * generic/tclInt.h (TclOpenFileChannelProc_,TclGetOpenMode,
+ (TclpOpenFileChannel):
+ * generic/tclPipe.c (TclCleanupChildren):
+ * generic/tclPosixStr.c (Tcl_ErrnoId,Tcl_ErrnoMsg,Tcl_SignalId,
+ (Tcl_SignalMsg):
+ * generic.tclTest.c (PretendTclpOpenFileChannel,
+ (TestOpenFileChannelProc1,TestOpenFileChannelProc2,
+ (TestOpenFileChannelProc3,TestReportOpenFileChannel):
+ * mac/tclMacChan.c (TclpOpenFileChannel):
+ * unix/tclUnixChan.c (TclpOpenFileChannel):
+ * win/tclWinChan.c (TclpOpenFileChannel): Updated APIs in
+ generic/tclIOUtil.c and generic/tclPosixStr.c according to the
+ guidelines of TIP 27. Updated callers. [Patch 499196]
+
+ * generic/tclDecls.h:
+ * generic/tclIntDecls.h: make genstubs
+
+ * doc/CrtChannel.3:
+ * doc/OpenFileChnl.3:
+ * generic/tcl.decls:
+ * generic/tclIO.h:
+ * generic/tclIO.c (DoWrite, Tcl_RegisterChannel, Tcl_GetChannel,
+ (Tcl_CreateChannel, Tcl_GetChannelName, CloseChannel, Tcl_Write,
+ (Tcl_WriteRaw, Tcl_Ungets, Tcl_BadChannelOption, Tcl_GetChannelOption,
+ (Tcl_SetChannelOption, Tcl_GetChannelNamesEx, Tcl_ChannelName):
+ Updated APIs in the file generic/tclIO.c according to the guidelines
+ of TIP 27. Several minor documentation corrections as well.
+ [Patch 503565]
+ * generic/tclDecls.h: make genstubs
+
+ * generic/tcl.h (Tcl_DriverOutputProc, Tcl_DriverGetOptionProc,
+ (Tcl_DriverSetOptionProc):
+ * generic/tclIOGT.c (TransformOutputProc, TransformGetOptionProc,
+ (TransformSetOptionProc):
+ * mac/tclMacChan.c (FileOutput, StdIOOutput):
+ * man/tclMacSock.c (TcpGetOptionProc, TcpOutput):
+ * unix/tclUnixChan.c (FileOutputProc, TcpGetOptionProc, TcpOutputProc,
+ (TtyGetOptionProc, TtySetOptionProc):
+ * unix/tclUnixPipe.c (PipeOuputProc):
+ * win/tclWinChan.c (FileOutputProc):
+ * win/tclWinConsole.c (ConsleOutputProc):
+ * win/tclWinPipe.c (PipeOuputProc):
+ * win/tclWinSerial.c (SerialOutputProc, SerialGetOptionProc,
+ (SerialSetOptionProc):
+ * win/tclWinSock.c (TcpGetOptionProc, TcpOutput): Updated channel
+ driver interface according to the guidelines of TIP 27. See also
+ [Bug 500348].
+
+ * doc/CrtChannel.3:
+ * generic/tcl.h:
+ * generic/tclIO.c:
+ * generic/tclIO.h:
+ * generic/tclInt.h:
+ * tools/checkLibraryDoc.tcl:
+ Moved Tcl_EolTranslation enum declaration from generic/tcl.h to
+ generic/tclInt.h (renamed to TclEolTranslation). It is not used
+ anywhere in Tcl's public interface.
+
+2002-01-14 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/GetIndex.3:
+ * doc/WrongNumArgs.3:
+ * generic/tcl.decls (Tcl_GetIndexFromObj, Tcl_GetIndexFromObjStruct,
+ (Tcl_WrongNumArgs):
+ * generic/tclIndexObj.c (Tcl_GetIndexFromObj,Tcl_GetIndexFromObjStruct,
+ (Tcl_WrongNumArgs): Updated APIs in the file generic/tclIndexObj.c
+ according to the guidelines of TIP 27. [Patch 501491]
+ * generic/tclDecls.h: make genstubs
+
+2002-01-11 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/configure.in:
+ * win/configure: Regen.
+ * win/configure.in: Use ${libdir} instead of ${exec_prefix}/lib
+ to properly support the --libdir option to configure. [Bug 489370]
+
+2002-01-11 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * win/tclWinSerial.c (SerialSetOptionProc): Applied patch for [Bug
+ 500348] supplied by Rolf Schroedter <schroedter@users.sf.net>. The
+ function modified the contents of the the 'value' string and now does
+ not do this anymore. This is a followup to the change made on
+ 2001-12-17.
+
+2002-01-11 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc: Removed -GD compiler option. It was intended for
+ future use, but MS is again changing the future at their whim. The
+ D4002 warning was harmless though, but someone using VC .NET logged it
+ as a concern. [Bug 501565]
+
+2002-01-11 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/Makefile.in: Burn Tcl build directory into tcltest executable
+ to avoid crashes caused by ld loading a previously installed version
+ of the tcl shared library. [Bug 218110]
+
+2002-01-10 Don Porter <dgp@users.sourceforge.net>,
+ Kevin Kenny <kennykb@users.sourceforge.net>
+
+ * unix/tclLoadDld.c (TclpLoadFile): syntax error: unbalanced parens.
+ Kevin notes that it's far from clear that this file is ever included
+ in an actual build; Linux without dlopen appears to be a nonexistent
+ configuration.
+
+2002-01-08 Don Porter <dgp@users.sourceforge.net>,
+ Kevin Kenny <kennykb@users.sourceforge.net>
+
+ * doc/StaticPkg.3 (Tcl_StaticPackage):
+ * generic/tcl.decls (Tcl_StaticPackage):
+ * generic/tclDecls.h (Tcl_StaticPackage):
+ * generic/tclInt.decls (TclGuessPackageName):
+ * generic/tclInt.h (TclGuessPackageName):
+ * generic/tclLoad.c (Tcl_StaticPackage):
+ * generic/tclLoadNone.c (TclGuessPackageName):
+ * mac/tclMacLoad.c (TclGuessPackageName):
+ * unix/tclLoadAout.c (TclGuessPackageName):
+ * unix/tclLoadDl.c (TclGuessPackageName):
+ * unix/tclLoadDld.c (TclGuessPackageName):
+ * unix/tclLoadDyld.c (TclGuessPackageName):
+ * unix/tclLoadNext.c (TclGuessPackageName):
+ * unix/tclLoadOSF.c (TclGuessPackageName):
+ * unix/tclLoadShl.c (TclGuessPackageName):
+ * win/tclWinLoad.c (TclGuessPackageName): Updated APIs in the files
+ */tcl*Load*.c according to the guidelines of TIP 27. [Patch 501096]
+
+2002-01-09 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclTest.c (MainLoop):
+ * tests/main.test (Tcl_Main-1.{3,4,5,6}): Corrected some non-portable
+ tests from the new Tcl_Main changes. Thanks to Kevin Kenny.
+
+2002-01-07 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclEvent.c (TclInExit):
+ * generic/tclIOUtil.c (SetFsPathFromAbsoluteNormalized,
+ (SetFsPathFromAny,Tcl_FSNewNativePath,DupFsPathInternalRep):
+ * generic/tclListObj.c (TclLsetList,TclLsetFlat): Added some type
+ casts to satisfy picky compilers.
+
+ * generic/tclMain.c: Bug fix: neglected the NULL case in
+ TclGetStartupScriptFileName(). Broke Tk/wish.
+
+2002-01-05 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/Tcl_Main.3:
+ * generic/tclMain.c: Substantial rewrite and expanded documentation
+ of Tcl_Main to correct a number of bugs and flaws:
+
+ - Interactive Tcl_Main can now enter a main loop, exit that loop and
+ continue interactive operations. The loop may even exit in the
+ midst of interactive command typing without loss of the partial
+ command. [Bugs 486453, 474131]
+ - Tcl_Main now gracefully handles deletion of its master
+ interpreter.
+ - Interactive Tcl_Main can now operate with non-blocking stdin
+ - Interactive Tcl_Main can now detect EOF on stdin even in
+ mid-command. [Bug 491341]
+ - Added VFS-aware internal routines for managing the startup script
+ selection.
+ - Tcl variable 'tcl_interactive' is now linked to C variable 'tty'
+ so that one can disable/enable interactive prompts at the script
+ level when there is no startup script. This is meant for use by
+ the test suite.
+ - Consistent use of the Tcl libraries standard channels as returned
+ by Tcl_GetStdChannel(); as opposed to the channels named 'stdin',
+ 'stdout', and 'stderr' in the master interp, which can be
+ different or unavailable.
+ - Tcl_Main now calls Tcl_Exit() if evaluation of [exit] in the
+ master interpreter returns, assuring Tcl_Main does not return.
+ - Documented Tcl_Main's absence from public stub table
+ - Documented that Tcl_Main does not return.
+ - Documented Tcl variables set by Tcl_Main.
+ - All prompts are done from a single procedure, Prompt.
+ - Use of Tcl_Obj-enabled interfaces everywhere.
+
+ * generic/tclInt.decls (TclGetStartupScriptPath,
+ (TclSetStartupScriptPath): New internal VFS-aware routines for
+ managing the startup script of Tcl_Main.
+ * generic/tclIntDecls.h:
+ * generic/tclStubInit.c: make genstubs
+
+ * generic/tclTest.c (TestsetmainloopCmd,TestexitmainloopCmd,
+ (Tcltest_Init,TestinterpdeleteCmd):
+ * tests/main.test (new): Added new file to test suite that thoroughly
+ tests generic/tclMain.c; added some new test commands for testing
+ Tcl_SetMainLoop().
+
+2002-01-04 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/Alloc.3:
+ * doc/Concat.3:
+ * doc/CrtMathFnc.3:
+ * doc/Hash.3:
+ * doc/Interp.3:
+ * doc/LinkVar.3:
+ * doc/ObjectType.3:
+ * doc/PkgRequire.3:
+ * doc/Preserve.3:
+ * doc/SetResult.3:
+ * doc/SplitList.3:
+ * doc/SplitPath.3:
+ * doc/TCL_MEM_DEBUG.3: Updated documentation to describe the ckalloc,
+ ckfree, ckrealloc, attemptckalloc, and attemptckrealloc macros, and
+ to accurately describe when and how they are used. [Bug 497459]
+
+ * generic/tclThreadJoin.c (TclRememberJoinableThread,TclJoinThread):
+ Replaced Tcl_Alloc and Tcl_Free calls with ckalloc and ckfree so that
+ memory debugging is supported.
+
+2002-01-04 Daniel Steffen <das@users.sourceforge.net>
+
+ * mac/tclMacTime.c (TclpGetTZName): fix for daylight savings TZName bug
+
+2002-01-03 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/FileSystem.3:
+ * generic/tclIOUtil.c: Updated some old uses of "fileName" to
+ new VFS terminology, "pathPtr".
+
+2002-01-03 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/basic.test (basic-39.4): Greatly simplified test while
+ still leaving it so that it crashes when run without the fix to
+ the [foreach] implementation.
+ * generic/tclCmdAH.c (Tcl_ForeachObjCmd): Stopped [Bug 494348] from
+ happening by not trying to be so clever with cacheing; if nothing
+ untoward is happening anyway, the less efficient technique will
+ only add a few instruction cycles (one function call and a few
+ derefs/assigns per list per iteration, with no change in the
+ number of tests) and if something odd *is* going on, the code is
+ now far more robust.
+
+ * tests/basic.test (basic-39.4): Reproducable script from [Bug 494348]
+
+2002-01-02 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/util.test (Wrapper_Tcl_StringMatch,util-5.*): Rewrote so the
+ test is performed with the right internal function since [string
+ match] no longer uses Tcl_StringCaseMatch internally.
+
+ * tests/string.test (string-11.51):
+ * generic/tclUtf.c (Tcl_UniCharCaseMatch):
+ * generic/tclUtil.c (Tcl_StringCaseMatch): Fault with matching
+ case-insensitive non-ASCII patterns containing upper case characters.
+ [Bug 233257]
+
+ ******************************************************************
+ *** CHANGELOG ENTRIES FOR 2001 IN "ChangeLog.2001" ***
+ *** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000" ***
+ *** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" ***
+ ******************************************************************
diff --git a/ChangeLog.2003 b/ChangeLog.2003
new file mode 100644
index 0000000..b12cd2c
--- /dev/null
+++ b/ChangeLog.2003
@@ -0,0 +1,3349 @@
+2003-12-25 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tclWin32Dll.c (DllMain): Add HAVE_NO_SEH blocks in place of
+ __try and __except statements to support gcc builds. This is needed
+ after David's changes on 2003-12-21. [Patch 858493]
+
+2003-12-23 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tclAlloc.c: All uses of 'panic' (the macro) changed to
+ * generic/tclBasic.c: 'Tcl_Panic' (the function). The #define of
+ * generic/tclBinary.c: panic in tcl.h clearly states it is deprecated
+ * generic/tclCkalloc.c: in the comments. [Patch 865264]
+ * generic/tclCmdAH.c:
+ * generic/tclCmdIL.c:
+ * generic/tclCmdMZ.c:
+ * generic/tclCompCmds.c:
+ * generic/tclCompExpr.c:
+ * generic/tclCompile.c:
+ * generic/tclConfig.c:
+ * generic/tclDictObj.c:
+ * generic/tclEncoding.c:
+ * generic/tclEvent.c:
+ * generic/tclExecute.c:
+ * generic/tclHash.c:
+ * generic/tclInterp.c:
+ * generic/tclIO.c:
+ * generic/tclIOCmd.c:
+ * generic/tclIOUtil.c:
+ * generic/tclListObj.c:
+ * generic/tclLiteral.c:
+ * generic/tclNamesp.c:
+ * generic/tclObj.c:
+ * generic/tclParse.c:
+ * generic/tclPathObj.c:
+ * generic/tclPkg.c:
+ * generic/tclPreserve.c:
+ * generic/tclProc.c:
+ * generic/tclStringObj.c:
+ * generic/tclTest.c:
+ * generic/tclThreadAlloc.c:
+ * generic/tclTimer.c:
+ * generic/tclTrace.c:
+ * generic/tclVar.c:
+ * mac/tclMacChan.c:
+ * mac/tclMacOSA.c:
+ * mac/tclMacResource.c:
+ * mac/tclMacSock.c
+ * mac/tclMacThrd.c:
+ * unix/tclUnixChan.c:
+ * unix/tclUnixNotfy.c:
+ * unix/tclUnixThrd.c:
+ * unix/tclXtNotify.c:
+ * win/tclWin32Dll.c:
+ * win/tclWinChan.c:
+ * win/tclWinFCmd.c:
+ * win/tclWinNotify.c:
+ * win/tclWinPipe.c:
+ * win/tclWinSock.c:
+ * win/tclWinThrd.c:
+
+ * generic/tclInt.h: Deprecated use of Tcl_Ckalloc changed to
+ Tcl_Alloc in the TclAllocObjStorage macro.
+
+2003-12-22 David Gravereaux <davygrvy@pobox.com>
+
+ * win/nmakehlp.c:
+ * win/rules.vc: New feature for extensions that use rules.vc. Now
+ reads header files for version strings. No more hard coding
+ TCL_VERSION = 8.5 and having to edit it when you swap cores.
+
+ * win/makefile.vc: VERSION macro now set by reading tcl.h for it.
+
+ * generic/tcl.h: Removed note that makefile.vc needs to have a version
+ number changed.
+
+2003-12-21 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWin32Dll.c: Structured Exception Handling added around
+ Tcl_Finalize called from DllMain's DLL_PROCESS_DETACH. We can't be
+ 100% assured that Tcl is being unloaded by the OS in a stable
+ condition and we need to protect the exit handlers should the stack be
+ in a hosed state. AT&T style assembly for SEH under MinGW has not been
+ added yet. This is a first part change for [Patch 858493]
+
+2003-12-17 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tclBinary.c (DeleteScanNumberCache): fixed crashing bug when
+ numeric scan-value cache contains NULL value.
+
+2003-12-17 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclCmdAH.c:
+ * unix/tclUnixFile.c:
+ * win/tclWinFCmd.c:
+ * tests/fCmd.test:
+ * tests/fileSystem.test:
+ * doc/file.n: final fix to support for relative links and its
+ implications on normalization and other parts of the filesystem code.
+ Fixes [Bug 859251] and some Windows problems with recursive file
+ delete/copy and symbolic links.
+
+2003-12-17 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclPathObj.c:
+ * tests/fileSystem.test: fix and tests for [Bug 860402] in new file
+ normalization code.
+
+2003-12-17 Zoran Vasiljevic <zv@archiware.com>
+
+ * generic/tclIOUtil.c: fixed 2 memory (object) leaks. [Bug 839519]
+
+ * generic/tclPathObj.c: fixed Tcl_FSGetTranslatedPath to always return
+ properly refcounted path object. [Bug 861515]
+
+2003-12-16 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/fCmd.test: marking fCmd-9.14.2, as nonPortable, since on
+ Solaris one can change the name of the current directory with 'file
+ rename'.
+ * doc/FileSystem.3: clarified documentation on ownership of return
+ objects/strings of some Tcl_FS* calls.
+
+2003-12-16 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclThreadAlloc.c (binfo): Made variable file-local.
+
+2003-12-15 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tcl.rc:
+ * win/tclsh.rc: Slight modification to the STRINGIFY macro to support
+ Borland's rc tool.
+
+ * win/tclWinFile.c (TclpUtime) : utimbuf struct not a problem with
+ Borland.
+
+ * win/tclWinTime.c (TclpGetDate) : Borland's localtime() has a slight
+ behavioral difference.
+
+ From Helmut Giese <hgiese@ratiosoft.com> [Patch 758097].
+
+2003-12-14 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tclInt.decls: commented-out entry for TclpCheckStackSpace,
+ removing it from the Stubs table. It's already declared in tclInt.h
+ and labeled as a function that is not to be exported. Regened tables.
+
+2003-12-14 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclCmdMZ.c (Tcl_SwitchObjCmd): TIP#75 Implementation
+ * tests/switch.test: Can now get submatch information when using
+ * doc/switch.n: -regexp matching in [switch].
+
+2003-12-14 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclPathObj.c: complete rewrite of generic file normalization
+ code to cope with links followed by '..'. [Bug 849514], and parts of
+ [Bug 859251]
+
+2003-12-12 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinChan.c: Win32's SetFilePointer() takes LONGs not DWORDs (a
+ signed/unsigned mismatch). Redid local vars to avoid all casting
+ except where truly required.
+
+2003-12-12 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclCmdAH.c: fix to normalization of non-existent user name
+ ('file normalize ~nobody') [Bug 858937]
+ * doc/file.n: clarify behaviour of 'file link' when the target is not
+ an absolute path.
+ * doc/filename.n: correct documentation to say that Windows Tcl does
+ handle '~user', for recent Windows releases, and clarified distinction
+ between MacOS 'classic' and MacOS X.
+ * doc/glob.n: clarification of glob's behaviour when returning
+ filenames starting with a '~'.
+
+ * tests/fileSystem.test:
+ * tests/fileName.test: new tests added for the normalization problem
+ above and other recentlt reported issues.
+
+ * win/tclWinFile.c: corrected unclear comments
+
+ * unix/tclUnixFile.c: allow creation of relative links. [Bug 833713]
+
+2003-12-11 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinSock.c (SocketThreadExitHandler) : added a TerminateThread
+ fallback just in case the socket handler thread is really in a paused
+ state. This can happen when Tcl is being unloaded by the OS from an
+ exception handler. See MSDN docs on DllMain, it states this behavior.
+
+2003-12-09 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/configure:
+ * unix/tcl.m4: updated OpenBSD build configuration based on
+ [Patch #775246] (cassoff)
+
+2003-12-09 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * unix/tclUnixPort.h: #ifdef'd out declarations of errno which are
+ * tools/man2tcl.c: known to cause problems with recent glibc.
+ [Bug 852369]
+
+2003-12-09 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * win/tclWinFile.c: fix to NT file permissions code [Bug 855923]
+ * tests/winFile.test: added tests for NT file permissions - patch and
+ test scripts supplied by Benny.
+
+ * tests/winFCmd.test: fixed one test for when not running in C:/
+
+2003-12-02 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclBinary.c (DeleteScanNumberCache, ScanNumber): Made the
+ numeric scan-value cache have proper references to the objects within
+ it so strange patterns of writes won't cause references to freed
+ objects. Thanks to Paul Obermeir for the report. [Bug 851747]
+
+2003-12-01 Miguel Sofer <msofer@users.sf.net>
+
+ * doc/lset.n: fix typo [Bug 852224]
+
+2003-11-24 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclParse.c: Corrected faulty check for trailing white
+ space in {expand} parsing. Thanks Andreas Leitgeb. [Bug 848262]
+ * tests/parse.test: New tests for the bug.
+
+2003-11-24 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclPathObj.c: fix to [Bug 845778] - Infinite recursion on
+ [cd] (Windows only bug), for which new tests have just been added.
+
+2003-11-21 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/winFCmd.test (winFCmd-16.10,11): Merged new tests from
+ core-8-4-branch.
+
+2003-11-20 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclVar.c: fix flag bit collision between LOOKUP_FOR_UPVAR
+ and TCL_PARSE_PART1 (deprecated) [Bug 835020]
+
+2003-11-19 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/compile.test (compile-16.22.0): Improved test for the recent
+ fix for Bug 845412.
+
+2003-11-19 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclCompile.c (TclCompileScript): Added a guard for the
+ expansion code so that long non-expanding commands don't get expansion
+ infrastructure inserted in them, especially when that infrastructure
+ isn't initialised. [Bug 845412]
+
+2003-11-18 David Gravereaux <davygrvy@pobox.com>
+
+ * contrib/djgpp/Makefile: Changes from Victor Wagner
+ * contrib/djgpp/langinfo.c (new): <vitus@45.free.net> for better
+ * contrib/djgpp/langinfo.h (new): DJGPP support.
+ * unix/tclUnixInit.c: .
+ * unix/tclUnixChan.c: .
+ * unix/tclUnixFCmd.c: .
+
+2003-11-17 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/reg.test: Added tests for [Bugs 230589, 504785, 505048, 840258]
+ recently fixed by 2003-11-15 commit to regcomp.c by Pavel Goran. His
+ notes on the fix: This bug results from an error in code that splits
+ states into "progress" and "no-progress" ones. This error causes an
+ interesting situation with the pre-collected single-linked list of
+ states to be splitted: many items were added to the list, but only
+ several of them are accessible from the list beginning, since the
+ "tmp" member of struct state (which is used here to hold a pointer to
+ the next list item) gets overwritten, which results in a "looped"
+ chain. As a result, not all of states are splitted, and one state is
+ splitted two times, causing incorrect "no-progress" flag values.
+
+2003-11-16 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclExecute.c (TclExecuteByteCode): Make sure that
+ Tcl_AsyncInvoke is called regularly when processing bytecodes.
+ * generic/tclTest.c (AsyncThreadProc, TestasyncCmd): Extended testing
+ harness to send an asynchronous marking without relying on UNIX
+ signals.
+ * tests/async.test (async-4.*): Tests to check that async events are
+ handled by the bytecode core. [Bug 746722]
+
+2003-11-15 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclTest.c (TestHashSystemHashCmd): Removed 'const' modifier
+ from hash type structure; it should be const and the hash code assumes
+ it behaves like const, but that's not how the API is defined. Like
+ this, we are following in the same footsteps as Tcl_RegisterObjType()
+ which has the same conditions on its argument. Stops VC++5.2 warning.
+ [Bug 842511]
+
+2003-11-14 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclHash.c (Tcl_DeleteHashTable,Tcl_HashStats,RebuildTable):
+ * generic/tclTest.c (TestHashSystemHashCmd): TIP#138 implementation,
+ * tests/misc.test: plus a new chunk of stuff to test the hash
+ functions more thoroughly in the test suite.
+ [Patch 731356, modified]
+
+ * doc/Tcl.n: Updated Tcl version number and changebars.
+
+2003-11-14 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/ParseCmd.3: Implementation of TIP 157. Adds recognition
+ * doc/Tcl.n: of the new leading {expand} syntax on words.
+ * generic/tcl.h: Parses such words as the new Tcl_Token type
+ * generic/tclBasic.c: TCL_TOKEN_EXPAND_WORD. Updated Tcl_EvalEx and
+ * generic/tclCompile.c: the bytecode compiler/execution engine to
+ * generic/tclCompile.h: recognize the new token type. New opcodes
+ * generic/tclExecute.c: INST_LIST_VERIFY and INST_INVOKE_EXP and a new
+ * generic/tclParse.c: operand type OPERAND_ULIST1 are defined. Docs
+ * generic/tclTest.c: and tests are included.
+ * tests/basic.test:
+ * tests/compile.test:
+ * tests/parse.test:
+
+ * library/auto.tcl: Replaced several [eval]s used to perform
+ * library/package.tcl: argument expansion with the new syntax. In the
+ * library/safe.tcl: test files lindex.test and lset.test, replaced
+ * tests/cmdInfo.test: use of [eval] to force direct string
+ * tests/encoding.test: evaluation with use of [testevalex] which more
+ * tests/execute.test: directly and robustly serves the same purpose.
+ * tests/fCmd.test:
+ * tests/http.test:
+ * tests/init.test:
+ * tests/interp.test:
+ * tests/io.test:
+ * tests/ioUtil.test:
+ * tests/iogt.test:
+ * tests/lindex.test:
+ * tests/lset.test:
+ * tests/namespace-old.test:
+ * tests/namespace.test:
+ * tests/pkg.test:
+ * tests/pkgMkIndex.test:
+ * tests/proc.test:
+ * tests/reg.test:
+ * tests/trace.test:
+ * tests/upvar.test:
+ * tests/winConsole.test:
+ * tests/winFCmd.test:
+
+2003-11-12 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/cmdMZ.test (cmdMZ-1.4): change to nonPortable as more systems
+ are using permissions caching, and this isn't really a Tcl controlled
+ issue.
+
+2003-11-11 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/configure:
+ * unix/tcl.m4: improve AIX --enable-64bit handling
+ remove -D__NO_STRING_INLINES -D__NO_MATH_INLINES from CFLAGS_OPTIMIZE
+ on Linux. Make default opt -O2 (was -O).
+
+2003-11-11 David Gravereaux <davygrvy@pobox.com>
+
+ * contrib/djgpp/Makefile: Suggested changes from vitus@45.free.net
+ (Victor Wagner)
+
+ * unix/tclUnixPort.h: added socklen_t typedef for DJGPP
+
+2003-11-10 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/tclUnixInit.c (TclpInitLibraryPath):
+ * win/tclWinInit.c (TclpInitLibraryPath): Fix for [Bug 832657]
+ that should not run afoul of startup constraints.
+
+ * library/dde/pkgIndex.tcl: Added safeguards so that registry and
+ * library/reg/pkgIndex.tcl: dde packages are not offered on
+ * win/tclWinDde.c: non-Windows platforms. Bumped to
+ * win/tclWinReg.c: registry 1.1.3 and dde 1.3.
+ * win/Makefile.in:
+ * win/configure.in:
+ * win/makefile.bc:
+ * win/makefile.vc:
+
+ * win/configure: autoconf (2.57)
+
+2003-11-10 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/cmdIL.test: Stopped cmdIL-5.5 from stomping over the test
+ command, and updated the tests to use some tcltest2 features in
+ relation to cleanup. [Bug 838384]
+
+2003-11-10 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclCmdAH.c:
+ * tests/fCmd.test: fix to misleading error message in 'file link'.
+ [Bug 836208]
+
+2003-11-07 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclIOUtil.c: fix to compiler warning/error with some
+ compilers. [Bug 835918]
+
+2003-11-07 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Makefile: optimized builds define NDEBUG to turn off
+ ThreadAlloc range checking.
+
+2003-11-05 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/unixInit.test (unixInit-2.10): New test to expose [Bug 832657]
+ failure of TclpInitLibraryPath() to properly handle .. in the path
+ of the executable.
+
+2003-11-04 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Makefile: added 'test' target.
+
+2003-11-03 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclIOUtil.c
+ * generic/tclInt.h: added comments and re-arranged code to clarify
+ distinction between Tcl_LoadHandle, ClientData for 'load'ed code, and
+ point out limitations of the design introduced with Tcl 8.4.
+
+ * unix/tclUnixFile.c: fix to memory leak
+
+ * generic/tclCmdIL.c: removed warning on Windows.
+
+2003-11-01 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclCmdIL.c (Tcl_LrepeatObjCmd): Check for sensible list
+ lengths and allow for soft failure of the memory subsystem in the
+ [lconcat] command [Bug 829027]. Uses direct list creation to avoid
+ extra copies when working near the limit of available memory. Also
+ reorganized to encourage optimizing compilers to optimize heavily.
+ * generic/tclListObj.c (TclNewListObjDirect): New list constructor
+ that does not copy the array of objects. Useful for creating
+ potentially very large lists or where you are about to throw away the
+ array argument which is being used in its entirety.
+
+2003-10-28 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c (NEXT_INST macros): replaced macro variable
+ "result" by "resultHandling" to avoid confusion.
+
+2003-10-23 Andreas Kupries <andreask@activestate.com>
+
+ * unix/tclUnixChan.c (Tcl_MakeFileChannel): Applied [Patch 813606]
+ fixing [Bug 813087]. Detection of sockets was off for Mac OS X which
+ implements pipes as local sockets. The new code ensures that only IP
+ sockets are detected as such.
+
+ * win/tclWinSock.c (TcpWatchProc): Watch for FD_CLOSE too when asked
+ for writable events by the generic layer.
+ (SocketEventProc): Generate a writable event too when a close is
+ detected.
+
+ Together the changes fix [Bug 599468].
+
+2003-10-23 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/resource.test:
+ * mac/tclMacResource.c: fix to resource freeing problem in 'resource'
+ command reported by Bernard Desgraupes.
+
+ * doc/FileSystem.3: updated documentation for 'glob' fix on 2003-10-13
+ below
+
+2003-10-22 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclCmdAH.c (Tcl_FileObjCmd): Changed FILE_ prefix to FCMD_
+ to stop symbol/#def clashes on Cygwin/Mingw32 on NT. [Bug 822528]
+
+2003-10-21 Daniel Steffen <das@users.sourceforge.net>
+
+ * tools/tcltk-man2html.tcl: fixed incorrect html generated for
+ .IP/.TP lists, now use <DL><DT>...<DD>...<P><DT>...<DD>...</DL>
+ instead of illegal <DL><P><DT>...<DD>...<P><DT>...<DD>...</DL>.
+ Added skipping of directives directly after .TP to avoid them being
+ used as item descriptions, e.g. .TP\n.VS in clock.n.
+
+2003-10-21 Andreas Kupries <andreask@pliers.activestate.com>
+
+ * win/tclWinPipe.c (BuildCommandLine): Applied the patch coming with
+ [Bug 805605] to the code, fixing the incorrect use of ispace noted by
+ Ronald Dauster <ronaldd@users.sourceforge.net>.
+
+2003-10-20 Kevin B. Kenny <kennykb@users.sourceforge.net>
+
+ * doc/msgcat.n:
+ * library/msgcat/msgcat.tcl (mclocale,mcload):
+ * tools/tcl.wse.in:
+ * unix/Makefile.in: Implementation of TIP#156, add a "root locale"
+ * win/makefile.bc: to the 'msgcat' package. Advanced msgcat
+ * win/Makefile.in: version number to 1.4
+ * win/Makefile.vc:
+
+2003-10-15 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclCmdIL.c (SortInfo,etc): Reorganized so that SortInfo
+ carries an array of integer indices instead of a Tcl list. This nips
+ shimmering problems in the bud and simplifies SelectObjFromSublist at
+ the cost of making setup slightly more complex. [Bug 823768]
+
+2003-10-14 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclAppInit.c (sigHandler): Punt gracefully if exitToken has
+ already been destroyed.
+
+2003-10-14 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclCmdMZ.c:
+ * tests/regexp.test: fix to [Bug 823524] in regsub; added three new
+ tests.
+
+2003-10-14 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c (TclAppendObjToErrorInfo): New internal routine
+ that appends a Tcl_Obj to the errorInfo, saving the caller the trouble
+ of extracting the string rep.
+
+ * generic/tclStringObj.c (TclAppendLimitedToObj): New internal
+ routine that supports truncated appends with optional ellipsis marking.
+ This single routine supports UTF-8-safe truncated appends needed in
+ several places throughout the Tcl source code, mostly for error and
+ stack messages. Clean fix for [Bug 760872].
+
+ * generic/tclInt.h: Declarations for new internal routines.
+
+ * generic/tclCmdMZ.c: Updated callers to use the new routines.
+ * generic/tclCompExpr.c:
+ * generic/tclCompile.c:
+ * generic/tclExecute.c:
+ * generic/tclIOUtil.c:
+ * generic/tclNamesp.c:
+ * generic/tclObj.c:
+ * generic/tclParseExpr.c:
+ * generic/tclProc.c:
+ * generic/tclStringObj.c:
+ * mac/tclMacResource.c:
+
+ * library/init.tcl: Updated ::errorInfo cleanup in [unknown] to
+ reflect slight modifications to Tcl_LogCommandInfo(). Corrects failing
+ init-4.* tests.
+
+2003-10-14 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ TIP#127 IMPLEMENTATION FROM JOE MICHAEL SCHLENKER
+
+ * generic/tclCmdIL.c (SelectObjFromSublist): Element selection engine.
+ * generic/tclCmdIL.c (Tcl_LsearchObjCmd, Tcl_LsortObjCmd):
+ * tests/lsearch.test: Set up and use of element selection engine,
+ * tests/cmdIL.test: plus tests and documentation.
+ * doc/lsearch.n: Based on [Patch 693836]
+ * doc/lsort.n:
+
+2003-10-13 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tcl.h:
+ * generic/tclFileName.c:
+ * generic/tclIOUtil.c:
+ * generic/tclPathObj.c:
+ * generic/tclTest.c:
+ * mac/tclMacFile.c:
+ * tests/fileName.test: better tests for [Bug 813273]
+ * unix/tclUnixFCmd.c:
+ * unix/tclUnixFile.c:
+ * win/tclWin32Dll.c:
+ * win/tclWinFCmd.c:
+ * win/tclWinFile.c:
+ * win/tclFileInt.h:
+
+ Fixed [Bug 800106] in which 'glob' was incapable of merging the
+ results of a directory listing (real or virtual) and any virtual
+ filesystem mountpoints in that directory (the latter were ignored).
+ This meant boundaries between different filesystems were not seamless
+ (e.g. 'glob */*' across a filesystem boundary was wrong). Added new
+ entry to Tcl_GlobTypeData in a totally backwards compatible way. To
+ allow listing of mounts, registered filesystems must support the
+ 'TCL_GLOB_TYPE_MOUNT' flag. If this is not supported (e.g. in tclvfs
+ 1.2) then mounts will simply not be listed for that filesystem.
+
+ Fixed [Bug 749876] 'file writable/readable/etc' (NativeAccess) using
+ correct permission checking code for Windows NT/2000/XP where more
+ complex user-based security/access priveleges are available,
+ particularly on shared volumes. The performance impact of this extra
+ checking will need further investigation. Note: Win 95,98,ME have no
+ support for this.
+
+ Also made better use of normalized rather than translated paths in the
+ platform specific code.
+
+2003-10-12 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tclUnixTest.c (TestalarmCmd): don't bother checking return
+ value of alarm. [Bug #664755] (english)
+
+2003-10-09 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/makefile.vc: Applied patches for bug #801467 by Joe Mistachkin
+ * win/tclAppInit.c: to fix incompatible TCL_MEM_DEBUG handling in
+ * generic/tclObj.c: Win32 VC builds.
+
+2003-10-08 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c: Save and restore the iPtr->flag bits that
+ control the state of errorCode and errorInfo management when calling
+ "leave" execution traces, so that all error information of the traced
+ command is still available whether traced or not. [Bug 760947]
+ Thanks to Yahalom Emet.
+
+2003-10-08 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclTest.c (TestNumUtfCharsCmd): Command to allow finer
+ access to Tcl_NumUtfChars for testing.
+ * generic/tclUtf.c (Tcl_NumUtfChars): Corrected string length
+ determining when the length parameter is negative; the terminator is a
+ zero byte, not (necessarily) a \u0000 character. [Bug 769812]
+
+2003-10-07 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/cmdAH.test:
+ * tests/exec.test: Corrected temporary file management
+ * tests/fileSystem.test: issues uncovered by -debug 1 test
+ * tests/io.test: operations. Also backported some
+ * tests/ioCmd.test: other fixes from the HEAD.
+ * tests/main.test:
+ * tests/pid.test: [Bugs 675605, 675655, 675659]
+ * tests/socket.test:
+ * tests/source.test:
+
+ * tests/fCmd.test: Run tests with the [temporaryDirectory] as the
+ current directory, so that tests can depend on ability to write files.
+ [Bug 575837]
+
+ * doc/OpenFileChnl.3: Updated Tcl_Tell and Tcl_Seek documentation to
+ reflect that they now return Tcl_WideInt (TIP 72). [Bug 787537]
+
+ * tests/io.test: Corrected several tests that failed when paths
+ * tests/ioCmd.test: included regexp-special chars. [Bug 775394]
+
+2003-10-06 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/configure:
+ * win/tcl.m4: removed incorrect checks for existence of optimization.
+ TCL_CFG_OPTIMIZED is now defined whenever the user does not build with
+ --enable-symbols.
+
+2003-10-06 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/regexp.test: Matched [makeFile] with [removeFile].
+ * tests/regexpComp.test: [Bug 675652]
+
+ * tests/fCmd.test (fCmd-8.2): Test only that tilde-substitution
+ happens, not for any particular result. [Bug 685991]
+
+ * unix/tcl.m4 (SC_PATH_TCLCONFIG): Corrected search path so that
+ alpha and beta releases of Tcl are not favored. [Bug 608698]
+
+ * tests/reg.test: Corrected duplicate test names.
+ * tests/resource.test: [Bugs 710370, 710358]
+ * tests/dict.test:
+
+ * tests/dict.test: Updated [package require tcltest] lines to
+ * tests/fileSystem.test: indiciate that these test files
+ * tests/lrepeat.test: use features of tcltest 2. [Bug 706114]
+ * tests/notify.test:
+ * tests/parseExpr.test:
+ * tests/unixNotfy.test:
+ * tests/winDde.test:
+
+2003-10-04 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c (TEBC):
+ * tests/execute.test (execute-8.2): fix for [Bug 816641] - faulty
+ execution and catch stack management.
+
+2003-10-03 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c: Fixed error in ref count management of command
+ * generic/tclCmdMZ.c: and execution traces that caused access to
+ freed memory in trace-32.1. [Bug 811483]
+
+2003-10-02 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclTrace.c: Corrected comingling of introspection results of
+ [trace info command] and [trace info execution]. [Bug 807243]
+ Thanks to Mark Saye.
+
+2003-10-01 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Makefile: fixed redo prebinding bug when DESTDIR="".
+ * mac/tclMacResource.c: fixed possible NULL dereference (bdesgraupes).
+
+2003-09-29 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclPathObj.c:
+ * tests/fileName.test: fix to inconsistent handling of backslash
+ path separators on Windows in 'file join' [Bug 813273]
+
+2003-09-29 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclPathObj.c (TclNativePathInFilesystem,TclFSGetPathType):
+ * generic/tclIOUtil.c (TclNativeDupInternalRep,TclGetPathType): Rename
+ to make sure function names won't interfere with other non-Tcl code
+ (reported by George Staplin)
+
+ TIP#121 IMPLEMENTATION FROM JOE MISTACHKIN
+
+ * generic/tclEvent.c (Tcl_SetExitProc,Tcl_Exit): Implementation of
+ application exit handler scheme.
+ * generic/tcl.decls (Tcl_SetExitProc): Public declaration.
+ * doc/Exit.3: Documentation of new API function.
+
+ TIP#112 IMPLEMENTATION
+
+ * generic/tclNamesp.c: Core of implementation.
+ * generic/tclInt.h (Namespace,TclInvalidateNsCmdLookup): Add command
+ list epoch counter and list of ensembles to namespace structure, and
+ define a macro to ease update of the epoch counter.
+ * generic/tclBasic.c (Tcl_CreateObjCommand,etc.): Update epoch counter
+ when list of commands in a namespace changes.
+ * generic/tclObj.c (TclInitObjSubsystem): Register ensemble subcommand
+ type.
+ * tests/namespace.test (42.1-47.6): Tests.
+ * doc/namespace.n: Documentation.
+
+ * library/http/http.tcl (geturl): Correctly check the type of
+ boolean-valued options. [Bug 811170]
+
+ * unix/tcl.m4 (SC_ENABLE_FRAMEWORK): Added note to make it clearer
+ that this is an OSX feature, not a general Unix feature. [Bug 619440]
+
+2003-09-28 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinPipe.c: The windows port of expect can call
+ TclWinAddProcess before any of the other pipe functions. Added a
+ missing PipeInit() call to make sure the initialization happens.
+
+2003-09-25 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Makefile: ensure SYMROOT exists if OBJROOT is overridden on
+ command line. Replaced explict use of /usr/bin by ${BINDIR}.
+
+2003-09-24 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * library/package.tcl (tcl::MacPkgUnknown, tcl::MacOSXPkgUnknown):
+ Minor performance tweaks to reduce the number of [file] invocations.
+ Meant to improve startup times, at least a little bit. (The generic
+ equivalent patch was applied on 2003-02-21).
+
+2003-09-24 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * trace.test: removed 'knownBug' from a test which doesn't illustrate
+ a bug, just a bad test.
+
+2003-09-23 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c:
+ * generic/tclInt.h: changed the evaluation-stack addressing mode, from
+ array-style to pointer-style; the catch stack and evaluation stack are
+ now contiguous in memory. [Patch 457449]
+
+2003-09-23 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/trace.test (trace-31,32-*): Added tests for [Bug 807243] and
+ [Bug 811483].
+
+ * library/init.tcl (auto_load, auto_import): Expanded Eric Melski's
+ 2000-01-28 fix for [Bug 218871] to all potentially troubled uses of
+ [info commands] on input data, where glob-special characters could
+ cause problems.
+
+2003-09-20 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/expr.test (expr-23.4): Prevented accidental wrapping round of
+ exponential operation; it isn't portable, and not what I intended to
+ test either. [Bug 808244]
+
+2003-09-19 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c: adding (DE)CACHE_STACK_INFO() pairs to protect
+ all calls that may cause traces on ::errorInfo or ::errorCode to
+ corrupt the stack. [Bug 804681]
+
+2003-09-17 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tclPathObj.c: fix to test-suite problem introduced by the bug fix
+ below. No problem in ordinary code, just test suite code which
+ manually adjusts tclPlatform. [Bug 808247]
+
+2003-09-16 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * doc/filename.n: documentation of Windows-specific feature as
+ discussed in [Bug 541989]
+ * generic/tclPathObj.c: fix for normalization of volume-relative paths
+ [Bug 767834]
+ * tests/winFCmd.test: new tests for both of the above.
+ * tests/cmdAH.test: fix for AFS problem in test suite [Bug 748960]
+
+2003-09-13 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ TIP#123 IMPLEMENTATION BASED ON WORK BY ARJEN MARKUS
+
+ * generic/tclCompile.h (INST_EXPON): Implementation of
+ * generic/tclCompile.c (tclInstructionTable): exponential operator.
+ * generic/tclCompExpr.c (operatorTable):
+ * generic/tclParseExpr.c (ParseExponentialExpr, GetLexeme):
+ * generic/tclExecute.c (TclExecuteByteCode, ExponWide, ExponLong):
+ (IllegalExprOperandType):
+ * tests/expr.test:
+ * tests/compExpr-old.test:
+ * doc/expr.n:
+
+2003-09-10 Don Porter <dgp@users.sourceforge.net>
+
+ * library/opt/optparse.tcl: Latest revisions caused [OptGuessType]
+ to guess "int" instead of "string" for empty strings. Missed the
+ required "-strict" option to [string is]. Thanks to Revar Desmera.
+ [Bug 803968]
+
+2003-09-08 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinLoad.c (TclpDlopen): Changed the error message for
+ ERROR_PROC_NOT_FOUND to be a bit more helpful in giving us clues.
+ "can't find specified procedure" means a function in the import table,
+ for implicit loading, couldn't be resolved and that's why the load
+ failed.
+
+2003-09-04 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/Tcl_Main.3:
+ * doc/FileSystem.3: Implementation of
+ * doc/source.n: TIPs 137/151. Adds a
+ * doc/tclsh.1: -encoding option to
+ * generic/tcl.decls: the [source] command
+ * generic/tclCmdMZ.c (Tcl_SourceObjCmd): and a new C routine,
+ * generic/tclIOUtil.c (Tcl_FSEvalFileEx): Tcl_FSEvalFileEx(),
+ * generic/tclMain.c (Tcl_Main): that provides C access
+ * mac/tclMacResource.c (Tcl_MacSourceObjCmd): to the same function.
+ * tests/cmdMZ.test: Also adds command line
+ * tests/main.test: option handling in Tcl_Main() so that tclsh
+ * tests/source.test: and other apps built on Tcl_Main() respect a
+ -encoding command line option before a script filename. Docs and tests
+ updated as well. [Patch 742683]
+ This is a ***POTENTIAL INCOMPATIBILITY*** only for those C programs
+ that embed Tcl, build on Tcl_Main(), and make use of Tcl_Main's former
+ ability to pass a leading "-encoding" option to interactive shell
+ operations.
+
+ * generic/tclInt.decls: Added internal stub
+ * generic/tclMain.c (Tcl*StartupScript*): table entries for two
+ new functions Tcl_SetStartupScript() and Tcl_GetStartupScript() that
+ set/get the path and encoding for the startup script to be evaluated
+ by either Tcl_Main() or Tk_Main(). Given public names in anticipation
+ of their exposure by a followup TIP.
+
+ * generic/tclDecls.h: make genstubs
+ * generic/tclIntDecls.h:
+ * generic/tclStubInit.c:
+
+2003-09-04 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/SplitList.3: Implementation of TIP 148. Fixes [Bug 489537].
+ * generic/tcl.h: Updated Tcl_ConvertCountedElement() to quote
+ * generic/tclUtil.c: the leading "#" character of all list elements
+ unless the TCL_DONT_QUOTE_HASH flag is passed in.
+
+ * generic/tclDictObj.c: Updated Tcl_ConvertCountedElement() callers
+ * generic/tclListObj.c: to pass in the TCL_DONT_QUOTE_HASH flags
+ * generic/tclResult.c: when appropriate.
+
+2003-08-31 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/return.n: Updated [return] docs to cover new TIP 90 features.
+
+ * doc/break.n: Added SEE ALSO references to return.n
+ * doc/continue.n:
+
+2003-09-01 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/Namespace.3: Basic documentation for the TIP#139 functions. This
+ will need improving, but the basic bits are there at least.
+
+2003-08-31 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/catch.n: Updated [catch] docs to cover new TIP 90 features.
+
+2003-08-29 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCmdAH.c: Corrected bug in TIP 90 implementation where
+ * tests/cmdMZ.test: the default -errorcode NONE value was not
+ copied into the return options dictionary. This correction modified
+ one test result.
+
+2003-08-27 David Gravereaux <davygrvy@pobox.com>
+
+ * compat/strftime.c (_fmt): Removed syst array intializer that
+ couldn't take variables within it under the watcom compiler:
+ 'Initializers must be constant'. I believe Borland has this strictness
+ as well. VC++ must be non-standard about this.
+
+ Changed Win32 platform #ifdef from 'WIN32' to '__WIN32__' as this is
+ the correct one to use across the Tcl sources. Even though we do force
+ it in tcl.h, the true parent one is __WIN32__.
+
+ Added missing CONST'ification usage to match prototype listed in
+ tclInt.decls.
+
+ * win/tclWinPort.h: Added a block for OpenWatcom adjustments that
+ fixes 1) the same issue Mo did for MinGW lack of missing LPFN_*
+ typedefs in their WINE derived <winsock2.h> and 2) The need to be
+ strict about how the char type needs to be signed by default.
+
+ * win/tclWinSock.c: Added OpenWatcom to the commentary about the
+ #ifdef HAVE_NO_LPFN_DECLS block.
+
+ * win/tclWinTime.c: Changed use of '_timezone' to 'timezone' as this
+ difference is already adjusted for in tclWinPort.h. Removed
+ unreferenced posixEpoch file-scope global.
+
+ * win/tclWinFile.c (WinReadLinkDirectory): Fix for 'Initializers must
+ be constant' with the driveSpec array using OpenWatcom.
+
+2003-08-27 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclUtil.c: Corrected [Bug 411825] and other bugs in
+ TclNeedSpace() where non-breaking space (\u00A0) and backslash-escaped
+ spaces were handled incorrectly.
+ * tests/util.test: Added new tests util-8.[2-6].
+
+2003-08-26 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tcl.h: Added some support for the LCC-Win32 compiler.
+ Unfortunetly, this compiler has a bug in its preprocessor and can't
+ build Tcl even with this minor patch. Also added some support for the
+ OpenWatcom compiler. A new win/makefile.wc to follow soon.
+
+2003-08-25 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tools/genStubs.tcl (genStubs::makeDecl): A more subtle way of
+ generating stubbed declarations allows us to have declarations of a
+ function in multiple interfaces simultaneously.
+
+ * generic/tcl.decls: Duplicated some namespace declarations from
+ tclInt.decls here, as mandated by TIP #139. This is OK since the
+ declarations match and will end up using the declarations in the
+ public code from now on because of #include ordering. Keeping the old
+ declarations in tclInt.decls; there's no need to gratuitously break
+ compatability for those extensions which are already clients of the
+ namespace code.
+
+2003-08-23 Zoran Vasiljevic <zoran@archiwrae.com>
+
+ * generic/tclIOUtil.c: merged fixes for thread-unsafe handling of
+ filesystem records [Bug 753315]. This also fixed the [Bug 788780]
+ * generic/tclPathObj.c: merged fixes for thread-unsafe handling of
+ filesystem records. [Bug 753315]
+
+ * generic/tclFileSystem.h: merged fixes for thread-unsafe handling of
+ filesystem records. [Bug 753315]
+
+2003-08-19 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tclWinSerial.c (SerialErrorStr): Fixed a syntax error created in
+ the previous code cleanup.
+
+2003-08-19 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * win/tclWinSerial.c: Adjusted commenting and spacing usage to follow
+ the principles of the Style Guide better.
+
+2003-08-18 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/configure: Regen.
+ * win/tcl.m4 (SC_ENABLE_SYMBOLS): Use test instead of -eq, which does
+ not work. [Bug 781109]
+
+2003-08-13 Chengye Mao <chengye.geo@yahoo.com>
+
+ * win/tclWinPipe.c: fixed a bug in BuildCommandLine. This bug built a
+ command line with a missing space between tclpipe.dll and the
+ following arguments. It caused error in Windows 98 when exec
+ command.com (e.g. dir). [Bug 789040]
+
+2003-08-11 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ TIP #136 IMPLEMENTATION from Simon Geard <simon.geard@ntlworld.com>
+ * generic/tclCmdIL.c (Tcl_LrepeatObjCmd): Adapted version of Simon's
+ * doc/lrepeat.n: patch, updated to the HEAD
+ * tests/lrepeat.test: and matching the core style.
+ * generic/tclBasic.c (buildIntCmds): Splice into core.
+ * generic/tclInt.h:
+ * doc/list.n: Cross-reference.
+
+2003-08-06 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tclWinInit.c: recognize amd64 and ia32_on_win64 cpus.
+
+2003-08-06 Don Porter <dgp@users.sourceforge.net>
+
+ * library/msgcat/msgcat.tcl: Added escape so that non-Windows
+ * library/msgcat/pkgIndex.tcl: platforms do not try to use the
+ registry package. This can save a costly and pointless package search.
+ Bumped to 1.3.1. Thanks to Dave Bodenstab. [Bug 781609]
+
+2003-08-05 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c (INST_INVOKE, INST_EVAL, INST_PUSH_RESULT):
+ added a Tcl_ResetResult(interp) at each point where the interp's
+ result is pushed onto the stack, to avoid keeping an extra reference
+ that may cause costly Tcl_Obj duplication. Detected by Franco Violi,
+ analyzed by Peter Spjuth and Donal Fellows. [Bug 781585]
+
+2003-07-28 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * doc/FileSystem.3:
+ * doc/Translate.3: better documentation of Tcl_TranslateFileName and
+ related functions. [Bug 775220]
+
+2003-07-24 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tcl.h: Revert change made on 2003-07-21 since it made the
+ sizeof(Tcl_Obj) different for regular vs mem debug builds.
+ * generic/tclInt.h: Define TclDecrRefCount in terms of
+ Tcl_DbDecrRefCount which removes one layer of inderection.
+ * generic/tclObj.c (TclDbInitNewObj, Tcl_DbIncrRefCount,
+ (Tcl_DbDecrRefCount, Tcl_DbIsShared): Define ThreadSpecificData that
+ contains a hashtable. The table is used to ensure that a Tcl_Obj is
+ only acted upon in the thread that allocated it. This checking code is
+ enabled only when mem debug and threads are enabled.
+
+2003-07-24 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/async.test: Added several tests that demonstrate [Bug
+ * tests/basic.test: 489537], Tcl's longstanding failure to
+ * tests/dict.test: properly quote any leading '#' character when
+ * tests/dstring.test: generating the string rep of a list so that
+ * tests/list.test: the comment-power of that character is hidden
+ * tests/parse.test: from any [eval], in order to satisfy the
+ * tests/util.test: documentation that [list] does [eval]-safe
+ quoting.
+
+2003-07-24 Reinhard Max <max@suse.de>
+
+ * library/package.tcl: Fixed a typo that broke pkg_mkIndex -verbose.
+ * tests/pkgMkIndex.test: Added a test for [pkg_mkIndex -verbose].
+
+ * ChangeLog.2002 (new file):
+ * ChangeLog: broke changes from 2002 into ChangeLog.2002 to reduce
+ size of the main ChangeLog.
+
+2003-07-23 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/Makefile.in: changes to html-tcl & html-tk targets for
+ compatibility with non-gnu makes.
+
+ * unix/Makefile.in: added macosx/README to dist target.
+
+2003-07-23 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tclWinReg.c (OpenSubKey): Fixed bug 775976 which causes the
+ registry set command to fail when built with VC7.
+ * library/reg/pkgIndex.tcl: Incremented the version to 1.1.2.
+
+2003-07-21 Mo DeJong <mdejong@users.sourceforge.net>
+
+ Check that the thread incrementing or decrementing the ref count of a
+ Tcl_Obj is the thread that originally allocated the thread. This fail
+ fast behavior will catch programming errors that allow a single
+ Tcl_Obj to be accessed from multiple threads.
+
+ * generic/tcl.h (Tcl_Obj): Add allocThread member to Tcl_Obj. This
+ member records the thread id the Tcl_Obj was allocated. It is used to
+ check that any future ref count incr or decr is done from the same
+ thread that allocated the Tcl_Obj. This member is defined only when
+ threads and mem debug are enabled.
+ * generic/tclInt.h (TclNewObj, TclDbNewObj, TclDecrRefCount):
+ Define TclNewObj and TclDbNewObj using TclDbInitNewObj when mem debug
+ is enabled. This fixes a problem where TclNewObj calls did not work
+ the same as TclDbNewObj when mem debug was enabled.
+ * generic/tclObj.c (TclDbInitNewObj, Tcl_DbIncrRefCount,
+ (Tcl_DbDecrRefCount): Add new helper to init Tcl_Obj members when mem
+ debug is enabled. Init the allocThread member in TclDbInitNewObj and
+ check it in Tcl_DbIncrRefCount and Tcl_DbDecrRefCount to make sure a
+ Tcl_Obj allocated in one thread is not being acted upon in another
+ thread.
+
+2003-07-21 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * test/cmdAH.test: ensure certain tests run in local filesystem. [Bug
+ 748960]
+
+2003-07-18 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Makefile: added option to allow installing manpages in
+ addition to default html help.
+
+2003-07-18 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/Utf.3: Tightened up documentation of Tcl_UtfNext and Tcl_UtfPrev
+ to better match the behaviour. [Bug 769895]
+
+2003-07-18 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/http/pkgIndex.tcl: upped to http v2.4.4
+ * library/http/http.tcl: add support for user:pass info in URL.
+ * tests/http.test: [Bug 759888] (shiobara)
+
+2003-07-18 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/tcltest.n: Restored the [Eval] proc to replace
+ * library/tcltest/tcltest.tcl: the [::puts] command when either the
+ -output or -error option for [test] is in use, in order to capture
+ data written to the output or error channels for comparison against
+ what is expected. This is easier to document and agrees better with
+ most user expectations than the previous attempt to replace [puts]
+ only in the caller's namespace. Documentation made more precise on
+ the subject. [Bug 706359]
+
+ * doc/AddErrInfo.3: Improved consistency of documentation by
+ * doc/CrtTrace.3: using "null" everywhere to refer to the
+ * doc/Encoding.3: character '\0', and using "NULL" everywhere
+ * doc/Eval.3: to refer to the value of a pointer that points
+ * doc/GetIndex.3: to nowhere. Also dropped references to ASCII
+ * doc/Hash.3: that are no longer true, and standardized on
+ * doc/LinkVar.3: the hyphenated spelling of "null-terminated".
+ * doc/Macintosh.3:
+ * doc/OpenFileChnl.3:
+ * doc/SetVar.3:
+ * doc/StringObj.3:
+ * doc/Utf.3:
+
+ * doc/CrtSlave.3 (Tcl_MakeSafe): Removed warning about possible
+ deprecation (no TIP on that).
+
+2003-07-17 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tclUnixFCmd.c: fix for compilation errors on platforms where
+ configure detects non-functional chflags(). [Bug 748946]
+
+ * macosx/Makefile: Rewrote buildsystem for Mac OS X framework build
+ to be purely make driven; in order to become independent of Apple's
+ closed-source IDE and build tool. The changes are intended to be
+ transparent to the Makefile user, all existing make targets and cmd
+ line variable overrides should continue to work. Changed build to only
+ include tcl specific html help in Tcl.framework, the tk specific html
+ help is now included in Tk.framework. Added var to allow overriding of
+ tclsh used during html help building (Landon Fuller).
+
+ * macosx/Tcl.pbproj/project.pbxproj:
+ * macosx/Tcl.pbproj/jingham.pbxuser: Changed to purely call through to
+ the make driven buildsystem; Tcl.framework is no longer assembled by
+ ProjectBuilder.
+ Set default SYMROOT in target options to simplify setting up PB
+ (manually setting common build folder for tcl & tk no longer needed).
+
+ * tools/tcltk-man2html.tcl: Added options to allow building only the
+ tcl or tk html help files; the default behaviour with none of the new
+ options is to build both, as before.
+
+ * unix/Makefile.in: Added targets for building only the tcl or tk help
+
+ * macosx/README (new): Tcl specific excerpts of tk/macosx/README.
+
+ * generic/tcl.h: Updated reminder comment about editing
+ macosx/Tcl.pbproj/project.pbxproj when version number changes.
+
+2003-07-16 Mumit Khan <khan@nanotech.wisc.edu>
+
+ * generic/tclPathObj.c (SetFsPathFromAny): Add Cygwin specific code to
+ convert POSIX filename to native format.
+ * generic/tclFileName.c (Tcl_TranslateFileName): And remove from here.
+ (TclDoGlob): Adjust for cygwin and append / for dirs instead of \
+ * win/tclWinFile.c (TclpObjChdir): Use chdir on Cygwin.
+ [Patch 679315]
+
+2003-07-16 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/safe.tcl (FileInAccessPath): normalize paths before
+ comparison. [Bug 759607] (myers)
+
+ * unix/tclUnixNotfy.c (NotifierThreadProc): correct size of found and
+ word vars from int to long. [Bug 767578] (hgo)
+
+ * generic/tcl.h: Add recognition of -DTCL_UTF_MAX=6 on the make
+ * generic/regcustom.h: line to support UCS-4 mode. No config arg at
+ this time, as it is not the recommended build mode.
+
+ * generic/tclPreserve.c: In Result and Preserve'd routines, do not
+ * generic/tclUtil.c: assume that ckfree == free, as that is not
+ * generic/tclResult.c: always true. [Bug 756791] (fuller)
+
+2003-07-16 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/CrtSlave.3 (Tcl_MakeSafe): Updated documentation to strongly
+ discourage use. IMHO code outside the core that uses this function is
+ a bug... [Bug 655300]
+
+2003-07-16 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclFileName.c (Tcl_GlobObjCmd): [Bug 771840]
+ * generic/tclPathObj.c (Tcl_FSConvertToPathType):[Bug 771947]
+ * unix/tclUnixFCmd.c (GetModeFromPermString): [Bug 771949]
+ Silence compiler warnings about unreached lines.
+
+ * library/tcltest/tcltest.tcl (ProcessFlags): Corrected broken call
+ * library/tcltest/pkgIndex.tcl: to [lrange]. Bumped to
+ version 2.2.4. [Bug 772333]
+
+2003-07-15 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/dltest/pkga.c (Pkga_EqObjCmd): Fix typo that was causing a
+ crash in load.test.
+
+2003-07-15 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/array.n: Make sure docs are synched with the 8.4 release.
+
+2003-07-15 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/http.n: Updated SYNOPSIS to match actual syntax of commands.
+ [Bug 756112]
+
+ * unix/dltest/pkga.c: Updated to not use Tcl_UtfNcmp and counted
+ strings instead of strcmp (not defined in any #include'd header) and
+ presumed NULL-terminated strings.
+
+ * generic/tclCompCmds.c (TclCompileIfCmd): Prior fix of Bug 711371 on
+ 2003-04-07 introduced a buffer overflow. Corrected. [Bug 771613]
+
+2003-07-15 Kevin B. Kenny <kennykb@acm.org>
+
+ * win/rules.vc: Added a missing $(OPTDEFINES) which broke the build if
+ STATS=memdbg was specified.
+
+2003-07-15 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclCmdIL.c (SortCompare): Cleared up confusing error
+ message. [Bug 771539]
+
+2003-07-11 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/binary.test (binary-46.*): Tests to help enforce the current
+ behaviour.
+ * doc/binary.n: Documented that [binary format a] and [binary scan a]
+ do encoding conversion by dropping high bytes, unlike the rest of the
+ core. [Bug 735364]
+
+2003-07-11 Don Porter <dgp@users.sourceforge.net>
+
+ * library/package.tcl: Corrected [pkg_mkIndex] bug reported on
+ comp.lang.tcl. The indexer was searching for newly indexed packages
+ instead of newly provided packages.
+
+2003-07-08 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/winFCmd.test: fix for five tests under win98 [Bug 767679]
+
+2003-07-07 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/array.n: add examples from Welton
+
+2003-06-23 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * doc/file.n: clarification of 'file tail' behaviour [Bug 737977]
+
+2003-07-04 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/expr.n: Tighten up the wording of some operations. [Bug 758488]
+
+ * tests/cmdAH.test: Made tests of [file mtime] work better on FAT
+ filesystems. [Patch 760768] Also a little general cleanup.
+
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd): Made [string map] accept
+ dictionaries for maps. This is much trickier than it looks, since map
+ entry ordering is significant. [Bug 759936]
+
+ * generic/tclVar.c (Tcl_ArrayObjCmd, TclArraySet): Made [array get]
+ and [array set] work with dictionaries, producing them and consuming
+ them. Note that for compatability reasons, you will never get a dict
+ from feeding a string literal to [array set] since that alters the
+ trace behaviour of "multi-key" sets. [Bug 759935]
+
+2003-06-23 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclTrace.c: fix to Window debug build compilation error.
+
+2003-06-27 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/init.test: Added [cleanupTests] to report results of tests
+ * tests/pkg.test: that run in slave interps. [Bugs 761334,761344]
+
+ * tests/http.test: Used more reliable path to find httpd script.
+
+2003-06-25 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/init.test: Added tests init-4.6.* to illustrate [Bug 760872]
+
+2003-06-25 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclTrace.c: New file, factoring out of virtually all the
+ various trace-related things from tclBasic.c and tclCmdMZ.c with the
+ goal of making this a separate maintenance area.
+
+2003-06-25 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): Add -ieee when compiling with cc and
+ add -mieee when compiling with gcc under OSF1-V5 "Tru64" systems. [Bug
+ 748957]
+
+2003-06-24 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/encoding.n: Corrected the docs to say that [source] uses the
+ system encoding, which it always did anyway (since 8.1) [Bug 742100]
+
+2003-06-24 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclHash.c (Tcl_HashStats): Prevented occurrence of
+ division-by-zero problems. [Bug 759749]
+
+2003-06-24 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/tclUnixPort.h: #undef inet_ntoa before #define to avoid
+ compiler warning under freebsd. [Bug 745844]
+
+2003-06-23 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * doc/dde.n: Committed TIP #135 which changes the
+ * win/tclWinDde.c: -exact option to -force. Also cleaned a
+ * tests/winDde.test: bug in the tests.
+ * library/dde/pkgIndex.tcl: Incremented version to 1.2.5
+
+ * doc/dde.n: Committed TIP #120 which provides the
+ * win/tclWinDde.c: dde package for safe interpreters.
+ * tests/winDde.test: Incremented package version to 1.2.4
+ * library/dde/pkgIndex.tcl:
+
+2003-06-23 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclFCmd.c: fix to bad error message when trying to do 'file
+ copy foo ""'. [Bug 756951]
+ * tests/fCmd.test: added two new tests for the bug.
+
+ * win/tclWinFile.c:
+ * win/tclWin32Dll.c: recommitted some filesystem globbing speed-ups,
+ but disabled some on the older Win 95/98/ME where they don't seem to
+ work.
+
+ * doc/FileSystem.3: documentation fix [Bug 720634]
+
+2003-06-18 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclNamesp.c (Tcl_Export): removed erroneous comments. [Bug
+ 756744]
+
+2003-06-17 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * win/makefile.vc: fixes to check-in below so compilation now works
+ again on Windows.
+
+ * generic/tclCmdMZ.c:
+ * tests/regexp.test: fixing of bugs related to regexp and regsub
+ matching of empty strings. Addition of a number of new tests. [Bug
+ 755335]
+
+2003-06-16 Andreas Kupries <andreask@activestate.com>
+
+ * win/Makefile.in: Haven't heard back from David for a week. Now
+ * win/configure: committing the remaining changes.
+ * win/configure.in: Note: In active contact with Helmut Giese about
+ * win/makefile.vc: the borland relatedchanges. This part will see
+ * win/rules.vc: future updates.
+ * win/tcl.m4:
+ * win/makefile.bc:
+
+2003-06-10 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tclConfig.c (ASSOC_KEY): Changed the key to
+ "tclPackageAboutDict" (tcl prefix) to make collisions with the keys of
+ other packages more unlikely.
+
+2003-06-10 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclBasic.c:
+ * generic/tclExecute.c: let TclExecuteObjvInternal call
+ TclInterpReady instead of relying on its callers to do so; fix for the
+ part of [Bug 495830] that is new in 8.4.
+ * tests/interp.test: Added tests 18.9 (knownbug) and 18.10
+
+2003-06-09 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tcl.decls: Ported the changes from the
+ * generic/tcl.h: 'tip-59-implementation' branch into the CVS
+ * generic/tclBasic.c: head. Regenerated stub table. Regenerated the
+ * generic/tclInt.h: configure's scripts, with help from Joe English.
+ * generic/tclDecls.h:
+ * generic/tclStubInit.c:
+ * generic/tclConfig.c:
+ * generic/tclPkgConfig.c:
+ * unix/Makefile.in:
+ * unix/configure.in: The changes in the windows section are not yet
+ * unix/tcl.m4: committed, they await feedback from David
+ * unix/mkLinks: Gravereaux.
+ * doc/RegConfig.3:
+ * mac/tclMacPkgConfig.c:
+ * tests/config.test:
+
+2003-06-09 Don Porter <dgp@users.sourceforge.net>
+
+ * string.test (string-4.15): Added test for [string first] bug
+ reported in Tcl 8.3, where test for all-single-byte-encoded strings
+ was not reliable.
+
+2003-06-04 Joe Mistachkin <joe@mistachkin.com>
+
+ * tools/man2help.tcl: Added duplicate help section checking and
+ * tools/index.tcl: corrected a comment typo for the getTopics proc
+ in index.tcl. [Bug 748700]
+
+2003-06-02 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * win/tclWinFCmd.c:
+ * tests/fCmd.test: fix to [Bug #747575] in which a bad error message
+ is given when trying to rename a busy directory to one with the same
+ prefix, but not the same name. Added three new tests.
+
+2003-05-23 D. Richard Hipp <drh@hwaci.com>
+
+ * win/tclWinTime.c: Add tests to detect and avoid a division by zero
+ in the windows precision timer calibration logic.
+
+2003-05-23 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclObj.c (tclCmdNameType): Converted internal rep
+ management of the cmdName Tcl_ObjType the opposite way, to always use
+ the twoPtrValue instead of always using the otherValuePtr. Previous
+ fix on 2003-05-12 broke several extensions that wanted to poke around
+ with the twoPtrValue.ptr2 value of a cmdName Tcl_Obj, like TclBlend
+ and e4graph. [Bug 726018]
+ Thanks to George Petasis for the bug report and Jacob Levy for testing
+ assistance.
+
+2003-05-23 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/mkLinks: Set the var S to "" at the top of the file to avoid
+ error when user has set S to something. [Tk Bug 739833]
+
+2003-05-22 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Tcl.pbproj/project.pbxproj: added missing references to new
+ source files tclPathObj.c and tclMacOSXFCmd.c.
+
+ * macosx/tclMacOSXBundle.c: fixed a problem that caused only the first
+ call to Tcl_MacOSXOpenVersionedBundleResources() for a given bundle
+ identifier to succeed. This caused the tcl runtime library not to be
+ found in all interps created after the inital one.
+
+2003-05-19 Kevin B. Kenny <kennykb@hippolyta>
+
+ * unix/tclUnixTime.c: Corrected a bug in conversion of non-ASCII
+ chars in the format string.
+
+2003-05-19 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Tcl.pbproj/project.pbxproj: changed tclConfig.sh location in
+ versioned framework subdirectories to be identical to location in
+ framework toplevel; fixed stub library symbolic links to be tcl
+ version specific.
+
+ * unix/tclUnixTime.c: fixed typo.
+
+2003-05-18 Kevin Kenny <kennykb@acm.org>
+
+ * compat/strftime.c: Modified TclpStrftime to return its result in
+ * generic/tclClock.c: UTF-8 encoding, and removed the conversion from
+ * mac/tclMacTime.c: system encoding to UTF-8 from [clock format].
+ * unix/tclUnixTime.c: Needed to avoid double conversion of the
+ * win/tclWinTime.c: timezone name on Windows systems. [Bug 624408]
+
+2003-05-16 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/dde/pkgIndex.tcl: Applied TIP #130 which provides for
+ * tests/winDde.test: unique dde server names. Added some more
+ * win/tclWinDde.c: tests. Fixes [Bug 219293]
+
+ * doc/dde.n: Updated documentation re TIP #130.
+ * tests/winDde.test: Applied patch for [Bug 738929] by KKB and changed
+ to new-style tests.
+
+2003-05-16 Kevin B. Kenny <kennykb@acm.org>
+
+ * unix/Makefile.in: Removed one excess source file tclDToA.c
+
+2003-05-16 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Tcl.pbproj/project.pbxproj: updated copyright year.
+
+2003-05-15 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclGetDate.y: added further hackery to the yacc
+ * generic/tclDate.c: post-processing to arrange for the code to set
+ * unix/Makefile.in: up exit handlers to free the stacks. [Bug
+ 736425]
+
+2003-05-15 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tclWinFile.c (TclpMatchInDirectory): revert glob code to r1.44
+ as 2003-04-11 optimizations broke Windows98 glob'ing.
+
+ * doc/socket.n: nroff font handling correction
+
+ * library/encoding/gb2312-raw.enc (new): This is the original
+ gb2312.enc renamed to allow for it to still be used. This is needed by
+ Tk (unix) because X fonts with gb2312* charsets really do want the
+ original gb2312 encoding. [Bug 557030]
+
+2003-05-14 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclCmdAH.c (Tcl_FormatObjCmd): Stop unwarranted demotion of
+ wide values to longs by formatting of int values. [Bug 699060]
+
+2003-05-14 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/encoding/gb2312.enc: copy euc-cn.enc over original
+ gb2312.enc. gb2312.enc appeared to not work as expected, and most uses
+ of gb2312 really mean euc-cn (which may be the cause of the problem).
+ [Bug 557030]
+
+2003-05-14 Daniel Steffen <das@users.sourceforge.net>
+
+ Implementation of TIP 118:
+
+ * generic/tclFCmd.c (TclFileAttrsCmd): return the list of attributes
+ that can be retrieved without error for a given file, instead of
+ aborting the whole command when any error occurs.
+
+ * unix/tclUnixFCmd.c: added support for new file attributes and for
+ copying Mac OS X file attributes & resource fork during [file copy].
+
+ * generic/tclInt.decls: added declarations of new external commands
+ needed by new file attributes support in tclUnixFCmd.c.
+
+ * macosx/tclMacOSXFCmd.c (new): Mac OS X specific implementation of
+ new file attributes and of attribute & resource fork copying.
+
+ * mac/tclMacFCmd.c: added implementation of -rsrclength attribute &
+ fixes to other attributes for consistency with OSX implementation.
+
+ * mac/tclMacResource.c: fixes to OSType handling.
+
+ * doc/file.n: documentation of [file attributes] changes.
+
+ * unix/configure.in: check for APIs needed by new file attributes.
+
+ * unix/Makefile.in:
+ * unix/tcl.m4: added new platform specifc tclMacOSXFCmd.c source.
+
+ * unix/configure:
+ * generic/tclStubInit.c:
+ * generic/tclIntPlatDecls.h: regen.
+
+ * tools/genStubs.tcl: fixes to completely broken code trying to
+ prevent overlap of "aqua", "macosx", "x11" and "unix" stub entries.
+
+ * tests/unixFCmd.test: added tests of -readonly attribute.
+
+ * tests/macOSXFCmd.test (new): tests of macosx file attributes and of
+ preservation of attributes & resource fork during [file copy].
+
+ * tests/macFCmd.test: restore -readonly attribute of test dir, as
+ otherwise its removal can fail on unices supporting -readonly.
+
+2003-05-13 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tclEnv.c: Another putenv() copy behavior problem repaired
+ when compiling on windows and using microsoft's runtime. [Bug 736421]
+
+2003-05-13 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclIOUtil.c: ensure cd is thread-safe.
+ [Bug 710642] (vasiljevic)
+
+2003-05-13 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclEvent.c (Tcl_Finalize): Removed unused variable to reduce
+ compiler warnings. [Bug 664745]
+
+2003-05-13 Joe Mistachkin <joe@mistachkin.com>
+
+ * generic/tcl.decls: Changed Tcl_JoinThread parameter name from
+ * generic/tclDecls.h: "id" to "threadId". [Bug 732477]
+ * unix/tclUnixThrd.c:
+ * win/tclWinThrd.c:
+ * mac/tclMacThrd.c:
+
+2003-05-13 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tcl.decls:
+ * macosx/tclMacOSXBundle.c: added extended version of the
+ Tcl_MacOSXOpenBundleResources() API taking an extra version number
+ argument: Tcl_MacOSXOpenVersionedBundleResources(). This is needed to
+ be able to access bundle resources in versioned frameworks such as Tcl
+ and Tk, otherwise if multiple versions were installed, only the latest
+ version's resources could be accessed. [Bug 736774]
+
+ * unix/tclUnixInit.c (Tcl_MacOSXGetLibraryPath): use new versioned
+ bundle resource API to get tcl runtime library for TCL_VERSION. [Bug
+ 736774]
+
+ * generic/tclPlatDecls.h:
+ * generic/tclStubInit.c: regen.
+
+ * unix/tclUnixPort.h: worked around the issue of realpath() not
+ being thread-safe on Mac OS X by defining NO_REALPATH for threaded
+ builds on Mac OS X. [Bug 711232]
+
+2003-05-12 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/cmdAH.test: General clean-up of tests so that all
+ tcltest-specific commands are protected by constraints and all
+ platforms see the same number of tests. [Bug 736431]
+
+2003-05-12 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclInterp.c: (AliasObjCmd): Added refCounting of the words
+ * tests/interp.test (interp-33.1): of the target of an interp
+ alias during its execution. Also added test. [Bug 730244]
+
+ * generic/tclBasic.c (TclInvokeObjectCommand): objv[argc] is no
+ longer set to NULL (Tcl_CreateObjCommand docs already say that it
+ should not be accessed).
+
+ * tests/cmdMZ.test: Forgot to import [temporaryDirectory].
+
+ * generic/tclObj.c (tclCmdNameType): Corrected variable use of the
+ otherValuePtr or the twoPtrValue.ptr1 fields to store a
+ (ResolvedCmdName *) as the internal rep. [Bug 726018]
+
+ * doc/Eval.3: Corrected prototype for Tcl_GlobalEvalObj [Bug 727622].
+
+2003-05-12 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclVar.c (TclObjLookupVar): [Bug 735335] temporary fix,
+ disabling usage of tclNsVarNameType.
+ * tests/var.test (var-15.1): test for [Bug 735335]
+
+2003-05-10 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tclWinSerial.c (SerialCloseProc): correct mem leak on closing a
+ Windows serial port [Bug 718002] (schroedter)
+
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd): prevent string repeat crash
+ when overflow sizes were given (throws error). [Bug 714106]
+
+2003-05-09 Joe Mistachkin <joe@mistachkin.com>
+
+ * generic/tclThreadAlloc.c (TclFreeAllocCache): Fixed memory leak
+ caused by treating cachePtr as a TLS index. [Bug 731754]
+
+ * win/tclAppInit.c (Tcl_AppInit): Fixed memory leaks caused by not
+ freeing the memory allocated by setargv and the async handler created
+ by Tcl_AppInit. An exit handler has been created that takes care of
+ both leaks. In addition, Tcl_AppInit now uses ckalloc instead of
+ Tcl_Alloc to allow for easier leak tracking and to be more consistent
+ with the rest of the Tcl core. [Bugs 733156, 733221]
+
+ * tools/encoding/txt2enc.c (main): Fixed memory leak caused by failing
+ to free the memory used by the toUnicode array of strings [Bug 733221]
+
+2003-05-09 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompile.c (TclCompileScript):
+ * tests/compile.test (compile-3.5): corrected wrong test and
+ behaviour in the earlier fix for [Bug 705406]; Don Porter reported
+ this as [Bug 735055], and provided the solution.
+
+2003-05-09 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclCmdMZ.c (Tcl_ReturnObjCmd): The array of strings passed
+ to Tcl_GetIndexFromObj must be NULL terminated. [Bug 735186]
+ Thanks to Joe Mistachkin for spotting this.
+
+2003-05-07 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/trace.n: Fixed very strange language in the documentation for
+ 'trace add execution'. [Bug 729821]
+
+ * generic/tclCmdMZ.c (Tcl_TraceObjCmd): Made error message for 'trace
+ info' more consistent with documentation. [Bug 706961]
+
+ * generic/tclDictObj.c (DictInfoCmd): Fixed memory leak caused by
+ confusion about string ownership. [Bug 731706]
+
+2003-05-05 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c: Implementation of TIP 90, which
+ * generic/tclCmdAH.c: extends the [catch] and [return]
+ * generic/tclCompCmds.c: commands to enable creation of a
+ * generic/tclExecute.c: proc that is a replacement for
+ * generic/tclInt.h: [return]. [Patch 531640]
+ * generic/tclProc.c:
+ * generic/tclResult.c:
+ * tests/cmdAH.test:
+ * tests/cmdMZ.test:
+ * tests/error.test:
+ * tests/proc-old.test:
+
+ * library/tcltest/tcltest.tcl: The -returnCodes option to [test]
+ failed to recognize the symbolic name "ok" for return code 0.
+
+2003-05-05 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclBasic.c (Tcl_HideCommand): Fixed error message for
+ grammar and spelling.
+
+2003-04-28 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclDictObj.c (DictIncrCmd): Updated to reflect the behaviour
+ with wide increments of the normal [incr] command.
+ * generic/tclInt.decls: Added TclIncrWideVar2 to internal stub table
+ and cleaned up.
+ * tests/incr.test (incr-3.*):
+ * generic/tclVar.c (TclIncrWideVar2, TclPtrIncrWideVar):
+ * generic/tclExecute.c (TclExecuteByteCode):
+ * generic/tclCmdIL.c (Tcl_IncrObjCmd): Make [incr] work when trying to
+ increment by wide values. [Bug 728838]
+
+ * generic/tclCompCmds.c (TclCompileSwitchCmd): Default mode of
+ operation of [switch] is exact matching. [Bug 727563]
+
+2003-04-25 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c: Tcl_EvalObjv() failed to honor the
+ TCL_EVAL_GLOBAL flag when resolving command names. Tcl_EvalEx passed a
+ string rep including leading whitespace and comments to
+ TclEvalObjvInternal().
+
+2003-04-25 Andreas Kupries <andreask@activestate.com>
+
+ * win/tclWinThrd.c: Applied SF patch #727271. This patch changes the
+ code to catch any errors returned by the windows functions handling
+ TLS ASAP instead of waiting to get some mysterious crash later on due
+ to bogus pointers. Patch provided by Joe Mistachkin.
+
+ This is a stop-gap measure to deal with the low number of ?TLS slots
+ provided by some of the variants of Windows (60-80).
+
+2003-04-24 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclFileName.c: fix to bug reported privately by Jeff where,
+ for example, 'glob -path {[tcl]} *' gets confused by the leading
+ special character (which is escaped internally), and instead lists
+ files in '/'. Bug only occurs on Windows where '\' is also a directory
+ separator.
+ * tests/fileName.test: added test for the above bug.
+
+2003-04-22 Andreas Kupries <andreask@activestate.com>
+
+ * The changes below fix SF bugs [593810], and [718045].
+
+ * generic/tclIO.c (Tcl_CutChannel, Tcl_SpliceChannel): Invoke
+ TclpCutSockChannel and TclpSpliceSockChannel.
+
+ * generic/tclInt.h: Declare TclpCutSockChannel and
+ TclpSpliceSockChannel.
+
+ * unix/tclUnixSock.c (TclpCutSockChannel, TclpSpliceSockChannel):
+ Dummy functions, on unix the sockets are _not_ handled specially.
+
+ * mac/tclMacSock.c (TclpCutSockChannel, TclpSpliceSockChannel):
+ * win/tclWinSock.c (TclpCutSockChannel, TclpSpliceSockChannel): New
+ functions to handle socket specific cut/splice operations: auto-init
+ of socket system for thread on splice, management of the module
+ internal per-thread list of sockets, management of association of
+ sockets with HWNDs for event notification.
+
+ * win/tclWinSock.c (NewSocketInfo): Extended initialization
+ assignments to cover all items of the structure. During debugging of
+ the new code mentioned above I found that two fileds could contain
+ bogus data.
+
+ * win/tclWinFile.c: Added #undef HAVE_NO_FINDEX_ENUMS before
+ definition because when compiling in debug mode the compiler complains
+ about a redefinition, and this warning is also treated as an error.
+
+2003-04-21 Don Porter <dgp@users.sourceforge.net>
+
+ * library/tcltest/tcltest.tcl: When the return code of a test does
+ not meet expectations, report that as the reason for test failure, and
+ do not attempt to check the test result for correctness. [Bug 725253]
+
+2003-04-18 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tclWinInt.h (VER_PLATFORM_WIN32_CE): conditionally define.
+ * win/tclWinInit.c: recognize Windows CE as a Win platform. This just
+ recognizes CE - full support will come later.
+
+ * win/configure: regen
+ * win/configure.in (SHELL): force it to /bin/sh as autoconf 2.5x
+ uses /bin/bash, which can fail to find exes in the path (ie: lib).
+
+ * generic/tclExecute.c (ExprCallMathFunc): remove incorrect
+ extraneous cast from Tcl_WideAsDouble.
+
+2003-04-18 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/open.n: Moved serial port options from [fconfigure] to
+ * doc/fconfigure.n: [open] as it is up to the creator of a channel
+ to describe the channel's special config
+ options. [Bug 679010]
+
+2003-04-16 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tcl.h: Made changes so that the "wideInt" Tcl_ObjType
+ * generic/tclObj.c: is defined on all platforms, even those where
+ * generic/tclPort.h: TCL_WIDE_INT_IS_LONG is defined. Also made the
+ Tcl_Value struct have a wideValue field on all platforms. This is a
+ ***POTENTIAL INCOMPATIBILITY*** for TCL_WIDE_INT_IS_LONG platforms
+ because that struct changes size. This is the same TIP 72
+ incompatibility that was seen on other platforms at the 8.4.0 release,
+ when this change should have happened as well. [Bug 713562]
+
+ * generic/tclInt.h: New internal macros TclGetWide() and
+ TclGetLongFromWide() to deal with both forms of the "wideInt"
+ Tcl_ObjType, so that conditional TCL_WIDE_INT_IS_LONG code is confined
+ to the header file.
+
+ * generic/tclCmdAH.c: Replaced most coding that was conditional
+ * generic/tclCmdIL.c: on TCL_WIDE_INT_IS_LONG with code that
+ * generic/tclExecute.c: works across platforms, sometimes using
+ * generic/tclTest.c: the new macros above to do it.
+ * generic/tclUtil.c:
+ * generic/tclVar.c:
+
+2003-04-17 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/socket.n: Added a paragraph to remind people to specify their
+ encodings when using sockets. [Bug 630621]
+
+2003-04-16 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/CrtMathFnc.3: Functions also have to deal with wide ints, but
+ this was not documented. [Bug 709720]
+
+2003-04-16 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclPathObj.c: removed undesired 'static' for function which
+ is now shared (previously it was duplicated).
+
+2003-04-15 Joe English <jenglish@users.sourceforge.net>
+
+ * doc/namespace.n: added example section "SCOPED SCRIPTS", supplied by
+ Kevin Kenny. [Bug 219183]
+
+2003-04-15 Kevin Kenny <kennykb@acm.org>
+
+ * makefile.vc: Updated makefile.vc to conform with Mo DeJong's changes
+ to Makefile.in and tclWinPipe.c on 2003-04-14. Now passes TCL_PIPE_DLL
+ in place of TCL_DBGX.
+ * win/tclWinTime.c: Corrected use of types to make compilation
+ compatible with VC++5.
+
+2003-04-15 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclIOUtil.c: finished check-in from yesterday, removing
+ duplicate function definition.
+
+2003-04-14 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclClock.c: Corrected compiler warnings.
+ * generic/tclTest.c:
+
+2003-04-14 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/Makefile.in: Don't define TCL_DBGX symbol for every compile.
+ Instead, define TCL_PIPE_DLL only when compiling tclWinPipe.c. This
+ will break other build systems, so they will need to remove the
+ TCL_DBGX define and replace it with a define for TCL_PIPE_DLL.
+ * win/tclWinPipe.c (TclpCreateProcess): Remove PREFIX_IDENT and
+ DEBUG_IDENT from top of file. Use TCL_PIPE_DLL passed in from build
+ env instead of trying to construct the dll name from already defined
+ symbols. This approach is more flexible and better in the long run.
+
+2003-04-14 Kevin Kenny <kennykb@acm.org>
+
+ * win/tclWinFile.c: added conditionals to restore compilation on
+ VC++6, which was broken by recent changes.
+
+2003-04-14 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclIOUtil.c:
+ * generic/tclPathObj.c:
+ * generic/tclFileSystem.h: overlooked one function which was
+ duplicated, so this is now shared between modules.
+ * win/tclWinFile.c: allow this file to compile with VC++ 5.2 again
+ since Mingw build fixes broke that.
+
+2003-04-13 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/configure: Regen.
+ * win/configure.in: Add check for FINDEX_INFO_LEVELS from winbase.h,
+ known to be a problem in VC++ 5.2. Define HAVE_NO_FINDEX_ENUMS if the
+ define does not exist.
+ * win/tclWinFile.c: Put declarations for FINDEX_INFO_LEVELS and
+ FINDEX_SEARCH_OPS inside a check for HAVE_NO_FINDEX_ENUMS so that
+ these are not declared twice. This fixes the Mingw build.
+ * win/tclWinTime.c: Rework the init of timeInfo so that the number or
+ initializers matches the declaration. This was broken under Mingw. Add
+ cast to avoid compile warning when calling the AccumulateSample
+ function.
+
+2003-04-12 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/Makefile.in (GENERIC_OBJS): add missing tclPathObj.c
+
+2003-04-12 Kevin Kenny <kennykb@acm.org>
+
+ * doc/clock.n:
+ * generic/tclClock.c (Tcl_ClockObjCmd):
+ * tests/clock.test: Implementation of TIP #124. Also renumbered test
+ cases to avoid duplicates. [Bug 710310]
+ * tests/winTime.test:
+ * win/tclWinTest.c (TestwinclockCmd, TestwinsleepCmd):
+ * win/tclWinTime.c (Tcl_WinTime, UpdateTimeEachSecond,
+ (ResetCounterSamples, AccumulateSample, SAMPLES, TimeInfo): Made
+ substantial changes to the phase-locked loop (replaced an IIR filter
+ with an FIR one) in a quest for improved loop stability (Bug not
+ logged at SF, but cited in private communication from Jeff Hobbs).
+
+2003-04-11 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd,STR_IS_INT): Corrected
+ inconsistent results of [string is integer] observed on systems where
+ sizeof(long) != sizeof(int). [Bug 718878]
+ * tests/string.test: Added tests for Bug 718878.
+ * doc/string.n: Clarified that [string is integer] accepts 32-bit
+ integers.
+
+2003-04-11 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tclIO.c (UpdateInterest): When dropping interest in
+ TCL_READABLE now dropping interest in TCL_EXCEPTION too. This fixes a
+ bug where Expect detects eof on a file prematurely on solaris 2.6 and
+ higher. A much more complete explanation is in the code itself (40
+ lines of comments for a one-line change :)
+
+2003-04-11 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/cmdAH.test: fix test suite problem if /home is a symlink. [Bug
+ 703264]
+ * generic/tclIOUtil.c: fix bad error message with 'cd ""'. [Bug
+ 704917]
+ * win/tclWinFile.c, win/tclWin32Dll.c:
+ * win/tclWinInt.h: allow Tcl to differentiate between reparse points
+ which are symlinks and mounted volumes, and correctly handle the
+ latter. This involves some elaborate code to find the actual drive
+ letter (if possible) corresponding to a mounted volume. [Bug 697862]
+ * tests/fileSystem.test: add constraints to stop tests running in
+ ordinary tcl interpreter. [Bug 705675]
+
+ * generic/tclIOUtil.c:
+ * generic/tclPathObj.c: (new file)
+ * generic/tclFileSystem.h: (new file)
+ * win/makefile.vc:
+ Split path object handling out of the virtual filesystem layer, into
+ tclPathObj.c. This refactoring cleans up the internal filesystem code,
+ and will make any future optimisations and forthcoming better
+ thread-safety much easier.
+
+ * generic/tclTest.c:
+ * tests/reg.test: added some 'knownBug' tests for problems in Tcl's
+ regexp code with the TCL_REG_CAN_MATCH flag (see Bug 703709). Code too
+ impenetrable to fix right now, but a fix is needed for tip113 to work
+ correctly.
+
+ * tests/fCmd.test
+ * win/tclWinFile.c: added some filesystem optimisation to the 'glob'
+ implementation, and some new tests.
+
+ * generic/tclCmdMZ.c: fix typo in comment
+
+ * tests/winFile.test:
+ * tests/ioUtil.test:
+ * tests/unixFCmd.test: renumbered tests with duplicate numbers. [Bug
+ 710361]
+
+2003-04-10 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/binary.n: Fixed typo in [binary format w] desc. [Bug 718543]
+
+2003-04-08 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclCmdAH.c (Tcl_ErrorObjCmd): Strings are only empty if
+ they have zero length, not if their first byte is zero, so fix test
+ guarding Tcl_AddObjErrorInfo to take this into account. [Bug
+ reported by Don Porter; no bug-id.]
+
+2003-04-07 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCompCmds.c (TclCompileIfCmd): Corrected string limits of
+ arguments interpolated in error messages. [Bug 711371]
+
+ * generic/tclCmdMZ.c (TraceExecutionProc): Added missing
+ Tcl_DiscardResult() call to avoid memory leak.
+
+2003-04-07 Donal K. Fellows <zzcgudf@ernie.mvc.mcc.ac.uk>
+
+ * generic/tclDictObj.c (Tcl_DictObjCmd): Stopped compilers from
+ moaning about switch fall-through. [Bug 716327]
+ (DictFilterCmd): Yet more warning killing, this time reported by
+ Miguel Sofer by private chat.
+
+2003-04-07 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/dict.test (dict-2.6):
+ * generic/tclDictObj.c (Tcl_NewDictObj, Tcl_DbNewDictObj): Oops!
+ Failed to fully initialise the Dict structure.
+ (DictIncrCmd): Moved valueAlreadyInDictionary label to stop compiler
+ complaints. [Bug 715751]
+
+ * generic/tclDictObj.c (DictIncrCmd): Followed style in the rest of
+ the core by commenting out wide-specific operations on platforms where
+ wides are longs, and used longs more thoroughly than ints through
+ [dict incr] anyway to forestall further bugs.
+ * generic/tclObj.c: Made sure there's always a tclWideIntType
+ implementation available, not that it is always useful. [Bug 713562]
+
+2003-04-05 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclDictObj.c: Removed commented out notes on declarations to
+ be moved to elsewhere in the Tcl core.
+
+ * generic/tclInt.h: Final stages of plumbing in.
+ * generic/tclBasic.c:
+ * generic/tclObj.c (TclInitObjSubsystem):
+
+ * unix/Makefile.in, win/Makefile.in, win/makefile.[bv]c: Build support.
+ * generic/tcl.decls: Added dict public API to stubs table.
+ * generic/tcl.h (Tcl_DictSearch): Added declaration of structure to
+ allow user code to iterate over dictionaries.
+
+ * doc/DictObj.3: New files containing dictionary implementation
+ * doc/dict.n: documentation and tests as as mandated by TIP
+ * generic/tclDictObj.c: #111.
+ * tests/dict.test:
+
+2003-04-03 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure:
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): Don't set TCL_LIBS if it is already
+ set to support use of TCL_LIBS var from tclConfig.sh in the Tk
+ configure script.
+
+2003-04-03 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/Makefile.in: Don't subst MATH_LIBS, LIBS, and DL_LIBS
+ separately. Instead, just subst TCL_LIBS since it includes the
+ others.
+ * unix/configure: Regen.
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS, SC_TCL_LINK_LIBS): Set and subst
+ TCL_LIBS in SC_CONFIG_CFLAGS instead of SC_TCL_LINK_LIBS. Don't subst
+ MATH_LIBS since it is now covered by TCL_LIBS.
+ * unix/tclConfig.sh.in: Use TCL_LIBS instead of DL_LIBS, LIBS, and
+ MATH_LIBS.
+ * unix/dltest/Makefile.in: Ditto.
+
+2003-04-03 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCompCmds.c (TclCompileReturnCmd): Now that [return]
+ compiles to INST_RETURN, it is safe to compile even outside a proc.
+
+2003-04-02 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/configure: Regen.
+ * win/configure.in: Set stub lib flag based on new LIBFLAGSUFFIX
+ variable.
+ * win/tcl.m4 (SC_CONFIG_CFLAGS): Set new LIBFLAGSUFFIX that works like
+ LIBSUFFIX, it is used when creating library names. The previous
+ implementation would generate -ltclstub85 instead of -ltclstub85s when
+ configured with --disable-shared.
+
+2003-04-02 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclParse.c (TclSubstTokens): Moved declaration of
+ utfCharBytes to beginning of procedure so that it does not go out of
+ scope (get free()d) while append is still pointing to it. [Bugs
+ 703167, 713754]
+
+2003-04-01 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): Check for inet_ntoa in -lbind inside
+ the BeOS block since doing it later broke the build under SuSE 7.3.
+ [Bug 713128]
+
+2003-04-01 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/README: Direct [source] of *.test files is no longer
+ recommended. The tests/*.test files should only be evaluated under the
+ control of the [runAllTests] command in tests/all.tcl.
+
+ * generic/tclExecute.c (INST_RETURN): Bytecompiled [return] failed to
+ reset iPtr->returnCode, causing tests parse-18.17 and parse-18.21 to
+ fail strangely.
+ * tests/parse.test (parse-18.21): Corrected now functioning test.
+ Added further coverage tests.
+
+2003-03-31 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/parse.test (parse-18.*): Coverage tests for the new
+ implementation of Tcl_SubstObj(). Note that tests parse-18.17 and
+ parse-18.21 demonstrate some bugs left to fix in the current code.
+
+2003-03-27 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): Use -Wl,--export-dynamic instead of
+ -rdynamic for LDFLAGS. The -rdynamic is not documented so it seems
+ better to pass the --export-dynamic flag to the linker. [Patch 573395]
+
+2003-03-27 Miguel Sofer <msofer@users.sf.net>
+
+ * tests/encoding.test:
+ * tests/proc-old.test:
+ * tests/set-old.test: Altered test numers to eliminate duplicates,
+ [Bugs 710313, 710320, 710352]
+
+2003-03-27 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/parseOld.test: Altered test numers to eliminate duplicates.
+ * tests/parse.test: [Bugs 710365, 710369]
+ * tests/expr-old.test:
+ * tests/expr.test:
+
+ * tests/utf.test: Altered test numers to eliminate duplicates.
+ * tests/trace.test: [Bugs 710322, 710327, 710349, 710363]
+ * tests/lsearch.test:
+ * tests/list.test:
+ * tests/info.test:
+ * tests/incr-old.test:
+ * tests/if-old.test:
+ * tests/format.test:
+ * tests/foreach.test:
+
+2003-03-26 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS, SC_TCL_LINK_LIBS): Add BeOS system to
+ SC_CONFIG_CFLAGS. Check for inet_ntoa in -lbind, needed for BeOS.
+
+2003-03-26 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/tcltest.n:
+ * library/tcltest/tcltest.tcl: Added reporting during [configure
+ -debug 1] operations to warn about multiple uses of the same test
+ name. [FRQ 576693]
+
+ * tests/msgcat.test (msgcat-2.2.1): changed test name to avoid
+ duplication. [Bug 710356]
+
+ * unix/dltest/pkg?.c: Changed all Tcl_InitStubs calls to pass
+ argument exact = 0, so that rebuilds are not required when Tcl
+ bumps to a new version. [Bug 701926]
+
+2003-03-24 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclVar.c:
+ * tests/var.test: fixing ObjMakeUpvar's lookup algorithm for the
+ created local variable. [Bug 631741] (Chris Darroch) and [Bug 696893]
+ (David Hilker)
+
+2003-03-24 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/dde/pkgIndex.tcl: bumped version to 1.2.2 in tclWinDde.c,
+ now adding here too.
+
+2003-03-22 Kevin Kenny <kennykb@acm.org>
+
+ * library/dde/pkgIndex.tcl:
+ * library/reg/pkgIndex.tcl: Fixed a bug where [package require dde]
+ or [package require registry] attempted to load the release version
+ of the DLL into a debug build. [Bug 708218] Thanks to Joe Mistachkin
+ for the patch.
+ * win/makefile.vc: Added quoting around the script name in the 'test'
+ target; Joe Mistachkin insists that he has a configuration that fails
+ to launch tcltest without it, and it appears harmless otherwise.
+
+2003-03-22 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tclWinDde.c: Make dde services conform the the documentation
+ such that giving only a topic name really returns all services with
+ that topic. [Bug 219155]
+ Prevent hangup caused by dde server applications failing to process
+ messages. [Bug 707822]
+ * tests/winDde.test: Corrected labels and added a test for search by
+ topic name.
+
+2003-03-20 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclInt.h (tclOriginalNotifier):
+ * generic/tclStubInit.c (tclOriginalNotifier):
+ * mac/tclMacNotify.c (Tcl_SetTimer,Tcl_WaitForEvent):
+ * unix/tclUnixNotfy.c (Tcl_SetTimer,Tcl_WaitForEvent,
+ (Tcl_CreateFileHandler,Tcl_DeleteFileHandler):
+ * win/tclWinNotify.c (Tcl_SetTimer,Tcl_WaitForEvent): Some linkers
+ apparently use a different representation for a pointer to a function
+ within the same compilation unit and a pointer to a function in a
+ different compilation unit. This causes checks like those in the
+ original notifier procedures to fall into infinite loops. The fix is
+ to store pointers to the original notifier procedures in a struct
+ defined in the same compilation unit as the stubs tables, and compare
+ against those values. [Bug 707174]
+
+ * generic/tclInt.h: Removed definition of ParseValue struct that is
+ no longer used.
+
+2003-03-19 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompile.c:
+ * tests/compile.test: bad command count on TCL_OUT_LINE_COMPILE.
+ [Bug 705406] (Don Porter)
+
+2003-03-19 Don Porter <dgp@users.sourceforge.net>
+
+ * library/auto.tcl: Replaced [regexp] and [regsub] with
+ * library/history.tcl: [string map] where possible. Thanks
+ * library/ldAout.tcl: to David Welton. [Bugs 667456,667558]
+ * library/safe.tcl: Bumped to http 2.4.3, opt 0.4.5, and
+ * library/http/http.tcl: tcltest 2.2.3.
+ * library/http/pkgIndex.tcl:
+ * library/opt/optparse.tcl:
+ * library/opt/pkgIndex.tcl:
+ * library/tcltest/tcltest.tcl:
+ * library/tcltest/pkgIndex.tcl:
+ * tools/genStubs.tcl:
+ * tools/tcltk-man2html.tcl:
+ * unix/mkLinks.tcl:
+
+ * doc/Eval.3 (Tcl_EvalObjEx): Corrected CONST and
+ * doc/ParseCmd.3 (Tcl_EvalTokensStandard): return type errors in
+ documentation. [Bug 683994]
+
+ * generic/tclCompCmds.c (TclCompileReturnCmd): Alternative fix for
+ * generic/tclCompile.c (INST_RETURN): [Bug 633204] that uses a new
+ * generic/tclCompile.h (INST_RETURN): bytecode INST_RETURN to
+ * generic/tclExecute.c (INST_RETURN): properly bytecode the [return]
+ command to something that returns TCL_RETURN.
+
+2003-03-18 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/configure: Regen.
+ * win/configure.in: Don't run the AC_CYGWIN macro since it uses
+ AC_CANONICAL_HOST under autoconf 2.5X. Just check to see if __CYGWIN__
+ is defined by the compiler and set the ac_cv_cygwin variable based on
+ that. [Bug 705912]
+
+2003-03-18 Kevin Kenny <kennykb@users.sourceforge.net>
+
+ * tests/registry.test: Changed the conditionals to avoid an abort if
+ [testlocale] is missing, as when running the test in tclsh rather than
+ tcltest. [Bug 705677]
+
+2003-03-18 Daniel Steffen <das@users.sourceforge.net>
+
+ * tools/tcltk-man2html.tcl: added support for building 'make html'
+ from inside distribution directories named with 8.x.x version numbers.
+ tcltk-man2html now uses the latest tcl8.x.x resp. tk8.x.x directories
+ found inside its --srcdir argument.
+
+2003-03-17 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/format.test: Renumber tests, a bunch of tests all had the same
+ id.
+
+2003-03-17 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/lsearch.n: Altered documentation of -ascii options so
+ * doc/lsort.n: they don't specify that they operate on ASCII
+ strings, which they never did anyway. [Bug
+ 703807]
+
+2003-03-14 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclCmdAH.c (Tcl_FormatObjCmd): Only add the modifier that
+ indicates we've got a wide int when we're formatting in an integer
+ style. Stops some libc's from going mad. [Bug 702622] Also tidied
+ whitespace.
+
+2003-03-13 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tcl.m4 (SC_WITH_TCL): Port version number fix that was made in
+ tk instead of tcl sources.
+
+2003-03-13 Mo DeJong <mdejong@users.sourceforge.net>
+
+ Require autoconf 2.57 or newer, see TIP 34 for a detailed explanation
+ of why this is good. This will no doubt break the build on some
+ platforms, let the flaming begin.
+
+ * tools/configure: Regen with autoconf 2.57.
+ * tools/configure.in: Require autoconf 2.57.
+ * unix/configure: Regen with autoconf 2.57.
+ * unix/configure.in: Require autoconf 2.57.
+ Apply AC_LIBOBJ changes from patch 529884.
+ * unix/tcl.m4: Ditto.
+ * win/configure: Regen with autoconf 2.57.
+ * win/configure.in: Require autoconf 2.57.
+ Don't subst LIBOBJS since this happens by default, this avoids an
+ autoconf error.
+
+2003-03-12 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c (Tcl_EvalTokensStandard):
+ * generic/tclCmdMZ.c (Tcl_SubstObj):
+ * generic/tclCompCmds.c (TclCompileSwitchCmd):
+ * generic/tclCompExpr.c (CompileSubExpr):
+ * generic/tclCompile.c (TclSetByteCodeFromAny,TclCompileScript,
+ (TclCompileTokens,TclCompileCmdWord):
+ * generic/tclCompile.h (TclCompileScript):
+ * generic/tclExecute.c (TclCompEvalObj):
+ * generic/tclInt.h (Interp,TCL_BRACKET_TERM,TclSubstTokens):
+ * generic/tclParse.c (ParseTokens,Tcl_SubstObj,TclSubstTokens):
+ * tests/subst.test (2.4, 8.7, 8.8, 11.4, 11.5):
+ Substantial refactoring of Tcl_SubstObj to make use of the same
+ parsing and substitution procedures as normal script evaluation.
+ Tcl_SubstObj() moved to tclParse.c. New routine TclSubstTokens()
+ created in tclParse.c which implements all substantial functioning of
+ Tcl_EvalTokensStandard(). TclCompileScript() loses its "nested"
+ argument, the Tcl_Interp struct loses its termOffset field and the
+ TCL_BRACKET_TERM flag in the evalFlags field, all of which were only
+ used (indirectly) by Tcl_SubstObj(). Tests subst-8.7,8.8,11.4,11.5
+ modified to accomodate the only behavior change: reporting of parse
+ errors now takes precedence over [return] and [continue] exceptions.
+ All other behavior should remain compatible. [RFE 536831,684982] [Bug
+ 685106]
+
+ * generic/tcl.h: Removed TCL_PREFIX_IDENT and TCL_DEBUG_IDENT
+ * win/tclWinPipe.c: from tcl.h -- they are not part of Tcl's
+ public interface. Put them in win/tclWinPipe.c where they are used.
+
+ * generic/tclInterp.c (Tcl_InterpObjCmd): Corrected and added
+ * tests/interp.test (interp-2.13): test for option
+ parsing beyond objc for [interp create --]. Thanks to Marco Maggi.
+ [Bug 702383]
+
+2003-03-11 Kevin Kenny <kennykb@users.sourceforge.net>
+
+ * win/makefile.vc: Added two missing uses of $(DBGX) so that
+ tclpip8x.dll loads without panicking on Win9x.
+
+2003-03-09 Kevin Kenny <kennykb@users.sourceforge.net>
+
+ * generic/tclTest.c (TestChannelCmd): Removed an unused local variable
+ that caused compilation problems on some platforms.
+
+2003-03-08 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/tcltest.n: Added missing "-body" to example. Thanks to Helmut
+ Giese. [Bug 700011]
+
+2003-03-07 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/io.test:
+ * tests/ioCmd.test: Define a fcopy constraint and add it to the
+ constraint list of any test that depends on the fcopy command. This is
+ only useful to Jacl which does not support fcopy.
+
+2003-03-07 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/encoding.test: Name temp files *.tcltestout instead of *.out
+ so that when they are removed later, we don't accidently toast any
+ files named *.out that the user has created in the build directory.
+
+2003-03-07 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclCmdAH.c (Tcl_FileObjCmd): Fix the setting of a file's
+ mtime and atime on 64-bit platforms. [Bug 698146]
+
+2003-03-06 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/io.test: Doh! Undo accidental commenting out of a couple of
+ tests.
+
+2003-03-06 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/io.test: Define a fileevent constraint and add it to the
+ constraint list of any test that depends on the fileevent command.
+ This is only useful to Jacl which does not support fileevent.
+
+2003-03-06 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/io.test: Define an openpipe constraint and add it to the
+ constraint list of any test that creates a pipe using the open
+ command. This is only useful to Jacl which does not support pipes.
+
+2003-03-06 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/TclUtf.c (Tcl_UniCharNcasecmp): Corrected failure to
+ * tests/utf.test (utf-25.*): properly compare Unicode strings of
+ different case in a case insensitive manner. [Bug 699042]
+
+2003-03-06 Kevin Kenny <kennykb@users.sourceforge.net>
+
+ * generic/tclCompCmds.c (TclCompileSwitchCmd):
+ Replaced a non-portable 'bzero' with a portable 'memset'. [Bug 698442]
+
+2003-03-06 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tclIO.c (Tcl_Seek, Tcl_OutputBuffered): If there is data
+ buffered in the statePtr->curOutPtr member then set the BUFFER_READY
+ flag in Tcl_Seek. This is needed so that the next call to FlushChannel
+ will write any buffered bytes before doing the seek. The existing code
+ would set the BUFFER_READY flag inside the Tcl_OutputBuffered
+ function. This was a programming error made when Tcl_OutputBuffered
+ was originally created in CVS revision 1.35. The setting of the
+ BUFFER_READY flag should not have been included in the
+ Tcl_OutputBuffered function.
+ * generic/tclTest.c (TestChannelCmd): Use the Tcl_InputBuffered and
+ Tcl_OutputBuffered util methods to query the amount of buffered input
+ and output.
+
+2003-03-06 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tclIO.c (Tcl_Flush): Compare the nextAdded member of the
+ ChannelBuffer to the nextRemoved member to determine if any output has
+ been buffered. The previous check against the value 0 seems to have
+ just been a coding error. See other methods like Tcl_OutputBuffered
+ for examples where nextAdded is compared to nextRemoved to find the
+ number of bytes buffered.
+
+2003-03-06 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tclIO.c (Tcl_GetsObj): Check that the eol pointer has not
+ gone past the end of the string when in auto translation mode and the
+ INPUT_SAW_CR flag is set. The previous code worked because the end of
+ string value \0 was being compared to \n, this patch just skips that
+ pointless check.
+
+2003-03-06 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tclIO.c (WriteBytes, WriteChars, Tcl_GetsObj, ReadBytes):
+ Rework calls to TranslateOutputEOL to make it clear that a boolean
+ value is being returned. Add some comments in an effort to make the
+ code more clear. This patch makes no functional changes.
+
+2003-03-06 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tclIO.c (Tcl_SetChannelOption): Invoke the
+ Tcl_SetChannelBufferSize method as a result of changing the
+ -buffersize option to fconfigure. The previous implementation used
+ some inlined code that reset the buffer size to the default size
+ instead of ignoring the request as implemented in
+ Tcl_SetChannelBufferSize.
+ * tests/io.test: Update test case so that it actually checks the
+ implementation of Tcl_SetChannelBufferSize.
+
+2003-03-05 David Gravereaux <davygrvy@pobox.com>
+
+ * win/rules.vc: updated default tcl version to 8.5.
+
+2003-03-05 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * generic/tclCompCmds.c (TclCompileSwitchCmd): First attempt at a
+ bytecode-compiled switch command. It only handles the most common case
+ of switching, but that should be enough for this to speed up a lot of
+ people's code. It is expected that the speed gains come from two
+ things: better handling of the switch itself, and integrated
+ compilation of the arms instead of embedding separate bytecode
+ sequences (i.e. better local variable handling.)
+ * tests/switch.test (switch-10.*): Tests of both uncompiled and
+ compiled switch behaviour. [Patch #644819]
+
+ * generic/tclCompile.h (TclFixupForwardJumpToHere): Additional macro
+ to make the most common kind of jump fixup a bit easier.
+
+2003-03-04 Don Porter <dgp@users.sourceforge.net>
+
+ * README: Bumped version number of
+ * generic/tcl.h: Tcl to 8.5a0.
+ * library/init.tcl:
+ * mac/README:
+ * macosx/Tcl.pbproj/project.pbxproj:
+ * tests/basic.test:
+ * tools/configure.in:
+ * tools/tcl.hpj.in:
+ * tools/tcl.wse.in:
+ * unix/configure.in:
+ * unix/tcl.spec:
+ * win/README:
+ * win/README.binary:
+ * win/configure.in:
+ * win/makefile.bc:
+ * win/makefile.vc:
+ * win/tcl.m4:
+
+ * tools/configure: autoconf
+ * unix/configure:
+ * win/configure:
+
+2003-03-03 Jeff Hobbs <jeffh@ActiveState.com>
+
+ *** 8.4.2 TAGGED FOR RELEASE ***
+
+2003-03-03 Daniel Steffen <das@users.sourceforge.net>
+
+ Mac OS Classic specific fixes:
+ * generic/tclIOUtil.c (TclNewFSPathObj): on TCL_PLATFORM_MAC, skip
+ potential directory separator at the beginning of addStrRep.
+ * mac/tclMacChan.c (OpenFileChannel, CommonWatch): followup fixes to
+ cut and splice implementation for file channels.
+ * mac/tclMacFile.c (TclpUtime): pass native path to utime().
+ * mac/tclMacFile.c (TclpObjLink): correctly implemented creation of
+ alias files via new static proc CreateAliasFile().
+ * mac/tclMacPort.h: define S_ISLNK macro to fix stat'ing of links.
+ * mac/tclMacUtil.c (FSpLocationFromPathAlias): fix to enable stat'ing
+ of broken links.
+
+2003-03-03 Kevin Kenny <kennykb@users.sourceforge.net>
+
+ * win/Makefile.vc: corrected bug introduced by 'g' for debug builds.
+
+2003-03-03 Don Porter <dgp@users.sourceforge.net>
+
+ * library/dde/pkgIndex.tcl: dde bumped to version 1.2.1 for
+ * win/tclWinDde.c: bundled release with Tcl 8.4.2
+
+ * library/reg/pkgIndex.tcl: registry bumped to version 1.1.1 for
+ * win/tclWinReg.c: bundled release with Tcl 8.4.2
+
+ * library/opt/pkgIndex.tcl: updated package index to version 0.4.4
+
+2003-02-28 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/configure:
+ * win/configure.in: check for 'g' for debug build type, not 'd'.
+ * win/rules.vc (DBGX): correct to use 'g' for nmake win makefile to
+ match the cygwin makefile for debug builds. [Bug 635107]
+
+2003-02-28 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * doc/file.n: subcommand is 'file volumes' not 'file volume'
+
+2003-02-27 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclIOUtil.c (MakeFsPathFromRelative): removed dead code
+ check of typePtr (darley).
+
+ * tests/winTime.test: added note about PCI hardware dependency issues
+ with high performance clock.
+
+2003-02-27 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/lsearch.test (lsearch-10.7):
+ * generic/tclCmdIL.c (Tcl_LsearchObjCmd): Stopped -start option from
+ causing an option when used with an empty list. [Bug 694232]
+
+2003-02-26 Chengye Mao <chengye.geo@yahoo.com>
+
+ * win/tclWinInit.c: fixed a bug in TclpSetVariables by initializing
+ dwUserNameLen with the sizeof(szUserName) before calling GetUserName.
+ Don't know if this bug has been recorded: it caused crash in starting
+ Tcl or wish in Windows.
+
+2003-02-26 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclCmdMZ.c (TraceCommandProc): Fix mem leak when deleting a
+ command that had trace on it. [Bug 693564] (sofer)
+
+2003-02-25 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/pkgMkIndex.n: Modified [pkg_mkIndex] to use -nocase matching
+ * library/package.tcl: of -load patterns, to better accomodate common
+ user errors due to confusion between [package names] names and [info
+ loaded] names.
+
+2003-02-25 Andreas Kupries <andreask@pliers.activestate.com>
+
+ * tests/pid.test: See below [Bug 678412].
+ * tests/io.test: Made more robust against spaces in paths [Bug 678400]
+
+2003-02-25 Miguel Sofer <msofer@users.sf.net>
+
+ * tests/execute.test: cleaning up testobj's at the end, to avoid
+ leak warning by valgrind.
+
+2003-02-22 Zoran Vasiljevic <zoran@archiwrae.com>
+
+ * generic/tclEvent.c (Tcl_FinalizeThread): Fix [Bug 571002]
+
+2003-02-21 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/binary.test (binary-44.[34]):
+ * generic/tclBinary.c (ScanNumber): Fixed problem with unwanted
+ sign-bit propagation when scanning wide ints. [Bug 690774]
+
+2003-02-21 Daniel Steffen <das@users.sourceforge.net>
+
+ * mac/tclMacChan.c (TclpCutFileChannel, TclpSpliceFileChannel):
+ Implemented missing cut and splice procs for file channels.
+
+2003-02-21 Don Porter <dgp@users.sourceforge.net>
+
+ * library/package.tcl (tclPkgUnknown): Minor performance tweaks to
+ reduce the number of [file] invocations. Meant to improve startup
+ times, at least a little bit. [Patch 687906]
+
+2003-02-20 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tcl.m4:
+ * unix/tclUnixPipe.c: (macosx) use vfork() instead of fork() to create
+ new processes, as recommended by Apple (vfork can be up to 100 times
+ faster thank fork on macosx).
+ * unix/configure: regen.
+
+2003-02-20 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclEncoding.c (LoadTableEncoding):
+ * library/encoding/cp932.enc: Correct jis round-trip encoding
+ * library/encoding/euc-jp.enc: by adding 'R' type to .enc files.
+ * library/encoding/iso2022-jp.enc: [Patch 689341] (koboyasi, taguchi)
+ * library/encoding/jis0208.enc:
+ * library/encoding/shiftjis.enc:
+ * tests/encoding.test:
+
+ * unix/tclUnixChan.c (Tcl_MakeTcpClientChannel): add
+ MakeTcpClientChannelMode that takes actual mode flags to avoid hang on
+ OS X (may be OS X bug, but patch works x-plat). [Bug 689835] (steffen)
+
+2003-02-20 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/regsub.n: Typo fix [Bug 688943]
+
+2003-02-19 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tclUnixThrd.c (TclpReaddir):
+ * unix/tclUnixPort.h: update to Bug 689100 patch to ensure that there
+ is a defined value of MAXNAMLEN (aka NAME_MAX in POSIX) and that we
+ have some buffer allocated.
+
+2003-02-19 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tclStringObj.c: restored Tcl_SetObjLength() side-effect of
+ always invalidating unicode rep (if the obj has a string rep). Added
+ hasUnicode flag to String struct, allows decoupling of validity of
+ unicode rep from buffer size allocated to it (improves memory
+ allocation efficiency). [Bugs 686782, 671138, 635200]
+
+ * macosx/Tcl.pbproj/project.pbxproj:
+ * macosx/Makefile: reworked embedded build to no longer require
+ relinking but to use install_name_tool instead to change the
+ install_names for embedded frameworks. [Bug 644510]
+
+ * macosx/Tcl.pbproj/project.pbxproj: preserve mod dates when running
+ 'make install' to build framework (avoids bogus rebuilds of dependent
+ frameworks because tcl headers appear changed).
+
+ * tests/ioCmd.test (iocmd-1.8): fix failure when system encoding is
+ utf-8: use iso8859-1 encoding explicitly.
+
+2003-02-18 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompile.c (TclCompileExprWords): remove unused variable
+ "range" [Bug 664743]
+ * generic/tclExecute.c (ExprSrandFunc): remove unused variable
+ "result" [Bug 664743]
+ * generic/tclStringObj.c (UpdateStringOfString): remove unused
+ variable "length" [Bug 664751]
+ * tests/execute.test (execute-7.30): fix for [Bug 664775]
+
+2003-02-18 Andreas Kupries <andreask@activestate.com>
+
+ * unix/tcl.m4: [Bug #651811] Added definition of _XOPEN_SOURCE and
+ linkage of 'xnet' library to HP 11 branch. This kills a lot of
+ socket-related failures in the testsuite when Tcl was compiled in 64
+ bit mode (both PA-RISC 2.0W, and IA 64).
+
+ * unix/configure: Regenerated.
+
+2003-02-18 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclIO.c (HaveVersion): correctly decl static
+
+ * unix/tclUnixThrd.c (TclpReaddir): reduce size of name string in tsd
+ to NAME_MAX instead of PATH_MAX. [Bug 689100] (waters)
+
+2003-02-18 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4 (SC_ENABLE_THREADS): Make sure -lpthread gets passed on
+ the link line when checking for the pthread_attr_setstacksize symbol.
+
+2003-02-18 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclTest.c: cleanup of new 'simplefs' test code, and better
+ documentation.
+
+2003-02-17 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclBasic.c (TclRenameCommand): fixing error in previous
+ commit.
+
+2003-02-17 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclExecute.c (TclExecuteByteCode INST_STR_MATCH):
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd STR_MATCH):
+ * generic/tclUtf.c (TclUniCharMatch):
+ * generic/tclInt.decls: add private TclUniCharMatch function that
+ * generic/tclIntDecls.h: does string match on counted unicode
+ * generic/tclStubInit.c: strings. Tcl_UniCharCaseMatch has the failing
+ * tests/string.test: that it can't handle strings or patterns with
+ * tests/stringComp.test: embedded NULLs. Added tests that actually try
+ strings/pats with NULLs. TclUniCharMatch should be TIPed and made
+ public in the next minor version rev.
+
+2003-02-17 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclBasic.c (TclRenameCommand): 'oldFullName' object was not
+ being freed on all function exits, causing a memory leak. [Bug 684756]
+
+2003-02-17 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tclIO.c (Tcl_GetsObj): Minor change so that eol is only
+ assigned at the top of the TCL_TRANSLATE_AUTO case block. The other
+ cases assign eol so this does not change any functionality.
+
+2003-02-17 Kevin Kenny <kennykb@users.sourceforge.net>
+
+ * tests/notify.test: Removed Windows line terminators. [Bug 687913].
+
+2003-02-15 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclBasic.c (Tcl_EvalEx):
+ * generic/tclCompExpr.c (CompileSubExpr):
+ * generic/tclCompile.c (TclCompileScript):
+ * generic/tclParse.c (Tcl_ParseCommand, ParseTokens):
+ * generic/tclParseExpr.c (ParsePrimaryExpr):
+ * tests/basic.test (47.1):
+ * tests/main.test (3.4):
+ * tests/misc.test (1.2):
+ * tests/parse.test (6.18):
+ * tests/parseExpr.test (15.35):
+ * tests/subst.test (8.6): Don Porter's fix for bad parsing of nested
+ scripts. [Bug 681841]
+
+2003-02-15 Kevin Kenny <kennykb@users.sourceforge.net>
+
+ * tests/notify.test (new-file):
+ * generic/tclTest.c (TclTest_Init, EventtestObjCmd, EventtestProc,
+ (EventTestDeleteProc):
+ * generic/tclNotify.c (Tcl_DeleteEvents): Fixed Tcl_DeleteEvents not
+ to get a pointer smash when deleting the last event in the queue.
+ Added test code in 'tcltest' and a new file of test cases
+ 'notify.test' to exercise this functionality; several of the new test
+ cases fail for the original code and pass for the corrected code. [Bug
+ 673714]
+
+ * unix/tclUnixTest.c (TestfilehandlerCmd): Corrected a couple of typos
+ in error messages. [Bug 596027]
+
+2003-02-14 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * README: Bumped to version 8.4.2.
+ * generic/tcl.h:
+ * tools/tcl.wse.in:
+ * unix/configure:
+ * unix/configure.in:
+ * unix/tcl.m4:
+ * unix/tcl.spec:
+ * win/README.binary:
+ * win/configure:
+ * win/configure.in:
+ * macosx/Tcl.pbproj/project.pbxproj:
+
+ * generic/tclStringObj.c (Tcl_GetCharLength): perf tweak
+
+ * unix/tcl.m4: correct HP-UX ia64 --enable-64bit build flags
+
+2003-02-14 Kevin Kenny <kennykb@users.sourceforge.net>
+
+ * win/tclWinTime.c: Added code to test and compensate for forward
+ leaps of the performance counter. See the MSDN Knowledge Base article
+ Q274323 for the hardware problem that makes this necessary on certain
+ machines.
+ * tests/winTime.test: Revised winTime-2.1 - it had a tolerance of
+ thousands of seconds, rather than milliseconds. (What's six orders of
+ magnitude among friends?) Both the above changes are triggered by a
+ problem reported at:
+ http://aspn.activestate.com/ASPN/Mail/Message/ActiveTcl/1536811
+ although the developers find it difficult to believe that it accounts
+ for the observed behavior and suspect a fault in the RTC chip.
+
+2003-02-13 Kevin Kenny <kennykb@users.sourceforge.net>
+
+ * win/tclWinInit.c: Added conversion from the system encoding to
+ tcl_platform(user), so that it works with non-ASCII7 user names. [Bug
+ 685926]
+
+ * doc/tclsh.1: Added language to describe the handling of the
+ end-of-file character \u001a embedded in a script file. [Bug 685485]
+
+2003-02-11 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/fileName.test:
+ * unix/tclUnixFile.c: fix for [Bug 685445] when using 'glob -l' on
+ broken symbolic links. Added two new tests for this bug.
+
+2003-02-11 Kevin Kenny <kennykb@users.sourceforge.net>
+
+ * tests/http.test: Corrected a problem where http-4.14 would fail when
+ run in an environment with a proxy server. Replaced references to
+ scriptics.com by tcl.tk.
+
+2003-02-11 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/lsearch.test:
+ * generic/tclCmdIL.c (Tcl_LsearchObjCmd): protect against the case
+ that lsearch -regepx list and pattern objects are equal.
+
+ * tests/stringObj.test:
+ * generic/tclStringObj.c (Tcl_GetCharLength): correct ascii char opt
+ of 2002-11-11 to not stop early on \x00. [Bug 684699]
+
+ * tests.parse.test: remove excess EOF whitespace
+
+ * generic/tclParse.c (CommandComplete): more paranoid check to break
+ on (p >= end) instead of just (p == end).
+
+2003-02-11 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclParse.c (CommandComplete):
+ * tests/parse.test: fix for [Bug 684744], by Don Porter.
+
+2003-02-11 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclIOUtil.c (Tcl_FSJoinPath, Tcl_FSGetNormalizedPath):
+ (UpdateStringOfFsPath): revert the cwdLen == 0 check and instead
+ follow a different code path in Tcl_FSJoinPath.
+ (Tcl_FSConvertToPathType, Tcl_FSGetNormalizedPath):
+ (Tcl_FSGetFileSystemForPath): Update string rep of path objects before
+ freeing the internal object. (darley)
+
+ * tests/fileSystem.test: added test 8.3
+ * generic/tclIOUtil.c (Tcl_FSGetNormalizedPath):
+ (UpdateStringOfFsPath): handle the cwdLen == 0 case
+
+ * unix/tclUnixFile.c (TclpMatchInDirectory): simplify the hidden file
+ match check.
+
+2003-02-10 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/configure:
+ * win/configure.in: Generate error when attempting to build under
+ Cygwin. The Cygwin port of Tcl/Tk does not build and people are filing
+ bug reports under the mistaken impression that someone is actually
+ maintaining the Cygwin port. A post to comp.lang.tcl asking someone to
+ volunteer as an area maintainer has generated no results. Closing bugs
+ 680840, 630199, and 634772 and marking as "Won't fix".
+
+2003-02-10 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/append.n: Return value was not documented. [Bug 683188]
+
+2003-02-10 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * doc/FileSystem.3:
+ * generic/tclIOUtil.c:
+ * generic/tclInt.h:
+ * tests/fileSystem.test:
+ * unix/tclUnixFCmd.c:
+ * unix/tclUnixFile.c:
+ * win/tclWinFile.c: further filesystem optimization, applying [Patch
+ 682500]. In particular, these code examples are faster now:
+ foreach f $flist { if {[file exists $f]} {file stat $f arr;...}}
+ foreach f [glob -dir $dir *] { # action and/or recursion on $f }
+ cd $dir
+ foreach f [glob *] { # action and/or recursion on $f }
+ cd ..
+
+ * generic/tclTest.c: Fix for [Bug 683181] where test suite left files
+ in 'tmp'.
+
+2003-02-08 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * library/safe.tcl: code cleanup of eval and string comp use.
+
+2003-02-07 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * win/tclWinFCmd.c: cleanup long lines
+ * win/tclWinFile.c: sped up pure 'glob' by a factor of 2.5
+ ('foreach f [glob *] { file exists $f }' is still slow)
+ * tests/fileSystem.text:
+ * tests/fileName.test: added new tests to ensure correct behaviour in
+ optimized filesystem code.
+
+2003-02-07 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclTest.c:
+ * tests/fileSystem.text: fixed test 7.2 to avoid a possible crash, and
+ not change the pwd.
+
+ * tests/http.text: added comment to test 4.15, that it may fail if you
+ use a proxy server.
+
+2003-02-06 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tclCompCmds.c (TclCompileIncrCmd):
+ * tests/incr.test: Don't include the text "(increment expression)" in
+ the errorInfo generated by the compiled version of the incr command
+ since it does not match the message generated by the non-compiled
+ version of incr. It is also not possible to match this error output
+ under Jacl, which does not support a compiler.
+
+2003-02-06 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tclExecute.c (TclExecuteByteCode): When an error is
+ encountered reading the increment value during a compiled call to
+ incr, add a "(reading increment)" error string to the errorInfo
+ variable. This makes the errorInfo variable set by the compiled incr
+ command match the value set by the non-compiled version.
+ * tests/incr-old.test: Change errorInfo result for the compiled incr
+ command case to match the modified implementation.
+ * tests/incr.test: Add tests to make sure the compiled and
+ non-compiled errorInfo messages are the same.
+
+2003-02-06 Don Porter <dgp@users.sourceforge.net>
+
+ * library/tcltest/tcltest.tcl: Filename arguments to [outputChannel]
+ and [errorChannel] (also -outfile and -errfile) were [open]ed but
+ never [closed]. Also, [cleanupTests] could remove output or error
+ files. [Bug 676978].
+ * library/tcltest/pkgIndex.tcl: Bumped to version 2.2.2.
+
+2003-02-05 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/interp.test:
+ * tests/set-old.test: Run test cases that depend on hash order through
+ lsort so that the tests also pass under Jacl. Does not change test
+ results under Tcl.
+
+2003-02-04 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclIOUtil.c:
+ * generic/tclEvent.c:
+ * generic/tclInt.h:
+ * mac/tclMacFCmd.c:
+ * unix/tclUnixFCmd.c:
+ * win/tclWin32Dll.c:
+ * win/tclWinFCmd.c:
+ * win/tclWinInit.c:
+ * win/tclWinInt.h:
+ * tests/fileSystem.test: fix to finalization/unloading/encoding issues
+ to make filesystem much less dependent on encodings for its cleanup,
+ and therefore allow it to be finalized later in the exit process. This
+ fixes fileSystem.test-7.1. Also fixed one more bug in setting of
+ modification dates of files which have undergone cross-platform
+ copies. [Patch 676271]
+
+ * tests/basic.test:
+ * tests/exec.test:
+ * tests/fileName.test:
+ * tests/io.test: fixed some test failures when tests are run from a
+ directory containing spaces.
+
+ * tests/fileSystem.test:
+ * generic/tclTest.c: added regression test for the modification date
+ setting of cross-platform file copies.
+
+2003-02-03 Kevin Kenny <kennykb@users.sourceforge.net>
+
+ * generic/tclBasic.c: Changed [trace add command] so that 'rename'
+ callbacks get fully qualified names of the command. [Bug 651271].
+ ***POTENTIAL INCOMPATIBILITY***
+ * tests/trace.test: Modified the test cases for [trace add command] to
+ expect fully qualified names on the 'rename' callbacks. Added a case
+ for renaming a proc within a namespace.
+ * doc/trace.n: Added language about use of fully qualified names in
+ trace callbacks.
+
+2003-02-01 Kevin Kenny <kennykb@users.sourceforge.net>
+
+ * generic/tclCompCmds.c: Removed an unused variable that caused
+ compiler warnings on SGI. [Bug 664379]
+
+ * generic/tclLoad.c: Changed the code so that if Tcl_StaticPackage is
+ called to report the same package as being loaded in two interps, it
+ shows up in [info loaded {}] in both of them (previously, it didn't
+ appear in the static package list in the second).
+
+ * tests/load.test Added regression test for the above bug. [Bug
+ 670042]
+
+ * generic/tclClock.c: Fixed a bug that incorrectly allowed [clock
+ clicks {}] and [clock clicks -] to be accepted as if they were [clock
+ clicks -milliseconds].
+
+ * tests/clock.test: Added regression tests for the above bug. [Bug
+ 675356]
+
+ * tests/unixNotfy.test: Added cleanup of working files. [Bug 675609]
+
+ * doc/Tcl.n: Added headings to the eleven paragraphs, to improve
+ formatting in the tools that attempt to extract tables of contents
+ from the manual pages. [Bug 627455]
+
+ * generic/tclClock.c: Expanded mutex protection around the setting of
+ env(TZ) and the thread-unsafe call to tzset(). [Bug 656660]
+
+2003-01-31 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/tcltest.test: Cleaned up management of file/directory
+ creation/deletion to improve "-debug 1" output. [Bug 675614]
+ The utility [slave] command failed to properly [list]-quote a
+ constructed [open] command, causing failure when the pathname
+ contained whitespace. [Bug 678415]
+
+ * tests/main.test: Stopped main.test from deleting existing file. Test
+ suite should not delete files that already exist. [Bug 675660]
+
+2003-01-28 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/main.test: Constrain tests that do not work on Windows. [Bug
+ 674387]
+
+2003-01-28 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclIOUtil.c: fix to setting modification date in
+ TclCrossFilesystemCopy. Also added 'panic' in
+ Tcl_FSGetFileSystemForPath under illegal calling circumstances which
+ lead to hard-to-track-down bugs.
+
+ * generic/tclTest.c: added test suite code to allow exercising a
+ vfs-crash-on-exit bug in Tcl's finalization caused by the encodings
+ being cleaned up before unloading occurs.
+ * tests/fileSystem.test: added new 'knownBug' test 7.1 to demonstrate
+ the crash on exit.
+
+2003-01-28 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tcl.h: Add TCL_PREFIX_IDENT and TCL_DEBUG_IDENT, used only
+ by TclpCreateProcess.
+ * unix/Makefile.in: Define TCL_DBGX.
+ * win/Makefile.in: Define TCL_DBGX.
+ * win/tclWinPipe.c (TclpCreateProcess): Check that the Tcl pipe dll
+ actually exists in the Tcl bin directory and panic if it is not found.
+ Incorporate TCL_DBGX into the Tcl pipe dll name. This fixes a really
+ mysterious error that would show up when exec'ing a 16 bit application
+ under Win95 or Win98 when Tcl was compiled with symbols. The error
+ seemed to indicate that the executable could not be found, but it was
+ actually the Tcl pipe dll that could not be found.
+
+2003-01-26 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/README: Update msys+mingw URL to release 6. This version bundles
+ gcc 3.
+
+2003-01-26 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/configure: Regen.
+ * win/configure.in: Add test that checks to see if the compiler can
+ cast to a union type.
+ * win/tclWinTime.c: Squelch compiler warning about union initializer
+ by casting to union type when compiling with gcc.
+
+2003-01-25 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tclIO.c (Tcl_CutChannel, Tcl_SpliceChannel): Invoke
+ TclpCutFileChannel and TclpSpliceFileChannel.
+ * generic/tclInt.h: Declare TclpCutFileChannel and
+ TclpSpliceFileChannel.
+ * unix/tclUnixChan.c (FileCloseProc, TclpOpenFileChannel,
+ (Tcl_MakeFileChannel, TclpCutFileChannel, TclpSpliceFileChannel):
+ Implement thread load data cut and splice for file channels. This
+ avoids an invalid memory ref when compiled with -DDEPRECATED.
+ * win/tclWinChan.c (FileCloseProc, TclpCutFileChannel,
+ (TclpSpliceFileChannel): Implement thread load data cut and splice for
+ file channels. This avoids an invalid memory ref that was showing up
+ in the thread extension.
+
+2003-01-25 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tclWin32Dll.c (TclpCheckStackSpace, squelch_warnings):
+ * win/tclWinChan.c (Tcl_MakeFileChannel, squelch_warnings):
+ * win/tclWinFCmd.c (DoRenameFile, DoCopyFile, squelch_warnings):
+ Re-implement inline ASM SEH handlers for gcc. The esp and ebp
+ registers are now saved on the stack instead of in global variables so
+ that the code is thread safe. Add additional checks when TCL_MEM_DEBUG
+ is defined to be sure the values were recovered from the stack
+ properly. Remove squelch_warnings functions and add a dummy call in
+ the handler methods to squelch compiler warnings.
+
+2003-01-25 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/configure:
+ * win/configure.in: Define HAVE_ALLOCA_GCC_INLINE when we detect that
+ no alloca function is found in malloc.h and we are compiling with GCC.
+ Remove HAVE_NO_ALLOC_DECL define.
+ * win/tclWin32Dll.c (TclpCheckStackSpace): Don't define alloca as a
+ cdecl function. Doing this caused a tricky runtime bug because the
+ _alloca function expects the size argument to be passed in a register
+ and not on the stack. To fix this problem, we use inline ASM when
+ compiling with gcc to invoke _alloca with the size argument loaded
+ into a register.
+
+2003-01-24 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tclWinDde.c (Dde_Init): clarified use of tsdPtr.
+ (DdeServerProc): better refcount handling of returnPackagePtr.
+
+ * generic/tclEvent.c (Tcl_Finalize): revert finalize change on
+ 2002-12-04 to correct the issue with extensions that have TSD needing
+ to finalize that before they are unloaded. This issue needs further
+ clarification.
+
+ * tests/unixFCmd.test: only do groups check on unix
+
+2003-01-24 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclStringObj.c: proper fixes for Tcl_SetObjLength and
+ Tcl_AttemptSetObjectLength dealing with string objects with both
+ pure-unicode and normal internal representations. Previous fix didn't
+ handle all cases correctly.
+ * generic/tclIO.c: Add 'Tcl_GetString()' to ensure the object has a
+ valid 'objPtr->bytes' field before manipulating it directly.
+
+ This fixes [Bug 635200] and [Bug 671138], but may reduce performance
+ of Unicode string handling in some cases. A further patch will be
+ applied to address this, once the code is known to be correct.
+
+2003-01-24 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/configure: Regen.
+ * win/configure.in: Add test to see if alloca is undefined in
+ malloc.h.
+ * win/tclWin32Dll.c (TclpCheckStackSpace): Rework the SEH exception
+ handler logic to avoid using the stack since alloca will modify the
+ stack. This was causing a nasty bug that would set the exception
+ handler to 0 because it tried to pop the previous exception handler
+ off the top of the stack.
+
+2003-01-23 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/lset.n: Fixed fault in return values from lset in documentation
+ examples [SF Bug #658463] and tidied up a bit at the same time.
+
+2003-01-21 Joe English <jenglish@users.sourceforge.net>
+
+ * doc/namespace.n (namespace inscope): Clarified documentation
+ [Patch 670110]
+
+2003-01-21 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/configure: Regen.
+ * win/tcl.m4 (SC_CONFIG_CFLAGS): Set SHLIB_SUFFIX so that
+ TCL_SHLIB_SUFFIX will be set to a useful value in the generated
+ tclConfig.sh. Set SHLIB_LD_LIBS to "" or '${LIBS}' based on the
+ --enable-shared flag. This matches the UNIX implementation.
+
+2003-01-18 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclCkalloc.c: change %ud to %u as appropriate.
+
+2003-01-17 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tclWinDde.c (DdeServerProc): Deallocate the Tcl_Obj returned by
+ ExecuteRemoteObject if it was not saved in a connection object.
+
+2003-01-17 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tcl.h: Revert earlier change that defined TCL_WIDE_INT_TYPE
+ as long long and TCL_LL_MODIFIER as L when compiling with mingw. This
+ change ended up causing some test case failures when compiling with
+ mingw.
+ * generic/tclObj.c (UpdateStringOfWideInt): Describe the warning
+ generated by mingw and why it needs to be ignored so that someone is
+ not tempted to "fix" this problem again in the future.
+
+2003-01-16 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclStringObj.c: Tcl_SetObjLength fix for when the object has
+ a unicode string rep. [Bug 635200]
+ * tests/stringObj.test: removed 'knownBug' constraint from test 14.1
+ now that this bug is fixed.
+
+ * generic/tclInt.h:
+ * generic/tclBasic.c:
+ * generic/tclCmdMZ.z:
+ * tests/trace.test: execution and command tracing bug fixes and
+ cleanup. In particular fixed [Bug 655645], [Bug 615043], [Bug 571385]
+ - fixed some subtle cleanup problems with tracing. This required
+ replacing Tcl_Preserve/Tcl_Release with a more robust refCount
+ approach. Solves at least one known crash caused by memory
+ corruption.
+ - fixed some confusion in the code between new style traces (Tcl
+ 8.4) and the very limited 'Tcl_CreateTrace' which existed before.
+ - made behaviour consistent with documentation (several tests even
+ contradicted the documentation before).
+ - fixed some minor error message details
+ - added a number of new tests
+
+2003-01-16 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tclWinSerial.c (SerialOutputProc): add casts for bytesWritten to
+ allow strict compilation (no warnings).
+
+ * tests/winDde.test:
+ * win/tclWinDde.c (Tcl_DdeObjCmd): Prevent crash when empty service
+ name is passed to 'dde eval' and goto errorNoResult in request and
+ poke error cases to free up any allocated data.
+
+2003-01-16 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tclWin32Dll.c (squelch_warnings): Squelch compiler warnings from
+ SEH ASM code.
+ * win/tclWinChan.c (squelch_warnings): Squelch compiler warnings from
+ SEH ASM code.
+ * win/tclWinDde.c: Add casts to avoid compiler warnings. Pass pointer
+ to DWORD instead of int to avoid compiler warnings.
+ * win/tclWinFCmd.c (squelch_warnings): Add casts and fixup decls to
+ avoid compiler warnings. Squelch compiler warnings from SEH ASM code.
+ * win/tclWinFile.c: Add casts and fixup decls to avoid compiler
+ warnings. Remove unused variable.
+ * win/tclWinNotify.c: Declare as DWORD instead of int to avoid
+ compiler warning.
+ * win/tclWinReg.c: Add casts to avoid compiler warning. Fix assignment
+ in if expression bug.
+ * win/tclWinSerial.c: Add casts to avoid compiler warnings. Remove
+ unused variable.
+ * win/tclWinSock.c: Add casts and fixup decls to avoid compiler
+ warnings.
+
+2003-01-14 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclClock.c (FormatClock): corrected typo that incorrectly
+ conditionally defined savedTZEnv and savedTimeZone.
+
+2003-01-13 Mo DeJong <mdejong@users.sourceforge.net>
+
+ Fix mingw build problems and compiler warnings.
+
+ * generic/tcl.h: Add if defined(__MINGW32__) check to code that sets
+ the TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER.
+ * generic/tclClock.c (FormatClock): Don't define savedTimeZone and
+ savedTZEnv if we are not going to use them.
+ * generic/tclEnv.c: Add cast to avoid warning.
+ * win/tclWinChan.c: Use DWORD instead of int to avoid compiler warning
+ * win/tclWinThrd.c: Only define allocLock, allocLockPtr, and dataKey
+ when TCL_THREADS is defined. This avoid a compiler warning about
+ unused variables.
+
+2003-01-12 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/README: Update msys + mingw URL, the new release includes the
+ released 1.0.8 version of msys which includes a number of bug fixes.
+
+2003-01-12 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/configure: Regen.
+ * win/tcl.m4 (SC_CONFIG_CFLAGS): Pull in addition of shell32.lib to
+ LIBS_GUI that was added to the Tk tcl.m4 but never made it back into
+ the Tcl version.
+
+2003-01-12 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tcl.h: Skip Tcl's define of CHAR, SHORT, and LONG when
+ HAVE_WINNT_IGNORE_VOID is defined. This avoids a bunch of compiler
+ warnings when building with Cygwin or Mingw.
+ * win/configure: Regen.
+ * win/configure.in: Define HAVE_WINNT_IGNORE_VOID when we detect a
+ winnt.h that still defines CHAR, SHORT, and LONG when VOID has already
+ been defined.
+ * win/tcl.m4 (SC_LOAD_TCLCONFIG): Subst the TCL_DEFS loaded from
+ tclConfig.sh so that Tcl defines can make it into the Tk Makefile.
+
+2003-01-12 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/configure: Regen.
+ * win/configure.in: Check for typedefs like LPFN_ACCEPT in winsock2.h
+ and define HAVE_NO_LPFN_DECLS if not found.
+ * win/tclWinSock.c: Define LPFN_* typedefs if HAVE_NO_LPFN_DECLS is
+ defined. This fixes the build under Mingw and Cygwin, it was broken by
+ the changes made on 2002-11-26.
+
+2003-01-10 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclIOUtil.c:
+ * win/tclWinInt.h:
+ * win/tclWinInit.c: fix to new WinTcl crash on exit with vfs,
+ introduced on 2002-12-06. Encodings must be cleaned up after the
+ filesystem.
+
+ * win/makefile.vc: fix to minor VC++ 5.2 syntax problem
+
+2003-01-09 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCompCmds.c (TclCompileReturnCmd): Corrected off-by-one
+ problem with recent commit. [Bug 633204]
+
+2003-01-09 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclFileName.c: remove unused variable 'macSpecialCase'
+ [Bug 664749]
+
+ * generic/tclIOUtil.c:
+ * generic/tclInt.h:
+ * unix/tclUnixFile.c:
+ * mac/tclMacFile.c:
+ * win/tclWinFile.c:
+ * win/tclWinInt.h:
+ * win/tclWin32Dll.c:
+ * tests/cmdAH.test: fix to non-ascii chars in paths when setting mtime
+ and atime through 'file (a|m)time $path $time'. [Bug 634151]
+
+2003-01-08 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclExecute.c (TclExprFloatError): Use the IS_NAN macro for
+ greater clarity of code.
+
+2003-01-07 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCompCmds.c (TclCompileReturnCmd):
+ * tests/compile.test: Corrects failure of bytecompiled [catch
+ {return}] to have result TCL_RETURN (not TCL_OK) [Bug 633204]. This
+ patch is a workaround for 8.4.X. A new opcode INST_RETURN is a better
+ long term solution for 8.5 and later.
+
+2003-01-04 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc:
+ * win/rules.vc: Fixed INSTALLDIR macro problem that blanked itself by
+ accident causing the install target to put the tree at the root of the
+ drive built on. Whoops..
+
+ Renamed the 'linkexten' option to be 'staticpkg'. Added 'thrdalloc' to
+ allow the switching _on_ of the thread allocator. Under testing, I
+ found it not to be benificial under windows for the purpose of the
+ application I was using it for. It was more important for this app
+ that resources for tcl threads be returned to the system rather than
+ saved/moved to the global recycler. Be extra clean or extra fast for
+ the default threaded build? Let's move to clean and allow it to be
+ switched on for users who find it benificial for their use of threads.
+
+ ******************************************************************
+ *** CHANGELOG ENTRIES FOR 2002 IN "ChangeLog.2002" ***
+ *** CHANGELOG ENTRIES FOR 2001 IN "ChangeLog.2001" ***
+ *** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000" ***
+ *** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" ***
+ ******************************************************************
diff --git a/ChangeLog.2004 b/ChangeLog.2004
new file mode 100644
index 0000000..82acd5c
--- /dev/null
+++ b/ChangeLog.2004
@@ -0,0 +1,4619 @@
+2004-12-29 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tcl.m4, win/configure: update MSVC CFLAGS_OPT to -O2, remove -Gs
+ (included in -O2) and -GD (outdated). Use "link -lib" instead of "lib"
+ binary and remove -YX for MSVC7 portability. Add -fomit-frame-pointer
+ for gcc OPT compiles. [Bug 1092952, 1091967] Align LIBS_GUI with Tk
+ head needs.
+
+2004-12-29 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclDate.c: Regen
+ * generic/tclGetDate.y (TclDatelex): Fixed a problem where a
+ four-digit group with >=2 leading zeroes appeared to be a two-digit
+ group, leading to misinterpreting the time 0012 as 1200. [Bug 1090413]
+ * library/clock.tcl: Added code to interpret correctly months outside
+ the range 01-12 as reduced modulo 12 with a corresponding adjustment
+ to the year. [Bug 1092789]
+ * tests/clock.test: Added regression test cases for the above two bugs
+ * unix/Makefile.in: Added --no-lines to the 'bison' command line to
+ * win/Makefile.in: help constrain the number of diffs in a cvs checkin
+
+2004-12-24 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompile.c:
+ * generic/tclCompile.h:
+ * generic/tclExecute.c:
+ * generic/tclInt.h:
+ * generic/tclLiteral.c:
+ * generic/tclProc.c:
+ Avoid sharing cmdName literals accross namespaces, and generalise
+ usage of the TclRegisterNewLiteral macro. [Patch 1090905]
+
+2004-12-20 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompile.c: moved TclInitCompiledLocals to tclProc.c
+ * generic/tclProc.c: new static InitCompiledLocals to allow for a
+ single pass over the proc's arguments at proc load time (instead of
+ two as previously). TclObjInterpProc() now allocates the
+ compiledLocals on the tcl execution stack, using the new
+ TclStackAlloc/Free functions.
+
+2004-12-16 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclInterp.c (Tcl_LimitSetTime, TimeLimitCallback):
+ (TclLimitRemoveAllHandlers, TclInitLimitSupport): Set a timer event to
+ trigger when the time limit runs out. All the time limit actually does
+ is check to see if the time limit has been exceeded, but this is
+ enough to fix [Bug 1085023].
+ * generic/tclInt.h (struct Interp): Added a field to hold the token
+ for the timer event handler associated with the current time limit.
+ * generic/tclEvent.c (Tcl_UpdateObjCmd, Tcl_VwaitObjCmd): Add error
+ message when limit exceeded.
+ * tests/interp.test (interp-34.[89]): Check that time limits handle
+ the two cases reported in [Bug 1085023]
+
+ * generic/tclTimer.c (TclCreateAbsoluteTimerHandler): New internal
+ function that allows setting a timer handler that will be triggered at
+ (or after) a specific time instead of at some number of milliseconds
+ in the future. This is a candidate for future exposure via a TIP.
+
+2004-12-15 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclBasic.c:
+ * generic/tclExecute.c:
+ * generic/tclInt.decls:
+ * generic/tclIntDecls.h:
+ * generic/tclNamesp.c:
+ * generic/tclProc.c:
+ * generic/tclStubInit.c:
+ * generic/tclTest.c: Added two new functions to allocate memory from
+ the execution stack (TclStackAlloc, TclStackFree). Added functions
+ TclPushStackFrame and TclPopStackFrame that do the work of
+ Tcl_PushCallFrame and Tcl_PopCallFrame, but using frames allocated in
+ the execution stack - i.e., heap instead of C-stack. The core uses
+ these two new functions exclusively; the old ones remain for backwards
+ compat, as at least two popular extensions (itcl, xotcl) are known to
+ use them.
+
+2004-12-14 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCmdIL.c:
+ * generic/tclInt.h:
+ * generic/tclProc.c:
+ * generic/tclVar.c: changing the isProcCallFrame field of the
+ CallFrame struct from a 0/1 field to flags. Should be perfectly
+ backwards compatible.
+
+2004-12-14 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/configure.in: Added special processing to remove "$U" from
+ libraries in the LIBOBJS value. This is an auto-make-ism we need to
+ avoid. [Bug 1081541]
+
+ * unix/configure: autoconf-2.57
+
+2004-12-13 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tcl.h: Restored extern "C" guards so that C++ code sees
+ function pointer typedef linkage consistent with earlier Tcl releases.
+ [Bug 1082349]
+
+ * generic/tclEncoding.c: Plugged some memory leaks. Thanks to Rolf Ade
+ * generic/tclUtil.c: for reports and testing [Bug 1083082]
+
+2004-12-13 Kevin B. Kenny <kennykb@acm.org>
+
+ * doc/clock.n: Clarify that the [clock scan] command does not accept
+ the full range of ISO8601 point-in-time formats. [Bug 1075433]
+
+2004-12-12 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclVar.c (TclArrayObjCmd - ARRAY_NAMES): leaking an object
+ [Bug 1084111] - thanks to Rolf Ade.
+
+2004-12-12 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclObj.c (TclSetCmdNameObj): special handling for fully
+ qualified command names (as in fix [Patch 456668]).
+
+2004-12-11 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclInt.h:
+ * generic/tclNamesp.c: converting the static function
+ GetNamespaceFromObj() to MODULE_SCOPE TclGetNamespaceFromObj().
+
+2004-12-10 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tools/tcl.wse.in, unix/tcl.spec, win/README.binary, README:
+ * win/configure.in, unix/configure.in, generic/tcl.h:
+ Bumped version number to 8.5a3 to distinguish HEAD of CVS development
+ from the recent 8.5a2 release.
+
+2004-12-10 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompile.c (TclInitCompiledLocals):
+ * generic/tclCompile.h:
+ * generic/tclInt.h:
+ * generic/tclProc.c (TclObjInterpProc, TclCreateProc): optimised
+ loops that initialise a proc's arguments and compiled local
+ variables, removing tests from inner loops.
+
+2004-12-10 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclInt.h: Move ensemble API decls here from tclNamesp.c
+
+2004-12-09 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclNamesp.c (TclMakeEnsembleCmd, TclSetEnsemble*)
+ (TclSetEnsemble*, TclFindEnsemble): Build an internal API for creating
+ and manipulating ensembles; they can be deleted using the normal
+ command-deletion API.
+
+ * doc/Async.3: Reword for better grammar, better nroff and get the
+ flag name right. (Reported by David Welton.)
+
+2004-12-07 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/unixInit.test (2.1-4): Added constraints so that when a value
+ of TCL_LIBRARY is required for process initialization, we skip the
+ tests that mess with that value.
+
+2004-12-07 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ *** 8.5a2 TAGGED FOR RELEASE ***
+
+ * unix/Makefile.in: add library/{tzdata,msgs} to dist target (kbk)
+
+ * doc/foreach.n: Adjust tabs to be friendlier to some HTML
+ converters. [Bug 1078760]
+
+2004-12-06 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tclUnixNotfy.c (NotifierThreadProc): init numFdBits
+ [Bug 1079286]
+
+ * doc/error.n, doc/SaveResult.3, doc/Thread.3: minor nroff typos
+
+2004-12-06 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/safe.test: Trim auto_path to improve performance [1080039]
+
+ * tests/msgcat.test: makeFile/removeFile cleanup [1079117]
+
+2004-12-04 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclEncoding.c: Different fix for [Bug 1077005].
+ * generic/tclEvent.c: Broke apart TclpSetInitialEncodings() on
+ * generic/tclInt.h: Windows into TclpSetInterfaces(), that is
+ * unix/tclUnixInit.c: fundamentally essential, and the initialization
+ * win/tclWinInit.c: of the system encoding, which is not. Made
+ the TclpSetInterfaces call part of TclInitSubsystems so it cannot be
+ overlooked.
+
+2004-12-03 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * changes: updated for 8.5a2 release
+
+2004-12-02 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclUtil.c (TclSetProcessGlobalValue): Handle the case where
+ a ProcessGlobalValue might be assigned to itself.
+
+ * generic/tclEncoding.c (MakeFileMap): Correct refcounting errors
+ managing values returned by TclPathPart (with refCount of 1!) that led
+ to a memory leak. [Bug 1077474].
+
+2004-12-02 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclPathObj.c: fix and new tests for [Bug 1074671] to ensure
+ * tests/fileSystem.test: tilde paths are not returned specially by
+ 'glob'.
+
+2004-12-02 Kevin B. Kenny <kennykb@acm.org>
+
+ * win/Makefile.in: Added a 'sed' in the setting of ROOT_DIR_NATIVE to
+ compensate for a bug in cygpath (at least version 1.36) that leaves a
+ trailing backslash on the end of the converted path.
+
+2004-12-02 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclInterp.c (Alias,Target,Master): Rewrote these so that the
+ aliases that refer to an interpreter are stored in a list and not a
+ hashtable (which was only ever a convenience, and forced the use of a
+ global mutex to generate keys!) [FRQ 1077210]
+ * generic/tclNamesp.c (numNsCreated): Moved into thread-local storage
+ to remove a global mutex. [FRQ 1077210]
+
+2004-12-01 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclUtil.c (TclGetProcessGlobalValue): Narrowed the scope of
+ mutex locks.
+
+ * generic/tclUtil.c: Updated Tcl_GetNameOfExecutable() to
+ * generic/tclEncoding.c: make use of a ProcessGlobalValue for
+ * generic/tclEvent.c: storing the executable name. Added
+ internal routines Tcl(Get|Set)ObjNameOfExecutable() to access that
+ storage in Tcl_Obj, rather than string format.
+
+ * unix/tclUnixFile.c: Rewrote TclpFindExecutable() to use
+ * win/tclWinFile.c: TclSetObjNameOfExecutable to store the
+ executable name it computes.
+
+ * generic/tclInt.h: Added internal stub entries for
+ * generic/tclInt.decls: TclpFindExecutable and
+ Tcl(Get|Set)ObjNameOfExecutable.
+
+ * generic/tclIntDecls.h: make genstubs
+ * generic/tclStubInit.c:
+
+ * generic/tclCmdIL.c: Retrieve executable name in Tcl_Obj form
+ * win/tclWinPipe.c: instead of string form.
+
+ * unix/tclUnixTest.c: Update [testfindexecutable] command to use new
+ internal interfaces.
+
+ * generic/tclEncoding.c: Moved TclpSetInitialEncodings() call
+ from Tcl_FindExecutable() into TclInitEncodingSubsystem(). This is
+ important on Windows where it establishes whether the "ascii" or
+ "unicode" set of system routines will be used, and that needs to be
+ done earlier to support filesystem operations. [Bug 1077005]
+
+2004-12-01 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/winDde.test: Rewritten to use tcltest2 features more
+ thoroughly (reducing the [catch] count!) and fix the problem with
+ winDde-6.1 being out of synch with the implementation.
+
+2004-11-30 Don Porter <dgp@users.sourceforge.net>
+
+ * library/init.tcl ([unknown]): Restored the save/restore of the
+ variables ::errorCode and ::errorInfo. This is needed when the
+ [::bgerror] command is auto-loaded (as it is by Tk).
+
+ Patch 976520 reworks several of the details involved with
+ startup/initialization of the Tcl library, focused on the activities
+ of Tcl_FindExecutable().
+
+ * generic/tclIO.c: Removed bogus claim in comment that encoding
+ "iso8859-1" is "built-in" to Tcl.
+
+ * generic/tclInt.h: Created a new struct ProcessGlobalValue,
+ * generic/tclUtil.c: routines Tcl(Get|Set)ProcessGlobalValue, and
+ function type TclInitProcessGlobalValueProc. Together, these take care
+ of the housekeeping for "values" (things that can be held in a
+ Tcl_Obj) that are global across a whole process. That is, they are
+ shared among multiple threads, and epoch and mutex protection must
+ govern the validity of cached copies maintained in each thread.
+
+ * generic/tclNotify.c: Modified TclInitNotifier() to tolerate being
+ called multiple times in the same thread.
+ * generic/tclEvent.c: Dropped the unused argv0 argument to
+ TclInitSubsystems(). Removed machinery to unsure only one
+ TclInitNotifier() call per thread, now that that is safe. Converted
+ Tcl(Get|Set)LibraryPath to use a ProcessGlobalValue, and moved them to
+ tclEncoding.c.
+ * generic/tclBasic.c: Updated caller.
+
+ * generic/tclInt.h: TclpFindExecutable now returns void.
+ * unix/tclUnixFile.c:
+ * win/tclWinFile.c:
+ * win/tclWinPipe.c:
+
+ * generic/tclEncoding.c: Built new encoding search initialization on a
+ foundation of ProcessGlobalValues, exposing new routines
+ Tcl(Get|Set)EncodingSearchPath. A cache of a map from encoding name to
+ directory pathname keeps track of where encodings are available for
+ loading. Tcl_FindExecutable greatly simplified into just three
+ function calls. The "library path" is now misnamed, as its only
+ remaining purpose is as a foundation for the default encoding search
+ path.
+
+ * generic/tclInterp.c: Inlined the initScript that is evaluated by
+ Tcl_Init(). Added verification after initScript evaluation that Tcl
+ can find its installed *.enc files, and that it has initialized
+ [encoding system] in agreement with what the environment expects.
+ [tclInit] no longer driven by the value of $::tcl_libPath; it largely
+ constructs its own search path now, rather than attempt to share one
+ with the encoding system.
+
+ * unix/tclUnixInit.c: TclpSetInitialEncodings factored so that a new
+ * win/tclWinInit.c: routine TclpGetEncodingNameFromEnvironment can
+ reveal that Tcl thinks the [encoding system] should be, even when an
+ incomplete encoding search path, or a missing *.enc file won't allow
+ that initialization to succeed. TclpInitLibraryPath reworked as an
+ initializer of a ProcessGlobalValue.
+
+ * unix/tclUnixTest.c: Update implementations of [testfindexecutable],
+ [testgetdefenc], and [testsetdefenc].
+
+ * tests/unixInit.test: Corrected tests to operate properly even when
+ a value of TCL_LIBRARY is required to find encodings.
+
+ * generic/tclInt.decls: New internal stubs: TclGetEncodingSearchPath,
+ TclSetEncodingSearchPath, TclpGetEncodingNameFromEnvironment. These
+ are candidates for public exposure by future TIPs.
+
+ * generic/tclIntDecls.h: make genstubs
+ * generic/tclStubInit.c:
+
+ * generic/tclTest.c: Updated [testencoding] to use
+ * tests/encoding.test: Tcl(Get|Set)EncodingSearchPath. Updated tests.
+
+2004-11-30 Kevin B. Kenny <kennykb@acm.org>
+
+ * library/clock.tcl: Corrected the regular expressions that match a
+ time zone to allow for time zones specified as +HH or -HH.
+ * tests/clock.test: Added regression test case for the above issue.
+ Thanks to Rolf Ade for reporting this issue [http://wiki.tcl.tk/13094]
+ * win/tclWinDde.c (Tcl_DdeObjCmd): Corrected a typo that caused a
+ compilation failure on VC++.
+
+2004-11-29 Andreas Kupries <andreask@activestate.com>
+
+ * win/Makefile.in (install-libraries): Brought entry '2004-10-26 Don
+ Porter (Tcl Modules)' into the windows world, actually the
+ win/configure buildsystem. The other windows buildsystems (.vc, .bc)
+ still have to be updated as well.
+
+2004-11-26 Andreas Kupries <andreask@activestate.com>
+
+ * win/tclWinDde.c (ExecuteRemoteObject): Removed bogus semicolon found
+ at the end of the header for the function definition, terminating it
+ early and preventing a compile. This is likely a fix for '2004-11-25
+ Donal'. I have to conclude that it is also unknown if the other
+ changes to this file actually pass the testsuite. Running testsuite
+ ... They don't. winDde-6.1 fails. This is only a message discrepance,
+ i.e. not too bad. Leaving resolution of that to Pat and Donal.
+
+2004-11-26 Don Porter <dgp@users.sourceforge.net>
+
+ * library/auto.tcl (tcl_findLibrary): Made sure the uniquifying
+ operations on the search path does not also normalize. [Bug 1072136]
+
+2004-11-26 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * unix/configure.in: Simplify the code to check for correctness of
+ strstr, strtoul and strtod.
+ * unix/tcl.m4 (SC_TCL_CHECK_BROKEN_FUNC): Split a complex stanza out
+ of configure.in into its own function. Also force it to do the right
+ thing with cacheing of results of AC_TRY_RUN to deal with issue raised
+ in [Patch 1073524]
+
+ * doc/foreach.n: Added simple example. [FRQ 1073334]
+
+2004-11-25 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclProc.c (TclObjInterpProc): Make it so that only
+ * generic/tclIndexObj.c (Tcl_WrongNumArgs): [proc] instances do
+ * tests/indexObj.test (indexObj-5.7): quoting of their first
+ arguments, so keeping [Bug 942757] fixed and making [Bug 1066837] be
+ fixed as well. Done with a load of #ifdef-ery because this hack is so
+ ugly nobody should keep it around once Itcl's fixed.
+
+2004-11-25 Reinhard Max <max@suse.de>
+
+ * tests/tcltest.test: The order in which [glob] returns the file names
+ is undefined, so tests should not depend on it.
+
+2004-11-25 Zoran Vasiljevic <vasiljevic@users.sf.net>
+
+ * doc/Thread.3:
+ * doc/Notifier.3: Added changes from the core-8-4-branch
+
+2004-11-25 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/dde.n: Synchronized the documentation of the commands with the
+ header of the docs and what the package actually does. Thanks to
+ Andreas Kupries for spotting this.
+ * win/tclWinDde.c (Tcl_DdeObjCmd): Much cleanup of argument parsing
+ code.
+
+2004-11-24 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tclPort.h: Relative include of tclWinPort.h returned as it
+ was requiring me set -I$(tcl_root)/win for my extensions that need to
+ include tclInt.h and doesn't appear to serve any purpose for windows
+ builds.
+
+2004-11-24 Kevin B. Kenny <kennykb@acm.org>
+
+ * unix/tcl.m4 (SC_ENABLE_THREADS): Corrected bad check for 3-argument
+ readdir_r [Bug 1001325].
+ * unix/configure: Regenerated.
+ * unix/tclUnixNotfy.c: Corrected all uses of 'select' to manage their
+ masks using the FD_CLR, FD_ISSET, FD_SET, and FD_ZERO macros rather
+ than bit-whacking that failed under Solaris-Sparc-64. [Bug 1071807]
+ * win/tclWinInit.c (TclpInitLibraryPath): Removed unused vars 'pathc'
+ and 'pathv' that caused compilation problems on VC++ with
+ --enable-symbols.
+
+2004-11-24 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/tcl.m4 (SC_ENABLE_THREADS): Corrected failure to determine the
+ number of arguments for readdir_r on SunOS systems. [Bug 1071701]
+
+ * unix/configure: autoconf-2.57
+
+ * generic/tclCmdIL.c (InfoVarsCmd): Corrected segfault in new
+ * tests/info.test (info-19.6): trivial matching branch [Bug 1072654]
+
+2004-11-24 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tools/man2html.tcl, tools/man2html1.tcl: Update to use Tcl 8.4.
+ * tools/man2html2.tcl: Fix broken .SS handling.
+
+2004-11-23 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * unix/Makefile.in: Add (commented-out) code to integrate tclConfig.h
+ into the dependency tree and 'make distclean'. [Bug 1068171]
+
+ * generic/tclResult.c (Tcl_AppendResultVA): Remove call to
+ Tcl_GetStringResult to speed up repeated calls to Tcl_AppendResult
+ with the side effect that code that wants to access interp->result
+ should always call Tcl_GetStringResult first. See [Patch 1041072]
+ discussion for more details.
+
+2004-11-22 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4 (SC_TCL_64BIT_FLAGS): Define HAVE_TYPE_OFF64_T only when
+ off64_t, open64(), and lseek64() are defined. IRIX 5.3 is known to not
+ include an open64 function. [Bug 1030465]
+
+2004-11-22 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4 (SC_ENABLE_THREADS): Check for a 2 argument version of
+ readdir_r that is known to exists under IRIX 5.3.
+ * unix/tclUnixThrd.c (TclpReaddir): Use either 2 arg or 3 arg version
+ of readdir_r. [Bug 1001325]
+
+2004-11-22 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/tclUnixInit.c (TclpInitLibraryPath): Purged dead code that used
+ * win/tclWinInit.c (TclpInitLibraryPath): to extend the "library
+ path". Search path construction for init.tcl is now done within the
+ [tclInit] proc.
+ * generic/tclInterp.c: Restored several directories to the search
+ * tests/unixInit.test: path used to locate init.tcl within [tclInit].
+ This change does not restore any directories to the encoding search
+ path, so should still avoid the price of an unreasonably large number
+ of filesystem accesses during encoding initialization at startup
+ [Bug 976438]
+
+2004-11-22 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclPathObj.c: fix and new test for [Bug 1043129] in the
+ * tests/fileSystem.test: treatment of backslashes in file join on
+ Windows.
+
+2004-11-21 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/AddErrInfo.3: Typo corrections (Thanks Daniel South).
+ * doc/interp.n:
+
+2004-11-19 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/AddErrInfo.3: Docs for Tcl_(Get|Set)ReturnOptions. [TIP 227]
+
+ * doc/AddErrInfo.3:
+ * doc/Async.3: Documentation updates to replace references
+ * doc/BackgdErr.3: to global variable ::errorInfo and ::errorCode
+ * doc/SaveResult.3: and to the ::bgerror command with references
+ * doc/after.n: to their preferred replacements, the
+ * doc/bgerror.n: -errorinfo and -errorcode return options,
+ * doc/error.n: the Tcl_*InterpState routines, and the
+ * doc/exec.n: [interp bgerror] command.
+ * doc/exit.n:
+ * doc/fileevent.n:
+ * doc/interp.n:
+ * doc/return.n:
+ * doc/tclvars.n:
+ * doc/update.n:
+
+ * tests/unixInit.test: Removed "knownBug" constraints to prompt bug
+ fixing before 8.5a2 release.
+
+2004-11-19 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Makefile:
+ * unix/configure.in:
+ * unix/tclUnixInit.c (MacOSXGetLibraryPath): changed detection of tcl
+ framework build when determining tclLibPath from overloaded
+ TCL_LIBRARY to configuration define TCL_FRAMEWORK. [Bug 1068088]
+
+ * unix/configure: autoconf-2.57
+ * unix/tclConfig.h.in: autoheader-2.57
+
+2004-11-18 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/SaveResult.3: Documentation for Tcl_*InterpState (TIP 226).
+
+ * generic/tclEvent.c (HandleBgErrors): Simplified program flow.
+
+ * tests/basic.test: Updated functional (not testing) uses of
+ * tests/io.test: [bgerror] to make use of [interp bgerror].
+ * tests/socket.test:
+ * tests/timer.test:
+
+ * tests/interp.test (interp-36.*): [interp bgerror] tests.
+
+ * generic/tclInterp.c: Corrected [interp bgerror] error messages.
+
+2004-11-18 Reinhard Max <max@suse.de>
+
+ * unix/tcl.m4 (SC_CONFIG_MANPAGES): Applied an improved version of
+ * unix/configure.in: [Patch 996085], that introduces
+ * unix/Makefile.in: --enable-man-suffix.
+
+ * unix/installManPage: added
+ * unix/mkLinks.tcl: removed
+ * unix/mkLinks: removed
+ * unix/configure: generated
+
+ * unix/Makefile.in: Don't install tclConfig.h .
+
+2004-11-17 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/configure.in: The change below reveals that the public data
+ type Tcl_StatBuf relies on config information. For now, disabled the
+ use of the tclConfig.h file until its full impact on Tcl's interface
+ can be assessed.
+
+ * unix/configure: autoconf-2.57
+
+ * generic/tcl.h: Moved the #include "tclConfig.h" out of
+ * generic/tclInt.h: tcl.h. The config settings are not part of
+ * generic/tclPort.: the public interface, and having it there
+ breaks compiled against uninstalled Tcl and extensions using
+ autoconf-2.5*.
+
+2004-11-16 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tclUnixChan.c (TtySetOptionProc): fixed crash configuring
+ -ttycontrol on a channel. [Bug 1067708]
+
+2004-11-16 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclIOUtil.c (TclFSEpochOk): There were two code paths via
+ which the thread copy of filesystemEpoch could be synched with the
+ master copy, but only one kept the filesystem list cache up to date.
+ Fix routes everything through a single code path. [Bug 1035775].
+
+2004-11-16 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): Stop architecture flags to 'ld' from
+ getting lost when [load] is disabled. [Bug 1016796]
+
+2004-11-16 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tcl.h:
+ * unix/configure.in: changed HAVE_CONFIG_H to HAVE_TCL_CONFIG_H.
+
+ * unix/configure: autoconf-2.57
+
+2004-11-15 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclInt.h: Added comment warning that the old ERR_IN_PROGRESS
+ and ERROR_CODE_SET flag values should not be re-used for the sake of
+ those extensions that have accessed them.
+
+ * generic/tclCmdMZ.c (Tcl_TraceObjCmd): Fixed Bug 1065378 which failed
+ * tests/trace.test (trace-33.1): to permit a variable trace
+ created with [trace variable] to be destroyed with [trace remove].
+ Thanks to Keith Vetter for the report.
+
+2004-11-15 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/tclvars.n: Added section to documentation on global variables
+ that are specific to tclsh and wish. [Patch 1065732]
+
+2004-11-12 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclEncoding.c (TableFromUtfProc): correct crash condition
+ when TCL_UTF_MAX == 6. [Bug 1004065]
+
+2004-11-12 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/interp.n: Basic documentation of the TIP#221 API.
+
+2004-11-12 Don Porter <dgp@users.sourceforge.net>
+
+ TIP #221 IMPLEMENTATION
+ * generic/tclBasic.c: Define [::tcl::Bgerror] in new interps.
+ * generic/tclEvent.c: Update Tcl_BackgroundError to make use of the
+ registered [interp bgerror] command.
+ * generic/tclInterp.c: New [interp bgerror] subcommand.
+ * tests/interp.test: syntax tests updated.
+
+ TIP #226 IMPLEMENTATION
+ * generic/tcl.decls: Stubs for Tcl_(Save|Restore|Discard)InterpState
+ * generic/tcl.h: New public opaque type, Tcl_InterpState.
+ * generic/tclInt.h: Drop old private declarations. Add
+ Tcl(Get|Set)BgErrorHandler
+ * generic/tclResult.c: Tcl_*InterpState implementations.
+ * generic/tclDictObj.c: Update callers.
+ * generic/tclIOGT.c:
+ * generic/tclTrace.c:
+
+ TIP #227 IMPLEMENTATION
+ * generic/tcl.decls: Stubs for Tcl_(Get|Set)ReturnOptions.
+ * generic/tclInt.h: Drop old private declarations.
+ * generic/tclResult.c: Tcl_*ReturnOptions implementations.
+ * generic/tclCmdAH.c: Update callers.
+ * generic/tclMain.c:
+
+ * generic/tclDecls.h: make genstubs
+ * generic/tclStubInit.c:
+
+ * unix/tclAppInit.c: Removed tclConfig.h #include, now that tcl.h
+ takes care of it for us.
+
+ * generic/tclInt.h: Moved verification of ptrdiff_t typedef from
+ * generic/tclExecute.c: multiple .c files into one common header where
+ * generic/tclVar.c: it is verifiably after tclConfig.h inclusion.
+
+2004-11-12 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tcl.h:
+ * generic/tclInt.h:
+ * unix/Makefile.in: include tclConfig.h from tcl.h and install it as a
+ public header. Normalized compiler include path order to
+ -I${BUILD_DIR} -I${UNIX_DIR} -I${GENERIC_DIR}.
+
+ * unix/dltest/Makefile.in: add ${BUILD_DIR}/.. to include path to pick
+ up tclConfig.h.
+
+ * unix/tclUnixInit.c: moved check for HAVE_CFBUNDLE define after
+ #include "tclInt.h" to ensure tclConfig.h has been included.
+
+2004-11-12 Reinhard Max <max@suse.de>
+
+ * unix/config.h.in:
+ * unix/tclConfig.h.in: renamed
+
+ * unix/Makefile.in: Completed support for config header,
+ * unix/configure.in: fixed building outside of the unix dir,
+ * unix/tclAppinit.c: and reflected the name change of config.h.
+ * generic/tclInt.h:
+
+ * unix/configure: generated
+
+2004-11-12 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * unix/config.h.in: Allow configure to put all the C #defs into
+ * unix/configure.in: a file (called config.h) so that Unix builds
+ * unix/tcl.m4: now take far fewer lines of scrollback to
+ * unix/Makefile.in: proceed (making it less likely that any errors
+ * generic/tclInt.h: or warnings will get missed).
+ * unix/tclAppInit.c: Part of the TIP#34 upgrades.
+
+ * unix/tcl.m4, unix/tclUnixPort.h: Check for pthread_attr_get_np in
+ <pthread.h> before forcing the use of <pthread_np.h> to make things
+ work on NetBSD 2.0. [Bug 1064882]
+
+ * doc/binary.n, doc/upvar.n: More minor fixes.
+
+2004-11-12 Daniel Steffen <das@users.sourceforge.net>
+
+ * doc/CrtChannel.3:
+ * doc/Interp.3:
+ * doc/Limit.3:
+ * doc/binary.n:
+ * doc/dict.n:
+ * doc/tm.n:
+ * doc/upvar.n: fixed *roff errors uncovered by running 'make html'.
+
+ * tools/tcltk-man2html.tcl: added faked support for bullet point
+ lists, i.e. *nroff ".IP \(bu" syntax.
+
+2004-11-11 Daniel Steffen <das@users.sourceforge.net>
+
+ * tests/fCmd.test:
+ * unix/tclUnixFCmd.c (TraverseUnixTree): added option to rewind() the
+ readdir() loop whenever the source hierarchy has been modified by
+ traverseProc (e.g. by deleting files); this is required to ensure
+ complete traversal of the source hierarchy on certain filesystems like
+ HFS+. Added test for failing recursive delete on Mac OS X that was due
+ to this. [Bug 1034337]
+
+ * generic/tclListObj.c (Tcl_ListObjReplace): use memmove() instead of
+ manual copy loop to shift list elements. Decreases time spent in
+ Tcl_ListObjReplace() from 5.2% to 1.7% of overall runtime of tclbench
+ on a ppc 7455 (i.e. 200% speed increase). [Patch 1064243]
+
+ * generic/tclHash.c: hoisted some constant pointer dereferences out of
+ loops to eliminate redundant loads that the gcc optimizer didn't deal
+ with. Decreases time spend in Tcl_FindHashEntry() by 10% over a full
+ run of the tcl testuite on a ppc 7455. [Patch 1064243]
+
+ * tests/fileName.test:
+ * tests/fileSystem.test:
+ * tests/io.test:
+ * tests/msgcat.test:
+ * tests/tcltest.test:
+ * tests/unixInit.test: fixed bugs causing failures when running tests
+ with -tmpdir arg not set to working dir.
+
+ * macosx/Makefile: corrected path to html help inside framework.
+ Prevent parallel make from building several targets at the same time.
+
+ * macosx/tclMacOSXFCmd.c (struct fileinfobuf): force struct to be
+ packed to prevent failures when builing with -malign=natural.
+
+2004-11-10 Andreas Kupries <andreask@activestate.com>
+
+ * unix/tclUnixChan.c: [Bug 727786]. Exterminated the code marked
+ DEPRECATED. This code has not been used in over a year now, and we
+ have no complaints.
+
+2004-11-08 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinPipe.c: The pipe channel driver now respects the -blocking
+ option when closing is the same way the UNIX side works. This is to
+ avoid a hung shell when exiting due to open pipes that refuse to close
+ in a graceful manner.
+ * doc/open.n: Added a note about -blocking 0 and lack of exit status
+ as it had never been documented. [Bug 947693]
+
+ ***POTENTIAL INCOMPATIBILITY***
+
+ Scripts that use async pipes on windows, must (like the UNIX side) set
+ -blocking to 1 before calling [close] to receive the exit status.
+
+2004-11-07 David Gravereaux <davygrvy@pobox.com>
+
+ * tests/winFile.test: added contraint to winFile-4.0 to prevent it
+ being run on NT4 [Bug 981829]
+
+2004-11-05 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/reg.test: Major reorganization so that this file is much
+ easier for a normal Tcl maintainer to comprehend. The test flags are
+ still very cryptic, but they appear to have to be that way. The number
+ of skipped tests has increased, but now the skipped tests have much
+ more meaningful content.
+
+ * tests/tm.test (genpaths): Add a [file normalize] so we pick up
+ Windows drive letters, etc. [Bug 1053568]
+
+2004-11-04 Don Porter <dgp@users.sourceforge.net>
+
+ * changes: Updates toward an 8.5a2 release.
+
+2004-11-03 Kevin B. Kenny <kennykb@acm.org>
+
+ * library/clock.tcl (FreeScan): Fixed a bug where scanning "Monday"
+ with a base time other than midnight incorrectly carried the base time
+ forward.
+
+ * test/clock.test (clock-33.{5,5a}): Made the test failure more
+ informative.
+
+ * tests/clock.test (clock-34.{28,44,45,46}): Removed 'knownBug'
+ constraints from tests that no longer fail.
+
+ Thanks to Don Porter for reporting these.
+
+2004-11-03 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tcl.h: Moved the preprocessor logic
+ * generic/tclDecls.h: from tclInt.h of setting the
+ * generic/tclInt.h: TCL_STORAGE_CLASS macro to the
+ * generic/tclIntDecls.h: tcl*Decls.h files now that no
+ * generic/tclIntPlatDecls.h: use of EXTERN is left in tclInt.h.
+ * generic/tclPlatDecls.h: Proto for Tcl_Main moved in tcl.h
+ * win/tclWinPort.h: to prior the inclusion of the Stubs
+ headers as they are now resetting TCL_STORAGE_CLASS. Removed
+ extraineous reset from tclWinPort.h. [Patch 1055668]
+
+ * generic/tclCompile.h: Removed extrainious reset of TCL_STORAGE_CLASS
+ missed in my last edit.
+
+2004-11-03 Don Porter <dgp@users.sourceforge.net>
+
+ * library/init.tcl ([unknown]): Corrections to the 2004-10-25 mods to
+ Aunt ??? in [unknown]. Flaws revealed by Itcl test suite, which still
+ apparently relies on this brokenness. Also added comment suggesting
+ the error message that any code using this hack *ought* to receive in
+ reply.
+
+ * generic/tclTrace.c (TclCallVarTraces): Improved ability to debug
+ * tests/incr-old.test (incr-old-2.6): errors during variable
+ * tests/incr.test (incr-{1,2}.28): traces by preserving the
+ * tests/set.test (set-{2,4}.4): -errorinfo data.
+ * tests/trace.test (trace-33.1): [Bug 527164]
+
+2004-11-02 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tclInt.h: added a check for #ifdef __cplusplus around the
+ #define of MODULE_SCOPE. About the only time it would be problem is
+ when someone is statically linking to Tcl and accessing internals from
+ a C++ file and has name mangling issues from the lack of "C" after
+ 'extern' [Patch 1055668].
+ * generic/tclCompile.h: Exchanged use of the EXTERN macro to the new
+ MODULE_SCOPE macro. Lowered exported internals count by 35. [Patch
+ 1055668]
+ * win/tclWinInt.h:
+ * win/tclWinPort.h: exported internals dropped by a count of 14.
+ * generic/tclFileSystem.h: Added use of MODULE_SCOPE on protos.
+ * generic/tclRegexp.h: manipulating TCL_STORAGE_CLASS unnecessary.
+
+2004-11-02 Don Porter <dgp@users.sourceforge.net>
+
+ * library/tcltest/tcltest.tcl: Corrected some misleading
+ * tests/tcltest.test (tcltest-26.1,2): displays of ::errorInfo and
+ ::errorCode information when the -setup, -body, and/or -cleanup scripts
+ return an unexpected return code. Thanks to Robert Seeger for the fix.
+ [RFE 1017151].
+
+2004-11-02 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclExecute.c (TclExecuteByteCode): Improved version of the
+ NaN fix from Miguel Sofer. [Bug 761471]
+
+2004-11-02 Kevin Kenny <kennykb@acm.org>
+
+ * library/tzdata/America/Cuiaba: Change to DST rules for
+ * library/tzdata/America/Havana: autumn of 2004.
+ [ftp://elsie.nci.nih.gov/pub/tzdata2004g.tar.gz]
+
+ * tools/tclZIC.tcl: Updated to be compatible with recent changes in
+ library/clock.tcl.
+
+2004-11-02 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * win/tclWinFile.c: Simplify TclpUtime to use Tcl_FSGetNativePath, and
+ add comments.
+
+2004-11-02 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclInt.h: Change uses of EXTERN to MODULE_SCOPE (defined in
+ this file too to be 'extern' if not overridden) as nothing declared in
+ tclInt.h is supposed to be visible outside the Tcl core. If there *is*
+ anything that extensions are actually using, we can open this up later
+ on. [Patch 1055668]
+
+ * doc/CrtChannel.3 (Tcl_GetChannelMode): Add synopsis. [Bug 1058446]
+
+2004-11-01 Kevin B. Kenny <kennykb@acm.org>
+
+ * win/tclWinFile.c (FromCTime, TclpUtime): Replaced a call to the
+ Posix 'utime' function with calls to Windows-API equivalents, to avoid
+ a bug where the VC++ versions misconvert times across a Daylight
+ Saving Time boundary. [Bug 926106]
+ * win/tclWinInt.h (TclWinProcs):
+ * win/tclWin32Dll.c (asciiProcs, unicodeProcs): Removed now-unused
+ reference to 'utime'.
+ * tests/cmdAH.test (cmdAH-24.12): Added test case for the above bug.
+
+2004-11-01 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclExecute.c (TclExecuteByteCode): Make INST_EQ and friends
+ handle NaN correctly in all cases. [Bug 761471]
+
+ * generic/tclNamesp.c (NamespaceInscopeCmd): Make the error message
+ generation the same as in NamespaceEvalCmd().
+ (Tcl_Import): Rationalized to use Tcl_EvalObjv().
+
+2004-10-31 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/io.test (io-40.3): Convert umask2 test constraint into a form
+ that most people will be able to satisfy.
+
+ * tests/cmdAH.test (cmdAH-8.45): Removed broken test constraint. It
+ didn't do what it was intended to do, and it implied the other correct
+ constraint. [Bug 1053908]
+
+ * generic/tclCmdIL.c (InfoGlobalsCmd):
+ * tests/info.test (info-8.4): Strip leading global-namespace
+ specifiers from the pattern argument. [Bug 1057461]
+
+2004-10-30 Kevin Kenny <kennykb@acm.org>
+
+ * generic/clock.c: Replaced WIN32 macro with __WIN32__. [Bug 1054357].
+ Thanks to David Gravereaux for the patch.
+ * win/tclWinFile.c: Removed a long-standing bug that causes incorrect
+ conversion between file time and UTC time if the file time is recorded
+ in a different Daylight Saving Time status than the current one. [Bug
+ 926106]
+
+2004-10-29 Don Porter <dgp@users.sourceforge.net>
+
+ * library/tcltest/tcltest.tcl: Correct reaction to errors in the
+ obsolete processCmdLineArgsHook. [Bug 1055673]
+ * library/tcltest/pkgIndex.tcl: Bump to tcltest 2.2.7
+ * unix/Makefile.in:
+ * tests/all.tcl: Update to use [tcltest::configure].
+
+2004-10-29 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * library/tm.tcl (::tcl::tm::*): Use the core proc engine to generate
+ the wrong-num-args error messages for the path ensemble.
+
+ Ensembles can now (sometimes) rewrite the error messages of their
+ subcommands so they appear more like the arguments that the user
+ passed to the ensemble. Below is a description of changes involved in
+ doing this.
+
+ * tests/namespace.test (namespace-50.*): Tests of ensemble subcommand
+ error message rewriting.
+ * generic/tclProc.c (TclObjInterpProc): Make procedures implement
+ their wrong-num-args message using Tcl_WrongNumArgs instead of
+ something baked-at-home.
+ * generic/tclNamesp.c (TclIsEnsemble, NsEnsembleImplementationCmd):
+ Added test of ensemble-hood (available to rest of core) and made
+ ensembles set up the rewriting for Tcl_WrongNumArgs to take advantage
+ of.
+ * generic/tclInt.h (Interp.ensembleRewrite): Extra fields.
+ * generic/tclIndexObj.c (Tcl_WrongNumArgs): Add knowledge of what is
+ going on in ensembles' command rewriting so this command can generate
+ the right error message itself.
+ * generic/tclBasic.c (Tcl_CreateInterp, TclEvalObjvInternal): Added
+ code to initialize (as empty) the rewriting fields and reset them when
+ we leak outside an ensemble implementation.
+
+2004-10-28 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c (INST_START_CMD):
+ * tests/execute.test (execute-8.3): fix for execution stack corruption
+ [Bug 1055676]. Credit dgp for detective work and fix.
+
+2004-10-27 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/socket.test (socket-13.1): Balanced [makeFile] and
+ [removeFile] commands.
+
+ * tests/clock.test: Correct duplicate test names.
+ * tests/namespace.test:
+ * tests/string.test:
+ * tests/io.test (io-50.4): Use namespace variables.
+
+2004-10-27 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tclInt.decls: The following 9 functions were moved from
+ * generic/tclInt.h: tclInt.h to the private/int Stubs table for
+ * generic/tclIntDecls.h: use by the test suite. As tclTest.obj is
+ * generic/tclStubInit.c: linked to the shell, these functions need
+ "blessed" status so as to always be exported from the library. Being
+ placed in the Stubs table guarantees this [Bug 1054748]:
+ TclpObjRemoveDirectory, TclpObjCopyDirectory,
+ TclpObjCreateDirectory, TclpObjDeleteFile,
+ TclpObjCopyFile, TclpObjRenameFile,
+ TclpObjStat, TclpObjAccess,
+ TclpOpenFileChannel
+
+ * tests/registry.test: Fixed test files to load the correct
+ * tests/winDde.test: registry and dde packages by using the info
+ * win/Makefile.in: from makefiles to tell tcltest where to load
+ * win/makefile.vc: them from. This avoids grabbing the wrong
+ package from $auto_path which might be the install point rather than
+ the dev location. Kudos to Jennifer Hom for adding -load and
+ -loadfile to the tcltest package. [Bug 926088]
+
+ * win/tclWinThrd.c (TclFinalizeLock): release the critical section
+ before deleting it. [Bug 731778]
+
+ * generic/tcl.h: Removed the file level 'extern "C" {' and the
+ coresponding closing block as it serves no purpose given that all the
+ function prototypes have the proper extern usage already.
+
+ * unix/tclAppInit.c: When built as tcltest, TclThread_Init was
+ * win/tclAppInit.c: getting called twice. First by Tcltest_Init,
+ then again in Tcl_AppInit. The call from Tcl_AppInit is now removed.
+
+2004-10-27 Andreas Kupries <andreask@activestate.com>
+
+ * tests/tm.test: Expanded on the testsuite entered by Donal.
+ * library/tm.tcl: Even found bugs, these have been corrected.
+
+2004-10-26 Kevin Kenny <kennykb@acm.org>
+
+ * tests/format.test (format-19.1): Additional regression test for [Bug
+ 868489].
+
+2004-10-27 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/*.n: Many small general documentation fixes.
+
+2004-10-26 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tclPipe.c (TclCleanupChildren): bad cast of resolvedPid
+ caused PIDs on win95 to go negative. winpipe-4.2 brought this to the
+ surface. Fixed with sprintf in place of TclFormatInt. Thanks to hgiese
+ [Patch 767676]
+
+2004-10-26 Andreas Kupries <andreask@activestate.com>
+
+ * library/tm.tcl (::tcl::tm::Defaults): Added a second [file dirname]
+ around the location of the executable. This fixes [Bug 1038705].
+ Instable of a bogus "foo/bin/lib" we now have the correct "foo/lib" as
+ a base path for modules.
+
+2004-10-26 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclParse.c (Tcl_SubstObj): Fix for failed subst-12.3 test
+ * tests/subst.test (subst-12.3-5): More tests for Bug 1036649.
+
+ * unix/Makefile.in (install-libraries): Updated the installation of
+ the http, msgcat, and tcltest packages to install as Tcl Modules on
+ Unix systems. Other platform Makefiles still need updating. [Patch
+ 1054370]
+
+ * tests/basic.test: Added missing constraints.
+ * tests/compile.test:
+ * tests/fileSystem.test:
+
+ * tests/init.test (init-2.8): Updated to not rely on http package.
+
+2004-10-26 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclInt.h:
+ * generic/tclVar.c: removed more direct references to the VAR flags,
+ replaced with access macros.
+
+2004-10-26 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/expr.n: Clarified that non-num/non-bool literals require
+ quoting. [Bug 1027849]. Also listed booleans as acceptable values.
+
+2004-10-26 Kevin B. Kenny <kennykb@acm.org>
+
+ * library/clock.tcl (FreeScan): Fixed a bug that caused relative days
+ of the week in free-form [clock scan] to be evaluated in the wrong
+ time zone.
+ * tests/clock.test (clock-31.[456]): Made sure that there isn't an
+ env(TZ) or env(TCL_TZ) lying around that will override the time zone
+ that we're trying to establish with the simulated registry.
+ Both problems reported as [Bug 1054101].
+
+2004-10-25 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/string.n (map): Rewrote to clarify that we don't just map single
+ characters. [Bug 1048005]
+ * doc/info.n (procs): Clarified that the pattern argument may have
+ namespace separators in it. [Bug 1047928]
+
+ * tests/cmdAH.test (cmdAH-8.45): Simplify in the hope that the reasons
+ for [Bug 1053908] will become clearer.
+
+2004-10-25 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclExecute.c (IllegalExprOperandType,TclExecuteByteCode):
+ Removed several DECACHE_INFO/CACHE_INFO pairs that are no longer
+ needed for protection because routines like Tcl_SetErrorCode() and
+ Tcl_AddErrorInfo() can no longer re-enter bytecode execution.
+
+ * generic/tclResult.c (TclProcessReturn): Bug fix. Be sure that a
+ missing -errorinfo option when code == TCL_ERROR causes the errorInfo
+ field to get reset.
+
+ * tests/thread.test (thread-4.4): Test depended on a ::errorInfo value
+ initialized to "". Added code to test to setup that requirement.
+
+ * library/auto.tcl: Purged Tcl's script library of all
+ * library/clock.tcl: remaining references to global vars
+ * library/init.tcl: ::errorInfo and ::errorCode.
+
+ * generic/tclMain.c (Tcl_Main): Updated to make use of
+ TclGetReturnOptions instead of ::errorInfo variable.
+
+ * generic/tclInterp.c (tclInit): Bug fix. Access dict variables with
+ [dict get], not array syntax.
+
+2004-10-25 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/tm.test: Rewrote the tests to actually perform syntax checks
+ on the public API. Added a new test (currently failing) to indicate
+ that the test suite is not complete yet.
+ * library/tm.tcl (path): Rewrote to turn this command into an ensemble
+ to make it faster and simpler.
+
+2004-10-24 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCmdIL.c:
+ * generic/tclExecute.c:
+ * generic/tclInt.h:
+ * generic/tclTrace.c: defined new macros to get/set the flags of
+ variables. The only files that still access the flag values directly
+ are tclCompCmds.c, tclCompile.c, tclProc.c and tclVar.c
+
+2004-10-24 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c (Tcl_LogCommandInfo,Tcl_AddObjErrorInfo): Shift
+ the initialization of errorCode to NONE to more central location.
+
+ * generic/tclEvent.c (BgError,Tcl_BackgroundError,HandleBgErrors):
+ Rewrite to build on the new TclGet/SetReturnOptions routines.
+
+ * generic/tclResult.c (TclGetReturnOptions): Add call to
+ Tcl_AddObjErrorInfo to be sure error fields are initialized.
+
+ * generic/tclResult.c (TclTransferResult): Rewrite to build on the new
+ TclGet/SetReturnOptions routines.
+
+2004-10-22 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/tm.n: Tightened up the documentation.
+ * tests/tm.test: Created (with partially dummy content) so TIP#189 can
+ be marked Final.
+
+ * generic/tclNamesp.c (NsEnsembleImplementationCmd): Make ensembles
+ cut their implementations out of error traces. This is the right thing
+ to do more often than not.
+
+2004-10-22 Kevin B. Kenny <kennykb@acm.org>
+
+ * library/clock.tcl: Fixed a typo where the fallback time zone became
+ ::localtime instead of :localtime. Fixed a bug where time zone names
+ containing hyphens could not be loaded.
+ * tests/clock.test: Added regression test cases that covers both bugs.
+ Thanks to Todd M. Helfter <tmh@jumpgate.itsp.purdue.edu> for finding
+ these bugs.
+
+2004-10-22 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclExecute.c (TclCompEvalObj, Tcl_ExprObj):
+ * generic/tclProc.c (TclProcCompileProc): Always call object
+ freeIntRepProc's in the same way.
+
+2004-10-22 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclVar.c: fixed bug in commit of 2004-07-23, which was
+ causing a leak of Proc structures and failure of compile-12.1. Two
+ lines were 'zombies' from the previous way localVarNames worked.
+ Credit dgp for finding this.
+
+2004-10-21 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclInt.h (Interp):
+ * generic/tclBasic.c (Tcl_CreateInterp,Tcl_DeleteInterp):
+ * generic/tclResult.c (GetKeys,ReleaseKeys,etc.): Moved the key values
+ of the return options dictionary out of private fields of the Interp
+ struct and into thread-static values managed in tclResult.c.
+
+ * generic/tclCmdAH.c (Tcl_CatchObjCmd, Tcl_ErrorObjCmd): Updated to
+ call the new TclGet/SetReturnOptions routines to do much of their
+ work.
+
+ * generic/tclInt.h (TclGetReturnOptions,TclSetReturnOptions):
+ * generic/tclResult.c (TclGetReturnOptions,TclSetReturnOptions): New
+ utility routines to get/set the return options of an interp. Intent is
+ that these routines will be converted to public routines after TIP
+ approval.
+
+ * generic/tclCmdMZ.c (TclProcessReturn,TclMergeReturnOptions):
+ * generic/tclResult.c (TclProcessReturn,TclMergeReturnOptions): Move
+ internal utility routines from tclCmdMZ.c to tclResult.c.
+
+ * generic/tclBasic.c (Tcl_CreateInterp, Tcl_DeleteInterp):
+ * generic/tclResult.c (TclTransferResult): Rework so that
+ iPtr->returnOpts can be NULL when there are no special options.
+
+ * generic/tclResult.c (TclRestoreInterpState): Plug potential memory
+ leak.
+
+2004-10-21 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclBasic.c: Various changes to [clock format] that,
+ * generic/tclClock.c: together, make it roughly twice as fast
+ * generic/tclInt.h: while all tests in the test suite
+ * library/clock.tcl: continue to pass.
+
+2004-10-20 Andreas Kupries <andreask@activestate.com>
+
+ * win/Makefile.in (install-msgs): Fixed a problem with the
+ * win/Makefile.in (install-tzdata): installation of timezone data and
+ message catalogs. They used the installed tcl library directory, not
+ the source library. Before it was installed. Switched to source lib
+ dir. Thanks to Kevin for the help in figuring this out.
+
+2004-10-20 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclThreadTest.c (ThreadEventProc): Corrected subtle bug
+ where the returned (char *) from Tcl_GetStringResult(interp) continued
+ to be used without copying or refcounting, while activity on the
+ interp continued. That's not safe, and recent changes demonstrated the
+ lack of safety with failing tests thread-4.3 and thread-4.5.
+
+2004-10-19 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclDictObj.c (DictWithCmd): Make sure all paths (that are
+ not themselves error paths) do not lose the result code.
+
+2004-10-19 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclInt.h (Tcl*InterpState): New internal routines
+ * generic/tclResult.c (Tcl*InterpState): TclSaveInterpState,
+ TclRestoreInterpState, and TclDiscardInterpState are superior
+ replacements for Tcl_(Save|Restore|Discard)Result. Intent is that
+ these routines will be converted to public routines after TIP
+ approval. Interfaces for these routines were shamelessly stolen from
+ Itcl.
+
+ * generic/tclBasic.c (TclEvalObjvInternal):
+ * generic/tclDictObj.c (DictUpdateCmd, DictWithCmd):
+ * generic/tclIOGT.c (ExecuteCallback):
+ * generic/tclTrace.c (Trace*Proc,TclCheck*Traces,TclCallVarTraces):
+ Callers of Tcl_*Result updated to call the new routines. The calls
+ were relocated in several cases to perform save/restore operations
+ only when needed.
+
+ * generic/tclEvent.c (HandleBgErrors):
+ * generic/tclFCmd.c (CopyRenameOneFile): Calls to Tcl_*Result that
+ were eliminated because they appeared to serve no useful purpose,
+ typically saving/restoring an error message, only to throw it away.
+
+2004-10-18 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c (Tcl_CreateInterp,Tcl_DeleteInterp):
+ * generic/tclCmdAH.c (Tcl_CatchObjCmd):
+ * generic/tclCmdMZ.c (TclMergeReturnOptions,TclProcessReturn):
+ * generic/tclCompCmds.c (TclCompileReturnCmd):
+ * generic/tclExecute.c (TclCompEvalObj):
+ * generic/tclInt.h (Interp):
+ * generic/tclProc.c (TclUpdateReturnInfo): Place primary storage of
+ the -level and -code information in private fields of the Interp
+ struct, rather than in a DictObj. This should significantly improve
+ performance of TclUpdateReturnInfo.
+
+2004-10-17 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclResult.c: removed unused variable [Bug 1048588]. Thanks
+ to Daniel South.
+
+2004-10-15 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCmdMZ.c (TclProcessReturn): Now that primary
+ * generic/tclProc.c (TclUpdateReturnInfo): storage for the
+ errorInfo and errorCode values are internal fields, we can set them at
+ the time of the [return] command, and not have to wait until the
+ specified number of "-level"s have popped.
+
+ * generic/tclBasic.c (Tcl_CreateInterp, Tcl_DeleteInterp)
+ (TclEvalObjvInternal, Tcl_LogCommandInfo, TclAddObjErrorInfo):
+ * generic/tclCmdAH.c (Tcl_CatchObjCmd):
+ * generic/tclEvent.c (BgError, ErrAssocData, Tcl_BackgroundError)
+ (HandleBgErrors, BgErrorDeleteProc):
+ * generic/tclExecute.c (TclCreateExecEnv, TclDeleteExecEnv):
+ * generic/tclIOUtil.c (comments only):
+ * generic/tclInt.h (ExecEnv,Interp, ERR_IN_PROGRESS):
+ * generic/tclInterp.c ([tclInit]):
+ * generic/tclMain.c (comments only):
+ * generic/tclNamesp.c (Tcl_CreateNamespace, Tcl_DeleteNamespace)
+ (TclTeardownNamespace):
+ * generic/tclProc.c (TclUpdateReturnInfo):
+ * generic/tclResult.c (Tcl_ResetResult, TclTransferResult):
+ * generic/tclTrace.c (CallVarTraces):
+ Reworked management of the "errorInfo" data of an interp. That
+ information is now primarily stored in a new private (Tcl_Obj *) field
+ of the Interp struct, rather than using a global variable ::errorInfo
+ as the primary storage. The ERR_IN_PROGRESS flag bit value is no
+ longer required to manage the value in its new location, and is
+ removed. Variable traces are established to support compatibility for
+ any code expecting the ::errorInfo variable to hold the information.
+
+ ***POTENTIAL INCOMPATIBILITY***
+ Code that sets traces on the ::errorInfo variable may notice a
+ difference in timing of the firing of those traces. Code that uses the
+ value ERR_IN_PROGRESS.
+
+2004-10-14 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ TIP#217 IMPLEMENTATION
+
+ * generic/tclCmdIL.c (Tcl_LsortObjCmd): Add -indices option from James
+ Salsman. [Patch 1017532]
+
+ * generic/tclUtil.c (TclMatchIsTrivial): Detect degenerate cases of
+ glob matching that let us avoid scanning through hash tables.
+ * generic/tclCmdIL.c (InfoCommandsCmd, InfoGlobalsCmd, InfoProcsCmd):
+ (InfoVarsCmd): Use this to speed up some [info] subcommands.
+
+2004-10-12 Kevin B. Kenny <kennykb@acm.org>
+
+ * library/tzdata/America/Campo_Grande:
+ * library/tzdata/America/Cuiaba:
+ * library/tzdata/America/Sao_Paulo
+ * library/tzdata/America/Argentina/Mendoza:
+ * library/tzdata/America/Argentina/San_Juan:
+ Synchronized to Olson's 'tzdata2004e'.
+
+2004-10-08 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ TIP#201 AND TIP#212 IMPLEMENTATIONS
+
+ * doc/dict.n, doc/expr.n: Documentation for new functionality.
+ * tests/expr.test: Basic tests of 'in' and 'ni' behaviour.
+ * tests/dict.test (dict-21.*,dict-22.*): Tests for [dict update] and
+ [dict with].
+ * generic/tclExecute.c (TclExecuteByteCode): Implementation of the
+ INST_LIST_IN and INST_LIST_NOT_IN bytecodes.
+ * generic/tclParseExpr.c (GetLexeme): Parse the 'in' and 'ni'
+ operators for TIP#201.
+ * generic/tclDictObj.c (DictUpdateCmd,DictWithCmd): Core of
+ implementation of TIP#212; docs and tests still to do...
+
+2004-10-07 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclTest.c (TestsetobjerrorcodeCmd): Simplified.
+
+2004-10-07 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclFileName.c:
+ * generic/tclFileSystem.h:
+ * generic/tclIOUtil.c:
+ * generic/tclPathObj.c:
+ * unix/tclUnixFile.c:
+ * win/tclWinFile.c:
+ * tests/fileName.test:
+ * tests/winFCmd.test: code reorganization for better generic/platform
+ code splitting [Bug 925620] removing the need for several #ifdef's,
+ and tests and fix for an unreported Windows glob problem ('glob -dir
+ C: -tails *').
+
+2004-10-07 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * *.3: Convert CONST to const and VOID to void so we document how
+ people should actually use the Tcl API and not the compatability hacks
+ that it has to have.
+
+ * doc/man.macros, *.3: Update .AS macro so it can know how wide to
+ make the third column of the argument list. Update documentation for C
+ API (only users) to take advantage of this.
+
+ * doc/FileSystem.3: Formatting fixes for greater documentation
+ clarity.
+
+2004-10-06 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclFileName.c (DoGlob, TclGlob): Stop messy sharing of
+ interpreter result and instead use a private object for collecting the
+ result of the glob. This simplifies TclGlob quite a lot.
+ * generic/tclIOUtil.c (Tcl_FSMatchInDirectory): Simplify by removing
+ some nesting. Also standardize variable names.
+ (FsAddMountsToGlobResult): Force updates to the list to be done
+ in-place, putting a side-condition of non-shared-ness on the resultPtr
+ argument to Tcl_FSMatchInDirectory, but everything would have broken
+ before if that was shared *anyway*.
+
+ * generic/tclEncoding.c (LoadTableEncoding): Removed reference to Tcl
+ interpreter; it wasn't needed as direct object use is more efficient.
+
+ * generic/tclPathObj.c: Made this file follow the style rules in the
+ Engineering Manual more closely, and also take advantage of the
+ internal object manipulation macros more.
+
+ * generic/tclCmdMZ.c (Tcl_SwitchObjCmd): Reorganized to have fewer
+ magic flag variables and to separate the code that scans for a match
+ from the code that processes a match body.
+
+2004-10-06 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c:
+ * generic/tclBinary.c:
+ * generic/tclCmdAH.c:
+ * generic/tclCmdIL.c:
+ * generic/tclCmdMZ.c:
+ * generic/tclCompExpr.c:
+ * generic/tclDictObj.c:
+ * generic/tclEncoding.c:
+ * generic/tclExecute.c:
+ * generic/tclFCmd.c:
+ * generic/tclHistory.c:
+ * generic/tclIndexObj.c:
+ * generic/tclInterp.c:
+ * generic/tclIO.c:
+ * generic/tclIOCmd.c:
+ * generic/tclNamesp.c:
+ * generic/tclObj.c:
+ * generic/tclPkg.c:
+ * generic/tclResult.c:
+ * generic/tclScan.c:
+ * generic/tclTimer.c:
+ * generic/tclTrace.c:
+ * generic/tclUtil.c:
+ * generic/tclVar.c:
+ * unix/tclUnixFCmd.c:
+ * unix/tclUnixPipe.c:
+ * win/tclWinDde.c:
+ * win/tclWinFCmd.c:
+ * win/tclWinPipe.c:
+ * win/tclWinReg.c:
+ It is a poor practice to directly set or append to the value of the
+ objResult of an interp, because that value might be shared, and in
+ that circumstance a Tcl_Panic() will be the result. Searched for
+ example of this practice and replaced with safer alternatives, often
+ using the Tcl_AppendResult() routine that dkf just rehabilitated.
+ * library/dde/pkgIndex.tcl: Bump to dde 1.3.1
+ * library/reg/pkgIndex.tcl: Bump to registry 1.1.5
+
+2004-10-06 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/SetResult.3: Made Tcl_AppendResult non-deprecated; better that
+ people use it than most of the common alternatives!
+ * generic/tclResult.c (Tcl_AppendResultVA): Make this work better with
+ Tcl_Objs. [Patch 1041072]
+ (Tcl_SetResult, Tcl_AppendElement): Change string to stringPtr to
+ avoid C++ keywords.
+
+2004-10-05 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c (TclObjInvoke): More simplification of the
+ TclObjInvoke routine toward unification with the rest of the
+ evaluation stack.
+
+ * generic/tclBasic.c (Tcl_CreateInterp, Tcl_DeleteInterp)
+ (TclEvalObjvInternal, Tcl_LogCommandInfo):
+ * generic/tclCmdAH.c (Tcl_CatchObjCmd):
+ * generic/tclEvent.c (BgError, Tcl_BackgroundError, HandleBgErrors):
+ * generic/tclInt.h (Interp, ERROR_CODE_SET):
+ * generic/tclNamesp.c (Tcl_CreateNamespace, Tcl_DeleteNamespace)
+ (TclTeardownNamespace):
+ * generic/tclResult.c (Tcl_ResetResult, Tcl_SetObjErrorCode)
+ (TclTransferResult):
+ * generic/tclTrace.c (CallVarTraces):
+ Reworked management of the "errorCode" data of an interp. That
+ information is now primarily stored in a new private (Tcl_Obj *) field
+ of the Interp struct, rather than using a global variable ::errorCode
+ as the primary storage. The ERROR_CODE_SET flag bit value is no longer
+ required to manage the value in its new location, and is removed.
+ Variable traces are established to support compatibility for any code
+ expecting the ::errorCode variable to hold the information.
+
+ ***POTENTIAL INCOMPATIBILITY***
+ Code that sets traces on the ::errorCode variable may notice a
+ difference in timing of the firing of those traces.
+
+ * generic/tclNamesp.c (Tcl_PopCallFrame): Removed Bug 1038021
+ workaround. That bug is now fixed.
+
+2004-10-04 Kevin B. Kenny <kennykb@acm.org>
+
+ * tests/clock.test (clock-34.*): Removed an antibug that forced
+ comparison of [clock scan] results with the :localtime time zone. Now
+ that [clock scan] uses the current time zone instead, the antibug
+ caused several tests to fail. [Bug 1038554]
+
+2004-10-04 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclParseExpr.c (GetLexeme): Ensure that the 'eq' and 'ne'
+ operators are followed by non-alphabetic characters so lexemes can't
+ run together. [Bug 884830]
+
+ * doc/DictObj.3, doc/dict.n: Clarified that a dictionary is not
+ order-preserving. [Bug 1032243] Also added another example to show off
+ more ways of using a dictionary and a few other formatting
+ improvements.
+
+2004-10-02 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclDictObj.c (TraceDictPath, Tcl_DictObjPutKeyList): Add
+ support for automatic creation of dictionary paths since that is what
+ everyone seems to actually expect of the API! [Bug 1037235]
+ (Tcl_DictObjNext): Make calling this after Tcl_DictObjDone non-fatal
+ as that simplifies a number of internal APIs. This doesn't break any
+ existing working code as it is a case which previously caused a panic.
+
+2004-10-02 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/namespace.test (namespace-8.7): Another test for save/restore
+ of ::errorInfo and ::errorCode during global namespace teardown.
+
+2004-10-01 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclProc.c (TclObjGetFrame, Tcl_UplevelObjCmd):
+ * generic/tclVar.c (Tcl_UpvarObjCmd): Cache stackframe level
+ references in the level object for speed.
+
+2004-09-30 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c (Tcl_CreateInterp):
+ * generic/tclInt.h (Interp): Removed the flag bit value
+ EXPR_INITIALIZED. It was set during interp creation and never tested.
+ Whatever purpose it had is in the past.
+
+ * generic/tclBasic.c (Tcl_EvalObjEx): Removed the flag bit value
+ * generic/tclInt.h (Interp): USE_EVAL_DIRECT. It was used
+ * generic/tcLTest.c (TestevalexObjCmd): only in the testing command
+ * tests/parser.test (parse-9.2): [testevalex] and nothing in
+ the test suite made use of the capability it enabled.
+
+ * generic/tclBasic.c (Tcl_AddObjErrorInfo): More re-organization
+ * generic/tclCmdAH.c (Tcl_ErrorObjCmd): of the management of
+ * generic/tclCmdMZ.c (TclProcessReturn): the errorCode value.
+ * tests/error.test (error-6.4-9):
+
+ * generic/tclNamespace.c (TclTeardownNamespace): Tcl_Obj-ified
+ * tests/namespace.test (namespace-8.5,6): the save/restore of
+ ::errorInfo and ::errorCode during global namespace teardown. Revised
+ the comment to clarify why this is done, and added tests that will
+ fail if this is not done.
+
+ * generic/tclResult.c (TclTransferResult): Added safety checks so that
+ unexpected undefined ::errorInfo or ::errorCode will not lead to a
+ segfault.
+
+ * generic/tclTrace.c (TclCallVarTraces): Save/restore the flag values
+ * tests/var.test (var-16.1): that define part of the
+ interpreter state during variable traces. [Bug 1038021].
+
+2004-09-30 Miguel Sofer <msofer@users.sf.net>
+
+ * tests/subst.test (12.1-2): added tests for [Bug 1036649]
+
+2004-09-29 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/basic.test (49.*): New tests for TCL_EVAL_GLOBAL.
+
+2004-09-29 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclVar.c (TclObjLookupVar, TclObjLookupVar):
+ (TclObjUnsetVar2, SetArraySearchObj):
+ * generic/tclUtil.c (SetEndOffsetFromAny):
+ * generic/tclStringObj.c (Tcl_SetStringObj):
+ (Tcl_SetUnicodeObj, SetStringFromAny):
+ * generic/tclResult.c (ResetObjResult):
+ * generic/tclRegexp.c (Tcl_GetRegExpFromObj):
+ * generic/tclPathObj.c (TclFSMakePathRelative, SetFsPathFromAny):
+ (TclFSMakePathFromNormalized, Tcl_FSNewNativePath):
+ * generic/tclObj.c (TclFreeObj, Tcl_SetBooleanObj, SetBooleanFromAny):
+ (Tcl_SetDoubleObj, SetDoubleFromAny, Tcl_SetIntObj):
+ (SetIntOrWideFromAny, Tcl_SetLongObj, SetWideIntFromAny):
+ (Tcl_SetWideIntObj, TclSetCmdNameObj, SetCmdNameFromAny):
+ * generic/tclNamesp.c (SetNsNameFromAny, MakeCachedEnsembleCommand):
+ * generic/tclListObj.c (Tcl_SetListObj, SetListFromAny):
+ * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct):
+ * generic/tclDictObj.c (SetDictFromAny):
+ * generic/tclCompile.c (TclInitByteCodeObj):
+ * generic/tclBinary.c (Tcl_SetByteArrayObj, SetByteArrayFromAny):
+ * generic/tclInt.h (TclFreeIntRep): Factorize out deletion of object
+ internal representation to a shared macro, so simplifying much code.
+
+2004-09-27 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclBasic.c (TclObjInvoke): fix for bogus gcc warning about
+ uninitialised variable.
+
+2004-09-27 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c: Removed internal routines TclInvoke,
+ * generic/tclInt.decls: TclGlobalInvoke, TclObjInvokeGlobal and the
+ * tests/basic.test: portion of TclObjInvoke that handles calls
+ without TCL_INVOKE_HIDDEN enabled. None of this code is called any
+ longer within the core, and the superior public interface,
+ Tcl_EvalObjv, is available for any external callers.
+
+ * generic/tclIntDecls.h: make genstubs
+ * generic/tclStubInit.c:
+
+ * generic/tclEvent.c (HandleBgErrors): Updated [bgerror] invocations
+ to make use of Tcl_Obj based routines, dropping the calls to
+ TclGlobalInvoke()
+
+2004-09-27 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclFileName.c:
+ * generic/tclFileSystem.h:
+ * generic/tclIOUtil.c:
+ * generic/tclPathObj.c:
+ * tests/cmdAH.test:
+ * tests/fileSystem.test:
+ * tests/winFCmd.test: fix to bad error message with 'cd' on windows,
+ when permissions are inadequate [Bug 1035462] and to treatment of a
+ volume-relative pwd on Windows [Bug 1018980].
+
+ * doc/FileSystem.3: added missing Tcl_GlobTypeData documentation [Bug
+ 935853]
+
+2004-09-27 Kevin Kenny <kennykb@acm.org>
+
+ * compat/strftime.c (Removed):
+ * generic/tclClock.c (removed TclClockOldscanObjCmd):
+ * generic/tclDate.c (Regenerated):
+ * generic/tclGetDate.y:
+ * generic/tclInt.decls (removed TclGetDate and TclpStrftime):
+ * generic/tclInt.h (removed TclGetDateInfo):
+ * generic/tclIntDecls.h (Regenerated):
+ * generic/tclStubInit.c (Regenerated):
+ * library/clock.tcl:
+ * unix/tclUnixTime.c (removed TclpStrftime):
+ * win/Makefile.in:
+ * win/makefile.bc:
+ * win/makefile.bc:
+ * win/tcl.dsp:
+ Continued refactoring of [clock] for TIP 173 changes. Broke the
+ free-form parser apart so that the Bison parser is responsible for
+ only parsing, while clock.tcl handles relative times like "next
+ Thursday", "next January". This change is needed to make timezones
+ other than :localtime and :Etc/UTC work with free-form scanning. This
+ change closes out the issue identified as being "for another day" in
+ my log message of 2004-09-08. The refactored code also eliminates the
+ last known references to TclpStrftime and TclGetDate, so those
+ routines (including compat/strftime.c) have been removed. The
+ refactoring also has the benefit that all storage in the Bison parser
+ is now on the C stack, eliminating any need for mutex protection
+ around [clock scan]. Also, changed the Makefiles so that 'make
+ gendate' is available on Windows as well as Unix.
+
+ * generic/tclCmdAH.c (Tcl_FormatObjCmd): Removed some grubby
+ * generic/tclObj.c (SetBooleanFromAny): work-around code that was
+ needed only because of Bug 868489.
+
+ * generic/tclBasic.c (TclObjInvoke): Removed three unused variables to
+ silence a compiler warning in VC++.
+
+2004-09-27 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * doc/FileSystem.3: fix to small typo.
+
+2004-09-26 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompCmds.c:
+ * generic/tclCompExpr.c:
+ * generic/tclCompile.c:
+ * generic/tclCompile.h:
+ * generic/tclInt.h:
+ * generic/tclProc.c:
+ * tests/compExpr-old.test:
+ * tests/compExpr.test:
+ * tests/expr.test:
+ * tests/for.test:
+ * tests/if.test:
+ * tests/incr.test:
+ * tests/while.test:
+ Report compilation errors at runtime, [Patch 1033689] by dgp.
+
+2004-09-23 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/dltest/Makefile.in (clean): Fixup make clean rule so that it
+ does not delete all files when SHLIB_SUFFIX is set to the empty string
+ in a static build. [Bug 1016726]
+
+2004-09-23 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c: Corrections to the 2004-09-21 commit
+ * generic/tclExecute.c: regarding ERR_ALREADY_LOGGED. That commit
+ * generic/tclNamesp.c: caused Tk test send-10.7 to fail. Added
+ * tests/namespace.test (25.7,8): tests in the Tcl test suite
+ * tests/pkg.test (2.25,26): to catch this error without the aid
+ of Tk in the future.
+
+ * generic/tclCmdAH.c (Tcl_ExprObjCmd): Simplified the TclObjCmdProc
+ of [expr] with a call to Tcl_ConcatObj.
+
+2004-09-22 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCmdMZ.c (TclProcessReturn): Support the -errorline
+ * generic/tclCompile.c (TclCompileScript): option to [return].
+ * tests/compile.test (16.23.*): Use that capability to defer reporting
+ * tests/misc.test (1.2): of parse errors until runtime. Updated
+ tests to reflect change. [Bug 1032805]
+
+2004-09-22 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c (INST_START_CMD):
+ * tests/proc.test (7.2-3): fix for [Bug 729692] was incorrect whenever
+ a loop exception was returned.
+
+2004-09-22 Kevin B. Kenny <kennykb@acm.org>
+
+ * library/tzdata/America/Montevideo: Updated to reflect
+ ftp://elsie.nci.nih.gov/pub/tzdata2004d.tar.gz. (Changes to
+ Asia/Jerusalem were in the comments only.) [Routine maintenance - no
+ bug] Spanish-language description of the change at
+ http://www.presidencia.gub.uy/decretos/2004091502.htm
+
+2004-09-21 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCompCmds.c: Tolerate [append] syntax errors
+ * tests/appendComp.test (8.1): at compile time, and allow runtime to
+ raise the error (or succeed if a redefined [append] allows).
+
+ * generic/tclBasic.c: Reworked management of the interp flag
+ * generic/tclCompile.c: ERR_ALREADY_LOGGED, to reduce its exposure.
+ * generic/tclExecute.c: Still left several referebces that are just
+ * generic/tclNamesp.c: too nice on performace to do away with. These
+ changes also resolve an inconsistency in the ::errorInfo values
+ produced by [namespace eval x error foo bar] and [namespace eval x
+ {error foo bar}].
+
+ * generic/tclExecute.c (TclCompEvalObj): Simplified the
+ TclCompEvalObj routine. Much housekeeping now reliably happens
+ elsewhere. [Patch 1031949]
+
+2004-09-21 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/interp.n: Tighten up wording on how [interp eval] and [interp
+ invokehidden] operate w.r.t. stack frames. [Bug 926590]
+
+2004-09-20 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/error.test (error-6.2,3): Added more tests to verify
+ ::errorCode setting by/after a [catch].
+
+2004-09-19 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCmdAH.c: removed outdated comment [Bug 1029518].
+
+2004-09-18 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclAppInit.c: Dde package can load into a safe interp. Claim
+ this fact for the Tcl_StaticPackage() call when the shell is built
+ with the TCL_USE_STATIC_PACKAGES option.
+
+2004-09-18 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclExecute.c (TEBC-INST_LSHIFT,INST_RSHIFT): Ensure that
+ large shifts end up shifting correctly. [Bug 868467]
+
+ * doc/FileSystem.3, doc/OpenFileChnl.3: More documentation fixes from
+ Mikhail Kolesnitchenko. [Patch 1022527]
+ * doc/*: Standardize highlighting of symbols defined in tcl.h
+
+2004-09-17 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c (Tcl_AddObjErrorInfo, Tcl_LogCommandInfo):
+ * generic/tclCmdAH.c ([catch], [error]):
+ * generic/tclCmdMZ.c ([return]):
+ * generic/tclProc.c (TclUpdateReturnInfo):
+ * generic/tclResult.c (Tcl_SetErrorCodeVA, Tcl_SetObjErrorCode)
+ (TclTransferResult): Refactored so that all errorCode setting flows
+ through Tcl_SetObjErrorCode(). This greatly reduces the number of
+ different places in the code that need to know details about an
+ internal bitflag field of the Interp struct. Also places errorCode
+ setting in one place for easier future mods.
+
+2004-09-17 Kevin B.Kenny <kennykb@acm.org>
+
+ * generic/tclDate.c: Revised tclGetDate.y to use bison instead of
+ * generic/tclGetDate.y: yacc to build the parser, eliminating all the
+ * generic/tclInt.h: complicated hackery involving 'sed'
+ * unix/Makefile.in: postprocessing. Rebuilt the parser.
+
+2004-09-14 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclClock.c (ClockOldscanObjCmd): Silenced a compiler warning
+ (long passed as a param where unsigend long was expected). 'Unsigned
+ long' is wrong, but the fix is really to change the signature of
+ TclGetDate to return a structure of its 'yy' variables and then do the
+ remaining work inside clock.tcl. But, as I said on 2004-09-08, that's
+ a job for another day. [Bug 1027993]
+
+2004-09-10 Miguel Sofer <msofer@users.sf.net>
+
+ * doc/interp.n:
+ * generic/tclInterp.c (TclPreventAliasLoop, AliasCreate):
+ * tests/interp.test (17.4-6, 19.3-4): fixing problems with renaming of
+ aliases [Bugs 707104 1026493]. Fix designed by dgp.
+
+2004-09-13 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclNamesp.c (NsEnsembleImplementationCmd): Add token field
+ to internal rep of EnsembleCmdRep structure so that we can check it to
+ see if the subcommand object is really being used with the same
+ ensemble. [Bug 1026903]
+
+2004-09-11 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclClock.c (TclMktimeObjCmd): Corrected a bad check for
+ error return from 'mktime'.
+ * generic/tclObj.c (Tcl_GetIntFromObj): Corrected a problem where
+ demoting a wide to an int failed on a big-endian machine. [Bug
+ 1026125].
+ * tests/clock.test (clock-43.1): Added regression test for error
+ return from 'mktime'.
+
+2004-09-11 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c (INST_CONCAT1): fix for [Bug 1025834]; avoid
+ unnecessary string copies.
+
+2004-09-10 David Gravereaux <davyrgvy@pobox.com>
+
+ * tests/tcltest.test: tcltest-12.3-4 needed to have
+ ::tcltest::loadScript set to empty in their -setup
+
+2004-09-10 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclObj.c (SetIntOrWideFromAny): Rewritten integral value
+ parsing code so that values do not flip so easily between numeric
+ representations. Thanks to KBK for this! [Bug 868489]
+
+ * generic/tclIO.c (Tcl_Seek): Make sure wide seeks do not fail to set
+ ::errorCode on error. [Bug 1025359]
+
+2004-09-10 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tcl.h: Micro formatting fixes.
+ * generic/tclIOGT.c: Channel version fixed, must be 3, to have
+ wideseekProc. Thanks to David Graveraux <davygrvy@pobox.com>.
+
+2004-09-11 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclNamespace.c (TclGetNamespaceForQualName): Resolved
+ longstanding inconsistency in the treatment of the TCL_NAMESPACE_ONLY
+ flag revealed by testing the 2004-09-09 commits against Itcl.
+ TCL_NAMESPACE_ONLY now acts as specified in the pre-function comment,
+ forcing resolution in the passed in context namespace. It has been
+ incorrectly forcing resolution in the interp's current namespace.
+
+2004-09-10 Kevin Kenny <kennykb@acm.org>
+
+ * library/clock.tcl: Fixed a bug where %z always put a plus sign on
+ the time zone in :localtime.
+ * tests/clock.test: Added test case for the above bug.
+
+2004-09-10 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c (INST_CONCAT1): added a peephole optimisation
+ for concatting an empty string. This enables replacing the idiom 'K $x
+ [set x {}]' by '$x[set x {}]' for fastest execution.
+
+2004-09-09 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinConsole.c: Calls to WriteFile and WriteConsoleA changed to
+ WriteConsole for simplicity.
+
+2004-09-09 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclNamesp.c (Tcl_ForgetImport): Corrected faulty
+
+ * tests/namespace.test: logic that relied exclusively on string
+ matching and failed in the presence of [rename]s. [Bug 560297] Also
+ corrected faulty prevention of [namespace import] cycles. [Bug 1017299]
+
+2004-09-08 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c (Tcl_CreateInterp): Removed obsolete field
+ for storing the string-based command procedure of built-in commands.
+ We no longer have any string-based built-in commands!
+
+2004-09-08 Kevin B. Kenny <kennykb@acm.org>
+
+ * compat/strftime.c (_conv): Corrected a problem where hour 0 would
+ format as a blank format group with %k.
+ * doc/clock.n: Corrected a buglet in the header information. [Bug
+ 1024058]
+ * generic/tclClock.c (TclClockMktimeObjCmd): Fixed a bug where the
+ month was scanned incorrectly in -timezone :localtime.
+ * tests/clock.test (clock-34.*,clock-40.1, clock-41.1): Adjusted the
+ clock-34.* test cases so that the consistency check is performed in
+ :localtime rather than the current time zone. This change allows
+ dealing with issues where the C library has a different idea of DST
+ conversion than Tcl. (Real fix would be to break TclGetDate into
+ separate parser and time converter, and do the time conversion in
+ clock.tcl. That's for another day.) Added regression test case for the
+ bug where month was scanned incorrectly in -timezone :localtime. [Bug
+ 1023779] Added regression test case for %k at the zero hour.
+
+2004-09-07 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc: some quoting needed to be removed as it was
+ breaking with VC7. [Bug 1023150]
+
+2004-09-07 Kevin B. Kenny <kennykb@acm.org>
+
+ * doc/clock.n: Documented the default -format, and changed references
+ to a (nonexistent) msgcat command to refer to the msgcat package. [Bug
+ 1023870]
+ * generic/tclTimer.c: Removed a premature optimisation that attempted
+ to store the assoc data in the client data; the optimisation caused a
+ bug that [after] would overwrite its imports. [Bug 1016167]
+ * library/clock.tcl (InitTZData, ClearCaches): Changed so that the
+ in-memory time zone :UTC (and its aliases) always gets reinitialised,
+ in case tzdata is absent. [Bug 1019537, 1023779]
+ * library/tzdata/*: Regenerated.
+ * tests/clock.test (clock-31.*, clock-39.1): Corrected a problem where
+ the 'system' locale tests fail on a non-English Windows machine. [Bug
+ 1023761]. Added a test to make sure that alias time zones load
+ correctly. [Bug 1023779].
+ * tests/timer.test (timer-1.1, timer-2.1): Changed to (one hopes!) be
+ more resilient on an overloaded system, if [after 200] sleeps for 300
+ ms or longer.
+ * tools/tclZIC.tcl (writeLinks): Corrected a problem where alias time
+ zone names were written incorrectly, causing them to fail to load at
+ run time. [Bug 1023779].
+ * win/tclWinTime.c (Tcl_GetTime): Eliminated CPUID tests on Win64 -
+ assuming that HAL vendors now do a better job of keeping the
+ performance counters synchronized among CPU's. [Bug 1020445]
+
+2004-09-06 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/tclvars.n, doc/tcltest.n, doc/tclsh.1, doc/safe.n, doc/expr.n
+ * doc/WrongNumArgs.3, doc/Utf.3, doc/TraceVar.3, doc/Thread.3
+ * doc/TCL_MEM_DEBUG.3, doc/SubstObj.3, doc/StdChannels.3
+ * doc/SetResult.3, doc/RegExp.3, doc/RegConfig.3, doc/RecEvalObj.3
+ * doc/PrintDbl.3, doc/ParseCmd.3, doc/Panic.3, doc/ObjectType.3
+ * doc/Object.3, doc/Namespace.3, doc/Interp.3, doc/IntObj.3
+ * doc/Hash.3, doc/GetOpnFl.3, doc/GetIndex.3, doc/Eval.3
+ * doc/Encoding.3, doc/DoubleObj.3, doc/DictObj.3, doc/CrtTimerHdlr.3
+ * doc/CrtObjCmd.3, doc/CrtMathFnc.3, doc/CrtCommand.3, doc/CrtChannel.3
+ * doc/ChnlStack.3, doc/ByteArrObj.3, doc/AssocData.3, doc/Alloc.3:
+ More documentation fixes from Mikhail Kolesnitchenko. [Patch 1022527]
+
+2004-09-03 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * unix/tclUnixFCmd.c: Stop NULL interp arguments from triggering a
+ crash when an error happens. [Bug 1020538]
+
+2004-09-02 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/lsearch.n: Clarified meaning of -dictionary. [Bug 759545]
+
+2004-09-02 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * win/makefile.vc: clock.tcl needs to be installed.
+
+2004-09-01 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tclWinReg.c (BroadcastValue): WIN64 cast corrections
+
+ * win/tclWinDde.c (DdeClientWindowProc):
+ (DdeServicesOnAck, DdeEnumWindowsCallback): WIN64 corrections
+
+ * win/tclWin32Dll.c (TclWinCPUID): need _asm for WIN64 (Itanium),
+ until we have it, just return unknown. [Bug 1020445]
+
+2004-09-01 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/regsub.n, doc/RegConfig.3, doc/Environment.3:
+ * doc/CrtChannel.3, doc/safe.n: Use correct abbreviations.
+
+2004-08-31 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/trace.n, doc/socket.n, doc/registry.n, doc/pid.n:
+ * doc/namespace.n, doc/msgcat.n, doc/lsort.n, doc/lsearch.n:
+ * doc/linsert.n, doc/info.n, doc/http.n, doc/history.n:
+ * doc/format.n, doc/file.n, doc/exec.n, doc/dde.n, doc/clock.n:
+ * doc/catch.n, doc/binary.n: More spelling and grammar fixes from
+ Mikhail Kolesnitchenko. [Patch 1018486]
+
+2004-08-31 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * doc/FileSystem.3:
+ * generic/tclIOUtil.c: Clarified documentation regarding ability of a
+ filesystem to say that it doesn't support a given operation using the
+ EXDEV posix error code (copyFileProc, renameFileProc, etc), and
+ updated one piece of code to ensure correct behaviour when an
+ operation is not supported [Bug 1017072]
+
+ * tests/fCmd.test: fix to test suite problem [Bug 1002884]
+
+2004-08-31 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/Makefile.in (install-libraries): portable sh fix.
+
+2004-08-30 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd): Stop [string map] from
+ crashing when its map and input string are the same object.
+
+2004-08-27 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclNamesp.c (FindEnsemble): Factor out the code to convert a
+ command name into an ensemble configuration and add support for
+ ignoring [namespace import] link chains. [Bug 1017022]
+ (NamespaceWhichCmd): Rework to use newer option parsing API.
+
+2004-08-27 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/Makefile.in: added customization of default module path roots
+ via TCL_MODULE_PATH makefile variable.
+ * macosx/Makefile: add platform standard locations to default module
+ path roots. [Patch 942881]
+
+ * tests/env.test: macosx fixes.
+
+2004-08-25 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/timer.test (timer-10.1): Test for Bug 1016167.
+ * generic/tclTimer.c: Workaround for situation when a [namespace
+ import] causes the objv[0] value to be something other than what
+ Tcl_AfterObjCmd expects. [Bug 1016167].
+
+2004-08-25 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclNamesp.c (NsEnsembleImplementationCmd): Use the ensemble
+ command token to get the name of the ensemble for passing to the
+ -unknown handler instead of relying on objv[0], which may contain
+ useless info in the presence of [namespace import]. Problem found by
+ Don Porter when investigating [Bug 1016167].
+
+2004-08-24 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclProc.c: The routine TclProcInterpProc was a
+ * generic/tclTestProcBodyObj.c: specific instance of the general
+ service already provided by TclObjInvokeProc. Removed
+ TclProcInterpProc and TclGetInterpProc from the code...
+
+ * generic/tclInt.decls: ...and from the internal stubs table.
+ * generic/tclIntDecls.h
+ * generic/tclStubInit.c
+
+2004-08-24 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/string.n: Added clarifying note.
+
+2004-08-23 Don Porter <dgp@users.sourceforge.net>
+
+ * library/auto.tcl: Updated [tcl_findLibrary] search path to
+ include any [<pkg>::pkgconfig get scriptdir,runtime] directory, as
+ well as the $::auto_path. [RFE 695441]
+
+2004-08-21 Kevin B. Kenny <kennykb@acm.org>
+
+ * tests/clock.test (clock-38.1): Changed TZ setting to specify CET in
+ excruciating detail to deal with systems that lack the Posix defaults
+ for DST changes (and to be formally correct with the change dates for
+ CET).
+
+2004-08-19 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclScan.c (Tcl_ScanObjCmd, ValidateFormat): Ensure that the
+ %ld conversion works correctly on 64-bit platforms. [Bug 1011860]
+
+2004-08-19 Kevin Kenny <kennykb@acm.org>
+
+ * library/clock.tcl (format): Changed default timezone format from
+ alphabetic to numeric to produce scannable times in more locales.
+ * tests/clock.test (clock-37.1): Removed now-unused 'needPST'
+ constraint and the comments that refer to it.
+
+2004-08-18 Andreas Kupries <andreask@activestate.com>
+
+ * library/init.tcl: Integrated TIP #189. We source a separate file
+ (see below), instead of inlining the contents of that file. This
+ should beeasier to maintain, and easier to backport/install in 8.4
+ installations.
+
+ Note: Usage of Tcl Modules is restricted to non-safe interps. It
+ cannot be loaded into a safe interp.
+
+ * library/tm.tcl: New file, the v2 reference implementation for TIP
+ #189, Tcl Modules.
+
+ * doc/tm.n: New file, documentation for Tcl Modules, based on the TIP.
+
+ * unix/mkLinks: Regenerated.
+ * win/makefile.vc: Added tm.tcl to list of files to install.
+
+2004-08-18 Kevin Kenny <kennykb@acm.org>
+
+ * tests/httpd (httpdRespond): Corrected an abuse of the [clock]
+ command that caused test failures for some values of [clock clicks].
+
+ * doc/clock.n
+ * generic/tclBasic.c (Tcl_CreateInterp, Tcl_HideUnsafeCommands):
+ * generic/tclClock.c (all):
+ * generic/tclInt.h:
+ * generic/tclInterp.c (CreateSlave):
+ * library/clock.tcl: (new file)
+ * library/init.tcl (clock):
+ * library/msgs/*.msg:(new files)
+ * library/tzdata/*:
+ * library/tzdata/*/*:
+ * library/tzdata/*/*/*: (new files)
+ * tools/installData.tcl: (new file)
+ * tools/loadICU.tcl: (new file)
+ * tools/makeTestCases.tcl: (new file)
+ * tools/tclZIC.tcl: (new file)
+ * unix/Makefile.in:
+ * unix/configure: (regenerated)
+ * unix/tcl.m4:
+ * tests/clock.test (all):
+ * win/Makefile.in:
+ * win/Makefile.vc:
+ Implementation of TIPs #173 and #209.
+
+ The [clock] command is now a Tcl ensemble, with most of its
+ functionality written in Tcl and callouts to C code only to access
+ low-level functions such as localtime, mktime and tzset.
+
+ In addition to the functionality changes called out in the two TIPs,
+ it is worth noting that the [clock] command in a safe slave
+ interpreter is now an alias to the [clock] command in the master, and
+ that [clock] is otherwise not expected to function entirely correctly
+ in safe interps. C code that simply does Tcl_MakeSafe needs to be
+ aware that [clock] may need special handling. (It appears unlikely
+ that such code actually exists.)
+
+ One incompatibility of note is that if the time zone cannot be
+ determined from the TZ, TCL_TZ environment variables, or from the
+ Windows control panel, so that the C library must be used for date and
+ time conversions, then times outside the range of time_t will fail;
+ they used to return bad data silently.
+
+ Many thanks to all the many people who assisted with testing,
+ debugging, criticism of the specification, and localisation. Deserving
+ of particular mention are Joe English, Clif Flynt, Donal K. Fellows,
+ Jeff Hobbs, Cameron Laird, Arjen Markus, Reinhard Max, Christopher
+ Nelson, Steve Offutt, Donald G. Porter, Pascal Scheffers, Peter da
+ Silva and Richard Suchenwirth-Bauersachs.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2004-08-16 Miguel Sofer <msofer@users.sf.net>
+
+ * doc/SetVar.3:
+ * generic/tclTest.c (TestseterrorcodeCmd):
+ * generic/tclVar.c (TclPtrSetVar):
+ * tests/result.test (result-4.*, result-5.*): [Bug 1008314] detected
+ and fixed by dgp.
+
+2004-08-13 Don Porter <dgp@users.sourceforge.net>
+
+ * library/msgcat/msgcat.tcl: Added checks to prevent [mclocale]
+ * tests/msgcat.test: from registering filesystem paths to possibly
+ malicious code to be evaluated by a later [mcload].
+
+2004-08-10 Zoran Vasiljevic <vasiljevic@users.sf.net>
+
+ * unix/tclUnixThrd.c (TclpThreadCreate): changed handling of the
+ returned thread ID since broken on 64-bit systems (Cray). Thanks to
+ Rob Ratcliff for reporting the bug.
+
+2004-08-03 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclNamesp.c (MakeCachedEnsembleCommand): Initialize the
+ epoch field cached in the subcommand. [Bug 989298]
+ (NsEnsembleImplementationCmd): Plug a leak (thanks to Miguel Sofer for
+ spotting it with valgrind) and reduce the number of goto labels to
+ make the code clearer.
+
+2004-08-02 Don Porter <dgp@users.sourceforge.net>
+
+ * library/package.tcl (pkg_mkIndex): Updated [pkg_mkIndex] to make
+ use of [glob -directory $dir -tails] and return options.
+
+ TIP#207 IMPLEMENTATION
+
+ * doc/interp.n: Added support for a -namespace option to the
+ * generic/tclBasic.c: [interp invokehidden] command. Also added an
+ * generic/tclInt.h: internal routine TclObjInvokeNamespace() and
+ * generic/tclInterp.c: corrected the flag names TCL_FIND_ONLY_NS and
+ * generic/tclNamesp.c: TCL_CREATE_NS_IF_UNKNOWN that are passed to the
+ * generic/tclTrace.c: internal routine TclGetNamespaceForQualName().
+ * tests/interp.test: [Patch 981841]
+
+ * generic/tclLiteral.c (TclCleanupLiteralTable): Corrected
+ * tests/compile.test (compile-12.4): flawed deletion of literal
+ internal reps that could lead to accessing of freed memory. Thanks to
+ Kevin Kenny for test case and fix [Bug 1001997].
+
+2004-07-30 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/safe.test (safe-2.1): Disabled senseless test. [Bug 999612]
+
+ * library/auto.tcl (auto_reset): Removed "protected" list of commands
+ from [auto_reset]. All entries in the auto_index can be re-loaded.
+ * library/package.tcl: Updated comment to reflect 2004-07-28 commit.
+
+ * generic/tclEvent.c (Tcl_Finalize): Re-organized Tcl_Finalize so
+ that Tcl_ExitProc's that call Tcl_Finalize recursively do not cause
+ deadlock. [Patch 999084 fixes Tk Bug 714956]
+
+2004-07-30 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/configure:
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): Darwin: instead of setting PLAT_OBJS
+ to explict object files in tcl.m4, refer to MAC_OSX_OBJS makefile var.
+ * unix/Makefile.in: added MAC_OSX_OBJS variable.
+
+2004-07-29 Don Porter <dgp@users.sourceforge.net>
+
+ * library/package.tcl: [::pkg::create] is now an alias. Test safe-2.1
+ will now fail until Bug 999612 is corrected.
+
+2004-07-28 Don Porter <dgp@users.sourceforge.net>
+
+ * library/package.tcl: Moved private command
+ * library/tclIndex: [pkg_compareExtension] into ::tcl::Pkg.
+ * tests/pkg_mkIndex.test: Also moved implementation of
+ [::pkg::create] to [::tcl::Pkg::Create].
+
+2004-07-25 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * tests/io.test: Make io-61.1 create file as binary to pass on Win32
+
+2004-07-23 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclVar.c: simplify tclLocalVarNameType, removing the
+ reference to the corresponding proc. The reference is now seen as
+ unnecessary, and it may cause leaking circular references under some
+ circumstances (see for example [Bug 994838]).
+
+2004-07-22 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/eofchar.data (removed): Test io-61.1 now generates its own
+ * tests/io.test: file of test data as needed.
+
+2004-07-20 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclEvent.c: Correct threaded obj allocator to
+ * generic/tclInt.h: fully cleanup on exit and allow for
+ * generic/tclThreadAlloc.c: reinitialization. [Bug 736426]
+ * unix/tclUnixThrd.c: (mistachkin, kenny)
+ * win/tclWinThrd.c:
+
+2004-07-21 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tclBasic.c (DeleteInterpProc):
+ * generic/tclLiteral.c (TclCleanupLiteralTable):
+ * generic/tclInt.h: added a TclCleanupLiteralTable function, called
+ from DeleteInterpProc, that frees internal representations of shared
+ literals early when an interpreter is being deleted. This change
+ corrects a number of memory mismanagement issues in the cases where
+ the internal representation of one literal contains a reference to
+ another, and avoids conditions such as resolved variable names
+ referring to procedure and namespace contexts that no longer exist.
+ [Bug 994838]
+
+2004-07-20 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/Makefile.in:
+ * win/Makefile.in: added 'install-private-headers' makefile target to
+ allow optionally installing private tcl headers. [FR 922727]
+
+ * macosx/Makefile: use new 'install-private-headers' target to install
+ private headers into framework. [FR 922727]
+
+ * unix/tclUnixFile.c (NativeMatchType): added support for readonly
+ matching of user immutable files (where available).
+
+ * macosx/tclMacOSXBundle.c: dynamically acquire address for
+ CFBundleOpenBundleResourceMap symbol, since it is only present in full
+ CoreFoundation on Mac OS X and not in CFLite on pure Darwin.
+
+2004-07-19 Zoran Vasiljevic <vasiljevic@users.sf.net>
+
+ * win/tclwinThrd.c: redefined MASTER_LOCK to call TclpMasterLock.
+ Fixes [Bug 987967]
+
+2004-07-17 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclIOUtil.c: fix to rare 'cd' infinite loop in normalization
+ with vfs [Bug 991420].
+ * tests/fileSystem.test: added test for above bug.
+
+ * doc/FileSystem.3: clarified documentation of posix error codes in
+ 'remove directory' FS proc - 'EEXIST' is used to signify a non-empty
+ directory error (bug reported against tclvfs).
+
+2004-07-16 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/Makefile.in, unix/tcl.m4: move (C|LD)FLAGS after their
+ * unix/configure.in, unix/configure: _DEFAULT to allow for env setting
+ to override m4 switches. Move SC_MISSING_POSIX_HEADERS up and
+ consolidate calls to limit redundancy in configure.
+ (CFLAGS_WARNING): Remove -Wconversion
+ (SC_ENABLE_THREADS): Set m4 to force threaded build when built against
+ a threaded Tcl core.
+
+2004-07-16 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tclIOCmd.c (Tcl_FcopyObjCmd): Corrected a typo in the
+ generation of error messages and simplified by reusing data in a
+ variable instead of retrieving the string again. Fixes [Bug 835289].
+
+ * doc/OpenFileChnl.3: Added description of the behaviour of
+ Tcl_ReadChars when its 'charsToRead' argument is set to -1. Fixes [Bug
+ 934511].
+
+ * doc/CrtCommand.3: Added note that the arguments given to the command
+ proc of a Tcl_CreateCommand are in utf8 since Tcl 8.1. Closing [Patch
+ 414778].
+
+ * doc/ChnlStack.3: Removed the declaration that the interp argument to
+ Tcl_(un)StackChannel can be NULL. This fixes [Bug 881220], reported by
+ Marco Maggi <marcomaggi@users.sourceforge.net>.
+
+ * tests/socket.test: Accepted two new testcases by Stuart Casoff
+ <stwo@users.sourceforge.net> checking that -server and -async don't go
+ together [Bug 796534].
+
+ * unix/tclUnixNotfy.c (NotifierThreadProc): Accepted Joe Mistachkin's
+ patch for [Bug 990500], properly closing the notifier thread when its
+ exits.
+
+2004-07-15 Andreas Kupries <andreask@activestate.com>
+
+ * unix/tclUnixThrd.c (TclpFinalizeMutex): Accepted Joe Mistachkin's
+ patch for [Bug 990453], closing leakage of mutexes. They were not
+ destroyed properly upon finalization.
+
+2004-07-15 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tclIO.h (CHANNEL_INCLOSE): New flag. Set in
+ * generic/tclIO.c (Tcl_UnregisterChannel): 'Tcl_Close' while the
+ * generic/tclIO.c (Tcl_Close): close callbacks are
+ run. Checked in 'Tcl_Close' and 'Tcl_Unregister' to prevent recursive
+ call of 'close' in the close-callbacks. This is a possible error made
+ by implementors of virtual filesystems based on 'tclvfs', thinking
+ that they have to close the channel in the close handler for the
+ filesystem.
+
+2004-07-14 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tclIO.c:
+ * generic/tclIO.h:
+ * Not reverting, but #ifdef'ing the changes from May 19, 2004 out of
+ the core. This removes the ***POTENTIAL INCOMPATIBILITY*** for channel
+ drivers it introduced. This has become possible due to Expect gaining
+ a BlockModeProc and now handling blockingg and non-blocking modes
+ correctly. Thus [SF Tcl Bug 943274] is still fixed if a recent enough
+ version of Expect is used.
+
+ * doc/CrtChannel.3: Added warning about usage of a channel without a
+ BlockModeProc.
+
+2004-07-15 Andreas Kupries <andreask@pliers.activestate.com>
+
+ * generic/tclIOCmd.c (Tcl_PutsObjCmd): Added length check to the old
+ depreceated newline syntax, to ensure that only "nonewline" is
+ accepted. [Tcl SF Bug 985869], reported by Joe Mistachkin
+ <mistachkin@users.sourceforge.net>.
+
+2004-07-15 Zoran Vasiljevic <vasiljevic@users.sf.net>
+
+ * generic/tclEvent.c (Tcl_Finalize): stuffed memory leak incurred by
+ re-initializing of TSD slots after the last call to
+ TclFinalizeThreadData (done from within Tcl_FinalizeThread()). We
+ basically just repeat the TclFinalizeThreadData() once more before
+ tearing down TSD keys in TclFinalizeSynchronization(). There should be
+ more elaborate mechanism in place for handling such issues, based on
+ thread cleanup handlers registered on the OS level. Such change
+ requires much more work and would also require TIP because some
+ visible parts of Tcl API would have to be modified. In the meantime,
+ this will do.
+
+ * generic/tclNotify.c (TclFinalizeNotifier): Added conditional
+ notifier finalization based on the fact that an TclInitNotifier has
+ been called for the current thread. This fixes the [Bug 770053] again.
+ Hopefully this time w/o unwanted side-effects.
+
+2004-07-15 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tclLiteral.c (TclReleaseLiteral): Removed unused variable
+ 'codePtr' to silence a message from VC++.
+
+2004-07-15 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompile.c (TclCompileScript):
+ * generic/tclLiteral.c (TclReleaseLiteral): fix for [Bug 467523],
+ which resurfaced with the latest changes. The previous strategy was to
+ have special code in TclReleaseLiteral to handle the self-references
+ generated by empty scripts. The new approach avoids the self-reference
+ altogether, by having empty scripts return an unshared literal.
+
+2004-07-15 Zoran Vasiljevic <vasiljevic@users.sf.net>
+
+ * generic/tclEvent.c (NewThreadProc): Backout of changes to fix the
+ [Bug 770053]. See SF bugreport for more info.
+
+2004-07-11 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclBasic.c (Tcl_EvalEx): leak fix by dgp, release
+ objv[objectsUsed] on error.
+
+2004-07-11 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclParse.c (Tcl_SubstObj): leak fix by dgp, release result
+ on error.
+
+2004-07-11 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclNamesp.c (BuildEnsembleConfig): Don't forget to clean out
+ references when deleting the hash table.
+ * generic/tclDictObj.c (Tcl_DictObjRemoveKeyList): Oops, forgot to
+ delete value object when removing the hash entry. [Bug 989093 in part]
+
+2004-07-11 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c (TEBC): fixed leak of expandNestList objs when
+ there is an error while an expansion is in progress (code added at
+ checkForCatch).
+
+2004-07-11 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclIOUtil.c: fix to 'cd' bug when vfs is active [tclvfs Bug
+ 986944] - this bug recently introduced by some threading fixes. Need
+ to work out how to add tests for this.
+
+2004-07-10 Kevin Kenny <kennykb@acm.org>
+
+ * tests/clock.test (clock-2.11): Changed the test so that it isn't an
+ infinite loop when run under valgrind on a slow virtual machine.
+ Thanks to Miguel Sofer for the bug report. Also put in code to restore
+ env(LC_TIME) after tests complete, silencing a warning from 'make
+ TESTFLAGS="-debug 1" test'.
+
+2004-07-08 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclBasic.c (DeleteInterpProc): reverted the modification of
+ 3 days ago, as the leak of [Bug 983660] is now handled by the change
+ in TclCleanupByteCode.
+ * generic/tclCompile.c (TclCleanupByteCode): let each bytecode remove
+ its references to literals at interp deletion, without updating the
+ dying literal table.
+ * generic/tclLiteral.c (TclDeleteLiteralTable): with the above change
+ to TclCleanupByteCode, this function now removes a single reference to
+ the literal object and cleans up its own structures.
+
+2004-07-08 Kevin Kenny <kennykb@acm.org>
+
+ * win/tclWinInit.c (AppendEnvironment): Silenced a compilation warning
+ about a type mismatch.
+
+2004-07-07 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompile.c (TclCompileScript): fix for [Bug 458361].
+ Single-word scripts are compiled with an unshared cmdName to avoid
+ shimmering between bytecode and cmdName reps.
+
+2004-07-07 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCmdMZ.c (TclMergeReturnOptions): Simplified logic and
+ removed potential memory leak. [Bug 986257].
+
+2004-07-07 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tools/man2help2.tcl (setTabs, IPmacro): Added support for the more
+ advanced *roff macros used in Tk's doc/bind.n
+
+ * generic/tclObj.c (TclInitObjSubsystem): Declare all current object
+ types.
+
+2004-07-06 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/cmdMZ.test (cmdMZ-return-2.17): Added a test that a word
+ containing backslash-quoted value is treated correctly.
+
+ * generic/tclCompile.c (TclWordKnownAtCompileTime): [Bug 986196]
+ Corrected flaw above and the flaw that caused TCL_TOKEN_SIMPLE_WORDs
+ to have their original word value copied ( "{a b}" ) rather than the
+ actual value ( "a b" ). Thanks to Kevin Kenny for report and tests.
+
+2004-07-06 Kevin B. Kenny <kennykb@acm.org>
+
+ * tests/cmdMZ.test (cmdMZ-return-2.15,cmdMZ-return-2.16): Added a test
+ that a return code containing spaces is correctly returned.
+
+2004-07-06 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tools/man2html2.tcl (IPmacro, setTabs): Added support for the more
+ advanced *roff macros used in Tk's doc/bind.n
+
+2004-07-05 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclBasic.c (DeleteInterpProc): fix for [Bug 983660], found
+ by pspjuth. Tear down the global namespace before freeing the interp
+ handle, to allow the bytecodes to free their non-shared literals.
+ * generic/tclLiteral.c (TclReleaseLiteral): moved special code for
+ self-ref so that it is also used for non-shared literals. Possible bug
+ found by inspection.
+
+2004-07-03 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c (ExprRoundFunc):
+ * tests/expr-old.test (39.1): added support for wide integers to
+ round(); [Bug 908375], reported by Hemang Lavana.
+
+2004-07-03 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompile.h:
+ * generic/tclInt.decls:
+ * generic/tclIntDecls.h:
+ * generic/tclStubInit.c: Moved declaration of TclCompEvalObj() from
+ tclCompile.h to the internal stubs table, for compiler
+ experimentation.
+
+2004-07-02 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/regcomp.c (stid): correct minor pointer size error
+
+ * generic/tclPipe.c (TclCreatePipeline): applied TIP #202 patch that
+ * doc/exec.n, tests/exec.test: adds 2>@1 as a special case
+ redirection of stderr to the result output.
+
+2004-07-02 Kevin B. Kenny <kennykb@acm.org>
+
+ * tests/io.test: Changed several tests to run the event loop rather
+ than just calling [update] periodically, avoiding intermittent
+ failures (usually in io-29.32) that stemmed from unreaped processes on
+ Windows.
+ * tests/winPipe.test (winpipe-1.11): Fixed a bug that caused test to
+ fail if the path name of the working directory contained whitespace
+ [Bug 678430]
+
+2004-07-01 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/fileSystem.test: Added test for [Bug 970529]
+
+2004-07-01 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * win/README.binary, win/README: Updated references to Tcl and Tk 8.4
+ to point to 8.5 instead. Thanks to Theo Verelst for spotting this.
+ * generic/tcl.h: Added note to help prevent those changes from getting
+ missed in the future.
+
+ * doc/Namespace.3, doc/load.n, doc/Limit.3: Typo fixes and remove
+ duplicate documentation. [Bug 983146]
+
+2004-06-30 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/fileSystem.test: Minor correction to new fileSystem-9.X tests
+ so that they clean up temporary directories correctly.
+
+2004-06-30 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * doc/filename.n: clarified behaviour concerning trailing slashes in
+ filenames [Bug 971976]
+
+ * win/tclWinFile.c:
+ * tests/fileSystem.test: fix and tests for [Bug 979879]
+
+2004-06-30 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ TIP#188 IMPLEMENTATION
+
+ * doc/string.n, tests/string.test: Add 'wideinteger' to things
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd): that can be tested for with
+ the [string is] subcommand. [Patch 940915, by Kevin Kenny]
+
+2004-06-29 Don Porter <dgp@users.sourceforge.net>
+
+ * win/tclWinInit.c: Corrected reference counting flaw in recent
+ changes. Thanks to Pat Thoyts. [Bug 981893].
+
+2004-06-29 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * win/tclWin32Dll.c: fix to compilation with VC++ 5.2
+
+2004-06-29 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * library/safe.tcl: Make sure that the temporary variable is local to
+ the namespace and not inadvertently global. [Bug 981733]
+
+2004-06-24 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/unixNotfy.test: Modified constraints so that testing with a
+ threaded tclsh (not tcltest) will not hang.
+
+2004-06-23 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclThreadStorage.c: Corrected type casting errors that led
+ to calculation of a negative index value, thus accesses outside the
+ threadStorageCache array, thus memory corruption. Crash observed on
+ Mac OS X platform.
+
+2004-06-23 Joe Mistachkin <joe@mistachkin.com>
+
+ * generic/tclThread.c: Implements platform independent thread storage
+ * generic/tclThreadStorage.c: mechanism and fixes associated bugs on
+ platforms where there is limited thread local storage space
+ (Win98/WinNT4). [Patch 976496]
+
+ * generic/tclInt.decls:
+ * generic/tclIntDecls.h: Added thread storage functions to the
+ * generic/tclStubInit.c: internal stubs table.
+
+ * unix/Makefile.in:
+ * unix/configure:
+ * unix/tcl.m4:
+ * win/makefile.vc:
+ * win/rules.vc:
+ * win/Makefile.in: Modified the unix, VC++, and Cygwin build systems
+ * win/configure: to include the new "tclThreadStorage.c" and the new
+ * win/tcl.m4: USE_THREAD_STORAGE define.
+
+2004-06-23 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * tests/io.test: Added -force to 18.1 and 18.2. This was failing on
+ WinXP.
+
+ * tests/winFCmd.test: Added a cleanup to winFCmd-16.11 to avoid a
+ failure in 16.12.
+
+ * tests/eofchar.data: Added -kb option to ensure a binary checkout to
+ win32 systems. This fixes a failure in io-61.1
+
+ * win/makefile.vc: fix for [Bug 977369] about launching tclsh to
+ generate a tclConfig.sh with the nmake build system
+
+2004-06-23 Kevin B. Kenny <kennykb@acm.org>
+
+ * tests/winDde.test (createChildProcess): Added a 200-ms delay (with
+ the event loop live) when shutting down the test DDE server process.
+ With the delay in place, nuisance failures of tests winDde-4.2, -6.5,
+ and -6.6 appear to be much less frequent. [Bug 957449]
+
+2004-06-23 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/*.test: Standardize use of platform constraints.
+
+ * unix/tclUnixInit.c (GetStackSize, TclpCheckStackSpace):
+ * unix/tclUnixThrd.c (TclpThreadGetStackSize): Added code to check
+ whether the C stack is about to be exceeded, from [Patch 746378] by
+ Joe Mistachkin but with substantial revisions.
+
+2004-06-22 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tclEvent.c (NewThreadProc): Fixed broken build on Windows
+ caused by missing TCL_THREAD_CREATE_RETURN.
+
+ * tests/stack.test (stack-3.1): Corrected nuisance error in threaded
+ builds.
+
+2004-06-22 Zoran Vasiljevic <vasiljevic@users.sf.net>
+
+ * generic/tclEvent.c:
+ * generic/tclInt.h:
+ * unix/tclUnixNotfy.c:
+ * unix/tclUnixThrd.c:
+ * win/tclWinThrd.c: [Bug 770053]. See bug report for more information
+ about what it does.
+
+ * tests/unixNotfy.test: rewritten to use tcltest::threadReap to
+ gracefully wait for the test thread to exit. Otherwise we got a race
+ condition with main thread exiting before the test thread. This
+ exposed the long-standing Tcl lib issue with resource
+ garbage-collection on application exit.
+
+2004-06-21 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tclWin32Dll.c (DllMain, _except_dllmain_detach_handler)
+ (TclpCheckStackSpace, _except_checkstackspace_handler)
+ (TclWinCPUID, _except_TclWinCPUID_detach_handler):
+ * win/tclWinChan.c (Tcl_MakeFileChannel)
+ (_except_makefilechannel_handler):
+ * win/tclWinFCmd.c (DoRenameFile, _except_dorenamefile_handler)
+ (DoCopyFile, _except_docopyfile_handler):
+ Rework pushing of exception handler function pointer so that compiling
+ with gcc -O3 works. Remove empty function call to avoid compiler
+ warning. Mark the DllMain function as noinline to avoid compiler error
+ from duplicated asm labels in generated code.
+
+2004-06-21 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclThreadAlloc.c (Ptr2Block): Rewrote so as to maximize the
+ chance of detecting and reporting a memory inconsistency without
+ relying on things being consistent. [Bug 975895]
+
+2004-06-18 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/load.test: Relaxed strictness of error message matching
+ for test load-2.3 so that it will pass on Mac OSX.
+
+ * generic/tclEncoding.c: Static TclFindEncodings -> FindEncodings.
+ * generic/tclInt.h: Updated TclpFindExecutable() so that failed
+ * generic/tclUtil.c: attempts to find the executable are saved
+ * unix/tclUnixFile.c: just as successful finds are. [Patch 966053]
+ * unix/tclUnixTest.c:
+
+2004-06-18 Kevin B. Kenny <kennykb@acm.org>
+
+ * tests/winFCmd.test (winFCmd-16.12): Changed test to compute the
+ target directory, so as not to fail if the user's HOME isn't the root.
+
+2004-06-19 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tcl.m4: autoconf 2.5 fixes in Darwin section.
+ * unix/configure: autoconf-2.57
+
+2004-06-18 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * unix/tclUnixInit.c (localeTable): Added some more locale to encoding
+ mapping info from Jim Huang <jserv@kaffe.org>
+
+ * generic/tclInt.h (PendingObjData,TclFreeObjMacro,etc):
+ * generic/tclObj.c (TclFreeObj): Added scheme for making TclFreeObj()
+ avoid blowing up the C stack when freeing up very large object trees.
+ [Bug 886231]
+
+ * win/tclWinInit.c (SetDefaultLibraryDir): Fix logic, simplify and add
+ comments.
+
+2004-06-17 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclObj.c: Added missing space in panic message.
+
+ * win/tclWinInit.c: Inform [tclInit] about the default library
+ directory via the ::tclDefaultLibrary variable. This should correct a
+ problem with my 2004-06-11 commit. Better solutions still in the
+ works. Thanks to Joe Mistachkin for pointing out the breakage.
+
+2004-06-16 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/library.n: Moved variables ::auto_oldpath and
+ * library/auto.tcl: ::unknown_pending into ::tcl namespace.
+ * library/init.tcl: [Bugs 808319, 948794]
+
+2004-06-15 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/binary.n: Added some notes to the documentation of the 'a'
+ format to address the point raised in [RFE 768852].
+
+2004-06-15 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tclConfig.sh.in (TCL_EXTRA_CFLAGS): set to @CFLAGS@, which is
+ the configure-time CFLAGS. Addendum to m4 change on 2004-05-26.
+
+2004-06-14 Kevin Kenny <kennykb@acm.org>
+
+ * win/Makefile.in: Corrected compilation flags for tclPkgConfig.c so
+ that it doesn't require Stubs.
+ * generic/tclBasic.c (Tcl_CreateInterp): Removed comment stating that
+ TclInitEmbeddedConfigurationInformation needs Stubs; with the change
+ above, the comment is now erroneous.
+
+2004-06-11 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/Encoding.3: Removed bogus claims about tcl_libPath.
+
+ * generic/tclInterp.c (Tcl_Init): Stopped setting the
+ tcl_libPath variable. [tclInit] can get all its directories without it.
+
+ * tests/unixInit.test: Modified test code that made use of
+ tcl_libPath variable.
+
+ * unix/tclUnixInit.c: Stopped setting the tclDefaultLibrary variable,
+ execept on the Mac OS X platform with HAVE_CFBUNDLE. In that
+ configuration we should seek some way to make use of the TIP 59
+ facilities and get rid of that usage of tclDefaultLibrary as well.
+
+ * generic/tclInterp.c: Updated [tclInit] to make $env(TCL_LIBRARY) an
+ absolute path, and to include the scriptdir,runtime configuration value
+ on the search path for init.tcl.
+
+ * unix/tclUnixInit.c: The routines Tcl_Init() and TclSourceRCFile()
+ * win/tclWinInit.c: had identical implementations for both win and
+ * generic/tclInterp.c: unix. Moved to a single generic implementation.
+ * generic/tclMain.c:
+ * library/init.tcl:
+ * generic/tclInitScript.h (removed):
+ * unix/Makefile.in:
+ * win/tcl.dsp:
+
+ * unix/configure.in: Updated TCL_PACKAGE_PATH value to handle
+ * win/configure.in: --libdir configuration.
+
+ * unix/configure.in: autoconf-2.57
+ * win/configure.in:
+
+ * generic/tclBasic.c (Tcl_CreateInterp): Moved call to
+ TclInitEmbeddedConfigurationInformation() earlier in
+ Tcl_CreateInterp() so that other parts of interp creation and
+ initialization may access and use the config values.
+
+2004-06-11 Kevin Kenny <kennykb@acm.org>
+
+ * win/tclAppInit.c: Restored the 'setargv' procedure when compiling
+ with mingw. Apparently, the command line parsing in mingw doesn't work
+ as well as that in vc++, and the result was (1) that winPipe-8.19
+ failed, and (2) that 'make test' would work at all only with
+ TESTFLAGS='-singleproc 1'. [Bug 967195]
+
+2004-06-10 Zoran Vasiljevic <vasiljevic@users.sf.net>
+
+ * generic/tclIOUtil.c: removed forceful setting of the private cached
+ current working directory rep from within the Tcl_FSChdir(). We
+ delegate this task to the Tcl_FSGetCwd() which does this task anyway.
+ The relevant code is still present but disabled temporarily until the
+ change proves correct. The Tcl test suite passes all test with the
+ given change so I suppose it is good enough.
+
+2004-06-10 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/tclUnixInit.c (TclpInitLibraryPath): Disabled addition of
+ * win/tclWinInit.c (TclpInitLibraryPath): relative-to-executable
+ directories to the library search path. A first step in reform of
+ Tcl's startup process.
+
+ ***POTENTIAL INCOMPATIBILITY***
+ Attempts to directly run ./tclsh or ./tcltest out of a build directory
+ will either fail, or will make use of an installed script library in
+ preference to the one in the source tree. Use `make shell` or `make
+ runtest` instead.
+
+ * tests/unixInit.test: Modified tests to suit above changes.
+
+ * generic/tclPathObj.c: Corrected [file tail] results when operating
+ on a path produced by TclNewFSPathObj(). [Bug 970529]
+
+2004-06-09 Zoran Vasiljevic <vasiljevic@users.sf.net>
+
+ * generic/tclIOUtil.c: partially corrected [Bug 932314]. Also
+ corrected return values of Tcl_FSChdir() to reflect those of the
+ underlying platform-specific call. Originally, return codes were mixed
+ with those of Tcl.
+
+2004-06-08 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompile.c:
+ * generic/tclExecute.c: handle warning [Bug 969066]
+
+2004-06-08 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclHash.c (RebuildTable): Move declaration of variable so it
+ is only declared when it is used. [Bug 969068]
+
+2004-06-07 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/lsearch.n: Added correct option to example. [Bug 968219]
+
+2004-06-05 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tcl.h: Corrected Tcl_WideInt declarations so that the mingw
+ build works again.
+ * generic/tclDecls.h: Changes to the tests for clock
+ * generic/tclInt.decls: frequency in Tcl_WinTime so
+ * generic/tclIntDecls.h: that any clock frequency is
+ * generic/tclIntPlatDecls.h: accepted provided that all
+ * generic/tclPlatDecls.h: CPU's in the system share a
+ * generic/tclStubInit.c: common chip, and hence,
+ * tests/platform.test (platform-1.3): presumably, a common clock.
+ * win/tclWin32Dll.c (TclWinCPUID): This change necessitated a
+ * win/tclWinTest.c (TestwincpuidCmd) small burst of assembly code
+ * win/tclWinTime.c (Tcl_GetTime): to read CPU ID information,
+ which was added as TclWinCPUID in the internal Stubs. To test this
+ code in the common case of a single-processor machine, a
+ 'testwincpuid' command was added to tclWinTest.c, and a test case in
+ platform.test. Thanks to Jeff Godfrey and Richard Suchenwirth for
+ reporting this bug. [Bug 976722]
+
+2004-06-04 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tcl.h: Restored #include <stdio.h> to tcl.h,
+ rejecting the "fix" for "Bug" 945570. Tcl_FSSeek() needs the values of
+ SEEK_SET, etc. and too many extensions rely on tcl.h providing stdio.h
+ for them.
+
+2004-06-02 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tclWinFile.c (TclpFindExecutable): when using GetModuleFileNameA
+ (Win9x), convert from CP_ACP to WCHAR then convert back to utf8.
+ Adjunct to 2004-04-07 fix.
+
+2004-06-02 David Gravereaux <davygrvy@pobox.com>
+
+ * tests/winPipe.test (winpipe-6.1): blocking set to 1 before closing
+ to ensure we get an exitcode. The windows pipe channel driver doesn't
+ differentiate between a blocking and non-blocking close just yet, but
+ will soon. Part of [Bug 947693]
+
+2004-06-02 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * doc/file.n: fix to documentation of 'file volumes' (Bug 962435)
+
+2004-06-01 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc: check for either MSDEVDIR or MSVCDIR being in the
+ environment, for VC7. [Bug 942214]
+
+ * generic/tclIO.c (Tcl_SetChannelOption): -buffersize wasn't
+ understanding hexidecimal notation nor was reporting number conversion
+ errors. The behavior to silently ignore settings outside the
+ acceptable range of Tcl_SetChannelBufferSize (<10 or >1M) is
+ unchanged. This silent ignoring behavior might be up for review soon.
+
+2004-05-30 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinPipe.c:
+ * win/tclWinPort.h: Reworked the win implementation of Tcl_WaitPid to
+ support exitcodes in the 'signed short' range. Even though this range
+ is non-portable, it is valid on windows. Detection of exception codes
+ are now more accurate. Previously, an application that exited with
+ ExitProcess((DWORD)-1); was improperly reported as exiting with
+ SIGABRT.
+
+2004-05-30 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclInterp.c: Added comments describing the purposes of each
+ function in the limit implementation and rewrote the names of some
+ non-public functions for greater clarity of purpose.
+ * doc/interp.n: Added note about what happens when a limited
+ interpreter creates a slave interpreter.
+ * doc/Limit.3: Added manual page for the resource limit subsystem's C
+ API. [Bug 953903]
+
+2004-05-29 Joe English <jenglish@users.sourceforge.net>
+
+ * doc/global.n, doc/interp.n, doc/lrange.n: Fix minor markup errors.
+
+2004-05-28 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/*.n: Added examples to many (too many to list) more man pages.
+
+2004-05-25 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c:
+ * generic/tclVar.c: using (ptrdiff_t) instead of (int) casting to
+ correct compiler warnings [Bug 961657], reported by Bob Techentin.
+
+2004-05-27 Kevin B. Kenny <kennykb@acm.org>
+
+ * tests/clock.test: Added a single test for the presence of %G in
+ [clock format], and conditioned out the clock-10.x series if they're
+ all going to fail because of a broken strftime() call. [Bug 961714]
+
+2004-05-27 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclHash.c (CompareStringKeys): Added #ifdef to allow people
+ to instruct this function to use strcmp(). [FRQ 951168]
+
+ * generic/tclVar.c: Moved declarations into #if guards so they only
+ happen when required.
+ * unix/tclUnixPort.h: Guard declaration of strtod() so it is only
+ enabled when we don't have a declaration in stdlib.h
+ * unix/tclUnixThrd.c (Tcl_CreateThread): Added declarations
+ * unix/tclUnixTest.c (AlarmHandler): and casts so that
+ * unix/tclUnixChan.c (TtyModemStatusStr): all functions are
+ * generic/tclScan.c (Tcl_ScanObjCmd): defined before use
+ * generic/tclDictObj.c (InvalidateDictChain): and no cross-type
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd): uses are performed.
+
+ The overall effect is to make building with gcc with the additional
+ flags -Wstrict-prototypes -Wmissing-prototypes produce no increase in
+ the total number of warnings (except for main(), which is undeclared
+ for traditional reasons.)
+
+2004-05-26 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/Makefile.in: Rework configure ordering to TCL_LINK_LIBS,
+ * unix/tcl.m4: ENABLE_SHARED, CONFIG_CFLAGS, & ENABLE_SYMBOLS
+ * unix/configure: before TCL_EARLY_FLAGS and TCL_64BIT_FLAGS
+ * unix/configure.in: (about 400 lines earlier) in configure.in. This
+ forces CFLAGS configuration to be done before many tests, which is
+ needed for 64-bit builds and may affect other builds. Also make
+ CONFIG_CFLAGS append to CFLAGS directly instead of using EXTRA_CFLAGS,
+ and have LDFLAGS append to any existing value. [Bug 874058]
+ * unix/dltest/Makefile.in: change EXTRA_CFLAGS to DEFS
+
+2004-05-26 Don Porter <dgp@users.sourceforge.net>
+
+ * library/tcltest/tcltest.tcl: Correction to debug prints and testing
+ * library/tcltest/pkgIndex.tcl: if TCLTEST_OPTIONS value. Corrected
+ * tests/tcltest.test: double increment of numTestFiles in
+ -singleproc 1 configurations. Updated tcltest-19.1 to tcltest 2.1
+ behavior. Corrected tcltest-25.3 to not falsely report a failure in
+ tcltest.test. Bumped to tcltest 2.2.6. [Bugs 960560, 960926]
+
+2004-05-25 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/http.n (http::config): add -urlencoding option (default utf-8)
+ * library/http/http.tcl: that specifies encoding conversion of
+ * library/http/pkgIndex.tcl: args for http::formatQuery. Previously
+ * tests/http.test: undefined, RFC 2718 says it should be
+ utf-8. 'http::config -urlencoding {}' returns previous behavior, which
+ will throw errors processing non-latin-1 chars. Bumped http package to
+ 2.5.0.
+
+2004-05-25 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclInterp.c (DeleteScriptLimitCallback): Move all deletion
+ of script callback hash table entries to happen here so the entries
+ are correctly removed at the right time. [Bug 960410]
+
+2004-05-25 Miguel Sofer <msofer@users.sf.net>
+
+ * docs/global.n: added details for qualified variable names [Bug
+ 959831]
+
+2004-05-25 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclNamesp.c (Tcl_FindNamespaceVar):
+ * tests/namespace.test (namespace-17.10-12): reverted commit of
+ 2004-05-23 and removed the tests, as it interferes with the varname
+ resolver and there are apps that break (AlphaTk). A fix will have to
+ wait for Tcl9.
+
+ * generic/tclVar.c: Caching of namespace variables disabled: no simple
+ way was found to avoid interfering with the resolver's idea of
+ variable existence. A cached varName may keep a variable's name in the
+ namespace's hash table, which is the resolver's criterion for
+ existence.
+
+ * tests/namespace.c (namespace-17.10): testing for interference
+ between varname caching and name resolver.
+
+2004-05-25 Kevin Kenny <kennykb@acm.org>
+
+ * tests/winFCmd.test: Correct test for the presence of a CD-ROM so
+ that it doesn't misdetect some other sort of filesystem with a
+ write-protected root as being a CD-ROM drive. [Bug 918267]
+
+2004-05-25 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/winPipe.test: Protect against path being set
+ * tests/unixInit.test: Unset path when done.
+ * tests/unload.test (unload-3.1): Verify [pkgb_sub] does not exist.
+ Delete interps when done.
+ * tests/stringComp.test: stop re-use of string.test test names
+ * tests/regexpComp.test: stop re-use of regexp.test test names
+ * tests/namespace.test (namespace-46.3): Verify [p] does not exist.
+ * tests/http.test: Clear away the custom [bgerror] when done.
+ * tests/io.test: Take care to use namespace variables.
+ * tests/autoMkindex.test (autoMkindex-5.2): Use variable "result"
+ that gets cleaned up.
+ * tests/exec.test: Clean up the "path" array.
+ * tests/interp.test (interp-9.3): Initialize res, so prior values
+ cannot make the test fail.
+ * tests/execute.test (execute-8.1): Updated to remove the trace set
+ on ::errorInfo. When left in place, that trace can cause later tests
+ to fail.
+
+2004-05-25 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclBasic.c: Removed references to Tcl_RenameCommand from
+ * generic/tcl.h: comments. [Bug 848440, second part]
+
+ * tests/fCmd.test: Rewrote tests that failed consistently on NFS so
+ they either succeed (through slightly more liberal matching of the
+ results) or are constrained to not run. [Bug 931312]
+
+ * doc/bgerror.n: Use idiomatic open flags for working with log
+ files. [Bug 959602]
+
+2004-05-24 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclExecute.c (VerifyExprObjType): use GET_WIDE_OR_INT to
+ properly have tclIntType used for smaller values. This corrects [TclX
+ Bug 896727] and any other 3rd party extension that created math
+ functions but was not yet WIDE_INT aware in them.
+
+2004-05-24 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclInterp.c (TclInitLimitSupport): Made limits work on
+ platforms where sizeof(void*)!=sizeof(int). [Bug 959193]
+
+2004-05-24 Miguel Sofer <msofer@users.sf.net>
+
+ * doc/set.n: accurate description of name resolution process,
+ referring to namespace.n for details [Bug 959180]
+
+2004-05-23 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclNamesp.c (Tcl_FindNamespaceVar): [Bug 959052] fixed,
+ insuring that no "zombie" variables are found.
+ * generic/tclVar.c (TclLookupSimpleVar): comments re [Bug 736729]
+ (predecessor of [Bug 959052]) removed.
+ * tests/namespace.test: added tests 17.10-12
+
+ The patch modifies non-documented behaviour, and passes every test in
+ the testsuite. However, scripts relying on the old behaviour may
+ break.
+ Note that the only behaviour change concerns the creative writing of
+ unset variables. More precisely, which variable will be created when
+ neither a namespace variable nor a global variable by that name
+ exists, as defined by [info vars]. The new behaviour is that the
+ namespace resolution process deems a variable to exist exactly when
+ [info vars] finds it - ie, either it has value, or else it was "fixed"
+ by a call to [variable].
+ Note: this patch was removed on 2002-05-25.
+
+2004-05-22 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclVar.c (TclObjLookupVar, TclObjUnsetVar2): fix for new (in
+ tcl8.4) exteriorisations of [Bug 736729] due to the use of
+ tclNsVarNameType obj types. Reenabling the use of this objType ("VAR
+ ref absolute" benchmark down to 66 ms, from 230). Added comments in
+ TclLookupSimpleVar explaining my current understanding of [Bug
+ 736729].
+
+2004-05-22 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclVar.c: fix for [Bug 735335]. The use of tclNsVarNameType
+ objs is still disabled, pending resolution of [Bug 736729].
+
+2004-05-21 Miguel Sofer <msofer@users.sf.net>
+
+ * tests/namespace.test (namespace-41.3): removed the {knownBug}
+ constraint: [Bug 231259] is closed since nov 2001, and the fix of [Bug
+ 729692] (INST_START_CMD) makes the test succeed.
+
+2004-05-21 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclExecute.c (TclExecuteByteCode): Move a few declarations a
+ short distance so pre-C99 compilers can cope. Also fix so
+ TCL_COMPILE_DEBUG path compiles...
+
+2004-05-21 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c (TclExecuteByteCode): reorganised TEBC
+ automatic variables, defining them in tight blocks instead of at the
+ function level. This has three purposes:
+ - it simplifies the analysis of individual instructions
+ - it is preliminary work to the non-recursive engine
+ - it allows a better register allocation by the optimiser; under
+ gcc3.3, this results in up to 10% runtime in some tests
+
+2004-05-20 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclInterp.c (TclLimitRemoveAllHandlers):
+ * generic/tclBasic.c (DeleteInterpProc):
+ * tests/interp.test (interp-34.7): Ensure that all limit callbacks are
+ deleted when their interpreters are deleted. [Bug 956083]
+
+2004-05-19 Kevin B. Kenny <kennykb@acm.org>
+
+ * win/tclWinFile.c (TclpMatchInDirectory): fix for an issue where
+ there was a sneak path from Tcl_DStringFree to SetErrorCode(0). The
+ result was that the error code could be reset between a call to
+ FindFirstFileEx and the check of its status return, leading to a
+ bizarre error return of {POSIX unknown {No error}}. (Found in
+ unplanned test - no incident logged at SourceForge.)
+
+2004-05-19 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/interp.test (interp-34.3): Rewrite this test to see if a time
+ limit can catch a tight bytecode loop, a maximally aggressive
+ denial-of-service attack.
+ * generic/tclInterp.c (Tcl_LimitCheck): Fix the sense of checks to see
+ whether a time limit has been extended.
+
+ * tests/*.test: Many minor fixes, including ensuring that every test
+ is run (so constraints control whether the test is doing anything) and
+ making sure that constraints are always set using the API instead of
+ poking around inside tcltest's internal datastructures. Also got rid
+ of all trailing whitespace lines from the test suite!
+
+2004-05-19 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tclIO.c: Fixed [SF Tcl Bug 943274]. This is the same problem
+ * generic/tclIO.h: as [SF Tcl Bug 462317], see ChangeLog entry
+ 2001-09-26. The fix done at that time is incomplete. It is possible to
+ get around it if the actual read operation is defered and not executed
+ in the event handler itself. Instead of tracking if we are in an read
+ caused by a synthesized fileevent we now track if the OS has delivered
+ a true event = actual data and bypass the driver if a read finds that
+ there is no actual data waiting. The flag is cleared by a short or
+ full read.
+
+ ***POTENTIAL INCOMPATIBILITY*** for channel drivers.
+
+2004-05-17 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclPathObj.c: fix to (Bug 956063) in 'file dirname'.
+ * tests/cmdAH.test: added test for this bug.
+
+ * doc/FileSystem.3: better documentation of refCount requirements of
+ some FS functions (Bug 956126)
+
+2004-05-19 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclTest.c (TestgetintCmd): Made the tests in get.test check
+ * tests/get.test: Tcl_GetInt() since the core now
+ avoids that function.
+
+2004-05-18 Kevin B. Kenny <kennykb@acm.org>
+
+ * compat/strftime.c (_fmt, ISO8601Week):
+ * doc/clock.n:
+ * tests/clock.test: Major rework to the handling of ISO8601 week
+ numbers. Now passes all the %G and %V test cases on Windows, Linux and
+ Solaris [Bugs 500285, 500389, and 852944]
+
+2004-05-18 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/append.n, doc/upvar.n: Added example.
+
+2004-05-18 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc: now generates a tclConfig.sh from Pat Thoyts [Patch
+ 909911]
+
+2004-05-18 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/lsearch.n: Improve clarity (based on [Patch 955361] by Peter
+ Spjuth)
+
+ * tools/man2help2.tcl (macro,SHmacro): Added support for subsection
+ (.SS) header macros.
+
+ * doc/interp.n: Added user documentation for the TIP#143 resource
+ limits and some examples.
+
+ * generic/tclInterp.c (Tcl_LimitCheck, Tcl_LimitTypeReset): Reset the
+ limit-exceeded flag when removing a limit.
+
+2004-05-18 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c (TclExecuteByteCode): added comments to
+ classify the variables according to their use in TEBC.
+
+2004-05-17 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/global.n, doc/uplevel.n: Added an example.
+
+ * tests/info.test (info-3.1): Corrected test result back to what it
+ used to be in Tcl 7.* now that command counts are being correctly kept
+
+ * generic/tclExecute.c (TEBC:INST_START_CMD): Make sure that the
+ command-count is always advanced. Allows TIP#143 limits to tell that
+ work is being done.
+
+ * doc/list.n: Updated example to fit with the unified format.
+ * doc/seek.n: Added some examples.
+
+2004-05-17 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * win/tclWinFile.c:
+ * tests/cmdAH.test: fix to (Bug 954263) where 'file executable' was
+ case-sensitive.
+
+2004-05-17 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/OpenFileChnl.3: Documented type of 'offset' argument to Tcl_Seek
+ was wrong. [Bug 953374]
+
+2004-05-16 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c (TclExecuteByteCode): remove one level of
+ indirection for compiledLocals addressing.
+
+2004-05-16 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c (INST_CALL_FUNC1): bugfix; restored
+ (DE)CACHE_STACK_INFO pair around the call - the user defined math
+ function could cause a recursive call to TEBC.
+
+2004-05-16 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclBasic.c (Tcl_DeleteInterp):
+ * generic/tclExecute.c (INST_START_CMD): interp deletion now modifies
+ the compileEpoch, eliminating the need for the check for interp
+ deletion in INST_START_CMD.
+
+2004-05-16 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompile.h:
+ * generic/tclCompile.c:
+ * generic/tclExecute.c: changed implementation of {expand}, last
+ chance while in alpha as ...
+
+ ***POTENTIAL INCOMPATIBILITY***
+ Scripts precompiled with ProComp under previous tcl8.5a versions may
+ malfunction due to changed instruction numbers for
+ INST_LIST_INDEX_IMM, INST_LIST_RANGE_IMM and INST_START_CMD.
+
+2004-05-14 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclInt.decls: Promoted TclpLocaltime and TclpGmtime
+ * generic/tclIntDecls.h: from Unix-specific stubs to the generic
+ * generic/tclIntPlatDecls.h: internal Stubs table. Reran 'genstubs'
+ * generic/tclStubInit.c:
+ * unix/tclUnixPort.h:
+
+ * generic/tclClock.c: Changed a buggy 'GMT' timezone specification
+ to the correct 'GMT0'. [Bug 922848]
+
+ * unix/tclUnixThrd.c: Moved TclpGmtime and TclpLocaltime to
+ unix/tclUnixTime.c where they belong.
+
+ * unix/tclUnixTime.c (TclpGmtime, TclpLocaltime, TclpGetTimeZone,
+ ThreadSafeGMTime [removed],
+ ThreadSafeLocalTime [removed],
+ SetTZIfNecessary, CleanupMemory):
+ Restructured to make sure that the same mutex protects all calls to
+ localtime, gmtime, and tzset. Added a check in front of those calls to
+ make sure that the TZ env var hasn't changed since the last call to
+ tzset, and repeat tzset if necessary. [Bug 942078] Removed a buggy
+ test of the Daylight Saving Time information in 'gettimeofday' in
+ favor of applying 'localtime' to a known value. [Bug 922848]
+
+ * tests/clock.test (clock-3.14): Added test to make sure that changes
+ to $env(TZ) take effect immediately.
+
+ * win/tclWinTime.c (TclpLocaltime, TclpGmtime): Added porting layer
+ for 'localtime' and 'gmtime' calls.
+
+2004-05-14 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c:
+ * generic/tclCompile.h: the math functions receive a pointer to top of
+ the stack (tosPtr) instead of the execution environment (eePtr). First
+ step towards a change in the execution stack management - it is now
+ only used within TEBC.
+
+2004-05-13 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ TIP#143 IMPLEMENTATION
+
+ * generic/tclExecute.c (TclCompEvalObj, TclExecuteByteCode):
+ * generic/tclBasic.c (TclEvalObjvInternal): Enable limit checking.
+ * generic/tclInterp.c (Tcl_Limit*): Public limit API.
+ * generic/tcl.decls:
+ * tests/interp.test: Basic tests of command limits.
+
+ * doc/binary.n: TIP#129 IMPLEMENTATION [Patch 858211]
+ * generic/tclBinary.c: Note that the test suite probably has many more
+ * tests/binary.test: failures now due to alterations in constraints.
+
+2004-05-12 Miguel Sofer <msofer@users.sf.net>
+
+ Optimisations for INST_START_CMD [Bug 926164].
+ * generic/tclCompile.c (TclCompileScript): avoid emitting
+ INST_START_CMD as the first instruction in a bytecoded Tcl_Obj. It is
+ not needed, as the checks are done before calling TEBC.
+ * generic/tclExecute.c (TclExecuteByteCode): runtime peephole
+ optimisation: check at INST_POP if the next instruction is
+ INST_START_CMD, in which case we fall through.
+
+2004-05-11 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/split.n, doc/join.n: Updated examples and added more.
+
+2004-05-11 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * doc/glob.n: documented behaviour of symbolic links with 'glob -types
+ d' (Bug 951489)
+
+2004-05-11 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/scan.n: Updated the examples to be clearer about their relevance
+ to the scan command.
+
+2004-05-10 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/scan.n: Added examples.
+
+2004-05-10 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinPipe.c (BuildCommandLine): Moved non-obvious appending
+ logic to outside the loop and added commentary for its purpose. Also
+ use the existence of contents in the linePtr rather than the scratch
+ DString post the append, as this more clear.
+
+ (TclpCreateProcess): When under NT, with no console, and executing a
+ DOS application, the path priming does not need an ending space as
+ BuildCommandLine() will do this for us.
+
+2004-05-08 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclFileName.c:
+ * generic/tclIOUtil.c: remove some compiler warnings on MacOS X.
+
+2004-05-07 Chengye Mao <chengye.geo@yahoo.com>
+
+ * win/tclWinPipe.c: refixed bug 789040 re-entered in rev 1.41. Let's
+ be careful and don't re-enter previously fixed bugs.
+
+2004-05-08 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/format.n: Added examples.
+
+2004-05-07 Miguel Sofer <msofer@users.sf.net>
+
+ * doc/unset.n: added upvar.n to the "see also" list
+
+2004-05-07 Reinhard Max <max@suse.de>
+
+ * generic/tclEncoding.c:
+ * tests/encoding.test: added support and tests for translating
+ embedded null characters between real nullbytes and the internal
+ representation on input/output [Bug 949905].
+
+2004-05-07 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclFileName.c:
+ * generic/tclIOUtil.c:
+ * generic/tclFileSystem.h:
+ * tests/fileSystem.test: fix for [Bug 943995], in which vfs-registered
+ root volumes were not handled correctly as glob patterns in all
+ circumstances.
+
+2004-05-06 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclInt.h:
+ * generic/tclObj.c (TclFreeObj): made TclFreeObj use the new macro
+ TclFreeObjMacro(), so that the allocation and freeing of Tcl_Obj is
+ defined in a single spot (the macros in tclInt.h), with the exception
+ of the TCL_MEM_DEBUG case.
+ The #ifdef logic for the corresponding macros has been reformulated to
+ make it clearer.
+
+2004-05-05 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/break.n, doc/continue.n, doc/for.n, doc/while.n: More examples.
+
+2004-05-05 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/unixInit.test (unixInit-2.10): Test correction for Mac OSX.
+ Be sure to consistently compare normalized path names. Thanks to
+ Steven Abner (tauvan). [Bug 948177]
+
+2004-05-05 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/CrtObjCmd.3: Remove reference to Tcl_RenameCommand; there is no
+ such API. [Bug 848440]
+
+2004-05-05 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinSock.c (SocketEventProc) : connect errors should fire both
+ the readable and writable handlers because this is how it works on
+ UNIX [Bug 794839]
+
+ * generic/tclEncoding.c (TclFinalizeEncodingSubsystem):
+ FreeEncoding(systemEncoding); moved to before the hash table iteration
+ as it was causing a double free attempt under some conditions.
+
+ * win/coffbase.txt: Added the tls extension to the list of preferred
+ load addresses.
+
+2004-05-04 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/fileSystem.test (filesystem-1.39): replace 'file volumes'
+ * tests/fileName.test (filename-12.9,10): lindex with direct C:/
+ hard-coded because A:/ was being used and that is empty for most.
+
+ * tests/winFCmd.test (winFCmd-16.12): test volumerelative $HOME
+
+2004-05-04 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclAlloc.c: Make sure Tclp*Alloc* routines get
+ * generic/tclInt.h: declared in the TCL_MEM_DEBUG and
+ * generic/tclThreadAlloc.c: TCL_THREADS configuration. [Bug 947564]
+
+ * tests/tcltest.test: Test corrections for Mac OSX. Thanks to Steven
+ Abner (tauvan). [Bug 947440]
+
+2004-05-04 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclEvent.c (TclSetLibraryPath): Suppress a warning.
+
+2004-05-03 Andreas Kupries <andreask@activestate.com>
+
+ * Applied [Patch 868853], fixing a mem leak in TtySetOptionProc.
+ Report and Patch provided by Stuart Cassoff <stwo@users.sf.net>.
+
+2004-05-03 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclProc.c (TclCreateProc): comments corrected.
+
+2004-05-03 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompile.c (TclCompileScript): setting the compilation
+ namespace outside of the loop.
+
+2004-05-03 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompile.c:
+ * generic/tclInt.h: reverted fix for [Bug 926445] of 2004-04-02,
+ restoring TCL_ALIGN to the header file. Todd Helfter reported that the
+ macro is required by tbcload.
+
+2004-05-03 Kevin Kenny <kennykb@acm.org>
+
+ * win/tclWin32Dll.c (TclpCheckStackSpace):
+ * tests/stack.test (stack-3.1): Fix for undetected stack overflow in
+ TclReExec on Windows. [Bug 947070]
+
+2004-05-03 Don Porter <dgp@users.sourceforge.net>
+
+ * library/init.tcl: Corrected unique prefix matching of
+ interactive command completion in [unknown]. [Bug 946952]
+
+2004-05-02 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclProc.c (TclObjInvokeProc):
+ * tests/proc.test (proc-3.6): fix for bad quoting of multi-word proc
+ names in error messages [Bug 942757]
+
+2004-04-30 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/glob.n, doc/incr.n, doc/set.n: More examples.
+ * doc/if.n, doc/rename.n, doc/time.n:
+
+2004-04-30 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclInt.h: Replaced Kevin Kenny's temporary
+ * generic/tclThreadAlloc.c: fix for Bug 945447 with a cleaner,
+ more permanent replacement.
+
+2004-04-30 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclThreadAlloc.c: Added a temporary (or so I hope!)
+ inclusion of "tclWinInt.h" to avoid problems when compiling on
+ Win32-VC++ with --enable-threads. [Bug 945447]
+
+2004-04-30 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/puts.n: Added a few examples.
+
+2004-04-29 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/execute.test (execute-8.2): Avoid crashes when there is
+ limited system stack space (threads-enabled).
+
+2004-04-28 Miguel Sofer <msofer@users.sf.net>
+
+ * doc/global.n:
+ * doc/upvar.n:
+ * generic/tclVar.c (ObjMakeUpvar):
+ * tests/upvar.test (upvar-8.11):
+ * tests/var.test (var-3.11): Avoid creation of unusable variables:
+ [Bug 600812] [TIP 184].
+
+2004-04-28 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/lsearch.n: Fixed fault in documentation of -index option [943448]
+
+2004-04-26 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/tclUnixFCmd.c (TclpObjNormalizePath): Corrected improper
+ positioning of returned checkpoint. [Bug 941108]
+
+2004-04-26 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/open.n, doc/close.n: Updated (thanks to David Welton) to be
+ clearer about pipeline errors and added example to open(n) that shows
+ simple pipeline use. [Patches 941377,941380]
+
+ * doc/DictObj.3: Added warning about the use of Tcl_DictObjDone and an
+ example of use of iteration. [Bug 940843]
+
+ * doc/Thread.3: Reworked to remove references to testing interfaces
+ and instead promote the use of the Thread package. [Patch 932527]
+ Also reworked and reordered the page for better readability.
+
+2004-04-25 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tcl.h: Removed obsolete declarations and #include's.
+ * generic/tclInt.h: [Bugs 926459, 926486]
+
+2004-04-24 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWin32Dll.c (DllMain): Added DisableThreadLibraryCalls() for
+ the DLL_PROCESS_ATTACH case. We're not interested in knowing about
+ DLL_THREAD_ATTACH, so disable the notices.
+
+2004-04-24 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tclPort.h:
+ * macosx/Makefile:
+ * unix/Makefile.in: followup on tcl header reform [FR 922727]: removed
+ use of relative #include paths in tclPort.h to allow installation of
+ private headers outside of tcl source tree; added 'unix' dir to
+ compiler header search path; add newly required tcl private headers to
+ Tcl.framework on Mac OSX.
+
+2004-04-23 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tclIO.c (Tcl_SetChannelOption): Fixed [SF Tcl Bug 930851].
+ When changing the eofchar we have to zap the related flags to prevent
+ them from prematurely aborting the next read.
+
+2004-04-25 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclPathObj.c: fix to [Bug 940281]. Tcl_FSJoinPath will now
+ always return a valid Tcl_Obj when the input is valid.
+ * generic/tclIOUtil.c: fix to [Bug 931823] for a more consistent
+ Tcl_FSPathSeparator() implementation which allows filesystems not to
+ implement their Tcl_FSFilesystemSeparatorProc if they wish to use the
+ default '/'. Also fixed associated memory leak seen with, e.g., tclvfs
+ package.
+ * doc/FileSystem.3: documented Tcl_FSJoinPath return values more
+ clearly, and Tcl_FSFilesystemSeparatorProc requirements.
+
+2004-04-23 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWin32Dll.c: Removed my mistake from 4/19 of adding an exit
+ handler to TclWinInit. TclWinEncodingsCleanup called from
+ TclFinalizeFilesystem does the Tcl_FreeEncoding for us.
+
+ * win/tclWinChan.c (Tcl_MakeFileChannel): Case for CloseHandle
+ returning zero and not throwing a
+ RaiseException(EXCEPTION_INVALID_HANDLE) now being done.
+
+2004-04-22 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tclEvent.c: TclSetLibraryPath's use of caching the stringrep
+ of the pathPtr object to TclGetLibraryPath called from another thread
+ was ineffective if the original's stringrep had been invalidated as
+ what happens when it gets muted to a list.
+
+ * win/tclWinTime.c: If the Tcl_ExitProc (StopCalibration) is called
+ from the stack frame of DllMain's PROCESS_DETACH, the wait operation
+ should timeout and continue.
+
+ * generic/tclInt.h:
+ * generic/tclThread.c:
+ * generic/tclEvent.c:
+ * unix/tclUnixThrd.c:
+ * win/tclWinThrd.c: Provisions made so masterLock, initLock, allocLock
+ and joinLock mutexes can be recovered during Tcl_Finalize.
+
+2004-04-22 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/switch.n: Reworked the examples to be more systematically named
+ and to cover some TIP#75 capabilities.
+
+ * doc/cd.n: Documentation clarification from David Welton.
+
+ * doc/exec.n: Added some examples, Windows ones from Arjen Markus and
+ Unix ones by myself.
+
+2004-04-21 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/Hash.3: Added note to Tcl_{First,Next}HashEntry docs that
+ deleting the element they return is supported (and is in fact the only
+ safe update you can do to the structure of a hashtable while an
+ iteration is going over it.)
+
+ * doc/bgerror.n: Added example from David Welton. [Patch 939473]
+
+ * doc/after.n: Added examples from David Welton. [Patch 938820]
+
+2004-04-19 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWin32Dll.c: Added an exit handler in TclWinInit() so
+ tclWinTCharEncoding could be freed during Tcl_Finalize().
+
+ * generic/tclEncoding.c: Added FreeEncoding(systemEncoding) in
+ TclFinalizeEncodingSubsystem because its ref count was incremented in
+ TclInitEncodingSubsystem.
+
+2004-04-19 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/read.n: Added example from David Welton. [Patch 938056]
+
+2004-04-19 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclObj.c (Tcl_GetDoubleFromObj) Corrected "short circuit"
+ conversion of int to double. Reported by Jeff Hobbs on the Tcl'ers
+ Chat.
+
+2004-04-16 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/lreplace.n, doc/lrange.n, doc/llength.n: More examples for
+ * doc/linsert.n, doc/lappend.n: the documentation.
+
+2004-04-16 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * doc/FileSystem.3: Corrected documentation of Tcl_FSUtime, and the
+ corresponding filesystem driver Tcl_FSUtimeProc. [Bug 935838]
+
+2004-04-16 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/socket.n: Added example from [Patch 936245].
+ * doc/gets.n: Added example based on [Patch 935911].
+
+2004-04-15 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclClock.c (Tcl_ClockObjCmd): Minor fault in a [clock
+ clicks] error message.
+
+2004-04-07 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tclWinInit.c (TclpSetInitialEncodings): note that WIN32_CE is
+ also a unicode platform.
+ * generic/tclEncoding.c (TclFindEncodings, Tcl_FindExecutable):
+ * generic/tclInt.h: Correct handling of UTF
+ * unix/tclUnixInit.c (TclpInitLibraryPath): data that is actually
+ * win/tclWinFile.c (TclpFindExecutable): "clean", allowing the
+ * win/tclWinInit.c (TclpInitLibraryPath): loading of Tcl from paths
+ that contain multi-byte chars on Windows [Bug 920667]
+
+ * win/configure: define TCL_LIB_FLAG, TCL_BUILD_LIB_SPEC,
+ * win/configure.in: TCL_LIB_SPEC, TCL_PACKAGE_PATH in tclConfig.sh.
+
+2004-04-06 Don Porter <dgp@users.sourceforge.net>
+
+ Patch 922727 committed. Implements three changes:
+
+ * generic/tclInt.h: Reworked the Tcl header files into a clean
+ * unix/tclUnixPort.h: hierarchy where tcl.h < tclPort.h < tclInt.h
+ * win/tclWinInt.h: and every C source file should #include
+ * win/tclWinPort.h: at most one of those files to satisfy its
+ declaration needs. tclWinInt.h and tclWinPort.h also better organized
+ so that tclWinPort.h includes the Windows implementation of
+ cross-platform declarations, while tclWinInt.h makes declarations that
+ are available on Windows only.
+
+ * generic/tclBinary.c (TCL_NO_MATH): Deleted the generic/tclMath.h
+ * generic/tclMath.h (removed): header file. The internal Tcl
+ * macosx/Makefile (PRIVATE_HEADERS): header, tclInt.h, has a
+ * win/tcl.dsp: #include <math.h> directly,
+ and file external to Tcl needing libm should do the same.
+
+ * win/Makefile.in (WIN_OBJS): Deleted the win/tclWinMtherr.c file.
+ * win/makefile.bc (TCLOBJS): It's a vestige from matherr() days
+ * win/makefile.vc (TCLOBJS): gone by.
+ * win/tcl.dsp:
+ * win/tclWinMtherr.c (removed):
+
+ End Patch 922727.
+
+ * tests/unixInit.test (unixInit-3.1): Default encoding on Darwin
+ systems is utf-8. Thanks to Steven Abner (tauvan). [Bug 928808]
+
+2004-04-06 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/cmdAH.test (cmdAH-18.2): Added constraint because
+ access(...,X_OK) is defined to be permitted to be meaningless when
+ running as root, and OSX exhibits this. [Bug 929892]
+
+2004-04-02 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompile.c:
+ * generic/tclInt.h: removed the macro TCL_ALIGN() from tclInt.h,
+ replaced by the static macro ALIGN() in tclCompile.c [Bug 926445]
+
+2004-04-02 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompile.h: removed redundant #ifdef _TCLINT [Bug 928415],
+ reported by tauvan.
+
+2004-04-02 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/tcltest.test: Corrected constraint typos: "nonRoot" ->
+ "notRoot". Thanks to Steven Abner (tauvan). [Bug 928353]
+
+2004-04-01 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclInt.h: Removed obsolete tclBlockTime* declarations. [Bug
+ 926454]
+
+2004-04-01 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclIOUtil.c: Fix to privately reported vfs bug with 'glob
+ -type d -dir . *' across a vfs boundary. No tests for this are
+ currently possible without effectively moving tclvfs into Tcl's test
+ suite.
+
+2004-03-31 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/msgcat.n: Clarified message catalog file encodings. [Bug 811457]
+ * library/msgcat/msgcat.tcl: Updated internals to make use of [dict]s
+ to store message catalog data and to use [source -encoding utf-8] to
+ access catalog files. Thanks to Michael Sclenker. [Patch 875055, RFE
+ 811459] Corrected [mcset] to be able to successfully set a translation
+ to the empty string. [mcset $loc $src {}] was incorrectly set the $loc
+ translation of $src back to $src. Also changed [ConvertLocale] to
+ minimally require a non-empty "language" part in the locale value. If
+ not, an error raised prompts [Init] to keep looking for a valid locale
+ value, or ultimately fall back on the "C" locale. [Bug 811461].
+ * library/msgcat/pkgIndex.tcl: Bump to msgcat 1.4.1.
+
+2004-03-30 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclHash.c (HashStringKey): Cleaned up. This function is not
+ faster, but it is a little bit clearer.
+ * generic/tclLiteral.c (HashString): Applied logic from HashObjKey.
+ * generic/tclObj.c (HashObjKey): Rewrote to fix fault which hashed
+ every single-character object to the same hash bucket. The new code is
+ shorter, simpler, clearer, and (happily) faster.
+
+2004-03-30 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c (TEBC): reverting to the previous method for
+ async tests in TEBC, as the new method turned out to be too costly.
+ Async tests now run every 64 instructions.
+
+2004-03-30 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompile.c: New instruction code INST_START_CMD that
+ * generic/tclCompile.h: allows checking the bytecode's validity
+ * generic/tclExecute.c: [Bug 729692] and the interp's readyness
+ * tests/interp.test (18.9): [Bug 495830] before running the command.
+ * tests/proc.test (7.1): It also changes the mechanics of the async
+ * tests/rename.test (6.1): tests in TEBC, doing it now at command
+ start instead of every 16 instructions.
+
+2004-03-30 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclFileName.c: Fix to Windows glob where the pattern is a
+ * generic/tclIOUtil.c: volume relative path or a network share [Bug
+ * tests/fileName.test: 898238]. On windows 'glob' will now return
+ * tests/fileSystem.test: the results of 'glob /foo/bar' and 'glob
+ \\foo\\bar' as 'C:/foo/bar', i.e. a correct absolute path (rather than
+ a volume relative path).
+
+ Note that the test suite does not test commands like
+ 'glob //Machine/Shared/*' (on a network share).
+
+2004-03-30 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclPathObj.c: Fix to filename bugs recently
+ * tests/fileName.test: introduced [Bug 918320].
+
+2004-03-29 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclMain.c (Tcl_Main, StdinProc): Append newline only
+ * tests/basic.test (basic-46.1): to incomplete scripts
+ as part of multi-line script construction. Do not add an extra
+ trailing newline to the complete script. [Bug 833150]
+
+2004-03-28 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompile.c (TclCompileScript): corrected possible segfault
+ when a compilation returns TCL_OUTLINE_COMPILE after having grown the
+ compile environment [Bug 925121].
+
+2004-03-27 Miguel Sofer <msofer@users.sf.net>
+
+ * doc/array.n: added documentation for trace-realted behaviour of
+ 'array get' [Bug 449893]
+
+2004-03-26 Don Porter <dgp@users.sourceforge.net>
+
+ * README: Bumped version number to 8.5a2 to distinguish
+ * tools/tcl.wse.in: HEAD of CVS development from the recent 8.5a1
+ * unix/configure.in: release.
+ * unix/tcl.spec:
+ * win/README.binary:
+ * win/configure.in:
+
+ * unix/configure: autoconf-2.57
+ * win/configure:
+
+2004-03-26 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclPathObj.c: Fix to Windows-only volume relative path
+ * tests/fileSystem.test: normalization. [Bug 923568]. Also fixed
+ another volume relative bug found while testing.
+
+2004-03-24 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclNamesp.c (NsEnsembleImplementationCmd): Fix messed up
+ handling of strncmp result which just happened to work in some libc
+ implementations. [Bug 922752]
+
+2004-03-23 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/StringObj.3: Inverted the sense of the documentation of how the
+ bytes parameter is documented to match behaviour. [Bug 921464]
+
+2004-03-19 Kevin B. Kenny <kennykb@acm.org>
+
+ * compat/strtoll.c:
+ * compat/strtoull.c:
+ * generic/tclIntDecls.h:
+ * generic/tclMain.c:
+ * generic/tclObj.c:
+ * win/tclWinDde.c:
+ * win/tclWinReg.c:
+ * win/tclWinTime.c: Made HEAD build on Windows VC++ again.
+
+2004-03-19 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclIntDecls.h: Made HEAD build on Solaris again by applying
+ fix recommended by Don Porter.
+
+2004-03-18 Reinhard Max <max@suse.de>
+
+ * generic/tclIntDecls.h: Removed TclpTime_t. It wasn't really needed,
+ * generic/tclInt.h: but caused warnings related to
+ * generic/tclInt.decls: strict aliasing with GCC 3.3.
+ * generic/tclClock.c:
+ * generic/tclDate.c:
+ * generic/tclGetDate.y:
+ * win/tclWinTime.c:
+ * unix/tclUnixTime.c:
+
+ * generic/tclNamesp.c: Added temporary pointer variables to work
+ * generic/tclStubLib.c: around warnings related to
+ * unix/tclUnixChan.c: strict aliasing with GCC 3.3.
+
+ * unix/tcl.m4: Removed -Wno-strict-aliasing.
+
+2004-03-18 Daniel Steffen <das@users.sourceforge.net>
+
+ Removed support for Mac OS Classic platform [Patch 918142]
+
+ * README:
+ * compat/string.h:
+ * doc/Encoding.3:
+ * doc/FileSystem.3:
+ * doc/Init.3:
+ * doc/Macintosh.3 (removed):
+ * doc/OpenFileChnl.3:
+ * doc/OpenTcp.3:
+ * doc/SourceRCFile.3:
+ * doc/Thread.3:
+ * doc/clock.n:
+ * doc/exec.n:
+ * doc/fconfigure.n:
+ * doc/file.n:
+ * doc/filename.n:
+ * doc/glob.n:
+ * doc/open.n:
+ * doc/puts.n:
+ * doc/resource.n (removed):
+ * doc/safe.n:
+ * doc/source.n:
+ * doc/tclvars.n:
+ * doc/unload.n:
+ * generic/README:
+ * generic/tcl.decls:
+ * generic/tcl.h:
+ * generic/tclAlloc.c:
+ * generic/tclBasic.c:
+ * generic/tclCmdAH.c:
+ * generic/tclDate.c:
+ * generic/tclDecls.h:
+ * generic/tclFCmd.c:
+ * generic/tclFileName.c:
+ * generic/tclGetDate.y:
+ * generic/tclIOCmd.c:
+ * generic/tclIOUtil.c:
+ * generic/tclInitScript.h:
+ * generic/tclInt.decls:
+ * generic/tclInt.h:
+ * generic/tclIntDecls.h:
+ * generic/tclIntPlatDecls.h:
+ * generic/tclMain.c:
+ * generic/tclMath.h:
+ * generic/tclNotify.c:
+ * generic/tclPathObj.c:
+ * generic/tclPlatDecls.h:
+ * generic/tclPort.h:
+ * generic/tclStubInit.c:
+ * generic/tclTest.c:
+ * generic/tclThreadJoin.c:
+ * library/auto.tcl:
+ * library/init.tcl:
+ * library/package.tcl:
+ * library/safe.tcl:
+ * library/tclIndex:
+ * mac/AppleScript.html (removed):
+ * mac/Background.doc (removed):
+ * mac/MW_TclAppleScriptHeader.h (removed):
+ * mac/MW_TclAppleScriptHeader.pch (removed):
+ * mac/MW_TclBuildLibHeader.h (removed):
+ * mac/MW_TclBuildLibHeader.pch (removed):
+ * mac/MW_TclHeader.h (removed):
+ * mac/MW_TclHeader.pch (removed):
+ * mac/MW_TclHeaderCommon.h (removed):
+ * mac/MW_TclStaticHeader.h (removed):
+ * mac/MW_TclStaticHeader.pch (removed):
+ * mac/MW_TclTestHeader.h (removed):
+ * mac/MW_TclTestHeader.pch (removed):
+ * mac/README (removed):
+ * mac/bugs.doc (removed):
+ * mac/libmoto.doc (removed):
+ * mac/morefiles.doc (removed):
+ * mac/porting.notes (removed):
+ * mac/tclMac.h (removed):
+ * mac/tclMacAETE.r (removed):
+ * mac/tclMacAlloc.c (removed):
+ * mac/tclMacAppInit.c (removed):
+ * mac/tclMacApplication.r (removed):
+ * mac/tclMacBOAAppInit.c (removed):
+ * mac/tclMacBOAMain.c (removed):
+ * mac/tclMacChan.c (removed):
+ * mac/tclMacCommonPch.h (removed):
+ * mac/tclMacDNR.c (removed):
+ * mac/tclMacEnv.c (removed):
+ * mac/tclMacExit.c (removed):
+ * mac/tclMacFCmd.c (removed):
+ * mac/tclMacFile.c (removed):
+ * mac/tclMacInit.c (removed):
+ * mac/tclMacInt.h (removed):
+ * mac/tclMacInterupt.c (removed):
+ * mac/tclMacLibrary.c (removed):
+ * mac/tclMacLibrary.r (removed):
+ * mac/tclMacLoad.c (removed):
+ * mac/tclMacMath.h (removed):
+ * mac/tclMacNotify.c (removed):
+ * mac/tclMacOSA.c (removed):
+ * mac/tclMacOSA.r (removed):
+ * mac/tclMacPanic.c (removed):
+ * mac/tclMacPkgConfig.c (removed):
+ * mac/tclMacPort.h (removed):
+ * mac/tclMacProjects.sea.hqx (removed):
+ * mac/tclMacResource.c (removed):
+ * mac/tclMacResource.r (removed):
+ * mac/tclMacSock.c (removed):
+ * mac/tclMacTclCode.r (removed):
+ * mac/tclMacTest.c (removed):
+ * mac/tclMacThrd.c (removed):
+ * mac/tclMacThrd.h (removed):
+ * mac/tclMacTime.c (removed):
+ * mac/tclMacUnix.c (removed):
+ * mac/tclMacUtil.c (removed):
+ * mac/tcltkMacBuildSupport.sea.hqx (removed):
+ * tests/all.tcl:
+ * tests/binary.test:
+ * tests/cmdAH.test:
+ * tests/cmdMZ.test:
+ * tests/fCmd.test:
+ * tests/fileName.test:
+ * tests/fileSystem.test:
+ * tests/interp.test:
+ * tests/io.test:
+ * tests/ioCmd.test:
+ * tests/load.test:
+ * tests/macFCmd.test (removed):
+ * tests/osa.test (removed):
+ * tests/resource.test (removed):
+ * tests/socket.test:
+ * tests/source.test:
+ * tests/unload.test:
+ * tools/cvtEOL.tcl (removed):
+ * tools/genStubs.tcl:
+ * unix/Makefile.in:
+ * unix/README:
+ * unix/mkLinks:
+ * unix/tcl.spec:
+ * win/README.binary:
+ * win/tcl.dsp:
+
+2004-03-17 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/lsearch.n: Improved examples on the advanced capabilities of
+ lsearch (with the right options, set element removal can be done)
+ following discussion on tkchat.
+
+2004-03-16 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/catch.n: Compiled [catch] no longer fails to catch syntax
+ errors. Removed the claims in the documentation that it does.
+ * doc/return.n: Updated example to use [dict merge].
+
+2004-03-16 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/configure, unix/tcl.m4: add -Wno-strict-aliasing for GCC to
+ suppress useless type puning warnings.
+
+2004-03-16 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/file.n: *roff formatting fix. [Bug 917171]
+
+2004-03-15 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinNotify.c: Fixed a mistake where the return value of
+ MsgWaitForMultipleObjectsEx for "a message is in the queue" wasn't
+ accurate. I removed the check on the case result==(WAIT_OBJECT_0 + 1)
+ This was having the error of falling into GetMessage and waiting there
+ by accident, which wasn't alertable through Tcl_AlertNotifier. I'll do
+ some more study on this and try to find-out why.
+
+2004-03-12 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ IMPLEMENTATION OF TIP#163
+ * generic/tclDictObj.c (DictMergeCmd): This is based on work by Joe
+ * tests/dict.test (dict-20.*): English in Tcl [FRQ 745851]
+ * doc/dict.n: but not exactly.
+
+2004-03-10 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclGetDate.y (TclGetDate): Fix so that [clock scan
+ <timeOfDay> -gmt true] uses the GMT base date instead of the local
+ one. [Bug 913513]
+ * tests/clock.test: Added test cases for wrong ISO8601 week number
+ [Bug 500285] and wrong GMT base date [Bug 913513]. Several tests still
+ fail on Windows, and these are actual faults in [clock scan]. Fix is
+ still pending.
+ * generic/tclDate.c: Regenerated.
+
+2004-03-08 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclFileName.c: Fix to 'glob -path' near the root
+ * tests/fileName.test: of the filesystem. [Bug 910525]
+
+2004-03-08 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclParse.c (TclParseInit): Modified TclParseInit so
+ * generic/tclTest.c ([testexprparser]): that Tcl_Parse initialization
+ conforms to documented promised about what fields will not be
+ modified by what Tcl_Parse* routines. [Bug 910595]
+
+2004-03-05 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/configure: Regen.
+ * win/configure.in: Check for define of MWMO_ALERTABLE in winuser.h.
+ * win/tclWinPort.h: If MWMO_ALERTABLE is not defined in winuser.h then
+ define it. This is needed for Mingw.
+
+2004-03-05 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclTest.c: Modified TesteventObjCmd to use a
+ Tcl_QueuePosition in place of an 'int' for the enumerated queue
+ position, to avoid a compiler warning on SGI. [Bug 771960]
+
+2004-03-05 Kevin B. Kenny <kennykb@acm.org>
+
+ * tests/registry.test: Applied fix from [Patch 910174] to make the test
+ for an English-language system include any country code, rather than
+ just English-United States.1252. Thanks to Pat Thoyts for the changes.
+
+2004-03-04 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * tests/registry.test: Applied fixed from [Bug 766159] to skip two
+ tests on Win98 that depend on a Unicode registry (NT specific).
+
+2004-03-04 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclInt.h (TclParseInit): Factored the common code
+ * generic/tclParse.c (TclParseInit): for initializing a Tcl_Parse
+ * generic/tclParseExpr.c: struct into one routine.
+
+2004-03-04 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * library/reg/pkgIndex.tcl: Added TIP #100 support to the
+ * win/tclWinReg.c: registry package [patch 903831]
+ This provides a Windows test of the TIP #100 mechanism and a sample to
+ show how unloading an extension can be done.
+
+2004-03-04 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * unix/dltest/pkgua.c: Fix minor syntax problems. [Bug 909288]
+
+2004-03-03 Jeff Hobbs <jeffh@ActiveState.com>
+
+ *** 8.5a1 TAGGED FOR RELEASE ***
+
+ * changes: updated for 8.5a1
+
+2004-03-03 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc: default environment variable for VC++ is %MSDevDir%
+ not %MSVCDir%, although vcvars32.bat sets both.
+
+ * win/tclWinNotify.c (Tcl_WaitForEvent) : Allows an idling notifier to
+ service "Asynchronous Procedure Calls" from its wait state. Only
+ useful for extension authors who decide they might want to try
+ "completion routines" with WriteFileEx(), as an example. From
+ experience, I recommend that "completion ports" should be used instead
+ as the execution of the callbacks are more managable.
+
+2004-03-01 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * README: update patchlevel to 8.5a1
+ * generic/tcl.h:
+ * tools/tcl.wse.in, tools/tclSplash.bmp:
+ * unix/configure, unix/configure.in, unix/tcl.spec:
+ * win/README.binary, win/configure, win/configure.in:
+
+ * unix/tcl.m4: update HP-11 build libs setup
+
+2004-03-01 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/tcl.m4 (SC_CONFIG_CFLAGS): Allow 64-bit enabling on
+ IRIX64-6.5* systems. [Bug 218561]
+ * unix/configure: autoconf-2.57
+
+ * generic/tclTrace.c (TclCheckInterpTraces): The TIP 62
+ * generic/tclTest.c (TestcmdtraceCmd): implementation introduced a
+ * tests/trace.test (trace-29.10): bug by testing the CallFrame
+ level instead of the iPtr->numLevels level when deciding what traces
+ created by Tcl_Create(Obj)Trace to call. Added test to expose the
+ error, and made fix. [FRQ 462580]
+
+2004-02-28 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/fileSystem.test: fix to Tcl Bug 905163.
+ * tests/fileName.test: fix to Tcl Bug 904705.
+
+ * doc/{various}.n: removed 'the the' typos.
+
+2004-02-26 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Makefile: fixed copyright year in Tcl.framework Info.plist
+
+2004-02-25 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/basic.test: Made several tests more robust to the
+ * tests/cmdMZ.test: list-quoting of path names that might contain
+ * tests/exec.test: Tcl-special chars like { or [. Should help us
+ * tests/io.test: sort out [Bug 554068]
+ * tests/pid.test:
+ * tests/socket.test:
+ * tests/source.test:
+ * tests/unixInit.test:
+
+2004-02-25 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclLoad.c (Tcl_LoadObjCmd): Missing dereference caused
+ segfault with non-loadable extension. [Bug 904307]
+
+ * unix/tclUnixChan.c (TcpGetOptionProc): Stop memory leak with very
+ long hostnames. [Bug 888777]
+
+2004-02-25 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tclWinDde.c: Removed some gcc warnings - except for the
+ -Wconversion warning for GetGlobalAtomName. gcc is just wrong about
+ this.
+
+2004-02-24 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ IMPLEMENTATION OF TIP#100 FROM GEORGIOS PETASIS
+ * generic/tclLoad.c (Tcl_UnloadObjCmd): Implementation.
+ * tests/unload.test: Test suite.
+ * unix/dltest/pkgua.c: Helper for test suite.
+ * doc/unload.n: Documentation.
+ Also assorted changes (mostly small) to several other files.
+
+2004-02-23 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/regc_locale.c (cclass): Buffer was having its size reset
+ instead of being released => memleak. [Bug 902562]
+
+2004-02-21 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclLoad.c (Tcl_LoadObjCmd): Fixed memory leak due to an
+ improper error exit route.
+
+2004-02-20 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinSock.c (SocketThreadExitHandler): Don't call
+ TerminateThread when WaitForSingleObject returns a timeout.
+ Tcl_Finalize called from DllMain will pause all threads. Trust that
+ the thread will get the close notice at a later time if it does ever
+ wake up before being cleaned up by the system anyway.
+
+2004-02-17 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/tcltest.n:
+ * library/tcltest/tcltest.tcl: Changed -verbose default value to
+ {body error} so that detailed information on unexpected errors in
+ tests is provided by default, even after the fix for [Bug 725253]
+
+2004-02-17 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/unixInit.test (unixInit-7.1):
+ * unix/tclUnixInit.c (TclpInitPlatform): ensure the std fds exist to
+ prevent crash condition [Bug 772288]
+
+2004-02-17 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclCompCmds.c (TclCompileSwitchCmd): Bozo mistake in memory
+ releasing order when in an error case. [Bug 898910]
+
+2004-02-16 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclTrace.c (TclTraceExecutionObjCmd)
+ (TclTraceCommandObjCmd): fix possible mem leak in trace info.
+
+2004-02-12 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tclWinInit.c (AppendEnvironment): Use the tail component of the
+ passed in lib path instead of just blindly using lib+4. That worked
+ when lib was "lib/..." but fails for other values. Thanks go to
+ Patrick Samson for pointing this out.
+
+2004-02-10 David Gravereaux <davygrvy@pobox.com>
+
+ * win/nmakehlp.c: better macro grepping logic.
+
+2004-02-07 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc:
+ * win/rules.vc:
+ * win/tcl.rc:
+ * win/tclsh.rc: Added an 'unchecked' option to the OPTS macro so a
+ core built with symbols can be linked to the non-debug enabled C
+ run-time. As per discussion with Kevin Kenny. Called like this:
+
+ nmake -af makefile.vc OPTS=unchecked,symbols
+
+ This clarifies the meaning of the 'g' naming suffix to mean only that
+ the binary requires the debug enabled C run-time. Whether the binary
+ contains symbols or not is a different condition.
+
+2004-02-06 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/clock.n: Removed reference to non-existent [file ctime].
+
+2004-02-05 David Gravereaux <davygrvy@pobox.com>
+
+ * docs/tclvars.n: Added clarification of the tcl_platform(debug) var
+ that it only refers to the flavor of the C run-time, and not whether
+ the core contains symbols.
+
+2004-02-05 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclFileName.c (SkipToChar): Corrected CONST and type-casting
+ issues that caused compiler warnings.
+
+2004-02-04 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCmdAH.c (StoreStatData): Removed improper refcount
+ decrement of the varName parameter. This error was causing segfaults
+ following test cmdAH-28.7.
+
+ * library/tcltest/tcltest.tcl: Corrected references to non-existent
+ $name variable in [cleanupTests]. [Bug 833637]
+
+2004-02-03 Don Porter <dgp@users.sourceforge.net>
+
+ * library/tcltest/tcltest.tcl: Corrected parsing of single command
+ line argument (option with missing value) [Bug 833910]
+ * library/tcltest/pkgIndex.tcl: Bump to version 2.2.5.
+
+2004-02-02 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tclIO.c (Tcl_Ungets): Fixes improper filling of the channel
+ buffer. This is the buffer before the splice. [Bug 405995]
+
+2004-02-01 David Gravereaux <davygrvy@pobox.com>
+
+ * tests/winPipe.test: more pass-thru commandline verifications.
+ * win/tclWinPipe.c (BuildCommandLine): Special case quoting for '{'
+ not required by the c-runtimes's parse_cmdline().
+ * win/tclAppInit.c: Removed our custom setargv() in favor of the work
+ provided by the c-runtime. [Bug 672938]
+
+ * win/nmakehlp.c: defensive techniques to avoid static buffer
+ overflows and a couple envars upsetting invokations of cl.exe and
+ link.exe. [Bug 885537]
+
+ * tests/winPipe.test: Added proof that BuildCommandLine() is not doing
+ the "N backslashes followed a quote -> insert N * 2 + 1 backslashes
+ then a quote" rule needed for the crt's parse_cmdline().
+ * win/tclWinPipe.c: Fixed BuildCommandLine() to pass the new cases.
+
+2004-01-30 David Gravereaux <davygrvy@pobox.com>
+
+ * win/makefile.vc: Use the -GZ compiler switch when building for
+ symbols. This is supposed to emulate the release build better to avoid
+ hiding problems that only show themselves in a release build.
+
+2004-01-29 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclPathObj.c: fix to [Bug 883143] in file normalization
+
+2004-01-29 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * doc/file.n:
+ * generic/tclFCmd.c
+ * generic/tclTest.c
+ * library/init.tcl
+ * mac/tclMacFile.c
+ * tests/fileSystem.test: fix to [Bug 886352] where 'file copy -force'
+ had inconsistent behaviour wrt target files with insufficient
+ permissions, particular from vfs->native fs. Behaviour of '-force' is
+ now always consistent (and now consistent with behaviour of 'file
+ delete -force'). Added new tests and documentation and cleaned up the
+ 'simplefs' test filesystem.
+
+ * generic/tclIOUtil.c
+ * unix/tclUnixFCmd.c
+ * unix/tclUnixFile.c
+ * win/tclWinFile.c: made native filesystems more robust to C code
+ which asks for mount lists.
+
+ * generic/tclPathObj.c: fix to [Bug 886607] removing warning/error
+ with some compilers.
+
+2004-01-28 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclObj.c (SetBooleanFromAny): Rewrite to do more efficient
+ string->bool conversion.
+ Many other minor whitespace/style fixes to this file too.
+
+2004-01-27 David Gravereaux <davygrvy@pobox.com>
+
+ * win/nmakehlp.c: Use '.\nul' as the sourcefile name instead of 'nul'
+ so VC 5.2 doesn't try searching the path for it and failing with a
+ possible dialogbox popping up about having to add a CD to an empty
+ drive. Also added a SetErrorMode() call to disable any dialogs that
+ cl.exe or link.exe might create. [Bug 885537]
+
+2004-01-22 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * doc/file.n: clarified documentation of 'file system' [Bug 883825]
+ * tests/fCmd.test: improved test result in failure case.
+
+2004-01-22 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/fileSystem.test: 3 new tests
+ * generic/tclPathObj.c: fix to [Bug 879555] in file normalization.
+ * doc/filename.n: small clarification to Windows behaviour with
+ filenames like '.....', 'a.....', '.....a'.
+
+ * generic/tclIOUtil.c: slight improvement to native cwd caching on
+ Windows.
+
+2004-01-21 David Gravereaux <davygrvy@pobox.com>
+
+ * doc/Panic.3: Mentions of 'panic' and 'panicVA' removed from the
+ documentation.
+
+2004-01-21 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * doc/FileSystem.3:
+ * generic/tcl.decls:
+ * generic/tclCmdAH.c
+ * generic/tclDecls.h
+ * generic/tclFCmd.c
+ * generic/tclFileName.c
+ * generic/tclFileSystem.h
+ * generic/tclIOUtil.c
+ * generic/tclInt.decls
+ * generic/tclInt.h
+ * generic/tclIntDecls.h
+ * generic/tclPathObj.c
+ * generic/tclStubInit.c
+ * generic/tclTest.c
+ * mac/tclMacFile.c
+ * tests/fileName.test
+ * tests/fileSystem.test
+ * tests/winFCmd.test
+ * unix/tclUnixFile.c
+ * win/tclWin32Dll.c
+ * win/tclWinFCmd.c
+ * win/tclWinFile.c
+ * win/tclWinInt.h
+
+ Three main issues accomplished: (1) cleaned up variable names in the
+ filesystem code so that 'pathPtr' is used throughout. (2) applied a
+ round of filesystem optimisation with better handling and caching of
+ relative and absolute paths, requiring fewer conversions. (3)
+ clarifications to the documentation, particularly regarding the
+ acceptable refCounts of objects. Some new tests added. Tcl benchmarks
+ show a significant improvement over 8.4.5, and on Windows typically a
+ small improvement over 8.3.5 (Unix still appears to require
+ optimisation). TCL_FILESYSTEM_VERSION_2 introduced, but for internal
+ use only. There should be no public incompatibilities from these
+ changes. Thanks to dgp for extensive testing.
+
+2004-01-19 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinPipe.c (Tcl_WaitPid): Fixed a thread-safety problem with
+ the process list. The delayed cut operation after the wait was going
+ stale by being outside the list lock. It now cuts within the lock and
+ does a locked splice for when it needs to instead. [Bug 859820]
+
+2004-01-18 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclCompile.c, generic/tclCompile.h: Two new opcodes,
+ INST_LIST_INDEX_IMM and INST_LIST_RANGE_IMM, that have operand(s) of
+ new type OPERAND_IDX4 which represents indexes into things like lists
+ (and perhaps other things eventually.)
+ * generic/tclExecute.c (TclExecuteByteCode): Implementation of the new
+ opcodes. INST_LIST_INDEX_IMM does a simple [lindex] with either front-
+ or end-based simple indexing. INST_LIST_RANGE_IMM does an [lrange]
+ with front- or end-based simple indexing for both the reference to the
+ first and last items in the range.
+ * generic/tclCompCmds.c (TclCompileLassignCmd): Generate bytecode for
+ the [lassign] command.
+
+2004-01-17 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinInit.c: added #pragma comment(lib, "advapi32.lib") when
+ compiling under VC++ so we don't need to specify it when linking.
+
+2004-01-17 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclCmdIL.c (Tcl_LassignObjCmd): Add more shimmering
+ protection for when the list is also one of the variables.
+
+ BASIC IMPLEMENTATION OF TIP#57
+ * generic/tclCmdIL.c (Tcl_LassignObjCmd): Implementation of the
+ [lassign] command that takes full advantage of Tcl's object API.
+ * doc/lassign.n: New file documenting the command.
+ * tests/cmdIL.test (cmdIL-6.*): Test suite for the command.
+
+2004-01-15 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinReg.c: Placed the requirement for advapi.lib into the
+ object file itself with #pragma comment (lib, ...) when built with
+ VC++. This will simplify linking for users of the static library.
+
+ * win/rules.vc: Added new 'fullwarn' to the CHECKS commandline macro;
+ sets $(FULLWARNINGS).
+
+ * win/makefile.vc: Removed 'advapi.lib' from $(baselibs). Added new
+ logic to crank-up the warning levels for both compile and link when
+ $(FULLWARNINGS) is set. Some clean-up with how the resource files are
+ built and how -DTCL_USE_STATIC_PACKAGES is sent when compiling the
+ shells.
+
+ * win/tclAppInit.c: Small change in how TCL_USE_STATIC_PACKAGES is
+ used.
+
+ * win/tcl.rc:
+ * win/tclsh.rc: Some clean-up with how the resource files are built.
+ Fixed 'OriginalFilename' problem that still thought a debug suffix was
+ still 'd', now is 'g'.
+
+2004-01-14 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclDictObj.c (TraceDictPath, DictExistsCmd): Adjusted
+ behaviour of [dict exists] so a failure to look up a dictionary along
+ the path of dicts doesn't trigger an error. This is how it was
+ documented to behave previously... [Bug 871387]
+
+ * generic/tclDictObj.c: Assorted dict fixes from Peter Spjuth relating
+ to [Bug 876170].
+ (SetDictFromAny): Make sure that lists retain their ordering even when
+ converted to dictionaries and back.
+ (TraceDictPath): Correct object reference count handling!
+ (DictReplaceCmd, DictRemoveCmd): Stop object leak.
+ (DictIncrCmd,DictLappendCmd,DictAppendCmd,DictSetCmd,DictUnsetCmd):
+ Simpler handling of reference counts when assigning to variables.
+ * tests/dict.test (dict-19.2): Memory leak stress test
+
+2004-01-13 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCmdMZ.c (Tcl_SwitchObjCmd): Silence compiler warnings.
+
+ Patch 876451: restores performance of [return]. Also allows forms such
+ as [return -code error $msg] to be bytecompiled.
+
+ * generic/tclInt.h: Factored Tcl_ReturnObjCmd() into two pieces:
+ * generic/tclCmdMZ.c: TclMergeReturnOptions(), which can parse the
+ options to [return], check their validity, and create the
+ corresponding return options dictionary, and TclProcessReturn(), which
+ takes that return options dictionary and performs the [return]
+ operation.
+
+ * generic/tclCompCmds.c: Rewrote TclCompileReturnCmd() to call
+ TclMergeReturnOptions() at compile time so the return options
+ dictionary is computed at compile time (when it is fully known). The
+ dictionary is pushed on the stack along with the result, and the code
+ and level values are included in the bytecode as operands. Also
+ supports optimized compilation of un-[catch]ed [return]s from procs
+ with default options into the INST_DONE instruction.
+
+ * generic/tclExecute.c: Rewrote INST_RETURN instruction to retrieve
+ the code and level operands, pop the return options from the stack,
+ and call TclProcessReturn() to perform the [return] operation.
+
+ * generic/tclCompile.h: New utilities include TclEmitInt4 macro
+ * generic/tclCompile.c: and TclWordKnownAtCompileTime().
+
+ End Patch 876451.
+
+ * generic/tclFileName.c (Tcl_GlobObjCmd): Latest changes to management
+ of the interp result by Tcl_GetIndexFromObj() exposed improper interp
+ result management in the [glob] command procedure. Corrected by
+ adopting the Tcl_SetObjResult(Tcl_NewStringObj) pattern. This stopped
+ a segfault in test filename-11.36. [Bug 877677]
+
+2004-01-13 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct, Tcl_WrongNumArgs):
+ Create fresh objects instead of using the one currently in the
+ interpreter, which isn't guaranteed to be fresh and unshared. The cost
+ for the core will be minimal because of the object cache, and this
+ fixes [Bug 875395].
+
+2004-01-12 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompExpr.c (CompileLandOrLorExpr): cosmetic changes.
+
+2004-01-12 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompExpr.c (CompileLandOrLorExpr): new logic, fewer
+ instructions. As a side effect, the instructions INST_LOR and
+ INST_LAND are now never used.
+ * generic/tclExecute.c (INST_JUMP*): small optimisation; fix a bug in
+ debug code.
+
+2004-01-11 David Gravereaux <davygrvy@pobox.com>
+
+ * win/tclWinThrd.c (Tcl_ConditionNotify): condPtr must be dereferenced
+ to see if there are waiters else uninitialized datum is manipulated.
+ [Bug 849007 789338 745068]
+
+2004-01-09 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tcl.h: Renamed and deprecated #defines moved to within the
+ #ifndef TCL_NO_DEPRECATED block. This allows us to build Tcl to check
+ for deprecated functions in use, such as panic() and Tcl_Ckalloc(). By
+ request from DKF. Extensions that build with -DTCL_NO_DEPRECATED now
+ have these macros as restricted.
+ ***POTENTIAL INCOMPATIBILITY***
+
+ * win/makefile.vc:
+ * win/rules.vc: Added -DTCL_NO_DEPRECATED usage to makefile.vc.
+ Called like this: nmake -af makefile.vc CHECKS=nodep
+
+2004-01-09 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclIOUtil.c: fix to infinite loop in TclFinalizeFilesystem
+ [Bug 873311]
+
+ ******************************************************************
+ *** CHANGELOG ENTRIES FOR 2003 IN "ChangeLog.2003" ***
+ *** CHANGELOG ENTRIES FOR 2002 IN "ChangeLog.2002" ***
+ *** CHANGELOG ENTRIES FOR 2001 IN "ChangeLog.2001" ***
+ *** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000" ***
+ *** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" ***
+ ******************************************************************
diff --git a/ChangeLog.2005 b/ChangeLog.2005
new file mode 100644
index 0000000..0d1d7cf
--- /dev/null
+++ b/ChangeLog.2005
@@ -0,0 +1,3822 @@
+2005-12-30 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclStubLib.c: Corrected a typo in "missing Stubs table
+ pointer."
+
+2005-12-27 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tcl.decls: Destubbed TclTomMathInitializeStubs - it is in
+ * generic/tcl.h: the stub library, not the main shared
+ * generic/tclBasic.c: library. Exported Tcl_InitBignumFromDouble.
+ * generic/tclExecute.c:
+ * generic/tclInt.h:
+ * generic/tclStrToD.c:
+
+ * generic/tclDecls.h:
+ * generic/tclStubLib.c:
+ * generic/tclStubInit.c: Regenerated.
+
+ * generic/clock.tcl: Reverted to using the time zone abbreviation and
+ not its name to "stop the bleeding" on [Bug 1386377]. This is *not* a
+ good long-term solution, but there may not be one.
+
+ * libtommath/bn_mp_sqrt.c: Improved the initial approximation to the
+ square root, roughly doubling the speed of the routine. (This is a
+ local change that needs to be communicated to Tom.)
+
+ * win/Makefile.in: Corrected a bug where tommath_class.h and
+ tommath_superclass.h were not installed, making it impossible for
+ client code to compile against the tommath stubs.
+
+ * library/tzdata: Updated to Olson's tzdata2005r. (Latest changes to
+ Daylight Saving Time in Canada, plus redefinition of the Posix-style
+ zones [e.g., EST5EDT] to be locale-independent.)
+
+ * libtommath: Updated to Tom St.Denis's release 0.37.
+
+2005-12-20 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * generic/tclThreadAlloc.c (Tcl_GetMemoryInfo): Format values as longs
+ and not ints, so they are less likely to wrap on 64-bit machines.
+
+2005-12-19 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCmdMZ.c: Modified [string is double] to use
+ * tests/string.test: TclParseNumber() to parse trailing whitespace.
+ Ensures consistency, and makes it easier to cleanup after invalid
+ internal reps left behind by parsing [Bugs 1360532 1382287].
+
+ * generic/tclParseExpr.c: Added TCL_PARSE_NO_WHITESPACE to
+ * generic/tclScan.c: TclParseNumber() calls since [scan] and [expr]
+ * tests/scan.test: parsing don't want spaces in parsed numbers.
+
+ * generic/tclInt.h: Added TCL_PARSE_NO_WHITESPACE flag to the
+ * generic/tclStrToD.c: TclParseNumber() interface.
+
+2005-12-19 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * doc/Tcl.n: Clarify what is going on in variable substitution
+ following thread on comp.lang.tcl.
+
+2005-12-18 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * generic/tclCompCmds.c (TclCompileDictCmd): Ensure that we only do an
+ 'endCatch' when there's a preceding 'beginCatch'. [Bug 1382528] Many
+ thanks to Anton Kovalenko for finding this and pointing out that it was
+ a catch stack handling problem!
+
+2005-12-14 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tclIOUtil.c: workaround gcc warning "comparison is always
+ * generic/tclTest.c: false due to limited range of data type".
+
+ * macosx/Tcl.xcode/project.pbxproj:
+ * macosx/Tcl.xcodeproj/project.pbxproj:
+ * unix/Makefile.in: add new tclTomMath* files.
+
+ * generic/tclBasic.c: replace panic with Tcl_Panic.
+
+2005-12-13 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tcl.decls: Added changes to export an additional stubs
+ * generic/tclBasic.c: table to represent the 'libtommath' routines
+ * generic/tclDecls.h: that Tcl uses and export them to callers.
+ * generic/tclInt.decls: Reran 'genstubs'
+ * generic/tclInt.h:
+ * generic/tclIntDecls.h:
+ * generic/tclIntPlatDecls.h:
+ * generic/tclStubInit.c:
+ * generic/tclStubLib.c:
+ * generic/tclTomMath.decls:
+ * generic/tclTomMath.h:
+ * generic/tclTomMathDecls.h:
+ * generic/tclTomMathInterface.c:
+ * generic/tommath.h:
+ * tools/fix_tommath_h.tcl:
+ * unix/Makefile.in:
+ * win/Makefile.in:
+ * win/makefile.vc:
+
+ * generic/tclClock.c: Made changes to silence a number of compiler
+ * generic/tclIO.c: warnings when building with mingw.
+ * generic/tclIORChan.c:
+ * generic/tclLink.c:
+ * generic/tclListObj.c:
+ * generic/tclObj.c:
+ * generic/tclParseExpr.c:
+ * generic/tclProc.c:
+ * generic/tclTimer.c:
+ * win/tclWinChan.c:
+ * win/tclWinConsole.c:
+ * win/tclWinDde.c:
+ * win/tclWinFCmd.c:
+ * win/tclWinFile.c:
+ * win/tclWinReg.c:
+ * win/tclWinSock.c:
+
+2005-12-13 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * generic/tclExecute.c (TEBC:DICT_FIRST,DICT_DONE): Only decrease the
+ references to the dictionary once the iteration completes. Do this by
+ storing the dict in the iterator context variable. [Bug 1379349] Thanks
+ to Ulrich Ring and Tobias Hippler for finding this.
+
+2005-12-12 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tcl.m4, unix/configure: Fix sh quoting error reported in
+ bash-3.1+ [Bug 1377619] (schafer)
+
+2005-12-12 Kevin B. Kenny <kennykb@acm.org>
+
+ * doc/mathfunc.n: Changed two examples from the incorrect 'tcl::math::'
+ to 'tcl::mathfunc::' [Bug 1378818]
+
+2005-12-09 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/configure: Regen.
+ * win/tcl.m4 (SC_CONFIG_CFLAGS): Define MACHINE for gcc builds. The
+ lack of a definition of this variable in the manifest file was causing
+ a runtime error in wish built with gcc.
+
+2005-12-09 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * tests/lsearch.test (lsearch-10.8..10): If the -start is off the end,
+ * generic/tclCmdIL.c (Tcl_LsearchObjCmd): searching should find nothing
+ at all. [Bug 1374778]
+
+2005-12-08 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/Makefile.in, win/makefile.vc: Add Win x64 and CE build support
+ * win/tcl.m4, win/configure: CE still requires C code fixes.
+
+ * generic/tcl.h: use struct __stat64 (not _stat64) for MSC_VER >= 1400
+ (i.e. latest Platform SDK).
+
+2005-12-07 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * doc/socket.n: Cross-referenced the socket documentation better to the
+ fconfigure documentation on the topic of asynch sockets.
+ * doc/fconfigure.n: Added keyword to documentation of -blocking option
+ so that people looking for "asynch" can find it as well.
+
+2005-12-05 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tclUnixPort.h (Darwin): fix incorrect __DARWIN_UNIX03 configure
+ overrides that were originally copied from Darwin CVS (rdar://3693001)
+
+2005-12-05 Kevin B. Kenny <kennykb@acm.org>
+
+ * tools/tclZIC.tcl: Updated to reflect changes in calling sequence when
+ GetJulianDateFromEraYearMonthDay moved to C.
+ * library/tzdata: Regenerated from Olson's tzdata2005p.tar.gz - the
+ 'systemv' changes appear not to affect Tcl's processing of the dates.
+
+2005-12-05 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/configure.in: move check for fts API to configure.in and run it
+ * unix/tcl.m4: on all platforms, since Linux glibc2 and *BSDs
+ also have this; using fts is more efficient than a recursive
+ opendir/readdir.
+ * unix/tclUnixFCmd.c (TraverseUnixTree): add support to fts code for
+ platforms with stat64.
+ * unix/configure:
+ * unix/tclConfig.h.in: regen.
+
+2005-12-05 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/configure: Use fts file API on Darwin if available.
+ * unix/tcl.m4: Addresses file delete issues in readdir noted
+ * unix/tclUnixFCmd.c: in [Bug 1034337]. (steffen)
+ Remove redundant stat call for each file in DoCopyFile. (steffen)
+
+2005-12-02 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclClock.c: Moved a tiny bit more of [clock format] from run
+ * library/clock.tcl: time to compile time, and fixed a l10n bug in the
+ process. [Bug 1371446]. Also, conditoned the call to SetupTimeZone to
+ speed the common case where TZData($timezone) already exists, and
+ achieved a puny speedup by making ::tcl::clock::getenv not throw
+ errors.
+ * unix/Makefile.in: Made some changes to support a 'make' command that
+ is present on some antiquated versions of Solaris.
+
+2005-12-01 Kevin B. Kenny <kennykb@acm.org>
+
+ * library/clock.tcl: Continued rationalizing the code, eliminating
+ numerous redundant [mc] calls. Added another time boost by precompiling
+ a [::format] command to do the bulk of the work of [clock format].
+
+2005-12-01 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * unix/Makefile.in: Add remaining dependency info. While automated
+ maintenance of this information would be good, having it at all is much
+ better than a poke in the eye with a sharp stick...
+
+2005-12-01 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tclClock.c: fix warning.
+
+ * unix/tcl.m4 (Darwin): fix error when MACOSX_DEPLOYMENT_TARGET unset
+ * unix/configure: regen.
+
+2005-11-30 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * unix/Makefile.in: Add dependency information relating to tclCompile.h
+ since when the list of opcodes changes it is usually useful to rebuild
+ everything that depends on it (but which is nonetheless a small
+ fraction of the total set of Tcl source files).
+
+ ***POTENTIAL INCOMPATIBILITY*** for bytecode savers/loaders. See below
+
+ * generic/tclCompCmds.c (TclCompileSwitchCmd): Arrange for very simple
+ [switch] invokations to be compiled into hash lookups into jump tables;
+ only a very specific kind of [switch] can be safely compiled this way,
+ but that happens to be the most common kind. This makes around 5-10%
+ difference to the speed of execution of clock.test.
+ * generic/tclExecute.c (TEBC:INST_JUMP_TABLE): New instruction to allow
+ for jumps to locations looked up in a hashtable. Requires a new AuxData
+ type, tclJumptableInfoType (supported by the functions DupJumptableInfo
+ and FreeJumptableInfo in tclCompCmds.c) so anything that saves bytecode
+ containing this *must* be updated!
+
+2005-11-30 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tclClock.c: Fixed a bad refcount in previous commit that led
+ to a corrupted heap. Also silenced a warning that some compilers gave
+ about the excessively long constant for JULIAN_SEC_POSIX_EPOCH. Also
+ fixed a bug where [clock format] would fail in the :localtime zone for
+ times before the Posix Epoch. Thanks to Miguel Sofer for pointing out
+ all of these. Also rationalized the code a little bit by moving parts
+ of [clock scan] into C, eliminating some code that was duplicated in
+ the C and Tcl layers.
+
+2005-11-29 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tclBasic.c: Moved a big part of [clock format] down
+ * generic/tclClock.c: to the C level in order to make it go faster.
+ * generic/tclInt.h: Preliminary measurements suggest that it
+ * generic/clock.tcl: more than doubles in speed with this change.
+
+2005-11-29 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * generic/tclCmdIL.c (Tcl_LsearchObjCmd): Allow [lsearch -regexp] to
+ process REs that contain backreferences. This expensive mode of
+ operation is only used if the RE would otherwise cause a compilation
+ failure. [Bug 1366683]
+
+2005-11-28 Kevin Kenny <kennykb@acm.org>
+
+ * tools/tclZIC.tcl (convertTimeOfDay): Corrected a typo that caused
+ wrong DST transitions in any time zone where the transition is
+ specified as local Standard Time (as opposed to wall-clock or UTC).
+ (Also updated the code to be bignum-safe.)
+ * tests/clock.test (clock-51.1): Added regression test for the above.
+ * library/tzdata: Updated to Olson's 'tzdata2005o' (changes for Cuba,
+ Nicaragua, Jordan, and Georgia) and regenerated. Thanks to Paul
+ Mackerras for reporting this problem.
+
+2005-11-27 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tcl.m4 (Darwin): add 64bit support, check for Tiger copyfile(),
+ add CFLAGS to SHLIB_LD to support passing -isysroot in env(CFLAGS) to
+ configure (flag can't be present twice, so can't be in both CFLAGS and
+ LDFLAGS during configure), don't use -prebind when deploying on 10.4,
+ define TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING (rdar://3171542).
+ (SC_ENABLE_LANGINFO, SC_TIME_HANDLER): add/fix caching, fix obsolete
+ autoconf macros. Sync with tk/unix/tcl.m4.
+
+ * unix/configure.in: fix obsolete autoconf macros, sync gratuitous
+ formatting/ordering differences with tk/unix/configure.in.
+
+ * unix/Makefile.in: add CFLAGS to tclsh/tcltest link to make executable
+ linking the same as during configure (needed to avoid losing any linker
+ relevant flags in CFLAGS, in particular flags that cannot be in
+ LDFLAGS). Avoid concurrent linking of tclsh and compiling of
+ tclTestInit.o or xtTestInit.o during parallel make.
+ (checkstubs, checkdoc, checkexports): dependency and Darwin fixes
+ (dist): add new macosx files.
+
+ * unix/tclLoadDyld.c (TclpDlopen): use NSADDIMAGE_OPTION_WITH_SEARCHING
+ on second NSAddImage only. [Bug 1204237]
+ (TclGuessPackageName): should not be MODULE_SCOPE.
+ (TclpLoadMemory): ppc64 and endian (i386) fixes, add support for
+ loading universal (fat) bundles from memory.
+
+ * unix/tclUnixFCmd.c:
+ * macosx/tclMacOSXFCmd.c: ppc64 and endian (i386) fixes.
+ (TclMacOSXCopyFileAttributes): add support for new Tiger copyfile() API
+ to enable copying of xattrs & ACLs by [file copy].
+
+ * generic/tcl.h: add Darwin specifc configure overrides for TCL_WIDE
+ defines to support fat compiles of ppc and ppc64 at the same time,
+ (replaces Darwin CVS fix by emoy, rdar://3693001). add/correct location
+ of version numbers in macosx files.
+
+ * generic/tclInt.h: clarify fat compile comment.
+
+ * unix/tclUnixPort.h: add Darwin specifc configure overrides to support
+ fat compiles, where configure runs only once for multiple architectures
+ (replaces Darwin CVS fix by emoy, rdar://3693001).
+
+ * macosx/tclMacOSXBundle.c:
+ * macosx/tclMacOSXNotify.c:
+ * unix/tclUnixNotfy.c:
+ * unix/tclUnixPort.h: fix #include order to support compile time
+ override of HAVE_COREFOUNDATION in tclUnixPort.h when building for
+ ppc64
+
+ * macosx/Tcl.pbproj/default.pbxuser (new file):
+ * macosx/Tcl.pbproj/jingham.pbxuser:
+ * macosx/Tcl.pbproj/project.pbxproj:
+ * macosx/Tcl.xcode/default.pbxuser (new file):
+ * macosx/Tcl.xcode/project.pbxproj (new file):
+ * macosx/Tcl.xcodeproj/default.pbxuser (new file):
+ * macosx/Tcl.xcodeproj/project.pbxproj (new file): new/updated
+ projects for Xcode 2.2 on 10.4, Xcode 1.5 on 10.3 & ProjectBuilder on
+ 10.2, with native tcltest targets and support for universal (fat)
+ compiles.
+
+ * macosx/README: clarification/cleanup, document new Xcode projects and
+ universal (fat) builds via CFLAGS (i.e. all of ppc ppc64 i386 at once).
+
+ * unix/Makefile.in:
+ * unix/aclocal.m4:
+ * unix/configure.in:
+ * unix/dltest/Makefile.in:
+ * macosx/configure.ac (new file): add support for inclusion of
+ unix/configure.in by macosx/configure.ac, allows generation of a config
+ headers enabled configure script in macosx (required by Xcode
+ projects).
+
+ * macosx/GNUmakefile: rename from Makefile to avoid overwriting by
+ configure run in tcl/macosx, add support for reusing configure cache,
+ build target fixes, remove GENERIC_FLAGS override now handled by
+ tcl.m4.
+
+ * generic/tcl.decls: add Tcl_Main declaration as comment to avoid
+ 'checkstubs' target complaining about it missing from stubs.
+
+ * generic/regex.h:
+ * generic/tclDate.c:
+ * generic/tclEnv.c:
+ * generic/tclGetDate.y:
+ * generic/tclIOUtil.c:
+ * generic/tclObj.c:
+ * generic/tclStubInit.c:
+ * generic/tclStubLib.c:
+ * generic/tclPathObj.c:
+ * generic/tclThreadAlloc.c:
+ * generic/tclThreadStorage.c:
+ * generic/tclTrace.c:
+ * generic/tclVar.c:
+ * generic/tommath.h:
+ * tools/fix_tommath_h.tcl:
+ * unix/tclUnixFCmd.c: ensure externally visible symbols not contained
+ in stubs table are declared as MODULE_SCOPE (or as static if not used
+ outside of own source file). These changes allow 'make checkstubs' to
+ complete without error on Darwin with gcc 4.
+
+ * generic/rege_dfa.c (getvacant):
+ * generic/regexec.c (cfind):
+ * generic/tclCompExpr.c (CompileSubExpr):
+ * generic/tclNamesp.c (NamespaceEnsembleCmd):
+ * unix/tclUnixChan.c (TclUnixWaitForFile): initialise variables to
+ silence gcc 4 warnings.
+
+ * generic/tclExecute.c (TclExecuteByteCode): fix unused variable
+ warning when NO_WIDE_TYPE is defined.
+
+ * generic/regguts.h: only #define NDEBUG if not already #defined.
+
+ * unix/tclUnixNotfy.c:
+ * macosx/tclMacOSXNotify.c: sync whitespace & comments.
+
+ * unix/tclUnixPort.h:
+ * win/tclWinPort.h: remove declaration of obsolete&unused TclpMutex
+ API.
+
+ * unix/configure:
+ * unix/tclConfig.h.in: regen.
+
+2005-11-21 Andreas Kupries <andreask@activestate.com>
+
+ * unix/Makefile.in (install-libraries): Updated Makefile to new
+ * win/Makefile.in (install-libraries): version of the http package.
+ This fixes the ifneeded/provide mismatch reported when trying to
+ require http. Should we maybe try to automatically extract the version
+ number from the http code to prevent future breakage ?
+
+ This follows the update of the version number by dgp on Nov 15 (No
+ entry found in the ChangeLog).
+
+2005-11-20 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/tclStubLib.c: Don't set tclStubsPtr to 0 when
+ Tcl_PkgRequireEx() fails [Fix for [Bug 1091431] "Tcl_InitStubs failure
+ crashes wish"]
+
+2005-11-18 Miguel Sofer <msofer@users.sf.net>
+
+ * tests/trace.test (trace-34.5): [Bug 1047286], added a second test
+ illustrating the role of "ns in callStack" in the ns's visibility
+ during deletion traces.
+
+2005-11-18 Kevin B. Kenny <kennykb@acm.org>
+
+ * doc/clock.n: Restored several missing lines near the %w format group
+ so that %w and %W are documented with their actual behaviour. [Bug
+ 1359183]
+
+2005-11-18 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclIO.c (TclFinalizeIOSubsystem): preserve statePtr until we
+ retrieve the next statePtr from it.
+
+2005-11-18 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclObj.c (GetBignumFromObj): replace NULL with
+ tclEmptyStringRep to stop memcpy from complaining in a debug build
+ (the corresponding branch is eliminated by the optimiser otherwise).
+
+2005-11-18 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tclIO.c (TclFinalizeIOSubsystem): Applied Pat Thoyts' patch
+ for [Bug 1359094]. This moves the retrieval of the next channel state
+ to the end of the loop, as the called closeproc may close other
+ channels, i.e. modify the list we are iterating, invalidating any
+ pointer retrieved earlier.
+
+2005-11-18 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclListObj.c: Restored the SetListFromAny routine to the
+ * generic/tclObj.c: "list" Tcl_ObjType, and restored the
+ Tcl_RegisterObjType() call for "list". This addresses the needs of some
+ "bridge" extensions to examine whether the Tcl_ObjType of a Tcl_Obj is
+ that of the "list" Tcl_ObjType.
+
+2005-11-18 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * library/http/http.tcl (http::geturl): Improved syntactic validation
+ of URLs, and better error messages in some cases. [Bug 1358369]
+
+2005-11-17 Miguel Sofer <msofer@users.sf.net>
+
+ * tests/namespace.test: fix comment
+
+2005-11-14 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclStrToD.c: More data in the "can't happen" Tcl_Panic to
+ aid debugging.
+
+ * generic/tclBasic.c (CallCommandTraces): Save/restore the interp
+ result during traces to fix [Bug 1355342].
+
+2005-11-13 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclInt.h:
+ * generic/tclNamesp.c:
+ * tests/namespace.test: fix for [Bug 1354540] and [Bug 1355942]. The
+ new tests 7.3-6 and the modified 51.13 fail due to the unrelated [Bug
+ 1355342]
+
+ * tests/trace.test: added tests 20.13-16 for [Bug 1355342]
+
+2005-11-12 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclBasic.c (Tcl_DeleteCommandFromToken):
+ * generic/tclObj.c (Tcl_GetCommandFromObj): more partial fixes for
+ [Bug 1354540] - making sure that cached references to a command being
+ deleted cannot be made reusable by a delete trace.
+
+2005-11-12 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclNamesp.c (Tcl_FindCommand): Do not find commands in dead
+ namespaces on the path. Partial fix for [Bug 1354540].
+
+2005-11-11 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclInt.h: Revised TclParseNumber interface to enable
+ * generic/tclScan.c: revision to the [scan] command implementation
+ * generic/tclStrToD.c: to permit tests scan-4.44,55 to pass again.
+ [Bug 1348067].
+
+2005-11-11 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclBasic.c (Tcl_DeleteCommandFromToken):
+ * generic/tclObj.c (Tcl_GetCommandFromObj): bump the cmd epoch early
+ to insure that cached references to this command are invalidated.
+ Partial fix for [Bug 1352734] - at least insures that namespace-51.13
+ does not cause a panic. The test is still marked as knownbug, pending
+ resolution of what is actually the correct return value ([Bug
+ 1354540])
+
+2005-11-09 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclTimer.c: Changed [after] so that it behaves correctly
+ * tests/timer.test: with negative arguments [Bug 1350293] and
+ arguments that overflow a 32-bit word. [Bug 1350291]
+
+2005-11-08 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/compile.test: Updated tests with changed behavior
+ * tests/execute.test: due to addition of bignums.
+ * tests/expr-old.test:
+ * tests/expr.test:
+ * tests/parseExpr.test:
+ * tests/platform.test:
+ * tests/string.test:
+
+2005-11-08 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tclUnixFCmd.c (MAX_READDIR_UNLINK_THRESHOLD): reduce to 130
+ based on errors seen on OS X 10.3 with lots of links in a dir.
+ [Bug 1034337 followup]
+
+2005-11-09 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * unix/Makefile.in (gdb-test): Added a new target to make it easier to
+ run the test suite inside a debugger.
+
+2005-11-08 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/compExpr-old.test: Updated tests with changed behavior due
+ to addition of bignums.
+
+ * tests/expr.test: Portable tests expr-46.13-18 [Bug 1341368]
+
+ * generic/tclPkg.c: Corrected inconsistencies in the value returned
+ * tests/pkg.test: by Tcl_PkgRequire(Ex) so that the returned
+ values will always agree with what is stored in the package database.
+ This way repeated calls to Tcl_PkgRequire(Ex) have the same results.
+ Thanks to Hemang Lavana. [Bug 1162286].
+
+2005-11-08 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * generic/tclTrace.c (TraceVarEx): Factor out heart of Tcl_TraceVar2
+ (TclTraceVariableObjCmd,TraceVarProc): Use the new internal API to
+ arrange for the clientData to be cleaned up at the same time as the
+ rest of the main trace record. This simplifies the code a bit at the
+ same time.
+
+2005-11-07 Miguel Sofer <msofer@users.sf.net>
+
+ * tests/trace.test (trace-13.2-4): added tests to detect leak, see [Bug
+ 1348775]. The recently added trace-8.9 test is now 13.4.
+
+2005-11-07 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * tests/dict.test (dict-19.2): arrange for the stress testing code to
+ only stress test the dict code and not the trace code as well. [Bug
+ 1342858]
+
+2005-11-05 Miguel Sofer <msofer@users.sf.net>
+
+ * tests/trace.test (trace-8.9): added test to detect leak, see [Bug
+ 1348775].
+
+2005-11-04 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tclWinPort.h: Applied [Patch 1267871] by Matt Newman for
+ * win/tclWinPipe.c: extended error code support on Windows.
+ * tests/exec.test: Tests for extended error codes.
+ * generic/tclPipe.c: Permit long codes (platform macros permitting).
+
+2005-11-04 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclBinary.c:
+ * generic/tclCmdAH.c:
+ * generic/tclCmdIL.c:
+ * generic/tclCmdMZ.c:
+ * generic/tclDictObj.c:
+ * generic/tclExecute.c:
+ * generic/tclIOCmd.c:
+ * generic/tclLink.c:
+ * generic/tclTest.c:
+ * generic/tclVar.c: fix for [Bug 1334947]. The functions TclPtrSetVar,
+ Tcl_ObjSetVar2 and Tcl_SetVar2Ex now always consume the newValuePtr
+ argument - i.e., they will free a 0-refCount object if they failed to
+ set the variable. Fixed all callers in the core.
+
+2005-11-04 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tclGetDate.y: Added abbreviations for the Korean
+ * library/clock.tcl: timezone. [Patch 1298737]
+ * generic/tclDate.c: Regenerated.
+
+ * tools/findBadExternals.tcl: Added this script, which locates external
+ symbols that do not begin with 'Tcl' or 'tcl' and hence might be in
+ conflict with other link libraries. Thanks to George Peter Staplin for
+ the idea and the initial version of the script. [Bug 1263012]
+
+ * unix/Makefile.in: Trimmed a bunch of fat out of the tommath/
+ directory in 'make dist'. [RFE 1333318]
+
+ * unix/tcl.m4: Added code to enable [load] on LynxOS. Thanks to
+ heidibr@users.sf.net for the patch. [Bug 1163896]. Removed the last
+ vestiges of GNU dld from the Unix build [RFE 1071992].
+
+ * unix/tclLoadDld.c: Removed.
+ * unix/configure: Regenerated.
+
+2005-11-04 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclInt.h:
+ * generic/tclNamesp.c:
+ * generic/tclVar.c:
+ * tests/trace.test: fix for [Bugs 1338280/1337229]; changed to use the
+ same approach as the 8.4 patch in the ticket (i.e., removed the patch
+ committed on 2005-31-10).
+
+2005-11-03 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * win/tclWin32Dll.c: Applied [Patch 1256872] to provide unicode
+ * win/tclWinConsole.c: support in the console on suitable systems.
+ * win/tclWinInt.h: Patch by Anton Kovalenko
+
+2005-11-02 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ Applied [Patch 1096916] to support building with MSVC 8.
+ * generic/regerror.c: Avoid use of reserved word.
+ * generic/tcl.h: Select the right Tcl_Stat structure
+ * generic/tclDate.c: Casts to handle 64 bit time_t case.
+ * tests/env.test: Include essential envvar on Win32
+ * win/nmakehlp.c: Handle new return codes.
+ * win/makefile.vc: Use the selected options.
+ * win/rules.vc: Check options are applicable
+ * win/tclWinPort.h: Disable deprecated function warnings
+ * win/tclWinSock.c: Provide default value to avoid warning.
+ * win/tclWinTime.c: Add casts to handle 64bit time_t type.
+
+2005-11-01 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclTrace.c (TclCheckExecutionTraces): Corrected mistaken
+ assumption that all command traces are set at the script level.
+ Report/fix from Jacques H. de Villiers. [Bug 1337941]
+
+ * tests/unixNotfy.test (1.1,2): Update error message whitespace to
+ match changes in code.
+
+ * tests/expr-old.test (expr-32.52): Use int(.) to restrict result of
+ left shift to the C long range.
+
+ * expr.test (expr-46.13): Added test that illustrates shortcoming of
+ [Patch 1340260].
+
+2005-10-31 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclNamesp.c: fix for [Bugs 1338280/1337229]. Thanks Don.
+ * tests/trace.test: fix duplicate test numbers
+
+2005-10-31 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * win/tclWinSerial.c (SerialSetOptionProc): Cleaned up option parsing
+ to produce more informative error messages and separate error and
+ non-error code paths better.
+ * tests/ioCmd.test (iocmd-8-19): Updated.
+
+2005-10-29 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclTrace.c (TraceVarProc): [Bug 1337229], partial fix. Ensure
+ that a second call with TCL_TRACE_DESTROYED does not lead to a second
+ call to Tcl_EventuallyFree(). It is still true that that second call
+ should not happen, so the bug is not completely fixed.
+ * tests/trace.test (test-18.3-4): added tests for [Bug 1337229] and
+ [Bug 1338280].
+
+2005-10-23 Vince Darley <vincentdarley@sourceforge.net>
+
+ * generic/tclFileName.c: fix to memory leak in glob [Bug 1335006] Obj
+ leak detection and patch by Eric Melbardis.
+
+ * tests/fCmd.test:
+ * win/tclWinFile.c: where appropriate windows API is available, try to
+ set 'nlink' and 'ino' stat fields (previously they were always 0). [Bug
+ 1325803]
+
+2005-10-22 Miguel Sofer <msofer@users.sf.net>
+
+ * tests/foreach.test (foreach-8.1): added test for [Bug 1189274]
+
+2005-10-22 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c (INST_INCR_*): fixed [Bug 1334570]. Obj leak
+ detection and patch by Eric Melbardis.
+
+2005-10-21 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclStrToD.c (RefineApproximation): Plugged a memory leak
+ where two intermediate results were not freed on one return path. [Bug
+ 1334461]. Thanks to Eric Melbardis for the patch.
+
+2005-10-21 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/binary.n: Clarify that virtually all code that uses the 'h'
+ format in [binary scan] should be using the 'H' format instead. It is
+ nearly always a bug to use the other!
+
+2005-10-20 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclListObj.c (TclLsetFlat):
+ * tests/lset.test (lset-10.3): fixed handling of unshared lists with
+ shared sublists, [Bug 1333036] reported by neuronstorm.
+
+2005-10-19 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclIORChan.c (PassReceivedError,PassReceivedErrorInterp):
+ Fix crash caused by passing -1 as the length to TclNewStringObj(). Only
+ Tcl_NewStringObj (the function call, not the macro) handles that sort
+ of thing correctly. This makes ioCmd.test pass again.
+
+2005-10-19 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclClock.c: Removed some dead code.
+ * generic/tclCmdIL.c:
+ * generic/tclCompCmds.c:
+ * generic/tclDictObj.c:
+ * generic/tclExecute.c:
+ * generic/tclLiteral.c:
+ * generic/tclParseExpr.c:
+ * generic/tclScan.c:
+ * generic/tclUtil.c:
+ * generic/tclVar.c:
+
+2005-10-19 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * generic/tclIORChan.c: General cleanup, removing checks that are
+ unnecessary due to the general contracts of other functions in the
+ core, converting to using ANSI declarations, etc. Note that nearly the
+ whole file has changed, but it is often just cosmetic.
+
+2005-10-19 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c (INST_DICT_APPEND, INST_DICT_LAPPEND): fixed
+ faulty peephole optimisation that can cause crashes, [Bug 1331475]
+ reported by Aric Bills.
+
+2005-10-18 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclExecute.c: Added optimization for I32L64 systems to avoid
+ using bignums to perform int multiplies. The improvement shows up most
+ dramatically in tclbench's matrix.bench.
+
+2005-10-15 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclExecute.c: Restored some optimizations of the
+ INST_INCR_SCALAR1_IMM opcode.
+
+2005-10-14 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+
+ * generic/tclIO.c (Tcl_ClearChannelHandlers): removed change dated
+ 2005-10-04 (see below). Look into [Bug 1323992] for detailed
+ discussion.
+
+ * generic/tcl.h: Fixed bad definition of CRTEXPORT which should have
+ been CRTIMPORT rather. This broke compilation of generic/tclMain.c and
+ was probably introduced by mistake while applying the fix for [Bug
+ 1256937] below.
+
+2005-10-14 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tclExecute.c (TclIncrObj, TclExecuteByteCode): Tidied up a
+ couple of infelicitous do {...} while(0) constructs.
+
+2005-10-14 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * generic/tcl.h: Fix for [Bug 1256937] - correctly decorate
+ * generic/tclMain.c: imported functions from msvcrt in static builds.
+
+2005-10-13 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/format.test: "Forward"-port of test updates relating to [Bug
+ 1284178]. The bug itself was fixed by TIP#237.
+
+2005-10-13 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+
+ * generic/tclIO.c (Tcl_ClearChannelHandlers): temporary ifdef
+ TCL_THREADS changes done to de-activate pending event processing when
+ channel is being closed/cutted.
+
+2005-10-13 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclExecute.c: Removed obsolete use of NO_ERRNO_H.
+ * tools/man2tcl.c:
+ * unix/tcl.m4:
+ * unix/tclConfig.h.in:
+ * win/configure.in:
+
+ * unix/configure: autoconf-2.59
+ * win/configure:
+
+ * compat/tclErrno.h: Removed obsolete file.
+
+ * generic/tclStrToD.c (TclParseNumber): Missing goto caused crash when
+ parsing "Na". [Bug 1325833]
+
+2005-10-12 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclExecute.c (GetNumberFromObj): Restored some lost
+ optimizations for empty string values. We avoid cost of a call to
+ TclParseNumber just to tell us an empty string isn't a number.
+
+2005-10-12 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclPathObj.c (SetFsPathFromAny): TclGetString macro must not
+ be combined with post-increment arguments. [Bug 1325099]
+
+2005-10-12 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tclExecute.c (Tcl_ExecuteByteCode, TclIncrObj): Several
+ common cases inlined in hopes of gaining a little performance in [incr]
+
+2005-10-10 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompCmds.c: New convenience macro CompileTokens().
+
+2005-10-10 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclExecute.c: Corrections to the NO_WIDE_TYPE build. Also
+ added missing "break" to a switch that broke wide XOR operations.
+
+2005-10-10 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclInterp.c (DeleteScriptLimitCallback)
+ (SetScriptLimitCallback): Improve the interlocking between the script
+ limit callback record and the hash table of current such records, to
+ prevent crashes in callbacks that create callbacks.
+ (Tcl_LimitSetTime): Reset the correct flag. Problem reported by
+ Nicolas Castagne <castagne@imag.fr> on comp.lang.tcl
+
+2005-10-10 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c: Fixing errors in last commit. (Two commits, the
+ second removes wrong comment).
+
+2005-10-09 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclBasic.c:
+ * generic/tclExecute.c:
+ * generic/tclStrToD.c:
+ * generic/tclStringObj.c: Initialise variables to avoid compiler
+ warnings ([Bug 1320818] among others).
+
+2005-10-08 Don Porter <dgp@users.sourceforge.net>
+
+ TIP#237 IMPLEMENTATION
+
+ [kennykb-numerics-branch] Resynchronized with the HEAD; at this
+ checkpoint [-rkennykb-numerics-branch-20051008], the HEAD and
+ kennykb-numerics-branch contain identical code.
+
+ [kennykb-numerics-branch] Merge updates from HEAD
+
+ * generic/tclExecute.c: More performance macros and special handling of
+ the wide integer type for performance on 32-bit systems.
+
+2005-10-07 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclExecute.c: Macro GetNumberFromObj() is version of
+ TclGetNumberFromObj() that saves a function call for common uses.
+
+ * generic/tclInt.h: Made #undef NO_WIDE_TYPE the default on 32-bit
+ systems. Being able to use 64-bit values without leaping to mp_int
+ should help with performance.
+
+ * generic/tclObj.c: Bug fixes in the #undef NO_WIDE_TYPE
+ * generic/tclExecute.c: configuration.
+
+ * generic/tclExecute.c: Improved performance of comparison opcodes and
+ bitwise operations and removed yet more dead code.
+
+2005-10-07 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tclUnixFCmd.c (TraverseUnixTree): Adjust 2004-11-11 change to
+ * tests/fCmd.test (fCmd-20.2): account for NFS special files
+ with a readdir rewind threshold. [Bug 1034337]
+
+2005-10-06 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclExecute.c: Improved performance of INST_RSHIFT and
+ INST_LSHIFT.
+
+2005-10-05 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclExecute.c: Improved performance of INST_MULT, INST_DIV,
+ INST_ADD, and INST_SUB and replaced a "goto... label" with a "break
+ from loop" in TclIncrObj() and removed some dead code.
+
+2005-10-05 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tclPipe.c (TclCreatePipeline): Fixed [Bug 1109294]. Applied
+ the patch provided by David Gravereaux.
+
+ * doc/CrtChannel.3: Fixed [Bug 1104682], by application of David
+ Welton's patch for it, and added a note about wideSeekProc.
+
+ * generic/tclIORChan.c (RcClose): Removed unreachable panic/return
+ statements. This fixes the remainder of [Bug 1286256].
+
+2005-10-05 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * tests/env.test (env-6.1):
+ * win/tclWinPort.h: define USE_PUTENV_FOR_UNSET 1
+ * generic/tclEnv.c (TclSetEnv, TclUnsetEnv): add USE_PUTENV_FOR_UNSET
+ to existing USE_PUTENV define to account for various systems that have
+ putenv(), but can't unset env vars with it. Note difference between
+ Windows and Linux for actually unsetting the env var (use of '=').
+ Correct the resizing of the environ array. We assume that we are in
+ full ownership, but that's not correct.[Bug 979640]
+
+2005-10-04 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+ * generic/tclExecute.c: Updated TclIncrObj() to more efficiently add
+ native long integers. Also updated IllegalExprOperandType and the
+ INST_UMINUS, INST_UPLUS, INST_BITNOT, and INST_TRY_CVT_TO_NUMERIC
+ sections for performance.
+
+ * generic/tclBasic.c: Updated more callers to make use of
+ TclGetNumberFromObj. Removed some dead code.
+
+2005-10-04 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tclWinSerial.c (SerialSetOptionProc): free argv [Bug 1067708]
+
+ * tests/http.test: do not URI encode -._~ according
+ * library/http/http.tcl (init): to RFC3986. [Bug 1182373] (aho)
+
+ * unix/tclLoadShl.c (TclpDlopen): use DYNAMIC_PATH on second shl_load
+ only. [Bug 1204237]
+
+ * doc/scan.n: scan %[] requires "one or more chars" [Bug 1277503]
+
+ * tests/winFile.test (getuser): allow valid Windows usernames. [Bug
+ 1311285]
+
+ * generic/tclParse.c (Tcl_ParseCommand): add code that recognizes {} in
+ addition to {expand} for word expansion (make with
+ -DALLOW_EMPTY_EXPAND).
+
+2005-10-04 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+
+ * generic/tclIO.c (Tcl_ClearChannelHandlers): now deletes any
+ outstanding timer for the channel. Also, prevents events still in the
+ event queue from triggering on the current channel.
+
+ * generic/tclTimer.c (Tcl_DeleteTimerHandler): bail out early if passed
+ NULL argument.
+
+2005-10-03 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclBasic.c: Re-implemented ExprRoundFunc and
+ ExprEntierFunc to use TclGetNumberFromObj.
+
+ * generic/tclInt.h: Added new routine TclGetNumberFromObj to
+ * generic/tclObj.c: provide efficient access to the actual
+ internal rep of a numeric Tcl_Obj without conversions.
+
+2005-10-03 Kevin Kenny <kennykb@acm.org>
+
+ * tools/loadICU.tcl: Changed the file names of message catalogs to
+ lowercase.
+ * tools/makeTestCases.tcl:
+ * library/tzdata/*: Olson's tzdata2005n.tar.gz. Includes new DST
+ rules for USA and a number of changes to other locales.
+ * tests/clock.test: Regenerated for new US DST rules.
+
+2005-09-30 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclMain.c: Separate encoding conversion of command line
+ arguments from list formatting. [Bug 1306162].
+
+2005-09-30 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclStringObj.c: Bug fix: Missing cast to large enough
+ integral size before << operations led to broken [format %llx] results.
+ Thanks to Robert Henry for reporting the bug.
+
+2005-09-29 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/mathfunc.n: implementation for TIP #255, expr min/max
+ * library/init.tcl:
+ * tests/info.test, tests/expr-old.test:
+
+2005-09-27 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tcl.h: Changed name of the new Tcl_Obj intrep field
+ * generic/tclObj.c: from "bignumValue" to "ptrAndLongRep" as
+ * generic/tclProc.c: described in TIP 237, and more suitable for
+ other more general uses.
+
+2005-09-27 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * tests/binary.test (binary-14.18): Added test for [Bug 1116542] though
+ the bug itself was already fixed by unrelated changes.
+
+2005-09-26 Kevin Kenny <kennykb@acm.org>
+
+ [kennykb-numerics-branch] Merge updates from HEAD.
+
+2005-09-26 Kevin Kenny <kennykb@acm.org>
+
+ * libtommath/: Updated to release 0.36.
+ * generic/tommath.h: Regenerated.
+ * generic/tclTomMathInterface.h: Added ten missing aliases for mp_*
+ functions to avoid namespace pollution in Tcl's exported symbols. [Bug
+ 1263012]
+
+2005-09-23 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * unix/Makefile.in: Added -DMP_PREC=4 switch to all compiles so
+ * win/Makefile.in: that minimum memory requirements of mp_int's
+ * win/makefile.vc: will not be quite so large. [Bug 1299153].
+
+ * generic/tclStrToD.c: Fixed memory leak. [Bug 1299803].
+ * generic/tclObj.c:
+
+2005-09-20 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclExecute.c: Revise TclIncrObj() to call
+ Tcl_GetBignumAndClearObj.
+
+ * generic/tcl.decls: Add Tcl_GetBignumAndClearObj.
+ * generic/tclObj.c:
+
+ * generic/tclDecls.h: make genstubs
+ * generic/tclStubInit.c:
+
+2005-09-16 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclInt.h: Added TclBNInitBigNumFromWideInt() so
+ * generic/tclTomMathInterface.c: that every caller isn't required to
+ duplicate the sign logic to use the unsigned interface.
+
+ * generic/tclBasic.c: Reduce the number of places where Tcl intrudes
+ * generic/tclExecute.c: into the internal format details of the mp_int
+ * generic/tclObj.c: struct.
+ * generic/tclStrToD.c:
+ * generic/tcLStringObj.c:
+
+ * generic/tclTomMath.h: Added mp_cmp_d to routines from libtommath
+ * unix/Makefile.in: used by Tcl.
+ * win/Makefile.in:
+ * win/makefile.vc:
+
+ * libtommath/bn_mp_add_d.c: Bug fix. For mp_add_d(&a, d, &c), when &a
+ has the value -d, then the value &c computed should be zero, but
+ mp_add_d was producing an inconsistent zero value with a sign field of
+ MP_NEG, something like a value of -0, which other routines in
+ libtommath can't handle.
+
+ * generic/tclExecute.c: Dropped all creation of "bigOne" values and
+ just use tommath routines that accept the value "1" directly.
+
+2005-09-15 Miguel Sofer <msofer@users.sf.net>
+
+ * doc/ParseCmd.3: copy/paste fix [Bug 1292427]
+
+2005-09-15 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch] Merge updates from HEAD.
+
+ * generic/tclStringObj.c (TclAppendFormattedObjs): Revision to
+ eliminate one round of string copying.
+
+ * generic/tclBasic.c: More callers of TclObjPrintf and
+ * generic/tclCkalloc.c: TclFormatToErrorInfo.
+ * generic/tclCmdMZ.c:
+ * generic/tclExecute.c:
+ * generic/tclIORChan.c:
+ * generic/tclMain.c:
+ * generic/tclProc.c:
+ * generic/tclTimer.c:
+ * generic/tclUtil.c:
+ * unix/tclUnixFCmd.c
+
+ * unix/configure: autoconf-2.59
+
+2005-09-15 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * unix/tcl.m4 (SC_TCL_EARLY_FLAGS): Added extra hack to allow Tcl to
+ transparently open large files on RHEL 3. [Bug 1287638]
+
+2005-09-14 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclStringObj.c: Bug fixes: ObjPrintfVA needed to
+ support "*" fields and needed to interpret precision limits on %s
+ conversions as a maximum number of bytes, not Tcl_UniChars, to take
+ from the (char *) argument.
+
+ * generic/tclBasic.c: Updated several callers to use
+ * generic/tclCkalloc.c: TclFormatToErrorInfo() and/or
+ * generic/tclCmdAH.c: TclObjPrintf().
+ * generic/tclCmdIL.c:
+ * generic/tclCmdMZ.c:
+ * generic/tclDictObj.c:
+ * generic/tclExecute.c:
+ * generic/tclIORChan.c:
+ * generic/tclIOUtil.c:
+ * generic/tclNamesp.c:
+ * generic/tclProc.c:
+
+ * library/init.tcl: Keep [unknown] in sync with errorInfo
+ formatting rules.
+
+2005-09-13 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c: First caller of TclFormatToErrorInfo.
+
+ * generic/tclInt.h: Using stdarg.h conventions, add more
+ * generic/tclStringObj.c: fixed arguments to TclFormatObj() and
+ TclObjPrintf(). Added new routine TclFormatToErrorInfo().
+
+ * generic/tcl.h: Explicitly standardized on the use of stdarg.h
+ * generic/tclBasic.c: conventions for functions with variable number
+ * generic/tclInt.h: of arguments. Support for varargs.h has been
+ * generic/tclPanic.c: implicitly gone for some time now. All
+ * generic/tclResult.c: TCL_VARARGS* macros purged from Tcl sources,
+ * generic/tclStringObj.c: leaving only some deprecated #define's
+ * tools/genStubs.tcl: in tcl.h for the sake of older extensions.
+
+ * generic/tclDecls.h: make genstubs
+
+ * doc/AddErrInfo.3: Replaced all documented requirement for use of
+ * doc/Eval.3: TCL_VARARGS_START() with requirement for use of
+ * doc/Panic.3: va_start().
+ * doc/SetResult.3:
+ * doc/StringObj.3:
+
+2005-09-12 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch] Merge updates from HEAD.
+
+ * generic/tclCmdAH.c: Added support for the "ll" width
+ * generic/tclStringObj.c: specifier to [format].
+
+ * generic/tclStringObj.c (TclAppendFormattedObjs): Bug fix: make
+ sure %ld formats force the collection of a wide value, when the value
+ could be a different long.
+
+2005-09-09 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tclIORChan.c (RcDecodeEventMask): Added missing type
+ declaration for the parameter 'mask'. This fixes the [Bug 1286256]. The
+ other warning can be removed only by removing the panic/return code.
+
+2005-09-09 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch] Merge updates from HEAD.
+
+2005-09-09 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tclStringObj.c: Added two missing casts to silence messages
+ from MSVC6.
+
+2005-09-09 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclInt.h: New internal routine TclObjPrintf()
+ * generic/tclStringObj.c: is similar to TclFormatObj() but
+ accepts arguments in non-Tcl_Obj format.
+
+ * generic/tclInt.h: New internal routines TclFormatObj()
+ * generic/tclStringObj.c: and TclAppendFormattedObjs() to offer
+ sprintf()-like means to append to Tcl_Obj. Work in progress toward
+ [RFE 572392].
+
+ * generic/tclCmdAH.c: Compiler directive NEW_FORMAT when #define'd
+ directs the [format] command to be implemented in terms of the new
+ TclAppendFormattedObjs() routine.
+
+2005-09-08 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ TIP#254 IMPLEMENTATION
+
+ * generic/tclLink.c (LinkTraceProc,ObjValue): Added many new of C var
+ * generic/tcl.h: to link to, making it
+ * doc/LinkVar.3: easier to seamlessly
+ * generic/tclTest.c (TestlinkCmd): couple C code and Tcl
+ * tests/link.test: scripts in an
+ application. [Patch 1242844]
+
+2005-09-07 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclUtf.c (Tcl_UniCharToUtf): Corrected handling of negative
+ * tests/utf.test (utf-1.5): Tcl_UniChar input value. Incorrect
+ handling was producing byte sequences outside of Tcl's legal internal
+ encoding. [Bug 1283976].
+
+2005-09-06 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclInt.h (List): Added flag to keep track of whether a list
+ * generic/tclListObj.c: with a string rep is provably canonical.
+ * generic/tclUtil.c (Tcl_ConcatObj): Do efficient concatenation and
+ * generic/tclBasic.c (Tcl_EvalObjEx): evaluation when the list is
+ canonical, and not just when the list is pure. This should make the
+ "pure list" hacking introduced in 8.3 much more robust.
+
+2005-09-05 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclObj.c (pendingObjDataKey): Added missing 'static' to stop
+ symbol from leaking outside the Tcl library. [Bug 1263012]
+
+2005-09-02 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclScan.c: Bug fix: The %o, %x, %i formats of [scan] must
+ not accept any 0b or 0o prefixes. [scan $s %o] must continue to work
+ even with KILL_OCTAL enabled.
+
+ * generic/tclInt.h: Added TCL_PARSE_SCAN_PREFIXES to the flags
+ * generic/tclStrToD.c: accepted by TclParseNumber.
+
+2005-09-01 Andreas Kupries <andreask@activestate.com>
+
+ * unix/tclUnixSock.c (InitializeHostName): Synchronized use of static
+ modifier in declaration and definition of function.
+
+ * unix/tclUnixChan.c (FileTruncateProc): Synchronized use of static
+ modifier in declaration and definition of function.
+
+ * generic/tclResult.c (ReleaseKeys): Synchronized use of static
+ modifier in declaration and definition of function.
+
+ * generic/tclListObj.c (NewListIntRep): Synchronized use of static
+ modifier in declaration and definition of function.
+
+ * generic/tclEncoding.c (InitializeEncodingSearchPath): Synchronized
+ use of static modifier in declaration and definition of function.
+
+ * generic/tclEncoding.c (FillEncodingFileMap): Synchronized use of
+ static modifier in declaration and definition of function.
+
+ * generic/tclIORChan.c (RcNewHandle): Synchronized use of static
+ modifier in declaration and definition of function.
+
+2005-09-01 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclObj.c: TclParseNumber calls meant to parse an integer
+ value now pass the TCL_PARSE_INTEGER_ONLY flag.
+
+ * generic/tclScan.c: Extended [scan] to accept the %lld, %llo, %llx,
+ and %lli formats. Numeric scanning is now done via TclParseNumber calls
+
+ * generic/tclInt.h: Extended TclParseNumber to accept new flag
+ * generic/tclStrToD.c: values TCL_PARSE_INTEGER_ONLY,
+ TCL_PARSE_OCTAL_ONLY, and TCL_PARSE_HEXIDECIMAL_ONLY, to give caller
+ more control over the parsing rules.
+
+2005-08-31 Vince Darley <vincentdarley@sourceforge.net>
+
+ * doc/FileSystem.3:
+ * unix/tclUnixFile.c:
+ * windows/tclWinFile.c: clarify that Tcl_FSMatchInDirectory may be
+ called with a NULL interpreter, and fix the code so this is allowed.
+ Tcl's core itself (tclEncoding.c:FillEncodingFileMap()) calls this
+ with a NULL interpreter.
+
+2005-08-30 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclObj.c: Extended bignum support to include bignums so
+ large they will not pack into a Tcl_Obj. When they outgrow Tcl's string
+ rep length limits, a panic will result.
+
+ * generic/tclTomMath.h: Added mp_sqrt to routines from
+ * unix/Makefile.in: libtommath used by Tcl.
+ * win/Makefile.in:
+ * win/makefile.vc:
+
+ * generic/tclBasic.c: Extended sqrt(.) so that range covers the
+ entire double range, accepting as many bignums in the domain as that
+ will allow.
+
+2005-08-29 Andreas Kupries <andreask@activestate.com>
+
+ * library/tm.tcl (::tcl::tm::roots): Accepted Don Porter's patch for
+ [Bug 1189657]. Syncs the implementation to the specification (TIP #189)
+
+2005-08-29 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch] Merge updates from HEAD.
+
+ * generic/tclBasic.c: Restored round(.) to the Tcl 8.4 rules.
+
+2005-08-29 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tclBasic.c (ExprMathFunc): Restored "round away from zero"
+ * tests/expr.test (expr-46.*): behaviour to the "round" function.
+ Added test cases for the behavior, including the awkward case of a
+ number whose fractional part is 1/2-1/2ulp. [Bug 1275043]
+
+2005-08-26 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tclIO.c: Moved Tcl_{Cut,Splice}Channel to
+ {Cut,Splice}Channel for internal use, and created new public functions
+ for Tcl_{Cut,Splice}Channel which walk the whole stack of
+ transformations and invoke the necessary thread actions. Added code to
+ Tcl_(Un)StackChannel to properly invoke the thread actions when pushing
+ and popping transformations on/from a channel.
+
+2005-08-26 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclNamesp.c (NamespaceEnsembleCmd): Reset the result after
+ creating an ensemble to clear any result object sharing (potentially
+ caused by delete traces) so that we can safely return the name of the
+ ensemble. Previously, this caused crashes in Snit's test suite.
+
+2005-08-25 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclListObj.c (UpdateStringOfList): Stop uncontrolled and
+ unsafe crashes from happening when working with very large string
+ representations. [Bug 1267380]
+
+ * generic/tclExecute.c (TEBC:INST_DICT_LAPPEND): Stop dropping a
+ duplicated object on the floor, which was a memory leak (and a wrong
+ result too). Thanks to Andreas Kupries for reporting this.
+
+2005-08-25 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch] Merge updates from HEAD
+
+ * generic/tclExecute.c: Bug fix. INST_RSHIFT: shift of negative values
+ produced incorrect results.
+
+ * generic/tclExecute.c: Bug fix. INST_*SHIFT opcodes stack management.
+ [expr 0<<6] should be 0, not 6.
+
+ * generic/tclBasic.c: Extended the domain of round(.) to all non-Inf,
+ non-NaN doubles, using bignums for the result as needed.
+
+2005-08-24 Andreas Kupries <andreask@activestate.com>
+
+ TIP#219 IMPLEMENTATION
+
+ * doc/SetChanErr.3: ** New File **. Documentation of the new channel
+ API functions.
+ * generic/tcl.decls: Stub declarations of the new channel API.
+ * generic/tclDecls.h: Regenerated
+ * generic/tclStubInit.c:
+
+ * tclIORChan.c: ** New File **. Implementation of the reflected
+ channel.
+ * generic/tclInt.h: Integration of reflected channel and new error
+ * generic/tclIO.c: propagation into the generic I/O core.
+ * generic/tclIOCmd.c:
+ * generic/tclIO.h:
+ * library/init.tcl:
+
+ * tests/io.test: Extended testsuite.
+ * tests/ioCmd.test:
+ * tests/chan.test:
+ * generic/tclTest.c:
+ * generic/tclThreadTest.c:
+
+ * unix/Makefile.in: Integration into the build machinery.
+ * win/Makefile.in:
+ * win/Makefile.vc:
+
+2005-08-24 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tclStrToD.c (Tcl_DoubleDigits): Fixed the corner cases of
+ * tests/binary.test (binary-65.*) formatting floating point
+ numbers with the largest and smallest possible significands, and added
+ test cases for them.
+
+2005-08-24 Kevin Kenny <kennykb@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclExecute.c: Corrected some TRACE bugs that prevented
+ compilation with --enable-symbols=all.
+ * generic/tclStrToD.c: Revised commentary to prepare for a renaming of
+ the file, removed some dead code, and fixed a bug where
+ TclBignumToDouble failed on huge negative numbers.
+ * tests/binary.test (binary-65.*): Added missing 'ieeeFloatingPoint'
+ to large/small significand tests.
+ * tests/expr.test (expr-45.*) Added missing braces around expressions.
+
+2005-08-24 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclBasic.c: Revised implementation of the ceil(.) and
+ * generic/tclInt.h: floor(.) math functions in light of the
+ * generic/tclStrToD.c: revised comparison operators, so that it is
+ always true that ($x <= ceil($x)) and ($x >= floor($x)). The simple
+ approach of "convert to double and call ceil() or floor()" could not
+ guarantee that.
+
+ * generic/tclExecute.c: Bug fix: TclBignumToDouble return -Inf when
+ appropriate. Removed declarations of removed routines.
+
+ * generic/tclExecute.c: Revised the type promotion rules of the
+ comparison operators so that they form proper equivalence classes over
+ the set of numeric strings.
+
+2005-08-23 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure.in:
+ * win/configure: Regen.
+ * win/configure.in: Update minimum autoconf version to 2.59.
+
+2005-08-23 Kevin Kenny <kennykb@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd):
+ * generic/tclInt.h:
+ * generic/tclObj.c (Tcl_GetBooleanFromObj, SetDoubleFromAny,
+ Tcl_GetLongFromObj, Tcl_GetWideIntFromObj, Tcl_GetBignumFromObj):
+ * generic/tclParseExpr.c (GetLexeme):
+ * generic/tclScan.c (Tcl_ScanObjCmd):
+ * generic/tclStrToD.c (TclParseNumber):
+ * tests/binary.test (binary-62.1-65.7):
+ * tests/expr.test (expr-40.1-42.1):
+ * scan.test (scan-14.1,14.2):
+ Modified Tcl_ParseNumber to accept an argument to force interpretation
+ as decimal, and modified [scan] to use it. Corrected a bug where Not a
+ Number with hexadecimal information bits returned consistently
+ incorrect values. #ifdef-ed out some code that is needed only for IBM
+ hexadecimal floating point. Fixed bugs in code to handle the corner
+ cases of smallest and largest significands. Added test cases to improve
+ test coverage in generic/tclStrToD.c. Added test cases for 0b notation
+ (TIP #114). Removed TclStrToD, and the static functions that it calls,
+ which are now dead code (TclParseNumber now does all input
+ floating-point conversions.)
+
+2005-08-23 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclStrToD.c: Bug fix: set shift magnitude properly whether
+ we're expanding to mp_int type or not.
+
+ * generic/tclExecute.c: Bug fix: ACCEPT_NAN under INST_UMINUS.
+
+ * generic/tclStrToD.c: New macros TIP_114_FORMATS and KILL_OCTAL to
+ configure acceptance of 0o and 0b numbers and rejection of "leading
+ zero as octal".
+
+ * generic/tclBasic.c: Re-used the guts of int(.) and wide(.) math
+ functions to perform conversions in OldMathFuncProc.
+
+ * generic/tclBasic.c: Support for ACCEPT_NAN.
+ * generic/tclExecute.c:
+
+ * generic/tclInt.decls: Restored TclExprFloatError to internal stubs
+ * generic/tclBasic.c: table, and moved definition back to
+ * generic/tclExecute.c: tclExecute.c from tclBasic.c to handle #undef
+ ACCEPT_NAN.
+
+ * generic/tclIntDecls.h: make genstubs
+ * generic/tclStubInit.c:
+
+ * generic/tclInt.h: New internal macros TclIsNaN and TclIsInfinite
+ * generic/tclBasic.c: replace the IS_NAN and IS_INF macros scattered
+ * generic/tclExecute.c: here and there.
+ * generic/tclObj.c:
+ * generic/tclStrToD.c:
+ * generic/tclUtil.c:
+
+2005-08-22 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tclConfig.h.in: autoheader-2.59.
+
+2005-08-22 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclInt.h: New ACCEPT_NAN macro to mark code that
+ * generic/tclCmdAH.c: supports or disables accepting of the NaN
+ * generic/tclExecute.c: value at various points.
+ * generic/tclLink.c:
+
+ * generic/tclStrToD.c: Bug fix. Parsing of +/- Infinity was reversed.
+
+ * generic/tclTestObj.c: Disabled unused [testconvertobj] command.
+
+ * generic/tclBasic: Added [expr {entier(.)}]. Rewrote int(.) and
+ wide(.) to use the same guts, accepting all non-Inf doubles as
+ arguments.
+
+ * generic/tclInt.h: New routine TclInitBignumFromDouble.
+ * generic/tclStrToD.c: Modified to return code and write error
+ message.
+
+ * generic/tclInt.h: TCL_WIDE_INT_IS_LONG implies NO_WIDE_TYPE.
+ * generic/tclObj.c: Removed now unnecessary tests of the
+ * generic/tclStrToD.c: TCL_WIDE_INT_IS_LONG definition.
+
+ * generic/tclInt.h: New internal routine TclSetBignumIntRep
+ * generic/tclObj.c: consolidates packing of bignum value into a
+ * generic/tclStrToD.c: Tcl_Obj within one source code file.
+
+ * tests/expr.test: Corrected the wideIs64bit constraint.
+ * tests/format.test:
+ * tests/scan.test:
+
+2005-08-21 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclInt.h: Moved TclParseInteger to tclUtil.c and
+ * generic/tclParseExpr.c: made it static.
+ * generic/tclUtil.c:
+
+ * generic/tclInt.decls: Moved TclExprFloatError to tclBasic.c and made
+ * generic/tclBasic.c: it static.
+ * generic/tclExecute.c:
+
+ * generitc/tclIntDecls.h: make genstubs
+ * generic/tclStubInit.c:
+
+ * generic/tclExecute.c: errno, IS_NAN, IS_INF, LLD no longer called in
+ this file; dropped/disabled support for them.
+
+ * generic/tclCompExpr.c: errno no longer used in these files;
+ * generic/tclParseExpr.c: dropped support "hack" for it.
+
+ * generic/tclStrToD.c: Disabled out of date support "hack" for errno.
+
+ * generic/tclBasic.c: Eliminated VerifyExprObjType. Initialize errno
+ to zero in OldMathFuncProc.
+
+2005-08-19 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclBasic.c: Updated OldMathFuncProc and ExprAbsFunc to do
+ less invasion into numeric Tcl_Obj internals. Made ExprDoubleFunc,
+ ExprIntFunc, ExprWideFunc, and ExprRoundFunc bignum-aware. Revised
+ ExprSrandFunc error message.
+
+ * generic/tclProc.c: Wrapped a few tclWideIntType uses in
+ * generic/tclCmdMZ.c: #ifndef NO_WIDE_TYPE.
+
+ * generic/tclInt.h: #define'd NO_WIDE_TYPE.
+
+ * generic/tclVar.c: Replaced TclPtrIncrVar and TclPtrIncrWideVar
+ * generic/tclInt.h: with TclPtrIncrObjVar and replaced TclIncrVar2
+ * generic/tclInt.decls: and TclIncrWideVar2 with TclIncrObjVar2. New
+ routines call on TclIncrObj to do the work.
+
+ * generic/tclIntDecls.h: make genstubs
+ * generic/tclStubInit.c:
+
+ * generic/tclCmdIL.c: Rework Tcl_IncrObjCmd and the INST_*INCR*
+ * generic/tclExecute.c: opcodes to use the new routines.
+
+2005-08-18 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclExecute.c: Fixed string rep invalidation bug in
+ * tests/dict.test (dict-11.17): INST_DICT_INCR_IMM rewrite.
+
+ * generic/tclDictObj.c: DictIncrCmd rewrite to use TclIncrObj.
+
+ * generic/tclInt.h: TclIncrObj static -> internal
+ * generic/tclExecute.c:
+
+2005-08-17 George Peter Staplin <GeorgePS@XMission.com>
+
+ * generic/tclBasic.c: eliminate a namespace clash caused by
+ BuiltinFuncTable not being static.
+
+ * generic/tclObj.c: fix a namespace clash caused by a missing
+ static for pendingObjData.
+
+2005-08-17 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tclEvent.c (Tcl_Finalize): Removed a copy-and-paste accident
+ that caused a (mostly harmless) double finalize of the load and
+ filesystem subsystems.
+ * tests/clock.test: Eliminated the bad test clock-43.1, and split
+ clock-50.1 into two tests, with a more permissive check on the error
+ message for an out-of-range value.
+
+2005-08-17 Kevin Kenny <kennykb@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclBasic.c (Tcl_Expr{Long,Double}{,Obj}): Updated to
+ * generic/tclTest.c: deal with
+ * tests/expr-old.test: bignums (well,
+ * tests/expr.test: mostly).
+ Added a missing "errno=0;" in ExprUnaryFunc so that spurious error
+ returns aren't detected.
+ Added test cases for Tcl_Expr* and Tcl_Expr*Obj because there was very
+ poor test coverage in those areas.
+ * generic/tclParseExpr.c: Reworked parsing of numbers to call
+ TclParseNumber rather than trying to do things locally.
+ * generic/tclStrToD.c: Corrected a comment. Changed so that *endPtrPtr
+ does not include any trailing whitespace.
+
+2005-08-17 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclExecute.c: New routine TclIncrObj to centralize the
+ increment operation needed in many places. Updated INST_DICT_INCR_IMM
+ to make use of it.
+
+2005-08-16 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclExecute.c: Made bit shifting opcodes and INST_MOD
+ bignum-aware.
+
+ * tests/scan.test: Making << bignum-aware means that repeated
+ * tests/string.test: left shifting cannot turn a positive into a
+ negative. Revised [int_range] and [largest_int] utility commands in the
+ test suite that relied on that happening. Without revision they became
+ infinite loops.
+
+ * generic/tclExecute.c: Made binary bitwise opcodes bignum-aware.
+
+ * generic/tclTomMath.h: Added mp_or and mp_xor to routines from
+ * unix/Makefile.in: libtommath used by Tcl.
+ * win/Makefile.in:
+ * win/makefile.vc:
+
+2005-08-15 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch] Updates from HEAD.
+ * generic/tclExecute.c: More revisions to IllegalExprOperandType.
+ Merged INST_BITNOT with INST_UMINUS and make it bignum-aware according
+ to the rule: ~a = -a - 1. Disabled unused code and noted more TODOs.
+
+ * generic/tclInt.decls: Disabled TclLooksLikeInt() and all callers.
+ * generic/tclUtil.c:
+ * generic/tclCompCmds.c:
+
+ * generic/tclBasic.c: Rewrite of VerifyExprObjType().
+
+ * generic/tclIntDecls.h: make genstubs
+ * generic/tclStubInit.c:
+
+ * generic/tclExecute.c: Updated execution of comparison bytecodes to
+ be bignum-aware, routing string compares through INST_STR_CMP.
+
+2005-08-14 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclExecute.c: Updated execution of arithmetic bytecodes to
+ be bignum-aware, and to allow calculations on NaN to produce a NaN
+ result. INST_UMINUS updated to call mp_neg.
+
+ * generic/tclTomMath.h: Added mp_and, mp_expt_d, and mp_neg to
+ * unix/Makefile.in: routines from libtommath used by Tcl.
+ * win/Makefile.in:
+ * win/makefile.vc:
+
+2005-08-13 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclObj.c: Extended Bignum auto-narrowing to auto-narrow
+ to tclWideIntType when appropriate; this helps keep things working as
+ the bytecode execution code is migrated to supporting bignums.
+
+ * generic/tclExecute.c: Major overhaul of IllegalExprOperandType.
+ Changed several TclNewFooObj() calls to more logically appropriate
+ ones. Added several TODO comments marking opportunies for future work.
+ Made more use of the eePtr->constants. Made INST_UMINUS bignum aware.
+
+2005-08-12 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclExecute.c: Simplify doCondJump. Use eePtr->constants as
+ result of INST_DICT_NEXT, INST_LAND, and INST_LOR. Separate INST_LNOT
+ from INST_UMINUS and simplify.
+
+2005-08-12 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tclClock.c (MktimeObjCmd):
+ * library/clock.tcl (GetSystemTimeZone, LoadZoneinfoFile)
+ (ReadZoneinfoFile):
+ * tests/clock.test (clock-50.1):
+ Added functionality to read /etc/localtime if it exists, so that Tcl's
+ time can track system time on Linux even if TZ is not set. Changed
+ ::tcl::clock::Mktime to check for failure, and added a test case that
+ mimics failure but is really success.
+
+2005-08-11 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclExecute.c: Rewrite of INST_LAND/INST_LOR to take advantage
+ of loss of "pure double" issues. Merged INST_UPLUS with
+ INST_TRY_CVT_TO_NUMERIC and updated to use improved rules for impure
+ "double"s as well.
+
+ * generic/tclStrToD.c: Restored conditional generation of
+ tclWideIntType values by TclParseNumber so that Tcl's not completely
+ broken while bignum calculation support is incomplete. The NO_WIDE_TYPE
+ macro can be used to disable this.
+
+ * generic/tclBasic.c (ExprAbsFunc): First pass making [expr abs(.)]
+ bignum-aware.
+
+2005-08-11 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tclEvent.c: Eliminated the USE_THREAD_STORAGE option
+ * generic/tclInt.h: (which is on in every build generated by
+ * generic/tclThread.c: by the standard configurator).
+ * generic/tclThreadStorage.c: Eliminated the code for thread specific
+ * unix/configure: data without USE_THREAD_STORAGE and
+ * unix/tcl.m4: radically refactored the code for
+ * unix/tclConfig.h.in: USE_THREAD_STORAGE so that it has fewer
+ * unix/tclUnixThrd.c: dependencies on the order of
+ * win/configure: finalization. (Also, made 'make
+ * win/Makefile.in: distclean' on Windows clean just a little
+ * win/rules.vc: bit cleaner.)
+ * win/tcl.m4:
+ * win/tclWinThrd.c:
+
+2005-08-10 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclTomMath.h: Added mp_shrink, mp_to_unsigned_bin,
+ * unix/Makefile.in: mp_to_unsigned_bin_n, and mp_unsigned_bin_size
+ * win/Makefile.in: to routines from libtommath used by Tcl.
+ * win/makefile.vc:
+
+ * generic/tommath.h: make gentommath_h
+
+ * generic/tclObj.c: Substantial rewrite to make all number parsing
+ flow through TclParseNumber(). Also established the NO_WIDE_TYPE and
+ BIGNUM_AUTO_NARROW #ifdef's to help track the assumptions of different
+ portions of the code.
+
+ * generic/tclInt.h: Added NO_WIDE_TYPE #ifdefs
+
+2005-08-10 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tclEvent.c (Tcl_Finalize): Pushed Tcl_FinalizeLoad and
+ Tcl_ResetFilesystem down after Tcl_FinalizeThreadAlloc because we can't
+ unload DLL's until after their TSD keys are finalized. (Note that we'll
+ still see aborts if an unloaded DLL has TSD - that still needs to be
+ fixed.
+
+ * tests/compExpr-old.test (compExpr-3.8): Made tests conditional on
+ * tests/expr.test (expr-3.8): 'unix' because they get
+ stack overflows on Win32 threaded builds,
+
+2005-08-09 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclPathObj.c: fix to [file rootname] bug in optimized code
+ path reported on comp.lang.tcl.
+
+2005-08-08 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclObj.c: Replaced some goto's with loops and started
+ use of BIGNUM_AUTO_NARROW and NO_WIDE_TYPE.
+
+2005-08-06 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclThreadStorage.c: Stop exposing the guts of the thread
+ storage system through the internal stubs table. Client code should
+ always use the standard API.
+
+2005-08-05 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch]
+ * generic/tclObj.c: Rewrote Tcl_GetDoubleFromObj().
+
+2005-08-05 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tclUnixInit.c (localeTable): Solaris uses a non-standard name
+ for the cp1251 charset. Thanks to Victor Wagner for reporting this.
+ [Bug 1252475]
+
+2005-08-05 Kevin Kenny <kennykb@users.sourceforge.net>
+
+ * win/makefile.vc: Removed unused file ldAout.tcl.
+ * win/makefile.bc: [Bug 1244361]
+
+ * tests/binary.test: Cleaned up testing for scanning of NaN. [Bug
+ 1246264]
+
+ * generic/tclBasic.c (ExprAbsFunc): Added code to handle the corner
+ * tests/expr.test (expr-38.1): case of applying 'abs' to the
+ smallest 32-bit integer. [Bug 1241572]
+
+2005-08-04 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tclIO.c (CloseChannel): Fixed comment nit, added apparently
+ missing word to complete a sentence.
+
+ * generic/tclObj.c (Tcl_DbDecrRefCount): Fixed whitespace nit in panic
+ message.
+
+2005-08-04 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch] Updated from HEAD
+
+ * generic/tclObj.c: Rewrote Tcl_GetBooleanFromObj() and supporting
+ routines to make use of TclParseNumber. This reduces the potential
+ number of times a string value must be scanned.
+
+ * generic/tclObj.c: Simplified routines that manage the typeTable.
+ Deleted the UpdateStringOfBoolean() routine, that can never be called.
+
+2005-08-03 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCompExpr.c: Untangled some dependencies in the
+ * generic/tclEvent.c: order of finalization routines.
+ * generic/tclInt.h: [Bug 1251399]
+ * generic/tclObj.c:
+
+2005-08-02 Don Porter <dgp@users.sourceforge.net>
+
+ [kennykb-numerics-branch] Updated from HEAD
+
+2005-07-30 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tclLoadDyld.c (TclpDlopen, TclpLoadMemory): workarounds for
+ bugs/changes in behaviour in Mac OS X 10.4 Tiger.
+
+2005-07-29 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclCmdIL.c (InfoGlobalsCmd): Even in high-speed mode, still
+ have to take care with non-existant variables. [Bug 1247135]
+
+2005-07-28 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/README: Update link to msys_mingw8.zip.
+
+2005-07-28 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/compExpr-old.test: Still more conversion of "nonPortable"
+ * tests/error.test: tests into tests with constraints that
+ * tests/expr-old.test: describe the limits of their
+ * tests/expr.test: portability. Also more consolidation
+ * tests/fileName.test: of constraint synonyms.
+ * tests/format.test: wideis64bit, 64bitInts => wideIs64bit
+ * tests/get.test: wideIntegerUnparsed => wideIs32bit
+ * tests/load.test: wideIntExpressions => wideBiggerThanInt
+ * tests/obj.test:
+ * tests/parseExpr.test: Dropped "roundOffBug" constraint that
+ * tests/string.test: protected from buggy sprintf.
+
+2005-07-28 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclPipe.c (TclCreatePipeline): Arrange for POSIX systems to
+ * unix/tclUnixPipe.c (TclpOpenFile): use the O_APPEND flag for
+ * tests/exec.test (exec-19.1): files opened in a pipeline
+ like ">>this". Note that Windows cannot support such access; there is
+ no equivalent flag on the handle that can be set at the kernel-call
+ level. The test is unix-specific in every way. [Bug 1245953]
+
+2005-07-27 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclUtil.c: Converted the $::tcl_precision value to be kept
+ per-thread to prevent different threads from stomping on each others'
+ formatting prescriptions.
+
+ ***POTENTIAL INCOMPATIBILITY*** Multi-threaded programs that set the
+ value of ::tcl_precision will now have to set it in each thread.
+
+ * tests/expr.test: Consolidated equivalent constraints into
+ * tests/fileName.test: single definitions and (more precise) names:
+ * tests/get.test: longis32bit, 32bit, !intsAre64bit => longIs32bit
+ * tests/listObj.test: empty => emptyTest; winOnly => win
+ * tests/obj.test: intsAre64bit => longIs64bit
+ Also updated some "nonPortable" tests to use constraints that mark
+ precisely what about them isn't portable, so the tests can run where
+ they work.
+
+ * library/init.tcl ([unknown]): Corrected return code handling in the
+ portions of [unknown] that expand incomplete commands during
+ interactive operations. [Bug 1214462].
+
+2005-07-26 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/configure.in: Check for a $prefix/share directory and add it the
+ the package if found. This will check for Tcl packages in
+ /usr/local/share when Tcl is configured with the default dist install.
+ [Patch 1231015]
+
+2005-07-26 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c (Tcl_CallWhenDeleted): Converted to use
+ per-thread counter, rather than a process global one that required
+ mutex protection. [RFE 1077194]
+
+ * generic/tclNamesp.c (TclTeardownNamespace): Re-ordering so that
+ * tests/trace.test (trace-34.4): command delete traces fire
+ while the command still exists. [Bug 1047286]
+
+2005-07-24 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * unix/configure: Regen.
+ * unix/tcl.m4 (SC_PROG_TCLSH, SC_BUILD_TCLSH):
+ * win/configure: Regen.
+ * win/tcl.m4 (SC_PROG_TCLSH, SC_BUILD_TCLSH): Split confused search
+ for tclsh on PATH and build and install locations into two macros.
+ SC_PROG_TCLSH searches just the PATH. SC_BUILD_TCLSH determines the
+ name of the tclsh executable in the Tcl build directory. [Bug 1160114]
+ [Patch 1244153]
+
+2005-07-23 Don Porter <dgp@users.sourceforge.net>
+
+ * library/auto.tcl: Updates to the Tcl script library to make use
+ * library/history.tcl: of Tcl 8.4 features. Forward port of
+ * library/init.tcl: appropriate portions of [Patch 1237755].
+ * library/package.tcl:
+ * library/safe.tcl:
+ * library/word.tcl:
+
+2005-07-23 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * tests/string.test: Add string is tests for functionality that was not
+ tested.
+ * win/README: Update msys + mingw URL. Remove old Cygwin + mingw info.
+
+2005-07-23 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c (INST_DICT_*): stop 2 compiler warnings for
+ uninitialised variables.
+
+2005-07-23 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclExecute.c (TEBC:INST_DICT_INCR_IMM): Fix the incrementor
+ to work correctly with wide values.
+
+2005-07-21 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclCompCmds.c (TclCompileDictCmd): First run at a compiler
+ * generic/tclExecute.c (TclExecuteByteCode): for dictionaries. Also
+ added an instruction to support 'finally'-like clauses, exposed more of
+ the dict guts to the rest of the core, and defined a few tests to
+ exercise more obscure parts of the compiler's operation that were bugs
+ during development.
+
+2005-07-21 Kevin B. Kenny <kennykb@acm.org>
+
+ * library/ldAout.tcl (***REMOVED***): Removed support for ancient
+ * unix/configure: BSD's, IRIX 4, RISCos and
+ * unix/Makefile.in: Ultrix. Removed two files whose
+ * unix/tcl.m4: code is used only on those
+ * unix/tclLoadAout.c (***REMOVED***): antique platforms.
+
+ ***POTENTIAL INCOMPATIBILITY*** if anyone actually uses those
+ platforms; it is to be noted though, that an error in the installer has
+ actually not caused a necessary file to be installed on those platforms
+ in several releases, and nobody's complained.
+
+2005-07-16 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclStrToD.c (RefineResult): Plugged a stupid memory leak in
+ RefineResult (called from Tcl_StrToD). [Tk Bug 1227781]
+
+2005-07-15 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclClock.c (TclClockLocaltimeObjCmd,ThreadSafeLocalTime):
+ * library/clock.tcl (GuessWindowsTimeZone, ClearCaches):
+ * tests/clock.test (clock-49.1, clock-49.2):
+ Handle correctly the case where localtime() returns NULL to report a
+ conversion error. Also handle the case where the Windows registry
+ contains timezone values that can be mapped to a tzdata file name but
+ the corresponding file does not exist or is corrupted, by falling back
+ on a Posix timezone string instead; this last case will avoid calls to
+ localtime() in starpacks on Windows. [Bug 1237907]
+
+2005-07-14 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * generic/tclCompile.c: Update to follow style guidelines.
+ (TclPrintInstruction): Reorganize to do better printing out of bytecode
+ with far fewer "special hacks" for particular opcodes.
+ * generic/tclCompile.h: Requires two new opcode types.
+
+2005-07-13 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/tclUnixSock.c: Use a ProcessGlobalValue to store the value
+ * win/tclWinSock.c: returned by Tcl_GetHostName() ([info
+ hostname]). Also re-order initialization of the value on Windows to
+ favor GetComputerName() over gethostname() as a source of the
+ information.
+
+2005-07-12 Kevin Kenny <kennykb@acm.org>
+
+ [kennykb-numerics-branch] Updated from HEAD
+
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd):
+ * generic/tclInt.h:
+ * generic/tclObj.c (Tcl_GetDoubleFromObj, SetDoubleFromAny)
+ (Tcl_GetIntFromObj, SetIntOrWideFromAny):
+ * generic/tclStrToD.c (TclParseNumber, etc.):
+ * tclTomMathInterface.c (TclBNInitBignumFromWideUInt):
+ * tests/obj.test (obj-1.1, obj-2.2, obj-3.1, obj-3.2):
+
+ Initial attempt at an implementation of TIP #249, comprising a unified
+ parser and modifications to the Tcl_Get*FromObj routines to use it.
+ Further integration of the parser is necessary and planned.
+
+2005-07-12 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/lsearch.n: Clarify documentation of -exact option; wording was
+ open to misinterpretation by non-English speakers.
+
+2005-07-11 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclExecute.c: General style cleanup.
+
+2005-07-08 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tclExecute.c (TclExecuteByteCode): Reimplement long and wide
+ type integer division and modulus operations so that the smallest and
+ largest integer values are handled properly. The divide operation is
+ more efficient since it no longer does a modulus or negation and only
+ checks for a remainder when the quotient will be a negative number.
+ The modulus operation is now a bit more complex because of a number of
+ special cases dealing with the smallest and largest integers.
+ * tests/expr.test: Add test cases for division and modulus operations
+ on the smallest and largest integer values for 32 and 64 bit types.
+ [Patch 1230205]
+
+2005-07-06 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclLink.c: Simplified LinkTraceProc [Bug 1208108].
+
+2005-07-05 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/Makefile.in: Purged use of TCLTESTARGS [RFE 1161550].
+
+ * generic/tclUtil.c: Converted TclFormatInt() into a macro.
+ * generic/tclInt.decls: [RFE 1194015]
+ * generic/tclInt.h:
+
+ * generic/tclIntDecls.h: make genstubs
+ * generic/tclStubInit.c:
+
+ * generic/tclNamesp.c: Allow for [namespace import] of a command
+ * tests/namespace.test: over a previous [namespace import] of itself
+ without throwing an error. [RFE 1230597]
+
+2005-07-04 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclDictObj.c (DictForCmd, DictFilterCmd): Interlocking of
+ dictionary internal representations is now done in the core of the dict
+ iterator. Purge the last attempts at doing it at a higher level as they
+ didn't work and were no longer needed.
+
+2005-07-01 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+
+ * unix/tclUnixNotfy.c: protect against spurious wake-ups while waiting
+ on the condition variable when tearing down the notifier thread [Bug
+ 1222872].
+
+2005-06-28 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tclExecute.c (TclExecuteByteCode): When parsing an integer
+ operand for a unary minus expression operator, check for a wide integer
+ that is actually LONG_MIN. If found, convert back to a long int type.
+ * tests/expr.test: Add constraint for 32bit long int type and 64bit
+ wide int type. Add tests that parse the smallest/largest long int and
+ wide int values.
+
+2005-06-24 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tclEvent.c (Tcl_Finalize):
+ * generic/tclInt.h:
+ * generic/tclPreserve.c (TclFinalizePreserve): Changed the finalization
+ logic so that Tcl_Preserve finalizes after exit handlers run; a lot of
+ code called from Tk's exit handlers presumes that Tcl_Preserve will
+ still work even from an exit handler.
+
+2005-06-24 Don Porter <dgp@users.sourceforge.net>
+
+ * library/auto.tcl: Make file safe to re-[source] without
+ destroying registered auto_mkindex_parser hooks.
+
+2005-06-23 Kevin Kenny <kennykb@acm.org>
+
+ * win/tclWinChan.c: More rewriting of __asm__ blocks that implement
+ * win/tclWinFCmd.c: SEH in GCC, because mingw's gcc 3.4.2 is not as
+ forgiving of violations committed by the old code and caused panics.
+ [Bug 1225957]
+
+2005-06-23 Daniel Steffen <das@users.sourceforge.net>
+
+ * tools/tcltk-man2html.tcl: fixed useversion glob pattern to accept
+ multi-digit patchlevels.
+
+2005-06-22 Don Porter <dgp@users.sourceforge.net>
+
+ * win/tclWinFile.c: Potential buffer overflow. [Bug 1225571] Thanks to
+ Pat Thoyts for discovery and fix.
+
+2005-06-22 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tclInt.h: Changed the finalization
+ * generic/tclEvent.c (Tcl_Finalize): logic to defer the
+ * generic/tclIO.c (TclFinalizeIOSubsystem): shutdown of the pipe
+ * unix/tclUnixPipe.c (TclFinalizePipes): management until after all
+ * win/tclWinPipe.c (TclFinalizePipes): channels have been closed,
+ in order to avoid a situation where the Windows PipeCloseProc2 would
+ re-establish the exit handler after exit handlers had already run,
+ corrupting the heap. [Bug 1225727] Also corrected a potential read of
+ uninitialized memory in PipeClose2Proc [Bug 1225044]
+
+2005-06-21 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tclInt.h: Followup to change made on 2005-06-18 by Daniel
+ Steffen. There are compilers (*) who error out on the redefinition of
+ WORDS_BIGENDIAN. We have to undef the previous definition (on the
+ command line) first to make this acceptable. (*): AIX native.
+
+2005-06-21 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclFileName.c: Changed [file split] and [file join] to treat
+ Windows drive letters similarly to ~ syntax and make sure that they
+ appear with "./" in front when they are in intermediate components of
+ the path. [Bug 1194458]
+ * tests/fileName.test: Added test for the above bug.
+
+2005-06-21 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c: Added missing walk of the list of active
+ * generic/tclTrace.c: traces to cleanup references to traces being
+ * generic/tclInt.h: deleted. [Bug 1201035] Made the walk of the
+ * tests/trace.test (trace-34.*): active trace list aware of the
+ direction of trace scanning, so the proper correction can be made.
+ [Bug 1224585]
+
+2005-06-21 Donal K. Fellows <dkf@users.sf.net>
+
+ * unix/tcl.m4 (SC_ENABLE_SYMBOLS): Only enable the 'compile' special
+ debugging feature when requested in configure.in; removes irrelevant
+ junk from the configure files of extensions that use Tcl's tcl.m4.
+
+2005-06-20 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclCompile.h (INST_PUSH_RETURN_OPTIONS): New opcode to allow
+ * generic/tclCompCmds.c (TclCompileCatchCmd): compilation of
+ * generic/tclCompile.c: TIP#90 catch [Bug
+ * generic/tclExecute.c (TclExecuteByteCode): 1219112]
+
+ * generic/tclCompCmds.c (TclCompileSwitchCmd): Ensure we spill to the
+ command form in all cases where it generates an error.
+
+2005-06-20 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tclCmdMZ.c (Tcl_SwitchObjCmd): Generate an error if a mode
+ argument like -exact is passed more than once to the switch command.
+ The previous implementation silently accepted invalid switch
+ invocations like [switch -exact -glob $str ...].
+ * tests/for.test: Check some error cases when invoking continue and
+ break inside a for loop next script.
+ * tests/switch.test: Add checks for shortened version of a mode
+ argument like -exact. Add test for more than one mode argument. Add
+ test for odd case of passing a variable as a body script.
+
+2005-06-18 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tclInt.h: ensure WORDS_BIGENDIAN is defined correctly with
+ fat compiles on Darwin (i.e. ppc and i386 at the same time), the
+ configure AC_C_BIGENDIAN check is not sufficient in this case because a
+ single run of the compiler builds for two architectures with different
+ endianness.
+
+ * unix/tcl.m4 (Darwin): add -headerpad_max_install_names to LDFLAGS to
+ ensure we can always relocate binaries with install_name_tool.
+
+ * unix/configure: autoconf-2.59
+
+2005-06-18 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclCmdAH.c (Tcl_FormatObjCmd): Fix for [Bug 1154163]; only
+ * tests/format.test: insert 'l' modifier when it is needed.
+
+2005-06-17 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclTimer.c (AfterDelay): Split out the code to manage
+ synchronous-delay [after] commands.
+ * tests/interp.test (interp-34.10): Time limits and synch-delay [after]
+ did not mix well... [Bug 1221395]
+
+2005-06-14 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclBasic.c (Tcl_DeleteCommandFromToken): Only delete a
+ * tests/namespace.test (namespace-49.2): command from the hashtable on
+ reentrant processing if it has not been already deleted; at least three
+ deletes of the same command are possible. [Bug 1220058]
+ * generic/tclTrace.c (TraceCommandProc): Remove bogus error message
+ creation when traces trigger in situations where the command has
+ already been deleted.
+
+2005-06-13 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclFCmd.c: correct fix to file mkdir 2005-06-09 [Bug 1219176]
+
+2005-06-12 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclCompCmds.c: Factor out some common idioms into named forms
+ for greater clarity.
+
+2005-06-10 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/chan.n: Fold in the descriptive parts of the documentation for
+ all the commands that [chan] builds on top of.
+
+2005-06-09 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclFCmd.c: fix to race condition in file mkdir [Bug 1217375]
+ * doc/glob.n: improve glob documentation [Bug 1190891]
+
+2005-06-09 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/expr.n, doc/mathfunc.n: Fix minor typos [Bug 1211078] and add
+ mention of distinctly-relevant [namespace path] subcommand.
+
+2005-06-07 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclInt.h: Reduced the Tcl_ObjTypes "index",
+ * generic/tclIndexObj.c: "ensembleCmd", "localVarName", and
+ * generic/tclNamesp.c: "levelReference" to file static scope.
+ * generic/tclProc.c:
+ * generic/tclVar.c:
+
+ * generic/tclObj.c: Restored registration of the "procbody"
+ Tcl_ObjType, as required by the tclcompiler application.
+
+ * generic/tclDecls.h: make genstubs
+ * generic/tclStubInit.c:
+
+2005-06-07 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclIO.c (Tcl_ChannelTruncateProc): Stop proliferation of
+ * generic/tcl.h: channel type versions
+ * doc/CrtChannel.3: following advice from AKu
+
+ Bump patchlevel to a4 to distinguish from a3 release.
+
+ * generic/tclInt.h (INTERP_TRACE_IN_PROGRESS): Add flag so the error
+ * generic/tclIndexObj.c (Tcl_WrongNumArgs): messages from ensembles
+ * generic/tclIOCmd.c (Tcl_ReadObjCmd): can be correct.
+
+ TIP#208 IMPLEMENTATION
+
+ * library/init.tcl: Create the chan ensemble.
+ * tests/chan.test: Rudimentary test suite.
+ * doc/chan.n: General documentation.
+
+ TRUNCATION API (part of TIP#208)
+ * generic/tcl.h, generic/tcl.decls: Declaration of the API.
+ * doc/CrtChannel.3, doc/OpenFileChnl.3: Documentation of the API.
+ * generic/tclBasic.c (Tcl_CreateInterp): Create the mapping into Tcl.
+ * generic/tclIOCmd.c (TclChanTruncateObjCmd): Implementation of
+ Tcl-level truncation API.
+ * generic/tclIO.c (Tcl_TruncateChannel): Generic C-level truncation API
+ implementation.
+ * unix/tclUnixChan.c (FileTruncateProc): Basic implementation of
+ truncating driver.
+
+ * win/tclWinChan.c (FileTruncateProc): Added implementation of file
+ truncation for Windows.
+ * tests/chan.test (chan-15.2): Added real test of truncation.
+
+2005-06-06 Kevin B. Kenny <kennykb@acm.org>
+
+ * win/tclWin32Dll.c: Corrected another buglet in the assembly code for
+ stack probing on Win32/gcc. [Bug 1213678]
+ * generic/tclObj,c: Added missing 'static' on definition of
+ UpdateStringOfBignum, and removed a 'switch' on a 'long long' operand
+ (which HP-UX native 'cc' seems unable to handle). [Bug 1215775]
+
+2005-06-04 Jeff Hobbs <jeffh@ActiveState.com>
+
+ *** 8.5a3 TAGGED FOR RELEASE ***
+
+ * unix/Makefile.in (dist): add libtommath
+
+2005-06-03 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * library/parray.tcl (parray): Only generate the sorted list of element
+ names once. Thanks to Andreas Leitgeb for spotting this.
+
+2005-06-03 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Makefile: fixed 'embedded' target.
+
+2005-06-02 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/Makefile.in (html): add BUILD_HTML_FLAGS optional var
+ * tools/tcltk-man2html.tcl: add a --useversion to prevent confusion
+ when multiple Tcl source dirs exist.
+
+2005-06-01 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c: For compatibility with earlier Tcl releases,
+ * generic/tclResult.c: when a command procedure simply does a
+ * generic/tclTest.c: "return TCL_RETURN;" we must interpret that
+ * tests/result.test: the same as
+ "return Tcl_SetReturnOptions(interp, Tcl_NewObj());" [Bug 1209759].
+
+2005-06-01 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclCompCmds.c (TclCompileSwitchCmd): Allow compilation of
+ -nocase -glob [switch]es (only one we know how to compile).
+
+ TIP#241 IMPLEMENTATION from Joe Mistachkin
+
+ * generic/tclCmdIL.c (Tcl_LsearchObjCmd, Tcl_LsortObjCmd):
+ * generic/tclCmdMZ.c (Tcl_SwitchObjCmd): Implementation of -nocase
+ option for [lsearch], [lsort] and [switch] commands.
+ * win/tclWinPort.h: Win uses nonstandard function names...
+ * tests/cmdIL.test, tests/lsearch.test, tests/switch.test: Tests
+ * doc/lsearch.n, doc/lsort.n, doc/switch.n: Docs
+
+ * generic/tclCompCmds.c (TclCompileLindexCmd): Compile the most common
+ case of [lindex] more efficiently.
+
+ * unix/tclUnixNotfy.c (Tcl_FinalizeNotifier): Pass the correct number
+ of arguments to Tcl_JoinThread.
+
+2005-05-31 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * unix/configure.in, unix/tcl.m4: Standardize generation of help
+ messages to always use AC_HELP_STRING and always (except for --with-tcl
+ and --with-tk, where the default is complex) say what the default is.
+
+2005-05-31 Zoran Vasiljevic <vasiljevic@users.sourceforge.net>
+
+ * unix/tclUnixNotfy.c: the notifier thread is now created as joinable
+ thread and it is properly joined in Tcl_FinalizeNotifier. This is an
+ attempt to fix the [Bug 1082283].
+
+2005-05-30 Zoran Vasiljevic <vasiljevic@users.sf.net>
+
+ * win/tclWinThrd.c: Fixed [Bug 1204064]
+
+2005-05-30 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ TIP #229 IMPLEMENTATION
+
+ * generic/tclNamesp.c (Tcl_FindCommand, TclResetShadowedCmdRefs)
+ (NamespacePathCmd, SetNsPath, UnlinkNsPath, TclInvalidateNsPath):
+ Implementation of the [namespace path] command and the command name
+ resolution engine.
+ * doc/info.n, doc/namespace.n: Doc updates.
+ * tests/namespace.test (namespace-51.*): Test updates.
+ * generic/tclResolve.c (BumpCmdRefEpochs, Tcl_SetNamespaceResolvers):
+ * generic/tclBasic.c (Tcl_CreateCommand, Tcl_CreateObjCommand): Ensure
+ that people don't see stale paths.
+ * generic/tclInt.h (Namespace, NamespacePathEntry): Structure defs.
+ * generic/tclCmdIL.c (InfoCommandsCmd): Updates to [info commands].
+
+2005-05-26 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/Makefile: moved & corrected EMBEDDED_BUILD check.
+
+ * unix/configure.in: corrected framework finalization to softlink stub
+ library to Versions/8.x subdir instead of Versions/Current.
+ * unix/configure: autoconf-2.59
+
+2005-05-25 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclCmdMZ.c (Tcl_TimeObjCmd): add necessary cast
+
+2005-05-25 Don Porter <dgp@users.sourceforge.net>
+
+ TIP#182 IMPLEMENTATION [Patch 1165062]
+
+ * doc/mathfunc.n: New built-in math function bool().
+ * generic/tclBasic.c:
+ * tests/expr.test:
+ * tests/info.test:
+
+2005-05-24 Don Porter <dgp@users.sourceforge.net>
+
+ * library/init.tcl: Updated [unknown] to be sure the [return]
+ * tests/init.test: options from an auto-loaded command are seen
+ correctly by the caller.
+
+2005-05-24 Daniel Steffen <das@users.sourceforge.net>
+
+ * tests/env.test: added DYLD_FRAMEWORK_PATH to the list of env vars
+ that need to be handled specially.
+
+ * macosx/Makefile:
+ * macosx/README:
+ * macosx/Tcl-Info.plist.in (new file):
+ * unix/Makefile.in:
+ * unix/configure.in:
+ * unix/tcl.m4:
+ * unix/tclUnixInit.c: moved all Darwin framework build support from
+ macosx/Makefile into the standard unix configure/make buildsystem, the
+ macosx/Makefile is no longer required to build Tcl.framework (but its
+ functionality is still available for backwards compatibility).
+ * unix/configure: autoconf-2.59
+
+ * generic/tclIOUtil.c (TclLoadFile):
+ * generic/tclInt.h:
+ * unix/tcl.m4:
+ * unix/tclLoadDyld.c: added support for [load]ing .bundle binaries in
+ addition to .dylib's: .bundle's can be [unload]ed (unlike .dylib's),
+ and can be [load]ed from memory, e.g. directly from VFS without needing
+ to be written out to a temporary location first. [Bug 1202209]
+ * unix/configure: autoconf-2.59
+ * unix/tclConfig.h.in: autoheader-2.59
+
+ * generic/tclCmdMZ.c (Tcl_TimeObjCmd): change [time] called with a
+ count > 1 to return a string with a float value instead of a rounded
+ off integer. [Bug 1202178]
+
+ * doc/expr.n:
+ * doc/string.n: fixed roff syntax complaints from 'make html'.
+
+2005-05-20 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclParseExpr.c: Corrected parser to recognize all
+ boolean literals accepted by Tcl_GetBoolean, including prefixes like
+ "y" and "f", and to allow "eq" and "ne" as function names in the proper
+ context. [Bug 1201589].
+
+2005-05-19 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclBasic.c (TclEvalObjvInternal): Rewrite for greater
+ clarity; although 'goto' is Bad, the contortions you have to go through
+ to avoid it can be worse...
+
+2005-05-19 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/tclMacOSXNotify.c (Tcl_InitNotifier): fixed crashing CFRelease
+ of runLoopSource in Tcl_InitNotifier (reported by Zoran):
+ CFRunLoopAddSource doesn't CFRetain, so can only CFRelease the
+ runLoopSource in Tcl_FinalizeNotifier.
+
+2005-05-18 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c (Tcl_ExprBoolean): Rewrite as wrapper around
+ Tcl_ExprBooleanObj.
+
+ * generic/tclCmdMZ.c ([string is boolean/true/false]): Rewrite dropping
+ string-based Tcl_GetBoolean call, so that internal reps are kept for
+ subsequent quick boolean operations.
+
+ * generic/tclExecute.c: Dropped most special handling of the "boolean"
+ Tcl_ObjType, since that type should now be rarely encountered.
+
+ * doc/BoolObj.3: Rewrite of documentation dropping many details
+ about the internals of Tcl_Objs. Shorter documentation focuses on the
+ function and use of the routines.
+
+ * generic/tclInt.h: Revision to the "boolean" Tcl_ObjType, so that
+ * generic/tclObj.c: only string values like "yes" and "false" are
+ * tests/obj.test: kept as the "boolean" Tcl_ObjType. The string
+ values "0" and "1" are kept as "int" Tcl_ObjType, which also produce
+ quick calls to Tcl_GetBooleanFromObj(). Since this internal change
+ means a Tcl_ConvertToType to a "boolean" Tcl_ObjType might not produce
+ a Tcl_Obj of type "boolean", the registration of the "boolean" type is
+ also removed.
+ ***POTENTIAL INCOMPATIBILITY***
+ For callers of Tcl_GetObjType on the type name "boolean".
+
+2005-05-17 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclObj.c (TclInitObjSubsystem): Removed the
+ * tests/listObj.test: registration of the Tcl_ObjType's "list",
+ * tests/obj.test: "procbody", "index", "ensembleCommand",
+ "localVarName", and "levelReference". The only reason to register a
+ Tcl_ObjType is to have it returned by Tcl_GetObjType, and the only
+ reason for that is to retrieve a (Tcl_ObjType *) to pass to
+ Tcl_ConvertToType(). None of the types above can support a
+ Tcl_ConvertToType() call; they panic. Better not to offer something
+ than to lead users into a panic.
+ ***POTENTIAL INCOMPATIBILITY***
+ For callers of Tcl_GetObjType on the type names listed above.
+
+2005-05-15 Kevin Kenny <kennykb@users.sourceforge.net>
+
+ * win/tclWin32Dll.c: conditioned definition of EXCEPTION_REGISTRATION
+ structures on HAVE_NO_SEH, to fix a bug in buildability on MSVC.
+
+2005-05-14 Daniel Steffen <das@users.sourceforge.net>
+
+ * generic/tclInt.decls:
+ * generic/tclTest.c:
+ * generic/tclUtil.c:
+ * win/tclWin32Dll.c: fixed link error due to direct access by tclTest.c
+ to the MODULE_SCOPE tclPlatform global: renamed existing
+ TclWinGetPlatform() accessor to TclGetPlatform() and moved it to
+ generic code so that it can be used by on all platforms where
+ MODULE_SCOPE is enforced.
+
+ * macosx/tclMacOSXBundle.c:
+ * unix/tclUnixInit.c:
+ * unix/tcl.m4 (Darwin): made use of CoreFoundation API configurable and
+ added test of CoreFoundation availablility to allow building on ppc64,
+ replaced HAVE_CFBUNDLE by HAVE_COREFOUNDATION; test for availability of
+ Tiger or later OSSpinLockLock API.
+
+ * unix/tclUnixNotfy.c:
+ * unix/Makefile.in:
+ * macosx/tclMacOSXNotify.c (new file): when CoreFoundation is
+ available, use new CFRunLoop based notifier: allows easy integration
+ with other event loops on Mac OS X, in particular the TkAqua Carbon
+ event loop is now integrated via a standard tcl event source (instead
+ of TkAqua upon loading having to finalize the exsting notifier and
+ replace it with its custom version). [Patch 1202052]
+
+ * tests/unixNotfy.test: don't run unthreaded tests on Darwin since
+ notifier may be using threads even in unthreaded core.
+
+ * unix/tclUnixPort.h:
+ * unix/tcl.m4 (Darwin): test for thread-unsafe realpath during
+ configure, as Darwin 7 and later realpath is threadsafe.
+
+ * macosx/Makefile: enable configure caching.
+
+ * unix/configure.in: wrap tclConfig.h header in #ifndef _TCLCONFIG so
+ that it can be included more than once without warnings from gcc4.0 (as
+ happens e.g. when including both tclInt.h and tclPort.h)
+
+ * macosx/tclMacOSXBundle.c:
+ * unix/tclUnixChan.c:
+ * unix/tclLoadDyld.c:
+ * unix/tclUnixInit.c: fixed gcc 4.0 warnings.
+
+ * unix/configure: autoconf-2.59
+ * unix/tclConfig.h.in: autoheader-2.59
+
+ * generic/tclIntDecls.h:
+ * generic/tclIntPlatDecls.h:
+ * generic/tclStubInit.c: make genstubs
+
+2005-05-13 Kevin Kenny <kennykb@acm.org>
+
+ * win/tclWin32Dll.c: Further rework of the SEH logic. All
+ EXCEPTION_REGISTRATION records are now in the activation record rather
+ than pushed on the stack.
+
+2005-05-13 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c: Dropped the TCL_NO_MATH configuration. It's
+ * generic/tclBinary.c: believed this has not been working in a long
+ * generic/tclExecute.c: time. Tcl needs math.h. [RFE 1200680]
+ * unix/Makefile.in:
+
+2005-05-12 Kevin Kenny <kennykb@acm.org>
+
+ * doc/mathfunc.n: Changed NAME line to match the name of the page.
+
+2005-05-11 Kevin Kenny <kennykb@acm.org>
+
+ [kennykb-numerics-branch] Resynchronized with the HEAD; at this
+ checkpoint [-rkennykb-numerics-branch-20050511], the HEAD and
+ kennykb-numerics-branch contain identical code.
+
+2005-05-11 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tclStrToD.c (TclStrToD, RefineResult, ParseNaN): Changed the
+ code to cast 'char' to UCHAR explicitly when using ctype macros, to
+ silence complaints from the Solaris compiler.
+
+2005-05-10 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tclUnixFCmd.c: add lint attr to enum to satisfy strictly
+ compliant compilers that don't like trailing ,s.
+
+ * tests/string.test: string-10.[21-30]
+ * generic/tclCmdMZ.c (Tcl_StringObjCmd): add extra checks to prevent
+ possible UMR in unichar cmp function for string map.
+
+2005-05-10 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tclBinary.c (FormatNumber): Fixed a bug where NaN's resulted
+ in reads of uninitialized memory when using 'd', 'q', or 'Q' format.
+ * generic/tclStrToD.c (ParseNaN, TclFormatNaN): Added code to handle
+ the peculiarities of HP's PA_RISC, which uses a different 'quiet' bit
+ in NaN from everyone else.
+ * libtommath/tommath_superclass.h: Corrected C++-style comment.
+
+2005-05-10 Kevin Kenny <kennykb@acm.org>
+
+ Merged all changes on kennykb-numerics-branch back into the HEAD.
+ TIP's 132 and 232 are now Final.
+
+2005-05-10 Kevin Kenny <kennykb@acm.org>
+
+ [kennykb-numerics-branch] Merged changes from HEAD.
+
+2005-05-10 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c (ExponLong, ExponWide):
+ * tests/expr.test (expr-23.34/35): fixed special case 'i**0' for i>0
+ [Bug 1198892]
+
+2005-05-09 Kevin B. Kenny <kennykb@acm.org>
+
+ [kennykb-numerics-branch]
+ * win/tclWin32Dll.c (TclpCheckStackSpace, TclWinCPUID): Reworked
+ structured event handling to function even with -fomit-frame-pointers.
+
+2005-05-08 Kevin B. Kenny <kennykb@acm.org>
+
+ [kennykb-numerics-branch]
+ * generic/tclStrToD.c: Made code more portable by finding a workaround
+ for MSVC's 'volatile' issue that does not require conditional
+ compilation.
+ * win/tclWin32Dll.c (TclWinCPUID): Removed structured event handling
+ from the GCC code since (a) bad code is generated by the instruction
+ scheduling with -O2, and (b) it's not needed on any reasonably modern
+ CPU.
+
+2005-05-07 Kevin B. Kenny <kennykb@acm.org>
+
+ [kennykb-numerics-branch]
+ * generic/tclEvent.c: Moved initialization of tclStrToD.c's
+ * generic/tclInt.h: static constants into a procedure called
+ * generic/tclStrToD.c: from TclInitSubsystems to avoid double checked
+ locking protocol. Cleaned up an issue where MSVC ignored the
+ 'volatile' specifier, causing incorrect comparison of an underflowed
+ number against zero.
+
+2005-05-06 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/tcl.m4, unix/configure: correct Solaris 10 (5.10) check and add
+ support for x86_64 Solaris cc builds.
+
+2005-05-05 Kevin B. Kenny <kennykb@acm.org>
+
+ [kennykb-numerics-branch] Merged with HEAD.
+
+2005-05-05 Kevin B. Kenny <kennykb@acm.org>
+
+ * win/tclWinThrd.c: Corrected a compilation error on the
+ --enable-threads configuration.
+
+2005-05-05 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclInt.decls: Converted TclMatchIsTrivial to a macro.
+ * generic/tclInt.h:
+ * generic/tclUtil.c:
+ * generic/tclIntDecls.h: `make genstubs`
+ * generic/tclStubInit.c:
+ * generic/tclBasic.c: Added callers of TclMatchIsTrivial where a
+ * generic/tclCmdIL.c: search can be done more efficiently when it is
+ * generic/tclCompCmds.c:recognized that a pattern match is really an
+ * generic/tclDictObj.c: exact match. [Patch 1076088]
+ * generic/tclIO.c:
+ * generic/tclNamesp.c:
+ * generic/tclVar.c:
+
+ * generic/tclCompCmds.c: Factored common efficiency trick into a
+ macro named CompileWord.
+
+ * generic/tclCompCmds.c: Replaced all instance of
+ * generic/tclCompile.c: TCL_OUT_LINE_COMPILE with TCL_ERROR.
+ * generic/tclInt.h: Now that we've eradicated the mistaken
+ * tests/appendComp.test: notion of a "compile-time error", we
+ can use the TCL_ERROR return code to signal any failure to produce
+ bytecode.
+
+2005-05-03 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/DString.3: Eliminated use of identifier "string" in Tcl's
+ * doc/Environment.3: public C API to avoid conflict/confusion with
+ * doc/Eval.3: the std::string of C++.
+ * doc/ExprLong.3, doc/ExprLongObj.3, doc/GetInt.3, doc/GetOpnFl.3:
+ * doc/ParseCmd.3, doc/RegExp.3, doc/SetResult.3, doc/StrMatch.3:
+ * doc/Utf.3, generic/tcl.decls, generic/tclBasic.c, generic/tclEnv.c:
+ * generic/tclGet.c, generic/tclParse.c, generic/tclParseExpr.c:
+ * generic/tclRegexp.c, generic/tclResult.c, generic/tclUtf.c:
+ * generic/tclUtil.c, unix/tclUnixChan.c:
+
+ * generic/tclDecls.h: `make genstubs`
+
+2005-05-02 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tcl.decls:
+ * generic/tclBasic.c: Simplified implementation of Tcl_ExprString.
+ * tests/expr-old.test:
+
+ * generic/tclDecls.h: `make genstubs`
+
+2005-04-30 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tclUnixNotfy.c: applied dkf's tkMacOSXNotify.c cleanup changes.
+
+2005-04-29 Don Porter <dgp@users.sourceforge.net>
+
+ TIP#176 IMPLEMENTATION [Patch 1165695]
+
+ * generic/tclUtil.c: Extended TclGetIntForIndex to recognize index
+ formats including end+integer and integer+/-integer.
+
+ * generic/tclCmdMZ.c: Extended the -start switch of [regexp] and
+ [regsub] to accept all index formats known by TclGetIntForIndex.
+
+ * doc/lindex.n: Updated docs to note new index formats.
+ * doc/linsert.n, doc/lrange.n, doc/lreplace.n, doc/lsearch.n:
+ * doc/lset.n, doc/lsort.n, doc/regexp.n, doc/regsub.n, doc/string.n:
+
+ * tests/cmdIL.test: Updated tests.
+ * tests/compile.test, tests/lindex.test, tests/linsert.test:
+ * tests/lrange.test, tests/lreplace.test, tests/lsearch.test:
+ * tests/lset.test, tests/regexp.test, tests/regexpComp.test:
+ * tests/string.test, tests/stringComp.test, tests/util.test:
+
+2005-04-28 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/unixInit.test (7.1): Alternative fix for the 2004-11-11 commit.
+
+2005-04-27 Don Porter <dgp@users.sourceforge.net>
+
+ * library/init.tcl: Corrected flaw in interactive command
+ * tests/main.test: auto-completion. [Bug 1191409].
+
+ TIP#183 IMPLEMENTATION [Patch 577093]
+
+ * generic/tclIOUtil.c (TclGetOpenModeEx): New routine.
+ * generic/tclInt.h:
+
+ * generic/tclIO.c (Tcl_OpenObjCmd): Support for "b" and
+ * doc/open.n: "BINARY" in "access" argument to [open].
+ * tests/ioCmd.test:
+
+2005-04-26 Kevin B. Kenny <kennykb@users.sourceforge.net>
+
+ * generic/tclBinary.c (FormatNumber): Dredge the NaN out of the
+ internal representation if Tcl_GetDoubleFromObj returns TCL_ERROR on a
+ NaN.
+
+ * generic/tclObj.c (Tcl_GetDoubleFromObj): Restored silent
+ overflow/underflow behaviour that the merge of 2004-04-25 messed up.
+ Thanks to Don Porter for calling attention to this bug. Also removed an
+ uninitialised memory reference in this function that valgrind caught.
+ Also changed to return TCL_ERROR on a pure NaN.
+
+ * generic/tclStrToD.c (RefineResult): Added a test for the initial
+ approximation being HUGE_VAL; this test avoids EDOM being returned from
+ ldexp on some platforms on input values exceeding the floating point
+ range.
+
+ * tests/expr.test (expr-29.*, expr-30.*): Added further tests of
+ overflow/underflow on input conversions.
+
+2005-04-25 Kevin B. Kenny <kennykb@users.sourceforge.net>
+
+ [kennykb-numerics-branch] Merged with HEAD.
+
+ * doc/CrtMathFunc.n: Revised documentation for TIP 232
+
+2005-04-25 Daniel Steffen <das@users.sourceforge.net>
+
+ * compat/string.h: fixed memchr() protoype for __APPLE__ so that we
+ build on Mac OS X 10.1 again.
+
+ * generic/tclNotify.c (TclFinalizeNotifier): fixed notifier not being
+ finalized in unthreaded core (was testing for notifier initialization
+ in current thread by checking thread id != 0 but thread id is always 0
+ in untreaded core).
+
+ * win/tclWinNotify.c (Tcl_WaitForEvent):
+ * unix/tclUnixNotfy.c (Tcl_WaitForEvent): don't call ScaleTimeProc for
+ zero wait times (as specified in TIP 233).
+
+ * unix/Makefile.in: added @PLAT_SRCS@ to SRCS and split out NOTIFY_SRCS
+ from UNIX_SRCS for parity with UNIX_OBJS & NOTIFY_OBJS.
+
+ * unix/tcl.m4 (Darwin): added configure checks for recently added
+ linker flags -single_module and -search_paths_first to allow building
+ with older tools (and on Mac OS X 10.1), use -single_module in SHLIB_LD
+ and not just T{CL,K}_SHLIB_LD_EXTRAS, added unexporting from Tk of
+ symbols from libtclstub to avoid duplicate symbol warnings, added
+ PLAT_SRCS definition for Mac OS X, defined MODULE_SCOPE to
+ __private_extern__.
+ (SC_MISSING_POSIX_HEADERS): added caching of dirent.h check.
+
+ * unix/configure: autoconf-2.59
+
+2005-04-25 Kevin B. Kenny <kennykb@users.sourceforge.net>
+
+ * library/tzdata/America/Boise:
+ * library/tzdata/America/Chicago:
+ * library/tzdata/America/Denver
+ * library/tzdata/America/Indianapolis:
+ * library/tzdata/America/Los_Angeles:
+ * library/tzdata/America/Louisville:
+ * library/tzdata/America/Managua:
+ * library/tzdata/America/New_York:
+ * library/tzdata/America/Phoenix:
+ * library/tzdata/America/Port-au-Prince:
+ * library/tzdata/America/Indiana/Knox:
+ * library/tzdata/America/Indiana/Marengo:
+ * library/tzdata/America/Indiana/Vevay:
+ * library/tzdata/America/Kentucky/Monticello:
+ * library/tzdata/America/North_Dakota/Center:
+ * library/tzdata/Asia/Tehran:
+ Olson's tzdata2005i. Corrects exact time at which Standard Time was
+ adopted in the US (generally, noon, Standard Time, rather than noon,
+ Local Mean Time). Adopts new civil rules for Nicaragua and Iran.
+
+2005-04-25 Don Porter <dgp@users.sourceforge.net>
+
+ * library/init.tcl: Use "ni" and "in" operators.
+
+2005-04-25 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c: fix for [Bug 1189274].
+
+2005-04-24 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclLiteral.c: Silence compiler warnings.
+ * generic/tclObj.c: [Bug 1188863].
+
+2005-04-22 Don Porter <dgp@users.sourceforge.net>
+
+ The 2005-04-21 changes to Tcl_GetBooleanFromObj were done to bring it
+ into agreement with its docs. Further investigation reveals it was the
+ docs that were incorrect.
+
+ * doc/BoolObj.3: Corrections to the documentation of
+ Tcl_GetBooleanFromObj to bring it into agreement with what this public
+ interface has always done, including noting the difference in function
+ between Tcl_GetBooleanFromObj and Tcl_GetBoolean.
+
+ * generic/tclGet.c: Revised Tcl_GetBoolean to no longer be a
+ wrapper around Tcl_GetBooleanFromObj (different function!).
+
+ * generic/tclObj.c: Removed TclGetTruthValueFromObj routine that
+ was added yesterday. Revisions so that only Tcl_GetBoolean-approved
+ values get the "boolean" Tcl_ObjType. This retains the fix for [Bug
+ 1187123].
+ * tests/string.test: Test string-23.0 for Bug 1187123.
+
+ * generic/tclInt.h: Revert most recent change.
+ * generic/tclBasic.c:
+ * generic/tclCompCmds.c:
+ * generic/tclDictObj.c:
+ * generic/tclExecute.c:
+ * tests/obj.test:
+
+2005-04-21 Don Porter <dgp@users.sourceforge.net>
+
+ * doc/GetInt.3: Convert argument "string" to "str" to agree with code.
+ Also clarified a few details on int and double formats.
+ * generic/tclGet.c: Radical code simplification. Converted
+ Tcl_GetFoo() routines into wrappers around Tcl_GetFooFromObj(). Reduces
+ code duplication, and the resulting potential for inconsistency.
+
+ * generic/tclObj.c: Several changes:
+
+ - Re-ordered error detection code so all values with trailing garbage
+ receive a "not an integer" message instead of an "integer too large"
+ message.
+ - Removed inactive code meant to deal with strtoul* routines that fail
+ to parse leading signs. All of them do, and if any are detected that
+ do not, the correct fix is replacement with compat/strtoul*.c, not a
+ lot of special care by the callers.
+ - Tcl_GetDoubleFromObj now avoids shimmering away a "wideInt" intrep.
+ - Fixed Tcl_GetBooleanFromObj to agree with its documentation and with
+ Tcl_GetBoolean, accepting only "0" and "1" and not other numeric
+ strings. [Bug 1187123]
+ - Added new private routine TclGetTruthValueFromObj to perform the more
+ permissive conversion of numeric values to boolean that is needed by
+ the [expr] machinery.
+
+ * generic/tclInt.h (TclGetTruthValueFromObj): New routine.
+ * generic/tclExecute.c: Updated callers to call new routine.
+ * generic/tclBasic.c: Updated callers to call new routine.
+ * generic/tclCompCmds.c: Updated callers to call new routine.
+ * generic/tclDictObj.c: Updated callers to call new routine.
+ * tests/obj.test: Corrected bad tests that actually expected
+ values like "47" and "0xac" to be accepted as booleans.
+
+ * generic/tclLiteral.c: Disabled the code that forces some literals
+ into the "int" Tcl_ObjType during registration. We can re-enable it if
+ this change causes trouble, but it seems more sensible to let Tcl's
+ "on-demand" shimmering rule, and not try to pre-guess things.
+
+2005-04-20 Kevin B. Kenny <kennykb@acm.org>
+
+ [kennykb-numerics-branch]
+ * doc/expr.n:
+ * doc/mathfunc.n (new file): Revised documentation for TIP 232
+
+2005-04-20 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclGet.c (Tcl_GetInt): Corrected error that did not
+ * generic/tclObj.c (Tcl_GetIntFromObj): permit 0x80000000 to be
+ recognized as an integer on TCL_WIDE_INT_IS_LONG systems [Bug 1090869].
+
+2005-04-20 Kevin B. Kenny <kennykb@acm.org>
+
+ * generic/tclFileName.c: Silenced a compiler warning about '/*' within
+ a comment.
+
+2005-04-19 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c: Added unsupported command
+ * generic/tclCmdAH.c: [::tcl::unsupported::EncodingDirs] to permit
+ * generic/tclInt.h: query/set of the encoding search path at
+ * generic/tclInterp.c: the script level. Updated init.tcl to make
+ * library/init.tcl: use of the new command. Also updated several
+ coding practices in init.tcl ("eq" for [string equal], etc.)
+
+2005-04-19 Kevin B. Kenny <kennykb@acm.org>
+
+ * library/clock.tcl (Initialize): Put initialization code into a proc
+ to avoid inadvertently clobbering global variables. [Bug 1185933]
+ * tests/clock.test (clock-48.1): Added regression test for the above
+ bug.
+ Thanks to Ulrich Ring for reporting this bug.
+
+2005-04-16 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/Var.c (Tcl_ArrayObjCmd - ARRAY_NAMES): fix Tcl_Obj leak. [Bug
+ 1084111]
+
+2005-04-16 Zoran Vasiljevic <vasiljevic@users.sf.net>
+
+ * generic/tclIOUtil.c: force clenaup of the interp result in
+ TclLoadFile(). Some implementations of TclpFindSymbol() will seed the
+ interp result with error message when unable to find the requested
+ symbol (this is not considered to be an error).
+
+ Set of changes correcting huge memory waste (not a leak) when a thread
+ exits. This has been introduced in 8.4.7 within an attempt to correctly
+ cleanup after ourselves when Tcl library is being unloaded with the
+ Tcl_Finalize() call.
+
+ This fixes the [Bug 1178445]
+
+ * generic/tclInt.h: added prototypes for TclpFreeAllocCache() and
+ TclFreeAllocCache()
+
+ * generic/tclThreadAlloc.c: modified TclFinalizeThreadAlloc() to
+ explicitly call TclpFreeAllocCache with the NULL-ptr as argument
+ signalling cleanup of private tsd key used only by the threading
+ allocator.
+
+ * unix/tclUnixThrd.c: fixed TclpFreeAllocCache() to recognize when
+ being called with NULL argument. This is a signal for it to clean up
+ the tsd key associated with the threading allocator.
+
+ * win/tclWinThrd.c: renamed TclWinFreeAllocCache to TclpFreeAllocCache
+ and fixed to recognize when being called with NULL argument. This is a
+ signal for it to clean up the tsd key associated with the threading
+ allocator.
+
+2005-04-13 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/unixInit.test: Disabled obsolete tests and removed code
+ * tests/encoding.test: that supported them.
+ * generic/tclInterp.c:
+
+ * library/init.tcl: Use auto-loading to bring in Tcl Module support
+ * library/tclIndex: as needed. This reduces startup time by
+ * library/tm.tcl: delaying this initialization to a later time.
+
+2005-04-15 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c: missing semicolons caused failure to compile
+ with TCL_COMPILE_DEBUG.
+
+2005-04-13 David Gravereaux <davygrvy@pobox.com>
+
+ * generic/tclIO.c (Tcl_SetChannelBufferSize): Lowest size limit
+ * tests/io.test: changed from ten bytes to one byte. Need for
+ * tests/iogt.test: this change was proven by Ross Cartlidge
+ <rossc@cisco.com> where [read stdin 1] was grabbing 10 bytes followed
+ by starting a child process that was intended to continue reading from
+ stdin. Even with -buffersize set to one, nine chars were getting lost
+ by the buffersize over reading for the native read() caused by [read].
+
+2005-04-13 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/tclUnixInit.c (TclpGetEncodingNameFromEnvironment): Reversed
+ order of verifying candidate [encoding system] value, checking against
+ a table in memory first before calling Tcl_GetEncoding and potentially
+ scanning through the filesystem. Also ordered the table so that a
+ binary search could be used within it. Improves startup time a bit more
+ on some systems.
+
+2005-04-13 Kevin B. Kenny <kennykb@acm.org>
+
+ * library/clock.n: Added a missing '--' on several [switch] commands to
+ improve performance of [clock format] and related operations. [FRQ
+ 1182459]
+
+2005-04-13 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * doc/fcopy.n: Improved documentation on copying binary files, added an
+ example and mentioned the use of [file copy].
+ * doc/fconfigure.n: Improved documentation of -encoding binary option.
+ This is all following comments from Steve Manning <steve@manning.net>
+ on comp.lang.tcl that the current documentation was not clear.
+
+2005-04-13 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompile.c:Commented out the functions
+ TclPrintInstruction(), TclPrintObject() and TclPrintSource() when not
+ debugging the compiler, as they are never called in that case.
+
+2005-04-12 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclInterp.c: Corrected bad syntax of Tcl_Panic() call.
+
+ * generic/tclUtil.c (TclGetProcessGlobalValue): More robust handling
+ of bad TclInitProcessGlobalValueProc behavior; an immediate panic
+ rather than a mysterious crash later.
+
+ * generic/tclEncoding.c: Several changes to the way the
+ encodingFileMap cache is maintained. Previously, it was attempted to
+ keep the file map filled and up to date with changes in the encoding
+ search path. This contributed to slow startup times since it required
+ an expensive "glob" operation to fill the cache. Now the validity of
+ items in the cache are checked at the time they are used, so the cache
+ is permitted to fall out of sync with the encoding search path. Only
+ [encoding names] and Tcl_GetEncodingNames() now pay the full expense.
+ [Bug 1177363]
+
+2005-04-12 Kevin B. Kenny <kennykb@acm.org>
+
+ * compat/strstr.c: Added default definition of NULL to accommodate
+ building on systems with badly broken headers. [Bug 1175161]
+
+2005-04-11 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * tools/tclZIC.tcl: Rewrote to take advantage of more features of Tcl
+ 8.5 (on which it was dependent anyway). Also added a [package require]
+ line to formalize the relationship.
+
+2005-04-11 Kevin Kenny <kennykb@users.sf.net>
+
+ [kennykb-numerics-branch] Merged with HEAD. Updated to libtommath 0.35.
+
+ * generic/tclBasic.c: Attempted to repeat changes that applied to
+ tclExecute.c in Miguel Sofer's commit of 2005-04-01, together with
+ (possibly) a few more uses of his new object creation macros. Also
+ plugged a memory leak in TclObjInvoke. [Bug 1180368]
+
+2005-04-10 Kevin Kenny <kennykb@acm.org>
+
+ * library/tzdata/America/Montevideo:
+ * library/tzdata/Asia/Almaty:
+ * library/tzdata/Asia/Aqtau:
+ * library/tzdata/Asia/Aqtobe:
+ * library/tzdata/Asia/Baku:
+ * library/tzdata/Asia/Jerusalem:
+ * library/tzdata/Asia/Oral:
+ * library/tzdata/Asia/Qyzylorda:
+ * library/tzdata/Indian/Chagos:
+ * library/tzdata/Indian/Cocos: Olson's tzdata2005h
+
+2005-04-10 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclBasic.c (TclObjInvoke): Plug memory leak. [Bug 1180368]
+
+2005-04-09 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c: fix possible leak of expansion Tcl_Objs
+
+2005-04-09 Daniel Steffen <das@users.sourceforge.net>
+
+ * macosx/README: updated requirements for OS & developer tool versions
+ and other small fixes/cleanup.
+
+ * generic/tclListObj.c (Tcl_ListObjIndex): added missing NULL return
+ when getting index from an empty list.
+
+ * unix/tcl.m4 (Darwin): added -single_module linker flag to
+ TCL_SHLIB_LD_EXTRAS and TK_SHLIB_LD_EXTRAS.
+ * unix/configure: autoconf-2.59
+
+2005-04-08 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclInt.h (TclGetEncodingFromObj): New function to
+ * generic/tclEncoding.c (TclGetEncodingFromObj): retrieve a
+ Tcl_Encoding value, as well as cache it in the internal rep of a new
+ "encoding" Tcl_ObjType.
+ * generic/tclCmdAH.c (Tcl_EncodingObjCmd): Updated to call new
+ function so that Tcl_Encoding's used by [encoding convert*] routines
+ are not freed too quickly. [Bug 1077262]
+
+2005-04-08 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclCompCmds.c (TclCompileSwitchCmd): Rewritten to be able to
+ handle the other form of [switch] and generate slightly simpler (but
+ longer) code.
+
+2005-04-06 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/upvar.n, doc/unset.n, doc/tell.n, doc/tclvars.n, doc/subst.n:
+ * doc/seek.n, doc/scan.n, doc/regsub.n, doc/registry.n, doc/regexp.n:
+ * doc/read.n, doc/puts.n, doc/pkgMkIndex.n, doc/open.n, doc/lreplace.n:
+ * doc/lrange.n, doc/load.n, doc/llength.n, doc/linsert.n, doc/lindex.n:
+ * doc/lappend.n, doc/info.n, doc/gets.n, doc/format.n, doc/flush.n:
+ * doc/fileevent.n, doc/file.n, doc/fblocked.n, doc/close.n:
+ * doc/array.n, doc/Utf.3, doc/TraceVar.3, doc/StrMatch.3, doc/RegExp.3:
+ * doc/PrintDbl.3, doc/OpenTcp.3, doc/OpenFileChnl.3, doc/Object.3:
+ * doc/Notifier.3, doc/LinkVar.3, doc/IntObj.3, doc/Interp.3:
+ * doc/GetOpnFl.3, doc/GetIndex.3, doc/Eval.3, doc/CrtMathFnc.3:
+ * doc/CrtFileHdlr.3, doc/CrtCommand.3, doc/CrtChannel.3:
+ * doc/Backslash.3: Purge old .VS/.VE macro instances.
+
+ * tools/man2html2.tcl (IPmacro): Rewrote to understand what .IP really
+ is (.IP and .TP are really just two ways of doing the same thing).
+ Change below made this relevant.
+ * doc/re_syntax.n: Change some uses of .TP to .IP to work around bugs
+ in various *roff implementations. Also reworded the atom descriptions
+ slightly.
+
+2005-04-05 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclExecute.c (ExprSrandFunc): Replaced incursions into the
+ * generic/tclUtil.c (TclGetIntForIndex): intreps of numeric types with
+ simpler calls of Tcl_GetIntFromObj and Tcl_GetLongFromObj, now that
+ those routines are better behaved wrt shimmering. [Patch 1177219]
+
+2005-04-05 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclInt.h:
+ * generic/tclObj.c: Change in TclDecrRefCount and TclFreeObj, to speed
+ up the freeing of simple Tcl_Obj [Patch 1174551]
+
+2005-04-04 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c: small opts in obj handling
+
+2005-04-02 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclVar.c: converted a few function calls to macros.
+
+2005-04-01 Miguel Sofer <msofer@users.sf.net>
+
+ * doc/ListObj.3:
+ * generic/tclBasic.c:
+ * generic/tclCmdIL.c:
+ * generic/tclConfig.c:
+ * generic/tclExecute.c:
+ * generic/tclInt.decls:
+ * generic/tclInt.h:
+ * generic/tclIntDecls.h:
+ * generic/tclListObj.c:
+ * generic/tclStubInit.c:
+ * generic/tclVar.c: Changed the internal representation of lists to
+ (a) reduce the malloc/free calls at list creation (from 2 to 1), (b)
+ reduce the cost of handling empty lists (we now never create a list
+ internal rep for them), (c) allow refcounting of the list internal rep.
+ The latter permits insuring that the pointers returned by
+ Tcl_ListObjGetElements remain valid even if the object shimmers away
+ from its original list type. This is [Patch 1158008]
+
+ * generic/tclExecute.c:
+ * generic/tclInt.h:
+ * generic/tclObj.c:
+ * generic/tclStringObj.c:
+ (1) defined new internal macros for creating and setting frequently
+ used obj types (int,long, wideInt, double, string). Changed TEBC to use
+ eg 'TclNewIntObj(objPtr, i)' to avoid the function call in 'objPtr =
+ Tcl_NewIntObj(i)'
+ (2) ExecEnv now stores two Tcl_Obj* pointing to the constants "0" and
+ "1", for use by TEBC.
+ (3) slight reduction in cost of INST_START_CMD
+
+2005-03-31 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c (INST_JUMP_TRUE/FALSE): replaced "test and
+ branch" with "compute index into table"
+
+2005-03-30 Donal K. Fellows <donal.k.fellows@manchester.ac.uk>
+
+ * doc/FileSystem.3: Defined loadHandle argument. [Bug 1172401]
+
+2005-03-29 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tcl.m4, win/configure: do not require cygpath in macros to allow
+ msys alone as an alternative.
+
+2005-03-24 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCompile.h: Move the TclInterpReady() declaration from
+ * generic/tclInt.h: tclCompile.h to tclInt.h. Should have been done
+ as part of the 1115904 bug fix on 2005-03-18.
+
+ * generic/tclThreadTest.c: Stop providing the phony package
+ "Thread 1.0" when the [::testthread] command is defined. It's never
+ used by anything, and conflicts with loading the real "Thread" package.
+
+2005-03-18 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclCompCmds.c (TclCompileIncrCmd): Corrected checks for
+ immediate operand usage to permit leading space and sign characters.
+ Restores more efficient bytecode for [incr x -1] that got lost in the
+ CONST string reforms of Tcl 8.4. [Bug 1165671]
+
+ * generic/tclBasic.c (Tcl_EvalEx): Restored recursion limit
+ * generic/tclParse.c (TclSubstTokens): testing in nested command
+ * tests/basic.test (basic-46.4): substitutions within direct
+ * tests/parse.test (parse-19.*): script evaluation (Tcl_EvalEx)
+ that got lost in the parser reforms of Tcl 8.1. Added tests for correct
+ behavior. [Bug 1115904]
+
+2005-03-15 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclFileName.c:
+ * win/tclWinFile.c:
+ * tests/winFCMd.test: fix to 'file pathtype' and 'file norm' failures
+ on reserved filenames like 'COM1:', etc.
+
+2005-03-15 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * unix/tcl.m4: Updated the OpenBSD configuration and regenerated
+ * unix/configure: the configure script.
+
+2005-03-15 Kevin B. Kenny <kennykb@acm.org>
+
+ [kennykb-numerics-branch] Merged with HEAD.
+
+ * generic/tclBasic.c (many):
+ * generic/tclCompExpr.c (CompileMathFuncCall):
+ * generic/tclCompile.h:
+ * generic/tclExecute.c (many):
+ * generic/tclParseExpr.c (ParsePrimaryExpr):
+ * tests/compExpr-old.test:
+ * tests/compExpr.test:
+ * tests/compile.test:
+ * tests/expr-old.test:
+ * tests/expr.test:
+ * tests/for.test:
+ * tests/parseExpr.test: Initial implementation of TIP #232.
+
+ * generic/tclObj.c (Tcl_DbNewBignumObj): Fixed typo that broke
+ --enable-symbols=mem build
+ * tests/binary.test (binary-40.3, binary-40.6): Corrected tests to
+ allow NaN(7ffffffffffff).
+
+2005-03-14 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c: fixed INST_PUSH1's debugging code (wrong obj
+ ref passed to TRACE_WITH_OBJ).
+
+2005-03-14 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompile.c: fixed INST_RETURN's stack effect in
+ tclInstructionTable (-1 instead of -2)
+
+2005-03-10 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclCompCmds.c: removed debugging line
+
+2005-03-10 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclTrace.c (TclCheckInterpTraces): Corrected mistaken cast
+ of ClientData to (TraceCommandInfo *) when not warranted. Thanks to
+ Yuri Victorovich for the report. [Bug 1153871]
+ * generic/tcl.h: Moved flag values TCL_TRACE_ENTER_EXEC and
+ * generic/tclInt.h: TCL_TRACE_LEAVE_EXEC from public interface into
+ private. Should be used only by internal workings of execution traces.
+
+2005-03-09 Kevin B. Kenny <kennykb@acm.org>
+
+ [kennykb-numerics-branch] Merged from HEAD.
+
+ * doc/PrintDbl.3:
+ * doc/tclVars.n: Documented new semantics for tcl_precision.
+ * generic/tclExecute.c (Tcl_ExecuteByteCode): Removed the check for
+ division-by-zero on IEEE-754 machines.
+ * generic/tclUtil.c (Tcl_PrintDouble): Corrected bug where numbers in
+ the range [1e-4 .. 1.) were printed incorrectly.
+ * tests/compExpr-old.test (compExpr-old-11.13): Revised test case for
+ division by zero.
+ * tests/expr-old.test (expr-34.11, expr-34.12): Revised test cases for
+ overflow in pow() to deal with infinities.
+ * tests/expr.test (expr-11.13, expr-29.1, expr-29.2): Revised test case
+ for division by zero and for underflow on input conversions.
+ * tests/parseExpr.test (parseExpr-16.11): Revised test case for
+ overflow on input conversion.
+ * tests/string.test (string-6.38 deleted): Removed test case for
+ underflow on input conversion, which is no longer an error.
+ * tests/util.test (util-10.*): Added test case for the bug in tclUtil.c
+
+2005-03-08 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/makefile.vc: clarify necessary defined vars that can come from
+ MSVC or the Platform SDK.
+
+2005-03-07 Donal K. Fellows <dkf@users.sf.net>
+
+ * doc/string.n: Minor typo. [Bug 1158247]
+
+2005-03-07 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclExecute.c: new peephole optimisation for INST_PUSH1; fixed
+ the peephole opt in INST_POP so that it is not used when
+ TCL_COMPILE_DEBUG is defined.
+
+2005-03-04 Kevin B. Kenny <kennykb@acm.org>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclCmdMZ.c: Changed [scan] to treat out-of-range floating
+ point values as infinities and zeroes.
+ * generic/tclExecute.c: Changed [expr] to be permissive about
+ infinities, allowing them to propagate.
+ * generic/tclGet.c: Changed Tcl_GetDouble to be permissive about
+ over/underflow.
+ * generic/tclObj.c: Changed SetDoubleFromAny to be permissive about
+ over/underflow.
+ * generic/tclParseExpr.c: Made [expr] permissive about input numbers
+ out of range.
+
+2005-03-03 Kevin B. Kenny <kennykb@acm.org>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclInt.h:
+ * generic/tclStrToD.c (Tcl_DoubleDigits, TclFormatNaN):
+ * generic/tclUtil.c (Tcl_PrintDouble): Changed the signature of
+ TclDoubleDigits so that it accepts a pointer to the signum of the
+ argument, and returns the signum via that pointer. Added very hacky
+ code to handle IEEE signed zeroes in Tcl_DoubleDigits. (It can't be
+ done other than as a hack until C9x; C89 simply doesn't deal with the
+ concept of -0.0). Added output conversion of tagged NaN values.
+ * generic/tclBinary.c (FormatNumber): Changed to allow [binary format]
+ to handle NaN.
+ * tests/binary.test (binary-60.1): Added a quick-n-dirty test to make
+ sure that NaN's can be scanned and formatted.
+ * generic/tclParseExpr.c (GetLexeme, ParseMaxDoubleLength): Modified so
+ that tagged NaN (e.g., NaN(DEADBEEF)) can be recognized.
+
+2005-03-02 Kevin B. Kenny <kennykb@acm.org>
+
+ [kennykb-numerics-branch] Merged with HEAD as of 2005-02-23.
+
+ * generic/tclExecute.c: Broadened test for NaN to work on Windows.
+ * generic/tclInt.h:
+ * generic/tclStrToD.c (Tcl_DoubleDigits):
+ * generic/tclUtil.c (Tcl_PrintDouble, TclPrecTraceProc): Added
+ Tcl_DoubleDigits to format 'double' numbers with the minimum number of
+ significant digits to yield correct rounding. Modified tcl_precision
+ to accept 0 as a precision (meaning "minimum digits"), and made 0 the
+ default. [TIP #132]
+ * generic/tclObj.c: Made NaN's throw an error in Tcl_GetDoubleFromObj.
+ * unix/Makefile.in:
+ * win/Makefile.in:
+ * win/makefile.vc: Added libtommath/bn_mp_init_set.c to the build.
+ * libtommath/tommath.h (mp_iseven): Fixed a bug that caused zero to
+ test 'odd'.
+ * generic/tommath.h: Regenerated.
+ * tests/binary.test:
+ * tests/expr-old.test:
+ * tests/expr.test:
+ * tests/scan.test: Corrected a number of tests that depended on
+ tcl_precision, and removed the {eformat} condition from tests that no
+ longer require it.
+ * tests/util.test: Corrected a number of tests that depended on
+ tcl_precision, and removed the {eformat} condition from tests that no
+ longer require it. Added a series of tests for correct rounding in
+ Tcl_PrintDouble. [TIP #132].
+
+2005-03-01 David N. Welton <davidw@dedasys.com>
+
+ * doc/CrtSlave.3: Changed to Tcl_Object to Tcl_Obj in the man page.
+
+2005-02-24 Don Porter <dgp@users.sourceforge.net>
+
+ * library/tcltest/tcltest.tcl: Better use of [glob -types] to avoid
+ * tests/tcltest.test: failed attempts to [source] a directory, and
+ similar matters. Thanks to "mpettigr". [Bug 1119798]
+
+ * library/tcltest/pkgIndex.tcl: Bump to tcltest 2.2.8
+ * unix/Makefile.in:
+ * win/Makefile.in:
+
+2005-02-23 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/CrtChannel.3 (THREADACTIONPROC): Formatting fix. [Bug 1149605]
+
+2005-02-17 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/tclWinFCmd.c (TraverseWinTree): use wcslen on wchar, not
+ Tcl_UniCharLen.
+
+2005-02-16 Miguel Sofer <msofer@users.sf.net>
+
+ * doc/variable.n: fix for [Bug 1124160], variables are detected by
+ [info vars] but not by [info locals].
+
+2005-02-11 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/Makefile.in: remove SHLIB_LD_FLAGS (only for AIX, inlined into
+ * unix/tcl.m4: SHLIB_LD). Combine AIX-* and AIX-5 branches in
+ * unix/configure: SC_CONFIG_CFLAGS. Correct gcc builds for AIX-4+
+ and HP-UX-11. autoconf-2.59 gen'd.
+
+2005-02-11 Miguel Sofer <msofer@users.sf.net>
+
+ * tests/basic.test (basic-26.3): new test
+
+2005-02-10 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclBasic.c (Tcl_EvalObjEx):
+ * tests/basic.test (basic-26.2): preserve the arguments passed to TEOV
+ in the pure-list branch, in case the list shimmers away. Fix for [Bug
+ 1119369], reported by Peter MacDonald.
+
+2005-02-10 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclFileName.c: fix for test failures introduced on 2005-01-17
+ [Bug 1119092]
+
+2005-02-10 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/binary.n: Made the documentation of sign bit masking and [binary
+ scan] consistent. [Bug 1117017]
+
+2005-02-08 David N. Welton <davidw@dedasys.com>
+
+ * doc/CrtChannel.3: Typo: return->returns.
+
+2005-02-06 Kevin B. Kenny <kennykb@acm.org>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclStrToD.c (TclStrToD, SafeLdExp): Added code to manage the
+ FPU precision on gcc+x86. Enabled fast conversion of floats with small
+ exponents now that precision is correct.
+ * tests/expr.test: Corrected test for the smallest representible value
+ to the right IEEE values.
+
+2005-02-06 David N. Welton <davidw@dedasys.com>
+
+ * doc/Thread.3: One-word grammar fix.
+
+2005-02-05 David N. Welton <davidw@dedasys.com>
+
+ * doc/Thread.3: Fixed sentence describing flags for Tcl_CreateThread.
+
+ * doc/FileSystem.3: Cleaned up typo in Tcl_FSNewNativePath
+ documentation.
+
+ * generic/tclPathObj.c: Cleaned up typo in comment.
+
+2005-02-03 Kevin B. Kenny <kennykb@acm.org>
+
+ [kennykb-numerics-branch]
+
+ * generic/tclStrToD.c (TclStrToD, RefineResult, SafeLdExp): Added code
+ to ensure that 'ldexp' is never called with a value that will underflow
+ * tests/expr.test: Added tests for the smallest representible value,
+ and rounding between it and zero. (The tests reflect current
+ behaviour; plan is to change the specification of Tcl so that input
+ conversion of doubles underflows silently.)
+
+2005-02-02 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * generic/tclProc.c (TclInitCompiledLocals): Add check for type of the
+ framePtr->procPtr->bodyPtr passed to TclInitCompiledLocals and panic if
+ it is not the correct type. If the body of the proc is not of the
+ compiled byte code type then the code will crash. This was discovered
+ while tracking down a crash in Itcl, that crash is fixed by Itcl patch
+ 1115085.
+
+2005-02-01 Kevin B. Kenny <kennykb@acm.org>
+
+ [kennykb-numerics-branch] Merged with HEAD as of today.
+
+ * generic/tclInt.decls: Changed numbers of new stubs to resolve a
+ conflict.
+ * generic/tclInt.h: Added new TclStrToD routine that replaces the
+ native 'strtod' throughout Tcl.
+ * generic/tclCmdMZ (Tcl_StringObjCmd):
+ * generic/tclGet.c (Tcl_GetDouble):
+ * generic/tclObj.c (SetBooleanFromAny, SetDoubleFromAny):
+ * generic/tclParseExpr.c (GetLexeme):
+ * generic/tclScan.c (Tcl_ScanObjCmd): Replaced all uses of the native
+ 'strtod' with a TclStrToD routine that performs correct rounding and
+ handles denormals.
+ * generic/tclStrToD.c: (new file)
+ New scanning function for extracting 'double' from a string that rounds
+ correctly, and handles denormals and infinities.
+ * unix/Makefile.in:
+ * win/Makefile.in:
+ * win/makefile.vc:
+ Added tclStrToD.c and the tommath routines that support it.
+
+ These changes represent a partial implementation of TIP #132. Output
+ conversion of floating point numbers, and proper handling of infinities
+ within expressions, still need to be addressed.
+
+2005-02-01 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclExecute.c (TclCompEvalObj): Removed stray statement left
+ behind in prior code reorganization.
+
+2005-01-31 Don Porter <dgp@users.sourceforge.net>
+
+ * unix/configure: autoconf-2.57
+
+2005-01-30 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/configure.in: Restored two double-evals that were removed in the
+ DBGX purge; these are still needed on some platforms to account for
+ TCL_TRIM_DOTS. [Bug 1112654]
+
+ * unix/configure: NOT REGENERATED: only have autoconf 2.59 here, need
+ to find someone with autoconf 2.57.
+
+2005-01-28 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * unix/configure, unix/tcl.m4: add solaris 64-bit gcc build support.
+ [Bug 1021871]
+
+2005-01-28 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/expr-old.test (expr-old-37.2): Added test for [Bug 1109484]
+
+2005-01-27 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * generic/tclBasic.c (Tcl_ExprBoolean, Tcl_ExprDouble)
+ (Tcl_ExprLong): Fix to recognize Tcl_WideInt type. [Bug 1109484]
+
+2005-01-26 Andreas Kupries <andreask@activestate.com>
+
+ TIP#218 IMPLEMENTATION
+
+ * generic/tclDecls.h: Regenerated from tcl.decls.
+ * generic/tclStubInit.c:
+
+ * doc/CrtChannel.3: Documentation of extended API,
+ * generic/tcl.decls: extended testsuite, and
+ * generic/tcl.h: implementation. Removal of old
+ * generic/tclIO.c: driver-specific TclpCut/Splice
+ * generic/tclInt.h: functions. Replaced with generic
+ * tests/io.test: thread-action calls through the
+ * unix/tclUnixChan.c: new hooks. Update of all builtin
+ * unix/tclUnixPipe.c: channel drivers to version 4.
+ * unix/tclUnixSock.c: Windows drivers extended to
+ * win/tclWinChan.c: manage thread state in a thread
+ * win/tclWinConsole.c: action handler.
+ * win/tclWinPipe.c:
+ * win/tclWinSerial.c:
+ * win/tclWinSock.c:
+
+2005-01-25 Don Porter <dgp@users.sourceforge.net>
+
+ * library/auto.tcl: Updated [auto_reset] to clear auto-loaded
+ commands in namespaces other than :: and to clear auto-loaded commands
+ that do not happen to be procs. [Bug 1101670]
+ ***POTENTIAL INCOMPATIBILITY***
+
+2005-01-25 Daniel Steffen <das@users.sourceforge.net>
+
+ * unix/tcl.m4 (Darwin): fixed bug with static build linking to dynamic
+ library in /usr/lib etc instead of linking to static library earlier in
+ search path. [Bug 956908] Removed obsolete references to Rhapsody.
+ * unix/configure: autoconf-2.57
+
+2005-01-21 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tclStubInit.c: Regenerated the stubs support code from the
+ * generic/tclDecls.h: modified tcl.decls (TIP #233, see below).
+
+ * doc/GetTime.3: Implemented TIP #233, i.e. the
+ * generic/tcl.decls: 'Virtualization of Tcl's Sense of Time'.
+ * generic/tcl.h: Declared, implemented, and documented the
+ * generic/tclInt.h: specified new API functions. Moved the
+ * unix/tclUnixEvent.c: native (OS) access to time information
+ * unix/tclUnixNotfy.c: into standard handler functions. Inserted
+ * unix/tclUnixTime.c: hooks calling on the handlers where native
+ * win/tclWinNotify.c: access was done before, and where scaling
+ * win/tclWinTime.c: between domains (real/virtual) is required.
+
+2005-01-21 Andreas Kupries <andreask@activestate.com>
+
+ * generic/tclThread.c: Typo police. Fixed some nits
+ * generic/tclCmdAH.c: in header comments of functions.
+ * generic/tclBasic.c: (Missing --).
+ * generic/tclFileName.c:
+
+2005-01-21 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/FileSystem.3: Add missing ARGUMENTS section definitions for
+ arguments to Tcl_FSLink. [Bug 1106272]
+
+2005-01-21 Kevin B. Kenny <kennykb@acm.org>
+
+ [kennykb-numerics-branch]
+
+ * unix/Makefile.in: Updated Makefile to build libtommath on Unix as
+ well as Windows. [Bug 1106865]
+
+ * generic/tclTestObj.c (TestbignumobjCmd): Silenced a compiler warning
+ about a mismatched 'const'.
+
+2005-01-20 Kevin B. Kenny <kennykb@acm.org>
+
+ [kennykb-numerics-branch] Development checkpoint.
+
+ * compat/strtoll.c: Reverted to HEAD.
+ * compat/strtoull.c:
+ * doc/Ensemble.3:
+ * generic/tclBasic.c:
+ * generic/tclCmdIL.c:
+ * generic/tclNamesp.c:
+ * generic/tclPathObj.c:
+ * generic/tclPort.h:
+ * unix/configure:
+ * unix/configure.in:
+ * unix/tcl.m4:
+ * win/configure:
+ * win/configure.in:
+ * win/rules.vc:
+ * win/tcl.m4:
+
+ * generic/tcl.h: Added declarations for bignum types, and for a
+ 'bignumValue' in the Tcl_Obj structure.
+ * generic/tclInt.h: Added declarations of interface procedures for
+ memory allocation in libtommath.
+
+ * generic/tcl.decls: Added new interface to bignum objects.
+ * generic/tclInt.decls: Added internal stubs for bignum routines used
+ by the test code in tclTestObj.c.
+
+ * generic/tclDecls/h: Regen.
+ * generic/tclIntDecls.h:
+ * generic/tclStubInit.h:
+
+ * tools/fix_tommath_h.tcl: (New file) Script to edit
+ libtommath/tommath.h and produce generic/tommath.h so that storage
+ classes, allocation routines, and data types conform to Tcl's
+ conventions.
+ * generic/tommath.h: (New file) Generated by the above.
+
+ * generic/tclTomMath.h: (New file) Additional declarations to be
+ included in tommath.h when building Tcl.
+
+ * generic/tclTomMathInterface.c: (New file) Small 'glue' routines
+ adapting tommath's API to Tcl.
+
+ * libtommath/bn_fast_s_mp_mul_digs.c:
+ * libtommath/bn_mp_mul_d.c:
+ * libtommath/bn_mp_read_radix.c:
+ * libtommath/tommath.h: Applied suggested changes from Tom St Denis
+ that correct an off-by-one error in single-digit multiplication
+ (leading to a pointer smash if uncorrected) and change the string
+ argument to 'mp_read_radix' from 'char*' to 'const char*'.
+
+ * libtommath/bn_mp_radix_size.c: Local patch to ensure that sufficient
+ memory is requested even if the number has a single digit.
+
+ * libtommath/bn_mp_read_radix.c: Local patch to return MP_VAL if the
+ input string contains an invalid character.
+
+ * generic/tclObj.c: Added accessor functions for bignums.
+ * generic/tclTestObj.c: Added a 'testbignumobj' command to exercise the
+ accessor functions for bignums.
+
+ * win/Makefile.in: Added rules for making libtommath.
+
+2005-01-19 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ TIP#235 IMPLEMENTATION
+
+ * doc/Ensemble.3: Documentation for the new public API.
+ * generic/tclNamesp.c (Tcl_CreateEnsemble,...): Rename of
+ * generic/tcl.decls: existing API into TIPped form.
+
+2005-01-19 Mo DeJong <mdejong@users.sourceforge.net>
+
+ * win/tclWinChan.c (FileCloseProc): Invoke TclpCutFileChannel() to
+ remove a FileInfo from the thread local list before deallocating it.
+ This should have been done via an earlier call to Tcl_CutChannel, but I
+ was running into a crash in the next call to Tcl_CutChannel during the
+ I/O finalization stage.
+
+2005-01-18 Kevin Kenny <kennykb@acm.org>
+
+ * library/tzdata/GMT+0:
+ * library/tzdata/GMT-0:
+ * library/tzdata/GMT0:
+ * library/tzdata/Greenwich:
+ * library/tzdata/Navajo:
+ * library/tzdata/Universal:
+ * library/tzdata/Zulu:
+ * library/tzdata/America/Asuncion:
+ * library/tzdata/America/Rosario:
+ * library/tzdata/Asia/Jerusalem:
+ * library/tzdata/Brazil/Acre:
+ Routine update per Olson's tzdata2005c. Removed links to links
+ (Greenwich in several aliases; Navajo; Acre). Updated Paraguayan DST
+ rules and "best guess" at this year's Israeli rules.
+
+2005-01-17 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * generic/tclFileName.c: fix for glob failure on Windows shares [Bug
+ 1100542].
+
+ * doc/pkgMkIndex.n: added documentation that 'pkg_mkIndex -lazy' is not
+ a good idea. [Bug 1101678]
+
+2005-01-14 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * tests/compile.test (compile-17.1): Document known issue with binding
+ time of compiled command interpretations in [expr].
+
+ * generic/tclIOUtil.c (TclFSFileAttrIndex): New helper function so that
+ we don't need to hard-code attribute indexes. [Bug 1100671]
+
+2005-01-13 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/string.n: Removed the term 'set' from the documentation of the
+ [string trim] commands, as it caused confusion.
+
+2005-01-12 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * unix/tcl.m4 (SC_PATH_{TCL,TK}CONFIG): Added code to detect the case
+ when the --with-tcl/--with-tk arguments point to the config scripts
+ themselves and not their directory. If this is the case, they now
+ complain but keep working. [FRQ 951247]
+ * unix/configure: autoconf-2.57
+
+2005-01-10 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/Makefile.in, unix/configure.in, unix/tcl.m4,
+ * unix/tclConfig.sh.in, unix/dltest/Makefile.in:
+ Remove ${DBGX}, ${TCL_DBGX} from Tcl build system [Patch 1081595].
+ * unix/configure: regenerated
+
+2005-01-10 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * unix/tclUnixFCmd.c (TclUnixCopyFile): Convert u_int to unsigned to
+ make clashes with types in standard C headers less of a problem. [Bug
+ 1098829]
+
+2005-01-09 Joe English <jenglish@users.sourceforge.net>
+
+ * unix/tclUnixThrd.c, unix/tclUnixPort.h: Remove readdir_r() and
+ related #ifdeffery (see [Bug 1095909]).
+ * unix/tcl.m4, unix/tclConfig.h.in: Don't check for HAVE_READDIR_R.
+ * unix/configure: Regenerated.
+
+2005-01-06 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * library/http/http.tcl (http::mapReply): Significant performance
+ enhancement by using [string map] instead of [regsub]/[subst], and
+ update version requirement to Tcl8.4. [Bug 1020491]
+
+2005-01-05 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * doc/lsearch.n, doc/re_syntax.n: Convert to other form of emacs mode
+ control comment to prevent problems with old versions of man. [Bug
+ 1085127]
+
+2005-01-05 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * tests/winDde.test: Fixed broken test result.
+
+2005-01-05 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+
+ * generic/tclInt.h, generic/tclPort.h: Move the #include of tclConfig.h
+ *first* before any reference to tcl.h so that the build configuration
+ is loaded before the first reference to any system headers. Issue
+ reported by Art Haas on tcl-core.
+
+2005-01-04 Don Porter <dgp@users.sourceforge.net>
+
+ * tests/fCmd.test (fCmd-18.10): Added notNetworkFilesystem constraint.
+ [Bug 456665]
+
+ ******************************************************************
+ *** CHANGELOG ENTRIES FOR 2004 IN "ChangeLog.2004" ***
+ *** CHANGELOG ENTRIES FOR 2003 IN "ChangeLog.2003" ***
+ *** CHANGELOG ENTRIES FOR 2002 IN "ChangeLog.2002" ***
+ *** CHANGELOG ENTRIES FOR 2001 IN "ChangeLog.2001" ***
+ *** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000" ***
+ *** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" ***
+ ******************************************************************
diff --git a/README b/README
index 181b0a1..de3e9e4 100644
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
README: Tcl
- This is the Tcl 8.4.19 source distribution.
+ This is the Tcl 8.5.10 source distribution.
http://tcl.sourceforge.net/
You can get any source release of Tcl from the file distributions
link at the above URL.
@@ -22,7 +22,7 @@ Contents
Tcl provides a powerful platform for creating integration applications that
tie together diverse applications, protocols, devices, and frameworks.
When paired with the Tk toolkit, Tcl provides the fastest and most powerful
-way to create GUI applications that run on PCs, Unix, and the Macintosh.
+way to create GUI applications that run on PCs, Unix, and Mac OS X.
Tcl can also be used for a variety of web-related tasks and for creating
powerful command languages for applications.
@@ -45,7 +45,7 @@ and selling it either in whole or in part. See the file
Extensive documentation is available at our website.
The home page for this release, including new features, is
- http://www.tcl.tk/software/tcltk/8.4.html
+ http://www.tcl.tk/software/tcltk/8.5.html
Detailed release notes can be found at the file distributions page
by clicking on the relevant version.
@@ -57,9 +57,9 @@ Information about Tcl itself can be found at
There have been many Tcl books on the market. Many are mentioned in the Wiki:
http://wiki.tcl.tk/_/ref?N=25206
-To view the complete set of reference manual entries for Tcl 8.4 online,
+To view the complete set of reference manual entries for Tcl 8.5 online,
visit the URL:
- http://www.tcl.tk/man/tcl8.4/
+ http://www.tcl.tk/man/tcl8.5/
2a. Unix Documentation
----------------------
@@ -118,8 +118,8 @@ information about Tcl, Tk, and related applications. The newsgroup is a
great place to ask general information questions. For bug reports, please
see the "Support and bug fixes" section below.
-6. The Tcler's Wiki
--------------------
+6. Tcl'ers Wiki
+---------------
A Wiki-based open community site covering all aspects of Tcl/Tk is at:
@@ -167,7 +167,7 @@ The Tcl community is too large for us to provide much individual support
for users. If you need help we suggest that you post questions to
comp.lang.tcl. We read the newsgroup and will attempt to answer esoteric
questions for which no one else is likely to know the answer. In addition,
-see the following page on the Wiki for links to other organizations that offer
+see the following Web site for links to other organizations that offer
Tcl/Tk training:
http://wiki.tcl.tk/training
diff --git a/changes b/changes
index f973758..23efc47 100644
--- a/changes
+++ b/changes
@@ -4216,7 +4216,7 @@ input lines. (redman)
This is used on Windows to avoid the various problems that people
have been seeing where the system hangs when tclsh is running
outside of the event loop. As part of this, renamed
-TcapAlertNotifier back to Tcl_AlertNotifier since it is public.
+TclpAlertNotifier back to Tcl_AlertNotifier since it is public.
(stanton)
3/23/99 (feature change) Test suite now uses "tcltest" namespace to
@@ -5856,7 +5856,7 @@ in the 8.4.3 release.
2003-07-16 (bug fix)[756791] corrected assumption that Tcl_Free == free
-2003-07-16 (feature enhancement) -DTCL_UTF_MAX=6 compile option forces
+2003-07-16 (feature enhancement) -DTCL_UTF_MAX=6 compile option forces
internal UCS-4 representation of Unicode (default is recommended UCS-2).
2003-07-16 (bug fix)[767578] 64-bit corrections in thread notifier.
@@ -5962,36 +5962,149 @@ various odd regexp "can't happen" bugs.
--- Released 8.4.6, March 1, 2004 --- See ChangeLog for details ---
+Changes to 8.5a1 include all changes to the 8.4 line through 8.4.6,
+plus the following, which focuses on the high-level feature changes
+in this changeset (new minor version) rather than bug fixes:
+
+ * refactored IO code to split FS path code into generic/tclPathObj.c
+ and generic/tclFileSystem.h
+
+ * refactored trace code into generic/tclTrace.c
+
+ * configure scripts now require autoconf 2.57 for regeneration
+
+ * updated runtime library scripts to use newer Tcl code features
+ (like replacing regsub with string map)
+
+ * improve robustness of tcltest test suite across environments
+
+ * changed the bytecode evaluation-stack addressing mode, from array-style
+ to pointer-style; the catch stack and evaluation stack are now
+ contiguous in memory
+
+ * switch command is now byte-compiled
+
+ * enhanced checking in 'file' command for Windows NT file permissions
+
+ * [TIP #57] new 'lassign' command (adopted from TclX)
+
+ * [TIP #75] switch -regexp now provides submatch info
+
+ * [TIP #90] extended 'catch' and 'return' to enable creation of procs
+ that are a true replacement for 'return'
+
+ * [TIP #100] new 'unload' command (can unload DLLs loaded via 'load',
+ requires the extension writer to support it)
+
+ * [TIP #111] new 'dict' command. Several commands have been updated
+ to handle the list form of dicts implicitly at the C level where
+ only lists were previously accepted
+
+ * [TIP #112] 'namespace ensemble' command addition allows for ensembles
+ that build on the namespace abstraction
+
+ * [TIP #118] file attributes -readonly option for unices that support
+ chflags(), support Mac Classic attribute options on OS X, add
+ -rsrclength for OS X, enhance file copy on OS X to copy finder
+ attributes and resource forks transparently
+
+ * [TIP #120] enable dde in safe interpreters
+ * [TIP #130] enable unique dde server names on Windows
+ * [TIP #135] change dde servername -exact option to -force
+=> dde 1.3
+
+ * [TIP #121] new Tcl_SetExitProc C API to control application shutdown
+
+ * [TIP #123] expr ** exponentiation operator
+
+ * [TIP #124] 'clock clicks -milliseconds' now returns a wide integer and a
+ new 'clock clicks -microseconds' returns a wide integer, representing
+ the number of microseconds, both since the Posix epoch
+
+ * [TIP #127] added 'lsearch -index' option
+
+ * [TIP #136] added 'lrepeat' command
+
+ * [TIP #137/151] Add -encoding option to 'source' command and main tclsh
+ executable.
+ *** POTENTIAL INCOMPATIBILITY ***
+ For Tcl embedders that build on Tcl_Main() and make use of Tcl_Main's
+ former ability to pass a leading "-encoding" option to interactive shell
+ operations, this will now be consumed by Tcl.
+
+ * [TIP #138] New TCL_HASH_KEY_SYSTEM_HASH option for Tcl hash tables
+
+ * [TIP #139] documented portions of Tcl's namespace C APIs
+
+ * [TIP #148] correct [list]-quoting of the '#' character
+ *** POTENTIAL INCOMPATIBILITY ***
+ For scripts that assume a particular (buggy) string rep for lists.
+
+ * [TIP #156] add "root locale" to msgcat
+=> msgcat 1.4
+
+ * [TIP #157] leading {expand} syntax on words to cause argument expansion.
+ This is a safer/cleaner alternative to the use of 'eval'.
+
+--- Released 8.5a1, March 3, 2004 --- See ChangeLog for details ---
+
+2004-03-04 (new feature) registry package is [unload]able (thoyts)
+=> registry 1.1.4
+
2004-03-08 (bug fix)[910525] [glob -path] in root directory (darley)
-2004-03-15 (bug fix)[916795] syntax error -> compiler segfault (sofer,porter)
+2004-03-12 (new feature)[TIP 163] [dict merge] (english, fellows)
+
+2004-03-18 (platform support) support for Mac Classic removed (steffen)
-2004-03-29 (bug fix)[920667] install into any Unicode path on Win (hobbs)
+2004-03-28 (bug fix)[925121] corrected segfault in bc compiler (sofer)
+
+2004-03-30 (bug fix)[495830,729692] bytecode execution checks
+each command/interp validity before executing. (sofer)
2004-03-31 (bug fix)[811457] support translation to "" (porter)
2004-03-31 (bug fix)[811461] ignore locales with no "language" part (porter)
-=> msgcat 1.3.2
+=> msgcat 1.4.1
+
+2004-04-01 (bug fix) make [glob -type d -dir . *] work across VFS boundary
+
+2004-04-06 (clean up) refactored Tcl header file #include order. Might
+create need for changes in extensions that #include private headers.
+Changed source code files should work with older Tcl as well. See ChangeLog.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2004-04-07 (bug fix)[920667] install into any Unicode path on Win (hobbs)
2004-04-07 (platform support) properly substitute more values in Windows
tclConfig.sh (hobbs)
2004-04-23 (bug fix)[930851] reset channel EOF when eofchar changes (kupries)
+2004-04-28 (bug fix)[600812][TIP 184] [upvar 0 scalar array(foo)] raises error
+
2004-05-03 (bug fix)[947070] stack overflow prevention on Win (kenny)
2004-05-03 (bug fix)[868853] fix leak in [fconfigure $serial -xchar] (cassoff)
-2004-04-05 (bug fix)[928353,929892,928808,947440,948177] test fixes: OSX
-(abner)
-
-2004-05-04 (bug fix) crash: [cd] w/ volumerelative $HOME (hobbs)
+2004-05 (bug fix)[928353,929892,928808,947440,948177] test fixes: OSX (abner)
2004-05-05 (bug fix)[794839] socket connect error -> r/w fileevents
(gravereaux)
-2004-05-14 (bug fix)[940278,922848] [clock] notices $::env(TZ) changes,
+2004-05-07 (bug fix)[949905] corrected utf-8 encoding of \u0000 on I/O (max)
+
+2004-05-13 (new feature)[TIP 129] [binary scan tnmrRqQ] (markus, fellows)
+
+2004-05-13 (new feature)[TIP 142] [interp limit] (fellows)
+
+2004-05-14 (bug fix)[940278,922848] [clock] notices $::env(TZ) changes,
gmt works on all platforms. (kenny, welton, glessner)
+2004-05-16 (feature rewrite) bytecode execution of {expand} changed
+ *** POTENTIAL INCOMPATIBILITY with prior 8.5a releases ***
+
+2004-05-18 (platform support) makefile.vc now generates tclConfig.sh (thoyts)
+
2004-05-18 (bug fix)[500285,500389,852944] [clock %G %V] ISO8601 week numbers
(kenny)
@@ -6005,24 +6118,34 @@ gmt works on all platforms. (kenny, welton, glessner)
2004-05-26 (bug fix)[960926] file count doubled when -singleproc 1 (porter)
=> tcltest 2.2.6
-2004-05-27 (bug fix)[949905] corrected utf-8 encoding of \u0000 on I/O (max)
+2004-05-26 (bug fix)[874058] improved build configuration on 64-bit systems.
+Corrects Tcl_StatBuf definition issues. (hobbs)
+
+2004-05-30 (platform support) Win: allow signed short exit codes (gravereaux)
2004-06-05 (bug fix)[976722] hi-res clock fixes: Win
(godfrey, suchenwirth, kenny)
-
2004-06-10 (bug fix)[932314] bad return values from Tcl_FSChdir() (vasiljevic)
-2004-06-14 (bug fix) correct dde hangs w/non-responsive apps (thoyts)
-=> dde 1.2.3
+2004-06-18 (platform support) regonize more unix locales (huang)
+
+2004-06-18 (bug fix) prevent stack overflow from long free() chains (fellows)
2004-06-21 (platform support) exceptions w/ gcc -O3 on Win (dejong)
+2004-06-23 (feature rewrite)[976496] thread local storage done with hash
+tables to avoid system limits (mistachkin)
+
2004-06-29 (bug fix)[981733] SafeBase global pollution (fellows)
+2004-06-30 (new feature)[TIP 188] [string is wideinteger] (kenny)
+
2004-07-02 (new feature)[TIP 202] pipe redirection 2>@1 (hobbs)
2004-07-03 (bug fix)[908375] round() wide integer support (lavana, sofer)
+2004-07-07 (bug fix)[458361] shimmer of single-word scripts suppressed (sofer)
+
2004-07-15 (bug fix)[770053] crash in thread finalize of notifier (vasiljevic)
2004-07-15 (bug fix)[990453] plug mutex leaks on reinit
@@ -6033,16 +6156,13 @@ gmt works on all platforms. (kenny, welton, glessner)
2004-07-19 (bug fix)[987967] improved self-init of mutexes on Win (vasiljevic)
-2004-07-19 (bug fix)[874058] improved build configuration on 64-bit systems.
-Corrects Tcl_StatBuf definition issues. (hobbs)
-
2004-07-20 (bug fix) pure Darwin/CFLite support (steffen)
2004-07-20 (bug fix)[736426] plug leaky allocator reinit (mistachkin, kenny)
---- Released 8.4.7, July 26, 2004 --- See ChangeLog for details ---
+2004-07-30 (bug fix)[999084] no deadlock in re-entrant Tcl_Finalize (porter)
-2004-07-28 (bug fix)[999084] no deadlock in re-entrant Tcl_Finalize (porter)
+2004-08-02 (new feature)[TIP 207] [interp invokehidden -namespace] (porter)
2004-08-10 (bug fix) thread IDs on 64-bit systems (ratcliff,vasiljevic)
@@ -6051,98 +6171,215 @@ Corrects Tcl_StatBuf definition issues. (hobbs)
2004-08-16 (bug fix)[1008314] Tcl_SetVar TCL_LIST_ELEMENT (sofer,porter)
+2004-08-18 (new feature)[TIP 173,209] complete [clock] rewrite (kenny)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2004-08-18 (new feature)[TIP 189] package loading for Tcl Modules (kupries)
+
2004-08-19 (bug fix)[1011860] [scan %ld] fix on LP64 (fellows,porter)
+2004-08-23 (bug fix)[695441] extend [tcl_findLibrary] search path to include
+ $::auto_path and [pkgconfig get scriptdir,runtime] (porter)
+
+2004-08-27 (platform support) TCL_MODULE_PATH values for Mac OSX (steffen)
+
+2004-08-27 (bug fix)[1017022] recognize imported ensembles (fellows)
+
2004-08-30 (bug fix) [string map $x $x] crash (fellows)
2004-09-01 (bug fix)[1020445] WIN64 support (hobbs)
+2004-09-03 (bug fix)[1020538] crash in [file copy] (violi,fellows)
+
2004-09-07 (bug fix)[1016167] [after] overwrites its imports (kenny)
2004-09-08 (bug fix) fixed [clock format 0 -format %k] (kenny)
2004-09-09 (bug fix)[560297] fixed broken [namespace forget] logic (porter)
-2004-09-09 (bug fix)[1017299] fixed [namespace import] cycle prevention (porter)
+2004-09-09 (bug fix)[1017299] fixed [namespace import] cycle prevention
+(porter)
2004-09-10 (performance) $x[set x {}] is now fast [K $x [set x {}]] (sofer)
-2004-09-10 (bug fix)[868489] better control over int <-> wideInt (fellows,kenny)
+2004-09-10 (bug fix)[868489] better control over int <-> wideInt
+(fellows,kenny)
2004-09-10 (bug fix)[1025359] POSIX errorCode from wide seeks (kupries,fellows)
+2004-09-10 (bug fix)[707104,1026493] fix [rename] of [interp alias] (porter)
+
2004-09-18 (bug fix)[868467] fix [expr 5>>32] => 0, not 5 (hintermayer,fellows)
-2004-09-23 (bug fix)[1016726] fix `make clean` in static config (leitgeb,dejong)
+2004-09-21 (bug fix) consistent errorinfo from [namespace eval x error foo bar]
+ and [namespace eval c {error foo bar}] (porter)
+
+2004-09-22 (feature change) syntax errors not reported at compile time;
+ deferred to runtime. Support [return -errorline]. (porter)
+
+2004-09-23 (bug fix)[1016726] fix `make clean` in static config
+(leitgeb,dejong)
-2004-09-29 (bug fix)[1036649] syntax error in [subst] => buffer overflow (sofer)
+2004-09-22 (feature change) report all compile errors at runtime (porter)
+
+2004-09-29 (bug fix)[1036649] syntax error in [subst] => buffer overflow
+(sofer)
2004-09-30 (bug fix)[1038021] save/restore error state: var traces (porter)
-2004-10-08 (bug fix)[954263] case insensitive [file exec] for Win (hobbs,darley)
+2004-10-01 (performance) stackframe level values in internal reps (fellows)
+
+2004-10-01 (feature change)[1037235] auto-create [dict] key paths (fellows)
+
+2004-10-04 (bug fix)[884830] eq and ne parse in expr (fellows)
+
+2004-10-05 (reform) errorInfo, errorCode management (porter)
+ *** POTENTIAL INCOMPATIBILITY for traces on those vars ***
+
+2004-10-06 (feature change)[1041072] re-bless and enhance Tcl_AppendResult
+(dkf)
+
+2004-10-06 (reform) more robust interp result appends (porter)
+=> dde 1.3.1
+=> registry 1.1.5
+
+2004-10-06 (reform) re-write of [glob] guts (fellows)
+
+2004-10-07 (reform)[925620] improved platform split of VFS code (darley)
+
+2004-10-08 (new feature)[TIP 201] "in" and "ni" expr operators (fellows)
+
+2004-10-08 (new feature)[TIP 212] [dict update]; [dict with] (fellows)
+
+2004-10-08 (bug fix)[954263] case insensitive [file exec] for Win
+(hobbs,darley)
2004-10-14 (performance) [info commands/globals/procs/vars $pattern] faster
- when $pattern is trivial (fellows)
+ when $pattern is trivial (fellows)
+
+2004-10-14 (new feature)[TIP 217] [lsort -indices] (salsman,fellows)
+
+2004-10-24 (reform) replaced bit flag values with macros for Var handling
+ *** POTENTIAL INCOMPATIBILITY for accesses to Var internals ***
+
+2004-10-26 (new feature)[1054370] install msgcat, http, tcltest as TM's
+(porter)
+
+2004-10-26 (bug fix)[767676] negative PIDs with pipes (giese,gravereaux)
+
+2004-10-27 (bug fix)[731778] stop critical section leaks
+(mistachkin,gravereaux)
+
+2004-10-27 (bug fix)[926088] -load option to find tested packages (gravereaux)
2004-10-28 (bug fix)[1030548] restore the --enable-symbols --enable-threads
- build on Win (mistachkin,kenny,kupries)
+build on Win (mistachkin,kenny,kupries)
2004-10-29 (bug fix)[1055673] fix command line syntax error message (porter)
=> tcltest 2.2.7
+2004-10-30 (bug fix)[926106] fix [file mtime] DST anomaly (kenny)
+
2004-10-31 (bug fix)[1057461] fix [info globals ::varName] (fellows)
2004-11-02 (bug fix)[761471] fix [expr {NaN == NaN}] (sofer)
2004-11-02 (bug fix)[1017151] misleading errorInfo after tests (seeger,porter)
+2004-11-03 (bug fix)[527164] preserve errorinfo from var traces (porter)
+
+2004-11-08 (bug fix){947693] Made -blocking option of channel during [close]
+consistent on Windows with Unix (gravereaux)
+ *** POTENTIAL INCOMPATIBILITY ***
+
2004-11-11 (bug fix)[1034337] recursive file delete, MacOSX (steffen)
+2004-11-12 (new feature)[TIP 221] [interp bgerror] (porter)
+
+2004-11-12 (new feature)[TIP 226] Tcl_(Save|Restore|Discard)InterpState
+(porter)
+
+2004-11-12 (new feature)[TIP 227] Tcl_(Get|Set)ReturnOptions (porter)
+
2004-11-12 (bug fix)[1004065] stop crash when TCL_UTF_MAX==6 (hobbs,porter)
2004-11-15 (bug fix)[10653678] [trace variable],[trace remove] interop (porter)
-2004-11-16 (bug fix)[695441] [tcl_findLibrary] search $::auto_path too (porter)
-
2004-11-16 (bug fix)[1067709] crash in [fconfigure -ttycontrol] (hobbs)
2004-11-18 (new feature) configure options --enable-man-suffix (max)
-Documentation improvements [759545,1058446,1062647,1065732,etc.]
-Test suite expansion [1036649,1001997,etc.]
+2004-11-22 (bug fix)[1030465] Improve HAVE_TYPE_OFF64_T check (dejong)
---- Released 8.4.8, November 18, 2004 --- See ChangeLog for details ---
+2004-11-22 (bug fix)[1043129] Fixed the treatment of backslashes in file
+join on Windows (darley)
-2004-11-22 (bug fix)[1030465] Improve HAVE_TYPE_OFF64_T check (dejong)
+2004-11-22 (bug fix)[976438] Move init.tcl search path construction to
+tclInit (porter)
-2004-11-23 (bug fix)[1072654] Fixed segfault in info vars trivial
+2004-11-24 (bug fix)[1072654] Fixed segfault in info vars trivial
matching branch (new in 8.4.8) (porter)
-2004-11-23 (bug fix)[1043129] Fixed the treatment of backslashes in file
-join on Windows (darley)
-
2004-11-24 (bug fix)[1001325, 1071701] Fixed readdir_r detection and usage
(dejong, kenny, porter)
2004-11-24 (bug fix)[1071807] Fixed all uses of 'select' to use standard
macros rather than older bit-whacking style (kenny)
+2004-11-26 (bug fix)[1073524] Simplify the code to check for correctness of
+strstr, strtoul and strtod on unix (fellows)
+
2004-11-26 (bug fix)[1072136] Remove file normalize on tcl_findLibrary
search path uniqification added in 8.4.8 (porter)
+2004-11-30 (bug fix)[976520] Rework startup/initialization of the Tcl
+library, encoding search initialization, and Tcl_FindExecutable structure.
+[tclInit] no longer driven by the value of $::tcl_libPath (TCLLIBPATH).
+(porter)
+ *** POTENTIAL INCOMPATIBILITY : makes encoding names case sensitive
+ on Windows, where they have been case insensitive ***
+
2004-12-02 (bug fix)[1074671] Ensure tilde paths are not returned specially
by 'glob' (darley)
---- Released 8.4.9, December 6, 2004 --- See ChangeLog for details ---
+Doc improvements [759545,926590,935853,1017072,1018486,1022527,1027849,
+ 1032243,1047928,1048005,1058446,1062647,1065732,1073334,etc.]
+Test suite expansion [1036649,1001997,etc.]
-2004-12-29 (platform support)[1092952,1091967] MSVC7, gcc OPT compiles (hobbs)
+--- Released 8.5a2, December 7, 2004 --- See ChangeLog for details ---
-2005-01-05 (bug fix)[1084595] encoding maps for some Chinese locales (fellows)
+2004-12-13 (bug fix)[1083082] encoding memory leaks (ade,porter)
+
+2004-12-13 (bug fix)[1082349] restored C++ extension support (porter)
+
+2004-12-14 (bug fix)[1081541] workaround automake-ism "$U" (porter)
+
+2004-12-15 (new feature) CallFrames on execution, not C, stack (sofer)
+
+2004-12-16 (bug fix)[1085023] [interp limit] support in [vwait], etc. (fellows)
+
+2004-12-29 (bug fix)[1090413] make [clock scan 0030] work (morian,kenny)
+
+2004-12-29 (bug fix)[1092789] make [clock scan 10000] work (porter,kenny)
+
+2004-12-29 (platform support)[1092952,1091967] MSVC7, gcc OPT compiles (hobbs)
2005-01-06 (performance)[1020491] [http::mapReply] (fellows)
=> http 2.5.1
+2005-01-09 (bug fix)[1095909] stopped use of readdir_r (english)
+
+2005-01-10 (enhancement)[1081595] stopped use of TCL_DBGX (english)
+
+2005-01-17 (bug fix)[1100542] [glob] of Windows shares (schar,darley)
+
+2005-01-19 (new feature)[TIP 235] C API for ensembles (fellows)
+
+2005-01-21 (new feature)[TIP 233] virtual time (kupries)
+
2005-01-25 (bug fix)[1101670] [auto_reset] update for [namespace] (porter)
+***POTENTIAL INCOMPATIBILITY***
+May cause re-[source]-ing of files that have not anticipated that before.
2005-01-27 (new feature)[TIP 218] Tcl_Channel API update for threads (kupries)
@@ -6153,7 +6390,7 @@ by 'glob' (darley)
2005-02-10 (bug fix)[1119369] Tcl_EvalObjEx: avoid shimmer loss of List intrep
(sofer,macdonald)
-2005-02-10 (platform support) correct gcc builds for AIX-4+, HP-UX-11 (hobbs)
+2005-02-11 (platform support) correct gcc builds for AIX-4+, HP-UX-11 (hobbs)
2005-02-24 (bug fix)[1119798] prevent [source $directory] (porter,mpettigr)
=> tcltest 2.2.8
@@ -6162,34 +6399,76 @@ by 'glob' (darley)
2005-03-15 (platform support) OpenBSD ports patch (thoyts)
-2005-03-15 (platform support)[1163422] time_t wider than long (kenny)
-
2005-03-18 (bug fix)[1115904] restore recursion limit in direct eval (porter)
+2005-03-24 (bug fix) stop conflict between Tcltest and Thread packages (porter)
+
2005-03-29 (platform support) allow msys builds without cygwin (hobbs)
-2005-04-06 (bug fix)[1178445] fix memory waste at thread exit (vasiljevic)
+2005-04-01 (internal change)[1158008] internal rep of "list" Tcl_Obj's
+now uses a refcounted struct (sofer)
+***POTENTIAL INCOMPATIBILITY***
+For any code that goes poking into the internals of "list" Tcl_Obj's
+
+2005-04-05 (performance)[1174551] Tcl_DecrRefCount of Tcl_Obj "chains" (sofer)
+
+2005-04-08 (performance)[1077262] better Tcl_Encoding cache lifetimes (porter)
+
+2005-04-10 (bug fix)[1180368] [interp invokehidden] mem leak (kenny,porter)
+
+2005-04-12 (performance)[1177363] startup encoding file scan (porter)
+
+2005-04-12 (performance)[1182459] [clock format] (kenny)
2005-04-13 (bug fix) min buffer size dropped from 10 to 1 byte (gravereaux)
-2005-04-19 (bug fix)[947693] Windows pipes honor -blocking during close
-(gravereaux) ***POTENTIAL INCOMPATIBILITY***
-async pipes on windows, set -blocking 1 before [close] to receive exit status
+2005-04-16 (bug fix)[1178445] fix memory waste at thread exit (vasiljevic)
+
+2004-04-16 (bug fix)[1084111] [array names] memory leak (ade,sofer)
+
+2005-04-19 (bug fix)[1185933] [clock] init clobbered global vars (ring,kenny)
+
+2005-04-19 (new feature) [::tcl::unsupported::EncodingDirs] - unsupported
+command to set search path for encoding files (porter)
2005-04-20 (bug fix)[1090869] Tcl_GetInt accept 0x80000000, 64-bit
(porter,singh)
2005-04-22 (bug fix)[1187123] [string is boolean] respect EIAS (porter)
+2005-04-25 (enhancement) update to tzdata2005i (kenny)
+
2005-04-25 (platform support) builds on Mac OS X 10.1 (steffen)
+2005-04-27 (new feature)[TIP 183] [open $f {... BINARY ...}] (porter)
+
+2005-04-29 (new feature)[TIP 176] simple index arithmetic (porter)
+
2005-05-06 (platform support) x86_64 Solarix cc and Solaris 10 builds (hobbs)
+2005-05-10 (bug fix)[1198892] [expr {i**0}] error (kaitschu,markus)
+
+2005-05-10 (new feature)[TIP 132] floating-point conversion to string (kenny)
+***POTENTIAL INCOMPATIBILITY***
+For scripts that rely on (tcl_precision==12) number formatting
+
+2005-05-10 (new feature)[TIP 232] math functions as commands (kenny)
+***POTENTIAL INCOMPATIBILITY***
+Tcl_GetMathFuncInfo functioning is reduced; routine is now deprecated
+
+2005-05-13 (feature removed) TCL_NO_MATH compiler directive (porter)
+
2005-05-14 (platform support) Mac OSX: configurable CoreFoundation API
(steffen)
2005-05-14 (platform support) Mac OSX: use realpath when threadsafe (steffen)
+2005-05-17 (feature removed) Tcl_ObjType's "list", "procbody", "index",
+"ensembleCommand", "localVarName", "levelReference, "boolean" are no
+longer registered (porter)
+***POTENTIAL INCOMPATIBILITY***
+For any callers of Tcl_GetObjType on those strings
+
2005-05-20 (bug fix)[1201589] boolean literal prefix in expressions (porter)
2005-05-24 (platform support) Darwin build support merged into unix (steffen)
@@ -6199,15 +6478,32 @@ Can support [load] from memory as well (steffen)
2005-05-24 (new feature)[1202178] [time] returns non-integer result (steffen)
+2005-05-25 (new feature)[TIP 182] [expr {bool(...)}] (mistachkin,porter)
+
+2005-05-30 (new feature)[TIP 229] [namespace path] (fellows)
+
2005-05-31 (bug fix)[1082283] Unix: notifier thread now joinable (vasiljevic)
+2005-06-01 (new feature)[TIP 241] -nocase: lsort, lsearch, switch (mistachkin)
+
+2005-06-01 (bug fix)[1209759] "return TCL_RETURN;" could cause panic (porter)
+
Documentation improvements [1075433,1085127,1117017,1124160,1149605,etc.]
---- Released 8.4.10, June 4, 2005 --- See ChangeLog for details ---
+--- Released 8.5a3, June 4, 2005 --- See ChangeLog for details ---
2005-06-06 (bug fix)[1213678] Windows/gcc: crash in stack.test (kenny)
-2005-06-07 (bug fix) Unix: --enable-threads compile failure (fellows)
+2005-06-07 (new feature)[TIP 208] [chan] and [chan truncate] (fellows)
+
+2005-06-07 (revert) Restored registration of "procbody" Tcl_ObjType (porter)
+Reduces the ***POTENTIAL INCOMPATIBILITY*** from 2005-05-17.
+
+2005-06-13 (bug fix)[1217375,1219176] [file mkdir] race (diekhans,darley)
+
+2005-06-14 (bug fix)[1220058] [namespace delete] crash (duquette,fellows)
+
+2005-06-17 (bug fix)[1221395] Tcl_LimitSetTime able to break [vwait] (fellows)
2005-06-18 (bug fix)[1154163] [format %h] on 64-bit OS's (kraft,fellows)
@@ -6223,18 +6519,16 @@ Documentation improvements [1075433,1085127,1117017,1124160,1149605,etc.]
2005-06-23 (bug fix)[1225957] Windows/gcc: crashes in assembler code (kenny)
-2005-06-27 (revert)[1101670] [auto_reset] disabled in non-global namespace.
-Restores Tcl 8.4.9 behavior (porter)
-
---- Released 8.4.11, June 28, 2005 --- See ChangeLog for details ---
+2005-06-24 (bug fix) make Tcl_Preserve safe in Tk exit handlers (kenny)
2005-07-01 (bug fix)[1222872] notifier spurious wake-up protection (vasiljevic)
-2005-07-05 (bug fix)[1077262] improved Tcl_Encoding lifetimes (porter)
-
2005-07-05 (bug fix)[1230597] allow idempotent [namespace import] (porter)
-2005-07-07 (bug fix)[1095909] readdir_r usage purged (hobbs)
+2005-07-15 (bug fix)[1237907] localtime() => NULL => crash (kenny)
+
+2005-07-21 (dropped support) IRIX 4, RISCos, Ultrix, and ancient BSD (kenny)
+***POTENTIAL INCOMPATIBILITY***
2005-07-22 (enhancement)[1237755] 8.4 features in script library (fradin,porter)
@@ -6242,6 +6536,12 @@ Restores Tcl 8.4.9 behavior (porter)
2005-07-26 (bug fix)[1047286] cmd delete traces during namespace delete (porter)
2005-07-26 (new unix feature)[1231015] ${prefix}/share on ::tcl_pkgPath (dejong)
+***POTENTIAL INCOMPATIBILITY***
+
+2005-07-27 (bug fix)[1214462] [unknown] can return exceptions (porter)
+
+2005-07-27 (new feature) value of ::tcl_precision now kept per-thread (porter)
+***POTENTIAL INCOMPATIBILITY***
2005-07-28 (unix bug fix)[1245953] O_APPEND for >> redirection (fellows)
@@ -6253,16 +6553,31 @@ Restores Tcl 8.4.9 behavior (porter)
2005-08-05 (Solaris bug fix)[1252475] recognize cp1251 encoding (wagner,fellows)
-2005-08-17 (bug fix)[1217375] [file mkdir] race (diekhans,darley)
+2005-08-11 (config options) eliminated USE_THREAD_STORAGE option (kenny)
+
+2005-08-23 (toolchain support) autoconf-2.59 now required (dejong)
+
+2005-08-24 (new feature)[TIP 219] reflected channels ([chan create]) (kupries)
2005-08-25 (bug fix)[1267380] [lrepeat] buffer overflow prevention (fellows)
+2005-08-26 (bug fix) fix [namespace ensemble] crashes in Snit (fellows)
+
2005-08-29 (bug fix)[1275043] restore round() away from zero (kenny)
+2005-08-29 (bug fix)[1189657] correct [tcl::tm::roots] (porter)
+
2005-09-07 (bug fix)[1283976] invalid [format %c -1] result (porter)
+2005-09-08 (new feature)[1242844][TIP 254] new types for Tcl_LinkVar (fellows)
+
+2005-09-07 (toolchain support) deprecate TCL_VARARGS*; stdarg.h assumed (porter)
+***POTENTIAL INCOMPATIBILITY***
+
2005-09-15 (RHEL bug fix)[1287638] support open >2GB files RHEL 3 (palan)
+2005-09-08 (new feature)[TIP 255] [expr min()] and [expr max()] (hobbs)
+
2005-09-30 (bug fix)[1306162] $argv encoding and list formatting (porter)
2005-10-04 (bug fix)[1067708] [fconfigure -ttycontrol] leak (hobbs)
@@ -6274,99 +6589,159 @@ Restores Tcl 8.4.9 behavior (porter)
2005-10-05 (bug fix)[979640] buffer overrun mixing putenv(), ::env (bold,hobbs)
-2005-10-13 (bug fix)[1284178] [format] accept all integer values (porter)
+2005-10-08 (new feature)[TIP 237] unlimited range for integers (kenny,porter)
+***POTENTIAL INCOMPATIBILITY*** for any code that relies on implicit truncation
+of integer calculations to the range of a C long
+
+2005-10-14 (platform support)[1256937] MSVC++ static builds (thoyts)
+
+2005-10-19 (bug fix)[1331475] [dict append] crash (bills,sofer)
+
+2005-10-20 (bug fix)[1333036] [lset] shared sublist handling (sofer)
-2005-10-22 (bug fix)[1251791] optimization exposed wide/int difference(sofer)
+2005-10-23 (bug fix)[1335006] memleack in [glob] (melbardis,darley)
-2005-10-23 (bug fix)[1334947] value refcount error in var setting (sofer)
+2005-10-23 (bug fix)[1325803] Win: [file stat] on links (bonilla,darley)
2005-11-01 (bug fix)[1337941] Tcl_TraceCommand() -> crash (devilliers,porter)
-2005-11-03 (new Win NT/XP feature) Unicode console support (kovalenko,thoyts)
+2005-11-02 (platform support)[1256937] MSVC 8 support (thoyts)
-2005-11-03 (bug fix)[1201171] [encoding system] in Tclkit (schekin,porter)
+2005-11-03 (new Win NT/XP feature) Unicode console support (kovalenko,thoyts)
-2005-11-04 (bug fix)[1337229,1338280] [namespace delete] / unset traces (porter)
+2005-11-04 (bug fix)[1337229,1338280] [namespace delete] / unset traces (sofer)
2005-11-04 (enhancement) Korean timezone abbreviations (kenny)
-2005-11-04 (bug fix)[1317477] double encoding of time zone (kenny)
+2005-11-04 (platform support)[1163896] LynxOS [load] (heidibr)
-2005-11-04 (Win enhancement)[1267871] extended exit codes (newman,thoyts)
+2005-11-04 (bug fix)[1334947] value refcount error in var setting (sofer)
-2005-11-04 (platform support)[1163896] LynxOS [load] (heidibr)
+2005-11-04 (Win enhancement)[1267871] extended exit codes (newman,thoyts)
-2005-11-08 (bug fix)[1348775] unset trace memory leak (sofer)
+2005-11-07 (bug fix)[1348775] unset trace memory leak (sofer)
-2005-11-08 (bug fix)[1162286] [package ifneeded] warns reported (lavana,porter)
- *** POTENTIAL INCOMPATIBILITY ***
+2005-11-08 (bug fix)[1162286] [package require] checks that the script
+registered by [package ifneeded] provides the version it claims (lavana,porter)
+*** POTENTIAL INCOMPATIBILITY ***
-2005-11-09 (bug fix)[1350293] [after $negative $script] fixed (kenny)
+2005-11-09 (bug fix)[1350293,1350291] [after $negative $script] fixed (kenny)
-2005-11-15 (Win bug fix)[926016,1353840] correct [file mtime] (kenny)
+2005-11-12 (bug fix)[1352734,1354540,1355942,1355342] [namespace delete]
+issues with [namespace path] and command delete traces (sofer,fellows)
2005-11-18 (bug fix)[1358369] URL parsing standards compliance (wu,fellows)
+=> http 2.5.2
-2005-11-18 (bug fix)[1359094] Tclkit crash (thoyts, kupries)
+2005-11-18 (revert) Restored registration of "list" Tcl_ObjType (porter)
+Reduces the ***POTENTIAL INCOMPATIBILITY*** from 2005-05-17.
-2005-11-18 (bug fix)[1355942,1355342] cmd delete trace/ namespace delete (sofer)
+2005-11-18 (bug fix)[1359094] Tclkit crash (thoyts, kupries)
2005-11-20 (bug fix)[1091431] Tcl_InitStubs failure crashes wish (english)
+2005-11-27 (platform support) Darwin 64bit, Tiger copyfile(), and
+Max OSX universal binaries support (steffen)
+
+2005-11-28 (bug fix) [clock] DST transition error (mackerras,kenny)
+
2005-11-29 (bug fix)[1366683] [lsearch -regexp] backrefs (cleverly,fellows)
-2005-11-29 (enhancement)[1369597] Win 64: --enable-64bit=amd64|ia64 (hobbs)
+2005-11-30 (performance) recoded portions of [clock] in C (kenny)
+
+2005-11-30 (enhancement) improved bytecode compiling of [switch] (fellows)
+*** POTENTIAL INCOMPATIBILITY ***
+For loading bytecode compiled and saved by earlier 8.5alpha releases
2005-12-05 (Darwin bug fix)[1034337] NFS recursive file delete (steffen)
---- Released 8.4.12, December 3, 2005 --- See ChangeLog for details ---
+2005-12-08 (platform support) Win x64 build (hobbs)
2005-12-09 (bug fix)[1374778] [lsearch -start $pastEnd] => -1 (fellows)
-2005-12-12 (bug fix)[1241572] correct [expr abs($LONG_MIN)] again (max)
-
2005-12-12 (bug fix)[1377619] configure syntax error exposed in bash-3.1 (hobbs)
-2006-01-09 (bug fix)[1400572] [info level $l] => "namespace inscope" (porter)
+2005-12-13 (bug fix)[1379349] [dict for] CoW error (ring,hippler,fellows)
+
+2005-12-18 (bug fix)[1382528] [dict for {k v} {} {}] crash (kovalenko,fellows)
+
+2005-12-27 clock tzdata updated to Olson's tzdata2005r (kenny)
+
+2005-12-27 libtommath updated to release 0.37 (kenny)
+
+2006-01-09 (bug fix)[1480572] [info level $l] => "namespace inscope" (porter)
+
+2006-01-11 (compat support)[1397843] when ::errorInfo is traced, fall back to
+old pattern of stack trace construction (porter).
+Reduces the ***POTENTIAL INCOMPATIBILITY*** from 2004-10-05.
+
+2006-01-12 (bug fix)[1366227] Win: [file stat] sharing violation (darley)
2006-01-23 (bug fix)[1410553] Tcl_GetRange Unicode confusion (twylite,spjuth)
+2006-01-23 (bug fix)[1412695] args handling in precompiled procs (traum,sofer)
+
+2006-02-01 (new feature)[1275435][TIP 250] [namespace upvar] (sofer)
+
+2006-02-01 (new feature)[958222][TIP 181] [namespace unknown] (madden)
+
+2006-02-01 (new feature)[944803][TIP 194] [apply] (mistachkin)
+
+2006-02-08 (new feature)[1413934][TIP 258] [encoding dirs], etc. (porter)
+
+2006-02-09 (new feature)[1413115][TIP 215] auto-init [incr] (leitgeb)
+
+2006-03-02 (bug fix)[1379287] norm of paths with /../ back to root (porter)
+
+2006-03-03 (compat support) Restored registration of a "boolean" Tcl_ObjType
+(porter)
+Reduces the ***POTENTIAL INCOMPATIBILITY*** from 2005-05-17.
+
2006-03-06 (bug fix)[1439836,1444291] fix TCL_EVAL_{GLOBAL,INVOKE} handling
when auto-loading or exec traces are present (porter)
2006-03-10 (bug fix)[1437595] Win socket finalize with threads (vasiljevic)
-2005-03-13 (revert 2005-07-26 change) ${prefix}/share on ::tcl_pkgPath (porter)
+2006-03-13 (revert 2005-07-26 change) ${prefix}/share on ::tcl_pkgPath (porter)
-2006-03-14 (bug fix)[1381436,859820] threadsafe Tcl_WaitPid (gravereaux,kupries)
+2006-03-14 (bug fix)[1448251] TCLX.y_TM_PATH handling (noble, kupries)
2006-03-14 (bug fix)[768659] pipeline error when last command missing (kupries)
2006-03-18 (bug fix)[1193497] Win porting of [file writable] (darley,vogel)
-2006-03-28 (bug fix)[1064247] BSD: path normalization with realpath() (steffen)
+2006-03-18 (bug fix)[1084705] [glob -nocomplain] silence empty result only,
+no other errors (darley)
+***POTENTIAL INCOMPATIBILITY***
-2006-03-28 (revert 2005-11-03 feature) Unicode console support (hobbs)
- *** POTENTIAL INCOMPATIBILITY ***
+2006-03-21 (platform enhancement)[823329] HFS globbing support (steffen)
+
+2006-03-23 (platform support) updated tcl.spec file (max)
+
+2006-03-28 (bug fix)[1064247] BSD: path normalization with realpath() (steffen)
2006-04-03 (bug fix)[1462248] crash reading utf-8 chars spanning multiple
buffers at end of file (kraft,kupries)
-2006-04-04 (revert 2005-11-08)[1162286] [package ifneeded] warns (porter)
- *** POTENTIAL INCOMPATIBILITY ***
-
2006-04-05 (bug fix)[1464039] Tcl_GetIndexFromObj: empty key (fellows)
2006-04-05 (bug fix) overdue dde, registry patchelevel increments (porter)
-=> dde 1.2.4
-=> registry 1.1.4
+=> dde 1.3.2
+=> registry 1.2
2006-04-06 (bug fix)[1457515] TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
removed (steffen)
2006-04-11 (bug fix)[1458266] enter/enterstep trace interference (leunissen)
---- Released 8.4.13, April 19, 2006 --- See ChangeLog for details ---
+2006-04-12 (feature change)[1376892] revised definition of [:print:] (fellows)
+
+(platform support) Use of _ANSI_ARGS_ purged. ANSI compiler required (fellows)
+
+Documentation improvements [1211078,1190891,1292427,1277503,1104682,1359183,
+1415725,666770]
+
+--- Released 8.5a4, April 27, 2006 --- See ChangeLog for details ---
2006-05-04 (bug fix)[1480509] srand() accept wide input (porter,afredd)
@@ -6375,20 +6750,33 @@ removed (steffen)
2006-05-13 (bug fix)[1482718] proc re-compile: preserve the previous
bytecode while references still on the stack (porter,ryazanov)
-2006-05-13 (bug fix)[943995] fixed [glob] on VFS (porter)
-
2006-05-27 (bug fix)[923072] Darwin: made unthreaded CoreFoundation notifier
naked-fork safe on Tiger (steffen)
-2006-05-31 (revert 2006-01-09)[1400572] namespace inscope & info level (porter)
- *** POTENTIAL INCOMPATIBILITY ***
+2006-06-20 (internal change) Dropped the internal routines used to hook into
+filesystem operations back in the pre-Tcl_Filesystem days. (porter)
+***POTENTIAL INCOMPATIBILITY***
+For extensions and programs that have never migrated to the supported Tcl 8.4
+interface for virtual filesystems
-2006-06-14 (platform support)[1424909] MS VS2005 support (thoyts)
+2006-07-05 (enhancement) Expression parser rewrite avoids stack overflow,
+reduces from O(N^2) to O(N) complexity, and greatly improves syntas error
+messages (porter)
+***POTENTIAL INCOMPATIBILITY***
+For any code relying on exact error messages.
2006-07-20 (platform support) Mac OS X weak linking (steffen)
2006-07-20 (bug fix) Darwin: execve() works iff event loop not yet run (steffen)
+2006-07-24 (bug fix)[1518166] Uninitialized Tcl_DString (afredd)
+
+2006-07-30 (bug fix)[1426279,1505383,1494664,1531530] [clock] fixes (kenny)
+
+2006-08-09 (bug fix)[1531184] [dict for {file stat} x {}] crash (fellows)
+
+2006-08-10 (bug fix)[1538262,1530474] code cleanup; optimizations (afredd)
+
2006-08-18 (bug fix) intermittent failures in TclUnixWaitForFile() (steffen)
2006-08-18 (platform support) Darwin x86_64 (steffen)
@@ -6397,61 +6785,168 @@ naked-fork safe on Tiger (steffen)
2006-08-21 (bug fix) Darwin: recursively called event loop (steffen)
+2006-08-21 (enhancement) Darwin: nanosec resolution clicks and [time] (steffen)
+
+2006-08-28 (bug fix)[1547681] TclFormatObj count arguments (mistachkin,porter)
+
+2006-08-28 (bug fix) stack.test failure on FreeBSD (mistachkin)
+
2006-08-30 (bug fix)[1548263] filesystem segfaults (hobbs,mccormack)
+2006-08-31 (bug fix)[1541274] [expr {sqrt(-1)}] => -NaN (suchenwirth,porter)
+
2006-09-06 (bug fix)[999544] use of MT-safe system calls (vasiljevic)
2006-09-10 (platform support) Darwin: msgcat use CFLocale (steffen)
-=> msgcat 1.3.4
+=> msgcat 1.4.2
+
+2006-09-10 (new feature) tcltest option: -verbose line (steffen)
+=> tcltest 2.3a1
+
+2006-09-19 (bug fix)[1555271,1561260] Several ** operator bugs (porter)
2006-09-22 (bug fix)[1562528] NULL terminates variadic calls (fellows,ryazanov)
+2006-09-22 (new feature)[1520767][TIP 268] [package] alpha/beta version;
+[package require] ranges, [package prefer] selection mode (kupries)
+
2006-09-26 (platform support) MSVC8 AMD64 support (thoyts)
+2006-09-27 (bug fix)[1567222] bignum << errors (porter)
+
+2006-09-30 (enhancement)[1190441] quiet no-op [history] (sofer)
+
+2006-10-04 clock tzdata updated to Olson's tzdata2006m (kenny)
+
2006-10-05 (bug fix)[1570718] make [lappend $nonList] complain (sofer,virden)
2006-10-05 (bug fix)[1122671] alignment fixes in unicode encoding routines
(hobbs,staplin)
-2006-10-05 (new feature) [set ::http::strict 1] (default value is 0) to enable
+2006-10-05 (enhancement) Allow "_" in Tcl Module filenames (kupries)
+
+2006-10-05 (new feature) [set ::http::strict 0] (default value is 1) to disable
URL validity checking against RFC 2986 (hobbs)
=> http 2.5.3
---- Released 8.4.14, October 19, 2006 --- See ChangeLog for details ---
+2006-10-06 (new feature)[1565751][TIP 275] [binary scan] unsigned (thoyts)
+
+2006-10-10 (bug fix)[1566526] crash cleaning up [namespace path] data (porter)
+
+2006-10-12 (bug fix)[1576006] better error messages from [interp alias] (sofer)
+
+2006-10-13 (platform support) get stack size on Darwin (steffen)
-2006-10-31 (platform support)[1582769] Fix build with VC2003 (thoyts)
+--- Released 8.5a5, October 20, 2006 --- See ChangeLog for details ---
-2006-11-07 (bug fix)[1586470] [file copy] on afs (kupries,dionizio)
+2006-10-20 (configure change) Added autodetection for OS-supplied timezone
+files (max)
+
+2006-10-23 (enhancement)[1577278] Ensure the Tcl call stack always has a
+CallFrame, even at level 0 (sofer)
+ *** POTENTIAL INCOMPATIBILITY for users of tclInt.h ***
+
+2006-10-23 (enhancement)[1577492] Tcl_PushCallFrame and [info level]
+enhanced for ensemble rewrites (sofer)
+ *** POTENTIAL INCOMPATIBILITY for [info level 0] on interp alias ***
+
+2006-11-02 (feature change)[TIP 293] Replace {expand} with {*} (hobbs)
+ *** POTENTIAL INCOMPATIBILITY with previous 8.5 alphas only ***
+
+2006-11-04 (new feature)[TIP 274] Exponentiation operator is right
+associative (porter)
+
+2006-11-09 (new feature)[TIP 272] Added [lreverse] and [string reverse]
+commands (fellows)
+
+2006-11-14 (new feature)[TIP 261] [namespace import] returns list of
+imported commands (porter)
+
+2006-11-15 (new feature)[TIP 270] New C routines Tcl_ObjPrintf,
+Tcl_AppendObjToErrorInfo, Tcl_Format, Tcl_AppendLimitedToObj,
+Tcl_AppendFormatToObj, Tcl_AppendPrintfToObj (porter)
+
+2006-11-22 (feature change) Moved TCL_REG_BOSONLY from tcl.h to tclInt (porter)
+
+2006-11-22 (new feature)[TIP 269] Added [string is list] classification
+command (mistackin, fellows)
+
+2006-11-25 (new feature)[TIP 174] Added commands corresponding to most
+expr operators in ::tcl::mathop (fellows)
2006-11-26 (platform support)[1230558] --enable-64bit on more systems (steffen)
-2006-11-27 (bug fix)[1602208] use > 32 async sockets on 64bit system (fontaine)
+2006-11-27 (bug fix)[1602208] Fix 64-bit handling of select() on unix where
+fd was greater than 32 (fontaine, kenny)
-2007-01-25 (configure change) ensure CPPFLAGS env var used when set (steffen)
+2006-11-28 (new feature)[TIP 280] Added [info frame] command for more
+Tcl-level debugging information (kupries)
-2007-01-30 (enhancement) new target: `install-private-headers` (hobbs, steffen)
+2006-12-01 (feature change)[TIP 298] Change Tcl_GetBignumAndClearObj to
+Tcl_TakeBignumFromObj (porter)
-2007-02-12 (bug fix)[1516109] escape encodings crossing chan buffers (dejong)
+2006-12-01 (new feature)[TIP 287] Added [chan pending] subcommand (cleverly)
-2007-03-01 (bug fix)[1671138] compiled [foreach {} x {}] hangs (fellows)
+2006-12-01 (new feature)[TIP 299] Added isqrt() expr operator (kenny)
-2007-03-10 (bug fix)[1675116] list shimmer crash in [lsort] (fellows)
+2006-12-04 (new feature)[TIP 267] Added -ignorestderr option to exec (fellows)
-2007-03-13 (bug fix)[1671087] list shimmer crash in [foreach] (porter)
+2006-12-05 (new feature)[TIP 291] ::tcl_platform(pointerSize) key (kupries)
-2007-03-13 (bug fix)[1669489] list shimmer crash in [array set] (porter)
+2007-01-11 (configure change) Remove "-Wconversion" from deflt CFLAGS (english)
-2007-03-17 (bug fix)[1682211] buffer overflow in [registry keys] (kenny)
-=> registry 1.1.5
+2007-01-25 (configure change) Ensure CPPFLAGS env var is used when set (steffen)
+
+2007-02-19 (configure change) Use SHLIB_SUFFIX=".so" on HP-UX IA64 (was
+".sl") (hobbs)
+
+2007-02-20 (bug fix)[1479814] Handle Windows NT \\?\... extended paths (thoyts)
+
+2007-03-01 (bug fix)[1671138] Fix infinite loop in compiled foreach with an
+empty list (fellows)
+
+2007-03-07 (enhancement) Improved Windows time zone tables to handle new US
+DST rules (kenny)
+
+2007-03-09 (enhancement) Improved Y2038 compliance of zoneinfo files (kenny)
-2007-04-29 (bug fix) fts_open() crash on 64bit Darwin 8 or earlier (steffen)
+2007-04-02 (enhancement) Added bytecode compilation for global, variable,
+upvar and namespace upvar (sofer)
---- Released 8.4.15, May 25, 2007 --- See ChangeLog for details ---
+2007-04-20 (bug fix) Improve clock localization for Japanese locale (kenny)
+
+2007-04-20 (enhancement) Document Tcl_SetNotifier & Tcl_ServiceModeHook (kenny)
+
+2007-04-23 (bug fix) fts_open() crash on 64bit Darwin 8 or earlier (steffen)
+
+--- Released 8.5a6, April 25, 2007 --- See ChangeLog for details ---
+
+2007-04-30 (bug fix)[1705778] many valgrind-detected leaks corrected
+
+2007-05-01 (bug fix)[1710709] leak in [string map] (porter)
+
+2007-05-02 (bug fix)[1710707] leaks in filesystem paths (mistachkin,kenny)
+
+2007-05-18 (feature change) {expand} syntax support removed. (porter)
+ *** POTENTIAL INCOMPATIBILITY with previous 8.5 alphas only ***
2007-05-29 (bug fix)[1712723] Joinable thread death on 64-bit (virden,hobbs)
+2007-05-30 (feature change)[1725186] When expanded literals are parsed,
+(example: {*}{1 2 3}), TCL_TOKEN_EXPAND_WORD token is no longer returned.
+Tokens reflecting the expansion are returned instead. (porter)
+ *** POTENTIAL INCOMPATIBILITY with previous 8.5 alphas only ***
+
2007-06-06 (platform support) Darwin: add plist to tclsh (steffen)
+2007-06-12 (enhancement) [info] is now a [namespace ensemble] (fellows)
+
+2007-06-20 (enhancement) better `make html` results (hobbs)
+
+2007-06-21 (feature change)[1740962] leave traces created during execution
+of traced command do not fire (sofer)
+ *** POTENTIAL INCOMPATIBILITY ***
+
2007-06-23 (bug fix) Darwin: prevent post-fork() abort() (steffen)
2007-06-27 (bug fix)[1743941] Infinite loop in Tcl_CreateTrace traces (porter)
@@ -6460,69 +6955,593 @@ URL validity checking against RFC 2986 (hobbs)
2007-06-30 (bug fix)[1726873] crash in thread sync objects (vasiljevic,twylite)
+2007-06-30 (bug fix)[1717186] [lsort -command \{ $l] leak (afredd,fellows)
+
2007-07-05 (bug fix)[1743676] no command named "" error message (porter,virden)
+2007-07-11 (bug fix)[1752146] [while 1 {}] & [interp limit] on commands (sofer)
+
+2007-07-31 (bug fix)[681877] tcl_platform(user) from system, not env (fellows)
+
+2007-07-31 (enhancement)[1750051] space efficiency of Tcl variables (sofer)
+ *** POTENTIAL INCOMPATIBILITY for C code that accesses internal
+ Tcl structs Var, Bytecode, Namespace, or CallFrame. ***
+
+2007-08-01 (enhancement)[1764318] word.tcl proc rewrites (petasis,fellows)
+
+2007-08-08 (bug fix)[1770224] [tcl::mathop::>> $big1 $big2] errors (porter)
+
2007-08-14 (platform support) Darwin [load] from VFS on intel & 64bit (steffen)
-2007-08-25 (bug fix)[1751117] [clock format ... %c] buffer overrun (kenny)
+2007-08-15 (bug fix)[1773127] corrected open mode "a+" (rottman,fellows)
+
+2007-08-16 (bug fix)[1773040] ::errorInfo trace crash (janssen,porter)
+
+2007-08-16 (performance)[1564517] pre-compile constant expressions (porter)
+
+2007-08-21 (bug fix)[1775878] 'puts \' in interactive tclsh failed to move to
+prompt for continuation line (porter)
+
+2007-08-25 (bug fix)[1781282] [clock scan] case senstivity (kenny)
+
+2007-08-25 (performance)[1767293] ** on native integer types (kenny)
+
+2007-09-03 clock tzdata updated to Olson's tzdata2007g (kenny)
+
+2007-09-06 (platform support) Darwin: drop support for Xcode 1.5 project, add
+project for Xcode 3.0 (steffen)
+
+2007-09-08 (bug fix)[1786481] nested [dict update] crash (fellows)
+
+2007-09-08 (bug fix)[1710710] TclPtrSetVar leak (mistachkin,sofer)
+
+2005-09-09 (feature removed) Tcl_ObjType "nsName" no longer registered (porter)
+ *** POTENTIAL INCOMPATIBILITY for Tcl_GetObjType("nsName") ***
2007-09-10 (bug fix)[1740631] Linked variable unlink prevention (maros,hobbs)
-2007-09-11 (platform support) Windows AMD64 support (thoyts)
+2007-09-11 (bug fix)[1786481] [dict update] stack management (sofer)
+ *** POTENTIAL INCOMPATIBILITY with previous 8.5 alpha bytecode only ***
+
+2007-09-11 (bug fix)[1578344] [package require -exact] 8.4 compat (porter)
+ *** POTENTIAL INCOMPATIBILITY with previous 8.5 alphas only ***
2007-09-11 (bug fix)[1772989,1071322] Support _, : in test constraints (porter)
-=> tcltest 2.2.9
+=> tcltest 2.3b1
+
+2007-09-11 (platform support) Windows AMD64 support (thoyts)
2007-09-14 (enhancement)[1793984] DTrace provider for Tcl (steffen)
+2007-09-14 (bug fix)[1519940] surplus ns path invalidation (fellows,bauer)
+
2007-09-15 (platform support) SunOS-5.1x link with cc, not ld (steffen)
---- Released 8.4.16, September 21, 2007 --- See ChangeLog for details ---
+2007-09-17 (platform support)[1748251] Fix NetBSD link failures (english)
+
+(bug fix)[1066755] Several stack efficiency efforts increases recursion limit
+on Windows to be larger than the default [interp recursionlimit] value
+
+--- Released 8.5b1, September 26, 2007 --- See ChangeLog for details ---
-2007-10-03 (bug fix) Corrected find of deleted command (sofer,neumann)
+2007-10-02 (bug fix)[1806422] proper [tcl::tm::path] autoload (porter)
+
+2007-10-02 (bug fix) Improve Tcl_DecrRefCount() robustness (staplin)
+
+2007-10-11 (bug fix)[1805887] [string is int -failindex] for 0o, 0b (porter)
2007-10-15 (bug fix)[1813528] Tcl_ParseBraces read past buffer (mistachkin)
-2007-10-30 (bug fix)[1810264] stop panic in RE lexer (fellows)
+2007-10-25 (bug fix)[1726873] intermittent crash in threads (vasiljevic)
+
+--- Released 8.5b2, October 26, 2007 --- See ChangeLog for details ---
+
+2007-10-27 (bug fix)[1821159] fixed broken compile on x86_64 (sofer)
+
+2007-10-27 (bug fix)[1810264] stop panic in RE lexer (fellows)
+
+2007-10-28 (enhancement)[1826906] Embed iso8859-1 encoding in libtcl (fellows)
+
+2007-11-01 (bug fix)[1808258] [string is ascii \000] (fellows)
+
+2007-11-05 (bug fix)[1823576] [fconfigure $serial -xchar \000] (cassof)
+
+2007-11-07 (performance)[1827996] binary glob matching (hobbs)
+
+2007-11-07 (performance) binary [gets] (hobbs)
+
+2007-11-09 (performance)[1829248] interp state reset (sofer)
+
+2007-11-10 (performance) stack checking (sofer)
+
+2007-11-10 (performance) list indexing bytecode (sofer)
+
+2007-11-11 (performance)[1830038] macros to fetch Tcl_Obj intreps (sofer)
+
+2007-11-11 (performance)[1830166] RE bytecode for simple cases (hobbs)
+
+2007-11-13 (performance) [switch] & [regexp] use RE bytecode (hobbs, fellows)
+
+2007-11-14 (performance) bytecode for [info exists] (fellows)
+
+2007-11-15 (new feature)[1231022] configure option: --disable-rpath (fellows)
2007-11-15 (bug fix)[1810038] infinite loop in RE compiler (lane,porter)
-2007-11-27 (bug fix)[1823552] encoding conversion for [info hostname] (porter)
+Many significant documentation improvements (fellows, sofer)
+
+--- Released 8.5b3, November 19, 2007 --- See ChangeLog for details ---
+
+2007-11-20 (enhancement) string rep of dict has stable order (fellows)
+
+2007-11-21 (enhancement) compiled ensemble support (fellows)
+
+2007-11-22 (enhancement) [dict] is now an ensemble (fellows)
+
+2007-11-23 (enhancement) [string] is now an ensemble (fellows)
+
+2007-11-26 (bug fix)[1815573] Correct stack checking failure (sofer,golovan)
+
+2007-11-27 (bug fix)[800753] Document single byte char limit for
+[chan configure -eofchar] (cassoff)
+
+2007-12-03 (enhancement)[1836519] [switch $val $body] safe/fast (fellows,spjuth)
+
+2007-12-03 (release) tcltest package bump to 2.3.0 (porter)
+
+2007-12-03 (bug fix)[1618235] fix BSD compile errors (fellows)
2007-12-05 (bug fix)[1844789] fix [lsearch -exact -integer] crash (fellows)
-2007-12-13 (bug fix)[1773127] corrected open mode "a+" (rottman,fellows)
+2007-12-05 (performance)[1845092] Tcl_ObjType for channel names (hobbs)
+
+2007-12-14 (bug fix)[1602539] NUL pollution in [glob] result (hobbs)
+
+2007-12-17 (bug fix)[1851832,1851524] memory alignment correction (sofer)
2007-12-18 (bug fix)[1810264] revised regexp engine to prevent debilitating
over-consumption of resources (drewry,lane,ormandy,fellows)
---- Released 8.4.17, January 4, 2008 --- See ChangeLog for details ---
+Several documentation and release notes improvements
+
+--- Released 8.5.0, December 20, 2007 --- See ChangeLog for details ---
+
+2007-12-23 (bug fix)[1857126] restore backref support to regexps (hobbs)
+
+2007-12-26 (enhancement)[1856994] [lsort] performance (sofer)
+
+2008-01-10 (bug fix)[1867855] fix [format %lli 0] crash (porter)
+
+2008-01-11 (bug fix)[1850424,1860425] stack checking on *bsd (sofer,noble)
2008-01-13 (bug fix)[1353846] crash in read-only serial (hobbs,newman)
+2008-01-15 (bug fix)[1869989] mem leak; expr literals (porter,melbardis)
+
+2008-01-20 (bug fix)[1869405] binary [gets]; stacked channels (hobbs,ficicchia)
+
+2008-01-22 (bug fix)[1867855] fix [lreverse {}] crash (sofer,madden)
+
2008-01-30 (bug fix)[1882373] fix Tcl_GetAlias pointer code (an00na)
---- Released 8.4.18, February 8, 2008 --- See ChangeLog for details ---
+Several documentation and release notes improvements
+
+--- Released 8.5.1, February 5, 2008 --- See ChangeLog for details ---
+
+2008-02-06 (enhancement) [clock format] performance (kenny)
+
+2008-02-12 (bug fix)[1891827] compiled [switch -nocase] error (fellows)
2008-02-22 (bug fix)[1818565] missing state array in http::status (thoyts)
=> http 2.5.4
-2008-02-26 (bug fix) possible crash in [gets] (hobbs)
+2008-02-26 (bug fix)[1868845] corrected [eof] ordering (thoyts)
2008-02-26 (new feature) [http::meta] command (thoyts)
=> http 2.5.5
+2008-02-26 (bug fix)[1902436] fixed regexps ending in \* (hobbs)
+
+2008-02-27 (bug fix)[1862555,1902423] [clock] range & l10n (kenny)
+
+2008-02-28 (bug fix) [return -level 0] memory leak (porter)
+
+2008-02-28 (bug fix) [format %llx $big] memory leak (porter)
+
+2008-02-28 (bug fix) expression parser error message memory leak (porter)
+
+2008-02-28 (bug fix) memory leak when enter trace modifies command (porter)
+
+2008-02-29 (enhancement) Consumer refcounting for Tcl_SetReturnOptions()
+and Tcl_AddObjToErrorInfo() (spjuth,porter)
+ *** POTENTIAL INCOMPATIBILITY ***
+
2008-03-07 (bug fix)[1899164] Avoid expr and script bytecode confusion (porter)
+2008-03-07 (bug fix)[1904907] finalize crash in Tcl_GetReturnOptions (kupries)
+
+2008-03-10 (bug fix)[1893815] expr {abs(-1e-350)} => -0.0 (porter)
+
+2008-03-10 (bug fix)[1901113] crash in [tcl::Bgerror {} {}] (madden,porter)
+
+2008-03-11 (bug fix)[1911919] unset trace inf loop in namespace delete (sofer)
+
+2008-03-12 (new feature) some HTTP 1.1 support in http (and more!) (hobbs)
+=> http 2.7
+
+2008-03-13 (enhancement) support space in INSTALL_ROOT or $builddir (steffen)
+
+2008-03-16 (bug fix)[1903325] bytecode stack space prediction crash (fellows)
+
+2008-03-18 (bug fix)[1914604] Tcl Modules: encoding fixed to utf-8; environment
+variables without "." added to customization hooks (kupries)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2008-03-18 (bug fix)[1914503] alignment of TclStackAlloc() return (sofer)\
+
+2008-03-20 (bug fix)[1868171] expose Tcl_GetMemoryInfo (for AOLserver) (fellows)
+
2008-03-24 (bug fix)[1923966] crash in [binary format x0s] (thoyts)
2008-03-27 (platform support)[1921166] Solaris 64bit build fixes (steffen)
-2008-04-04 (bug fix)[780533] [fcopy -size -command] callback failure (ferrieux)
+2008-03-27 clock tzdata updated to Olson's tzdata2008b (kenny)
+
+--- Released 8.5.2, March 28, 2008 --- See ChangeLog for details ---
+
+2008-03-30 (bug fix)[1783544] more robust TclIsNaN() (kenny,teterin)
+
+2008-04-01 (bug fix)[1839067] FP round fix for Solaris/x86 (kupries,schlenker)
+
+2008-04-02 (bug fix)[780533,1932639] [fcopy] callbacks unreliable (ferrieux)
+
+2008-04-04 (bug fix) [chan postevent] crash (kupries)
+
+2008-04-07 (bug fix) Fix broken [format {% d}] (max)
+
+2008-04-07 (bug fix)[1350564] Bi-directional [fcopy] now supported (ferrieux)
+
+2008-05-07 (bug fix) [dict append] crash (mccormack,fellows)
+
+2008-05-21 (bug fix)[1968882] [info complete "\\\n"] => 0 (porter)
+
+2008-05-22 (bug fix)[1968245] Tcl_LogCommandInfo() accept length=-1 (darroch)
+
+2008-05-23 (bug fix)[1965787] 32-bit overflow in [tell] result (ferrieux)
+
+2008-06-12 (platform support) Solaris static build with DTrace (steffen)
+
+2008-06-12 (platform support) Solaris/amd64 gcc 64bit support (steffen)
+
+2008-06-20 (bug fix)[1999035] make [interp bgerror $i] act in $i (porter)
+
+2008-06-23 (bug fix)[1972879] bad path intrep caching (porter)
+
+2008-06-24 (bug fix)[1999176] crash in [glob -dir {} a] (porter)
+
+2008-06-25 (bug fix)[1999119] Support TM packages in Safe Base (kupries)
+
+--- Released 8.5.3, June 30, 2008 --- See ChangeLog for details ---
+
+2008-07-03 (bug fix)[1969717] fix package finding on Samba shares (jos)
+
+2008-07-03 (bug fix)[1987821] mem leak in [seek] on reflected chan (kupries)
+
+2008-07-20 (enhancement)[2008248] dict->list preserve item intreps (pasadyn)
+
+2008-07-21 (bug fix)[2015723] [file] bad use of inodes on Windows (thoyts)
+
+2008-07-21 (enhancement) [info frame] returns file data in more cases (kupries)
+
+2008-07-29 (bug fix)[2030670] fix rare panic in TclStackFree (pasadyn,sofer)
+
+2008-08-08 tzdata updated to Olson's tzdata2008e (kenny)
+
+2008-08-11 (bug fix)[2046846] 64bit support for http zlib crc (thoyts)
+=> http 2.7.1
+
+2008-08-11 (enhancement) automatic [package provide] for TMs (kupries)
+
+--- Released 8.5.4, August 15, 2008 --- See ChangeLog for details ---
+
+2008-08-14 (bug fix)[2055782] fix crash in [namespace inscope] (sofer)
+
+2008-08-21 (bug fix)[2065115] correct handling of ***= RE's (hobbs,porter)
+
+2008-09-10 (enhancement) efficient list->dict conversion (elby,fellows)
+
+2008-09-17 (bug fix)[2116053] export [min] and [max] from tcl::mathfunc (sofer)
+
+2008-09-27 (bug fix)[2130992] prevent overflow crash in [lrepeat] (fellows)
+
+2008-10-05 (bug fix)[2143288] correct bad isqrt() results (boffey,kenny)
+
+2008-10-08 (bug fix)[2151707] fix stack trace from variable trace (porter)
+
+--- Released 8.5.5, October 15, 2008 --- See ChangeLog for details ---
+
+2008-10-24 (bug fix) fix failure to read SHOUTcast streams (thoyts)
+=> http 2.7.2
+
+2008-11-10 (bug fix)[2255235] [platform::shell::LOCATE] update (ring,kupries)
+=> platform::shell 1.1.4
+
+2008-11-13 (bug fix)[2269431] VFS [load] -> tempfile litter (ficicchia,nijtmans)
+
+2008-11-30 (bug fix)[2362156] [clock]: colon in format string (mizuno,kenny)
+
+2008-12-01 (bug fix)[2251175] [{*}{\{}] errors (hellström,ferrieux,porter)
+
+2008-12-02 (bug fix)[2270477] hang in channel finalization (ferrieux,kupries)
+
+2008-12-04 (bug fix)[2385549] [file normalize] failed on some paths (porter)
+
+2008-12-10 tzdata updated to Olson's tzdata2008i (kenny)
+
+2008-12-11 (bug fix)[2407783] spoil ChannelState when channel name passes
+among multiple interps (kupries)
+
+2008-12-21 (bug fix) Fix ability to join threads on 64-bit Windows (thoyts)
+
+2008-12-21 (bug fix)[2114900] updated tclIndex file (cassoff,kenny)
+
+--- Released 8.5.6, December 21, 2008 --- See ChangeLog for details ---
+
+2009-01-03 (bug fix)[2481670] [clock add] error message (talvo)
+
+2009-01-19 (new feature) CONFIG_INSTALL_DIR - where tclConfig.sh goes (cassoff)
+
+2009-01-19 (platform support) better tools for BSD ports (cassoff)
+
+2009-01-21 (bug fix)[2458202] exit crash with [chan create]d channel (kupries)
+
+2009-01-29 (bug fix)[2519474] Tcl_FindCommand() bug exposed by oo (fellows)
+
+2009-02-04 (bug fix)[2561746] [string repeat] overflow crash (porter)
+
+2009-02-17 (platform support) MSVC and _WIN64 (hobbs)
+
+2009-02-20 (bug fix)[2571597] [file pathtype /a] wrong result (nadkarni,porter)
+
+2009-03-15 (platform support) translate SIGINFO where defined (BSD) (teterin)
+
+2009-03-18 (bug fix)[2688184] memleak in [file normalize] (mistachkin)
+
+2009-03-20 (bug fix)[2597185] crash in Tcl_AppendStringToObj (porter)
+
+2009-03-27 (bug fix)[2710920] [file dirname|tail /foo/] errors (epler,porter)
+
+2009-03-30 (bug fix)[2603158] Tcl_AppendObjToObj: append to self crash (porter)
+
+2009-04-07 (bug fix)[2561794,2669109,2494093,2553906] string overflow (porter)
+
+2009-04-08 (bug fix)[2570363] unsafe [eval]s in tcltest (bron,porter)
+=> tcltest 2.3.1
+
+2009-04-08 (platform support) more Darwin kernel patterns (steffen)
+=> platform 1.0.4
+
+2009-04-09 (bug fix)[26245326] [http::geturl] connection failures (golovan)
+=> http 2.7.3
+
+2009-04-10 (new feature) Darwin: embeddable CoreFoundation notifier (steffen)
+
+2009-04-10 (bug fix)[1961211] Darwin [load] back-compatibility (steffen)
+
+2009-04-14 tzdata updated to Olson's tzdata2009f (kenny)
+
+--- Released 8.5.7, April 15, 2009 --- See ChangeLog for details ---
+
+2009-04-27 (bug fix)[2446662] uniformly declare EOF on RST on sockets (ferrieux)
+
+2009-04-27 (bug fix)[1028264] delay WSACleanup() from under our feet (ferrieux)
+
+2009-05-07 (bug fix)[2785893] find command in deleted namespace (sofer)
+
+2009-05-29 (platform support) account for ia64_32 (kupries)
+=> platform 1.0.5
+
+2009-06-02 (bug fix)[2798543] incorrect [expr] integer ** results (porter)
+
+2009-06-10 (bug fix)[2801413] overflow in [format] (porter)
+
+2009-06-13 (bug fix)[2802881] corrected compile env context (tasada,porter)
+
+2009-07-01 (bug fix)[2806622] Win: bad tcl_platform(user) value (thoyts)
+
+2009-07-16 (bug fix)[2819200] underflow settings on MIPS systems (porter)
+
+2009-07-23 (bug fix)[2820349] plug event leak in notifier (mistachkin)
+
+2009-07-24 (bug fix)[2826248] crash in Tcl_GetChannelHandle (sonnenburg,kupries)
+
+2009-07-31 (bug fix)[2830354] overflow in [format] (misch,porter)
+
+2009-08-06 (bug fix)[2827000] reflected channels can signal EGAIN (kupries)
+
+2009-08-20 (bug fix)[2806250] EIAS violation in ~foo pathnames (porter)
+
+2009-08-21 (bug fix)[2837800] [glob */foo] return ./~x/foo (porter)
+
+2009-08-24 (bug fix) nested event loop notifier w/TkAqua Cocoa (alaoui,steffen)
+
+2009-08-25 (bug fix) [info frame] account for continuation lines (kupries)
+
+2009-08-27 (bug fix)[2845535] overflows in [format] (porter)
+
+2009-09-01 (bug fix) improved error message in tcltest (porter)
+=> tcltest 2.3.2
+
+2009-09-11 (bug fix)[2849860] http handle "quoted" charset value (fellows)
+=> http 2.7.4
+
+2009-10-04 (bug fix)[2569449] Core Foundation memory bug in Tiger (steffen)
+
+2009-10-06 (bug fix)[1941434] broken tclTomMath.h includes (porter)
+
+2009-10-07 (bug fix)[2871908] leaked hash table (mistachkin,kupries)
+
+2009-10-08 (bug fix)[2874678] bignum leak in [dict incr] (fellows)
+
+2009-10-17 (bug fix)[2629338] crash in var unset traces (raney,fellows)
+
+2009-10-19 (bug fix)[2107634] extend [read] and [gets] to Tcl string limits
+(morrison,parker,porter)
+
+2009-10-21 (bug fix)[2882561] Haiku OS signal support (morrison,fellows)
+
+2009-10-24 Broken DST applied EU rules to US zones (lehenbauer,kenny)
+
+2009-10-29 (bug fix)[2800740] halved bignum memory on 64-bit systems (porter)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2009-11-03 tzdata updated to Olson's tzdata2009q (kenny)
+
+2009-11-03 (bug fix)[2854929] TM search path support in Safe Base (kupries)
+
+2009-11-11 (bug fix)[2888099] [close] loses ENOSPC error (khomoutov,ferrieux)
+
+2009-11-11 (bug fix)[2891171] RFC 3986 compliance for ? in URL (nijtmans)
+=> http 2.7.5
+
+2009-11-12 (bug fix)[2895565] [fcopy -size] miscounts when converting encodings
+(kupries)
+
+--- Released 8.5.8, November 16, 2009 --- See ChangeLog for details ---
+
+2009-11-16 (bug fix)[2891556] encoding finalization crash (mistachkin,ferrieux)
+
+2009-12-09 (enhancement) rewrite of the Safe Base commands (kupries)
+
+2009-12-16 (bug fix)[2913616] msgcat: improved safe interp support (fellows)
+=> msgcat 1.4.3
+
+2009-12-23 (bug fix)[2913625] [info script/nameof] in safe interps (fellows)
+
+2009-12-28 (bug fix)[2891362] enable time limit in child interps (fellows)
+
+2009-12-28 (bug fix)[2895741] enable min(), max() in safe interps (fellows)
+
+2010-01-05 (bug fix)[2918610] [file rootname] corruption (magerya,porter)
+
+2010-01-06 (enhancement) Haiku, CYGWIN support improvements (nijtmans)
+
+2010-01-18 (bug fix)[2932421] less [format %s] shimmer (ferrieux)
+
+2010-01-18 (bug fix)[2918110] [chan postevent] crash (bron,kupries)
+
+2010-02-01 (bug fix)[2942697] faster match: some pathological regexp patterns
+(lane,fellows)
+
+2010-02-02 (bug fix)[2939073] [array unset] unset trace crash (ferrieux)
+
+2010-02-02 (bug fix)[2933089] [info frame] shared lit trouble (kupries)
+
+2010-02-11 (bug fix)[2949740] [open |noSuch rb] crash (kovalenko,fellows)
+
+2010-02-11 (bug fix)[2954959] get sign of abs($zero) right (nijtmans)
+
+2010-03-09 (bug fix)[2936225] stop [chan copy] to slow channel consuming all
+memory with buffer backup (ferrieux)
+
+2010-03-20 (enhancement) permit [fcopy] of > 2**31 bytes (fellows)
+
+2010-03-24 (bug fix)[2383005] [return -errorcode] reject non-list (porter)
+
+2010-03-25 (bug fix)[2976504] broken fstatfs() call (reeuwijk,fellows)
+
+2010-03-30 (bug fix)[2978773] refchan mem preservation (kupries)
+
+2010-05-19 (bug fix)[3004007] dict/list shimmer w/o string rep loss (fellows)
+
+2010-06-09 (bug fixes) platform: several fixes for 64 bit systems (kupries)
+=> platform 1.0.9
+
+2010-06-16 (bug fix)[3016135] [clock format] in he_IL locale (nijtmans)
+
+2010-06-28 (bug fix)[3019634] support errno.h changes in MSVC++ 2010 (nijtmans)
+
+2010-07-02 (enhancement) -errorcode for [expr] domain errors (fellows)
+
+2010-07-28 (bug fix)[3037525] crash deleting vars @ callframe pop (sofer)
+
+2010-08-04 (bug fix)[3034840] mem corrupt when refchan loses interp (kupries)
+
+2010-08-04 (enhancement) Win [load] use LOAD_WITH_ALTERED_SEARCH_PATH (hobbs)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2010-08-12 (bug fix)[2826551] line-sensitive matching in regexp (dejong)
+
+2010-08-19 (bug fix)[3048354] buffer overflow detect in Fortify build (fellows)
+
+2010-08-23 tzdata updated to Olson's tzdata2010l (kenny)
+
+2010-09-01 (bug fix)[3057639] no read traces [lappend arr(elem) ...] (hobbs)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+--- Released 8.5.9, September 8, 2010 --- See ChangeLog for details ---
+
+2010-09-24 (bug fix)[3056775] race condition in Win sockets (twylite,kupries)
+
+2010-10-23 (update)[3085863] Update Unicode data to 6.0 (nijtmans)
+
+2010-11-02 Safe Tcl handling of empty path lists (cassoff)
+
+2010-11-03 (bug fix)[3098302] crash in compiled [catch] (kenny)
+
+2010-11-15 (TIP 378)[3081184] improved TIP 280 performance (kupries)
+
+2010-11-30 (enhancement) Restore TclFormatInt for performance (hobbs)
+
+2010-11-30 (enhancement) Tcl_PrintDouble performance improvements (kenny)
+
+2010-12-12 (platform) OpenBSD build improvements (cassoff)
+
+2010-12-17 (platform) Revisions to support rpm 4.4.2 (cassoff)
+
+2011-01-13 (bug fix)[3142026] GrowEvaluationStack OBOE (harder,sofer)
+
+2011-01-19 (bug fix)[3072640] protect writes to ::error* variables (sofer)
+
+2011-03-06 (bug fix)[3200987,3192636] parser buffer overruns (porter)
+
+2011-03-08 (bug fix)[3202905] failed intrep release of interp result (mccormack)
+
+2011-03-09 (bug fix)[3202171] repair [namespace inscope] optimizer (porter)
+
+2011-03-14 (bug fix) Fixes from libtommath 0.42.0 release (fellows)
+
+2011-03-21 (bug fix)[3216070] [load] extension from embed Tcl apps (nijtmans)
+
+2011-04-12 (bug fix)[3285472] intrep corruption in [string reverse] (porter)
+
+2011-04-13 (bug fix)[2662380] crash when variable append trace unsets (sofer)
+
+2011-04-13 (bug fix)[3285375] Buffer overflow in [concat] (porter)
+
+2011-05-02 (internals change) revised TclFindElement() interface (porter)
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2011-05-05 (enhancement) dict->list w/o string rep generation (porter)
+
+2011-05-10 (bug fix)[3173086] Crash parsing long lists (rogers,porter)
+
+2011-05-12 (bug fix)[2715421] surplus \n in POST (passadyn,thoyts)
+=> http 2.7.6
+
+2011-05-24 tzdata updated to Olson's tzdata2011g (iyer)
+
+2011-05-25 (enhancement) msgcat internal improvements (fellows)
+=> msgcat 1.4.4
+
+2011-06-02 (bug fix)[3185407] cmd resolution epoch flaw (nadkarni,fellows)
+
+2011-06-13 (bug fix)[3315098] mem leak generating double string rep (neumann)
-2008-04-07 (new feature)[1350564] eased fileevent constraints during [fcopy]
-(ferrieux)
+2011-06-21 (new cmd) [tcltest::loadIntoSlaveInterpreter] (fellows)
+=> tcltest 2.3.3
-2008-04-10 (bug fix)[1557855] crash on some [fcopy -size] values (ferrieux)
+2011-06-22 (new feature) DEB_HOST_MULTIARCH support (kupries)
+=> platform 1.0.10
---- Released 8.4.19, April 18, 2008 --- See ChangeLog for details ---
+--- Released 8.5.10, June 23, 2011 --- See ChangeLog for details ---
diff --git a/compat/fixstrtod.c b/compat/fixstrtod.c
index ba1a480..91f309e 100644
--- a/compat/fixstrtod.c
+++ b/compat/fixstrtod.c
@@ -20,12 +20,12 @@
* somes systems (e.g. SunOS 4.1.4) stdlib.h doesn't declare strtod.
*/
-extern double strtod();
+extern double strtod(char *, char **);
double
-fixstrtod(string, endPtr)
- char *string;
- char **endPtr;
+fixstrtod(
+ char *string,
+ char **endPtr)
{
double d;
d = strtod(string, endPtr);
diff --git a/compat/gettod.c b/compat/gettod.c
index 059c36a..28e1432 100644
--- a/compat/gettod.c
+++ b/compat/gettod.c
@@ -10,18 +10,18 @@
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
-#include "tcl.h"
#include "tclPort.h"
#include <sys/timeb.h>
#undef timezone
int
-gettimeofday(tp, tz)
-struct timeval *tp;
-struct timezone *tz;
+gettimeofday(
+ struct timeval *tp,
+ struct timezone *tz)
{
struct timeb t;
+
ftime(&t);
tp->tv_sec = t.time;
tp->tv_usec = t. millitm * 1000;
diff --git a/compat/memcmp.c b/compat/memcmp.c
index 3a4974b..5fce528 100644
--- a/compat/memcmp.c
+++ b/compat/memcmp.c
@@ -1,24 +1,21 @@
-/*
+/*
* memcmp.c --
*
* Source code for the "memcmp" library routine.
*
* Copyright (c) 1998 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
-#include "tcl.h"
#include "tclPort.h"
/*
- * Here is the prototype just in case it is not included
- * in tclPort.h.
+ * Here is the prototype just in case it is not included in tclPort.h.
*/
-int memcmp _ANSI_ARGS_((CONST VOID *s1,
- CONST VOID *s2, size_t n));
+int memcmp(CONST VOID *s1, CONST VOID *s2, size_t n);
/*
*----------------------------------------------------------------------
@@ -28,11 +25,10 @@ int memcmp _ANSI_ARGS_((CONST VOID *s1,
* Compares two bytes sequences.
*
* Results:
- * compares its arguments, looking at the first n
- * bytes (each interpreted as an unsigned char), and returns
- * an integer less than, equal to, or greater than 0, accord-
- * ing as s1 is less than, equal to, or
- * greater than s2 when taken to be unsigned 8 bit numbers.
+ * Compares its arguments, looking at the first n bytes (each interpreted
+ * as an unsigned char), and returns an integer less than, equal to, or
+ * greater than 0, according as s1 is less than, equal to, or greater
+ * than s2 when taken to be unsigned 8 bit numbers.
*
* Side effects:
* None.
@@ -41,10 +37,10 @@ int memcmp _ANSI_ARGS_((CONST VOID *s1,
*/
int
-memcmp(s1, s2, n)
- CONST VOID *s1; /* First string. */
- CONST VOID *s2; /* Second string. */
- size_t n; /* Length to compare. */
+memcmp(
+ CONST VOID *s1, /* First string. */
+ CONST VOID *s2, /* Second string. */
+ size_t n) /* Length to compare. */
{
CONST unsigned char *ptr1 = (CONST unsigned char *) s1;
CONST unsigned char *ptr2 = (CONST unsigned char *) s2;
@@ -52,9 +48,17 @@ memcmp(s1, s2, n)
for ( ; n-- ; ptr1++, ptr2++) {
unsigned char u1 = *ptr1, u2 = *ptr2;
- if ( u1 != u2) {
+ if (u1 != u2) {
return (u1-u2);
}
}
return 0;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/compat/opendir.c b/compat/opendir.c
index 25e8392..3fe70c1 100644
--- a/compat/opendir.c
+++ b/compat/opendir.c
@@ -1,14 +1,12 @@
/*
* opendir.c --
*
- * This file provides dirent-style directory-reading procedures
- * for V7 Unix systems that don't have such procedures. The
- * origin of this code is unclear, but it seems to have come
- * originally from Larry Wall.
+ * This file provides dirent-style directory-reading procedures for V7
+ * Unix systems that don't have such procedures. The origin of this code
+ * is unclear, but it seems to have come originally from Larry Wall.
*/
#include "tclInt.h"
-#include "tclPort.h"
#undef DIRSIZ
#define DIRSIZ(dp) \
@@ -17,24 +15,28 @@
/*
* open a directory.
*/
+
DIR *
-opendir(name)
-char *name;
+opendir(
+ char *name)
{
- register DIR *dirp;
- register int fd;
- char *myname;
+ register DIR *dirp;
+ register int fd;
+ char *myname;
- myname = ((*name == '\0') ? "." : name);
- if ((fd = open(myname, 0, 0)) == -1)
- return NULL;
- if ((dirp = (DIR *)ckalloc(sizeof(DIR))) == NULL) {
- close (fd);
- return NULL;
- }
- dirp->dd_fd = fd;
- dirp->dd_loc = 0;
- return dirp;
+ myname = ((*name == '\0') ? "." : name);
+ if ((fd = open(myname, 0, 0)) == -1) {
+ return NULL;
+ }
+ dirp = (DIR *) ckalloc(sizeof(DIR));
+ if (dirp == NULL) {
+ /* unreachable? */
+ close(fd);
+ return NULL;
+ }
+ dirp->dd_fd = fd;
+ dirp->dd_loc = 0;
+ return dirp;
}
/*
@@ -44,62 +46,65 @@ char *name;
#define ODIRSIZ 14
struct olddirect {
- ino_t od_ino;
- char od_name[ODIRSIZ];
+ ino_t od_ino;
+ char od_name[ODIRSIZ];
};
#else /* a Pyramid in the ATT universe */
#define ODIRSIZ 248
struct olddirect {
- long od_ino;
- short od_fill1, od_fill2;
- char od_name[ODIRSIZ];
+ long od_ino;
+ short od_fill1, od_fill2;
+ char od_name[ODIRSIZ];
};
#endif
/*
* get next entry in a directory.
*/
+
struct dirent *
-readdir(dirp)
-register DIR *dirp;
+readdir(
+ register DIR *dirp)
{
- register struct olddirect *dp;
- static struct dirent dir;
+ register struct olddirect *dp;
+ static struct dirent dir;
- for (;;) {
- if (dirp->dd_loc == 0) {
- dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf,
- DIRBLKSIZ);
- if (dirp->dd_size <= 0)
- return NULL;
- }
- if (dirp->dd_loc >= dirp->dd_size) {
- dirp->dd_loc = 0;
- continue;
- }
- dp = (struct olddirect *)(dirp->dd_buf + dirp->dd_loc);
- dirp->dd_loc += sizeof(struct olddirect);
- if (dp->od_ino == 0)
- continue;
- dir.d_ino = dp->od_ino;
- strncpy(dir.d_name, dp->od_name, ODIRSIZ);
- dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */
- dir.d_namlen = strlen(dir.d_name);
- dir.d_reclen = DIRSIZ(&dir);
- return (&dir);
+ for (;;) {
+ if (dirp->dd_loc == 0) {
+ dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ);
+ if (dirp->dd_size <= 0) {
+ return NULL;
+ }
+ }
+ if (dirp->dd_loc >= dirp->dd_size) {
+ dirp->dd_loc = 0;
+ continue;
}
+ dp = (struct olddirect *)(dirp->dd_buf + dirp->dd_loc);
+ dirp->dd_loc += sizeof(struct olddirect);
+ if (dp->od_ino == 0) {
+ continue;
+ }
+ dir.d_ino = dp->od_ino;
+ strncpy(dir.d_name, dp->od_name, ODIRSIZ);
+ dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */
+ dir.d_namlen = strlen(dir.d_name);
+ dir.d_reclen = DIRSIZ(&dir);
+ return &dir;
+ }
}
/*
* close a directory.
*/
+
void
-closedir(dirp)
-register DIR *dirp;
+closedir(
+ register DIR *dirp)
{
- close(dirp->dd_fd);
- dirp->dd_fd = -1;
- dirp->dd_loc = 0;
- ckfree((char *) dirp);
+ close(dirp->dd_fd);
+ dirp->dd_fd = -1;
+ dirp->dd_loc = 0;
+ ckfree((char *) dirp);
}
diff --git a/compat/strftime.c b/compat/strftime.c
deleted file mode 100644
index 68016ac..0000000
--- a/compat/strftime.c
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
- * strftime.c --
- *
- * This file contains a modified version of the BSD 4.4 strftime
- * function.
- *
- * This file is a modified version of the strftime.c file from the BSD 4.4
- * source. See the copyright notice below for details on redistribution
- * restrictions. The "license.terms" file does not apply to this file.
- *
- * Changes 2002 Copyright (c) 2002 ActiveState Corporation.
- */
-
-/*
- * Copyright (c) 1989 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <time.h>
-#include <string.h>
-#include <locale.h>
-#include "tclInt.h"
-#include "tclPort.h"
-
-#define TM_YEAR_BASE 1900
-#define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0))
-
-typedef struct {
- const char *abday[7];
- const char *day[7];
- const char *abmon[12];
- const char *mon[12];
- const char *am_pm[2];
- const char *d_t_fmt;
- const char *d_fmt;
- const char *t_fmt;
- const char *t_fmt_ampm;
-} _TimeLocale;
-
-/*
- * This is the C locale default. On Windows, if we wanted to make this
- * localized, we would use GetLocaleInfo to get the correct values.
- * It may be acceptable to do localization of month/day names, as the
- * numerical values would be considered the locale-independent versions.
- */
-static const _TimeLocale _DefaultTimeLocale =
-{
- {
- "Sun","Mon","Tue","Wed","Thu","Fri","Sat",
- },
- {
- "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
- "Friday", "Saturday"
- },
- {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- },
- {
- "January", "February", "March", "April", "May", "June", "July",
- "August", "September", "October", "November", "December"
- },
- {
- "AM", "PM"
- },
- "%a %b %d %H:%M:%S %Y",
- "%m/%d/%y",
- "%H:%M:%S",
- "%I:%M:%S %p"
-};
-
-static const _TimeLocale *_CurrentTimeLocale = &_DefaultTimeLocale;
-
-static int isGMT;
-static size_t gsize;
-static char *pt;
-static int _add _ANSI_ARGS_((const char* str));
-static int _conv _ANSI_ARGS_((int n, int digits, int pad));
-static int _secs _ANSI_ARGS_((const struct tm *t));
-static size_t _fmt _ANSI_ARGS_((const char *format,
- const struct tm *t));
-static int ISO8601Week _ANSI_ARGS_((CONST struct tm* t, int *year ));
-
-size_t
-TclpStrftime(s, maxsize, format, t, useGMT)
- char *s;
- size_t maxsize;
- const char *format;
- const struct tm *t;
- int useGMT;
-{
- if (format[0] == '%' && format[1] == 'Q') {
- /* Format as a stardate */
- sprintf(s, "Stardate %2d%03d.%01d",
- (((t->tm_year + TM_YEAR_BASE) + 377) - 2323),
- (((t->tm_yday + 1) * 1000) /
- (365 + IsLeapYear((t->tm_year + TM_YEAR_BASE)))),
- (((t->tm_hour * 60) + t->tm_min)/144));
- return(strlen(s));
- }
-
- isGMT = useGMT;
- /*
- * We may be able to skip this for useGMT, but it should be harmless.
- * -- hobbs
- */
- tzset();
-
- pt = s;
- if ((gsize = maxsize) < 1)
- return(0);
- if (_fmt(format, t)) {
- *pt = '\0';
- return(maxsize - gsize);
- }
- return(0);
-}
-
-#define SUN_WEEK(t) (((t)->tm_yday + 7 - \
- ((t)->tm_wday)) / 7)
-#define MON_WEEK(t) (((t)->tm_yday + 7 - \
- ((t)->tm_wday ? (t)->tm_wday - 1 : 6)) / 7)
-
-static size_t
-_fmt(format, t)
- const char *format;
- const struct tm *t;
-{
-#ifdef WIN32
-#define BUF_SIZ 256
- TCHAR buf[BUF_SIZ];
- SYSTEMTIME syst = {
- t->tm_year + 1900,
- t->tm_mon + 1,
- t->tm_wday,
- t->tm_mday,
- t->tm_hour,
- t->tm_min,
- t->tm_sec,
- 0,
- };
-#endif
- for (; *format; ++format) {
- if (*format == '%') {
- ++format;
- if (*format == 'E') {
- /* Alternate Era */
- ++format;
- } else if (*format == 'O') {
- /* Alternate numeric symbols */
- ++format;
- }
- switch(*format) {
- case '\0':
- --format;
- break;
- case 'A':
- if (t->tm_wday < 0 || t->tm_wday > 6)
- return(0);
- if (!_add(_CurrentTimeLocale->day[t->tm_wday]))
- return(0);
- continue;
- case 'a':
- if (t->tm_wday < 0 || t->tm_wday > 6)
- return(0);
- if (!_add(_CurrentTimeLocale->abday[t->tm_wday]))
- return(0);
- continue;
- case 'B':
- if (t->tm_mon < 0 || t->tm_mon > 11)
- return(0);
- if (!_add(_CurrentTimeLocale->mon[t->tm_mon]))
- return(0);
- continue;
- case 'b':
- case 'h':
- if (t->tm_mon < 0 || t->tm_mon > 11)
- return(0);
- if (!_add(_CurrentTimeLocale->abmon[t->tm_mon]))
- return(0);
- continue;
- case 'C':
- if (!_conv((t->tm_year + TM_YEAR_BASE) / 100,
- 2, '0'))
- return(0);
- continue;
- case 'D':
- if (!_fmt("%m/%d/%y", t))
- return(0);
- continue;
- case 'd':
- if (!_conv(t->tm_mday, 2, '0'))
- return(0);
- continue;
- case 'e':
- if (!_conv(t->tm_mday, 2, ' '))
- return(0);
- continue;
- case 'g':
- {
- int year;
- ISO8601Week( t, &year );
- if ( !_conv( year%100, 2, '0' ) ) {
- return( 0 );
- }
- continue;
- }
- case 'G':
- {
- int year;
- ISO8601Week( t, &year );
- if ( !_conv( year, 4, '0' ) ) {
- return( 0 );
- }
- continue;
- }
- case 'H':
- if (!_conv(t->tm_hour, 2, '0'))
- return(0);
- continue;
- case 'I':
- if (!_conv(t->tm_hour % 12 ?
- t->tm_hour % 12 : 12, 2, '0'))
- return(0);
- continue;
- case 'j':
- if (!_conv(t->tm_yday + 1, 3, '0'))
- return(0);
- continue;
- case 'k':
- if (!_conv(t->tm_hour, 2, ' '))
- return(0);
- continue;
- case 'l':
- if (!_conv(t->tm_hour % 12 ?
- t->tm_hour % 12: 12, 2, ' '))
- return(0);
- continue;
- case 'M':
- if (!_conv(t->tm_min, 2, '0'))
- return(0);
- continue;
- case 'm':
- if (!_conv(t->tm_mon + 1, 2, '0'))
- return(0);
- continue;
- case 'n':
- if (!_add("\n"))
- return(0);
- continue;
- case 'p':
- if (!_add(_CurrentTimeLocale->am_pm[t->tm_hour >= 12]))
- return(0);
- continue;
- case 'R':
- if (!_fmt("%H:%M", t))
- return(0);
- continue;
- case 'r':
- if (!_fmt(_CurrentTimeLocale->t_fmt_ampm, t))
- return(0);
- continue;
- case 'S':
- if (!_conv(t->tm_sec, 2, '0'))
- return(0);
- continue;
- case 's':
- if (!_secs(t))
- return(0);
- continue;
- case 'T':
- if (!_fmt("%H:%M:%S", t))
- return(0);
- continue;
- case 't':
- if (!_add("\t"))
- return(0);
- continue;
- case 'U':
- if (!_conv(SUN_WEEK(t), 2, '0'))
- return(0);
- continue;
- case 'u':
- if (!_conv(t->tm_wday ? t->tm_wday : 7, 1, '0'))
- return(0);
- continue;
- case 'V':
- {
- int week = ISO8601Week( t, NULL );
- if (!_conv(week, 2, '0'))
- return(0);
- continue;
- }
- case 'W':
- if (!_conv(MON_WEEK(t), 2, '0'))
- return(0);
- continue;
- case 'w':
- if (!_conv(t->tm_wday, 1, '0'))
- return(0);
- continue;
-#ifdef WIN32
- /*
- * To properly handle the localized time routines on Windows,
- * we must make use of the special localized calls.
- */
- case 'c':
- if (!GetDateFormat(LOCALE_USER_DEFAULT,
- DATE_LONGDATE | LOCALE_USE_CP_ACP,
- &syst, NULL, buf, BUF_SIZ)
- || !_add(buf)
- || !_add(" ")) {
- return(0);
- }
- /*
- * %c is created with LONGDATE + " " + TIME on Windows,
- * so continue to %X case here.
- */
- case 'X':
- if (!GetTimeFormat(LOCALE_USER_DEFAULT,
- LOCALE_USE_CP_ACP,
- &syst, NULL, buf, BUF_SIZ)
- || !_add(buf)) {
- return(0);
- }
- continue;
- case 'x':
- if (!GetDateFormat(LOCALE_USER_DEFAULT,
- DATE_SHORTDATE | LOCALE_USE_CP_ACP,
- &syst, NULL, buf, BUF_SIZ)
- || !_add(buf)) {
- return(0);
- }
- continue;
-#else
- case 'c':
- if (!_fmt(_CurrentTimeLocale->d_t_fmt, t))
- return(0);
- continue;
- case 'x':
- if (!_fmt(_CurrentTimeLocale->d_fmt, t))
- return(0);
- continue;
- case 'X':
- if (!_fmt(_CurrentTimeLocale->t_fmt, t))
- return(0);
- continue;
-#endif
- case 'y':
- if (!_conv((t->tm_year + TM_YEAR_BASE) % 100,
- 2, '0'))
- return(0);
- continue;
- case 'Y':
- if (!_conv((t->tm_year + TM_YEAR_BASE), 4, '0'))
- return(0);
- continue;
- case 'Z': {
- char *name = (isGMT ? "GMT" : TclpGetTZName(t->tm_isdst));
- int wrote;
- Tcl_UtfToExternal(NULL, NULL, name, -1, 0, NULL,
- pt, gsize, NULL, &wrote, NULL);
- pt += wrote;
- gsize -= wrote;
- continue;
- }
- case '%':
- /*
- * X311J/88-090 (4.12.3.5): if conversion char is
- * undefined, behavior is undefined. Print out the
- * character itself as printf(3) does.
- */
- default:
- break;
- }
- }
- if (!gsize--)
- return(0);
- *pt++ = *format;
- }
- return(gsize);
-}
-
-static int
-_secs(t)
- const struct tm *t;
-{
- static char buf[15];
- register time_t s;
- register char *p;
- struct tm tmp;
-
- /* Make a copy, mktime(3) modifies the tm struct. */
- tmp = *t;
- s = mktime(&tmp);
- for (p = buf + sizeof(buf) - 2; s > 0 && p > buf; s /= 10)
- *p-- = (char)(s % 10 + '0');
- return(_add(++p));
-}
-
-static int
-_conv(n, digits, pad)
- int n, digits;
- int pad;
-{
- static char buf[10];
- register char *p;
-
- p = buf + sizeof( buf ) - 1;
- *p-- = '\0';
- if ( n == 0 ) {
- *p-- = '0'; --digits;
- } else {
- for (; n > 0 && p > buf; n /= 10, --digits)
- *p-- = (char)(n % 10 + '0');
- }
- while (p > buf && digits-- > 0)
- *p-- = (char) pad;
- return(_add(++p));
-}
-
-static int
-_add(str)
- const char *str;
-{
- for (;; ++pt, --gsize) {
- if (!gsize)
- return(0);
- if (!(*pt = *str++))
- return(1);
- }
-}
-
-static int
-ISO8601Week( t, year )
- CONST struct tm* t;
- int* year;
-{
- /* Find the day-of-year of the Thursday in
- * the week in question. */
-
- int ydayThursday;
- int week;
- if ( t->tm_wday == 0 ) {
- ydayThursday = t->tm_yday - 3;
- } else {
- ydayThursday = t->tm_yday - t->tm_wday + 4;
- }
-
- if ( ydayThursday < 0 ) {
-
- /* This is the last week of the previous year. */
- if ( IsLeapYear(( t->tm_year + TM_YEAR_BASE - 1 )) ) {
- ydayThursday += 366;
- } else {
- ydayThursday += 365;
- }
- week = ydayThursday / 7 + 1;
- if ( year != NULL ) {
- *year = t->tm_year + 1899;
- }
-
- } else if ( ( IsLeapYear(( t -> tm_year + TM_YEAR_BASE ))
- && ydayThursday >= 366 )
- || ( !IsLeapYear(( t -> tm_year
- + TM_YEAR_BASE ))
- && ydayThursday >= 365 ) ) {
-
- /* This is week 1 of the following year */
-
- week = 1;
- if ( year != NULL ) {
- *year = t->tm_year + 1901;
- }
-
- } else {
-
- week = ydayThursday / 7 + 1;
- if ( year != NULL ) {
- *year = t->tm_year + 1900;
- }
-
- }
-
- return week;
-
-}
diff --git a/compat/string.h b/compat/string.h
index fbf9cf8..4eb2b86 100644
--- a/compat/string.h
+++ b/compat/string.h
@@ -22,9 +22,7 @@
* it exists everywhere)
*/
-#ifndef MAC_TCL
#include <sys/types.h>
-#endif
#ifdef __APPLE__
extern VOID * memchr _ANSI_ARGS_((CONST VOID *s, int c, size_t n));
diff --git a/compat/strncasecmp.c b/compat/strncasecmp.c
index d00ea5b..76cf549 100644
--- a/compat/strncasecmp.c
+++ b/compat/strncasecmp.c
@@ -6,16 +6,16 @@
* Copyright (c) 1988-1993 The Regents of the University of California.
* Copyright (c) 1995-1996 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclPort.h"
/*
- * This array is designed for mapping upper and lower case letter
- * together for a case independent comparison. The mappings are
- * based upon ASCII character sequences.
+ * This array is designed for mapping upper and lower case letter together for
+ * a case independent comparison. The mappings are based upon ASCII character
+ * sequences.
*/
static unsigned char charmap[] = {
@@ -54,14 +54,11 @@ static unsigned char charmap[] = {
};
/*
- * Here are the prototypes just in case they are not included
- * in tclPort.h.
+ * Here are the prototypes just in case they are not included in tclPort.h.
*/
-int strncasecmp _ANSI_ARGS_((CONST char *s1,
- CONST char *s2, size_t n));
-int strcasecmp _ANSI_ARGS_((CONST char *s1,
- CONST char *s2));
+int strncasecmp(CONST char *s1, CONST char *s2, size_t n);
+int strcasecmp(CONST char *s1, CONST char *s2);
/*
*----------------------------------------------------------------------
@@ -71,9 +68,8 @@ int strcasecmp _ANSI_ARGS_((CONST char *s1,
* Compares two strings, ignoring case differences.
*
* Results:
- * Compares two null-terminated strings s1 and s2, returning -1, 0,
- * or 1 if s1 is lexicographically less than, equal to, or greater
- * than s2.
+ * Compares two null-terminated strings s1 and s2, returning -1, 0, or 1
+ * if s1 is lexicographically less than, equal to, or greater than s2.
*
* Side effects:
* None.
@@ -82,9 +78,9 @@ int strcasecmp _ANSI_ARGS_((CONST char *s1,
*/
int
-strcasecmp(s1, s2)
- CONST char *s1; /* First string. */
- CONST char *s2; /* Second string. */
+strcasecmp(
+ CONST char *s1, /* First string. */
+ CONST char *s2) /* Second string. */
{
unsigned char u1, u2;
@@ -106,9 +102,9 @@ strcasecmp(s1, s2)
* Compares two strings, ignoring case differences.
*
* Results:
- * Compares up to length chars of s1 and s2, returning -1, 0, or 1
- * if s1 is lexicographically less than, equal to, or greater
- * than s2 over those characters.
+ * Compares up to length chars of s1 and s2, returning -1, 0, or 1 if s1
+ * is lexicographically less than, equal to, or greater than s2 over
+ * those characters.
*
* Side effects:
* None.
@@ -117,10 +113,10 @@ strcasecmp(s1, s2)
*/
int
-strncasecmp(s1, s2, length)
- CONST char *s1; /* First string. */
- CONST char *s2; /* Second string. */
- size_t length; /* Maximum number of characters to compare
+strncasecmp(
+ CONST char *s1, /* First string. */
+ CONST char *s2, /* Second string. */
+ size_t length) /* Maximum number of characters to compare
* (stop earlier if the end of either string
* is reached). */
{
diff --git a/compat/strstr.c b/compat/strstr.c
index 98d567d..6698c9f 100644
--- a/compat/strstr.c
+++ b/compat/strstr.c
@@ -6,11 +6,11 @@
* Copyright (c) 1988-1993 The Regents of the University of California.
* Copyright (c) 1994 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
-#include <tcl.h>
+#include "tcl.h"
#ifndef NULL
#define NULL 0
#endif
@@ -23,12 +23,10 @@
* Locate the first instance of a substring in a string.
*
* Results:
- * If string contains substring, the return value is the
- * location of the first matching instance of substring
- * in string. If string doesn't contain substring, the
- * return value is 0. Matching is done on an exact
- * character-for-character basis with no wildcards or special
- * characters.
+ * If string contains substring, the return value is the location of the
+ * first matching instance of substring in string. If string doesn't
+ * contain substring, the return value is 0. Matching is done on an exact
+ * character-for-character basis with no wildcards or special characters.
*
* Side effects:
* None.
@@ -37,15 +35,16 @@
*/
char *
-strstr(string, substring)
- register char *string; /* String to search. */
- char *substring; /* Substring to try to find in string. */
+strstr(
+ register char *string, /* String to search. */
+ char *substring) /* Substring to try to find in string. */
{
register char *a, *b;
- /* First scan quickly through the two strings looking for a
- * single-character match. When it's found, then compare the
- * rest of the substring.
+ /*
+ * First scan quickly through the two strings looking for a
+ * single-character match. When it's found, then compare the rest of the
+ * substring.
*/
b = substring;
diff --git a/compat/strtod.c b/compat/strtod.c
index c5d4b96..1147825 100644
--- a/compat/strtod.c
+++ b/compat/strtod.c
@@ -11,7 +11,6 @@
*/
#include "tclInt.h"
-#include "tclPort.h"
#include <ctype.h>
#ifndef TRUE
@@ -61,20 +60,19 @@ static double powersOf10[] = { /* Table giving binary powers of 10. Entry */
*/
double
-strtod(string, endPtr)
- CONST char *string; /* A decimal ASCII floating-point number,
- * optionally preceded by white space.
- * Must have form "-I.FE-X", where I is the
- * integer part of the mantissa, F is the
- * fractional part of the mantissa, and X
- * is the exponent. Either of the signs
- * may be "+", "-", or omitted. Either I
- * or F may be omitted, or both. The decimal
- * point isn't necessary unless F is present.
- * The "E" may actually be an "e". E and X
- * may both be omitted (but not just one).
- */
- char **endPtr; /* If non-NULL, store terminating character's
+strtod(
+ CONST char *string, /* A decimal ASCII floating-point number,
+ * optionally preceded by white space. Must
+ * have form "-I.FE-X", where I is the integer
+ * part of the mantissa, F is the fractional
+ * part of the mantissa, and X is the
+ * exponent. Either of the signs may be "+",
+ * "-", or omitted. Either I or F may be
+ * omitted, or both. The decimal point isn't
+ * necessary unless F is present. The "E" may
+ * actually be an "e". E and X may both be
+ * omitted (but not just one). */
+ char **endPtr) /* If non-NULL, store terminating character's
* address here. */
{
int sign, expSign = FALSE;
@@ -83,19 +81,19 @@ strtod(string, endPtr)
register int c;
int exp = 0; /* Exponent read from "EX" field. */
int fracExp = 0; /* Exponent that derives from the fractional
- * part. Under normal circumstatnces, it is
+ * part. Under normal circumstatnces, it is
* the negative of the number of digits in F.
* However, if I is very long, the last digits
* of I get dropped (otherwise a long I with a
* large negative exponent could cause an
- * unnecessary overflow on I alone). In this
+ * unnecessary overflow on I alone). In this
* case, fracExp is incremented one for each
* dropped digit. */
int mantSize; /* Number of digits in mantissa. */
int decPt; /* Number of mantissa digits BEFORE decimal
* point. */
- CONST char *pExp; /* Temporarily holds location of exponent
- * in string. */
+ CONST char *pExp; /* Temporarily holds location of exponent in
+ * string. */
/*
* Strip off leading blanks and check for a sign.
@@ -134,10 +132,10 @@ strtod(string, endPtr)
}
/*
- * Now suck up the digits in the mantissa. Use two integers to
- * collect 9 digits each (this is faster than using floating-point).
- * If the mantissa has more than 18 digits, ignore the extras, since
- * they can't affect the value anyway.
+ * Now suck up the digits in the mantissa. Use two integers to collect 9
+ * digits each (this is faster than using floating-point). If the mantissa
+ * has more than 18 digits, ignore the extras, since they can't affect the
+ * value anyway.
*/
pExp = p;
@@ -145,7 +143,7 @@ strtod(string, endPtr)
if (decPt < 0) {
decPt = mantSize;
} else {
- mantSize -= 1; /* One of the digits was the point. */
+ mantSize -= 1; /* One of the digits was the point. */
}
if (mantSize > 18) {
fracExp = decPt - 18;
@@ -159,9 +157,9 @@ strtod(string, endPtr)
goto done;
} else {
int frac1, frac2;
+
frac1 = 0;
- for ( ; mantSize > 9; mantSize -= 1)
- {
+ for ( ; mantSize > 9; mantSize -= 1) {
c = *p;
p += 1;
if (c == '.') {
@@ -171,8 +169,7 @@ strtod(string, endPtr)
frac1 = 10*frac1 + (c - '0');
}
frac2 = 0;
- for (; mantSize > 0; mantSize -= 1)
- {
+ for (; mantSize > 0; mantSize -= 1) {
c = *p;
p += 1;
if (c == '.') {
@@ -216,10 +213,9 @@ strtod(string, endPtr)
}
/*
- * Generate a floating-point number that represents the exponent.
- * Do this by processing the exponent one bit at a time to combine
- * many powers of 2 of 10. Then combine the exponent with the
- * fraction.
+ * Generate a floating-point number that represents the exponent. Do this
+ * by processing the exponent one bit at a time to combine many powers of
+ * 2 of 10. Then combine the exponent with the fraction.
*/
if (exp < 0) {
@@ -244,7 +240,7 @@ strtod(string, endPtr)
fraction *= dblExp;
}
-done:
+ done:
if (endPtr != NULL) {
*endPtr = (char *) p;
}
diff --git a/compat/strtol.c b/compat/strtol.c
index bc21c4b..793f094 100644
--- a/compat/strtol.c
+++ b/compat/strtol.c
@@ -6,14 +6,12 @@
* Copyright (c) 1988 The Regents of the University of California.
* Copyright (c) 1994 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <ctype.h>
#include "tclInt.h"
-#include "tclPort.h"
-
/*
*----------------------------------------------------------------------
@@ -23,11 +21,10 @@
* Convert an ASCII string into an integer.
*
* Results:
- * The return value is the integer equivalent of string. If endPtr
- * is non-NULL, then *endPtr is filled in with the character
- * after the last one that was part of the integer. If string
- * doesn't contain a valid integer value, then zero is returned
- * and *endPtr is set to string.
+ * The return value is the integer equivalent of string. If endPtr is
+ * non-NULL, then *endPtr is filled in with the character after the last
+ * one that was part of the integer. If string doesn't contain a valid
+ * integer value, then zero is returned and *endPtr is set to string.
*
* Side effects:
* None.
@@ -36,20 +33,18 @@
*/
long int
-strtol(string, endPtr, base)
- CONST char *string; /* String of ASCII digits, possibly
- * preceded by white space. For bases
- * greater than 10, either lower- or
- * upper-case digits may be used.
- */
- char **endPtr; /* Where to store address of terminating
+strtol(
+ CONST char *string, /* String of ASCII digits, possibly preceded
+ * by white space. For bases greater than 10,
+ * either lower- or upper-case digits may be
+ * used. */
+ char **endPtr, /* Where to store address of terminating
* character, or NULL. */
- int base; /* Base for conversion. Must be less
- * than 37. If 0, then the base is chosen
- * from the leading characters of string:
- * "0x" means hex, "0" means octal, anything
- * else means decimal.
- */
+ int base) /* Base for conversion. Must be less than 37.
+ * If 0, then the base is chosen from the
+ * leading characters of string: "0x" means
+ * hex, "0" means octal, anything else means
+ * decimal. */
{
register CONST char *p;
long result;
diff --git a/compat/strtoll.c b/compat/strtoll.c
deleted file mode 100644
index a829d70..0000000
--- a/compat/strtoll.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * strtoll.c --
- *
- * Source code for the "strtoll" library procedure.
- *
- * Copyright (c) 1988 The Regents of the University of California.
- * Copyright (c) 1994 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include "tcl.h"
-#include "tclPort.h"
-#include <ctype.h>
-
-#define TCL_WIDEINT_MAX (((Tcl_WideUInt)Tcl_LongAsWide(-1))>>1)
-
-
-/*
- *----------------------------------------------------------------------
- *
- * strtoll --
- *
- * Convert an ASCII string into an integer.
- *
- * Results:
- * The return value is the integer equivalent of string. If endPtr
- * is non-NULL, then *endPtr is filled in with the character
- * after the last one that was part of the integer. If string
- * doesn't contain a valid integer value, then zero is returned
- * and *endPtr is set to string.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-#if TCL_WIDE_INT_IS_LONG
-long long
-#else
-Tcl_WideInt
-#endif
-strtoll(string, endPtr, base)
- CONST char *string; /* String of ASCII digits, possibly
- * preceded by white space. For bases
- * greater than 10, either lower- or
- * upper-case digits may be used.
- */
- char **endPtr; /* Where to store address of terminating
- * character, or NULL. */
- int base; /* Base for conversion. Must be less
- * than 37. If 0, then the base is chosen
- * from the leading characters of string:
- * "0x" means hex, "0" means octal, anything
- * else means decimal.
- */
-{
- register CONST char *p;
- Tcl_WideInt result = Tcl_LongAsWide(0);
- Tcl_WideUInt uwResult;
-
- /*
- * Skip any leading blanks.
- */
-
- p = string;
- while (isspace(UCHAR(*p))) {
- p += 1;
- }
-
- /*
- * Check for a sign.
- */
-
- errno = 0;
- if (*p == '-') {
- p += 1;
- uwResult = strtoull(p, endPtr, base);
- if (errno != ERANGE) {
- if (uwResult > TCL_WIDEINT_MAX+1) {
- errno = ERANGE;
- return Tcl_LongAsWide(-1);
- } else if (uwResult > TCL_WIDEINT_MAX) {
- return ~((Tcl_WideInt)TCL_WIDEINT_MAX);
- } else {
- result = -((Tcl_WideInt) uwResult);
- }
- }
- } else {
- if (*p == '+') {
- p += 1;
- }
- uwResult = strtoull(p, endPtr, base);
- if (errno != ERANGE) {
- if (uwResult > TCL_WIDEINT_MAX) {
- errno = ERANGE;
- return Tcl_LongAsWide(-1);
- } else {
- result = uwResult;
- }
- }
- }
- if ((result == 0) && (endPtr != 0) && (*endPtr == p)) {
- *endPtr = (char *) string;
- }
- return result;
-}
diff --git a/compat/strtoul.c b/compat/strtoul.c
index b9d2785..9d3f372 100644
--- a/compat/strtoul.c
+++ b/compat/strtoul.c
@@ -6,17 +6,16 @@
* Copyright (c) 1988 The Regents of the University of California.
* Copyright (c) 1994 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
/*
- * The table below is used to convert from ASCII digits to a
- * numerical equivalent. It maps from '0' through 'z' to integers
- * (100 for non-digit characters).
+ * The table below is used to convert from ASCII digits to a numerical
+ * equivalent. It maps from '0' through 'z' to integers (100 for non-digit
+ * characters).
*/
static char cvtIn[] = {
@@ -38,11 +37,10 @@ static char cvtIn[] = {
* Convert an ASCII string into an integer.
*
* Results:
- * The return value is the integer equivalent of string. If endPtr
- * is non-NULL, then *endPtr is filled in with the character
- * after the last one that was part of the integer. If string
- * doesn't contain a valid integer value, then zero is returned
- * and *endPtr is set to string.
+ * The return value is the integer equivalent of string. If endPtr is
+ * non-NULL, then *endPtr is filled in with the character after the last
+ * one that was part of the integer. If string doesn't contain a valid
+ * integer value, then zero is returned and *endPtr is set to string.
*
* Side effects:
* None.
@@ -51,20 +49,18 @@ static char cvtIn[] = {
*/
unsigned long int
-strtoul(string, endPtr, base)
- CONST char *string; /* String of ASCII digits, possibly
- * preceded by white space. For bases
- * greater than 10, either lower- or
- * upper-case digits may be used.
- */
- char **endPtr; /* Where to store address of terminating
+strtoul(
+ CONST char *string, /* String of ASCII digits, possibly preceded
+ * by white space. For bases greater than 10,
+ * either lower- or upper-case digits may be
+ * used. */
+ char **endPtr, /* Where to store address of terminating
* character, or NULL. */
- int base; /* Base for conversion. Must be less
- * than 37. If 0, then the base is chosen
- * from the leading characters of string:
- * "0x" means hex, "0" means octal, anything
- * else means decimal.
- */
+ int base) /* Base for conversion. Must be less than 37.
+ * If 0, then the base is chosen from the
+ * leading characters of string: "0x" means
+ * hex, "0" means octal, anything else means
+ * decimal. */
{
register CONST char *p;
register unsigned long int result = 0;
@@ -91,31 +87,29 @@ strtoul(string, endPtr, base)
}
/*
- * If no base was provided, pick one from the leading characters
- * of the string.
+ * If no base was provided, pick one from the leading characters of the
+ * string.
*/
- if (base == 0)
- {
+ if (base == 0) {
if (*p == '0') {
p += 1;
if ((*p == 'x') || (*p == 'X')) {
p += 1;
base = 16;
} else {
-
/*
- * Must set anyDigits here, otherwise "0" produces a
- * "no digits" error.
+ * Must set anyDigits here, otherwise "0" produces a "no
+ * digits" error.
*/
anyDigits = 1;
base = 8;
}
+ } else {
+ base = 10;
}
- else base = 10;
} else if (base == 16) {
-
/*
* Skip a leading "0x" from hex numbers.
*/
@@ -126,12 +120,13 @@ strtoul(string, endPtr, base)
}
/*
- * Sorry this code is so messy, but speed seems important. Do
- * different things for base 8, 10, 16, and other.
+ * Sorry this code is so messy, but speed seems important. Do different
+ * things for base 8, 10, 16, and other.
*/
if (base == 8) {
unsigned long maxres = ULONG_MAX >> 3;
+
for ( ; ; p += 1) {
digit = *p - '0';
if (digit > 7) {
@@ -145,6 +140,7 @@ strtoul(string, endPtr, base)
}
} else if (base == 10) {
unsigned long maxres = ULONG_MAX / 10;
+
for ( ; ; p += 1) {
digit = *p - '0';
if (digit > 9) {
@@ -158,6 +154,7 @@ strtoul(string, endPtr, base)
}
} else if (base == 16) {
unsigned long maxres = ULONG_MAX >> 4;
+
for ( ; ; p += 1) {
digit = *p - '0';
if (digit > ('z' - '0')) {
@@ -173,8 +170,9 @@ strtoul(string, endPtr, base)
result += digit;
anyDigits = 1;
}
- } else if ( base >= 2 && base <= 36 ) {
+ } else if (base >= 2 && base <= 36) {
unsigned long maxres = ULONG_MAX / base;
+
for ( ; ; p += 1) {
digit = *p - '0';
if (digit > ('z' - '0')) {
diff --git a/compat/strtoull.c b/compat/strtoull.c
deleted file mode 100644
index d0dd853..0000000
--- a/compat/strtoull.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * strtoull.c --
- *
- * Source code for the "strtoull" library procedure.
- *
- * Copyright (c) 1988 The Regents of the University of California.
- * Copyright (c) 1994 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include "tcl.h"
-#include "tclPort.h"
-#include <ctype.h>
-
-/*
- * The table below is used to convert from ASCII digits to a
- * numerical equivalent. It maps from '0' through 'z' to integers
- * (100 for non-digit characters).
- */
-
-static char cvtIn[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* '0' - '9' */
- 100, 100, 100, 100, 100, 100, 100, /* punctuation */
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 'A' - 'Z' */
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- 30, 31, 32, 33, 34, 35,
- 100, 100, 100, 100, 100, 100, /* punctuation */
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 'a' - 'z' */
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- 30, 31, 32, 33, 34, 35};
-
-
-/*
- *----------------------------------------------------------------------
- *
- * strtoull --
- *
- * Convert an ASCII string into an integer.
- *
- * Results:
- * The return value is the integer equivalent of string. If endPtr
- * is non-NULL, then *endPtr is filled in with the character
- * after the last one that was part of the integer. If string
- * doesn't contain a valid integer value, then zero is returned
- * and *endPtr is set to string.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-#if TCL_WIDE_INT_IS_LONG
-unsigned long long
-#else
-Tcl_WideUInt
-#endif
-strtoull(string, endPtr, base)
- CONST char *string; /* String of ASCII digits, possibly
- * preceded by white space. For bases
- * greater than 10, either lower- or
- * upper-case digits may be used.
- */
- char **endPtr; /* Where to store address of terminating
- * character, or NULL. */
- int base; /* Base for conversion. Must be less
- * than 37. If 0, then the base is chosen
- * from the leading characters of string:
- * "0x" means hex, "0" means octal, anything
- * else means decimal.
- */
-{
- register CONST char *p;
- register Tcl_WideUInt result = 0;
- register unsigned digit;
- register Tcl_WideUInt shifted;
- int anyDigits = 0, negative = 0;
-
- /*
- * Skip any leading blanks.
- */
-
- p = string;
- while (isspace(UCHAR(*p))) { /* INTL: locale-dependent */
- p += 1;
- }
-
- /*
- * Check for a sign.
- */
-
- if (*p == '-') {
- p += 1;
- negative = 1;
- } else {
- if (*p == '+') {
- p += 1;
- }
- }
-
- /*
- * If no base was provided, pick one from the leading characters
- * of the string.
- */
-
- if (base == 0) {
- if (*p == '0') {
- p += 1;
- if (*p == 'x' || *p == 'X') {
- p += 1;
- base = 16;
- } else {
-
- /*
- * Must set anyDigits here, otherwise "0" produces a
- * "no digits" error.
- */
-
- anyDigits = 1;
- base = 8;
- }
- } else {
- base = 10;
- }
- } else if (base == 16) {
-
- /*
- * Skip a leading "0x" from hex numbers.
- */
-
- if ((p[0] == '0') && (p[1] == 'x' || *p == 'X')) {
- p += 2;
- }
- }
-
- /*
- * Sorry this code is so messy, but speed seems important. Do
- * different things for base 8, 10, 16, and other.
- */
-
- if (base == 8) {
- for ( ; ; p += 1) {
- digit = *p - '0';
- if (digit > 7) {
- break;
- }
- shifted = result << 3;
- if ((shifted >> 3) != result) {
- goto overflow;
- }
- result = shifted + digit;
- if ( result < shifted ) {
- goto overflow;
- }
- anyDigits = 1;
- }
- } else if (base == 10) {
- for ( ; ; p += 1) {
- digit = *p - '0';
- if (digit > 9) {
- break;
- }
- shifted = 10 * result;
- if ((shifted / 10) != result) {
- goto overflow;
- }
- result = shifted + digit;
- if ( result < shifted ) {
- goto overflow;
- }
- anyDigits = 1;
- }
- } else if (base == 16) {
- for ( ; ; p += 1) {
- digit = *p - '0';
- if (digit > ('z' - '0')) {
- break;
- }
- digit = cvtIn[digit];
- if (digit > 15) {
- break;
- }
- shifted = result << 4;
- if ((shifted >> 4) != result) {
- goto overflow;
- }
- result = shifted + digit;
- if ( result < shifted ) {
- goto overflow;
- }
- anyDigits = 1;
- }
- } else if ( base >= 2 && base <= 36 ) {
- for ( ; ; p += 1) {
- digit = *p - '0';
- if (digit > ('z' - '0')) {
- break;
- }
- digit = cvtIn[digit];
- if (digit >= (unsigned) base) {
- break;
- }
- shifted = result * base;
- if ((shifted/base) != result) {
- goto overflow;
- }
- result = shifted + digit;
- if ( result < shifted ) {
- goto overflow;
- }
- anyDigits = 1;
- }
- }
-
- /*
- * Negate if we found a '-' earlier.
- */
-
- if (negative) {
- result = (Tcl_WideUInt)(-((Tcl_WideInt)result));
- }
-
- /*
- * See if there were any digits at all.
- */
-
- if (!anyDigits) {
- p = string;
- }
-
- if (endPtr != 0) {
- *endPtr = (char *) p;
- }
-
- return result;
-
- /*
- * On overflow generate the right output
- */
-
- overflow:
- errno = ERANGE;
- if (endPtr != 0) {
- for ( ; ; p += 1) {
- digit = *p - '0';
- if (digit > ('z' - '0')) {
- break;
- }
- digit = cvtIn[digit];
- if (digit >= (unsigned) base) {
- break;
- }
- }
- *endPtr = (char *) p;
- }
- return (Tcl_WideUInt)Tcl_LongAsWide(-1);
-}
diff --git a/compat/tclErrno.h b/compat/tclErrno.h
deleted file mode 100644
index f4e3680..0000000
--- a/compat/tclErrno.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * tclErrno.h --
- *
- * This header file contains the various POSIX errno definitions that
- * are used by Tcl. This file is derived from the spec POSIX 2.4 and
- * previous implementations for Berkeley UNIX.
- *
- * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
- * Copyright (c) 1996 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-extern int errno; /* global error number */
-
-#define EPERM 1 /* Operation not permitted */
-#define ENOENT 2 /* No such file or directory */
-#define ESRCH 3 /* No such process */
-#define EINTR 4 /* Interrupted system call */
-#define EIO 5 /* Input/output error */
-#define ENXIO 6 /* Device not configured */
-#define E2BIG 7 /* Argument list too long */
-#define ENOEXEC 8 /* Exec format error */
-#define EBADF 9 /* Bad file descriptor */
-#define ECHILD 10 /* No child processes */
-#define EDEADLK 11 /* Resource deadlock avoided */
- /* 11 was EAGAIN */
-#define ENOMEM 12 /* Cannot allocate memory */
-#define EACCES 13 /* Permission denied */
-#define EFAULT 14 /* Bad address */
-#define ENOTBLK 15 /* Block device required */
-#define EBUSY 16 /* Device busy */
-#define EEXIST 17 /* File exists */
-#define EXDEV 18 /* Cross-device link */
-#define ENODEV 19 /* Operation not supported by device */
-#define ENOTDIR 20 /* Not a directory */
-#define EISDIR 21 /* Is a directory */
-#define EINVAL 22 /* Invalid argument */
-#define ENFILE 23 /* Too many open files in system */
-#define EMFILE 24 /* Too many open files */
-#define ENOTTY 25 /* Inappropriate ioctl for device */
-#define ETXTBSY 26 /* Text file busy */
-#define EFBIG 27 /* File too large */
-#define ENOSPC 28 /* No space left on device */
-#define ESPIPE 29 /* Illegal seek */
-#define EROFS 30 /* Read-only file system */
-#define EMLINK 31 /* Too many links */
-#define EPIPE 32 /* Broken pipe */
-#define EDOM 33 /* Numerical argument out of domain */
-#define ERANGE 34 /* Result too large */
-#define EAGAIN 35 /* Resource temporarily unavailable */
-#define EWOULDBLOCK EAGAIN /* Operation would block */
-#define EINPROGRESS 36 /* Operation now in progress */
-#define EALREADY 37 /* Operation already in progress */
-#define ENOTSOCK 38 /* Socket operation on non-socket */
-#define EDESTADDRREQ 39 /* Destination address required */
-#define EMSGSIZE 40 /* Message too long */
-#define EPROTOTYPE 41 /* Protocol wrong type for socket */
-#define ENOPROTOOPT 42 /* Protocol not available */
-#define EPROTONOSUPPORT 43 /* Protocol not supported */
-#define ESOCKTNOSUPPORT 44 /* Socket type not supported */
-#define EOPNOTSUPP 45 /* Operation not supported on socket */
-#define EPFNOSUPPORT 46 /* Protocol family not supported */
-#define EAFNOSUPPORT 47 /* Address family not supported by protocol family */
-#define EADDRINUSE 48 /* Address already in use */
-#define EADDRNOTAVAIL 49 /* Can't assign requested address */
-#define ENETDOWN 50 /* Network is down */
-#define ENETUNREACH 51 /* Network is unreachable */
-#define ENETRESET 52 /* Network dropped connection on reset */
-#define ECONNABORTED 53 /* Software caused connection abort */
-#define ECONNRESET 54 /* Connection reset by peer */
-#define ENOBUFS 55 /* No buffer space available */
-#define EISCONN 56 /* Socket is already connected */
-#define ENOTCONN 57 /* Socket is not connected */
-#define ESHUTDOWN 58 /* Can't send after socket shutdown */
-#define ETOOMANYREFS 59 /* Too many references: can't splice */
-#define ETIMEDOUT 60 /* Connection timed out */
-#define ECONNREFUSED 61 /* Connection refused */
-#define ELOOP 62 /* Too many levels of symbolic links */
-#define ENAMETOOLONG 63 /* File name too long */
-#define EHOSTDOWN 64 /* Host is down */
-#define EHOSTUNREACH 65 /* No route to host */
-#define ENOTEMPTY 66 /* Directory not empty */
-#define EPROCLIM 67 /* Too many processes */
-#define EUSERS 68 /* Too many users */
-#define EDQUOT 69 /* Disc quota exceeded */
-#define ESTALE 70 /* Stale NFS file handle */
-#define EREMOTE 71 /* Too many levels of remote in path */
-#define EBADRPC 72 /* RPC struct is bad */
-#define ERPCMISMATCH 73 /* RPC version wrong */
-#define EPROGUNAVAIL 74 /* RPC prog. not avail */
-#define EPROGMISMATCH 75 /* Program version wrong */
-#define EPROCUNAVAIL 76 /* Bad procedure for program */
-#define ENOLCK 77 /* No locks available */
-#define ENOSYS 78 /* Function not implemented */
-#define EOVERFLOW 79 /* Value too large to be stored in data type */
diff --git a/compat/tmpnam.c b/compat/tmpnam.c
deleted file mode 100644
index 89ce5fb..0000000
--- a/compat/tmpnam.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of California at Berkeley. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific written prior permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-#include <stdio.h>
-
-/*
- * Use /tmp instead of /usr/tmp, because L_tmpname is only 14 chars
- * on some machines (like NeXT machines) and /usr/tmp will cause
- * buffer overflows.
- */
-
-#ifdef P_tmpdir
-# undef P_tmpdir
-#endif
-#define P_tmpdir "/tmp"
-
-char *
-tmpnam(s)
- char *s;
-{
- static char name[50];
- char *mktemp();
-
- if (!s)
- s = name;
- (void)sprintf(s, "%s/XXXXXX", P_tmpdir);
- return(mktemp(s));
-}
diff --git a/compat/waitpid.c b/compat/waitpid.c
index a5960ce..8f65799 100644
--- a/compat/waitpid.c
+++ b/compat/waitpid.c
@@ -1,19 +1,17 @@
/*
* waitpid.c --
*
- * This procedure emulates the POSIX waitpid kernel call on
- * BSD systems that don't have waitpid but do have wait3.
- * This code is based on a prototype version written by
- * Mark Diekhans and Karl Lehenbauer.
+ * This procedure emulates the POSIX waitpid kernel call on BSD systems
+ * that don't have waitpid but do have wait3. This code is based on a
+ * prototype version written by Mark Diekhans and Karl Lehenbauer.
*
* Copyright (c) 1993 The Regents of the University of California.
* Copyright (c) 1994 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
-#include "tclInt.h"
#include "tclPort.h"
#ifndef pid_t
@@ -21,40 +19,37 @@
#endif
/*
- * A linked list of the following structures is used to keep track
- * of processes for which we received notification from the kernel,
- * but the application hasn't waited for them yet (this can happen
- * because wait may not return the process we really want). We
- * save the information here until the application finally does
- * wait for the process.
+ * A linked list of the following structures is used to keep track of
+ * processes for which we received notification from the kernel, but the
+ * application hasn't waited for them yet (this can happen because wait may
+ * not return the process we really want). We save the information here until
+ * the application finally does wait for the process.
*/
typedef struct WaitInfo {
- pid_t pid; /* Pid of process that exited. */
- WAIT_STATUS_TYPE status; /* Status returned when child exited
- * or suspended. */
- struct WaitInfo *nextPtr; /* Next in list of exited processes. */
+ pid_t pid; /* Pid of process that exited. */
+ WAIT_STATUS_TYPE status; /* Status returned when child exited or
+ * suspended. */
+ struct WaitInfo *nextPtr; /* Next in list of exited processes. */
} WaitInfo;
-static WaitInfo *deadList = NULL; /* First in list of all dead
- * processes. */
+static WaitInfo *deadList = NULL;
+ /* First in list of all dead processes. */
/*
*----------------------------------------------------------------------
*
* waitpid --
*
- * This procedure emulates the functionality of the POSIX
- * waitpid kernel call, using the BSD wait3 kernel call.
- * Note: it doesn't emulate absolutely all of the waitpid
- * functionality, in that it doesn't support pid's of 0
- * or < -1.
+ * This procedure emulates the functionality of the POSIX waitpid kernel
+ * call, using the BSD wait3 kernel call. Note: it doesn't emulate
+ * absolutely all of the waitpid functionality, in that it doesn't
+ * support pid's of 0 or < -1.
*
* Results:
- * -1 is returned if there is an error in the wait kernel call.
- * Otherwise the pid of an exited or suspended process is
- * returned and *statusPtr is set to the status value of the
- * process.
+ * -1 is returned if there is an error in the wait kernel call. Otherwise
+ * the pid of an exited or suspended process is returned and *statusPtr
+ * is set to the status value of the process.
*
* Side effects:
* None.
@@ -67,12 +62,12 @@ static WaitInfo *deadList = NULL; /* First in list of all dead
#endif
pid_t
-waitpid(pid, statusPtr, options)
- pid_t pid; /* The pid to wait on. Must be -1 or
- * greater than zero. */
- int *statusPtr; /* Where to store wait status for the
+waitpid(
+ pid_t pid, /* The pid to wait on. Must be -1 or greater
+ * than zero. */
+ int *statusPtr, /* Where to store wait status for the
* process. */
- int options; /* OR'ed combination of WNOHANG and
+ int options) /* OR'ed combination of WNOHANG and
* WUNTRACED. */
{
register WaitInfo *waitPtr, *prevPtr;
@@ -85,9 +80,9 @@ waitpid(pid, statusPtr, options)
}
/*
- * See if there's a suitable process that has already stopped or
- * exited. If so, remove it from the list of exited processes and
- * return its information.
+ * See if there's a suitable process that has already stopped or exited.
+ * If so, remove it from the list of exited processes and return its
+ * information.
*/
for (waitPtr = deadList, prevPtr = NULL; waitPtr != NULL;
@@ -110,12 +105,12 @@ waitpid(pid, statusPtr, options)
}
/*
- * Wait for any process to stop or exit. If it's an acceptable one
- * then return it to the caller; otherwise store information about it
- * in the list of exited processes and try again. On systems that
- * have only wait but not wait3, there are several situations we can't
- * handle, but we do the best we can (e.g. can still handle some
- * combinations of options by invoking wait instead of wait3).
+ * Wait for any process to stop or exit. If it's an acceptable one then
+ * return it to the caller; otherwise store information about it in the
+ * list of exited processes and try again. On systems that have only wait
+ * but not wait3, there are several situations we can't handle, but we do
+ * the best we can (e.g. can still handle some combinations of options by
+ * invoking wait instead of wait3).
*/
while (1) {
@@ -148,13 +143,13 @@ waitpid(pid, statusPtr, options)
return result;
/*
- * Can't return this info to caller. Save it in the list of
- * stopped or exited processes. Tricky point: first check for
- * an existing entry for the process and overwrite it if it
- * exists (e.g. a previously stopped process might now be dead).
+ * Can't return this info to caller. Save it in the list of stopped or
+ * exited processes. Tricky point: first check for an existing entry
+ * for the process and overwrite it if it exists (e.g. a previously
+ * stopped process might now be dead).
*/
- saveInfo:
+ saveInfo:
for (waitPtr = deadList; waitPtr != NULL; waitPtr = waitPtr->nextPtr) {
if (waitPtr->pid == result) {
waitPtr->status = status;
@@ -167,6 +162,7 @@ waitpid(pid, statusPtr, options)
waitPtr->nextPtr = deadList;
deadList = waitPtr;
- waitAgain: continue;
+ waitAgain:
+ continue;
}
}
diff --git a/doc/Access.3 b/doc/Access.3
index cab6466..98d6635 100644
--- a/doc/Access.3
+++ b/doc/Access.3
@@ -19,7 +19,7 @@ int
int
\fBTcl_Stat\fR(\fIpath\fR, \fIstatPtr\fR)
.SH ARGUMENTS
-.AS "struct stat" *statPtr in
+.AS "struct stat" *statPtr out
.AP char *path in
Native name of the file to check the attributes of.
.AP int mode in
diff --git a/doc/AddErrInfo.3 b/doc/AddErrInfo.3
index 7351dce..45a0c41 100644
--- a/doc/AddErrInfo.3
+++ b/doc/AddErrInfo.3
@@ -6,17 +6,29 @@
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
-.TH Tcl_AddErrorInfo 3 8.0 Tcl "Tcl Library Procedures"
+.TH Tcl_AddErrorInfo 3 8.5 Tcl "Tcl Library Procedures"
.BS
.SH NAME
-Tcl_AddObjErrorInfo, Tcl_AddErrorInfo, Tcl_SetObjErrorCode, Tcl_SetErrorCode, Tcl_SetErrorCodeVA, Tcl_PosixError, Tcl_LogCommandInfo \- record information about errors
+Tcl_GetReturnOptions, Tcl_SetReturnOptions, Tcl_AddErrorInfo, Tcl_AppendObjToErrorInfo, Tcl_AddObjErrorInfo, Tcl_SetObjErrorCode, Tcl_SetErrorCode, Tcl_SetErrorCodeVA, Tcl_PosixError, Tcl_LogCommandInfo \- retrieve or record information about errors and other return options
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
+.VS 8.5
.sp
-\fBTcl_AddObjErrorInfo\fR(\fIinterp, message, length\fR)
+Tcl_Obj *
+\fBTcl_GetReturnOptions\fR(\fIinterp, code\fR)
+.sp
+int
+\fBTcl_SetReturnOptions\fR(\fIinterp, options\fR)
+.VE 8.5
.sp
\fBTcl_AddErrorInfo\fR(\fIinterp, message\fR)
+.VS 8.5
+.sp
+\fBTcl_AppendObjToErrorInfo\fR(\fIinterp, objPtr\fR)
+.VE 8.5
+.sp
+\fBTcl_AddObjErrorInfo\fR(\fIinterp, message, length\fR)
.sp
\fBTcl_SetObjErrorCode\fR(\fIinterp, errorObjPtr\fR)
.sp
@@ -24,38 +36,47 @@ Tcl_AddObjErrorInfo, Tcl_AddErrorInfo, Tcl_SetObjErrorCode, Tcl_SetErrorCode, Tc
.sp
\fBTcl_SetErrorCodeVA\fR(\fIinterp, argList\fR)
.sp
-CONST char *
+const char *
\fBTcl_PosixError\fR(\fIinterp\fR)
.sp
void
\fBTcl_LogCommandInfo\fR(\fIinterp, script, command, commandLength\fR)
.SH ARGUMENTS
-.AS Tcl_Interp *message
+.AS Tcl_Interp commandLength
.AP Tcl_Interp *interp in
Interpreter in which to record information.
+.AP int code
+The code returned from script evaluation.
+.AP Tcl_Obj *options
+A dictionary of return options.
.AP char *message in
+For \fBTcl_AddErrorInfo\fR,
+this is a conventional C string to append to the \fB\-errorinfo\fR return option.
For \fBTcl_AddObjErrorInfo\fR,
-this points to the first byte of an array of bytes
-containing a string to record in the \fBerrorInfo\fR variable.
+this points to the first byte of an array of \fIlength\fR bytes
+containing a string to append to the \fB\-errorinfo\fR return option.
This byte array may contain embedded null bytes
unless \fIlength\fR is negative.
-For \fBTcl_AddErrorInfo\fR,
-this is a conventional C string to record in the \fBerrorInfo\fR variable.
+.VS 8.5
+.AP Tcl_Obj *objPtr in
+A message to be appended to the \fB\-errorinfo\fR return option
+in the form of a Tcl_Obj value.
+.VE 8.5
.AP int length in
The number of bytes to copy from \fImessage\fR when
-setting the \fBerrorInfo\fR variable.
+appending to the \fB\-errorinfo\fR return option.
If negative, all bytes up to the first null byte are used.
.AP Tcl_Obj *errorObjPtr in
-This variable \fBerrorCode\fR will be set to this value.
+The \fB\-errorcode\fR return option will be set to this value.
.AP char *element in
-String to record as one element of \fBerrorCode\fR variable.
+String to record as one element of the \fB\-errorcode\fR return option.
Last \fIelement\fR argument must be NULL.
.AP va_list argList in
An argument list which must have been initialized using
-\fBTCL_VARARGS_START\fR, and cleared using \fBva_end\fR.
-.AP "CONST char" *script in
+\fBva_start\fR, and cleared using \fBva_end\fR.
+.AP "const char" *script in
Pointer to first character in script containing command (must be <= command)
-.AP "CONST char" *command in
+.AP "const char" *command in
Pointer to first character in command that generated the error
.AP int commandLength in
Number of bytes in command; -1 means use all bytes up to first null byte
@@ -63,70 +84,156 @@ Number of bytes in command; -1 means use all bytes up to first null byte
.SH DESCRIPTION
.PP
-These procedures are used to manipulate two Tcl global variables
-that hold information about errors.
-The variable \fBerrorInfo\fR holds a stack trace of the
+.VS 8.5
+The \fBTcl_SetReturnOptions\fR and \fBTcl_GetReturnOptions\fR
+routines expose the same capabilities as the \fBreturn\fR and
+\fBcatch\fR commands, respectively, in the form of a C interface.
+.PP
+\fBTcl_GetReturnOptions\fR retrieves the dictionary of return options
+from an interpreter following a script evaluation.
+Routines such as \fBTcl_Eval\fR are called to evaluate a
+script in an interpreter. These routines return an integer
+completion code. These routines also leave in the interpreter
+both a result and a dictionary of return options generated
+by script evaluation. Just as \fBTcl_GetObjResult\fR retrieves
+the result, \fBTcl_GetReturnOptions\fR retrieves the dictionary
+of return options. The integer completion code should be
+passed as the \fIcode\fR argument to \fBTcl_GetReturnOptions\fR
+so that all required options will be present in the dictionary.
+Specifically, a \fIcode\fR value of \fBTCL_ERROR\fR will
+ensure that entries for the keys \fB\-errorinfo\fR,
+\fB\-errorcode\fR, and \fB\-errorline\fR will appear in the
+dictionary. Also, the entries for the keys \fB\-code\fR
+and \fB\-level\fR will be adjusted if necessary to agree
+with the value of \fIcode\fR. The \fB(Tcl_Obj *)\fR returned
+by \fBTcl_GetReturnOptions\fR points to an unshared
+\fBTcl_Obj\fR with reference count of zero. The dictionary
+may be written to, either adding, removing, or overwriting
+any entries in it, with the need to check for a shared object.
+.PP
+A typical usage for \fBTcl_GetReturnOptions\fR is to
+retrieve the stack trace when script evaluation returns
+\fBTCL_ERROR\fR, like so:
+.CS
+int code = Tcl_Eval(interp, script);
+if (code == TCL_ERROR) {
+ Tcl_Obj *options = Tcl_GetReturnOptions(interp, code);
+ Tcl_Obj *key = Tcl_NewStringObj("-errorinfo", -1);
+ Tcl_Obj *stackTrace;
+ Tcl_IncrRefCount(key);
+ Tcl_DictObjGet(NULL, options, key, &stackTrace);
+ Tcl_DecrRefCount(key);
+ /* Do something with stackTrace */
+}
+.CE
+.PP
+\fBTcl_SetReturnOptions\fR sets the return options
+of \fIinterp\fR to be \fIoptions\fR. If \fIoptions\fR
+contains any invalid value for any key, TCL_ERROR will
+be returned, and the interp result will be set to an
+appropriate error message. Otherwise, a completion code
+in agreement with the \fB\-code\fR and \fB\-level\fR
+keys in \fIoptions\fR will be returned.
+.PP
+As an example, Tcl's \fBreturn\fR command itself could
+be implemented in terms of \fBTcl_SetReturnOptions\fR
+like so:
+.CS
+if ((objc % 2) == 0) { /* explicit result argument */
+ objc--;
+ Tcl_SetObjResult(interp, objv[objc]);
+}
+return Tcl_SetReturnOptions(interp, Tcl_NewListObj(objc-1, objv+1));
+.CE
+(It is not really implemented that way. Internal access
+privileges allow for a more efficient alternative that meshes
+better with the bytecode compiler.)
+.PP
+Note that a newly created \fBTcl_Obj\fR may be passed
+in as the \fIoptions\fR argument without the need to tend
+to any reference counting. This is analogous to
+\fBTcl_SetObjResult\fR.
+.PP
+While \fBTcl_SetReturnOptions\fR provides a general interface
+to set any collection of return options, there are a handful
+of return options that are very frequently used. Most
+notably the \fB\-errorinfo\fR and \fB\-errorcode\fR return
+options should be set properly when the command procedure
+of a command returns \fBTCL_ERROR\fR. Tcl provides several
+simpler interfaces to more directly set these return options.
+.VE 8.5
+.PP
+The \fB\-errorinfo\fR option holds a stack trace of the
operations that were in progress when an error occurred,
and is intended to be human-readable.
-The variable \fBerrorCode\fR holds a list of items that
+The \fB\-errorcode\fR option holds a list of items that
are intended to be machine-readable.
-The first item in \fBerrorCode\fR identifies the class of
+The first item in the \fB\-errorcode\fR value identifies the class of
error that occurred
(e.g. POSIX means an error occurred in a POSIX system call)
-and additional elements in \fBerrorCode\fR hold additional pieces
+and additional elements hold additional pieces
of information that depend on the class.
-See the Tcl overview manual entry for details on the various
-formats for \fBerrorCode\fR.
+See the tclvars manual entry for details on the various
+formats for the \fB\-errorcode\fR option used by
+Tcl's built-in commands.
.PP
-The \fBerrorInfo\fR variable is gradually built up as an
+The \fB\-errorinfo\fR option value is gradually built up as an
error unwinds through the nested operations.
-Each time an error code is returned to \fBTcl_EvalObjEx\fR
-(or \fBTcl_Eval\fR, which calls \fBTcl_EvalObjEx\fR)
-it calls the procedure \fBTcl_AddObjErrorInfo\fR to add
-additional text to \fBerrorInfo\fR describing the
+Each time an error code is returned to \fBTcl_Eval\fR, or
+any of the routines that performs script evaluation,
+the procedure \fBTcl_AddErrorInfo\fR is called to add
+additional text to the \fB\-errorinfo\fR value describing the
command that was being executed when the error occurred.
By the time the error has been passed all the way back
to the application, it will contain a complete trace
of the activity in progress when the error occurred.
.PP
It is sometimes useful to add additional information to
-\fBerrorInfo\fR beyond what can be supplied automatically
-by \fBTcl_EvalObjEx\fR.
-\fBTcl_AddObjErrorInfo\fR may be used for this purpose:
-its \fImessage\fR and \fIlength\fR arguments describe an additional
-string to be appended to \fBerrorInfo\fR.
-For example, the \fBsource\fR command calls \fBTcl_AddObjErrorInfo\fR
-to record the name of the file being processed and the
-line number on which the error occurred;
-for Tcl procedures, the procedure name and line number
+the \fB\-errorinfo\fR value beyond what can be supplied automatically
+by the script evaluation routines.
+\fBTcl_AddErrorInfo\fR may be used for this purpose:
+its \fImessage\fR argument is an additional
+string to be appended to the \fB\-errorinfo\fR option.
+For example, when an error arises during the \fBsource\fR command,
+the procedure \fBTcl_AddErrorInfo\fR is called to
+record the name of the file being processed and the
+line number on which the error occurred.
+Likewise, when an error arises during evaluation of a
+Tcl procedures, the procedure name and line number
within the procedure are recorded, and so on.
-The best time to call \fBTcl_AddObjErrorInfo\fR is just after
-\fBTcl_EvalObjEx\fR has returned \fBTCL_ERROR\fR.
-In calling \fBTcl_AddObjErrorInfo\fR, you may find it useful to
-use the \fBerrorLine\fR field of the interpreter (see the
-\fBTcl_Interp\fR manual entry for details).
-.PP
-\fBTcl_AddErrorInfo\fR resembles \fBTcl_AddObjErrorInfo\fR
-but differs in initializing \fBerrorInfo\fR from the string
-value of the interpreter's result
-if the error is just starting to be logged.
-It does not use the result as a Tcl object
-so any embedded null characters in the result
-will cause information to be lost.
-It also takes a conventional C string in \fImessage\fR
-instead of \fBTcl_AddObjErrorInfo\fR's counted string.
+The best time to call \fBTcl_AddErrorInfo\fR is just after
+a script evaluation routine has returned \fBTCL_ERROR\fR.
+The value of the \fB\-errorline\fR return option (retrieved
+via a call to \fBTcl_GetReturnOptions\fR) often makes up
+a useful part of the \fImessage\fR passed to \fBTcl_AddErrorInfo\fR.
+.PP
+.VS 8.5
+\fBTcl_AppendObjToErrorInfo\fR is an alternative interface to the
+same functionality as \fBTcl_AddErrorInfo\fR. \fBTcl_AppendObjToErrorInfo\fR
+is called when the string value to be appended to the \fB\-errorinfo\fR option
+is available as a \fBTcl_Obj\fR instead of as a \fBchar\fR array.
+.VE 8.5
+.PP
+\fBTcl_AddObjErrorInfo\fR is nearly identical
+to \fBTcl_AddErrorInfo\fR, except that it has an additional \fIlength\fR
+argument. This allows the \fImessage\fR string to contain
+embedded null bytes. This is essentially never a good idea.
+If the \fImessage\fR needs to contain the null character \fBU+0000\fR,
+Tcl's usual internal encoding rules should be used to avoid
+the need for a null byte. If the \fBTcl_AddObjErrorInfo\fR
+interface is used at all, it should be with a negative \fIlength\fR value.
.PP
The procedure \fBTcl_SetObjErrorCode\fR is used to set the
-\fBerrorCode\fR variable. \fIerrorObjPtr\fR contains a list object
-built up by the caller. \fBerrorCode\fR is set to this
-value. \fBTcl_SetObjErrorCode\fR is typically invoked just
-before returning an error in an object command. If an error is
+\fB\-errorcode\fR return option to the list object \fIerrorObjPtr\fR
+built up by the caller.
+\fBTcl_SetObjErrorCode\fR is typically invoked just
+before returning an error. If an error is
returned without calling \fBTcl_SetObjErrorCode\fR or
\fBTcl_SetErrorCode\fR the Tcl interpreter automatically sets
-\fBerrorCode\fR to \fBNONE\fR.
+the \fB\-errorcode\fR return option to \fBNONE\fR.
.PP
The procedure \fBTcl_SetErrorCode\fR is also used to set the
-\fBerrorCode\fR variable. However, it takes one or more strings to
+\fB\-errorcode\fR return option. However, it takes one or more strings to
record instead of an object. Otherwise, it is similar to
\fBTcl_SetObjErrorCode\fR in behavior.
.PP
@@ -134,9 +241,10 @@ record instead of an object. Otherwise, it is similar to
instead of taking a variable number of arguments it takes an argument list.
.PP
\fBTcl_PosixError\fR
-sets the \fBerrorCode\fR variable after an error in a POSIX kernel call.
+sets the \fB\-errorcode\fR variable after an error in a POSIX kernel call.
It reads the value of the \fBerrno\fR C variable and calls
-\fBTcl_SetErrorCode\fR to set \fBerrorCode\fR in the \fBPOSIX\fR format.
+\fBTcl_SetErrorCode\fR to set the \fB\-errorcode\fR return
+option in the \fBPOSIX\fR format.
The caller must previously have called \fBTcl_SetErrno\fR to set
\fBerrno\fR; this is necessary on some platforms (e.g. Windows) where Tcl
is linked into an application as a shared library, or when the error
@@ -146,41 +254,44 @@ occurs in a dynamically loaded extension. See the manual entry for
\fBTcl_PosixError\fR returns a human-readable diagnostic message
for the error
(this is the same value that will appear as the third element
-in \fBerrorCode\fR).
+in the \fB\-errorcode\fR value).
It may be convenient to include this string as part of the
error message returned to the application in
the interpreter's result.
.PP
\fBTcl_LogCommandInfo\fR is invoked after an error occurs in an
interpreter. It adds information about the command that was being
-executed when the error occurred to the \fBerrorInfo\fR variable, and
-the line number stored internally in the interpreter is set. On the
-first call to \fBTcl_LogCommandInfo\fR or \fBTcl_AddObjErrorInfo\fR
-since an error occurred, the old information in \fBerrorInfo\fR is
-deleted.
+executed when the error occurred to the \fB\-errorinfo\fR value, and
+the line number stored internally in the interpreter is set.
+.PP
+In older releases of Tcl, there was no \fBTcl_GetReturnOptions\fR
+routine. In its place, the global Tcl variables \fBerrorInfo\fR
+and \fBerrorCode\fR were the only place to retrieve the error
+information. Much existing code written for older Tcl releases
+still access this information via those global variables.
.PP
-It is important to call the procedures described here rather than
+It is important to realize that while reading from those
+global variables remains a supported way to access these
+return option values, it is important not to assume that
+writing to those global variables will properly set the
+corresponding return options. It has long been emphasized
+in this manual page that it is important to
+call the procedures described here rather than
setting \fBerrorInfo\fR or \fBerrorCode\fR directly with
\fBTcl_ObjSetVar2\fR.
-The reason for this is that the Tcl interpreter keeps information
-about whether these procedures have been called.
-For example, the first time \fBTcl_AddObjErrorInfo\fR is called
-for an error, it clears the existing value of \fBerrorInfo\fR
-and adds the error message in the interpreter's result to the variable
-before appending \fImessage\fR;
-in subsequent calls, it just appends the new \fImessage\fR.
-When \fBTcl_SetErrorCode\fR is called, it sets a flag indicating
-that \fBerrorCode\fR has been set;
-this allows the Tcl interpreter to set \fBerrorCode\fR to \fBNONE\fR
-if it receives an error return
-when \fBTcl_SetErrorCode\fR hasn't been called.
.PP
If the procedure \fBTcl_ResetResult\fR is called,
-it clears all of the state associated with
-\fBerrorInfo\fR and \fBerrorCode\fR
-(but it doesn't actually modify the variables).
-If an error had occurred, this will clear the error state to
-make it appear as if no error had occurred after all.
+it clears all of the state of the interpreter associated with
+script evaluation, including the entire return options dictionary.
+In particular, the \fB\-errorinfo\fR and \fB\-errorcode\fR options
+are reset.
+If an error had occurred, the \fBTcl_ResetResult\fR call will
+clear the error state to make it appear as if no error had
+occurred after all.
+The global variables \fBerrorInfo\fR and
+\fBerrorCode\fR are not modified by \fBTcl_ResetResult\fR
+so they continue to hold a record of information about the
+most recent error seen in an interpreter.
.SH "SEE ALSO"
Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_Interp, Tcl_ResetResult, Tcl_SetErrno
diff --git a/doc/Alloc.3 b/doc/Alloc.3
index e90114d..ca4f949 100644
--- a/doc/Alloc.3
+++ b/doc/Alloc.3
@@ -67,22 +67,24 @@ further allocation.
\fBTcl_Realloc\fR changes the size of the block pointed to by
\fIptr\fR to \fIsize\fR bytes and returns a pointer to the new block.
The contents will be unchanged up to the lesser of the new and old
-sizes. The returned location may be different from \fIptr\fR.
+sizes. The returned location may be different from \fIptr\fR. If
+\fIptr\fR is NULL, this is equivalent to calling \fBTcl_Alloc\fR with
+just the \fIsize\fR argument.
.PP
\fBTcl_AttemptAlloc\fR and \fBTcl_AttemptRealloc\fR are identical in
function to \fBTcl_Alloc\fR and \fBTcl_Realloc\fR, except that
\fBTcl_AttemptAlloc\fR and \fBTcl_AttemptRealloc\fR will not cause the Tcl
interpreter to \fBpanic\fR if the memory allocation fails. If the
allocation fails, these functions will return NULL. Note that on some
-platforms, attempting to allocate a block of memory will also cause
-these functions to return NULL.
+platforms, but not all, attempting to allocate a zero-sized block of
+memory will also cause these functions to return NULL.
.PP
The procedures \fBckalloc\fR, \fBckfree\fR, \fBckrealloc\fR,
\fBattemptckalloc\fR, and \fBattemptckrealloc\fR are implemented
as macros. Normally, they are synonyms for the corresponding
procedures documented on this page. When Tcl and all modules
calling Tcl are compiled with \fBTCL_MEM_DEBUG\fR defined, however,
-these macros are redefined to be special debugging versions of
+these macros are redefined to be special debugging versions
of these procedures. To support Tcl's memory debugging within a
module, use the macros rather than direct calls to \fBTcl_Alloc\fR, etc.
diff --git a/doc/AllowExc.3 b/doc/AllowExc.3
index 621ea47..ae595f1 100644
--- a/doc/AllowExc.3
+++ b/doc/AllowExc.3
@@ -16,7 +16,7 @@ Tcl_AllowExceptions \- allow all exceptions in next script evaluation
.sp
\fBTcl_AllowExceptions\fR(\fIinterp\fR)
.SH ARGUMENTS
-.AS Tcl_Interp *doublePtr
+.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Interpreter in which script will be evaluated.
.BE
@@ -25,8 +25,8 @@ Interpreter in which script will be evaluated.
.PP
If a script is evaluated at top-level (i.e. no other scripts are
pending evaluation when the script is invoked), and if the script
-terminates with a completion code other than TCL_OK, TCL_ERROR
-or TCL_RETURN, then Tcl normally converts this into a TCL_ERROR
+terminates with a completion code other than \fBTCL_OK\fR, \fBTCL_ERROR\fR
+or \fBTCL_RETURN\fR, then Tcl normally converts this into a \fBTCL_ERROR\fR
return with an appropriate message. The particular script
evaluation procedures of Tcl that act in the manner are
\fBTcl_EvalObjEx\fR, \fBTcl_EvalObjv\fR, \fBTcl_Eval\fR, \fBTcl_EvalEx\fR,
@@ -38,7 +38,7 @@ calling one of those a procedures, then arbitrary completion
codes are permitted from the script, and they are returned without
modification.
This is useful in cases where the caller can deal with exceptions
-such as TCL_BREAK or TCL_CONTINUE in a meaningful way.
+such as \fBTCL_BREAK\fR or \fBTCL_CONTINUE\fR in a meaningful way.
.SH KEYWORDS
continue, break, exception, interpreter
diff --git a/doc/AppInit.3 b/doc/AppInit.3
index 14d30cf..0473090 100644
--- a/doc/AppInit.3
+++ b/doc/AppInit.3
@@ -24,7 +24,9 @@ Interpreter for the application.
.SH DESCRIPTION
.PP
-\fBTcl_AppInit\fR is a ``hook'' procedure that is invoked by
+\fBTcl_AppInit\fR is a
+.QW hook
+procedure that is invoked by
the main programs for Tcl applications such as \fBtclsh\fR and \fBwish\fR.
Its purpose is to allow new Tcl applications to be created without
modifying the main programs provided as part of Tcl and Tk.
@@ -47,8 +49,8 @@ Tcl variables \fBargv\fR and \fBargv0\fR in \fIinterp\fR.
.IP [3]
Invoke a startup script to initialize the application.
.LP
-\fBTcl_AppInit\fR returns TCL_OK or TCL_ERROR.
-If it returns TCL_ERROR then it must leave an error message in
+\fBTcl_AppInit\fR returns \fBTCL_OK\fR or \fBTCL_ERROR\fR.
+If it returns \fBTCL_ERROR\fR then it must leave an error message in
for the interpreter's result; otherwise the result is ignored.
.PP
In addition to \fBTcl_AppInit\fR, your application should also contain
@@ -58,7 +60,7 @@ Tcl_Main(argc, argv, Tcl_AppInit);
.CE
The third argument to \fBTcl_Main\fR gives the address of the
application-specific initialization procedure to invoke.
-This means that you don't have to use the name \fBTcl_AppInit\fR
+This means that you do not have to use the name \fBTcl_AppInit\fR
for the procedure, but in practice the name is nearly always
\fBTcl_AppInit\fR (in versions before Tcl 7.4 the name \fBTcl_AppInit\fR
was implicit; there was no way to specify the procedure explicitly).
diff --git a/doc/AssocData.3 b/doc/AssocData.3
index 105ebd6..e4c7bab 100644
--- a/doc/AssocData.3
+++ b/doc/AssocData.3
@@ -8,9 +8,7 @@
.TH Tcl_SetAssocData 3 7.5 Tcl "Tcl Library Procedures"
.BS
.SH NAME
-Tcl_GetAssocData, Tcl_SetAssocData, Tcl_DeleteAssocData \- manage
-associations of string keys and user specified data with Tcl
-interpreters.
+Tcl_GetAssocData, Tcl_SetAssocData, Tcl_DeleteAssocData \- manage associations of string keys and user specified data with Tcl interpreters
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -22,12 +20,10 @@ ClientData
.sp
\fBTcl_DeleteAssocData\fR(\fIinterp, key\fR)
.SH ARGUMENTS
-.AS Tcl_InterpDeleteProc *delProcPtr
+.AS Tcl_InterpDeleteProc **delProcPtr
.AP Tcl_Interp *interp in
Interpreter in which to execute the specified command.
-.VS 8.4
-.AP "CONST char" *key in
-.VE
+.AP "const char" *key in
Key for association with which to store data or from which to delete or
retrieve data. Typically the module prefix for a package.
.AP Tcl_InterpDeleteProc *delProc in
@@ -67,8 +63,8 @@ is deleted. \fIDeleteProc\fR should have arguments and result that match
the type \fBTcl_InterpDeleteProc\fR:
.CS
typedef void Tcl_InterpDeleteProc(
- ClientData \fIclientData\fR,
- Tcl_Interp *\fIinterp\fR);
+ ClientData \fIclientData\fR,
+ Tcl_Interp *\fIinterp\fR);
.CE
When \fIdeleteProc\fR is invoked the \fIclientData\fR and \fIinterp\fR
arguments will be the same as the corresponding arguments passed to
diff --git a/doc/Async.3 b/doc/Async.3
index cc3354b..c4439a4 100644
--- a/doc/Async.3
+++ b/doc/Async.3
@@ -48,9 +48,9 @@ or 0 if \fIinterp\fR is NULL.
These procedures provide a safe mechanism for dealing with
asynchronous events such as signals.
If an event such as a signal occurs while a Tcl script is being
-evaluated then it isn't safe to take any substantive action to
+evaluated then it is not safe to take any substantive action to
process the event.
-For example, it isn't safe to evaluate a Tcl script since the
+For example, it is not safe to evaluate a Tcl script since the
interpreter may already be in the middle of evaluating a script;
it may not even be safe to allocate memory, since a memory
allocation could have been in progress when the event occurred.
@@ -140,7 +140,6 @@ If new handlers become ready while handlers are executing,
\fBTcl_AsyncInvoke\fR will invoke them all; at each point it
invokes the highest-priority (oldest) ready handler, repeating
this over and over until there are no longer any ready handlers.
-
.SH WARNING
.PP
It is almost always a bad idea for an asynchronous event
@@ -150,12 +149,11 @@ This sort of behavior can disrupt the execution of scripts in
subtle ways and result in bugs that are extremely difficult
to track down.
If an asynchronous event handler needs to evaluate Tcl scripts
-then it should first save the interpreter's result plus the values
-of the variables \fBerrorInfo\fR and \fBerrorCode\fR (this can
-be done, for example, by storing them in dynamic strings).
+then it should first save the interpreter's state by calling
+\fBTcl_SaveInterpState\fR, passing in the \fIcode\fR argument.
When the asynchronous handler is finished it should restore
-the interpreter's result, \fBerrorInfo\fR, and \fBerrorCode\fR,
-and return the \fIcode\fR argument.
+the interpreter's state by calling \fBTcl_RestoreInterpState\fR,
+and then returning the \fIcode\fR argument.
.SH KEYWORDS
-asynchronous event, handler, signal
+asynchronous event, handler, signal, Tcl_SaveInterpState, thread
diff --git a/doc/BackgdErr.3 b/doc/BackgdErr.3
index 532bb44..1e46b03 100644
--- a/doc/BackgdErr.3
+++ b/doc/BackgdErr.3
@@ -24,7 +24,8 @@ Interpreter in which the error occurred.
.SH DESCRIPTION
.PP
This procedure is typically invoked when a Tcl error occurs during
-``background processing'' such as executing an event handler.
+.QW "background processing"
+such as executing an event handler.
When such an error occurs, the error condition is reported to Tcl
or to a widget or some other C code, and there is not usually any
obvious way for that code to report the error to the user.
@@ -32,25 +33,29 @@ In these cases the code calls \fBTcl_BackgroundError\fR with an
\fIinterp\fR argument identifying the interpreter in which the
error occurred. At the time \fBTcl_BackgroundError\fR is invoked,
the interpreter's result is expected to contain an error message.
-\fBTcl_BackgroundError\fR will invoke the \fBbgerror\fR
-Tcl command to report the error in an application-specific fashion.
-If no \fBbgerror\fR command exists, or if it returns with an error condition,
-then \fBTcl_BackgroundError\fR reports the error itself by printing
-a message on the standard error file.
+\fBTcl_BackgroundError\fR will invoke the command registered
+in that interpreter to handle background errors by the
+\fBinterp bgerror\fR command.
+The registered handler command is meant to report the error
+in an application-specific fashion. The handler command
+receives two arguments, the result of the interp, and the
+return options of the interp at the time the error occurred.
+If the application registers no handler command, the default
+handler command will attempt to call \fBbgerror\fR to report
+the error. If an error condition arises while invoking the
+handler command, then \fBTcl_BackgroundError\fR reports the
+error itself by printing a message on the standard error file.
.PP
-\fBTcl_BackgroundError\fR does not invoke \fBbgerror\fR immediately
+\fBTcl_BackgroundError\fR does not invoke the handler command immediately
because this could potentially interfere with scripts that are in process
at the time the error occurred.
-Instead, it invokes \fBbgerror\fR later as an idle callback.
-\fBTcl_BackgroundError\fR saves the values of the \fBerrorInfo\fR and
-\fBerrorCode\fR variables and restores these values just before
-invoking \fBbgerror\fR.
+Instead, it invokes the handler command later as an idle callback.
.PP
It is possible for many background errors to accumulate before
-\fBbgerror\fR is invoked. When this happens, each of the errors
-is processed in order. However, if \fBbgerror\fR returns a
+the handler command is invoked. When this happens, each of the errors
+is processed in order. However, if the handle command returns a
break exception, then all remaining error reports for the
interpreter are skipped.
.SH KEYWORDS
-background, bgerror, error
+background, bgerror, error, interp
diff --git a/doc/Backslash.3 b/doc/Backslash.3
index eb859d7..8b399fc 100644
--- a/doc/Backslash.3
+++ b/doc/Backslash.3
@@ -17,35 +17,31 @@ Tcl_Backslash \- parse a backslash sequence
char
\fBTcl_Backslash\fR(\fIsrc, countPtr\fR)
.SH ARGUMENTS
-.AS char *countPtr
+.AS char *countPtr out
.AP char *src in
Pointer to a string starting with a backslash.
.AP int *countPtr out
-If \fIcountPtr\fR isn't NULL, \fI*countPtr\fR gets filled
+If \fIcountPtr\fR is not NULL, \fI*countPtr\fR gets filled
in with number of characters in the backslash sequence, including
the backslash character.
.BE
.SH DESCRIPTION
.PP
-.VS 8.1
The use of \fBTcl_Backslash\fR is deprecated in favor of
\fBTcl_UtfBackslash\fR.
.PP
This is a utility procedure provided for backwards compatibility with
non-internationalized Tcl extensions. It parses a backslash sequence and
returns the low byte of the Unicode character corresponding to the sequence.
-.VE
\fBTcl_Backslash\fR modifies \fI*countPtr\fR to contain the number of
characters in the backslash sequence.
.PP
See the Tcl manual entry for information on the valid backslash sequences.
All of the sequences described in the Tcl manual entry are supported by
\fBTcl_Backslash\fR.
-.VS 8.1 br
.SH "SEE ALSO"
Tcl(n), Tcl_UtfBackslash(3)
-.VE
.SH KEYWORDS
backslash, parse
diff --git a/doc/BoolObj.3 b/doc/BoolObj.3
index 2814e4e..395d159 100644
--- a/doc/BoolObj.3
+++ b/doc/BoolObj.3
@@ -1,14 +1,15 @@
'\"
'\" Copyright (c) 1996-1997 Sun Microsystems, Inc.
+'\" Contributions from Don Porter, NIST, 2005. (not subject to US copyright)
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
-.TH Tcl_BooleanObj 3 8.0 Tcl "Tcl Library Procedures"
+.TH Tcl_BooleanObj 3 8.5 Tcl "Tcl Library Procedures"
.BS
.SH NAME
-Tcl_NewBooleanObj, Tcl_SetBooleanObj, Tcl_GetBooleanFromObj \- manipulate Tcl objects as boolean values
+Tcl_NewBooleanObj, Tcl_SetBooleanObj, Tcl_GetBooleanFromObj \- store/retrieve boolean value in a Tcl_Obj
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -21,20 +22,14 @@ Tcl_Obj *
int
\fBTcl_GetBooleanFromObj\fR(\fIinterp, objPtr, boolPtr\fR)
.SH ARGUMENTS
-.AS Tcl_Interp *interp
+.AS Tcl_Interp boolValue in/out
.AP int boolValue in
-Integer value used to initialize or set a boolean object.
-If the integer is nonzero, the boolean object is set to 1;
-otherwise the boolean object is set to 0.
+Integer value to be stored as a boolean value in a Tcl_Obj.
.AP Tcl_Obj *objPtr in/out
-For \fBTcl_SetBooleanObj\fR, this points to the object to be converted
-to boolean type.
-For \fBTcl_GetBooleanFromObj\fR, this refers to the object
-from which to get a boolean value;
-if \fIobjPtr\fR does not already point to a boolean object,
-an attempt will be made to convert it to one.
+Points to the Tcl_Obj in which to store, or from which to
+retrieve a boolean value.
.AP Tcl_Interp *interp in/out
-If an error occurs during conversion,
+If a boolean value cannot be retrieved,
an error message is left in the interpreter's result object
unless \fIinterp\fR is NULL.
.AP int *boolPtr out
@@ -44,44 +39,57 @@ stores the boolean value (0 or 1) obtained from \fIobjPtr\fR.
.SH DESCRIPTION
.PP
-These procedures are used to create, modify, and read
-boolean Tcl objects from C code.
-\fBTcl_NewBooleanObj\fR and \fBTcl_SetBooleanObj\fR
-will create a new object of boolean type
-or modify an existing object to have boolean type.
-Both of these procedures set the object to have the
-boolean value (0 or 1) specified by \fIboolValue\fR;
-if \fIboolValue\fR is nonzero, the object is set to 1,
-otherwise to 0.
-\fBTcl_NewBooleanObj\fR returns a pointer to a newly created object
-with reference count zero.
-Both procedures set the object's type to be boolean
-and assign the boolean value to the object's internal representation
-\fIlongValue\fR member.
-\fBTcl_SetBooleanObj\fR invalidates any old string representation
-and, if the object is not already a boolean object,
-frees any old internal representation.
+These procedures are used to pass boolean values to and from
+Tcl as Tcl_Obj's. When storing a boolean value into a Tcl_Obj,
+any non-zero integer value in \fIboolValue\fR is taken to be
+the boolean value \fB1\fR, and the integer value \fB0\fR is
+taken to be the boolean value \fB0\fR.
.PP
-\fBTcl_GetBooleanFromObj\fR attempts to return a boolean value
-from the Tcl object \fIobjPtr\fR.
-If the object is not already a boolean object,
-it will attempt to convert it to one.
-If an error occurs during conversion, it returns \fBTCL_ERROR\fR
-and leaves an error message in the interpreter's result object
-unless \fIinterp\fR is NULL.
-Otherwise, \fBTcl_GetBooleanFromObj\fR returns \fBTCL_OK\fR
-and stores the boolean value in the address given by \fIboolPtr\fR.
-If the object is not already a boolean object,
-the conversion will free any old internal representation.
-Objects having a string representation equal to any of \fB0\fR,
-\fBfalse\fR, \fBno\fR, or \fBoff\fR have a boolean value 0; if the
-string representation is any of \fB1\fR, \fBtrue\fR, \fByes\fR, or
-\fBon\fR the boolean value is 1.
-Any of these string values may be abbreviated, and upper-case spellings
-are also acceptable.
+\fBTcl_NewBooleanObj\fR creates a new Tcl_Obj, stores the boolean
+value \fIboolValue\fR in it, and returns a pointer to the new Tcl_Obj.
+The new Tcl_Obj has reference count of zero.
+.PP
+\fBTcl_SetBooleanObj\fR accepts \fIobjPtr\fR, a pointer to
+an existing Tcl_Obj, and stores in the Tcl_Obj \fI*objPtr\fR
+the boolean value \fIboolValue\fR. This is a write operation
+on \fI*objPtr\fR, so \fIobjPtr\fR must be unshared. Attempts to
+write to a shared Tcl_Obj will panic. A successful write
+of \fIboolValue\fR into \fI*objPtr\fR implies the freeing of
+any former value stored in \fI*objPtr\fR.
+.PP
+\fBTcl_GetBooleanFromObj\fR attempts to retrieve a boolean value
+from the value stored in \fI*objPtr\fR.
+If \fIobjPtr\fR holds a string value recognized by \fBTcl_GetBoolean\fR,
+then the recognized boolean value is written at the address given
+by \fIboolPtr\fR.
+If \fIobjPtr\fR holds any value recognized as
+a number by Tcl, then if that value is zero a 0 is written at
+the address given by \fIboolPtr\fR and if that
+value is non-zero a 1 is written at the address given by \fIboolPtr\fR.
+In all cases where a value is written at the address given
+by \fIboolPtr\fR, \fBTcl_GetBooleanFromObj\fR returns \fBTCL_OK\fR.
+If the value of \fIobjPtr\fR does not meet any of the conditions
+above, then \fBTCL_ERROR\fR is returned and an error message is
+left in the interpreter's result unless \fIinterp\fR is NULL.
+\fBTcl_GetBooleanFromObj\fR may also make changes to the internal
+fields of \fI*objPtr\fR so that future calls to
+\fBTcl_GetBooleanFromObj\fR on the same \fIobjPtr\fR can be
+performed more efficiently.
+.PP
+Note that the routines \fBTcl_GetBooleanFromObj\fR and
+\fBTcl_GetBoolean\fR are not functional equivalents.
+The set of values for which \fBTcl_GetBooleanFromObj\fR
+will return \fBTCL_OK\fR is strictly larger than
+the set of values for which \fBTcl_GetBoolean\fR will do the same.
+For example, the value
+.QW 5
+passed to \fBTcl_GetBooleanFromObj\fR
+will lead to a \fBTCL_OK\fR return (and the boolean value 1),
+while the same value passed to \fBTcl_GetBoolean\fR will lead to
+a \fBTCL_ERROR\fR return.
.SH "SEE ALSO"
-Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_GetObjResult
+Tcl_NewObj, Tcl_IsShared, Tcl_GetBoolean
.SH KEYWORDS
-boolean, boolean object, boolean type, internal representation, object, object type, string representation
+boolean, object
diff --git a/doc/ByteArrObj.3 b/doc/ByteArrObj.3
index 51c4363..738da32 100644
--- a/doc/ByteArrObj.3
+++ b/doc/ByteArrObj.3
@@ -25,8 +25,8 @@ unsigned char *
unsigned char *
\fBTcl_SetByteArrayLength\fR(\fIobjPtr, length\fR)
.SH ARGUMENTS
-.AS "unsigned char" *lengthPtr in/out
-.AP "CONST unsigned char" *bytes in
+.AS "const unsigned char" *lengthPtr in/out
+.AP "const unsigned char" *bytes in
The array of bytes used to initialize or set a byte-array object.
.AP int length in
The length of the array of bytes. It must be >= 0.
@@ -48,7 +48,7 @@ results of binary IO operations or data structures created with the
\fBbinary\fR command. In Tcl, an array of bytes is not equivalent to a
string. Conceptually, a string is an array of Unicode characters, while a
byte-array is an array of 8-bit quantities with no implicit meaning.
-Accesser functions are provided to get the string representation of a
+Accessor functions are provided to get the string representation of a
byte-array or to convert an arbitrary object to a byte-array. Obtaining the
string representation of a byte-array object (by calling
\fBTcl_GetStringFromObj\fR) produces a properly formed UTF-8 sequence with a
diff --git a/doc/CallDel.3 b/doc/CallDel.3
index 02bb445..8e6445b 100644
--- a/doc/CallDel.3
+++ b/doc/CallDel.3
@@ -38,8 +38,8 @@ time of the call.
type \fBTcl_InterpDeleteProc\fR:
.CS
typedef void Tcl_InterpDeleteProc(
- ClientData \fIclientData\fR,
- Tcl_Interp *\fIinterp\fR);
+ ClientData \fIclientData\fR,
+ Tcl_Interp *\fIinterp\fR);
.CE
The \fIclientData\fR and \fIinterp\fR parameters are
copies of the \fIclientData\fR and \fIinterp\fR arguments given
@@ -51,7 +51,7 @@ interpreter is about to go away.
.PP
\fBTcl_DontCallWhenDeleted\fR cancels a previous call to
\fBTcl_CallWhenDeleted\fR with the same arguments, so that
-\fIproc\fR won't be called after all when \fIinterp\fR is
+\fIproc\fR will not be called after all when \fIinterp\fR is
deleted.
If there is no deletion callback that matches \fIinterp\fR,
\fIproc\fR, and \fIclientData\fR then the call to
diff --git a/doc/ChnlStack.3 b/doc/ChnlStack.3
index ebd8d63..8ac5a0d 100644
--- a/doc/ChnlStack.3
+++ b/doc/ChnlStack.3
@@ -8,7 +8,7 @@
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
-Tcl_StackChannel, Tcl_UnstackChannel, Tcl_GetStackedChannel, Tcl_GetTopChannel \- stack an I/O channel on top of another, and undo it
+Tcl_StackChannel, Tcl_UnstackChannel, Tcl_GetStackedChannel, Tcl_GetTopChannel \- manipulate stacked I/O channels
.SH SYNOPSIS
.nf
.nf
@@ -27,17 +27,17 @@ Tcl_Channel
\fBTcl_GetTopChannel\fR(\fIchannel\fR)
.sp
.SH ARGUMENTS
-.AS Tcl_ChannelType
+.AS Tcl_ChannelType clientData
.AP Tcl_Interp *interp in
Interpreter for error reporting.
.AP Tcl_ChannelType *typePtr in
-The new channel I/O procedures to use for \fIchannel\fP.
+The new channel I/O procedures to use for \fIchannel\fR.
.AP ClientData clientData in
Arbitrary one-word value to pass to channel I/O procedures.
.AP int mask in
Conditions under which \fIchannel\fR will be used: OR-ed combination of
\fBTCL_READABLE\fR, \fBTCL_WRITABLE\fR and \fBTCL_EXCEPTION\fR.
-This can be a subset of the operations currently allowed on \fIchannel\fP.
+This can be a subset of the operations currently allowed on \fIchannel\fR.
.AP Tcl_Channel channel in
An existing Tcl channel such as returned by \fBTcl_CreateChannel\fR.
.BE
@@ -55,9 +55,9 @@ stacked channels. Anyone using stacked channels or creating stacked
channel drivers should update to the new \fBTCL_CHANNEL_VERSION_2\fR
\fBTcl_ChannelType\fR structure. See \fBTcl_CreateChannel\fR for details.
.PP
-\fBTcl_StackChannel\fR stacks a new \fIchannel\fP on an existing channel
-with the same name that was registered for \fIchannel\fP by
-\fBTcl_RegisterChannel\fP.
+\fBTcl_StackChannel\fR stacks a new \fIchannel\fR on an existing channel
+with the same name that was registered for \fIchannel\fR by
+\fBTcl_RegisterChannel\fR.
.PP
\fBTcl_StackChannel\fR works by creating a new channel structure and
placing itself on top of the channel stack. EOL translation, encoding and
@@ -68,7 +68,7 @@ remain at the top of the channel stack. A pointer to the new top channel
structure is returned. If an error occurs when stacking the channel, NULL
is returned instead.
.PP
-The \fImask\fP parameter specifies the operations that are allowed on the
+The \fImask\fR parameter specifies the operations that are allowed on the
new channel. These can be a subset of the operations allowed on the
original channel. For example, a read-write channel may become read-only
after the \fBTcl_StackChannel\fR call.
@@ -77,10 +77,10 @@ Closing a channel closes the channels stacked below it. The close of
stacked channels is executed in a way that allows buffered data to be
properly flushed.
.PP
-\fBTcl_UnstackChannel\fP reverses the process. The old channel is
+\fBTcl_UnstackChannel\fR reverses the process. The old channel is
associated with the channel name, and the processing module added by
\fBTcl_StackChannel\fR is destroyed. If there is no old channel, then
-\fBTcl_UnstackChannel\fP is equivalent to \fBTcl_Close\fP. If an error
+\fBTcl_UnstackChannel\fR is equivalent to \fBTcl_Close\fR. If an error
occurs unstacking the channel, \fBTCL_ERROR\fR is returned, otherwise
\fBTCL_OK\fR is returned.
.PP
diff --git a/doc/CmdCmplt.3 b/doc/CmdCmplt.3
index e2a7064..eeae039 100644
--- a/doc/CmdCmplt.3
+++ b/doc/CmdCmplt.3
@@ -17,8 +17,8 @@ Tcl_CommandComplete \- Check for unmatched braces in a Tcl command
int
\fBTcl_CommandComplete\fR(\fIcmd\fR)
.SH ARGUMENTS
-.AS "CONST char" *cmd
-.AP "CONST char" *cmd in
+.AS "const char" *cmd
+.AP "const char" *cmd in
Command string to test for completeness.
.BE
diff --git a/doc/Concat.3 b/doc/Concat.3
index fdb479e..c38bf82 100644
--- a/doc/Concat.3
+++ b/doc/Concat.3
@@ -14,12 +14,13 @@ Tcl_Concat \- concatenate a collection of strings
.nf
\fB#include <tcl.h>\fR
.sp
-CONST char *
+const char *
\fBTcl_Concat\fR(\fIargc, argv\fR)
.SH ARGUMENTS
+.AS "const char *const" argv[]
.AP int argc in
Number of strings.
-.AP "CONST char * CONST" argv[] in
+.AP "const char *const" argv[] in
Array of strings to concatenate. Must have \fIargc\fR entries.
.BE
@@ -41,12 +42,9 @@ copies strings from \fBargv\fR to the result. If an element of
is ignored entirely. This white-space removal was added to make
the output of the \fBconcat\fR command cleaner-looking.
.PP
-.VS
The result string is dynamically allocated
using \fBTcl_Alloc\fR; the caller must eventually release the space
by calling \fBTcl_Free\fR.
-.VE
-.VS
.SH "SEE ALSO"
Tcl_ConcatObj
.SH KEYWORDS
diff --git a/doc/CrtChannel.3 b/doc/CrtChannel.3
index fc034a0..212a239 100644
--- a/doc/CrtChannel.3
+++ b/doc/CrtChannel.3
@@ -9,7 +9,7 @@
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
-Tcl_CreateChannel, Tcl_GetChannelInstanceData, Tcl_GetChannelType, Tcl_GetChannelName, Tcl_GetChannelHandle, Tcl_GetChannelMode, Tcl_GetChannelBufferSize, Tcl_SetChannelBufferSize, Tcl_NotifyChannel, Tcl_BadChannelOption, Tcl_ChannelName, Tcl_ChannelVersion, Tcl_ChannelBlockModeProc, Tcl_ChannelCloseProc, Tcl_ChannelClose2Proc, Tcl_ChannelInputProc, Tcl_ChannelOutputProc, Tcl_ChannelSeekProc, Tcl_ChannelWideSeekProc, Tcl_ChannelSetOptionProc, Tcl_ChannelGetOptionProc, Tcl_ChannelWatchProc, Tcl_ChannelGetHandleProc, Tcl_ChannelFlushProc, Tcl_ChannelHandlerProc, Tcl_ChannelThreadActionProc, Tcl_IsChannelShared, Tcl_IsChannelRegistered, Tcl_CutChannel, Tcl_SpliceChannel, Tcl_IsChannelExisting, Tcl_ClearChannelHandlers, Tcl_GetChannelThread, Tcl_ChannelBuffered \- procedures for creating and manipulating channels
+Tcl_CreateChannel, Tcl_GetChannelInstanceData, Tcl_GetChannelType, Tcl_GetChannelName, Tcl_GetChannelHandle, Tcl_GetChannelMode, Tcl_GetChannelBufferSize, Tcl_SetChannelBufferSize, Tcl_NotifyChannel, Tcl_BadChannelOption, Tcl_ChannelName, Tcl_ChannelVersion, Tcl_ChannelBlockModeProc, Tcl_ChannelCloseProc, Tcl_ChannelClose2Proc, Tcl_ChannelInputProc, Tcl_ChannelOutputProc, Tcl_ChannelSeekProc, Tcl_ChannelWideSeekProc, Tcl_ChannelTruncateProc, Tcl_ChannelSetOptionProc, Tcl_ChannelGetOptionProc, Tcl_ChannelWatchProc, Tcl_ChannelGetHandleProc, Tcl_ChannelFlushProc, Tcl_ChannelHandlerProc, Tcl_ChannelThreadActionProc, Tcl_IsChannelShared, Tcl_IsChannelRegistered, Tcl_CutChannel, Tcl_SpliceChannel, Tcl_IsChannelExisting, Tcl_ClearChannelHandlers, Tcl_GetChannelThread, Tcl_ChannelBuffered \- procedures for creating and manipulating channels
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -23,16 +23,14 @@ ClientData
Tcl_ChannelType *
\fBTcl_GetChannelType\fR(\fIchannel\fR)
.sp
-CONST char *
+const char *
\fBTcl_GetChannelName\fR(\fIchannel\fR)
.sp
int
\fBTcl_GetChannelHandle\fR(\fIchannel, direction, handlePtr\fR)
.sp
-.VS 8.4
Tcl_ThreadId
\fBTcl_GetChannelThread\fR(\fIchannel\fR)
-.VE 8.4
.sp
int
\fBTcl_GetChannelMode\fR(\fIchannel\fR)
@@ -46,7 +44,6 @@ int
.sp
int
\fBTcl_BadChannelOption\fR(\fIinterp, optionName, optionList\fR)
-.VS 8.4
.sp
int
\fBTcl_IsChannelShared\fR(\fIchannel\fR)
@@ -65,12 +62,11 @@ void
.sp
void
\fBTcl_ClearChannelHandlers\fR(\fIchannel\fR)
-.VE 8.4
.sp
int
\fBTcl_ChannelBuffered\fR(\fIchannel\fR)
.sp
-CONST char *
+const char *
\fBTcl_ChannelName\fR(\fItypePtr\fR)
.sp
Tcl_ChannelTypeVersion
@@ -94,13 +90,16 @@ Tcl_DriverOutputProc *
Tcl_DriverSeekProc *
\fBTcl_ChannelSeekProc\fR(\fItypePtr\fR)
.sp
-.VS 8.4
Tcl_DriverWideSeekProc *
\fBTcl_ChannelWideSeekProc\fR(\fItypePtr\fR)
.sp
Tcl_DriverThreadActionProc *
\fBTcl_ChannelThreadActionProc\fR(\fItypePtr\fR)
-.VE 8.4
+.sp
+.VS 8.5
+Tcl_DriverTruncateProc *
+\fBTcl_ChannelTruncateProc\fR(\fItypePtr\fR)
+.VE 8.5
.sp
Tcl_DriverSetOptionProc *
\fBTcl_ChannelSetOptionProc\fR(\fItypePtr\fR)
@@ -121,11 +120,11 @@ Tcl_DriverHandlerProc *
\fBTcl_ChannelHandlerProc\fR(\fItypePtr\fR)
.sp
.SH ARGUMENTS
-.AS Tcl_ChannelType *channelName in
-.AP Tcl_ChannelType *typePtr in
+.AS "const Tcl_ChannelType" *channelName
+.AP "const Tcl_ChannelType" *typePtr in
Points to a structure containing the addresses of procedures that
can be called to perform I/O and other functions on the channel.
-.AP "CONST char" *channelName in
+.AP "const char" *channelName in
The name of this channel, such as \fBfile3\fR; must not be in use
by any other channel. Can be NULL, in which case the channel is
created without a name.
@@ -151,10 +150,11 @@ and \fBTCL_EXCEPTION\fR that indicates events that have occurred on
this channel.
.AP Tcl_Interp *interp in
Current interpreter. (can be NULL)
-.AP "CONST char" *optionName in
+.AP "const char" *optionName in
Name of the invalid option.
-.AP "CONST char" *optionList in
-Specific options list (space separated words, without "-")
+.AP "const char" *optionList in
+Specific options list (space separated words, without
+.QW \- )
to append to the standard generic options list.
Can be NULL for generic options error message only.
@@ -178,7 +178,7 @@ driver provides a \fBTcl_ChannelType\fR structure containing pointers to
functions implementing the various operations used by the generic layer to
communicate with the channel driver. The \fBTcl_ChannelType\fR structure
and the functions referenced by it are described in the section
-TCL_CHANNELTYPE, below.
+\fBTCL_CHANNELTYPE\fR, below.
.PP
Second, channel drivers usually provide a Tcl command to create
instances of that type of channel. For example, the Tcl \fBopen\fR
@@ -205,7 +205,7 @@ structure to perform operations on the channel.
\fItypePtr\fR and \fIinstanceData\fR with it. The channel is opened in the
mode indicated by \fImask\fR.
For a discussion of channel drivers, their operations and the
-\fBTcl_ChannelType\fR structure, see the section TCL_CHANNELTYPE, below.
+\fBTcl_ChannelType\fR structure, see the section \fBTCL_CHANNELTYPE\fR, below.
.PP
\fBTcl_CreateChannel\fR interacts with the code managing the standard
channels. Once a standard channel was initialized either through a
@@ -237,11 +237,9 @@ then \fBTCL_ERROR\fR is returned instead. Different channel drivers
will return different types of handle. Refer to the manual entries
for each driver to determine what type of handle is returned.
.PP
-.VS 8.4
\fBTcl_GetChannelThread\fR returns the id of the thread currently managing
the specified \fIchannel\fR. This allows channel drivers to send their file
events to the correct event queue even for a multi-threaded core.
-.VE 8.4
.PP
\fBTcl_GetChannelMode\fR returns an OR-ed combination of \fBTCL_READABLE\fR
and \fBTCL_WRITABLE\fR, indicating whether the channel is open for input
@@ -265,15 +263,15 @@ occurred on the channel. Channel drivers are responsible for invoking
this function whenever the channel handlers need to be called for the
channel. See \fBWATCHPROC\fR below for more details.
.PP
-\fBTcl_BadChannelOption\fR is called from driver specific set or get option
-procs to generate a complete error message.
+\fBTcl_BadChannelOption\fR is called from driver specific
+\fIsetOptionProc\fR or \fIgetOptionProc\fR to generate a complete
+error message.
.PP
\fBTcl_ChannelBuffered\fR returns the number of bytes of input
currently buffered in the internal buffer (push back area) of the
channel itself. It does not report about the data in the overall
buffers for the stack of channels the supplied channel is part of.
.PP
-.VS 8.4
\fBTcl_IsChannelShared\fR checks the refcount of the specified
\fIchannel\fR and returns whether the \fIchannel\fR was shared among
multiple interpreters (result == 1) or not (result == 0).
@@ -290,26 +288,24 @@ name is registered in the (thread)-global list of all channels (result
(thread)global list of all channels (of the current thread).
Application to a channel still registered in some interpreter
is not allowed.
-.VS 8.4
+.VS 8.5
Also notifies the driver if the \fBTcl_ChannelType\fR version is
\fBTCL_CHANNEL_VERSION_4\fR (or higher), and
\fBTcl_DriverThreadActionProc\fR is defined for it.
-.VE 8.4
+.VE 8.5
.PP
\fBTcl_SpliceChannel\fR adds the specified \fIchannel\fR to the
(thread)global list of all channels (of the current thread).
Application to a channel registered in some interpreter is not allowed.
-.VS 8.4
+.VS 8.5
Also notifies the driver if the \fBTcl_ChannelType\fR version is
\fBTCL_CHANNEL_VERSION_4\fR (or higher), and
\fBTcl_DriverThreadActionProc\fR is defined for it.
-.VE 8.4
+.VE 8.5
.PP
-\fBTcl_ClearChannelHandlers\fR removes all channelhandlers and event
+\fBTcl_ClearChannelHandlers\fR removes all channel handlers and event
scripts associated with the specified \fIchannel\fR, thus shutting
down all event processing for this channel.
-.VE 8.4
-
.SH TCL_CHANNELTYPE
.PP
A channel driver provides a \fBTcl_ChannelType\fR structure that contains
@@ -322,22 +318,25 @@ details about the old structure.
The \fBTcl_ChannelType\fR structure contains the following fields:
.CS
typedef struct Tcl_ChannelType {
- char *\fItypeName\fR;
- Tcl_ChannelTypeVersion \fIversion\fR;
- Tcl_DriverCloseProc *\fIcloseProc\fR;
- Tcl_DriverInputProc *\fIinputProc\fR;
- Tcl_DriverOutputProc *\fIoutputProc\fR;
- Tcl_DriverSeekProc *\fIseekProc\fR;
- Tcl_DriverSetOptionProc *\fIsetOptionProc\fR;
- Tcl_DriverGetOptionProc *\fIgetOptionProc\fR;
- Tcl_DriverWatchProc *\fIwatchProc\fR;
- Tcl_DriverGetHandleProc *\fIgetHandleProc\fR;
- Tcl_DriverClose2Proc *\fIclose2Proc\fR;
- Tcl_DriverBlockModeProc *\fIblockModeProc\fR;
- Tcl_DriverFlushProc *\fIflushProc\fR;
- Tcl_DriverHandlerProc *\fIhandlerProc\fR;
- Tcl_DriverWideSeekProc *\fIwideSeekProc\fR;
- Tcl_DriverThreadActionProc *\fIthreadActionProc\fR;
+ char *\fItypeName\fR;
+ Tcl_ChannelTypeVersion \fIversion\fR;
+ Tcl_DriverCloseProc *\fIcloseProc\fR;
+ Tcl_DriverInputProc *\fIinputProc\fR;
+ Tcl_DriverOutputProc *\fIoutputProc\fR;
+ Tcl_DriverSeekProc *\fIseekProc\fR;
+ Tcl_DriverSetOptionProc *\fIsetOptionProc\fR;
+ Tcl_DriverGetOptionProc *\fIgetOptionProc\fR;
+ Tcl_DriverWatchProc *\fIwatchProc\fR;
+ Tcl_DriverGetHandleProc *\fIgetHandleProc\fR;
+ Tcl_DriverClose2Proc *\fIclose2Proc\fR;
+ Tcl_DriverBlockModeProc *\fIblockModeProc\fR;
+ Tcl_DriverFlushProc *\fIflushProc\fR;
+ Tcl_DriverHandlerProc *\fIhandlerProc\fR;
+ Tcl_DriverWideSeekProc *\fIwideSeekProc\fR;
+ Tcl_DriverThreadActionProc *\fIthreadActionProc\fR;
+.VS 8.5
+ Tcl_DriverTruncateProc *\fItruncateProc\fR;
+.VE 8.5
} Tcl_ChannelType;
.CE
.PP
@@ -345,11 +344,11 @@ It is not necessary to provide implementations for all channel
operations. Those which are not necessary may be set to NULL in the
struct: \fIblockModeProc\fR, \fIseekProc\fR, \fIsetOptionProc\fR,
\fIgetOptionProc\fR, and \fIclose2Proc\fR, in addition to
-\fIflushProc\fR, \fIhandlerProc\fR, and \fIthreadActionProc\fR. Other
-functions that cannot be implemented in a meaningful way should return
-\fBEINVAL\fR when called, to indicate that the operations they
-represent are not available. Also note that \fIwideSeekProc\fR can be
-NULL if \fIseekProc\fR is.
+\fIflushProc\fR, \fIhandlerProc\fR, \fIthreadActionProc\fR, and
+\fItruncateProc\fR. Other functions that cannot be implemented in a
+meaningful way should return \fBEINVAL\fR when called, to indicate
+that the operations they represent are not available. Also note that
+\fIwideSeekProc\fR can be NULL if \fIseekProc\fR is.
.PP
The user should only use the above structure for \fBTcl_ChannelType\fR
instantiation. When referencing fields in a \fBTcl_ChannelType\fR
@@ -358,20 +357,19 @@ structure, the following functions should be used to obtain the values:
\fBTcl_ChannelBlockModeProc\fR, \fBTcl_ChannelCloseProc\fR,
\fBTcl_ChannelClose2Proc\fR, \fBTcl_ChannelInputProc\fR,
\fBTcl_ChannelOutputProc\fR, \fBTcl_ChannelSeekProc\fR,
-.VS 8.4
-\fBTcl_ChannelWideSeekProc\fR,
-\fBTcl_ChannelThreadActionProc\fR,
-.VE 8.4
+\fBTcl_ChannelWideSeekProc\fR, \fBTcl_ChannelThreadActionProc\fR,
+.VS 8.5
+\fBTcl_ChannelTruncateProc\fR,
+.VE 8.5
\fBTcl_ChannelSetOptionProc\fR, \fBTcl_ChannelGetOptionProc\fR,
\fBTcl_ChannelWatchProc\fR, \fBTcl_ChannelGetHandleProc\fR,
\fBTcl_ChannelFlushProc\fR, or \fBTcl_ChannelHandlerProc\fR.
.PP
The change to the structures was made in such a way that standard channel
types are binary compatible. However, channel types that use stacked
-channels (ie: TLS, Trf) have new versions to correspond to the above change
+channels (i.e. TLS, Trf) have new versions to correspond to the above change
since the previous code for stacked channels had problems.
-
-.SH TYPENAME
+.SS TYPENAME
.PP
The \fItypeName\fR field contains a null-terminated string that
identifies the type of the device implemented by this driver, e.g.
@@ -379,19 +377,19 @@ identifies the type of the device implemented by this driver, e.g.
.PP
This value can be retrieved with \fBTcl_ChannelName\fR, which returns
a pointer to the string.
-
-.SH VERSION
+.SS VERSION
.PP
The \fIversion\fR field should be set to the version of the structure
that you require. \fBTCL_CHANNEL_VERSION_2\fR is the minimum recommended.
-.VS 8.4
-\fBTCL_CHANNEL_VERSION_3\fR must be set to specifiy the \fIwideSeekProc\fR member.
-.VE 8.4
-.VS 8.4
-\fBTCL_CHANNEL_VERSION_4\fR must be set to specifiy the
-\fIthreadActionProc\fR member (includes \fIwideSeekProc\fR).
-.VE 8.4
+\fBTCL_CHANNEL_VERSION_3\fR must be set to specify the \fIwideSeekProc\fR member.
+\fBTCL_CHANNEL_VERSION_4\fR must be set to specify the \fIthreadActionProc\fR member
+(includes \fIwideSeekProc\fR).
+.VS 8.5
+\fBTCL_CHANNEL_VERSION_5\fR must be set to specify the
+\fItruncateProc\fR members (includes
+\fIwideSeekProc\fR and \fIthreadActionProc\fR).
+.VE 8.5
If it is not set to any of these, then this
\fBTcl_ChannelType\fR is assumed to have the original structure. See
\fBOLD CHANNEL TYPES\fR for more details. While Tcl will recognize
@@ -399,12 +397,14 @@ and function with either structures, stacked channels must be of at
least \fBTCL_CHANNEL_VERSION_2\fR to function correctly.
.PP
This value can be retrieved with \fBTcl_ChannelVersion\fR, which returns
-.VS 8.4
-one of \fBTCL_CHANNEL_VERSION_4\fR, \fBTCL_CHANNEL_VERSION_3\fR,
-.VE 8.4
-\fBTCL_CHANNEL_VERSION_2\fR, or \fBTCL_CHANNEL_VERSION_1\fR.
-
-.SH BLOCKMODEPROC
+one of
+.VS 8.5
+\fBTCL_CHANNEL_VERSION_5\fR,
+.VE 8.5
+\fBTCL_CHANNEL_VERSION_4\fR,
+\fBTCL_CHANNEL_VERSION_3\fR,
+\fBTCL_CHANNEL_VERSION_2\fR or \fBTCL_CHANNEL_VERSION_1\fR.
+.SS BLOCKMODEPROC
.PP
The \fIblockModeProc\fR field contains the address of a function called by
the generic layer to set blocking and nonblocking mode on the device.
@@ -412,8 +412,8 @@ the generic layer to set blocking and nonblocking mode on the device.
.PP
.CS
typedef int Tcl_DriverBlockModeProc(
- ClientData \fIinstanceData\fR,
- int \fImode\fR);
+ ClientData \fIinstanceData\fR,
+ int \fImode\fR);
.CE
.PP
The \fIinstanceData\fR is the same as the value passed to
@@ -437,11 +437,9 @@ A channel driver \fBnot\fR supplying a \fIblockModeProc\fR has to be
very, very careful. It has to tell the generic layer exactly which
blocking mode is acceptable to it, and should this also document for
the user so that the blocking mode of the channel is not changed to an
-inacceptable value. Any confusion here may lead the interpreter into a
+unacceptable value. Any confusion here may lead the interpreter into a
(spurious and difficult to find) deadlock.
-
-
-.SH "CLOSEPROC AND CLOSE2PROC"
+.SS "CLOSEPROC AND CLOSE2PROC"
.PP
The \fIcloseProc\fR field contains the address of a function called by the
generic layer to clean up driver-related information when the channel is
@@ -449,8 +447,8 @@ closed. \fICloseProc\fR must match the following prototype:
.PP
.CS
typedef int Tcl_DriverCloseProc(
- ClientData \fIinstanceData\fR,
- Tcl_Interp *\fIinterp\fR);
+ ClientData \fIinstanceData\fR,
+ Tcl_Interp *\fIinterp\fR);
.CE
.PP
The \fIinstanceData\fR argument is the same as the value provided to
@@ -471,9 +469,9 @@ following prototype:
.PP
.CS
typedef int Tcl_DriverClose2Proc(
- ClientData \fIinstanceData\fR,
- Tcl_Interp *\fIinterp\fR,
- int \fIflags\fR);
+ ClientData \fIinstanceData\fR,
+ Tcl_Interp *\fIinterp\fR,
+ int \fIflags\fR);
.CE
.PP
The \fIclose2Proc\fR will be called with \fIflags\fR set to an OR'ed
@@ -491,11 +489,10 @@ return a nonzero POSIX error code. In addition, if an error occurs and
\fIinterp\fR is not NULL, the procedure should store an error message
in the interpreter's result.
.PP
-These value can be retrieved with \fBTcl_ChannelCloseProc\fR or
-\fBTcl_ChannelClose2Proc\fR, which returns a pointer to the respective
-function.
-
-.SH INPUTPROC
+The \fIcloseProc\fR and \fIclose2Proc\fR values can be retrieved with
+\fBTcl_ChannelCloseProc\fR or \fBTcl_ChannelClose2Proc\fR, which
+return a pointer to the respective function.
+.SS INPUTPROC
.PP
The \fIinputProc\fR field contains the address of a function called by the
generic layer to read data from the file or device and store it in an
@@ -503,10 +500,10 @@ internal buffer. \fIInputProc\fR must match the following prototype:
.PP
.CS
typedef int Tcl_DriverInputProc(
- ClientData \fIinstanceData\fR,
- char *\fIbuf\fR,
- int \fIbufSize\fR,
- int *\fIerrorCodePtr\fR);
+ ClientData \fIinstanceData\fR,
+ char *\fIbuf\fR,
+ int \fIbufSize\fR,
+ int *\fIerrorCodePtr\fR);
.CE
.PP
\fIInstanceData\fR is the same as the value passed to
@@ -539,8 +536,7 @@ blocking.
.PP
This value can be retrieved with \fBTcl_ChannelInputProc\fR, which returns
a pointer to the function.
-
-.SH OUTPUTPROC
+.SS OUTPUTPROC
.PP
The \fIoutputProc\fR field contains the address of a function called by the
generic layer to transfer data from an internal buffer to the output device.
@@ -548,10 +544,10 @@ generic layer to transfer data from an internal buffer to the output device.
.PP
.CS
typedef int Tcl_DriverOutputProc(
- ClientData \fIinstanceData\fR,
- CONST char *\fIbuf\fR,
- int \fItoWrite\fR,
- int *\fIerrorCodePtr\fR);
+ ClientData \fIinstanceData\fR,
+ const char *\fIbuf\fR,
+ int \fItoWrite\fR,
+ int *\fIerrorCodePtr\fR);
.CE
.PP
\fIInstanceData\fR is the same as the value passed to
@@ -578,8 +574,7 @@ without writing any data.
.PP
This value can be retrieved with \fBTcl_ChannelOutputProc\fR, which returns
a pointer to the function.
-
-.SH "SEEKPROC AND WIDESEEKPROC"
+.SS "SEEKPROC AND WIDESEEKPROC"
.PP
The \fIseekProc\fR field contains the address of a function called by the
generic layer to move the access point at which subsequent input or output
@@ -588,10 +583,10 @@ prototype:
.PP
.CS
typedef int Tcl_DriverSeekProc(
- ClientData \fIinstanceData\fR,
- long \fIoffset\fR,
- int \fIseekMode\fR,
- int *\fIerrorCodePtr\fR);
+ ClientData \fIinstanceData\fR,
+ long \fIoffset\fR,
+ int \fIseekMode\fR,
+ int *\fIerrorCodePtr\fR);
.CE
.PP
The \fIinstanceData\fR argument is the same as the value given to
@@ -608,7 +603,6 @@ does not implement seeking.
The return value is the new access point or -1 in case of error. If an
error occurred, the function should not move the access point.
.PP
-.VS 8.4
If there is a non-NULL \fIseekProc\fR field, the \fIwideSeekProc\fR
field may contain the address of an alternative function to use which
handles wide (i.e. larger than 32-bit) offsets, so allowing seeks
@@ -619,10 +613,10 @@ following prototype:
.PP
.CS
typedef Tcl_WideInt Tcl_DriverWideSeekProc(
- ClientData \fIinstanceData\fR,
- Tcl_WideInt \fIoffset\fR,
- int \fIseekMode\fR,
- int *\fIerrorCodePtr\fR);
+ ClientData \fIinstanceData\fR,
+ Tcl_WideInt \fIoffset\fR,
+ int \fIseekMode\fR,
+ int *\fIerrorCodePtr\fR);
.CE
.PP
The arguments and return values mean the same thing as with
@@ -633,9 +627,7 @@ The \fIseekProc\fR value can be retrieved with
\fBTcl_ChannelSeekProc\fR, which returns a pointer to the function,
and similarly the \fIwideSeekProc\fR can be retrieved with
\fBTcl_ChannelWideSeekProc\fR.
-.VE 8.4
-
-.SH SETOPTIONPROC
+.SS SETOPTIONPROC
.PP
The \fIsetOptionProc\fR field contains the address of a function called by
the generic layer to set a channel type specific option on a channel.
@@ -643,10 +635,10 @@ the generic layer to set a channel type specific option on a channel.
.PP
.CS
typedef int Tcl_DriverSetOptionProc(
- ClientData \fIinstanceData\fR,
- Tcl_Interp *\fIinterp\fR,
- CONST char *\fIoptionName\fR,
- CONST char *\fInewValue\fR);
+ ClientData \fIinstanceData\fR,
+ Tcl_Interp *\fIinterp\fR,
+ const char *\fIoptionName\fR,
+ const char *\fInewValue\fR);
.CE
.PP
\fIoptionName\fR is the name of an option to set, and \fInewValue\fR is
@@ -656,7 +648,7 @@ created. The function should do whatever channel type specific action is
required to implement the new value of the option.
.PP
Some options are handled by the generic code and this function is never
-called to set them, e.g. \fB-blockmode\fR. Other options are specific to
+called to set them, e.g. \fB\-blockmode\fR. Other options are specific to
each channel type and the \fIsetOptionProc\fR procedure of the channel
driver will get called to implement them. The \fIsetOptionProc\fR field can
be NULL, which indicates that this channel type supports no type specific
@@ -676,8 +668,7 @@ error code.
.PP
This value can be retrieved with \fBTcl_ChannelSetOptionProc\fR, which returns
a pointer to the function.
-
-.SH GETOPTIONPROC
+.SS GETOPTIONPROC
.PP
The \fIgetOptionProc\fR field contains the address of a function called by
the generic layer to get the value of a channel type specific option on a
@@ -685,10 +676,10 @@ channel. \fIgetOptionProc\fR must match the following prototype:
.PP
.CS
typedef int Tcl_DriverGetOptionProc(
- ClientData \fIinstanceData\fR,
- Tcl_Interp *\fIinterp\fR,
- CONST char *\fIoptionName\fR,
- Tcl_DString *\fIoptionValue\fR);
+ ClientData \fIinstanceData\fR,
+ Tcl_Interp *\fIinterp\fR,
+ const char *\fIoptionName\fR,
+ Tcl_DString *\fIoptionValue\fR);
.CE
.PP
\fIOptionName\fR is the name of an option supported by this type of
@@ -706,7 +697,7 @@ function should also call \fBTcl_SetErrno\fR to store an appropriate POSIX
error code.
.PP
Some options are handled by the generic code and this function is never
-called to retrieve their value, e.g. \fB-blockmode\fR. Other options are
+called to retrieve their value, e.g. \fB\-blockmode\fR. Other options are
specific to each channel type and the \fIgetOptionProc\fR procedure of the
channel driver will get called to implement them. The \fIgetOptionProc\fR
field can be NULL, which indicates that this channel type supports no type
@@ -714,8 +705,7 @@ specific options.
.PP
This value can be retrieved with \fBTcl_ChannelGetOptionProc\fR, which returns
a pointer to the function.
-
-.SH WATCHPROC
+.SS WATCHPROC
.PP
The \fIwatchProc\fR field contains the address of a function called
by the generic layer to initialize the event notification mechanism to
@@ -724,8 +714,8 @@ notice events of interest on this channel.
.PP
.CS
typedef void Tcl_DriverWatchProc(
- ClientData \fIinstanceData\fR,
- int \fImask\fR);
+ ClientData \fIinstanceData\fR,
+ int \fImask\fR);
.CE
.PP
The \fIinstanceData\fR is the same as the value passed to
@@ -747,8 +737,7 @@ details on how to queue an event.
.PP
This value can be retrieved with \fBTcl_ChannelWatchProc\fR, which returns
a pointer to the function.
-
-.SH GETHANDLEPROC
+.SS GETHANDLEPROC
.PP
The \fIgetHandleProc\fR field contains the address of a function called by
the generic layer to retrieve a device-specific handle from the channel.
@@ -756,9 +745,9 @@ the generic layer to retrieve a device-specific handle from the channel.
.PP
.CS
typedef int Tcl_DriverGetHandleProc(
- ClientData \fIinstanceData\fR,
- int \fIdirection\fR,
- ClientData *\fIhandlePtr\fR);
+ ClientData \fIinstanceData\fR,
+ int \fIdirection\fR,
+ ClientData *\fIhandlePtr\fR);
.CE
.PP
\fIInstanceData\fR is the same as the value passed to
@@ -777,8 +766,7 @@ device handles, the function should return \fBTCL_ERROR\fR.
.PP
This value can be retrieved with \fBTcl_ChannelGetHandleProc\fR, which returns
a pointer to the function.
-
-.SH FLUSHPROC
+.SS FLUSHPROC
.PP
The \fIflushProc\fR field is currently reserved for future use.
It should be set to NULL.
@@ -786,13 +774,12 @@ It should be set to NULL.
.PP
.CS
typedef int Tcl_DriverFlushProc(
- ClientData \fIinstanceData\fR);
+ ClientData \fIinstanceData\fR);
.CE
.PP
This value can be retrieved with \fBTcl_ChannelFlushProc\fR, which returns
a pointer to the function.
-
-.SH HANDLERPROC
+.SS HANDLERPROC
.PP
The \fIhandlerProc\fR field contains the address of a function called by
the generic layer to notify the channel that an event occurred. It should
@@ -802,8 +789,8 @@ that occur on the underlying (stacked) channel.
.PP
.CS
typedef int Tcl_DriverHandlerProc(
- ClientData \fIinstanceData\fR,
- int \fIinterestMask\fR);
+ ClientData \fIinstanceData\fR,
+ int \fIinterestMask\fR);
.CE
.PP
\fIInstanceData\fR is the same as the value passed to \fBTcl_CreateChannel\fR
@@ -814,8 +801,7 @@ type of event occurred on this channel.
This value can be retrieved with \fBTcl_ChannelHandlerProc\fR, which returns
a pointer to the function.
-.VS 8.4
-.SH "THREADACTIONPROC"
+.SS "THREADACTIONPROC"
.PP
The \fIthreadActionProc\fR field contains the address of the function
called by the generic layer when a channel is created, closed, or
@@ -832,8 +818,8 @@ might be maintaining using the calling thread as the associate. See
.PP
.CS
typedef void Tcl_DriverThreadActionProc(
- ClientData \fIinstanceData\fR,
- int \fIaction\fR);
+ ClientData \fIinstanceData\fR,
+ int \fIaction\fR);
.CE
.PP
\fIInstanceData\fR is the same as the value passed to
@@ -841,53 +827,79 @@ typedef void Tcl_DriverThreadActionProc(
.PP
These values can be retrieved with \fBTcl_ChannelThreadActionProc\fR,
which returns a pointer to the function.
-.VE 8.4
-
+.SS "TRUNCATEPROC"
+.PP
+The \fItruncateProc\fR field contains the address of the function
+called by the generic layer when a channel is truncated to some
+length. It can be NULL.
+.PP
+.CS
+typedef int Tcl_DriverTruncateProc(
+ ClientData \fIinstanceData\fR,
+ Tcl_WideInt \fIlength\fR);
+.CE
+.PP
+\fIInstanceData\fR is the same as the value passed to
+\fBTcl_CreateChannel\fR when this channel was created, and
+\fIlength\fR is the new length of the underlying file, which should
+not be negative. The result should be 0 on success or an errno code
+(suitable for use with \fBTcl_SetErrno\fR) on failure.
+.PP
+These values can be retrieved with \fBTcl_ChannelTruncateProc\fR,
+which returns a pointer to the function.
.SH TCL_BADCHANNELOPTION
.PP
-This procedure generates a "bad option" error message in an
+This procedure generates a
+.QW "bad option"
+error message in an
(optional) interpreter. It is used by channel drivers when
-a invalid Set/Get option is requested. Its purpose is to concatenate
+an invalid Set/Get option is requested. Its purpose is to concatenate
the generic options list to the specific ones and factorize
the generic options error message string.
.PP
-It always return \fBTCL_ERROR\fR
+It always returns \fBTCL_ERROR\fR
.PP
An error message is generated in \fIinterp\fR's result object to
-indicate that a command was invoked with the a bad option
+indicate that a command was invoked with a bad option.
The message has the form
.CS
bad option "blah": should be one of
<...generic options...>+<...specific options...>
+.CE
so you get for instance:
+.CS
bad option "-blah": should be one of -blocking,
-buffering, -buffersize, -eofchar, -translation,
-peername, or -sockname
-when called with \fIoptionList\fR="peername sockname"
.CE
-``blah'' is the \fIoptionName\fR argument and ``<specific options>''
+when called with \fIoptionList\fR equal to
+.QW "peername sockname"
+.PP
+.QW blah
+is the \fIoptionName\fR argument and
+.QW "<specific options>"
is a space separated list of specific option words.
The function takes good care of inserting minus signs before
-each option, commas after, and an ``or'' before the last option.
-
+each option, commas after, and an
+.QW or
+before the last option.
.SH "OLD CHANNEL TYPES"
-
The original (8.3.1 and below) \fBTcl_ChannelType\fR structure contains
the following fields:
.PP
.CS
typedef struct Tcl_ChannelType {
- char *\fItypeName\fR;
- Tcl_DriverBlockModeProc *\fIblockModeProc\fR;
- Tcl_DriverCloseProc *\fIcloseProc\fR;
- Tcl_DriverInputProc *\fIinputProc\fR;
- Tcl_DriverOutputProc *\fIoutputProc\fR;
- Tcl_DriverSeekProc *\fIseekProc\fR;
- Tcl_DriverSetOptionProc *\fIsetOptionProc\fR;
- Tcl_DriverGetOptionProc *\fIgetOptionProc\fR;
- Tcl_DriverWatchProc *\fIwatchProc\fR;
- Tcl_DriverGetHandleProc *\fIgetHandleProc\fR;
- Tcl_DriverClose2Proc *\fIclose2Proc\fR;
+ char *\fItypeName\fR;
+ Tcl_DriverBlockModeProc *\fIblockModeProc\fR;
+ Tcl_DriverCloseProc *\fIcloseProc\fR;
+ Tcl_DriverInputProc *\fIinputProc\fR;
+ Tcl_DriverOutputProc *\fIoutputProc\fR;
+ Tcl_DriverSeekProc *\fIseekProc\fR;
+ Tcl_DriverSetOptionProc *\fIsetOptionProc\fR;
+ Tcl_DriverGetOptionProc *\fIgetOptionProc\fR;
+ Tcl_DriverWatchProc *\fIwatchProc\fR;
+ Tcl_DriverGetHandleProc *\fIgetHandleProc\fR;
+ Tcl_DriverClose2Proc *\fIclose2Proc\fR;
} Tcl_ChannelType;
.CE
.PP
@@ -897,33 +909,32 @@ the new \fBTcl_ChannelType\fR structure if you are creating a stacked
channel driver, due to problems with the earlier stacked channel
implementation (in 8.2.0 to 8.3.1).
.PP
-.VS 8.4
Prior to 8.4.0 (i.e. during the later releases of 8.3 and early part
of the 8.4 development cycle) the \fBTcl_ChannelType\fR structure
contained the following fields:
.PP
.CS
typedef struct Tcl_ChannelType {
- char *\fItypeName\fR;
- Tcl_ChannelTypeVersion \fIversion\fR;
- Tcl_DriverCloseProc *\fIcloseProc\fR;
- Tcl_DriverInputProc *\fIinputProc\fR;
- Tcl_DriverOutputProc *\fIoutputProc\fR;
- Tcl_DriverSeekProc *\fIseekProc\fR;
- Tcl_DriverSetOptionProc *\fIsetOptionProc\fR;
- Tcl_DriverGetOptionProc *\fIgetOptionProc\fR;
- Tcl_DriverWatchProc *\fIwatchProc\fR;
- Tcl_DriverGetHandleProc *\fIgetHandleProc\fR;
- Tcl_DriverClose2Proc *\fIclose2Proc\fR;
- Tcl_DriverBlockModeProc *\fIblockModeProc\fR;
- Tcl_DriverFlushProc *\fIflushProc\fR;
- Tcl_DriverHandlerProc *\fIhandlerProc\fR;
+ char *\fItypeName\fR;
+ Tcl_ChannelTypeVersion \fIversion\fR;
+ Tcl_DriverCloseProc *\fIcloseProc\fR;
+ Tcl_DriverInputProc *\fIinputProc\fR;
+ Tcl_DriverOutputProc *\fIoutputProc\fR;
+ Tcl_DriverSeekProc *\fIseekProc\fR;
+ Tcl_DriverSetOptionProc *\fIsetOptionProc\fR;
+ Tcl_DriverGetOptionProc *\fIgetOptionProc\fR;
+ Tcl_DriverWatchProc *\fIwatchProc\fR;
+ Tcl_DriverGetHandleProc *\fIgetHandleProc\fR;
+ Tcl_DriverClose2Proc *\fIclose2Proc\fR;
+ Tcl_DriverBlockModeProc *\fIblockModeProc\fR;
+ Tcl_DriverFlushProc *\fIflushProc\fR;
+ Tcl_DriverHandlerProc *\fIhandlerProc\fR;
+ Tcl_DriverTruncateProc *\fItruncateProc\fR;
} Tcl_ChannelType;
.CE
.PP
When the above structure is registered as a channel type, the
\fIversion\fR field should always be \fBTCL_CHANNEL_VERSION_2\fR.
-.VE 8.4
.SH "SEE ALSO"
Tcl_Close(3), Tcl_OpenFileChannel(3), Tcl_SetErrno(3), Tcl_QueueEvent(3), Tcl_StackChannel(3), Tcl_GetStdChannel(3)
diff --git a/doc/CrtChnlHdlr.3 b/doc/CrtChnlHdlr.3
index ea07ef2..f5fd1bd 100644
--- a/doc/CrtChnlHdlr.3
+++ b/doc/CrtChnlHdlr.3
@@ -48,8 +48,8 @@ what it means for a channel to be readable or writable.
\fIProc\fR must conform to the following prototype:
.CS
typedef void Tcl_ChannelProc(
- ClientData \fIclientData\fR,
- int \fImask\fR);
+ ClientData \fIclientData\fR,
+ int \fImask\fR);
.CE
.PP
The \fIclientData\fR argument is the same as the value passed to
@@ -62,7 +62,7 @@ contain a subset of the bits from the \fImask\fR argument to
.PP
Each channel handler is identified by a unique combination of \fIchannel\fR,
\fIproc\fR and \fIclientData\fR.
-There may be many handlers for a given channel as long as they don't
+There may be many handlers for a given channel as long as they do not
have the same \fIchannel\fR, \fIproc\fR, and \fIclientData\fR.
If \fBTcl_CreateChannelHandler\fR is invoked when there is already a handler
for \fIchannel\fR, \fIproc\fR, and \fIclientData\fR, then no new
diff --git a/doc/CrtCloseHdlr.3 b/doc/CrtCloseHdlr.3
index 35f8261..c8804b1 100644
--- a/doc/CrtCloseHdlr.3
+++ b/doc/CrtCloseHdlr.3
@@ -21,7 +21,7 @@ void
\fBTcl_DeleteCloseHandler\fR(\fIchannel, proc, clientData\fR)
.sp
.SH ARGUMENTS
-.AS Tcl_CloseProc callbackData in
+.AS Tcl_CloseProc clientData
.AP Tcl_Channel channel in
The channel for which to create or delete a close callback.
.AP Tcl_CloseProc *proc in
@@ -39,7 +39,7 @@ Arbitrary one-word value to pass to \fIproc\fR.
.PP
.CS
typedef void Tcl_CloseProc(
- ClientData \fIclientData\fR);
+ ClientData \fIclientData\fR);
.CE
.PP
The \fIclientData\fR is the same as the value provided in the call to
diff --git a/doc/CrtCommand.3 b/doc/CrtCommand.3
index da0da22..fcc04d5 100644
--- a/doc/CrtCommand.3
+++ b/doc/CrtCommand.3
@@ -17,12 +17,10 @@ Tcl_CreateCommand \- implement new commands in C
Tcl_Command
\fBTcl_CreateCommand\fR(\fIinterp, cmdName, proc, clientData, deleteProc\fR)
.SH ARGUMENTS
-.AS Tcl_CmdDeleteProc **deleteProcPtr
+.AS Tcl_CmdDeleteProc *deleteProc
.AP Tcl_Interp *interp in
Interpreter in which to create new command.
-.VS 8.4
-.AP "CONST char" *cmdName in
-.VE
+.AP "const char" *cmdName in
Name of command.
.AP Tcl_CmdProc *proc in
Implementation of new command: \fIproc\fR will be called whenever
@@ -79,10 +77,10 @@ and it returns NULL.
\fBTcl_CmdProc\fR:
.CS
typedef int Tcl_CmdProc(
- ClientData \fIclientData\fR,
- Tcl_Interp *\fIinterp\fR,
- int \fIargc\fR,
- CONST char *\fIargv\fR[]);
+ ClientData \fIclientData\fR,
+ Tcl_Interp *\fIinterp\fR,
+ int \fIargc\fR,
+ const char *\fIargv\fR[]);
.CE
When \fIproc\fR is invoked the \fIclientData\fR and \fIinterp\fR
parameters will be copies of the \fIclientData\fR and \fIinterp\fR
@@ -95,26 +93,23 @@ the command name) and \fIargv\fR giving the values of the arguments
as strings. The \fIargv\fR array will contain \fIargc\fR+1 values;
the first \fIargc\fR values point to the argument strings, and the
last value is NULL.
-.VS
Note that the argument strings should not be modified as they may
point to constant strings or may be shared with other parts of the
interpreter.
-.VE
.PP
-.VS
Note that the argument strings are encoded in normalized UTF-8 since
version 8.1 of Tcl.
-.VE
.PP
-\fIProc\fR must return an integer code that is either \fBTCL_OK\fR, \fBTCL_ERROR\fR,
-\fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or \fBTCL_CONTINUE\fR. See the Tcl overview man page
+\fIProc\fR must return an integer code that is expected to be one of
+\fBTCL_OK\fR, \fBTCL_ERROR\fR, \fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or
+\fBTCL_CONTINUE\fR. See the Tcl overview man page
for details on what these codes mean. Most normal commands will only
return \fBTCL_OK\fR or \fBTCL_ERROR\fR. In addition, \fIproc\fR must set
the interpreter result to point to a string value;
in the case of a \fBTCL_OK\fR return code this gives the result
of the command, and in the case of \fBTCL_ERROR\fR it gives an error message.
The \fBTcl_SetResult\fR procedure provides an easy interface for setting
-the return value; for complete details on how the the interpreter result
+the return value; for complete details on how the interpreter result
field is managed, see the \fBTcl_Interp\fR man page.
Before invoking a command procedure,
\fBTcl_Eval\fR sets the interpreter result to point to an empty string,
@@ -135,11 +130,11 @@ application an opportunity to release any structures associated
with the command. \fIDeleteProc\fR should have arguments and
result that match the type \fBTcl_CmdDeleteProc\fR:
.CS
-typedef void Tcl_CmdDeleteProc(ClientData \fIclientData\fR);
+typedef void Tcl_CmdDeleteProc(
+ ClientData \fIclientData\fR);
.CE
The \fIclientData\fR argument will be the same as the \fIclientData\fR
argument passed to \fBTcl_CreateCommand\fR.
-.PP
.SH "SEE ALSO"
Tcl_CreateObjCommand, Tcl_DeleteCommand, Tcl_GetCommandInfo, Tcl_SetCommandInfo, Tcl_GetCommandName, Tcl_SetObjResult
diff --git a/doc/CrtFileHdlr.3 b/doc/CrtFileHdlr.3
index af21f0b..5627bd4 100644
--- a/doc/CrtFileHdlr.3
+++ b/doc/CrtFileHdlr.3
@@ -13,18 +13,14 @@ Tcl_CreateFileHandler, Tcl_DeleteFileHandler \- associate procedure callbacks wi
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
-.VS
.sp
\fBTcl_CreateFileHandler\fR(\fIfd, mask, proc, clientData\fR)
.sp
\fBTcl_DeleteFileHandler\fR(\fIfd\fR)
-.VE
.SH ARGUMENTS
.AS Tcl_FileProc clientData
-.VS
.AP int fd in
Unix file descriptor for an open file or device.
-.VE
.AP int mask in
Conditions under which \fIproc\fR should be called:
OR-ed combination of \fBTCL_READABLE\fR, \fBTCL_WRITABLE\fR,
@@ -39,12 +35,10 @@ Arbitrary one-word value to pass to \fIproc\fR.
.SH DESCRIPTION
.PP
-.VS
\fBTcl_CreateFileHandler\fR arranges for \fIproc\fR to be
invoked in the future whenever I/O becomes possible on a file
or an exceptional condition exists for the file. The file
is indicated by \fIfd\fR, and the conditions of interest
-.VE
are indicated by \fImask\fR. For example, if \fImask\fR
is \fBTCL_READABLE\fR, \fIproc\fR will be called when
the file is readable.
@@ -57,8 +51,8 @@ as \fBvwait\fR.
type \fBTcl_FileProc\fR:
.CS
typedef void Tcl_FileProc(
- ClientData \fIclientData\fR,
- int \fImask\fR);
+ ClientData \fIclientData\fR,
+ int \fImask\fR);
.CE
The \fIclientData\fR parameter to \fIproc\fR is a copy
of the \fIclientData\fR
@@ -85,14 +79,12 @@ events while waiting for files to become ready for I/O. For this to work
correctly, the application may need to use non-blocking I/O operations on
the files for which handlers are declared. Otherwise the application may
block if it reads or writes too much data; while waiting for the I/O to
-complete the application won't be able to service other events. Use
+complete the application will not be able to service other events. Use
\fBTcl_SetChannelOption\fR with \fB\-blocking\fR to set the channel into
blocking or nonblocking mode as required.
.PP
-.VS
Note that these interfaces are only supported by the Unix
implementation of the Tcl notifier.
-.VE
.SH KEYWORDS
callback, file, handler
diff --git a/doc/CrtMathFnc.3 b/doc/CrtMathFnc.3
index 43ba8fd..9629912 100644
--- a/doc/CrtMathFnc.3
+++ b/doc/CrtMathFnc.3
@@ -17,20 +17,17 @@ Tcl_CreateMathFunc, Tcl_GetMathFuncInfo, Tcl_ListMathFuncs \- Define, query and
void
\fBTcl_CreateMathFunc\fR(\fIinterp, name, numArgs, argTypes, proc, clientData\fR)
.sp
-.VS 8.4
int
-\fBTcl_GetMathFuncInfo\fR(\fIinterp, name, numArgsPtr, argTypesPtr, procPtr, clientDataPtr\fR)
+\fBTcl_GetMathFuncInfo\fR(\fIinterp, name, numArgsPtr, argTypesPtr, procPtr,
+ clientDataPtr\fR)
.sp
Tcl_Obj *
\fBTcl_ListMathFuncs\fR(\fIinterp, pattern\fR)
-.VE
.SH ARGUMENTS
-.AS Tcl_ValueType *clientDataPtr
+.AS Tcl_ValueType *clientDataPtr out
.AP Tcl_Interp *interp in
Interpreter in which new function will be defined.
-.VS 8.4
-.AP "CONST char" *name in
-.VE
+.AP "const char" *name in
Name for new function.
.AP int numArgs in
Number of arguments to new function; also gives size of \fIargTypes\fR array.
@@ -51,12 +48,12 @@ will need to be freed up using \fITcl_Free\fR.
.AP Tcl_MathProc **procPtr out
Points to a variable that will be set to contain a pointer to the
implementation code for the function (or NULL if the function is
-implemented directly in bytecode.)
+implemented directly in bytecode).
.AP ClientData *clientDataPtr out
Points to a variable that will be set to contain the clientData
argument passed to \fITcl_CreateMathFunc\fR when the function was
created if the function is not implemented directly in bytecode.
-.AP "CONST char" *pattern in
+.AP "const char" *pattern in
Pattern to match against function names so as to filter them (by
passing to \fITcl_StringMatch\fR), or NULL to not apply any filter.
.BE
@@ -65,71 +62,70 @@ passing to \fITcl_StringMatch\fR), or NULL to not apply any filter.
.PP
Tcl allows a number of mathematical functions to be used in
expressions, such as \fBsin\fR, \fBcos\fR, and \fBhypot\fR.
-\fBTcl_CreateMathFunc\fR allows applications to add additional functions
+These functions are represented by commands in the namespace,
+\fBtcl::mathfunc\fR. The \fBTcl_CreateMathFunc\fR function is
+an obsolete way for applications to add additional functions
to those already provided by Tcl or to replace existing functions.
+It should not be used by new applications, which should create
+math functions using \fBTcl_CreateObjCommand\fR to create a command
+in the \fBtcl::mathfunc\fR namespace.
+.PP
+In the \fBTcl_CreateMathFunc\fR interface,
\fIName\fR is the name of the function as it will appear in expressions.
-If \fIname\fR doesn't already exist as a function then a new function
-is created. If it does exist, then the existing function is replaced.
+If \fIname\fR does not already exist in the \fB::tcl::mathfunc\fR
+namespace, then a new command is created in that namespace.
+If \fIname\fR does exist, then the existing function is replaced.
\fINumArgs\fR and \fIargTypes\fR describe the arguments to the function.
Each entry in the \fIargTypes\fR array must be
-.VS 8.4
-one of TCL_INT, TCL_DOUBLE, TCL_WIDE_INT,
-or TCL_EITHER to indicate whether the corresponding argument must be an
+one of \fBTCL_INT\fR, \fBTCL_DOUBLE\fR, \fBTCL_WIDE_INT\fR,
+or \fBTCL_EITHER\fR to indicate whether the corresponding argument must be an
integer, a double-precision floating value, a wide (64-bit) integer,
or any, respectively.
-.VE 8.4
.PP
Whenever the function is invoked in an expression Tcl will invoke
\fIproc\fR. \fIProc\fR should have arguments and result that match
the type \fBTcl_MathProc\fR:
.CS
typedef int Tcl_MathProc(
- ClientData \fIclientData\fR,
- Tcl_Interp *\fIinterp\fR,
- Tcl_Value *\fIargs\fR,
- Tcl_Value *\fIresultPtr\fR);
+ ClientData \fIclientData\fR,
+ Tcl_Interp *\fIinterp\fR,
+ Tcl_Value *\fIargs\fR,
+ Tcl_Value *\fIresultPtr\fR);
.CE
.PP
When \fIproc\fR is invoked the \fIclientData\fR and \fIinterp\fR
arguments will be the same as those passed to \fBTcl_CreateMathFunc\fR.
\fIArgs\fR will point to an array of \fInumArgs\fR Tcl_Value structures,
which describe the actual arguments to the function:
-.VS 8.4
.CS
typedef struct Tcl_Value {
- Tcl_ValueType \fItype\fR;
- long \fIintValue\fR;
- double \fIdoubleValue\fR;
- Tcl_WideInt \fIwideValue\fR;
+ Tcl_ValueType \fItype\fR;
+ long \fIintValue\fR;
+ double \fIdoubleValue\fR;
+ Tcl_WideInt \fIwideValue\fR;
} Tcl_Value;
.CE
.PP
The \fItype\fR field indicates the type of the argument and is
-one of TCL_INT, TCL_DOUBLE or TCL_WIDE_INT.
-.VE 8.4
+one of \fBTCL_INT\fR, \fBTCL_DOUBLE\fR or \fBTCL_WIDE_INT\fR.
It will match the \fIargTypes\fR value specified for the function unless
-the \fIargTypes\fR value was TCL_EITHER. Tcl converts
+the \fIargTypes\fR value was \fBTCL_EITHER\fR. Tcl converts
the argument supplied in the expression to the type requested in
\fIargTypes\fR, if that is necessary.
Depending on the value of the \fItype\fR field, the \fIintValue\fR,
-.VS 8.4
\fIdoubleValue\fR or \fIwideValue\fR
-.VE 8.4
field will contain the actual value of the argument.
.PP
\fIProc\fR should compute its result and store it either as an integer
in \fIresultPtr->intValue\fR or as a floating value in
\fIresultPtr->doubleValue\fR.
It should set also \fIresultPtr->type\fR to one of
-.VS 8.4
-TCL_INT, TCL_DOUBLE or TCL_WIDE_INT
-.VE 8.4
+\fBTCL_INT\fR, \fBTCL_DOUBLE\fR or \fBTCL_WIDE_INT\fR
to indicate which value was set.
-Under normal circumstances \fIproc\fR should return TCL_OK.
+Under normal circumstances \fIproc\fR should return \fBTCL_OK\fR.
If an error occurs while executing the function, \fIproc\fR should
-return TCL_ERROR and leave an error message in the interpreter's result.
+return \fBTCL_ERROR\fR and leave an error message in the interpreter's result.
.PP
-.VS 8.4
\fBTcl_GetMathFuncInfo\fR retrieves the values associated with
function \fIname\fR that were passed to a preceding
\fBTcl_CreateMathFunc\fR call. Normally, the return code is
@@ -140,20 +136,21 @@ result.
If an error did not occur, the array reference placed in the variable
pointed to by \fIargTypesPtr\fR is newly allocated, and should be
released by passing it to \fBTcl_Free\fR. Some functions (the
-standard set implemented in the core) are implemented directly at the
-bytecode level; attempting to retrieve values for them causes a NULL
-to be stored in the variable pointed to by \fIprocPtr\fR and the
-variable pointed to by \fIclientDataPtr\fR will not be modified.
+standard set implemented in the core, and those defined by placing
+commands in the \fBtcl::mathfunc\fR namespace) do not have
+argument type information; attempting to retrieve values for
+them causes a NULL to be stored in the variable pointed to by
+\fIprocPtr\fR and the variable pointed to by \fIclientDataPtr\fR
+will not be modified. The variable pointed to by \fInumArgsPointer\fR
+will contain -1, and no argument types will be stored in the variable
+pointed to by \fIargTypesPointer\fR.
.PP
\fBTcl_ListMathFuncs\fR returns a Tcl object containing a list of all
the math functions defined in the interpreter whose name matches
-\fIpattern\fR. In the case of an error, NULL is returned and an error
-message is left in the interpreter result, and otherwise the returned
-object will have a reference count of zero.
-.VE
+\fIpattern\fR. The returned object has a reference count of zero.
+
+.SH "SEE ALSO"
+expr(n), info(n), Tcl_CreateObjCommand(3), Tcl_Free(3), Tcl_NewListObj(3)
.SH KEYWORDS
expression, mathematical function
-
-.SH "SEE ALSO"
-expr(n), info(n), Tcl_Free(3), Tcl_NewListObj(3)
diff --git a/doc/CrtObjCmd.3 b/doc/CrtObjCmd.3
index bcb57f3..a05efc2 100644
--- a/doc/CrtObjCmd.3
+++ b/doc/CrtObjCmd.3
@@ -28,17 +28,13 @@ int
int
\fBTcl_SetCommandInfo\fR(\fIinterp, cmdName, infoPtr\fR)
.sp
-.VS 8.4
int
\fBTcl_GetCommandInfoFromToken\fR(\fItoken, infoPtr\fR)
.sp
int
\fBTcl_SetCommandInfoFromToken\fR(\fItoken, infoPtr\fR)
-.VE
.sp
-.VS 8.4
-CONST char *
-.VE
+const char *
\fBTcl_GetCommandName\fR(\fIinterp, token\fR)
.sp
void
@@ -47,12 +43,10 @@ void
Tcl_Command
\fBTcl_GetCommandFromObj\fR(\fIinterp, objPtr\fR)
.SH ARGUMENTS
-.AS Tcl_ObjCmdProc *deleteProc in/out
+.AS Tcl_CmdDeleteProc *deleteProc in/out
.AP Tcl_Interp *interp in
Interpreter in which to create a new command or that contains a command.
-.VS 8.4
.AP char *cmdName in
-.VE
Name of command.
.AP Tcl_ObjCmdProc *proc in
Implementation of the new command: \fIproc\fR will be called whenever
@@ -96,11 +90,10 @@ and it returns NULL.
\fBTcl_ObjCmdProc\fR:
.CS
typedef int Tcl_ObjCmdProc(
- ClientData \fIclientData\fR,
- Tcl_Interp *\fIinterp\fR,
- int \fIobjc\fR,
-.VS
- Tcl_Obj *CONST \fIobjv\fR[]);
+ ClientData \fIclientData\fR,
+ Tcl_Interp *\fIinterp\fR,
+ int \fIobjc\fR,
+ Tcl_Obj *const \fIobjv\fR[]);
.CE
When \fIproc\fR is invoked, the \fIclientData\fR and \fIinterp\fR parameters
will be copies of the \fIclientData\fR and \fIinterp\fR arguments given to
@@ -117,7 +110,7 @@ Additionally, when \fIproc\fR is invoked, it must not modify the contents
of the \fIobjv\fR array by assigning new pointer values to any element of the
array (for example, \fIobjv\fR[\fB2\fR] = \fBNULL\fR) because this will
cause memory to be lost and the runtime stack to be corrupted. The
-\fBCONST\fR in the declaration of \fIobjv\fR will cause ANSI-compliant
+\fBconst\fR in the declaration of \fIobjv\fR will cause ANSI-compliant
compilers to report any such attempted assignment as an error. However,
it is acceptable to modify the internal representation of any individual
object argument. For instance, the user may call
@@ -125,7 +118,6 @@ object argument. For instance, the user may call
representation of that object; that call may change the type of the object
that \fIobjv\fR[\fB2\fR] points at, but will not change where
\fIobjv\fR[\fB2\fR] points.
-.VE
.PP
\fIproc\fR must return an integer code that is either \fBTCL_OK\fR,
\fBTCL_ERROR\fR, \fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or \fBTCL_CONTINUE\fR.
@@ -168,7 +160,8 @@ application an opportunity to release any structures associated
with the command. \fIDeleteProc\fR should have arguments and
result that match the type \fBTcl_CmdDeleteProc\fR:
.CS
-typedef void Tcl_CmdDeleteProc(ClientData \fIclientData\fR);
+typedef void Tcl_CmdDeleteProc(
+ ClientData \fIclientData\fR);
.CE
The \fIclientData\fR argument will be the same as the \fIclientData\fR
argument passed to \fBTcl_CreateObjCommand\fR.
@@ -176,7 +169,7 @@ argument passed to \fBTcl_CreateObjCommand\fR.
\fBTcl_DeleteCommand\fR deletes a command from a command interpreter.
Once the call completes, attempts to invoke \fIcmdName\fR in
\fIinterp\fR will result in errors.
-If \fIcmdName\fR isn't bound as a command in \fIinterp\fR then
+If \fIcmdName\fR is not bound as a command in \fIinterp\fR then
\fBTcl_DeleteCommand\fR does nothing and returns -1; otherwise
it returns 0.
There are no restrictions on \fIcmdName\fR: it may refer to
@@ -206,14 +199,14 @@ pointed to by \fIinfoPtr\fR and returns 1.
A \fBTcl_CmdInfo\fR structure has the following fields:
.CS
typedef struct Tcl_CmdInfo {
- int isNativeObjectProc;
- Tcl_ObjCmdProc *objProc;
- ClientData objClientData;
- Tcl_CmdProc *proc;
- ClientData clientData;
- Tcl_CmdDeleteProc *deleteProc;
- ClientData deleteData;
- Tcl_Namespace *namespacePtr;
+ int \fIisNativeObjectProc\fR;
+ Tcl_ObjCmdProc *\fIobjProc\fR;
+ ClientData \fIobjClientData\fR;
+ Tcl_CmdProc *\fIproc\fR;
+ ClientData \fIclientData\fR;
+ Tcl_CmdDeleteProc *\fIdeleteProc\fR;
+ ClientData \fIdeleteData\fR;
+ Tcl_Namespace *\fInamespacePtr\fR;
} Tcl_CmdInfo;
.CE
The \fIisNativeObjectProc\fR field has the value 1
@@ -285,16 +278,16 @@ This name does not include any \fB::\fR namespace qualifiers.
The command corresponding to \fItoken\fR must not have been deleted.
The string returned by \fBTcl_GetCommandName\fR is in dynamic memory
owned by Tcl and is only guaranteed to retain its value as long as the
-command isn't deleted or renamed; callers should copy the string if
+command is not deleted or renamed; callers should copy the string if
they need to keep it for a long time.
.PP
-\fBTcl_GetCommandFullName\fR produces the fully-qualified name
+\fBTcl_GetCommandFullName\fR produces the fully qualified name
of a command from a command token.
The name, including all namespace prefixes,
-is appended to the object specified by \fIobjPtr\fP.
+is appended to the object specified by \fIobjPtr\fR.
.PP
\fBTcl_GetCommandFromObj\fR returns a token for the command
-specified by the name in a \fBTcl_Obj\fP.
+specified by the name in a \fBTcl_Obj\fR.
The command name is resolved relative to the current namespace.
Returns NULL if the command is not found.
.SH "SEE ALSO"
diff --git a/doc/CrtSlave.3 b/doc/CrtSlave.3
index f87a4e0..3863373 100644
--- a/doc/CrtSlave.3
+++ b/doc/CrtSlave.3
@@ -8,7 +8,7 @@
.TH Tcl_CreateSlave 3 7.6 Tcl "Tcl Library Procedures"
.BS
.SH NAME
-Tcl_IsSafe, Tcl_MakeSafe, Tcl_CreateSlave, Tcl_GetSlave, Tcl_GetMaster, Tcl_GetInterpPath, Tcl_CreateAlias, Tcl_CreateAliasObj, Tcl_GetAlias, Tcl_GetAliasObj, Tcl_ExposeCommand, Tcl_HideCommand \- manage multiple Tcl interpreters, aliases and hidden commands.
+Tcl_IsSafe, Tcl_MakeSafe, Tcl_CreateSlave, Tcl_GetSlave, Tcl_GetMaster, Tcl_GetInterpPath, Tcl_CreateAlias, Tcl_CreateAliasObj, Tcl_GetAlias, Tcl_GetAliasObj, Tcl_ExposeCommand, Tcl_HideCommand \- manage multiple Tcl interpreters, aliases and hidden commands
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -31,20 +31,21 @@ Tcl_Interp *
int
\fBTcl_GetInterpPath\fR(\fIaskingInterp, slaveInterp\fR)
.sp
-.VS
int
-\fBTcl_CreateAlias\fR(\fIslaveInterp, slaveCmd, targetInterp, targetCmd, argc, argv\fR)
+\fBTcl_CreateAlias\fR(\fIslaveInterp, slaveCmd, targetInterp, targetCmd,
+ argc, argv\fR)
.sp
int
-\fBTcl_CreateAliasObj\fR(\fIslaveInterp, slaveCmd, targetInterp, targetCmd, objc, objv\fR)
-.VE
+\fBTcl_CreateAliasObj\fR(\fIslaveInterp, slaveCmd, targetInterp, targetCmd,
+ objc, objv\fR)
.sp
int
-\fBTcl_GetAlias\fR(\fIinterp, slaveCmd, targetInterpPtr, targetCmdPtr, argcPtr, argvPtr\fR)
+\fBTcl_GetAlias\fR(\fIinterp, slaveCmd, targetInterpPtr, targetCmdPtr,
+ argcPtr, argvPtr\fR)
.sp
-.VS
int
-\fBTcl_GetAliasObj\fR(\fIinterp, slaveCmd, targetInterpPtr, targetCmdPtr, objcPtr, objvPtr\fR)
+\fBTcl_GetAliasObj\fR(\fIinterp, slaveCmd, targetInterpPtr, targetCmdPtr,
+ objcPtr, objvPtr\fR)
.sp
int
\fBTcl_ExposeCommand\fR(\fIinterp, hiddenCmdName, cmdName\fR)
@@ -52,44 +53,46 @@ int
int
\fBTcl_HideCommand\fR(\fIinterp, cmdName, hiddenCmdName\fR)
.SH ARGUMENTS
-.AS Tcl_InterpDeleteProc **hiddenCmdName
+.AS "const char *const" **targetInterpPtr out
.AP Tcl_Interp *interp in
Interpreter in which to execute the specified command.
-.AP "CONST char" *slaveName in
+.AP "const char" *slaveName in
Name of slave interpreter to create or manipulate.
.AP int isSafe in
-If non-zero, a ``safe'' slave that is suitable for running untrusted code
+If non-zero, a
+.QW safe
+slave that is suitable for running untrusted code
is created, otherwise a trusted slave is created.
.AP Tcl_Interp *slaveInterp in
Interpreter to use for creating the source command for an alias (see
below).
-.AP "CONST char" *slaveCmd in
+.AP "const char" *slaveCmd in
Name of source command for alias.
.AP Tcl_Interp *targetInterp in
Interpreter that contains the target command for an alias.
-.AP "CONST char" *targetCmd in
+.AP "const char" *targetCmd in
Name of target command for alias in \fItargetInterp\fR.
.AP int argc in
Count of additional arguments to pass to the alias command.
-.AP "CONST char * CONST" *argv in
+.AP "const char *const" *argv in
Vector of strings, the additional arguments to pass to the alias command.
This storage is owned by the caller.
.AP int objc in
Count of additional object arguments to pass to the alias object command.
-.AP Tcl_Object **objv in
+.AP Tcl_Obj **objv in
Vector of Tcl_Obj structures, the additional object arguments to pass to
the alias object command.
This storage is owned by the caller.
.AP Tcl_Interp **targetInterpPtr in
Pointer to location to store the address of the interpreter where a target
command is defined for an alias.
-.AP "CONST char" **targetCmdPtr out
+.AP "const char" **targetCmdPtr out
Pointer to location to store the address of the name of the target command
for an alias.
.AP int *argcPtr out
Pointer to location to store count of additional arguments to be passed to
the alias. The location is in storage owned by the caller.
-.AP "CONST char" ***argvPtr out
+.AP "const char" ***argvPtr out
Pointer to location to store a vector of strings, the additional arguments
to pass to an alias. The location is in storage owned by the caller, the
vector of strings is owned by the called function.
@@ -101,17 +104,11 @@ Pointer to location to store a vector of Tcl_Obj structures, the additional
arguments to pass to an object alias command. The location is in storage
owned by the caller, the vector of Tcl_Obj structures is owned by the
called function.
-.VS
-.VS 8.4
-.AP "CONST char" *cmdName in
-.VE
+.AP "const char" *cmdName in
Name of an exposed command to hide or create.
-.VS 8.4
-.AP "CONST char" *hiddenCmdName in
-.VE
+.AP "const char" *hiddenCmdName in
Name under which a hidden command is stored and with which it can be
exposed or invoked.
-.VE
.BE
.SH DESCRIPTION
@@ -129,16 +126,21 @@ It also creates a slave command named \fIslaveName\fR in \fIinterp\fR which
allows \fIinterp\fR to manipulate the new slave.
If \fIisSafe\fR is zero, the command creates a trusted slave in which Tcl
code has access to all the Tcl commands.
-If it is \fB1\fR, the command creates a ``safe'' slave in which Tcl code
-has access only to set of Tcl commands defined as ``Safe Tcl''; see the
-manual entry for the Tcl \fBinterp\fR command for details.
+If it is \fB1\fR, the command creates a
+.QW safe
+slave in which Tcl code has access only to set of Tcl commands defined as
+.QW "Safe Tcl" ;
+see the manual entry for the Tcl \fBinterp\fR command for details.
If the creation of the new slave interpreter failed, \fBNULL\fR is returned.
.PP
-\fBTcl_IsSafe\fR returns \fB1\fR if \fIinterp\fR is ``safe'' (was created
-with the \fBTCL_SAFE_INTERPRETER\fR flag specified),
+\fBTcl_IsSafe\fR returns \fB1\fR if \fIinterp\fR is
+.QW safe
+(was created with the \fBTCL_SAFE_INTERPRETER\fR flag specified),
\fB0\fR otherwise.
.PP
-\fBTcl_MakeSafe\fR marks \fIinterp\fR as ``safe'', so that future
+\fBTcl_MakeSafe\fR marks \fIinterp\fR as
+.QW safe ,
+so that future
calls to \fBTcl_IsSafe\fR will return 1. It also removes all known
potentially-unsafe core functionality (both commands and variables)
from \fIinterp\fR. However, it cannot know what parts of an extension
@@ -163,7 +165,6 @@ of the relative path succeeds, \fBTCL_OK\fR is returned, else
\fBTCL_ERROR\fR is returned and the \fIresult\fR field in
\fIaskingInterp\fR contains the error message.
.PP
-.VS
\fBTcl_CreateAlias\fR creates an object command named \fIslaveCmd\fR in
\fIslaveInterp\fR that when invoked, will cause the command \fItargetCmd\fR
to be invoked in \fItargetInterp\fR. The arguments specified by the strings
@@ -180,7 +181,6 @@ restrictions on how they are related.
\fBTcl_CreateAliasObj\fR is similar to \fBTcl_CreateAlias\fR except
that it takes a vector of objects to pass as additional arguments instead
of a vector of strings.
-.VE
.PP
\fBTcl_GetAlias\fR returns information about an alias \fIaliasName\fR
in \fIinterp\fR. Any of the result fields can be \fBNULL\fR, in
@@ -188,7 +188,6 @@ which case the corresponding datum is not returned. If a result field is
non\-\fBNULL\fR, the address indicated is set to the corresponding datum.
For example, if \fItargetNamePtr\fR is non\-\fBNULL\fR it is set to a
pointer to the string containing the name of the target command.
-.VS
.PP
\fBTcl_GetAliasObj\fR is similar to \fBTcl_GetAlias\fR except that it
returns a pointer to a vector of Tcl_Obj structures instead of a vector of
diff --git a/doc/CrtTimerHdlr.3 b/doc/CrtTimerHdlr.3
index 9018ae2..e948728 100644
--- a/doc/CrtTimerHdlr.3
+++ b/doc/CrtTimerHdlr.3
@@ -9,8 +9,7 @@
.TH Tcl_CreateTimerHandler 3 7.5 Tcl "Tcl Library Procedures"
.BS
.SH NAME
-Tcl_CreateTimerHandler, Tcl_DeleteTimerHandler \- call a procedure at a
-given time
+Tcl_CreateTimerHandler, Tcl_DeleteTimerHandler \- call a procedure at a given time
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -28,7 +27,7 @@ Procedure to invoke after \fImilliseconds\fR have elapsed.
.AP ClientData clientData in
Arbitrary one-word value to pass to \fIproc\fR.
.AP Tcl_TimerToken token in
-Token for previously-created timer handler (the return value
+Token for previously created timer handler (the return value
from some previous call to \fBTcl_CreateTimerHandler\fR).
.BE
@@ -43,7 +42,7 @@ dispatch events through \fBTcl_DoOneEvent\fR or through Tcl commands
such as \fBvwait\fR.
The call to \fIproc\fR may not be made at the exact time given by
\fImilliseconds\fR: it will be made at the next opportunity
-after that time. For example, if \fBTcl_DoOneEvent\fR isn't
+after that time. For example, if \fBTcl_DoOneEvent\fR is not
called until long after the time has elapsed, or if there
are other pending events to process before the call to
\fIproc\fR, then the call to \fIproc\fR will be delayed.
@@ -61,7 +60,7 @@ structure containing application-specific information about
what to do in \fIproc\fR.
.PP
\fBTcl_DeleteTimerHandler\fR may be called to delete a
-previously-created timer handler. It deletes the handler
+previously created timer handler. It deletes the handler
indicated by \fItoken\fR so that no call to \fIproc\fR
will be made; if that handler no longer exists
(e.g. because the time period has already elapsed and \fIproc\fR
diff --git a/doc/CrtTrace.3 b/doc/CrtTrace.3
index e11bd55..076f47b 100644
--- a/doc/CrtTrace.3
+++ b/doc/CrtTrace.3
@@ -1,7 +1,7 @@
'\"
'\" Copyright (c) 1989-1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
-'\" Copyright (c) 2002 by Kevin B. Kenny. All rights reserved.
+'\" Copyright (c) 2002 by Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -23,7 +23,7 @@ Tcl_Trace
.sp
\fBTcl_DeleteTrace\fR(\fIinterp, trace\fR)
.SH ARGUMENTS
-.AS Tcl_CmdObjTraceDeleteProc (clientData)()
+.AS Tcl_CmdObjTraceDeleteProc *deleteProc
.AP Tcl_Interp *interp in
Interpreter containing command to be traced or untraced.
.AP int level in
@@ -36,14 +36,14 @@ A value of 0 means that commands at any level are traced.
.AP int flags in
Flags governing the trace execution. See below for details.
.AP Tcl_CmdObjTraceProc *objProc in
-Procedure to call for each command that's executed. See below for
+Procedure to call for each command that is executed. See below for
details of the calling sequence.
.AP Tcl_CmdTraceProc *proc in
-Procedure to call for each command that's executed. See below for
+Procedure to call for each command that is executed. See below for
details on the calling sequence.
.AP ClientData clientData in
Arbitrary one-word value to pass to \fIobjProc\fR or \fIproc\fR.
-.AP Tcl_CmdObjTraceDeleteProc *deleteProc
+.AP Tcl_CmdObjTraceDeleteProc *deleteProc in
Procedure to call when the trace is deleted. See below for details of
the calling sequence. A NULL pointer is permissible and results in no
callback when the trace is deleted.
@@ -65,13 +65,13 @@ interpreter.
\fBTcl_CmdObjTraceProc\fR:
.CS
typedef int \fBTcl_CmdObjTraceProc\fR(
- \fBClientData\fR \fIclientData\fR,
- \fBTcl_Interp\fR* \fIinterp\fR,
- int \fIlevel\fR,
- CONST char* \fIcommand\fR,
- \fBTcl_Command\fR \fIcommandToken\fR,
- int \fIobjc\fR,
- \fBTcl_Obj\fR *CONST \fIobjv\fR[] );
+ \fBClientData\fR \fIclientData\fR,
+ \fBTcl_Interp\fR* \fIinterp\fR,
+ int \fIlevel\fR,
+ const char *\fIcommand\fR,
+ \fBTcl_Command\fR \fIcommandToken\fR,
+ int \fIobjc\fR,
+ \fBTcl_Obj\fR *const \fIobjv\fR[] );
.CE
The \fIclientData\fR and \fIinterp\fR parameters are copies of the
corresponding arguments given to \fBTcl_CreateTrace\fR.
@@ -141,8 +141,7 @@ When \fBTcl_DeleteTrace\fR is called, the interpreter invokes the
\fBTcl_CmdObjTraceDeleteProc\fR:
.CS
typedef void \fBTcl_CmdObjTraceDeleteProc\fR(
- \fBClientData\fR \fIclientData\fR
-);
+ \fBClientData\fR \fIclientData\fR);
.CE
The \fIclientData\fR parameter will be the same as the
\fIclientData\fR parameter that was originally passed to
@@ -156,14 +155,14 @@ that its \fIproc\fR parameter should have arguments and result that
match the type \fBTcl_CmdTraceProc\fR:
.CS
typedef void Tcl_CmdTraceProc(
- ClientData \fIclientData\fR,
- Tcl_Interp *\fIinterp\fR,
- int \fIlevel\fR,
- char *\fIcommand\fR,
- Tcl_CmdProc *\fIcmdProc\fR,
- ClientData \fIcmdClientData\fR,
- int \fIargc\fR,
- CONST char *\fIargv\fR[]);
+ ClientData \fIclientData\fR,
+ Tcl_Interp *\fIinterp\fR,
+ int \fIlevel\fR,
+ char *\fIcommand\fR,
+ Tcl_CmdProc *\fIcmdProc\fR,
+ ClientData \fIcmdClientData\fR,
+ int \fIargc\fR,
+ const char *\fIargv\fR[]);
.CE
The parameters to the \fIproc\fR callback are similar to those of the
\fIobjProc\fR callback above. The \fIcommandToken\fR is
diff --git a/doc/DString.3 b/doc/DString.3
index 8c6f516..a85b1cf 100644
--- a/doc/DString.3
+++ b/doc/DString.3
@@ -17,10 +17,10 @@ Tcl_DStringInit, Tcl_DStringAppend, Tcl_DStringAppendElement, Tcl_DStringStartSu
\fBTcl_DStringInit\fR(\fIdsPtr\fR)
.sp
char *
-\fBTcl_DStringAppend\fR(\fIdsPtr, string, length\fR)
+\fBTcl_DStringAppend\fR(\fIdsPtr, bytes, length\fR)
.sp
char *
-\fBTcl_DStringAppendElement\fR(\fIdsPtr, string\fR)
+\fBTcl_DStringAppendElement\fR(\fIdsPtr, element\fR)
.sp
\fBTcl_DStringStartSublist\fR(\fIdsPtr\fR)
.sp
@@ -42,13 +42,15 @@ char *
.sp
\fBTcl_DStringGetResult\fR(\fIinterp, dsPtr\fR)
.SH ARGUMENTS
-.AS Tcl_DString newLength
+.AS Tcl_DString newLength in/out
.AP Tcl_DString *dsPtr in/out
Pointer to structure that is used to manage a dynamic string.
-.AP "CONST char" *string in
-Pointer to characters to add to dynamic string.
+.AP "const char" *bytes in
+Pointer to characters to append to dynamic string.
+.AP "const char" *element in
+Pointer to characters to append as list element to dynamic string.
.AP int length in
-Number of characters from string to add to dynamic string. If -1,
+Number of bytes from \fIbytes\fR to add to dynamic string. If -1,
add all characters up to null terminating character.
.AP int newLength in
New length for dynamic string, not including null terminating
@@ -75,7 +77,7 @@ string.
.PP
\fBTcl_DStringAppend\fR adds new information to a dynamic string,
allocating more memory for the string if needed.
-If \fIlength\fR is less than zero then everything in \fIstring\fR
+If \fIlength\fR is less than zero then everything in \fIbytes\fR
is appended to the dynamic string; otherwise \fIlength\fR
specifies the number of bytes to append.
\fBTcl_DStringAppend\fR returns a pointer to the characters of
@@ -83,14 +85,16 @@ the new string. The string can also be retrieved from the
\fIstring\fR field of the Tcl_DString structure.
.PP
\fBTcl_DStringAppendElement\fR is similar to \fBTcl_DStringAppend\fR
-except that it doesn't take a \fIlength\fR argument (it appends
-all of \fIstring\fR) and it converts the string to a proper list element
+except that it does not take a \fIlength\fR argument (it appends
+all of \fIelement\fR) and it converts the string to a proper list element
before appending.
\fBTcl_DStringAppendElement\fR adds a separator space before the
new list element unless the new list element is the first in a
list or sub-list (i.e. either the current string is empty, or it
-contains the single character ``{'', or the last two characters of
-the current string are `` {'').
+contains the single character
+.QW { ,
+or the last two characters of the current string are
+.QW " {" ).
\fBTcl_DStringAppendElement\fR returns a pointer to the
characters of the new string.
.PP
@@ -128,7 +132,7 @@ will still need to be called.
This procedure is now deprecated. \fBTcl_DStringSetLength\fR should
be used instead.
.PP
-\fBTcl_DStringFree\fR should be called when you're finished using
+\fBTcl_DStringFree\fR should be called when you are finished using
the string. It frees up any memory that was allocated for the string
and reinitializes the string's value to an empty string.
.PP
diff --git a/doc/DetachPids.3 b/doc/DetachPids.3
index 17b57eb..0535cd8 100644
--- a/doc/DetachPids.3
+++ b/doc/DetachPids.3
@@ -19,18 +19,18 @@ Tcl_DetachPids, Tcl_ReapDetachedProcs, Tcl_WaitPid \- manage child processes in
\fBTcl_ReapDetachedProcs\fR()
.sp
Tcl_Pid
-\fBTcl_WaitPid\fR(\fIpid, statPtr, options\fR)
+\fBTcl_WaitPid\fR(\fIpid, statusPtr, options\fR)
.SH ARGUMENTS
-.AS int *statusPtr
+.AS Tcl_Pid *statusPtr out
.AP int numPids in
Number of process ids contained in the array pointed to by \fIpidPtr\fR.
.AP int *pidPtr in
Address of array containing \fInumPids\fR process ids.
.AP Tcl_Pid pid in
The id of the process (pipe) to wait for.
-.AP int* statPtr out
+.AP int *statusPtr out
The result of waiting on a process (pipe). Either 0 or ECHILD.
-.AP int options
+.AP int options in
The options controlling the wait. WNOHANG specifies not to wait when
checking the process.
.BE
@@ -49,16 +49,16 @@ overflow, even if all the children have exited.
\fBTcl_DetachPids\fR may be called to ask Tcl to take responsibility
for one or more processes whose process ids are contained in the
\fIpidPtr\fR array passed as argument. The caller presumably
-has started these processes running in background and doesn't
+has started these processes running in background and does not
want to have to deal with them again.
.PP
\fBTcl_ReapDetachedProcs\fR invokes the \fBwaitpid\fR kernel call
on each of the background processes so that its state can be cleaned
-up if it has exited. If the process hasn't exited yet,
-\fBTcl_ReapDetachedProcs\fR doesn't wait for it to exit; it will check again
+up if it has exited. If the process has not exited yet,
+\fBTcl_ReapDetachedProcs\fR does not wait for it to exit; it will check again
the next time it is invoked.
Tcl automatically calls \fBTcl_ReapDetachedProcs\fR each time the
-\fBexec\fR command is executed, so in most cases it isn't necessary
+\fBexec\fR command is executed, so in most cases it is not necessary
for any code outside of Tcl to invoke \fBTcl_ReapDetachedProcs\fR.
However, if you call \fBTcl_DetachPids\fR in situations where the
\fBexec\fR command may never get executed, you may wish to call
diff --git a/doc/DictObj.3 b/doc/DictObj.3
new file mode 100644
index 0000000..74b8dd1
--- /dev/null
+++ b/doc/DictObj.3
@@ -0,0 +1,234 @@
+'\"
+'\" Copyright (c) 2003 Donal K. Fellows
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.so man.macros
+.TH Tcl_DictObj 3 8.5 Tcl "Tcl Library Procedures"
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+Tcl_NewDictObj, Tcl_DictObjPut, Tcl_DictObjGet, Tcl_DictObjRemove, Tcl_DictObjSize, Tcl_DictObjFirst, Tcl_DictObjNext, Tcl_DictObjDone, Tcl_DictObjPutKeyList, Tcl_DictObjRemoveKeyList \- manipulate Tcl objects as dictionaries
+.SH SYNOPSIS
+.nf
+\fB#include <tcl.h>\fR
+.sp
+Tcl_Obj *
+\fBTcl_NewDictObj\fR()
+.sp
+int
+\fBTcl_DictObjGet\fR(\fIinterp, dictPtr, keyPtr, valuePtrPtr\fR)
+.sp
+int
+\fBTcl_DictObjPut\fR(\fIinterp, dictPtr, keyPtr, valuePtr\fR)
+.sp
+int
+\fBTcl_DictObjRemove\fR(\fIinterp, dictPtr, keyPtr\fR)
+.sp
+int
+\fBTcl_DictObjSize\fR(\fIinterp, dictPtr, sizePtr\fR)
+.sp
+int
+\fBTcl_DictObjFirst\fR(\fIinterp, dictPtr, searchPtr,
+ keyPtrPtr, valuePtrPtr, donePtr\fR)
+.sp
+void
+\fBTcl_DictObjNext\fR(\fIsearchPtr, keyPtrPtr, valuePtrPtr, donePtr\fR)
+.sp
+void
+\fBTcl_DictObjDone\fR(\fIsearchPtr\fR)
+.sp
+int
+\fBTcl_DictObjPutKeyList\fR(\fIinterp, dictPtr, keyc, keyv, valuePtr\fR)
+.sp
+int
+\fBTcl_DictObjRemoveKeyList\fR(\fIinterp, dictPtr, keyc, keyv\fR)
+.SH ARGUMENTS
+.AS Tcl_DictSearch "**valuePtrPtr" in/out
+.AP Tcl_Interp *interp in
+If an error occurs while converting an object to be a dictionary object,
+an error message is left in the interpreter's result object
+unless \fIinterp\fR is NULL.
+.AP Tcl_Obj *dictPtr in/out
+Points to the dictionary object to be manipulated.
+If \fIdictPtr\fR does not already point to a dictionary object,
+an attempt will be made to convert it to one.
+.AP Tcl_Obj *keyPtr in
+Points to the key for the key/value pair being manipulated within the
+dictionary object.
+.AP Tcl_Obj **keyPtrPtr out
+Points to a variable that will have the key from a key/value pair
+placed within it. May be NULL to indicate that the caller is not
+interested in the key.
+.AP Tcl_Obj *valuePtr in
+Points to the value for the key/value pair being manipulate within the
+dictionary object (or sub-object, in the case of
+\fBTcl_DictObjPutKeyList\fR.)
+.AP Tcl_Obj **valuePtrPtr out
+Points to a variable that will have the value from a key/value pair
+placed within it. For \fBTcl_DictObjFirst\fR and
+\fBTcl_DictObjNext\fR, this may be NULL to indicate that the caller is
+not interested in the value.
+.AP int *sizePtr out
+Points to a variable that will have the number of key/value pairs
+contained within the dictionary placed within it.
+.AP Tcl_DictSearch *searchPtr in/out
+Pointer to record to use to keep track of progress in enumerating all
+key/value pairs in a dictionary. The contents of the record will be
+initialized by the call to \fBTcl_DictObjFirst\fR. If the enumerating
+is to be terminated before all values in the dictionary have been
+returned, the search record \fImust\fR be passed to
+\fBTcl_DictObjDone\fR to enable the internal locks to be released.
+.AP int *donePtr out
+Points to a variable that will have a non-zero value written into it
+when the enumeration of the key/value pairs in a dictionary has
+completed, and a zero otherwise.
+.AP int keyc in
+Indicates the number of keys that will be supplied in the \fIkeyv\fR
+array.
+.AP "Tcl_Obj *const" *keyv in
+Array of \fIkeyc\fR pointers to objects that
+\fBTcl_DictObjPutKeyList\fR and \fBTcl_DictObjRemoveKeyList\fR will
+use to locate the key/value pair to manipulate within the
+sub-dictionaries of the main dictionary object passed to them.
+.BE
+
+.SH DESCRIPTION
+.PP
+Tcl dictionary objects have an internal representation that supports
+efficient mapping from keys to values and which guarantees that the
+particular ordering of keys within the dictionary remains the same
+modulo any keys being deleted (which removes them from the order) or
+added (which adds them to the end of the order). If reinterpreted as a
+list, the values at the even-valued indices in the list will be the
+keys of the dictionary, and each will be followed (in the odd-valued
+index) by the value associated with that key.
+.PP
+The procedures described in this man page are used to
+create, modify, index, and iterate over dictionary objects from C code.
+.PP
+\fBTcl_NewDictObj\fR creates a new, empty dictionary object. The
+string representation of the object will be invalid, and the reference
+count of the object will be zero.
+.PP
+\fBTcl_DictObjGet\fR looks up the given key within the given
+dictionary and writes a pointer to the value associated with that key
+into the variable pointed to by \fIvaluePtrPtr\fR, or a NULL if the
+key has no mapping within the dictionary. The result of this
+procedure is \fBTCL_OK\fR, or \fBTCL_ERROR\fR if the \fIdictPtr\fR cannot be
+converted to a dictionary.
+.PP
+\fBTcl_DictObjPut\fR updates the given dictionary so that the given
+key maps to the given value; any key may exist at most once in any
+particular dictionary. The dictionary must not be shared, but the key
+and value may be. This procedure may increase the reference count of
+both key and value if it proves necessary to store them. Neither key
+nor value should be NULL. The result of this procedure is \fBTCL_OK\fR, or
+\fBTCL_ERROR\fR if the \fIdictPtr\fR cannot be converted to a dictionary.
+.PP
+\fBTcl_DictObjRemove\fR updates the given dictionary so that the given
+key has no mapping to any value. The dictionary must not be shared,
+but the key may be. The key actually stored in the dictionary will
+have its reference count decremented if it was present. It is not an
+error if the key did not previously exist. The result of this
+procedure is \fBTCL_OK\fR, or \fBTCL_ERROR\fR if the \fIdictPtr\fR cannot be
+converted to a dictionary.
+.PP
+\fBTcl_DictObjSize\fR updates the given variable with the number of
+key/value pairs currently in the given dictionary. The result of this
+procedure is \fBTCL_OK\fR, or \fBTCL_ERROR\fR if the \fIdictPtr\fR cannot be
+converted to a dictionary.
+.PP
+\fBTcl_DictObjFirst\fR commences an iteration across all the key/value
+pairs in the given dictionary, placing the key and value in the
+variables pointed to by the \fIkeyPtrPtr\fR and \fIvaluePtrPtr\fR
+arguments (which may be NULL to indicate that the caller is
+uninterested in they key or variable respectively.) The next
+key/value pair in the dictionary may be retrieved with
+\fBTcl_DictObjNext\fR. Concurrent updates of the dictionary's
+internal representation will not modify the iteration processing
+unless the dictionary is unshared, when this will trigger premature
+termination of the iteration instead (which Tcl scripts cannot trigger
+via the \fBdict\fR command.) The \fIsearchPtr\fR argument points to a
+piece of context that is used to identify which particular iteration
+is being performed, and is initialized by the call to
+\fBTcl_DictObjFirst\fR. The \fIdonePtr\fR argument points to a
+variable that is updated to be zero of there are further key/value
+pairs to be iterated over, or non-zero if the iteration is complete.
+The order of iteration is implementation-defined. If the
+\fIdictPtr\fR argument cannot be converted to a dictionary,
+\fBTcl_DictObjFirst\fR returns \fBTCL_ERROR\fR and the iteration is not
+commenced, and otherwise it returns \fBTCL_OK\fR.
+.PP
+When \fBTcl_DictObjFirst\fR is called upon a dictionary, a lock is placed on
+the dictionary to enable that dictionary to be iterated over safely without
+regard for whether the dictionary is modified during the iteration. Because of
+this, once the iteration over a dictionary's keys has finished (whether
+because all values have been iterated over as indicated by the variable
+indicated by the \fIdonePtr\fR argument being set to one, or because no
+further values are required) the \fBTcl_DictObjDone\fR function must be called
+with the same \fIsearchPtr\fR as was passed to \fBTcl_DictObjFirst\fR so that
+the internal locks can be released. Once a particular \fIsearchPtr\fR is
+passed to \fBTcl_DictObjDone\fR, passing it to \fBTcl_DictObjNext\fR (without
+first initializing it with \fBTcl_DictObjFirst\fR) will result in no values
+being produced and the variable pointed to by \fIdonePtr\fR being set to one.
+It is safe to call \fBTcl_DictObjDone\fR multiple times on the same
+\fIsearchPtr\fR for each call to \fBTcl_DictObjFirst\fR.
+.PP
+The procedures \fBTcl_DictObjPutKeyList\fR and
+\fBTcl_DictObjRemoveKeyList\fR are the close analogues of
+\fBTcl_DictObjPut\fR and \fBTcl_DictObjRemove\fR respectively, except
+that instead of working with a single dictionary, they are designed to
+operate on a nested tree of dictionaries, with inner dictionaries
+stored as values inside outer dictionaries. The \fIkeyc\fR and
+\fIkeyv\fR arguments specify a list of keys (with outermost keys
+first) that acts as a path to the key/value pair to be affected. Note
+that there is no corresponding operation for reading a value for a
+path as this is easy to construct from repeated use of
+\fBTcl_DictObjGet\fR. With \fBTcl_DictObjPutKeyList\fR, nested
+dictionaries are created for non-terminal keys where they do not
+already exist. With \fBTcl_DictObjRemoveKeyList\fR, all non-terminal
+keys must exist and have dictionaries as their values.
+.SH EXAMPLE
+Using the dictionary iteration interface to search determine if there
+is a key that maps to itself:
+.PP
+.CS
+Tcl_DictSearch search;
+Tcl_Obj *key, *value;
+int done;
+
+/*
+ * Assume interp and objPtr are parameters. This is the
+ * idiomatic way to start an iteration over the dictionary; it
+ * sets a lock on the internal representation that ensures that
+ * there are no concurrent modification issues when normal
+ * reference count management is also used. The lock is
+ * released automatically when the loop is finished, but must
+ * be released manually when an exceptional exit from the loop
+ * is performed. However it is safe to try to release the lock
+ * even if we've finished iterating over the loop.
+ */
+if (\fBTcl_DictObjFirst\fR(interp, objPtr, &search,
+ &key, &value, &done) != TCL_OK) {
+ return TCL_ERROR;
+}
+for (; !done ; \fBTcl_DictObjNext\fR(&search, &key, &value, &done)) {
+ /*
+ * Note that strcmp() is not a good way of comparing
+ * objects and is just used here for demonstration
+ * purposes.
+ */
+ if (!strcmp(Tcl_GetString(key), Tcl_GetString(value))) {
+ break;
+ }
+}
+\fBTcl_DictObjDone\fR(&search);
+Tcl_SetObjResult(interp, Tcl_NewBooleanObj(!done));
+return TCL_OK;
+.CE
+.SH "SEE ALSO"
+Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_InitObjHashTable
+.SH KEYWORDS
+dict, dict object, dictionary, dictionary object, hash table, iteration, object
diff --git a/doc/DoOneEvent.3 b/doc/DoOneEvent.3
index 058307d..9bdf926 100644
--- a/doc/DoOneEvent.3
+++ b/doc/DoOneEvent.3
@@ -21,9 +21,9 @@ int
.AP int flags in
This parameter is normally zero. It may be an OR-ed combination
of any of the following flag bits:
-TCL_WINDOW_EVENTS,
-TCL_FILE_EVENTS, TCL_TIMER_EVENTS, TCL_IDLE_EVENTS, TCL_ALL_EVENTS, or
-TCL_DONT_WAIT.
+\fBTCL_WINDOW_EVENTS\fR, \fBTCL_FILE_EVENTS\fR,
+\fBTCL_TIMER_EVENTS\fR, \fBTCL_IDLE_EVENTS\fR, \fBTCL_ALL_EVENTS\fR,
+or \fBTCL_DONT_WAIT\fR.
.BE
.SH DESCRIPTION
@@ -71,7 +71,7 @@ Process all kinds of events: equivalent to OR-ing together all of the
above flags or specifying none of them.
.TP 27
\fBTCL_DONT_WAIT\fR \-
-Don't sleep: process only events that are ready at the time of the
+Do not sleep: process only events that are ready at the time of the
call.
.LP
If any of the flags \fBTCL_WINDOW_EVENTS\fR, \fBTCL_FILE_EVENTS\fR,
diff --git a/doc/DoWhenIdle.3 b/doc/DoWhenIdle.3
index a15f1cb..bfc19fb 100644
--- a/doc/DoWhenIdle.3
+++ b/doc/DoWhenIdle.3
@@ -30,7 +30,7 @@ Arbitrary one-word value to pass to \fIproc\fR.
\fBTcl_DoWhenIdle\fR arranges for \fIproc\fR to be invoked
when the application becomes idle. The application is
considered to be idle when \fBTcl_DoOneEvent\fR has been
-called, couldn't find any events to handle, and is about
+called, could not find any events to handle, and is about
to go to sleep waiting for an event to occur. At this
point all pending \fBTcl_DoWhenIdle\fR handlers are
invoked. For each call to \fBTcl_DoWhenIdle\fR there will
@@ -59,7 +59,7 @@ all of the handlers are removed. If no existing handlers match
\fIproc\fR and \fIclientData\fR then nothing happens.
.PP
\fBTcl_DoWhenIdle\fR is most useful in situations where
-(a) a piece of work will have to be done but (b) it's
+(a) a piece of work will have to be done but (b) it is
possible that something will happen in the near future
that will change what has to be done or require something
different to be done. \fBTcl_DoWhenIdle\fR allows the
diff --git a/doc/DoubleObj.3 b/doc/DoubleObj.3
index b65af58..12818b0 100644
--- a/doc/DoubleObj.3
+++ b/doc/DoubleObj.3
@@ -23,55 +23,42 @@ int
.SH ARGUMENTS
.AS Tcl_Interp doubleValue in/out
.AP double doubleValue in
-A double-precision floating point value used to initialize or set a double object.
+A double-precision floating-point value used to initialize or set a Tcl object.
.AP Tcl_Obj *objPtr in/out
-For \fBTcl_SetDoubleObj\fR, this points to the object to be converted
-to double type.
+For \fBTcl_SetDoubleObj\fR, this points to the object in which to store a
+double value.
For \fBTcl_GetDoubleFromObj\fR, this refers to the object
-from which to get a double value;
-if \fIobjPtr\fR does not already point to a double object,
-an attempt will be made to convert it to one.
+from which to retrieve a double value.
.AP Tcl_Interp *interp in/out
-If an error occurs during conversion,
-an error message is left in the interpreter's result object
-unless \fIinterp\fR is NULL.
+When non-NULL, an error message is left here when double value retrieval fails.
.AP double *doublePtr out
-Points to place to store the double value
-obtained from \fIobjPtr\fR.
+Points to place to store the double value obtained from \fIobjPtr\fR.
.BE
.SH DESCRIPTION
.PP
-These procedures are used to create, modify, and read
-double Tcl objects from C code.
-\fBTcl_NewDoubleObj\fR and \fBTcl_SetDoubleObj\fR
-will create a new object of double type
-or modify an existing object to have double type.
-Both of these procedures set the object to have the
-double-precision floating point value given by \fIdoubleValue\fR;
-\fBTcl_NewDoubleObj\fR returns a pointer to a newly created object
-with reference count zero.
-Both procedures set the object's type to be double
-and assign the double value to the object's internal representation
-\fIdoubleValue\fR member.
-\fBTcl_SetDoubleObj\fR invalidates any old string representation
-and, if the object is not already a double object,
-frees any old internal representation.
+These procedures are used to create, modify, and read Tcl objects that
+hold double-precision floating-point values.
.PP
-\fBTcl_GetDoubleFromObj\fR attempts to return a double value
-from the Tcl object \fIobjPtr\fR.
-If the object is not already a double object,
-it will attempt to convert it to one.
-If an error occurs during conversion, it returns \fBTCL_ERROR\fR
-and leaves an error message in the interpreter's result object
-unless \fIinterp\fR is NULL.
-Otherwise, it returns \fBTCL_OK\fR and stores the double value
-in the address given by \fIdoublePtr\fR.
-If the object is not already a double object,
-the conversion will free any old internal representation.
-
+\fBTcl_NewDoubleObj\fR creates and returns a new Tcl object initialized to
+the double value \fIdoubleValue\fR. The returned Tcl object is unshared.
+.PP
+\fBTcl_SetDoubleObj\fR sets the value of an existing Tcl object pointed to
+by \fIobjPtr\fR to the double value \fIdoubleValue\fR. The \fIobjPtr\fR
+argument must point to an unshared Tcl object. Any attempt to set the value
+of a shared Tcl object violates Tcl's copy-on-write policy. Any existing
+string representation or internal representation in the unshared Tcl object
+will be freed as a consequence of setting the new value.
+.PP
+\fBTcl_GetDoubleFromObj\fR attempts to retrieve a double value from the
+Tcl object \fIobjPtr\fR. If the attempt succeeds, then \fBTCL_OK\fR is
+returned, and the double value is written to the storage pointed to by
+\fIdoublePtr\fR. If the attempt fails, then \fBTCL_ERROR\fR is returned,
+and if \fIinterp\fR is non-NULL, an error message is left in \fIinterp\fR.
+The \fBTcl_ObjType\fR of \fIobjPtr\fR may be changed to make subsequent
+calls to \fBTcl_GetDoubleFromObj\fR more efficient.
+'\" TODO: add discussion of treatment of NaN value
.SH "SEE ALSO"
Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_GetObjResult
-
.SH KEYWORDS
double, double object, double type, internal representation, object, object type, string representation
diff --git a/doc/DumpActiveMemory.3 b/doc/DumpActiveMemory.3
index 6e00eb3..1f6cb46 100644
--- a/doc/DumpActiveMemory.3
+++ b/doc/DumpActiveMemory.3
@@ -7,7 +7,7 @@
.TH "Tcl_DumpActiveMemory" 3 8.1 Tcl "Tcl Library Procedures"
.BS
.SH NAME
-Tcl_DumpActiveMemory, Tcl_InitMemory, Tcl_ValidateAllMemory \- Validated memory allocation interface.
+Tcl_DumpActiveMemory, Tcl_InitMemory, Tcl_ValidateAllMemory \- Validated memory allocation interface
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -22,9 +22,10 @@ void
\fBTcl_ValidateAllMemory\fR(\fIfileName, line\fR)
.SH ARGUMENTS
+.AS Tcl_Interp *fileName
.AP Tcl_Interp *interp in
Tcl interpreter in which to add commands.
-.AP "CONST char" *fileName in
+.AP "const char" *fileName in
For \fBTcl_DumpActiveMemory\fR, name of the file to which memory
information will be written. For \fBTcl_ValidateAllMemory\fR, name of
the file from which the call is being made (normally \fB__FILE__\fR).
diff --git a/doc/Encoding.3 b/doc/Encoding.3
index 913d4fa..a940a5b 100644
--- a/doc/Encoding.3
+++ b/doc/Encoding.3
@@ -8,7 +8,7 @@
.TH Tcl_GetEncoding 3 "8.1" Tcl "Tcl Library Procedures"
.BS
.SH NAME
-Tcl_GetEncoding, Tcl_FreeEncoding, Tcl_ExternalToUtfDString, Tcl_ExternalToUtf, Tcl_UtfToExternalDString, Tcl_UtfToExternal, Tcl_WinTCharToUtf, Tcl_WinUtfToTChar, Tcl_GetEncodingName, Tcl_SetSystemEncoding, Tcl_GetEncodingNames, Tcl_CreateEncoding, Tcl_GetDefaultEncodingDir, Tcl_SetDefaultEncodingDir \- procedures for creating and using encodings.
+Tcl_GetEncoding, Tcl_FreeEncoding, Tcl_GetEncodingFromObj, Tcl_ExternalToUtfDString, Tcl_ExternalToUtf, Tcl_UtfToExternalDString, Tcl_UtfToExternal, Tcl_WinTCharToUtf, Tcl_WinUtfToTChar, Tcl_GetEncodingName, Tcl_SetSystemEncoding, Tcl_GetEncodingNameFromEnvironment, Tcl_GetEncodingNames, Tcl_CreateEncoding, Tcl_GetEncodingSearchPath, Tcl_SetEncodingSearchPath, Tcl_GetDefaultEncodingDir, Tcl_SetDefaultEncodingDir \- procedures for creating and using encodings
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -19,19 +19,24 @@ Tcl_Encoding
void
\fBTcl_FreeEncoding\fR(\fIencoding\fR)
.sp
+.VS 8.5
+int
+\fBTcl_GetEncodingFromObj\fR(\fIinterp, objPtr, encodingPtr\fR)
+.VE 8.5
+.sp
char *
\fBTcl_ExternalToUtfDString\fR(\fIencoding, src, srcLen, dstPtr\fR)
.sp
-int
-\fBTcl_ExternalToUtf\fR(\fIinterp, encoding, src, srcLen, flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr,
- dstCharsPtr\fR)
-.sp
-char *
+char *
\fBTcl_UtfToExternalDString\fR(\fIencoding, src, srcLen, dstPtr\fR)
.sp
int
-\fBTcl_UtfToExternal\fR(\fIinterp, encoding, src, srcLen, flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr,
- dstCharsPtr\fR)
+\fBTcl_ExternalToUtf\fR(\fIinterp, encoding, src, srcLen, flags, statePtr,
+ dst, dstLen, srcReadPtr, dstWrotePtr, dstCharsPtr\fR)
+.sp
+int
+\fBTcl_UtfToExternal\fR(\fIinterp, encoding, src, srcLen, flags, statePtr,
+ dst, dstLen, srcReadPtr, dstWrotePtr, dstCharsPtr\fR)
.sp
char *
\fBTcl_WinTCharToUtf\fR(\fItsrc, srcLen, dstPtr\fR)
@@ -39,41 +44,60 @@ char *
TCHAR *
\fBTcl_WinUtfToTChar\fR(\fIsrc, srcLen, dstPtr\fR)
.sp
-CONST char *
+const char *
\fBTcl_GetEncodingName\fR(\fIencoding\fR)
.sp
int
\fBTcl_SetSystemEncoding\fR(\fIinterp, name\fR)
.sp
+.VS 8.5
+const char *
+\fBTcl_GetEncodingNameFromEnvironment\fR(\fIbufPtr\fR)
+.VE 8.5
+.sp
void
\fBTcl_GetEncodingNames\fR(\fIinterp\fR)
.sp
Tcl_Encoding
\fBTcl_CreateEncoding\fR(\fItypePtr\fR)
.sp
-CONST char *
+.VS 8.5
+Tcl_Obj *
+\fBTcl_GetEncodingSearchPath\fR()
+.sp
+int
+\fBTcl_SetEncodingSearchPath\fR(\fIsearchPath\fR)
+.VE 8.5
+.sp
+const char *
\fBTcl_GetDefaultEncodingDir\fR(\fIvoid\fR)
.sp
void
\fBTcl_SetDefaultEncodingDir\fR(\fIpath\fR)
-
-
.SH ARGUMENTS
-.AS Tcl_EncodingState *dstWrotePtr
+.AS "const Tcl_EncodingType" *dstWrotePtr in/out
.AP Tcl_Interp *interp in
Interpreter to use for error reporting, or NULL if no error reporting is
desired.
-.AP "CONST char" *name in
+.AP "const char" *name in
Name of encoding to load.
.AP Tcl_Encoding encoding in
The encoding to query, free, or use for converting text. If \fIencoding\fR is
NULL, the current system encoding is used.
-.AP "CONST char" *src in
+.AP Tcl_Obj *objPtr in
+.VS 8.5
+Name of encoding to get token for.
+.VE 8.5
+.AP Tcl_Encoding *encodingPtr out
+.VS 8.5
+Points to storage where encoding token is to be written.
+.VE 8.5
+.AP "const char" *src in
For the \fBTcl_ExternalToUtf\fR functions, an array of bytes in the
specified encoding that are to be converted to UTF-8. For the
\fBTcl_UtfToExternal\fR and \fBTcl_WinUtfToTChar\fR functions, an array of
UTF-8 characters to be converted to the specified encoding.
-.AP "CONST TCHAR" *tsrc in
+.AP "const TCHAR" *tsrc in
An array of Windows TCHAR characters to convert to UTF-8.
.AP int srcLen in
Length of \fIsrc\fR or \fItsrc\fR in bytes. If the length is negative, the
@@ -83,21 +107,21 @@ Pointer to an uninitialized or free \fBTcl_DString\fR in which the converted
result will be stored.
.AP int flags in
Various flag bits OR-ed together.
-TCL_ENCODING_START signifies that the
+\fBTCL_ENCODING_START\fR signifies that the
source buffer is the first block in a (potentially multi-block) input
stream, telling the conversion routine to reset to an initial state and
perform any initialization that needs to occur before the first byte is
-converted. TCL_ENCODING_END signifies that the source buffer is the last
+converted. \fBTCL_ENCODING_END\fR signifies that the source buffer is the last
block in a (potentially multi-block) input stream, telling the conversion
routine to perform any finalization that needs to occur after the last
byte is converted and then to reset to an initial state.
-TCL_ENCODING_STOPONERROR signifies that the conversion routine should
-return immediately upon reading a source character that doesn't exist in
+\fBTCL_ENCODING_STOPONERROR\fR signifies that the conversion routine should
+return immediately upon reading a source character that does not exist in
the target encoding; otherwise a default fallback character will
automatically be substituted.
.AP Tcl_EncodingState *statePtr in/out
Used when converting a (generally long or indefinite length) byte stream
-in a piece by piece fashion. The conversion routine stores its current
+in a piece-by-piece fashion. The conversion routine stores its current
state in \fI*statePtr\fR after \fIsrc\fR (the buffer containing the
current piece) has been converted; that state information must be passed
back when converting the next piece of the stream so the conversion
@@ -120,9 +144,17 @@ buffer as a result of the conversion. May be NULL.
.AP int *dstCharsPtr out
Filled with the number of characters that correspond to the number of bytes
stored in the output buffer. May be NULL.
-.AP Tcl_EncodingType *typePtr in
+.AP Tcl_DString *bufPtr out
+.VS 8.5
+Storage for the prescribed system encoding name.
+.VE 8.5
+.AP "const Tcl_EncodingType" *typePtr in
Structure that defines a new type of encoding.
-.AP "CONST char" *path in
+.AP Tcl_Obj *searchPath in
+.VS 8.5
+List of filesystem directories in which to search for encoding data files.
+.VE 8.5
+.AP "const char" *path in
A path to the location of the encoding file.
.BE
.SH INTRODUCTION
@@ -149,7 +181,7 @@ platform-independent manner.
.SH DESCRIPTION
.PP
\fBTcl_GetEncoding\fR finds an encoding given its \fIname\fR. The name may
-refer to a builtin Tcl encoding, a user-defined encoding registered by
+refer to a built-in Tcl encoding, a user-defined encoding registered by
calling \fBTcl_CreateEncoding\fR, or a dynamically-loadable encoding
file. The return value is a token that represents the encoding and can be
used in subsequent calls to procedures such as \fBTcl_GetEncodingName\fR,
@@ -170,6 +202,20 @@ anywhere (i.e., it has been freed as many times as it has been gotten)
\fBTcl_FreeEncoding\fR will release all storage the encoding was using
and delete it from the database.
.PP
+.VS 8.5
+\fBTcl_GetEncodingFromObj\fR treats the string representation of
+\fIobjPtr\fR as an encoding name, and finds an encoding with that
+name, just as \fBTcl_GetEncoding\fR does. When an encoding is found,
+it is cached within the \fBobjPtr\fR value for future reference, the
+\fBTcl_Encoding\fR token is written to the storage pointed to by
+\fIencodingPtr\fR, and the value \fBTCL_OK\fR is returned. If no such
+encoding is found, the value \fBTCL_ERROR\fR is returned, and no
+writing to \fB*\fR\fIencodingPtr\fR takes place. Just as with
+\fBTcl_GetEncoding\fR, the caller should call \fBTcl_FreeEncoding\fR
+on the resulting encoding token when that token will no longer be
+used.
+.VE 8.5
+.PP
\fBTcl_ExternalToUtfDString\fR converts a source buffer \fIsrc\fR from the
specified \fIencoding\fR into UTF-8. The converted bytes are stored in
\fIdstPtr\fR, which is then null-terminated. The caller should eventually
@@ -192,7 +238,7 @@ All bytes of \fIsrc\fR were converted.
The destination buffer was not large enough for all of the converted data; as
many characters as could fit were converted though.
.IP \fBTCL_CONVERT_MULTIBYTE\fR 29
-The last fews bytes in the source buffer were the beginning of a multibyte
+The last few bytes in the source buffer were the beginning of a multibyte
sequence, but more bytes were needed to complete this sequence. A
subsequent call to the conversion routine should pass a buffer containing
the unconverted bytes that remained in \fIsrc\fR plus some further bytes
@@ -204,7 +250,7 @@ if the input stream has been damaged or if the input encoding method was
misidentified.
.IP \fBTCL_CONVERT_UNKNOWN\fR 29
The source buffer contained a character that could not be represented in
-the target encoding and TCL_ENCODING_STOPONERROR was specified.
+the target encoding and \fBTCL_ENCODING_STOPONERROR\fR was specified.
.RE
.LP
\fBTcl_UtfToExternalDString\fR converts a source buffer \fIsrc\fR from UTF-8
@@ -228,19 +274,26 @@ is filled with the corresponding number of bytes that were stored in
\fBTcl_WinUtfToTChar\fR and \fBTcl_WinTCharToUtf\fR are
Windows-only convenience
functions for converting between UTF-8 and Windows strings. On Windows 95
-(as with the Macintosh and Unix operating systems),
-all strings exchanged between Tcl and the operating system are "char"
+(as with the Unix operating system),
+all strings exchanged between Tcl and the operating system are
+.QW "char"
based. On Windows NT, some strings exchanged between Tcl and the
-operating system are "char" oriented while others are in Unicode. By
+operating system are
+.QW "char"
+oriented while others are in Unicode. By
convention, in Windows a TCHAR is a character in the ANSI code page
on Windows 95 and a Unicode character on Windows NT.
.PP
-If you planned to use the same "char" based interfaces on both Windows
+If you planned to use the same
+.QW "char"
+based interfaces on both Windows
95 and Windows NT, you could use \fBTcl_UtfToExternal\fR and
\fBTcl_ExternalToUtf\fR (or their \fBTcl_DString\fR equivalents) with an
encoding of NULL (the current system encoding). On the other hand,
if you planned to use the Unicode interface when running on Windows NT
-and the "char" interfaces when running on Windows 95, you would have
+and the
+.QW "char"
+interfaces when running on Windows 95, you would have
to perform the following type of test over and over in your program
(as represented in pseudo-code):
.CS
@@ -250,6 +303,7 @@ if (running NT) {
Tcl_FreeEncoding(encoding);
} else {
nativeBuffer <- Tcl_UtfToExternal(NULL, utfBuffer);
+}
.CE
\fBTcl_WinUtfToTChar\fR and \fBTcl_WinTCharToUtf\fR automatically
handle this test and use the proper encoding based on the current
@@ -269,11 +323,20 @@ was used to create the encoding. The string returned by
whenever the user passes a NULL value for the \fIencoding\fR argument to
any of the other encoding functions. If \fIname\fR is NULL, the system
encoding is reset to the default system encoding, \fBbinary\fR. If the
-name did not refer to any known or loadable encoding, TCL_ERROR is
+name did not refer to any known or loadable encoding, \fBTCL_ERROR\fR is
returned and an error message is left in \fIinterp\fR. Otherwise, this
procedure increments the reference count of the new system encoding,
decrements the reference count of the old system encoding, and returns
-TCL_OK.
+\fBTCL_OK\fR.
+.PP
+.VS 8.5
+\fBTcl_GetEncodingNameFromEnvironment\fR provides a means for the Tcl
+library to report the encoding name it believes to be the correct one
+to use as the system encoding, based on system calls and examination of
+the environment suitable for the platform. It accepts \fIbufPtr\fR,
+a pointer to an uninitialized or freed \fBTcl_DString\fR and writes
+the encoding name to it. The \fBTcl_DStringValue\fR is returned.
+.VE 8.5
.PP
\fBTcl_GetEncodingNames\fR sets the \fIinterp\fR result to a list
consisting of the names of all the encodings that are currently defined
@@ -301,12 +364,12 @@ convert between this encoding and UTF-8. It is defined as follows:
.PP
.CS
typedef struct Tcl_EncodingType {
- CONST char *\fIencodingName\fR;
- Tcl_EncodingConvertProc *\fItoUtfProc\fR;
- Tcl_EncodingConvertProc *\fIfromUtfProc\fR;
- Tcl_EncodingFreeProc *\fIfreeProc\fR;
- ClientData \fIclientData\fR;
- int \fInullSize\fR;
+ const char *\fIencodingName\fR;
+ Tcl_EncodingConvertProc *\fItoUtfProc\fR;
+ Tcl_EncodingConvertProc *\fIfromUtfProc\fR;
+ Tcl_EncodingFreeProc *\fIfreeProc\fR;
+ ClientData \fIclientData\fR;
+ int \fInullSize\fR;
} Tcl_EncodingType;
.CE
.PP
@@ -336,16 +399,16 @@ type \fBTcl_EncodingConvertProc\fR:
.PP
.CS
typedef int Tcl_EncodingConvertProc(
- ClientData \fIclientData\fR,
- CONST char *\fIsrc\fR,
- int \fIsrcLen\fR,
- int \fIflags\fR,
- Tcl_Encoding *\fIstatePtr\fR,
- char *\fIdst\fR,
- int \fIdstLen\fR,
- int *\fIsrcReadPtr\fR,
- int *\fIdstWrotePtr\fR,
- int *\fIdstCharsPtr\fR);
+ ClientData \fIclientData\fR,
+ const char *\fIsrc\fR,
+ int \fIsrcLen\fR,
+ int \fIflags\fR,
+ Tcl_EncodingState *\fIstatePtr\fR,
+ char *\fIdst\fR,
+ int \fIdstLen\fR,
+ int *\fIsrcReadPtr\fR,
+ int *\fIdstWrotePtr\fR,
+ int *\fIdstCharsPtr\fR);
.CE
.PP
The \fItoUtfProc\fR and \fIfromUtfProc\fR procedures are called by the
@@ -367,20 +430,42 @@ The callback procedure \fIfreeProc\fR, if non-NULL, should match the type
\fBTcl_EncodingFreeProc\fR:
.CS
typedef void Tcl_EncodingFreeProc(
- ClientData \fIclientData\fR);
+ ClientData \fIclientData\fR);
.CE
.PP
This \fIfreeProc\fR function is called when the encoding is deleted. The
\fIclientData\fR parameter is the same as the \fIclientData\fR field
specified to \fBTcl_CreateEncoding\fR when the encoding was created.
.PP
-
+.VS 8.5
+\fBTcl_GetEncodingSearchPath\fR and \fBTcl_SetEncodingSearchPath\fR
+are called to access and set the list of filesystem directories searched
+for encoding data files.
+.PP
+The value returned by \fBTcl_GetEncodingSearchPath\fR
+is the value stored by the last successful call to
+\fBTcl_SetEncodingSearchPath\fR. If no calls to
+\fBTcl_SetEncodingSearchPath\fR have occurred, Tcl will compute an initial
+value based on the environment. There is one encoding search path for the
+entire process, shared by all threads in the process.
+.PP
+\fBTcl_SetEncodingSearchPath\fR stores \fIsearchPath\fR and returns
+\fBTCL_OK\fR, unless \fIsearchPath\fR is not a valid Tcl list, which
+causes \fBTCL_ERROR\fR to be returned. The elements of \fIsearchPath\fR
+are not verified as existing readable filesystem directories. When
+searching for encoding data files takes place, and non-existent or
+non-readable filesystem directories on the \fIsearchPath\fR are silently
+ignored.
+.PP
\fBTcl_GetDefaultEncodingDir\fR and \fBTcl_SetDefaultEncodingDir\fR
-access and set the directory to use when locating the default encoding
-files. If this value is not NULL, the \fBTclpInitLibraryPath\fR routine
-appends the path to the head of the search path, and uses this path as
-the first place to look into when trying to locate the encoding file.
-
+are obsolete interfaces best replaced with calls to
+\fBTcl_GetEncodingSearchPath\fR and \fBTcl_SetEncodingSearchPath\fR.
+They are called to access and set the first element of the \fIsearchPath\fR
+list. Since Tcl searches \fIsearchPath\fR for encoding data files in
+list order, these routines establish the
+.QW default
+directory in which to find encoding data files.
+.VE 8.5
.SH "ENCODING FILES"
Space would prohibit precompiling into Tcl every possible encoding
algorithm, so many encodings are stored on disk as dynamically-loadable
@@ -392,23 +477,25 @@ external encoding may consist of single-byte, multi-byte, or double-byte
characters.
.PP
Each dynamically-loadable encoding is represented as a text file. The
-initial line of the file, beginning with a ``#'' symbol, is a comment
+initial line of the file, beginning with a
+.QW #
+symbol, is a comment
that provides a human-readable description of the file. The next line
identifies the type of encoding file. It can be one of the following
letters:
-.IP "[1] \fBS\fR"
+.IP "[1] \fBS\fR"
A single-byte encoding, where one character is always one byte long in the
encoding. An example is \fBiso8859-1\fR, used by many European languages.
-.IP "[2] \fBD\fR"
+.IP "[2] \fBD\fR"
A double-byte encoding, where one character is always two bytes long in the
encoding. An example is \fBbig5\fR, used for Chinese text.
-.IP "[3] \fBM\fR"
+.IP "[3] \fBM\fR"
A multi-byte encoding, where one character may be either one or two bytes long.
-Certain bytes are a lead bytes, indicating that another byte must follow
+Certain bytes are lead bytes, indicating that another byte must follow
and that together the two bytes represent one character. Other bytes are not
lead bytes and represent themselves. An example is \fBshiftjis\fR, used by
many Japanese computers.
-.IP "[4] \fBE\fR"
+.IP "[4] \fBE\fR"
An escape-sequence encoding, specifying that certain sequences of bytes
do not represent characters, but commands that describe how following bytes
should be interpreted.
@@ -478,7 +565,7 @@ and 0x8163 in \fBshiftjis\fR map to 203E and 2026 in Unicode, respectively.
Following the first page will be all the other pages, each in the same
format as the first: one number identifying the page followed by 256
double-byte Unicode characters. If a character in the encoding maps to the
-Unicode character 0000, it means that the character doesn't actually exist.
+Unicode character 0000, it means that the character does not actually exist.
If all characters on a page would map to 0000, that page can be omitted.
.PP
Case [4] is the escape-sequence encoding file. The lines in an this type of
@@ -490,13 +577,13 @@ encoding:
E
init {}
final {}
-iso8859-1 \\x1b(B
-jis0201 \\x1b(J
-jis0208 \\x1b$@
-jis0208 \\x1b$B
-jis0212 \\x1b$(D
-gb2312 \\x1b$A
-ksc5601 \\x1b$(C
+iso8859-1 \ex1b(B
+jis0201 \ex1b(J
+jis0208 \ex1b$@
+jis0208 \ex1b$B
+jis0212 \ex1b$(D
+gb2312 \ex1b$A
+ksc5601 \ex1b$(C
.CE
.PP
In the file, the first column represents an option and the second column
@@ -505,16 +592,16 @@ the first character is converted, while \fBfinal\fR is a string to emit
or expect after the last character. All other options are names of
table-based encodings; the associated value is the escape-sequence that
marks that encoding. Tcl syntax is used for the values; in the above
-example, for instance, ``\fB{}\fR'' represents the empty string and
-``\fB\\x1b\fR'' represents character 27.
+example, for instance,
+.QW \fB{}\fR
+represents the empty string and
+.QW \fB\ex1b\fR
+represents character 27.
.PP
When \fBTcl_GetEncoding\fR encounters an encoding \fIname\fR that has not
been loaded, it attempts to load an encoding file called \fIname\fB.enc\fR
-from the \fBencoding\fR subdirectory of each directory specified in the
-library path \fB$tcl_libPath\fR. If the encoding file exists, but is
+from the \fBencoding\fR subdirectory of each directory that Tcl searches
+for its script library. If the encoding file exists, but is
malformed, an error message will be left in \fIinterp\fR.
.SH KEYWORDS
utf, encoding, convert
-
-
-
diff --git a/doc/Ensemble.3 b/doc/Ensemble.3
new file mode 100644
index 0000000..5a5842d
--- /dev/null
+++ b/doc/Ensemble.3
@@ -0,0 +1,186 @@
+'\"
+'\" Copyright (c) 2005 Donal K. Fellows
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+'\" This documents the C API introduced in TIP#235
+'\"
+.so man.macros
+.TH Tcl_Ensemble 3 8.5 Tcl "Tcl Library Procedures"
+.BS
+.SH NAME
+Tcl_CreateEnsemble, Tcl_FindEnsemble, Tcl_GetEnsembleFlags, Tcl_GetEnsembleMappingDict, Tcl_GetEnsembleNamespace, Tcl_GetEnsembleUnknownHandler, Tcl_GetEnsembleSubcommandList, Tcl_IsEnsemble, Tcl_SetEnsembleFlags, Tcl_SetEnsembleMappingDict, Tcl_SetEnsembleSubcommandList, Tcl_SetEnsembleUnknownHandler \- manipulate ensemble commands
+.SH SYNOPSIS
+.nf
+\fB#include <tcl.h>\fR
+.sp
+Tcl_Command
+\fBTcl_CreateEnsemble\fR(\fIinterp, name, namespacePtr, ensFlags\fR)
+.sp
+Tcl_Command
+\fBTcl_FindEnsemble\fR(\fIinterp, cmdNameObj, flags\fR)
+.sp
+int
+\fBTcl_IsEnsemble\fR(\fItoken\fR)
+.sp
+int
+\fBTcl_GetEnsembleFlags\fR(\fIinterp, token, ensFlagsPtr\fR)
+.sp
+int
+\fBTcl_SetEnsembleFlags\fR(\fIinterp, token, ensFlags\fR)
+.sp
+int
+\fBTcl_GetEnsembleMappingDict\fR(\fIinterp, token, dictObjPtr\fR)
+.sp
+int
+\fBTcl_SetEnsembleMappingDict\fR(\fIinterp, token, dictObj\fR)
+.sp
+int
+\fBTcl_GetEnsembleSubcommandList\fR(\fIinterp, token, listObjPtr\fR)
+.sp
+int
+\fBTcl_SetEnsembleSubcommandList\fR(\fIinterp, token, listObj\fR)
+.sp
+int
+\fBTcl_GetEnsembleUnknownHandler\fR(\fIinterp, token, listObjPtr\fR)
+.sp
+int
+\fBTcl_SetEnsembleUnknownHandler\fR(\fIinterp, token, listObj\fR)
+.sp
+int
+\fBTcl_GetEnsembleNamespace\fR(\fIinterp, token, namespacePtrPtr\fR)
+.SH ARGUMENTS
+.AS Tcl_Namespace **namespacePtrPtr in/out
+.AP Tcl_Interp *interp in/out
+The interpreter in which the ensemble is to be created or found. Also
+where error result messages are written. The functions whose names
+start with \fBTcl_GetEnsemble\fR may have a NULL for the \fIinterp\fR,
+but all other functions must not.
+.AP "const char" *name in
+The name of the ensemble command to be created.
+.AP Tcl_Namespace *namespacePtr in
+The namespace to which the ensemble command is to be bound, or NULL
+for the current namespace.
+.AP int ensFlags in
+An ORed set of flag bits describing the basic configuration of the
+ensemble. Currently only one bit has meaning, TCL_ENSEMBLE_PREFIX,
+which is present when the ensemble command should also match
+unambiguous prefixes of subcommands.
+.AP Tcl_Obj *cmdNameObj in
+A value holding the name of the ensemble command to look up.
+.AP int flags in
+An ORed set of flag bits controlling the behavior of
+\fBTcl_FindEnsemble\fR. Currently only TCL_LEAVE_ERR_MSG is supported.
+.AP Tcl_Command token in
+A normal command token that refers to an ensemble command, or which
+you wish to use for testing as an ensemble command in \fBTcl_IsEnsemble\fR.
+.AP int *ensFlagsPtr out
+Pointer to a variable into which to write the current ensemble flag
+bits; currently only the bit TCL_ENSEMBLE_PREFIX is defined.
+.AP Tcl_Obj *dictObj in
+A dictionary value to use for the subcommand to implementation command
+prefix mapping dictionary in the ensemble. May be NULL if the mapping
+dictionary is to be removed.
+.AP Tcl_Obj **dictObjPtr out
+Pointer to a variable into which to write the current ensemble mapping
+dictionary.
+.AP Tcl_Obj *listObj in
+A list value to use for the defined list of subcommands in the
+dictionary or the unknown subcommmand handler command prefix. May be
+NULL if the subcommand list or unknown handler are to be removed.
+.AP Tcl_Obj **listObjPtr out
+Pointer to a variable into which to write the current defiend list of
+subcommands or the current unknown handler prefix.
+.AP Tcl_Namespace **namespacePtrPtr out
+Pointer to a variable into which to write the handle of the namespace
+to which the ensemble is bound.
+.BE
+
+.SH DESCRIPTION
+An ensemble is a command, bound to some namespace, which consists of a
+collection of subcommands implemented by other Tcl commands. The first
+argument to the ensemble command is always interpreted as a selector
+that states what subcommand to execute.
+.PP
+Ensembles are created using \fBTcl_CreateEnsemble\fR, which takes four
+arguments: the interpreter to work within, the name of the ensemble to
+create, the namespace within the interpreter to bind the ensemble to,
+and the default set of ensemble flags. The result of the function is
+the command token for the ensemble, which may be used to further
+configure the ensemble using the API described below in \fBENSEMBLE
+PROPERTIES\fR.
+.PP
+Given the name of an ensemble command, the token for that command may
+be retrieved using \fBTcl_FindEnsemble\fR. If the given command name
+(in \fIcmdNameObj\fR) does not refer to an ensemble command, the
+result of the function is NULL and (if the TCL_LEAVE_ERR_MSG bit is
+set in \fIflags\fR) an error message is left in the interpreter
+result.
+.PP
+A command token may be checked to see if it refers to an ensemble
+using \fBTcl_IsEnsemble\fR. This returns 1 if the token refers to an
+ensemble, or 0 otherwise.
+.SS "ENSEMBLE PROPERTIES"
+Every ensemble has four read-write properties and a read-only
+property. The properties are:
+.TP
+\fBflags\fR (read-write)
+The set of flags for the ensemble, expressed as a
+bit-field. Currently, the only public flag is TCL_ENSEMBLE_PREFIX
+which is set when unambiguous prefixes of subcommands are permitted to
+be resolved to implementations as well as exact matches. The flags may
+be read and written using \fBTcl_GetEnsembleFlags\fR and
+\fBTcl_SetEnsembleFlags\fR respectively. The result of both of those
+functions is a Tcl result code (TCL_OK, or TCL_ERROR if the token does
+not refer to an ensemble).
+.TP
+\fBmapping dictionary\fR (read-write)
+A dictionary containing a mapping from subcommand names to lists of
+words to use as a command prefix (replacing the first two words of the
+command which are the ensemble command itself and the subcommand
+name), or NULL if every subcommand is to be mapped to the command with
+the same unqualified name in the ensemble's bound namespace. Defaults
+to NULL. May be read and written using
+\fBTcl_GetEnsembleMappingDict\fR and \fBTcl_SetEnsembleMappingDict\fR
+respectively. The result of both of those functions is a Tcl result
+code (TCL_OK, or TCL_ERROR if the token does not refer to an
+ensemble) and the dictionary obtained from
+\fBTcl_GetEnsembleMappingDict\fR should always be treated as immutable
+even if it is unshared.
+.TP
+\fBsubcommand list\fR (read-write)
+A list of all the subcommand names for the ensemble, or NULL if this
+is to be derived from either the keys of the mapping dictionary (see
+above) or (if that is also NULL) from the set of commands exported by
+the bound namespace. May be read and written using
+\fBTcl_GetEnsembleSubcommandList\fR and
+\fBTcl_SetEnsembleSubcommandList\fR respectively. The result of both
+of those functions is a Tcl result code (TCL_OK, or TCL_ERROR if the
+token does not refer to an ensemble) and the list obtained from
+\fBTcl_GetEnsembleSubcommandList\fR should always be treated as
+immutable even if it is unshared.
+.TP
+\fBunknown subcommand handler command prefix\fR (read-write)
+A list of words to prepend on the front of any subcommand when the
+subcommand is unknown to the ensemble (according to the current prefix
+handling rule); see the \fBnamespace ensemble\fR command for more
+details. If NULL, the default behavior \- generate a suitable error
+message \- will be used when an unknown subcommand is encountered. May
+be read and written using \fBTcl_GetEnsembleUnknownHandler\fR and
+\fBTcl_SetEnsembleUnknownHandler\fR respectively. The result of both
+functions is a Tcl result code (TCL_OK, or TCL_ERROR if the token does
+not refer to an ensemble) and the list obtained from
+\fBTcl_GetEnsembleUnknownHandler\fR should always be treated as
+immutable even if it is unshared.
+.TP
+\fBbound namespace\fR (read-only)
+The namespace to which the ensemble is bound; when the namespace is
+deleted, so too will the ensemble, and this namespace is also the
+namespace whose list of exported commands is used if both the mapping
+dictionary and the subcommand list properties are NULL. May be read
+using \fBTcl_GetEnsembleNamespace\fR which returns a Tcl result code
+(TCL_OK, or TCL_ERROR if the token does not refer to an ensemble).
+
+.SH "SEE ALSO"
+namespace(n), Tcl_DeleteCommandFromToken(3)
diff --git a/doc/Environment.3 b/doc/Environment.3
index 7f92d48..3753f43 100644
--- a/doc/Environment.3
+++ b/doc/Environment.3
@@ -14,21 +14,25 @@ Tcl_PutEnv \- procedures to manipulate the environment
\fB#include <tcl.h>\fR
.sp
int
-\fBTcl_PutEnv\fR(\fIstring\fR)
+\fBTcl_PutEnv\fR(\fIassignment\fR)
.SH ARGUMENTS
-.AP "CONST char" *string in
-Info about environment variable in the form NAME=value.
-The \fIstring\fR argument is in the system encoding.
+.AS "const char" *assignment
+.AP "const char" *assignment in
+Info about environment variable in the format
+.QW \fINAME\fB=\fIvalue\fR .
+The \fIassignment\fR argument is in the system encoding.
.BE
-
.SH DESCRIPTION
.PP
\fBTcl_PutEnv\fR sets an environment variable. The information is
-passed in a single string of the form NAME=value. This procedure is
+passed in a single string of the form
+.QW \fINAME\fB=\fIvalue\fR .
+This procedure is
intended to be a stand-in for the UNIX \fBputenv\fR system call. All
-tcl-based applications using \fBputenv\fR should redefine it to
+Tcl-based applications using \fBputenv\fR should redefine it to
\fBTcl_PutEnv\fR so that they will interface properly to the Tcl
runtime.
-
+.SH "SEE ALSO"
+tclvars(n)
.SH KEYWORDS
environment, variable
diff --git a/doc/Eval.3 b/doc/Eval.3
index 1efe270..f232cad 100644
--- a/doc/Eval.3
+++ b/doc/Eval.3
@@ -15,7 +15,6 @@ Tcl_EvalObjEx, Tcl_EvalFile, Tcl_EvalObjv, Tcl_Eval, Tcl_EvalEx, Tcl_GlobalEval,
.nf
\fB#include <tcl.h>\fR
.sp
-.VS
int
\fBTcl_EvalObjEx\fR(\fIinterp, objPtr, flags\fR)
.sp
@@ -38,12 +37,12 @@ int
\fBTcl_GlobalEvalObj\fR(\fIinterp, objPtr\fR)
.sp
int
-\fBTcl_VarEval\fR(\fIinterp, string, string, ... \fB(char *) NULL\fR)
+\fBTcl_VarEval\fR(\fIinterp, part, part, ... \fB(char *) NULL\fR)
.sp
int
\fBTcl_VarEvalVA\fR(\fIinterp, argList\fR)
.SH ARGUMENTS
-.AS Tcl_Interp **termPtr;
+.AS Tcl_Interp **termPtr
.AP Tcl_Interp *interp in
Interpreter in which to execute the script. The interpreter's result is
modified to hold the result or error message from the script.
@@ -52,7 +51,7 @@ A Tcl object containing the script to execute.
.AP int flags in
ORed combination of flag bits that specify additional options.
\fBTCL_EVAL_GLOBAL\fR and \fBTCL_EVAL_DIRECT\fR are currently supported.
-.AP "CONST char" *fileName in
+.AP "const char" *fileName in
Name of a file containing a Tcl script.
.AP int objc in
The number of objects in the array pointed to by \fIobjPtr\fR;
@@ -64,13 +63,13 @@ value of a single word in the command to execute.
The number of bytes in \fIscript\fR, not including any
null terminating character. If \-1, then all characters up to the
first null byte are used.
-.AP "CONST char" *script in
+.AP "const char" *script in
Points to first byte of script to execute (null-terminated and UTF-8).
-.AP char *string in
+.AP char *part in
String forming part of a Tcl script.
.AP va_list argList in
-An argument list which must have been initialised using
-\fBTCL_VARARGS_START\fR, and cleared using \fBva_end\fR.
+An argument list which must have been initialized using
+\fBva_start\fR, and cleared using \fBva_end\fR.
.BE
.SH DESCRIPTION
@@ -97,26 +96,33 @@ result; it can be retrieved using \fBTcl_GetObjResult\fR.
\fBTcl_EvalFile\fR reads the file given by \fIfileName\fR and evaluates
its contents as a Tcl script. It returns the same information as
\fBTcl_EvalObjEx\fR.
-If the file couldn't be read then a Tcl error is returned to describe
-why the file couldn't be read.
-.VS 8.4
-The eofchar for files is '\\32' (^Z) for all platforms.
-If you require a ``^Z'' in code for string comparison, you can use
-``\\032'' or ``\\u001a'', which will be safely substituted by the Tcl
-interpreter into ``^Z''.
-.VE 8.4
+If the file could not be read then a Tcl error is returned to describe
+why the file could not be read.
+The eofchar for files is
+.QW \e32
+(^Z) for all platforms. If you require a
+.QW ^Z
+in code for string comparison, you can use
+.QW \e032
+or
+.QW \eu001a ,
+which will be safely substituted by the Tcl interpreter into
+.QW ^Z .
.PP
\fBTcl_EvalObjv\fR executes a single pre-parsed command instead of a
script. The \fIobjc\fR and \fIobjv\fR arguments contain the values
of the words for the Tcl command, one word in each object in
\fIobjv\fR. \fBTcl_EvalObjv\fR evaluates the command and returns
a completion code and result just like \fBTcl_EvalObjEx\fR.
+The caller of \fBTcl_EvalObjv\fR has to manage the reference count of the
+elements of \fIobjv\fR, insuring that the objects are valid until
+\fBTcl_EvalObjv\fR returns.
.PP
\fBTcl_Eval\fR is similar to \fBTcl_EvalObjEx\fR except that the script to
be executed is supplied as a string instead of an object and no compilation
occurs. The string should be a proper UTF-8 string as converted by
\fBTcl_ExternalToUtfDString\fR or \fBTcl_ExternalToUtf\fR when it is known
-to possibly contain upper ASCII characters who's possible combinations
+to possibly contain upper ASCII characters whose possible combinations
might be a UTF-8 special code. The string is parsed and executed directly
(using \fBTcl_EvalObjv\fR) instead of compiling it and executing the
bytecodes. In situations where it is known that the script will never be
@@ -126,7 +132,7 @@ executed again, \fBTcl_Eval\fR may be faster than \fBTcl_EvalObjEx\fR.
Tcl 8.0, \fBTcl_Eval\fR copies the object result in \fIinterp\fR to
\fIinterp->result\fR (use is deprecated) where it can be accessed directly.
This makes \fBTcl_Eval\fR somewhat slower than \fBTcl_EvalEx\fR, which
-doesn't do the copy.
+does not do the copy.
.PP
\fBTcl_EvalEx\fR is an extended version of \fBTcl_Eval\fR that takes
additional arguments \fInumBytes\fR and \fIflags\fR. For the
@@ -163,8 +169,8 @@ compiled to bytecodes; instead it is executed directly
as is done by \fBTcl_EvalEx\fR. The
\fBTCL_EVAL_DIRECT\fR flag is useful in situations where the
contents of an object are going to change immediately, so the
-bytecodes won't be reused in a future execution. In this case,
-it's faster to execute the script directly.
+bytecodes will not be reused in a future execution. In this case,
+it is faster to execute the script directly.
.TP 23
\fBTCL_EVAL_GLOBAL\fR
If this flag is set, the script is processed at global level. This
@@ -197,7 +203,6 @@ the \fBreturn\fR, \fBbreak\fR, or \fBcontinue\fR command was
invoked in an inappropriate place.
This means that top-level applications should never see a return code
from \fBTcl_EvalObjEx\fR other then \fBTCL_OK\fR or \fBTCL_ERROR\fR.
-.VE
.SH KEYWORDS
execute, file, global, object, result, script
diff --git a/doc/Exit.3 b/doc/Exit.3
index a281829..aa69b47 100644
--- a/doc/Exit.3
+++ b/doc/Exit.3
@@ -5,10 +5,10 @@
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
-.TH Tcl_Exit 3 8.1 Tcl "Tcl Library Procedures"
+.TH Tcl_Exit 3 8.5 Tcl "Tcl Library Procedures"
.BS
.SH NAME
-Tcl_Exit, Tcl_Finalize, Tcl_CreateExitHandler, Tcl_DeleteExitHandler, Tcl_ExitThread, Tcl_FinalizeThread, Tcl_CreateThreadExitHandler, Tcl_DeleteThreadExitHandler \- end the application or thread (and invoke exit handlers)
+Tcl_Exit, Tcl_Finalize, Tcl_CreateExitHandler, Tcl_DeleteExitHandler, Tcl_ExitThread, Tcl_FinalizeThread, Tcl_CreateThreadExitHandler, Tcl_DeleteThreadExitHandler, Tcl_SetExitProc \- end the application or thread (and invoke exit handlers)
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -28,6 +28,11 @@ Tcl_Exit, Tcl_Finalize, Tcl_CreateExitHandler, Tcl_DeleteExitHandler, Tcl_ExitTh
\fBTcl_CreateThreadExitHandler\fR(\fIproc, clientData\fR)
.sp
\fBTcl_DeleteThreadExitHandler\fR(\fIproc, clientData\fR)
+.sp
+.VS 8.5
+Tcl_ExitProc *
+\fBTcl_SetExitProc\fR(\fIproc\fR)
+.VE 8.5
.SH ARGUMENTS
.AS Tcl_ExitProc clientData
.AP int status in
@@ -36,7 +41,9 @@ Exact meaning may
be platform-specific. 0 usually means a normal exit, any nonzero value
usually means that an error occurred.
.AP Tcl_ExitProc *proc in
-Procedure to invoke before exiting application.
+Procedure to invoke before exiting application, or (for
+\fBTcl_SetExitProc\fR) NULL to uninstall the current application exit
+procedure.
.AP ClientData clientData in
Arbitrary one-word value to pass to \fIproc\fR.
.BE
@@ -57,6 +64,12 @@ otherwise causes the application to terminate without calling
\fBTcl_Exit\fR, the exit handlers will not be run.
\fBTcl_Exit\fR internally invokes the \fBexit\fR system call, thus it never
returns control to its caller.
+.VS 8.5
+If an application exit handler has been installed (see
+\fBTcl_SetExitProc\fR), that handler is invoked with an argument
+consisting of the exit status (cast to ClientData); the application
+exit handler should not return control to Tcl.
+.VE 8.5
.PP
\fBTcl_Finalize\fR is similar to \fBTcl_Exit\fR except that it does not
exit from the current process.
@@ -71,14 +84,12 @@ However, to ensure portability, your code should always invoke
code will work on all platforms. \fBTcl_Finalize\fR can be safely called
more than once.
.PP
-.VS
\fBTcl_ExitThread\fR is used to terminate the current thread and invoke
per-thread exit handlers. This finalization is done by
\fBTcl_FinalizeThread\fR, which you can call if you just want to clean
up per-thread state and invoke the thread exit handlers.
\fBTcl_Finalize\fR calls \fBTcl_FinalizeThread\fR for the current
thread automatically.
-.VE
.PP
\fBTcl_CreateExitHandler\fR arranges for \fIproc\fR to be invoked
by \fBTcl_Finalize\fR and \fBTcl_Exit\fR.
@@ -105,7 +116,6 @@ indicated by \fIproc\fR and \fIclientData\fR so that no call
to \fIproc\fR will be made. If no such handler exists then
\fBTcl_DeleteExitHandler\fR or \fBTcl_DeleteThreadExitHandler\fR does nothing.
.PP
-.VS
.PP
\fBTcl_Finalize\fR and \fBTcl_Exit\fR execute all registered exit handlers,
in reverse order from the order in which they were registered.
@@ -115,15 +125,23 @@ unloads \fBB\fR before it itself is unloaded.
If extension \fBA\fR registers its exit handlers before loading extension
\fBB\fR, this ensures that any exit handlers for \fBB\fR will be executed
before the exit handlers for \fBA\fR.
-.VE
-.VS
.PP
\fBTcl_Finalize\fR and \fBTcl_Exit\fR call \fBTcl_FinalizeThread\fR
and the thread exit handlers \fIafter\fR
the process-wide exit handlers. This is because thread finalization shuts
down the I/O channel system, so any attempt at I/O by the global exit
handlers will vanish into the bitbucket.
-.VE
+.PP
+.VS 8.5
+\fBTcl_SetExitProc\fR installs an application exit handler, returning
+the previously-installed application exit handler or NULL if no
+application handler was installed. If an application exit handler is
+installed, that exit handler takes over complete responsibility for
+finalization of Tcl's subsystems via \fBTcl_Finalize\fR at an
+appropriate time. The argument passed to \fIproc\fR when it is
+invoked will be the exit status code (as passed to \fBTcl_Exit\fR)
+cast to a ClientData value.
+.VE 8.5
.SH KEYWORDS
callback, cleanup, dynamic loading, end application, exit, unloading, thread
diff --git a/doc/ExprLong.3 b/doc/ExprLong.3
index ead98f5..ef93284 100644
--- a/doc/ExprLong.3
+++ b/doc/ExprLong.3
@@ -15,23 +15,21 @@ Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean, Tcl_ExprString \- evaluate an exp
\fB#include <tcl.h>\fR
.sp
int
-\fBTcl_ExprLong\fR(\fIinterp, string, longPtr\fR)
+\fBTcl_ExprLong\fR(\fIinterp, expr, longPtr\fR)
.sp
int
-\fBTcl_ExprDouble\fR(\fIinterp, string, doublePtr\fR)
+\fBTcl_ExprDouble\fR(\fIinterp, expr, doublePtr\fR)
.sp
int
-\fBTcl_ExprBoolean\fR(\fIinterp, string, booleanPtr\fR)
+\fBTcl_ExprBoolean\fR(\fIinterp, expr, booleanPtr\fR)
.sp
int
-\fBTcl_ExprString\fR(\fIinterp, string\fR)
+\fBTcl_ExprString\fR(\fIinterp, expr\fR)
.SH ARGUMENTS
-.AS Tcl_Interp *booleanPtr
+.AS Tcl_Interp *booleanPtr out
.AP Tcl_Interp *interp in
-Interpreter in whose context to evaluate \fIstring\fR.
-.VS 8.4
-.AP "CONST char" *string in
-.VE
+Interpreter in whose context to evaluate \fIexpr\fR.
+.AP "const char" *expr in
Expression to be evaluated.
.AP long *longPtr out
Pointer to location in which to store the integer value of the
@@ -47,7 +45,7 @@ expression.
.SH DESCRIPTION
.PP
These four procedures all evaluate the expression
-given by the \fIstring\fR argument
+given by the \fIexpr\fR argument
and return the result in one of four different forms.
The expression can have any of the forms accepted by the \fBexpr\fR command.
Note that these procedures have been largely replaced by the
@@ -92,7 +90,11 @@ number, then they store 0 at \fI*booleanPtr\fR if
the value was zero and 1 otherwise.
If the expression's actual value is a non-numeric string then
it must be one of the values accepted by \fBTcl_GetBoolean\fR
-such as ``yes'' or ``no'', or else an error occurs.
+such as
+.QW yes
+or
+.QW no ,
+or else an error occurs.
.PP
\fBTcl_ExprString\fR returns the value of the expression as a
string stored in the interpreter's result.
diff --git a/doc/ExprLongObj.3 b/doc/ExprLongObj.3
index c3e9697..c8a564d 100644
--- a/doc/ExprLongObj.3
+++ b/doc/ExprLongObj.3
@@ -86,7 +86,11 @@ number, then they store 0 at \fI*booleanPtr\fR if
the value was zero and 1 otherwise.
If the expression's actual value is a non-numeric string then
it must be one of the values accepted by \fBTcl_GetBoolean\fR
-such as ``yes'' or ``no'', or else an error occurs.
+such as
+.QW yes
+or
+.QW no ,
+or else an error occurs.
.PP
If \fBTcl_ExprObj\fR successfully evaluates the expression,
it stores a pointer to the Tcl object
diff --git a/doc/FileSystem.3 b/doc/FileSystem.3
index 7475989..32407d8 100644
--- a/doc/FileSystem.3
+++ b/doc/FileSystem.3
@@ -8,7 +8,7 @@
.TH Filesystem 3 8.4 Tcl "Tcl Library Procedures"
.BS
.SH NAME
-Tcl_FSRegister, Tcl_FSUnregister, Tcl_FSData, Tcl_FSMountsChanged, Tcl_FSGetFileSystemForPath, Tcl_FSGetPathType, Tcl_FSCopyFile, Tcl_FSCopyDirectory, Tcl_FSCreateDirectory, Tcl_FSDeleteFile, Tcl_FSRemoveDirectory, Tcl_FSRenameFile, Tcl_FSListVolumes, Tcl_FSEvalFile, Tcl_FSLoadFile, Tcl_FSMatchInDirectory, Tcl_FSLink, Tcl_FSLstat, Tcl_FSUtime, Tcl_FSFileAttrsGet, Tcl_FSFileAttrsSet, Tcl_FSFileAttrStrings, Tcl_FSStat, Tcl_FSAccess, Tcl_FSOpenFileChannel, Tcl_FSGetCwd, Tcl_FSChdir, Tcl_FSPathSeparator, Tcl_FSJoinPath, Tcl_FSSplitPath, Tcl_FSEqualPaths, Tcl_FSGetNormalizedPath, Tcl_FSJoinToPath, Tcl_FSConvertToPathType, Tcl_FSGetInternalRep, Tcl_FSGetTranslatedPath, Tcl_FSGetTranslatedStringPath, Tcl_FSNewNativePath, Tcl_FSGetNativePath, Tcl_FSFileSystemInfo, Tcl_AllocStatBuf \- procedures to interact with any filesystem
+Tcl_FSRegister, Tcl_FSUnregister, Tcl_FSData, Tcl_FSMountsChanged, Tcl_FSGetFileSystemForPath, Tcl_FSGetPathType, Tcl_FSCopyFile, Tcl_FSCopyDirectory, Tcl_FSCreateDirectory, Tcl_FSDeleteFile, Tcl_FSRemoveDirectory, Tcl_FSRenameFile, Tcl_FSListVolumes, Tcl_FSEvalFile, Tcl_FSEvalFileEx, Tcl_FSLoadFile, Tcl_FSMatchInDirectory, Tcl_FSLink, Tcl_FSLstat, Tcl_FSUtime, Tcl_FSFileAttrsGet, Tcl_FSFileAttrsSet, Tcl_FSFileAttrStrings, Tcl_FSStat, Tcl_FSAccess, Tcl_FSOpenFileChannel, Tcl_FSGetCwd, Tcl_FSChdir, Tcl_FSPathSeparator, Tcl_FSJoinPath, Tcl_FSSplitPath, Tcl_FSEqualPaths, Tcl_FSGetNormalizedPath, Tcl_FSJoinToPath, Tcl_FSConvertToPathType, Tcl_FSGetInternalRep, Tcl_FSGetTranslatedPath, Tcl_FSGetTranslatedStringPath, Tcl_FSNewNativePath, Tcl_FSGetNativePath, Tcl_FSFileSystemInfo, Tcl_AllocStatBuf \- procedures to interact with any filesystem
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -26,10 +26,10 @@ void
\fBTcl_FSMountsChanged\fR(\fIfsPtr\fR)
.sp
Tcl_Filesystem*
-\fBTcl_FSGetFileSystemForPath\fR(\fIpathObjPtr\fR)
+\fBTcl_FSGetFileSystemForPath\fR(\fIpathPtr\fR)
.sp
Tcl_PathType
-\fBTcl_FSGetPathType\fR(\fIpathObjPtr\fR)
+\fBTcl_FSGetPathType\fR(\fIpathPtr\fR)
.sp
int
\fBTcl_FSCopyFile\fR(\fIsrcPathPtr, destPathPtr\fR)
@@ -52,6 +52,11 @@ int
Tcl_Obj*
\fBTcl_FSListVolumes\fR(\fIvoid\fR)
.sp
+.VS 8.5
+int
+\fBTcl_FSEvalFileEx\fR(\fIinterp, pathPtr, encodingName\fR)
+.VE 8.5
+.sp
int
\fBTcl_FSEvalFile\fR(\fIinterp, pathPtr\fR)
.sp
@@ -60,7 +65,7 @@ int
handlePtr, unloadProcPtr\fR)
.sp
int
-\fBTcl_FSMatchInDirectory\fR(\fIinterp, result, pathPtr, pattern, types\fR)
+\fBTcl_FSMatchInDirectory\fR(\fIinterp, resultPtr, pathPtr, pattern, types\fR)
.sp
Tcl_Obj*
\fBTcl_FSLink\fR(\fIlinkNamePtr, toPtr, linkAction\fR)
@@ -77,7 +82,7 @@ int
int
\fBTcl_FSFileAttrsSet\fR(\fIinterp, int index, pathPtr, Tcl_Obj *objPtr\fR)
.sp
-CONST char**
+const char**
\fBTcl_FSFileAttrStrings\fR(\fIpathPtr, objPtrRef\fR)
.sp
int
@@ -86,7 +91,7 @@ int
int
\fBTcl_FSAccess\fR(\fIpathPtr, mode\fR)
.sp
-Tcl_Channel
+Tcl_Channel
\fBTcl_FSOpenFileChannel\fR(\fIinterp, pathPtr, modeString, permissions\fR)
.sp
Tcl_Obj*
@@ -116,19 +121,19 @@ Tcl_Obj*
int
\fBTcl_FSConvertToPathType\fR(\fIinterp, pathPtr\fR)
.sp
-ClientData
+ClientData
\fBTcl_FSGetInternalRep\fR(\fIpathPtr, fsPtr\fR)
.sp
-Tcl_Obj*
+Tcl_Obj *
\fBTcl_FSGetTranslatedPath\fR(\fIinterp, pathPtr\fR)
.sp
-CONST char*
+const char *
\fBTcl_FSGetTranslatedStringPath\fR(\fIinterp, pathPtr\fR)
.sp
Tcl_Obj*
\fBTcl_FSNewNativePath\fR(\fIfsPtr, clientData\fR)
.sp
-CONST char*
+const char *
\fBTcl_FSGetNativePath\fR(\fIpathPtr\fR)
.sp
Tcl_Obj*
@@ -137,7 +142,7 @@ Tcl_Obj*
Tcl_StatBuf*
\fBTcl_AllocStatBuf\fR()
.SH ARGUMENTS
-.AS Tcl_Filesystem *fsPtr in
+.AS Tcl_FSUnloadFileProc **unloadProcPtr out
.AP Tcl_Filesystem *fsPtr in
Points to a structure containing the addresses of procedures that
can be called to perform the various filesystem operations.
@@ -146,21 +151,21 @@ The path represented by this object is used for the operation in
question. If the object does not already have an internal \fBpath\fR
representation, it will be converted to have one.
.AP Tcl_Obj *srcPathPtr in
-As for \fBpathPtr\fR, but used for the source file for a copy or
+As for \fIpathPtr\fR, but used for the source file for a copy or
rename operation.
.AP Tcl_Obj *destPathPtr in
-As for \fBpathPtr\fR, but used for the destination filename for a copy or
+As for \fIpathPtr\fR, but used for the destination filename for a copy or
rename operation.
-.AP "CONST char" *pattern in
-Only files or directories matching this pattern will be returned by
-\fBTcl_FSMatchInDirectory\fR.
-.AP GlobTypeData *types in
+.AP "const char" *encodingName in
+The encoding of the data stored in the
+file identified by \fIpathPtr\fR and to be evaluated.
+.AP "const char" *pattern in
+Only files or directories matching this pattern will be returned.
+.AP Tcl_GlobTypeData *types in
Only files or directories matching the type descriptions contained in
-this structure will be returned by \fBTcl_FSMatchInDirectory\fR. It
-is very important that the 'directory' flag is properly handled.
-This parameter may be NULL.
+this structure will be returned. This parameter may be NULL.
.AP Tcl_Interp *interp in
-Interpreter to use either for results, evaluation, or reporting error
+Interpreter to use either for results, evaluation, or reporting error
messages.
.AP ClientData clientData in
The native description of the path object to create.
@@ -173,17 +178,17 @@ to \fBpath\fR type.
.AP Tcl_Obj *listObj in
The list of path elements to operate on with a \fBjoin\fR operation.
.AP int elements in
-If non-negative, the number of elements in the listObj which should
+If non-negative, the number of elements in the \fIlistObj\fR which should
be joined together. If negative, then all elements are joined.
.AP Tcl_Obj **errorPtr out
In the case of an error, filled with an object containing the name of
the file which caused an error in the various copy/rename operations.
.AP Tcl_Obj **objPtrRef out
Filled with an object containing the result of the operation.
-.AP Tcl_Obj *result out
-Pre-allocated object in which to store (by lappending) the list of
-files or directories which are successfully matched in
-\fBTcl_FSMatchInDirectory\fR.
+.AP Tcl_Obj *resultPtr out
+Pre-allocated object in which to store (using
+\fBTcl_ListObjAppendElement\fR) the list of
+files or directories which are successfully matched.
.AP int mode in
Mask consisting of one or more of R_OK, W_OK, X_OK and F_OK. R_OK,
W_OK and X_OK request checking whether the file exists and has read,
@@ -191,25 +196,25 @@ write and execute permissions, respectively. F_OK just requests
checking for the existence of the file.
.AP Tcl_StatBuf *statPtr out
The structure that contains the result of a stat or lstat operation.
-.AP "CONST char" *sym1 in
+.AP "const char" *sym1 in
Name of a procedure to look up in the file's symbol table
-.AP "CONST char" *sym2 in
+.AP "const char" *sym2 in
Name of a procedure to look up in the file's symbol table
.AP Tcl_PackageInitProc **proc1Ptr out
Filled with the init function for this code.
.AP Tcl_PackageInitProc **proc2Ptr out
Filled with the safe-init function for this code.
-.AP Tcl_LoadHandle *handlePtr out
-Filled with an abstract token representing the loaded file.
.AP ClientData *clientDataPtr out
Filled with the clientData value to pass to this code's unload
function when it is called.
-.AP TclfsUnloadFileProc_ **unloadProcPtr out
+.AP Tcl_LoadHandle *handlePtr out
+Filled with an abstract token representing the loaded file.
+.AP Tcl_FSUnloadFileProc **unloadProcPtr out
Filled with the function to use to unload this piece of code.
.AP utimbuf *tval in
-The access and modification times in this structure are read and
+The access and modification times in this structure are read and
used to set those values for a given file.
-.AP "CONST char" *modeString in
+.AP "const char" *modeString in
Specifies how the file is to be accessed. May have any of the values
allowed for the \fImode\fR argument to the Tcl \fBopen\fR command.
.AP int permissions in
@@ -221,151 +226,215 @@ If non-NULL, filled with the number of elements in the split path.
The base path on to which to join the given elements. May be NULL.
.AP int objc in
The number of elements in \fIobjv\fR.
-.AP "Tcl_Obj *CONST" objv[] in
+.AP "Tcl_Obj *const" objv[] in
The elements to join to the given base path.
+.AP Tcl_Obj *linkNamePtr in
+The name of the link to be created or read.
+.AP Tcl_Obj *toPtr in
+What the link called \fIlinkNamePtr\fR should be linked to, or NULL if
+the symbolic link specified by \fIlinkNamePtr\fR is to be read.
+.AP int linkAction in
+OR-ed combination of flags indicating what kind of link should be
+created (will be ignored if \fItoPtr\fR is NULL). Valid bits to set
+are \fBTCL_CREATE_SYMBOLIC_LINK\fR and \fBTCL_CREATE_HARD_LINK\fR.
+When both flags are set and the underlying filesystem can do either,
+symbolic links are preferred.
.BE
.SH DESCRIPTION
.PP
-There are several reasons for calling the \fBTcl_FS...\fR functions
+There are several reasons for calling the \fBTcl_FS\fR API functions
+(e.g. \fBTcl_FSAccess\fR and \fBTcl_FSStat\fR)
rather than calling system level functions like \fBaccess\fR and
\fBstat\fR directly. First, they will work cross-platform, so an
-extension which calls them should work unmodified on Unix, MacOS and
+extension which calls them should work unmodified on Unix and
Windows. Second, the Windows implementation of some of these functions
fixes some bugs in the system level calls. Third, these function calls
-deal with any 'Utf to platform-native' path conversions which may be
+deal with any
+.QW "Utf to platform-native"
+path conversions which may be
required (and may cache the results of such conversions for greater
efficiency on subsequent calls). Fourth, and perhaps most importantly,
-all of these functions are 'virtual filesystem aware'. Any virtual
-filesystem which has been registered (through
+all of these functions are
+.QW "virtual filesystem aware" .
+Any virtual filesystem (VFS for short) which has been registered (through
\fBTcl_FSRegister\fR) may reroute file access to alternative
media or access methods. This means that all of these functions (and
therefore the corresponding \fBfile\fR, \fBglob\fR, \fBpwd\fR, \fBcd\fR,
-\fBopen\fR, etc. Tcl commands) may be operate on 'files' which are not
+\fBopen\fR, etc. Tcl commands) may be operate on
+.QW files
+which are not
native files in the native filesystem. This also means that any Tcl
-extension which accesses the filesystem through this API is
-automatically 'virtual filesystem aware'. Of course, if an extension
+extension which accesses the filesystem (FS for short) through this API is
+automatically
+.QW "virtual filesystem aware" .
+Of course, if an extension
accesses the native filesystem directly (through platform-specific
-APIs, for example), then Tcl cannot intercept such calls.
+APIs, for example), then Tcl cannot intercept such calls.
.PP
-If appropriate vfs's have been registered, the 'files' may, to give two
+If appropriate VFSes have been registered, the
+.QW files
+may, to give two
examples, be remote (e.g. situated on a remote ftp server) or archived
(e.g. lying inside a .zip archive). Such registered filesystems provide
a lookup table of functions to implement all or some of the functionality
listed here. Finally, the \fBTcl_FSStat\fR and \fBTcl_FSLstat\fR calls
-abstract away from what the 'struct stat' buffer buffer is actually
+abstract away from what the
+.QW "struct stat"
+buffer is actually
declared to be, allowing the same code to be used both on systems with
and systems without support for files larger than 2GB in size.
.PP
-The \fBTcl_FS...\fR are objectified and may cache internal
+The \fBTcl_FS\fR API is objectified and may cache internal
representations and other path-related strings (e.g. the current working
directory). One side-effect of this is that one must not pass in objects
-with a refCount of zero to any of these functions. If such calls were
+with a reference count of zero to any of these functions. If such calls were
handled, they might result
in memory leaks (under some circumstances, the filesystem code may wish
to retain a reference to the passed in object, and so one must not assume
-that after any of these calls return, the object still has a refCount of
-zero - it may have been incremented), or in a direct segfault
+that after any of these calls return, the object still has a reference count of
+zero - it may have been incremented) or in a direct segmentation fault
+(or other memory access error)
due to the object being freed part way through the complex object
manipulation required to ensure that the path is fully normalized and
absolute for filesystem determination. The practical lesson to learn
-from this is that \fBTcl_Obj *path = Tcl_NewStringObj(...) ;
-Tcl_FS...(path) ; Tcl_DecrRefCount(path)\fR is wrong, and may segfault.
-The 'path' must have its refCount incremented before passing it in, or
-decrementing it. For this reason, objects with a refCount of zero are
+from this is that
+.CS
+Tcl_Obj *path = Tcl_NewStringObj(...);
+Tcl_FS\fIWhatever\fR(path);
+Tcl_DecrRefCount(path);
+.CE
+is wrong, and may cause memory errors. The \fIpath\fR must have its
+reference count incremented before passing it in, or
+decrementing it. For this reason, objects with a reference count of zero are
considered not to be valid filesystem paths and calling any Tcl_FS API
-with such an object will result in no action being taken.
-.PP
-\fBTcl_FSCopyFile\fR attempts to copy the file given by srcPathPtr to the
-path name given by destPathPtr. If the two paths given lie in the same
+function with such an object will result in no action being taken.
+.SS "FS API FUNCTIONS"
+\fBTcl_FSCopyFile\fR attempts to copy the file given by \fIsrcPathPtr\fR to the
+path name given by \fIdestPathPtr\fR. If the two paths given lie in the same
filesystem (according to \fBTcl_FSGetFileSystemForPath\fR) then that
-filesystem's 'copy file' function is called (if it is non-NULL).
-Otherwise the function returns -1 and sets Tcl's errno to the 'EXDEV'
-posix error code (which signifies a 'cross-domain link').
-.PP
-\fBTcl_FSCopyDirectory\fR attempts to copy the directory given by srcPathPtr to the
-path name given by destPathPtr. If the two paths given lie in the same
+filesystem's
+.QW "copy file"
+function is called (if it is non-NULL).
+Otherwise the function returns -1 and sets the \fBerrno\fR global C
+variable to the
+.QW EXDEV
+POSIX error code (which signifies a
+.QW "cross-domain link" ).
+.PP
+\fBTcl_FSCopyDirectory\fR attempts to copy the directory given by \fIsrcPathPtr\fR to the
+path name given by \fIdestPathPtr\fR. If the two paths given lie in the same
filesystem (according to \fBTcl_FSGetFileSystemForPath\fR) then that
-filesystem's 'copy file' function is called (if it is non-NULL).
-Otherwise the function returns -1 and sets Tcl's errno to the 'EXDEV'
-posix error code (which signifies a 'cross-domain link').
+filesystem's
+.QW "copy file"
+function is called (if it is non-NULL).
+Otherwise the function returns -1 and sets the \fBerrno\fR global C
+variable to the
+.QW EXDEV
+POSIX error code (which signifies a
+.QW "cross-domain link" ).
.PP
\fBTcl_FSCreateDirectory\fR attempts to create the directory given by
-pathPtr by calling the owning filesystem's 'create directory'
+\fIpathPtr\fR by calling the owning filesystem's
+.QW "create directory"
function.
.PP
\fBTcl_FSDeleteFile\fR attempts to delete the file given by
-pathPtr by calling the owning filesystem's 'delete file'
+\fIpathPtr\fR by calling the owning filesystem's
+.QW "delete file"
function.
.PP
\fBTcl_FSRemoveDirectory\fR attempts to remove the directory given by
-pathPtr by calling the owning filesystem's 'remove directory'
+\fIpathPtr\fR by calling the owning filesystem's
+.QW "remove directory"
function.
.PP
\fBTcl_FSRenameFile\fR attempts to rename the file or directory given by
-srcPathPtr to the path name given by destPathPtr. If the two paths
+\fIsrcPathPtr\fR to the path name given by \fIdestPathPtr\fR. If the two paths
given lie in the same filesystem (according to
-\fBTcl_FSGetFileSystemForPath\fR) then that filesystem's 'rename file'
+\fBTcl_FSGetFileSystemForPath\fR) then that filesystem's
+.QW "rename file"
function is called (if it is non-NULL). Otherwise the function returns -1
-and sets Tcl's errno to the 'EXDEV' posix error code (which signifies
-a ``cross-domain link'').
-.PP
-\fBTcl_FSListVolumes\fR calls each filesystem which has a non-NULL 'list
-volumes' function and asks them to return their list of root volumes. It
+and sets the \fBerrno\fR global C variable to the
+.QW EXDEV
+POSIX error code (which signifies a
+.QW "cross-domain link" ).
+.PP
+\fBTcl_FSListVolumes\fR calls each filesystem which has a non-NULL
+.QW "list volumes"
+function and asks them to return their list of root volumes. It
accumulates the return values in a list which is returned to the
-caller (with a refCount of 0).
+caller (with a reference count of 0).
.PP
-\fBTcl_FSEvalFile\fR reads the file given by \fIpathPtr\fR and evaluates
+.VS 8.5
+\fBTcl_FSEvalFileEx\fR reads the file given by \fIpathPtr\fR using
+the encoding identified by \fIencodingName\fR and evaluates
its contents as a Tcl script. It returns the same information as
\fBTcl_EvalObjEx\fR.
-If the file couldn't be read then a Tcl error is returned to describe
-why the file couldn't be read.
-The eofchar for files is '\\32' (^Z) for all platforms.
-If you require a ``^Z'' in code for string comparison, you can use
-``\\032'' or ``\\u001a'', which will be safely substituted by the Tcl
-interpreter into ``^Z''.
+If \fIencodingName\fR is NULL, the system encoding is used for
+reading the file contents.
+If the file could not be read then a Tcl error is returned to describe
+why the file could not be read.
+The eofchar for files is
+.QW \e32
+(^Z) for all platforms.
+If you require a
+.QW ^Z
+in code for string comparison, you can use
+.QW \e032
+or
+.QW \eu001a ,
+which will be safely substituted by the Tcl interpreter into
+.QW ^Z .
+\fBTcl_FSEvalFile\fR is a simpler version of
+\fBTcl_FSEvalFileEx\fR that always uses the system encoding
+when reading the file.
+.VE 8.5
.PP
\fBTcl_FSLoadFile\fR dynamically loads a binary code file into memory and
returns the addresses of two procedures within that file, if they are
-defined. The appropriate function for the filesystem to which pathPtr
+defined. The appropriate function for the filesystem to which \fIpathPtr\fR
belongs will be called. If that filesystem does not implement this
function (most virtual filesystems will not, because of OS limitations
in dynamically loading binary code), Tcl will attempt to copy the file
to a temporary directory and load that temporary file.
.PP
Returns a standard Tcl completion code. If an error occurs, an error
-message is left in the interp's result.
+message is left in the \fIinterp\fR's result.
.PP
\fBTcl_FSMatchInDirectory\fR is used by the globbing code to search a
directory for all files which match a given pattern. The appropriate
-function for the filesystem to which pathPtr belongs will be called.
+function for the filesystem to which \fIpathPtr\fR belongs will be called.
.PP
The return value is a standard Tcl result indicating whether an error
-occurred in globbing. Error messages are placed in interp, but good
-results are placed in the resultPtr given.
-
-Note that the 'glob' code implements recursive patterns internally, so
+occurred in globbing. Error messages are placed in interp (unless
+interp is NULL, which is allowed), but good results are placed in the
+resultPtr given.
+.PP
+Note that the \fBglob\fR code implements recursive patterns internally, so
this function will only ever be passed simple patterns, which can be
-matched using the logic of 'string match'. To handle recursion, Tcl
+matched using the logic of \fBstring match\fR. To handle recursion, Tcl
will call this function frequently asking only for directories to be
-returned.
+returned. A special case of being called with a NULL pattern indicates
+that the path needs to be checked only for the correct type.
.PP
-\fBTcl_FSLink\fR replaces the library version of readlink(), and
-extends it to support the creation of links. The appropriate function
-for the filesystem to which linkNamePtr belongs will be called.
+\fBTcl_FSLink\fR replaces the library version of \fBreadlink\fR, and
+extends it to support the creation of links. The appropriate function
+for the filesystem to which \fIlinkNamePtr\fR belongs will be called.
.PP
-If the \fItoPtr\fR is NULL, a readlink action is performed. The result
+If the \fItoPtr\fR is NULL, a
+.QW "read link"
+action is performed. The result
is a Tcl_Obj specifying the contents of the symbolic link given by
\fIlinkNamePtr\fR, or NULL if the link could not be read. The result is owned
by the caller, which should call Tcl_DecrRefCount when the result is no
longer needed. If the \fItoPtr\fR is not NULL, Tcl should create a link
of one of the types passed in in the \fIlinkAction\fR flag. This flag is
-an or'd combination of TCL_CREATE_SYMBOLIC_LINK and TCL_CREATE_HARD_LINK.
+an ORed combination of \fBTCL_CREATE_SYMBOLIC_LINK\fR and \fBTCL_CREATE_HARD_LINK\fR.
Where a choice exists (i.e. more than one flag is passed in), the Tcl
convention is to prefer symbolic links. When a link is successfully
created, the return value should be \fItoPtr\fR (which is therefore
-already owned by the caller). If unsuccessful, NULL should be
-returned.
+already owned by the caller). If unsuccessful, NULL is returned.
.PP
\fBTcl_FSLstat\fR fills the stat structure \fIstatPtr\fR with information
about the specified file. You do not need any access rights to the
@@ -381,43 +450,49 @@ If \fIpath\fR exists, \fBTcl_FSLstat\fR returns 0 and the stat structure
is filled with data. Otherwise, -1 is returned, and no stat info is
given.
.PP
-\fBTcl_FSUtime\fR replaces the library version of utime.
+\fBTcl_FSUtime\fR replaces the library version of utime.
+.PP
+This returns 0 on success and -1 on error (as per the \fButime\fR
+documentation). If successful, the function
+will update the
+.QW atime
+and
+.QW mtime
+values of the file given.
.PP
-For results see 'utime' documentation. If successful, the function
-will update the 'atime' and 'mtime' values of the file given.
+\fBTcl_FSFileAttrsGet\fR implements read access for the hookable \fBfile
+attributes\fR subcommand. The appropriate function for the filesystem to
+which \fIpathPtr\fR belongs will be called.
.PP
-\fBTcl_FSFileAttrsGet\fR implements read access for the hookable 'file
-attributes' subcommand. The appropriate function for the filesystem to
-which pathPtr belongs will be called.
+If the result is \fBTCL_OK\fR, then an object was placed in
+\fIobjPtrRef\fR, which
+will only be temporarily valid (unless \fBTcl_IncrRefCount\fR is called).
.PP
-If the result is TCL_OK, then an object was placed in objPtrRef, which
-will only be temporarily valid (unless Tcl_IncrRefCount is called).
+\fBTcl_FSFileAttrsSet\fR implements write access for the hookable \fBfile
+attributes\fR subcommand. The appropriate function for the filesystem to
+which \fIpathPtr\fR belongs will be called.
.PP
-\fBTcl_FSFileAttrsSet\fR implements write access for the hookable 'file
-attributes' subcommand. The appropriate function for the filesystem to
-which pathPtr belongs will be called.
+\fBTcl_FSFileAttrStrings\fR implements part of the hookable \fBfile
+attributes\fR subcommand. The appropriate function for the filesystem
+to which \fIpathPtr\fR belongs will be called.
.PP
-\fBTcl_FSFileAttrStrings\fR implements part of the hookable 'file attributes'
-subcommand. The appropriate function for the filesystem to which
-pathPtr belongs will be called.
-.PP
The called procedure may either return an array of strings, or may
-instead return NULL and place a Tcl list into the given objPtrRef. Tcl
-will take that list and first increment its refCount before using it.
-On completion of that use, Tcl will decrement its refCount. Hence if
+instead return NULL and place a Tcl list into the given \fIobjPtrRef\fR. Tcl
+will take that list and first increment its reference count before using it.
+On completion of that use, Tcl will decrement its reference count. Hence if
the list should be disposed of by Tcl when done, it should have a
-refCount of zero, and if the list should not be disposed of, the
-filesystem should ensure it retains a refCount on the object.
+reference count of zero, and if the list should not be disposed of, the
+filesystem should ensure it retains a reference count to the object.
.PP
\fBTcl_FSAccess\fR checks whether the process would be allowed to read,
-write or test for existence of the file (or other file system object)
-whose name is pathname. If pathname is a symbolic link on Unix,
+write or test for existence of the file (or other filesystem object)
+whose name is \fIpathname\fR. If \fIpathname\fR is a symbolic link on Unix,
then permissions of the file referred by this symbolic link are
tested.
.PP
On success (all requested permissions granted), zero is returned. On
error (at least one bit in mode asked for a permission that is denied,
-or some other error occurred), -1 is returned.
+or some other error occurred), -1 is returned.
.PP
\fBTcl_FSStat\fR fills the stat structure \fIstatPtr\fR with information
about the specified file. You do not need any access rights to the
@@ -451,87 +526,110 @@ If one of the standard channels, \fBstdin, stdout\fR or \fBstderr\fR was
previously closed, the act of creating the new channel also assigns it as a
replacement for the standard channel.
.PP
-\fBTcl_FSGetCwd\fR replaces the library version of getcwd().
+\fBTcl_FSGetCwd\fR replaces the library version of \fBgetcwd\fR.
.PP
It returns the Tcl library's current working directory. This may be
-different to the native platform's working directory, in the case for
-which the cwd is not in the native filesystem.
+different to the native platform's working directory, which happens when
+the current working directory is not in the native filesystem.
.PP
The result is a pointer to a Tcl_Obj specifying the current directory,
or NULL if the current directory could not be determined. If NULL is
-returned, an error message is left in the interp's result.
-
-The result already has its refCount incremented for the caller. When
-it is no longer needed, that refCount should be decremented. This is
+returned, an error message is left in the \fIinterp\fR's result.
+.PP
+The result already has its reference count incremented for the caller. When
+it is no longer needed, that reference count should be decremented. This is
needed for thread-safety purposes, to allow multiple threads to access
this and related functions, while ensuring the results are always
valid.
.PP
-\fBTcl_FSChdir\fR replaces the library version of chdir(). The path is
+\fBTcl_FSChdir\fR replaces the library version of \fBchdir\fR. The path is
normalized and then passed to the filesystem which claims it. If that
-filesystem does not implement this function, Tcl will fallback to a
-combination of stat and access to check whether the directory exists
-and has appropriate permissions.
-.PP
-For results, see chdir() documentation. If successful, we keep a
-record of the successful path in cwdPathPtr for subsequent calls to
-getcwd.
-.PP
-\fBTcl_FSPathSeparator\fR returns the separator character to be used for
-most specific element of the path specified by pathPtr (i.e. the last
+filesystem does not implement this function, Tcl will fallback to a
+combination of \fBstat\fR and \fBaccess\fR to check whether the directory
+exists and has appropriate permissions.
+.PP
+For results, see \fBchdir\fR documentation. If successful, we keep a
+record of the successful path in \fIcwdPathPtr\fR for subsequent calls to
+\fBTcl_FSGetCwd\fR.
+.PP
+\fBTcl_FSPathSeparator\fR returns the separator character to be used for
+most specific element of the path specified by \fIpathPtr\fR (i.e. the last
part of the path).
.PP
The separator is returned as a Tcl_Obj containing a string of length
1. If the path is invalid, NULL is returned.
.PP
-\fBTcl_FSJoinPath\fR takes the given Tcl_Obj, which should be a valid list,
-and returns the path object given by considering the first 'elements'
-elements as valid path segments. If elements < 0, we use the entire
-list.
-.PP
-Returns object with refCount of zero, containing the joined path.
+\fBTcl_FSJoinPath\fR takes the given Tcl_Obj, which must be a valid
+list (which is allowed to have a reference count of zero), and returns the path
+object given by considering the first \fIelements\fR elements as valid path
+segments (each path segment may be a complete path, a partial path or
+just a single possible directory or file name). If any path segment is
+actually an absolute path, then all prior path segments are discarded.
+If \fIelements\fR is less than 0, we use the entire list.
+.PP
+It is possible that the returned object is actually an element
+of the given list, so the caller should be careful to increment the
+reference count of the result before freeing the list.
+.PP
+The returned object, typically with a reference count of zero (but it
+could be shared
+under some conditions), contains the joined path. The caller must
+add a reference count to the object before using it. In particular, the
+returned object could be an element of the given list, so freeing the
+list might free the object prematurely if no reference count has been taken.
+If the number of elements is zero, then the returned object will be
+an empty-string Tcl_Obj.
.PP
\fBTcl_FSSplitPath\fR takes the given Tcl_Obj, which should be a valid path,
-and returns a Tcl List object containing each segment of that path as
+and returns a Tcl list object containing each segment of that path as
an element.
-.PP
-Returns list object with refCount of zero. If the passed in lenPtr is
-non-NULL, we use it to return the number of elements in the returned
-list.
+It returns a list object with a reference count of zero. If the
+passed in \fIlenPtr\fR is non-NULL, the variable it points to will be
+updated to contain the number of elements in the returned list.
.PP
\fBTcl_FSEqualPaths\fR tests whether the two paths given represent the same
filesystem object
.PP
-It returns 1 if the paths are equal, and 0 if they are different. If
+It returns 1 if the paths are equal, and 0 if they are different. If
either path is NULL, 0 is always returned.
.PP
\fBTcl_FSGetNormalizedPath\fR this important function attempts to extract
from the given Tcl_Obj a unique normalized path representation, whose
string value can be used as a unique identifier for the file.
.PP
-It returns the normalized path object, with refCount of zero, or NULL
-if the path was invalid or could otherwise not be successfully
-converted. Extraction of absolute, normalized paths is very
-efficient (because the filesystem operates on these representations
-internally), although the result when the filesystem contains
-numerous symbolic links may not be the most user-friendly
-version of a path.
+It returns the normalized path object, owned by Tcl, or NULL if the path
+was invalid or could otherwise not be successfully converted.
+Extraction of absolute, normalized paths is very efficient (because the
+filesystem operates on these representations internally), although the
+result when the filesystem contains numerous symbolic links may not be
+the most user-friendly version of a path. The return value is owned by
+Tcl and has a lifetime equivalent to that of the \fIpathPtr\fR passed in
+(unless that is a relative path, in which case the normalized path
+object may be freed any time the cwd changes) - the caller can of
+course increment the refCount if it wishes to maintain a copy for longer.
.PP
\fBTcl_FSJoinToPath\fR takes the given object, which should usually be a
valid path or NULL, and joins onto it the array of paths segments
given.
.PP
-Returns object with refCount of zero, containing the joined path.
+Returns object, typically with refCount of zero (but it could be shared
+under some conditions), containing the joined path. The caller must
+add a refCount to the object before using it. If any of the objects
+passed into this function (pathPtr or path elements) have a refCount
+of zero, they will be freed when this function returns.
.PP
\fBTcl_FSConvertToPathType\fR tries to convert the given Tcl_Obj to a valid
Tcl path type, taking account of the fact that the cwd may have changed
even if this object is already supposedly of the correct type.
-The filename may begin with "~" (to indicate current user's home
-directory) or "~<user>" (to indicate any user's home directory).
-.PP
-If the conversion succeeds (i.e. the object is a valid path in one of
-the current filesystems), then TCL_OK is returned. Otherwise
-TCL_ERROR is returned, and an error message may
+The filename may begin with
+.QW ~
+(to indicate current user's home directory) or
+.QW ~<user>
+(to indicate any user's home directory).
+.PP
+If the conversion succeeds (i.e. the object is a valid path in one of
+the current filesystems), then \fBTCL_OK\fR is returned. Otherwise
+\fBTCL_ERROR\fR is returned, and an error message may
be left in the interpreter.
.PP
\fBTcl_FSGetInternalRep\fR extracts the internal representation of a given
@@ -545,12 +643,17 @@ representation is cached, so that repeated calls to this function will
not require additional conversions.
.PP
\fBTcl_FSGetTranslatedPath\fR attempts to extract the translated path
-from the given Tcl_Obj.
+from the given Tcl_Obj.
.PP
If the translation succeeds (i.e. the object is a valid path), then it is
returned. Otherwise NULL will be returned, and an error message may be
-left in the interpreter. A "translated" path is one which contains no
-"~" or "~user" sequences (these have been expanded to their current
+left in the interpreter. A
+.QW translated
+path is one which contains no
+.QW ~
+or
+.QW ~user
+sequences (these have been expanded to their current
representation in the filesystem). The object returned is owned by the
caller, which must store it or call Tcl_DecrRefCount to ensure memory is
freed. This function is of little practical use, and
@@ -560,37 +663,53 @@ better functions to use for most purposes.
\fBTcl_FSGetTranslatedStringPath\fR does the same as
\fBTcl_FSGetTranslatedPath\fR, but returns a character string or NULL.
The string returned is dynamically allocated and owned by the caller,
-which must store it or call ckfree to ensure it is freed. Again,
+which must store it or call \fBckfree\fR to ensure it is freed. Again,
\fBTcl_FSGetNormalizedPath\fR or \fBTcl_GetNativePath\fR are usually
better functions to use for most purposes.
.PP
-\fBTcl_FSNewNativePath\fR performs something like that reverse of the
+\fBTcl_FSNewNativePath\fR performs something like the reverse of the
usual obj->path->nativerep conversions. If some code retrieves a path
-in native form (from, e.g. readlink or a native dialog), and that path
+in native form (from, e.g. \fBreadlink\fR or a native dialog), and that path
is to be used at the Tcl level, then calling this function is an
efficient way of creating the appropriate path object type.
.PP
-The resulting object is a pure 'path' object, which will only receive
-a Utf-8 string representation if that is required by some Tcl code.
+The resulting object is a pure
+.QW path
+object, which will only receive
+a UTF-8 string representation if that is required by some Tcl code.
.PP
-\fBTcl_FSGetNativePath\fR is for use by the Win/Unix/MacOS native
+\fBTcl_FSGetNativePath\fR is for use by the Win/Unix native
filesystems, so that they can easily retrieve the native (char* or
TCHAR*) representation of a path. This function is a convenience
wrapper around \fBTcl_FSGetInternalRep\fR, and assumes the native
-representation is string-based. It may be desirable in the future
-to have non-string-based native representations (for example, on
-MacOS, a representation using a fileSpec of FSRef structure would
-probably be more efficient). On Windows a full Unicode
-representation would allow for paths of unlimited length. Currently
-the representation is simply a character string containing the
-complete, absolute path in the native encoding.
+representation is string-based. It may be desirable in the future to
+have non-string-based native representations (for example, on MacOSX, a
+representation using a fileSpec of FSRef structure would probably be
+more efficient). On Windows a full Unicode representation would allow
+for paths of unlimited length. Currently the representation is simply a
+character string which may contain either the relative path or a
+complete, absolute normalized path in the native encoding (complex
+conditions dictate which of these will be provided, so neither can be
+relied upon, unless the path is known to be absolute). If you need a
+native path which must be absolute, then you should ask for the native
+version of a normalized path. If for some reason a non-absolute,
+non-normalized version of the path is needed, that must be constructed
+separately (e.g. using \fBTcl_FSGetTranslatedPath\fR).
.PP
The native representation is cached so that repeated calls to this
-function will not require additional conversions.
+function will not require additional conversions. The return value is
+owned by Tcl and has a lifetime equivalent to that of the \fIpathPtr\fR
+passed in (unless that is a relative path, in which case the native
+representation may be freed any time the cwd changes).
.PP
\fBTcl_FSFileSystemInfo\fR returns a list of two elements. The first
-element is the name of the filesystem (e.g. "native" or "vfs" or "zip"
-or "prowrap", perhaps), and the second is the particular type of the
+element is the name of the filesystem (e.g.
+.QW native ,
+.QW vfs ,
+.QW zip ,
+or
+.QW prowrap ,
+perhaps), and the second is the particular type of the
given path within that filesystem (which is filesystem dependent). The
second element may be empty if the filesystem does not provide a
further categorization of files.
@@ -603,25 +722,24 @@ recognized, when NULL will be returned.
.PP
If no filesystem will accept the path, NULL is returned.
.PP
-\fBTcl_FSGetPathType\fR determines whether the given path is relative
+\fBTcl_FSGetPathType\fR determines whether the given path is relative
to the current directory, relative to the current volume, or
absolute.
.PP
-It returns one of TCL_PATH_ABSOLUTE, TCL_PATH_RELATIVE, or
-TCL_PATH_VOLUME_RELATIVE
+It returns one of \fBTCL_PATH_ABSOLUTE\fR, \fBTCL_PATH_RELATIVE\fR, or
+\fBTCL_PATH_VOLUME_RELATIVE\fR
.PP
\fBTcl_AllocStatBuf\fR allocates a \fITcl_StatBuf\fR on the system
heap (which may be deallocated by being passed to \fBckfree\fR.) This
allows extensions to invoke \fBTcl_FSStat\fR and \fBTcl_FSLStat\fR
without being dependent on the size of the buffer. That in turn
depends on the flags used to build Tcl.
-.PP
-.SH TCL_FILESYSTEM
+.SH "THE VIRTUAL FILESYSTEM API"
.PP
A filesystem provides a \fBTcl_Filesystem\fR structure that contains
pointers to functions that implement the various operations on a
filesystem; these operations are invoked as needed by the generic
-layer, which generally occurs through the functions listed above.
+layer, which generally occurs through the functions listed above.
.PP
The \fBTcl_Filesystem\fR structures are manipulated using the following
methods.
@@ -631,13 +749,13 @@ optional piece of data to associated with that filesystem. On calling
this function, Tcl will attach the filesystem to the list of known
filesystems, and it will become fully functional immediately. Tcl does
not check if the same filesystem is registered multiple times (and in
-general that is not a good thing to do). TCL_OK will be returned.
+general that is not a good thing to do). \fBTCL_OK\fR will be returned.
.PP
\fBTcl_FSUnregister\fR removes the given filesystem structure from
-the list of known filesystems, if it is known, and returns TCL_OK. If
-the filesystem is not currently registered, TCL_ERROR is returned.
+the list of known filesystems, if it is known, and returns \fBTCL_OK\fR. If
+the filesystem is not currently registered, \fBTCL_ERROR\fR is returned.
.PP
-\fBTcl_FSData\fR will return the ClientData associated with the given
+\fBTcl_FSData\fR will return the ClientData associated with the given
filesystem, if that filesystem is registered. Otherwise it will
return NULL.
.PP
@@ -645,41 +763,42 @@ return NULL.
the set of mount points for the given (already registered) filesystem
have changed, and that cached file representations may therefore no
longer be correct.
+.SS "THE TCL_FILESYSTEM STRUCTURE"
.PP
The \fBTcl_Filesystem\fR structure contains the following fields:
.CS
typedef struct Tcl_Filesystem {
- CONST char *\fItypeName\fR;
- int \fIstructureLength\fR;
- Tcl_FSVersion \fIversion\fR;
+ const char *\fItypeName\fR;
+ int \fIstructureLength\fR;
+ Tcl_FSVersion \fIversion\fR;
Tcl_FSPathInFilesystemProc *\fIpathInFilesystemProc\fR;
Tcl_FSDupInternalRepProc *\fIdupInternalRepProc\fR;
Tcl_FSFreeInternalRepProc *\fIfreeInternalRepProc\fR;
Tcl_FSInternalToNormalizedProc *\fIinternalToNormalizedProc\fR;
Tcl_FSCreateInternalRepProc *\fIcreateInternalRepProc\fR;
- Tcl_FSNormalizePathProc *\fInormalizePathProc\fR;
+ Tcl_FSNormalizePathProc *\fInormalizePathProc\fR;
Tcl_FSFilesystemPathTypeProc *\fIfilesystemPathTypeProc\fR;
Tcl_FSFilesystemSeparatorProc *\fIfilesystemSeparatorProc\fR;
- Tcl_FSStatProc *\fIstatProc\fR;
- Tcl_FSAccessProc *\fIaccessProc\fR;
- Tcl_FSOpenFileChannelProc *\fIopenFileChannelProc\fR;
- Tcl_FSMatchInDirectoryProc *\fImatchInDirectoryProc\fR;
- Tcl_FSUtimeProc *\fIutimeProc\fR;
- Tcl_FSLinkProc *\fIlinkProc\fR;
- Tcl_FSListVolumesProc *\fIlistVolumesProc\fR;
+ Tcl_FSStatProc *\fIstatProc\fR;
+ Tcl_FSAccessProc *\fIaccessProc\fR;
+ Tcl_FSOpenFileChannelProc *\fIopenFileChannelProc\fR;
+ Tcl_FSMatchInDirectoryProc *\fImatchInDirectoryProc\fR;
+ Tcl_FSUtimeProc *\fIutimeProc\fR;
+ Tcl_FSLinkProc *\fIlinkProc\fR;
+ Tcl_FSListVolumesProc *\fIlistVolumesProc\fR;
Tcl_FSFileAttrStringsProc *\fIfileAttrStringsProc\fR;
Tcl_FSFileAttrsGetProc *\fIfileAttrsGetProc\fR;
Tcl_FSFileAttrsSetProc *\fIfileAttrsSetProc\fR;
- Tcl_FSCreateDirectoryProc *\fIcreateDirectoryProc\fR;
- Tcl_FSRemoveDirectoryProc *\fIremoveDirectoryProc\fR;
- Tcl_FSDeleteFileProc *\fIdeleteFileProc\fR;
- Tcl_FSCopyFileProc *\fIcopyFileProc\fR;
- Tcl_FSRenameFileProc *\fIrenameFileProc\fR;
- Tcl_FSCopyDirectoryProc *\fIcopyDirectoryProc\fR;
- Tcl_FSLstatProc *\fIlstatProc\fR;
- Tcl_FSLoadFileProc *\fIloadFileProc\fR;
- Tcl_FSGetCwdProc *\fIgetCwdProc\fR;
- Tcl_FSChdirProc *\fIchdirProc\fR;
+ Tcl_FSCreateDirectoryProc *\fIcreateDirectoryProc\fR;
+ Tcl_FSRemoveDirectoryProc *\fIremoveDirectoryProc\fR;
+ Tcl_FSDeleteFileProc *\fIdeleteFileProc\fR;
+ Tcl_FSCopyFileProc *\fIcopyFileProc\fR;
+ Tcl_FSRenameFileProc *\fIrenameFileProc\fR;
+ Tcl_FSCopyDirectoryProc *\fIcopyDirectoryProc\fR;
+ Tcl_FSLstatProc *\fIlstatProc\fR;
+ Tcl_FSLoadFileProc *\fIloadFileProc\fR;
+ Tcl_FSGetCwdProc *\fIgetCwdProc\fR;
+ Tcl_FSChdirProc *\fIchdirProc\fR;
} Tcl_Filesystem;
.CE
.PP
@@ -697,20 +816,26 @@ side-effects which are required by the filesystem; Tcl has less
efficient emulations it can fall back on). It is important to note
that, in the current version of Tcl, most of these fallbacks are only
used to handle commands initiated in Tcl, not in C. What this means is,
-that if a 'file rename' command is issued in Tcl, and the relevant
+that if a \fBfile rename\fR command is issued in Tcl, and the relevant
filesystem(s) do not implement their \fITcl_FSRenameFileProc\fR, Tcl's
core will instead fallback on a combination of other filesystem
functions (it will use \fITcl_FSCopyFileProc\fR followed by
\fITcl_FSDeleteFileProc\fR, and if \fITcl_FSCopyFileProc\fR is not
implemented there is a further fallback). However, if a
-\fITcl_FSRenameFile\fR command is issued at the C level, no such
+\fITcl_FSRenameFileProc\fR command is issued at the C level, no such
fallbacks occur. This is true except for the last four entries in the
-filesystem table (lstat, load, getcwd and chdir)
+filesystem table (\fBlstat\fR, \fBload\fR, \fBgetcwd\fR and \fBchdir\fR)
for which fallbacks do in fact occur at the C level.
.PP
-As an example, here is the filesystem lookup table used by the
-"vfs" extension which allows filesystem actions to be implemented
-in Tcl.
+Any functions which take path names in Tcl_Obj form take
+those names in UTF\-8 form. The filesystem infrastructure API is
+designed to support efficient, cached conversion of these UTF\-8 paths
+to other native representations.
+.SS "EXAMPLE FILESYSTEM DEFINITION"
+.PP
+Here is the filesystem lookup table used by the
+.QW vfs
+extension which allows filesystem actions to be implemented in Tcl.
.CS
static Tcl_Filesystem vfsFilesystem = {
"tclvfs",
@@ -719,14 +844,15 @@ static Tcl_Filesystem vfsFilesystem = {
&VfsPathInFilesystem,
&VfsDupInternalRep,
&VfsFreeInternalRep,
- /* No internal to normalized, since we don't create any
- * pure 'internal' Tcl_Obj path representations */
+ /* No internal to normalized, since we don't create
+ * any pure 'internal' Tcl_Obj path representations */
NULL,
- /* No create native rep function, since we don't use it
- * and don't choose to support uses of 'Tcl_FSNewNativePath' */
+ /* No create native rep function, since we don't use
+ * it and don't choose to support uses of
+ * Tcl_FSNewNativePath */
NULL,
- /* Normalize path isn't needed - we assume paths only have
- * one representation */
+ /* Normalize path isn't needed - we assume paths only
+ * have one representation */
NULL,
&VfsFilesystemPathType,
&VfsFilesystemSeparator,
@@ -735,57 +861,57 @@ static Tcl_Filesystem vfsFilesystem = {
&VfsOpenFileChannel,
&VfsMatchInDirectory,
&VfsUtime,
- /* We choose not to support symbolic links inside our vfs's */
+ /* We choose not to support symbolic links inside our
+ * VFS's */
NULL,
&VfsListVolumes,
&VfsFileAttrStrings,
&VfsFileAttrsGet,
&VfsFileAttrsSet,
&VfsCreateDirectory,
- &VfsRemoveDirectory,
+ &VfsRemoveDirectory,
&VfsDeleteFile,
- /* No copy file - fallback will occur at Tcl level */
+ /* No copy file; use the core fallback mechanism */
NULL,
- /* No rename file - fallback will occur at Tcl level */
+ /* No rename file; use the core fallback mechanism */
+ NULL,
+ /* No copy directory; use the core fallback mechanism */
NULL,
- /* No copy directory - fallback will occur at Tcl level */
- NULL,
/* Core will use stat for lstat */
NULL,
- /* No load - fallback on core implementation */
+ /* No load; use the core fallback mechanism */
NULL,
- /* We don't need a getcwd or chdir - fallback on Tcl's versions */
+ /* We don't need a getcwd or chdir; the core's own
+ * internal value is suitable */
NULL,
NULL
};
.CE
+.SH "FILESYSTEM INFRASTRUCTURE"
.PP
-Any functions which take path names in Tcl_Obj form take
-those names in UTF\-8 form. The filesystem infrastructure API is
-designed to support efficient, cached conversion of these UTF\-8 paths
-to other native representations.
-.SH TYPENAME
+These fields contain basic information about the filesystem structure
+and addresses of functions which are used to associate
+a particular filesystem with a file path, and deal with the internal
+handling of path representations, for example copying and freeing such
+representations.
+.SS TYPENAME
.PP
The \fItypeName\fR field contains a null-terminated string that
identifies the type of the filesystem implemented, e.g.
-\fBnative\fR or \fBzip\fR or \fBvfs\fR.
-.PP
-.SH "STRUCTURE LENGTH"
+.QW native ,
+.QW zip
+or
+.QW vfs .
+.SS "STRUCTURE LENGTH"
.PP
The \fIstructureLength\fR field is generally implemented as
\fIsizeof(Tcl_Filesystem)\fR, and is there to allow easier
binary backwards compatibility if the size of the structure
changes in a future Tcl release.
-.SH VERSION
+.SS VERSION
.PP
The \fIversion\fR field should be set to \fBTCL_FILESYSTEM_VERSION_1\fR.
-.SH "FILESYSTEM INFRASTRUCTURE"
-.PP
-These fields contain addresses of functions which are used to associate
-a particular filesystem with a file path, and deal with the internal
-handling of path representations, for example copying and freeing such
-representations.
-.SH PATHINFILESYSTEMPROC
+.SS PATHINFILESYSTEMPROC
.PP
The \fIpathInFilesystemProc\fR field contains the address of a function
which is called to determine whether a given path object belongs to this
@@ -793,7 +919,7 @@ filesystem or not. Tcl will only call the rest of the filesystem
functions with a path for which this function has returned \fBTCL_OK\fR.
If the path does not belong, -1 should be returned (the behaviour of Tcl
for any other return value is not defined). If \fBTCL_OK\fR is returned,
-then the optional \fBclientDataPtr\fR output parameter can be used to
+then the optional \fIclientDataPtr\fR output parameter can be used to
return an internal (filesystem specific) representation of the path,
which will be cached inside the path object, and may be retrieved
efficiently by the other filesystem functions. Tcl will simultaneously
@@ -803,10 +929,10 @@ Tcl's internal list of known filesystems.
.PP
.CS
typedef int Tcl_FSPathInFilesystemProc(
- Tcl_Obj *\fIpathPtr\fR,
- ClientData *\fIclientDataPtr\fR);
+ Tcl_Obj *\fIpathPtr\fR,
+ ClientData *\fIclientDataPtr\fR);
.CE
-.SH DUPINTERNALREPPROC
+.SS DUPINTERNALREPPROC
.PP
This function makes a copy of a path's internal representation, and is
called when Tcl needs to duplicate a path object. If NULL, Tcl will
@@ -815,18 +941,18 @@ regenerated later.
.PP
.CS
typedef ClientData Tcl_FSDupInternalRepProc(
- ClientData \fIclientData\fR);
+ ClientData \fIclientData\fR);
.CE
-.SH FREEINTERNALREPPROC
+.SS FREEINTERNALREPPROC
Free the internal representation. This must be implemented if internal
representations need freeing (i.e. if some memory is allocated when an
internal representation is generated), but may otherwise be NULL.
.PP
.CS
typedef void Tcl_FSFreeInternalRepProc(
- ClientData \fIclientData\fR);
+ ClientData \fIclientData\fR);
.CE
-.SH INTERNALTONORMALIZEDPROC
+.SS INTERNALTONORMALIZEDPROC
.PP
Function to convert internal representation to a normalized path. Only
required if the filesystem creates pure path objects with no string/path
@@ -835,9 +961,9 @@ representation is the normalized path.
.PP
.CS
typedef Tcl_Obj* Tcl_FSInternalToNormalizedProc(
- ClientData \fIclientData\fR);
+ ClientData \fIclientData\fR);
.CE
-.SH CREATEINTERNALREPPROC
+.SS CREATEINTERNALREPPROC
.PP
Function to take a path object, and calculate an internal
representation for it, and store that native representation in the
@@ -847,36 +973,41 @@ immediately creates an internal representation for paths it accepts.
.PP
.CS
typedef ClientData Tcl_FSCreateInternalRepProc(
- Tcl_Obj *\fIpathPtr\fR);
+ Tcl_Obj *\fIpathPtr\fR);
.CE
-.SH NORMALIZEPATHPROC
+.SS NORMALIZEPATHPROC
.PP
Function to normalize a path. Should be implemented for all
filesystems which can have multiple string representations for the same
-path object. In Tcl, every 'path' must have a single unique 'normalized'
+path object. In Tcl, every
+.QW path
+must have a single unique
+.QW normalized
string representation. Depending on the filesystem,
there may be more than one unnormalized string representation which
refers to that path (e.g. a relative path, a path with different
character case if the filesystem is case insensitive, a path contain a
-reference to a home directory such as '~', a path containing symbolic
+reference to a home directory such as
+.QW ~ ,
+a path containing symbolic
links, etc). If the very last component in the path is a symbolic
link, it should not be converted into the object it points to (but
its case or other aspects should be made unique). All other path
components should be converted from symbolic links. This one
-exception is required to agree with Tcl's semantics with 'file
-delete', 'file rename', 'file copy' operating on symbolic links.
-This function may be called with 'nextCheckpoint' either
+exception is required to agree with Tcl's semantics with \fBfile
+delete\fR, \fBfile rename\fR, \fBfile copy\fR operating on symbolic links.
+This function may be called with \fInextCheckpoint\fR either
at the beginning of the path (i.e. zero), at the end of the path, or
at any intermediate file separator in the path. It will never
point to any other arbitrary position in the path. In the last of
-the three valid cases, the implementation can assume that the path
+the three valid cases, the implementation can assume that the path
up to and including the file separator is known and normalized.
.PP
.CS
typedef int Tcl_FSNormalizePathProc(
- Tcl_Interp *\fIinterp\fR,
- Tcl_Obj *\fIpathPtr\fR,
- int \fInextCheckpoint\fR);
+ Tcl_Interp *\fIinterp\fR,
+ Tcl_Obj *\fIpathPtr\fR,
+ int \fInextCheckpoint\fR);
.CE
.SH "FILESYSTEM OPERATIONS"
.PP
@@ -890,43 +1021,52 @@ this may be desirable (for example, a read-only filesystem should not
implement the last four functions, and a filesystem which does not
support symbolic links need not implement the \fBreadlink\fR function,
etc. The Tcl core expects filesystems to behave in this way).
-.SH FILESYSTEMPATHTYPEPROC
+.SS FILESYSTEMPATHTYPEPROC
.PP
Function to determine the type of a path in this filesystem. May be
NULL, in which case no type information will be available to users of
-the filesystem. The 'type' is used only for informational purposes,
+the filesystem. The
+.QW type
+is used only for informational purposes,
and should be returned as the string representation of the Tcl_Obj
-which is returned. A typical return value might be "networked", "zip"
-or "ftp". The Tcl_Obj result is owned by the filesystem and so Tcl will
-increment the refCount of that object if it wishes to retain a reference
+which is returned. A typical return value might be
+.QW networked ,
+.QW zip
+or
+.QW ftp .
+The Tcl_Obj result is owned by the filesystem and so Tcl will
+increment the refCount of that object if it wishes to retain a reference
to it.
.PP
.CS
typedef Tcl_Obj* Tcl_FSFilesystemPathTypeProc(
- Tcl_Obj *\fIpathPtr\fR);
+ Tcl_Obj *\fIpathPtr\fR);
.CE
-.SH FILESYSTEMSEPARATORPROC
+.SS FILESYSTEMSEPARATORPROC
.PP
Function to return the separator character(s) for this filesystem.
-Must be implemented, otherwise the \fBfile separator\fR command will not
-function correctly. The usual return value will be a Tcl_Obj
-containing the string "/".
+This need only be implemented if the filesystem wishes to use a
+different separator than the standard string
+.QW / .
+Amongst other
+uses, it is returned by the \fBfile separator\fR command. The
+return value should be an object with refCount of zero.
.PP
.CS
typedef Tcl_Obj* Tcl_FSFilesystemSeparatorProc(
- Tcl_Obj *\fIpathPtr\fR);
+ Tcl_Obj *\fIpathPtr\fR);
.CE
-.SH STATPROC
+.SS STATPROC
.PP
-Function to process a \fBTcl_FSStat()\fR call. Must be implemented for any
-reasonable filesystem, since many Tcl level commands depend crucially
+Function to process a \fBTcl_FSStat\fR call. Must be implemented for any
+reasonable filesystem, since many Tcl level commands depend crucially
upon it (e.g. \fBfile atime\fR, \fBfile isdirectory\fR, \fBfile size\fR,
\fBglob\fR).
.PP
.CS
typedef int Tcl_FSStatProc(
- Tcl_Obj *\fIpathPtr\fR,
- Tcl_StatBuf *\fIstatPtr\fR);
+ Tcl_Obj *\fIpathPtr\fR,
+ Tcl_StatBuf *\fIstatPtr\fR);
.CE
.PP
The \fBTcl_FSStatProc\fR fills the stat structure \fIstatPtr\fR with
@@ -942,40 +1082,40 @@ last metadata change time.
If the file represented by \fIpathPtr\fR exists, the
\fBTcl_FSStatProc\fR returns 0 and the stat structure is filled with
data. Otherwise, -1 is returned, and no stat info is given.
-.SH ACCESSPROC
+.SS ACCESSPROC
.PP
-Function to process a \fBTcl_FSAccess()\fR call. Must be implemented for
-any reasonable filesystem, since many Tcl level commands depend crucially
+Function to process a \fBTcl_FSAccess\fR call. Must be implemented for
+any reasonable filesystem, since many Tcl level commands depend crucially
upon it (e.g. \fBfile exists\fR, \fBfile readable\fR).
.PP
.CS
typedef int Tcl_FSAccessProc(
- Tcl_Obj *\fIpathPtr\fR,
- int \fImode\fR);
+ Tcl_Obj *\fIpathPtr\fR,
+ int \fImode\fR);
.CE
.PP
The \fBTcl_FSAccessProc\fR checks whether the process would be allowed
-to read, write or test for existence of the file (or other file system
-object) whose name is pathname. If pathname is a symbolic link, then
+to read, write or test for existence of the file (or other filesystem
+object) whose name is in \fIpathPtr\fR. If the pathname refers to a
+symbolic link, then the
permissions of the file referred by this symbolic link should be tested.
.PP
On success (all requested permissions granted), zero is returned. On
error (at least one bit in mode asked for a permission that is denied,
or some other error occurred), -1 is returned.
+.SS OPENFILECHANNELPROC
.PP
-.SH OPENFILECHANNELPROC
-.PP
-Function to process a \fBTcl_FSOpenFileChannel()\fR call. Must be
+Function to process a \fBTcl_FSOpenFileChannel\fR call. Must be
implemented for any reasonable filesystem, since any operations
-which require open or accessing a file's contents will use it
+which require open or accessing a file's contents will use it
(e.g. \fBopen\fR, \fBencoding\fR, and many Tk commands).
.PP
.CS
typedef Tcl_Channel Tcl_FSOpenFileChannelProc(
- Tcl_Interp *\fIinterp\fR,
- Tcl_Obj *\fIpathPtr\fR,
- int \fImode\fR,
- int \fIpermissions\fR);
+ Tcl_Interp *\fIinterp\fR,
+ Tcl_Obj *\fIpathPtr\fR,
+ int \fImode\fR,
+ int \fIpermissions\fR);
.CE
.PP
The \fBTcl_FSOpenFileChannelProc\fR opens a file specified by
@@ -996,20 +1136,20 @@ interpreter; to register it, use \fBTcl_RegisterChannel\fR. If one of
the standard channels, \fBstdin, stdout\fR or \fBstderr\fR was
previously closed, the act of creating the new channel also assigns it
as a replacement for the standard channel.
-.SH MATCHINDIRECTORYPROC
+.SS MATCHINDIRECTORYPROC
.PP
-Function to process a \fBTcl_FSMatchInDirectory()\fR call. If not
+Function to process a \fBTcl_FSMatchInDirectory\fR call. If not
implemented, then glob and recursive copy functionality will be lacking
-in the filesystem (and this may impact commands like 'encoding names'
+in the filesystem (and this may impact commands like \fBencoding names\fR
which use glob functionality internally).
.PP
.CS
typedef int Tcl_FSMatchInDirectoryProc(
- Tcl_Interp* \fIinterp\fR,
- Tcl_Obj *\fIresult\fR,
- Tcl_Obj *\fIpathPtr\fR,
- CONST char *\fIpattern\fR,
- Tcl_GlobTypeData * \fItypes\fR);
+ Tcl_Interp* \fIinterp\fR,
+ Tcl_Obj *\fIresultPtr\fR,
+ Tcl_Obj *\fIpathPtr\fR,
+ const char *\fIpattern\fR,
+ Tcl_GlobTypeData *\fItypes\fR);
.CE
.PP
The function should return all files or directories (or other filesystem
@@ -1026,12 +1166,13 @@ not, so code should be flexible to both possibilities.
.PP
The return value is a standard Tcl result indicating whether an error
occurred in the matching process. Error messages are placed in
-\fIinterp\fR; on a \fBTCL_OK\fR result, results should be added to the
-\fIresult\fR object given (which can be assumed to be a valid
-unshared Tcl list). The matches added
-to \fIresult\fR should include any path prefix given in \fIpathPtr\fR
-(this usually means they will be absolute path specifications).
-Note that if no matches are found, that simply leads to an empty
+\fIinterp\fR, unless \fIinterp\fR in NULL in which case no error
+message need be generated; on a \fBTCL_OK\fR result, results should be
+added to the \fIresultPtr\fR object given (which can be assumed to be a
+valid unshared Tcl list). The matches added
+to \fIresultPtr\fR should include any path prefix given in \fIpathPtr\fR
+(this usually means they will be absolute path specifications).
+Note that if no matches are found, that simply leads to an empty
result; errors are only signaled for actual file or filesystem
problems which may occur during the matching process.
.PP
@@ -1039,14 +1180,14 @@ The \fBTcl_GlobTypeData\fR structure passed in the \fItypes\fR
parameter contains the following fields:
.CS
typedef struct Tcl_GlobTypeData {
- /* Corresponds to bcdpfls as in 'find -t' */
- int \fItype\fR;
- /* Corresponds to file permissions */
- int \fIperm\fR;
- /* Acceptable mac type */
- Tcl_Obj *\fImacType\fR;
- /* Acceptable mac creator */
- Tcl_Obj *\fImacCreator\fR;
+ /* Corresponds to bcdpfls as in 'find -t' */
+ int \fItype\fR;
+ /* Corresponds to file permissions */
+ int \fIperm\fR;
+ /* Acceptable mac type */
+ Tcl_Obj *\fImacType\fR;
+ /* Acceptable mac creator */
+ Tcl_Obj *\fImacCreator\fR;
} Tcl_GlobTypeData;
.CE
.PP
@@ -1062,50 +1203,52 @@ which lie within the given \fIpathPtr\fR (and in this case, \fIpathPtr\fR
need not lie within the same filesystem - different to all other cases in
which this function is called). Support for this is critical if Tcl is
to have seamless transitions between from one filesystem to another.
-.SH UTIMEPROC
+.SS UTIMEPROC
.PP
-Function to process a \fBTcl_FSUtime()\fR call. Required to allow setting
-(not reading) of times with 'file mtime', 'file atime' and the
-open-r/open-w/fcopy implementation of 'file copy'.
+Function to process a \fBTcl_FSUtime\fR call. Required to allow setting
+(not reading) of times with \fBfile mtime\fR, \fBfile atime\fR and the
+open-r/open-w/fcopy implementation of \fBfile copy\fR.
.PP
.CS
typedef int Tcl_FSUtimeProc(
- Tcl_Obj *\fIpathPtr\fR,
- struct utimbuf *\fItval\fR);
+ Tcl_Obj *\fIpathPtr\fR,
+ struct utimbuf *\fItval\fR);
.CE
.PP
The access and modification times of the file specified by \fIpathPtr\fR
should be changed to the values given in the \fItval\fR structure.
.PP
-The return value is a standard Tcl result indicating whether an error
-occurred in the process.
-.SH LINKPROC
+The return value should be 0 on success and -1 on an error, as
+with the system \fButime\fR.
+.SS LINKPROC
.PP
-Function to process a \fBTcl_FSLink()\fR call. Should be implemented
+Function to process a \fBTcl_FSLink\fR call. Should be implemented
only if the filesystem supports links, and may otherwise be NULL.
.PP
.CS
typedef Tcl_Obj* Tcl_FSLinkProc(
- Tcl_Obj *\fIlinkNamePtr\fR,
- Tcl_Obj *\fItoPtr\fR,
- int \fIlinkAction\fR);
+ Tcl_Obj *\fIlinkNamePtr\fR,
+ Tcl_Obj *\fItoPtr\fR,
+ int \fIlinkAction\fR);
.CE
.PP
If \fItoPtr\fR is NULL, the function is being asked to read the
contents of a link. The result is a Tcl_Obj specifying the contents of
the link given by \fIlinkNamePtr\fR, or NULL if the link could
-not be read. The result is owned by the caller, which should call
-Tcl_DecrRefCount when the result is no longer needed. If \fItoPtr\fR
-is not NULL, the function should attempt to create a link. The result
-in this case should be \fItoPtr\fR if the link was successful and NULL
-otherwise. In this case the result is not owned by the caller. See
+not be read. The result is owned by the caller (and should therefore
+have its ref count incremented before being returned). Any callers
+should call Tcl_DecrRefCount on this result when it is no longer needed.
+If \fItoPtr\fR is not NULL, the function should attempt to create a link.
+The result in this case should be \fItoPtr\fR if the link was successful
+and NULL otherwise. In this case the result is not owned by the caller
+(i.e. no ref count manipulation on either end is needed). See
the documentation for \fBTcl_FSLink\fR for the correct interpretation
of the \fIlinkAction\fR flags.
-.SH LISTVOLUMESPROC
+.SS LISTVOLUMESPROC
.PP
Function to list any filesystem volumes added by this filesystem.
Should be implemented only if the filesystem adds volumes at the head
-of the filesystem, so that they can be returned by 'file volumes'.
+of the filesystem, so that they can be returned by \fBfile volumes\fR.
.PP
.CS
typedef Tcl_Obj* Tcl_FSListVolumesProc(void);
@@ -1116,7 +1259,9 @@ NULL (or an empty list) if no volumes are provided. The result object
is considered to be owned by the filesystem (not by Tcl's core), but
should be given a refCount for Tcl. Tcl will use the contents of the
list and then decrement that refCount. This allows filesystems to
-choose whether they actually want to retain a 'master list' of volumes
+choose whether they actually want to retain a
+.QW "master list"
+of volumes
or not (if not, they generate the list on the fly and pass it to Tcl
with a refCount of 1 and then forget about the list, if yes, then
they simply increment the refCount of their master list and pass it
@@ -1124,8 +1269,7 @@ to Tcl which will copy the contents and then decrement the count back
to where it was).
.PP
Therefore, Tcl considers return values from this proc to be read-only.
-.PP
-.SH FILEATTRSTRINGSPROC
+.SS FILEATTRSTRINGSPROC
.PP
Function to list all attribute strings which are valid for this
filesystem. If not implemented the filesystem will not support
@@ -1135,94 +1279,98 @@ not implemented, there is no need to implement the \fBget\fR and \fBset\fR
methods.
.PP
.CS
-typedef CONST char** Tcl_FSFileAttrStringsProc(
- Tcl_Obj *\fIpathPtr\fR,
- Tcl_Obj** \fIobjPtrRef\fR);
+typedef const char** Tcl_FSFileAttrStringsProc(
+ Tcl_Obj *\fIpathPtr\fR,
+ Tcl_Obj** \fIobjPtrRef\fR);
.CE
.PP
The called function may either return an array of strings, or may
-instead return NULL and place a Tcl list into the given objPtrRef. Tcl
-will take that list and first increment its refCount before using it.
-On completion of that use, Tcl will decrement its refCount. Hence if
+instead return NULL and place a Tcl list into the given \fIobjPtrRef\fR. Tcl
+will take that list and first increment its reference count before using it.
+On completion of that use, Tcl will decrement its reference count. Hence if
the list should be disposed of by Tcl when done, it should have a
-refCount of zero, and if the list should not be disposed of, the
-filesystem should ensure it retains a refCount on the object.
-.SH FILEATTRSGETPROC
+reference count of zero, and if the list should not be disposed of, the
+filesystem should ensure it returns an object with a reference count
+of at least one.
+.SS FILEATTRSGETPROC
.PP
-Function to process a \fBTcl_FSFileAttrsGet()\fR call, used by 'file
-attributes'.
+Function to process a \fBTcl_FSFileAttrsGet\fR call, used by \fBfile
+attributes\fR.
.PP
.CS
typedef int Tcl_FSFileAttrsGetProc(
- Tcl_Interp *\fIinterp\fR,
- int \fIindex\fR,
- Tcl_Obj *\fIpathPtr\fR,
- Tcl_Obj **\fIobjPtrRef\fR);
+ Tcl_Interp *\fIinterp\fR,
+ int \fIindex\fR,
+ Tcl_Obj *\fIpathPtr\fR,
+ Tcl_Obj **\fIobjPtrRef\fR);
.CE
.PP
Returns a standard Tcl return code. The attribute value retrieved,
which corresponds to the \fIindex\fR'th element in the list returned by
-the Tcl_FSFileAttrStringsProc, is a Tcl_Obj placed in objPtrRef (if
-TCL_OK was returned) and is likely to have a refCount of zero. Either
+the \fBTcl_FSFileAttrStringsProc\fR, is a Tcl_Obj placed in \fIobjPtrRef\fR (if
+\fBTCL_OK\fR was returned) and is likely to have a reference count of zero. Either
way we must either store it somewhere (e.g. the Tcl result), or
-Incr/Decr its refCount to ensure it is properly freed.
-.SH FILEATTRSSETPROC
+Incr/Decr its reference count to ensure it is properly freed.
+.SS FILEATTRSSETPROC
.PP
-Function to process a \fBTcl_FSFileAttrsSet()\fR call, used by 'file
-attributes'. If the filesystem is read-only, there is no need
+Function to process a \fBTcl_FSFileAttrsSet\fR call, used by \fBfile
+attributes\fR. If the filesystem is read-only, there is no need
to implement this.
.PP
.CS
typedef int Tcl_FSFileAttrsSetProc(
- Tcl_Interp *\fIinterp\fR,
- int \fIindex\fR,
- Tcl_Obj *\fIpathPtr\fR,
- Tcl_Obj *\fIobjPtr\fR);
+ Tcl_Interp *\fIinterp\fR,
+ int \fIindex\fR,
+ Tcl_Obj *\fIpathPtr\fR,
+ Tcl_Obj *\fIobjPtr\fR);
.CE
.PP
The attribute value of the \fIindex\fR'th element in the list returned by
the Tcl_FSFileAttrStringsProc should be set to the \fIobjPtr\fR given.
-.SH CREATEDIRECTORYPROC
+.SS CREATEDIRECTORYPROC
.PP
-Function to process a \fBTcl_FSCreateDirectory()\fR call. Should be
+Function to process a \fBTcl_FSCreateDirectory\fR call. Should be
implemented unless the FS is read-only.
.PP
.CS
typedef int Tcl_FSCreateDirectoryProc(
- Tcl_Obj *\fIpathPtr\fR);
+ Tcl_Obj *\fIpathPtr\fR);
.CE
.PP
The return value is a standard Tcl result indicating whether an error
occurred in the process. If successful, a new directory should have
been added to the filesystem in the location specified by
\fIpathPtr\fR.
-.SH REMOVEDIRECTORYPROC
+.SS REMOVEDIRECTORYPROC
.PP
-Function to process a 'Tcl_FSRemoveDirectory()' call. Should be
+Function to process a \fBTcl_FSRemoveDirectory\fR call. Should be
implemented unless the FS is read-only.
.PP
.CS
typedef int Tcl_FSRemoveDirectoryProc(
- Tcl_Obj *\fIpathPtr\fR,
- int \fIrecursive\fR,
- Tcl_Obj **\fIerrorPtr\fR);
+ Tcl_Obj *\fIpathPtr\fR,
+ int \fIrecursive\fR,
+ Tcl_Obj **\fIerrorPtr\fR);
.CE
.PP
The return value is a standard Tcl result indicating whether an error
occurred in the process. If successful, the directory specified by
\fIpathPtr\fR should have been removed from the filesystem. If the
-\fIrecursive\fR flag is given, then a non-empty directory should
-be deleted without error. If an error does occur, the name of
-the file or directory which caused the error should be placed in
-\fIerrorPtr\fR.
-.SH DELETEFILEPROC
-.PP
-Function to process a \fBTcl_FSDeleteFile()\fR call. Should be implemented
+\fIrecursive\fR flag is given, then a non-empty directory should be
+deleted without error. If this flag is not given, then and the
+directory is non-empty a POSIX
+.QW EEXIST
+error should be signaled. If an
+error does occur, the name of the file or directory which caused the
+error should be placed in \fIerrorPtr\fR.
+.SS DELETEFILEPROC
+.PP
+Function to process a \fBTcl_FSDeleteFile\fR call. Should be implemented
unless the FS is read-only.
.PP
.CS
typedef int Tcl_FSDeleteFileProc(
- Tcl_Obj *\fIpathPtr\fR);
+ Tcl_Obj *\fIpathPtr\fR);
.CE
.PP
The return value is a standard Tcl result indicating whether an error
@@ -1233,73 +1381,82 @@ function and not Tcl_FSRemoveDirectoryProc when needed to delete them
(even if they are symbolic links to directories).
.SH "FILESYSTEM EFFICIENCY"
.PP
-.SH LSTATPROC
+These functions need not be implemented for a particular filesystem
+because the core has a fallback implementation available. See each
+individual description for the consequences of leaving the field NULL.
+.SS LSTATPROC
.PP
-Function to process a \fBTcl_FSLstat()\fR call. If not implemented, Tcl
+Function to process a \fBTcl_FSLstat\fR call. If not implemented, Tcl
will attempt to use the \fIstatProc\fR defined above instead. Therefore
it need only be implemented if a filesystem can differentiate between
\fBstat\fR and \fBlstat\fR calls.
.PP
.CS
typedef int Tcl_FSLstatProc(
- Tcl_Obj *\fIpathPtr\fR,
- Tcl_StatBuf *\fIstatPtr\fR);
+ Tcl_Obj *\fIpathPtr\fR,
+ Tcl_StatBuf *\fIstatPtr\fR);
.CE
.PP
-The behavior of this function is very similar to that of the
-Tcl_FSStatProc defined above, except that if it is applied
+The behavior of this function is very similar to that of the
+\fBTcl_FSStatProc\fR defined above, except that if it is applied
to a symbolic link, it returns information about the link, not
about the target file.
+.SS COPYFILEPROC
.PP
-.SH COPYFILEPROC
-.PP
-Function to process a \fBTcl_FSCopyFile()\fR call. If not implemented Tcl
-will fall back on open-r, open-w and fcopy as a copying mechanism.
+Function to process a \fBTcl_FSCopyFile\fR call. If not implemented Tcl
+will fall back on \fBopen\fR-r, \fBopen\fR-w and \fBfcopy\fR as a
+copying mechanism.
Therefore it need only be implemented if the filesystem can perform
that action more efficiently.
.PP
.CS
typedef int Tcl_FSCopyFileProc(
- Tcl_Obj *\fIsrcPathPtr\fR,
- Tcl_Obj *\fIdestPathPtr\fR);
+ Tcl_Obj *\fIsrcPathPtr\fR,
+ Tcl_Obj *\fIdestPathPtr\fR);
.CE
.PP
The return value is a standard Tcl result indicating whether an error
occurred in the copying process. Note that, \fIdestPathPtr\fR is the
name of the file which should become the copy of \fIsrcPathPtr\fR. It
is never the name of a directory into which \fIsrcPathPtr\fR could be
-copied (i.e. the function is much simpler than the Tcl level 'file
-copy' subcommand). Note that,
+copied (i.e. the function is much simpler than the Tcl level \fBfile
+copy\fR subcommand). Note that,
if the filesystem supports symbolic links, Tcl will always call this
-function and not Tcl_FSCopyDirectoryProc when needed to copy them
-(even if they are symbolic links to directories).
-.SH RENAMEFILEPROC
-.PP
-Function to process a \fBTcl_FSRenameFile()\fR call. If not implemented,
+function and not \fIcopyDirectoryProc\fR when needed to copy them
+(even if they are symbolic links to directories). Finally, if the
+filesystem determines it cannot support the \fBfile copy\fR action,
+calling \fBTcl_SetErrno(EXDEV)\fR and returning a non-\fBTCL_OK\fR
+result will tell Tcl to use its standard fallback mechanisms.
+.SS RENAMEFILEPROC
+.PP
+Function to process a \fBTcl_FSRenameFile\fR call. If not implemented,
Tcl will fall back on a copy and delete mechanism. Therefore it need
only be implemented if the filesystem can perform that action more
efficiently.
.PP
.CS
typedef int Tcl_FSRenameFileProc(
- Tcl_Obj *\fIsrcPathPtr\fR,
- Tcl_Obj *\fIdestPathPtr\fR);
+ Tcl_Obj *\fIsrcPathPtr\fR,
+ Tcl_Obj *\fIdestPathPtr\fR);
.CE
.PP
The return value is a standard Tcl result indicating whether an error
-occurred in the renaming process.
-.SH COPYDIRECTORYPROC
-.PP
-Function to process a \fBTcl_FSCopyDirectory()\fR call. If not
-implemented, Tcl will fall back on a recursive create-dir, file copy
+occurred in the renaming process. If the
+filesystem determines it cannot support the \fBfile rename\fR action,
+calling \fBTcl_SetErrno(EXDEV)\fR and returning a non-\fBTCL_OK\fR
+result will tell Tcl to use its standard fallback mechanisms.
+.SS COPYDIRECTORYPROC
+.PP
+Function to process a \fBTcl_FSCopyDirectory\fR call. If not
+implemented, Tcl will fall back on a recursive \fBfile mkdir\fR, \fBfile copy\fR
mechanism. Therefore it need only be implemented if the filesystem can
perform that action more efficiently.
.PP
.CS
typedef int Tcl_FSCopyDirectoryProc(
- Tcl_Obj *\fIsrcPathPtr\fR,
- Tcl_Obj *\fIdestPathPtr\fR,
- Tcl_Obj **\fIerrorPtr\fR);
+ Tcl_Obj *\fIsrcPathPtr\fR,
+ Tcl_Obj *\fIdestPathPtr\fR,
+ Tcl_Obj **\fIerrorPtr\fR);
.CE
.PP
The return value is a standard Tcl result indicating whether an error
@@ -1309,33 +1466,42 @@ the file or directory which caused the error should be placed in
directory-name which should become the mirror-image of
\fIsrcPathPtr\fR. It is not the name of a directory into which
\fIsrcPathPtr\fR should be copied (i.e. the function is much simpler
-than the Tcl level 'file copy' subcommand).
-.SH LOADFILEPROC
-.PP
-Function to process a \fBTcl_FSLoadFile()\fR call. If not implemented, Tcl
-will fall back on a copy to native-temp followed by a Tcl_FSLoadFile on
+than the Tcl level \fBfile copy\fR subcommand). Finally, if the
+filesystem determines it cannot support the directory copy action,
+calling \fBTcl_SetErrno(EXDEV)\fR and returning a non-\fBTCL_OK\fR
+result will tell Tcl to use its standard fallback mechanisms.
+.SS LOADFILEPROC
+.PP
+Function to process a \fBTcl_FSLoadFile\fR call. If not implemented, Tcl
+will fall back on a copy to native-temp followed by a \fBTcl_FSLoadFile\fR on
that temporary copy. Therefore it need only be implemented if the
filesystem can load code directly, or it can be implemented simply to
-return TCL_ERROR to disable load functionality in this filesystem
+return \fBTCL_ERROR\fR to disable load functionality in this filesystem
entirely.
.PP
.CS
typedef int Tcl_FSLoadFileProc(
- Tcl_Interp * \fIinterp\fR,
- Tcl_Obj *\fIpathPtr\fR,
- Tcl_LoadHandle * \fIhandlePtr\fR,
- Tcl_FSUnloadFileProc * \fIunloadProcPtr\fR);
+ Tcl_Interp *\fIinterp\fR,
+ Tcl_Obj *\fIpathPtr\fR,
+ Tcl_LoadHandle *\fIhandlePtr\fR,
+ Tcl_FSUnloadFileProc *\fIunloadProcPtr\fR);
.CE
.PP
Returns a standard Tcl completion code. If an error occurs, an error
-message is left in the interp's result. The function dynamically loads
-a binary code file into memory. On a successful
-load, the \fIhandlePtr\fR should be filled with a token for
-the dynamically loaded file, and the \fIunloadProcPtr\fR should be
-filled in with the address of a procedure. The procedure will be
-called with the given Tcl_LoadHandle as its only parameter when Tcl
-needs to unload the file.
-.SH UNLOADFILEPROC
+message is left in the \fIinterp\fR's result. The function dynamically loads a
+binary code file into memory. On a successful load, the \fIhandlePtr\fR
+should be filled with a token for the dynamically loaded file, and the
+\fIunloadProcPtr\fR should be filled in with the address of a procedure.
+The unload procedure will be called with the given \fBTcl_LoadHandle\fR as its
+only parameter when Tcl needs to unload the file. For example, for the
+native filesystem, the \fBTcl_LoadHandle\fR returned is currently a token
+which can be used in the private \fBTclpFindSymbol\fR to access functions
+in the new code. Each filesystem is free to define the
+\fBTcl_LoadHandle\fR as it requires. Finally, if the
+filesystem determines it cannot support the file load action,
+calling \fBTcl_SetErrno(EXDEV)\fR and returning a non-\fBTCL_OK\fR
+result will tell Tcl to use its standard fallback mechanisms.
+.SS UNLOADFILEPROC
.PP
Function to unload a previously successfully loaded file. If load was
implemented, then this should also be implemented, if there is any
@@ -1343,17 +1509,17 @@ cleanup action required.
.PP
.CS
typedef void Tcl_FSUnloadFileProc(
- Tcl_LoadHandle \fIloadHandle\fR);
+ Tcl_LoadHandle \fIloadHandle\fR);
.CE
-.SH GETCWDPROC
+.SS GETCWDPROC
.PP
-Function to process a \fBTcl_FSGetCwd()\fR call. Most filesystems need not
-implement this. It will usually only be called once, if 'getcwd' is
-called before 'chdir'. May be NULL.
+Function to process a \fBTcl_FSGetCwd\fR call. Most filesystems need not
+implement this. It will usually only be called once, if \fBgetcwd\fR is
+called before \fBchdir\fR. May be NULL.
.PP
.CS
typedef Tcl_Obj* Tcl_FSGetCwdProc(
- Tcl_Interp *\fIinterp\fR);
+ Tcl_Interp *\fIinterp\fR);
.CE
.PP
If the filesystem supports a native notion of a current working
@@ -1361,26 +1527,28 @@ directory (which might perhaps change independent of Tcl), this
function should return that cwd as the result, or NULL if the current
directory could not be determined (e.g. the user does not have
appropriate permissions on the cwd directory). If NULL is returned, an
-error message is left in the interp's result.
-.PP
-.SH CHDIRPROC
+error message is left in the \fIinterp\fR's result.
+.SS CHDIRPROC
.PP
-Function to process a \fBTcl_FSChdir()\fR call. If filesystems do not
+Function to process a \fBTcl_FSChdir\fR call. If filesystems do not
implement this, it will be emulated by a series of directory access
checks. Otherwise, virtual filesystems which do implement it need only
-respond with a positive return result if the dirName is a valid,
+respond with a positive return result if the \fIpathPtr\fR is a valid,
accessible directory in their filesystem. They need not remember the
-result, since that will be automatically remembered for use by GetCwd.
+result, since that will be automatically remembered for use by
+\fBTcl_FSGetCwd\fR.
Real filesystems should carry out the correct action (i.e. call the
-correct system 'chdir' api).
+correct system \fBchdir\fR API).
.PP
.CS
typedef int Tcl_FSChdirProc(
- Tcl_Obj *\fIpathPtr\fR);
+ Tcl_Obj *\fIpathPtr\fR);
.CE
.PP
The \fBTcl_FSChdirProc\fR changes the applications current working
directory to the value specified in \fIpathPtr\fR. The function returns
-1 on error or 0 on success.
+.SH "SEE ALSO"
+cd(n), file(n), load(n), open(n), pwd(n), unload(n)
.SH KEYWORDS
-stat access filesystem vfs
+stat, access, filesystem, vfs, virtual
diff --git a/doc/FindExec.3 b/doc/FindExec.3
index 9c42f9a..0e225e9 100644
--- a/doc/FindExec.3
+++ b/doc/FindExec.3
@@ -16,10 +16,10 @@ Tcl_FindExecutable, Tcl_GetNameOfExecutable \- identify or return the name of th
void
\fBTcl_FindExecutable\fR(\fIargv0\fR)
.sp
-CONST char *
+const char *
\fBTcl_GetNameOfExecutable\fR()
.SH ARGUMENTS
-.AS char *argv0 in
+.AS char *argv0
.AP char *argv0 in
The first command-line argument to the program, which gives the
application's name.
diff --git a/doc/GetCwd.3 b/doc/GetCwd.3
index f8fce52..964e237 100755..100644
--- a/doc/GetCwd.3
+++ b/doc/GetCwd.3
@@ -19,7 +19,7 @@ char *
int
\fBTcl_Chdir\fR(\fIpath\fR)
.SH ARGUMENTS
-.AS Tcl_DString *bufferPtr
+.AS Tcl_DString *bufferPtr in/out
.AP Tcl_Interp *interp in
Interpreter in which to report an error, if any.
.AP Tcl_DString *bufferPtr in/out
@@ -39,7 +39,7 @@ the same functionality as the Tcl \fBpwd\fR command.
.PP
\fBTcl_GetCwd\fR returns a pointer to a string specifying the current
directory, or NULL if the current directory could not be determined.
-If NULL is returned, an error message is left in the interp's result.
+If NULL is returned, an error message is left in the \fIinterp\fR's result.
Storage for the result string is allocated in bufferPtr; the caller
must call \fBTcl_DStringFree()\fR when the result is no longer needed.
The format of the path is UTF\-8.
diff --git a/doc/GetHostName.3 b/doc/GetHostName.3
index 694ac4a..28f3a4f 100644
--- a/doc/GetHostName.3
+++ b/doc/GetHostName.3
@@ -11,7 +11,7 @@ Tcl_GetHostName \- get the name of the local host
.nf
\fB#include <tcl.h>\fR
.sp
-CONST char *
+const char *
\fBTcl_GetHostName\fR()
.BE
diff --git a/doc/GetIndex.3 b/doc/GetIndex.3
index e47f89b..82590fb 100644
--- a/doc/GetIndex.3
+++ b/doc/GetIndex.3
@@ -16,14 +16,12 @@ Tcl_GetIndexFromObj, Tcl_GetIndexFromObjStruct \- lookup string in table of keyw
int
\fBTcl_GetIndexFromObj\fR(\fIinterp, objPtr, tablePtr, msg, flags,
indexPtr\fR)
-.VS
.sp
int
\fBTcl_GetIndexFromObjStruct\fR(\fIinterp, objPtr, structTablePtr, offset,
-msg, flags, indexPtr\fR)
-.VE
+ msg, flags, indexPtr\fR)
.SH ARGUMENTS
-.AS "CONST char" **tablePtr
+.AS "const char" *structTablePtr in/out
.AP Tcl_Interp *interp in
Interpreter to use for error reporting; if NULL, then no message is
provided on errors.
@@ -31,19 +29,17 @@ provided on errors.
The string value of this object is used to search through \fItablePtr\fR.
The internal representation is modified to hold the index of the matching
table entry.
-.AP "CONST char" **tablePtr in
+.AP "const char" **tablePtr in
An array of null-terminated strings. The end of the array is marked
by a NULL string pointer.
-.AP "CONST VOID" *structTablePtr in
-An array of arbitrary type, typically some \fBstruct\fP type.
+.AP "const void" *structTablePtr in
+An array of arbitrary type, typically some \fBstruct\fR type.
The first member of the structure must be a null-terminated string.
-The size of the structure is given by \fIoffset\fP.
-.VS
+The size of the structure is given by \fIoffset\fR.
.AP int offset in
The offset to add to structTablePtr to get to the next entry.
The end of the array is marked by a NULL string pointer.
-.VE
-.AP "CONST char" *msg in
+.AP "const char" *msg in
Null-terminated string describing what is being looked up, such as
\fBoption\fR. This string is included in error messages.
.AP int flags in
@@ -66,14 +62,14 @@ the strings in \fItablePtr\fR to find a match. A match occurs if
for exactly one of the strings in \fItablePtr\fR and the
\fBTCL_EXACT\fR flag was not specified; in either case
the index of the matching entry is stored at \fI*indexPtr\fR
-and TCL_OK is returned.
+and \fBTCL_OK\fR is returned.
.PP
If there is no matching entry,
-TCL_ERROR is returned and an error message is left in \fIinterp\fR's
-result if \fIinterp\fR isn't NULL. \fIMsg\fR is included in the
+\fBTCL_ERROR\fR is returned and an error message is left in \fIinterp\fR's
+result if \fIinterp\fR is not NULL. \fIMsg\fR is included in the
error message to indicate what was being looked up. For example,
if \fImsg\fR is \fBoption\fR the error message will have a form like
-\fBbad option "firt": must be first, second, or third\fR.
+.QW "\fBbad option \N'34'firt\N'34': must be first, second, or third\fR" .
.PP
If \fBTcl_GetIndexFromObj\fR completes successfully it modifies the
internal representation of \fIobjPtr\fR to hold the address of
@@ -85,17 +81,18 @@ operation. Note: \fBTcl_GetIndexFromObj\fR assumes that the entries
in \fItablePtr\fR are static: they must not change between
invocations. If the value of \fIobjPtr\fR is the empty string,
\fBTcl_GetIndexFromObj\fR will treat it as a non-matching value
-and return TCL_ERROR.
-.VS
+and return \fBTCL_ERROR\fR.
.PP
\fBTcl_GetIndexFromObjStruct\fR works just like
\fBTcl_GetIndexFromObj\fR, except that instead of treating
-\fItablePtr\fR as an array of string pointers, it treats it as the
-first in a series of string ptrs that are spaced apart by \fIoffset\fR
-bytes. This is particularly useful when processing things like
+\fItablePtr\fR as an array of string pointers, it treats it as a
+pointer to the first string in a series of strings that have
+\fIoffset\fR bytes between them (i.e. that there is a pointer to the
+first array of characters at \fItablePtr\fR, a pointer to the second
+array of characters at \fItablePtr\fR+\fIoffset\fR bytes, etc.)
+This is particularly useful when processing things like
\fBTk_ConfigurationSpec\fR, whose string keys are in the same place in
each of several array elements.
-.VE
.SH "SEE ALSO"
Tcl_WrongNumArgs
diff --git a/doc/GetInt.3 b/doc/GetInt.3
index 677527a..f77d337 100644
--- a/doc/GetInt.3
+++ b/doc/GetInt.3
@@ -15,62 +15,69 @@ Tcl_GetInt, Tcl_GetDouble, Tcl_GetBoolean \- convert from string to integer, dou
\fB#include <tcl.h>\fR
.sp
int
-\fBTcl_GetInt\fR(\fIinterp, string, intPtr\fR)
+\fBTcl_GetInt\fR(\fIinterp, src, intPtr\fR)
.sp
int
-\fBTcl_GetDouble\fR(\fIinterp, string, doublePtr\fR)
+\fBTcl_GetDouble\fR(\fIinterp, src, doublePtr\fR)
.sp
int
-\fBTcl_GetBoolean\fR(\fIinterp, string, boolPtr\fR)
+\fBTcl_GetBoolean\fR(\fIinterp, src, boolPtr\fR)
.SH ARGUMENTS
-.AS Tcl_Interp *doublePtr
+.AS Tcl_Interp *doublePtr out
.AP Tcl_Interp *interp in
Interpreter to use for error reporting.
-.AP "CONST char" *string in
+.AP "const char" *src in
Textual value to be converted.
.AP int *intPtr out
-Points to place to store integer value converted from \fIstring\fR.
+Points to place to store integer value converted from \fIsrc\fR.
.AP double *doublePtr out
Points to place to store double-precision floating-point
-value converted from \fIstring\fR.
+value converted from \fIsrc\fR.
.AP int *boolPtr out
-Points to place to store boolean value (0 or 1) converted from \fIstring\fR.
+Points to place to store boolean value (0 or 1) converted from \fIsrc\fR.
.BE
.SH DESCRIPTION
.PP
These procedures convert from strings to integers or double-precision
floating-point values or booleans (represented as 0- or 1-valued
-integers). Each of the procedures takes a \fIstring\fR argument,
+integers). Each of the procedures takes a \fIsrc\fR argument,
converts it to an internal form of a particular type, and stores
the converted value at the location indicated by the procedure's
third argument. If all goes well, each of the procedures returns
-TCL_OK. If \fIstring\fR doesn't have the proper syntax for the
-desired type then TCL_ERROR is returned, an error message is left
+\fBTCL_OK\fR. If \fIsrc\fR does not have the proper syntax for the
+desired type then \fBTCL_ERROR\fR is returned, an error message is left
in the interpreter's result, and nothing is stored at *\fIintPtr\fR
or *\fIdoublePtr\fR or *\fIboolPtr\fR.
.PP
-\fBTcl_GetInt\fR expects \fIstring\fR to consist of a collection
+\fBTcl_GetInt\fR expects \fIsrc\fR to consist of a collection
of integer digits, optionally signed and optionally preceded by
-white space. If the first two characters of \fIstring\fR are ``0x''
-then \fIstring\fR is expected to be in hexadecimal form; otherwise,
-if the first character of \fIstring\fR is ``0'' then \fIstring\fR
-is expected to be in octal form; otherwise, \fIstring\fR is
+white space. If the first two characters of \fIsrc\fR
+after the optional white space and sign are
+.QW 0x
+then \fIsrc\fR is expected to be in hexadecimal form; otherwise,
+if the first such character is
+.QW 0
+then \fIsrc\fR
+is expected to be in octal form; otherwise, \fIsrc\fR is
expected to be in decimal form.
.PP
-\fBTcl_GetDouble\fR expects \fIstring\fR to consist of a floating-point
+\fBTcl_GetDouble\fR expects \fIsrc\fR to consist of a floating-point
number, which is: white space; a sign; a sequence of digits; a
-decimal point; a sequence of digits; the letter ``e''; and a
-signed decimal exponent. Any of the fields may be omitted, except that
+decimal point; a sequence of digits; the letter
+.QW e ;
+a signed decimal exponent; and more white space.
+Any of the fields may be omitted, except that
the digits either before or after the decimal point must be present
-and if the ``e'' is present then it must be followed by the
-exponent number.
+and if the
+.QW e
+is present then it must be followed by the exponent number.
.PP
-\fBTcl_GetBoolean\fR expects \fIstring\fR to specify a boolean
-value. If \fIstring\fR is any of \fB0\fR, \fBfalse\fR,
+\fBTcl_GetBoolean\fR expects \fIsrc\fR to specify a boolean
+value. If \fIsrc\fR is any of \fB0\fR, \fBfalse\fR,
\fBno\fR, or \fBoff\fR, then \fBTcl_GetBoolean\fR stores a zero
value at \fI*boolPtr\fR.
-If \fIstring\fR is any of \fB1\fR, \fBtrue\fR, \fByes\fR, or \fBon\fR,
+If \fIsrc\fR is any of \fB1\fR, \fBtrue\fR, \fByes\fR, or \fBon\fR,
then 1 is stored at \fI*boolPtr\fR.
Any of these values may be abbreviated, and upper-case spellings
are also acceptable.
diff --git a/doc/GetOpnFl.3 b/doc/GetOpnFl.3
index e914b8f..38aa976 100644
--- a/doc/GetOpnFl.3
+++ b/doc/GetOpnFl.3
@@ -8,29 +8,29 @@
.TH Tcl_GetOpenFile 3 8.0 Tcl "Tcl Library Procedures"
.BS
.SH NAME
-Tcl_GetOpenFile \- Get a standard IO File * handle from a channel. (Unix only)
+Tcl_GetOpenFile \- Return a FILE* for a channel registered in the given interpreter (Unix only)
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
-\fBTcl_GetOpenFile\fR(\fIinterp, string, write, checkUsage, filePtr\fR)
+\fBTcl_GetOpenFile\fR(\fIinterp, chanID, write, checkUsage, filePtr\fR)
.sp
.SH ARGUMENTS
-.AS Tcl_Interp checkUsage
+.AS Tcl_Interp checkUsage out
.AP Tcl_Interp *interp in
Tcl interpreter from which file handle is to be obtained.
-.AP "CONST char" *string in
+.AP "const char" *chanID in
String identifying channel, such as \fBstdin\fR or \fBfile4\fR.
.AP int write in
Non-zero means the file will be used for writing, zero means it will
be used for reading.
.AP int checkUsage in
-If non-zero, then an error will be generated if the file wasn't opened
+If non-zero, then an error will be generated if the file was not opened
for the access indicated by \fIwrite\fR.
.AP ClientData *filePtr out
Points to word in which to store pointer to FILE structure for
-the file given by \fIstring\fR.
+the file given by \fIchanID\fR.
.BE
.SH DESCRIPTION
@@ -44,17 +44,15 @@ be used for reading or writing.
In some cases, such as a channel that connects to a pipeline of
subprocesses, different FILE pointers will be returned for reading
and writing.
-\fBTcl_GetOpenFile\fR normally returns TCL_OK.
-If an error occurs in \fBTcl_GetOpenFile\fR (e.g. \fIstring\fR didn't
-make any sense or \fIcheckUsage\fR was set and the file wasn't opened
-for the access specified by \fIwrite\fR) then TCL_ERROR is returned
+\fBTcl_GetOpenFile\fR normally returns \fBTCL_OK\fR.
+If an error occurs in \fBTcl_GetOpenFile\fR (e.g. \fIchanID\fR did not
+make any sense or \fIcheckUsage\fR was set and the file was not opened
+for the access specified by \fIwrite\fR) then \fBTCL_ERROR\fR is returned
and the interpreter's result will contain an error message.
In the current implementation \fIcheckUsage\fR is ignored and consistency
checks are always performed.
-.VS
.PP
Note that this interface is only supported on the Unix platform.
-.VE
.SH KEYWORDS
channel, file handle, permissions, pipeline, read, write
diff --git a/doc/GetStdChan.3 b/doc/GetStdChan.3
index e0f754a..045d15a 100644
--- a/doc/GetStdChan.3
+++ b/doc/GetStdChan.3
@@ -20,7 +20,7 @@ Tcl_Channel
\fBTcl_SetStdChannel\fR(\fIchannel, type\fR)
.sp
.SH ARGUMENTS
-.AS Tcl_Channel channel in
+.AS Tcl_Channel channel
.AP int type in
The identifier for the standard channel to retrieve or modify. Must be one of
\fBTCL_STDIN\fR, \fBTCL_STDOUT\fR, or \fBTCL_STDERR\fR.
@@ -76,7 +76,6 @@ standard error being last.
.PP
See \fBTcl_StandardChannels\fR for a general treatise about standard
channels and the behaviour of the Tcl library with regard to them.
-.PP
.SH "SEE ALSO"
Tcl_Close(3), Tcl_CreateChannel(3), Tcl_Main(3), tclsh(1)
diff --git a/doc/GetTime.3 b/doc/GetTime.3
index 92457bd..14a9e8c 100644
--- a/doc/GetTime.3
+++ b/doc/GetTime.3
@@ -1,5 +1,5 @@
'\"
-'\" Copyright (c) 2001 by Kevin B. Kenny.
+'\" Copyright (c) 2001 by Kevin B. Kenny <kennykb@acm.org>.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -8,16 +8,39 @@
.TH Tcl_GetTime 3 8.4 Tcl "Tcl Library Procedures"
.BS
.SH NAME
-Tcl_GetTime \- get date and time
+Tcl_GetTime, Tcl_SetTimeProc, Tcl_QueryTimeProc \- get date and time
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
-\fBTcl_GetTime\fR(\fI timePtr \fR)
+\fBTcl_GetTime\fR(\fItimePtr\fR)
+.sp
+\fBTcl_SetTimeProc\fR(\fIgetProc, scaleProc, clientData\fR)
+.sp
+\fBTcl_QueryTimeProc\fR(\fIgetProcPtr, scaleProcPtr, clientDataPtr\fR)
.SH ARGUMENTS
-.AS "Tcl_Time *" timePtr
+.AS "Tcl_Time *" timePtr out
.AP "Tcl_Time *" timePtr out
Points to memory in which to store the date and time information.
+.AS "Tcl_GetTimeProc *" getProc in
+.AP "Tcl_GetTimeProc *" getProc in
+Pointer to handler function replacing \fBTcl_GetTime\fR's access to the OS.
+.AS "Tcl_ScaleTimeProc *" scaleProc in
+.AP "Tcl_ScaleTimeProc *" scaleProc in
+Pointer to handler function for the conversion of time delays in the
+virtual domain to real-time.
+.AS "ClientData *" clientData in
+.AP "ClientData *" clientData in
+Value passed through to the two handler functions.
+.AS "Tcl_GetTimeProc **" getProcPtr inout
+.AP "Tcl_GetTimeProc **" getProcPtr inout
+Pointer to place the currently registered get handler function into.
+.AS "Tcl_ScaleTimeProc **" scaleProcPtr inout
+.AP "Tcl_ScaleTimeProc **" scaleProcPtr inout
+Pointer to place the currently registered scale handler function into.
+.AS "ClientData **" clientDataPtr inout
+.AP "ClientData **" clientDataPtr inout
+Pointer to place the currently registered pass-through value into.
.BE
.SH DESCRIPTION
.PP
@@ -45,6 +68,32 @@ computer system. On multiprocessor variants of Windows, this number
may be limited to the 10- or 20-ms granularity of the system clock.
(On single-processor Windows systems, the \fIusec\fR field is derived
from a performance counter and is highly precise.)
+.PP
+The \fBTcl_SetTime\fR function registers two related handler functions
+with the core. The first handler function is a replacement for
+\fBTcl_GetTime\fR, or rather the OS access made by
+\fBTcl_GetTime\fR. The other handler function is used by the Tcl
+notifier to convert wait/block times from the virtual domain into real
+time.
+.PP
+The \fBTcl_QueryTime\fR function returns the currently registered
+handler functions. If no external handlers were set then this will
+return the standard handlers accessing and processing the native time
+of the OS. The arguments to the function are allowed to be NULL; and
+any argument which is NULL is ignored and not set.
+.PP
+Any handler pair specified has to return data which is consistent
+between them. In other words, setting one handler of the pair to
+something assuming a 10-times slowdown, and the other handler of the
+pair to something assuming a two-times slowdown is wrong and not
+allowed.
+.PP
+The set handler functions are allowed to run the delivered time
+backwards, however this should be avoided. We have to allow it as the
+native time can run backwards as the user can fiddle with the system
+time one way or other. Note that the insertion of the hooks will not
+change the behaviour of the Tcl core with regard to this situation,
+i.e. the existing behaviour is retained.
.SH "SEE ALSO"
clock
.SH KEYWORDS
diff --git a/doc/GetVersion.3 b/doc/GetVersion.3
index 4fa26f4..47034d0 100755..100644
--- a/doc/GetVersion.3
+++ b/doc/GetVersion.3
@@ -15,6 +15,7 @@ Tcl_GetVersion \- get the version of the library at runtime
.sp
\fBTcl_GetVersion\fR(\fImajor, minor, patchLevel, type\fR)
.SH ARGUMENTS
+.AS Tcl_ReleaseType *patchLevel out
.AP int *major out
Major version number of the Tcl library.
.AP int *minor out
diff --git a/doc/Hash.3 b/doc/Hash.3
index 1f6040a..78b8459 100644
--- a/doc/Hash.3
+++ b/doc/Hash.3
@@ -44,21 +44,21 @@ Tcl_HashEntry *
Tcl_HashEntry *
\fBTcl_NextHashEntry\fR(\fIsearchPtr\fR)
.sp
-CONST char *
+char *
\fBTcl_HashStats\fR(\fItablePtr\fR)
.SH ARGUMENTS
-.AS Tcl_HashSearch *searchPtr
+.AS Tcl_HashKeyType *searchPtr out
.AP Tcl_HashTable *tablePtr in
Address of hash table structure (for all procedures but
\fBTcl_InitHashTable\fR, this must have been initialized by
previous call to \fBTcl_InitHashTable\fR).
.AP int keyType in
Kind of keys to use for new hash table. Must be either
-TCL_STRING_KEYS, TCL_ONE_WORD_KEYS, TCL_CUSTOM_TYPE_KEYS,
-TCL_CUSTOM_PTR_KEYS, or an integer value greater than 1.
+\fBTCL_STRING_KEYS\fR, \fBTCL_ONE_WORD_KEYS\fR, \fBTCL_CUSTOM_TYPE_KEYS\fR,
+\fBTCL_CUSTOM_PTR_KEYS\fR, or an integer value greater than 1.
.AP Tcl_HashKeyType *typePtr in
Address of structure which defines the behaviour of the hash table.
-.AP "CONST char" *key in
+.AP "const char" *key in
Key to use for probe into table. Exact form depends on
\fIkeyType\fR used to create table.
.AP int *newPtr out
@@ -86,7 +86,9 @@ STRUCTURE\fR below). All of the keys in a given table have the same
form, which is specified when the table is initialized.
.PP
The value of a hash table entry can be anything that fits in the same
-space as a ``char *'' pointer. Values for hash table entries are
+space as a
+.QW "char *"
+pointer. Values for hash table entries are
managed entirely by clients, not by the hash module itself. Typically
each entry's value is a pointer to a data structure managed by client
code.
@@ -122,8 +124,10 @@ They are passed to hashing routines using the address of the
first character of the string.
.IP \fBTCL_ONE_WORD_KEYS\fR 25
Keys are single-word values; they are passed to hashing routines
-and stored in hash table entries as ``char *'' values.
-The pointer value is the key; it need not (and usually doesn't)
+and stored in hash table entries as
+.QW "char *"
+values.
+The pointer value is the key; it need not (and usually does not)
actually point to a string.
.IP \fBTCL_CUSTOM_TYPE_KEYS\fR 25
Keys are of arbitrary type, and are stored in the entry. Hashing
@@ -138,7 +142,9 @@ structure is described in the section
.IP \fIother\fR 25
If \fIkeyType\fR is not one of the above,
then it must be an integer value greater than 1.
-In this case the keys will be arrays of ``int'' values, where
+In this case the keys will be arrays of
+.QW int
+values, where
\fIkeyType\fR gives the number of ints in each key.
This allows structures to be used as keys.
All keys must have the same size.
@@ -159,7 +165,7 @@ before deleting the table.
.PP
\fBTcl_CreateHashEntry\fR locates the entry corresponding to a
particular key, creating a new entry in the table if there
-wasn't already one with the given key.
+was not already one with the given key.
If an entry already existed with the given key then \fI*newPtr\fR
is set to zero.
If a new entry was created, then \fI*newPtr\fR is set to a non-zero
@@ -175,28 +181,34 @@ the client is responsible for any cleanup associated with the
entry's value, such as freeing a structure that it points to.
.PP
\fBTcl_FindHashEntry\fR is similar to \fBTcl_CreateHashEntry\fR
-except that it doesn't create a new entry if the key doesn't exist;
+except that it does not create a new entry if the key doesn't exist;
instead, it returns NULL as result.
.PP
\fBTcl_GetHashValue\fR and \fBTcl_SetHashValue\fR are used to
read and write an entry's value, respectively.
-Values are stored and retrieved as type ``ClientData'', which is
+Values are stored and retrieved as type
+.QW ClientData ,
+which is
large enough to hold a pointer value. On almost all machines this is
large enough to hold an integer value too.
.PP
\fBTcl_GetHashKey\fR returns the key for a given hash table entry,
-either as a pointer to a string, a one-word (``char *'') key, or
+either as a pointer to a string, a one-word
+.PQ "char *"
+key, or
as a pointer to the first word of an array of integers, depending
on the \fIkeyType\fR used to create a hash table.
In all cases \fBTcl_GetHashKey\fR returns a result with type
-``char *''.
+.QW "char *" .
When the key is a string or array, the result of \fBTcl_GetHashKey\fR
points to information in the table entry; this information will
remain valid until the entry is deleted or its table is deleted.
.PP
\fBTcl_FirstHashEntry\fR and \fBTcl_NextHashEntry\fR may be used
to scan all of the entries in a hash table.
-A structure of type ``Tcl_HashSearch'', provided by the client,
+A structure of type
+.QW Tcl_HashSearch ,
+provided by the client,
is used to keep track of progress through the table.
\fBTcl_FirstHashEntry\fR initializes the search record and
returns the first entry in the table (or NULL if the table is
@@ -207,9 +219,10 @@ NULL if the end of the table has been reached.
A call to \fBTcl_FirstHashEntry\fR followed by calls to
\fBTcl_NextHashEntry\fR will return each of the entries in
the table exactly once, in an arbitrary order.
-It is unadvisable to modify the structure of the table, e.g.
-by creating or deleting entries, while the search is in
-progress.
+It is inadvisable to modify the structure of the table, e.g.
+by creating or deleting entries, while the search is in progress,
+with the exception of deleting the entry returned by
+\fBTcl_FirstHashEntry\fR or \fBTcl_NextHashEntry\fR.
.PP
\fBTcl_HashStats\fR returns a dynamically-allocated string with
overall information about a hash table, such as the number of
@@ -228,10 +241,10 @@ to any of the fields of any of the hash-related data structures;
use the procedures and macros defined here.
.SH "THE TCL_HASHKEYTYPE STRUCTURE"
.PP
-Extension writers can define new hash key types by defining four
-procedures, initializing a Tcl_HashKeyType structure to describe
-the type, and calling \fBTcl_InitCustomHashTable\fR.
-The \fBTcl_HashKeyType\fR structure is defined as follows:
+Extension writers can define new hash key types by defining four procedures,
+initializing a \fBTcl_HashKeyType\fR structure to describe the type, and
+calling \fBTcl_InitCustomHashTable\fR. The \fBTcl_HashKeyType\fR structure is
+defined as follows:
.CS
typedef struct Tcl_HashKeyType {
int \fIversion\fR;
@@ -243,61 +256,71 @@ typedef struct Tcl_HashKeyType {
} Tcl_HashKeyType;
.CE
.PP
-The \fIversion\fR member is the version of the table. If this
-structure is extended in future then the version can be used
-to distinguish between different structures. It should be set
-to \fBTCL_HASH_KEY_TYPE_VERSION\fR.
+The \fIversion\fR member is the version of the table. If this structure is
+extended in future then the version can be used to distinguish between
+different structures. It should be set to \fBTCL_HASH_KEY_TYPE_VERSION\fR.
.PP
-The \fIflags\fR member is one or more of the following values OR'ed together:
+The \fIflags\fR member is 0 or one or more of the following values OR'ed
+together:
.IP \fBTCL_HASH_KEY_RANDOMIZE_HASH\fR 25
-There are some things, pointers for example which don't hash well
-because they do not use the lower bits. If this flag is set then the
-hash table will attempt to rectify this by randomising the bits and
-then using the upper N bits as the index into the table.
+There are some things, pointers for example which do not hash well because
+they do not use the lower bits. If this flag is set then the hash table will
+attempt to rectify this by randomizing the bits and then using the upper N
+bits as the index into the table.
+.IP \fBTCL_HASH_KEY_SYSTEM_HASH\fR 25
+.VS 8.5
+This flag forces Tcl to use the memory allocation procedures provided by the
+operating system when allocating and freeing memory used to store the hash
+table data structures, and not any of Tcl's own customized memory allocation
+routines. This is important if the hash table is to be used in the
+implementation of a custom set of allocation routines, or something that a
+custom set of allocation routines might depend on, in order to avoid any
+circular dependency.
+.VE 8.5
.PP
-The \fIhashKeyProc\fR member contains the address of a function
-called to calculate a hash value for the key.
+The \fIhashKeyProc\fR member contains the address of a function called to
+calculate a hash value for the key.
.CS
typedef unsigned int (Tcl_HashKeyProc) (
- Tcl_HashTable *\fItablePtr\fR,
- VOID *\fIkeyPtr\fR);
+ Tcl_HashTable *\fItablePtr\fR,
+ void *\fIkeyPtr\fR);
.CE
-If this is NULL then \fIkeyPtr\fR is used and
+If this is NULL then \fIkeyPtr\fR is used and
\fBTCL_HASH_KEY_RANDOMIZE_HASH\fR is assumed.
.PP
-The \fIcompareKeysProc\fR member contains the address of a function
-called to compare two keys.
+The \fIcompareKeysProc\fR member contains the address of a function called to
+compare two keys.
.CS
-typedef int (Tcl_CompareHashKeysProc) (VOID *\fIkeyPtr\fR,
- Tcl_HashEntry *\fIhPtr\fR);
+typedef int (Tcl_CompareHashKeysProc) (
+ void *\fIkeyPtr\fR,
+ Tcl_HashEntry *\fIhPtr\fR);
.CE
-If this is NULL then the \fIkeyPtr\fR pointers are compared.
-If the keys don't match then the function returns 0, otherwise
-it returns 1.
+If this is NULL then the \fIkeyPtr\fR pointers are compared. If the keys do
+not match then the function returns 0, otherwise it returns 1.
.PP
-The \fIallocEntryProc\fR member contains the address of a function
-called to allocate space for an entry and initialise the key.
+The \fIallocEntryProc\fR member contains the address of a function called to
+allocate space for an entry and initialize the key and clientData.
.CS
typedef Tcl_HashEntry *(Tcl_AllocHashEntryProc) (
- Tcl_HashTable *\fItablePtr\fR, VOID *\fIkeyPtr\fR);
+ Tcl_HashTable *\fItablePtr\fR,
+ void *\fIkeyPtr\fR);
.CE
If this is NULL then Tcl_Alloc is used to allocate enough space for a
-Tcl_HashEntry and the key pointer is assigned to key.oneWordValue.
-String keys and array keys use this function to allocate enough
-space for the entry and the key in one block, rather than doing
-it in two blocks. This saves space for a pointer to the key from
-the entry and another memory allocation. Tcl_Obj * keys use this
-function to allocate enough space for an entry and increment the
-reference count on the object.
-If
+Tcl_HashEntry, the key pointer is assigned to key.oneWordValue and the
+clientData is set to NULL. String keys and array keys use this function to
+allocate enough space for the entry and the key in one block, rather than
+doing it in two blocks. This saves space for a pointer to the key from the
+entry and another memory allocation. Tcl_Obj* keys use this function to
+allocate enough space for an entry and increment the reference count on the
+object.
.PP
-The \fIfreeEntryProc\fR member contains the address of a function
-called to free space for an entry.
+The \fIfreeEntryProc\fR member contains the address of a function called to
+free space for an entry.
.CS
typedef void (Tcl_FreeHashEntryProc) (Tcl_HashEntry *\fIhPtr\fR);
.CE
-If this is NULL then Tcl_Free is used to free the space for the
-entry. Tcl_Obj * keys use this function to decrement the
-reference count on the object.
+If this is NULL then Tcl_Free is used to free the space for the entry.
+Tcl_Obj* keys use this function to decrement the reference count on the
+object.
.SH KEYWORDS
hash table, key, lookup, search, value
diff --git a/doc/Init.3 b/doc/Init.3
index e78423e..f421479 100644
--- a/doc/Init.3
+++ b/doc/Init.3
@@ -14,17 +14,16 @@ Tcl_Init \- find and source initialization script
int
\fBTcl_Init\fR(\fIinterp\fR)
.SH ARGUMENTS
+.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Interpreter to initialize.
.BE
.SH DESCRIPTION
.PP
-\fBTcl_Init\fR is a helper procedure that finds and \fBsource\fR's the
+\fBTcl_Init\fR is a helper procedure that finds and \fBsource\fRs the
\fBinit.tcl\fR script, which should exist somewhere on the Tcl library
-path. On Macintosh systems, it additionally checks for an \fBInit\fR
-resource and sources the contents of that resource if \fBinit.tcl\fR
-cannot be found.
+path.
.PP
\fBTcl_Init\fR is typically called from \fBTcl_AppInit\fR procedures.
diff --git a/doc/InitStubs.3 b/doc/InitStubs.3
index 2cfbb70..318c564 100644
--- a/doc/InitStubs.3
+++ b/doc/InitStubs.3
@@ -13,13 +13,13 @@ Tcl_InitStubs \- initialize the Tcl stubs mechanism
.nf
\fB#include <tcl.h>\fR
.sp
-CONST char *
+const char *
\fBTcl_InitStubs\fR(\fIinterp, version, exact\fR)
.SH ARGUMENTS
-.AS Tcl_Interp *interp in
+.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Tcl interpreter handle.
-.AP "CONST char" *version in
+.AP "const char" *version in
A version string consisting of one or more decimal numbers
separated by dots.
.AP int exact in
@@ -59,8 +59,8 @@ steps:
Call \fBTcl_InitStubs\fR in the extension before calling any other
Tcl functions.
.IP 2) 5
-Define the USE_TCL_STUBS symbol. Typically, you would include the
--DUSE_TCL_STUBS flag when compiling the extension.
+Define the \fBUSE_TCL_STUBS\fR symbol. Typically, you would include the
+\fB\-DUSE_TCL_STUBS\fR flag when compiling the extension.
.IP 3) 5
Link the extension with the Tcl stubs library instead of the standard
Tcl library. On Unix platforms, the library name is
diff --git a/doc/IntObj.3 b/doc/IntObj.3
index 15b6bd9..5cf677d 100644
--- a/doc/IntObj.3
+++ b/doc/IntObj.3
@@ -5,10 +5,10 @@
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
-.TH Tcl_IntObj 3 8.0 Tcl "Tcl Library Procedures"
+.TH Tcl_IntObj 3 8.5 Tcl "Tcl Library Procedures"
.BS
.SH NAME
-Tcl_NewIntObj, Tcl_NewLongObj, Tcl_NewWideIntObj, Tcl_SetIntObj, Tcl_SetLongObj, Tcl_SetWideIntObj, Tcl_GetIntFromObj, Tcl_GetLongFromObj, Tcl_GetWideIntFromObj \- manipulate Tcl objects as integers and wide integers
+Tcl_NewIntObj, Tcl_NewLongObj, Tcl_NewWideIntObj, Tcl_SetIntObj, Tcl_SetLongObj, Tcl_SetWideIntObj, Tcl_GetIntFromObj, Tcl_GetLongFromObj, Tcl_GetWideIntFromObj, Tcl_NewBignumObj, Tcl_SetBignumObj, Tcl_GetBignumFromObj, Tcl_TakeBignumFromObj \- manipulate Tcl objects as integer values
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -19,18 +19,14 @@ Tcl_Obj *
Tcl_Obj *
\fBTcl_NewLongObj\fR(\fIlongValue\fR)
.sp
-.VS 8.4
Tcl_Obj *
\fBTcl_NewWideIntObj\fR(\fIwideValue\fR)
-.VE 8.4
.sp
\fBTcl_SetIntObj\fR(\fIobjPtr, intValue\fR)
.sp
\fBTcl_SetLongObj\fR(\fIobjPtr, longValue\fR)
.sp
-.VS 8.4
\fBTcl_SetWideIntObj\fR(\fIobjPtr, wideValue\fR)
-.VE 8.4
.sp
int
\fBTcl_GetIntFromObj\fR(\fIinterp, objPtr, intPtr\fR)
@@ -38,110 +34,127 @@ int
int
\fBTcl_GetLongFromObj\fR(\fIinterp, objPtr, longPtr\fR)
.sp
-.VS 8.4
int
\fBTcl_GetWideIntFromObj\fR(\fIinterp, objPtr, widePtr\fR)
-.VE 8.4
+.sp
+.sp
+.VS 8.5
+\fB#include <tclTomMath.h>\fR
+.sp
+Tcl_Obj *
+\fBTcl_NewBignumObj\fR(\fIbigValue\fR)
+.sp
+\fBTcl_SetBignumObj\fR(\fIobjPtr, bigValue\fR)
+.sp
+int
+\fBTcl_GetBignumFromObj\fR(\fIinterp, objPtr, bigValue\fR)
+.sp
+int
+\fBTcl_TakeBignumFromObj\fR(\fIinterp, objPtr, bigValue\fR)
+.sp
+int
+\fBTcl_InitBignumFromDouble\fR(\fIinterp, doubleValue, bigValue\fR)
+.VE 8.5
.SH ARGUMENTS
-.AS Tcl_WideInt *interp
+.AS Tcl_WideInt doubleValue in/out
.AP int intValue in
-Integer value used to initialize or set an integer object.
+Integer value used to initialize or set a Tcl object.
.AP long longValue in
-Long integer value used to initialize or set an integer object.
+Long integer value used to initialize or set a Tcl object.
.AP Tcl_WideInt wideValue in
-.VS 8.4
-Wide integer value (minimum 64-bits wide where supported by the
-compiler) used to initialize or set a wide integer object.
-.VE 8.4
+Wide integer value used to initialize or set a Tcl object.
.AP Tcl_Obj *objPtr in/out
-For \fBTcl_SetIntObj\fR, \fBTcl_SetLongObj\fR, and
-.VS 8.4
-\fBTcl_SetWideIntObj\fR, this points to the object to be converted to
-integer type. For \fBTcl_GetIntFromObj\fR, \fBTcl_GetLongFromObj\fR,
-and \fBTcl_GetWideIntFromObj\fR, this refers to the object from which
-to get an integer or long integer value; if \fIobjPtr\fR does not
-already point to an integer object (or a wide integer object in the
-case of \fBTcl_SetWideIntObj\fR and \fBTcl_GetWideIntFromObj\fR,) an
-.VE 8.4
-attempt will be made to convert it to one.
+For \fBTcl_SetIntObj\fR, \fBTcl_SetLongObj\fR, \fBTcl_SetWideIntObj\fR,
+and \fBTcl_SetBignumObj\fR, this points to the object in which to store an
+integral value. For \fBTcl_GetIntFromObj\fR, \fBTcl_GetLongFromObj\fR,
+\fBTcl_GetWideIntFromObj\fR, \fBTcl_GetBignumFromObj\fR, and
+\fBTcl_TakeBignumFromObj\fR, this refers to the object from which
+to retrieve an integral value.
.AP Tcl_Interp *interp in/out
-If an error occurs during conversion,
-an error message is left in the interpreter's result object
-unless \fIinterp\fR is NULL.
+When non-NULL, an error message is left here when integral value
+retrieval fails.
.AP int *intPtr out
-Points to place to store the integer value
-obtained by \fBTcl_GetIntFromObj\fR from \fIobjPtr\fR.
+Points to place to store the integer value retrieved from \fIobjPtr\fR.
.AP long *longPtr out
-Points to place to store the long integer value
-obtained by \fBTcl_GetLongFromObj\fR from \fIobjPtr\fR.
+Points to place to store the long integer value retrieved from \fIobjPtr\fR.
.AP Tcl_WideInt *widePtr out
-.VS 8.4
-Points to place to store the wide integer value
-obtained by \fBTcl_GetWideIntFromObj\fR from \fIobjPtr\fR.
-.VE 8.4
+Points to place to store the wide integer value retrieved from \fIobjPtr\fR.
+.AP mp_int *bigValue in/out
+.VS 8.5
+Points to a multi-precision integer structure declared by the LibTomMath
+library.
+.VE 8.5
+.AP double doubleValue in
+.VS 8.5
+Double value from which the integer part is determined and
+used to initialize a multi-precision integer value.
+.VE 8.5
.BE
.SH DESCRIPTION
.PP
-These procedures are used to create, modify, and read
-integer and wide integer Tcl objects from C code.
-\fBTcl_NewIntObj\fR, \fBTcl_NewLongObj\fR,
-\fBTcl_SetIntObj\fR, and \fBTcl_SetLongObj\fR
-create a new object of integer type
-or modify an existing object to have integer type,
-.VS 8.4
-and \fBTcl_NewWideIntObj\fR and \fBTcl_SetWideIntObj\fR create a new
-object of wide integer type or modify an existing object to have wide
-integer type.
-.VE 8.4
-\fBTcl_NewIntObj\fR and \fBTcl_SetIntObj\fR set the object to have the
-integer value given by \fIintValue\fR,
-\fBTcl_NewLongObj\fR and \fBTcl_SetLongObj\fR
-set the object to have the
-long integer value given by \fIlongValue\fR,
-.VS 8.4
-and \fBTcl_NewWideIntObj\fR and \fBTcl_SetWideIntObj\fR set the object
-to have the wide integer value given by \fIwideValue\fR.
-\fBTcl_NewIntObj\fR, \fBTcl_NewLongObj\fR and \fBTcl_NewWideIntObj\fR
-return a pointer to a newly created object with reference count zero.
-These procedures set the object's type to be integer
-and assign the integer value to the object's internal representation
-\fIlongValue\fR or \fIwideValue\fR member (as appropriate).
-\fBTcl_SetIntObj\fR, \fBTcl_SetLongObj\fR
-and \fBTcl_SetWideIntObj\fR
-.VE 8.4
-invalidate any old string representation and,
-if the object is not already an integer object,
-free any old internal representation.
+.VS 8.5
+These procedures are used to create, modify, and read Tcl objects
+that hold integral values.
.PP
-\fBTcl_GetIntFromObj\fR and \fBTcl_GetLongFromObj\fR
-attempt to return an integer value from the Tcl object \fIobjPtr\fR,
-.VS 8.4
-and \fBTcl_GetWideIntFromObj\fR attempts to return a wide integer
-value from the Tcl object \fIobjPtr\fR.
-If the object is not already an integer object,
-or a wide integer object in the case of \fBTcl_GetWideIntFromObj\fR
-.VE 8.4
-they will attempt to convert it to one.
-If an error occurs during conversion, they return \fBTCL_ERROR\fR
-and leave an error message in the interpreter's result object
-unless \fIinterp\fR is NULL.
-Also, if the long integer held in the object's internal representation
-\fIlongValue\fR member can not be represented in a (non-long) integer,
-\fBTcl_GetIntFromObj\fR returns \fBTCL_ERROR\fR
-and leaves an error message in the interpreter's result object
-unless \fIinterp\fR is NULL.
-Otherwise, all three procedures return \fBTCL_OK\fR and
-store the integer, long integer value
-.VS 8.4
-or wide integer in the address given by \fIintPtr\fR, \fIlongPtr\fR
-and \fIwidePtr\fR
-.VE 8.4
-respectively. If the object is not already an integer or wide integer
-object, the conversion will free any old internal representation.
-
+The different routines exist to accommodate different integral types in C
+with which values might be exchanged. The C integral types for which Tcl
+provides value exchange routines are \fBint\fR, \fBlong int\fR,
+\fBTcl_WideInt\fR, and \fBmp_int\fR. The \fBint\fR and \fBlong int\fR types
+are provided by the C language standard. The \fBTcl_WideInt\fR type is a
+typedef defined to be whatever signed integral type covers at least the
+64-bit integer range (-9223372036854775808 to 9223372036854775807). Depending
+on the platform and the C compiler, the actual type might be
+\fBlong int\fR, \fBlong long int\fR, \fBint64\fR, or something else.
+The \fBmp_int\fR type is a multiple-precision integer type defined
+by the LibTomMath multiple-precision integer library.
+.PP
+The \fBTcl_NewIntObj\fR, \fBTcl_NewLongObj\fR, \fBTcl_NewWideIntObj\fR,
+and \fBTcl_NewBignumObj\fR routines each create and return a new
+Tcl object initialized to the integral value of the argument. The
+returned Tcl object is unshared.
+.PP
+The \fBTcl_SetIntObj\fR, \fBTcl_SetLongObj\fR, \fBTcl_SetWideIntObj\fR,
+and \fBTcl_SetBignumObj\fR routines each set the value of an existing
+Tcl object pointed to by \fIobjPtr\fR to the integral value provided
+by the other argument. The \fIobjPtr\fR argument must point to an
+unshared Tcl object. Any attempt to set the value of a shared Tcl object
+violates Tcl's copy-on-write policy. Any existing string representation
+or internal representation in the unshared Tcl object will be freed
+as a consequence of setting the new value.
+.PP
+The \fBTcl_GetIntFromObj\fR, \fBTcl_GetLongFromObj\fR,
+\fBTcl_GetWideIntFromObj\fR, \fBTcl_GetBignumFromObj\fR, and
+\fBTcl_TakeBignumFromObj\fR routines attempt to retrieve an integral
+value of the appropriate type from the Tcl object \fIobjPtr\fR. If the
+attempt succeeds, then \fBTCL_OK\fR is returned, and the value is
+written to the storage provided by the caller. The attempt might
+fail if \fIobjPtr\fR does not hold an integral value, or if the
+value exceeds the range of the target type. If the attempt fails,
+then \fBTCL_ERROR\fR is returned, and if \fIinterp\fR is non-NULL,
+an error message is left in \fIinterp\fR. The \fBTcl_ObjType\fR
+of \fIobjPtr\fR may be changed to make subsequent calls to the
+same routine more efficient. Unlike the other functions,
+\fBTcl_TakeBignumFromObj\fR may set the content of the Tcl object
+\fIobjPtr\fR to an empty string in the process of retrieving the
+multiple-precision integer value.
+.PP
+The choice between \fBTcl_GetBignumFromObj\fR and
+\fBTcl_TakeBignumFromObj\fR is governed by how the caller will
+continue to use \fIobjPtr\fR. If after the \fBmp_int\fR value
+is retrieved from \fIobjPtr\fR, the caller will make no more
+use of \fIobjPtr\fR, then using \fBTcl_TakeBignumFromObj\fR
+permits Tcl to detect when an unshared \fIobjPtr\fR permits the
+value to be moved instead of copied, which should be more efficient.
+If anything later in the caller requires
+\fIobjPtr\fR to continue to hold the same value, then
+\fBTcl_GetBignumFromObj\fR must be chosen.
+.PP
+The \fBTcl_InitBignumFromDouble\fR routine is a utility procedure
+that extracts the integer part of \fIdoubleValue\fR and stores that
+integer value in the \fBmp_int\fR value \fIbigValue\fR.
+.VE 8.5
.SH "SEE ALSO"
Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_GetObjResult
-
.SH KEYWORDS
integer, integer object, integer type, internal representation, object, object type, string representation
diff --git a/doc/Interp.3 b/doc/Interp.3
index 7d1f515..0b1de03 100644
--- a/doc/Interp.3
+++ b/doc/Interp.3
@@ -15,9 +15,9 @@ Tcl_Interp \- client-visible fields of interpreter structures
\fB#include <tcl.h>\fR
.sp
typedef struct {
- char *\fIresult\fR;
- Tcl_FreeProc *\fIfreeProc\fR;
- int \fIerrorLine\fR;
+ char *\fIresult\fR;
+ Tcl_FreeProc *\fIfreeProc\fR;
+ int \fIerrorLine\fR;
} Tcl_Interp;
typedef void Tcl_FreeProc(char *\fIblockPtr\fR);
@@ -28,17 +28,23 @@ typedef void Tcl_FreeProc(char *\fIblockPtr\fR);
The \fBTcl_CreateInterp\fR procedure returns a pointer to a Tcl_Interp
structure. This pointer is then passed into other Tcl procedures
to process commands in the interpreter and perform other operations
-on the interpreter. Interpreter structures contain many many fields
+on the interpreter. Interpreter structures contain many fields
that are used by Tcl, but only three that may be accessed by
clients: \fIresult\fR, \fIfreeProc\fR, and \fIerrorLine\fR.
.PP
+.VS 8.5
+\fBNote that access to all three fields, \fIresult\fB, \fIfreeProc\fB and
+\fIerrorLine\fB is deprecated.\fR Use \fBTcl_SetResult\fR,
+\fBTcl_GetResult\fR, and \fBTcl_GetReturnOptions\fR instead.
+.VE 8.5
+.PP
The \fIresult\fR and \fIfreeProc\fR fields are used to return
results or error messages from commands.
This information is returned by command procedures back to \fBTcl_Eval\fR,
and by \fBTcl_Eval\fR back to its callers.
The \fIresult\fR field points to the string that represents the
result or error message, and the \fIfreeProc\fR field tells how
-to dispose of the storage for the string when it isn't needed anymore.
+to dispose of the storage for the string when it is not needed anymore.
The easiest way for command procedures to manipulate these
fields is to call procedures like \fBTcl_SetResult\fR
or \fBTcl_AppendResult\fR; they
@@ -55,7 +61,6 @@ should point to an empty string.
Normally, results are assumed to be statically allocated,
which means that the contents will not change before the next time
\fBTcl_Eval\fR is called or some other command procedure is invoked.
-.VS
In this case, the \fIfreeProc\fR field must be zero.
Alternatively, a command procedure may dynamically
allocate its return value (e.g. using \fBTcl_Alloc\fR)
@@ -64,7 +69,6 @@ In this case, the command procedure must also set \fIinterp->freeProc\fR
to the address of a procedure that can free the value, or \fBTCL_DYNAMIC\fR
if the storage was allocated directly by Tcl or by a call to
\fBTcl_Alloc\fR.
-.VE
If \fIinterp->freeProc\fR is non-zero, then Tcl will call \fIfreeProc\fR
to free the space pointed to by \fIinterp->result\fR before it
invokes the next command.
@@ -76,10 +80,8 @@ macro should be used for this purpose).
\fIFreeProc\fR should have arguments and result that match the
\fBTcl_FreeProc\fR declaration above: it receives a single
argument which is a pointer to the result value to free.
-.VS
In most applications \fBTCL_DYNAMIC\fR is the only non-zero value ever
used for \fIfreeProc\fR.
-.VE
However, an application may store a different procedure address
in \fIfreeProc\fR in order to use an alternate memory allocator
or in order to do other cleanup when the result memory is freed.
diff --git a/doc/Limit.3 b/doc/Limit.3
new file mode 100644
index 0000000..928ebe1
--- /dev/null
+++ b/doc/Limit.3
@@ -0,0 +1,194 @@
+'\"
+'\" Copyright (c) 2004 Donal K. Fellows
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.so man.macros
+.TH Tcl_LimitCheck 3 8.5 Tcl "Tcl Library Procedures"
+.BS
+.SH NAME
+Tcl_LimitAddHandler, Tcl_LimitCheck, Tcl_LimitExceeded, Tcl_LimitGetCommands, Tcl_LimitGetGranularity, Tcl_LimitGetTime, Tcl_LimitReady, Tcl_LimitRemoveHandler, Tcl_LimitSetCommands, Tcl_LimitSetGranularity, Tcl_LimitSetTime, Tcl_LimitTypeEnabled, Tcl_LimitTypeExceeded, Tcl_LimitTypeReset, Tcl_LimitTypeSet \- manage and check resource limits on interpreters
+.SH SYNOPSIS
+.nf
+\fB#include <tcl.h>\fR
+.sp
+int
+\fBTcl_LimitCheck\fR(\fIinterp\fR)
+.sp
+int
+\fBTcl_LimitReady\fR(\fIinterp\fR)
+.sp
+int
+\fBTcl_LimitExceeded\fR(\fIinterp\fR)
+.sp
+int
+\fBTcl_LimitTypeExceeded\fR(\fIinterp, type\fR)
+.sp
+int
+\fBTcl_LimitTypeEnabled\fR(\fIinterp, type\fR)
+.sp
+void
+\fBTcl_LimitTypeSet\fR(\fIinterp, type\fR)
+.sp
+void
+\fBTcl_LimitTypeReset\fR(\fIinterp, type\fR)
+.sp
+int
+\fBTcl_LimitGetCommands\fR(\fIinterp\fR)
+.sp
+void
+\fBTcl_LimitSetCommands\fR(\fIinterp, commandLimit\fR)
+.sp
+void
+\fBTcl_LimitGetTime\fR(\fIinterp, timeLimitPtr\fR)
+.sp
+void
+\fBTcl_LimitSetTime\fR(\fIinterp, timeLimitPtr\fR)
+.sp
+int
+\fBTcl_LimitGetGranularity\fR(\fIinterp, type\fR)
+.sp
+void
+\fBTcl_LimitSetGranularity\fR(\fIinterp, type, granularity\fR)
+.sp
+void
+\fBTcl_LimitAddHandler\fR(\fIinterp, type, handlerProc, clientData, deleteProc\fR)
+.sp
+void
+\fBTcl_LimitRemoveHandler\fR(\fIinterp, type, handlerProc, clientData\fR)
+.SH ARGUMENTS
+.AS Tcl_LimitHandlerDeleteProc commandLimit in/out
+.AP Tcl_Interp *interp in
+Interpreter that the limit being managed applies to or that will have
+its limits checked.
+.AP int type in
+The type of limit that the operation refers to. This must be either
+\fBTCL_LIMIT_COMMANDS\fR or \fBTCL_LIMIT_TIME\fR.
+.AP int commandLimit in
+The maximum number of commands (as reported by \fBinfo cmdcount\fR)
+that may be executed in the interpreter.
+.AP Tcl_Time *timeLimitPtr in/out
+A pointer to a structure that will either have the new time limit read
+from (\fBTcl_LimitSetTime\fR) or the current time limit written to
+(\fBTcl_LimitGetTime\fR).
+.AP int granularity in
+Divisor that indicates how often a particular limit should really be
+checked. Must be at least 1.
+.AP Tcl_LimitHandlerProc *handlerProc in
+Function to call when a particular limit is exceeded. If the
+\fIhandlerProc\fR removes or raises the limit during its processing,
+the limited interpreter will be permitted to continue to process after
+the handler returns. Many handlers may be attached to the same
+interpreter limit; their order of execution is not defined, and they
+must be identified by \fIhandlerProc\fR and \fIclientData\fR when they
+are deleted.
+.AP ClientData clientData in
+Arbitrary pointer-sized word used to pass some context to the
+\fIhandlerProc\fR function.
+.AP Tcl_LimitHandlerDeleteProc *deleteProc in
+Function to call whenever a handler is deleted. May be NULL if the
+\fIclientData\fR requires no deletion.
+.BE
+
+.SH DESCRIPTION
+.PP
+Tcl's interpreter resource limit subsystem allows for close control
+over how much computation time a script may use, and is useful for
+cases where a program is divided into multiple pieces where some parts
+are more trusted than others (e.g. web application servers).
+.PP
+Every interpreter may have a limit on the wall-time for execution, and
+a limit on the number of commands that the interpreter may execute.
+Since checking of these limits is potentially expensive (especially
+the time limit), each limit also has a checking granularity, which is
+a divisor for an internal count of the number of points in the core
+where a check may be performed (which is immediately before executing
+a command and at an unspecified frequency between running commands,
+which can happen in empty-bodied \fBwhile\fR loops).
+.PP
+The final component of the limit engine is a callback scheme which
+allows for notifications of when a limit has been exceeded. These
+callbacks can just provide logging, or may allocate more resources to
+the interpreter to permit it to continue processing longer.
+.PP
+When a limit is exceeded (and the callbacks have run; the order of
+execution of the callbacks is unspecified) execution in the limited
+interpreter is stopped by raising an error and setting a flag that
+prevents the \fBcatch\fR command in that interpreter from trapping
+that error. It is up to the context that started execution in that
+interpreter (typically a master interpreter) to handle the error.
+.SH "LIMIT CHECKING API"
+.PP
+To check the resource limits for an interpreter, call
+\fBTcl_LimitCheck\fR, which returns \fBTCL_OK\fR if the limit was not
+exceeded (after processing callbacks) and \fBTCL_ERROR\fR if the limit was
+exceeded (in which case an error message is also placed in the
+interpreter result). That function should only be called when
+\fBTcl_LimitReady\fR returns non-zero so that granularity policy is
+enforced. This API is designed to be similar in usage to
+\fBTcl_AsyncReady\fR and \fBTcl_AsyncInvoke\fR.
+.PP
+When writing code that may behave like \fBcatch\fR in respect of
+errors, you should only trap an error if \fBTcl_LimitExceeded\fR
+returns zero. If it returns non-zero, the interpreter is in a
+limit-exceeded state and errors should be allowed to propagate to the
+calling context. You can also check whether a particular type of
+limit has been exceeded using \fBTcl_LimitTypeExceeded\fR.
+.SH "LIMIT CONFIGURATION"
+.PP
+To check whether a limit has been set (but not whether it has actually
+been exceeded) on an interpreter, call \fBTcl_LimitTypeEnabled\fR with
+the type of limit you want to check. To enable a particular limit
+call \fBTcl_LimitTypeSet\fR, and to disable a limit call
+\fBTcl_LimitTypeReset\fR.
+.PP
+The level of a command limit may be set using
+\fBTcl_LimitSetCommands\fR, and retrieved using
+\fBTcl_LimitGetCommands\fR. Similarly for a time limit with
+\fBTcl_LimitSetTime\fR and \fBTcl_LimitGetTime\fR respectively, but
+with that API the time limit is copied from and to the Tcl_Time
+structure that the \fItimeLimitPtr\fR argument points to.
+.PP
+The checking granularity for a particular limit may be set using
+\fBTcl_LimitSetGranularity\fR and retrieved using
+\fBTcl_LimitGetGranularity\fR. Note that granularities must always be
+positive.
+.SS "LIMIT CALLBACKS"
+.PP
+To add a handler callback to be invoked when a limit is exceeded, call
+\fBTcl_LimitAddHandler\fR. The \fIhandlerProc\fR argument describes
+the function that will actually be called; it should have the
+following prototype:
+.PP
+.CS
+typedef void Tcl_LimitHandlerProc(
+ ClientData \fIclientData\fR,
+ Tcl_Interp *\fIinterp\fR);
+.CE
+.PP
+The \fIclientData\fR argument to the handler will be whatever is
+passed to the \fIclientData\fR argument to \fBTcl_LimitAddHandler\fR,
+and the \fIinterp\fR is the interpreter that had its limit exceeded.
+.PP
+The \fIdeleteProc\fR argument to \fBTcl_LimitAddHandler\fR is a
+function to call to delete the \fIclientData\fR value. It may be
+\fBTCL_STATIC\fR or NULL if no deletion action is necessary, or
+\fBTCL_DYNAMIC\fR if all that is necessary is to free the structure with
+\fBTcl_Free\fR. Otherwise, it should refer to a function with the
+following prototype:
+.PP
+.CS
+typedef void Tcl_LimitHandlerDeleteProc(
+ ClientData \fIclientData\fR);
+.CE
+.PP
+A limit handler may be deleted using \fBTcl_LimitRemoveHandler\fR; the
+handler removed will be the first one found (out of the handlers added
+with \fBTcl_LimitAddHandler\fR) with exactly matching \fItype\fR,
+\fIhandlerProc\fR and \fIclientData\fR arguments. This function
+always invokes the \fIdeleteProc\fR on the \fIclientData\fR (unless
+the \fIdeleteProc\fR was NULL or \fBTCL_STATIC\fR).
+
+.SH KEYWORDS
+interpreter, resource, limit, commands, time, callback
diff --git a/doc/LinkVar.3 b/doc/LinkVar.3
index a1dfcca..6361fb4 100644
--- a/doc/LinkVar.3
+++ b/doc/LinkVar.3
@@ -25,17 +25,24 @@ int
.AP Tcl_Interp *interp in
Interpreter that contains \fIvarName\fR.
Also used by \fBTcl_LinkVar\fR to return error messages.
-.AP "CONST char" *varName in
-Name of global variable.
+.AP "const char" *varName in
+Name of global variable.
.AP char *addr in
Address of C variable that is to be linked to \fIvarName\fR.
.AP int type in
-Type of C variable. Must be one of TCL_LINK_INT, TCL_LINK_DOUBLE,
-.VS 8.4
-TCL_LINK_WIDE_INT,
-.VE 8.4
-TCL_LINK_BOOLEAN, or TCL_LINK_STRING, optionally OR'ed with
-TCL_LINK_READ_ONLY to make Tcl variable read-only.
+Type of C variable. Must be one of \fBTCL_LINK_INT\fR,
+.VS 8.5
+\fBTCL_LINK_UINT\fR, \fBTCL_LINK_CHAR\fR, \fBTCL_LINK_UCHAR\fR,
+\fBTCL_LINK_SHORT\fR, \fBTCL_LINK_USHORT\fR, \fBTCL_LINK_LONG\fR,
+\fBTCL_LINK_ULONG\fR,
+.VE 8.5
+\fBTCL_LINK_WIDE_INT\fR,
+.VS 8.5
+\fBTCL_LINK_WIDE_UINT\fR, \fBTCL_LINK_FLOAT\fR,
+.VE 8.5
+\fBTCL_LINK_DOUBLE\fR, \fBTCL_LINK_BOOLEAN\fR, or
+\fBTCL_LINK_STRING\fR, optionally OR'ed with \fBTCL_LINK_READ_ONLY\fR
+to make Tcl variable read-only.
.BE
.SH DESCRIPTION
@@ -46,14 +53,14 @@ given by \fIaddr\fR.
Whenever the Tcl variable is read the value of the C variable will
be returned, and whenever the Tcl variable is written the C
variable will be updated to have the same value.
-\fBTcl_LinkVar\fR normally returns TCL_OK; if an error occurs
+\fBTcl_LinkVar\fR normally returns \fBTCL_OK\fR; if an error occurs
while setting up the link (e.g. because \fIvarName\fR is the
-name of array) then TCL_ERROR is returned and the interpreter's result
+name of array) then \fBTCL_ERROR\fR is returned and the interpreter's result
contains an error message.
.PP
The \fItype\fR argument specifies the type of the C variable,
and must have one of the following values, optionally OR'ed with
-TCL_LINK_READ_ONLY:
+\fBTCL_LINK_READ_ONLY\fR:
.TP
\fBTCL_LINK_INT\fR
The C variable is of type \fBint\fR.
@@ -61,6 +68,61 @@ Any value written into the Tcl variable must have a proper integer
form acceptable to \fBTcl_GetIntFromObj\fR; attempts to write
non-integer values into \fIvarName\fR will be rejected with
Tcl errors.
+.VS 8.5
+.TP
+\fBTCL_LINK_UINT\fR
+The C variable is of type \fBunsigned int\fR.
+Any value written into the Tcl variable must have a proper unsigned
+integer form acceptable to \fBTcl_GetWideIntFromObj\fR and in the
+platform's defined range for the \fBunsigned int\fR type; attempts to
+write non-integer values (or values outside the range) into
+\fIvarName\fR will be rejected with Tcl errors.
+.TP
+\fBTCL_LINK_CHAR\fR
+The C variable is of type \fBchar\fR.
+Any value written into the Tcl variable must have a proper integer
+form acceptable to \fBTcl_GetIntFromObj\fR and be in the range of the
+\fBchar\fR datatype; attempts to write non-integer or out-of-range
+values into \fIvarName\fR will be rejected with Tcl errors.
+.TP
+\fBTCL_LINK_UCHAR\fR
+The C variable is of type \fBunsigned char\fR.
+Any value written into the Tcl variable must have a proper unsigned
+integer form acceptable to \fBTcl_GetIntFromObj\fR and in the
+platform's defined range for the \fBunsigned char\fR type; attempts to
+write non-integer values (or values outside the range) into
+\fIvarName\fR will be rejected with Tcl errors.
+.TP
+\fBTCL_LINK_SHORT\fR
+The C variable is of type \fBshort\fR.
+Any value written into the Tcl variable must have a proper integer
+form acceptable to \fBTcl_GetIntFromObj\fR and be in the range of the
+\fBshort\fR datatype; attempts to write non-integer or out-of-range
+values into \fIvarName\fR will be rejected with Tcl errors.
+.TP
+\fBTCL_LINK_USHORT\fR
+The C variable is of type \fBunsigned short\fR.
+Any value written into the Tcl variable must have a proper unsigned
+integer form acceptable to \fBTcl_GetIntFromObj\fR and in the
+platform's defined range for the \fBunsigned short\fR type; attempts to
+write non-integer values (or values outside the range) into
+\fIvarName\fR will be rejected with Tcl errors.
+.TP
+\fBTCL_LINK_LONG\fR
+The C variable is of type \fBlong\fR.
+Any value written into the Tcl variable must have a proper integer
+form acceptable to \fBTcl_GetLongFromObj\fR; attempts to write
+non-integer or out-of-range
+values into \fIvarName\fR will be rejected with Tcl errors.
+.TP
+\fBTCL_LINK_ULONG\fR
+The C variable is of type \fBunsigned long\fR.
+Any value written into the Tcl variable must have a proper unsigned
+integer form acceptable to \fBTcl_GetWideIntFromObj\fR and in the
+platform's defined range for the \fBunsigned long\fR type; attempts to
+write non-integer values (or values outside the range) into
+\fIvarName\fR will be rejected with Tcl errors.
+.VE 8.5
.TP
\fBTCL_LINK_DOUBLE\fR
The C variable is of type \fBdouble\fR.
@@ -68,21 +130,44 @@ Any value written into the Tcl variable must have a proper real
form acceptable to \fBTcl_GetDoubleFromObj\fR; attempts to write
non-real values into \fIvarName\fR will be rejected with
Tcl errors.
+.VS 8.5
+.TP
+\fBTCL_LINK_FLOAT\fR
+The C variable is of type \fBfloat\fR.
+Any value written into the Tcl variable must have a proper real
+form acceptable to \fBTcl_GetDoubleFromObj\fR and must be within the
+range acceptable for a \fBfloat\fR; attempts to
+write non-real values (or values outside the range) into
+\fIvarName\fR will be rejected with Tcl errors.
+.VE 8.5
.TP
\fBTCL_LINK_WIDE_INT\fR
-.VS 8.4
The C variable is of type \fBTcl_WideInt\fR (which is an integer type
at least 64-bits wide on all platforms that can support it.)
Any value written into the Tcl variable must have a proper integer
form acceptable to \fBTcl_GetWideIntFromObj\fR; attempts to write
non-integer values into \fIvarName\fR will be rejected with
Tcl errors.
-.VE 8.4
+.VS 8.5
+.TP
+\fBTCL_LINK_WIDE_UINT\fR
+The C variable is of type \fBTcl_WideUInt\fR (which is an unsigned
+integer type at least 64-bits wide on all platforms that can support
+it.)
+Any value written into the Tcl variable must have a proper unsigned
+integer form acceptable to \fBTcl_GetWideIntFromObj\fR (it will be
+cast to unsigned);
+.\" FIXME! Use bignums instead.
+attempts to write non-integer values into \fIvarName\fR will be
+rejected with Tcl errors.
+.VE 8.5
.TP
\fBTCL_LINK_BOOLEAN\fR
The C variable is of type \fBint\fR.
-If its value is zero then it will read from Tcl as ``0'';
-otherwise it will read from Tcl as ``1''.
+If its value is zero then it will read from Tcl as
+.QW 0 ;
+otherwise it will read from Tcl as
+.QW 1 .
Whenever \fIvarName\fR is
modified, the C variable will be set to a 0 or 1 value.
Any value written into the Tcl variable must have a proper boolean
@@ -92,17 +177,16 @@ Tcl errors.
.TP
\fBTCL_LINK_STRING\fR
The C variable is of type \fBchar *\fR.
-.VS
If its value is not NULL then it must be a pointer to a string
allocated with \fBTcl_Alloc\fR or \fBckalloc\fR.
-.VE
Whenever the Tcl variable is modified the current C string will be
freed and new memory will be allocated to hold a copy of the variable's
new value.
If the C variable contains a NULL pointer then the Tcl variable
-will read as ``NULL''.
+will read as
+.QW NULL .
.PP
-If the TCL_LINK_READ_ONLY flag is present in \fItype\fR then the
+If the \fBTCL_LINK_READ_ONLY\fR flag is present in \fItype\fR then the
variable will be read-only from Tcl, so that its value can only be
changed by modifying the C variable.
Attempts to write the variable from Tcl will be rejected with errors.
diff --git a/doc/ListObj.3 b/doc/ListObj.3
index 2adea4e..443eafe 100644
--- a/doc/ListObj.3
+++ b/doc/ListObj.3
@@ -36,7 +36,7 @@ int
int
\fBTcl_ListObjReplace\fR(\fIinterp, listPtr, first, count, objc, objv\fR)
.SH ARGUMENTS
-.AS Tcl_Interp "*CONST objv[]" out
+.AS "Tcl_Obj *const" *elemListPtr in/out
.AP Tcl_Interp *interp in
If an error occurs while converting an object to be a list object,
an error message is left in the interpreter's result object
@@ -71,13 +71,11 @@ will insert into a new list object,
and \fBTcl_ListObjReplace\fR will insert into \fIlistPtr\fR.
For \fBTcl_SetListObj\fR,
the number of Tcl objects to insert into \fIobjPtr\fR.
-.VS
-.AP Tcl_Obj "*CONST\ objv[]" in
+.AP "Tcl_Obj *const" objv[] in
An array of pointers to objects.
\fBTcl_NewListObj\fR will insert these objects into a new list object
and \fBTcl_ListObjReplace\fR will insert them into an existing \fIlistPtr\fR.
Each object will become a separate list element.
-.VE
.AP int *intPtr out
Points to location where \fBTcl_ListObjLength\fR
stores the length of the list.
@@ -151,8 +149,9 @@ has reference count zero.
the elements in a list object. It returns the count by storing it in the
address \fIobjcPtr\fR. Similarly, it returns the array pointer by storing
it in the address \fIobjvPtr\fR.
-The memory pointed to is managed by Tcl and should not be freed by the
-caller.
+The memory pointed to is managed by Tcl and should not be freed or written
+to by the caller. If the list is empty, 0 is stored at \fIobjcPtr\fR
+and NULL at \fIobjvPtr\fR.
If \fIlistPtr\fR is not already a list object, \fBTcl_ListObjGetElements\fR
will attempt to convert it to one; if the conversion fails, it returns
\fBTCL_ERROR\fR and leaves an error message in the interpreter's result
@@ -219,27 +218,33 @@ it can be used to implement a number of list operations.
For example, the following code inserts the \fIobjc\fR objects
referenced by the array of object pointers \fIobjv\fR
just before the element \fIindex\fR of the list referenced by \fIlistPtr\fR:
+.PP
.CS
-result = Tcl_ListObjReplace(interp, listPtr, index, 0, objc, objv);
+result = Tcl_ListObjReplace(interp, listPtr, index, 0,
+ objc, objv);
.CE
+.PP
Similarly, the following code appends the \fIobjc\fR objects
referenced by the array \fIobjv\fR
to the end of the list \fIlistPtr\fR:
+.PP
.CS
result = Tcl_ListObjLength(interp, listPtr, &length);
if (result == TCL_OK) {
- result = Tcl_ListObjReplace(interp, listPtr, length, 0, objc, objv);
+ result = Tcl_ListObjReplace(interp, listPtr, length, 0,
+ objc, objv);
}
.CE
+.PP
The \fIcount\fR list elements starting at \fIfirst\fR can be deleted
by simply calling \fBTcl_ListObjReplace\fR
with a NULL \fIobjvPtr\fR:
+.PP
.CS
-result = Tcl_ListObjReplace(interp, listPtr, first, count, 0, NULL);
+result = Tcl_ListObjReplace(interp, listPtr, first, count,
+ 0, NULL);
.CE
-
.SH "SEE ALSO"
Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_GetObjResult
-
.SH KEYWORDS
append, index, insert, internal representation, length, list, list object, list type, object, object type, replace, string representation
diff --git a/doc/Macintosh.3 b/doc/Macintosh.3
deleted file mode 100644
index cd97578..0000000
--- a/doc/Macintosh.3
+++ /dev/null
@@ -1,109 +0,0 @@
-'\"
-'\" Copyright (c) 1997-1998 Sun Microsystems, Inc.
-'\"
-'\" See the file "license.terms" for information on usage and redistribution
-'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-'\"
-.so man.macros
-.TH Tcl_MacSetEventProc 3 "8.1" Tcl "Tcl Library Procedures"
-.BS
-.SH NAME
-Tcl_MacSetEventProc, Tcl_MacConvertTextResource, Tcl_MacEvalResource, Tcl_MacFindResource, Tcl_GetOSTypeFromObj, Tcl_SetOSTypeObj, Tcl_NewOSTypeObj \- procedures to handle Macintosh resources and other Macintosh specifics
-.SH SYNOPSIS
-.nf
-\fB#include <tcl.h>\fR
-.sp
-int
-\fBTcl_MacEvalResource\fR(\fIinterp, resourceName, resourceNumber, fileName\fR)
-.sp
-char*
-\fBTcl_MacConvertTextResource\fR(\fIresource\fR)
-.sp
-Handle
-\fBTcl_MacFindResource\fR(\fIinterp, resourceType, resourceName, resourceNumber, resFileRef, releaseIt\fR)
-.sp
-Tcl_Obj*
-\fBTcl_NewOSTypeObj\fR(\fInewOSType\fR)
-.sp
-void
-\fBTcl_SetOSTypeObj\fR(\fIobjPtr, newOSType\fR)
-.sp
-int
-\fBTcl_GetOSTypeFromObj\fR(\fIinterp, objPtr, osTypePtr\fR)
-.sp
-void
-\fBTcl_MacSetEventProc\fR(\fIprocPtr\fR)
-.SH ARGUMENTS
-.AP Tcl_Interp *interp in
-Interpreter to use for error reporting, or NULL if no error reporting is
-desired.
-.AP "CONST char" *resourceName in
-Name of TEXT resource to source, NULL if number should be used.
-.AP int resourceNumber in
-Resource id of source.
-.AP "CONST char" *fileName in
-Name of file to process. NULL if application resource.
-.AP Handle resource in
-Handle to TEXT resource.
-.AP long resourceType in
-Type of resource to load.
-.AP "CONST char" *resFileRef in
-Registered resource file reference, NULL if searching all open resource files.
-.AP int *releaseIt out
-Should we release this resource when done.
-.AP int newOSType in
-Int used to initialize the new object or set the object's value.
-.AP Tcl_Obj *objPtr in
-Object whose internal representation is to be set or retrieved.
-.AP osTypePtr out
-Place to store the resulting integer.
-.AP Tcl_MacConvertEventPtr procPtr in
-Reference to the new function to handle all incoming Mac events.
-
-.BE
-.SH INTRODUCTION
-.PP
-The described routines are used to implement the Macintosh specific
-\fBresource\fR command and the Mac specific notifier.. They manipulate
-or use Macintosh resources and provide administration for open
-resource file references.
-
-.SH DESCRIPTION
-.PP
-\fBTcl_MacEvalResource\fR extends the \fBsource\fR command to
-Macintosh resources. It sources Tcl code from a Text resource.
-Currently only sources the resource by name, file IDs may be supported
-at a later date.
-.PP
-\fBTcl_MacConvertTextResource\fR converts a TEXT resource into a Tcl
-suitable string. It mallocs the returned memory, converts ``\\r'' to
-``\\n'', and appends a null. The caller has the responsibility for
-freeing the memory.
-.PP
-\fBTcl_MacFindResource\fR provides a higher level interface for
-loading resources. It is used by \fBresource read\fR.
-.PP
-\fBTcl_NewOSTypeObj\fR is used to create a new resource name type
-object. The object type is "ostype".
-.PP
-\fBTcl_SetOSTypeObj\fR modifies an object to be a resource type and to
-have the specified long value.
-.PP
-\fBTcl_GetOSTypeFromObj\fR attempts to return an int from the Tcl
-object "objPtr". If the object is not already an int, an attempt will
-be made to convert it to one.
-.PP
-\fBTcl_MacSetEventProc\fR sets the event handling procedure for the
-application. This function will be passed all incoming Mac events.
-This function usually controls the console or some other entity like
-Tk.
-
-.SH RESOURCE TYPES
-.PP
-Resource types are 4-byte values used by the macintosh resource
-facility to tag parts of the resource fork in a file so that the OS
-knows how to handle them. As all 4 bytes are restricted to printable
-characters such a type can be interpreted as a 4 character string too.
-
-.SH KEYWORDS
-macintosh, mac, resource, notifier
diff --git a/doc/Namespace.3 b/doc/Namespace.3
new file mode 100644
index 0000000..5477329
--- /dev/null
+++ b/doc/Namespace.3
@@ -0,0 +1,165 @@
+'\"
+'\" Copyright (c) 2003 Donal K. Fellows
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+'\" Note that some of these functions do not seem to belong, but they
+'\" were all introduced with the same TIP (#139)
+'\"
+.so man.macros
+.TH Tcl_Namespace 3 8.5 Tcl "Tcl Library Procedures"
+.BS
+.SH NAME
+Tcl_AppendExportList, Tcl_CreateNamespace, Tcl_DeleteNamespace, Tcl_Export, Tcl_FindCommand, Tcl_FindNamespace, Tcl_ForgetImport, Tcl_GetCurrentNamespace, Tcl_GetGlobalNamespace, Tcl_GetNamespaceUnknownHandler, Tcl_Import, Tcl_SetNamespaceUnknownHandler \- manipulate namespaces
+.SH SYNOPSIS
+.nf
+\fB#include <tcl.h>\fR
+.sp
+Tcl_Namespace *
+\fBTcl_CreateNamespace\fR(\fIinterp, name, clientData, deleteProc\fR)
+.sp
+\fBTcl_DeleteNamespace\fR(\fInsPtr\fR)
+.sp
+int
+\fBTcl_AppendExportList\fR(\fIinterp, nsPtr, objPtr\fR)
+.sp
+int
+\fBTcl_Export\fR(\fIinterp, nsPtr, pattern, resetListFirst\fR)
+.sp
+int
+\fBTcl_Import\fR(\fIinterp, nsPtr, pattern, allowOverwrite\fR)
+.sp
+int
+\fBTcl_ForgetImport\fR(\fIinterp, nsPtr, pattern\fR)
+.sp
+Tcl_Namespace *
+\fBTcl_GetCurrentNamespace\fR(\fIinterp\fR)
+.sp
+Tcl_Namespace *
+\fBTcl_GetGlobalNamespace\fR(\fIinterp\fR)
+.sp
+Tcl_Namespace *
+\fBTcl_FindNamespace\fR(\fIinterp, name, contextNsPtr, flags\fR)
+.sp
+Tcl_Command
+\fBTcl_FindCommand\fR(\fIinterp, name, contextNsPtr, flags\fR)
+.sp
+Tcl_Obj *
+\fBTcl_GetNamespaceUnknownHandler(\fIinterp, nsPtr\fR)
+.sp
+int
+\fBTcl_SetNamespaceUnknownHandler(\fIinterp, nsPtr, handlerPtr\fR)
+.SH ARGUMENTS
+.AS Tcl_NamespaceDeleteProc allowOverwrite in/out
+.AP Tcl_Interp *interp in/out
+The interpreter in which the namespace exists and where name lookups
+are performed. Also where error result messages are written.
+.AP "const char" *name in
+The name of the namespace or command to be created or accessed.
+.AP ClientData clientData in
+A context pointer by the creator of the namespace. Not interpreted by
+Tcl at all.
+.AP Tcl_NamespaceDeleteProc *deleteProc in
+A pointer to function to call when the namespace is deleted, or NULL
+if no such callback is to be performed.
+.AP Tcl_Namespace *nsPtr in
+The namespace to be manipulated, or NULL (for other than
+\fBTcl_DeleteNamespace\fR) to manipulate the current namespace.
+.AP Tcl_Obj *objPtr out
+A reference to an unshared object to which the function output will be
+written.
+.AP "const char" *pattern in
+The glob-style pattern (see \fBTcl_StringMatch\fR) that describes the
+commands to be imported or exported.
+.AP int resetListFirst in
+Whether the list of export patterns should be reset before adding the
+current pattern to it.
+.AP int allowOverwrite in
+Whether new commands created by this import action can overwrite
+existing commands.
+.AP Tcl_Namespace *contextNsPtr in
+The location in the namespace hierarchy where the search for a
+namespace or command should be conducted relative to when the search
+term is not rooted at the global namespace. NULL indicates the
+current namespace.
+.AP int flags in
+OR-ed combination of bits controlling how the search is to be
+performed. The following flags are supported: \fBTCL_GLOBAL_ONLY\fR
+(indicates that the search is always to be conducted relative to the
+global namespace), \fBTCL_NAMESPACE_ONLY\fR (just for \fBTcl_FindCommand\fR;
+indicates that the search is always to be conducted relative to the
+context namespace), and \fBTCL_LEAVE_ERR_MSG\fR (indicates that an error
+message should be left in the interpreter if the search fails.)
+.AP Tcl_Obj *handlerPtr in
+A script fragment to be installed as the unknown command handler for the
+namespace, or NULL to reset the handler to its default.
+.BE
+
+.SH DESCRIPTION
+.PP
+Namespaces are hierarchic naming contexts that can contain commands
+and variables. They also maintain a list of patterns that describes
+what commands are exported, and can import commands that have been
+exported by other namespaces. Namespaces can also be manipulated
+through the Tcl command \fBnamespace\fR.
+.PP
+The \fITcl_Namespace\fR structure encapsulates a namespace, and is
+guaranteed to have the following fields in it: \fIname\fR (the local
+name of the namespace, with no namespace separator characters in it,
+with empty denoting the global namespace), \fIfullName\fR (the fully
+specified name of the namespace), \fIclientData\fR, \fIdeleteProc\fR
+(the values specified in the call to \fBTcl_CreateNamespace\fR), and
+\fIparentPtr\fR (a pointer to the containing namespace, or NULL for
+the global namespace.)
+.PP
+\fBTcl_CreateNamespace\fR creates a new namespace. The
+\fIdeleteProc\fR will have the following type signature:
+.CS
+typedef void (Tcl_NamespaceDeleteProc) (ClientData clientData);
+.CE
+.PP
+\fBTcl_DeleteNamespace\fR deletes a namespace.
+.PP
+\fBTcl_AppendExportList\fR retrieves the export patterns for a
+namespace given namespace and appends them (as list items) to
+\fIobjPtr\fR.
+.PP
+\fBTcl_Export\fR sets and appends to the export patterns for a
+namespace. Patterns are appended unless the \fIresetListFirst\fR flag
+is true.
+.PP
+\fBTcl_Import\fR imports commands matching a pattern into a
+namespace. Note that the pattern must include the name of the
+namespace to import from. This function returns an error if
+an attempt to import a command over an existing command is made,
+unless the \fIallowOverwrite\fR flag has been set.
+.PP
+\fBTcl_ForgetImport\fR removes imports matching a pattern.
+.PP
+\fBTcl_GetCurrentNamespace\fR returns the current namespace for an
+interpreter.
+.PP
+\fBTcl_GetGlobalNamespace\fR returns the global namespace for an
+interpreter.
+.PP
+\fBTcl_FindNamespace\fR searches for a namespace named \fIname\fR
+within the context of the namespace \fIcontextNsPtr\fR. If the
+namespace cannot be found, NULL is returned.
+.PP
+\fBTcl_FindCommand\fR searches for a command named \fIname\fR within
+the context of the namespace \fIcontextNsPtr\fR. If the command
+cannot be found, NULL is returned.
+.PP
+\fBTcl_GetNamespaceUnknownHandler\fR returns the unknown command handler
+for the namespace, or NULL if none is set.
+.PP
+\fBTcl_SetNamespaceUnknownHandler\fR sets the unknown command handler for
+the namespace. If \fIhandlerPtr\fR is NULL, then the handler is reset to
+its default.
+
+.SH "SEE ALSO"
+Tcl_CreateCommand, Tcl_ListObjAppendElements, Tcl_SetVar
+
+.SH KEYWORDS
+namespace, command
diff --git a/doc/Notifier.3 b/doc/Notifier.3
index bb2fef4..7858a8c 100644
--- a/doc/Notifier.3
+++ b/doc/Notifier.3
@@ -25,7 +25,6 @@ void
.sp
void
\fBTcl_QueueEvent\fR(\fIevPtr, position\fR)
-.VS 8.1
.sp
void
\fBTcl_ThreadQueueEvent\fR(\fIthreadId, evPtr, position\fR)
@@ -63,12 +62,16 @@ int
int
\fBTcl_GetServiceMode\fR()
.sp
-int
+int
\fBTcl_SetServiceMode\fR(\fImode\fR)
-.VE
-
+.sp
+void
+\fBTcl_ServiceModeHook\fR(\fImode\fR)
+.sp
+void
+\fBTcl_SetNotifier\fR(\fInotifierProcPtr\fR)
.SH ARGUMENTS
-.AS Tcl_EventDeleteProc milliseconds
+.AS Tcl_EventDeleteProc *notifierProcPtr
.AP Tcl_EventSetupProc *setupProc in
Procedure to invoke to prepare for event wait in \fBTcl_DoOneEvent\fR.
.AP Tcl_EventCheckProc *checkProc in
@@ -97,11 +100,13 @@ Procedure to invoke for each queued event in \fBTcl_DeleteEvents\fR.
.AP int flags in
What types of events to service. These flags are the same as those
passed to \fBTcl_DoOneEvent\fR.
-.VS 8.1
.AP int mode in
Indicates whether events should be serviced by \fBTcl_ServiceAll\fR.
Must be one of \fBTCL_SERVICE_NONE\fR or \fBTCL_SERVICE_ALL\fR.
-.VE
+.AP Tcl_NotifierProcs* notifierProcPtr in
+Structure of function pointers describing notifier procedures that are
+to replace the ones installed in the executable. See
+\fBREPLACING THE NOTIFIER\fR for details.
.BE
.SH INTRODUCTION
@@ -135,9 +140,7 @@ sources place events onto the queue so that they may be processed in
order at appropriate times during the event loop. The event queue
guarantees a fair discipline of event handling, so that no event
source can starve the others. It also allows events to be saved for
-servicing at a future time.
-.VS 8.1
-Threaded applications work in a
+servicing at a future time. Threaded applications work in a
similar manner, except that there is a separate event queue for
each thread containing a Tcl interpreter.
\fBTcl_QueueEvent\fR is used (primarily
@@ -169,7 +172,6 @@ The procedures \fBTcl_ServiceAll\fR, \fBTcl_ServiceEvent\fR,
to help connect Tcl's event loop to an external event loop such as
Motif's.
.SH "NOTIFIER BASICS"
-.VE
.PP
The easiest way to understand how the notifier works is to consider
what happens when \fBTcl_DoOneEvent\fR is called.
@@ -180,17 +182,13 @@ things:
.IP [1]
Check the event queue to see if it contains any events that can
be serviced. If so, service the first possible event, remove it
-.VS 8.1
from the queue, and return. It does this by calling
\fBTcl_ServiceEvent\fR and passing in the \fIflags\fR argument.
-.VE
.IP [2]
Prepare to block for an event. To do this, \fBTcl_DoOneEvent\fR
invokes a \fIsetup procedure\fR in each event source.
The event source will perform event-source specific initialization and
-.VS 8.1
possibly call \fBTcl_SetMaxBlockTime\fR to limit how long
-.VE
\fBTcl_WaitForEvent\fR will block if no new events occur.
.IP [3]
Call \fBTcl_WaitForEvent\fR. This procedure is implemented differently
@@ -233,8 +231,8 @@ the event source.
\fISetupProc\fR should match the following prototype:
.CS
typedef void Tcl_EventSetupProc(
- ClientData \fIclientData\fR,
- int \fIflags\fR);
+ ClientData \fIclientData\fR,
+ int \fIflags\fR);
.CE
The \fIclientData\fR argument will be the same as the \fIclientData\fR
argument to \fBTcl_CreateEventSource\fR; it is typically used to
@@ -243,7 +241,7 @@ The \fIflags\fR argument will be the same as the \fIflags\fR
argument passed to \fBTcl_DoOneEvent\fR except that it will never
be 0 (\fBTcl_DoOneEvent\fR replaces 0 with \fBTCL_ALL_EVENTS\fR).
\fIFlags\fR indicates what kinds of events should be considered;
-if the bit corresponding to this event source isn't set, the event
+if the bit corresponding to this event source is not set, the event
source should return immediately without doing anything. For
example, the file event source checks for the \fBTCL_FILE_EVENTS\fR
bit.
@@ -256,7 +254,6 @@ request notification with a Windows event. For timer-driven event
sources such as timer events or any polled event, the event source
can call \fBTcl_SetMaxBlockTime\fR to force the application to wake
up after a specified time even if no events have occurred.
-.VS 8.1
If no event source calls \fBTcl_SetMaxBlockTime\fR
then \fBTcl_WaitForEvent\fR will wait as long as necessary for an
event to occur; otherwise, it will only wait as long as the shortest
@@ -268,28 +265,24 @@ events already queued. If there are, it calls
\fBTcl_SetMaxBlockTime\fR with a 0 block time so that
\fBTcl_WaitForEvent\fR does not block if there is no new data on the X
connection.
-.VE
The \fItimePtr\fR argument to \fBTcl_WaitForEvent\fR points to
a structure that describes a time interval in seconds and
microseconds:
.CS
typedef struct Tcl_Time {
- long \fIsec\fR;
- long \fIusec\fR;
+ long \fIsec\fR;
+ long \fIusec\fR;
} Tcl_Time;
.CE
The \fIusec\fR field should be less than 1000000.
.PP
-.VS 8.1
Information provided to \fBTcl_SetMaxBlockTime\fR
is only used for the next call to \fBTcl_WaitForEvent\fR; it is
discarded after \fBTcl_WaitForEvent\fR returns.
-.VE
The next time an event wait is done each of the event sources'
setup procedures will be called again, and they can specify new
information for that event wait.
.PP
-.VS 8.1
If the application uses an external event loop rather than
\fBTcl_DoOneEvent\fR, the event sources may need to call
\fBTcl_SetMaxBlockTime\fR at other times. For example, if a new event
@@ -305,7 +298,6 @@ platform-specific procedures may also be available for
\fIsetupProc\fR, if there is additional information needed by
\fBTcl_WaitForEvent\fR on that platform. For example, on Unix systems
the \fBTcl_CreateFileHandler\fR interface can be used to wait for file events.
-.VE
.PP
The second procedure provided by each event source is its check
procedure, indicated by the \fIcheckProc\fR argument to
@@ -313,8 +305,8 @@ procedure, indicated by the \fIcheckProc\fR argument to
following prototype:
.CS
typedef void Tcl_EventCheckProc(
- ClientData \fIclientData\fR,
- int \fIflags\fR);
+ ClientData \fIclientData\fR,
+ int \fIflags\fR);
.CE
The arguments to this procedure are the same as those for \fIsetupProc\fR.
\fBCheckProc\fR is invoked by \fBTcl_DoOneEvent\fR after it has waited
@@ -363,24 +355,20 @@ events at the front of the queue, such as a series of
Enter and Leave events synthesized during a grab or ungrab operation
in Tk.
.PP
-.VS 8.1
When it is time to handle an event from the queue (steps 1 and 4
above) \fBTcl_ServiceEvent\fR will invoke the \fIproc\fR specified
-.VE
in the first queued \fBTcl_Event\fR structure.
\fIProc\fR must match the following prototype:
.CS
typedef int Tcl_EventProc(
- Tcl_Event *\fIevPtr\fR,
- int \fIflags\fR);
+ Tcl_Event *\fIevPtr\fR,
+ int \fIflags\fR);
.CE
The first argument to \fIproc\fR is a pointer to the event, which will
be the same as the first argument to the \fBTcl_QueueEvent\fR call that
added the event to the queue.
The second argument to \fIproc\fR is the \fIflags\fR argument for the
-.VS 8.1
current call to \fBTcl_ServiceEvent\fR; this is used by the event source
-.VE
to return immediately if its events are not relevant.
.PP
It is up to \fIproc\fR to handle the event, typically by invoking
@@ -389,20 +377,17 @@ Once the event source has finished handling the event it returns 1
to indicate that the event can be removed from the queue.
If for some reason the event source decides that the event cannot
be handled at this time, it may return 0 to indicate that the event
-.VS 8.1
should be deferred for processing later; in this case \fBTcl_ServiceEvent\fR
-.VE
will go on to the next event in the queue and attempt to service it.
There are several reasons why an event source might defer an event.
One possibility is that events of this type are excluded by the
\fIflags\fR argument.
For example, the file event source will always return 0 if the
-\fBTCL_FILE_EVENTS\fR bit isn't set in \fIflags\fR.
+\fBTCL_FILE_EVENTS\fR bit is not set in \fIflags\fR.
Another example of deferring events happens in Tk if
\fBTk_RestrictEvents\fR has been invoked to defer certain kinds
of window events.
.PP
-.VS 8.1
When \fIproc\fR returns 1, \fBTcl_ServiceEvent\fR will remove the
event from the event queue and free its storage.
Note that the storage for an event must be allocated by
@@ -422,8 +407,9 @@ Tcl_ThreadID for the current thread, use the \fBTcl_GetCurrentThread\fR
procedure. (A thread would then need to pass this identifier to other
threads for those threads to be able to add events to its queue.)
After adding an event to another thread's queue, you then typically
-need to call \fBTcl_ThreadAlert\fR to "wake up" that thread's notifier to
-alert it to the new event.
+need to call \fBTcl_ThreadAlert\fR to
+.QW "wake up"
+that thread's notifier to alert it to the new event.
.PP
\fBTcl_DeleteEvents\fR can be used to explicitly remove one or more
events from the event queue. \fBTcl_DeleteEvents\fR calls \fIproc\fR
@@ -432,8 +418,8 @@ returns 1. Events for which the procedure returns 0 are left in the
queue. \fIProc\fR should match the following prototype:
.CS
typedef int Tcl_EventDeleteProc(
- Tcl_Event *\fIevPtr\fR,
- ClientData \fIclientData\fR);
+ Tcl_Event *\fIevPtr\fR,
+ ClientData \fIclientData\fR);
.CE
The \fIclientData\fR argument will be the same as the \fIclientData\fR
argument to \fBTcl_DeleteEvents\fR; it is typically used to point to
@@ -444,23 +430,21 @@ point to the next event in the queue.
\fIcheckProc\fR, and \fIclientData\fR arguments must exactly match those
provided to the \fBTcl_CreateEventSource\fR for the event source to be deleted.
If no such source exists, \fBTcl_DeleteEventSource\fR has no effect.
-.VE
.SH "CREATING A NEW NOTIFIER"
.PP
The notifier consists of all the procedures described in this manual
entry, plus \fBTcl_DoOneEvent\fR and \fBTcl_Sleep\fR, which are
-.VS 8.1
available on all platforms, and \fBTcl_CreateFileHandler\fR and
\fBTcl_DeleteFileHandler\fR, which are Unix-specific. Most of these
procedures are generic, in that they are the same for all notifiers.
-However, eight of the procedures are notifier-dependent:
-\fBTcl_InitNotifier\fR, \fBTcl_AlertNotifier\fR, \fBTcl_FinalizeNotifier\fR,
-\fBTcl_SetTimer\fR, \fBTcl_Sleep\fR, \fBTcl_WaitForEvent\fR,
-\fBTcl_CreateFileHandler\fR and \fBTcl_DeleteFileHandler\fR. To
-support a new platform or to integrate Tcl with an
-application-specific event loop, you must write new versions of these
-procedures.
+However, none of the procedures are notifier-dependent:
+\fBTcl_InitNotifier\fR, \fBTcl_AlertNotifier\fR,
+\fBTcl_FinalizeNotifier\fR, \fBTcl_SetTimer\fR, \fBTcl_Sleep\fR,
+\fBTcl_WaitForEvent\fR, \fBTcl_CreateFileHandler\fR,
+\fBTcl_DeleteFileHandler\fR and \fBTcl_ServiceModeHook\fR. To support a
+new platform or to integrate Tcl with an application-specific event loop,
+you must write new versions of these procedures.
.PP
\fBTcl_InitNotifier\fR initializes the notifier state and returns
a handle to the notifier state. Tcl calls this
@@ -469,7 +453,9 @@ procedure when initializing a Tcl interpreter. Similarly,
called by \fBTcl_Finalize\fR when shutting down a Tcl interpreter.
.PP
\fBTcl_WaitForEvent\fR is the lowest-level procedure in the notifier;
-it is responsible for waiting for an ``interesting'' event to occur or
+it is responsible for waiting for an
+.QW interesting
+event to occur or
for a given time to elapse. Before \fBTcl_WaitForEvent\fR is invoked,
each of the event sources' setup procedure will have been invoked.
The \fItimePtr\fR argument to
@@ -483,13 +469,13 @@ to occur; it should not actually process the event in any way.
Later on, the
event sources will process the raw events and create Tcl_Events on
the event queue in their \fIcheckProc\fR procedures.
-However, on some platforms (such as Windows) this isn't possible;
+However, on some platforms (such as Windows) this is not possible;
events may be processed in \fBTcl_WaitForEvent\fR, including queuing
Tcl_Events and more (for example, callbacks for native widgets may be
invoked). The return value from \fBTcl_WaitForEvent\fR must be either
0, 1, or \-1. On platforms such as Windows where events get processed in
\fBTcl_WaitForEvent\fR, a return value of 1 means that there may be more
-events still pending that haven't been processed. This is a sign to the
+events still pending that have not been processed. This is a sign to the
caller that it must call \fBTcl_WaitForEvent\fR again if it wants all
pending events to be processed. A 0 return value means that calling
\fBTcl_WaitForEvent\fR again will not have any effect: either this is a
@@ -504,7 +490,9 @@ forever because there were no active event sources and the timeout was
infinite.
.PP
\fBTcl_AlertNotifier\fR is used in multithreaded applications to allow
-any thread to "wake up" the notifier to alert it to new events on its
+any thread to
+.QW "wake up"
+the notifier to alert it to new events on its
queue. \fBTcl_AlertNotifier\fR requires as an argument the notifier
handle returned by \fBTcl_InitNotifier\fR.
.PP
@@ -514,11 +502,18 @@ invoked by \fBTcl_SetMaxBlockTime\fR whenever the maximum blocking
time has been reduced. \fBTcl_SetTimer\fR should arrange for the
external event loop to invoke \fBTcl_ServiceAll\fR after the specified
interval even if no events have occurred. This interface is needed
-because \fBTcl_WaitForEvent\fR isn't invoked when there is an external
+because \fBTcl_WaitForEvent\fR is not invoked when there is an external
event loop. If the
notifier will only be used from \fBTcl_DoOneEvent\fR, then
\fBTcl_SetTimer\fR need not do anything.
.PP
+\fBTcl_ServiceModeHook\fR is called by the platform-independent portion
+of the notifier when client code makes a call to
+\fBTcl_SetServiceMode\fR. This hook is provided to support operating
+systems that require special event handling when the application is in
+a modal loop (the Windows notifier, for instance, uses this hook to
+create a communication window).
+.PP
On Unix systems, the file event source also needs support from the
notifier. The file event source consists of the
\fBTcl_CreateFileHandler\fR and \fBTcl_DeleteFileHandler\fR
@@ -532,6 +527,38 @@ The easiest way to create a new notifier is to look at the code
for an existing notifier, such as the files \fBunix/tclUnixNotfy.c\fR
or \fBwin/tclWinNotify.c\fR in the Tcl source distribution.
+.SH "REPLACING THE NOTIFIER"
+.PP
+A notifier that has been written according to the conventions above
+can also be installed in a running process in place of the standard
+notifier. This mechanism is used so that a single executable can be
+used (with the standard notifier) as a stand-alone program and reused
+(with a replacement notifier in a loadable extension) as an extension
+to another program, such as a Web browser plugin.
+.PP
+To do this, the extension makes a call to \fBTcl_SetNotifier\fR
+passing a pointer to a \fBTcl_NotifierProcs\fR data structure. The
+structure has the following layout:
+.CS
+typedef struct Tcl_NotifierProcs {
+ Tcl_SetTimerProc *setTimerProc;
+ Tcl_WaitForEventProc *waitForEventProc;
+ Tcl_CreateFileHandlerProc *createFileHandlerProc;
+ Tcl_DeleteFileHandlerProc *deleteFileHandlerProc;
+ Tcl_InitNotifierProc *initNotifierProc;
+ Tcl_FinalizeNotifierProc *finalizeNotifierProc;
+ Tcl_AlertNotifierProc *alertNotifierProc;
+ Tcl_ServiceModeHookProc *serviceModeHookProc;
+} Tcl_NotifierProcs;
+.CE
+Following the call to \fBTcl_SetNotifier\fR, the pointers given in
+the \fBTcl_NotifierProcs\fR structure replace whatever notifier had
+been installed in the process.
+.PP
+It is extraordinarily unwise to replace a running notifier. Normally,
+\fBTcl_SetNotifier\fR should be called at process initialization time
+before the first call to \fBTcl_InitNotifier\fR.
+
.SH "EXTERNAL EVENT LOOPS"
.PP
The notifier interfaces are designed so that Tcl can be embedded into
@@ -592,7 +619,7 @@ then calls to \fBTcl_ServiceAll\fR will behave normally.
mode, which should be restored when the recursive loop exits.
\fBTcl_GetServiceMode\fR returns the current value of the service
mode.
-.VE
+
.SH "SEE ALSO"
\fBTcl_CreateFileHandler\fR, \fBTcl_DeleteFileHandler\fR, \fBTcl_Sleep\fR,
\fBTcl_DoOneEvent\fR, \fBThread(3)\fR
diff --git a/doc/Object.3 b/doc/Object.3
index 4e8fa6f..4817b9b 100644
--- a/doc/Object.3
+++ b/doc/Object.3
@@ -5,7 +5,7 @@
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
-.TH Tcl_Obj 3 8.1 Tcl "Tcl Library Procedures"
+.TH Tcl_Obj 3 8.5 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_NewObj, Tcl_DuplicateObj, Tcl_IncrRefCount, Tcl_DecrRefCount, Tcl_IsShared, Tcl_InvalidateStringRep \- manipulate Tcl objects
@@ -28,7 +28,7 @@ int
.sp
\fBTcl_InvalidateStringRep\fR(\fIobjPtr\fR)
.SH ARGUMENTS
-.AS Tcl_Obj *objPtr in
+.AS Tcl_Obj *objPtr
.AP Tcl_Obj *objPtr in
Points to an object;
must have been the result of a previous call to \fBTcl_NewObj\fR.
@@ -100,34 +100,37 @@ reclaim an object's storage.
.PP
Tcl objects are typed.
An object's internal representation is controlled by its type.
-Seven types are predefined in the Tcl core
+Several types are predefined in the Tcl core
including integer, double, list, and bytecode.
Extension writers can extend the set of types
-by using the procedure \fBTcl_RegisterObjType\fR .
-
+by defining their own \fBTcl_ObjType\fR structs.
.SH "THE TCL_OBJ STRUCTURE"
.PP
Each Tcl object is represented by a \fBTcl_Obj\fR structure
which is defined as follows.
.CS
typedef struct Tcl_Obj {
- int \fIrefCount\fR;
- char *\fIbytes\fR;
- int \fIlength\fR;
- Tcl_ObjType *\fItypePtr\fR;
- union {
- long \fIlongValue\fR;
- double \fIdoubleValue\fR;
- VOID *\fIotherValuePtr\fR;
- struct {
- VOID *\fIptr1\fR;
- VOID *\fIptr2\fR;
- } \fItwoPtrValue\fR;
- } \fIinternalRep\fR;
+ int \fIrefCount\fR;
+ char *\fIbytes\fR;
+ int \fIlength\fR;
+ Tcl_ObjType *\fItypePtr\fR;
+ union {
+ long \fIlongValue\fR;
+ double \fIdoubleValue\fR;
+ void *\fIotherValuePtr\fR;
+ Tcl_WideInt \fIwideValue\fR;
+ struct {
+ void *\fIptr1\fR;
+ void *\fIptr2\fR;
+ } \fItwoPtrValue\fR;
+ struct {
+ void *\fIptr\fR;
+ unsigned long \fIvalue\fR;
+ } \fIptrAndLongRep\fR;
+ } \fIinternalRep\fR;
} Tcl_Obj;
.CE
The \fIbytes\fR and the \fIlength\fR members together hold
-.VS 8.1
an object's UTF-8 string representation,
which is a \fIcounted string\fR not containing null bytes (UTF-8 null
characters should be encoded as a two byte sequence: 192, 128.)
@@ -137,7 +140,6 @@ The byte array must always have a null byte after the last data byte,
at offset \fIlength\fR;
this allows string representations
to be treated as conventional null-terminated C strings.
-.VE 8.1
C programs use \fBTcl_GetStringFromObj\fR and \fBTcl_GetString\fR to get
an object's string representation.
If \fIbytes\fR is NULL,
@@ -151,10 +153,11 @@ the internal representation is invalid.
.PP
The \fIinternalRep\fR union member holds
an object's internal representation.
-This is either a (long) integer, a double-precision floating point number,
+This is either a (long) integer, a double-precision floating-point number,
a pointer to a value containing additional information
-needed by the object's type to represent the object,
-or two arbitrary pointers.
+needed by the object's type to represent the object, a Tcl_WideInt
+integer, two arbitrary pointers, or a pair made up of an unsigned long
+integer and a pointer.
.PP
The \fIrefCount\fR member is used to tell when it is safe to free
an object's storage.
@@ -224,7 +227,6 @@ creates a new internal representation for an object
and changes its \fItypePtr\fR.
See the man page for \fBTcl_RegisterObjType\fR
to see how to create a new object type.
-
.SH "EXAMPLE OF THE LIFETIME OF AN OBJECT"
.PP
As an example of the lifetime of an object,
@@ -262,9 +264,8 @@ no longer corresponds to the internal representation.
.CE
The string representation of \fIx\fR's object is needed
and is recomputed.
-The string representation is now \fB124\fR.
+The string representation is now \fB124\fR
and both representations are again valid.
-
.SH "STORAGE MANAGEMENT OF OBJECTS"
.PP
Tcl objects are allocated on the heap and are shared as much as possible
@@ -281,7 +282,7 @@ if the object's reference count drops to zero, frees its storage.
An object shared by different code or data structures has
\fIrefCount\fR greater than 1.
Incrementing an object's reference count ensures that
-it won't be freed too early or have its value change accidently.
+it will not be freed too early or have its value change accidentally.
.PP
As an example, the bytecode interpreter shares argument objects
between calling and called Tcl procedures to avoid having to copy objects.
@@ -297,7 +298,7 @@ When an object's reference count drops less than or equal to zero,
\fBTcl_DecrRefCount\fR reclaims its storage.
Most command procedures do not have to be concerned about
reference counting since they use an object's value immediately
-and don't retain a pointer to the object after they return.
+and do not retain a pointer to the object after they return.
However, if they do retain a pointer to an object in a data structure,
they must be careful to increment its reference count
since the retained pointer is a new reference.
@@ -312,26 +313,29 @@ by using \fBTcl_DuplicateObj\fR;
this returns a new duplicate of the original object
that has \fIrefCount\fR 0.
If the object is not shared,
-the command procedure "owns" the object and can safely modify it directly.
+the command procedure
+.QW "owns"
+the object and can safely modify it directly.
For example, the following code appears in the command procedure
that implements \fBlinsert\fR.
This procedure modifies the list object passed to it in \fIobjv[1]\fR
by inserting \fIobjc-3\fR new elements before \fIindex\fR.
+.PP
.CS
listPtr = objv[1];
if (Tcl_IsShared(listPtr)) {
- listPtr = Tcl_DuplicateObj(listPtr);
+ listPtr = Tcl_DuplicateObj(listPtr);
}
-result = Tcl_ListObjReplace(interp, listPtr, index, 0, (objc-3), &(objv[3]));
+result = Tcl_ListObjReplace(interp, listPtr, index, 0,
+ (objc-3), &(objv[3]));
.CE
+.PP
As another example, \fBincr\fR's command procedure
must check whether the variable's object is shared before
incrementing the integer in its internal representation.
If it is shared, it needs to duplicate the object
-in order to avoid accidently changing values in other data structures.
-
+in order to avoid accidentally changing values in other data structures.
.SH "SEE ALSO"
-Tcl_ConvertToType, Tcl_GetIntFromObj, Tcl_ListObjAppendElement, Tcl_ListObjIndex, Tcl_ListObjReplace, Tcl_RegisterObjType
-
+Tcl_ConvertToType(3), Tcl_GetIntFromObj(3), Tcl_ListObjAppendElement(3), Tcl_ListObjIndex(3), Tcl_ListObjReplace(3), Tcl_RegisterObjType(3)
.SH KEYWORDS
internal representation, object, object creation, object type, reference counting, string representation, type conversion
diff --git a/doc/ObjectType.3 b/doc/ObjectType.3
index cc84fd1..974ea6c 100644
--- a/doc/ObjectType.3
+++ b/doc/ObjectType.3
@@ -24,12 +24,12 @@ int
int
\fBTcl_ConvertToType\fR(\fIinterp, objPtr, typePtr\fR)
.SH ARGUMENTS
-.AS Tcl_ObjType *typeName in
+.AS "const char" *typeName
.AP Tcl_ObjType *typePtr in
Points to the structure containing information about the Tcl object type.
This storage must live forever,
typically by being statically allocated.
-.AP "CONST char" *typeName in
+.AP "const char" *typeName in
The name of a Tcl object type that \fBTcl_GetObjType\fR should look up.
.AP Tcl_Interp *interp in
Interpreter to use for error reporting.
@@ -43,12 +43,14 @@ must have been the result of a previous call to \fBTcl_NewObj\fR.
.SH DESCRIPTION
.PP
The procedures in this man page manage Tcl object types.
-The are used to register new object types,
-look up types,
+They are used to register new object types, look up types,
and force conversions from one type to another.
.PP
\fBTcl_RegisterObjType\fR registers a new Tcl object type
-in the table of all object types supported by Tcl.
+in the table of all object types that \fBTcl_GetObjType\fR
+can look up by name. There are other object types supported by Tcl
+as well, which Tcl chooses not to register. Extensions can likewise
+choose to register the object types they create or not.
The argument \fItypePtr\fR points to a Tcl_ObjType structure that
describes the new type by giving its name
and by supplying pointers to four procedures
@@ -59,11 +61,11 @@ it is replaced with the new type.
The Tcl_ObjType structure is described
in the section \fBTHE TCL_OBJTYPE STRUCTURE\fR below.
.PP
-\fBTcl_GetObjType\fR returns a pointer to the Tcl_ObjType
+\fBTcl_GetObjType\fR returns a pointer to the registered Tcl_ObjType
with name \fItypeName\fR.
It returns NULL if no type with that name is registered.
.PP
-\fBTcl_AppendAllObjTypes\fR appends the name of each object type
+\fBTcl_AppendAllObjTypes\fR appends the name of each registered object type
as a list element onto the Tcl object referenced by \fIobjPtr\fR.
The return value is \fBTCL_OK\fR unless there was an error
converting \fIobjPtr\fR to a list object;
@@ -73,7 +75,8 @@ in that case \fBTCL_ERROR\fR is returned.
if possible.
It creates a new internal representation for \fIobjPtr\fR
appropriate for the target type \fItypePtr\fR
-and sets its \fItypePtr\fR member to that type.
+and sets its \fItypePtr\fR member as determined by calling the
+\fItypePtr->setFromAnyProc\fR routine.
Any internal representation for \fIobjPtr\fR's old type is freed.
If an error occurs during conversion, it returns \fBTCL_ERROR\fR
and leaves an error message in the result object for \fIinterp\fR
@@ -81,118 +84,168 @@ unless \fIinterp\fR is NULL.
Otherwise, it returns \fBTCL_OK\fR.
Passing a NULL \fIinterp\fR allows this procedure to be used
as a test whether the conversion can be done (and in fact was done).
-
+.VS 8.5
+.PP
+In many cases, the \fItypePtr->setFromAnyProc\fR routine will
+set \fIobjPtr->typePtr\fR to the argument value \fItypePtr\fR,
+but that is no longer guaranteed. The \fIsetFromAnyProc\fR is
+free to set the internal representation for \fIobjPtr\fR to make
+use of another related Tcl_ObjType, if it sees fit.
+.VE 8.5
.SH "THE TCL_OBJTYPE STRUCTURE"
.PP
Extension writers can define new object types by defining four
-procedures,
-initializing a Tcl_ObjType structure to describe the type,
-and calling \fBTcl_RegisterObjType\fR.
+procedures and
+initializing a Tcl_ObjType structure to describe the type.
+Extension writers may also pass a pointer to their Tcl_ObjType
+structure to \fBTcl_RegisterObjType\fR if they wish to permit
+other extensions to look up their Tcl_ObjType by name with
+the \fBTcl_GetObjType\fR routine.
The \fBTcl_ObjType\fR structure is defined as follows:
+.PP
.CS
typedef struct Tcl_ObjType {
- char *\fIname\fR;
- Tcl_FreeInternalRepProc *\fIfreeIntRepProc\fR;
- Tcl_DupInternalRepProc *\fIdupIntRepProc\fR;
- Tcl_UpdateStringProc *\fIupdateStringProc\fR;
- Tcl_SetFromAnyProc *\fIsetFromAnyProc\fR;
+ char *\fIname\fR;
+ Tcl_FreeInternalRepProc *\fIfreeIntRepProc\fR;
+ Tcl_DupInternalRepProc *\fIdupIntRepProc\fR;
+ Tcl_UpdateStringProc *\fIupdateStringProc\fR;
+ Tcl_SetFromAnyProc *\fIsetFromAnyProc\fR;
} Tcl_ObjType;
.CE
+.SS "THE NAME FIELD"
.PP
The \fIname\fR member describes the name of the type, e.g. \fBint\fR.
-Extension writers can look up an object type using its name
-with the \fBTcl_GetObjType\fR procedure.
+When a type is registered, this is the name used by callers
+of \fBTcl_GetObjType\fR to lookup the type. For unregistered
+types, the \fIname\fR field is primarily of value for debugging.
The remaining four members are pointers to procedures
called by the generic Tcl object code:
+.SS "THE SETFROMANYPROC FIELD"
.PP
The \fIsetFromAnyProc\fR member contains the address of a function
called to create a valid internal representation
from an object's string representation.
+.PP
.CS
-typedef int (Tcl_SetFromAnyProc) (Tcl_Interp *\fIinterp\fR, Tcl_Obj *\fIobjPtr\fR);
+typedef int (Tcl_SetFromAnyProc) (Tcl_Interp *\fIinterp\fR,
+ Tcl_Obj *\fIobjPtr\fR);
.CE
-If an internal representation can't be created from the string,
+.PP
+If an internal representation cannot be created from the string,
it returns \fBTCL_ERROR\fR and puts a message
describing the error in the result object for \fIinterp\fR
unless \fIinterp\fR is NULL.
If \fIsetFromAnyProc\fR is successful,
it stores the new internal representation,
sets \fIobjPtr\fR's \fItypePtr\fR member to point to
-\fIsetFromAnyProc\fR's \fBTcl_ObjType\fR, and returns \fBTCL_OK\fR.
+the \fBTcl_ObjType\fR struct corresponding to the new
+internal representation, and returns \fBTCL_OK\fR.
Before setting the new internal representation,
the \fIsetFromAnyProc\fR must free any internal representation
of \fIobjPtr\fR's old type;
it does this by calling the old type's \fIfreeIntRepProc\fR
if it is not NULL.
-As an example, the \fIsetFromAnyProc\fR for the builtin Tcl integer type
+.PP
+As an example, the \fIsetFromAnyProc\fR for the built-in Tcl list type
gets an up-to-date string representation for \fIobjPtr\fR
by calling \fBTcl_GetStringFromObj\fR.
-It parses the string to obtain an integer and,
-if this succeeds,
-stores the integer in \fIobjPtr\fR's internal representation
-and sets \fIobjPtr\fR's \fItypePtr\fR member to point to the integer type's
+It parses the string to verify it is in a valid list format and
+to obtain each element value in the list, and, if this succeeds,
+stores the list elements in \fIobjPtr\fR's internal representation
+and sets \fIobjPtr\fR's \fItypePtr\fR member to point to the list type's
Tcl_ObjType structure.
+.PP
Do not release \fIobjPtr\fR's old internal representation unless you
replace it with a new one or reset the \fItypePtr\fR member to NULL.
.PP
+The \fIsetFromAnyProc\fR member may be set to NULL, if the routines
+making use of the internal representation have no need to derive that
+internal representation from an arbitrary string value. However, in
+this case, passing a pointer to the type to Tcl_ConvertToType() will
+lead to a panic, so to avoid this possibility, the type
+should \fInot\fR be registered.
+.SS "THE UPDATESTRINGPROC FIELD"
+.PP
The \fIupdateStringProc\fR member contains the address of a function
called to create a valid string representation
from an object's internal representation.
+.PP
.CS
typedef void (Tcl_UpdateStringProc) (Tcl_Obj *\fIobjPtr\fR);
.CE
+.PP
\fIobjPtr\fR's \fIbytes\fR member is always NULL when it is called.
It must always set \fIbytes\fR non-NULL before returning.
We require the string representation's byte array
-to have a null after the last byte, at offset \fIlength\fR;
-this allows string representations that do not contain null bytes
+to have a null after the last byte, at offset \fIlength\fR,
+and to have no null bytes before that; this allows string representations
to be treated as conventional null character-terminated C strings.
+These restrictions are easily met by using Tcl's internal UTF encoding
+for the string representation, same as one would do for other
+Tcl routines accepting string values as arguments.
Storage for the byte array must be allocated in the heap by \fBTcl_Alloc\fR
or \fBckalloc\fR. Note that \fIupdateStringProc\fRs must allocate
enough storage for the string's bytes and the terminating null byte.
-The \fIupdateStringProc\fR for Tcl's builtin list type, for example,
-builds an array of strings for each element object
-and then calls \fBTcl_Merge\fR
-to construct a string with proper Tcl list structure.
-It stores this string as the list object's string representation.
+.PP
+The \fIupdateStringProc\fR for Tcl's built-in double type, for example,
+calls Tcl_PrintDouble to write to a buffer of size TCL_DOUBLE_SPACE,
+then allocates and copies the string representation to just enough
+space to hold it. A pointer to the allocated space is stored in
+the \fIbytes\fR member.
+.PP
+The \fIupdateStringProc\fR member may be set to NULL, if the routines
+making use of the internal representation are written so that the
+string representation is never invalidated. Failure to meet this
+obligation will lead to panics or crashes when \fBTcl_GetStringFromObj\fR
+or other similar routines ask for the string representation.
+.SS "THE DUPINTREPPROC FIELD"
.PP
The \fIdupIntRepProc\fR member contains the address of a function
called to copy an internal representation from one object to another.
+.PP
.CS
-typedef void (Tcl_DupInternalRepProc) (Tcl_Obj *\fIsrcPtr\fR, Tcl_Obj *\fIdupPtr\fR);
+typedef void (Tcl_DupInternalRepProc) (Tcl_Obj *\fIsrcPtr\fR,
+ Tcl_Obj *\fIdupPtr\fR);
.CE
+.PP
\fIdupPtr\fR's internal representation is made a copy of \fIsrcPtr\fR's
internal representation.
Before the call,
\fIsrcPtr\fR's internal representation is valid and \fIdupPtr\fR's is not.
\fIsrcPtr\fR's object type determines what
copying its internal representation means.
+.PP
For example, the \fIdupIntRepProc\fR for the Tcl integer type
simply copies an integer.
-The builtin list type's \fIdupIntRepProc\fR
-allocates a new array that points at the original element objects;
-the elements are shared between the two lists
-(and their reference counts are incremented to reflect the new references).
+The built-in list type's \fIdupIntRepProc\fR uses a far more
+sophisticated scheme to continue sharing storage as much as it
+reasonably can.
+.SS "THE FREEINTREPPROC FIELD"
.PP
The \fIfreeIntRepProc\fR member contains the address of a function
that is called when an object is freed.
+.PP
.CS
typedef void (Tcl_FreeInternalRepProc) (Tcl_Obj *\fIobjPtr\fR);
.CE
+.PP
The \fIfreeIntRepProc\fR function can deallocate the storage
for the object's internal representation
and do other type-specific processing necessary when an object is freed.
-For example, Tcl list objects have an \fIinternalRep.otherValuePtr\fR
-that points to an array of pointers to each element in the list.
-The list type's \fIfreeIntRepProc\fR decrements
-the reference count for each element object
-(since the list will no longer refer to those objects),
-then deallocates the storage for the array of pointers.
+.PP
+For example, the list type's \fIfreeIntRepProc\fR respects
+the storage sharing scheme established by the \fIdupIntRepProc\fR
+so that it only frees storage when the last object sharing it
+is being freed.
+.PP
The \fIfreeIntRepProc\fR member can be set to NULL
to indicate that the internal representation does not require freeing.
-
+The \fIfreeIntRepProc\fR implementation must not access the
+\fIbytes\fR member of the object, since Tcl makes its own internal
+uses of that field during object deletion. The defined tasks for
+the \fIfreeIntRepProc\fR have no need to consult the \fIbytes\fR
+member.
.SH "SEE ALSO"
Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount
-
.SH KEYWORDS
internal representation, object, object type, string representation, type conversion
diff --git a/doc/OpenFileChnl.3 b/doc/OpenFileChnl.3
index 80596d7..0d722f6 100644
--- a/doc/OpenFileChnl.3
+++ b/doc/OpenFileChnl.3
@@ -9,7 +9,7 @@
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
-Tcl_OpenFileChannel, Tcl_OpenCommandChannel, Tcl_MakeFileChannel, Tcl_GetChannel, Tcl_GetChannelNames, Tcl_GetChannelNamesEx, Tcl_RegisterChannel, Tcl_UnregisterChannel, Tcl_DetachChannel, Tcl_IsStandardChannel, Tcl_Close, Tcl_ReadChars, Tcl_Read, Tcl_GetsObj, Tcl_Gets, Tcl_WriteObj, Tcl_WriteChars, Tcl_Write, Tcl_Flush, Tcl_Seek, Tcl_Tell, Tcl_GetChannelOption, Tcl_SetChannelOption, Tcl_Eof, Tcl_InputBlocked, Tcl_InputBuffered, Tcl_OutputBuffered, Tcl_Ungets, Tcl_ReadRaw, Tcl_WriteRaw \- buffered I/O facilities using channels
+Tcl_OpenFileChannel, Tcl_OpenCommandChannel, Tcl_MakeFileChannel, Tcl_GetChannel, Tcl_GetChannelNames, Tcl_GetChannelNamesEx, Tcl_RegisterChannel, Tcl_UnregisterChannel, Tcl_DetachChannel, Tcl_IsStandardChannel, Tcl_Close, Tcl_ReadChars, Tcl_Read, Tcl_GetsObj, Tcl_Gets, Tcl_WriteObj, Tcl_WriteChars, Tcl_Write, Tcl_Flush, Tcl_Seek, Tcl_Tell, Tcl_TruncateChannel, Tcl_GetChannelOption, Tcl_SetChannelOption, Tcl_Eof, Tcl_InputBlocked, Tcl_InputBuffered, Tcl_OutputBuffered, Tcl_Ungets, Tcl_ReadRaw, Tcl_WriteRaw \- buffered I/O facilities using channels
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -25,14 +25,12 @@ Tcl_Channel
.sp
Tcl_Channel
\fBTcl_GetChannel\fR(\fIinterp, channelName, modePtr\fR)
-.VS 8.3
.sp
int
\fBTcl_GetChannelNames\fR(\fIinterp\fR)
.sp
int
\fBTcl_GetChannelNamesEx\fR(\fIinterp, pattern\fR)
-.VE
.sp
void
\fBTcl_RegisterChannel\fR(\fIinterp, channel\fR)
@@ -49,7 +47,6 @@ int
int
\fBTcl_Close\fR(\fIinterp, channel\fR)
.sp
-.VS 8.1
int
\fBTcl_ReadChars\fR(\fIchannel, readObjPtr, charsToRead, appendFlag\fR)
.sp
@@ -73,15 +70,12 @@ int
.sp
int
\fBTcl_Write\fR(\fIchannel, byteBuf, bytesToWrite\fR)
-.VE
-.VS 8.3.2
.sp
int
\fBTcl_ReadRaw\fR(\fIchannel, readBuf, bytesToRead\fR)
.sp
int
\fBTcl_WriteRaw\fR(\fIchannel, byteBuf, bytesToWrite\fR)
-.VE
.sp
int
\fBTcl_Eof\fR(\fIchannel\fR)
@@ -94,19 +88,20 @@ int
.sp
int
\fBTcl_InputBuffered\fR(\fIchannel\fR)
-.VS 8.4
.sp
int
\fBTcl_OutputBuffered\fR(\fIchannel\fR)
-.VE
.sp
-.VS 8.4
Tcl_WideInt
\fBTcl_Seek\fR(\fIchannel, offset, seekMode\fR)
.sp
Tcl_WideInt
\fBTcl_Tell\fR(\fIchannel\fR)
-.VE 8.4
+.sp
+.VS 8.5
+int
+\fBTcl_TruncateChannel\fR(\fIchannel, length\fR)
+.VE 8.5
.sp
int
\fBTcl_GetChannelOption\fR(\fIinterp, channel, optionName, optionValue\fR)
@@ -115,12 +110,12 @@ int
\fBTcl_SetChannelOption\fR(\fIinterp, channel, optionName, newValue\fR)
.sp
.SH ARGUMENTS
-.AS Tcl_ChannelType newClientProcPtr in
+.AS Tcl_DString *channelName in/out
.AP Tcl_Interp *interp in
Used for error reporting and to look up a channel registered in it.
-.AP "CONST char" *fileName in
+.AP "const char" *fileName in
The name of a local or network file.
-.AP "CONST char" *mode in
+.AP "const char" *mode in
Specifies how the file is to be accessed. May have any of the values
allowed for the \fImode\fR argument to the Tcl \fBopen\fR command.
.AP int permissions in
@@ -128,7 +123,7 @@ POSIX-style permission flags such as 0644. If a new file is created, these
permissions will be set on the created file.
.AP int argc in
The number of elements in \fIargv\fR.
-.AP "CONST char" **argv in
+.AP "const char" **argv in
Arguments for constructing a command pipeline. These values have the same
meaning as the non-switch arguments to the Tcl \fBexec\fR command.
.AP int flags in
@@ -147,20 +142,17 @@ file descriptor, for Windows it is a HANDLE.
.AP int readOrWrite in
OR-ed combination of \fBTCL_READABLE\fR and \fBTCL_WRITABLE\fR to indicate
what operations are valid on \fIhandle\fR.
-.AP "CONST char" *channelName in
+.AP "const char" *channelName in
The name of the channel.
.AP int *modePtr out
Points at an integer variable that will receive an OR-ed combination of
\fBTCL_READABLE\fR and \fBTCL_WRITABLE\fR denoting whether the channel is
open for reading and writing.
-.VS 8.3
-.AP "CONST char" *pattern in
+.AP "const char" *pattern in
The pattern to match on, passed to Tcl_StringMatch, or NULL.
-.VE
.AP Tcl_Channel channel in
A Tcl channel for input or output. Must have been the return value
from a procedure such as \fBTcl_OpenFileChannel\fR.
-.VS 8.1 br
.AP Tcl_Obj *readObjPtr in/out
A pointer to a Tcl Object in which to store the characters read from the
channel.
@@ -184,25 +176,22 @@ object.
A pointer to a Tcl dynamic string in which to store the line read from the
channel. Must have been initialized by the caller. The line read will be
appended to any data already in the dynamic string.
-.VS 8.3
-.AP "CONST char" *input in
+.AP "const char" *input in
The input to add to a channel buffer.
.AP int inputLen in
Length of the input
.AP int addAtEnd in
Flag indicating whether the input should be added to the end or
beginning of the channel buffer.
-.VE
.AP Tcl_Obj *writeObjPtr in
A pointer to a Tcl Object whose contents will be output to the channel.
-.AP "CONST char" *charBuf in
+.AP "const char" *charBuf in
A buffer containing the characters to output to the channel.
-.AP "CONST char" *byteBuf in
+.AP "const char" *byteBuf in
A buffer containing the bytes to output to the channel.
.AP int bytesToWrite in
The number of bytes to consume from \fIcharBuf\fR or \fIbyteBuf\fR and
output to the channel.
-.VE
.AP Tcl_WideInt offset in
How far to move the access point in the channel at which the next input or
output operation will be applied, measured in bytes from the position
@@ -211,13 +200,15 @@ given by \fIseekMode\fR. May be either positive or negative.
Relative to which point to seek; used with \fIoffset\fR to calculate the new
access point for the channel. Legal values are \fBSEEK_SET\fR,
\fBSEEK_CUR\fR, and \fBSEEK_END\fR.
-.AP "CONST char" *optionName in
+.AP Tcl_WideInt length in
+The (non-negative) length to truncate the channel the channel to.
+.AP "const char" *optionName in
The name of an option applicable to this channel, such as \fB\-blocking\fR.
May have any of the values accepted by the \fBfconfigure\fR command.
.AP Tcl_DString *optionValue in
Where to store the value of an option or a list of all options and their
values. Must have been initialized by the caller.
-.AP "CONST char" *newValue in
+.AP "const char" *newValue in
New value for the option given by \fIoptionName\fR.
.BE
@@ -228,7 +219,7 @@ platform-independent mechanism for performing buffered input
and output operations on a variety of file, socket, and device
types.
The channel mechanism is extensible to new channel types, by
-providing a low level channel driver for the new type; the channel driver
+providing a low-level channel driver for the new type; the channel driver
interface is described in the manual entry for \fBTcl_CreateChannel\fR. The
channel mechanism provides a buffering scheme modeled after
Unix's standard I/O, and it also allows for nonblocking I/O on
@@ -255,8 +246,6 @@ leaves an error message in \fIinterp\fR's result after any error.
As of Tcl 8.4, the object-based API \fBTcl_FSOpenFileChannel\fR should
be used in preference to \fBTcl_OpenFileChannel\fR wherever possible.
.PP
-
-.PP
The newly created channel is not registered in the supplied interpreter; to
register it, use \fBTcl_RegisterChannel\fR, described below.
If one of the standard channels, \fBstdin, stdout\fR or \fBstderr\fR was
@@ -349,7 +338,7 @@ reference to a channel that is also registered in a Tcl interpreter.
.PP
This procedure interacts with the code managing the standard
channels. If no standard channels were initialized before the first
-call to \fBTcl_RegisterChannel\fR they will get initialized by that
+call to \fBTcl_RegisterChannel\fR, they will get initialized by that
call. See \fBTcl_StandardChannels\fR for a general treatise about
standard channels and the behaviour of the Tcl library with regard to
them.
@@ -376,7 +365,7 @@ accessible in \fIinterp\fR. After this call, Tcl programs will no longer be
able to use the channel's name to refer to the channel in that interpreter.
Beyond that, this command has no further effect. It cannot be used on
the standard channels (stdout, stderr, stdin), and will return
-TCL_ERROR if passed one of those channels.
+\fBTCL_ERROR\fR if passed one of those channels.
.PP
Code not associated with a Tcl interpreter can call
\fBTcl_DetachChannel\fR with \fIinterp\fR as NULL, to indicate to Tcl
@@ -423,7 +412,6 @@ been given as the \fBchan\fR argument in a call to
when all calls to \fBTcl_RegisterChannel\fR have been matched by
corresponding calls to \fBTcl_UnregisterChannel\fR.
-.VS 8.1 br
.SH "TCL_READCHARS AND TCL_READ"
.PP
\fBTcl_ReadChars\fR consumes bytes from \fIchannel\fR, converting the bytes
@@ -434,7 +422,7 @@ that were stored in \fIreadObjPtr\fR. If an error occurs while reading, the
return value is \-1 and \fBTcl_ReadChars\fR records a POSIX error code that
can be retrieved with \fBTcl_GetErrno\fR.
.PP
-Setting \fIcharsToRead\fR to \fB-1\fR will cause the command to read
+Setting \fIcharsToRead\fR to \fB\-1\fR will cause the command to read
all characters currently available (non-blocking) or everything until
eof (blocking mode).
.PP
@@ -467,7 +455,7 @@ from a channel, manipulated by calling \fBTcl_GetByteArrayFromObj\fR and
related functions, and then written to a channel without the expense of ever
converting to or from UTF-8.
.PP
-\fBTcl_Read\fR is similar to \fBTcl_ReadChars\fR, except that it doesn't do
+\fBTcl_Read\fR is similar to \fBTcl_ReadChars\fR, except that it does not do
encoding conversions, regardless of the channel's encoding. It is deprecated
and exists for backwards compatibility with non-internationalized Tcl
extensions. It consumes bytes from \fIchannel\fR and stores them in
@@ -519,9 +507,11 @@ at either the head or tail of the queue. The pointer \fIinput\fR points
to the data that is to be added. The length of the input to add is given
by \fIinputLen\fR. A non-zero value of \fIaddAtEnd\fR indicates that the
data is to be added at the end of queue; otherwise it will be added at the
-head of the queue. If \fIchannel\fR has a "sticky" EOF set, no data will be
+head of the queue. If \fIchannel\fR has a
+.QW sticky
+EOF set, no data will be
added to the input queue. \fBTcl_Ungets\fR returns \fIinputLen\fR or
--1 if an error occurs.
+\-1 if an error occurs.
.SH "TCL_WRITECHARS, TCL_WRITEOBJ, AND TCL_WRITE"
.PP
@@ -561,7 +551,7 @@ byte-oriented data can be read from a channel, manipulated by calling
\fBTcl_GetByteArrayFromObj\fR and related functions, and then written to a
channel without the expense of ever converting to or from UTF-8.
.PP
-\fBTcl_Write\fR is similar to \fBTcl_WriteChars\fR except that it doesn't do
+\fBTcl_Write\fR is similar to \fBTcl_WriteChars\fR except that it does not do
encoding conversions, regardless of the channel's encoding. It is
deprecated and exists for backwards compatibility with non-internationalized
Tcl extensions. It accepts \fIbytesToWrite\fR bytes of data at
@@ -577,7 +567,6 @@ not. Thus this function is \fBonly\fR usable for transformational
channel drivers, i.e. drivers used in the middle of a stack of
channels, to move data from the transformation into the channel below
it.
-.VE
.SH TCL_FLUSH
.PP
@@ -609,6 +598,14 @@ After an error, the access point may or may not have been moved.
\fBTcl_Tell\fR returns the current access point for a channel. The returned
value is \-1 if the channel does not support seeking.
+.SH TCL_TRUNCATECHANNEL
+.PP
+.VS 8.5
+\fBTcl_TruncateChannel\fR truncates the file underlying \fIchannel\fR
+to a given \fIlength\fR of bytes. It returns \fBTCL_OK\fR if the
+operation succeeded, and \fBTCL_ERROR\fR otherwise.
+.VE 8.5
+
.SH TCL_GETCHANNELOPTION
.PP
\fBTcl_GetChannelOption\fR retrieves, in \fIoptionValue\fR, the value of one of
@@ -658,11 +655,9 @@ buffered in the internal buffers for a channel. If the channel is not open
for reading, this function always returns zero.
.SH TCL_OUTPUTBUFFERED
-.VS 8.4
\fBTcl_OutputBuffered\fR returns the number of bytes of output
currently buffered in the internal buffers for a channel. If the
channel is not open for writing, this function always returns zero.
-.VE
.SH "PLATFORM ISSUES"
.PP
@@ -673,8 +668,7 @@ call. On Windows platforms, the handle is a file \fBHANDLE\fR when
the channel was created with \fBTcl_OpenFileChannel\fR,
\fBTcl_OpenCommandChannel\fR, or \fBTcl_MakeFileChannel\fR. Other
channel types may return a different type of handle on Windows
-platforms. On the Macintosh platform, the handle is a file reference
-number as returned from \fBHOpenDF\fR.
+platforms.
.SH "SEE ALSO"
DString(3), fconfigure(n), filename(n), fopen(3), Tcl_CreateChannel(3)
diff --git a/doc/OpenTcp.3 b/doc/OpenTcp.3
index 4ddb8a7..98d8cb0 100644
--- a/doc/OpenTcp.3
+++ b/doc/OpenTcp.3
@@ -24,18 +24,18 @@ Tcl_Channel
\fBTcl_OpenTcpServer\fR(\fIinterp, port, myaddr, proc, clientData\fR)
.sp
.SH ARGUMENTS
-.AS Tcl_ChannelType newClientProcPtr in
+.AS Tcl_TcpAcceptProc clientData
.AP Tcl_Interp *interp in
Tcl interpreter to use for error reporting. If non-NULL and an
error occurs, an error message is left in the interpreter's result.
.AP int port in
A port number to connect to as a client or to listen on as a server.
-.AP "CONST char" *host in
+.AP "const char" *host in
A string specifying a host name or address for the remote end of the connection.
.AP int myport in
A port number for the client's end of the socket. If 0, a port number
is allocated at random.
-.AP "CONST char" *myaddr in
+.AP "const char" *myaddr in
A string specifying the host name or address for network interface to use
for the local end of the connection. If NULL, a default interface is
chosen.
@@ -113,24 +113,24 @@ replacement for the standard channel.
.PP
\fBTcl_OpenTcpServer\fR opens a TCP socket on the local host on a specified
\fIport\fR and uses the Tcl event mechanism to accept requests from clients
-to connect to it. The \fImyaddr\fP argument specifies the network interface.
-If \fImyaddr\fP is NULL the special address INADDR_ANY should be used to
+to connect to it. The \fImyaddr\fR argument specifies the network interface.
+If \fImyaddr\fR is NULL the special address INADDR_ANY should be used to
allow connections from any network interface.
Each time a client connects to this socket, Tcl creates a channel
for the new connection and invokes \fIproc\fR with information about
-the channel. \fIProc\fR must match the following prototype:
+the channel. \fIProc\fR must match the following prototype:
.CS
typedef void Tcl_TcpAcceptProc(
- ClientData \fIclientData\fR,
- Tcl_Channel \fIchannel\fR,
- char *\fIhostName\fR,
- int \fIport\fP);
+ ClientData \fIclientData\fR,
+ Tcl_Channel \fIchannel\fR,
+ char *\fIhostName\fR,
+ int \fIport\fR);
.CE
.PP
The \fIclientData\fR argument will be the same as the \fIclientData\fR
argument to \fBTcl_OpenTcpServer\fR, \fIchannel\fR will be the handle
for the new channel, \fIhostName\fR points to a string containing
-the name of the client host making the connection, and \fIport\fP
+the name of the client host making the connection, and \fIport\fR
will contain the client's port number.
The new channel
is opened for both input and output.
@@ -162,14 +162,11 @@ If one of the standard channels, \fBstdin, stdout\fR or \fBstderr\fR was
previously closed, the act of creating the new channel also assigns it as a
replacement for the standard channel.
-.VS
.SH "PLATFORM ISSUES"
.PP
On Unix platforms, the socket handle is a Unix file descriptor as
returned by the \fBsocket\fR system call. On the Windows platform, the
-socket handle is a \fBSOCKET\fR as defined in the WinSock API. On the
-Macintosh platform, the socket handle is a \fBStreamPtr\fR.
-.VE
+socket handle is a \fBSOCKET\fR as defined in the WinSock API.
.SH "SEE ALSO"
Tcl_OpenFileChannel(3), Tcl_RegisterChannel(3), vwait(n)
diff --git a/doc/Panic.3 b/doc/Panic.3
index 3fb0c83..b53ca11 100644
--- a/doc/Panic.3
+++ b/doc/Panic.3
@@ -7,7 +7,7 @@
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
-Tcl_Panic, Tcl_PanicVA, Tcl_SetPanicProc, panic, panicVA \- report fatal error and abort
+Tcl_Panic, Tcl_PanicVA, Tcl_SetPanicProc \- report fatal error and abort
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -21,21 +21,15 @@ void
void
\fBTcl_SetPanicProc\fR(\fIpanicProc\fR)
.sp
-void
-\fBpanic\fR(\fIformat\fR, \fIarg\fR, \fIarg\fR, \fI...\fR)
-.sp
-void
-\fBpanicVA\fR(\fIformat\fR, \fIargList\fR)
-.sp
.SH ARGUMENTS
.AS Tcl_PanicProc *panicProc
-.AP "CONST char*" format in
+.AP "const char*" format in
A printf-style format string.
.AP "" arg in
Arguments matching the format string.
.AP va_list argList in
An argument list of arguments matching the format string.
-Must have been initialized using \fBTCL_VARARGS_START\fR,
+Must have been initialized using \fBva_start\fR,
and cleared using \fBva_end\fR.
.AP Tcl_PanicProc *panicProc in
Procedure to report fatal error message and abort.
@@ -51,7 +45,7 @@ to display a message describing the error and abort the process. The
\fIformat\fR argument is a format string describing how to format the
remaining arguments \fIarg\fR into an error message, according to the
same formatting rules used by the \fBprintf\fR family of functions. The
-same formatting rules are also used by the builtin Tcl command
+same formatting rules are also used by the built-in Tcl command
\fBformat\fR.
.PP
In a freshly loaded Tcl library, \fBTcl_Panic\fR prints the formatted
@@ -65,8 +59,8 @@ type \fBTcl_PanicProc\fR:
.PP
.CS
typedef void Tcl_PanicProc(
- CONST char *\fBformat\fR,
- \fBarg\fR, \fBarg\fR,...);
+ const char *\fBformat\fR,
+ \fBarg\fR, \fBarg\fR,...);
.CE
.PP
After \fBTcl_SetPanicProc\fR returns, any future calls to
@@ -92,11 +86,7 @@ have a panic message displayed the same way that panic messages from Tcl
will be displayed.
.PP
\fBTcl_PanicVA\fR is the same as \fBTcl_Panic\fR except that instead of
-taking a variable number of arguments it takes an argument list. The
-procedures \fBpanic\fR and \fBpanicVA\fR are synonyms (implemented as
-macros) for \fBTcl_Panic\fR and \fBTcl_PanicVA\fR, respectively. They
-exist to support old code; new code should use direct calls to
-\fBTcl_Panic\fR or \fBTcl_PanicVA\fR.
+taking a variable number of arguments it takes an argument list.
.SH "SEE ALSO"
abort(3), printf(3), exec(n), format(n)
diff --git a/doc/ParseCmd.3 b/doc/ParseCmd.3
index af6b02e..b5fc6d0 100644
--- a/doc/ParseCmd.3
+++ b/doc/ParseCmd.3
@@ -14,22 +14,22 @@ Tcl_ParseCommand, Tcl_ParseExpr, Tcl_ParseBraces, Tcl_ParseQuotedString, Tcl_Par
\fB#include <tcl.h>\fR
.sp
int
-\fBTcl_ParseCommand\fR(\fIinterp, string, numBytes, nested, parsePtr\fR)
+\fBTcl_ParseCommand\fR(\fIinterp, start, numBytes, nested, parsePtr\fR)
.sp
int
-\fBTcl_ParseExpr\fR(\fIinterp, string, numBytes, parsePtr\fR)
+\fBTcl_ParseExpr\fR(\fIinterp, start, numBytes, parsePtr\fR)
.sp
int
-\fBTcl_ParseBraces\fR(\fIinterp, string, numBytes, parsePtr, append, termPtr\fR)
+\fBTcl_ParseBraces\fR(\fIinterp, start, numBytes, parsePtr, append, termPtr\fR)
.sp
int
-\fBTcl_ParseQuotedString\fR(\fIinterp, string, numBytes, parsePtr, append, termPtr\fR)
+\fBTcl_ParseQuotedString\fR(\fIinterp, start, numBytes, parsePtr, append, termPtr\fR)
.sp
int
-\fBTcl_ParseVarName\fR(\fIinterp, string, numBytes, parsePtr, append\fR)
+\fBTcl_ParseVarName\fR(\fIinterp, start, numBytes, parsePtr, append\fR)
.sp
-CONST char *
-\fBTcl_ParseVar\fR(\fIinterp, string, termPtr\fR)
+const char *
+\fBTcl_ParseVar\fR(\fIinterp, start, termPtr\fR)
.sp
\fBTcl_FreeParse\fR(\fIusedParsePtr\fR)
.sp
@@ -39,7 +39,7 @@ Tcl_Obj *
int
\fBTcl_EvalTokensStandard\fR(\fIinterp, tokenPtr, numTokens\fR)
.SH ARGUMENTS
-.AS Tcl_Interp *usedParsePtr
+.AS Tcl_Interp *usedParsePtr out
.AP Tcl_Interp *interp out
For procedures other than \fBTcl_FreeParse\fR, \fBTcl_EvalTokens\fR
and \fBTcl_EvalTokensStandard\fR, used only for error reporting;
@@ -47,12 +47,12 @@ if NULL, then no error messages are left after errors.
For \fBTcl_EvalTokens\fR and \fBTcl_EvalTokensStandard\fR,
determines the context for evaluating the
script and also is used for error reporting; must not be NULL.
-.AP "CONST char" *string in
+.AP "const char" *start in
Pointer to first character in string to parse.
.AP int numBytes in
-Number of bytes in \fIstring\fR, not including any terminating null
+Number of bytes in string to parse, not including any terminating null
character. If less than 0 then the script consists of all characters
-in \fIstring\fR up to the first null character.
+following \fIstart\fR up to the first null character.
.AP int nested in
Non-zero means that the script is part of a command substitution so an
unquoted close bracket should be treated as a command terminator. If zero,
@@ -69,7 +69,7 @@ Any previous information in this structure
is ignored, unless \fIappend\fR is non-zero in a call to
\fBTcl_ParseBraces\fR, \fBTcl_ParseQuotedString\fR,
or \fBTcl_ParseVarName\fR.
-.AP "CONST char" **termPtr out
+.AP "const char" **termPtr out
If not NULL, points to a location where
\fBTcl_ParseBraces\fR, \fBTcl_ParseQuotedString\fR, and
\fBTcl_ParseVar\fR will store a pointer to the character
@@ -90,7 +90,7 @@ and fills in the structure pointed to by \fIparsePtr\fR
with a collection of tokens describing the information that was parsed.
The procedures normally return \fBTCL_OK\fR.
However, if an error occurs then they return \fBTCL_ERROR\fR,
-leave an error message in \fIinterp's\fR result
+leave an error message in \fIinterp\fR's result
(if \fIinterp\fR is not NULL),
and leave nothing in \fIparsePtr\fR.
.PP
@@ -117,9 +117,9 @@ result, and no information is left at \fI*parsePtr\fR.
.PP
\fBTcl_ParseBraces\fR parses a string or command argument
enclosed in braces such as
-\fB{hello}\fR or \fB{string \\t with \\t tabs}\fR
-from the beginning of its argument \fIstring\fR.
-The first character of \fIstring\fR must be \fB{\fR.
+\fB{hello}\fR or \fB{string \et with \et tabs}\fR
+from the beginning of its argument \fIstart\fR.
+The first character of \fIstart\fR must be \fB{\fR.
If the braced string was parsed successfully,
\fBTcl_ParseBraces\fR returns \fBTCL_OK\fR,
fills in the structure pointed to by \fIparsePtr\fR
@@ -133,15 +133,15 @@ an error message is left in \fIinterp\fR's result,
and no information is left at \fI*parsePtr\fR or \fI*termPtr\fR.
.PP
\fBTcl_ParseQuotedString\fR parses a double-quoted string such as
-\fB"sum is [expr $a+$b]"\fR
-from the beginning of the argument \fIstring\fR.
-The first character of \fIstring\fR must be \fB"\fR.
+\fB"sum is [expr {$a+$b}]"\fR
+from the beginning of the argument \fIstart\fR.
+The first character of \fIstart\fR must be \fB\N'34'\fR.
If the double-quoted string was parsed successfully,
\fBTcl_ParseQuotedString\fR returns \fBTCL_OK\fR,
fills in the structure pointed to by \fIparsePtr\fR
with information about the structure of the string
(see below for details),
-and stores a pointer to the character just after the terminating \fB"\fR
+and stores a pointer to the character just after the terminating \fB\N'34'\fR
in the location given by \fI*termPtr\fR.
If an error occurs while parsing the string
then \fBTCL_ERROR\fR is returned,
@@ -149,20 +149,20 @@ an error message is left in \fIinterp\fR's result,
and no information is left at \fI*parsePtr\fR or \fI*termPtr\fR.
.PP
\fBTcl_ParseVarName\fR parses a Tcl variable reference such as
-\fB$abc\fR or \fB$x([expr $index + 1])\fR from the beginning of its
-\fIstring\fR argument.
-The first character of \fIstring\fR must be \fB$\fR.
+\fB$abc\fR or \fB$x([expr {$index + 1}])\fR from the beginning of its
+\fIstart\fR argument.
+The first character of \fIstart\fR must be \fB$\fR.
If a variable name was parsed successfully, \fBTcl_ParseVarName\fR
returns \fBTCL_OK\fR and fills in the structure pointed to by
\fIparsePtr\fR with information about the structure of the variable name
(see below for details). If an error
occurs while parsing the command then \fBTCL_ERROR\fR is returned, an
-error message is left in \fIinterp\fR's result (if \fIinterp\fR isn't
+error message is left in \fIinterp\fR's result (if \fIinterp\fR is not
NULL), and no information is left at \fI*parsePtr\fR.
.PP
\fBTcl_ParseVar\fR parse a Tcl variable reference such as \fB$abc\fR
-or \fB$x([expr $index + 1])\fR from the beginning of its \fIstring\fR
-argument. The first character of \fIstring\fR must be \fB$\fR. If
+or \fB$x([expr {$index + 1}])\fR from the beginning of its \fIstart\fR
+argument. The first character of \fIstart\fR must be \fB$\fR. If
the variable name is parsed successfully, \fBTcl_ParseVar\fR returns a
pointer to the string value of the variable. If an error occurs while
parsing, then NULL is returned and an error message is left in
@@ -210,21 +210,21 @@ of \fBTcl_EvalTokens\fR is deprecated.
return parse information in two data structures, Tcl_Parse and Tcl_Token:
.CS
typedef struct Tcl_Parse {
- CONST char *\fIcommentStart\fR;
- int \fIcommentSize\fR;
- CONST char *\fIcommandStart\fR;
- int \fIcommandSize\fR;
- int \fInumWords\fR;
- Tcl_Token *\fItokenPtr\fR;
- int \fInumTokens\fR;
- ...
+ const char *\fIcommentStart\fR;
+ int \fIcommentSize\fR;
+ const char *\fIcommandStart\fR;
+ int \fIcommandSize\fR;
+ int \fInumWords\fR;
+ Tcl_Token *\fItokenPtr\fR;
+ int \fInumTokens\fR;
+ ...
} Tcl_Parse;
typedef struct Tcl_Token {
- int \fItype\fR;
- CONST char *\fIstart\fR;
- int \fIsize\fR;
- int \fInumComponents\fR;
+ int \fItype\fR;
+ const char *\fIstart\fR;
+ int \fIsize\fR;
+ int \fInumComponents\fR;
} Tcl_Token;
.CE
.PP
@@ -285,6 +285,16 @@ This token has the same meaning as \fBTCL_TOKEN_WORD\fR, except that
the word is guaranteed to consist of a single \fBTCL_TOKEN_TEXT\fR
sub-token. The \fInumComponents\fR field is always 1.
.TP
+\fBTCL_TOKEN_EXPAND_WORD\fR
+.VS 8.5
+This token has the same meaning as \fBTCL_TOKEN_WORD\fR, except that
+the command parser notes this word began with the expansion
+prefix \fB{*}\fR, indicating that after substitution,
+the list value of this word should be expanded to form multiple
+arguments in command evaluation. This
+token type can only be created by Tcl_ParseCommand.
+.VE 8.5
+.TP
\fBTCL_TOKEN_TEXT\fR
The token describes a range of literal text that is part of a word.
The \fInumComponents\fR field is always 0.
@@ -294,7 +304,7 @@ The token describes a backslash sequence such as \fB\en\fR or \fB\e0xa3\fR.
The \fInumComponents\fR field is always 0.
.TP
\fBTCL_TOKEN_COMMAND\fR
-The token describes a command whose result result must be substituted into
+The token describes a command whose result must be substituted into
the word. The token includes the square brackets that surround the
command. The \fInumComponents\fR field is always 0 (the nested command
is not parsed; call \fBTcl_ParseCommand\fR recursively if you want to
@@ -344,7 +354,7 @@ this includes the sub-tokens for any nested \fBTCL_TOKEN_SUB_EXPR\fR tokens.
\fBTCL_TOKEN_OPERATOR\fR
The token describes one operator of an expression
such as \fB&&\fR or \fBhypot\fR.
-An \fBTCL_TOKEN_OPERATOR\fR token is always preceded by a
+A \fBTCL_TOKEN_OPERATOR\fR token is always preceded by a
\fBTCL_TOKEN_SUB_EXPR\fR token
that describes the operator and its operands;
the \fBTCL_TOKEN_SUB_EXPR\fR token's \fInumComponents\fR field
@@ -352,7 +362,7 @@ can be used to determine the number of operands.
A binary operator such as \fB*\fR
is followed by two \fBTCL_TOKEN_SUB_EXPR\fR tokens
that describe its operands.
-A unary operator like \fB-\fR
+A unary operator like \fB\-\fR
is followed by a single \fBTCL_TOKEN_SUB_EXPR\fR token
for its operand.
If the operator is a math function such as \fBlog10\fR,
@@ -373,12 +383,16 @@ is always 0.
After \fBTcl_ParseCommand\fR returns, the first token pointed to by
the \fItokenPtr\fR field of the
Tcl_Parse structure always has type \fBTCL_TOKEN_WORD\fR or
-\fBTCL_TOKEN_SIMPLE_WORD\fR. It is followed by the sub-tokens
+.VS 8.5
+\fBTCL_TOKEN_SIMPLE_WORD\fR or \fBTCL_TOKEN_EXPAND_WORD\fR.
+It is followed by the sub-tokens
that must be concatenated to produce the value of that word.
The next token is the \fBTCL_TOKEN_WORD\fR or \fBTCL_TOKEN_SIMPLE_WORD\fR
-token for the second word, followed by sub-tokens for that
+of \fBTCL_TOKEN_EXPAND_WORD\fR token for the second word,
+followed by sub-tokens for that
word, and so on until all \fInumWords\fR have been accounted
for.
+.VE 8.5
.PP
After \fBTcl_ParseExpr\fR returns, the first token pointed to by
the \fItokenPtr\fR field of the
@@ -415,7 +429,7 @@ Tcl_Parse structure depends on the contents of the quoted string.
It will consist of one or more \fBTCL_TOKEN_TEXT\fR, \fBTCL_TOKEN_BS\fR,
\fBTCL_TOKEN_COMMAND\fR, and \fBTCL_TOKEN_VARIABLE\fR sub-tokens.
The array always contains at least one token;
-for example, if the argument \fIstring\fR is empty,
+for example, if the argument \fIstart\fR is empty,
the array returned consists of a single \fBTCL_TOKEN_TEXT\fR token
with a zero \fIsize\fR field.
Only the token information in the Tcl_Parse structure
@@ -436,7 +450,7 @@ the \fIcommentStart\fR, \fIcommentSize\fR,
.PP
All of the character pointers in the
Tcl_Parse and Tcl_Token structures refer
-to characters in the \fIstring\fR argument passed to
+to characters in the \fIstart\fR argument passed to
\fBTcl_ParseCommand\fR, \fBTcl_ParseExpr\fR, \fBTcl_ParseBraces\fR,
\fBTcl_ParseQuotedString\fR, and \fBTcl_ParseVarName\fR.
.PP
diff --git a/doc/PkgRequire.3 b/doc/PkgRequire.3
index fcccd58..810947d 100644
--- a/doc/PkgRequire.3
+++ b/doc/PkgRequire.3
@@ -8,21 +8,24 @@
.TH Tcl_PkgRequire 3 7.5 Tcl "Tcl Library Procedures"
.BS
.SH NAME
-Tcl_PkgRequire, Tcl_PkgRequireEx, Tcl_PkgPresent, Tcl_PkgPresentEx, Tcl_PkgProvide, Tcl_PkgProvideEx \- package version control
+Tcl_PkgRequire, Tcl_PkgRequireEx, Tcl_PkgRequireProc, Tcl_PkgPresent, Tcl_PkgPresentEx, Tcl_PkgProvide, Tcl_PkgProvideEx \- package version control
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
-CONST char *
+const char *
\fBTcl_PkgRequire\fR(\fIinterp, name, version, exact\fR)
.sp
-CONST char *
+const char *
\fBTcl_PkgRequireEx\fR(\fIinterp, name, version, exact, clientDataPtr\fR)
.sp
-CONST char *
+int
+\fBTcl_PkgRequireProc\fR(\fIinterp, name, objc, objv, clientDataPtr\fR)
+.sp
+const char *
\fBTcl_PkgPresent\fR(\fIinterp, name, version, exact\fR)
.sp
-CONST char *
+const char *
\fBTcl_PkgPresentEx\fR(\fIinterp, name, version, exact, clientDataPtr\fR)
.sp
int
@@ -31,12 +34,12 @@ int
int
\fBTcl_PkgProvideEx\fR(\fIinterp, name, version, clientData\fR)
.SH ARGUMENTS
-.AS ClientData clientDataPtr
+.AS ClientData clientDataPtr out
.AP Tcl_Interp *interp in
Interpreter where package is needed or available.
-.AP "CONST char" *name in
+.AP "const char" *name in
Name of package.
-.AP "CONST char" *version in
+.AP "const char" *version in
A version string consisting of one or more decimal numbers
separated by dots.
.AP int exact in
@@ -51,7 +54,12 @@ Arbitrary value to be associated with the package.
Pointer to place to store the value associated with the matching
package. It is only changed if the pointer is not NULL and the
function completed successfully.
+.AP int objc in
+Number of requirements.
+.AP Tcl_Obj* objv[] in
+Array of requirements.
.BE
+
.SH DESCRIPTION
.PP
These procedures provide C-level interfaces to Tcl's package and
@@ -71,13 +79,18 @@ that is provided in the interpreter (which may be different than
\fIversion\fR); if an error occurs they return NULL and leave an error
message in the interpreter's result.
.PP
-\fBTcl_PkgProvide\fR returns TCL_OK if it completes successfully;
-if an error occurs it returns TCL_ERROR and leaves an error message
+\fBTcl_PkgProvide\fR returns \fBTCL_OK\fR if it completes successfully;
+if an error occurs it returns \fBTCL_ERROR\fR and leaves an error message
in the interpreter's result.
.PP
\fBTcl_PkgProvideEx\fR, \fBTcl_PkgPresentEx\fR and \fBTcl_PkgRequireEx\fR
allow the setting and retrieving of the client data associated with
the package. In all other respects they are equivalent to the matching
functions.
+.PP
+\fBTcl_PkgRequireProc\fR is the form of \fBpackage require\fR handling
+multiple requirements. The other forms are present for backward
+compatibility and translate their invocations to this form.
+
.SH KEYWORDS
package, present, provide, require, version
diff --git a/doc/Preserve.3 b/doc/Preserve.3
index b5d608e..2b3edc0 100644
--- a/doc/Preserve.3
+++ b/doc/Preserve.3
@@ -9,7 +9,7 @@
.TH Tcl_Preserve 3 7.5 Tcl "Tcl Library Procedures"
.BS
.SH NAME
-Tcl_Preserve, Tcl_Release, Tcl_EventuallyFree \- avoid freeing storage while it's being used
+Tcl_Preserve, Tcl_Release, Tcl_EventuallyFree \- avoid freeing storage while it is being used
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -36,7 +36,7 @@ having to do with widget deletion, but are also useful in many other
situations. When a widget is deleted, its
widget record (the structure holding information specific to the
widget) must be returned to the storage allocator.
-However, it's possible that the widget record is in active use
+However, it is possible that the widget record is in active use
by one of the procedures on the stack at the time of the deletion.
This can happen, for example, if the command associated with a button
widget causes the button to be destroyed: an X event causes an
diff --git a/doc/PrintDbl.3 b/doc/PrintDbl.3
index 75e7663..279b4d5 100644
--- a/doc/PrintDbl.3
+++ b/doc/PrintDbl.3
@@ -16,19 +16,17 @@ Tcl_PrintDouble \- Convert floating value to string
.sp
\fBTcl_PrintDouble\fR(\fIinterp, value, dst\fR)
.SH ARGUMENTS
-.AS Tcl_Interp *interp
+.AS Tcl_Interp *interp out
.AP Tcl_Interp *interp in
-.VS
Before Tcl 8.0, the \fBtcl_precision\fR variable in this interpreter
controlled the conversion. As of Tcl 8.0, this argument is ignored and
the conversion is controlled by the \fBtcl_precision\fR variable
that is now shared by all interpreters.
-.VE
.AP double value in
Floating-point value to be converted.
.AP char *dst out
-Where to store string representing \fIvalue\fR. Must have at
-least TCL_DOUBLE_SPACE characters of storage.
+Where to store the string representing \fIvalue\fR. Must have at
+least \fBTCL_DOUBLE_SPACE\fR characters of storage.
.BE
.SH DESCRIPTION
@@ -36,10 +34,22 @@ least TCL_DOUBLE_SPACE characters of storage.
\fBTcl_PrintDouble\fR generates a string that represents the value
of \fIvalue\fR and stores it in memory at the location given by
\fIdst\fR. It uses \fB%g\fR format to generate the string, with one
-special twist: the string is guaranteed to contain either
-a ``.'' or an ``e'' so that it doesn't look like an integer. Where
-\fB%g\fR would generate an integer with no decimal point, \fBTcl_PrintDouble\fR
-adds ``.0''.
+special twist: the string is guaranteed to contain either a
+.QW .
+or an
+.QW e
+so that it does not look like an integer. Where \fB%g\fR would
+generate an integer with no decimal point, \fBTcl_PrintDouble\fR adds
+.QW .0 .
+.VS 8.5
+.PP
+If the \fBtcl_precision\fR value is non-zero, the result will have
+precisely that many digits of significance. If the value is zero
+(the default), the result will have the fewest digits needed to
+represent the number in such a way that \fBTcl_NewDoubleObj\fR
+will generate the same number when presented with the given string.
+IEEE semantics of rounding to even apply to the conversion.
+.VE
.SH KEYWORDS
conversion, double-precision, floating-point, string
diff --git a/doc/RecEvalObj.3 b/doc/RecEvalObj.3
index 25982c8..2eed471 100644
--- a/doc/RecEvalObj.3
+++ b/doc/RecEvalObj.3
@@ -16,15 +16,15 @@ Tcl_RecordAndEvalObj \- save command on history list before evaluating
int
\fBTcl_RecordAndEvalObj\fR(\fIinterp, cmdPtr, flags\fR)
.SH ARGUMENTS
-.AS Tcl_Interp *interp;
+.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Tcl interpreter in which to evaluate command.
.AP Tcl_Obj *cmdPtr in
Points to a Tcl object containing a command (or sequence of commands)
to execute.
.AP int flags in
-An OR'ed combination of flag bits. TCL_NO_EVAL means record the
-command but don't evaluate it. TCL_EVAL_GLOBAL means evaluate
+An OR'ed combination of flag bits. \fBTCL_NO_EVAL\fR means record the
+command but do not evaluate it. \fBTCL_EVAL_GLOBAL\fR means evaluate
the command at global level instead of the current stack level.
.BE
@@ -32,18 +32,18 @@ the command at global level instead of the current stack level.
.PP
\fBTcl_RecordAndEvalObj\fR is invoked to record a command as an event
on the history list and then execute it using \fBTcl_EvalObjEx\fR
-(or \fBTcl_GlobalEvalObj\fR if the TCL_EVAL_GLOBAL bit is set
+(or \fBTcl_GlobalEvalObj\fR if the \fBTCL_EVAL_GLOBAL\fR bit is set
in \fIflags\fR).
-It returns a completion code such as TCL_OK just like \fBTcl_EvalObjEx\fR,
+It returns a completion code such as \fBTCL_OK\fR just like \fBTcl_EvalObjEx\fR,
as well as a result object containing additional information
(a result value or error message)
that can be retrieved using \fBTcl_GetObjResult\fR.
-If you don't want the command recorded on the history list then
+If you do not want the command recorded on the history list then
you should invoke \fBTcl_EvalObjEx\fR instead of \fBTcl_RecordAndEvalObj\fR.
Normally \fBTcl_RecordAndEvalObj\fR is only called with top-level
commands typed by the user, since the purpose of history is to
-allow the user to re-issue recently-invoked commands.
-If the \fIflags\fR argument contains the TCL_NO_EVAL bit then
+allow the user to re-issue recently invoked commands.
+If the \fIflags\fR argument contains the \fBTCL_NO_EVAL\fR bit then
the command is recorded without being evaluated.
.SH "SEE ALSO"
diff --git a/doc/RecordEval.3 b/doc/RecordEval.3
index 4ca030d..a8f3087 100644
--- a/doc/RecordEval.3
+++ b/doc/RecordEval.3
@@ -17,14 +17,14 @@ Tcl_RecordAndEval \- save command on history list before evaluating
int
\fBTcl_RecordAndEval\fR(\fIinterp, cmd, flags\fR)
.SH ARGUMENTS
-.AS Tcl_Interp *interp;
+.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Tcl interpreter in which to evaluate command.
-.AP "CONST char" *cmd in
+.AP "const char" *cmd in
Command (or sequence of commands) to execute.
.AP int flags in
-An OR'ed combination of flag bits. TCL_NO_EVAL means record the
-command but don't evaluate it. TCL_EVAL_GLOBAL means evaluate
+An OR'ed combination of flag bits. \fBTCL_NO_EVAL\fR means record the
+command but do not evaluate it. \fBTCL_EVAL_GLOBAL\fR means evaluate
the command at global level instead of the current stack level.
.BE
@@ -32,15 +32,15 @@ the command at global level instead of the current stack level.
.PP
\fBTcl_RecordAndEval\fR is invoked to record a command as an event
on the history list and then execute it using \fBTcl_Eval\fR
-(or \fBTcl_GlobalEval\fR if the TCL_EVAL_GLOBAL bit is set in \fIflags\fR).
-It returns a completion code such as TCL_OK just like \fBTcl_Eval\fR
+(or \fBTcl_GlobalEval\fR if the \fBTCL_EVAL_GLOBAL\fR bit is set in \fIflags\fR).
+It returns a completion code such as \fBTCL_OK\fR just like \fBTcl_Eval\fR
and it leaves information in the interpreter's result.
-If you don't want the command recorded on the history list then
+If you do not want the command recorded on the history list then
you should invoke \fBTcl_Eval\fR instead of \fBTcl_RecordAndEval\fR.
Normally \fBTcl_RecordAndEval\fR is only called with top-level
commands typed by the user, since the purpose of history is to
allow the user to re-issue recently-invoked commands.
-If the \fIflags\fR argument contains the TCL_NO_EVAL bit then
+If the \fIflags\fR argument contains the \fBTCL_NO_EVAL\fR bit then
the command is recorded without being evaluated.
.PP
Note that \fBTcl_RecordAndEval\fR has been largely replaced by the
diff --git a/doc/RegConfig.3 b/doc/RegConfig.3
new file mode 100644
index 0000000..19c0bb0
--- /dev/null
+++ b/doc/RegConfig.3
@@ -0,0 +1,112 @@
+'\"
+'\" Copyright (c) 2002 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.so man.macros
+.TH Tcl_RegisterConfig 3 8.4 Tcl "Tcl Library Procedures"
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+Tcl_RegisterConfig \- procedures to register embedded configuration information
+.SH SYNOPSIS
+.nf
+\fB#include <tcl.h>\fR
+.sp
+void
+\fBTcl_RegisterConfig\fR(\fIinterp, pkgName, configuration, valEncoding\fR)
+.sp
+.SH ARGUMENTS
+.AS Tcl_Interp *configuration
+.AP Tcl_Interp *interp in
+Refers to the interpreter the embedded configuration information is
+registered for. Must not be NULL.
+.AP "const char" *pkgName in
+Contains the name of the package registering the embedded
+configuration as ASCII string. This means that this information is in
+UTF-8 too. Must not be NULL.
+.AP Tcl_Config *configuration in
+Refers to an array of Tcl_Config entries containing the information
+embedded in the binary library. Must not be NULL. The end of the array
+is signaled by either a key identical to NULL, or a key referring to
+the empty string.
+.AP "const char" *valEncoding in
+Contains the name of the encoding used to store the configuration
+values as ASCII string. This means that this information is in UTF-8
+too. Must not be NULL.
+.BE
+
+.SH DESCRIPTION
+.PP
+The function described here has its base in TIP 59 and provides
+extensions with support for the embedding of configuration
+information into their binary library and the generation of a
+Tcl-level interface for querying this information.
+.PP
+To embed configuration information into their binary library an
+extension has to define a non-volatile array of Tcl_Config entries in
+one if its source files and then call \fBTcl_RegisterConfig\fR to
+register that information.
+.PP
+\fBTcl_RegisterConfig\fR takes four arguments; first, a reference to
+the interpreter we are registering the information with, second, the
+name of the package registering its configuration information, third,
+a pointer to an array of structures, and fourth a string declaring the
+encoding used by the configuration values.
+.PP
+The string \fIvalEncoding\fR contains the name of an encoding known to
+Tcl. All these names are use only characters in the ASCII subset of
+UTF-8 and are thus implicitly in the UTF-8 encoding. It is expected
+that keys are legible English text and therefore using the ASCII
+subset of UTF-8. In other words, they are expected to be in UTF-8
+too. The values associated with the keys can be any string
+however. For these the contents of \fIvalEncoding\fR define which
+encoding was used to represent the characters of the strings.
+.PP
+Each element of the \fIconfiguration\fR array refers to two strings
+containing the key and the value associated with that key. The end of
+the array is signaled by either an empty key or a key identical to
+NULL. The function makes \fBno\fR copy of the \fIconfiguration\fR
+array. This means that the caller has to make sure that the memory
+holding this array is never released. This is the meaning behind the
+word \fBnon-volatile\fR used earlier. The easiest way to accomplish
+this is to define a global static array of Tcl_Config entries. See the file
+.QW generic/tclPkgConfig.c
+in the sources of the Tcl core for an example.
+.PP
+When called \fBTcl_RegisterConfig\fR will
+.IP (1)
+create a namespace having the provided \fIpkgName\fR, if not yet
+existing.
+.IP (2)
+create the command \fBpkgconfig\fR in that namespace and link it to
+the provided information so that the keys from _configuration_ and
+their associated values can be retrieved through calls to
+\fBpkgconfig\fR.
+.PP
+The command \fBpkgconfig\fR will provide two subcommands, \fBlist\fR
+and \fBget\fR:
+.RS
+.TP
+::\fIpkgName\fR::\fBpkgconfig\fR list
+Returns a list containing the names of all defined keys.
+.TP
+::\fIpkgName\fR::\fBpkgconfig\fR get \fIkey\fR
+Returns the configuration value associated with the specified
+\fIkey\fR.
+.RE
+.SH TCL_CONFIG
+.PP
+The \fBTcl_Config\fR structure contains the following fields:
+.PP
+.CS
+typedef struct Tcl_Config {
+ const char* key;
+ const char* value;
+} Tcl_Config;
+.CE
+.\" No cross references yet.
+.\" .SH "SEE ALSO"
+.SH KEYWORDS
+embedding, configuration, binary library
diff --git a/doc/RegExp.3 b/doc/RegExp.3
index d2163f2..0ac091c 100644
--- a/doc/RegExp.3
+++ b/doc/RegExp.3
@@ -16,93 +16,88 @@ Tcl_RegExpMatch, Tcl_RegExpCompile, Tcl_RegExpExec, Tcl_RegExpRange, Tcl_GetRegE
\fB#include <tcl.h>\fR
.sp
int
-\fBTcl_RegExpMatchObj\fR(\fIinterp\fR, \fIstrObj\fR, \fIpatObj\fR)
+\fBTcl_RegExpMatchObj\fR(\fIinterp\fR, \fItextObj\fR, \fIpatObj\fR)
.sp
int
-\fBTcl_RegExpMatch\fR(\fIinterp\fR, \fIstring\fR, \fIpattern\fR)
+\fBTcl_RegExpMatch\fR(\fIinterp\fR, \fItext\fR, \fIpattern\fR)
.sp
Tcl_RegExp
\fBTcl_RegExpCompile\fR(\fIinterp\fR, \fIpattern\fR)
.sp
int
-\fBTcl_RegExpExec\fR(\fIinterp\fR, \fIregexp\fR, \fIstring\fR, \fIstart\fR)
+\fBTcl_RegExpExec\fR(\fIinterp\fR, \fIregexp\fR, \fItext\fR, \fIstart\fR)
.sp
+void
\fBTcl_RegExpRange\fR(\fIregexp\fR, \fIindex\fR, \fIstartPtr\fR, \fIendPtr\fR)
-.VS 8.1
.sp
Tcl_RegExp
\fBTcl_GetRegExpFromObj\fR(\fIinterp\fR, \fIpatObj\fR, \fIcflags\fR)
.sp
int
-\fBTcl_RegExpExecObj\fR(\fIinterp\fR, \fIregexp\fR, \fIobjPtr\fR, \fIoffset\fR, \fInmatches\fR, \fIeflags\fR)
+\fBTcl_RegExpExecObj\fR(\fIinterp\fR, \fIregexp\fR, \fItextObj\fR, \fIoffset\fR, \fInmatches\fR, \fIeflags\fR)
.sp
+void
\fBTcl_RegExpGetInfo\fR(\fIregexp\fR, \fIinfoPtr\fR)
-.VE 8.1
-
+.fi
.SH ARGUMENTS
-.AS Tcl_Interp *interp
+.AS Tcl_RegExpInfo *interp in/out
.AP Tcl_Interp *interp in
Tcl interpreter to use for error reporting. The interpreter may be
NULL if no error reporting is desired.
-.VS 8.1
-.AP Tcl_Obj *strObj in/out
-Refers to the object from which to get the string to search. The
+.AP Tcl_Obj *textObj in/out
+Refers to the object from which to get the text to search. The
internal representation of the object may be converted to a form that
can be efficiently searched.
.AP Tcl_Obj *patObj in/out
Refers to the object from which to get a regular expression. The
compiled regular expression is cached in the object.
-.VE 8.1
-.AP char *string in
-String to check for a match with a regular expression.
-.AP "CONST char" *pattern in
+.AP char *text in
+Text to search for a match with a regular expression.
+.AP "const char" *pattern in
String in the form of a regular expression pattern.
.AP Tcl_RegExp regexp in
Compiled regular expression. Must have been returned previously
by \fBTcl_GetRegExpFromObj\fR or \fBTcl_RegExpCompile\fR.
.AP char *start in
-If \fIstring\fR is just a portion of some other string, this argument
+If \fItext\fR is just a portion of some other string, this argument
identifies the beginning of the larger string.
-If it isn't the same as \fIstring\fR, then no \fB^\fR matches
-will be allowed.
+If it is not the same as \fItext\fR, then no
+.QW \fB^\fR
+matches will be allowed.
.AP int index in
Specifies which range is desired: 0 means the range of the entire
match, 1 or greater means the range that matched a parenthesized
sub-expression.
-.VS 8.4
-.AP "CONST char" **startPtr out
+.AP "const char" **startPtr out
The address of the first character in the range is stored here, or
NULL if there is no such range.
-.AP "CONST char" **endPtr out
+.AP "const char" **endPtr out
The address of the character just after the last one in the range
is stored here, or NULL if there is no such range.
-.VE 8.4
-.VS 8.1
.AP int cflags in
-OR-ed combination of compilation flags. See below for more information.
-.AP Tcl_Obj *objPtr in/out
-An object which contains the string to check for a match with a
-regular expression.
+OR-ed combination of the compilation flags \fBTCL_REG_ADVANCED\fR,
+\fBTCL_REG_EXTENDED\fR, \fBTCL_REG_BASIC\fR, \fBTCL_REG_EXPANDED\fR,
+\fBTCL_REG_QUOTE\fR, \fBTCL_REG_NOCASE\fR, \fBTCL_REG_NEWLINE\fR,
+\fBTCL_REG_NLSTOP\fR, \fBTCL_REG_NLANCH\fR, \fBTCL_REG_NOSUB\fR, and
+\fBTCL_REG_CANMATCH\fR. See below for more information.
.AP int offset in
-The character offset into the string where matching should begin.
+The character offset into the text where matching should begin.
The value of the offset has no impact on \fB^\fR matches. This
behavior is controlled by \fIeflags\fR.
.AP int nmatches in
The number of matching subexpressions that should be remembered for
later use. If this value is 0, then no subexpression match
-information will be computed. If the value is -1, then
+information will be computed. If the value is \-1, then
all of the matching subexpressions will be remembered. Any other
value will be taken as the maximum number of subexpressions to
remember.
.AP int eflags in
-OR-ed combination of the values TCL_REG_NOTBOL and TCL_REG_NOTEOL.
-See below for more information.
+OR-ed combination of the execution flags \fBTCL_REG_NOTBOL\fR and
+\fBTCL_REG_NOTEOL\fR. See below for more information.
.AP Tcl_RegExpInfo *infoPtr out
The address of the location where information about a previous match
should be stored by \fBTcl_RegExpGetInfo\fR.
-.VE 8.1
.BE
-
.SH DESCRIPTION
.PP
\fBTcl_RegExpMatch\fR determines whether its \fIpattern\fR argument
@@ -114,13 +109,11 @@ If there is no match then \fBTcl_RegExpMatch\fR returns 0.
If an error occurs in the matching process (e.g. \fIpattern\fR
is not a valid regular expression) then \fBTcl_RegExpMatch\fR
returns \-1 and leaves an error message in the interpreter result.
-.VS 8.1.2
\fBTcl_RegExpMatchObj\fR is similar to \fBTcl_RegExpMatch\fR except it
-operates on the Tcl objects \fIstrObj\fR and \fIpatObj\fR instead of
+operates on the Tcl objects \fItextObj\fR and \fIpatObj\fR instead of
UTF strings.
\fBTcl_RegExpMatchObj\fR is generally more efficient than
\fBTcl_RegExpMatch\fR, so it is the preferred interface.
-.VE 8.1.2
.PP
\fBTcl_RegExpCompile\fR, \fBTcl_RegExpExec\fR, and \fBTcl_RegExpRange\fR
provide lower-level access to the regular expression pattern matcher.
@@ -136,7 +129,7 @@ up to the next call to \fBTcl_RegExpCompile\fR; it is not safe to
retain these values for long periods of time.
.PP
\fBTcl_RegExpExec\fR executes the regular expression pattern matcher.
-It returns 1 if \fIstring\fR contains a range of characters that
+It returns 1 if \fItext\fR contains a range of characters that
match \fIregexp\fR, 0 if no match is found, and
\-1 if an error occurs.
In the case of an error, \fBTcl_RegExpExec\fR leaves an error
@@ -145,14 +138,16 @@ When searching a string for multiple matches of a pattern,
it is important to distinguish between the start of the original
string and the start of the current search.
For example, when searching for the second occurrence of a
-match, the \fIstring\fR argument might point to the character
+match, the \fItext\fR argument might point to the character
just after the first match; however, it is important for the
pattern matcher to know that this is not the start of the entire string,
-so that it doesn't allow \fB^\fR atoms in the pattern to match.
+so that it does not allow
+.QW \fB^\fR
+atoms in the pattern to match.
The \fIstart\fR argument provides this information by pointing
-to the start of the overall string containing \fIstring\fR.
-\fIStart\fR will be less than or equal to \fIstring\fR; if it
-is less than \fIstring\fR then no \fB^\fR matches will be allowed.
+to the start of the overall string containing \fItext\fR.
+\fIStart\fR will be less than or equal to \fItext\fR; if it
+is less than \fItext\fR then no \fB^\fR matches will be allowed.
.PP
\fBTcl_RegExpRange\fR may be invoked after \fBTcl_RegExpExec\fR
returns; it provides detailed information about what ranges of
@@ -168,7 +163,6 @@ information is returned about the range of characters that matched the
If there is no range corresponding to \fIindex\fR then NULL
is stored in \fI*startPtr\fR and \fI*endPtr\fR.
.PP
-.VS 8.1
\fBTcl_GetRegExpFromObj\fR, \fBTcl_RegExpExecObj\fR, and
\fBTcl_RegExpGetInfo\fR are object interfaces that provide the most
direct control of Henry Spencer's regular expression library. For
@@ -190,23 +184,29 @@ occurs while compiling the regular expression then
\fBTcl_GetRegExpFromObj\fR returns NULL and leaves an error message in
the interpreter result. The regular expression token can be used as
long as the internal representation of \fIpatObj\fR refers to the
-compiled form. The \fIeflags\fR argument is a bitwise OR of
+compiled form. The \fIcflags\fR argument is a bit-wise OR of
zero or more of the following flags that control the compilation of
\fIpatObj\fR:
.RS 2
.TP
\fBTCL_REG_ADVANCED\fR
-Compile advanced regular expressions (`AREs'). This mode corresponds to
-the normal regular expression syntax accepted by the Tcl regexp and
-regsub commands.
+Compile advanced regular expressions
+.PQ ARE s .
+This mode corresponds to
+the normal regular expression syntax accepted by the Tcl \fBregexp\fR and
+\fBregsub\fR commands.
.TP
\fBTCL_REG_EXTENDED\fR
-Compile extended regular expressions (`EREs'). This mode corresponds
+Compile extended regular expressions
+.PQ ERE s .
+This mode corresponds
to the regular expression syntax recognized by Tcl 8.0 and earlier
versions.
.TP
\fBTCL_REG_BASIC\fR
-Compile basic regular expressions (`BREs'). This mode corresponds
+Compile basic regular expressions
+.PQ BRE s .
+This mode corresponds
to the regular expression syntax recognized by common Unix utilities
like \fBsed\fR and \fBgrep\fR. This is the default if no flags are
specified.
@@ -226,26 +226,54 @@ Compile for matching that ignores upper/lower case distinctions.
\fBTCL_REG_NEWLINE\fR
Compile for newline-sensitive matching. By default, newline is a
completely ordinary character with no special meaning in either
-regular expressions or strings. With this flag, `[^' bracket
-expressions and `.' never match newline, `^' matches an empty string
-after any newline in addition to its normal function, and `$' matches
+regular expressions or strings. With this flag,
+.QW [^
+bracket expressions and
+.QW .
+never match newline,
+.QW ^
+matches an empty string
+after any newline in addition to its normal function, and
+.QW $
+matches
an empty string before any newline in addition to its normal function.
-\fBREG_NEWLINE\fR is the bitwise OR of \fBREG_NLSTOP\fR and
+\fBREG_NEWLINE\fR is the bit-wise OR of \fBREG_NLSTOP\fR and
\fBREG_NLANCH\fR.
.TP
\fBTCL_REG_NLSTOP\fR
Compile for partial newline-sensitive matching,
with the behavior of
-`[^' bracket expressions and `.' affected,
-but not the behavior of `^' and `$'. In this mode, `[^' bracket
-expressions and `.' never match newline.
+.QW [^
+bracket expressions and
+.QW .
+affected, but not the behavior of
+.QW ^
+and
+.QW $ .
+In this mode,
+.QW [^
+bracket expressions and
+.QW .
+never match newline.
.TP
\fBTCL_REG_NLANCH\fR
Compile for inverse partial newline-sensitive matching,
with the behavior of
-of `^' and `$' (the ``anchors'') affected, but not the behavior of
-`[^' bracket expressions and `.'. In this mode `^' matches an empty string
-after any newline in addition to its normal function, and `$' matches
+.QW ^
+and
+.QW $
+(the
+.QW anchors )
+affected, but not the behavior of
+.QW [^
+bracket expressions and
+.QW . .
+In this mode
+.QW ^
+matches an empty string
+after any newline in addition to its normal function, and
+.QW $
+matches
an empty string before any newline in addition to its normal function.
.TP
\fBTCL_REG_NOSUB\fR
@@ -273,25 +301,33 @@ error message in the interpreter result. The \fInmatches\fR value
indicates to the matcher how many subexpressions are of interest. If
\fInmatches\fR is 0, then no subexpression match information is
recorded, which may allow the matcher to make various optimizations.
-If the value is -1, then all of the subexpressions in the pattern are
+If the value is \-1, then all of the subexpressions in the pattern are
remembered. If the value is a positive integer, then only that number
of subexpressions will be remembered. Matching begins at the
specified Unicode character index given by \fIoffset\fR. Unlike
\fBTcl_RegExpExec\fR, the behavior of anchors is not affected by the
offset value. Instead the behavior of the anchors is explicitly
-controlled by the \fIeflags\fR argument, which is a bitwise OR of
+controlled by the \fIeflags\fR argument, which is a bit-wise OR of
zero or more of the following flags:
.RS 2
.TP
\fBTCL_REG_NOTBOL\fR
The starting character will not be treated as the beginning of a
-line or the beginning of the string, so `^' will not match there.
-Note that this flag has no effect on how `\fB\eA\fR' matches.
+line or the beginning of the string, so
+.QW ^
+will not match there.
+Note that this flag has no effect on how
+.QW \fB\eA\fR
+matches.
.TP
\fBTCL_REG_NOTEOL\fR
The last character in the string will not be treated as the end of a
-line or the end of the string, so '$' will not match there.
-Note that this flag has no effect on how `\fB\eZ\fR' matches.
+line or the end of the string, so
+.QW $
+will not match there.
+Note that this flag has no effect on how
+.QW \fB\eZ\fR
+matches.
.RE
.PP
\fBTcl_RegExpGetInfo\fR retrieves information about the last match
@@ -301,16 +337,16 @@ defined as follows:
.PP
.CS
typedef struct Tcl_RegExpInfo {
- int \fInsubs\fR;
- Tcl_RegExpIndices *\fImatches\fR;
- long \fIextendStart\fR;
+ int \fInsubs\fR;
+ Tcl_RegExpIndices *\fImatches\fR;
+ long \fIextendStart\fR;
} Tcl_RegExpInfo;
.CE
.PP
The \fInsubs\fR field contains a count of the number of parenthesized
subexpressions within the regular expression. If the \fBTCL_REG_NOSUB\fR
was used, then this value will be zero. The \fImatches\fR field
-points to an array of \fInsubs\fR values that indicate the bounds of each
+points to an array of \fInsubs\fR+1 values that indicate the bounds of each
subexpression matched. The first element in the array refers to the
range matched by the entire regular expression, and subsequent elements
refer to the parenthesized subexpressions in the order that they
@@ -319,8 +355,8 @@ follows:
.PP
.CS
typedef struct Tcl_RegExpIndices {
- long \fIstart\fR;
- long \fIend\fR;
+ long \fIstart\fR;
+ long \fIend\fR;
} Tcl_RegExpIndices;
.CE
.PP
@@ -331,7 +367,7 @@ subexpression. The \fIend\fR index identifies the first character
after the matched subexpression. If the subexpression matched the
empty string, then \fIstart\fR and \fIend\fR will be equal. If the
subexpression did not participate in the match, then \fIstart\fR and
-\fIend\fR will be set to -1.
+\fIend\fR will be set to \-1.
.PP
The \fIextendStart\fR field in \fBTcl_RegExpInfo\fR is only set if the
\fBTCL_REG_CANMATCH\fR flag was used. It indicates the first
@@ -340,8 +376,7 @@ found, this will be the same as the beginning of the current match.
If no match was found, then it indicates the earliest point at which a
match might occur if additional text is appended to the string. If it
is no match is possible even with further text, this field will be set
-to -1.
-.VE 8.1
+to \-1.
.SH "SEE ALSO"
re_syntax(n)
.SH KEYWORDS
diff --git a/doc/SaveResult.3 b/doc/SaveResult.3
index 8eb9b46..f47500e 100644
--- a/doc/SaveResult.3
+++ b/doc/SaveResult.3
@@ -1,5 +1,6 @@
'\"
'\" Copyright (c) 1997 by Sun Microsystems, Inc.
+'\" Contributions from Don Porter, NIST, 2004. (not subject to US copyright)
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -8,35 +9,95 @@
.TH Tcl_SaveResult 3 8.1 Tcl "Tcl Library Procedures"
.BS
.SH NAME
-Tcl_SaveResult, Tcl_RestoreResult, Tcl_DiscardResult \- save and restore an interpreter's result
+Tcl_SaveInterpState, Tcl_RestoreInterpState, Tcl_DiscardInterpState, Tcl_SaveResult, Tcl_RestoreResult, Tcl_DiscardResult \- save and restore an interpreter's state
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
-\fBTcl_SaveResult(\fIinterp, statePtr\fB)\fR
+Tcl_InterpState
+\fBTcl_SaveInterpState\fR(\fIinterp, status\fR)
.sp
-\fBTcl_RestoreResult(\fIinterp, statePtr\fB)\fR
+int
+\fBTcl_RestoreInterpState\fR(\fIinterp, state\fR)
.sp
-\fBTcl_DiscardResult(\fIstatePtr\fB)\fR
+\fBTcl_DiscardInterpState\fR(\fIstate\fR)
+.sp
+\fBTcl_SaveResult\fR(\fIinterp, savedPtr\fR)
+.sp
+\fBTcl_RestoreResult\fR(\fIinterp, savedPtr\fR)
+.sp
+\fBTcl_DiscardResult\fR(\fIsavedPtr\fR)
.SH ARGUMENTS
-.AS Tcl_SavedResult statePtr
+.AS Tcl_InterpState savedPtr
.AP Tcl_Interp *interp in
Interpreter for which state should be saved.
-.AP Tcl_SavedResult *statePtr in
+.AP int status in
+Return code value to save as part of interpreter state.
+.AP Tcl_InterpState state in
+Saved state token to be restored or discarded.
+.AP Tcl_SavedResult *savedPtr in
Pointer to location where interpreter result should be saved or restored.
.BE
.SH DESCRIPTION
.PP
+.VS 8.5
These routines allows a C procedure to take a snapshot of the current
-interpreter result so that it can be restored after a call
+state of an interpreter so that it can be restored after a call
to \fBTcl_Eval\fR or some other routine that modifies the interpreter
-result. These routines are passed a pointer to a structure that is
-used to store enough information to restore the interpreter result
-state. This structure can be allocated on the stack of the calling
+state. There are two triplets of routines meant to work together.
+.PP
+The first triplet stores the snapshot of interpreter state in
+an opaque token returned by \fBTcl_SaveInterpState\fR. That token
+value may then be passed back to one of \fBTcl_RestoreInterpState\fR
+or \fBTcl_DiscardInterpState\fR, depending on whether the interp
+state is to be restored. So long as one of the latter two routines
+is called, Tcl will take care of memory management.
+.PP
+The second triplet stores the snapshot of only the interpreter
+result (not its complete state) in memory allocated by the caller.
+These routines are passed a pointer to a \fBTcl_SavedResult\fR structure
+that is used to store enough information to restore the interpreter result.
+This structure can be allocated on the stack of the calling
procedure. These routines do not save the state of any error
-information in the interpreter (e.g. the \fBerrorCode\fR or
-\fBerrorInfo\fR variables).
+information in the interpreter (e.g. the \fB\-errorcode\fR or
+\fB\-errorinfo\fR return options, when an error is in progress).
+.PP
+Because the routines \fBTcl_SaveInterpState\fR,
+\fBTcl_RestoreInterpState\fR, and \fBTcl_DiscardInterpState\fR perform
+a superset of the functions provided by the other routines,
+any new code should only make use of the more powerful routines.
+The older, weaker routines \fBTcl_SaveResult\fR, \fBTcl_RestoreResult\fR,
+and \fBTcl_DiscardResult\fR continue to exist only for the sake
+of existing programs that may already be using them.
+.PP
+\fBTcl_SaveInterpState\fR takes a snapshot of those portions of
+interpreter state that make up the full result of script evaluation.
+This include the interpreter result, the return code (passed in
+as the \fIstatus\fR argument, and any return options, including
+\fB\-errorinfo\fR and \fB\-errorcode\fR when an error is in progress.
+This snapshot is returned as an opaque token of type \fBTcl_InterpState\fR.
+The call to \fBTcl_SaveInterpState\fR does not itself change the
+state of the interpreter. Unlike \fBTcl_SaveResult\fR, it does
+not reset the interpreter.
+.PP
+\fBTcl_RestoreInterpState\fR accepts a \fBTcl_InterpState\fR token
+previously returned by \fBTcl_SaveInterpState\fR and restores the
+state of the interp to the state held in that snapshot. The return
+value of \fBTcl_RestoreInterpState\fR is the status value originally
+passed to \fBTcl_SaveInterpState\fR when the snapshot token was
+created.
+.PP
+\fBTcl_DiscardInterpState\fR is called to release a \fBTcl_InterpState\fR
+token previously returned by \fBTcl_SaveInterpState\fR when that
+snapshot is not to be restored to an interp.
+.PP
+The \fBTcl_InterpState\fR token returned by \fBTcl_SaveInterpState\fR
+must eventually be passed to either \fBTcl_RestoreInterpState\fR
+or \fBTcl_DiscardInterpState\fR to avoid a memory leak. Once
+the \fBTcl_InterpState\fR token is passed to one of them, the
+token is no longer valid and should not be used anymore.
+.VE 8.5
.PP
\fBTcl_SaveResult\fR moves the string and object results
of \fIinterp\fR into the location specified by \fIstatePtr\fR.
diff --git a/doc/SetChanErr.3 b/doc/SetChanErr.3
new file mode 100644
index 0000000..13bd94a
--- /dev/null
+++ b/doc/SetChanErr.3
@@ -0,0 +1,153 @@
+'\"
+'\" Copyright (c) 2005 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.so man.macros
+.TH Tcl_SetChannelError 3 8.5 Tcl "Tcl Library Procedures"
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+Tcl_SetChannelError, Tcl_SetChannelErrorInterp, Tcl_GetChannelError, Tcl_GetChannelErrorInterp \- functions to create/intercept Tcl errors by channel drivers.
+.SH SYNOPSIS
+.nf
+\fB#include <tcl.h>\fR
+.sp
+void
+\fBTcl_SetChannelError\fR(\fIchan, msg\fR)
+.sp
+void
+\fBTcl_SetChannelErrorInterp\fR(\fIinterp, msg\fR)
+.sp
+void
+\fBTcl_GetChannelError\fR(\fIchan, msgPtr\fR)
+.sp
+void
+\fBTcl_GetChannelErrorInterp\fR(\fIinterp, msgPtr\fR)
+.sp
+.SH ARGUMENTS
+.AS Tcl_Channel chan
+.AP Tcl_Channel chan in
+Refers to the Tcl channel whose bypass area is accessed.
+.AP Tcl_Interp* interp in
+Refers to the Tcl interpreter whose bypass area is accessed.
+.AP Tcl_Obj* msg in
+Error message put into a bypass area. A list of return options and
+values, followed by a string message. Both message and the
+option/value information are optional.
+.AP Tcl_Obj** msgPtr out
+Reference to a place where the message stored in the accessed bypass
+area can be stored in.
+.BE
+.SH DESCRIPTION
+.PP
+The current definition of a Tcl channel driver does not permit the
+direct return of arbitrary error messages, except for the setting and
+retrieval of channel options. All other functions are restricted to
+POSIX error codes.
+.PP
+The functions described here overcome this limitation. Channel drivers
+are allowed to use \fBTcl_SetChannelError\fR and
+\fBTcl_SetChannelErrorInterp\fR to place arbitrary error messages in
+\fBbypass areas\fI defined for channels and interpreters. And the
+generic I/O layer uses \fBTcl_GetChannelError\fR and
+\fBTcl_GetChannelErrorInterp\fR to look for messages in the bypass
+areas and arrange for their return as errors. The posix error codes
+set by a driver are used now if and only if no messages are present.
+.PP
+\fBTcl_SetChannelError\fR stores error information in the bypass area
+of the specified channel. The number of references to the \fBmsg\fR
+object goes up by one. Previously stored information will be
+discarded, by releasing the reference held by the channel. The channel
+reference must not be NULL.
+.PP
+\fBTcl_SetChannelErrorInterp\fR stores error information in the bypass
+area of the specified interpreter. The number of references to the
+\fBmsg\fR object goes up by one. Previously stored information will be
+discarded, by releasing the reference held by the interpreter. The
+interpreter reference must not be NULL.
+.PP
+\fBTcl_GetChannelError\fR places either the error message held in the
+bypass area of the specified channel into \fImsgPtr\fR, or NULL; and
+resets the bypass. I.e. after an invocation all following invocations
+will return NULL, until an intervening invocation of
+\fBTcl_SetChannelError\fR with a non-NULL message. The \fImsgPtr\fR
+must not be NULL. The reference count of the message is not touched.
+The reference previously held by the channel is now held by the caller
+of the function and it is its responsibility to release that reference
+when it is done with the object.
+.PP
+\fBTcl_GetChannelErrorInterp\fR places either the error message held
+in the bypass area of the specified interpreter into \fImsgPtr\fR, or
+NULL; and resets the bypass. I.e. after an invocation all following
+invocations will return NULL, until an intervening invocation of
+\fBTcl_SetChannelErrorInterp\fR with a non-NULL message. The
+\fImsgPtr\fR must not be NULL. The reference count of the message is
+not touched. The reference previously held by the interpreter is now
+held by the caller of the function and it is its responsibility to
+release that reference when it is done with the object.
+.PP
+Which functions of a channel driver are allowed to use which bypass
+function is listed below, as is which functions of the public channel
+API may leave a messages in the bypass areas.
+.PP
+.IP \fBTcl_DriverCloseProc\fR
+May use \fBTcl_SetChannelErrorInterp\fR, and only this function.
+.IP \fBTcl_DriverInputProc\fR
+May use \fBTcl_SetChannelError\fR, and only this function.
+.IP \fBTcl_DriverOutputProc\fR
+May use \fBTcl_SetChannelError\fR, and only this function.
+.IP \fBTcl_DriverSeekProc\fR
+May use \fBTcl_SetChannelError\fR, and only this function.
+.IP \fBTcl_DriverWideSeekProc\fR
+May use \fBTcl_SetChannelError\fR, and only this function.
+.IP \fBTcl_DriverSetOptionProc\fR
+Has already the ability to pass arbitrary error messages. Must
+\fBnot\fR use any of the new functions.
+.IP \fBTcl_DriverGetOptionProc\fR
+Has already the ability to pass arbitrary error messages. Must
+\fBnot\fR use any of the new functions.
+.IP \fBTcl_DriverWatchProc\fR
+Must \fBnot\fR use any of the new functions. Is internally called and
+has no ability to return any type of error whatsoever.
+.IP \fBTcl_DriverBlockModeProc\fR
+May use \fBTcl_SetChannelError\fR, and only this function.
+.IP \fBTcl_DriverGetHandleProc\fR
+Must \fBnot\fR use any of the new functions. It is only a low-level
+function, and not used by Tcl commands.
+.IP \fBTcl_DriverHandlerProc\fR
+Must \fBnot\fR use any of the new functions. Is internally called and
+has no ability to return any type of error whatsoever.
+.PP
+Given the information above the following public functions of the Tcl
+C API are affected by these changes. I.e. when these functions are
+called the channel may now contain a stored arbitrary error message
+requiring processing by the caller.
+.PP
+.IP \fBTcl_StackChannel\fR
+.IP \fBTcl_Seek\fR
+.IP \fBTcl_Tell\fR
+.IP \fBTcl_ReadRaw\fR
+.IP \fBTcl_Read\fR
+.IP \fBTcl_ReadChars\fR
+.IP \fBTcl_Gets\fR
+.IP \fBTcl_GetsObj\fR
+.IP \fBTcl_Flush\fR
+.IP \fBTcl_WriteRaw\fR
+.IP \fBTcl_WriteObj\fR
+.IP \fBTcl_Write\fR
+.IP \fBTcl_WriteChars\fR
+.PP
+All other API functions are unchanged. Especially the functions below
+leave all their error information in the interpreter result.
+.PP
+.IP \fBTcl_Close\fR
+.IP \fBTcl_UnregisterChannel\fR
+.IP \fBTcl_UnstackChannel\fR
+
+.SH "SEE ALSO"
+Tcl_Close(3), Tcl_OpenFileChannel(3), Tcl_SetErrno(3)
+
+.SH KEYWORDS
+channel driver, error messages, channel type
diff --git a/doc/SetErrno.3 b/doc/SetErrno.3
index f29345a..1735952 100644
--- a/doc/SetErrno.3
+++ b/doc/SetErrno.3
@@ -19,14 +19,14 @@ void
int
\fBTcl_GetErrno\fR()
.sp
-CONST char *
+const char *
\fBTcl_ErrnoId\fR()
.sp
-CONST char *
+const char *
\fBTcl_ErrnoMsg\fR(\fIerrorCode\fR)
.sp
.SH ARGUMENTS
-.AS int errorCode in
+.AS int errorCode
.AP int errorCode in
A POSIX error code such as \fBENOENT\fR.
.BE
@@ -52,9 +52,11 @@ instead of accessing \fBerrno\fR directly.
\fBTcl_ErrnoId\fR and \fBTcl_ErrnoMsg\fR return string
representations of \fBerrno\fR values. \fBTcl_ErrnoId\fR
returns a machine-readable textual identifier such as
-"EACCES" that corresponds to the current value of \fBerrno\fR.
+.QW EACCES
+that corresponds to the current value of \fBerrno\fR.
\fBTcl_ErrnoMsg\fR returns a human-readable string such as
-"permission denied" that corresponds to the value of its
+.QW "permission denied"
+that corresponds to the value of its
\fIerrorCode\fR argument. The \fIerrorCode\fR argument is
typically the value returned by \fBTcl_GetErrno\fR.
The strings returned by these functions are
diff --git a/doc/SetResult.3 b/doc/SetResult.3
index 9844251..2245794 100644
--- a/doc/SetResult.3
+++ b/doc/SetResult.3
@@ -19,38 +19,40 @@ Tcl_SetObjResult, Tcl_GetObjResult, Tcl_SetResult, Tcl_GetStringResult, Tcl_Appe
Tcl_Obj *
\fBTcl_GetObjResult\fR(\fIinterp\fR)
.sp
-\fBTcl_SetResult\fR(\fIinterp, string, freeProc\fR)
+\fBTcl_SetResult\fR(\fIinterp, result, freeProc\fR)
.sp
-CONST char *
+const char *
\fBTcl_GetStringResult\fR(\fIinterp\fR)
.sp
-\fBTcl_AppendResult\fR(\fIinterp, string, string, ... , \fB(char *) NULL\fR)
+\fBTcl_AppendResult\fR(\fIinterp, result, result, ... , \fB(char *) NULL\fR)
.sp
\fBTcl_AppendResultVA\fR(\fIinterp, argList\fR)
.sp
-\fBTcl_AppendElement\fR(\fIinterp, string\fR)
+\fBTcl_AppendElement\fR(\fIinterp, element\fR)
.sp
\fBTcl_ResetResult\fR(\fIinterp\fR)
.sp
\fBTcl_FreeResult\fR(\fIinterp\fR)
.SH ARGUMENTS
-.AS Tcl_FreeProc freeProc
+.AS Tcl_FreeProc freeProc out
.AP Tcl_Interp *interp out
Interpreter whose result is to be modified or read.
.AP Tcl_Obj *objPtr in
Object value to become result for \fIinterp\fR.
-.AP char *string in
+.AP char *result in
String value to become result for \fIinterp\fR or to be
appended to the existing result.
+.AP char *element in
+String value to append as a list element
+to the existing result of \fIinterp\fR.
.AP Tcl_FreeProc *freeProc in
Address of procedure to call to release storage at
-\fIstring\fR, or \fBTCL_STATIC\fR, \fBTCL_DYNAMIC\fR, or
+\fIresult\fR, or \fBTCL_STATIC\fR, \fBTCL_DYNAMIC\fR, or
\fBTCL_VOLATILE\fR.
.AP va_list argList in
-An argument list which must have been initialised using
-\fBTCL_VARARGS_START\fR, and cleared using \fBva_end\fR.
+An argument list which must have been initialized using
+\fBva_start\fR, and cleared using \fBva_end\fR.
.BE
-
.SH DESCRIPTION
.PP
The procedures described here are utilities for manipulating the
@@ -82,20 +84,20 @@ references to it remain.
The object's reference count is not incremented;
if the caller needs to retain a long-term pointer to the object
they should use \fBTcl_IncrRefCount\fR to increment its reference count
-in order to keep it from being freed too early or accidently changed.
+in order to keep it from being freed too early or accidentally changed.
.PP
\fBTcl_SetResult\fR
-arranges for \fIstring\fR to be the result for the current Tcl
+arranges for \fIresult\fR to be the result for the current Tcl
command in \fIinterp\fR, replacing any existing result.
The \fIfreeProc\fR argument specifies how to manage the storage
-for the \fIstring\fR argument;
+for the \fIresult\fR argument;
it is discussed in the section
\fBTHE TCL_FREEPROC ARGUMENT TO TCL_SETRESULT\fR below.
-If \fIstring\fR is \fBNULL\fR, then \fIfreeProc\fR is ignored
+If \fIresult\fR is \fBNULL\fR, then \fIfreeProc\fR is ignored
and \fBTcl_SetResult\fR
re-initializes \fIinterp\fR's result to point to an empty string.
.PP
-\fBTcl_GetStringResult\fR returns the result for \fIinterp\fR as an string.
+\fBTcl_GetStringResult\fR returns the result for \fIinterp\fR as a string.
If the result was set to an object by a \fBTcl_SetObjResult\fR call,
the object form will be converted to a string and returned.
If the object's string representation contains null bytes,
@@ -114,60 +116,62 @@ and the result is left as a empty string.
\fBTcl_ResetResult\fR also clears the error state managed by
\fBTcl_AddErrorInfo\fR, \fBTcl_AddObjErrorInfo\fR,
and \fBTcl_SetErrorCode\fR.
-
-.SH "OLD STRING PROCEDURES"
-.PP
-Use of the following procedures is deprecated
-since they manipulate the Tcl result as a string.
-Procedures such as \fBTcl_SetObjResult\fR
-that manipulate the result as an object
-can be significantly more efficient.
.PP
\fBTcl_AppendResult\fR makes it easy to build up Tcl results in pieces.
-It takes each of its \fIstring\fR arguments and appends them in order
+It takes each of its \fIresult\fR arguments and appends them in order
to the current result associated with \fIinterp\fR.
If the result is in its initialized empty state (e.g. a command procedure
was just invoked or \fBTcl_ResetResult\fR was just called),
then \fBTcl_AppendResult\fR sets the result to the concatenation of
-its \fIstring\fR arguments.
+its \fIresult\fR arguments.
\fBTcl_AppendResult\fR may be called repeatedly as additional pieces
of the result are produced.
\fBTcl_AppendResult\fR takes care of all the
storage management issues associated with managing \fIinterp\fR's
result, such as allocating a larger result area if necessary.
-It also converts the current interpreter result from an object
-to a string, if necessary, before appending the argument strings.
-Any number of \fIstring\fR arguments may be passed in a single
+It also manages conversion to and from the \fIresult\fR field of the
+\fIinterp\fR so as to handle backward-compatibility with old-style
+extensions.
+Any number of \fIresult\fR arguments may be passed in a single
call; the last argument in the list must be a NULL pointer.
.PP
\fBTcl_AppendResultVA\fR is the same as \fBTcl_AppendResult\fR except that
instead of taking a variable number of arguments it takes an argument list.
+.SH "OLD STRING PROCEDURES"
+.PP
+Use of the following procedures (is deprecated
+since they manipulate the Tcl result as a string.
+Procedures such as \fBTcl_SetObjResult\fR
+that manipulate the result as an object
+can be significantly more efficient.
.PP
\fBTcl_AppendElement\fR is similar to \fBTcl_AppendResult\fR in
that it allows results to be built up in pieces.
-However, \fBTcl_AppendElement\fR takes only a single \fIstring\fR
+However, \fBTcl_AppendElement\fR takes only a single \fIelement\fR
argument and it appends that argument to the current result
as a proper Tcl list element.
\fBTcl_AppendElement\fR adds backslashes or braces if necessary
to ensure that \fIinterp\fR's result can be parsed as a list and that
-\fIstring\fR will be extracted as a single element.
+\fIelement\fR will be extracted as a single element.
Under normal conditions, \fBTcl_AppendElement\fR will add a space
character to \fIinterp\fR's result just before adding the new
list element, so that the list elements in the result are properly
separated.
However if the new list element is the first in a list or sub-list
(i.e. \fIinterp\fR's current result is empty, or consists of the
-single character ``{'', or ends in the characters `` {'') then no
-space is added.
+single character
+.QW { ,
+or ends in the characters
+.QW " {" )
+then no space is added.
.PP
\fBTcl_FreeResult\fR performs part of the work
of \fBTcl_ResetResult\fR.
It frees up the memory associated with \fIinterp\fR's result.
-It also sets \fIinterp->freeProc\fR to zero, but doesn't
+It also sets \fIinterp->freeProc\fR to zero, but does not
change \fIinterp->result\fR or clear error state.
\fBTcl_FreeResult\fR is most commonly used when a procedure
is about to replace one result value with another.
-
.SH "DIRECT ACCESS TO INTERP->RESULT IS DEPRECATED"
.PP
It used to be legal for programs to
@@ -178,32 +182,31 @@ because it can make the result's string and object forms inconsistent.
Programs should always read the result
using the procedures \fBTcl_GetObjResult\fR or \fBTcl_GetStringResult\fR,
and write the result using \fBTcl_SetObjResult\fR or \fBTcl_SetResult\fR.
-
.SH "THE TCL_FREEPROC ARGUMENT TO TCL_SETRESULT"
.PP
\fBTcl_SetResult\fR's \fIfreeProc\fR argument specifies how
-the Tcl system is to manage the storage for the \fIstring\fR argument.
+the Tcl system is to manage the storage for the \fIresult\fR argument.
If \fBTcl_SetResult\fR or \fBTcl_SetObjResult\fR are called
at a time when \fIinterp\fR holds a string result,
they do whatever is necessary to dispose of the old string result
(see the \fBTcl_Interp\fR manual entry for details on this).
.PP
-If \fIfreeProc\fR is \fBTCL_STATIC\fR it means that \fIstring\fR
+If \fIfreeProc\fR is \fBTCL_STATIC\fR it means that \fIresult\fR
refers to an area of static storage that is guaranteed not to be
modified until at least the next call to \fBTcl_Eval\fR.
If \fIfreeProc\fR
-is \fBTCL_DYNAMIC\fR it means that \fIstring\fR was allocated with a call
+is \fBTCL_DYNAMIC\fR it means that \fIresult\fR was allocated with a call
to \fBTcl_Alloc\fR and is now the property of the Tcl system.
\fBTcl_SetResult\fR will arrange for the string's storage to be
released by calling \fBTcl_Free\fR when it is no longer needed.
-If \fIfreeProc\fR is \fBTCL_VOLATILE\fR it means that \fIstring\fR
+If \fIfreeProc\fR is \fBTCL_VOLATILE\fR it means that \fIresult\fR
points to an area of memory that is likely to be overwritten when
\fBTcl_SetResult\fR returns (e.g. it points to something in a stack frame).
In this case \fBTcl_SetResult\fR will make a copy of the string in
dynamically allocated storage and arrange for the copy to be the
result for the current Tcl command.
.PP
-If \fIfreeProc\fR isn't one of the values \fBTCL_STATIC\fR,
+If \fIfreeProc\fR is not one of the values \fBTCL_STATIC\fR,
\fBTCL_DYNAMIC\fR, and \fBTCL_VOLATILE\fR, then it is the address
of a procedure that Tcl should call to free the string.
This allows applications to use non-standard storage allocators.
@@ -214,10 +217,8 @@ result that match the type \fBTcl_FreeProc\fR:
typedef void Tcl_FreeProc(char *\fIblockPtr\fR);
.CE
When \fIfreeProc\fR is called, its \fIblockPtr\fR will be set to
-the value of \fIstring\fR passed to \fBTcl_SetResult\fR.
-
+the value of \fIresult\fR passed to \fBTcl_SetResult\fR.
.SH "SEE ALSO"
Tcl_AddErrorInfo, Tcl_CreateObjCommand, Tcl_SetErrorCode, Tcl_Interp
-
.SH KEYWORDS
append, command, element, list, object, result, return value, interpreter
diff --git a/doc/SetVar.3 b/doc/SetVar.3
index 9391e3e..ce47a73 100644
--- a/doc/SetVar.3
+++ b/doc/SetVar.3
@@ -14,29 +14,25 @@ Tcl_SetVar2Ex, Tcl_SetVar, Tcl_SetVar2, Tcl_ObjSetVar2, Tcl_GetVar2Ex, Tcl_GetVa
.nf
\fB#include <tcl.h>\fR
.sp
-.VS 8.1
Tcl_Obj *
\fBTcl_SetVar2Ex\fR(\fIinterp, name1, name2, newValuePtr, flags\fR)
-.VE
.sp
-CONST char *
+const char *
\fBTcl_SetVar\fR(\fIinterp, varName, newValue, flags\fR)
.sp
-CONST char *
+const char *
\fBTcl_SetVar2\fR(\fIinterp, name1, name2, newValue, flags\fR)
.sp
Tcl_Obj *
\fBTcl_ObjSetVar2\fR(\fIinterp, part1Ptr, part2Ptr, newValuePtr, flags\fR)
.sp
-.VS 8.1
Tcl_Obj *
\fBTcl_GetVar2Ex\fR(\fIinterp, name1, name2, flags\fR)
-.VE
.sp
-CONST char *
+const char *
\fBTcl_GetVar\fR(\fIinterp, varName, flags\fR)
.sp
-CONST char *
+const char *
\fBTcl_GetVar2\fR(\fIinterp, name1, name2, flags\fR)
.sp
Tcl_Obj *
@@ -51,29 +47,27 @@ int
.AS Tcl_Interp *newValuePtr
.AP Tcl_Interp *interp in
Interpreter containing variable.
-.AP "CONST char" *name1 in
+.AP "const char" *name1 in
Contains the name of an array variable (if \fIname2\fR is non-NULL)
or (if \fIname2\fR is NULL) either the name of a scalar variable
or a complete name including both variable name and index.
May include \fB::\fR namespace qualifiers
to specify a variable in a particular namespace.
-.AP "CONST char" *name2 in
+.AP "const char" *name2 in
If non-NULL, gives name of element within array; in this
case \fIname1\fR must refer to an array variable.
.AP Tcl_Obj *newValuePtr in
-.VS 8.1
Points to a Tcl object containing the new value for the variable.
-.VE
.AP int flags in
OR-ed combination of bits providing additional information. See below
for valid values.
-.AP "CONST char" *varName in
+.AP "const char" *varName in
Name of variable.
May include \fB::\fR namespace qualifiers
to specify a variable in a particular namespace.
May refer to a scalar variable or an element of
an array.
-.AP "CONST char" *newValue in
+.AP "const char" *newValue in
New value for variable, specified as a null-terminated string.
A copy of this value is stored in the variable.
.AP Tcl_Obj *part1Ptr in
@@ -91,7 +85,6 @@ within an array and \fIpart1Ptr\fR must refer to an array variable.
These procedures are used to create, modify, read, and delete
Tcl variables from C code.
.PP
-.VS 8.1
\fBTcl_SetVar2Ex\fR, \fBTcl_SetVar\fR, \fBTcl_SetVar2\fR, and
\fBTcl_ObjSetVar2\fR
will create a new variable or modify an existing one.
@@ -105,14 +98,12 @@ a pointer to a Tcl_Obj. \fBTcl_SetVar\fR and \fBTcl_SetVar2\fR
take the new value as a string and return a string; they are
usually less efficient than \fBTcl_ObjSetVar2\fR. Note that the
return value may be different than the \fInewValuePtr\fR or
-.VE
\fInewValue\fR argument, due to modifications made by write traces.
If an error occurs in setting the variable (e.g. an array
variable is referenced without giving an index into the array)
NULL is returned and an error message is left in \fIinterp\fR's
result if the \fBTCL_LEAVE_ERR_MSG\fR \fIflag\fR bit is set.
.PP
-.VS 8.1
\fBTcl_GetVar2Ex\fR, \fBTcl_GetVar\fR, \fBTcl_GetVar2\fR, and
\fBTcl_ObjGetVar2\fR
return the current value of a variable.
@@ -125,9 +116,8 @@ returned as a pointer to a Tcl_Obj. For \fBTcl_GetVar\fR and
\fBTcl_GetVar2\fR the value is returned as a string; this is
usually less efficient, so \fBTcl_GetVar2Ex\fR or \fBTcl_ObjGetVar2\fR
are preferred.
-.VE
If an error occurs while reading the variable (e.g. the variable
-doesn't exist or an array element is specified for a scalar
+does not exist or an array element is specified for a scalar
variable), then NULL is returned and an error message is left
in \fIinterp\fR's result if the \fBTCL_LEAVE_ERR_MSG\fR \fIflag\fR
bit is set.
@@ -137,9 +127,9 @@ a variable, so that future attempts to read the variable will return
an error.
The arguments to these procedures are treated in the same way
as the arguments to the procedures above.
-If the variable is successfully removed then TCL_OK is returned.
-If the variable cannot be removed because it doesn't exist then
-TCL_ERROR is returned and an error message is left
+If the variable is successfully removed then \fBTCL_OK\fR is returned.
+If the variable cannot be removed because it does not exist then
+\fBTCL_ERROR\fR is returned and an error message is left
in \fIinterp\fR's result if the \fBTCL_LEAVE_ERR_MSG\fR \fIflag\fR
bit is set.
If an array element is specified, the given element is removed
@@ -158,23 +148,20 @@ close parenthesis, then the value between the parentheses is
treated as an index (which can have any string value) and
the characters before the first open
parenthesis are treated as the name of an array variable.
-If \fIvarName\fR doesn't have parentheses as described above, then
+If \fIvarName\fR does not have parentheses as described above, then
the entire string is treated as the name of a scalar variable.
.IP [2]
If the \fIname1\fR and \fIname2\fR arguments are provided and
\fIname2\fR is non-NULL, then an array element is specified and
the array name and index have
already been separated by the caller: \fIname1\fR contains the
-name and \fIname2\fR contains the index.
-.VS 8.1
-An error is generated
+name and \fIname2\fR contains the index. An error is generated
if \fIname1\fR contains an open parenthesis and ends with a
close parenthesis (array element) and \fIname2\fR is non-NULL.
.IP [3]
If \fIname2\fR is NULL, \fIname1\fR is treated just like
\fIvarName\fR in case [1] above (it can be either a scalar or an array
element variable name).
-.VE
.PP
The \fIflags\fR argument may be used to specify any of several
options to the procedures.
@@ -203,7 +190,7 @@ If an error is returned and this bit is set in \fIflags\fR, then
an error message will be left in the interpreter's result,
where it can be retrieved with \fBTcl_GetObjResult\fR
or \fBTcl_GetStringResult\fR.
-If this flag bit isn't set then no error message is left
+If this flag bit is not set then no error message is left
and the interpreter's result will not be modified.
.TP
\fBTCL_APPEND_VALUE\fR
@@ -218,7 +205,10 @@ Tcl list element before setting (or appending to) the variable.
A separator space is appended before the new list element unless
the list element is going to be the first element in a list or
sublist (i.e. the variable's current value is empty, or contains
-the single character ``{'', or ends in `` }'').
+the single character
+.QW { ,
+or ends in
+.QW " }" ).
When appending, the original value of the variable must also be
a valid list, so that the operation is the appending of a new
list element onto a list.
@@ -231,12 +221,12 @@ Under normal circumstances, the return value is a pointer
to the variable's value (which is stored in Tcl's variable
structure and will not change before the next call to \fBTcl_SetVar\fR
or \fBTcl_SetVar2\fR).
-\fBTcl_GetVar\fR and \fBTcl_GetVar2\fR use the flag bits TCL_GLOBAL_ONLY
-and TCL_LEAVE_ERR_MSG, both of
+\fBTcl_GetVar\fR and \fBTcl_GetVar2\fR use the flag bits \fBTCL_GLOBAL_ONLY\fR
+and \fBTCL_LEAVE_ERR_MSG\fR, both of
which have
the same meaning as for \fBTcl_SetVar\fR.
If an error occurs in reading the variable (e.g. the variable
-doesn't exist or an array element is specified for a scalar
+does not exist or an array element is specified for a scalar
variable), then NULL is returned.
.PP
\fBTcl_UnsetVar\fR and \fBTcl_UnsetVar2\fR may be used to remove
@@ -244,9 +234,9 @@ a variable, so that future calls to \fBTcl_GetVar\fR or \fBTcl_GetVar2\fR
for the variable will return an error.
The arguments to these procedures are treated in the same way
as the arguments to \fBTcl_GetVar\fR and \fBTcl_GetVar2\fR.
-If the variable is successfully removed then TCL_OK is returned.
-If the variable cannot be removed because it doesn't exist then
-TCL_ERROR is returned.
+If the variable is successfully removed then \fBTCL_OK\fR is returned.
+If the variable cannot be removed because it does not exist then
+\fBTCL_ERROR\fR is returned.
If an array element is specified, the given element is removed
but the array remains.
If an array name is specified without an index, then the entire
diff --git a/doc/Signal.3 b/doc/Signal.3
index f8eafd0..5b12654 100644
--- a/doc/Signal.3
+++ b/doc/Signal.3
@@ -13,13 +13,14 @@ Tcl_SignalId, Tcl_SignalMsg \- Convert signal codes
.nf
\fB#include <tcl.h>\fR
.sp
-CONST char *
+const char *
\fBTcl_SignalId\fR(\fIsig\fR)
.sp
-CONST char *
+const char *
\fBTcl_SignalMsg\fR(\fIsig\fR)
.sp
.SH ARGUMENTS
+.AS int sig
.AP int sig in
A POSIX signal number such as \fBSIGPIPE\fR.
.BE
@@ -29,8 +30,11 @@ A POSIX signal number such as \fBSIGPIPE\fR.
\fBTcl_SignalId\fR and \fBTcl_SignalMsg\fR return a string
representation of the provided signal number (\fIsig\fR).
\fBTcl_SignalId\fR returns a machine-readable textual identifier such
-as "SIGPIPE". \fBTcl_SignalMsg\fR returns a human-readable string such
-as "bus error". The strings returned by these functions are
+as
+.QW SIGPIPE .
+\fBTcl_SignalMsg\fR returns a human-readable string such as
+.QW "bus error" .
+The strings returned by these functions are
statically allocated and the caller must not free or modify them.
.SH KEYWORDS
diff --git a/doc/Sleep.3 b/doc/Sleep.3
index 1abd2e6..2423ba1 100644
--- a/doc/Sleep.3
+++ b/doc/Sleep.3
@@ -16,20 +16,19 @@ Tcl_Sleep \- delay execution for a given number of milliseconds
.sp
\fBTcl_Sleep\fR(\fIms\fR)
.SH ARGUMENTS
+.AS int ms
.AP int ms in
Number of milliseconds to sleep.
.BE
-
.SH DESCRIPTION
.PP
This procedure delays the calling process by the number of
milliseconds given by the \fIms\fR parameter and returns
after that time has elapsed. It is typically used for things
like flashing a button, where the delay is short and the
-application needn't do anything while it waits. For longer
+application need not do anything while it waits. For longer
delays where the application needs to respond to other events
during the delay, the procedure \fBTcl_CreateTimerHandler\fR
should be used instead of \fBTcl_Sleep\fR.
-
.SH KEYWORDS
sleep, time, wait
diff --git a/doc/SourceRCFile.3 b/doc/SourceRCFile.3
index ed949cd..eabc47c 100644
--- a/doc/SourceRCFile.3
+++ b/doc/SourceRCFile.3
@@ -14,6 +14,7 @@ Tcl_SourceRCFile \- source the Tcl rc file
void
\fBTcl_SourceRCFile\fR(\fIinterp\fR)
.SH ARGUMENTS
+.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Tcl interpreter to source rc file into.
.BE
@@ -26,10 +27,6 @@ sourced is obtained from the global variable \fBtcl_rcFileName\fR in
the interpreter given by \fIinterp\fR. If this variable is not
defined, or if the file it indicates cannot be found, no action is
taken.
-.PP
-On the Macintosh, after sourcing the rc file, this function will
-additionally source the TEXT resource indicated by the global variable
-\fBtcl_rcRsrcName\fR in \fIinterp\fR.
.SH KEYWORDS
application-specific initialization, main program, rc file
diff --git a/doc/SplitList.3 b/doc/SplitList.3
index b1a298d..fd6ec8b 100644
--- a/doc/SplitList.3
+++ b/doc/SplitList.3
@@ -32,7 +32,7 @@ int
int
\fBTcl_ConvertCountedElement\fR(\fIsrc, length, dst, flags\fR)
.SH ARGUMENTS
-.AS "CONST char * CONST" ***argvPtr
+.AS "const char *const" ***argvPtr out
.AP Tcl_Interp *interp out
Interpreter to use for error reporting. If NULL, then no error message
is left.
@@ -40,17 +40,17 @@ is left.
Pointer to a string with proper list structure.
.AP int *argcPtr out
Filled in with number of elements in \fIlist\fR.
-.AP "CONST char" ***argvPtr out
+.AP "const char" ***argvPtr out
\fI*argvPtr\fR will be filled in with the address of an array of
pointers to the strings that are the extracted elements of \fIlist\fR.
There will be \fI*argcPtr\fR valid entries in the array, followed by
a NULL entry.
.AP int argc in
Number of elements in \fIargv\fR.
-.AP "CONST char * CONST" *argv in
+.AP "const char *const" *argv in
Array of strings to merge together into a single list.
Each string will become a separate element of the list.
-.AP "CONST char" *src in
+.AP "const char" *src in
String that is to become an element of a list.
.AP int *flagsPtr in
Pointer to word to fill in with information about \fIsrc\fR.
@@ -151,7 +151,7 @@ include spaces between adjacent list elements.
\fBTcl_ConvertElement\fR uses one of two different approaches to
handle the special characters in \fIsrc\fR. Wherever possible, it
handles special characters by surrounding the string with braces.
-This produces clean-looking output, but can't be used in some situations,
+This produces clean-looking output, but cannot be used in some situations,
such as when \fIsrc\fR contains unmatched braces.
In these situations, \fBTcl_ConvertElement\fR handles special
characters by generating backslash sequences for them.
@@ -164,6 +164,20 @@ used to generate a portion of an argument for a Tcl command.
In this case, surrounding \fIsrc\fR with curly braces would cause
the command not to be parsed correctly.
.PP
+.VS 8.5
+By default, \fBTcl_ConvertElement\fR will use quoting in its output
+to be sure the first character of an element is not the hash
+character
+.PQ # .
+This is to be sure the first element of any list
+passed to \fBeval\fR is not mis-parsed as the beginning of a comment.
+When a list element is not the first element of a list, this quoting
+is not necessary. When the caller can be sure that the element is
+not the first element of a list, it can disable quoting of the leading
+hash character by OR-ing the flag value returned by \fBTcl_ScanElement\fR
+with \fBTCL_DONT_QUOTE_HASH\fR.
+.VE 8.5
+.PP
\fBTcl_ScanCountedElement\fR and \fBTcl_ConvertCountedElement\fR are
the same as \fBTcl_ScanElement\fR and \fBTcl_ConvertElement\fR, except
the length of string \fIsrc\fR is specified by the \fIlength\fR
diff --git a/doc/SplitPath.3 b/doc/SplitPath.3
index 9bc6acb..6578e3d 100644
--- a/doc/SplitPath.3
+++ b/doc/SplitPath.3
@@ -21,20 +21,20 @@ char *
Tcl_PathType
\fBTcl_GetPathType\fR(\fIpath\fR)
.SH ARGUMENTS
-.AS Tcl_DString ***argvPtr
-.AP "CONST char * CONST" *argvPtr in
+.AS "const char *const" ***argvPtr in/out
+.AP "const char" *path in
File path in a form appropriate for the current platform (see the
\fBfilename\fR manual entry for acceptable forms for path names).
.AP int *argcPtr out
Filled in with number of path elements in \fIpath\fR.
-.AP "CONST char" ***argvPtr out
+.AP "const char" ***argvPtr out
\fI*argvPtr\fR will be filled in with the address of an array of
pointers to the strings that are the extracted elements of \fIpath\fR.
There will be \fI*argcPtr\fR valid entries in the array, followed by
a NULL entry.
.AP int argc in
Number of elements in \fIargv\fR.
-.AP "CONST char * CONST" *argv in
+.AP "const char *const" *argv in
Array of path elements to merge together into a single path.
.AP Tcl_DString *resultPtr in/out
A pointer to an initialized \fBTcl_DString\fR to which the result of
diff --git a/doc/StaticPkg.3 b/doc/StaticPkg.3
index f4c279c..0dd67d1 100644
--- a/doc/StaticPkg.3
+++ b/doc/StaticPkg.3
@@ -8,7 +8,7 @@
.TH Tcl_StaticPackage 3 7.5 Tcl "Tcl Library Procedures"
.BS
.SH NAME
-Tcl_StaticPackage \- make a statically linked package available via the \fBload\fR command
+Tcl_StaticPackage \- make a statically linked package available via the 'load' command
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -20,8 +20,8 @@ Tcl_StaticPackage \- make a statically linked package available via the \fBload\
If not NULL, points to an interpreter into which the package has
already been loaded (i.e., the caller has already invoked the
appropriate initialization procedure). NULL means the package
-hasn't yet been incorporated into any interpreter.
-.AP "CONST char" *pkgName in
+has not yet been incorporated into any interpreter.
+.AP "const char" *pkgName in
Name of the package; should be properly capitalized (first letter
upper-case, all others lower-case).
.AP Tcl_PackageInitProc *initProc in
@@ -30,7 +30,7 @@ interpreter.
.AP Tcl_PackageInitProc *safeInitProc in
Procedure to call to incorporate this package into a safe interpreter
(one that will execute untrusted scripts). NULL means the package
-can't be used in safe interpreters.
+cannot be used in safe interpreters.
.BE
.SH DESCRIPTION
diff --git a/doc/StdChannels.3 b/doc/StdChannels.3
index 2a7dd05..b5b020e 100644
--- a/doc/StdChannels.3
+++ b/doc/StdChannels.3
@@ -26,8 +26,7 @@ output and the other for error messages.
.PP
Tcl generalizes this concept in a cross-platform way and
exposes standard channels to the script level.
-
-.SH APIs
+.SS "APPLICATION PROGRAMMING INTERFACES"
.PP
The public API procedures dealing directly with standard channels are
\fBTcl_GetStdChannel\fR and \fBTcl_SetStdChannel\fR. Additional public
@@ -41,17 +40,21 @@ channel information, or when implicitly required during registration
of a new channel.
.PP
These cases differ in how they handle unavailable platform- specific
-standard channels. (A channel is not ``available'' if it could not be
+standard channels. (A channel is not
+.QW available
+if it could not be
successfully opened; for example, in a Tcl application run as a
Windows NT service.)
.TP
1)
A single standard channel is initialized when it is explicitly
-specified in a call to \fBTcl_SetStdChannel\fR. The state of the
+specified in a call to \fBTcl_SetStdChannel\fR. The states of the
other standard channels are unaffected.
-.sp
+.RS
+.PP
Missing platform-specific standard channels do not matter here. This
approach is not available at the script level.
+.RE
.TP
2)
All uninitialized standard channels are initialized to
@@ -67,9 +70,7 @@ when information about any standard channel is requested with a call
to \fBTcl_GetStdChannel\fR, or with a call to \fBTcl_GetChannel\fR
which specifies one of the standard names (\fBstdin\fR, \fBstdout\fR
and \fBstderr\fR).
-.RE
-.sp
-.RS
+.PP
In case of missing platform-specific standard channels, the Tcl
standard channels are considered as initialized and then immediately
closed. This means that the first three Tcl channels then opened by
@@ -80,14 +81,13 @@ the application are designated as the Tcl standard channels.
All uninitialized standard channels are initialized to
platform-specific default values when a user-requested channel is
registered with \fBTcl_RegisterChannel\fR.
-.sp
+.PP
In case of unavailable platform-specific standard channels the channel
whose creation caused the initialization of the Tcl standard channels
is made a normal channel. The next three Tcl channels opened by the
application are designated as the Tcl standard channels. In other
words, of the first four Tcl channels opened by the application the
second to fourth are designated as the Tcl standard channels.
-.PP
.SH "RE-INITIALIZATION OF TCL STANDARD CHANNELS"
.PP
Once a Tcl standard channel is initialized through one of the methods
@@ -101,21 +101,20 @@ channel, too. If more than one Tcl standard channel was closed
that slot was not initialized before. It is this behavior which
enables an application to employ method 1 of initialization, i.e. to
create and designate their own Tcl standard channels.
-
-.SH tclsh
+.SH "SHELL-SPECIFIC DETAILS"
+.SS tclsh
.PP
-The Tcl shell (or rather \fBTcl_Main\fR) uses method 2 to initialize
+The Tcl shell (or rather the function \fBTcl_Main\fR, which forms the
+core of the shell's implementation) uses method 2 to initialize
the standard channels.
-
-.SH wish
+.SS wish
.PP
-The windowing shell (or rather \fBTk_MainEx\fR) uses method 1 to
+The windowing shell (or rather the function \fBTk_MainEx\fR, which
+forms the core of the shell's implementation) uses method 1 to
initialize the standard channels (See \fBTk_InitConsoleChannels\fR)
on non-Unix platforms. On Unix platforms, \fBTk_MainEx\fR implicitly
uses method 2 to initialize the standard channels.
-
.SH "SEE ALSO"
Tcl_CreateChannel(3), Tcl_RegisterChannel(3), Tcl_GetChannel(3), Tcl_GetStdChannel(3), Tcl_SetStdChannel(3), Tk_InitConsoleChannels(3), tclsh(1), wish(1), Tcl_Main(3), Tk_MainEx(3)
-
.SH KEYWORDS
standard channels
diff --git a/doc/StrMatch.3 b/doc/StrMatch.3
index f490c19..5adaf6e 100644
--- a/doc/StrMatch.3
+++ b/doc/StrMatch.3
@@ -6,7 +6,7 @@
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
-.TH Tcl_StringMatch 3 8.1 Tcl "Tcl Library Procedures"
+.TH Tcl_StringMatch 3 8.5 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_StringMatch, Tcl_StringCaseMatch \- test whether a string matches a pattern
@@ -15,19 +15,20 @@ Tcl_StringMatch, Tcl_StringCaseMatch \- test whether a string matches a pattern
\fB#include <tcl.h>\fR
.sp
int
-\fBTcl_StringMatch\fR(\fIstring\fR, \fIpattern\fR)
+\fBTcl_StringMatch\fR(\fIstr\fR, \fIpattern\fR)
.sp
int
-\fBTcl_StringCaseMatch\fR(\fIstring\fR, \fIpattern\fR, \fInocase\fR)
+\fBTcl_StringCaseMatch\fR(\fIstr\fR, \fIpattern\fR, \fIflags\fR)
.SH ARGUMENTS
-.AP char *string in
+.AS "const char" *pattern
+.AP "const char" *str in
String to test.
-.AP char *pattern in
+.AP "const char" *pattern in
Pattern to match against string. May contain special
characters from the set *?\e[].
-.AP int nocase in
-Specifies whether the match should be done case-sensitive (0) or
-case-insensitive (1).
+.AP int flags in
+OR-ed combination of match flags, currently only \fBTCL_MATCH_NOCASE\fR.
+0 specifies a case-sensitive search.
.BE
.SH DESCRIPTION
@@ -35,16 +36,14 @@ case-insensitive (1).
This utility procedure determines whether a string matches
a given pattern. If it does, then \fBTcl_StringMatch\fR returns
1. Otherwise \fBTcl_StringMatch\fR returns 0. The algorithm
-used for matching is the same algorithm used in the ``string match''
+used for matching is the same algorithm used in the \fBstring match\fR
Tcl command and is similar to the algorithm used by the C-shell
for file name matching; see the Tcl manual entry for details.
-.VS 8.1
.PP
-In \fBTcl_StringCaseMatch\fR, the algorithm is the same, but you have
-the option to make the matching case-insensitive. If you choose this
-(by passing \fBnocase\fR as 1), then the string and pattern are
-essentially matched in the lower case.
-.VE 8.1
+In \fBTcl_StringCaseMatch\fR, the algorithm is
+the same, but you have the option to make the matching case-insensitive.
+If you choose this (by passing \fBTCL_MATCH_NOCASE\fR), then the string and
+pattern are essentially matched in the lower case.
.SH KEYWORDS
match, pattern, string
diff --git a/doc/StringObj.3 b/doc/StringObj.3
index 6a624db..e451c61 100644
--- a/doc/StringObj.3
+++ b/doc/StringObj.3
@@ -8,7 +8,7 @@
.TH Tcl_StringObj 3 8.1 Tcl "Tcl Library Procedures"
.BS
.SH NAME
-Tcl_NewStringObj, Tcl_NewUnicodeObj, Tcl_SetStringObj, Tcl_SetUnicodeObj, Tcl_GetStringFromObj, Tcl_GetString, Tcl_GetUnicodeFromObj, Tcl_GetUnicode, Tcl_GetUniChar, Tcl_GetCharLength, Tcl_GetRange, Tcl_AppendToObj, Tcl_AppendUnicodeToObj, Tcl_AppendStringsToObj, Tcl_AppendStringsToObjVA, Tcl_AppendObjToObj, Tcl_SetObjLength, Tcl_ConcatObj, Tcl_AttemptSetObjLength \- manipulate Tcl objects as strings
+Tcl_NewStringObj, Tcl_NewUnicodeObj, Tcl_SetStringObj, Tcl_SetUnicodeObj, Tcl_GetStringFromObj, Tcl_GetString, Tcl_GetUnicodeFromObj, Tcl_GetUnicode, Tcl_GetUniChar, Tcl_GetCharLength, Tcl_GetRange, Tcl_AppendToObj, Tcl_AppendUnicodeToObj, Tcl_AppendObjToObj, Tcl_AppendStringsToObj, Tcl_AppendStringsToObjVA, Tcl_AppendLimitedToObj, Tcl_Format, Tcl_AppendFormatToObj, Tcl_ObjPrintf, Tcl_AppendPrintfToObj, Tcl_SetObjLength, Tcl_AttemptSetObjLength, Tcl_ConcatObj \- manipulate Tcl objects as strings
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -60,6 +60,23 @@ void
.sp
void
\fBTcl_AppendStringsToObjVA\fR(\fIobjPtr, argList\fR)
+.VS 8.5
+.sp
+void
+\fBTcl_AppendLimitedToObj\fR(\fIobjPtr, bytes, length, limit, ellipsis\fR)
+.sp
+Tcl_Obj *
+\fBTcl_Format\fR(\fIinterp, format, objc, objv\fR)
+.sp
+int
+\fBTcl_AppendFormatToObj\fR(\fIinterp, objPtr, format, objc, objv\fR)
+.sp
+Tcl_Obj *
+\fBTcl_ObjPrintf\fR(\fIformat, ...\fR)
+.sp
+int
+\fBTcl_AppendPrintfToObj\fR(\fIobjPtr, format, ...\fR)
+.VE 8.5
.sp
void
\fBTcl_SetObjLength\fR(\fIobjPtr, newLength\fR)
@@ -70,22 +87,20 @@ int
Tcl_Obj *
\fBTcl_ConcatObj\fR(\fIobjc, objv\fR)
.SH ARGUMENTS
-.AS "CONST Tcl_UniChar" *appendObjPtr in/out
-.AP "CONST char" *bytes in
-.VS 8.1
+.AS "const Tcl_UniChar" *appendObjPtr in/out
+.AP "const char" *bytes in
Points to the first byte of an array of UTF-8-encoded bytes
used to set or append to a string object.
-This byte array should not contain embedded null bytes
-unless \fIlength\fR is negative. (Applications needing null bytes
-should represent them as the two-byte sequence \fI\\700\\600\fR, use
+This byte array may contain embedded null characters
+unless \fInumChars\fR is negative. (Applications needing null bytes
+should represent them as the two-byte sequence \fI\e700\e600\fR, use
\fBTcl_ExternalToUtf\fR to convert, or \fBTcl_NewByteArrayObj\fR if
the string is a collection of uninterpreted bytes.)
-.VE 8.1
.AP int length in
The number of bytes to copy from \fIbytes\fR when
initializing, setting, or appending to a string object.
If negative, all bytes up to the first null are used.
-.AP "CONST Tcl_UniChar" *unicode in
+.AP "const Tcl_UniChar" *unicode in
Points to the first byte of an array of Unicode characters
used to set or append to a string object.
This byte array may contain embedded null characters
@@ -108,19 +123,26 @@ Points to an object to manipulate.
The object to append to \fIobjPtr\fR in \fBTcl_AppendObjToObj\fR.
.AP int *lengthPtr out
If non-NULL, the location where \fBTcl_GetStringFromObj\fR will store
-the the length of an object's string representation.
-.AP "CONST char" *string in
+the length of an object's string representation.
+.AP "const char" *string in
Null-terminated string value to append to \fIobjPtr\fR.
.AP va_list argList in
An argument list which must have been initialised using
-\fBTCL_VARARGS_START\fR, and cleared using \fBva_end\fR.
+\fBva_start\fR, and cleared using \fBva_end\fR.
+.AP int limit in
+Maximum number of bytes to be appended.
+.AP "const char" *ellipsis in
+Suffix to append when the limit leads to string truncation.
+If NULL is passed then the suffix "..." is used.
+.AP "const char" *format in
+Format control string including % conversion specifiers.
+.AP int objc in
+The number of elements to format or concatenate.
+.AP Tcl_Obj *objv[] in
+The array of objects to format or concatenate.
.AP int newLength in
New length for the string value of \fIobjPtr\fR, not including the
final null character.
-.AP int objc in
-The number of elements to concatenate.
-.AP Tcl_Obj *objv[] in
-The array of objects to concatenate.
.BE
.SH DESCRIPTION
@@ -130,7 +152,7 @@ be manipulated as string values. They use the internal representation
of the object to store additional information to make the string
manipulations more efficient. In particular, they make a series of
append operations efficient by allocating extra storage space for the
-string so that it doesn't have to be copied for each append.
+string so that it does not have to be copied for each append.
Also, indexing and length computations are optimized because the
Unicode string representation is calculated and cached as needed.
When using the \fBTcl_Append*\fR family of functions where the
@@ -163,7 +185,7 @@ will be able to modify the string representation within the
\fBTcl_UpdateStringProc\fR of their \fBTcl_ObjType\fR. Except for that
limited purpose, the pointer returned by \fBTcl_GetStringFromObj\fR
or \fBTcl_GetString\fR should be treated as read-only. It is
-recommended that this pointer be assigned to a (CONST char *) variable.
+recommended that this pointer be assigned to a (const char *) variable.
Even in the limited situations where writing to this pointer is
acceptable, one should take care to respect the copy-on-write
semantics required by \fBTcl_Obj\fR's, with appropriate calls
@@ -229,6 +251,88 @@ must be a NULL pointer to indicate the end of the list.
except that instead of taking a variable number of arguments it takes an
argument list.
.PP
+.VS 8.5
+\fBTcl_AppendLimitedToObj\fR is similar to \fBTcl_AppendToObj\fR
+except that it imposes a limit on how many bytes are appended.
+This can be handy when the string to be appended might be
+very large, but the value being constructed should not be allowed to grow
+without bound. A common usage is when constructing an error message, where the
+end result should be kept short enough to be read.
+Bytes from \fIbytes\fR are appended to \fIobjPtr\fR, but no more
+than \fIlimit\fR bytes total are to be appended. If the limit prevents
+all \fIlength\fR bytes that are available from being appended, then the
+appending is done so that the last bytes appended are from the
+string \fIellipsis\fR. This allows for an indication of the truncation
+to be left in the string.
+When \fIlength\fR is \fB-1\fR, all bytes up to the first zero byte are appended,
+subject to the limit. When \fIellipsis\fR is NULL, the default
+string \fB...\fR is used. When \fIellipsis\fR is non-NULL, it must point
+to a zero-byte-terminated string in Tcl's internal UTF encoding.
+The number of bytes appended can be less than the lesser
+of \fIlength\fR and \fIlimit\fR when appending fewer
+bytes is necessary to append only whole multi-byte characters.
+.PP
+\fBTcl_Format\fR is the C-level interface to the engine of the \fBformat\fR
+command. The actual command procedure for \fBformat\fR is little more
+than
+.CS
+Tcl_Format(interp, Tcl_GetString(objv[1]), objc-2, objv+2);
+.CE
+The \fIobjc\fR Tcl_Obj values in \fIobjv\fR are formatted into a string
+according to the conversion specification in \fIformat\fR argument, following
+the documentation for the \fBformat\fR command. The resulting formatted
+string is converted to a new Tcl_Obj with refcount of zero and returned.
+If some error happens during production of the formatted string, NULL is
+returned, and an error message is recorded in \fIinterp\fR, if \fIinterp\fR
+is non-NULL.
+.PP
+\fBTcl_AppendFormatToObj\fR is an appending alternative form
+of \fBTcl_Format\fR with functionality equivalent to
+.CS
+Tcl_Obj *newPtr = Tcl_Format(interp, format, objc, objv);
+if (newPtr == NULL) return TCL_ERROR;
+Tcl_AppendObjToObj(objPtr, newPtr);
+return TCL_OK;
+.CE
+but with greater convenience and efficiency when the appending
+functionality is needed.
+.PP
+\fBTcl_ObjPrintf\fR serves as a replacement for the common sequence
+.CS
+char buf[SOME_SUITABLE_LENGTH];
+sprintf(buf, format, ...);
+Tcl_NewStringObj(buf, -1);
+.CE
+but with greater convenience and no need to
+determine \fBSOME_SUITABLE_LENGTH\fR. The formatting is done with the same
+core formatting engine used by \fBTcl_Format\fR. This means the set of
+supported conversion specifiers is that of the \fBformat\fR command and
+not that of the \fBsprintf\fR routine where the two sets differ. When a
+conversion specifier passed to \fBTcl_ObjPrintf\fR includes a precision,
+the value is taken as a number of bytes, as \fBsprintf\fR does, and not
+as a number of characters, as \fBformat\fR does. This is done on the
+assumption that C code is more likely to know how many bytes it is
+passing around than the number of encoded characters those bytes happen
+to represent. The variable number of arguments passed in should be of
+the types that would be suitable for passing to \fBsprintf\fR. Note in
+this example usage, \fIx\fR is of type \fBlong\fR.
+.CS
+long x = 5;
+Tcl_Obj *objPtr = Tcl_ObjPrintf("Value is %d", x);
+.CE
+If the value of \fIformat\fR contains internal inconsistencies or invalid
+specifier formats, the formatted string result produced by
+\fBTcl_ObjPrintf\fR will be an error message describing the error.
+.PP
+\fBTcl_AppendPrintfToObj\fR is an appending alternative form
+of \fBTcl_ObjPrintf\fR with functionality equivalent to
+.CS
+Tcl_AppendObjToObj(objPtr, Tcl_ObjPrintf(format, ...));
+.CE
+but with greater convenience and efficiency when the appending
+functionality is needed.
+.VE 8.5
+.PP
The \fBTcl_SetObjLength\fR procedure changes the length of the
string value of its \fIobjPtr\fR argument. If the \fInewLength\fR
argument is greater than the space allocated for the object's
@@ -265,7 +369,7 @@ cleaner-looking. \fBTcl_ConcatObj\fR returns a pointer to a
newly-created object whose ref count is zero.
.SH "SEE ALSO"
-Tcl_NewObj, Tcl_IncrRefCount, Tcl_DecrRefCount
+Tcl_NewObj, Tcl_IncrRefCount, Tcl_DecrRefCount, format, sprintf
.SH KEYWORDS
append, internal representation, object, object type, string object,
diff --git a/doc/SubstObj.3 b/doc/SubstObj.3
index 9f016c0..786b595 100644
--- a/doc/SubstObj.3
+++ b/doc/SubstObj.3
@@ -16,7 +16,7 @@ Tcl_SubstObj \- perform substitutions on Tcl objects
Tcl_Obj *
\fBTcl_SubstObj\fR(\fIinterp, objPtr, flags\fR)
.SH ARGUMENTS
-.AS Tcl_Interp **termPtr;
+.AS Tcl_Interp **termPtr
.AP Tcl_Interp *interp in
Interpreter in which to execute Tcl scripts and lookup variables. If
an error occurs, the interpreter's result is modified to hold an error
@@ -30,7 +30,6 @@ perform. The flags \fBTCL_SUBST_COMMANDS\fR,
currently supported, and \fBTCL_SUBST_ALL\fR is provided as a
convenience for the common case where all substitutions are desired.
.BE
-
.SH DESCRIPTION
.PP
The \fBTcl_SubstObj\fR function is used to perform substitutions on
@@ -51,19 +50,19 @@ When the \fBTCL_SUBST_VARIABLES\fR bit is set in \fIflags\fR,
sequences that look like variable substitutions for Tcl commands are
replaced by the contents of the named variable.
.PP
-When th \fBTCL_SUBST_COMMANDS\fR bit is set in \fIflags\fR, sequences
+When the \fBTCL_SUBST_COMMANDS\fR bit is set in \fIflags\fR, sequences
that look like command substitutions for Tcl commands are replaced by
-the result of evaluating that script. Where an uncaught continue
-exception occurs during the evaluation of a command substitution, an
-empty string is substituted for the command. Where an uncaught break
-exception occurs during the evaluation of a command substitution, the
+the result of evaluating that script. Where an uncaught
+.QW "continue exception"
+occurs during the evaluation of a command substitution, an
+empty string is substituted for the command. Where an uncaught
+.QW "break exception"
+occurs during the evaluation of a command substitution, the
result of the whole substitution on \fIobjPtr\fR will be truncated at
the point immediately before the start of the command substitution,
and no characters will be added to the result or substitutions
performed after that point.
-
.SH "SEE ALSO"
subst(n)
-
.SH KEYWORDS
backslash substitution, command substitution, variable substitution
diff --git a/doc/TCL_MEM_DEBUG.3 b/doc/TCL_MEM_DEBUG.3
index c531ac6..05d4564 100644
--- a/doc/TCL_MEM_DEBUG.3
+++ b/doc/TCL_MEM_DEBUG.3
@@ -7,53 +7,56 @@
.TH TCL_MEM_DEBUG 3 8.1 Tcl "Tcl Library Procedures"
.BS
.SH NAME
-TCL_MEM_DEBUG \- Compile-time flag to enable Tcl memory debugging.
+TCL_MEM_DEBUG \- Compile-time flag to enable Tcl memory debugging
.BE
-
.SH DESCRIPTION
When Tcl is compiled with \fBTCL_MEM_DEBUG\fR defined, a powerful set
-of memory debugging aids are included in the compiled binary. This
+of memory debugging aids is included in the compiled binary. This
includes C and Tcl functions which can aid with debugging
memory leaks, memory allocation overruns, and other memory related
errors.
-
.SH "ENABLING MEMORY DEBUGGING"
.PP
To enable memory debugging, Tcl should be recompiled from scratch with
-\fBTCL_MEM_DEBUG\fR defined. This will also compile in a non-stub
+\fBTCL_MEM_DEBUG\fR defined (e.g. by passing the
+\fI\-\-enable\-symbols=mem\fR flag to the \fIconfigure\fR script when
+building). This will also compile in a non-stub
version of \fBTcl_InitMemory\fR to add the \fBmemory\fR command to Tcl.
.PP
\fBTCL_MEM_DEBUG\fR must be either left defined for all modules or undefined
for all modules that are going to be linked together. If they are not, link
-errors will occur, with either \fBTclDbCkfree\fR and \fBTcl_DbCkalloc\fR or
+errors will occur, with either \fBTcl_DbCkfree\fR and \fBTcl_DbCkalloc\fR or
\fBTcl_Ckalloc\fR and \fBTcl_Ckfree\fR being undefined.
.PP
Once memory debugging support has been compiled into Tcl, the C
functions \fBTcl_ValidateAllMemory\fR, and \fBTcl_DumpActiveMemory\fR,
and the Tcl \fBmemory\fR command can be used to validate and examine
memory usage.
-
.SH "GUARD ZONES"
.PP
When memory debugging is enabled, whenever a call to \fBckalloc\fR is
-made, slightly more memory than requested is allocated so the memory debugging
-code can keep track of the allocated memory, and eight-byte ``guard
-zones'' are placed in front of and behind the space that will be
+made, slightly more memory than requested is allocated so the memory
+debugging code can keep track of the allocated memory, and eight-byte
+.QW "guard zones"
+are placed in front of and behind the space that will be
returned to the caller. (The sizes of the guard zones are defined by the
C #define \fBLOW_GUARD_SIZE\fR and #define \fBHIGH_GUARD_SIZE\fR
-in the file \fIgeneric/tclCkalloc.c\fR -- it can
+in the file \fIgeneric/tclCkalloc.c\fR \(em it can
be extended if you suspect large overwrite problems, at some cost in
performance.) A known pattern is written into the guard zones and, on
a call to \fBckfree\fR, the guard zones of the space being freed are
checked to see if either zone has been modified in any way. If one
has been, the guard bytes and their new contents are identified, and a
-``low guard failed'' or ``high guard failed'' message is issued. The
-``guard failed'' message includes the address of the memory packet and
+.QW "low guard failed"
+or
+.QW "high guard failed"
+message is issued. The
+.QW "guard failed"
+message includes the address of the memory packet and
the file name and line number of the code that called \fBckfree\fR.
This allows you to detect the common sorts of one-off problems, where
not enough space was allocated to contain the data written, for
example.
-
.SH "DEBUGGING DIFFICULT MEMORY CORRUPTION PROBLEMS"
.PP
Normally, Tcl compiled with memory debugging enabled will make it easy
@@ -66,16 +69,12 @@ This will enable memory validation from the first call to
\fBckalloc\fR, again, at a large performance impact.
.PP
If you are desperate and validating memory on every call to
-\fBckalloc\fR and \fBckfree\fR isn't enough, you can explicitly call
+\fBckalloc\fR and \fBckfree\fR is not enough, you can explicitly call
\fBTcl_ValidateAllMemory\fR directly at any point. It takes a \fIchar
*\fR and an \fIint\fR which are normally the filename and line number
of the caller, but they can actually be anything you want. Remember
to remove the calls after you find the problem.
-
.SH "SEE ALSO"
ckalloc, memory, Tcl_ValidateAllMemory, Tcl_DumpActiveMemory
-
.SH KEYWORDS
memory, debug
-
-
diff --git a/doc/Tcl.n b/doc/Tcl.n
index d329bb9..8b5b501 100644
--- a/doc/Tcl.n
+++ b/doc/Tcl.n
@@ -6,7 +6,7 @@
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
-.TH Tcl n "8.1" Tcl "Tcl Built-In Commands"
+.TH Tcl n "8.5" Tcl "Tcl Built-In Commands"
.BS
.SH NAME
Tcl \- Tool Command Language
@@ -39,17 +39,37 @@ Different commands interpret their words differently.
Words of a command are separated by white space (except for
newlines, which are command separators).
.IP "[4] \fBDouble quotes.\fR"
-If the first character of a word is double-quote (``"'') then
-the word is terminated by the next double-quote character.
+If the first character of a word is double-quote
+.PQ \N'34'
+then the word is terminated by the next double-quote character.
If semi-colons, close brackets, or white space characters
(including newlines) appear between the quotes then they are treated
as ordinary characters and included in the word.
Command substitution, variable substitution, and backslash substitution
are performed on the characters between the quotes as described below.
The double-quotes are not retained as part of the word.
-.IP "[5] \fBBraces.\fR"
-If the first character of a word is an open brace (``{'') then
-the word is terminated by the matching close brace (``}'').
+.VS 8.5 br
+.IP "[5] \fBArgument expansion.\fR"
+If a word starts with the string
+.QW {*}
+followed by a non-whitespace character, then the leading
+.QW {*}
+is removed and the rest of the word is parsed and substituted as any other
+word. After substitution, the word is parsed as a list (without command or
+variable substitutions; backslash substitutions are performed as is normal for
+a list and individual internal words may be surrounded by either braces or
+double-quote characters), and its words are added to the command being
+substituted. For instance,
+.QW "cmd a {*}{b [c]} d {*}{$e f \N'34'g h\N'34'}"
+is equivalent to
+.QW "cmd a b {[c]} d {$e} f \N'34'g h\N'34'" .
+.VE 8.5
+.IP "[6] \fBBraces.\fR"
+If the first character of a word is an open brace
+.PQ {
+and rule [5] does not apply, then
+the word is terminated by the matching close brace
+.PQ } "" .
Braces nest within the word: for each additional open
brace there must be an additional close brace (however,
if an open brace or close brace within the word is
@@ -61,20 +81,24 @@ below, nor do semi-colons, newlines, close brackets,
or white space receive any special interpretation.
The word will consist of exactly the characters between the
outer braces, not including the braces themselves.
-.IP "[6] \fBCommand substitution.\fR"
-If a word contains an open bracket (``['') then Tcl performs
-\fIcommand substitution\fR.
+.IP "[7] \fBCommand substitution.\fR"
+If a word contains an open bracket
+.PQ [
+then Tcl performs \fIcommand substitution\fR.
To do this it invokes the Tcl interpreter recursively to process
the characters following the open bracket as a Tcl script.
The script may contain any number of commands and must be terminated
-by a close bracket (``]'').
+by a close bracket
+.PQ ] "" .
The result of the script (i.e. the result of its last command) is
substituted into the word in place of the brackets and all of the
characters between them.
There may be any number of command substitutions in a single word.
Command substitution is not performed on words enclosed in braces.
-.IP "[7] \fBVariable substitution.\fR"
-If a word contains a dollar-sign (``$'') followed by one of the forms
+.IP "[8] \fBVariable substitution.\fR"
+If a word contains a dollar-sign
+.PQ $
+followed by one of the forms
described below, then Tcl performs \fIvariable
substitution\fR: the dollar-sign and the following characters are
replaced in the word by the value of a variable.
@@ -101,9 +125,10 @@ characters whatsoever except for close braces.
There may be any number of variable substitutions in a single word.
Variable substitution is not performed on words enclosed in braces.
.RE
-.IP "[8] \fBBackslash substitution.\fR"
-If a backslash (``\e'') appears within a word then
-\fIbackslash substitution\fR occurs.
+.IP "[9] \fBBackslash substitution.\fR"
+If a backslash
+.PQ \e
+appears within a word then \fIbackslash substitution\fR occurs.
In all cases but those described below the backslash is dropped and
the following character is treated as an ordinary
character and included in the word.
@@ -141,12 +166,12 @@ A single space character replaces the backslash, newline, and all spaces
and tabs after the newline. This backslash sequence is unique in that it
is replaced in a separate pre-pass before the command is actually parsed.
This means that it will be replaced even when it occurs between braces,
-and the resulting space will be treated as a word separator if it isn't
+and the resulting space will be treated as a word separator if it is not
in braces or quotes.
.TP 7
\e\e
-Backslash (``\e'').
-.VS 8.1 br
+Backslash
+.PQ \e "" .
.TP 7
\e\fIooo\fR
.
@@ -167,19 +192,20 @@ be 0.
The hexadecimal digits \fIhhhh\fR (one, two, three, or four of them) give a
sixteen-bit hexadecimal value for the Unicode character that will be
inserted.
-.VE
.LP
Backslash substitution is not performed on words enclosed in braces,
except for backslash-newline as described above.
.RE
-.IP "[9] \fBComments.\fR"
-If a hash character (``#'') appears at a point where Tcl is
+.IP "[10] \fBComments.\fR"
+If a hash character
+.PQ #
+appears at a point where Tcl is
expecting the first character of the first word of a command,
then the hash character and the characters that follow it, up
through the next newline, are treated as a comment and ignored.
The comment character only has significance when it appears
at the beginning of a command.
-.IP "[10] \fBOrder of substitution.\fR"
+.IP "[11] \fBOrder of substitution.\fR"
Each character is processed exactly once by the Tcl interpreter
as part of creating the words of a command.
For example, if variable substitution occurs then no further
@@ -200,8 +226,9 @@ set y [set x 0][incr x][incr x]
.CE
will always set the variable \fIy\fR to the value, \fI012\fR.
.RE
-.IP "[11] \fBSubstitution and word boundaries.\fR"
-Substitutions do not affect the word boundaries of a command.
+.IP "[12] \fBSubstitution and word boundaries.\fR"
+Substitutions do not affect the word boundaries of a command,
+except for argument expansion as specified in rule [5].
For example, during variable substitution the entire value of
the variable becomes part of a single word, even if the variable's
value contains spaces.
diff --git a/doc/Tcl_Main.3 b/doc/Tcl_Main.3
index 4f29c82..54b2e84 100644
--- a/doc/Tcl_Main.3
+++ b/doc/Tcl_Main.3
@@ -19,7 +19,7 @@ Tcl_Main, Tcl_SetMainLoop \- main program and event loop definition for Tcl-base
.sp
\fBTcl_SetMainLoop\fR(\fImainLoopProc\fR)
.SH ARGUMENTS
-.AS Tcl_AppInitProc *appInitProc
+.AS Tcl_MainLoopProc *mainLoopProc
.AP int argc in
Number of elements in \fIargv\fR.
.AP char *argv[] in
@@ -34,7 +34,9 @@ Address of an application-specific event loop procedure.
.SH DESCRIPTION
.PP
\fBTcl_Main\fR can serve as the main program for Tcl-based shell
-applications. A ``shell application'' is a program
+applications. A
+.QW "shell application"
+is a program
like tclsh or wish that supports both interactive interpretation
of Tcl and evaluation of a script contained in a file given as
a command line argument. \fBTcl_Main\fR is offered as a convenience
@@ -74,9 +76,12 @@ channels to their default values. See \fBTcl_StandardChannels\fR for
more information.
.PP
\fBTcl_Main\fR supports two modes of operation, depending on the
-values of \fIargc\fR and \fIargv\fR. If \fIargv[1]\fR exists and
-does not begin with the character \fI-\fR, it is taken to be the
-name of a file containing a \fIstartup script\fR, which \fBTcl_Main\fR
+values of \fIargc\fR and \fIargv\fR. If the first few arguments
+in \fIargv\fR match ?\fB\-encoding \fIname\fR? \fIfileName\fR,
+where \fIfileName\fR does not begin with the character \fI\-\fR,
+then \fIfileName\fR is taken to be the name of a file containing
+a \fIstartup script\fR, and \fIname\fR is taken to be the name
+of the encoding of the contents of that file, which \fBTcl_Main\fR
will attempt to evaluate. Otherwise, \fBTcl_Main\fR will enter an
interactive mode.
.PP
@@ -86,8 +91,9 @@ the Tcl variables \fIargc\fR, \fIargv\fR, \fIargv0\fR, and
.PP
When it has finished its own initialization, but before it processes
commands, \fBTcl_Main\fR calls the procedure given by the
-\fIappInitProc\fR argument. This procedure provides a ``hook'' for
-the application to perform its own initialization of the interpreter
+\fIappInitProc\fR argument. This procedure provides a
+.QW hook
+for the application to perform its own initialization of the interpreter
created by \fBTcl_Main\fR, such as defining application-specific
commands. The procedure must have an interface that matches the
type \fBTcl_AppInitProc\fR:
@@ -114,7 +120,6 @@ The prompts and command evaluation results are written to the standard
output channel only if the Tcl variable \fItcl_interactive\fR in the
master interpreter holds a non-zero integer value.
.PP
-.VS 8.4
\fBTcl_SetMainLoop\fR allows setting an event loop procedure to be run.
This allows, for example, Tk to be dynamically loaded and set its event
loop. The event loop will run following the startup script. If you
@@ -127,7 +132,6 @@ The main loop procedure must have an interface that matches the type
.CS
typedef void Tcl_MainLoopProc(void);
.CE
-.VE 8.4
.PP
\fBTcl_Main\fR does not return. Normally a program based on
\fBTcl_Main\fR will terminate when the \fBexit\fR command is
diff --git a/doc/Thread.3 b/doc/Thread.3
index 2ffd6ef..80d34ad 100644
--- a/doc/Thread.3
+++ b/doc/Thread.3
@@ -9,7 +9,7 @@
.TH Threads 3 "8.1" Tcl "Tcl Library Procedures"
.BS
.SH NAME
-Tcl_ConditionNotify, Tcl_ConditionWait, Tcl_ConditionFinalize, Tcl_GetThreadData, Tcl_MutexLock, Tcl_MutexUnlock, Tcl_MutexFinalize, Tcl_CreateThread, Tcl_JoinThread \- Tcl thread support.
+Tcl_ConditionNotify, Tcl_ConditionWait, Tcl_ConditionFinalize, Tcl_GetThreadData, Tcl_MutexLock, Tcl_MutexUnlock, Tcl_MutexFinalize, Tcl_CreateThread, Tcl_JoinThread \- Tcl thread support
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -41,14 +41,14 @@ int
int
\fBTcl_JoinThread\fR(\fIid, result\fR)
.SH ARGUMENTS
-.AS Tcl_ThreadDataKey *keyPtr
+.AS Tcl_CreateThreadProc threadProc out
.AP Tcl_Condition *condPtr in
A condition variable, which must be associated with a mutex lock.
.AP Tcl_Mutex *mutexPtr in
A mutex lock.
.AP Tcl_Time *timePtr in
A time limit on the condition wait. NULL to wait forever.
-Note that a polling value of 0 seconds doesn't make much sense.
+Note that a polling value of 0 seconds does not make much sense.
.AP Tcl_ThreadDataKey *keyPtr in
This identifies a block of thread local storage. The key should be
static and process-wide, yet each thread will end up associating
@@ -80,42 +80,38 @@ waited upon into it.
Beginning with the 8.1 release, the Tcl core is thread safe, which
allows you to incorporate Tcl into multithreaded applications without
customizing the Tcl core. To enable Tcl multithreading support,
-you must include the \fB--enable-threads\fR option to \fBconfigure\fR
+you must include the \fB\-\|\-enable-threads\fR option to \fBconfigure\fR
when you configure and compile your Tcl core.
.PP
An important constraint of the Tcl threads implementation is that
\fIonly the thread that created a Tcl interpreter can use that
interpreter\fR. In other words, multiple threads can not access
-the same Tcl interpreter. (However, as was the case in previous
-releases, a single thread can safely create and use multiple
-interpreters.)
-.PP
-.VS 8.3.1
-Tcl does provide \fBTcl_CreateThread\fR for creating threads. The
+the same Tcl interpreter. (However, a single thread can safely create
+and use multiple interpreters.)
+.SH DESCRIPTION
+Tcl provides \fBTcl_CreateThread\fR for creating threads. The
caller can determine the size of the stack given to the new thread and
modify the behaviour through the supplied \fIflags\fR. The value
\fBTCL_THREAD_STACK_DEFAULT\fR for the \fIstackSize\fR indicates that
the default size as specified by the operating system is to be used
-for the new thread. As for the flags, currently are only the values
-\fBTCL_THREAD_NOFLAGS\fR and \fBTCL_THREAD_JOINABLE\fR defined. The
+for the new thread. As for the flags, currently only the values
+\fBTCL_THREAD_NOFLAGS\fR and \fBTCL_THREAD_JOINABLE\fR are defined. The
first of them invokes the default behaviour with no
specialties. Using the second value marks the new thread as
\fIjoinable\fR. This means that another thread can wait for the such
marked thread to exit and join it.
.PP
-Restrictions: On some unix systems the pthread-library does not
-contain the functionality to specify the stacksize of a thread. The
-specified value for the stacksize is ignored on these systems. Both
-Windows and Macintosh currently do not support joinable threads. This
-flag value is therefore ignored on these platforms.
-.VE
+Restrictions: On some UNIX systems the pthread-library does not
+contain the functionality to specify the stack size of a thread. The
+specified value for the stack size is ignored on these systems.
+Windows currently does not support joinable threads. This
+flag value is therefore ignored on this platform.
.PP
-Tcl does provide \fBTcl_ExitThread\fR and \fBTcl_FinalizeThread\fR
+Tcl provides the \fBTcl_ExitThread\fR and \fBTcl_FinalizeThread\fR functions
for terminating threads and invoking optional per-thread exit
handlers. See the \fBTcl_Exit\fR page for more information on these
procedures.
.PP
-.VS
The \fBTcl_JoinThread\fR function is provided to allow threads to wait
upon the exit of another thread, which must have been marked as
joinable through usage of the \fBTCL_THREAD_JOINABLE\fR-flag during
@@ -127,36 +123,29 @@ thread which already exited is possible, the system will retain the
necessary information until after the call to \fBTcl_JoinThread\fR.
This means that not calling \fBTcl_JoinThread\fR for a joinable thread
will cause a memory leak.
-.VE
.PP
+The \fBTcl_GetThreadData\fR call returns a pointer to a block of
+thread-private data. Its argument is a key that is shared by all threads
+and a size for the block of storage. The storage is automatically
+allocated and initialized to all zeros the first time each thread asks for it.
+The storage is automatically deallocated by \fBTcl_FinalizeThread\fR.
+.SS "SYNCHRONIZATION AND COMMUNICATION"
Tcl provides \fBTcl_ThreadQueueEvent\fR and \fBTcl_ThreadAlert\fR
-for handling event queueing in multithreaded applications. See
+for handling event queuing in multithreaded applications. See
the \fBNotifier\fR manual page for more information on these procedures.
.PP
-In this release, the Tcl language itself provides no support for
-creating multithreaded scripts (for example, scripts that could spawn
-a Tcl interpreter in a separate thread). If you need to add this
-feature at this time, see the \fItclThreadTest.c\fR
-file in the Tcl source distribution for an experimental implementation
-or use the Tcl "Threading Extension" package implementing thread creation
-and management commands at the script level.
-
-
-.SH DESCRIPTION
A mutex is a lock that is used to serialize all threads through a piece
of code by calling \fBTcl_MutexLock\fR and \fBTcl_MutexUnlock\fR.
If one thread holds a mutex, any other thread calling \fBTcl_MutexLock\fR will
block until \fBTcl_MutexUnlock\fR is called.
-.VS
A mutex can be destroyed after its use by calling \fBTcl_MutexFinalize\fR.
The result of locking a mutex twice from the same thread is undefined.
On some platforms it will result in a deadlock.
-.VE
The \fBTcl_MutexLock\fR, \fBTcl_MutexUnlock\fR and \fBTcl_MutexFinalize\fR
procedures are defined as empty macros if not compiling with threads enabled.
For declaration of mutexes the \fBTCL_DECLARE_MUTEX\fR macro should be used.
This macro assures correct mutex handling even when the core is compiled
-without threads enabled.
+without threads enabled.
.PP
A condition variable is used as a signaling mechanism:
a thread can lock a mutex and then wait on a condition variable
@@ -174,40 +163,33 @@ The caller of \fBTcl_ConditionWait\fR should be prepared for spurious
notifications by calling \fBTcl_ConditionWait\fR within a while loop
that tests some invariant.
.PP
-.VS
A condition variable can be destroyed after its use by calling
\fBTcl_ConditionFinalize\fR.
.PP
The \fBTcl_ConditionNotify\fR, \fBTcl_ConditionWait\fR and
\fBTcl_ConditionFinalize\fR procedures are defined as empty macros if
not compiling with threads enabled.
-.VE
-.PP
-The \fBTcl_GetThreadData\fR call returns a pointer to a block of
-thread-private data. Its argument is a key that is shared by all threads
-and a size for the block of storage. The storage is automatically
-allocated and initialized to all zeros the first time each thread asks for it.
-The storage is automatically deallocated by \fBTcl_FinalizeThread\fR.
-.SH INITIALIZATION
+.SS INITIALIZATION
.PP
-All of these synchronization objects are self initializing.
+All of these synchronization objects are self-initializing.
They are implemented as opaque pointers that should be NULL
upon first use.
The mutexes and condition variables are
-.VS
either cleaned up by process exit handlers (if living that long) or
explicitly by calls to \fBTcl_MutexFinalize\fR or
\fBTcl_ConditionFinalize\fR.
-.VE
Thread local storage is reclaimed during \fBTcl_FinalizeThread\fR.
-.SH "CREATING THREADS"
-The API to create threads is not finalized at this time.
-There are private facilities to create threads that contain a new
-Tcl interpreter, and to send scripts among threads.
-Dive into tclThreadTest.c and tclThread.c for examples.
+.SH "SCRIPT-LEVEL ACCESS TO THREADS"
+.VS 8.5
+Tcl provides no built-in commands for scripts to use to create,
+manage, or join threads, nor any script-level access to mutex or
+condition variables. It provides such facilities only via C
+interfaces, and leaves it up to packages to expose these matters to
+the script level. One such package is the \fBThread\fR package.
+.VE 8.5
.SH "SEE ALSO"
-Tcl_GetCurrentThread, Tcl_ThreadQueueEvent, Tcl_ThreadAlert,
-Tcl_ExitThread, Tcl_FinalizeThread,
-Tcl_CreateThreadExitHandler, Tcl_DeleteThreadExitHandler
+Tcl_GetCurrentThread(3), Tcl_ThreadQueueEvent(3), Tcl_ThreadAlert(3),
+Tcl_ExitThread(3), Tcl_FinalizeThread(3), Tcl_CreateThreadExitHandler(3),
+Tcl_DeleteThreadExitHandler(3), Thread
.SH KEYWORDS
thread, mutex, condition variable, thread local storage
diff --git a/doc/ToUpper.3 b/doc/ToUpper.3
index ece0fb2..d6b3006 100644
--- a/doc/ToUpper.3
+++ b/doc/ToUpper.3
@@ -8,7 +8,7 @@
.TH Tcl_UtfToUpper 3 "8.1" Tcl "Tcl Library Procedures"
.BS
.SH NAME
-Tcl_UniCharToUpper, Tcl_UniCharToLower, Tcl_UniCharToTitle, Tcl_UtfToUpper, Tcl_UtfToLower, Tcl_UtfToTitle \- routines for manipulating the case of Unicode characters and UTF-8 strings.
+Tcl_UniCharToUpper, Tcl_UniCharToLower, Tcl_UniCharToTitle, Tcl_UtfToUpper, Tcl_UtfToLower, Tcl_UtfToTitle \- routines for manipulating the case of Unicode characters and UTF-8 strings
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
diff --git a/doc/TraceCmd.3 b/doc/TraceCmd.3
index 5c84249..020f1ca 100644
--- a/doc/TraceCmd.3
+++ b/doc/TraceCmd.3
@@ -25,10 +25,11 @@ void
.AS Tcl_CommandTraceProc prevClientData
.AP Tcl_Interp *interp in
Interpreter containing the command.
-.AP "CONST char" *cmdName in
+.AP "const char" *cmdName in
Name of command.
.AP int flags in
-OR-ed collection of the value TCL_TRACE_RENAME and TCL_TRACE_DELETE.
+OR'ed collection of the values \fBTCL_TRACE_RENAME\fR and
+\fBTCL_TRACE_DELETE\fR.
.AP Tcl_CommandTraceProc *proc in
Procedure to call when specified operations occur to \fIcmdName\fR.
.AP ClientData clientData in
@@ -38,19 +39,18 @@ If non-NULL, gives last value returned by \fBTcl_CommandTraceInfo\fR,
so this call will return information about next trace. If NULL, this
call will return information about first trace.
.BE
-
.SH DESCRIPTION
.PP
\fBTcl_TraceCommand\fR allows a C procedure to monitor operations
performed on a Tcl command, so that the C procedure is invoked
whenever the command is renamed or deleted. If the trace is created
-successfully then \fBTcl_TraceCommand\fR returns TCL_OK. If an error
+successfully then \fBTcl_TraceCommand\fR returns \fBTCL_OK\fR. If an error
occurred (e.g. \fIcmdName\fR specifies a non-existent command) then
-TCL_ERROR is returned and an error message is left in the
+\fBTCL_ERROR\fR is returned and an error message is left in the
interpreter's result.
.PP
The \fIflags\fR argument to \fBTcl_TraceCommand\fR indicates when the
-trace procedure is to be invoked. It consists of an OR-ed combination
+trace procedure is to be invoked. It consists of an OR'ed combination
of any of the following values:
.TP
\fBTCL_TRACE_RENAME\fR
@@ -64,10 +64,10 @@ Whenever one of the specified operations occurs to the command,
match the type \fBTcl_CommandTraceProc\fR:
.CS
typedef void Tcl_CommandTraceProc(
- ClientData \fIclientData\fR,
+ ClientData \fIclientData\fR,
Tcl_Interp *\fIinterp\fR,
- CONST char *\fIoldName\fR,
- CONST char *\fInewName\fR,
+ const char *\fIoldName\fR,
+ const char *\fInewName\fR,
int \fIflags\fR);
.CE
The \fIclientData\fR and \fIinterp\fR parameters will have the same
@@ -77,17 +77,17 @@ data structure that describes what to do when \fIproc\fR is invoked.
\fIOldName\fR gives the name of the command being renamed, and
\fInewName\fR gives the name that the command is being renamed to (or
an empty string or NULL when the command is being deleted.)
-\fIFlags\fR is an OR-ed combination of bits potentially providing
-several pieces of information. One of the bits TCL_TRACE_RENAME and
-TCL_TRACE_DELETE will be set in \fIflags\fR to indicate which
+\fIFlags\fR is an OR'ed combination of bits potentially providing
+several pieces of information. One of the bits \fBTCL_TRACE_RENAME\fR and
+\fBTCL_TRACE_DELETE\fR will be set in \fIflags\fR to indicate which
operation is being performed on the command. The bit
-TCL_TRACE_DESTROYED will be set in \fIflags\fR if the trace is about
+\fBTCL_TRACE_DESTROYED\fR will be set in \fIflags\fR if the trace is about
to be destroyed; this information may be useful to \fIproc\fR so that
it can clean up its own internal data structures (see the section
-TCL_TRACE_DESTROYED below for more details). Lastly, the bit
-TCL_INTERP_DESTROYED will be set if the entire interpreter is being
+\fBTCL_TRACE_DESTROYED\fR below for more details). Lastly, the bit
+\fBTCL_INTERP_DESTROYED\fR will be set if the entire interpreter is being
destroyed. When this bit is set, \fIproc\fR must be especially
-careful in the things it does (see the section TCL_INTERP_DESTROYED
+careful in the things it does (see the section \fBTCL_INTERP_DESTROYED\fR
below).
.PP
\fBTcl_UntraceCommand\fR may be used to remove a trace. If the
@@ -109,7 +109,7 @@ argument.
If the \fIprevClientData\fR argument is NULL then the return
value corresponds to the first (most recently created) matching
trace, or NULL if there are no matching traces.
-If the \fIprevClientData\fR argument isn't NULL, then it should
+If the \fIprevClientData\fR argument is not NULL, then it should
be the return value from a previous call to \fBTcl_CommandTraceInfo\fR.
In this case, the new return value will correspond to the next
matching trace after the one whose \fIclientData\fR matches
@@ -117,15 +117,13 @@ matching trace after the one whose \fIclientData\fR matches
or if there are no more matching traces after it.
This mechanism makes it possible to step through all of the
traces for a given command that have the same \fIproc\fR.
-
.SH "CALLING COMMANDS DURING TRACES"
.PP
During rename traces, the command being renamed is visible with both
names simultaneously, and the command still exists during delete
-traces (if TCL_INTERP_DESTROYED is not set). However, there is no
+traces (if \fBTCL_INTERP_DESTROYED\fR is not set). However, there is no
mechanism for signaling that an error occurred in a trace procedure,
so great care should be taken that errors do not get silently lost.
-
.SH "MULTIPLE TRACES"
.PP
It is possible for multiple traces to exist on the same command.
@@ -137,32 +135,27 @@ If the command being renamed is renamed by one of its rename traces,
that renaming takes precedence over the one that triggered the trace
and the collection of traces will not be reexecuted; if several traces
rename the command, the last renaming takes precedence.
-
.SH "TCL_TRACE_DESTROYED FLAG"
.PP
-In a delete callback to \fIproc\fR, the TCL_TRACE_DESTROYED bit
+In a delete callback to \fIproc\fR, the \fBTCL_TRACE_DESTROYED\fR bit
is set in \fIflags\fR.
-
-'\" Perhaps need some more comments here? - DKF
-
+.\" Perhaps need some more comments here? - DKF
.SH "TCL_INTERP_DESTROYED"
.PP
When an interpreter is destroyed, unset traces are called for
all of its commands.
-The TCL_INTERP_DESTROYED bit will be set in the \fIflags\fR
+The \fBTCL_INTERP_DESTROYED\fR bit will be set in the \fIflags\fR
argument passed to the trace procedures.
Trace procedures must be extremely careful in what they do if
-the TCL_INTERP_DESTROYED bit is set.
+the \fBTCL_INTERP_DESTROYED\fR bit is set.
It is not safe for the procedures to invoke any Tcl procedures
on the interpreter, since its state is partially deleted.
All that trace procedures should do under these circumstances is
to clean up and free their own internal data structures.
-
.SH BUGS
.PP
-Tcl doesn't do any error checking to prevent trace procedures
-from misusing the interpreter during traces with TCL_INTERP_DESTROYED
+Tcl does not do any error checking to prevent trace procedures
+from misusing the interpreter during traces with \fBTCL_INTERP_DESTROYED\fR
set.
-
.SH KEYWORDS
clientData, trace, command
diff --git a/doc/TraceVar.3 b/doc/TraceVar.3
index 98b242e..f80d86f 100644
--- a/doc/TraceVar.3
+++ b/doc/TraceVar.3
@@ -33,23 +33,24 @@ ClientData
.AS Tcl_VarTraceProc prevClientData
.AP Tcl_Interp *interp in
Interpreter containing variable.
-.AP "CONST char" *varName in
+.AP "const char" *varName in
Name of variable. May refer to a scalar variable, to
an array variable with no index, or to an array variable
with a parenthesized index.
.AP int flags in
-OR-ed combination of the values TCL_TRACE_READS, TCL_TRACE_WRITES,
-TCL_TRACE_UNSETS, TCL_TRACE_ARRAY, TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
-TCL_TRACE_RESULT_DYNAMIC and TCL_TRACE_RESULT_OBJECT.
+OR-ed combination of the values \fBTCL_TRACE_READS\fR,
+\fBTCL_TRACE_WRITES\fR, \fBTCL_TRACE_UNSETS\fR, \fBTCL_TRACE_ARRAY\fR,
+\fBTCL_GLOBAL_ONLY\fR, \fBTCL_NAMESPACE_ONLY\fR,
+\fBTCL_TRACE_RESULT_DYNAMIC\fR and \fBTCL_TRACE_RESULT_OBJECT\fR.
Not all flags are used by all
procedures. See below for more information.
.AP Tcl_VarTraceProc *proc in
Procedure to invoke whenever one of the traced operations occurs.
.AP ClientData clientData in
Arbitrary one-word value to pass to \fIproc\fR.
-.AP "CONST char" *name1 in
+.AP "const char" *name1 in
Name of scalar or array variable (without array index).
-.AP "CONST char" *name2 in
+.AP "const char" *name2 in
For a trace on an element of an array, gives the index of the
element. For traces on scalar variables or on whole arrays,
is NULL.
@@ -59,15 +60,14 @@ If non-NULL, gives last value returned by \fBTcl_VarTraceInfo\fR or
next trace. If NULL, this call will return information about first
trace.
.BE
-
.SH DESCRIPTION
.PP
\fBTcl_TraceVar\fR allows a C procedure to monitor and control
access to a Tcl variable, so that the C procedure is invoked
whenever the variable is read or written or unset.
If the trace is created successfully then \fBTcl_TraceVar\fR returns
-TCL_OK. If an error occurred (e.g. \fIvarName\fR specifies an element
-of an array, but the actual variable isn't an array) then TCL_ERROR
+\fBTCL_OK\fR. If an error occurred (e.g. \fIvarName\fR specifies an element
+of an array, but the actual variable is not an array) then \fBTCL_ERROR\fR
is returned and an error message is left in the interpreter's result.
.PP
The \fIflags\fR argument to \fBTcl_TraceVar\fR indicates when the
@@ -103,21 +103,19 @@ Invoke \fIproc\fR whenever the array command is invoked.
This gives the trace procedure a chance to update the array before
array names or array get is called. Note that this is called
before an array set, but that will trigger write traces.
-.VS 8.4
.TP
\fBTCL_TRACE_RESULT_DYNAMIC\fR
The result of invoking the \fIproc\fR is a dynamically allocated
string that will be released by the Tcl library via a call to
\fBckfree\fR. Must not be specified at the same time as
-TCL_TRACE_RESULT_OBJECT.
+\fBTCL_TRACE_RESULT_OBJECT\fR.
.TP
\fBTCL_TRACE_RESULT_OBJECT\fR
The result of invoking the \fIproc\fR is a Tcl_Obj* (cast to a char*)
with a reference count of at least one. The ownership of that
reference will be transferred to the Tcl core for release (when the
core has finished with it) via a call to \fBTcl_DecrRefCount\fR. Must
-not be specified at the same time as TCL_TRACE_RESULT_DYNAMIC.
-.VE 8.4
+not be specified at the same time as \fBTCL_TRACE_RESULT_DYNAMIC\fR.
.PP
Whenever one of the specified operations occurs on the variable,
\fIproc\fR will be invoked.
@@ -125,11 +123,11 @@ It should have arguments and result that match the type
\fBTcl_VarTraceProc\fR:
.CS
typedef char *Tcl_VarTraceProc(
- ClientData \fIclientData\fR,
- Tcl_Interp *\fIinterp\fR,
- char *\fIname1\fR,
- char *\fIname2\fR,
- int \fIflags\fR);
+ ClientData \fIclientData\fR,
+ Tcl_Interp *\fIinterp\fR,
+ char *\fIname1\fR,
+ char *\fIname2\fR,
+ int \fIflags\fR);
.CE
The \fIclientData\fR and \fIinterp\fR parameters will
have the same values as those passed to \fBTcl_TraceVar\fR when the
@@ -142,30 +140,30 @@ in the normal two-part form (see the description of \fBTcl_TraceVar2\fR
below for details).
\fIFlags\fR is an OR-ed combination of bits providing several
pieces of information.
-One of the bits TCL_TRACE_READS, TCL_TRACE_WRITES, TCL_TRACE_ARRAY,
-or TCL_TRACE_UNSETS
+One of the bits \fBTCL_TRACE_READS\fR, \fBTCL_TRACE_WRITES\fR,
+\fBTCL_TRACE_ARRAY\fR, or \fBTCL_TRACE_UNSETS\fR
will be set in \fIflags\fR to indicate which operation is being performed
on the variable.
-The bit TCL_GLOBAL_ONLY will be set whenever the variable being
+The bit \fBTCL_GLOBAL_ONLY\fR will be set whenever the variable being
accessed is a global one not accessible from the current level of
procedure call: the trace procedure will need to pass this flag
back to variable-related procedures like \fBTcl_GetVar\fR if it
attempts to access the variable.
-The bit TCL_NAMESPACE_ONLY will be set whenever the variable being
+The bit \fBTCL_NAMESPACE_ONLY\fR will be set whenever the variable being
accessed is a namespace one not accessible from the current level of
procedure call: the trace procedure will need to pass this flag
back to variable-related procedures like \fBTcl_GetVar\fR if it
attempts to access the variable.
-The bit TCL_TRACE_DESTROYED will be set in \fIflags\fR if the trace is
+The bit \fBTCL_TRACE_DESTROYED\fR will be set in \fIflags\fR if the trace is
about to be destroyed; this information may be useful to \fIproc\fR
so that it can clean up its own internal data structures (see
-the section TCL_TRACE_DESTROYED below for more details).
-Lastly, the bit TCL_INTERP_DESTROYED will be set if the entire
+the section \fBTCL_TRACE_DESTROYED\fR below for more details).
+Lastly, the bit \fBTCL_INTERP_DESTROYED\fR will be set if the entire
interpreter is being destroyed.
When this bit is set, \fIproc\fR must be especially careful in
-the things it does (see the section TCL_INTERP_DESTROYED below).
+the things it does (see the section \fBTCL_INTERP_DESTROYED\fR below).
The trace procedure's return value should normally be NULL; see
-ERROR RETURNS below for information on other possibilities.
+\fBERROR RETURNS\fR below for information on other possibilities.
.PP
\fBTcl_UntraceVar\fR may be used to remove a trace.
If the variable specified by \fIinterp\fR, \fIvarName\fR, and \fIflags\fR
@@ -180,14 +178,14 @@ traces set on a given variable.
The return value from \fBTcl_VarTraceInfo\fR is the \fIclientData\fR
associated with a particular trace.
The trace must be on the variable specified by the \fIinterp\fR,
-\fIvarName\fR, and \fIflags\fR arguments (only the TCL_GLOBAL_ONLY and
-TCL_NAMESPACE_ONLY bits from \fIflags\fR is used; other bits are
+\fIvarName\fR, and \fIflags\fR arguments (only the \fBTCL_GLOBAL_ONLY\fR and
+\fBTCL_NAMESPACE_ONLY\fR bits from \fIflags\fR is used; other bits are
ignored) and its trace procedure must the same as the \fIproc\fR
argument.
If the \fIprevClientData\fR argument is NULL then the return
value corresponds to the first (most recently created) matching
trace, or NULL if there are no matching traces.
-If the \fIprevClientData\fR argument isn't NULL, then it should
+If the \fIprevClientData\fR argument is not NULL, then it should
be the return value from a previous call to \fBTcl_VarTraceInfo\fR.
In this case, the new return value will correspond to the next
matching trace after the one whose \fIclientData\fR matches
@@ -195,7 +193,6 @@ matching trace after the one whose \fIclientData\fR matches
or if there are no more matching traces after it.
This mechanism makes it possible to step through all of the
traces for a given variable that have the same \fIproc\fR.
-
.SH "TWO-PART NAMES"
.PP
The procedures \fBTcl_TraceVar2\fR, \fBTcl_UntraceVar2\fR, and
@@ -204,7 +201,6 @@ The procedures \fBTcl_TraceVar2\fR, \fBTcl_UntraceVar2\fR, and
except that the name of the variable consists of two parts.
\fIName1\fR gives the name of a scalar variable or array,
and \fIname2\fR gives the name of an element within an array.
-.VS 8.1
When \fIname2\fR is NULL,
\fIname1\fR may contain both an array and an element name:
if the name contains an open parenthesis and ends with a
@@ -213,14 +209,10 @@ treated as an element name (which can have any string value) and
the characters before the first open
parenthesis are treated as the name of an array variable.
If \fIname2\fR is NULL and \fIname1\fR does not refer
-to an array element
-.VE
-it means that either the variable is
+to an array element it means that either the variable is
a scalar or the trace is to be set on the entire array rather
than an individual element (see WHOLE-ARRAY TRACES below for
more information).
-
-
.SH "ACCESSING VARIABLES DURING TRACES"
.PP
During read, write, and array traces, the
@@ -246,7 +238,6 @@ from the variable before any trace procedures are invoked.
If new traces are set by unset trace procedures, these traces
will be invoked on accesses to the variable by the trace
procedures.
-
.SH "CALLBACK TIMING"
.PP
When read tracing has been specified for a variable, the trace
@@ -286,7 +277,6 @@ When unset tracing has been specified, the trace procedure
will be invoked whenever the variable is destroyed.
The traces will be called after the variable has been
completely unset.
-
.SH "WHOLE-ARRAY TRACES"
.PP
If a call to \fBTcl_TraceVar\fR or \fBTcl_TraceVar2\fR specifies
@@ -299,7 +289,6 @@ When an array is unset, a whole-array trace will be invoked
just once, with \fIname1\fR equal to the name of the array
and \fIname2\fR NULL; it will not be invoked once for each
element.
-
.SH "MULTIPLE TRACES"
.PP
It is possible for multiple traces to exist on the same variable.
@@ -311,7 +300,6 @@ before the individual-element traces.
If a read or write trace unsets the variable then all of the unset
traces will be invoked but the remainder of the read and write traces
will be skipped.
-
.SH "ERROR RETURNS"
.PP
Under normal conditions trace procedures should return NULL, indicating
@@ -320,13 +308,11 @@ If \fIproc\fR returns a non-NULL value it signifies that an
error occurred.
The return value must be a pointer to a static character string
containing an error message,
-.VS 8.4
-unless (\fIexactly\fR one of) the TCL_TRACE_RESULT_DYNAMIC and
-TCL_TRACE_RESULT_OBJECT flags is set, which specify that the result is
+unless (\fIexactly\fR one of) the \fBTCL_TRACE_RESULT_DYNAMIC\fR and
+\fBTCL_TRACE_RESULT_OBJECT\fR flags is set, which specify that the result is
either a dynamic string (to be released with \fBckfree\fR) or a
Tcl_Obj* (cast to char* and to be released with
\fBTcl_DecrRefCount\fR) containing the error message.
-.VE 8.4
If a trace procedure returns an error, no further traces are
invoked for the access and the traced access aborts with the
given message.
@@ -340,56 +326,51 @@ The return value from \fIproc\fR is only used during read and
write tracing.
During unset traces, the return value is ignored and all relevant
trace procedures will always be invoked.
-
.SH "RESTRICTIONS"
.PP
A trace procedure can be called at any time, even when there
-is a partially-formed result in the interpreter's result area. If
+is a partially formed result in the interpreter's result area. If
the trace procedure does anything that could damage this result (such
as calling \fBTcl_Eval\fR) then it must save the original values of
the interpreter's \fBresult\fR and \fBfreeProc\fR fields and restore
them before it returns.
-
.SH "UNDEFINED VARIABLES"
.PP
It is legal to set a trace on an undefined variable.
The variable will still appear to be undefined until the
first time its value is set.
If an undefined variable is traced and then unset, the unset will fail
-with an error (``no such variable''), but the trace
-procedure will still be invoked.
-
+with an error
+.PQ "no such variable" "" ,
+but the trace procedure will still be invoked.
.SH "TCL_TRACE_DESTROYED FLAG"
.PP
-In an unset callback to \fIproc\fR, the TCL_TRACE_DESTROYED bit
+In an unset callback to \fIproc\fR, the \fBTCL_TRACE_DESTROYED\fR bit
is set in \fIflags\fR if the trace is being removed as part
of the deletion.
Traces on a variable are always removed whenever the variable
-is deleted; the only time TCL_TRACE_DESTROYED isn't set is for
+is deleted; the only time \fBTCL_TRACE_DESTROYED\fR is not set is for
a whole-array trace invoked when only a single element of an
array is unset.
-
.SH "TCL_INTERP_DESTROYED"
.PP
When an interpreter is destroyed, unset traces are called for
all of its variables.
-The TCL_INTERP_DESTROYED bit will be set in the \fIflags\fR
+The \fBTCL_INTERP_DESTROYED\fR bit will be set in the \fIflags\fR
argument passed to the trace procedures.
Trace procedures must be extremely careful in what they do if
-the TCL_INTERP_DESTROYED bit is set.
+the \fBTCL_INTERP_DESTROYED\fR bit is set.
It is not safe for the procedures to invoke any Tcl procedures
on the interpreter, since its state is partially deleted.
All that trace procedures should do under these circumstances is
to clean up and free their own internal data structures.
-
.SH BUGS
.PP
-Tcl doesn't do any error checking to prevent trace procedures
-from misusing the interpreter during traces with TCL_INTERP_DESTROYED
+Tcl does not do any error checking to prevent trace procedures
+from misusing the interpreter during traces with \fBTCL_INTERP_DESTROYED\fR
set.
.PP
-Array traces are not yet integrated with the Tcl "info exists" command,
+Array traces are not yet integrated with the Tcl \fBinfo exists\fR command,
nor is there Tcl-level access to array traces.
-
.SH KEYWORDS
clientData, trace, variable
diff --git a/doc/Translate.3 b/doc/Translate.3
index 59a64ea..d434cda 100644
--- a/doc/Translate.3
+++ b/doc/Translate.3
@@ -17,11 +17,12 @@ Tcl_TranslateFileName \- convert file name to native form and replace tilde with
char *
\fBTcl_TranslateFileName\fR(\fIinterp\fR, \fIname\fR, \fIbufferPtr\fR)
.SH ARGUMENTS
-.AS Tcl_DString *bufferPtr
+.AS Tcl_DString *bufferPtr in/out
.AP Tcl_Interp *interp in
Interpreter in which to report an error, if any.
-.AP "CONST char" *name in
-File name, which may start with a ``~''.
+.AP "const char" *name in
+File name, which may start with a
+.QW ~ .
.AP Tcl_DString *bufferPtr in/out
If needed, this dynamic string is used to store the new file name.
At the time of the call it should be uninitialized or free. The
@@ -31,9 +32,18 @@ anything stored here.
.SH DESCRIPTION
.PP
-This utility procedure translates a file name to a form suitable for
-passing to the local operating system. It converts network names into
-native form and does tilde substitution.
+This utility procedure translates a file name to a platform-specific form
+which, after being converted to the appropriate encoding, is suitable for
+passing to the local operating system. In particular, it converts
+network names into native form and does tilde substitution.
+.PP
+However, with the advent of the newer \fBTcl_FSGetNormalizedPath\fR and
+\fBTcl_GetNativePath\fR, there is no longer any need to use this
+procedure. In particular, \fBTcl_GetNativePath\fR performs all the
+necessary translation and encoding conversion, is virtual-filesystem
+aware, and caches the native result for faster repeated calls.
+Finally \fBTcl_GetNativePath\fR does not require you to free anything
+afterwards.
.PP
If
\fBTcl_TranslateFileName\fR has to do tilde substitution or translate
@@ -44,7 +54,7 @@ After \fBTcl_TranslateFileName\fR returns a non-NULL result, the caller must
eventually invoke \fBTcl_DStringFree\fR to free any information
placed in \fI*bufferPtr\fR. The caller need not know whether or
not \fBTcl_TranslateFileName\fR actually used the string; \fBTcl_TranslateFileName\fR
-initializes \fI*bufferPtr\fR even if it doesn't use it, so the call to
+initializes \fI*bufferPtr\fR even if it does not use it, so the call to
\fBTcl_DStringFree\fR will be safe in either case.
.PP
If an error occurs (e.g. because there was no user by the given
diff --git a/doc/UniCharIsAlpha.3 b/doc/UniCharIsAlpha.3
index 22b81c1..6029b2d 100644
--- a/doc/UniCharIsAlpha.3
+++ b/doc/UniCharIsAlpha.3
@@ -46,6 +46,7 @@ int
int
\fBTcl_UniCharIsWordChar\fR(\fIch\fR)
.SH ARGUMENTS
+.AS int ch
.AP int ch in
The Tcl_UniChar to be examined.
.BE
@@ -61,7 +62,7 @@ with the various routines.
Note: A Tcl_UniChar is a Unicode character represented as an unsigned,
fixed-size quantity.
-.SH CHARACTER CLASSES
+.SH "CHARACTER CLASSES"
.PP
\fBTcl_UniCharIsAlnum\fR tests if the character is an alphanumeric Unicode character.
.PP
diff --git a/doc/UpVar.3 b/doc/UpVar.3
index 95c4a9a..f1e6fe4 100644
--- a/doc/UpVar.3
+++ b/doc/UpVar.3
@@ -20,30 +20,31 @@ int
int
\fBTcl_UpVar2(\fIinterp, frameName, name1, name2, destName, flags\fB)\fR
.SH ARGUMENTS
-.AS Tcl_VarTraceProc prevClientData
+.AS "const char" *sourceName
.AP Tcl_Interp *interp in
Interpreter containing variables; also used for error reporting.
-.AP "CONST char" *frameName in
+.AP "const char" *frameName in
Identifies the stack frame containing source variable.
May have any of the forms accepted by
the \fBupvar\fR command, such as \fB#0\fR or \fB1\fR.
-.AP "CONST char" *sourceName in
+.AP "const char" *sourceName in
Name of source variable, in the frame given by \fIframeName\fR.
May refer to a scalar variable or to an array variable with a
parenthesized index.
-.AP "CONST char" *destName in
+.AP "const char" *destName in
Name of destination variable, which is to be linked to source
variable so that references to \fIdestName\fR
refer to the other variable. Must not currently exist except as
an upvar-ed variable.
.AP int flags in
-Either TCL_GLOBAL_ONLY or 0; if non-zero, then \fIdestName\fR is
-a global variable; otherwise it is a local to the current procedure
-(or global if no procedure is active).
-.AP "CONST char" *name1 in
+One of \fBTCL_GLOBAL_ONLY\fR, \fBTCL_NAMESPACE_ONLY\fR or 0; if non-zero,
+then \fIdestName\fR is a global or namespace variable; otherwise it is
+local to the current procedure (or current namespace if no procedure is
+active).
+.AP "const char" *name1 in
First part of source variable's name (scalar name, or name of array
without array index).
-.AP "CONST char" *name2 in
+.AP "const char" *name2 in
If source variable is an element of an array, gives the index of the element.
For scalar source variables, is NULL.
.BE
@@ -61,7 +62,7 @@ element name (by calling \fBTcl_UpVar2\fR).
The destination variable name is specified in a single string; it
may not be an array element.
.PP
-Both procedures return either TCL_OK or TCL_ERROR, and they
+Both procedures return either \fBTCL_OK\fR or \fBTCL_ERROR\fR, and they
leave an error message in the interpreter's result if an error occurs.
.PP
As with the \fBupvar\fR command, the source variable need not exist;
diff --git a/doc/Utf.3 b/doc/Utf.3
index af472ae..8e39fef 100644
--- a/doc/Utf.3
+++ b/doc/Utf.3
@@ -8,7 +8,7 @@
.TH Utf 3 "8.1" Tcl "Tcl Library Procedures"
.BS
.SH NAME
-Tcl_UniChar, Tcl_UniCharCaseMatch, Tcl_UniCharNcasecmp, Tcl_UniCharToUtf, Tcl_UtfToUniChar, Tcl_UniCharToUtfDString, Tcl_UtfToUniCharDString, Tcl_UniCharLen, Tcl_UniCharNcmp, Tcl_UtfCharComplete, Tcl_NumUtfChars, Tcl_UtfFindFirst, Tcl_UtfFindLast, Tcl_UtfNext, Tcl_UtfPrev, Tcl_UniCharAtIndex, Tcl_UtfAtIndex, Tcl_UtfBackslash \- routines for manipulating UTF-8 strings.
+Tcl_UniChar, Tcl_UniCharCaseMatch, Tcl_UniCharNcasecmp, Tcl_UniCharToUtf, Tcl_UtfToUniChar, Tcl_UniCharToUtfDString, Tcl_UtfToUniCharDString, Tcl_UniCharLen, Tcl_UniCharNcmp, Tcl_UtfCharComplete, Tcl_NumUtfChars, Tcl_UtfFindFirst, Tcl_UtfFindLast, Tcl_UtfNext, Tcl_UtfPrev, Tcl_UniCharAtIndex, Tcl_UtfAtIndex, Tcl_UtfBackslash \- routines for manipulating UTF-8 strings
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -20,91 +20,91 @@ int
.sp
int
\fBTcl_UtfToUniChar\fR(\fIsrc, chPtr\fR)
-.VS 8.4
.sp
char *
-\fBTcl_UniCharToUtfDString\fR(\fIuniStr, numChars, dstPtr\fR)
+\fBTcl_UniCharToUtfDString\fR(\fIuniStr, uniLength, dsPtr\fR)
.sp
Tcl_UniChar *
-\fBTcl_UtfToUniCharDString\fR(\fIsrc, len, dstPtr\fR)
-.VE 8.4
+\fBTcl_UtfToUniCharDString\fR(\fIsrc, length, dsPtr\fR)
.sp
int
\fBTcl_UniCharLen\fR(\fIuniStr\fR)
.sp
int
-\fBTcl_UniCharNcmp\fR(\fIuniStr, uniStr, num\fR)
-.VS 8.4
+\fBTcl_UniCharNcmp\fR(\fIucs, uct, numChars\fR)
.sp
int
-\fBTcl_UniCharNcasecmp\fR(\fIuniStr, uniStr, num\fR)
+\fBTcl_UniCharNcasecmp\fR(\fIucs, uct, numChars\fR)
.sp
int
\fBTcl_UniCharCaseMatch\fR(\fIuniStr, uniPattern, nocase\fR)
-.VE 8.4
.sp
int
-\fBTcl_UtfNcmp\fR(\fIsrc, src, num\fR)
+\fBTcl_UtfNcmp\fR(\fIcs, ct, numChars\fR)
.sp
int
-\fBTcl_UtfNcasecmp\fR(\fIsrc, src, num\fR)
+\fBTcl_UtfNcasecmp\fR(\fIcs, ct, numChars\fR)
.sp
int
-\fBTcl_UtfCharComplete\fR(\fIsrc, len\fR)
+\fBTcl_UtfCharComplete\fR(\fIsrc, length\fR)
.sp
int
-\fBTcl_NumUtfChars\fR(\fIsrc, len\fR)
-.VS 8.4
+\fBTcl_NumUtfChars\fR(\fIsrc, length\fR)
.sp
-CONST char *
+const char *
\fBTcl_UtfFindFirst\fR(\fIsrc, ch\fR)
.sp
-CONST char *
+const char *
\fBTcl_UtfFindLast\fR(\fIsrc, ch\fR)
.sp
-CONST char *
+const char *
\fBTcl_UtfNext\fR(\fIsrc\fR)
.sp
-CONST char *
+const char *
\fBTcl_UtfPrev\fR(\fIsrc, start\fR)
-.VE 8.4
.sp
Tcl_UniChar
\fBTcl_UniCharAtIndex\fR(\fIsrc, index\fR)
-.VS 8.4
.sp
-CONST char *
+const char *
\fBTcl_UtfAtIndex\fR(\fIsrc, index\fR)
-.VE 8.4
.sp
int
\fBTcl_UtfBackslash\fR(\fIsrc, readPtr, dst\fR)
.SH ARGUMENTS
-.AS "CONST Tcl_UniChar" numChars in/out
+.AS "const Tcl_UniChar" *uniPattern in/out
.AP char *buf out
Buffer in which the UTF-8 representation of the Tcl_UniChar is stored. At most
-TCL_UTF_MAX bytes are stored in the buffer.
+\fBTCL_UTF_MAX\fR bytes are stored in the buffer.
.AP int ch in
The Tcl_UniChar to be converted or examined.
.AP Tcl_UniChar *chPtr out
Filled with the Tcl_UniChar represented by the head of the UTF-8 string.
-.AP "CONST char" *src in
+.AP "const char" *src in
Pointer to a UTF-8 string.
-.AP "CONST Tcl_UniChar" *uniStr in
+.AP "const char" *cs in
+Pointer to a UTF-8 string.
+.AP "const char" *ct in
+Pointer to a UTF-8 string.
+.AP "const Tcl_UniChar" *uniStr in
+A null-terminated Unicode string.
+.AP "const Tcl_UniChar" *ucs in
+A null-terminated Unicode string.
+.AP "const Tcl_UniChar" *uct in
A null-terminated Unicode string.
-.AP "CONST Tcl_UniChar" *uniPattern in
+.AP "const Tcl_UniChar" *uniPattern in
A null-terminated Unicode string.
-.AP int len in
+.AP int length in
The length of the UTF-8 string in bytes (not UTF-8 characters). If
negative, all bytes up to the first null byte are used.
-.AP int numChars in
+.AP int uniLength in
The length of the Unicode string in characters. Must be greater than or
equal to 0.
-.AP "Tcl_DString" *dstPtr in/out
-A pointer to a previously-initialized \fBTcl_DString\fR.
-.AP "unsigned long" num in
+.AP "Tcl_DString" *dsPtr in/out
+A pointer to a previously initialized \fBTcl_DString\fR.
+.AP "unsigned long" numChars in
The number of characters to compare.
-.AP "CONST char" *start in
+.AP "const char" *start in
Pointer to the beginning of a UTF-8 string.
.AP int index in
The index of a character (not byte) in the UTF-8 string.
@@ -113,12 +113,10 @@ If non-NULL, filled with the number of bytes in the backslash sequence,
including the backslash character.
.AP char *dst out
Buffer in which the bytes represented by the backslash sequence are stored.
-At most TCL_UTF_MAX bytes are stored in the buffer.
-.VS 8.4
+At most \fBTCL_UTF_MAX\fR bytes are stored in the buffer.
.AP int nocase in
Specifies whether the match should be done case-sensitive (0) or
case-insensitive (1).
-.VE 8.4
.BE
.SH DESCRIPTION
@@ -126,7 +124,7 @@ case-insensitive (1).
These routines convert between UTF-8 strings and Tcl_UniChars. A
Tcl_UniChar is a Unicode character represented as an unsigned, fixed-size
quantity. A UTF-8 character is a Unicode character represented as
-a varying-length sequence of up to TCL_UTF_MAX bytes. A multibyte UTF-8
+a varying-length sequence of up to \fBTCL_UTF_MAX\fR bytes. A multibyte UTF-8
sequence consists of a lead byte followed by some number of trail bytes.
.PP
\fBTCL_UTF_MAX\fR is the maximum number of bytes that it takes to
@@ -138,7 +136,7 @@ in \fIbuf\fR.
.PP
\fBTcl_UtfToUniChar\fR reads one UTF-8 character starting at \fIsrc\fR
and stores it as a Tcl_UniChar in \fI*chPtr\fR. The return value is the
-number of bytes read from \fIsrc\fR.. The caller must ensure that the
+number of bytes read from \fIsrc\fR. The caller must ensure that the
source buffer is long enough such that this routine does not run off the
end and dereference non-existent or random memory; if the source buffer
is known to be null-terminated, this will not happen. If the input is
@@ -147,15 +145,17 @@ byte of \fIsrc\fR in \fI*chPtr\fR as a Tcl_UniChar between 0x0000 and
0x00ff and return 1.
.PP
\fBTcl_UniCharToUtfDString\fR converts the given Unicode string
-to UTF-8, storing the result in a previously-initialized \fBTcl_DString\fR.
-You must specify the length of the given Unicode string.
+to UTF-8, storing the result in a previously initialized \fBTcl_DString\fR.
+You must specify \fIuniLength\fR, the length of the given Unicode string.
The return value is a pointer to the UTF-8 representation of the
Unicode string. Storage for the return value is appended to the
end of the \fBTcl_DString\fR.
.PP
\fBTcl_UtfToUniCharDString\fR converts the given UTF-8 string to Unicode,
-storing the result in the previously-initialized \fBTcl_DString\fR.
-you may either specify the length of the given UTF-8 string or "-1",
+storing the result in the previously initialized \fBTcl_DString\fR.
+In the argument \fIlength\fR, you may either specify the length of
+the given UTF-8 string in bytes or
+.QW \-1 ,
in which case \fBTcl_UtfToUniCharDString\fR uses \fBstrlen\fR to
calculate the length. The return value is a pointer to the Unicode
representation of the UTF-8 string. Storage for the return value
@@ -168,24 +168,22 @@ the number of Unicode characters (not bytes) in that string.
.PP
\fBTcl_UniCharNcmp\fR and \fBTcl_UniCharNcasecmp\fR correspond to
\fBstrncmp\fR and \fBstrncasecmp\fR, respectively, for Unicode characters.
-They accepts two null-terminated Unicode strings and the number of characters
-to compare. Both strings are assumed to be at least \fIlen\fR characters
+They accept two null-terminated Unicode strings and the number of characters
+to compare. Both strings are assumed to be at least \fInumChars\fR characters
long. \fBTcl_UniCharNcmp\fR compares the two strings character-by-character
according to the Unicode character ordering. It returns an integer greater
than, equal to, or less than 0 if the first string is greater than, equal
to, or less than the second string respectively. \fBTcl_UniCharNcasecmp\fR
is the Unicode case insensitive version.
.PP
-.VS 8.4
\fBTcl_UniCharCaseMatch\fR is the Unicode equivalent to
\fBTcl_StringCaseMatch\fR. It accepts a null-terminated Unicode string,
a Unicode pattern, and a boolean value specifying whether the match should
be case sensitive and returns whether the string matches the pattern.
-.VE 8.4
.PP
\fBTcl_UtfNcmp\fR corresponds to \fBstrncmp\fR for UTF-8 strings. It
accepts two null-terminated UTF-8 strings and the number of characters
-to compare. (Both strings are assumed to be at least \fIlen\fR
+to compare. (Both strings are assumed to be at least \fInumChars\fR
characters long.) \fBTcl_UtfNcmp\fR compares the two strings
character-by-character according to the Unicode character ordering.
It returns an integer greater than, equal to, or less than 0 if the
@@ -198,7 +196,7 @@ differences in case when comparing upper, lower or title case
characters.
.PP
\fBTcl_UtfCharComplete\fR returns 1 if the source UTF-8 string \fIsrc\fR
-of length \fIlen\fR bytes is long enough to be decoded by
+of \fIlength\fR bytes is long enough to be decoded by
\fBTcl_UtfToUniChar\fR, or 0 otherwise. This function does not guarantee
that the UTF-8 string is properly formed. This routine is used by
procedures that are operating on a byte at a time and need to know if a
@@ -206,7 +204,7 @@ full Tcl_UniChar has been seen.
.PP
\fBTcl_NumUtfChars\fR corresponds to \fBstrlen\fR for UTF-8 strings. It
returns the number of Tcl_UniChars that are represented by the UTF-8 string
-\fIsrc\fR. The length of the source string is \fIlen\fR bytes. If the
+\fIsrc\fR. The length of the source string is \fIlength\fR bytes. If the
length is negative, all bytes up to the first null byte are used.
.PP
\fBTcl_UtfFindFirst\fR corresponds to \fBstrchr\fR for UTF-8 strings. It
@@ -248,7 +246,7 @@ the return pointer points to the first character in the source string.
\fBTcl_UtfBackslash\fR is a utility procedure used by several of the Tcl
commands. It parses a backslash sequence and stores the properly formed
UTF-8 character represented by the backslash sequence in the output
-buffer \fIdst\fR. At most TCL_UTF_MAX bytes are stored in the buffer.
+buffer \fIdst\fR. At most \fBTCL_UTF_MAX\fR bytes are stored in the buffer.
\fBTcl_UtfBackslash\fR modifies \fI*readPtr\fR to contain the number
of bytes in the backslash sequence, including the backslash character.
The return value is the number of bytes stored in the output buffer.
diff --git a/doc/WrongNumArgs.3 b/doc/WrongNumArgs.3
index 00aa653..2175858 100644
--- a/doc/WrongNumArgs.3
+++ b/doc/WrongNumArgs.3
@@ -15,16 +15,16 @@ Tcl_WrongNumArgs \- generate standard error message for wrong number of argument
.sp
\fBTcl_WrongNumArgs\fR(\fIinterp, objc, objv, message\fR)
.SH ARGUMENTS
-.AS Tcl_Interp "*CONST objv[]"
+.AS "Tcl_Obj *const" *message
.AP Tcl_Interp interp in
Interpreter in which error will be reported: error message gets stored
in its result object.
.AP int objc in
Number of leading arguments from \fIobjv\fR to include in error
message.
-.AP Tcl_Obj "*CONST\ objv[]" in
+.AP "Tcl_Obj *const" objv[] in
Arguments to command that had the wrong number of arguments.
-.AP "CONST char" *message in
+.AP "const char" *message in
Additional error information to print after leading arguments
from \fIobjv\fR. This typically gives the acceptable syntax
of the command. This argument may be NULL.
@@ -39,7 +39,8 @@ standard error message and stores it in the result object of
\fIinterp\fR. The message includes the \fIobjc\fR initial
elements of \fIobjv\fR plus \fImessage\fR. For example, if
\fIobjv\fR consists of the values \fBfoo\fR and \fBbar\fR,
-\fIobjc\fR is 1, and \fImessage\fR is ``\fBfileName count\fR''
+\fIobjc\fR is 1, and \fImessage\fR is
+.QW "\fBfileName count\fR"
then \fIinterp\fR's result object will be set to the following
string:
.CS
@@ -61,7 +62,7 @@ subcommand we would like to use the full subcommand name rather than
the abbreviation. If the \fBTcl_WrongNumArgs\fR command finds any
\fIindexObjects\fR in the \fIobjv\fR array it will use the full subcommand
name in the error message instead of the abbreviated name that was
-originally passed in. Using the above example, lets assume that
+originally passed in. Using the above example, let us assume that
\fIbar\fR is actually an abbreviation for \fIbarfly\fR and the object
is now an indexObject because it was passed to
\fBTcl_GetIndexFromObj\fR. In this case the error message would be:
diff --git a/doc/after.n b/doc/after.n
index dbe0783..21961d3 100644
--- a/doc/after.n
+++ b/doc/after.n
@@ -46,8 +46,9 @@ The delayed command is formed by concatenating all the \fIscript\fR
arguments in the same fashion as the \fBconcat\fR command.
The command will be executed at global level (outside the context
of any Tcl procedure).
-If an error occurs while executing the delayed command then the
-\fBbgerror\fR mechanism is used to report the error.
+If an error occurs while executing the delayed command then
+the background error will be reported by the command
+registered with \fB interp bgerror\fR.
The \fBafter\fR command returns an identifier that can be used
to cancel the delayed command using \fBafter cancel\fR.
.TP
@@ -76,7 +77,8 @@ loop is entered and there are no events to process.
The command returns an identifier that can be used
to cancel the delayed command using \fBafter cancel\fR.
If an error occurs while executing the script then the
-\fBbgerror\fR mechanism is used to report the error.
+background error will be reported by the command
+registered with \fB interp bgerror\fR.
.TP
\fBafter info \fR?\fIid\fR?
This command returns information about existing event handlers.
@@ -134,7 +136,7 @@ doOneStep
.CE
.SH "SEE ALSO"
-bgerror(n), concat(n), update(n), vwait(n)
+concat(n), interp(n), update(n), vwait(n)
.SH KEYWORDS
cancel, delay, idle callback, sleep, time
diff --git a/doc/append.n b/doc/append.n
index 1ff43ee..dc9adbe 100644
--- a/doc/append.n
+++ b/doc/append.n
@@ -18,15 +18,18 @@ append \- Append to variable
.SH DESCRIPTION
.PP
Append all of the \fIvalue\fR arguments to the current value
-of variable \fIvarName\fR. If \fIvarName\fR doesn't exist,
+of variable \fIvarName\fR. If \fIvarName\fR does not exist,
it is given a value equal to the concatenation of all the
\fIvalue\fR arguments.
The result of this command is the new value stored in variable
\fIvarName\fR.
This command provides an efficient way to build up long
variables incrementally.
-For example, ``\fBappend a $b\fR'' is much more efficient than
-``\fBset a $a$b\fR'' if \fB$a\fR is long.
+For example,
+.QW "\fBappend a $b\fR"
+is much more efficient than
+.QW "\fBset a $a$b\fR"
+if \fB$a\fR is long.
.SH EXAMPLE
Building a string of comma-separated numbers piecemeal using a loop.
.CS
diff --git a/doc/apply.n b/doc/apply.n
new file mode 100644
index 0000000..8a38aac
--- /dev/null
+++ b/doc/apply.n
@@ -0,0 +1,96 @@
+'\"
+'\" Copyright (c) 2006 Miguel Sofer
+'\" Copyright (c) 2006 Donal K. Fellows
+'\"
+.so man.macros
+.TH apply n "" Tcl "Tcl Built-In Commands"
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+apply \- Apply an anonymous function
+.SH SYNOPSIS
+\fBapply \fIfunc\fR ?\fIarg1 arg2 ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+The command \fBapply\fR applies the function \fIfunc\fR to the arguments
+\fIarg1 arg2 ...\fR and returns the result.
+.PP
+The function \fIfunc\fR is a two element list \fI{args body}\fR or a three
+element list \fI{args body namespace}\fR (as if the
+\fBlist\fR command had been used).
+The first element \fIargs\fR specifies the formal arguments to
+\fIfunc\fR. The specification of the formal arguments \fIargs\fR
+is shared with the \fBproc\fR command, and is described in detail in the
+corresponding manual page.
+.PP
+The contents of \fIbody\fR are executed by the Tcl interpreter
+after the local variables corresponding to the formal arguments are given
+the values of the actual parameters \fIarg1 arg2 ...\fR.
+When \fIbody\fR is being executed, variable names normally refer to
+local variables, which are created automatically when referenced and
+deleted when \fBapply\fR returns. One local variable is automatically
+created for each of the function's arguments.
+Global variables can only be accessed by invoking
+the \fBglobal\fR command or the \fBupvar\fR command.
+Namespace variables can only be accessed by invoking
+the \fBvariable\fR command or the \fBupvar\fR command.
+.PP
+The invocation of \fBapply\fR adds a call frame to Tcl's evaluation stack
+(the stack of frames accessed via \fBuplevel\fR). The execution of \fIbody\fR
+proceeds in this call frame, in the namespace given by \fInamespace\fR or
+in the global namespace if none was specified. If given, \fInamespace\fR is
+interpreted relative to the global namespace even if its name does not start
+with
+.QW :: .
+.PP
+The semantics of \fBapply\fR can also be described by:
+.PP
+.CS
+proc apply {fun args} {
+ set len [llength $fun]
+ if {($len < 2) || ($len > 3)} {
+ error "can't interpret \e"$fun\e" as anonymous function"
+ }
+ lassign $fun argList body ns
+ set name ::$ns::[getGloballyUniqueName]
+ set body0 {
+ rename [lindex [info level 0] 0] {}
+ }
+ proc $name $argList ${body0}$body
+ set code [catch {uplevel 1 $name $args} res opt]
+ return -options $opt $res
+}
+.CE
+.SH EXAMPLES
+This shows how to make a simple general command that applies a transformation
+to each element of a list.
+.CS
+proc map {lambda list} {
+ set result {}
+ foreach item $list {
+ lappend result [\fBapply\fR $lambda $item]
+ }
+ return $result
+}
+map {x {return [string length $x]:$x}} {a bb ccc dddd}
+ \fI\(-> 1:a 2:bb 3:ccc 4:dddd\fR
+map {x {expr {$x**2 + 3*$x - 2}}} {-4 -3 -2 -1 0 1 2 3 4}
+ \fI\(-> 2 -2 -4 -4 -2 2 8 16 26\fR
+.CE
+.PP
+The \fBapply\fR command is also useful for defining callbacks for use in the
+\fBtrace\fR command:
+.CS
+set vbl "123abc"
+trace add variable vbl write {\fBapply\fR {{v1 v2 op} {
+ upvar 1 $v1 v
+ puts "updated variable to \e"$v\e""
+}}}
+set vbl 123
+set vbl abc
+.CE
+.SH "SEE ALSO"
+proc(n), uplevel(n)
+.SH KEYWORDS
+argument, procedure, anonymous function
diff --git a/doc/array.n b/doc/array.n
index 7713f8c..e112c23 100644
--- a/doc/array.n
+++ b/doc/array.n
@@ -14,7 +14,6 @@ array \- Manipulate array variables
.SH SYNOPSIS
\fBarray \fIoption arrayName\fR ?\fIarg arg ...\fR?
.BE
-
.SH DESCRIPTION
.PP
This command performs one of several operations on the
@@ -34,7 +33,7 @@ check, and must have been the return value from a previous
invocation of \fBarray startsearch\fR.
This option is particularly useful if an array has an element
with an empty name, since the return value from
-\fBarray nextelement\fR won't indicate whether the search
+\fBarray nextelement\fR will not indicate whether the search
has been completed.
.TP
\fBarray donesearch \fIarrayName searchId\fR
@@ -58,21 +57,24 @@ array are included in the result.
If \fIpattern\fR is specified, then only those elements whose names
match \fIpattern\fR (using the matching rules of
\fBstring match\fR) are included.
-If \fIarrayName\fR isn't the name of an array variable, or if
+If \fIarrayName\fR is not the name of an array variable, or if
the array contains no elements, then an empty list is returned.
+If traces on the array modify the list of elements, the elements
+returned are those that exist both before and after the call to
+\fBarray get\fR.
.TP
\fBarray names \fIarrayName\fR ?\fImode\fR? ?\fIpattern\fR?
Returns a list containing the names of all of the elements in
the array that match \fIpattern\fR. \fIMode\fR may be one of
-\fB-exact\fR, \fB-glob\fR, or \fB-regexp\fR. If specified, \fImode\fR
+\fB\-exact\fR, \fB\-glob\fR, or \fB\-regexp\fR. If specified, \fImode\fR
designates which matching rules to use to match \fIpattern\fR against
the names of the elements in the array. If not specified, \fImode\fR
-defaults to \fB-glob\fR. See the documentation for \fBstring match\fR
+defaults to \fB\-glob\fR. See the documentation for \fBstring match\fR
for information on glob style matching, and the documentation for
\fBregexp\fR for information on regexp matching.
If \fIpattern\fR is omitted then the command returns all of
the element names in the array. If there are no (matching) elements
-in the array, or if \fIarrayName\fR isn't the name of an array
+in the array, or if \fIarrayName\fR is not the name of an array
variable, then an empty string is returned.
.TP
\fBarray nextelement \fIarrayName searchId\fR
@@ -100,7 +102,7 @@ and \fIlist\fR is empty,
\fBarray size \fIarrayName\fR
Returns a decimal string giving the number of elements in the
array.
-If \fIarrayName\fR isn't the name of an array then 0 is returned.
+If \fIarrayName\fR is not the name of an array then 0 is returned.
.TP
\fBarray startsearch \fIarrayName\fR
This command initializes an element-by-element search through the
@@ -117,59 +119,55 @@ It is currently more efficient and easier to use either the \fBarray
get\fR or \fBarray names\fR, together with \fBforeach\fR, to iterate
over all but very large arrays. See the examples below for how to do
this.
-.VS 8.4
.TP
\fBarray statistics \fIarrayName\fR
Returns statistics about the distribution of data within the hashtable
that represents the array. This information includes the number of
entries in the table, the number of buckets, and the utilization of
the buckets.
-.VE 8.4
-.VS 8.3
.TP
\fBarray unset \fIarrayName\fR ?\fIpattern\fR?
Unsets all of the elements in the array that match \fIpattern\fR (using the
-matching rules of \fBstring match\fR). If \fIarrayName\fR isn't the name
+matching rules of \fBstring match\fR). If \fIarrayName\fR is not the name
of an array variable or there are no matching elements in the array, no
error will be raised. If \fIpattern\fR is omitted and \fIarrayName\fR is
an array variable, then the command unsets the entire array.
The command always returns an empty string.
-.VE 8.3
.SH EXAMPLES
.CS
\fBarray set\fR colorcount {
- red 1
- green 5
- blue 4
- white 9
+ red 1
+ green 5
+ blue 4
+ white 9
}
foreach {color count} [\fBarray get\fR colorcount] {
- puts "Color: $color Count: $count"
+ puts "Color: $color Count: $count"
}
- => Color: blue Count: 4
+ \fB\(->\fR Color: blue Count: 4
Color: white Count: 9
Color: green Count: 5
Color: red Count: 1
foreach color [\fBarray names\fR colorcount] {
- puts "Color: $color Count: $colorcount($color)"
+ puts "Color: $color Count: $colorcount($color)"
}
- => Color: blue Count: 4
+ \fB\(->\fR Color: blue Count: 4
Color: white Count: 9
Color: green Count: 5
Color: red Count: 1
-foreach color [lsort [array names colorcount]] {
- puts "Color: $color Count: $colorcount($color)"
+foreach color [lsort [\fBarray names\fR colorcount]] {
+ puts "Color: $color Count: $colorcount($color)"
}
- => Color: blue Count: 4
+ \fB\(->\fR Color: blue Count: 4
Color: green Count: 5
Color: red Count: 1
Color: white Count: 9
\fBarray statistics\fR colorcount
- => 4 entries in table, 4 buckets
+ \fB\(->\fR 4 entries in table, 4 buckets
number of buckets with 0 entries: 1
number of buckets with 1 entries: 2
number of buckets with 2 entries: 1
@@ -183,9 +181,7 @@ foreach color [lsort [array names colorcount]] {
number of buckets with 10 or more entries: 0
average search distance for entry: 1.2
.CE
-
.SH "SEE ALSO"
list(n), string(n), variable(n), trace(n), foreach(n)
-
.SH KEYWORDS
array, element names, search
diff --git a/doc/bgerror.n b/doc/bgerror.n
index 5b42766..cb91351 100644
--- a/doc/bgerror.n
+++ b/doc/bgerror.n
@@ -16,14 +16,27 @@ bgerror \- Command invoked to process background errors
.BE
.SH DESCRIPTION
+.VS 8.5
+Release 8.5 of Tcl supports the \fBinterp bgerror\fR command,
+which allows applications to register in an interpreter the command
+that will handle background errors in that interpreter. In older
+releases of Tcl, this level of control was not available, and applications
+could control the handling of background errors only by creating
+a command with the particular command name \fBbgerror\fR in the
+global namespace of an interpreter. The following documentation
+describes the interface requirements of the \fBbgerror\fR command
+an application might define to retain compatibility with pre-8.5
+releases of Tcl. Applications intending to support only
+Tcl releases 8.5 and later should simply make use of \fBinterp bgerror\fR.
+.VE 8.5
.PP
-The \fBbgerror\fR command doesn't exist as built-in part of Tcl. Instead,
+The \fBbgerror\fR command does not exist as built-in part of Tcl. Instead,
individual applications or users can define a \fBbgerror\fR
command (e.g. as a Tcl procedure) if they wish to handle background
errors.
.PP
A background error is one that occurs in an event handler or some
-other command that didn't originate with the application.
+other command that did not originate with the application.
For example, if an error occurs while executing a command specified
with the \fBafter\fR command, then it is a background error.
For a non-background error, the error can simply be returned up
@@ -34,8 +47,10 @@ unwinding ends in the Tcl library and there is no obvious way for Tcl
to report the error.
.PP
When Tcl detects a background error, it saves information about the
-error and invokes the \fBbgerror\fR command later as an idle event
-handler. Before invoking \fBbgerror\fR, Tcl restores the
+error and invokes a handler command registered by \fBinterp bgerror\fR
+later as an idle event handler. The default handler command in turn
+calls the \fBbgerror\fR command .
+Before invoking \fBbgerror\fR, Tcl restores the
\fBerrorInfo\fR and \fBerrorCode\fR variables to their values at the
time the error occurred, then it invokes \fBbgerror\fR with the error
message as its only argument. Tcl assumes that the application has
@@ -54,22 +69,6 @@ error, in the order they occurred. However, if \fBbgerror\fR returns
with a break exception, then any remaining errors are skipped without
calling \fBbgerror\fR.
.PP
-Tcl has no default implementation for \fBbgerror\fR. However, in
-applications using Tk there is a default \fBbgerror\fR procedure which
-posts a dialog box containing the error message and offers the user a
-chance to see a stack trace showing where the error occurred. In
-addition to allowing the user to view the stack trace, the dialog
-provides an additional application configurable button which may be
-used, for example, to save the stack trace to a file. By default,
-this is the behavior associated with that button. This behavior can
-be redefined by setting the option database values
-\fB*ErrorDialog.function.text\fR, to specify the caption for the
-function button, and \fB*ErrorDialog.function.command\fR, to specify
-the command to be run. The text of the stack trace is appended to the
-command when it is evaluated. If either of these options is set to
-the empty string, then the additional button will not be displayed in
-the dialog.
-.PP
If you are writing code that will be used by others as part of a
package or other kind of library, consider avoiding \fBbgerror\fR.
The reason for this is that the application programmer may also want
@@ -87,7 +86,7 @@ proc bgerror {message} {
.CE
.SH "SEE ALSO"
-after(n), tclvars(n)
+after(n), interp(n), tclvars(n)
.SH KEYWORDS
background error, reporting
diff --git a/doc/binary.n b/doc/binary.n
index fbe1a8c..6b2150e 100644
--- a/doc/binary.n
+++ b/doc/binary.n
@@ -15,17 +15,15 @@ binary \- Insert and extract fields from binary strings
.br
\fBbinary scan \fIstring formatString \fR?\fIvarName varName ...\fR?
.BE
-
.SH DESCRIPTION
.PP
This command provides facilities for manipulating binary data. The
first form, \fBbinary format\fR, creates a binary string from normal
-Tcl values. For example, given the values 16 and 22, on a 32 bit
+Tcl values. For example, given the values 16 and 22, on a 32-bit
architecture, it might produce an 8-byte binary string consisting of
two 4-byte integers, one for each of the numbers. The second form of
the command, \fBbinary scan\fR, does the opposite: it extracts data
from a binary string and returns it as ordinary Tcl string values.
-
.SH "BINARY FORMAT"
.PP
The \fBbinary format\fR command generates a binary string whose layout
@@ -34,7 +32,8 @@ the additional arguments. The resulting binary value is returned.
.PP
The \fIformatString\fR consists of a sequence of zero or more field
specifiers separated by zero or more spaces. Each field specifier is
-a single type character followed by an optional numeric \fIcount\fR.
+a single type character followed by an optional flag character followed
+by an optional numeric \fIcount\fR.
Most field specifiers consume one argument to obtain the value to be
formatted. The type character specifies how the value is to be
formatted. The \fIcount\fR typically indicates how many items of the
@@ -42,12 +41,13 @@ specified type are taken from the value. If present, the \fIcount\fR
is a non-negative decimal integer or \fB*\fR, which normally indicates
that all of the items in the value are to be used. If the number of
arguments does not match the number of fields in the format string
-that consume arguments, then an error is generated.
+that consume arguments, then an error is generated. The flag character
+is ignored for for \fBbinary format\fR.
.PP
Here is a small example to clarify the relation between the field
specifiers and the arguments:
.CS
-\fBbinary format d3d {1.0 2.0 3.0 4.0} 0.1\fR
+\fBbinary format\fR d3d {1.0 2.0 3.0 4.0} 0.1
.CE
.PP
The first argument is a list of four numbers, but because of the count
@@ -62,13 +62,14 @@ to just after the last byte stored. The cursor is initially at
position 0 at the beginning of the data. The type may be any one of
the following characters:
.IP \fBa\fR 5
-Stores a character string of length \fIcount\fR in the output string.
+Stores a byte string of length \fIcount\fR in the output string.
Every character is taken as modulo 256 (i.e. the low byte of every
character is used, and the high byte discarded) so when storing
-character strings not wholly expressible using the characters \\u0000-\\u00ff,
-the \fBencoding convertto\fR command should be used
-first if this truncation is not desired (i.e. if the characters are
-not part of the ISO 8859-1 character set.)
+character strings not wholly expressible using the characters \eu0000-\eu00ff,
+the \fBencoding convertto\fR command should be used first to change
+the string into an external representation
+if this truncation is not desired (i.e. if the characters are
+not part of the ISO 8859\-1 character set.)
If \fIarg\fR has fewer than \fIcount\fR bytes, then additional zero
bytes are used to pad out the field. If \fIarg\fR is longer than the
specified length, the extra characters will be ignored. If
@@ -77,16 +78,33 @@ formatted. If \fIcount\fR is omitted, then one character will be
formatted. For example,
.RS
.CS
-\fBbinary format a7a*a alpha bravo charlie\fR
+\fBbinary format\fR a7a*a alpha bravo charlie
.CE
-will return a string equivalent to \fBalpha\\000\\000bravoc\fR.
+will return a string equivalent to \fBalpha\e000\e000bravoc\fR,
+.CS
+\fBbinary format\fR a* [encoding convertto utf-8 \eu20ac]
+.CE
+will return a string equivalent to \fB\e342\e202\e254\fR (which is the
+UTF-8 byte sequence for a Euro-currency character) and
+.CS
+\fBbinary format\fR a* [encoding convertto iso8859-15 \eu20ac]
+.CE
+will return a string equivalent to \fB\e244\fR (which is the ISO
+8859\-15 byte sequence for a Euro-currency character). Contrast these
+last two with:
+.CS
+\fBbinary format\fR a* \eu20ac
+.CE
+which returns a string equivalent to \fB\e254\fR (i.e. \fB\exac\fR) by
+truncating the high-bits of the character, and which is probably not
+what is desired.
.RE
.IP \fBA\fR 5
This form is the same as \fBa\fR except that spaces are used for
padding instead of nulls. For example,
.RS
.CS
-\fBbinary format A6A*A alpha bravo charlie\fR
+\fBbinary format\fR A6A*A alpha bravo charlie
.CE
will return \fBalpha bravoc\fR.
.RE
@@ -105,25 +123,26 @@ does not end at a byte boundary, the remaining bits of the last byte
will be zeros. For example,
.RS
.CS
-\fBbinary format b5b* 11100 111000011010\fR
+\fBbinary format\fR b5b* 11100 111000011010
.CE
-will return a string equivalent to \fB\\x07\\x87\\x05\fR.
+will return a string equivalent to \fB\ex07\ex87\ex05\fR.
.RE
.IP \fBB\fR 5
This form is the same as \fBb\fR except that the bits are stored in
high-to-low order within each byte. For example,
.RS
.CS
-\fBbinary format B5B* 11100 111000011010\fR
+\fBbinary format\fR B5B* 11100 111000011010
.CE
-will return a string equivalent to \fB\\xe0\\xe1\\xa0\fR.
+will return a string equivalent to \fB\exe0\exe1\exa0\fR.
.RE
-.IP \fBh\fR 5
-Stores a string of \fIcount\fR hexadecimal digits in low-to-high
+.IP \fBH\fR 5
+Stores a string of \fIcount\fR hexadecimal digits in high-to-low
within each byte in the output string. \fIArg\fR must contain a
-sequence of characters in the set ``0123456789abcdefABCDEF''. The
-resulting bytes are emitted in first to last order with the hex digits
-being formatted in low-to-high order within each byte. If \fIarg\fR
+sequence of characters in the set
+.QW 0123456789abcdefABCDEF .
+The resulting bytes are emitted in first to last order with the hex digits
+being formatted in high-to-low order within each byte. If \fIarg\fR
has fewer than \fIcount\fR digits, then zeros will be used for the
remaining digits. If \fIarg\fR has more than the specified number of
digits, the extra digits will be ignored. If \fIcount\fR is
@@ -133,37 +152,36 @@ number of digits formatted does not end at a byte boundary, the
remaining bits of the last byte will be zeros. For example,
.RS
.CS
-\fBbinary format h3h* AB def\fR
+\fBbinary format\fR H3H*H2 ab DEF 987
.CE
-will return a string equivalent to \fB\\xba\\x00\\xed\\x0f\fR.
+will return a string equivalent to \fB\exab\ex00\exde\exf0\ex98\fR.
.RE
-.IP \fBH\fR 5
-This form is the same as \fBh\fR except that the digits are stored in
-high-to-low order within each byte. For example,
+.IP \fBh\fR 5
+This form is the same as \fBH\fR except that the digits are stored in
+low-to-high order within each byte. This is seldom required. For example,
.RS
.CS
-\fBbinary format H3H* ab DEF\fR
+\fBbinary format\fR h3h*h2 AB def 987
.CE
-will return a string equivalent to \fB\\xab\\x00\\xde\\xf0\fR.
+will return a string equivalent to \fB\exba\ex00\exed\ex0f\ex89\fR.
.RE
.IP \fBc\fR 5
Stores one or more 8-bit integer values in the output string. If no
\fIcount\fR is specified, then \fIarg\fR must consist of an integer
-value; otherwise \fIarg\fR must consist of a list containing at least
-\fIcount\fR integer elements. The low-order 8 bits of each integer
+value. If \fIcount\fR is specified, \fIarg\fR must consist of a list
+containing at least that many integers. The low-order 8 bits of each integer
are stored as a one-byte value at the cursor position. If \fIcount\fR
-is \fB*\fR, then all of the integers in the list are formatted. If
-the number of elements in the list is fewer than \fIcount\fR, then an
-error is generated. If the number of elements in the list is greater
+is \fB*\fR, then all of the integers in the list are formatted. If the
+number of elements in the list is greater
than \fIcount\fR, then the extra elements are ignored. For example,
.RS
.CS
-\fBbinary format c3cc* {3 -3 128 1} 260 {2 5}\fR
+\fBbinary format\fR c3cc* {3 -3 128 1} 260 {2 5}
.CE
will return a string equivalent to
-\fB\\x03\\xfd\\x80\\x04\\x02\\x05\fR, whereas
+\fB\ex03\exfd\ex80\ex04\ex02\ex05\fR, whereas
.CS
-\fBbinary format c {2 5}\fR
+\fBbinary format\fR c {2 5}
.CE
will generate an error.
.RE
@@ -175,10 +193,10 @@ the cursor position with the least significant byte stored first. For
example,
.RS
.CS
-\fBbinary format s3 {3 -3 258 1}\fR
+\fBbinary format\fR s3 {3 -3 258 1}
.CE
will return a string equivalent to
-\fB\\x03\\x00\\xfd\\xff\\x02\\x01\fR.
+\fB\ex03\ex00\exfd\exff\ex02\ex01\fR.
.RE
.IP \fBS\fR 5
This form is the same as \fBs\fR except that it stores one or more
@@ -186,11 +204,19 @@ This form is the same as \fBs\fR except that it stores one or more
example,
.RS
.CS
-\fBbinary format S3 {3 -3 258 1}\fR
+\fBbinary format\fR S3 {3 -3 258 1}
.CE
will return a string equivalent to
-\fB\\x00\\x03\\xff\\xfd\\x01\\x02\fR.
-.RE
+\fB\ex00\ex03\exff\exfd\ex01\ex02\fR.
+.RE
+.IP \fBt\fR 5
+.VS 8.5
+This form (mnemonically \fItiny\fR) is the same as \fBs\fR and \fBS\fR
+except that it stores the 16-bit integers in the output string in the
+native byte order of the machine where the Tcl script is running.
+To determine what the native byte order of the machine is, refer to
+the \fBbyteOrder\fR element of the \fBtcl_platform\fR array.
+.VE 8.5
.IP \fBi\fR 5
This form is the same as \fBc\fR except that it stores one or more
32-bit integers in little-endian byte order in the output string. The
@@ -199,10 +225,10 @@ the cursor position with the least significant byte stored first. For
example,
.RS
.CS
-\fBbinary format i3 {3 -3 65536 1}\fR
+\fBbinary format\fR i3 {3 -3 65536 1}
.CE
will return a string equivalent to
-\fB\\x03\\x00\\x00\\x00\\xfd\\xff\\xff\\xff\\x00\\x00\\x01\\x00\fR
+\fB\ex03\ex00\ex00\ex00\exfd\exff\exff\exff\ex00\ex00\ex01\ex00\fR
.RE
.IP \fBI\fR 5
This form is the same as \fBi\fR except that it stores one or more one
@@ -210,13 +236,21 @@ or more 32-bit integers in big-endian byte order in the output string.
For example,
.RS
.CS
-\fBbinary format I3 {3 -3 65536 1}\fR
+\fBbinary format\fR I3 {3 -3 65536 1}
.CE
will return a string equivalent to
-\fB\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xfd\\x00\\x01\\x00\\x00\fR
-.RE
+\fB\ex00\ex00\ex00\ex03\exff\exff\exff\exfd\ex00\ex01\ex00\ex00\fR
+.RE
+.IP \fBn\fR 5
+.VS 8.5
+This form (mnemonically \fInumber\fR or \fInormal\fR) is the same as
+\fBi\fR and \fBI\fR except that it stores the 32-bit integers in the
+output string in the native byte order of the machine where the Tcl
+script is running.
+To determine what the native byte order of the machine is, refer to
+the \fBbyteOrder\fR element of the \fBtcl_platform\fR array.
+.VE 8.5
.IP \fBw\fR 5
-.VS 8.4
This form is the same as \fBc\fR except that it stores one or more
64-bit integers in little-endian byte order in the output string. The
low-order 64-bits of each integer are stored as an eight-byte value at
@@ -224,7 +258,7 @@ the cursor position with the least significant byte stored first. For
example,
.RS
.CS
-\fBbinary format w 7810179016327718216\fR
+\fBbinary format\fR w 7810179016327718216
.CE
will return the string \fBHelloTcl\fR
.RE
@@ -234,14 +268,22 @@ or more 64-bit integers in big-endian byte order in the output string.
For example,
.RS
.CS
-\fBbinary format Wc 4785469626960341345 110\fR
+\fBbinary format\fR Wc 4785469626960341345 110
.CE
will return the string \fBBigEndian\fR
-.VE
.RE
+.IP \fBm\fR 5
+.VS 8.5
+This form (mnemonically the mirror of \fBw\fR) is the same as \fBw\fR
+and \fBW\fR except that it stores the 64-bit integers in the output
+string in the native byte order of the machine where the Tcl script is
+running.
+To determine what the native byte order of the machine is, refer to
+the \fBbyteOrder\fR element of the \fBtcl_platform\fR array.
+.VE 8.5
.IP \fBf\fR 5
This form is the same as \fBc\fR except that it stores one or more one
-or more single-precision floating in the machine's native
+or more single-precision floating point numbers in the machine's native
representation in the output string. This representation is not
portable across architectures, so it should not be used to communicate
floating point numbers across the network. The size of a floating
@@ -249,28 +291,54 @@ point number may vary across architectures, so the number of bytes
that are generated may vary. If the value overflows the
machine's native representation, then the value of FLT_MAX
as defined by the system will be used instead. Because Tcl uses
-double-precision floating-point numbers internally, there may be some
+double-precision floating point numbers internally, there may be some
loss of precision in the conversion to single-precision. For example,
on a Windows system running on an Intel Pentium processor,
.RS
.CS
-\fBbinary format f2 {1.6 3.4}\fR
+\fBbinary format\fR f2 {1.6 3.4}
.CE
will return a string equivalent to
-\fB\\xcd\\xcc\\xcc\\x3f\\x9a\\x99\\x59\\x40\fR.
-.RE
+\fB\excd\excc\excc\ex3f\ex9a\ex99\ex59\ex40\fR.
+.RE
+.IP \fBr\fR 5
+.VS 8.5
+This form (mnemonically \fIreal\fR) is the same as \fBf\fR except that
+it stores the single-precision floating point numbers in little-endian
+order. This conversion only produces meaningful output when used on
+machines which use the IEEE floating point representation (very
+common, but not universal.)
+.VE 8.5
+.IP \fBR\fR 5
+.VS 8.5
+This form is the same as \fBr\fR except that it stores the
+single-precision floating point numbers in big-endian order.
+.VE 8.5
.IP \fBd\fR 5
This form is the same as \fBf\fR except that it stores one or more one
-or more double-precision floating in the machine's native
+or more double-precision floating point numbers in the machine's native
representation in the output string. For example, on a
Windows system running on an Intel Pentium processor,
.RS
.CS
-\fBbinary format d1 {1.6}\fR
+\fBbinary format\fR d1 {1.6}
.CE
will return a string equivalent to
-\fB\\x9a\\x99\\x99\\x99\\x99\\x99\\xf9\\x3f\fR.
-.RE
+\fB\ex9a\ex99\ex99\ex99\ex99\ex99\exf9\ex3f\fR.
+.RE
+.IP \fBq\fR 5
+.VS 8.5
+This form (mnemonically the mirror of \fBd\fR) is the same as \fBd\fR
+except that it stores the double-precision floating point numbers in
+little-endian order. This conversion only produces meaningful output
+when used on machines which use the IEEE floating point representation
+(very common, but not universal.)
+.VE 8.5
+.IP \fBQ\fR 5
+.VS 8.5
+This form is the same as \fBq\fR except that it stores the
+double-precision floating point numbers in big-endian order.
+.VE 8.5
.IP \fBx\fR 5
Stores \fIcount\fR null bytes in the output string. If \fIcount\fR is
not specified, stores one null byte. If \fIcount\fR is \fB*\fR,
@@ -278,9 +346,9 @@ generates an error. This type does not consume an argument. For
example,
.RS
.CS
-\fBbinary format a3xa3x2a3 abc def ghi\fR
+\fBbinary format\fR a3xa3x2a3 abc def ghi
.CE
-will return a string equivalent to \fBabc\\000def\\000\\000ghi\fR.
+will return a string equivalent to \fBabc\e000def\e000\e000ghi\fR.
.RE
.IP \fBX\fR 5
Moves the cursor back \fIcount\fR bytes in the output string. If
@@ -291,7 +359,7 @@ omitted then the cursor is moved back one byte. This type does not
consume an argument. For example,
.RS
.CS
-\fBbinary format a3X*a3X2a3 abc def ghi\fR
+\fBbinary format\fR a3X*a3X2a3 abc def ghi
.CE
will return \fBdghi\fR.
.RE
@@ -306,16 +374,17 @@ the output string. If \fIcount\fR is omitted, then an error will be
generated. This type does not consume an argument. For example,
.RS
.CS
-\fBbinary format a5@2a1@*a3@10a1 abcde f ghi j\fR
+\fBbinary format\fR a5@2a1@*a3@10a1 abcde f ghi j
.CE
-will return \fBabfdeghi\\000\\000j\fR.
+will return \fBabfdeghi\e000\e000j\fR.
.RE
-
.SH "BINARY SCAN"
.PP
The \fBbinary scan\fR command parses fields from a binary string,
returning the number of conversions performed. \fIString\fR gives the
-input to be parsed and \fIformatString\fR indicates how to parse it.
+input bytes to be parsed (one byte per character, and characters not
+representable as a byte have their high bits chopped)
+and \fIformatString\fR indicates how to parse it.
Each \fIvarName\fR gives the name of a variable; when a field is
scanned from \fIstring\fR the result is assigned to the corresponding
variable.
@@ -323,7 +392,8 @@ variable.
As with \fBbinary format\fR, the \fIformatString\fR consists of a
sequence of zero or more field specifiers separated by zero or more
spaces. Each field specifier is a single type character followed by
-an optional numeric \fIcount\fR. Most field specifiers consume one
+an optional flag character followed by an optional numeric \fIcount\fR.
+Most field specifiers consume one
argument to obtain the variable into which the scanned values should
be placed. The type character specifies how the binary data is to be
interpreted. The \fIcount\fR typically indicates how many items of
@@ -335,13 +405,16 @@ position to satisfy the current field specifier, then the
corresponding variable is left untouched and \fBbinary scan\fR returns
immediately with the number of variables that were set. If there are
not enough arguments for all of the fields in the format string that
-consume arguments, then an error is generated.
+consume arguments, then an error is generated. The flag character
+.QW u
+may be given to cause some types to be read as unsigned values. The flag
+is accepted for all field types but is ignored for non-integer fields.
.PP
A similar example as with \fBbinary format\fR should explain the
relation between field specifiers and arguments in case of the binary
scan subcommand:
.CS
-\fBbinary scan $bytes s3s first second\fR
+\fBbinary scan\fR $bytes s3s first second
.CE
.PP
This command (provided the binary string in the variable \fIbytes\fR
@@ -352,31 +425,33 @@ integers), no assignment to \fIsecond\fR will be made, and if
\fIbytes\fR contains fewer than 6 bytes (i.e. three 2-byte integers),
no assignment to \fIfirst\fR will be made. Hence:
.CS
-\fBputs [binary scan abcdefg s3s first second]\fR
-\fBputs $first\fR
-\fBputs $second\fR
+puts [\fBbinary scan\fR abcdefg s3s first second]
+puts $first
+puts $second
.CE
will print (assuming neither variable is set previously):
.CS
-\fB1\fR
-\fB25185 25699 26213\fR
-\fIcan't read "second": no such variable\fR
+1
+25185 25699 26213
+can't read "second": no such variable
.CE
.PP
-It is \fBimportant\fR to note that the \fBc\fR, \fBs\fR, and \fBS\fR
+It is \fIimportant\fR to note that the \fBc\fR, \fBs\fR, and \fBS\fR
(and \fBi\fR and \fBI\fR on 64bit systems) will be scanned into
long data size values. In doing this, values that have their high
bit set (0x80 for chars, 0x8000 for shorts, 0x80000000 for ints),
will be sign extended. Thus the following will occur:
.CS
-\fBset signShort [binary format s1 0x8000]\fR
-\fBbinary scan $signShort s1 val; \fI# val == 0xFFFF8000\fR
+set signShort [\fBbinary format\fR s1 0x8000]
+\fBbinary scan\fR $signShort s1 val; \fI# val == 0xFFFF8000\fR
.CE
-If you want to produce an unsigned value, then you can mask the return
-value to the desired size. For example, to produce an unsigned short
-value:
+If you require unsigned values you can include the
+.QW u
+flag character following
+the field type. For example, to read an unsigned short value:
.CS
-\fBset val [expr {$val & 0xFFFF}]; \fI# val == 0x8000\fR
+set signShort [\fBbinary format\fR s1 0x8000]
+\fBbinary scan\fR $signShort su1 val; \fI# val == 0x00008000\fR
.CE
.PP
Each type-count pair moves an imaginary cursor through the binary data,
@@ -384,116 +459,128 @@ reading bytes from the current position. The cursor is initially
at position 0 at the beginning of the data. The type may be any one of
the following characters:
.IP \fBa\fR 5
-The data is a character string of length \fIcount\fR. If \fIcount\fR
+The data is a byte string of length \fIcount\fR. If \fIcount\fR
is \fB*\fR, then all of the remaining bytes in \fIstring\fR will be
scanned into the variable. If \fIcount\fR is omitted, then one
-character will be scanned.
-All characters scanned will be interpreted as being in the
-range \\u0000-\\u00ff so the \fBencoding convertfrom\fR command might be
-needed if the string is not an ISO 8859\-1 string.
+byte will be scanned.
+All bytes scanned will be interpreted as being characters in the
+range \eu0000-\eu00ff so the \fBencoding convertfrom\fR command will be
+needed if the string is not a binary string or a string encoded in ISO
+8859\-1.
For example,
.RS
.CS
-\fBbinary scan abcde\\000fghi a6a10 var1 var2\fR
+\fBbinary scan\fR abcde\e000fghi a6a10 var1 var2
+.CE
+will return \fB1\fR with the string equivalent to \fBabcde\e000\fR
+stored in \fIvar1\fR and \fIvar2\fR left unmodified, and
+.CS
+\fBbinary scan\fR \e342\e202\e254 a* var1
+set var2 [encoding convertfrom utf-8 $var1]
.CE
-will return \fB1\fR with the string equivalent to \fBabcde\\000\fR
-stored in \fBvar1\fR and \fBvar2\fR left unmodified.
+will store a Euro-currency character in \fIvar2\fR.
.RE
.IP \fBA\fR 5
This form is the same as \fBa\fR, except trailing blanks and nulls are stripped from
the scanned value before it is stored in the variable. For example,
.RS
.CS
-\fBbinary scan "abc efghi \\000" A* var1\fR
+\fBbinary scan\fR "abc efghi \e000" A* var1
.CE
-will return \fB1\fR with \fBabc efghi\fR stored in \fBvar1\fR.
+will return \fB1\fR with \fBabc efghi\fR stored in \fIvar1\fR.
.RE
.IP \fBb\fR 5
The data is turned into a string of \fIcount\fR binary digits in
-low-to-high order represented as a sequence of ``1'' and ``0''
+low-to-high order represented as a sequence of
+.QW 1
+and
+.QW 0
characters. The data bytes are scanned in first to last order with
the bits being taken in low-to-high order within each byte. Any extra
bits in the last byte are ignored. If \fIcount\fR is \fB*\fR, then
-all of the remaining bits in \fBstring\fR will be scanned. If
+all of the remaining bits in \fIstring\fR will be scanned. If
\fIcount\fR is omitted, then one bit will be scanned. For example,
.RS
.CS
-\fBbinary scan \\x07\\x87\\x05 b5b* var1 var2\fR
+\fBbinary scan\fR \ex07\ex87\ex05 b5b* var1 var2
.CE
-will return \fB2\fR with \fB11100\fR stored in \fBvar1\fR and
-\fB1110000110100000\fR stored in \fBvar2\fR.
+will return \fB2\fR with \fB11100\fR stored in \fIvar1\fR and
+\fB1110000110100000\fR stored in \fIvar2\fR.
.RE
.IP \fBB\fR 5
This form is the same as \fBb\fR, except the bits are taken in
high-to-low order within each byte. For example,
.RS
.CS
-\fBbinary scan \\x70\\x87\\x05 B5B* var1 var2\fR
+\fBbinary scan\fR \ex70\ex87\ex05 B5B* var1 var2
.CE
-will return \fB2\fR with \fB01110\fR stored in \fBvar1\fR and
-\fB1000011100000101\fR stored in \fBvar2\fR.
+will return \fB2\fR with \fB01110\fR stored in \fIvar1\fR and
+\fB1000011100000101\fR stored in \fIvar2\fR.
.RE
-.IP \fBh\fR 5
+.IP \fBH\fR 5
The data is turned into a string of \fIcount\fR hexadecimal digits in
-low-to-high order represented as a sequence of characters in the set
-``0123456789abcdef''. The data bytes are scanned in first to last
-order with the hex digits being taken in low-to-high order within each
-byte. Any extra bits in the last byte are ignored. If \fIcount\fR
-is \fB*\fR, then all of the remaining hex digits in \fBstring\fR will be
-scanned. If \fIcount\fR is omitted, then one hex digit will be
-scanned. For example,
+high-to-low order represented as a sequence of characters in the set
+.QW 0123456789abcdef .
+The data bytes are scanned in first to last
+order with the hex digits being taken in high-to-low order within each
+byte. Any extra bits in the last byte are ignored. If \fIcount\fR is
+\fB*\fR, then all of the remaining hex digits in \fIstring\fR will be
+scanned. If \fIcount\fR is omitted, then one hex digit will be
+scanned. For example,
.RS
.CS
-\fBbinary scan \\x07\\x86\\x05 h3h* var1 var2\fR
+\fBbinary scan\fR \ex07\exC6\ex05\ex1f\ex34 H3H* var1 var2
.CE
-will return \fB2\fR with \fB706\fR stored in \fBvar1\fR and
-\fB50\fR stored in \fBvar2\fR.
+will return \fB2\fR with \fB07c\fR stored in \fIvar1\fR and
+\fB051f34\fR stored in \fIvar2\fR.
.RE
-.IP \fBH\fR 5
-This form is the same as \fBh\fR, except the digits are taken in
-high-to-low order within each byte. For example,
+.IP \fBh\fR 5
+This form is the same as \fBH\fR, except the digits are taken in
+reverse (low-to-high) order within each byte. For example,
.RS
.CS
-\fBbinary scan \\x07\\x86\\x05 H3H* var1 var2\fR
+\fBbinary scan\fR \ex07\ex86\ex05\ex12\ex34 h3h* var1 var2
.CE
-will return \fB2\fR with \fB078\fR stored in \fBvar1\fR and
-\fB05\fR stored in \fBvar2\fR.
+will return \fB2\fR with \fB706\fR stored in \fIvar1\fR and
+\fB502143\fR stored in \fIvar2\fR.
.RE
+Note that most code that wishes to parse the hexadecimal digits from
+multiple bytes in order should use the \fBH\fR format.
.IP \fBc\fR 5
The data is turned into \fIcount\fR 8-bit signed integers and stored
in the corresponding variable as a list. If \fIcount\fR is \fB*\fR,
-then all of the remaining bytes in \fBstring\fR will be scanned. If
+then all of the remaining bytes in \fIstring\fR will be scanned. If
\fIcount\fR is omitted, then one 8-bit integer will be scanned. For
example,
.RS
.CS
-\fBbinary scan \\x07\\x86\\x05 c2c* var1 var2\fR
+\fBbinary scan\fR \ex07\ex86\ex05 c2c* var1 var2
.CE
-will return \fB2\fR with \fB7 -122\fR stored in \fBvar1\fR and \fB5\fR
-stored in \fBvar2\fR. Note that the integers returned are signed, but
+will return \fB2\fR with \fB7 -122\fR stored in \fIvar1\fR and \fB5\fR
+stored in \fIvar2\fR. Note that the integers returned are signed, but
they can be converted to unsigned 8-bit quantities using an expression
like:
.CS
-\fBexpr { $num & 0xff }\fR
+set num [expr { $num & 0xff }]
.CE
.RE
.IP \fBs\fR 5
The data is interpreted as \fIcount\fR 16-bit signed integers
represented in little-endian byte order. The integers are stored in
the corresponding variable as a list. If \fIcount\fR is \fB*\fR, then
-all of the remaining bytes in \fBstring\fR will be scanned. If
+all of the remaining bytes in \fIstring\fR will be scanned. If
\fIcount\fR is omitted, then one 16-bit integer will be scanned. For
example,
.RS
.CS
-\fBbinary scan \\x05\\x00\\x07\\x00\\xf0\\xff s2s* var1 var2\fR
+\fBbinary scan\fR \ex05\ex00\ex07\ex00\exf0\exff s2s* var1 var2
.CE
-will return \fB2\fR with \fB5 7\fR stored in \fBvar1\fR and \fB-16\fR
-stored in \fBvar2\fR. Note that the integers returned are signed, but
+will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR
+stored in \fIvar2\fR. Note that the integers returned are signed, but
they can be converted to unsigned 16-bit quantities using an expression
like:
.CS
-\fBexpr { $num & 0xffff }\fR
+set num [expr { $num & 0xffff }]
.CE
.RE
.IP \fBS\fR 5
@@ -502,28 +589,37 @@ as \fIcount\fR 16-bit signed integers represented in big-endian byte
order. For example,
.RS
.CS
-\fBbinary scan \\x00\\x05\\x00\\x07\\xff\\xf0 S2S* var1 var2\fR
+\fBbinary scan\fR \ex00\ex05\ex00\ex07\exff\exf0 S2S* var1 var2
.CE
-will return \fB2\fR with \fB5 7\fR stored in \fBvar1\fR and \fB-16\fR
-stored in \fBvar2\fR.
+will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR
+stored in \fIvar2\fR.
.RE
+.IP \fBt\fR 5
+.VS 8.5
+The data is interpreted as \fIcount\fR 16-bit signed integers
+represented in the native byte order of the machine running the Tcl
+script. It is otherwise identical to \fBs\fR and \fBS\fR.
+To determine what the native byte order of the machine is, refer to
+the \fBbyteOrder\fR element of the \fBtcl_platform\fR array.
+.VE 8.5
.IP \fBi\fR 5
The data is interpreted as \fIcount\fR 32-bit signed integers
represented in little-endian byte order. The integers are stored in
the corresponding variable as a list. If \fIcount\fR is \fB*\fR, then
-all of the remaining bytes in \fBstring\fR will be scanned. If
+all of the remaining bytes in \fIstring\fR will be scanned. If
\fIcount\fR is omitted, then one 32-bit integer will be scanned. For
example,
.RS
.CS
-\fBbinary scan \\x05\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\xf0\\xff\\xff\\xff i2i* var1 var2\fR
+set str \ex05\ex00\ex00\ex00\ex07\ex00\ex00\ex00\exf0\exff\exff\exff
+\fBbinary scan\fR $str i2i* var1 var2
.CE
-will return \fB2\fR with \fB5 7\fR stored in \fBvar1\fR and \fB-16\fR
-stored in \fBvar2\fR. Note that the integers returned are signed, but
+will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR
+stored in \fIvar2\fR. Note that the integers returned are signed, but
they can be converted to unsigned 32-bit quantities using an expression
like:
.CS
-\fBexpr { $num & 0xffffffff }\fR
+set num [expr { $num & 0xffffffff }]
.CE
.RE
.IP \fBI\fR 5
@@ -532,25 +628,34 @@ as \fIcount\fR 32-bit signed integers represented in big-endian byte
order. For example,
.RS
.CS
-\fBbinary scan \\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x07\\xff\\xff\\xff\\xf0 I2I* var1 var2\fR
+set str \ex00\ex00\ex00\ex05\ex00\ex00\ex00\ex07\exff\exff\exff\exf0
+\fBbinary scan\fR $str I2I* var1 var2
.CE
-will return \fB2\fR with \fB5 7\fR stored in \fBvar1\fR and \fB-16\fR
-stored in \fBvar2\fR.
+will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR
+stored in \fIvar2\fR.
.RE
+.IP \fBn\fR 5
+.VS 8.5
+The data is interpreted as \fIcount\fR 32-bit signed integers
+represented in the native byte order of the machine running the Tcl
+script. It is otherwise identical to \fBi\fR and \fBI\fR.
+To determine what the native byte order of the machine is, refer to
+the \fBbyteOrder\fR element of the \fBtcl_platform\fR array.
+.VE 8.5
.IP \fBw\fR 5
-.VS 8.4
The data is interpreted as \fIcount\fR 64-bit signed integers
represented in little-endian byte order. The integers are stored in
the corresponding variable as a list. If \fIcount\fR is \fB*\fR, then
-all of the remaining bytes in \fBstring\fR will be scanned. If
+all of the remaining bytes in \fIstring\fR will be scanned. If
\fIcount\fR is omitted, then one 64-bit integer will be scanned. For
example,
.RS
.CS
-\fBbinary scan \\x05\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\xf0\\xff\\xff\\xff wi* var1 var2\fR
+set str \ex05\ex00\ex00\ex00\ex07\ex00\ex00\ex00\exf0\exff\exff\exff
+\fBbinary scan\fR $str wi* var1 var2
.CE
-will return \fB2\fR with \fB30064771077\fR stored in \fBvar1\fR and
-\fB-16\fR stored in \fBvar2\fR. Note that the integers returned are
+will return \fB2\fR with \fB30064771077\fR stored in \fIvar1\fR and
+\fB\-16\fR stored in \fIvar2\fR. Note that the integers returned are
signed and cannot be represented by Tcl as unsigned values.
.RE
.IP \fBW\fR 5
@@ -559,18 +664,26 @@ as \fIcount\fR 64-bit signed integers represented in big-endian byte
order. For example,
.RS
.CS
-\fBbinary scan \\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x07\\xff\\xff\\xff\\xf0 WI* var1 var2\fR
+set str \ex00\ex00\ex00\ex05\ex00\ex00\ex00\ex07\exff\exff\exff\exf0
+\fBbinary scan\fR $str WI* var1 var2
.CE
-will return \fB2\fR with \fB21474836487\fR stored in \fBvar1\fR and \fB-16\fR
-stored in \fBvar2\fR.
-.VE
+will return \fB2\fR with \fB21474836487\fR stored in \fIvar1\fR and \fB\-16\fR
+stored in \fIvar2\fR.
.RE
+.IP \fBm\fR 5
+.VS 8.5
+The data is interpreted as \fIcount\fR 64-bit signed integers
+represented in the native byte order of the machine running the Tcl
+script. It is otherwise identical to \fBw\fR and \fBW\fR.
+To determine what the native byte order of the machine is, refer to
+the \fBbyteOrder\fR element of the \fBtcl_platform\fR array.
+.VE 8.5
.IP \fBf\fR 5
The data is interpreted as \fIcount\fR single-precision floating point
numbers in the machine's native representation. The floating point
numbers are stored in the corresponding variable as a list. If
\fIcount\fR is \fB*\fR, then all of the remaining bytes in
-\fBstring\fR will be scanned. If \fIcount\fR is omitted, then one
+\fIstring\fR will be scanned. If \fIcount\fR is omitted, then one
single-precision floating point number will be scanned. The size of a
floating point number may vary across architectures, so the number of
bytes that are scanned may vary. If the data does not represent a
@@ -579,11 +692,25 @@ compiler dependent. For example, on a Windows system running on an
Intel Pentium processor,
.RS
.CS
-\fBbinary scan \\x3f\\xcc\\xcc\\xcd f var1\fR
+\fBbinary scan\fR \ex3f\excc\excc\excd f var1
.CE
will return \fB1\fR with \fB1.6000000238418579\fR stored in
-\fBvar1\fR.
+\fIvar1\fR.
.RE
+.IP \fBr\fR 5
+.VS 8.5
+This form is the same as \fBf\fR except that the data is interpreted
+as \fIcount\fR single-precision floating point number in little-endian
+order. This conversion is not portable to the minority of systems not
+using IEEE floating point representations.
+.VE 8.5
+.IP \fBR\fR 5
+.VS 8.5
+This form is the same as \fBf\fR except that the data is interpreted
+as \fIcount\fR single-precision floating point number in big-endian
+order. This conversion is not portable to the minority of systems not
+using IEEE floating point representations.
+.VE 8.5
.IP \fBd\fR 5
This form is the same as \fBf\fR except that the data is interpreted
as \fIcount\fR double-precision floating point numbers in the
@@ -591,23 +718,37 @@ machine's native representation. For example, on a Windows system
running on an Intel Pentium processor,
.RS
.CS
-\fBbinary scan \\x9a\\x99\\x99\\x99\\x99\\x99\\xf9\\x3f d var1\fR
+\fBbinary scan\fR \ex9a\ex99\ex99\ex99\ex99\ex99\exf9\ex3f d var1
.CE
will return \fB1\fR with \fB1.6000000000000001\fR
-stored in \fBvar1\fR.
-.RE
+stored in \fIvar1\fR.
+.RE
+.IP \fBq\fR 5
+.VS 8.5
+This form is the same as \fBd\fR except that the data is interpreted
+as \fIcount\fR double-precision floating point number in little-endian
+order. This conversion is not portable to the minority of systems not
+using IEEE floating point representations.
+.VE 8.5
+.IP \fBQ\fR 5
+.VS 8.5
+This form is the same as \fBd\fR except that the data is interpreted
+as \fIcount\fR double-precision floating point number in big-endian
+order. This conversion is not portable to the minority of systems not
+using IEEE floating point representations.
+.VE 8.5
.IP \fBx\fR 5
Moves the cursor forward \fIcount\fR bytes in \fIstring\fR. If
\fIcount\fR is \fB*\fR or is larger than the number of bytes after the
-current cursor cursor position, then the cursor is positioned after
+current cursor position, then the cursor is positioned after
the last byte in \fIstring\fR. If \fIcount\fR is omitted, then the
cursor is moved forward one byte. Note that this type does not
consume an argument. For example,
.RS
.CS
-\fBbinary scan \\x01\\x02\\x03\\x04 x2H* var1\fR
+\fBbinary scan\fR \ex01\ex02\ex03\ex04 x2H* var1
.CE
-will return \fB1\fR with \fB0304\fR stored in \fBvar1\fR.
+will return \fB1\fR with \fB0304\fR stored in \fIvar1\fR.
.RE
.IP \fBX\fR 5
Moves the cursor back \fIcount\fR bytes in \fIstring\fR. If
@@ -618,10 +759,10 @@ is omitted then the cursor is moved back one byte. Note that this
type does not consume an argument. For example,
.RS
.CS
-\fBbinary scan \\x01\\x02\\x03\\x04 c2XH* var1 var2\fR
+\fBbinary scan\fR \ex01\ex02\ex03\ex04 c2XH* var1 var2
.CE
-will return \fB2\fR with \fB1 2\fR stored in \fBvar1\fR and \fB020304\fR
-stored in \fBvar2\fR.
+will return \fB2\fR with \fB1 2\fR stored in \fIvar1\fR and \fB020304\fR
+stored in \fIvar2\fR.
.RE
.IP \fB@\fR 5
Moves the cursor to the absolute location in the data string specified
@@ -631,21 +772,23 @@ by \fIcount\fR. Note that position 0 refers to the first byte in
\fIcount\fR is omitted, then an error will be generated. For example,
.RS
.CS
-\fBbinary scan \\x01\\x02\\x03\\x04 c2@1H* var1 var2\fR
+\fBbinary scan\fR \ex01\ex02\ex03\ex04 c2@1H* var1 var2
.CE
-will return \fB2\fR with \fB1 2\fR stored in \fBvar1\fR and \fB020304\fR
-stored in \fBvar2\fR.
+will return \fB2\fR with \fB1 2\fR stored in \fIvar1\fR and \fB020304\fR
+stored in \fIvar2\fR.
.RE
-.SH "PLATFORM ISSUES"
-Sometimes it is desirable to format or scan integer values in the
-native byte order for the machine. Refer to the \fBbyteOrder\fR
-element of the \fBtcl_platform\fR array to decide which type character
-to use when formatting or scanning integers.
+.SH "PORTABILITY ISSUES"
+The \fBr\fR, \fBR\fR, \fBq\fR and \fBQ\fR conversions will only work
+reliably for transferring data between computers which are all using
+IEEE floating point representations. This is very common, but not
+universal. To transfer floating-point numbers portably between all
+architectures, use their textual representation (as produced by
+\fBformat\fR) instead.
.SH EXAMPLES
This is a procedure to write a Tcl string to a binary-encoded channel as
UTF-8 data preceded by a length word:
.CS
-proc writeString {channel string} {
+proc \fIwriteString\fR {channel string} {
set data [encoding convertto utf-8 $string]
puts -nonewline [\fBbinary format\fR Ia* \e
[string length $data] $data]
@@ -653,9 +796,9 @@ proc writeString {channel string} {
.CE
.PP
This procedure reads a string from a channel that was written by the
-previously presented \fBwriteString\fR procedure:
+previously presented \fIwriteString\fR procedure:
.CS
-proc readString {channel} {
+proc \fIreadString\fR {channel} {
if {![\fBbinary scan\fR [read $channel 4] I length]} {
error "missing length"
}
@@ -663,9 +806,7 @@ proc readString {channel} {
return [encoding convertfrom utf-8 $data]
}
.CE
-
.SH "SEE ALSO"
format(n), scan(n), tclvars(n)
-
.SH KEYWORDS
binary, format, scan
diff --git a/doc/catch.n b/doc/catch.n
index f2d5533..0e2ec04 100644
--- a/doc/catch.n
+++ b/doc/catch.n
@@ -1,18 +1,19 @@
'\"
'\" Copyright (c) 1993-1994 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
+'\" Contributions from Don Porter, NIST, 2003. (not subject to US copyright)
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
-.TH catch n "8.0" Tcl "Tcl Built-In Commands"
+.TH catch n "8.5" Tcl "Tcl Built-In Commands"
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
catch \- Evaluate script and trap exceptional returns
.SH SYNOPSIS
-\fBcatch\fI script \fR?\fIvarName\fR?
+\fBcatch\fI script \fR?\fIresultVarName\fR? ?\fIoptionsVarName\fR?
.BE
.SH DESCRIPTION
@@ -35,44 +36,61 @@ new commands that return other integer values as return codes as well,
and scripts that make use of the \fBreturn -code\fR command can also
have return codes other than the five defined by Tcl.
.PP
-If the \fIvarName\fR argument is given, then the variable it names is
+If the \fIresultVarName\fR argument is given, then the variable it names is
set to the result of the script evaluation. When the return code from
-the script is 1 (\fBTCL_ERROR\fR), the value stored in \fIvarName\fR is an error
+the script is 1 (\fBTCL_ERROR\fR), the value stored in \fIresultVarName\fR is an error
message. When the return code from the script is 0 (\fBTCL_OK\fR), the value
stored in \fIresultVarName\fR is the value returned from \fIscript\fR.
.PP
-If \fIscript\fR does not raise an error, \fBcatch\fR will return 0
-(\fBTCL_OK\fR) and set the variable to the value returned from \fIscript\fR.
+.VS 8.5
+If the \fIoptionsVarName\fR argument is given, then the variable it
+names is set to a dictionary of return options returned by evaluation
+of \fIscript\fR. Tcl specifies two entries that are always
+defined in the dictionary: \fB\-code\fR and \fB\-level\fR. When
+the return code from evaluation of \fIscript\fR is not \fBTCL_RETURN\fR,
+the value of the \fB\-level\fR entry will be 0, and the value
+of the \fB\-code\fR entry will be the same as the return code.
+Only when the return code is \fBTCL_RETURN\fR will the values of
+the \fB\-level\fR and \fB\-code\fR entries be something else, as
+further described in the documentation for the \fBreturn\fR command.
.PP
-Note that \fBcatch\fR catches all exceptions, including those
-generated by \fBbreak\fR and \fBcontinue\fR as well as errors. The
-only errors that are not caught are syntax errors found when the
-script is compiled. This is because the catch command only catches
-errors during runtime. When the catch statement is compiled, the
-script is compiled as well and any syntax errors will generate a Tcl
-error.
-
+When the return code from evaluation of \fIscript\fR is \fBTCL_ERROR\fR,
+three additional entries are defined in the dictionary of return options
+stored in \fIoptionsVarName\fR: \fB\-errorinfo\fR, \fB\-errorcode\fR,
+and \fB\-errorline\fR. The value of the \fB\-errorinfo\fR entry
+is a formatted stack trace containing more information about
+the context in which the error happened. The formatted stack
+trace is meant to be read by a person. The value of
+the \fB\-errorcode\fR entry is additional information about the
+error stored as a list. The \fB\-errorcode\fR value is meant to
+be further processed by programs, and may not be particularly
+readable by people. The value of the \fB\-errorline\fR entry
+is an integer indicating which line of \fIscript\fR was being
+evaluated when the error occurred. The values of the \fB\-errorinfo\fR
+and \fB\-errorcode\fR entries of the most recent error are also
+available as values of the global variables \fB::errorInfo\fR
+and \fB::errorCode\fR respectively.
+.PP
+Tcl packages may provide commands that set other entries in the
+dictionary of return options, and the \fBreturn\fR command may be
+used by scripts to set return options in addition to those defined
+above.
+.VE 8.5
.SH EXAMPLES
The \fBcatch\fR command may be used in an \fBif\fR to branch based on
the success of a script.
.CS
if { [\fBcatch\fR {open $someFile w} fid] } {
- puts stderr "Could not open $someFile for writing\\n$fid"
+ puts stderr "Could not open $someFile for writing\en$fid"
exit 1
}
.CE
.PP
-The \fBcatch\fR command will not catch compiled syntax errors. The
-first time proc \fBfoo\fR is called, the body will be compiled and a
-Tcl error will be generated.
-.CS
-proc foo {} {
- \fBcatch\fR {expr {1 +- }}
-}
-.CE
+There are more complex examples of \fBcatch\fR usage in the
+documentation for the \fBreturn\fR command.
.SH "SEE ALSO"
-break(n), continue(n), error(n), return(n), tclvars(n)
+break(n), continue(n), dict(n), error(n), return(n), tclvars(n)
.SH KEYWORDS
catch, error
diff --git a/doc/chan.n b/doc/chan.n
new file mode 100644
index 0000000..f5d3d54
--- /dev/null
+++ b/doc/chan.n
@@ -0,0 +1,736 @@
+'\"
+'\" Copyright (c) 2005-2006 Donal K. Fellows
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+.so man.macros
+.TH chan n 8.5 Tcl "Tcl Built-In Commands"
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+chan \- Read, write and manipulate channels
+.SH SYNOPSIS
+\fBchan \fIoption\fR ?\fIarg arg ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+This command provides several operations for reading from, writing to
+and otherwise manipulating open channels (such as have been created
+with the \fBopen\fR and \fBsocket\fR commands, or the default named
+channels \fBstdin\fR, \fBstdout\fR or \fBstderr\fR which correspond to
+the process's standard input, output and error streams respectively).
+\fIOption\fR indicates what to do with the channel; any unique
+abbreviation for \fIoption\fR is acceptable. Valid options are:
+.TP
+\fBchan blocked \fIchannelId\fR
+.
+This tests whether the last input operation on the channel called
+\fIchannelId\fR failed because it would have otherwise caused the
+process to block, and returns 1 if that was the case. It returns 0
+otherwise. Note that this only ever returns 1 when the channel has
+been configured to be non-blocking; all Tcl channels have blocking
+turned on by default.
+.TP
+\fBchan close \fIchannelId\fR
+.
+Close and destroy the channel called \fIchannelId\fR. Note that this
+deletes all existing file-events registered on the channel.
+.RS
+.PP
+As part of closing the channel, all buffered output is flushed to the
+channel's output device, any buffered input is discarded, the
+underlying operating system resource is closed and \fIchannelId\fR
+becomes unavailable for future use.
+.PP
+If the channel is blocking, the command does not return until all
+output is flushed. If the channel is nonblocking and there is
+unflushed output, the channel remains open and the command returns
+immediately; output will be flushed in the background and the channel
+will be closed when all the flushing is complete.
+.PP
+If \fIchannelId\fR is a blocking channel for a command pipeline then
+\fBchan close\fR waits for the child processes to complete.
+.PP
+If the channel is shared between interpreters, then \fBchan close\fR
+makes \fIchannelId\fR unavailable in the invoking interpreter but has
+no other effect until all of the sharing interpreters have closed the
+channel. When the last interpreter in which the channel is registered
+invokes \fBchan close\fR (or \fBclose\fR), the cleanup actions
+described above occur. See the \fBinterp\fR command for a description
+of channel sharing.
+.PP
+Channels are automatically closed when an interpreter is destroyed and
+when the process exits. Channels are switched to blocking mode, to
+ensure that all output is correctly flushed before the process exits.
+.PP
+The command returns an empty string, and may generate an error if
+an error occurs while flushing output. If a command in a command
+pipeline created with \fBopen\fR returns an error, \fBchan close\fR
+generates an error (similar to the \fBexec\fR command.)
+.RE
+.TP
+\fBchan configure \fIchannelId\fR ?\fIoptionName\fR? ?\fIvalue\fR? ?\fIoptionName value\fR?...
+.
+Query or set the configuration options of the channel named
+\fIchannelId\fR.
+.RS
+.PP
+If no \fIoptionName\fR or \fIvalue\fR arguments are supplied, the
+command returns a list containing alternating option names and values
+for the channel. If \fIoptionName\fR is supplied but no \fIvalue\fR
+then the command returns the current value of the given option. If
+one or more pairs of \fIoptionName\fR and \fIvalue\fR are supplied,
+the command sets each of the named options to the corresponding
+\fIvalue\fR; in this case the return value is an empty string.
+.PP
+The options described below are supported for all channels. In
+addition, each channel type may add options that only it supports. See
+the manual entry for the command that creates each type of channels
+for the options that that specific type of channel supports. For
+example, see the manual entry for the \fBsocket\fR command for its
+additional options.
+.TP
+\fB\-blocking\fR \fIboolean\fR
+.
+The \fB\-blocking\fR option determines whether I/O operations on the
+channel can cause the process to block indefinitely. The value of the
+option must be a proper boolean value. Channels are normally in
+blocking mode; if a channel is placed into nonblocking mode it will
+affect the operation of the \fBchan gets\fR, \fBchan read\fR, \fBchan
+puts\fR, \fBchan flush\fR, and \fBchan close\fR commands; see the
+documentation for those commands for details. For nonblocking mode to
+work correctly, the application must be using the Tcl event loop
+(e.g. by calling \fBTcl_DoOneEvent\fR or invoking the \fBvwait\fR
+command).
+.TP
+\fB\-buffering\fR \fInewValue\fR
+.
+If \fInewValue\fR is \fBfull\fR then the I/O system will buffer output
+until its internal buffer is full or until the \fBchan flush\fR
+command is invoked. If \fInewValue\fR is \fBline\fR, then the I/O
+system will automatically flush output for the channel whenever a
+newline character is output. If \fInewValue\fR is \fBnone\fR, the I/O
+system will flush automatically after every output operation. The
+default is for \fB\-buffering\fR to be set to \fBfull\fR except for
+channels that connect to terminal-like devices; for these channels the
+initial setting is \fBline\fR. Additionally, \fBstdin\fR and
+\fBstdout\fR are initially set to \fBline\fR, and \fBstderr\fR is set
+to \fBnone\fR.
+.TP
+\fB\-buffersize\fR \fInewSize\fR
+.
+\fINewvalue\fR must be an integer; its value is used to set the size
+of buffers, in bytes, subsequently allocated for this channel to store
+input or output. \fINewvalue\fR must be a number of no more than one
+million, allowing buffers of up to one million bytes in size.
+.TP
+\fB\-encoding\fR \fIname\fR
+.
+This option is used to specify the encoding of the channel as one of
+the named encodings returned by \fBencoding names\fR or the special
+value \fBbinary\fR, so that the data can be converted to and from
+Unicode for use in Tcl. For instance, in order for Tcl to read
+characters from a Japanese file in \fBshiftjis\fR and properly process
+and display the contents, the encoding would be set to \fBshiftjis\fR.
+Thereafter, when reading from the channel, the bytes in the Japanese
+file would be converted to Unicode as they are read. Writing is also
+supported \- as Tcl strings are written to the channel they will
+automatically be converted to the specified encoding on output.
+.RS
+.PP
+If a file contains pure binary data (for instance, a JPEG image), the
+encoding for the channel should be configured to be \fBbinary\fR. Tcl
+will then assign no interpretation to the data in the file and simply
+read or write raw bytes. The Tcl \fBbinary\fR command can be used to
+manipulate this byte-oriented data. It is usually better to set the
+\fB\-translation\fR option to \fBbinary\fR when you want to transfer
+binary data, as this turns off the other automatic interpretations of
+the bytes in the stream as well.
+.PP
+The default encoding for newly opened channels is the same platform-
+and locale-dependent system encoding used for interfacing with the
+operating system, as returned by \fBencoding system\fR.
+.RE
+.TP
+\fB\-eofchar\fR \fIchar\fR
+.TP
+\fB\-eofchar\fR \fB{\fIinChar outChar\fB}\fR
+.
+This option supports DOS file systems that use Control-z (\ex1a) as an
+end of file marker. If \fIchar\fR is not an empty string, then this
+character signals end-of-file when it is encountered during input.
+For output, the end-of-file character is output when the channel is
+closed. If \fIchar\fR is the empty string, then there is no special
+end of file character marker. For read-write channels, a two-element
+list specifies the end of file marker for input and output,
+respectively. As a convenience, when setting the end-of-file
+character for a read-write channel you can specify a single value that
+will apply to both reading and writing. When querying the end-of-file
+character of a read-write channel, a two-element list will always be
+returned. The default value for \fB\-eofchar\fR is the empty string
+in all cases except for files under Windows. In that case the
+\fB\-eofchar\fR is Control-z (\ex1a) for reading and the empty string
+for writing.
+The acceptable range for \fB\-eofchar\fR values is \ex01 - \ex7f;
+attempting to set \fB\-eofchar\fR to a value outside of this range will
+generate an error.
+.TP
+\fB\-translation\fR \fImode\fR
+.TP
+\fB\-translation\fR \fB{\fIinMode outMode\fB}\fR
+.
+In Tcl scripts the end of a line is always represented using a single
+newline character (\en). However, in actual files and devices the end
+of a line may be represented differently on different platforms, or
+even for different devices on the same platform. For example, under
+UNIX newlines are used in files, whereas carriage-return-linefeed
+sequences are normally used in network connections. On input (i.e.,
+with \fBchan gets\fR and \fBchan read\fR) the Tcl I/O system
+automatically translates the external end-of-line representation into
+newline characters. Upon output (i.e., with \fBchan puts\fR), the I/O
+system translates newlines to the external end-of-line representation.
+The default translation mode, \fBauto\fR, handles all the common cases
+automatically, but the \fB\-translation\fR option provides explicit
+control over the end of line translations.
+.RS
+.PP
+The value associated with \fB\-translation\fR is a single item for
+read-only and write-only channels. The value is a two-element list for
+read-write channels; the read translation mode is the first element of
+the list, and the write translation mode is the second element. As a
+convenience, when setting the translation mode for a read-write channel
+you can specify a single value that will apply to both reading and
+writing. When querying the translation mode of a read-write channel, a
+two-element list will always be returned. The following values are
+currently supported:
+.TP
+\fBauto\fR
+.
+As the input translation mode, \fBauto\fR treats any of newline
+(\fBlf\fR), carriage return (\fBcr\fR), or carriage return followed by
+a newline (\fBcrlf\fR) as the end of line representation. The end of
+line representation can even change from line-to-line, and all cases
+are translated to a newline. As the output translation mode,
+\fBauto\fR chooses a platform specific representation; for sockets on
+all platforms Tcl chooses \fBcrlf\fR, for all Unix flavors, it chooses
+\fBlf\fR, and for the various flavors of Windows it chooses
+\fBcrlf\fR. The default setting for \fB\-translation\fR is \fBauto\fR
+for both input and output.
+.TP
+\fBbinary\fR
+.
+No end-of-line translations are performed. This is nearly identical
+to \fBlf\fR mode, except that in addition \fBbinary\fR mode also sets
+the end-of-file character to the empty string (which disables it) and
+sets the encoding to \fBbinary\fR (which disables encoding filtering).
+See the description of \fB\-eofchar\fR and \fB\-encoding\fR for more
+information.
+.TP
+\fBcr\fR
+.
+The end of a line in the underlying file or device is represented by a
+single carriage return character. As the input translation mode,
+\fBcr\fR mode converts carriage returns to newline characters. As the
+output translation mode, \fBcr\fR mode translates newline characters
+to carriage returns.
+.TP
+\fBcrlf\fR
+.
+The end of a line in the underlying file or device is represented by a
+carriage return character followed by a linefeed character. As the
+input translation mode, \fBcrlf\fR mode converts
+carriage-return-linefeed sequences to newline characters. As the
+output translation mode, \fBcrlf\fR mode translates newline characters
+to carriage-return-linefeed sequences. This mode is typically used on
+Windows platforms and for network connections.
+.TP
+\fBlf\fR
+.
+The end of a line in the underlying file or device is represented by a
+single newline (linefeed) character. In this mode no translations
+occur during either input or output. This mode is typically used on
+UNIX platforms.
+.RE
+.RE
+.TP
+\fBchan copy \fIinputChan outputChan\fR ?\fB\-size \fIsize\fR? ?\fB\-command \fIcallback\fR?
+.
+Copy data from the channel \fIinputChan\fR, which must have been
+opened for reading, to the channel \fIoutputChan\fR, which must have
+been opened for writing. The \fBchan copy\fR command leverages the
+buffering in the Tcl I/O system to avoid extra copies and to avoid
+buffering too much data in main memory when copying large files to
+slow destinations like network sockets.
+.RS
+.PP
+The \fBchan copy\fR command transfers data from \fIinputChan\fR until
+end of file or \fIsize\fR bytes have been transferred. If no
+\fB\-size\fR argument is given, then the copy goes until end of file.
+All the data read from \fIinputChan\fR is copied to \fIoutputChan\fR.
+Without the \fB\-command\fR option, \fBchan copy\fR blocks until the
+copy is complete and returns the number of bytes written to
+\fIoutputChan\fR.
+.PP
+The \fB\-command\fR argument makes \fBchan copy\fR work in the
+background. In this case it returns immediately and the
+\fIcallback\fR is invoked later when the copy completes. The
+\fIcallback\fR is called with one or two additional arguments that
+indicates how many bytes were written to \fIoutputChan\fR. If an
+error occurred during the background copy, the second argument is the
+error string associated with the error. With a background copy, it is
+not necessary to put \fIinputChan\fR or \fIoutputChan\fR into
+non-blocking mode; the \fBchan copy\fR command takes care of that
+automatically. However, it is necessary to enter the event loop by
+using the \fBvwait\fR command or by using Tk.
+.PP
+You are not allowed to do other I/O operations with \fIinputChan\fR or
+\fIoutputChan\fR during a background \fBchan copy\fR. If either
+\fIinputChan\fR or \fIoutputChan\fR get closed while the copy is in
+progress, the current copy is stopped and the command callback is
+\fInot\fR made. If \fIinputChan\fR is closed, then all data already
+queued for \fIoutputChan\fR is written out.
+.PP
+Note that \fIinputChan\fR can become readable during a background
+copy. You should turn off any \fBchan event\fR or \fBfileevent\fR
+handlers during a background copy so those handlers do not interfere
+with the copy. Any I/O attempted by a \fBchan event\fR or
+\fBfileevent\fR handler will get a
+.QW "channel busy"
+error.
+.PP
+\fBChan copy\fR translates end-of-line sequences in \fIinputChan\fR
+and \fIoutputChan\fR according to the \fB\-translation\fR option for
+these channels (see \fBchan configure\fR above). The translations
+mean that the number of bytes read from \fIinputChan\fR can be
+different than the number of bytes written to \fIoutputChan\fR. Only
+the number of bytes written to \fIoutputChan\fR is reported, either as
+the return value of a synchronous \fBchan copy\fR or as the argument
+to the callback for an asynchronous \fBchan copy\fR.
+.PP
+\fBChan copy\fR obeys the encodings and character translations
+configured for the channels. This means that the incoming characters
+are converted internally first UTF-8 and then into the encoding of the
+channel \fBchan copy\fR writes to (see \fBchan configure\fR above for
+details on the \fB\-encoding\fR and \fB\-translation\fR options). No
+conversion is done if both channels are set to encoding \fBbinary\fR
+and have matching translations. If only the output channel is set to
+encoding \fBbinary\fR the system will write the internal UTF-8
+representation of the incoming characters. If only the input channel
+is set to encoding \fBbinary\fR the system will assume that the
+incoming bytes are valid UTF-8 characters and convert them according
+to the output encoding. The behaviour of the system for bytes which
+are not valid UTF-8 characters is undefined in this case.
+.RE
+.TP
+\fBchan create \fImode cmdPrefix\fR
+.
+This subcommand creates a new script level channel using the command
+prefix \fIcmdPrefix\fR as its handler. Any such channel is called a
+\fBreflected\fR channel. The specified command prefix, \fBcmdPrefix\fR,
+must be a non-empty list, and should provide the API described in the
+\fBreflectedchan\fR manual page. The handle of the new channel is
+returned as the result of the \fBchan create\fR command, and the
+channel is open. Use either \fBclose\fR or \fBchan close\fR to remove
+the channel.
+.RS
+.PP
+The argument \fImode\fR specifies if the new channel is opened for
+reading, writing, or both. It has to be a list containing any of the
+strings
+.QW \fBread\fR
+or
+.QW \fBwrite\fR .
+The list must have at least one
+element, as a channel you can neither write to nor read from makes no
+sense. The handler command for the new channel must support the chosen
+mode, or an error is thrown.
+.PP
+The command prefix is executed in the global namespace, at the top of
+call stack, following the appending of arguments as described in the
+\fBreflectedchan\fR manual page. Command resolution happens at the
+time of the call. Renaming the command, or destroying it means that
+the next call of a handler method may fail, causing the channel
+command invoking the handler to fail as well. Depending on the
+subcommand being invoked, the error message may not be able to explain
+the reason for that failure.
+.PP
+Every channel created with this subcommand knows which interpreter it
+was created in, and only ever executes its handler command in that
+interpreter, even if the channel was shared with and/or was moved into
+a different interpreter. Each reflected channel also knows the thread
+it was created in, and executes its handler command only in that
+thread, even if the channel was moved into a different thread. To this
+end all invocations of the handler are forwarded to the original
+thread by posting special events to it. This means that the original
+thread (i.e. the thread that executed the \fBchan create\fR command)
+must have an active event loop, i.e. it must be able to process such
+events. Otherwise the thread sending them will \fIblock
+indefinitely\fR. Deadlock may occur.
+.PP
+Note that this permits the creation of a channel whose two endpoints
+live in two different threads, providing a stream-oriented bridge
+between these threads. In other words, we can provide a way for
+regular stream communication between threads instead of having to send
+commands.
+.PP
+When a thread or interpreter is deleted, all channels created with
+this subcommand and using this thread/interpreter as their computing
+base are deleted as well, in all interpreters they have been shared
+with or moved into, and in whatever thread they have been transfered
+to. While this pulls the rug out under the other thread(s) and/or
+interpreter(s), this cannot be avoided. Trying to use such a channel
+will cause the generation of a regular error about unknown channel
+handles.
+.PP
+This subcommand is \fBsafe\fR and made accessible to safe
+interpreters. While it arranges for the execution of arbitrary Tcl
+code the system also makes sure that the code is always executed
+within the safe interpreter.
+.RE
+.TP
+\fBchan eof \fIchannelId\fR
+.
+Test whether the last input operation on the channel called
+\fIchannelId\fR failed because the end of the data stream was reached,
+returning 1 if end-of-file was reached, and 0 otherwise.
+.TP
+\fBchan event \fIchannelId event\fR ?\fIscript\fR?
+.
+Arrange for the Tcl script \fIscript\fR to be installed as a \fIfile
+event handler\fR to be called whenever the channel called
+\fIchannelId\fR enters the state described by \fIevent\fR (which must
+be either \fBreadable\fR or \fBwritable\fR); only one such handler may
+be installed per event per channel at a time. If \fIscript\fR is the
+empty string, the current handler is deleted (this also happens if the
+channel is closed or the interpreter deleted). If \fIscript\fR is
+omitted, the currently installed script is returned (or an empty
+string if no such handler is installed). The callback is only
+performed if the event loop is being serviced (e.g. via \fBvwait\fR or
+\fBupdate\fR).
+.RS
+.PP
+A file event handler is a binding between a channel and a script, such
+that the script is evaluated whenever the channel becomes readable or
+writable. File event handlers are most commonly used to allow data to
+be received from another process on an event-driven basis, so that the
+receiver can continue to interact with the user or with other channels
+while waiting for the data to arrive. If an application invokes
+\fBchan gets\fR or \fBchan read\fR on a blocking channel when there is
+no input data available, the process will block; until the input data
+arrives, it will not be able to service other events, so it will
+appear to the user to
+.QW "freeze up" .
+With \fBchan event\fR, the
+process can tell when data is present and only invoke \fBchan gets\fR
+or \fBchan read\fR when they will not block.
+.PP
+A channel is considered to be readable if there is unread data
+available on the underlying device. A channel is also considered to
+be readable if there is unread data in an input buffer, except in the
+special case where the most recent attempt to read from the channel
+was a \fBchan gets\fR call that could not find a complete line in the
+input buffer. This feature allows a file to be read a line at a time
+in nonblocking mode using events. A channel is also considered to be
+readable if an end of file or error condition is present on the
+underlying file or device. It is important for \fIscript\fR to check
+for these conditions and handle them appropriately; for example, if
+there is no special check for end of file, an infinite loop may occur
+where \fIscript\fR reads no data, returns, and is immediately invoked
+again.
+.PP
+A channel is considered to be writable if at least one byte of data
+can be written to the underlying file or device without blocking, or
+if an error condition is present on the underlying file or device.
+Note that client sockets opened in asynchronous mode become writable
+when they become connected or if the connection fails.
+.PP
+Event-driven I/O works best for channels that have been placed into
+nonblocking mode with the \fBchan configure\fR command. In blocking
+mode, a \fBchan puts\fR command may block if you give it more data
+than the underlying file or device can accept, and a \fBchan gets\fR
+or \fBchan read\fR command will block if you attempt to read more data
+than is ready; no events will be processed while the commands block.
+In nonblocking mode \fBchan puts\fR, \fBchan read\fR, and \fBchan
+gets\fR never block.
+.PP
+The script for a file event is executed at global level (outside the
+context of any Tcl procedure) in the interpreter in which the \fBchan
+event\fR command was invoked. If an error occurs while executing the
+script then the command registered with \fBinterp bgerror\fR is used
+to report the error. In addition, the file event handler is deleted
+if it ever returns an error; this is done in order to prevent infinite
+loops due to buggy handlers.
+.RE
+.TP
+\fBchan flush \fIchannelId\fR
+.
+Ensures that all pending output for the channel called \fIchannelId\fR
+is written.
+.RS
+.PP
+If the channel is in blocking mode the command does not return until
+all the buffered output has been flushed to the channel. If the
+channel is in nonblocking mode, the command may return before all
+buffered output has been flushed; the remainder will be flushed in the
+background as fast as the underlying file or device is able to absorb
+it.
+.RE
+.TP
+\fBchan gets \fIchannelId\fR ?\fIvarName\fR?
+.
+Reads the next line from the channel called \fIchannelId\fR. If
+\fIvarName\fR is not specified, the result of the command will be the
+line that has been read (without a trailing newline character) or an
+empty string upon end-of-file or, in non-blocking mode, if the data
+available is exhausted. If \fIvarName\fR is specified, the line that
+has been read will be written to the variable called \fIvarName\fR and
+result will be the number of characters that have been read or -1 if
+end-of-file was reached or, in non-blocking mode, if the data
+available is exhausted.
+.RS
+.PP
+If an end-of-file occurs while part way through reading a line, the
+partial line will be returned (or written into \fIvarName\fR). When
+\fIvarName\fR is not specified, the end-of-file case can be
+distinguished from an empty line using the \fBchan eof\fR command, and
+the partial-line-but-nonblocking case can be distinguished with the
+\fBchan blocked\fR command.
+.RE
+.TP
+\fBchan names\fR ?\fIpattern\fR?
+.
+Produces a list of all channel names. If \fIpattern\fR is specified,
+only those channel names that match it (according to the rules of
+\fBstring match\fR) will be returned.
+.TP
+\fBchan pending \fImode channelId\fR
+.
+Depending on whether \fImode\fR is \fBinput\fR or \fBoutput\fR,
+returns the number of
+bytes of input or output (respectively) currently buffered
+internally for \fIchannelId\fR (especially useful in a readable event
+callback to impose application-specific limits on input line lengths to avoid
+a potential denial-of-service attack where a hostile user crafts
+an extremely long line that exceeds the available memory to buffer it).
+Returns -1 if the channel was not opened for the mode in question.
+.TP
+\fBchan postevent \fIchannelId eventSpec\fR
+.
+This subcommand is used by command handlers specified with \fBchan
+create\fR. It notifies the channel represented by the handle
+\fIchannelId\fR that the event(s) listed in the \fIeventSpec\fR have
+occurred. The argument has to be a list containing any of the strings
+\fBread\fR and \fBwrite\fR. The list must contain at least one
+element as it does not make sense to invoke the command if there are
+no events to post.
+.RS
+.PP
+Note that this subcommand can only be used with channel handles that
+were created/opened by \fBchan create\fR. All other channels will
+cause this subcommand to report an error.
+.PP
+As only the Tcl level of a channel, i.e. its command handler, should
+post events to it we also restrict the usage of this command to the
+interpreter that created the channel. In other words, posting events
+to a reflected channel from an interpreter that does not contain it's
+implementation is not allowed. Attempting to post an event from any
+other interpreter will cause this subcommand to report an error.
+.PP
+Another restriction is that it is not possible to post events that the
+I/O core has not registered an interest in. Trying to do so will cause
+the method to throw an error. See the command handler method
+\fBwatch\fR described in \fBreflectedchan\fR, the document specifying
+the API of command handlers for reflected channels.
+.PP
+This command is \fBsafe\fR and made accessible to safe interpreters.
+It can trigger the execution of \fBchan event\fR handlers, whether in the
+current interpreter or in other interpreters or other threads, even
+where the event is posted from a safe interpreter and listened for by
+a trusted interpreter. \fBChan event\fR handlers are \fIalways\fR
+executed in the interpreter that set them up.
+.RE
+.TP
+\fBchan puts\fR ?\fB\-nonewline\fR? ?\fIchannelId\fR? \fIstring\fR
+.
+Writes \fIstring\fR to the channel named \fIchannelId\fR followed by a
+newline character. A trailing newline character is written unless the
+optional flag \fB\-nonewline\fR is given. If \fIchannelId\fR is
+omitted, the string is written to the standard output channel,
+\fBstdout\fR.
+.RS
+.PP
+Newline characters in the output are translated by \fBchan puts\fR to
+platform-specific end-of-line sequences according to the currently
+configured value of the \fB\-translation\fR option for the channel
+(for example, on PCs newlines are normally replaced with
+carriage-return-linefeed sequences; see \fBchan configure\fR above for
+details).
+.PP
+Tcl buffers output internally, so characters written with \fBchan
+puts\fR may not appear immediately on the output file or device; Tcl
+will normally delay output until the buffer is full or the channel is
+closed. You can force output to appear immediately with the \fBchan
+flush\fR command.
+.PP
+When the output buffer fills up, the \fBchan puts\fR command will
+normally block until all the buffered data has been accepted for
+output by the operating system. If \fIchannelId\fR is in nonblocking
+mode then the \fBchan puts\fR command will not block even if the
+operating system cannot accept the data. Instead, Tcl continues to
+buffer the data and writes it in the background as fast as the
+underlying file or device can accept it. The application must use the
+Tcl event loop for nonblocking output to work; otherwise Tcl never
+finds out that the file or device is ready for more output data. It
+is possible for an arbitrarily large amount of data to be buffered for
+a channel in nonblocking mode, which could consume a large amount of
+memory. To avoid wasting memory, nonblocking I/O should normally be
+used in an event-driven fashion with the \fBchan event\fR command
+(do not invoke \fBchan puts\fR unless you have recently been notified
+via a file event that the channel is ready for more output data).
+.RE
+.TP
+\fBchan read \fIchannelId\fR ?\fInumChars\fR?
+.TP
+\fBchan read \fR?\fB\-nonewline\fR? \fIchannelId\fR
+.
+In the first form, the result will be the next \fInumChars\fR
+characters read from the channel named \fIchannelId\fR; if
+\fInumChars\fR is omitted, all characters up to the point when the
+channel would signal a failure (whether an end-of-file, blocked or
+other error condition) are read. In the second form (i.e. when
+\fInumChars\fR has been omitted) the flag \fB\-nonewline\fR may be
+given to indicate that any trailing newline in the string that has
+been read should be trimmed.
+.RS
+.PP
+If \fIchannelId\fR is in nonblocking mode, \fBchan read\fR may not
+read as many characters as requested: once all available input has
+been read, the command will return the data that is available rather
+than blocking for more input. If the channel is configured to use a
+multi-byte encoding, then there may actually be some bytes remaining
+in the internal buffers that do not form a complete character. These
+bytes will not be returned until a complete character is available or
+end-of-file is reached. The \fB\-nonewline\fR switch is ignored if
+the command returns before reaching the end of the file.
+.PP
+\fBChan read\fR translates end-of-line sequences in the input into
+newline characters according to the \fB\-translation\fR option for the
+channel (see \fBchan configure\fR above for a discussion on the ways
+in which \fBchan configure\fR will alter input).
+.PP
+When reading from a serial port, most applications should configure
+the serial port channel to be nonblocking, like this:
+.CS
+\fBchan configure \fIchannelId \fB\-blocking \fI0\fR.
+.CE
+Then \fBchan read\fR behaves much like described above. Note that
+most serial ports are comparatively slow; it is entirely possible to
+get a \fBreadable\fR event for each character read from them. Care
+must be taken when using \fBchan read\fR on blocking serial ports:
+.TP
+\fBchan read \fIchannelId numChars\fR
+.
+In this form \fBchan read\fR blocks until \fInumChars\fR have been
+received from the serial port.
+.TP
+\fBchan read \fIchannelId\fR
+.
+In this form \fBchan read\fR blocks until the reception of the
+end-of-file character, see \fBchan configure -eofchar\fR. If there no
+end-of-file character has been configured for the channel, then
+\fBchan read\fR will block forever.
+.RE
+.TP
+\fBchan seek \fIchannelId offset\fR ?\fIorigin\fR?
+.
+Sets the current access position within the underlying data stream for
+the channel named \fIchannelId\fR to be \fIoffset\fR bytes relative to
+\fIorigin\fR. \fIOffset\fR must be an integer (which may be negative)
+and \fIorigin\fR must be one of the following:
+.RS
+.TP 10
+\fBstart\fR
+.
+The new access position will be \fIoffset\fR bytes from the start
+of the underlying file or device.
+.TP 10
+\fBcurrent\fR
+.
+The new access position will be \fIoffset\fR bytes from the current
+access position; a negative \fIoffset\fR moves the access position
+backwards in the underlying file or device.
+.TP 10
+\fBend\fR
+.
+The new access position will be \fIoffset\fR bytes from the end of the
+file or device. A negative \fIoffset\fR places the access position
+before the end of file, and a positive \fIoffset\fR places the access
+position after the end of file.
+.PP
+The \fIorigin\fR argument defaults to \fBstart\fR.
+.PP
+\fBChan seek\fR flushes all buffered output for the channel before the
+command returns, even if the channel is in nonblocking mode. It also
+discards any buffered and unread input. This command returns an empty
+string. An error occurs if this command is applied to channels whose
+underlying file or device does not support seeking.
+.PP
+Note that \fIoffset\fR values are byte offsets, not character offsets.
+Both \fBchan seek\fR and \fBchan tell\fR operate in terms of bytes,
+not characters, unlike \fBchan read\fR.
+.RE
+.TP
+\fBchan tell \fIchannelId\fR
+.
+Returns a number giving the current access position within the
+underlying data stream for the channel named \fIchannelId\fR. This
+value returned is a byte offset that can be passed to \fBchan seek\fR
+in order to set the channel to a particular position. Note that this
+value is in terms of bytes, not characters like \fBchan read\fR. The
+value returned is -1 for channels that do not support seeking.
+.TP
+\fBchan truncate \fIchannelId\fR ?\fIlength\fR?
+.
+Sets the byte length of the underlying data stream for the channel
+named \fIchannelId\fR to be \fIlength\fR (or to the current byte
+offset within the underlying data stream if \fIlength\fR is
+omitted). The channel is flushed before truncation.
+.SH EXAMPLE
+This opens a file using a known encoding (CP1252, a very common encoding
+on Windows), searches for a string, rewrites that part, and truncates the
+file after a further two lines.
+.PP
+.CS
+set f [open somefile.txt r+]
+\fBchan configure\fR $f -encoding cp1252
+set offset 0
+
+\fI# Search for string "FOOBAR" in the file\fR
+while {[\fBchan gets\fR $f line] >= 0} {
+ set idx [string first FOOBAR $line]
+ if {$idx > -1} {
+ \fI# Found it; rewrite line\fR
+
+ \fBchan seek\fR $f [expr {$offset + $idx}]
+ \fBchan puts\fR -nonewline $f BARFOO
+
+ \fI# Skip to end of following line, and truncate\fR
+ \fBchan gets\fR $f
+ \fBchan gets\fR $f
+ \fBchan truncate\fR $f
+
+ \fI# Stop searching the file now\fR
+ break
+ }
+
+ \fI# Save offset of start of next line for later\fR
+ set offset [\fBchan tell\fR $f]
+}
+\fBchan close\fR $f
+.CE
+.SH "SEE ALSO"
+close(n), eof(n), fblocked(n), fconfigure(n), fcopy(n), file(n),
+fileevent(n), flush(n), gets(n), open(n), puts(n), read(n), seek(n),
+socket(n), tell(n), refchan(n)
+.SH KEYWORDS
+channel, input, output, events, offset
diff --git a/doc/clock.n b/doc/clock.n
index 8e00c43..600722b 100644
--- a/doc/clock.n
+++ b/doc/clock.n
@@ -1,259 +1,890 @@
'\"
-'\" Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
-'\" Copyright (c) 1995-1997 Sun Microsystems, Inc.
-'\" Copyright (c) 1998-1999 Scriptics Corporation
-'\" Copyright (c) 2002 ActiveState Corporation
+'\" Generated from file './doc/clock.dt' by tcllib/doctools with format 'nroff'
+'\" Copyright (c) 2004 Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
'\"
-'\" This documentation is derived from the time and date facilities of
-'\" TclX, by Mark Diekhans and Karl Lehenbauer.
-'\"
-'\" See the file "license.terms" for information on usage and redistribution
-'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-'\"
.so man.macros
-.TH clock n 8.4 Tcl "Tcl Built-In Commands"
+.TH "clock" n 8.5 Tcl "Tcl Built-In Commands"
.BS
-'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
-clock \- Obtain and manipulate time
-.SH SYNOPSIS
-\fBclock \fIoption\fR ?\fIarg arg ...\fR?
+clock \- Obtain and manipulate dates and times
+.SH "SYNOPSIS"
+package require \fBTcl 8.5\fR
+.sp
+\fBclock add\fR \fItimeVal\fR ?\fIcount unit...\fR? ?\fI\-option value\fR?
+.sp
+\fBclock clicks\fR ?\fI\-option\fR?
+.sp
+\fBclock format\fR \fItimeVal\fR ?\fI\-option value\fR...?
+.sp
+\fBclock microseconds\fR
+.sp
+\fBclock milliseconds\fR
+.sp
+\fBclock scan\fR \fIinputString\fR ?\fI\-option value\fR...?
+.sp
+\fBclock seconds\fR
+.sp
.BE
-
-.SH DESCRIPTION
-.PP
-This command performs one of several operations that may obtain
-or manipulate strings or values that represent some notion of
-time. The \fIoption\fR argument determines what action is carried
-out by the command. The legal \fIoptions\fR (which may be
-abbreviated) are:
-.VS 8.3
-.TP
-\fBclock clicks\fR ?\fB\-milliseconds\fR?
-Return a high-resolution time value as a system-dependent integer
-value. The unit of the value is system-dependent but should be the
-highest resolution clock available on the system such as a CPU cycle
-counter. If \fB\-milliseconds\fR is specified, then the value is
-guaranteed to be of millisecond granularity.
-This value should only be used for the relative measurement
-of elapsed time.
-.VE 8.3
-.TP
-\fBclock format \fIclockValue\fR ?\fB\-format \fIstring\fR? ?\fB\-gmt \fIboolean\fR?
-Converts an integer time value, typically returned by
-\fBclock seconds\fR, \fBclock scan\fR, or the \fBatime\fR or \fBmtime\fR
-options of the \fBfile\fR command, to human-readable
-form. If the \fB\-format\fR argument is present the next argument is a
-string that describes how the date and time are to be formatted.
-Field descriptors consist of a \fB%\fR followed by a field
-descriptor character. All other characters are copied into the result.
-Valid field descriptors are:
+.SH "DESCRIPTION"
+.PP
+The \fBclock\fR command performs several operations that obtain and
+manipulate values that represent times. The command supports several
+subcommands that determine what action is carried out by the command.
+.TP
+\fBclock add\fR \fItimeVal\fR ?\fIcount unit...\fR? ?\fI\-option value\fR?
+Adds a (possibly negative) offset to a time that is expressed as an
+integer number of seconds. See \fBCLOCK ARITHMETIC\fR for a full description.
+.TP
+\fBclock clicks\fR ?\fI\-option\fR?
+If no \fI\-option\fR argument is supplied, returns a high-resolution
+time value as a system-dependent integer value. The unit of the value
+is system-dependent but should be the highest resolution clock available
+on the system such as a CPU cycle counter. See \fBHIGH RESOLUTION TIMERS\fR for a full description.
.RS
-.IP \fB%%\fR
-Insert a %.
-.IP \fB%a\fR
-Abbreviated weekday name (Mon, Tue, etc.).
-.IP \fB%A\fR
-Full weekday name (Monday, Tuesday, etc.).
-.IP \fB%b\fR
-Abbreviated month name (Jan, Feb, etc.).
-.IP \fB%B\fR
-Full month name.
-.VS 8.4
-.IP \fB%c\fR
-Locale specific date and time. The format for date and time
-in the default "C" locale on Unix/Mac is "%a %b %d %H:%M:%S %Y".
-On Windows, this value is the locale specific long date and time, as
-specified in the Regional Options control panel settings.
-.IP \fB%C\fR
-First two digits of the four-digit year (19 or 20).
-.VE 8.4
-.IP \fB%d\fR
-Day of month (01 - 31).
-.VS 8.4
-'\" Since the inclusion of compat/strftime.c, %D, %e, %h should work on all
-'\" platforms.
-.IP \fB%D\fR
-Date as %m/%d/%y.
-.IP \fB%e\fR
-Day of month (1 - 31), no leading zeros.
-.IP \fB%g\fR
-The ISO8601 year number corresponding to the ISO8601 week (%V), expressed
-as a two-digit year-of-the-century, with leading zero if necessary.
-.IP \fB%G\fR
-The ISO8601 year number corresponding to the ISO8601 week (%V), expressed
-as a four-digit number.
-.IP \fB%h\fR
-Abbreviated month name.
-.VE 8.4
-.IP \fB%H\fR
-Hour in 24-hour format (00 - 23).
-.VS 8.4
-.IP \fB%I\fR
-Hour in 12-hour format (01 - 12).
-.VE 8.4
-.IP \fB%j\fR
-Day of year (001 - 366).
-.VS 8.4
-.IP \fB%k\fR
-Hour in 24-hour format, without leading zeros (0 - 23).
-.IP \fB%l\fR
-Hour in 12-hour format, without leading zeros (1 - 12).
-.VE 8.4
-.IP \fB%m\fR
-Month number (01 - 12).
-.IP \fB%M\fR
-Minute (00 - 59).
-.VS 8.4
-.IP \fB%n\fR
-Insert a newline.
-.VE 8.4
-.IP \fB%p\fR
-AM/PM indicator.
-.VS 8.4
-.IP \fB%r\fR
-Time in a locale-specific "meridian" format. The "meridian"
-format in the default "C" locale is "%I:%M:%S %p".
-.IP \fB%R\fR
-Time as %H:%M.
-.IP \fB%s\fR
-Count of seconds since the epoch, expressed as a decimal integer.
-.VE 8.4
-.IP \fB%S\fR
-Seconds (00 - 59).
-.VS 8.4
-.IP \fB%t\fR
-Insert a tab.
-.IP \fB%T\fR
-Time as %H:%M:%S.
-.IP \fB%u\fR
-Weekday number (Monday = 1, Sunday = 7).
-.VE 8.4
-.IP \fB%U\fR
-Week of year (00 - 52), Sunday is the first day of the week.
-.VS 8.4
-.IP \fB%V\fR
-Week of year according to ISO-8601 rules. Week 1 of a given
-year is the week containing 4 January.
-.IP \fB%w\fR
-Weekday number (Sunday = 0, Saturday = 6).
-.VE 8.4
-.IP \fB%W\fR
-Week of year (00 - 52), Monday is the first day of the week.
-.VS 8.4
-.IP \fB%x\fR
-Locale specific date format. The format for a date in the default "C"
-locale for Unix/Mac is "%m/%d/%y".
-On Windows, this value is the locale specific short date format, as
-specified in the Regional Options control panel settings.
-.IP \fB%X\fR
-Locale specific 24-hour time format. The format for a
-24-hour time in the default "C" locale for Unix/Mac is "%H:%M:%S".
-On Windows, this value is the locale specific time format, as
-specified in the Regional Options control panel settings.
-.VE 8.4
-.IP \fB%y\fR
-Year without century (00 - 99).
-.IP \fB%Y\fR
-Year with century (e.g. 1990)
-.IP \fB%Z\fR
-Time zone name.
+.PP
+If the \fI\-option\fR argument is \fI\-milliseconds\fR, then the command
+is synonymous with \fBclock milliseconds\fR (see below). This
+usage is obsolete, and \fBclock milliseconds\fR is to be
+considered the preferred way of obtaining a count of milliseconds.
+.PP
+If the \fI\-option\fR argument is \fI\-microseconds\fR, then the command
+is synonymous with \fBclock microseconds\fR (see below). This
+usage is obsolete, and \fBclock microseconds\fR is to be
+considered the preferred way of obtaining a count of microseconds.
.RE
-.VS 8.4
-.sp
-'\" All the field descriptors should be portable now that
-'\" compat/strftime.c is in place, with the possible exception
-'\" of the time zone name.
-'\".RS
-'\"In addition, the following field descriptors may be supported on some
-'\"systems (e.g. Unix but not Windows):
-'\".IP \fB%D\fR
-'\"Date as %m/%d/%y.
-'\".IP \fB%e\fR
-'\"Day of month (1 - 31), no leading zeros.
-'\".IP \fB%h\fR
-'\"Abbreviated month name.
-'\".IP \fB%n\fR
-'\"Insert a newline.
-'\".IP \fB%r\fR
-'\"Time as %I:%M:%S %p.
-'\".IP \fB%R\fR
-'\"Time as %H:%M.
-'\".IP \fB%t\fR
-'\"Insert a tab.
-'\".IP \fB%T\fR
-'\"Time as %H:%M:%S.
-'\".RE
-'\".sp
-.VE 8.4
+.TP
+\fBclock format\fR \fItimeVal\fR ?\fI\-option value\fR...?
+Formats a time that is expressed as an integer number of seconds into a format
+intended for consumption by users or external programs.
+See \fBFORMATTING TIMES\fR for a full description.
+.TP
+\fBclock microseconds\fR
+Returns the current time as an integer number of microseconds. See \fBHIGH RESOLUTION TIMERS\fR for a full description.
+.TP
+\fBclock milliseconds\fR
+Returns the current time as an integer number of milliseconds. See \fBHIGH RESOLUTION TIMERS\fR for a full description.
+.TP
+\fBclock scan\fR \fIinputString\fR ?\fI\-option value\fR...?
+Scans a time that is expressed as a character string and produces an
+integer number of seconds.
+See \fBSCANNING TIMES\fR for a full description.
+.TP
+\fBclock seconds\fR
+Returns the current time as an integer number of seconds.
+.SS "PARAMETERS"
+.TP
+\fIcount\fR
+An integer representing a count of some unit of time. See
+\fBCLOCK ARITHMETIC\fR for the details.
+.TP
+\fItimeVal\fR
+An integer value passed to the \fBclock\fR command that represents an
+absolute time as a number of seconds from the \fIepoch time\fR of
+1 January 1970, 00:00 UTC. Note that the count of seconds does not
+include any leap seconds; seconds are counted as if each UTC day has
+exactly 86400 seconds. Tcl responds to leap seconds by speeding or
+slowing its clock by a tiny fraction for some minutes until it is
+back in sync with UTC; its data model does not represent minutes that
+have 59 or 61 seconds.
+.TP
+\fIunit\fR
+One of the words, \fBseconds\fR, \fBminutes\fR, \fBhours\fR,
+\fBdays\fR, \fBweeks\fR, \fBmonths\fR, or \fByears\fR, or
+any unique prefix of such a word. Used in conjunction with \fIcount\fR
+to identify an interval of time, for example, \fI3 seconds\fR or
+\fI1 year\fR.
+.SS "OPTIONS"
+.TP
+\fB\-base\fR time
+Specifies that any relative times present in a \fBclock scan\fR command
+are to be given relative to \fItime\fR. \fItime\fR must be expressed as
+a count of nominal seconds from the epoch time of 1 January 1970, 00:00 UTC.
+.TP
+\fB\-format\fR format
+Specifies the desired output format for \fBclock format\fR or the
+expected input format for \fBclock scan\fR. The \fIformat\fR string consists
+of any number of characters other than the per-cent sign
+.PQ \fB%\fR
+interspersed with any number of \fIformat groups\fR, which are two-character
+sequences beginning with the per-cent sign. The permissible format groups,
+and their interpretation, are described under \fBFORMAT GROUPS\fR.
+.RS
+.PP
+On \fBclock format\fR, the default format is
+.CS
+%a %b %d %H:%M:%S %z %Y
+.CE
+.PP
+On \fBclock scan\fR, the lack of a \fI\-format\fR option indicates that a
+.QW "free format scan"
+is requested; see \fBFREE FORM SCAN\fR for a description of what happens.
+.RE
+.TP
+\fB\-gmt\fR boolean
+If \fIboolean\fR is true, specifies that a time specified to \fBclock add\fR,
+\fBclock format\fR or \fBclock scan\fR should be processed in
+UTC. If \fIboolean\fR is false, the processing defaults to the local time
+zone. This usage is obsolete; the correct current usage is to
+specify the UTC time zone with
+.QW "\fB\-timezone\fR \fI:UTC\fR"
+or any of the equivalent ways to specify it.
+.TP
+\fB\-locale\fR localeName
+Specifies that locale-dependent scanning and formatting (and date arithmetic
+for dates preceding the adoption of the Gregorian calendar) is to be done in
+the locale identified by \fIlocaleName\fR. The locale name may be any of
+the locales acceptable to the \fBmsgcat\fR package, or it may be the special
+name \fIsystem\fR, which represents the current locale of the process, or
+the null string, which represents Tcl's default locale.
+.RS
+.PP
+The effect of locale on scanning and formatting is discussed in the
+descriptions of the individual format groups under \fBFORMAT GROUPS\fR.
+The effect of locale on clock arithmetic is discussed under
+\fBCLOCK ARITHMETIC\fR.
+.RE
+.TP
+\fB\-timezone\fR zoneName
+Specifies that clock arithmetic, formatting, and scanning are to be done
+according to the rules for the time zone specified by \fIzoneName\fR.
+The permissible values, and their interpretation, are discussed under
+\fBTIME ZONES\fR.
+On subcommands that expect a \fB\-timezone\fR argument, the default
+is to use the \fIcurrent time zone\fR. The current time zone is
+determined, in order of preference, by:
.RS
-If the \fB\-format\fR argument is not specified, the format string
-\fB"%a %b %d %H:%M:%S %Z %Y"\fR is used. If the \fB\-gmt\fR argument
-is present the next argument must be a boolean which if true specifies
-that the time will be formatted as Greenwich Mean Time. If false
-then the local timezone will be used as defined by the operating
-environment.
+.IP [1]
+the environment variable \fBTCL_TZ\fR.
+.IP [2]
+the environment variable \fBTZ\fR.
+.IP [3]
+on Windows systems, the time zone settings from the Control Panel.
.RE
+If none of these is present, the C \fBlocaltime\fR and \fBmktime\fR
+functions are used to attempt to convert times between local and
+Greenwich. On 32-bit systems, this approach is likely to have bugs,
+particularly for times that lie outside the window (approximately the
+years 1902 to 2037) that can be represented in a 32-bit integer.
+.SH "CLOCK ARITHMETIC"
+The \fBclock add\fR command performs clock arithmetic on a value
+(expressed as nominal seconds from the epoch time of 1 January 1970, 00:00 UTC)
+given as its first argument. The remaining arguments (other than the
+possible \fB\-timezone\fR, \fB\-locale\fR and \fB\-gmt\fR options)
+are integers and keywords in alternation, where the keywords are chosen
+from \fBseconds\fR, \fBminutes\fR, \fBhours\fR,
+\fBdays\fR, \fBweeks\fR, \fBmonths\fR, or \fByears\fR, or
+any unique prefix of such a word.
+.PP
+Addition of seconds, minutes and hours is fairly straightforward;
+the given time increment (times sixty for minutes, or 3600 for hours)
+is simply added to the \fItimeVal\fR given
+to the \fBclock add\fR command. The result is interpreted as
+a nominal number of seconds from the Epoch.
+.PP
+Surprising results
+may be obtained when crossing a point at which a leap second is
+inserted or removed; the \fBclock add\fR command simply ignores
+leap seconds and therefore assumes that times come in sequence,
+23:59:58, 23:59:59, 00:00:00. (This assumption is handled by
+the fact that Tcl's model of time reacts to leap seconds by speeding
+or slowing the clock by a minuscule amount until Tcl's time
+is back in step with the world.
+.PP
+The fact that adding and subtracting hours is defined in terms of
+absolute time means that it will add fixed amounts of time in time zones
+that observe summer time (Daylight Saving Time). For example,
+the following code sets the value of \fBx\fR to \fB04:00:00\fR because
+the clock has changed in the interval in question.
+.CS
+set s [\fBclock scan\fR {2004-10-30 05:00:00} \e
+ -format {%Y-%m-%d %H:%M:%S} \e
+ -timezone :America/New_York]
+set a [\fBclock add\fR $s 24 hours -timezone :America/New_York]
+set x [\fBclock format\fR $a \e
+ -format {%H:%M:%S} -timezone :America/New_York]
+.CE
+.PP
+Adding and subtracting days and weeks is accomplished by converting
+the given time to a calendar day and time of day in the appropriate
+time zone and locale. The requisite number of days (weeks are converted
+to days by multiplying by seven) is added to the calendar day, and
+the date and time are then converted back to a count of seconds from
+the epoch time.
+.PP
+Adding and subtracting a given number of days across the point that
+the time changes at the start or end of summer time (Daylight Saving Time)
+results in the \fIsame local time\fR on the day in question. For
+instance, the following code sets the value of \fBx\fR to \fB05:00:00\fR.
+.CS
+set s [\fBclock scan\fR {2004-10-30 05:00:00} \e
+ -format {%Y-%m-%d %H:%M:%S} \e
+ -timezone :America/New_York]
+set a [\fBclock add\fR $s 1 day -timezone :America/New_York]
+set x [\fBclock format\fR $a \e
+ -format {%H:%M:%S} -timezone :America/New_York]
+.CE
+.PP
+In cases of ambiguity, where the same local time happens twice
+on the same day, the earlier time is used. In cases where the conversion
+yields an impossible time (for instance, 02:30 during the Spring
+Daylight Saving Time change using US rules), the time is converted
+as if the clock had not changed. Thus, the following code
+will set the value of \fBx\fR to \fB03:30:00\fR.
+.CS
+set s [\fBclock scan\fR {2004-04-03 02:30:00} \e
+ -format {%Y-%m-%d %H:%M:%S} \e
+ -timezone :America/New_York]
+set a [\fBclock add\fR $s 1 day -timezone :America/New_York]
+set x [\fBclock format\fR $a \e
+ -format {%H:%M:%S} -timezone :America/New_York]
+.CE
+.PP
+Adding a given number of days or weeks works correctly across the conversion
+between the Julian and Gregorian calendars; the omitted days are skipped.
+The following code sets \fBz\fR to \fB1752-09-14\fR.
+.CS
+set x [\fBclock scan\fR 1752-09-02 -format %Y-%m-%d -locale en_US]
+set y [\fBclock add\fR $x 1 day -locale en_US]
+set z [\fBclock format\fR $y -format %Y-%m-%d -locale en_US]
+.CE
+.PP
+In the bizarre case that adding the given number of days yields a date
+that does not exist because it falls within the dropped days of the
+Julian-to-Gregorian conversion, the date is converted as if it was
+on the Julian calendar.
+.PP
+Adding a number of months, or a number of years, is similar; it
+converts the given time to a calendar date and time of day. It then
+adds the requisite number of months or years, and reconverts the resulting
+date and time of day to an absolute time.
+.PP
+If the resulting date is impossible because the month has too few days
+(for example, when adding 1 month to 31 January), the last day of the
+month is substituted. Thus, adding 1 month to 31 January will result in
+28 February in a common year or 29 February in a leap year.
+.PP
+The rules for handling anomalies relating to summer time and to the
+Gregorian calendar are the same when adding/subtracting months and
+years as they are when adding/subtracting days and weeks.
+.PP
+If multiple \fIcount unit\fR pairs are present on the command, they
+are evaluated consecutively, from left to right.
+.SH "HIGH RESOLUTION TIMERS"
+Most of the subcommands supported by the \fBclock\fR command deal with
+times represented as a count of seconds from the epoch time, and this is the
+representation that \fBclock seconds\fR returns. There are three exceptions,
+which are all intended for use where higher-resolution times are required.
+\fBclock milliseconds\fR returns the count of milliseconds from the
+epoch time, and \fBclock microseconds\fR returns the count of microseconds
+from the epoch time. In addition, there is a \fBclock clicks\fR command
+that returns a platform-dependent high-resolution timer. Unlike
+\fBclock seconds\fR and \fBclock milliseconds\fR, the value
+of \fBclock clicks\fR is not guaranteed to be tied to any fixed
+epoch; it is simply intended to be the most precise interval timer
+available, and is intended only for relative timing studies such as
+benchmarks.
+.SH "FORMATTING TIMES"
+The \fBclock format\fR command produces times for display to a user
+or writing to an external medium. The command accepts times that are
+expressed in seconds from the epoch time of 1 January 1970, 00:00 UTC,
+as returned by \fBclock seconds\fR, \fBclock scan\fR, \fBclock add\fR,
+\fBfile atime\fR or \fBfile mtime\fR.
+.PP
+If a \fB\-format\fR option is present, the following argument is
+a string that specifies how the date and time are to be formatted.
+The string consists
+of any number of characters other than the per-cent sign
+.PQ \fB%\fR
+interspersed with any number of \fIformat groups\fR, which are two-character
+sequences beginning with the per-cent sign. The permissible format groups,
+and their interpretation, are described under \fBFORMAT GROUPS\fR.
+.PP
+If a \fB\-timezone\fR option is present, the following
+argument is a string that specifies the time zone in which the date and time
+are to be formatted. As an alternative to
+.QW "\fB\-timezone\fR \fI:UTC\fR" ,
+the obsolete usage
+.QW "\fB\-gmt\fR \fItrue\fR"
+may be used. See
+\fBTIME ZONES\fR for the permissible variants for the time zone.
+.PP
+If a \fB\-locale\fR option is present, the following argument is
+a string that specifies the locale in which the time is to be formatted,
+in the same format that is used for the \fBmsgcat\fR package. Note
+that the default, if \fB\-locale\fR is not specified, is the root locale
+\fB{}\fR rather than the current locale. The current locale may
+be obtained by using \fB\-locale\fR \fBcurrent\fR.
+In addition, some platforms support a \fBsystem\fR locale that
+reflects the user's current choices. For instance, on Windows, the
+format that the user has selected from dates and times in the Control
+Panel can be obtained by using the \fBsystem\fR locale. On
+platforms that do not define a user selection of date and time formats
+separate from \fBLC_TIME\fR, \fB\-locale\fR \fBsystem\fR is
+synonymous with \fB\-locale\fR \fBcurrent\fR.
+.SH "SCANNING TIMES"
+The \fBclock scan\fR command accepts times that are formatted as
+strings and converts them to counts of seconds from the epoch time
+of 1 January 1970, 00:00 UTC. It normally takes a \fB\-format\fR
+option that is followed by a string describing
+the expected format of the input. (See
+\fBFREE FORM SCAN\fR for the effect of \fBclock scan\fR
+without such an argument.) The string consists of any number of
+characters other than the per-cent sign
+.PQ \fB%\fR "" ,
+interspersed with any number of \fIformat groups\fR, which are two-character
+sequences beginning with the per-cent sign. The permissible format groups,
+and their interpretation, are described under \fBFORMAT GROUPS\fR.
+.PP
+If a \fB\-timezone\fR option is present, the following
+argument is a string that specifies the time zone in which the date and time
+are to be interpreted. As an alternative to \fB\-timezone\fR \fI:UTC\fR,
+the obsolete usage \fB\-gmt\fR \fItrue\fR may be used. See
+\fBTIME ZONES\fR for the permissible variants for the time zone.
+.PP
+If a \fB\-locale\fR option is present, the following argument is
+a string that specifies the locale in which the time is to be interpreted,
+in the same format that is used for the \fBmsgcat\fR package. Note
+that the default, if \fB\-locale\fR is not specified, is the root locale
+\fB{}\fR rather than the current locale. The current locale may
+be obtained by using \fB\-locale\fR \fBcurrent\fR.
+In addition, some platforms support a \fBsystem\fR locale that
+reflects the user's current choices. For instance, on Windows, the
+format that the user has selected from dates and times in the Control
+Panel can be obtained by using the \fBsystem\fR locale. On
+platforms that do not define a user selection of date and time formats
+separate from \fBLC_TIME\fR, \fB\-locale\fR \fBsystem\fR is
+synonymous with \fB\-locale\fR \fBcurrent\fR.
+.PP
+If a \fB\-base\fR option is present, the following argument is
+a time (expressed in seconds from the epoch time) that is used as
+a \fIbase time\fR for interpreting relative times. If no
+\fB\-base\fR option is present, the base time is the current time.
+.PP
+Scanning of times in fixed format works by determining three things:
+the date, the time of day, and the time zone. These three are then
+combined into a point in time, which is returned as the number of seconds
+from the epoch.
+.PP
+Before scanning begins, the format string is preprocessed
+to replace \fB%c\fR, \fB%Ec\fR, \fB%x\fR, \fB%Ex\fR,
+\fB%X\fR. \fB%Ex\fR, \fB%r\fR, \fB%R\fR, \fB%T\fR,
+\fB%D\fR, \fB%EY\fR and \fB%+\fR format groups with counterparts
+that are appropriate to the current locale and contain none of the
+above groups. For instance, \fB%D\fR will (in the \fBen_US\fR locale)
+be replaced with \fB%m/%d/%Y\fR.
+.PP
+The date is determined according to the fields that are present in the
+preprocessed format string. In order of preference:
+.IP [1]
+If the string contains a \fB%s\fR format group, representing
+seconds from the epoch, that group is used to determine the date.
+.IP [2]
+If the string contains a \fB%J\fR format group, representing
+the Julian Day Number, that group is used to determine the date.
+.IP [3]
+If the string contains a complete set of format groups specifying
+century, year, month, and day of month; century, year, and day of year;
+or ISO8601 fiscal year, week of year, and day of week; those groups are
+combined and used to determine the date. If more than one complete
+set is present, the one at the rightmost position in the string is
+used.
+.IP [4]
+If the string lacks a century but contains a set of format
+groups specifying year of century, month and day of month; year of
+century and day of year; or two-digit ISO8601 fiscal year, week of year,
+and day of week; those groups are
+combined and used to determine the date. If more than one complete
+set is present, the one at the rightmost position in the string is
+used. The year is presumed to lie in the range 1938 to 2037 inclusive.
+.IP [5]
+If the string entirely lacks any specification for the year
+(or contains the year only on the locale's alternative calendar)
+and contains a set of format groups specifying month and day of month,
+day of year, or week of year and day of week, those groups are
+combined and used to determine the date. If more than one complete
+set is present, the one at the rightmost position in the string is
+used. The year is determined by interpreting the base time in the given
+time zone.
+.IP [6]
+If the string contains none of the above sets, but has a day
+of the month or day of the week, the day of the month or day of the week
+are used to determine the date by interpreting the base time in the
+given time zone and returning the given day of the current week or month.
+(The week runs from Monday to Sunday, ISO8601-fashion.) If both day
+of month and day of week are present, the day of the month takes
+priority.
+.IP [7]
+If none of the above rules results in a usable date, the date
+of the base time in the given time zone is used.
+.PP
+The time is also determined according to the fields that are present in the
+preprocessed format string. In order of preference:
+.IP [1]
+If the string contains a \fB%s\fR format group, representing
+seconds from the epoch, that group determines the time of day.
+.IP [2]
+If the string contains either an hour on the 24-hour clock
+or an hour on the 12-hour clock plus an AM/PM indicator, that hour determines
+the hour of the day. If the string further contains a group specifying
+the minute of the hour, that group combines with the hour. If the string
+further contains a group specifying the second of the minute, that group
+combines with the hour and minute.
+.IP [3]
+If the string contains neither a \fB%s\fR format group nor
+a group specifying the hour of the day, then midnight (\fB00:00\fR, the start
+of the given date) is used.
+The time zone is determined by either the \fB\-timezone\fR or \fB\-gmt\fR
+options, or by using the current time zone.
+.PP
+If a format string lacks a \fB%z\fR or \fB%Z\fR format group,
+it is possible for the time to be ambiguous because it appears twice
+in the same day, once without and once with Daylight Saving Time.
+If this situation occurs, the first occurrence of the time is chosen.
+(For this reason, it is wise to have the input string contain the
+time zone when converting local times. This caveat does not apply to
+UTC times.)
+.SH "FORMAT GROUPS"
+The following format groups are recognized by the \fBclock scan\fR and
+\fBclock format\fR commands.
+.TP
+\fB%a\fR
+On output, receives an abbreviation (\fIe.g.,\fR \fBMon\fR) for the day
+of the week in the given locale. On input, matches the name of the day
+of the week in the given locale (in either abbreviated or full form, or
+any unique prefix of either form).
+.TP
+\fB%A\fR
+On output, receives the full name (\fIe.g.,\fR \fBMonday\fR) of the day
+of the week in the given locale. On input, matches the name of the day
+of the week in the given locale (in either abbreviated or full form, or
+any unique prefix of either form).
+.TP
+\fB%b\fR
+On output, receives an abbreviation (\fIe.g.,\fR \fBJan\fR) for the name
+of the month in the given locale. On input, matches the name of the month
+in the given locale (in either abbreviated or full form, or
+any unique prefix of either form).
+.TP
+\fB%B\fR
+On output, receives the full name (\fIe.g.,\fR \fBJanuary\fR)
+of the month in the given locale. On input, matches the name of the month
+in the given locale (in either abbreviated or full form, or
+any unique prefix of either form).
+.TP
+\fB%c\fR
+On output, receives a localized representation of date and time of day;
+the localized representation is expected to use the Gregorian calendar.
+On input, matches whatever \fB%c\fR produces.
.TP
-\fBclock scan \fIdateString\fR ?\fB\-base \fIclockVal\fR? ?\fB\-gmt \fIboolean\fR?
-Convert \fIdateString\fR to an integer clock value (see \fBclock seconds\fR).
-This command can parse and convert virtually any standard date and/or time
-string, which can include standard time zone mnemonics. If only a time is
-specified, the current date is assumed. If the string does not contain a
-time zone mnemonic, the local time zone is assumed, unless the \fB\-gmt\fR
+\fB%C\fR
+On output, receives the number of the century in Indo-Arabic numerals.
+On input, matches one or two digits, possibly with leading whitespace,
+that are expected to be the number of the century.
+.TP
+\fB%d\fR
+On output, produces the number of the day of the month, as two decimal
+digits. On input, matches one or two digits, possibly with leading
+whitespace, that are expected to be the number of the day of the month.
+.TP
+\fB%D\fR
+This format group is synonymous with \fB%m/%d/%Y\fR. It should be
+used only in exchanging data within the \fBen_US\fR locale, since
+other locales typically do not use this order for the fields of the date.
+.TP
+\fB%e\fR
+On output, produces the number of the day of the month, as one or
+two decimal digits (with a leading blank for one-digit dates).
+On input, matches one or two digits, possibly with leading
+whitespace, that are expected to be the number of the day of the month.
+.TP
+\fB%Ec\fR
+On output, produces a locale-dependent representation of the date and
+time of day in the locale's alternative calendar. On input, matches
+whatever \fB%Ec\fR produces. The locale's alternative calendar need not
+be the Gregorian calendar.
+.TP
+\fB%EC\fR
+On output, produces a locale-dependent name of an era in the locale's
+alternative calendar. On input, matches the name of the era or any
+unique prefix.
+.TP
+\fB%EE\fR
+On output, produces the string \fBB.C.E.\fR or \fBC.E.\fR, or a
+string of the same meaning in the locale, to indicate whether \fB%Y\fR refers
+to years before or after Year 1 of the Common Era. On input, accepts
+the string \fBB.C.E.\fR, \fBB.C.\fR, \fBC.E.\fR, \fBA.D.\fR, or the
+abbreviation appropriate to the current locale, and uses it to fix
+whether \fB%Y\fR refers to years before or after Year 1 of the
+Common Era.
+.TP
+\fB%Ex\fR
+On output, produces a locale-dependent representation of the date
+in the locale's alternative calendar. On input, matches
+whatever \fB%Ex\fR produces. The locale's alternative calendar need not
+be the Gregorian calendar.
+.TP
+\fB%EX\fR
+On output, produces a locale-dependent representation of the
+time of day in the locale's alternative numerals. On input, matches
+whatever \fB%EX\fR produces.
+.TP
+\fB%Ey\fR
+On output, produces a locale-dependent number of the year of the era
+in the locale's alternative calendar and numerals. On input, matches
+such a number.
+.TP
+\fB%EY\fR
+On output, produces a representation of the year in the locale's
+alternative calendar and numerals. On input, matches what \fB%EY\fR
+produces. Often synonymous with \fB%EC%Ey\fR.
+.TP
+\fB%g\fR
+On output, produces a two-digit year number suitable for use with
+the week-based ISO8601 calendar; that is, the year number corresponds
+to the week number produced by \fB%V\fR. On input, accepts such
+a two-digit year number, possibly with leading whitespace.
+.TP
+\fB%G\fR
+On output, produces a four-digit year number suitable for use with
+the week-based ISO8601 calendar; that is, the year number corresponds
+to the week number produced by \fB%V\fR. On input, accepts such
+a four-digit year number, possibly with leading whitespace.
+.TP
+\fB%h\fR
+This format group is synonymous with \fB%b\fR.
+.TP
+\fB%H\fR
+On output, produces a two-digit number giving the hour of the day
+(00-23) on a 24-hour clock. On input, accepts such a number.
+.TP
+\fB%I\fR
+On output, produces a two-digit number giving the hour of the day
+(12-11) on a 12-hour clock. On input, accepts such a number.
+.TP
+\fB%j\fR
+On output, produces a three-digit number giving the day of the year
+(001-366). On input, accepts such a number.
+.TP
+\fB%J\fR
+On output, produces a string of digits giving the Julian Day Number.
+On input, accepts a string of digits and interprets it as a Julian Day Number.
+The Julian Day Number is a count of the number of calendar days
+that have elapsed since 1 January, 4713 BCE of the proleptic
+Julian calendar. The epoch time of 1 January 1970 corresponds
+to Julian Day Number 2440588.
+.TP
+\fB%k\fR
+On output, produces a one- or two-digit number giving the hour of the day
+(0-23) on a 24-hour clock. On input, accepts such a number.
+.TP
+\fB%l\fR
+On output, produces a one- or two-digit number giving the hour of the day
+(12-11) on a 12-hour clock. On input, accepts such a number.
+.TP
+\fB%m\fR
+On output, produces the number of the month (01-12) with exactly two
+digits. On input, accepts two digits and interprets them as the number
+of the month.
+.TP
+\fB%M\fR
+On output, produces the number of the minute of the hour (00-59)
+with exactly two digits. On input, accepts two digits and interprets them
+as the number of the minute of the hour.
+.TP
+\fB%N\fR
+On output, produces the number of the month (1-12) with one or two digits,
+and a leading blank for one-digit dates.
+On input, accepts one or two digits, possibly with leading whitespace,
+and interprets them as the number of the month.
+.TP
+\fB%Od\fR, \fB%Oe\fR, \fB%OH\fR, \fB%OI\fR, \fB%Ok\fR, \fB%Ol\fR, \fB%Om\fR, \fB%OM\fR, \fB%OS\fR, \fB%Ou\fR, \fB%Ow\fR, \fB%Oy\fR
+All of these format groups are synonymous with their counterparts
+without the
+.QW \fBO\fR ,
+except that the string is produced and parsed in the
+locale-dependent alternative numerals.
+.TP
+\fB%p\fR
+On output, produces an indicator for the part of the day, \fBAM\fR
+or \fBPM\fR, appropriate to the given locale. If the script of the
+given locale supports multiple letterforms, lowercase is preferred.
+On input, matches the representation \fBAM\fR or \fBPM\fR in
+the given locale, in either case.
+.TP
+\fB%P\fR
+On output, produces an indicator for the part of the day, \fBam\fR
+or \fBpm\fR, appropriate to the given locale. If the script of the
+given locale supports multiple letterforms, uppercase is preferred.
+On input, matches the representation \fBAM\fR or \fBPM\fR in
+the given locale, in either case.
+.TP
+\fB%Q\fR
+This format group is reserved for internal use within the Tcl library.
+.TP
+\fB%r\fR
+On output, produces a locale-dependent time of day representation on a
+12-hour clock. On input, accepts whatever \fB%r\fR produces.
+.TP
+\fB%R\fR
+On output, produces a locale-dependent time of day representation on a
+24-hour clock. On input, accepts whatever \fB%R\fR produces.
+.TP
+\fB%s\fR
+On output, simply formats the \fItimeVal\fR argument as a decimal
+integer and inserts it into the output string. On input, accepts
+a decimal integer and uses is as the time value without any further
+processing. Since \fB%s\fR uniquely determines a point in time, it
+overrides all other input formats.
+.TP
+\fB%S\fR
+On output, produces a two-digit number of the second of the minute
+(00-59). On input, accepts two digits and uses them as the second of the
+minute.
+.TP
+\fB%t\fR
+On output, produces a TAB character. On input, matches a TAB character.
+.TP
+\fB%T\fR
+Synonymous with \fB%H:%M:%S\fR.
+.TP
+\fB%u\fR
+On output, produces the number of the day of the week
+(\fB1\fR\(->Monday, \fB7\fR\(->Sunday). On input, accepts a single digit and
+interprets it as the day of the week. Sunday may be either \fB0\fR or
+\fB7\fR.
+.TP
+\fB%U\fR
+On output, produces the ordinal number of the week of the year
+(00-53). The first Sunday of the year is the first day of week 01. On
+input accepts two digits which are otherwise ignored. This format
+group is never used in determining an input date. This interpretation
+of the week of the year was once common in US banking but is now
+largely obsolete. See \fB%V\fR for the ISO8601 week number.
+.TP
+\fB%V\fR
+On output, produces the number of the ISO8601 week as a two digit
+number (01-53). Week 01 is the week containing January 4; or the first
+week of the year containing at least 4 days; or the week containing
+the first Thursday of the year (the three statements are
+equivalent). Each week begins on a Monday. On input, accepts the
+ISO8601 week number.
+.TP
+\fB%w\fR
+On output, produces the ordinal number of the day of the week
+(Sunday==0; Saturday==6). On input, accepts a single digit and
+interprets it as the day of the week; Sunday may be represented as
+either 0 or 7. Note that \fB%w\fR is not the ISO8601 weekday number,
+which is produced and accepted by \fB%u\fR.
+.TP
+\fB%W\fR
+On output, produces a week number (00-53) within the year; week 01
+begins on the first Monday of the year. On input, accepts two digits,
+which are otherwise ignored. This format group is never used in
+determining an input date. It is not the ISO8601 week number; that
+week is produced and accepted by \fB%V\fR.
+.TP
+\fB%x\fR
+On output, produces the date in a locale-dependent representation. On
+input, accepts whatever \fB%x\fR produces and is used to determine
+calendar date.
+.TP
+\fB%X\fR
+On output, produces the time of day in a locale-dependent
+representation. On input, accepts whatever \fB%X\fR produces and is used
+to determine time of day.
+.TP
+\fB%y\fR
+On output, produces the two-digit year of the century. On input,
+accepts two digits, and is used to determine calendar date. The
+date is presumed to lie between 1938 and 2037 inclusive. Note
+that \fB%y\fR does not yield a year appropriate for use with the ISO8601
+week number \fB%V\fR; programs should use \fB%g\fR for that purpose.
+.TP
+\fB%Y\fR
+On output, produces the four-digit calendar year. On input,
+accepts four digits and may be used to determine calendar date. Note
+that \fB%Y\fR does not yield a year appropriate for use with the ISO8601
+week number \fB%V\fR; programs should use \fB%G\fR for that purpose.
+.TP
+\fB%z\fR
+On output, produces the current time zone, expressed in hours and
+minutes east (+hhmm) or west (\-hhmm) of Greenwich. On input, accepts a
+time zone specifier (see \fBTIME ZONES\fR below) that will be used to
+determine the time zone.
+.TP
+\fB%Z\fR
+On output, produces the current time zone's name, possibly
+translated to the given locale. On input, accepts a time zone
+specifier (see \fBTIME ZONES\fR below) that will be used to determine the
+time zone. This option should, in general, be used on input only when
+parsing RFC822 dates. Other uses are fraught with ambiguity; for
+instance, the string \fBBST\fR may represent British Summer Time or
+Brazilian Standard Time. It is recommended that date/time strings for
+use by computers use numeric time zones instead.
+.TP
+\fB%%\fR
+On output, produces a literal
+.QW \fB%\fR
+character. On input, matches a literal
+.QW \fB%\fR
+character.
+.TP
+\fB%+\fR
+Synonymous with
+.QW "\fB%a %b %e %H:%M:%S %Z %Y\fR" .
+.SH "TIME ZONES"
+When the \fBclock\fR command is processing a local time, it has several
+possible sources for the time zone to use. In order of preference, they
+are:
+.IP [1]
+A time zone specified inside a string being parsed and matched by a \fB%z\fR
+or \fB%Z\fR format group.
+.IP [2]
+A time zone specified with the \fB\-timezone\fR option to the \fBclock\fR
+command (or, equivalently, by \fB\-gmt\fR \fB1\fR).
+.IP [3]
+A time zone specified in an environment variable \fBTCL_TZ\fR.
+.IP [4]
+A time zone specified in an environment variable \fBTZ\fR.
+.IP [5]
+The local time zone from the Control Panel on Windows systems.
+.IP [6]
+The C library's idea of the local time zone, as defined by the
+\fBmktime\fR and \fBlocaltime\fR functions.
+.PP
+In case [1] \fIonly,\fR the string is tested to see if it is one
+of the strings:
+.CS
+ gmt ut utc bst wet wat at
+ nft nst ndt ast adt est edt
+ cst cdt mst mdt pst pdt yst
+ ydt hst hdt cat ahst nt idlw
+ cet cest met mewt mest swt sst
+ eet eest bt it zp4 zp5 ist
+ zp6 wast wadt jt cct jst cast
+ cadt east eadt gst nzt nzst nzdt
+ idle
+.CE
+If it is a string in the above list, it designates a known
+time zone, and is interpreted as such.
+.PP
+For time zones in case [1] that do not match any of the above strings,
+and always for cases [2]-[6], the following rules apply.
+.PP
+If the time zone begins with a colon, it is one of a
+standardized list of names like \fB:America/New_York\fR
+that give the rules for various locales. A complete list
+of the location names is too lengthy to be listed here.
+On most Tcl installations, the definitions of the locations
+are to be found in named files in the directory
+.QW "\fI/no_backup/tools/lib/tcl8.5/clock/tzdata\fR" .
+On some Unix systems, these files are omitted, and the definitions are
+instead obtained from system files in
+.QW "\fI/usr/share/zoneinfo\fR" ,
+.QW "\fI/usr/share/lib/zoneinfo\fR"
+or
+.QW "\fI/usr/local/etc/zoneinfo\fR" .
+As a special case, the name \fB:localtime\fR refers to
+the local time zone as defined by the C library.
+.PP
+A time zone string consisting of a plus or minus sign followed by
+four or six decimal digits is interpreted as an offset in
+hours, minutes, and seconds (if six digits are present) from
+UTC. The plus sign denotes a sign east of Greenwich;
+the minus sign one west of Greenwich.
+.PP
+A time zone string conforming to the Posix specification of the \fBTZ\fR
+environment variable will be recognized. The specification
+may be found at
+\fIhttp://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html\fR.
+.PP
+Any other time zone string is processed by prefixing a colon and attempting
+to use it as a location name, as above.
+.SH "LOCALIZATION"
+Developers wishing to localize the date and time formatting and parsing
+are referred to \fIhttp://tip.tcl.tk/173\fR for a
+specification.
+.SH "FREE FORM SCAN"
+If the \fBclock scan\fR command is invoked without a \fB\-format\fR
+option, then it requests a \fIfree-form scan.\fR \fI
+This form of scan is deprecated.\fR The reason for the deprecation
+is that there are too many ambiguities. (Does the string
+.QW 2000
+represent a year, a time of day, or a quantity?) No set of rules
+for interpreting free-form dates and times has been found to
+give unsurprising results in all cases.
+.PP
+If free-form scan is used, only the \fB\-base\fR and \fB\-gmt\fR
+options are accepted. The \fB\-timezone\fR and \fB\-locale\fR
+options will result in an error if \fB\-format\fR is not supplied.
+.PP
+For the benefit of users who need to understand legacy code that
+uses free-form scan, the documentation for how free-form scan
+interprets a string is included here:
+.PP
+If only a time is
+specified, the current date is assumed. If the \fIinputString\fR
+does not contain a
+time zone mnemonic, the local time zone is assumed, unless the \fB\-gmt\fR
argument is true, in which case the clock value is calculated assuming
that the specified time is relative to Greenwich Mean Time.
-\fB-gmt\fR, if specified, affects only the computed time value; it does not
-impact the interpretation of \fB-base\fR.
-.sp
+\fB\-gmt\fR, if specified, affects only the computed time value; it does not
+impact the interpretation of \fB\-base\fR.
+.PP
If the \fB\-base\fR flag is specified, the next argument should contain
an integer clock value. Only the date in this value is used, not the
time. This is useful for determining the time on a specific day or
doing other date-relative conversions.
-.sp
-The \fIdateString\fR consists of zero or more specifications of the
+.PP
+The \fIinputString\fR argument consists of zero or more specifications of the
following form:
-.RS
.TP
\fItime\fR
-A time of day, which is of the form: \fIhh\fR?\fI:mm\fR?\fI:ss\fR??
-?\fImeridian\fR? ?\fIzone\fR? or \fIhhmm \fR?\fImeridian\fR?
-?\fIzone\fR?. If no meridian is specified, \fIhh\fR is interpreted on
+A time of day, which is of the form: \fBhh?:mm?:ss?? ?meridian? ?zone?\fR
+or \fBhhmm ?meridian? ?zone?\fR
+If no meridian is specified, \fBhh\fR is interpreted on
a 24-hour clock.
.TP
\fIdate\fR
A specific month and day with optional year. The
-acceptable formats are \fImm/dd\fR?\fI/yy\fR?, \fImonthname dd\fR
-?, \fIyy\fR?, \fIdd monthname \fR?\fIyy\fR?, \fIday, dd monthname
-yy\fR, \fI?CC?yymmdd\fR, \fI?CC?yy-mm-dd\fR, \fIdd-monthname-?CC?yy\fR.
+acceptable formats are
+.QW "\fBmm/dd\fR?\fB/yy\fR?" ,
+.QW "\fBmonthname dd\fR?\fB, yy\fR?" ,
+.QW "\fBday, dd monthname \fR?\fByy\fR?" ,
+.QW "\fBdd monthname yy\fR" ,
+.QW "?\fBCC\fR?\fByymmdd\fR" ,
+and
+.QW "\fBdd-monthname-\fR?\fBCC\fR?\fByy\fR" .
The default year is the current year. If the year is less
-.VS
than 100, we treat the years 00-68 as 2000-2068 and the years 69-99
as 1969-1999. Not all platforms can represent the years 38-70, so
an error may result if these years are used.
-.VE
.TP
\fIISO 8601 point-in-time\fR
-An ISO 8601 point-in-time specification, such as \fICCyymmddThhmmss\fR, where
-T is the literal T, \fICCyymmdd hhmmss\fR, or
-\fICCyymmddThh:mm:ss\fR. Note that only these three formats are accepted.
+An ISO 8601 point-in-time specification, such as
+.QW \fICCyymmdd\fBT\fIhhmmss\fR,
+where \fBT\fR is the literal
+.QW T ,
+.QW "\fICCyymmdd hhmmss\fR" ,
+or
+.QW \fICCyymmdd\fBT\fIhh:mm:ss\fR .
+Note that only these three formats are accepted.
The command does \fInot\fR accept the full range of point-in-time
specifications specified in ISO8601. Other formats can be recognized by
-using commands such as \fBregexp\fR to extract their fields and reorganize
-them into a form accepted by the \fBclock scan\fR command.
+giving an explicit \fI\-format\fR option to the \fBclock scan\fR command.
.TP
\fIrelative time\fR
-A specification relative to the current time. The format is \fInumber
-unit\fR acceptable units are \fByear\fR, \fBfortnight\fR, \fBmonth\fR, \fBweek\fR, \fBday\fR,
+A specification relative to the current time. The format is \fBnumber
+unit\fR. Acceptable units are \fByear\fR, \fBfortnight\fR,
+\fBmonth\fR, \fBweek\fR, \fBday\fR,
\fBhour\fR, \fBminute\fR (or \fBmin\fR), and \fBsecond\fR (or \fBsec\fR). The
unit can be specified as a singular or plural, as in \fB3 weeks\fR.
These modifiers may also be specified:
\fBtomorrow\fR, \fByesterday\fR, \fBtoday\fR, \fBnow\fR,
\fBlast\fR, \fBthis\fR, \fBnext\fR, \fBago\fR.
-.RE
-.sp
-.RS
+.PP
The actual date is calculated according to the following steps.
+.PP
First, any absolute date and/or time is processed and converted.
Using that time as the base, day-of-week specifications are added.
Next, relative specifications are used. If a date or day is
@@ -262,29 +893,9 @@ used. Finally, a correction is applied so that the correct hour of
the day is produced after allowing for daylight savings time
differences and the correct date is given when going from the end
of a long month to a short month.
-.sp
-Daylight savings time correction is applied only when the relative time
-is specified in units of days or more, ie, days, weeks, fortnights, months or
-years. This means that when crossing the daylight savings time boundary,
-different results will be given for \fBclock scan "1 day"\fR and
-\fBclock scan "24 hours"\fR:
-.CS
-.ta 6c
-% \fBclock scan\fR "1 day" -base [\fBclock scan\fR 1999-10-31]
-941443200
-% \fBclock scan\fR "24 hours" -base [\fBclock scan\fR 1999-10-31]
-941439600
-.CE
-.RE
-.TP
-\fBclock seconds\fR
-Return the current date and time as a system-dependent integer value. The
-unit of the value is seconds, allowing it to be used for relative time
-calculations. The value is usually defined as total elapsed time from
-an ``epoch''. You shouldn't assume the value of the epoch.
-
.SH "SEE ALSO"
-date(1), time(n)
-
+msgcat(n)
.SH KEYWORDS
clock, date, time
+.SH "COPYRIGHT"
+Copyright (c) 2004 Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
diff --git a/doc/close.n b/doc/close.n
index a1c5f01..4ef3c7d 100644
--- a/doc/close.n
+++ b/doc/close.n
@@ -10,7 +10,7 @@
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
-close \- Close an open channel.
+close \- Close an open channel
.SH SYNOPSIS
\fBclose \fIchannelId\fR
.BE
@@ -19,17 +19,14 @@ close \- Close an open channel.
.PP
Closes the channel given by \fIchannelId\fR.
.PP
-.VS
\fIChannelId\fR must be an identifier for an open channel such as a
Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR),
the return value from an invocation of \fBopen\fR or \fBsocket\fR, or
the result of a channel creation command provided by a Tcl extension.
-.VE
.PP
All buffered output is flushed to the channel's output device,
any buffered input is discarded, the underlying file or device is closed,
and \fIchannelId\fR becomes unavailable for use.
-.VS "" br
.PP
If the channel is blocking, the command does not return until all output
is flushed.
@@ -37,11 +34,9 @@ If the channel is nonblocking and there is unflushed output, the
channel remains open and the command
returns immediately; output will be flushed in the background and the
channel will be closed when all the flushing is complete.
-.VE
.PP
If \fIchannelId\fR is a blocking channel for a command pipeline then
\fBclose\fR waits for the child processes to complete.
-.VS "" br
.PP
If the channel is shared between interpreters, then \fBclose\fR
makes \fIchannelId\fR unavailable in the invoking interpreter but has no
@@ -54,7 +49,6 @@ When the last interpreter in which the channel is registered invokes
Channels are automatically closed when an interpreter is destroyed and
when the process exits. Channels are switched to blocking mode, to ensure
that all output is correctly flushed before the process exits.
-.VE
.PP
The command returns an empty string, and may generate an error if
an error occurs while flushing output. If a command in a command
diff --git a/doc/concat.n b/doc/concat.n
index e52d978..f7317c4 100644
--- a/doc/concat.n
+++ b/doc/concat.n
@@ -24,27 +24,33 @@ into a single list.
It permits any number of arguments;
if no \fIarg\fRs are supplied, the result is an empty string.
.SH EXAMPLES
-Although \fBconcat\fR will concatenate lists (so the command:
+Although \fBconcat\fR will concatenate lists, flattening them in the process
+(so giving the following interactive session):
+.PP
.CS
-\fBconcat\fR a b {c d e} {f {g h}}
+\fI%\fR \fBconcat\fR a b {c d e} {f {g h}}
+\fIa b c d e f {g h}\fR
.CE
-will return "\fBa b c d e f {g h}\fR" as its result), it will also
-concatenate things that are not lists, and hence the command:
+.PP
+it will also concatenate things that are not lists, as can be seen from this
+session:
+.PP
.CS
-\fBconcat\fR " a b {c " d " e} f"
+\fI%\fR \fBconcat\fR " a b {c " d " e} f"
+\fIa b {c d e} f\fR
.CE
-will return "\fBa b {c d e} f\fR" as its result.
.PP
-Note that the concatenation does not remove spaces from the middle of
-its arguments, so the command:
+Note also that the concatenation does not remove spaces from the middle of
+values, as can be seen here:
+.PP
.CS
-\fBconcat\fR "a b c" { d e f }
+\fI%\fR \fBconcat\fR "a b c" { d e f }
+\fIa b c d e f\fR
.CE
-will return "\fBa b c d e f\fR" (i.e. with three spaces between
-the \fBa\fR, the \fBb\fR and the \fBc\fR).
-
+.PP
+(i.e., there are three spaces between each of the \fBa\fR, the \fBb\fR and the
+\fBc\fR).
.SH "SEE ALSO"
-append(n), eval(n)
-
+append(n), eval(n), join(n)
.SH KEYWORDS
concatenate, join, lists
diff --git a/doc/dde.n b/doc/dde.n
index 7222f51..ce00aee 100644
--- a/doc/dde.n
+++ b/doc/dde.n
@@ -6,26 +6,26 @@
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
-.TH dde n 1.2 dde "Tcl Bundled Packages"
+.TH dde n 1.3 dde "Tcl Bundled Packages"
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
dde \- Execute a Dynamic Data Exchange command
.SH SYNOPSIS
.sp
-\fBpackage require dde 1.2\fR
+\fBpackage require dde 1.3\fR
.sp
-\fBdde eval\fR ?\fB\-async\fR? \fIservice cmd\fR ?\fIarg ...\fR?
+\fBdde servername\fR ?\fB\-force\fR? ?\fB\-handler \fIproc\fR? ?\fB\-\|\-\fR? ?\fItopic\fR?
.sp
\fBdde execute\fR ?\fB\-async\fR? \fIservice topic data\fR
.sp
-\fBdde poke \fIservice topic item data\fR
-.sp
-\fBdde request\fR ?\fB\-binary\fR? \fIservice topic data\fR
+\fBdde poke\fR \fIservice topic item data\fR
.sp
-\fBdde servername\fR ?\fItopic\fR?
+\fBdde request\fR ?\fB\-binary\fR? \fIservice topic item\fR
.sp
\fBdde services \fIservice topic\fR
+.sp
+\fBdde eval\fR ?\fB\-async\fR? \fItopic cmd \fR?\fIarg arg ...\fR?
.BE
.SH DESCRIPTION
@@ -37,23 +37,40 @@ transaction needs a \fIservice name\fR and a \fItopic\fR. Both the
\fIservice name\fR and \fItopic\fR are application defined; Tcl uses
the service name \fBTclEval\fR, while the topic name is the name of the
interpreter given by \fBdde servername\fR. Other applications have their
-own \fIservice name\fRs and \fItopic\fRs. For instance, Microsoft Excel
+own \fIservice names\fR and \fItopics\fR. For instance, Microsoft Excel
has the service name \fBExcel\fR.
.PP
-The \fBeval\fR and \fBexecute\fR commands accept the option \fB\-async\fR:
-
.SH "DDE COMMANDS"
.PP
The following commands are a subset of the full Dynamic Data Exchange
set of commands.
.TP
-\fBdde servername \fR?\fItopic\fR?
+\fBdde servername \fR?\fB\-force\fR? ?\fB\-handler \fIproc\fR? ?\fB\-\|\-\fR? ?\fItopic\fR?
+.
\fBdde servername\fR registers the interpreter as a DDE server with
the service name \fBTclEval\fR and the topic name specified by \fItopic\fR.
If no \fItopic\fR is given, \fBdde servername\fR returns the name
-of the current topic or the empty string if it is not registered as a service.
+of the current topic or the empty string if it is not registered as a
+service. If the given \fItopic\fR name is already in use, then a
+suffix of the form
+.QW " #2"
+or
+.QW " #3"
+is appended to the name to make it
+unique. The command's result will be the name actually used. The
+\fB\-force\fR option is used to force registration of precisely the
+given \fItopic\fR name.
+.RS
+.PP
+The \fB\-handler\fR option specifies a Tcl procedure that will be called to
+process calls to the dde server. If the package has been loaded into a
+safe interpreter then a \fB\-handler\fR procedure must be defined. The
+procedure is called with all the arguments provided by the remote
+call.
+.RE
.TP
\fBdde execute\fR ?\fB\-async\fR? \fIservice topic data\fR
+.
\fBdde execute\fR takes the \fIdata\fR and sends it to the server indicated
by \fIservice\fR with the topic indicated by \fItopic\fR. Typically,
\fIservice\fR is the name of an application, and \fItopic\fR is a file to
@@ -65,6 +82,7 @@ script did not run, unless the \fB\-async\fR flag was used, in which case
the command returns immediately with no error.
.TP
\fBdde poke \fIservice topic item data\fR
+.
\fBdde poke\fR passes the \fIdata\fR to the server indicated by
\fIservice\fR using the \fItopic\fR and \fIitem\fR specified. Typically,
\fIservice\fR is the name of an application. \fItopic\fR is application
@@ -74,6 +92,7 @@ it must always be non-null. The \fIdata\fR field is given to the remote
application.
.TP
\fBdde request\fR ?\fB\-binary\fR? \fIservice topic item\fR
+.
\fBdde request\fR is typically used to get the value of something; the
value of a cell in Microsoft Excel or the text of a selection in
Microsoft Word. \fIservice\fR is typically the name of an application,
@@ -84,24 +103,25 @@ string with terminating null. If \fB\-binary\fR is specified, the
result is returned as a byte array.
.TP
\fBdde services \fIservice topic\fR
+.
\fBdde services\fR returns a list of service-topic pairs that
currently exist on the machine. If \fIservice\fR and \fItopic\fR are
-both null strings ({}), then all service-topic pairs currently
-available on the system are returned. If \fIservice\fR is null and
+both empty strings ({}), then all service-topic pairs currently
+available on the system are returned. If \fIservice\fR is empty and
\fItopic\fR is not, then all services with the specified topic are
-returned. If \fIservice\fR is not null and \fItopic\fR is, all topics
-for a given service are returned. If both are not null, if that
-service-topic pair currently exists, it is returned; otherwise, null
-is returned.
+returned. If \fIservice\fR is non-empty and \fItopic\fR is, all topics
+for a given service are returned. If both are non-empty, if that
+service-topic pair currently exists, it is returned; otherwise, an
+empty string is returned.
.TP
\fBdde eval\fR ?\fB\-async\fR? \fItopic cmd \fR?\fIarg arg ...\fR?
+.
\fBdde eval\fR evaluates a command and its arguments using the interpreter
specified by \fItopic\fR. The DDE service must be the \fBTclEval\fR
service. The \fB\-async\fR option requests asynchronous invocation. The
command returns an error message if the script did not run, unless the
\fB\-async\fR flag was used, in which case the command returns immediately
-with no error. This command can be used to replace \fBsend\fR on Windows.
-
+with no error. This command can be used to replace send on Windows.
.SH "DDE AND TCL"
A Tcl interpreter always has a service name of \fBTclEval\fR. Each
different interpreter of all running Tcl applications must be
@@ -134,7 +154,6 @@ without adding the \fB&\fR to place the process in the background).
If for any reason the event queue is not flushed, DDE commands may
hang until the event queue is flushed. This can create a deadlock
situation.
-
.SH EXAMPLE
This asks Internet Explorer (which must already be running) to go to a
particularly important website:
@@ -142,9 +161,7 @@ particularly important website:
package require dde
\fBdde execute\fR iexplore WWW_OpenURL http://www.tcl.tk/
.CE
-
.SH "SEE ALSO"
tk(n), winfo(n), send(n)
-
.SH KEYWORDS
application, dde, name, remote execution
diff --git a/doc/dict.n b/doc/dict.n
new file mode 100644
index 0000000..c54a990
--- /dev/null
+++ b/doc/dict.n
@@ -0,0 +1,370 @@
+'\"
+'\" Copyright (c) 2003 Donal K. Fellows
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.so man.macros
+.TH dict n 8.5 Tcl "Tcl Built-In Commands"
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+dict \- Manipulate dictionaries
+.SH SYNOPSIS
+\fBdict \fIoption arg \fR?\fIarg ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+Performs one of several operations on dictionary values or variables
+containing dictionary values (see the \fBDICTIONARY VALUES\fR section
+below for a description), depending on \fIoption\fR. The legal
+\fIoption\fRs (which may be abbreviated) are:
+.TP
+\fBdict append \fIdictionaryVariable key \fR?\fIstring ...\fR?
+This appends the given string (or strings) to the value that the given
+key maps to in the dictionary value contained in the given variable,
+writing the resulting dictionary value back to that variable.
+Non-existent keys are treated as if they map to an empty string.
+.TP
+\fBdict create \fR?\fIkey value ...\fR?
+Create a new dictionary that contains each of the key/value mappings
+listed as arguments (keys and values alternating, with each key being
+followed by its associated value.)
+.TP
+\fBdict exists \fIdictionaryValue key \fR?\fIkey ...\fR?
+This returns a boolean value indicating whether the given key (or path
+of keys through a set of nested dictionaries) exists in the given
+dictionary value. This returns a true value exactly when \fBdict
+get\fR on that path will succeed.
+.TP
+\fBdict filter \fIdictionaryValue filterType arg \fR?\fIarg ...\fR?
+This takes a dictionary value and returns a new dictionary that
+contains just those key/value pairs that match the specified filter
+type (which may be abbreviated.) Supported filter types are:
+.RS
+.TP
+\fBdict filter \fIdictionaryValue \fBkey \fIglobPattern\fR
+The key rule only matches those key/value pairs whose keys match the
+given pattern (in the style of \fBstring match\fR.)
+.TP
+\fBdict filter \fIdictionaryValue \fBscript {\fIkeyVar valueVar\fB} \fIscript\fR
+The script rule tests for matching by assigning the key to the
+\fIkeyVar\fR and the value to the \fIvalueVar\fR, and then evaluating
+the given script which should return a boolean value (with the
+key/value pair only being included in the result of the \fBdict
+filter\fR when a true value is returned.) Note that the first
+argument after the rule selection word is a two-element list. If the
+\fIscript\fR returns with a condition of \fBTCL_BREAK\fR, no further
+key/value pairs are considered for inclusion in the resulting
+dictionary, and a condition of \fBTCL_CONTINUE\fR is equivalent to a false
+result. The key/value pairs are tested in the order in which the keys
+were inserted into the dictionary.
+.TP
+\fBdict filter \fIdictionaryValue \fBvalue \fIglobPattern\fR
+The value rule only matches those key/value pairs whose values match
+the given pattern (in the style of \fBstring match\fR.)
+.RE
+.TP
+\fBdict for {\fIkeyVar valueVar\fB} \fIdictionaryValue body\fR
+This command takes three arguments, the first a two-element list of
+variable names (for the key and value respectively of each mapping in
+the dictionary), the second the dictionary value to iterate across,
+and the third a script to be evaluated for each mapping with the key
+and value variables set appropriately (in the manner of \fBforeach\fR.)
+The result of the command is an empty string. If any evaluation of the
+body generates a \fBTCL_BREAK\fR result, no further pairs from the
+dictionary will be iterated over and the \fBdict for\fR command will
+terminate successfully immediately. If any evaluation of the body
+generates a \fBTCL_CONTINUE\fR result, this shall be treated exactly like a
+normal \fBTCL_OK\fR result. The order of iteration is the order in
+which the keys were inserted into the dictionary.
+.TP
+\fBdict get \fIdictionaryValue \fR?\fIkey ...\fR?
+Given a dictionary value (first argument) and a key (second argument),
+this will retrieve the value for that key. Where several keys are
+supplied, the behaviour of the command shall be as if the result of
+\fBdict get $dictVal $key\fR was passed as the first argument to
+\fBdict get\fR with the remaining arguments as second (and possibly
+subsequent) arguments. This facilitates lookups in nested
+dictionaries. For example, the following two commands are equivalent:
+.RS
+.PP
+.CS
+dict get $dict foo bar spong
+dict get [dict get [dict get $dict foo] bar] spong
+.CE
+.PP
+If no keys are provided, \fBdict get\fR will return a list containing pairs of
+elements in a manner similar to \fBarray get\fR. That is, the first
+element of each pair would be the key and the second element would be
+the value for that key.
+.PP
+It is an error to attempt to retrieve a value for a key that is not
+present in the dictionary.
+.RE
+.TP
+\fBdict incr \fIdictionaryVariable key \fR?\fIincrement\fR?
+This adds the given increment value (an integer that defaults to 1 if
+not specified) to the value that the given key maps to in the
+dictionary value contained in the given variable, writing the
+resulting dictionary value back to that variable. Non-existent keys
+are treated as if they map to 0. It is an error to increment a value
+for an existing key if that value is not an integer.
+.TP
+\fBdict info \fIdictionaryValue\fR
+This returns information (intended for display to people) about the
+given dictionary though the format of this data is dependent on the
+implementation of the dictionary. For dictionaries that are
+implemented by hash tables, it is expected that this will return the
+string produced by \fBTcl_HashStats\fR, similar to \fBarray statistics\fR.
+.TP
+\fBdict keys \fIdictionaryValue \fR?\fIglobPattern\fR?
+Return a list of all keys in the given dictionary value. If a pattern
+is supplied, only those keys that match it (according to the rules of
+\fBstring match\fR) will be returned. The returned keys will be in the
+order that they were inserted into the dictionary.
+.TP
+\fBdict lappend \fIdictionaryVariable key \fR?\fIvalue ...\fR?
+This appends the given items to the list value that the given key maps
+to in the dictionary value contained in the given variable, writing
+the resulting dictionary value back to that variable. Non-existent
+keys are treated as if they map to an empty list, and it is legal for
+there to be no items to append to the list. It is an error for the
+value that the key maps to to not be representable as a list.
+.TP
+\fBdict merge \fR?\fIdictionaryValue ...\fR?
+Return a dictionary that contains the contents of each of the
+\fIdictionaryValue\fR arguments. Where two (or more) dictionaries
+contain a mapping for the same key, the resulting dictionary maps that
+key to the value according to the last dictionary on the command line
+containing a mapping for that key.
+.TP
+\fBdict remove \fIdictionaryValue \fR?\fIkey ...\fR?
+Return a new dictionary that is a copy of an old one passed in as
+first argument except without mappings for each of the keys listed.
+It is legal for there to be no keys to remove, and it also legal for
+any of the keys to be removed to not be present in the input
+dictionary in the first place.
+.TP
+\fBdict replace \fIdictionaryValue \fR?\fIkey value ...\fR?
+Return a new dictionary that is a copy of an old one passed in as
+first argument except with some values different or some extra
+key/value pairs added. It is legal for this command to be called with
+no key/value pairs, but illegal for this command to be called with a
+key but no value.
+.TP
+\fBdict set \fIdictionaryVariable key \fR?\fIkey ...\fR? \fIvalue\fR
+This operation takes the name of a variable containing a dictionary
+value and places an updated dictionary value in that variable
+containing a mapping from the given key to the given value. When
+multiple keys are present, this operation creates or updates a chain
+of nested dictionaries.
+.TP
+\fBdict size \fIdictionaryValue\fR
+Return the number of key/value mappings in the given dictionary value.
+.TP
+\fBdict unset \fIdictionaryVariable key \fR?\fIkey ...\fR?
+This operation (the companion to \fBdict set\fR) takes the name of a
+variable containing a dictionary value and places an updated
+dictionary value in that variable that does not contain a mapping for
+the given key. Where multiple keys are present, this describes a path
+through nested dictionaries to the mapping to remove. At least one key
+must be specified, but the last key on the key-path need not exist.
+All other components on the path must exist.
+.TP
+\fBdict update \fIdictionaryVariable key varName \fR?\fIkey varName ...\fR? \fIbody\fR
+Execute the Tcl script in \fIbody\fR with the value for each \fIkey\fR
+(as found by reading the dictionary value in \fIdictionaryVariable\fR)
+mapped to the variable \fIvarName\fR. There may be multiple
+\fIkey\fR/\fIvarName\fR pairs. If a \fIkey\fR does not have a mapping,
+that corresponds to an unset \fIvarName\fR. When \fIbody\fR
+terminates, any changes made to the \fIvarName\fRs is reflected back
+to the dictionary within \fIdictionaryVariable\fR (unless
+\fIdictionaryVariable\fR itself becomes unreadable, when all updates
+are silently discarded), even if the result of \fIbody\fR is an error
+or some other kind of exceptional exit. The result of \fBdict
+update\fR is (unless some kind of error occurs) the result of the
+evaluation of \fIbody\fR.
+.RS
+.PP
+Each \fIvarName\fR is mapped in the scope enclosing the \fBdict update\fR;
+it is recommended that this command only be used in a local scope
+(\fBproc\fRedure or lambda term for \fBapply\fR). Because of
+this, the variables set by \fBdict update\fR will continue to
+exist after the command finishes (unless explicitly \fBunset\fR).
+Note that the mapping of values to variables
+does not use traces; changes to the \fIdictionaryVariable\fR's
+contents only happen when \fIbody\fR terminates.
+.RE
+.TP
+\fBdict values \fIdictionaryValue \fR?\fIglobPattern\fR?
+Return a list of all values in the given dictionary value. If a
+pattern is supplied, only those values that match it (according to the
+rules of \fBstring match\fR) will be returned. The returned values
+will be in the order of that the keys associated with those values
+were inserted into the dictionary.
+.TP
+\fBdict with \fIdictionaryVariable \fR?\fIkey ...\fR? \fIbody\fR
+Execute the Tcl script in \fIbody\fR with the value for each key in
+\fIdictionaryVariable\fR mapped (in a manner similarly to \fBdict
+update\fR) to a variable with the same name. Where one or more
+\fIkey\fRs are available, these indicate a chain of nested
+dictionaries, with the innermost dictionary being the one opened out
+for the execution of \fIbody\fR. As with \fBdict update\fR, making
+\fIdictionaryVariable\fR unreadable will make the updates to the
+dictionary be discarded, and this also happens if the contents of
+\fIdictionaryVariable\fR are adjusted so that the chain of
+dictionaries no longer exists. The result of \fBdict with\fR is
+(unless some kind of error occurs) the result of the evaluation of
+\fIbody\fR.
+.RS
+.PP
+The variables are mapped in the scope enclosing the \fBdict with\fR;
+it is recommended that this command only be used in a local scope
+(\fBproc\fRedure or lambda term for \fBapply\fR). Because of
+this, the variables set by \fBdict with\fR will continue to
+exist after the command finishes (unless explicitly \fBunset\fR).
+Note that the mapping of values to variables does not use
+traces; changes to the \fIdictionaryVariable\fR's contents only happen
+when \fIbody\fR terminates.
+.RE
+.SH "DICTIONARY VALUES"
+.PP
+Dictionaries are values that contain an efficient, order-preserving
+mapping from arbitrary keys to arbitrary values.
+Each key in the dictionary maps to a single value.
+They have a textual format that is exactly that of any list with an
+even number of elements, with each mapping in the dictionary being
+represented as two items in the list. When a command takes a
+dictionary and produces a new dictionary based on it (either returning
+it or writing it back into the variable that the starting dictionary
+was read from) the new dictionary will have the same order of keys,
+modulo any deleted keys and with new keys added on to the end.
+When a string is interpreted as a dictionary and it would otherwise
+have duplicate keys, only the last value for a particular key is used;
+the others are ignored, meaning that,
+.QW "apple banana"
+and
+.QW "apple carrot apple banana"
+are equivalent dictionaries (with different string representations).
+.PP
+Operations that derive a new dictionary from an old one (e.g., updates
+like \fBdict set\fR and \fBdict unset\fR) preserve the order of keys
+in the dictionary. The exceptions to this are for any new keys they
+add, which are appended to the sequence, and any keys that are
+removed, which are excised from the order.
+.SH EXAMPLES
+.PP
+Basic dictionary usage:
+.PP
+.CS
+# Make a dictionary to map extensions to descriptions
+set filetypes [\fBdict create\fR .txt "Text File" .tcl "Tcl File"]
+
+# Add/update the dictionary
+\fBdict set\fR filetypes .tcl "Tcl Script"
+\fBdict set\fR filetypes .tm "Tcl Module"
+\fBdict set\fR filetypes .gif "GIF Image"
+\fBdict set\fR filetypes .png "PNG Image"
+
+# Simple read from the dictionary
+set ext ".tcl"
+set desc [\fBdict get\fR $filetypes $ext]
+puts "$ext is for a $desc"
+
+# Somewhat more complex, with existence test
+foreach filename [glob *] {
+ set ext [file extension $filename]
+ if {[\fBdict exists\fR $filetypes $ext]} {
+ puts "$filename is a [\fBdict get\fR $filetypes $ext]"
+ }
+}
+.CE
+.PP
+Constructing and using nested dictionaries:
+.PP
+.CS
+# Data for one employee
+\fBdict set\fR employeeInfo 12345-A forenames "Joe"
+\fBdict set\fR employeeInfo 12345-A surname "Schmoe"
+\fBdict set\fR employeeInfo 12345-A street "147 Short Street"
+\fBdict set\fR employeeInfo 12345-A city "Springfield"
+\fBdict set\fR employeeInfo 12345-A phone "555-1234"
+# Data for another employee
+\fBdict set\fR employeeInfo 98372-J forenames "Anne"
+\fBdict set\fR employeeInfo 98372-J surname "Other"
+\fBdict set\fR employeeInfo 98372-J street "32995 Oakdale Way"
+\fBdict set\fR employeeInfo 98372-J city "Springfield"
+\fBdict set\fR employeeInfo 98372-J phone "555-8765"
+# The above data probably ought to come from a database...
+
+# Print out some employee info
+set i 0
+puts "There are [\fBdict size\fR $employeeInfo] employees"
+\fBdict for\fR {id info} $employeeInfo {
+ puts "Employee #[incr i]: $id"
+ \fBdict with\fR info {
+ puts " Name: $forenames $surname"
+ puts " Address: $street, $city"
+ puts " Telephone: $phone"
+ }
+}
+# Another way to iterate and pick out names...
+foreach id [\fBdict keys\fR $employeeInfo] {
+ puts "Hello, [\fBdict get\fR $employeeInfo $id forenames]!"
+}
+.CE
+.PP
+A localizable version of \fBstring toupper\fR:
+.PP
+.CS
+# Set up the basic C locale
+set capital [\fBdict create\fR C [\fBdict create\fR]]
+foreach c [split {abcdefghijklmnopqrstuvwxyz} ""] {
+ \fBdict set\fR capital C $c [string toupper $c]
+}
+
+# English locales can luckily share the "C" locale
+\fBdict set\fR capital en [\fBdict get\fR $capital C]
+\fBdict set\fR capital en_US [\fBdict get\fR $capital C]
+\fBdict set\fR capital en_GB [\fBdict get\fR $capital C]
+
+# ... and so on for other supported languages ...
+
+# Now get the mapping for the current locale and use it.
+set upperCaseMap [\fBdict get\fR $capital $env(LANG)]
+set upperCase [string map $upperCaseMap $string]
+.CE
+.PP
+Showing the detail of \fBdict with\fR:
+.PP
+.CS
+proc sumDictionary {varName} {
+ upvar 1 $varName vbl
+ foreach key [\fBdict keys\fR $vbl] {
+ # Manufacture an entry in the subdictionary
+ \fBdict set\fR vbl $key total 0
+ # Add the values and remove the old
+ \fBdict with\fR vbl $key {
+ set total [expr {$x + $y + $z}]
+ unset x y z
+ }
+ }
+ puts "last total was $total, for key $key"
+}
+
+set myDict {
+ a {x 1 y 2 z 3}
+ b {x 6 y 5 z 4}
+}
+
+sumDictionary myDict
+# prints: \fIlast total was 15, for key b\fR
+
+puts "dictionary is now \\"$myDict\\""
+# prints: \fIdictionary is now "a {total 6} b {total 15}"\fR
+.CE
+.SH "SEE ALSO"
+append(n), array(n), foreach(n), incr(n), list(n), lappend(n), set(n)
+.SH KEYWORDS
+dictionary, create, update, lookup, iterate, filter
diff --git a/doc/encoding.n b/doc/encoding.n
index 5950246..f8f3d54 100644
--- a/doc/encoding.n
+++ b/doc/encoding.n
@@ -39,6 +39,19 @@ string. Each byte is stored in the lower 8-bits of a Unicode
character. If \fIencoding\fR is not specified, the current
system encoding is used.
.TP
+\fBencoding dirs\fR ?\fIdirectoryList\fR?
+.VS 8.5
+Tcl can load encoding data files from the file system that describe
+additional encodings for it to work with. This command sets the search
+path for \fB*.enc\fR encoding data files to the list of directories
+\fIdirectoryList\fR. If \fIdirectoryList\fR is omitted then the
+command returns the current list of directories that make up the
+search path. It is an error for \fIdirectoryList\fR to not be a valid
+list. If, when a search for an encoding data file is happening, an
+element in \fIdirectoryList\fR does not refer to a readable,
+searchable directory, that element is ignored.
+.VE 8.5
+.TP
\fBencoding names\fR
Returns a list containing the names of all of the encodings that are
currently available.
@@ -67,10 +80,11 @@ of the original string. The \fBencoding\fR command can be used to
convert this string to the expected Japanese Unicode characters. For
example,
.CS
-set s [\fBencoding convertfrom\fR euc-jp "\\xA4\\xCF"]
+set s [\fBencoding convertfrom\fR euc-jp "\exA4\exCF"]
.CE
-would return the Unicode string "\\u306F", which is the Hiragana
-letter HA.
+would return the Unicode string
+.QW "\eu306F" ,
+which is the Hiragana letter HA.
.SH "SEE ALSO"
Tcl_GetEncoding(3)
diff --git a/doc/error.n b/doc/error.n
index 8c47ba3..77391e5 100644
--- a/doc/error.n
+++ b/doc/error.n
@@ -21,36 +21,42 @@ Returns a \fBTCL_ERROR\fR code, which causes command interpretation to be
unwound. \fIMessage\fR is a string that is returned to the application
to indicate what went wrong.
.PP
-If the \fIinfo\fR argument is provided and is non-empty,
-it is used to initialize the global variable \fBerrorInfo\fR.
-\fBerrorInfo\fR is used to accumulate a stack trace of what
-was in progress when an error occurred; as nested commands unwind,
-the Tcl interpreter adds information to \fBerrorInfo\fR. If the
-\fIinfo\fR argument is present, it is used to initialize
-\fBerrorInfo\fR and the first increment of unwind information
-will not be added by the Tcl interpreter. In other
+The \fB\-errorinfo\fR return option of an interpreter is used
+to accumulate a stack trace of what was in progress when an
+error occurred; as nested commands unwind,
+the Tcl interpreter adds information to the \fB\-errorinfo\fR
+return option. If the \fIinfo\fR argument is present, it is
+used to initialize the \fB\-errorinfo\fR return options and
+the first increment of unwind information
+will not be added by the Tcl interpreter.
+In other
words, the command containing the \fBerror\fR command will not appear
-in \fBerrorInfo\fR; in its place will be \fIinfo\fR.
-This feature is most useful in conjunction with the \fBcatch\fR command:
+in the stack trace; in its place will be \fIinfo\fR.
+Historically, this feature had been most useful in conjunction
+with the \fBcatch\fR command:
if a caught error cannot be handled successfully, \fIinfo\fR can be used
to return a stack trace reflecting the original point of occurrence
of the error:
.CS
\fBcatch {...} errMsg
-set savedInfo $errorInfo
+set savedInfo $::errorInfo
\&...
error $errMsg $savedInfo\fR
.CE
+When working with Tcl 8.5 or later, the following code
+should be used instead:
+.CS
+\fBcatch {...} errMsg options
+\&...
+return -options $options $errMsg\fR
+.CE
.PP
If the \fIcode\fR argument is present, then its value is stored
-in the \fBerrorCode\fR global variable. This variable is intended
-to hold a machine-readable description of the error in cases where
-such information is available; see the \fBtclvars\fR manual
-page for information on the proper format for the variable.
-If the \fIcode\fR argument is not
-present, then \fBerrorCode\fR is automatically reset to
-``NONE'' by the Tcl interpreter as part of processing the
-error generated by the command.
+in the \fB\-errorcode\fR return option. The \fB\-errorcode\fR
+return option is intended to hold a machine-readable description
+of the error in cases where such information is available; see
+the \fBreturn\fR manual page for information on the proper format
+for this option's value.
.SH EXAMPLE
Generate an error if a basic mathematical operation fails:
.CS
@@ -60,7 +66,7 @@ if {1+2 != 3} {
.CE
.SH "SEE ALSO"
-catch(n), return(n), tclvars(n)
+catch(n), return(n)
.SH KEYWORDS
-error, errorCode, errorInfo
+error
diff --git a/doc/eval.n b/doc/eval.n
index 81b9b1f..a642d23 100644
--- a/doc/eval.n
+++ b/doc/eval.n
@@ -25,10 +25,39 @@ Tcl interpreter recursively, and returns the result of that
evaluation (or any error generated by it).
Note that the \fBlist\fR command quotes sequences of words in such a
way that they are not further expanded by the \fBeval\fR command.
-.SH EXAMPLE
-This procedure acts in a way that is analogous to the \fBlappend\fR
-command, except it inserts the argument values at the start of the
-list in the variable:
+.SH EXAMPLES
+Often, it is useful to store a fragment of a script in a variable and
+execute it later on with extra values appended. This technique is used
+in a number of places throughout the Tcl core (e.g. in \fBfcopy\fR,
+\fBlsort\fR and \fBtrace\fR command callbacks). This example shows how
+to do this using core Tcl commands:
+.CS
+set script {
+ puts "logging now"
+ lappend $myCurrentLogVar
+}
+set myCurrentLogVar log1
+# Set up a switch of logging variable part way through!
+after 20000 set myCurrentLogVar log2
+
+for {set i 0} {$i<10} {incr i} {
+ # Introduce a random delay
+ after [expr {int(5000 * rand())}]
+ update ;# Check for the asynch log switch
+ \fBeval\fR $script $i [clock clicks]
+}
+.CE
+.PP
+.VS 8.5
+Note that in the most common case (where the script fragment is
+actually just a list of words forming a command prefix), it is better
+to use \fB{*}$script\fR when doing this sort of invocation
+pattern. It is less general than the \fBeval\fR command, and hence
+easier to make robust in practice.
+.VE 8.5
+The following procedure acts in a way that is analogous to the
+\fBlappend\fR command, except it inserts the argument values at the
+start of the list in the variable:
.CS
proc lprepend {varName args} {
upvar 1 $varName var
@@ -38,9 +67,16 @@ proc lprepend {varName args} {
set var [\fBeval\fR [list linsert $var 0] $args]
}
.CE
+.VS 8.5
+However, the last line would now normally be written without
+\fBeval\fR, like this:
+.CS
+set var [linsert $var 0 {*}$args]
+.CE
+.VE 8.5
+
+.SH "SEE ALSO"
+catch(n), concat(n), error(n), interp(n), list(n), namespace(n), subst(n), tclvars(n), uplevel(n)
.SH KEYWORDS
concatenate, evaluate, script
-
-.SH "SEE ALSO"
-catch(n), concat(n), error(n), list(n), subst(n), tclvars(n)
diff --git a/doc/exec.n b/doc/exec.n
index 3f85fd6..fd4e9cf 100644
--- a/doc/exec.n
+++ b/doc/exec.n
@@ -1,12 +1,13 @@
'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
+'\" Copyright (c) 2006 Donal K. Fellows.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
-.TH exec n 7.6 Tcl "Tcl Built-In Commands"
+.TH exec n 8.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
@@ -28,6 +29,12 @@ they are treated as command-line switches and are not part
of the pipeline specification. The following switches are
currently supported:
.TP 13
+\fB\-ignorestderr\fR
+.VS 8.5
+Stops the \fBexec\fR command from treating the output of messages to the
+pipeline's standard error channel as an error case.
+.VE 8.5
+.TP 13
\fB\-keepnewline\fR
Retains a trailing newline in the pipeline's output.
Normally a trailing newline will be deleted.
@@ -40,76 +47,84 @@ If an \fIarg\fR (or pair of \fIarg\fRs) has one of the forms
described below then it is used by \fBexec\fR to control the
flow of input and output among the subprocess(es).
Such arguments will not be passed to the subprocess(es). In forms
-such as ``< \fIfileName\fR'' \fIfileName\fR may either be in a
-separate argument from ``<'' or in the same argument with no
-intervening space (i.e. ``<\fIfileName\fR'').
+such as
+.QW "\fB<\fR \fIfileName\fR" ,
+\fIfileName\fR may either be in a separate argument from
+.QW \fB<\fR
+or in the same argument with no intervening space (i.e.
+.QW \fB<\fIfileName\fR ).
.TP 15
-|
+\fB|\fR
Separates distinct commands in the pipeline. The standard output
of the preceding command will be piped into the standard input
of the next command.
.TP 15
-|&
+\fB|&\fR
Separates distinct commands in the pipeline. Both standard output
and standard error of the preceding command will be piped into
the standard input of the next command.
This form of redirection overrides forms such as 2> and >&.
.TP 15
-<\0\fIfileName\fR
+\fB<\0\fIfileName\fR
The file named by \fIfileName\fR is opened and used as the standard
input for the first command in the pipeline.
.TP 15
-<@\0\fIfileId\fR
+\fB<@\0\fIfileId\fR
\fIFileId\fR must be the identifier for an open file, such as the return
value from a previous call to \fBopen\fR.
It is used as the standard input for the first command in the pipeline.
\fIFileId\fR must have been opened for reading.
.TP 15
-<<\0\fIvalue\fR
+\fB<<\0\fIvalue\fR
\fIValue\fR is passed to the first command as its standard input.
.TP 15
->\0\fIfileName\fR
+\fB>\0\fIfileName\fR
Standard output from the last command is redirected to the file named
\fIfileName\fR, overwriting its previous contents.
.TP 15
-2>\0\fIfileName\fR
+\fB2>\0\fIfileName\fR
Standard error from all commands in the pipeline is redirected to the
file named \fIfileName\fR, overwriting its previous contents.
.TP 15
->&\0\fIfileName\fR
+\fB>&\0\fIfileName\fR
Both standard output from the last command and standard error from all
commands are redirected to the file named \fIfileName\fR, overwriting
its previous contents.
.TP 15
->>\0\fIfileName\fR
+\fB>>\0\fIfileName\fR
Standard output from the last command is
redirected to the file named \fIfileName\fR, appending to it rather
than overwriting it.
.TP 15
-2>>\0\fIfileName\fR
+\fB2>>\0\fIfileName\fR
Standard error from all commands in the pipeline is
redirected to the file named \fIfileName\fR, appending to it rather
than overwriting it.
.TP 15
->>&\0\fIfileName\fR
+\fB>>&\0\fIfileName\fR
Both standard output from the last command and standard error from
all commands are redirected to the file named \fIfileName\fR,
appending to it rather than overwriting it.
.TP 15
->@\0\fIfileId\fR
+\fB>@\0\fIfileId\fR
\fIFileId\fR must be the identifier for an open file, such as the return
value from a previous call to \fBopen\fR.
Standard output from the last command is redirected to \fIfileId\fR's
file, which must have been opened for writing.
.TP 15
-2>@\0\fIfileId\fR
+\fB2>@\0\fIfileId\fR
\fIFileId\fR must be the identifier for an open file, such as the return
value from a previous call to \fBopen\fR.
Standard error from all commands in the pipeline is
redirected to \fIfileId\fR's file.
The file must have been opened for writing.
.TP 15
->&@\0\fIfileId\fR
+\fB2>@1\0\fR
+Standard error from all commands in the pipeline is redirected to the
+command result. This operator is only valid at the end of the command
+pipeline.
+.TP 15
+\fB>&@\0\fIfileId\fR
\fIFileId\fR must be the identifier for an open file, such as the return
value from a previous call to \fBopen\fR.
Both standard output from the last command and standard error from
@@ -118,15 +133,23 @@ The file must have been opened for writing.
.PP
If standard output has not been redirected then the \fBexec\fR
command returns the standard output from the last command
-in the pipeline.
+in the pipeline,
+.VS 8.5
+unless
+.QW 2>@1
+was specified, in which case standard error is included as well.
+.VE 8.5
If any of the commands in the pipeline exit abnormally or
are killed or suspended, then \fBexec\fR will return an error
and the error message will include the pipeline's output followed by
error messages describing the abnormal terminations; the
-\fBerrorCode\fR variable will contain additional information
+\fB\-errorcode\fR return option will contain additional information
about the last abnormal termination encountered.
If any of the commands writes to its standard error file and that
-standard error isn't redirected,
+standard error is not redirected
+.VS 8.5
+and \fB\-ignorestderr\fR is not specified,
+.VE 8.5
then \fBexec\fR will return an error; the error message
will include the pipeline's standard output, followed by messages
about abnormal terminations (if any), followed by the standard error
@@ -135,22 +158,27 @@ output.
If the last character of the result or error message
is a newline then that character is normally deleted
from the result or error message.
-This is consistent with other Tcl return values, which don't
+This is consistent with other Tcl return values, which do not
normally end with newlines.
However, if \fB\-keepnewline\fR is specified then the trailing
newline is retained.
.PP
-If standard input isn't redirected with ``<'' or ``<<''
-or ``<@'' then the standard input for the first command in the
+If standard input is not redirected with
+.QW < ,
+.QW <<
+or
+.QW <@
+then the standard input for the first command in the
pipeline is taken from the application's current standard input.
.PP
-If the last \fIarg\fR is ``&'' then the pipeline will be
-executed in background.
+If the last \fIarg\fR is
+.QW &
+then the pipeline will be executed in background.
In this case the \fBexec\fR command will return a list whose
elements are the process identifiers for all of the subprocesses
in the pipeline.
The standard output from the last command in the pipeline will
-go to the application's standard output if it hasn't been
+go to the application's standard output if it has not been
redirected, and error output from all of
the commands in the pipeline will go to the application's
standard error file unless redirected.
@@ -162,26 +190,28 @@ in the PATH environment variable are searched for
an executable by the given name.
If the name contains a slash then it must refer to an executable
reachable from the current directory.
-No ``glob'' expansion or other shell-like substitutions
+No
+.QW glob
+expansion or other shell-like substitutions
are performed on the arguments to commands.
-
-.VS
.SH "PORTABILITY ISSUES"
.TP
\fBWindows\fR (all versions)
.
-Reading from or writing to a socket, using the ``\fB@\0\fIfileId\fR''
+Reading from or writing to a socket, using the
+.QW \fB@\0\fIfileId\fR
notation, does not work. When reading from a socket, a 16-bit DOS
application will hang and a 32-bit application will return immediately with
end-of-file. When either type of application writes to a socket, the
information is instead sent to the console, if one is present, or is
discarded.
-.sp
+.RS
+.PP
The Tk console text widget does not provide real standard IO capabilities.
Under Tk, when redirecting from standard input, all applications will see an
immediate end-of-file; information redirected to standard output or standard
error will be discarded.
-.sp
+.PP
Either forward or backward slashes are accepted as path separators for
arguments to Tcl commands. When executing an application, the path name
specified for the application may also contain forward or backward slashes
@@ -192,12 +222,16 @@ path name with forward slashes will not automatically be converted to use
the backslash character. If an argument contains forward slashes as the
path separator, it may or may not be recognized as a path name, depending on
the program.
-.sp
+.PP
Additionally, when calling a 16-bit DOS or Windows 3.X application, all path
-names must use the short, cryptic, path format (e.g., using ``applba~1.def''
-instead of ``applbakery.default''), which can be obtained with the
-\fBfile attributes $fileName -shortname\fR command.
-.sp
+names must use the short, cryptic, path format (e.g., using
+.QW applba~1.def
+instead of
+.QW applbakery.default ),
+which can be obtained with the
+.QW "\fBfile attributes \fIfileName \fB\-shortname\fR"
+command.
+.PP
Two or more forward or backward slashes in a row in a path refer to a
network path. For example, a simple concatenation of the root directory
\fBc:/\fR with a subdirectory \fB/windows/system\fR will yield
@@ -206,25 +240,25 @@ point called \fBsystem\fR on the machine called \fBwindows\fR (and the
\fBc:/\fR is ignored), and is not equivalent to \fBc:/windows/system\fR,
which describes a directory on the current computer. The \fBfile join\fR
command should be used to concatenate path components.
-.sp
-.RS
+.PP
Note that there are two general types of Win32 console applications:
.RS
-1) CLI -- CommandLine Interface, simple stdio exchange. \fBnetstat.exe\fR for
+.IP [1]
+CLI \(em CommandLine Interface, simple stdio exchange. \fBnetstat.exe\fR for
example.
-.br
-2) TUI -- Textmode User Interface, any application that accesses the console
+.IP [2]
+TUI \(em Textmode User Interface, any application that accesses the console
API for doing such things as cursor movement, setting text color, detecting
key presses and mouse movement, etc. An example would be \fBtelnet.exe\fR
from Windows 2000. These types of applications are not common in a windows
environment, but do exist.
.RE
+.PP
\fBexec\fR will not work well with TUI applications when a console is not
present, as is done when launching applications under wish. It is desirable
to have console applications hidden and detached. This is a designed-in
limitation as \fBexec\fR wants to communicate over pipes. The Expect
extension addresses this issue when communicating with a TUI application.
-.sp
.RE
.TP
\fBWindows NT\fR
@@ -235,26 +269,24 @@ the name as it was specified. Then, in order, \fB.com\fR, \fB.exe\fR, and
for the longer name. If a directory name was not specified as part of the
application name, the following directories are automatically searched in
order when attempting to locate the application:
-.sp
-.RS
.RS
+.IP \(bu
The directory from which the Tcl executable was loaded.
-.br
+.IP \(bu
The current directory.
-.br
+.IP \(bu
The Windows NT 32-bit system directory.
-.br
+.IP \(bu
The Windows NT 16-bit system directory.
-.br
+.IP \(bu
The Windows NT home directory.
-.br
+.IP \(bu
The directories listed in the path.
-.RE
-.sp
+.PP
In order to execute shell built-in commands like \fBdir\fR and \fBcopy\fR,
-the caller must prepend the desired command with ``\fBcmd.exe /c\0\fR''
+the caller must prepend the desired command with
+.QW "\fBcmd.exe /c\0\fR"
because built-in commands are not implemented using executables.
-.sp
.RE
.TP
\fBWindows 9x\fR
@@ -265,39 +297,42 @@ the name as it was specified. Then, in order, \fB.com\fR, \fB.exe\fR, and
for the longer name. If a directory name was not specified as part of the
application name, the following directories are automatically searched in
order when attempting to locate the application:
-.sp
-.RS
.RS
+.IP \(bu
The directory from which the Tcl executable was loaded.
-.br
+.IP \(bu
The current directory.
-.br
+.IP \(bu
The Windows 9x system directory.
-.br
+.IP \(bu
The Windows 9x home directory.
-.br
+.IP \(bu
The directories listed in the path.
.RE
-.sp
+.RS
+.PP
In order to execute shell built-in commands like \fBdir\fR and \fBcopy\fR,
-the caller must prepend the desired command with ``\fBcommand.com /c\0\fR''
+the caller must prepend the desired command with
+.QW "\fBcommand.com /c\0\fR"
because built-in commands are not implemented using executables.
-.sp
+.PP
Once a 16-bit DOS application has read standard input from a console and
then quit, all subsequently run 16-bit DOS applications will see the
standard input as already closed. 32-bit applications do not have this
problem and will run correctly, even after a 16-bit DOS application thinks
that standard input is closed. There is no known workaround for this bug
at this time.
-.sp
+.PP
Redirection between the \fBNUL:\fR device and a 16-bit application does not
always work. When redirecting from \fBNUL:\fR, some applications may hang,
-others will get an infinite stream of ``0x01'' bytes, and some will actually
+others will get an infinite stream of
+.QW 0x01
+bytes, and some will actually
correctly get an immediate end-of-file; the behavior seems to depend upon
something compiled into the application itself. When redirecting greater than
4K or so to \fBNUL:\fR, some applications will hang. The above problems do not
happen with 32-bit applications.
-.sp
+.PP
All DOS 16-bit applications are run synchronously. All standard input from
a pipe to a 16-bit DOS application is collected into a temporary file; the
other end of the pipe must be closed before the 16-bit DOS application
@@ -307,7 +342,7 @@ must terminate before the temporary files are redirected to the next stage
of the pipeline. This is due to a workaround for a Windows 95 bug in the
implementation of pipes, and is how the standard Windows 95 DOS shell
handles pipes itself.
-.sp
+.PP
Certain applications, such as \fBcommand.com\fR, should not be executed
interactively. Applications which directly access the console window,
rather than reading from their standard input and writing to their standard
@@ -315,12 +350,8 @@ output may fail, hang Tcl, or even hang the system if their own private
console window is not available to them.
.RE
.TP
-\fBMacintosh\fR
-The \fBexec\fR command is not implemented and does not exist under Macintosh.
-.TP
\fBUnix\fR\0\0\0\0\0\0\0
The \fBexec\fR command is fully functional and works as described.
-
.SH "UNIX EXAMPLES"
Here are some examples of the use of the \fBexec\fR command on Unix.
.PP
@@ -330,13 +361,14 @@ To execute a simple program and get its result:
.CE
.PP
To execute a program that can return a non-zero result, you should
-wrap the call to \fBexec\fR in \fBcatch\fR and check what the contents
-of the global \fBerrorCode\fR variable is if you have an error:
+wrap the call to \fBexec\fR in \fBcatch\fR and check the contents
+of the \fB\-errorcode\fR return option if you have an error:
.CS
set status 0
-if {[catch {\fBexec\fR grep foo bar.txt} results]} {
- if {[lindex $::errorCode 0] eq "CHILDSTATUS"} {
- set status [lindex $::errorCode 2]
+if {[catch {\fBexec\fR grep foo bar.txt} results options]} {
+ set details [dict get $options -errorcode]
+ if {[lindex $details 0] eq "CHILDSTATUS"} {
+ set status [lindex $details 2]
} else {
# Some kind of unexpected failure
}
@@ -359,9 +391,8 @@ remember that Tcl does not handle globbing or expand things into
multiple arguments by default. Instead you should write things like
this:
.CS
-eval [list \fBexec\fR ls -l] [glob *.tcl]
+\fBexec\fR ls -l {*}[glob *.tcl]
.CE
-.PP
.SH "WINDOWS EXAMPLES"
Here are some examples of the use of the \fBexec\fR command on Windows.
.PP
@@ -395,15 +426,15 @@ differences in behaviour between \fBexec\fR and DOS batch files.
.PP
When in doubt, use the command \fBauto_execok\fR: it will return the
complete path to the program as seen by the \fBexec\fR command. This
-applies especially when you want to run "internal" commands like
+applies especially when you want to run
+.QW internal
+commands like
\fIdir\fR from a Tcl script (if you just want to list filenames, use
the \fBglob\fR command.) To do that, use this:
.CS
-eval [list \fBexec\fR] [auto_execok dir] [list *.tcl]
+\fBexec\fR {*}[auto_execok dir] *.tcl
.CE
-
.SH "SEE ALSO"
error(n), open(n)
-
.SH KEYWORDS
execute, pipeline, redirection, subprocess
diff --git a/doc/exit.n b/doc/exit.n
index 5d1dc0b..eccd635 100644
--- a/doc/exit.n
+++ b/doc/exit.n
@@ -19,23 +19,23 @@ exit \- End the application
.PP
Terminate the process, returning \fIreturnCode\fR to the
system as the exit status.
-If \fIreturnCode\fR isn't specified then it defaults
+If \fIreturnCode\fR is not specified then it defaults
to 0.
.SH EXAMPLE
Since non-zero exit codes are usually interpreted as error cases by
the calling process, the \fBexit\fR command is an important part of
-signalling that something fatal has gone wrong. This code fragment is
+signaling that something fatal has gone wrong. This code fragment is
useful in scripts to act as a general problem trap:
.CS
proc main {} {
# ... put the real main code in here ...
}
-if {[catch {main} msg]} {
+if {[catch {main} msg options]} {
puts stderr "unexpected script error: $msg"
if {[info exist env(DEBUG)]} {
puts stderr "---- BEGIN TRACE ----"
- puts stderr $errorInfo
+ puts stderr [dict get $options -errorinfo]
puts stderr "---- END TRACE ----"
}
@@ -45,7 +45,7 @@ if {[catch {main} msg]} {
.CE
.SH "SEE ALSO"
-exec(n), tclvars(n)
+exec(n)
.SH KEYWORDS
exit, process
diff --git a/doc/expr.n b/doc/expr.n
index e529925..8d6a8ae 100644
--- a/doc/expr.n
+++ b/doc/expr.n
@@ -1,12 +1,13 @@
'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-2000 Sun Microsystems, Inc.
+'\" Copyright (c) 2005 by Kevin B. Kenny <kennykb@acm.org>. All rights reserved
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
-.TH expr n 8.4 Tcl "Tcl Built-In Commands"
+.TH expr n 8.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
@@ -14,14 +15,14 @@ expr \- Evaluate an expression
.SH SYNOPSIS
\fBexpr \fIarg \fR?\fIarg arg ...\fR?
.BE
-
.SH DESCRIPTION
.PP
Concatenates \fIarg\fRs (adding separator spaces between them),
evaluates the result as a Tcl expression, and returns the value.
-The operators permitted in Tcl expressions are a subset of
-the operators permitted in C expressions, and they have the
-same meaning and precedence as the corresponding C operators.
+The operators permitted in Tcl expressions include a subset of
+the operators permitted in C expressions. For those operators
+common to both Tcl and C, Tcl applies the same meaning and precedence
+as the corresponding C operators.
Expressions almost always yield numeric results
(integer or floating-point values).
For example, the expression
@@ -31,36 +32,38 @@ For example, the expression
evaluates to 14.2.
Tcl expressions differ from C expressions in the way that
operands are specified. Also, Tcl expressions support
-non-numeric operands and string comparisons.
-.SH OPERANDS
+non-numeric operands and string comparisons, as well as some
+additional operators not found in C.
+.SS OPERANDS
.PP
A Tcl expression consists of a combination of operands, operators,
and parentheses.
White space may be used between the operands and operators and
parentheses; it is ignored by the expression's instructions.
Where possible, operands are interpreted as integer values.
-Integer values may be specified in decimal (the normal case), in octal (if the
-first character of the operand is \fB0\fR), or in hexadecimal (if the first
-two characters of the operand are \fB0x\fR).
+.VS 8.5
+Integer values may be specified in decimal (the normal case), in binary
+(if the first two characters of the operand are \fB0b\fR), in octal
+(if the first two characters of the operand are \fB0o\fR), or in hexadecimal
+(if the first two characters of the operand are \fB0x\fR). For
+compatibility with older Tcl releases, an octal integer value is also
+indicated simply when the first character of the operand is \fB0\fR,
+whether or not the second character is also \fBo\fR.
If an operand does not have one of the integer formats given
above, then it is treated as a floating-point number if that is
-possible. Floating-point numbers may be specified in any of the
-ways accepted by an ANSI-compliant C compiler (except that the
-\fBf\fR, \fBF\fR, \fBl\fR, and \fBL\fR suffixes will not be permitted in
-most installations). For example, all of the
+possible. Floating-point numbers may be specified in any of several
+common formats making use of the decimal digits, the decimal point \fB.\fR,
+the characters \fBe\fR or \fBE\fR indicating scientific notation, and
+the sign characters \fB+\fR or \fB\-\fR. For example, all of the
following are valid floating-point numbers: 2.1, 3., 6e4, 7.91e+16.
+Also recognized as floating point values are the strings \fBInf\fR
+and \fBNaN\fR making use of any case for each character.
+.VE 8.5
If no numeric interpretation is possible (note that all literal
operands that are not numeric or boolean must be quoted with either
braces or with double quotes), then an operand is left as a string
(and only a limited set of operators may be applied to it).
.PP
-.VS 8.4
-On 32-bit systems, integer values MAX_INT (0x7FFFFFFF) and MIN_INT
-(-0x80000000) will be represented as 32-bit values, and integer values
-outside that range will be represented as 64-bit values (if that is
-possible at all.)
-.VE 8.4
-.PP
Operands may be specified in any of the following ways:
.IP [1]
As a numeric value, either integer or floating-point.
@@ -84,8 +87,8 @@ The command will be executed and its result will be used as
the operand.
.IP [7]
As a mathematical function whose arguments have any of the above
-forms for operands, such as \fBsin($x)\fR. See below for a list of defined
-functions.
+forms for operands, such as \fBsin($x)\fR. See \fBMATH FUNCTIONS\fR below for
+a discussion of how mathematical functions are handled.
.LP
Where the above substitutions occur (e.g. inside quoted strings), they
are performed by the expression's instructions.
@@ -102,21 +105,27 @@ Then the command on the left side of each of the lines below
will produce the value on the right side of the line:
.CS
.ta 6c
-\fBexpr 3.1 + $a 6.1
-expr 2 + "$a.$b" 5.6
-expr 4*[llength "6 2"] 8
-expr {{word one} < "word $a"} 0\fR
+\fBexpr\fR 3.1 + $a \fI6.1\fR
+\fBexpr\fR 2 + "$a.$b" \fI5.6\fR
+\fBexpr\fR 4*[llength "6 2"] \fI8\fR
+\fBexpr\fR {{word one} < "word $a"} \fI0\fR
.CE
-.SH OPERATORS
+.SS OPERATORS
.PP
-The valid operators are listed below, grouped in decreasing order
-of precedence:
+The valid operators (most of which are also available as commands in
+the \fBtcl::mathop\fR namespace; see the \fBmathop\fR(n) manual page
+for details) are listed below, grouped in decreasing order of precedence:
.TP 20
\fB\-\0\0+\0\0~\0\0!\fR
Unary minus, unary plus, bit-wise NOT, logical NOT. None of these operators
may be applied to string operands, and bit-wise NOT may be
applied only to integers.
.TP 20
+\fB**\fR
+.VS 8.5
+Exponentiation. Valid for any numeric operands.
+.VE 8.5
+.TP 20
\fB*\0\0/\0\0%\fR
Multiply, divide, remainder. None of these operators may be
applied to string operands, and remainder may be applied only
@@ -140,12 +149,19 @@ in which case string comparison is used.
\fB==\0\0!=\fR
Boolean equal and not equal. Each operator produces a zero/one result.
Valid for all operand types.
-.VS 8.4
.TP 20
\fBeq\0\0ne\fR
Boolean string equal and string not equal. Each operator produces a
zero/one result. The operand types are interpreted only as strings.
-.VE 8.4
+.TP 20
+\fBin\0\0ni\fR
+.VS 8.5
+List containment and negated list containment. Each operator produces
+a zero/one result and treats its first argument as a string and its
+second argument as a Tcl list. The \fBin\fR operator indicates
+whether the first argument is a member of the second argument list;
+the \fBni\fR operator inverts the sense of the result.
+.VE 8.5
.TP 20
\fB&\fR
Bit-wise AND. Valid for integer operands only.
@@ -173,168 +189,84 @@ The \fIx\fR operand must have a boolean or numeric value.
.LP
See the C manual for more details on the results
produced by each operator.
+.VS 8.5
+The exponentiation operator promotes types like the multiply and
+divide operators, and produces a result that is the same as the output
+of the \fBpow\fR function (after any type conversions.)
+.VE 8.5
All of the binary operators group left-to-right within the same
precedence level. For example, the command
.CS
-\fBexpr 4*2 < 7\fR
+\fBexpr\fR {4*2 < 7}
.CE
returns 0.
.PP
-The \fB&&\fR, \fB||\fR, and \fB?:\fR operators have ``lazy
-evaluation'', just as in C,
-which means that operands are not evaluated if they are
+The \fB&&\fR, \fB||\fR, and \fB?:\fR operators have
+.QW "lazy evaluation" ,
+just as in C, which means that operands are not evaluated if they are
not needed to determine the outcome. For example, in the command
.CS
\fBexpr {$v ? [a] : [b]}\fR
.CE
-only one of \fB[a]\fR or \fB[b]\fR will actually be evaluated,
+only one of
+.QW \fB[a]\fR
+or
+.QW \fB[b]\fR
+will actually be evaluated,
depending on the value of \fB$v\fR. Note, however, that this is
only true if the entire expression is enclosed in braces; otherwise
-the Tcl parser will evaluate both \fB[a]\fR and \fB[b]\fR before
-invoking the \fBexpr\fR command.
-.SH "MATH FUNCTIONS"
+the Tcl parser will evaluate both
+.QW \fB[a]\fR
+and
+.QW \fB[b]\fR
+before invoking the \fBexpr\fR command.
+.SS "MATH FUNCTIONS"
.PP
-Tcl supports the following mathematical functions in expressions, all
-of which work solely with floating-point numbers unless otherwise noted:
-.DS
-.ta 3c 6c 9c
-\fBabs\fR \fBcosh\fR \fBlog\fR \fBsqrt\fR
-\fBacos\fR \fBdouble\fR \fBlog10\fR \fBsrand\fR
-\fBasin\fR \fBexp\fR \fBpow\fR \fBtan\fR
-\fBatan\fR \fBfloor\fR \fBrand\fR \fBtanh\fR
-\fBatan2\fR \fBfmod\fR \fBround\fR \fBwide\fR
-\fBceil\fR \fBhypot\fR \fBsin\fR
-\fBcos\fR \fBint\fR \fBsinh\fR
-.DE
+.VS 8.5
+When the expression parser encounters a mathematical function
+such as \fBsin($x)\fR, it replaces it with a call to an ordinary
+Tcl function in the \fBtcl::mathfunc\fR namespace. The processing
+of an expression such as:
+.CS
+\fBexpr {sin($x+$y)}\fR
+.CE
+is the same in every way as the processing of:
+.CS
+\fBexpr {[tcl::mathfunc::sin [expr {$x+$y}]]}\fR
+.CE
+which in turn is the same as the processing of:
+.CS
+\fBtcl::mathfunc::sin [expr {$x+$y}]\fR
+.CE
.PP
-.TP
-\fBabs(\fIarg\fB)\fR
-Returns the absolute value of \fIarg\fR. \fIArg\fR may be either
-integer or floating-point, and the result is returned in the same form.
-.TP
-\fBacos(\fIarg\fB)\fR
-Returns the arc cosine of \fIarg\fR, in the range [\fI0\fR,\fIpi\fR]
-radians. \fIArg\fR should be in the range [\fI-1\fR,\fI1\fR].
-.TP
-\fBasin(\fIarg\fB)\fR
-Returns the arc sine of \fIarg\fR, in the range [\fI-pi/2\fR,\fIpi/2\fR]
-radians. \fIArg\fR should be in the range [\fI-1\fR,\fI1\fR].
-.TP
-\fBatan(\fIarg\fB)\fR
-Returns the arc tangent of \fIarg\fR, in the range [\fI-pi/2\fR,\fIpi/2\fR]
-radians.
-.TP
-\fBatan2(\fIy, x\fB)\fR
-Returns the arc tangent of \fIy\fR/\fIx\fR, in the range [\fI-pi\fR,\fIpi\fR]
-radians. \fIx\fR and \fIy\fR cannot both be 0. If \fIx\fR is greater
-than \fI0\fR, this is equivalent to \fBatan(\fIy/x\fB)\fR.
-.TP
-\fBceil(\fIarg\fB)\fR
-Returns the smallest integral floating-point value (i.e. with a zero
-fractional part) not less than \fIarg\fR.
-.TP
-\fBcos(\fIarg\fB)\fR
-Returns the cosine of \fIarg\fR, measured in radians.
-.TP
-\fBcosh(\fIarg\fB)\fR
-Returns the hyperbolic cosine of \fIarg\fR. If the result would cause
-an overflow, an error is returned.
-.TP
-\fBdouble(\fIarg\fB)\fR
-If \fIarg\fR is a floating-point value, returns \fIarg\fR, otherwise converts
-\fIarg\fR to floating-point and returns the converted value.
-.TP
-\fBexp(\fIarg\fB)\fR
-Returns the exponential of \fIarg\fR, defined as \fIe\fR**\fIarg\fR.
-If the result would cause an overflow, an error is returned.
-.TP
-\fBfloor(\fIarg\fB)\fR
-Returns the largest integral floating-point value (i.e. with a zero
-fractional part) not greater than \fIarg\fR.
-.TP
-\fBfmod(\fIx, y\fB)\fR
-Returns the floating-point remainder of the division of \fIx\fR by
-\fIy\fR. If \fIy\fR is 0, an error is returned.
-.TP
-\fBhypot(\fIx, y\fB)\fR
-Computes the length of the hypotenuse of a right-angled triangle
-\fBsqrt(\fIx\fR*\fIx\fR+\fIy\fR*\fIy\fB)\fR.
-.TP
-\fBint(\fIarg\fB)\fR
-.VS 8.4
-If \fIarg\fR is an integer value of the same width as the machine
-word, returns \fIarg\fR, otherwise
-converts \fIarg\fR to an integer (of the same size as a machine word,
-i.e. 32-bits on 32-bit systems, and 64-bits on 64-bit systems) by
-truncation and returns the converted value.
-.VE 8.4
-.TP
-\fBlog(\fIarg\fB)\fR
-Returns the natural logarithm of \fIarg\fR. \fIArg\fR must be a
-positive value.
-.TP
-\fBlog10(\fIarg\fB)\fR
-Returns the base 10 logarithm of \fIarg\fR. \fIArg\fR must be a
-positive value.
-.TP
-\fBpow(\fIx, y\fB)\fR
-Computes the value of \fIx\fR raised to the power \fIy\fR. If \fIx\fR
-is negative, \fIy\fR must be an integer value.
-.TP
-\fBrand()\fR
-Returns a pseudo-random floating-point value in the range (\fI0\fR,\fI1\fR).
-The generator algorithm is a simple linear congruential generator that
-is not cryptographically secure. Each result from \fBrand\fR completely
-determines all future results from subsequent calls to \fBrand\fR, so
-\fBrand\fR should not be used to generate a sequence of secrets, such as
-one-time passwords. The seed of the generator is initialized from the
-internal clock of the machine or may be set with the \fBsrand\fR function.
-.TP
-\fBround(\fIarg\fB)\fR
-If \fIarg\fR is an integer value, returns \fIarg\fR, otherwise converts
-\fIarg\fR to integer by rounding and returns the converted value.
-.TP
-\fBsin(\fIarg\fB)\fR
-Returns the sine of \fIarg\fR, measured in radians.
-.TP
-\fBsinh(\fIarg\fB)\fR
-Returns the hyperbolic sine of \fIarg\fR. If the result would cause
-an overflow, an error is returned.
-.TP
-\fBsqrt(\fIarg\fB)\fR
-Returns the square root of \fIarg\fR. \fIArg\fR must be non-negative.
-.TP
-\fBsrand(\fIarg\fB)\fR
-The \fIarg\fR, which must be an integer, is used to reset the seed for
-the random number generator of \fBrand\fR. Returns the first random
-number (see \fBrand()\fR) from that seed. Each interpreter has its own seed.
-.TP
-\fBtan(\fIarg\fB)\fR
-Returns the tangent of \fIarg\fR, measured in radians.
-.TP
-\fBtanh(\fIarg\fB)\fR
-Returns the hyperbolic tangent of \fIarg\fR.
-.TP
-\fBwide(\fIarg\fB)\fR
-.VS 8.4
-Converts \fIarg\fR to an integer value at least 64-bits wide (by sign-extension
-if \fIarg\fR is a 32-bit number) if it is not one already.
-.VE 8.4
+The executor will search for \fBtcl::mathfunc::sin\fR using the usual
+rules for resolving functions in namespaces. Either
+\fB::tcl::mathfunc::sin\fR or \fB[namespace
+current]::tcl::mathfunc::sin\fR will satisfy the request, and others
+may as well (depending on the current \fBnamespace path\fR setting).
.PP
-In addition to these predefined functions, applications may
-define additional functions using \fBTcl_CreateMathFunc\fR().
-.SH "TYPES, OVERFLOW, AND PRECISION"
+See the \fBmathfunc\fR(n) manual page for the math functions that are
+available by default.
+.VE 8.5
+.SS "TYPES, OVERFLOW, AND PRECISION"
.PP
-All internal computations involving integers are done with the C type
-\fIlong\fR, and all internal computations involving floating-point are
+.VS 8.5
+All internal computations involving integers are done calling on the
+LibTomMath multiple precision integer library as required so that all
+integer calculations are performed exactly. Note that in Tcl releases
+prior to 8.5, integer calculations were performed with one of the C types
+\fIlong int\fR or \fITcl_WideInt\fR, causing implicit range truncation
+in those calculations where values overflowed the range of those types.
+Any code that relied on these implicit truncations will need to explicitly
+add \fBint()\fR or \fBwide()\fR function calls to expressions at the points
+where such truncation is required to take place.
+.VE 8.5
+.PP
+All internal computations involving floating-point are
done with the C type \fIdouble\fR.
When converting a string to floating-point, exponent overflow is
-detected and results in a Tcl error.
-For conversion to integer from string, detection of overflow depends
-on the behavior of some routines in the local C library, so it should
-be regarded as unreliable.
-In any case, integer overflow and underflow are generally not detected
-reliably for intermediate results. Floating-point overflow and underflow
+detected and results in the \fIdouble\fR value of \fBInf\fR or
+\fB\-Inf\fR as appropriate. Floating-point overflow and underflow
are detected to the degree supported by the hardware, which is generally
pretty reliable.
.PP
@@ -344,34 +276,36 @@ For arithmetic computations, integers are used until some
floating-point number is introduced, after which floating-point is used.
For example,
.CS
-\fBexpr 5 / 4\fR
+\fBexpr\fR {5 / 4}
.CE
returns 1, while
.CS
-\fBexpr 5 / 4.0\fR
-\fBexpr 5 / ( [string length "abcd"] + 0.0 )\fR
+\fBexpr\fR {5 / 4.0}
+\fBexpr\fR {5 / ( [string length "abcd"] + 0.0 )}
.CE
both return 1.25.
-Floating-point values are always returned with a ``\fB.\fR''
-or an \fBe\fR so that they will not look like integer values. For
-example,
+Floating-point values are always returned with a
+.QW \fB.\fR
+or an
+.QW \fBe\fR
+so that they will not look like integer values. For example,
.CS
-\fBexpr 20.0/5.0\fR
+\fBexpr\fR {20.0/5.0}
.CE
returns \fB4.0\fR, not \fB4\fR.
-.SH "STRING OPERATIONS"
+.SS "STRING OPERATIONS"
.PP
String values may be used as operands of the comparison operators,
although the expression evaluator tries to do comparisons as integer
or floating-point when it can,
-.VS 8.4
except in the case of the \fBeq\fR and \fBne\fR operators.
-.VE 8.4
If one of the operands of a comparison is a string and the other
-has a numeric value, the numeric operand is converted back to
-a string using the C \fIsprintf\fR format specifier
-\fB%d\fR for integers and \fB%g\fR for floating-point values.
-For example, the commands
+has a numeric value, a canonical string representation of the numeric
+operand value is generated to compare with the string operand.
+Canonical string representation for integer values is a decimal string
+format. Canonical string representation for floating-point values
+is that produced by the \fB%g\fR format specifier of Tcl's
+\fBformat\fR command. For example, the commands
.CS
\fBexpr {"0x03" > "2"}\fR
\fBexpr {"0y" < "0x12"}\fR
@@ -380,14 +314,10 @@ both return 1. The first comparison is done using integer
comparison, and the second is done using string comparison after
the second operand is converted to the string \fB18\fR.
Because of Tcl's tendency to treat values as numbers whenever
-possible, it isn't generally a good idea to use operators like \fB==\fR
+possible, it is not generally a good idea to use operators like \fB==\fR
when you really want string comparison and the values of the
-operands could be arbitrary; it's better in these cases to use
-.VS 8.4
-the \fBeq\fR or \fBne\fR operators, or
-.VE 8.4
-the \fBstring\fR command instead.
-
+operands could be arbitrary; it is better in these cases to use
+the \fBeq\fR or \fBne\fR operators, or the \fBstring\fR command instead.
.SH "PERFORMANCE CONSIDERATIONS"
.PP
Enclose expressions in braces for the best speed and the smallest
@@ -410,7 +340,7 @@ then the \fBexpr\fR command will evaluate the expression \fB$a + 2*4\fR.
Most expressions do not require a second round of substitutions.
Either they are enclosed in braces or, if not,
their variable and command substitutions yield numbers or strings
-that don't themselves require substitutions.
+that do not themselves require substitutions.
However, because a few unbraced expressions
need two rounds of substitutions,
the bytecode compiler must emit
@@ -419,12 +349,18 @@ The most expensive code is required for
unbraced expressions that contain command substitutions.
These expressions must be implemented by generating new code
each time the expression is executed.
+.VS 8.5
+When the expression is unbraced to allow the substitution of a function or
+operator, consider using the commands documented in the \fBmathfunc\fR(n) or
+\fBmathop\fR(n) manual pages directly instead.
+.VE 8.5
.SH EXAMPLES
-Define a procedure that computes an "interesting" mathematical
-function:
+Define a procedure that computes an
+.QW interesting
+mathematical function:
.CS
-proc calc {x y} {
- \fBexpr\fR { ($x*$x - $y*$y) / exp($x*$x + $y*$y) }
+proc tcl::mathfunc::calc {x y} {
+ \fBexpr\fR { ($x**2 - $y**2) / exp($x**2 + $y**2) }
}
.CE
.PP
@@ -461,9 +397,14 @@ Generate a random integer in the range 0..99 inclusive:
.CS
set randNum [\fBexpr\fR { int(100 * rand()) }]
.CE
-
.SH "SEE ALSO"
-array(n), for(n), if(n), string(n), Tcl(n), while(n)
-
+array(n), for(n), if(n), mathfunc(n), mathop(n), namespace(n), proc(n),
+string(n), Tcl(n), while(n)
.SH KEYWORDS
arithmetic, boolean, compare, expression, fuzzy comparison
+.SH COPYRIGHT
+.nf
+Copyright (c) 1993 The Regents of the University of California.
+Copyright (c) 1994-2000 Sun Microsystems Incorporated.
+Copyright (c) 2005 by Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
+.fi
diff --git a/doc/fblocked.n b/doc/fblocked.n
index 08d8054..d8e8af7 100644
--- a/doc/fblocked.n
+++ b/doc/fblocked.n
@@ -24,12 +24,10 @@ characters available for input and no end-of-line sequence, \fBgets\fR
returns an empty string and a subsequent call to \fBfblocked\fR will
return 1.
.PP
-.VS
\fIChannelId\fR must be an identifier for an open channel such as a
Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR),
the return value from an invocation of \fBopen\fR or \fBsocket\fR, or
the result of a channel creation command provided by a Tcl extension.
-.VE
.SH EXAMPLE
The \fBfblocked\fR command is particularly useful when writing network
servers, as it allows you to write your code in a line-by-line style
diff --git a/doc/fconfigure.n b/doc/fconfigure.n
index 11a4c4f..0763232 100644
--- a/doc/fconfigure.n
+++ b/doc/fconfigure.n
@@ -47,7 +47,8 @@ channel can cause the process to block indefinitely.
The value of the option must be a proper boolean value.
Channels are normally in blocking mode; if a channel is placed into
nonblocking mode it will affect the operation of the \fBgets\fR,
-\fBread\fR, \fBputs\fR, \fBflush\fR, and \fBclose\fR commands;
+\fBread\fR, \fBputs\fR, \fBflush\fR, and \fBclose\fR commands by
+allowing them to operate asynchronously;
see the documentation for those commands for details.
For nonblocking mode to work correctly, the application must be
using the Tcl event loop (e.g. by calling \fBTcl_DoOneEvent\fR or
@@ -89,11 +90,14 @@ If a file contains pure binary data (for instance, a JPEG image), the
encoding for the channel should be configured to be \fBbinary\fR. Tcl
will then assign no interpretation to the data in the file and simply read or
write raw bytes. The Tcl \fBbinary\fR command can be used to manipulate this
-byte-oriented data.
+byte-oriented data. It is usually better to set the
+\fB\-translation\fR option to \fBbinary\fR when you want to transfer
+binary data, as this turns off the other automatic interpretations of
+the bytes in the stream as well.
.PP
The default encoding for newly opened channels is the same platform- and
locale-dependent system encoding used for interfacing with the operating
-system.
+system, as returned by \fBencoding system\fR.
.RE
.TP
\fB\-eofchar\fR \fIchar\fR
@@ -114,6 +118,9 @@ channel, a two-element list will always be returned. The default value
for \fB\-eofchar\fR is the empty string in all cases except for files
under Windows. In that case the \fB\-eofchar\fR is Control-z (\ex1a) for
reading and the empty string for writing.
+The acceptable range for \fB\-eofchar\fR values is \ex01 - \ex7f;
+attempting to set \fB\-eofchar\fR to a value outside of this range will
+generate an error.
.TP
\fB\-translation\fR \fImode\fR
.TP
@@ -124,11 +131,11 @@ newline character (\en). However, in actual files and devices the end of
a line may be represented differently on different platforms, or even for
different devices on the same platform. For example, under UNIX newlines
are used in files, whereas carriage-return-linefeed sequences are
-normally used in network connections. On input (i.e., with \fBgets\fP
-and \fBread\fP) the Tcl I/O system automatically translates the external
+normally used in network connections. On input (i.e., with \fBgets\fR
+and \fBread\fR) the Tcl I/O system automatically translates the external
end-of-line representation into newline characters. Upon output (i.e.,
-with \fBputs\fP), the I/O system translates newlines to the external
-end-of-line representation. The default translation mode, \fBauto\fP,
+with \fBputs\fR), the I/O system translates newlines to the external
+end-of-line representation. The default translation mode, \fBauto\fR,
handles all the common cases automatically, but the \fB\-translation\fR
option provides explicit control over the end of line translations.
.RS
@@ -146,25 +153,24 @@ currently supported:
\fBauto\fR
.
As the input translation mode, \fBauto\fR treats any of newline
-(\fBlf\fP), carriage return (\fBcr\fP), or carriage return followed by a
-newline (\fBcrlf\fP) as the end of line representation. The end of line
+(\fBlf\fR), carriage return (\fBcr\fR), or carriage return followed by a
+newline (\fBcrlf\fR) as the end of line representation. The end of line
representation can even change from line-to-line, and all cases are
translated to a newline. As the output translation mode, \fBauto\fR
chooses a platform specific representation; for sockets on all platforms
-Tcl chooses \fBcrlf\fR, for all Unix flavors, it chooses \fBlf\fR, for the
-Macintosh platform it chooses \fBcr\fR and for the various flavors of
-Windows it chooses \fBcrlf\fR. The default setting for
-\fB\-translation\fR is \fBauto\fR for both input and output.
+Tcl chooses \fBcrlf\fR, for all Unix flavors, it chooses \fBlf\fR, and
+for the various flavors of Windows it chooses \fBcrlf\fR. The default
+setting for \fB\-translation\fR is \fBauto\fR for both input and output.
.TP
\fBbinary\fR
.
No end-of-line translations are performed. This is nearly identical to
-\fBlf\fP mode, except that in addition \fBbinary\fP mode also sets the
+\fBlf\fR mode, except that in addition \fBbinary\fR mode also sets the
end-of-file character to the empty string (which disables it) and sets the
encoding to \fBbinary\fR (which disables encoding filtering). See the
description of \fB\-eofchar\fR and \fB\-encoding\fR for more information.
-.PP
.RS
+.PP
Internally, i.e. when it comes to the actual behaviour of the
translator this value \fBis\fR identical to \fBlf\fR and is therefore
reported as such when queried. Even if \fBbinary\fR was used to set
@@ -175,17 +181,17 @@ the translation.
.
The end of a line in the underlying file or device is represented by a
single carriage return character. As the input translation mode,
-\fBcr\fP mode converts carriage returns to newline characters. As the
-output translation mode, \fBcr\fP mode translates newline characters to
-carriage returns. This mode is typically used on Macintosh platforms.
+\fBcr\fR mode converts carriage returns to newline characters. As the
+output translation mode, \fBcr\fR mode translates newline characters to
+carriage returns.
.TP
\fBcrlf\fR
.
The end of a line in the underlying file or device is represented by a
carriage return character followed by a linefeed character. As the input
-translation mode, \fBcrlf\fP mode converts carriage-return-linefeed
+translation mode, \fBcrlf\fR mode converts carriage-return-linefeed
sequences to newline characters. As the output translation mode,
-\fBcrlf\fP mode translates newline characters to carriage-return-linefeed
+\fBcrlf\fR mode translates newline characters to carriage-return-linefeed
sequences. This mode is typically used on Windows platforms and for
network connections.
.TP
@@ -251,12 +257,12 @@ set words {}
while {[llength $words] < 3} {
gets $f line
if {[string match "#*" $line]} continue
- lappend words [eval concat [scan $line %d%d%d]]
+ lappend words {*}[join [scan $line %d%d%d]]
}
# Those words supply the size of the image and its
# overall depth per channel. Assign to variables.
-foreach {xSize ySize depth} $words {break}
+lassign $words xSize ySize depth
# Now switch to binary mode to pull in the data,
# one byte per channel (red,green,blue) per pixel.
diff --git a/doc/fcopy.n b/doc/fcopy.n
index 3702f15..d583cf0 100644
--- a/doc/fcopy.n
+++ b/doc/fcopy.n
@@ -10,54 +10,56 @@
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
-fcopy \- Copy data from one channel to another.
+fcopy \- Copy data from one channel to another
.SH SYNOPSIS
\fBfcopy \fIinchan\fR \fIoutchan\fR ?\fB\-size \fIsize\fR? ?\fB\-command \fIcallback\fR?
.BE
.SH DESCRIPTION
.PP
-The \fBfcopy\fP command copies data from one I/O channel, \fIinchan\fR to another I/O channel, \fIoutchan\fR.
-The \fBfcopy\fP command leverages the buffering in the Tcl I/O system to
+The \fBfcopy\fR command copies data from one I/O channel, \fIinchan\fR to another I/O channel, \fIoutchan\fR.
+The \fBfcopy\fR command leverages the buffering in the Tcl I/O system to
avoid extra copies and to avoid buffering too much data in
main memory when copying large files to slow destinations like
network sockets.
.PP
-The \fBfcopy\fP
+The \fBfcopy\fR
command transfers data from \fIinchan\fR until end of file
-or \fIsize\fP bytes have been
-transferred. If no \fB\-size\fP argument is given,
+or \fIsize\fR bytes have been
+transferred. If no \fB\-size\fR argument is given,
then the copy goes until end of file.
All the data read from \fIinchan\fR is copied to \fIoutchan\fR.
-Without the \fB\-command\fP option, \fBfcopy\fP blocks until the copy is complete
+Without the \fB\-command\fR option, \fBfcopy\fR blocks until the copy is complete
and returns the number of bytes written to \fIoutchan\fR.
.PP
-The \fB\-command\fP argument makes \fBfcopy\fP work in the background.
-In this case it returns immediately and the \fIcallback\fP is invoked
+The \fB\-command\fR argument makes \fBfcopy\fR work in the background.
+In this case it returns immediately and the \fIcallback\fR is invoked
later when the copy completes.
-The \fIcallback\fP is called with
+The \fIcallback\fR is called with
one or two additional
arguments that indicates how many bytes were written to \fIoutchan\fR.
If an error occurred during the background copy, the second argument is the
error string associated with the error.
With a background copy,
it is not necessary to put \fIinchan\fR or \fIoutchan\fR into
-non-blocking mode; the \fBfcopy\fP command takes care of that automatically.
+non-blocking mode; the \fBfcopy\fR command takes care of that automatically.
However, it is necessary to enter the event loop by using
-the \fBvwait\fP command or by using Tk.
+the \fBvwait\fR command or by using Tk.
.PP
You are not allowed to do other I/O operations with
-\fIinchan\fR or \fIoutchan\fR during a background fcopy.
+\fIinchan\fR or \fIoutchan\fR during a background \fBfcopy\fR.
If either \fIinchan\fR or \fIoutchan\fR get closed
while the copy is in progress, the current copy is stopped
-and the command callback is \fInot\fP made.
+and the command callback is \fInot\fR made.
If \fIinchan\fR is closed,
then all data already queued for \fIoutchan\fR is written out.
.PP
Note that \fIinchan\fR can become readable during a background copy.
-You should turn off any \fBfileevent\fP handlers during a background
+You should turn off any \fBfileevent\fR handlers during a background
copy so those handlers do not interfere with the copy.
-Any I/O attempted by a \fBfileevent\fP handler will get a "channel busy" error.
+Any I/O attempted by a \fBfileevent\fR handler will get a
+.QW "channel busy"
+error.
.PP
\fBFcopy\fR translates end-of-line sequences in \fIinchan\fR and \fIoutchan\fR
according to the \fB\-translation\fR option
@@ -67,30 +69,46 @@ See the manual entry for \fBfconfigure\fR for details on the
The translations mean that the number of bytes read from \fIinchan\fR
can be different than the number of bytes written to \fIoutchan\fR.
Only the number of bytes written to \fIoutchan\fR is reported,
-either as the return value of a synchronous \fBfcopy\fP or
-as the argument to the callback for an asynchronous \fBfcopy\fP.
+either as the return value of a synchronous \fBfcopy\fR or
+as the argument to the callback for an asynchronous \fBfcopy\fR.
.PP
-\fBFcopy\fR obeys the encodings configured for the channels. This
+\fBFcopy\fR obeys the encodings and character translations configured
+for the channels. This
means that the incoming characters are converted internally first
UTF-8 and then into the encoding of the channel \fBfcopy\fR writes
to. See the manual entry for \fBfconfigure\fR for details on the
-\fB\-encoding\fR option. No conversion is done if both channels are
-set to encoding "binary". If only the output channel is set to
-encoding "binary" the system will write the internal UTF-8
-representation of the incoming characters. If only the input channel
-is set to encoding "binary" the system will assume that the incoming
+\fB\-encoding\fR and \fB\-translation\fR options. No conversion is
+done if both channels are
+set to encoding
+.QW binary
+and have matching translations. If only the output channel is set to encoding
+.QW binary
+the system will write the internal UTF-8 representation of the incoming
+characters. If only the input channel is set to encoding
+.QW binary
+the system will assume that the incoming
bytes are valid UTF-8 characters and convert them according to the
output encoding. The behaviour of the system for bytes which are not
valid UTF-8 characters is undefined in this case.
-.SH EXAMPLE
+.SH EXAMPLES
.PP
-This first example shows how the callback gets
+The first example transfers the contents of one channel exactly to
+another. Note that when copying one file to another, it is better to
+use \fBfile copy\fR which also copies file metadata (e.g. the file
+access permissions) where possible.
+.CS
+fconfigure $in -translation binary
+fconfigure $out -translation binary
+\fBfcopy\fR $in $out
+.CE
+.PP
+This second example shows how the callback gets
passed the number of bytes transferred.
It also uses vwait to put the application into the event loop.
Of course, this simplified example could be done without the command
callback.
-.DS
+.CS
proc Cleanup {in out bytes {error {}}} {
global total
set total $bytes
@@ -102,14 +120,13 @@ proc Cleanup {in out bytes {error {}}} {
}
set in [open $file1]
set out [socket $server $port]
-fcopy $in $out -command [list Cleanup $in $out]
+\fBfcopy\fR $in $out -command [list Cleanup $in $out]
vwait total
-
-.DE
+.CE
.PP
-The second example copies in chunks and tests for end of file
+The third example copies in chunks and tests for end of file
in the command callback
-.DS
+.CS
proc CopyMore {in out chunk bytes {error {}}} {
global total done
incr total $bytes
@@ -118,21 +135,21 @@ proc CopyMore {in out chunk bytes {error {}}} {
close $in
close $out
} else {
- fcopy $in $out -command [list CopyMore $in $out $chunk] \\
- -size $chunk
+ \fBfcopy\fR $in $out -size $chunk \e
+ -command [list CopyMore $in $out $chunk]
}
}
set in [open $file1]
set out [socket $server $port]
set chunk 1024
set total 0
-fcopy $in $out -command [list CopyMore $in $out $chunk] -size $chunk
+\fBfcopy\fR $in $out -size $chunk \e
+ -command [list CopyMore $in $out $chunk]
vwait done
-
-.DE
+.CE
.SH "SEE ALSO"
-eof(n), fblocked(n), fconfigure(n)
+eof(n), fblocked(n), fconfigure(n), file(n)
.SH KEYWORDS
blocking, channel, end of line, end of file, nonblocking, read, translation
diff --git a/doc/file.n b/doc/file.n
index bc9eccc..b62d252 100644
--- a/doc/file.n
+++ b/doc/file.n
@@ -14,7 +14,6 @@ file \- Manipulate file names and attributes
.SH SYNOPSIS
\fBfile \fIoption\fR \fIname\fR ?\fIarg arg ...\fR?
.BE
-
.SH DESCRIPTION
.PP
This command provides several operations on a file's name or attributes.
@@ -30,7 +29,7 @@ Returns a decimal string giving the time at which file \fIname\fR was last
accessed. If \fItime\fR is specified, it is an access time to set
for the file. The time is measured in the standard POSIX fashion as
seconds from a fixed starting time (often January 1, 1970). If the file
-doesn't exist or its access time cannot be queried or set then an error is
+does not exist or its access time cannot be queried or set then an error is
generated. On Windows, FAT file systems do not support access time.
.TP
\fBfile attributes \fIname\fR
@@ -38,18 +37,19 @@ generated. On Windows, FAT file systems do not support access time.
\fBfile attributes \fIname\fR ?\fBoption\fR?
.TP
\fBfile attributes \fIname\fR ?\fBoption value option value...\fR?
-.RS
+.
This subcommand returns or sets platform specific values associated
with a file. The first form returns a list of the platform specific
flags and their values. The second form returns the value for the
specific option. The third form sets one or more of the values. The
values are as follows:
+.RS
.PP
-On Unix, \fB-group\fR gets or sets the group name for the file. A group id
-can be given to the command, but it returns a group name. \fB-owner\fR gets
+On Unix, \fB\-group\fR gets or sets the group name for the file. A group id
+can be given to the command, but it returns a group name. \fB\-owner\fR gets
or sets the user name of the owner of the file. The command returns the
owner name, but the numerical id can be passed when setting the
-owner. \fB-permissions\fR sets or retrieves the octal code that chmod(1)
+owner. \fB\-permissions\fR sets or retrieves the octal code that chmod(1)
uses. This command does also has limited support for setting using the
symbolic attributes for chmod(1), of the form [ugo]?[[+\-=][rwxst],[...]],
where multiple symbolic attributes can be separated by commas (example:
@@ -57,45 +57,49 @@ where multiple symbolic attributes can be separated by commas (example:
permissions for group and other). A simplified \fBls\fR style string,
of the form rwxrwxrwx (must be 9 characters), is also supported
(example: \fBrwxr\-xr\-t\fR is equivalent to 01755).
+On versions of Unix supporting file flags, \fB\-readonly\fR gives the
+value or sets or clears the readonly attribute of the file,
+i.e. the user immutable flag \fBuchg\fR to chflags(1).
.PP
-On Windows, \fB-archive\fR gives the value or sets or clears the
-archive attribute of the file. \fB-hidden\fR gives the value or sets
-or clears the hidden attribute of the file. \fB-longname\fR will
+On Windows, \fB\-archive\fR gives the value or sets or clears the
+archive attribute of the file. \fB\-hidden\fR gives the value or sets
+or clears the hidden attribute of the file. \fB\-longname\fR will
expand each path element to its long version. This attribute cannot be
-set. \fB-readonly\fR gives the value or sets or clears the readonly
-attribute of the file. \fB-shortname\fR gives a string where every
+set. \fB\-readonly\fR gives the value or sets or clears the readonly
+attribute of the file. \fB\-shortname\fR gives a string where every
path element is replaced with its short (8.3) version of the
-name. This attribute cannot be set. \fB-system\fR gives or sets or
+name. This attribute cannot be set. \fB\-system\fR gives or sets or
clears the value of the system attribute of the file.
.PP
-On Macintosh, \fB-creator\fR gives or sets the Finder creator type of
-the file. \fB-hidden\fR gives or sets or clears the hidden attribute
-of the file. \fB-readonly\fR gives or sets or clears the readonly
-attribute of the file. Note that directories can only be locked if
-File Sharing is turned on. \fB-type\fR gives or sets the Finder file
-type for the file.
+On Mac OS X and Darwin, \fB\-creator\fR gives or sets the
+Finder creator type of the file. \fB\-hidden\fR gives or sets or clears
+the hidden attribute of the file. \fB\-readonly\fR gives or sets or
+clears the readonly attribute of the file. \fB\-rsrclength\fR gives
+the length of the resource fork of the file, this attribute can only be
+set to the value 0, which results in the resource fork being stripped
+off the file.
.RE
-.VS
.TP
\fBfile channels ?\fIpattern\fR?
.
-If \fIpattern\fR isn't specified, returns a list of names of all
+If \fIpattern\fR is not specified, returns a list of names of all
registered open channels in this interpreter. If \fIpattern\fR is
specified, only those names matching \fIpattern\fR are returned. Matching
is determined using the same rules as for \fBstring match\fR.
-.VE
.TP
\fBfile copy \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource\fR \fItarget\fR
.TP
\fBfile copy \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource\fR ?\fIsource\fR ...? \fItargetDir\fR
-.RS
+.
The first form makes a copy of the file or directory \fIsource\fR under
the pathname \fItarget\fR. If \fItarget\fR is an existing directory,
then the second form is used. The second form makes a copy inside
\fItargetDir\fR of each \fIsource\fR file listed. If a directory is
specified as a \fIsource\fR, then the contents of the directory will be
recursively copied into \fItargetDir\fR. Existing files will not be
-overwritten unless the \fB\-force\fR option is specified. When copying
+overwritten unless the \fB\-force\fR option is specified (when Tcl will
+also attempt to adjust permissions on the destination file or directory
+if that is necessary to allow the copy to proceed). When copying
within a single filesystem, \fIfile copy\fR will copy soft links (i.e.
the links themselves are copied, not the things they point to). Trying
to overwrite a non-empty directory, overwrite a directory with a file,
@@ -104,7 +108,6 @@ or overwrite a file with a directory will all result in errors even if
specified, halting at the first error, if any. A \fB\-\|\-\fR marks
the end of switches; the argument following the \fB\-\|\-\fR will be
treated as a \fIsource\fR even if it starts with a \fB\-\fR.
-.RE
.TP
\fBfile delete \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIpathname\fR ?\fIpathname\fR ... ?
.
@@ -116,9 +119,11 @@ Trying to delete a non-existent file is not considered an error.
Trying to delete a read-only file will cause the file to be deleted,
even if the \fB\-force\fR flags is not specified. If the \fB\-force\fR
option is specified on a directory, Tcl will attempt both to change
-permissions and move the current directory 'pwd' out of the given path
-if that is necessary to allow the deletion to proceed. Arguments are
-processed in the order specified, halting at the first error, if any.
+permissions and move the current directory
+.QW pwd
+out of the given path if that is necessary to allow the deletion to
+proceed. Arguments are processed in the order specified, halting at
+the first error, if any.
A \fB\-\|\-\fR marks the end of switches; the argument following the
\fB\-\|\-\fR will be treated as a \fIpathname\fR even if it starts with
a \fB\-\fR.
@@ -126,9 +131,10 @@ a \fB\-\fR.
\fBfile dirname \fIname\fR
Returns a name comprised of all of the path components in \fIname\fR
excluding the last element. If \fIname\fR is a relative file name and
-only contains one path element, then returns ``\fB.\fR'' (or ``\fB:\fR''
-on the Macintosh). If \fIname\fR refers to a root directory, then the
-root directory is returned. For example,
+only contains one path element, then returns
+.QW \fB.\fR .
+If \fIname\fR refers to a root directory, then the root directory is
+returned. For example,
.RS
.CS
\fBfile dirname c:/\fR
@@ -186,39 +192,53 @@ returns \fB/foo/bar\fR.
.PP
Note that any of the names can contain separators, and that the result
is always canonical for the current platform: \fB/\fR for Unix and
-Windows, and \fB:\fR for Macintosh.
+Windows.
.RE
.TP
-\fBfile link ?\fI-linktype\fR? \fIlinkName\fR ?\fItarget\fR?
+\fBfile link ?\fI\-linktype\fR? \fIlinkName\fR ?\fItarget\fR?
.
If only one argument is given, that argument is assumed to be
\fIlinkName\fR, and this command returns the value of the link given by
\fIlinkName\fR (i.e. the name of the file it points to). If
-\fIlinkName\fR isn't a link or its value cannot be read (as, for example,
+\fIlinkName\fR is not a link or its value cannot be read (as, for example,
seems to be the case with hard links, which look just like ordinary
files), then an error is returned.
-.
+.RS
+.PP
If 2 arguments are given, then these are assumed to be \fIlinkName\fR
and \fItarget\fR. If \fIlinkName\fR already exists, or if \fItarget\fR
-doesn't exist, an error will be returned. Otherwise, Tcl creates a new
-link called \fIlinkName\fR which points to the existing filesystem object
-at \fItarget\fR, where the type of the link is platform-specific (on Unix
-a symbolic link will be the default). This is useful for the case where
-the user wishes to create a link in a cross-platform way, and doesn't
-care what type of link is created.
-.
+does not exist, an error will be returned. Otherwise, Tcl creates a new
+link called \fIlinkName\fR which points to the existing filesystem
+object at \fItarget\fR (which is also the returned value), where the
+type of the link is platform-specific (on Unix a symbolic link will be
+the default). This is useful for the case where the user wishes to
+create a link in a cross-platform way, and does not care what type of
+link is created.
+.PP
If the user wishes to make a link of a specific type only, (and signal an
error if for some reason that is not possible), then the optional
-\fI-linktype\fR argument should be given. Accepted values for
-\fI-linktype\fR are "-symbolic" and "-hard".
-.
-When creating links on filesystems that either do not support any links,
-or do not support the specific type requested, an error message will be
-returned. In particular Windows 95, 98 and ME do not support any links
-at present, but most Unix platforms support both symbolic and hard links
-(the latter for files only), MacOS supports symbolic links and Windows
-NT/2000/XP (on NTFS drives) support symbolic directory links and hard
-file links.
+\fI\-linktype\fR argument should be given. Accepted values for
+\fI\-linktype\fR are
+.QW \-symbolic
+and
+.QW \-hard .
+.PP
+On Unix, symbolic links can be made to relative paths, and those paths
+must be relative to the actual \fIlinkName\fR's location (not to the
+cwd), but on all other platforms where relative links are not supported,
+target paths will always be converted to absolute, normalized form
+before the link is created (and therefore relative paths are interpreted
+as relative to the cwd). Furthermore,
+.QW ~user
+paths are always expanded
+to absolute form. When creating links on filesystems that either do not
+support any links, or do not support the specific type requested, an
+error message will be returned. In particular Windows 95, 98 and ME do
+not support any links at present, but most Unix platforms support both
+symbolic and hard links (the latter for files only) and Windows
+NT/2000/XP (on NTFS drives) support symbolic
+directory links and hard file links.
+.RE
.TP
\fBfile lstat \fIname varName\fR
.
@@ -226,7 +246,7 @@ Same as \fBstat\fR option (see below) except uses the \fIlstat\fR
kernel call instead of \fIstat\fR. This means that if \fIname\fR
refers to a symbolic link the information returned in \fIvarName\fR
is for the link rather than the file it refers to. On systems that
-don't support symbolic links this option behaves exactly the same
+do not support symbolic links this option behaves exactly the same
as the \fBstat\fR option.
.TP
\fBfile mkdir \fIdir\fR ?\fIdir\fR ...?
@@ -244,32 +264,35 @@ Returns a decimal string giving the time at which file \fIname\fR was last
modified. If \fItime\fR is specified, it is a modification time to set for
the file (equivalent to Unix \fBtouch\fR). The time is measured in the
standard POSIX fashion as seconds from a fixed starting time (often January
-1, 1970). If the file doesn't exist or its modified time cannot be queried
+1, 1970). If the file does not exist or its modified time cannot be queried
or set then an error is generated.
.TP
\fBfile nativename \fIname\fR
.
Returns the platform-specific name of the file. This is useful if the
-filename is needed to pass to a platform-specific call, such as exec
-under Windows or AppleScript on the Macintosh.
+filename is needed to pass to a platform-specific call, such as to a
+subprocess via \fBexec\fR under Windows (see \fBEXAMPLES\fR below).
.TP
\fBfile normalize \fIname\fR
.
-.RS
Returns a unique normalized path representation for the file-system
object (file, directory, link, etc), whose string value can be used as a
unique identifier for it. A normalized path is an absolute path which has
-all '../', './' removed. Also it is one which is in the ``standard''
-format for the native platform. On MacOS, Unix, this means the segments
+all
+.QW ../
+and
+.QW ./
+removed. Also it is one which is in the
+.QW standard
+format for the native platform. On Unix, this means the segments
leading up to the path must be free of symbolic links/aliases (but the
very last path component may be a symbolic link), and on Windows it also
means we want the long form with that form's case-dependence (which
gives us a unique, case-dependent path). The one exception concerning the
last link in the path is necessary, because Tcl or the user may wish to
-operate on the actual symbolic link itself (for example 'file delete', 'file
-rename', 'file copy' are defined to operate on symbolic links, not on the
-things that they point to).
-.RE
+operate on the actual symbolic link itself (for example \fBfile delete\fR,
+\fBfile rename\fR, \fBfile copy\fR are defined to operate on symbolic
+links, not on the things that they point to).
.TP
\fBfile owned \fIname\fR
.
@@ -278,13 +301,13 @@ otherwise.
.TP
\fBfile pathtype \fIname\fR
.
-Returns one of \fBabsolute\fR, \fBrelative\fR, \fBvolumerelative\fR. If
-\fIname\fR refers to a specific file on a specific volume, the path type
-will be \fBabsolute\fR. If \fIname\fR refers to a file relative to the
-current working directory, then the path type will be \fBrelative\fR. If
-\fIname\fR refers to a file relative to the current working directory on
-a specified volume, or to a specific file on the current working volume, then
-the path type is \fBvolumerelative\fR.
+Returns one of \fBabsolute\fR, \fBrelative\fR, \fBvolumerelative\fR. If
+\fIname\fR refers to a specific file on a specific volume, the path type will
+be \fBabsolute\fR. If \fIname\fR refers to a file relative to the current
+working directory, then the path type will be \fBrelative\fR. If \fIname\fR
+refers to a file relative to the current working directory on a specified
+volume, or to a specific file on the current working volume, then the path
+type is \fBvolumerelative\fR.
.TP
\fBfile readable \fIname\fR
.
@@ -294,14 +317,14 @@ Returns \fB1\fR if file \fIname\fR is readable by the current user,
\fBfile readlink \fIname\fR
.
Returns the value of the symbolic link given by \fIname\fR (i.e. the name
-of the file it points to). If \fIname\fR isn't a symbolic link or its
-value cannot be read, then an error is returned. On systems that don't
+of the file it points to). If \fIname\fR is not a symbolic link or its
+value cannot be read, then an error is returned. On systems that do not
support symbolic links this option is undefined.
.TP
\fBfile rename \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource\fR \fItarget\fR
.TP
\fBfile rename \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource\fR ?\fIsource\fR ...? \fItargetDir\fR
-.RS
+.
The first form takes the file or directory specified by pathname
\fIsource\fR and renames it to \fItarget\fR, moving the file if the
pathname \fItarget\fR specifies a name in a different directory. If
@@ -316,13 +339,14 @@ result in errors. Arguments are processed in the order specified,
halting at the first error, if any. A \fB\-\|\-\fR marks the end of
switches; the argument following the \fB\-\|\-\fR will be treated as a
\fIsource\fR even if it starts with a \fB\-\fR.
-.RE
.TP
\fBfile rootname \fIname\fR
.
Returns all of the characters in \fIname\fR up to but not including the
-last ``.'' character in the last component of name. If the last
-component of \fIname\fR doesn't contain a dot, then returns \fIname\fR.
+last
+.QW .
+character in the last component of name. If the last
+component of \fIname\fR does not contain a dot, then returns \fIname\fR.
.TP
\fBfile separator\fR ?\fIname\fR?
.
@@ -335,7 +359,7 @@ is generated.
\fBfile size \fIname\fR
.
Returns a decimal string giving the size of file \fIname\fR in bytes. If
-the file doesn't exist or its size cannot be queried then an error is
+the file does not exist or its size cannot be queried then an error is
generated.
.TP
\fBfile split \fIname\fR
@@ -343,7 +367,7 @@ generated.
Returns a list whose elements are the path components in \fIname\fR. The
first element of the list will have the same path type as \fIname\fR.
All other elements will be relative. Path separators will be discarded
-unless they are needed ensure that an element is unambiguously relative.
+unless they are needed to ensure that an element is unambiguously relative.
For example, under Unix
.RS
.CS
@@ -370,24 +394,32 @@ empty string.
.TP
\fBfile system \fIname\fR
.
-Returns a list of two elements, the first of which is the name of the
-filesystem to use for the file, and the second an arbitrary string
-representing the filesystem-specific nature or type of the location
-within that filesystem. If a filesystem only supports one type of file,
-the second element may be null. For example the native files have a
-first element 'native', and a second element which is a platform-specific
-type name for the file's system (e.g. 'NTFS', 'FAT', etc), or possibly
-the empty string if no further information is available or if this
-is not implemented. A generic virtual file system might return the
-list 'vfs ftp' to represent a file on a remote ftp site mounted as a
-virtual filesystem through an extension called 'vfs'. If the file does
-not belong to any filesystem, an error is generated.
+Returns a list of one or two elements, the first of which is the name of
+the filesystem to use for the file, and the second, if given, an
+arbitrary string representing the filesystem-specific nature or type of
+the location within that filesystem. If a filesystem only supports one
+type of file, the second element may not be supplied. For example the
+native files have a first element
+.QW native ,
+and a second element which when given is a platform-specific type name
+for the file's system (e.g.
+.QW NTFS ,
+.QW FAT ,
+on Windows). A generic virtual file system might return
+the list
+.QW "vfs ftp"
+to represent a file on a remote ftp site mounted as a
+virtual filesystem through an extension called
+.QW vfs .
+If the file does not belong to any filesystem, an error is generated.
.TP
\fBfile tail \fIname\fR
.
-Returns all of the characters in \fIname\fR after the last directory
-separator. If \fIname\fR contains no separators then returns
-\fIname\fR.
+Returns all of the characters in the last filesystem component of
+\fIname\fR. Any trailing directory separator in \fIname\fR is ignored.
+If \fIname\fR contains no separators then returns \fIname\fR. So,
+\fBfile tail a/b\fR, \fBfile tail a/b/\fR and \fBfile tail b\fR all
+return \fBb\fR.
.TP
\fBfile type \fIname\fR
.
@@ -398,13 +430,15 @@ Returns a string giving the type of file \fIname\fR, which will be one of
\fBfile volumes\fR
.
Returns the absolute paths to the volumes mounted on the system, as a
-proper Tcl list. On the Macintosh, this will be a list of the mounted
-drives, both local and network. N.B. if two drives have the same name,
-they will both appear on the volume list, but there is currently no way,
-from Tcl, to access any but the first of these drives. On UNIX, the
-command will always return "/", since all filesystems are locally mounted.
+proper Tcl list. Without any virtual filesystems mounted as root
+volumes, on UNIX, the command will always return
+.QW / ,
+since all filesystems are locally mounted.
On Windows, it will return a list of the available local drives
-(e.g. {a:/ c:/}).
+(e.g.
+.QW "a:/ c:/" ).
+If any virtual filesystem has mounted additional
+volumes, they will be in the returned list.
.TP
\fBfile writable \fIname\fR
.
@@ -431,7 +465,7 @@ proc findMatchingCFiles {dir} {
set ext .o
}
}
- foreach file [glob -nocomplain -directory $dir *.c] {
+ foreach file [glob \-nocomplain \-directory $dir *.c] {
set objectFile [\fBfile tail\fR [\fBfile rootname\fR $file]]$ext
if {[\fBfile exists\fR $objectFile]} {
lappend files $file
@@ -451,12 +485,19 @@ if {![\fBfile isdirectory\fR [\fBfile dirname\fR $newName]]} {
\fBfile mkdir\fR [\fBfile dirname\fR $newName]
}
\fBfile rename\fR $oldName $newName
-\fBfile link\fR -symbolic $oldName $newName
+\fBfile link\fR \-symbolic $oldName $newName
+.CE
+.PP
+On Windows, a file can be
+.QW started
+easily enough (equivalent to double-clicking on it in the Explorer
+interface) but the name passed to the operating system must be in
+native format:
+.CS
+exec {*}[auto_execok start] {} [\fBfile nativename\fR ~/example.txt]
.CE
-
.SH "SEE ALSO"
filename(n), open(n), close(n), eof(n), gets(n), tell(n), seek(n),
fblocked(n), flush(n)
-
.SH KEYWORDS
attributes, copy files, delete files, directory, file, move files, name, rename files, stat
diff --git a/doc/fileevent.n b/doc/fileevent.n
index 99fe43a..eb555f5 100644
--- a/doc/fileevent.n
+++ b/doc/fileevent.n
@@ -28,17 +28,17 @@ interact with the user while waiting for the data to arrive. If an
application invokes \fBgets\fR or \fBread\fR on a blocking channel when
there is no input data available, the process will block; until the input
data arrives, it will not be able to service other events, so it will
-appear to the user to ``freeze up''. With \fBfileevent\fR, the process can
+appear to the user to
+.QW "freeze up" .
+With \fBfileevent\fR, the process can
tell when data is present and only invoke \fBgets\fR or \fBread\fR when
-they won't block.
+they will not block.
.PP
-.VS
The \fIchannelId\fR argument to \fBfileevent\fR refers to an open
channel such as a Tcl standard channel (\fBstdin\fR, \fBstdout\fR,
or \fBstderr\fR), the return value from an invocation of \fBopen\fR
or \fBsocket\fR, or the result of a channel creation command provided
by a Tcl extension.
-.VE
.PP
If the \fIscript\fR argument is specified, then \fBfileevent\fR
creates a new event handler: \fIscript\fR will be evaluated
@@ -94,7 +94,7 @@ The script for a file event is executed at global level (outside the
context of any Tcl procedure) in the interpreter in which the
\fBfileevent\fR command was invoked.
If an error occurs while executing the script then the
-\fBbgerror\fR mechanism is used to report the error.
+command registered with \fBinterp bgerror\fR is used to report the error.
In addition, the file event handler is deleted if it ever returns
an error; this is done in order to prevent infinite loops due to
buggy handlers.
@@ -117,7 +117,7 @@ proc GetData {chan} {
by Mark Diekhans.
.SH "SEE ALSO"
-bgerror(n), fconfigure(n), gets(n), puts(n), read(n), Tcl_StandardChannels(3)
+fconfigure(n), gets(n), interp(n), puts(n), read(n), Tcl_StandardChannels(3)
.SH KEYWORDS
asynchronous I/O, blocking, channel, event handler, nonblocking, readable,
diff --git a/doc/filename.n b/doc/filename.n
index b588440..1fe22f0 100644
--- a/doc/filename.n
+++ b/doc/filename.n
@@ -23,7 +23,6 @@ to be portable should not assume a particular form for file names.
Instead, portable scripts must use the \fBfile split\fR and \fBfile
join\fR commands to manipulate file names (see the \fBfile\fR manual
entry for more details).
-
.SH "PATH TYPES"
.PP
File names are grouped into three general types based on the starting point
@@ -36,76 +35,26 @@ qualified, either giving the path relative to the root directory on the
current volume, or relative to the current directory of the specified
volume. The \fBfile pathtype\fR command can be used to determine the
type of a given path.
-
.SH "PATH SYNTAX"
.PP
The rules for native names depend on the value reported in the Tcl
array element \fBtcl_platform(platform)\fR:
.TP 10
-\fBmac\fR
-On Apple Macintosh systems, Tcl supports two forms of path names. The
-normal Mac style names use colons as path separators. Paths may be
-relative or absolute, and file names may contain any character other
-than colon. A leading colon causes the rest of the path to be
-interpreted relative to the current directory. If a path contains a
-colon that is not at the beginning, then the path is interpreted as an
-absolute path. Sequences of two or more colons anywhere in the path
-are used to construct relative paths where \fB::\fR refers to the
-parent of the current directory, \fB:::\fR refers to the parent of the
-parent, and so forth.
+\fBUnix\fR
+On Unix and Apple MacOS X platforms, Tcl uses path names where the
+components are separated by slashes. Path names may be relative or
+absolute, and file names may contain any character other than slash.
+The file names \fB\&.\fR and \fB\&..\fR are special and refer to the
+current directory and the parent of the current directory respectively.
+Multiple adjacent slash characters are interpreted as a single
+separator. Any number of trailing slash characters at the end of a
+path are simply ignored, so the paths \fBfoo\fR, \fBfoo/\fR and
+\fBfoo//\fR are all identical, and in particular \fBfoo/\fR does not
+necessarily mean a directory is being referred.
.RS
.PP
-In addition to Macintosh style names, Tcl also supports a subset of
-Unix-like names. If a path contains no colons, then it is interpreted
-like a Unix path. Slash is used as the path separator. The file name
-\fB\&.\fR refers to the current directory, and \fB\&..\fR refers to the
-parent of the current directory. However, some names like \fB/\fR or
-\fB/..\fR have no mapping, and are interpreted as Macintosh names. In
-general, commands that generate file names will return Macintosh style
-names, but commands that accept file names will take both Macintosh
-and Unix-style names.
-.PP
-The following examples illustrate various forms of path names:
-.TP 15
-\fB:\fR
-Relative path to the current folder.
-.TP 15
-\fBMyFile\fR
-Relative path to a file named \fBMyFile\fR in the current folder.
-.TP 15
-\fBMyDisk:MyFile\fR
-Absolute path to a file named \fBMyFile\fR on the device named \fBMyDisk\fR.
-.TP 15
-\fB:MyDir:MyFile\fR
-Relative path to a file name \fBMyFile\fR in a folder named
-\fBMyDir\fR in the current folder.
-.TP 15
-\fB::MyFile\fR
-Relative path to a file named \fBMyFile\fR in the folder above the
-current folder.
-.TP 15
-\fB:::MyFile\fR
-Relative path to a file named \fBMyFile\fR in the folder two levels above the
-current folder.
-.TP 15
-\fB/MyDisk/MyFile\fR
-Absolute path to a file named \fBMyFile\fR on the device named
-\fBMyDisk\fR.
-.TP 15
-\fB\&../MyFile\fR
-Relative path to a file named \fBMyFile\fR in the folder above the
-current folder.
-.RE
-.TP
-\fBunix\fR
-On Unix platforms, Tcl uses path names where the components are
-separated by slashes. Path names may be relative or absolute, and
-file names may contain any character other than slash. The file names
-\fB\&.\fR and \fB\&..\fR are special and refer to the current directory
-and the parent of the current directory respectively. Multiple
-adjacent slash characters are interpreted as a single separator.
-The following examples illustrate various forms of path names:
-.RS
+The following examples illustrate various forms of path
+names:
.TP 15
\fB/\fR
Absolute path to the root directory.
@@ -129,7 +78,7 @@ Relative path to the file \fBfoo\fR in the directory above the current
directory.
.RE
.TP
-\fBwindows\fR
+\fBWindows\fR
On Microsoft Windows platforms, Tcl supports both drive-relative and UNC
style names. Both \fB/\fR and \fB\e\fR may be used as directory separators
in either type of name. Drive-relative names consist of an optional drive
@@ -169,37 +118,39 @@ Volume-relative path to a file \fBfoo\fR in the root directory of the current
volume. This is not a valid UNC path, so the assumption is that the
extra backslashes are superfluous.
.RE
-
.SH "TILDE SUBSTITUTION"
.PP
In addition to the file name rules described above, Tcl also supports
-\fIcsh\fR-style tilde substitution. If a file name starts with a
-tilde, then the file name will be interpreted as if the first element
-is replaced with the location of the home directory for the given
-user. If the tilde is followed immediately by a separator, then the
-\fB$HOME\fR environment variable is substituted. Otherwise the
-characters between the tilde and the next separator are taken as a
-user name, which is used to retrieve the user's home directory for
-substitution.
+\fIcsh\fR-style tilde substitution. If a file name starts with a tilde,
+then the file name will be interpreted as if the first element is
+replaced with the location of the home directory for the given user. If
+the tilde is followed immediately by a separator, then the \fB$HOME\fR
+environment variable is substituted. Otherwise the characters between
+the tilde and the next separator are taken as a user name, which is used
+to retrieve the user's home directory for substitution. This works on
+Unix, MacOS X and Windows (except very old releases).
.PP
-The Macintosh and Windows platforms do not support tilde substitution
-when a user name follows the tilde. On these platforms, attempts to
-use a tilde followed by a user name will generate an error that the
-user does not exist when Tcl attempts to interpret that part of the
-path or otherwise access the file. The behaviour of these paths
-when not trying to interpret them is the same as on Unix. File
-names that have a tilde without a user name will be correctly
-substituted using the \fB$HOME\fR environment variable, just like
-for Unix.
-
+Old Windows platforms do not support tilde substitution when a user name
+follows the tilde. On these platforms, attempts to use a tilde followed
+by a user name will generate an error that the user does not exist when
+Tcl attempts to interpret that part of the path or otherwise access the
+file. The behaviour of these paths when not trying to interpret them is
+the same as on Unix. File names that have a tilde without a user name
+will be correctly substituted using the \fB$HOME\fR environment
+variable, just like for Unix.
.SH "PORTABILITY ISSUES"
.PP
Not all file systems are case sensitive, so scripts should avoid code
that depends on the case of characters in a file name. In addition,
the character sets allowed on different devices may differ, so scripts
should choose file names that do not contain special characters like:
-\fB<>:"/\e|\fR. The safest approach is to use names consisting of
-alphanumeric characters only. Also Windows 3.1 only supports file
+\fB<>:?"/\e|\fR.
+'\""\" reset emacs highlighting
+The safest approach is to use names consisting of
+alphanumeric characters only. Care should be taken with filenames
+which contain spaces (common on Windows systems) and
+filenames where the backslash is the directory separator (Windows
+native path names). Also Windows 3.1 only supports file
names with a root of no more than 8 characters and an extension of no
more than 3 characters.
.PP
@@ -207,16 +158,21 @@ On Windows platforms there are file and path length restrictions.
Complete paths or filenames longer than about 260 characters will lead
to errors in most file operations.
.PP
-Another Windows peculiarity is that any number of trailing dots '.' in
-filenames are totally ignored, so, for example, attempts to create a
-file or directory with a name "foo." will result in the creation of a
-file/directory with name "foo". This fact is reflected in the
-results of 'file normalize'. Furthermore, a file name consisting only
-of dots '.........' or dots with trailing characters '.....abc' is
-illegal.
+Another Windows peculiarity is that any number of trailing dots
+.QW .
+in filenames are totally ignored, so, for example, attempts to create a
+file or directory with a name
+.QW foo.
+will result in the creation of a file/directory with name
+.QW foo .
+This fact is reflected in the results of \fBfile normalize\fR.
+Furthermore, a file name consisting only of dots
+.QW .........
+or dots with trailing characters
+.QW .....abc
+is illegal.
+.SH "SEE ALSO"
+file(n), glob(n)
.SH KEYWORDS
current directory, absolute file name, relative file name,
volume-relative file name, portability
-
-.SH "SEE ALSO"
-file(n), glob(n)
diff --git a/doc/flush.n b/doc/flush.n
index a288141..1c79ea0 100644
--- a/doc/flush.n
+++ b/doc/flush.n
@@ -19,13 +19,11 @@ flush \- Flush buffered output for a channel
.PP
Flushes any output that has been buffered for \fIchannelId\fR.
.PP
-.VS
\fIChannelId\fR must be an identifier for an open channel such as a
Tcl standard channel (\fBstdout\fR or \fBstderr\fR), the return
value from an invocation of \fBopen\fR or \fBsocket\fR, or the result
of a channel creation command provided by a Tcl extension. The
channel must have been opened for writing.
-.VE
.PP
If the channel is in blocking mode the command does not return until all the
buffered output has been flushed to the channel. If the channel is in
diff --git a/doc/for.n b/doc/for.n
index 14755cb..033903f 100644
--- a/doc/for.n
+++ b/doc/for.n
@@ -10,7 +10,7 @@
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
-for \- ``For'' loop
+for \- 'For' loop
.SH SYNOPSIS
\fBfor \fIstart test next body\fR
.BE
diff --git a/doc/foreach.n b/doc/foreach.n
index be7a6fb..654c0cf 100644
--- a/doc/foreach.n
+++ b/doc/foreach.n
@@ -35,9 +35,9 @@ In the general case there can be more than one value list
and each value list can be associated with a list of loop variables
(e.g., \fIvarlist1\fR and \fIvarlist2\fR).
During each iteration of the loop
-the variables of each \fIvarlist\fP are assigned
-consecutive values from the corresponding \fIlist\fP.
-Values in each \fIlist\fP are used in order from first to last,
+the variables of each \fIvarlist\fR are assigned
+consecutive values from the corresponding \fIlist\fR.
+Values in each \fIlist\fR are used in order from first to last,
and each value is used exactly once.
The total number of loop iterations is large enough to use
up all the values from all the value lists.
@@ -49,37 +49,48 @@ The \fBbreak\fR and \fBcontinue\fR statements may be
invoked inside \fIbody\fR, with the same effect as in the \fBfor\fR
command. \fBForeach\fR returns an empty string.
.SH EXAMPLES
+This loop prints every value in a list together with the square and
+cube of the value:
+.CS
+'\" Maintainers: notice the tab hacking below!
+.ta 3i
+set values {1 3 5 7 2 4 6 8} ;# Odd numbers first, for fun!
+puts "Value\etSquare\etCube" ;# Neat-looking header
+\fBforeach\fR x $values { ;# Now loop and print...
+ puts " $x\et [expr {$x**2}]\et [expr {$x**3}]"
+}
+.CE
.PP
The following loop uses i and j as loop variables to iterate over
pairs of elements of a single list.
-.DS
+.CS
set x {}
\fBforeach\fR {i j} {a b c d e f} {
lappend x $j $i
}
# The value of x is "b a d c f e"
# There are 3 iterations of the loop.
-.DE
+.CE
.PP
The next loop uses i and j to iterate over two lists in parallel.
-.DS
+.CS
set x {}
\fBforeach\fR i {a b c} j {d e f g} {
lappend x $i $j
}
# The value of x is "a d b e c f {} g"
# There are 4 iterations of the loop.
-.DE
+.CE
.PP
The two forms are combined in the following example.
-.DS
+.CS
set x {}
\fBforeach\fR i {a b c} {j k} {d e f g} {
lappend x $i $j $k
}
# The value of x is "a d e b f g c {} {}"
# There are 3 iterations of the loop.
-.DE
+.CE
.SH "SEE ALSO"
for(n), while(n), break(n), continue(n)
diff --git a/doc/format.n b/doc/format.n
index 0dea667..f842f16 100644
--- a/doc/format.n
+++ b/doc/format.n
@@ -17,9 +17,8 @@ format \- Format a string in the style of sprintf
.SH INTRODUCTION
.PP
-This command generates a formatted string in the same way as the
-ANSI C \fBsprintf\fR procedure (it uses \fBsprintf\fR in its
-implementation).
+This command generates a formatted string in a fashion similar to the
+ANSI C \fBsprintf\fR procedure.
\fIFormatString\fR indicates how to format the result, using
\fB%\fR conversion specifiers as in \fBsprintf\fR, and the additional
arguments, if any, provide values to be substituted into the result.
@@ -42,15 +41,15 @@ of all of the conversion specifiers in \fIformatString\fR.
.PP
Each conversion specifier may contain up to six different parts:
an XPG3 position specifier,
-a set of flags, a minimum field width, a precision, a length modifier,
+a set of flags, a minimum field width, a precision, a size modifier,
and a conversion character.
Any of these fields may be omitted except for the conversion character.
The fields that are present must appear in the order given above.
The paragraphs below discuss each of these fields in turn.
.PP
If the \fB%\fR is followed by a decimal number and a \fB$\fR, as in
-``\fB%2$d\fR'', then the value to convert is not taken from the
-next sequential argument.
+.QW \fB%2$d\fR ,
+then the value to convert is not taken from the next sequential argument.
Instead, it is taken from the argument indicated by the number,
where 1 corresponds to the first \fIarg\fR.
If the conversion specifier requires multiple arguments because
@@ -74,8 +73,8 @@ Specifies that a number should always be printed with a sign,
even if positive.
.TP 10
\fIspace\fR
-Specifies that a space should be added to the beginning of the
-number if the first character isn't a sign.
+Specifies that a space should be added to the beginning of the
+number if the first character is not a sign.
.TP 10
\fB0\fR
Specifies that the number should be padded on the left with
@@ -92,7 +91,7 @@ has a decimal point.
For \fBg\fR and \fBG\fR conversions it specifies that
trailing zeroes should not be removed.
.PP
-The third portion of a conversion specifier is a number giving a
+The third portion of a conversion specifier is a decimal number giving a
minimum field width for this conversion.
It is typically used to make columns line up in tabular printouts.
If the converted argument contains fewer characters than the
@@ -104,7 +103,7 @@ may be used to specify padding with zeroes on the left or with
spaces on the right, respectively.
If the minimum field width is specified as \fB*\fR rather than
a number, then the next argument to the \fBformat\fR command
-determines the minimum field width; it must be a numeric string.
+determines the minimum field width; it must be an integer value.
.PP
The fourth portion of a conversion specifier is a precision,
which consists of a period followed by a number.
@@ -123,17 +122,19 @@ If the precision is specified with \fB*\fR rather than a number
then the next argument to the \fBformat\fR command determines the precision;
it must be a numeric string.
.PP
-The fifth part of a conversion specifier is a length modifier,
-which must be \fBh\fR or \fBl\fR.
-If it is \fBh\fR it specifies that the numeric value should be
-truncated to a 16-bit value before converting.
-This option is rarely useful.
-.VS 8.4
-If it is \fBl\fR it specifies that the numeric value should be (at
-least) a 64-bit value. If neither \fBh\fR nor \fBl\fR are present,
-numeric values are interpreted as being values of the width of the
-native machine word, as described by \fBtcl_platform(wordSize)\fR.
-.VE
+The fifth part of a conversion specifier is a size modifier,
+which must be \fBll\fR, \fBh\fR, or \fBl\fR.
+If it is \fBll\fR it specifies that an integer value is taken
+without truncation for conversion to a formatted substring.
+If it is \fBh\fR it specifies that an integer value is
+truncated to a 16-bit range before converting. This option is rarely useful.
+If it is \fBl\fR it specifies that the integer value is
+truncated to the same range as that produced by the \fBwide()\fR
+function of the \fBexpr\fR command (at least a 64-bit range).
+If neither \fBh\fR nor \fBl\fR are present, the integer value is
+truncated to the same range as that produced by the \fBint()\fR
+function of the \fBexpr\fR command (at least a 32-bit range, but
+determined by the value of \fBtcl_platform(wordSize)\fR).
.PP
The last thing in a conversion specifier is an alphabetic character
that determines what kind of conversion to perform.
@@ -146,33 +147,32 @@ Convert integer to signed decimal string.
Convert integer to unsigned decimal string.
.TP 10
\fBi\fR
-Convert integer to signed decimal string; the integer may either be
-in decimal, in octal (with a leading \fB0\fR) or in hexadecimal
-(with a leading \fB0x\fR).
+Convert integer to signed decimal string (equivalent to \fBd\fR).
.TP 10
\fBo\fR
Convert integer to unsigned octal string.
.TP 10
\fBx\fR or \fBX\fR
Convert integer to unsigned hexadecimal string, using digits
-``0123456789abcdef'' for \fBx\fR and ``0123456789ABCDEF'' for \fBX\fR).
-.VS
+.QW 0123456789abcdef
+for \fBx\fR and
+.QW 0123456789ABCDEF
+for \fBX\fR).
.TP 10
\fBc\fR
Convert integer to the Unicode character it represents.
-.VE
.TP 10
\fBs\fR
No conversion; just insert string.
.TP 10
\fBf\fR
-Convert floating-point number to signed decimal string of
+Convert number to signed decimal string of
the form \fIxx.yyy\fR, where the number of \fIy\fR's is determined by
the precision (default: 6).
If the precision is 0 then no decimal point is output.
.TP 10
-\fBe\fR or \fBe\fR
-Convert floating-point number to scientific notation in the
+\fBe\fR or \fBE\fR
+Convert number to scientific notation in the
form \fIx.yyy\fBe\(+-\fIzz\fR, where the number of \fIy\fR's is determined
by the precision (default: 6).
If the precision is 0 then no decimal point is output.
@@ -181,40 +181,34 @@ printed instead of \fBe\fR.
.TP 10
\fBg\fR or \fBG\fR
If the exponent is less than \-4 or greater than or equal to the
-precision, then convert floating-point number as for \fB%e\fR or
+precision, then convert number as for \fB%e\fR or
\fB%E\fR.
Otherwise convert as for \fB%f\fR.
Trailing zeroes and a trailing decimal point are omitted.
.TP 10
\fB%\fR
No conversion: just insert \fB%\fR.
-.LP
-For the numerical conversions the argument being converted must
-be an integer or floating-point string; format converts the argument
-to binary and then converts it back to a string according to
-the conversion specifier.
.SH "DIFFERENCES FROM ANSI SPRINTF"
.PP
The behavior of the format command is the same as the
ANSI C \fBsprintf\fR procedure except for the following
differences:
.IP [1]
-\fB%p\fR and \fB%n\fR specifiers are not currently supported.
+\fB%p\fR and \fB%n\fR specifiers are not supported.
.IP [2]
-For \fB%c\fR conversions the argument must be a decimal string,
+For \fB%c\fR conversions the argument must be an integer value,
which will then be converted to the corresponding character value.
.IP [3]
-The \fBl\fR modifier
-.VS 8.4
-is ignored for real values and on 64-bit platforms, which are always
-converted as if the \fBl\fR modifier were present (i.e. the types
-\fBdouble\fR and \fBlong\fR are used for the internal representation
-of real and integer values, respectively).
-.VE 8.4
-If the \fBh\fR modifier is specified then integer values are truncated
-to \fBshort\fR before conversion. Both \fBh\fR and \fBl\fR modifiers
-are ignored on all other conversions.
+The size modifiers are ignored when formatting floating-point values.
+The \fBll\fR modifier has no \fBsprintf\fR counterpart.
.SH EXAMPLES
+Convert the numeric value of a UNICODE character to the character
+itself:
+.CS
+set value 120
+set char [\fBformat\fR %c $value]
+.CE
+.PP
Convert the output of \fBtime\fR into seconds to an accuracy of
hundredths of a second:
.CS
@@ -235,7 +229,7 @@ reordering the data values passed to \fBformat\fR:
set fmt1 "Today, %d shares in %s were bought at $%.2f each"
puts [\fBformat\fR $fmt1 123 "Global BigCorp" 19.37]
-set fmt2 "Bought %2\\$s equity ($%3$.2f x %1\\$d) today"
+set fmt2 "Bought %2\e$s equity ($%3$.2f x %1\e$d) today"
puts [\fBformat\fR $fmt2 123 "Global BigCorp" 19.37]
.CE
.PP
@@ -261,9 +255,7 @@ for {set i 0} {$i<=20} {incr i} {
# Finish off by printing the separator again
puts $sep
.CE
-
.SH "SEE ALSO"
scan(n), sprintf(3), string(n)
-
.SH KEYWORDS
conversion specifier, format, sprintf, string, substitution
diff --git a/doc/gets.n b/doc/gets.n
index d61d072..bed7e32 100644
--- a/doc/gets.n
+++ b/doc/gets.n
@@ -21,13 +21,11 @@ This command reads the next line from \fIchannelId\fR, returns everything
in the line up to (but not including) the end-of-line character(s), and
discards the end-of-line character(s).
.PP
-.VS
\fIChannelId\fR must be an identifier for an open channel such as the
Tcl standard input channel (\fBstdin\fR), the return value from an
invocation of \fBopen\fR or \fBsocket\fR, or the result of a channel
creation command provided by a Tcl extension. The channel must have
been opened for input.
-.VE
.PP
If \fIvarName\fR is omitted the line is returned as the result of the
command.
diff --git a/doc/glob.n b/doc/glob.n
index 6f45d90..c257983 100644
--- a/doc/glob.n
+++ b/doc/glob.n
@@ -17,14 +17,17 @@ glob \- Return names of files that match patterns
.SH DESCRIPTION
.PP
-This command performs file name ``globbing'' in a fashion similar to
+This command performs file name
+.QW globbing
+in a fashion similar to
the csh shell. It returns a list of the files whose names match any
-of the \fIpattern\fR arguments.
+of the \fIpattern\fR arguments. No particular order is guaranteed
+in the list, so if a sorted list is required the caller should use
+\fBlsort\fR.
.LP
If the initial arguments to \fBglob\fR start with \fB\-\fR then
they are treated as switches. The following switches are
currently supported:
-.VS 8.3
.TP
\fB\-directory\fR \fIdirectory\fR
Search for files which match the given patterns starting in the given
@@ -35,14 +38,13 @@ characters explicitly. This option may not be used in conjunction with
whose names may contain glob-sensitive characters.
.TP
\fB\-join\fR
-The remaining pattern arguments are treated as a single pattern
-obtained by joining the arguments with directory separators.
-.VE 8.3
+The remaining pattern arguments, after option processing, are treated
+as a single pattern obtained by joining the arguments with directory
+separators.
.TP
\fB\-nocomplain\fR
Allows an empty list to be returned without error; without this
switch an error is returned if the result list would be empty.
-.VS 8.3
.TP
\fB\-path\fR \fIpathPrefix\fR
Search for files with the given \fIpathPrefix\fR where the rest of the name
@@ -100,10 +102,10 @@ The following are equivalent:
\fBglob */\fR
.CE
.RE
-except that the first case doesn't return the trailing ``/'' and
-is more platform independent.
+except that the first case doesn't return the trailing
+.QW /
+and is more platform independent.
.RE
-.VE 8.3
.TP
\fB\-\|\-\fR
Marks the end of switches. The argument following this one will
@@ -129,20 +131,35 @@ Matches the character \fIx\fR.
\fB{\fIa\fB,\fIb\fB,\fI...\fR}
Matches any of the strings \fIa\fR, \fIb\fR, etc.
.LP
-On Unix, as with csh, a ``.'' at the beginning of a file's name or just
-after a ``/'' must be matched explicitly or with a {} construct,
-unless the ``-types hidden'' flag is given (since ``.'' at the beginning
-of a file's name indicates that it is hidden). On other platforms,
-files beginning with a ``.'' are handled no differently to any others,
-except the special directories ``.'' and ``..'' which must be matched
-explicitly (this is to avoid a recursive pattern like ``glob -join * *
-* *'' from recursing up the directory hierarchy as well as down).
-In addition, all ``/'' characters must be matched explicitly.
+On Unix, as with csh, a
+.QW .
+at the beginning of a file's name or just after a
+.QW /
+must be matched explicitly or with a {} construct, unless the
+\fB\-types hidden\fR flag is given (since
+.QW .
+at the beginning of a file's name indicates that it is hidden). On
+other platforms, files beginning with a
+.QW .
+are handled no differently to any others, except the special directories
+.QW .
+and
+.QW ..
+which must be matched explicitly (this is to avoid a recursive pattern like
+.QW "glob -join * * * *"
+from recursing up the directory hierarchy as well as down). In addition, all
+.QW /
+characters must be matched explicitly.
.LP
-If the first character in a \fIpattern\fR is ``~'' then it refers
-to the home directory for the user whose name follows the ``~''.
-If the ``~'' is followed immediately by ``/'' then the value of
-the HOME environment variable is used.
+If the first character in a \fIpattern\fR is
+.QW ~
+then it refers to the home directory for the user whose name follows the
+.QW ~ .
+If the
+.QW ~
+is followed immediately by
+.QW /
+then the value of the HOME environment variable is used.
.LP
The \fBglob\fR command differs from csh globbing in two ways.
First, it does not sort its result list (use the \fBlsort\fR
@@ -152,29 +169,32 @@ exist; in csh no check for existence is made unless a pattern
contains a ?, *, or [] construct.
.LP
When the \fBglob\fR command returns relative paths whose filenames
-start with a tilde ``~'' (for example through \fBglob *\fR or
-\fBglob -tails\fR, the returned list will not quote the tilde with
-``./''. This means care must be taken if those names are later to
+start with a tilde
+.QW ~
+(for example through \fBglob *\fR or \fBglob -tails\fR, the returned
+list will not quote the tilde with
+.QW ./ .
+This means care must be taken if those names are later to
be used with \fBfile join\fR, to avoid them being interpreted as
absolute paths pointing to a given user's home directory.
.SH "PORTABILITY ISSUES"
.PP
-Unlike other Tcl commands that will accept both network and native
-style names (see the \fBfilename\fR manual entry for details on how
-native and network names are specified), the \fBglob\fR command only
-accepts native names.
-.TP
\fBWindows\fR
.
For Windows UNC names, the servername and sharename components of the path
may not contain ?, *, or [] constructs. On Windows NT, if \fIpattern\fR is
-of the form ``\fB~\fIusername\fB@\fIdomain\fR'' it refers to the home
+of the form
+.QW \fB~\fIusername\fB@\fIdomain\fR ,
+it refers to the home
directory of the user whose account information resides on the specified NT
domain server. Otherwise, user account information is obtained from
the local computer. On Windows 95 and 98, \fBglob\fR accepts patterns
-like ``.../'' and ``..../'' for successively higher up parent directories.
-
-.
+like
+.QW .../
+and
+.QW ..../
+for successively higher up parent directories.
+.PP
Since the backslash character has a special meaning to the glob
command, glob patterns containing Windows style path separators need
special care. The pattern \fIC:\e\efoo\e\e*\fR is interpreted as
@@ -184,13 +204,6 @@ interpreted as a wildcard character. One solution to this problem is
to use the Unix style forward slash as a path separator. Windows style
paths can be converted to Unix style paths with the command \fBfile
join $path\fR (or \fBfile normalize $path\fR in Tcl 8.4).
-.TP
-\fBMacintosh\fR
-.
-When using the options, \fB\-directory\fR, \fB\-join\fR or \fB\-path\fR, glob
-assumes the directory separator for the entire pattern is the standard
-``:''. When not using these options, glob examines each pattern argument
-and uses ``/'' unless the pattern contains a ``:''.
.SH EXAMPLES
Find all the Tcl files in the current directory:
.CS
@@ -208,7 +221,12 @@ Find all subdirectories of the current directory:
\fBglob\fR \-type d *
.CE
.PP
-Find all files whose name contains an "a", a "b" or the sequence "cde":
+Find all files whose name contains an
+.QW a ,
+a
+.QW b
+or the sequence
+.QW cde :
.CS
\fBglob\fR \-type f *{a,b,cde}*
.CE
diff --git a/doc/global.n b/doc/global.n
index b0e4389..c9d7a36 100644
--- a/doc/global.n
+++ b/doc/global.n
@@ -26,6 +26,10 @@ in the list returned by \fBinfo locals\fR).
If \fIvarname\fR contains namespace qualifiers, the local variable's name is
the unqualified name of the global variable, as determined by the
\fBnamespace tail\fR command.
+.PP
+\fIvarname\fR is always treated as the name of a variable, not an
+array element. An error is returned if the name looks like an array element,
+such as \fBa(b)\fR.
.SH EXAMPLES
This procedure sets the namespace variable \fI::a::x\fR
.CS
@@ -43,7 +47,7 @@ opened with \fBsocket\fR or as part of a counted HTTP response).
.CS
proc accum {string} {
\fBglobal\fR accumulator
- append accumulator $string \\n
+ append accumulator $string \en
}
.CE
diff --git a/doc/history.n b/doc/history.n
index 0ce7c4c..ba507b4 100644
--- a/doc/history.n
+++ b/doc/history.n
@@ -14,20 +14,20 @@ history \- Manipulate the history list
.SH SYNOPSIS
\fBhistory \fR?\fIoption\fR? ?\fIarg arg ...\fR?
.BE
-
.SH DESCRIPTION
.PP
The \fBhistory\fR command performs one of several operations related to
recently-executed commands recorded in a history list. Each of
-these recorded commands is referred to as an ``event''. When
-specifying an event to the \fBhistory\fR command, the following
+these recorded commands is referred to as an
+.QW event .
+When specifying an event to the \fBhistory\fR command, the following
forms may be used:
.IP [1]
A number: if positive, it refers to the event with
that number (all events are numbered starting at 1). If the number
is negative, it selects an event relative to the current event
(\fB\-1\fR refers to the previous event, \fB\-2\fR to the one before that, and
-so on). Event \fB0\fP refers to the current event.
+so on). Event \fB0\fR refers to the current event.
.IP [2]
A string: selects the most recent event that matches the string.
An event is considered to match the string either if the string is
@@ -43,7 +43,7 @@ as \fBhistory info\fR, described below.
\fBhistory add\fI command \fR?\fBexec\fR?
Adds the \fIcommand\fR argument to the history list as a new event. If
\fBexec\fR is specified (or abbreviated) then the command is also
-executed and its result is returned. If \fBexec\fR isn't specified
+executed and its result is returned. If \fBexec\fR is not specified
then an empty string is returned as result.
.TP
\fBhistory change\fI newValue\fR ?\fIevent\fR?
@@ -87,16 +87,16 @@ revision: see below for details.
.PP
Pre-8.0 Tcl had a complex history revision mechanism.
The current mechanism is more limited, and the old
-history operations \fBsubstitute\fP and \fBwords\fP have been removed.
-(As a consolation, the \fBclear\fP operation was added.)
+history operations \fBsubstitute\fR and \fBwords\fR have been removed.
+(As a consolation, the \fBclear\fR operation was added.)
.PP
-The history option \fBredo\fR results in much simpler ``history revision''.
+The history option \fBredo\fR results in much simpler
+.QW "history revision" .
When this option is invoked then the most recent event
is modified to eliminate the history command and replace it with
the result of the history command.
If you want to redo an event without modifying history, then use
-the \fBevent\fP operation to retrieve some event,
-and the \fBadd\fP operation to add it to history and execute it.
-
+the \fBevent\fR operation to retrieve some event,
+and the \fBadd\fR operation to add it to history and execute it.
.SH KEYWORDS
event, history, record
diff --git a/doc/http.n b/doc/http.n
index a563b5d..24b5f6a 100644
--- a/doc/http.n
+++ b/doc/http.n
@@ -7,21 +7,22 @@
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
-.TH "http" n 2.5 http "Tcl Bundled Packages"
+.TH "http" n 2.7 http "Tcl Bundled Packages"
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
-http \- Client-side implementation of the HTTP/1.0 protocol.
+http \- Client-side implementation of the HTTP/1.1 protocol
.SH SYNOPSIS
-\fBpackage require http ?2.5?\fR
+\fBpackage require http ?2.7?\fR
+.\" See Also -useragent option documentation in body!
.sp
\fB::http::config \fI?options?\fR
.sp
\fB::http::geturl \fIurl ?options?\fR
.sp
-\fB::http::formatQuery\fP \fIkey value\fP ?\fIkey value\fP ...?
+\fB::http::formatQuery\fR \fIkey value\fR ?\fIkey value\fR ...?
.sp
-\fB::http::reset\fP \fItoken\fP ?\fIwhy\fP?
+\fB::http::reset\fR \fItoken\fR ?\fIwhy\fR?
.sp
\fB::http::wait \fItoken\fR
.sp
@@ -45,12 +46,12 @@ http \- Client-side implementation of the HTTP/1.0 protocol.
.sp
\fB::http::unregister \fIproto\fR
.BE
-
.SH DESCRIPTION
.PP
-The \fBhttp\fR package provides the client side of the HTTP/1.0
-protocol. The package implements the GET, POST, and HEAD operations
-of HTTP/1.0. It allows configuration of a proxy host to get through
+The \fBhttp\fR package provides the client side of the HTTP/1.1
+protocol, as defined in RFC 2616.
+The package implements the GET, POST, and HEAD operations
+of HTTP/1.1. It allows configuration of a proxy host to get through
firewalls. The package is compatible with the \fBSafesock\fR security
policy, so it can be used by untrusted applets to do URL fetching from
a restricted set of hosts. This package can be extended to support
@@ -63,9 +64,9 @@ is performed.
The return value of \fB::http::geturl\fR is a token for the transaction.
The value is also the name of an array in the ::http namespace
that contains state information about the transaction. The elements
-of this array are described in the STATE ARRAY section.
+of this array are described in the \fBSTATE ARRAY\fR section.
.PP
-If the \fB-command\fP option is specified, then
+If the \fB\-command\fR option is specified, then
the HTTP operation is done in the background.
\fB::http::geturl\fR returns immediately after generating the
HTTP request and the callback is invoked
@@ -75,7 +76,7 @@ applications, the caller can use \fB::http::wait\fR after calling
\fB::http::geturl\fR to start the event loop.
.SH COMMANDS
.TP
-\fB::http::config\fP ?\fIoptions\fR?
+\fB::http::config\fR ?\fIoptions\fR?
The \fB::http::config\fR command is used to set and query the name of the
proxy server and port, and the User-Agent name used in the HTTP
requests. If no options are specified, then the current configuration
@@ -85,20 +86,21 @@ that setting is returned. Otherwise, the options should be a set of
flags and values that define the configuration:
.RS
.TP
-\fB\-accept\fP \fImimetypes\fP
+\fB\-accept\fR \fImimetypes\fR
The Accept header of the request. The default is */*, which means that
all types of documents are accepted. Otherwise you can supply a
comma-separated list of mime type patterns that you are
-willing to receive. For example, "image/gif, image/jpeg, text/*".
+willing to receive. For example,
+.QW "image/gif, image/jpeg, text/*" .
.TP
-\fB\-proxyhost\fP \fIhostname\fP
+\fB\-proxyhost\fR \fIhostname\fR
The name of the proxy host, if any. If this value is the
empty string, the URL host is contacted directly.
.TP
-\fB\-proxyport\fP \fInumber\fP
+\fB\-proxyport\fR \fInumber\fR
The proxy port number.
.TP
-\fB\-proxyfilter\fP \fIcommand\fP
+\fB\-proxyfilter\fR \fIcommand\fR
The command is a callback that is made during
\fB::http::geturl\fR
to determine if a proxy is required for a given host. One argument, a
@@ -109,7 +111,7 @@ an empty list. The default filter returns the values of the
\fB\-proxyhost\fR and \fB\-proxyport\fR settings if they are
non-empty.
.TP
-\fB\-urlencoding\fP \fIencoding\fP
+\fB\-urlencoding\fR \fIencoding\fR
The \fIencoding\fR used for creating the x-url-encoded URLs with
\fB::http::formatQuery\fR. The default is \fButf-8\fR, as specified by RFC
2718. Prior to http 2.5 this was unspecified, and that behavior can be
@@ -118,45 +120,46 @@ returned by specifying the empty string (\fB{}\fR), although
\fB::http::formatQuery\fR throwing an error processing non-latin-1
characters.
.TP
-\fB\-useragent\fP \fIstring\fP
-The value of the User-Agent header in the HTTP request. The default
-is \fB"Tcl http client package 2.4."\fR
+\fB\-useragent\fR \fIstring\fR
+The value of the User-Agent header in the HTTP request. The default is
+.QW "\fBTcl http client package 2.7\fR" .
.RE
.TP
-\fB::http::geturl\fP \fIurl\fP ?\fIoptions\fP?
+\fB::http::geturl\fR \fIurl\fR ?\fIoptions\fR?
The \fB::http::geturl\fR command is the main procedure in the package.
The \fB\-query\fR option causes a POST operation and
the \fB\-validate\fR option causes a HEAD operation;
otherwise, a GET operation is performed. The \fB::http::geturl\fR command
returns a \fItoken\fR value that can be used to get
-information about the transaction. See the STATE ARRAY and ERRORS section for
+information about the transaction. See the \fBSTATE ARRAY\fR and
+\fBERRORS\fR section for
details. The \fB::http::geturl\fR command blocks until the operation
completes, unless the \fB\-command\fR option specifies a callback
that is invoked when the HTTP transaction completes.
\fB::http::geturl\fR takes several options:
.RS
.TP
-\fB\-binary\fP \fIboolean\fP
+\fB\-binary\fR \fIboolean\fR
Specifies whether to force interpreting the URL data as binary. Normally
this is auto-detected (anything not beginning with a \fBtext\fR content
type or whose content encoding is \fBgzip\fR or \fBcompress\fR is
considered binary data).
.TP
-\fB\-blocksize\fP \fIsize\fP
+\fB\-blocksize\fR \fIsize\fR
The block size used when reading the URL.
At most \fIsize\fR bytes are read at once. After each block, a call to the
\fB\-progress\fR callback is made (if that option is specified).
.TP
-\fB\-channel\fP \fIname\fP
+\fB\-channel\fR \fIname\fR
Copy the URL contents to channel \fIname\fR instead of saving it in
\fBstate(body)\fR.
.TP
-\fB\-command\fP \fIcallback\fP
-Invoke \fIcallback\fP after the HTTP transaction completes.
-This option causes \fB::http::geturl\fP to return immediately.
-The \fIcallback\fP gets an additional argument that is the \fItoken\fR returned
+\fB\-command\fR \fIcallback\fR
+Invoke \fIcallback\fR after the HTTP transaction completes.
+This option causes \fB::http::geturl\fR to return immediately.
+The \fIcallback\fR gets an additional argument that is the \fItoken\fR returned
from \fB::http::geturl\fR. This token is the name of an array that is
-described in the STATE ARRAY section. Here is a template for the
+described in the \fBSTATE ARRAY\fR section. Here is a template for the
callback:
.RS
.CS
@@ -167,27 +170,30 @@ proc httpCallback {token} {
.CE
.RE
.TP
-\fB\-handler\fP \fIcallback\fP
-Invoke \fIcallback\fP whenever HTTP data is available; if present, nothing
+\fB\-handler\fR \fIcallback\fR
+Invoke \fIcallback\fR whenever HTTP data is available; if present, nothing
else will be done with the HTTP data. This procedure gets two additional
arguments: the socket for the HTTP data and the \fItoken\fR returned from
-\fB::http::geturl\fR. The token is the name of a global array that is described
-in the STATE ARRAY section. The procedure is expected to return the number
-of bytes read from the socket. Here is a template for the callback:
+\fB::http::geturl\fR. The token is the name of a global array that is
+described in the \fBSTATE ARRAY\fR section. The procedure is expected
+to return the number of bytes read from the socket. Here is a
+template for the callback:
.RS
.CS
proc httpHandlerCallback {socket token} {
upvar #0 $token state
# Access socket, and state as a Tcl array
+ # For example...
...
- (example: set data [read $socket 1000];set nbytes [string length $data])
+ set data [read $socket 1000]
+ set nbytes [string length $data]
...
- return nbytes
+ return $nbytes
}
.CE
.RE
.TP
-\fB\-headers\fP \fIkeyvaluelist\fP
+\fB\-headers\fR \fIkeyvaluelist\fR
This option is used to add extra headers to the HTTP request. The
\fIkeyvaluelist\fR argument must be a list with an even number of
elements that alternate between keys and values. The keys become
@@ -199,7 +205,20 @@ HTTP request:
Pragma: no-cache
.CE
.TP
-\fB\-progress\fP \fIcallback\fP
+\fB\-keepalive\fR \fIboolean\fR
+If true, attempt to keep the connection open for servicing
+multiple requests. Default is 0.
+.TP
+\fB\-method\fR \fItype\fR
+Force the HTTP request method to \fItype\fR. \fB::http::geturl\fR will
+auto-select GET, POST or HEAD based on other options, but this option
+enables choices like PUT and DELETE for webdav support.
+.TP
+\fB\-myaddr\fR \fIaddress\fR
+Pass an specific local address to the underlying \fBsocket\fR call in case
+multiple interfaces are available.
+.TP
+\fB\-progress\fR \fIcallback\fR
The \fIcallback\fR is made after each transfer of data from the URL.
The callback gets three additional arguments: the \fItoken\fR from
\fB::http::geturl\fR, the expected total size of the contents from the
@@ -215,13 +234,18 @@ proc httpProgress {token total current} {
.CE
.RE
.TP
-\fB\-query\fP \fIquery\fP
+\fB\-protocol\fR \fIversion\fR
+Select the HTTP protocol version to use. This should be 1.0 or 1.1 (the
+default). Should only be necessary for servers that do not understand or
+otherwise complain about HTTP/1.1.
+.TP
+\fB\-query\fR \fIquery\fR
This flag causes \fB::http::geturl\fR to do a POST request that passes the
\fIquery\fR to the server. The \fIquery\fR must be an x-url-encoding
formatted query. The \fB::http::formatQuery\fR procedure can be used to
do the formatting.
.TP
-\fB\-queryblocksize\fP \fIsize\fP
+\fB\-queryblocksize\fR \fIsize\fR
The block size used when posting query data to the URL.
At most
\fIsize\fR
@@ -229,103 +253,106 @@ bytes are written at once. After each block, a call to the
\fB\-queryprogress\fR
callback is made (if that option is specified).
.TP
-\fB\-querychannel\fP \fIchannelID\fP
+\fB\-querychannel\fR \fIchannelID\fR
This flag causes \fB::http::geturl\fR to do a POST request that passes the
data contained in \fIchannelID\fR to the server. The data contained in
\fIchannelID\fR must be an x-url-encoding
-formatted query unless the \fB\-type\fP option below is used.
+formatted query unless the \fB\-type\fR option below is used.
If a Content-Length header is not specified via the \fB\-headers\fR options,
\fB::http::geturl\fR attempts to determine the size of the post data
in order to create that header. If it is
unable to determine the size, it returns an error.
.TP
-\fB\-queryprogress\fP \fIcallback\fP
+\fB\-queryprogress\fR \fIcallback\fR
The \fIcallback\fR is made after each transfer of data to the URL
(i.e. POST) and acts exactly like the \fB\-progress\fR option (the
callback format is the same).
.TP
-\fB\-timeout\fP \fImilliseconds\fP
+\fB\-strict\fR \fIboolean\fR
+Whether to enforce RFC 3986 URL validation on the request. Default is 1.
+.TP
+\fB\-timeout\fR \fImilliseconds\fR
If \fImilliseconds\fR is non-zero, then \fB::http::geturl\fR sets up a timeout
to occur after the specified number of milliseconds.
-A timeout results in a call to \fB::http::reset\fP and to
-the \fB-command\fP callback, if specified.
-The return value of \fB::http::status\fP is \fBtimeout\fP
+A timeout results in a call to \fB::http::reset\fR and to
+the \fB\-command\fR callback, if specified.
+The return value of \fB::http::status\fR is \fBtimeout\fR
after a timeout has occurred.
.TP
-\fB\-type\fP \fImime-type\fP
+\fB\-type\fR \fImime-type\fR
Use \fImime-type\fR as the \fBContent-Type\fR value, instead of the
default value (\fBapplication/x-www-form-urlencoded\fR) during a
POST operation.
.TP
-\fB\-validate\fP \fIboolean\fP
+\fB\-validate\fR \fIboolean\fR
If \fIboolean\fR is non-zero, then \fB::http::geturl\fR does an HTTP HEAD
request. This request returns meta information about the URL, but the
contents are not returned. The meta information is available in the
-\fBstate(meta) \fR variable after the transaction. See the STATE
-ARRAY section for details.
+\fBstate(meta) \fR variable after the transaction. See the
+\fBSTATE ARRAY\fR section for details.
.RE
.TP
-\fB::http::formatQuery\fP \fIkey value\fP ?\fIkey value\fP ...?
+\fB::http::formatQuery\fR \fIkey value\fR ?\fIkey value\fR ...?
This procedure does x-url-encoding of query data. It takes an even
number of arguments that are the keys and values of the query. It
encodes the keys and values, and generates one string that has the
proper & and = separators. The result is suitable for the
\fB\-query\fR value passed to \fB::http::geturl\fR.
.TP
-\fB::http::reset\fP \fItoken\fP ?\fIwhy\fP?
+\fB::http::reset\fR \fItoken\fR ?\fIwhy\fR?
This command resets the HTTP transaction identified by \fItoken\fR, if
-any. This sets the \fBstate(status)\fP value to \fIwhy\fP, which defaults to \fBreset\fR, and then calls the registered \fB\-command\fR callback.
+any. This sets the \fBstate(status)\fR value to \fIwhy\fR, which defaults to \fBreset\fR, and then calls the registered \fB\-command\fR callback.
.TP
-\fB::http::wait\fP \fItoken\fP
+\fB::http::wait\fR \fItoken\fR
This is a convenience procedure that blocks and waits for the
transaction to complete. This only works in trusted code because it
-uses \fBvwait\fR. Also, it's not useful for the case where
-\fB::http::geturl\fP is called \fIwithout\fP the \fB-command\fP option
-because in this case the \fB::http::geturl\fP call doesn't return
-until the HTTP transaction is complete, and thus there's nothing to
+uses \fBvwait\fR. Also, it is not useful for the case where
+\fB::http::geturl\fR is called \fIwithout\fR the \fB\-command\fR option
+because in this case the \fB::http::geturl\fR call does not return
+until the HTTP transaction is complete, and thus there is nothing to
wait for.
.TP
-\fB::http::data\fP \fItoken\fP
-This is a convenience procedure that returns the \fBbody\fP element
+\fB::http::data\fR \fItoken\fR
+This is a convenience procedure that returns the \fBbody\fR element
(i.e., the URL data) of the state array.
.TP
-\fB::http::error\fP \fItoken\fP
-This is a convenience procedure that returns the \fBerror\fP element
+\fB::http::error\fR \fItoken\fR
+This is a convenience procedure that returns the \fBerror\fR element
of the state array.
.TP
-\fB::http::status\fP \fItoken\fP
-This is a convenience procedure that returns the \fBstatus\fP element of
+\fB::http::status\fR \fItoken\fR
+This is a convenience procedure that returns the \fBstatus\fR element of
the state array.
.TP
-\fB::http::code\fP \fItoken\fP
-This is a convenience procedure that returns the \fBhttp\fP element of the
+\fB::http::code\fR \fItoken\fR
+This is a convenience procedure that returns the \fBhttp\fR element of the
state array.
.TP
-\fB::http::ncode\fP \fItoken\fP
+\fB::http::ncode\fR \fItoken\fR
This is a convenience procedure that returns just the numeric return
-code (200, 404, etc.) from the \fBhttp\fP element of the state array.
+code (200, 404, etc.) from the \fBhttp\fR element of the state array.
.TP
-\fB::http::size\fP \fItoken\fP
-This is a convenience procedure that returns the \fBcurrentsize\fP
+\fB::http::size\fR \fItoken\fR
+This is a convenience procedure that returns the \fBcurrentsize\fR
element of the state array, which represents the number of bytes
-received from the URL in the \fB::http::geturl\fP call.
+received from the URL in the \fB::http::geturl\fR call.
.TP
-\fB::http::meta\fP \fItoken\fP
-This is a convenience procedure that returns the \fBmeta\fP
+\fB::http::meta\fR \fItoken\fR
+This is a convenience procedure that returns the \fBmeta\fR
element of the state array which contains the HTTP response
headers. See below for an explanation of this element.
.TP
-\fB::http::cleanup\fP \fItoken\fP
+\fB::http::cleanup\fR \fItoken\fR
This procedure cleans up the state associated with the connection
-identified by \fItoken\fP. After this call, the procedures
-like \fB::http::data\fP cannot be used to get information
-about the operation. It is \fIstrongly\fP recommended that you call
-this function after you're done with a given HTTP request. Not doing
+identified by \fItoken\fR. After this call, the procedures
+like \fB::http::data\fR cannot be used to get information
+about the operation. It is \fIstrongly\fR recommended that you call
+this function after you are done with a given HTTP request. Not doing
so will result in memory not being freed, and if your app calls
-\fB::http::geturl\fP enough times, the memory leak could cause a
+\fB::http::geturl\fR enough times, the memory leak could cause a
performance hit...or worse.
.TP
-\fB::http::register\fP \fIproto port command\fP
+\fB::http::register\fR \fIproto port command\fR
This procedure allows one to provide custom HTTP transport types
such as HTTPS, by registering a prefix, the default port, and the
command to execute to create the Tcl \fBchannel\fR. E.g.:
@@ -340,12 +367,11 @@ set token [::http::geturl https://my.secure.site/]
.CE
.RE
.TP
-\fB::http::unregister\fP \fIproto\fP
+\fB::http::unregister\fR \fIproto\fR
This procedure unregisters a protocol handler that was previously
registered via \fB::http::register\fR.
-
-.SH "ERRORS"
-The \fB::http::geturl\fP procedure will raise errors in the following cases:
+.SH ERRORS
+The \fB::http::geturl\fR procedure will raise errors in the following cases:
invalid command line options,
an invalid URL,
a URL on a non-existent host,
@@ -354,60 +380,59 @@ These errors mean that it
cannot even start the network transaction.
It will also raise an error if it gets an I/O error while
writing out the HTTP request header.
-For synchronous \fB::http::geturl\fP calls (where \fB-command\fP is
+For synchronous \fB::http::geturl\fR calls (where \fB\-command\fR is
not specified), it will raise an error if it gets an I/O error while
-reading the HTTP reply headers or data. Because \fB::http::geturl\fP
-doesn't return a token in these cases, it does all the required
-cleanup and there's no issue of your app having to call
-\fB::http::cleanup\fP.
+reading the HTTP reply headers or data. Because \fB::http::geturl\fR
+does not return a token in these cases, it does all the required
+cleanup and there is no issue of your app having to call
+\fB::http::cleanup\fR.
.PP
-For asynchronous \fB::http::geturl\fP calls, all of the above error
-situations apply, except that if there's any error while
-reading the
+For asynchronous \fB::http::geturl\fR calls, all of the above error
+situations apply, except that if there is any error while reading the
HTTP reply headers or data, no exception is thrown. This is because
-after writing the HTTP headers, \fB::http::geturl\fP returns, and the
+after writing the HTTP headers, \fB::http::geturl\fR returns, and the
rest of the HTTP transaction occurs in the background. The command
callback can check if any error occurred during the read by calling
-\fB::http::status\fP to check the status and if its \fIerror\fP,
-calling \fB::http::error\fP to get the error message.
+\fB::http::status\fR to check the status and if its \fIerror\fR,
+calling \fB::http::error\fR to get the error message.
.PP
Alternatively, if the main program flow reaches a point where it needs
to know the result of the asynchronous HTTP request, it can call
-\fB::http::wait\fP and then check status and error, just as the
+\fB::http::wait\fR and then check status and error, just as the
callback does.
.PP
In any case, you must still call
-\fB::http::cleanup\fP to delete the state array when you're done.
+\fB::http::cleanup\fR to delete the state array when you are done.
.PP
There are other possible results of the HTTP transaction
-determined by examining the status from \fB::http::status\fP.
+determined by examining the status from \fB::http::status\fR.
These are described below.
.TP
ok
-If the HTTP transaction completes entirely, then status will be \fBok\fP.
-However, you should still check the \fB::http::code\fP value to get
-the HTTP status. The \fB::http::ncode\fP procedure provides just
-the numeric error (e.g., 200, 404 or 500) while the \fB::http::code\fP
-procedure returns a value like "HTTP 404 File not found".
+If the HTTP transaction completes entirely, then status will be \fBok\fR.
+However, you should still check the \fB::http::code\fR value to get
+the HTTP status. The \fB::http::ncode\fR procedure provides just
+the numeric error (e.g., 200, 404 or 500) while the \fB::http::code\fR
+procedure returns a value like
+.QW "HTTP 404 File not found" .
.TP
eof
If the server closes the socket without replying, then no error
-is raised, but the status of the transaction will be \fBeof\fP.
+is raised, but the status of the transaction will be \fBeof\fR.
.TP
error
-The error message will also be stored in the \fBerror\fP status
-array element, accessible via \fB::http::error\fP.
+The error message will also be stored in the \fBerror\fR status
+array element, accessible via \fB::http::error\fR.
.PP
-Another error possibility is that \fB::http::geturl\fP is unable to
+Another error possibility is that \fB::http::geturl\fR is unable to
write all the post query data to the server before the server
responds and closes the socket.
-The error message is saved in the \fBposterror\fP status array
-element and then \fB::http::geturl\fP attempts to complete the
+The error message is saved in the \fBposterror\fR status array
+element and then \fB::http::geturl\fR attempts to complete the
transaction.
If it can read the server's response
-it will end up with an \fBok\fP status, otherwise it will have
-an \fBeof\fP status.
-
+it will end up with an \fBok\fR status, otherwise it will have
+an \fBeof\fR status.
.SH "STATE ARRAY"
The \fB::http::geturl\fR procedure returns a \fItoken\fR that can be used to
get to the state of the HTTP transaction in the form of a Tcl array.
@@ -417,14 +442,14 @@ upvar #0 $token state
.CE
Once the data associated with the URL is no longer needed, the state
array should be unset to free up storage.
-The \fB::http::cleanup\fP procedure is provided for that purpose.
+The \fB::http::cleanup\fR procedure is provided for that purpose.
The following elements of
the array are supported:
.RS
.TP
\fBbody\fR
The contents of the URL. This will be empty if the \fB\-channel\fR
-option has been specified. This value is returned by the \fB::http::data\fP command.
+option has been specified. This value is returned by the \fB::http::data\fR command.
.TP
\fBcharset\fR
The value of the charset attribute from the \fBContent-Type\fR meta-data
@@ -437,7 +462,7 @@ A copy of the \fBContent-Encoding\fR meta-data value.
.TP
\fBcurrentsize\fR
The current number of bytes fetched from the URL.
-This value is returned by the \fB::http::size\fP command.
+This value is returned by the \fB::http::size\fR command.
.TP
\fBerror\fR
If defined, this is the error string seen when the HTTP transaction
@@ -445,10 +470,10 @@ was aborted.
.TP
\fBhttp\fR
The HTTP status reply from the server. This value
-is returned by the \fB::http::code\fP command. The format of this value is:
+is returned by the \fB::http::code\fR command. The format of this value is:
.RS
.CS
-\fIHTTP/1.0 code string\fP
+\fIHTTP/1.1 code string\fR
.CE
The \fIcode\fR is a three-digit number defined in the HTTP standard.
A code of 200 is OK. Codes beginning with 4 or 5 indicate errors.
@@ -488,7 +513,7 @@ the post query data to the server.
.TP
\fBstatus\fR
Either \fBok\fR, for successful completion, \fBreset\fR for
-user-reset, \fBtimeout\fP if a timeout occurred before the transaction
+user-reset, \fBtimeout\fR if a timeout occurred before the transaction
could complete, or \fBerror\fR for an error condition. During the
transaction this value is the empty string.
.TP
@@ -506,7 +531,7 @@ The requested URL.
# Copy a URL to a file and print meta-data
proc httpcopy { url file {chunk 4096} } {
set out [open $file w]
- set token [\fB::http::geturl\fR $url -channel $out \\
+ set token [\fB::http::geturl\fR $url -channel $out \e
-progress httpCopyProgress -blocksize $chunk]
close $out
@@ -537,9 +562,7 @@ proc httpCopyProgress {args} {
flush stderr
}
.CE
-
.SH "SEE ALSO"
safe(n), socket(n), safesock(n)
-
.SH KEYWORDS
security policy, socket
diff --git a/doc/if.n b/doc/if.n
index b9e9219..d84cf08 100644
--- a/doc/if.n
+++ b/doc/if.n
@@ -30,7 +30,8 @@ then \fBbody2\fR is executed, and so on.
If none of the expressions evaluates to true then \fIbodyN\fR is
executed.
The \fBthen\fR and \fBelse\fR arguments are optional
-``noise words'' to make the command easier to read.
+.QW "noise words"
+to make the command easier to read.
There may be any number of \fBelseif\fR clauses, including zero.
\fIBodyN\fR may also be omitted as long as \fBelse\fR is omitted too.
The return value from the command is the result of the body script
diff --git a/doc/incr.n b/doc/incr.n
index c98d795..72b3ff8 100644
--- a/doc/incr.n
+++ b/doc/incr.n
@@ -24,6 +24,12 @@ integer) is added to the value of variable \fIvarName\fR; otherwise
1 is added to \fIvarName\fR.
The new value is stored as a decimal string in variable \fIvarName\fR
and also returned as result.
+.PP
+.VS 8.5
+Starting with the Tcl 8.5 release, the variable \fIvarName\fR passed
+to \fBincr\fR may be unset, and in that case, it will be set to
+the value \fIincrement\fR or to the default increment value of \fB1\fR.
+.VE 8.5
.SH EXAMPLES
Add one to the contents of the variable \fIx\fR:
.CS
@@ -42,7 +48,7 @@ variable \fIx\fR:
.CE
.PP
Add nothing at all to the variable \fIx\fR (often useful for checking
-whether an argument to a procedure is actually numeric and generating
+whether an argument to a procedure is actually integral and generating
an error if it is not):
.CS
\fBincr\fR x 0
diff --git a/doc/info.n b/doc/info.n
index 1b11397..fae0d43 100644
--- a/doc/info.n
+++ b/doc/info.n
@@ -21,7 +21,7 @@ info \- Return information about the state of the Tcl interpreter
.PP
This command provides information about various internals of the Tcl
interpreter.
-The legal \fIoption\fR's (which may be abbreviated) are:
+The legal \fIoption\fRs (which may be abbreviated) are:
.TP
\fBinfo args \fIprocname\fR
Returns a list containing the names of the arguments to procedure
@@ -37,8 +37,11 @@ Returns a count of the total number of commands that have been invoked
in this interpreter.
.TP
\fBinfo commands \fR?\fIpattern\fR?
-If \fIpattern\fR isn't specified,
-returns a list of names of all the Tcl commands in the current namespace,
+If \fIpattern\fR is not specified,
+.\" Do not move this .VS above the .TP
+.VS 8.5
+returns a list of names of all the Tcl commands visible
+(i.e. executable without using a qualified name) to the current namespace,
including both the built-in commands written in C and
the command procedures defined using the \fBproc\fR command.
If \fIpattern\fR is specified,
@@ -51,21 +54,25 @@ and may have pattern matching special characters
at the end to specify a set of commands in that namespace.
If \fIpattern\fR is a qualified name,
the resulting list of command names has each one qualified with the name
-of the specified namespace.
+of the specified namespace, and only the commands defined in the named
+namespace are returned.
+.\" Technically, most of this hasn't changed; that's mostly just the
+.\" way it always worked. Hardly anyone knew that though.
+.VE 8.5
.TP
\fBinfo complete \fIcommand\fR
Returns 1 if \fIcommand\fR is a complete Tcl command in the sense of
having no unclosed quotes, braces, brackets or array element names.
-If the command doesn't appear to be complete then 0 is returned.
+If the command does not appear to be complete then 0 is returned.
This command is typically used in line-oriented input environments
to allow users to type in commands that span multiple lines; if the
-command isn't complete, the script can delay evaluating it until additional
+command is not complete, the script can delay evaluating it until additional
lines have been typed to complete the command.
.TP
\fBinfo default \fIprocname arg varname\fR
\fIProcname\fR must be the name of a Tcl command procedure and \fIarg\fR
must be the name of an argument to that procedure. If \fIarg\fR
-doesn't have a default value then the command returns \fB0\fR.
+does not have a default value then the command returns \fB0\fR.
Otherwise it returns \fB1\fR and places the default value of \fIarg\fR
into variable \fIvarname\fR.
.TP
@@ -73,18 +80,125 @@ into variable \fIvarname\fR.
Returns \fB1\fR if the variable named \fIvarName\fR exists in the
current context (either as a global or local variable) and has been
defined by being given a value, returns \fB0\fR otherwise.
-.VS 8.4
+.TP
+\fBinfo frame\fR ?\fInumber\fR?
+This command provides access to all frames on the stack, even those
+hidden from \fBinfo level\fR. If \fInumber\fR is not specified, this
+command returns a number giving the frame level of the command. This
+is 1 if the command is invoked at top-level. If \fInumber\fR is
+specified, then the result is a dictionary containing the location
+information for the command at the \fInumber\fRed level on the stack.
+.RS
+.PP
+If \fInumber\fR is positive (> 0) then it selects a particular stack
+level (1 refers to the top-most active command, i.e., \fBinfo frame\fR
+itself, 2 to the command it was called from, and so on); otherwise it
+gives a level relative to the current command (0 refers to the current
+command, i.e., \fBinfo frame\fR itself, -1 to its caller, and so on).
+.PP
+This is similar to how \fBinfo level\fR works, except that this
+subcommand reports all frames, like \fBsource\fRd scripts,
+\fBeval\fRs, \fBuplevel\fRs, etc.
+.PP
+Note that for nested commands, like
+.QW "foo [bar [x]]" ,
+only
+.QW x
+will be seen by an \fBinfo frame\fR invoked within
+.QW x .
+This is the same as for \fBinfo level\fR and error stack traces.
+.PP
+The result dictionary may contain the keys listed below, with the
+specified meanings for their values:
+.TP
+\fBtype\fR
+This entry is always present and describes the nature of the location
+for the command. The recognized values are \fBsource\fR, \fBproc\fR,
+\fBeval\fR, and \fBprecompiled\fR.
+.RS
+.TP
+\fBsource\fR\0\0\0\0\0\0\0\0
+means that the command is found in a script loaded by the \fBsource\fR
+command.
+.TP
+\fBproc\fR\0\0\0\0\0\0\0\0
+means that the command is found in dynamically created procedure body.
+.TP
+\fBeval\fR\0\0\0\0\0\0\0\0
+means that the command is executed by \fBeval\fR or \fBuplevel\fR.
+.TP
+\fBprecompiled\fR\0\0\0\0\0\0\0\0
+means that the command is found in a precompiled script (loadable by
+the package \fBtbcload\fR), and no further information will be
+available.
+.RE
+.TP
+\fBline\fR
+This entry provides the number of the line the command is at inside of
+the script it is a part of. This information is not present for type
+\fBprecompiled\fR. For type \fBsource\fR this information is counted
+relative to the beginning of the file, whereas for the last two types
+the line is counted relative to the start of the script.
+.TP
+\fBfile\fR
+This entry is present only for type \fBsource\fR. It provides the
+normalized path of the file the command is in.
+.TP
+\fBcmd\fR
+This entry provides the string representation of the command. This is
+usually the unsubstituted form, however for commands which are a pure
+list executed by eval it is the substituted form as they have no other
+string representation. Care is taken that the pure-List property of
+the latter is not spoiled.
+.TP
+\fBproc\fR
+This entry is present only if the command is found in the body of a
+regular Tcl procedure. It then provides the name of that procedure.
+.TP
+\fBlambda\fR
+This entry is present only if the command is found in the body of an
+anonymous Tcl procedure, i.e. a lambda. It then provides the entire
+definition of the lambda in question.
+.TP
+\fBlevel\fR
+This entry is present only if the queried frame has a corresponding
+frame returned by \fBinfo level\fR. It provides the index of this
+frame, relative to the current level (0 and negative numbers).
+.PP
+A thing of note is that for procedures statically defined in files the
+locations of commands in their bodies will be reported with type
+\fBsource\fR and absolute line numbers, and not as type
+\fBproc\fR. The same is true for procedures nested in statically
+defined procedures, and literal eval scripts in files or statically
+defined procedures.
+.PP
+In contrast, a procedure definition or \fBeval\fR within a dynamically
+\fBeval\fRuated environment count linenumbers relative to the start of
+their script, even if they would be able to count relative to the
+start of the outer dynamic script. That type of number usually makes
+more sense.
+.PP
+A different way of describing this behaviour is that file based
+locations are tracked as deeply as possible, and where this is not
+possible the lines are counted based on the smallest possible
+\fBeval\fR or procedure body, as that scope is usually easier to find
+than any dynamic outer scope.
+.PP
+The syntactic form \fB{*}\fR is handled like \fBeval\fR. I.e. if it
+is given a literal list argument the system tracks the linenumber
+within the list words as well, and otherwise all linenumbers are
+counted relative to the start of each word (smallest scope)
+.RE
.TP
\fBinfo functions \fR?\fIpattern\fR?
-If \fIpattern\fR isn't specified, returns a list of all the math
+If \fIpattern\fR is not specified, returns a list of all the math
functions currently defined.
If \fIpattern\fR is specified, only those functions whose name matches
\fIpattern\fR are returned. Matching is determined using the same
rules as for \fBstring match\fR.
-.VE
.TP
\fBinfo globals \fR?\fIpattern\fR?
-If \fIpattern\fR isn't specified, returns a list of all the names
+If \fIpattern\fR is not specified, returns a list of all the names
of currently-defined global variables.
Global variables are variables in the global namespace.
If \fIpattern\fR is specified, only those names matching \fIpattern\fR
@@ -94,13 +208,11 @@ are returned. Matching is determined using the same rules as for
\fBinfo hostname\fR
Returns the name of the computer on which this invocation is being
executed.
-.VS
Note that this name is not guaranteed to be the fully qualified domain
name of the host. Where machines have several different names (as is
common on systems with both TCP/IP (DNS) and NetBIOS-based networking
installed,) it is the name that is suitable for TCP/IP networking that
is returned.
-.VE
.TP
\fBinfo level\fR ?\fInumber\fR?
If \fInumber\fR is not specified, this command returns a number
@@ -135,7 +247,7 @@ To get a list of just the packages in the current interpreter, specify
an empty string for the \fIinterp\fR argument.
.TP
\fBinfo locals \fR?\fIpattern\fR?
-If \fIpattern\fR isn't specified, returns a list of all the names
+If \fIpattern\fR is not specified, returns a list of all the names
of currently-defined local variables, including arguments to the
current procedure, if any.
Variables defined with the \fBglobal\fR, \fBupvar\fR and
@@ -154,7 +266,7 @@ Returns the value of the global variable \fBtcl_patchLevel\fR; see
the \fBtclvars\fR manual entry for more information.
.TP
\fBinfo procs \fR?\fIpattern\fR?
-If \fIpattern\fR isn't specified, returns a list of all the
+If \fIpattern\fR is not specified, returns a list of all the
names of Tcl command procedures in the current namespace.
If \fIpattern\fR is specified,
only those procedure names in the current namespace
@@ -180,7 +292,7 @@ Otherwise the command returns an empty string.
\fBinfo sharedlibextension\fR
Returns the extension used on this platform for the names of files
containing shared libraries (for example, \fB.so\fR under Solaris).
-If shared libraries aren't supported on this platform then an empty
+If shared libraries are not supported on this platform then an empty
string is returned.
.TP
\fBinfo tclversion\fR
@@ -188,7 +300,7 @@ Returns the value of the global variable \fBtcl_version\fR; see
the \fBtclvars\fR manual entry for more information.
.TP
\fBinfo vars\fR ?\fIpattern\fR?
-If \fIpattern\fR isn't specified,
+If \fIpattern\fR is not specified,
returns a list of all the names of currently-visible variables.
This includes locals and currently-visible globals.
If \fIpattern\fR is specified, only those names matching \fIpattern\fR
@@ -203,11 +315,14 @@ If \fIpattern\fR is a qualified name,
the resulting list of variable names
has each matching namespace variable qualified with the name
of its namespace.
-Note that a currently-visible variable may not yet "exist" if it has not
+Note that a currently-visible variable may not yet
+.QW exist
+if it has not
been set (e.g. a variable declared but not set by \fBvariable\fR).
.SH EXAMPLE
This command prints out a procedure suitable for saving in a Tcl
script:
+.PP
.CS
proc printProc {procName} {
set result [list proc $procName]
@@ -224,13 +339,10 @@ proc printProc {procName} {
puts [lappend result $formals [\fBinfo body\fR $procName]]
}
.CE
-
.SH "SEE ALSO"
global(n), proc(n)
-
.SH KEYWORDS
command, information, interpreter, level, namespace, procedure, variable
-
-'\" Local Variables:
-'\" mode: nroff
-'\" End:
+.\" Local Variables:
+.\" mode: nroff
+.\" End:
diff --git a/doc/interp.n b/doc/interp.n
index bbe7826..c753ee9 100644
--- a/doc/interp.n
+++ b/doc/interp.n
@@ -1,5 +1,6 @@
'\"
'\" Copyright (c) 1995-1996 Sun Microsystems, Inc.
+'\" Copyright (c) 2004 Donal K. Fellows
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -11,15 +12,14 @@
.SH NAME
interp \- Create and manipulate Tcl interpreters
.SH SYNOPSIS
-\fBinterp \fIoption \fR?\fIarg arg ...\fR?
+\fBinterp \fIsubcommand \fR?\fIarg arg ...\fR?
.BE
-
.SH DESCRIPTION
.PP
-This command makes it possible to create one or more new Tcl
+This command makes it possible to create one or more new Tcl
interpreters that co-exist with the creating interpreter in the
same application. The creating interpreter is called the \fImaster\fR
-and the new interpreter is called a \fIslave\fR.
+and the new interpreter is called a \fIslave\fR.
A master can create any number of slaves, and each slave can
itself create additional slaves for which it is master, resulting
in a hierarchy of interpreters.
@@ -32,7 +32,11 @@ a command in a slave interpreter which, when invoked, causes a
command to be invoked in its master interpreter or in another slave
interpreter. The only other connections between interpreters are
through environment variables (the \fBenv\fR variable), which are
-normally shared among all interpreters in the application. Note that the
+normally shared among all interpreters in the application,
+.VS 8.5
+and by resource limit exceeded callbacks.
+.VE 8.5
+Note that the
name space for files (such as the names returned by the \fBopen\fR command)
is no longer shared between interpreters. Explicit commands are provided to
share files and to transfer references to open files from one interpreter
@@ -45,7 +49,6 @@ scripts without fear of them damaging other interpreters or the
application's environment. For example, all IO channel creation
commands and subprocess creation commands are made inaccessible to safe
interpreters.
-.VS
See \fBSAFE INTERPRETERS\fR below for more information on
what features are present in a safe interpreter.
The dangerous functionality is not removed from the safe interpreter;
@@ -53,10 +56,9 @@ instead, it is \fIhidden\fR, so that only trusted interpreters can obtain
access to it. For a detailed explanation of hidden commands, see
\fBHIDDEN COMMANDS\fR, below.
The alias mechanism can be used for protected communication (analogous to a
-kernel call) between a slave interpreter and its master.
-See \fBALIAS INVOCATION\fR, below, for more details
+kernel call) between a slave interpreter and its master.
+See \fBALIAS INVOCATION\fR, below, for more details
on how the alias mechanism works.
-.VE
.PP
A qualified interpreter name is a proper Tcl lists containing a subset of its
ancestors in the interpreter hierarchy, terminated by the string naming the
@@ -78,7 +80,7 @@ Both restrictions are motivated by safety concerns.
The \fBinterp\fR command is used to create, delete, and manipulate
slave interpreters, and to share or transfer
channels between interpreters. It can have any of several forms, depending
-on the \fIoption\fR argument:
+on the \fIsubcommand\fR argument:
.TP
\fBinterp\fR \fBalias\fR \fIsrcPath\fR \fIsrcToken\fR
Returns a Tcl list whose elements are the \fItargetCmd\fR and
@@ -102,7 +104,9 @@ may be anywhere in the hierarchy of interpreters under the interpreter
invoking the command.
\fISrcPath\fR and \fIsrcCmd\fR identify the source of the alias.
\fISrcPath\fR is a Tcl list whose elements select a particular
-interpreter. For example, ``\fBa b\fR'' identifies an interpreter
+interpreter. For example,
+.QW "\fBa b\fR"
+identifies an interpreter
\fBb\fR, which is a slave of interpreter \fBa\fR, which is a slave
of the invoking interpreter. An empty list specifies the interpreter
invoking the command. \fIsrcCmd\fR gives the name of a new
@@ -116,7 +120,7 @@ already exist; it is not created by this command.
The alias arranges for the given target command to be invoked
in the target interpreter whenever the given source command is
invoked in the source interpreter. See \fBALIAS INVOCATION\fR below for
-more details.
+more details.
The command returns a token that uniquely identifies the command created
\fIsrcCmd\fR, even if the command is renamed afterwards. The token may but
does not have to be equal to \fIsrcCmd\fR.
@@ -124,16 +128,26 @@ does not have to be equal to \fIsrcCmd\fR.
\fBinterp\fR \fBaliases \fR?\fIpath\fR?
This command returns a Tcl list of the tokens of all the source commands for
aliases defined in the interpreter identified by \fIpath\fR. The tokens
-correspond to the values returned when
-the aliases were created (which may not be the same
+correspond to the values returned when
+the aliases were created (which may not be the same
as the current names of the commands).
.TP
+\fBinterp bgerror \fIpath\fR ?\fIcmdPrefix\fR?
+.VS 8.5
+This command either gets or sets the current background error handler
+for the interpreter identified by \fIpath\fR. If \fIcmdPrefix\fR is
+absent, the current background error handler is returned, and if it is
+present, it is a list of words (of minimum length one) that describes
+what to set the interpreter's background error to. See the
+\fBBACKGROUND ERROR HANDLING\fR section for more details.
+.VE 8.5
+.TP
\fBinterp\fR \fBcreate \fR?\fB\-safe\fR? ?\fB\-\|\-\fR? ?\fIpath\fR?
Creates a slave interpreter identified by \fIpath\fR and a new command,
called a \fIslave command\fR. The name of the slave command is the last
component of \fIpath\fR. The new slave interpreter and the slave command
are created in the interpreter identified by the path obtained by removing
-the last component from \fIpath\fR. For example, if \fIpath is \fBa b
+the last component from \fIpath\fR. For example, if \fIpath\fR is \fBa b
c\fR then a new slave interpreter and slave command named \fBc\fR are
created in the interpreter identified by the path \fBa b\fR.
The slave command may be used to manipulate the new interpreter as
@@ -152,6 +166,44 @@ given name already exists in this master.
The initial recursion limit of the slave interpreter is set to the
current recursion limit of its parent interpreter.
.TP
+\fBinterp\fR \fBdebug \fIpath\fR ?\fI\-frame\fR ?\fIbool\fR??
+.
+Controls whether frame-level stack information is captured in the
+slave interpreter identified by \fIpath\fR. If no arguments are
+given, option and current setting are returned. If \fI\-frame\fR
+is given, the debug setting is set to the given boolean if provided
+and the current setting is returned.
+This only effects the output of \fBinfo frame\fR, in that exact
+frame-level information for command invocation at the bytecode level
+is only captured with this setting on.
+.PP
+.RS
+For example, with code like
+.PP
+.CS
+\fBproc\fR mycontrol {... script} {
+ ...
+ \fBuplevel\fR 1 $script
+ ...
+}
+
+\fBproc\fR dosomething {...} {
+ ...
+ mycontrol {
+ somecode
+ }
+}
+.CE
+.PP
+the standard setting will provide a relative line number for the
+command \fBsomecode\fR and the relevant frame will be of type
+\fBeval\fR. With frame-debug active on the other hand the tracking
+extends so far that the system will be able to determine the file and
+absolute line number of this command, and return a frame of type
+\fBsource\fR. This more exact information is paid for with slower
+execution of all commands.
+.RE
+.TP
\fBinterp\fR \fBdelete \fR?\fIpath ...?\fR
Deletes zero or more interpreters given by the optional \fIpath\fR
arguments, and for each interpreter, it also deletes its slaves. The
@@ -163,9 +215,9 @@ exists, the command raises an error.
This command concatenates all of the \fIarg\fR arguments in the same
fashion as the \fBconcat\fR command, then evaluates the resulting string as
a Tcl script in the slave interpreter identified by \fIpath\fR. The result
-of this evaluation (including error information such as the \fBerrorInfo\fR
-and \fBerrorCode\fR variables, if an error occurs) is returned to the
-invoking interpreter.
+of this evaluation (including all \fBreturn\fR options,
+such as \fB\-errorinfo\fR and \fB\-errorcode\fR information, if an
+error occurs) is returned to the invoking interpreter.
Note that the script will be executed in the current context stack frame of the
\fIpath\fR interpreter; this is so that the implementations (in a master
interpreter) of aliases in a slave interpreter can execute scripts in
@@ -173,10 +225,9 @@ the slave that find out information about the slave's current state
and stack frame.
.TP
\fBinterp exists \fIpath\fR
-Returns \fB1\fR if a slave interpreter by the specified \fIpath\fR
+Returns \fB1\fR if a slave interpreter by the specified \fIpath\fR
exists in this master, \fB0\fR otherwise. If \fIpath\fR is omitted, the
invoking interpreter is used.
-.VS "" BR
.TP
\fBinterp expose \fIpath\fR \fIhiddenName\fR ?\fIexposedCmdName\fR?
Makes the hidden command \fIhiddenName\fR exposed, eventually bringing
@@ -191,11 +242,11 @@ Hidden commands are explained in more detail in \fBHIDDEN COMMANDS\fR, below.
\fBinterp\fR \fBhide\fR \fIpath\fR \fIexposedCmdName\fR ?\fIhiddenCmdName\fR?
Makes the exposed command \fIexposedCmdName\fR hidden, renaming
it to the hidden command \fIhiddenCmdName\fR, or keeping the same name if
-\fIhiddenCmdName\fR is not given, in the interpreter denoted
+\fIhiddenCmdName\fR is not given, in the interpreter denoted
by \fIpath\fR.
If a hidden command with the targeted name already exists, this command
fails.
-Currently both \fIexposedCmdName\fR and \fIhiddenCmdName\fR can
+Currently both \fIexposedCmdName\fR and \fIhiddenCmdName\fR can
not contain namespace qualifiers, or an error is raised.
Commands to be hidden by \fBinterp hide\fR are looked up in the global
namespace even if the current namespace is not the global one. This
@@ -207,21 +258,41 @@ Hidden commands are explained in more detail in \fBHIDDEN COMMANDS\fR, below.
Returns a list of the names of all hidden commands in the interpreter
identified by \fIpath\fR.
.TP
-\fBinterp\fR \fBinvokehidden\fR \fIpath\fR ?\fB-global\fR? \fIhiddenCmdName\fR ?\fIarg ...\fR?
+\fBinterp\fR \fBinvokehidden\fR \fIpath\fR ?\fI\-option ...\fR? \fIhiddenCmdName\fR ?\fIarg ...\fR?
Invokes the hidden command \fIhiddenCmdName\fR with the arguments supplied
in the interpreter denoted by \fIpath\fR. No substitutions or evaluation
-are applied to the arguments.
-If the \fB-global\fR flag is present, the hidden command is invoked at the
+are applied to the arguments. Three \fI\-option\fRs are supported, all
+of which start with \fB\-\fR: \fB\-namespace\fR (which takes a single
+argument afterwards, \fInsName\fR), \fB\-global\fR, and \fB\-\|\-\fR.
+If the \fB\-namespace\fR flag is present, the hidden command is invoked in
+the namespace called \fInsName\fR in the target interpreter.
+If the \fB\-global\fR flag is present, the hidden command is invoked at the
global level in the target interpreter; otherwise it is invoked at the
current call frame and can access local variables in that and outer call
frames.
+The \fB\-\|\-\fR flag allows the \fIhiddenCmdName\fR argument to start with a
+.QW \-
+character, and is otherwise unnecessary.
+If both the \fB\-namespace\fR and \fB\-global\fR flags are present, the
+\fB\-namespace\fR flag is ignored.
+Note that the hidden command will be executed (by default) in the
+current context stack frame of the \fIpath\fR interpreter.
Hidden commands are explained in more detail in \fBHIDDEN COMMANDS\fR, below.
-.VE
+.TP
+\fBinterp\fR \fBlimit\fR \fIpath\fR \fIlimitType\fR ?\fI\-option\fR? ?\fIvalue\fR \fI...\fR?
+.VS 8.5
+Sets up, manipulates and queries the configuration of the resource
+limit \fIlimitType\fR for the interpreter denoted by \fIpath\fR. If
+no \fI\-option\fR is specified, return the current configuration of the
+limit. If \fI\-option\fR is the sole argument, return the value of that
+option. Otherwise, a list of \fI\-option\fR/\fIvalue\fR argument pairs
+must supplied. See \fBRESOURCE LIMITS\fR below for a more detailed
+explanation of what limits and options are supported.
+.VE 8.5
.TP
\fBinterp issafe\fR ?\fIpath\fR?
Returns \fB1\fR if the interpreter identified by the specified \fIpath\fR
is safe, \fB0\fR otherwise.
-.VS "" BR
.TP
\fBinterp marktrusted\fR \fIpath\fR
Marks the interpreter identified by \fIpath\fR as trusted. Does
@@ -229,7 +300,6 @@ not expose the hidden commands. This command can only be invoked from a
trusted interpreter.
The command has no effect if the interpreter identified by \fIpath\fR is
already trusted.
-.VE
.TP
\fBinterp\fR \fBrecursionlimit\fR \fIpath\fR ?\fInewlimit\fR?
Returns the maximum allowable nesting depth for the interpreter
@@ -239,14 +309,16 @@ of more than \fInewlimit\fR calls to \fBTcl_Eval()\fR
and related procedures in that interpreter will return an error.
The \fInewlimit\fR value is also returned.
The \fInewlimit\fR value must be a positive integer between 1 and the
-maximum value of a non-long integer on the platform.
-.sp
+maximum value of a non-long integer on the platform.
+.RS
+.PP
The command sets the maximum size of the Tcl call stack only. It cannot
by itself prevent stack overflows on the C stack being used by the
application. If your machine has a limit on the size of the C stack, you
may get stack overflows before reaching the limit set by the command. If
this happens, see if there is a mechanism in your system for increasing
-the maximum size of the C stack.
+the maximum size of the C stack.
+.RE
.TP
\fBinterp\fR \fBshare\fR \fIsrcPath channelId destPath\fR
Causes the IO channel identified by \fIchannelId\fR to become shared
@@ -293,7 +365,7 @@ The valid forms of this command are:
\fIslave \fBaliases\fR
Returns a Tcl list whose elements are the tokens of all the
aliases in \fIslave\fR. The tokens correspond to the values returned when
-the aliases were created (which may not be the same
+the aliases were created (which may not be the same
as the current names of the commands).
.TP
\fIslave \fBalias \fIsrcToken\fR
@@ -320,19 +392,28 @@ The command returns a token that uniquely identifies the command created
\fIsrcCmd\fR, even if the command is renamed afterwards. The token may but
does not have to be equal to \fIsrcCmd\fR.
.TP
+\fIslave \fBbgerror\fR ?\fIcmdPrefix\fR?
+.VS 8.5
+This command either gets or sets the current background error handler
+for the \fIslave\fR interpreter. If \fIcmdPrefix\fR is
+absent, the current background error handler is returned, and if it is
+present, it is a list of words (of minimum length one) that describes
+what to set the interpreter's background error to. See the
+\fBBACKGROUND ERROR HANDLING\fR section for more details.
+.VE 8.5
+.TP
\fIslave \fBeval \fIarg \fR?\fIarg ..\fR?
This command concatenates all of the \fIarg\fR arguments in
the same fashion as the \fBconcat\fR command, then evaluates
the resulting string as a Tcl script in \fIslave\fR.
-The result of this evaluation (including error information
-such as the \fBerrorInfo\fR and \fBerrorCode\fR variables, if an
+The result of this evaluation (including all \fBreturn\fR options,
+such as \fB\-errorinfo\fR and \fB\-errorcode\fR information, if an
error occurs) is returned to the invoking interpreter.
Note that the script will be executed in the current context stack frame
of \fIslave\fR; this is so that the implementations (in a master
interpreter) of aliases in a slave interpreter can execute scripts in
the slave that find out information about the slave's current state
and stack frame.
-.VS "" BR
.TP
\fIslave \fBexpose \fIhiddenName \fR?\fIexposedCmdName\fR?
This command exposes the hidden command \fIhiddenName\fR, eventually bringing
@@ -344,12 +425,12 @@ fails.
For more details on hidden commands, see \fBHIDDEN COMMANDS\fR, below.
.TP
\fIslave \fBhide \fIexposedCmdName\fR ?\fIhiddenCmdName\fR?
-This command hides the exposed command \fIexposedCmdName\fR, renaming it to
+This command hides the exposed command \fIexposedCmdName\fR, renaming it to
the hidden command \fIhiddenCmdName\fR, or keeping the same name if the
argument is not given, in the \fIslave\fR interpreter.
If a hidden command with the targeted name already exists, this command
fails.
-Currently both \fIexposedCmdName\fR and \fIhiddenCmdName\fR can
+Currently both \fIexposedCmdName\fR and \fIhiddenCmdName\fR can
not contain namespace qualifiers, or an error is raised.
Commands to be hidden are looked up in the global
namespace even if the current namespace is not the global one. This
@@ -360,27 +441,46 @@ For more details on hidden commands, see \fBHIDDEN COMMANDS\fR, below.
\fIslave \fBhidden\fR
Returns a list of the names of all hidden commands in \fIslave\fR.
.TP
-\fIslave \fBinvokehidden\fR ?\fB-global\fR \fIhiddenName \fR?\fIarg ..\fR?
+\fIslave \fBinvokehidden\fR ?\fI\-option ...\fR? \fIhiddenName \fR?\fIarg ..\fR?
This command invokes the hidden command \fIhiddenName\fR with the
supplied arguments, in \fIslave\fR. No substitutions or evaluations are
-applied to the arguments.
-If the \fB-global\fR flag is given, the command is invoked at the global
+applied to the arguments. Three \fI\-option\fRs are supported, all
+of which start with \fB\-\fR: \fB\-namespace\fR (which takes a single
+argument afterwards, \fInsName\fR), \fB\-global\fR, and \fB\-\|\-\fR.
+If the \fB\-namespace\fR flag is given, the hidden command is invoked in
+the specified namespace in the slave.
+If the \fB\-global\fR flag is given, the command is invoked at the global
level in the slave; otherwise it is invoked at the current call frame and
can access local variables in that or outer call frames.
+The \fB\-\|\-\fR flag allows the \fIhiddenCmdName\fR argument to start with a
+.QW \-
+character, and is otherwise unnecessary.
+If both the \fB\-namespace\fR and \fB\-global\fR flags are given, the
+\fB\-namespace\fR flag is ignored.
+Note that the hidden command will be executed (by default) in the
+current context stack frame of \fIslave\fR.
For more details on hidden commands,
see \fBHIDDEN COMMANDS\fR, below.
-.VE
.TP
\fIslave \fBissafe\fR
Returns \fB1\fR if the slave interpreter is safe, \fB0\fR otherwise.
-.VS "" BR
+.TP
+\fIslave \fBlimit\fR \fIlimitType\fR ?\fI\-option\fR? ?\fIvalue\fR \fI...\fR?
+.VS 8.5
+Sets up, manipulates and queries the configuration of the resource
+limit \fIlimitType\fR for the slave interpreter. If no \fI\-option\fR
+is specified, return the current configuration of the limit. If
+\fI\-option\fR is the sole argument, return the value of that option.
+Otherwise, a list of \fI\-option\fR/\fIvalue\fR argument pairs must
+supplied. See \fBRESOURCE LIMITS\fR below for a more detailed explanation of
+what limits and options are supported.
+.VE 8.5
.TP
\fIslave \fBmarktrusted\fR
Marks the slave interpreter as trusted. Can only be invoked by a
trusted interpreter. This command does not expose any hidden
commands in the slave interpreter. The command has no effect if the slave
is already trusted.
-.VE
.TP
\fIslave\fR \fBrecursionlimit\fR ?\fInewlimit\fR?
Returns the maximum allowable nesting depth for the \fIslave\fR interpreter.
@@ -389,14 +489,16 @@ set so that nesting of more than \fInewlimit\fR calls to \fBTcl_Eval()\fR
and related procedures in \fIslave\fR will return an error.
The \fInewlimit\fR value is also returned.
The \fInewlimit\fR value must be a positive integer between 1 and the
-maximum value of a non-long integer on the platform.
-.sp
+maximum value of a non-long integer on the platform.
+.RS
+.PP
The command sets the maximum size of the Tcl call stack only. It cannot
by itself prevent stack overflows on the C stack being used by the
application. If your machine has a limit on the size of the C stack, you
may get stack overflows before reaching the limit set by the command. If
this happens, see if there is a mechanism in your system for increasing
-the maximum size of the C stack.
+the maximum size of the C stack.
+.RE
.SH "SAFE INTERPRETERS"
.PP
A safe interpreter is one with restricted functionality, so that
@@ -422,32 +524,33 @@ A safe interpreter is created with exactly the following set of
built-in commands:
.DS
.ta 1.2i 2.4i 3.6i
-\fBafter append array binary
-break case catch clock
-close concat continue eof
-error eval expr fblocked
-fcopy fileevent flush for
-foreach format gets global
-if incr info interp
-join lappend lindex linsert
-list llength lrange lreplace
-lsearch lsort namespace package
-pid proc puts read
-regexp regsub rename return
-scan seek set split
-string subst switch tell
-time trace unset update
-uplevel upvar variable vwait
-while\fR
+\fBafter\fR \fBappend\fR \fBapply\fR \fBarray\fR
+\fBbinary\fR \fBbreak\fR \fBcatch\fR \fBchan\fR
+\fBclock\fR \fBclose\fR \fBconcat\fR \fBcontinue\fR
+\fBdict\fR \fBeof\fR \fBerror\fR \fBeval\fR
+\fBexpr\fR \fBfblocked\fR \fBfcopy\fR \fBfileevent\fR
+\fBflush\fR \fBfor\fR \fBforeach\fR \fBformat\fR
+\fBgets\fR \fBglobal\fR \fBif\fR \fBincr\fR
+\fBinfo\fR \fBinterp\fR \fBjoin\fR \fBlappend\fR
+\fBlassign\fR \fBlindex\fR \fBlinsert\fR \fBlist\fR
+\fBllength\fR \fBlrange\fR \fBlrepeat\fR \fBlreplace\fR
+\fBlsearch\fR \fBlset\fR \fBlsort\fR \fBnamespace\fR
+\fBpackage\fR \fBpid\fR \fBproc\fR \fBputs\fR
+\fBread\fR \fBregexp\fR \fBregsub\fR \fBrename\fR
+\fBreturn\fR \fBscan\fR \fBseek\fR \fBset\fR
+\fBsplit\fR \fBstring\fR \fBsubst\fR \fBswitch\fR
+\fBtell\fR \fBtime\fR \fBtrace\fR \fBunset\fR
+\fBupdate\fR \fBuplevel\fR \fBupvar\fR \fBvariable\fR
+\fBvwait\fR \fBwhile\fR
.DE
-.VS "" BR
The following commands are hidden by \fBinterp create\fR when it
creates a safe interpreter:
.DS
.ta 1.2i 2.4i 3.6i
-\fBcd encoding exec exit
-fconfigure file glob load
-open pwd socket source\fR
+\fBcd\fR \fBencoding\fR \fBexec\fR \fBexit\fR
+\fBfconfigure\fR \fBfile\fR \fBglob\fR \fBload\fR
+\fBopen\fR \fBpwd\fR \fBsocket\fR \fBsource\fR
+\fBunload\fR
.DE
These commands can be recreated later as Tcl procedures or aliases, or
re-exposed by \fBinterp expose\fR.
@@ -456,25 +559,24 @@ The following commands from Tcl's library of support procedures are
not present in a safe interpreter:
.DS
.ta 1.6i 3.2i
-\fBauto_exec_ok auto_import auto_load
-auto_load_index auto_qualify unknown\fR
+\fBauto_exec_ok\fR \fBauto_import\fR \fBauto_load\fR
+\fBauto_load_index\fR \fBauto_qualify\fR \fBunknown\fR
.DE
Note in particular that safe interpreters have no default \fBunknown\fR
-command, so Tcl's default autoloading facilities are not available.
+command, so Tcl's default autoloading facilities are not available.
Autoload access to Tcl's commands that are normally autoloaded:
.DS
.ta 2.1i
-\fB
-auto_mkindex auto_mkindex_old
-auto_reset history
-parray pkg_mkIndex
-::pkg::create ::safe::interpAddToAccessPath
-::safe::interpCreate ::safe::interpConfigure
-::safe::interpDelete ::safe::interpFindInAccessPath
-::safe::interpInit ::safe::setLogCmd
-tcl_endOfWord tcl_findLibrary
-tcl_startOfNextWord tcl_startOfPreviousWord
-tcl_wordBreakAfter tcl_wordBreakBefore\fR
+\fBauto_mkindex\fR \fBauto_mkindex_old\fR
+\fBauto_reset\fR \fBhistory\fR
+\fBparray\fR \fBpkg_mkIndex\fR
+\fB::pkg::create\fR \fB::safe::interpAddToAccessPath\fR
+\fB::safe::interpCreate\fR \fB::safe::interpConfigure\fR
+\fB::safe::interpDelete\fR \fB::safe::interpFindInAccessPath\fR
+\fB::safe::interpInit\fR \fB::safe::setLogCmd\fR
+\fBtcl_endOfWord\fR \fBtcl_findLibrary\fR
+\fBtcl_startOfNextWord\fR \fBtcl_startOfPreviousWord\fR
+\fBtcl_wordBreakAfter\fR \fBtcl_wordBreakBefore\fR
.DE
can only be provided by explicit definition of an \fBunknown\fR command
in the safe interpreter. This will involve exposing the \fBsource\fR
@@ -482,7 +584,6 @@ command. This is most easily accomplished by creating the safe interpreter
with Tcl's \fBSafe\-Tcl\fR mechanism. \fBSafe\-Tcl\fR provides safe
versions of \fBsource\fR, \fBload\fR, and other Tcl commands needed
to support autoloading of commands and the loading of packages.
-.VE
.PP
In addition, the \fBenv\fR variable is not present in a safe interpreter,
so it cannot share environment variables with other interpreters. The
@@ -518,9 +619,10 @@ as they would be for any other command invoked in that interpreter.
The command procedure for the source command takes its arguments
and merges them with the \fItargetCmd\fR and \fIarg\fRs for the
alias to create a new array of arguments. If the words
-of \fIsrcCmd\fR were ``\fIsrcCmd arg1 arg2 ... argN\fR'',
+of \fIsrcCmd\fR were
+.QW "\fIsrcCmd arg1 arg2 ... argN\fR" ,
the new set of words will be
-``\fItargetCmd arg arg ... arg arg1 arg2 ... argN\fR'',
+.QW "\fItargetCmd arg arg ... arg arg1 arg2 ... argN\fR" ,
where \fItargetCmd\fR and \fIarg\fRs are the values supplied when the
alias was created. \fITargetCmd\fR is then used to locate a command
procedure in the target interpreter, and that command procedure
@@ -540,7 +642,6 @@ evaluated or substituted, since this would provide an escape
mechanism whereby the slave interpreter could execute arbitrary
code in the master. This in turn would compromise the security
of the system.
-.VS
.SH "HIDDEN COMMANDS"
.PP
Safe interpreters greatly restrict the functionality available to Tcl
@@ -608,10 +709,108 @@ Commands to be hidden by \fBinterp hide\fR are looked up in the global
namespace even if the current namespace is not the global one. This
prevents slaves from fooling a master interpreter into hiding the wrong
command, by making the current namespace be different from the global one.
-.VE
-.SH CREDITS
+.SH "RESOURCE LIMITS"
+.VS 8.5
.PP
-This mechanism is based on the Safe-Tcl prototype implemented
+Every interpreter has two kinds of resource limits that may be imposed by any
+master interpreter upon its slaves. Command limits (of type \fBcommand\fR)
+restrict the total number of Tcl commands that may be executed by an
+interpreter (as can be inspected via the \fBinfo cmdcount\fR command), and
+time limits (of type \fBtime\fR) place a limit by which execution within the
+interpreter must complete. Note that time limits are expressed as
+\fIabsolute\fR times (as in \fBclock seconds\fR) and not relative times (as in
+\fBafter\fR) because they may be modified after creation.
+.PP
+When a limit is exceeded for an interpreter, first any handler callbacks
+defined by master interpreters are called. If those callbacks increase or
+remove the limit, execution within the (previously) limited interpreter
+continues. If the limit is still in force, an error is generated at that point
+and normal processing of errors within the interpreter (by the \fBcatch\fR
+command) is disabled, so the error propagates outwards (building a stack-trace
+as it goes) to the point where the limited interpreter was invoked (e.g. by
+\fBinterp eval\fR) where it becomes the responsibility of the calling code to
+catch and handle.
+.SS "LIMIT OPTIONS"
+.PP
+Every limit has a number of options associated with it, some of which are
+common across all kinds of limits, and others of which are particular to the
+kind of limit.
+.VE 8.5
+.TP
+\fB\-command\fR
+.VS 8.5
+This option (common for all limit types) specifies (if non-empty) a Tcl script
+to be executed in the global namespace of the interpreter reading and writing
+the option when the particular limit in the limited interpreter is exceeded.
+The callback may modify the limit on the interpreter if it wishes the limited
+interpreter to continue executing. If the callback generates an error, it is
+reported through the background error mechanism (see \fBBACKGROUND ERROR
+HANDLING\fR). Note that the callbacks defined by one interpreter are
+completely isolated from the callbacks defined by another, and that the order
+in which those callbacks are called is undefined.
+.VE 8.5
+.TP
+\fB\-granularity\fR
+.VS 8.5
+This option (common for all limit types) specifies how frequently (out of the
+points when the Tcl interpreter is in a consistent state where limit checking
+is possible) that the limit is actually checked. This allows the tuning of how
+frequently a limit is checked, and hence how often the limit-checking overhead
+(which may be substantial in the case of time limits) is incurred.
+.VE 8.5
+.TP
+\fB\-milliseconds\fR
+.VS 8.5
+This option specifies the number of milliseconds after the moment defined in
+the \fB\-seconds\fR option that the time limit will fire. It should only ever
+be specified in conjunction with the \fB\-seconds\fR option (whether it was
+set previously or is being set this invocation.)
+.VE 8.5
+.TP
+\fB\-seconds\fR
+.VS 8.5
+This option specifies the number of seconds after the epoch (see \fBclock
+seconds\fR) that the time limit for the interpreter will be triggered. The
+limit will be triggered at the start of the second unless specified at a
+sub-second level using the \fB\-milliseconds\fR option. This option may be the
+empty string, which indicates that a time limit is not set for the
+interpreter.
+.VE 8.5
+.TP
+\fB\-value\fR
+.VS 8.5
+This option specifies the number of commands that the interpreter may execute
+before triggering the command limit. This option may be the empty string,
+which indicates that a command limit is not set for the interpreter.
+.PP
+Where an interpreter with a resource limit set on it creates a slave
+interpreter, that slave interpreter will have resource limits imposed on it
+that are at least as restrictive as the limits on the creating master
+interpreter. If the master interpreter of the limited master wishes to relax
+these conditions, it should hide the \fBinterp\fR command in the child and
+then use aliases and the \fBinterp invokehidden\fR subcommand to provide such
+access as it chooses to the \fBinterp\fR command to the limited master as
+necessary.
+.SH "BACKGROUND ERROR HANDLING"
+.PP
+When an error happens in a situation where it cannot be reported directly up
+the stack (e.g. when processing events in an \fBupdate\fR or \fBvwait\fR call)
+the error is instead reported through the background error handling mechanism.
+Every interpreter has a background error handler registered; the default error
+handler arranges for the \fBbgerror\fR command in the interpreter's global
+namespace to be called, but other error handlers may be installed and process
+background errors in substantially different ways.
+.PP
+A background error handler consists of a non-empty list of words to which will
+be appended two further words at invocation time. The first word will be the
+error message string, and the second will a dictionary of return options (this
+is also the sort of information that can be obtained by trapping a normal
+error using \fBcatch\fR of course.) The resulting list will then be executed
+in the interpreter's global namespace without further substitutions being
+performed.
+.VE 8.5
+.SH CREDITS
+The safe interpreter mechanism is based on the Safe-Tcl prototype implemented
by Nathaniel Borenstein and Marshall Rose.
.SH EXAMPLES
Creating and using an alias for a command in the current interpreter:
@@ -621,22 +820,33 @@ set idx [getIndex delta]
.CE
.PP
Executing an arbitrary command in a safe interpreter where every
-invokation of \fBlappend\fR is logged:
+invocation of \fBlappend\fR is logged:
.CS
set i [\fBinterp create\fR -safe]
\fBinterp hide\fR $i lappend
\fBinterp alias\fR $i lappend {} loggedLappend $i
proc loggedLappend {i args} {
- puts "logged invokation of lappend $args"
- # Be extremely careful about command construction
- eval [linsert $args 0 \\
- \fBinterp invokehidden\fR $i lappend]
+ puts "logged invocation of lappend $args"
+ \fBinterp invokehidden\fR $i lappend {*}$args
}
\fBinterp eval\fR $i $someUntrustedScript
.CE
-
+.PP
+.VS 8.5
+Setting a resource limit on an interpreter so that an infinite loop
+terminates.
+.CS
+set i [\fBinterp create\fR]
+\fBinterp limit\fR $i command -value 1000
+\fBinterp eval\fR $i {
+ set x 0
+ while {1} {
+ puts "Counting up... [incr x]"
+ }
+}
+.CE
+.VE 8.5
.SH "SEE ALSO"
-load(n), safe(n), Tcl_CreateSlave(3)
-
+bgerror(n), load(n), safe(n), Tcl_CreateSlave(3)
.SH KEYWORDS
alias, master interpreter, safe interpreter, slave interpreter
diff --git a/doc/join.n b/doc/join.n
index f28c07c..582b730 100644
--- a/doc/join.n
+++ b/doc/join.n
@@ -27,14 +27,14 @@ Making a comma-separated list:
.CS
set data {1 2 3 4 5}
\fBjoin\fR $data ", "
- \fB=> 1, 2, 3, 4, 5\fR
+ \fB\(-> 1, 2, 3, 4, 5\fR
.CE
.PP
Using \fBjoin\fR to flatten a list by a single level:
.CS
set data {1 {2 3} 4 {5 {6 7} 8}}
\fBjoin\fR $data
- \fB=> 1 2 3 4 5 {6 7} 8\fR
+ \fB\(-> 1 2 3 4 5 {6 7} 8\fR
.CE
.SH "SEE ALSO"
diff --git a/doc/lappend.n b/doc/lappend.n
index cb5d7fa..dbed3bb 100644
--- a/doc/lappend.n
+++ b/doc/lappend.n
@@ -1,7 +1,7 @@
'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
-'\" Copyright (c) 2001 Kevin B. Kenny. All rights reserved.
+'\" Copyright (c) 2001 Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -21,14 +21,16 @@ lappend \- Append list elements onto a variable
This command treats the variable given by \fIvarName\fR as a list
and appends each of the \fIvalue\fR arguments to that list as a separate
element, with spaces between elements.
-If \fIvarName\fR doesn't exist, it is created as a list with elements
+If \fIvarName\fR does not exist, it is created as a list with elements
given by the \fIvalue\fR arguments.
\fBLappend\fR is similar to \fBappend\fR except that the \fIvalue\fRs
are appended as list elements rather than raw text.
This command provides a relatively efficient way to build up
-large lists. For example, ``\fBlappend a $b\fR'' is much
-more efficient than ``\fBset a [concat $a [list $b]]\fR'' when
-\fB$a\fR is long.
+large lists. For example,
+.QW "\fBlappend a $b\fR"
+is much more efficient than
+.QW "\fBset a [concat $a [list $b]]\fR"
+when \fB$a\fR is long.
.SH EXAMPLE
Using \fBlappend\fR to build up a list of numbers.
.CS
@@ -41,10 +43,7 @@ Using \fBlappend\fR to build up a list of numbers.
.CE
.SH "SEE ALSO"
-list(n), lindex(n), linsert(n), llength(n),
-.VS 8.4
-lset(n)
-.VE
+list(n), lindex(n), linsert(n), llength(n), lset(n),
lsort(n), lrange(n)
.SH KEYWORDS
diff --git a/doc/lassign.n b/doc/lassign.n
new file mode 100644
index 0000000..b791feb
--- /dev/null
+++ b/doc/lassign.n
@@ -0,0 +1,55 @@
+'\"
+'\" Copyright (c) 1992-1999 Karl Lehenbauer & Mark Diekhans
+'\" Copyright (c) 2004 Donal K. Fellows
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.so man.macros
+.TH lassign n 8.5 Tcl "Tcl Built-In Commands"
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+lassign \- Assign list elements to variables
+.SH SYNOPSIS
+\fBlassign \fIlist varName \fR?\fIvarName ...\fR?
+.BE
+
+.SH DESCRIPTION
+.PP
+This command treats the value \fIlist\fR as a list and assigns
+successive elements from that list to the variables given by the
+\fIvarName\fR arguments in order. If there are more variable names
+than list elements, the remaining variables are set to the empty
+string. If there are more list elements than variables, a list of
+unassigned elements is returned.
+.SH EXAMPLES
+An illustration of how multiple assignment works, and what happens
+when there are either too few or too many elements.
+.CS
+lassign {a b c} x y z ;# Empty return
+puts $x ;# Prints "a"
+puts $y ;# Prints "b"
+puts $z ;# Prints "c"
+
+lassign {d e} x y z ;# Empty return
+puts $x ;# Prints "d"
+puts $y ;# Prints "e"
+puts $z ;# Prints ""
+
+lassign {f g h i} x y ;# Returns "h i"
+puts $x ;# Prints "f"
+puts $y ;# Prints "g"
+.CE
+The \fBlassign\fR command has other uses. It can be used to create
+the analogue of the
+.QW shift
+command in many shell languages like this:
+.CS
+set ::argv [lassign $::argv argumentToReadOff]
+.CE
+.SH "SEE ALSO"
+lindex(n), list(n), lset(n), set(n)
+
+.SH KEYWORDS
+assign, element, list, multiple, set, variable
diff --git a/doc/library.n b/doc/library.n
index 67b1037..f29af8b 100644
--- a/doc/library.n
+++ b/doc/library.n
@@ -21,15 +21,12 @@ auto_execok, auto_import, auto_load, auto_mkindex, auto_mkindex_old, auto_qualif
\fBauto_reset\fR
\fBtcl_findLibrary \fIbasename version patch initScript enVarName varName\fR
\fBparray \fIarrayName\fR
-.VS
\fBtcl_endOfWord \fIstr start\fR
\fBtcl_startOfNextWord \fIstr start\fR
\fBtcl_startOfPreviousWord \fIstr start\fR
\fBtcl_wordBreakAfter \fIstr start\fR
\fBtcl_wordBreakBefore \fIstr start\fR
-.VE
.BE
-
.SH INTRODUCTION
.PP
Tcl includes a library of Tcl procedures for commonly-needed functions.
@@ -55,7 +52,6 @@ If the library procedure \fBTcl_Init\fR is invoked from an application's
The code in \fBinit.tcl\fR will define the \fBunknown\fR procedure
and arrange for the other procedures to be loaded on-demand using
the auto-load mechanism defined below.
-
.SH "COMMAND PROCEDURES"
.PP
The following procedures are provided in the Tcl library:
@@ -68,7 +64,7 @@ named by \fIcmd\fR. If not, it returns an empty string. This command
examines the directories in the current search path (given by the PATH
environment variable) in its search for an executable file named
\fIcmd\fR. On Windows platforms, the search is expanded with the same
-directories and file extensions as used by \fBexec\fR. \fBAuto_exec\fR
+directories and file extensions as used by \fBexec\fR. \fBAuto_execok\fR
remembers information about previous searches in an array named
\fBauto_execs\fR; this avoids the path search in future calls for the
same \fIcmd\fR. The command \fBauto_reset\fR may be used to force
@@ -98,7 +94,7 @@ with the \fBauto_mkindex\fR command. If \fIcmd\fR is found in an
index file, then the appropriate script is evaluated to create the
command. The \fBauto_load\fR command returns 1 if \fIcmd\fR was
successfully created. The command returns 0 if there was no index
-entry for \fIcmd\fR or if the script didn't actually define \fIcmd\fR
+entry for \fIcmd\fR or if the script did not actually define \fIcmd\fR
(e.g. because index information is out of date). If an error occurs
while processing the script, then that error is returned.
\fBAuto_load\fR only reads the index information once and saves it in
@@ -136,9 +132,11 @@ unsophisticated way: if any line contains the word \fBproc\fR
as its first characters then it is assumed to be a procedure
definition and the next word of the line is taken as the
procedure's name.
-Procedure definitions that don't appear in this way (e.g. they
+Procedure definitions that do not appear in this way (e.g. they
have spaces before the \fBproc\fR) will not be indexed. If your
-script contains "dangerous" code, such as global initialization
+script contains
+.QW dangerous
+code, such as global initialization
code or procedure names with special characters like \fB$\fR,
\fB*\fR, \fB[\fR or \fB]\fR, you are safer using auto_mkindex_old.
.RE
@@ -148,7 +146,7 @@ Destroys all the information cached by \fBauto_execok\fR and
\fBauto_load\fR. This information will be re-read from disk the next
time it is needed. \fBAuto_reset\fR also deletes any procedures
listed in the auto-load index, so that fresh copies of them will be
-loaded the next time that they're used.
+loaded the next time that they are used.
.TP
\fBauto_qualify \fIcommand namespace\fR
Computes a list of fully qualified names for \fIcommand\fR. This list
@@ -174,18 +172,20 @@ This is a standard search procedure for use by extensions during
their initialization. They call this procedure to look for their
script library in several standard directories.
The last component of the name of the library directory is
-normally \fIbasenameversion\fP
-(e.g., tk8.0), but it might be "library" when in the build hierarchies.
+normally \fIbasenameversion\fR
+(e.g., tk8.0), but it might be
+.QW library
+when in the build hierarchies.
The \fIinitScript\fR file will be sourced into the interpreter
once it is found. The directory in which this file is found is
-stored into the global variable \fIvarName\fP.
+stored into the global variable \fIvarName\fR.
If this variable is already defined (e.g., by C code during
application initialization) then no searching is done.
Otherwise the search looks in these directories:
-the directory named by the environment variable \fIenVarName\fP;
+the directory named by the environment variable \fIenVarName\fR;
relative to the Tcl library directory;
relative to the executable file in the standard installation
-bin or bin/\fIarch\fP directory;
+bin or bin/\fIarch\fR directory;
relative to the executable file in the current build tree;
relative to the executable file in a parallel build tree.
.TP
@@ -196,7 +196,6 @@ in the array \fIarrayName\fR.
It may be either local or global.
.TP
\fBtcl_endOfWord \fIstr start\fR
-.VS
Returns the index of the first end-of-word location that occurs after
a starting index \fIstart\fR in the string \fIstr\fR. An end-of-word
location is defined to be the first non-word character following the
@@ -232,8 +231,6 @@ Returns the index of the first word boundary before the starting index
boundaries before the starting point in the given string. The index
returned refers to the second character of the pair that comprises a
boundary.
-.VE
-
.SH "VARIABLES"
.PP
The following global variables are defined or used by the procedures in
@@ -268,17 +265,18 @@ the directories listed in the $tcl_pkgPath variable.
If set, then it specifies the location of the directory containing
library scripts (the value of this variable will be
assigned to the \fBtcl_library\fR variable and therefore returned by
-the command \fBinfo library\fR). If this variable isn't set then
+the command \fBinfo library\fR). If this variable is not set then
a default value is used.
.TP
\fBenv(TCLLIBPATH)\fR
If set, then it must contain a valid Tcl list giving directories to
search during auto-load operations. Directories must be specified in
-Tcl format, using "/" as the path separator, regardless of platform.
+Tcl format, using
+.QW /
+as the path separator, regardless of platform.
This variable is only used when initializing the \fBauto_path\fR variable.
.TP
\fBtcl_nonwordchars\fR
-.VS
This variable contains a regular expression that is used by routines
like \fBtcl_endOfWord\fR to identify whether a character is part of a
word or not. If the pattern matches a character, the character is
@@ -294,17 +292,7 @@ word or not. If the pattern matches a character, the character is
considered to be a word character. On Windows platforms, words are
comprised of any character that is not a space, tab, or newline. Under
Unix, words are comprised of numbers, letters or underscores.
-.VE
-.TP
-\fBunknown_pending\fR
-Used by \fBunknown\fR to record the command(s) for which it is
-searching.
-It is used to detect errors where \fBunknown\fR recurses on itself
-infinitely.
-The variable is unset before \fBunknown\fR returns.
-
.SH "SEE ALSO"
info(n), re_syntax(n)
-
.SH KEYWORDS
auto-exec, auto-load, library, unknown, word, whitespace
diff --git a/doc/lindex.n b/doc/lindex.n
index a12fdcf..f0417ac 100644
--- a/doc/lindex.n
+++ b/doc/lindex.n
@@ -1,7 +1,7 @@
'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
-'\" Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
+'\" Copyright (c) 2001 by Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -17,9 +17,8 @@ lindex \- Retrieve an element from a list
.BE
.SH DESCRIPTION
.PP
-.VS 8.4
-The \fBlindex\fP command accepts a parameter, \fIlist\fP, which
-it treats as a Tcl list. It also accepts zero or more \fIindices\fP into
+The \fBlindex\fR command accepts a parameter, \fIlist\fR, which
+it treats as a Tcl list. It also accepts zero or more \fIindices\fR into
the list. The indices may be presented either consecutively on the
command line, or grouped in a
Tcl list and presented as a single argument.
@@ -37,7 +36,6 @@ In this case, the return value of \fBlindex\fR is simply the value of the
.PP
When presented with a single index, the \fBlindex\fR command
treats \fIlist\fR as a Tcl list and returns the
-.VE
\fIindex\fR'th element from it (0 refers to the first element of the list).
In extracting the element, \fBlindex\fR observes the same rules
concerning braces and quotes and backslashes as the Tcl command
@@ -46,11 +44,12 @@ substitution and command substitution do not occur.
If \fIindex\fR is negative or greater than or equal to the number
of elements in \fIvalue\fR, then an empty
string is returned.
-If \fIindex\fR has the value \fBend\fR, it refers to the last element
-in the list, and \fBend\-\fIinteger\fR refers to the last element in
-the list minus the specified integer offset.
+.VS 8.5
+The interpretation of each simple \fIindex\fR value is the same as
+for the command \fBstring index\fR, supporting simple index
+arithmetic and indices relative to the end of the list.
+.VE 8.5
.PP
-.VS 8.4
If additional \fIindex\fR arguments are supplied, then each argument is
used in turn to select an element from the previous indexing operation,
allowing the script to select elements from sublists. The command,
@@ -67,25 +66,33 @@ lindex [lindex [lindex $a 1] 2] 3
.CE
.SH EXAMPLES
.CS
-\fBlindex\fR {a b c} \fI=> a b c\fR
-\fBlindex\fR {a b c} {} \fI=> a b c\fR
-\fBlindex\fR {a b c} 0 \fI=> a\fR
-\fBlindex\fR {a b c} 2 \fI=> c\fR
-\fBlindex\fR {a b c} end \fI=> c\fR
-\fBlindex\fR {a b c} end-1 \fI=> b\fR
-\fBlindex\fR {{a b c} {d e f} {g h i}} 2 1 \fI=> h\fR
-\fBlindex\fR {{a b c} {d e f} {g h i}} {2 1} \fI=> h\fR
-\fBlindex\fR {{{a b} {c d}} {{e f} {g h}}} 1 1 0 \fI=> g\fR
-\fBlindex\fR {{{a b} {c d}} {{e f} {g h}}} {1 1 0} \fI=> g\fR
+\fBlindex\fR {a b c}
+ \fI\(-> a b c\fR
+\fBlindex\fR {a b c} {}
+ \fI\(-> a b c\fR
+\fBlindex\fR {a b c} 0
+ \fI\(-> a\fR
+\fBlindex\fR {a b c} 2
+ \fI\(-> c\fR
+\fBlindex\fR {a b c} end
+ \fI\(-> c\fR
+\fBlindex\fR {a b c} end-1
+ \fI\(-> b\fR
+\fBlindex\fR {{a b c} {d e f} {g h i}} 2 1
+ \fI\(-> h\fR
+\fBlindex\fR {{a b c} {d e f} {g h i}} {2 1}
+ \fI\(-> h\fR
+\fBlindex\fR {{{a b} {c d}} {{e f} {g h}}} 1 1 0
+ \fI\(-> g\fR
+\fBlindex\fR {{{a b} {c d}} {{e f} {g h}}} {1 1 0}
+ \fI\(-> g\fR
.CE
-.VE
.SH "SEE ALSO"
list(n), lappend(n), linsert(n), llength(n), lsearch(n),
-.VS 8.4
-lset(n),
+lset(n), lsort(n), lrange(n), lreplace(n),
+.VS 8.5
+string(n)
.VE
-lsort(n),
-lrange(n), lreplace(n)
.SH KEYWORDS
element, index, list
diff --git a/doc/linsert.n b/doc/linsert.n
index 7b85adb..9f37fcd 100644
--- a/doc/linsert.n
+++ b/doc/linsert.n
@@ -1,7 +1,7 @@
'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
-'\" Copyright (c) 2001 Kevin B. Kenny. All rights reserved.
+'\" Copyright (c) 2001 Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -22,11 +22,12 @@ This command produces a new list from \fIlist\fR by inserting all of the
\fIelement\fR arguments just before the \fIindex\fR'th element of
\fIlist\fR. Each \fIelement\fR argument will become a separate element of
the new list. If \fIindex\fR is less than or equal to zero, then the new
-elements are inserted at the beginning of the list. If \fIindex\fR has the
-value \fBend\fR, or if it is greater than or equal to the number of
-elements in the list, then the new elements are appended to the list.
-\fBend\-\fIinteger\fR refers to the last element in the list minus the
-specified integer offset.
+elements are inserted at the beginning of the list.
+.VS 8.5
+The interpretation of the \fIindex\fR value is the same as
+for the command \fBstring index\fR, supporting simple index
+arithmetic and indices relative to the end of the list.
+.VE
.SH EXAMPLE
Putting some values into a list, first indexing from the start and
then indexing from the end, and then chaining them together:
@@ -39,9 +40,10 @@ set newerList [\fBlinsert\fR [\fBlinsert\fR $oldList end-1 quick] 1 lazy]
.CE
.SH "SEE ALSO"
-.VS 8.4
list(n), lappend(n), lindex(n), llength(n), lsearch(n),
-lset(n), lsort(n), lrange(n), lreplace(n)
+lset(n), lsort(n), lrange(n), lreplace(n),
+.VS 8.5
+string(n)
.VE
.SH KEYWORDS
diff --git a/doc/list.n b/doc/list.n
index 21f9edb..2bcdafb 100644
--- a/doc/list.n
+++ b/doc/list.n
@@ -1,7 +1,7 @@
'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
-'\" Copyright (c) 2001 Kevin B. Kenny. All rights reserved.
+'\" Copyright (c) 2001 Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -43,11 +43,10 @@ while \fBconcat\fR with the same arguments will return
.SH "SEE ALSO"
lappend(n), lindex(n), linsert(n), llength(n), lrange(n),
-lreplace(n), lsearch(n),
-.VS 8.4
-lset(n),
-.VE 8.4
-lsort(n)
+.VS 8.5
+lrepeat(n),
+.VE 8.5
+lreplace(n), lsearch(n), lset(n), lsort(n)
.SH KEYWORDS
element, list
diff --git a/doc/llength.n b/doc/llength.n
index 977d9ef..627800f 100644
--- a/doc/llength.n
+++ b/doc/llength.n
@@ -1,7 +1,7 @@
'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
-'\" Copyright (c) 2001 Kevin B. Kenny. All rights reserved.
+'\" Copyright (c) 2001 Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -48,10 +48,8 @@ An empty list is not necessarily an empty string:
.CE
.SH "SEE ALSO"
-.VS 8.4
list(n), lappend(n), lindex(n), linsert(n), lsearch(n),
lset(n), lsort(n), lrange(n), lreplace(n)
-.VE
.SH KEYWORDS
element, list, length
diff --git a/doc/load.n b/doc/load.n
index 02fec35..e5501f6 100644
--- a/doc/load.n
+++ b/doc/load.n
@@ -9,7 +9,7 @@
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
-load \- Load machine code and initialize new commands.
+load \- Load machine code and initialize new commands
.SH SYNOPSIS
\fBload \fIfileName\fR
.br
@@ -71,7 +71,12 @@ in an application. If a given \fIfileName\fR is loaded into multiple
interpreters, then the first \fBload\fR will load the code and
call the initialization procedure; subsequent \fBload\fRs will
call the initialization procedure without loading the code again.
-It is not possible to unload or reload a package.
+.VS 8.5
+For Tcl versions lower than 8.5, it is not possible to unload or reload a
+package. From version 8.5 however, the \fBunload\fR command allows the unloading
+of libraries loaded with \fBload\fR, for libraries that are aware of the
+Tcl's unloading mechanism.
+.VE 8.5
.PP
The \fBload\fR command also supports packages that are statically
linked with the application, if those packages have been registered
@@ -85,13 +90,10 @@ This may be done differently on different platforms.
The default guess, which is used on most UNIX platforms, is to
take the last element of \fIfileName\fR, strip off the first
three characters if they are \fBlib\fR, and use any following
-.VS
alphabetic and underline characters as the module name.
-.VE
For example, the command \fBload libxyz4.2.so\fR uses the module
name \fBxyz\fR and the command \fBload bin/last.so {}\fR uses the
module name \fBlast\fR.
-.VS "" br
.PP
If \fIfileName\fR is an empty string, then \fIpackageName\fR must
be specified.
@@ -102,17 +104,20 @@ Otherwise, the \fBload\fR command searches for a dynamically loaded
package by that name, and uses it if it is found. If several
different files have been \fBload\fRed with different versions of
the package, Tcl picks the file that was loaded first.
-.VE
.SH "PORTABILITY ISSUES"
.TP
\fBWindows\fR\0\0\0\0\0
.
-When a load fails with "library not found" error, it is also possible
+When a load fails with
+.QW "library not found"
+error, it is also possible
that a dependent library was not found. To see the dependent libraries,
-type ``dumpbin -imports <dllname>'' in a DOS console to see what the
-library must import.
-When loading a DLL in the current directory, Windows will ignore ``./'' as
-a path specifier and use a search heuristic to find the DLL instead.
+type
+.QW "dumpbin -imports <dllname>"
+in a DOS console to see what the library must import.
+When loading a DLL in the current directory, Windows will ignore
+.QW ./
+as a path specifier and use a search heuristic to find the DLL instead.
To avoid this, load the DLL with:
.CS
\fBload\fR [file join [pwd] mylib.DLL]
@@ -131,7 +136,7 @@ The following is a minimal extension:
#include <stdio.h>
static int fooCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
- printf("called with %d arguments\\n", objc);
+ printf("called with %d arguments\en", objc);
return TCL_OK;
}
int Foo_Init(Tcl_Interp *interp) {
diff --git a/doc/lrange.n b/doc/lrange.n
index 5b0d187..34f0150 100644
--- a/doc/lrange.n
+++ b/doc/lrange.n
@@ -1,7 +1,7 @@
'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
-'\" Copyright (c) 2001 Kevin B. Kenny. All rights reserved.
+'\" Copyright (c) 2001 Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -21,18 +21,24 @@ lrange \- Return one or more adjacent elements from a list
\fIList\fR must be a valid Tcl list. This command will
return a new list consisting of elements
\fIfirst\fR through \fIlast\fR, inclusive.
-\fIFirst\fR or \fIlast\fR
-may be \fBend\fR (or any abbreviation of it) to refer to the last
-element of the list.
+.VS 8.5
+The index values \fIfirst\fR and \fIlast\fR are interpreted
+the same as index values for the command \fBstring index\fR,
+supporting simple index arithmetic and indices relative to the
+end of the list.
+.VE
If \fIfirst\fR is less than zero, it is treated as if it were zero.
If \fIlast\fR is greater than or equal to the number of elements
in the list, then it is treated as if it were \fBend\fR.
If \fIfirst\fR is greater than \fIlast\fR then an empty string
is returned.
-Note: ``\fBlrange \fIlist first first\fR'' does not always produce the
-same result as ``\fBlindex \fIlist first\fR'' (although it often does
-for simple fields that aren't enclosed in braces); it does, however,
-produce exactly the same results as ``\fBlist [lindex \fIlist first\fB]\fR''
+Note:
+.QW "\fBlrange \fIlist first first\fR"
+does not always produce the same result as
+.QW "\fBlindex \fIlist first\fR"
+(although it often does for simple fields that are not enclosed in
+braces); it does, however, produce exactly the same results as
+.QW "\fBlist [lindex \fIlist first\fB]\fR"
.SH EXAMPLES
Selecting the first two elements:
.CS
@@ -64,9 +70,10 @@ elements to
.CE
.SH "SEE ALSO"
-.VS 8.4
list(n), lappend(n), lindex(n), linsert(n), llength(n), lsearch(n),
-lset(n), lreplace(n), lsort(n)
+lset(n), lreplace(n), lsort(n),
+.VS 8.5
+string(n)
.VE
.SH KEYWORDS
diff --git a/doc/lrepeat.n b/doc/lrepeat.n
new file mode 100644
index 0000000..ac78690
--- /dev/null
+++ b/doc/lrepeat.n
@@ -0,0 +1,39 @@
+'\"
+'\" Copyright (c) 2003 by Simon Geard. All rights reserved.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.so man.macros
+.TH lrepeat n 8.5 Tcl "Tcl Built-In Commands"
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+lrepeat \- Build a list by repeating elements
+.SH SYNOPSIS
+\fBlrepeat \fInumber element1 \fR?\fIelement2 element3 ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+The \fBlrepeat\fR command creates a list of size \fInumber * number of
+elements\fR by repeating \fInumber\fR times the sequence of elements
+\fIelement1 element2 ...\fR. \fInumber\fR must be a positive integer,
+\fIelementn\fR can be any Tcl value. Note that \fBlrepeat 1 arg ...\fR
+is identical to \fBlist arg ...\fR, though the \fIarg\fR is required
+with \fBlrepeat\fR.
+.SH EXAMPLES
+.CS
+\fBlrepeat\fR 3 a
+ \fI\(-> a a a\fR
+\fBlrepeat\fR 3 [\fBlrepeat\fR 3 0]
+ \fI\(-> {0 0 0} {0 0 0} {0 0 0}\fR
+\fBlrepeat\fR 3 a b c
+ \fI\(-> a b c a b c a b c\fR
+\fBlrepeat\fR 3 [\fBlrepeat\fR 2 a] b c
+ \fI\(-> {a a} b c {a a} b c {a a} b c\fR
+.CE
+.SH "SEE ALSO"
+list(n), lappend(n), linsert(n), llength(n), lset(n)
+
+.SH KEYWORDS
+element, index, list
diff --git a/doc/lreplace.n b/doc/lreplace.n
index 600a986..2cd79d8 100644
--- a/doc/lreplace.n
+++ b/doc/lreplace.n
@@ -1,7 +1,7 @@
'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
-'\" Copyright (c) 2001 Kevin B. Kenny. All rights reserved.
+'\" Copyright (c) 2001 Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -15,26 +15,31 @@ lreplace \- Replace elements in a list with new elements
.SH SYNOPSIS
\fBlreplace \fIlist first last \fR?\fIelement element ...\fR?
.BE
-
.SH DESCRIPTION
.PP
\fBlreplace\fR returns a new list formed by replacing one or more elements of
\fIlist\fR with the \fIelement\fR arguments.
-\fIfirst\fR and \fIlast\fR specify the first and last index of the
-range of elements to replace. 0 refers to the first element of the
-list, and \fBend\fR (or any abbreviation of it) may be used to refer
-to the last element of the list. If \fIlist\fR is empty, then
-\fIfirst\fR and \fIlast\fR are ignored.
-
-If \fIfirst\fR is less than zero, it is considered to refer to the
+.VS 8.5
+\fIfirst\fR and \fIlast\fR are index values specifying the first and
+last elements of the range to replace.
+The index values \fIfirst\fR and \fIlast\fR are interpreted
+the same as index values for the command \fBstring index\fR,
+supporting simple index arithmetic and indices relative to the
+end of the list.
+0 refers to the first element of the
+list, and \fBend\fR refers to the last element of the list.
+If \fIlist\fR is empty, then \fIfirst\fR and \fIlast\fR are ignored.
+.VE
+.PP
+If \fIfirst\fR is less than zero, it is considered to refer to before the
first element of the list. For non-empty lists, the element indicated
-by \fIfirst\fR must exist.
-
-If \fIlast\fR is less than zero but greater than \fIfirst\fR, then any
-specified elements will be prepended to the list. If \fIlast\fR is
-less than \fIfirst\fR then no elements are deleted; the new elements
-are simply inserted before \fIfirst\fR.
-
+by \fIfirst\fR must exist or \fIfirst\fR must indicate before the
+start of the list.
+.PP
+If \fIlast\fR is less than \fIfirst\fR, then any specified elements
+will be inserted into the list at the point specified by \fIfirst\fR
+with no elements being deleted.
+.PP
The \fIelement\fR arguments specify zero or more new arguments to
be added to the list in place of those that were deleted.
Each \fIelement\fR argument will become a separate element of
@@ -61,12 +66,20 @@ a b c d e
% set var [\fBlreplace\fR $var end end]
a b c d
.CE
-
+.PP
+A procedure to delete a given element from a list:
+.CS
+proc lremove {listVariable value} {
+ upvar 1 $listVariable var
+ set idx [lsearch -exact $var $value]
+ set var [\fBlreplace\fR $var $idx $idx]
+}
+.CE
.SH "SEE ALSO"
-.VS 8.4
-list(n), lappend(n), lindex(n), linsert(n), llength(n), lsearch(n),
-lset(n), lrange(n), lsort(n)
+list(n), lappend(n), lindex(n), linsert(n), llength(n), lsearch(n),
+lset(n), lrange(n), lsort(n),
+.VS 8.5
+string(n)
.VE
-
.SH KEYWORDS
element, list, replace
diff --git a/doc/lreverse.n b/doc/lreverse.n
new file mode 100644
index 0000000..da5e489
--- /dev/null
+++ b/doc/lreverse.n
@@ -0,0 +1,31 @@
+'\" -*- nroff -*-
+'\" Copyright (c) 2006 by Donal K. Fellows. All rights reserved.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.so man.macros
+.TH lreverse n 8.5 Tcl "Tcl Built-In Commands"
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+lreverse \- Reverse the order of a list
+.SH SYNOPSIS
+\fBlreverse \fIlist\fR
+.BE
+.SH DESCRIPTION
+.PP
+The \fBlreverse\fR command returns a list that has the same elements as its
+input list, \fIlist\fR, except with the elements in the reverse order.
+.SH EXAMPLES
+.CS
+\fBlreverse\fR {a a b c}
+ \fI\(-> c b a a\fR
+\fBlreverse\fR {a b {c d} e f}
+ \fI\(-> f e {c d} b a\fR
+.CE
+.SH "SEE ALSO"
+list(n), lsearch(n), lsort(n)
+
+.SH KEYWORDS
+element, list, reverse
diff --git a/doc/lsearch.n b/doc/lsearch.n
index 37362fa..b046ba2 100644
--- a/doc/lsearch.n
+++ b/doc/lsearch.n
@@ -1,13 +1,14 @@
'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
-'\" Copyright (c) 2001 Kevin B. Kenny. All rights reserved.
+'\" Copyright (c) 2001 Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
+'\" Copyright (c) 2003-2004 Donal K. Fellows.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
-.TH lsearch n 8.4 Tcl "Tcl Built-In Commands"
+.TH lsearch n 8.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
@@ -21,121 +22,169 @@ lsearch \- See if a list contains a particular element
This command searches the elements of \fIlist\fR to see if one
of them matches \fIpattern\fR. If so, the command returns the index
of the first matching element
-.VS 8.4
(unless the options \fB\-all\fR or \fB\-inline\fR are specified.)
-.VE 8.4
If not, the command returns \fB\-1\fR. The \fIoption\fR arguments
indicates how the elements of the list are to be matched against
-\fIpattern\fR and it must have one of the following values:
-.TP
-\fB\-all\fR
-.VS 8.4
-Changes the result to be the list of all matching indices (or all
-matching values if \fB\-inline\fR is specified as well.)
-.VE 8.4
-.TP
-\fB\-ascii\fR
-The list elements are to be examined as Unicode strings (the name is
-for backward-compatability reasons.) This option is only meaningful
-when used with \fB\-exact\fR or \fB\-sorted\fR.
-.TP
-\fB\-decreasing\fR
-The list elements are sorted in decreasing order. This option is only
-meaningful when used with \fB\-sorted\fR.
-.TP
-\fB\-dictionary\fR
-The list elements are to be compared using dictionary-style
-comparisons (see \fBlsort\fR for a fuller description). This option
-is only meaningful when used with \fB\-exact\fR or \fB\-sorted\fR, and
-it is only distinguishable from the \fB\-ascii\fR option when
-the \fB\-sorted\fR option is given, because values are only
-dictionary-equal when exactly equal.
+\fIpattern\fR and must have one of the values below:
+.SS "MATCHING STYLE OPTIONS"
+If all matching style options are omitted, the default matching style
+is \fB\-glob\fR. If more than one matching style is specified, the
+last matching style given takes precedence.
.TP
\fB\-exact\fR
-The list element must contain exactly the same string as \fIpattern\fR.
+\fIPattern\fR is a literal string that is compared for exact equality
+against each list element.
.TP
\fB\-glob\fR
\fIPattern\fR is a glob-style pattern which is matched against each list
element using the same rules as the \fBstring match\fR command.
.TP
-\fB\-increasing\fR
-The list elements are sorted in increasing order. This option is only
-meaningful when used with \fB\-sorted\fR.
+\fB\-regexp\fR
+\fIPattern\fR is treated as a regular expression and matched against
+each list element using the rules described in the \fBre_syntax\fR
+reference page.
+.TP
+\fB\-sorted\fR
+The list elements are in sorted order. If this option is specified,
+\fBlsearch\fR will use a more efficient searching algorithm to search
+\fIlist\fR. If no other options are specified, \fIlist\fR is assumed
+to be sorted in increasing order, and to contain ASCII strings. This
+option is mutually exclusive with \fB\-glob\fR and \fB\-regexp\fR, and
+is treated exactly like \fB\-exact\fR when either \fB\-all\fR or
+\fB\-not\fR are specified.
+.SS "GENERAL MODIFIER OPTIONS"
+These options may be given with all matching styles.
+.TP
+\fB\-all\fR
+.
+Changes the result to be the list of all matching indices (or all matching
+values if \fB\-inline\fR is specified as well.) If indices are returned, the
+indices will be in numeric order. If values are returned, the order of the
+values will be the order of those values within the input \fIlist\fR.
.TP
\fB\-inline\fR
-.VS 8.4
The matching value is returned instead of its index (or an empty
string if no value matches.) If \fB\-all\fR is also specified, then
the result of the command is the list of all values that matched.
-.VE 8.4
-.TP
-\fB\-integer\fR
-The list elements are to be compared as integers. This option is only
-meaningful when used with \fB\-exact\fR or \fB\-sorted\fR.
.TP
\fB\-not\fR
-.VS 8.4
This negates the sense of the match, returning the index of the first
non-matching value in the list.
-.VE 8.4
+.TP
+\fB\-start\fR\0\fIindex\fR
+The list is searched starting at position \fIindex\fR.
+.VS 8.5
+The interpretation of the \fIindex\fR value is the same as
+for the command \fBstring index\fR, supporting simple index
+arithmetic and indices relative to the end of the list.
+.VE 8.5
+.SS "CONTENTS DESCRIPTION OPTIONS"
+These options describe how to interpret the items in the list being
+searched. They are only meaningful when used with the \fB\-exact\fR
+and \fB\-sorted\fR options. If more than one is specified, the last
+one takes precedence. The default is \fB\-ascii\fR.
+.TP
+\fB\-ascii\fR
+The list elements are to be examined as Unicode strings (the name is
+for backward-compatibility reasons.)
+.TP
+\fB\-dictionary\fR
+The list elements are to be compared using dictionary-style
+comparisons (see \fBlsort\fR for a fuller description). Note that this
+only makes a meaningful difference from the \fB\-ascii\fR option when
+the \fB\-sorted\fR option is given, because values are only
+dictionary-equal when exactly equal.
+.TP
+\fB\-integer\fR
+The list elements are to be compared as integers.
+.VS 8.5
+.TP
+\fB\-nocase\fR
+Causes comparisons to be handled in a case-insensitive manner. Has no
+effect if combined with the \fB\-dictionary\fR, \fB\-integer\fR, or
+\fB\-real\fR options.
+.VE 8.5
.TP
\fB\-real\fR
-The list elements are to be compared as floating-point values. This
-option is only meaningful when used with \fB\-exact\fR or \fB\-sorted\fR.
+The list elements are to be compared as floating-point values.
+.SS "SORTED LIST OPTIONS"
+These options (only meaningful with the \fB\-sorted\fR option) specify
+how the list is sorted. If more than one is given, the last one takes
+precedence. The default option is \fB\-increasing\fR.
.TP
-\fB\-regexp\fR
-\fIPattern\fR is treated as a regular expression and matched against
-each list element using the rules described in the \fBre_syntax\fR
-reference page.
+\fB\-decreasing\fR
+The list elements are sorted in decreasing order. This option is only
+meaningful when used with \fB\-sorted\fR.
.TP
-\fB\-sorted\fR
-The list elements are in sorted order. If this option is specified,
-\fBlsearch\fR will use a more efficient searching algorithm to search
-\fIlist\fR. If no other options are specified, \fIlist\fR is assumed
-to be sorted in increasing order, and to contain ASCII strings. This
-option is mutually exclusive with \fB\-glob\fR and \fB\-regexp\fR, and
-is treated exactly like \fB-exact\fR when either \fB\-all\fR, or
-\fB\-not\fR is specified.
-.TP
-\fB\-start\fR \fIindex\fR
-.VS 8.4
-The list is searched starting at position \fIindex\fR. If \fIindex\fR
-has the value \fBend\fR, it refers to the last element in the list,
-and \fBend\-\fIinteger\fR refers to the last element in the list minus
-the specified integer offset.
-.VE 8.4
-.PP
-If \fIoption\fR is omitted then it defaults to \fB\-glob\fR. If more
-than one of \fB\-exact\fR, \fB\-glob\fR, \fB\-regexp\fR, and
-\fB\-sorted\fR is specified, whichever option is specified last takes
-precedence. If more than one of \fB\-ascii\fR, \fB\-dictionary\fR,
-\fB\-integer\fR and \fB\-real\fR is specified, the option specified
-last takes precedence. If more than one of \fB\-increasing\fR and
-\fB\-decreasing\fR is specified, the option specified last takes
-precedence.
-
-.VS 8.4
+\fB\-increasing\fR
+The list elements are sorted in increasing order. This option is only
+meaningful when used with \fB\-sorted\fR.
+.SS "NESTED LIST OPTIONS"
+.VS 8.5
+These options are used to search lists of lists. They may be used
+with any other options.
+.TP
+\fB\-index\fR\0\fIindexList\fR
+This option is designed for use when searching within nested lists.
+The \fIindexList\fR argument gives a path of indices (much as might be
+used with the \fBlindex\fR or \fBlset\fR commands) within each element
+to allow the location of the term being matched against.
+.TP
+\fB\-subindices\fR
+If this option is given, the index result from this command (or every
+index result when \fB\-all\fR is also specified) will be a complete
+path (suitable for use with \fBlindex\fR or \fBlset\fR) within the
+overall list to the term found. This option has no effect unless the
+\fI\-index\fR is also specified, and is just a convenience short-cut.
+.VE 8.5
.SH EXAMPLES
+Basic searching:
.CS
-\fBlsearch\fR {a b c d e} c \fI=> 2\fR
-\fBlsearch\fR -all {a b c a b c} c \fI=> 2 5\fR
-\fBlsearch\fR -inline {a20 b35 c47} b* \fI=> b35\fR
-\fBlsearch\fR -inline -not {a20 b35 c47} b* \fI=> a20\fR
-\fBlsearch\fR -all -inline -not {a20 b35 c47} b* \fI=> a20 c47\fR
-\fBlsearch\fR -all -not {a20 b35 c47} b* \fI=> 0 2\fR
-\fBlsearch\fR -start 3 {a b c a b c} c \fI=> 5\fR
+\fBlsearch\fR {a b c d e} c
+ \fI\(-> 2\fR
+\fBlsearch\fR -all {a b c a b c} c
+ \fI\(-> 2 5\fR
+.CE
+.PP
+Using \fBlsearch\fR to filter lists:
+.CS
+\fBlsearch\fR -inline {a20 b35 c47} b*
+ \fI\(-> b35\fR
+\fBlsearch\fR -inline -not {a20 b35 c47} b*
+ \fI\(-> a20\fR
+\fBlsearch\fR -all -inline -not {a20 b35 c47} b*
+ \fI\(-> a20 c47\fR
+\fBlsearch\fR -all -not {a20 b35 c47} b*
+ \fI\(-> 0 2\fR
+.CE
+.PP
+This can even do a
+.QW set-like
+removal operation:
+.CS
+\fBlsearch\fR -all -inline -not -exact {a b c a d e a f g a} a
+ \fI\(-> b c d e f g\fR
+.CE
+.PP
+Searching may start part-way through the list:
+.CS
+\fBlsearch\fR -start 3 {a b c a b c} c
+ \fI\(-> 5\fR
+.CE
+.PP
+It is also possible to search inside elements:
+.CS
+\fBlsearch\fR -index 1 -all -inline {{a abc} {b bcd} {c cde}} *bc*
+ \fI\(-> {a abc} {b bcd}\fR
.CE
-.VE 8.4
-
.SH "SEE ALSO"
-.VS 8.4
foreach(n), list(n), lappend(n), lindex(n), linsert(n), llength(n),
-lset(n), lsort(n), lrange(n), lreplace(n)
+lset(n), lsort(n), lrange(n), lreplace(n),
+.VS 8.5
+string(n)
.VE
-
.SH KEYWORDS
list, match, pattern, regular expression, search, string
-
'\" Local Variables:
'\" mode: nroff
'\" End:
diff --git a/doc/lset.n b/doc/lset.n
index 81ee225..5efcbae 100755..100644
--- a/doc/lset.n
+++ b/doc/lset.n
@@ -1,5 +1,5 @@
'\"
-'\" Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
+'\" Copyright (c) 2001 by Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -50,9 +50,11 @@ command.
If \fIindex\fR is negative or greater than or equal to the number
of elements in \fI$varName\fR, then an error occurs.
.PP
-If \fIindex\fR has the value \fBend\fR, it refers to the last element
-in the list, and \fBend\-\fIinteger\fR refers to the last element in
-the list minus the specified integer offset.
+.VS 8.5
+The interpretation of each simple \fIindex\fR value is the same as
+for the command \fBstring index\fR, supporting simple index
+arithmetic and indices relative to the end of the list.
+.VE 8.5
.PP
If additional \fIindex\fR arguments are supplied, then each argument is
used in turn to address an element within a sublist designated
@@ -76,36 +78,51 @@ of a list. If an index is outside the permitted range, an error is reported.
In each of these examples, the initial value of \fIx\fR is:
.CS
set x [list [list a b c] [list d e f] [list g h i]]
- => {a b c} {d e f} {g h i}
+ \fI\(-> {a b c} {d e f} {g h i}\fR
.CE
The indicated return value also becomes the new value of \fIx\fR
(except in the last case, which is an error which leaves the value of
\fIx\fR unchanged.)
.CS
-lset x {j k l} => j k l
-lset x {} {j k l} => j k l
-lset x 0 j => j {d e f} {g h i}
-lset x 2 j => {a b c} {d e f} j
-lset x end j => {a b c} {d e f} j
-lset x end-1 j => {a b c} j {g h i}
-lset x 2 1 j => {a b c} {d e f} {g j i}
-lset x {2 1} j => {a b c} {d e f} {g j i}
-lset x {2 3} j => \fIlist index out of range\fR
+\fBlset\fR x {j k l}
+ \fI\(-> j k l\fR
+\fBlset\fR x {} {j k l}
+ \fI\(-> j k l\fR
+\fBlset\fR x 0 j
+ \fI\(-> j {d e f} {g h i}\fR
+\fBlset\fR x 2 j
+ \fI\(-> {a b c} {d e f} j\fR
+\fBlset\fR x end j
+ \fI\(-> {a b c} {d e f} j\fR
+\fBlset\fR x end-1 j
+ \fI\(-> {a b c} j {g h i}\fR
+\fBlset\fR x 2 1 j
+ \fI\(-> {a b c} {d e f} {g j i}\fR
+\fBlset\fR x {2 1} j
+ \fI\(-> {a b c} {d e f} {g j i}\fR
+\fBlset\fR x {2 3} j
+ \fI\(-> list index out of range\fR
.CE
In the following examples, the initial value of \fIx\fR is:
.CS
set x [list [list [list a b] [list c d]] \e
[list [list e f] [list g h]]]
- => {{a b} {c d}} {{e f} {g h}}
+ \fI\(-> {{a b} {c d}} {{e f} {g h}}\fR
.CE
The indicated return value also becomes the new value of \fIx\fR.
.CS
-lset x 1 1 0 j => {{a b} {c d}} {{e f} {j h}}
-lset x {1 1 0} j => {{a b} {c d}} {{e f} {j h}}
+\fBlset\fR x 1 1 0 j
+ \fI\(-> {{a b} {c d}} {{e f} {j h}}\fR
+\fBlset\fR x {1 1 0} j
+ \fI\(-> {{a b} {c d}} {{e f} {j h}}\fR
.CE
.SH "SEE ALSO"
list(n), lappend(n), lindex(n), linsert(n), llength(n), lsearch(n),
-lsort(n), lrange(n), lreplace(n)
+lsort(n), lrange(n), lreplace(n),
+.VS 8.5
+string(n)
+.VE
+
.SH KEYWORDS
element, index, list, replace, set
diff --git a/doc/lsort.n b/doc/lsort.n
index fa8cdd7..1726e92 100644
--- a/doc/lsort.n
+++ b/doc/lsort.n
@@ -2,13 +2,13 @@
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 1999 Scriptics Corporation
-'\" Copyright (c) 2001 Kevin B. Kenny. All rights reserved.
+'\" Copyright (c) 2001 Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
-.TH lsort n 8.3 Tcl "Tcl Built-In Commands"
+.TH lsort n 8.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
@@ -57,47 +57,72 @@ be considered less than, equal to, or greater than the second,
respectively.
.TP 20
\fB\-increasing\fR
-Sort the list in increasing order (``smallest'' items first).
+Sort the list in increasing order
+.PQ smallest "items first" .
This is the default.
.TP 20
\fB\-decreasing\fR
-Sort the list in decreasing order (``largest'' items first).
+Sort the list in decreasing order
+.PQ largest "items first" .
.TP 20
-\fB\-index\0\fIindex\fR
+\fB\-indices\fR
+.VS "8.5 (TIP#217)"
+Return a list of indices into \fIlist\fR in sorted order instead of
+the values themselves.
+.VE "8.5 (TIP#217)"
+.TP 20
+\fB\-index\0\fIindexList\fR
If this option is specified, each of the elements of \fIlist\fR must
itself be a proper Tcl sublist. Instead of sorting based on whole
-sublists, \fBlsort\fR will extract the \fIindex\fR'th element from
-each sublist and sort based on the given element. The keyword
-\fBend\fP is allowed for the \fIindex\fP to sort on the last sublist
-element,
-.VS 8.4
-and \fBend-\fIindex\fR sorts on a sublist element offset from
-the end.
-.VE
+sublists, \fBlsort\fR will extract the \fIindexList\fR'th element from
+each sublist
+.VS 8.5
+(as if the overall element and the \fIindexList\fR were passed to
+\fBlindex\fR) and sort based on the given element.
+.VE 8.5
For example,
.RS
.CS
-lsort -integer -index 1 {{First 24} {Second 18} {Third 30}}
+lsort -integer -index 1 \e
+ {{First 24} {Second 18} {Third 30}}
.CE
returns \fB{Second 18} {First 24} {Third 30}\fR, and
-.VS 8.4
'\"
'\" This example is from the test suite!
'\"
.CS
-lsort -index end-1 {{a 1 e i} {b 2 3 f g} {c 4 5 6 d h}}
+lsort -index end-1 \e
+ {{a 1 e i} {b 2 3 f g} {c 4 5 6 d h}}
.CE
-returns \fB{c 4 5 6 d h} {a 1 e i} {b 2 3 f g}\fR.
-.VE
+returns \fB{c 4 5 6 d h} {a 1 e i} {b 2 3 f g}\fR,
+.VS 8.5
+and
+.CS
+lsort -index {0 1} {
+ {{b i g} 12345}
+ {{d e m o} 34512}
+ {{c o d e} 54321}
+}
+.CE
+returns \fB{{d e m o} 34512} {{b i g} 12345} {{c o d e} 54321}\fR
+(because \fBe\fR sorts before \fBi\fR which sorts before \fBo\fR.)
+.VE 8.5
This option is much more efficient than using \fB\-command\fR
to achieve the same effect.
.RE
+.VS 8.5
+.TP 20
+\fB\-nocase\fR
+Causes comparisons to be handled in a case-insensitive manner. Has no
+effect if combined with the \fB\-dictionary\fR, \fB\-integer\fR, or
+\fB\-real\fR options.
+.VE 8.5
.TP 20
\fB\-unique\fR
If this option is specified, then only the last set of duplicate
elements found in the list will be retained. Note that duplicates are
determined relative to the comparison used in the sort. Thus if
-\fI-index 0\fR is used, \fB{1 a}\fR and \fB{1 b}\fR would be
+\fI\-index 0\fR is used, \fB{1 a}\fR and \fB{1 b}\fR would be
considered duplicates and only the second element, \fB{1 b}\fR, would
be retained.
.SH "NOTES"
@@ -169,16 +194,14 @@ More complex sorting using a comparison function:
}
return [string compare [lindex $a 1] [lindex $b 1]]
}
-% \fBlsort\fR -command compare \\
+% \fBlsort\fR -command compare \e
{{3 apple} {0x2 carrot} {1 dingo} {2 banana}}
{1 dingo} {2 banana} {0x2 carrot} {3 apple}
.CE
.SH "SEE ALSO"
-.VS 8.4
list(n), lappend(n), lindex(n), linsert(n), llength(n), lsearch(n),
lset(n), lrange(n), lreplace(n)
-.VE
.SH KEYWORDS
element, list, order, sort
diff --git a/doc/man.macros b/doc/man.macros
index 5d0c6fa..ddd073d 100644
--- a/doc/man.macros
+++ b/doc/man.macros
@@ -1,69 +1,77 @@
-'\" The definitions below are for supplemental macros used in Tcl/Tk
-'\" manual entries.
-'\"
-'\" .AP type name in/out ?indent?
-'\" Start paragraph describing an argument to a library procedure.
-'\" type is type of argument (int, etc.), in/out is either "in", "out",
-'\" or "in/out" to describe whether procedure reads or modifies arg,
-'\" and indent is equivalent to second arg of .IP (shouldn't ever be
-'\" needed; use .AS below instead)
-'\"
-'\" .AS ?type? ?name?
-'\" Give maximum sizes of arguments for setting tab stops. Type and
-'\" name are examples of largest possible arguments that will be passed
-'\" to .AP later. If args are omitted, default tab stops are used.
-'\"
-'\" .BS
-'\" Start box enclosure. From here until next .BE, everything will be
-'\" enclosed in one large box.
-'\"
-'\" .BE
-'\" End of box enclosure.
-'\"
-'\" .CS
-'\" Begin code excerpt.
-'\"
-'\" .CE
-'\" End code excerpt.
-'\"
-'\" .VS ?version? ?br?
-'\" Begin vertical sidebar, for use in marking newly-changed parts
-'\" of man pages. The first argument is ignored and used for recording
-'\" the version when the .VS was added, so that the sidebars can be
-'\" found and removed when they reach a certain age. If another argument
-'\" is present, then a line break is forced before starting the sidebar.
-'\"
-'\" .VE
-'\" End of vertical sidebar.
-'\"
-'\" .DS
-'\" Begin an indented unfilled display.
-'\"
-'\" .DE
-'\" End of indented unfilled display.
-'\"
-'\" .SO
-'\" Start of list of standard options for a Tk widget. The
-'\" options follow on successive lines, in four columns separated
-'\" by tabs.
-'\"
-'\" .SE
-'\" End of list of standard options for a Tk widget.
-'\"
-'\" .OP cmdName dbName dbClass
-'\" Start of description of a specific option. cmdName gives the
-'\" option's name as specified in the class command, dbName gives
-'\" the option's name in the option database, and dbClass gives
-'\" the option's class in the option database.
-'\"
-'\" .UL arg1 arg2
-'\" Print arg1 underlined, then print arg2 normally.
-'\"
-'\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
+.\" The -*- nroff -*- definitions below are for supplemental macros used
+.\" in Tcl/Tk manual entries.
+.\"
+.\" .AP type name in/out ?indent?
+.\" Start paragraph describing an argument to a library procedure.
+.\" type is type of argument (int, etc.), in/out is either "in", "out",
+.\" or "in/out" to describe whether procedure reads or modifies arg,
+.\" and indent is equivalent to second arg of .IP (shouldn't ever be
+.\" needed; use .AS below instead)
+.\"
+.\" .AS ?type? ?name?
+.\" Give maximum sizes of arguments for setting tab stops. Type and
+.\" name are examples of largest possible arguments that will be passed
+.\" to .AP later. If args are omitted, default tab stops are used.
+.\"
+.\" .BS
+.\" Start box enclosure. From here until next .BE, everything will be
+.\" enclosed in one large box.
+.\"
+.\" .BE
+.\" End of box enclosure.
+.\"
+.\" .CS
+.\" Begin code excerpt.
+.\"
+.\" .CE
+.\" End code excerpt.
+.\"
+.\" .VS ?version? ?br?
+.\" Begin vertical sidebar, for use in marking newly-changed parts
+.\" of man pages. The first argument is ignored and used for recording
+.\" the version when the .VS was added, so that the sidebars can be
+.\" found and removed when they reach a certain age. If another argument
+.\" is present, then a line break is forced before starting the sidebar.
+.\"
+.\" .VE
+.\" End of vertical sidebar.
+.\"
+.\" .DS
+.\" Begin an indented unfilled display.
+.\"
+.\" .DE
+.\" End of indented unfilled display.
+.\"
+.\" .SO ?manpage?
+.\" Start of list of standard options for a Tk widget. The manpage
+.\" argument defines where to look up the standard options; if
+.\" omitted, defaults to "options". The options follow on successive
+.\" lines, in three columns separated by tabs.
+.\"
+.\" .SE
+.\" End of list of standard options for a Tk widget.
+.\"
+.\" .OP cmdName dbName dbClass
+.\" Start of description of a specific option. cmdName gives the
+.\" option's name as specified in the class command, dbName gives
+.\" the option's name in the option database, and dbClass gives
+.\" the option's class in the option database.
+.\"
+.\" .UL arg1 arg2
+.\" Print arg1 underlined, then print arg2 normally.
+.\"
+.\" .QW arg1 ?arg2?
+.\" Print arg1 in quotes, then arg2 normally (for trailing punctuation).
+.\"
+.\" .PQ arg1 ?arg2?
+.\" Print an open parenthesis, arg1 in quotes, then arg2 normally
+.\" (for trailing punctuation) and then a closing parenthesis.
+.\"
+.\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
.if t .wh -1.3i ^B
.nr ^l \n(.l
.ad b
-'\" # Start an argument description
+.\" # Start an argument description
.de AP
.ie !"\\$4"" .TP \\$4
.el \{\
@@ -72,7 +80,7 @@
.\}
.ta \\n()Au \\n()Bu
.ie !"\\$3"" \{\
-\&\\$1 \\fI\\$2\\fP (\\$3)
+\&\\$1 \\fI\\$2\\fP (\\$3)
.\".b
.\}
.el \{\
@@ -85,7 +93,7 @@
.\}
.\}
..
-'\" # define tabbing values for .AP
+.\" # define tabbing values for .AP
.de AS
.nr )A 10n
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
@@ -95,9 +103,9 @@
.nr )C \\n()Bu+\\w'(in/out)'u+2n
..
.AS Tcl_Interp Tcl_CreateInterp in/out
-'\" # BS - start boxed text
-'\" # ^y = starting y location
-'\" # ^b = 1
+.\" # BS - start boxed text
+.\" # ^y = starting y location
+.\" # ^b = 1
.de BS
.br
.mk ^y
@@ -107,7 +115,7 @@
.if n \l'\\n(.lu\(ul'
.if n .fi
..
-'\" # BE - end boxed text (draw box now)
+.\" # BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
@@ -127,16 +135,16 @@
.br
.nr ^b 0
..
-'\" # VS - start vertical sidebar
-'\" # ^Y = starting y location
-'\" # ^v = 1 (for troff; for nroff this doesn't matter)
+.\" # VS - start vertical sidebar
+.\" # ^Y = starting y location
+.\" # ^v = 1 (for troff; for nroff this doesn't matter)
.de VS
.if !"\\$2"" .br
.mk ^Y
.ie n 'mc \s12\(br\s0
.el .nr ^v 1u
..
-'\" # VE - end of vertical sidebar
+.\" # VE - end of vertical sidebar
.de VE
.ie n 'mc
.el \{\
@@ -151,9 +159,9 @@
.\}
.nr ^v 0
..
-'\" # Special macro to handle page bottom: finish off current
-'\" # box/sidebar if in box/sidebar mode, then invoked standard
-'\" # page bottom macro.
+.\" # Special macro to handle page bottom: finish off current
+.\" # box/sidebar if in box/sidebar mode, then invoked standard
+.\" # page bottom macro.
.de ^B
.ev 2
'ti 0
@@ -180,34 +188,36 @@
.mk ^Y
.\}
..
-'\" # DS - begin display
+.\" # DS - begin display
.de DS
.RS
.nf
.sp
..
-'\" # DE - end display
+.\" # DE - end display
.de DE
.fi
.RE
.sp
..
-'\" # SO - start of list of standard options
+.\" # SO - start of list of standard options
.de SO
+'ie '\\$1'' .ds So \\fBoptions\\fR
+'el .ds So \\fB\\$1\\fR
.SH "STANDARD OPTIONS"
.LP
.nf
.ta 5.5c 11c
.ft B
..
-'\" # SE - end of list of standard options
+.\" # SE - end of list of standard options
.de SE
.fi
.ft R
.LP
-See the \\fBoptions\\fR manual entry for details on the standard options.
+See the \\*(So manual entry for details on the standard options.
..
-'\" # OP - start of full description for a single option
+.\" # OP - start of full description for a single option
.de OP
.LP
.nf
@@ -218,17 +228,40 @@ Database Class: \\fB\\$3\\fR
.fi
.IP
..
-'\" # CS - begin code excerpt
+.\" # CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
-'\" # CE - end code excerpt
+.\" # CE - end code excerpt
.de CE
.fi
.RE
..
+.\" # UL - underline word
.de UL
\\$1\l'|0\(ul'\\$2
..
+.\" # QW - apply quotation marks to word
+.de QW
+.ie '\\*(lq'"' ``\\$1''\\$2
+.\"" fix emacs highlighting
+.el \\*(lq\\$1\\*(rq\\$2
+..
+.\" # PQ - apply parens and quotation marks to word
+.de PQ
+.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
+.\"" fix emacs highlighting
+.el (\\*(lq\\$1\\*(rq\\$2)\\$3
+..
+.\" # QR - quoted range
+.de QR
+.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
+.\"" fix emacs highlighting
+.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
+..
+.\" # MT - "empty" string
+.de MT
+.QW ""
+..
diff --git a/doc/mathfunc.n b/doc/mathfunc.n
new file mode 100644
index 0000000..4ba25e4
--- /dev/null
+++ b/doc/mathfunc.n
@@ -0,0 +1,271 @@
+'\"
+'\" Copyright (c) 1993 The Regents of the University of California.
+'\" Copyright (c) 1994-2000 Sun Microsystems, Inc.
+'\" Copyright (c) 2005 by Kevin B. Kenny <kennykb@acm.org>. All rights reserved
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.so man.macros
+.TH mathfunc n 8.5 Tcl "Tcl Mathematical Functions"
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+mathfunc \- Mathematical functions for Tcl expressions
+.SH SYNOPSIS
+package require \fBTcl 8.5\fR
+.sp
+\fB::tcl::mathfunc::abs\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::acos\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::asin\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::atan\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::atan2\fR \fIy\fR \fIx\fR
+.br
+\fB::tcl::mathfunc::bool\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::ceil\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::cos\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::cosh\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::double\fR \fIarg\fR
+.br
+.VS 8.5
+\fB::tcl::mathfunc::entier\fR \fIarg\fR
+.br
+.VE 8.5
+\fB::tcl::mathfunc::exp\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::floor\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::fmod\fR \fIx\fR \fIy\fR
+.br
+\fB::tcl::mathfunc::hypot\fR \fIx\fR \fIy\fR
+.br
+\fB::tcl::mathfunc::int\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::isqrt\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::log\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::log10\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::max\fR \fIarg\fR ?\fIarg\fR ...?
+.br
+\fB::tcl::mathfunc::min\fR \fIarg\fR ?\fIarg\fR ...?
+.br
+\fB::tcl::mathfunc::pow\fR \fIx\fR \fIy\fR
+.br
+\fB::tcl::mathfunc::rand\fR
+.br
+\fB::tcl::mathfunc::round\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::sin\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::sinh\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::sqrt\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::srand\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::tan\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::tanh\fR \fIarg\fR
+.br
+\fB::tcl::mathfunc::wide\fR \fIarg\fR
+.sp
+.BE
+.SH "DESCRIPTION"
+.PP
+The \fBexpr\fR command handles mathematical functions of the form
+\fBsin($x)\fR or \fBatan2($y,$x)\fR by converting them to calls of the
+form \fB[tcl::mathfunc::sin [expr {$x}]]\fR or
+\fB[tcl::mathfunc::atan2 [expr {$y}] [expr {$x}]]\fR.
+A number of math functions are available by default within the
+namespace \fB::tcl::mathfunc\fR; these functions are also available
+for code apart from \fBexpr\fR, by invoking the given commands
+directly.
+.PP
+Tcl supports the following mathematical functions in expressions, all
+of which work solely with floating-point numbers unless otherwise noted:
+.DS
+.ta 3c 6c 9c
+\fBabs\fR \fBacos\fR \fBasin\fR \fBatan\fR
+\fBatan2\fR \fBbool\fR \fBceil\fR \fBcos\fR
+\fBcosh\fR \fBdouble\fR \fBentier\fR \fBexp\fR
+\fBfloor\fR \fBfmod\fR \fBhypot\fR \fBint\fR
+\fBisqrt\fR \fBlog\fR \fBlog10\fR \fBmax\fR
+\fBmin\fR \fBpow\fR \fBrand\fR \fBround\fR
+\fBsin\fR \fBsinh\fR \fBsqrt\fR \fBsrand\fR
+\fBtan\fR \fBtanh\fR \fBwide\fR
+.DE
+.PP
+In addition to these predefined functions, applications may
+define additional functions by using \fBproc\fR (or any other method,
+such as \fBinterp alias\fR or \fBTcl_CreateObjCommand\fR) to define
+new commands in the \fBtcl::mathfunc\fR namespace. In addition, an
+obsolete interface named \fBTcl_CreateMathFunc\fR() is available to
+extensions that are written in C. The latter interface is not recommended
+for new implementations.
+.SS "DETAILED DEFINITIONS"
+.TP
+\fBabs \fIarg\fR
+Returns the absolute value of \fIarg\fR. \fIArg\fR may be either
+integer or floating-point, and the result is returned in the same form.
+.TP
+\fBacos \fIarg\fR
+Returns the arc cosine of \fIarg\fR, in the range [\fI0\fR,\fIpi\fR]
+radians. \fIArg\fR should be in the range [\fI\-1\fR,\fI1\fR].
+.TP
+\fBasin \fIarg\fR
+Returns the arc sine of \fIarg\fR, in the range [\fI\-pi/2\fR,\fIpi/2\fR]
+radians. \fIArg\fR should be in the range [\fI\-1\fR,\fI1\fR].
+.TP
+\fBatan \fIarg\fR
+Returns the arc tangent of \fIarg\fR, in the range [\fI\-pi/2\fR,\fIpi/2\fR]
+radians.
+.TP
+\fBatan2 \fIy x\fR
+Returns the arc tangent of \fIy\fR/\fIx\fR, in the range [\fI\-pi\fR,\fIpi\fR]
+radians. \fIx\fR and \fIy\fR cannot both be 0. If \fIx\fR is greater
+than \fI0\fR, this is equivalent to
+.QW "\fBatan \fR[\fBexpr\fR {\fIy\fB/\fIx\fR}]" .
+.TP
+\fBbool \fIarg\fR
+Accepts any numeric value, or any string acceptable to
+\fBstring is boolean\fR, and returns the corresponding
+boolean value \fB0\fR or \fB1\fR. Non-zero numbers are true.
+Other numbers are false. Non-numeric strings produce boolean value in
+agreement with \fBstring is true\fR and \fBstring is false\fR.
+.TP
+\fBceil \fIarg\fR
+Returns the smallest integral floating-point value (i.e. with a zero
+fractional part) not less than \fIarg\fR. The argument may be any
+numeric value.
+.TP
+\fBcos \fIarg\fR
+Returns the cosine of \fIarg\fR, measured in radians.
+.TP
+\fBcosh \fIarg\fR
+Returns the hyperbolic cosine of \fIarg\fR. If the result would cause
+an overflow, an error is returned.
+.TP
+\fBdouble \fIarg\fR
+The argument may be any numeric value,
+If \fIarg\fR is a floating-point value, returns \fIarg\fR, otherwise converts
+\fIarg\fR to floating-point and returns the converted value. May return
+\fBInf\fR or \fB\-Inf\fR when the argument is a numeric value that exceeds
+the floating-point range.
+.TP
+\fBentier \fIarg\fR
+.VS 8.5
+The argument may be any numeric value. The integer part of \fIarg\fR
+is determined and returned. The integer range returned by this function
+is unlimited, unlike \fBint\fR and \fBwide\fR which
+truncate their range to fit in particular storage widths.
+.VE 8.5
+.TP
+\fBexp \fIarg\fR
+Returns the exponential of \fIarg\fR, defined as \fIe\fR**\fIarg\fR.
+If the result would cause an overflow, an error is returned.
+.TP
+\fBfloor \fIarg\fR
+Returns the largest integral floating-point value (i.e. with a zero
+fractional part) not greater than \fIarg\fR. The argument may be
+any numeric value.
+.TP
+\fBfmod \fIx y\fR
+Returns the floating-point remainder of the division of \fIx\fR by
+\fIy\fR. If \fIy\fR is 0, an error is returned.
+.TP
+\fBhypot \fIx y\fR
+Computes the length of the hypotenuse of a right-angled triangle
+.QW "\fBsqrt\fR [\fBexpr\fR {\fIx\fB*\fIx\fB+\fIy\fB*\fIy\fR}]".
+.TP
+\fBint \fIarg\fR
+The argument may be any numeric value. The integer part of \fIarg\fR
+is determined, and then the low order bits of that integer value up
+to the machine word size are returned as an integer value. For reference,
+the number of bytes in the machine word are stored in
+\fBtcl_platform(wordSize)\fR.
+.TP
+\fBisqrt \fIarg\fR
+Computes the integer part of the square root of \fIarg\fR. \fIArg\fR must be
+a positive value, either an integer or a floating point number.
+Unlike \fBsqrt\fR, which is limited to the precision of a floating point
+number, \fIisqrt\fR will return a result of arbitrary precision.
+.TP
+\fBlog \fIarg\fR
+Returns the natural logarithm of \fIarg\fR. \fIArg\fR must be a
+positive value.
+.TP
+\fBlog10 \fIarg\fR
+Returns the base 10 logarithm of \fIarg\fR. \fIArg\fR must be a
+positive value.
+.TP
+\fBmax \fIarg\fB \fI...\fR
+Accepts one or more numeric arguments. Returns the one argument
+with the greatest value.
+.TP
+\fBmin \fIarg\fB \fI...\fR
+Accepts one or more numeric arguments. Returns the one argument
+with the least value.
+.TP
+\fBpow \fIx y\fR
+Computes the value of \fIx\fR raised to the power \fIy\fR. If \fIx\fR
+is negative, \fIy\fR must be an integer value.
+.TP
+\fBrand\fR
+Returns a pseudo-random floating-point value in the range (\fI0\fR,\fI1\fR).
+The generator algorithm is a simple linear congruential generator that
+is not cryptographically secure. Each result from \fBrand\fR completely
+determines all future results from subsequent calls to \fBrand\fR, so
+\fBrand\fR should not be used to generate a sequence of secrets, such as
+one-time passwords. The seed of the generator is initialized from the
+internal clock of the machine or may be set with the \fBsrand\fR function.
+.TP
+\fBround \fIarg\fR
+If \fIarg\fR is an integer value, returns \fIarg\fR, otherwise converts
+\fIarg\fR to integer by rounding and returns the converted value.
+.TP
+\fBsin \fIarg\fR
+Returns the sine of \fIarg\fR, measured in radians.
+.TP
+\fBsinh \fIarg\fR
+Returns the hyperbolic sine of \fIarg\fR. If the result would cause
+an overflow, an error is returned.
+.TP
+\fBsqrt \fIarg\fR
+The argument may be any non-negative numeric value. Returns a floating-point
+value that is the square root of \fIarg\fR. May return \fBInf\fR when the
+argument is a numeric value that exceeds the square of the maximum value of
+the floating-point range.
+.TP
+\fBsrand \fIarg\fR
+The \fIarg\fR, which must be an integer, is used to reset the seed for
+the random number generator of \fBrand\fR. Returns the first random
+number (see \fBrand\fR) from that seed. Each interpreter has its own seed.
+.TP
+\fBtan \fIarg\fR
+Returns the tangent of \fIarg\fR, measured in radians.
+.TP
+\fBtanh \fIarg\fR
+Returns the hyperbolic tangent of \fIarg\fR.
+.TP
+\fBwide \fIarg\fR
+The argument may be any numeric value. The integer part of \fIarg\fR
+is determined, and then the low order 64 bits of that integer value
+are returned as an integer value.
+.SH "SEE ALSO"
+expr(n), mathop(n), namespace(n)
+.SH "COPYRIGHT"
+.nf
+Copyright (c) 1993 The Regents of the University of California.
+Copyright (c) 1994-2000 Sun Microsystems Incorporated.
+Copyright (c) 2005, 2006 by Kevin B. Kenny <kennykb@acm.org>.
+.fi
diff --git a/doc/mathop.n b/doc/mathop.n
new file mode 100644
index 0000000..5a6ba4e
--- /dev/null
+++ b/doc/mathop.n
@@ -0,0 +1,299 @@
+.\" -*- nroff -*-
+.\" Copyright (c) 2006-2007 Donal K. Fellows.
+.\"
+.\" See the file "license.terms" for information on usage and redistribution
+.\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+.\"
+.so man.macros
+.TH mathop n 8.5 Tcl "Tcl Mathematical Operator Commands"
+.BS
+.\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+mathop \- Mathematical operators as Tcl commands
+.SH SYNOPSIS
+package require \fBTcl 8.5\fR
+.sp
+\fB::tcl::mathop::!\fR \fInumber\fR
+.br
+\fB::tcl::mathop::~\fR \fInumber\fR
+.br
+\fB::tcl::mathop::+\fR ?\fInumber\fR ...?
+.br
+\fB::tcl::mathop::\-\fR \fInumber\fR ?\fInumber\fR ...?
+.br
+\fB::tcl::mathop::*\fR ?\fInumber\fR ...?
+.br
+\fB::tcl::mathop::/\fR \fInumber\fR ?\fInumber\fR ...?
+.br
+\fB::tcl::mathop::%\fR \fInumber number\fR
+.br
+\fB::tcl::mathop::**\fR ?\fInumber\fR ...?
+.br
+\fB::tcl::mathop::&\fR ?\fInumber\fR ...?
+.br
+\fB::tcl::mathop::|\fR ?\fInumber\fR ...?
+.br
+\fB::tcl::mathop::^\fR ?\fInumber\fR ...?
+.br
+\fB::tcl::mathop::<<\fR \fInumber number\fR
+.br
+\fB::tcl::mathop::>>\fR \fInumber number\fR
+.br
+\fB::tcl::mathop::==\fR ?\fIarg\fR ...?
+.br
+\fB::tcl::mathop::!=\fR \fIarg arg\fR
+.br
+\fB::tcl::mathop::<\fR ?\fIarg\fR ...?
+.br
+\fB::tcl::mathop::<=\fR ?\fIarg\fR ...?
+.br
+\fB::tcl::mathop::>=\fR ?\fIarg\fR ...?
+.br
+\fB::tcl::mathop::>\fR ?\fIarg\fR ...?
+.br
+\fB::tcl::mathop::eq\fR ?\fIarg\fR ...?
+.br
+\fB::tcl::mathop::ne\fR \fIarg arg\fR
+.br
+\fB::tcl::mathop::in\fR \fIarg list\fR
+.br
+\fB::tcl::mathop::ni\fR \fIarg list\fR
+.sp
+.BE
+.SH DESCRIPTION
+.PP
+The commands in the \fB::tcl::mathop\fR namespace implement the same set of
+operations as supported by the \fBexpr\fR command. All are exported from the
+namespace, but are not imported into any other namespace by default. Note that
+renaming, reimplementing or deleting any of the commands in the namespace does
+\fInot\fR alter the way that the \fBexpr\fR command behaves, and nor does
+defining any new commands in the \fB::tcl::mathop\fR namespace.
+.PP
+The following operator commands are supported:
+.DS
+.ta 2c 4c 6c 8c
+\fB~\fR \fB!\fR \fB+\fR \fB\-\fR \fB*\fR
+\fB/\fR \fB%\fR \fB**\fR \fB&\fR \fB|\fR
+\fB^\fR \fB>>\fR \fB<<\fR \fB==\fR \fBeq\fR
+\fB!=\fR \fBne\fR \fB<\fR \fB<=\fR \fB>\fR
+\fB>=\fR \fBin\fR \fBni\fR
+.DE
+.SS "MATHEMATICAL OPERATORS"
+.PP
+The behaviors of the mathematical operator commands are as follows:
+.TP
+\fB!\fR \fIboolean\fR
+.
+Returns the boolean negation of \fIboolean\fR, where \fIboolean\fR may be any
+numeric value or any other form of boolean value (i.e. it returns truth if the
+argument is falsity or zero, and falsity if the argument is truth or
+non-zero).
+.TP
+\fB+\fR ?\fInumber\fR ...?
+.
+Returns the sum of arbitrarily many arguments. Each \fInumber\fR argument may
+be any numeric value. If no arguments are given, the result will be zero (the
+summation identity).
+.TP
+\fB\-\fR \fInumber\fR ?\fInumber\fR ...?
+.
+If only a single \fInumber\fR argument is given, returns the negation of that
+numeric value. Otherwise returns the number that results when all subsequent
+numeric values are subtracted from the first one. All \fInumber\fR arguments
+must be numeric values. At least one argument must be given.
+.TP
+\fB*\fR ?\fInumber\fR ...?
+.
+Returns the product of arbitrarily many arguments. Each \fInumber\fR may be
+any numeric value. If no arguments are given, the result will be one (the
+multiplicative identity).
+.TP
+\fB/\fR \fInumber\fR ?\fInumber\fR ...?
+.
+If only a single \fInumber\fR argument is given, returns the reciprocal of that
+numeric value (i.e. the value obtained by dividing 1.0 by that value).
+Otherwise returns the number that results when the first numeric argument is
+divided by all subsequent numeric arguments. All \fInumber\fR arguments must
+be numeric values. At least one argument must be given.
+.RS
+.PP
+Note that when the leading values in the list of arguments are integers,
+integer division will be used for those initial steps (i.e. the intermediate
+results will be as if the functions \fIfloor\fR and \fIint\fR are applied to
+them, in that order). If all values in the operation are integers, the result
+will be an integer.
+.RE
+.TP
+\fB%\fR \fInumber number\fR
+.
+Returns the integral modulus of the first argument with respect to the second.
+Each \fInumber\fR must have an integral value. Note that Tcl defines this
+operation exactly even for negative numbers, so that the following equality
+holds true:
+.RS
+.CS
+(\fIx \fB/ \fIy\fR) \fB* \fIy \fB== \fIx \fB-\fR (\fIx \fB% \fIy\fR)
+.CE
+.RE
+.TP
+\fB**\fR ?\fInumber\fR ...?
+.
+Returns the result of raising each value to the power of the result of
+recursively operating on the result of processing the following arguments, so
+.QW "\fB** 2 3 4\fR"
+is the same as
+.QW "\fB** 2 [** 3 4]\fR" .
+Each \fInumber\fR may be
+any numeric value, though the second number must not be fractional if the
+first is negative. If no arguments are given, the result will be one, and if
+only one argument is given, the result will be that argument. The
+result will have an integral value only when all arguments are
+integral values.
+.SS "COMPARISON OPERATORS"
+.PP
+The behaviors of the comparison operator commands (most of which operate
+preferentially on numeric arguments) are as follows:
+.TP
+\fB==\fR ?\fIarg\fR ...?
+.
+Returns whether each argument is equal to the arguments on each side of it in
+the sense of the \fBexpr\fR == operator (\fIi.e.\fR, numeric comparison if
+possible, exact string comparison otherwise). If fewer than two arguments
+are given, this operation always returns a true value.
+.TP
+\fBeq\fR ?\fIarg\fR ...?
+.
+Returns whether each argument is equal to the arguments on each side of it
+using exact string comparison. If fewer than two arguments are given, this
+operation always returns a true value.
+.TP
+\fB!=\fR \fIarg arg\fR
+.
+Returns whether the two arguments are not equal to each other, in the sense of
+the \fBexpr\fR != operator (\fIi.e.\fR, numeric comparison if possible, exact
+string comparison otherwise).
+.TP
+\fBne\fR \fIarg arg\fR
+.
+Returns whether the two arguments are not equal to each other using exact
+string comparison.
+.TP
+\fB<\fR ?\fIarg\fR ...?
+.
+Returns whether the arbitrarily-many arguments are ordered, with each argument
+after the first having to be strictly more than the one preceding it.
+Comparisons are performed preferentially on the numeric values, and are
+otherwise performed using UNICODE string comparison. If fewer than two
+arguments are present, this operation always returns a true value. When the
+arguments are numeric but should be compared as strings, the \fBstring
+compare\fR command should be used instead.
+.TP
+\fB<=\fR ?\fIarg\fR ...?
+.
+Returns whether the arbitrarily-many arguments are ordered, with each argument
+after the first having to be equal to or more than the one preceding it.
+Comparisons are performed preferentially on the numeric values, and are
+otherwise performed using UNICODE string comparison. If fewer than two
+arguments are present, this operation always returns a true value. When the
+arguments are numeric but should be compared as strings, the \fBstring
+compare\fR command should be used instead.
+.TP
+\fB>\fR ?\fIarg\fR ...?
+.
+Returns whether the arbitrarily-many arguments are ordered, with each argument
+after the first having to be strictly less than the one preceding it.
+Comparisons are performed preferentially on the numeric values, and are
+otherwise performed using UNICODE string comparison. If fewer than two
+arguments are present, this operation always returns a true value. When the
+arguments are numeric but should be compared as strings, the \fBstring
+compare\fR command should be used instead.
+.TP
+\fB>=\fR ?\fIarg\fR ...?
+.
+Returns whether the arbitrarily-many arguments are ordered, with each argument
+after the first having to be equal to or less than the one preceding it.
+Comparisons are performed preferentially on the numeric values, and are
+otherwise performed using UNICODE string comparison. If fewer than two
+arguments are present, this operation always returns a true value. When the
+arguments are numeric but should be compared as strings, the \fBstring
+compare\fR command should be used instead.
+.SS "BIT-WISE OPERATORS"
+.PP
+The behaviors of the bit-wise operator commands (all of which only operate on
+integral arguments) are as follows:
+.TP
+\fB~\fR \fInumber\fR
+.
+Returns the bit-wise negation of \fInumber\fR. \fINumber\fR may be an integer
+of any size. Note that the result of this operation will always have the
+opposite sign to the input \fInumber\fR.
+.TP
+\fB&\fR ?\fInumber\fR ...?
+.
+Returns the bit-wise AND of each of the arbitrarily many arguments. Each
+\fInumber\fR must have an integral value. If no arguments are given, the
+result will be minus one.
+.TP
+\fB|\fR ?\fInumber\fR ...?
+.
+Returns the bit-wise OR of each of the arbitrarily many arguments. Each
+\fInumber\fR must have an integral value. If no arguments are given, the
+result will be zero.
+.TP
+\fB^\fR ?\fInumber\fR ...?
+.
+Returns the bit-wise XOR of each of the arbitrarily many arguments. Each
+\fInumber\fR must have an integral value. If no arguments are given, the
+result will be zero.
+.TP
+\fB<<\fR \fInumber number\fR
+.
+Returns the result of bit-wise shifting the first argument left by the
+number of bits specified in the second argument. Each \fInumber\fR
+must have an integral value.
+.TP
+\fB>>\fR \fInumber number\fR
+.
+Returns the result of bit-wise shifting the first argument right by
+the number of bits specified in the second argument. Each \fInumber\fR
+must have an integral value.
+.SS "LIST OPERATORS"
+.PP
+The behaviors of the list-oriented operator commands are as follows:
+.TP
+\fBin\fR \fIarg list\fR
+.
+Returns whether the value \fIarg\fR is present in the list \fIlist\fR
+(according to exact string comparison of elements).
+.TP
+\fBni\fR \fIarg list\fR
+.
+Returns whether the value \fIarg\fR is not present in the list \fIlist\fR
+(according to exact string comparison of elements).
+.SH EXAMPLES
+The simplest way to use the operators is often by using \fBnamespace path\fR
+to make the commands available. This has the advantage of not affecting the
+set of commands defined by the current namespace.
+.CS
+namespace path {\fB::tcl::mathop\fR ::tcl::mathfunc}
+
+\fI# Compute the sum of some numbers\fR
+set sum [\fB+\fR 1 2 3]
+
+\fI# Compute the average of a list\fR
+set list {1 2 3 4 5 6}
+set mean [\fB/\fR [\fB+\fR {*}$list] [double [llength $list]]]
+
+\fI# Test for list membership\fR
+set gotIt [\fBin\fR 3 $list]
+
+\fI# Test to see if a value is within some defined range\fR
+set inRange [\fB<=\fR 1 $x 5]
+
+\fI# Test to see if a list is sorted\fR
+set sorted [\fB<=\fR {*}$list]
+.CE
+.SH "SEE ALSO"
+expr(n), mathfunc(n), namespace(n)
+.SH KEYWORDS
+command, expression, operator
diff --git a/doc/memory.n b/doc/memory.n
index 9485192..4ff681d 100644
--- a/doc/memory.n
+++ b/doc/memory.n
@@ -7,11 +7,10 @@
.TH memory n 8.1 Tcl "Tcl Built-In Commands"
.BS
.SH NAME
-memory \- Control Tcl memory debugging capabilities.
+memory \- Control Tcl memory debugging capabilities
.SH SYNOPSIS
\fBmemory \fIoption \fR?\fIarg arg ...\fR?
.BE
-
.SH DESCRIPTION
.PP
The \fBmemory\fR command gives the Tcl developer control of Tcl's memory
@@ -21,9 +20,11 @@ memory debugging enabled (when \fBTCL_MEM_DEBUG\fR is defined at
compile time), and after \fBTcl_InitMemory\fR has been called.
.TP
\fBmemory active\fR \fIfile\fR
+.
Write a list of all currently allocated memory to the specified \fIfile\fR.
.TP
\fBmemory break_on_malloc\fR \fIcount\fR
+.
After the \fIcount\fR allocations have been performed, \fBckalloc\fR
outputs a message to this effect and that it is now attempting to enter
the C debugger. Tcl will then issue a \fISIGINT\fR signal against itself.
@@ -31,22 +32,33 @@ If you are running Tcl under a C debugger, it should then enter the debugger
command mode.
.TP
\fBmemory info\fR
+.
Returns a report containing the total allocations and frees since
Tcl began, the current packets allocated (the current
number of calls to \fBckalloc\fR not met by a corresponding call
to \fBckfree\fR), the current bytes allocated, and the maximum number
of packets and bytes allocated.
.TP
-\fB memory init [on|off]\fR
+\fBmemory init \fR[\fBon\fR|\fBoff\fR]
+.
Turn on or off the pre-initialization of all allocated memory
-with bogus bytes. Useful for detecting the use of uninitialized values.
+with bogus bytes. Useful for detecting the use of uninitialized
+values.
+.TP
+\fBmemory objs \fIfile\fR
+.
+Causes a list of all allocated Tcl_Obj values to be written to the specified
+\fIfile\fR immediately, together with where they were allocated. Useful for
+checking for leaks of values.
.TP
\fBmemory onexit\fR \fIfile\fR
+.
Causes a list of all allocated memory to be written to the specified \fIfile\fR
during the finalization of Tcl's memory subsystem. Useful for checking
that memory is properly cleaned up during process exit.
.TP
\fBmemory tag\fR \fIstring\fR
+.
Each packet of memory allocated by \fBckalloc\fR can have associated
with it a string-valued tag. In the lists of allocated memory generated
by \fBmemory active\fR and \fBmemory onexit\fR, the tag for each packet
@@ -54,22 +66,25 @@ is printed along with other information about the packet. The
\fBmemory tag\fR command sets the tag value for subsequent calls
to \fBckalloc\fR to be \fIstring\fR.
.TP
-\fBmemory trace [on|off]\fR
-.br
+\fBmemory trace \fR[\fBon\fR|\fBoff\fR]
+.
Turns memory tracing on or off. When memory tracing is on, every call
to \fBckalloc\fR causes a line of trace information to be written to
\fIstderr\fR, consisting of the word \fIckalloc\fR, followed by the
address returned, the amount of memory allocated, and the C filename
and line number of the code performing the allocation. For example:
.RS
+.PP
.CS
ckalloc 40e478 98 tclProc.c 1406
.CE
+.PP
Calls to \fBckfree\fR are traced in the same manner.
.RE
.TP
\fBmemory trace_on_at_malloc\fR \fIcount\fR
-Enable memory tracing after \fIcount\fR \fBckalloc\fR's have been performed.
+.
+Enable memory tracing after \fIcount\fR \fBckalloc\fRs have been performed.
For example, if you enter \fBmemory trace_on_at_malloc 100\fR,
after the 100th call to \fBckalloc\fR, memory trace information will begin
being displayed for all allocations and frees. Since there can be a lot
@@ -79,7 +94,8 @@ produced), if you can identify a number of allocations that occur before
the problem sets in. The current number of memory allocations that have
occurred since Tcl started is printed on a guard zone failure.
.TP
-\fBmemory validate [on|off]\fR
+\fBmemory validate \fR[\fBon\fR|\fBoff\fR]
+.
Turns memory validation on or off. When memory validation is enabled,
on every call to \fBckalloc\fR or \fBckfree\fR, the guard zones are
checked for every piece of memory currently in existence that was
@@ -90,9 +106,7 @@ overwrite can be detected on the first call to \fBckalloc\fR or
\fBckfree\fR after the overwrite occurred, rather than when the
specific memory with the overwritten guard zone(s) is freed, which may
occur long after the overwrite occurred.
-
.SH "SEE ALSO"
ckalloc, ckfree, Tcl_ValidateAllMemory, Tcl_DumpActiveMemory, TCL_MEM_DEBUG
-
.SH KEYWORDS
memory, debug
diff --git a/doc/msgcat.n b/doc/msgcat.n
index e6e08b5..00141ad 100644
--- a/doc/msgcat.n
+++ b/doc/msgcat.n
@@ -5,15 +5,15 @@
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
-.TH "msgcat" n 1.3 msgcat "Tcl Bundled Packages"
+.TH "msgcat" n 1.4 msgcat "Tcl Bundled Packages"
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
msgcat \- Tcl message catalog
.SH SYNOPSIS
-\fBpackage require Tcl 8.2\fR
+\fBpackage require Tcl 8.5\fR
.sp
-\fBpackage require msgcat 1.3.4\fR
+\fBpackage require msgcat 1.4.2\fR
.sp
\fB::msgcat::mc \fIsrc-string\fR ?\fIarg arg ...\fR?
.sp
@@ -31,13 +31,13 @@ msgcat \- Tcl message catalog
.sp
\fB::msgcat::mcunknown \fIlocale src-string\fR
.BE
-
.SH DESCRIPTION
.PP
The \fBmsgcat\fR package provides a set of functions
that can be used to manage multi-lingual user interfaces.
-Text strings are defined in a ``message catalog'' which
-is independent from the application, and
+Text strings are defined in a
+.QW "message catalog"
+which is independent from the application, and
which can be edited or localized without modifying
the application source code. New languages
or locales are provided by adding a new file to
@@ -53,6 +53,7 @@ Returns a translation of \fIsrc-string\fR according to the
user's current locale. If additional arguments past \fIsrc-string\fR
are given, the \fBformat\fR command is used to substitute the
additional arguments in the translation of \fIsrc-string\fR.
+.RS
.PP
\fB::msgcat::mc\fR will search the messages defined
in the current namespace for a translation of \fIsrc-string\fR; if
@@ -67,6 +68,7 @@ application can pass the English string through \fB::msgcat::mc\fR and
use the result. If an application is written for a single language in
this fashion, then it is easy to add support for additional languages
later simply by defining new message catalog entries.
+.RE
.TP
\fB::msgcat::mcmax ?\fIsrc-string src-string ...\fR?
Given several source strings, \fB::msgcat::mcmax\fR returns the length
@@ -91,13 +93,16 @@ preference. The list is derived from the current
locale set in msgcat by \fB::msgcat::mclocale\fR, and
cannot be set independently. For example, if the
current locale is en_US_funky, then \fB::msgcat::mcpreferences\fR
-returns \fB{en_US_funky en_US en}\fR.
+.VS 1.4
+returns \fB{en_US_funky en_US en {}}\fR.
+.VE 1.4
.TP
\fB::msgcat::mcload \fIdirname\fR
Searches the specified directory for files that match
the language specifications returned by \fB::msgcat::mcpreferences\fR
-(note that these are all lowercase), extended by the file
-extension ``.msg''. Each matching file is
+(note that these are all lowercase), extended by the file extension
+.QW .msg .
+Each matching file is
read in order, assuming a UTF-8 encoding. The file contents are
then evaluated as a Tcl script. This means that Unicode characters
may be present in the message file either directly in their UTF-8
@@ -137,10 +142,15 @@ The locale is specified to \fBmsgcat\fR by a locale string
passed to \fB::msgcat::mclocale\fR.
The locale string consists of
a language code, an optional country code, and an optional
-system-specific code, each separated by ``_''. The country and language
+system-specific code, each separated by
+.QW _ .
+The country and language
codes are specified in standards ISO-639 and ISO-3166.
-For example, the locale ``en'' specifies English and ``en_US'' specifies
-U.S. English.
+For example, the locale
+.QW en
+specifies English and
+.QW en_US
+specifies U.S. English.
.PP
When the msgcat package is first loaded, the locale is initialized
according to the user's environment. The variables \fBenv(LC_ALL)\fR,
@@ -159,14 +169,25 @@ On Windows, if none of those environment variables is set, msgcat will
attempt to extract locale information from the
registry. If all these attempts to discover an initial locale
from the user's environment fail, msgcat defaults to an initial
-locale of ``C''.
+locale of
+.QW C .
.PP
-When a locale is specified by the user, a ``best match'' search is
-performed during string translation. For example, if a user specifies
-en_GB_Funky, the locales ``en_GB_Funky'', ``en_GB'', and ``en'' are
-searched in order until a matching translation string is found. If no
-translation string is available, then \fB::msgcat::mcunknown\fR is
-called.
+When a locale is specified by the user, a
+.QW "best match"
+search is performed during string translation. For example, if a user
+specifies
+.VS 1.4
+en_GB_Funky, the locales
+.QW en_GB_Funky ,
+.QW en_GB ,
+.QW en
+and
+.MT
+(the empty string)
+.VE 1.4
+are searched in order until a matching translation
+string is found. If no translation string is available, then
+\fB::msgcat::mcunknown\fR is called.
.SH "NAMESPACES AND MESSAGE CATALOGS"
.PP
Strings stored in the message catalog are stored relative
@@ -194,10 +215,13 @@ hello from ::foo
When searching for a translation of a message, the
message catalog will search first the current namespace,
then the parent of the current namespace, and so on until
-the global namespace is reached. This allows child namespaces
-to "inherit" messages from their parent namespace.
+the global namespace is reached. This allows child namespaces to
+.QW inherit
+messages from their parent namespace.
.PP
-For example, executing (in the ``en'' locale) the code
+For example, executing (in the
+.QW en
+locale) the code
.CS
\fB::msgcat::mcset\fR en m1 ":: message1"
\fB::msgcat::mcset\fR en m2 ":: message2"
@@ -227,12 +251,23 @@ to the following conditions:
.IP [1]
All message files for a package are in the same directory.
.IP [2]
-The message file name is a msgcat locale specifier (all lowercase)
-followed by ``.msg''. For example:
+The message file name is a msgcat locale specifier (all lowercase) followed by
+.QW .msg .
+For example:
.CS
-es.msg -- spanish
-en_gb.msg -- United Kingdom English
+es.msg \(em spanish
+en_gb.msg \(em United Kingdom English
.CE
+.VS 1.4
+\fIException:\fR The message file for the root locale
+.MT
+is called
+.QW \fBROOT.msg\fR .
+This exception is made so as not to
+cause peculiar behavior, such as marking the message file as
+.QW hidden
+on Unix file systems.
+.VE 1.4
.IP [3]
The file contains a series of calls to \fBmcset\fR and
\fBmcmset\fR, setting the necessary translation strings
@@ -276,8 +311,8 @@ format "In location %s we produced %d units" $city $num
This can be handled by using the positional
parameters:
.CS
-format "We produced %1\\$d units in location %2\\$s" $num $city
-format "In location %2\\$s we produced %1\\$d units" $num $city
+format "We produced %1\e$d units in location %2\e$s" $num $city
+format "In location %2\e$s we produced %1\e$d units" $num $city
.CE
.PP
Similarly, positional parameters can be used with \fBscan\fR to
@@ -285,9 +320,7 @@ extract values from internationalized strings.
.SH CREDITS
.PP
The message catalog code was developed by Mark Harrison.
-
.SH "SEE ALSO"
format(n), scan(n), namespace(n), package(n)
-
.SH KEYWORDS
internationalization, i18n, localization, l10n, message, text, translation
diff --git a/doc/namespace.n b/doc/namespace.n
index 5468416..ddf7b51 100644
--- a/doc/namespace.n
+++ b/doc/namespace.n
@@ -2,28 +2,28 @@
'\" Copyright (c) 1993-1997 Bell Labs Innovations for Lucent Technologies
'\" Copyright (c) 1997 Sun Microsystems, Inc.
'\" Copyright (c) 2000 Scriptics Corporation.
+'\" Copyright (c) 2004-2005 Donal K. Fellows.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
-.TH namespace n 8.0 Tcl "Tcl Built-In Commands"
+.TH namespace n 8.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
namespace \- create and manipulate contexts for commands and variables
.SH SYNOPSIS
-\fBnamespace \fR?\fIoption\fR? ?\fIarg ...\fR?
+\fBnamespace \fR?\fIsubcommand\fR? ?\fIarg ...\fR?
.BE
-
.SH DESCRIPTION
.PP
The \fBnamespace\fR command lets you create, access, and destroy
separate contexts for commands and variables.
See the section \fBWHAT IS A NAMESPACE?\fR below
for a brief overview of namespaces.
-The legal values of \fIoption\fR are listed below.
-Note that you can abbreviate the \fIoption\fRs.
+The legal values of \fIsubcommand\fR are listed below.
+Note that you can abbreviate the \fIsubcommand\fRs.
.TP
\fBnamespace children \fR?\fInamespace\fR? ?\fIpattern\fR?
Returns a list of all child namespaces that belong to the
@@ -54,7 +54,7 @@ and they will be passed to \fIscript\fR as additional arguments.
For example, suppose the command
\fBset script [namespace code {foo bar}]\fR
is invoked in namespace \fB::a::b\fR.
-Then \fBeval "$script x y"\fR
+Then \fBeval $script [list x y]\fR
can be executed in any namespace (assuming the value of
\fBscript\fR has been passed in properly)
and will have the same effect as the command
@@ -69,7 +69,8 @@ of how this is used to create callback scripts.
.TP
\fBnamespace current\fR
Returns the fully-qualified name for the current namespace.
-The actual name of the global namespace is ``''
+The actual name of the global namespace is
+.MT
(i.e., an empty string),
but this command returns \fB::\fR for the global namespace
as a convenience to programmers.
@@ -82,9 +83,16 @@ If a procedure is currently executing inside the namespace,
the namespace will be kept alive until the procedure returns;
however, the namespace is marked to prevent other code from
looking it up by name.
-If a namespace doesn't exist, this command returns an error.
+If a namespace does not exist, this command returns an error.
If no namespace names are given, this command does nothing.
.TP
+\fBnamespace ensemble\fR \fIsubcommand\fR ?\fIarg ...\fR?
+.VS 8.5
+Creates and manipulates a command that is formed out of an ensemble of
+subcommands. See the section \fBENSEMBLES\fR below for further
+details.
+.VE 8.5
+.TP
\fBnamespace eval\fR \fInamespace arg\fR ?\fIarg ...\fR?
Activates a namespace called \fInamespace\fR and evaluates some code
in that context.
@@ -93,11 +101,12 @@ If more than one \fIarg\fR argument is specified,
the arguments are concatenated together with a space between each one
in the same fashion as the \fBeval\fR command,
and the result is evaluated.
-.br
-.sp
+.RS
+.PP
If \fInamespace\fR has leading namespace qualifiers
and any leading namespaces do not exist,
they are automatically created.
+.RE
.TP
\fBnamespace exists\fR \fInamespace\fR
Returns \fB1\fR if \fInamespace\fR is a valid namespace in the current
@@ -117,10 +126,10 @@ but it may not include any namespace qualifiers.
That is, the pattern can only specify commands
in the current (exporting) namespace.
Each \fIpattern\fR is appended onto the namespace's list of export patterns.
-If the \-\fBclear\fR flag is given,
+If the \fB\-clear\fR flag is given,
the namespace's export pattern list is reset to empty before any
\fIpattern\fR arguments are appended.
-If no \fIpattern\fRs are given and the \-\fBclear\fR flag isn't given,
+If no \fIpattern\fRs are given and the \fB\-clear\fR flag is not given,
this command returns the namespace's current export list.
.TP
\fBnamespace forget \fR?\fIpattern pattern ...\fR?
@@ -129,24 +138,37 @@ Each \fIpattern\fR is a simple or qualified name such as
\fBx\fR, \fBfoo::x\fR or \fBa::b::p*\fR.
Qualified names contain double colons (\fB::\fR) and qualify a name
with the name of one or more namespaces.
-Each \fIqualified pattern\fR is qualified with the name of an
-exporting namespace
+Each
+.QW "qualified pattern"
+is qualified with the name of an exporting namespace
and may have glob-style special characters in the command name
at the end of the qualified name.
Glob characters may not appear in a namespace name.
-For each \fIsimple pattern\fR this command deletes the matching
-commands of the
+For each
+.QW "simple pattern"
+this command deletes the matching commands of the
current namespace that were imported from a different namespace.
-For \fIqualified patterns\fR, this command first finds the matching
-exported commands.
+For
+.QW "qualified patterns" ,
+this command first finds the matching exported commands.
It then checks whether any of those commands
were previously imported by the current namespace.
-If so, this command deletes the corresponding imported commands.
+If so, this command deletes the corresponding imported commands.
In effect, this un-does the action of a \fBnamespace import\fR command.
.TP
\fBnamespace import \fR?\fB\-force\fR? ?\fIpattern\fR \fIpattern ...\fR?
-Imports commands into a namespace.
-Each \fIpattern\fR is a qualified name like
+.VS 8.5
+Imports commands into a namespace, or queries the set of imported
+commands in a namespace. When no arguments are present,
+\fBnamespace import\fR returns the list of commands in
+the current namespace that have been imported from other
+namespaces. The commands in the returned list are in
+the format of simple names, with no namespace qualifiers at all.
+This format is suitable for composition with \fBnamespace forget\fR
+(see \fBEXAMPLES\fR below).
+.VE 8.5
+When \fIpattern\fR arguments are present,
+each \fIpattern\fR is a qualified name like
\fBfoo::x\fR or \fBa::p*\fR.
That is, it includes the name of an exporting namespace
and may have glob-style special characters in the command name
@@ -180,12 +202,18 @@ The \fBnamespace inscope\fR command is much like the \fBnamespace eval\fR
command except that the \fInamespace\fR must already exist,
and \fBnamespace inscope\fR appends additional \fIarg\fRs
as proper list elements.
-.br
+.RS
+.PP
+.CS
\fBnamespace inscope ::foo $script $x $y $z\fR
+.CE
is equivalent to
+.CS
\fBnamespace eval ::foo [concat $script [list $x $y $z]]\fR
+.CE
thus additional arguments will not undergo a second round of substitution,
as is the case with \fBnamespace eval\fR.
+.RE
.TP
\fBnamespace origin \fIcommand\fR
Returns the fully-qualified name of the original command
@@ -207,6 +235,17 @@ for namespace \fInamespace\fR.
If \fInamespace\fR is not specified,
the fully-qualified name of the current namespace's parent is returned.
.TP
+\fBnamespace path\fR ?\fInamespaceList\fR?
+.\" Should really have the .TP inside the .VS, but that triggers a groff bug
+.VS 8.5
+Returns the command resolution path of the current namespace. If
+\fInamespaceList\fR is specified as a list of named namespaces, the
+current namespace's command resolution path is set to those namespaces
+and returns the empty list. The default command resolution path is
+always empty. See the section \fBNAME RESOLUTION\fR below for an
+explanation of the rules regarding name resolution.
+.VE 8.5
+.TP
\fBnamespace qualifiers\fR \fIstring\fR
Returns any leading namespace qualifiers for \fIstring\fR.
Qualifiers are namespace names separated by double colons (\fB::\fR).
@@ -228,6 +267,27 @@ This command is the complement of the \fBnamespace qualifiers\fR command.
It does not check whether the namespace names are, in fact,
the names of currently defined namespaces.
.TP
+\fBnamespace upvar\fR \fInamespace\fR \fIotherVar myVar \fR?\fIotherVar myVar \fR...
+This command arranges for one or more local variables in the current
+procedure to refer to variables in \fInamespace\fR. The namespace name is
+resolved as described in section \fBNAME RESOLUTION\fR.
+The command
+\fBnamespace upvar $ns a b\fR has the same behaviour as
+\fBupvar 0 ${ns}::a b\fR, with the sole exception of the resolution rules
+used for qualified namespace or variable names.
+\fBnamespace upvar\fR returns an empty string.
+.TP
+\fBnamespace unknown\fR ?\fIscript\fR?
+Sets or returns the unknown command handler for the current namespace.
+The handler is invoked when a command called from within the namespace
+cannot be found (in either the current namespace or the global namespace).
+The \fIscript\fR argument, if given, should be a well
+formed list representing a command name and optional arguments. When
+the handler is invoked, the full invocation line will be appended to the
+script and the result evaluated in the context of the namespace. The
+default handler for all namespaces is \fB::unknown\fR. If no argument
+is given, it returns the handler for the current namespace.
+.TP
\fBnamespace which\fR ?\-\fBcommand\fR? ?\-\fBvariable\fR? \fIname\fR
Looks up \fIname\fR as either a command or variable
and returns its fully-qualified name.
@@ -237,7 +297,7 @@ this command returns a fully-qualified name in the global namespace.
If the command or variable does not exist,
this command returns an empty string. If the variable has been
created but not defined, such as with the \fBvariable\fR command
-or through a \fBtrace\fR on the variable, this command will return the
+or through a \fBtrace\fR on the variable, this command will return the
fully-qualified name of the variable.
If no flag is given, \fIname\fR is treated as a command name.
See the section \fBNAME RESOLUTION\fR below for an explanation of
@@ -246,7 +306,7 @@ the rules regarding name resolution.
.PP
A namespace is a collection of commands and variables.
It encapsulates the commands and variables to ensure that they
-won't interfere with the commands and variables of other namespaces.
+will not interfere with the commands and variables of other namespaces.
Tcl has always had one such collection,
which we refer to as the \fIglobal namespace\fR.
The global namespace holds all global variables and commands.
@@ -317,8 +377,9 @@ Qualified names are similar to the hierarchical path names for
Unix files or Tk widgets,
except that \fB::\fR is used as the separator
instead of \fB/\fR or \fB.\fR.
-The topmost or global namespace has the name ``'' (i.e., an empty string),
-although \fB::\fR is a synonym.
+The topmost or global namespace has the name
+.MT
+(i.e., an empty string), although \fB::\fR is a synonym.
As an example, the name \fB::safe::interp::create\fR
refers to the command \fBcreate\fR in the namespace \fBinterp\fR
that is a child of namespace \fB::safe\fR,
@@ -377,11 +438,19 @@ If you provide a fully-qualified name that starts with a \fB::\fR,
there is no question about what command, variable, or namespace
you mean.
However, if the name does not start with a \fB::\fR
-(i.e., is \fIrelative\fR),
-Tcl follows a fixed rule for looking it up:
-Command and variable names are always resolved
+(i.e., is \fIrelative\fR),
+Tcl follows basic rules for looking it up:
+Variable names are always resolved
by looking first in the current namespace,
and then in the global namespace.
+.VS 8.5
+Command names are also always resolved by looking in the current
+namespace first. If not found there, they are searched for in every
+namespace on the current namespace's command path (which is empty by
+default). If not found there, command names are looked up in the
+global namespace (or, failing that, are processed by the \fBunknown\fR
+command.)
+.VE 8.5
Namespace names, on the other hand, are always resolved
by looking in only the current namespace.
.PP
@@ -409,7 +478,7 @@ set traceLevel 0
}
.CE
Here Tcl looks for \fBtraceLevel\fR first in the namespace \fBFoo::Debug\fR.
-Since it is not found there, Tcl then looks for it
+Since it is not found there, Tcl then looks for it
in the global namespace.
The variable \fBFoo::traceLevel\fR is completely ignored
during the name resolution process.
@@ -484,7 +553,7 @@ from a namespace that that namespace exported
with a \fBnamespace export\fR command.
.PP
Importing \fIevery\fR command from a namespace is generally
-a bad idea since you don't know what you will get.
+a bad idea since you do not know what you will get.
It is better to import just the specific commands you need.
For example, the command
.CS
@@ -561,12 +630,14 @@ may be imported by other namespaces.
If a \fBnamespace import\fR command specifies a command
that is not exported, the command is not imported.
.SH "SCOPED SCRIPTS"
+.PP
The \fBnamespace code\fR command is the means by which a script may be
packaged for evaluation in a namespace other than the one in which it
was created. It is used most often to create event handlers, Tk bindings,
and traces for evaluation in the global context. For instance, the following
-code indicates how to direct a variable trace callback into the current
+code indicates how to direct a variable \fBtrace\fR callback into the current
namespace:
+.PP
.CS
\fBnamespace eval\fR a {
variable b
@@ -575,14 +646,172 @@ namespace:
puts "the value of $n1 has changed to $var"
return
}
- trace variable b w [\fBnamespace code\fR theTraceCallback]
+ trace add variable b write [\fBnamespace code\fR theTraceCallback]
}
set a::b c
.CE
+.PP
When executed, it prints the message:
+.PP
.CS
the value of a::b has changed to c
.CE
+.SH ENSEMBLES
+.PP
+.VS 8.5
+The \fBnamespace ensemble\fR is used to create and manipulate ensemble
+commands, which are commands formed by grouping subcommands together.
+The commands typically come from the current namespace when the
+ensemble was created, though this is configurable. Note that there
+may be any number of ensembles associated with any namespace
+(including none, which is true of all namespaces by default), though
+all the ensembles associated with a namespace are deleted when that
+namespace is deleted. The link between an ensemble command and its
+namespace is maintained however the ensemble is renamed.
+.PP
+Three subcommands of the \fBnamespace ensemble\fR command are defined:
+.TP
+\fBnamespace ensemble create\fR ?\fIoption value ...\fR?
+Creates a new ensemble command linked to the current namespace,
+returning the fully qualified name of the command created. The
+arguments to \fBnamespace ensemble create\fR allow the configuration
+of the command as if with the \fBnamespace ensemble configure\fR
+command. If not overridden with the \fB\-command\fR option, this
+command creates an ensemble with exactly the same name as the linked
+namespace. See the section \fBENSEMBLE OPTIONS\fR below for a full
+list of options supported and their effects.
+.TP
+\fBnamespace ensemble configure \fIcommand\fR ?\fIoption\fR? ?\fIvalue ...\fR?
+Retrieves the value of an option associated with the ensemble command
+named \fIcommand\fR, or updates some options associated with that
+ensemble command. See the section \fBENSEMBLE OPTIONS\fR below for a
+full list of options supported and their effects.
+.TP
+\fBnamespace ensemble exists\fR \fIcommand\fR
+Returns a boolean value that describes whether the command
+\fIcommand\fR exists and is an ensemble command. This command only
+ever returns an error if the number of arguments to the command is
+wrong.
+.PP
+When called, an ensemble command takes its first argument and looks it
+up (according to the rules described below) to discover a list of
+words to replace the ensemble command and subcommand with. The
+resulting list of words is then evaluated (with no further
+substitutions) as if that was what was typed originally (i.e. by
+passing the list of words through \fBTcl_EvalObjv\fR) and returning
+the result of the command. Note that it is legal to make the target
+of an ensemble rewrite be another (or even the same) ensemble
+command. The ensemble command will not be visible through the use of
+the \fBuplevel\fR or \fBinfo level\fR commands.
+.SS "ENSEMBLE OPTIONS"
+.PP
+The following options, supported by the \fBnamespace ensemble
+create\fR and \fBnamespace ensemble configure\fR commands, control how
+an ensemble command behaves:
+.TP
+\fB\-map\fR
+When non-empty, this option supplies a dictionary that provides a
+mapping from subcommand names to a list of prefix words to substitute
+in place of the ensemble command and subcommand words (in a manner
+similar to an alias created with \fBinterp alias\fR; the words are not
+reparsed after substitution). When this option is empty, the mapping
+will be from the local name of the subcommand to its fully-qualified
+name. Note that when this option is non-empty and the
+\fB\-subcommands\fR option is empty, the ensemble subcommand names
+will be exactly those words that have mappings in the dictionary.
+.TP
+\fB\-prefixes\fR
+This option (which is enabled by default) controls whether the
+ensemble command recognizes unambiguous prefixes of its subcommands.
+When turned off, the ensemble command requires exact matching of
+subcommand names.
+.TP
+\fB\-subcommands\fR
+When non-empty, this option lists exactly what subcommands are in the
+ensemble. The mapping for each of those commands will be either whatever
+is defined in the \fB\-map\fR option, or to the command with the same
+name in the namespace linked to the ensemble. If this option is
+empty, the subcommands of the namespace will either be the keys of the
+dictionary listed in the \fB\-map\fR option or the exported commands
+of the linked namespace at the time of the invocation of the ensemble
+command.
+.TP
+\fB\-unknown\fR
+When non-empty, this option provides a partial command (to which all
+the words that are arguments to the ensemble command, including the
+fully-qualified name of the ensemble, are appended) to handle the case
+where an ensemble subcommand is not recognized and would otherwise
+generate an error. When empty (the default) an error (in the style of
+\fBTcl_GetIndexFromObj\fR) is generated whenever the ensemble is
+unable to determine how to implement a particular subcommand. See
+\fBUNKNOWN HANDLER BEHAVIOUR\fR for more details.
+.PP
+The following extra option is allowed by \fBnamespace ensemble
+create\fR:
+.TP
+\fB\-command\fR
+This write-only option allows the name of the ensemble created by
+\fBnamespace ensemble create\fR to be anything in any existing
+namespace. The default value for this option is the fully-qualified
+name of the namespace in which the \fBnamespace ensemble create\fR
+command is invoked.
+.PP
+The following extra option is allowed by \fBnamespace ensemble
+configure\fR:
+.TP
+\fB\-namespace\fR
+This read-only option allows the retrieval of the fully-qualified name
+of the namespace which the ensemble was created within.
+.SS "UNKNOWN HANDLER BEHAVIOUR"
+.PP
+If an unknown handler is specified for an ensemble, that handler is
+called when the ensemble command would otherwise return an error due
+to it being unable to decide which subcommand to invoke. The exact
+conditions under which that occurs are controlled by the
+\fB\-subcommands\fR, \fB\-map\fR and \fB\-prefixes\fR options as
+described above.
+.PP
+To execute the unknown handler, the ensemble mechanism takes the
+specified \fB\-unknown\fR option and appends each argument of the
+attempted ensemble command invocation (including the ensemble command
+itself, expressed as a fully qualified name). It invokes the resulting
+command in the scope of the attempted call. If the execution of the
+unknown handler terminates normally, the ensemble engine reparses the
+subcommand (as described below) and tries to dispatch it again, which
+is ideal for when the ensemble's configuration has been updated by the
+unknown subcommand handler. Any other kind of termination of the
+unknown handler is treated as an error.
+.PP
+The result of the unknown handler is expected to be a list (it is an
+error if it is not). If the list is an empty list, the ensemble
+command attempts to look up the original subcommand again and, if it
+is not found this time, an error will be generated just as if the
+\fB\-unknown\fR handler was not there (i.e. for any particular
+invocation of an ensemble, its unknown handler will be called at most
+once.) This makes it easy for the unknown handler to update the
+ensemble or its backing namespace so as to provide an implementation
+of the desired subcommand and reparse.
+.PP
+When the result is a non-empty list, the words of that list are used
+to replace the ensemble command and subcommand, just as if they had
+been looked up in the \fB\-map\fR. It is up to the unknown handler to
+supply all namespace qualifiers if the implementing subcommand is not
+in the namespace of the caller of the ensemble command. Also note that
+when ensemble commands are chained (e.g. if you make one of the
+commands that implement an ensemble subcommand into an ensemble, in a
+manner similar to the \fBtext\fR widget's tag and mark subcommands) then the
+rewrite happens in the context of the caller of the outermost
+ensemble. That is to say that ensembles do not in themselves place any
+namespace contexts on the Tcl call stack.
+.PP
+Where an empty \fB\-unknown\fR handler is given (the default), the
+ensemble command will generate an error message based on the list of
+commands that the ensemble has defined (formatted similarly to the
+error message from \fBTcl_GetIndexFromObj\fR). This is the error that
+will be thrown when the subcommand is still not recognized during
+reparsing. It is also an error for an \fB\-unknown\fR handler to
+delete its namespace.
+.VE 8.5
.SH EXAMPLES
Create a namespace containing a variable and an exported command:
.CS
@@ -599,20 +828,38 @@ Create a namespace containing a variable and an exported command:
Call the command defined in the previous example in various ways.
.CS
# Direct call
-foo::grill
+::foo::grill
+
+# Use the command resolution path to find the name
+\fBnamespace eval\fR boo {
+ \fBnamespace path\fR ::foo
+ grill
+}
# Import into current namespace, then call local alias
-namespace import foo::grill
+\fBnamespace import\fR foo::grill
grill
+
+# Create two ensembles, one with the default name and one with a
+# specified name. Then call through the ensembles.
+\fBnamespace eval\fR foo {
+ \fBnamespace ensemble\fR create
+ \fBnamespace ensemble\fR create -command ::foobar
+}
+foo grill
+foobar grill
.CE
.PP
Look up where the command imported in the previous example came from:
.CS
puts "grill came from [\fBnamespace origin\fR grill]"
.CE
-
+.PP
+Remove all imported commands from the current namespace:
+.CS
+namespace forget {*}[namespace import]
+.CE
.SH "SEE ALSO"
-variable(n)
-
+interp(n), upvar(n), variable(n)
.SH KEYWORDS
-exported, internal, variable
+command, ensemble, exported, internal, variable
diff --git a/doc/open.n b/doc/open.n
index 1557ca9..88283bb 100644
--- a/doc/open.n
+++ b/doc/open.n
@@ -19,7 +19,6 @@ open \- Open a file-based or command pipeline channel
.br
\fBopen \fIfileName access permissions\fR
.BE
-
.SH DESCRIPTION
.PP
This command opens a file, serial port, or command pipeline and returns a
@@ -43,22 +42,30 @@ Open the file for both reading and writing; the file must
already exist.
.TP 15
\fBw\fR
-Open the file for writing only. Truncate it if it exists. If it doesn't
+Open the file for writing only. Truncate it if it exists. If it does not
exist, create a new file.
.TP 15
\fBw+\fR
Open the file for reading and writing. Truncate it if it exists.
-If it doesn't exist, create a new file.
+If it does not exist, create a new file.
.TP 15
\fBa\fR
-Open the file for writing only. If the file doesn't exist,
+Open the file for writing only. If the file does not exist,
create a new empty file.
Set the file pointer to the end of the file prior to each write.
.TP 15
\fBa+\fR
-Open the file for reading and writing. If the file doesn't exist,
+Open the file for reading and writing. If the file does not exist,
create a new empty file.
Set the initial access position to the end of the file.
+.VS 8.5
+.PP
+All of the legal \fIaccess\fR values above may have the character
+\fBb\fR added as the second or third character in the value to
+indicate that the opened channel should be configured with the
+\fB\-translation binary\fR option, making the channel suitable for
+reading or writing of binary data.
+.VE 8.5
.PP
In the second form, \fIaccess\fR consists of a list of any of the
following flags, all of which have the standard POSIX meanings.
@@ -75,9 +82,14 @@ Open the file for both reading and writing.
.TP 15
\fBAPPEND\fR
Set the file pointer to the end of the file prior to each write.
+.VS 8.5
+.TP 15
+\fBBINARY\fR
+Configure the opened channel with the \fB\-translation binary\fR option.
+.VE 8.5
.TP 15
\fBCREAT\fR
-Create the file if it doesn't already exist (without this flag it
+Create the file if it does not already exist (without this flag it
is an error for the file not to exist).
.TP 15
\fBEXCL\fR
@@ -104,18 +116,11 @@ If a new file is created as part of opening it, \fIpermissions\fR
(an integer) is used to set the permissions for the new file in
conjunction with the process's file mode creation mask.
\fIPermissions\fR defaults to 0666.
-.PP
-Note that if you are going to be reading or writing binary data from
-the channel created by this command, you should use the
-\fBfconfigure\fR command to change the \fB-translation\fR option of
-the channel to \fBbinary\fR before transferring any binary data. This
-is in contrast to the ``b'' character passed as part of the equivalent
-of the \fIaccess\fR parameter to some versions of the C library
-\fIfopen()\fR function.
-
.SH "COMMAND PIPELINES"
.PP
-If the first character of \fIfileName\fR is ``|'' then the
+If the first character of \fIfileName\fR is
+.QW |
+then the
remaining characters of \fIfileName\fR are treated as a list of arguments
that describe a command pipeline to invoke, in the same style as the
arguments for \fBexec\fR.
@@ -140,7 +145,6 @@ returned (a silent \fBclose\fR with -blocking 0).
It is often useful to use the \fBfileevent\fR command with pipelines
so other processing may happen at the same time as running the command
in the background.
-.VS 8.4
.SH "SERIAL COMMUNICATIONS"
.PP
If \fIfileName\fR refers to a serial port, then the specified serial port
@@ -156,8 +160,14 @@ This option is a set of 4 comma-separated values: the baud rate, parity,
number of data bits, and number of stop bits for this serial port. The
\fIbaud\fR rate is a simple integer that specifies the connection speed.
\fIParity\fR is one of the following letters: \fBn\fR, \fBo\fR, \fBe\fR,
-\fBm\fR, \fBs\fR; respectively signifying the parity options of ``none'',
-``odd'', ``even'', ``mark'', or ``space''. \fIData\fR is the number of
+\fBm\fR, \fBs\fR; respectively signifying the parity options of
+.QW none ,
+.QW odd ,
+.QW even ,
+.QW mark ,
+or
+.QW space .
+\fIData\fR is the number of
data bits and should be an integer from 5 to 8, while \fIstop\fR is the
number of stop bits and should be the integer 1 or 2.
.TP
@@ -165,19 +175,21 @@ number of stop bits and should be the integer 1 or 2.
(Windows and Unix). This option is used to setup automatic handshake
control. Note that not all handshake types maybe supported by your operating
system. The \fItype\fR parameter is case-independent.
-.sp
+.RS
+.PP
If \fItype\fR is \fBnone\fR then any handshake is switched off.
\fBrtscts\fR activates hardware handshake. Hardware handshake signals
are described below.
For software handshake \fBxonxoff\fR the handshake characters can be redefined
-with \fB-xchar\fR.
+with \fB\-xchar\fR.
An additional hardware handshake \fBdtrdsr\fR is available only under Windows.
There is no default handshake configuration, the initial value depends
on your operating system settings.
-The \fB-handshake\fR option cannot be queried.
+The \fB\-handshake\fR option cannot be queried.
+.RE
.TP
\fB\-queue\fR
-(Windows and Unix). The \fB-queue\fR option can only be queried.
+(Windows and Unix). The \fB\-queue\fR option can only be queried.
It returns a list of two integers representing the current number
of bytes in the input and output queue respectively.
.TP
@@ -186,7 +198,7 @@ of bytes in the input and output queue respectively.
read operations. It specifies the maximum interval between the
reception of two bytes in milliseconds.
For Unix systems the granularity is 100 milliseconds.
-The \fB-timeout\fR option does not affect write operations or
+The \fB\-timeout\fR option does not affect write operations or
nonblocking reads.
This option cannot be queried.
.TP
@@ -197,13 +209,13 @@ The \fIsignal\fR names are case-independent.
\fB{RTS 1 DTR 0}\fR sets the RTS output to high and the DTR output to low.
The BREAK condition (see below) is enabled and disabled with \fB{BREAK 1}\fR and
\fB{BREAK 0}\fR respectively.
-It's not a good idea to change the \fBRTS\fR (or \fBDTR\fR) signal
+It is not a good idea to change the \fBRTS\fR (or \fBDTR\fR) signal
with active hardware handshake \fBrtscts\fR (or \fBdtrdsr\fR).
The result is unpredictable.
-The \fB-ttycontrol\fR option cannot be queried.
+The \fB\-ttycontrol\fR option cannot be queried.
.TP
\fB\-ttystatus\fR
-(Windows and Unix). The \fB-ttystatus\fR option can only be
+(Windows and Unix). The \fB\-ttystatus\fR option can only be
queried. It returns the current modem status and handshake input signals
(see below).
The result is a list of signal,value pairs with a fixed order,
@@ -239,7 +251,6 @@ In case of a serial communication error, \fBread\fR or \fBputs\fR
returns a general Tcl file I/O error.
\fBfconfigure -lasterror\fR can be called to get a list of error details.
See below for an explanation of the various error codes.
-
.SH "SERIAL PORT SIGNALS"
.PP
RS-232 is the most commonly used standard electrical interface for serial
@@ -250,7 +261,6 @@ lines and handshaking. Here we are using the terms \fIworkstation\fR for
your computer and \fImodem\fR for the external device, because some signal
names (DCD, RI) come from modems. Of course your external device may use
these signal lines for other purposes.
-
.IP \fBTXD(output)\fR
\fBTransmitted Data:\fR Outgoing serial data.
.IP \fBRXD(input)\fR
@@ -270,8 +280,9 @@ serial port is opened.
\fBData Set Ready:\fR The complement to DTR. Tells the workstation that the
modem is ready to establish a link.
.IP \fBDCD(input)\fR
-\fBData Carrier Detect:\fR This line becomes active when a modem detects
-a "Carrier" signal.
+\fBData Carrier Detect:\fR This line becomes active when a modem detects a
+.QW Carrier
+signal.
.IP \fBRI(input)\fR
\fBRing Indicator:\fR Goes active when the modem detects an incoming call.
.IP \fBBREAK\fR
@@ -281,17 +292,15 @@ milliseconds. Normally a receive or transmit data signal stays at the mark
(on=1) voltage until the next character is transferred. A BREAK is sometimes
used to reset the communications line or change the operating mode of
communications hardware.
-
.SH "ERROR CODES (Windows only)"
.PP
A lot of different errors may occur during serial read operations or during
event polling in background. The external device may have been switched
off, the data lines may be noisy, system buffers may overrun or your mode
-settings may be wrong. That's why a reliable software should always
+settings may be wrong. That is why a reliable software should always
\fBcatch\fR serial read operations. In cases of an error Tcl returns a
general file I/O error. Then \fBfconfigure -lasterror\fR may help to
locate the problem. The following error codes may be returned.
-
.TP 10
\fBRXOVER\fR
Windows input buffer overrun. The data comes faster than your scripts reads
@@ -320,8 +329,6 @@ may cause this error.
.TP 10
\fBBREAK\fR
A BREAK condition has been detected by your UART (see above).
-.VE
-
.SH "PORTABILITY ISSUES"
.TP
\fBWindows \fR(all versions)
@@ -356,7 +363,8 @@ standard input from a pipe and send standard output to a pipe run
synchronously. Command pipelines that do not execute 16-bit DOS
applications run asynchronously and can be opened for both reading and
writing.
-.sp
+.RS
+.PP
When running Tcl interactively, there may be some strange interactions
between the real console, if one is present, and a command pipeline that uses
standard input or output. If a command pipeline is opened for reading from
@@ -369,7 +377,7 @@ console at the same time. If the command pipeline is started from a script,
so that Tcl is not accessing the console, or if the command pipeline does
not use standard input or output, but is redirected from or to a file, then
the above problems do not occur.
-.sp
+.PP
Whether or not Tcl is running interactively, if a command pipeline is opened
for reading from a 16-bit DOS application, the call to \fBopen\fR will not
return until end-of-file has been received from the command pipeline's
@@ -377,22 +385,16 @@ standard output. If a command pipeline is opened for writing to a 16-bit DOS
application, no data will be sent to the command pipeline's standard output
until the pipe is actually closed. This problem occurs because 16-bit DOS
applications are run synchronously, as described above.
-.TP
-\fBMacintosh\fR
-Opening a serial port is not currently implemented under Macintosh.
-.sp
-Opening a command pipeline is not supported under Macintosh, since
-applications do not support the concept of standard input or output.
+.RE
.TP
\fBUnix\fR\0\0\0\0\0\0\0
Valid values for \fIfileName\fR to open a serial port are generally of the
form \fB/dev/tty\fIX\fR, where \fIX\fR is \fBa\fR or \fBb\fR, but the name
of any pseudo-file that maps to a serial port may be used.
-.VS 8.4
Advanced configuration options are only supported for serial ports
when Tcl is built to use the POSIX serial interface.
-.VE 8.4
-.sp
+.RS
+.PP
When running Tcl interactively, there may be some strange interactions
between the console, if one is present, and a command pipeline that uses
standard input. If a command pipeline is opened for reading, some
@@ -402,9 +404,10 @@ both Tcl and the child application are competing for the console at the
same time. If the command pipeline is started from a script, so that Tcl is
not accessing the console, or if the command pipeline does not use standard
input, but is redirected from a file, then the above problem does not occur.
-.LP
-See the PORTABILITY ISSUES section of the \fBexec\fR command for additional
-information not specific to command pipelines about executing
+.RE
+.PP
+See the \fBPORTABILITY ISSUES\fR section of the \fBexec\fR command for
+additional information not specific to command pipelines about executing
applications on the various platforms
.SH "EXAMPLE"
Open a command pipeline and catch any errors:
@@ -415,11 +418,9 @@ if {[catch {close $fl} err]} {
puts "ls command failed: $err"
}
.CE
-
.SH "SEE ALSO"
file(n), close(n), filename(n), fconfigure(n), gets(n), read(n),
puts(n), exec(n), pid(n), fopen(3)
-
.SH KEYWORDS
access mode, append, create, file, non-blocking, open, permissions,
pipeline, process, serial
diff --git a/doc/package.n b/doc/package.n
index 60be18b..d4fe657 100644
--- a/doc/package.n
+++ b/doc/package.n
@@ -15,13 +15,16 @@ package \- Facilities for package loading and version control
\fBpackage forget ?\fIpackage package ...\fR?
\fBpackage ifneeded \fIpackage version\fR ?\fIscript\fR?
\fBpackage names\fR
-\fBpackage present \fR?\fB\-exact\fR? \fIpackage \fR?\fIversion\fR?
+\fBpackage present \fIpackage \fR?\fIrequirement...\fR?
+\fBpackage present \-exact \fIpackage version\fR
\fBpackage provide \fIpackage \fR?\fIversion\fR?
-\fBpackage require \fR?\fB\-exact\fR? \fIpackage \fR?\fIversion\fR?
+\fBpackage require \fIpackage \fR?\fIrequirement...\fR?
+\fBpackage require \-exact \fIpackage version\fR
\fBpackage unknown \fR?\fIcommand\fR?
\fBpackage vcompare \fIversion1 version2\fR
\fBpackage versions \fIpackage\fR
-\fBpackage vsatisfies \fIversion1 version2\fR
+\fBpackage vsatisfies \fIversion requirement...\fR
+\fBpackage prefer \fR?\fBlatest\fR|\fBstable\fR?
.fi
.BE
@@ -74,7 +77,8 @@ interpreter for which a version has been provided (via
script is available.
The order of elements in the list is arbitrary.
.TP
-\fBpackage present \fR?\fB\-exact\fR? \fIpackage \fR?\fIversion\fR?
+\fBpackage present\fR ?\fB\-exact\fR? \fIpackage\fR ?\fIrequirement...\fR?
+.
This command is equivalent to \fBpackage require\fR except that it
does not try and load the package if it is not already loaded.
.TP
@@ -90,25 +94,34 @@ returns the version number that is currently provided, or an
empty string if no \fBpackage provide\fR command has been
invoked for \fIpackage\fR in this interpreter.
.TP
-\fBpackage require \fR?\fB\-exact\fR? \fIpackage \fR?\fIversion\fR?
+\fBpackage require\fR \fIpackage \fR?\fIrequirement...\fR?
This command is typically invoked by Tcl code that wishes to use
a particular version of a particular package. The arguments
indicate which package is wanted, and the command ensures that
a suitable version of the package is loaded into the interpreter.
If the command succeeds, it returns the version number that is
loaded; otherwise it generates an error.
-If both the \fB\-exact\fR
-switch and the \fIversion\fR argument are specified then only the
-given version is acceptable. If \fB\-exact\fR is omitted but
-\fIversion\fR is specified, then versions later than \fIversion\fR
-are also acceptable as long as they have the same major version
-number as \fIversion\fR.
-If both \fB\-exact\fR and \fIversion\fR are omitted then any
-version whatsoever is acceptable.
+.RS
+.PP
+A suitable version of the package is any version which satisfies at
+least one of the requirements, per the rules of \fBpackage
+vsatisfies\fR. If multiple versions are suitable the implementation
+with the highest version is chosen. This last part is additionally
+influenced by the selection mode set with \fBpackage prefer\fR.
+.PP
+In the
+.QW stable
+selection mode the command will select the highest
+stable version satisfying the requirements, if any. If no stable
+version satisfies the requirements, the highest unstable version
+satisfying the requirements will be selected. In the
+.QW latest
+selection mode the command will accept the highest version satisfying
+all the requirements, regardless of its stableness.
+.PP
If a version of \fIpackage\fR has already been provided (by invoking
the \fBpackage provide\fR command), then its version number must
-satisfy the criteria given by \fB\-exact\fR and \fIversion\fR and
-the command returns immediately.
+satisfy the \fIrequirement\fRs and the command returns immediately.
Otherwise, the command searches the database of information provided by
previous \fBpackage ifneeded\fR commands to see if an acceptable
version of the package is available.
@@ -124,20 +137,28 @@ it completes, Tcl checks again to see if the package is now provided
or if there is a \fBpackage ifneeded\fR script for it.
If all of these steps fail to provide an acceptable version of the
package, then the command returns an error.
+.RE
+.TP
+\fBpackage require \-exact \fIpackage version\fR
+This form of the command is used when only the given \fIversion\fR
+of \fIpackage\fR is acceptable to the caller. This command is
+equivalent to \fBpackage require \fIpackage version\fR-\fIversion\fR.
.TP
\fBpackage unknown \fR?\fIcommand\fR?
-This command supplies a ``last resort'' command to invoke during
+This command supplies a
+.QW "last resort"
+command to invoke during
\fBpackage require\fR if no suitable version of a package can be found
in the \fBpackage ifneeded\fR database.
If the \fIcommand\fR argument is supplied, it contains the first part
of a command; when the command is invoked during a \fBpackage require\fR
-command, Tcl appends two additional arguments giving the desired package
-name and version.
+command, Tcl appends one or more additional arguments giving the desired
+package name and requirements.
For example, if \fIcommand\fR is \fBfoo bar\fR and later the command
\fBpackage require test 2.4\fR is invoked, then Tcl will execute
the command \fBfoo bar test 2.4\fR to load the package.
-If no version number is supplied to the \fBpackage require\fR command,
-then the version argument for the invoked command will be an empty string.
+If no requirements are supplied to the \fBpackage require\fR command,
+then only the name will be added to invoked command.
If the \fBpackage unknown\fR command is invoked without a \fIcommand\fR
argument, then the current \fBpackage unknown\fR script is returned,
or an empty string if there is none.
@@ -154,11 +175,107 @@ Returns a list of all the version numbers of \fIpackage\fR
for which information has been provided by \fBpackage ifneeded\fR
commands.
.TP
-\fBpackage vsatisfies \fIversion1 version2\fR
-Returns 1 if scripts written for \fIversion2\fR will work unchanged
-with \fIversion1\fR (i.e. \fIversion1\fR is equal to or greater
-than \fIversion2\fR and they both have the same major version
-number), 0 otherwise.
+\fBpackage vsatisfies \fIversion requirement...\fR
+Returns 1 if the \fIversion\fR satisfies at least one of the given
+requirements, and 0 otherwise. Each \fIrequirement\fR is allowed to
+have any of the forms:
+.RS
+.TP
+min
+This form is called
+.QW min-bounded .
+.TP
+min-
+This form is called
+.QW min-unbound .
+.TP
+min-max
+This form is called
+.QW bounded .
+.RE
+.RS
+.PP
+where
+.QW min
+and
+.QW max
+are valid version numbers. The legacy syntax is
+a special case of the extended syntax, keeping backward
+compatibility. Regarding satisfaction the rules are:
+.RE
+.RS
+.IP [1]
+The \fIversion\fR has to pass at least one of the listed
+\fIrequirement\fRs to be satisfactory.
+.IP [2]
+A version satisfies a
+.QW bounded
+requirement when
+.RS
+.IP [a]
+For \fImin\fR equal to the \fImax\fR if, and only if the \fIversion\fR
+is equal to the \fImin\fR.
+.IP [b]
+Otherwise if, and only if the \fIversion\fR is greater than or equal
+to the \fImin\fR, and less than the \fImax\fR, where both \fImin\fR
+and \fImax\fR have been padded internally with
+.QW a0 .
+Note that while the comparison to \fImin\fR is inclusive, the
+comparison to \fImax\fR is exclusive.
+.RE
+.IP [3]
+A
+.QW min-bounded
+requirement is a
+.QW bounded
+requirement in disguise,
+with the \fImax\fR part implicitly specified as the next higher major
+version number of the \fImin\fR part. A version satisfies it per the
+rules above.
+.IP [4]
+A \fIversion\fR satisfies a
+.QW min-unbound
+requirement if, and only if it is greater than or equal to the
+\fImin\fR, where the \fImin\fR has been padded internally with
+.QW a0 .
+There is no constraint to a maximum.
+.RE
+.TP
+\fBpackage prefer \fR?\fBlatest\fR|\fBstable\fR?
+With no arguments, the commands returns either
+.QW latest
+or
+.QW stable ,
+whichever describes the current mode of selection logic used by
+\fBpackage require\fR.
+.RS
+.PP
+When passed the argument
+.QW latest ,
+it sets the selection logic mode to
+.QW latest .
+.PP
+When passed the argument
+.QW stable ,
+if the mode is already
+.QW stable ,
+that value is kept. If the mode is already
+.QW latest ,
+then the attempt to set it back to
+.QW stable
+is ineffective and the mode value remains
+.QW latest .
+.PP
+When passed any other value as an argument, raise an invalid argument
+error.
+.PP
+When an interpreter is created, its initial selection mode value is set to
+.QW stable
+unless the environment variable \fBTCL_PKG_PREFER_LATEST\fR
+is set. If that environment variable is defined (with any value) then
+the initial (and permanent) selection mode value is set to
+.QW latest .
+.RE
.SH "VERSION NUMBERS"
.PP
Version numbers consist of one or more decimal numbers separated
@@ -170,6 +287,30 @@ For example, version 2.1 is later than 1.3 and version
3.4.6 is later than 3.3.5.
Missing fields are equivalent to zeroes: version 1.3 is the
same as version 1.3.0 and 1.3.0.0, so it is earlier than 1.3.1 or 1.3.0.2.
+In addition, the letters
+.QW a
+(alpha) and/or
+.QW b
+(beta) may appear
+exactly once to replace a dot for separation. These letters
+semantically add a negative specifier into the version, where
+.QW a
+is \-2, and
+.QW b
+is \-1. Each may be specified only once, and
+.QW a
+or
+.QW b
+are mutually exclusive in a specifier. Thus 1.3a1 becomes (semantically)
+1.3.\-2.1, 1.3b1 is 1.3.\-1.1. Negative numbers are not directly allowed
+in version specifiers.
+A version number not containing the letters
+.QW a
+or
+.QW b
+as specified
+above is called a \fBstable\fR version, whereas presence of the letters
+causes the version to be called is \fBunstable\fR.
A later version number is assumed to be upwards compatible with
an earlier version number as long as both versions have the same
major version number.
@@ -183,7 +324,7 @@ to work unmodified with either version 1.7.3 or version 3.1.
The recommended way to use packages in Tcl is to invoke \fBpackage require\fR
and \fBpackage provide\fR commands in scripts, and use the procedure
\fBpkg_mkIndex\fR to create package index files.
-Once you've done this, packages will be loaded automatically
+Once you have done this, packages will be loaded automatically
in response to \fBpackage require\fR commands.
See the documentation for \fBpkg_mkIndex\fR for details.
.SH EXAMPLES
@@ -205,9 +346,7 @@ if {[catch {\fBpackage require\fR Snack}]} {
# We have the package, configure the app to use it
}
.CE
-
.SH "SEE ALSO"
msgcat(n), packagens(n), pkgMkIndex(n)
-
.SH KEYWORDS
package, version
diff --git a/doc/packagens.n b/doc/packagens.n
index a0386f2..1220b20 100644
--- a/doc/packagens.n
+++ b/doc/packagens.n
@@ -7,8 +7,7 @@
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
-pkg::create \- Construct an appropriate \fBpackage ifneeded\fR
-command for a given package specification
+pkg::create \- Construct an appropriate 'package ifneeded' command for a given package specification
.SH SYNOPSIS
\fB::pkg::create \fI\-name packageName\fR \fI\-version packageVersion\fR ?\fI\-load filespec\fR? ... ?\fI\-source filespec\fR? ...
.BE
@@ -45,9 +44,7 @@ specifies a Tcl library that must be loaded with the
specified.
.PP
At least one \fB\-load\fR or \fB\-source\fR parameter must be given.
-
.SH "SEE ALSO"
package(n)
-
.SH KEYWORDS
auto-load, index, package, version
diff --git a/doc/pid.n b/doc/pid.n
index 1001ddc..97a42a7 100644
--- a/doc/pid.n
+++ b/doc/pid.n
@@ -23,7 +23,7 @@ In this case the \fBpid\fR command will return a list whose elements
are the process identifiers of all the processes in the pipeline,
in order.
The list will be empty if \fIfileId\fR refers to an open file
-that isn't a process pipeline.
+that is not a process pipeline.
If no \fIfileId\fR argument is given then \fBpid\fR returns the process
identifier of the current process.
All process identifiers are returned as decimal strings.
diff --git a/doc/pkgMkIndex.n b/doc/pkgMkIndex.n
index d0ea771..5895407 100644
--- a/doc/pkgMkIndex.n
+++ b/doc/pkgMkIndex.n
@@ -12,12 +12,9 @@
pkg_mkIndex \- Build an index for automatic loading of packages
.SH SYNOPSIS
.nf
-.VS 8.3.0
\fBpkg_mkIndex ?\fI\-direct\fR? ?\fI\-lazy\fR? ?\fI\-load pkgPat\fR? ?\fI\-verbose\fR? \fIdir\fR ?\fIpattern pattern ...\fR?
-.VE
.fi
.BE
-
.SH DESCRIPTION
.PP
\fBPkg_mkIndex\fR is a utility procedure that is part of the standard
@@ -39,10 +36,9 @@ Create the index by invoking \fBpkg_mkIndex\fR.
The \fIdir\fR argument gives the name of a directory and each
\fIpattern\fR argument is a \fBglob\fR-style pattern that selects
script or binary files in \fIdir\fR.
-.VS 8.0.3
The default pattern is \fB*.tcl\fR and \fB*.[info sharedlibextension]\fR.
-.VE
-.br
+.RS
+.PP
\fBPkg_mkIndex\fR will create a file \fBpkgIndex.tcl\fR in \fIdir\fR
with package information about all the files given by the \fIpattern\fR
arguments.
@@ -53,10 +49,10 @@ and new commands appear (this is why it is essential to have
in the files, as described above).
If you have a package split among scripts and binary files,
or if you have dependencies among files,
-you may have to use the \fB\-load\fP option
+you may have to use the \fB\-load\fR option
or adjust the order in which \fBpkg_mkIndex\fR processes
-the files. See COMPLEX CASES below.
-
+the files. See \fBCOMPLEX CASES\fR below.
+.RE
.IP [3]
Install the package as a subdirectory of one of the directories given by
the \fBtcl_pkgPath\fR variable. If \fB$tcl_pkgPath\fR contains more
@@ -70,7 +66,8 @@ the package's script and/or binary files as well as the \fBpkgIndex.tcl\fR
file. As long as the package is installed as a subdirectory of a
directory in \fB$tcl_pkgPath\fR it will automatically be found during
\fBpackage require\fR commands.
-.br
+.RS
+.PP
If you install the package anywhere else, then you must ensure that
the directory containing the package is in the \fBauto_path\fR global variable
or an immediate subdirectory of one of the directories in \fBauto_path\fR.
@@ -83,6 +80,7 @@ You can add a directory to \fBauto_path\fR explicitly in your
application, or you can add the directory to your \fBTCLLIBPATH\fR
environment variable: if this environment variable is present,
Tcl initializes \fBauto_path\fR from it during application startup.
+.RE
.IP [4]
Once the above steps have been taken, all you need to do to use a
package is to invoke \fBpackage require\fR.
@@ -96,7 +94,6 @@ in \fBauto_path\fR, but only one will actually be loaded in a given
interpreter, based on the first call to \fBpackage require\fR.
Different versions of a package may be loaded in different
interpreters.
-
.SH OPTIONS
The optional switches are:
.TP 15
@@ -107,22 +104,22 @@ upon \fBpackage require\fR. This is the default.
\fB\-lazy\fR
The generated index will manage to delay loading the package until the
use of one of the commands provided by the package, instead of loading
-it immediately upon \fBpackage require\fR.
+it immediately upon \fBpackage require\fR. This is not compatible with
+the use of \fIauto_reset\fR, and therefore its use is discouraged.
.TP 15
\fB\-load \fIpkgPat\fR
The index process will pre-load any packages that exist in the
-current interpreter and match \fIpkgPat\fP into the slave interpreter used to
+current interpreter and match \fIpkgPat\fR into the slave interpreter used to
generate the index. The pattern match uses string match rules, but without
making case distinctions.
See COMPLEX CASES below.
.TP 15
\fB\-verbose\fR
Generate output during the indexing process. Output is via
-the \fBtclLog\fP procedure, which by default prints to stderr.
+the \fBtclLog\fR procedure, which by default prints to stderr.
.TP 15
\fB\-\-\fR
-End of the flags, in case \fIdir\fP begins with a dash.
-
+End of the flags, in case \fIdir\fR begins with a dash.
.SH "PACKAGES AND THE AUTO-LOADER"
.PP
The package management facilities overlap somewhat with the auto-loader,
@@ -142,7 +139,6 @@ If you use \fBpkg_mkIndex\fR to index a package, its commands cannot
be invoked until \fBpackage require\fR has been used to select a
version; in contrast, packages indexed with \fBauto_mkindex\fR
can be used immediately since there is no version control.
-
.SH "HOW IT WORKS"
.PP
\fBPkg_mkIndex\fR depends on the \fBpackage unknown\fR command,
@@ -157,18 +153,14 @@ commands for each version of each available package; these commands
invoke \fBpackage provide\fR commands to announce the
availability of the package, and they setup auto-loader
information to load the files of the package.
-.VS 8.3
If the \fI\-lazy\fR flag was provided when the \fBpkgIndex.tcl\fR
was generated,
-.VE
-a given file of a given version of a given package isn't
+a given file of a given version of a given package is not
actually loaded until the first time one of its commands
is invoked.
Thus, after invoking \fBpackage require\fR you may
not see the package's commands in the interpreter, but you will be able
to invoke the commands and they will be auto-loaded.
-
-.VS 8.3
.SH "DIRECT LOADING"
.PP
Some packages, for instance packages which use namespaces and export
@@ -177,8 +169,6 @@ that their package files be loaded immediately upon \fBpackage require\fR
instead of delaying the actual loading to the first use of one of the
package's command. This is the default mode when generating the package
index. It can be overridden by specifying the \fI\-lazy\fR argument.
-.VE
-
.SH "COMPLEX CASES"
Most complex cases of dependencies among scripts
and binary files, and packages being split among scripts and
@@ -193,28 +183,28 @@ with some glob patterns.
.PP
In general, it is OK for scripts to have dependencies on other
packages.
-If scripts contain \fBpackage require\fP commands, these are
+If scripts contain \fBpackage require\fR commands, these are
stubbed out in the interpreter used to process the scripts,
so these do not cause problems.
If scripts call into other packages in global code,
-these calls are handled by a stub \fBunknown\fP command.
+these calls are handled by a stub \fBunknown\fR command.
However, if scripts make variable references to other package's
variables in global code, these will cause errors. That is
also bad coding style.
.PP
If binary files have dependencies on other packages, things
can become tricky because it is not possible to stub out
-C-level APIs such as \fBTcl_PkgRequire\fP API
+C-level APIs such as \fBTcl_PkgRequire\fR API
when loading a binary file.
For example, suppose the BLT package requires Tk, and expresses
-this with a call to \fBTcl_PkgRequire\fP in its \fBBlt_Init\fP routine.
+this with a call to \fBTcl_PkgRequire\fR in its \fBBlt_Init\fR routine.
To support this, you must run \fBpkg_mkIndex\fR in an interpreter that
has Tk loaded. You can achieve this with the
\fB\-load \fIpkgPat\fR option. If you specify this option,
\fBpkg_mkIndex\fR will load any packages listed by
-\fBinfo loaded\fP and that match \fIpkgPat\fP
+\fBinfo loaded\fR and that match \fIpkgPat\fR
into the interpreter used to process files.
-In most cases this will satisfy the \fBTcl_PkgRequire\fP calls
+In most cases this will satisfy the \fBTcl_PkgRequire\fR calls
made by binary files.
.PP
If you are indexing two binary files and one depends on the other,
@@ -224,19 +214,17 @@ and then the package it provides
will be available when the second file is processed.
You may also need to load the first package into the
temporary interpreter used to create the index by using
-the \fB\-load\fP flag;
-it won't hurt to specify package patterns that are not yet loaded.
+the \fB\-load\fR flag;
+it will not hurt to specify package patterns that are not yet loaded.
.PP
If you have a package that is split across scripts and a binary file,
-then you should avoid the \fB\-load\fP flag. The problem is that
+then you should avoid the \fB\-load\fR flag. The problem is that
if you load a package before computing the index it masks any
other files that provide part of the same package.
-If you must use \fB\-load\fP,
+If you must use \fB\-load\fR,
then you must specify the scripts first; otherwise the package loaded from
the binary file may mask the package defined by the scripts.
-
.SH "SEE ALSO"
package(n)
-
.SH KEYWORDS
auto-load, index, package, version
diff --git a/doc/platform.n b/doc/platform.n
new file mode 100644
index 0000000..053448d
--- /dev/null
+++ b/doc/platform.n
@@ -0,0 +1,66 @@
+'\"
+'\" Copyright (c) 2006 ActiveState Software Inc
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.so man.macros
+.TH "platform" n 1.0.4 platform "Tcl Bundled Packages"
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+platform \- System identification support code and utilities
+.SH SYNOPSIS
+.nf
+\fBpackage require platform ?1.0.4?\fR
+.sp
+\fBplatform::generic\fR
+\fBplatform::identify\fR
+\fBplatform::patterns \fIidentifier\fR
+.fi
+.BE
+.SH DESCRIPTION
+.PP
+The \fBplatform\fR package provides several utility commands useful
+for the identification of the architecture of a machine running Tcl.
+.PP
+Whilst Tcl provides the \fBtcl_platform\fR array for identifying the
+current architecture (in particular, the platform and machine
+elements) this is not always sufficient. This is because (on Unix
+machines) \fBtcl_platform\fR reflects the values returned by the
+\fBuname\fR command and these are not standardized across platforms and
+architectures. In addition, on at least one platform (AIX) the
+\fBtcl_platform(machine)\fR contains the CPU serial number.
+.PP
+Consequently, individual applications need to manipulate the values in
+\fBtcl_platform\fR (along with the output of system specific
+utilities) - which is both inconvenient for developers, and introduces
+the potential for inconsistencies in identifying architectures and in
+naming conventions.
+.PP
+The \fBplatform\fR package prevents such fragmentation - i.e., it
+establishes a standard naming convention for architectures running Tcl
+and makes it more convenient for developers to identify the current
+architecture a Tcl program is running on.
+.SH COMMANDS
+.TP
+\fBplatform::identify\fR
+This command returns an identifier describing the platform the Tcl
+core is running on. The returned identifier has the general format
+\fIOS\fR-\fICPU\fR. The \fIOS\fR part of the identifier may contain
+details like kernel version, libc version, etc., and this information
+may contain dashes as well. The \fICPU\fR part will not contain
+dashes, making the preceding dash the last dash in the result.
+.TP
+\fBplatform::generic\fR
+This command returns a simplified identifier describing the platform
+the Tcl core is running on. In contrast to \fBplatform::identify\fR it
+leaves out details like kernel version, libc version, etc. The
+returned identifier has the general format \fIOS\fR-\fICPU\fR.
+.TP
+\fBplatform::patterns \fIidentifier\fR
+This command takes an identifier as returned by
+\fBplatform::identify\fR and returns a list of identifiers describing
+compatible architectures.
+.SH KEYWORDS
+operating system, cpu architecture, platform, architecture
diff --git a/doc/platform_shell.n b/doc/platform_shell.n
new file mode 100644
index 0000000..eef4d4e
--- /dev/null
+++ b/doc/platform_shell.n
@@ -0,0 +1,57 @@
+'\"
+'\" Copyright (c) 2006-2008 ActiveState Software Inc
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.so man.macros
+.TH "platform::shell" n 1.1.4 platform::shell "Tcl Bundled Packages"
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+platform::shell \- System identification support code and utilities
+.SH SYNOPSIS
+.nf
+\fBpackage require platform::shell ?1.1.4?\fR
+.sp
+\fBplatform::shell::generic \fIshell\fR
+\fBplatform::shell::identify \fIshell\fR
+\fBplatform::shell::platform \fIshell\fR
+.fi
+.BE
+.SH DESCRIPTION
+.PP
+The \fBplatform::shell\fR package provides several utility commands useful
+for the identification of the architecture of a specific Tcl shell.
+.PP
+This package allows the identification of the architecture of a
+specific Tcl shell different from the shell running the package. The
+only requirement is that the other shell (identified by its path), is
+actually executable on the current machine.
+.PP
+While for most platform this means that the architecture of the
+interrogated shell is identical to the architecture of the running
+shell this is not generally true. A counter example are all platforms
+which have 32 and 64 bit variants and where a 64bit system is able to
+run 32bit code. For these running and interrogated shell may have
+different 32/64 bit settings and thus different identifiers.
+.PP
+For applications like a code repository it is important to identify
+the architecture of the shell which will actually run the installed
+packages, versus the architecture of the shell running the repository
+software.
+.SH COMMANDS
+.TP
+\fBplatform::shell::identify \fIshell\fR
+This command does the same identification as \fBplatform::identify\fR,
+for the specified Tcl shell, in contrast to the running shell.
+.TP
+\fBplatform::shell::generic \fIshell\fR
+This command does the same identification as \fBplatform::generic\fR,
+for the specified Tcl shell, in contrast to the running shell.
+.TP
+\fBplatform::shell::platform \fIshell\fR
+This command returns the contents of \fBtcl_platform(platform)\fR for
+the specified Tcl shell.
+.SH KEYWORDS
+operating system, cpu architecture, platform, architecture
diff --git a/doc/proc.n b/doc/proc.n
index c335b3e..4525207 100644
--- a/doc/proc.n
+++ b/doc/proc.n
@@ -33,17 +33,25 @@ elements specifies
one argument. Each argument specifier is also a list with either
one or two fields. If there is only a single field in the specifier
then it is the name of the argument; if there are two fields, then
-the first is the argument name and the second is its default value.
+the first is the argument name and the second is its default value.
+Arguments with default values that are followed by non-defaulted
+arguments become required arguments. In 8.6 this will be considered an
+error.
.PP
When \fIname\fR is invoked a local variable
will be created for each of the formal arguments to the procedure; its
value will be the value of corresponding argument in the invoking command
or the argument's default value.
+Actual arguments are assigned to formal arguments strictly in order.
Arguments with default values need not be
specified in a procedure invocation. However, there must be enough
actual arguments for all the
-formal arguments that don't have defaults, and there must not be any extra
-actual arguments. There is one special case to permit procedures with
+formal arguments that do not have defaults, and there must not be any extra
+actual arguments.
+Arguments with default values that are followed by non-defaulted
+arguments become required arguments (in 8.6 it will be considered an
+error).
+There is one special case to permit procedures with
variable numbers of arguments. If the last formal argument has the name
\fBargs\fR, then a call to the procedure may contain more actual arguments
than the procedure has formals. In this case, all of the actual arguments
@@ -55,14 +63,12 @@ When \fIbody\fR is being executed, variable names normally refer to
local variables, which are created automatically when referenced and
deleted when the procedure returns. One local variable is automatically
created for each of the procedure's arguments.
-Global variables can only be accessed by invoking
-the \fBglobal\fR command or the \fBupvar\fR command.
-Namespace variables can only be accessed by invoking
-the \fBvariable\fR command or the \fBupvar\fR command.
+Other variables can only be accessed by invoking one of the \fBglobal\fR,
+\fBvariable\fR, \fBupvar\fR or \fBnamespace upvar\fR commands.
.PP
The \fBproc\fR command returns an empty string. When a procedure is
invoked, the procedure's return value is the value specified in a
-\fBreturn\fR command. If the procedure doesn't execute an explicit
+\fBreturn\fR command. If the procedure does not execute an explicit
\fBreturn\fR, then its return value is the value of the last command
executed in the procedure's body.
If an error occurs while executing the procedure
diff --git a/doc/puts.n b/doc/puts.n
index 9fa5f15..5cd8721 100644
--- a/doc/puts.n
+++ b/doc/puts.n
@@ -20,13 +20,11 @@ puts \- Write to a channel
Writes the characters given by \fIstring\fR to the channel given
by \fIchannelId\fR.
.PP
-.VS
\fIChannelId\fR must be an identifier for an open channel such as a
Tcl standard channel (\fBstdout\fR or \fBstderr\fR), the return
value from an invocation of \fBopen\fR or \fBsocket\fR, or the result
of a channel creation command provided by a Tcl extension. The channel
must have been opened for output.
-.VE
.PP
If no \fIchannelId\fR is specified then it defaults to
\fBstdout\fR. \fBPuts\fR normally outputs a newline character after
@@ -37,8 +35,7 @@ Newline characters in the output are translated by \fBputs\fR to
platform-specific end-of-line sequences according to the current
value of the \fB\-translation\fR option for the channel (for example,
on PCs newlines are normally replaced with carriage-return-linefeed
-sequences; on Macintoshes newlines are normally replaced with
-carriage-returns).
+sequences.
See the \fBfconfigure\fR manual entry for a discussion on ways in
which \fBfconfigure\fR will alter output.
.PP
@@ -64,7 +61,7 @@ buffered for a channel in nonblocking mode, which could consume a
large amount of memory.
To avoid wasting memory, nonblocking I/O should normally
be used in an event-driven fashion with the \fBfileevent\fR command
-(don't invoke \fBputs\fR unless you have recently been notified
+(do not invoke \fBputs\fR unless you have recently been notified
via a file event that the channel is ready for more output data).
.SH EXAMPLES
Write a short message to the console (or wherever \fBstdout\fR is
diff --git a/doc/pwd.n b/doc/pwd.n
index 99a438f..e63b815 100644
--- a/doc/pwd.n
+++ b/doc/pwd.n
@@ -22,7 +22,7 @@ Returns the absolute path name of the current working directory.
Sometimes it is useful to change to a known directory when running
some external command using \fBexec\fR, but it is important to keep
the application usually running in the directory that it was started
-in (unless the user specifies otherwise) since that minimises user
+in (unless the user specifies otherwise) since that minimizes user
confusion. The way to do this is to save the current directory while
the external command is being run:
.CS
@@ -32,7 +32,6 @@ cd /tmp
exec tar -xf $tarFile
cd $savedDir
.CE
-
.SH "SEE ALSO"
file(n), cd(n), glob(n), filename(n)
diff --git a/doc/re_syntax.n b/doc/re_syntax.n
index 3a47e25..8701641 100644
--- a/doc/re_syntax.n
+++ b/doc/re_syntax.n
@@ -9,922 +9,820 @@
.TH re_syntax n "8.1" Tcl "Tcl Built-In Commands"
.BS
.SH NAME
-re_syntax \- Syntax of Tcl regular expressions.
+re_syntax \- Syntax of Tcl regular expressions
.BE
-
.SH DESCRIPTION
.PP
A \fIregular expression\fR describes strings of characters.
-It's a pattern that matches certain strings and doesn't match others.
-
+It's a pattern that matches certain strings and does not match others.
.SH "DIFFERENT FLAVORS OF REs"
-Regular expressions (``RE''s), as defined by POSIX, come in two
-flavors: \fIextended\fR REs (``EREs'') and \fIbasic\fR REs (``BREs'').
+Regular expressions
+.PQ RE s ,
+as defined by POSIX, come in two flavors: \fIextended\fR REs
+.PQ ERE s
+and \fIbasic\fR REs
+.PQ BRE s .
EREs are roughly those of the traditional \fIegrep\fR, while BREs are
-roughly those of the traditional \fIed\fR. This implementation adds
-a third flavor, \fIadvanced\fR REs (``AREs''), basically EREs with
-some significant extensions.
+roughly those of the traditional \fIed\fR. This implementation adds
+a third flavor, \fIadvanced\fR REs
+.PQ ARE s ,
+basically EREs with some significant extensions.
.PP
-This manual page primarily describes AREs. BREs mostly exist for
+This manual page primarily describes AREs. BREs mostly exist for
backward compatibility in some old programs; they will be discussed at
-the end. POSIX EREs are almost an exact subset of AREs. Features of
+the end. POSIX EREs are almost an exact subset of AREs. Features of
AREs that are not present in EREs will be indicated.
-
.SH "REGULAR EXPRESSION SYNTAX"
.PP
Tcl regular expressions are implemented using the package written by
Henry Spencer, based on the 1003.2 spec and some (not quite all) of
-the Perl5 extensions (thanks, Henry!). Much of the description of
+the Perl5 extensions (thanks, Henry!). Much of the description of
regular expressions below is copied verbatim from his manual entry.
.PP
An ARE is one or more \fIbranches\fR,
-separated by `\fB|\fR',
+separated by
+.QW \fB|\fR ,
matching anything that matches any of the branches.
.PP
A branch is zero or more \fIconstraints\fR or \fIquantified atoms\fR,
concatenated.
It matches a match for the first, followed by a match for the second, etc;
an empty branch matches the empty string.
-.PP
+.SS QUANTIFIERS
A quantified atom is an \fIatom\fR possibly followed
by a single \fIquantifier\fR.
-Without a quantifier, it matches a match for the atom.
+Without a quantifier, it matches a single match for the atom.
The quantifiers,
and what a so-quantified atom matches, are:
.RS 2
.TP 6
\fB*\fR
+.
a sequence of 0 or more matches of the atom
.TP
\fB+\fR
+.
a sequence of 1 or more matches of the atom
.TP
\fB?\fR
+.
a sequence of 0 or 1 matches of the atom
.TP
\fB{\fIm\fB}\fR
+.
a sequence of exactly \fIm\fR matches of the atom
.TP
\fB{\fIm\fB,}\fR
+.
a sequence of \fIm\fR or more matches of the atom
.TP
\fB{\fIm\fB,\fIn\fB}\fR
+.
a sequence of \fIm\fR through \fIn\fR (inclusive) matches of the atom;
\fIm\fR may not exceed \fIn\fR
.TP
\fB*? +? ?? {\fIm\fB}? {\fIm\fB,}? {\fIm\fB,\fIn\fB}?\fR
-\fInon-greedy\fR quantifiers,
-which match the same possibilities,
+.
+\fInon-greedy\fR quantifiers, which match the same possibilities,
but prefer the smallest number rather than the largest number
-of matches (see MATCHING)
+of matches (see \fBMATCHING\fR)
.RE
.PP
-The forms using
-\fB{\fR and \fB}\fR
-are known as \fIbound\fRs.
-The numbers
-\fIm\fR and \fIn\fR are unsigned decimal integers
-with permissible values from 0 to 255 inclusive.
-.PP
+The forms using \fB{\fR and \fB}\fR are known as \fIbound\fRs. The
+numbers \fIm\fR and \fIn\fR are unsigned decimal integers with
+permissible values from 0 to 255 inclusive.
+.SS ATOMS
An atom is one of:
.RS 2
-.TP 6
-\fB(\fIre\fB)\fR
-(where \fIre\fR is any regular expression)
-matches a match for
-\fIre\fR, with the match noted for possible reporting
-.TP
-\fB(?:\fIre\fB)\fR
-as previous,
-but does no reporting
-(a ``non-capturing'' set of parentheses)
-.TP
-\fB()\fR
-matches an empty string,
-noted for possible reporting
-.TP
-\fB(?:)\fR
-matches an empty string,
-without reporting
-.TP
-\fB[\fIchars\fB]\fR
-a \fIbracket expression\fR,
-matching any one of the \fIchars\fR (see BRACKET EXPRESSIONS for more detail)
-.TP
- \fB.\fR
+.IP \fB(\fIre\fB)\fR 6
+matches a match for \fIre\fR (\fIre\fR is any regular expression) with
+the match noted for possible reporting
+.IP \fB(?:\fIre\fB)\fR
+as previous, but does no reporting (a
+.QW non-capturing
+set of parentheses)
+.IP \fB()\fR
+matches an empty string, noted for possible reporting
+.IP \fB(?:)\fR
+matches an empty string, without reporting
+.IP \fB[\fIchars\fB]\fR
+a \fIbracket expression\fR, matching any one of the \fIchars\fR (see
+\fBBRACKET EXPRESSIONS\fR for more detail)
+.IP \fB.\fR
matches any single character
-.TP
-\fB\e\fIk\fR
-(where \fIk\fR is a non-alphanumeric character)
-matches that character taken as an ordinary character,
-e.g. \e\e matches a backslash character
-.TP
-\fB\e\fIc\fR
-where \fIc\fR is alphanumeric
-(possibly followed by other characters),
-an \fIescape\fR (AREs only),
-see ESCAPES below
-.TP
-\fB{\fR
-when followed by a character other than a digit,
-matches the left-brace character `\fB{\fR';
-when followed by a digit, it is the beginning of a
-\fIbound\fR (see above)
-.TP
-\fIx\fR
-where \fIx\fR is
-a single character with no other significance, matches that character.
+.IP \fB\e\fIk\fR
+matches the non-alphanumeric character \fIk\fR
+taken as an ordinary character, e.g. \fB\e\e\fR matches a backslash
+character
+.IP \fB\e\fIc\fR
+where \fIc\fR is alphanumeric (possibly followed by other characters),
+an \fIescape\fR (AREs only), see \fBESCAPES\fR below
+.IP \fB{\fR
+when followed by a character other than a digit, matches the
+left-brace character
+.QW \fB{\fR ;
+when followed by a digit, it is the beginning of a \fIbound\fR (see above)
+.IP \fIx\fR
+where \fIx\fR is a single character with no other significance,
+matches that character.
.RE
-.PP
+.SS CONSTRAINTS
A \fIconstraint\fR matches an empty string when specific conditions
-are met.
-A constraint may not be followed by a quantifier.
-The simple constraints are as follows; some more constraints are
-described later, under ESCAPES.
+are met. A constraint may not be followed by a quantifier. The
+simple constraints are as follows; some more constraints are described
+later, under \fBESCAPES\fR.
.RS 2
.TP 8
\fB^\fR
+.
matches at the beginning of a line
.TP
\fB$\fR
+.
matches at the end of a line
.TP
\fB(?=\fIre\fB)\fR
-\fIpositive lookahead\fR (AREs only), matches at any point
-where a substring matching \fIre\fR begins
+.
+\fIpositive lookahead\fR (AREs only), matches at any point where a
+substring matching \fIre\fR begins
.TP
\fB(?!\fIre\fB)\fR
-\fInegative lookahead\fR (AREs only), matches at any point
-where no substring matching \fIre\fR begins
+.
+\fInegative lookahead\fR (AREs only), matches at any point where no
+substring matching \fIre\fR begins
.RE
.PP
The lookahead constraints may not contain back references (see later),
and all parentheses within them are considered non-capturing.
.PP
-An RE may not end with `\fB\e\fR'.
-
+An RE may not end with
+.QW \fB\e\fR .
.SH "BRACKET EXPRESSIONS"
-A \fIbracket expression\fR is a list of characters enclosed in `\fB[\|]\fR'.
-It normally matches any single character from the list (but see below).
-If the list begins with `\fB^\fR',
-it matches any single character
-(but see below) \fInot\fR from the rest of the list.
-.PP
-If two characters in the list are separated by `\fB\-\fR',
-this is shorthand
-for the full \fIrange\fR of characters between those two (inclusive) in the
-collating sequence,
-e.g.
-\fB[0\-9]\fR
-in ASCII matches any decimal digit.
-Two ranges may not share an
+A \fIbracket expression\fR is a list of characters enclosed in
+.QW \fB[\|]\fR .
+It normally matches any single character from the list
+(but see below). If the list begins with
+.QW \fB^\fR ,
+it matches any single character (but see below) \fInot\fR from the
+rest of the list.
+.PP
+If two characters in the list are separated by
+.QW \fB\-\fR ,
+this is shorthand for the full \fIrange\fR of characters between those two
+(inclusive) in the collating sequence, e.g.
+.QW \fB[0\-9]\fR
+in Unicode matches any conventional decimal digit. Two ranges may not share an
endpoint, so e.g.
-\fBa\-c\-e\fR
-is illegal.
-Ranges are very collating-sequence-dependent,
-and portable programs should avoid relying on them.
-.PP
-To include a literal
-\fB]\fR
-or
-\fB\-\fR
-in the list,
-the simplest method is to
-enclose it in
-\fB[.\fR and \fB.]\fR
-to make it a collating element (see below).
-Alternatively,
-make it the first character
-(following a possible `\fB^\fR'),
-or (AREs only) precede it with `\fB\e\fR'.
-Alternatively, for `\fB\-\fR',
-make it the last character,
-or the second endpoint of a range.
-To use a literal
-\fB\-\fR
-as the first endpoint of a range,
-make it a collating element
-or (AREs only) precede it with `\fB\e\fR'.
-With the exception of these, some combinations using
-\fB[\fR
-(see next
-paragraphs), and escapes,
-all other special characters lose their
-special significance within a bracket expression.
-.PP
-Within a bracket expression, a collating element (a character,
-a multi-character sequence that collates as if it were a single character,
-or a collating-sequence name for either)
-enclosed in
-\fB[.\fR and \fB.]\fR
-stands for the
-sequence of characters of that collating element.
-The sequence is a single element of the bracket expression's list.
-A bracket expression in a locale that has
-multi-character collating elements
-can thus match more than one character.
-.VS 8.2
-So (insidiously), a bracket expression that starts with \fB^\fR
-can match multi-character collating elements even if none of them
-appear in the bracket expression!
-(\fINote:\fR Tcl currently has no multi-character collating elements.
-This information is only for illustration.)
-.PP
-For example, assume the collating sequence includes a \fBch\fR
-multi-character collating element.
-Then the RE \fB[[.ch.]]*c\fR (zero or more \fBch\fP's followed by \fBc\fP)
-matches the first five characters of `\fBchchcc\fR'.
-Also, the RE \fB[^c]b\fR matches all of `\fBchb\fR'
-(because \fB[^c]\fR matches the multi-character \fBch\fR).
-.VE 8.2
-.PP
-Within a bracket expression, a collating element enclosed in
-\fB[=\fR
-and
-\fB=]\fR
-is an equivalence class, standing for the sequences of characters
-of all collating elements equivalent to that one, including itself.
-(If there are no other equivalent collating elements,
-the treatment is as if the enclosing delimiters were `\fB[.\fR'\&
-and `\fB.]\fR'.)
-For example, if
-\fBo\fR
-and
-\fB\o'o^'\fR
-are the members of an equivalence class,
-then `\fB[[=o=]]\fR', `\fB[[=\o'o^'=]]\fR',
-and `\fB[o\o'o^']\fR'\&
-are all synonymous.
-An equivalence class may not be an endpoint
-of a range.
-.VS 8.2
-(\fINote:\fR
-Tcl currently implements only the Unicode locale.
-It doesn't define any equivalence classes.
-The examples above are just illustrations.)
-.VE 8.2
-.PP
-Within a bracket expression, the name of a \fIcharacter class\fR enclosed
-in
-\fB[:\fR
-and
-\fB:]\fR
-stands for the list of all characters
-(not all collating elements!)
-belonging to that
-class.
+.QW \fBa\-c\-e\fR
+is illegal. Ranges in Tcl always use the
+Unicode collating sequence, but other programs may use other collating
+sequences and this can be a source of incompatability between programs.
+.PP
+To include a literal \fB]\fR or \fB\-\fR in the list, the simplest
+method is to enclose it in \fB[.\fR and \fB.]\fR to make it a
+collating element (see below). Alternatively, make it the first
+character (following a possible
+.QW \fB^\fR ),
+or (AREs only) precede it with
+.QW \fB\e\fR .
+Alternatively, for
+.QW \fB\-\fR ,
+make it the last character, or the second endpoint of a range. To use
+a literal \fB\-\fR as the first endpoint of a range, make it a
+collating element or (AREs only) precede it with
+.QW \fB\e\fR .
+With the exception of
+these, some combinations using \fB[\fR (see next paragraphs), and
+escapes, all other special characters lose their special significance
+within a bracket expression.
+.SS "CHARACTER CLASSES"
+Within a bracket expression, the name of a \fIcharacter class\fR
+enclosed in \fB[:\fR and \fB:]\fR stands for the list of all
+characters (not all collating elements!) belonging to that class.
Standard character classes are:
-.PP
+.IP \fBalpha\fR 8
+A letter.
+.IP \fBupper\fR 8
+An upper-case letter.
+.IP \fBlower\fR 8
+A lower-case letter.
+.IP \fBdigit\fR 8
+A decimal digit.
+.IP \fBxdigit\fR 8
+A hexadecimal digit.
+.IP \fBalnum\fR 8
+An alphanumeric (letter or digit).
+.IP \fBprint\fR 8
+A "printable" (same as graph, except also including space).
+.IP \fBblank\fR 8
+A space or tab character.
+.IP \fBspace\fR 8
+A character producing white space in displayed text.
+.IP \fBpunct\fR 8
+A punctuation character.
+.IP \fBgraph\fR 8
+A character with a visible representation (includes both alnum and punct).
+.IP \fBcntrl\fR 8
+A control character.
+.PP
+A locale may provide others. A character class may not be used as an endpoint
+of a range.
.RS
-.ne 5
-.ta 3c
-.nf
-\fBalpha\fR A letter.
-\fBupper\fR An upper-case letter.
-\fBlower\fR A lower-case letter.
-\fBdigit\fR A decimal digit.
-\fBxdigit\fR A hexadecimal digit.
-\fBalnum\fR An alphanumeric (letter or digit).
-\fBprint\fR An alphanumeric (same as alnum).
-\fBblank\fR A space or tab character.
-\fBspace\fR A character producing white space in displayed text.
-\fBpunct\fR A punctuation character.
-\fBgraph\fR A character with a visible representation.
-\fBcntrl\fR A control character.
-.fi
+.PP
+(\fINote:\fR the current Tcl implementation has only one locale, the Unicode
+locale, which supports exactly the above classes.)
.RE
+.SS "BRACKETED CONSTRAINTS"
+There are two special cases of bracket expressions: the bracket
+expressions
+.QW \fB[[:<:]]\fR
+and
+.QW \fB[[:>:]]\fR
+are constraints, matching empty strings at the beginning and end of a word
+respectively.
+.\" note, discussion of escapes below references this definition of word
+A word is defined as a sequence of word characters that is neither preceded
+nor followed by word characters. A word character is an \fIalnum\fR character
+or an underscore
+.PQ \fB_\fR "" .
+These special bracket expressions are deprecated; users of AREs should use
+constraint escapes instead (see below).
+.SS "COLLATING ELEMENTS"
+Within a bracket expression, a collating element (a character, a
+multi-character sequence that collates as if it were a single
+character, or a collating-sequence name for either) enclosed in
+\fB[.\fR and \fB.]\fR stands for the sequence of characters of that
+collating element. The sequence is a single element of the bracket
+expression's list. A bracket expression in a locale that has
+multi-character collating elements can thus match more than one
+character. So (insidiously), a bracket expression that starts with
+\fB^\fR can match multi-character collating elements even if none of
+them appear in the bracket expression!
+.RS
.PP
-A locale may provide others.
-.VS 8.2
-(Note that the current Tcl implementation has only one locale:
-the Unicode locale.)
-.VE 8.2
-A character class may not be used as an endpoint of a range.
+(\fINote:\fR Tcl has no multi-character collating elements. This information
+is only for illustration.)
+.RE
.PP
-There are two special cases of bracket expressions:
-the bracket expressions
-\fB[[:<:]]\fR
+For example, assume the collating sequence includes a \fBch\fR multi-character
+collating element. Then the RE
+.QW \fB[[.ch.]]*c\fR
+(zero or more
+.QW \fBch\fRs
+followed by
+.QW \fBc\fR )
+matches the first five characters of
+.QW \fBchchcc\fR .
+Also, the RE
+.QW \fB[^c]b\fR
+matches all of
+.QW \fBchb\fR
+(because
+.QW \fB[^c]\fR
+matches the multi-character
+.QW \fBch\fR ).
+.SS "EQUIVALENCE CLASSES"
+Within a bracket expression, a collating element enclosed in \fB[=\fR
+and \fB=]\fR is an equivalence class, standing for the sequences of
+characters of all collating elements equivalent to that one, including
+itself. (If there are no other equivalent collating elements, the
+treatment is as if the enclosing delimiters were
+.QW \fB[.\fR \&
and
-\fB[[:>:]]\fR
-are constraints, matching empty strings at
-the beginning and end of a word respectively.
-'\" note, discussion of escapes below references this definition of word
-A word is defined as a sequence of
-word characters
-that is neither preceded nor followed by
-word characters.
-A word character is an
-\fIalnum\fR
-character
-or an underscore
-(\fB_\fR).
-These special bracket expressions are deprecated;
-users of AREs should use constraint escapes instead (see below).
-.SH ESCAPES
-Escapes (AREs only), which begin with a
-\fB\e\fR
-followed by an alphanumeric character,
-come in several varieties:
-character entry, class shorthands, constraint escapes, and back references.
-A
-\fB\e\fR
-followed by an alphanumeric character but not constituting
-a valid escape is illegal in AREs.
-In EREs, there are no escapes:
-outside a bracket expression,
-a
-\fB\e\fR
-followed by an alphanumeric character merely stands for that
-character as an ordinary character,
-and inside a bracket expression,
-\fB\e\fR
-is an ordinary character.
-(The latter is the one actual incompatibility between EREs and AREs.)
+.QW \fB.]\fR .)
+For example, if \fBo\fR and \fB\N'244'\fR are the members of an
+equivalence class, then
+.QW \fB[[=o=]]\fR ,
+.QW \fB[[=\N'244'=]]\fR ,
+and
+.QW \fB[o\N'244']\fR \&
+are all synonymous. An equivalence class may not be an endpoint of a range.
+.RS
.PP
+(\fINote:\fR Tcl implements only the Unicode locale. It does not define any
+equivalence classes. The examples above are just illustrations.)
+.RE
+.SH ESCAPES
+Escapes (AREs only), which begin with a \fB\e\fR followed by an
+alphanumeric character, come in several varieties: character entry,
+class shorthands, constraint escapes, and back references. A \fB\e\fR
+followed by an alphanumeric character but not constituting a valid
+escape is illegal in AREs. In EREs, there are no escapes: outside a
+bracket expression, a \fB\e\fR followed by an alphanumeric character
+merely stands for that character as an ordinary character, and inside
+a bracket expression, \fB\e\fR is an ordinary character. (The latter
+is the one actual incompatibility between EREs and AREs.)
+.SS "CHARACTER-ENTRY ESCAPES"
Character-entry escapes (AREs only) exist to make it easier to specify
non-printing and otherwise inconvenient characters in REs:
.RS 2
.TP 5
\fB\ea\fR
+.
alert (bell) character, as in C
.TP
\fB\eb\fR
+.
backspace, as in C
.TP
\fB\eB\fR
-synonym for
-\fB\e\fR
-to help reduce backslash doubling in some
+.
+synonym for \fB\e\fR to help reduce backslash doubling in some
applications where there are multiple levels of backslash processing
.TP
\fB\ec\fIX\fR
-(where X is any character) the character whose
-low-order 5 bits are the same as those of
-\fIX\fR,
-and whose other bits are all zero
+.
+(where \fIX\fR is any character) the character whose low-order 5 bits
+are the same as those of \fIX\fR, and whose other bits are all zero
.TP
\fB\ee\fR
-the character whose collating-sequence name
-is `\fBESC\fR',
+.
+the character whose collating-sequence name is
+.QW \fBESC\fR ,
or failing that, the character with octal value 033
.TP
\fB\ef\fR
+.
formfeed, as in C
.TP
\fB\en\fR
+.
newline, as in C
.TP
\fB\er\fR
+.
carriage return, as in C
.TP
\fB\et\fR
+.
horizontal tab, as in C
.TP
\fB\eu\fIwxyz\fR
-(where
-\fIwxyz\fR
-is exactly four hexadecimal digits)
-the Unicode character
-\fBU+\fIwxyz\fR
-in the local byte ordering
+.
+(where \fIwxyz\fR is exactly four hexadecimal digits) the Unicode
+character \fBU+\fIwxyz\fR in the local byte ordering
.TP
\fB\eU\fIstuvwxyz\fR
-(where
-\fIstuvwxyz\fR
-is exactly eight hexadecimal digits)
-reserved for a somewhat-hypothetical Unicode extension to 32 bits
+.
+(where \fIstuvwxyz\fR is exactly eight hexadecimal digits) reserved
+for a somewhat-hypothetical Unicode extension to 32 bits
.TP
\fB\ev\fR
-vertical tab, as in C
-are all available.
+.
+vertical tab, as in C are all available.
.TP
\fB\ex\fIhhh\fR
-(where
-\fIhhh\fR
-is any sequence of hexadecimal digits)
-the character whose hexadecimal value is
-\fB0x\fIhhh\fR
-(a single character no matter how many hexadecimal digits are used).
+.
+(where \fIhhh\fR is any sequence of hexadecimal digits) the character
+whose hexadecimal value is \fB0x\fIhhh\fR (a single character no
+matter how many hexadecimal digits are used).
.TP
\fB\e0\fR
-the character whose value is
-\fB0\fR
+.
+the character whose value is \fB0\fR
.TP
\fB\e\fIxy\fR
-(where
-\fIxy\fR
-is exactly two octal digits,
-and is not a
-\fIback reference\fR (see below))
-the character whose octal value is
+.
+(where \fIxy\fR is exactly two octal digits, and is not a \fIback
+reference\fR (see below)) the character whose octal value is
\fB0\fIxy\fR
.TP
\fB\e\fIxyz\fR
-(where
-\fIxyz\fR
-is exactly three octal digits,
-and is not a
-back reference (see below))
-the character whose octal value is
+.
+(where \fIxyz\fR is exactly three octal digits, and is not a back
+reference (see below)) the character whose octal value is
\fB0\fIxyz\fR
.RE
.PP
-Hexadecimal digits are `\fB0\fR'-`\fB9\fR', `\fBa\fR'-`\fBf\fR',
-and `\fBA\fR'-`\fBF\fR'.
-Octal digits are `\fB0\fR'-`\fB7\fR'.
+Hexadecimal digits are
+.QR \fB0\fR \fB9\fR ,
+.QR \fBa\fR \fBf\fR ,
+and
+.QR \fBA\fR \fBF\fR .
+Octal digits are
+.QR \fB0\fR \fB7\fR .
.PP
The character-entry escapes are always taken as ordinary characters.
-For example,
-\fB\e135\fR
-is
-\fB]\fR
-in ASCII,
-but
-\fB\e135\fR
-does not terminate a bracket expression.
-Beware, however, that some applications (e.g., C compilers) interpret
-such sequences themselves before the regular-expression package
-gets to see them, which may require doubling (quadrupling, etc.) the `\fB\e\fR'.
-.PP
-Class-shorthand escapes (AREs only) provide shorthands for certain commonly-used
-character classes:
+For example, \fB\e135\fR is \fB]\fR in Unicode, but \fB\e135\fR does
+not terminate a bracket expression. Beware, however, that some
+applications (e.g., C compilers and the Tcl interpreter if the regular
+expression is not quoted with braces) interpret such sequences
+themselves before the regular-expression package gets to see them,
+which may require doubling (quadrupling, etc.) the
+.QW \fB\e\fR .
+.SS "CLASS-SHORTHAND ESCAPES"
+Class-shorthand escapes (AREs only) provide shorthands for certain
+commonly-used character classes:
.RS 2
.TP 10
\fB\ed\fR
+.
\fB[[:digit:]]\fR
.TP
\fB\es\fR
+.
\fB[[:space:]]\fR
.TP
\fB\ew\fR
-\fB[[:alnum:]_]\fR
-(note underscore)
+.
+\fB[[:alnum:]_]\fR (note underscore)
.TP
\fB\eD\fR
+.
\fB[^[:digit:]]\fR
.TP
\fB\eS\fR
+.
\fB[^[:space:]]\fR
.TP
\fB\eW\fR
-\fB[^[:alnum:]_]\fR
-(note underscore)
+.
+\fB[^[:alnum:]_]\fR (note underscore)
.RE
.PP
-Within bracket expressions, `\fB\ed\fR', `\fB\es\fR',
-and `\fB\ew\fR'\&
-lose their outer brackets,
-and `\fB\eD\fR', `\fB\eS\fR',
-and `\fB\eW\fR'\&
-are illegal.
-.VS 8.2
-(So, for example, \fB[a-c\ed]\fR is equivalent to \fB[a-c[:digit:]]\fR.
-Also, \fB[a-c\eD]\fR, which is equivalent to \fB[a-c^[:digit:]]\fR, is illegal.)
-.VE 8.2
-.PP
-A constraint escape (AREs only) is a constraint,
-matching the empty string if specific conditions are met,
-written as an escape:
+Within bracket expressions,
+.QW \fB\ed\fR ,
+.QW \fB\es\fR ,
+and
+.QW \fB\ew\fR \&
+lose their outer brackets, and
+.QW \fB\eD\fR ,
+.QW \fB\eS\fR ,
+and
+.QW \fB\eW\fR \&
+are illegal. (So, for example,
+.QW \fB[a-c\ed]\fR
+is equivalent to
+.QW \fB[a-c[:digit:]]\fR .
+Also,
+.QW \fB[a-c\eD]\fR ,
+which is equivalent to
+.QW \fB[a-c^[:digit:]]\fR ,
+is illegal.)
+.SS "CONSTRAINT ESCAPES"
+A constraint escape (AREs only) is a constraint, matching the empty
+string if specific conditions are met, written as an escape:
.RS 2
.TP 6
\fB\eA\fR
-matches only at the beginning of the string
-(see MATCHING, below, for how this differs from `\fB^\fR')
+.
+matches only at the beginning of the string (see \fBMATCHING\fR,
+below, for how this differs from
+.QW \fB^\fR )
.TP
\fB\em\fR
+.
matches only at the beginning of a word
.TP
\fB\eM\fR
+.
matches only at the end of a word
.TP
\fB\ey\fR
+.
matches only at the beginning or end of a word
.TP
\fB\eY\fR
+.
matches only at a point that is not the beginning or end of a word
.TP
\fB\eZ\fR
-matches only at the end of the string
-(see MATCHING, below, for how this differs from `\fB$\fR')
+.
+matches only at the end of the string (see \fBMATCHING\fR, below, for
+how this differs from
+.QW \fB$\fR )
.TP
\fB\e\fIm\fR
-(where
-\fIm\fR
-is a nonzero digit) a \fIback reference\fR, see below
+.
+(where \fIm\fR is a nonzero digit) a \fIback reference\fR, see below
.TP
\fB\e\fImnn\fR
-(where
-\fIm\fR
-is a nonzero digit, and
-\fInn\fR
-is some more digits,
-and the decimal value
-\fImnn\fR
-is not greater than the number of closing capturing parentheses seen so far)
-a \fIback reference\fR, see below
+.
+(where \fIm\fR is a nonzero digit, and \fInn\fR is some more digits,
+and the decimal value \fImnn\fR is not greater than the number of
+closing capturing parentheses seen so far) a \fIback reference\fR, see
+below
.RE
.PP
A word is defined as in the specification of
-\fB[[:<:]]\fR
+.QW \fB[[:<:]]\fR
and
-\fB[[:>:]]\fR
-above.
-Constraint escapes are illegal within bracket expressions.
-.PP
-A back reference (AREs only) matches the same string matched by the parenthesized
-subexpression specified by the number,
-so that (e.g.)
-\fB([bc])\e1\fR
+.QW \fB[[:>:]]\fR
+above. Constraint escapes are illegal within bracket expressions.
+.SS "BACK REFERENCES"
+A back reference (AREs only) matches the same string matched by the
+parenthesized subexpression specified by the number, so that (e.g.)
+.QW \fB([bc])\e1\fR
matches
-\fBbb\fR
+.QW \fBbb\fR
or
-\fBcc\fR
-but not `\fBbc\fR'.
+.QW \fBcc\fR
+but not
+.QW \fBbc\fR .
The subexpression must entirely precede the back reference in the RE.
Subexpressions are numbered in the order of their leading parentheses.
Non-capturing parentheses do not define subexpressions.
.PP
-There is an inherent historical ambiguity between octal character-entry
-escapes and back references, which is resolved by heuristics,
-as hinted at above.
-A leading zero always indicates an octal escape.
-A single non-zero digit, not followed by another digit,
-is always taken as a back reference.
-A multi-digit sequence not starting with a zero is taken as a back
-reference if it comes after a suitable subexpression
-(i.e. the number is in the legal range for a back reference),
-and otherwise is taken as octal.
+There is an inherent historical ambiguity between octal
+character-entry escapes and back references, which is resolved by
+heuristics, as hinted at above. A leading zero always indicates an
+octal escape. A single non-zero digit, not followed by another digit,
+is always taken as a back reference. A multi-digit sequence not
+starting with a zero is taken as a back reference if it comes after a
+suitable subexpression (i.e. the number is in the legal range for a
+back reference), and otherwise is taken as octal.
.SH "METASYNTAX"
In addition to the main syntax described above, there are some special
forms and miscellaneous syntactic facilities available.
.PP
Normally the flavor of RE being used is specified by
-application-dependent means.
-However, this can be overridden by a \fIdirector\fR.
-If an RE of any flavor begins with `\fB***:\fR',
-the rest of the RE is an ARE.
-If an RE of any flavor begins with `\fB***=\fR',
-the rest of the RE is taken to be a literal string,
-with all characters considered ordinary characters.
-.PP
-An ARE may begin with \fIembedded options\fR:
-a sequence
-\fB(?\fIxyz\fB)\fR
-(where
-\fIxyz\fR
-is one or more alphabetic characters)
-specifies options affecting the rest of the RE.
-These supplement, and can override,
-any options specified by the application.
-The available option letters are:
+application-dependent means. However, this can be overridden by a
+\fIdirector\fR. If an RE of any flavor begins with
+.QW \fB***:\fR ,
+the rest of the RE is an ARE. If an RE of any flavor begins with
+.QW \fB***=\fR ,
+the rest of the RE is taken to be a literal string, with
+all characters considered ordinary characters.
+.PP
+An ARE may begin with \fIembedded options\fR: a sequence
+\fB(?\fIxyz\fB)\fR (where \fIxyz\fR is one or more alphabetic
+characters) specifies options affecting the rest of the RE. These
+supplement, and can override, any options specified by the
+application. The available option letters are:
.RS 2
.TP 3
\fBb\fR
+.
rest of RE is a BRE
.TP 3
\fBc\fR
+.
case-sensitive matching (usual default)
.TP 3
\fBe\fR
+.
rest of RE is an ERE
.TP 3
\fBi\fR
-case-insensitive matching (see MATCHING, below)
+.
+case-insensitive matching (see \fBMATCHING\fR, below)
.TP 3
\fBm\fR
-historical synonym for
-\fBn\fR
+.
+historical synonym for \fBn\fR
.TP 3
\fBn\fR
-newline-sensitive matching (see MATCHING, below)
+.
+newline-sensitive matching (see \fBMATCHING\fR, below)
.TP 3
\fBp\fR
-partial newline-sensitive matching (see MATCHING, below)
+.
+partial newline-sensitive matching (see \fBMATCHING\fR, below)
.TP 3
\fBq\fR
-rest of RE is a literal (``quoted'') string, all ordinary characters
+.
+rest of RE is a literal
+.PQ quoted
+string, all ordinary characters
.TP 3
\fBs\fR
+.
non-newline-sensitive matching (usual default)
.TP 3
\fBt\fR
+.
tight syntax (usual default; see below)
.TP 3
\fBw\fR
-inverse partial newline-sensitive (``weird'') matching (see MATCHING, below)
+.
+inverse partial newline-sensitive
+.PQ weird
+matching (see \fBMATCHING\fR, below)
.TP 3
\fBx\fR
+.
expanded syntax (see below)
.RE
.PP
-Embedded options take effect at the
-\fB)\fR
-terminating the sequence.
-They are available only at the start of an ARE,
-and may not be used later within it.
-.PP
-In addition to the usual (\fItight\fR) RE syntax, in which all characters are
-significant, there is an \fIexpanded\fR syntax,
-available in all flavors of RE
-with the \fB-expanded\fR switch, or in AREs with the embedded x option.
-In the expanded syntax,
-white-space characters are ignored
-and all characters between a
-\fB#\fR
-and the following newline (or the end of the RE) are ignored,
-permitting paragraphing and commenting a complex RE.
-There are three exceptions to that basic rule:
-.RS 2
-.PP
-a white-space character or `\fB#\fR' preceded by `\fB\e\fR' is retained
-.PP
-white space or `\fB#\fR' within a bracket expression is retained
-.PP
+Embedded options take effect at the \fB)\fR terminating the sequence.
+They are available only at the start of an ARE, and may not be used
+later within it.
+.PP
+In addition to the usual (\fItight\fR) RE syntax, in which all
+characters are significant, there is an \fIexpanded\fR syntax,
+available in all flavors of RE with the \fB\-expanded\fR switch, or in
+AREs with the embedded x option. In the expanded syntax, white-space
+characters are ignored and all characters between a \fB#\fR and the
+following newline (or the end of the RE) are ignored, permitting
+paragraphing and commenting a complex RE. There are three exceptions
+to that basic rule:
+.IP \(bu 3
+a white-space character or
+.QW \fB#\fR
+preceded by
+.QW \fB\e\fR
+is retained
+.IP \(bu 3
+white space or
+.QW \fB#\fR
+within a bracket expression is retained
+.IP \(bu 3
white space and comments are illegal within multi-character symbols
-like the ARE `\fB(?:\fR' or the BRE `\fB\e(\fR'
-.RE
+like the ARE
+.QW \fB(?:\fR
+or the BRE
+.QW \fB\e(\fR
.PP
Expanded-syntax white-space characters are blank, tab, newline, and
-.VS 8.2
any character that belongs to the \fIspace\fR character class.
-.VE 8.2
-.PP
-Finally, in an ARE,
-outside bracket expressions, the sequence `\fB(?#\fIttt\fB)\fR'
-(where
-\fIttt\fR
-is any text not containing a `\fB)\fR')
-is a comment,
-completely ignored.
-Again, this is not allowed between the characters of
-multi-character symbols like `\fB(?:\fR'.
+.PP
+Finally, in an ARE, outside bracket expressions, the sequence
+.QW \fB(?#\fIttt\fB)\fR
+(where \fIttt\fR is any text not containing a
+.QW \fB)\fR )
+is a comment, completely ignored. Again, this is not
+allowed between the characters of multi-character symbols like
+.QW \fB(?:\fR .
Such comments are more a historical artifact than a useful facility,
-and their use is deprecated;
-use the expanded syntax instead.
-.PP
-\fINone\fR of these metasyntax extensions is available if the application
-(or an initial
-\fB***=\fR
-director)
-has specified that the user's input be treated as a literal string
-rather than as an RE.
+and their use is deprecated; use the expanded syntax instead.
+.PP
+\fINone\fR of these metasyntax extensions is available if the
+application (or an initial
+.QW \fB***=\fR
+director) has specified that the
+user's input be treated as a literal string rather than as an RE.
.SH MATCHING
In the event that an RE could match more than one substring of a given
-string,
-the RE matches the one starting earliest in the string.
-If the RE could match more than one substring starting at that point,
-its choice is determined by its \fIpreference\fR:
-either the longest substring, or the shortest.
-.PP
-Most atoms, and all constraints, have no preference.
-A parenthesized RE has the same preference (possibly none) as the RE.
-A quantified atom with quantifier
-\fB{\fIm\fB}\fR
-or
-\fB{\fIm\fB}?\fR
-has the same preference (possibly none) as the atom itself.
-A quantified atom with other normal quantifiers (including
-\fB{\fIm\fB,\fIn\fB}\fR
-with
-\fIm\fR
-equal to
-\fIn\fR)
-prefers longest match.
-A quantified atom with other non-greedy quantifiers (including
-\fB{\fIm\fB,\fIn\fB}?\fR
-with
-\fIm\fR
-equal to
-\fIn\fR)
-prefers shortest match.
-A branch has the same preference as the first quantified atom in it
-which has a preference.
-An RE consisting of two or more branches connected by the
-\fB|\fR
-operator prefers longest match.
-.PP
-Subject to the constraints imposed by the rules for matching the whole RE,
-subexpressions also match the longest or shortest possible substrings,
-based on their preferences,
-with subexpressions starting earlier in the RE taking priority over
-ones starting later.
-Note that outer subexpressions thus take priority over
-their component subexpressions.
-.PP
-Note that the quantifiers
-\fB{1,1}\fR
-and
-\fB{1,1}?\fR
-can be used to force longest and shortest preference, respectively,
-on a subexpression or a whole RE.
-.PP
-Match lengths are measured in characters, not collating elements.
-An empty string is considered longer than no match at all.
-For example,
-\fBbb*\fR
-matches the three middle characters of `\fBabbbc\fR',
-\fB(week|wee)(night|knights)\fR
-matches all ten characters of `\fBweeknights\fR',
+string, the RE matches the one starting earliest in the string. If
+the RE could match more than one substring starting at that point, its
+choice is determined by its \fIpreference\fR: either the longest
+substring, or the shortest.
+.PP
+Most atoms, and all constraints, have no preference. A parenthesized
+RE has the same preference (possibly none) as the RE. A quantified
+atom with quantifier \fB{\fIm\fB}\fR or \fB{\fIm\fB}?\fR has the same
+preference (possibly none) as the atom itself. A quantified atom with
+other normal quantifiers (including \fB{\fIm\fB,\fIn\fB}\fR with
+\fIm\fR equal to \fIn\fR) prefers longest match. A quantified atom
+with other non-greedy quantifiers (including \fB{\fIm\fB,\fIn\fB}?\fR
+with \fIm\fR equal to \fIn\fR) prefers shortest match. A branch has
+the same preference as the first quantified atom in it which has a
+preference. An RE consisting of two or more branches connected by the
+\fB|\fR operator prefers longest match.
+.PP
+Subject to the constraints imposed by the rules for matching the whole
+RE, subexpressions also match the longest or shortest possible
+substrings, based on their preferences, with subexpressions starting
+earlier in the RE taking priority over ones starting later. Note that
+outer subexpressions thus take priority over their component
+subexpressions.
+.PP
+Note that the quantifiers \fB{1,1}\fR and \fB{1,1}?\fR can be used to
+force longest and shortest preference, respectively, on a
+subexpression or a whole RE.
+.PP
+Match lengths are measured in characters, not collating elements. An
+empty string is considered longer than no match at all. For example,
+.QW \fBbb*\fR
+matches the three middle characters of
+.QW \fBabbbc\fR ,
+.QW \fB(week|wee)(night|knights)\fR
+matches all ten characters of
+.QW \fBweeknights\fR ,
when
-\fB(.*).*\fR
+.QW \fB(.*).*\fR
is matched against
-\fBabc\fR
-the parenthesized subexpression
-matches all three characters, and
-when
-\fB(a*)*\fR
+.QW \fBabc\fR
+the parenthesized subexpression matches all three characters, and when
+.QW \fB(a*)*\fR
is matched against
-\fBbc\fR
-both the whole RE and the parenthesized
-subexpression match an empty string.
-.PP
-If case-independent matching is specified,
-the effect is much as if all case distinctions had vanished from the
-alphabet.
-When an alphabetic that exists in multiple cases appears as an
-ordinary character outside a bracket expression, it is effectively
-transformed into a bracket expression containing both cases,
-so that
-\fBx\fR
-becomes `\fB[xX]\fR'.
-When it appears inside a bracket expression, all case counterparts
-of it are added to the bracket expression, so that
-\fB[x]\fR
+.QW \fBbc\fR
+both the whole RE and the parenthesized subexpression match an empty string.
+.PP
+If case-independent matching is specified, the effect is much as if
+all case distinctions had vanished from the alphabet. When an
+alphabetic that exists in multiple cases appears as an ordinary
+character outside a bracket expression, it is effectively transformed
+into a bracket expression containing both cases, so that \fBx\fR
becomes
-\fB[xX]\fR
-and
-\fB[^x]\fR
-becomes `\fB[^xX]\fR'.
-.PP
-If newline-sensitive matching is specified, \fB.\fR
-and bracket expressions using
-\fB^\fR
-will never match the newline character
-(so that matches will never cross newlines unless the RE
-explicitly arranges it)
-and
-\fB^\fR
-and
-\fB$\fR
-will match the empty string after and before a newline
-respectively, in addition to matching at beginning and end of string
-respectively.
-ARE
-\fB\eA\fR
+.QW \fB[xX]\fR .
+When it appears inside a bracket expression,
+all case counterparts of it are added to the bracket expression, so
+that
+.QW \fB[x]\fR
+becomes
+.QW \fB[xX]\fR
and
-\fB\eZ\fR
+.QW \fB[^x]\fR
+becomes
+.QW \fB[^xX]\fR .
+.PP
+If newline-sensitive matching is specified, \fB.\fR and bracket
+expressions using \fB^\fR will never match the newline character (so
+that matches will never cross newlines unless the RE explicitly
+arranges it) and \fB^\fR and \fB$\fR will match the empty string after
+and before a newline respectively, in addition to matching at
+beginning and end of string respectively. ARE \fB\eA\fR and \fB\eZ\fR
continue to match beginning or end of string \fIonly\fR.
.PP
-If partial newline-sensitive matching is specified,
-this affects \fB.\fR
-and bracket expressions
-as with newline-sensitive matching, but not
-\fB^\fR
-and `\fB$\fR'.
+If partial newline-sensitive matching is specified, this affects
+\fB.\fR and bracket expressions as with newline-sensitive matching,
+but not \fB^\fR and \fB$\fR.
.PP
-If inverse partial newline-sensitive matching is specified,
-this affects
-\fB^\fR
-and
-\fB$\fR
-as with
-newline-sensitive matching,
-but not \fB.\fR
-and bracket expressions.
-This isn't very useful but is provided for symmetry.
+If inverse partial newline-sensitive matching is specified, this
+affects \fB^\fR and \fB$\fR as with newline-sensitive matching, but
+not \fB.\fR and bracket expressions. This is not very useful but is
+provided for symmetry.
.SH "LIMITS AND COMPATIBILITY"
-No particular limit is imposed on the length of REs.
-Programs intended to be highly portable should not employ REs longer
-than 256 bytes,
-as a POSIX-compliant implementation can refuse to accept such REs.
-.PP
-The only feature of AREs that is actually incompatible with
-POSIX EREs is that
-\fB\e\fR
-does not lose its special
-significance inside bracket expressions.
-All other ARE features use syntax which is illegal or has
-undefined or unspecified effects in POSIX EREs;
-the
-\fB***\fR
-syntax of directors likewise is outside the POSIX
-syntax for both BREs and EREs.
-.PP
-Many of the ARE extensions are borrowed from Perl, but some have
-been changed to clean them up, and a few Perl extensions are not present.
-Incompatibilities of note include `\fB\eb\fR', `\fB\eB\fR',
-the lack of special treatment for a trailing newline,
-the addition of complemented bracket expressions to the things
-affected by newline-sensitive matching,
-the restrictions on parentheses and back references in lookahead constraints,
-and the longest/shortest-match (rather than first-match) matching semantics.
-.PP
-The matching rules for REs containing both normal and non-greedy quantifiers
-have changed since early beta-test versions of this package.
-(The new rules are much simpler and cleaner,
-but don't work as hard at guessing the user's real intentions.)
-.PP
-Henry Spencer's original 1986 \fIregexp\fR package,
-still in widespread use (e.g., in pre-8.1 releases of Tcl),
-implemented an early version of today's EREs.
-There are four incompatibilities between \fIregexp\fR's near-EREs
-(`RREs' for short) and AREs.
-In roughly increasing order of significance:
-.PP
-.RS
-In AREs,
-\fB\e\fR
-followed by an alphanumeric character is either an
-escape or an error,
-while in RREs, it was just another way of writing the
-alphanumeric.
-This should not be a problem because there was no reason to write
-such a sequence in RREs.
-.PP
-\fB{\fR
-followed by a digit in an ARE is the beginning of a bound,
-while in RREs,
-\fB{\fR
-was always an ordinary character.
-Such sequences should be rare,
-and will often result in an error because following characters
-will not look like a valid bound.
-.PP
-In AREs,
-\fB\e\fR
-remains a special character within `\fB[\|]\fR',
-so a literal
-\fB\e\fR
-within
-\fB[\|]\fR
-must be written `\fB\e\e\fR'.
-\fB\e\e\fR
-also gives a literal
-\fB\e\fR
-within
-\fB[\|]\fR
-in RREs,
+No particular limit is imposed on the length of REs. Programs
+intended to be highly portable should not employ REs longer than 256
+bytes, as a POSIX-compliant implementation can refuse to accept such
+REs.
+.PP
+The only feature of AREs that is actually incompatible with POSIX EREs
+is that \fB\e\fR does not lose its special significance inside bracket
+expressions. All other ARE features use syntax which is illegal or
+has undefined or unspecified effects in POSIX EREs; the \fB***\fR
+syntax of directors likewise is outside the POSIX syntax for both BREs
+and EREs.
+.PP
+Many of the ARE extensions are borrowed from Perl, but some have been
+changed to clean them up, and a few Perl extensions are not present.
+Incompatibilities of note include
+.QW \fB\eb\fR ,
+.QW \fB\eB\fR ,
+the lack of special treatment for a trailing newline, the addition of
+complemented bracket expressions to the things affected by
+newline-sensitive matching, the restrictions on parentheses and back
+references in lookahead constraints, and the longest/shortest-match
+(rather than first-match) matching semantics.
+.PP
+The matching rules for REs containing both normal and non-greedy
+quantifiers have changed since early beta-test versions of this
+package. (The new rules are much simpler and cleaner, but do not work
+as hard at guessing the user's real intentions.)
+.PP
+Henry Spencer's original 1986 \fIregexp\fR package, still in
+widespread use (e.g., in pre-8.1 releases of Tcl), implemented an
+early version of today's EREs. There are four incompatibilities
+between \fIregexp\fR's near-EREs
+.PQ RREs " for short"
+and AREs. In roughly increasing order of significance:
+.IP \(bu 3
+In AREs, \fB\e\fR followed by an alphanumeric character is either an
+escape or an error, while in RREs, it was just another way of writing
+the alphanumeric. This should not be a problem because there was no
+reason to write such a sequence in RREs.
+.IP \(bu 3
+\fB{\fR followed by a digit in an ARE is the beginning of a bound,
+while in RREs, \fB{\fR was always an ordinary character. Such
+sequences should be rare, and will often result in an error because
+following characters will not look like a valid bound.
+.IP \(bu 3
+In AREs, \fB\e\fR remains a special character within
+.QW \fB[\|]\fR ,
+so a literal \fB\e\fR within \fB[\|]\fR must be written
+.QW \fB\e\e\fR .
+\fB\e\e\fR also gives a literal \fB\e\fR within \fB[\|]\fR in RREs,
but only truly paranoid programmers routinely doubled the backslash.
-.PP
-AREs report the longest/shortest match for the RE,
-rather than the first found in a specified search order.
-This may affect some RREs which were written in the expectation that
-the first match would be reported.
-(The careful crafting of RREs to optimize the search order for fast
-matching is obsolete (AREs examine all possible matches
-in parallel, and their performance is largely insensitive to their
-complexity) but cases where the search order was exploited to deliberately
-find a match which was \fInot\fR the longest/shortest will need rewriting.)
-.RE
-
+.IP \(bu 3
+AREs report the longest/shortest match for the RE, rather than the
+first found in a specified search order. This may affect some RREs
+which were written in the expectation that the first match would be
+reported. (The careful crafting of RREs to optimize the search order
+for fast matching is obsolete (AREs examine all possible matches in
+parallel, and their performance is largely insensitive to their
+complexity) but cases where the search order was exploited to
+deliberately find a match which was \fInot\fR the longest/shortest
+will need rewriting.)
.SH "BASIC REGULAR EXPRESSIONS"
-BREs differ from EREs in several respects. `\fB|\fR', `\fB+\fR',
-and
-\fB?\fR
-are ordinary characters and there is no equivalent
-for their functionality.
-The delimiters for bounds are
-\fB\e{\fR
-and `\fB\e}\fR',
-with
-\fB{\fR
-and
-\fB}\fR
-by themselves ordinary characters.
-The parentheses for nested subexpressions are
-\fB\e(\fR
-and `\fB\e)\fR',
-with
-\fB(\fR
-and
-\fB)\fR
-by themselves ordinary characters.
-\fB^\fR
-is an ordinary character except at the beginning of the
-RE or the beginning of a parenthesized subexpression,
-\fB$\fR
-is an ordinary character except at the end of the
-RE or the end of a parenthesized subexpression,
-and
-\fB*\fR
-is an ordinary character if it appears at the beginning of the
-RE or the beginning of a parenthesized subexpression
-(after a possible leading `\fB^\fR').
-Finally,
-single-digit back references are available,
-and
-\fB\e<\fR
-and
-\fB\e>\fR
-are synonyms for
-\fB[[:<:]]\fR
+BREs differ from EREs in several respects.
+.QW \fB|\fR ,
+.QW \fB+\fR ,
+and \fB?\fR are ordinary characters and there is no equivalent for their
+functionality. The delimiters for bounds are \fB\e{\fR and
+.QW \fB\e}\fR ,
+with \fB{\fR and \fB}\fR by themselves ordinary characters. The
+parentheses for nested subexpressions are \fB\e(\fR and
+.QW \fB\e)\fR ,
+with \fB(\fR and \fB)\fR by themselves ordinary
+characters. \fB^\fR is an ordinary character except at the beginning
+of the RE or the beginning of a parenthesized subexpression, \fB$\fR
+is an ordinary character except at the end of the RE or the end of a
+parenthesized subexpression, and \fB*\fR is an ordinary character if
+it appears at the beginning of the RE or the beginning of a
+parenthesized subexpression (after a possible leading
+.QW \fB^\fR ).
+Finally, single-digit back references are available, and \fB\e<\fR and
+\fB\e>\fR are synonyms for
+.QW \fB[[:<:]]\fR
and
-\fB[[:>:]]\fR
-respectively;
-no other escapes are available.
-
+.QW \fB[[:>:]]\fR
+respectively; no other escapes are available.
.SH "SEE ALSO"
RegExp(3), regexp(n), regsub(n), lsearch(n), switch(n), text(n)
-
.SH KEYWORDS
match, regular expression, string
+.\" Local Variables:
+.\" mode: nroff
+.\" End:
diff --git a/doc/read.n b/doc/read.n
index 9584756..5398b08 100644
--- a/doc/read.n
+++ b/doc/read.n
@@ -30,13 +30,11 @@ the channel is configured to use a multi-byte encoding, then the
number of characters read may not be the same as the number of bytes
read.
.PP
-.VS
\fIChannelId\fR must be an identifier for an open channel such as the
Tcl standard input channel (\fBstdin\fR), the return value from an
invocation of \fBopen\fR or \fBsocket\fR, or the result of a channel
creation command provided by a Tcl extension. The channel must have
been opened for input.
-.VE
.PP
If \fIchannelId\fR is in nonblocking mode, the command may not read as
many characters as requested: once all available input has been read,
@@ -78,7 +76,7 @@ with each line in the file corresponding to an element in the list:
set fl [open /proc/meminfo]
set data [\fBread\fR $fl]
close $fl
-set lines [split $data \\n]
+set lines [split $data \en]
.CE
.SH "SEE ALSO"
diff --git a/doc/refchan.n b/doc/refchan.n
new file mode 100644
index 0000000..577c78a
--- /dev/null
+++ b/doc/refchan.n
@@ -0,0 +1,340 @@
+'\"
+'\" Copyright (c) 2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.so man.macros
+.TH refchan n 8.5 Tcl "Tcl Built-In Commands"
+.BS
+.\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+refchan \- Command handler API of reflected channels, version 1
+.SH SYNOPSIS
+\fBcmdPrefix \fIoption\fR ?\fIarg arg ...\fR?
+.BE
+.SH DESCRIPTION
+.PP
+The Tcl-level handler for a reflected channel has to be a command with
+subcommands (termed an \fIensemble\fR, as it is a command such as that
+created by \fBnamespace ensemble create\fR, though the implementation
+of handlers for reflected channel \fIis not\fR tied to \fBnamespace
+ensemble\fRs in any way). Note that \fIcmdPrefix\fR is whatever was
+specified in the call to \fBchan create\fR, and may consist of
+multiple arguments; this will be expanded to multiple words in place
+of the prefix.
+.PP
+Of all the possible subcommands, the handler \fImust\fR support
+\fBinitialize\fR, \fBfinalize\fR, and \fBwatch\fR. Support for the
+other subcommands is optional.
+.SS "MANDATORY SUBCOMMANDS"
+.TP
+\fIcmdPrefix \fBinitialize \fIchannelId mode\fR
+.
+An invocation of this subcommand will be the first call the
+\fIcmdPrefix\fR will receive for the specified new \fIchannelId\fR. It
+is the responsibility of this subcommand to set up any internal data
+structures required to keep track of the channel and its state.
+.RS
+.PP
+The return value of the method has to be a list containing the names
+of all subcommands supported by the \fIcmdPrefix\fR. This also tells
+the Tcl core which version of the API for reflected channels is used by
+this command handler.
+.PP
+Any error thrown by the method will abort the creation of the channel
+and no channel will be created. The thrown error will appear as error
+thrown by \fBchan create\fR. Any exception other than an \fBerror\fR
+(e.g. \fBbreak\fR, etc.) is treated as (and converted to) an error.
+.PP
+\fBNote:\fR If the creation of the channel was aborted due to failures
+here, then the \fBfinalize\fR subcommand will not be called.
+.PP
+The \fImode\fR argument tells the handler whether the channel was
+opened for reading, writing, or both. It is a list containing any of
+the strings \fBread\fR or \fBwrite\fR. The list will always
+contain at least one element.
+.PP
+The subcommand must throw an error if the chosen mode is not
+supported by the \fIcmdPrefix\fR.
+.RE
+.TP
+\fIcmdPrefix \fBfinalize \fIchannelId\fR
+.
+An invocation of this subcommand will be the last call the
+\fIcmdPrefix\fR will receive for the specified \fIchannelId\fR. It will
+be generated just before the destruction of the data structures of the
+channel held by the Tcl core. The command handler \fImust not\fR
+access the \fIchannelId\fR anymore in no way. Upon this subcommand being
+called, any internal resources allocated to this channel must be
+cleaned up.
+.RS
+.PP
+The return value of this subcommand is ignored.
+.PP
+If the subcommand throws an error the command which caused its
+invocation (usually \fBclose\fR) will appear to have thrown this
+error. Any exception beyond \fIerror\fR (e.g. \fIbreak\fR, etc.) is
+treated as (and converted to) an error.
+.PP
+This subcommand is not invoked if the creation of the channel was
+aborted during \fBinitialize\fR (See above).
+.RE
+.TP
+\fIcmdPrefix \fBwatch \fIchannelId eventspec\fR
+.
+This subcommand notifies the \fIcmdPrefix\fR that the specified
+\fIchannelId\fR is interested in the events listed in the
+\fIeventspec\fR. This argument is a list containing any of \fBread\fR
+and \fBwrite\fR. The list may be empty, which signals that the
+channel does not wish to be notified of any events. In that situation,
+the handler should disable event generation completely.
+.RS
+.PP
+\fBWarning:\fR Any return value of the subcommand is ignored. This
+includes all errors thrown by the subcommand, break, continue, and
+custom return codes.
+.PP
+This subcommand interacts with \fBchan postevent\fR. Trying to post an
+event which was not listed in the last call to \fBwatch\fR will cause
+\fBchan postevent\fR to throw an error.
+.RE
+.SS "OPTIONAL SUBCOMMANDS"
+.TP
+\fIcmdPrefix \fBread \fIchannelId count\fR
+.
+This \fIoptional\fR subcommand is called when the user requests data from the
+channel \fIchannelId\fR. \fIcount\fR specifies how many \fBbytes\fR have been
+requested. If the subcommand is not supported then it is not possible to read
+from the channel handled by the command.
+.RS
+.PP
+The return value of this subcommand is taken as the requested data
+\fIbytes\fR. If the returned data contains more bytes than requested,
+an error will be signaled and later thrown by the command which
+performed the read (usually \fBgets\fR or \fBread\fR). However,
+returning fewer bytes than requested is acceptable.
+.PP
+Note that returning nothing (0 bytes) is a signal to the higher layers
+that \fBEOF\fR has been reached on the channel. To signal that the
+channel is out of data right now, but has not yet reached \fBEOF\fR,
+it is necessary to throw the error "EAGAIN", i.e. to either
+.PP
+.CS
+return -code error EAGAIN
+.CE
+or
+.CS
+error EAGAIN
+.CE
+.PP
+For extensibility any error whose value is a negative integer number
+will cause the higher layers to set the C-level variable "\fBerrno\fR"
+to the absolute value of this number, signaling a system error. This
+means that both
+.PP
+.CS
+return -code error -11
+.CE
+and
+.CS
+error -11
+.CE
+.PP
+are equivalent to the examples above, using the more readable string "EAGAIN".
+No other error value has such a mapping to a symbolic string.
+.PP
+If the subcommand throws any other error, the command which caused its
+invocation (usually \fBgets\fR, or \fBread\fR) will appear to have
+thrown this error. Any exception beyond \fIerror\fR, (e.g.
+\fIbreak\fR, etc.) is treated as and converted to an error.
+.RE
+.TP
+\fIcmdPrefix \fBwrite \fIchannelId data\fR
+.
+This \fIoptional\fR subcommand is called when the user writes data to
+the channel \fIchannelId\fR. The \fIdata\fR argument contains \fIbytes\fR, not
+characters. Any type of transformation (EOL, encoding) configured for
+the channel has already been applied at this point. If this subcommand
+is not supported then it is not possible to write to the channel
+handled by the command.
+.RS
+.PP
+The return value of the subcommand is taken as the number of bytes
+written by the channel. Anything non-numeric will cause an error to be
+signaled and later thrown by the command which performed the write. A
+negative value implies that the write failed. Returning a value
+greater than the number of bytes given to the handler, or zero, is
+forbidden and will cause the Tcl core to throw an error.
+.PP
+To signal that the channel is not able to accept data for writing
+right now, it is necessary to throw the error "EAGAIN", i.e. to either
+.PP
+.CS
+return -code error EAGAIN
+.CE
+or
+.CS
+error EAGAIN
+.CE
+.PP
+For extensibility any error whose value is a negative integer number
+will cause the higher layers to set the C-level variable "\fBerrno\fR"
+to the absolute value of this number, signaling a system error.
+However, note that the exact mapping between these error numbers and
+their meanings is operating system dependent.
+.PP
+For example, while on Linux both
+.PP
+.CS
+return -code error -11
+.CE
+and
+.CS
+error -11
+.CE
+.PP
+are equivalent to the examples above, using the more readable string "EAGAIN",
+this is not true for BSD, where the equivalent number is -35.
+.PP
+The symbolic string however is the same across systems, and internally
+translated to the correct number. No other error value has such a mapping
+to a symbolic string.
+.PP
+If the subcommand throws any other error the command which caused its
+invocation (usually \fBputs\fR) will appear to have thrown this error.
+Any exception beyond \fIerror\fR (e.g.\ \fIbreak\fR, etc.) is treated
+as and converted to an error.
+.RE
+.TP
+\fIcmdPrefix \fBseek \fIchannelId offset base\fR
+.
+This \fIoptional\fR subcommand is responsible for the handling of
+\fBseek\fR and \fBtell\fR requests on the channel \fIchannelId\fR. If it is not
+supported then seeking will not be possible for the channel.
+.RS
+.PP
+The \fIbase\fR argument is one of
+.TP 10
+\fBstart\fR
+.
+Seeking is relative to the beginning of the channel.
+.TP 10
+\fBcurrent\fR
+.
+Seeking is relative to the current seek position.
+.TP 10
+\fBend\fR
+.
+Seeking is relative to the end of the channel.
+.PP
+The \fIbase\fR argument of the builtin \fBchan seek\fR command takes
+the same names.
+.PP
+The \fIoffset\fR is an integer number specifying the amount of
+\fBbytes\fR to seek forward or backward. A positive number should seek
+forward, and a negative number should seek backward.
+.PP
+A channel may provide only limited seeking. For example sockets can
+seek forward, but not backward.
+.PP
+The return value of the subcommand is taken as the (new) location of
+the channel, counted from the start. This has to be an integer number
+greater than or equal to zero.
+.PP
+If the subcommand throws an error the command which caused its
+invocation (usually \fBseek\fR, or \fBtell\fR) will appear to have
+thrown this error. Any exception beyond \fIerror\fR (e.g. \fIbreak\fR,
+etc.) is treated as and converted to an error.
+.PP
+The offset/base combination of 0/\fBcurrent\fR signals a \fBtell\fR
+request, i.e. seek nothing relative to the current location, making
+the new location identical to the current one, which is then returned.
+.RE
+.TP
+\fIcmdPrefix \fBconfigure \fIchannelId option value\fR
+.
+This \fIoptional\fR subcommand is for setting the type-specific options of
+channel \fIchannelId\fR. The \fIoption\fR argument indicates the option to be
+written, and the \fIvalue\fR argument indicates the value to set the option to.
+.RS
+.PP
+This subcommand will never try to update more than one option at a
+time; that is behavior implemented in the Tcl channel core.
+.PP
+The return value of the subcommand is ignored.
+.PP
+If the subcommand throws an error the command which performed the
+(re)configuration or query (usually \fBfconfigure\fR or \fBchan
+configure\fR) will appear to have thrown this error. Any exception
+beyond \fIerror\fR (e.g. \fIbreak\fR, etc.) is treated as and
+converted to an error.
+.RE
+.TP
+\fIcmdPrefix \fBcget \fIchannelId option\fR
+.
+This \fIoptional\fR subcommand is used when reading a single type-specific
+option of channel \fIchannelId\fR. If this subcommand is supported then the
+subcommand \fBcgetall\fR must be supported as well.
+.RS
+.PP
+The subcommand should return the value of the specified \fIoption\fR.
+.PP
+If the subcommand throws an error, the command which performed the
+(re)configuration or query (usually \fBfconfigure\fR) will appear to
+have thrown this error. Any exception beyond \fIerror\fR (e.g.
+\fIbreak\fR, etc.) is treated as and converted to an error.
+.RE
+.TP
+\fIcmdPrefix \fBcgetall \fIchannelId\fR
+.
+This \fIoptional\fR subcommand is used for reading all type-specific options
+of channel \fIchannelId\fR. If this subcommand is supported then the
+subcommand \fBcget\fR has to be supported as well.
+.RS
+.PP
+The subcommand should return a list of all options and their values.
+This list must have an even number of elements.
+.PP
+If the subcommand throws an error the command which performed the
+(re)configuration or query (usually \fBfconfigure\fR) will appear to
+have thrown this error. Any exception beyond \fIerror\fR (e.g.
+\fIbreak\fR, etc.) is treated as and converted to an error.
+.RE
+.TP
+\fIcmdPrefix \fBblocking \fIchannelId mode\fR
+.
+This \fIoptional\fR subcommand handles changes to the blocking mode of the
+channel \fIchannelId\fR. The \fImode\fR is a boolean flag. A true value means
+that the channel has to be set to blocking, and a false value means that the
+channel should be non-blocking.
+.RS
+.PP
+The return value of the subcommand is ignored.
+.PP
+If the subcommand throws an error the command which caused its
+invocation (usually \fBfconfigure\fR) will appear to have thrown this
+error. Any exception beyond \fIerror\fR (e.g. \fIbreak\fR, etc.) is
+treated as and converted to an error.
+.RE
+.SH NOTES
+Some of the functions supported in channels defined in Tcl's C
+interface are not available to channels reflected to the Tcl level.
+.PP
+The function \fBTcl_DriverGetHandleProc\fR is not supported; i.e.
+reflected channels do not have OS specific handles.
+.PP
+The function \fBTcl_DriverHandlerProc\fR is not supported. This driver
+function is relevant only for stacked channels, i.e. transformations.
+Reflected channels are always base channels, not transformations.
+.PP
+The function \fBTcl_DriverFlushProc\fR is not supported. This is
+because the current generic I/O layer of Tcl does not use this
+function anywhere at all. Therefore support at the Tcl level makes no
+sense either. This may be altered in the future (through extending the
+API defined here and changing its version number) should the function
+be used at some time in the future.
+.SH "SEE ALSO"
+chan(n)
+.SH KEYWORDS
+channel, reflection
diff --git a/doc/regexp.n b/doc/regexp.n
index a1692bd..100f0d8 100644
--- a/doc/regexp.n
+++ b/doc/regexp.n
@@ -18,8 +18,8 @@ regexp \- Match a regular expression against a string
.SH DESCRIPTION
.PP
Determines whether the regular expression \fIexp\fR matches part or
-all of \fIstring\fR and returns 1 if it does, 0 if it doesn't, unless
-\fB-inline\fR is specified (see below).
+all of \fIstring\fR and returns 1 if it does, 0 if it does not, unless
+\fB\-inline\fR is specified (see below).
(Regular expression matching is described in the \fBre_syntax\fR
reference page.)
.LP
@@ -60,20 +60,37 @@ range of characters.
\fB\-line\fR
Enables newline-sensitive matching. By default, newline is a
completely ordinary character with no special meaning. With this
-flag, `[^' bracket expressions and `.' never match newline, `^'
+flag,
+.QW [^
+bracket expressions and
+.QW .
+never match newline,
+.QW ^
matches an empty string after any newline in addition to its normal
-function, and `$' matches an empty string before any newline in
+function, and
+.QW $
+matches an empty string before any newline in
addition to its normal function. This flag is equivalent to
specifying both \fB\-linestop\fR and \fB\-lineanchor\fR, or the
\fB(?n)\fR embedded option (see the \fBre_syntax\fR manual page).
.TP 15
\fB\-linestop\fR
-Changes the behavior of `[^' bracket expressions and `.' so that they
+Changes the behavior of
+.QW [^
+bracket expressions and
+.QW .
+so that they
stop at newlines. This is the same as specifying the \fB(?p)\fR
embedded option (see the \fBre_syntax\fR manual page).
.TP 15
\fB\-lineanchor\fR
-Changes the behavior of `^' and `$' (the ``anchors'') so they match the
+Changes the behavior of
+.QW ^
+and
+.QW $
+(the
+.QW anchors )
+so they match the
beginning and end of a line respectively. This is the same as
specifying the \fB(?w)\fR embedded option (see the \fBre_syntax\fR
manual page).
@@ -81,7 +98,6 @@ manual page).
\fB\-nocase\fR
Causes upper-case characters in \fIstring\fR to be treated as
lower case during the matching process.
-.VS 8.3
.TP 15
\fB\-all\fR
Causes the regular expression to be matched as many times as possible
@@ -91,69 +107,85 @@ the last match only.
.TP 15
\fB\-inline\fR
Causes the command to return, as a list, the data that would otherwise
-be placed in match variables. When using \fB-inline\fR,
-match variables may not be specified. If used with \fB-all\fR, the
+be placed in match variables. When using \fB\-inline\fR,
+match variables may not be specified. If used with \fB\-all\fR, the
list will be concatenated at each iteration, such that a flat list is
always returned. For each match iteration, the command will append the
overall match data, plus one element for each subexpression in the
regular expression. Examples are:
.CS
- regexp -inline -- {\\w(\\w)} " inlined "
- => {in n}
- regexp -all -inline -- {\\w(\\w)} " inlined "
- => {in n li i ne e}
+\fBregexp\fR -inline -- {\ew(\ew)} " inlined "
+ \fI\(-> in n\fR
+\fBregexp\fR -all -inline -- {\ew(\ew)} " inlined "
+ \fI\(-> in n li i ne e\fR
.CE
.TP 15
\fB\-start\fR \fIindex\fR
Specifies a character index offset into the string to start
-matching the regular expression at. When using this switch, `^'
-will not match the beginning of the line, and \\A will still
+matching the regular expression at.
+.VS 8.5
+The \fIindex\fR value is interpreted in the same manner
+as the \fIindex\fR argument to \fBstring index\fR.
+.VE 8.5
+When using this switch,
+.QW ^
+will not match the beginning of the line, and \eA will still
match the start of the string at \fIindex\fR. If \fB\-indices\fR
is specified, the indices will be indexed starting from the
absolute beginning of the input string.
\fIindex\fR will be constrained to the bounds of the input string.
-.VE 8.3
.TP 15
\fB\-\|\-\fR
Marks the end of switches. The argument following this one will
be treated as \fIexp\fR even if it starts with a \fB\-\fR.
.PP
-If there are more \fIsubMatchVar\fR's than parenthesized
+If there are more \fIsubMatchVar\fRs than parenthesized
subexpressions within \fIexp\fR, or if a particular subexpression
-in \fIexp\fR doesn't match the string (e.g. because it was in a
-portion of the expression that wasn't matched), then the corresponding
-\fIsubMatchVar\fR will be set to ``\fB\-1 \-1\fR'' if \fB\-indices\fR
-has been specified or to an empty string otherwise.
+in \fIexp\fR does not match the string (e.g. because it was in a
+portion of the expression that was not matched), then the corresponding
+\fIsubMatchVar\fR will be set to
+.QW "\fB\-1 \-1\fR"
+if \fB\-indices\fR has been specified or to an empty string otherwise.
.SH EXAMPLES
+.PP
Find the first occurrence of a word starting with \fBfoo\fR in a
string that is not actually an instance of \fBfoobar\fR, and get the
letters following it up to the end of the word into a variable:
.CS
-\fBregexp\fR {\\<foo(?!bar\\>)(\\w*)} $string \-> restOfWord
+\fBregexp\fR {\emfoo(?!bar\eM)(\ew*)} $string \-> restOfWord
.CE
Note that the whole matched substring has been placed in the variable
-\fB\->\fR which is a name chosen to look nice given that we are not
+.QW \fB\->\fR ,
+which is a name chosen to look nice given that we are not
actually interested in its contents.
.PP
Find the index of the word \fBbadger\fR (in any case) within a string
and store that in the variable \fBlocation\fR:
.CS
-\fBregexp\fR \-indices {(?i)\\<badger\\>} $string location
+\fBregexp\fR \-indices {(?i)\embadger\eM} $string location
+.CE
+This could also be written as a \fIbasic\fR regular expression (as opposed
+to using the default syntax of \fIadvanced\fR regular expressions) match by
+prefixing the expression with a suitable flag:
+.CS
+\fBregexp\fR \-indices {(?ib)\e<badger\e>} $string location
.CE
.PP
-Count the number of octal digits in a string:
+This counts the number of octal digits in a string:
.CS
\fBregexp\fR \-all {[0\-7]} $string
.CE
.PP
-List all words (consisting of all sequences of non-whitespace
-characters) in a string:
+This lists all words (consisting of all sequences of non-whitespace
+characters) in a string, and is useful as a more powerful version of the
+\fBsplit\fR command:
.CS
-\fBregexp\fR \-all \-inline {\\S+} $string
+\fBregexp\fR \-all \-inline {\eS+} $string
.CE
-
.SH "SEE ALSO"
-re_syntax(n), regsub(n)
-
+re_syntax(n), regsub(n),
+.VS 8.5
+string(n)
+.VE
.SH KEYWORDS
-match, regular expression, string
+match, parsing, pattern, regular expression, splitting, string
diff --git a/doc/registry.n b/doc/registry.n
index 6809cb7..e4371e6 100644
--- a/doc/registry.n
+++ b/doc/registry.n
@@ -17,7 +17,6 @@ registry \- Manipulate the Windows registry
.sp
\fBregistry \fIoption\fR \fIkeyName\fR ?\fIarg arg ...\fR?
.BE
-
.SH DESCRIPTION
.PP
The \fBregistry\fR package provides a general set of operations for
@@ -28,29 +27,28 @@ as a corrupted registry can leave your system in an unusable state.
.PP
\fIKeyName\fR is the name of a registry key. Registry keys must be
one of the following forms:
-.IP
+.RS
+.PP
\fB\e\e\fIhostname\fB\e\fIrootname\fB\e\fIkeypath\fR
-.IP
+.PP
\fIrootname\fB\e\fIkeypath\fR
-.IP
+.PP
\fIrootname\fR
+.RE
.PP
\fIHostname\fR specifies the name of any valid Windows
host that exports its registry. The \fIrootname\fR component must be
one of \fBHKEY_LOCAL_MACHINE\fR, \fBHKEY_USERS\fR,
-.VS
\fBHKEY_CLASSES_ROOT\fR, \fBHKEY_CURRENT_USER\fR,
\fBHKEY_CURRENT_CONFIG\fR, \fBHKEY_PERFORMANCE_DATA\fR, or
\fBHKEY_DYN_DATA\fR. The \fIkeypath\fR can be one or more
-.VE
registry key names separated by backslash (\fB\e\fR) characters.
.PP
\fIOption\fR indicates what to do with the registry key name. Any
unique abbreviation for \fIoption\fR is acceptable. The valid options
are:
-.VS 8.4
.TP
-\fBregistry broadcast \fIkeyName\fR ?\fI-timeout milliseconds\fR?
+\fBregistry broadcast \fIkeyName\fR ?\fB\-timeout \fImilliseconds\fR?
.
Sends a broadcast message to the system and running programs to notify them
of certain updates. This is necessary to propagate changes to key registry
@@ -59,13 +57,22 @@ milliseconds, to wait for applications to respond to the broadcast message.
It defaults to 3000. The following example demonstrates how to add a path
to the global Environment and notify applications of the change without
requiring a logoff/logon step (assumes admin privileges):
+.RS
+.PP
.CS
-set regPath {HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment}
-set curPath [registry get $regPath "Path"]
-registry set $regPath "Path" "$curPath;$addPath"
-registry broadcast "Environment"
+set regPath [join {
+ HKEY_LOCAL_MACHINE
+ SYSTEM
+ CurrentControlSet
+ Control
+ {Session Manager}
+ Environment
+} "\e\e"]
+set curPath [\fBregistry get\fR $regPath "Path"]
+\fBregistry set\fR $regPath "Path" "$curPath;$addPath"
+\fBregistry broadcast\fR "Environment"
.CE
-.VE 8.4
+.RE
.TP
\fBregistry delete \fIkeyName\fR ?\fIvalueName\fR?
.
@@ -81,11 +88,11 @@ did not exist, the command has no effect.
Returns the data associated with the value \fIvalueName\fR under the key
\fIkeyName\fR. If either the key or the value does not exist, then an
error is generated. For more details on the format of the returned
-data, see SUPPORTED TYPES, below.
+data, see \fBSUPPORTED TYPES\fR, below.
.TP
\fBregistry keys \fIkeyName\fR ?\fIpattern\fR?
.
-If \fIpattern\fR isn't specified, returns a list of names of all the
+If \fIpattern\fR is not specified, returns a list of names of all the
subkeys of \fIkeyName\fR. If \fIpattern\fR is specified, only those
names matching \fIpattern\fR are returned. Matching is determined
using the same rules as for \fBstring\fR \fBmatch\fR. If the
@@ -93,27 +100,26 @@ specified \fIkeyName\fR does not exist, then an error is generated.
.TP
\fBregistry set \fIkeyName\fR ?\fIvalueName data \fR?\fItype\fR??
.
-If \fIvalueName\fR isn't specified, creates the key \fIkeyName\fR if
-it doesn't already exist. If \fIvalueName\fR is specified, creates
+If \fIvalueName\fR is not specified, creates the key \fIkeyName\fR if
+it does not already exist. If \fIvalueName\fR is specified, creates
the key \fIkeyName\fR and value \fIvalueName\fR if necessary. The
contents of \fIvalueName\fR are set to \fIdata\fR with the type
-indicated by \fItype\fR. If \fItype\fR isn't specified, the type
+indicated by \fItype\fR. If \fItype\fR is not specified, the type
\fBsz\fR is assumed. For more details on the data and type arguments,
-see SUPPORTED TYPES below.
+see \fBSUPPORTED TYPES\fR below.
.TP
\fBregistry type \fIkeyName valueName\fR
.
Returns the type of the value \fIvalueName\fR in the key
\fIkeyName\fR. For more information on the possible types, see
-SUPPORTED TYPES, below.
+\fBSUPPORTED TYPES\fR, below.
.TP
\fBregistry values \fIkeyName\fR ?\fIpattern\fR?
.
-If \fIpattern\fR isn't specified, returns a list of names of all the
+If \fIpattern\fR is not specified, returns a list of names of all the
values of \fIkeyName\fR. If \fIpattern\fR is specified, only those
names matching \fIpattern\fR are returned. Matching is determined
using the same rules as for \fBstring\fR \fBmatch\fR.
-
.SH "SUPPORTED TYPES"
Each value under a key in the registry contains some data of a
particular type in a type-specific representation. The \fBregistry\fR
@@ -145,8 +151,9 @@ represented in Tcl as a string.
.
The registry value contains a null-terminated string that contains
unexpanded references to environment variables in the normal Windows
-style (for example, "%PATH%"). The data is represented in Tcl as a
-string.
+style (for example,
+.QW %PATH% ).
+The data is represented in Tcl as a string.
.TP
\fBdword\fR
.
@@ -182,6 +189,7 @@ The registry command is only available on Windows.
.SH EXAMPLE
Print out how double-clicking on a Tcl script file will invoke a Tcl
interpreter:
+.PP
.CS
package require registry
set ext .tcl
@@ -195,6 +203,5 @@ set command [\fBregistry get\fR $path {}]
puts "$ext opens with $command"
.CE
-
.SH KEYWORDS
registry
diff --git a/doc/regsub.n b/doc/regsub.n
index 4e5e88d..5adfd61 100644
--- a/doc/regsub.n
+++ b/doc/regsub.n
@@ -13,40 +13,41 @@
.SH NAME
regsub \- Perform substitutions based on regular expression pattern matching
.SH SYNOPSIS
-.VS 8.4
\fBregsub \fR?\fIswitches\fR? \fIexp string subSpec \fR?\fIvarName\fR?
-.VE 8.4
.BE
-
.SH DESCRIPTION
.PP
This command matches the regular expression \fIexp\fR against
\fIstring\fR,
-.VS 8.4
and either copies \fIstring\fR to the variable whose name is
given by \fIvarName\fR or returns \fIstring\fR if \fIvarName\fR is not
present.
-.VE 8.4
(Regular expression matching is described in the \fBre_syntax\fR
reference page.)
If there is a match, then while copying \fIstring\fR to \fIvarName\fR
-.VS 8.4
(or to the result of this command if \fIvarName\fR is not present)
-.VE 8.4
the portion of \fIstring\fR that
matched \fIexp\fR is replaced with \fIsubSpec\fR.
-If \fIsubSpec\fR contains a ``&'' or ``\e0'', then it is replaced
-in the substitution with the portion of \fIstring\fR that
-matched \fIexp\fR.
-If \fIsubSpec\fR contains a ``\e\fIn\fR'', where \fIn\fR is a digit
+If \fIsubSpec\fR contains a
+.QW &
+or
+.QW \e0 ,
+then it is replaced in the substitution with the portion of
+\fIstring\fR that matched \fIexp\fR.
+If \fIsubSpec\fR contains a
+.QW \e\fIn\fR ,
+where \fIn\fR is a digit
between 1 and 9, then it is replaced in the substitution with
-the portion of \fIstring\fR that matched the \fIn\fR-th
+the portion of \fIstring\fR that matched the \fIn\fR'th
parenthesized subexpression of \fIexp\fR.
Additional backslashes may be used in \fIsubSpec\fR to prevent special
-interpretation of ``&'' or ``\e0'' or ``\e\fIn\fR'' or
-backslash.
+interpretation of
+.QW & ,
+.QW \e0 ,
+.QW \e\fIn\fR
+and backslashes.
The use of backslashes in \fIsubSpec\fR tends to interact badly
-with the Tcl parser's use of backslashes, so it's generally
+with the Tcl parser's use of backslashes, so it is generally
safest to enclose \fIsubSpec\fR in braces if it includes
backslashes.
.LP
@@ -59,7 +60,10 @@ All ranges in \fIstring\fR that match \fIexp\fR are found and
substitution is performed for each of these ranges.
Without this switch only the first
matching range is found and substituted.
-If \fB\-all\fR is specified, then ``&'' and ``\e\fIn\fR''
+If \fB\-all\fR is specified, then
+.QW &
+and
+.QW \e\fIn\fR
sequences are handled for each substitution using the information
from the corresponding match.
.TP 15
@@ -70,21 +74,37 @@ the \fB(?x)\fR embedded option (see the \fBre_syntax\fR manual page).
.TP 15
\fB\-line\fR
Enables newline-sensitive matching. By default, newline is a
-completely ordinary character with no special meaning. With this
-flag, `[^' bracket expressions and `.' never match newline, `^'
+completely ordinary character with no special meaning. With this flag,
+.QW [^
+bracket expressions and
+.QW .
+never match newline,
+.QW ^
matches an empty string after any newline in addition to its normal
-function, and `$' matches an empty string before any newline in
+function, and
+.QW $
+matches an empty string before any newline in
addition to its normal function. This flag is equivalent to
specifying both \fB\-linestop\fR and \fB\-lineanchor\fR, or the
\fB(?n)\fR embedded option (see the \fBre_syntax\fR manual page).
.TP 15
\fB\-linestop\fR
-Changes the behavior of `[^' bracket expressions and `.' so that they
+Changes the behavior of
+.QW [^
+bracket expressions and
+.QW .
+so that they
stop at newlines. This is the same as specifying the \fB(?p)\fR
embedded option (see the \fBre_syntax\fR manual page).
.TP 15
\fB\-lineanchor\fR
-Changes the behavior of `^' and `$' (the ``anchors'') so they match the
+Changes the behavior of
+.QW ^
+and
+.QW $
+(the
+.QW anchors )
+so they match the
beginning and end of a line respectively. This is the same as
specifying the \fB(?w)\fR embedded option (see the \fBre_syntax\fR
manual page).
@@ -96,8 +116,14 @@ by \fIsubSpec\fR use the original unconverted form of \fIstring\fR.
.TP 10
\fB\-start\fR \fIindex\fR
Specifies a character index offset into the string to start
-matching the regular expression at. When using this switch, `^'
-will not match the beginning of the line, and \\A will still
+matching the regular expression at.
+.VS 8.5
+The \fIindex\fR value is interpreted in the same manner
+as the \fIindex\fR argument to \fBstring index\fR.
+.VE 8.5
+When using this switch,
+.QW ^
+will not match the beginning of the line, and \eA will still
match the start of the string at \fIindex\fR.
\fIindex\fR will be constrained to the bounds of the input string.
.TP 10
@@ -105,42 +131,51 @@ match the start of the string at \fIindex\fR.
Marks the end of switches. The argument following this one will
be treated as \fIexp\fR even if it starts with a \fB\-\fR.
.PP
-.VS 8.4
If \fIvarName\fR is supplied, the command returns a count of the
number of matching ranges that were found and replaced, otherwise the
string after replacement is returned.
-.VE 8.4
See the manual entry for \fBregexp\fR for details on the interpretation
of regular expressions.
.SH EXAMPLES
+.PP
Replace (in the string in variable \fIstring\fR) every instance of
\fBfoo\fR which is a word by itself with \fBbar\fR:
.CS
-\fBregsub\fR -all {\e<foo\e>} $string bar string
+\fBregsub\fR -all {\emfoo\eM} $string bar string
+.CE
+or (using the
+.QW "basic regular expression"
+syntax):
+.CS
+\fBregsub\fR -all {(?b)\e<foo\e>} $string bar string
.CE
.PP
Insert double-quotes around the first instance of the word
-\fBinteresting\fR, however it is capitalised.
+\fBinteresting\fR, however it is capitalized.
.CS
-\fBregsub\fR -nocase {\e<interesting\e>} $string {"&"} string
+\fBregsub\fR -nocase {\eyinteresting\ey} $string {"&"} string
.CE
.PP
Convert all non-ASCII and Tcl-significant characters into \eu escape
sequences by using \fBregsub\fR and \fBsubst\fR in combination:
.CS
-# This RE is just a character class for everything "bad"
-set RE {[][{}\e$\es\eu0100-\euffff]}
+# This RE is just a character class for almost everything "bad"
+set RE {[][{};#\e\e\e$ \er\et\eu0080-\euffff]}
# We will substitute with a fragment of Tcl script in brackets
set substitution {[format \e\e\e\eu%04x [scan "\e\e&" %c]]}
# Now we apply the substitution to get a subst-string that
-# will perform the computational parts of the conversion.
-set quoted [subst [\fBregsub\fR -all $RE $string $substitution]]
+# will perform the computational parts of the conversion. Note
+# that newline is handled specially through \fBstring map\fR since
+# backslash-newline is a special sequence.
+set quoted [subst [string map {\en {\e\eu000a}} \e
+ [\fBregsub\fR -all $RE $string $substitution]]]
.CE
-
.SH "SEE ALSO"
-regexp(n), re_syntax(n), subst(n)
-
+regexp(n), re_syntax(n), subst(n),
+.VS 8.5
+string(n)
+.VE
.SH KEYWORDS
-match, pattern, regular expression, substitute
+match, pattern, quoting, regular expression, substitute
diff --git a/doc/resource.n b/doc/resource.n
deleted file mode 100644
index d8d2fbf..0000000
--- a/doc/resource.n
+++ /dev/null
@@ -1,154 +0,0 @@
-'\"
-'\" Copyright (c) 1997 Sun Microsystems, Inc.
-'\"
-'\" See the file "license.terms" for information on usage and redistribution
-'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-'\"
-.so man.macros
-.TH resource n 8.0 Tcl "Tcl Built-In Commands"
-.BS
-'\" Note: do not modify the .SH NAME line immediately below!
-.SH NAME
-resource \- Manipulate Macintosh resources
-.SH SYNOPSIS
-\fBresource \fIoption\fR ?\fIarg arg ...\fR?
-.BE
-
-.SH DESCRIPTION
-.PP
-The \fBresource\fR command provides some generic operations for
-dealing with Macintosh resources. This command is only supported on
-the Macintosh platform. Each Macintosh file consists of two
-\fIforks\fR: a \fIdata\fR fork and a \fIresource\fR fork. You use the
-normal open, puts, close, etc. commands to manipulate the data fork.
-You must use this command, however, to interact with the resource
-fork. \fIOption\fR indicates what resource command to perform. Any
-unique abbreviation for \fIoption\fR is acceptable. The valid options
-are:
-.TP
-\fBresource close \fIrsrcRef\fR
-Closes the given resource reference (obtained from \fBresource
-open\fR). Resources from that resource file will no longer be
-available.
-.TP
-\fBresource delete\fR ?\fIoptions\fR? \fIresourceType\fR
-This command will delete the resource specified by \fIoptions\fR and
-type \fIresourceType\fR (see RESOURCE TYPES below). The options
-give you several ways to specify the resource to be deleted.
-.RS
-.TP
-\fB\-id\fR \fIresourceId\fR
-If the \fB-id\fR option is given the id \fIresourceId\fR (see RESOURCE
-IDS below) is used to specify the resource to be deleted. The id must
-be a number - to specify a name use the \fB\-name\fR option.
-.TP
-\fB\-name\fR \fIresourceName\fR
-If \fB-name\fR is specified, the resource named
-\fIresourceName\fR will be deleted. If the \fB-id\fR is also
-provided, then there must be a resource with BOTH this name and
-this id. If no name is provided, then the id will be used regardless
-of the name of the actual resource.
-.TP
-\fB\-file\fR \fIresourceRef\fR
-If the \fB-file\fR option is specified then the resource will be
-deleted from the file pointed to by \fIresourceRef\fR. Otherwise the
-first resource with the given \fIresourceName\fR and or
-\fIresourceId\fR which is found on the resource file path will be
-deleted. To inspect the file path, use the \fIresource files\fR command.
-.RE
-.TP
-\fBresource files ?\fIresourceRef\fR?
-If \fIresourceRef\fRis not provided, this command returns a Tcl list
-of the resource references for all the currently open resource files.
-The list is in the normal Macintosh search order for resources. If
-\fIresourceRef\fR is specified, the command will
-return the path to the file whose resource fork is represented by that
-token.
-.TP
-\fBresource list \fIresourceType\fR ?\fIresourceRef\fR?
-List all of the resources ids of type \fIresourceType\fR (see RESOURCE
-TYPES below). If \fIresourceRef\fR is specified then the command will
-limit the search to that particular resource file. Otherwise, all
-resource files currently opened by the application will be searched.
-A Tcl list of either the resource name's or resource id's of the found
-resources will be returned. See the RESOURCE IDS section below for
-more details about what a resource id is.
-.TP
-\fBresource open \fIfileName\fR ?\fIaccess\fR?
-Open the resource for the file \fIfileName\fR. Standard file access
-permissions may also be specified (see the manual entry for \fBopen\fR
-for details). A resource reference (\fIresourceRef\fR) is returned
-that can be used by the other resource commands. An error can occur
-if the file doesn't exist or the file does not have a resource fork.
-However, if you open the file with write permissions the file and/or
-resource fork will be created instead of generating an error.
-.TP
-\fBresource read \fIresourceType\fR \fIresourceId\fR ?\fIresourceRef\fR?
-Read the entire resource of type \fIresourceType\fR (see RESOURCE
-TYPES below) and the name or id of \fIresourceId\fR (see RESOURCE IDS
-below) into memory and return the result. If \fIresourceRef\fR is
-specified we limit our search to that resource file, otherwise we
-search all open resource forks in the application. It is important to
-note that most Macintosh resource use a binary format and the data
-returned from this command may have embedded NULLs or other non-ASCII
-data.
-.TP
-\fBresource types ?\fIresourceRef\fR?
-This command returns a Tcl list of all resource types (see RESOURCE
-TYPES below) found in the resource file pointed to by
-\fIresourceRef\fR. If \fIresourceRef\fR is not specified it will
-return all the resource types found in every resource file currently
-opened by the application.
-.TP
-\fBresource write\fR ?\fIoptions\fR? \fIresourceType\fR \fIdata\fR
-This command will write the passed in \fIdata\fR as a new resource of
-type \fIresourceType\fR (see RESOURCE TYPES below). Several options
-are available that describe where and how the resource is stored.
-.RS
-.TP
-\fB\-id\fR \fIresourceId\fR
-If the \fB-id\fR option is given the id \fIresourceId\fR (see RESOURCE
-IDS below) is used for the new resource, otherwise a unique id will be
-generated that will not conflict with any existing resource. However,
-the id must be a number - to specify a name use the \fB\-name\fR option.
-.TP
-\fB\-name\fR \fIresourceName\fR
-If \fB-name\fR is specified the resource will be named
-\fIresourceName\fR, otherwise it will have the empty string as the
-name.
-.TP
-\fB\-file\fR \fIresourceRef\fR
-If the \fB-file\fR option is specified then the resource will be
-written in the file pointed to by \fIresourceRef\fR, otherwise the
-most recently open resource will be used.
-.TP
-\fB\-force\fR
-If the target resource already exists, then by default Tcl will not
-overwrite it, but raise an error instead. Use the -force flag to
-force overwriting the extant resource.
-.RE
-
-.SH "RESOURCE TYPES"
-Resource types are defined as a four character string that is then
-mapped to an underlying id. For example, \fBTEXT\fR refers to the
-Macintosh resource type for text. The type \fBSTR#\fR is a list of
-counted strings. All Macintosh resources must be of some type. See
-Macintosh documentation for a more complete list of resource types
-that are commonly used.
-
-.SH "RESOURCE IDS"
-For this command the notion of a resource id actually refers to two
-ideas in Macintosh resources. Every place you can use a resource Id
-you can use either the resource name or a resource number. Names are
-always searched or returned in preference to numbers. For example,
-the \fBresource list\fR command will return names if they exist or
-numbers if the name is NULL.
-
-.SH "PORTABILITY ISSUES"
-The resource command is only available on Macintosh.
-
-.SH "SEE ALSO"
-open(n)
-
-.SH KEYWORDS
-open, resource
diff --git a/doc/return.n b/doc/return.n
index 25cf8b4..b08de4a 100644
--- a/doc/return.n
+++ b/doc/return.n
@@ -1,32 +1,45 @@
'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
+'\" Contributions from Don Porter, NIST, 2003. (not subject to US copyright)
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
-.TH return n 7.0 Tcl "Tcl Built-In Commands"
+.TH return n 8.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
-return \- Return from a procedure
+return \- Return from a procedure, or set return code of a script
.SH SYNOPSIS
-\fBreturn \fR?\fB\-code \fIcode\fR? ?\fB\-errorinfo \fIinfo\fR? ?\fB\-errorcode\fI code\fR? ?\fIstring\fR?
+\fBreturn \fR?\fIresult\fR?
+.sp
+\fBreturn \fR?\fB\-code \fIcode\fR? ?\fIresult\fR?
+.sp
+\fBreturn \fR?\fIoption value \fR...? ?\fIresult\fR?
.BE
-
.SH DESCRIPTION
.PP
-Return immediately from the current procedure
-(or top-level command or \fBsource\fR command),
-with \fIstring\fR as the return value. If \fIstring\fR is not specified then
-an empty string will be returned as result.
+In its simplest usage, the \fBreturn\fR command is used without options
+in the body of a procedure to immediately return control to the caller
+of the procedure. If a \fIresult\fR argument is provided, its value
+becomes the result of the procedure passed back to the caller.
+If \fIresult\fR is not specified then an empty string will be returned
+to the caller as the result of the procedure.
+.PP
+The \fBreturn\fR command serves a similar function within script
+files that are evaluated by the \fBsource\fR command. When \fBsource\fR
+evaluates the contents of a file as a script, an invocation of
+the \fBreturn\fR command will cause script evaluation
+to immediately cease, and the value \fIresult\fR (or an empty string)
+will be returned as the result of the \fBsource\fR command.
.SH "EXCEPTIONAL RETURN CODES"
.PP
In addition to the result of a procedure, the return
code of a procedure may also be set by \fBreturn\fR
-through use of the \fB-code\fR option.
-In the usual case where the \fB\-code\fR option isn't
+through use of the \fB\-code\fR option.
+In the usual case where the \fB\-code\fR option is not
specified the procedure will return normally.
However, the \fB\-code\fR option may be used to generate an
exceptional return from the procedure.
@@ -61,29 +74,135 @@ were the command \fBcontinue\fR.
\fIValue\fR must be an integer; it will be returned as the
return code for the current procedure.
.LP
-The \fB\-code\fR option is rarely used.
-It is provided so that procedures that implement
-new control structures can reflect exceptional conditions back to
-their callers.
-.PP
-Two additional options, \fB\-errorinfo\fR and \fB\-errorcode\fR,
-may be used to provide additional information during error
-returns.
-These options are ignored unless \fIcode\fR is \fBerror\fR.
-.PP
-The \fB\-errorinfo\fR option specifies an initial stack
-trace for the \fBerrorInfo\fR variable; if it is not specified then
-the stack trace left in \fBerrorInfo\fR will include the call to
-the procedure and higher levels on the stack but it will not include
-any information about the context of the error within the procedure.
-Typically the \fIinfo\fR value is supplied from the value left
-in \fBerrorInfo\fR after a \fBcatch\fR command trapped an error within
-the procedure.
-.PP
-If the \fB\-errorcode\fR option is specified then \fIcode\fR provides
-a value for the \fBerrorCode\fR variable.
-If the option is not specified then \fBerrorCode\fR will
-default to \fBNONE\fR.
+When a procedure wants to signal that it has received invalid
+arguments from its caller, it may use \fBreturn -code error\fR
+with \fIresult\fR set to a suitable error message. Otherwise
+usage of the \fBreturn -code\fR option is mostly limited to
+procedures that implement a new control structure.
+.PP
+The \fBreturn \-code\fR command acts similarly within script
+files that are evaluated by the \fBsource\fR command. During the
+evaluation of the contents of a file as a script by \fBsource\fR,
+an invocation of the \fBreturn \-code \fIcode\fR command will cause
+the return code of \fBsource\fR to be \fIcode\fR.
+.SH "RETURN OPTIONS"
+.PP
+.VS 8.5
+In addition to a result and a return code, evaluation of a command
+in Tcl also produces a dictionary of return options. In general
+usage, all \fIoption value\fR pairs given as arguments to \fBreturn\fR
+become entries in the return options dictionary, and any values at all
+are acceptable except as noted below. The \fBcatch\fR command may be
+used to capture all of this information \(em the return code, the result,
+and the return options dictionary \(em that arise from evaluation of a
+script.
+.VE 8.5
+.PP
+As documented above, the \fB\-code\fR entry in the return options dictionary
+receives special treatment by Tcl. There are other return options also
+recognized and treated specially by Tcl. They are:
+.TP
+\fB\-errorcode \fIlist\fR
+The \fB\-errorcode\fR option receives special treatment only when the value
+of the \fB\-code\fR option is \fBTCL_ERROR\fR. Then the \fIlist\fR value
+is meant to be additional information about the error,
+presented as a Tcl list for further processing by programs.
+If no \fB\-errorcode\fR option is provided to \fBreturn\fR when
+the \fB\-code error\fR option is provided, Tcl will set the value
+of the \fB\-errorcode\fR entry in the return options dictionary
+to the default value of \fBNONE\fR. The \fB\-errorcode\fR return
+option will also be stored in the global variable \fBerrorCode\fR.
+.TP
+\fB\-errorinfo \fIinfo\fR
+The \fB\-errorinfo\fR option receives special treatment only when the value
+of the \fB\-code\fR option is \fBTCL_ERROR\fR. Then \fIinfo\fR is the initial
+stack trace, meant to provide to a human reader additional information
+about the context in which the error occurred. The stack trace will
+also be stored in the global variable \fBerrorInfo\fR.
+If no \fB\-errorinfo\fR option is provided to \fBreturn\fR when
+the \fB\-code error\fR option is provided, Tcl will provide its own
+initial stack trace value in the entry for \fB\-errorinfo\fR. Tcl's
+initial stack trace will include only the call to the procedure, and
+stack unwinding will append information about higher stack levels, but
+there will be no information about the context of the error within
+the procedure. Typically the \fIinfo\fR value is supplied from
+the value of \fB\-errorinfo\fR in a return options dictionary captured
+by the \fBcatch\fR command (or from the copy of that information
+stored in the global variable \fBerrorInfo\fR).
+.TP
+\fB\-level \fIlevel\fR
+.VS 8.5
+The \fB\-level\fR and \fB\-code\fR options work together to set the return
+code to be returned by one of the commands currently being evaluated.
+The \fIlevel\fR value must be a non-negative integer representing a number
+of levels on the call stack. It defines the number of levels up the stack
+at which the return code of a command currently being evaluated should
+be \fIcode\fR. If no \fB\-level\fR option is provided, the default value
+of \fIlevel\fR is 1, so that \fBreturn\fR sets the return code that the
+current procedure returns to its caller, 1 level up the call stack. The
+mechanism by which these options work is described in more detail below.
+.VE 8.5
+.TP
+\fB\-options \fIoptions\fR
+.VS 8.5
+The value \fIoptions\fR must be a valid dictionary. The entries of that
+dictionary are treated as additional \fIoption value\fR pairs for the
+\fBreturn\fR command.
+.VE 8.5
+.SH "RETURN CODE HANDLING MECHANISMS"
+.PP
+Return codes are used in Tcl to control program flow. A Tcl script
+is a sequence of Tcl commands. So long as each command evaluation
+returns a return code of \fBTCL_OK\fR, evaluation will continue to the next
+command in the script. Any exceptional return code (non-\fBTCL_OK\fR)
+returned by a command evaluation causes the flow on to the next
+command to be interrupted. Script evaluation ceases, and the
+exceptional return code from the command becomes the return code
+of the full script evaluation. This is the mechanism by which
+errors during script evaluation cause an interruption and unwinding
+of the call stack. It is also the mechanism by which commands
+like \fBbreak\fR, \fBcontinue\fR, and \fBreturn\fR cause script
+evaluation to terminate without evaluating all commands in sequence.
+.PP
+Some of Tcl's built-in commands evaluate scripts as part of their
+functioning. These commands can make use of exceptional return
+codes to enable special features. For example, the built-in
+Tcl commands that provide loops \(em such as \fBwhile\fR, \fBfor\fR,
+and \fBforeach\fR \(em evaluate a script that is the body of the
+loop. If evaluation of the loop body returns the return code
+of \fBTCL_BREAK\fR or \fBTCL_CONTINUE\fR, the loop command can react in such
+a way as to give the \fBbreak\fR and \fBcontinue\fR commands
+their documented interpretation in loops.
+.PP
+.VS 8.5
+Procedure invocation also involves evaluation of a script, the body
+of the procedure. Procedure invocation provides special treatment
+when evaluation of the procedure body returns the return code
+\fBTCL_RETURN\fR. In that circumstance, the \fB\-level\fR entry in the
+return options dictionary is decremented. If after decrementing,
+the value of the \fB\-level\fR entry is 0, then the value of
+the \fB\-code\fR entry becomes the return code of the procedure.
+If after decrementing, the value of the \fB\-level\fR entry is
+greater than zero, then the return code of the procedure is
+\fBTCL_RETURN\fR. If the procedure invocation occurred during the
+evaluation of the body of another procedure, the process will
+repeat itself up the call stack, decrementing the value of the
+\fB\-level\fR entry at each level, so that the \fIcode\fR will
+be the return code of the current command \fIlevel\fR levels
+up the call stack. The \fBsource\fR command performs the
+same handling of the \fBTCL_RETURN\fR return code, which explains
+the similarity of \fBreturn\fR invocation during a \fBsource\fR
+to \fBreturn\fR invocation within a procedure.
+.PP
+The return code of the \fBreturn\fR command itself triggers this
+special handling by procedure invocation. If \fBreturn\fR
+is provided the option \fB\-level 0\fR, then the return code
+of the \fBreturn\fR command itself will be the value \fIcode\fR
+of the \fB\-code\fR option (or \fBTCL_OK\fR by default). Any other value
+for the \fB\-level\fR option (including the default value of 1)
+will cause the return code of the \fBreturn\fR command itself
+to be \fBTCL_RETURN\fR, triggering a return from the enclosing procedure.
+.VE 8.5
.SH EXAMPLES
First, a simple example of using \fBreturn\fR to return from a
procedure, interrupting the procedure body.
@@ -107,9 +226,9 @@ to report invalid arguments.
.CS
proc factorial {n} {
if {![string is integer $n] || ($n < 0)} {
- \fBreturn\fR -code error \\
- "expected non-negative integer,\\
- but got \\"$n\\""
+ \fBreturn\fR -code error \e
+ "expected non-negative integer,\e
+ but got \e"$n\e""
}
if {$n < 2} {
\fBreturn\fR 1
@@ -121,7 +240,7 @@ proc factorial {n} {
}
set product [expr {$n * $factor}]
if {$product < 0} {
- \fBreturn\fR -code error \\
+ \fBreturn\fR -code error \e
"overflow computing factorial of $n"
}
\fBreturn\fR $product
@@ -134,9 +253,44 @@ proc myBreak {} {
\fBreturn\fR -code break
}
.CE
-
+.PP
+.VS 8.5
+With the \fB\-level 0\fR option, \fBreturn\fR itself can serve
+as a replacement for \fBbreak\fR.
+.CS
+interp alias {} Break {} \fBreturn\fR -level 0 -code break
+.CE
+.PP
+An example of using \fBcatch\fR and \fBreturn -options\fR to
+re-raise a caught error:
+.CS
+proc doSomething {} {
+ set resource [allocate]
+ catch {
+ # Long script of operations
+ # that might raise an error
+ } result options
+ deallocate $resource
+ \fBreturn\fR -options $options $result
+}
+.CE
+.PP
+Finally an example of advanced use of the \fBreturn\fR options
+to create a procedure replacement for \fBreturn\fR itself:
+.CS
+proc myReturn {args} {
+ set result ""
+ if {[llength $args] % 2} {
+ set result [lindex $args end]
+ set args [lrange $args 0 end-1]
+ }
+ set options [dict merge {-level 1} $args]
+ dict incr options -level
+ \fBreturn\fR -options $options $result
+}
+.CE
+.VE 8.5
.SH "SEE ALSO"
-break(n), catch(n), continue(n), error(n), proc(n), source(n), tclvars(n)
-
+break(n), catch(n), continue(n), dict(n), error(n), proc(n), source(n), tclvars(n)
.SH KEYWORDS
break, catch, continue, error, procedure, return
diff --git a/doc/safe.n b/doc/safe.n
index 6eabd79..78fa6ad 100644
--- a/doc/safe.n
+++ b/doc/safe.n
@@ -9,7 +9,7 @@
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
-Safe\ Base \- A mechanism for creating and manipulating safe interpreters.
+Safe\ Base \- A mechanism for creating and manipulating safe interpreters
.SH SYNOPSIS
\fB::safe::interpCreate\fR ?\fIslave\fR? ?\fIoptions...\fR?
.sp
@@ -24,14 +24,13 @@ Safe\ Base \- A mechanism for creating and manipulating safe interpreters.
\fB::safe::interpFindInAccessPath\fR \fIslave\fR \fIdirectory\fR
.sp
\fB::safe::setLogCmd\fR ?\fIcmd arg...\fR?
-.SH OPTIONS
+.SS OPTIONS
.PP
?\fB\-accessPath\fR \fIpathList\fR?
?\fB\-statics\fR \fIboolean\fR? ?\fB\-noStatics\fR?
?\fB\-nested\fR \fIboolean\fR? ?\fB\-nestedLoadOk\fR?
?\fB\-deleteHook\fR \fIscript\fR?
.BE
-
.SH DESCRIPTION
Safe Tcl is a mechanism for executing untrusted Tcl scripts
safely and for providing mediated access by such scripts to
@@ -61,8 +60,7 @@ Different levels of security can be selected by using the optional flags
of the commands described below.
.PP
All commands provided in the master interpreter by the Safe Base reside in
-the \fBsafe\fR namespace:
-
+the \fBsafe\fR namespace.
.SH COMMANDS
The following commands are provided in the master interpreter:
.TP
@@ -93,14 +91,17 @@ safe interpreter and change each and only the provided options.
See the section on \fBOPTIONS\fR below for options description.
Example of use:
.RS
+.PP
.CS
-# Create a new interp with the same configuration as "$i0" :
-set i1 [eval safe::interpCreate [safe::interpConfigure $i0]]
+# Create new interp with the same configuration as "$i0":
+set i1 [safe::interpCreate {*}[safe::interpConfigure $i0]]
+
# Get the current deleteHook
set dh [safe::interpConfigure $i0 \-del]
-# Change (only) the statics loading ok attribute of an interp
-# and its deleteHook (leaving the rest unchanged) :
-safe::interpConfigure $i0 \-delete {foo bar} \-statics 0 ;
+
+# Change (only) the statics loading ok attribute of an
+# interp and its deleteHook (leaving the rest unchanged):
+safe::interpConfigure $i0 \-delete {foo bar} \-statics 0
.CE
.RE
.TP
@@ -117,8 +118,10 @@ This command finds and returns the token for the real directory
It generates an error if the directory is not found.
Example of use:
.RS
+.PP
.CS
-$slave eval [list set tk_library [::safe::interpFindInAccessPath $name $tk_library]]
+$slave eval [list set tk_library \e
+ [::safe::interpFindInAccessPath $name $tk_library]]
.CE
.RE
.TP
@@ -130,8 +133,10 @@ If the directory is already in the virtual path, it only returns the token
without adding the directory to the virtual path again.
Example of use:
.RS
+.PP
.CS
-$slave eval [list set tk_library [::safe::interpAddToAccessPath $name $tk_library]]
+$slave eval [list set tk_library \e
+ [::safe::interpAddToAccessPath $name $tk_library]]
.CE
.RE
.TP
@@ -150,14 +155,18 @@ This prevents a safe interpreter from seeing messages about failures
and other events that might contain sensitive information such as real
directory names.
.RS
+.PP
Example of use:
+.PP
.CS
::safe::setLogCmd puts stderr
.CE
+.PP
Below is the output of a sample session in which a safe interpreter
attempted to source a file not found in its virtual access path.
Note that the safe interpreter only received an error message saying that
the file was not found:
+.PP
.CS
NOTICE for slave interp10 : Created
NOTICE for slave interp10 : Setting accessPath=(/foo/bar) staticsok=1 nestedok=0 deletehook=()
@@ -165,8 +174,7 @@ NOTICE for slave interp10 : auto_path in interp10 has been set to {$p(:0:)}
ERROR for slave interp10 : /foo/bar/init.tcl: no such file or directory
.CE
.RE
-
-.SH OPTIONS
+.SS OPTIONS
The following options are common to
\fB::safe::interpCreate\fR, \fB::safe::interpInit\fR,
and \fB::safe::interpConfigure\fR.
@@ -190,7 +198,7 @@ The default value is \fBtrue\fR :
safe interpreters are allowed to load statically linked packages.
.TP
\fB\-noStatics\fR
-This option is a convenience shortcut for \fB-statics false\fR and
+This option is a convenience shortcut for \fB\-statics false\fR and
thus specifies that the safe interpreter will not be allowed
to load statically linked packages.
.TP
@@ -202,7 +210,7 @@ safe interpreters are not allowed to load packages into
their own sub-interpreters.
.TP
\fB\-nestedLoadOk\fR
-This option is a convenience shortcut for \fB-nested true\fR and
+This option is a convenience shortcut for \fB\-nested true\fR and
thus specifies the safe interpreter will be allowed
to load packages into its own sub-interpreters.
.TP
@@ -252,7 +260,6 @@ the system encoding, but allows all other subcommands including
\fBexit\fR
The calling interpreter is deleted and its computation is stopped, but the
Tcl process in which this interpreter exists is not terminated.
-
.SH SECURITY
The Safe Base does not attempt to completely prevent annoyance and
denial of service attacks. These forms of attack prevent the
@@ -288,8 +295,7 @@ for the \fBsource\fR and \fBload\fR aliases provided to the slave
are path in the form of
\fB[file join \fR\fItoken filename\fR\fB]\fR (i.e. when using the
native file path formats: \fItoken\fR\fB/\fR\fIfilename\fR
-on Unix, \fItoken\fR\fB\\\fIfilename\fR on Windows,
-and \fItoken\fR\fB:\fR\fIfilename\fR on the Mac),
+on Unix and \fItoken\fR\fB\e\fIfilename\fR on Windows),
where \fItoken\fR is representing one of the directories
of the \fIaccessPath\fR list and \fIfilename\fR is
one file in that directory (no sub directories access are allowed).
@@ -305,8 +311,12 @@ To further prevent potential information leakage from sensitive files that
are accidentally included in the set of files that can be sourced by a safe
interpreter, the \fBsource\fR alias restricts access to files
meeting the following constraints: the file name must
-fourteen characters or shorter, must not contain more than one dot ("\fB.\fR"),
-must end up with the extension \fB.tcl\fR or be called \fBtclIndex\fR.
+fourteen characters or shorter, must not contain more than one dot
+.PQ \fB.\fR "" ,
+must end up with the extension
+.PQ \fB.tcl\fR
+or be called
+.PQ \fBtclIndex\fR .
.PP
Each element of the initial access path
list will be assigned a token that will be set in
@@ -316,9 +326,9 @@ the \fBtcl_library\fR for that slave.
If the access path argument is not given or is the empty list,
the default behavior is to let the slave access the same packages
as the master has access to (Or to be more precise:
-only packages written in Tcl (which by definition can't be dangerous
+only packages written in Tcl (which by definition cannot be dangerous
as they run in the slave interpreter) and C extensions that
-provides a Safe_Init entry point). For that purpose, the master's
+provides a _SafeInit entry point). For that purpose, the master's
\fBauto_path\fR will be used to construct the slave access path.
In order that the slave successfully loads the Tcl library files
(which includes the auto-loading mechanism itself) the \fBtcl_library\fR will be
@@ -339,10 +349,8 @@ When the \fIaccessPath\fR is changed after the first creation or
initialization (i.e. through \fBinterpConfigure -accessPath \fR\fIlist\fR),
an \fBauto_reset\fR is automatically evaluated in the safe interpreter
to synchronize its \fBauto_index\fR with the new token list.
-
.SH "SEE ALSO"
interp(n), library(n), load(n), package(n), source(n), unknown(n)
-
.SH KEYWORDS
alias, auto\-loading, auto_mkindex, load, master interpreter, safe
interpreter, slave interpreter, source
diff --git a/doc/scan.n b/doc/scan.n
index 320280a..ca096da 100644
--- a/doc/scan.n
+++ b/doc/scan.n
@@ -15,17 +15,17 @@ scan \- Parse string using conversion specifiers in the style of sscanf
.SH SYNOPSIS
\fBscan \fIstring format \fR?\fIvarName varName ...\fR?
.BE
-
.SH INTRODUCTION
.PP
-This command parses fields from an input string in the same fashion as the
-ANSI C \fBsscanf\fR procedure and returns a count of the number of
+This command parses substrings from an input string in a fashion similar
+to the ANSI C \fBsscanf\fR procedure and returns a count of the number of
conversions performed, or -1 if the end of the input string is reached
before any conversions have been performed. \fIString\fR gives the input
to be parsed and \fIformat\fR indicates how to parse it, using \fB%\fR
conversion specifiers as in \fBsscanf\fR. Each \fIvarName\fR gives the
-name of a variable; when a field is scanned from \fIstring\fR the result is
-converted back into a string and assigned to the corresponding variable.
+name of a variable; when a substring is scanned from \fIstring\fR that
+matches a conversion specifier, the substring is assigned to the
+corresponding variable.
If no \fIvarName\fR variables are specified, then \fBscan\fR works in an
inline manner, returning the data that would otherwise be stored in the
variables as a list. In the inline case, an empty string is returned when
@@ -37,29 +37,28 @@ performed.
If the next character in \fIformat\fR is a blank or tab then it
matches any number of white space characters in \fIstring\fR (including
zero).
-Otherwise, if it isn't a \fB%\fR character then it
+Otherwise, if it is not a \fB%\fR character then it
must match the next character of \fIstring\fR.
When a \fB%\fR is encountered in \fIformat\fR, it indicates
the start of a conversion specifier.
-.VS 8.4
A conversion specifier contains up to four fields after the \fB%\fR:
-a \fB*\fR, which indicates that the converted value is to be discarded
-instead of assigned to a variable; a XPG3 position specifier; a number
-indicating a maximum field width; a field size modifier; and a
+a XPG3 position specifier (or a \fB*\fR to indicate the converted
+value is to be discarded instead of assigned to any variable); a number
+indicating a maximum substring width; a size modifier; and a
conversion character.
-.VE 8.4
All of these fields are optional except for the conversion character.
The fields that are present must appear in the order given above.
.PP
When \fBscan\fR finds a conversion specifier in \fIformat\fR, it
first skips any white-space characters in \fIstring\fR (unless the
-specifier is \fB[\fR or \fBc\fR).
+conversion character is \fB[\fR or \fBc\fR).
Then it converts the next input characters according to the
conversion specifier and stores the result in the variable given
by the next argument to \fBscan\fR.
.PP
If the \fB%\fR is followed by a decimal number and a \fB$\fR, as in
-``\fB%2$d\fR'', then the variable to use is not taken from the next
+.QW \fB%2$d\fR ,
+then the variable to use is not taken from the next
sequential argument. Instead, it is taken from the argument indicated
by the number, where 1 corresponds to the first \fIvarName\fR. If
there are any positional specifiers in \fIformat\fR then all of the
@@ -68,86 +67,75 @@ list must correspond to exactly one conversion specifier or an error
is generated, or in the inline case, any position can be specified
at most once and the empty positions will be filled in with empty strings.
.PP
+.VS 8.5
+The size modifier field is used only when scanning a substring into
+one of Tcl's integer values. The size modifier field dictates the
+integer range acceptable to be stored in a variable, or, for the inline
+case, in a position in the result list.
+The syntactically valid values for the size modifier are \fBh\fR, \fBL\fR,
+\fBl\fR, and \fBll\fR. The \fBh\fR size modifier value is equivalent
+to the absence of a size modifier in the the conversion specifier.
+Either one indicates the integer range to be stored is limited to
+the same range produced by the \fBint()\fR function of the \fBexpr\fR
+command. The \fBL\fR size modifier is equivalent to the \fBl\fR size
+modifier. Either one indicates the integer range to be stored is
+limited to the same range produced by the \fBwide()\fR function of
+the \fBexpr\fR command. The \fBll\fR size modifier indicates that
+the integer range to be stored is unlimited.
+.VE 8.5
+.PP
The following conversion characters are supported:
.TP 10
\fBd\fR
-The input field must be a decimal integer.
-It is read in and the value is stored in the variable as a decimal string.
-.VS 8.4
-If the \fBl\fR or \fBL\fR field size modifier is given, the scanned
-value will have an internal representation that is at least 64-bits in
-size.
-.VE 8.4
+The input substring must be a decimal integer.
+It is read in and the integer value is stored in the variable,
+truncated as required by the size modifier value.
.TP 10
\fBo\fR
-The input field must be an octal integer. It is read in and the
-value is stored in the variable as a decimal string.
-.VS 8.4
-If the \fBl\fR or \fBL\fR field size modifier is given, the scanned
-value will have an internal representation that is at least 64-bits in
-size.
-If the value exceeds MAX_INT (017777777777 on platforms using 32-bit
-integers when the \fBl\fR and \fBL\fR modifiers are not given), it
-will be truncated to a signed integer. Hence, 037777777777 will
-appear as -1 on a 32-bit machine by default.
-.VE 8.4
+The input substring must be an octal integer. It is read in and the
+integer value is stored in the variable,
+truncated as required by the size modifier value.
.TP 10
\fBx\fR
-The input field must be a hexadecimal integer. It is read in
-and the value is stored in the variable as a decimal string.
-.VS 8.4
-If the \fBl\fR or \fBL\fR field size modifier is given, the scanned
-value will have an internal representation that is at least 64-bits in
-size.
-If the value exceeds MAX_INT (0x7FFFFFFF on platforms using 32-bit
-integers when the \fBl\fR and \fBL\fR modifiers are not given), it
-will be truncated to a signed integer. Hence, 0xFFFFFFFF will appear
-as -1 on a 32-bit machine.
-.VE 8.4
+The input substring must be a hexadecimal integer.
+It is read in and the integer value is stored in the variable,
+truncated as required by the size modifier value.
.TP 10
\fBu\fR
-The input field must be a decimal integer. The value is stored in the
-variable as an unsigned decimal integer string.
-.VS 8.4
-If the \fBl\fR or \fBL\fR field size modifier is given, the scanned
-value will have an internal representation that is at least 64-bits in
-size.
-.VE 8.4
+The input substring must be a decimal integer.
+The integer value is truncated as required by the size modifier
+value, and the corresponding unsigned value for that truncated
+range is computed and stored in the variable as a decimal string.
+The conversion makes no sense without reference to a truncation range,
+so the size modifier \fBll\fR is not permitted in combination
+with conversion character \fBu\fR.
.TP 10
\fBi\fR
-The input field must be an integer. The base (i.e. decimal, octal, or
-hexadecimal) is determined in the same fashion as described in
-\fBexpr\fR. The value is stored in the variable as a decimal string.
-.VS 8.4
-If the \fBl\fR or \fBL\fR field size modifier is given, the scanned
-value will have an internal representation that is at least 64-bits in
-size.
-.VE 8.4
+The input substring must be an integer. The base (i.e. decimal, binary,
+octal, or hexadecimal) is determined in the same fashion as described in
+\fBexpr\fR. The integer value is stored in the variable,
+truncated as required by the size modifier value.
.TP 10
\fBc\fR
-A single character is read in and its binary value is stored in
-the variable as a decimal string.
+A single character is read in and its Unicode value is stored in
+the variable as an integer value.
Initial white space is not skipped in this case, so the input
-field may be a white-space character.
-This conversion is different from the ANSI standard in that the
-input field always consists of a single character and no field
-width may be specified.
+substring may be a white-space character.
.TP 10
\fBs\fR
-The input field consists of all the characters up to the next
+The input substring consists of all the characters up to the next
white-space character; the characters are copied to the variable.
.TP 10
\fBe\fR or \fBf\fR or \fBg\fR
-The input field must be a floating-point number consisting
+The input substring must be a floating-point number consisting
of an optional sign, a string of decimal digits possibly
containing a decimal point, and an optional exponent consisting
of an \fBe\fR or \fBE\fR followed by an optional sign and a string of
decimal digits.
-It is read in and stored in the variable as a floating-point string.
+It is read in and stored in the variable as a floating-point value.
.TP 10
\fB[\fIchars\fB]\fR
-The input field consists of any number of characters in
-\fIchars\fR.
+The input substring consists of one or more characters in \fIchars\fR.
The matching string is stored in the variable.
If the first character between the brackets is a \fB]\fR then
it is treated as part of \fIchars\fR rather than the closing
@@ -159,8 +147,7 @@ If the first or last character between the brackets is a \fB\-\fR, then
it is treated as part of \fIchars\fR rather than indicating a range.
.TP 10
\fB[^\fIchars\fB]\fR
-The input field consists of any number of characters not in
-\fIchars\fR.
+The input substring consists of one or more characters not in \fIchars\fR.
The matching string is stored in the variable.
If the character immediately following the \fB^\fR is a \fB]\fR then it is
treated as part of the set rather than the closing bracket for
@@ -170,7 +157,7 @@ contains a sequence of the form \fIa\fB\-\fIb\fR then any
character between \fIa\fR and \fIb\fR (inclusive) will be excluded
from the set.
If the first or last character between the brackets is a \fB\-\fR, then
-it is treated as part of \fIchars\fR rather than indicating a range.
+it is treated as part of \fIchars\fR rather than indicating a range value.
.TP 10
\fBn\fR
No input is consumed from the input string. Instead, the total number
@@ -180,8 +167,8 @@ The number of characters read from the input for a conversion is the
largest number that makes sense for that particular conversion (e.g.
as many decimal digits as possible for \fB%d\fR, as
many octal digits as possible for \fB%o\fR, and so on).
-The input field for a given conversion terminates either when a
-white-space character is encountered or when the maximum field
+The input substring for a given conversion terminates either when a
+white-space character is encountered or when the maximum substring
width has been reached, whichever comes first.
If a \fB*\fR is present in the conversion specifier
then no variable is assigned and the next scan argument is not consumed.
@@ -190,24 +177,29 @@ then no variable is assigned and the next scan argument is not consumed.
The behavior of the \fBscan\fR command is the same as the behavior of
the ANSI C \fBsscanf\fR procedure except for the following differences:
.IP [1]
-\fB%p\fR conversion specifier is not currently supported.
+\fB%p\fR conversion specifier is not supported.
.IP [2]
For \fB%c\fR conversions a single character value is
converted to a decimal string, which is then assigned to the
corresponding \fIvarName\fR;
-no field width may be specified for this conversion.
+no substring width may be specified for this conversion.
.IP [3]
-.VS 8.4
The \fBh\fR modifier is always ignored and the \fBl\fR and \fBL\fR
modifiers are ignored when converting real values (i.e. type
-\fBdouble\fR is used for the internal representation).
-.VE 8.4
+\fBdouble\fR is used for the internal representation). The \fBll\fR
+modifier has no \fBsscanf\fR counterpart.
.IP [4]
If the end of the input string is reached before any conversions have been
performed and no variables are given, an empty string is returned.
.SH EXAMPLES
+Convert a UNICODE character to its numeric value:
+.CS
+set char "x"
+set value [\fBscan\fR $char %c]
+.CE
+.PP
Parse a simple color specification of the form \fI#RRGGBB\fR using
-hexadecimal conversions with field sizes:
+hexadecimal conversions with substring sizes:
.CS
set string "#08D03F"
\fBscan\fR $string "#%2x%2x%2x" r g b
@@ -245,7 +237,7 @@ looking for the terminating character explicitly:
set string "(5.2,-4e-2)"
# Note that the spaces before the literal parts of
# the scan pattern are significant, and that ")" is
-# the Unicode character \\u0029
+# the Unicode character \eu0029
if {
[\fBscan\fR $string " (%f ,%f %c" x y last] != 3
|| $last != 0x0029
@@ -254,9 +246,22 @@ if {
}
puts "X=$x, Y=$y"
.CE
-
+.PP
+.VS 8.5
+An interactive session demonstrating the truncation of integer
+values determined by size modifiers:
+.CS
+% set tcl_platform(wordSize)
+4
+% scan 20000000000000000000 %d
+2147483647
+% scan 20000000000000000000 %ld
+9223372036854775807
+% scan 20000000000000000000 %lld
+20000000000000000000
+.CE
+.VE 8.5
.SH "SEE ALSO"
format(n), sscanf(3)
-
.SH KEYWORDS
conversion specifier, parse, scan
diff --git a/doc/seek.n b/doc/seek.n
index bbc586f..d4ce9b7 100644
--- a/doc/seek.n
+++ b/doc/seek.n
@@ -19,12 +19,10 @@ seek \- Change the access position for an open channel
.PP
Changes the current access position for \fIchannelId\fR.
.PP
-.VS
\fIChannelId\fR must be an identifier for an open channel such as a
Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR),
the return value from an invocation of \fBopen\fR or \fBsocket\fR, or
the result of a channel creation command provided by a Tcl extension.
-.VE
.PP
The \fIoffset\fR and \fIorigin\fR
arguments specify the position at which the next read or write will occur
@@ -55,11 +53,9 @@ This command returns an empty string.
An error occurs if this command is applied to channels whose underlying
file or device does not support seeking.
.PP
-.VS 8.1
Note that \fIoffset\fR values are byte offsets, not character
offsets. Both \fBseek\fR and \fBtell\fR operate in terms of bytes,
not characters, unlike \fBread\fR.
-.VE 8.1
.SH EXAMPLES
Read a file twice:
.CS
diff --git a/doc/set.n b/doc/set.n
index 3233475..fb8dfac 100644
--- a/doc/set.n
+++ b/doc/set.n
@@ -14,13 +14,12 @@ set \- Read and write variables
.SH SYNOPSIS
\fBset \fIvarName \fR?\fIvalue\fR?
.BE
-
.SH DESCRIPTION
.PP
Returns the value of variable \fIvarName\fR.
If \fIvalue\fR is specified, then set
the value of \fIvarName\fR to \fIvalue\fR, creating a new variable
-if one doesn't already exist, and return its value.
+if one does not already exist, and return its value.
If \fIvarName\fR contains an open parenthesis and ends with a
close parenthesis, then it refers to an array element: the characters
before the first open parenthesis are the name of the array,
@@ -42,7 +41,7 @@ unless \fIvarName\fR was declared to resolve differently through one of the
.SH EXAMPLES
Store a random number in the variable \fIr\fR:
.CS
-\fBset\fR r [expr rand()]
+\fBset\fR r [expr {rand()}]
.CE
.PP
Store a short message in an array element:
@@ -65,9 +64,7 @@ practice instead of doing double-dereferencing):
\fBset\fR vbl in[expr {rand() >= 0.5}]
\fBset\fR out [\fBset\fR $vbl]
.CE
-
.SH "SEE ALSO"
expr(n), global(n), namespace(n), proc(n), trace(n), unset(n), upvar(n), variable(n)
-
.SH KEYWORDS
read, write, variable
diff --git a/doc/socket.n b/doc/socket.n
index a4dda4a..bd307b7 100644
--- a/doc/socket.n
+++ b/doc/socket.n
@@ -75,7 +75,16 @@ connection attempt succeeds or fails, if the socket is in blocking mode, the
operation will wait until the connection is completed or fails. If the
socket is in nonblocking mode and a \fBgets\fR or \fBflush\fR is done on
the socket before the connection attempt succeeds or fails, the operation
-returns immediately and \fBfblocked\fR on the socket returns 1.
+returns immediately and \fBfblocked\fR on the socket returns 1. Synchronous
+client sockets may be switched (after they have connected) to operating in
+asynchronous mode using:
+.RS
+.CS
+\fBfconfigure \fIchan \fB\-blocking 0\fR
+.CE
+.PP
+See the \fBfconfigure\fR command for more details.
+.RE
.SH "SERVER SOCKETS"
.PP
If the \fB\-server\fR option is specified then the new socket
@@ -91,7 +100,7 @@ with three additional arguments: the name of the new channel, the
address, in network address notation, of the client's host, and
the client's port number.
.PP
-The following additional option may also be specified before \fIhost\fR:
+The following additional option may also be specified before \fIport\fR:
.TP
\fB\-myaddr\fI addr\fR
\fIAddr\fR gives the domain-style name or numerical IP address of
@@ -108,7 +117,7 @@ channel shuts down the server so that no new connections will be
accepted; however, existing connections will be unaffected.
.PP
Server sockets depend on the Tcl event mechanism to find out when
-new connections are opened. If the application doesn't enter the
+new connections are opened. If the application does not enter the
event loop, for example by invoking the \fBvwait\fR command or
calling the C procedure \fBTcl_DoOneEvent\fR, then no connections
will be accepted.
diff --git a/doc/source.n b/doc/source.n
index 18004a8..69d383e 100644
--- a/doc/source.n
+++ b/doc/source.n
@@ -15,11 +15,10 @@ source \- Evaluate a file or resource as a Tcl script
.SH SYNOPSIS
\fBsource \fIfileName\fR
.sp
-\fBsource\fR \fB\-rsrc \fIresourceName \fR?\fIfileName\fR?
-.sp
-\fBsource\fR \fB\-rsrcid \fIresourceId \fR?\fIfileName\fR?
+.VS 8.5
+\fBsource\fR \fB\-encoding \fIencodingName fileName\fR
+.VE 8.5
.BE
-
.SH DESCRIPTION
.PP
This command takes the contents of the specified file or resource
@@ -31,23 +30,26 @@ If a \fBreturn\fR command is invoked from within the script then the
remainder of the file will be skipped and the \fBsource\fR command
will return normally with the result from the \fBreturn\fR command.
.PP
-.VS 8.4
-The end-of-file character for files is '\\32' (^Z) for all platforms.
+The end-of-file character for files is
+.QW \e32
+(^Z) for all platforms.
The source command will read files up to this character. This
restriction does not exist for the \fBread\fR or \fBgets\fR commands,
allowing for files containing code and data segments (scripted documents).
-If you require a ``^Z'' in code for string comparison, you can use
-``\\032'' or ``\\u001a'', which will be safely substituted by the Tcl
-interpreter into ``^Z''.
-.VE 8.4
+If you require a
+.QW ^Z
+in code for string comparison, you can use
+.QW \e032
+or
+.QW \eu001a ,
+which will be safely substituted by the Tcl interpreter into
+.QW ^Z .
.PP
-The \fI\-rsrc\fR and \fI\-rsrcid\fR forms of this command are only
-available on Macintosh computers. These versions of the command
-allow you to source a script from a \fBTEXT\fR resource. You may specify
-what \fBTEXT\fR resource to source by either name or id. By default Tcl
-searches all open resource files, which include the current
-application and any loaded C extensions. Alternatively, you may
-specify the \fIfileName\fR where the \fBTEXT\fR resource can be found.
+.VS 8.5
+The \fB\-encoding\fR option is used to specify the encoding of
+the data stored in \fIfileName\fR. When the \fB\-encoding\fR option
+is omitted, the system encoding is assumed.
+.VE 8.5
.SH EXAMPLE
Run the script in the file \fBfoo.tcl\fR and then the script in the
file \fBbar.tcl\fR:
@@ -61,9 +63,7 @@ foreach scriptFile {foo.tcl bar.tcl} {
\fBsource\fR $scriptFile
}
.CE
-
.SH "SEE ALSO"
-file(n), cd(n), info(n)
-
+file(n), cd(n), encoding(n), info(n)
.SH KEYWORDS
file, script
diff --git a/doc/split.n b/doc/split.n
index 11e4013..c289be0 100644
--- a/doc/split.n
+++ b/doc/split.n
@@ -32,7 +32,7 @@ If \fIsplitChars\fR is an empty string then each character of
Divide up a USENET group name into its hierarchical components:
.CS
\fBsplit\fR "comp.lang.tcl.announce" .
- \fI=> comp lang tcl announce\fR
+ \fI\(-> comp lang tcl announce\fR
.CE
.PP
See how the \fBsplit\fR command splits on \fIevery\fR character in
@@ -40,21 +40,21 @@ See how the \fBsplit\fR command splits on \fIevery\fR character in
careful:
.CS
\fBsplit\fR "alpha beta gamma" "temp"
- \fI=> al {ha b} {} {a ga} {} a\fR
+ \fI\(-> al {ha b} {} {a ga} {} a\fR
.CE
.PP
Extract the list words from a string that is not a well-formed list:
.CS
\fBsplit\fR "Example with {unbalanced brace character"
- \fI=> Example with \\{unbalanced brace character\fR
+ \fI\(-> Example with \e{unbalanced brace character\fR
.CE
.PP
Split a string into its constituent characters
.CS
\fBsplit\fR "Hello world" {}
- \fI=> H e l l o { } w o r l d\fR
+ \fI\(-> H e l l o { } w o r l d\fR
.CE
-.SH "PARSING RECORD-ORIENTED FILES"
+.SS "PARSING RECORD-ORIENTED FILES"
Parse a Unix /etc/passwd file, which consists of one entry per line,
with each line consisting of a colon-separated list of fields:
.CS
@@ -64,7 +64,7 @@ set content [read $fid]
close $fid
## Split into records on newlines
-set records [\fBsplit\fR $content "\\n"]
+set records [\fBsplit\fR $content "\en"]
## Iterate over the records
foreach rec $records {
@@ -73,7 +73,7 @@ foreach rec $records {
set fields [\fBsplit\fR $rec ":"]
## Assign fields to variables and print some out...
- lassign $fields \\
+ lassign $fields \e
userName password uid grp longName homeDir shell
puts "$longName uses [file tail $shell] for a login shell"
}
diff --git a/doc/string.n b/doc/string.n
index ef49f15..dfb5a90 100644
--- a/doc/string.n
+++ b/doc/string.n
@@ -1,14 +1,14 @@
-'\"
-'\" Copyright (c) 1993 The Regents of the University of California.
-'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
-'\"
-'\" See the file "license.terms" for information on usage and redistribution
-'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-'\"
+.\"
+.\" Copyright (c) 1993 The Regents of the University of California.
+.\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
+.\"
+.\" See the file "license.terms" for information on usage and redistribution
+.\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+.\"
.so man.macros
.TH string n 8.1 Tcl "Tcl Built-In Commands"
.BS
-'\" Note: do not modify the .SH NAME line immediately below!
+.\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
string \- Manipulate strings
.SH SYNOPSIS
@@ -39,7 +39,7 @@ first \fIlength\fR characters are used in the comparison. If
\fB\-length\fR is negative, it is ignored. If \fB\-nocase\fR is
specified, then the strings are compared in a case-insensitive manner.
.TP
-\fBstring equal\fR ?\fB\-nocase\fR? ?\fB-length int\fR? \fIstring1 string2\fR
+\fBstring equal\fR ?\fB\-nocase\fR? ?\fB\-length int\fR? \fIstring1 string2\fR
Perform a character-by-character comparison of strings \fIstring1\fR
and \fIstring2\fR. Returns 1 if \fIstring1\fR and \fIstring2\fR are
identical, or 0 when not. If \fB\-length\fR is specified, then only
@@ -47,13 +47,13 @@ the first \fIlength\fR characters are used in the comparison. If
\fB\-length\fR is negative, it is ignored. If \fB\-nocase\fR is
specified, then the strings are compared in a case-insensitive manner.
.TP
-\fBstring first \fIstring1 string2\fR ?\fIstartIndex\fR?
-Search \fIstring2\fR for a sequence of characters that exactly match
-the characters in \fIstring1\fR. If found, return the index of the
-first character in the first such match within \fIstring2\fR. If not
+\fBstring first \fIneedleString haystackString\fR ?\fIstartIndex\fR?
+Search \fIhaystackString\fR for a sequence of characters that exactly match
+the characters in \fIneedleString\fR. If found, return the index of the
+first character in the first such match within \fIhaystackString\fR. If not
found, return \-1. If \fIstartIndex\fR is specified (in any of the
forms accepted by the \fBindex\fR method), then the search is
-constrained to start with the character in \fIstring2\fR specified by
+constrained to start with the character in \fIhaystackString\fR specified by
the index. For example,
.RS
.CS
@@ -70,23 +70,61 @@ will return \fB\-1\fR.
Returns the \fIcharIndex\fR'th character of the \fIstring\fR argument.
A \fIcharIndex\fR of 0 corresponds to the first character of the
string. \fIcharIndex\fR may be specified as follows:
+.VS 8.5
.RS
.IP \fIinteger\fR 10
-The char specified at this integral index.
+For any index value that passes \fBstring is integer -strict\fR,
+the char specified at this integral index
+(e.g. \fB2\fR would refer to the
+.QW c
+in
+.QW abcd ).
.IP \fBend\fR 10
-The last char of the string.
-.IP \fBend\-\fIinteger\fR 10
-The last char of the string minus the specified integer offset
-(e.g. \fBend\-1\fR would refer to the "c" in "abcd").
+The last char of the string
+(e.g. \fBend\fR would refer to the
+.QW d
+in
+.QW abcd ).
+.IP \fBend\fR\-\fIN\fR 10
+The last char of the string minus the specified integer offset \fIN\fR
+(e.g. \fBend\fR\-1 would refer to the
+.QW c
+in
+.QW abcd ).
+.IP \fBend\fR+\fIN\fR 10
+The last char of the string plus the specified integer offset \fIN\fR
+(e.g. \fBend\fR+\-1 would refer to the
+.QW c
+in
+.QW abcd ).
+.IP \fIM\fR+\fIN\fR 10
+The char specified at the integral index that is the sum of
+integer values \fIM\fR and \fIN\fR
+(e.g. \fB1+1\fR would refer to the
+.QW c
+in
+.QW abcd ).
+.IP \fIM\fR\-\fIN\fR 10
+The char specified at the integral index that is the difference of
+integer values \fIM\fR and \fIN\fR
+(e.g. \fB2\-1\fR would refer to the
+.QW b
+in
+.QW abcd ).
+.PP
+In the specifications above, the integer value \fIM\fR contains no
+trailing whitespace and the integer value \fIN\fR contains no
+leading whitespace.
.PP
If \fIcharIndex\fR is less than 0 or greater than or equal to the
-length of the string then an empty string is returned.
+length of the string then this command returns an empty string.
.RE
+.VE
.TP
\fBstring is \fIclass\fR ?\fB\-strict\fR? ?\fB\-failindex \fIvarname\fR? \fIstring\fR
Returns 1 if \fIstring\fR is a valid member of the specified character
class, otherwise returns 0. If \fB\-strict\fR is specified, then an
-empty string returns 0, otherwise and empty string will return 1 on
+empty string returns 0, otherwise an empty string will return 1 on
any class. If \fB\-failindex\fR is specified, then if the function
returns 0, the index in the string where the class was no longer valid
will be stored in the variable named \fIvarname\fR. The \fIvarname\fR
@@ -98,7 +136,7 @@ Any Unicode alphabet or digit character.
.IP \fBalpha\fR 12
Any Unicode alphabet character.
.IP \fBascii\fR 12
-Any character with a value less than \\u0080 (those that are in the
+Any character with a value less than \eu0080 (those that are in the
7\-bit ascii range).
.IP \fBboolean\fR 12
Any of the forms allowed to \fBTcl_GetBoolean\fR.
@@ -117,9 +155,15 @@ false.
.IP \fBgraph\fR 12
Any Unicode printing character, except space.
.IP \fBinteger\fR 12
-Any of the valid forms for an ordinary integer in Tcl, with optional
-surrounding whitespace. In case of under/overflow in the value, 0 is
-returned and the \fIvarname\fR will contain \-1.
+Any of the valid string formats for a 32-bit integer value in Tcl,
+with optional surrounding whitespace. In case of under/overflow in
+the value, 0 is returned and the \fIvarname\fR will contain \-1.
+.IP \fBlist\fR 12
+Any proper list structure, with optional surrounding whitespace. In
+case of improper list structure, 0 is returned and the \fIvarname\fR
+will contain the index of the
+.QW element
+where the list parsing fails, or \-1 if this cannot be determined.
.IP \fBlower\fR 12
Any Unicode lower case alphabet character.
.IP \fBprint\fR 12
@@ -133,6 +177,12 @@ Any of the forms allowed to \fBTcl_GetBoolean\fR where the value is
true.
.IP \fBupper\fR 12
Any upper case alphabet character in the Unicode character set.
+.VS 8.5
+.IP \fBwideinteger\fR 12
+Any of the valid forms for a wide integer in Tcl, with optional
+surrounding whitespace. In case of under/overflow in the value, 0 is
+returned and the \fIvarname\fR will contain \-1.
+.VE 8.5
.IP \fBwordchar\fR 12
Any Unicode word character. That is any alphanumeric character, and
any Unicode connector punctuation characters (e.g. underscore).
@@ -144,13 +194,13 @@ function will return 0, then the \fIvarname\fR will always be set to
0, due to the varied nature of a valid boolean value.
.RE
.TP
-\fBstring last \fIstring1 string2\fR ?\fIlastIndex\fR?
-Search \fIstring2\fR for a sequence of characters that exactly match
-the characters in \fIstring1\fR. If found, return the index of the
-first character in the last such match within \fIstring2\fR. If there
+\fBstring last \fIneedleString haystackString\fR ?\fIlastIndex\fR?
+Search \fIhaystackString\fR for a sequence of characters that exactly match
+the characters in \fIneedleString\fR. If found, return the index of the
+first character in the last such match within \fIhaystackString\fR. If there
is no match, then return \-1. If \fIlastIndex\fR is specified (in any
of the forms accepted by the \fBindex\fR method), then only the
-characters in \fIstring2\fR at or before the specified \fIlastIndex\fR
+characters in \fIhaystackString\fR at or before the specified \fIlastIndex\fR
will be considered by the search. For example,
.RS
.CS
@@ -198,7 +248,7 @@ it will return the string \fB02c322c222c\fR.
.TP
\fBstring match\fR ?\fB\-nocase\fR? \fIpattern\fR \fIstring\fR
See if \fIpattern\fR matches \fIstring\fR; return 1 if it does, 0 if
-it doesn't. If \fB\-nocase\fR is specified, then the pattern attempts
+it does not. If \fB\-nocase\fR is specified, then the pattern attempts
to match against the string in a case insensitive manner. For the two
strings to match, their contents must be identical except that the
following special sequences may appear in \fIpattern\fR:
@@ -213,10 +263,16 @@ Matches any character in the set given by \fIchars\fR. If a sequence
of the form \fIx\fB\-\fIy\fR appears in \fIchars\fR, then any
character between \fIx\fR and \fIy\fR, inclusive, will match. When
used with \fB\-nocase\fR, the end points of the range are converted to
-lower case first. Whereas {[A\-z]} matches '_' when matching
-case-sensitively ('_' falls between the 'Z' and 'a'), with
-\fB\-nocase\fR this is considered like {[A\-Za\-z]} (and probably what
-was meant in the first place).
+lower case first. Whereas {[A\-z]} matches
+.QW _
+when matching case-sensitively (since
+.QW _
+falls between the
+.QW Z
+and
+.QW a ),
+with \fB\-nocase\fR this is considered like {[A\-Za\-z]} (and
+probably what was meant in the first place).
.IP \fB\e\fIx\fR 10
Matches the single character \fIx\fR. This provides a way of avoiding
the special interpretation of the characters \fB*?[]\e\fR in
@@ -249,6 +305,12 @@ and if \fIlast\fR is greater than or equal to the length of the string
then it is treated as if it were \fBend\fR. If \fIfirst\fR is greater
than \fIlast\fR or the length of the initial string, or \fIlast\fR is
less than 0, then the initial string is returned untouched.
+.VS 8.5
+.TP
+\fBstring reverse \fIstring\fR
+Returns a string that is the same length as \fIstring\fR but with its
+characters in the reverse order.
+.VE 8.5
.TP
\fBstring tolower \fIstring\fR ?\fIfirst\fR? ?\fIlast\fR?
Returns a value equal to \fIstring\fR except that all upper (or title)
@@ -278,19 +340,19 @@ specified as for the \fBindex\fR method.
.TP
\fBstring trim \fIstring\fR ?\fIchars\fR?
Returns a value equal to \fIstring\fR except that any leading or
-trailing characters from the set given by \fIchars\fR are removed. If
+trailing characters present in the string given by \fIchars\fR are removed. If
\fIchars\fR is not specified then white space is removed (spaces,
tabs, newlines, and carriage returns).
.TP
\fBstring trimleft \fIstring\fR ?\fIchars\fR?
Returns a value equal to \fIstring\fR except that any leading
-characters from the set given by \fIchars\fR are removed. If
+characters present in the string given by \fIchars\fR are removed. If
\fIchars\fR is not specified then white space is removed (spaces,
tabs, newlines, and carriage returns).
.TP
\fBstring trimright \fIstring\fR ?\fIchars\fR?
Returns a value equal to \fIstring\fR except that any trailing
-characters from the set given by \fIchars\fR are removed. If
+characters present in the string given by \fIchars\fR are removed. If
\fIchars\fR is not specified then white space is removed (spaces,
tabs, newlines, and carriage returns).
.TP
@@ -325,4 +387,9 @@ if {$length == 0} {
expr(n), list(n)
.SH KEYWORDS
-case conversion, compare, index, match, pattern, string, word, equal, ctype
+case conversion, compare, index, match, pattern, string, word, equal,
+ctype, character, reverse
+
+.\" Local Variables:
+.\" mode: nroff
+.\" End:
diff --git a/doc/subst.n b/doc/subst.n
index b161de6..5a162c4 100644
--- a/doc/subst.n
+++ b/doc/subst.n
@@ -15,7 +15,6 @@ subst \- Perform backslash, command, and variable substitutions
.SH SYNOPSIS
\fBsubst \fR?\fB\-nobackslashes\fR? ?\fB\-nocommands\fR? ?\fB\-novariables\fR? \fIstring\fR
.BE
-
.SH DESCRIPTION
.PP
This command performs variable substitutions, command substitutions,
@@ -34,15 +33,14 @@ For example, if \fB\-nocommands\fR is specified, command substitution
is not performed: open and close brackets are treated as ordinary characters
with no special interpretation.
.PP
-.VS 8.4
Note that the substitution of one kind can include substitution of
-other kinds. For example, even when the \fB-novariables\fR option
+other kinds. For example, even when the \fB\-novariables\fR option
is specified, command substitution is performed without restriction.
This means that any variable substitution necessary to complete the
command substitution will still take place. Likewise, any command
substitution necessary to complete a variable substitution will
-take place, even when \fB-nocommands\fR is specified. See the
-EXAMPLES below.
+take place, even when \fB\-nocommands\fR is specified. See the
+\fBEXAMPLES\fR below.
.PP
If an error occurs during substitution, then \fBsubst\fR will return
that error. If a break exception occurs during command or variable
@@ -54,10 +52,11 @@ will be substituted for that entire command or variable substitution
(as long as it is well-formed Tcl.) If a return exception occurs,
or any other return code is returned during command or variable
substitution, then the returned value is substituted for that
-substitution. See the EXAMPLES below. In this way, all exceptional
-return codes are ``caught'' by \fBsubst\fR. The \fBsubst\fR command
+substitution. See the \fBEXAMPLES\fR below. In this way, all exceptional
+return codes are
+.QW caught
+by \fBsubst\fR. The \fBsubst\fR command
itself will either return an error, or will complete successfully.
-.VE
.SH EXAMPLES
.PP
When it performs its substitutions, \fIsubst\fR does not give any
@@ -67,22 +66,31 @@ command substitutions) so the script
set a 44
\fBsubst\fR {xyz {$a}}
.CE
-returns ``\fBxyz {44}\fR'', not ``\fBxyz {$a}\fR''
-.VS 8.4
+returns
+.QW "\fBxyz {44}\fR" ,
+not
+.QW "\fBxyz {$a}\fR"
and the script
.CS
-set a "p\\} q \\{r"
+set a "p\e} q \e{r"
\fBsubst\fR {xyz {$a}}
.CE
-return ``\fBxyz {p} q {r}\fR'', not ``\fBxyz {p\\} q \\{r}\fR''.
+returns
+.QW "\fBxyz {p} q {r}\fR" ,
+not
+.QW "\fBxyz {p\e} q \e{r}\fR".
.PP
When command substitution is performed, it includes any variable
-substitution necessary to evaluate the script.
+substitution necessary to evaluate the script.
.CS
set a 44
\fBsubst\fR -novariables {$a [format $a]}
.CE
-returns ``\fB$a 44\fR'', not ``\fB$a $a\fR''. Similarly, when
+returns
+.QW "\fB$a 44\fR" ,
+not
+.QW "\fB$a $a\fR" .
+Similarly, when
variable substitution is performed, it includes any command
substitution necessary to retrieve the value of the variable.
.CS
@@ -90,7 +98,10 @@ proc b {} {return c}
array set a {c c [b] tricky}
\fBsubst\fR -nocommands {[b] $a([b])}
.CE
-returns ``\fB[b] c\fR'', not ``\fB[b] tricky\fR''.
+returns
+.QW "\fB[b] c\fR" ,
+not
+.QW "\fB[b] tricky\fR" .
.PP
The continue and break exceptions allow command substitutions to
prevent substitution of the rest of the command substitution and the
@@ -99,25 +110,36 @@ when processing text using \fIsubst\fR. For example, the script
.CS
\fBsubst\fR {abc,[break],def}
.CE
-returns ``\fBabc,\fR'', not ``\fBabc,,def\fR'' and the script
+returns
+.QW \fBabc,\fR ,
+not
+.QW \fBabc,,def\fR
+and the script
.CS
-\fBsubst\fR {abc,[continue;expr 1+2],def}
+\fBsubst\fR {abc,[continue;expr {1+2}],def}
.CE
-returns ``\fBabc,,def\fR'', not ``\fBabc,3,def\fR''.
+returns
+.QW \fBabc,,def\fR ,
+not
+.QW \fBabc,3,def\fR .
.PP
Other exceptional return codes substitute the returned value
.CS
-\fBsubst\fR {abc,[return foo;expr 1+2],def}
+\fBsubst\fR {abc,[return foo;expr {1+2}],def}
.CE
-returns ``\fBabc,foo,def\fR'', not ``\fBabc,3,def\fR'' and
+returns
+.QW \fBabc,foo,def\fR ,
+not
+.QW \fBabc,3,def\fR
+and
.CS
-\fBsubst\fR {abc,[return -code 10 foo;expr 1+2],def}
+\fBsubst\fR {abc,[return -code 10 foo;expr {1+2}],def}
.CE
-also returns ``\fBabc,foo,def\fR'', not ``\fBabc,3,def\fR''.
-.VE
-
+also returns
+.QW \fBabc,foo,def\fR ,
+not
+.QW \fBabc,3,def\fR .
.SH "SEE ALSO"
Tcl(n), eval(n), break(n), continue(n)
-
.SH KEYWORDS
backslash substitution, command substitution, variable substitution
diff --git a/doc/switch.n b/doc/switch.n
index 32da66c..defa849 100644
--- a/doc/switch.n
+++ b/doc/switch.n
@@ -6,7 +6,7 @@
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
-.TH switch n 7.0 Tcl "Tcl Built-In Commands"
+.TH switch n 8.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
@@ -16,7 +16,6 @@ switch \- Evaluate one of several scripts, depending on a given value
.sp
\fBswitch \fR?\fIoptions\fR?\fI string \fR{\fIpattern body \fR?\fIpattern body \fR...?}
.BE
-
.SH DESCRIPTION
.PP
The \fBswitch\fR command matches its \fIstring\fR argument against each of
@@ -31,8 +30,13 @@ matches \fIstring\fR and no default is given, then the \fBswitch\fR
command returns an empty string.
.PP
If the initial arguments to \fBswitch\fR start with \fB\-\fR then
-they are treated as options. The following options are
-currently supported:
+they are treated as options
+.VS 8.5
+unless there are exactly two arguments to \fBswitch\fR (in which case the
+first must the \fIstring\fR and the second must be the
+\fIpattern\fR/\fIbody\fR list).
+.VE 8.5
+The following options are currently supported:
.TP 10
\fB\-exact\fR
Use exact matching when comparing \fIstring\fR to a pattern. This
@@ -46,10 +50,48 @@ When matching \fIstring\fR to the patterns, use glob-style matching
When matching \fIstring\fR to the patterns, use regular
expression matching
(as described in the \fBre_syntax\fR reference page).
+'\" Options defined by TIP#75
+.VS 8.5
+.TP 10
+\fB\-nocase\fR
+Causes comparisons to be handled in a case-insensitive manner.
+.TP 10
+\fB\-matchvar\fR \fIvarName\fR
+This option (only legal when \fB\-regexp\fR is also specified)
+specifies the name of a variable into which the list of matches
+found by the regular expression engine will be written. The first
+element of the list written will be the overall substring of the input
+string (i.e. the \fIstring\fR argument to \fBswitch\fR) matched, the
+second element of the list will be the substring matched by the first
+capturing parenthesis in the regular expression that matched, and so
+on. When a \fBdefault\fR branch is taken, the variable will have the
+empty list written to it. This option may be specified at the same
+time as the \fB\-indexvar\fR option.
+.TP 10
+\fB\-indexvar\fR \fIvarName\fR
+This option (only legal when \fB\-regexp\fR is also specified)
+specifies the name of a variable into which the list of indices
+referring to matching substrings
+found by the regular expression engine will be written. The first
+element of the list written will be a two-element list specifying the
+index of the start and index of the first character after the end of
+the overall substring of the input
+string (i.e. the \fIstring\fR argument to \fBswitch\fR) matched, in a
+similar way to the \fB\-indices\fR option to the \fBregexp\fR can
+obtain. Similarly, the second element of the list refers to the first
+capturing parenthesis in the regular expression that matched, and so
+on. When a \fBdefault\fR branch is taken, the variable will have the
+empty list written to it. This option may be specified at the same
+time as the \fB\-matchvar\fR option.
+.VE 8.5
.TP 10
\fB\-\|\-\fR
Marks the end of options. The argument following this one will
be treated as \fIstring\fR even if it starts with a \fB\-\fR.
+.VS 8.5
+This is not required when the matching patterns and bodies are grouped
+together in a single argument.
+.VE 8.5
.PP
Two syntaxes are provided for the \fIpattern\fR and \fIbody\fR arguments.
The first uses a separate argument for each of the patterns and commands;
@@ -66,9 +108,12 @@ no command or variable substitutions are performed on them; this makes
the behavior of the second form different than the first form in some
cases.
.PP
-If a \fIbody\fR is specified as ``\fB\-\fR'' it means that the \fIbody\fR
+If a \fIbody\fR is specified as
+.QW \fB\-\fR
+it means that the \fIbody\fR
for the next pattern should also be used as the body for this
-pattern (if the next pattern also has a body of ``\fB\-\fR''
+pattern (if the next pattern also has a body of
+.QW \fB\-\fR
then the body after that is used, and so on).
This feature makes it possible to share a single \fIbody\fR among
several patterns.
@@ -81,7 +126,7 @@ The \fBswitch\fR command can match against variables and not just
literals, as shown here (the result is \fI2\fR):
.CS
set foo "abc"
-\fBswitch\fR abc a \- b {expr 1} $foo {expr 2} default {expr 3}
+\fBswitch\fR abc a \- b {expr {1}} $foo {expr {2}} default {expr {3}}
.CE
.PP
Using glob matching and the fall-through body is an alternative to
@@ -90,9 +135,9 @@ writing regular expressions with alternations, as can be seen here
.CS
\fBswitch\fR \-glob aaab {
a*b \-
- b {expr 1}
- a* {expr 2}
- default {expr 3}
+ b {expr {1}}
+ a* {expr {2}}
+ default {expr {3}}
}
.CE
.PP
@@ -100,22 +145,39 @@ Whenever nothing matches, the \fBdefault\fR clause (which must be
last) is taken. This example has a result of \fI3\fR:
.CS
\fBswitch\fR xyz {
- a \-
+ a \-
b {
# Correct Comment Placement
- expr 1
+ expr {1}
}
c {
- expr 2
+ expr {2}
}
default {
- expr 3
+ expr {3}
+ }
+}
+.CE
+.PP
+.VS 8.5
+When matching against regular expressions, information about what
+exactly matched is easily obtained using the \fB\-matchvar\fR option:
+.CS
+\fBswitch\fR \-regexp \-matchvar foo \-\- $bar {
+ a(b*)c {
+ puts "Found [string length [lindex $foo 1]] 'b's"
+ }
+ d(e*)f(g*)h {
+ puts "Found [string length [lindex $foo 1]] 'e's and\e
+ [string length [lindex $foo 2]] 'g's"
}
}
.CE
-
+.VE 8.5
.SH "SEE ALSO"
for(n), if(n), regexp(n)
-
.SH KEYWORDS
switch, match, regular expression
+.\" Local Variables:
+.\" mode: nroff
+.\" End:
diff --git a/doc/tclsh.1 b/doc/tclsh.1
index 76323f1..f604c2e 100644
--- a/doc/tclsh.1
+++ b/doc/tclsh.1
@@ -12,7 +12,7 @@
.SH NAME
tclsh \- Simple shell containing Tcl interpreter
.SH SYNOPSIS
-\fBtclsh\fR ?\fIfileName arg arg ...\fR?
+\fBtclsh\fR ?-encoding \fIname\fR? ?\fIfileName arg arg ...\fR?
.BE
.SH DESCRIPTION
@@ -26,26 +26,33 @@ It runs until the \fBexit\fR command is invoked or until it
reaches end-of-file on its standard input.
If there exists a file \fB.tclshrc\fR (or \fBtclshrc.tcl\fR on
the Windows platforms) in the home directory of
-the user, \fBtclsh\fR evaluates the file as a Tcl script
+the user, interactive \fBtclsh\fR evaluates the file as a Tcl script
just before reading the first command from standard input.
.SH "SCRIPT FILES"
.PP
-If \fBtclsh\fR is invoked with arguments then the first argument
-is the name of a script file and any additional arguments
+.VS 8.5
+If \fBtclsh\fR is invoked with arguments then the first few arguments
+specify the name of a script file, and, optionally, the encoding of
+the text data stored in that script file.
+.VE 8.5
+Any additional arguments
are made available to the script as variables (see below).
Instead of reading commands from standard input \fBtclsh\fR will
read Tcl commands from the named file; \fBtclsh\fR will exit
when it reaches the end of the file.
-.VS 8.4
The end of the file may be marked either by the physical end of
-the medium, or by the character, '\\032' ('\\u001a', control-Z).
+the medium, or by the character,
+.QW \e032
+.PQ \eu001a ", control-Z" .
If this character is present in the file, the \fBtclsh\fR application
will read text up to but not including the character. An application
that requires this character in the file may safely encode it as
-``\\032'', ``\\x1a'', or ``\\u001a''; or may generate it by use of commands
-such as \fBformat\fR or \fBbinary\fR.
-.VE
+.QW \e032 ,
+.QW \ex1a ,
+or
+.QW \eu001a ;
+or may generate it by use of commands such as \fBformat\fR or \fBbinary\fR.
There is no automatic evaluation of \fB.tclshrc\fR when the name
of a script file is presented on the \fBtclsh\fR command
line, but the script file can always \fBsource\fR it if desired.
@@ -57,8 +64,8 @@ If you create a Tcl script in a file whose first line is
then you can invoke the script file directly from your shell if
you mark the file as executable.
This assumes that \fBtclsh\fR has been installed in the default
-location in /usr/local/bin; if it's installed somewhere else
-then you'll have to modify the above line to match.
+location in /usr/local/bin; if it is installed somewhere else
+then you will have to modify the above line to match.
Many UNIX systems do not allow the \fB#!\fR line to exceed about
30 characters in length, so be sure that the \fBtclsh\fR
executable can be accessed with a short file name.
@@ -71,7 +78,7 @@ following three lines:
exec tclsh "$0" "$@"\fR
.CE
This approach has three advantages over the approach in the previous
-paragraph. First, the location of the \fBtclsh\fR binary doesn't have
+paragraph. First, the location of the \fBtclsh\fR binary does not have
to be hard-wired into the script: it can be anywhere in your shell
search path. Second, it gets around the 30-character file name limit
in the previous approach.
@@ -89,13 +96,11 @@ When \fBtclsh\fR starts up, it treats all three lines as comments,
since the backslash at the end of the second line causes the third
line to be treated as part of the comment on the second line.
.PP
-.VS
-You should note that it is also common practise to install tclsh with
+You should note that it is also common practice to install tclsh with
its version number as part of the name. This has the advantage of
allowing multiple versions of Tcl to exist on the same system at once,
but also the disadvantage of making it harder to write scripts that
start up uniformly across different versions of Tcl.
-.VE
.SH "VARIABLES"
.PP
@@ -121,14 +126,16 @@ device), 0 otherwise.
.SH PROMPTS
.PP
When \fBtclsh\fR is invoked interactively it normally prompts for each
-command with ``\fB% \fR''. You can change the prompt by setting the
+command with
+.QW "\fB% \fR" .
+You can change the prompt by setting the
variables \fBtcl_prompt1\fR and \fBtcl_prompt2\fR. If variable
\fBtcl_prompt1\fR exists then it must consist of a Tcl script
to output a prompt; instead of outputting a prompt \fBtclsh\fR
will evaluate the script in \fBtcl_prompt1\fR.
The variable \fBtcl_prompt2\fR is used in a similar way when
-a newline is typed but the current command isn't yet complete;
-if \fBtcl_prompt2\fR isn't set then no prompt is output for
+a newline is typed but the current command is not yet complete;
+if \fBtcl_prompt2\fR is not set then no prompt is output for
incomplete commands.
.SH "STANDARD CHANNELS"
@@ -136,7 +143,7 @@ incomplete commands.
See \fBTcl_StandardChannels\fR for more explanations.
.SH "SEE ALSO"
-fconfigure(n), tclvars(n)
+encoding(n), fconfigure(n), tclvars(n)
.SH KEYWORDS
argument, interpreter, prompt, script file, shell
diff --git a/doc/tcltest.n b/doc/tcltest.n
index 497afe7..9ac8f66 100644
--- a/doc/tcltest.n
+++ b/doc/tcltest.n
@@ -9,14 +9,14 @@
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.so man.macros
-.TH "tcltest" n 2.2 tcltest "Tcl Bundled Packages"
+.TH "tcltest" n 2.3 tcltest "Tcl Bundled Packages"
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
tcltest \- Test harness support code and utilities
.SH SYNOPSIS
.nf
-\fBpackage require tcltest ?2.2.5?\fR
+\fBpackage require tcltest ?2.3?\fR
.sp
\fBtcltest::test \fIname description ?option value ...?\fR
\fBtcltest::test \fIname description ?constraints? body result\fR
@@ -77,12 +77,12 @@ in and exported from the \fB::tcltest\fR namespace, as indicated in
the \fBSYNOPSIS\fR above. In the following sections, all commands
will be described by their simple names, in the interest of brevity.
.PP
-The central command of \fBtcltest\fR is [\fBtest\fR] that defines
-and runs a test. Testing with [\fBtest\fR] involves evaluation
+The central command of \fBtcltest\fR is \fBtest\fR that defines
+and runs a test. Testing with \fBtest\fR involves evaluation
of a Tcl script and comparing the result to an expected result, as
configured and controlled by a number of options. Several other
commands provided by \fBtcltest\fR govern the configuration of
-[\fBtest\fR] and the collection of many [\fBtest\fR] commands into
+\fBtest\fR and the collection of many \fBtest\fR commands into
test suites.
.PP
See \fBCREATING TEST SUITES WITH TCLTEST\fR below for an extended example
@@ -93,29 +93,30 @@ for your Tcl-enabled code.
\fBtest\fR \fIname description ?option value ...?\fR
Defines and possibly runs a test with the name \fIname\fR and
description \fIdescription\fR. The name and description of a test
-are used in messages reported by [\fBtest\fR] during the
+are used in messages reported by \fBtest\fR during the
test, as configured by the options of \fBtcltest\fR. The
-remaining \fIoption value\fR arguments to [\fBtest\fR]
+remaining \fIoption value\fR arguments to \fBtest\fR
define the test, including the scripts to run, the conditions
under which to run them, the expected result, and the means
by which the expected and actual results should be compared.
See \fBTESTS\fR below for a complete description of the valid
-options and how they define a test. The [\fBtest\fR] command
-returns an empty string.
+options and how they define a test. The \fBtest\fR command
+returns an empty string.
.TP
\fBtest\fR \fIname description ?constraints? body result\fR
-This form of [\fBtest\fR] is provided to support test suites written
+This form of \fBtest\fR is provided to support test suites written
for version 1 of the \fBtcltest\fR package, and also a simpler
interface for a common usage. It is the same as
-[\fBtest\fR \fIname description\fB -constraints \fIconstraints\fB -body
-\fIbody\fB -result \fIresult\fR]. All other options to [\fBtest\fR]
+.QW "\fBtest\fR \fIname description\fB \-constraints \fIconstraints\fB \-body \fIbody\fB \-result \fIresult\fR" .
+All other options to \fBtest\fR
take their default values. When \fIconstraints\fR is omitted, this
-form of [\fBtest\fR] can be distinguished from the first because
-all \fIoption\fRs begin with ``-''.
+form of \fBtest\fR can be distinguished from the first because
+all \fIoption\fRs begin with
+.QW \- .
.TP
\fBloadTestedCommands\fR
Evaluates in the caller's context the script specified by
-[\fBconfigure -load\fR] or [\fBconfigure -loadfile\fR].
+\fBconfigure \-load\fR or \fBconfigure \-loadfile\fR.
Returns the result of that script evaluation, including any error
raised by the script. Use this command and the related
configuration options to provide the commands to be tested to
@@ -124,31 +125,31 @@ the interpreter running the test suite.
\fBmakeFile\fR \fIcontents name ?directory?\fR
Creates a file named \fIname\fR relative to
directory \fIdirectory\fR and write \fIcontents\fR
-to that file using the encoding [\fBencoding system\fR].
+to that file using the encoding \fBencoding system\fR.
If \fIcontents\fR does not end with a newline, a newline
will be appended so that the file named \fIname\fR
does end with a newline. Because the system encoding is used,
this command is only suitable for making text files.
The file will be removed by the next evaluation
-of [\fBcleanupTests\fR], unless it is removed by
-[\fBremoveFile\fR] first. The default value of
-\fIdirectory\fR is the directory [\fBconfigure -tmpdir\fR].
+of \fBcleanupTests\fR, unless it is removed by
+\fBremoveFile\fR first. The default value of
+\fIdirectory\fR is the directory \fBconfigure \-tmpdir\fR.
Returns the full path of the file created. Use this command
to create any text file required by a test with contents as needed.
.TP
\fBremoveFile\fR \fIname ?directory?\fR
Forces the file referenced by \fIname\fR to be removed. This file name
should be relative to \fIdirectory\fR. The default value of
-\fIdirectory\fR is the directory [\fBconfigure -tmpdir\fR].
+\fIdirectory\fR is the directory \fBconfigure \-tmpdir\fR.
Returns an empty string. Use this command to delete files
-created by [\fBmakeFile\fR].
+created by \fBmakeFile\fR.
.TP
\fBmakeDirectory\fR \fIname ?directory?\fR
Creates a directory named \fIname\fR relative to directory \fIdirectory\fR.
-The directory will be removed by the next evaluation of [\fBcleanupTests\fR],
-unless it is removed by [\fBremoveDirectory\fR] first.
+The directory will be removed by the next evaluation of \fBcleanupTests\fR,
+unless it is removed by \fBremoveDirectory\fR first.
The default value of \fIdirectory\fR is the directory
-[\fBconfigure -tmpdir\fR].
+\fBconfigure \-tmpdir\fR.
Returns the full path of the directory created. Use this command
to create any directories that are required to exist by a test.
.TP
@@ -156,16 +157,16 @@ to create any directories that are required to exist by a test.
Forces the directory referenced by \fIname\fR to be removed. This
directory should be relative to \fIdirectory\fR.
The default value of \fIdirectory\fR is the directory
-[\fBconfigure -tmpdir\fR].
+\fBconfigure \-tmpdir\fR.
Returns an empty string. Use this command to delete any directories
-created by [\fBmakeDirectory\fR].
+created by \fBmakeDirectory\fR.
.TP
\fBviewFile\fR \fIfile ?directory?\fR
Returns the contents of \fIfile\fR, except for any
-final newline, just as [\fBread -nonewline\fR] would return.
-This file name should be relative to \fIdirectory\fR.
+final newline, just as \fBread \-nonewline\fR would return.
+This file name should be relative to \fIdirectory\fR.
The default value of \fIdirectory\fR is the directory
-[\fBconfigure -tmpdir\fR]. Use this command
+\fBconfigure \-tmpdir\fR. Use this command
as a convenient way to turn the contents of a file generated
by a test into the result of that test for matching against
an expected result. The contents of the file are read using
@@ -176,25 +177,27 @@ files.
Intended to clean up and summarize after several tests have been
run. Typically called once per test file, at the end of the file
after all tests have been completed. For best effectiveness, be
-sure that the [\fBcleanupTests\fR] is evaluated even if an error
-occurs earlier in the test file evaluation.
-.sp
+sure that the \fBcleanupTests\fR is evaluated even if an error
+occurs earlier in the test file evaluation.
+.RS
+.PP
Prints statistics about the tests run and removes files that were
-created by [\fBmakeDirectory\fR] and [\fBmakeFile\fR] since the
-last [\fBcleanupTests\fR]. Names of files and directories
-in the directory [\fBconfigure -tmpdir\fR] created since
-the last [\fBcleanupTests\fR], but not created by
-[\fBmakeFile\fR] or [\fBmakeDirectory\fR] are printed
-to [\fBoutputChannel\fR]. This command also restores the original
-shell environment, as described by the ::env
+created by \fBmakeDirectory\fR and \fBmakeFile\fR since the
+last \fBcleanupTests\fR. Names of files and directories
+in the directory \fBconfigure \-tmpdir\fR created since
+the last \fBcleanupTests\fR, but not created by
+\fBmakeFile\fR or \fBmakeDirectory\fR are printed
+to \fBoutputChannel\fR. This command also restores the original
+shell environment, as described by the \fB::env\fR
array. Returns an empty string.
+.RE
.TP
\fBrunAllTests\fR
This is a master command meant to run an entire suite of tests,
spanning multiple files and/or directories, as governed by
the configurable options of \fBtcltest\fR. See \fBRUNNING ALL TESTS\fR
below for a complete description of the many variations possible
-with [\fBrunAllTests\fR].
+with \fBrunAllTests\fR.
.SH "CONFIGURATION COMMANDS"
.TP
\fBconfigure\fR
@@ -212,19 +215,21 @@ corresponding value \fIvalue\fR, in order. Raises an error if
an \fIoption\fR is not a supported configurable option, or if
\fIvalue\fR is not a valid value for the corresponding \fIoption\fR,
or if a \fIvalue\fR is not provided. When an error is raised, the
-operation of [\fBconfigure\fR] is halted, and subsequent \fIoption value\fR
+operation of \fBconfigure\fR is halted, and subsequent \fIoption value\fR
arguments are not processed.
-.sp
+.RS
+.PP
If the environment variable \fB::env(TCLTEST_OPTIONS)\fR exists when
-the \fBtcltest\fR package is loaded (by [\fBpackage require tcltest\fR])
-then its value is taken as a list of arguments to pass to [\fBconfigure\fR].
+the \fBtcltest\fR package is loaded (by \fBpackage require tcltest\fR)
+then its value is taken as a list of arguments to pass to \fBconfigure\fR.
This allows the default values of the configuration options to be
set by the environment.
+.RE
.TP
\fBcustomMatch \fImode script\fR
-Registers \fImode\fR as a new legal value of the \fB-match\fR option
-to [\fBtest\fR]. When the \fB-match \fImode\fR option is
-passed to [\fBtest\fR], the script \fIscript\fR will be evaluated
+Registers \fImode\fR as a new legal value of the \fB\-match\fR option
+to \fBtest\fR. When the \fB\-match \fImode\fR option is
+passed to \fBtest\fR, the script \fIscript\fR will be evaluated
to compare the actual result of evaluating the body of the test
to the expected result.
To perform the match, the \fIscript\fR is completed with two additional
@@ -232,82 +237,82 @@ words, the expected result, and the actual result, and the completed script
is evaluated in the global namespace.
The completed script is expected to return a boolean value indicating
whether or not the results match. The built-in matching modes of
-[\fBtest\fR] are \fBexact\fR, \fBglob\fR, and \fBregexp\fR.
+\fBtest\fR are \fBexact\fR, \fBglob\fR, and \fBregexp\fR.
.TP
\fBtestConstraint \fIconstraint ?boolean?\fR
Sets or returns the boolean value associated with the named \fIconstraint\fR.
See \fBTEST CONSTRAINTS\fR below for more information.
.TP
\fBinterpreter\fR \fI?executableName?\fR
-Sets or returns the name of the executable to be [\fBexec\fR]ed by
-[\fBrunAllTests\fR] to run each test file when
-[\fBconfigure -singleproc\fR] is false.
-The default value for [\fBinterpreter\fR] is the name of the
-currently running program as returned by [\fBinfo nameofexecutable\fR].
+Sets or returns the name of the executable to be \fBexec\fRed by
+\fBrunAllTests\fR to run each test file when
+\fBconfigure \-singleproc\fR is false.
+The default value for \fBinterpreter\fR is the name of the
+currently running program as returned by \fBinfo nameofexecutable\fR.
.TP
\fBoutputChannel\fR \fI?channelID?\fR
Sets or returns the output channel ID. This defaults to stdout.
Any test that prints test related output should send
-that output to [\fBoutputChannel\fR] rather than letting
+that output to \fBoutputChannel\fR rather than letting
that output default to stdout.
.TP
\fBerrorChannel\fR \fI?channelID?\fR
Sets or returns the error channel ID. This defaults to stderr.
Any test that prints error messages should send
-that output to [\fBerrorChannel\fR] rather than printing
+that output to \fBerrorChannel\fR rather than printing
directly to stderr.
.SH "SHORTCUT COMMANDS"
.TP
\fBdebug \fI?level?\fR
-Same as [\fBconfigure -debug \fI?level?\fR].
+Same as \fBconfigure \-debug \fI?level?\fR.
.TP
\fBerrorFile \fI?filename?\fR
-Same as [\fBconfigure -errfile \fI?filename?\fR].
+Same as \fBconfigure \-errfile \fI?filename?\fR.
.TP
\fBlimitConstraints \fI?boolean?\fR
-Same as [\fBconfigure -limitconstraints \fI?boolean?\fR].
+Same as \fBconfigure \-limitconstraints \fI?boolean?\fR.
.TP
\fBloadFile \fI?filename?\fR
-Same as [\fBconfigure -loadfile \fI?filename?\fR].
+Same as \fBconfigure \-loadfile \fI?filename?\fR.
.TP
\fBloadScript \fI?script?\fR
-Same as [\fBconfigure -load \fI?script?\fR].
+Same as \fBconfigure \-load \fI?script?\fR.
.TP
\fBmatch \fI?patternList?\fR
-Same as [\fBconfigure -match \fI?patternList?\fR].
+Same as \fBconfigure \-match \fI?patternList?\fR.
.TP
\fBmatchDirectories \fI?patternList?\fR
-Same as [\fBconfigure -relateddir \fI?patternList?\fR].
+Same as \fBconfigure \-relateddir \fI?patternList?\fR.
.TP
\fBmatchFiles \fI?patternList?\fR
-Same as [\fBconfigure -file \fI?patternList?\fR].
+Same as \fBconfigure \-file \fI?patternList?\fR.
.TP
\fBoutputFile \fI?filename?\fR
-Same as [\fBconfigure -outfile \fI?filename?\fR].
+Same as \fBconfigure \-outfile \fI?filename?\fR.
.TP
\fBpreserveCore \fI?level?\fR
-Same as [\fBconfigure -preservecore \fI?level?\fR].
+Same as \fBconfigure \-preservecore \fI?level?\fR.
.TP
\fBsingleProcess \fI?boolean?\fR
-Same as [\fBconfigure -singleproc \fI?boolean?\fR].
+Same as \fBconfigure \-singleproc \fI?boolean?\fR.
.TP
\fBskip \fI?patternList?\fR
-Same as [\fBconfigure -skip \fI?patternList?\fR].
+Same as \fBconfigure \-skip \fI?patternList?\fR.
.TP
\fBskipDirectories \fI?patternList?\fR
-Same as [\fBconfigure -asidefromdir \fI?patternList?\fR].
+Same as \fBconfigure \-asidefromdir \fI?patternList?\fR.
.TP
\fBskipFiles \fI?patternList?\fR
-Same as [\fBconfigure -notfile \fI?patternList?\fR].
+Same as \fBconfigure \-notfile \fI?patternList?\fR.
.TP
\fBtemporaryDirectory \fI?directory?\fR
-Same as [\fBconfigure -tmpdir \fI?directory?\fR].
+Same as \fBconfigure \-tmpdir \fI?directory?\fR.
.TP
\fBtestsDirectory \fI?directory?\fR
-Same as [\fBconfigure -testdir \fI?directory?\fR].
+Same as \fBconfigure \-testdir \fI?directory?\fR.
.TP
\fBverbose \fI?level?\fR
-Same as [\fBconfigure -verbose \fI?level?\fR].
+Same as \fBconfigure \-verbose \fI?level?\fR.
.SH "OTHER COMMANDS"
.PP
The remaining commands provided by \fBtcltest\fR have better
@@ -316,43 +321,49 @@ are retained to support existing test suites, but should be avoided
in new code.
.TP
\fBtest\fR \fIname description optionList\fR
-This form of [\fBtest\fR] was provided to enable passing many
-options spanning several lines to [\fBtest\fR] as a single
+This form of \fBtest\fR was provided to enable passing many
+options spanning several lines to \fBtest\fR as a single
argument quoted by braces, rather than needing to backslash quote
-the newlines between arguments to [\fBtest\fR]. The \fIoptionList\fR
+the newlines between arguments to \fBtest\fR. The \fIoptionList\fR
argument is expected to be a list with an even number of elements
representing \fIoption\fR and \fIvalue\fR arguments to pass
-to [\fBtest\fR]. However, these values are not passed directly, as
-in the alternate forms of [\fBswitch\fR]. Instead, this form makes
+to \fBtest\fR. However, these values are not passed directly, as
+in the alternate forms of \fBswitch\fR. Instead, this form makes
an unfortunate attempt to overthrow Tcl's substitution rules by
performing substitutions on some of the list elements as an attempt to
-implement a ``do what I mean'' interpretation of a brace-enclosed
-``block''. The result is nearly impossible to document clearly, and
+implement a
+.QW "do what I mean"
+interpretation of a brace-enclosed
+.QW block .
+The result is nearly impossible to document clearly, and
for that reason this form is not recommended. See the examples in
\fBCREATING TEST SUITES WITH TCLTEST\fR below to see that this
form is really not necessary to avoid backslash-quoted newlines.
If you insist on using this form, examine
the source code of \fBtcltest\fR if you want to know the substitution
details, or just enclose the third through last argument
-to [\fBtest\fR] in braces and hope for the best.
+to \fBtest\fR in braces and hope for the best.
.TP
\fBworkingDirectory\fR \fI?directoryName?\fR
Sets or returns the current working directory when the test suite is
running. The default value for workingDirectory is the directory in
-which the test suite was launched. The Tcl commands [\fBcd\fR] and
-[\fBpwd\fR] are sufficient replacements.
+which the test suite was launched. The Tcl commands \fBcd\fR and
+\fBpwd\fR are sufficient replacements.
.TP
\fBnormalizeMsg\fR \fImsg\fR
-Returns the result of removing the ``extra'' newlines from \fImsg\fR,
-where ``extra'' is rather imprecise. Tcl offers plenty of string
+Returns the result of removing the
+.QW extra
+newlines from \fImsg\fR, where
+.QW extra
+is rather imprecise. Tcl offers plenty of string
processing commands to modify strings as you wish, and
-[\fBcustomMatch\fR] allows flexible matching of actual and expected
+\fBcustomMatch\fR allows flexible matching of actual and expected
results.
.TP
\fBnormalizePath\fR \fIpathVar\fR
Resolves symlinks in a path, thus creating a path without internal
redirection. It is assumed that \fIpathVar\fR is absolute.
-\fIpathVar\fR is modified in place. The Tcl command [\fBfile normalize\fR]
+\fIpathVar\fR is modified in place. The Tcl command \fBfile normalize\fR
is a sufficient replacement.
.TP
\fBbytestring\fR \fIstring\fR
@@ -362,52 +373,54 @@ value supplied in \fIstring\fR. This allows the tester to create
denormalized or improperly formed strings to pass to C procedures that
are supposed to accept strings with embedded NULL types and confirm
that a string result has a certain pattern of bytes. This is
-exactly equivalent to the Tcl command [\fBencoding convertfrom identity\fR].
+exactly equivalent to the Tcl command \fBencoding convertfrom identity\fR.
.SH TESTS
.PP
-The [\fBtest\fR] command is the heart of the \fBtcltest\fR package.
+The \fBtest\fR command is the heart of the \fBtcltest\fR package.
Its essential function is to evaluate a Tcl script and compare
-the result with an expected result. The options of [\fBtest\fR]
+the result with an expected result. The options of \fBtest\fR
define the test script, the environment in which to evaluate it,
the expected result, and how the compare the actual result to
the expected result. Some configuration options of \fBtcltest\fR
-also influence how [\fBtest\fR] operates.
+also influence how \fBtest\fR operates.
+.PP
+The valid options for \fBtest\fR are summarized:
.PP
-The valid options for [\fBtest\fR] are summarized:
.CS
-.ta 0.8i
\fBtest\fR \fIname\fR \fIdescription\fR
- ?-constraints \fIkeywordList|expression\fR?
- ?-setup \fIsetupScript\fR?
- ?-body \fItestScript\fR?
- ?-cleanup \fIcleanupScript\fR?
- ?-result \fIexpectedAnswer\fR?
- ?-output \fIexpectedOutput\fR?
- ?-errorOutput \fIexpectedError\fR?
- ?-returnCodes \fIcodeList\fR?
- ?-match \fImode\fR?
+ ?-constraints \fIkeywordList|expression\fR?
+ ?-setup \fIsetupScript\fR?
+ ?-body \fItestScript\fR?
+ ?-cleanup \fIcleanupScript\fR?
+ ?-result \fIexpectedAnswer\fR?
+ ?-output \fIexpectedOutput\fR?
+ ?-errorOutput \fIexpectedError\fR?
+ ?-returnCodes \fIcodeList\fR?
+ ?-match \fImode\fR?
.CE
+.PP
The \fIname\fR may be any string. It is conventional to choose
a \fIname\fR according to the pattern:
+.PP
.CS
\fItarget\fR-\fImajorNum\fR.\fIminorNum\fR
.CE
+.PP
For white-box (regression) tests, the target should be the name of the
C function or Tcl procedure being tested. For black-box tests, the
target should be the name of the feature being tested. Some conventions
call for the names of black-box tests to have the suffix \fB_bb\fR.
Related tests should share a major number. As a test suite evolves,
it is best to have the same test name continue to correspond to the
-same test, so that it remains meaningful to say things like ``Test
-foo-1.3 passed in all releases up to 3.4, but began failing in
-release 3.5.''
+same test, so that it remains meaningful to say things like
+.QW "Test foo-1.3 passed in all releases up to 3.4, but began failing in release 3.5."
.PP
-During evaluation of [\fBtest\fR], the \fIname\fR will be compared
+During evaluation of \fBtest\fR, the \fIname\fR will be compared
to the lists of string matching patterns returned by
-[\fBconfigure -match\fR], and [\fBconfigure -skip\fR]. The test
+\fBconfigure \-match\fR, and \fBconfigure \-skip\fR. The test
will be run only if \fIname\fR matches any of the patterns from
-[\fBconfigure -match\fR] and matches none of the patterns
-from [\fBconfigure -skip\fR].
+\fBconfigure \-match\fR and matches none of the patterns
+from \fBconfigure \-skip\fR.
.PP
The \fIdescription\fR should be a short textual description of the
test. The \fIdescription\fR is included in output produced by the
@@ -419,124 +432,125 @@ a bug, include the bug ID in the description.
.PP
Valid attributes and associated values are:
.TP
-\fB-constraints \fIkeywordList|expression\fR
-The optional \fB-constraints\fR attribute can be list of one or more
-keywords or an expression. If the \fB-constraints\fR value is a list of
+\fB\-constraints \fIkeywordList|expression\fR
+The optional \fB\-constraints\fR attribute can be list of one or more
+keywords or an expression. If the \fB\-constraints\fR value is a list of
keywords, each of these keywords should be the name of a constraint
-defined by a call to [\fBtestConstraint\fR]. If any of the listed
+defined by a call to \fBtestConstraint\fR. If any of the listed
constraints is false or does not exist, the test is skipped. If the
-\fB-constraints\fR value is an expression, that expression
+\fB\-constraints\fR value is an expression, that expression
is evaluated. If the expression evaluates to true, then the test is run.
-Note that the expression form of \fB-constraints\fR may interfere with the
-operation of [\fBconfigure -constraints\fR] and
-[\fBconfigure -limitconstraints\fR], and is not recommended.
+Note that the expression form of \fB\-constraints\fR may interfere with the
+operation of \fBconfigure \-constraints\fR and
+\fBconfigure \-limitconstraints\fR, and is not recommended.
Appropriate constraints should be added to any tests that should
not always be run. That is, conditional evaluation of a test
-should be accomplished by the \fB-constraints\fR option, not by
-conditional evaluation of [\fBtest\fR]. In that way, the same
+should be accomplished by the \fB\-constraints\fR option, not by
+conditional evaluation of \fBtest\fR. In that way, the same
number of tests are always reported by the test suite, though
the number skipped may change based on the testing environment.
The default value is an empty list.
See \fBTEST CONSTRAINTS\fR below for a list of built-in constraints
and information on how to add your own constraints.
.TP
-\fB-setup \fIscript\fR
-The optional \fB-setup\fR attribute indicates a \fIscript\fR that will be run
-before the script indicated by the \fB-body\fR attribute. If evaluation
+\fB\-setup \fIscript\fR
+The optional \fB\-setup\fR attribute indicates a \fIscript\fR that will be run
+before the script indicated by the \fB\-body\fR attribute. If evaluation
of \fIscript\fR raises an error, the test will fail. The default value
is an empty script.
.TP
-\fB-body \fIscript\fR
-The \fB-body\fR attribute indicates the \fIscript\fR to run to carry out the
+\fB\-body \fIscript\fR
+The \fB\-body\fR attribute indicates the \fIscript\fR to run to carry out the
test. It must return a result that can be checked for correctness.
If evaluation of \fIscript\fR raises an error, the test will fail.
The default value is an empty script.
.TP
-\fB-cleanup \fIscript\fR
-The optional \fB-cleanup\fR attribute indicates a \fIscript\fR that will be
-run after the script indicated by the \fB-body\fR attribute.
+\fB\-cleanup \fIscript\fR
+The optional \fB\-cleanup\fR attribute indicates a \fIscript\fR that will be
+run after the script indicated by the \fB\-body\fR attribute.
If evaluation of \fIscript\fR raises an error, the test will fail.
The default value is an empty script.
.TP
-\fB-match \fImode\fR
-The \fB-match\fR attribute determines how expected answers supplied by
-\fB-result\fR, \fB-output\fR, and \fB-errorOutput\fR are compared. Valid
+\fB\-match \fImode\fR
+The \fB\-match\fR attribute determines how expected answers supplied by
+\fB\-result\fR, \fB\-output\fR, and \fB\-errorOutput\fR are compared. Valid
values for \fImode\fR are \fBregexp\fR, \fBglob\fR, \fBexact\fR, and
-any value registered by a prior call to [\fBcustomMatch\fR]. The default
+any value registered by a prior call to \fBcustomMatch\fR. The default
value is \fBexact\fR.
.TP
-\fB-result \fIexpectedValue\fR
-The \fB-result\fR attribute supplies the \fIexpectedValue\fR against which
+\fB\-result \fIexpectedValue\fR
+The \fB\-result\fR attribute supplies the \fIexpectedValue\fR against which
the return value from script will be compared. The default value is
an empty string.
.TP
-\fB-output \fIexpectedValue\fR
-The \fB-output\fR attribute supplies the \fIexpectedValue\fR against which
-any output sent to \fBstdout\fR or [\fBoutputChannel\fR] during evaluation
+\fB\-output \fIexpectedValue\fR
+The \fB\-output\fR attribute supplies the \fIexpectedValue\fR against which
+any output sent to \fBstdout\fR or \fBoutputChannel\fR during evaluation
of the script(s) will be compared. Note that only output printed using
-[\fB::puts\fR] is used for comparison. If \fB-output\fR is not specified,
-output sent to \fBstdout\fR and [\fBoutputChannel\fR] is not processed for
+\fB::puts\fR is used for comparison. If \fB\-output\fR is not specified,
+output sent to \fBstdout\fR and \fBoutputChannel\fR is not processed for
comparison.
.TP
-\fB-errorOutput \fIexpectedValue\fR
-The \fB-errorOutput\fR attribute supplies the \fIexpectedValue\fR against
-which any output sent to \fBstderr\fR or [\fBerrorChannel\fR] during
+\fB\-errorOutput \fIexpectedValue\fR
+The \fB\-errorOutput\fR attribute supplies the \fIexpectedValue\fR against
+which any output sent to \fBstderr\fR or \fBerrorChannel\fR during
evaluation of the script(s) will be compared. Note that only output
-printed using [\fB::puts\fR] is used for comparison. If \fB-errorOutput\fR
-is not specified, output sent to \fBstderr\fR and [\fBerrorChannel\fR] is
+printed using \fB::puts\fR is used for comparison. If \fB\-errorOutput\fR
+is not specified, output sent to \fBstderr\fR and \fBerrorChannel\fR is
not processed for comparison.
.TP
-\fB-returnCodes \fIexpectedCodeList\fR
-The optional \fB-returnCodes\fR attribute supplies \fIexpectedCodeList\fR,
+\fB\-returnCodes \fIexpectedCodeList\fR
+The optional \fB\-returnCodes\fR attribute supplies \fIexpectedCodeList\fR,
a list of return codes that may be accepted from evaluation of the
-\fB-body\fR script. If evaluation of the \fB-body\fR script returns
+\fB\-body\fR script. If evaluation of the \fB\-body\fR script returns
a code not in the \fIexpectedCodeList\fR, the test fails. All
-return codes known to [\fBreturn\fR], in both numeric and symbolic
+return codes known to \fBreturn\fR, in both numeric and symbolic
form, including extended return codes, are acceptable elements in
-the \fIexpectedCodeList\fR. Default value is \fB{ok return}\fR.
+the \fIexpectedCodeList\fR. Default value is
+.QW \fBok return\fR.
.PP
-To pass, a test must successfully evaluate its \fB-setup\fR, \fB-body\fR,
-and \fB-cleanup\fR scripts. The return code of the \fB-body\fR script and
+To pass, a test must successfully evaluate its \fB\-setup\fR, \fB\-body\fR,
+and \fB\-cleanup\fR scripts. The return code of the \fB\-body\fR script and
its result must match expected values, and if specified, output and error
-data from the test must match expected \fB-output\fR and \fB-errorOutput\fR
+data from the test must match expected \fB\-output\fR and \fB\-errorOutput\fR
values. If any of these conditions are not met, then the test fails.
Note that all scripts are evaluated in the context of the caller
-of [\fBtest\fR].
+of \fBtest\fR.
.PP
-As long as [\fBtest\fR] is called with valid syntax and legal
+As long as \fBtest\fR is called with valid syntax and legal
values for all attributes, it will not raise an error. Test
-failures are instead reported as output written to [\fBoutputChannel\fR].
+failures are instead reported as output written to \fBoutputChannel\fR.
In default operation, a successful test produces no output. The output
-messages produced by [\fBtest\fR] are controlled by the
-[\fBconfigure -verbose\fR] option as described in \fBCONFIGURABLE OPTIONS\fR
+messages produced by \fBtest\fR are controlled by the
+\fBconfigure \-verbose\fR option as described in \fBCONFIGURABLE OPTIONS\fR
below. Any output produced by the test scripts themselves should be
-produced using [\fB::puts\fR] to [\fBoutputChannel\fR] or
-[\fBerrorChannel\fR], so that users of the test suite may
-easily capture output with the [\fBconfigure -outfile\fR] and
-[\fBconfigure -errfile\fR] options, and so that the \fB-output\fR
-and \fB-errorOutput\fR attributes work properly.
+produced using \fB::puts\fR to \fBoutputChannel\fR or
+\fBerrorChannel\fR, so that users of the test suite may
+easily capture output with the \fBconfigure \-outfile\fR and
+\fBconfigure \-errfile\fR options, and so that the \fB\-output\fR
+and \fB\-errorOutput\fR attributes work properly.
.SH "TEST CONSTRAINTS"
.PP
Constraints are used to determine whether or not a test should be skipped.
Each constraint has a name, which may be any string, and a boolean
-value. Each [\fBtest\fR] has a \fB-constraints\fR value which is a
+value. Each \fBtest\fR has a \fB\-constraints\fR value which is a
list of constraint names. There are two modes of constraint control.
Most frequently, the default mode is used, indicated by a setting
-of [\fBconfigure -limitconstraints\fR] to false. The test will run
+of \fBconfigure \-limitconstraints\fR to false. The test will run
only if all constraints in the list are true-valued. Thus,
-the \fB-constraints\fR option of [\fBtest\fR] is a convenient, symbolic
+the \fB\-constraints\fR option of \fBtest\fR is a convenient, symbolic
way to define any conditions required for the test to be possible or
-meaningful. For example, a [\fBtest\fR] with \fB-constraints unix\fR
+meaningful. For example, a \fBtest\fR with \fB\-constraints unix\fR
will only be run if the constraint \fBunix\fR is true, which indicates
the test suite is being run on a Unix platform.
.PP
-Each [\fBtest\fR] should include whatever \fB-constraints\fR are
+Each \fBtest\fR should include whatever \fB\-constraints\fR are
required to constrain it to run only where appropriate. Several
constraints are pre-defined in the \fBtcltest\fR package, listed
below. The registration of user-defined constraints is performed
-by the [\fBtestConstraint\fR] command. User-defined constraints
+by the \fBtestConstraint\fR command. User-defined constraints
may appear within a test file, or within the script specified
-by the [\fBconfigure -load\fR] or [\fBconfigure -loadfile\fR]
+by the \fBconfigure \-load\fR or \fBconfigure \-loadfile\fR
options.
.PP
The following is a list of constraints pre-defined by the
@@ -581,15 +595,15 @@ test can not be run on a Mac. This flag is used
to temporarily disable a test.
.TP
\fIunixCrash\fR
-test crashes if it's run on Unix. This flag is used to temporarily
+test crashes if it is run on Unix. This flag is used to temporarily
disable a test.
.TP
\fIwinCrash\fR
-test crashes if it's run on Windows. This flag is used to temporarily
+test crashes if it is run on Windows. This flag is used to temporarily
disable a test.
.TP
\fImacCrash\fR
-test crashes if it's run on a Mac. This flag is used to temporarily
+test crashes if it is run on a Mac. This flag is used to temporarily
disable a test.
.TP
\fIemptyTest\fR
@@ -643,46 +657,50 @@ test can only run if Unix user is not root
.TP
\fIeformat\fR
test can only run if app has a working version of sprintf with respect
-to the "e" format of floating-point numbers.
+to the
+.QW e
+format of floating-point numbers.
.TP
\fIstdio\fR
-test can only be run if [\fBinterpreter\fR] can be [\fBopen\fR]ed
+test can only be run if \fBinterpreter\fR can be \fBopen\fRed
as a pipe.
.PP
The alternative mode of constraint control is enabled by setting
-[\fBconfigure -limitconstraints\fR] to true. With that configuration
+\fBconfigure \-limitconstraints\fR to true. With that configuration
setting, all existing constraints other than those in the constraint
-list returned by [\fBconfigure -constraints\fR] are set to false.
-When the value of [\fBconfigure -constraints\fR]
+list returned by \fBconfigure \-constraints\fR are set to false.
+When the value of \fBconfigure \-constraints\fR
is set, all those constraints are set to true. The effect is that
-when both options [\fBconfigure -constraints\fR] and
-[\fBconfigure -limitconstraints\fR] are in use, only those tests including
-only constraints from the [\fBconfigure -constraints\fR] list
+when both options \fBconfigure \-constraints\fR and
+\fBconfigure \-limitconstraints\fR are in use, only those tests including
+only constraints from the \fBconfigure \-constraints\fR list
are run; all others are skipped. For example, one might set
up a configuration with
+.PP
.CS
\fBconfigure\fR -constraints knownBug \e
-limitconstraints true \e
-verbose pass
.CE
+.PP
to run exactly those tests that exercise known bugs, and discover
-whether any of them pass, indicating the bug had been fixed.
+whether any of them pass, indicating the bug had been fixed.
.SH "RUNNING ALL TESTS"
.PP
-The single command [\fBrunAllTests\fR] is evaluated to run an entire
+The single command \fBrunAllTests\fR is evaluated to run an entire
test suite, spanning many files and directories. The configuration
options of \fBtcltest\fR control the precise operations. The
-[\fBrunAllTests\fR] command begins by printing a summary of its
-configuration to [\fBoutputChannel\fR].
+\fBrunAllTests\fR command begins by printing a summary of its
+configuration to \fBoutputChannel\fR.
.PP
Test files to be evaluated are sought in the directory
-[\fBconfigure -testdir\fR]. The list of files in that directory
-that match any of the patterns in [\fBconfigure -file\fR] and
-match none of the patterns in [\fBconfigure -notfile\fR] is generated
+\fBconfigure \-testdir\fR. The list of files in that directory
+that match any of the patterns in \fBconfigure \-file\fR and
+match none of the patterns in \fBconfigure \-notfile\fR is generated
and sorted. Then each file will be evaluated in turn. If
-[\fBconfigure -singleproc\fR] is true, then each file will
-be [\fBsource\fR]d in the caller's context. If it is false,
-then a copy of [\fBinterpreter\fR] will be [\fBexec\fR]d to
+\fBconfigure \-singleproc\fR is true, then each file will
+be \fBsource\fRd in the caller's context. If it is false,
+then a copy of \fBinterpreter\fR will be \fBexec\fR'd to
evaluate each file. The multi-process operation is useful
when testing can cause errors so severe that a process
terminates. Although such an error may terminate a child
@@ -690,17 +708,17 @@ process evaluating one file, the master process can continue
with the rest of the test suite. In multi-process operation,
the configuration of \fBtcltest\fR in the master process is
passed to the child processes as command line arguments,
-with the exception of [\fBconfigure -outfile\fR]. The
-[\fBrunAllTests\fR] command in the
+with the exception of \fBconfigure \-outfile\fR. The
+\fBrunAllTests\fR command in the
master process collects all output from the child processes
and collates their results into one master report. Any
reports of individual test failures, or messages requested
-by a [\fBconfigure -verbose\fR] setting are passed directly
-on to [\fBoutputChannel\fR] by the master process.
+by a \fBconfigure \-verbose\fR setting are passed directly
+on to \fBoutputChannel\fR by the master process.
.PP
After evaluating all selected test files, a summary of the
-results is printed to [\fBoutputChannel\fR]. The summary
-includes the total number of [\fBtest\fR]s evaluated, broken
+results is printed to \fBoutputChannel\fR. The summary
+includes the total number of \fBtest\fRs evaluated, broken
down into those skipped, those passed, and those failed.
The summary also notes the number of files evaluated, and the names
of any files with failing tests or errors. A list of
@@ -708,45 +726,45 @@ the constraints that caused tests to be skipped, and the
number of tests skipped for each is also printed. Also,
messages are printed if it appears that evaluation of
a test file has caused any temporary files to be left
-behind in [\fBconfigure -tmpdir\fR].
+behind in \fBconfigure \-tmpdir\fR.
.PP
Having completed and summarized all selected test files,
-[\fBrunAllTests\fR] then recursively acts on subdirectories
-of [\fBconfigure -testdir\fR]. All subdirectories that
-match any of the patterns in [\fBconfigure -relateddir\fR]
+\fBrunAllTests\fR then recursively acts on subdirectories
+of \fBconfigure \-testdir\fR. All subdirectories that
+match any of the patterns in \fBconfigure \-relateddir\fR
and do not match any of the patterns in
-[\fBconfigure -asidefromdir\fR] are examined. If
+\fBconfigure \-asidefromdir\fR are examined. If
a file named \fBall.tcl\fR is found in such a directory,
-it will be [\fBsource\fR]d in the caller's context.
+it will be \fBsource\fRd in the caller's context.
Whether or not an examined directory contains an
\fBall.tcl\fR file, its subdirectories are also scanned
-against the [\fBconfigure -relateddir\fR] and
-[\fBconfigure -asidefromdir\fR] patterns. In this way,
+against the \fBconfigure \-relateddir\fR and
+\fBconfigure \-asidefromdir\fR patterns. In this way,
many directories in a directory tree can have all their
-test files evaluated by a single [\fBrunAllTests\fR]
+test files evaluated by a single \fBrunAllTests\fR
command.
.SH "CONFIGURABLE OPTIONS"
-The [\fBconfigure\fR] command is used to set and query the configurable
+The \fBconfigure\fR command is used to set and query the configurable
options of \fBtcltest\fR. The valid options are:
.TP
-\fB-singleproc \fIboolean\fR
-Controls whether or not [\fBrunAllTests\fR] spawns a child process for
+\fB\-singleproc \fIboolean\fR
+Controls whether or not \fBrunAllTests\fR spawns a child process for
each test file. No spawning when \fIboolean\fR is true. Default
value is false.
.TP
-\fB-debug \fIlevel\fR
+\fB\-debug \fIlevel\fR
Sets the debug level to \fIlevel\fR, an integer value indicating how
much debugging information should be printed to stdout. Note that
debug messages always go to stdout, independent of the value of
-[\fBconfigure -outfile\fR]. Default value is 0. Levels are defined as:
+\fBconfigure \-outfile\fR. Default value is 0. Levels are defined as:
.RS
.IP 0
Do not display any debug information.
.IP 1
Display information regarding whether a test is skipped because it
-doesn't match any of the tests that were specified using by
-[\fBconfigure -match\fR] (userSpecifiedNonMatch) or matches any of
-the tests specified by [\fBconfigure -skip\fR] (userSpecifiedSkip). Also
+does not match any of the tests that were specified using by
+\fBconfigure \-match\fR (userSpecifiedNonMatch) or matches any of
+the tests specified by \fBconfigure \-skip\fR (userSpecifiedSkip). Also
print warnings about possible lack of cleanup or balance in test files.
Also print warnings about any re-use of test names.
.IP 2
@@ -758,10 +776,10 @@ Display information regarding what individual procs in the test
harness are doing.
.RE
.TP
-\fB-verbose \fIlevel\fR
+\fB\-verbose \fIlevel\fR
Sets the type of output verbosity desired to \fIlevel\fR,
a list of zero or more of the elements \fBbody\fR, \fBpass\fR,
-\fBskip\fR, \fBstart\fR, and \fBerror\fR. Default value
+\fBskip\fR, \fBstart\fR, \fBerror\fR and \fBline\fR. Default value
is \fB{body error}\fR.
Levels are defined as:
.RS
@@ -776,108 +794,121 @@ Print output whenever a test starts
.IP "error (e)"
Print errorInfo and errorCode, if they exist, when a test return code
does not match its expected return code
+.IP "line (l)"
+Print source file line information of failed tests
.RE
The single letter abbreviations noted above are also recognized
-so that [\fBconfigure -verbose pt\fR] is the same as
-[\fBconfigure -verbose {pass start}\fR].
+so that
+.QW "\fBconfigure \-verbose pt\fR"
+is the same as
+.QW "\fBconfigure \-verbose {pass start}\fR" .
.TP
-\fB-preservecore \fIlevel\fR
+\fB\-preservecore \fIlevel\fR
Sets the core preservation level to \fIlevel\fR. This level
determines how stringent checks for core files are. Default
value is 0. Levels are defined as:
.RS
.IP 0
-No checking - do not check for core files at the end of each test
-command, but do check for them in [\fBrunAllTests\fR] after all
+No checking \(em do not check for core files at the end of each test
+command, but do check for them in \fBrunAllTests\fR after all
test files have been evaluated.
.IP 1
-Also check for core files at the end of each [\fBtest\fR] command.
+Also check for core files at the end of each \fBtest\fR command.
.IP 2
Check for core files at all times described above, and save a
-copy of each core file produced in [\fBconfigure -tmpdir\fR].
+copy of each core file produced in \fBconfigure \-tmpdir\fR.
.RE
.TP
-\fB-limitconstraints \fIboolean\fR
-Sets the mode by which [\fBtest\fR] honors constraints as described
+\fB\-limitconstraints \fIboolean\fR
+Sets the mode by which \fBtest\fR honors constraints as described
in \fBTESTS\fR above. Default value is false.
.TP
-\fB-constraints \fIlist\fR
+\fB\-constraints \fIlist\fR
Sets all the constraints in \fIlist\fR to true. Also used in
-combination with [\fBconfigure -limitconstraints true\fR] to control an
+combination with \fBconfigure \-limitconstraints true\fR to control an
alternative constraint mode as described in \fBTESTS\fR above.
Default value is an empty list.
.TP
-\fB-tmpdir \fIdirectory\fR
-Sets the temporary directory to be used by [\fBmakeFile\fR],
-[\fBmakeDirectory\fR], [\fBviewFile\fR], [\fBremoveFile\fR],
-and [\fBremoveDirectory\fR] as the default directory where
+\fB\-tmpdir \fIdirectory\fR
+Sets the temporary directory to be used by \fBmakeFile\fR,
+\fBmakeDirectory\fR, \fBviewFile\fR, \fBremoveFile\fR,
+and \fBremoveDirectory\fR as the default directory where
temporary files and directories created by test files should
-be created. Default value is [\fBworkingDirectory\fR].
+be created. Default value is \fBworkingDirectory\fR.
.TP
-\fB-testdir \fIdirectory\fR
-Sets the directory searched by [\fBrunAllTests\fR] for test files
-and subdirectories. Default value is [\fBworkingDirectory\fR].
+\fB\-testdir \fIdirectory\fR
+Sets the directory searched by \fBrunAllTests\fR for test files
+and subdirectories. Default value is \fBworkingDirectory\fR.
.TP
-\fB-file \fIpatternList\fR
-Sets the list of patterns used by [\fBrunAllTests\fR] to determine
-what test files to evaluate. Default value is \fB*.test\fR.
+\fB\-file \fIpatternList\fR
+Sets the list of patterns used by \fBrunAllTests\fR to determine
+what test files to evaluate. Default value is
+.QW \fB*.test\fR .
.TP
-\fB-notfile \fIpatternList\fR
-Sets the list of patterns used by [\fBrunAllTests\fR] to determine
-what test files to skip. Default value is \fBl.*.test\fR, so
-that any SCCS lock files are skipped.
+\fB\-notfile \fIpatternList\fR
+Sets the list of patterns used by \fBrunAllTests\fR to determine
+what test files to skip. Default value is
+.QW \fBl.*.test\fR ,
+so that any SCCS lock files are skipped.
.TP
-\fB-relateddir \fIpatternList\fR
-Sets the list of patterns used by [\fBrunAllTests\fR] to determine
+\fB\-relateddir \fIpatternList\fR
+Sets the list of patterns used by \fBrunAllTests\fR to determine
what subdirectories to search for an \fBall.tcl\fR file. Default
-value is \fB*\fR.
+value is
+.QW \fB*\fR .
.TP
-\fB-asidefromdir \fIpatternList\fR
-Sets the list of patterns used by [\fBrunAllTests\fR] to determine
+\fB\-asidefromdir \fIpatternList\fR
+Sets the list of patterns used by \fBrunAllTests\fR to determine
what subdirectories to skip when searching for an \fBall.tcl\fR file.
Default value is an empty list.
.TP
-\fB-match \fIpatternList\fR
-Set the list of patterns used by [\fBtest\fR] to determine whether
-a test should be run. Default value is \fB*\fR.
+\fB\-match \fIpatternList\fR
+Set the list of patterns used by \fBtest\fR to determine whether
+a test should be run. Default value is
+.QW \fB*\fR .
.TP
-\fB-skip \fIpatternList\fR
-Set the list of patterns used by [\fBtest\fR] to determine whether
+\fB\-skip \fIpatternList\fR
+Set the list of patterns used by \fBtest\fR to determine whether
a test should be skipped. Default value is an empty list.
.TP
-\fB-load \fIscript\fR
-Sets a script to be evaluated by [\fBloadTestedCommands\fR].
+\fB\-load \fIscript\fR
+Sets a script to be evaluated by \fBloadTestedCommands\fR.
Default value is an empty script.
.TP
-\fB-loadfile \fIfilename\fR
+\fB\-loadfile \fIfilename\fR
Sets the filename from which to read a script to be evaluated
-by [\fBloadTestedCommands\fR]. This is an alternative to
-\fB-load\fR. They cannot be used together.
+by \fBloadTestedCommands\fR. This is an alternative to
+\fB\-load\fR. They cannot be used together.
.TP
-\fB-outfile \fIfilename\fR
+\fB\-outfile \fIfilename\fR
Sets the file to which all output produced by tcltest should be
-written. A file named \fIfilename\fR will be [\fBopen\fR]ed for writing,
-and the resulting channel will be set as the value of [\fBoutputChannel\fR].
+written. A file named \fIfilename\fR will be \fBopen\fRed for writing,
+and the resulting channel will be set as the value of \fBoutputChannel\fR.
.TP
-\fB-errfile \fIfilename\fR
+\fB\-errfile \fIfilename\fR
Sets the file to which all error output produced by tcltest
-should be written. A file named \fIfilename\fR will be [\fBopen\fR]ed
+should be written. A file named \fIfilename\fR will be \fBopen\fRed
for writing, and the resulting channel will be set as the value
-of [\fBerrorChannel\fR].
+of \fBerrorChannel\fR.
.SH "CREATING TEST SUITES WITH TCLTEST"
.PP
-The fundamental element of a test suite is the individual [\fBtest\fR]
+The fundamental element of a test suite is the individual \fBtest\fR
command. We begin with several examples.
.IP [1]
Test of a script that returns normally.
+.RS
+.PP
.CS
\fBtest\fR example-1.0 {normal return} {
format %s value
} value
.CE
+.RE
.IP [2]
Test of a script that requires context setup and cleanup. Note the
bracing and indenting style that avoids any need for line continuation.
+.RS
+.PP
.CS
\fBtest\fR example-1.1 {test file existence} -setup {
set file [makeFile {} test]
@@ -887,15 +918,21 @@ bracing and indenting style that avoids any need for line continuation.
removeFile test
} -result 1
.CE
+.RE
.IP [3]
Test of a script that raises an error.
+.RS
+.PP
.CS
\fBtest\fR example-1.2 {error return} -body {
error message
} -returnCodes error -result message
.CE
+.RE
.IP [4]
Test with a constraint.
+.RS
+.PP
.CS
\fBtest\fR example-1.3 {user owns created files} -constraints {
unix
@@ -907,47 +944,57 @@ Test with a constraint.
removeFile test
} -result $::tcl_platform(user)
.CE
+.RE
.PP
-At the next higher layer of organization, several [\fBtest\fR] commands
+At the next higher layer of organization, several \fBtest\fR commands
are gathered together into a single test file. Test files should have
names with the \fB.test\fR extension, because that is the default pattern
-used by [\fBrunAllTests\fR] to find test files. It is a good rule of
+used by \fBrunAllTests\fR to find test files. It is a good rule of
thumb to have one test file for each source code file of your project.
It is good practice to edit the test file and the source code file
together, keeping tests synchronized with code changes.
.PP
-Most of the code in the test file should be the [\fBtest\fR] commands.
+Most of the code in the test file should be the \fBtest\fR commands.
Use constraints to skip tests, rather than conditional evaluation
-of [\fBtest\fR]. That is, do this:
+of \fBtest\fR.
.IP [5]
+Recommended system for writing conditional tests, using constraints to
+guard:
+.RS
+.PP
.CS
\fBtestConstraint\fR X [expr $myRequirement]
\fBtest\fR goodConditionalTest {} X {
# body
} result
.CE
-and do not do this:
+.RE
.IP [6]
+Discouraged system for writing conditional tests, using \fBif\fR to
+guard:
+.RS
+.PP
.CS
if $myRequirement {
test badConditionalTest {} {
- #body
+ #body
} result
}
.CE
+.RE
.PP
-Use the \fB-setup\fR and \fB-cleanup\fR options to establish and release
+Use the \fB\-setup\fR and \fB\-cleanup\fR options to establish and release
all context requirements of the test body. Do not make tests depend on
prior tests in the file. Those prior tests might be skipped. If several
consecutive tests require the same context, the appropriate setup
and cleanup scripts may be stored in variable for passing to each tests
-\fB-setup\fR and \fB-cleanup\fR options. This is a better solution than
-performing setup outside of [\fBtest\fR] commands, because the setup will
+\fB\-setup\fR and \fB\-cleanup\fR options. This is a better solution than
+performing setup outside of \fBtest\fR commands, because the setup will
only be done if necessary, and any errors during setup will be reported,
and not cause the test file to abort.
.PP
A test file should be able to be combined with other test files and not
-interfere with them, even when [\fBconfigure -singleproc 1\fR] causes
+interfere with them, even when \fBconfigure \-singleproc 1\fR causes
all files to be evaluated in a common interpreter. A simple way to
achieve this is to have your tests define all their commands and variables
in a namespace that is deleted when the test file evaluation is complete.
@@ -955,14 +1002,16 @@ A good namespace to use is a child namespace \fBtest\fR of the namespace
of the module you are testing.
.PP
A test file should also be able to be evaluated directly as a script,
-not depending on being called by a master [\fBrunAllTests\fR]. This
+not depending on being called by a master \fBrunAllTests\fR. This
means that each test file should process command line arguments to give
the tester all the configuration control that \fBtcltest\fR provides.
.PP
-After all [\fBtest\fR]s in a test file, the command [\fBcleanupTests\fR]
+After all \fBtest\fRs in a test file, the command \fBcleanupTests\fR
should be called.
.IP [7]
Here is a sketch of a sample test file illustrating those points:
+.RS
+.PP
.CS
package require tcltest 2.2
eval \fB::tcltest::configure\fR $argv
@@ -973,36 +1022,40 @@ namespace eval ::example::test {
variable SETUP {#common setup code}
variable CLEANUP {#common cleanup code}
\fBtest\fR example-1 {} -setup $SETUP -body {
- # First test
+ # First test
} -cleanup $CLEANUP -result {...}
\fBtest\fR example-2 {} -constraints X -setup $SETUP -body {
- # Second test; constrained
+ # Second test; constrained
} -cleanup $CLEANUP -result {...}
\fBtest\fR example-3 {} {
- # Third test; no context required
+ # Third test; no context required
} {...}
\fBcleanupTests\fR
}
namespace delete ::example::test
.CE
+.RE
.PP
The next level of organization is a full test suite, made up of several
test files. One script is used to control the entire suite. The
-basic function of this script is to call [\fBrunAllTests\fR] after
+basic function of this script is to call \fBrunAllTests\fR after
doing any necessary setup. This script is usually named \fBall.tcl\fR
-because that's the default name used by [\fBrunAllTests\fR] when combining
+because that is the default name used by \fBrunAllTests\fR when combining
multiple test suites into one testing run.
.IP [8]
Here is a sketch of a sample test suite master script:
+.RS
+.PP
.CS
package require Tcl 8.4
package require tcltest 2.2
package require example
-\fB::tcltest::configure\fR -testdir \
+\fB::tcltest::configure\fR -testdir \e
[file dirname [file normalize [info script]]]
eval \fB::tcltest::configure\fR $argv
\fB::tcltest::runAllTests\fR
.CE
+.RE
.SH COMPATIBILITY
.PP
A number of commands and variables in the \fB::tcltest\fR namespace
@@ -1012,21 +1065,24 @@ here. They are no longer part of the supported public interface of
to continue to support existing test suites written to the older
interface specifications, many of those deprecated commands and
variables still work as before. For example, in many circumstances,
-[\fBconfigure\fR] will be automatically called shortly after
-[\fBpackage require tcltest 2.1\fR] succeeds with arguments
+\fBconfigure\fR will be automatically called shortly after
+\fBpackage require tcltest 2.1\fR succeeds with arguments
from the variable \fB::argv\fR. This is to support test suites
that depend on the old behavior that \fBtcltest\fR was automatically
configured from command line arguments. New test files should not
depend on this, but should explicitly include
+.PP
.CS
eval \fB::tcltest::configure\fR $::argv
.CE
+.PP
to establish a configuration from command line arguments.
.SH "KNOWN ISSUES"
-There are two known issues related to nested evaluations of [\fBtest\fR].
+There are two known issues related to nested evaluations of \fBtest\fR.
The first issue relates to the stack level in which test scripts are
executed. Tests nested within other tests may be executed at the same
stack level as the outermost test. For example, in the following code:
+.PP
.CS
\fBtest\fR level-1.1 {level 1} {
-body {
@@ -1035,27 +1091,38 @@ stack level as the outermost test. For example, in the following code:
}
}
.CE
+.PP
any script executed in level-2.1 may be executed at the same stack
level as the script defined for level-1.1.
.PP
-In addition, while two [\fBtest\fR]s have been run, results will only
-be reported by [\fBcleanupTests\fR] for tests at the same level as
+In addition, while two \fBtest\fRs have been run, results will only
+be reported by \fBcleanupTests\fR for tests at the same level as
test level-1.1. However, test results for all tests run prior to
level-1.1 will be available when test level-2.1 runs. What this
means is that if you try to access the test results for test level-2.1,
-it will may say that 'm' tests have run, 'n' tests have
-been skipped, 'o' tests have passed and 'p' tests have failed,
-where 'm', 'n', 'o', and 'p' refer to tests that were run at the
-same test level as test level-1.1.
+it will may say that
+.QW m
+tests have run,
+.QW n
+tests have been skipped,
+.QW o
+tests have passed and
+.QW p
+tests have failed, where
+.QW m ,
+.QW n ,
+.QW o ,
+and
+.QW p
+refer to tests that were run at the same test level as test level-1.1.
.PP
Implementation of output and error comparison in the test command
depends on usage of ::puts in your application code. Output is
intercepted by redefining the ::puts command while the defined test
script is being run. Errors thrown by C procedures or printed
directly from C applications will not be caught by the test command.
-Therefore, usage of the \fB-output\fR and \fB-errorOutput\fR
-options to [\fBtest\fR] is useful only for pure Tcl applications
-that use [\fB::puts\fR] to produce output.
-
+Therefore, usage of the \fB\-output\fR and \fB\-errorOutput\fR
+options to \fBtest\fR is useful only for pure Tcl applications
+that use \fB::puts\fR to produce output.
.SH KEYWORDS
test, test harness, test suite
diff --git a/doc/tclvars.n b/doc/tclvars.n
index d097a92..885de34 100644
--- a/doc/tclvars.n
+++ b/doc/tclvars.n
@@ -12,7 +12,6 @@
.SH NAME
tclvars \- Variables used by Tcl
.BE
-
.SH DESCRIPTION
.PP
The following global variables are created and managed automatically
@@ -25,7 +24,7 @@ whose elements are the environment variables for the process.
Reading an element will return the value of the corresponding
environment variable.
Setting an element of the array will modify the corresponding
-environment variable or create a new one if it doesn't already
+environment variable or create a new one if it does not already
exist.
Unsetting an element of \fBenv\fR will remove the corresponding
environment variable.
@@ -35,90 +34,74 @@ If the entire \fBenv\fR array is unset then Tcl will stop
monitoring \fBenv\fR accesses and will not update environment
variables.
.RS
-.VS 8.0
+.PP
Under Windows, the environment variables PATH and COMSPEC in any
capitalization are converted automatically to upper case. For instance, the
-PATH variable could be exported by the operating system as ``path'',
-``Path'', ``PaTh'', etc., causing otherwise simple Tcl code to have to
+PATH variable could be exported by the operating system as
+.QW path ,
+.QW Path ,
+.QW PaTh ,
+etc., causing otherwise simple Tcl code to have to
support many special cases. All other environment variables inherited by
Tcl are left unmodified. Setting an env array variable to blank is the
same as unsetting it as this is the behavior of the underlying Windows OS.
It should be noted that relying on an existing and empty environment variable
-won't work on windows and is discouraged for cross-platform usage.
-.VE
-.RE
-.RS
-On the Macintosh, the environment variable is constructed by Tcl as no
-global environment variable exists. The environment variables that
-are created for Tcl include:
-.TP
-\fBLOGIN\fR
-This holds the Chooser name of the Macintosh.
-.TP
-\fBUSER\fR
-This also holds the Chooser name of the Macintosh.
-.TP
-\fBSYS_FOLDER\fR
-The path to the system directory.
-.TP
-\fBAPPLE_M_FOLDER\fR
-The path to the Apple Menu directory.
-.TP
-\fBCP_FOLDER\fR
-The path to the control panels directory.
-.TP
-\fBDESK_FOLDER\fR
-The path to the desk top directory.
-.TP
-\fBEXT_FOLDER\fR
-The path to the system extensions directory.
-.TP
-\fBPREF_FOLDER\fR
-The path to the preferences directory.
-.TP
-\fBPRINT_MON_FOLDER\fR
-The path to the print monitor directory.
-.TP
-\fBSHARED_TRASH_FOLDER\fR
-The path to the network trash directory.
-.TP
-\fBTRASH_FOLDER\fR
-The path to the trash directory.
-.TP
-\fBSTART_UP_FOLDER\fR
-The path to the start up directory.
-.TP
-\fBHOME\fR
-The path to the application's default directory.
+will not work on Windows and is discouraged for cross-platform usage.
.PP
-You can also create your own environment variables for the Macintosh.
-A file named \fITcl Environment Variables\fR may be placed in the
-preferences folder in the Mac system folder. Each line of this file
-should be of the form \fIVAR_NAME=var_data\fR.
+The following elements of \fBenv\fR are special to Tcl:
+.TP
+\fBenv(HOME)\fR
+.
+This environment variable, if set, gives the location of the directory
+considered to be the current user's home directory, and to which a
+call of \fBcd\fR without arguments or with just
+.QW ~
+as an argument will change into. Most platforms set this correctly by
+default; it does not normally need to be set by user code.
+.TP
+\fBenv(TCL_LIBRARY)\fR
+.
+If set, then it specifies the location of the directory containing
+library scripts (the value of this variable will be
+assigned to the \fBtcl_library\fR variable and therefore returned by
+the command \fBinfo library\fR). If this variable is not set then
+a default value is used.
+.RS
.PP
-The last alternative is to place environment variables in a 'STR#'
-resource named \fITcl Environment Variables\fR of the application. This
-is considered a little more ``Mac like'' than a Unix style Environment
-Variable file. Each entry in the 'STR#' resource has the same format
-as above. The source code file \fItclMacEnv.c\fR contains the
-implementation of the env mechanisms. This file contains many
-#define's that allow customization of the env mechanisms to fit your
-applications needs.
+Note that this environment variable should \fInot\fR normally be set.
+.RE
+.TP
+\fBenv(TCLLIBPATH)\fR
+.
+If set, then it must contain a valid Tcl list giving directories to
+search during auto-load operations. Directories must be specified in
+Tcl format, using
+.QW /
+as the path separator, regardless of platform.
+This variable is only used when initializing the \fBauto_path\fR variable.
+.TP
+\fBenv(TCL_INTERP_DEBUG_FRAME)\fR
+.
+If existing, it has the same effect as running \fBinterp debug {} -frame 1\fR
+as the very first command of each new Tcl interpreter.
.RE
.TP
\fBerrorCode\fR
-After an error has occurred, this variable will be set to hold
-a list value representing additional information about the error
+This variable holds the value of the \fB\-errorcode\fR return option
+set by the most recent error that occurred in this interpreter.
+This list value represents additional information about the error
in a form that is easy to process with programs.
The first element of the list identifies a general class of
errors, and determines the format of the rest of the list.
-The following formats for \fBerrorCode\fR are used by the
-Tcl core; individual applications may define additional formats.
+The following formats for \fB\-errorcode\fR return options
+are used by the Tcl core; individual applications may define
+additional formats.
.RS
.TP
\fBARITH\fI code msg\fR
+.
This format is used when an arithmetic error occurs (e.g. an attempt
-to divide by zero in the \fBexpr\fR command).
+to divide zero by zero in the \fBexpr\fR command).
\fICode\fR identifies the precise error and \fImsg\fR provides a
human-readable description of the error. \fICode\fR will be either
DIVZERO (for an attempt to divide by zero),
@@ -126,62 +109,77 @@ DOMAIN (if an argument is outside the domain of a function, such as acos(\-3)),
IOVERFLOW (for integer overflow),
OVERFLOW (for a floating-point overflow),
or UNKNOWN (if the cause of the error cannot be determined).
+.RS
+.PP
+Detection of these errors depends in part on the underlying hardware
+and system libraries.
+.RE
.TP
\fBCHILDKILLED\fI pid sigName msg\fR
This format is used when a child process has been killed because of
-a signal. The second element of \fBerrorCode\fR will be the
-process's identifier (in decimal).
-The third element will be the symbolic name of the signal that caused
+a signal. The \fIpid\fR element will be the process's identifier (in decimal).
+The \fIsigName\fR element will be the symbolic name of the signal that caused
the process to terminate; it will be one of the names from the
include file signal.h, such as \fBSIGPIPE\fR.
-The fourth element will be a short human-readable message
-describing the signal, such as ``write on pipe with no readers''
+The \fImsg\fR element will be a short human-readable message
+describing the signal, such as
+.QW "write on pipe with no readers"
for \fBSIGPIPE\fR.
.TP
\fBCHILDSTATUS\fI pid code\fR
This format is used when a child process has exited with a non-zero
-exit status. The second element of \fBerrorCode\fR will be the
-process's identifier (in decimal) and the third element will be the exit
+exit status. The \fIpid\fR element will be the
+process's identifier (in decimal) and the \fIcode\fR element will be the exit
code returned by the process (also in decimal).
.TP
\fBCHILDSUSP\fI pid sigName msg\fR
This format is used when a child process has been suspended because
of a signal.
-The second element of \fBerrorCode\fR will be the process's identifier,
-in decimal.
-The third element will be the symbolic name of the signal that caused
+The \fIpid\fR element will be the process's identifier, in decimal.
+The \fIsigName\fR element will be the symbolic name of the signal that caused
the process to suspend; this will be one of the names from the
include file signal.h, such as \fBSIGTTIN\fR.
-The fourth element will be a short human-readable message
-describing the signal, such as ``background tty read''
+The \fImsg\fR element will be a short human-readable message
+describing the signal, such as
+.QW "background tty read"
for \fBSIGTTIN\fR.
.TP
\fBNONE\fR
This format is used for errors where no additional information is
available for an error besides the message returned with the
-error. In these cases \fBerrorCode\fR will consist of a list
-containing a single element whose contents are \fBNONE\fR.
+error. In these cases the \fB\-errorcode\fR return option
+will consist of a list containing a single element whose
+contents are \fBNONE\fR.
.TP
\fBPOSIX \fIerrName msg\fR
-If the first element of \fBerrorCode\fR is \fBPOSIX\fR, then
+If the first element is \fBPOSIX\fR, then
the error occurred during a POSIX kernel call.
-The second element of the list will contain the symbolic name
+The \fIerrName\fR element will contain the symbolic name
of the error that occurred, such as \fBENOENT\fR; this will
be one of the values defined in the include file errno.h.
-The third element of the list will be a human-readable
+The \fImsg\fR element will be a human-readable
message corresponding to \fIerrName\fR, such as
-``no such file or directory'' for the \fBENOENT\fR case.
+.QW "no such file or directory"
+for the \fBENOENT\fR case.
.PP
-To set \fBerrorCode\fR, applications should use library
-procedures such as \fBTcl_SetErrorCode\fR and \fBTcl_PosixError\fR,
-or they may invoke the \fBerror\fR command.
-If one of these methods hasn't been used, then the Tcl
-interpreter will reset the variable to \fBNONE\fR after
+To set the \fB\-errorcode\fR return option, applications should use library
+procedures such as \fBTcl_SetObjErrorCode\fR, \fBTcl_SetReturnOptions\fR,
+and \fBTcl_PosixError\fR, or they may invoke the \fB\-errorcode\fR
+option of the \fBreturn\fR command.
+If none of these methods for setting the error code has been used,
+the Tcl interpreter will reset the variable to \fBNONE\fR after
the next error.
.RE
+.\" .TP
+.\" \fBTCL\fR ...
+.\" .
+.\" Indicates some sort of problem generated in relation to Tcl itself,
+.\" e.g. a failure to look up a channel or variable.
.TP
\fBerrorInfo\fR
-After an error has occurred, this string will contain one or more lines
+This variable holds the value of the \fB\-errorinfo\fR return option
+set by the most recent error that occurred in this interpreter.
+This string value will contain one or more lines
identifying the Tcl commands and procedures that were being executed
when the most recent error occurred.
Its contents take the form of a stack trace showing the various
@@ -203,19 +201,19 @@ is created by searching several different directories until one is
found that contains an appropriate Tcl startup script.
If the \fBTCL_LIBRARY\fR environment variable exists, then
the directory it names is checked first.
-If \fBTCL_LIBRARY\fR isn't set or doesn't refer to an appropriate
+If \fBTCL_LIBRARY\fR is not set or doesn't refer to an appropriate
directory, then Tcl checks several other directories based on a
compiled-in default location, the location of the binary containing
the application, and the current working directory.
.TP
\fBtcl_patchLevel\fR
+.
When an interpreter is created Tcl initializes this variable to
hold a string giving the current patch level for Tcl, such as
-\fB7.3p2\fR for Tcl 7.3 with the first two official patches, or
-\fB7.4b4\fR for the fourth beta release of Tcl 7.4.
+\fB8.4.16\fR for Tcl 8.4 with the first sixteen official patches, or
+\fB8.5b3\fR for the third beta release of Tcl 8.5.
The value of this variable is returned by the \fBinfo patchlevel\fR
command.
-.VS 8.0 br
.TP
\fBtcl_pkgPath\fR
This variable holds a list of directories indicating where packages are
@@ -228,29 +226,26 @@ subdirectory of one of the entries in \fB$tcl_pkgPath\fR. The directories
in \fB$tcl_pkgPath\fR are included by default in the \fBauto_path\fR
variable, so they and their immediate subdirectories are automatically
searched for packages during \fBpackage require\fR commands. Note:
-\fBtcl_pkgPath\fR it not intended to be modified by the application. Its
+\fBtcl_pkgPath\fR is not intended to be modified by the application. Its
value is added to \fBauto_path\fR at startup; changes to \fBtcl_pkgPath\fR
are not reflected in \fBauto_path\fR. If you want Tcl to search additional
directories for packages you should add the names of those directories to
\fBauto_path\fR, not \fBtcl_pkgPath\fR.
-.VE
.TP
\fBtcl_platform\fR
This is an associative array whose elements contain information about
the platform on which the application is running, such as the name of
the operating system, its current release number, and the machine's
instruction set. The elements listed below will always
-be defined, but they may have empty strings as values if Tcl couldn't
+be defined, but they may have empty strings as values if Tcl could not
retrieve any relevant information. In addition, extensions
and applications may add additional values to the array. The
predefined elements are:
.RS
-.VS
.TP
\fBbyteOrder\fR
The native byte order of this machine: either \fBlittleEndian\fR or
\fBbigEndian\fR.
-.VE
.TP
\fBdebug\fR
If this variable exists, then the interpreter was compiled with and linked
@@ -266,7 +261,7 @@ is the value returned by \fBuname -m\fR.
.TP
\fBos\fR
The name of the operating system running on this machine,
-such as \fBWindows 95\fR, \fBWindows NT\fR, \fBMacOS\fR, or \fBSunOS\fR.
+such as \fBWindows 95\fR, \fBWindows NT\fR, or \fBSunOS\fR.
On UNIX machines, this is the value returned by \fBuname -s\fR.
On Windows 95 and Windows 98, the value returned will be \fBWindows
95\fR to provide better backwards compatibility to Windows 95; to
@@ -279,7 +274,7 @@ Windows 95, the version will be 4.0; on Windows 98, the version will
be 4.10.
.TP
\fBplatform\fR
-Either \fBwindows\fR, \fBmacintosh\fR, or \fBunix\fR. This identifies the
+Either \fBwindows\fR, or \fBunix\fR. This identifies the
general operating environment of the machine.
.TP
\fBthreaded\fR
@@ -290,33 +285,71 @@ was compiled with threads enabled.
This identifies the
current user based on the login information available on the platform.
This comes from the USER or LOGNAME environment variable on Unix,
-and the value from GetUserName on Windows and Macintosh.
+and the value from GetUserName on Windows.
.TP
\fBwordSize\fR
-.VS 8.4
This gives the size of the native-machine word in bytes (strictly, it
is same as the result of evaluating \fIsizeof(long)\fR in C.)
-.VE 8.4
+.TP
+\fBpointerSize\fR
+This gives the size of the native-machine pointer in bytes (strictly, it
+is same as the result of evaluating \fIsizeof(void*)\fR in C.)
.RE
.TP
\fBtcl_precision\fR
-.VS
+.
This variable controls the number of digits to generate
when converting floating-point values to strings. It defaults
-to 12.
-17 digits is ``perfect'' for IEEE floating-point in that it allows
+to 0. \fIApplications should not change this value;\fR it is
+provided for compatibility with legacy code.
+.PP
+.RS
+The default value of 0 is special, meaning that Tcl should
+convert numbers using as few digits as possible while still
+distinguishing any floating point number from its nearest
+neighbours. It differs from using an arbitrarily high value
+for \fItcl_precision\fR in that an inexact number like \fI1.4\fR
+will convert as \fI1.4\fR rather than \fI1.3999999999999999\fR
+even though the latter is nearer to the exact value of the
+binary number.
+.RE
+.PP
+.RS
+If \fBtcl_precision\fR is not zero, then when Tcl converts a floating
+point number, it creates a decimal representation of at most
+\fBtcl_precision\fR significant digits; the result may be shorter if
+the shorter result represents the original number exactly. If no
+result of at most \fBtcl_precision\fR digits is an exact representation
+of the original number, the one that is closest to the original
+number is chosen.
+If the original number lies precisely between two equally accurate
+decimal representations, then the one with an even value for the least
+significant digit is chosen; for instance, if \fBtcl_precision\fR is 3, then
+0.3125 will convert to 0.312, not 0.313, while 0.6875 will convert to
+0.688, not 0.687. Any string of trailing zeroes that remains is trimmed.
+.RE
+.PP
+.RS
+a \fBtcl_precision\fR value of 17 digits is
+.QW perfect
+for IEEE floating-point in that it allows
double-precision values to be converted to strings and back to
-binary with no loss of information. However, using 17 digits prevents
-any rounding, which produces longer, less intuitive results. For example,
-\fBexpr 1.4\fR returns 1.3999999999999999 with \fBtcl_precision\fR
-set to 17, vs. 1.4 if \fBtcl_precision\fR is 12.
+binary with no loss of information. For this reason, you will often
+see it as a value in legacy code that must run on Tcl versions before
+8.5. It is no longer recommended; as noted above, a zero value is the
+preferred method.
+.RE
+.PP
.RS
-All interpreters in a process share a single \fBtcl_precision\fR value:
+All interpreters in a thread share a single \fBtcl_precision\fR value:
changing it in one interpreter will affect all other interpreters as
-well. However, safe interpreters are not allowed to modify the
+well. Safe interpreters are not allowed to modify the
variable.
.RE
-.VE
+.PP
+.RS
+Valid values for \fBtcl_precision\fR range from 0 to 17.
+.RE
.TP
\fBtcl_rcFileName\fR
This variable is used during initialization to indicate the name of a
@@ -326,15 +359,6 @@ of this file and \fBsource\fR it if it exists. For example, for \fBwish\fR
the variable is set to \fB~/.wishrc\fR for Unix and \fB~/wishrc.tcl\fR
for Windows.
.TP
-\fBtcl_rcRsrcName\fR
-This variable is only used on Macintosh systems. The variable is used
-during initialization to indicate the name of a user-specific
-\fBTEXT\fR resource located in the application or extension resource
-forks. If it is set by application-specific initialization, then the
-Tcl startup code will check for the existence of this resource and
-\fBsource\fR it if it exists. For example, the Macintosh \fBwish\fR
-application has the variable is set to \fBtclshrc\fR.
-.TP
\fBtcl_traceCompile\fR
The value of this variable can be set to control
how much tracing information
@@ -346,11 +370,11 @@ Setting it to 2 generates a detailed listing in stdout of the
bytecode instructions emitted during every compilation.
This variable is useful in
tracking down suspected problems with the Tcl compiler.
-It is also occasionally useful when converting
-existing code to use Tcl8.0.
.PP
+.RS
This variable and functionality only exist if
\fBTCL_COMPILE_DEBUG\fR was defined during Tcl's compilation.
+.RE
.TP
\fBtcl_traceExec\fR
The value of this variable can be set to control
@@ -371,26 +395,30 @@ of bytecode instructions are not shown.
Setting this variable is useful in
tracking down suspected problems with the bytecode compiler
and interpreter.
-It is also occasionally useful when converting
-code to use Tcl8.0.
.PP
+.RS
This variable and functionality only exist if
\fBTCL_COMPILE_DEBUG\fR was defined during Tcl's compilation.
+.RE
.TP
\fBtcl_wordchars\fR
The value of this variable is a regular expression that can be set to
-control what are considered ``word'' characters, for instances like
+control what are considered
+.QW word
+characters, for instances like
selecting a word by double-clicking in text in Tk. It is platform
-dependent. On Windows, it defaults to \fB\\S\fR, meaning anything
-but a Unicode space character. Otherwise it defaults to \fB\\w\fR,
+dependent. On Windows, it defaults to \fB\eS\fR, meaning anything
+but a Unicode space character. Otherwise it defaults to \fB\ew\fR,
which is any Unicode word character (number, letter, or underscore).
.TP
\fBtcl_nonwordchars\fR
The value of this variable is a regular expression that can be set to
-control what are considered ``non-word'' characters, for instances like
+control what are considered
+.QW non-word
+characters, for instances like
selecting a word by double-clicking in text in Tk. It is platform
-dependent. On Windows, it defaults to \fB\\s\fR, meaning any Unicode space
-character. Otherwise it defaults to \fB\\W\fR, which is anything but a
+dependent. On Windows, it defaults to \fB\es\fR, meaning any Unicode space
+character. Otherwise it defaults to \fB\eW\fR, which is anything but a
Unicode word character (number, letter, or underscore).
.TP
\fBtcl_version\fR
@@ -422,15 +450,13 @@ Contains 1 if \fBtclsh\fR or \fBwish\fR is running interactively (no
script was specified and standard input is a terminal-like device), 0
otherwise.
.PP
-The \fBwish\fR executably additionally specifies the following global
+The \fBwish\fR executable additionally specifies the following global
variable:
.TP 6
\fBgeometry\fR
If set, contains the user-supplied geometry specification to use for
the main Tk window.
-
.SH "SEE ALSO"
eval(n), tclsh(1), wish(1)
-
.SH KEYWORDS
arithmetic, bytecode, compiler, error, environment, POSIX, precision, subprocess, variables
diff --git a/doc/tell.n b/doc/tell.n
index 559f709..282cae5 100644
--- a/doc/tell.n
+++ b/doc/tell.n
@@ -17,21 +17,17 @@ tell \- Return current access position for an open channel
.SH DESCRIPTION
.PP
-.VS 8.1
Returns an integer string giving the current access position in
\fIchannelId\fR. This value returned is a byte offset that can be passed to
\fBseek\fR in order to set the channel to a particular position. Note
that this value is in terms of bytes, not characters like \fBread\fR.
-.VE 8.1
The value returned is -1 for channels that do not support
seeking.
.PP
-.VS
\fIChannelId\fR must be an identifier for an open channel such as a
Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR),
the return value from an invocation of \fBopen\fR or \fBsocket\fR, or
the result of a channel creation command provided by a Tcl extension.
-.VE
.SH EXAMPLE
Read a line from a file channel only if it starts with \fBfoobar\fR:
.CS
diff --git a/doc/time.n b/doc/time.n
index 38ae49a..bdd0786 100644
--- a/doc/time.n
+++ b/doc/time.n
@@ -18,7 +18,7 @@ time \- Time the execution of a script
.SH DESCRIPTION
.PP
This command will call the Tcl interpreter \fIcount\fR
-times to evaluate \fIscript\fR (or once if \fIcount\fR isn't
+times to evaluate \fIscript\fR (or once if \fIcount\fR is not
specified). It will then return a string of the form
.CS
\fB503 microseconds per iteration\fR
diff --git a/doc/tm.n b/doc/tm.n
new file mode 100644
index 0000000..aef06dd
--- /dev/null
+++ b/doc/tm.n
@@ -0,0 +1,293 @@
+'\"
+'\" Copyright (c) 2004-2010 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.so man.macros
+.TH tm n 8.5 Tcl "Tcl Built-In Commands"
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+tm \- Facilities for locating and loading of Tcl Modules
+.SH SYNOPSIS
+.nf
+\fB::tcl::tm::path add \fR?\fIpath\fR...?
+\fB::tcl::tm::path remove \fR?\fIpath\fR...?
+\fB::tcl::tm::path list\fR
+\fB::tcl::tm::roots \fR?\fIpath\fR...?
+.fi
+.BE
+.SH DESCRIPTION
+This document describes the facilities for locating and loading Tcl
+Modules (see \fBMODULE DEFINITION\fR for the definition of a Tcl Module).
+The following commands are supported:
+.TP
+\fB::tcl::tm::path add \fR?\fIpath\fR...?
+.
+The paths are added at the head to the list of module paths, in order
+of appearance. This means that the last argument ends up as the new
+head of the list.
+.RS
+.PP
+The command enforces the restriction that no path may be an ancestor
+directory of any other path on the list. If any of the new paths
+violates this restriction an error will be raised, before any of the
+paths have been added. In other words, if only one path argument
+violates the restriction then none will be added.
+.PP
+If a path is already present as is, no error will be raised and no
+action will be taken.
+.PP
+Paths are searched later in the order of their appearance in the
+list. As they are added to the front of the list they are searched in
+reverse order of addition. In other words, the paths added last are
+looked at first.
+.RE
+.TP
+\fB::tcl::tm::path remove \fR?\fIpath\fR...?
+.
+Removes the paths from the list of module paths. The command silently
+ignores all paths which are not on the list.
+.TP
+\fB::tcl::tm::path list\fR
+.
+Returns a list containing all registered module paths, in the order
+that they are searched for modules.
+.TP
+\fB::tcl::tm::roots \fR?\fIpath\fR...?
+.
+Similar to \fBpath add\fR, and layered on top of it. This command
+takes a list of paths, extends each with
+.QW "\fBtcl\fIX\fB/site-tcl\fR" ,
+and
+.QW "\fBtcl\fIX\fB/\fIX\fB.\fIy\fR" ,
+for major version \fIX\fR of the
+Tcl interpreter and minor version \fIy\fR less than or equal to the
+minor version of the interpreter, and adds the resulting set of paths
+to the list of paths to search.
+.RS
+.PP
+This command is used internally by the system to set up the
+system-specific default paths.
+.PP
+The command has been exposed to allow a build system to define
+additional root paths beyond those described by this document.
+.RE
+.SH "MODULE DEFINITION"
+A Tcl Module is a Tcl Package contained in a single file, and no other
+files required by it. This file has to be \fBsource\fRable. In other
+words, a Tcl Module is always imported via:
+.CS
+source module_file
+.CE
+.PP
+The \fBload\fR command is not directly used. This restriction is not
+an actual limitation, as some may believe.
+Ever since 8.4 the Tcl \fBsource\fR command reads only until the first
+^Z character. This allows us to combine an arbitrary Tcl script with
+arbitrary binary data into one file, where the script processes the
+attached data in any it chooses to fully import and activate the
+package.
+.PP
+The name of a module file has to match the regular expression:
+.CS
+([_[:alpha:]][:_[:alnum:]]*)-([[:digit:]].*)\e.tm
+.CE
+.PP
+The first capturing parentheses provides the name of the package, the
+second clause its version. In addition to matching the pattern, the
+extracted version number must not raise an error when used in the
+command:
+.CS
+package vcompare $version 0
+.CE
+.PP
+.SH "FINDING MODULES"
+The directory tree for storing Tcl modules is separate from other
+parts of the filesystem and independent of \fBauto_path\fR.
+.PP
+Tcl Modules are searched for in all directories listed in the result
+of the command \fB::tcl::tm::path list\fR.
+This is called the \fIModule path\fR. Neither the \fBauto_path\fR nor
+the \fBtcl_pkgPath\fR variables are used.
+All directories on the module path have to obey one restriction:
+.RS
+.PP
+For any two directories, neither is an ancestor directory of the
+other.
+.RE
+.PP
+This is required to avoid ambiguities in package naming. If for
+example the two directories
+.QW "\fIfoo/\fR"
+and
+.QW "\fIfoo/cool\fR"
+were on
+the path a package named \fBcool::ice\fR could be found via the
+names \fBcool::ice\fR or \fBice\fR, the latter potentially
+obscuring a package named \fBice\fR, unqualified.
+.PP
+Before the search is started, the name of the requested package is
+translated into a partial path, using the following algorithm:
+.RS
+.PP
+All occurrences of
+.QW "\fB::\fR"
+in the package name are replaced by
+the appropriate directory separator character for the platform we are
+on. On Unix, for example, this is
+.QW "\fB/\fR" .
+.RE
+.PP
+Example:
+.RS
+.PP
+The requested package is \fBencoding::base64\fR. The generated
+partial path is
+.QW "\fIencoding/base64\fR" .
+.RE
+.PP
+After this translation the package is looked for in all module paths,
+by combining them one-by-one, first to last with the partial path to
+form a complete search pattern. Note that the search algorithm rejects
+all files where the filename does not match the regular expression
+given in the section \fBMODULE DEFINITION\fR. For the remaining
+files \fIprovide scripts\fR are generated and added to the package
+ifneeded database.
+.PP
+The algorithm falls back to the previous unknown handler when none of
+the found module files satisfy the request. If the request was
+satisfied the fall-back is ignored.
+.PP
+Note that packages in module form have \fIno\fR control over the
+\fIindex\fR and \fIprovide script\fRs entered into the package
+database for them.
+For a module file \fBMF\fR the \fIindex script\fR is always:
+.CS
+package ifneeded \fBPNAME PVERSION\fR [list source \fBMF\fR]
+.CE
+and the \fIprovide script\fR embedded in the above is:
+.CS
+source \fBMF\fR
+.CE
+.PP
+Both package name \fBPNAME\fR and package version \fBPVERSION\fR are
+extracted from the filename \fBMF\fR according to the definition
+below:
+.CS
+\fBMF\fR = /module_path/\fBPNAME\(fm\fR-\fBPVERSION\fR.tm
+.CE
+.PP
+Where \fBPNAME\(fm\fR is the partial path of the module as defined in
+section \fBFINDING MODULES\fR, and translated into \fBPNAME\fR by
+changing all directory separators to
+.QW "\fB::\fR" ,
+and \fBmodule_path\fR is the path (from the list of paths to search)
+that we found the module file under.
+.PP
+Note also that we are here creating a connection between package names
+and paths. Tcl is case-sensitive when it comes to comparing package
+names, but there are filesystems which are not, like NTFS. Luckily
+these filesystems do store the case of the name, despite not using the
+information when comparing.
+.PP
+Given the above we allow the names for packages in Tcl modules to have
+mixed-case, but also require that there are no collisions when
+comparing names in a case-insensitive manner. In other words, if a
+package \fBFoo\fR is deployed in the form of a Tcl Module,
+packages like \fBfoo\fR, \fBfOo\fR, etc. are not allowed
+anymore.
+.SH "DEFAULT PATHS"
+The default list of paths on the module path is computed by a
+\fBtclsh\fR as follows, where \fIX\fR is the major version of the Tcl
+interpreter and \fIy\fR is less than or equal to the minor version of
+the Tcl interpreter.
+.PP
+All the default paths are added to the module path, even those paths
+which do not exist. Non-existent paths are filtered out during actual
+searches. This enables a user to create one of the paths searched when
+needed and all running applications will automatically pick up any
+modules placed in them.
+.PP
+The paths are added in the order as they are listed below, and for
+lists of paths defined by an environment variable in the order they
+are found in the variable.
+.SS "SYSTEM SPECIFIC PATHS"
+.TP
+\fBfile normalize [info library]/../tcl\fIX\fB/\fIX\fB.\fIy\fR
+.
+In other words, the interpreter will look into a directory specified
+by its major version and whose minor versions are less than or equal
+to the minor version of the interpreter.
+.RS
+.PP
+For example for Tcl 8.4 the paths searched are:
+.CS
+\fB[info library]/../tcl8/8.4\fR
+\fB[info library]/../tcl8/8.3\fR
+\fB[info library]/../tcl8/8.2\fR
+\fB[info library]/../tcl8/8.1\fR
+\fB[info library]/../tcl8/8.0\fR
+.CE
+.PP
+This definition assumes that a package defined for Tcl \fIX\fB.\fIy\fR
+can also be used by all interpreters which have the same major number
+\fIX\fR and a minor number greater than \fIy\fR.
+.RE
+.TP
+\fBfile normalize EXEC/tcl\fIX\fB/\fIX\fB.\fIy\fR
+.
+Where \fBEXEC\fR is \fBfile normalize [info nameofexecutable]/../lib\fR
+or \fBfile normalize [::tcl::pkgconfig get libdir,runtime]\fR
+.RS
+.PP
+This sets of paths is handled equivalently to the set coming before,
+except that it is anchored in \fBEXEC_PREFIX\fR.
+For a build with \fBPREFIX\fR = \fBEXEC_PREFIX\fR the two sets are
+identical.
+.RE
+.SS "SITE SPECIFIC PATHS"
+.TP
+\fBfile normalize [info library]/../tcl\fIX\fB/site-tcl\fR
+.
+Note that this is always a single entry because \fIX\fR is always a
+specific value (the current major version of Tcl).
+.SS "USER SPECIFIC PATHS"
+.TP
+\fB$::env(TCL\fIX\fB_\fIy\fB_TM_PATH)\fR
+.
+A list of paths, separated by either \fB:\fR (Unix) or \fB;\fR
+(Windows). This is user and site specific as this environment variable
+can be set not only by the user's profile, but by system configuration
+scripts as well.
+.TP
+\fB$::env(TCL\fIX\fB.\fIy\fB_TM_PATH)\fR
+.
+Same meaning and content as the previous variable. However the use of
+dot '.' to separate major and minor version number makes this name
+less to non-portable and its use is discouraged. Support of this
+variable has been kept only for backward compatibility with the
+original specification, i.e. TIP 189.
+.PP
+These paths are seen and therefore shared by all Tcl shells in the
+\fB$::env(PATH)\fR of the user.
+.PP
+Note that \fIX\fR and \fIy\fR follow the general rules set out
+above. In other words, Tcl 8.4, for example, will look at these 5
+environment variables:
+.CS
+\fB$::env(TCL8.4_TM_PATH)\fR \fB$::env(TCL8_4_TM_PATH)\fR
+\fB$::env(TCL8.3_TM_PATH)\fR \fB$::env(TCL8_3_TM_PATH)\fR
+\fB$::env(TCL8.2_TM_PATH)\fR \fB$::env(TCL8_2_TM_PATH)\fR
+\fB$::env(TCL8.1_TM_PATH)\fR \fB$::env(TCL8_1_TM_PATH)\fR
+\fB$::env(TCL8.0_TM_PATH)\fR \fB$::env(TCL8_0_TM_PATH)\fR
+.CE
+.SH "SEE ALSO"
+package(n), Tcl Improvement Proposal #189
+.QW "\fITcl Modules\fR"
+(online at http://tip.tcl.tk/189.html), Tcl Improvement Proposal #190
+.QW "\fIImplementation Choices for Tcl Modules\fR"
+(online at http://tip.tcl.tk/190.html)
+.SH "KEYWORDS"
+modules, package
diff --git a/doc/trace.n b/doc/trace.n
index 552b269..9d40123 100644
--- a/doc/trace.n
+++ b/doc/trace.n
@@ -15,52 +15,57 @@ trace \- Monitor variable accesses, command usages and command executions
.SH SYNOPSIS
\fBtrace \fIoption\fR ?\fIarg arg ...\fR?
.BE
-
.SH DESCRIPTION
.PP
This command causes Tcl commands to be executed whenever certain operations are
-invoked. The legal \fIoption\fR's (which may be abbreviated) are:
+invoked. The legal \fIoption\fRs (which may be abbreviated) are:
.TP
\fBtrace add \fItype name ops ?args?\fR
Where \fItype\fR is \fBcommand\fR, \fBexecution\fR, or \fBvariable\fR.
.RS
.TP
-\fBtrace add command\fR \fIname ops command\fR
-Arrange for \fIcommand\fR to be executed whenever command \fIname\fR
-is modified in one of the ways given by the list \fIops\fR. \fIName\fR will be
-resolved using the usual namespace resolution rules used by
-procedures. If the command does not exist, an error will be thrown.
+\fBtrace add command\fR \fIname ops commandPrefix\fR
+.
+Arrange for \fIcommandPrefix\fR to be executed (with additional arguments)
+whenever command \fIname\fR is modified in one of the ways given by the list
+\fIops\fR. \fIName\fR will be resolved using the usual namespace resolution
+rules used by commands. If the command does not exist, an error will be
+thrown.
.RS
.PP
\fIOps\fR indicates which operations are of interest, and is a list of
one or more of the following items:
.TP
\fBrename\fR
-Invoke \fIcommand\fR whenever the command is renamed. Note that
-renaming to the empty string is considered deletion, and will not
-be traced with '\fBrename\fR'.
+.
+Invoke \fIcommandPrefix\fR whenever the traced command is renamed. Note that
+renaming to the empty string is considered deletion, and will not be traced
+with
+.QW \fBrename\fR .
.TP
\fBdelete\fR
-Invoke \fIcommand\fR when the command is deleted. Commands can be
-deleted explicitly by using the \fBrename\fR command to rename the
-command to an empty string. Commands are also deleted when the
-interpreter is deleted, but traces will not be invoked because there is no
-interpreter in which to execute them.
+.
+Invoke \fIcommandPrefix\fR when the traced command is deleted. Commands can be
+deleted explicitly by using the \fBrename\fR command to rename the command to
+an empty string. Commands are also deleted when the interpreter is deleted,
+but traces will not be invoked because there is no interpreter in which to
+execute them.
.PP
-When the trace triggers, depending on the operations being traced, a
-number of arguments are appended to \fIcommand\fR so that the actual
-command is as follows:
+When the trace triggers, depending on the operations being traced, a number of
+arguments are appended to \fIcommandPrefix\fR so that the actual command is as
+follows:
.CS
-\fIcommand oldName newName op\fR
+\fIcommandPrefix oldName newName op\fR
.CE
-\fIOldName\fR and \fInewName\fR give the traced command's current
-(old) name, and the name to which it is being renamed (the empty
-string if this is a 'delete' operation).
+\fIOldName\fR and \fInewName\fR give the traced command's current (old) name,
+and the name to which it is being renamed (the empty string if this is a
+.QW delete
+operation).
\fIOp\fR indicates what operation is being performed on the
command, and is one of \fBrename\fR or \fBdelete\fR as
defined above. The trace operation cannot be used to stop a command
from being deleted. Tcl will always remove the command once the trace
-is complete. Recursive renaming or deleting will not cause further traces
+is complete. Recursive renaming or deleting will not cause further traces
of the same type to be evaluated, so a delete trace which itself
deletes the command, or a rename trace which itself renames the
command will not cause further trace evaluations to occur.
@@ -68,90 +73,100 @@ Both \fIoldName\fR and \fInewName\fR are fully qualified with any namespace(s)
in which they appear.
.RE
.TP
-\fBtrace add execution\fR \fIname ops command\fR
-Arrange for \fIcommand\fR to be executed whenever command \fIname\fR
-is executed, with traces occurring at the points indicated by the list
-\fIops\fR. \fIName\fR will be
-resolved using the usual namespace resolution rules used by
-procedures. If the command does not exist, an error will be thrown.
+\fBtrace add execution\fR \fIname ops commandPrefix\fR
+.
+Arrange for \fIcommandPrefix\fR to be executed (with additional arguments)
+whenever command \fIname\fR is executed, with traces occurring at the points
+indicated by the list \fIops\fR. \fIName\fR will be resolved using the usual
+namespace resolution rules used by commands. If the command does not exist,
+an error will be thrown.
.RS
.PP
\fIOps\fR indicates which operations are of interest, and is a list of
one or more of the following items:
.TP
\fBenter\fR
-Invoke \fIcommand\fR whenever the command \fIname\fR is executed,
+Invoke \fIcommandPrefix\fR whenever the command \fIname\fR is executed,
just before the actual execution takes place.
.TP
\fBleave\fR
-Invoke \fIcommand\fR whenever the command \fIname\fR is executed,
+Invoke \fIcommandPrefix\fR whenever the command \fIname\fR is executed,
just after the actual execution takes place.
.TP
\fBenterstep\fR
-Invoke \fIcommand\fR for every Tcl command which is executed
-inside the procedure \fIname\fR, just before the actual execution
-takes place. For example if we have 'proc foo {} { puts "hello" }',
-then an \fIenterstep\fR trace would be
-invoked just before \fIputs "hello"\fR is executed.
-Setting an \fIenterstep\fR trace on a \fIcommand\fR
-will not result in an error and is simply ignored.
+.
+Invoke \fIcommandPrefix\fR for every Tcl command which is executed from the
+start of the execution of the procedure \fIname\fR until that
+procedure finishes. \fICommandPrefix\fR is invoked just before the actual
+execution of the Tcl command being reported takes place. For example
+if we have
+.QW "proc foo {} { puts \N'34'hello\N'34' }" ,
+then an \fIenterstep\fR trace would be invoked just before
+.QW "\fIputs \N'34'hello\N'34'\fR"
+is executed.
+Setting an \fIenterstep\fR trace on a command \fIname\fR that does not refer
+to a procedure will not result in an error and is simply ignored.
.TP
\fBleavestep\fR
-Invoke \fIcommand\fR for every Tcl command which is executed
-inside the procedure \fIname\fR, just after the actual execution
-takes place.
-Setting a \fIleavestep\fR trace on a \fIcommand\fR
-will not result in an error and is simply ignored.
+.
+Invoke \fIcommandPrefix\fR for every Tcl command which is executed from the
+start of the execution of the procedure \fIname\fR until that
+procedure finishes. \fICommandPrefix\fR is invoked just after the actual
+execution of the Tcl command being reported takes place.
+Setting a \fIleavestep\fR trace on a command \fIname\fR that does not refer to
+a procedure will not result in an error and is simply ignored.
.PP
-When the trace triggers, depending on the operations being traced, a
-number of arguments are appended to \fIcommand\fR so that the actual
+When the trace triggers, depending on the operations being traced, a
+number of arguments are appended to \fIcommandPrefix\fR so that the actual
command is as follows:
.PP
For \fBenter\fR and \fBenterstep\fR operations:
.CS
-\fIcommand command-string op\fR
+\fIcommandPrefix command-string op\fR
.CE
-\fICommand-string\fR gives the complete current command being
-executed (the traced command for a \fBenter\fR operation, an
+\fICommand-string\fR gives the complete current command being
+executed (the traced command for a \fBenter\fR operation, an
arbitrary command for a \fBenterstep\fR operation), including
all arguments in their fully expanded form.
\fIOp\fR indicates what operation is being performed on the
command execution, and is one of \fBenter\fR or \fBenterstep\fR as
defined above. The trace operation can be used to stop the
command from executing, by deleting the command in question. Of
-course when the command is subsequently executed, an 'invalid command'
+course when the command is subsequently executed, an
+.QW "invalid command"
error will occur.
.PP
For \fBleave\fR and \fBleavestep\fR operations:
.CS
\fIcommand command-string code result op\fR
.CE
-\fICommand-string\fR gives the complete current command being
-executed (the traced command for a \fBenter\fR operation, an
+\fICommand-string\fR gives the complete current command being
+executed (the traced command for a \fBenter\fR operation, an
arbitrary command for a \fBenterstep\fR operation), including
all arguments in their fully expanded form.
\fICode\fR gives the result code of that execution, and \fIresult\fR
the result string.
\fIOp\fR indicates what operation is being performed on the
command execution, and is one of \fBleave\fR or \fBleavestep\fR as
-defined above.
+defined above.
Note that the creation of many \fBenterstep\fR or
\fBleavestep\fR traces can lead to unintuitive results, since the
invoked commands from one trace can themselves lead to further
command invocations for other traces.
.PP
-\fICommand\fR executes in the same context as the code that invoked
-the traced operation: thus the \fIcommand\fR, if invoked from a procedure,
-will have access to the same local variables as code in the procedure.
-This context may be different than the context in which the trace was
-created. If \fIcommand\fR invokes a procedure (which it normally does)
-then the procedure will have to use upvar or uplevel commands if it wishes
-to access the local variables of the code which invoked the trace operation.
+\fICommandPrefix\fR executes in the same context as the code that invoked
+the traced operation: thus the \fIcommandPrefix\fR, if invoked from a
+procedure, will have access to the same local variables as code in the
+procedure. This context may be different than the context in which the trace
+was created. If \fIcommandPrefix\fR invokes a procedure (which it normally
+does) then the procedure will have to use \fBupvar\fR or \fBuplevel\fR
+commands if it wishes to access the local variables of the code which invoked
+the trace operation.
.PP
-While \fIcommand\fR is executing during an execution trace, traces
-on \fIname\fR are temporarily disabled. This allows the \fIcommand\fR
+While \fIcommandPrefix\fR is executing during an execution trace, traces
+on \fIname\fR are temporarily disabled. This allows the \fIcommandPrefix\fR
to execute \fIname\fR in its body without invoking any other traces again.
-If an error occurs while executing the \fIcommand\fR body, then the
+If an error occurs while executing the \fIcommandPrefix\fR, then the
command \fIname\fR as a whole will return that same error.
.PP
When multiple traces are set on \fIname\fR, then for \fIenter\fR
@@ -160,17 +175,17 @@ in the reverse order of how the traces were originally created;
and for \fIleave\fR and \fIleavestep\fR operations, the traced
commands are invoked in the original order of creation.
.PP
-The behavior of execution traces is currently undefined for a command
+The behavior of execution traces is currently undefined for a command
\fIname\fR imported into another namespace.
.RE
.TP
-\fBtrace add variable\fI name ops command\fR
-Arrange for \fIcommand\fR to be executed whenever variable \fIname\fR
+\fBtrace add variable\fI name ops commandPrefix\fR
+Arrange for \fIcommandPrefix\fR to be executed whenever variable \fIname\fR
is accessed in one of the ways given by the list \fIops\fR. \fIName\fR may
refer to a normal variable, an element of an array, or to an array
as a whole (i.e. \fIname\fR may be just the name of an array, with no
parenthesized index). If \fIname\fR refers to a whole array, then
-\fIcommand\fR is invoked whenever any element of the array is
+\fIcommandPrefix\fR is invoked whenever any element of the array is
manipulated. If the variable does not exist, it will be created but
will not be given a value, so it will be visible to \fBnamespace which\fR
queries, but not to \fBinfo exists\fR queries.
@@ -180,20 +195,20 @@ queries, but not to \fBinfo exists\fR queries.
one or more of the following items:
.TP
\fBarray\fR
-Invoke \fIcommand\fR whenever the variable is accessed or modified via
+Invoke \fIcommandPrefix\fR whenever the variable is accessed or modified via
the \fBarray\fR command, provided that \fIname\fR is not a scalar
variable at the time that the \fBarray\fR command is invoked. If
\fIname\fR is a scalar variable, the access via the \fBarray\fR
command will not trigger the trace.
.TP
\fBread\fR
-Invoke \fIcommand\fR whenever the variable is read.
+Invoke \fIcommandPrefix\fR whenever the variable is read.
.TP
\fBwrite\fR
-Invoke \fIcommand\fR whenever the variable is written.
+Invoke \fIcommandPrefix\fR whenever the variable is written.
.TP
\fBunset\fR
-Invoke \fIcommand\fR whenever the variable is unset. Variables
+Invoke \fIcommandPrefix\fR whenever the variable is unset. Variables
can be unset explicitly with the \fBunset\fR command, or
implicitly when procedures return (all of their local variables
are unset). Variables are also unset when interpreters are
@@ -201,9 +216,9 @@ deleted, but traces will not be invoked because there is no
interpreter in which to execute them.
.PP
When the trace triggers, three arguments are appended to
-\fIcommand\fR so that the actual command is as follows:
+\fIcommandPrefix\fR so that the actual command is as follows:
.CS
-\fIcommand name1 name2 op\fR
+\fIcommandPrefix name1 name2 op\fR
.CE
\fIName1\fR and \fIname2\fR give the name(s) for the variable
being accessed: if the variable is a scalar then \fIname1\fR
@@ -221,11 +236,11 @@ different name.
variable, and is one of \fBread\fR, \fBwrite\fR, or \fBunset\fR as
defined above.
.PP
-\fICommand\fR executes in the same context as the code that invoked
+\fICommandPrefix\fR executes in the same context as the code that invoked
the traced operation: if the variable was accessed as part of a Tcl
-procedure, then \fIcommand\fR will have access to the same local
+procedure, then \fIcommandPrefix\fR will have access to the same local
variables as code in the procedure. This context may be different
-than the context in which the trace was created. If \fIcommand\fR
+than the context in which the trace was created. If \fIcommandPrefix\fR
invokes a procedure (which it normally does) then the procedure will
have to use \fBupvar\fR or \fBuplevel\fR if it wishes to access the
traced variable. Note also that \fIname1\fR may not necessarily be
@@ -233,25 +248,25 @@ the same as the name used to set the trace on the variable;
differences can occur if the access is made through a variable defined
with the \fBupvar\fR command.
.PP
-For read and write traces, \fIcommand\fR can modify the variable to
-affect the result of the traced operation. If \fIcommand\fR modifies
+For read and write traces, \fIcommandPrefix\fR can modify the variable to
+affect the result of the traced operation. If \fIcommandPrefix\fR modifies
the value of a variable during a read or write trace, then the new
value will be returned as the result of the traced operation. The
-return value from \fIcommand\fR is ignored except that if it returns
+return value from \fIcommandPrefix\fR is ignored except that if it returns
an error of any sort then the traced operation also returns an error
with the same error message returned by the trace command (this
mechanism can be used to implement read-only variables, for example).
-For write traces, \fIcommand\fR is invoked after the variable's value
+For write traces, \fIcommandPrefix\fR is invoked after the variable's value
has been changed; it can write a new value into the variable to
override the original value specified in the write operation. To
-implement read-only variables, \fIcommand\fR will have to restore the
+implement read-only variables, \fIcommandPrefix\fR will have to restore the
old value of the variable.
.PP
-While \fIcommand\fR is executing during a read or write trace, traces
+While \fIcommandPrefix\fR is executing during a read or write trace, traces
on the variable are temporarily disabled. This means that reads and
-writes invoked by \fIcommand\fR will occur directly, without invoking
-\fIcommand\fR (or any other traces) again. However, if \fIcommand\fR
-unsets the variable then unset traces will be invoked.
+writes invoked by \fIcommandPrefix\fR will occur directly, without invoking
+\fIcommandPrefix\fR (or any other traces) again. However, if
+\fIcommandPrefix\fR unsets the variable then unset traces will be invoked.
.PP
When an unset trace is invoked, the variable has already been deleted:
it will appear to be undefined with no traces. If an unset occurs
@@ -279,28 +294,28 @@ This command returns an empty string.
.RE
.RE
.TP
-\fBtrace remove \fItype name opList command\fR
+\fBtrace remove \fItype name opList commandPrefix\fR
Where \fItype\fR is either \fBcommand\fR, \fBexecution\fR or \fBvariable\fR.
.RS
.TP
-\fBtrace remove command\fI name opList command\fR
+\fBtrace remove command\fI name opList commandPrefix\fR
If there is a trace set on command \fIname\fR with the operations and
-command given by \fIopList\fR and \fIcommand\fR, then the trace is
-removed, so that \fIcommand\fR will never again be invoked. Returns
-an empty string. If \fIname\fR doesn't exist, the command will throw
+command given by \fIopList\fR and \fIcommandPrefix\fR, then the trace is
+removed, so that \fIcommandPrefix\fR will never again be invoked. Returns
+an empty string. If \fIname\fR does not exist, the command will throw
an error.
.TP
-\fBtrace remove execution\fI name opList command\fR
+\fBtrace remove execution\fI name opList commandPrefix\fR
If there is a trace set on command \fIname\fR with the operations and
-command given by \fIopList\fR and \fIcommand\fR, then the trace is
-removed, so that \fIcommand\fR will never again be invoked. Returns
-an empty string. If \fIname\fR doesn't exist, the command will throw
+command given by \fIopList\fR and \fIcommandPrefix\fR, then the trace is
+removed, so that \fIcommandPrefix\fR will never again be invoked. Returns
+an empty string. If \fIname\fR does not exist, the command will throw
an error.
.TP
-\fBtrace remove variable\fI name opList command\fR
+\fBtrace remove variable\fI name opList commandPrefix\fR
If there is a trace set on variable \fIname\fR with the operations and
-command given by \fIopList\fR and \fIcommand\fR, then the trace is
-removed, so that \fIcommand\fR will never again be invoked. Returns
+command given by \fIopList\fR and \fIcommandPrefix\fR, then the trace is
+removed, so that \fIcommandPrefix\fR will never again be invoked. Returns
an empty string.
.RE
.TP
@@ -311,24 +326,24 @@ Where \fItype\fR is either \fBcommand\fR, \fBexecution\fR or \fBvariable\fR.
\fBtrace info command\fI name\fR
Returns a list containing one element for each trace currently set on
command \fIname\fR. Each element of the list is itself a list
-containing two elements, which are the \fIopList\fR and \fIcommand\fR
-associated with the trace. If \fIname\fR doesn't have any traces set,
+containing two elements, which are the \fIopList\fR and \fIcommandPrefix\fR
+associated with the trace. If \fIname\fR does not have any traces set,
then the result of the command will be an empty string. If \fIname\fR
-doesn't exist, the command will throw an error.
+does not exist, the command will throw an error.
.TP
\fBtrace info execution\fI name\fR
Returns a list containing one element for each trace currently set on
command \fIname\fR. Each element of the list is itself a list
-containing two elements, which are the \fIopList\fR and \fIcommand\fR
-associated with the trace. If \fIname\fR doesn't have any traces set,
+containing two elements, which are the \fIopList\fR and \fIcommandPrefix\fR
+associated with the trace. If \fIname\fR does not have any traces set,
then the result of the command will be an empty string. If \fIname\fR
-doesn't exist, the command will throw an error.
+does not exist, the command will throw an error.
.TP
\fBtrace info variable\fI name\fR
Returns a list containing one element for each trace currently set on
variable \fIname\fR. Each element of the list is itself a list
-containing two elements, which are the \fIopList\fR and \fIcommand\fR
-associated with the trace. If \fIname\fR doesn't exist or doesn't
+containing two elements, which are the \fIopList\fR and \fIcommandPrefix\fR
+associated with the trace. If \fIname\fR does not exist or does not
have any traces set, then the result of the command will be an empty
string.
.RE
@@ -341,8 +356,8 @@ This is equivalent to \fBtrace add variable \fIname ops command\fR.
.TP
\fBtrace vdelete \fIname ops command\fR
This is equivalent to \fBtrace remove variable \fIname ops command\fR
-.TP
-\fBtrace vinfo \fIname\fR
+.TP
+\fBtrace vinfo \fIname\fR
This is equivalent to \fBtrace info variable \fIname\fR
.RE
.PP
@@ -375,9 +390,22 @@ proc doMult args {
\fBtrace add\fR variable foo write doMult
\fBtrace add\fR variable bar write doMult
.CE
-
+.PP
+Print a trace of what commands are executed during the processing of a Tcl
+procedure:
+.CS
+proc x {} { y }
+proc y {} { z }
+proc z {} { puts hello }
+proc report args {puts [info level 0]}
+\fBtrace add\fR execution x enterstep report
+x
+ \(-> \fIreport y enterstep\fR
+ \fIreport z enterstep\fR
+ \fIreport {puts hello} enterstep\fR
+ \fIhello\fR
+.CE
.SH "SEE ALSO"
set(n), unset(n)
-
.SH KEYWORDS
read, command, rename, variable, write, trace, unset
diff --git a/doc/unknown.n b/doc/unknown.n
index a5cbe6f..c258daa 100644
--- a/doc/unknown.n
+++ b/doc/unknown.n
@@ -14,22 +14,24 @@ unknown \- Handle attempts to use non-existent commands
.SH SYNOPSIS
\fBunknown \fIcmdName \fR?\fIarg arg ...\fR?
.BE
-
.SH DESCRIPTION
.PP
This command is invoked by the Tcl interpreter whenever a script
-tries to invoke a command that doesn't exist. The default implementation
+tries to invoke a command that does not exist. The default implementation
of \fBunknown\fR is a library procedure defined when Tcl initializes an
interpreter. You can override the default \fBunknown\fR to change its
-functionality. Note that there is no default implementation of
-\fBunknown\fR in a safe interpreter.
+functionality, or you can register a new handler for individual namespaces
+using the \fBnamespace unknown\fR command. Note that there is no default
+implementation of \fBunknown\fR in a safe interpreter.
.PP
If the Tcl interpreter encounters a command name for which there
-is not a defined command, then Tcl checks for the existence of
-a command named \fBunknown\fR.
-If there is no such command, then the interpreter returns an
-error.
-If the \fBunknown\fR command exists, then it is invoked with
+is not a defined command (in either the current namespace, or the
+global namespace), then Tcl checks for the existence of
+an unknown handler for the current namespace. By default, this
+handler is a command named \fB::unknown\fR. If there is no such
+command, then the interpreter returns an error.
+If the \fBunknown\fR command exists (or a new handler has been
+registered for the current namespace), then it is invoked with
arguments consisting of the fully-substituted name and arguments
for the original non-existent command.
The \fBunknown\fR command typically does things like searching
@@ -49,7 +51,7 @@ If the auto-load fails then \fBunknown\fR calls \fBauto_execok\fR
to see if there is an executable file by the name \fIcmd\fR.
If so, it invokes the Tcl \fBexec\fR command
with \fIcmd\fR and all the \fIargs\fR as arguments.
-If \fIcmd\fR can't be auto-executed, \fBunknown\fR checks to
+If \fIcmd\fR cannot be auto-executed, \fBunknown\fR checks to
see if the command was invoked at top-level and outside of any
script. If so, then \fBunknown\fR takes two additional steps.
First, it sees if \fIcmd\fR has one of the following three forms:
@@ -80,12 +82,10 @@ rename \fBunknown\fR _original_unknown
# Provide our own implementation
proc \fBunknown\fR args {
puts stderr "WARNING: unknown command: $args"
- uplevel 1 [list _original_unknown {expand}$args]
+ uplevel 1 [list _original_unknown {*}$args]
}
.CE
-
.SH "SEE ALSO"
-info(n), proc(n), interp(n), library(n)
-
+info(n), proc(n), interp(n), library(n), namespace(n)
.SH KEYWORDS
error, non-existent command
diff --git a/doc/unload.n b/doc/unload.n
new file mode 100644
index 0000000..f060cd6
--- /dev/null
+++ b/doc/unload.n
@@ -0,0 +1,162 @@
+'\"
+'\" Copyright (c) 2003 George Petasis <petasis@iit.demokritos.gr>.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.so man.macros
+.TH unload n 8.5 Tcl "Tcl Built-In Commands"
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+unload \- Unload machine code
+.SH SYNOPSIS
+\fBunload \fR?\fIswitches\fR? \fIfileName\fR
+.br
+\fBunload \fR?\fIswitches\fR? \fIfileName packageName\fR
+.br
+\fBunload \fR?\fIswitches\fR? \fIfileName packageName interp\fR
+.BE
+.SH DESCRIPTION
+.PP
+This command tries to unload shared libraries previously loaded
+with \fBload\fR from the application's address space. \fIfileName\fR
+is the name of the file containing the library file to be unload; it
+must be the same as the filename provided to \fBload\fR for
+loading the library.
+The \fIpackageName\fR argument is the name of the package (as
+determined by or passed to \fBload\fR), and is used to
+compute the name of the unload procedure; if not supplied, it is
+computed from \fIfileName\fR in the same manner as \fBload\fR.
+The \fIinterp\fR argument is the path name of the interpreter from
+which to unload the package (see the \fBinterp\fR manual entry for
+details); if \fIinterp\fR is omitted, it defaults to the
+interpreter in which the \fBunload\fR command was invoked.
+.PP
+If the initial arguments to \fBunload\fR start with \fB\-\fR then
+they are treated as switches. The following switches are
+currently supported:
+.TP
+\fB\-nocomplain\fR
+.
+Suppresses all error messages. If this switch is given, \fBunload\fR will
+never report an error.
+.TP
+\fB\-keeplibrary\fR
+.
+This switch will prevent \fBunload\fR from issuing the operating system call
+that will unload the library from the process.
+.TP
+\fB\-\|\-\fR
+.
+Marks the end of switches. The argument following this one will
+be treated as a \fIfileName\fR even if it starts with a \fB\-\fR.
+.SS "UNLOAD OPERATION"
+.PP
+When a file containing a shared library is loaded through the
+\fBload\fR command, Tcl associates two reference counts to the library
+file. The first counter shows how many times the library has been
+loaded into normal (trusted) interpreters while the second describes how many
+times the library has been loaded into safe interpreters. As a file containing
+a shared library can be loaded only once by Tcl (with the first \fBload\fR
+call on the file), these counters track how many interpreters use the library.
+Each subsequent call to \fBload\fR after the first simply increments the
+proper reference count.
+.PP
+\fBunload\fR works in the opposite direction. As a first step, \fBunload\fR
+will check whether the library is unloadable: an unloadable library exports
+a special unload procedure. The name of the unload procedure is determined by
+\fIpackageName\fR and whether or not the target interpreter
+is a safe one. For normal interpreters the name of the initialization
+procedure will have the form \fIpkg\fB_Unload\fR, where \fIpkg\fR
+is the same as \fIpackageName\fR except that the first letter is
+converted to upper case and all other letters
+are converted to lower case. For example, if \fIpackageName\fR is
+\fBfoo\fR or \fBFOo\fR, the initialization procedure's name will
+be \fBFoo_Unload\fR.
+If the target interpreter is a safe interpreter, then the name
+of the initialization procedure will be \fIpkg\fB_SafeUnload\fR
+instead of \fIpkg\fB_Unload\fR.
+.PP
+If \fBunload\fR determines that a library is not unloadable (or unload
+functionality has been disabled during compilation), an error will be returned.
+If the library is unloadable, then \fBunload\fR will call the unload
+procedure. If the unload procedure returns \fBTCL_OK\fR, \fBunload\fR will proceed
+and decrease the proper reference count (depending on the target interpreter
+type). When both reference counts have reached 0, the library will be
+detached from the process.
+.SS "UNLOAD HOOK PROTOTYPE"
+.PP
+The unload procedure must match the following prototype:
+.CS
+typedef int Tcl_PackageUnloadProc(Tcl_Interp *\fIinterp\fR, int \fIflags\fR);
+.CE
+.PP
+The \fIinterp\fR argument identifies the interpreter from which the
+library is to be unloaded. The unload procedure must return
+\fBTCL_OK\fR or \fBTCL_ERROR\fR to indicate whether or not it completed
+successfully; in the event of an error it should set the interpreter's result
+to point to an error message. In this case, the result of the
+\fBunload\fR command will be the result returned by the unload procedure.
+.PP
+The \fIflags\fR argument can be either \fBTCL_UNLOAD_DETACH_FROM_INTERPRETER\fR
+or \fBTCL_UNLOAD_DETACH_FROM_PROCESS\fR. In case the library will remain
+attached to the process after the unload procedure returns (i.e. because
+the library is used by other interpreters),
+\fBTCL_UNLOAD_DETACH_FROM_INTERPRETER\fR will be defined. However, if the
+library is used only by the target interpreter and the library will be
+detached from the application as soon as the unload procedure returns,
+the \fIflags\fR argument will be set to \fBTCL_UNLOAD_DETACH_FROM_PROCESS\fR.
+.SS NOTES
+.PP
+The \fBunload\fR command cannot unload libraries that are statically
+linked with the application.
+If \fIfileName\fR is an empty string, then the \fIpackageName\fR argument must
+be specified.
+.PP
+If \fIpackageName\fR is omitted or specified as an empty string,
+Tcl tries to guess the name of the package.
+This may be done differently on different platforms.
+The default guess, which is used on most UNIX platforms, is to
+take the last element of \fIfileName\fR, strip off the first
+three characters if they are \fBlib\fR, and use any following
+alphabetic and underline characters as the module name.
+For example, the command \fBunload libxyz4.2.so\fR uses the module
+name \fBxyz\fR and the command \fBunload bin/last.so {}\fR uses the
+module name \fBlast\fR.
+.SH "PORTABILITY ISSUES"
+.TP
+\fBUnix\fR\0\0\0\0\0
+.
+Not all unix operating systems support library unloading. Under such
+an operating system \fBunload\fR returns an error (unless \fB\-nocomplain\fR
+has been specified).
+.SH BUGS
+.PP
+If the same file is \fBload\fRed by different \fIfileName\fRs, it will
+be loaded into the process's address space multiple times. The
+behavior of this varies from system to system (some systems may
+detect the redundant loads, others may not). In case a library has been
+silently detached by the operating system (and as a result Tcl thinks the
+library is still loaded), it may be dangerous to use
+\fBunload\fR on such a library (as the library will be completely detached
+from the application while some interpreters will continue to use it).
+.SH EXAMPLE
+If an unloadable module in the file \fBfoobar.dll\fR had been loaded
+using the \fBload\fR command like this (on Windows):
+.CS
+load c:/some/dir/foobar.dll
+.CE
+then it would be unloaded like this:
+.CS
+\fBunload\fR c:/some/dir/foobar.dll
+.CE
+.PP
+This allows a C code module to be installed temporarily into a
+long-running Tcl program and then removed again (either because it is
+no longer needed or because it is being updated with a new version)
+without having to shut down the overall Tcl process.
+.SH "SEE ALSO"
+info sharedlibextension, load(n), safe(n)
+.SH KEYWORDS
+binary code, unloading, safe interpreter, shared library
diff --git a/doc/unset.n b/doc/unset.n
index 2bde1e2..29d7e7c 100644
--- a/doc/unset.n
+++ b/doc/unset.n
@@ -15,7 +15,6 @@ unset \- Delete variables
.SH SYNOPSIS
\fBunset \fR?\fI\-nocomplain\fR? ?\fI\-\-\fR? ?\fIname name name ...\fR?
.BE
-
.SH DESCRIPTION
.PP
This command removes one or more variables.
@@ -26,16 +25,14 @@ element is removed without affecting the rest of the array.
If a \fIname\fR consists of an array name with no parenthesized
index, then the entire array is deleted.
The \fBunset\fR command returns an empty string as result.
-.VS 8.4
If \fI\-nocomplain\fR is specified as the first argument, any possible
errors are suppressed. The option may not be abbreviated, in order to
disambiguate it from possible variable names. The option \fI\-\-\fR
indicates the end of the options, and should be used if you wish to
remove a variable with the same name as any of the options.
-.VE 8.4
If an error occurs, any variables after the named one causing the error
are not
-deleted. An error can occur when the named variable doesn't exist, or the
+deleted. An error can occur when the named variable does not exist, or the
name refers to an array element but the variable is a scalar, or the name
refers to a variable in a non-existent namespace.
.SH EXAMPLE
@@ -59,9 +56,7 @@ parray squares
puts "The prime squares are:"
parray squares
.CE
-
.SH "SEE ALSO"
set(n), trace(n), upvar(n)
-
.SH KEYWORDS
remove, variable
diff --git a/doc/update.n b/doc/update.n
index 41a50f8..555766c 100644
--- a/doc/update.n
+++ b/doc/update.n
@@ -17,7 +17,8 @@ update \- Process pending events and idle callbacks
.SH DESCRIPTION
.PP
-This command is used to bring the application ``up to date''
+This command is used to bring the application
+.QW "up to date"
by entering the event loop repeatedly until all pending events
(including idle callbacks) have been processed.
.PP
@@ -59,7 +60,7 @@ while {!$done} {
.CE
.SH "SEE ALSO"
-after(n), bgerror(n)
+after(n), interp(n)
.SH KEYWORDS
event, flush, handler, idle, update
diff --git a/doc/uplevel.n b/doc/uplevel.n
index d34716c..c8ef0ff 100644
--- a/doc/uplevel.n
+++ b/doc/uplevel.n
@@ -14,7 +14,6 @@ uplevel \- Execute a script in a different stack frame
.SH SYNOPSIS
\fBuplevel \fR?\fIlevel\fR?\fI arg \fR?\fIarg ...\fR?
.BE
-
.SH DESCRIPTION
.PP
All of the \fIarg\fR arguments are concatenated as if they had
@@ -53,16 +52,16 @@ the command
.CE
then the \fBset\fR command will modify the same variable \fBx\fR in \fBb\fR's
context: the procedure \fBc\fR does not appear to be on the call stack
-when \fBd\fR is executing. The command ``\fBinfo level\fR'' may
+when \fBd\fR is executing. The \fBinfo level\fR command may
be used to obtain the level of the current procedure.
.PP
\fBUplevel\fR makes it possible to implement new control
constructs as Tcl procedures (for example, \fBuplevel\fR could
be used to implement the \fBwhile\fR construct as a Tcl procedure).
.PP
-\fBnamespace eval\fR is another way (besides procedure calls)
-that the Tcl naming context can change.
-It adds a call frame to the stack to represent the namespace context.
+The \fBnamespace eval\fR and \fBapply\fR commands offer other ways
+(besides procedure calls) that the Tcl naming context can change.
+They add a call frame to the stack to represent the namespace context.
This means each \fBnamespace eval\fR command
counts as another call level for \fBuplevel\fR and \fBupvar\fR commands.
For example, \fBinfo level 1\fR will return a list
@@ -90,9 +89,7 @@ proc do {body while condition} {
}
}
.CE
-
.SH "SEE ALSO"
-namespace(n), upvar(n)
-
+apply(n), namespace(n), upvar(n)
.SH KEYWORDS
context, level, namespace, stack frame, variables
diff --git a/doc/upvar.n b/doc/upvar.n
index 03f4cd9..a255485 100644
--- a/doc/upvar.n
+++ b/doc/upvar.n
@@ -22,7 +22,7 @@ procedure to refer to variables in an enclosing procedure call or
to global variables.
\fILevel\fR may have any of the forms permitted for the \fBuplevel\fR
command, and may be omitted if the first letter of the first \fIotherVar\fR
-isn't \fB#\fR or a digit (it defaults to \fB1\fR).
+is not \fB#\fR or a digit (it defaults to \fB1\fR).
For each \fIotherVar\fR argument, \fBupvar\fR makes the variable
by that name in the procedure frame given by \fIlevel\fR (or at
global level, if \fIlevel\fR is \fB#0\fR) accessible
@@ -33,8 +33,8 @@ call; it will be created the first time \fImyVar\fR is referenced, just like
an ordinary variable. There must not exist a variable by the
name \fImyVar\fR at the time \fBupvar\fR is invoked.
\fIMyVar\fR is always treated as the name of a variable, not an
-array element. Even if the name looks like an array element,
-such as \fBa(b)\fR, a regular variable is created.
+array element. An error is returned if the name looks like an array element,
+such as \fBa(b)\fR.
\fIOtherVar\fR may refer to a scalar variable, an array,
or an array element.
\fBUpvar\fR returns an empty string.
@@ -44,14 +44,14 @@ procedure calling and also makes it easier to build new control constructs
as Tcl procedures.
For example, consider the following procedure:
.CS
-proc add2 name {
+proc \fIadd2\fR name {
\fBupvar\fR $name x
- set x [expr $x+2]
+ set x [expr {$x + 2}]
}
.CE
-\fBadd2\fR is invoked with an argument giving the name of a variable,
-and it adds two to the value of that variable.
-Although \fBadd2\fR could have been implemented using \fBuplevel\fR
+If \fIadd2\fR is invoked with an argument giving the name of a variable,
+it adds two to the value of that variable.
+Although \fIadd2\fR could have been implemented using \fBuplevel\fR
instead of \fBupvar\fR, \fBupvar\fR makes it simpler for \fBadd2\fR
to access the variable in the caller's procedure frame.
.PP
@@ -66,7 +66,6 @@ the outermost procedure call or the outermost \fBnamespace eval\fR command.
Also, \fBuplevel #0\fR evaluates a script
at top-level in the outermost namespace (the global namespace).
.PP
-.VS
If an upvar variable is unset (e.g. \fBx\fR in \fBadd2\fR above), the
\fBunset\fR operation affects the variable it is linked to, not the
upvar variable. There is no way to unset an upvar variable except
@@ -80,19 +79,21 @@ unexpected manner. If a variable trace is defined on \fIotherVar\fR, that
trace will be triggered by actions involving \fImyVar\fR. However,
the trace procedure will be passed the name of \fImyVar\fR, rather
than the name of \fIotherVar\fR. Thus, the output of the following code
-will be \fBlocalVar\fR rather than \fBoriginalVar\fR:
+will be
+.QW "\fIlocalVar\fR"
+rather than
+.QW "\fIoriginalVar\fR" :
.CS
-proc \fBtraceproc\fR { name index op } {
+proc \fItraceproc\fR { name index op } {
puts $name
}
-proc \fBsetByUpvar\fR { name value } {
+proc \fIsetByUpvar\fR { name value } {
\fBupvar\fR $name localVar
set localVar $value
}
set originalVar 1
-trace variable originalVar w \fBtraceproc\fR
-\fBsetByUpvar\fR originalVar 2
-}
+trace variable originalVar w \fItraceproc\fR
+\fIsetByUpvar\fR originalVar 2
.CE
.PP
If \fIotherVar\fR refers to an element of an array, then variable
@@ -100,7 +101,6 @@ traces set for the entire array will not be invoked when \fImyVar\fR
is accessed (but traces on the particular element will still be
invoked). In particular, if the array is \fBenv\fR, then changes
made to \fImyVar\fR will not be passed to subprocesses correctly.
-.VE
.SH EXAMPLE
A \fBdecr\fR command that works like \fBincr\fR except it subtracts
the value from the variable instead of adding it:
diff --git a/doc/vwait.n b/doc/vwait.n
index d1cdcbc..e7289e1 100644
--- a/doc/vwait.n
+++ b/doc/vwait.n
@@ -21,7 +21,7 @@ the application if no events are ready. It continues processing
events until some event handler sets the value of variable
\fIvarName\fR. Once \fIvarName\fR has been set, the \fBvwait\fR
command will return as soon as the event handler that modified
-\fIvarName\fR completes. \fIvarName\fR must globally scoped
+\fIvarName\fR completes. \fIvarName\fR must be globally scoped
(either with a call to \fBglobal\fR for the \fIvarName\fR, or with
the full namespace path specification).
.PP
diff --git a/generic/README b/generic/README
index ec6139a..d1c078e 100644
--- a/generic/README
+++ b/generic/README
@@ -1,3 +1,3 @@
This directory contains Tcl source files that work on all the platforms
-where Tcl runs (e.g. UNIX, PCs, and Macintoshes). Platform-specific
-sources are in the directories ../unix, ../win, ../macosx, and ../mac.
+where Tcl runs (e.g. UNIX, PCs, and MacOSX). Platform-specific
+sources are in the directories ../unix, ../win, and ../macosx.
diff --git a/generic/regc_color.c b/generic/regc_color.c
index f6716be..ba1f668 100644
--- a/generic/regc_color.c
+++ b/generic/regc_color.c
@@ -2,24 +2,24 @@
* colorings of characters
* This file is #included by regcomp.c.
*
- * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
- *
+ * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
+ *
* Development of this software was funded, in part, by Cray Research Inc.,
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
- * Corporation, none of whom are responsible for the results. The author
- * thanks all of them.
- *
+ * Corporation, none of whom are responsible for the results. The author
+ * thanks all of them.
+ *
* Redistribution and use in source and binary forms -- with or without
* modification -- are permitted for any purpose, provided that
* redistributions in source form retain this entire copyright notice and
* indicate the origin and nature of any modifications.
- *
- * I'd appreciate being given credit for this package in the documentation
- * of software which uses it, but that is not a requirement.
- *
+ *
+ * I'd appreciate being given credit for this package in the documentation of
+ * software which uses it, but that is not a requirement.
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
@@ -28,662 +28,712 @@
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- *
- *
- * Note that there are some incestuous relationships between this code and
- * NFA arc maintenance, which perhaps ought to be cleaned up sometime.
+ * Note that there are some incestuous relationships between this code and NFA
+ * arc maintenance, which perhaps ought to be cleaned up sometime.
*/
-
-
#define CISERR() VISERR(cm->v)
#define CERR(e) VERR(cm->v, (e))
-
-
-
+
/*
- initcm - set up new colormap
^ static VOID initcm(struct vars *, struct colormap *);
*/
-static VOID
-initcm(v, cm)
-struct vars *v;
-struct colormap *cm;
+static void
+initcm(
+ struct vars *v,
+ struct colormap *cm)
{
- int i;
- int j;
- union tree *t;
- union tree *nextt;
- struct colordesc *cd;
-
- cm->magic = CMMAGIC;
- cm->v = v;
-
- cm->ncds = NINLINECDS;
- cm->cd = cm->cdspace;
- cm->max = 0;
- cm->free = 0;
-
- cd = cm->cd; /* cm->cd[WHITE] */
- cd->sub = NOSUB;
- cd->arcs = NULL;
- cd->flags = 0;
- cd->nchrs = CHR_MAX - CHR_MIN + 1;
-
- /* upper levels of tree */
- for (t = &cm->tree[0], j = NBYTS-1; j > 0; t = nextt, j--) {
- nextt = t + 1;
- for (i = BYTTAB-1; i >= 0; i--)
- t->tptr[i] = nextt;
+ int i;
+ int j;
+ union tree *t;
+ union tree *nextt;
+ struct colordesc *cd;
+
+ cm->magic = CMMAGIC;
+ cm->v = v;
+
+ cm->ncds = NINLINECDS;
+ cm->cd = cm->cdspace;
+ cm->max = 0;
+ cm->free = 0;
+
+ cd = cm->cd; /* cm->cd[WHITE] */
+ cd->sub = NOSUB;
+ cd->arcs = NULL;
+ cd->flags = 0;
+ cd->nchrs = CHR_MAX - CHR_MIN + 1;
+
+ /*
+ * Upper levels of tree.
+ */
+
+ for (t=&cm->tree[0], j=NBYTS-1 ; j>0 ; t=nextt, j--) {
+ nextt = t + 1;
+ for (i=BYTTAB-1 ; i>=0 ; i--) {
+ t->tptr[i] = nextt;
}
- /* bottom level is solid white */
- t = &cm->tree[NBYTS-1];
- for (i = BYTTAB-1; i >= 0; i--)
- t->tcolor[i] = WHITE;
- cd->block = t;
-}
+ }
+ /*
+ * Bottom level is solid white.
+ */
+
+ t = &cm->tree[NBYTS-1];
+ for (i=BYTTAB-1 ; i>=0 ; i--) {
+ t->tcolor[i] = WHITE;
+ }
+ cd->block = t;
+}
+
/*
- freecm - free dynamically-allocated things in a colormap
^ static VOID freecm(struct colormap *);
*/
-static VOID
-freecm(cm)
-struct colormap *cm;
+static void
+freecm(
+ struct colormap *cm)
{
- size_t i;
- union tree *cb;
-
- cm->magic = 0;
- if (NBYTS > 1)
- cmtreefree(cm, cm->tree, 0);
- for (i = 1; i <= cm->max; i++) /* skip WHITE */
- if (!UNUSEDCOLOR(&cm->cd[i])) {
- cb = cm->cd[i].block;
- if (cb != NULL)
- FREE(cb);
- }
- if (cm->cd != cm->cdspace)
- FREE(cm->cd);
+ size_t i;
+ union tree *cb;
+
+ cm->magic = 0;
+ if (NBYTS > 1) {
+ cmtreefree(cm, cm->tree, 0);
+ }
+ for (i=1 ; i<=cm->max ; i++) { /* skip WHITE */
+ if (!UNUSEDCOLOR(&cm->cd[i])) {
+ cb = cm->cd[i].block;
+ if (cb != NULL) {
+ FREE(cb);
+ }
+ }
+ }
+ if (cm->cd != cm->cdspace) {
+ FREE(cm->cd);
+ }
}
-
+
/*
- cmtreefree - free a non-terminal part of a colormap tree
^ static VOID cmtreefree(struct colormap *, union tree *, int);
*/
-static VOID
-cmtreefree(cm, tree, level)
-struct colormap *cm;
-union tree *tree;
-int level; /* level number (top == 0) of this block */
+static void
+cmtreefree(
+ struct colormap *cm,
+ union tree *tree,
+ int level) /* level number (top == 0) of this block */
{
- int i;
- union tree *t;
- union tree *fillt = &cm->tree[level+1];
- union tree *cb;
-
- assert(level < NBYTS-1); /* this level has pointers */
- for (i = BYTTAB-1; i >= 0; i--) {
- t = tree->tptr[i];
- assert(t != NULL);
- if (t != fillt) {
- if (level < NBYTS-2) { /* more pointer blocks below */
- cmtreefree(cm, t, level+1);
- FREE(t);
- } else { /* color block below */
- cb = cm->cd[t->tcolor[0]].block;
- if (t != cb) /* not a solid block */
- FREE(t);
- }
+ int i;
+ union tree *t;
+ union tree *fillt = &cm->tree[level+1];
+ union tree *cb;
+
+ assert(level < NBYTS-1); /* this level has pointers */
+ for (i=BYTTAB-1 ; i>=0 ; i--) {
+ t = tree->tptr[i];
+ assert(t != NULL);
+ if (t != fillt) {
+ if (level < NBYTS-2) { /* more pointer blocks below */
+ cmtreefree(cm, t, level+1);
+ FREE(t);
+ } else { /* color block below */
+ cb = cm->cd[t->tcolor[0]].block;
+ if (t != cb) { /* not a solid block */
+ FREE(t);
}
+ }
}
+ }
}
-
+
/*
- setcolor - set the color of a character in a colormap
^ static color setcolor(struct colormap *, pchr, pcolor);
*/
static color /* previous color */
-setcolor(cm, c, co)
-struct colormap *cm;
-pchr c;
-pcolor co;
+setcolor(
+ struct colormap *cm,
+ pchr c,
+ pcolor co)
{
- uchr uc = c;
- int shift;
- int level;
- int b;
- int bottom;
- union tree *t;
- union tree *newt;
- union tree *fillt;
- union tree *lastt;
- union tree *cb;
- color prev;
-
- assert(cm->magic == CMMAGIC);
- if (CISERR() || co == COLORLESS)
+ uchr uc = c;
+ int shift;
+ int level;
+ int b;
+ int bottom;
+ union tree *t;
+ union tree *newt;
+ union tree *fillt;
+ union tree *lastt;
+ union tree *cb;
+ color prev;
+
+ assert(cm->magic == CMMAGIC);
+ if (CISERR() || co == COLORLESS) {
+ return COLORLESS;
+ }
+
+ t = cm->tree;
+ for (level=0, shift=BYTBITS*(NBYTS-1) ; shift>0; level++, shift-=BYTBITS){
+ b = (uc >> shift) & BYTMASK;
+ lastt = t;
+ t = lastt->tptr[b];
+ assert(t != NULL);
+ fillt = &cm->tree[level+1];
+ bottom = (shift <= BYTBITS) ? 1 : 0;
+ cb = (bottom) ? cm->cd[t->tcolor[0]].block : fillt;
+ if (t == fillt || t == cb) { /* must allocate a new block */
+ newt = (union tree *) MALLOC((bottom) ?
+ sizeof(struct colors) : sizeof(struct ptrs));
+ if (newt == NULL) {
+ CERR(REG_ESPACE);
return COLORLESS;
-
- t = cm->tree;
- for (level = 0, shift = BYTBITS * (NBYTS - 1); shift > 0;
- level++, shift -= BYTBITS) {
- b = (uc >> shift) & BYTMASK;
- lastt = t;
- t = lastt->tptr[b];
- assert(t != NULL);
- fillt = &cm->tree[level+1];
- bottom = (shift <= BYTBITS) ? 1 : 0;
- cb = (bottom) ? cm->cd[t->tcolor[0]].block : fillt;
- if (t == fillt || t == cb) { /* must allocate a new block */
- newt = (union tree *)MALLOC((bottom) ?
- sizeof(struct colors) : sizeof(struct ptrs));
- if (newt == NULL) {
- CERR(REG_ESPACE);
- return COLORLESS;
- }
- if (bottom)
- memcpy(VS(newt->tcolor), VS(t->tcolor),
- BYTTAB*sizeof(color));
- else
- memcpy(VS(newt->tptr), VS(t->tptr),
- BYTTAB*sizeof(union tree *));
- t = newt;
- lastt->tptr[b] = t;
- }
+ }
+ if (bottom) {
+ memcpy(newt->tcolor, t->tcolor, BYTTAB*sizeof(color));
+ } else {
+ memcpy(newt->tptr, t->tptr, BYTTAB*sizeof(union tree *));
+ }
+ t = newt;
+ lastt->tptr[b] = t;
}
+ }
- b = uc & BYTMASK;
- prev = t->tcolor[b];
- t->tcolor[b] = (color)co;
- return prev;
+ b = uc & BYTMASK;
+ prev = t->tcolor[b];
+ t->tcolor[b] = (color) co;
+ return prev;
}
-
+
/*
- maxcolor - report largest color number in use
^ static color maxcolor(struct colormap *);
*/
static color
-maxcolor(cm)
-struct colormap *cm;
+maxcolor(
+ struct colormap *cm)
{
- if (CISERR())
- return COLORLESS;
+ if (CISERR()) {
+ return COLORLESS;
+ }
- return (color)cm->max;
+ return (color) cm->max;
}
-
+
/*
- newcolor - find a new color (must be subject of setcolor at once)
- * Beware: may relocate the colordescs.
+ * Beware: may relocate the colordescs.
^ static color newcolor(struct colormap *);
*/
static color /* COLORLESS for error */
-newcolor(cm)
-struct colormap *cm;
+newcolor(
+ struct colormap *cm)
{
- struct colordesc *cd;
- struct colordesc *new;
- size_t n;
-
- if (CISERR())
- return COLORLESS;
-
- if (cm->free != 0) {
- assert(cm->free > 0);
- assert((size_t)cm->free < cm->ncds);
- cd = &cm->cd[cm->free];
- assert(UNUSEDCOLOR(cd));
- assert(cd->arcs == NULL);
- cm->free = cd->sub;
- } else if (cm->max < cm->ncds - 1) {
- cm->max++;
- cd = &cm->cd[cm->max];
+ struct colordesc *cd;
+ size_t n;
+
+ if (CISERR()) {
+ return COLORLESS;
+ }
+
+ if (cm->free != 0) {
+ assert(cm->free > 0);
+ assert((size_t) cm->free < cm->ncds);
+ cd = &cm->cd[cm->free];
+ assert(UNUSEDCOLOR(cd));
+ assert(cd->arcs == NULL);
+ cm->free = cd->sub;
+ } else if (cm->max < cm->ncds - 1) {
+ cm->max++;
+ cd = &cm->cd[cm->max];
+ } else {
+ struct colordesc *newCd;
+
+ /*
+ * Oops, must allocate more.
+ */
+
+ n = cm->ncds * 2;
+ if (cm->cd == cm->cdspace) {
+ newCd = (struct colordesc *) MALLOC(n * sizeof(struct colordesc));
+ if (newCd != NULL) {
+ memcpy(newCd, cm->cdspace,
+ cm->ncds * sizeof(struct colordesc));
+ }
} else {
- /* oops, must allocate more */
- n = cm->ncds * 2;
- if (cm->cd == cm->cdspace) {
- new = (struct colordesc *)MALLOC(n *
- sizeof(struct colordesc));
- if (new != NULL)
- memcpy(VS(new), VS(cm->cdspace), cm->ncds *
- sizeof(struct colordesc));
- } else
- new = (struct colordesc *)REALLOC(cm->cd,
- n * sizeof(struct colordesc));
- if (new == NULL) {
- CERR(REG_ESPACE);
- return COLORLESS;
- }
- cm->cd = new;
- cm->ncds = n;
- assert(cm->max < cm->ncds - 1);
- cm->max++;
- cd = &cm->cd[cm->max];
+ newCd = (struct colordesc *)
+ REALLOC(cm->cd, n * sizeof(struct colordesc));
}
-
- cd->nchrs = 0;
- cd->sub = NOSUB;
- cd->arcs = NULL;
- cd->flags = 0;
- cd->block = NULL;
-
- return (color)(cd - cm->cd);
+ if (newCd == NULL) {
+ CERR(REG_ESPACE);
+ return COLORLESS;
+ }
+ cm->cd = newCd;
+ cm->ncds = n;
+ assert(cm->max < cm->ncds - 1);
+ cm->max++;
+ cd = &cm->cd[cm->max];
+ }
+
+ cd->nchrs = 0;
+ cd->sub = NOSUB;
+ cd->arcs = NULL;
+ cd->flags = 0;
+ cd->block = NULL;
+
+ return (color) (cd - cm->cd);
}
-
+
/*
- freecolor - free a color (must have no arcs or subcolor)
^ static VOID freecolor(struct colormap *, pcolor);
*/
-static VOID
-freecolor(cm, co)
-struct colormap *cm;
-pcolor co;
+static void
+freecolor(
+ struct colormap *cm,
+ pcolor co)
{
- struct colordesc *cd = &cm->cd[co];
- color pco, nco; /* for freelist scan */
-
- assert(co >= 0);
- if (co == WHITE)
- return;
-
- assert(cd->arcs == NULL);
- assert(cd->sub == NOSUB);
- assert(cd->nchrs == 0);
- cd->flags = FREECOL;
- if (cd->block != NULL) {
- FREE(cd->block);
- cd->block = NULL; /* just paranoia */
+ struct colordesc *cd = &cm->cd[co];
+ color pco, nco; /* for freelist scan */
+
+ assert(co >= 0);
+ if (co == WHITE) {
+ return;
+ }
+
+ assert(cd->arcs == NULL);
+ assert(cd->sub == NOSUB);
+ assert(cd->nchrs == 0);
+ cd->flags = FREECOL;
+ if (cd->block != NULL) {
+ FREE(cd->block);
+ cd->block = NULL; /* just paranoia */
+ }
+
+ if ((size_t) co == cm->max) {
+ while (cm->max > WHITE && UNUSEDCOLOR(&cm->cd[cm->max])) {
+ cm->max--;
}
-
- if ((size_t)co == cm->max) {
- while (cm->max > WHITE && UNUSEDCOLOR(&cm->cd[cm->max]))
- cm->max--;
- assert(cm->free >= 0);
- while ((size_t)cm->free > cm->max)
- cm->free = cm->cd[cm->free].sub;
- if (cm->free > 0) {
- assert(cm->free < cm->max);
- pco = cm->free;
- nco = cm->cd[pco].sub;
- while (nco > 0)
- if ((size_t)nco > cm->max) {
- /* take this one out of freelist */
- nco = cm->cd[nco].sub;
- cm->cd[pco].sub = nco;
- } else {
- assert(nco < cm->max);
- pco = nco;
- nco = cm->cd[pco].sub;
- }
+ assert(cm->free >= 0);
+ while ((size_t) cm->free > cm->max) {
+ cm->free = cm->cd[cm->free].sub;
+ }
+ if (cm->free > 0) {
+ assert(cm->free < cm->max);
+ pco = cm->free;
+ nco = cm->cd[pco].sub;
+ while (nco > 0) {
+ if ((size_t) nco > cm->max) {
+ /*
+ * Take this one out of freelist.
+ */
+
+ nco = cm->cd[nco].sub;
+ cm->cd[pco].sub = nco;
+ } else {
+ assert(nco < cm->max);
+ pco = nco;
+ nco = cm->cd[pco].sub;
}
- } else {
- cd->sub = cm->free;
- cm->free = (color)(cd - cm->cd);
+ }
}
+ } else {
+ cd->sub = cm->free;
+ cm->free = (color) (cd - cm->cd);
+ }
}
-
+
/*
- pseudocolor - allocate a false color, to be managed by other means
^ static color pseudocolor(struct colormap *);
*/
static color
-pseudocolor(cm)
-struct colormap *cm;
+pseudocolor(
+ struct colormap *cm)
{
- color co;
-
- co = newcolor(cm);
- if (CISERR())
- return COLORLESS;
- cm->cd[co].nchrs = 1;
- cm->cd[co].flags = PSEUDO;
- return co;
+ color co;
+
+ co = newcolor(cm);
+ if (CISERR()) {
+ return COLORLESS;
+ }
+ cm->cd[co].nchrs = 1;
+ cm->cd[co].flags = PSEUDO;
+ return co;
}
-
+
/*
- subcolor - allocate a new subcolor (if necessary) to this chr
^ static color subcolor(struct colormap *, pchr c);
*/
static color
-subcolor(cm, c)
-struct colormap *cm;
-pchr c;
+subcolor(
+ struct colormap *cm,
+ pchr c)
{
- color co; /* current color of c */
- color sco; /* new subcolor */
-
- co = GETCOLOR(cm, c);
- sco = newsub(cm, co);
- if (CISERR())
- return COLORLESS;
- assert(sco != COLORLESS);
-
- if (co == sco) /* already in an open subcolor */
- return co; /* rest is redundant */
- cm->cd[co].nchrs--;
- cm->cd[sco].nchrs++;
- setcolor(cm, c, sco);
- return sco;
+ color co; /* current color of c */
+ color sco; /* new subcolor */
+
+ co = GETCOLOR(cm, c);
+ sco = newsub(cm, co);
+ if (CISERR()) {
+ return COLORLESS;
+ }
+ assert(sco != COLORLESS);
+
+ if (co == sco) { /* already in an open subcolor */
+ return co; /* rest is redundant */
+ }
+ cm->cd[co].nchrs--;
+ cm->cd[sco].nchrs++;
+ setcolor(cm, c, sco);
+ return sco;
}
-
+
/*
- newsub - allocate a new subcolor (if necessary) for a color
^ static color newsub(struct colormap *, pcolor);
*/
static color
-newsub(cm, co)
-struct colormap *cm;
-pcolor co;
+newsub(
+ struct colormap *cm,
+ pcolor co)
{
- color sco; /* new subcolor */
-
- sco = cm->cd[co].sub;
- if (sco == NOSUB) { /* color has no open subcolor */
- if (cm->cd[co].nchrs == 1) /* optimization */
- return co;
- sco = newcolor(cm); /* must create subcolor */
- if (sco == COLORLESS) {
- assert(CISERR());
- return COLORLESS;
- }
- cm->cd[co].sub = sco;
- cm->cd[sco].sub = sco; /* open subcolor points to self */
+ color sco; /* new subcolor */
+
+ sco = cm->cd[co].sub;
+ if (sco == NOSUB) { /* color has no open subcolor */
+ if (cm->cd[co].nchrs == 1) { /* optimization */
+ return co;
+ }
+ sco = newcolor(cm); /* must create subcolor */
+ if (sco == COLORLESS) {
+ assert(CISERR());
+ return COLORLESS;
}
- assert(sco != NOSUB);
+ cm->cd[co].sub = sco;
+ cm->cd[sco].sub = sco; /* open subcolor points to self */
+ }
+ assert(sco != NOSUB);
- return sco;
+ return sco;
}
-
+
/*
- subrange - allocate new subcolors to this range of chrs, fill in arcs
^ static VOID subrange(struct vars *, pchr, pchr, struct state *,
^ struct state *);
*/
-static VOID
-subrange(v, from, to, lp, rp)
-struct vars *v;
-pchr from;
-pchr to;
-struct state *lp;
-struct state *rp;
+static void
+subrange(
+ struct vars *v,
+ pchr from,
+ pchr to,
+ struct state *lp,
+ struct state *rp)
{
- uchr uf;
- int i;
-
- assert(from <= to);
-
- /* first, align "from" on a tree-block boundary */
- uf = (uchr)from;
- i = (int)( ((uf + BYTTAB-1) & (uchr)~BYTMASK) - uf );
- for (; from <= to && i > 0; i--, from++)
- newarc(v->nfa, PLAIN, subcolor(v->cm, from), lp, rp);
- if (from > to) /* didn't reach a boundary */
- return;
-
- /* deal with whole blocks */
- for (; to - from >= BYTTAB; from += BYTTAB)
- subblock(v, from, lp, rp);
-
- /* clean up any remaining partial table */
- for (; from <= to; from++)
- newarc(v->nfa, PLAIN, subcolor(v->cm, from), lp, rp);
+ uchr uf;
+ int i;
+
+ assert(from <= to);
+
+ /*
+ * First, align "from" on a tree-block boundary
+ */
+
+ uf = (uchr) from;
+ i = (int) (((uf + BYTTAB - 1) & (uchr) ~BYTMASK) - uf);
+ for (; from<=to && i>0; i--, from++) {
+ newarc(v->nfa, PLAIN, subcolor(v->cm, from), lp, rp);
+ }
+ if (from > to) { /* didn't reach a boundary */
+ return;
+ }
+
+ /*
+ * Deal with whole blocks.
+ */
+
+ for (; to-from>=BYTTAB ; from+=BYTTAB) {
+ subblock(v, from, lp, rp);
+ }
+
+ /*
+ * Clean up any remaining partial table.
+ */
+
+ for (; from<=to ; from++) {
+ newarc(v->nfa, PLAIN, subcolor(v->cm, from), lp, rp);
+ }
}
-
+
/*
- subblock - allocate new subcolors for one tree block of chrs, fill in arcs
^ static VOID subblock(struct vars *, pchr, struct state *, struct state *);
*/
-static VOID
-subblock(v, start, lp, rp)
-struct vars *v;
-pchr start; /* first of BYTTAB chrs */
-struct state *lp;
-struct state *rp;
+static void
+subblock(
+ struct vars *v,
+ pchr start, /* first of BYTTAB chrs */
+ struct state *lp,
+ struct state *rp)
{
- uchr uc = start;
- struct colormap *cm = v->cm;
- int shift;
- int level;
- int i;
- int b;
- union tree *t;
- union tree *cb;
- union tree *fillt;
- union tree *lastt;
- int previ;
- int ndone;
- color co;
- color sco;
-
- assert((uc % BYTTAB) == 0);
-
- /* find its color block, making new pointer blocks as needed */
- t = cm->tree;
- fillt = NULL;
- for (level = 0, shift = BYTBITS * (NBYTS - 1); shift > 0;
- level++, shift -= BYTBITS) {
- b = (uc >> shift) & BYTMASK;
- lastt = t;
- t = lastt->tptr[b];
- assert(t != NULL);
- fillt = &cm->tree[level+1];
- if (t == fillt && shift > BYTBITS) { /* need new ptr block */
- t = (union tree *)MALLOC(sizeof(struct ptrs));
- if (t == NULL) {
- CERR(REG_ESPACE);
- return;
- }
- memcpy(VS(t->tptr), VS(fillt->tptr),
- BYTTAB*sizeof(union tree *));
- lastt->tptr[b] = t;
- }
+ uchr uc = start;
+ struct colormap *cm = v->cm;
+ int shift;
+ int level;
+ int i;
+ int b;
+ union tree *t;
+ union tree *cb;
+ union tree *fillt;
+ union tree *lastt;
+ int previ;
+ int ndone;
+ color co;
+ color sco;
+
+ assert((uc % BYTTAB) == 0);
+
+ /*
+ * Find its color block, making new pointer blocks as needed.
+ */
+
+ t = cm->tree;
+ fillt = NULL;
+ for (level=0, shift=BYTBITS*(NBYTS-1); shift>0; level++, shift-=BYTBITS) {
+ b = (uc >> shift) & BYTMASK;
+ lastt = t;
+ t = lastt->tptr[b];
+ assert(t != NULL);
+ fillt = &cm->tree[level+1];
+ if (t == fillt && shift > BYTBITS) { /* need new ptr block */
+ t = (union tree *) MALLOC(sizeof(struct ptrs));
+ if (t == NULL) {
+ CERR(REG_ESPACE);
+ return;
+ }
+ memcpy(t->tptr, fillt->tptr, BYTTAB*sizeof(union tree *));
+ lastt->tptr[b] = t;
}
+ }
+
+ /*
+ * Special cases: fill block or solid block.
+ */
+ co = t->tcolor[0];
+ cb = cm->cd[co].block;
+ if (t == fillt || t == cb) {
+ /*
+ * Either way, we want a subcolor solid block.
+ */
- /* special cases: fill block or solid block */
- co = t->tcolor[0];
- cb = cm->cd[co].block;
- if (t == fillt || t == cb) {
- /* either way, we want a subcolor solid block */
- sco = newsub(cm, co);
- t = cm->cd[sco].block;
- if (t == NULL) { /* must set it up */
- t = (union tree *)MALLOC(sizeof(struct colors));
- if (t == NULL) {
- CERR(REG_ESPACE);
- return;
- }
- for (i = 0; i < BYTTAB; i++)
- t->tcolor[i] = sco;
- cm->cd[sco].block = t;
- }
- /* find loop must have run at least once */
- lastt->tptr[b] = t;
- newarc(v->nfa, PLAIN, sco, lp, rp);
- cm->cd[co].nchrs -= BYTTAB;
- cm->cd[sco].nchrs += BYTTAB;
+ sco = newsub(cm, co);
+ t = cm->cd[sco].block;
+ if (t == NULL) { /* must set it up */
+ t = (union tree *) MALLOC(sizeof(struct colors));
+ if (t == NULL) {
+ CERR(REG_ESPACE);
return;
+ }
+ for (i=0 ; i<BYTTAB ; i++) {
+ t->tcolor[i] = sco;
+ }
+ cm->cd[sco].block = t;
}
- /* general case, a mixed block to be altered */
- i = 0;
- while (i < BYTTAB) {
- co = t->tcolor[i];
- sco = newsub(cm, co);
- newarc(v->nfa, PLAIN, sco, lp, rp);
- previ = i;
- do {
- t->tcolor[i++] = sco;
- } while (i < BYTTAB && t->tcolor[i] == co);
- ndone = i - previ;
- cm->cd[co].nchrs -= ndone;
- cm->cd[sco].nchrs += ndone;
- }
-}
+ /*
+ * Find loop must have run at least once.
+ */
+
+ lastt->tptr[b] = t;
+ newarc(v->nfa, PLAIN, sco, lp, rp);
+ cm->cd[co].nchrs -= BYTTAB;
+ cm->cd[sco].nchrs += BYTTAB;
+ return;
+ }
+
+ /*
+ * General case, a mixed block to be altered.
+ */
+ i = 0;
+ while (i < BYTTAB) {
+ co = t->tcolor[i];
+ sco = newsub(cm, co);
+ newarc(v->nfa, PLAIN, sco, lp, rp);
+ previ = i;
+ do {
+ t->tcolor[i++] = sco;
+ } while (i < BYTTAB && t->tcolor[i] == co);
+ ndone = i - previ;
+ cm->cd[co].nchrs -= ndone;
+ cm->cd[sco].nchrs += ndone;
+ }
+}
+
/*
- okcolors - promote subcolors to full colors
^ static VOID okcolors(struct nfa *, struct colormap *);
*/
-static VOID
-okcolors(nfa, cm)
-struct nfa *nfa;
-struct colormap *cm;
+static void
+okcolors(
+ struct nfa *nfa,
+ struct colormap *cm)
{
- struct colordesc *cd;
- struct colordesc *end = CDEND(cm);
- struct colordesc *scd;
- struct arc *a;
- color co;
- color sco;
-
- for (cd = cm->cd, co = 0; cd < end; cd++, co++) {
- sco = cd->sub;
- if (UNUSEDCOLOR(cd) || sco == NOSUB) {
- /* has no subcolor, no further action */
- } else if (sco == co) {
- /* is subcolor, let parent deal with it */
- } else if (cd->nchrs == 0) {
- /* parent empty, its arcs change color to subcolor */
- cd->sub = NOSUB;
- scd = &cm->cd[sco];
- assert(scd->nchrs > 0);
- assert(scd->sub == sco);
- scd->sub = NOSUB;
- while ((a = cd->arcs) != NULL) {
- assert(a->co == co);
- uncolorchain(cm, a);
- a->co = sco;
- colorchain(cm, a);
- }
- freecolor(cm, co);
- } else {
- /* parent's arcs must gain parallel subcolor arcs */
- cd->sub = NOSUB;
- scd = &cm->cd[sco];
- assert(scd->nchrs > 0);
- assert(scd->sub == sco);
- scd->sub = NOSUB;
- for (a = cd->arcs; a != NULL; a = a->colorchain) {
- assert(a->co == co);
- newarc(nfa, a->type, sco, a->from, a->to);
- }
- }
+ struct colordesc *cd;
+ struct colordesc *end = CDEND(cm);
+ struct colordesc *scd;
+ struct arc *a;
+ color co;
+ color sco;
+
+ for (cd=cm->cd, co=0 ; cd<end ; cd++, co++) {
+ sco = cd->sub;
+ if (UNUSEDCOLOR(cd) || sco == NOSUB) {
+ /*
+ * Has no subcolor, no further action.
+ */
+ } else if (sco == co) {
+ /*
+ * Is subcolor, let parent deal with it.
+ */
+ } else if (cd->nchrs == 0) {
+ /*
+ * Parent empty, its arcs change color to subcolor.
+ */
+
+ cd->sub = NOSUB;
+ scd = &cm->cd[sco];
+ assert(scd->nchrs > 0);
+ assert(scd->sub == sco);
+ scd->sub = NOSUB;
+ while ((a = cd->arcs) != NULL) {
+ assert(a->co == co);
+ uncolorchain(cm, a);
+ a->co = sco;
+ colorchain(cm, a);
+ }
+ freecolor(cm, co);
+ } else {
+ /*
+ * Parent's arcs must gain parallel subcolor arcs.
+ */
+
+ cd->sub = NOSUB;
+ scd = &cm->cd[sco];
+ assert(scd->nchrs > 0);
+ assert(scd->sub == sco);
+ scd->sub = NOSUB;
+ for (a=cd->arcs ; a!=NULL ; a=a->colorchain) {
+ assert(a->co == co);
+ newarc(nfa, a->type, sco, a->from, a->to);
+ }
}
+ }
}
-
+
/*
- colorchain - add this arc to the color chain of its color
^ static VOID colorchain(struct colormap *, struct arc *);
*/
-static VOID
-colorchain(cm, a)
-struct colormap *cm;
-struct arc *a;
+static void
+colorchain(
+ struct colormap *cm,
+ struct arc *a)
{
- struct colordesc *cd = &cm->cd[a->co];
-
- if (cd->arcs)
- cd->arcs->colorchain_rev = a;
- a->colorchain = cd->arcs;
- a->colorchain_rev = NULL;
- cd->arcs = a;
+ struct colordesc *cd = &cm->cd[a->co];
+
+ if (cd->arcs != NULL) {
+ cd->arcs->colorchainRev = a;
+ }
+ a->colorchain = cd->arcs;
+ a->colorchainRev = NULL;
+ cd->arcs = a;
}
-
+
/*
- uncolorchain - delete this arc from the color chain of its color
^ static VOID uncolorchain(struct colormap *, struct arc *);
*/
-static VOID
-uncolorchain(cm, a)
-struct colormap *cm;
-struct arc *a;
-{
- struct colordesc *cd = &cm->cd[a->co];
- struct arc *aa = a->colorchain_rev;
-
- if (aa == NULL) {
- assert(cd->arcs == a);
- cd->arcs = a->colorchain;
- } else {
- assert(aa->colorchain == a);
- aa->colorchain = a->colorchain;
- }
- if (a->colorchain)
- a->colorchain->colorchain_rev = aa;
- a->colorchain = NULL; /* paranoia */
- a->colorchain_rev = NULL;
-}
-
-/*
- - singleton - is this character in its own color?
- ^ static int singleton(struct colormap *, pchr c);
- */
-static int /* predicate */
-singleton(cm, c)
-struct colormap *cm;
-pchr c;
+static void
+uncolorchain(
+ struct colormap *cm,
+ struct arc *a)
{
- color co; /* color of c */
-
- co = GETCOLOR(cm, c);
- if (cm->cd[co].nchrs == 1 && cm->cd[co].sub == NOSUB)
- return 1;
- return 0;
+ struct colordesc *cd = &cm->cd[a->co];
+ struct arc *aa = a->colorchainRev;
+
+ if (aa == NULL) {
+ assert(cd->arcs == a);
+ cd->arcs = a->colorchain;
+ } else {
+ assert(aa->colorchain == a);
+ aa->colorchain = a->colorchain;
+ }
+ if (a->colorchain != NULL) {
+ a->colorchain->colorchainRev = aa;
+ }
+ a->colorchain = NULL; /* paranoia */
+ a->colorchainRev = NULL;
}
-
+
/*
- rainbow - add arcs of all full colors (but one) between specified states
^ static VOID rainbow(struct nfa *, struct colormap *, int, pcolor,
^ struct state *, struct state *);
*/
-static VOID
-rainbow(nfa, cm, type, but, from, to)
-struct nfa *nfa;
-struct colormap *cm;
-int type;
-pcolor but; /* COLORLESS if no exceptions */
-struct state *from;
-struct state *to;
+static void
+rainbow(
+ struct nfa *nfa,
+ struct colormap *cm,
+ int type,
+ pcolor but, /* COLORLESS if no exceptions */
+ struct state *from,
+ struct state *to)
{
- struct colordesc *cd;
- struct colordesc *end = CDEND(cm);
- color co;
-
- for (cd = cm->cd, co = 0; cd < end && !CISERR(); cd++, co++)
- if (!UNUSEDCOLOR(cd) && cd->sub != co && co != but &&
- !(cd->flags&PSEUDO))
- newarc(nfa, type, co, from, to);
+ struct colordesc *cd;
+ struct colordesc *end = CDEND(cm);
+ color co;
+
+ for (cd=cm->cd, co=0 ; cd<end && !CISERR(); cd++, co++) {
+ if (!UNUSEDCOLOR(cd) && (cd->sub != co) && (co != but)
+ && !(cd->flags&PSEUDO)) {
+ newarc(nfa, type, co, from, to);
+ }
+ }
}
-
+
/*
- colorcomplement - add arcs of complementary colors
* The calling sequence ought to be reconciled with cloneouts().
^ static VOID colorcomplement(struct nfa *, struct colormap *, int,
^ struct state *, struct state *, struct state *);
*/
-static VOID
-colorcomplement(nfa, cm, type, of, from, to)
-struct nfa *nfa;
-struct colormap *cm;
-int type;
-struct state *of; /* complements of this guy's PLAIN outarcs */
-struct state *from;
-struct state *to;
+static void
+colorcomplement(
+ struct nfa *nfa,
+ struct colormap *cm,
+ int type,
+ struct state *of, /* complements of this guy's PLAIN outarcs */
+ struct state *from,
+ struct state *to)
{
- struct colordesc *cd;
- struct colordesc *end = CDEND(cm);
- color co;
-
- assert(of != from);
- for (cd = cm->cd, co = 0; cd < end && !CISERR(); cd++, co++)
- if (!UNUSEDCOLOR(cd) && !(cd->flags&PSEUDO))
- if (findarc(of, PLAIN, co) == NULL)
- newarc(nfa, type, co, from, to);
+ struct colordesc *cd;
+ struct colordesc *end = CDEND(cm);
+ color co;
+
+ assert(of != from);
+ for (cd=cm->cd, co=0 ; cd<end && !CISERR() ; cd++, co++) {
+ if (!UNUSEDCOLOR(cd) && !(cd->flags&PSEUDO)) {
+ if (findarc(of, PLAIN, co) == NULL) {
+ newarc(nfa, type, co, from, to);
+ }
+ }
+ }
}
-
-
-
+
#ifdef REG_DEBUG
/*
^ #ifdef REG_DEBUG
@@ -693,87 +743,106 @@ struct state *to;
- dumpcolors - debugging output
^ static VOID dumpcolors(struct colormap *, FILE *);
*/
-static VOID
-dumpcolors(cm, f)
-struct colormap *cm;
-FILE *f;
+static void
+dumpcolors(
+ struct colormap *cm,
+ FILE *f)
{
- struct colordesc *cd;
- struct colordesc *end;
- color co;
- chr c;
- char *has;
-
- fprintf(f, "max %ld\n", (long)cm->max);
- if (NBYTS > 1)
- fillcheck(cm, cm->tree, 0, f);
- end = CDEND(cm);
- for (cd = cm->cd + 1, co = 1; cd < end; cd++, co++) /* skip 0 */
- if (!UNUSEDCOLOR(cd)) {
- assert(cd->nchrs > 0);
- has = (cd->block != NULL) ? "#" : "";
- if (cd->flags&PSEUDO)
- fprintf(f, "#%2ld%s(ps): ", (long)co, has);
- else
- fprintf(f, "#%2ld%s(%2d): ", (long)co,
- has, cd->nchrs);
- /* it's hard to do this more efficiently */
- for (c = CHR_MIN; c < CHR_MAX; c++)
- if (GETCOLOR(cm, c) == co)
- dumpchr(c, f);
- assert(c == CHR_MAX);
- if (GETCOLOR(cm, c) == co)
- dumpchr(c, f);
- fprintf(f, "\n");
+ struct colordesc *cd;
+ struct colordesc *end;
+ color co;
+ chr c;
+ char *has;
+
+ fprintf(f, "max %ld\n", (long) cm->max);
+ if (NBYTS > 1) {
+ fillcheck(cm, cm->tree, 0, f);
+ }
+ end = CDEND(cm);
+ for (cd=cm->cd+1, co=1 ; cd<end ; cd++, co++) { /* skip 0 */
+ if (!UNUSEDCOLOR(cd)) {
+ assert(cd->nchrs > 0);
+ has = (cd->block != NULL) ? "#" : "";
+ if (cd->flags&PSEUDO) {
+ fprintf(f, "#%2ld%s(ps): ", (long) co, has);
+ } else {
+ fprintf(f, "#%2ld%s(%2d): ", (long) co, has, cd->nchrs);
+ }
+
+ /*
+ * It's hard to do this more efficiently.
+ */
+
+ for (c=CHR_MIN ; c<CHR_MAX ; c++) {
+ if (GETCOLOR(cm, c) == co) {
+ dumpchr(c, f);
}
+ }
+ assert(c == CHR_MAX);
+ if (GETCOLOR(cm, c) == co) {
+ dumpchr(c, f);
+ }
+ fprintf(f, "\n");
+ }
+ }
}
-
+
/*
- fillcheck - check proper filling of a tree
^ static VOID fillcheck(struct colormap *, union tree *, int, FILE *);
*/
-static VOID
-fillcheck(cm, tree, level, f)
-struct colormap *cm;
-union tree *tree;
-int level; /* level number (top == 0) of this block */
-FILE *f;
+static void
+fillcheck(
+ struct colormap *cm,
+ union tree *tree,
+ int level, /* level number (top == 0) of this block */
+ FILE *f)
{
- int i;
- union tree *t;
- union tree *fillt = &cm->tree[level+1];
-
- assert(level < NBYTS-1); /* this level has pointers */
- for (i = BYTTAB-1; i >= 0; i--) {
- t = tree->tptr[i];
- if (t == NULL)
- fprintf(f, "NULL found in filled tree!\n");
- else if (t == fillt)
- {}
- else if (level < NBYTS-2) /* more pointer blocks below */
- fillcheck(cm, t, level+1, f);
+ int i;
+ union tree *t;
+ union tree *fillt = &cm->tree[level+1];
+
+ assert(level < NBYTS-1); /* this level has pointers */
+ for (i=BYTTAB-1 ; i>=0 ; i--) {
+ t = tree->tptr[i];
+ if (t == NULL) {
+ fprintf(f, "NULL found in filled tree!\n");
+ } else if (t == fillt) {
+ /* empty body */
+ } else if (level < NBYTS-2) { /* more pointer blocks below */
+ fillcheck(cm, t, level+1, f);
}
+ }
}
-
+
/*
- dumpchr - print a chr
* Kind of char-centric but works well enough for debug use.
^ static VOID dumpchr(pchr, FILE *);
*/
-static VOID
-dumpchr(c, f)
-pchr c;
-FILE *f;
+static void
+dumpchr(
+ pchr c,
+ FILE *f)
{
- if (c == '\\')
- fprintf(f, "\\\\");
- else if (c > ' ' && c <= '~')
- putc((char)c, f);
- else
- fprintf(f, "\\u%04lx", (long)c);
+ if (c == '\\') {
+ fprintf(f, "\\\\");
+ } else if (c > ' ' && c <= '~') {
+ putc((char) c, f);
+ } else {
+ fprintf(f, "\\u%04lx", (long) c);
+ }
}
/*
^ #endif
*/
#endif /* ifdef REG_DEBUG */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/regc_cvec.c b/generic/regc_cvec.c
index d2d56fc..64f34cd 100644
--- a/generic/regc_cvec.c
+++ b/generic/regc_cvec.c
@@ -3,20 +3,20 @@
* This file is #included by regcomp.c.
*
* Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
- *
+ *
* Development of this software was funded, in part, by Cray Research Inc.,
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
- * Corporation, none of whom are responsible for the results. The author
- * thanks all of them.
- *
+ * Corporation, none of whom are responsible for the results. The author
+ * thanks all of them.
+ *
* Redistribution and use in source and binary forms -- with or without
* modification -- are permitted for any purpose, provided that
* redistributions in source form retain this entire copyright notice and
* indicate the origin and nature of any modifications.
- *
- * I'd appreciate being given credit for this package in the documentation
- * of software which uses it, but that is not a requirement.
- *
+ *
+ * I'd appreciate being given credit for this package in the documentation of
+ * software which uses it, but that is not a requirement.
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -27,182 +27,120 @@
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
/*
+ * Notes:
+ * Only (selected) functions in _this_ file should treat chr* as non-constant.
+ */
+
+/*
- newcvec - allocate a new cvec
- ^ static struct cvec *newcvec(int, int, int);
+ ^ static struct cvec *newcvec(int, int);
*/
static struct cvec *
-newcvec(nchrs, nranges, nmcces)
- int nchrs; /* to hold this many chrs... */
- int nranges; /* ... and this many ranges... */
- int nmcces; /* ... and this many MCCEs */
+newcvec(
+ int nchrs, /* to hold this many chrs... */
+ int nranges) /* ... and this many ranges... */
{
- size_t n;
- size_t nc;
- struct cvec *cv;
+ size_t nc = (size_t)nchrs + (size_t)nranges*2;
+ size_t n = sizeof(struct cvec) + nc*sizeof(chr);
+ struct cvec *cv = (struct cvec *) MALLOC(n);
- nc = (size_t)nchrs + (size_t)nmcces*(MAXMCCE+1) + (size_t)nranges*2;
- n = sizeof(struct cvec) + (size_t)(nmcces-1)*sizeof(chr *)
- + nc*sizeof(chr);
- cv = (struct cvec *)MALLOC(n);
if (cv == NULL) {
return NULL;
}
cv->chrspace = nchrs;
- cv->chrs = (chr *)&cv->mcces[nmcces]; /* chrs just after MCCE ptrs */
- cv->mccespace = nmcces;
- cv->ranges = cv->chrs + nchrs + nmcces*(MAXMCCE+1);
+ cv->chrs = (chr *)(((char *)cv)+sizeof(struct cvec));
+ cv->ranges = cv->chrs + nchrs;
cv->rangespace = nranges;
return clearcvec(cv);
}
-
+
/*
- clearcvec - clear a possibly-new cvec
* Returns pointer as convenience.
^ static struct cvec *clearcvec(struct cvec *);
*/
static struct cvec *
-clearcvec(cv)
- struct cvec *cv; /* character vector */
+clearcvec(
+ struct cvec *cv) /* character vector */
{
- int i;
-
assert(cv != NULL);
cv->nchrs = 0;
- assert(cv->chrs == (chr *)&cv->mcces[cv->mccespace]);
- cv->nmcces = 0;
- cv->nmccechrs = 0;
cv->nranges = 0;
- for (i = 0; i < cv->mccespace; i++) {
- cv->mcces[i] = NULL;
- }
-
return cv;
}
-
+
/*
- addchr - add a chr to a cvec
^ static VOID addchr(struct cvec *, pchr);
*/
-static VOID
-addchr(cv, c)
- struct cvec *cv; /* character vector */
- pchr c; /* character to add */
+static void
+addchr(
+ struct cvec *cv, /* character vector */
+ pchr c) /* character to add */
{
- assert(cv->nchrs < cv->chrspace - cv->nmccechrs);
cv->chrs[cv->nchrs++] = (chr)c;
}
-
+
/*
- addrange - add a range to a cvec
^ static VOID addrange(struct cvec *, pchr, pchr);
*/
-static VOID
-addrange(cv, from, to)
- struct cvec *cv; /* character vector */
- pchr from; /* first character of range */
- pchr to; /* last character of range */
+static void
+addrange(
+ struct cvec *cv, /* character vector */
+ pchr from, /* first character of range */
+ pchr to) /* last character of range */
{
assert(cv->nranges < cv->rangespace);
cv->ranges[cv->nranges*2] = (chr)from;
cv->ranges[cv->nranges*2 + 1] = (chr)to;
cv->nranges++;
}
-
-/*
- - addmcce - add an MCCE to a cvec
- ^ static VOID addmcce(struct cvec *, chr *, chr *);
- */
-static VOID
-addmcce(cv, startp, endp)
- struct cvec *cv; /* character vector */
- chr *startp; /* beginning of text */
- chr *endp; /* just past end of text */
-{
- int len;
- int i;
- chr *s;
- chr *d;
-
- if (startp == NULL && endp == NULL) {
- return;
- }
- len = endp - startp;
- assert(len > 0);
- assert(cv->nchrs + len < cv->chrspace - cv->nmccechrs);
- assert(cv->nmcces < cv->mccespace);
- d = &cv->chrs[cv->chrspace - cv->nmccechrs - len - 1];
- cv->mcces[cv->nmcces++] = d;
- for (s = startp, i = len; i > 0; s++, i--) {
- *d++ = *s;
- }
- *d++ = 0; /* endmarker */
- assert(d == &cv->chrs[cv->chrspace - cv->nmccechrs]);
- cv->nmccechrs += len + 1;
-}
-
-/*
- - haschr - does a cvec contain this chr?
- ^ static int haschr(struct cvec *, pchr);
- */
-static int /* predicate */
-haschr(cv, c)
- struct cvec *cv; /* character vector */
- pchr c; /* character to test for */
-{
- int i;
- chr *p;
-
- for (p = cv->chrs, i = cv->nchrs; i > 0; p++, i--) {
- if (*p == c) {
- return 1;
- }
- }
- for (p = cv->ranges, i = cv->nranges; i > 0; p += 2, i--) {
- if ((*p <= c) && (c <= *(p+1))) {
- return 1;
- }
- }
- return 0;
-}
-
+
/*
- getcvec - get a cvec, remembering it as v->cv
- ^ static struct cvec *getcvec(struct vars *, int, int, int);
+ ^ static struct cvec *getcvec(struct vars *, int, int);
*/
static struct cvec *
-getcvec(v, nchrs, nranges, nmcces)
- struct vars *v; /* context */
- int nchrs; /* to hold this many chrs... */
- int nranges; /* ... and this many ranges... */
- int nmcces; /* ... and this many MCCEs */
+getcvec(
+ struct vars *v, /* context */
+ int nchrs, /* to hold this many chrs... */
+ int nranges) /* ... and this many ranges... */
{
- if (v->cv != NULL && nchrs <= v->cv->chrspace &&
- nranges <= v->cv->rangespace && nmcces <= v->cv->mccespace) {
+ if ((v->cv != NULL) && (nchrs <= v->cv->chrspace) &&
+ (nranges <= v->cv->rangespace)) {
return clearcvec(v->cv);
}
if (v->cv != NULL) {
freecvec(v->cv);
}
- v->cv = newcvec(nchrs, nranges, nmcces);
+ v->cv = newcvec(nchrs, nranges);
if (v->cv == NULL) {
ERR(REG_ESPACE);
}
return v->cv;
}
-
+
/*
- freecvec - free a cvec
^ static VOID freecvec(struct cvec *);
*/
-static VOID
-freecvec(cv)
- struct cvec *cv; /* character vector */
+static void
+freecvec(
+ struct cvec *cv) /* character vector */
{
FREE(cv);
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/regc_lex.c b/generic/regc_lex.c
index 588718d..bc61e14 100644
--- a/generic/regc_lex.c
+++ b/generic/regc_lex.c
@@ -3,20 +3,20 @@
* This file is #included by regcomp.c.
*
* Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
- *
+ *
* Development of this software was funded, in part, by Cray Research Inc.,
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
* Corporation, none of whom are responsible for the results. The author
- * thanks all of them.
- *
+ * thanks all of them.
+ *
* Redistribution and use in source and binary forms -- with or without
* modification -- are permitted for any purpose, provided that
* redistributions in source form retain this entire copyright notice and
* indicate the origin and nature of any modifications.
- *
- * I'd appreciate being given credit for this package in the documentation
- * of software which uses it, but that is not a requirement.
- *
+ *
+ * I'd appreciate being given credit for this package in the documentation of
+ * software which uses it, but that is not a requirement.
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -27,7 +27,6 @@
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
/* scanning macros (know about v) */
@@ -35,9 +34,10 @@
#define HAVE(n) (v->stop - v->now >= (n))
#define NEXT1(c) (!ATEOS() && *v->now == CHR(c))
#define NEXT2(a,b) (HAVE(2) && *v->now == CHR(a) && *(v->now+1) == CHR(b))
-#define NEXT3(a,b,c) (HAVE(3) && *v->now == CHR(a) && \
- *(v->now+1) == CHR(b) && \
- *(v->now+2) == CHR(c))
+#define NEXT3(a,b,c) \
+ (HAVE(3) && *v->now == CHR(a) && \
+ *(v->now+1) == CHR(b) && \
+ *(v->now+2) == CHR(c))
#define SET(c) (v->nexttype = (c))
#define SETV(c, n) (v->nexttype = (c), v->nextvalue = (n))
#define RET(c) return (SET(c), 1)
@@ -60,804 +60,907 @@
/* construct pointer past end of chr array */
#define ENDOF(array) ((array) + sizeof(array)/sizeof(chr))
-
+
/*
- lexstart - set up lexical stuff, scan leading options
^ static VOID lexstart(struct vars *);
*/
-static VOID
-lexstart(v)
-struct vars *v;
+static void
+lexstart(
+ struct vars *v)
{
- prefixes(v); /* may turn on new type bits etc. */
- NOERR();
+ prefixes(v); /* may turn on new type bits etc. */
+ NOERR();
- if (v->cflags&REG_QUOTE) {
- assert(!(v->cflags&(REG_ADVANCED|REG_EXPANDED|REG_NEWLINE)));
- INTOCON(L_Q);
- } else if (v->cflags&REG_EXTENDED) {
- assert(!(v->cflags&REG_QUOTE));
- INTOCON(L_ERE);
- } else {
- assert(!(v->cflags&(REG_QUOTE|REG_ADVF)));
- INTOCON(L_BRE);
- }
+ if (v->cflags&REG_QUOTE) {
+ assert(!(v->cflags&(REG_ADVANCED|REG_EXPANDED|REG_NEWLINE)));
+ INTOCON(L_Q);
+ } else if (v->cflags&REG_EXTENDED) {
+ assert(!(v->cflags&REG_QUOTE));
+ INTOCON(L_ERE);
+ } else {
+ assert(!(v->cflags&(REG_QUOTE|REG_ADVF)));
+ INTOCON(L_BRE);
+ }
- v->nexttype = EMPTY; /* remember we were at the start */
- next(v); /* set up the first token */
+ v->nexttype = EMPTY; /* remember we were at the start */
+ next(v); /* set up the first token */
}
-
+
/*
- prefixes - implement various special prefixes
^ static VOID prefixes(struct vars *);
*/
-static VOID
-prefixes(v)
-struct vars *v;
+static void
+prefixes(
+ struct vars *v)
{
- /* literal string doesn't get any of this stuff */
- if (v->cflags&REG_QUOTE)
- return;
+ /*
+ * Literal string doesn't get any of this stuff.
+ */
- /* initial "***" gets special things */
- if (HAVE(4) && NEXT3('*', '*', '*'))
- switch (*(v->now + 3)) {
- case CHR('?'): /* "***?" error, msg shows version */
- ERR(REG_BADPAT);
- return; /* proceed no further */
- break;
- case CHR('='): /* "***=" shifts to literal string */
- NOTE(REG_UNONPOSIX);
- v->cflags |= REG_QUOTE;
- v->cflags &= ~(REG_ADVANCED|REG_EXPANDED|REG_NEWLINE);
- v->now += 4;
- return; /* and there can be no more prefixes */
- break;
- case CHR(':'): /* "***:" shifts to AREs */
- NOTE(REG_UNONPOSIX);
- v->cflags |= REG_ADVANCED;
- v->now += 4;
- break;
- default: /* otherwise *** is just an error */
- ERR(REG_BADRPT);
- return;
- break;
- }
+ if (v->cflags&REG_QUOTE) {
+ return;
+ }
- /* BREs and EREs don't get embedded options */
- if ((v->cflags&REG_ADVANCED) != REG_ADVANCED)
- return;
+ /*
+ * Initial "***" gets special things.
+ */
- /* embedded options (AREs only) */
- if (HAVE(3) && NEXT2('(', '?') && iscalpha(*(v->now + 2))) {
- NOTE(REG_UNONPOSIX);
- v->now += 2;
- for (; !ATEOS() && iscalpha(*v->now); v->now++)
- switch (*v->now) {
- case CHR('b'): /* BREs (but why???) */
- v->cflags &= ~(REG_ADVANCED|REG_QUOTE);
- break;
- case CHR('c'): /* case sensitive */
- v->cflags &= ~REG_ICASE;
- break;
- case CHR('e'): /* plain EREs */
- v->cflags |= REG_EXTENDED;
- v->cflags &= ~(REG_ADVF|REG_QUOTE);
- break;
- case CHR('i'): /* case insensitive */
- v->cflags |= REG_ICASE;
- break;
- case CHR('m'): /* Perloid synonym for n */
- case CHR('n'): /* \n affects ^ $ . [^ */
- v->cflags |= REG_NEWLINE;
- break;
- case CHR('p'): /* ~Perl, \n affects . [^ */
- v->cflags |= REG_NLSTOP;
- v->cflags &= ~REG_NLANCH;
- break;
- case CHR('q'): /* literal string */
- v->cflags |= REG_QUOTE;
- v->cflags &= ~REG_ADVANCED;
- break;
- case CHR('s'): /* single line, \n ordinary */
- v->cflags &= ~REG_NEWLINE;
- break;
- case CHR('t'): /* tight syntax */
- v->cflags &= ~REG_EXPANDED;
- break;
- case CHR('w'): /* weird, \n affects ^ $ only */
- v->cflags &= ~REG_NLSTOP;
- v->cflags |= REG_NLANCH;
- break;
- case CHR('x'): /* expanded syntax */
- v->cflags |= REG_EXPANDED;
- break;
- default:
- ERR(REG_BADOPT);
- return;
- }
- if (!NEXT1(')')) {
- ERR(REG_BADOPT);
- return;
- }
- v->now++;
- if (v->cflags&REG_QUOTE)
- v->cflags &= ~(REG_EXPANDED|REG_NEWLINE);
+ if (HAVE(4) && NEXT3('*', '*', '*')) {
+ switch (*(v->now + 3)) {
+ case CHR('?'): /* "***?" error, msg shows version */
+ ERR(REG_BADPAT);
+ return; /* proceed no further */
+ break;
+ case CHR('='): /* "***=" shifts to literal string */
+ NOTE(REG_UNONPOSIX);
+ v->cflags |= REG_QUOTE;
+ v->cflags &= ~(REG_ADVANCED|REG_EXPANDED|REG_NEWLINE);
+ v->now += 4;
+ return; /* and there can be no more prefixes */
+ break;
+ case CHR(':'): /* "***:" shifts to AREs */
+ NOTE(REG_UNONPOSIX);
+ v->cflags |= REG_ADVANCED;
+ v->now += 4;
+ break;
+ default: /* otherwise *** is just an error */
+ ERR(REG_BADRPT);
+ return;
+ break;
}
-}
+ }
+ /*
+ * BREs and EREs don't get embedded options.
+ */
+
+ if ((v->cflags&REG_ADVANCED) != REG_ADVANCED) {
+ return;
+ }
+
+ /*
+ * Embedded options (AREs only).
+ */
+
+ if (HAVE(3) && NEXT2('(', '?') && iscalpha(*(v->now + 2))) {
+ NOTE(REG_UNONPOSIX);
+ v->now += 2;
+ for (; !ATEOS() && iscalpha(*v->now); v->now++) {
+ switch (*v->now) {
+ case CHR('b'): /* BREs (but why???) */
+ v->cflags &= ~(REG_ADVANCED|REG_QUOTE);
+ break;
+ case CHR('c'): /* case sensitive */
+ v->cflags &= ~REG_ICASE;
+ break;
+ case CHR('e'): /* plain EREs */
+ v->cflags |= REG_EXTENDED;
+ v->cflags &= ~(REG_ADVF|REG_QUOTE);
+ break;
+ case CHR('i'): /* case insensitive */
+ v->cflags |= REG_ICASE;
+ break;
+ case CHR('m'): /* Perloid synonym for n */
+ case CHR('n'): /* \n affects ^ $ . [^ */
+ v->cflags |= REG_NEWLINE;
+ break;
+ case CHR('p'): /* ~Perl, \n affects . [^ */
+ v->cflags |= REG_NLSTOP;
+ v->cflags &= ~REG_NLANCH;
+ break;
+ case CHR('q'): /* literal string */
+ v->cflags |= REG_QUOTE;
+ v->cflags &= ~REG_ADVANCED;
+ break;
+ case CHR('s'): /* single line, \n ordinary */
+ v->cflags &= ~REG_NEWLINE;
+ break;
+ case CHR('t'): /* tight syntax */
+ v->cflags &= ~REG_EXPANDED;
+ break;
+ case CHR('w'): /* weird, \n affects ^ $ only */
+ v->cflags &= ~REG_NLSTOP;
+ v->cflags |= REG_NLANCH;
+ break;
+ case CHR('x'): /* expanded syntax */
+ v->cflags |= REG_EXPANDED;
+ break;
+ default:
+ ERR(REG_BADOPT);
+ return;
+ }
+ }
+ if (!NEXT1(')')) {
+ ERR(REG_BADOPT);
+ return;
+ }
+ v->now++;
+ if (v->cflags&REG_QUOTE) {
+ v->cflags &= ~(REG_EXPANDED|REG_NEWLINE);
+ }
+ }
+}
+
/*
- lexnest - "call a subroutine", interpolating string at the lexical level
* Note, this is not a very general facility. There are a number of
* implicit assumptions about what sorts of strings can be subroutines.
- ^ static VOID lexnest(struct vars *, chr *, chr *);
+ ^ static VOID lexnest(struct vars *, const chr *, const chr *);
*/
-static VOID
-lexnest(v, beginp, endp)
-struct vars *v;
-chr *beginp; /* start of interpolation */
-chr *endp; /* one past end of interpolation */
+static void
+lexnest(
+ struct vars *v,
+ const chr *beginp, /* start of interpolation */
+ const chr *endp) /* one past end of interpolation */
{
- assert(v->savenow == NULL); /* only one level of nesting */
- v->savenow = v->now;
- v->savestop = v->stop;
- v->now = beginp;
- v->stop = endp;
+ assert(v->savenow == NULL); /* only one level of nesting */
+ v->savenow = v->now;
+ v->savestop = v->stop;
+ v->now = beginp;
+ v->stop = endp;
}
-
+
/*
* string constants to interpolate as expansions of things like \d
*/
-static chr backd[] = { /* \d */
- CHR('['), CHR('['), CHR(':'),
- CHR('d'), CHR('i'), CHR('g'), CHR('i'), CHR('t'),
- CHR(':'), CHR(']'), CHR(']')
+
+static const chr backd[] = { /* \d */
+ CHR('['), CHR('['), CHR(':'),
+ CHR('d'), CHR('i'), CHR('g'), CHR('i'), CHR('t'),
+ CHR(':'), CHR(']'), CHR(']')
};
-static chr backD[] = { /* \D */
- CHR('['), CHR('^'), CHR('['), CHR(':'),
- CHR('d'), CHR('i'), CHR('g'), CHR('i'), CHR('t'),
- CHR(':'), CHR(']'), CHR(']')
+static const chr backD[] = { /* \D */
+ CHR('['), CHR('^'), CHR('['), CHR(':'),
+ CHR('d'), CHR('i'), CHR('g'), CHR('i'), CHR('t'),
+ CHR(':'), CHR(']'), CHR(']')
};
-static chr brbackd[] = { /* \d within brackets */
- CHR('['), CHR(':'),
- CHR('d'), CHR('i'), CHR('g'), CHR('i'), CHR('t'),
- CHR(':'), CHR(']')
+static const chr brbackd[] = { /* \d within brackets */
+ CHR('['), CHR(':'),
+ CHR('d'), CHR('i'), CHR('g'), CHR('i'), CHR('t'),
+ CHR(':'), CHR(']')
};
-static chr backs[] = { /* \s */
- CHR('['), CHR('['), CHR(':'),
- CHR('s'), CHR('p'), CHR('a'), CHR('c'), CHR('e'),
- CHR(':'), CHR(']'), CHR(']')
+static const chr backs[] = { /* \s */
+ CHR('['), CHR('['), CHR(':'),
+ CHR('s'), CHR('p'), CHR('a'), CHR('c'), CHR('e'),
+ CHR(':'), CHR(']'), CHR(']')
};
-static chr backS[] = { /* \S */
- CHR('['), CHR('^'), CHR('['), CHR(':'),
- CHR('s'), CHR('p'), CHR('a'), CHR('c'), CHR('e'),
- CHR(':'), CHR(']'), CHR(']')
+static const chr backS[] = { /* \S */
+ CHR('['), CHR('^'), CHR('['), CHR(':'),
+ CHR('s'), CHR('p'), CHR('a'), CHR('c'), CHR('e'),
+ CHR(':'), CHR(']'), CHR(']')
};
-static chr brbacks[] = { /* \s within brackets */
- CHR('['), CHR(':'),
- CHR('s'), CHR('p'), CHR('a'), CHR('c'), CHR('e'),
- CHR(':'), CHR(']')
+static const chr brbacks[] = { /* \s within brackets */
+ CHR('['), CHR(':'),
+ CHR('s'), CHR('p'), CHR('a'), CHR('c'), CHR('e'),
+ CHR(':'), CHR(']')
};
-static chr backw[] = { /* \w */
- CHR('['), CHR('['), CHR(':'),
- CHR('a'), CHR('l'), CHR('n'), CHR('u'), CHR('m'),
- CHR(':'), CHR(']'), CHR('_'), CHR(']')
+static const chr backw[] = { /* \w */
+ CHR('['), CHR('['), CHR(':'),
+ CHR('a'), CHR('l'), CHR('n'), CHR('u'), CHR('m'),
+ CHR(':'), CHR(']'), CHR('_'), CHR(']')
};
-static chr backW[] = { /* \W */
- CHR('['), CHR('^'), CHR('['), CHR(':'),
- CHR('a'), CHR('l'), CHR('n'), CHR('u'), CHR('m'),
- CHR(':'), CHR(']'), CHR('_'), CHR(']')
+static const chr backW[] = { /* \W */
+ CHR('['), CHR('^'), CHR('['), CHR(':'),
+ CHR('a'), CHR('l'), CHR('n'), CHR('u'), CHR('m'),
+ CHR(':'), CHR(']'), CHR('_'), CHR(']')
};
-static chr brbackw[] = { /* \w within brackets */
- CHR('['), CHR(':'),
- CHR('a'), CHR('l'), CHR('n'), CHR('u'), CHR('m'),
- CHR(':'), CHR(']'), CHR('_')
+static const chr brbackw[] = { /* \w within brackets */
+ CHR('['), CHR(':'),
+ CHR('a'), CHR('l'), CHR('n'), CHR('u'), CHR('m'),
+ CHR(':'), CHR(']'), CHR('_')
};
-
+
/*
- lexword - interpolate a bracket expression for word characters
* Possibly ought to inquire whether there is a "word" character class.
^ static VOID lexword(struct vars *);
*/
-static VOID
-lexword(v)
-struct vars *v;
+static void
+lexword(
+ struct vars *v)
{
- lexnest(v, backw, ENDOF(backw));
+ lexnest(v, backw, ENDOF(backw));
}
-
+
/*
- next - get next token
^ static int next(struct vars *);
*/
static int /* 1 normal, 0 failure */
-next(v)
-struct vars *v;
+next(
+ struct vars *v)
{
- chr c;
+ chr c;
- /* errors yield an infinite sequence of failures */
- if (ISERR())
- return 0; /* the error has set nexttype to EOS */
+ /*
+ * Errors yield an infinite sequence of failures.
+ */
- /* remember flavor of last token */
- v->lasttype = v->nexttype;
+ if (ISERR()) {
+ return 0; /* the error has set nexttype to EOS */
+ }
- /* REG_BOSONLY */
- if (v->nexttype == EMPTY && (v->cflags&REG_BOSONLY)) {
- /* at start of a REG_BOSONLY RE */
- RETV(SBEGIN, 0); /* same as \A */
- }
+ /*
+ * Remember flavor of last token.
+ */
- /* if we're nested and we've hit end, return to outer level */
- if (v->savenow != NULL && ATEOS()) {
- v->now = v->savenow;
- v->stop = v->savestop;
- v->savenow = v->savestop = NULL;
- }
+ v->lasttype = v->nexttype;
- /* skip white space etc. if appropriate (not in literal or []) */
- if (v->cflags&REG_EXPANDED)
- switch (v->lexcon) {
- case L_ERE:
- case L_BRE:
- case L_EBND:
- case L_BBND:
- skip(v);
- break;
- }
+ /*
+ * REG_BOSONLY
+ */
- /* handle EOS, depending on context */
- if (ATEOS()) {
- switch (v->lexcon) {
- case L_ERE:
- case L_BRE:
- case L_Q:
- RET(EOS);
- break;
- case L_EBND:
- case L_BBND:
- FAILW(REG_EBRACE);
- break;
- case L_BRACK:
- case L_CEL:
- case L_ECL:
- case L_CCL:
- FAILW(REG_EBRACK);
- break;
- }
- assert(NOTREACHED);
+ if (v->nexttype == EMPTY && (v->cflags&REG_BOSONLY)) {
+ /* at start of a REG_BOSONLY RE */
+ RETV(SBEGIN, 0); /* same as \A */
+ }
+
+ /*
+ * If we're nested and we've hit end, return to outer level.
+ */
+
+ if (v->savenow != NULL && ATEOS()) {
+ v->now = v->savenow;
+ v->stop = v->savestop;
+ v->savenow = v->savestop = NULL;
+ }
+
+ /*
+ * Skip white space etc. if appropriate (not in literal or [])
+ */
+
+ if (v->cflags&REG_EXPANDED) {
+ switch (v->lexcon) {
+ case L_ERE:
+ case L_BRE:
+ case L_EBND:
+ case L_BBND:
+ skip(v);
+ break;
}
+ }
- /* okay, time to actually get a character */
- c = *v->now++;
+ /*
+ * Handle EOS, depending on context.
+ */
- /* deal with the easy contexts, punt EREs to code below */
+ if (ATEOS()) {
switch (v->lexcon) {
- case L_BRE: /* punt BREs to separate function */
- return brenext(v, c);
- break;
- case L_ERE: /* see below */
- break;
- case L_Q: /* literal strings are easy */
- RETV(PLAIN, c);
- break;
- case L_BBND: /* bounds are fairly simple */
+ case L_ERE:
+ case L_BRE:
+ case L_Q:
+ RET(EOS);
+ break;
case L_EBND:
- switch (c) {
- case CHR('0'): case CHR('1'): case CHR('2'): case CHR('3'):
- case CHR('4'): case CHR('5'): case CHR('6'): case CHR('7'):
- case CHR('8'): case CHR('9'):
- RETV(DIGIT, (chr)DIGITVAL(c));
- break;
- case CHR(','):
- RET(',');
- break;
- case CHR('}'): /* ERE bound ends with } */
- if (INCON(L_EBND)) {
- INTOCON(L_ERE);
- if ((v->cflags&REG_ADVF) && NEXT1('?')) {
- v->now++;
- NOTE(REG_UNONPOSIX);
- RETV('}', 0);
- }
- RETV('}', 1);
- } else
- FAILW(REG_BADBR);
- break;
- case CHR('\\'): /* BRE bound ends with \} */
- if (INCON(L_BBND) && NEXT1('}')) {
- v->now++;
- INTOCON(L_BRE);
- RET('}');
- } else
- FAILW(REG_BADBR);
- break;
- default:
- FAILW(REG_BADBR);
- break;
- }
- assert(NOTREACHED);
- break;
- case L_BRACK: /* brackets are not too hard */
- switch (c) {
- case CHR(']'):
- if (LASTTYPE('['))
- RETV(PLAIN, c);
- else {
- INTOCON((v->cflags&REG_EXTENDED) ?
- L_ERE : L_BRE);
- RET(']');
- }
- break;
- case CHR('\\'):
- NOTE(REG_UBBS);
- if (!(v->cflags&REG_ADVF))
- RETV(PLAIN, c);
- NOTE(REG_UNONPOSIX);
- if (ATEOS())
- FAILW(REG_EESCAPE);
- (DISCARD)lexescape(v);
- switch (v->nexttype) { /* not all escapes okay here */
- case PLAIN:
- return 1;
- break;
- case CCLASS:
- switch (v->nextvalue) {
- case 'd':
- lexnest(v, brbackd, ENDOF(brbackd));
- break;
- case 's':
- lexnest(v, brbacks, ENDOF(brbacks));
- break;
- case 'w':
- lexnest(v, brbackw, ENDOF(brbackw));
- break;
- default:
- FAILW(REG_EESCAPE);
- break;
- }
- /* lexnest done, back up and try again */
- v->nexttype = v->lasttype;
- return next(v);
- break;
- }
- /* not one of the acceptable escapes */
- FAILW(REG_EESCAPE);
- break;
- case CHR('-'):
- if (LASTTYPE('[') || NEXT1(']'))
- RETV(PLAIN, c);
- else
- RETV(RANGE, c);
- break;
- case CHR('['):
- if (ATEOS())
- FAILW(REG_EBRACK);
- switch (*v->now++) {
- case CHR('.'):
- INTOCON(L_CEL);
- /* might or might not be locale-specific */
- RET(COLLEL);
- break;
- case CHR('='):
- INTOCON(L_ECL);
- NOTE(REG_ULOCALE);
- RET(ECLASS);
- break;
- case CHR(':'):
- INTOCON(L_CCL);
- NOTE(REG_ULOCALE);
- RET(CCLASS);
- break;
- default: /* oops */
- v->now--;
- RETV(PLAIN, c);
- break;
- }
- assert(NOTREACHED);
- break;
- default:
- RETV(PLAIN, c);
- break;
- }
- assert(NOTREACHED);
- break;
- case L_CEL: /* collating elements are easy */
- if (c == CHR('.') && NEXT1(']')) {
- v->now++;
- INTOCON(L_BRACK);
- RETV(END, '.');
- } else
- RETV(PLAIN, c);
- break;
- case L_ECL: /* ditto equivalence classes */
- if (c == CHR('=') && NEXT1(']')) {
- v->now++;
- INTOCON(L_BRACK);
- RETV(END, '=');
- } else
- RETV(PLAIN, c);
- break;
- case L_CCL: /* ditto character classes */
- if (c == CHR(':') && NEXT1(']')) {
- v->now++;
- INTOCON(L_BRACK);
- RETV(END, ':');
- } else
- RETV(PLAIN, c);
- break;
- default:
- assert(NOTREACHED);
- break;
+ case L_BBND:
+ FAILW(REG_EBRACE);
+ break;
+ case L_BRACK:
+ case L_CEL:
+ case L_ECL:
+ case L_CCL:
+ FAILW(REG_EBRACK);
+ break;
}
+ assert(NOTREACHED);
+ }
+
+ /*
+ * Okay, time to actually get a character.
+ */
+
+ c = *v->now++;
- /* that got rid of everything except EREs and AREs */
- assert(INCON(L_ERE));
+ /*
+ * Deal with the easy contexts, punt EREs to code below.
+ */
- /* deal with EREs and AREs, except for backslashes */
+ switch (v->lexcon) {
+ case L_BRE: /* punt BREs to separate function */
+ return brenext(v, c);
+ break;
+ case L_ERE: /* see below */
+ break;
+ case L_Q: /* literal strings are easy */
+ RETV(PLAIN, c);
+ break;
+ case L_BBND: /* bounds are fairly simple */
+ case L_EBND:
switch (c) {
- case CHR('|'):
- RET('|');
- break;
- case CHR('*'):
+ case CHR('0'): case CHR('1'): case CHR('2'): case CHR('3'):
+ case CHR('4'): case CHR('5'): case CHR('6'): case CHR('7'):
+ case CHR('8'): case CHR('9'):
+ RETV(DIGIT, (chr)DIGITVAL(c));
+ break;
+ case CHR(','):
+ RET(',');
+ break;
+ case CHR('}'): /* ERE bound ends with } */
+ if (INCON(L_EBND)) {
+ INTOCON(L_ERE);
if ((v->cflags&REG_ADVF) && NEXT1('?')) {
- v->now++;
- NOTE(REG_UNONPOSIX);
- RETV('*', 0);
+ v->now++;
+ NOTE(REG_UNONPOSIX);
+ RETV('}', 0);
}
- RETV('*', 1);
+ RETV('}', 1);
+ } else {
+ FAILW(REG_BADBR);
+ }
+ break;
+ case CHR('\\'): /* BRE bound ends with \} */
+ if (INCON(L_BBND) && NEXT1('}')) {
+ v->now++;
+ INTOCON(L_BRE);
+ RET('}');
+ } else {
+ FAILW(REG_BADBR);
+ }
+ break;
+ default:
+ FAILW(REG_BADBR);
+ break;
+ }
+ assert(NOTREACHED);
+ break;
+ case L_BRACK: /* brackets are not too hard */
+ switch (c) {
+ case CHR(']'):
+ if (LASTTYPE('[')) {
+ RETV(PLAIN, c);
+ } else {
+ INTOCON((v->cflags&REG_EXTENDED) ? L_ERE : L_BRE);
+ RET(']');
+ }
+ break;
+ case CHR('\\'):
+ NOTE(REG_UBBS);
+ if (!(v->cflags&REG_ADVF)) {
+ RETV(PLAIN, c);
+ }
+ NOTE(REG_UNONPOSIX);
+ if (ATEOS()) {
+ FAILW(REG_EESCAPE);
+ }
+ (DISCARD)lexescape(v);
+ switch (v->nexttype) { /* not all escapes okay here */
+ case PLAIN:
+ return 1;
break;
- case CHR('+'):
- if ((v->cflags&REG_ADVF) && NEXT1('?')) {
- v->now++;
- NOTE(REG_UNONPOSIX);
- RETV('+', 0);
+ case CCLASS:
+ switch (v->nextvalue) {
+ case 'd':
+ lexnest(v, brbackd, ENDOF(brbackd));
+ break;
+ case 's':
+ lexnest(v, brbacks, ENDOF(brbacks));
+ break;
+ case 'w':
+ lexnest(v, brbackw, ENDOF(brbackw));
+ break;
+ default:
+ FAILW(REG_EESCAPE);
+ break;
}
- RETV('+', 1);
+
+ /*
+ * lexnest() done, back up and try again.
+ */
+
+ v->nexttype = v->lasttype;
+ return next(v);
break;
- case CHR('?'):
- if ((v->cflags&REG_ADVF) && NEXT1('?')) {
- v->now++;
- NOTE(REG_UNONPOSIX);
- RETV('?', 0);
- }
- RETV('?', 1);
+ }
+
+ /*
+ * Not one of the acceptable escapes.
+ */
+
+ FAILW(REG_EESCAPE);
+ break;
+ case CHR('-'):
+ if (LASTTYPE('[') || NEXT1(']')) {
+ RETV(PLAIN, c);
+ } else {
+ RETV(RANGE, c);
+ }
+ break;
+ case CHR('['):
+ if (ATEOS()) {
+ FAILW(REG_EBRACK);
+ }
+ switch (*v->now++) {
+ case CHR('.'):
+ INTOCON(L_CEL);
+
+ /*
+ * Might or might not be locale-specific.
+ */
+
+ RET(COLLEL);
break;
- case CHR('{'): /* bounds start or plain character */
- if (v->cflags&REG_EXPANDED)
- skip(v);
- if (ATEOS() || !iscdigit(*v->now)) {
- NOTE(REG_UBRACES);
- NOTE(REG_UUNSPEC);
- RETV(PLAIN, c);
- } else {
- NOTE(REG_UBOUNDS);
- INTOCON(L_EBND);
- RET('{');
- }
- assert(NOTREACHED);
+ case CHR('='):
+ INTOCON(L_ECL);
+ NOTE(REG_ULOCALE);
+ RET(ECLASS);
break;
- case CHR('('): /* parenthesis, or advanced extension */
- if ((v->cflags&REG_ADVF) && NEXT1('?')) {
- NOTE(REG_UNONPOSIX);
- v->now++;
- switch (*v->now++) {
- case CHR(':'): /* non-capturing paren */
- RETV('(', 0);
- break;
- case CHR('#'): /* comment */
- while (!ATEOS() && *v->now != CHR(')'))
- v->now++;
- if (!ATEOS())
- v->now++;
- assert(v->nexttype == v->lasttype);
- return next(v);
- break;
- case CHR('='): /* positive lookahead */
- NOTE(REG_ULOOKAHEAD);
- RETV(LACON, 1);
- break;
- case CHR('!'): /* negative lookahead */
- NOTE(REG_ULOOKAHEAD);
- RETV(LACON, 0);
- break;
- default:
- FAILW(REG_BADRPT);
- break;
- }
- assert(NOTREACHED);
- }
- if (v->cflags&REG_NOSUB)
- RETV('(', 0); /* all parens non-capturing */
- else
- RETV('(', 1);
+ case CHR(':'):
+ INTOCON(L_CCL);
+ NOTE(REG_ULOCALE);
+ RET(CCLASS);
break;
- case CHR(')'):
- if (LASTTYPE('(')) {
- NOTE(REG_UUNSPEC);
- }
- RETV(')', c);
+ default: /* oops */
+ v->now--;
+ RETV(PLAIN, c);
break;
- case CHR('['): /* easy except for [[:<:]] and [[:>:]] */
- if (HAVE(6) && *(v->now+0) == CHR('[') &&
- *(v->now+1) == CHR(':') &&
- (*(v->now+2) == CHR('<') ||
- *(v->now+2) == CHR('>')) &&
- *(v->now+3) == CHR(':') &&
- *(v->now+4) == CHR(']') &&
- *(v->now+5) == CHR(']')) {
- c = *(v->now+2);
- v->now += 6;
- NOTE(REG_UNONPOSIX);
- RET((c == CHR('<')) ? '<' : '>');
+ }
+ assert(NOTREACHED);
+ break;
+ default:
+ RETV(PLAIN, c);
+ break;
+ }
+ assert(NOTREACHED);
+ break;
+ case L_CEL: /* collating elements are easy */
+ if (c == CHR('.') && NEXT1(']')) {
+ v->now++;
+ INTOCON(L_BRACK);
+ RETV(END, '.');
+ } else {
+ RETV(PLAIN, c);
+ }
+ break;
+ case L_ECL: /* ditto equivalence classes */
+ if (c == CHR('=') && NEXT1(']')) {
+ v->now++;
+ INTOCON(L_BRACK);
+ RETV(END, '=');
+ } else {
+ RETV(PLAIN, c);
+ }
+ break;
+ case L_CCL: /* ditto character classes */
+ if (c == CHR(':') && NEXT1(']')) {
+ v->now++;
+ INTOCON(L_BRACK);
+ RETV(END, ':');
+ } else {
+ RETV(PLAIN, c);
+ }
+ break;
+ default:
+ assert(NOTREACHED);
+ break;
+ }
+
+ /*
+ * That got rid of everything except EREs and AREs.
+ */
+
+ assert(INCON(L_ERE));
+
+ /*
+ * Deal with EREs and AREs, except for backslashes.
+ */
+
+ switch (c) {
+ case CHR('|'):
+ RET('|');
+ break;
+ case CHR('*'):
+ if ((v->cflags&REG_ADVF) && NEXT1('?')) {
+ v->now++;
+ NOTE(REG_UNONPOSIX);
+ RETV('*', 0);
+ }
+ RETV('*', 1);
+ break;
+ case CHR('+'):
+ if ((v->cflags&REG_ADVF) && NEXT1('?')) {
+ v->now++;
+ NOTE(REG_UNONPOSIX);
+ RETV('+', 0);
+ }
+ RETV('+', 1);
+ break;
+ case CHR('?'):
+ if ((v->cflags&REG_ADVF) && NEXT1('?')) {
+ v->now++;
+ NOTE(REG_UNONPOSIX);
+ RETV('?', 0);
+ }
+ RETV('?', 1);
+ break;
+ case CHR('{'): /* bounds start or plain character */
+ if (v->cflags&REG_EXPANDED) {
+ skip(v);
+ }
+ if (ATEOS() || !iscdigit(*v->now)) {
+ NOTE(REG_UBRACES);
+ NOTE(REG_UUNSPEC);
+ RETV(PLAIN, c);
+ } else {
+ NOTE(REG_UBOUNDS);
+ INTOCON(L_EBND);
+ RET('{');
+ }
+ assert(NOTREACHED);
+ break;
+ case CHR('('): /* parenthesis, or advanced extension */
+ if ((v->cflags&REG_ADVF) && NEXT1('?')) {
+ NOTE(REG_UNONPOSIX);
+ v->now++;
+ switch (*v->now++) {
+ case CHR(':'): /* non-capturing paren */
+ RETV('(', 0);
+ break;
+ case CHR('#'): /* comment */
+ while (!ATEOS() && *v->now != CHR(')')) {
+ v->now++;
}
- INTOCON(L_BRACK);
- if (NEXT1('^')) {
- v->now++;
- RETV('[', 0);
+ if (!ATEOS()) {
+ v->now++;
}
- RETV('[', 1);
- break;
- case CHR('.'):
- RET('.');
+ assert(v->nexttype == v->lasttype);
+ return next(v);
break;
- case CHR('^'):
- RET('^');
+ case CHR('='): /* positive lookahead */
+ NOTE(REG_ULOOKAHEAD);
+ RETV(LACON, 1);
break;
- case CHR('$'):
- RET('$');
+ case CHR('!'): /* negative lookahead */
+ NOTE(REG_ULOOKAHEAD);
+ RETV(LACON, 0);
break;
- case CHR('\\'): /* mostly punt backslashes to code below */
- if (ATEOS())
- FAILW(REG_EESCAPE);
- break;
- default: /* ordinary character */
- RETV(PLAIN, c);
+ default:
+ FAILW(REG_BADRPT);
break;
+ }
+ assert(NOTREACHED);
+ }
+ if (v->cflags&REG_NOSUB) {
+ RETV('(', 0); /* all parens non-capturing */
+ } else {
+ RETV('(', 1);
+ }
+ break;
+ case CHR(')'):
+ if (LASTTYPE('(')) {
+ NOTE(REG_UUNSPEC);
+ }
+ RETV(')', c);
+ break;
+ case CHR('['): /* easy except for [[:<:]] and [[:>:]] */
+ if (HAVE(6) && *(v->now+0) == CHR('[') &&
+ *(v->now+1) == CHR(':') &&
+ (*(v->now+2) == CHR('<') || *(v->now+2) == CHR('>')) &&
+ *(v->now+3) == CHR(':') &&
+ *(v->now+4) == CHR(']') &&
+ *(v->now+5) == CHR(']')) {
+ c = *(v->now+2);
+ v->now += 6;
+ NOTE(REG_UNONPOSIX);
+ RET((c == CHR('<')) ? '<' : '>');
+ }
+ INTOCON(L_BRACK);
+ if (NEXT1('^')) {
+ v->now++;
+ RETV('[', 0);
+ }
+ RETV('[', 1);
+ break;
+ case CHR('.'):
+ RET('.');
+ break;
+ case CHR('^'):
+ RET('^');
+ break;
+ case CHR('$'):
+ RET('$');
+ break;
+ case CHR('\\'): /* mostly punt backslashes to code below */
+ if (ATEOS()) {
+ FAILW(REG_EESCAPE);
}
+ break;
+ default: /* ordinary character */
+ RETV(PLAIN, c);
+ break;
+ }
- /* ERE/ARE backslash handling; backslash already eaten */
- assert(!ATEOS());
- if (!(v->cflags&REG_ADVF)) { /* only AREs have non-trivial escapes */
- if (iscalnum(*v->now)) {
- NOTE(REG_UBSALNUM);
- NOTE(REG_UUNSPEC);
- }
- RETV(PLAIN, *v->now++);
+ /*
+ * ERE/ARE backslash handling; backslash already eaten.
+ */
+
+ assert(!ATEOS());
+ if (!(v->cflags&REG_ADVF)) {/* only AREs have non-trivial escapes */
+ if (iscalnum(*v->now)) {
+ NOTE(REG_UBSALNUM);
+ NOTE(REG_UUNSPEC);
}
- (DISCARD)lexescape(v);
- if (ISERR())
- FAILW(REG_EESCAPE);
- if (v->nexttype == CCLASS) { /* fudge at lexical level */
- switch (v->nextvalue) {
- case 'd': lexnest(v, backd, ENDOF(backd)); break;
- case 'D': lexnest(v, backD, ENDOF(backD)); break;
- case 's': lexnest(v, backs, ENDOF(backs)); break;
- case 'S': lexnest(v, backS, ENDOF(backS)); break;
- case 'w': lexnest(v, backw, ENDOF(backw)); break;
- case 'W': lexnest(v, backW, ENDOF(backW)); break;
- default:
- assert(NOTREACHED);
- FAILW(REG_ASSERT);
- break;
- }
- /* lexnest done, back up and try again */
- v->nexttype = v->lasttype;
- return next(v);
+ RETV(PLAIN, *v->now++);
+ }
+ (DISCARD)lexescape(v);
+ if (ISERR()) {
+ FAILW(REG_EESCAPE);
+ }
+ if (v->nexttype == CCLASS) {/* fudge at lexical level */
+ switch (v->nextvalue) {
+ case 'd': lexnest(v, backd, ENDOF(backd)); break;
+ case 'D': lexnest(v, backD, ENDOF(backD)); break;
+ case 's': lexnest(v, backs, ENDOF(backs)); break;
+ case 'S': lexnest(v, backS, ENDOF(backS)); break;
+ case 'w': lexnest(v, backw, ENDOF(backw)); break;
+ case 'W': lexnest(v, backW, ENDOF(backW)); break;
+ default:
+ assert(NOTREACHED);
+ FAILW(REG_ASSERT);
+ break;
}
- /* otherwise, lexescape has already done the work */
- return !ISERR();
-}
+ /* lexnest done, back up and try again */
+ v->nexttype = v->lasttype;
+ return next(v);
+ }
+
+ /*
+ * Otherwise, lexescape has already done the work.
+ */
+ return !ISERR();
+}
+
/*
- lexescape - parse an ARE backslash escape (backslash already eaten)
* Note slightly nonstandard use of the CCLASS type code.
^ static int lexescape(struct vars *);
*/
static int /* not actually used, but convenient for RETV */
-lexescape(v)
-struct vars *v;
+lexescape(
+ struct vars *v)
{
- chr c;
- static chr alert[] = {
- CHR('a'), CHR('l'), CHR('e'), CHR('r'), CHR('t')
- };
- static chr esc[] = {
- CHR('E'), CHR('S'), CHR('C')
- };
- chr *save;
-
- assert(v->cflags&REG_ADVF);
-
- assert(!ATEOS());
- c = *v->now++;
- if (!iscalnum(c))
- RETV(PLAIN, c);
+ chr c;
+ static chr alert[] = {
+ CHR('a'), CHR('l'), CHR('e'), CHR('r'), CHR('t')
+ };
+ static chr esc[] = {
+ CHR('E'), CHR('S'), CHR('C')
+ };
+ const chr *save;
- NOTE(REG_UNONPOSIX);
- switch (c) {
- case CHR('a'):
- RETV(PLAIN, chrnamed(v, alert, ENDOF(alert), CHR('\007')));
- break;
- case CHR('A'):
- RETV(SBEGIN, 0);
- break;
- case CHR('b'):
- RETV(PLAIN, CHR('\b'));
- break;
- case CHR('B'):
- RETV(PLAIN, CHR('\\'));
- break;
- case CHR('c'):
- NOTE(REG_UUNPORT);
- if (ATEOS())
- FAILW(REG_EESCAPE);
- RETV(PLAIN, (chr)(*v->now++ & 037));
- break;
- case CHR('d'):
- NOTE(REG_ULOCALE);
- RETV(CCLASS, 'd');
- break;
- case CHR('D'):
- NOTE(REG_ULOCALE);
- RETV(CCLASS, 'D');
- break;
- case CHR('e'):
- NOTE(REG_UUNPORT);
- RETV(PLAIN, chrnamed(v, esc, ENDOF(esc), CHR('\033')));
- break;
- case CHR('f'):
- RETV(PLAIN, CHR('\f'));
- break;
- case CHR('m'):
- RET('<');
- break;
- case CHR('M'):
- RET('>');
- break;
- case CHR('n'):
- RETV(PLAIN, CHR('\n'));
- break;
- case CHR('r'):
- RETV(PLAIN, CHR('\r'));
- break;
- case CHR('s'):
- NOTE(REG_ULOCALE);
- RETV(CCLASS, 's');
- break;
- case CHR('S'):
- NOTE(REG_ULOCALE);
- RETV(CCLASS, 'S');
- break;
- case CHR('t'):
- RETV(PLAIN, CHR('\t'));
- break;
- case CHR('u'):
- c = lexdigits(v, 16, 4, 4);
- if (ISERR())
- FAILW(REG_EESCAPE);
- RETV(PLAIN, c);
- break;
- case CHR('U'):
- c = lexdigits(v, 16, 8, 8);
- if (ISERR())
- FAILW(REG_EESCAPE);
- RETV(PLAIN, c);
- break;
- case CHR('v'):
- RETV(PLAIN, CHR('\v'));
- break;
- case CHR('w'):
- NOTE(REG_ULOCALE);
- RETV(CCLASS, 'w');
- break;
- case CHR('W'):
- NOTE(REG_ULOCALE);
- RETV(CCLASS, 'W');
- break;
- case CHR('x'):
- NOTE(REG_UUNPORT);
- c = lexdigits(v, 16, 1, 255); /* REs >255 long outside spec */
- if (ISERR())
- FAILW(REG_EESCAPE);
- RETV(PLAIN, c);
- break;
- case CHR('y'):
- NOTE(REG_ULOCALE);
- RETV(WBDRY, 0);
- break;
- case CHR('Y'):
- NOTE(REG_ULOCALE);
- RETV(NWBDRY, 0);
- break;
- case CHR('Z'):
- RETV(SEND, 0);
- break;
- case CHR('1'): case CHR('2'): case CHR('3'): case CHR('4'):
- case CHR('5'): case CHR('6'): case CHR('7'): case CHR('8'):
- case CHR('9'):
- save = v->now;
- v->now--; /* put first digit back */
- c = lexdigits(v, 10, 1, 255); /* REs >255 long outside spec */
- if (ISERR())
- FAILW(REG_EESCAPE);
- /* ugly heuristic (first test is "exactly 1 digit?") */
- if (v->now-save == 0 || ((int)c > 0 && (int)c <= v->nsubexp)) {
- NOTE(REG_UBACKREF);
- RETV(BACKREF, (chr)c);
- }
- /* oops, doesn't look like it's a backref after all... */
- v->now = save;
- /* and fall through into octal number */
- case CHR('0'):
- NOTE(REG_UUNPORT);
- v->now--; /* put first digit back */
- c = lexdigits(v, 8, 1, 3);
- if (ISERR())
- FAILW(REG_EESCAPE);
- RETV(PLAIN, c);
- break;
- default:
- assert(iscalpha(c));
- FAILW(REG_EESCAPE); /* unknown alphabetic escape */
- break;
+ assert(v->cflags&REG_ADVF);
+
+ assert(!ATEOS());
+ c = *v->now++;
+ if (!iscalnum(c)) {
+ RETV(PLAIN, c);
+ }
+
+ NOTE(REG_UNONPOSIX);
+ switch (c) {
+ case CHR('a'):
+ RETV(PLAIN, chrnamed(v, alert, ENDOF(alert), CHR('\007')));
+ break;
+ case CHR('A'):
+ RETV(SBEGIN, 0);
+ break;
+ case CHR('b'):
+ RETV(PLAIN, CHR('\b'));
+ break;
+ case CHR('B'):
+ RETV(PLAIN, CHR('\\'));
+ break;
+ case CHR('c'):
+ NOTE(REG_UUNPORT);
+ if (ATEOS()) {
+ FAILW(REG_EESCAPE);
}
- assert(NOTREACHED);
-}
+ RETV(PLAIN, (chr)(*v->now++ & 037));
+ break;
+ case CHR('d'):
+ NOTE(REG_ULOCALE);
+ RETV(CCLASS, 'd');
+ break;
+ case CHR('D'):
+ NOTE(REG_ULOCALE);
+ RETV(CCLASS, 'D');
+ break;
+ case CHR('e'):
+ NOTE(REG_UUNPORT);
+ RETV(PLAIN, chrnamed(v, esc, ENDOF(esc), CHR('\033')));
+ break;
+ case CHR('f'):
+ RETV(PLAIN, CHR('\f'));
+ break;
+ case CHR('m'):
+ RET('<');
+ break;
+ case CHR('M'):
+ RET('>');
+ break;
+ case CHR('n'):
+ RETV(PLAIN, CHR('\n'));
+ break;
+ case CHR('r'):
+ RETV(PLAIN, CHR('\r'));
+ break;
+ case CHR('s'):
+ NOTE(REG_ULOCALE);
+ RETV(CCLASS, 's');
+ break;
+ case CHR('S'):
+ NOTE(REG_ULOCALE);
+ RETV(CCLASS, 'S');
+ break;
+ case CHR('t'):
+ RETV(PLAIN, CHR('\t'));
+ break;
+ case CHR('u'):
+ c = lexdigits(v, 16, 4, 4);
+ if (ISERR()) {
+ FAILW(REG_EESCAPE);
+ }
+ RETV(PLAIN, c);
+ break;
+ case CHR('U'):
+ c = lexdigits(v, 16, 8, 8);
+ if (ISERR()) {
+ FAILW(REG_EESCAPE);
+ }
+ RETV(PLAIN, c);
+ break;
+ case CHR('v'):
+ RETV(PLAIN, CHR('\v'));
+ break;
+ case CHR('w'):
+ NOTE(REG_ULOCALE);
+ RETV(CCLASS, 'w');
+ break;
+ case CHR('W'):
+ NOTE(REG_ULOCALE);
+ RETV(CCLASS, 'W');
+ break;
+ case CHR('x'):
+ NOTE(REG_UUNPORT);
+ c = lexdigits(v, 16, 1, 255); /* REs >255 long outside spec */
+ if (ISERR()) {
+ FAILW(REG_EESCAPE);
+ }
+ RETV(PLAIN, c);
+ break;
+ case CHR('y'):
+ NOTE(REG_ULOCALE);
+ RETV(WBDRY, 0);
+ break;
+ case CHR('Y'):
+ NOTE(REG_ULOCALE);
+ RETV(NWBDRY, 0);
+ break;
+ case CHR('Z'):
+ RETV(SEND, 0);
+ break;
+ case CHR('1'): case CHR('2'): case CHR('3'): case CHR('4'):
+ case CHR('5'): case CHR('6'): case CHR('7'): case CHR('8'):
+ case CHR('9'):
+ save = v->now;
+ v->now--; /* put first digit back */
+ c = lexdigits(v, 10, 1, 255); /* REs >255 long outside spec */
+ if (ISERR()) {
+ FAILW(REG_EESCAPE);
+ }
+
+ /*
+ * Ugly heuristic (first test is "exactly 1 digit?")
+ */
+
+ if (v->now - save == 0 || ((int) c > 0 && (int)c <= v->nsubexp)) {
+ NOTE(REG_UBACKREF);
+ RETV(BACKREF, (chr)c);
+ }
+
+ /*
+ * Oops, doesn't look like it's a backref after all...
+ */
+ v->now = save;
+
+ /*
+ * And fall through into octal number.
+ */
+
+ case CHR('0'):
+ NOTE(REG_UUNPORT);
+ v->now--; /* put first digit back */
+ c = lexdigits(v, 8, 1, 3);
+ if (ISERR()) {
+ FAILW(REG_EESCAPE);
+ }
+ RETV(PLAIN, c);
+ break;
+ default:
+ assert(iscalpha(c));
+ FAILW(REG_EESCAPE); /* unknown alphabetic escape */
+ break;
+ }
+ assert(NOTREACHED);
+}
+
/*
- lexdigits - slurp up digits and return chr value
^ static chr lexdigits(struct vars *, int, int, int);
*/
static chr /* chr value; errors signalled via ERR */
-lexdigits(v, base, minlen, maxlen)
-struct vars *v;
-int base;
-int minlen;
-int maxlen;
+lexdigits(
+ struct vars *v,
+ int base,
+ int minlen,
+ int maxlen)
{
- uchr n; /* unsigned to avoid overflow misbehavior */
- int len;
- chr c;
- int d;
- CONST uchr ub = (uchr) base;
-
- n = 0;
- for (len = 0; len < maxlen && !ATEOS(); len++) {
- c = *v->now++;
- switch (c) {
- case CHR('0'): case CHR('1'): case CHR('2'): case CHR('3'):
- case CHR('4'): case CHR('5'): case CHR('6'): case CHR('7'):
- case CHR('8'): case CHR('9'):
- d = DIGITVAL(c);
- break;
- case CHR('a'): case CHR('A'): d = 10; break;
- case CHR('b'): case CHR('B'): d = 11; break;
- case CHR('c'): case CHR('C'): d = 12; break;
- case CHR('d'): case CHR('D'): d = 13; break;
- case CHR('e'): case CHR('E'): d = 14; break;
- case CHR('f'): case CHR('F'): d = 15; break;
- default:
- v->now--; /* oops, not a digit at all */
- d = -1;
- break;
- }
+ uchr n; /* unsigned to avoid overflow misbehavior */
+ int len;
+ chr c;
+ int d;
+ CONST uchr ub = (uchr) base;
- if (d >= base) { /* not a plausible digit */
- v->now--;
- d = -1;
- }
- if (d < 0)
- break; /* NOTE BREAK OUT */
- n = n*ub + (uchr)d;
+ n = 0;
+ for (len = 0; len < maxlen && !ATEOS(); len++) {
+ c = *v->now++;
+ switch (c) {
+ case CHR('0'): case CHR('1'): case CHR('2'): case CHR('3'):
+ case CHR('4'): case CHR('5'): case CHR('6'): case CHR('7'):
+ case CHR('8'): case CHR('9'):
+ d = DIGITVAL(c);
+ break;
+ case CHR('a'): case CHR('A'): d = 10; break;
+ case CHR('b'): case CHR('B'): d = 11; break;
+ case CHR('c'): case CHR('C'): d = 12; break;
+ case CHR('d'): case CHR('D'): d = 13; break;
+ case CHR('e'): case CHR('E'): d = 14; break;
+ case CHR('f'): case CHR('F'): d = 15; break;
+ default:
+ v->now--; /* oops, not a digit at all */
+ d = -1;
+ break;
}
- if (len < minlen)
- ERR(REG_EESCAPE);
- return (chr)n;
-}
+ if (d >= base) { /* not a plausible digit */
+ v->now--;
+ d = -1;
+ }
+ if (d < 0) {
+ break; /* NOTE BREAK OUT */
+ }
+ n = n*ub + (uchr)d;
+ }
+ if (len < minlen) {
+ ERR(REG_EESCAPE);
+ }
+ return (chr)n;
+}
+
/*
- brenext - get next BRE token
* This is much like EREs except for all the stupid backslashes and the
@@ -865,197 +968,218 @@ int maxlen;
^ static int brenext(struct vars *, pchr);
*/
static int /* 1 normal, 0 failure */
-brenext(v, pc)
-struct vars *v;
-pchr pc;
+brenext(
+ struct vars *v,
+ pchr pc)
{
- chr c = (chr)pc;
+ chr c = (chr)pc;
- switch (c) {
- case CHR('*'):
- if (LASTTYPE(EMPTY) || LASTTYPE('(') || LASTTYPE('^'))
- RETV(PLAIN, c);
- RET('*');
- break;
- case CHR('['):
- if (HAVE(6) && *(v->now+0) == CHR('[') &&
- *(v->now+1) == CHR(':') &&
- (*(v->now+2) == CHR('<') ||
- *(v->now+2) == CHR('>')) &&
- *(v->now+3) == CHR(':') &&
- *(v->now+4) == CHR(']') &&
- *(v->now+5) == CHR(']')) {
- c = *(v->now+2);
- v->now += 6;
- NOTE(REG_UNONPOSIX);
- RET((c == CHR('<')) ? '<' : '>');
- }
- INTOCON(L_BRACK);
- if (NEXT1('^')) {
- v->now++;
- RETV('[', 0);
- }
- RETV('[', 1);
- break;
- case CHR('.'):
- RET('.');
- break;
- case CHR('^'):
- if (LASTTYPE(EMPTY))
- RET('^');
- if (LASTTYPE('(')) {
- NOTE(REG_UUNSPEC);
- RET('^');
- }
- RETV(PLAIN, c);
- break;
- case CHR('$'):
- if (v->cflags&REG_EXPANDED)
- skip(v);
- if (ATEOS())
- RET('$');
- if (NEXT2('\\', ')')) {
- NOTE(REG_UUNSPEC);
- RET('$');
- }
- RETV(PLAIN, c);
- break;
- case CHR('\\'):
- break; /* see below */
- default:
- RETV(PLAIN, c);
- break;
+ switch (c) {
+ case CHR('*'):
+ if (LASTTYPE(EMPTY) || LASTTYPE('(') || LASTTYPE('^')) {
+ RETV(PLAIN, c);
+ }
+ RET('*');
+ break;
+ case CHR('['):
+ if (HAVE(6) && *(v->now+0) == CHR('[') &&
+ *(v->now+1) == CHR(':') &&
+ (*(v->now+2) == CHR('<') || *(v->now+2) == CHR('>')) &&
+ *(v->now+3) == CHR(':') &&
+ *(v->now+4) == CHR(']') &&
+ *(v->now+5) == CHR(']')) {
+ c = *(v->now+2);
+ v->now += 6;
+ NOTE(REG_UNONPOSIX);
+ RET((c == CHR('<')) ? '<' : '>');
+ }
+ INTOCON(L_BRACK);
+ if (NEXT1('^')) {
+ v->now++;
+ RETV('[', 0);
+ }
+ RETV('[', 1);
+ break;
+ case CHR('.'):
+ RET('.');
+ break;
+ case CHR('^'):
+ if (LASTTYPE(EMPTY)) {
+ RET('^');
+ }
+ if (LASTTYPE('(')) {
+ NOTE(REG_UUNSPEC);
+ RET('^');
}
+ RETV(PLAIN, c);
+ break;
+ case CHR('$'):
+ if (v->cflags&REG_EXPANDED) {
+ skip(v);
+ }
+ if (ATEOS()) {
+ RET('$');
+ }
+ if (NEXT2('\\', ')')) {
+ NOTE(REG_UUNSPEC);
+ RET('$');
+ }
+ RETV(PLAIN, c);
+ break;
+ case CHR('\\'):
+ break; /* see below */
+ default:
+ RETV(PLAIN, c);
+ break;
+ }
- assert(c == CHR('\\'));
+ assert(c == CHR('\\'));
- if (ATEOS())
- FAILW(REG_EESCAPE);
+ if (ATEOS()) {
+ FAILW(REG_EESCAPE);
+ }
- c = *v->now++;
- switch (c) {
- case CHR('{'):
- INTOCON(L_BBND);
- NOTE(REG_UBOUNDS);
- RET('{');
- break;
- case CHR('('):
- RETV('(', 1);
- break;
- case CHR(')'):
- RETV(')', c);
- break;
- case CHR('<'):
- NOTE(REG_UNONPOSIX);
- RET('<');
- break;
- case CHR('>'):
- NOTE(REG_UNONPOSIX);
- RET('>');
- break;
- case CHR('1'): case CHR('2'): case CHR('3'): case CHR('4'):
- case CHR('5'): case CHR('6'): case CHR('7'): case CHR('8'):
- case CHR('9'):
- NOTE(REG_UBACKREF);
- RETV(BACKREF, (chr)DIGITVAL(c));
- break;
- default:
- if (iscalnum(c)) {
- NOTE(REG_UBSALNUM);
- NOTE(REG_UUNSPEC);
- }
- RETV(PLAIN, c);
- break;
+ c = *v->now++;
+ switch (c) {
+ case CHR('{'):
+ INTOCON(L_BBND);
+ NOTE(REG_UBOUNDS);
+ RET('{');
+ break;
+ case CHR('('):
+ RETV('(', 1);
+ break;
+ case CHR(')'):
+ RETV(')', c);
+ break;
+ case CHR('<'):
+ NOTE(REG_UNONPOSIX);
+ RET('<');
+ break;
+ case CHR('>'):
+ NOTE(REG_UNONPOSIX);
+ RET('>');
+ break;
+ case CHR('1'): case CHR('2'): case CHR('3'): case CHR('4'):
+ case CHR('5'): case CHR('6'): case CHR('7'): case CHR('8'):
+ case CHR('9'):
+ NOTE(REG_UBACKREF);
+ RETV(BACKREF, (chr)DIGITVAL(c));
+ break;
+ default:
+ if (iscalnum(c)) {
+ NOTE(REG_UBSALNUM);
+ NOTE(REG_UUNSPEC);
}
+ RETV(PLAIN, c);
+ break;
+ }
- assert(NOTREACHED);
+ assert(NOTREACHED);
}
-
+
/*
- skip - skip white space and comments in expanded form
^ static VOID skip(struct vars *);
*/
-static VOID
-skip(v)
-struct vars *v;
+static void
+skip(
+ struct vars *v)
{
- chr *start = v->now;
-
- assert(v->cflags&REG_EXPANDED);
-
- for (;;) {
- while (!ATEOS() && iscspace(*v->now))
- v->now++;
- if (ATEOS() || *v->now != CHR('#'))
- break; /* NOTE BREAK OUT */
- assert(NEXT1('#'));
- while (!ATEOS() && *v->now != CHR('\n'))
- v->now++;
- /* leave the newline to be picked up by the iscspace loop */
+ const chr *start = v->now;
+
+ assert(v->cflags&REG_EXPANDED);
+
+ for (;;) {
+ while (!ATEOS() && iscspace(*v->now)) {
+ v->now++;
+ }
+ if (ATEOS() || *v->now != CHR('#')) {
+ break; /* NOTE BREAK OUT */
+ }
+ assert(NEXT1('#'));
+ while (!ATEOS() && *v->now != CHR('\n')) {
+ v->now++;
}
- if (v->now != start)
- NOTE(REG_UNONPOSIX);
-}
+ /*
+ * Leave the newline to be picked up by the iscspace loop.
+ */
+ }
+ if (v->now != start) {
+ NOTE(REG_UNONPOSIX);
+ }
+}
+
/*
- newline - return the chr for a newline
* This helps confine use of CHR to this source file.
^ static chr newline(NOPARMS);
*/
static chr
-newline()
+newline(void)
{
- return CHR('\n');
+ return CHR('\n');
}
-
+
/*
- ch - return the chr sequence for regc_locale.c's fake collating element ch
* This helps confine use of CHR to this source file. Beware that the caller
* knows how long the sequence is.
^ #ifdef REG_DEBUG
- ^ static chr *ch(NOPARMS);
+ ^ static const chr *ch(NOPARMS);
^ #endif
*/
#ifdef REG_DEBUG
-static chr *
-ch()
+static const chr *
+ch(void)
{
- static chr chstr[] = { CHR('c'), CHR('h'), CHR('\0') };
+ static chr chstr[] = { CHR('c'), CHR('h'), CHR('\0') };
- return chstr;
+ return chstr;
}
#endif
-
+
/*
- chrnamed - return the chr known by a given (chr string) name
* The code is a bit clumsy, but this routine gets only such specialized
* use that it hardly matters.
- ^ static chr chrnamed(struct vars *, chr *, chr *, pchr);
+ ^ static chr chrnamed(struct vars *, const chr *, const chr *, pchr);
*/
static chr
-chrnamed(v, startp, endp, lastresort)
-struct vars *v;
-chr *startp; /* start of name */
-chr *endp; /* just past end of name */
-pchr lastresort; /* what to return if name lookup fails */
+chrnamed(
+ struct vars *v,
+ const chr *startp, /* start of name */
+ const chr *endp, /* just past end of name */
+ pchr lastresort) /* what to return if name lookup fails */
{
- celt c;
- int errsave;
- int e;
- struct cvec *cv;
-
- errsave = v->err;
- v->err = 0;
- c = element(v, startp, endp);
- e = v->err;
- v->err = errsave;
-
- if (e != 0)
- return (chr)lastresort;
-
- cv = range(v, c, c, 0);
- if (cv->nchrs == 0)
- return (chr)lastresort;
- return cv->chrs[0];
+ celt c;
+ int errsave;
+ int e;
+ struct cvec *cv;
+
+ errsave = v->err;
+ v->err = 0;
+ c = element(v, startp, endp);
+ e = v->err;
+ v->err = errsave;
+
+ if (e != 0) {
+ return (chr)lastresort;
+ }
+
+ cv = range(v, c, c, 0);
+ if (cv->nchrs == 0) {
+ return (chr)lastresort;
+ }
+ return cv->chrs[0];
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/regc_locale.c b/generic/regc_locale.c
index 0424aee..124dff4 100644
--- a/generic/regc_locale.c
+++ b/generic/regc_locale.c
@@ -12,9 +12,9 @@
/* ASCII character-name table */
-static struct cname {
- CONST char *name;
- CONST char code;
+static const struct cname {
+ const char *name;
+ const char code;
} cnames[] = {
{"NUL", '\0'},
{"SOH", '\001'},
@@ -133,7 +133,7 @@ typedef struct crange {
* Unicode: alphabetic characters.
*/
-static CONST crange alphaRangeTable[] = {
+static const crange alphaRangeTable[] = {
{0x0041, 0x005a}, {0x0061, 0x007a}, {0x00c0, 0x00d6}, {0x00d8, 0x00f6},
{0x00f8, 0x02c1}, {0x02c6, 0x02d1}, {0x02e0, 0x02e4}, {0x0370, 0x0374},
{0x037a, 0x037d}, {0x0388, 0x038a}, {0x038e, 0x03a1}, {0x03a3, 0x03f5},
@@ -200,7 +200,7 @@ static CONST crange alphaRangeTable[] = {
#define NUM_ALPHA_RANGE (sizeof(alphaRangeTable)/sizeof(crange))
-static CONST chr alphaCharTable[] = {
+static const chr alphaCharTable[] = {
0x00aa, 0x00b5, 0x00ba, 0x02ec, 0x02ee, 0x0376, 0x0377, 0x0386, 0x038c,
0x0559, 0x066e, 0x066f, 0x06d5, 0x06e5, 0x06e6, 0x06ee, 0x06ef, 0x06ff,
0x0710, 0x07b1, 0x07f4, 0x07f5, 0x07fa, 0x081a, 0x0824, 0x0828, 0x093d,
@@ -227,7 +227,7 @@ static CONST chr alphaCharTable[] = {
* Unicode: decimal digit characters.
*/
-static CONST crange digitRangeTable[] = {
+static const crange digitRangeTable[] = {
{0x0030, 0x0039}, {0x0660, 0x0669}, {0x06f0, 0x06f9}, {0x07c0, 0x07c9},
{0x0966, 0x096f}, {0x09e6, 0x09ef}, {0x0a66, 0x0a6f}, {0x0ae6, 0x0aef},
{0x0b66, 0x0b6f}, {0x0be6, 0x0bef}, {0x0c66, 0x0c6f}, {0x0ce6, 0x0cef},
@@ -249,7 +249,7 @@ static CONST crange digitRangeTable[] = {
* Unicode: punctuation characters.
*/
-static CONST crange punctRangeTable[] = {
+static const crange punctRangeTable[] = {
{0x0021, 0x0023}, {0x0025, 0x002a}, {0x002c, 0x002f}, {0x005b, 0x005d},
{0x055a, 0x055f}, {0x066a, 0x066d}, {0x0700, 0x070d}, {0x07f7, 0x07f9},
{0x0830, 0x083e}, {0x0f04, 0x0f12}, {0x0f3a, 0x0f3d}, {0x0fd0, 0x0fd4},
@@ -267,7 +267,7 @@ static CONST crange punctRangeTable[] = {
#define NUM_PUNCT_RANGE (sizeof(punctRangeTable)/sizeof(crange))
-static CONST chr punctCharTable[] = {
+static const chr punctCharTable[] = {
0x003a, 0x003b, 0x003f, 0x0040, 0x005f, 0x007b, 0x007d, 0x00a1, 0x00ab,
0x00b7, 0x00bb, 0x00bf, 0x037e, 0x0387, 0x0589, 0x058a, 0x05be, 0x05c0,
0x05c3, 0x05c6, 0x05f3, 0x05f4, 0x0609, 0x060a, 0x060c, 0x060d, 0x061b,
@@ -288,13 +288,13 @@ static CONST chr punctCharTable[] = {
* Unicode: white space characters.
*/
-static CONST crange spaceRangeTable[] = {
+static const crange spaceRangeTable[] = {
{0x0009, 0x000d}, {0x2000, 0x200a}
};
#define NUM_SPACE_RANGE (sizeof(spaceRangeTable)/sizeof(crange))
-static CONST chr spaceCharTable[] = {
+static const chr spaceCharTable[] = {
0x0020, 0x00a0, 0x1680, 0x180e, 0x2028, 0x2029, 0x202f, 0x205f, 0x3000
};
@@ -304,7 +304,7 @@ static CONST chr spaceCharTable[] = {
* Unicode: lowercase characters.
*/
-static CONST crange lowerRangeTable[] = {
+static const crange lowerRangeTable[] = {
{0x0061, 0x007a}, {0x00df, 0x00f6}, {0x00f8, 0x00ff}, {0x017e, 0x0180},
{0x0199, 0x019b}, {0x01bd, 0x01bf}, {0x0233, 0x0239}, {0x024f, 0x0293},
{0x0295, 0x02af}, {0x037b, 0x037d}, {0x03ac, 0x03ce}, {0x03d5, 0x03d7},
@@ -320,7 +320,7 @@ static CONST crange lowerRangeTable[] = {
#define NUM_LOWER_RANGE (sizeof(lowerRangeTable)/sizeof(crange))
-static CONST chr lowerCharTable[] = {
+static const chr lowerCharTable[] = {
0x00aa, 0x00b5, 0x00ba, 0x0101, 0x0103, 0x0105, 0x0107, 0x0109, 0x010b,
0x010d, 0x010f, 0x0111, 0x0113, 0x0115, 0x0117, 0x0119, 0x011b, 0x011d,
0x011f, 0x0121, 0x0123, 0x0125, 0x0127, 0x0129, 0x012b, 0x012d, 0x012f,
@@ -391,7 +391,7 @@ static CONST chr lowerCharTable[] = {
* Unicode: uppercase characters.
*/
-static CONST crange upperRangeTable[] = {
+static const crange upperRangeTable[] = {
{0x0041, 0x005a}, {0x00c0, 0x00d6}, {0x00d8, 0x00de}, {0x0189, 0x018b},
{0x018e, 0x0191}, {0x0196, 0x0198}, {0x01b1, 0x01b3}, {0x01f6, 0x01f8},
{0x0243, 0x0246}, {0x0388, 0x038a}, {0x0391, 0x03a1}, {0x03a3, 0x03ab},
@@ -406,7 +406,7 @@ static CONST crange upperRangeTable[] = {
#define NUM_UPPER_RANGE (sizeof(upperRangeTable)/sizeof(crange))
-static CONST chr upperCharTable[] = {
+static const chr upperCharTable[] = {
0x0100, 0x0102, 0x0104, 0x0106, 0x0108, 0x010a, 0x010c, 0x010e, 0x0110,
0x0112, 0x0114, 0x0116, 0x0118, 0x011a, 0x011c, 0x011e, 0x0120, 0x0122,
0x0124, 0x0126, 0x0128, 0x012a, 0x012c, 0x012e, 0x0130, 0x0132, 0x0134,
@@ -477,7 +477,7 @@ static CONST chr upperCharTable[] = {
* Unicode: unicode print characters excluding space.
*/
-static CONST crange graphRangeTable[] = {
+static const crange graphRangeTable[] = {
{0x0021, 0x007e}, {0x00a0, 0x00ac}, {0x00ae, 0x011f}, {0x0121, 0x021f},
{0x0221, 0x031f}, {0x0321, 0x0377}, {0x037a, 0x037e}, {0x0384, 0x038a},
{0x038e, 0x03a1}, {0x03a3, 0x041f}, {0x0421, 0x051f}, {0x0521, 0x0527},
@@ -611,7 +611,7 @@ static CONST crange graphRangeTable[] = {
#define NUM_GRAPH_RANGE (sizeof(graphRangeTable)/sizeof(crange))
-static CONST chr graphCharTable[] = {
+static const chr graphCharTable[] = {
0x038c, 0x0589, 0x058a, 0x061e, 0x061f, 0x085e, 0x098f, 0x0990, 0x09b2,
0x09c7, 0x09c8, 0x09d7, 0x09dc, 0x09dd, 0x0a0f, 0x0a10, 0x0a32, 0x0a33,
0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a47, 0x0a48, 0x0a51, 0x0a5e,
@@ -634,7 +634,7 @@ static CONST chr graphCharTable[] = {
* L*), Numbers (N*), Punctuation (P*), Symbols (S*) and Spaces (Zs).
*/
-static CONST crange printRangeTable[] = {
+static const crange printRangeTable[] = {
{0x0020, 0x007E}, {0x00A0, 0x01F5}, {0x01FA, 0x0217}, {0x0250, 0x02A8},
{0x02B0, 0x02DE}, {0x02E0, 0x02E9}, {0x0374, 0x0375}, {0x0384, 0x038A},
{0x038E, 0x03A1}, {0x03A3, 0x03CE}, {0x03D0, 0x03D6}, {0x03E2, 0x03F3},
@@ -692,7 +692,7 @@ static CONST crange printRangeTable[] = {
#define NUM_PRINT_RANGE (sizeof(printRangeTable)/sizeof(crange))
-static CONST chr printCharTable[] = {
+static const chr printCharTable[] = {
0x037A, 0x037E, 0x038C, 0x03DA, 0x03DC, 0x03DE, 0x03E0, 0x0589, 0x05BE,
0x05C0, 0x05C3, 0x060C, 0x061B, 0x061F, 0x06E9, 0x093D, 0x0950, 0x09B2,
0x0A5E, 0x0A8D, 0x0ABD, 0x0AD0, 0x0AE0, 0x0B3D, 0x0B9C, 0x0CDE, 0x0E01,
@@ -710,56 +710,19 @@ static CONST chr printCharTable[] = {
#define CH NOCELT
/*
- - nmcces - how many distinct MCCEs are there?
- ^ static int nmcces(struct vars *);
- */
-static int
-nmcces(v)
- struct vars *v; /* context */
-{
- /*
- * No multi-character collating elements defined at the moment.
- */
- return 0;
-}
-
-/*
- - nleaders - how many chrs can be first chrs of MCCEs?
- ^ static int nleaders(struct vars *);
- */
-static int
-nleaders(v)
- struct vars *v; /* context */
-{
- return 0;
-}
-
-/*
- - allmcces - return a cvec with all the MCCEs of the locale
- ^ static struct cvec *allmcces(struct vars *, struct cvec *);
- */
-static struct cvec *
-allmcces(v, cv)
- struct vars *v; /* context */
- struct cvec *cv; /* this is supposed to have enough room */
-{
- return clearcvec(cv);
-}
-
-/*
- element - map collating-element name to celt
- ^ static celt element(struct vars *, CONST chr *, CONST chr *);
+ ^ static celt element(struct vars *, const chr *, const chr *);
*/
static celt
-element(v, startp, endp)
- struct vars *v; /* context */
- CONST chr *startp; /* points to start of name */
- CONST chr *endp; /* points just past end of name */
+element(
+ struct vars *v, /* context */
+ const chr *startp, /* points to start of name */
+ const chr *endp) /* points just past end of name */
{
- CONST struct cname *cn;
+ const struct cname *cn;
size_t len;
Tcl_DString ds;
- CONST char *np;
+ const char *np;
/*
* Generic: one-chr names stand for themselves.
@@ -802,11 +765,11 @@ element(v, startp, endp)
^ static struct cvec *range(struct vars *, celt, celt, int);
*/
static struct cvec *
-range(v, a, b, cases)
- struct vars *v; /* context */
- celt a; /* range start */
- celt b; /* range end, might equal a */
- int cases; /* case-independent? */
+range(
+ struct vars *v, /* context */
+ celt a, /* range start */
+ celt b, /* range end, might equal a */
+ int cases) /* case-independent? */
{
int nchrs;
struct cvec *cv;
@@ -818,7 +781,7 @@ range(v, a, b, cases)
}
if (!cases) { /* easy version */
- cv = getcvec(v, 0, 1, 0);
+ cv = getcvec(v, 0, 1);
NOERRN();
addrange(cv, a, b);
return cv;
@@ -832,7 +795,7 @@ range(v, a, b, cases)
nchrs = (b - a + 1)*2 + 4;
- cv = getcvec(v, nchrs, 0, 0);
+ cv = getcvec(v, nchrs, 0);
NOERRN();
for (c=a; c<=b; c++) {
@@ -859,8 +822,8 @@ range(v, a, b, cases)
^ static int before(celt, celt);
*/
static int /* predicate */
-before(x, y)
- celt x, y; /* collating elements */
+before(
+ celt x, celt y) /* collating elements */
{
if (x < y) {
return 1;
@@ -874,11 +837,11 @@ before(x, y)
^ static struct cvec *eclass(struct vars *, celt, int);
*/
static struct cvec *
-eclass(v, c, cases)
- struct vars *v; /* context */
- celt c; /* Collating element representing
- * the equivalence class. */
- int cases; /* all cases? */
+eclass(
+ struct vars *v, /* context */
+ celt c, /* Collating element representing the
+ * equivalence class. */
+ int cases) /* all cases? */
{
struct cvec *cv;
@@ -887,7 +850,7 @@ eclass(v, c, cases)
*/
if ((v->cflags&REG_FAKE) && c == 'x') {
- cv = getcvec(v, 4, 0, 0);
+ cv = getcvec(v, 4, 0);
addchr(cv, (chr)'x');
addchr(cv, (chr)'y');
if (cases) {
@@ -904,7 +867,7 @@ eclass(v, c, cases)
if (cases) {
return allcases(v, c);
}
- cv = getcvec(v, 1, 0, 0);
+ cv = getcvec(v, 1, 0);
assert(cv != NULL);
addchr(cv, (chr)c);
return cv;
@@ -913,27 +876,27 @@ eclass(v, c, cases)
/*
- cclass - supply cvec for a character class
* Must include case counterparts on request.
- ^ static struct cvec *cclass(struct vars *, CONST chr *, CONST chr *, int);
+ ^ static struct cvec *cclass(struct vars *, const chr *, const chr *, int);
*/
static struct cvec *
-cclass(v, startp, endp, cases)
- struct vars *v; /* context */
- CONST chr *startp; /* where the name starts */
- CONST chr *endp; /* just past the end of the name */
- int cases; /* case-independent? */
+cclass(
+ struct vars *v, /* context */
+ const chr *startp, /* where the name starts */
+ const chr *endp, /* just past the end of the name */
+ int cases) /* case-independent? */
{
size_t len;
struct cvec *cv = NULL;
Tcl_DString ds;
- CONST char *np;
- CONST char *CONST *namePtr;
+ const char *np;
+ const char *const *namePtr;
int i, index;
/*
* The following arrays define the valid character class names.
*/
- static CONST char *CONST classNames[] = {
+ static const char *const classNames[] = {
"alnum", "alpha", "ascii", "blank", "cntrl", "digit", "graph",
"lower", "print", "punct", "space", "upper", "xdigit", NULL
};
@@ -984,8 +947,19 @@ cclass(v, startp, endp, cases)
switch((enum classes) index) {
case CC_PRINT:
+ cv = getcvec(v, NUM_PRINT_CHAR, NUM_PRINT_RANGE);
+ if (cv) {
+ for (i=0 ; (size_t)i<NUM_PRINT_CHAR ; i++) {
+ addchr(cv, printCharTable[i]);
+ }
+ for (i=0 ; (size_t)i<NUM_PRINT_RANGE ; i++) {
+ addrange(cv, printRangeTable[i].start,
+ printRangeTable[i].end);
+ }
+ }
+ break;
case CC_ALNUM:
- cv = getcvec(v, NUM_ALPHA_CHAR, NUM_DIGIT_RANGE + NUM_ALPHA_RANGE, 0);
+ cv = getcvec(v, NUM_ALPHA_CHAR, NUM_DIGIT_RANGE + NUM_ALPHA_RANGE);
if (cv) {
for (i=0 ; (size_t)i<NUM_ALPHA_CHAR ; i++) {
addchr(cv, alphaCharTable[i]);
@@ -1001,7 +975,7 @@ cclass(v, startp, endp, cases)
}
break;
case CC_ALPHA:
- cv = getcvec(v, NUM_ALPHA_CHAR, NUM_ALPHA_RANGE, 0);
+ cv = getcvec(v, NUM_ALPHA_CHAR, NUM_ALPHA_RANGE);
if (cv) {
for (i=0 ; (size_t)i<NUM_ALPHA_RANGE ; i++) {
addrange(cv, alphaRangeTable[i].start,
@@ -1013,23 +987,23 @@ cclass(v, startp, endp, cases)
}
break;
case CC_ASCII:
- cv = getcvec(v, 0, 1, 0);
+ cv = getcvec(v, 0, 1);
if (cv) {
addrange(cv, 0, 0x7f);
}
break;
case CC_BLANK:
- cv = getcvec(v, 2, 0, 0);
+ cv = getcvec(v, 2, 0);
addchr(cv, '\t');
addchr(cv, ' ');
break;
case CC_CNTRL:
- cv = getcvec(v, 0, 2, 0);
+ cv = getcvec(v, 0, 2);
addrange(cv, 0x0, 0x1f);
addrange(cv, 0x7f, 0x9f);
break;
case CC_DIGIT:
- cv = getcvec(v, 0, NUM_DIGIT_RANGE, 0);
+ cv = getcvec(v, 0, NUM_DIGIT_RANGE);
if (cv) {
for (i=0 ; (size_t)i<NUM_DIGIT_RANGE ; i++) {
addrange(cv, digitRangeTable[i].start,
@@ -1038,7 +1012,7 @@ cclass(v, startp, endp, cases)
}
break;
case CC_PUNCT:
- cv = getcvec(v, NUM_PUNCT_CHAR, NUM_PUNCT_RANGE, 0);
+ cv = getcvec(v, NUM_PUNCT_CHAR, NUM_PUNCT_RANGE);
if (cv) {
for (i=0 ; (size_t)i<NUM_PUNCT_RANGE ; i++) {
addrange(cv, punctRangeTable[i].start,
@@ -1058,7 +1032,8 @@ cclass(v, startp, endp, cases)
* Whatever is actually the case, the number of ranges is fixed (until
* someone comes up with a better arrangement!)
*/
- cv = getcvec(v, 0, 3, 0);
+
+ cv = getcvec(v, 0, 3);
if (cv) {
addrange(cv, '0', '9');
addrange(cv, 'a', 'f');
@@ -1066,7 +1041,7 @@ cclass(v, startp, endp, cases)
}
break;
case CC_SPACE:
- cv = getcvec(v, NUM_SPACE_CHAR, NUM_SPACE_RANGE, 0);
+ cv = getcvec(v, NUM_SPACE_CHAR, NUM_SPACE_RANGE);
if (cv) {
for (i=0 ; (size_t)i<NUM_SPACE_RANGE ; i++) {
addrange(cv, spaceRangeTable[i].start,
@@ -1078,7 +1053,7 @@ cclass(v, startp, endp, cases)
}
break;
case CC_LOWER:
- cv = getcvec(v, NUM_LOWER_CHAR, NUM_LOWER_RANGE, 0);
+ cv = getcvec(v, NUM_LOWER_CHAR, NUM_LOWER_RANGE);
if (cv) {
for (i=0 ; (size_t)i<NUM_LOWER_RANGE ; i++) {
addrange(cv, lowerRangeTable[i].start,
@@ -1090,7 +1065,7 @@ cclass(v, startp, endp, cases)
}
break;
case CC_UPPER:
- cv = getcvec(v, NUM_UPPER_CHAR, NUM_UPPER_RANGE, 0);
+ cv = getcvec(v, NUM_UPPER_CHAR, NUM_UPPER_RANGE);
if (cv) {
for (i=0 ; (size_t)i<NUM_UPPER_RANGE ; i++) {
addrange(cv, upperRangeTable[i].start,
@@ -1102,7 +1077,7 @@ cclass(v, startp, endp, cases)
}
break;
case CC_GRAPH:
- cv = getcvec(v, NUM_GRAPH_CHAR, NUM_GRAPH_RANGE, 0);
+ cv = getcvec(v, NUM_GRAPH_CHAR, NUM_GRAPH_RANGE);
if (cv) {
for (i=0 ; (size_t)i<NUM_GRAPH_RANGE ; i++) {
addrange(cv, graphRangeTable[i].start,
@@ -1127,9 +1102,9 @@ cclass(v, startp, endp, cases)
^ static struct cvec *allcases(struct vars *, pchr);
*/
static struct cvec *
-allcases(v, pc)
- struct vars *v; /* context */
- pchr pc; /* character to get case equivs of */
+allcases(
+ struct vars *v, /* context */
+ pchr pc) /* character to get case equivs of */
{
struct cvec *cv;
chr c = (chr)pc;
@@ -1140,10 +1115,10 @@ allcases(v, pc)
tc = Tcl_UniCharToTitle((chr)c);
if (tc != uc) {
- cv = getcvec(v, 3, 0, 0);
+ cv = getcvec(v, 3, 0);
addchr(cv, tc);
} else {
- cv = getcvec(v, 2, 0, 0);
+ cv = getcvec(v, 2, 0);
}
addchr(cv, lc);
if (lc != uc) {
@@ -1158,12 +1133,12 @@ allcases(v, pc)
* Note that it does not need to report anything except equal/unequal.
* Note also that the length is exact, and the comparison should not
* stop at embedded NULs!
- ^ static int cmp(CONST chr *, CONST chr *, size_t);
+ ^ static int cmp(const chr *, const chr *, size_t);
*/
-static int /* 0 for equal, nonzero for unequal */
-cmp(x, y, len)
- CONST chr *x, *y; /* strings to compare */
- size_t len; /* exact length of comparison */
+static int /* 0 for equal, nonzero for unequal */
+cmp(
+ const chr *x, const chr *y, /* strings to compare */
+ size_t len) /* exact length of comparison */
{
return memcmp(VS(x), VS(y), len*sizeof(chr));
}
@@ -1174,12 +1149,12 @@ cmp(x, y, len)
* Note that it does not need to report anything except equal/unequal.
* Note also that the length is exact, and the comparison should not
* stop at embedded NULs!
- ^ static int casecmp(CONST chr *, CONST chr *, size_t);
+ ^ static int casecmp(const chr *, const chr *, size_t);
*/
-static int /* 0 for equal, nonzero for unequal */
-casecmp(x, y, len)
- CONST chr *x, *y; /* strings to compare */
- size_t len; /* exact length of comparison */
+static int /* 0 for equal, nonzero for unequal */
+casecmp(
+ const chr *x, const chr *y, /* strings to compare */
+ size_t len) /* exact length of comparison */
{
for (; len > 0; len--, x++, y++) {
if ((*x!=*y) && (Tcl_UniCharToLower(*x) != Tcl_UniCharToLower(*y))) {
diff --git a/generic/regc_nfa.c b/generic/regc_nfa.c
index 48f56a9..19dbe63 100644
--- a/generic/regc_nfa.c
+++ b/generic/regc_nfa.c
@@ -2,24 +2,24 @@
* NFA utilities.
* This file is #included by regcomp.c.
*
- * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
- *
+ * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
+ *
* Development of this software was funded, in part, by Cray Research Inc.,
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
- * Corporation, none of whom are responsible for the results. The author
- * thanks all of them.
- *
+ * Corporation, none of whom are responsible for the results. The author
+ * thanks all of them.
+ *
* Redistribution and use in source and binary forms -- with or without
* modification -- are permitted for any purpose, provided that
* redistributions in source form retain this entire copyright notice and
* indicate the origin and nature of any modifications.
- *
- * I'd appreciate being given credit for this package in the documentation
- * of software which uses it, but that is not a requirement.
- *
+ *
+ * I'd appreciate being given credit for this package in the documentation of
+ * software which uses it, but that is not a requirement.
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
@@ -28,471 +28,510 @@
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- *
- *
- * One or two things that technically ought to be in here
- * are actually in color.c, thanks to some incestuous relationships in
- * the color chains.
+ * One or two things that technically ought to be in here are actually in
+ * color.c, thanks to some incestuous relationships in the color chains.
*/
#define NISERR() VISERR(nfa->v)
#define NERR(e) VERR(nfa->v, (e))
-
-
+
/*
- newnfa - set up an NFA
^ static struct nfa *newnfa(struct vars *, struct colormap *, struct nfa *);
*/
static struct nfa * /* the NFA, or NULL */
-newnfa(v, cm, parent)
-struct vars *v;
-struct colormap *cm;
-struct nfa *parent; /* NULL if primary NFA */
+newnfa(
+ struct vars *v,
+ struct colormap *cm,
+ struct nfa *parent) /* NULL if primary NFA */
{
- struct nfa *nfa;
-
- nfa = (struct nfa *)MALLOC(sizeof(struct nfa));
- if (nfa == NULL)
- return NULL;
-
- nfa->states = NULL;
- nfa->slast = NULL;
- nfa->free = NULL;
- nfa->nstates = 0;
- nfa->cm = cm;
- nfa->v = v;
- nfa->size = 0;
- nfa->bos[0] = nfa->bos[1] = COLORLESS;
- nfa->eos[0] = nfa->eos[1] = COLORLESS;
- nfa->parent = parent;
- nfa->post = newfstate(nfa, '@'); /* number 0 */
- nfa->pre = newfstate(nfa, '>'); /* number 1 */
-
- nfa->init = newstate(nfa); /* may become invalid later */
- nfa->final = newstate(nfa);
- if (ISERR()) {
- freenfa(nfa);
- return NULL;
- }
- rainbow(nfa, nfa->cm, PLAIN, COLORLESS, nfa->pre, nfa->init);
- newarc(nfa, '^', 1, nfa->pre, nfa->init);
- newarc(nfa, '^', 0, nfa->pre, nfa->init);
- rainbow(nfa, nfa->cm, PLAIN, COLORLESS, nfa->final, nfa->post);
- newarc(nfa, '$', 1, nfa->final, nfa->post);
- newarc(nfa, '$', 0, nfa->final, nfa->post);
-
- if (ISERR()) {
- freenfa(nfa);
- return NULL;
- }
- return nfa;
-}
+ struct nfa *nfa;
+ nfa = (struct nfa *) MALLOC(sizeof(struct nfa));
+ if (nfa == NULL) {
+ return NULL;
+ }
+
+ nfa->states = NULL;
+ nfa->slast = NULL;
+ nfa->free = NULL;
+ nfa->nstates = 0;
+ nfa->cm = cm;
+ nfa->v = v;
+ nfa->size = 0;
+ nfa->bos[0] = nfa->bos[1] = COLORLESS;
+ nfa->eos[0] = nfa->eos[1] = COLORLESS;
+ nfa->parent = parent; /* Precedes newfstate so parent is valid. */
+ nfa->post = newfstate(nfa, '@'); /* number 0 */
+ nfa->pre = newfstate(nfa, '>'); /* number 1 */
+
+ nfa->init = newstate(nfa); /* May become invalid later. */
+ nfa->final = newstate(nfa);
+ if (ISERR()) {
+ freenfa(nfa);
+ return NULL;
+ }
+ rainbow(nfa, nfa->cm, PLAIN, COLORLESS, nfa->pre, nfa->init);
+ newarc(nfa, '^', 1, nfa->pre, nfa->init);
+ newarc(nfa, '^', 0, nfa->pre, nfa->init);
+ rainbow(nfa, nfa->cm, PLAIN, COLORLESS, nfa->final, nfa->post);
+ newarc(nfa, '$', 1, nfa->final, nfa->post);
+ newarc(nfa, '$', 0, nfa->final, nfa->post);
+
+ if (ISERR()) {
+ freenfa(nfa);
+ return NULL;
+ }
+ return nfa;
+}
+
/*
- - too_many_states - checks if the max states exceeds the compile-time value
- ^ static int too_many_states(struct nfa *);
+ - TooManyStates - checks if the max states exceeds the compile-time value
+ ^ static int TooManyStates(struct nfa *);
*/
static int
-too_many_states(nfa)
-struct nfa *nfa;
+TooManyStates(
+ struct nfa *nfa)
{
- struct nfa *parent = nfa->parent;
- size_t sz = nfa->size;
- while (parent != NULL) {
- sz = parent->size;
- parent = parent->parent;
- }
- if (sz > REG_MAX_STATES)
- return 1;
- return 0;
+ struct nfa *parent = nfa->parent;
+ size_t sz = nfa->size;
+
+ while (parent != NULL) {
+ sz = parent->size;
+ parent = parent->parent;
+ }
+ if (sz > REG_MAX_STATES) {
+ return 1;
+ }
+ return 0;
}
-
+
/*
- - increment_size - increases the tracked size of the NFA and its parents.
- ^ static void increment_size(struct nfa *);
+ - IncrementSize - increases the tracked size of the NFA and its parents.
+ ^ static void IncrementSize(struct nfa *);
*/
static void
-increment_size(nfa)
-struct nfa *nfa;
+IncrementSize(
+ struct nfa *nfa)
{
- struct nfa *parent = nfa->parent;
- nfa->size++;
- while (parent != NULL) {
- parent->size++;
- parent = parent->parent;
- }
-}
+ struct nfa *parent = nfa->parent;
+ nfa->size++;
+ while (parent != NULL) {
+ parent->size++;
+ parent = parent->parent;
+ }
+}
+
/*
- - decrement_size - increases the tracked size of the NFA and its parents.
- ^ static void decrement_size(struct nfa *);
+ - DecrementSize - increases the tracked size of the NFA and its parents.
+ ^ static void DecrementSize(struct nfa *);
*/
static void
-decrement_size(nfa)
-struct nfa *nfa;
+DecrementSize(
+ struct nfa *nfa)
{
- struct nfa *parent = nfa->parent;
- nfa->size--;
- while (parent != NULL) {
- parent->size--;
- parent = parent->parent;
- }
-}
+ struct nfa *parent = nfa->parent;
+ nfa->size--;
+ while (parent != NULL) {
+ parent->size--;
+ parent = parent->parent;
+ }
+}
+
/*
- freenfa - free an entire NFA
^ static VOID freenfa(struct nfa *);
*/
-static VOID
-freenfa(nfa)
-struct nfa *nfa;
+static void
+freenfa(
+ struct nfa *nfa)
{
- struct state *s;
-
- while ((s = nfa->states) != NULL) {
- s->nins = s->nouts = 0; /* don't worry about arcs */
- freestate(nfa, s);
- }
- while ((s = nfa->free) != NULL) {
- nfa->free = s->next;
- destroystate(nfa, s);
- }
+ struct state *s;
- nfa->slast = NULL;
- nfa->nstates = -1;
- nfa->pre = NULL;
- nfa->post = NULL;
- FREE(nfa);
+ while ((s = nfa->states) != NULL) {
+ s->nins = s->nouts = 0; /* don't worry about arcs */
+ freestate(nfa, s);
+ }
+ while ((s = nfa->free) != NULL) {
+ nfa->free = s->next;
+ destroystate(nfa, s);
+ }
+
+ nfa->slast = NULL;
+ nfa->nstates = -1;
+ nfa->pre = NULL;
+ nfa->post = NULL;
+ FREE(nfa);
}
-
+
/*
- newstate - allocate an NFA state, with zero flag value
^ static struct state *newstate(struct nfa *);
*/
static struct state * /* NULL on error */
-newstate(nfa)
-struct nfa *nfa;
+newstate(
+ struct nfa *nfa)
{
- struct state *s;
-
- if (too_many_states(nfa)) {
- /* XXX: add specific error for this */
- NERR(REG_ETOOBIG);
- return NULL;
- }
- if (nfa->free != NULL) {
- s = nfa->free;
- nfa->free = s->next;
- } else {
- s = (struct state *)MALLOC(sizeof(struct state));
- if (s == NULL) {
- NERR(REG_ESPACE);
- return NULL;
- }
- s->oas.next = NULL;
- s->free = NULL;
- s->noas = 0;
- }
+ struct state *s;
- assert(nfa->nstates >= 0);
- s->no = nfa->nstates++;
- s->flag = 0;
- if (nfa->states == NULL)
- nfa->states = s;
- s->nins = 0;
- s->ins = NULL;
- s->nouts = 0;
- s->outs = NULL;
- s->tmp = NULL;
- s->next = NULL;
- if (nfa->slast != NULL) {
- assert(nfa->slast->next == NULL);
- nfa->slast->next = s;
+ if (TooManyStates(nfa)) {
+ /* XXX: add specific error for this */
+ NERR(REG_ETOOBIG);
+ return NULL;
+ }
+ if (nfa->free != NULL) {
+ s = nfa->free;
+ nfa->free = s->next;
+ } else {
+ s = (struct state *) MALLOC(sizeof(struct state));
+ if (s == NULL) {
+ NERR(REG_ESPACE);
+ return NULL;
}
- s->prev = nfa->slast;
- nfa->slast = s;
- /* Track the current size and the parent size */
- increment_size(nfa);
- return s;
+ s->oas.next = NULL;
+ s->free = NULL;
+ s->noas = 0;
+ }
+
+ assert(nfa->nstates >= 0);
+ s->no = nfa->nstates++;
+ s->flag = 0;
+ if (nfa->states == NULL) {
+ nfa->states = s;
+ }
+ s->nins = 0;
+ s->ins = NULL;
+ s->nouts = 0;
+ s->outs = NULL;
+ s->tmp = NULL;
+ s->next = NULL;
+ if (nfa->slast != NULL) {
+ assert(nfa->slast->next == NULL);
+ nfa->slast->next = s;
+ }
+ s->prev = nfa->slast;
+ nfa->slast = s;
+
+ /*
+ * Track the current size and the parent size.
+ */
+
+ IncrementSize(nfa);
+ return s;
}
-
+
/*
- newfstate - allocate an NFA state with a specified flag value
^ static struct state *newfstate(struct nfa *, int flag);
*/
static struct state * /* NULL on error */
-newfstate(nfa, flag)
-struct nfa *nfa;
-int flag;
+newfstate(
+ struct nfa *nfa,
+ int flag)
{
- struct state *s;
+ struct state *s;
- s = newstate(nfa);
- if (s != NULL)
- s->flag = (char)flag;
- return s;
+ s = newstate(nfa);
+ if (s != NULL) {
+ s->flag = (char) flag;
+ }
+ return s;
}
-
+
/*
- dropstate - delete a state's inarcs and outarcs and free it
^ static VOID dropstate(struct nfa *, struct state *);
*/
-static VOID
-dropstate(nfa, s)
-struct nfa *nfa;
-struct state *s;
+static void
+dropstate(
+ struct nfa *nfa,
+ struct state *s)
{
- struct arc *a;
+ struct arc *a;
- while ((a = s->ins) != NULL)
- freearc(nfa, a);
- while ((a = s->outs) != NULL)
- freearc(nfa, a);
- freestate(nfa, s);
+ while ((a = s->ins) != NULL) {
+ freearc(nfa, a);
+ }
+ while ((a = s->outs) != NULL) {
+ freearc(nfa, a);
+ }
+ freestate(nfa, s);
}
-
+
/*
- freestate - free a state, which has no in-arcs or out-arcs
^ static VOID freestate(struct nfa *, struct state *);
*/
-static VOID
-freestate(nfa, s)
-struct nfa *nfa;
-struct state *s;
+static void
+freestate(
+ struct nfa *nfa,
+ struct state *s)
{
- assert(s != NULL);
- assert(s->nins == 0 && s->nouts == 0);
-
- s->no = FREESTATE;
- s->flag = 0;
- if (s->next != NULL)
- s->next->prev = s->prev;
- else {
- assert(s == nfa->slast);
- nfa->slast = s->prev;
- }
- if (s->prev != NULL)
- s->prev->next = s->next;
- else {
- assert(s == nfa->states);
- nfa->states = s->next;
- }
- s->prev = NULL;
- s->next = nfa->free; /* don't delete it, put it on the free list */
- nfa->free = s;
- decrement_size(nfa);
+ assert(s != NULL);
+ assert(s->nins == 0 && s->nouts == 0);
+
+ s->no = FREESTATE;
+ s->flag = 0;
+ if (s->next != NULL) {
+ s->next->prev = s->prev;
+ } else {
+ assert(s == nfa->slast);
+ nfa->slast = s->prev;
+ }
+ if (s->prev != NULL) {
+ s->prev->next = s->next;
+ } else {
+ assert(s == nfa->states);
+ nfa->states = s->next;
+ }
+ s->prev = NULL;
+ s->next = nfa->free; /* don't delete it, put it on the free list */
+ nfa->free = s;
+ DecrementSize(nfa);
}
-
+
/*
- destroystate - really get rid of an already-freed state
^ static VOID destroystate(struct nfa *, struct state *);
*/
-static VOID
-destroystate(nfa, s)
-struct nfa *nfa;
-struct state *s;
+static void
+destroystate(
+ struct nfa *nfa,
+ struct state *s)
{
- struct arcbatch *ab;
- struct arcbatch *abnext;
-
- assert(s->no == FREESTATE);
- for (ab = s->oas.next; ab != NULL; ab = abnext) {
- abnext = ab->next;
- FREE(ab);
- }
- s->ins = NULL;
- s->outs = NULL;
- s->next = NULL;
- FREE(s);
+ struct arcbatch *ab;
+ struct arcbatch *abnext;
+
+ assert(s->no == FREESTATE);
+ for (ab=s->oas.next ; ab!=NULL ; ab=abnext) {
+ abnext = ab->next;
+ FREE(ab);
+ }
+ s->ins = NULL;
+ s->outs = NULL;
+ s->next = NULL;
+ FREE(s);
}
-
+
/*
- newarc - set up a new arc within an NFA
- ^ static VOID newarc(struct nfa *, int, pcolor, struct state *,
+ ^ static VOID newarc(struct nfa *, int, pcolor, struct state *,
^ struct state *);
*/
-static VOID
-newarc(nfa, t, co, from, to)
-struct nfa *nfa;
-int t;
-pcolor co;
-struct state *from;
-struct state *to;
+static void
+newarc(
+ struct nfa *nfa,
+ int t,
+ pcolor co,
+ struct state *from,
+ struct state *to)
{
- struct arc *a;
-
- assert(from != NULL && to != NULL);
+ struct arc *a;
- /* check for duplicates */
- for (a = from->outs; a != NULL; a = a->outchain)
- if (a->to == to && a->co == co && a->type == t)
- return;
-
- a = allocarc(nfa, from);
- if (NISERR())
- return;
- assert(a != NULL);
-
- a->type = t;
- a->co = (color)co;
- a->to = to;
- a->from = from;
-
- /*
- * Put the new arc on the beginning, not the end, of the chains.
- * Not only is this easier, it has the very useful side effect that
- * deleting the most-recently-added arc is the cheapest case rather
- * than the most expensive one.
- */
- a->inchain = to->ins;
- to->ins = a;
- a->outchain = from->outs;
- from->outs = a;
+ assert(from != NULL && to != NULL);
- from->nouts++;
- to->nins++;
+ /*
+ * Check for duplicates.
+ */
- if (COLORED(a) && nfa->parent == NULL)
- colorchain(nfa->cm, a);
+ for (a=from->outs ; a!=NULL ; a=a->outchain) {
+ if (a->to == to && a->co == co && a->type == t) {
+ return;
+ }
+ }
+ a = allocarc(nfa, from);
+ if (NISERR()) {
return;
+ }
+ assert(a != NULL);
+
+ a->type = t;
+ a->co = (color) co;
+ a->to = to;
+ a->from = from;
+
+ /*
+ * Put the new arc on the beginning, not the end, of the chains. Not only
+ * is this easier, it has the very useful side effect that deleting the
+ * most-recently-added arc is the cheapest case rather than the most
+ * expensive one.
+ */
+
+ a->inchain = to->ins;
+ to->ins = a;
+ a->outchain = from->outs;
+ from->outs = a;
+
+ from->nouts++;
+ to->nins++;
+
+ if (COLORED(a) && nfa->parent == NULL) {
+ colorchain(nfa->cm, a);
+ }
}
-
+
/*
- allocarc - allocate a new out-arc within a state
^ static struct arc *allocarc(struct nfa *, struct state *);
*/
static struct arc * /* NULL for failure */
-allocarc(nfa, s)
-struct nfa *nfa;
-struct state *s;
+allocarc(
+ struct nfa *nfa,
+ struct state *s)
{
- struct arc *a;
- struct arcbatch *new;
- int i;
+ struct arc *a;
- /* shortcut */
- if (s->free == NULL && s->noas < ABSIZE) {
- a = &s->oas.a[s->noas];
- s->noas++;
- return a;
- }
+ /*
+ * Shortcut
+ */
- /* if none at hand, get more */
- if (s->free == NULL) {
- new = (struct arcbatch *)MALLOC(sizeof(struct arcbatch));
- if (new == NULL) {
- NERR(REG_ESPACE);
- return NULL;
- }
- new->next = s->oas.next;
- s->oas.next = new;
+ if (s->free == NULL && s->noas < ABSIZE) {
+ a = &s->oas.a[s->noas];
+ s->noas++;
+ return a;
+ }
- for (i = 0; i < ABSIZE; i++) {
- new->a[i].type = 0;
- new->a[i].freechain = &new->a[i+1];
- }
- new->a[ABSIZE-1].freechain = NULL;
- s->free = &new->a[0];
+ /*
+ * if none at hand, get more
+ */
+
+ if (s->free == NULL) {
+ struct arcbatch *newAb = (struct arcbatch *)
+ MALLOC(sizeof(struct arcbatch));
+ int i;
+
+ if (newAb == NULL) {
+ NERR(REG_ESPACE);
+ return NULL;
}
- assert(s->free != NULL);
+ newAb->next = s->oas.next;
+ s->oas.next = newAb;
- a = s->free;
- s->free = a->freechain;
- return a;
+ for (i=0 ; i<ABSIZE ; i++) {
+ newAb->a[i].type = 0;
+ newAb->a[i].freechain = &newAb->a[i+1];
+ }
+ newAb->a[ABSIZE-1].freechain = NULL;
+ s->free = &newAb->a[0];
+ }
+ assert(s->free != NULL);
+
+ a = s->free;
+ s->free = a->freechain;
+ return a;
}
-
+
/*
- freearc - free an arc
^ static VOID freearc(struct nfa *, struct arc *);
*/
-static VOID
-freearc(nfa, victim)
-struct nfa *nfa;
-struct arc *victim;
+static void
+freearc(
+ struct nfa *nfa,
+ struct arc *victim)
{
- struct state *from = victim->from;
- struct state *to = victim->to;
- struct arc *a;
-
- assert(victim->type != 0);
-
- /* take it off color chain if necessary */
- if (COLORED(victim) && nfa->parent == NULL)
- uncolorchain(nfa->cm, victim);
-
- /* take it off source's out-chain */
- assert(from != NULL);
- assert(from->outs != NULL);
- a = from->outs;
- if (a == victim) /* simple case: first in chain */
- from->outs = victim->outchain;
- else {
- for (; a != NULL && a->outchain != victim; a = a->outchain)
- continue;
- assert(a != NULL);
- a->outchain = victim->outchain;
+ struct state *from = victim->from;
+ struct state *to = victim->to;
+ struct arc *a;
+
+ assert(victim->type != 0);
+
+ /*
+ * Take it off color chain if necessary.
+ */
+
+ if (COLORED(victim) && nfa->parent == NULL) {
+ uncolorchain(nfa->cm, victim);
+ }
+
+ /*
+ * Take it off source's out-chain.
+ */
+
+ assert(from != NULL);
+ assert(from->outs != NULL);
+ a = from->outs;
+ if (a == victim) { /* simple case: first in chain */
+ from->outs = victim->outchain;
+ } else {
+ for (; a!=NULL && a->outchain!=victim ; a=a->outchain) {
+ continue;
}
- from->nouts--;
-
- /* take it off target's in-chain */
- assert(to != NULL);
- assert(to->ins != NULL);
- a = to->ins;
- if (a == victim) /* simple case: first in chain */
- to->ins = victim->inchain;
- else {
- for (; a != NULL && a->inchain != victim; a = a->inchain)
- continue;
- assert(a != NULL);
- a->inchain = victim->inchain;
+ assert(a != NULL);
+ a->outchain = victim->outchain;
+ }
+ from->nouts--;
+
+ /*
+ * Take it off target's in-chain.
+ */
+
+ assert(to != NULL);
+ assert(to->ins != NULL);
+ a = to->ins;
+ if (a == victim) { /* simple case: first in chain */
+ to->ins = victim->inchain;
+ } else {
+ for (; a->inchain!=victim ; a=a->inchain) {
+ assert(a->inchain != NULL);
+ continue;
}
- to->nins--;
-
- /* clean up and place on free list */
- victim->type = 0;
- victim->from = NULL; /* precautions... */
- victim->to = NULL;
- victim->inchain = NULL;
- victim->outchain = NULL;
- victim->freechain = from->free;
- from->free = victim;
+ a->inchain = victim->inchain;
+ }
+ to->nins--;
+
+ /*
+ * Clean up and place on free list.
+ */
+
+ victim->type = 0;
+ victim->from = NULL; /* precautions... */
+ victim->to = NULL;
+ victim->inchain = NULL;
+ victim->outchain = NULL;
+ victim->freechain = from->free;
+ from->free = victim;
}
-
+
/*
- findarc - find arc, if any, from given source with given type and color
* If there is more than one such arc, the result is random.
^ static struct arc *findarc(struct state *, int, pcolor);
*/
static struct arc *
-findarc(s, type, co)
-struct state *s;
-int type;
-pcolor co;
+findarc(
+ struct state *s,
+ int type,
+ pcolor co)
{
- struct arc *a;
+ struct arc *a;
- for (a = s->outs; a != NULL; a = a->outchain)
- if (a->type == type && a->co == co)
- return a;
- return NULL;
+ for (a=s->outs ; a!=NULL ; a=a->outchain) {
+ if (a->type == type && a->co == co) {
+ return a;
+ }
+ }
+ return NULL;
}
-
+
/*
- cparc - allocate a new arc within an NFA, copying details from old one
- ^ static VOID cparc(struct nfa *, struct arc *, struct state *,
+ ^ static VOID cparc(struct nfa *, struct arc *, struct state *,
^ struct state *);
*/
-static VOID
-cparc(nfa, oa, from, to)
-struct nfa *nfa;
-struct arc *oa;
-struct state *from;
-struct state *to;
+static void
+cparc(
+ struct nfa *nfa,
+ struct arc *oa,
+ struct state *from,
+ struct state *to)
{
- newarc(nfa, oa->type, oa->co, from, to);
+ newarc(nfa, oa->type, oa->co, from, to);
}
-
+
/*
- moveins - move all in arcs of a state to another state
* You might think this could be done better by just updating the
@@ -501,341 +540,365 @@ struct state *to;
* ones to exploit the suppression built into newarc.
^ static VOID moveins(struct nfa *, struct state *, struct state *);
*/
-static VOID
-moveins(nfa, old, new)
-struct nfa *nfa;
-struct state *old;
-struct state *new;
+static void
+moveins(
+ struct nfa *nfa,
+ struct state *oldState,
+ struct state *newState)
{
- struct arc *a;
+ struct arc *a;
- assert(old != new);
+ assert(oldState != newState);
- while ((a = old->ins) != NULL) {
- cparc(nfa, a, a->from, new);
- freearc(nfa, a);
- }
- assert(old->nins == 0);
- assert(old->ins == NULL);
+ while ((a = oldState->ins) != NULL) {
+ cparc(nfa, a, a->from, newState);
+ freearc(nfa, a);
+ }
+ assert(oldState->nins == 0);
+ assert(oldState->ins == NULL);
}
-
+
/*
- copyins - copy all in arcs of a state to another state
^ static VOID copyins(struct nfa *, struct state *, struct state *);
*/
-static VOID
-copyins(nfa, old, new)
-struct nfa *nfa;
-struct state *old;
-struct state *new;
+static void
+copyins(
+ struct nfa *nfa,
+ struct state *oldState,
+ struct state *newState)
{
- struct arc *a;
+ struct arc *a;
- assert(old != new);
+ assert(oldState != newState);
- for (a = old->ins; a != NULL; a = a->inchain)
- cparc(nfa, a, a->from, new);
+ for (a=oldState->ins ; a!=NULL ; a=a->inchain) {
+ cparc(nfa, a, a->from, newState);
+ }
}
-
+
/*
- moveouts - move all out arcs of a state to another state
^ static VOID moveouts(struct nfa *, struct state *, struct state *);
*/
-static VOID
-moveouts(nfa, old, new)
-struct nfa *nfa;
-struct state *old;
-struct state *new;
+static void
+moveouts(
+ struct nfa *nfa,
+ struct state *oldState,
+ struct state *newState)
{
- struct arc *a;
+ struct arc *a;
- assert(old != new);
+ assert(oldState != newState);
- while ((a = old->outs) != NULL) {
- cparc(nfa, a, new, a->to);
- freearc(nfa, a);
- }
+ while ((a = oldState->outs) != NULL) {
+ cparc(nfa, a, newState, a->to);
+ freearc(nfa, a);
+ }
}
-
+
/*
- copyouts - copy all out arcs of a state to another state
^ static VOID copyouts(struct nfa *, struct state *, struct state *);
*/
-static VOID
-copyouts(nfa, old, new)
-struct nfa *nfa;
-struct state *old;
-struct state *new;
+static void
+copyouts(
+ struct nfa *nfa,
+ struct state *oldState,
+ struct state *newState)
{
- struct arc *a;
+ struct arc *a;
- assert(old != new);
+ assert(oldState != newState);
- for (a = old->outs; a != NULL; a = a->outchain)
- cparc(nfa, a, new, a->to);
+ for (a=oldState->outs ; a!=NULL ; a=a->outchain) {
+ cparc(nfa, a, newState, a->to);
+ }
}
-
+
/*
- cloneouts - copy out arcs of a state to another state pair, modifying type
^ static VOID cloneouts(struct nfa *, struct state *, struct state *,
^ struct state *, int);
*/
-static VOID
-cloneouts(nfa, old, from, to, type)
-struct nfa *nfa;
-struct state *old;
-struct state *from;
-struct state *to;
-int type;
+static void
+cloneouts(
+ struct nfa *nfa,
+ struct state *old,
+ struct state *from,
+ struct state *to,
+ int type)
{
- struct arc *a;
+ struct arc *a;
- assert(old != from);
+ assert(old != from);
- for (a = old->outs; a != NULL; a = a->outchain)
- newarc(nfa, type, a->co, from, to);
+ for (a=old->outs ; a!=NULL ; a=a->outchain) {
+ newarc(nfa, type, a->co, from, to);
+ }
}
-
+
/*
- delsub - delete a sub-NFA, updating subre pointers if necessary
* This uses a recursive traversal of the sub-NFA, marking already-seen
* states using their tmp pointer.
^ static VOID delsub(struct nfa *, struct state *, struct state *);
*/
-static VOID
-delsub(nfa, lp, rp)
-struct nfa *nfa;
-struct state *lp; /* the sub-NFA goes from here... */
-struct state *rp; /* ...to here, *not* inclusive */
+static void
+delsub(
+ struct nfa *nfa,
+ struct state *lp, /* the sub-NFA goes from here... */
+ struct state *rp) /* ...to here, *not* inclusive */
{
- assert(lp != rp);
+ assert(lp != rp);
- rp->tmp = rp; /* mark end */
+ rp->tmp = rp; /* mark end */
- deltraverse(nfa, lp, lp);
- assert(lp->nouts == 0 && rp->nins == 0); /* did the job */
- assert(lp->no != FREESTATE && rp->no != FREESTATE); /* no more */
+ deltraverse(nfa, lp, lp);
+ assert(lp->nouts == 0 && rp->nins == 0); /* did the job */
+ assert(lp->no != FREESTATE && rp->no != FREESTATE); /* no more */
- rp->tmp = NULL; /* unmark end */
- lp->tmp = NULL; /* and begin, marked by deltraverse */
+ rp->tmp = NULL; /* unmark end */
+ lp->tmp = NULL; /* and begin, marked by deltraverse */
}
-
+
/*
- deltraverse - the recursive heart of delsub
* This routine's basic job is to destroy all out-arcs of the state.
^ static VOID deltraverse(struct nfa *, struct state *, struct state *);
*/
-static VOID
-deltraverse(nfa, leftend, s)
-struct nfa *nfa;
-struct state *leftend;
-struct state *s;
+static void
+deltraverse(
+ struct nfa *nfa,
+ struct state *leftend,
+ struct state *s)
{
- struct arc *a;
- struct state *to;
-
- if (s->nouts == 0)
- return; /* nothing to do */
- if (s->tmp != NULL)
- return; /* already in progress */
-
- s->tmp = s; /* mark as in progress */
-
- while ((a = s->outs) != NULL) {
- to = a->to;
- deltraverse(nfa, leftend, to);
- assert(to->nouts == 0 || to->tmp != NULL);
- freearc(nfa, a);
- if (to->nins == 0 && to->tmp == NULL) {
- assert(to->nouts == 0);
- freestate(nfa, to);
- }
+ struct arc *a;
+ struct state *to;
+
+ if (s->nouts == 0) {
+ return; /* nothing to do */
+ }
+ if (s->tmp != NULL) {
+ return; /* already in progress */
+ }
+
+ s->tmp = s; /* mark as in progress */
+
+ while ((a = s->outs) != NULL) {
+ to = a->to;
+ deltraverse(nfa, leftend, to);
+ assert(to->nouts == 0 || to->tmp != NULL);
+ freearc(nfa, a);
+ if (to->nins == 0 && to->tmp == NULL) {
+ assert(to->nouts == 0);
+ freestate(nfa, to);
}
+ }
- assert(s->no != FREESTATE); /* we're still here */
- assert(s == leftend || s->nins != 0); /* and still reachable */
- assert(s->nouts == 0); /* but have no outarcs */
+ assert(s->no != FREESTATE); /* we're still here */
+ assert(s == leftend || s->nins != 0); /* and still reachable */
+ assert(s->nouts == 0); /* but have no outarcs */
- s->tmp = NULL; /* we're done here */
+ s->tmp = NULL; /* we're done here */
}
-
+
/*
- dupnfa - duplicate sub-NFA
- * Another recursive traversal, this time using tmp to point to duplicates
- * as well as mark already-seen states. (You knew there was a reason why
- * it's a state pointer, didn't you? :-))
- ^ static VOID dupnfa(struct nfa *, struct state *, struct state *,
+ * Another recursive traversal, this time using tmp to point to duplicates as
+ * well as mark already-seen states. (You knew there was a reason why it's a
+ * state pointer, didn't you? :-))
+ ^ static VOID dupnfa(struct nfa *, struct state *, struct state *,
^ struct state *, struct state *);
*/
-static VOID
-dupnfa(nfa, start, stop, from, to)
-struct nfa *nfa;
-struct state *start; /* duplicate of subNFA starting here */
-struct state *stop; /* and stopping here */
-struct state *from; /* stringing duplicate from here */
-struct state *to; /* to here */
+static void
+dupnfa(
+ struct nfa *nfa,
+ struct state *start, /* duplicate of subNFA starting here */
+ struct state *stop, /* and stopping here */
+ struct state *from, /* stringing duplicate from here */
+ struct state *to) /* to here */
{
- if (start == stop) {
- newarc(nfa, EMPTY, 0, from, to);
- return;
- }
+ if (start == stop) {
+ newarc(nfa, EMPTY, 0, from, to);
+ return;
+ }
- stop->tmp = to;
- duptraverse(nfa, start, from);
- /* done, except for clearing out the tmp pointers */
+ stop->tmp = to;
+ duptraverse(nfa, start, from);
+ /* done, except for clearing out the tmp pointers */
- stop->tmp = NULL;
- cleartraverse(nfa, start);
+ stop->tmp = NULL;
+ cleartraverse(nfa, start);
}
-
+
/*
- duptraverse - recursive heart of dupnfa
^ static VOID duptraverse(struct nfa *, struct state *, struct state *);
*/
-static VOID
-duptraverse(nfa, s, stmp)
-struct nfa *nfa;
-struct state *s;
-struct state *stmp; /* s's duplicate, or NULL */
+static void
+duptraverse(
+ struct nfa *nfa,
+ struct state *s,
+ struct state *stmp) /* s's duplicate, or NULL */
{
- struct arc *a;
+ struct arc *a;
- if (s->tmp != NULL)
- return; /* already done */
+ if (s->tmp != NULL) {
+ return; /* already done */
+ }
- s->tmp = (stmp == NULL) ? newstate(nfa) : stmp;
- if (s->tmp == NULL) {
- assert(NISERR());
- return;
- }
+ s->tmp = (stmp == NULL) ? newstate(nfa) : stmp;
+ if (s->tmp == NULL) {
+ assert(NISERR());
+ return;
+ }
- for (a = s->outs; a != NULL && !NISERR(); a = a->outchain) {
- duptraverse(nfa, a->to, (struct state *)NULL);
- if (NISERR())
- break;
- assert(a->to->tmp != NULL);
- cparc(nfa, a, s->tmp, a->to->tmp);
+ for (a=s->outs ; a!=NULL && !NISERR() ; a=a->outchain) {
+ duptraverse(nfa, a->to, NULL);
+ if (NISERR()) {
+ break;
}
+ assert(a->to->tmp != NULL);
+ cparc(nfa, a, s->tmp, a->to->tmp);
+ }
}
-
+
/*
- cleartraverse - recursive cleanup for algorithms that leave tmp ptrs set
^ static VOID cleartraverse(struct nfa *, struct state *);
*/
-static VOID
-cleartraverse(nfa, s)
-struct nfa *nfa;
-struct state *s;
+static void
+cleartraverse(
+ struct nfa *nfa,
+ struct state *s)
{
- struct arc *a;
+ struct arc *a;
- if (s->tmp == NULL)
- return;
- s->tmp = NULL;
+ if (s->tmp == NULL) {
+ return;
+ }
+ s->tmp = NULL;
- for (a = s->outs; a != NULL; a = a->outchain)
- cleartraverse(nfa, a->to);
+ for (a=s->outs ; a!=NULL ; a=a->outchain) {
+ cleartraverse(nfa, a->to);
+ }
}
-
+
/*
- specialcolors - fill in special colors for an NFA
^ static VOID specialcolors(struct nfa *);
*/
-static VOID
-specialcolors(nfa)
-struct nfa *nfa;
+static void
+specialcolors(
+ struct nfa *nfa)
{
- /* false colors for BOS, BOL, EOS, EOL */
- if (nfa->parent == NULL) {
- nfa->bos[0] = pseudocolor(nfa->cm);
- nfa->bos[1] = pseudocolor(nfa->cm);
- nfa->eos[0] = pseudocolor(nfa->cm);
- nfa->eos[1] = pseudocolor(nfa->cm);
- } else {
- assert(nfa->parent->bos[0] != COLORLESS);
- nfa->bos[0] = nfa->parent->bos[0];
- assert(nfa->parent->bos[1] != COLORLESS);
- nfa->bos[1] = nfa->parent->bos[1];
- assert(nfa->parent->eos[0] != COLORLESS);
- nfa->eos[0] = nfa->parent->eos[0];
- assert(nfa->parent->eos[1] != COLORLESS);
- nfa->eos[1] = nfa->parent->eos[1];
- }
+ /*
+ * False colors for BOS, BOL, EOS, EOL
+ */
+
+ if (nfa->parent == NULL) {
+ nfa->bos[0] = pseudocolor(nfa->cm);
+ nfa->bos[1] = pseudocolor(nfa->cm);
+ nfa->eos[0] = pseudocolor(nfa->cm);
+ nfa->eos[1] = pseudocolor(nfa->cm);
+ } else {
+ assert(nfa->parent->bos[0] != COLORLESS);
+ nfa->bos[0] = nfa->parent->bos[0];
+ assert(nfa->parent->bos[1] != COLORLESS);
+ nfa->bos[1] = nfa->parent->bos[1];
+ assert(nfa->parent->eos[0] != COLORLESS);
+ nfa->eos[0] = nfa->parent->eos[0];
+ assert(nfa->parent->eos[1] != COLORLESS);
+ nfa->eos[1] = nfa->parent->eos[1];
+ }
}
-
+
/*
- optimize - optimize an NFA
^ static long optimize(struct nfa *, FILE *);
*/
static long /* re_info bits */
-optimize(nfa, f)
-struct nfa *nfa;
-FILE *f; /* for debug output; NULL none */
+optimize(
+ struct nfa *nfa,
+ FILE *f) /* for debug output; NULL none */
{
- int verbose = (f != NULL) ? 1 : 0;
-
- if (verbose)
- fprintf(f, "\ninitial cleanup:\n");
- cleanup(nfa); /* may simplify situation */
- if (verbose)
- dumpnfa(nfa, f);
- if (verbose)
- fprintf(f, "\nempties:\n");
- fixempties(nfa, f); /* get rid of EMPTY arcs */
- if (verbose)
- fprintf(f, "\nconstraints:\n");
- pullback(nfa, f); /* pull back constraints backward */
- pushfwd(nfa, f); /* push fwd constraints forward */
- if (verbose)
- fprintf(f, "\nfinal cleanup:\n");
- cleanup(nfa); /* final tidying */
- return analyze(nfa); /* and analysis */
+ int verbose = (f != NULL) ? 1 : 0;
+
+ if (verbose) {
+ fprintf(f, "\ninitial cleanup:\n");
+ }
+ cleanup(nfa); /* may simplify situation */
+ if (verbose) {
+ dumpnfa(nfa, f);
+ }
+ if (verbose) {
+ fprintf(f, "\nempties:\n");
+ }
+ fixempties(nfa, f); /* get rid of EMPTY arcs */
+ if (verbose) {
+ fprintf(f, "\nconstraints:\n");
+ }
+ pullback(nfa, f); /* pull back constraints backward */
+ pushfwd(nfa, f); /* push fwd constraints forward */
+ if (verbose) {
+ fprintf(f, "\nfinal cleanup:\n");
+ }
+ cleanup(nfa); /* final tidying */
+ return analyze(nfa); /* and analysis */
}
-
+
/*
- pullback - pull back constraints backward to (with luck) eliminate them
^ static VOID pullback(struct nfa *, FILE *);
*/
-static VOID
-pullback(nfa, f)
-struct nfa *nfa;
-FILE *f; /* for debug output; NULL none */
+static void
+pullback(
+ struct nfa *nfa,
+ FILE *f) /* for debug output; NULL none */
{
- struct state *s;
- struct state *nexts;
- struct arc *a;
- struct arc *nexta;
- int progress;
-
- /* find and pull until there are no more */
- do {
- progress = 0;
- for (s = nfa->states; s != NULL && !NISERR(); s = nexts) {
- nexts = s->next;
- for (a = s->outs; a != NULL && !NISERR(); a = nexta) {
- nexta = a->outchain;
- if (a->type == '^' || a->type == BEHIND)
- if (pull(nfa, a))
- progress = 1;
- assert(nexta == NULL || s->no != FREESTATE);
- }
- }
- if (progress && f != NULL)
- dumpnfa(nfa, f);
- } while (progress && !NISERR());
- if (NISERR())
- return;
-
- for (a = nfa->pre->outs; a != NULL; a = nexta) {
+ struct state *s;
+ struct state *nexts;
+ struct arc *a;
+ struct arc *nexta;
+ int progress;
+
+ /*
+ * Find and pull until there are no more.
+ */
+
+ do {
+ progress = 0;
+ for (s=nfa->states ; s!=NULL && !NISERR() ; s=nexts) {
+ nexts = s->next;
+ for (a=s->outs ; a!=NULL && !NISERR() ; a=nexta) {
nexta = a->outchain;
- if (a->type == '^') {
- assert(a->co == 0 || a->co == 1);
- newarc(nfa, PLAIN, nfa->bos[a->co], a->from, a->to);
- freearc(nfa, a);
+ if (a->type == '^' || a->type == BEHIND) {
+ if (pull(nfa, a)) {
+ progress = 1;
+ }
}
+ assert(nexta == NULL || s->no != FREESTATE);
+ }
}
+ if (progress && f != NULL) {
+ dumpnfa(nfa, f);
+ }
+ } while (progress && !NISERR());
+ if (NISERR()) {
+ return;
+ }
+
+ for (a=nfa->pre->outs ; a!=NULL ; a=nexta) {
+ nexta = a->outchain;
+ if (a->type == '^') {
+ assert(a->co == 0 || a->co == 1);
+ newarc(nfa, PLAIN, nfa->bos[a->co], a->from, a->to);
+ freearc(nfa, a);
+ }
+ }
}
-
+
/*
- pull - pull a back constraint backward past its source state
* A significant property of this function is that it deletes at most
@@ -844,136 +907,155 @@ FILE *f; /* for debug output; NULL none */
^ static int pull(struct nfa *, struct arc *);
*/
static int /* 0 couldn't, 1 could */
-pull(nfa, con)
-struct nfa *nfa;
-struct arc *con;
+pull(
+ struct nfa *nfa,
+ struct arc *con)
{
- struct state *from = con->from;
- struct state *to = con->to;
- struct arc *a;
- struct arc *nexta;
- struct state *s;
-
- if (from == to) { /* circular constraint is pointless */
- freearc(nfa, con);
- return 1;
- }
- if (from->flag) /* can't pull back beyond start */
- return 0;
- if (from->nins == 0) { /* unreachable */
- freearc(nfa, con);
- return 1;
- }
+ struct state *from = con->from;
+ struct state *to = con->to;
+ struct arc *a;
+ struct arc *nexta;
+ struct state *s;
+
+ if (from == to) { /* circular constraint is pointless */
+ freearc(nfa, con);
+ return 1;
+ }
+ if (from->flag) { /* can't pull back beyond start */
+ return 0;
+ }
+ if (from->nins == 0) { /* unreachable */
+ freearc(nfa, con);
+ return 1;
+ }
- /*
- * DGP 2007-11-15: Cloning a state with a circular constraint on its
- * list of outs can lead to trouble [Bug 1810038], so get rid of them
- * first.
- */
+ /*
+ * DGP 2007-11-15: Cloning a state with a circular constraint on its list
+ * of outs can lead to trouble [Bug 1810038], so get rid of them first.
+ */
- for (a = from->outs; a != NULL; a = nexta) {
- nexta = a->outchain;
- switch (a->type) {
- case '^':
- case '$':
- case BEHIND:
- case AHEAD:
- if (from == a->to) {
- freearc(nfa, a);
- }
- break;
- }
+ for (a = from->outs; a != NULL; a = nexta) {
+ nexta = a->outchain;
+ switch (a->type) {
+ case '^':
+ case '$':
+ case BEHIND:
+ case AHEAD:
+ if (from == a->to) {
+ freearc(nfa, a);
+ }
+ break;
}
+ }
- /* first, clone from state if necessary to avoid other outarcs */
- if (from->nouts > 1) {
- s = newstate(nfa);
- if (NISERR())
- return 0;
- assert(to != from); /* con is not an inarc */
- copyins(nfa, from, s); /* duplicate inarcs */
- cparc(nfa, con, s, to); /* move constraint arc */
- freearc(nfa, con);
- from = s;
- con = from->outs;
- }
- assert(from->nouts == 1);
+ /*
+ * First, clone from state if necessary to avoid other outarcs.
+ */
- /* propagate the constraint into the from state's inarcs */
- for (a = from->ins; a != NULL; a = nexta) {
- nexta = a->inchain;
- switch (combine(con, a)) {
- case INCOMPATIBLE: /* destroy the arc */
- freearc(nfa, a);
- break;
- case SATISFIED: /* no action needed */
- break;
- case COMPATIBLE: /* swap the two arcs, more or less */
- s = newstate(nfa);
- if (NISERR())
- return 0;
- cparc(nfa, a, s, to); /* anticipate move */
- cparc(nfa, con, a->from, s);
- if (NISERR())
- return 0;
- freearc(nfa, a);
- break;
- default:
- assert(NOTREACHED);
- break;
- }
+ if (from->nouts > 1) {
+ s = newstate(nfa);
+ if (NISERR()) {
+ return 0;
}
+ assert(to != from); /* con is not an inarc */
+ copyins(nfa, from, s); /* duplicate inarcs */
+ cparc(nfa, con, s, to); /* move constraint arc */
+ freearc(nfa, con);
+ from = s;
+ con = from->outs;
+ }
+ assert(from->nouts == 1);
+
+ /*
+ * Propagate the constraint into the from state's inarcs.
+ */
+
+ for (a=from->ins ; a!=NULL ; a=nexta) {
+ nexta = a->inchain;
+ switch (combine(con, a)) {
+ case INCOMPATIBLE: /* destroy the arc */
+ freearc(nfa, a);
+ break;
+ case SATISFIED: /* no action needed */
+ break;
+ case COMPATIBLE: /* swap the two arcs, more or less */
+ s = newstate(nfa);
+ if (NISERR()) {
+ return 0;
+ }
+ cparc(nfa, a, s, to); /* anticipate move */
+ cparc(nfa, con, a->from, s);
+ if (NISERR()) {
+ return 0;
+ }
+ freearc(nfa, a);
+ break;
+ default:
+ assert(NOTREACHED);
+ break;
+ }
+ }
- /* remaining inarcs, if any, incorporate the constraint */
- moveins(nfa, from, to);
- dropstate(nfa, from); /* will free the constraint */
- return 1;
-}
+ /*
+ * Remaining inarcs, if any, incorporate the constraint.
+ */
+ moveins(nfa, from, to);
+ dropstate(nfa, from); /* will free the constraint */
+ return 1;
+}
+
/*
- pushfwd - push forward constraints forward to (with luck) eliminate them
^ static VOID pushfwd(struct nfa *, FILE *);
*/
-static VOID
-pushfwd(nfa, f)
-struct nfa *nfa;
-FILE *f; /* for debug output; NULL none */
+static void
+pushfwd(
+ struct nfa *nfa,
+ FILE *f) /* for debug output; NULL none */
{
- struct state *s;
- struct state *nexts;
- struct arc *a;
- struct arc *nexta;
- int progress;
-
- /* find and push until there are no more */
- do {
- progress = 0;
- for (s = nfa->states; s != NULL && !NISERR(); s = nexts) {
- nexts = s->next;
- for (a = s->ins; a != NULL && !NISERR(); a = nexta) {
- nexta = a->inchain;
- if (a->type == '$' || a->type == AHEAD)
- if (push(nfa, a))
- progress = 1;
- assert(nexta == NULL || s->no != FREESTATE);
- }
- }
- if (progress && f != NULL)
- dumpnfa(nfa, f);
- } while (progress && !NISERR());
- if (NISERR())
- return;
-
- for (a = nfa->post->ins; a != NULL; a = nexta) {
+ struct state *s;
+ struct state *nexts;
+ struct arc *a;
+ struct arc *nexta;
+ int progress;
+
+ /*
+ * Find and push until there are no more.
+ */
+
+ do {
+ progress = 0;
+ for (s=nfa->states ; s!=NULL && !NISERR() ; s=nexts) {
+ nexts = s->next;
+ for (a = s->ins; a != NULL && !NISERR(); a = nexta) {
nexta = a->inchain;
- if (a->type == '$') {
- assert(a->co == 0 || a->co == 1);
- newarc(nfa, PLAIN, nfa->eos[a->co], a->from, a->to);
- freearc(nfa, a);
+ if (a->type == '$' || a->type == AHEAD) {
+ if (push(nfa, a)) {
+ progress = 1;
+ }
}
+ assert(nexta == NULL || s->no != FREESTATE);
+ }
+ }
+ if (progress && f != NULL) {
+ dumpnfa(nfa, f);
}
+ } while (progress && !NISERR());
+ if (NISERR()) {
+ return;
+ }
+
+ for (a = nfa->post->ins; a != NULL; a = nexta) {
+ nexta = a->inchain;
+ if (a->type == '$') {
+ assert(a->co == 0 || a->co == 1);
+ newarc(nfa, PLAIN, nfa->eos[a->co], a->from, a->to);
+ freearc(nfa, a);
+ }
+ }
}
-
+
/*
- push - push a forward constraint forward past its destination state
* A significant property of this function is that it deletes at most
@@ -982,94 +1064,106 @@ FILE *f; /* for debug output; NULL none */
^ static int push(struct nfa *, struct arc *);
*/
static int /* 0 couldn't, 1 could */
-push(nfa, con)
-struct nfa *nfa;
-struct arc *con;
+push(
+ struct nfa *nfa,
+ struct arc *con)
{
- struct state *from = con->from;
- struct state *to = con->to;
- struct arc *a;
- struct arc *nexta;
- struct state *s;
-
- if (to == from) { /* circular constraint is pointless */
- freearc(nfa, con);
- return 1;
- }
- if (to->flag) /* can't push forward beyond end */
- return 0;
- if (to->nouts == 0) { /* dead end */
- freearc(nfa, con);
- return 1;
+ struct state *from = con->from;
+ struct state *to = con->to;
+ struct arc *a;
+ struct arc *nexta;
+ struct state *s;
+
+ if (to == from) { /* circular constraint is pointless */
+ freearc(nfa, con);
+ return 1;
+ }
+ if (to->flag) { /* can't push forward beyond end */
+ return 0;
+ }
+ if (to->nouts == 0) { /* dead end */
+ freearc(nfa, con);
+ return 1;
+ }
+
+ /*
+ * DGP 2007-11-15: Here we duplicate the same protections as appear
+ * in pull() above to avoid troubles with cloning a state with a
+ * circular constraint on its list of ins. It is not clear whether
+ * this is necessary, or is protecting against a "can't happen".
+ * Any test case that actually leads to a freearc() call here would
+ * be a welcome addition to the test suite.
+ */
+
+ for (a = to->ins; a != NULL; a = nexta) {
+ nexta = a->inchain;
+ switch (a->type) {
+ case '^':
+ case '$':
+ case BEHIND:
+ case AHEAD:
+ if (a->from == to) {
+ freearc(nfa, a);
+ }
+ break;
}
+ }
+ /*
+ * First, clone to state if necessary to avoid other inarcs.
+ */
- /*
- * DGP 2007-11-15: Here we duplicate the same protections as appear
- * in pull() above to avoid troubles with cloning a state with a
- * circular constraint on its list of ins. It is not clear whether
- * this is necessary, or is protecting against a "can't happen".
- * Any test case that actually leads to a freearc() call here would
- * be a welcome addition to the test suite.
- */
-
- for (a = to->ins; a != NULL; a = nexta) {
- nexta = a->inchain;
- switch (a->type) {
- case '^':
- case '$':
- case BEHIND:
- case AHEAD:
- if (a->from == to) {
- freearc(nfa, a);
- }
- break;
- }
+ if (to->nins > 1) {
+ s = newstate(nfa);
+ if (NISERR()) {
+ return 0;
}
-
- /* first, clone to state if necessary to avoid other inarcs */
- if (to->nins > 1) {
- s = newstate(nfa);
- if (NISERR())
- return 0;
- copyouts(nfa, to, s); /* duplicate outarcs */
- cparc(nfa, con, from, s); /* move constraint */
- freearc(nfa, con);
- to = s;
- con = to->ins;
+ copyouts(nfa, to, s); /* duplicate outarcs */
+ cparc(nfa, con, from, s); /* move constraint */
+ freearc(nfa, con);
+ to = s;
+ con = to->ins;
+ }
+ assert(to->nins == 1);
+
+ /*
+ * Propagate the constraint into the to state's outarcs.
+ */
+
+ for (a = to->outs; a != NULL; a = nexta) {
+ nexta = a->outchain;
+ switch (combine(con, a)) {
+ case INCOMPATIBLE: /* destroy the arc */
+ freearc(nfa, a);
+ break;
+ case SATISFIED: /* no action needed */
+ break;
+ case COMPATIBLE: /* swap the two arcs, more or less */
+ s = newstate(nfa);
+ if (NISERR()) {
+ return 0;
+ }
+ cparc(nfa, con, s, a->to); /* anticipate move */
+ cparc(nfa, a, from, s);
+ if (NISERR()) {
+ return 0;
+ }
+ freearc(nfa, a);
+ break;
+ default:
+ assert(NOTREACHED);
+ break;
}
- assert(to->nins == 1);
+ }
- /* propagate the constraint into the to state's outarcs */
- for (a = to->outs; a != NULL; a = nexta) {
- nexta = a->outchain;
- switch (combine(con, a)) {
- case INCOMPATIBLE: /* destroy the arc */
- freearc(nfa, a);
- break;
- case SATISFIED: /* no action needed */
- break;
- case COMPATIBLE: /* swap the two arcs, more or less */
- s = newstate(nfa);
- if (NISERR())
- return 0;
- cparc(nfa, con, s, a->to); /* anticipate move */
- cparc(nfa, a, from, s);
- if (NISERR())
- return 0;
- freearc(nfa, a);
- break;
- default:
- assert(NOTREACHED);
- break;
- }
- }
+ /*
+ * Remaining outarcs, if any, incorporate the constraint.
+ */
- /* remaining outarcs, if any, incorporate the constraint */
- moveouts(nfa, to, from);
- dropstate(nfa, to); /* will free the constraint */
- return 1;
+ moveouts(nfa, to, from);
+ dropstate(nfa, to); /* will free the constraint */
+ return 1;
}
-
+
/*
- combine - constraint lands on an arc, what happens?
^ #def INCOMPATIBLE 1 // destroys arc
@@ -1078,397 +1172,450 @@ struct arc *con;
^ static int combine(struct arc *, struct arc *);
*/
static int
-combine(con, a)
-struct arc *con;
-struct arc *a;
+combine(
+ struct arc *con,
+ struct arc *a)
{
-# define CA(ct,at) (((ct)<<CHAR_BIT) | (at))
-
- switch (CA(con->type, a->type)) {
- case CA('^', PLAIN): /* newlines are handled separately */
- case CA('$', PLAIN):
- return INCOMPATIBLE;
- break;
- case CA(AHEAD, PLAIN): /* color constraints meet colors */
- case CA(BEHIND, PLAIN):
- if (con->co == a->co)
- return SATISFIED;
- return INCOMPATIBLE;
- break;
- case CA('^', '^'): /* collision, similar constraints */
- case CA('$', '$'):
- case CA(AHEAD, AHEAD):
- case CA(BEHIND, BEHIND):
- if (con->co == a->co) /* true duplication */
- return SATISFIED;
- return INCOMPATIBLE;
- break;
- case CA('^', BEHIND): /* collision, dissimilar constraints */
- case CA(BEHIND, '^'):
- case CA('$', AHEAD):
- case CA(AHEAD, '$'):
- return INCOMPATIBLE;
- break;
- case CA('^', '$'): /* constraints passing each other */
- case CA('^', AHEAD):
- case CA(BEHIND, '$'):
- case CA(BEHIND, AHEAD):
- case CA('$', '^'):
- case CA('$', BEHIND):
- case CA(AHEAD, '^'):
- case CA(AHEAD, BEHIND):
- case CA('^', LACON):
- case CA(BEHIND, LACON):
- case CA('$', LACON):
- case CA(AHEAD, LACON):
- return COMPATIBLE;
- break;
+#define CA(ct,at) (((ct)<<CHAR_BIT) | (at))
+
+ switch (CA(con->type, a->type)) {
+ case CA('^', PLAIN): /* newlines are handled separately */
+ case CA('$', PLAIN):
+ return INCOMPATIBLE;
+ break;
+ case CA(AHEAD, PLAIN): /* color constraints meet colors */
+ case CA(BEHIND, PLAIN):
+ if (con->co == a->co) {
+ return SATISFIED;
+ }
+ return INCOMPATIBLE;
+ break;
+ case CA('^', '^'): /* collision, similar constraints */
+ case CA('$', '$'):
+ case CA(AHEAD, AHEAD):
+ case CA(BEHIND, BEHIND):
+ if (con->co == a->co) { /* true duplication */
+ return SATISFIED;
}
- assert(NOTREACHED);
- return INCOMPATIBLE; /* for benefit of blind compilers */
+ return INCOMPATIBLE;
+ break;
+ case CA('^', BEHIND): /* collision, dissimilar constraints */
+ case CA(BEHIND, '^'):
+ case CA('$', AHEAD):
+ case CA(AHEAD, '$'):
+ return INCOMPATIBLE;
+ break;
+ case CA('^', '$'): /* constraints passing each other */
+ case CA('^', AHEAD):
+ case CA(BEHIND, '$'):
+ case CA(BEHIND, AHEAD):
+ case CA('$', '^'):
+ case CA('$', BEHIND):
+ case CA(AHEAD, '^'):
+ case CA(AHEAD, BEHIND):
+ case CA('^', LACON):
+ case CA(BEHIND, LACON):
+ case CA('$', LACON):
+ case CA(AHEAD, LACON):
+ return COMPATIBLE;
+ break;
+ }
+ assert(NOTREACHED);
+ return INCOMPATIBLE; /* for benefit of blind compilers */
}
-
+
/*
- fixempties - get rid of EMPTY arcs
^ static VOID fixempties(struct nfa *, FILE *);
*/
-static VOID
-fixempties(nfa, f)
-struct nfa *nfa;
-FILE *f; /* for debug output; NULL none */
+static void
+fixempties(
+ struct nfa *nfa,
+ FILE *f) /* for debug output; NULL none */
{
- struct state *s;
- struct state *nexts;
- struct arc *a;
- struct arc *nexta;
- int progress;
-
- /* find and eliminate empties until there are no more */
- do {
- progress = 0;
- for (s = nfa->states; s != NULL && !NISERR()
- && s->no != FREESTATE; s = nexts) {
- nexts = s->next;
- for (a = s->outs; a != NULL && !NISERR(); a = nexta) {
- nexta = a->outchain;
- if (a->type == EMPTY && unempty(nfa, a))
- progress = 1;
- assert(nexta == NULL || s->no != FREESTATE);
- }
+ struct state *s;
+ struct state *nexts;
+ struct arc *a;
+ struct arc *nexta;
+ int progress;
+
+ /*
+ * Find and eliminate empties until there are no more.
+ */
+
+ do {
+ progress = 0;
+ for (s = nfa->states; s != NULL && !NISERR()
+ && s->no != FREESTATE; s = nexts) {
+ nexts = s->next;
+ for (a = s->outs; a != NULL && !NISERR(); a = nexta) {
+ nexta = a->outchain;
+ if (a->type == EMPTY && unempty(nfa, a)) {
+ progress = 1;
}
- if (progress && f != NULL)
- dumpnfa(nfa, f);
- } while (progress && !NISERR());
+ assert(nexta == NULL || s->no != FREESTATE);
+ }
+ }
+ if (progress && f != NULL) {
+ dumpnfa(nfa, f);
+ }
+ } while (progress && !NISERR());
}
-
+
/*
- unempty - optimize out an EMPTY arc, if possible
- * Actually, as it stands this function always succeeds, but the return
- * value is kept with an eye on possible future changes.
+ * Actually, as it stands this function always succeeds, but the return value
+ * is kept with an eye on possible future changes.
^ static int unempty(struct nfa *, struct arc *);
*/
static int /* 0 couldn't, 1 could */
-unempty(nfa, a)
-struct nfa *nfa;
-struct arc *a;
+unempty(
+ struct nfa *nfa,
+ struct arc *a)
{
- struct state *from = a->from;
- struct state *to = a->to;
- int usefrom; /* work on from, as opposed to to? */
+ struct state *from = a->from;
+ struct state *to = a->to;
+ int usefrom; /* work on from, as opposed to to? */
- assert(a->type == EMPTY);
- assert(from != nfa->pre && to != nfa->post);
+ assert(a->type == EMPTY);
+ assert(from != nfa->pre && to != nfa->post);
- if (from == to) { /* vacuous loop */
- freearc(nfa, a);
- return 1;
+ if (from == to) { /* vacuous loop */
+ freearc(nfa, a);
+ return 1;
+ }
+
+ /*
+ * Decide which end to work on.
+ */
+
+ usefrom = 1; /* default: attack from */
+ if (from->nouts > to->nins) {
+ usefrom = 0;
+ } else if (from->nouts == to->nins) {
+ /*
+ * Decide on secondary issue: move/copy fewest arcs.
+ */
+
+ if (from->nins > to->nouts) {
+ usefrom = 0;
}
+ }
- /* decide which end to work on */
- usefrom = 1; /* default: attack from */
- if (from->nouts > to->nins)
- usefrom = 0;
- else if (from->nouts == to->nins) {
- /* decide on secondary issue: move/copy fewest arcs */
- if (from->nins > to->nouts)
- usefrom = 0;
+ freearc(nfa, a);
+ if (usefrom) {
+ if (from->nouts == 0) {
+ /*
+ * Was the state's only outarc.
+ */
+
+ moveins(nfa, from, to);
+ freestate(nfa, from);
+ } else {
+ copyins(nfa, from, to);
}
-
- freearc(nfa, a);
- if (usefrom) {
- if (from->nouts == 0) {
- /* was the state's only outarc */
- moveins(nfa, from, to);
- freestate(nfa, from);
- } else
- copyins(nfa, from, to);
+ } else {
+ if (to->nins == 0) {
+ /*
+ * Was the state's only inarc.
+ */
+
+ moveouts(nfa, to, from);
+ freestate(nfa, to);
} else {
- if (to->nins == 0) {
- /* was the state's only inarc */
- moveouts(nfa, to, from);
- freestate(nfa, to);
- } else
- copyouts(nfa, to, from);
+ copyouts(nfa, to, from);
}
+ }
- return 1;
+ return 1;
}
-
+
/*
- cleanup - clean up NFA after optimizations
^ static VOID cleanup(struct nfa *);
*/
-static VOID
-cleanup(nfa)
-struct nfa *nfa;
+static void
+cleanup(
+ struct nfa *nfa)
{
- struct state *s;
- struct state *nexts;
- int n;
-
- /* clear out unreachable or dead-end states */
- /* use pre to mark reachable, then post to mark can-reach-post */
- markreachable(nfa, nfa->pre, (struct state *)NULL, nfa->pre);
- markcanreach(nfa, nfa->post, nfa->pre, nfa->post);
- for (s = nfa->states; s != NULL; s = nexts) {
- nexts = s->next;
- if (s->tmp != nfa->post && !s->flag)
- dropstate(nfa, s);
+ struct state *s;
+ struct state *nexts;
+ int n;
+
+ /*
+ * Clear out unreachable or dead-end states. Use pre to mark reachable,
+ * then post to mark can-reach-post.
+ */
+
+ markreachable(nfa, nfa->pre, NULL, nfa->pre);
+ markcanreach(nfa, nfa->post, nfa->pre, nfa->post);
+ for (s = nfa->states; s != NULL; s = nexts) {
+ nexts = s->next;
+ if (s->tmp != nfa->post && !s->flag) {
+ dropstate(nfa, s);
}
- assert(nfa->post->nins == 0 || nfa->post->tmp == nfa->post);
- cleartraverse(nfa, nfa->pre);
- assert(nfa->post->nins == 0 || nfa->post->tmp == NULL);
- /* the nins==0 (final unreachable) case will be caught later */
-
- /* renumber surviving states */
- n = 0;
- for (s = nfa->states; s != NULL; s = s->next)
- s->no = n++;
- nfa->nstates = n;
+ }
+ assert(nfa->post->nins == 0 || nfa->post->tmp == nfa->post);
+ cleartraverse(nfa, nfa->pre);
+ assert(nfa->post->nins == 0 || nfa->post->tmp == NULL);
+ /* the nins==0 (final unreachable) case will be caught later */
+
+ /*
+ * Renumber surviving states.
+ */
+
+ n = 0;
+ for (s = nfa->states; s != NULL; s = s->next) {
+ s->no = n++;
+ }
+ nfa->nstates = n;
}
-
+
/*
- markreachable - recursive marking of reachable states
^ static VOID markreachable(struct nfa *, struct state *, struct state *,
^ struct state *);
*/
-static VOID
-markreachable(nfa, s, okay, mark)
-struct nfa *nfa;
-struct state *s;
-struct state *okay; /* consider only states with this mark */
-struct state *mark; /* the value to mark with */
+static void
+markreachable(
+ struct nfa *nfa,
+ struct state *s,
+ struct state *okay, /* consider only states with this mark */
+ struct state *mark) /* the value to mark with */
{
- struct arc *a;
+ struct arc *a;
- if (s->tmp != okay)
- return;
- s->tmp = mark;
+ if (s->tmp != okay) {
+ return;
+ }
+ s->tmp = mark;
- for (a = s->outs; a != NULL; a = a->outchain)
- markreachable(nfa, a->to, okay, mark);
+ for (a = s->outs; a != NULL; a = a->outchain) {
+ markreachable(nfa, a->to, okay, mark);
+ }
}
-
+
/*
- markcanreach - recursive marking of states which can reach here
^ static VOID markcanreach(struct nfa *, struct state *, struct state *,
^ struct state *);
*/
-static VOID
-markcanreach(nfa, s, okay, mark)
-struct nfa *nfa;
-struct state *s;
-struct state *okay; /* consider only states with this mark */
-struct state *mark; /* the value to mark with */
+static void
+markcanreach(
+ struct nfa *nfa,
+ struct state *s,
+ struct state *okay, /* consider only states with this mark */
+ struct state *mark) /* the value to mark with */
{
- struct arc *a;
+ struct arc *a;
- if (s->tmp != okay)
- return;
- s->tmp = mark;
+ if (s->tmp != okay) {
+ return;
+ }
+ s->tmp = mark;
- for (a = s->ins; a != NULL; a = a->inchain)
- markcanreach(nfa, a->from, okay, mark);
+ for (a = s->ins; a != NULL; a = a->inchain) {
+ markcanreach(nfa, a->from, okay, mark);
+ }
}
-
+
/*
- analyze - ascertain potentially-useful facts about an optimized NFA
^ static long analyze(struct nfa *);
*/
static long /* re_info bits to be ORed in */
-analyze(nfa)
-struct nfa *nfa;
+analyze(
+ struct nfa *nfa)
{
- struct arc *a;
- struct arc *aa;
-
- if (nfa->pre->outs == NULL)
- return REG_UIMPOSSIBLE;
- for (a = nfa->pre->outs; a != NULL; a = a->outchain)
- for (aa = a->to->outs; aa != NULL; aa = aa->outchain)
- if (aa->to == nfa->post)
- return REG_UEMPTYMATCH;
- return 0;
+ struct arc *a;
+ struct arc *aa;
+
+ if (nfa->pre->outs == NULL) {
+ return REG_UIMPOSSIBLE;
+ }
+ for (a = nfa->pre->outs; a != NULL; a = a->outchain) {
+ for (aa = a->to->outs; aa != NULL; aa = aa->outchain) {
+ if (aa->to == nfa->post) {
+ return REG_UEMPTYMATCH;
+ }
+ }
+ }
+ return 0;
}
-
+
/*
- compact - compact an NFA
^ static VOID compact(struct nfa *, struct cnfa *);
*/
-static VOID
-compact(nfa, cnfa)
-struct nfa *nfa;
-struct cnfa *cnfa;
+static void
+compact(
+ struct nfa *nfa,
+ struct cnfa *cnfa)
{
- struct state *s;
- struct arc *a;
- size_t nstates;
- size_t narcs;
- struct carc *ca;
- struct carc *first;
-
- assert (!NISERR());
-
- nstates = 0;
- narcs = 0;
- for (s = nfa->states; s != NULL; s = s->next) {
- nstates++;
- narcs += 1 + s->nouts + 1;
- /* 1 as a fake for flags, nouts for arcs, 1 as endmarker */
+ struct state *s;
+ struct arc *a;
+ size_t nstates;
+ size_t narcs;
+ struct carc *ca;
+ struct carc *first;
+
+ assert(!NISERR());
+
+ nstates = 0;
+ narcs = 0;
+ for (s = nfa->states; s != NULL; s = s->next) {
+ nstates++;
+ narcs += 1 + s->nouts + 1;
+ /* 1 as a fake for flags, nouts for arcs, 1 as endmarker */
+ }
+
+ cnfa->states = (struct carc **) MALLOC(nstates * sizeof(struct carc *));
+ cnfa->arcs = (struct carc *) MALLOC(narcs * sizeof(struct carc));
+ if (cnfa->states == NULL || cnfa->arcs == NULL) {
+ if (cnfa->states != NULL) {
+ FREE(cnfa->states);
}
-
- cnfa->states = (struct carc **)MALLOC(nstates * sizeof(struct carc *));
- cnfa->arcs = (struct carc *)MALLOC(narcs * sizeof(struct carc));
- if (cnfa->states == NULL || cnfa->arcs == NULL) {
- if (cnfa->states != NULL)
- FREE(cnfa->states);
- if (cnfa->arcs != NULL)
- FREE(cnfa->arcs);
- NERR(REG_ESPACE);
- return;
+ if (cnfa->arcs != NULL) {
+ FREE(cnfa->arcs);
}
- cnfa->nstates = nstates;
- cnfa->pre = nfa->pre->no;
- cnfa->post = nfa->post->no;
- cnfa->bos[0] = nfa->bos[0];
- cnfa->bos[1] = nfa->bos[1];
- cnfa->eos[0] = nfa->eos[0];
- cnfa->eos[1] = nfa->eos[1];
- cnfa->ncolors = maxcolor(nfa->cm) + 1;
- cnfa->flags = 0;
-
- ca = cnfa->arcs;
- for (s = nfa->states; s != NULL; s = s->next) {
- assert((size_t)s->no < nstates);
- cnfa->states[s->no] = ca;
- ca->co = 0; /* clear and skip flags "arc" */
+ NERR(REG_ESPACE);
+ return;
+ }
+ cnfa->nstates = nstates;
+ cnfa->pre = nfa->pre->no;
+ cnfa->post = nfa->post->no;
+ cnfa->bos[0] = nfa->bos[0];
+ cnfa->bos[1] = nfa->bos[1];
+ cnfa->eos[0] = nfa->eos[0];
+ cnfa->eos[1] = nfa->eos[1];
+ cnfa->ncolors = maxcolor(nfa->cm) + 1;
+ cnfa->flags = 0;
+
+ ca = cnfa->arcs;
+ for (s = nfa->states; s != NULL; s = s->next) {
+ assert((size_t) s->no < nstates);
+ cnfa->states[s->no] = ca;
+ ca->co = 0; /* clear and skip flags "arc" */
+ ca++;
+ first = ca;
+ for (a = s->outs; a != NULL; a = a->outchain) {
+ switch (a->type) {
+ case PLAIN:
+ ca->co = a->co;
+ ca->to = a->to->no;
ca++;
- first = ca;
- for (a = s->outs; a != NULL; a = a->outchain)
- switch (a->type) {
- case PLAIN:
- ca->co = a->co;
- ca->to = a->to->no;
- ca++;
- break;
- case LACON:
- assert(s->no != cnfa->pre);
- ca->co = (color)(cnfa->ncolors + a->co);
- ca->to = a->to->no;
- ca++;
- cnfa->flags |= HASLACONS;
- break;
- default:
- assert(NOTREACHED);
- break;
- }
- carcsort(first, ca-1);
- ca->co = COLORLESS;
- ca->to = 0;
+ break;
+ case LACON:
+ assert(s->no != cnfa->pre);
+ ca->co = (color) (cnfa->ncolors + a->co);
+ ca->to = a->to->no;
ca++;
+ cnfa->flags |= HASLACONS;
+ break;
+ default:
+ assert(NOTREACHED);
+ break;
+ }
}
- assert(ca == &cnfa->arcs[narcs]);
- assert(cnfa->nstates != 0);
-
- /* mark no-progress states */
- for (a = nfa->pre->outs; a != NULL; a = a->outchain)
- cnfa->states[a->to->no]->co = 1;
- cnfa->states[nfa->pre->no]->co = 1;
+ carcsort(first, ca-1);
+ ca->co = COLORLESS;
+ ca->to = 0;
+ ca++;
+ }
+ assert(ca == &cnfa->arcs[narcs]);
+ assert(cnfa->nstates != 0);
+
+ /*
+ * Mark no-progress states.
+ */
+
+ for (a = nfa->pre->outs; a != NULL; a = a->outchain) {
+ cnfa->states[a->to->no]->co = 1;
+ }
+ cnfa->states[nfa->pre->no]->co = 1;
}
-
+
/*
- carcsort - sort compacted-NFA arcs by color
* Really dumb algorithm, but if the list is long enough for that to matter,
* you're in real trouble anyway.
^ static VOID carcsort(struct carc *, struct carc *);
*/
-static VOID
-carcsort(first, last)
-struct carc *first;
-struct carc *last;
+static void
+carcsort(
+ struct carc *first,
+ struct carc *last)
{
- struct carc *p;
- struct carc *q;
- struct carc tmp;
-
- if (last - first <= 1)
- return;
-
- for (p = first; p <= last; p++)
- for (q = p; q <= last; q++)
- if (p->co > q->co ||
- (p->co == q->co && p->to > q->to)) {
- assert(p != q);
- tmp = *p;
- *p = *q;
- *q = tmp;
- }
-}
+ struct carc *p;
+ struct carc *q;
+ struct carc tmp;
+ if (last - first <= 1) {
+ return;
+ }
+
+ for (p = first; p <= last; p++) {
+ for (q = p; q <= last; q++) {
+ if (p->co > q->co || (p->co == q->co && p->to > q->to)) {
+ assert(p != q);
+ tmp = *p;
+ *p = *q;
+ *q = tmp;
+ }
+ }
+ }
+}
+
/*
- freecnfa - free a compacted NFA
^ static VOID freecnfa(struct cnfa *);
*/
-static VOID
-freecnfa(cnfa)
-struct cnfa *cnfa;
+static void
+freecnfa(
+ struct cnfa *cnfa)
{
- assert(cnfa->nstates != 0); /* not empty already */
- cnfa->nstates = 0;
- FREE(cnfa->states);
- FREE(cnfa->arcs);
+ assert(cnfa->nstates != 0); /* not empty already */
+ cnfa->nstates = 0;
+ FREE(cnfa->states);
+ FREE(cnfa->arcs);
}
-
+
/*
- dumpnfa - dump an NFA in human-readable form
^ static VOID dumpnfa(struct nfa *, FILE *);
*/
-static VOID
-dumpnfa(nfa, f)
-struct nfa *nfa;
-FILE *f;
+static void
+dumpnfa(
+ struct nfa *nfa,
+ FILE *f)
{
#ifdef REG_DEBUG
- struct state *s;
-
- fprintf(f, "pre %d, post %d", nfa->pre->no, nfa->post->no);
- if (nfa->bos[0] != COLORLESS)
- fprintf(f, ", bos [%ld]", (long)nfa->bos[0]);
- if (nfa->bos[1] != COLORLESS)
- fprintf(f, ", bol [%ld]", (long)nfa->bos[1]);
- if (nfa->eos[0] != COLORLESS)
- fprintf(f, ", eos [%ld]", (long)nfa->eos[0]);
- if (nfa->eos[1] != COLORLESS)
- fprintf(f, ", eol [%ld]", (long)nfa->eos[1]);
- fprintf(f, "\n");
- for (s = nfa->states; s != NULL; s = s->next)
- dumpstate(s, f);
- if (nfa->parent == NULL)
- dumpcolors(nfa->cm, f);
- fflush(f);
+ struct state *s;
+
+ fprintf(f, "pre %d, post %d", nfa->pre->no, nfa->post->no);
+ if (nfa->bos[0] != COLORLESS) {
+ fprintf(f, ", bos [%ld]", (long) nfa->bos[0]);
+ }
+ if (nfa->bos[1] != COLORLESS) {
+ fprintf(f, ", bol [%ld]", (long) nfa->bos[1]);
+ }
+ if (nfa->eos[0] != COLORLESS) {
+ fprintf(f, ", eos [%ld]", (long) nfa->eos[0]);
+ }
+ if (nfa->eos[1] != COLORLESS) {
+ fprintf(f, ", eol [%ld]", (long) nfa->eos[1]);
+ }
+ fprintf(f, "\n");
+ for (s = nfa->states; s != NULL; s = s->next) {
+ dumpstate(s, f);
+ }
+ if (nfa->parent == NULL) {
+ dumpcolors(nfa->cm, f);
+ }
+ fflush(f);
#endif
}
-
+
#ifdef REG_DEBUG /* subordinates of dumpnfa */
/*
^ #ifdef REG_DEBUG
@@ -1478,165 +1625,185 @@ FILE *f;
- dumpstate - dump an NFA state in human-readable form
^ static VOID dumpstate(struct state *, FILE *);
*/
-static VOID
-dumpstate(s, f)
-struct state *s;
-FILE *f;
+static void
+dumpstate(
+ struct state *s,
+ FILE *f)
{
- struct arc *a;
-
- fprintf(f, "%d%s%c", s->no, (s->tmp != NULL) ? "T" : "",
- (s->flag) ? s->flag : '.');
- if (s->prev != NULL && s->prev->next != s)
- fprintf(f, "\tstate chain bad\n");
- if (s->nouts == 0)
- fprintf(f, "\tno out arcs\n");
- else
- dumparcs(s, f);
- fflush(f);
- for (a = s->ins; a != NULL; a = a->inchain) {
- if (a->to != s)
- fprintf(f, "\tlink from %d to %d on %d's in-chain\n",
- a->from->no, a->to->no, s->no);
+ struct arc *a;
+
+ fprintf(f, "%d%s%c", s->no, (s->tmp != NULL) ? "T" : "",
+ (s->flag) ? s->flag : '.');
+ if (s->prev != NULL && s->prev->next != s) {
+ fprintf(f, "\tstate chain bad\n");
+ }
+ if (s->nouts == 0) {
+ fprintf(f, "\tno out arcs\n");
+ } else {
+ dumparcs(s, f);
+ }
+ fflush(f);
+ for (a = s->ins; a != NULL; a = a->inchain) {
+ if (a->to != s) {
+ fprintf(f, "\tlink from %d to %d on %d's in-chain\n",
+ a->from->no, a->to->no, s->no);
}
+ }
}
-
+
/*
- dumparcs - dump out-arcs in human-readable form
^ static VOID dumparcs(struct state *, FILE *);
*/
-static VOID
-dumparcs(s, f)
-struct state *s;
-FILE *f;
+static void
+dumparcs(
+ struct state *s,
+ FILE *f)
{
- int pos;
+ int pos;
- assert(s->nouts > 0);
- /* printing arcs in reverse order is usually clearer */
- pos = dumprarcs(s->outs, s, f, 1);
- if (pos != 1)
- fprintf(f, "\n");
+ assert(s->nouts > 0);
+ /* printing arcs in reverse order is usually clearer */
+ pos = dumprarcs(s->outs, s, f, 1);
+ if (pos != 1) {
+ fprintf(f, "\n");
+ }
}
-
+
/*
- dumprarcs - dump remaining outarcs, recursively, in reverse order
^ static int dumprarcs(struct arc *, struct state *, FILE *, int);
*/
static int /* resulting print position */
-dumprarcs(a, s, f, pos)
-struct arc *a;
-struct state *s;
-FILE *f;
-int pos; /* initial print position */
+dumprarcs(
+ struct arc *a,
+ struct state *s,
+ FILE *f,
+ int pos) /* initial print position */
{
- if (a->outchain != NULL)
- pos = dumprarcs(a->outchain, s, f, pos);
- dumparc(a, s, f);
- if (pos == 5) {
- fprintf(f, "\n");
- pos = 1;
- } else
- pos++;
- return pos;
+ if (a->outchain != NULL) {
+ pos = dumprarcs(a->outchain, s, f, pos);
+ }
+ dumparc(a, s, f);
+ if (pos == 5) {
+ fprintf(f, "\n");
+ pos = 1;
+ } else {
+ pos++;
+ }
+ return pos;
}
-
+
/*
- dumparc - dump one outarc in readable form, including prefixing tab
^ static VOID dumparc(struct arc *, struct state *, FILE *);
*/
-static VOID
-dumparc(a, s, f)
-struct arc *a;
-struct state *s;
-FILE *f;
+static void
+dumparc(
+ struct arc *a,
+ struct state *s,
+ FILE *f)
{
- struct arc *aa;
- struct arcbatch *ab;
-
- fprintf(f, "\t");
- switch (a->type) {
- case PLAIN:
- fprintf(f, "[%ld]", (long)a->co);
- break;
- case AHEAD:
- fprintf(f, ">%ld>", (long)a->co);
- break;
- case BEHIND:
- fprintf(f, "<%ld<", (long)a->co);
- break;
- case LACON:
- fprintf(f, ":%ld:", (long)a->co);
- break;
- case '^':
- case '$':
- fprintf(f, "%c%d", a->type, (int)a->co);
- break;
- case EMPTY:
- break;
- default:
- fprintf(f, "0x%x/0%lo", a->type, (long)a->co);
- break;
+ struct arc *aa;
+ struct arcbatch *ab;
+
+ fprintf(f, "\t");
+ switch (a->type) {
+ case PLAIN:
+ fprintf(f, "[%ld]", (long) a->co);
+ break;
+ case AHEAD:
+ fprintf(f, ">%ld>", (long) a->co);
+ break;
+ case BEHIND:
+ fprintf(f, "<%ld<", (long) a->co);
+ break;
+ case LACON:
+ fprintf(f, ":%ld:", (long) a->co);
+ break;
+ case '^':
+ case '$':
+ fprintf(f, "%c%d", a->type, (int) a->co);
+ break;
+ case EMPTY:
+ break;
+ default:
+ fprintf(f, "0x%x/0%lo", a->type, (long) a->co);
+ break;
+ }
+ if (a->from != s) {
+ fprintf(f, "?%d?", a->from->no);
+ }
+ for (ab = &a->from->oas; ab != NULL; ab = ab->next) {
+ for (aa = &ab->a[0]; aa < &ab->a[ABSIZE]; aa++) {
+ if (aa == a) {
+ break; /* NOTE BREAK OUT */
+ }
}
- if (a->from != s)
- fprintf(f, "?%d?", a->from->no);
- for (ab = &a->from->oas; ab != NULL; ab = ab->next) {
- for (aa = &ab->a[0]; aa < &ab->a[ABSIZE]; aa++)
- if (aa == a)
- break; /* NOTE BREAK OUT */
- if (aa < &ab->a[ABSIZE]) /* propagate break */
- break; /* NOTE BREAK OUT */
+ if (aa < &ab->a[ABSIZE]) { /* propagate break */
+ break; /* NOTE BREAK OUT */
}
- if (ab == NULL)
- fprintf(f, "?!?"); /* not in allocated space */
- fprintf(f, "->");
- if (a->to == NULL) {
- fprintf(f, "NULL");
- return;
+ }
+ if (ab == NULL) {
+ fprintf(f, "?!?"); /* not in allocated space */
+ }
+ fprintf(f, "->");
+ if (a->to == NULL) {
+ fprintf(f, "NULL");
+ return;
+ }
+ fprintf(f, "%d", a->to->no);
+ for (aa = a->to->ins; aa != NULL; aa = aa->inchain) {
+ if (aa == a) {
+ break; /* NOTE BREAK OUT */
}
- fprintf(f, "%d", a->to->no);
- for (aa = a->to->ins; aa != NULL; aa = aa->inchain)
- if (aa == a)
- break; /* NOTE BREAK OUT */
- if (aa == NULL)
- fprintf(f, "?!?"); /* missing from in-chain */
+ }
+ if (aa == NULL) {
+ fprintf(f, "?!?"); /* missing from in-chain */
+ }
}
/*
^ #endif
*/
#endif /* ifdef REG_DEBUG */
-
+
/*
- dumpcnfa - dump a compacted NFA in human-readable form
^ static VOID dumpcnfa(struct cnfa *, FILE *);
*/
-static VOID
-dumpcnfa(cnfa, f)
-struct cnfa *cnfa;
-FILE *f;
+static void
+dumpcnfa(
+ struct cnfa *cnfa,
+ FILE *f)
{
#ifdef REG_DEBUG
- int st;
-
- fprintf(f, "pre %d, post %d", cnfa->pre, cnfa->post);
- if (cnfa->bos[0] != COLORLESS)
- fprintf(f, ", bos [%ld]", (long)cnfa->bos[0]);
- if (cnfa->bos[1] != COLORLESS)
- fprintf(f, ", bol [%ld]", (long)cnfa->bos[1]);
- if (cnfa->eos[0] != COLORLESS)
- fprintf(f, ", eos [%ld]", (long)cnfa->eos[0]);
- if (cnfa->eos[1] != COLORLESS)
- fprintf(f, ", eol [%ld]", (long)cnfa->eos[1]);
- if (cnfa->flags&HASLACONS)
- fprintf(f, ", haslacons");
- fprintf(f, "\n");
- for (st = 0; st < cnfa->nstates; st++)
- dumpcstate(st, cnfa->states[st], cnfa, f);
- fflush(f);
+ int st;
+
+ fprintf(f, "pre %d, post %d", cnfa->pre, cnfa->post);
+ if (cnfa->bos[0] != COLORLESS) {
+ fprintf(f, ", bos [%ld]", (long) cnfa->bos[0]);
+ }
+ if (cnfa->bos[1] != COLORLESS) {
+ fprintf(f, ", bol [%ld]", (long) cnfa->bos[1]);
+ }
+ if (cnfa->eos[0] != COLORLESS) {
+ fprintf(f, ", eos [%ld]", (long) cnfa->eos[0]);
+ }
+ if (cnfa->eos[1] != COLORLESS) {
+ fprintf(f, ", eol [%ld]", (long) cnfa->eos[1]);
+ }
+ if (cnfa->flags&HASLACONS) {
+ fprintf(f, ", haslacons");
+ }
+ fprintf(f, "\n");
+ for (st = 0; st < cnfa->nstates; st++) {
+ dumpcstate(st, cnfa->states[st], cnfa, f);
+ }
+ fflush(f);
#endif
}
-
+
#ifdef REG_DEBUG /* subordinates of dumpcnfa */
/*
^ #ifdef REG_DEBUG
@@ -1646,36 +1813,46 @@ FILE *f;
- dumpcstate - dump a compacted-NFA state in human-readable form
^ static VOID dumpcstate(int, struct carc *, struct cnfa *, FILE *);
*/
-static VOID
-dumpcstate(st, ca, cnfa, f)
-int st;
-struct carc *ca;
-struct cnfa *cnfa;
-FILE *f;
+static void
+dumpcstate(
+ int st,
+ struct carc *ca,
+ struct cnfa *cnfa,
+ FILE *f)
{
- int i;
- int pos;
-
- fprintf(f, "%d%s", st, (ca[0].co) ? ":" : ".");
- pos = 1;
- for (i = 1; ca[i].co != COLORLESS; i++) {
- if (ca[i].co < cnfa->ncolors)
- fprintf(f, "\t[%ld]->%d", (long)ca[i].co, ca[i].to);
- else
- fprintf(f, "\t:%ld:->%d", (long)ca[i].co-cnfa->ncolors,
- ca[i].to);
- if (pos == 5) {
- fprintf(f, "\n");
- pos = 1;
- } else
- pos++;
+ int i;
+ int pos;
+
+ fprintf(f, "%d%s", st, (ca[0].co) ? ":" : ".");
+ pos = 1;
+ for (i = 1; ca[i].co != COLORLESS; i++) {
+ if (ca[i].co < cnfa->ncolors) {
+ fprintf(f, "\t[%ld]->%d", (long) ca[i].co, ca[i].to);
+ } else {
+ fprintf(f, "\t:%ld:->%d", (long) ca[i].co-cnfa->ncolors,ca[i].to);
}
- if (i == 1 || pos != 1)
- fprintf(f, "\n");
- fflush(f);
+ if (pos == 5) {
+ fprintf(f, "\n");
+ pos = 1;
+ } else {
+ pos++;
+ }
+ }
+ if (i == 1 || pos != 1) {
+ fprintf(f, "\n");
+ }
+ fflush(f);
}
/*
^ #endif
*/
#endif /* ifdef REG_DEBUG */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/regcomp.c b/generic/regcomp.c
index 66cdf33..6dea04b 100644
--- a/generic/regcomp.c
+++ b/generic/regcomp.c
@@ -2,24 +2,24 @@
* re_*comp and friends - compile REs
* This file #includes several others (see the bottom).
*
- * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
- *
+ * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
+ *
* Development of this software was funded, in part, by Cray Research Inc.,
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
- * Corporation, none of whom are responsible for the results. The author
- * thanks all of them.
- *
+ * Corporation, none of whom are responsible for the results. The author
+ * thanks all of them.
+ *
* Redistribution and use in source and binary forms -- with or without
* modification -- are permitted for any purpose, provided that
* redistributions in source form retain this entire copyright notice and
* indicate the origin and nature of any modifications.
- *
- * I'd appreciate being given credit for this package in the documentation
- * of software which uses it, but that is not a requirement.
- *
+ *
+ * I'd appreciate being given credit for this package in the documentation of
+ * software which uses it, but that is not a requirement.
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
@@ -38,203 +38,189 @@
/* =====^!^===== begin forwards =====^!^===== */
/* automatically gathered by fwd; do not hand-edit */
/* === regcomp.c === */
-int compile _ANSI_ARGS_((regex_t *, CONST chr *, size_t, int));
-static VOID moresubs _ANSI_ARGS_((struct vars *, int));
-static int freev _ANSI_ARGS_((struct vars *, int));
-static VOID makesearch _ANSI_ARGS_((struct vars *, struct nfa *));
-static struct subre *parse _ANSI_ARGS_((struct vars *, int, int, struct state *, struct state *));
-static struct subre *parsebranch _ANSI_ARGS_((struct vars *, int, int, struct state *, struct state *, int));
-static VOID parseqatom _ANSI_ARGS_((struct vars *, int, int, struct state *, struct state *, struct subre *));
-static VOID nonword _ANSI_ARGS_((struct vars *, int, struct state *, struct state *));
-static VOID word _ANSI_ARGS_((struct vars *, int, struct state *, struct state *));
-static int scannum _ANSI_ARGS_((struct vars *));
-static VOID repeat _ANSI_ARGS_((struct vars *, struct state *, struct state *, int, int));
-static VOID bracket _ANSI_ARGS_((struct vars *, struct state *, struct state *));
-static VOID cbracket _ANSI_ARGS_((struct vars *, struct state *, struct state *));
-static VOID brackpart _ANSI_ARGS_((struct vars *, struct state *, struct state *));
-static chr *scanplain _ANSI_ARGS_((struct vars *));
-static VOID leaders _ANSI_ARGS_((struct vars *, struct cvec *));
-static VOID onechr _ANSI_ARGS_((struct vars *, pchr, struct state *, struct state *));
-static VOID dovec _ANSI_ARGS_((struct vars *, struct cvec *, struct state *, struct state *));
-static celt nextleader _ANSI_ARGS_((struct vars *, pchr, pchr));
-static VOID wordchrs _ANSI_ARGS_((struct vars *));
-static struct subre *subre _ANSI_ARGS_((struct vars *, int, int, struct state *, struct state *));
-static VOID freesubre _ANSI_ARGS_((struct vars *, struct subre *));
-static VOID freesrnode _ANSI_ARGS_((struct vars *, struct subre *));
-static VOID optst _ANSI_ARGS_((struct vars *, struct subre *));
-static int numst _ANSI_ARGS_((struct subre *, int));
-static VOID markst _ANSI_ARGS_((struct subre *));
-static VOID cleanst _ANSI_ARGS_((struct vars *));
-static long nfatree _ANSI_ARGS_((struct vars *, struct subre *, FILE *));
-static long nfanode _ANSI_ARGS_((struct vars *, struct subre *, FILE *));
-static int newlacon _ANSI_ARGS_((struct vars *, struct state *, struct state *, int));
-static VOID freelacons _ANSI_ARGS_((struct subre *, int));
-static VOID rfree _ANSI_ARGS_((regex_t *));
-static VOID dump _ANSI_ARGS_((regex_t *, FILE *));
-static VOID dumpst _ANSI_ARGS_((struct subre *, FILE *, int));
-static VOID stdump _ANSI_ARGS_((struct subre *, FILE *, int));
-static char *stid _ANSI_ARGS_((struct subre *, char *, size_t));
+int compile(regex_t *, const chr *, size_t, int);
+static void moresubs(struct vars *, int);
+static int freev(struct vars *, int);
+static void makesearch(struct vars *, struct nfa *);
+static struct subre *parse(struct vars *, int, int, struct state *, struct state *);
+static struct subre *parsebranch(struct vars *, int, int, struct state *, struct state *, int);
+static void parseqatom(struct vars *, int, int, struct state *, struct state *, struct subre *);
+static void nonword(struct vars *, int, struct state *, struct state *);
+static void word(struct vars *, int, struct state *, struct state *);
+static int scannum(struct vars *);
+static void repeat(struct vars *, struct state *, struct state *, int, int);
+static void bracket(struct vars *, struct state *, struct state *);
+static void cbracket(struct vars *, struct state *, struct state *);
+static void brackpart(struct vars *, struct state *, struct state *);
+static const chr *scanplain(struct vars *);
+static void onechr(struct vars *, pchr, struct state *, struct state *);
+static void dovec(struct vars *, struct cvec *, struct state *, struct state *);
+static void wordchrs(struct vars *);
+static struct subre *subre(struct vars *, int, int, struct state *, struct state *);
+static void freesubre(struct vars *, struct subre *);
+static void freesrnode(struct vars *, struct subre *);
+static void optst(struct vars *, struct subre *);
+static int numst(struct subre *, int);
+static void markst(struct subre *);
+static void cleanst(struct vars *);
+static long nfatree(struct vars *, struct subre *, FILE *);
+static long nfanode(struct vars *, struct subre *, FILE *);
+static int newlacon(struct vars *, struct state *, struct state *, int);
+static void freelacons(struct subre *, int);
+static void rfree(regex_t *);
+static void dump(regex_t *, FILE *);
+static void dumpst(struct subre *, FILE *, int);
+static void stdump(struct subre *, FILE *, int);
+static const char *stid(struct subre *, char *, size_t);
/* === regc_lex.c === */
-static VOID lexstart _ANSI_ARGS_((struct vars *));
-static VOID prefixes _ANSI_ARGS_((struct vars *));
-static VOID lexnest _ANSI_ARGS_((struct vars *, chr *, chr *));
-static VOID lexword _ANSI_ARGS_((struct vars *));
-static int next _ANSI_ARGS_((struct vars *));
-static int lexescape _ANSI_ARGS_((struct vars *));
-static chr lexdigits _ANSI_ARGS_((struct vars *, int, int, int));
-static int brenext _ANSI_ARGS_((struct vars *, pchr));
-static VOID skip _ANSI_ARGS_((struct vars *));
-static chr newline _ANSI_ARGS_((NOPARMS));
+static void lexstart(struct vars *);
+static void prefixes(struct vars *);
+static void lexnest(struct vars *, const chr *, const chr *);
+static void lexword(struct vars *);
+static int next(struct vars *);
+static int lexescape(struct vars *);
+static chr lexdigits(struct vars *, int, int, int);
+static int brenext(struct vars *, pchr);
+static void skip(struct vars *);
+static chr newline(NOPARMS);
#ifdef REG_DEBUG
-static chr *ch _ANSI_ARGS_((NOPARMS));
+static const chr *ch(NOPARMS);
#endif
-static chr chrnamed _ANSI_ARGS_((struct vars *, chr *, chr *, pchr));
+static chr chrnamed(struct vars *, const chr *, const chr *, pchr);
/* === regc_color.c === */
-static VOID initcm _ANSI_ARGS_((struct vars *, struct colormap *));
-static VOID freecm _ANSI_ARGS_((struct colormap *));
-static VOID cmtreefree _ANSI_ARGS_((struct colormap *, union tree *, int));
-static color setcolor _ANSI_ARGS_((struct colormap *, pchr, pcolor));
-static color maxcolor _ANSI_ARGS_((struct colormap *));
-static color newcolor _ANSI_ARGS_((struct colormap *));
-static VOID freecolor _ANSI_ARGS_((struct colormap *, pcolor));
-static color pseudocolor _ANSI_ARGS_((struct colormap *));
-static color subcolor _ANSI_ARGS_((struct colormap *, pchr c));
-static color newsub _ANSI_ARGS_((struct colormap *, pcolor));
-static VOID subrange _ANSI_ARGS_((struct vars *, pchr, pchr, struct state *, struct state *));
-static VOID subblock _ANSI_ARGS_((struct vars *, pchr, struct state *, struct state *));
-static VOID okcolors _ANSI_ARGS_((struct nfa *, struct colormap *));
-static VOID colorchain _ANSI_ARGS_((struct colormap *, struct arc *));
-static VOID uncolorchain _ANSI_ARGS_((struct colormap *, struct arc *));
-static int singleton _ANSI_ARGS_((struct colormap *, pchr c));
-static VOID rainbow _ANSI_ARGS_((struct nfa *, struct colormap *, int, pcolor, struct state *, struct state *));
-static VOID colorcomplement _ANSI_ARGS_((struct nfa *, struct colormap *, int, struct state *, struct state *, struct state *));
+static void initcm(struct vars *, struct colormap *);
+static void freecm(struct colormap *);
+static void cmtreefree(struct colormap *, union tree *, int);
+static color setcolor(struct colormap *, pchr, pcolor);
+static color maxcolor(struct colormap *);
+static color newcolor(struct colormap *);
+static void freecolor(struct colormap *, pcolor);
+static color pseudocolor(struct colormap *);
+static color subcolor(struct colormap *, pchr c);
+static color newsub(struct colormap *, pcolor);
+static void subrange(struct vars *, pchr, pchr, struct state *, struct state *);
+static void subblock(struct vars *, pchr, struct state *, struct state *);
+static void okcolors(struct nfa *, struct colormap *);
+static void colorchain(struct colormap *, struct arc *);
+static void uncolorchain(struct colormap *, struct arc *);
+static void rainbow(struct nfa *, struct colormap *, int, pcolor, struct state *, struct state *);
+static void colorcomplement(struct nfa *, struct colormap *, int, struct state *, struct state *, struct state *);
#ifdef REG_DEBUG
-static VOID dumpcolors _ANSI_ARGS_((struct colormap *, FILE *));
-static VOID fillcheck _ANSI_ARGS_((struct colormap *, union tree *, int, FILE *));
-static VOID dumpchr _ANSI_ARGS_((pchr, FILE *));
+static void dumpcolors(struct colormap *, FILE *);
+static void fillcheck(struct colormap *, union tree *, int, FILE *);
+static void dumpchr(pchr, FILE *);
#endif
/* === regc_nfa.c === */
-static struct nfa *newnfa _ANSI_ARGS_((struct vars *, struct colormap *, struct nfa *));
-static VOID freenfa _ANSI_ARGS_((struct nfa *));
-static struct state *newstate _ANSI_ARGS_((struct nfa *));
-static struct state *newfstate _ANSI_ARGS_((struct nfa *, int flag));
-static VOID dropstate _ANSI_ARGS_((struct nfa *, struct state *));
-static VOID freestate _ANSI_ARGS_((struct nfa *, struct state *));
-static VOID destroystate _ANSI_ARGS_((struct nfa *, struct state *));
-static VOID newarc _ANSI_ARGS_((struct nfa *, int, pcolor, struct state *, struct state *));
-static struct arc *allocarc _ANSI_ARGS_((struct nfa *, struct state *));
-static VOID freearc _ANSI_ARGS_((struct nfa *, struct arc *));
-static struct arc *findarc _ANSI_ARGS_((struct state *, int, pcolor));
-static VOID cparc _ANSI_ARGS_((struct nfa *, struct arc *, struct state *, struct state *));
-static VOID moveins _ANSI_ARGS_((struct nfa *, struct state *, struct state *));
-static VOID copyins _ANSI_ARGS_((struct nfa *, struct state *, struct state *));
-static VOID moveouts _ANSI_ARGS_((struct nfa *, struct state *, struct state *));
-static VOID copyouts _ANSI_ARGS_((struct nfa *, struct state *, struct state *));
-static VOID cloneouts _ANSI_ARGS_((struct nfa *, struct state *, struct state *, struct state *, int));
-static VOID delsub _ANSI_ARGS_((struct nfa *, struct state *, struct state *));
-static VOID deltraverse _ANSI_ARGS_((struct nfa *, struct state *, struct state *));
-static VOID dupnfa _ANSI_ARGS_((struct nfa *, struct state *, struct state *, struct state *, struct state *));
-static VOID duptraverse _ANSI_ARGS_((struct nfa *, struct state *, struct state *));
-static VOID cleartraverse _ANSI_ARGS_((struct nfa *, struct state *));
-static VOID specialcolors _ANSI_ARGS_((struct nfa *));
-static long optimize _ANSI_ARGS_((struct nfa *, FILE *));
-static VOID pullback _ANSI_ARGS_((struct nfa *, FILE *));
-static int pull _ANSI_ARGS_((struct nfa *, struct arc *));
-static VOID pushfwd _ANSI_ARGS_((struct nfa *, FILE *));
-static int push _ANSI_ARGS_((struct nfa *, struct arc *));
+static struct nfa *newnfa(struct vars *, struct colormap *, struct nfa *);
+static void freenfa(struct nfa *);
+static struct state *newstate(struct nfa *);
+static struct state *newfstate(struct nfa *, int flag);
+static void dropstate(struct nfa *, struct state *);
+static void freestate(struct nfa *, struct state *);
+static void destroystate(struct nfa *, struct state *);
+static void newarc(struct nfa *, int, pcolor, struct state *, struct state *);
+static struct arc *allocarc(struct nfa *, struct state *);
+static void freearc(struct nfa *, struct arc *);
+static struct arc *findarc(struct state *, int, pcolor);
+static void cparc(struct nfa *, struct arc *, struct state *, struct state *);
+static void moveins(struct nfa *, struct state *, struct state *);
+static void copyins(struct nfa *, struct state *, struct state *);
+static void moveouts(struct nfa *, struct state *, struct state *);
+static void copyouts(struct nfa *, struct state *, struct state *);
+static void cloneouts(struct nfa *, struct state *, struct state *, struct state *, int);
+static void delsub(struct nfa *, struct state *, struct state *);
+static void deltraverse(struct nfa *, struct state *, struct state *);
+static void dupnfa(struct nfa *, struct state *, struct state *, struct state *, struct state *);
+static void duptraverse(struct nfa *, struct state *, struct state *);
+static void cleartraverse(struct nfa *, struct state *);
+static void specialcolors(struct nfa *);
+static long optimize(struct nfa *, FILE *);
+static void pullback(struct nfa *, FILE *);
+static int pull(struct nfa *, struct arc *);
+static void pushfwd(struct nfa *, FILE *);
+static int push(struct nfa *, struct arc *);
#define INCOMPATIBLE 1 /* destroys arc */
#define SATISFIED 2 /* constraint satisfied */
#define COMPATIBLE 3 /* compatible but not satisfied yet */
-static int combine _ANSI_ARGS_((struct arc *, struct arc *));
-static VOID fixempties _ANSI_ARGS_((struct nfa *, FILE *));
-static int unempty _ANSI_ARGS_((struct nfa *, struct arc *));
-static VOID cleanup _ANSI_ARGS_((struct nfa *));
-static VOID markreachable _ANSI_ARGS_((struct nfa *, struct state *, struct state *, struct state *));
-static VOID markcanreach _ANSI_ARGS_((struct nfa *, struct state *, struct state *, struct state *));
-static long analyze _ANSI_ARGS_((struct nfa *));
-static VOID compact _ANSI_ARGS_((struct nfa *, struct cnfa *));
-static VOID carcsort _ANSI_ARGS_((struct carc *, struct carc *));
-static VOID freecnfa _ANSI_ARGS_((struct cnfa *));
-static VOID dumpnfa _ANSI_ARGS_((struct nfa *, FILE *));
+static int combine(struct arc *, struct arc *);
+static void fixempties(struct nfa *, FILE *);
+static int unempty(struct nfa *, struct arc *);
+static void cleanup(struct nfa *);
+static void markreachable(struct nfa *, struct state *, struct state *, struct state *);
+static void markcanreach(struct nfa *, struct state *, struct state *, struct state *);
+static long analyze(struct nfa *);
+static void compact(struct nfa *, struct cnfa *);
+static void carcsort(struct carc *, struct carc *);
+static void freecnfa(struct cnfa *);
+static void dumpnfa(struct nfa *, FILE *);
#ifdef REG_DEBUG
-static VOID dumpstate _ANSI_ARGS_((struct state *, FILE *));
-static VOID dumparcs _ANSI_ARGS_((struct state *, FILE *));
-static int dumprarcs _ANSI_ARGS_((struct arc *, struct state *, FILE *, int));
-static VOID dumparc _ANSI_ARGS_((struct arc *, struct state *, FILE *));
+static void dumpstate(struct state *, FILE *);
+static void dumparcs(struct state *, FILE *);
+static int dumprarcs(struct arc *, struct state *, FILE *, int);
+static void dumparc(struct arc *, struct state *, FILE *);
#endif
-static VOID dumpcnfa _ANSI_ARGS_((struct cnfa *, FILE *));
+static void dumpcnfa(struct cnfa *, FILE *);
#ifdef REG_DEBUG
-static VOID dumpcstate _ANSI_ARGS_((int, struct carc *, struct cnfa *, FILE *));
+static void dumpcstate(int, struct carc *, struct cnfa *, FILE *);
#endif
/* === regc_cvec.c === */
-static struct cvec *newcvec _ANSI_ARGS_((int, int, int));
-static struct cvec *clearcvec _ANSI_ARGS_((struct cvec *));
-static VOID addchr _ANSI_ARGS_((struct cvec *, pchr));
-static VOID addrange _ANSI_ARGS_((struct cvec *, pchr, pchr));
-static VOID addmcce _ANSI_ARGS_((struct cvec *, chr *, chr *));
-static int haschr _ANSI_ARGS_((struct cvec *, pchr));
-static struct cvec *getcvec _ANSI_ARGS_((struct vars *, int, int, int));
-static VOID freecvec _ANSI_ARGS_((struct cvec *));
+static struct cvec *clearcvec(struct cvec *);
+static void addchr(struct cvec *, pchr);
+static void addrange(struct cvec *, pchr, pchr);
+static struct cvec *newcvec(int, int);
+static struct cvec *getcvec(struct vars *, int, int);
+static void freecvec(struct cvec *);
/* === regc_locale.c === */
-static int nmcces _ANSI_ARGS_((struct vars *));
-static int nleaders _ANSI_ARGS_((struct vars *));
-static struct cvec *allmcces _ANSI_ARGS_((struct vars *, struct cvec *));
-static celt element _ANSI_ARGS_((struct vars *, CONST chr *, CONST chr *));
-static struct cvec *range _ANSI_ARGS_((struct vars *, celt, celt, int));
-static int before _ANSI_ARGS_((celt, celt));
-static struct cvec *eclass _ANSI_ARGS_((struct vars *, celt, int));
-static struct cvec *cclass _ANSI_ARGS_((struct vars *, CONST chr *, CONST chr *, int));
-static struct cvec *allcases _ANSI_ARGS_((struct vars *, pchr));
-static int cmp _ANSI_ARGS_((CONST chr *, CONST chr *, size_t));
-static int casecmp _ANSI_ARGS_((CONST chr *, CONST chr *, size_t));
+static celt element(struct vars *, const chr *, const chr *);
+static struct cvec *range(struct vars *, celt, celt, int);
+static int before(celt, celt);
+static struct cvec *eclass(struct vars *, celt, int);
+static struct cvec *cclass(struct vars *, const chr *, const chr *, int);
+static struct cvec *allcases(struct vars *, pchr);
+static int cmp(const chr *, const chr *, size_t);
+static int casecmp(const chr *, const chr *, size_t);
/* automatically gathered by fwd; do not hand-edit */
/* =====^!^===== end forwards =====^!^===== */
-
-
-
+
/* internal variables, bundled for easy passing around */
struct vars {
- regex_t *re;
- chr *now; /* scan pointer into string */
- chr *stop; /* end of string */
- chr *savenow; /* saved now and stop for "subroutine call" */
- chr *savestop;
- int err; /* error code (0 if none) */
- int cflags; /* copy of compile flags */
- int lasttype; /* type of previous token */
- int nexttype; /* type of next token */
- chr nextvalue; /* value (if any) of next token */
- int lexcon; /* lexical context type (see lex.c) */
- int nsubexp; /* subexpression count */
- struct subre **subs; /* subRE pointer vector */
- size_t nsubs; /* length of vector */
- struct subre *sub10[10]; /* initial vector, enough for most */
- struct nfa *nfa; /* the NFA */
- struct colormap *cm; /* character color map */
- color nlcolor; /* color of newline */
- struct state *wordchrs; /* state in nfa holding word-char outarcs */
- struct subre *tree; /* subexpression tree */
- struct subre *treechain; /* all tree nodes allocated */
- struct subre *treefree; /* any free tree nodes */
- int ntree; /* number of tree nodes */
- struct cvec *cv; /* interface cvec */
- struct cvec *cv2; /* utility cvec */
- struct cvec *mcces; /* collating-element information */
-# define ISCELEADER(v,c) (v->mcces != NULL && haschr(v->mcces, (c)))
- struct state *mccepbegin; /* in nfa, start of MCCE prototypes */
- struct state *mccepend; /* in nfa, end of MCCE prototypes */
- struct subre *lacons; /* lookahead-constraint vector */
- int nlacons; /* size of lacons */
+ regex_t *re;
+ const chr *now; /* scan pointer into string */
+ const chr *stop; /* end of string */
+ const chr *savenow; /* saved now and stop for "subroutine call" */
+ const chr *savestop;
+ int err; /* error code (0 if none) */
+ int cflags; /* copy of compile flags */
+ int lasttype; /* type of previous token */
+ int nexttype; /* type of next token */
+ chr nextvalue; /* value (if any) of next token */
+ int lexcon; /* lexical context type (see lex.c) */
+ int nsubexp; /* subexpression count */
+ struct subre **subs; /* subRE pointer vector */
+ size_t nsubs; /* length of vector */
+ struct subre *sub10[10]; /* initial vector, enough for most */
+ struct nfa *nfa; /* the NFA */
+ struct colormap *cm; /* character color map */
+ color nlcolor; /* color of newline */
+ struct state *wordchrs; /* state in nfa holding word-char outarcs */
+ struct subre *tree; /* subexpression tree */
+ struct subre *treechain; /* all tree nodes allocated */
+ struct subre *treefree; /* any free tree nodes */
+ int ntree; /* number of tree nodes */
+ struct cvec *cv; /* interface cvec */
+ struct cvec *cv2; /* utility cvec */
+ struct subre *lacons; /* lookahead-constraint vector */
+ int nlacons; /* size of lacons */
};
/* parsing macros; most know that `v' is the struct vars pointer */
#define NEXT() (next(v)) /* advance by one token */
#define SEE(t) (v->nexttype == (t)) /* is next token this? */
#define EAT(t) (SEE(t) && next(v)) /* if next is this, swallow it */
-#define VISERR(vv) ((vv)->err != 0) /* have we seen an error yet? */
+#define VISERR(vv) ((vv)->err != 0)/* have we seen an error yet? */
#define ISERR() VISERR(v)
-#define VERR(vv,e) ((vv)->nexttype = EOS, ((vv)->err) ? (vv)->err :\
- ((vv)->err = (e)))
+#define VERR(vv,e) \
+ ((vv)->nexttype = EOS, ((vv)->err) ? (vv)->err : ((vv)->err = (e)))
#define ERR(e) VERR(v, e) /* record an error */
#define NOERR() {if (ISERR()) return;} /* if error seen, return */
#define NOERRN() {if (ISERR()) return NULL;} /* NOERR with retval */
@@ -264,395 +250,459 @@ struct vars {
#define PREFER 'P' /* length preference */
/* is an arc colored, and hence on a color chain? */
-#define COLORED(a) ((a)->type == PLAIN || (a)->type == AHEAD || \
- (a)->type == BEHIND)
-
-
+#define COLORED(a) \
+ ((a)->type == PLAIN || (a)->type == AHEAD || (a)->type == BEHIND)
/* static function list */
static struct fns functions = {
- rfree, /* regfree insides */
+ rfree, /* regfree insides */
};
-
-
-
+
/*
- compile - compile regular expression
- ^ int compile(regex_t *, CONST chr *, size_t, int);
+ ^ int compile(regex_t *, const chr *, size_t, int);
*/
int
-compile(re, string, len, flags)
-regex_t *re;
-CONST chr *string;
-size_t len;
-int flags;
+compile(
+ regex_t *re,
+ const chr *string,
+ size_t len,
+ int flags)
{
- struct vars var;
- struct vars *v = &var;
- struct guts *g;
- int i;
- size_t j;
- FILE *debug = (flags&REG_PROGRESS) ? stdout : (FILE *)NULL;
-# define CNOERR() { if (ISERR()) return freev(v, v->err); }
-
- /* sanity checks */
-
- if (re == NULL || string == NULL)
- return REG_INVARG;
- if ((flags&REG_QUOTE) &&
- (flags&(REG_ADVANCED|REG_EXPANDED|REG_NEWLINE)))
- return REG_INVARG;
- if (!(flags&REG_EXTENDED) && (flags&REG_ADVF))
- return REG_INVARG;
-
- /* initial setup (after which freev() is callable) */
- v->re = re;
- v->now = (chr *)string;
- v->stop = v->now + len;
- v->savenow = v->savestop = NULL;
- v->err = 0;
- v->cflags = flags;
- v->nsubexp = 0;
- v->subs = v->sub10;
- v->nsubs = 10;
- for (j = 0; j < v->nsubs; j++)
- v->subs[j] = NULL;
- v->nfa = NULL;
- v->cm = NULL;
- v->nlcolor = COLORLESS;
- v->wordchrs = NULL;
- v->tree = NULL;
- v->treechain = NULL;
- v->treefree = NULL;
- v->cv = NULL;
- v->cv2 = NULL;
- v->mcces = NULL;
- v->lacons = NULL;
- v->nlacons = 0;
- re->re_magic = REMAGIC;
- re->re_info = 0; /* bits get set during parse */
- re->re_csize = sizeof(chr);
- re->re_guts = NULL;
- re->re_fns = VS(&functions);
-
- /* more complex setup, malloced things */
- re->re_guts = VS(MALLOC(sizeof(struct guts)));
- if (re->re_guts == NULL)
- return freev(v, REG_ESPACE);
- g = (struct guts *)re->re_guts;
- g->tree = NULL;
- initcm(v, &g->cmap);
- v->cm = &g->cmap;
- g->lacons = NULL;
- g->nlacons = 0;
- ZAPCNFA(g->search);
- v->nfa = newnfa(v, v->cm, (struct nfa *)NULL);
- CNOERR();
- v->cv = newcvec(100, 20, 10);
- if (v->cv == NULL)
- return freev(v, REG_ESPACE);
- i = nmcces(v);
- if (i > 0) {
- v->mcces = newcvec(nleaders(v), 0, i);
- CNOERR();
- v->mcces = allmcces(v, v->mcces);
- leaders(v, v->mcces);
- addmcce(v->mcces, (chr *)NULL, (chr *)NULL); /* dummy */
- }
- CNOERR();
-
- /* parsing */
- lexstart(v); /* also handles prefixes */
- if ((v->cflags&REG_NLSTOP) || (v->cflags&REG_NLANCH)) {
- /* assign newline a unique color */
- v->nlcolor = subcolor(v->cm, newline());
- okcolors(v->nfa, v->cm);
- }
- CNOERR();
- v->tree = parse(v, EOS, PLAIN, v->nfa->init, v->nfa->final);
- assert(SEE(EOS)); /* even if error; ISERR() => SEE(EOS) */
- CNOERR();
- assert(v->tree != NULL);
-
- /* finish setup of nfa and its subre tree */
- specialcolors(v->nfa);
- CNOERR();
- if (debug != NULL) {
- fprintf(debug, "\n\n\n========= RAW ==========\n");
- dumpnfa(v->nfa, debug);
- dumpst(v->tree, debug, 1);
- }
- optst(v, v->tree);
- v->ntree = numst(v->tree, 1);
- markst(v->tree);
- cleanst(v);
+ AllocVars(v);
+ struct guts *g;
+ int i;
+ size_t j;
+ FILE *debug = (flags&REG_PROGRESS) ? stdout : NULL;
+#define CNOERR() { if (ISERR()) return freev(v, v->err); }
+
+ /*
+ * Sanity checks.
+ */
+
+ if (re == NULL || string == NULL) {
+ FreeVars(v);
+ return REG_INVARG;
+ }
+ if ((flags&REG_QUOTE) && (flags&(REG_ADVANCED|REG_EXPANDED|REG_NEWLINE))) {
+ FreeVars(v);
+ return REG_INVARG;
+ }
+ if (!(flags&REG_EXTENDED) && (flags&REG_ADVF)) {
+ FreeVars(v);
+ return REG_INVARG;
+ }
+
+ /*
+ * Initial setup (after which freev() is callable).
+ */
+
+ v->re = re;
+ v->now = string;
+ v->stop = v->now + len;
+ v->savenow = v->savestop = NULL;
+ v->err = 0;
+ v->cflags = flags;
+ v->nsubexp = 0;
+ v->subs = v->sub10;
+ v->nsubs = 10;
+ for (j = 0; j < v->nsubs; j++) {
+ v->subs[j] = NULL;
+ }
+ v->nfa = NULL;
+ v->cm = NULL;
+ v->nlcolor = COLORLESS;
+ v->wordchrs = NULL;
+ v->tree = NULL;
+ v->treechain = NULL;
+ v->treefree = NULL;
+ v->cv = NULL;
+ v->cv2 = NULL;
+ v->lacons = NULL;
+ v->nlacons = 0;
+ re->re_magic = REMAGIC;
+ re->re_info = 0; /* bits get set during parse */
+ re->re_csize = sizeof(chr);
+ re->re_guts = NULL;
+ re->re_fns = VS(&functions);
+
+ /*
+ * More complex setup, malloced things.
+ */
+
+ re->re_guts = VS(MALLOC(sizeof(struct guts)));
+ if (re->re_guts == NULL) {
+ return freev(v, REG_ESPACE);
+ }
+ g = (struct guts *) re->re_guts;
+ g->tree = NULL;
+ initcm(v, &g->cmap);
+ v->cm = &g->cmap;
+ g->lacons = NULL;
+ g->nlacons = 0;
+ ZAPCNFA(g->search);
+ v->nfa = newnfa(v, v->cm, NULL);
+ CNOERR();
+ v->cv = newcvec(100, 20);
+ if (v->cv == NULL) {
+ return freev(v, REG_ESPACE);
+ }
+
+ /*
+ * Parsing.
+ */
+
+ lexstart(v); /* also handles prefixes */
+ if ((v->cflags&REG_NLSTOP) || (v->cflags&REG_NLANCH)) {
+ /*
+ * Assign newline a unique color.
+ */
+
+ v->nlcolor = subcolor(v->cm, newline());
+ okcolors(v->nfa, v->cm);
+ }
+ CNOERR();
+ v->tree = parse(v, EOS, PLAIN, v->nfa->init, v->nfa->final);
+ assert(SEE(EOS)); /* even if error; ISERR() => SEE(EOS) */
+ CNOERR();
+ assert(v->tree != NULL);
+
+ /*
+ * Finish setup of nfa and its subre tree.
+ */
+
+ specialcolors(v->nfa);
+ CNOERR();
+ if (debug != NULL) {
+ fprintf(debug, "\n\n\n========= RAW ==========\n");
+ dumpnfa(v->nfa, debug);
+ dumpst(v->tree, debug, 1);
+ }
+ optst(v, v->tree);
+ v->ntree = numst(v->tree, 1);
+ markst(v->tree);
+ cleanst(v);
+ if (debug != NULL) {
+ fprintf(debug, "\n\n\n========= TREE FIXED ==========\n");
+ dumpst(v->tree, debug, 1);
+ }
+
+ /*
+ * Build compacted NFAs for tree and lacons.
+ */
+
+ re->re_info |= nfatree(v, v->tree, debug);
+ CNOERR();
+ assert(v->nlacons == 0 || v->lacons != NULL);
+ for (i = 1; i < v->nlacons; i++) {
if (debug != NULL) {
- fprintf(debug, "\n\n\n========= TREE FIXED ==========\n");
- dumpst(v->tree, debug, 1);
+ fprintf(debug, "\n\n\n========= LA%d ==========\n", i);
}
+ nfanode(v, &v->lacons[i], debug);
+ }
+ CNOERR();
+ if (v->tree->flags&SHORTER) {
+ NOTE(REG_USHORTEST);
+ }
- /* build compacted NFAs for tree and lacons */
- re->re_info |= nfatree(v, v->tree, debug);
- CNOERR();
- assert(v->nlacons == 0 || v->lacons != NULL);
- for (i = 1; i < v->nlacons; i++) {
- if (debug != NULL)
- fprintf(debug, "\n\n\n========= LA%d ==========\n", i);
- nfanode(v, &v->lacons[i], debug);
- }
- CNOERR();
- if (v->tree->flags&SHORTER)
- NOTE(REG_USHORTEST);
-
- /* build compacted NFAs for tree, lacons, fast search */
- if (debug != NULL)
- fprintf(debug, "\n\n\n========= SEARCH ==========\n");
- /* can sacrifice main NFA now, so use it as work area */
- (DISCARD)optimize(v->nfa, debug);
- CNOERR();
- makesearch(v, v->nfa);
- CNOERR();
- compact(v->nfa, &g->search);
- CNOERR();
-
- /* looks okay, package it up */
- re->re_nsub = v->nsubexp;
- v->re = NULL; /* freev no longer frees re */
- g->magic = GUTSMAGIC;
- g->cflags = v->cflags;
- g->info = re->re_info;
- g->nsub = re->re_nsub;
- g->tree = v->tree;
- v->tree = NULL;
- g->ntree = v->ntree;
- g->compare = (v->cflags&REG_ICASE) ? casecmp : cmp;
- g->lacons = v->lacons;
- v->lacons = NULL;
- g->nlacons = v->nlacons;
-
- if (flags&REG_DUMP)
- dump(re, stdout);
-
- assert(v->err == 0);
- return freev(v, 0);
-}
+ /*
+ * Build compacted NFAs for tree, lacons, fast search.
+ */
+
+ if (debug != NULL) {
+ fprintf(debug, "\n\n\n========= SEARCH ==========\n");
+ }
+
+ /*
+ * Can sacrifice main NFA now, so use it as work area.
+ */
+
+ (DISCARD) optimize(v->nfa, debug);
+ CNOERR();
+ makesearch(v, v->nfa);
+ CNOERR();
+ compact(v->nfa, &g->search);
+ CNOERR();
+ /*
+ * Looks okay, package it up.
+ */
+
+ re->re_nsub = v->nsubexp;
+ v->re = NULL; /* freev no longer frees re */
+ g->magic = GUTSMAGIC;
+ g->cflags = v->cflags;
+ g->info = re->re_info;
+ g->nsub = re->re_nsub;
+ g->tree = v->tree;
+ v->tree = NULL;
+ g->ntree = v->ntree;
+ g->compare = (v->cflags&REG_ICASE) ? casecmp : cmp;
+ g->lacons = v->lacons;
+ v->lacons = NULL;
+ g->nlacons = v->nlacons;
+
+ if (flags&REG_DUMP) {
+ dump(re, stdout);
+ }
+
+ assert(v->err == 0);
+ return freev(v, 0);
+}
+
/*
- moresubs - enlarge subRE vector
- ^ static VOID moresubs(struct vars *, int);
+ ^ static void moresubs(struct vars *, int);
*/
-static VOID
-moresubs(v, wanted)
-struct vars *v;
-int wanted; /* want enough room for this one */
+static void
+moresubs(
+ struct vars *v,
+ int wanted) /* want enough room for this one */
{
- struct subre **p;
- size_t n;
-
- assert(wanted > 0 && (size_t)wanted >= v->nsubs);
- n = (size_t)wanted * 3 / 2 + 1;
- if (v->subs == v->sub10) {
- p = (struct subre **)MALLOC(n * sizeof(struct subre *));
- if (p != NULL)
- memcpy(VS(p), VS(v->subs),
- v->nsubs * sizeof(struct subre *));
- } else
- p = (struct subre **)REALLOC(v->subs, n*sizeof(struct subre *));
- if (p == NULL) {
- ERR(REG_ESPACE);
- return;
+ struct subre **p;
+ size_t n;
+
+ assert(wanted > 0 && (size_t)wanted >= v->nsubs);
+ n = (size_t)wanted * 3 / 2 + 1;
+ if (v->subs == v->sub10) {
+ p = (struct subre **) MALLOC(n * sizeof(struct subre *));
+ if (p != NULL) {
+ memcpy(p, v->subs, v->nsubs * sizeof(struct subre *));
}
- v->subs = p;
- for (p = &v->subs[v->nsubs]; v->nsubs < n; p++, v->nsubs++)
- *p = NULL;
- assert(v->nsubs == n);
- assert((size_t)wanted < v->nsubs);
+ } else {
+ p = (struct subre **) REALLOC(v->subs, n*sizeof(struct subre *));
+ }
+ if (p == NULL) {
+ ERR(REG_ESPACE);
+ return;
+ }
+
+ v->subs = p;
+ for (p = &v->subs[v->nsubs]; v->nsubs < n; p++, v->nsubs++) {
+ *p = NULL;
+ }
+ assert(v->nsubs == n);
+ assert((size_t)wanted < v->nsubs);
}
-
+
/*
- freev - free vars struct's substructures where necessary
- * Optionally does error-number setting, and always returns error code
- * (if any), to make error-handling code terser.
+ * Optionally does error-number setting, and always returns error code (if
+ * any), to make error-handling code terser.
^ static int freev(struct vars *, int);
*/
static int
-freev(v, err)
-struct vars *v;
-int err;
+freev(
+ struct vars *v,
+ int err)
{
- if (v->re != NULL)
- rfree(v->re);
- if (v->subs != v->sub10)
- FREE(v->subs);
- if (v->nfa != NULL)
- freenfa(v->nfa);
- if (v->tree != NULL)
- freesubre(v, v->tree);
- if (v->treechain != NULL)
- cleanst(v);
- if (v->cv != NULL)
- freecvec(v->cv);
- if (v->cv2 != NULL)
- freecvec(v->cv2);
- if (v->mcces != NULL)
- freecvec(v->mcces);
- if (v->lacons != NULL)
- freelacons(v->lacons, v->nlacons);
- ERR(err); /* nop if err==0 */
-
- return v->err;
+ register int ret;
+
+ if (v->re != NULL) {
+ rfree(v->re);
+ }
+ if (v->subs != v->sub10) {
+ FREE(v->subs);
+ }
+ if (v->nfa != NULL) {
+ freenfa(v->nfa);
+ }
+ if (v->tree != NULL) {
+ freesubre(v, v->tree);
+ }
+ if (v->treechain != NULL) {
+ cleanst(v);
+ }
+ if (v->cv != NULL) {
+ freecvec(v->cv);
+ }
+ if (v->cv2 != NULL) {
+ freecvec(v->cv2);
+ }
+ if (v->lacons != NULL) {
+ freelacons(v->lacons, v->nlacons);
+ }
+ ERR(err); /* nop if err==0 */
+
+ ret = v->err;
+ FreeVars(v);
+ return ret;
}
-
+
/*
- makesearch - turn an NFA into a search NFA (implicit prepend of .*?)
* NFA must have been optimize()d already.
- ^ static VOID makesearch(struct vars *, struct nfa *);
+ ^ static void makesearch(struct vars *, struct nfa *);
*/
-static VOID
-makesearch(v, nfa)
-struct vars *v;
-struct nfa *nfa;
+static void
+makesearch(
+ struct vars *v,
+ struct nfa *nfa)
{
- struct arc *a;
- struct arc *b;
- struct state *pre = nfa->pre;
- struct state *s;
- struct state *s2;
- struct state *slist;
-
- /* no loops are needed if it's anchored */
- for (a = pre->outs; a != NULL; a = a->outchain) {
- assert(a->type == PLAIN);
- if (a->co != nfa->bos[0] && a->co != nfa->bos[1])
- break;
- }
- if (a != NULL) {
- /* add implicit .* in front */
- rainbow(nfa, v->cm, PLAIN, COLORLESS, pre, pre);
+ struct arc *a, *b;
+ struct state *pre = nfa->pre;
+ struct state *s, *s2, *slist;
- /* and ^* and \A* too -- not always necessary, but harmless */
- newarc(nfa, PLAIN, nfa->bos[0], pre, pre);
- newarc(nfa, PLAIN, nfa->bos[1], pre, pre);
+ /*
+ * No loops are needed if it's anchored.
+ */
+
+ for (a = pre->outs; a != NULL; a = a->outchain) {
+ assert(a->type == PLAIN);
+ if (a->co != nfa->bos[0] && a->co != nfa->bos[1]) {
+ break;
}
+ }
+ if (a != NULL) {
+ /*
+ * Add implicit .* in front.
+ */
+
+ rainbow(nfa, v->cm, PLAIN, COLORLESS, pre, pre);
/*
- * Now here's the subtle part. Because many REs have no lookback
- * constraints, often knowing when you were in the pre state tells
- * you little; it's the next state(s) that are informative. But
- * some of them may have other inarcs, i.e. it may be possible to
- * make actual progress and then return to one of them. We must
- * de-optimize such cases, splitting each such state into progress
- * and no-progress states.
+ * And ^* and \A* too -- not always necessary, but harmless.
*/
- /* first, make a list of the states */
- slist = NULL;
- for (a = pre->outs; a != NULL; a = a->outchain) {
- s = a->to;
- for (b = s->ins; b != NULL; b = b->inchain)
- if (b->from != pre)
- break;
- if (b != NULL) { /* must be split */
- if (s->tmp == NULL) { /* if not already in the list */
- /* (fixes bugs 505048, 230589, */
- /* 840258, 504785) */
- s->tmp = slist;
- slist = s;
- }
- }
+ newarc(nfa, PLAIN, nfa->bos[0], pre, pre);
+ newarc(nfa, PLAIN, nfa->bos[1], pre, pre);
+ }
+
+ /*
+ * Now here's the subtle part. Because many REs have no lookback
+ * constraints, often knowing when you were in the pre state tells you
+ * little; it's the next state(s) that are informative. But some of them
+ * may have other inarcs, i.e. it may be possible to make actual progress
+ * and then return to one of them. We must de-optimize such cases,
+ * splitting each such state into progress and no-progress states.
+ */
+
+ /*
+ * First, make a list of the states.
+ */
+
+ slist = NULL;
+ for (a=pre->outs ; a!=NULL ; a=a->outchain) {
+ s = a->to;
+ for (b=s->ins ; b!=NULL ; b=b->inchain) {
+ if (b->from != pre) {
+ break;
+ }
+ }
+ if (b != NULL && s->tmp == NULL) {
+ /*
+ * Must be split if not already in the list (fixes bugs 505048,
+ * 230589, 840258, 504785).
+ */
+
+ s->tmp = slist;
+ slist = s;
}
+ }
+
+ /*
+ * Do the splits.
+ */
+
+ for (s=slist ; s!=NULL ; s=s2) {
+ s2 = newstate(nfa);
- /* do the splits */
- for (s = slist; s != NULL; s = s2) {
- s2 = newstate(nfa);
- copyouts(nfa, s, s2);
- for (a = s->ins; a != NULL; a = b) {
- b = a->inchain;
- if (a->from != pre) {
- cparc(nfa, a, a->from, s2);
- freearc(nfa, a);
- }
- }
- s2 = s->tmp;
- s->tmp = NULL; /* clean up while we're at it */
+ copyouts(nfa, s, s2);
+ for (a=s->ins ; a!=NULL ; a=b) {
+ b = a->inchain;
+
+ if (a->from != pre) {
+ cparc(nfa, a, a->from, s2);
+ freearc(nfa, a);
+ }
}
+ s2 = s->tmp;
+ s->tmp = NULL; /* clean up while we're at it */
+ }
}
-
+
/*
- parse - parse an RE
- * This is actually just the top level, which parses a bunch of branches
- * tied together with '|'. They appear in the tree as the left children
- * of a chain of '|' subres.
+ * This is actually just the top level, which parses a bunch of branches tied
+ * together with '|'. They appear in the tree as the left children of a chain
+ * of '|' subres.
^ static struct subre *parse(struct vars *, int, int, struct state *,
^ struct state *);
*/
static struct subre *
-parse(v, stopper, type, init, final)
-struct vars *v;
-int stopper; /* EOS or ')' */
-int type; /* LACON (lookahead subRE) or PLAIN */
-struct state *init; /* initial state */
-struct state *final; /* final state */
+parse(
+ struct vars *v,
+ int stopper, /* EOS or ')' */
+ int type, /* LACON (lookahead subRE) or PLAIN */
+ struct state *init, /* initial state */
+ struct state *final) /* final state */
{
- struct state *left; /* scaffolding for branch */
- struct state *right;
- struct subre *branches; /* top level */
- struct subre *branch; /* current branch */
- struct subre *t; /* temporary */
- int firstbranch; /* is this the first branch? */
-
- assert(stopper == ')' || stopper == EOS);
-
- branches = subre(v, '|', LONGER, init, final);
+ struct state *left, *right; /* scaffolding for branch */
+ struct subre *branches; /* top level */
+ struct subre *branch; /* current branch */
+ struct subre *t; /* temporary */
+ int firstbranch; /* is this the first branch? */
+
+ assert(stopper == ')' || stopper == EOS);
+
+ branches = subre(v, '|', LONGER, init, final);
+ NOERRN();
+ branch = branches;
+ firstbranch = 1;
+ do { /* a branch */
+ if (!firstbranch) {
+ /*
+ * Need a place to hang the branch.
+ */
+
+ branch->right = subre(v, '|', LONGER, init, final);
+ NOERRN();
+ branch = branch->right;
+ }
+ firstbranch = 0;
+ left = newstate(v->nfa);
+ right = newstate(v->nfa);
NOERRN();
- branch = branches;
- firstbranch = 1;
- do { /* a branch */
- if (!firstbranch) {
- /* need a place to hang it */
- branch->right = subre(v, '|', LONGER, init, final);
- NOERRN();
- branch = branch->right;
- }
- firstbranch = 0;
- left = newstate(v->nfa);
- right = newstate(v->nfa);
- NOERRN();
- EMPTYARC(init, left);
- EMPTYARC(right, final);
- NOERRN();
- branch->left = parsebranch(v, stopper, type, left, right, 0);
- NOERRN();
- branch->flags |= UP(branch->flags | branch->left->flags);
- if ((branch->flags &~ branches->flags) != 0) /* new flags */
- for (t = branches; t != branch; t = t->right)
- t->flags |= branch->flags;
- } while (EAT('|'));
- assert(SEE(stopper) || SEE(EOS));
-
- if (!SEE(stopper)) {
- assert(stopper == ')' && SEE(EOS));
- ERR(REG_EPAREN);
+ EMPTYARC(init, left);
+ EMPTYARC(right, final);
+ NOERRN();
+ branch->left = parsebranch(v, stopper, type, left, right, 0);
+ NOERRN();
+ branch->flags |= UP(branch->flags | branch->left->flags);
+ if ((branch->flags &~ branches->flags) != 0) { /* new flags */
+ for (t = branches; t != branch; t = t->right) {
+ t->flags |= branch->flags;
+ }
}
+ } while (EAT('|'));
+ assert(SEE(stopper) || SEE(EOS));
- /* optimize out simple cases */
- if (branch == branches) { /* only one branch */
- assert(branch->right == NULL);
- t = branch->left;
- branch->left = NULL;
- freesubre(v, branches);
- branches = t;
- } else if (!MESSY(branches->flags)) { /* no interesting innards */
- freesubre(v, branches->left);
- branches->left = NULL;
- freesubre(v, branches->right);
- branches->right = NULL;
- branches->op = '=';
- }
+ if (!SEE(stopper)) {
+ assert(stopper == ')' && SEE(EOS));
+ ERR(REG_EPAREN);
+ }
- return branches;
-}
+ /*
+ * Optimize out simple cases.
+ */
+ if (branch == branches) { /* only one branch */
+ assert(branch->right == NULL);
+ t = branch->left;
+ branch->left = NULL;
+ freesubre(v, branches);
+ branches = t;
+ } else if (!MESSY(branches->flags)) { /* no interesting innards */
+ freesubre(v, branches->left);
+ branches->left = NULL;
+ freesubre(v, branches->right);
+ branches->right = NULL;
+ branches->op = '=';
+ }
+
+ return branches;
+}
+
/*
- parsebranch - parse one branch of an RE
* This mostly manages concatenation, working closely with parseqatom().
@@ -662,1514 +712,1446 @@ struct state *final; /* final state */
^ struct state *, int);
*/
static struct subre *
-parsebranch(v, stopper, type, left, right, partial)
-struct vars *v;
-int stopper; /* EOS or ')' */
-int type; /* LACON (lookahead subRE) or PLAIN */
-struct state *left; /* leftmost state */
-struct state *right; /* rightmost state */
-int partial; /* is this only part of a branch? */
+parsebranch(
+ struct vars *v,
+ int stopper, /* EOS or ')' */
+ int type, /* LACON (lookahead subRE) or PLAIN */
+ struct state *left, /* leftmost state */
+ struct state *right, /* rightmost state */
+ int partial) /* is this only part of a branch? */
{
- struct state *lp; /* left end of current construct */
- int seencontent; /* is there anything in this branch yet? */
- struct subre *t;
-
- lp = left;
- seencontent = 0;
- t = subre(v, '=', 0, left, right); /* op '=' is tentative */
- NOERRN();
- while (!SEE('|') && !SEE(stopper) && !SEE(EOS)) {
- if (seencontent) { /* implicit concat operator */
- lp = newstate(v->nfa);
- NOERRN();
- moveins(v->nfa, right, lp);
- }
- seencontent = 1;
-
- /* NB, recursion in parseqatom() may swallow rest of branch */
- parseqatom(v, stopper, type, lp, right, t);
+ struct state *lp; /* left end of current construct */
+ int seencontent; /* is there anything in this branch yet? */
+ struct subre *t;
+
+ lp = left;
+ seencontent = 0;
+ t = subre(v, '=', 0, left, right); /* op '=' is tentative */
+ NOERRN();
+ while (!SEE('|') && !SEE(stopper) && !SEE(EOS)) {
+ if (seencontent) { /* implicit concat operator */
+ lp = newstate(v->nfa);
+ NOERRN();
+ moveins(v->nfa, right, lp);
}
+ seencontent = 1;
+
+ /* NB, recursion in parseqatom() may swallow rest of branch */
+ parseqatom(v, stopper, type, lp, right, t);
+ }
- if (!seencontent) { /* empty branch */
- if (!partial)
- NOTE(REG_UUNSPEC);
- assert(lp == left);
- EMPTYARC(left, right);
+ if (!seencontent) { /* empty branch */
+ if (!partial) {
+ NOTE(REG_UUNSPEC);
}
+ assert(lp == left);
+ EMPTYARC(left, right);
+ }
- return t;
+ return t;
}
-
+
/*
- parseqatom - parse one quantified atom or constraint of an RE
- * The bookkeeping near the end cooperates very closely with parsebranch();
- * in particular, it contains a recursion that can involve parsing the rest
- * of the branch, making this function's name somewhat inaccurate.
- ^ static VOID parseqatom(struct vars *, int, int, struct state *,
+ * The bookkeeping near the end cooperates very closely with parsebranch(); in
+ * particular, it contains a recursion that can involve parsing the rest of
+ * the branch, making this function's name somewhat inaccurate.
+ ^ static void parseqatom(struct vars *, int, int, struct state *,
^ struct state *, struct subre *);
*/
-static VOID
-parseqatom(v, stopper, type, lp, rp, top)
-struct vars *v;
-int stopper; /* EOS or ')' */
-int type; /* LACON (lookahead subRE) or PLAIN */
-struct state *lp; /* left state to hang it on */
-struct state *rp; /* right state to hang it on */
-struct subre *top; /* subtree top */
+static void
+parseqatom(
+ struct vars *v,
+ int stopper, /* EOS or ')' */
+ int type, /* LACON (lookahead subRE) or PLAIN */
+ struct state *lp, /* left state to hang it on */
+ struct state *rp, /* right state to hang it on */
+ struct subre *top) /* subtree top */
{
- struct state *s; /* temporaries for new states */
- struct state *s2;
-# define ARCV(t, val) newarc(v->nfa, t, val, lp, rp)
- int m, n;
- struct subre *atom; /* atom's subtree */
- struct subre *t;
- int cap; /* capturing parens? */
- int pos; /* positive lookahead? */
- int subno; /* capturing-parens or backref number */
- int atomtype;
- int qprefer; /* quantifier short/long preference */
- int f;
- struct subre **atomp; /* where the pointer to atom is */
-
- /* initial bookkeeping */
- atom = NULL;
- assert(lp->nouts == 0); /* must string new code */
- assert(rp->nins == 0); /* between lp and rp */
- subno = 0; /* just to shut lint up */
-
- /* an atom or constraint... */
- atomtype = v->nexttype;
- switch (atomtype) {
+ struct state *s; /* temporaries for new states */
+ struct state *s2;
+#define ARCV(t, val) newarc(v->nfa, t, val, lp, rp)
+ int m, n;
+ struct subre *atom; /* atom's subtree */
+ struct subre *t;
+ int cap; /* capturing parens? */
+ int pos; /* positive lookahead? */
+ int subno; /* capturing-parens or backref number */
+ int atomtype;
+ int qprefer; /* quantifier short/long preference */
+ int f;
+ struct subre **atomp; /* where the pointer to atom is */
+
+ /*
+ * Initial bookkeeping.
+ */
+
+ atom = NULL;
+ assert(lp->nouts == 0); /* must string new code */
+ assert(rp->nins == 0); /* between lp and rp */
+ subno = 0; /* just to shut lint up */
+
+ /*
+ * An atom or constraint...
+ */
+
+ atomtype = v->nexttype;
+ switch (atomtype) {
/* first, constraints, which end by returning */
- case '^':
- ARCV('^', 1);
- if (v->cflags&REG_NLANCH)
- ARCV(BEHIND, v->nlcolor);
- NEXT();
- return;
- break;
- case '$':
- ARCV('$', 1);
- if (v->cflags&REG_NLANCH)
- ARCV(AHEAD, v->nlcolor);
- NEXT();
- return;
- break;
- case SBEGIN:
- ARCV('^', 1); /* BOL */
- ARCV('^', 0); /* or BOS */
- NEXT();
- return;
- break;
- case SEND:
- ARCV('$', 1); /* EOL */
- ARCV('$', 0); /* or EOS */
- NEXT();
- return;
- break;
- case '<':
- wordchrs(v); /* does NEXT() */
- s = newstate(v->nfa);
- NOERR();
- nonword(v, BEHIND, lp, s);
- word(v, AHEAD, s, rp);
- return;
- break;
- case '>':
- wordchrs(v); /* does NEXT() */
- s = newstate(v->nfa);
- NOERR();
- word(v, BEHIND, lp, s);
- nonword(v, AHEAD, s, rp);
- return;
- break;
- case WBDRY:
- wordchrs(v); /* does NEXT() */
- s = newstate(v->nfa);
- NOERR();
- nonword(v, BEHIND, lp, s);
- word(v, AHEAD, s, rp);
- s = newstate(v->nfa);
- NOERR();
- word(v, BEHIND, lp, s);
- nonword(v, AHEAD, s, rp);
- return;
- break;
- case NWBDRY:
- wordchrs(v); /* does NEXT() */
- s = newstate(v->nfa);
- NOERR();
- word(v, BEHIND, lp, s);
- word(v, AHEAD, s, rp);
- s = newstate(v->nfa);
- NOERR();
- nonword(v, BEHIND, lp, s);
- nonword(v, AHEAD, s, rp);
- return;
- break;
- case LACON: /* lookahead constraint */
- pos = v->nextvalue;
- NEXT();
- s = newstate(v->nfa);
- s2 = newstate(v->nfa);
- NOERR();
- t = parse(v, ')', LACON, s, s2);
- freesubre(v, t); /* internal structure irrelevant */
- assert(SEE(')') || ISERR());
- NEXT();
- n = newlacon(v, s, s2, pos);
- NOERR();
- ARCV(LACON, n);
- return;
- break;
- /* then errors, to get them out of the way */
- case '*':
- case '+':
- case '?':
- case '{':
- ERR(REG_BADRPT);
- return;
- break;
- default:
- ERR(REG_ASSERT);
- return;
- break;
- /* then plain characters, and minor variants on that theme */
- case ')': /* unbalanced paren */
- if ((v->cflags&REG_ADVANCED) != REG_EXTENDED) {
- ERR(REG_EPAREN);
- return;
- }
- /* legal in EREs due to specification botch */
- NOTE(REG_UPBOTCH);
- /* fallthrough into case PLAIN */
- case PLAIN:
- onechr(v, v->nextvalue, lp, rp);
- okcolors(v->nfa, v->cm);
- NOERR();
- NEXT();
- break;
- case '[':
- if (v->nextvalue == 1)
- bracket(v, lp, rp);
- else
- cbracket(v, lp, rp);
- assert(SEE(']') || ISERR());
- NEXT();
- break;
- case '.':
- rainbow(v->nfa, v->cm, PLAIN,
- (v->cflags&REG_NLSTOP) ? v->nlcolor : COLORLESS,
- lp, rp);
- NEXT();
- break;
- /* and finally the ugly stuff */
- case '(': /* value flags as capturing or non */
- cap = (type == LACON) ? 0 : v->nextvalue;
- if (cap) {
- v->nsubexp++;
- subno = v->nsubexp;
- if ((size_t)subno >= v->nsubs)
- moresubs(v, subno);
- assert((size_t)subno < v->nsubs);
- } else
- atomtype = PLAIN; /* something that's not '(' */
- NEXT();
- /* need new endpoints because tree will contain pointers */
- s = newstate(v->nfa);
- s2 = newstate(v->nfa);
- NOERR();
- EMPTYARC(lp, s);
- EMPTYARC(s2, rp);
- NOERR();
- atom = parse(v, ')', PLAIN, s, s2);
- assert(SEE(')') || ISERR());
- NEXT();
- NOERR();
- if (cap) {
- v->subs[subno] = atom;
- t = subre(v, '(', atom->flags|CAP, lp, rp);
- NOERR();
- t->subno = subno;
- t->left = atom;
- atom = t;
- }
- /* postpone everything else pending possible {0} */
- break;
- case BACKREF: /* the Feature From The Black Lagoon */
- INSIST(type != LACON, REG_ESUBREG);
- INSIST(v->nextvalue < v->nsubs, REG_ESUBREG);
- INSIST(v->subs[v->nextvalue] != NULL, REG_ESUBREG);
- NOERR();
- assert(v->nextvalue > 0);
- atom = subre(v, 'b', BACKR, lp, rp);
- subno = v->nextvalue;
- atom->subno = subno;
- EMPTYARC(lp, rp); /* temporarily, so there's something */
- NEXT();
- break;
+ case '^':
+ ARCV('^', 1);
+ if (v->cflags&REG_NLANCH) {
+ ARCV(BEHIND, v->nlcolor);
}
-
- /* ...and an atom may be followed by a quantifier */
- switch (v->nexttype) {
- case '*':
- m = 0;
- n = INFINITY;
- qprefer = (v->nextvalue) ? LONGER : SHORTER;
- NEXT();
- break;
- case '+':
- m = 1;
- n = INFINITY;
- qprefer = (v->nextvalue) ? LONGER : SHORTER;
- NEXT();
- break;
- case '?':
- m = 0;
- n = 1;
- qprefer = (v->nextvalue) ? LONGER : SHORTER;
- NEXT();
- break;
- case '{':
- NEXT();
- m = scannum(v);
- if (EAT(',')) {
- if (SEE(DIGIT))
- n = scannum(v);
- else
- n = INFINITY;
- if (m > n) {
- ERR(REG_BADBR);
- return;
- }
- /* {m,n} exercises preference, even if it's {m,m} */
- qprefer = (v->nextvalue) ? LONGER : SHORTER;
- } else {
- n = m;
- /* {m} passes operand's preference through */
- qprefer = 0;
- }
- if (!SEE('}')) { /* catches errors too */
- ERR(REG_BADBR);
- return;
- }
- NEXT();
- break;
- default: /* no quantifier */
- m = n = 1;
- qprefer = 0;
- break;
+ NEXT();
+ return;
+ case '$':
+ ARCV('$', 1);
+ if (v->cflags&REG_NLANCH) {
+ ARCV(AHEAD, v->nlcolor);
}
+ NEXT();
+ return;
+ case SBEGIN:
+ ARCV('^', 1); /* BOL */
+ ARCV('^', 0); /* or BOS */
+ NEXT();
+ return;
+ case SEND:
+ ARCV('$', 1); /* EOL */
+ ARCV('$', 0); /* or EOS */
+ NEXT();
+ return;
+ case '<':
+ wordchrs(v); /* does NEXT() */
+ s = newstate(v->nfa);
+ NOERR();
+ nonword(v, BEHIND, lp, s);
+ word(v, AHEAD, s, rp);
+ return;
+ case '>':
+ wordchrs(v); /* does NEXT() */
+ s = newstate(v->nfa);
+ NOERR();
+ word(v, BEHIND, lp, s);
+ nonword(v, AHEAD, s, rp);
+ return;
+ case WBDRY:
+ wordchrs(v); /* does NEXT() */
+ s = newstate(v->nfa);
+ NOERR();
+ nonword(v, BEHIND, lp, s);
+ word(v, AHEAD, s, rp);
+ s = newstate(v->nfa);
+ NOERR();
+ word(v, BEHIND, lp, s);
+ nonword(v, AHEAD, s, rp);
+ return;
+ case NWBDRY:
+ wordchrs(v); /* does NEXT() */
+ s = newstate(v->nfa);
+ NOERR();
+ word(v, BEHIND, lp, s);
+ word(v, AHEAD, s, rp);
+ s = newstate(v->nfa);
+ NOERR();
+ nonword(v, BEHIND, lp, s);
+ nonword(v, AHEAD, s, rp);
+ return;
+ case LACON: /* lookahead constraint */
+ pos = v->nextvalue;
+ NEXT();
+ s = newstate(v->nfa);
+ s2 = newstate(v->nfa);
+ NOERR();
+ t = parse(v, ')', LACON, s, s2);
+ freesubre(v, t); /* internal structure irrelevant */
+ assert(SEE(')') || ISERR());
+ NEXT();
+ n = newlacon(v, s, s2, pos);
+ NOERR();
+ ARCV(LACON, n);
+ return;
- /* annoying special case: {0} or {0,0} cancels everything */
- if (m == 0 && n == 0) {
- if (atom != NULL)
- freesubre(v, atom);
- if (atomtype == '(')
- v->subs[subno] = NULL;
- delsub(v->nfa, lp, rp);
- EMPTYARC(lp, rp);
- return;
+ /*
+ * Then errors, to get them out of the way.
+ */
+
+ case '*':
+ case '+':
+ case '?':
+ case '{':
+ ERR(REG_BADRPT);
+ return;
+ default:
+ ERR(REG_ASSERT);
+ return;
+
+ /*
+ * Then plain characters, and minor variants on that theme.
+ */
+
+ case ')': /* unbalanced paren */
+ if ((v->cflags&REG_ADVANCED) != REG_EXTENDED) {
+ ERR(REG_EPAREN);
+ return;
}
- /* if not a messy case, avoid hard part */
- assert(!MESSY(top->flags));
- f = top->flags | qprefer | ((atom != NULL) ? atom->flags : 0);
- if (atomtype != '(' && atomtype != BACKREF && !MESSY(UP(f))) {
- if (!(m == 1 && n == 1))
- repeat(v, lp, rp, m, n);
- if (atom != NULL)
- freesubre(v, atom);
- top->flags = f;
- return;
+ /*
+ * Legal in EREs due to specification botch.
+ */
+
+ NOTE(REG_UPBOTCH);
+ /* fallthrough into case PLAIN */
+ case PLAIN:
+ onechr(v, v->nextvalue, lp, rp);
+ okcolors(v->nfa, v->cm);
+ NOERR();
+ NEXT();
+ break;
+ case '[':
+ if (v->nextvalue == 1) {
+ bracket(v, lp, rp);
+ } else {
+ cbracket(v, lp, rp);
}
+ assert(SEE(']') || ISERR());
+ NEXT();
+ break;
+ case '.':
+ rainbow(v->nfa, v->cm, PLAIN,
+ (v->cflags&REG_NLSTOP) ? v->nlcolor : COLORLESS, lp, rp);
+ NEXT();
+ break;
/*
- * hard part: something messy
- * That is, capturing parens, back reference, short/long clash, or
- * an atom with substructure containing one of those.
+ * And finally the ugly stuff.
*/
- /* now we'll need a subre for the contents even if they're boring */
- if (atom == NULL) {
- atom = subre(v, '=', 0, lp, rp);
- NOERR();
+ case '(': /* value flags as capturing or non */
+ cap = (type == LACON) ? 0 : v->nextvalue;
+ if (cap) {
+ v->nsubexp++;
+ subno = v->nsubexp;
+ if ((size_t)subno >= v->nsubs) {
+ moresubs(v, subno);
+ }
+ assert((size_t)subno < v->nsubs);
+ } else {
+ atomtype = PLAIN; /* something that's not '(' */
}
+ NEXT();
/*
- * prepare a general-purpose state skeleton
- *
- * ---> [s] ---prefix---> [begin] ---atom---> [end] ----rest---> [rp]
- * / /
- * [lp] ----> [s2] ----bypass---------------------
- *
- * where bypass is an empty, and prefix is some repetitions of atom
+ * Need new endpoints because tree will contain pointers.
*/
- s = newstate(v->nfa); /* first, new endpoints for the atom */
+
+ s = newstate(v->nfa);
s2 = newstate(v->nfa);
NOERR();
- moveouts(v->nfa, lp, s);
- moveins(v->nfa, rp, s2);
+ EMPTYARC(lp, s);
+ EMPTYARC(s2, rp);
NOERR();
- atom->begin = s;
- atom->end = s2;
- s = newstate(v->nfa); /* and spots for prefix and bypass */
- s2 = newstate(v->nfa);
+ atom = parse(v, ')', PLAIN, s, s2);
+ assert(SEE(')') || ISERR());
+ NEXT();
NOERR();
- EMPTYARC(lp, s);
- EMPTYARC(lp, s2);
+ if (cap) {
+ v->subs[subno] = atom;
+ t = subre(v, '(', atom->flags|CAP, lp, rp);
+ NOERR();
+ t->subno = subno;
+ t->left = atom;
+ atom = t;
+ }
+
+ /*
+ * Postpone everything else pending possible {0}.
+ */
+
+ break;
+ case BACKREF: /* the Feature From The Black Lagoon */
+ INSIST(type != LACON, REG_ESUBREG);
+ INSIST(v->nextvalue < v->nsubs, REG_ESUBREG);
+ INSIST(v->subs[v->nextvalue] != NULL, REG_ESUBREG);
NOERR();
+ assert(v->nextvalue > 0);
+ atom = subre(v, 'b', BACKR, lp, rp);
+ subno = v->nextvalue;
+ atom->subno = subno;
+ EMPTYARC(lp, rp); /* temporarily, so there's something */
+ NEXT();
+ break;
+ }
- /* break remaining subRE into x{...} and what follows */
- t = subre(v, '.', COMBINE(qprefer, atom->flags), lp, rp);
- t->left = atom;
- atomp = &t->left;
- /* here we should recurse... but we must postpone that to the end */
-
- /* split top into prefix and remaining */
- assert(top->op == '=' && top->left == NULL && top->right == NULL);
- top->left = subre(v, '=', top->flags, top->begin, lp);
- top->op = '.';
- top->right = t;
-
- /* if it's a backref, now is the time to replicate the subNFA */
- if (atomtype == BACKREF) {
- assert(atom->begin->nouts == 1); /* just the EMPTY */
- delsub(v->nfa, atom->begin, atom->end);
- assert(v->subs[subno] != NULL);
- /* and here's why the recursion got postponed: it must */
- /* wait until the skeleton is filled in, because it may */
- /* hit a backref that wants to copy the filled-in skeleton */
- dupnfa(v->nfa, v->subs[subno]->begin, v->subs[subno]->end,
- atom->begin, atom->end);
- NOERR();
- }
+ /*
+ * ...and an atom may be followed by a quantifier.
+ */
- /* it's quantifier time; first, turn x{0,...} into x{1,...}|empty */
- if (m == 0) {
- EMPTYARC(s2, atom->end); /* the bypass */
- assert(PREF(qprefer) != 0);
- f = COMBINE(qprefer, atom->flags);
- t = subre(v, '|', f, lp, atom->end);
- NOERR();
- t->left = atom;
- t->right = subre(v, '|', PREF(f), s2, atom->end);
- NOERR();
- t->right->left = subre(v, '=', 0, s2, atom->end);
- NOERR();
- *atomp = t;
- atomp = &t->left;
- m = 1;
- }
+ switch (v->nexttype) {
+ case '*':
+ m = 0;
+ n = INFINITY;
+ qprefer = (v->nextvalue) ? LONGER : SHORTER;
+ NEXT();
+ break;
+ case '+':
+ m = 1;
+ n = INFINITY;
+ qprefer = (v->nextvalue) ? LONGER : SHORTER;
+ NEXT();
+ break;
+ case '?':
+ m = 0;
+ n = 1;
+ qprefer = (v->nextvalue) ? LONGER : SHORTER;
+ NEXT();
+ break;
+ case '{':
+ NEXT();
+ m = scannum(v);
+ if (EAT(',')) {
+ if (SEE(DIGIT)) {
+ n = scannum(v);
+ } else {
+ n = INFINITY;
+ }
+ if (m > n) {
+ ERR(REG_BADBR);
+ return;
+ }
+
+ /*
+ * {m,n} exercises preference, even if it's {m,m}
+ */
- /* deal with the rest of the quantifier */
- if (atomtype == BACKREF) {
- /* special case: backrefs have internal quantifiers */
- EMPTYARC(s, atom->begin); /* empty prefix */
- /* just stuff everything into atom */
- repeat(v, atom->begin, atom->end, m, n);
- atom->min = (short)m;
- atom->max = (short)n;
- atom->flags |= COMBINE(qprefer, atom->flags);
- } else if (m == 1 && n == 1) {
- /* no/vacuous quantifier: done */
- EMPTYARC(s, atom->begin); /* empty prefix */
+ qprefer = (v->nextvalue) ? LONGER : SHORTER;
} else {
- /* turn x{m,n} into x{m-1,n-1}x, with capturing */
- /* parens in only second x */
- dupnfa(v->nfa, atom->begin, atom->end, s, atom->begin);
- assert(m >= 1 && m != INFINITY && n >= 1);
- repeat(v, s, atom->begin, m-1, (n == INFINITY) ? n : n-1);
- f = COMBINE(qprefer, atom->flags);
- t = subre(v, '.', f, s, atom->end); /* prefix and atom */
- NOERR();
- t->left = subre(v, '=', PREF(f), s, atom->begin);
- NOERR();
- t->right = atom;
- *atomp = t;
+ n = m;
+ /*
+ * {m} passes operand's preference through.
+ */
+
+ qprefer = 0;
+ }
+ if (!SEE('}')) { /* catches errors too */
+ ERR(REG_BADBR);
+ return;
}
+ NEXT();
+ break;
+ default: /* no quantifier */
+ m = n = 1;
+ qprefer = 0;
+ break;
+ }
+
+ /*
+ * Annoying special case: {0} or {0,0} cancels everything.
+ */
- /* and finally, look after that postponed recursion */
- t = top->right;
- if (!(SEE('|') || SEE(stopper) || SEE(EOS)))
- t->right = parsebranch(v, stopper, type, atom->end, rp, 1);
- else {
- EMPTYARC(atom->end, rp);
- t->right = subre(v, '=', 0, atom->end, rp);
+ if (m == 0 && n == 0) {
+ if (atom != NULL) {
+ freesubre(v, atom);
}
- assert(SEE('|') || SEE(stopper) || SEE(EOS));
- t->flags |= COMBINE(t->flags, t->right->flags);
- top->flags |= COMBINE(top->flags, t->flags);
-}
+ if (atomtype == '(') {
+ v->subs[subno] = NULL;
+ }
+ delsub(v->nfa, lp, rp);
+ EMPTYARC(lp, rp);
+ return;
+ }
+
+ /*
+ * If not a messy case, avoid hard part.
+ */
+
+ assert(!MESSY(top->flags));
+ f = top->flags | qprefer | ((atom != NULL) ? atom->flags : 0);
+ if (atomtype != '(' && atomtype != BACKREF && !MESSY(UP(f))) {
+ if (!(m == 1 && n == 1)) {
+ repeat(v, lp, rp, m, n);
+ }
+ if (atom != NULL) {
+ freesubre(v, atom);
+ }
+ top->flags = f;
+ return;
+ }
+
+ /*
+ * hard part: something messy
+ * That is, capturing parens, back reference, short/long clash, or an atom
+ * with substructure containing one of those.
+ */
+
+ /*
+ * Now we'll need a subre for the contents even if they're boring.
+ */
+
+ if (atom == NULL) {
+ atom = subre(v, '=', 0, lp, rp);
+ NOERR();
+ }
+
+ /*
+ * Prepare a general-purpose state skeleton.
+ *
+ * ---> [s] ---prefix---> [begin] ---atom---> [end] ----rest---> [rp]
+ * / /
+ * [lp] ----> [s2] ----bypass---------------------
+ *
+ * where bypass is an empty, and prefix is some repetitions of atom
+ */
+
+ s = newstate(v->nfa); /* first, new endpoints for the atom */
+ s2 = newstate(v->nfa);
+ NOERR();
+ moveouts(v->nfa, lp, s);
+ moveins(v->nfa, rp, s2);
+ NOERR();
+ atom->begin = s;
+ atom->end = s2;
+ s = newstate(v->nfa); /* and spots for prefix and bypass */
+ s2 = newstate(v->nfa);
+ NOERR();
+ EMPTYARC(lp, s);
+ EMPTYARC(lp, s2);
+ NOERR();
+
+ /*
+ * Break remaining subRE into x{...} and what follows.
+ */
+
+ t = subre(v, '.', COMBINE(qprefer, atom->flags), lp, rp);
+ t->left = atom;
+ atomp = &t->left;
+
+ /*
+ * Here we should recurse... but we must postpone that to the end.
+ */
+
+ /*
+ * Split top into prefix and remaining.
+ */
+
+ assert(top->op == '=' && top->left == NULL && top->right == NULL);
+ top->left = subre(v, '=', top->flags, top->begin, lp);
+ top->op = '.';
+ top->right = t;
+
+ /*
+ * If it's a backref, now is the time to replicate the subNFA.
+ */
+
+ if (atomtype == BACKREF) {
+ assert(atom->begin->nouts == 1); /* just the EMPTY */
+ delsub(v->nfa, atom->begin, atom->end);
+ assert(v->subs[subno] != NULL);
+
+ /*
+ * And here's why the recursion got postponed: it must wait until the
+ * skeleton is filled in, because it may hit a backref that wants to
+ * copy the filled-in skeleton.
+ */
+
+ dupnfa(v->nfa, v->subs[subno]->begin, v->subs[subno]->end,
+ atom->begin, atom->end);
+ NOERR();
+ }
+ /*
+ * It's quantifier time; first, turn x{0,...} into x{1,...}|empty
+ */
+
+ if (m == 0) {
+ EMPTYARC(s2, atom->end);/* the bypass */
+ assert(PREF(qprefer) != 0);
+ f = COMBINE(qprefer, atom->flags);
+ t = subre(v, '|', f, lp, atom->end);
+ NOERR();
+ t->left = atom;
+ t->right = subre(v, '|', PREF(f), s2, atom->end);
+ NOERR();
+ t->right->left = subre(v, '=', 0, s2, atom->end);
+ NOERR();
+ *atomp = t;
+ atomp = &t->left;
+ m = 1;
+ }
+
+ /*
+ * Deal with the rest of the quantifier.
+ */
+
+ if (atomtype == BACKREF) {
+ /*
+ * Special case: backrefs have internal quantifiers.
+ */
+
+ EMPTYARC(s, atom->begin); /* empty prefix */
+
+ /*
+ * Just stuff everything into atom.
+ */
+
+ repeat(v, atom->begin, atom->end, m, n);
+ atom->min = (short) m;
+ atom->max = (short) n;
+ atom->flags |= COMBINE(qprefer, atom->flags);
+ } else if (m == 1 && n == 1) {
+ /*
+ * No/vacuous quantifier: done.
+ */
+
+ EMPTYARC(s, atom->begin); /* empty prefix */
+ } else {
+ /*
+ * Turn x{m,n} into x{m-1,n-1}x, with capturing parens in only second
+ * x
+ */
+
+ dupnfa(v->nfa, atom->begin, atom->end, s, atom->begin);
+ assert(m >= 1 && m != INFINITY && n >= 1);
+ repeat(v, s, atom->begin, m-1, (n == INFINITY) ? n : n-1);
+ f = COMBINE(qprefer, atom->flags);
+ t = subre(v, '.', f, s, atom->end); /* prefix and atom */
+ NOERR();
+ t->left = subre(v, '=', PREF(f), s, atom->begin);
+ NOERR();
+ t->right = atom;
+ *atomp = t;
+ }
+
+ /*
+ * And finally, look after that postponed recursion.
+ */
+
+ t = top->right;
+ if (!(SEE('|') || SEE(stopper) || SEE(EOS))) {
+ t->right = parsebranch(v, stopper, type, atom->end, rp, 1);
+ } else {
+ EMPTYARC(atom->end, rp);
+ t->right = subre(v, '=', 0, atom->end, rp);
+ }
+ assert(SEE('|') || SEE(stopper) || SEE(EOS));
+ t->flags |= COMBINE(t->flags, t->right->flags);
+ top->flags |= COMBINE(top->flags, t->flags);
+}
+
/*
- nonword - generate arcs for non-word-character ahead or behind
- ^ static VOID nonword(struct vars *, int, struct state *, struct state *);
+ ^ static void nonword(struct vars *, int, struct state *, struct state *);
*/
-static VOID
-nonword(v, dir, lp, rp)
-struct vars *v;
-int dir; /* AHEAD or BEHIND */
-struct state *lp;
-struct state *rp;
+static void
+nonword(
+ struct vars *v,
+ int dir, /* AHEAD or BEHIND */
+ struct state *lp,
+ struct state *rp)
{
- int anchor = (dir == AHEAD) ? '$' : '^';
+ int anchor = (dir == AHEAD) ? '$' : '^';
- assert(dir == AHEAD || dir == BEHIND);
- newarc(v->nfa, anchor, 1, lp, rp);
- newarc(v->nfa, anchor, 0, lp, rp);
- colorcomplement(v->nfa, v->cm, dir, v->wordchrs, lp, rp);
- /* (no need for special attention to \n) */
+ assert(dir == AHEAD || dir == BEHIND);
+ newarc(v->nfa, anchor, 1, lp, rp);
+ newarc(v->nfa, anchor, 0, lp, rp);
+ colorcomplement(v->nfa, v->cm, dir, v->wordchrs, lp, rp);
+ /* (no need for special attention to \n) */
}
-
+
/*
- word - generate arcs for word character ahead or behind
- ^ static VOID word(struct vars *, int, struct state *, struct state *);
+ ^ static void word(struct vars *, int, struct state *, struct state *);
*/
-static VOID
-word(v, dir, lp, rp)
-struct vars *v;
-int dir; /* AHEAD or BEHIND */
-struct state *lp;
-struct state *rp;
+static void
+word(
+ struct vars *v,
+ int dir, /* AHEAD or BEHIND */
+ struct state *lp,
+ struct state *rp)
{
- assert(dir == AHEAD || dir == BEHIND);
- cloneouts(v->nfa, v->wordchrs, lp, rp, dir);
- /* (no need for special attention to \n) */
+ assert(dir == AHEAD || dir == BEHIND);
+ cloneouts(v->nfa, v->wordchrs, lp, rp, dir);
+ /* (no need for special attention to \n) */
}
-
+
/*
- scannum - scan a number
^ static int scannum(struct vars *);
*/
static int /* value, <= DUPMAX */
-scannum(v)
-struct vars *v;
+scannum(
+ struct vars *v)
{
- int n = 0;
+ int n = 0;
- while (SEE(DIGIT) && n < DUPMAX) {
- n = n*10 + v->nextvalue;
- NEXT();
- }
- if (SEE(DIGIT) || n > DUPMAX) {
- ERR(REG_BADBR);
- return 0;
- }
- return n;
+ while (SEE(DIGIT) && n < DUPMAX) {
+ n = n*10 + v->nextvalue;
+ NEXT();
+ }
+ if (SEE(DIGIT) || n > DUPMAX) {
+ ERR(REG_BADBR);
+ return 0;
+ }
+ return n;
}
-
+
/*
- repeat - replicate subNFA for quantifiers
* The duplication sequences used here are chosen carefully so that any
* pointers starting out pointing into the subexpression end up pointing into
- * the last occurrence. (Note that it may not be strung between the same
- * left and right end states, however!) This used to be important for the
- * subRE tree, although the important bits are now handled by the in-line
- * code in parse(), and when this is called, it doesn't matter any more.
- ^ static VOID repeat(struct vars *, struct state *, struct state *, int, int);
+ * the last occurrence. (Note that it may not be strung between the same left
+ * and right end states, however!) This used to be important for the subRE
+ * tree, although the important bits are now handled by the in-line code in
+ * parse(), and when this is called, it doesn't matter any more.
+ ^ static void repeat(struct vars *, struct state *, struct state *, int, int);
*/
-static VOID
-repeat(v, lp, rp, m, n)
-struct vars *v;
-struct state *lp;
-struct state *rp;
-int m;
-int n;
+static void
+repeat(
+ struct vars *v,
+ struct state *lp,
+ struct state *rp,
+ int m,
+ int n)
{
-# define SOME 2
-# define INF 3
-# define PAIR(x, y) ((x)*4 + (y))
-# define REDUCE(x) ( ((x) == INFINITY) ? INF : (((x) > 1) ? SOME : (x)) )
- CONST int rm = REDUCE(m);
- CONST int rn = REDUCE(n);
- struct state *s;
- struct state *s2;
-
- switch (PAIR(rm, rn)) {
- case PAIR(0, 0): /* empty string */
- delsub(v->nfa, lp, rp);
- EMPTYARC(lp, rp);
- break;
- case PAIR(0, 1): /* do as x| */
- EMPTYARC(lp, rp);
- break;
- case PAIR(0, SOME): /* do as x{1,n}| */
- repeat(v, lp, rp, 1, n);
- NOERR();
- EMPTYARC(lp, rp);
- break;
- case PAIR(0, INF): /* loop x around */
- s = newstate(v->nfa);
- NOERR();
- moveouts(v->nfa, lp, s);
- moveins(v->nfa, rp, s);
- EMPTYARC(lp, s);
- EMPTYARC(s, rp);
- break;
- case PAIR(1, 1): /* no action required */
- break;
- case PAIR(1, SOME): /* do as x{0,n-1}x = (x{1,n-1}|)x */
- s = newstate(v->nfa);
- NOERR();
- moveouts(v->nfa, lp, s);
- dupnfa(v->nfa, s, rp, lp, s);
- NOERR();
- repeat(v, lp, s, 1, n-1);
- NOERR();
- EMPTYARC(lp, s);
- break;
- case PAIR(1, INF): /* add loopback arc */
- s = newstate(v->nfa);
- s2 = newstate(v->nfa);
- NOERR();
- moveouts(v->nfa, lp, s);
- moveins(v->nfa, rp, s2);
- EMPTYARC(lp, s);
- EMPTYARC(s2, rp);
- EMPTYARC(s2, s);
- break;
- case PAIR(SOME, SOME): /* do as x{m-1,n-1}x */
- s = newstate(v->nfa);
- NOERR();
- moveouts(v->nfa, lp, s);
- dupnfa(v->nfa, s, rp, lp, s);
- NOERR();
- repeat(v, lp, s, m-1, n-1);
- break;
- case PAIR(SOME, INF): /* do as x{m-1,}x */
- s = newstate(v->nfa);
- NOERR();
- moveouts(v->nfa, lp, s);
- dupnfa(v->nfa, s, rp, lp, s);
- NOERR();
- repeat(v, lp, s, m-1, n);
- break;
- default:
- ERR(REG_ASSERT);
- break;
- }
+#define SOME 2
+#define INF 3
+#define PAIR(x, y) ((x)*4 + (y))
+#define REDUCE(x) ( ((x) == INFINITY) ? INF : (((x) > 1) ? SOME : (x)) )
+ const int rm = REDUCE(m);
+ const int rn = REDUCE(n);
+ struct state *s, *s2;
+
+ switch (PAIR(rm, rn)) {
+ case PAIR(0, 0): /* empty string */
+ delsub(v->nfa, lp, rp);
+ EMPTYARC(lp, rp);
+ break;
+ case PAIR(0, 1): /* do as x| */
+ EMPTYARC(lp, rp);
+ break;
+ case PAIR(0, SOME): /* do as x{1,n}| */
+ repeat(v, lp, rp, 1, n);
+ NOERR();
+ EMPTYARC(lp, rp);
+ break;
+ case PAIR(0, INF): /* loop x around */
+ s = newstate(v->nfa);
+ NOERR();
+ moveouts(v->nfa, lp, s);
+ moveins(v->nfa, rp, s);
+ EMPTYARC(lp, s);
+ EMPTYARC(s, rp);
+ break;
+ case PAIR(1, 1): /* no action required */
+ break;
+ case PAIR(1, SOME): /* do as x{0,n-1}x = (x{1,n-1}|)x */
+ s = newstate(v->nfa);
+ NOERR();
+ moveouts(v->nfa, lp, s);
+ dupnfa(v->nfa, s, rp, lp, s);
+ NOERR();
+ repeat(v, lp, s, 1, n-1);
+ NOERR();
+ EMPTYARC(lp, s);
+ break;
+ case PAIR(1, INF): /* add loopback arc */
+ s = newstate(v->nfa);
+ s2 = newstate(v->nfa);
+ NOERR();
+ moveouts(v->nfa, lp, s);
+ moveins(v->nfa, rp, s2);
+ EMPTYARC(lp, s);
+ EMPTYARC(s2, rp);
+ EMPTYARC(s2, s);
+ break;
+ case PAIR(SOME, SOME): /* do as x{m-1,n-1}x */
+ s = newstate(v->nfa);
+ NOERR();
+ moveouts(v->nfa, lp, s);
+ dupnfa(v->nfa, s, rp, lp, s);
+ NOERR();
+ repeat(v, lp, s, m-1, n-1);
+ break;
+ case PAIR(SOME, INF): /* do as x{m-1,}x */
+ s = newstate(v->nfa);
+ NOERR();
+ moveouts(v->nfa, lp, s);
+ dupnfa(v->nfa, s, rp, lp, s);
+ NOERR();
+ repeat(v, lp, s, m-1, n);
+ break;
+ default:
+ ERR(REG_ASSERT);
+ break;
+ }
}
-
+
/*
- bracket - handle non-complemented bracket expression
* Also called from cbracket for complemented bracket expressions.
- ^ static VOID bracket(struct vars *, struct state *, struct state *);
+ ^ static void bracket(struct vars *, struct state *, struct state *);
*/
-static VOID
-bracket(v, lp, rp)
-struct vars *v;
-struct state *lp;
-struct state *rp;
+static void
+bracket(
+ struct vars *v,
+ struct state *lp,
+ struct state *rp)
{
- assert(SEE('['));
- NEXT();
- while (!SEE(']') && !SEE(EOS))
- brackpart(v, lp, rp);
- assert(SEE(']') || ISERR());
- okcolors(v->nfa, v->cm);
+ assert(SEE('['));
+ NEXT();
+ while (!SEE(']') && !SEE(EOS)) {
+ brackpart(v, lp, rp);
+ }
+ assert(SEE(']') || ISERR());
+ okcolors(v->nfa, v->cm);
}
-
+
/*
- cbracket - handle complemented bracket expression
* We do it by calling bracket() with dummy endpoints, and then complementing
- * the result. The alternative would be to invoke rainbow(), and then delete
+ * the result. The alternative would be to invoke rainbow(), and then delete
* arcs as the b.e. is seen... but that gets messy.
- ^ static VOID cbracket(struct vars *, struct state *, struct state *);
+ ^ static void cbracket(struct vars *, struct state *, struct state *);
*/
-static VOID
-cbracket(v, lp, rp)
-struct vars *v;
-struct state *lp;
-struct state *rp;
+static void
+cbracket(
+ struct vars *v,
+ struct state *lp,
+ struct state *rp)
{
- struct state *left = newstate(v->nfa);
- struct state *right = newstate(v->nfa);
- struct state *s;
- struct arc *a; /* arc from lp */
- struct arc *ba; /* arc from left, from bracket() */
- struct arc *pa; /* MCCE-prototype arc */
- color co;
- chr *p;
- int i;
+ struct state *left = newstate(v->nfa);
+ struct state *right = newstate(v->nfa);
- NOERR();
- bracket(v, left, right);
- if (v->cflags&REG_NLSTOP)
- newarc(v->nfa, PLAIN, v->nlcolor, left, right);
- NOERR();
+ NOERR();
+ bracket(v, left, right);
+ if (v->cflags&REG_NLSTOP) {
+ newarc(v->nfa, PLAIN, v->nlcolor, left, right);
+ }
+ NOERR();
- assert(lp->nouts == 0); /* all outarcs will be ours */
+ assert(lp->nouts == 0); /* all outarcs will be ours */
- /* easy part of complementing */
- colorcomplement(v->nfa, v->cm, PLAIN, left, lp, rp);
- NOERR();
- if (v->mcces == NULL) { /* no MCCEs -- we're done */
- dropstate(v->nfa, left);
- assert(right->nins == 0);
- freestate(v->nfa, right);
- return;
- }
-
- /* but complementing gets messy in the presence of MCCEs... */
- NOTE(REG_ULOCALE);
- for (p = v->mcces->chrs, i = v->mcces->nchrs; i > 0; p++, i--) {
- co = GETCOLOR(v->cm, *p);
- a = findarc(lp, PLAIN, co);
- ba = findarc(left, PLAIN, co);
- if (ba == NULL) {
- assert(a != NULL);
- freearc(v->nfa, a);
- } else {
- assert(a == NULL);
- }
- s = newstate(v->nfa);
- NOERR();
- newarc(v->nfa, PLAIN, co, lp, s);
- NOERR();
- pa = findarc(v->mccepbegin, PLAIN, co);
- assert(pa != NULL);
- if (ba == NULL) { /* easy case, need all of them */
- cloneouts(v->nfa, pa->to, s, rp, PLAIN);
- newarc(v->nfa, '$', 1, s, rp);
- newarc(v->nfa, '$', 0, s, rp);
- colorcomplement(v->nfa, v->cm, AHEAD, pa->to, s, rp);
- } else { /* must be selective */
- if (findarc(ba->to, '$', 1) == NULL) {
- newarc(v->nfa, '$', 1, s, rp);
- newarc(v->nfa, '$', 0, s, rp);
- colorcomplement(v->nfa, v->cm, AHEAD, pa->to,
- s, rp);
- }
- for (pa = pa->to->outs; pa != NULL; pa = pa->outchain)
- if (findarc(ba->to, PLAIN, pa->co) == NULL)
- newarc(v->nfa, PLAIN, pa->co, s, rp);
- if (s->nouts == 0) /* limit of selectivity: none */
- dropstate(v->nfa, s); /* frees arc too */
- }
- NOERR();
- }
+ /*
+ * Easy part of complementing, and all there is to do since the MCCE code
+ * was removed.
+ */
- delsub(v->nfa, left, right);
- assert(left->nouts == 0);
- freestate(v->nfa, left);
- assert(right->nins == 0);
- freestate(v->nfa, right);
+ colorcomplement(v->nfa, v->cm, PLAIN, left, lp, rp);
+ NOERR();
+ dropstate(v->nfa, left);
+ assert(right->nins == 0);
+ freestate(v->nfa, right);
+ return;
}
-
+
/*
- brackpart - handle one item (or range) within a bracket expression
- ^ static VOID brackpart(struct vars *, struct state *, struct state *);
+ ^ static void brackpart(struct vars *, struct state *, struct state *);
*/
-static VOID
-brackpart(v, lp, rp)
-struct vars *v;
-struct state *lp;
-struct state *rp;
+static void
+brackpart(
+ struct vars *v,
+ struct state *lp,
+ struct state *rp)
{
- celt startc;
- celt endc;
- struct cvec *cv;
- chr *startp;
- chr *endp;
- chr c[1];
-
- /* parse something, get rid of special cases, take shortcuts */
+ celt startc, endc;
+ struct cvec *cv;
+ const chr *startp, *endp;
+ chr c[1];
+
+ /*
+ * Parse something, get rid of special cases, take shortcuts.
+ */
+
+ switch (v->nexttype) {
+ case RANGE: /* a-b-c or other botch */
+ ERR(REG_ERANGE);
+ return;
+ break;
+ case PLAIN:
+ c[0] = v->nextvalue;
+ NEXT();
+
+ /*
+ * Shortcut for ordinary chr (not range).
+ */
+
+ if (!SEE(RANGE)) {
+ onechr(v, c[0], lp, rp);
+ return;
+ }
+ startc = element(v, c, c+1);
+ NOERR();
+ break;
+ case COLLEL:
+ startp = v->now;
+ endp = scanplain(v);
+ INSIST(startp < endp, REG_ECOLLATE);
+ NOERR();
+ startc = element(v, startp, endp);
+ NOERR();
+ break;
+ case ECLASS:
+ startp = v->now;
+ endp = scanplain(v);
+ INSIST(startp < endp, REG_ECOLLATE);
+ NOERR();
+ startc = element(v, startp, endp);
+ NOERR();
+ cv = eclass(v, startc, (v->cflags&REG_ICASE));
+ NOERR();
+ dovec(v, cv, lp, rp);
+ return;
+ break;
+ case CCLASS:
+ startp = v->now;
+ endp = scanplain(v);
+ INSIST(startp < endp, REG_ECTYPE);
+ NOERR();
+ cv = cclass(v, startp, endp, (v->cflags&REG_ICASE));
+ NOERR();
+ dovec(v, cv, lp, rp);
+ return;
+ break;
+ default:
+ ERR(REG_ASSERT);
+ return;
+ break;
+ }
+
+ if (SEE(RANGE)) {
+ NEXT();
switch (v->nexttype) {
- case RANGE: /* a-b-c or other botch */
- ERR(REG_ERANGE);
- return;
- break;
case PLAIN:
- c[0] = v->nextvalue;
- NEXT();
- /* shortcut for ordinary chr (not range, not MCCE leader) */
- if (!SEE(RANGE) && !ISCELEADER(v, c[0])) {
- onechr(v, c[0], lp, rp);
- return;
- }
- startc = element(v, c, c+1);
- NOERR();
- break;
+ case RANGE:
+ c[0] = v->nextvalue;
+ NEXT();
+ endc = element(v, c, c+1);
+ NOERR();
+ break;
case COLLEL:
- startp = v->now;
- endp = scanplain(v);
- INSIST(startp < endp, REG_ECOLLATE);
- NOERR();
- startc = element(v, startp, endp);
- NOERR();
- break;
- case ECLASS:
- startp = v->now;
- endp = scanplain(v);
- INSIST(startp < endp, REG_ECOLLATE);
- NOERR();
- startc = element(v, startp, endp);
- NOERR();
- cv = eclass(v, startc, (v->cflags&REG_ICASE));
- NOERR();
- dovec(v, cv, lp, rp);
- return;
- break;
- case CCLASS:
- startp = v->now;
- endp = scanplain(v);
- INSIST(startp < endp, REG_ECTYPE);
- NOERR();
- cv = cclass(v, startp, endp, (v->cflags&REG_ICASE));
- NOERR();
- dovec(v, cv, lp, rp);
- return;
- break;
+ startp = v->now;
+ endp = scanplain(v);
+ INSIST(startp < endp, REG_ECOLLATE);
+ NOERR();
+ endc = element(v, startp, endp);
+ NOERR();
+ break;
default:
- ERR(REG_ASSERT);
- return;
- break;
+ ERR(REG_ERANGE);
+ return;
+ break;
}
+ } else {
+ endc = startc;
+ }
- if (SEE(RANGE)) {
- NEXT();
- switch (v->nexttype) {
- case PLAIN:
- case RANGE:
- c[0] = v->nextvalue;
- NEXT();
- endc = element(v, c, c+1);
- NOERR();
- break;
- case COLLEL:
- startp = v->now;
- endp = scanplain(v);
- INSIST(startp < endp, REG_ECOLLATE);
- NOERR();
- endc = element(v, startp, endp);
- NOERR();
- break;
- default:
- ERR(REG_ERANGE);
- return;
- break;
- }
- } else
- endc = startc;
+ /*
+ * Ranges are unportable. Actually, standard C does guarantee that digits
+ * are contiguous, but making that an exception is just too complicated.
+ */
- /*
- * Ranges are unportable. Actually, standard C does
- * guarantee that digits are contiguous, but making
- * that an exception is just too complicated.
- */
- if (startc != endc)
- NOTE(REG_UUNPORT);
- cv = range(v, startc, endc, (v->cflags&REG_ICASE));
- NOERR();
- dovec(v, cv, lp, rp);
+ if (startc != endc) {
+ NOTE(REG_UUNPORT);
+ }
+ cv = range(v, startc, endc, (v->cflags&REG_ICASE));
+ NOERR();
+ dovec(v, cv, lp, rp);
}
-
+
/*
- scanplain - scan PLAIN contents of [. etc.
- * Certain bits of trickery in lex.c know that this code does not try
- * to look past the final bracket of the [. etc.
- ^ static chr *scanplain(struct vars *);
+ * Certain bits of trickery in lex.c know that this code does not try to look
+ * past the final bracket of the [. etc.
+ ^ static const chr *scanplain(struct vars *);
*/
-static chr * /* just after end of sequence */
-scanplain(v)
-struct vars *v;
+static const chr * /* just after end of sequence */
+scanplain(
+ struct vars *v)
{
- chr *endp;
+ const chr *endp;
- assert(SEE(COLLEL) || SEE(ECLASS) || SEE(CCLASS));
- NEXT();
+ assert(SEE(COLLEL) || SEE(ECLASS) || SEE(CCLASS));
+ NEXT();
+ endp = v->now;
+ while (SEE(PLAIN)) {
endp = v->now;
- while (SEE(PLAIN)) {
- endp = v->now;
- NEXT();
- }
-
- assert(SEE(END) || ISERR());
NEXT();
+ }
- return endp;
-}
+ assert(SEE(END) || ISERR());
+ NEXT();
-/*
- - leaders - process a cvec of collating elements to also include leaders
- * Also gives all characters involved their own colors, which is almost
- * certainly necessary, and sets up little disconnected subNFA.
- ^ static VOID leaders(struct vars *, struct cvec *);
- */
-static VOID
-leaders(v, cv)
-struct vars *v;
-struct cvec *cv;
-{
- int mcce;
- chr *p;
- chr leader;
- struct state *s;
- struct arc *a;
-
- v->mccepbegin = newstate(v->nfa);
- v->mccepend = newstate(v->nfa);
- NOERR();
-
- for (mcce = 0; mcce < cv->nmcces; mcce++) {
- p = cv->mcces[mcce];
- leader = *p;
- if (!haschr(cv, leader)) {
- addchr(cv, leader);
- s = newstate(v->nfa);
- newarc(v->nfa, PLAIN, subcolor(v->cm, leader),
- v->mccepbegin, s);
- okcolors(v->nfa, v->cm);
- } else {
- a = findarc(v->mccepbegin, PLAIN,
- GETCOLOR(v->cm, leader));
- assert(a != NULL);
- s = a->to;
- assert(s != v->mccepend);
- }
- p++;
- assert(*p != 0 && *(p+1) == 0); /* only 2-char MCCEs for now */
- newarc(v->nfa, PLAIN, subcolor(v->cm, *p), s, v->mccepend);
- okcolors(v->nfa, v->cm);
- }
+ return endp;
}
-
+
/*
- onechr - fill in arcs for a plain character, and possible case complements
* This is mostly a shortcut for efficient handling of the common case.
- ^ static VOID onechr(struct vars *, pchr, struct state *, struct state *);
+ ^ static void onechr(struct vars *, pchr, struct state *, struct state *);
*/
-static VOID
-onechr(v, c, lp, rp)
-struct vars *v;
-pchr c;
-struct state *lp;
-struct state *rp;
+static void
+onechr(
+ struct vars *v,
+ pchr c,
+ struct state *lp,
+ struct state *rp)
{
- if (!(v->cflags&REG_ICASE)) {
- newarc(v->nfa, PLAIN, subcolor(v->cm, c), lp, rp);
- return;
- }
+ if (!(v->cflags&REG_ICASE)) {
+ newarc(v->nfa, PLAIN, subcolor(v->cm, c), lp, rp);
+ return;
+ }
- /* rats, need general case anyway... */
- dovec(v, allcases(v, c), lp, rp);
-}
+ /*
+ * Rats, need general case anyway...
+ */
+ dovec(v, allcases(v, c), lp, rp);
+}
+
/*
- dovec - fill in arcs for each element of a cvec
- * This one has to handle the messy cases, like MCCEs and MCCE leaders.
- ^ static VOID dovec(struct vars *, struct cvec *, struct state *,
+ ^ static void dovec(struct vars *, struct cvec *, struct state *,
^ struct state *);
*/
-static VOID
-dovec(v, cv, lp, rp)
-struct vars *v;
-struct cvec *cv;
-struct state *lp;
-struct state *rp;
+static void
+dovec(
+ struct vars *v,
+ struct cvec *cv,
+ struct state *lp,
+ struct state *rp)
{
- chr ch, from, to;
- celt ce;
- chr *p;
- int i;
- color co;
- struct cvec *leads;
- struct arc *a;
- struct arc *pa; /* arc in prototype */
- struct state *s;
- struct state *ps; /* state in prototype */
-
- /* need a place to store leaders, if any */
- if (nmcces(v) > 0) {
- assert(v->mcces != NULL);
- if (v->cv2 == NULL || v->cv2->nchrs < v->mcces->nchrs) {
- if (v->cv2 != NULL)
- free(v->cv2);
- v->cv2 = newcvec(v->mcces->nchrs, 0, v->mcces->nmcces);
- NOERR();
- leads = v->cv2;
- } else
- leads = clearcvec(v->cv2);
- } else
- leads = NULL;
-
- /* first, get the ordinary characters out of the way */
- for (p = cv->chrs, i = cv->nchrs; i > 0; p++, i--) {
- ch = *p;
- if (!ISCELEADER(v, ch))
- newarc(v->nfa, PLAIN, subcolor(v->cm, ch), lp, rp);
- else {
- assert(singleton(v->cm, ch));
- assert(leads != NULL);
- if (!haschr(leads, ch))
- addchr(leads, ch);
- }
+ chr ch, from, to;
+ const chr *p;
+ int i;
+
+ for (p = cv->chrs, i = cv->nchrs; i > 0; p++, i--) {
+ ch = *p;
+ newarc(v->nfa, PLAIN, subcolor(v->cm, ch), lp, rp);
+ }
+
+ for (p = cv->ranges, i = cv->nranges; i > 0; p += 2, i--) {
+ from = *p;
+ to = *(p+1);
+ if (from <= to) {
+ subrange(v, from, to, lp, rp);
}
+ }
- /* and the ranges */
- for (p = cv->ranges, i = cv->nranges; i > 0; p += 2, i--) {
- from = *p;
- to = *(p+1);
- while (from <= to && (ce = nextleader(v, from, to)) != NOCELT) {
- if (from < ce)
- subrange(v, from, ce - 1, lp, rp);
- assert(singleton(v->cm, ce));
- assert(leads != NULL);
- if (!haschr(leads, ce))
- addchr(leads, ce);
- from = ce + 1;
- }
- if (from <= to)
- subrange(v, from, to, lp, rp);
- }
-
- if ((leads == NULL || leads->nchrs == 0) && cv->nmcces == 0)
- return;
-
- /* deal with the MCCE leaders */
- NOTE(REG_ULOCALE);
- for (p = leads->chrs, i = leads->nchrs; i > 0; p++, i--) {
- co = GETCOLOR(v->cm, *p);
- a = findarc(lp, PLAIN, co);
- if (a != NULL)
- s = a->to;
- else {
- s = newstate(v->nfa);
- NOERR();
- newarc(v->nfa, PLAIN, co, lp, s);
- NOERR();
- }
- pa = findarc(v->mccepbegin, PLAIN, co);
- assert(pa != NULL);
- ps = pa->to;
- newarc(v->nfa, '$', 1, s, rp);
- newarc(v->nfa, '$', 0, s, rp);
- colorcomplement(v->nfa, v->cm, AHEAD, ps, s, rp);
- NOERR();
- }
-
- /* and the MCCEs */
- for (i = 0; i < cv->nmcces; i++) {
- p = cv->mcces[i];
- assert(singleton(v->cm, *p));
- if (!singleton(v->cm, *p)) {
- ERR(REG_ASSERT);
- return;
- }
- ch = *p++;
- co = GETCOLOR(v->cm, ch);
- a = findarc(lp, PLAIN, co);
- if (a != NULL)
- s = a->to;
- else {
- s = newstate(v->nfa);
- NOERR();
- newarc(v->nfa, PLAIN, co, lp, s);
- NOERR();
- }
- assert(*p != 0); /* at least two chars */
- assert(singleton(v->cm, *p));
- ch = *p++;
- co = GETCOLOR(v->cm, ch);
- assert(*p == 0); /* and only two, for now */
- newarc(v->nfa, PLAIN, co, s, rp);
- NOERR();
- }
-}
-
-/*
- - nextleader - find next MCCE leader within range
- ^ static celt nextleader(struct vars *, pchr, pchr);
- */
-static celt /* NOCELT means none */
-nextleader(v, from, to)
-struct vars *v;
-pchr from;
-pchr to;
-{
- int i;
- chr *p;
- chr ch;
- celt it = NOCELT;
-
- if (v->mcces == NULL)
- return it;
-
- for (i = v->mcces->nchrs, p = v->mcces->chrs; i > 0; i--, p++) {
- ch = *p;
- if (from <= ch && ch <= to)
- if (it == NOCELT || ch < it)
- it = ch;
- }
- return it;
}
-
+
/*
- wordchrs - set up word-chr list for word-boundary stuff, if needed
- * The list is kept as a bunch of arcs between two dummy states; it's
- * disposed of by the unreachable-states sweep in NFA optimization.
- * Does NEXT(). Must not be called from any unusual lexical context.
- * This should be reconciled with the \w etc. handling in lex.c, and
- * should be cleaned up to reduce dependencies on input scanning.
- ^ static VOID wordchrs(struct vars *);
+ * The list is kept as a bunch of arcs between two dummy states; it's disposed
+ * of by the unreachable-states sweep in NFA optimization. Does NEXT(). Must
+ * not be called from any unusual lexical context. This should be reconciled
+ * with the \w etc. handling in lex.c, and should be cleaned up to reduce
+ * dependencies on input scanning.
+ ^ static void wordchrs(struct vars *);
*/
-static VOID
-wordchrs(v)
-struct vars *v;
+static void
+wordchrs(
+ struct vars *v)
{
- struct state *left;
- struct state *right;
+ struct state *left, *right;
- if (v->wordchrs != NULL) {
- NEXT(); /* for consistency */
- return;
- }
+ if (v->wordchrs != NULL) {
+ NEXT(); /* for consistency */
+ return;
+ }
- left = newstate(v->nfa);
- right = newstate(v->nfa);
- NOERR();
- /* fine point: implemented with [::], and lexer will set REG_ULOCALE */
- lexword(v);
- NEXT();
- assert(v->savenow != NULL && SEE('['));
- bracket(v, left, right);
- assert((v->savenow != NULL && SEE(']')) || ISERR());
- NEXT();
- NOERR();
- v->wordchrs = left;
-}
+ left = newstate(v->nfa);
+ right = newstate(v->nfa);
+ NOERR();
+ /*
+ * Fine point: implemented with [::], and lexer will set REG_ULOCALE.
+ */
+
+ lexword(v);
+ NEXT();
+ assert(v->savenow != NULL && SEE('['));
+ bracket(v, left, right);
+ assert((v->savenow != NULL && SEE(']')) || ISERR());
+ NEXT();
+ NOERR();
+ v->wordchrs = left;
+}
+
/*
- subre - allocate a subre
^ static struct subre *subre(struct vars *, int, int, struct state *,
^ struct state *);
*/
static struct subre *
-subre(v, op, flags, begin, end)
-struct vars *v;
-int op;
-int flags;
-struct state *begin;
-struct state *end;
+subre(
+ struct vars *v,
+ int op,
+ int flags,
+ struct state *begin,
+ struct state *end)
{
- struct subre *ret;
-
- ret = v->treefree;
- if (ret != NULL)
- v->treefree = ret->left;
- else {
- ret = (struct subre *)MALLOC(sizeof(struct subre));
- if (ret == NULL) {
- ERR(REG_ESPACE);
- return NULL;
- }
- ret->chain = v->treechain;
- v->treechain = ret;
+ struct subre *ret = v->treefree;
+
+ if (ret != NULL) {
+ v->treefree = ret->left;
+ } else {
+ ret = (struct subre *) MALLOC(sizeof(struct subre));
+ if (ret == NULL) {
+ ERR(REG_ESPACE);
+ return NULL;
}
-
- assert(strchr("|.b(=", op) != NULL);
-
- ret->op = op;
- ret->flags = flags;
- ret->retry = 0;
- ret->subno = 0;
- ret->min = ret->max = 1;
- ret->left = NULL;
- ret->right = NULL;
- ret->begin = begin;
- ret->end = end;
- ZAPCNFA(ret->cnfa);
-
- return ret;
+ ret->chain = v->treechain;
+ v->treechain = ret;
+ }
+
+ assert(strchr("|.b(=", op) != NULL);
+
+ ret->op = op;
+ ret->flags = flags;
+ ret->retry = 0;
+ ret->subno = 0;
+ ret->min = ret->max = 1;
+ ret->left = NULL;
+ ret->right = NULL;
+ ret->begin = begin;
+ ret->end = end;
+ ZAPCNFA(ret->cnfa);
+
+ return ret;
}
-
+
/*
- freesubre - free a subRE subtree
- ^ static VOID freesubre(struct vars *, struct subre *);
+ ^ static void freesubre(struct vars *, struct subre *);
*/
-static VOID
-freesubre(v, sr)
-struct vars *v; /* might be NULL */
-struct subre *sr;
+static void
+freesubre(
+ struct vars *v, /* might be NULL */
+ struct subre *sr)
{
- if (sr == NULL)
- return;
-
- if (sr->left != NULL)
- freesubre(v, sr->left);
- if (sr->right != NULL)
- freesubre(v, sr->right);
-
- freesrnode(v, sr);
+ if (sr == NULL) {
+ return;
+ }
+
+ if (sr->left != NULL) {
+ freesubre(v, sr->left);
+ }
+ if (sr->right != NULL) {
+ freesubre(v, sr->right);
+ }
+
+ freesrnode(v, sr);
}
-
+
/*
- freesrnode - free one node in a subRE subtree
- ^ static VOID freesrnode(struct vars *, struct subre *);
+ ^ static void freesrnode(struct vars *, struct subre *);
*/
-static VOID
-freesrnode(v, sr)
-struct vars *v; /* might be NULL */
-struct subre *sr;
+static void
+freesrnode(
+ struct vars *v, /* might be NULL */
+ struct subre *sr)
{
- if (sr == NULL)
- return;
-
- if (!NULLCNFA(sr->cnfa))
- freecnfa(&sr->cnfa);
- sr->flags = 0;
-
- if (v != NULL) {
- sr->left = v->treefree;
- v->treefree = sr;
- } else
- FREE(sr);
+ if (sr == NULL) {
+ return;
+ }
+
+ if (!NULLCNFA(sr->cnfa)) {
+ freecnfa(&sr->cnfa);
+ }
+ sr->flags = 0;
+
+ if (v != NULL) {
+ sr->left = v->treefree;
+ v->treefree = sr;
+ } else {
+ FREE(sr);
+ }
}
-
+
/*
- optst - optimize a subRE subtree
- ^ static VOID optst(struct vars *, struct subre *);
+ ^ static void optst(struct vars *, struct subre *);
*/
-static VOID
-optst(v, t)
-struct vars *v;
-struct subre *t;
+static void
+optst(
+ struct vars *v,
+ struct subre *t)
{
/*
* DGP (2007-11-13): I assume it was the programmer's intent to eventually
* come back and add code to optimize subRE trees, but the routine coded
- * just spent effort traversing the tree and doing nothing. We can do
+ * just spends effort traversing the tree and doing nothing. We can do
* nothing with less effort.
*/
return;
}
-
+
/*
- numst - number tree nodes (assigning retry indexes)
^ static int numst(struct subre *, int);
*/
static int /* next number */
-numst(t, start)
-struct subre *t;
-int start; /* starting point for subtree numbers */
+numst(
+ struct subre *t,
+ int start) /* starting point for subtree numbers */
{
- int i;
-
- assert(t != NULL);
-
- i = start;
- t->retry = (short)i++;
- if (t->left != NULL)
- i = numst(t->left, i);
- if (t->right != NULL)
- i = numst(t->right, i);
- return i;
+ int i;
+
+ assert(t != NULL);
+
+ i = start;
+ t->retry = (short) i++;
+ if (t->left != NULL) {
+ i = numst(t->left, i);
+ }
+ if (t->right != NULL) {
+ i = numst(t->right, i);
+ }
+ return i;
}
-
+
/*
- markst - mark tree nodes as INUSE
- ^ static VOID markst(struct subre *);
+ ^ static void markst(struct subre *);
*/
-static VOID
-markst(t)
-struct subre *t;
+static void
+markst(
+ struct subre *t)
{
- assert(t != NULL);
-
- t->flags |= INUSE;
- if (t->left != NULL)
- markst(t->left);
- if (t->right != NULL)
- markst(t->right);
+ assert(t != NULL);
+
+ t->flags |= INUSE;
+ if (t->left != NULL) {
+ markst(t->left);
+ }
+ if (t->right != NULL) {
+ markst(t->right);
+ }
}
-
+
/*
- cleanst - free any tree nodes not marked INUSE
- ^ static VOID cleanst(struct vars *);
+ ^ static void cleanst(struct vars *);
*/
-static VOID
-cleanst(v)
-struct vars *v;
+static void
+cleanst(
+ struct vars *v)
{
- struct subre *t;
- struct subre *next;
+ struct subre *t;
+ struct subre *next;
- for (t = v->treechain; t != NULL; t = next) {
- next = t->chain;
- if (!(t->flags&INUSE))
- FREE(t);
+ for (t = v->treechain; t != NULL; t = next) {
+ next = t->chain;
+ if (!(t->flags&INUSE)) {
+ FREE(t);
}
- v->treechain = NULL;
- v->treefree = NULL; /* just on general principles */
+ }
+ v->treechain = NULL;
+ v->treefree = NULL; /* just on general principles */
}
-
+
/*
- nfatree - turn a subRE subtree into a tree of compacted NFAs
^ static long nfatree(struct vars *, struct subre *, FILE *);
*/
static long /* optimize results from top node */
-nfatree(v, t, f)
-struct vars *v;
-struct subre *t;
-FILE *f; /* for debug output */
+nfatree(
+ struct vars *v,
+ struct subre *t,
+ FILE *f) /* for debug output */
{
- assert(t != NULL && t->begin != NULL);
+ assert(t != NULL && t->begin != NULL);
- if (t->left != NULL)
- (DISCARD)nfatree(v, t->left, f);
- if (t->right != NULL)
- (DISCARD)nfatree(v, t->right, f);
+ if (t->left != NULL) {
+ (DISCARD) nfatree(v, t->left, f);
+ }
+ if (t->right != NULL) {
+ (DISCARD) nfatree(v, t->right, f);
+ }
- return nfanode(v, t, f);
+ return nfanode(v, t, f);
}
-
+
/*
- nfanode - do one NFA for nfatree
^ static long nfanode(struct vars *, struct subre *, FILE *);
*/
static long /* optimize results */
-nfanode(v, t, f)
-struct vars *v;
-struct subre *t;
-FILE *f; /* for debug output */
+nfanode(
+ struct vars *v,
+ struct subre *t,
+ FILE *f) /* for debug output */
{
- struct nfa *nfa;
- long ret = 0;
- char idbuf[50];
-
- assert(t->begin != NULL);
-
- if (f != NULL)
- fprintf(f, "\n\n\n========= TREE NODE %s ==========\n",
- stid(t, idbuf, sizeof(idbuf)));
- nfa = newnfa(v, v->cm, v->nfa);
- NOERRZ();
- dupnfa(nfa, t->begin, t->end, nfa->init, nfa->final);
- if (!ISERR()) {
- specialcolors(nfa);
- ret = optimize(nfa, f);
- }
- if (!ISERR())
- compact(nfa, &t->cnfa);
-
- freenfa(nfa);
- return ret;
+ struct nfa *nfa;
+ long ret = 0;
+ char idbuf[50];
+
+ assert(t->begin != NULL);
+
+ if (f != NULL) {
+ fprintf(f, "\n\n\n========= TREE NODE %s ==========\n",
+ stid(t, idbuf, sizeof(idbuf)));
+ }
+ nfa = newnfa(v, v->cm, v->nfa);
+ NOERRZ();
+ dupnfa(nfa, t->begin, t->end, nfa->init, nfa->final);
+ if (!ISERR()) {
+ specialcolors(nfa);
+ ret = optimize(nfa, f);
+ }
+ if (!ISERR()) {
+ compact(nfa, &t->cnfa);
+ }
+
+ freenfa(nfa);
+ return ret;
}
-
+
/*
- newlacon - allocate a lookahead-constraint subRE
^ static int newlacon(struct vars *, struct state *, struct state *, int);
*/
static int /* lacon number */
-newlacon(v, begin, end, pos)
-struct vars *v;
-struct state *begin;
-struct state *end;
-int pos;
+newlacon(
+ struct vars *v,
+ struct state *begin,
+ struct state *end,
+ int pos)
{
- int n;
- struct subre *sub;
-
- if (v->nlacons == 0) {
- v->lacons = (struct subre *)MALLOC(2 * sizeof(struct subre));
- n = 1; /* skip 0th */
- v->nlacons = 2;
- } else {
- v->lacons = (struct subre *)REALLOC(v->lacons,
- (v->nlacons+1)*sizeof(struct subre));
- n = v->nlacons++;
- }
- if (v->lacons == NULL) {
- ERR(REG_ESPACE);
- return 0;
- }
- sub = &v->lacons[n];
- sub->begin = begin;
- sub->end = end;
- sub->subno = pos;
- ZAPCNFA(sub->cnfa);
- return n;
+ struct subre *sub;
+ int n;
+
+ if (v->nlacons == 0) {
+ v->lacons = (struct subre *) MALLOC(2 * sizeof(struct subre));
+ n = 1; /* skip 0th */
+ v->nlacons = 2;
+ } else {
+ v->lacons = (struct subre *) REALLOC(v->lacons,
+ (v->nlacons+1)*sizeof(struct subre));
+ n = v->nlacons++;
+ }
+
+ if (v->lacons == NULL) {
+ ERR(REG_ESPACE);
+ return 0;
+ }
+
+ sub = &v->lacons[n];
+ sub->begin = begin;
+ sub->end = end;
+ sub->subno = pos;
+ ZAPCNFA(sub->cnfa);
+ return n;
}
-
+
/*
- freelacons - free lookahead-constraint subRE vector
- ^ static VOID freelacons(struct subre *, int);
+ ^ static void freelacons(struct subre *, int);
*/
-static VOID
-freelacons(subs, n)
-struct subre *subs;
-int n;
+static void
+freelacons(
+ struct subre *subs,
+ int n)
{
- struct subre *sub;
- int i;
-
- assert(n > 0);
- for (sub = subs + 1, i = n - 1; i > 0; sub++, i--) /* no 0th */
- if (!NULLCNFA(sub->cnfa))
- freecnfa(&sub->cnfa);
- FREE(subs);
-}
+ struct subre *sub;
+ int i;
+ assert(n > 0);
+ for (sub=subs+1, i=n-1; i>0; sub++, i--) { /* no 0th */
+ if (!NULLCNFA(sub->cnfa)) {
+ freecnfa(&sub->cnfa);
+ }
+ }
+ FREE(subs);
+}
+
/*
- rfree - free a whole RE (insides of regfree)
- ^ static VOID rfree(regex_t *);
+ ^ static void rfree(regex_t *);
*/
-static VOID
-rfree(re)
-regex_t *re;
+static void
+rfree(
+ regex_t *re)
{
- struct guts *g;
-
- if (re == NULL || re->re_magic != REMAGIC)
- return;
-
- re->re_magic = 0; /* invalidate RE */
- g = (struct guts *)re->re_guts;
- re->re_guts = NULL;
- re->re_fns = NULL;
- g->magic = 0;
- freecm(&g->cmap);
- if (g->tree != NULL)
- freesubre((struct vars *)NULL, g->tree);
- if (g->lacons != NULL)
- freelacons(g->lacons, g->nlacons);
- if (!NULLCNFA(g->search))
- freecnfa(&g->search);
- FREE(g);
+ struct guts *g;
+
+ if (re == NULL || re->re_magic != REMAGIC) {
+ return;
+ }
+
+ re->re_magic = 0; /* invalidate RE */
+ g = (struct guts *) re->re_guts;
+ re->re_guts = NULL;
+ re->re_fns = NULL;
+ g->magic = 0;
+ freecm(&g->cmap);
+ if (g->tree != NULL) {
+ freesubre(NULL, g->tree);
+ }
+ if (g->lacons != NULL) {
+ freelacons(g->lacons, g->nlacons);
+ }
+ if (!NULLCNFA(g->search)) {
+ freecnfa(&g->search);
+ }
+ FREE(g);
}
-
+
/*
- dump - dump an RE in human-readable form
- ^ static VOID dump(regex_t *, FILE *);
+ ^ static void dump(regex_t *, FILE *);
*/
-static VOID
-dump(re, f)
-regex_t *re;
-FILE *f;
+static void
+dump(
+ regex_t *re,
+ FILE *f)
{
#ifdef REG_DEBUG
- struct guts *g;
- int i;
-
- if (re->re_magic != REMAGIC)
- fprintf(f, "bad magic number (0x%x not 0x%x)\n", re->re_magic,
- REMAGIC);
- if (re->re_guts == NULL) {
- fprintf(f, "NULL guts!!!\n");
- return;
- }
- g = (struct guts *)re->re_guts;
- if (g->magic != GUTSMAGIC)
- fprintf(f, "bad guts magic number (0x%x not 0x%x)\n", g->magic,
- GUTSMAGIC);
-
- fprintf(f, "\n\n\n========= DUMP ==========\n");
- fprintf(f, "nsub %d, info 0%lo, csize %d, ntree %d\n",
- re->re_nsub, re->re_info, re->re_csize, g->ntree);
-
- dumpcolors(&g->cmap, f);
- if (!NULLCNFA(g->search)) {
- printf("\nsearch:\n");
- dumpcnfa(&g->search, f);
- }
- for (i = 1; i < g->nlacons; i++) {
- fprintf(f, "\nla%d (%s):\n", i,
- (g->lacons[i].subno) ? "positive" : "negative");
- dumpcnfa(&g->lacons[i].cnfa, f);
- }
- fprintf(f, "\n");
- dumpst(g->tree, f, 0);
+ struct guts *g;
+ int i;
+
+ if (re->re_magic != REMAGIC) {
+ fprintf(f, "bad magic number (0x%x not 0x%x)\n",
+ re->re_magic, REMAGIC);
+ }
+ if (re->re_guts == NULL) {
+ fprintf(f, "NULL guts!!!\n");
+ return;
+ }
+ g = (struct guts *) re->re_guts;
+ if (g->magic != GUTSMAGIC) {
+ fprintf(f, "bad guts magic number (0x%x not 0x%x)\n",
+ g->magic, GUTSMAGIC);
+ }
+
+ fprintf(f, "\n\n\n========= DUMP ==========\n");
+ fprintf(f, "nsub %d, info 0%lo, csize %d, ntree %d\n",
+ re->re_nsub, re->re_info, re->re_csize, g->ntree);
+
+ dumpcolors(&g->cmap, f);
+ if (!NULLCNFA(g->search)) {
+ printf("\nsearch:\n");
+ dumpcnfa(&g->search, f);
+ }
+ for (i = 1; i < g->nlacons; i++) {
+ fprintf(f, "\nla%d (%s):\n", i,
+ (g->lacons[i].subno) ? "positive" : "negative");
+ dumpcnfa(&g->lacons[i].cnfa, f);
+ }
+ fprintf(f, "\n");
+ dumpst(g->tree, f, 0);
#endif
}
-
+
/*
- dumpst - dump a subRE tree
- ^ static VOID dumpst(struct subre *, FILE *, int);
+ ^ static void dumpst(struct subre *, FILE *, int);
*/
-static VOID
-dumpst(t, f, nfapresent)
-struct subre *t;
-FILE *f;
-int nfapresent; /* is the original NFA still around? */
+static void
+dumpst(
+ struct subre *t,
+ FILE *f,
+ int nfapresent) /* is the original NFA still around? */
{
- if (t == NULL)
- fprintf(f, "null tree\n");
- else
- stdump(t, f, nfapresent);
- fflush(f);
+ if (t == NULL) {
+ fprintf(f, "null tree\n");
+ } else {
+ stdump(t, f, nfapresent);
+ }
+ fflush(f);
}
-
+
/*
- stdump - recursive guts of dumpst
- ^ static VOID stdump(struct subre *, FILE *, int);
+ ^ static void stdump(struct subre *, FILE *, int);
*/
-static VOID
-stdump(t, f, nfapresent)
-struct subre *t;
-FILE *f;
-int nfapresent; /* is the original NFA still around? */
+static void
+stdump(
+ struct subre *t,
+ FILE *f,
+ int nfapresent) /* is the original NFA still around? */
{
- char idbuf[50];
-
- fprintf(f, "%s. `%c'", stid(t, idbuf, sizeof(idbuf)), t->op);
- if (t->flags&LONGER)
- fprintf(f, " longest");
- if (t->flags&SHORTER)
- fprintf(f, " shortest");
- if (t->flags&MIXED)
- fprintf(f, " hasmixed");
- if (t->flags&CAP)
- fprintf(f, " hascapture");
- if (t->flags&BACKR)
- fprintf(f, " hasbackref");
- if (!(t->flags&INUSE))
- fprintf(f, " UNUSED");
- if (t->subno != 0)
- fprintf(f, " (#%d)", t->subno);
- if (t->min != 1 || t->max != 1) {
- fprintf(f, " {%d,", t->min);
- if (t->max != INFINITY)
- fprintf(f, "%d", t->max);
- fprintf(f, "}");
- }
- if (nfapresent)
- fprintf(f, " %ld-%ld", (long)t->begin->no, (long)t->end->no);
- if (t->left != NULL)
- fprintf(f, " L:%s", stid(t->left, idbuf, sizeof(idbuf)));
- if (t->right != NULL)
- fprintf(f, " R:%s", stid(t->right, idbuf, sizeof(idbuf)));
- if (!NULLCNFA(t->cnfa)) {
- fprintf(f, "\n");
- dumpcnfa(&t->cnfa, f);
+ char idbuf[50];
+
+ fprintf(f, "%s. `%c'", stid(t, idbuf, sizeof(idbuf)), t->op);
+ if (t->flags&LONGER) {
+ fprintf(f, " longest");
+ }
+ if (t->flags&SHORTER) {
+ fprintf(f, " shortest");
+ }
+ if (t->flags&MIXED) {
+ fprintf(f, " hasmixed");
+ }
+ if (t->flags&CAP) {
+ fprintf(f, " hascapture");
+ }
+ if (t->flags&BACKR) {
+ fprintf(f, " hasbackref");
+ }
+ if (!(t->flags&INUSE)) {
+ fprintf(f, " UNUSED");
+ }
+ if (t->subno != 0) {
+ fprintf(f, " (#%d)", t->subno);
+ }
+ if (t->min != 1 || t->max != 1) {
+ fprintf(f, " {%d,", t->min);
+ if (t->max != INFINITY) {
+ fprintf(f, "%d", t->max);
}
+ fprintf(f, "}");
+ }
+ if (nfapresent) {
+ fprintf(f, " %ld-%ld", (long)t->begin->no, (long)t->end->no);
+ }
+ if (t->left != NULL) {
+ fprintf(f, " L:%s", stid(t->left, idbuf, sizeof(idbuf)));
+ }
+ if (t->right != NULL) {
+ fprintf(f, " R:%s", stid(t->right, idbuf, sizeof(idbuf)));
+ }
+ if (!NULLCNFA(t->cnfa)) {
fprintf(f, "\n");
- if (t->left != NULL)
- stdump(t->left, f, nfapresent);
- if (t->right != NULL)
- stdump(t->right, f, nfapresent);
+ dumpcnfa(&t->cnfa, f);
+ }
+ fprintf(f, "\n");
+ if (t->left != NULL) {
+ stdump(t->left, f, nfapresent);
+ }
+ if (t->right != NULL) {
+ stdump(t->right, f, nfapresent);
+ }
}
-
+
/*
- stid - identify a subtree node for dumping
- ^ static char *stid(struct subre *, char *, size_t);
+ ^ static const char *stid(struct subre *, char *, size_t);
*/
-static char * /* points to buf or constant string */
-stid(t, buf, bufsize)
-struct subre *t;
-char *buf;
-size_t bufsize;
+static const char * /* points to buf or constant string */
+stid(
+ struct subre *t,
+ char *buf,
+ size_t bufsize)
{
- /* big enough for hex int or decimal t->retry? */
- if (bufsize < sizeof(void*)*2 + 3 || bufsize < sizeof(t->retry)*3 + 1)
- return "unable";
- if (t->retry != 0)
- sprintf(buf, "%d", t->retry);
- else
- sprintf(buf, "%p", t);
- return buf;
+ /*
+ * Big enough for hex int or decimal t->retry?
+ */
+
+ if (bufsize < sizeof(void*)*2 + 3 || bufsize < sizeof(t->retry)*3 + 1) {
+ return "unable";
+ }
+ if (t->retry != 0) {
+ sprintf(buf, "%d", t->retry);
+ } else {
+ sprintf(buf, "%p", t);
+ }
+ return buf;
}
#include "regc_lex.c"
@@ -2177,3 +2159,11 @@ size_t bufsize;
#include "regc_nfa.c"
#include "regc_cvec.c"
#include "regc_locale.c"
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/regcustom.h b/generic/regcustom.h
index e258acd..ac33087 100644
--- a/generic/regcustom.h
+++ b/generic/regcustom.h
@@ -1,22 +1,22 @@
/*
* Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
- *
+ *
* Development of this software was funded, in part, by Cray Research Inc.,
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
- * Corporation, none of whom are responsible for the results. The author
- * thanks all of them.
- *
- * Redistribution and use in source and binary forms -- with or without
- * modification -- are permitted for any purpose, provided that
- * redistributions in source form retain this entire copyright notice and
- * indicate the origin and nature of any modifications.
- *
- * I'd appreciate being given credit for this package in the documentation
- * of software which uses it, but that is not a requirement.
- *
+ * Corporation, none of whom are responsible for the results. The author
+ * thanks all of them.
+ *
+ * Redistribution and use in source and binary forms - with or without
+ * modification - are permitted for any purpose, provided that redistributions
+ * in source form retain this entire copyright notice and indicate the origin
+ * and nature of any modifications.
+ *
+ * I'd appreciate being given credit for this package in the documentation of
+ * software which uses it, but that is not a requirement.
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
@@ -26,23 +26,28 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* headers if any */
+/*
+ * Headers if any.
+ */
+
#include "tclInt.h"
-/* overrides for regguts.h definitions, if any */
-#define FUNCPTR(name, args) (*name) _ANSI_ARGS_(args)
+/*
+ * Overrides for regguts.h definitions, if any.
+ */
+
+#define FUNCPTR(name, args) (*name)args
#define MALLOC(n) ckalloc(n)
#define FREE(p) ckfree(VS(p))
#define REALLOC(p,n) ckrealloc(VS(p),n)
-
-
/*
- * Do not insert extras between the "begin" and "end" lines -- this
- * chunk is automatically extracted to be fitted into regex.h.
+ * Do not insert extras between the "begin" and "end" lines - this chunk is
+ * automatically extracted to be fitted into regex.h.
*/
+
/* --- begin --- */
-/* ensure certain things don't sneak in from system headers */
+/* Ensure certain things don't sneak in from system headers. */
#ifdef __REG_WIDE_T
#undef __REG_WIDE_T
#endif
@@ -67,54 +72,90 @@
#ifdef __REG_NOCHAR
#undef __REG_NOCHAR
#endif
-/* interface types */
+/* Interface types */
#define __REG_WIDE_T Tcl_UniChar
-#define __REG_REGOFF_T long /* not really right, but good enough... */
-#define __REG_VOID_T VOID
-#define __REG_CONST CONST
-/* names and declarations */
+#define __REG_REGOFF_T long /* Not really right, but good enough... */
+#define __REG_VOID_T void
+#define __REG_CONST const
+/* Names and declarations */
#define __REG_WIDE_COMPILE TclReComp
#define __REG_WIDE_EXEC TclReExec
-#define __REG_NOFRONT /* don't want regcomp() and regexec() */
-#define __REG_NOCHAR /* or the char versions */
+#define __REG_NOFRONT /* Don't want regcomp() and regexec() */
+#define __REG_NOCHAR /* Or the char versions */
#define regfree TclReFree
#define regerror TclReError
/* --- end --- */
+/*
+ * Internal character type and related.
+ */
-
-/* internal character type and related */
-typedef Tcl_UniChar chr; /* the type itself */
-typedef int pchr; /* what it promotes to */
-typedef unsigned uchr; /* unsigned type that will hold a chr */
-typedef int celt; /* type to hold chr, MCCE number, or NOCELT */
-#define NOCELT (-1) /* celt value which is not valid chr or MCCE */
-#define CHR(c) (UCHAR(c)) /* turn char literal into chr literal */
-#define DIGITVAL(c) ((c)-'0') /* turn chr digit into its value */
+typedef Tcl_UniChar chr; /* The type itself. */
+typedef int pchr; /* What it promotes to. */
+typedef unsigned uchr; /* Unsigned type that will hold a chr. */
+typedef int celt; /* Type to hold chr, or NOCELT */
+#define NOCELT (-1) /* Celt value which is not valid chr */
+#define CHR(c) (UCHAR(c)) /* Turn char literal into chr literal */
+#define DIGITVAL(c) ((c)-'0') /* Turn chr digit into its value */
#if TCL_UTF_MAX > 3
-#define CHRBITS 32 /* bits in a chr; must not use sizeof */
-#define CHR_MIN 0x00000000 /* smallest and largest chr; the value */
-#define CHR_MAX 0xffffffff /* CHR_MAX-CHR_MIN+1 should fit in uchr */
+#define CHRBITS 32 /* Bits in a chr; must not use sizeof */
+#define CHR_MIN 0x00000000 /* Smallest and largest chr; the value */
+#define CHR_MAX 0xffffffff /* CHR_MAX-CHR_MIN+1 should fit in uchr */
#else
-#define CHRBITS 16 /* bits in a chr; must not use sizeof */
-#define CHR_MIN 0x0000 /* smallest and largest chr; the value */
-#define CHR_MAX 0xffff /* CHR_MAX-CHR_MIN+1 should fit in uchr */
+#define CHRBITS 16 /* Bits in a chr; must not use sizeof */
+#define CHR_MIN 0x0000 /* Smallest and largest chr; the value */
+#define CHR_MAX 0xffff /* CHR_MAX-CHR_MIN+1 should fit in uchr */
#endif
-/* functions operating on chr */
+/*
+ * Functions operating on chr.
+ */
+
#define iscalnum(x) Tcl_UniCharIsAlnum(x)
#define iscalpha(x) Tcl_UniCharIsAlpha(x)
#define iscdigit(x) Tcl_UniCharIsDigit(x)
#define iscspace(x) Tcl_UniCharIsSpace(x)
-/* name the external functions */
+/*
+ * Name the external functions.
+ */
+
#define compile TclReComp
#define exec TclReExec
-/* enable/disable debugging code (by whether REG_DEBUG is defined or not) */
-#if 0 /* no debug unless requested by makefile */
+/*
+& Enable/disable debugging code (by whether REG_DEBUG is defined or not).
+*/
+
+#if 0 /* No debug unless requested by makefile. */
#define REG_DEBUG /* */
#endif
-/* and pick up the standard header */
+/*
+ * Method of allocating a local workspace. We used a thread-specific data
+ * space to store this because the regular expression engine is never
+ * reentered from the same thread; it doesn't make any callbacks.
+ */
+
+#if 1
+#define AllocVars(vPtr) \
+ static Tcl_ThreadDataKey varsKey; \
+ register struct vars *vPtr = (struct vars *) \
+ Tcl_GetThreadData(&varsKey, sizeof(struct vars))
+#else
+/*
+ * This strategy for allocating workspace is "more proper" in some sense, but
+ * quite a bit slower. Using TSD (as above) leads to code that is quite a bit
+ * faster in practice (measured!)
+ */
+#define AllocVars(vPtr) \
+ register struct vars *vPtr = (struct vars *) MALLOC(sizeof(struct vars))
+#define FreeVars(vPtr) \
+ FREE(vPtr)
+#endif
+
+/*
+ * And pick up the standard header.
+ */
+
#include "regex.h"
diff --git a/generic/rege_dfa.c b/generic/rege_dfa.c
index bc391fd..e233680 100644
--- a/generic/rege_dfa.c
+++ b/generic/rege_dfa.c
@@ -3,20 +3,20 @@
* This file is #included by regexec.c.
*
* Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
- *
+ *
* Development of this software was funded, in part, by Cray Research Inc.,
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
* Corporation, none of whom are responsible for the results. The author
- * thanks all of them.
- *
+ * thanks all of them.
+ *
* Redistribution and use in source and binary forms -- with or without
* modification -- are permitted for any purpose, provided that
* redistributions in source form retain this entire copyright notice and
* indicate the origin and nature of any modifications.
- *
+ *
* I'd appreciate being given credit for this package in the documentation
* of software which uses it, but that is not a requirement.
- *
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -29,521 +29,620 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
-
+
/*
- longest - longest-preferred matching engine
^ static chr *longest(struct vars *, struct dfa *, chr *, chr *, int *);
*/
static chr * /* endpoint, or NULL */
-longest(v, d, start, stop, hitstopp)
-struct vars *v; /* used only for debug and exec flags */
-struct dfa *d;
-chr *start; /* where the match should start */
-chr *stop; /* match must end at or before here */
-int *hitstopp; /* record whether hit v->stop, if non-NULL */
+longest(
+ struct vars *v, /* used only for debug and exec flags */
+ struct dfa *d,
+ chr *start, /* where the match should start */
+ chr *stop, /* match must end at or before here */
+ int *hitstopp) /* record whether hit v->stop, if non-NULL */
{
- chr *cp;
- chr *realstop = (stop == v->stop) ? stop : stop + 1;
- color co;
- struct sset *css;
- struct sset *ss;
- chr *post;
- int i;
- struct colormap *cm = d->cm;
-
- /* initialize */
- css = initialize(v, d, start);
- cp = start;
- if (hitstopp != NULL)
- *hitstopp = 0;
-
- /* startup */
- FDEBUG(("+++ startup +++\n"));
- if (cp == v->start) {
- co = d->cnfa->bos[(v->eflags&REG_NOTBOL) ? 0 : 1];
- FDEBUG(("color %ld\n", (long)co));
- } else {
- co = GETCOLOR(cm, *(cp - 1));
- FDEBUG(("char %c, color %ld\n", (char)*(cp-1), (long)co));
- }
- css = miss(v, d, css, co, cp, start);
- if (css == NULL)
- return NULL;
- css->lastseen = cp;
-
- /* main loop */
- if (v->eflags&REG_FTRACE)
- while (cp < realstop) {
- FDEBUG(("+++ at c%d +++\n", css - d->ssets));
- co = GETCOLOR(cm, *cp);
- FDEBUG(("char %c, color %ld\n", (char)*cp, (long)co));
- ss = css->outs[co];
- if (ss == NULL) {
- ss = miss(v, d, css, co, cp+1, start);
- if (ss == NULL)
- break; /* NOTE BREAK OUT */
- }
- cp++;
- ss->lastseen = cp;
- css = ss;
+ chr *cp;
+ chr *realstop = (stop == v->stop) ? stop : stop + 1;
+ color co;
+ struct sset *css;
+ struct sset *ss;
+ chr *post;
+ int i;
+ struct colormap *cm = d->cm;
+
+ /*
+ * Initialize.
+ */
+
+ css = initialize(v, d, start);
+ cp = start;
+ if (hitstopp != NULL) {
+ *hitstopp = 0;
+ }
+
+ /*
+ * Startup.
+ */
+
+ FDEBUG(("+++ startup +++\n"));
+ if (cp == v->start) {
+ co = d->cnfa->bos[(v->eflags&REG_NOTBOL) ? 0 : 1];
+ FDEBUG(("color %ld\n", (long)co));
+ } else {
+ co = GETCOLOR(cm, *(cp - 1));
+ FDEBUG(("char %c, color %ld\n", (char)*(cp-1), (long)co));
+ }
+ css = miss(v, d, css, co, cp, start);
+ if (css == NULL) {
+ return NULL;
+ }
+ css->lastseen = cp;
+
+ /*
+ * Main loop.
+ */
+
+ if (v->eflags&REG_FTRACE) {
+ while (cp < realstop) {
+ FDEBUG(("+++ at c%d +++\n", css - d->ssets));
+ co = GETCOLOR(cm, *cp);
+ FDEBUG(("char %c, color %ld\n", (char)*cp, (long)co));
+ ss = css->outs[co];
+ if (ss == NULL) {
+ ss = miss(v, d, css, co, cp+1, start);
+ if (ss == NULL) {
+ break; /* NOTE BREAK OUT */
}
- else
- while (cp < realstop) {
- co = GETCOLOR(cm, *cp);
- ss = css->outs[co];
- if (ss == NULL) {
- ss = miss(v, d, css, co, cp+1, start);
- if (ss == NULL)
- break; /* NOTE BREAK OUT */
- }
- cp++;
- ss->lastseen = cp;
- css = ss;
+ }
+ cp++;
+ ss->lastseen = cp;
+ css = ss;
+ }
+ } else {
+ while (cp < realstop) {
+ co = GETCOLOR(cm, *cp);
+ ss = css->outs[co];
+ if (ss == NULL) {
+ ss = miss(v, d, css, co, cp+1, start);
+ if (ss == NULL) {
+ break; /* NOTE BREAK OUT */
}
+ }
+ cp++;
+ ss->lastseen = cp;
+ css = ss;
+ }
+ }
- /* shutdown */
- FDEBUG(("+++ shutdown at c%d +++\n", css - d->ssets));
- if (cp == v->stop && stop == v->stop) {
- if (hitstopp != NULL)
- *hitstopp = 1;
- co = d->cnfa->eos[(v->eflags&REG_NOTEOL) ? 0 : 1];
- FDEBUG(("color %ld\n", (long)co));
- ss = miss(v, d, css, co, cp, start);
- /* special case: match ended at eol? */
- if (ss != NULL && (ss->flags&POSTSTATE))
- return cp;
- else if (ss != NULL)
- ss->lastseen = cp; /* to be tidy */
+ /*
+ * Shutdown.
+ */
+
+ FDEBUG(("+++ shutdown at c%d +++\n", css - d->ssets));
+ if (cp == v->stop && stop == v->stop) {
+ if (hitstopp != NULL) {
+ *hitstopp = 1;
+ }
+ co = d->cnfa->eos[(v->eflags&REG_NOTEOL) ? 0 : 1];
+ FDEBUG(("color %ld\n", (long)co));
+ ss = miss(v, d, css, co, cp, start);
+
+ /*
+ * Special case: match ended at eol?
+ */
+
+ if (ss != NULL && (ss->flags&POSTSTATE)) {
+ return cp;
+ } else if (ss != NULL) {
+ ss->lastseen = cp; /* to be tidy */
}
+ }
- /* find last match, if any */
- post = d->lastpost;
- for (ss = d->ssets, i = d->nssused; i > 0; ss++, i--)
- if ((ss->flags&POSTSTATE) && post != ss->lastseen &&
- (post == NULL || post < ss->lastseen))
- post = ss->lastseen;
- if (post != NULL) /* found one */
- return post - 1;
+ /*
+ * Find last match, if any.
+ */
- return NULL;
-}
+ post = d->lastpost;
+ for (ss = d->ssets, i = d->nssused; i > 0; ss++, i--) {
+ if ((ss->flags&POSTSTATE) && (post != ss->lastseen) &&
+ (post == NULL || post < ss->lastseen)) {
+ post = ss->lastseen;
+ }
+ }
+ if (post != NULL) { /* found one */
+ return post - 1;
+ }
+ return NULL;
+}
+
/*
- shortest - shortest-preferred matching engine
^ static chr *shortest(struct vars *, struct dfa *, chr *, chr *, chr *,
^ chr **, int *);
*/
static chr * /* endpoint, or NULL */
-shortest(v, d, start, min, max, coldp, hitstopp)
-struct vars *v;
-struct dfa *d;
-chr *start; /* where the match should start */
-chr *min; /* match must end at or after here */
-chr *max; /* match must end at or before here */
-chr **coldp; /* store coldstart pointer here, if nonNULL */
-int *hitstopp; /* record whether hit v->stop, if non-NULL */
+shortest(
+ struct vars *v,
+ struct dfa *d,
+ chr *start, /* where the match should start */
+ chr *min, /* match must end at or after here */
+ chr *max, /* match must end at or before here */
+ chr **coldp, /* store coldstart pointer here, if nonNULL */
+ int *hitstopp) /* record whether hit v->stop, if non-NULL */
{
- chr *cp;
- chr *realmin = (min == v->stop) ? min : min + 1;
- chr *realmax = (max == v->stop) ? max : max + 1;
- color co;
- struct sset *css;
- struct sset *ss;
- struct colormap *cm = d->cm;
-
- /* initialize */
- css = initialize(v, d, start);
- cp = start;
- if (hitstopp != NULL)
- *hitstopp = 0;
-
- /* startup */
- FDEBUG(("--- startup ---\n"));
- if (cp == v->start) {
- co = d->cnfa->bos[(v->eflags&REG_NOTBOL) ? 0 : 1];
- FDEBUG(("color %ld\n", (long)co));
- } else {
- co = GETCOLOR(cm, *(cp - 1));
- FDEBUG(("char %c, color %ld\n", (char)*(cp-1), (long)co));
- }
- css = miss(v, d, css, co, cp, start);
- if (css == NULL)
- return NULL;
- css->lastseen = cp;
- ss = css;
-
- /* main loop */
- if (v->eflags&REG_FTRACE)
- while (cp < realmax) {
- FDEBUG(("--- at c%d ---\n", css - d->ssets));
- co = GETCOLOR(cm, *cp);
- FDEBUG(("char %c, color %ld\n", (char)*cp, (long)co));
- ss = css->outs[co];
- if (ss == NULL) {
- ss = miss(v, d, css, co, cp+1, start);
- if (ss == NULL)
- break; /* NOTE BREAK OUT */
- }
- cp++;
- ss->lastseen = cp;
- css = ss;
- if ((ss->flags&POSTSTATE) && cp >= realmin)
- break; /* NOTE BREAK OUT */
+ chr *cp;
+ chr *realmin = (min == v->stop) ? min : min + 1;
+ chr *realmax = (max == v->stop) ? max : max + 1;
+ color co;
+ struct sset *css;
+ struct sset *ss;
+ struct colormap *cm = d->cm;
+
+ /*
+ * Initialize.
+ */
+
+ css = initialize(v, d, start);
+ cp = start;
+ if (hitstopp != NULL) {
+ *hitstopp = 0;
+ }
+
+ /*
+ * Startup.
+ */
+
+ FDEBUG(("--- startup ---\n"));
+ if (cp == v->start) {
+ co = d->cnfa->bos[(v->eflags&REG_NOTBOL) ? 0 : 1];
+ FDEBUG(("color %ld\n", (long)co));
+ } else {
+ co = GETCOLOR(cm, *(cp - 1));
+ FDEBUG(("char %c, color %ld\n", (char)*(cp-1), (long)co));
+ }
+ css = miss(v, d, css, co, cp, start);
+ if (css == NULL) {
+ return NULL;
+ }
+ css->lastseen = cp;
+ ss = css;
+
+ /*
+ * Main loop.
+ */
+
+ if (v->eflags&REG_FTRACE) {
+ while (cp < realmax) {
+ FDEBUG(("--- at c%d ---\n", css - d->ssets));
+ co = GETCOLOR(cm, *cp);
+ FDEBUG(("char %c, color %ld\n", (char)*cp, (long)co));
+ ss = css->outs[co];
+ if (ss == NULL) {
+ ss = miss(v, d, css, co, cp+1, start);
+ if (ss == NULL) {
+ break; /* NOTE BREAK OUT */
}
- else
- while (cp < realmax) {
- co = GETCOLOR(cm, *cp);
- ss = css->outs[co];
- if (ss == NULL) {
- ss = miss(v, d, css, co, cp+1, start);
- if (ss == NULL)
- break; /* NOTE BREAK OUT */
- }
- cp++;
- ss->lastseen = cp;
- css = ss;
- if ((ss->flags&POSTSTATE) && cp >= realmin)
- break; /* NOTE BREAK OUT */
+ }
+ cp++;
+ ss->lastseen = cp;
+ css = ss;
+ if ((ss->flags&POSTSTATE) && cp >= realmin) {
+ break; /* NOTE BREAK OUT */
+ }
+ }
+ } else {
+ while (cp < realmax) {
+ co = GETCOLOR(cm, *cp);
+ ss = css->outs[co];
+ if (ss == NULL) {
+ ss = miss(v, d, css, co, cp+1, start);
+ if (ss == NULL) {
+ break; /* NOTE BREAK OUT */
}
+ }
+ cp++;
+ ss->lastseen = cp;
+ css = ss;
+ if ((ss->flags&POSTSTATE) && cp >= realmin) {
+ break; /* NOTE BREAK OUT */
+ }
+ }
+ }
- if (ss == NULL)
- return NULL;
-
- if (coldp != NULL) /* report last no-progress state set, if any */
- *coldp = lastcold(v, d);
-
- if ((ss->flags&POSTSTATE) && cp > min) {
- assert(cp >= realmin);
- cp--;
- } else if (cp == v->stop && max == v->stop) {
- co = d->cnfa->eos[(v->eflags&REG_NOTEOL) ? 0 : 1];
- FDEBUG(("color %ld\n", (long)co));
- ss = miss(v, d, css, co, cp, start);
- /* match might have ended at eol */
- if ((ss == NULL || !(ss->flags&POSTSTATE)) && hitstopp != NULL)
- *hitstopp = 1;
+ if (ss == NULL) {
+ return NULL;
+ }
+
+ if (coldp != NULL) { /* report last no-progress state set, if any */
+ *coldp = lastcold(v, d);
+ }
+
+ if ((ss->flags&POSTSTATE) && cp > min) {
+ assert(cp >= realmin);
+ cp--;
+ } else if (cp == v->stop && max == v->stop) {
+ co = d->cnfa->eos[(v->eflags&REG_NOTEOL) ? 0 : 1];
+ FDEBUG(("color %ld\n", (long)co));
+ ss = miss(v, d, css, co, cp, start);
+
+ /*
+ * Match might have ended at eol.
+ */
+
+ if ((ss == NULL || !(ss->flags&POSTSTATE)) && hitstopp != NULL) {
+ *hitstopp = 1;
}
+ }
- if (ss == NULL || !(ss->flags&POSTSTATE))
- return NULL;
+ if (ss == NULL || !(ss->flags&POSTSTATE)) {
+ return NULL;
+ }
- return cp;
+ return cp;
}
-
+
/*
- lastcold - determine last point at which no progress had been made
^ static chr *lastcold(struct vars *, struct dfa *);
*/
static chr * /* endpoint, or NULL */
-lastcold(v, d)
-struct vars *v;
-struct dfa *d;
+lastcold(
+ struct vars *v,
+ struct dfa *d)
{
- struct sset *ss;
- chr *nopr;
- int i;
-
- nopr = d->lastnopr;
- if (nopr == NULL)
- nopr = v->start;
- for (ss = d->ssets, i = d->nssused; i > 0; ss++, i--)
- if ((ss->flags&NOPROGRESS) && nopr < ss->lastseen)
- nopr = ss->lastseen;
- return nopr;
+ struct sset *ss;
+ chr *nopr;
+ int i;
+
+ nopr = d->lastnopr;
+ if (nopr == NULL) {
+ nopr = v->start;
+ }
+ for (ss = d->ssets, i = d->nssused; i > 0; ss++, i--) {
+ if ((ss->flags&NOPROGRESS) && nopr < ss->lastseen) {
+ nopr = ss->lastseen;
+ }
+ }
+ return nopr;
}
-
+
/*
- newdfa - set up a fresh DFA
^ static struct dfa *newdfa(struct vars *, struct cnfa *,
^ struct colormap *, struct smalldfa *);
*/
static struct dfa *
-newdfa(v, cnfa, cm, small)
-struct vars *v;
-struct cnfa *cnfa;
-struct colormap *cm;
-struct smalldfa *small; /* preallocated space, may be NULL */
+newdfa(
+ struct vars *v,
+ struct cnfa *cnfa,
+ struct colormap *cm,
+ struct smalldfa *sml) /* preallocated space, may be NULL */
{
- struct dfa *d;
- size_t nss = cnfa->nstates * 2;
- int wordsper = (cnfa->nstates + UBITS - 1) / UBITS;
- struct smalldfa *smallwas = small;
-
- assert(cnfa != NULL && cnfa->nstates != 0);
-
- if (nss <= FEWSTATES && cnfa->ncolors <= FEWCOLORS) {
- assert(wordsper == 1);
- if (small == NULL) {
- small = (struct smalldfa *)MALLOC(
- sizeof(struct smalldfa));
- if (small == NULL) {
- ERR(REG_ESPACE);
- return NULL;
- }
- }
- d = &small->dfa;
- d->ssets = small->ssets;
- d->statesarea = small->statesarea;
- d->work = &d->statesarea[nss];
- d->outsarea = small->outsarea;
- d->incarea = small->incarea;
- d->cptsmalloced = 0;
- d->mallocarea = (smallwas == NULL) ? (char *)small : NULL;
- } else {
- d = (struct dfa *)MALLOC(sizeof(struct dfa));
- if (d == NULL) {
- ERR(REG_ESPACE);
- return NULL;
- }
- d->ssets = (struct sset *)MALLOC(nss * sizeof(struct sset));
- d->statesarea = (unsigned *)MALLOC((nss+WORK) * wordsper *
- sizeof(unsigned));
- d->work = &d->statesarea[nss * wordsper];
- d->outsarea = (struct sset **)MALLOC(nss * cnfa->ncolors *
- sizeof(struct sset *));
- d->incarea = (struct arcp *)MALLOC(nss * cnfa->ncolors *
- sizeof(struct arcp));
- d->cptsmalloced = 1;
- d->mallocarea = (char *)d;
- if (d->ssets == NULL || d->statesarea == NULL ||
- d->outsarea == NULL || d->incarea == NULL) {
- freedfa(d);
- ERR(REG_ESPACE);
- return NULL;
- }
+ struct dfa *d;
+ size_t nss = cnfa->nstates * 2;
+ int wordsper = (cnfa->nstates + UBITS - 1) / UBITS;
+ struct smalldfa *smallwas = sml;
+
+ assert(cnfa != NULL && cnfa->nstates != 0);
+
+ if (nss <= FEWSTATES && cnfa->ncolors <= FEWCOLORS) {
+ assert(wordsper == 1);
+ if (sml == NULL) {
+ sml = (struct smalldfa *) MALLOC(sizeof(struct smalldfa));
+ if (sml == NULL) {
+ ERR(REG_ESPACE);
+ return NULL;
+ }
}
-
- d->nssets = (v->eflags&REG_SMALL) ? 7 : nss;
- d->nssused = 0;
- d->nstates = cnfa->nstates;
- d->ncolors = cnfa->ncolors;
- d->wordsper = wordsper;
- d->cnfa = cnfa;
- d->cm = cm;
- d->lastpost = NULL;
- d->lastnopr = NULL;
- d->search = d->ssets;
-
- /* initialization of sset fields is done as needed */
-
- return d;
+ d = &sml->dfa;
+ d->ssets = sml->ssets;
+ d->statesarea = sml->statesarea;
+ d->work = &d->statesarea[nss];
+ d->outsarea = sml->outsarea;
+ d->incarea = sml->incarea;
+ d->cptsmalloced = 0;
+ d->mallocarea = (smallwas == NULL) ? (char *)sml : NULL;
+ } else {
+ d = (struct dfa *)MALLOC(sizeof(struct dfa));
+ if (d == NULL) {
+ ERR(REG_ESPACE);
+ return NULL;
+ }
+ d->ssets = (struct sset *)MALLOC(nss * sizeof(struct sset));
+ d->statesarea = (unsigned *)
+ MALLOC((nss+WORK) * wordsper * sizeof(unsigned));
+ d->work = &d->statesarea[nss * wordsper];
+ d->outsarea = (struct sset **)
+ MALLOC(nss * cnfa->ncolors * sizeof(struct sset *));
+ d->incarea = (struct arcp *)
+ MALLOC(nss * cnfa->ncolors * sizeof(struct arcp));
+ d->cptsmalloced = 1;
+ d->mallocarea = (char *)d;
+ if (d->ssets == NULL || d->statesarea == NULL ||
+ d->outsarea == NULL || d->incarea == NULL) {
+ freedfa(d);
+ ERR(REG_ESPACE);
+ return NULL;
+ }
+ }
+
+ d->nssets = (v->eflags&REG_SMALL) ? 7 : nss;
+ d->nssused = 0;
+ d->nstates = cnfa->nstates;
+ d->ncolors = cnfa->ncolors;
+ d->wordsper = wordsper;
+ d->cnfa = cnfa;
+ d->cm = cm;
+ d->lastpost = NULL;
+ d->lastnopr = NULL;
+ d->search = d->ssets;
+
+ /*
+ * Initialization of sset fields is done as needed.
+ */
+
+ return d;
}
-
+
/*
- freedfa - free a DFA
- ^ static VOID freedfa(struct dfa *);
+ ^ static void freedfa(struct dfa *);
*/
-static VOID
-freedfa(d)
-struct dfa *d;
+static void
+freedfa(
+ struct dfa *d)
{
- if (d->cptsmalloced) {
- if (d->ssets != NULL)
- FREE(d->ssets);
- if (d->statesarea != NULL)
- FREE(d->statesarea);
- if (d->outsarea != NULL)
- FREE(d->outsarea);
- if (d->incarea != NULL)
- FREE(d->incarea);
+ if (d->cptsmalloced) {
+ if (d->ssets != NULL) {
+ FREE(d->ssets);
+ }
+ if (d->statesarea != NULL) {
+ FREE(d->statesarea);
+ }
+ if (d->outsarea != NULL) {
+ FREE(d->outsarea);
}
+ if (d->incarea != NULL) {
+ FREE(d->incarea);
+ }
+ }
- if (d->mallocarea != NULL)
- FREE(d->mallocarea);
+ if (d->mallocarea != NULL) {
+ FREE(d->mallocarea);
+ }
}
-
+
/*
- hash - construct a hash code for a bitvector
* There are probably better ways, but they're more expensive.
^ static unsigned hash(unsigned *, int);
*/
static unsigned
-hash(uv, n)
-unsigned *uv;
-int n;
+hash(
+ unsigned *uv,
+ int n)
{
- int i;
- unsigned h;
-
- h = 0;
- for (i = 0; i < n; i++)
- h ^= uv[i];
- return h;
+ int i;
+ unsigned h;
+
+ h = 0;
+ for (i = 0; i < n; i++) {
+ h ^= uv[i];
+ }
+ return h;
}
-
+
/*
- initialize - hand-craft a cache entry for startup, otherwise get ready
^ static struct sset *initialize(struct vars *, struct dfa *, chr *);
*/
static struct sset *
-initialize(v, d, start)
-struct vars *v; /* used only for debug flags */
-struct dfa *d;
-chr *start;
+initialize(
+ struct vars *v, /* used only for debug flags */
+ struct dfa *d,
+ chr *start)
{
- struct sset *ss;
- int i;
-
- /* is previous one still there? */
- if (d->nssused > 0 && (d->ssets[0].flags&STARTER))
- ss = &d->ssets[0];
- else { /* no, must (re)build it */
- ss = getvacant(v, d, start, start);
- for (i = 0; i < d->wordsper; i++)
- ss->states[i] = 0;
- BSET(ss->states, d->cnfa->pre);
- ss->hash = HASH(ss->states, d->wordsper);
- assert(d->cnfa->pre != d->cnfa->post);
- ss->flags = STARTER|LOCKED|NOPROGRESS;
- /* lastseen dealt with below */
+ struct sset *ss;
+ int i;
+
+ /*
+ * Is previous one still there?
+ */
+
+ if (d->nssused > 0 && (d->ssets[0].flags&STARTER)) {
+ ss = &d->ssets[0];
+ } else { /* no, must (re)build it */
+ ss = getvacant(v, d, start, start);
+ for (i = 0; i < d->wordsper; i++) {
+ ss->states[i] = 0;
}
-
- for (i = 0; i < d->nssused; i++)
- d->ssets[i].lastseen = NULL;
- ss->lastseen = start; /* maybe untrue, but harmless */
- d->lastpost = NULL;
- d->lastnopr = NULL;
- return ss;
+ BSET(ss->states, d->cnfa->pre);
+ ss->hash = HASH(ss->states, d->wordsper);
+ assert(d->cnfa->pre != d->cnfa->post);
+ ss->flags = STARTER|LOCKED|NOPROGRESS;
+
+ /*
+ * lastseen dealt with below
+ */
+ }
+
+ for (i = 0; i < d->nssused; i++) {
+ d->ssets[i].lastseen = NULL;
+ }
+ ss->lastseen = start; /* maybe untrue, but harmless */
+ d->lastpost = NULL;
+ d->lastnopr = NULL;
+ return ss;
}
-
+
/*
- miss - handle a cache miss
^ static struct sset *miss(struct vars *, struct dfa *, struct sset *,
^ pcolor, chr *, chr *);
*/
static struct sset * /* NULL if goes to empty set */
-miss(v, d, css, co, cp, start)
-struct vars *v; /* used only for debug flags */
-struct dfa *d;
-struct sset *css;
-pcolor co;
-chr *cp; /* next chr */
-chr *start; /* where the attempt got started */
+miss(
+ struct vars *v, /* used only for debug flags */
+ struct dfa *d,
+ struct sset *css,
+ pcolor co,
+ chr *cp, /* next chr */
+ chr *start) /* where the attempt got started */
{
- struct cnfa *cnfa = d->cnfa;
- int i;
- unsigned h;
- struct carc *ca;
- struct sset *p;
- int ispost;
- int noprogress;
- int gotstate;
- int dolacons;
- int sawlacons;
-
- /* for convenience, we can be called even if it might not be a miss */
- if (css->outs[co] != NULL) {
- FDEBUG(("hit\n"));
- return css->outs[co];
- }
- FDEBUG(("miss\n"));
-
- /* first, what set of states would we end up in? */
- for (i = 0; i < d->wordsper; i++)
- d->work[i] = 0;
- ispost = 0;
- noprogress = 1;
- gotstate = 0;
- for (i = 0; i < d->nstates; i++)
- if (ISBSET(css->states, i))
- for (ca = cnfa->states[i]+1; ca->co != COLORLESS; ca++)
- if (ca->co == co) {
- BSET(d->work, ca->to);
- gotstate = 1;
- if (ca->to == cnfa->post)
- ispost = 1;
- if (!cnfa->states[ca->to]->co)
- noprogress = 0;
- FDEBUG(("%d -> %d\n", i, ca->to));
- }
- dolacons = (gotstate) ? (cnfa->flags&HASLACONS) : 0;
- sawlacons = 0;
- while (dolacons) { /* transitive closure */
- dolacons = 0;
- for (i = 0; i < d->nstates; i++)
- if (ISBSET(d->work, i))
- for (ca = cnfa->states[i]+1; ca->co != COLORLESS;
- ca++) {
- if (ca->co <= cnfa->ncolors)
- continue; /* NOTE CONTINUE */
- sawlacons = 1;
- if (ISBSET(d->work, ca->to))
- continue; /* NOTE CONTINUE */
- if (!lacon(v, cnfa, cp, ca->co))
- continue; /* NOTE CONTINUE */
- BSET(d->work, ca->to);
- dolacons = 1;
- if (ca->to == cnfa->post)
- ispost = 1;
- if (!cnfa->states[ca->to]->co)
- noprogress = 0;
- FDEBUG(("%d :> %d\n", i, ca->to));
- }
+ struct cnfa *cnfa = d->cnfa;
+ int i;
+ unsigned h;
+ struct carc *ca;
+ struct sset *p;
+ int ispost;
+ int noprogress;
+ int gotstate;
+ int dolacons;
+ int sawlacons;
+
+ /*
+ * For convenience, we can be called even if it might not be a miss.
+ */
+
+ if (css->outs[co] != NULL) {
+ FDEBUG(("hit\n"));
+ return css->outs[co];
+ }
+ FDEBUG(("miss\n"));
+
+ /*
+ * First, what set of states would we end up in?
+ */
+
+ for (i = 0; i < d->wordsper; i++) {
+ d->work[i] = 0;
+ }
+ ispost = 0;
+ noprogress = 1;
+ gotstate = 0;
+ for (i = 0; i < d->nstates; i++) {
+ if (ISBSET(css->states, i)) {
+ for (ca = cnfa->states[i]+1; ca->co != COLORLESS; ca++) {
+ if (ca->co == co) {
+ BSET(d->work, ca->to);
+ gotstate = 1;
+ if (ca->to == cnfa->post) {
+ ispost = 1;
+ }
+ if (!cnfa->states[ca->to]->co) {
+ noprogress = 0;
+ }
+ FDEBUG(("%d -> %d\n", i, ca->to));
+ }
+ }
}
- if (!gotstate)
- return NULL;
- h = HASH(d->work, d->wordsper);
-
- /* next, is that in the cache? */
- for (p = d->ssets, i = d->nssused; i > 0; p++, i--)
- if (HIT(h, d->work, p, d->wordsper)) {
- FDEBUG(("cached c%d\n", p - d->ssets));
- break; /* NOTE BREAK OUT */
+ }
+ dolacons = (gotstate) ? (cnfa->flags&HASLACONS) : 0;
+ sawlacons = 0;
+ while (dolacons) { /* transitive closure */
+ dolacons = 0;
+ for (i = 0; i < d->nstates; i++) {
+ if (ISBSET(d->work, i)) {
+ for (ca = cnfa->states[i]+1; ca->co != COLORLESS; ca++) {
+ if (ca->co <= cnfa->ncolors) {
+ continue; /* NOTE CONTINUE */
+ }
+ sawlacons = 1;
+ if (ISBSET(d->work, ca->to)) {
+ continue; /* NOTE CONTINUE */
+ }
+ if (!lacon(v, cnfa, cp, ca->co)) {
+ continue; /* NOTE CONTINUE */
+ }
+ BSET(d->work, ca->to);
+ dolacons = 1;
+ if (ca->to == cnfa->post) {
+ ispost = 1;
+ }
+ if (!cnfa->states[ca->to]->co) {
+ noprogress = 0;
+ }
+ FDEBUG(("%d :> %d\n", i, ca->to));
}
- if (i == 0) { /* nope, need a new cache entry */
- p = getvacant(v, d, cp, start);
- assert(p != css);
- for (i = 0; i < d->wordsper; i++)
- p->states[i] = d->work[i];
- p->hash = h;
- p->flags = (ispost) ? POSTSTATE : 0;
- if (noprogress)
- p->flags |= NOPROGRESS;
- /* lastseen to be dealt with by caller */
+ }
}
-
- if (!sawlacons) { /* lookahead conds. always cache miss */
- FDEBUG(("c%d[%d]->c%d\n", css - d->ssets, co, p - d->ssets));
- css->outs[co] = p;
- css->inchain[co] = p->ins;
- p->ins.ss = css;
- p->ins.co = (color)co;
+ }
+ if (!gotstate) {
+ return NULL;
+ }
+ h = HASH(d->work, d->wordsper);
+
+ /*
+ * Next, is that in the cache?
+ */
+
+ for (p = d->ssets, i = d->nssused; i > 0; p++, i--) {
+ if (HIT(h, d->work, p, d->wordsper)) {
+ FDEBUG(("cached c%d\n", p - d->ssets));
+ break; /* NOTE BREAK OUT */
+ }
+ }
+ if (i == 0) { /* nope, need a new cache entry */
+ p = getvacant(v, d, cp, start);
+ assert(p != css);
+ for (i = 0; i < d->wordsper; i++) {
+ p->states[i] = d->work[i];
+ }
+ p->hash = h;
+ p->flags = (ispost) ? POSTSTATE : 0;
+ if (noprogress) {
+ p->flags |= NOPROGRESS;
}
- return p;
-}
+ /*
+ * lastseen to be dealt with by caller
+ */
+ }
+
+ if (!sawlacons) { /* lookahead conds. always cache miss */
+ FDEBUG(("c%d[%d]->c%d\n", css - d->ssets, co, p - d->ssets));
+ css->outs[co] = p;
+ css->inchain[co] = p->ins;
+ p->ins.ss = css;
+ p->ins.co = (color)co;
+ }
+ return p;
+}
+
/*
- lacon - lookahead-constraint checker for miss()
^ static int lacon(struct vars *, struct cnfa *, chr *, pcolor);
*/
static int /* predicate: constraint satisfied? */
-lacon(v, pcnfa, cp, co)
-struct vars *v;
-struct cnfa *pcnfa; /* parent cnfa */
-chr *cp;
-pcolor co; /* "color" of the lookahead constraint */
+lacon(
+ struct vars *v,
+ struct cnfa *pcnfa, /* parent cnfa */
+ chr *cp,
+ pcolor co) /* "color" of the lookahead constraint */
{
- int n;
- struct subre *sub;
- struct dfa *d;
- struct smalldfa sd;
- chr *end;
-
- n = co - pcnfa->ncolors;
- assert(n < v->g->nlacons && v->g->lacons != NULL);
- FDEBUG(("=== testing lacon %d\n", n));
- sub = &v->g->lacons[n];
- d = newdfa(v, &sub->cnfa, &v->g->cmap, &sd);
- if (d == NULL) {
- ERR(REG_ESPACE);
- return 0;
- }
- end = longest(v, d, cp, v->stop, (int *)NULL);
- freedfa(d);
- FDEBUG(("=== lacon %d match %d\n", n, (end != NULL)));
- return (sub->subno) ? (end != NULL) : (end == NULL);
+ int n;
+ struct subre *sub;
+ struct dfa *d;
+ struct smalldfa sd;
+ chr *end;
+
+ n = co - pcnfa->ncolors;
+ assert(n < v->g->nlacons && v->g->lacons != NULL);
+ FDEBUG(("=== testing lacon %d\n", n));
+ sub = &v->g->lacons[n];
+ d = newdfa(v, &sub->cnfa, &v->g->cmap, &sd);
+ if (d == NULL) {
+ ERR(REG_ESPACE);
+ return 0;
+ }
+ end = longest(v, d, cp, v->stop, (int *)NULL);
+ freedfa(d);
+ FDEBUG(("=== lacon %d match %d\n", n, (end != NULL)));
+ return (sub->subno) ? (end != NULL) : (end == NULL);
}
-
+
/*
- getvacant - get a vacant state set
* This routine clears out the inarcs and outarcs, but does not otherwise
@@ -551,127 +650,167 @@ pcolor co; /* "color" of the lookahead constraint */
^ static struct sset *getvacant(struct vars *, struct dfa *, chr *, chr *);
*/
static struct sset *
-getvacant(v, d, cp, start)
-struct vars *v; /* used only for debug flags */
-struct dfa *d;
-chr *cp;
-chr *start;
+getvacant(
+ struct vars *v, /* used only for debug flags */
+ struct dfa *d,
+ chr *cp,
+ chr *start)
{
- int i;
- struct sset *ss;
- struct sset *p;
- struct arcp ap;
- struct arcp lastap = {NULL, 0}; /* silence gcc 4 warning */
- color co;
-
- ss = pickss(v, d, cp, start);
- assert(!(ss->flags&LOCKED));
-
- /* clear out its inarcs, including self-referential ones */
- ap = ss->ins;
- while ((p = ap.ss) != NULL) {
- co = ap.co;
- FDEBUG(("zapping c%d's %ld outarc\n", p - d->ssets, (long)co));
- p->outs[co] = NULL;
- ap = p->inchain[co];
- p->inchain[co].ss = NULL; /* paranoia */
+ int i;
+ struct sset *ss;
+ struct sset *p;
+ struct arcp ap;
+ struct arcp lastap = {NULL, 0}; /* silence gcc 4 warning */
+ color co;
+
+ ss = pickss(v, d, cp, start);
+ assert(!(ss->flags&LOCKED));
+
+ /*
+ * Clear out its inarcs, including self-referential ones.
+ */
+
+ ap = ss->ins;
+ while ((p = ap.ss) != NULL) {
+ co = ap.co;
+ FDEBUG(("zapping c%d's %ld outarc\n", p - d->ssets, (long)co));
+ p->outs[co] = NULL;
+ ap = p->inchain[co];
+ p->inchain[co].ss = NULL; /* paranoia */
+ }
+ ss->ins.ss = NULL;
+
+ /*
+ * Take it off the inarc chains of the ssets reached by its outarcs.
+ */
+
+ for (i = 0; i < d->ncolors; i++) {
+ p = ss->outs[i];
+ assert(p != ss); /* not self-referential */
+ if (p == NULL) {
+ continue; /* NOTE CONTINUE */
}
- ss->ins.ss = NULL;
-
- /* take it off the inarc chains of the ssets reached by its outarcs */
- for (i = 0; i < d->ncolors; i++) {
- p = ss->outs[i];
- assert(p != ss); /* not self-referential */
- if (p == NULL)
- continue; /* NOTE CONTINUE */
- FDEBUG(("del outarc %d from c%d's in chn\n", i, p - d->ssets));
- if (p->ins.ss == ss && p->ins.co == i)
- p->ins = ss->inchain[i];
- else {
- assert(p->ins.ss != NULL);
- for (ap = p->ins; ap.ss != NULL &&
- !(ap.ss == ss && ap.co == i);
- ap = ap.ss->inchain[ap.co])
- lastap = ap;
- assert(ap.ss != NULL);
- lastap.ss->inchain[lastap.co] = ss->inchain[i];
- }
- ss->outs[i] = NULL;
- ss->inchain[i].ss = NULL;
+ FDEBUG(("del outarc %d from c%d's in chn\n", i, p - d->ssets));
+ if (p->ins.ss == ss && p->ins.co == i) {
+ p->ins = ss->inchain[i];
+ } else {
+ assert(p->ins.ss != NULL);
+ for (ap = p->ins; ap.ss != NULL &&
+ !(ap.ss == ss && ap.co == i);
+ ap = ap.ss->inchain[ap.co]) {
+ lastap = ap;
+ }
+ assert(ap.ss != NULL);
+ lastap.ss->inchain[lastap.co] = ss->inchain[i];
}
+ ss->outs[i] = NULL;
+ ss->inchain[i].ss = NULL;
+ }
- /* if ss was a success state, may need to remember location */
- if ((ss->flags&POSTSTATE) && ss->lastseen != d->lastpost &&
- (d->lastpost == NULL || d->lastpost < ss->lastseen))
- d->lastpost = ss->lastseen;
+ /*
+ * If ss was a success state, may need to remember location.
+ */
- /* likewise for a no-progress state */
- if ((ss->flags&NOPROGRESS) && ss->lastseen != d->lastnopr &&
- (d->lastnopr == NULL || d->lastnopr < ss->lastseen))
- d->lastnopr = ss->lastseen;
+ if ((ss->flags&POSTSTATE) && ss->lastseen != d->lastpost &&
+ (d->lastpost == NULL || d->lastpost < ss->lastseen)) {
+ d->lastpost = ss->lastseen;
+ }
- return ss;
-}
+ /*
+ * Likewise for a no-progress state.
+ */
+ if ((ss->flags&NOPROGRESS) && ss->lastseen != d->lastnopr &&
+ (d->lastnopr == NULL || d->lastnopr < ss->lastseen)) {
+ d->lastnopr = ss->lastseen;
+ }
+
+ return ss;
+}
+
/*
- pickss - pick the next stateset to be used
^ static struct sset *pickss(struct vars *, struct dfa *, chr *, chr *);
*/
static struct sset *
-pickss(v, d, cp, start)
-struct vars *v; /* used only for debug flags */
-struct dfa *d;
-chr *cp;
-chr *start;
+pickss(
+ struct vars *v, /* used only for debug flags */
+ struct dfa *d,
+ chr *cp,
+ chr *start)
{
- int i;
- struct sset *ss;
- struct sset *end;
- chr *ancient;
-
- /* shortcut for cases where cache isn't full */
- if (d->nssused < d->nssets) {
- i = d->nssused;
- d->nssused++;
- ss = &d->ssets[i];
- FDEBUG(("new c%d\n", i));
- /* set up innards */
- ss->states = &d->statesarea[i * d->wordsper];
- ss->flags = 0;
- ss->ins.ss = NULL;
- ss->ins.co = WHITE; /* give it some value */
- ss->outs = &d->outsarea[i * d->ncolors];
- ss->inchain = &d->incarea[i * d->ncolors];
- for (i = 0; i < d->ncolors; i++) {
- ss->outs[i] = NULL;
- ss->inchain[i].ss = NULL;
- }
- return ss;
+ int i;
+ struct sset *ss;
+ struct sset *end;
+ chr *ancient;
+
+ /*
+ * Shortcut for cases where cache isn't full.
+ */
+
+ if (d->nssused < d->nssets) {
+ i = d->nssused;
+ d->nssused++;
+ ss = &d->ssets[i];
+ FDEBUG(("new c%d\n", i));
+
+ /*
+ * Set up innards.
+ */
+
+ ss->states = &d->statesarea[i * d->wordsper];
+ ss->flags = 0;
+ ss->ins.ss = NULL;
+ ss->ins.co = WHITE; /* give it some value */
+ ss->outs = &d->outsarea[i * d->ncolors];
+ ss->inchain = &d->incarea[i * d->ncolors];
+ for (i = 0; i < d->ncolors; i++) {
+ ss->outs[i] = NULL;
+ ss->inchain[i].ss = NULL;
+ }
+ return ss;
+ }
+
+ /*
+ * Look for oldest, or old enough anyway.
+ */
+
+ if (cp - start > d->nssets*2/3) { /* oldest 33% are expendable */
+ ancient = cp - d->nssets*2/3;
+ } else {
+ ancient = start;
+ }
+ for (ss = d->search, end = &d->ssets[d->nssets]; ss < end; ss++) {
+ if ((ss->lastseen == NULL || ss->lastseen < ancient)
+ && !(ss->flags&LOCKED)) {
+ d->search = ss + 1;
+ FDEBUG(("replacing c%d\n", ss - d->ssets));
+ return ss;
}
+ }
+ for (ss = d->ssets, end = d->search; ss < end; ss++) {
+ if ((ss->lastseen == NULL || ss->lastseen < ancient)
+ && !(ss->flags&LOCKED)) {
+ d->search = ss + 1;
+ FDEBUG(("replacing c%d\n", ss - d->ssets));
+ return ss;
+ }
+ }
- /* look for oldest, or old enough anyway */
- if (cp - start > d->nssets*2/3) /* oldest 33% are expendable */
- ancient = cp - d->nssets*2/3;
- else
- ancient = start;
- for (ss = d->search, end = &d->ssets[d->nssets]; ss < end; ss++)
- if ((ss->lastseen == NULL || ss->lastseen < ancient) &&
- !(ss->flags&LOCKED)) {
- d->search = ss + 1;
- FDEBUG(("replacing c%d\n", ss - d->ssets));
- return ss;
- }
- for (ss = d->ssets, end = d->search; ss < end; ss++)
- if ((ss->lastseen == NULL || ss->lastseen < ancient) &&
- !(ss->flags&LOCKED)) {
- d->search = ss + 1;
- FDEBUG(("replacing c%d\n", ss - d->ssets));
- return ss;
- }
+ /*
+ * Nobody's old enough?!? -- something's really wrong.
+ */
- /* nobody's old enough?!? -- something's really wrong */
- FDEBUG(("can't find victim to replace!\n"));
- assert(NOTREACHED);
- ERR(REG_ASSERT);
- return d->ssets;
+ FDEBUG(("can't find victim to replace!\n"));
+ assert(NOTREACHED);
+ ERR(REG_ASSERT);
+ return d->ssets;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/regerror.c b/generic/regerror.c
index 182830d..49b6f3e 100644
--- a/generic/regerror.c
+++ b/generic/regerror.c
@@ -2,20 +2,20 @@
* regerror - error-code expansion
*
* Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
- *
+ *
* Development of this software was funded, in part, by Cray Research Inc.,
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
* Corporation, none of whom are responsible for the results. The author
- * thanks all of them.
- *
+ * thanks all of them.
+ *
* Redistribution and use in source and binary forms -- with or without
* modification -- are permitted for any purpose, provided that
* redistributions in source form retain this entire copyright notice and
* indicate the origin and nature of any modifications.
- *
- * I'd appreciate being given credit for this package in the documentation
- * of software which uses it, but that is not a requirement.
- *
+ *
+ * I'd appreciate being given credit for this package in the documentation of
+ * software which uses it, but that is not a requirement.
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -31,79 +31,99 @@
#include "regguts.h"
-/* unknown-error explanation */
+/*
+ * Unknown-error explanation.
+ */
+
static char unk[] = "*** unknown regex error code 0x%x ***";
-/* struct to map among codes, code names, and explanations */
+/*
+ * Struct to map among codes, code names, and explanations.
+ */
+
static struct rerr {
- int code;
- char *name;
- char *explain;
+ int code;
+ const char *name;
+ const char *explain;
} rerrs[] = {
- /* the actual table is built from regex.h */
-# include "regerrs.h"
- { -1, "", "oops" }, /* explanation special-cased in code */
+ /* The actual table is built from regex.h */
+#include "regerrs.h"
+ { -1, "", "oops" }, /* explanation special-cased in code */
};
-
+
/*
- regerror - the interface to error numbers
*/
/* ARGSUSED */
-size_t /* actual space needed (including NUL) */
-regerror(code, preg, errbuf, errbuf_size)
-int code; /* error code, or REG_ATOI or REG_ITOA */
-CONST regex_t *preg; /* associated regex_t (unused at present) */
-char *errbuf; /* result buffer (unless errbuf_size==0) */
-size_t errbuf_size; /* available space in errbuf, can be 0 */
+size_t /* Actual space needed (including NUL) */
+regerror(
+ int code, /* Error code, or REG_ATOI or REG_ITOA */
+ const regex_t *preg, /* Associated regex_t (unused at present) */
+ char *errbuf, /* Result buffer (unless errbuf_size==0) */
+ size_t errbuf_size) /* Available space in errbuf, can be 0 */
{
- struct rerr *r;
- char *msg;
- char convbuf[sizeof(unk)+50]; /* 50 = plenty for int */
- size_t len;
- int icode;
+ struct rerr *r;
+ const char *msg;
+ char convbuf[sizeof(unk)+50]; /* 50 = plenty for int */
+ size_t len;
+ int icode;
- switch (code) {
- case REG_ATOI: /* convert name to number */
- for (r = rerrs; r->code >= 0; r++)
- if (strcmp(r->name, errbuf) == 0)
- break;
- sprintf(convbuf, "%d", r->code); /* -1 for unknown */
- msg = convbuf;
+ switch (code) {
+ case REG_ATOI: /* Convert name to number */
+ for (r = rerrs; r->code >= 0; r++) {
+ if (strcmp(r->name, errbuf) == 0) {
break;
- case REG_ITOA: /* convert number to name */
- icode = atoi(errbuf); /* not our problem if this fails */
- for (r = rerrs; r->code >= 0; r++)
- if (r->code == icode)
- break;
- if (r->code >= 0)
- msg = r->name;
- else { /* unknown; tell him the number */
- sprintf(convbuf, "REG_%u", (unsigned)icode);
- msg = convbuf;
- }
+ }
+ }
+ sprintf(convbuf, "%d", r->code); /* -1 for unknown */
+ msg = convbuf;
+ break;
+ case REG_ITOA: /* Convert number to name */
+ icode = atoi(errbuf); /* Not our problem if this fails */
+ for (r = rerrs; r->code >= 0; r++) {
+ if (r->code == icode) {
break;
- default: /* a real, normal error code */
- for (r = rerrs; r->code >= 0; r++)
- if (r->code == code)
- break;
- if (r->code >= 0)
- msg = r->explain;
- else { /* unknown; say so */
- sprintf(convbuf, unk, code);
- msg = convbuf;
- }
+ }
+ }
+ if (r->code >= 0) {
+ msg = r->name;
+ } else { /* Unknown; tell him the number */
+ sprintf(convbuf, "REG_%u", (unsigned)icode);
+ msg = convbuf;
+ }
+ break;
+ default: /* A real, normal error code */
+ for (r = rerrs; r->code >= 0; r++) {
+ if (r->code == code) {
break;
+ }
+ }
+ if (r->code >= 0) {
+ msg = r->explain;
+ } else { /* Unknown; say so */
+ sprintf(convbuf, unk, code);
+ msg = convbuf;
}
+ break;
+ }
- len = strlen(msg) + 1; /* space needed, including NUL */
- if (errbuf_size > 0) {
- if (errbuf_size > len)
- strcpy(errbuf, msg);
- else { /* truncate to fit */
- strncpy(errbuf, msg, errbuf_size-1);
- errbuf[errbuf_size-1] = '\0';
- }
+ len = strlen(msg) + 1; /* Space needed, including NUL */
+ if (errbuf_size > 0) {
+ if (errbuf_size > len) {
+ strcpy(errbuf, msg);
+ } else { /* Truncate to fit */
+ strncpy(errbuf, msg, errbuf_size-1);
+ errbuf[errbuf_size-1] = '\0';
}
+ }
- return len;
+ return len;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/regex.h b/generic/regex.h
index a35925a..fa86092 100644
--- a/generic/regex.h
+++ b/generic/regex.h
@@ -4,20 +4,20 @@
* regular expressions
*
* Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
- *
+ *
* Development of this software was funded, in part, by Cray Research Inc.,
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
- * Corporation, none of whom are responsible for the results. The author
- * thanks all of them.
- *
+ * Corporation, none of whom are responsible for the results. The author
+ * thanks all of them.
+ *
* Redistribution and use in source and binary forms -- with or without
* modification -- are permitted for any purpose, provided that
* redistributions in source form retain this entire copyright notice and
* indicate the origin and nature of any modifications.
*
- * I'd appreciate being given credit for this package in the documentation
- * of software which uses it, but that is not a requirement.
- *
+ * I'd appreciate being given credit for this package in the documentation of
+ * software which uses it, but that is not a requirement.
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -30,38 +30,35 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
- *
* Prototypes etc. marked with "^" within comments get gathered up (and
- * possibly edited) by the regfwd program and inserted near the bottom of
- * this file.
+ * possibly edited) by the regfwd program and inserted near the bottom of this
+ * file.
*
- * We offer the option of declaring one wide-character version of the
- * RE functions as well as the char versions. To do that, define
- * __REG_WIDE_T to the type of wide characters (unfortunately, there
- * is no consensus that wchar_t is suitable) and __REG_WIDE_COMPILE and
- * __REG_WIDE_EXEC to the names to be used for the compile and execute
- * functions (suggestion: re_Xcomp and re_Xexec, where X is a letter
- * suggestive of the wide type, e.g. re_ucomp and re_uexec for Unicode).
- * For cranky old compilers, it may be necessary to do something like:
+ * We offer the option of declaring one wide-character version of the RE
+ * functions as well as the char versions. To do that, define __REG_WIDE_T to
+ * the type of wide characters (unfortunately, there is no consensus that
+ * wchar_t is suitable) and __REG_WIDE_COMPILE and __REG_WIDE_EXEC to the
+ * names to be used for the compile and execute functions (suggestion:
+ * re_Xcomp and re_Xexec, where X is a letter suggestive of the wide type,
+ * e.g. re_ucomp and re_uexec for Unicode). For cranky old compilers, it may
+ * be necessary to do something like:
* #define __REG_WIDE_COMPILE(a,b,c,d) re_Xcomp(a,b,c,d)
* #define __REG_WIDE_EXEC(a,b,c,d,e,f,g) re_Xexec(a,b,c,d,e,f,g)
* rather than just #defining the names as parameterless macros.
*
* For some specialized purposes, it may be desirable to suppress the
- * declarations of the "front end" functions, regcomp() and regexec(),
- * or of the char versions of the compile and execute functions. To
- * suppress the front-end functions, define __REG_NOFRONT. To suppress
- * the char versions, define __REG_NOCHAR.
+ * declarations of the "front end" functions, regcomp() and regexec(), or of
+ * the char versions of the compile and execute functions. To suppress the
+ * front-end functions, define __REG_NOFRONT. To suppress the char versions,
+ * define __REG_NOCHAR.
*
* The right place to do those defines (and some others you may want, see
- * below) would be <sys/types.h>. If you don't have control of that file,
- * the right place to add your own defines to this file is marked below.
- * This is normally done automatically, by the makefile and regmkhdr, based
- * on the contents of regcustom.h.
+ * below) would be <sys/types.h>. If you don't have control of that file, the
+ * right place to add your own defines to this file is marked below. This is
+ * normally done automatically, by the makefile and regmkhdr, based on the
+ * contents of regcustom.h.
*/
-
-
/*
* voodoo for C++
*/
@@ -69,18 +66,15 @@
extern "C" {
#endif
-
-
/*
* Add your own defines, if needed, here.
*/
-
-
/*
- * Location where a chunk of regcustom.h is automatically spliced into
- * this file (working from its prototype, regproto.h).
+ * Location where a chunk of regcustom.h is automatically spliced into this
+ * file (working from its prototype, regproto.h).
*/
+
/* --- begin --- */
/* ensure certain things don't sneak in from system headers */
#ifdef __REG_WIDE_T
@@ -121,15 +115,14 @@ extern "C" {
#define regerror TclReError
/* --- end --- */
-
/*
* interface types etc.
*/
/*
- * regoff_t has to be large enough to hold either off_t or ssize_t,
- * and must be signed; it's only a guess that long is suitable, so we
- * offer <sys/types.h> an override.
+ * regoff_t has to be large enough to hold either off_t or ssize_t, and must
+ * be signed; it's only a guess that long is suitable, so we offer
+ * <sys/types.h> an override.
*/
#ifdef __REG_REGOFF_T
typedef __REG_REGOFF_T regoff_t;
@@ -148,8 +141,8 @@ typedef void re_void;
#endif
/*
- * Also for benefit of old compilers, <sys/types.h> can supply a macro
- * which expands to a substitute for `const'.
+ * Also for benefit of old compilers, <sys/types.h> can supply a macro which
+ * expands to a substitute for `const'.
*/
#ifndef __REG_CONST
#define __REG_CONST const
@@ -163,43 +156,41 @@ typedef void re_void;
/* the biggie, a compiled RE (or rather, a front end to same) */
typedef struct {
- int re_magic; /* magic number */
- size_t re_nsub; /* number of subexpressions */
- long re_info; /* information about RE */
-# define REG_UBACKREF 000001
-# define REG_ULOOKAHEAD 000002
-# define REG_UBOUNDS 000004
-# define REG_UBRACES 000010
-# define REG_UBSALNUM 000020
-# define REG_UPBOTCH 000040
-# define REG_UBBS 000100
-# define REG_UNONPOSIX 000200
-# define REG_UUNSPEC 000400
-# define REG_UUNPORT 001000
-# define REG_ULOCALE 002000
-# define REG_UEMPTYMATCH 004000
-# define REG_UIMPOSSIBLE 010000
-# define REG_USHORTEST 020000
- int re_csize; /* sizeof(character) */
- char *re_endp; /* backward compatibility kludge */
- /* the rest is opaque pointers to hidden innards */
- char *re_guts; /* `char *' is more portable than `void *' */
- char *re_fns;
+ int re_magic; /* magic number */
+ size_t re_nsub; /* number of subexpressions */
+ long re_info; /* information about RE */
+#define REG_UBACKREF 000001
+#define REG_ULOOKAHEAD 000002
+#define REG_UBOUNDS 000004
+#define REG_UBRACES 000010
+#define REG_UBSALNUM 000020
+#define REG_UPBOTCH 000040
+#define REG_UBBS 000100
+#define REG_UNONPOSIX 000200
+#define REG_UUNSPEC 000400
+#define REG_UUNPORT 001000
+#define REG_ULOCALE 002000
+#define REG_UEMPTYMATCH 004000
+#define REG_UIMPOSSIBLE 010000
+#define REG_USHORTEST 020000
+ int re_csize; /* sizeof(character) */
+ char *re_endp; /* backward compatibility kludge */
+ /* the rest is opaque pointers to hidden innards */
+ char *re_guts; /* `char *' is more portable than `void *' */
+ char *re_fns;
} regex_t;
/* result reporting (may acquire more fields later) */
typedef struct {
- regoff_t rm_so; /* start of substring */
- regoff_t rm_eo; /* end of substring */
+ regoff_t rm_so; /* start of substring */
+ regoff_t rm_eo; /* end of substring */
} regmatch_t;
/* supplementary control and reporting */
typedef struct {
- regmatch_t rm_extend; /* see REG_EXPECT */
+ regmatch_t rm_extend; /* see REG_EXPECT */
} rm_detail_t;
-
-
/*
* compilation
^ #ifndef __REG_NOCHAR
@@ -231,8 +222,6 @@ typedef struct {
#define REG_FAKE 010000 /* none of your business :-) */
#define REG_PROGRESS 020000 /* none of your business :-) */
-
-
/*
* execution
^ #ifndef __REG_NOCHAR
@@ -254,23 +243,19 @@ typedef struct {
#define REG_MTRACE 0020 /* none of your business */
#define REG_SMALL 0040 /* none of your business */
-
-
/*
* misc generics (may be more functions here eventually)
^ re_void regfree(regex_t *);
*/
-
-
/*
* error reporting
* Be careful if modifying the list of error codes -- the table used by
* regerror() is generated automatically from this file!
*
- * Note that there is no wide-char variant of regerror at this time; what
- * kind of character is used for error reports is independent of what kind
- * is used in matching.
+ * Note that there is no wide-char variant of regerror at this time; what kind
+ * of character is used for error reports is independent of what kind is used
+ * in matching.
*
^ extern size_t regerror(int, __REG_CONST regex_t *, char *, size_t);
*/
@@ -297,8 +282,6 @@ typedef struct {
#define REG_ATOI 101 /* convert error-code name to number */
#define REG_ITOA 102 /* convert error-code number to name */
-
-
/*
* the prototypes, as possibly munched by regfwd
*/
@@ -306,30 +289,28 @@ typedef struct {
/* automatically gathered by fwd; do not hand-edit */
/* === regproto.h === */
#ifndef __REG_NOCHAR
-int re_comp _ANSI_ARGS_((regex_t *, __REG_CONST char *, size_t, int));
+int re_comp(regex_t *, __REG_CONST char *, size_t, int);
#endif
#ifndef __REG_NOFRONT
-int regcomp _ANSI_ARGS_((regex_t *, __REG_CONST char *, int));
+int regcomp(regex_t *, __REG_CONST char *, int);
#endif
#ifdef __REG_WIDE_T
-int __REG_WIDE_COMPILE _ANSI_ARGS_((regex_t *, __REG_CONST __REG_WIDE_T *, size_t, int));
+MODULE_SCOPE int __REG_WIDE_COMPILE(regex_t *, __REG_CONST __REG_WIDE_T *, size_t, int);
#endif
#ifndef __REG_NOCHAR
-int re_exec _ANSI_ARGS_((regex_t *, __REG_CONST char *, size_t, rm_detail_t *, size_t, regmatch_t [], int));
+int re_exec(regex_t *, __REG_CONST char *, size_t, rm_detail_t *, size_t, regmatch_t [], int);
#endif
#ifndef __REG_NOFRONT
-int regexec _ANSI_ARGS_((regex_t *, __REG_CONST char *, size_t, regmatch_t [], int));
+int regexec(regex_t *, __REG_CONST char *, size_t, regmatch_t [], int);
#endif
#ifdef __REG_WIDE_T
-int __REG_WIDE_EXEC _ANSI_ARGS_((regex_t *, __REG_CONST __REG_WIDE_T *, size_t, rm_detail_t *, size_t, regmatch_t [], int));
+MODULE_SCOPE int __REG_WIDE_EXEC(regex_t *, __REG_CONST __REG_WIDE_T *, size_t, rm_detail_t *, size_t, regmatch_t [], int);
#endif
-re_void regfree _ANSI_ARGS_((regex_t *));
-extern size_t regerror _ANSI_ARGS_((int, __REG_CONST regex_t *, char *, size_t));
+MODULE_SCOPE re_void regfree(regex_t *);
+MODULE_SCOPE size_t regerror(int, __REG_CONST regex_t *, char *, size_t);
/* automatically gathered by fwd; do not hand-edit */
/* =====^!^===== end forwards =====^!^===== */
-
-
/*
* more C++ voodoo
*/
@@ -337,6 +318,4 @@ extern size_t regerror _ANSI_ARGS_((int, __REG_CONST regex_t *, char *, size_t))
}
#endif
-
-
#endif
diff --git a/generic/regexec.c b/generic/regexec.c
index be459d3..c902209 100644
--- a/generic/regexec.c
+++ b/generic/regexec.c
@@ -2,20 +2,20 @@
* re_*exec and friends - match REs
*
* Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
- *
+ *
* Development of this software was funded, in part, by Cray Research Inc.,
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
* Corporation, none of whom are responsible for the results. The author
- * thanks all of them.
- *
+ * thanks all of them.
+ *
* Redistribution and use in source and binary forms -- with or without
* modification -- are permitted for any purpose, provided that
* redistributions in source form retain this entire copyright notice and
* indicate the origin and nature of any modifications.
- *
- * I'd appreciate being given credit for this package in the documentation
- * of software which uses it, but that is not a requirement.
- *
+ *
+ * I'd appreciate being given credit for this package in the documentation of
+ * software which uses it, but that is not a requirement.
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -26,1015 +26,1181 @@
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include "regguts.h"
+/*
+ * Lazy-DFA representation.
+ */
-
-/* lazy-DFA representation */
struct arcp { /* "pointer" to an outarc */
- struct sset *ss;
- color co;
+ struct sset *ss;
+ color co;
};
struct sset { /* state set */
- unsigned *states; /* pointer to bitvector */
- unsigned hash; /* hash of bitvector */
-# define HASH(bv, nw) (((nw) == 1) ? *(bv) : hash(bv, nw))
-# define HIT(h,bv,ss,nw) ((ss)->hash == (h) && ((nw) == 1 || \
- memcmp(VS(bv), VS((ss)->states), (nw)*sizeof(unsigned)) == 0))
- int flags;
-# define STARTER 01 /* the initial state set */
-# define POSTSTATE 02 /* includes the goal state */
-# define LOCKED 04 /* locked in cache */
-# define NOPROGRESS 010 /* zero-progress state set */
- struct arcp ins; /* chain of inarcs pointing here */
- chr *lastseen; /* last entered on arrival here */
- struct sset **outs; /* outarc vector indexed by color */
- struct arcp *inchain; /* chain-pointer vector for outarcs */
+ unsigned *states; /* pointer to bitvector */
+ unsigned hash; /* hash of bitvector */
+#define HASH(bv, nw) (((nw) == 1) ? *(bv) : hash(bv, nw))
+#define HIT(h,bv,ss,nw) ((ss)->hash == (h) && ((nw) == 1 || \
+ memcmp(VS(bv), VS((ss)->states), (nw)*sizeof(unsigned)) == 0))
+ int flags;
+#define STARTER 01 /* the initial state set */
+#define POSTSTATE 02 /* includes the goal state */
+#define LOCKED 04 /* locked in cache */
+#define NOPROGRESS 010 /* zero-progress state set */
+ struct arcp ins; /* chain of inarcs pointing here */
+ chr *lastseen; /* last entered on arrival here */
+ struct sset **outs; /* outarc vector indexed by color */
+ struct arcp *inchain; /* chain-pointer vector for outarcs */
};
struct dfa {
- int nssets; /* size of cache */
- int nssused; /* how many entries occupied yet */
- int nstates; /* number of states */
- int ncolors; /* length of outarc and inchain vectors */
- int wordsper; /* length of state-set bitvectors */
- struct sset *ssets; /* state-set cache */
- unsigned *statesarea; /* bitvector storage */
- unsigned *work; /* pointer to work area within statesarea */
- struct sset **outsarea; /* outarc-vector storage */
- struct arcp *incarea; /* inchain storage */
- struct cnfa *cnfa;
- struct colormap *cm;
- chr *lastpost; /* location of last cache-flushed success */
- chr *lastnopr; /* location of last cache-flushed NOPROGRESS */
- struct sset *search; /* replacement-search-pointer memory */
- int cptsmalloced; /* were the areas individually malloced? */
- char *mallocarea; /* self, or master malloced area, or NULL */
+ int nssets; /* size of cache */
+ int nssused; /* how many entries occupied yet */
+ int nstates; /* number of states */
+ int ncolors; /* length of outarc and inchain vectors */
+ int wordsper; /* length of state-set bitvectors */
+ struct sset *ssets; /* state-set cache */
+ unsigned *statesarea; /* bitvector storage */
+ unsigned *work; /* pointer to work area within statesarea */
+ struct sset **outsarea; /* outarc-vector storage */
+ struct arcp *incarea; /* inchain storage */
+ struct cnfa *cnfa;
+ struct colormap *cm;
+ chr *lastpost; /* location of last cache-flushed success */
+ chr *lastnopr; /* location of last cache-flushed NOPROGRESS */
+ struct sset *search; /* replacement-search-pointer memory */
+ int cptsmalloced; /* were the areas individually malloced? */
+ char *mallocarea; /* self, or master malloced area, or NULL */
};
#define WORK 1 /* number of work bitvectors needed */
-/* setup for non-malloc allocation for small cases */
+/*
+ * Setup for non-malloc allocation for small cases.
+ */
+
#define FEWSTATES 20 /* must be less than UBITS */
#define FEWCOLORS 15
struct smalldfa {
- struct dfa dfa;
- struct sset ssets[FEWSTATES*2];
- unsigned statesarea[FEWSTATES*2 + WORK];
- struct sset *outsarea[FEWSTATES*2 * FEWCOLORS];
- struct arcp incarea[FEWSTATES*2 * FEWCOLORS];
+ struct dfa dfa;
+ struct sset ssets[FEWSTATES*2];
+ unsigned statesarea[FEWSTATES*2 + WORK];
+ struct sset *outsarea[FEWSTATES*2 * FEWCOLORS];
+ struct arcp incarea[FEWSTATES*2 * FEWCOLORS];
};
#define DOMALLOC ((struct smalldfa *)NULL) /* force malloc */
+/*
+ * Internal variables, bundled for easy passing around.
+ */
-
-/* internal variables, bundled for easy passing around */
struct vars {
- regex_t *re;
- struct guts *g;
- int eflags; /* copies of arguments */
- size_t nmatch;
- regmatch_t *pmatch;
- rm_detail_t *details;
- chr *start; /* start of string */
- chr *stop; /* just past end of string */
- int err; /* error code if any (0 none) */
- regoff_t *mem; /* memory vector for backtracking */
- struct smalldfa dfa1;
- struct smalldfa dfa2;
+ regex_t *re;
+ struct guts *g;
+ int eflags; /* copies of arguments */
+ size_t nmatch;
+ regmatch_t *pmatch;
+ rm_detail_t *details;
+ chr *start; /* start of string */
+ chr *stop; /* just past end of string */
+ int err; /* error code if any (0 none) */
+ regoff_t *mem; /* memory vector for backtracking */
+ struct smalldfa dfa1;
+ struct smalldfa dfa2;
};
-#define VISERR(vv) ((vv)->err != 0) /* have we seen an error yet? */
+#define VISERR(vv) ((vv)->err != 0) /* have we seen an error yet? */
#define ISERR() VISERR(v)
-#define VERR(vv,e) (((vv)->err) ? (vv)->err : ((vv)->err = (e)))
-#define ERR(e) VERR(v, e) /* record an error */
+#define VERR(vv,e) (((vv)->err) ? (vv)->err : ((vv)->err = (e)))
+#define ERR(e) VERR(v, e) /* record an error */
#define NOERR() {if (ISERR()) return v->err;} /* if error seen, return it */
#define OFF(p) ((p) - v->start)
#define LOFF(p) ((long)OFF(p))
-
-
-
+
/*
* forward declarations
*/
/* =====^!^===== begin forwards =====^!^===== */
/* automatically gathered by fwd; do not hand-edit */
/* === regexec.c === */
-int exec _ANSI_ARGS_((regex_t *, CONST chr *, size_t, rm_detail_t *, size_t, regmatch_t [], int));
-static int find _ANSI_ARGS_((struct vars *, struct cnfa *, struct colormap *));
-static int cfind _ANSI_ARGS_((struct vars *, struct cnfa *, struct colormap *));
-static int cfindloop _ANSI_ARGS_((struct vars *, struct cnfa *, struct colormap *, struct dfa *, struct dfa *, chr **));
-static VOID zapsubs _ANSI_ARGS_((regmatch_t *, size_t));
-static VOID zapmem _ANSI_ARGS_((struct vars *, struct subre *));
-static VOID subset _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *));
-static int dissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *));
-static int condissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *));
-static int altdissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *));
-static int cdissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *));
-static int ccondissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *));
-static int crevdissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *));
-static int cbrdissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *));
-static int caltdissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *));
+int exec(regex_t *, CONST chr *, size_t, rm_detail_t *, size_t, regmatch_t [], int);
+static int find(struct vars *, struct cnfa *, struct colormap *);
+static int cfind(struct vars *, struct cnfa *, struct colormap *);
+static int cfindloop(struct vars *, struct cnfa *, struct colormap *, struct dfa *, struct dfa *, chr **);
+static VOID zapsubs(regmatch_t *, size_t);
+static VOID zapmem(struct vars *, struct subre *);
+static VOID subset(struct vars *, struct subre *, chr *, chr *);
+static int dissect(struct vars *, struct subre *, chr *, chr *);
+static int condissect(struct vars *, struct subre *, chr *, chr *);
+static int altdissect(struct vars *, struct subre *, chr *, chr *);
+static int cdissect(struct vars *, struct subre *, chr *, chr *);
+static int ccondissect(struct vars *, struct subre *, chr *, chr *);
+static int crevdissect(struct vars *, struct subre *, chr *, chr *);
+static int cbrdissect(struct vars *, struct subre *, chr *, chr *);
+static int caltdissect(struct vars *, struct subre *, chr *, chr *);
/* === rege_dfa.c === */
-static chr *longest _ANSI_ARGS_((struct vars *, struct dfa *, chr *, chr *, int *));
-static chr *shortest _ANSI_ARGS_((struct vars *, struct dfa *, chr *, chr *, chr *, chr **, int *));
-static chr *lastcold _ANSI_ARGS_((struct vars *, struct dfa *));
-static struct dfa *newdfa _ANSI_ARGS_((struct vars *, struct cnfa *, struct colormap *, struct smalldfa *));
-static VOID freedfa _ANSI_ARGS_((struct dfa *));
-static unsigned hash _ANSI_ARGS_((unsigned *, int));
-static struct sset *initialize _ANSI_ARGS_((struct vars *, struct dfa *, chr *));
-static struct sset *miss _ANSI_ARGS_((struct vars *, struct dfa *, struct sset *, pcolor, chr *, chr *));
-static int lacon _ANSI_ARGS_((struct vars *, struct cnfa *, chr *, pcolor));
-static struct sset *getvacant _ANSI_ARGS_((struct vars *, struct dfa *, chr *, chr *));
-static struct sset *pickss _ANSI_ARGS_((struct vars *, struct dfa *, chr *, chr *));
+static chr *longest(struct vars *, struct dfa *, chr *, chr *, int *);
+static chr *shortest(struct vars *, struct dfa *, chr *, chr *, chr *, chr **, int *);
+static chr *lastcold(struct vars *, struct dfa *);
+static struct dfa *newdfa(struct vars *, struct cnfa *, struct colormap *, struct smalldfa *);
+static VOID freedfa(struct dfa *);
+static unsigned hash(unsigned *, int);
+static struct sset *initialize(struct vars *, struct dfa *, chr *);
+static struct sset *miss(struct vars *, struct dfa *, struct sset *, pcolor, chr *, chr *);
+static int lacon(struct vars *, struct cnfa *, chr *, pcolor);
+static struct sset *getvacant(struct vars *, struct dfa *, chr *, chr *);
+static struct sset *pickss(struct vars *, struct dfa *, chr *, chr *);
/* automatically gathered by fwd; do not hand-edit */
/* =====^!^===== end forwards =====^!^===== */
-
-
-
+
/*
- exec - match regular expression
^ int exec(regex_t *, CONST chr *, size_t, rm_detail_t *,
^ size_t, regmatch_t [], int);
*/
int
-exec(re, string, len, details, nmatch, pmatch, flags)
-regex_t *re;
-CONST chr *string;
-size_t len;
-rm_detail_t *details;
-size_t nmatch;
-regmatch_t pmatch[];
-int flags;
+exec(
+ regex_t *re,
+ CONST chr *string,
+ size_t len,
+ rm_detail_t *details,
+ size_t nmatch,
+ regmatch_t pmatch[],
+ int flags)
{
- struct vars var;
- register struct vars *v = &var;
- int st;
- size_t n;
- int backref;
-# define LOCALMAT 20
- regmatch_t mat[LOCALMAT];
-# define LOCALMEM 40
- regoff_t mem[LOCALMEM];
-
- /* sanity checks */
- if (re == NULL || string == NULL || re->re_magic != REMAGIC)
- return REG_INVARG;
- if (re->re_csize != sizeof(chr))
- return REG_MIXED;
-
- /* setup */
- v->re = re;
- v->g = (struct guts *)re->re_guts;
- if ((v->g->cflags&REG_EXPECT) && details == NULL)
- return REG_INVARG;
- if (v->g->info&REG_UIMPOSSIBLE)
- return REG_NOMATCH;
- backref = (v->g->info&REG_UBACKREF) ? 1 : 0;
- v->eflags = flags;
- if (v->g->cflags&REG_NOSUB)
- nmatch = 0; /* override client */
- v->nmatch = nmatch;
- if (backref) {
- /* need work area */
- if (v->g->nsub + 1 <= LOCALMAT)
- v->pmatch = mat;
- else
- v->pmatch = (regmatch_t *)MALLOC((v->g->nsub + 1) *
- sizeof(regmatch_t));
- if (v->pmatch == NULL)
- return REG_ESPACE;
- v->nmatch = v->g->nsub + 1;
- } else
- v->pmatch = pmatch;
- v->details = details;
- v->start = (chr *)string;
- v->stop = (chr *)string + len;
- v->err = 0;
- if (backref) {
- /* need retry memory */
- assert(v->g->ntree >= 0);
- n = (size_t)v->g->ntree;
- if (n <= LOCALMEM)
- v->mem = mem;
- else
- v->mem = (regoff_t *)MALLOC(n*sizeof(regoff_t));
- if (v->mem == NULL) {
- if (v->pmatch != pmatch && v->pmatch != mat)
- FREE(v->pmatch);
- return REG_ESPACE;
- }
- } else
- v->mem = NULL;
-
- /* do it */
- assert(v->g->tree != NULL);
- if (backref)
- st = cfind(v, &v->g->tree->cnfa, &v->g->cmap);
- else
- st = find(v, &v->g->tree->cnfa, &v->g->cmap);
-
- /* copy (portion of) match vector over if necessary */
- if (st == REG_OKAY && v->pmatch != pmatch && nmatch > 0) {
- zapsubs(pmatch, nmatch);
- n = (nmatch < v->nmatch) ? nmatch : v->nmatch;
- memcpy(VS(pmatch), VS(v->pmatch), n*sizeof(regmatch_t));
+ AllocVars(v);
+ int st;
+ size_t n;
+ int backref;
+#define LOCALMAT 20
+ regmatch_t mat[LOCALMAT];
+#define LOCALMEM 40
+ regoff_t mem[LOCALMEM];
+
+ /*
+ * Sanity checks.
+ */
+
+ if (re == NULL || string == NULL || re->re_magic != REMAGIC) {
+ FreeVars(v);
+ return REG_INVARG;
+ }
+ if (re->re_csize != sizeof(chr)) {
+ FreeVars(v);
+ return REG_MIXED;
+ }
+
+ /*
+ * Setup.
+ */
+
+ v->re = re;
+ v->g = (struct guts *)re->re_guts;
+ if ((v->g->cflags&REG_EXPECT) && details == NULL) {
+ FreeVars(v);
+ return REG_INVARG;
+ }
+ if (v->g->info&REG_UIMPOSSIBLE) {
+ FreeVars(v);
+ return REG_NOMATCH;
+ }
+ backref = (v->g->info&REG_UBACKREF) ? 1 : 0;
+ v->eflags = flags;
+ if (v->g->cflags&REG_NOSUB) {
+ nmatch = 0; /* override client */
+ }
+ v->nmatch = nmatch;
+ if (backref) {
+ /*
+ * Need work area.
+ */
+
+ if (v->g->nsub + 1 <= LOCALMAT) {
+ v->pmatch = mat;
+ } else {
+ v->pmatch = (regmatch_t *)
+ MALLOC((v->g->nsub + 1) * sizeof(regmatch_t));
}
-
- /* clean up */
- if (v->pmatch != pmatch && v->pmatch != mat)
+ if (v->pmatch == NULL) {
+ FreeVars(v);
+ return REG_ESPACE;
+ }
+ v->nmatch = v->g->nsub + 1;
+ } else {
+ v->pmatch = pmatch;
+ }
+ v->details = details;
+ v->start = (chr *)string;
+ v->stop = (chr *)string + len;
+ v->err = 0;
+ if (backref) {
+ /*
+ * Need retry memory.
+ */
+
+ assert(v->g->ntree >= 0);
+ n = (size_t)v->g->ntree;
+ if (n <= LOCALMEM) {
+ v->mem = mem;
+ } else {
+ v->mem = (regoff_t *) MALLOC(n*sizeof(regoff_t));
+ }
+ if (v->mem == NULL) {
+ if (v->pmatch != pmatch && v->pmatch != mat) {
FREE(v->pmatch);
- if (v->mem != NULL && v->mem != mem)
- FREE(v->mem);
- return st;
+ }
+ FreeVars(v);
+ return REG_ESPACE;
+ }
+ } else {
+ v->mem = NULL;
+ }
+
+ /*
+ * Do it.
+ */
+
+ assert(v->g->tree != NULL);
+ if (backref) {
+ st = cfind(v, &v->g->tree->cnfa, &v->g->cmap);
+ } else {
+ st = find(v, &v->g->tree->cnfa, &v->g->cmap);
+ }
+
+ /*
+ * Copy (portion of) match vector over if necessary.
+ */
+
+ if (st == REG_OKAY && v->pmatch != pmatch && nmatch > 0) {
+ zapsubs(pmatch, nmatch);
+ n = (nmatch < v->nmatch) ? nmatch : v->nmatch;
+ memcpy(VS(pmatch), VS(v->pmatch), n*sizeof(regmatch_t));
+ }
+
+ /*
+ * Clean up.
+ */
+
+ if (v->pmatch != pmatch && v->pmatch != mat) {
+ FREE(v->pmatch);
+ }
+ if (v->mem != NULL && v->mem != mem) {
+ FREE(v->mem);
+ }
+ FreeVars(v);
+ return st;
}
-
+
/*
- find - find a match for the main NFA (no-complications case)
^ static int find(struct vars *, struct cnfa *, struct colormap *);
*/
static int
-find(v, cnfa, cm)
-struct vars *v;
-struct cnfa *cnfa;
-struct colormap *cm;
+find(
+ struct vars *v,
+ struct cnfa *cnfa,
+ struct colormap *cm)
{
- struct dfa *s;
- struct dfa *d;
- chr *begin;
- chr *end = NULL;
- chr *cold;
- chr *open; /* open and close of range of possible starts */
- chr *close;
- int hitend;
- int shorter = (v->g->tree->flags&SHORTER) ? 1 : 0;
-
- /* first, a shot with the search RE */
- s = newdfa(v, &v->g->search, cm, &v->dfa1);
- assert(!(ISERR() && s != NULL));
- NOERR();
- MDEBUG(("\nsearch at %ld\n", LOFF(v->start)));
- cold = NULL;
- close = shortest(v, s, v->start, v->start, v->stop, &cold, (int *)NULL);
- freedfa(s);
- NOERR();
- if (v->g->cflags&REG_EXPECT) {
- assert(v->details != NULL);
- if (cold != NULL)
- v->details->rm_extend.rm_so = OFF(cold);
- else
- v->details->rm_extend.rm_so = OFF(v->stop);
- v->details->rm_extend.rm_eo = OFF(v->stop); /* unknown */
+ struct dfa *s;
+ struct dfa *d;
+ chr *begin;
+ chr *end = NULL;
+ chr *cold;
+ chr *open; /* Open and close of range of possible
+ * starts */
+ chr *close;
+ int hitend;
+ int shorter = (v->g->tree->flags&SHORTER) ? 1 : 0;
+
+ /*
+ * First, a shot with the search RE.
+ */
+
+ s = newdfa(v, &v->g->search, cm, &v->dfa1);
+ assert(!(ISERR() && s != NULL));
+ NOERR();
+ MDEBUG(("\nsearch at %ld\n", LOFF(v->start)));
+ cold = NULL;
+ close = shortest(v, s, v->start, v->start, v->stop, &cold, NULL);
+ freedfa(s);
+ NOERR();
+ if (v->g->cflags&REG_EXPECT) {
+ assert(v->details != NULL);
+ if (cold != NULL) {
+ v->details->rm_extend.rm_so = OFF(cold);
+ } else {
+ v->details->rm_extend.rm_so = OFF(v->stop);
+ }
+ v->details->rm_extend.rm_eo = OFF(v->stop); /* unknown */
+ }
+ if (close == NULL) { /* not found */
+ return REG_NOMATCH;
+ }
+ if (v->nmatch == 0) { /* found, don't need exact location */
+ return REG_OKAY;
+ }
+
+ /*
+ * Find starting point and match.
+ */
+
+ assert(cold != NULL);
+ open = cold;
+ cold = NULL;
+ MDEBUG(("between %ld and %ld\n", LOFF(open), LOFF(close)));
+ d = newdfa(v, cnfa, cm, &v->dfa1);
+ assert(!(ISERR() && d != NULL));
+ NOERR();
+ for (begin = open; begin <= close; begin++) {
+ MDEBUG(("\nfind trying at %ld\n", LOFF(begin)));
+ if (shorter) {
+ end = shortest(v, d, begin, begin, v->stop, NULL, &hitend);
+ } else {
+ end = longest(v, d, begin, v->stop, &hitend);
}
- if (close == NULL) /* not found */
- return REG_NOMATCH;
- if (v->nmatch == 0) /* found, don't need exact location */
- return REG_OKAY;
-
- /* find starting point and match */
- assert(cold != NULL);
- open = cold;
- cold = NULL;
- MDEBUG(("between %ld and %ld\n", LOFF(open), LOFF(close)));
- d = newdfa(v, cnfa, cm, &v->dfa1);
- assert(!(ISERR() && d != NULL));
NOERR();
- for (begin = open; begin <= close; begin++) {
- MDEBUG(("\nfind trying at %ld\n", LOFF(begin)));
- if (shorter)
- end = shortest(v, d, begin, begin, v->stop,
- (chr **)NULL, &hitend);
- else
- end = longest(v, d, begin, v->stop, &hitend);
- NOERR();
- if (hitend && cold == NULL)
- cold = begin;
- if (end != NULL)
- break; /* NOTE BREAK OUT */
+ if (hitend && cold == NULL) {
+ cold = begin;
}
- assert(end != NULL); /* search RE succeeded so loop should */
- freedfa(d);
-
- /* and pin down details */
- assert(v->nmatch > 0);
- v->pmatch[0].rm_so = OFF(begin);
- v->pmatch[0].rm_eo = OFF(end);
- if (v->g->cflags&REG_EXPECT) {
- if (cold != NULL)
- v->details->rm_extend.rm_so = OFF(cold);
- else
- v->details->rm_extend.rm_so = OFF(v->stop);
- v->details->rm_extend.rm_eo = OFF(v->stop); /* unknown */
+ if (end != NULL) {
+ break; /* NOTE BREAK OUT */
}
- if (v->nmatch == 1) /* no need for submatches */
- return REG_OKAY;
-
- /* submatches */
- zapsubs(v->pmatch, v->nmatch);
- return dissect(v, v->g->tree, begin, end);
+ }
+ assert(end != NULL); /* search RE succeeded so loop should */
+ freedfa(d);
+
+ /*
+ * And pin down details.
+ */
+
+ assert(v->nmatch > 0);
+ v->pmatch[0].rm_so = OFF(begin);
+ v->pmatch[0].rm_eo = OFF(end);
+ if (v->g->cflags&REG_EXPECT) {
+ if (cold != NULL) {
+ v->details->rm_extend.rm_so = OFF(cold);
+ } else {
+ v->details->rm_extend.rm_so = OFF(v->stop);
+ }
+ v->details->rm_extend.rm_eo = OFF(v->stop); /* unknown */
+ }
+ if (v->nmatch == 1) { /* no need for submatches */
+ return REG_OKAY;
+ }
+
+ /*
+ * Submatches.
+ */
+
+ zapsubs(v->pmatch, v->nmatch);
+ return dissect(v, v->g->tree, begin, end);
}
-
+
/*
- cfind - find a match for the main NFA (with complications)
^ static int cfind(struct vars *, struct cnfa *, struct colormap *);
*/
static int
-cfind(v, cnfa, cm)
-struct vars *v;
-struct cnfa *cnfa;
-struct colormap *cm;
+cfind(
+ struct vars *v,
+ struct cnfa *cnfa,
+ struct colormap *cm)
{
- struct dfa *s;
- struct dfa *d;
- chr *cold = NULL; /* silence gcc 4 warning */
- int ret;
-
- s = newdfa(v, &v->g->search, cm, &v->dfa1);
- NOERR();
- d = newdfa(v, cnfa, cm, &v->dfa2);
- if (ISERR()) {
- assert(d == NULL);
- freedfa(s);
- return v->err;
- }
-
- ret = cfindloop(v, cnfa, cm, d, s, &cold);
-
- freedfa(d);
+ struct dfa *s;
+ struct dfa *d;
+ chr *cold = NULL; /* silence gcc 4 warning */
+ int ret;
+
+ s = newdfa(v, &v->g->search, cm, &v->dfa1);
+ NOERR();
+ d = newdfa(v, cnfa, cm, &v->dfa2);
+ if (ISERR()) {
+ assert(d == NULL);
freedfa(s);
- NOERR();
- if (v->g->cflags&REG_EXPECT) {
- assert(v->details != NULL);
- if (cold != NULL)
- v->details->rm_extend.rm_so = OFF(cold);
- else
- v->details->rm_extend.rm_so = OFF(v->stop);
- v->details->rm_extend.rm_eo = OFF(v->stop); /* unknown */
+ return v->err;
+ }
+
+ ret = cfindloop(v, cnfa, cm, d, s, &cold);
+
+ freedfa(d);
+ freedfa(s);
+ NOERR();
+ if (v->g->cflags&REG_EXPECT) {
+ assert(v->details != NULL);
+ if (cold != NULL) {
+ v->details->rm_extend.rm_so = OFF(cold);
+ } else {
+ v->details->rm_extend.rm_so = OFF(v->stop);
}
- return ret;
+ v->details->rm_extend.rm_eo = OFF(v->stop); /* unknown */
+ }
+ return ret;
}
-
+
/*
- cfindloop - the heart of cfind
^ static int cfindloop(struct vars *, struct cnfa *, struct colormap *,
^ struct dfa *, struct dfa *, chr **);
*/
static int
-cfindloop(v, cnfa, cm, d, s, coldp)
-struct vars *v;
-struct cnfa *cnfa;
-struct colormap *cm;
-struct dfa *d;
-struct dfa *s;
-chr **coldp; /* where to put coldstart pointer */
+cfindloop(
+ struct vars *v,
+ struct cnfa *cnfa,
+ struct colormap *cm,
+ struct dfa *d,
+ struct dfa *s,
+ chr **coldp) /* where to put coldstart pointer */
{
- chr *begin;
- chr *end;
- chr *cold;
- chr *open; /* open and close of range of possible starts */
- chr *close;
- chr *estart;
- chr *estop;
- int er;
- int shorter = v->g->tree->flags&SHORTER;
- int hitend;
-
- assert(d != NULL && s != NULL);
+ chr *begin;
+ chr *end;
+ chr *cold;
+ chr *open; /* Open and close of range of possible
+ * starts */
+ chr *close;
+ chr *estart;
+ chr *estop;
+ int er;
+ int shorter = v->g->tree->flags&SHORTER;
+ int hitend;
+
+ assert(d != NULL && s != NULL);
+ cold = NULL;
+ close = v->start;
+ do {
+ MDEBUG(("\ncsearch at %ld\n", LOFF(close)));
+ close = shortest(v, s, close, close, v->stop, &cold, NULL);
+ if (close == NULL) {
+ break; /* NOTE BREAK */
+ }
+ assert(cold != NULL);
+ open = cold;
cold = NULL;
- close = v->start;
- do {
- MDEBUG(("\ncsearch at %ld\n", LOFF(close)));
- close = shortest(v, s, close, close, v->stop, &cold, (int *)NULL);
- if (close == NULL)
- break; /* NOTE BREAK */
- assert(cold != NULL);
- open = cold;
- cold = NULL;
- MDEBUG(("cbetween %ld and %ld\n", LOFF(open), LOFF(close)));
- for (begin = open; begin <= close; begin++) {
- MDEBUG(("\ncfind trying at %ld\n", LOFF(begin)));
- estart = begin;
- estop = v->stop;
- for (;;) {
- if (shorter)
- end = shortest(v, d, begin, estart,
- estop, (chr **)NULL, &hitend);
- else
- end = longest(v, d, begin, estop,
- &hitend);
- if (hitend && cold == NULL)
- cold = begin;
- if (end == NULL)
- break; /* NOTE BREAK OUT */
- MDEBUG(("tentative end %ld\n", LOFF(end)));
- zapsubs(v->pmatch, v->nmatch);
- zapmem(v, v->g->tree);
- er = cdissect(v, v->g->tree, begin, end);
- if (er == REG_OKAY) {
- if (v->nmatch > 0) {
- v->pmatch[0].rm_so = OFF(begin);
- v->pmatch[0].rm_eo = OFF(end);
- }
- *coldp = cold;
- return REG_OKAY;
- }
- if (er != REG_NOMATCH) {
- ERR(er);
- return er;
- }
- if ((shorter) ? end == estop : end == begin) {
- /* no point in trying again */
- *coldp = cold;
- return REG_NOMATCH;
- }
- /* go around and try again */
- if (shorter)
- estart = end + 1;
- else
- estop = end - 1;
- }
+ MDEBUG(("cbetween %ld and %ld\n", LOFF(open), LOFF(close)));
+ for (begin = open; begin <= close; begin++) {
+ MDEBUG(("\ncfind trying at %ld\n", LOFF(begin)));
+ estart = begin;
+ estop = v->stop;
+ for (;;) {
+ if (shorter) {
+ end = shortest(v, d, begin, estart, estop, NULL, &hitend);
+ } else {
+ end = longest(v, d, begin, estop, &hitend);
+ }
+ if (hitend && cold == NULL) {
+ cold = begin;
+ }
+ if (end == NULL) {
+ break; /* NOTE BREAK OUT */
}
- } while (close < v->stop);
- *coldp = cold;
- return REG_NOMATCH;
-}
+ MDEBUG(("tentative end %ld\n", LOFF(end)));
+ zapsubs(v->pmatch, v->nmatch);
+ zapmem(v, v->g->tree);
+ er = cdissect(v, v->g->tree, begin, end);
+ if (er == REG_OKAY) {
+ if (v->nmatch > 0) {
+ v->pmatch[0].rm_so = OFF(begin);
+ v->pmatch[0].rm_eo = OFF(end);
+ }
+ *coldp = cold;
+ return REG_OKAY;
+ }
+ if (er != REG_NOMATCH) {
+ ERR(er);
+ return er;
+ }
+ if ((shorter) ? end == estop : end == begin) {
+ /*
+ * No point in trying again.
+ */
+
+ *coldp = cold;
+ return REG_NOMATCH;
+ }
+
+ /*
+ * Go around and try again
+ */
+
+ if (shorter) {
+ estart = end + 1;
+ } else {
+ estop = end - 1;
+ }
+ }
+ }
+ } while (close < v->stop);
+ *coldp = cold;
+ return REG_NOMATCH;
+}
+
/*
- zapsubs - initialize the subexpression matches to "no match"
^ static VOID zapsubs(regmatch_t *, size_t);
*/
-static VOID
-zapsubs(p, n)
-regmatch_t *p;
-size_t n;
+static void
+zapsubs(
+ regmatch_t *p,
+ size_t n)
{
- size_t i;
+ size_t i;
- for (i = n-1; i > 0; i--) {
- p[i].rm_so = -1;
- p[i].rm_eo = -1;
- }
+ for (i = n-1; i > 0; i--) {
+ p[i].rm_so = -1;
+ p[i].rm_eo = -1;
+ }
}
-
+
/*
- zapmem - initialize the retry memory of a subtree to zeros
^ static VOID zapmem(struct vars *, struct subre *);
*/
-static VOID
-zapmem(v, t)
-struct vars *v;
-struct subre *t;
+static void
+zapmem(
+ struct vars *v,
+ struct subre *t)
{
- if (t == NULL)
- return;
-
- assert(v->mem != NULL);
- v->mem[t->retry] = 0;
- if (t->op == '(') {
- assert(t->subno > 0);
- v->pmatch[t->subno].rm_so = -1;
+ if (t == NULL) {
+ return;
+ }
+
+ assert(v->mem != NULL);
+ v->mem[t->retry] = 0;
+ if (t->op == '(') {
+ assert(t->subno > 0);
+ v->pmatch[t->subno].rm_so = -1;
v->pmatch[t->subno].rm_eo = -1;
- }
-
- if (t->left != NULL)
- zapmem(v, t->left);
- if (t->right != NULL)
- zapmem(v, t->right);
+ }
+
+ if (t->left != NULL) {
+ zapmem(v, t->left);
+ }
+ if (t->right != NULL) {
+ zapmem(v, t->right);
+ }
}
-
+
/*
- subset - set any subexpression relevant to a successful subre
^ static VOID subset(struct vars *, struct subre *, chr *, chr *);
*/
-static VOID
-subset(v, sub, begin, end)
-struct vars *v;
-struct subre *sub;
-chr *begin;
-chr *end;
+static void
+subset(
+ struct vars *v,
+ struct subre *sub,
+ chr *begin,
+ chr *end)
{
- int n = sub->subno;
+ int n = sub->subno;
- assert(n > 0);
- if ((size_t)n >= v->nmatch)
- return;
+ assert(n > 0);
+ if ((size_t)n >= v->nmatch) {
+ return;
+ }
- MDEBUG(("setting %d\n", n));
- v->pmatch[n].rm_so = OFF(begin);
- v->pmatch[n].rm_eo = OFF(end);
+ MDEBUG(("setting %d\n", n));
+ v->pmatch[n].rm_so = OFF(begin);
+ v->pmatch[n].rm_eo = OFF(end);
}
-
+
/*
- dissect - determine subexpression matches (uncomplicated case)
^ static int dissect(struct vars *, struct subre *, chr *, chr *);
*/
static int /* regexec return code */
-dissect(v, t, begin, end)
-struct vars *v;
-struct subre *t;
-chr *begin; /* beginning of relevant substring */
-chr *end; /* end of same */
+dissect(
+ struct vars *v,
+ struct subre *t,
+ chr *begin, /* beginning of relevant substring */
+ chr *end) /* end of same */
{
- assert(t != NULL);
- MDEBUG(("dissect %ld-%ld\n", LOFF(begin), LOFF(end)));
-
- switch (t->op) {
- case '=': /* terminal node */
- assert(t->left == NULL && t->right == NULL);
- return REG_OKAY; /* no action, parent did the work */
- break;
- case '|': /* alternation */
- assert(t->left != NULL);
- return altdissect(v, t, begin, end);
- break;
- case 'b': /* back ref -- shouldn't be calling us! */
- return REG_ASSERT;
- break;
- case '.': /* concatenation */
- assert(t->left != NULL && t->right != NULL);
- return condissect(v, t, begin, end);
- break;
- case '(': /* capturing */
- assert(t->left != NULL && t->right == NULL);
- assert(t->subno > 0);
- subset(v, t, begin, end);
- return dissect(v, t->left, begin, end);
- break;
- default:
- return REG_ASSERT;
- break;
- }
+ assert(t != NULL);
+ MDEBUG(("dissect %ld-%ld\n", LOFF(begin), LOFF(end)));
+
+ switch (t->op) {
+ case '=': /* terminal node */
+ assert(t->left == NULL && t->right == NULL);
+ return REG_OKAY; /* no action, parent did the work */
+ case '|': /* alternation */
+ assert(t->left != NULL);
+ return altdissect(v, t, begin, end);
+ case 'b': /* back ref -- shouldn't be calling us! */
+ return REG_ASSERT;
+ case '.': /* concatenation */
+ assert(t->left != NULL && t->right != NULL);
+ return condissect(v, t, begin, end);
+ case '(': /* capturing */
+ assert(t->left != NULL && t->right == NULL);
+ assert(t->subno > 0);
+ subset(v, t, begin, end);
+ return dissect(v, t->left, begin, end);
+ default:
+ return REG_ASSERT;
+ }
}
-
+
/*
- condissect - determine concatenation subexpression matches (uncomplicated)
^ static int condissect(struct vars *, struct subre *, chr *, chr *);
*/
static int /* regexec return code */
-condissect(v, t, begin, end)
-struct vars *v;
-struct subre *t;
-chr *begin; /* beginning of relevant substring */
-chr *end; /* end of same */
+condissect(
+ struct vars *v,
+ struct subre *t,
+ chr *begin, /* beginning of relevant substring */
+ chr *end) /* end of same */
{
- struct dfa *d;
- struct dfa *d2;
- chr *mid;
- int i;
- int shorter = (t->left->flags&SHORTER) ? 1 : 0;
- chr *stop = (shorter) ? end : begin;
-
- assert(t->op == '.');
- assert(t->left != NULL && t->left->cnfa.nstates > 0);
- assert(t->right != NULL && t->right->cnfa.nstates > 0);
-
- d = newdfa(v, &t->left->cnfa, &v->g->cmap, &v->dfa1);
- NOERR();
- d2 = newdfa(v, &t->right->cnfa, &v->g->cmap, &v->dfa2);
- if (ISERR()) {
- assert(d2 == NULL);
- freedfa(d);
- return v->err;
+ struct dfa *d;
+ struct dfa *d2;
+ chr *mid;
+ int i;
+ int shorter = (t->left->flags&SHORTER) ? 1 : 0;
+ chr *stop = (shorter) ? end : begin;
+
+ assert(t->op == '.');
+ assert(t->left != NULL && t->left->cnfa.nstates > 0);
+ assert(t->right != NULL && t->right->cnfa.nstates > 0);
+
+ d = newdfa(v, &t->left->cnfa, &v->g->cmap, &v->dfa1);
+ NOERR();
+ d2 = newdfa(v, &t->right->cnfa, &v->g->cmap, &v->dfa2);
+ if (ISERR()) {
+ assert(d2 == NULL);
+ freedfa(d);
+ return v->err;
+ }
+
+ /*
+ * Pick a tentative midpoint.
+ */
+
+ if (shorter) {
+ mid = shortest(v, d, begin, begin, end, NULL, NULL);
+ } else {
+ mid = longest(v, d, begin, end, NULL);
+ }
+ if (mid == NULL) {
+ freedfa(d);
+ freedfa(d2);
+ return REG_ASSERT;
+ }
+ MDEBUG(("tentative midpoint %ld\n", LOFF(mid)));
+
+ /*
+ * Iterate until satisfaction or failure.
+ */
+
+ while (longest(v, d2, mid, end, NULL) != end) {
+ /*
+ * That midpoint didn't work, find a new one.
+ */
+
+ if (mid == stop) {
+ /*
+ * All possibilities exhausted!
+ */
+
+ MDEBUG(("no midpoint!\n"));
+ freedfa(d);
+ freedfa(d2);
+ return REG_ASSERT;
}
-
- /* pick a tentative midpoint */
- if (shorter)
- mid = shortest(v, d, begin, begin, end, (chr **)NULL,
- (int *)NULL);
- else
- mid = longest(v, d, begin, end, (int *)NULL);
- if (mid == NULL) {
- freedfa(d);
- freedfa(d2);
- return REG_ASSERT;
+ if (shorter) {
+ mid = shortest(v, d, begin, mid+1, end, NULL, NULL);
+ } else {
+ mid = longest(v, d, begin, mid-1, NULL);
}
- MDEBUG(("tentative midpoint %ld\n", LOFF(mid)));
-
- /* iterate until satisfaction or failure */
- while (longest(v, d2, mid, end, (int *)NULL) != end) {
- /* that midpoint didn't work, find a new one */
- if (mid == stop) {
- /* all possibilities exhausted! */
- MDEBUG(("no midpoint!\n"));
- freedfa(d);
- freedfa(d2);
- return REG_ASSERT;
- }
- if (shorter)
- mid = shortest(v, d, begin, mid+1, end, (chr **)NULL,
- (int *)NULL);
- else
- mid = longest(v, d, begin, mid-1, (int *)NULL);
- if (mid == NULL) {
- /* failed to find a new one! */
- MDEBUG(("failed midpoint!\n"));
- freedfa(d);
- freedfa(d2);
- return REG_ASSERT;
- }
- MDEBUG(("new midpoint %ld\n", LOFF(mid)));
+ if (mid == NULL) {
+ /*
+ * Failed to find a new one!
+ */
+
+ MDEBUG(("failed midpoint!\n"));
+ freedfa(d);
+ freedfa(d2);
+ return REG_ASSERT;
}
-
- /* satisfaction */
- MDEBUG(("successful\n"));
- freedfa(d);
- freedfa(d2);
- i = dissect(v, t->left, begin, mid);
- if (i != REG_OKAY)
- return i;
- return dissect(v, t->right, mid, end);
+ MDEBUG(("new midpoint %ld\n", LOFF(mid)));
+ }
+
+ /*
+ * Satisfaction.
+ */
+
+ MDEBUG(("successful\n"));
+ freedfa(d);
+ freedfa(d2);
+ i = dissect(v, t->left, begin, mid);
+ if (i != REG_OKAY) {
+ return i;
+ }
+ return dissect(v, t->right, mid, end);
}
-
+
/*
- altdissect - determine alternative subexpression matches (uncomplicated)
^ static int altdissect(struct vars *, struct subre *, chr *, chr *);
*/
static int /* regexec return code */
-altdissect(v, t, begin, end)
-struct vars *v;
-struct subre *t;
-chr *begin; /* beginning of relevant substring */
-chr *end; /* end of same */
+altdissect(
+ struct vars *v,
+ struct subre *t,
+ chr *begin, /* beginning of relevant substring */
+ chr *end) /* end of same */
{
- struct dfa *d;
- int i;
-
- assert(t != NULL);
- assert(t->op == '|');
-
- for (i = 0; t != NULL; t = t->right, i++) {
- MDEBUG(("trying %dth\n", i));
- assert(t->left != NULL && t->left->cnfa.nstates > 0);
- d = newdfa(v, &t->left->cnfa, &v->g->cmap, &v->dfa1);
- if (ISERR())
- return v->err;
- if (longest(v, d, begin, end, (int *)NULL) == end) {
- MDEBUG(("success\n"));
- freedfa(d);
- return dissect(v, t->left, begin, end);
- }
- freedfa(d);
+ struct dfa *d;
+ int i;
+
+ assert(t != NULL);
+ assert(t->op == '|');
+
+ for (i = 0; t != NULL; t = t->right, i++) {
+ MDEBUG(("trying %dth\n", i));
+ assert(t->left != NULL && t->left->cnfa.nstates > 0);
+ d = newdfa(v, &t->left->cnfa, &v->g->cmap, &v->dfa1);
+ if (ISERR()) {
+ return v->err;
+ }
+ if (longest(v, d, begin, end, NULL) == end) {
+ MDEBUG(("success\n"));
+ freedfa(d);
+ return dissect(v, t->left, begin, end);
}
- return REG_ASSERT; /* none of them matched?!? */
+ freedfa(d);
+ }
+ return REG_ASSERT; /* none of them matched?!? */
}
-
+
/*
- cdissect - determine subexpression matches (with complications)
- * The retry memory stores the offset of the trial midpoint from begin,
- * plus 1 so that 0 uniquely means "clean slate".
+ * The retry memory stores the offset of the trial midpoint from begin, plus 1
+ * so that 0 uniquely means "clean slate".
^ static int cdissect(struct vars *, struct subre *, chr *, chr *);
*/
static int /* regexec return code */
-cdissect(v, t, begin, end)
-struct vars *v;
-struct subre *t;
-chr *begin; /* beginning of relevant substring */
-chr *end; /* end of same */
+cdissect(
+ struct vars *v,
+ struct subre *t,
+ chr *begin, /* beginning of relevant substring */
+ chr *end) /* end of same */
{
- int er;
-
- assert(t != NULL);
- MDEBUG(("cdissect %ld-%ld %c\n", LOFF(begin), LOFF(end), t->op));
-
- switch (t->op) {
- case '=': /* terminal node */
- assert(t->left == NULL && t->right == NULL);
- return REG_OKAY; /* no action, parent did the work */
- break;
- case '|': /* alternation */
- assert(t->left != NULL);
- return caltdissect(v, t, begin, end);
- break;
- case 'b': /* back ref -- shouldn't be calling us! */
- assert(t->left == NULL && t->right == NULL);
- return cbrdissect(v, t, begin, end);
- break;
- case '.': /* concatenation */
- assert(t->left != NULL && t->right != NULL);
- return ccondissect(v, t, begin, end);
- break;
- case '(': /* capturing */
- assert(t->left != NULL && t->right == NULL);
- assert(t->subno > 0);
- er = cdissect(v, t->left, begin, end);
- if (er == REG_OKAY)
- subset(v, t, begin, end);
- return er;
- break;
- default:
- return REG_ASSERT;
- break;
+ int er;
+
+ assert(t != NULL);
+ MDEBUG(("cdissect %ld-%ld %c\n", LOFF(begin), LOFF(end), t->op));
+
+ switch (t->op) {
+ case '=': /* terminal node */
+ assert(t->left == NULL && t->right == NULL);
+ return REG_OKAY; /* no action, parent did the work */
+ case '|': /* alternation */
+ assert(t->left != NULL);
+ return caltdissect(v, t, begin, end);
+ case 'b': /* back ref -- shouldn't be calling us! */
+ assert(t->left == NULL && t->right == NULL);
+ return cbrdissect(v, t, begin, end);
+ case '.': /* concatenation */
+ assert(t->left != NULL && t->right != NULL);
+ return ccondissect(v, t, begin, end);
+ case '(': /* capturing */
+ assert(t->left != NULL && t->right == NULL);
+ assert(t->subno > 0);
+ er = cdissect(v, t->left, begin, end);
+ if (er == REG_OKAY) {
+ subset(v, t, begin, end);
}
+ return er;
+ default:
+ return REG_ASSERT;
+ }
}
-
+
/*
- ccondissect - concatenation subexpression matches (with complications)
- * The retry memory stores the offset of the trial midpoint from begin,
- * plus 1 so that 0 uniquely means "clean slate".
+ * The retry memory stores the offset of the trial midpoint from begin, plus 1
+ * so that 0 uniquely means "clean slate".
^ static int ccondissect(struct vars *, struct subre *, chr *, chr *);
*/
static int /* regexec return code */
-ccondissect(v, t, begin, end)
-struct vars *v;
-struct subre *t;
-chr *begin; /* beginning of relevant substring */
-chr *end; /* end of same */
+ccondissect(
+ struct vars *v,
+ struct subre *t,
+ chr *begin, /* beginning of relevant substring */
+ chr *end) /* end of same */
{
- struct dfa *d;
- struct dfa *d2;
- chr *mid;
- int er;
-
- assert(t->op == '.');
- assert(t->left != NULL && t->left->cnfa.nstates > 0);
- assert(t->right != NULL && t->right->cnfa.nstates > 0);
+ struct dfa *d, *d2;
+ chr *mid;
+ int er;
+
+ assert(t->op == '.');
+ assert(t->left != NULL && t->left->cnfa.nstates > 0);
+ assert(t->right != NULL && t->right->cnfa.nstates > 0);
+
+ if (t->left->flags&SHORTER) { /* reverse scan */
+ return crevdissect(v, t, begin, end);
+ }
+
+ d = newdfa(v, &t->left->cnfa, &v->g->cmap, DOMALLOC);
+ if (ISERR()) {
+ return v->err;
+ }
+ d2 = newdfa(v, &t->right->cnfa, &v->g->cmap, DOMALLOC);
+ if (ISERR()) {
+ freedfa(d);
+ return v->err;
+ }
+ MDEBUG(("cconcat %d\n", t->retry));
- if (t->left->flags&SHORTER) /* reverse scan */
- return crevdissect(v, t, begin, end);
+ /*
+ * Pick a tentative midpoint.
+ */
- d = newdfa(v, &t->left->cnfa, &v->g->cmap, DOMALLOC);
- if (ISERR())
- return v->err;
- d2 = newdfa(v, &t->right->cnfa, &v->g->cmap, DOMALLOC);
- if (ISERR()) {
- freedfa(d);
- return v->err;
+ if (v->mem[t->retry] == 0) {
+ mid = longest(v, d, begin, end, NULL);
+ if (mid == NULL) {
+ freedfa(d);
+ freedfa(d2);
+ return REG_NOMATCH;
}
- MDEBUG(("cconcat %d\n", t->retry));
-
- /* pick a tentative midpoint */
- if (v->mem[t->retry] == 0) {
- mid = longest(v, d, begin, end, (int *)NULL);
- if (mid == NULL) {
- freedfa(d);
- freedfa(d2);
- return REG_NOMATCH;
+ MDEBUG(("tentative midpoint %ld\n", LOFF(mid)));
+ v->mem[t->retry] = (mid - begin) + 1;
+ } else {
+ mid = begin + (v->mem[t->retry] - 1);
+ MDEBUG(("working midpoint %ld\n", LOFF(mid)));
+ }
+
+ /*
+ * Iterate until satisfaction or failure.
+ */
+
+ for (;;) {
+ /*
+ * Try this midpoint on for size.
+ */
+
+ if (longest(v, d2, mid, end, NULL) == end) {
+ er = cdissect(v, t->left, begin, mid);
+ if (er == REG_OKAY) {
+ er = cdissect(v, t->right, mid, end);
+ if (er == REG_OKAY) {
+ /*
+ * Satisfaction.
+ */
+
+ MDEBUG(("successful\n"));
+ freedfa(d);
+ freedfa(d2);
+ return REG_OKAY;
}
- MDEBUG(("tentative midpoint %ld\n", LOFF(mid)));
- v->mem[t->retry] = (mid - begin) + 1;
- } else {
- mid = begin + (v->mem[t->retry] - 1);
- MDEBUG(("working midpoint %ld\n", LOFF(mid)));
+ }
+ if ((er != REG_OKAY) && (er != REG_NOMATCH)) {
+ freedfa(d);
+ freedfa(d2);
+ return er;
+ }
}
- /* iterate until satisfaction or failure */
- for (;;) {
- /* try this midpoint on for size */
- if (longest(v, d2, mid, end, NULL) == end) {
- er = cdissect(v, t->left, begin, mid);
- if (er == REG_OKAY) {
- er = cdissect(v, t->right, mid, end);
- if (er == REG_OKAY) {
- /* satisfaction */
- MDEBUG(("successful\n"));
- freedfa(d);
- freedfa(d2);
- return REG_OKAY;
- }
- }
- if ((er != REG_OKAY) && (er != REG_NOMATCH)) {
- freedfa(d);
- freedfa(d2);
- return er;
- }
- }
+ /*
+ * That midpoint didn't work, find a new one.
+ */
- /* that midpoint didn't work, find a new one */
- if (mid == begin) {
- /* all possibilities exhausted */
- MDEBUG(("%d no midpoint\n", t->retry));
- freedfa(d);
- freedfa(d2);
- return REG_NOMATCH;
- }
- mid = longest(v, d, begin, mid-1, (int *)NULL);
- if (mid == NULL) {
- /* failed to find a new one */
- MDEBUG(("%d failed midpoint\n", t->retry));
- freedfa(d);
- freedfa(d2);
- return REG_NOMATCH;
- }
- MDEBUG(("%d: new midpoint %ld\n", t->retry, LOFF(mid)));
- v->mem[t->retry] = (mid - begin) + 1;
- zapmem(v, t->left);
- zapmem(v, t->right);
+ if (mid == begin) {
+ /*
+ * All possibilities exhausted.
+ */
+
+ MDEBUG(("%d no midpoint\n", t->retry));
+ freedfa(d);
+ freedfa(d2);
+ return REG_NOMATCH;
}
+ mid = longest(v, d, begin, mid-1, NULL);
+ if (mid == NULL) {
+ /*
+ * Failed to find a new one.
+ */
+
+ MDEBUG(("%d failed midpoint\n", t->retry));
+ freedfa(d);
+ freedfa(d2);
+ return REG_NOMATCH;
+ }
+ MDEBUG(("%d: new midpoint %ld\n", t->retry, LOFF(mid)));
+ v->mem[t->retry] = (mid - begin) + 1;
+ zapmem(v, t->left);
+ zapmem(v, t->right);
+ }
}
-
+
/*
- crevdissect - determine backref shortest-first subexpression matches
- * The retry memory stores the offset of the trial midpoint from begin,
- * plus 1 so that 0 uniquely means "clean slate".
+ * The retry memory stores the offset of the trial midpoint from begin, plus 1
+ * so that 0 uniquely means "clean slate".
^ static int crevdissect(struct vars *, struct subre *, chr *, chr *);
*/
static int /* regexec return code */
-crevdissect(v, t, begin, end)
-struct vars *v;
-struct subre *t;
-chr *begin; /* beginning of relevant substring */
-chr *end; /* end of same */
+crevdissect(
+ struct vars *v,
+ struct subre *t,
+ chr *begin, /* beginning of relevant substring */
+ chr *end) /* end of same */
{
- struct dfa *d;
- struct dfa *d2;
- chr *mid;
- int er;
+ struct dfa *d;
+ struct dfa *d2;
+ chr *mid;
+ int er;
+
+ assert(t->op == '.');
+ assert(t->left != NULL && t->left->cnfa.nstates > 0);
+ assert(t->right != NULL && t->right->cnfa.nstates > 0);
+ assert(t->left->flags&SHORTER);
+
+ /*
+ * Concatenation -- need to split the substring between parts.
+ */
+
+ d = newdfa(v, &t->left->cnfa, &v->g->cmap, DOMALLOC);
+ if (ISERR()) {
+ return v->err;
+ }
+ d2 = newdfa(v, &t->right->cnfa, &v->g->cmap, DOMALLOC);
+ if (ISERR()) {
+ freedfa(d);
+ return v->err;
+ }
+ MDEBUG(("crev %d\n", t->retry));
- assert(t->op == '.');
- assert(t->left != NULL && t->left->cnfa.nstates > 0);
- assert(t->right != NULL && t->right->cnfa.nstates > 0);
- assert(t->left->flags&SHORTER);
+ /*
+ * Pick a tentative midpoint.
+ */
- /* concatenation -- need to split the substring between parts */
- d = newdfa(v, &t->left->cnfa, &v->g->cmap, DOMALLOC);
- if (ISERR())
- return v->err;
- d2 = newdfa(v, &t->right->cnfa, &v->g->cmap, DOMALLOC);
- if (ISERR()) {
- freedfa(d);
- return v->err;
+ if (v->mem[t->retry] == 0) {
+ mid = shortest(v, d, begin, begin, end, NULL, NULL);
+ if (mid == NULL) {
+ freedfa(d);
+ freedfa(d2);
+ return REG_NOMATCH;
}
- MDEBUG(("crev %d\n", t->retry));
-
- /* pick a tentative midpoint */
- if (v->mem[t->retry] == 0) {
- mid = shortest(v, d, begin, begin, end, (chr **)NULL, (int *)NULL);
- if (mid == NULL) {
- freedfa(d);
- freedfa(d2);
- return REG_NOMATCH;
+ MDEBUG(("tentative midpoint %ld\n", LOFF(mid)));
+ v->mem[t->retry] = (mid - begin) + 1;
+ } else {
+ mid = begin + (v->mem[t->retry] - 1);
+ MDEBUG(("working midpoint %ld\n", LOFF(mid)));
+ }
+
+ /*
+ * Iterate until satisfaction or failure.
+ */
+
+ for (;;) {
+ /*
+ * Try this midpoint on for size.
+ */
+
+ if (longest(v, d2, mid, end, NULL) == end) {
+ er = cdissect(v, t->left, begin, mid);
+ if (er == REG_OKAY) {
+ er = cdissect(v, t->right, mid, end);
+ if (er == REG_OKAY) {
+ /*
+ * Satisfaction.
+ */
+
+ MDEBUG(("successful\n"));
+ freedfa(d);
+ freedfa(d2);
+ return REG_OKAY;
}
- MDEBUG(("tentative midpoint %ld\n", LOFF(mid)));
- v->mem[t->retry] = (mid - begin) + 1;
- } else {
- mid = begin + (v->mem[t->retry] - 1);
- MDEBUG(("working midpoint %ld\n", LOFF(mid)));
+ }
+ if (er != REG_OKAY && er != REG_NOMATCH) {
+ freedfa(d);
+ freedfa(d2);
+ return er;
+ }
}
- /* iterate until satisfaction or failure */
- for (;;) {
- /* try this midpoint on for size */
- if (longest(v, d2, mid, end, NULL) == end) {
- er = cdissect(v, t->left, begin, mid);
- if (er == REG_OKAY) {
- er = cdissect(v, t->right, mid, end);
- if (er == REG_OKAY) {
- /* satisfaction */
- MDEBUG(("successful\n"));
- freedfa(d);
- freedfa(d2);
- return REG_OKAY;
- }
- }
- if (er != REG_OKAY && er != REG_NOMATCH) {
- freedfa(d);
- freedfa(d2);
- return er;
- }
- }
+ /*
+ * That midpoint didn't work, find a new one.
+ */
- /* that midpoint didn't work, find a new one */
- if (mid == end) {
- /* all possibilities exhausted */
- MDEBUG(("%d no midpoint\n", t->retry));
- freedfa(d);
- freedfa(d2);
- return REG_NOMATCH;
- }
- mid = shortest(v, d, begin, mid+1, end, (chr **)NULL, (int *)NULL);
- if (mid == NULL) {
- /* failed to find a new one */
- MDEBUG(("%d failed midpoint\n", t->retry));
- freedfa(d);
- freedfa(d2);
- return REG_NOMATCH;
- }
- MDEBUG(("%d: new midpoint %ld\n", t->retry, LOFF(mid)));
- v->mem[t->retry] = (mid - begin) + 1;
- zapmem(v, t->left);
- zapmem(v, t->right);
+ if (mid == end) {
+ /*
+ * All possibilities exhausted.
+ */
+
+ MDEBUG(("%d no midpoint\n", t->retry));
+ freedfa(d);
+ freedfa(d2);
+ return REG_NOMATCH;
}
+ mid = shortest(v, d, begin, mid+1, end, NULL, NULL);
+ if (mid == NULL) {
+ /*
+ * Failed to find a new one.
+ */
+
+ MDEBUG(("%d failed midpoint\n", t->retry));
+ freedfa(d);
+ freedfa(d2);
+ return REG_NOMATCH;
+ }
+ MDEBUG(("%d: new midpoint %ld\n", t->retry, LOFF(mid)));
+ v->mem[t->retry] = (mid - begin) + 1;
+ zapmem(v, t->left);
+ zapmem(v, t->right);
+ }
}
-
+
/*
- cbrdissect - determine backref subexpression matches
^ static int cbrdissect(struct vars *, struct subre *, chr *, chr *);
*/
static int /* regexec return code */
-cbrdissect(v, t, begin, end)
-struct vars *v;
-struct subre *t;
-chr *begin; /* beginning of relevant substring */
-chr *end; /* end of same */
+cbrdissect(
+ struct vars *v,
+ struct subre *t,
+ chr *begin, /* beginning of relevant substring */
+ chr *end) /* end of same */
{
- int i;
- int n = t->subno;
- size_t len;
- chr *paren;
- chr *p;
- chr *stop;
- int min = t->min;
- int max = t->max;
-
- assert(t != NULL);
- assert(t->op == 'b');
- assert(n >= 0);
- assert((size_t)n < v->nmatch);
-
- MDEBUG(("cbackref n%d %d{%d-%d}\n", t->retry, n, min, max));
-
- if (v->pmatch[n].rm_so == -1)
- return REG_NOMATCH;
- paren = v->start + v->pmatch[n].rm_so;
- len = v->pmatch[n].rm_eo - v->pmatch[n].rm_so;
-
- /* no room to maneuver -- retries are pointless */
- if (v->mem[t->retry])
- return REG_NOMATCH;
- v->mem[t->retry] = 1;
-
- /* special-case zero-length string */
- if (len == 0) {
- if (begin == end)
- return REG_OKAY;
- return REG_NOMATCH;
+ int i;
+ int n = t->subno;
+ size_t len;
+ chr *paren;
+ chr *p;
+ chr *stop;
+ int min = t->min;
+ int max = t->max;
+
+ assert(t != NULL);
+ assert(t->op == 'b');
+ assert(n >= 0);
+ assert((size_t)n < v->nmatch);
+
+ MDEBUG(("cbackref n%d %d{%d-%d}\n", t->retry, n, min, max));
+
+ if (v->pmatch[n].rm_so == -1) {
+ return REG_NOMATCH;
+ }
+ paren = v->start + v->pmatch[n].rm_so;
+ len = v->pmatch[n].rm_eo - v->pmatch[n].rm_so;
+
+ /*
+ * No room to maneuver -- retries are pointless.
+ */
+
+ if (v->mem[t->retry]) {
+ return REG_NOMATCH;
+ }
+ v->mem[t->retry] = 1;
+
+ /*
+ * Special-case zero-length string.
+ */
+
+ if (len == 0) {
+ if (begin == end) {
+ return REG_OKAY;
}
+ return REG_NOMATCH;
+ }
+
+ /*
+ * And too-short string.
+ */
+
+ assert(end >= begin);
+ if ((size_t)(end - begin) < len) {
+ return REG_NOMATCH;
+ }
+ stop = end - len;
+
+ /*
+ * Count occurrences.
+ */
- /* and too-short string */
- assert(end >= begin);
- if ((size_t)(end - begin) < len)
- return REG_NOMATCH;
- stop = end - len;
-
- /* count occurrences */
- i = 0;
- for (p = begin; p <= stop && (i < max || max == INFINITY); p += len) {
- if ((*v->g->compare)(paren, p, len) != 0)
- break;
- i++;
+ i = 0;
+ for (p = begin; p <= stop && (i < max || max == INFINITY); p += len) {
+ if ((*v->g->compare)(paren, p, len) != 0) {
+ break;
}
- MDEBUG(("cbackref found %d\n", i));
-
- /* and sort it out */
- if (p != end) /* didn't consume all of it */
- return REG_NOMATCH;
- if (min <= i && (i <= max || max == INFINITY))
- return REG_OKAY;
- return REG_NOMATCH; /* out of range */
-}
+ i++;
+ }
+ MDEBUG(("cbackref found %d\n", i));
+ /*
+ * And sort it out.
+ */
+
+ if (p != end) { /* didn't consume all of it */
+ return REG_NOMATCH;
+ }
+ if (min <= i && (i <= max || max == INFINITY)) {
+ return REG_OKAY;
+ }
+ return REG_NOMATCH; /* out of range */
+}
+
/*
- caltdissect - determine alternative subexpression matches (w. complications)
^ static int caltdissect(struct vars *, struct subre *, chr *, chr *);
*/
static int /* regexec return code */
-caltdissect(v, t, begin, end)
-struct vars *v;
-struct subre *t;
-chr *begin; /* beginning of relevant substring */
-chr *end; /* end of same */
+caltdissect(
+ struct vars *v,
+ struct subre *t,
+ chr *begin, /* beginning of relevant substring */
+ chr *end) /* end of same */
{
- struct dfa *d;
- int er;
-# define UNTRIED 0 /* not yet tried at all */
-# define TRYING 1 /* top matched, trying submatches */
-# define TRIED 2 /* top didn't match or submatches exhausted */
-
- if (t == NULL)
- return REG_NOMATCH;
- assert(t->op == '|');
- if (v->mem[t->retry] == TRIED)
- return caltdissect(v, t->right, begin, end);
-
- MDEBUG(("calt n%d\n", t->retry));
- assert(t->left != NULL);
+ struct dfa *d;
+ int er;
+#define UNTRIED 0 /* not yet tried at all */
+#define TRYING 1 /* top matched, trying submatches */
+#define TRIED 2 /* top didn't match or submatches exhausted */
- if (v->mem[t->retry] == UNTRIED) {
- d = newdfa(v, &t->left->cnfa, &v->g->cmap, DOMALLOC);
- if (ISERR())
- return v->err;
- if (longest(v, d, begin, end, (int *)NULL) != end) {
- freedfa(d);
- v->mem[t->retry] = TRIED;
- return caltdissect(v, t->right, begin, end);
- }
- freedfa(d);
- MDEBUG(("calt matched\n"));
- v->mem[t->retry] = TRYING;
- }
+ if (t == NULL) {
+ return REG_NOMATCH;
+ }
+ assert(t->op == '|');
+ if (v->mem[t->retry] == TRIED) {
+ return caltdissect(v, t->right, begin, end);
+ }
- er = cdissect(v, t->left, begin, end);
- if (er != REG_NOMATCH)
- return er;
+ MDEBUG(("calt n%d\n", t->retry));
+ assert(t->left != NULL);
- v->mem[t->retry] = TRIED;
- return caltdissect(v, t->right, begin, end);
-}
+ if (v->mem[t->retry] == UNTRIED) {
+ d = newdfa(v, &t->left->cnfa, &v->g->cmap, DOMALLOC);
+ if (ISERR()) {
+ return v->err;
+ }
+ if (longest(v, d, begin, end, NULL) != end) {
+ freedfa(d);
+ v->mem[t->retry] = TRIED;
+ return caltdissect(v, t->right, begin, end);
+ }
+ freedfa(d);
+ MDEBUG(("calt matched\n"));
+ v->mem[t->retry] = TRYING;
+ }
+ er = cdissect(v, t->left, begin, end);
+ if (er != REG_NOMATCH) {
+ return er;
+ }
+ v->mem[t->retry] = TRIED;
+ return caltdissect(v, t->right, begin, end);
+}
#include "rege_dfa.c"
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/regfree.c b/generic/regfree.c
index 17a7389..b0aaa70 100644
--- a/generic/regfree.c
+++ b/generic/regfree.c
@@ -2,20 +2,20 @@
* regfree - free an RE
*
* Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
- *
+ *
* Development of this software was funded, in part, by Cray Research Inc.,
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
* Corporation, none of whom are responsible for the results. The author
- * thanks all of them.
- *
+ * thanks all of them.
+ *
* Redistribution and use in source and binary forms -- with or without
* modification -- are permitted for any purpose, provided that
* redistributions in source form retain this entire copyright notice and
* indicate the origin and nature of any modifications.
- *
- * I'd appreciate being given credit for this package in the documentation
- * of software which uses it, but that is not a requirement.
- *
+ *
+ * I'd appreciate being given credit for this package in the documentation of
+ * software which uses it, but that is not a requirement.
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -27,13 +27,11 @@
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- *
- *
- * You might think that this could be incorporated into regcomp.c, and
- * that would be a reasonable idea... except that this is a generic
- * function (with a generic name), applicable to all compiled REs
- * regardless of the size of their characters, whereas the stuff in
- * regcomp.c gets compiled once per character size.
+ * You might think that this could be incorporated into regcomp.c, and that
+ * would be a reasonable idea... except that this is a generic function (with
+ * a generic name), applicable to all compiled REs regardless of the size of
+ * their characters, whereas the stuff in regcomp.c gets compiled once per
+ * character size.
*/
#include "regguts.h"
@@ -43,11 +41,20 @@
*
* Ignoring invocation with NULL is a convenience.
*/
-VOID
-regfree(re)
-regex_t *re;
+void
+regfree(
+ regex_t *re)
{
- if (re == NULL)
- return;
- (*((struct fns *)re->re_fns)->free)(re);
+ if (re == NULL) {
+ return;
+ }
+ (*((struct fns *)re->re_fns)->free)(re);
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/regfronts.c b/generic/regfronts.c
index 82f48e2..5003297 100644
--- a/generic/regfronts.c
+++ b/generic/regfronts.c
@@ -1,24 +1,24 @@
/*
* regcomp and regexec - front ends to re_ routines
*
- * Mostly for implementation of backward-compatibility kludges. Note
- * that these routines exist ONLY in char versions.
+ * Mostly for implementation of backward-compatibility kludges. Note that
+ * these routines exist ONLY in char versions.
*
* Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
- *
+ *
* Development of this software was funded, in part, by Cray Research Inc.,
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
* Corporation, none of whom are responsible for the results. The author
- * thanks all of them.
- *
+ * thanks all of them.
+ *
* Redistribution and use in source and binary forms -- with or without
* modification -- are permitted for any purpose, provided that
* redistributions in source form retain this entire copyright notice and
* indicate the origin and nature of any modifications.
- *
- * I'd appreciate being given credit for this package in the documentation
- * of software which uses it, but that is not a requirement.
- *
+ *
+ * I'd appreciate being given credit for this package in the documentation of
+ * software which uses it, but that is not a requirement.
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -29,55 +29,63 @@
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include "regguts.h"
-
+
/*
- regcomp - compile regular expression
*/
int
-regcomp(re, str, flags)
-regex_t *re;
-CONST char *str;
-int flags;
+regcomp(
+ regex_t *re,
+ CONST char *str,
+ int flags)
{
- size_t len;
- int f = flags;
+ size_t len;
+ int f = flags;
- if (f&REG_PEND) {
- len = re->re_endp - str;
- f &= ~REG_PEND;
- } else
- len = strlen(str);
+ if (f&REG_PEND) {
+ len = re->re_endp - str;
+ f &= ~REG_PEND;
+ } else {
+ len = strlen(str);
+ }
- return re_comp(re, str, len, f);
+ return re_comp(re, str, len, f);
}
-
+
/*
- regexec - execute regular expression
*/
int
-regexec(re, str, nmatch, pmatch, flags)
-regex_t *re;
-CONST char *str;
-size_t nmatch;
-regmatch_t pmatch[];
-int flags;
+regexec(
+ regex_t *re,
+ CONST char *str,
+ size_t nmatch,
+ regmatch_t pmatch[],
+ int flags)
{
- CONST char *start;
- size_t len;
- int f = flags;
+ CONST char *start;
+ size_t len;
+ int f = flags;
- if (f&REG_STARTEND) {
- start = str + pmatch[0].rm_so;
- len = pmatch[0].rm_eo - pmatch[0].rm_so;
- f &= ~REG_STARTEND;
- } else {
- start = str;
- len = strlen(str);
- }
+ if (f & REG_STARTEND) {
+ start = str + pmatch[0].rm_so;
+ len = pmatch[0].rm_eo - pmatch[0].rm_so;
+ f &= ~REG_STARTEND;
+ } else {
+ start = str;
+ len = strlen(str);
+ }
- return re_exec(re, start, len, nmatch, pmatch, f);
+ return re_exec(re, start, len, nmatch, pmatch, f);
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/regguts.h b/generic/regguts.h
index c77a8fc..67e3d03 100644
--- a/generic/regguts.h
+++ b/generic/regguts.h
@@ -2,20 +2,20 @@
* Internal interface definitions, etc., for the reg package
*
* Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
- *
+ *
* Development of this software was funded, in part, by Cray Research Inc.,
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
* Corporation, none of whom are responsible for the results. The author
- * thanks all of them.
- *
+ * thanks all of them.
+ *
* Redistribution and use in source and binary forms -- with or without
* modification -- are permitted for any purpose, provided that
* redistributions in source form retain this entire copyright notice and
* indicate the origin and nature of any modifications.
- *
- * I'd appreciate being given credit for this package in the documentation
- * of software which uses it, but that is not a requirement.
- *
+ *
+ * I'd appreciate being given credit for this package in the documentation of
+ * software which uses it, but that is not a requirement.
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -28,17 +28,13 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
-
/*
- * Environmental customization. It should not (I hope) be necessary to
- * alter the file you are now reading -- regcustom.h should handle it all,
- * given care here and elsewhere.
+ * Environmental customization. It should not (I hope) be necessary to alter
+ * the file you are now reading -- regcustom.h should handle it all, given
+ * care here and elsewhere.
*/
#include "regcustom.h"
-
-
/*
* Things that regcustom.h might override.
*/
@@ -54,34 +50,34 @@
/* assertions */
#ifndef assert
-# ifndef REG_DEBUG
-# ifndef NDEBUG
-# define NDEBUG /* no assertions */
-# endif
-# endif
+#ifndef REG_DEBUG
+#ifndef NDEBUG
+#define NDEBUG /* no assertions */
+#endif
+#endif /* !REG_DEBUG */
#include <assert.h>
#endif
/* voids */
#ifndef VOID
-#define VOID void /* for function return values */
+#define VOID void /* for function return values */
#endif
#ifndef DISCARD
-#define DISCARD VOID /* for throwing values away */
+#define DISCARD void /* for throwing values away */
#endif
#ifndef PVOID
-#define PVOID VOID * /* generic pointer */
+#define PVOID void * /* generic pointer */
#endif
#ifndef VS
-#define VS(x) ((PVOID)(x)) /* cast something to generic ptr */
+#define VS(x) ((void*)(x)) /* cast something to generic ptr */
#endif
#ifndef NOPARMS
-#define NOPARMS VOID /* for empty parm lists */
+#define NOPARMS void /* for empty parm lists */
#endif
/* const */
#ifndef CONST
-#define CONST const /* for old compilers, might be empty */
+#define CONST const /* for old compilers, might be empty */
#endif
/* function-pointer declarator */
@@ -109,11 +105,9 @@
#include <limits.h>
#endif
#ifndef _POSIX2_RE_DUP_MAX
-#define _POSIX2_RE_DUP_MAX 255 /* normally from <limits.h> */
+#define _POSIX2_RE_DUP_MAX 255 /* normally from <limits.h> */
#endif
-
-
/*
* misc
*/
@@ -126,8 +120,6 @@
#define REMAGIC 0xfed7 /* magic number for main struct */
-
-
/*
* debugging facilities
*/
@@ -141,8 +133,6 @@
#define MDEBUG(arglist) {}
#endif
-
-
/*
* bitmap manipulation
*/
@@ -150,14 +140,13 @@
#define BSET(uv, sn) ((uv)[(sn)/UBITS] |= (unsigned)1 << ((sn)%UBITS))
#define ISBSET(uv, sn) ((uv)[(sn)/UBITS] & ((unsigned)1 << ((sn)%UBITS)))
-
-
/*
- * We dissect a chr into byts for colormap table indexing. Here we define
- * a byt, which will be the same as a byte on most machines... The exact
- * size of a byt is not critical, but about 8 bits is good, and extraction
- * of 8-bit chunks is sometimes especially fast.
+ * We dissect a chr into byts for colormap table indexing. Here we define a
+ * byt, which will be the same as a byte on most machines... The exact size of
+ * a byt is not critical, but about 8 bits is good, and extraction of 8-bit
+ * chunks is sometimes especially fast.
*/
+
#ifndef BYTBITS
#define BYTBITS 8 /* bits in a byt */
#endif
@@ -166,69 +155,66 @@
#define NBYTS ((CHRBITS+BYTBITS-1)/BYTBITS)
/* the definition of GETCOLOR(), below, assumes NBYTS <= 4 */
-
-
/*
* As soon as possible, we map chrs into equivalence classes -- "colors" --
* which are of much more manageable number.
*/
+
typedef short color; /* colors of characters */
typedef int pcolor; /* what color promotes to */
#define COLORLESS (-1) /* impossible color */
#define WHITE 0 /* default color, parent of all others */
-
-
/*
- * A colormap is a tree -- more precisely, a DAG -- indexed at each level
- * by a byt of the chr, to map the chr to a color efficiently. Because
- * lower sections of the tree can be shared, it can exploit the usual
- * sparseness of such a mapping table. The tree is always NBYTS levels
- * deep (in the past it was shallower during construction but was "filled"
- * to full depth at the end of that); areas that are unaltered as yet point
- * to "fill blocks" which are entirely WHITE in color.
+ * A colormap is a tree -- more precisely, a DAG -- indexed at each level by a
+ * byt of the chr, to map the chr to a color efficiently. Because lower
+ * sections of the tree can be shared, it can exploit the usual sparseness of
+ * such a mapping table. The tree is always NBYTS levels deep (in the past it
+ * was shallower during construction but was "filled" to full depth at the end
+ * of that); areas that are unaltered as yet point to "fill blocks" which are
+ * entirely WHITE in color.
*/
/* the tree itself */
struct colors {
- color ccolor[BYTTAB];
+ color ccolor[BYTTAB];
};
struct ptrs {
- union tree *pptr[BYTTAB];
+ union tree *pptr[BYTTAB];
};
union tree {
- struct colors colors;
- struct ptrs ptrs;
+ struct colors colors;
+ struct ptrs ptrs;
};
#define tcolor colors.ccolor
#define tptr ptrs.pptr
-/* internal per-color structure for the color machinery */
+/* Internal per-color descriptor structure for the color machinery */
struct colordesc {
- uchr nchrs; /* number of chars of this color */
- color sub; /* open subcolor (if any); free chain ptr */
-# define NOSUB COLORLESS
- struct arc *arcs; /* color chain */
- int flags;
-# define FREECOL 01 /* currently free */
-# define PSEUDO 02 /* pseudocolor, no real chars */
-# define UNUSEDCOLOR(cd) ((cd)->flags&FREECOL)
- union tree *block; /* block of solid color, if any */
+ uchr nchrs; /* number of chars of this color */
+ color sub; /* open subcolor (if any); free chain ptr */
+#define NOSUB COLORLESS
+ struct arc *arcs; /* color chain */
+ int flags;
+#define FREECOL 01 /* currently free */
+#define PSEUDO 02 /* pseudocolor, no real chars */
+#define UNUSEDCOLOR(cd) ((cd)->flags&FREECOL)
+ union tree *block; /* block of solid color, if any */
};
/* the color map itself */
struct colormap {
- int magic;
-# define CMMAGIC 0x876
- struct vars *v; /* for compile error reporting */
- size_t ncds; /* number of colordescs */
- size_t max; /* highest in use */
- color free; /* beginning of free chain (if non-0) */
- struct colordesc *cd;
-# define CDEND(cm) (&(cm)->cd[(cm)->max + 1])
-# define NINLINECDS ((size_t)10)
- struct colordesc cdspace[NINLINECDS];
- union tree tree[NBYTS]; /* tree top, plus fill blocks */
+ int magic;
+#define CMMAGIC 0x876
+ struct vars *v; /* for compile error reporting */
+ size_t ncds; /* number of colordescs */
+ size_t max; /* highest in use */
+ color free; /* beginning of free chain (if non-0) */
+ struct colordesc *cd;
+#define CDEND(cm) (&(cm)->cd[(cm)->max + 1])
+#define NINLINECDS ((size_t)10)
+ struct colordesc cdspace[NINLINECDS];
+ union tree tree[NBYTS]; /* tree top, plus fill blocks */
};
/* optimization magic to do fast chr->color mapping */
@@ -247,182 +233,196 @@ struct colormap {
#define GETCOLOR(cm, c) ((cm)->tree->tptr[B3(c)]->tptr[B2(c)]->tptr[B1(c)]->tcolor[B0(c)])
#endif
-
-
/*
* Interface definitions for locale-interface functions in locale.c.
- * Multi-character collating elements (MCCEs) cause most of the trouble.
*/
+
+/* Representation of a set of characters. */
struct cvec {
- int nchrs; /* number of chrs */
- int chrspace; /* number of chrs possible */
- chr *chrs; /* pointer to vector of chrs */
- int nranges; /* number of ranges (chr pairs) */
- int rangespace; /* number of chrs possible */
- chr *ranges; /* pointer to vector of chr pairs */
- int nmcces; /* number of MCCEs */
- int mccespace; /* number of MCCEs possible */
- int nmccechrs; /* number of chrs used for MCCEs */
- chr *mcces[1]; /* pointers to 0-terminated MCCEs */
- /* and both batches of chrs are on the end */
+ int nchrs; /* number of chrs */
+ int chrspace; /* number of chrs possible */
+ chr *chrs; /* pointer to vector of chrs */
+ int nranges; /* number of ranges (chr pairs) */
+ int rangespace; /* number of chrs possible */
+ chr *ranges; /* pointer to vector of chr pairs */
};
-/* caution: this value cannot be changed easily */
-#define MAXMCCE 2 /* length of longest MCCE */
-
-
-
/*
- * definitions for NFA internal representation
+ * definitions for non-deterministic finite autmaton (NFA) internal
+ * representation
*
- * Having a "from" pointer within each arc may seem redundant, but it
- * saves a lot of hassle.
+ * Having a "from" pointer within each arc may seem redundant, but it saves a
+ * lot of hassle.
*/
+
struct state;
struct arc {
- int type;
-# define ARCFREE '\0'
- color co;
- struct state *from; /* where it's from (and contained within) */
- struct state *to; /* where it's to */
- struct arc *outchain; /* *from's outs chain or free chain */
-# define freechain outchain
- struct arc *inchain; /* *to's ins chain */
- struct arc *colorchain; /* color's arc chain */
- struct arc *colorchain_rev; /* back-link in color's arc chain */
+ int type;
+#define ARCFREE '\0'
+ color co;
+ struct state *from; /* where it's from (and contained within) */
+ struct state *to; /* where it's to */
+ struct arc *outchain; /* *from's outs chain or free chain */
+#define freechain outchain
+ struct arc *inchain; /* *to's ins chain */
+ struct arc *colorchain; /* color's arc chain */
+ struct arc *colorchainRev; /* back-link in color's arc chain */
};
struct arcbatch { /* for bulk allocation of arcs */
- struct arcbatch *next;
-# define ABSIZE 10
- struct arc a[ABSIZE];
+ struct arcbatch *next;
+#define ABSIZE 10
+ struct arc a[ABSIZE];
};
struct state {
- int no;
-# define FREESTATE (-1)
- char flag; /* marks special states */
- int nins; /* number of inarcs */
- struct arc *ins; /* chain of inarcs */
- int nouts; /* number of outarcs */
- struct arc *outs; /* chain of outarcs */
- struct arc *free; /* chain of free arcs */
- struct state *tmp; /* temporary for traversal algorithms */
- struct state *next; /* chain for traversing all */
- struct state *prev; /* back chain */
- struct arcbatch oas; /* first arcbatch, avoid malloc in easy case */
- int noas; /* number of arcs used in first arcbatch */
+ int no;
+#define FREESTATE (-1)
+ char flag; /* marks special states */
+ int nins; /* number of inarcs */
+ struct arc *ins; /* chain of inarcs */
+ int nouts; /* number of outarcs */
+ struct arc *outs; /* chain of outarcs */
+ struct arc *free; /* chain of free arcs */
+ struct state *tmp; /* temporary for traversal algorithms */
+ struct state *next; /* chain for traversing all */
+ struct state *prev; /* back chain */
+ struct arcbatch oas; /* first arcbatch, avoid malloc in easy case */
+ int noas; /* number of arcs used in first arcbatch */
};
struct nfa {
- struct state *pre; /* pre-initial state */
- struct state *init; /* initial state */
- struct state *final; /* final state */
- struct state *post; /* post-final state */
- int nstates; /* for numbering states */
- struct state *states; /* state-chain header */
- struct state *slast; /* tail of the chain */
- struct state *free; /* free list */
- struct colormap *cm; /* the color map */
- color bos[2]; /* colors, if any, assigned to BOS and BOL */
- color eos[2]; /* colors, if any, assigned to EOS and EOL */
- size_t size; /* current NFA size; differs from nstates as
- * it will be incremented by its children */
- struct vars *v; /* simplifies compile error reporting */
- struct nfa *parent; /* parent NFA, if any */
+ struct state *pre; /* pre-initial state */
+ struct state *init; /* initial state */
+ struct state *final; /* final state */
+ struct state *post; /* post-final state */
+ int nstates; /* for numbering states */
+ struct state *states; /* state-chain header */
+ struct state *slast; /* tail of the chain */
+ struct state *free; /* free list */
+ struct colormap *cm; /* the color map */
+ color bos[2]; /* colors, if any, assigned to BOS and BOL */
+ color eos[2]; /* colors, if any, assigned to EOS and EOL */
+ size_t size; /* Current NFA size; differs from nstates as
+ * it also counts the number of states created
+ * by children of this state. */
+ struct vars *v; /* simplifies compile error reporting */
+ struct nfa *parent; /* parent NFA, if any */
};
-
-
/*
* definitions for compacted NFA
*/
+
struct carc {
- color co; /* COLORLESS is list terminator */
- int to; /* state number */
+ color co; /* COLORLESS is list terminator */
+ int to; /* state number */
};
struct cnfa {
- int nstates; /* number of states */
- int ncolors; /* number of colors */
- int flags;
-# define HASLACONS 01 /* uses lookahead constraints */
- int pre; /* setup state number */
- int post; /* teardown state number */
- color bos[2]; /* colors, if any, assigned to BOS and BOL */
- color eos[2]; /* colors, if any, assigned to EOS and EOL */
- struct carc **states; /* vector of pointers to outarc lists */
- struct carc *arcs; /* the area for the lists */
+ int nstates; /* number of states */
+ int ncolors; /* number of colors */
+ int flags;
+#define HASLACONS 01 /* uses lookahead constraints */
+ int pre; /* setup state number */
+ int post; /* teardown state number */
+ color bos[2]; /* colors, if any, assigned to BOS and BOL */
+ color eos[2]; /* colors, if any, assigned to EOS and EOL */
+ struct carc **states; /* vector of pointers to outarc lists */
+ struct carc *arcs; /* the area for the lists */
};
#define ZAPCNFA(cnfa) ((cnfa).nstates = 0)
#define NULLCNFA(cnfa) ((cnfa).nstates == 0)
+/*
+ * Used to limit the maximum NFA size to something sane. [Bug 1810264]
+ */
-/* Used to limit the maximum NFA size */
#ifndef REG_MAX_STATES
-#define REG_MAX_STATES 100000
+# define REG_MAX_STATES 100000
#endif
-
/*
* subexpression tree
*/
+
struct subre {
- char op; /* '|', '.' (concat), 'b' (backref), '(', '=' */
- char flags;
-# define LONGER 01 /* prefers longer match */
-# define SHORTER 02 /* prefers shorter match */
-# define MIXED 04 /* mixed preference below */
-# define CAP 010 /* capturing parens below */
-# define BACKR 020 /* back reference below */
-# define INUSE 0100 /* in use in final tree */
-# define LOCAL 03 /* bits which may not propagate up */
-# define LMIX(f) ((f)<<2) /* LONGER -> MIXED */
-# define SMIX(f) ((f)<<1) /* SHORTER -> MIXED */
-# define UP(f) (((f)&~LOCAL) | (LMIX(f) & SMIX(f) & MIXED))
-# define MESSY(f) ((f)&(MIXED|CAP|BACKR))
-# define PREF(f) ((f)&LOCAL)
-# define PREF2(f1, f2) ((PREF(f1) != 0) ? PREF(f1) : PREF(f2))
-# define COMBINE(f1, f2) (UP((f1)|(f2)) | PREF2(f1, f2))
- short retry; /* index into retry memory */
- int subno; /* subexpression number (for 'b' and '(') */
- short min; /* min repetitions, for backref only */
- short max; /* max repetitions, for backref only */
- struct subre *left; /* left child, if any (also freelist chain) */
- struct subre *right; /* right child, if any */
- struct state *begin; /* outarcs from here... */
- struct state *end; /* ...ending in inarcs here */
- struct cnfa cnfa; /* compacted NFA, if any */
- struct subre *chain; /* for bookkeeping and error cleanup */
+ char op; /* '|', '.' (concat), 'b' (backref), '(',
+ * '=' */
+ char flags;
+#define LONGER 01 /* prefers longer match */
+#define SHORTER 02 /* prefers shorter match */
+#define MIXED 04 /* mixed preference below */
+#define CAP 010 /* capturing parens below */
+#define BACKR 020 /* back reference below */
+#define INUSE 0100 /* in use in final tree */
+#define LOCAL 03 /* bits which may not propagate up */
+#define LMIX(f) ((f)<<2) /* LONGER -> MIXED */
+#define SMIX(f) ((f)<<1) /* SHORTER -> MIXED */
+#define UP(f) (((f)&~LOCAL) | (LMIX(f) & SMIX(f) & MIXED))
+#define MESSY(f) ((f)&(MIXED|CAP|BACKR))
+#define PREF(f) ((f)&LOCAL)
+#define PREF2(f1, f2) ((PREF(f1) != 0) ? PREF(f1) : PREF(f2))
+#define COMBINE(f1, f2) (UP((f1)|(f2)) | PREF2(f1, f2))
+ short retry; /* index into retry memory */
+ int subno; /* subexpression number (for 'b' and '(') */
+ short min; /* min repetitions, for backref only */
+ short max; /* max repetitions, for backref only */
+ struct subre *left; /* left child, if any (also freelist chain) */
+ struct subre *right; /* right child, if any */
+ struct state *begin; /* outarcs from here... */
+ struct state *end; /* ...ending in inarcs here */
+ struct cnfa cnfa; /* compacted NFA, if any */
+ struct subre *chain; /* for bookkeeping and error cleanup */
};
-
-
/*
- * table of function pointers for generic manipulation functions
- * A regex_t's re_fns points to one of these.
+ * table of function pointers for generic manipulation functions. A regex_t's
+ * re_fns points to one of these.
*/
+
struct fns {
- VOID FUNCPTR(free, (regex_t *));
+ VOID FUNCPTR(free, (regex_t *));
};
-
-
/*
* the insides of a regex_t, hidden behind a void *
*/
+
struct guts {
- int magic;
-# define GUTSMAGIC 0xfed9
- int cflags; /* copy of compile flags */
- long info; /* copy of re_info */
- size_t nsub; /* copy of re_nsub */
- struct subre *tree;
- struct cnfa search; /* for fast preliminary search */
- int ntree;
- struct colormap cmap;
- int FUNCPTR(compare, (CONST chr *, CONST chr *, size_t));
- struct subre *lacons; /* lookahead-constraint vector */
- int nlacons; /* size of lacons */
+ int magic;
+#define GUTSMAGIC 0xfed9
+ int cflags; /* copy of compile flags */
+ long info; /* copy of re_info */
+ size_t nsub; /* copy of re_nsub */
+ struct subre *tree;
+ struct cnfa search; /* for fast preliminary search */
+ int ntree;
+ struct colormap cmap;
+ int FUNCPTR(compare, (CONST chr *, CONST chr *, size_t));
+ struct subre *lacons; /* lookahead-constraint vector */
+ int nlacons; /* size of lacons */
};
+
+/*
+ * Magic for allocating a variable workspace. This default version is
+ * stack-hungry.
+ */
+
+#ifndef AllocVars
+#define AllocVars(vPtr) \
+ struct vars var; \
+ register struct vars *vPtr = &var
+#endif
+#ifndef FreeVars
+#define FreeVars(vPtr) ((void) 0)
+#endif
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tcl.decls b/generic/tcl.decls
index c89c0da..20e9575 100644
--- a/generic/tcl.decls
+++ b/generic/tcl.decls
@@ -4,10 +4,11 @@
# functions that are exported by the Tcl library via the stubs table.
# This file is used to generate the tclDecls.h, tclPlatDecls.h,
# tclStub.c, and tclPlatStub.c files.
-#
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2001, 2002 by Kevin B. Kenny. All rights reserved.
+# Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
+#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -26,33 +27,34 @@ hooks {tclPlat tclInt tclIntPlat}
# to preserve backwards compatibility.
declare 0 generic {
- int Tcl_PkgProvideEx(Tcl_Interp* interp, CONST char* name,
- CONST char* version, ClientData clientData)
+ int Tcl_PkgProvideEx(Tcl_Interp *interp, CONST char *name,
+ CONST char *version, ClientData clientData)
}
declare 1 generic {
- CONST84_RETURN char * Tcl_PkgRequireEx(Tcl_Interp *interp, CONST char *name,
- CONST char *version, int exact, ClientData *clientDataPtr)
+ CONST84_RETURN char *Tcl_PkgRequireEx(Tcl_Interp *interp,
+ CONST char *name, CONST char *version, int exact,
+ ClientData *clientDataPtr)
}
declare 2 generic {
void Tcl_Panic(CONST char *format, ...)
}
declare 3 generic {
- char * Tcl_Alloc(unsigned int size)
+ char *Tcl_Alloc(unsigned int size)
}
declare 4 generic {
void Tcl_Free(char *ptr)
}
declare 5 generic {
- char * Tcl_Realloc(char *ptr, unsigned int size)
+ char *Tcl_Realloc(char *ptr, unsigned int size)
}
declare 6 generic {
- char * Tcl_DbCkalloc(unsigned int size, CONST char *file, int line)
+ char *Tcl_DbCkalloc(unsigned int size, CONST char *file, int line)
}
declare 7 generic {
int Tcl_DbCkfree(char *ptr, CONST char *file, int line)
}
declare 8 generic {
- char * Tcl_DbCkrealloc(char *ptr, unsigned int size,
+ char *Tcl_DbCkrealloc(char *ptr, unsigned int size,
CONST char *file, int line)
}
@@ -67,7 +69,6 @@ declare 9 unix {
declare 10 unix {
void Tcl_DeleteFileHandler(int fd)
}
-
declare 11 generic {
void Tcl_SetTimer(Tcl_Time *timePtr)
}
@@ -84,10 +85,10 @@ declare 15 generic {
void Tcl_AppendStringsToObj(Tcl_Obj *objPtr, ...)
}
declare 16 generic {
- void Tcl_AppendToObj(Tcl_Obj* objPtr, CONST char* bytes, int length)
+ void Tcl_AppendToObj(Tcl_Obj *objPtr, CONST char *bytes, int length)
}
declare 17 generic {
- Tcl_Obj * Tcl_ConcatObj(int objc, Tcl_Obj *CONST objv[])
+ Tcl_Obj *Tcl_ConcatObj(int objc, Tcl_Obj *CONST objv[])
}
declare 18 generic {
int Tcl_ConvertToType(Tcl_Interp *interp, Tcl_Obj *objPtr,
@@ -103,48 +104,48 @@ declare 21 generic {
int Tcl_DbIsShared(Tcl_Obj *objPtr, CONST char *file, int line)
}
declare 22 generic {
- Tcl_Obj * Tcl_DbNewBooleanObj(int boolValue, CONST char *file, int line)
+ Tcl_Obj *Tcl_DbNewBooleanObj(int boolValue, CONST char *file, int line)
}
declare 23 generic {
- Tcl_Obj * Tcl_DbNewByteArrayObj(CONST unsigned char *bytes, int length,
+ Tcl_Obj *Tcl_DbNewByteArrayObj(CONST unsigned char *bytes, int length,
CONST char *file, int line)
}
declare 24 generic {
- Tcl_Obj * Tcl_DbNewDoubleObj(double doubleValue,
- CONST char *file, int line)
+ Tcl_Obj *Tcl_DbNewDoubleObj(double doubleValue, CONST char *file,
+ int line)
}
declare 25 generic {
- Tcl_Obj * Tcl_DbNewListObj(int objc, Tcl_Obj *CONST *objv,
+ Tcl_Obj *Tcl_DbNewListObj(int objc, Tcl_Obj *CONST *objv,
CONST char *file, int line)
}
declare 26 generic {
- Tcl_Obj * Tcl_DbNewLongObj(long longValue, CONST char *file, int line)
+ Tcl_Obj *Tcl_DbNewLongObj(long longValue, CONST char *file, int line)
}
declare 27 generic {
- Tcl_Obj * Tcl_DbNewObj(CONST char *file, int line)
+ Tcl_Obj *Tcl_DbNewObj(CONST char *file, int line)
}
declare 28 generic {
- Tcl_Obj * Tcl_DbNewStringObj(CONST char *bytes, int length,
+ Tcl_Obj *Tcl_DbNewStringObj(CONST char *bytes, int length,
CONST char *file, int line)
}
declare 29 generic {
- Tcl_Obj * Tcl_DuplicateObj(Tcl_Obj *objPtr)
+ Tcl_Obj *Tcl_DuplicateObj(Tcl_Obj *objPtr)
}
declare 30 generic {
void TclFreeObj(Tcl_Obj *objPtr)
}
declare 31 generic {
- int Tcl_GetBoolean(Tcl_Interp *interp, CONST char *str, int *boolPtr)
+ int Tcl_GetBoolean(Tcl_Interp *interp, CONST char *src, int *boolPtr)
}
declare 32 generic {
int Tcl_GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
int *boolPtr)
}
declare 33 generic {
- unsigned char * Tcl_GetByteArrayFromObj(Tcl_Obj *objPtr, int *lengthPtr)
+ unsigned char *Tcl_GetByteArrayFromObj(Tcl_Obj *objPtr, int *lengthPtr)
}
declare 34 generic {
- int Tcl_GetDouble(Tcl_Interp *interp, CONST char *str, double *doublePtr)
+ int Tcl_GetDouble(Tcl_Interp *interp, CONST char *src, double *doublePtr)
}
declare 35 generic {
int Tcl_GetDoubleFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
@@ -155,7 +156,7 @@ declare 36 generic {
CONST84 char **tablePtr, CONST char *msg, int flags, int *indexPtr)
}
declare 37 generic {
- int Tcl_GetInt(Tcl_Interp *interp, CONST char *str, int *intPtr)
+ int Tcl_GetInt(Tcl_Interp *interp, CONST char *src, int *intPtr)
}
declare 38 generic {
int Tcl_GetIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *intPtr)
@@ -164,10 +165,10 @@ declare 39 generic {
int Tcl_GetLongFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, long *longPtr)
}
declare 40 generic {
- Tcl_ObjType * Tcl_GetObjType(CONST char *typeName)
+ Tcl_ObjType *Tcl_GetObjType(CONST char *typeName)
}
declare 41 generic {
- char * Tcl_GetStringFromObj(Tcl_Obj *objPtr, int *lengthPtr)
+ char *Tcl_GetStringFromObj(Tcl_Obj *objPtr, int *lengthPtr)
}
declare 42 generic {
void Tcl_InvalidateStringRep(Tcl_Obj *objPtr)
@@ -200,22 +201,22 @@ declare 49 generic {
Tcl_Obj *Tcl_NewBooleanObj(int boolValue)
}
declare 50 generic {
- Tcl_Obj *Tcl_NewByteArrayObj(CONST unsigned char* bytes, int length)
+ Tcl_Obj *Tcl_NewByteArrayObj(CONST unsigned char *bytes, int length)
}
declare 51 generic {
- Tcl_Obj * Tcl_NewDoubleObj(double doubleValue)
+ Tcl_Obj *Tcl_NewDoubleObj(double doubleValue)
}
declare 52 generic {
- Tcl_Obj * Tcl_NewIntObj(int intValue)
+ Tcl_Obj *Tcl_NewIntObj(int intValue)
}
declare 53 generic {
- Tcl_Obj * Tcl_NewListObj(int objc, Tcl_Obj *CONST objv[])
+ Tcl_Obj *Tcl_NewListObj(int objc, Tcl_Obj *CONST objv[])
}
declare 54 generic {
- Tcl_Obj * Tcl_NewLongObj(long longValue)
+ Tcl_Obj *Tcl_NewLongObj(long longValue)
}
declare 55 generic {
- Tcl_Obj * Tcl_NewObj(void)
+ Tcl_Obj *Tcl_NewObj(void)
}
declare 56 generic {
Tcl_Obj *Tcl_NewStringObj(CONST char *bytes, int length)
@@ -224,7 +225,7 @@ declare 57 generic {
void Tcl_SetBooleanObj(Tcl_Obj *objPtr, int boolValue)
}
declare 58 generic {
- unsigned char * Tcl_SetByteArrayLength(Tcl_Obj *objPtr, int length)
+ unsigned char *Tcl_SetByteArrayLength(Tcl_Obj *objPtr, int length)
}
declare 59 generic {
void Tcl_SetByteArrayObj(Tcl_Obj *objPtr, CONST unsigned char *bytes,
@@ -246,7 +247,7 @@ declare 64 generic {
void Tcl_SetObjLength(Tcl_Obj *objPtr, int length)
}
declare 65 generic {
- void Tcl_SetStringObj(Tcl_Obj* objPtr, CONST char* bytes, int length)
+ void Tcl_SetStringObj(Tcl_Obj *objPtr, CONST char *bytes, int length)
}
declare 66 generic {
void Tcl_AddErrorInfo(Tcl_Interp *interp, CONST char *message)
@@ -259,7 +260,7 @@ declare 68 generic {
void Tcl_AllowExceptions(Tcl_Interp *interp)
}
declare 69 generic {
- void Tcl_AppendElement(Tcl_Interp *interp, CONST char *string)
+ void Tcl_AppendElement(Tcl_Interp *interp, CONST char *element)
}
declare 70 generic {
void Tcl_AppendResult(Tcl_Interp *interp, ...)
@@ -304,7 +305,7 @@ declare 82 generic {
int Tcl_CommandComplete(CONST char *cmd)
}
declare 83 generic {
- char * Tcl_Concat(int argc, CONST84 char * CONST *argv)
+ char *Tcl_Concat(int argc, CONST84 char *CONST *argv)
}
declare 84 generic {
int Tcl_ConvertElement(CONST char *src, char *dst, int flags)
@@ -316,7 +317,7 @@ declare 85 generic {
declare 86 generic {
int Tcl_CreateAlias(Tcl_Interp *slave, CONST char *slaveCmd,
Tcl_Interp *target, CONST char *targetCmd, int argc,
- CONST84 char * CONST *argv)
+ CONST84 char *CONST *argv)
}
declare 87 generic {
int Tcl_CreateAliasObj(Tcl_Interp *slave, CONST char *slaveCmd,
@@ -348,11 +349,11 @@ declare 93 generic {
void Tcl_CreateExitHandler(Tcl_ExitProc *proc, ClientData clientData)
}
declare 94 generic {
- Tcl_Interp * Tcl_CreateInterp(void)
+ Tcl_Interp *Tcl_CreateInterp(void)
}
declare 95 generic {
void Tcl_CreateMathFunc(Tcl_Interp *interp, CONST char *name,
- int numArgs, Tcl_ValueType *argTypes,
+ int numArgs, Tcl_ValueType *argTypes,
Tcl_MathProc *proc, ClientData clientData)
}
declare 96 generic {
@@ -362,7 +363,7 @@ declare 96 generic {
Tcl_CmdDeleteProc *deleteProc)
}
declare 97 generic {
- Tcl_Interp * Tcl_CreateSlave(Tcl_Interp *interp, CONST char *slaveName,
+ Tcl_Interp *Tcl_CreateSlave(Tcl_Interp *interp, CONST char *slaveName,
int isSafe)
}
declare 98 generic {
@@ -409,7 +410,7 @@ declare 109 generic {
declare 110 generic {
void Tcl_DeleteInterp(Tcl_Interp *interp)
}
-declare 111 {unix win} {
+declare 111 generic {
void Tcl_DetachPids(int numPids, Tcl_Pid *pidPtr)
}
declare 112 generic {
@@ -429,10 +430,10 @@ declare 116 generic {
void Tcl_DoWhenIdle(Tcl_IdleProc *proc, ClientData clientData)
}
declare 117 generic {
- char * Tcl_DStringAppend(Tcl_DString *dsPtr, CONST char *str, int length)
+ char *Tcl_DStringAppend(Tcl_DString *dsPtr, CONST char *bytes, int length)
}
declare 118 generic {
- char * Tcl_DStringAppendElement(Tcl_DString *dsPtr, CONST char *string)
+ char *Tcl_DStringAppendElement(Tcl_DString *dsPtr, CONST char *element)
}
declare 119 generic {
void Tcl_DStringEndSublist(Tcl_DString *dsPtr)
@@ -459,13 +460,13 @@ declare 126 generic {
int Tcl_Eof(Tcl_Channel chan)
}
declare 127 generic {
- CONST84_RETURN char * Tcl_ErrnoId(void)
+ CONST84_RETURN char *Tcl_ErrnoId(void)
}
declare 128 generic {
- CONST84_RETURN char * Tcl_ErrnoMsg(int err)
+ CONST84_RETURN char *Tcl_ErrnoMsg(int err)
}
declare 129 generic {
- int Tcl_Eval(Tcl_Interp *interp, CONST char *string)
+ int Tcl_Eval(Tcl_Interp *interp, CONST char *script)
}
# This is obsolete, use Tcl_FSEvalFile
declare 130 generic {
@@ -485,19 +486,19 @@ declare 134 generic {
CONST char *cmdName)
}
declare 135 generic {
- int Tcl_ExprBoolean(Tcl_Interp *interp, CONST char *str, int *ptr)
+ int Tcl_ExprBoolean(Tcl_Interp *interp, CONST char *expr, int *ptr)
}
declare 136 generic {
int Tcl_ExprBooleanObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *ptr)
}
declare 137 generic {
- int Tcl_ExprDouble(Tcl_Interp *interp, CONST char *str, double *ptr)
+ int Tcl_ExprDouble(Tcl_Interp *interp, CONST char *expr, double *ptr)
}
declare 138 generic {
int Tcl_ExprDoubleObj(Tcl_Interp *interp, Tcl_Obj *objPtr, double *ptr)
}
declare 139 generic {
- int Tcl_ExprLong(Tcl_Interp *interp, CONST char *str, long *ptr)
+ int Tcl_ExprLong(Tcl_Interp *interp, CONST char *expr, long *ptr)
}
declare 140 generic {
int Tcl_ExprLongObj(Tcl_Interp *interp, Tcl_Obj *objPtr, long *ptr)
@@ -507,7 +508,7 @@ declare 141 generic {
Tcl_Obj **resultPtrPtr)
}
declare 142 generic {
- int Tcl_ExprString(Tcl_Interp *interp, CONST char *string)
+ int Tcl_ExprString(Tcl_Interp *interp, CONST char *expr)
}
declare 143 generic {
void Tcl_Finalize(void)
@@ -516,7 +517,7 @@ declare 144 generic {
void Tcl_FindExecutable(CONST char *argv0)
}
declare 145 generic {
- Tcl_HashEntry * Tcl_FirstHashEntry(Tcl_HashTable *tablePtr,
+ Tcl_HashEntry *Tcl_FirstHashEntry(Tcl_HashTable *tablePtr,
Tcl_HashSearch *searchPtr)
}
declare 146 generic {
@@ -557,47 +558,47 @@ declare 155 generic {
int Tcl_GetChannelMode(Tcl_Channel chan)
}
declare 156 generic {
- CONST84_RETURN char * Tcl_GetChannelName(Tcl_Channel chan)
+ CONST84_RETURN char *Tcl_GetChannelName(Tcl_Channel chan)
}
declare 157 generic {
int Tcl_GetChannelOption(Tcl_Interp *interp, Tcl_Channel chan,
CONST char *optionName, Tcl_DString *dsPtr)
}
declare 158 generic {
- Tcl_ChannelType * Tcl_GetChannelType(Tcl_Channel chan)
+ Tcl_ChannelType *Tcl_GetChannelType(Tcl_Channel chan)
}
declare 159 generic {
int Tcl_GetCommandInfo(Tcl_Interp *interp, CONST char *cmdName,
Tcl_CmdInfo *infoPtr)
}
declare 160 generic {
- CONST84_RETURN char * Tcl_GetCommandName(Tcl_Interp *interp,
+ CONST84_RETURN char *Tcl_GetCommandName(Tcl_Interp *interp,
Tcl_Command command)
}
declare 161 generic {
int Tcl_GetErrno(void)
}
declare 162 generic {
- CONST84_RETURN char * Tcl_GetHostName(void)
+ CONST84_RETURN char *Tcl_GetHostName(void)
}
declare 163 generic {
int Tcl_GetInterpPath(Tcl_Interp *askInterp, Tcl_Interp *slaveInterp)
}
declare 164 generic {
- Tcl_Interp * Tcl_GetMaster(Tcl_Interp *interp)
+ Tcl_Interp *Tcl_GetMaster(Tcl_Interp *interp)
}
declare 165 generic {
- CONST char * Tcl_GetNameOfExecutable(void)
+ CONST char *Tcl_GetNameOfExecutable(void)
}
declare 166 generic {
- Tcl_Obj * Tcl_GetObjResult(Tcl_Interp *interp)
+ Tcl_Obj *Tcl_GetObjResult(Tcl_Interp *interp)
}
# Tcl_GetOpenFile is only available on unix, but it is a part of the old
# generic interface, so we inlcude it here for compatibility reasons.
declare 167 unix {
- int Tcl_GetOpenFile(Tcl_Interp *interp, CONST char *str, int forWriting,
+ int Tcl_GetOpenFile(Tcl_Interp *interp, CONST char *chanID, int forWriting,
int checkUsage, ClientData *filePtr)
}
# Obsolete. Should now use Tcl_FSGetPathType which is objectified
@@ -615,20 +616,20 @@ declare 171 generic {
int Tcl_GetServiceMode(void)
}
declare 172 generic {
- Tcl_Interp * Tcl_GetSlave(Tcl_Interp *interp, CONST char *slaveName)
+ Tcl_Interp *Tcl_GetSlave(Tcl_Interp *interp, CONST char *slaveName)
}
declare 173 generic {
Tcl_Channel Tcl_GetStdChannel(int type)
}
declare 174 generic {
- CONST84_RETURN char * Tcl_GetStringResult(Tcl_Interp *interp)
+ CONST84_RETURN char *Tcl_GetStringResult(Tcl_Interp *interp)
}
declare 175 generic {
- CONST84_RETURN char * Tcl_GetVar(Tcl_Interp *interp, CONST char *varName,
+ CONST84_RETURN char *Tcl_GetVar(Tcl_Interp *interp, CONST char *varName,
int flags)
}
declare 176 generic {
- CONST84_RETURN char * Tcl_GetVar2(Tcl_Interp *interp, CONST char *part1,
+ CONST84_RETURN char *Tcl_GetVar2(Tcl_Interp *interp, CONST char *part1,
CONST char *part2, int flags)
}
declare 177 generic {
@@ -661,7 +662,7 @@ declare 185 generic {
}
# Obsolete, use Tcl_FSJoinPath
declare 186 generic {
- char * Tcl_JoinPath(int argc, CONST84 char * CONST *argv,
+ char *Tcl_JoinPath(int argc, CONST84 char *CONST *argv,
Tcl_DString *resultPtr)
}
declare 187 generic {
@@ -671,7 +672,7 @@ declare 187 generic {
# This slot is reserved for use by the plus patch:
# declare 188 generic {
-# Tcl_MainLoop
+# Tcl_MainLoop
# }
declare 189 generic {
@@ -684,23 +685,23 @@ declare 191 generic {
Tcl_Channel Tcl_MakeTcpClientChannel(ClientData tcpSocket)
}
declare 192 generic {
- char * Tcl_Merge(int argc, CONST84 char * CONST *argv)
+ char *Tcl_Merge(int argc, CONST84 char *CONST *argv)
}
declare 193 generic {
- Tcl_HashEntry * Tcl_NextHashEntry(Tcl_HashSearch *searchPtr)
+ Tcl_HashEntry *Tcl_NextHashEntry(Tcl_HashSearch *searchPtr)
}
declare 194 generic {
void Tcl_NotifyChannel(Tcl_Channel channel, int mask)
}
declare 195 generic {
- Tcl_Obj * Tcl_ObjGetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
+ Tcl_Obj *Tcl_ObjGetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
Tcl_Obj *part2Ptr, int flags)
}
declare 196 generic {
- Tcl_Obj * Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
+ Tcl_Obj *Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags)
}
-declare 197 {unix win} {
+declare 197 generic {
Tcl_Channel Tcl_OpenCommandChannel(Tcl_Interp *interp, int argc,
CONST84 char **argv, int flags)
}
@@ -725,10 +726,10 @@ declare 202 generic {
void Tcl_PrintDouble(Tcl_Interp *interp, double value, char *dst)
}
declare 203 generic {
- int Tcl_PutEnv(CONST char *string)
+ int Tcl_PutEnv(CONST char *assignment)
}
declare 204 generic {
- CONST84_RETURN char * Tcl_PosixError(Tcl_Interp *interp)
+ CONST84_RETURN char *Tcl_PosixError(Tcl_Interp *interp)
}
declare 205 generic {
void Tcl_QueueEvent(Tcl_Event *evPtr, Tcl_QueuePosition position)
@@ -736,7 +737,7 @@ declare 205 generic {
declare 206 generic {
int Tcl_Read(Tcl_Channel chan, char *bufPtr, int toRead)
}
-declare 207 {unix win} {
+declare 207 generic {
void Tcl_ReapDetachedProcs(void)
}
declare 208 generic {
@@ -752,14 +753,14 @@ declare 211 generic {
void Tcl_RegisterObjType(Tcl_ObjType *typePtr)
}
declare 212 generic {
- Tcl_RegExp Tcl_RegExpCompile(Tcl_Interp *interp, CONST char *string)
+ Tcl_RegExp Tcl_RegExpCompile(Tcl_Interp *interp, CONST char *pattern)
}
declare 213 generic {
int Tcl_RegExpExec(Tcl_Interp *interp, Tcl_RegExp regexp,
- CONST char *str, CONST char *start)
+ CONST char *text, CONST char *start)
}
declare 214 generic {
- int Tcl_RegExpMatch(Tcl_Interp *interp, CONST char *str,
+ int Tcl_RegExpMatch(Tcl_Interp *interp, CONST char *text,
CONST char *pattern)
}
declare 215 generic {
@@ -773,10 +774,10 @@ declare 217 generic {
void Tcl_ResetResult(Tcl_Interp *interp)
}
declare 218 generic {
- int Tcl_ScanElement(CONST char *str, int *flagPtr)
+ int Tcl_ScanElement(CONST char *src, int *flagPtr)
}
declare 219 generic {
- int Tcl_ScanCountedElement(CONST char *str, int length, int *flagPtr)
+ int Tcl_ScanCountedElement(CONST char *src, int length, int *flagPtr)
}
# Obsolete
declare 220 generic {
@@ -819,7 +820,7 @@ declare 231 generic {
int Tcl_SetRecursionLimit(Tcl_Interp *interp, int depth)
}
declare 232 generic {
- void Tcl_SetResult(Tcl_Interp *interp, char *str,
+ void Tcl_SetResult(Tcl_Interp *interp, char *result,
Tcl_FreeProc *freeProc)
}
declare 233 generic {
@@ -835,18 +836,18 @@ declare 236 generic {
void Tcl_SetStdChannel(Tcl_Channel channel, int type)
}
declare 237 generic {
- CONST84_RETURN char * Tcl_SetVar(Tcl_Interp *interp, CONST char *varName,
+ CONST84_RETURN char *Tcl_SetVar(Tcl_Interp *interp, CONST char *varName,
CONST char *newValue, int flags)
}
declare 238 generic {
- CONST84_RETURN char * Tcl_SetVar2(Tcl_Interp *interp, CONST char *part1,
+ CONST84_RETURN char *Tcl_SetVar2(Tcl_Interp *interp, CONST char *part1,
CONST char *part2, CONST char *newValue, int flags)
}
declare 239 generic {
- CONST84_RETURN char * Tcl_SignalId(int sig)
+ CONST84_RETURN char *Tcl_SignalId(int sig)
}
declare 240 generic {
- CONST84_RETURN char * Tcl_SignalMsg(int sig)
+ CONST84_RETURN char *Tcl_SignalMsg(int sig)
}
declare 241 generic {
void Tcl_SourceRCFile(Tcl_Interp *interp)
@@ -879,7 +880,7 @@ declare 248 generic {
int flags, Tcl_VarTraceProc *proc, ClientData clientData)
}
declare 249 generic {
- char * Tcl_TranslateFileName(Tcl_Interp *interp, CONST char *name,
+ char *Tcl_TranslateFileName(Tcl_Interp *interp, CONST char *name,
Tcl_DString *bufferPtr)
}
declare 250 generic {
@@ -943,7 +944,6 @@ declare 265 generic {
declare 266 generic {
void Tcl_ValidateAllMemory(CONST char *file, int line)
}
-
declare 267 generic {
void Tcl_AppendResultVA(Tcl_Interp *interp, va_list argList)
}
@@ -951,30 +951,28 @@ declare 268 generic {
void Tcl_AppendStringsToObjVA(Tcl_Obj *objPtr, va_list argList)
}
declare 269 generic {
- CONST84_RETURN char * Tcl_HashStats(Tcl_HashTable *tablePtr)
+ char *Tcl_HashStats(Tcl_HashTable *tablePtr)
}
declare 270 generic {
- CONST84_RETURN char * Tcl_ParseVar(Tcl_Interp *interp, CONST char *str,
+ CONST84_RETURN char *Tcl_ParseVar(Tcl_Interp *interp, CONST char *start,
CONST84 char **termPtr)
}
declare 271 generic {
- CONST84_RETURN char * Tcl_PkgPresent(Tcl_Interp *interp, CONST char *name,
+ CONST84_RETURN char *Tcl_PkgPresent(Tcl_Interp *interp, CONST char *name,
CONST char *version, int exact)
}
declare 272 generic {
- CONST84_RETURN char * Tcl_PkgPresentEx(Tcl_Interp *interp, CONST char *name,
- CONST char *version, int exact, ClientData *clientDataPtr)
+ CONST84_RETURN char *Tcl_PkgPresentEx(Tcl_Interp *interp,
+ CONST char *name, CONST char *version, int exact,
+ ClientData *clientDataPtr)
}
declare 273 generic {
- int Tcl_PkgProvide(Tcl_Interp *interp, CONST char *name,
+ int Tcl_PkgProvide(Tcl_Interp *interp, CONST char *name,
CONST char *version)
}
-
-# TIP #268: The internally used new Require function is in slot
-# 573. Assuming TCL_TIP268 was activated.
-
+# TIP #268: The internally used new Require function is in slot 573.
declare 274 generic {
- CONST84_RETURN char * Tcl_PkgRequire(Tcl_Interp *interp, CONST char *name,
+ CONST84_RETURN char *Tcl_PkgRequire(Tcl_Interp *interp, CONST char *name,
CONST char *version, int exact)
}
declare 275 generic {
@@ -1011,8 +1009,9 @@ declare 280 generic {
# version into the new one).
declare 281 generic {
- Tcl_Channel Tcl_StackChannel(Tcl_Interp *interp, Tcl_ChannelType *typePtr,
- ClientData instanceData, int mask, Tcl_Channel prevChan)
+ Tcl_Channel Tcl_StackChannel(Tcl_Interp *interp,
+ Tcl_ChannelType *typePtr, ClientData instanceData,
+ int mask, Tcl_Channel prevChan)
}
declare 282 generic {
int Tcl_UnstackChannel(Tcl_Interp *interp, Tcl_Channel chan)
@@ -1030,14 +1029,13 @@ declare 284 generic {
# declare 285 generic {
# }
-
# Added in 8.1:
declare 286 generic {
void Tcl_AppendObjToObj(Tcl_Obj *objPtr, Tcl_Obj *appendObjPtr)
}
declare 287 generic {
- Tcl_Encoding Tcl_CreateEncoding(Tcl_EncodingType *typePtr)
+ Tcl_Encoding Tcl_CreateEncoding(CONST Tcl_EncodingType *typePtr)
}
declare 288 generic {
void Tcl_CreateThreadExitHandler(Tcl_ExitProc *proc, ClientData clientData)
@@ -1069,7 +1067,7 @@ declare 295 generic {
int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr)
}
declare 296 generic {
- char * Tcl_ExternalToUtfDString(Tcl_Encoding encoding,
+ char *Tcl_ExternalToUtfDString(Tcl_Encoding encoding,
CONST char *src, int srcLen, Tcl_DString *dsPtr)
}
declare 297 generic {
@@ -1088,21 +1086,21 @@ declare 301 generic {
Tcl_Encoding Tcl_GetEncoding(Tcl_Interp *interp, CONST char *name)
}
declare 302 generic {
- CONST84_RETURN char * Tcl_GetEncodingName(Tcl_Encoding encoding)
+ CONST84_RETURN char *Tcl_GetEncodingName(Tcl_Encoding encoding)
}
declare 303 generic {
void Tcl_GetEncodingNames(Tcl_Interp *interp)
}
declare 304 generic {
int Tcl_GetIndexFromObjStruct(Tcl_Interp *interp, Tcl_Obj *objPtr,
- CONST VOID *tablePtr, int offset, CONST char *msg, int flags,
+ CONST void *tablePtr, int offset, CONST char *msg, int flags,
int *indexPtr)
}
declare 305 generic {
- VOID * Tcl_GetThreadData(Tcl_ThreadDataKey *keyPtr, int size)
+ void *Tcl_GetThreadData(Tcl_ThreadDataKey *keyPtr, int size)
}
declare 306 generic {
- Tcl_Obj * Tcl_GetVar2Ex(Tcl_Interp *interp, CONST char *part1,
+ Tcl_Obj *Tcl_GetVar2Ex(Tcl_Interp *interp, CONST char *part1,
CONST char *part2, int flags)
}
declare 307 generic {
@@ -1122,7 +1120,7 @@ declare 311 generic {
Tcl_Time *timePtr)
}
declare 312 generic {
- int Tcl_NumUtfChars(CONST char *src, int len)
+ int Tcl_NumUtfChars(CONST char *src, int length)
}
declare 313 generic {
int Tcl_ReadChars(Tcl_Channel channel, Tcl_Obj *objPtr, int charsToRead,
@@ -1138,14 +1136,14 @@ declare 316 generic {
int Tcl_SetSystemEncoding(Tcl_Interp *interp, CONST char *name)
}
declare 317 generic {
- Tcl_Obj * Tcl_SetVar2Ex(Tcl_Interp *interp, CONST char *part1,
- CONST char *part2, Tcl_Obj *newValuePtr, int flags)
+ Tcl_Obj *Tcl_SetVar2Ex(Tcl_Interp *interp, CONST char *part1,
+ CONST char *part2, Tcl_Obj *newValuePtr, int flags)
}
declare 318 generic {
void Tcl_ThreadAlert(Tcl_ThreadId threadId)
}
declare 319 generic {
- void Tcl_ThreadQueueEvent(Tcl_ThreadId threadId, Tcl_Event* evPtr,
+ void Tcl_ThreadQueueEvent(Tcl_ThreadId threadId, Tcl_Event *evPtr,
Tcl_QueuePosition position)
}
declare 320 generic {
@@ -1164,25 +1162,25 @@ declare 324 generic {
int Tcl_UniCharToUtf(int ch, char *buf)
}
declare 325 generic {
- CONST84_RETURN char * Tcl_UtfAtIndex(CONST char *src, int index)
+ CONST84_RETURN char *Tcl_UtfAtIndex(CONST char *src, int index)
}
declare 326 generic {
- int Tcl_UtfCharComplete(CONST char *src, int len)
+ int Tcl_UtfCharComplete(CONST char *src, int length)
}
declare 327 generic {
int Tcl_UtfBackslash(CONST char *src, int *readPtr, char *dst)
}
declare 328 generic {
- CONST84_RETURN char * Tcl_UtfFindFirst(CONST char *src, int ch)
+ CONST84_RETURN char *Tcl_UtfFindFirst(CONST char *src, int ch)
}
declare 329 generic {
- CONST84_RETURN char * Tcl_UtfFindLast(CONST char *src, int ch)
+ CONST84_RETURN char *Tcl_UtfFindLast(CONST char *src, int ch)
}
declare 330 generic {
- CONST84_RETURN char * Tcl_UtfNext(CONST char *src)
+ CONST84_RETURN char *Tcl_UtfNext(CONST char *src)
}
declare 331 generic {
- CONST84_RETURN char * Tcl_UtfPrev(CONST char *src, CONST char *start)
+ CONST84_RETURN char *Tcl_UtfPrev(CONST char *src, CONST char *start)
}
declare 332 generic {
int Tcl_UtfToExternal(Tcl_Interp *interp, Tcl_Encoding encoding,
@@ -1191,7 +1189,7 @@ declare 332 generic {
int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr)
}
declare 333 generic {
- char * Tcl_UtfToExternalDString(Tcl_Encoding encoding,
+ char *Tcl_UtfToExternalDString(Tcl_Encoding encoding,
CONST char *src, int srcLen, Tcl_DString *dsPtr)
}
declare 334 generic {
@@ -1213,10 +1211,10 @@ declare 339 generic {
int Tcl_WriteObj(Tcl_Channel chan, Tcl_Obj *objPtr)
}
declare 340 generic {
- char * Tcl_GetString(Tcl_Obj *objPtr)
+ char *Tcl_GetString(Tcl_Obj *objPtr)
}
declare 341 generic {
- CONST84_RETURN char * Tcl_GetDefaultEncodingDir(void)
+ CONST84_RETURN char *Tcl_GetDefaultEncodingDir(void)
}
declare 342 generic {
void Tcl_SetDefaultEncodingDir(CONST char *path)
@@ -1249,25 +1247,24 @@ declare 351 generic {
int Tcl_UniCharIsWordChar(int ch)
}
declare 352 generic {
- int Tcl_UniCharLen(CONST Tcl_UniChar *str)
+ int Tcl_UniCharLen(CONST Tcl_UniChar *uniStr)
}
declare 353 generic {
- int Tcl_UniCharNcmp(CONST Tcl_UniChar *cs, CONST Tcl_UniChar *ct,
- unsigned long n)
+ int Tcl_UniCharNcmp(CONST Tcl_UniChar *ucs, CONST Tcl_UniChar *uct,
+ unsigned long numChars)
}
declare 354 generic {
- char * Tcl_UniCharToUtfDString(CONST Tcl_UniChar *string,
- int numChars, Tcl_DString *dsPtr)
+ char *Tcl_UniCharToUtfDString(CONST Tcl_UniChar *uniStr,
+ int uniLength, Tcl_DString *dsPtr)
}
declare 355 generic {
- Tcl_UniChar * Tcl_UtfToUniCharDString(CONST char *string,
+ Tcl_UniChar *Tcl_UtfToUniCharDString(CONST char *src,
int length, Tcl_DString *dsPtr)
}
declare 356 generic {
Tcl_RegExp Tcl_GetRegExpFromObj(Tcl_Interp *interp, Tcl_Obj *patObj,
int flags)
}
-
declare 357 generic {
Tcl_Obj *Tcl_EvalTokens(Tcl_Interp *interp, Tcl_Token *tokenPtr,
int count)
@@ -1280,24 +1277,24 @@ declare 359 generic {
CONST char *command, int length)
}
declare 360 generic {
- int Tcl_ParseBraces(Tcl_Interp *interp, CONST char *string, int numBytes,
+ int Tcl_ParseBraces(Tcl_Interp *interp, CONST char *start, int numBytes,
Tcl_Parse *parsePtr, int append, CONST84 char **termPtr)
}
declare 361 generic {
- int Tcl_ParseCommand(Tcl_Interp *interp, CONST char *string, int numBytes,
+ int Tcl_ParseCommand(Tcl_Interp *interp, CONST char *start, int numBytes,
int nested, Tcl_Parse *parsePtr)
}
declare 362 generic {
- int Tcl_ParseExpr(Tcl_Interp *interp, CONST char *string, int numBytes,
- Tcl_Parse *parsePtr)
+ int Tcl_ParseExpr(Tcl_Interp *interp, CONST char *start, int numBytes,
+ Tcl_Parse *parsePtr)
}
declare 363 generic {
- int Tcl_ParseQuotedString(Tcl_Interp *interp, CONST char *string,
+ int Tcl_ParseQuotedString(Tcl_Interp *interp, CONST char *start,
int numBytes, Tcl_Parse *parsePtr, int append,
CONST84 char **termPtr)
}
declare 364 generic {
- int Tcl_ParseVarName(Tcl_Interp *interp, CONST char *string, int numBytes,
+ int Tcl_ParseVarName(Tcl_Interp *interp, CONST char *start, int numBytes,
Tcl_Parse *parsePtr, int append)
}
# These 4 functions are obsolete, use Tcl_FSGetCwd, Tcl_FSChdir,
@@ -1337,13 +1334,13 @@ declare 375 generic {
}
declare 376 generic {
int Tcl_RegExpExecObj(Tcl_Interp *interp, Tcl_RegExp regexp,
- Tcl_Obj *objPtr, int offset, int nmatches, int flags)
+ Tcl_Obj *textObj, int offset, int nmatches, int flags)
}
declare 377 generic {
void Tcl_RegExpGetInfo(Tcl_RegExp regexp, Tcl_RegExpInfo *infoPtr)
}
declare 378 generic {
- Tcl_Obj * Tcl_NewUnicodeObj(CONST Tcl_UniChar *unicode, int numChars)
+ Tcl_Obj *Tcl_NewUnicodeObj(CONST Tcl_UniChar *unicode, int numChars)
}
declare 379 generic {
void Tcl_SetUnicodeObj(Tcl_Obj *objPtr, CONST Tcl_UniChar *unicode,
@@ -1356,24 +1353,24 @@ declare 381 generic {
Tcl_UniChar Tcl_GetUniChar(Tcl_Obj *objPtr, int index)
}
declare 382 generic {
- Tcl_UniChar * Tcl_GetUnicode(Tcl_Obj *objPtr)
+ Tcl_UniChar *Tcl_GetUnicode(Tcl_Obj *objPtr)
}
declare 383 generic {
- Tcl_Obj * Tcl_GetRange(Tcl_Obj *objPtr, int first, int last)
+ Tcl_Obj *Tcl_GetRange(Tcl_Obj *objPtr, int first, int last)
}
declare 384 generic {
void Tcl_AppendUnicodeToObj(Tcl_Obj *objPtr, CONST Tcl_UniChar *unicode,
int length)
}
declare 385 generic {
- int Tcl_RegExpMatchObj(Tcl_Interp *interp, Tcl_Obj *stringObj,
+ int Tcl_RegExpMatchObj(Tcl_Interp *interp, Tcl_Obj *textObj,
Tcl_Obj *patternObj)
}
declare 386 generic {
void Tcl_SetNotifier(Tcl_NotifierProcs *notifierProcPtr)
}
declare 387 generic {
- Tcl_Mutex * Tcl_GetAllocMutex(void)
+ Tcl_Mutex *Tcl_GetAllocMutex(void)
}
declare 388 generic {
int Tcl_GetChannelNames(Tcl_Interp *interp)
@@ -1410,62 +1407,70 @@ declare 397 generic {
int Tcl_ChannelBuffered(Tcl_Channel chan)
}
declare 398 generic {
- CONST84_RETURN char * Tcl_ChannelName(Tcl_ChannelType *chanTypePtr)
+ CONST84_RETURN char *Tcl_ChannelName(CONST Tcl_ChannelType *chanTypePtr)
}
declare 399 generic {
- Tcl_ChannelTypeVersion Tcl_ChannelVersion(Tcl_ChannelType *chanTypePtr)
+ Tcl_ChannelTypeVersion Tcl_ChannelVersion(
+ CONST Tcl_ChannelType *chanTypePtr)
}
declare 400 generic {
- Tcl_DriverBlockModeProc * Tcl_ChannelBlockModeProc(Tcl_ChannelType
- *chanTypePtr)
+ Tcl_DriverBlockModeProc *Tcl_ChannelBlockModeProc(
+ CONST Tcl_ChannelType *chanTypePtr)
}
declare 401 generic {
- Tcl_DriverCloseProc * Tcl_ChannelCloseProc(Tcl_ChannelType *chanTypePtr)
+ Tcl_DriverCloseProc *Tcl_ChannelCloseProc(
+ CONST Tcl_ChannelType *chanTypePtr)
}
declare 402 generic {
- Tcl_DriverClose2Proc * Tcl_ChannelClose2Proc(Tcl_ChannelType *chanTypePtr)
+ Tcl_DriverClose2Proc *Tcl_ChannelClose2Proc(
+ CONST Tcl_ChannelType *chanTypePtr)
}
declare 403 generic {
- Tcl_DriverInputProc * Tcl_ChannelInputProc(Tcl_ChannelType *chanTypePtr)
+ Tcl_DriverInputProc *Tcl_ChannelInputProc(
+ CONST Tcl_ChannelType *chanTypePtr)
}
declare 404 generic {
- Tcl_DriverOutputProc * Tcl_ChannelOutputProc(Tcl_ChannelType *chanTypePtr)
+ Tcl_DriverOutputProc *Tcl_ChannelOutputProc(
+ CONST Tcl_ChannelType *chanTypePtr)
}
declare 405 generic {
- Tcl_DriverSeekProc * Tcl_ChannelSeekProc(Tcl_ChannelType *chanTypePtr)
+ Tcl_DriverSeekProc *Tcl_ChannelSeekProc(
+ CONST Tcl_ChannelType *chanTypePtr)
}
declare 406 generic {
- Tcl_DriverSetOptionProc * Tcl_ChannelSetOptionProc(Tcl_ChannelType
- *chanTypePtr)
+ Tcl_DriverSetOptionProc *Tcl_ChannelSetOptionProc(
+ CONST Tcl_ChannelType *chanTypePtr)
}
declare 407 generic {
- Tcl_DriverGetOptionProc * Tcl_ChannelGetOptionProc(Tcl_ChannelType
- *chanTypePtr)
+ Tcl_DriverGetOptionProc *Tcl_ChannelGetOptionProc(
+ CONST Tcl_ChannelType *chanTypePtr)
}
declare 408 generic {
- Tcl_DriverWatchProc * Tcl_ChannelWatchProc(Tcl_ChannelType *chanTypePtr)
+ Tcl_DriverWatchProc *Tcl_ChannelWatchProc(
+ CONST Tcl_ChannelType *chanTypePtr)
}
declare 409 generic {
- Tcl_DriverGetHandleProc * Tcl_ChannelGetHandleProc(Tcl_ChannelType
- *chanTypePtr)
+ Tcl_DriverGetHandleProc *Tcl_ChannelGetHandleProc(
+ CONST Tcl_ChannelType *chanTypePtr)
}
declare 410 generic {
- Tcl_DriverFlushProc * Tcl_ChannelFlushProc(Tcl_ChannelType *chanTypePtr)
+ Tcl_DriverFlushProc *Tcl_ChannelFlushProc(
+ CONST Tcl_ChannelType *chanTypePtr)
}
declare 411 generic {
- Tcl_DriverHandlerProc * Tcl_ChannelHandlerProc(Tcl_ChannelType
- *chanTypePtr)
+ Tcl_DriverHandlerProc *Tcl_ChannelHandlerProc(
+ CONST Tcl_ChannelType *chanTypePtr)
}
# Introduced in 8.4a2
declare 412 generic {
- int Tcl_JoinThread(Tcl_ThreadId threadId, int* result)
+ int Tcl_JoinThread(Tcl_ThreadId threadId, int *result)
}
declare 413 generic {
int Tcl_IsChannelShared(Tcl_Channel channel)
}
declare 414 generic {
- int Tcl_IsChannelRegistered(Tcl_Interp* interp, Tcl_Channel channel)
+ int Tcl_IsChannelRegistered(Tcl_Interp *interp, Tcl_Channel channel)
}
declare 415 generic {
void Tcl_CutChannel(Tcl_Channel channel)
@@ -1477,32 +1482,27 @@ declare 417 generic {
void Tcl_ClearChannelHandlers(Tcl_Channel channel)
}
declare 418 generic {
- int Tcl_IsChannelExisting(CONST char* channelName)
+ int Tcl_IsChannelExisting(CONST char *channelName)
}
-
declare 419 generic {
- int Tcl_UniCharNcasecmp(CONST Tcl_UniChar *cs, CONST Tcl_UniChar *ct,
- unsigned long n)
+ int Tcl_UniCharNcasecmp(CONST Tcl_UniChar *ucs, CONST Tcl_UniChar *uct,
+ unsigned long numChars)
}
declare 420 generic {
- int Tcl_UniCharCaseMatch(CONST Tcl_UniChar *ustr,
- CONST Tcl_UniChar *pattern, int nocase)
+ int Tcl_UniCharCaseMatch(CONST Tcl_UniChar *uniStr,
+ CONST Tcl_UniChar *uniPattern, int nocase)
}
-
declare 421 generic {
Tcl_HashEntry *Tcl_FindHashEntry(Tcl_HashTable *tablePtr, CONST char *key)
}
-
declare 422 generic {
Tcl_HashEntry *Tcl_CreateHashEntry(Tcl_HashTable *tablePtr,
CONST char *key, int *newPtr)
}
-
declare 423 generic {
void Tcl_InitCustomHashTable(Tcl_HashTable *tablePtr, int keyType,
Tcl_HashKeyType *typePtr)
}
-
declare 424 generic {
void Tcl_InitObjHashTable(Tcl_HashTable *tablePtr)
}
@@ -1520,46 +1520,54 @@ declare 427 generic {
int flags, Tcl_CommandTraceProc *proc, ClientData clientData)
}
declare 428 generic {
- char * Tcl_AttemptAlloc(unsigned int size)
+ char *Tcl_AttemptAlloc(unsigned int size)
}
declare 429 generic {
- char * Tcl_AttemptDbCkalloc(unsigned int size, CONST char *file, int line)
+ char *Tcl_AttemptDbCkalloc(unsigned int size, CONST char *file, int line)
}
declare 430 generic {
- char * Tcl_AttemptRealloc(char *ptr, unsigned int size)
+ char *Tcl_AttemptRealloc(char *ptr, unsigned int size)
}
declare 431 generic {
- char * Tcl_AttemptDbCkrealloc(char *ptr, unsigned int size,
+ char *Tcl_AttemptDbCkrealloc(char *ptr, unsigned int size,
CONST char *file, int line)
}
declare 432 generic {
int Tcl_AttemptSetObjLength(Tcl_Obj *objPtr, int length)
}
+
+# TIP#10 (thread-aware channels) akupries
declare 433 generic {
Tcl_ThreadId Tcl_GetChannelThread(Tcl_Channel channel)
}
+
# introduced in 8.4a3
declare 434 generic {
- Tcl_UniChar * Tcl_GetUnicodeFromObj(Tcl_Obj *objPtr, int *lengthPtr)
+ Tcl_UniChar *Tcl_GetUnicodeFromObj(Tcl_Obj *objPtr, int *lengthPtr)
}
+
+# TIP#15 (math function introspection) dkf
declare 435 generic {
int Tcl_GetMathFuncInfo(Tcl_Interp *interp, CONST char *name,
int *numArgsPtr, Tcl_ValueType **argTypesPtr,
Tcl_MathProc **procPtr, ClientData *clientDataPtr)
}
declare 436 generic {
- Tcl_Obj * Tcl_ListMathFuncs(Tcl_Interp *interp, CONST char *pattern)
+ Tcl_Obj *Tcl_ListMathFuncs(Tcl_Interp *interp, CONST char *pattern)
}
+
+# TIP#36 (better access to 'subst') dkf
declare 437 generic {
- Tcl_Obj * Tcl_SubstObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags)
+ Tcl_Obj *Tcl_SubstObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags)
}
+
+# TIP#17 (virtual filesystem layer) vdarley
declare 438 generic {
- int Tcl_DetachChannel(Tcl_Interp* interp, Tcl_Channel channel)
+ int Tcl_DetachChannel(Tcl_Interp *interp, Tcl_Channel channel)
}
declare 439 generic {
int Tcl_IsStandardChannel(Tcl_Channel channel)
}
-# New functions due to TIP#17
declare 440 generic {
int Tcl_FSCopyFile(Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr)
}
@@ -1574,11 +1582,9 @@ declare 443 generic {
int Tcl_FSDeleteFile(Tcl_Obj *pathPtr)
}
declare 444 generic {
- int Tcl_FSLoadFile(Tcl_Interp * interp,
- Tcl_Obj *pathPtr, CONST char * sym1, CONST char * sym2,
- Tcl_PackageInitProc ** proc1Ptr,
- Tcl_PackageInitProc ** proc2Ptr,
- Tcl_LoadHandle * handlePtr,
+ int Tcl_FSLoadFile(Tcl_Interp *interp, Tcl_Obj *pathPtr, CONST char *sym1,
+ CONST char *sym2, Tcl_PackageInitProc **proc1Ptr,
+ Tcl_PackageInitProc **proc2Ptr, Tcl_LoadHandle *handlePtr,
Tcl_FSUnloadFileProc **unloadProcPtr)
}
declare 445 generic {
@@ -1586,7 +1592,7 @@ declare 445 generic {
Tcl_Obj *pathPtr, CONST char *pattern, Tcl_GlobTypeData *types)
}
declare 446 generic {
- Tcl_Obj * Tcl_FSLink(Tcl_Obj *pathPtr, Tcl_Obj *toPtr, int linkAction)
+ Tcl_Obj *Tcl_FSLink(Tcl_Obj *pathPtr, Tcl_Obj *toPtr, int linkAction)
}
declare 447 generic {
int Tcl_FSRemoveDirectory(Tcl_Obj *pathPtr,
@@ -1610,7 +1616,8 @@ declare 452 generic {
int index, Tcl_Obj *pathPtr, Tcl_Obj *objPtr)
}
declare 453 generic {
- CONST char ** Tcl_FSFileAttrStrings(Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef)
+ CONST char **Tcl_FSFileAttrStrings(Tcl_Obj *pathPtr,
+ Tcl_Obj **objPtrRef)
}
declare 454 generic {
int Tcl_FSStat(Tcl_Obj *pathPtr, Tcl_StatBuf *buf)
@@ -1623,7 +1630,7 @@ declare 456 generic {
CONST char *modeString, int permissions)
}
declare 457 generic {
- Tcl_Obj* Tcl_FSGetCwd(Tcl_Interp *interp)
+ Tcl_Obj *Tcl_FSGetCwd(Tcl_Interp *interp)
}
declare 458 generic {
int Tcl_FSChdir(Tcl_Obj *pathPtr)
@@ -1632,46 +1639,46 @@ declare 459 generic {
int Tcl_FSConvertToPathType(Tcl_Interp *interp, Tcl_Obj *pathPtr)
}
declare 460 generic {
- Tcl_Obj* Tcl_FSJoinPath(Tcl_Obj *listObj, int elements)
+ Tcl_Obj *Tcl_FSJoinPath(Tcl_Obj *listObj, int elements)
}
declare 461 generic {
- Tcl_Obj* Tcl_FSSplitPath(Tcl_Obj* pathPtr, int *lenPtr)
+ Tcl_Obj *Tcl_FSSplitPath(Tcl_Obj *pathPtr, int *lenPtr)
}
declare 462 generic {
- int Tcl_FSEqualPaths(Tcl_Obj* firstPtr, Tcl_Obj* secondPtr)
+ int Tcl_FSEqualPaths(Tcl_Obj *firstPtr, Tcl_Obj *secondPtr)
}
declare 463 generic {
- Tcl_Obj* Tcl_FSGetNormalizedPath(Tcl_Interp *interp, Tcl_Obj* pathObjPtr)
+ Tcl_Obj *Tcl_FSGetNormalizedPath(Tcl_Interp *interp, Tcl_Obj *pathPtr)
}
declare 464 generic {
- Tcl_Obj* Tcl_FSJoinToPath(Tcl_Obj *basePtr, int objc,
+ Tcl_Obj *Tcl_FSJoinToPath(Tcl_Obj *pathPtr, int objc,
Tcl_Obj *CONST objv[])
}
declare 465 generic {
- ClientData Tcl_FSGetInternalRep(Tcl_Obj* pathObjPtr,
+ ClientData Tcl_FSGetInternalRep(Tcl_Obj *pathPtr,
Tcl_Filesystem *fsPtr)
}
declare 466 generic {
- Tcl_Obj* Tcl_FSGetTranslatedPath(Tcl_Interp *interp, Tcl_Obj* pathPtr)
+ Tcl_Obj *Tcl_FSGetTranslatedPath(Tcl_Interp *interp, Tcl_Obj *pathPtr)
}
declare 467 generic {
int Tcl_FSEvalFile(Tcl_Interp *interp, Tcl_Obj *fileName)
}
declare 468 generic {
- Tcl_Obj* Tcl_FSNewNativePath(Tcl_Filesystem* fromFilesystem,
+ Tcl_Obj *Tcl_FSNewNativePath(Tcl_Filesystem *fromFilesystem,
ClientData clientData)
}
declare 469 generic {
- CONST char* Tcl_FSGetNativePath(Tcl_Obj* pathObjPtr)
+ CONST char *Tcl_FSGetNativePath(Tcl_Obj *pathPtr)
}
declare 470 generic {
- Tcl_Obj* Tcl_FSFileSystemInfo(Tcl_Obj* pathObjPtr)
+ Tcl_Obj *Tcl_FSFileSystemInfo(Tcl_Obj *pathPtr)
}
declare 471 generic {
- Tcl_Obj* Tcl_FSPathSeparator(Tcl_Obj* pathObjPtr)
+ Tcl_Obj *Tcl_FSPathSeparator(Tcl_Obj *pathPtr)
}
declare 472 generic {
- Tcl_Obj* Tcl_FSListVolumes(void)
+ Tcl_Obj *Tcl_FSListVolumes(void)
}
declare 473 generic {
int Tcl_FSRegister(ClientData clientData, Tcl_Filesystem *fsPtr)
@@ -1683,51 +1690,53 @@ declare 475 generic {
ClientData Tcl_FSData(Tcl_Filesystem *fsPtr)
}
declare 476 generic {
- CONST char* Tcl_FSGetTranslatedStringPath(Tcl_Interp *interp,
- Tcl_Obj* pathPtr)
+ CONST char *Tcl_FSGetTranslatedStringPath(Tcl_Interp *interp,
+ Tcl_Obj *pathPtr)
}
declare 477 generic {
- Tcl_Filesystem* Tcl_FSGetFileSystemForPath(Tcl_Obj* pathObjPtr)
+ Tcl_Filesystem *Tcl_FSGetFileSystemForPath(Tcl_Obj *pathPtr)
}
declare 478 generic {
- Tcl_PathType Tcl_FSGetPathType(Tcl_Obj *pathObjPtr)
+ Tcl_PathType Tcl_FSGetPathType(Tcl_Obj *pathPtr)
}
-# New function due to TIP#49
+
+# TIP#49 (detection of output buffering) akupries
declare 479 generic {
int Tcl_OutputBuffered(Tcl_Channel chan)
}
declare 480 generic {
void Tcl_FSMountsChanged(Tcl_Filesystem *fsPtr)
-}
-# New function due to TIP#56
+}
+
+# TIP#56 (evaluate a parsed script) msofer
declare 481 generic {
int Tcl_EvalTokensStandard(Tcl_Interp *interp, Tcl_Token *tokenPtr,
int count)
}
-# New export due to TIP#73
+# TIP#73 (access to current time) kbk
declare 482 generic {
- void Tcl_GetTime(Tcl_Time* timeBuf)
+ void Tcl_GetTime(Tcl_Time *timeBuf)
}
-# New exports due to TIP#32
-
+# TIP#32 (object-enabled traces) kbk
declare 483 generic {
- Tcl_Trace Tcl_CreateObjTrace(Tcl_Interp* interp, int level, int flags,
- Tcl_CmdObjTraceProc* objProc, ClientData clientData,
- Tcl_CmdObjTraceDeleteProc* delProc)
+ Tcl_Trace Tcl_CreateObjTrace(Tcl_Interp *interp, int level, int flags,
+ Tcl_CmdObjTraceProc *objProc, ClientData clientData,
+ Tcl_CmdObjTraceDeleteProc *delProc)
}
declare 484 generic {
- int Tcl_GetCommandInfoFromToken(Tcl_Command token, Tcl_CmdInfo* infoPtr)
+ int Tcl_GetCommandInfoFromToken(Tcl_Command token, Tcl_CmdInfo *infoPtr)
}
declare 485 generic {
int Tcl_SetCommandInfoFromToken(Tcl_Command token,
- CONST Tcl_CmdInfo* infoPtr)
+ CONST Tcl_CmdInfo *infoPtr)
}
### New functions on 64-bit dev branch ###
+# TIP#72 (64-bit values) dkf
declare 486 generic {
- Tcl_Obj * Tcl_DbNewWideIntObj(Tcl_WideInt wideValue,
+ Tcl_Obj *Tcl_DbNewWideIntObj(Tcl_WideInt wideValue,
CONST char *file, int line)
}
declare 487 generic {
@@ -1735,13 +1744,13 @@ declare 487 generic {
Tcl_WideInt *widePtr)
}
declare 488 generic {
- Tcl_Obj * Tcl_NewWideIntObj(Tcl_WideInt wideValue)
+ Tcl_Obj *Tcl_NewWideIntObj(Tcl_WideInt wideValue)
}
declare 489 generic {
void Tcl_SetWideIntObj(Tcl_Obj *objPtr, Tcl_WideInt wideValue)
}
declare 490 generic {
- Tcl_StatBuf * Tcl_AllocStatBuf(void)
+ Tcl_StatBuf *Tcl_AllocStatBuf(void)
}
declare 491 generic {
Tcl_WideInt Tcl_Seek(Tcl_Channel chan, Tcl_WideInt offset, int mode)
@@ -1750,130 +1759,433 @@ declare 492 generic {
Tcl_WideInt Tcl_Tell(Tcl_Channel chan)
}
-# New export due to TIP#91
+# TIP#91 (back-compat enhancements for channels) dkf
declare 493 generic {
- Tcl_DriverWideSeekProc * Tcl_ChannelWideSeekProc(
- Tcl_ChannelType *chanTypePtr)
-}
-
-# Slots 494 to 553 are taken already by 8.5
-# #111 - Dicts (494 ... 504)
-# #59 - Config (505)
-# #139 - Namespace API (506 ... 517)
-# #137 - source -encoding (518)
-# #121 - ExitProc (519)
-# #121 - Resource Limits (520 ... 534)
-# #226 - S/R Interp State (535 ... 537)
-# #227 - S/G Return Opts (538 ... 539)
-# #235 - Ensemble C API (540 ... 551)
-# #233 - Virtualized Time (552 ... 553)
-
-# TIP#218 (Driver Thread Actions) davygrvy/akupries ChannelType ver 4
-# These slots are used by 8.5 as well.
-declare 554 generic {
- Tcl_DriverThreadActionProc *Tcl_ChannelThreadActionProc(Tcl_ChannelType *chanTypePtr)
+ Tcl_DriverWideSeekProc *Tcl_ChannelWideSeekProc(
+ CONST Tcl_ChannelType *chanTypePtr)
}
-# Slots 555 to 572 are taken already by 8.5
-# TIP #237: Arbitrary-prec Integers (555 ... 559)
-# TIP #208: 'chan' Command (560 ... 561)
-# TIP #219: Channel Reflection (562 ... 565)
-# TIP #237: Add. bignum support (566)
-# TIP #181: 'namespace unknown' Cmd (567 ... 568)
-# TIP #258: Enhanced Encodings API (569 ... 572)
+# ----- BASELINE -- FOR -- 8.4.0 ----- #
-# TIP#268: Extended version numbers and requirements.
-# The slot is present even if TCL_TIP268 is not activated.
+# TIP#111 (dictionaries) dkf
+declare 494 generic {
+ int Tcl_DictObjPut(Tcl_Interp *interp, Tcl_Obj *dictPtr,
+ Tcl_Obj *keyPtr, Tcl_Obj *valuePtr)
+}
+declare 495 generic {
+ int Tcl_DictObjGet(Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr,
+ Tcl_Obj **valuePtrPtr)
+}
+declare 496 generic {
+ int Tcl_DictObjRemove(Tcl_Interp *interp, Tcl_Obj *dictPtr,
+ Tcl_Obj *keyPtr)
+}
+declare 497 generic {
+ int Tcl_DictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr, int *sizePtr)
+}
+declare 498 generic {
+ int Tcl_DictObjFirst(Tcl_Interp *interp, Tcl_Obj *dictPtr,
+ Tcl_DictSearch *searchPtr,
+ Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr)
+}
+declare 499 generic {
+ void Tcl_DictObjNext(Tcl_DictSearch *searchPtr,
+ Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr)
+}
+declare 500 generic {
+ void Tcl_DictObjDone(Tcl_DictSearch *searchPtr)
+}
+declare 501 generic {
+ int Tcl_DictObjPutKeyList(Tcl_Interp *interp, Tcl_Obj *dictPtr,
+ int keyc, Tcl_Obj *CONST *keyv, Tcl_Obj *valuePtr)
+}
+declare 502 generic {
+ int Tcl_DictObjRemoveKeyList(Tcl_Interp *interp, Tcl_Obj *dictPtr,
+ int keyc, Tcl_Obj *CONST *keyv)
+}
+declare 503 generic {
+ Tcl_Obj *Tcl_NewDictObj(void)
+}
+declare 504 generic {
+ Tcl_Obj *Tcl_DbNewDictObj(CONST char *file, int line)
+}
-declare 573 generic {
- int Tcl_PkgRequireProc(Tcl_Interp *interp, CONST char *name,
- int objc, Tcl_Obj *CONST objv[], ClientData *clientDataPtr)
+# TIP#59 (configuration reporting) akupries
+declare 505 generic {
+ void Tcl_RegisterConfig(Tcl_Interp *interp, CONST char *pkgName,
+ Tcl_Config *configuration, CONST char *valEncoding)
}
-##############################################################################
+# TIP #139 (partial exposure of namespace API - transferred from tclInt.decls)
+# dkf, API by Brent Welch?
+declare 506 generic {
+ Tcl_Namespace *Tcl_CreateNamespace(Tcl_Interp *interp, CONST char *name,
+ ClientData clientData, Tcl_NamespaceDeleteProc *deleteProc)
+}
+declare 507 generic {
+ void Tcl_DeleteNamespace(Tcl_Namespace *nsPtr)
+}
+declare 508 generic {
+ int Tcl_AppendExportList(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
+ Tcl_Obj *objPtr)
+}
+declare 509 generic {
+ int Tcl_Export(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
+ CONST char *pattern, int resetListFirst)
+}
+declare 510 generic {
+ int Tcl_Import(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
+ CONST char *pattern, int allowOverwrite)
+}
+declare 511 generic {
+ int Tcl_ForgetImport(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
+ CONST char *pattern)
+}
+declare 512 generic {
+ Tcl_Namespace *Tcl_GetCurrentNamespace(Tcl_Interp *interp)
+}
+declare 513 generic {
+ Tcl_Namespace *Tcl_GetGlobalNamespace(Tcl_Interp *interp)
+}
+declare 514 generic {
+ Tcl_Namespace *Tcl_FindNamespace(Tcl_Interp *interp, CONST char *name,
+ Tcl_Namespace *contextNsPtr, int flags)
+}
+declare 515 generic {
+ Tcl_Command Tcl_FindCommand(Tcl_Interp *interp, CONST char *name,
+ Tcl_Namespace *contextNsPtr, int flags)
+}
+declare 516 generic {
+ Tcl_Command Tcl_GetCommandFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr)
+}
+declare 517 generic {
+ void Tcl_GetCommandFullName(Tcl_Interp *interp, Tcl_Command command,
+ Tcl_Obj *objPtr)
+}
-# Define the platform specific public Tcl interface. These functions are
-# only available on the designated platform.
+# TIP#137 (encoding-aware source command) dgp for Anton Kovalenko
+declare 518 generic {
+ int Tcl_FSEvalFileEx(Tcl_Interp *interp, Tcl_Obj *fileName,
+ CONST char *encodingName)
+}
-interface tclPlat
+# TIP#121 (exit handler) dkf for Joe Mistachkin
+declare 519 generic {
+ Tcl_ExitProc *Tcl_SetExitProc(Tcl_ExitProc *proc)
+}
-######################
-# Windows declarations
+# TIP#143 (resource limits) dkf
+declare 520 generic {
+ void Tcl_LimitAddHandler(Tcl_Interp *interp, int type,
+ Tcl_LimitHandlerProc *handlerProc, ClientData clientData,
+ Tcl_LimitHandlerDeleteProc *deleteProc)
+}
+declare 521 generic {
+ void Tcl_LimitRemoveHandler(Tcl_Interp *interp, int type,
+ Tcl_LimitHandlerProc *handlerProc, ClientData clientData)
+}
+declare 522 generic {
+ int Tcl_LimitReady(Tcl_Interp *interp)
+}
+declare 523 generic {
+ int Tcl_LimitCheck(Tcl_Interp *interp)
+}
+declare 524 generic {
+ int Tcl_LimitExceeded(Tcl_Interp *interp)
+}
+declare 525 generic {
+ void Tcl_LimitSetCommands(Tcl_Interp *interp, int commandLimit)
+}
+declare 526 generic {
+ void Tcl_LimitSetTime(Tcl_Interp *interp, Tcl_Time *timeLimitPtr)
+}
+declare 527 generic {
+ void Tcl_LimitSetGranularity(Tcl_Interp *interp, int type, int granularity)
+}
+declare 528 generic {
+ int Tcl_LimitTypeEnabled(Tcl_Interp *interp, int type)
+}
+declare 529 generic {
+ int Tcl_LimitTypeExceeded(Tcl_Interp *interp, int type)
+}
+declare 530 generic {
+ void Tcl_LimitTypeSet(Tcl_Interp *interp, int type)
+}
+declare 531 generic {
+ void Tcl_LimitTypeReset(Tcl_Interp *interp, int type)
+}
+declare 532 generic {
+ int Tcl_LimitGetCommands(Tcl_Interp *interp)
+}
+declare 533 generic {
+ void Tcl_LimitGetTime(Tcl_Interp *interp, Tcl_Time *timeLimitPtr)
+}
+declare 534 generic {
+ int Tcl_LimitGetGranularity(Tcl_Interp *interp, int type)
+}
-# Added in Tcl 8.1
+# TIP#226 (interpreter result state management) dgp
+declare 535 generic {
+ Tcl_InterpState Tcl_SaveInterpState(Tcl_Interp *interp, int status)
+}
+declare 536 generic {
+ int Tcl_RestoreInterpState(Tcl_Interp *interp, Tcl_InterpState state)
+}
+declare 537 generic {
+ void Tcl_DiscardInterpState(Tcl_InterpState state)
+}
-declare 0 win {
- TCHAR * Tcl_WinUtfToTChar(CONST char *str, int len, Tcl_DString *dsPtr)
+# TIP#227 (return options interface) dgp
+declare 538 generic {
+ int Tcl_SetReturnOptions(Tcl_Interp *interp, Tcl_Obj *options)
}
-declare 1 win {
- char * Tcl_WinTCharToUtf(CONST TCHAR *str, int len, Tcl_DString *dsPtr)
+declare 539 generic {
+ Tcl_Obj *Tcl_GetReturnOptions(Tcl_Interp *interp, int result)
}
-##################
-# Mac declarations
+# TIP#235 (ensembles) dkf
+declare 540 generic {
+ int Tcl_IsEnsemble(Tcl_Command token)
+}
+declare 541 generic {
+ Tcl_Command Tcl_CreateEnsemble(Tcl_Interp *interp, CONST char *name,
+ Tcl_Namespace *namespacePtr, int flags)
+}
+declare 542 generic {
+ Tcl_Command Tcl_FindEnsemble(Tcl_Interp *interp, Tcl_Obj *cmdNameObj,
+ int flags)
+}
+declare 543 generic {
+ int Tcl_SetEnsembleSubcommandList(Tcl_Interp *interp, Tcl_Command token,
+ Tcl_Obj *subcmdList)
+}
+declare 544 generic {
+ int Tcl_SetEnsembleMappingDict(Tcl_Interp *interp, Tcl_Command token,
+ Tcl_Obj *mapDict)
+}
+declare 545 generic {
+ int Tcl_SetEnsembleUnknownHandler(Tcl_Interp *interp, Tcl_Command token,
+ Tcl_Obj *unknownList)
+}
+declare 546 generic {
+ int Tcl_SetEnsembleFlags(Tcl_Interp *interp, Tcl_Command token, int flags)
+}
+declare 547 generic {
+ int Tcl_GetEnsembleSubcommandList(Tcl_Interp *interp, Tcl_Command token,
+ Tcl_Obj **subcmdListPtr)
+}
+declare 548 generic {
+ int Tcl_GetEnsembleMappingDict(Tcl_Interp *interp, Tcl_Command token,
+ Tcl_Obj **mapDictPtr)
+}
+declare 549 generic {
+ int Tcl_GetEnsembleUnknownHandler(Tcl_Interp *interp, Tcl_Command token,
+ Tcl_Obj **unknownListPtr)
+}
+declare 550 generic {
+ int Tcl_GetEnsembleFlags(Tcl_Interp *interp, Tcl_Command token,
+ int *flagsPtr)
+}
+declare 551 generic {
+ int Tcl_GetEnsembleNamespace(Tcl_Interp *interp, Tcl_Command token,
+ Tcl_Namespace **namespacePtrPtr)
+}
-# This is needed by the shells to handle Macintosh events.
-
-declare 0 mac {
- void Tcl_MacSetEventProc(Tcl_MacConvertEventPtr procPtr)
+# TIP#233 (virtualized time) akupries
+declare 552 generic {
+ void Tcl_SetTimeProc(Tcl_GetTimeProc *getProc,
+ Tcl_ScaleTimeProc *scaleProc,
+ ClientData clientData)
+}
+declare 553 generic {
+ void Tcl_QueryTimeProc(Tcl_GetTimeProc **getProc,
+ Tcl_ScaleTimeProc **scaleProc,
+ ClientData *clientData)
}
-# These routines are useful for handling using scripts from resources
-# in the application shell
+# TIP#218 (driver thread actions) davygrvy/akupries ChannelType ver 4
+declare 554 generic {
+ Tcl_DriverThreadActionProc *Tcl_ChannelThreadActionProc(
+ CONST Tcl_ChannelType *chanTypePtr)
+}
-declare 1 mac {
- char * Tcl_MacConvertTextResource(Handle resource)
+# TIP#237 (arbitrary-precision integers) kbk
+declare 555 generic {
+ Tcl_Obj *Tcl_NewBignumObj(mp_int *value)
}
-declare 2 mac {
- int Tcl_MacEvalResource(Tcl_Interp *interp, CONST char *resourceName,
- int resourceNumber, CONST char *fileName)
+declare 556 generic {
+ Tcl_Obj *Tcl_DbNewBignumObj(mp_int *value, CONST char *file, int line)
}
-declare 3 mac {
- Handle Tcl_MacFindResource(Tcl_Interp *interp, long resourceType,
- CONST char *resourceName, int resourceNumber,
- CONST char *resFileRef, int * releaseIt)
+declare 557 generic {
+ void Tcl_SetBignumObj(Tcl_Obj *obj, mp_int *value)
+}
+declare 558 generic {
+ int Tcl_GetBignumFromObj(Tcl_Interp *interp, Tcl_Obj *obj, mp_int *value)
+}
+declare 559 generic {
+ int Tcl_TakeBignumFromObj(Tcl_Interp *interp, Tcl_Obj *obj, mp_int *value)
}
-# These routines support the new OSType object type (i.e. the packed 4
-# character type and creator codes).
+# TIP #208 ('chan' command) jeffh
+declare 560 generic {
+ int Tcl_TruncateChannel(Tcl_Channel chan, Tcl_WideInt length)
+}
+declare 561 generic {
+ Tcl_DriverTruncateProc *Tcl_ChannelTruncateProc(
+ CONST Tcl_ChannelType *chanTypePtr)
+}
-declare 4 mac {
- int Tcl_GetOSTypeFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
- OSType *osTypePtr)
+# TIP#219 (channel reflection api) akupries
+declare 562 generic {
+ void Tcl_SetChannelErrorInterp(Tcl_Interp *interp, Tcl_Obj *msg)
+}
+declare 563 generic {
+ void Tcl_GetChannelErrorInterp(Tcl_Interp *interp, Tcl_Obj **msg)
}
-declare 5 mac {
- void Tcl_SetOSTypeObj(Tcl_Obj *objPtr, OSType osType)
+declare 564 generic {
+ void Tcl_SetChannelError(Tcl_Channel chan, Tcl_Obj *msg)
}
-declare 6 mac {
- Tcl_Obj * Tcl_NewOSTypeObj(OSType osType)
+declare 565 generic {
+ void Tcl_GetChannelError(Tcl_Channel chan, Tcl_Obj **msg)
}
-# These are not in MSL 2.1.2, so we need to export them from the
-# Tcl shared library. They are found in the compat directory.
-
-declare 7 mac {
- int strncasecmp(CONST char *s1, CONST char *s2, size_t n)
+# TIP #237 (additional conversion functions for bignum support) kbk/dgp
+declare 566 generic {
+ int Tcl_InitBignumFromDouble(Tcl_Interp *interp, double initval,
+ mp_int *toInit)
}
-declare 8 mac {
- int strcasecmp(CONST char *s1, CONST char *s2)
+
+# TIP#181 (namespace unknown command) dgp for Neil Madden
+declare 567 generic {
+ Tcl_Obj *Tcl_GetNamespaceUnknownHandler(Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr)
+}
+declare 568 generic {
+ int Tcl_SetNamespaceUnknownHandler(Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr, Tcl_Obj *handlerPtr)
}
-##################
-# Mac OS X declarations
-#
+# TIP#258 (enhanced interface for encodings) dgp
+declare 569 generic {
+ int Tcl_GetEncodingFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ Tcl_Encoding *encodingPtr)
+}
+declare 570 generic {
+ Tcl_Obj *Tcl_GetEncodingSearchPath(void)
+}
+declare 571 generic {
+ int Tcl_SetEncodingSearchPath(Tcl_Obj *searchPath)
+}
+declare 572 generic {
+ CONST char *Tcl_GetEncodingNameFromEnvironment(Tcl_DString *bufPtr)
+}
+
+# TIP#268 (extended version numbers and requirements) akupries
+declare 573 generic {
+ int Tcl_PkgRequireProc(Tcl_Interp *interp, CONST char *name,
+ int objc, Tcl_Obj *CONST objv[], ClientData *clientDataPtr)
+}
+
+# TIP#270 (utility C routines for string formatting) dgp
+declare 574 generic {
+ void Tcl_AppendObjToErrorInfo(Tcl_Interp *interp, Tcl_Obj *objPtr)
+}
+declare 575 generic {
+ void Tcl_AppendLimitedToObj(Tcl_Obj *objPtr, CONST char *bytes, int length,
+ int limit, CONST char *ellipsis)
+}
+declare 576 generic {
+ Tcl_Obj *Tcl_Format(Tcl_Interp *interp, CONST char *format, int objc,
+ Tcl_Obj *CONST objv[])
+}
+declare 577 generic {
+ int Tcl_AppendFormatToObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ CONST char *format, int objc, Tcl_Obj *CONST objv[])
+}
+declare 578 generic {
+ Tcl_Obj *Tcl_ObjPrintf(CONST char *format, ...)
+}
+declare 579 generic {
+ void Tcl_AppendPrintfToObj(Tcl_Obj *objPtr, CONST char *format, ...)
+}
+
+##############################################################################
+
+# Define the platform specific public Tcl interface. These functions are only
+# available on the designated platform.
+
+interface tclPlat
+
+################################
+# Unix specific functions
+# (none)
+
+################################
+# Windows specific functions
+
+# Added in Tcl 8.1
+
+declare 0 win {
+ TCHAR *Tcl_WinUtfToTChar(CONST char *str, int len, Tcl_DString *dsPtr)
+}
+declare 1 win {
+ char *Tcl_WinTCharToUtf(CONST TCHAR *str, int len, Tcl_DString *dsPtr)
+}
+
+################################
+# Mac OS X specific functions
declare 0 macosx {
int Tcl_MacOSXOpenBundleResources(Tcl_Interp *interp,
- CONST char *bundleName,
- int hasResourceFile,
- int maxPathLen,
- char *libraryPath)
+ CONST char *bundleName, int hasResourceFile,
+ int maxPathLen, char *libraryPath)
}
declare 1 macosx {
int Tcl_MacOSXOpenVersionedBundleResources(Tcl_Interp *interp,
- CONST char *bundleName,
- CONST char *bundleVersion,
- int hasResourceFile,
- int maxPathLen,
- char *libraryPath)
+ CONST char *bundleName, CONST char *bundleVersion,
+ int hasResourceFile, int maxPathLen, char *libraryPath)
+}
+
+##############################################################################
+
+# Public functions that are not accessible via the stubs table.
+
+export {
+ void Tcl_Main(int argc, char **argv, Tcl_AppInitProc *appInitProc)
+}
+export {
+ CONST char *Tcl_InitStubs(Tcl_Interp *interp, CONST char *version,
+ int exact)
+}
+export {
+ CONST char *TclTomMathInitializeStubs(Tcl_Interp* interp,
+ CONST char* version, int epoch, int revision)
+}
+export {
+ CONST char *Tcl_PkgInitStubsCheck(Tcl_Interp *interp, CONST char *version,
+ int exact)
+}
+export {
+ void Tcl_GetMemoryInfo(Tcl_DString *dsPtr)
+}
+
+# Global variables that need to be exported from the tcl shared library.
+
+export {
+ TclStubs *tclStubsPtr (fool checkstubs)
+}
+export {
+ TclPlatStubs *tclPlatStubsPtr (fool checkstubs)
+}
+export {
+ TclIntStubs *tclIntStubsPtr (fool checkstubs)
+}
+export {
+ TclIntPlatStubs *tclIntPlatStubsPtr (fool checkstubs)
+}
+export {
+ TclTomMathStubs* tclTomMathStubsPtr (fool checkstubs)
}
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/generic/tcl.h b/generic/tcl.h
index bd720ff..88b68db 100644
--- a/generic/tcl.h
+++ b/generic/tcl.h
@@ -1,8 +1,8 @@
/*
* tcl.h --
*
- * This header file describes the externally-visible facilities
- * of the Tcl interpreter.
+ * This header file describes the externally-visible facilities of the
+ * Tcl interpreter.
*
* Copyright (c) 1987-1994 The Regents of the University of California.
* Copyright (c) 1993-1996 Lucent Technologies.
@@ -10,8 +10,8 @@
* Copyright (c) 1998-2000 by Scriptics Corporation.
* Copyright (c) 2002 by Kevin B. Kenny. All rights reserved.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#ifndef _TCL
@@ -34,37 +34,38 @@ extern "C" {
#define TCL_FINAL_RELEASE 2
/*
- * When version numbers change here, must also go into the following files
- * and update the version numbers:
+ * When version numbers change here, must also go into the following files and
+ * update the version numbers:
*
- * library/init.tcl (only if Major.minor changes, not patchlevel) 1 LOC
+ * library/init.tcl (1 LOC patch)
* unix/configure.in (2 LOC Major, 2 LOC minor, 1 LOC patch)
* win/configure.in (as above)
* win/tcl.m4 (not patchlevel)
- * win/makefile.vc (not patchlevel) 2 LOC
- * README (sections 0 and 2)
- * mac/README (2 LOC, not patchlevel)
+ * win/makefile.bc (not patchlevel) 2 LOC
+ * README (sections 0 and 2, with and without separator)
* macosx/Tcl.pbproj/project.pbxproj (not patchlevel) 1 LOC
* macosx/Tcl.pbproj/default.pbxuser (not patchlevel) 1 LOC
- * win/README.binary (sections 0-4)
+ * macosx/Tcl.xcode/project.pbxproj (not patchlevel) 2 LOC
+ * macosx/Tcl.xcode/default.pbxuser (not patchlevel) 1 LOC
+ * macosx/Tcl-Common.xcconfig (not patchlevel) 1 LOC
* win/README (not patchlevel) (sections 0 and 2)
- * unix/tcl.spec (2 LOC Major/Minor, 1 LOC patch)
- * tests/basic.test (1 LOC M/M, not patchlevel)
+ * unix/tcl.spec (1 LOC patch)
* tools/tcl.hpj.in (not patchlevel, for windows installer)
* tools/tcl.wse.in (for windows installer)
* tools/tclSplash.bmp (not patchlevel)
*/
+
#define TCL_MAJOR_VERSION 8
-#define TCL_MINOR_VERSION 4
+#define TCL_MINOR_VERSION 5
#define TCL_RELEASE_LEVEL TCL_FINAL_RELEASE
-#define TCL_RELEASE_SERIAL 19
+#define TCL_RELEASE_SERIAL 10
-#define TCL_VERSION "8.4"
-#define TCL_PATCH_LEVEL "8.4.19"
+#define TCL_VERSION "8.5"
+#define TCL_PATCH_LEVEL "8.5.10"
/*
- * The following definitions set up the proper options for Windows
- * compilers. We use this method because there is no autoconf equivalent.
+ * The following definitions set up the proper options for Windows compilers.
+ * We use this method because there is no autoconf equivalent.
*/
#ifndef __WIN32__
@@ -82,6 +83,7 @@ extern "C" {
/*
* STRICT: See MSDN Article Q83456
*/
+
#ifdef __WIN32__
# ifndef STRICT
# define STRICT
@@ -89,26 +91,10 @@ extern "C" {
#endif /* __WIN32__ */
/*
- * The following definitions set up the proper options for Macintosh
- * compilers. We use this method because there is no autoconf equivalent.
- */
-
-#ifdef MAC_TCL
-#include <ConditionalMacros.h>
-# ifndef USE_TCLALLOC
-# define USE_TCLALLOC 1
-# endif
-# ifndef NO_STRERROR
-# define NO_STRERROR 1
-# endif
-# define INLINE
-#endif
-
-
-/*
* Utility macros: STRINGIFY takes an argument and wraps it in "" (double
* quotation marks), JOIN joins two arguments.
*/
+
#ifndef STRINGIFY
# define STRINGIFY(x) STRINGIFY1(x)
# define STRINGIFY1(x) #x
@@ -118,21 +104,20 @@ extern "C" {
# define JOIN1(a,b) a##b
#endif
-/*
- * A special definition used to allow this header file to be included
- * from windows or mac resource files so that they can obtain version
- * information. RC_INVOKED is defined by default by the windows RC tool
- * and manually set for macintosh.
+/*
+ * A special definition used to allow this header file to be included from
+ * windows resource files so that they can obtain version information.
+ * RC_INVOKED is defined by default by the windows RC tool.
*
- * Resource compilers don't like all the C stuff, like typedefs and
- * procedure declarations, that occur below, so block them out.
+ * Resource compilers don't like all the C stuff, like typedefs and function
+ * declarations, that occur below, so block them out.
*/
#ifndef RC_INVOKED
/*
- * Special macro to define mutexes, that doesn't do anything
- * if we are not using threads.
+ * Special macro to define mutexes, that doesn't do anything if we are not
+ * using threads.
*/
#ifdef TCL_THREADS
@@ -142,62 +127,61 @@ extern "C" {
#endif
/*
- * Macros that eliminate the overhead of the thread synchronization
- * functions when compiling without thread support.
+ * Tcl's public routine Tcl_FSSeek() uses the values SEEK_SET, SEEK_CUR, and
+ * SEEK_END, all #define'd by stdio.h .
+ *
+ * Also, many extensions need stdio.h, and they've grown accustomed to tcl.h
+ * providing it for them rather than #include-ing it themselves as they
+ * should, so also for their sake, we keep the #include to be consistent with
+ * prior Tcl releases.
*/
-#ifndef TCL_THREADS
-#define Tcl_MutexLock(mutexPtr)
-#define Tcl_MutexUnlock(mutexPtr)
-#define Tcl_MutexFinalize(mutexPtr)
-#define Tcl_ConditionNotify(condPtr)
-#define Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
-#define Tcl_ConditionFinalize(condPtr)
-#endif /* TCL_THREADS */
-
-
-#ifndef BUFSIZ
-# include <stdio.h>
-#endif
-
+#include <stdio.h>
/*
- * Definitions that allow Tcl functions with variable numbers of
- * arguments to be used with either varargs.h or stdarg.h. TCL_VARARGS
- * is used in procedure prototypes. TCL_VARARGS_DEF is used to declare
- * the arguments in a function definiton: it takes the type and name of
- * the first argument and supplies the appropriate argument declaration
- * string for use in the function definition. TCL_VARARGS_START
- * initializes the va_list data structure and returns the first argument.
+ * Support for functions with a variable number of arguments.
+ *
+ * The following TCL_VARARGS* macros are to support old extensions
+ * written for older versions of Tcl where the macros permitted
+ * support for the varargs.h system as well as stdarg.h .
+ *
+ * New code should just directly be written to use stdarg.h conventions.
*/
-#if !defined(NO_STDARG)
-# include <stdarg.h>
-# define TCL_VARARGS(type, name) (type name, ...)
-# define TCL_VARARGS_DEF(type, name) (type name, ...)
-# define TCL_VARARGS_START(type, name, list) (va_start(list, name), name)
-#else
-# include <varargs.h>
-# define TCL_VARARGS(type, name) ()
-# define TCL_VARARGS_DEF(type, name) (va_alist)
-# define TCL_VARARGS_START(type, name, list) \
- (va_start(list), va_arg(list, type))
+
+#include <stdarg.h>
+#ifndef TCL_NO_DEPRECATED
+# define TCL_VARARGS(type, name) (type name, ...)
+# define TCL_VARARGS_DEF(type, name) (type name, ...)
+# define TCL_VARARGS_START(type, name, list) (va_start(list, name), name)
#endif
/*
- * Macros used to declare a function to be exported by a DLL.
- * Used by Windows, maps to no-op declarations on non-Windows systems.
- * The default build on windows is for a DLL, which causes the DLLIMPORT
- * and DLLEXPORT macros to be nonempty. To build a static library, the
- * macro STATIC_BUILD should be defined.
+ * Macros used to declare a function to be exported by a DLL. Used by Windows,
+ * maps to no-op declarations on non-Windows systems. The default build on
+ * windows is for a DLL, which causes the DLLIMPORT and DLLEXPORT macros to be
+ * nonempty. To build a static library, the macro STATIC_BUILD should be
+ * defined.
+ *
+ * Note: when building static but linking dynamically to MSVCRT we must still
+ * correctly decorate the C library imported function. Use CRTIMPORT
+ * for this purpose. _DLL is defined by the compiler when linking to
+ * MSVCRT.
*/
#if (defined(__WIN32__) && (defined(_MSC_VER) || (__BORLANDC__ >= 0x0550) || defined(__LCC__) || defined(__WATCOMC__) || (defined(__GNUC__) && defined(__declspec))))
+# define HAVE_DECLSPEC 1
# ifdef STATIC_BUILD
# define DLLIMPORT
# define DLLEXPORT
+# ifdef _DLL
+# define CRTIMPORT __declspec(dllimport)
+# else
+# define CRTIMPORT
+# endif
# else
# define DLLIMPORT __declspec(dllimport)
# define DLLEXPORT __declspec(dllexport)
+# define CRTIMPORT __declspec(dllimport)
# endif
#else
# define DLLIMPORT
@@ -206,23 +190,25 @@ extern "C" {
# else
# define DLLEXPORT
# endif
+# define CRTIMPORT
#endif
/*
* These macros are used to control whether functions are being declared for
- * import or export. If a function is being declared while it is being built
+ * import or export. If a function is being declared while it is being built
* to be included in a shared library, then it should have the DLLEXPORT
- * storage class. If is being declared for use by a module that is going to
+ * storage class. If is being declared for use by a module that is going to
* link against the shared library, then it should have the DLLIMPORT storage
- * class. If the symbol is beind declared for a static build or for use from a
+ * class. If the symbol is beind declared for a static build or for use from a
* stub library, then the storage class should be empty.
*
- * The convention is that a macro called BUILD_xxxx, where xxxx is the
- * name of a library we are building, is set on the compile line for sources
- * that are to be placed in the library. When this macro is set, the
- * storage class will be set to DLLEXPORT. At the end of the header file, the
- * storage class will be reset to DLLIMPORT.
+ * The convention is that a macro called BUILD_xxxx, where xxxx is the name of
+ * a library we are building, is set on the compile line for sources that are
+ * to be placed in the library. When this macro is set, the storage class will
+ * be set to DLLEXPORT. At the end of the header file, the storage class will
+ * be reset to DLLIMPORT.
*/
+
#undef TCL_STORAGE_CLASS
#ifdef BUILD_tcl
# define TCL_STORAGE_CLASS DLLEXPORT
@@ -234,11 +220,11 @@ extern "C" {
# endif
#endif
-
/*
- * Definitions that allow this header file to be used either with or
- * without ANSI C features like function prototypes.
+ * Definitions that allow this header file to be used either with or without
+ * ANSI C features like function prototypes.
*/
+
#undef _ANSI_ARGS_
#undef CONST
#ifndef INLINE
@@ -265,7 +251,7 @@ extern "C" {
# define CONST84_RETURN
#else
# ifdef USE_COMPAT_CONST
-# define CONST84
+# define CONST84
# define CONST84_RETURN CONST
# else
# define CONST84 CONST
@@ -273,10 +259,10 @@ extern "C" {
# endif
#endif
-
/*
- * Make sure EXTERN isn't defined elsewhere
+ * Make sure EXTERN isn't defined elsewhere.
*/
+
#ifdef EXTERN
# undef EXTERN
#endif /* EXTERN */
@@ -287,15 +273,12 @@ extern "C" {
# define EXTERN extern TCL_STORAGE_CLASS
#endif
-
/*
- * The following code is copied from winnt.h.
- * If we don't replicate it here, then <windows.h> can't be included
- * after tcl.h, since tcl.h also defines VOID.
- * This block is skipped under Cygwin and Mingw.
- *
- *
+ * The following code is copied from winnt.h. If we don't replicate it here,
+ * then <windows.h> can't be included after tcl.h, since tcl.h also defines
+ * VOID. This block is skipped under Cygwin and Mingw.
*/
+
#if defined(__WIN32__) && !defined(HAVE_WINNT_IGNORE_VOID)
#ifndef VOID
#define VOID void
@@ -306,15 +289,14 @@ typedef long LONG;
#endif /* __WIN32__ && !HAVE_WINNT_IGNORE_VOID */
/*
- * Macro to use instead of "void" for arguments that must have
- * type "void *" in ANSI C; maps them to type "char *" in
- * non-ANSI systems.
+ * Macro to use instead of "void" for arguments that must have type "void *"
+ * in ANSI C; maps them to type "char *" in non-ANSI systems.
*/
#ifndef NO_VOID
-# define VOID void
+#define VOID void
#else
-# define VOID char
+#define VOID char
#endif
/*
@@ -339,22 +321,23 @@ typedef long LONG;
# ifdef __LP64__
# undef TCL_WIDE_INT_TYPE
# define TCL_WIDE_INT_IS_LONG 1
+# define TCL_CFG_DO64BIT 1
# else /* !__LP64__ */
# define TCL_WIDE_INT_TYPE long long
# undef TCL_WIDE_INT_IS_LONG
+# undef TCL_CFG_DO64BIT
# endif /* __LP64__ */
# undef HAVE_STRUCT_STAT64
-# include <mach/mach.h>
#endif /* __APPLE__ */
/*
- * Define Tcl_WideInt to be a type that is (at least) 64-bits wide,
- * and define Tcl_WideUInt to be the unsigned variant of that type
- * (assuming that where we have one, we can have the other.)
+ * Define Tcl_WideInt to be a type that is (at least) 64-bits wide, and define
+ * Tcl_WideUInt to be the unsigned variant of that type (assuming that where
+ * we have one, we can have the other.)
*
* Also defines the following macros:
- * TCL_WIDE_INT_IS_LONG - if wide ints are really longs (i.e. we're on
- * a real 64-bit system.)
+ * TCL_WIDE_INT_IS_LONG - if wide ints are really longs (i.e. we're on a real
+ * 64-bit system.)
* Tcl_WideAsLong - forgetful converter from wideInt to long.
* Tcl_LongAsWide - sign-extending converter from long to wideInt.
* Tcl_WideAsDouble - converter from wideInt to double.
@@ -363,12 +346,9 @@ typedef long LONG;
* The following invariant should hold for any long value 'longVal':
* longVal == Tcl_WideAsLong(Tcl_LongAsWide(longVal))
*
- * Note on converting between Tcl_WideInt and strings. This
- * implementation (in tclObj.c) depends on the functions strtoull()
- * and sprintf(...,"%" TCL_LL_MODIFIER "d",...). TCL_LL_MODIFIER_SIZE
- * is the length of the modifier string, which is "ll" on most 32-bit
- * Unix systems. It has to be split up like this to allow for the more
- * complex formats sometimes needed (e.g. in the format(n) command.)
+ * Note on converting between Tcl_WideInt and strings. This implementation (in
+ * tclObj.c) depends on the function
+ * sprintf(...,"%" TCL_LL_MODIFIER "d",...).
*/
#if !defined(TCL_WIDE_INT_TYPE)&&!defined(TCL_WIDE_INT_IS_LONG)
@@ -377,7 +357,6 @@ typedef long LONG;
# ifdef __BORLANDC__
typedef struct stati64 Tcl_StatBuf;
# define TCL_LL_MODIFIER "L"
-# define TCL_LL_MODIFIER_SIZE 1
# else /* __BORLANDC__ */
# if defined(_WIN64)
typedef struct __stat64 Tcl_StatBuf;
@@ -387,12 +366,10 @@ typedef struct _stati64 Tcl_StatBuf;
typedef struct _stat32i64 Tcl_StatBuf;
# endif /* _MSC_VER < 1400 */
# define TCL_LL_MODIFIER "I64"
-# define TCL_LL_MODIFIER_SIZE 3
# endif /* __BORLANDC__ */
# elif defined(__GNUC__)
# define TCL_WIDE_INT_TYPE long long
# define TCL_LL_MODIFIER "ll"
-# define TCL_LL_MODIFIER_SIZE 2
# if defined(__WIN32__)
typedef struct _stat32i64 Tcl_StatBuf;
# else
@@ -400,8 +377,8 @@ typedef struct stat Tcl_StatBuf;
# endif
# else /* ! __WIN32__ && ! __GNUC__ */
/*
- * Don't know what platform it is and configure hasn't discovered what
- * is going on for us. Try to guess...
+ * Don't know what platform it is and configure hasn't discovered what is
+ * going on for us. Try to guess...
*/
# ifdef NO_LIMITS_H
# error please define either TCL_WIDE_INT_TYPE or TCL_WIDE_INT_IS_LONG
@@ -431,12 +408,11 @@ typedef struct stat Tcl_StatBuf;
# define Tcl_DoubleAsWide(val) ((long)((double)(val)))
# ifndef TCL_LL_MODIFIER
# define TCL_LL_MODIFIER "l"
-# define TCL_LL_MODIFIER_SIZE 1
# endif /* !TCL_LL_MODIFIER */
#else /* TCL_WIDE_INT_IS_LONG */
/*
- * The next short section of defines are only done when not running on
- * Windows or some other strange platform.
+ * The next short section of defines are only done when not running on Windows
+ * or some other strange platform.
*/
# ifndef TCL_LL_MODIFIER
# ifdef HAVE_STRUCT_STAT64
@@ -445,40 +421,28 @@ typedef struct stat64 Tcl_StatBuf;
typedef struct stat Tcl_StatBuf;
# endif /* HAVE_STRUCT_STAT64 */
# define TCL_LL_MODIFIER "ll"
-# define TCL_LL_MODIFIER_SIZE 2
# endif /* !TCL_LL_MODIFIER */
# define Tcl_WideAsLong(val) ((long)((Tcl_WideInt)(val)))
# define Tcl_LongAsWide(val) ((Tcl_WideInt)((long)(val)))
# define Tcl_WideAsDouble(val) ((double)((Tcl_WideInt)(val)))
# define Tcl_DoubleAsWide(val) ((Tcl_WideInt)((double)(val)))
#endif /* TCL_WIDE_INT_IS_LONG */
-
-
-/*
- * This flag controls whether binary compatability is maintained with
- * extensions built against a previous version of Tcl. This is true
- * by default.
- */
-#ifndef TCL_PRESERVE_BINARY_COMPATABILITY
-# define TCL_PRESERVE_BINARY_COMPATABILITY 1
-#endif
-
/*
- * Data structures defined opaquely in this module. The definitions below
- * just provide dummy types. A few fields are made visible in Tcl_Interp
- * structures, namely those used for returning a string result from
- * commands. Direct access to the result field is discouraged in Tcl 8.0.
- * The interpreter result is either an object or a string, and the two
- * values are kept consistent unless some C code sets interp->result
- * directly. Programmers should use either the procedure Tcl_GetObjResult()
- * or Tcl_GetStringResult() to read the interpreter's result. See the
- * SetResult man page for details.
- *
- * Note: any change to the Tcl_Interp definition below must be mirrored
- * in the "real" definition in tclInt.h.
+ * Data structures defined opaquely in this module. The definitions below just
+ * provide dummy types. A few fields are made visible in Tcl_Interp
+ * structures, namely those used for returning a string result from commands.
+ * Direct access to the result field is discouraged in Tcl 8.0. The
+ * interpreter result is either an object or a string, and the two values are
+ * kept consistent unless some C code sets interp->result directly.
+ * Programmers should use either the function Tcl_GetObjResult() or
+ * Tcl_GetStringResult() to read the interpreter's result. See the SetResult
+ * man page for details.
*
- * Note: Tcl_ObjCmdProc procedures do not directly set result and freeProc.
+ * Note: any change to the Tcl_Interp definition below must be mirrored in the
+ * "real" definition in tclInt.h.
+ *
+ * Note: Tcl_ObjCmdProc functions do not directly set result and freeProc.
* Instead, they set a Tcl_Obj member in the "real" structure that can be
* accessed with Tcl_GetObjResult() and Tcl_SetObjResult().
*/
@@ -487,25 +451,29 @@ typedef struct Tcl_Interp {
char *result; /* If the last command returned a string
* result, this points to it. */
void (*freeProc) _ANSI_ARGS_((char *blockPtr));
- /* Zero means the string result is
- * statically allocated. TCL_DYNAMIC means
- * it was allocated with ckalloc and should
- * be freed with ckfree. Other values give
- * the address of procedure to invoke to
- * free the result. Tcl_Eval must free it
- * before executing next command. */
- int errorLine; /* When TCL_ERROR is returned, this gives
- * the line number within the command where
- * the error occurred (1 if first line). */
+ /* Zero means the string result is statically
+ * allocated. TCL_DYNAMIC means it was
+ * allocated with ckalloc and should be freed
+ * with ckfree. Other values give the address
+ * of function to invoke to free the result.
+ * Tcl_Eval must free it before executing next
+ * command. */
+ int errorLine; /* When TCL_ERROR is returned, this gives the
+ * line number within the command where the
+ * error occurred (1 if first line). */
} Tcl_Interp;
typedef struct Tcl_AsyncHandler_ *Tcl_AsyncHandler;
typedef struct Tcl_Channel_ *Tcl_Channel;
+typedef struct Tcl_ChannelTypeVersion_ *Tcl_ChannelTypeVersion;
typedef struct Tcl_Command_ *Tcl_Command;
typedef struct Tcl_Condition_ *Tcl_Condition;
+typedef struct Tcl_Dict_ *Tcl_Dict;
typedef struct Tcl_EncodingState_ *Tcl_EncodingState;
typedef struct Tcl_Encoding_ *Tcl_Encoding;
typedef struct Tcl_Event Tcl_Event;
+typedef struct Tcl_InterpState_ *Tcl_InterpState;
+typedef struct Tcl_LoadHandle_ *Tcl_LoadHandle;
typedef struct Tcl_Mutex_ *Tcl_Mutex;
typedef struct Tcl_Pid_ *Tcl_Pid;
typedef struct Tcl_RegExp_ *Tcl_RegExp;
@@ -514,155 +482,153 @@ typedef struct Tcl_ThreadId_ *Tcl_ThreadId;
typedef struct Tcl_TimerToken_ *Tcl_TimerToken;
typedef struct Tcl_Trace_ *Tcl_Trace;
typedef struct Tcl_Var_ *Tcl_Var;
-typedef struct Tcl_ChannelTypeVersion_ *Tcl_ChannelTypeVersion;
-typedef struct Tcl_LoadHandle_ *Tcl_LoadHandle;
/*
- * Definition of the interface to procedures implementing threads.
- * A procedure following this definition is given to each call of
- * 'Tcl_CreateThread' and will be called as the main fuction of
- * the new thread created by that call.
+ * Definition of the interface to functions implementing threads. A function
+ * following this definition is given to each call of 'Tcl_CreateThread' and
+ * will be called as the main fuction of the new thread created by that call.
*/
-#ifdef MAC_TCL
-typedef pascal void *(Tcl_ThreadCreateProc) _ANSI_ARGS_((ClientData clientData));
-#elif defined __WIN32__
+
+#if defined __WIN32__
typedef unsigned (__stdcall Tcl_ThreadCreateProc) _ANSI_ARGS_((ClientData clientData));
#else
typedef void (Tcl_ThreadCreateProc) _ANSI_ARGS_((ClientData clientData));
#endif
-
/*
* Threading function return types used for abstracting away platform
- * differences when writing a Tcl_ThreadCreateProc. See the NewThread
- * function in generic/tclThreadTest.c for it's usage.
+ * differences when writing a Tcl_ThreadCreateProc. See the NewThread function
+ * in generic/tclThreadTest.c for it's usage.
*/
-#ifdef MAC_TCL
-# define Tcl_ThreadCreateType pascal void *
-# define TCL_THREAD_CREATE_RETURN return NULL
-#elif defined __WIN32__
+
+#if defined __WIN32__
# define Tcl_ThreadCreateType unsigned __stdcall
# define TCL_THREAD_CREATE_RETURN return 0
#else
# define Tcl_ThreadCreateType void
-# define TCL_THREAD_CREATE_RETURN
+# define TCL_THREAD_CREATE_RETURN
#endif
-
/*
* Definition of values for default stacksize and the possible flags to be
* given to Tcl_CreateThread.
*/
-#define TCL_THREAD_STACK_DEFAULT (0) /* Use default size for stack */
-#define TCL_THREAD_NOFLAGS (0000) /* Standard flags, default behaviour */
-#define TCL_THREAD_JOINABLE (0001) /* Mark the thread as joinable */
+
+#define TCL_THREAD_STACK_DEFAULT (0) /* Use default size for stack. */
+#define TCL_THREAD_NOFLAGS (0000) /* Standard flags, default
+ * behaviour. */
+#define TCL_THREAD_JOINABLE (0001) /* Mark the thread as joinable. */
/*
- * Flag values passed to Tcl_GetRegExpFromObj.
+ * Flag values passed to Tcl_StringCaseMatch.
*/
-#define TCL_REG_BASIC 000000 /* BREs (convenience) */
-#define TCL_REG_EXTENDED 000001 /* EREs */
-#define TCL_REG_ADVF 000002 /* advanced features in EREs */
-#define TCL_REG_ADVANCED 000003 /* AREs (which are also EREs) */
-#define TCL_REG_QUOTE 000004 /* no special characters, none */
-#define TCL_REG_NOCASE 000010 /* ignore case */
-#define TCL_REG_NOSUB 000020 /* don't care about subexpressions */
-#define TCL_REG_EXPANDED 000040 /* expanded format, white space &
- * comments */
-#define TCL_REG_NLSTOP 000100 /* \n doesn't match . or [^ ] */
-#define TCL_REG_NLANCH 000200 /* ^ matches after \n, $ before */
-#define TCL_REG_NEWLINE 000300 /* newlines are line terminators */
-#define TCL_REG_CANMATCH 001000 /* report details on partial/limited
- * matches */
+
+#define TCL_MATCH_NOCASE (1<<0)
/*
- * The following flag is experimental and only intended for use by Expect. It
- * will probably go away in a later release.
+ * Flag values passed to Tcl_GetRegExpFromObj.
*/
-#define TCL_REG_BOSONLY 002000 /* prepend \A to pattern so it only
- * matches at the beginning of the
- * string. */
+
+#define TCL_REG_BASIC 000000 /* BREs (convenience). */
+#define TCL_REG_EXTENDED 000001 /* EREs. */
+#define TCL_REG_ADVF 000002 /* Advanced features in EREs. */
+#define TCL_REG_ADVANCED 000003 /* AREs (which are also EREs). */
+#define TCL_REG_QUOTE 000004 /* No special characters, none. */
+#define TCL_REG_NOCASE 000010 /* Ignore case. */
+#define TCL_REG_NOSUB 000020 /* Don't care about subexpressions. */
+#define TCL_REG_EXPANDED 000040 /* Expanded format, white space &
+ * comments. */
+#define TCL_REG_NLSTOP 000100 /* \n doesn't match . or [^ ] */
+#define TCL_REG_NLANCH 000200 /* ^ matches after \n, $ before. */
+#define TCL_REG_NEWLINE 000300 /* Newlines are line terminators. */
+#define TCL_REG_CANMATCH 001000 /* Report details on partial/limited
+ * matches. */
/*
* Flags values passed to Tcl_RegExpExecObj.
*/
+
#define TCL_REG_NOTBOL 0001 /* Beginning of string does not match ^. */
#define TCL_REG_NOTEOL 0002 /* End of string does not match $. */
/*
- * Structures filled in by Tcl_RegExpInfo. Note that all offset values are
- * relative to the start of the match string, not the beginning of the
- * entire string.
+ * Structures filled in by Tcl_RegExpInfo. Note that all offset values are
+ * relative to the start of the match string, not the beginning of the entire
+ * string.
*/
+
typedef struct Tcl_RegExpIndices {
- long start; /* character offset of first character in match */
- long end; /* character offset of first character after the
- * match. */
+ long start; /* Character offset of first character in
+ * match. */
+ long end; /* Character offset of first character after
+ * the match. */
} Tcl_RegExpIndices;
typedef struct Tcl_RegExpInfo {
- int nsubs; /* number of subexpressions in the
- * compiled expression */
- Tcl_RegExpIndices *matches; /* array of nsubs match offset
- * pairs */
- long extendStart; /* The offset at which a subsequent
- * match might begin. */
+ int nsubs; /* Number of subexpressions in the compiled
+ * expression. */
+ Tcl_RegExpIndices *matches; /* Array of nsubs match offset pairs. */
+ long extendStart; /* The offset at which a subsequent match
+ * might begin. */
long reserved; /* Reserved for later use. */
} Tcl_RegExpInfo;
/*
- * Picky compilers complain if this typdef doesn't appear before the
- * struct's reference in tclDecls.h.
+ * Picky compilers complain if this typdef doesn't appear before the struct's
+ * reference in tclDecls.h.
*/
+
typedef Tcl_StatBuf *Tcl_Stat_;
typedef struct stat *Tcl_OldStat_;
/*
* When a TCL command returns, the interpreter contains a result from the
- * command. Programmers are strongly encouraged to use one of the
- * procedures Tcl_GetObjResult() or Tcl_GetStringResult() to read the
- * interpreter's result. See the SetResult man page for details. Besides
- * this result, the command procedure returns an integer code, which is
- * one of the following:
+ * command. Programmers are strongly encouraged to use one of the functions
+ * Tcl_GetObjResult() or Tcl_GetStringResult() to read the interpreter's
+ * result. See the SetResult man page for details. Besides this result, the
+ * command function returns an integer code, which is one of the following:
*
- * TCL_OK Command completed normally; the interpreter's
- * result contains the command's result.
- * TCL_ERROR The command couldn't be completed successfully;
- * the interpreter's result describes what went wrong.
- * TCL_RETURN The command requests that the current procedure
- * return; the interpreter's result contains the
- * procedure's return value.
- * TCL_BREAK The command requests that the innermost loop
- * be exited; the interpreter's result is meaningless.
- * TCL_CONTINUE Go on to the next iteration of the current loop;
- * the interpreter's result is meaningless.
- */
-#define TCL_OK 0
-#define TCL_ERROR 1
-#define TCL_RETURN 2
-#define TCL_BREAK 3
-#define TCL_CONTINUE 4
-
-#define TCL_RESULT_SIZE 200
+ * TCL_OK Command completed normally; the interpreter's result
+ * contains the command's result.
+ * TCL_ERROR The command couldn't be completed successfully; the
+ * interpreter's result describes what went wrong.
+ * TCL_RETURN The command requests that the current function return;
+ * the interpreter's result contains the function's
+ * return value.
+ * TCL_BREAK The command requests that the innermost loop be
+ * exited; the interpreter's result is meaningless.
+ * TCL_CONTINUE Go on to the next iteration of the current loop; the
+ * interpreter's result is meaningless.
+ */
+
+#define TCL_OK 0
+#define TCL_ERROR 1
+#define TCL_RETURN 2
+#define TCL_BREAK 3
+#define TCL_CONTINUE 4
+
+#define TCL_RESULT_SIZE 200
/*
* Flags to control what substitutions are performed by Tcl_SubstObj():
*/
+
#define TCL_SUBST_COMMANDS 001
#define TCL_SUBST_VARIABLES 002
#define TCL_SUBST_BACKSLASHES 004
#define TCL_SUBST_ALL 007
-
/*
* Argument descriptors for math function callbacks in expressions:
*/
+
typedef enum {
TCL_INT, TCL_DOUBLE, TCL_EITHER, TCL_WIDE_INT
} Tcl_ValueType;
+
typedef struct Tcl_Value {
- Tcl_ValueType type; /* Indicates intValue or doubleValue is
- * valid, or both. */
+ Tcl_ValueType type; /* Indicates intValue or doubleValue is valid,
+ * or both. */
long intValue; /* Integer value. */
double doubleValue; /* Double-precision floating value. */
Tcl_WideInt wideValue; /* Wide (min. 64-bit) integer value. */
@@ -670,14 +636,13 @@ typedef struct Tcl_Value {
/*
* Forward declaration of Tcl_Obj to prevent an error when the forward
- * reference to Tcl_Obj is encountered in the procedure types declared
- * below.
+ * reference to Tcl_Obj is encountered in the function types declared below.
*/
-struct Tcl_Obj;
+struct Tcl_Obj;
/*
- * Procedure types defined by Tcl:
+ * Function types defined by Tcl:
*/
typedef int (Tcl_AppInitProc) _ANSI_ARGS_((Tcl_Interp *interp));
@@ -695,8 +660,8 @@ typedef int (Tcl_CmdObjTraceProc) _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int level, CONST char *command,
Tcl_Command commandInfo, int objc, struct Tcl_Obj * CONST * objv));
typedef void (Tcl_CmdObjTraceDeleteProc) _ANSI_ARGS_((ClientData clientData));
-typedef void (Tcl_DupInternalRepProc) _ANSI_ARGS_((struct Tcl_Obj *srcPtr,
- struct Tcl_Obj *dupPtr));
+typedef void (Tcl_DupInternalRepProc) _ANSI_ARGS_((struct Tcl_Obj *srcPtr,
+ struct Tcl_Obj *dupPtr));
typedef int (Tcl_EncodingConvertProc)_ANSI_ARGS_((ClientData clientData,
CONST char *src, int srcLen, int flags, Tcl_EncodingState *statePtr,
char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr,
@@ -706,7 +671,7 @@ typedef int (Tcl_EventProc) _ANSI_ARGS_((Tcl_Event *evPtr, int flags));
typedef void (Tcl_EventCheckProc) _ANSI_ARGS_((ClientData clientData,
int flags));
typedef int (Tcl_EventDeleteProc) _ANSI_ARGS_((Tcl_Event *evPtr,
- ClientData clientData));
+ ClientData clientData));
typedef void (Tcl_EventSetupProc) _ANSI_ARGS_((ClientData clientData,
int flags));
typedef void (Tcl_ExitProc) _ANSI_ARGS_((ClientData clientData));
@@ -723,15 +688,18 @@ typedef void (Tcl_NamespaceDeleteProc) _ANSI_ARGS_((ClientData clientData));
typedef int (Tcl_ObjCmdProc) _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int objc, struct Tcl_Obj * CONST * objv));
typedef int (Tcl_PackageInitProc) _ANSI_ARGS_((Tcl_Interp *interp));
-typedef void (Tcl_PanicProc) _ANSI_ARGS_(TCL_VARARGS(CONST char *, format));
+typedef int (Tcl_PackageUnloadProc) _ANSI_ARGS_((Tcl_Interp *interp,
+ int flags));
+typedef void (Tcl_PanicProc) _ANSI_ARGS_((CONST char *format, ...));
typedef void (Tcl_TcpAcceptProc) _ANSI_ARGS_((ClientData callbackData,
- Tcl_Channel chan, char *address, int port));
+ Tcl_Channel chan, char *address, int port));
typedef void (Tcl_TimerProc) _ANSI_ARGS_((ClientData clientData));
typedef int (Tcl_SetFromAnyProc) _ANSI_ARGS_((Tcl_Interp *interp,
struct Tcl_Obj *objPtr));
typedef void (Tcl_UpdateStringProc) _ANSI_ARGS_((struct Tcl_Obj *objPtr));
typedef char *(Tcl_VarTraceProc) _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, CONST84 char *part1, CONST84 char *part2, int flags));
+ Tcl_Interp *interp, CONST84 char *part1, CONST84 char *part2,
+ int flags));
typedef void (Tcl_CommandTraceProc) _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, CONST char *oldName, CONST char *newName,
int flags));
@@ -743,37 +711,35 @@ typedef void (Tcl_ServiceModeHookProc) _ANSI_ARGS_((int mode));
typedef ClientData (Tcl_InitNotifierProc) _ANSI_ARGS_((VOID));
typedef void (Tcl_FinalizeNotifierProc) _ANSI_ARGS_((ClientData clientData));
typedef void (Tcl_MainLoopProc) _ANSI_ARGS_((void));
-
+
/*
- * The following structure represents a type of object, which is a
- * particular internal representation for an object plus a set of
- * procedures that provide standard operations on objects of that type.
+ * The following structure represents a type of object, which is a particular
+ * internal representation for an object plus a set of functions that provide
+ * standard operations on objects of that type.
*/
typedef struct Tcl_ObjType {
char *name; /* Name of the type, e.g. "int". */
Tcl_FreeInternalRepProc *freeIntRepProc;
/* Called to free any storage for the type's
- * internal rep. NULL if the internal rep
- * does not need freeing. */
+ * internal rep. NULL if the internal rep does
+ * not need freeing. */
Tcl_DupInternalRepProc *dupIntRepProc;
- /* Called to create a new object as a copy
- * of an existing object. */
+ /* Called to create a new object as a copy of
+ * an existing object. */
Tcl_UpdateStringProc *updateStringProc;
- /* Called to update the string rep from the
+ /* Called to update the string rep from the
* type's internal representation. */
Tcl_SetFromAnyProc *setFromAnyProc;
- /* Called to convert the object's internal
- * rep to this type. Frees the internal rep
- * of the old type. Returns TCL_ERROR on
- * failure. */
+ /* Called to convert the object's internal rep
+ * to this type. Frees the internal rep of the
+ * old type. Returns TCL_ERROR on failure. */
} Tcl_ObjType;
-
/*
- * One of the following structures exists for each object in the Tcl
- * system. An object stores a value as either a string, some internal
- * representation, or both.
+ * One of the following structures exists for each object in the Tcl system.
+ * An object stores a value as either a string, some internal representation,
+ * or both.
*/
typedef struct Tcl_Obj {
@@ -783,98 +749,57 @@ typedef struct Tcl_Obj {
* must be followed by a null byte (i.e., at
* offset length) but may also contain
* embedded null characters. The array's
- * storage is allocated by ckalloc. NULL
- * means the string rep is invalid and must
- * be regenerated from the internal rep.
- * Clients should use Tcl_GetStringFromObj
- * or Tcl_GetString to get a pointer to the
- * byte array as a readonly value. */
+ * storage is allocated by ckalloc. NULL means
+ * the string rep is invalid and must be
+ * regenerated from the internal rep. Clients
+ * should use Tcl_GetStringFromObj or
+ * Tcl_GetString to get a pointer to the byte
+ * array as a readonly value. */
int length; /* The number of bytes at *bytes, not
* including the terminating null. */
Tcl_ObjType *typePtr; /* Denotes the object's type. Always
* corresponds to the type of the object's
- * internal rep. NULL indicates the object
- * has no internal rep (has no type). */
+ * internal rep. NULL indicates the object has
+ * no internal rep (has no type). */
union { /* The internal representation: */
- long longValue; /* - an long integer value */
- double doubleValue; /* - a double-precision floating value */
- VOID *otherValuePtr; /* - another, type-specific value */
- Tcl_WideInt wideValue; /* - a long long value */
- struct { /* - internal rep as two pointers */
+ long longValue; /* - an long integer value. */
+ double doubleValue; /* - a double-precision floating value. */
+ VOID *otherValuePtr; /* - another, type-specific value. */
+ Tcl_WideInt wideValue; /* - a long long value. */
+ struct { /* - internal rep as two pointers. */
VOID *ptr1;
VOID *ptr2;
} twoPtrValue;
+ struct { /* - internal rep as a wide int, tightly
+ * packed fields. */
+ VOID *ptr; /* Pointer to digits. */
+ unsigned long value;/* Alloc, used, and signum packed into a
+ * single word. */
+ } ptrAndLongRep;
} internalRep;
} Tcl_Obj;
-
/*
- * Macros to increment and decrement a Tcl_Obj's reference count, and to
- * test whether an object is shared (i.e. has reference count > 1).
- * Note: clients should use Tcl_DecrRefCount() when they are finished using
- * an object, and should never call TclFreeObj() directly. TclFreeObj() is
- * only defined and made public in tcl.h to support Tcl_DecrRefCount's macro
- * definition. Note also that Tcl_DecrRefCount() refers to the parameter
- * "obj" twice. This means that you should avoid calling it with an
- * expression that is expensive to compute or has side effects.
+ * Macros to increment and decrement a Tcl_Obj's reference count, and to test
+ * whether an object is shared (i.e. has reference count > 1). Note: clients
+ * should use Tcl_DecrRefCount() when they are finished using an object, and
+ * should never call TclFreeObj() directly. TclFreeObj() is only defined and
+ * made public in tcl.h to support Tcl_DecrRefCount's macro definition. Note
+ * also that Tcl_DecrRefCount() refers to the parameter "obj" twice. This
+ * means that you should avoid calling it with an expression that is expensive
+ * to compute or has side effects.
*/
+
void Tcl_IncrRefCount _ANSI_ARGS_((Tcl_Obj *objPtr));
void Tcl_DecrRefCount _ANSI_ARGS_((Tcl_Obj *objPtr));
int Tcl_IsShared _ANSI_ARGS_((Tcl_Obj *objPtr));
-
-#ifdef TCL_MEM_DEBUG
-# define Tcl_IncrRefCount(objPtr) \
- Tcl_DbIncrRefCount(objPtr, __FILE__, __LINE__)
-# define Tcl_DecrRefCount(objPtr) \
- Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__)
-# define Tcl_IsShared(objPtr) \
- Tcl_DbIsShared(objPtr, __FILE__, __LINE__)
-#else
-# define Tcl_IncrRefCount(objPtr) \
- ++(objPtr)->refCount
- /*
- * Use do/while0 idiom for optimum correctness without compiler warnings
- * http://c2.com/cgi/wiki?TrivialDoWhileLoop
- */
-# define Tcl_DecrRefCount(objPtr) \
- do { if (--(objPtr)->refCount <= 0) TclFreeObj(objPtr); } while(0)
-# define Tcl_IsShared(objPtr) \
- ((objPtr)->refCount > 1)
-#endif
/*
- * Macros and definitions that help to debug the use of Tcl objects.
- * When TCL_MEM_DEBUG is defined, the Tcl_New declarations are
- * overridden to call debugging versions of the object creation procedures.
+ * The following structure contains the state needed by Tcl_SaveResult. No-one
+ * outside of Tcl should access any of these fields. This structure is
+ * typically allocated on the stack.
*/
-#ifdef TCL_MEM_DEBUG
-# define Tcl_NewBooleanObj(val) \
- Tcl_DbNewBooleanObj(val, __FILE__, __LINE__)
-# define Tcl_NewByteArrayObj(bytes, len) \
- Tcl_DbNewByteArrayObj(bytes, len, __FILE__, __LINE__)
-# define Tcl_NewDoubleObj(val) \
- Tcl_DbNewDoubleObj(val, __FILE__, __LINE__)
-# define Tcl_NewIntObj(val) \
- Tcl_DbNewLongObj(val, __FILE__, __LINE__)
-# define Tcl_NewListObj(objc, objv) \
- Tcl_DbNewListObj(objc, objv, __FILE__, __LINE__)
-# define Tcl_NewLongObj(val) \
- Tcl_DbNewLongObj(val, __FILE__, __LINE__)
-# define Tcl_NewObj() \
- Tcl_DbNewObj(__FILE__, __LINE__)
-# define Tcl_NewStringObj(bytes, len) \
- Tcl_DbNewStringObj(bytes, len, __FILE__, __LINE__)
-# define Tcl_NewWideIntObj(val) \
- Tcl_DbNewWideIntObj(val, __FILE__, __LINE__)
-#endif /* TCL_MEM_DEBUG */
-
-
-/*
- * The following structure contains the state needed by
- * Tcl_SaveResult. No-one outside of Tcl should access any of these
- * fields. This structure is typically allocated on the stack.
- */
typedef struct Tcl_SavedResult {
char *result;
Tcl_FreeProc *freeProc;
@@ -885,49 +810,47 @@ typedef struct Tcl_SavedResult {
char resultSpace[TCL_RESULT_SIZE+1];
} Tcl_SavedResult;
-
/*
- * The following definitions support Tcl's namespace facility.
- * Note: the first five fields must match exactly the fields in a
- * Namespace structure (see tclInt.h).
+ * The following definitions support Tcl's namespace facility. Note: the first
+ * five fields must match exactly the fields in a Namespace structure (see
+ * tclInt.h).
*/
typedef struct Tcl_Namespace {
- char *name; /* The namespace's name within its parent
- * namespace. This contains no ::'s. The
- * name of the global namespace is ""
- * although "::" is an synonym. */
- char *fullName; /* The namespace's fully qualified name.
- * This starts with ::. */
- ClientData clientData; /* Arbitrary value associated with this
+ char *name; /* The namespace's name within its parent
+ * namespace. This contains no ::'s. The name
+ * of the global namespace is "" although "::"
+ * is an synonym. */
+ char *fullName; /* The namespace's fully qualified name. This
+ * starts with ::. */
+ ClientData clientData; /* Arbitrary value associated with this
* namespace. */
- Tcl_NamespaceDeleteProc* deleteProc;
- /* Procedure invoked when deleting the
+ Tcl_NamespaceDeleteProc *deleteProc;
+ /* Function invoked when deleting the
* namespace to, e.g., free clientData. */
- struct Tcl_Namespace* parentPtr;
- /* Points to the namespace that contains
- * this one. NULL if this is the global
+ struct Tcl_Namespace *parentPtr;
+ /* Points to the namespace that contains this
+ * one. NULL if this is the global
* namespace. */
} Tcl_Namespace;
-
/*
- * The following structure represents a call frame, or activation record.
- * A call frame defines a naming context for a procedure call: its local
- * scope (for local variables) and its namespace scope (used for non-local
- * variables; often the global :: namespace). A call frame can also define
- * the naming context for a namespace eval or namespace inscope command:
- * the namespace in which the command's code should execute. The
- * Tcl_CallFrame structures exist only while procedures or namespace
- * eval/inscope's are being executed, and provide a Tcl call stack.
- *
- * A call frame is initialized and pushed using Tcl_PushCallFrame and
- * popped using Tcl_PopCallFrame. Storage for a Tcl_CallFrame must be
- * provided by the Tcl_PushCallFrame caller, and callers typically allocate
- * them on the C call stack for efficiency. For this reason, Tcl_CallFrame
- * is defined as a structure and not as an opaque token. However, most
- * Tcl_CallFrame fields are hidden since applications should not access
- * them directly; others are declared as "dummyX".
+ * The following structure represents a call frame, or activation record. A
+ * call frame defines a naming context for a procedure call: its local scope
+ * (for local variables) and its namespace scope (used for non-local
+ * variables; often the global :: namespace). A call frame can also define the
+ * naming context for a namespace eval or namespace inscope command: the
+ * namespace in which the command's code should execute. The Tcl_CallFrame
+ * structures exist only while procedures or namespace eval/inscope's are
+ * being executed, and provide a Tcl call stack.
+ *
+ * A call frame is initialized and pushed using Tcl_PushCallFrame and popped
+ * using Tcl_PopCallFrame. Storage for a Tcl_CallFrame must be provided by the
+ * Tcl_PushCallFrame caller, and callers typically allocate them on the C call
+ * stack for efficiency. For this reason, Tcl_CallFrame is defined as a
+ * structure and not as an opaque token. However, most Tcl_CallFrame fields
+ * are hidden since applications should not access them directly; others are
+ * declared as "dummyX".
*
* WARNING!! The structure definition must be kept consistent with the
* CallFrame structure in tclInt.h. If you change one, change the other.
@@ -950,59 +873,58 @@ typedef struct Tcl_CallFrame {
VOID *dummy13;
} Tcl_CallFrame;
-
/*
* Information about commands that is returned by Tcl_GetCommandInfo and
- * passed to Tcl_SetCommandInfo. objProc is an objc/objv object-based
- * command procedure while proc is a traditional Tcl argc/argv
- * string-based procedure. Tcl_CreateObjCommand and Tcl_CreateCommand
- * ensure that both objProc and proc are non-NULL and can be called to
- * execute the command. However, it may be faster to call one instead of
- * the other. The member isNativeObjectProc is set to 1 if an
- * object-based procedure was registered by Tcl_CreateObjCommand, and to
- * 0 if a string-based procedure was registered by Tcl_CreateCommand.
- * The other procedure is typically set to a compatibility wrapper that
- * does string-to-object or object-to-string argument conversions then
- * calls the other procedure.
+ * passed to Tcl_SetCommandInfo. objProc is an objc/objv object-based command
+ * function while proc is a traditional Tcl argc/argv string-based function.
+ * Tcl_CreateObjCommand and Tcl_CreateCommand ensure that both objProc and
+ * proc are non-NULL and can be called to execute the command. However, it may
+ * be faster to call one instead of the other. The member isNativeObjectProc
+ * is set to 1 if an object-based function was registered by
+ * Tcl_CreateObjCommand, and to 0 if a string-based function was registered by
+ * Tcl_CreateCommand. The other function is typically set to a compatibility
+ * wrapper that does string-to-object or object-to-string argument conversions
+ * then calls the other function.
*/
typedef struct Tcl_CmdInfo {
- int isNativeObjectProc; /* 1 if objProc was registered by a call to
- * Tcl_CreateObjCommand; 0 otherwise.
- * Tcl_SetCmdInfo does not modify this
- * field. */
- Tcl_ObjCmdProc *objProc; /* Command's object-based procedure. */
- ClientData objClientData; /* ClientData for object proc. */
- Tcl_CmdProc *proc; /* Command's string-based procedure. */
- ClientData clientData; /* ClientData for string proc. */
+ int isNativeObjectProc; /* 1 if objProc was registered by a call to
+ * Tcl_CreateObjCommand; 0 otherwise.
+ * Tcl_SetCmdInfo does not modify this
+ * field. */
+ Tcl_ObjCmdProc *objProc; /* Command's object-based function. */
+ ClientData objClientData; /* ClientData for object proc. */
+ Tcl_CmdProc *proc; /* Command's string-based function. */
+ ClientData clientData; /* ClientData for string proc. */
Tcl_CmdDeleteProc *deleteProc;
- /* Procedure to call when command is
- * deleted. */
- ClientData deleteData; /* Value to pass to deleteProc (usually
- * the same as clientData). */
- Tcl_Namespace *namespacePtr; /* Points to the namespace that contains
- * this command. Note that Tcl_SetCmdInfo
- * will not change a command's namespace;
- * use Tcl_RenameCommand to do that. */
-
+ /* Function to call when command is
+ * deleted. */
+ ClientData deleteData; /* Value to pass to deleteProc (usually the
+ * same as clientData). */
+ Tcl_Namespace *namespacePtr;/* Points to the namespace that contains this
+ * command. Note that Tcl_SetCmdInfo will not
+ * change a command's namespace; use
+ * TclRenameCommand or Tcl_Eval (of 'rename')
+ * to do that. */
} Tcl_CmdInfo;
/*
- * The structure defined below is used to hold dynamic strings. The only
- * field that clients should use is the string field, accessible via the
- * macro Tcl_DStringValue.
+ * The structure defined below is used to hold dynamic strings. The only
+ * fields that clients should use are string and length, accessible via the
+ * macros Tcl_DStringValue and Tcl_DStringLength.
*/
+
#define TCL_DSTRING_STATIC_SIZE 200
typedef struct Tcl_DString {
- char *string; /* Points to beginning of string: either
+ char *string; /* Points to beginning of string: either
* staticSpace below or a malloced array. */
int length; /* Number of non-NULL characters in the
* string. */
int spaceAvl; /* Total number of bytes available for the
* string and its terminating NULL char. */
char staticSpace[TCL_DSTRING_STATIC_SIZE];
- /* Space to use in common case where string
- * is small. */
+ /* Space to use in common case where string is
+ * small. */
} Tcl_DString;
#define Tcl_DStringLength(dsPtr) ((dsPtr)->length)
@@ -1010,54 +932,75 @@ typedef struct Tcl_DString {
#define Tcl_DStringTrunc Tcl_DStringSetLength
/*
- * Definitions for the maximum number of digits of precision that may
- * be specified in the "tcl_precision" variable, and the number of
- * bytes of buffer space required by Tcl_PrintDouble.
+ * Definitions for the maximum number of digits of precision that may be
+ * specified in the "tcl_precision" variable, and the number of bytes of
+ * buffer space required by Tcl_PrintDouble.
*/
-#define TCL_MAX_PREC 17
-#define TCL_DOUBLE_SPACE (TCL_MAX_PREC+10)
+
+#define TCL_MAX_PREC 17
+#define TCL_DOUBLE_SPACE (TCL_MAX_PREC+10)
/*
* Definition for a number of bytes of buffer space sufficient to hold the
- * string representation of an integer in base 10 (assuming the existence
- * of 64-bit integers).
+ * string representation of an integer in base 10 (assuming the existence of
+ * 64-bit integers).
*/
+
#define TCL_INTEGER_SPACE 24
/*
- * Flag that may be passed to Tcl_ConvertElement to force it not to
- * output braces (careful! if you change this flag be sure to change
- * the definitions at the front of tclUtil.c).
+ * Flag values passed to Tcl_ConvertElement.
+ * TCL_DONT_USE_BRACES forces it not to enclose the element in braces, but to
+ * use backslash quoting instead.
+ * TCL_DONT_QUOTE_HASH disables the default quoting of the '#' character. It
+ * is safe to leave the hash unquoted when the element is not the first
+ * element of a list, and this flag can be used by the caller to indicate
+ * that condition.
*/
+
#define TCL_DONT_USE_BRACES 1
+#define TCL_DONT_QUOTE_HASH 8
/*
* Flag that may be passed to Tcl_GetIndexFromObj to force it to disallow
* abbreviated strings.
*/
+
#define TCL_EXACT 1
/*
- * Flag values passed to Tcl_RecordAndEval and/or Tcl_EvalObj.
- * WARNING: these bit choices must not conflict with the bit choices
- * for evalFlag bits in tclInt.h!!
+ * Flag values passed to Tcl_RecordAndEval, Tcl_EvalObj, Tcl_EvalObjv.
+ * WARNING: these bit choices must not conflict with the bit choices for
+ * evalFlag bits in tclInt.h!
+ *
+ * Meanings:
+ * TCL_NO_EVAL: Just record this command
+ * TCL_EVAL_GLOBAL: Execute script in global namespace
+ * TCL_EVAL_DIRECT: Do not compile this script
+ * TCL_EVAL_INVOKE: Magical Tcl_EvalObjv mode for aliases/ensembles
+ * o Run in iPtr->lookupNsPtr or global namespace
+ * o Cut out of error traces
+ * o Don't reset the flags controlling ensemble
+ * error message rewriting.
*/
#define TCL_NO_EVAL 0x10000
#define TCL_EVAL_GLOBAL 0x20000
#define TCL_EVAL_DIRECT 0x40000
-#define TCL_EVAL_INVOKE 0x80000
+#define TCL_EVAL_INVOKE 0x80000
/*
- * Special freeProc values that may be passed to Tcl_SetResult (see
- * the man page for details):
+ * Special freeProc values that may be passed to Tcl_SetResult (see the man
+ * page for details):
*/
-#define TCL_VOLATILE ((Tcl_FreeProc *) 1)
-#define TCL_STATIC ((Tcl_FreeProc *) 0)
-#define TCL_DYNAMIC ((Tcl_FreeProc *) 3)
+
+#define TCL_VOLATILE ((Tcl_FreeProc *) 1)
+#define TCL_STATIC ((Tcl_FreeProc *) 0)
+#define TCL_DYNAMIC ((Tcl_FreeProc *) 3)
/*
- * Flag values passed to variable-related procedures.
+ * Flag values passed to variable-related functions.
*/
+
#define TCL_GLOBAL_ONLY 1
#define TCL_NAMESPACE_ONLY 2
#define TCL_APPEND_VALUE 4
@@ -1078,7 +1021,15 @@ typedef struct Tcl_DString {
#define TCL_TRACE_RESULT_OBJECT 0x10000
/*
- * Flag values passed to command-related procedures.
+ * Flag values for ensemble commands.
+ */
+
+#define TCL_ENSEMBLE_PREFIX 0x02/* Flag value to say whether to allow
+ * unambiguous prefixes of commands or to
+ * require exact matches for command names. */
+
+/*
+ * Flag values passed to command-related functions.
*/
#define TCL_TRACE_RENAME 0x2000
@@ -1087,39 +1038,40 @@ typedef struct Tcl_DString {
#define TCL_ALLOW_INLINE_COMPILATION 0x20000
/*
- * Flag values passed to Tcl_CreateObjTrace, and used internally
- * by command execution traces. Slots 4,8,16 and 32 are
- * used internally by execution traces (see tclCmdMZ.c)
+ * The TCL_PARSE_PART1 flag is deprecated and has no effect. The part1 is now
+ * always parsed whenever the part2 is NULL. (This is to avoid a common error
+ * when converting code to use the new object based APIs and forgetting to
+ * give the flag)
*/
-#define TCL_TRACE_ENTER_EXEC 1
-#define TCL_TRACE_LEAVE_EXEC 2
-/*
- * The TCL_PARSE_PART1 flag is deprecated and has no effect.
- * The part1 is now always parsed whenever the part2 is NULL.
- * (This is to avoid a common error when converting code to
- * use the new object based APIs and forgetting to give the
- * flag)
- */
#ifndef TCL_NO_DEPRECATED
-# define TCL_PARSE_PART1 0x400
+# define TCL_PARSE_PART1 0x400
#endif
-
/*
* Types for linked variables:
*/
+
#define TCL_LINK_INT 1
#define TCL_LINK_DOUBLE 2
#define TCL_LINK_BOOLEAN 3
#define TCL_LINK_STRING 4
#define TCL_LINK_WIDE_INT 5
+#define TCL_LINK_CHAR 6
+#define TCL_LINK_UCHAR 7
+#define TCL_LINK_SHORT 8
+#define TCL_LINK_USHORT 9
+#define TCL_LINK_UINT 10
+#define TCL_LINK_LONG 11
+#define TCL_LINK_ULONG 12
+#define TCL_LINK_FLOAT 13
+#define TCL_LINK_WIDE_UINT 14
#define TCL_LINK_READ_ONLY 0x80
-
/*
* Forward declarations of Tcl_HashTable and related types.
*/
+
typedef struct Tcl_HashKeyType Tcl_HashKeyType;
typedef struct Tcl_HashTable Tcl_HashTable;
typedef struct Tcl_HashEntry Tcl_HashEntry;
@@ -1134,170 +1086,163 @@ typedef void (Tcl_FreeHashEntryProc) _ANSI_ARGS_((Tcl_HashEntry *hPtr));
/*
* This flag controls whether the hash table stores the hash of a key, or
- * recalculates it. There should be no reason for turning this flag off
- * as it is completely binary and source compatible unless you directly
- * access the bucketPtr member of the Tcl_HashTableEntry structure. This
- * member has been removed and the space used to store the hash value.
+ * recalculates it. There should be no reason for turning this flag off as it
+ * is completely binary and source compatible unless you directly access the
+ * bucketPtr member of the Tcl_HashTableEntry structure. This member has been
+ * removed and the space used to store the hash value.
*/
+
#ifndef TCL_HASH_KEY_STORE_HASH
# define TCL_HASH_KEY_STORE_HASH 1
#endif
/*
- * Structure definition for an entry in a hash table. No-one outside
- * Tcl should access any of these fields directly; use the macros
- * defined below.
+ * Structure definition for an entry in a hash table. No-one outside Tcl
+ * should access any of these fields directly; use the macros defined below.
*/
struct Tcl_HashEntry {
- Tcl_HashEntry *nextPtr; /* Pointer to next entry in this
- * hash bucket, or NULL for end of
- * chain. */
- Tcl_HashTable *tablePtr; /* Pointer to table containing entry. */
+ Tcl_HashEntry *nextPtr; /* Pointer to next entry in this hash bucket,
+ * or NULL for end of chain. */
+ Tcl_HashTable *tablePtr; /* Pointer to table containing entry. */
#if TCL_HASH_KEY_STORE_HASH
-# if TCL_PRESERVE_BINARY_COMPATABILITY
- VOID *hash; /* Hash value, stored as pointer to
- * ensure that the offsets of the
- * fields in this structure are not
- * changed. */
-# else
- unsigned int hash; /* Hash value. */
-# endif
+ VOID *hash; /* Hash value, stored as pointer to ensure
+ * that the offsets of the fields in this
+ * structure are not changed. */
#else
- Tcl_HashEntry **bucketPtr; /* Pointer to bucket that points to
- * first entry in this entry's chain:
- * used for deleting the entry. */
+ Tcl_HashEntry **bucketPtr; /* Pointer to bucket that points to first
+ * entry in this entry's chain: used for
+ * deleting the entry. */
#endif
- ClientData clientData; /* Application stores something here
- * with Tcl_SetHashValue. */
- union { /* Key has one of these forms: */
- char *oneWordValue; /* One-word value for key. */
- Tcl_Obj *objPtr; /* Tcl_Obj * key value. */
- int words[1]; /* Multiple integer words for key.
- * The actual size will be as large
- * as necessary for this table's
- * keys. */
- char string[4]; /* String for key. The actual size
- * will be as large as needed to hold
- * the key. */
- } key; /* MUST BE LAST FIELD IN RECORD!! */
+ ClientData clientData; /* Application stores something here with
+ * Tcl_SetHashValue. */
+ union { /* Key has one of these forms: */
+ char *oneWordValue; /* One-word value for key. */
+ Tcl_Obj *objPtr; /* Tcl_Obj * key value. */
+ int words[1]; /* Multiple integer words for key. The actual
+ * size will be as large as necessary for this
+ * table's keys. */
+ char string[4]; /* String for key. The actual size will be as
+ * large as needed to hold the key. */
+ } key; /* MUST BE LAST FIELD IN RECORD!! */
};
/*
* Flags used in Tcl_HashKeyType.
*
- * TCL_HASH_KEY_RANDOMIZE_HASH:
+ * TCL_HASH_KEY_RANDOMIZE_HASH -
* There are some things, pointers for example
* which don't hash well because they do not use
* the lower bits. If this flag is set then the
* hash table will attempt to rectify this by
* randomising the bits and then using the upper
* N bits as the index into the table.
+ * TCL_HASH_KEY_SYSTEM_HASH - If this flag is set then all memory internally
+ * allocated for the hash table that is not for an
+ * entry will use the system heap.
*/
+
#define TCL_HASH_KEY_RANDOMIZE_HASH 0x1
+#define TCL_HASH_KEY_SYSTEM_HASH 0x2
/*
- * Structure definition for the methods associated with a hash table
- * key type.
+ * Structure definition for the methods associated with a hash table key type.
*/
+
#define TCL_HASH_KEY_TYPE_VERSION 1
struct Tcl_HashKeyType {
int version; /* Version of the table. If this structure is
* extended in future then the version can be
* used to distinguish between different
- * structures.
- */
-
+ * structures. */
int flags; /* Flags, see above for details. */
-
- /* Calculates a hash value for the key. If this is NULL then the pointer
- * itself is used as a hash value.
- */
Tcl_HashKeyProc *hashKeyProc;
-
- /* Compares two keys and returns zero if they do not match, and non-zero
- * if they do. If this is NULL then the pointers are compared.
- */
+ /* Calculates a hash value for the key. If
+ * this is NULL then the pointer itself is
+ * used as a hash value. */
Tcl_CompareHashKeysProc *compareKeysProc;
-
- /* Called to allocate memory for a new entry, i.e. if the key is a
- * string then this could allocate a single block which contains enough
- * space for both the entry and the string. Only the key field of the
- * allocated Tcl_HashEntry structure needs to be filled in. If something
- * else needs to be done to the key, i.e. incrementing a reference count
- * then that should be done by this function. If this is NULL then Tcl_Alloc
- * is used to allocate enough space for a Tcl_HashEntry and the key pointer
- * is assigned to key.oneWordValue.
- */
+ /* Compares two keys and returns zero if they
+ * do not match, and non-zero if they do. If
+ * this is NULL then the pointers are
+ * compared. */
Tcl_AllocHashEntryProc *allocEntryProc;
-
- /* Called to free memory associated with an entry. If something else needs
- * to be done to the key, i.e. decrementing a reference count then that
- * should be done by this function. If this is NULL then Tcl_Free is used
- * to free the Tcl_HashEntry.
- */
+ /* Called to allocate memory for a new entry,
+ * i.e. if the key is a string then this could
+ * allocate a single block which contains
+ * enough space for both the entry and the
+ * string. Only the key field of the allocated
+ * Tcl_HashEntry structure needs to be filled
+ * in. If something else needs to be done to
+ * the key, i.e. incrementing a reference
+ * count then that should be done by this
+ * function. If this is NULL then Tcl_Alloc is
+ * used to allocate enough space for a
+ * Tcl_HashEntry and the key pointer is
+ * assigned to key.oneWordValue. */
Tcl_FreeHashEntryProc *freeEntryProc;
+ /* Called to free memory associated with an
+ * entry. If something else needs to be done
+ * to the key, i.e. decrementing a reference
+ * count then that should be done by this
+ * function. If this is NULL then Tcl_Free is
+ * used to free the Tcl_HashEntry. */
};
/*
- * Structure definition for a hash table. Must be in tcl.h so clients
- * can allocate space for these structures, but clients should never
- * access any fields in this structure.
+ * Structure definition for a hash table. Must be in tcl.h so clients can
+ * allocate space for these structures, but clients should never access any
+ * fields in this structure.
*/
#define TCL_SMALL_HASH_TABLE 4
struct Tcl_HashTable {
- Tcl_HashEntry **buckets; /* Pointer to bucket array. Each
- * element points to first entry in
- * bucket's hash chain, or NULL. */
+ Tcl_HashEntry **buckets; /* Pointer to bucket array. Each element
+ * points to first entry in bucket's hash
+ * chain, or NULL. */
Tcl_HashEntry *staticBuckets[TCL_SMALL_HASH_TABLE];
- /* Bucket array used for small tables
- * (to avoid mallocs and frees). */
- int numBuckets; /* Total number of buckets allocated
- * at **bucketPtr. */
- int numEntries; /* Total number of entries present
- * in table. */
- int rebuildSize; /* Enlarge table when numEntries gets
- * to be this large. */
- int downShift; /* Shift count used in hashing
- * function. Designed to use high-
- * order bits of randomized keys. */
- int mask; /* Mask value used in hashing
- * function. */
- int keyType; /* Type of keys used in this table.
- * It's either TCL_CUSTOM_KEYS,
- * TCL_STRING_KEYS, TCL_ONE_WORD_KEYS,
- * or an integer giving the number of
- * ints that is the size of the key.
- */
-#if TCL_PRESERVE_BINARY_COMPATABILITY
+ /* Bucket array used for small tables (to
+ * avoid mallocs and frees). */
+ int numBuckets; /* Total number of buckets allocated at
+ * **bucketPtr. */
+ int numEntries; /* Total number of entries present in
+ * table. */
+ int rebuildSize; /* Enlarge table when numEntries gets to be
+ * this large. */
+ int downShift; /* Shift count used in hashing function.
+ * Designed to use high-order bits of
+ * randomized keys. */
+ int mask; /* Mask value used in hashing function. */
+ int keyType; /* Type of keys used in this table. It's
+ * either TCL_CUSTOM_KEYS, TCL_STRING_KEYS,
+ * TCL_ONE_WORD_KEYS, or an integer giving the
+ * number of ints that is the size of the
+ * key. */
Tcl_HashEntry *(*findProc) _ANSI_ARGS_((Tcl_HashTable *tablePtr,
CONST char *key));
Tcl_HashEntry *(*createProc) _ANSI_ARGS_((Tcl_HashTable *tablePtr,
CONST char *key, int *newPtr));
-#endif
- Tcl_HashKeyType *typePtr; /* Type of the keys used in the
- * Tcl_HashTable. */
+ Tcl_HashKeyType *typePtr; /* Type of the keys used in the
+ * Tcl_HashTable. */
};
/*
- * Structure definition for information used to keep track of searches
- * through hash tables:
+ * Structure definition for information used to keep track of searches through
+ * hash tables:
*/
typedef struct Tcl_HashSearch {
- Tcl_HashTable *tablePtr; /* Table being searched. */
- int nextIndex; /* Index of next bucket to be
- * enumerated after present one. */
- Tcl_HashEntry *nextEntryPtr; /* Next entry to be enumerated in the
- * the current bucket. */
+ Tcl_HashTable *tablePtr; /* Table being searched. */
+ int nextIndex; /* Index of next bucket to be enumerated after
+ * present one. */
+ Tcl_HashEntry *nextEntryPtr;/* Next entry to be enumerated in the current
+ * bucket. */
} Tcl_HashSearch;
/*
* Acceptable key types for hash tables:
*
- * TCL_STRING_KEYS: The keys are strings, they are copied into
- * the entry.
+ * TCL_STRING_KEYS: The keys are strings, they are copied into the
+ * entry.
* TCL_ONE_WORD_KEYS: The keys are pointers, the pointer is stored
* in the entry.
* TCL_CUSTOM_TYPE_KEYS: The keys are arbitrary types which are copied
@@ -1305,69 +1250,39 @@ typedef struct Tcl_HashSearch {
* TCL_CUSTOM_PTR_KEYS: The keys are pointers to arbitrary types, the
* pointer is stored in the entry.
*
- * While maintaining binary compatability the above have to be distinct
- * values as they are used to differentiate between old versions of the
- * hash table which don't have a typePtr and new ones which do. Once binary
- * compatability is discarded in favour of making more wide spread changes
- * TCL_STRING_KEYS can be the same as TCL_CUSTOM_TYPE_KEYS, and
- * TCL_ONE_WORD_KEYS can be the same as TCL_CUSTOM_PTR_KEYS because they
- * simply determine how the key is accessed from the entry and not the
- * behaviour.
+ * While maintaining binary compatability the above have to be distinct values
+ * as they are used to differentiate between old versions of the hash table
+ * which don't have a typePtr and new ones which do. Once binary compatability
+ * is discarded in favour of making more wide spread changes TCL_STRING_KEYS
+ * can be the same as TCL_CUSTOM_TYPE_KEYS, and TCL_ONE_WORD_KEYS can be the
+ * same as TCL_CUSTOM_PTR_KEYS because they simply determine how the key is
+ * accessed from the entry and not the behaviour.
*/
#define TCL_STRING_KEYS 0
#define TCL_ONE_WORD_KEYS 1
-
-#if TCL_PRESERVE_BINARY_COMPATABILITY
-# define TCL_CUSTOM_TYPE_KEYS -2
-# define TCL_CUSTOM_PTR_KEYS -1
-#else
-# define TCL_CUSTOM_TYPE_KEYS TCL_STRING_KEYS
-# define TCL_CUSTOM_PTR_KEYS TCL_ONE_WORD_KEYS
-#endif
+#define TCL_CUSTOM_TYPE_KEYS -2
+#define TCL_CUSTOM_PTR_KEYS -1
/*
- * Macros for clients to use to access fields of hash entries:
+ * Structure definition for information used to keep track of searches through
+ * dictionaries. These fields should not be accessed by code outside
+ * tclDictObj.c
*/
-#define Tcl_GetHashValue(h) ((h)->clientData)
-#define Tcl_SetHashValue(h, value) ((h)->clientData = (ClientData) (value))
-#if TCL_PRESERVE_BINARY_COMPATABILITY
-# define Tcl_GetHashKey(tablePtr, h) \
- ((char *) (((tablePtr)->keyType == TCL_ONE_WORD_KEYS || \
- (tablePtr)->keyType == TCL_CUSTOM_PTR_KEYS) \
- ? (h)->key.oneWordValue \
- : (h)->key.string))
-#else
-# define Tcl_GetHashKey(tablePtr, h) \
- ((char *) (((tablePtr)->keyType == TCL_ONE_WORD_KEYS) \
- ? (h)->key.oneWordValue \
- : (h)->key.string))
-#endif
+typedef struct {
+ void *next; /* Search position for underlying hash
+ * table. */
+ int epoch; /* Epoch marker for dictionary being searched,
+ * or -1 if search has terminated. */
+ Tcl_Dict dictionaryPtr; /* Reference to dictionary being searched. */
+} Tcl_DictSearch;
/*
- * Macros to use for clients to use to invoke find and create procedures
- * for hash tables:
+ * Flag values to pass to Tcl_DoOneEvent to disable searches for some kinds of
+ * events:
*/
-#if TCL_PRESERVE_BINARY_COMPATABILITY
-# define Tcl_FindHashEntry(tablePtr, key) \
- (*((tablePtr)->findProc))(tablePtr, key)
-# define Tcl_CreateHashEntry(tablePtr, key, newPtr) \
- (*((tablePtr)->createProc))(tablePtr, key, newPtr)
-#else /* !TCL_PRESERVE_BINARY_COMPATABILITY */
-/*
- * Macro to use new extended version of Tcl_InitHashTable.
- */
-# define Tcl_InitHashTable(tablePtr, keyType) \
- Tcl_InitHashTableEx(tablePtr, keyType, NULL)
-#endif /* TCL_PRESERVE_BINARY_COMPATABILITY */
-
-
-/*
- * Flag values to pass to Tcl_DoOneEvent to disable searches
- * for some kinds of events:
- */
#define TCL_DONT_WAIT (1<<1)
#define TCL_WINDOW_EVENTS (1<<2)
#define TCL_FILE_EVENTS (1<<3)
@@ -1376,22 +1291,23 @@ typedef struct Tcl_HashSearch {
#define TCL_ALL_EVENTS (~TCL_DONT_WAIT)
/*
- * The following structure defines a generic event for the Tcl event
- * system. These are the things that are queued in calls to Tcl_QueueEvent
- * and serviced later by Tcl_DoOneEvent. There can be many different
- * kinds of events with different fields, corresponding to window events,
- * timer events, etc. The structure for a particular event consists of
- * a Tcl_Event header followed by additional information specific to that
- * event.
+ * The following structure defines a generic event for the Tcl event system.
+ * These are the things that are queued in calls to Tcl_QueueEvent and
+ * serviced later by Tcl_DoOneEvent. There can be many different kinds of
+ * events with different fields, corresponding to window events, timer events,
+ * etc. The structure for a particular event consists of a Tcl_Event header
+ * followed by additional information specific to that event.
*/
+
struct Tcl_Event {
- Tcl_EventProc *proc; /* Procedure to call to service this event. */
+ Tcl_EventProc *proc; /* Function to call to service this event. */
struct Tcl_Event *nextPtr; /* Next in list of pending events, or NULL. */
};
/*
* Positions to pass to Tcl_QueueEvent:
*/
+
typedef enum {
TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, TCL_QUEUE_MARK
} Tcl_QueuePosition;
@@ -1400,16 +1316,16 @@ typedef enum {
* Values to pass to Tcl_SetServiceMode to specify the behavior of notifier
* event routines.
*/
+
#define TCL_SERVICE_NONE 0
#define TCL_SERVICE_ALL 1
-
/*
- * The following structure keeps is used to hold a time value, either as
- * an absolute time (the number of seconds from the epoch) or as an
- * elapsed time. On Unix systems the epoch is Midnight Jan 1, 1970 GMT.
- * On Macintosh systems the epoch is Midnight Jan 1, 1904 GMT.
+ * The following structure keeps is used to hold a time value, either as an
+ * absolute time (the number of seconds from the epoch) or as an elapsed time.
+ * On Unix systems the epoch is Midnight Jan 1, 1970 GMT.
*/
+
typedef struct Tcl_Time {
long sec; /* Seconds. */
long usec; /* Microseconds. */
@@ -1418,21 +1334,31 @@ typedef struct Tcl_Time {
typedef void (Tcl_SetTimerProc) _ANSI_ARGS_((Tcl_Time *timePtr));
typedef int (Tcl_WaitForEventProc) _ANSI_ARGS_((Tcl_Time *timePtr));
+/*
+ * TIP #233 (Virtualized Time)
+ */
+
+typedef void (Tcl_GetTimeProc) _ANSI_ARGS_((Tcl_Time *timebuf,
+ ClientData clientData));
+typedef void (Tcl_ScaleTimeProc) _ANSI_ARGS_((Tcl_Time *timebuf,
+ ClientData clientData));
/*
- * Bits to pass to Tcl_CreateFileHandler and Tcl_CreateChannelHandler
- * to indicate what sorts of events are of interest:
+ * Bits to pass to Tcl_CreateFileHandler and Tcl_CreateChannelHandler to
+ * indicate what sorts of events are of interest:
*/
-#define TCL_READABLE (1<<1)
-#define TCL_WRITABLE (1<<2)
-#define TCL_EXCEPTION (1<<3)
+
+#define TCL_READABLE (1<<1)
+#define TCL_WRITABLE (1<<2)
+#define TCL_EXCEPTION (1<<3)
/*
- * Flag values to pass to Tcl_OpenCommandChannel to indicate the
- * disposition of the stdio handles. TCL_STDIN, TCL_STDOUT, TCL_STDERR,
- * are also used in Tcl_GetStdChannel.
+ * Flag values to pass to Tcl_OpenCommandChannel to indicate the disposition
+ * of the stdio handles. TCL_STDIN, TCL_STDOUT, TCL_STDERR, are also used in
+ * Tcl_GetStdChannel.
*/
-#define TCL_STDIN (1<<1)
+
+#define TCL_STDIN (1<<1)
#define TCL_STDOUT (1<<2)
#define TCL_STDERR (1<<3)
#define TCL_ENFORCE_MODE (1<<4)
@@ -1441,25 +1367,29 @@ typedef int (Tcl_WaitForEventProc) _ANSI_ARGS_((Tcl_Time *timePtr));
* Bits passed to Tcl_DriverClose2Proc to indicate which side of a channel
* should be closed.
*/
-#define TCL_CLOSE_READ (1<<1)
-#define TCL_CLOSE_WRITE (1<<2)
+
+#define TCL_CLOSE_READ (1<<1)
+#define TCL_CLOSE_WRITE (1<<2)
/*
- * Value to use as the closeProc for a channel that supports the
- * close2Proc interface.
+ * Value to use as the closeProc for a channel that supports the close2Proc
+ * interface.
*/
-#define TCL_CLOSE2PROC ((Tcl_DriverCloseProc *)1)
+
+#define TCL_CLOSE2PROC ((Tcl_DriverCloseProc *) 1)
/*
- * Channel version tag. This was introduced in 8.3.2/8.4.
+ * Channel version tag. This was introduced in 8.3.2/8.4.
*/
+
#define TCL_CHANNEL_VERSION_1 ((Tcl_ChannelTypeVersion) 0x1)
#define TCL_CHANNEL_VERSION_2 ((Tcl_ChannelTypeVersion) 0x2)
#define TCL_CHANNEL_VERSION_3 ((Tcl_ChannelTypeVersion) 0x3)
#define TCL_CHANNEL_VERSION_4 ((Tcl_ChannelTypeVersion) 0x4)
+#define TCL_CHANNEL_VERSION_5 ((Tcl_ChannelTypeVersion) 0x5)
/*
- * TIP #218: Channel Actions, Ids for Tcl_DriverThreadActionProc
+ * TIP #218: Channel Actions, Ids for Tcl_DriverThreadActionProc.
*/
#define TCL_CHANNEL_THREAD_INSERT (0)
@@ -1468,6 +1398,7 @@ typedef int (Tcl_WaitForEventProc) _ANSI_ARGS_((Tcl_Time *timePtr));
/*
* Typedefs for the various operations in a channel type:
*/
+
typedef int (Tcl_DriverBlockModeProc) _ANSI_ARGS_((
ClientData instanceData, int mode));
typedef int (Tcl_DriverCloseProc) _ANSI_ARGS_((ClientData instanceData,
@@ -1482,7 +1413,7 @@ typedef int (Tcl_DriverSeekProc) _ANSI_ARGS_((ClientData instanceData,
long offset, int mode, int *errorCodePtr));
typedef int (Tcl_DriverSetOptionProc) _ANSI_ARGS_((
ClientData instanceData, Tcl_Interp *interp,
- CONST char *optionName, CONST char *value));
+ CONST char *optionName, CONST char *value));
typedef int (Tcl_DriverGetOptionProc) _ANSI_ARGS_((
ClientData instanceData, Tcl_Interp *interp,
CONST84 char *optionName, Tcl_DString *dsPtr));
@@ -1491,124 +1422,111 @@ typedef void (Tcl_DriverWatchProc) _ANSI_ARGS_((
typedef int (Tcl_DriverGetHandleProc) _ANSI_ARGS_((
ClientData instanceData, int direction,
ClientData *handlePtr));
-typedef int (Tcl_DriverFlushProc) _ANSI_ARGS_((
- ClientData instanceData));
+typedef int (Tcl_DriverFlushProc) _ANSI_ARGS_((ClientData instanceData));
typedef int (Tcl_DriverHandlerProc) _ANSI_ARGS_((
ClientData instanceData, int interestMask));
typedef Tcl_WideInt (Tcl_DriverWideSeekProc) _ANSI_ARGS_((
ClientData instanceData, Tcl_WideInt offset,
int mode, int *errorCodePtr));
-
- /* TIP #218, Channel Thread Actions */
-typedef void (Tcl_DriverThreadActionProc) _ANSI_ARGS_ ((
- ClientData instanceData, int action));
-
/*
- * The following declarations either map ckalloc and ckfree to
- * malloc and free, or they map them to procedures with all sorts
- * of debugging hooks defined in tclCkalloc.c.
+ * TIP #218, Channel Thread Actions
*/
-#ifdef TCL_MEM_DEBUG
-
-# define ckalloc(x) Tcl_DbCkalloc(x, __FILE__, __LINE__)
-# define ckfree(x) Tcl_DbCkfree(x, __FILE__, __LINE__)
-# define ckrealloc(x,y) Tcl_DbCkrealloc((x), (y),__FILE__, __LINE__)
-# define attemptckalloc(x) Tcl_AttemptDbCkalloc(x, __FILE__, __LINE__)
-# define attemptckrealloc(x,y) Tcl_AttemptDbCkrealloc((x), (y), __FILE__, __LINE__)
-#else /* !TCL_MEM_DEBUG */
-
+typedef void (Tcl_DriverThreadActionProc) _ANSI_ARGS_ ((
+ ClientData instanceData, int action));
/*
- * If we are not using the debugging allocator, we should call the
- * Tcl_Alloc, et al. routines in order to guarantee that every module
- * is using the same memory allocator both inside and outside of the
- * Tcl library.
+ * TIP #208, File Truncation (etc.)
*/
-# define ckalloc(x) Tcl_Alloc(x)
-# define ckfree(x) Tcl_Free(x)
-# define ckrealloc(x,y) Tcl_Realloc(x,y)
-# define attemptckalloc(x) Tcl_AttemptAlloc(x)
-# define attemptckrealloc(x,y) Tcl_AttemptRealloc(x,y)
-# define Tcl_InitMemory(x)
-# define Tcl_DumpActiveMemory(x)
-# define Tcl_ValidateAllMemory(x,y)
-
-#endif /* !TCL_MEM_DEBUG */
+typedef int (Tcl_DriverTruncateProc) _ANSI_ARGS_((
+ ClientData instanceData, Tcl_WideInt length));
/*
* struct Tcl_ChannelType:
*
- * One such structure exists for each type (kind) of channel.
- * It collects together in one place all the functions that are
- * part of the specific channel type.
+ * One such structure exists for each type (kind) of channel. It collects
+ * together in one place all the functions that are part of the specific
+ * channel type.
*
- * It is recommend that the Tcl_Channel* functions are used to access
- * elements of this structure, instead of direct accessing.
+ * It is recommend that the Tcl_Channel* functions are used to access elements
+ * of this structure, instead of direct accessing.
*/
+
typedef struct Tcl_ChannelType {
- char *typeName; /* The name of the channel type in Tcl
- * commands. This storage is owned by
- * channel type. */
- Tcl_ChannelTypeVersion version; /* Version of the channel type. */
- Tcl_DriverCloseProc *closeProc; /* Procedure to call to close the
- * channel, or TCL_CLOSE2PROC if the
- * close2Proc should be used
- * instead. */
- Tcl_DriverInputProc *inputProc; /* Procedure to call for input
- * on channel. */
- Tcl_DriverOutputProc *outputProc; /* Procedure to call for output
- * on channel. */
- Tcl_DriverSeekProc *seekProc; /* Procedure to call to seek
- * on the channel. May be NULL. */
+ char *typeName; /* The name of the channel type in Tcl
+ * commands. This storage is owned by channel
+ * type. */
+ Tcl_ChannelTypeVersion version;
+ /* Version of the channel type. */
+ Tcl_DriverCloseProc *closeProc;
+ /* Function to call to close the channel, or
+ * TCL_CLOSE2PROC if the close2Proc should be
+ * used instead. */
+ Tcl_DriverInputProc *inputProc;
+ /* Function to call for input on channel. */
+ Tcl_DriverOutputProc *outputProc;
+ /* Function to call for output on channel. */
+ Tcl_DriverSeekProc *seekProc;
+ /* Function to call to seek on the channel.
+ * May be NULL. */
Tcl_DriverSetOptionProc *setOptionProc;
- /* Set an option on a channel. */
+ /* Set an option on a channel. */
Tcl_DriverGetOptionProc *getOptionProc;
- /* Get an option from a channel. */
- Tcl_DriverWatchProc *watchProc; /* Set up the notifier to watch
- * for events on this channel. */
+ /* Get an option from a channel. */
+ Tcl_DriverWatchProc *watchProc;
+ /* Set up the notifier to watch for events on
+ * this channel. */
Tcl_DriverGetHandleProc *getHandleProc;
- /* Get an OS handle from the channel
- * or NULL if not supported. */
- Tcl_DriverClose2Proc *close2Proc; /* Procedure to call to close the
- * channel if the device supports
- * closing the read & write sides
- * independently. */
+ /* Get an OS handle from the channel or NULL
+ * if not supported. */
+ Tcl_DriverClose2Proc *close2Proc;
+ /* Function to call to close the channel if
+ * the device supports closing the read &
+ * write sides independently. */
Tcl_DriverBlockModeProc *blockModeProc;
- /* Set blocking mode for the
- * raw channel. May be NULL. */
+ /* Set blocking mode for the raw channel. May
+ * be NULL. */
/*
- * Only valid in TCL_CHANNEL_VERSION_2 channels or later
+ * Only valid in TCL_CHANNEL_VERSION_2 channels or later.
*/
- Tcl_DriverFlushProc *flushProc; /* Procedure to call to flush a
- * channel. May be NULL. */
- Tcl_DriverHandlerProc *handlerProc; /* Procedure to call to handle a
- * channel event. This will be passed
- * up the stacked channel chain. */
+ Tcl_DriverFlushProc *flushProc;
+ /* Function to call to flush a channel. May be
+ * NULL. */
+ Tcl_DriverHandlerProc *handlerProc;
+ /* Function to call to handle a channel event.
+ * This will be passed up the stacked channel
+ * chain. */
/*
- * Only valid in TCL_CHANNEL_VERSION_3 channels or later
+ * Only valid in TCL_CHANNEL_VERSION_3 channels or later.
*/
Tcl_DriverWideSeekProc *wideSeekProc;
- /* Procedure to call to seek
- * on the channel which can
- * handle 64-bit offsets. May be
- * NULL, and must be NULL if
- * seekProc is NULL. */
-
- /*
- * Only valid in TCL_CHANNEL_VERSION_4 channels or later
- * TIP #218, Channel Thread Actions
- */
- Tcl_DriverThreadActionProc *threadActionProc;
- /* Procedure to call to notify
- * the driver of thread specific
- * activity for a channel.
- * May be NULL. */
+ /* Function to call to seek on the channel
+ * which can handle 64-bit offsets. May be
+ * NULL, and must be NULL if seekProc is
+ * NULL. */
+ /*
+ * Only valid in TCL_CHANNEL_VERSION_4 channels or later.
+ * TIP #218, Channel Thread Actions.
+ */
+ Tcl_DriverThreadActionProc *threadActionProc;
+ /* Function to call to notify the driver of
+ * thread specific activity for a channel. May
+ * be NULL. */
+
+ /*
+ * Only valid in TCL_CHANNEL_VERSION_5 channels or later.
+ * TIP #208, File Truncation.
+ */
+ Tcl_DriverTruncateProc *truncateProc;
+ /* Function to call to truncate the underlying
+ * file to a particular length. May be NULL if
+ * the channel does not support truncation. */
} Tcl_ChannelType;
/*
- * The following flags determine whether the blockModeProc above should
- * set the channel into blocking or nonblocking mode. They are passed
- * as arguments to the blockModeProc procedure in the above structure.
+ * The following flags determine whether the blockModeProc above should set
+ * the channel into blocking or nonblocking mode. They are passed as arguments
+ * to the blockModeProc function in the above structure.
*/
+
#define TCL_MODE_BLOCKING 0 /* Put channel into blocking mode. */
#define TCL_MODE_NONBLOCKING 1 /* Put channel into nonblocking
* mode. */
@@ -1616,31 +1534,29 @@ typedef struct Tcl_ChannelType {
/*
* Enum for different types of file paths.
*/
+
typedef enum Tcl_PathType {
TCL_PATH_ABSOLUTE,
TCL_PATH_RELATIVE,
TCL_PATH_VOLUME_RELATIVE
} Tcl_PathType;
-
-/*
- * The following structure is used to pass glob type data amongst
- * the various glob routines and Tcl_FSMatchInDirectory.
+/*
+ * The following structure is used to pass glob type data amongst the various
+ * glob routines and Tcl_FSMatchInDirectory.
*/
+
typedef struct Tcl_GlobTypeData {
- /* Corresponds to bcdpfls as in 'find -t' */
- int type;
- /* Corresponds to file permissions */
- int perm;
- /* Acceptable mac type */
- Tcl_Obj* macType;
- /* Acceptable mac creator */
- Tcl_Obj* macCreator;
+ int type; /* Corresponds to bcdpfls as in 'find -t'. */
+ int perm; /* Corresponds to file permissions. */
+ Tcl_Obj *macType; /* Acceptable Mac type. */
+ Tcl_Obj *macCreator; /* Acceptable Mac creator. */
} Tcl_GlobTypeData;
/*
- * type and permission definitions for glob command
+ * Type and permission definitions for glob command.
*/
+
#define TCL_GLOB_TYPE_BLOCK (1<<0)
#define TCL_GLOB_TYPE_CHAR (1<<1)
#define TCL_GLOB_TYPE_DIR (1<<2)
@@ -1656,66 +1572,70 @@ typedef struct Tcl_GlobTypeData {
#define TCL_GLOB_PERM_W (1<<3)
#define TCL_GLOB_PERM_X (1<<4)
+/*
+ * Flags for the unload callback function.
+ */
+
+#define TCL_UNLOAD_DETACH_FROM_INTERPRETER (1<<0)
+#define TCL_UNLOAD_DETACH_FROM_PROCESS (1<<1)
/*
* Typedefs for the various filesystem operations:
*/
+
typedef int (Tcl_FSStatProc) _ANSI_ARGS_((Tcl_Obj *pathPtr, Tcl_StatBuf *buf));
typedef int (Tcl_FSAccessProc) _ANSI_ARGS_((Tcl_Obj *pathPtr, int mode));
-typedef Tcl_Channel (Tcl_FSOpenFileChannelProc)
- _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *pathPtr,
- int mode, int permissions));
-typedef int (Tcl_FSMatchInDirectoryProc) _ANSI_ARGS_((Tcl_Interp* interp,
- Tcl_Obj *result, Tcl_Obj *pathPtr, CONST char *pattern,
+typedef Tcl_Channel (Tcl_FSOpenFileChannelProc) _ANSI_ARGS_((
+ Tcl_Interp *interp, Tcl_Obj *pathPtr, int mode, int permissions));
+typedef int (Tcl_FSMatchInDirectoryProc) _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *result, Tcl_Obj *pathPtr, CONST char *pattern,
Tcl_GlobTypeData * types));
-typedef Tcl_Obj* (Tcl_FSGetCwdProc) _ANSI_ARGS_((Tcl_Interp *interp));
+typedef Tcl_Obj * (Tcl_FSGetCwdProc) _ANSI_ARGS_((Tcl_Interp *interp));
typedef int (Tcl_FSChdirProc) _ANSI_ARGS_((Tcl_Obj *pathPtr));
-typedef int (Tcl_FSLstatProc) _ANSI_ARGS_((Tcl_Obj *pathPtr,
- Tcl_StatBuf *buf));
+typedef int (Tcl_FSLstatProc) _ANSI_ARGS_((Tcl_Obj *pathPtr,
+ Tcl_StatBuf *buf));
typedef int (Tcl_FSCreateDirectoryProc) _ANSI_ARGS_((Tcl_Obj *pathPtr));
typedef int (Tcl_FSDeleteFileProc) _ANSI_ARGS_((Tcl_Obj *pathPtr));
typedef int (Tcl_FSCopyDirectoryProc) _ANSI_ARGS_((Tcl_Obj *srcPathPtr,
- Tcl_Obj *destPathPtr, Tcl_Obj **errorPtr));
+ Tcl_Obj *destPathPtr, Tcl_Obj **errorPtr));
typedef int (Tcl_FSCopyFileProc) _ANSI_ARGS_((Tcl_Obj *srcPathPtr,
- Tcl_Obj *destPathPtr));
+ Tcl_Obj *destPathPtr));
typedef int (Tcl_FSRemoveDirectoryProc) _ANSI_ARGS_((Tcl_Obj *pathPtr,
- int recursive, Tcl_Obj **errorPtr));
+ int recursive, Tcl_Obj **errorPtr));
typedef int (Tcl_FSRenameFileProc) _ANSI_ARGS_((Tcl_Obj *srcPathPtr,
- Tcl_Obj *destPathPtr));
+ Tcl_Obj *destPathPtr));
typedef void (Tcl_FSUnloadFileProc) _ANSI_ARGS_((Tcl_LoadHandle loadHandle));
-typedef Tcl_Obj* (Tcl_FSListVolumesProc) _ANSI_ARGS_((void));
+typedef Tcl_Obj * (Tcl_FSListVolumesProc) _ANSI_ARGS_((void));
/* We have to declare the utime structure here. */
struct utimbuf;
-typedef int (Tcl_FSUtimeProc) _ANSI_ARGS_((Tcl_Obj *pathPtr,
- struct utimbuf *tval));
-typedef int (Tcl_FSNormalizePathProc) _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *pathPtr, int nextCheckpoint));
+typedef int (Tcl_FSUtimeProc) _ANSI_ARGS_((Tcl_Obj *pathPtr,
+ struct utimbuf *tval));
+typedef int (Tcl_FSNormalizePathProc) _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *pathPtr, int nextCheckpoint));
typedef int (Tcl_FSFileAttrsGetProc) _ANSI_ARGS_((Tcl_Interp *interp,
- int index, Tcl_Obj *pathPtr,
- Tcl_Obj **objPtrRef));
-typedef CONST char** (Tcl_FSFileAttrStringsProc) _ANSI_ARGS_((Tcl_Obj *pathPtr,
- Tcl_Obj** objPtrRef));
+ int index, Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef));
+typedef CONST char ** (Tcl_FSFileAttrStringsProc) _ANSI_ARGS_((
+ Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef));
typedef int (Tcl_FSFileAttrsSetProc) _ANSI_ARGS_((Tcl_Interp *interp,
- int index, Tcl_Obj *pathPtr,
- Tcl_Obj *objPtr));
-typedef Tcl_Obj* (Tcl_FSLinkProc) _ANSI_ARGS_((Tcl_Obj *pathPtr,
- Tcl_Obj *toPtr, int linkType));
-typedef int (Tcl_FSLoadFileProc) _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj *pathPtr,
- Tcl_LoadHandle *handlePtr,
- Tcl_FSUnloadFileProc **unloadProcPtr));
-typedef int (Tcl_FSPathInFilesystemProc) _ANSI_ARGS_((Tcl_Obj *pathPtr,
- ClientData *clientDataPtr));
-typedef Tcl_Obj* (Tcl_FSFilesystemPathTypeProc)
- _ANSI_ARGS_((Tcl_Obj *pathPtr));
-typedef Tcl_Obj* (Tcl_FSFilesystemSeparatorProc)
- _ANSI_ARGS_((Tcl_Obj *pathPtr));
+ int index, Tcl_Obj *pathPtr, Tcl_Obj *objPtr));
+typedef Tcl_Obj * (Tcl_FSLinkProc) _ANSI_ARGS_((Tcl_Obj *pathPtr,
+ Tcl_Obj *toPtr, int linkType));
+typedef int (Tcl_FSLoadFileProc) _ANSI_ARGS_((Tcl_Interp * interp,
+ Tcl_Obj *pathPtr, Tcl_LoadHandle *handlePtr,
+ Tcl_FSUnloadFileProc **unloadProcPtr));
+typedef int (Tcl_FSPathInFilesystemProc) _ANSI_ARGS_((Tcl_Obj *pathPtr,
+ ClientData *clientDataPtr));
+typedef Tcl_Obj * (Tcl_FSFilesystemPathTypeProc) _ANSI_ARGS_((
+ Tcl_Obj *pathPtr));
+typedef Tcl_Obj * (Tcl_FSFilesystemSeparatorProc) _ANSI_ARGS_((
+ Tcl_Obj *pathPtr));
typedef void (Tcl_FSFreeInternalRepProc) _ANSI_ARGS_((ClientData clientData));
-typedef ClientData (Tcl_FSDupInternalRepProc)
- _ANSI_ARGS_((ClientData clientData));
-typedef Tcl_Obj* (Tcl_FSInternalToNormalizedProc)
- _ANSI_ARGS_((ClientData clientData));
-typedef ClientData (Tcl_FSCreateInternalRepProc) _ANSI_ARGS_((Tcl_Obj *pathPtr));
+typedef ClientData (Tcl_FSDupInternalRepProc) _ANSI_ARGS_((
+ ClientData clientData));
+typedef Tcl_Obj * (Tcl_FSInternalToNormalizedProc) _ANSI_ARGS_((
+ ClientData clientData));
+typedef ClientData (Tcl_FSCreateInternalRepProc) _ANSI_ARGS_((
+ Tcl_Obj *pathPtr));
typedef struct Tcl_FSVersion_ *Tcl_FSVersion;
@@ -1733,207 +1653,183 @@ typedef struct Tcl_FSVersion_ *Tcl_FSVersion;
/*
* struct Tcl_Filesystem:
*
- * One such structure exists for each type (kind) of filesystem.
- * It collects together in one place all the functions that are
- * part of the specific filesystem. Tcl always accesses the
- * filesystem through one of these structures.
- *
- * Not all entries need be non-NULL; any which are NULL are simply
- * ignored. However, a complete filesystem should provide all of
- * these functions. The explanations in the structure show
- * the importance of each function.
+ * One such structure exists for each type (kind) of filesystem. It collects
+ * together in one place all the functions that are part of the specific
+ * filesystem. Tcl always accesses the filesystem through one of these
+ * structures.
+ *
+ * Not all entries need be non-NULL; any which are NULL are simply ignored.
+ * However, a complete filesystem should provide all of these functions. The
+ * explanations in the structure show the importance of each function.
*/
typedef struct Tcl_Filesystem {
- CONST char *typeName; /* The name of the filesystem. */
- int structureLength; /* Length of this structure, so future
- * binary compatibility can be assured. */
- Tcl_FSVersion version;
- /* Version of the filesystem type. */
+ CONST char *typeName; /* The name of the filesystem. */
+ int structureLength; /* Length of this structure, so future binary
+ * compatibility can be assured. */
+ Tcl_FSVersion version; /* Version of the filesystem type. */
Tcl_FSPathInFilesystemProc *pathInFilesystemProc;
- /* Function to check whether a path is in
- * this filesystem. This is the most
- * important filesystem procedure. */
+ /* Function to check whether a path is in this
+ * filesystem. This is the most important
+ * filesystem function. */
Tcl_FSDupInternalRepProc *dupInternalRepProc;
- /* Function to duplicate internal fs rep. May
- * be NULL (but then fs is less efficient). */
+ /* Function to duplicate internal fs rep. May
+ * be NULL (but then fs is less efficient). */
Tcl_FSFreeInternalRepProc *freeInternalRepProc;
- /* Function to free internal fs rep. Must
- * be implemented, if internal representations
- * need freeing, otherwise it can be NULL. */
+ /* Function to free internal fs rep. Must be
+ * implemented if internal representations
+ * need freeing, otherwise it can be NULL. */
Tcl_FSInternalToNormalizedProc *internalToNormalizedProc;
- /* Function to convert internal representation
- * to a normalized path. Only required if
- * the fs creates pure path objects with no
- * string/path representation. */
+ /* Function to convert internal representation
+ * to a normalized path. Only required if the
+ * fs creates pure path objects with no
+ * string/path representation. */
Tcl_FSCreateInternalRepProc *createInternalRepProc;
- /* Function to create a filesystem-specific
- * internal representation. May be NULL
- * if paths have no internal representation,
- * or if the Tcl_FSPathInFilesystemProc
- * for this filesystem always immediately
- * creates an internal representation for
- * paths it accepts. */
- Tcl_FSNormalizePathProc *normalizePathProc;
- /* Function to normalize a path. Should
- * be implemented for all filesystems
- * which can have multiple string
- * representations for the same path
- * object. */
+ /* Function to create a filesystem-specific
+ * internal representation. May be NULL if
+ * paths have no internal representation, or
+ * if the Tcl_FSPathInFilesystemProc for this
+ * filesystem always immediately creates an
+ * internal representation for paths it
+ * accepts. */
+ Tcl_FSNormalizePathProc *normalizePathProc;
+ /* Function to normalize a path. Should be
+ * implemented for all filesystems which can
+ * have multiple string representations for
+ * the same path object. */
Tcl_FSFilesystemPathTypeProc *filesystemPathTypeProc;
- /* Function to determine the type of a
- * path in this filesystem. May be NULL. */
+ /* Function to determine the type of a path in
+ * this filesystem. May be NULL. */
Tcl_FSFilesystemSeparatorProc *filesystemSeparatorProc;
- /* Function to return the separator
- * character(s) for this filesystem. Must
- * be implemented. */
- Tcl_FSStatProc *statProc;
- /*
- * Function to process a 'Tcl_FSStat()'
- * call. Must be implemented for any
- * reasonable filesystem.
- */
- Tcl_FSAccessProc *accessProc;
- /*
- * Function to process a 'Tcl_FSAccess()'
- * call. Must be implemented for any
- * reasonable filesystem.
- */
- Tcl_FSOpenFileChannelProc *openFileChannelProc;
- /*
- * Function to process a
- * 'Tcl_FSOpenFileChannel()' call. Must be
- * implemented for any reasonable
- * filesystem.
- */
- Tcl_FSMatchInDirectoryProc *matchInDirectoryProc;
- /* Function to process a
- * 'Tcl_FSMatchInDirectory()'. If not
- * implemented, then glob and recursive
- * copy functionality will be lacking in
- * the filesystem. */
- Tcl_FSUtimeProc *utimeProc;
- /* Function to process a
- * 'Tcl_FSUtime()' call. Required to
- * allow setting (not reading) of times
- * with 'file mtime', 'file atime' and
- * the open-r/open-w/fcopy implementation
- * of 'file copy'. */
- Tcl_FSLinkProc *linkProc;
- /* Function to process a
- * 'Tcl_FSLink()' call. Should be
- * implemented only if the filesystem supports
- * links (reading or creating). */
- Tcl_FSListVolumesProc *listVolumesProc;
- /* Function to list any filesystem volumes
- * added by this filesystem. Should be
- * implemented only if the filesystem adds
- * volumes at the head of the filesystem. */
+ /* Function to return the separator
+ * character(s) for this filesystem. Must be
+ * implemented. */
+ Tcl_FSStatProc *statProc; /* Function to process a 'Tcl_FSStat()' call.
+ * Must be implemented for any reasonable
+ * filesystem. */
+ Tcl_FSAccessProc *accessProc;
+ /* Function to process a 'Tcl_FSAccess()'
+ * call. Must be implemented for any
+ * reasonable filesystem. */
+ Tcl_FSOpenFileChannelProc *openFileChannelProc;
+ /* Function to process a
+ * 'Tcl_FSOpenFileChannel()' call. Must be
+ * implemented for any reasonable
+ * filesystem. */
+ Tcl_FSMatchInDirectoryProc *matchInDirectoryProc;
+ /* Function to process a
+ * 'Tcl_FSMatchInDirectory()'. If not
+ * implemented, then glob and recursive copy
+ * functionality will be lacking in the
+ * filesystem. */
+ Tcl_FSUtimeProc *utimeProc; /* Function to process a 'Tcl_FSUtime()' call.
+ * Required to allow setting (not reading) of
+ * times with 'file mtime', 'file atime' and
+ * the open-r/open-w/fcopy implementation of
+ * 'file copy'. */
+ Tcl_FSLinkProc *linkProc; /* Function to process a 'Tcl_FSLink()' call.
+ * Should be implemented only if the
+ * filesystem supports links (reading or
+ * creating). */
+ Tcl_FSListVolumesProc *listVolumesProc;
+ /* Function to list any filesystem volumes
+ * added by this filesystem. Should be
+ * implemented only if the filesystem adds
+ * volumes at the head of the filesystem. */
Tcl_FSFileAttrStringsProc *fileAttrStringsProc;
- /* Function to list all attributes strings
- * which are valid for this filesystem.
- * If not implemented the filesystem will
- * not support the 'file attributes' command.
- * This allows arbitrary additional information
- * to be attached to files in the filesystem. */
+ /* Function to list all attributes strings
+ * which are valid for this filesystem. If not
+ * implemented the filesystem will not support
+ * the 'file attributes' command. This allows
+ * arbitrary additional information to be
+ * attached to files in the filesystem. */
Tcl_FSFileAttrsGetProc *fileAttrsGetProc;
- /* Function to process a
- * 'Tcl_FSFileAttrsGet()' call, used by
- * 'file attributes'. */
+ /* Function to process a
+ * 'Tcl_FSFileAttrsGet()' call, used by 'file
+ * attributes'. */
Tcl_FSFileAttrsSetProc *fileAttrsSetProc;
- /* Function to process a
- * 'Tcl_FSFileAttrsSet()' call, used by
- * 'file attributes'. */
- Tcl_FSCreateDirectoryProc *createDirectoryProc;
- /* Function to process a
- * 'Tcl_FSCreateDirectory()' call. Should
- * be implemented unless the FS is
- * read-only. */
- Tcl_FSRemoveDirectoryProc *removeDirectoryProc;
- /* Function to process a
- * 'Tcl_FSRemoveDirectory()' call. Should
- * be implemented unless the FS is
- * read-only. */
- Tcl_FSDeleteFileProc *deleteFileProc;
- /* Function to process a
- * 'Tcl_FSDeleteFile()' call. Should
- * be implemented unless the FS is
- * read-only. */
- Tcl_FSCopyFileProc *copyFileProc;
- /* Function to process a
- * 'Tcl_FSCopyFile()' call. If not
- * implemented Tcl will fall back
- * on open-r, open-w and fcopy as
- * a copying mechanism, for copying
- * actions initiated in Tcl (not C). */
- Tcl_FSRenameFileProc *renameFileProc;
- /* Function to process a
- * 'Tcl_FSRenameFile()' call. If not
- * implemented, Tcl will fall back on
- * a copy and delete mechanism, for
- * rename actions initiated in Tcl (not C). */
- Tcl_FSCopyDirectoryProc *copyDirectoryProc;
- /* Function to process a
- * 'Tcl_FSCopyDirectory()' call. If
- * not implemented, Tcl will fall back
- * on a recursive create-dir, file copy
- * mechanism, for copying actions
- * initiated in Tcl (not C). */
- Tcl_FSLstatProc *lstatProc;
- /* Function to process a
- * 'Tcl_FSLstat()' call. If not implemented,
- * Tcl will attempt to use the 'statProc'
- * defined above instead. */
- Tcl_FSLoadFileProc *loadFileProc;
- /* Function to process a
- * 'Tcl_FSLoadFile()' call. If not
- * implemented, Tcl will fall back on
- * a copy to native-temp followed by a
- * Tcl_FSLoadFile on that temporary copy. */
- Tcl_FSGetCwdProc *getCwdProc;
- /*
- * Function to process a 'Tcl_FSGetCwd()'
- * call. Most filesystems need not
- * implement this. It will usually only be
- * called once, if 'getcwd' is called
- * before 'chdir'. May be NULL.
- */
- Tcl_FSChdirProc *chdirProc;
- /*
- * Function to process a 'Tcl_FSChdir()'
- * call. If filesystems do not implement
- * this, it will be emulated by a series of
- * directory access checks. Otherwise,
- * virtual filesystems which do implement
- * it need only respond with a positive
- * return result if the dirName is a valid
- * directory in their filesystem. They
- * need not remember the result, since that
- * will be automatically remembered for use
- * by GetCwd. Real filesystems should
- * carry out the correct action (i.e. call
- * the correct system 'chdir' api). If not
- * implemented, then 'cd' and 'pwd' will
- * fail inside the filesystem.
- */
+ /* Function to process a
+ * 'Tcl_FSFileAttrsSet()' call, used by 'file
+ * attributes'. */
+ Tcl_FSCreateDirectoryProc *createDirectoryProc;
+ /* Function to process a
+ * 'Tcl_FSCreateDirectory()' call. Should be
+ * implemented unless the FS is read-only. */
+ Tcl_FSRemoveDirectoryProc *removeDirectoryProc;
+ /* Function to process a
+ * 'Tcl_FSRemoveDirectory()' call. Should be
+ * implemented unless the FS is read-only. */
+ Tcl_FSDeleteFileProc *deleteFileProc;
+ /* Function to process a 'Tcl_FSDeleteFile()'
+ * call. Should be implemented unless the FS
+ * is read-only. */
+ Tcl_FSCopyFileProc *copyFileProc;
+ /* Function to process a 'Tcl_FSCopyFile()'
+ * call. If not implemented Tcl will fall back
+ * on open-r, open-w and fcopy as a copying
+ * mechanism, for copying actions initiated in
+ * Tcl (not C). */
+ Tcl_FSRenameFileProc *renameFileProc;
+ /* Function to process a 'Tcl_FSRenameFile()'
+ * call. If not implemented, Tcl will fall
+ * back on a copy and delete mechanism, for
+ * rename actions initiated in Tcl (not C). */
+ Tcl_FSCopyDirectoryProc *copyDirectoryProc;
+ /* Function to process a
+ * 'Tcl_FSCopyDirectory()' call. If not
+ * implemented, Tcl will fall back on a
+ * recursive create-dir, file copy mechanism,
+ * for copying actions initiated in Tcl (not
+ * C). */
+ Tcl_FSLstatProc *lstatProc; /* Function to process a 'Tcl_FSLstat()' call.
+ * If not implemented, Tcl will attempt to use
+ * the 'statProc' defined above instead. */
+ Tcl_FSLoadFileProc *loadFileProc;
+ /* Function to process a 'Tcl_FSLoadFile()'
+ * call. If not implemented, Tcl will fall
+ * back on a copy to native-temp followed by a
+ * Tcl_FSLoadFile on that temporary copy. */
+ Tcl_FSGetCwdProc *getCwdProc;
+ /* Function to process a 'Tcl_FSGetCwd()'
+ * call. Most filesystems need not implement
+ * this. It will usually only be called once,
+ * if 'getcwd' is called before 'chdir'. May
+ * be NULL. */
+ Tcl_FSChdirProc *chdirProc; /* Function to process a 'Tcl_FSChdir()' call.
+ * If filesystems do not implement this, it
+ * will be emulated by a series of directory
+ * access checks. Otherwise, virtual
+ * filesystems which do implement it need only
+ * respond with a positive return result if
+ * the dirName is a valid directory in their
+ * filesystem. They need not remember the
+ * result, since that will be automatically
+ * remembered for use by GetCwd. Real
+ * filesystems should carry out the correct
+ * action (i.e. call the correct system
+ * 'chdir' api). If not implemented, then 'cd'
+ * and 'pwd' will fail inside the
+ * filesystem. */
} Tcl_Filesystem;
/*
- * The following definitions are used as values for the 'linkAction' flag
- * to Tcl_FSLink, or the linkProc of any filesystem. Any combination
- * of flags can be given. For link creation, the linkProc should create
- * a link which matches any of the types given.
- *
- * TCL_CREATE_SYMBOLIC_LINK: Create a symbolic or soft link.
- * TCL_CREATE_HARD_LINK: Create a hard link.
+ * The following definitions are used as values for the 'linkAction' flag to
+ * Tcl_FSLink, or the linkProc of any filesystem. Any combination of flags can
+ * be given. For link creation, the linkProc should create a link which
+ * matches any of the types given.
+ *
+ * TCL_CREATE_SYMBOLIC_LINK - Create a symbolic or soft link.
+ * TCL_CREATE_HARD_LINK - Create a hard link.
*/
-#define TCL_CREATE_SYMBOLIC_LINK 0x01
-#define TCL_CREATE_HARD_LINK 0x02
+
+#define TCL_CREATE_SYMBOLIC_LINK 0x01
+#define TCL_CREATE_HARD_LINK 0x02
/*
- * The following structure represents the Notifier functions that
- * you can override with the Tcl_SetNotifier call.
+ * The following structure represents the Notifier functions that you can
+ * override with the Tcl_SetNotifier call.
*/
+
typedef struct Tcl_NotifierProcs {
Tcl_SetTimerProc *setTimerProc;
Tcl_WaitForEventProc *waitForEventProc;
@@ -1945,164 +1841,160 @@ typedef struct Tcl_NotifierProcs {
Tcl_ServiceModeHookProc *serviceModeHookProc;
} Tcl_NotifierProcs;
-
/*
- * The following structure represents a user-defined encoding. It collects
+ * The following structure represents a user-defined encoding. It collects
* together all the functions that are used by the specific encoding.
*/
+
typedef struct Tcl_EncodingType {
- CONST char *encodingName; /* The name of the encoding, e.g. "euc-jp".
+ CONST char *encodingName; /* The name of the encoding, e.g. "euc-jp".
* This name is the unique key for this
* encoding type. */
Tcl_EncodingConvertProc *toUtfProc;
- /* Procedure to convert from external
- * encoding into UTF-8. */
+ /* Function to convert from external encoding
+ * into UTF-8. */
Tcl_EncodingConvertProc *fromUtfProc;
- /* Procedure to convert from UTF-8 into
+ /* Function to convert from UTF-8 into
* external encoding. */
Tcl_EncodingFreeProc *freeProc;
- /* If non-NULL, procedure to call when this
+ /* If non-NULL, function to call when this
* encoding is deleted. */
ClientData clientData; /* Arbitrary value associated with encoding
- * type. Passed to conversion procedures. */
+ * type. Passed to conversion functions. */
int nullSize; /* Number of zero bytes that signify
- * end-of-string in this encoding. This
- * number is used to determine the source
- * string length when the srcLen argument is
- * negative. Must be 1 or 2. */
-} Tcl_EncodingType;
+ * end-of-string in this encoding. This number
+ * is used to determine the source string
+ * length when the srcLen argument is
+ * negative. Must be 1 or 2. */
+} Tcl_EncodingType;
/*
* The following definitions are used as values for the conversion control
* flags argument when converting text from one character set to another:
*
- * TCL_ENCODING_START: Signifies that the source buffer is the first
+ * TCL_ENCODING_START - Signifies that the source buffer is the first
* block in a (potentially multi-block) input
- * stream. Tells the conversion procedure to
- * reset to an initial state and perform any
+ * stream. Tells the conversion function to reset
+ * to an initial state and perform any
* initialization that needs to occur before the
- * first byte is converted. If the source
- * buffer contains the entire input stream to be
+ * first byte is converted. If the source buffer
+ * contains the entire input stream to be
* converted, this flag should be set.
- *
- * TCL_ENCODING_END: Signifies that the source buffer is the last
+ * TCL_ENCODING_END - Signifies that the source buffer is the last
* block in a (potentially multi-block) input
- * stream. Tells the conversion routine to
+ * stream. Tells the conversion routine to
* perform any finalization that needs to occur
* after the last byte is converted and then to
- * reset to an initial state. If the source
+ * reset to an initial state. If the source
* buffer contains the entire input stream to be
* converted, this flag should be set.
- *
- * TCL_ENCODING_STOPONERROR: If set, then the converter will return
- * immediately upon encountering an invalid
- * byte sequence or a source character that has
- * no mapping in the target encoding. If clear,
- * then the converter will skip the problem,
- * substituting one or more "close" characters
- * in the destination buffer and then continue
- * to sonvert the source.
+ * TCL_ENCODING_STOPONERROR - If set, then the converter will return
+ * immediately upon encountering an invalid byte
+ * sequence or a source character that has no
+ * mapping in the target encoding. If clear, then
+ * the converter will skip the problem,
+ * substituting one or more "close" characters in
+ * the destination buffer and then continue to
+ * convert the source.
*/
+
#define TCL_ENCODING_START 0x01
#define TCL_ENCODING_END 0x02
#define TCL_ENCODING_STOPONERROR 0x04
-
/*
- * The following data structures and declarations are for the new Tcl
- * parser.
+ * The following data structures and declarations are for the new Tcl parser.
*/
/*
- * For each word of a command, and for each piece of a word such as a
- * variable reference, one of the following structures is created to
- * describe the token.
+ * For each word of a command, and for each piece of a word such as a variable
+ * reference, one of the following structures is created to describe the
+ * token.
*/
+
typedef struct Tcl_Token {
- int type; /* Type of token, such as TCL_TOKEN_WORD;
- * see below for valid types. */
+ int type; /* Type of token, such as TCL_TOKEN_WORD; see
+ * below for valid types. */
CONST char *start; /* First character in token. */
int size; /* Number of bytes in token. */
- int numComponents; /* If this token is composed of other
- * tokens, this field tells how many of
- * them there are (including components of
- * components, etc.). The component tokens
- * immediately follow this one. */
+ int numComponents; /* If this token is composed of other tokens,
+ * this field tells how many of them there are
+ * (including components of components, etc.).
+ * The component tokens immediately follow
+ * this one. */
} Tcl_Token;
/*
- * Type values defined for Tcl_Token structures. These values are
- * defined as mask bits so that it's easy to check for collections of
- * types.
+ * Type values defined for Tcl_Token structures. These values are defined as
+ * mask bits so that it's easy to check for collections of types.
*
* TCL_TOKEN_WORD - The token describes one word of a command,
- * from the first non-blank character of
- * the word (which may be " or {) up to but
- * not including the space, semicolon, or
- * bracket that terminates the word.
- * NumComponents counts the total number of
- * sub-tokens that make up the word. This
- * includes, for example, sub-tokens of
- * TCL_TOKEN_VARIABLE tokens.
- * TCL_TOKEN_SIMPLE_WORD - This token is just like TCL_TOKEN_WORD
- * except that the word is guaranteed to
- * consist of a single TCL_TOKEN_TEXT
- * sub-token.
- * TCL_TOKEN_TEXT - The token describes a range of literal
- * text that is part of a word.
- * NumComponents is always 0.
- * TCL_TOKEN_BS - The token describes a backslash sequence
- * that must be collapsed. NumComponents
- * is always 0.
+ * from the first non-blank character of the word
+ * (which may be " or {) up to but not including
+ * the space, semicolon, or bracket that
+ * terminates the word. NumComponents counts the
+ * total number of sub-tokens that make up the
+ * word. This includes, for example, sub-tokens
+ * of TCL_TOKEN_VARIABLE tokens.
+ * TCL_TOKEN_SIMPLE_WORD - This token is just like TCL_TOKEN_WORD except
+ * that the word is guaranteed to consist of a
+ * single TCL_TOKEN_TEXT sub-token.
+ * TCL_TOKEN_TEXT - The token describes a range of literal text
+ * that is part of a word. NumComponents is
+ * always 0.
+ * TCL_TOKEN_BS - The token describes a backslash sequence that
+ * must be collapsed. NumComponents is always 0.
* TCL_TOKEN_COMMAND - The token describes a command whose result
- * must be substituted into the word. The
- * token includes the enclosing brackets.
- * NumComponents is always 0.
- * TCL_TOKEN_VARIABLE - The token describes a variable
- * substitution, including the dollar sign,
- * variable name, and array index (if there
- * is one) up through the right
- * parentheses. NumComponents tells how
- * many additional tokens follow to
- * represent the variable name. The first
- * token will be a TCL_TOKEN_TEXT token
- * that describes the variable name. If
- * the variable is an array reference then
- * there will be one or more additional
- * tokens, of type TCL_TOKEN_TEXT,
+ * must be substituted into the word. The token
+ * includes the enclosing brackets. NumComponents
+ * is always 0.
+ * TCL_TOKEN_VARIABLE - The token describes a variable substitution,
+ * including the dollar sign, variable name, and
+ * array index (if there is one) up through the
+ * right parentheses. NumComponents tells how
+ * many additional tokens follow to represent the
+ * variable name. The first token will be a
+ * TCL_TOKEN_TEXT token that describes the
+ * variable name. If the variable is an array
+ * reference then there will be one or more
+ * additional tokens, of type TCL_TOKEN_TEXT,
* TCL_TOKEN_BS, TCL_TOKEN_COMMAND, and
- * TCL_TOKEN_VARIABLE, that describe the
- * array index; numComponents counts the
- * total number of nested tokens that make
- * up the variable reference, including
- * sub-tokens of TCL_TOKEN_VARIABLE tokens.
- * TCL_TOKEN_SUB_EXPR - The token describes one subexpression of a
- * expression, from the first non-blank
- * character of the subexpression up to but not
- * including the space, brace, or bracket
- * that terminates the subexpression.
- * NumComponents counts the total number of
- * following subtokens that make up the
- * subexpression; this includes all subtokens
- * for any nested TCL_TOKEN_SUB_EXPR tokens.
- * For example, a numeric value used as a
+ * TCL_TOKEN_VARIABLE, that describe the array
+ * index; numComponents counts the total number
+ * of nested tokens that make up the variable
+ * reference, including sub-tokens of
+ * TCL_TOKEN_VARIABLE tokens.
+ * TCL_TOKEN_SUB_EXPR - The token describes one subexpression of an
+ * expression, from the first non-blank character
+ * of the subexpression up to but not including
+ * the space, brace, or bracket that terminates
+ * the subexpression. NumComponents counts the
+ * total number of following subtokens that make
+ * up the subexpression; this includes all
+ * subtokens for any nested TCL_TOKEN_SUB_EXPR
+ * tokens. For example, a numeric value used as a
* primitive operand is described by a
* TCL_TOKEN_SUB_EXPR token followed by a
* TCL_TOKEN_TEXT token. A binary subexpression
* is described by a TCL_TOKEN_SUB_EXPR token
- * followed by the TCL_TOKEN_OPERATOR token
- * for the operator, then TCL_TOKEN_SUB_EXPR
- * tokens for the left then the right operands.
+ * followed by the TCL_TOKEN_OPERATOR token for
+ * the operator, then TCL_TOKEN_SUB_EXPR tokens
+ * for the left then the right operands.
* TCL_TOKEN_OPERATOR - The token describes one expression operator.
* An operator might be the name of a math
* function such as "abs". A TCL_TOKEN_OPERATOR
* token is always preceeded by one
* TCL_TOKEN_SUB_EXPR token for the operator's
- * subexpression, and is followed by zero or
- * more TCL_TOKEN_SUB_EXPR tokens for the
- * operator's operands. NumComponents is
- * always 0.
+ * subexpression, and is followed by zero or more
+ * TCL_TOKEN_SUB_EXPR tokens for the operator's
+ * operands. NumComponents is always 0.
+ * TCL_TOKEN_EXPAND_WORD - This token is just like TCL_TOKEN_WORD except
+ * that it marks a word that began with the
+ * literal character prefix "{*}". This word is
+ * marked to be expanded - that is, broken into
+ * words after substitution is complete.
*/
+
#define TCL_TOKEN_WORD 1
#define TCL_TOKEN_SIMPLE_WORD 2
#define TCL_TOKEN_TEXT 4
@@ -2111,12 +2003,13 @@ typedef struct Tcl_Token {
#define TCL_TOKEN_VARIABLE 32
#define TCL_TOKEN_SUB_EXPR 64
#define TCL_TOKEN_OPERATOR 128
+#define TCL_TOKEN_EXPAND_WORD 256
/*
- * Parsing error types. On any parsing error, one of these values
- * will be stored in the error field of the Tcl_Parse structure
- * defined below.
+ * Parsing error types. On any parsing error, one of these values will be
+ * stored in the error field of the Tcl_Parse structure defined below.
*/
+
#define TCL_PARSE_SUCCESS 0
#define TCL_PARSE_QUOTE_EXTRA 1
#define TCL_PARSE_BRACE_EXTRA 2
@@ -2129,31 +2022,32 @@ typedef struct Tcl_Token {
#define TCL_PARSE_BAD_NUMBER 9
/*
- * A structure of the following type is filled in by Tcl_ParseCommand.
- * It describes a single command parsed from an input string.
+ * A structure of the following type is filled in by Tcl_ParseCommand. It
+ * describes a single command parsed from an input string.
*/
+
#define NUM_STATIC_TOKENS 20
typedef struct Tcl_Parse {
- CONST char *commentStart; /* Pointer to # that begins the first of
- * one or more comments preceding the
- * command. */
+ CONST char *commentStart; /* Pointer to # that begins the first of one
+ * or more comments preceding the command. */
int commentSize; /* Number of bytes in comments (up through
- * newline character that terminates the
- * last comment). If there were no
- * comments, this field is 0. */
- CONST char *commandStart; /* First character in first word of command. */
- int commandSize; /* Number of bytes in command, including
- * first character of first word, up
- * through the terminating newline,
- * close bracket, or semicolon. */
- int numWords; /* Total number of words in command. May
- * be 0. */
- Tcl_Token *tokenPtr; /* Pointer to first token representing
- * the words of the command. Initially
- * points to staticTokens, but may change
- * to point to malloc-ed space if command
- * exceeds space in staticTokens. */
+ * newline character that terminates the last
+ * comment). If there were no comments, this
+ * field is 0. */
+ CONST char *commandStart; /* First character in first word of
+ * command. */
+ int commandSize; /* Number of bytes in command, including first
+ * character of first word, up through the
+ * terminating newline, close bracket, or
+ * semicolon. */
+ int numWords; /* Total number of words in command. May be
+ * 0. */
+ Tcl_Token *tokenPtr; /* Pointer to first token representing the
+ * words of the command. Initially points to
+ * staticTokens, but may change to point to
+ * malloc-ed space if command exceeds space in
+ * staticTokens. */
int numTokens; /* Total number of tokens in command. */
int tokensAvailable; /* Total number of tokens available at
* *tokenPtr. */
@@ -2161,94 +2055,91 @@ typedef struct Tcl_Parse {
* above. */
/*
- * The fields below are intended only for the private use of the
- * parser. They should not be used by procedures that invoke
- * Tcl_ParseCommand.
+ * The fields below are intended only for the private use of the parser.
+ * They should not be used by functions that invoke Tcl_ParseCommand.
*/
CONST char *string; /* The original command string passed to
* Tcl_ParseCommand. */
- CONST char *end; /* Points to the character just after the
- * last one in the command string. */
- Tcl_Interp *interp; /* Interpreter to use for error reporting,
- * or NULL. */
+ CONST char *end; /* Points to the character just after the last
+ * one in the command string. */
+ Tcl_Interp *interp; /* Interpreter to use for error reporting, or
+ * NULL. */
CONST char *term; /* Points to character in string that
- * terminated most recent token. Filled in
- * by ParseTokens. If an error occurs,
- * points to beginning of region where the
- * error occurred (e.g. the open brace if
- * the close brace is missing). */
+ * terminated most recent token. Filled in by
+ * ParseTokens. If an error occurs, points to
+ * beginning of region where the error
+ * occurred (e.g. the open brace if the close
+ * brace is missing). */
int incomplete; /* This field is set to 1 by Tcl_ParseCommand
* if the command appears to be incomplete.
* This information is used by
* Tcl_CommandComplete. */
Tcl_Token staticTokens[NUM_STATIC_TOKENS];
- /* Initial space for tokens for command.
- * This space should be large enough to
- * accommodate most commands; dynamic
- * space is allocated for very large
- * commands that don't fit here. */
+ /* Initial space for tokens for command. This
+ * space should be large enough to accommodate
+ * most commands; dynamic space is allocated
+ * for very large commands that don't fit
+ * here. */
} Tcl_Parse;
/*
* The following definitions are the error codes returned by the conversion
* routines:
*
- * TCL_OK: All characters were converted.
- *
- * TCL_CONVERT_NOSPACE: The output buffer would not have been large
+ * TCL_OK - All characters were converted.
+ * TCL_CONVERT_NOSPACE - The output buffer would not have been large
* enough for all of the converted data; as many
* characters as could fit were converted though.
- *
- * TCL_CONVERT_MULTIBYTE: The last few bytes in the source string were
+ * TCL_CONVERT_MULTIBYTE - The last few bytes in the source string were
* the beginning of a multibyte sequence, but
* more bytes were needed to complete this
- * sequence. A subsequent call to the conversion
+ * sequence. A subsequent call to the conversion
* routine should pass the beginning of this
* unconverted sequence plus additional bytes
- * from the source stream to properly convert
- * the formerly split-up multibyte sequence.
- *
- * TCL_CONVERT_SYNTAX: The source stream contained an invalid
- * character sequence. This may occur if the
+ * from the source stream to properly convert the
+ * formerly split-up multibyte sequence.
+ * TCL_CONVERT_SYNTAX - The source stream contained an invalid
+ * character sequence. This may occur if the
* input stream has been damaged or if the input
- * encoding method was misidentified. This error
+ * encoding method was misidentified. This error
* is reported only if TCL_ENCODING_STOPONERROR
* was specified.
- *
- * TCL_CONVERT_UNKNOWN: The source string contained a character
- * that could not be represented in the target
- * encoding. This error is reported only if
+ * TCL_CONVERT_UNKNOWN - The source string contained a character that
+ * could not be represented in the target
+ * encoding. This error is reported only if
* TCL_ENCODING_STOPONERROR was specified.
*/
-#define TCL_CONVERT_MULTIBYTE -1
-#define TCL_CONVERT_SYNTAX -2
-#define TCL_CONVERT_UNKNOWN -3
-#define TCL_CONVERT_NOSPACE -4
+
+#define TCL_CONVERT_MULTIBYTE -1
+#define TCL_CONVERT_SYNTAX -2
+#define TCL_CONVERT_UNKNOWN -3
+#define TCL_CONVERT_NOSPACE -4
/*
* The maximum number of bytes that are necessary to represent a single
- * Unicode character in UTF-8. The valid values should be 3 or 6 (or
- * perhaps 1 if we want to support a non-unicode enabled core).
- * If 3, then Tcl_UniChar must be 2-bytes in size (UCS-2). (default)
- * If 6, then Tcl_UniChar must be 4-bytes in size (UCS-4).
- * At this time UCS-2 mode is the default and recommended mode.
- * UCS-4 is experimental and not recommended. It works for the core,
- * but most extensions expect UCS-2.
+ * Unicode character in UTF-8. The valid values should be 3 or 6 (or perhaps 1
+ * if we want to support a non-unicode enabled core). If 3, then Tcl_UniChar
+ * must be 2-bytes in size (UCS-2) (the default). If 6, then Tcl_UniChar must
+ * be 4-bytes in size (UCS-4). At this time UCS-2 mode is the default and
+ * recommended mode. UCS-4 is experimental and not recommended. It works for
+ * the core, but most extensions expect UCS-2.
*/
+
#ifndef TCL_UTF_MAX
#define TCL_UTF_MAX 3
#endif
/*
- * This represents a Unicode character. Any changes to this should
- * also be reflected in regcustom.h.
+ * This represents a Unicode character. Any changes to this should also be
+ * reflected in regcustom.h.
*/
+
#if TCL_UTF_MAX > 3
/*
- * unsigned int isn't 100% accurate as it should be a strict 4-byte
- * value (perhaps wchar_t). 64-bit systems may have troubles. The
- * size of this value must be reflected correctly in regcustom.h and
+ * unsigned int isn't 100% accurate as it should be a strict 4-byte value
+ * (perhaps wchar_t). 64-bit systems may have troubles. The size of this
+ * value must be reflected correctly in regcustom.h and
* in tclEncoding.c.
* XXX: Tcl is currently UCS-2 and planning UTF-16 for the Unicode
* XXX: string rep that Tcl_UniChar represents. Changing the size
@@ -2259,51 +2150,62 @@ typedef unsigned int Tcl_UniChar;
typedef unsigned short Tcl_UniChar;
#endif
+/*
+ * TIP #59: The following structure is used in calls 'Tcl_RegisterConfig' to
+ * provide the system with the embedded configuration data.
+ */
+
+typedef struct Tcl_Config {
+ CONST char *key; /* Configuration key to register. ASCII
+ * encoded, thus UTF-8. */
+ CONST char *value; /* The value associated with the key. System
+ * encoding. */
+} Tcl_Config;
/*
- * Deprecated Tcl procedures:
+ * Flags for TIP#143 limits, detailing which limits are active in an
+ * interpreter. Used for Tcl_{Add,Remove}LimitHandler type argument.
*/
-#ifndef TCL_NO_DEPRECATED
-# define Tcl_EvalObj(interp,objPtr) \
- Tcl_EvalObjEx((interp),(objPtr),0)
-# define Tcl_GlobalEvalObj(interp,objPtr) \
- Tcl_EvalObjEx((interp),(objPtr),TCL_EVAL_GLOBAL)
-#endif
+#define TCL_LIMIT_COMMANDS 0x01
+#define TCL_LIMIT_TIME 0x02
/*
- * These function have been renamed. The old names are deprecated, but we
- * define these macros for backwards compatibilty.
+ * Structure containing information about a limit handler to be called when a
+ * command- or time-limit is exceeded by an interpreter.
*/
-#define Tcl_Ckalloc Tcl_Alloc
-#define Tcl_Ckfree Tcl_Free
-#define Tcl_Ckrealloc Tcl_Realloc
-#define Tcl_Return Tcl_SetResult
-#define Tcl_TildeSubst Tcl_TranslateFileName
-#define panic Tcl_Panic
-#define panicVA Tcl_PanicVA
+typedef void (Tcl_LimitHandlerProc) _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp));
+typedef void (Tcl_LimitHandlerDeleteProc) _ANSI_ARGS_((ClientData clientData));
+
+typedef struct mp_int mp_int;
+#define MP_INT_DECLARED
+typedef unsigned int mp_digit;
+#define MP_DIGIT_DECLARED
/*
- * The following constant is used to test for older versions of Tcl
- * in the stubs tables.
+ * The following constant is used to test for older versions of Tcl in the
+ * stubs tables.
*
* Jan Nijtman's plus patch uses 0xFCA1BACF, so we need to pick a different
* value since the stubs tables don't match.
*/
-#define TCL_STUB_MAGIC ((int)0xFCA3BACF)
+#define TCL_STUB_MAGIC ((int) 0xFCA3BACF)
/*
* The following function is required to be defined in all stubs aware
- * extensions. The function is actually implemented in the stub
- * library, not the main Tcl library, although there is a trivial
- * implementation in the main library in case an extension is statically
- * linked into an application.
+ * extensions. The function is actually implemented in the stub library, not
+ * the main Tcl library, although there is a trivial implementation in the
+ * main library in case an extension is statically linked into an application.
*/
EXTERN CONST char * Tcl_InitStubs _ANSI_ARGS_((Tcl_Interp *interp,
CONST char *version, int exact));
+EXTERN CONST char * TclTomMathInitializeStubs _ANSI_ARGS_((
+ Tcl_Interp *interp, CONST char *version,
+ int epoch, int revision));
#ifndef USE_TCL_STUBS
@@ -2312,50 +2214,213 @@ EXTERN CONST char * Tcl_InitStubs _ANSI_ARGS_((Tcl_Interp *interp,
*/
#define Tcl_InitStubs(interp, version, exact) \
- Tcl_PkgRequire(interp, "Tcl", version, exact)
+ Tcl_PkgInitStubsCheck(interp, version, exact)
#endif
+ /*
+ * TODO - tommath stubs export goes here!
+ */
+
/*
- * Include the public function declarations that are accessible via
- * the stubs table.
+ * Public functions that are not accessible via the stubs table.
+ * Tcl_GetMemoryInfo is needed for AOLserver. [Bug 1868171]
*/
-#include "tclDecls.h"
+EXTERN void Tcl_Main _ANSI_ARGS_((int argc, char **argv,
+ Tcl_AppInitProc *appInitProc));
+EXTERN CONST char * Tcl_PkgInitStubsCheck _ANSI_ARGS_((Tcl_Interp *interp,
+ CONST char *version, int exact));
+#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
+EXTERN void Tcl_GetMemoryInfo _ANSI_ARGS_((Tcl_DString *dsPtr));
+#endif
/*
- * Include platform specific public function declarations that are
- * accessible via the stubs table.
+ * Include the public function declarations that are accessible via the stubs
+ * table.
*/
+#include "tclDecls.h"
+
/*
- * tclPlatDecls.h can't be included here on the Mac, as we need
- * Mac specific headers to define the Mac types used in this file,
- * but these Mac haders conflict with a number of tk types
- * and thus can't be included in the globally read tcl.h
- * This header was originally added here as a fix for bug 5241
- * (stub link error for symbols in TclPlatStubs table), as a work-
- * around for the bug on the mac, tclMac.h is included immediately
- * after tcl.h in the tcl precompiled header (with DLLEXPORT set).
+ * Include platform specific public function declarations that are accessible
+ * via the stubs table.
*/
-#if !defined(MAC_TCL)
#include "tclPlatDecls.h"
+
+/*
+ * The following declarations either map ckalloc and ckfree to malloc and
+ * free, or they map them to functions with all sorts of debugging hooks
+ * defined in tclCkalloc.c.
+ */
+
+#ifdef TCL_MEM_DEBUG
+
+# define ckalloc(x) Tcl_DbCkalloc(x, __FILE__, __LINE__)
+# define ckfree(x) Tcl_DbCkfree(x, __FILE__, __LINE__)
+# define ckrealloc(x,y) Tcl_DbCkrealloc((x), (y),__FILE__, __LINE__)
+# define attemptckalloc(x) Tcl_AttemptDbCkalloc(x, __FILE__, __LINE__)
+# define attemptckrealloc(x,y) Tcl_AttemptDbCkrealloc((x), (y), __FILE__, __LINE__)
+
+#else /* !TCL_MEM_DEBUG */
+
+/*
+ * If we are not using the debugging allocator, we should call the Tcl_Alloc,
+ * et al. routines in order to guarantee that every module is using the same
+ * memory allocator both inside and outside of the Tcl library.
+ */
+
+# define ckalloc(x) Tcl_Alloc(x)
+# define ckfree(x) Tcl_Free(x)
+# define ckrealloc(x,y) Tcl_Realloc(x,y)
+# define attemptckalloc(x) Tcl_AttemptAlloc(x)
+# define attemptckrealloc(x,y) Tcl_AttemptRealloc(x,y)
+# undef Tcl_InitMemory
+# define Tcl_InitMemory(x)
+# undef Tcl_DumpActiveMemory
+# define Tcl_DumpActiveMemory(x)
+# undef Tcl_ValidateAllMemory
+# define Tcl_ValidateAllMemory(x,y)
+
+#endif /* !TCL_MEM_DEBUG */
+
+#ifdef TCL_MEM_DEBUG
+# define Tcl_IncrRefCount(objPtr) \
+ Tcl_DbIncrRefCount(objPtr, __FILE__, __LINE__)
+# define Tcl_DecrRefCount(objPtr) \
+ Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__)
+# define Tcl_IsShared(objPtr) \
+ Tcl_DbIsShared(objPtr, __FILE__, __LINE__)
+#else
+# define Tcl_IncrRefCount(objPtr) \
+ ++(objPtr)->refCount
+ /*
+ * Use do/while0 idiom for optimum correctness without compiler warnings.
+ * http://c2.com/cgi/wiki?TrivialDoWhileLoop
+ */
+# define Tcl_DecrRefCount(objPtr) \
+ do { if (--(objPtr)->refCount <= 0) TclFreeObj(objPtr); } while(0)
+# define Tcl_IsShared(objPtr) \
+ ((objPtr)->refCount > 1)
#endif
/*
- * Public functions that are not accessible via the stubs table.
+ * Macros and definitions that help to debug the use of Tcl objects. When
+ * TCL_MEM_DEBUG is defined, the Tcl_New declarations are overridden to call
+ * debugging versions of the object creation functions.
*/
-EXTERN void Tcl_Main _ANSI_ARGS_((int argc, char **argv,
- Tcl_AppInitProc *appInitProc));
+#ifdef TCL_MEM_DEBUG
+# undef Tcl_NewBignumObj
+# define Tcl_NewBignumObj(val) \
+ Tcl_DbNewBignumObj(val, __FILE__, __LINE__)
+# undef Tcl_NewBooleanObj
+# define Tcl_NewBooleanObj(val) \
+ Tcl_DbNewBooleanObj(val, __FILE__, __LINE__)
+# undef Tcl_NewByteArrayObj
+# define Tcl_NewByteArrayObj(bytes, len) \
+ Tcl_DbNewByteArrayObj(bytes, len, __FILE__, __LINE__)
+# undef Tcl_NewDoubleObj
+# define Tcl_NewDoubleObj(val) \
+ Tcl_DbNewDoubleObj(val, __FILE__, __LINE__)
+# undef Tcl_NewIntObj
+# define Tcl_NewIntObj(val) \
+ Tcl_DbNewLongObj(val, __FILE__, __LINE__)
+# undef Tcl_NewListObj
+# define Tcl_NewListObj(objc, objv) \
+ Tcl_DbNewListObj(objc, objv, __FILE__, __LINE__)
+# undef Tcl_NewLongObj
+# define Tcl_NewLongObj(val) \
+ Tcl_DbNewLongObj(val, __FILE__, __LINE__)
+# undef Tcl_NewObj
+# define Tcl_NewObj() \
+ Tcl_DbNewObj(__FILE__, __LINE__)
+# undef Tcl_NewStringObj
+# define Tcl_NewStringObj(bytes, len) \
+ Tcl_DbNewStringObj(bytes, len, __FILE__, __LINE__)
+# undef Tcl_NewWideIntObj
+# define Tcl_NewWideIntObj(val) \
+ Tcl_DbNewWideIntObj(val, __FILE__, __LINE__)
+#endif /* TCL_MEM_DEBUG */
/*
- * Convenience declaration of Tcl_AppInit for backwards compatibility.
- * This function is not *implemented* by the tcl library, so the storage
- * class is neither DLLEXPORT nor DLLIMPORT
+ * Macros for clients to use to access fields of hash entries:
*/
+
+#define Tcl_GetHashValue(h) ((h)->clientData)
+#define Tcl_SetHashValue(h, value) ((h)->clientData = (ClientData) (value))
+#define Tcl_GetHashKey(tablePtr, h) \
+ ((char *) (((tablePtr)->keyType == TCL_ONE_WORD_KEYS || \
+ (tablePtr)->keyType == TCL_CUSTOM_PTR_KEYS) \
+ ? (h)->key.oneWordValue \
+ : (h)->key.string))
+
+/*
+ * Macros to use for clients to use to invoke find and create functions for
+ * hash tables:
+ */
+
+#undef Tcl_FindHashEntry
+#define Tcl_FindHashEntry(tablePtr, key) \
+ (*((tablePtr)->findProc))(tablePtr, key)
+#undef Tcl_CreateHashEntry
+#define Tcl_CreateHashEntry(tablePtr, key, newPtr) \
+ (*((tablePtr)->createProc))(tablePtr, key, newPtr)
+
+/*
+ * Macros that eliminate the overhead of the thread synchronization functions
+ * when compiling without thread support.
+ */
+
+#ifndef TCL_THREADS
+#undef Tcl_MutexLock
+#define Tcl_MutexLock(mutexPtr)
+#undef Tcl_MutexUnlock
+#define Tcl_MutexUnlock(mutexPtr)
+#undef Tcl_MutexFinalize
+#define Tcl_MutexFinalize(mutexPtr)
+#undef Tcl_ConditionNotify
+#define Tcl_ConditionNotify(condPtr)
+#undef Tcl_ConditionWait
+#define Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
+#undef Tcl_ConditionFinalize
+#define Tcl_ConditionFinalize(condPtr)
+#endif /* TCL_THREADS */
+
+#ifndef TCL_NO_DEPRECATED
+ /*
+ * Deprecated Tcl functions:
+ */
+
+# undef Tcl_EvalObj
+# define Tcl_EvalObj(interp,objPtr) \
+ Tcl_EvalObjEx((interp),(objPtr),0)
+# undef Tcl_GlobalEvalObj
+# define Tcl_GlobalEvalObj(interp,objPtr) \
+ Tcl_EvalObjEx((interp),(objPtr),TCL_EVAL_GLOBAL)
+
+ /*
+ * These function have been renamed. The old names are deprecated, but we
+ * define these macros for backwards compatibilty.
+ */
+
+# define Tcl_Ckalloc Tcl_Alloc
+# define Tcl_Ckfree Tcl_Free
+# define Tcl_Ckrealloc Tcl_Realloc
+# define Tcl_Return Tcl_SetResult
+# define Tcl_TildeSubst Tcl_TranslateFileName
+# define panic Tcl_Panic
+# define panicVA Tcl_PanicVA
+#endif
+
+/*
+ * Convenience declaration of Tcl_AppInit for backwards compatibility. This
+ * function is not *implemented* by the tcl library, so the storage class is
+ * neither DLLEXPORT nor DLLIMPORT.
+ */
+
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS
@@ -2369,8 +2434,17 @@ EXTERN int Tcl_AppInit _ANSI_ARGS_((Tcl_Interp *interp));
/*
* end block for C++
*/
+
#ifdef __cplusplus
}
#endif
#endif /* _TCL */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclAlloc.c b/generic/tclAlloc.c
index 5022618..7647b4d 100644
--- a/generic/tclAlloc.c
+++ b/generic/tclAlloc.c
@@ -1,10 +1,10 @@
-/*
+/*
* tclAlloc.c --
*
- * This is a very fast storage allocator. It allocates blocks of a
- * small number of different sizes, and keeps free lists of each size.
- * Blocks that don't exactly fit are passed up to the next larger size.
- * Blocks over a certain size are directly allocated from the system.
+ * This is a very fast storage allocator. It allocates blocks of a small
+ * number of different sizes, and keeps free lists of each size. Blocks
+ * that don't exactly fit are passed up to the next larger size. Blocks
+ * over a certain size are directly allocated from the system.
*
* Copyright (c) 1983 Regents of the University of California.
* Copyright (c) 1996-1997 Sun Microsystems, Inc.
@@ -12,8 +12,8 @@
*
* Portions contributed by Chris Kingsley, Jack Jansen and Ray Johnson.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
/*
@@ -21,10 +21,8 @@
* that has significantly reduced lock contention.
*/
-#if !defined(TCL_THREADS) || !defined(USE_THREAD_ALLOC) || defined(TCL_MEM_DEBUG)
-
#include "tclInt.h"
-#include "tclPort.h"
+#if !defined(TCL_THREADS) || !defined(USE_THREAD_ALLOC)
#if USE_TCLALLOC
@@ -35,58 +33,49 @@
#endif
/*
- * We should really make use of AC_CHECK_TYPE(caddr_t)
- * here, but it can wait until Tcl uses config.h properly.
- */
-#if defined(MAC_TCL) || defined(_MSC_VER) || defined(__MINGW32__) || defined(__BORLANDC__)
-typedef unsigned long caddr_t;
-#endif
-
-/*
- * Alignment for allocated memory.
+ * We should really make use of AC_CHECK_TYPE(caddr_t) here, but it can wait
+ * until Tcl uses config.h properly.
*/
-#if defined(__APPLE__)
-#define ALLOCALIGN 16
-#else
-#define ALLOCALIGN 8
+#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__BORLANDC__)
+typedef unsigned long caddr_t;
#endif
/*
- * The overhead on a block is at least 8 bytes. When free, this space
- * contains a pointer to the next free block, and the bottom two bits must
- * be zero. When in use, the first byte is set to MAGIC, and the second
- * byte is the size index. The remaining bytes are for alignment.
- * If range checking is enabled then a second word holds the size of the
- * requested block, less 1, rounded up to a multiple of sizeof(RMAGIC).
- * The order of elements is critical: ov_magic must overlay the low order
- * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern.
+ * The overhead on a block is at least 8 bytes. When free, this space contains
+ * a pointer to the next free block, and the bottom two bits must be zero.
+ * When in use, the first byte is set to MAGIC, and the second byte is the
+ * size index. The remaining bytes are for alignment. If range checking is
+ * enabled then a second word holds the size of the requested block, less 1,
+ * rounded up to a multiple of sizeof(RMAGIC). The order of elements is
+ * critical: ov.magic must overlay the low order bits of ov.next, and ov.magic
+ * can not be a valid ov.next bit pattern.
*/
union overhead {
- union overhead *ov_next; /* when free */
- unsigned char ov_padding[ALLOCALIGN];/* align struct to ALLOCALIGN bytes */
+ union overhead *next; /* when free */
+ unsigned char padding[TCL_ALLOCALIGN]; /* align struct to TCL_ALLOCALIGN bytes */
struct {
- unsigned char ovu_magic0; /* magic number */
- unsigned char ovu_index; /* bucket # */
- unsigned char ovu_unused; /* unused */
- unsigned char ovu_magic1; /* other magic number */
+ unsigned char magic0; /* magic number */
+ unsigned char index; /* bucket # */
+ unsigned char unused; /* unused */
+ unsigned char magic1; /* other magic number */
#ifdef RCHECK
- unsigned short ovu_rmagic; /* range magic number */
- unsigned long ovu_size; /* actual block size */
- unsigned short ovu_unused2; /* padding to 8-byte align */
+ unsigned short rmagic; /* range magic number */
+ unsigned long size; /* actual block size */
+ unsigned short unused2; /* padding to 8-byte align */
#endif
} ovu;
-#define ov_magic0 ovu.ovu_magic0
-#define ov_magic1 ovu.ovu_magic1
-#define ov_index ovu.ovu_index
-#define ov_rmagic ovu.ovu_rmagic
-#define ov_size ovu.ovu_size
+#define overMagic0 ovu.magic0
+#define overMagic1 ovu.magic1
+#define bucketIndex ovu.index
+#define rangeCheckMagic ovu.rmagic
+#define realBlockSize ovu.size
};
-#define MAGIC 0xef /* magic # on accounting info */
-#define RMAGIC 0x5555 /* magic # on range info */
+#define MAGIC 0xef /* magic # on accounting info */
+#define RMAGIC 0x5555 /* magic # on range info */
#ifdef RCHECK
#define RSLOP sizeof (unsigned short)
@@ -97,38 +86,45 @@ union overhead {
#define OVERHEAD (sizeof(union overhead) + RSLOP)
/*
- * nextf[i] is the pointer to the next free block of size 2^(i+3). The
+ * Macro to make it easier to refer to the end-of-block guard magic.
+ */
+
+#define BLOCK_END(overPtr) \
+ (*(unsigned short *)((caddr_t)((overPtr) + 1) + (overPtr)->realBlockSize))
+
+/*
+ * nextf[i] is the pointer to the next free block of size 2^(i+3). The
* smallest allocatable block is MINBLOCK bytes. The overhead information
* precedes the data area returned to the user.
*/
-#define MINBLOCK ((sizeof(union overhead) + (ALLOCALIGN-1)) & ~(ALLOCALIGN-1))
+#define MINBLOCK ((sizeof(union overhead) + (TCL_ALLOCALIGN-1)) & ~(TCL_ALLOCALIGN-1))
#define NBUCKETS (13 - (MINBLOCK >> 4))
#define MAXMALLOC (1<<(NBUCKETS+2))
-static union overhead *nextf[NBUCKETS];
+static union overhead *nextf[NBUCKETS];
-/*
- * The following structure is used to keep track of all system memory
- * currently owned by Tcl. When finalizing, all this memory will
- * be returned to the system.
+/*
+ * The following structure is used to keep track of all system memory
+ * currently owned by Tcl. When finalizing, all this memory will be returned
+ * to the system.
*/
struct block {
struct block *nextPtr; /* Linked list. */
- struct block *prevPtr; /* Linked list for big blocks, ensures 8-byte
+ struct block *prevPtr; /* Linked list for big blocks, ensures 8-byte
* alignment for suballocated blocks. */
};
-static struct block *blockList; /* Tracks the suballocated blocks. */
-static struct block bigBlocks = { /* Big blocks aren't suballocated. */
+static struct block *blockList; /* Tracks the suballocated blocks. */
+static struct block bigBlocks={ /* Big blocks aren't suballocated. */
&bigBlocks, &bigBlocks
};
/*
- * The allocator is protected by a special mutex that must be
- * explicitly initialized. Futhermore, because Tcl_Alloc may be
- * used before anything else in Tcl, we make this module self-initializing
- * after all with the allocInit variable.
+ * The allocator is protected by a special mutex that must be explicitly
+ * initialized. Futhermore, because Tcl_Alloc may be used before anything else
+ * in Tcl, we make this module self-initializing after all with the allocInit
+ * variable.
*/
#ifdef TCL_THREADS
@@ -136,21 +132,20 @@ static Tcl_Mutex *allocMutexPtr;
#endif
static int allocInit = 0;
-
#ifdef MSTATS
/*
- * nmalloc[i] is the difference between the number of mallocs and frees
- * for a given block size.
+ * numMallocs[i] is the difference between the number of mallocs and frees for
+ * a given block size.
*/
-static unsigned int nmalloc[NBUCKETS+1];
+static unsigned int numMallocs[NBUCKETS+1];
#include <stdio.h>
#endif
#if defined(DEBUG) || defined(RCHECK)
-#define ASSERT(p) if (!(p)) panic(# p)
-#define RANGE_ASSERT(p) if (!(p)) panic(# p)
+#define ASSERT(p) if (!(p)) Tcl_Panic(# p)
+#define RANGE_ASSERT(p) if (!(p)) Tcl_Panic(# p)
#else
#define ASSERT(p)
#define RANGE_ASSERT(p)
@@ -160,8 +155,7 @@ static unsigned int nmalloc[NBUCKETS+1];
* Prototypes for functions used only in this file.
*/
-static void MoreCore _ANSI_ARGS_((int bucket));
-
+static void MoreCore(int bucket);
/*
*-------------------------------------------------------------------------
@@ -180,7 +174,7 @@ static void MoreCore _ANSI_ARGS_((int bucket));
*/
void
-TclInitAlloc()
+TclInitAlloc(void)
{
if (!allocInit) {
allocInit = 1;
@@ -195,27 +189,26 @@ TclInitAlloc()
*
* TclFinalizeAllocSubsystem --
*
- * Release all resources being used by this subsystem, including
- * aggressively freeing all memory allocated by TclpAlloc() that
- * has not yet been released with TclpFree().
- *
- * After this function is called, all memory allocated with
- * TclpAlloc() should be considered unusable.
+ * Release all resources being used by this subsystem, including
+ * aggressively freeing all memory allocated by TclpAlloc() that has not
+ * yet been released with TclpFree().
+ *
+ * After this function is called, all memory allocated with TclpAlloc()
+ * should be considered unusable.
*
* Results:
* None.
*
* Side effects:
- * This subsystem is self-initializing, since memory can be
- * allocated before Tcl is formally initialized. After this call,
- * this subsystem has been reset to its initial state and is
- * usable again.
+ * This subsystem is self-initializing, since memory can be allocated
+ * before Tcl is formally initialized. After this call, this subsystem
+ * has been reset to its initial state and is usable again.
*
*-------------------------------------------------------------------------
*/
void
-TclFinalizeAllocSubsystem()
+TclFinalizeAllocSubsystem(void)
{
unsigned int i;
struct block *blockPtr, *nextPtr;
@@ -235,14 +228,14 @@ TclFinalizeAllocSubsystem()
bigBlocks.nextPtr = &bigBlocks;
bigBlocks.prevPtr = &bigBlocks;
- for (i = 0; i < NBUCKETS; i++) {
+ for (i=0 ; i<NBUCKETS ; i++) {
nextf[i] = NULL;
#ifdef MSTATS
- nmalloc[i] = 0;
+ numMallocs[i] = 0;
#endif
}
#ifdef MSTATS
- nmalloc[i] = 0;
+ numMallocs[i] = 0;
#endif
Tcl_MutexUnlock(allocMutexPtr);
}
@@ -264,30 +257,32 @@ TclFinalizeAllocSubsystem()
*/
char *
-TclpAlloc(nbytes)
- unsigned int nbytes; /* Number of bytes to allocate. */
+TclpAlloc(
+ unsigned int numBytes) /* Number of bytes to allocate. */
{
- register union overhead *op;
+ register union overhead *overPtr;
register long bucket;
- register unsigned amt;
+ register unsigned amount;
struct block *bigBlockPtr = NULL;
if (!allocInit) {
/*
- * We have to make the "self initializing" because Tcl_Alloc
- * may be used before any other part of Tcl. E.g., see
- * main() for tclsh!
+ * We have to make the "self initializing" because Tcl_Alloc may be
+ * used before any other part of Tcl. E.g., see main() for tclsh!
*/
+
TclInitAlloc();
}
Tcl_MutexLock(allocMutexPtr);
+
/*
- * First the simple case: we simple allocate big blocks directly
+ * First the simple case: we simple allocate big blocks directly.
*/
- if (nbytes >= MAXMALLOC - OVERHEAD) {
- if (nbytes <= UINT_MAX - OVERHEAD - sizeof(struct block)) {
- bigBlockPtr = (struct block *) TclpSysAlloc((unsigned)
- (sizeof(struct block) + OVERHEAD + nbytes), 0);
+
+ if (numBytes >= MAXMALLOC - OVERHEAD) {
+ if (numBytes <= UINT_MAX - OVERHEAD -sizeof(struct block)) {
+ bigBlockPtr = (struct block *) TclpSysAlloc((unsigned)
+ (sizeof(struct block) + OVERHEAD + numBytes), 0);
}
if (bigBlockPtr == NULL) {
Tcl_MutexUnlock(allocMutexPtr);
@@ -298,74 +293,83 @@ TclpAlloc(nbytes)
bigBlockPtr->prevPtr = &bigBlocks;
bigBlockPtr->nextPtr->prevPtr = bigBlockPtr;
- op = (union overhead *) (bigBlockPtr + 1);
- op->ov_magic0 = op->ov_magic1 = MAGIC;
- op->ov_index = 0xff;
+ overPtr = (union overhead *) (bigBlockPtr + 1);
+ overPtr->overMagic0 = overPtr->overMagic1 = MAGIC;
+ overPtr->bucketIndex = 0xff;
#ifdef MSTATS
- nmalloc[NBUCKETS]++;
+ numMallocs[NBUCKETS]++;
#endif
+
#ifdef RCHECK
/*
- * Record allocated size of block and
- * bound space with magic numbers.
+ * Record allocated size of block and bound space with magic numbers.
*/
- op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
- op->ov_rmagic = RMAGIC;
- *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
+
+ overPtr->realBlockSize = (numBytes + RSLOP - 1) & ~(RSLOP - 1);
+ overPtr->rangeCheckMagic = RMAGIC;
+ BLOCK_END(overPtr) = RMAGIC;
#endif
+
Tcl_MutexUnlock(allocMutexPtr);
- return (void *)(op+1);
+ return (void *)(overPtr+1);
}
+
/*
- * Convert amount of memory requested into closest block size
- * stored in hash buckets which satisfies request.
- * Account for space used per block for accounting.
+ * Convert amount of memory requested into closest block size stored in
+ * hash buckets which satisfies request. Account for space used per block
+ * for accounting.
*/
- amt = MINBLOCK; /* size of first bucket */
+ amount = MINBLOCK; /* size of first bucket */
bucket = MINBLOCK >> 4;
- while (nbytes + OVERHEAD > amt) {
- amt <<= 1;
- if (amt == 0) {
+ while (numBytes + OVERHEAD > amount) {
+ amount <<= 1;
+ if (amount == 0) {
Tcl_MutexUnlock(allocMutexPtr);
- return (NULL);
+ return NULL;
}
bucket++;
}
- ASSERT( bucket < NBUCKETS );
+ ASSERT(bucket < NBUCKETS);
/*
- * If nothing in hash bucket right now,
- * request more memory from the system.
+ * If nothing in hash bucket right now, request more memory from the
+ * system.
*/
- if ((op = nextf[bucket]) == NULL) {
+
+ if ((overPtr = nextf[bucket]) == NULL) {
MoreCore(bucket);
- if ((op = nextf[bucket]) == NULL) {
+ if ((overPtr = nextf[bucket]) == NULL) {
Tcl_MutexUnlock(allocMutexPtr);
- return (NULL);
+ return NULL;
}
}
+
/*
* Remove from linked list
*/
- nextf[bucket] = op->ov_next;
- op->ov_magic0 = op->ov_magic1 = MAGIC;
- op->ov_index = (unsigned char) bucket;
+
+ nextf[bucket] = overPtr->next;
+ overPtr->overMagic0 = overPtr->overMagic1 = MAGIC;
+ overPtr->bucketIndex = (unsigned char) bucket;
+
#ifdef MSTATS
- nmalloc[bucket]++;
+ numMallocs[bucket]++;
#endif
+
#ifdef RCHECK
/*
- * Record allocated size of block and
- * bound space with magic numbers.
+ * Record allocated size of block and bound space with magic numbers.
*/
- op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
- op->ov_rmagic = RMAGIC;
- *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
+
+ overPtr->realBlockSize = (numBytes + RSLOP - 1) & ~(RSLOP - 1);
+ overPtr->rangeCheckMagic = RMAGIC;
+ BLOCK_END(overPtr) = RMAGIC;
#endif
+
Tcl_MutexUnlock(allocMutexPtr);
- return ((char *)(op + 1));
+ return ((char *)(overPtr + 1));
}
/*
@@ -387,28 +391,29 @@ TclpAlloc(nbytes)
*/
static void
-MoreCore(bucket)
- int bucket; /* What bucket to allocat to. */
+MoreCore(
+ int bucket) /* What bucket to allocat to. */
{
- register union overhead *op;
- register long sz; /* size of desired block */
- long amt; /* amount to allocate */
- int nblks; /* how many blocks we get */
+ register union overhead *overPtr;
+ register long size; /* size of desired block */
+ long amount; /* amount to allocate */
+ int numBlocks; /* how many blocks we get */
struct block *blockPtr;
/*
- * sbrk_size <= 0 only for big, FLUFFY, requests (about
- * 2^30 bytes on a VAX, I think) or for a negative arg.
+ * sbrk_size <= 0 only for big, FLUFFY, requests (about 2^30 bytes on a
+ * VAX, I think) or for a negative arg.
*/
- sz = 1 << (bucket + 3);
- ASSERT(sz > 0);
- amt = MAXMALLOC;
- nblks = amt / sz;
- ASSERT(nblks*sz == amt);
+ size = 1 << (bucket + 3);
+ ASSERT(size > 0);
- blockPtr = (struct block *) TclpSysAlloc((unsigned)
- (sizeof(struct block) + amt), 1);
+ amount = MAXMALLOC;
+ numBlocks = amount / size;
+ ASSERT(numBlocks*size == amount);
+
+ blockPtr = (struct block *) TclpSysAlloc((unsigned)
+ (sizeof(struct block) + amount), 1);
/* no more room! */
if (blockPtr == NULL) {
return;
@@ -416,18 +421,18 @@ MoreCore(bucket)
blockPtr->nextPtr = blockList;
blockList = blockPtr;
- op = (union overhead *) (blockPtr + 1);
-
+ overPtr = (union overhead *) (blockPtr + 1);
+
/*
- * Add new memory allocated to that on
- * free list for this hash bucket.
+ * Add new memory allocated to that on free list for this hash bucket.
*/
- nextf[bucket] = op;
- while (--nblks > 0) {
- op->ov_next = (union overhead *)((caddr_t)op + sz);
- op = (union overhead *)((caddr_t)op + sz);
+
+ nextf[bucket] = overPtr;
+ while (--numBlocks > 0) {
+ overPtr->next = (union overhead *)((caddr_t)overPtr + size);
+ overPtr = (union overhead *)((caddr_t)overPtr + size);
}
- op->ov_next = (union overhead *)NULL;
+ overPtr->next = NULL;
}
/*
@@ -447,47 +452,51 @@ MoreCore(bucket)
*/
void
-TclpFree(cp)
- char *cp; /* Pointer to memory to free. */
-{
+TclpFree(
+ char *oldPtr) /* Pointer to memory to free. */
+{
register long size;
- register union overhead *op;
+ register union overhead *overPtr;
struct block *bigBlockPtr;
- if (cp == NULL) {
+ if (oldPtr == NULL) {
return;
}
Tcl_MutexLock(allocMutexPtr);
- op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
+ overPtr = (union overhead *)((caddr_t)oldPtr - sizeof (union overhead));
- ASSERT(op->ov_magic0 == MAGIC); /* make sure it was in use */
- ASSERT(op->ov_magic1 == MAGIC);
- if (op->ov_magic0 != MAGIC || op->ov_magic1 != MAGIC) {
+ ASSERT(overPtr->overMagic0 == MAGIC); /* make sure it was in use */
+ ASSERT(overPtr->overMagic1 == MAGIC);
+ if (overPtr->overMagic0 != MAGIC || overPtr->overMagic1 != MAGIC) {
Tcl_MutexUnlock(allocMutexPtr);
return;
}
- RANGE_ASSERT(op->ov_rmagic == RMAGIC);
- RANGE_ASSERT(*(unsigned short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC);
- size = op->ov_index;
- if ( size == 0xff ) {
+ RANGE_ASSERT(overPtr->rangeCheckMagic == RMAGIC);
+ RANGE_ASSERT(BLOCK_END(overPtr) == RMAGIC);
+ size = overPtr->bucketIndex;
+ if (size == 0xff) {
#ifdef MSTATS
- nmalloc[NBUCKETS]--;
+ numMallocs[NBUCKETS]--;
#endif
- bigBlockPtr = (struct block *) op - 1;
+
+ bigBlockPtr = (struct block *) overPtr - 1;
bigBlockPtr->prevPtr->nextPtr = bigBlockPtr->nextPtr;
bigBlockPtr->nextPtr->prevPtr = bigBlockPtr->prevPtr;
TclpSysFree(bigBlockPtr);
+
Tcl_MutexUnlock(allocMutexPtr);
return;
}
ASSERT(size < NBUCKETS);
- op->ov_next = nextf[size]; /* also clobbers ov_magic */
- nextf[size] = op;
+ overPtr->next = nextf[size]; /* also clobbers overMagic */
+ nextf[size] = overPtr;
+
#ifdef MSTATS
- nmalloc[size]--;
+ numMallocs[size]--;
#endif
+
Tcl_MutexUnlock(allocMutexPtr);
}
@@ -508,34 +517,34 @@ TclpFree(cp)
*/
char *
-TclpRealloc(cp, nbytes)
- char *cp; /* Pointer to alloced block. */
- unsigned int nbytes; /* New size of memory. */
-{
+TclpRealloc(
+ char *oldPtr, /* Pointer to alloced block. */
+ unsigned int numBytes) /* New size of memory. */
+{
int i;
- union overhead *op;
+ union overhead *overPtr;
struct block *bigBlockPtr;
int expensive;
- unsigned long maxsize;
+ unsigned long maxSize;
- if (cp == NULL) {
- return (TclpAlloc(nbytes));
+ if (oldPtr == NULL) {
+ return TclpAlloc(numBytes);
}
Tcl_MutexLock(allocMutexPtr);
- op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
+ overPtr = (union overhead *)((caddr_t)oldPtr - sizeof (union overhead));
- ASSERT(op->ov_magic0 == MAGIC); /* make sure it was in use */
- ASSERT(op->ov_magic1 == MAGIC);
- if (op->ov_magic0 != MAGIC || op->ov_magic1 != MAGIC) {
+ ASSERT(overPtr->overMagic0 == MAGIC); /* make sure it was in use */
+ ASSERT(overPtr->overMagic1 == MAGIC);
+ if (overPtr->overMagic0 != MAGIC || overPtr->overMagic1 != MAGIC) {
Tcl_MutexUnlock(allocMutexPtr);
return NULL;
}
- RANGE_ASSERT(op->ov_rmagic == RMAGIC);
- RANGE_ASSERT(*(unsigned short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC);
- i = op->ov_index;
+ RANGE_ASSERT(overPtr->rangeCheckMagic == RMAGIC);
+ RANGE_ASSERT(BLOCK_END(overPtr) == RMAGIC);
+ i = overPtr->bucketIndex;
/*
* If the block isn't in a bin, just realloc it.
@@ -543,11 +552,11 @@ TclpRealloc(cp, nbytes)
if (i == 0xff) {
struct block *prevPtr, *nextPtr;
- bigBlockPtr = (struct block *) op - 1;
+ bigBlockPtr = (struct block *) overPtr - 1;
prevPtr = bigBlockPtr->prevPtr;
nextPtr = bigBlockPtr->nextPtr;
- bigBlockPtr = (struct block *) TclpSysRealloc(bigBlockPtr,
- sizeof(struct block) + OVERHEAD + nbytes);
+ bigBlockPtr = (struct block *) TclpSysRealloc(bigBlockPtr,
+ sizeof(struct block) + OVERHEAD + numBytes);
if (bigBlockPtr == NULL) {
Tcl_MutexUnlock(allocMutexPtr);
return NULL;
@@ -555,63 +564,69 @@ TclpRealloc(cp, nbytes)
if (prevPtr->nextPtr != bigBlockPtr) {
/*
- * If the block has moved, splice the new block into the list where
- * the old block used to be.
+ * If the block has moved, splice the new block into the list
+ * where the old block used to be.
*/
prevPtr->nextPtr = bigBlockPtr;
nextPtr->prevPtr = bigBlockPtr;
}
- op = (union overhead *) (bigBlockPtr + 1);
+ overPtr = (union overhead *) (bigBlockPtr + 1);
+
#ifdef MSTATS
- nmalloc[NBUCKETS]++;
+ numMallocs[NBUCKETS]++;
#endif
+
#ifdef RCHECK
/*
* Record allocated size of block and update magic number bounds.
*/
- op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
- *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
+ overPtr->realBlockSize = (numBytes + RSLOP - 1) & ~(RSLOP - 1);
+ BLOCK_END(overPtr) = RMAGIC;
#endif
+
Tcl_MutexUnlock(allocMutexPtr);
- return (char *)(op+1);
+ return (char *)(overPtr+1);
}
- maxsize = 1 << (i+3);
+ maxSize = 1 << (i+3);
expensive = 0;
- if ( nbytes + OVERHEAD > maxsize ) {
+ if (numBytes+OVERHEAD > maxSize) {
expensive = 1;
- } else if ( i > 0 && nbytes + OVERHEAD < (maxsize/2) ) {
+ } else if (i>0 && numBytes+OVERHEAD < maxSize/2) {
expensive = 1;
}
if (expensive) {
- void *newp;
+ void *newPtr;
Tcl_MutexUnlock(allocMutexPtr);
- newp = TclpAlloc(nbytes);
- if ( newp == NULL ) {
+ newPtr = TclpAlloc(numBytes);
+ if (newPtr == NULL) {
return NULL;
}
- maxsize -= OVERHEAD;
- if ( maxsize < nbytes )
- nbytes = maxsize;
- memcpy((VOID *) newp, (VOID *) cp, (size_t) nbytes);
- TclpFree(cp);
- return newp;
+ maxSize -= OVERHEAD;
+ if (maxSize < numBytes) {
+ numBytes = maxSize;
+ }
+ memcpy(newPtr, oldPtr, (size_t) numBytes);
+ TclpFree(oldPtr);
+ return newPtr;
}
-
+
/*
* Ok, we don't have to copy, it fits as-is
*/
+
#ifdef RCHECK
- op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
- *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
+ overPtr->realBlockSize = (numBytes + RSLOP - 1) & ~(RSLOP - 1);
+ BLOCK_END(overPtr) = RMAGIC;
#endif
+
Tcl_MutexUnlock(allocMutexPtr);
- return(cp);
+ return(oldPtr);
}
/*
@@ -619,9 +634,9 @@ TclpRealloc(cp, nbytes)
*
* mstats --
*
- * Prints two lines of numbers, one showing the length of the
- * free list for each size category, the second showing the
- * number of mallocs - frees for each size category.
+ * Prints two lines of numbers, one showing the length of the free list
+ * for each size category, the second showing the number of mallocs -
+ * frees for each size category.
*
* Results:
* None.
@@ -634,35 +649,39 @@ TclpRealloc(cp, nbytes)
#ifdef MSTATS
void
-mstats(s)
- char *s; /* Where to write info. */
+mstats(
+ char *s) /* Where to write info. */
{
register int i, j;
- register union overhead *p;
- int totfree = 0,
- totused = 0;
+ register union overhead *overPtr;
+ int totalFree = 0, totalUsed = 0;
Tcl_MutexLock(allocMutexPtr);
+
fprintf(stderr, "Memory allocation statistics %s\nTclpFree:\t", s);
for (i = 0; i < NBUCKETS; i++) {
- for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
+ for (j=0, overPtr=nextf[i]; overPtr; overPtr=overPtr->next, j++) {
fprintf(stderr, " %d", j);
- totfree += j * (1 << (i + 3));
+ }
+ totalFree += j * (1 << (i + 3));
}
+
fprintf(stderr, "\nused:\t");
for (i = 0; i < NBUCKETS; i++) {
- fprintf(stderr, " %d", nmalloc[i]);
- totused += nmalloc[i] * (1 << (i + 3));
+ fprintf(stderr, " %d", numMallocs[i]);
+ totalUsed += numMallocs[i] * (1 << (i + 3));
}
+
fprintf(stderr, "\n\tTotal small in use: %d, total free: %d\n",
- totused, totfree);
- fprintf(stderr, "\n\tNumber of big (>%d) blocks in use: %d\n",
- MAXMALLOC, nmalloc[NBUCKETS]);
+ totalUsed, totalFree);
+ fprintf(stderr, "\n\tNumber of big (>%d) blocks in use: %d\n",
+ MAXMALLOC, numMallocs[NBUCKETS]);
+
Tcl_MutexUnlock(allocMutexPtr);
}
#endif
-#else /* !USE_TCLALLOC */
+#else /* !USE_TCLALLOC */
/*
*----------------------------------------------------------------------
@@ -681,10 +700,10 @@ mstats(s)
*/
char *
-TclpAlloc(nbytes)
- unsigned int nbytes; /* Number of bytes to allocate. */
+TclpAlloc(
+ unsigned int numBytes) /* Number of bytes to allocate. */
{
- return (char*) malloc(nbytes);
+ return (char*) malloc(numBytes);
}
/*
@@ -704,10 +723,10 @@ TclpAlloc(nbytes)
*/
void
-TclpFree(cp)
- char *cp; /* Pointer to memory to free. */
-{
- free(cp);
+TclpFree(
+ char *oldPtr) /* Pointer to memory to free. */
+{
+ free(oldPtr);
return;
}
@@ -728,12 +747,20 @@ TclpFree(cp)
*/
char *
-TclpRealloc(cp, nbytes)
- char *cp; /* Pointer to alloced block. */
- unsigned int nbytes; /* New size of memory. */
-{
- return (char*) realloc(cp, nbytes);
+TclpRealloc(
+ char *oldPtr, /* Pointer to alloced block. */
+ unsigned int numBytes) /* New size of memory. */
+{
+ return (char*) realloc(oldPtr, numBytes);
}
#endif /* !USE_TCLALLOC */
#endif /* !TCL_THREADS */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclAsync.c b/generic/tclAsync.c
index 98087c5..ca18f5e 100644
--- a/generic/tclAsync.c
+++ b/generic/tclAsync.c
@@ -1,91 +1,78 @@
-/*
+/*
* tclAsync.c --
*
- * This file provides low-level support needed to invoke signal
- * handlers in a safe way. The code here doesn't actually handle
- * signals, though. This code is based on proposals made by
- * Mark Diekhans and Don Libes.
+ * This file provides low-level support needed to invoke signal handlers
+ * in a safe way. The code here doesn't actually handle signals, though.
+ * This code is based on proposals made by Mark Diekhans and Don Libes.
*
* Copyright (c) 1993 The Regents of the University of California.
* Copyright (c) 1994 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
/* Forward declaration */
struct ThreadSpecificData;
/*
- * One of the following structures exists for each asynchronous
- * handler:
+ * One of the following structures exists for each asynchronous handler:
*/
typedef struct AsyncHandler {
- int ready; /* Non-zero means this handler should
- * be invoked in the next call to
- * Tcl_AsyncInvoke. */
- struct AsyncHandler *nextPtr; /* Next in list of all handlers for
- * the process. */
- Tcl_AsyncProc *proc; /* Procedure to call when handler
- * is invoked. */
- ClientData clientData; /* Value to pass to handler when it
- * is invoked. */
+ int ready; /* Non-zero means this handler should be
+ * invoked in the next call to
+ * Tcl_AsyncInvoke. */
+ struct AsyncHandler *nextPtr;
+ /* Next in list of all handlers for the
+ * process. */
+ Tcl_AsyncProc *proc; /* Procedure to call when handler is
+ * invoked. */
+ ClientData clientData; /* Value to pass to handler when it is
+ * invoked. */
struct ThreadSpecificData *originTsd;
- /* Used in Tcl_AsyncMark to modify thread-
- * specific data from outside the thread
- * it is associated to. */
- Tcl_ThreadId originThrdId; /* Origin thread where this token was
- * created and where it will be
- * yielded. */
+ /* Used in Tcl_AsyncMark to modify thread-
+ * specific data from outside the thread it is
+ * associated to. */
+ Tcl_ThreadId originThrdId; /* Origin thread where this token was created
+ * and where it will be yielded. */
} AsyncHandler;
-
typedef struct ThreadSpecificData {
/*
- * The variables below maintain a list of all existing handlers
- * specific to the calling thread.
- */
- AsyncHandler *firstHandler; /* First handler defined for process,
- * or NULL if none. */
- AsyncHandler *lastHandler; /* Last handler or NULL. */
-
- /*
- * The variable below is set to 1 whenever a handler becomes ready and
- * it is cleared to zero whenever Tcl_AsyncInvoke is called. It can be
- * checked elsewhere in the application by calling Tcl_AsyncReady to see
- * if Tcl_AsyncInvoke should be invoked.
+ * The variables below maintain a list of all existing handlers specific
+ * to the calling thread.
*/
-
- int asyncReady;
-
- /*
- * The variable below indicates whether Tcl_AsyncInvoke is currently
- * working. If so then we won't set asyncReady again until
- * Tcl_AsyncInvoke returns.
- */
-
- int asyncActive;
-
- Tcl_Mutex asyncMutex; /* Thread-specific AsyncHandler linked-list lock */
-
+ AsyncHandler *firstHandler; /* First handler defined for process, or NULL
+ * if none. */
+ AsyncHandler *lastHandler; /* Last handler or NULL. */
+ int asyncReady; /* This is set to 1 whenever a handler becomes
+ * ready and it is cleared to zero whenever
+ * Tcl_AsyncInvoke is called. It can be
+ * checked elsewhere in the application by
+ * calling Tcl_AsyncReady to see if
+ * Tcl_AsyncInvoke should be invoked. */
+ int asyncActive; /* Indicates whether Tcl_AsyncInvoke is
+ * currently working. If so then we won't set
+ * asyncReady again until Tcl_AsyncInvoke
+ * returns. */
+ Tcl_Mutex asyncMutex; /* Thread-specific AsyncHandler linked-list
+ * lock */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
-
/*
*----------------------------------------------------------------------
*
* TclFinalizeAsync --
*
- * Finalizes the mutex in the thread local data structure for the
- * async subsystem.
+ * Finalizes the mutex in the thread local data structure for the async
+ * subsystem.
*
* Results:
- * None.
+ * None.
*
* Side effects:
* Forgets knowledge of the mutex should it have been created.
@@ -94,7 +81,7 @@ static Tcl_ThreadDataKey dataKey;
*/
void
-TclFinalizeAsync()
+TclFinalizeAsync(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -109,12 +96,12 @@ TclFinalizeAsync()
* Tcl_AsyncCreate --
*
* This procedure creates the data structures for an asynchronous
- * handler, so that no memory has to be allocated when the handler
- * is activated.
+ * handler, so that no memory has to be allocated when the handler is
+ * activated.
*
* Results:
- * The return value is a token for the handler, which can be used
- * to activate it later on.
+ * The return value is a token for the handler, which can be used to
+ * activate it later on.
*
* Side effects:
* Information about the handler is recorded.
@@ -123,10 +110,10 @@ TclFinalizeAsync()
*/
Tcl_AsyncHandler
-Tcl_AsyncCreate(proc, clientData)
- Tcl_AsyncProc *proc; /* Procedure to call when handler
- * is invoked. */
- ClientData clientData; /* Argument to pass to handler. */
+Tcl_AsyncCreate(
+ Tcl_AsyncProc *proc, /* Procedure to call when handler is
+ * invoked. */
+ ClientData clientData) /* Argument to pass to handler. */
{
AsyncHandler *asyncPtr;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -155,10 +142,10 @@ Tcl_AsyncCreate(proc, clientData)
*
* Tcl_AsyncMark --
*
- * This procedure is called to request that an asynchronous handler
- * be invoked as soon as possible. It's typically called from
- * an interrupt handler, where it isn't safe to do anything that
- * depends on or modifies application state.
+ * This procedure is called to request that an asynchronous handler be
+ * invoked as soon as possible. It's typically called from an interrupt
+ * handler, where it isn't safe to do anything that depends on or
+ * modifies application state.
*
* Results:
* None.
@@ -170,8 +157,8 @@ Tcl_AsyncCreate(proc, clientData)
*/
void
-Tcl_AsyncMark(async)
- Tcl_AsyncHandler async; /* Token for handler. */
+Tcl_AsyncMark(
+ Tcl_AsyncHandler async) /* Token for handler. */
{
AsyncHandler *token = (AsyncHandler *) async;
@@ -189,13 +176,12 @@ Tcl_AsyncMark(async)
*
* Tcl_AsyncInvoke --
*
- * This procedure is called at a "safe" time at background level
- * to invoke any active asynchronous handlers.
+ * This procedure is called at a "safe" time at background level to
+ * invoke any active asynchronous handlers.
*
* Results:
- * The return value is a normal Tcl result, which is intended to
- * replace the code argument as the current completion code for
- * interp.
+ * The return value is a normal Tcl result, which is intended to replace
+ * the code argument as the current completion code for interp.
*
* Side effects:
* Depends on the handlers that are active.
@@ -204,14 +190,13 @@ Tcl_AsyncMark(async)
*/
int
-Tcl_AsyncInvoke(interp, code)
- Tcl_Interp *interp; /* If invoked from Tcl_Eval just after
- * completing a command, points to
- * interpreter. Otherwise it is
- * NULL. */
- int code; /* If interp is non-NULL, this gives
- * completion code from command that
- * just completed. */
+Tcl_AsyncInvoke(
+ Tcl_Interp *interp, /* If invoked from Tcl_Eval just after
+ * completing a command, points to
+ * interpreter. Otherwise it is NULL. */
+ int code) /* If interp is non-NULL, this gives
+ * completion code from command that just
+ * completed. */
{
AsyncHandler *asyncPtr;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -229,13 +214,12 @@ Tcl_AsyncInvoke(interp, code)
}
/*
- * Make one or more passes over the list of handlers, invoking
- * at most one handler in each pass. After invoking a handler,
- * go back to the start of the list again so that (a) if a new
- * higher-priority handler gets marked while executing a lower
- * priority handler, we execute the higher-priority handler
- * next, and (b) if a handler gets deleted during the execution
- * of a handler, then the list structure may change so it isn't
+ * Make one or more passes over the list of handlers, invoking at most one
+ * handler in each pass. After invoking a handler, go back to the start of
+ * the list again so that (a) if a new higher-priority handler gets marked
+ * while executing a lower priority handler, we execute the higher-
+ * priority handler next, and (b) if a handler gets deleted during the
+ * execution of a handler, then the list structure may change so it isn't
* safe to continue down the list anyway.
*/
@@ -264,8 +248,8 @@ Tcl_AsyncInvoke(interp, code)
*
* Tcl_AsyncDelete --
*
- * Frees up all the state for an asynchronous handler. The handler
- * should never be used again.
+ * Frees up all the state for an asynchronous handler. The handler should
+ * never be used again.
*
* Results:
* None.
@@ -284,8 +268,8 @@ Tcl_AsyncInvoke(interp, code)
*/
void
-Tcl_AsyncDelete(async)
- Tcl_AsyncHandler async; /* Token for handler to delete. */
+Tcl_AsyncDelete(
+ Tcl_AsyncHandler async) /* Token for handler to delete. */
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
AsyncHandler *asyncPtr = (AsyncHandler *) async;
@@ -296,7 +280,7 @@ Tcl_AsyncDelete(async)
*/
if (asyncPtr->originThrdId != Tcl_GetCurrentThread()) {
- panic("Tcl_AsyncDelete: async handler deleted by the wrong thread");
+ Tcl_Panic("Tcl_AsyncDelete: async handler deleted by the wrong thread");
}
/*
@@ -314,7 +298,7 @@ Tcl_AsyncDelete(async)
thisPtr = thisPtr->nextPtr;
}
if (thisPtr == NULL) {
- panic("Tcl_AsyncDelete: cannot find async handler");
+ Tcl_Panic("Tcl_AsyncDelete: cannot find async handler");
}
if (asyncPtr == tsdPtr->firstHandler) {
tsdPtr->firstHandler = asyncPtr->nextPtr;
@@ -334,13 +318,13 @@ Tcl_AsyncDelete(async)
*
* Tcl_AsyncReady --
*
- * This procedure can be used to tell whether Tcl_AsyncInvoke
- * needs to be called. This procedure is the external interface
- * for checking the thread-specific asyncReady variable.
+ * This procedure can be used to tell whether Tcl_AsyncInvoke needs to be
+ * called. This procedure is the external interface for checking the
+ * thread-specific asyncReady variable.
*
* Results:
- * The return value is 1 whenever a handler is ready and is 0
- * when no handlers are ready.
+ * The return value is 1 whenever a handler is ready and is 0 when no
+ * handlers are ready.
*
* Side effects:
* None.
@@ -349,8 +333,23 @@ Tcl_AsyncDelete(async)
*/
int
-Tcl_AsyncReady()
+Tcl_AsyncReady(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
return tsdPtr->asyncReady;
}
+
+int *
+TclGetAsyncReadyPtr(void)
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ return &(tsdPtr->asyncReady);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index acecba6..eb041c6 100644
--- a/generic/tclBasic.c
+++ b/generic/tclBasic.c
@@ -1,9 +1,9 @@
-/*
+/*
* tclBasic.c --
*
* Contains the basic facilities for TCL command interpretation,
- * including interpreter creation and deletion, command creation
- * and deletion, and command/script execution.
+ * including interpreter creation and deletion, command creation and
+ * deletion, and command/script execution.
*
* Copyright (c) 1987-1994 The Regents of the University of California.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
@@ -11,270 +11,353 @@
* Copyright (c) 2001, 2002 by Kevin B. Kenny. All rights reserved.
* Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
#include "tclCompile.h"
-#ifndef TCL_GENERIC_ONLY
-# include "tclPort.h"
-#endif
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+#include "tommath.h"
/*
- * Static procedures in this file:
+ * Determine whether we're using IEEE floating point
*/
-static char * CallCommandTraces _ANSI_ARGS_((Interp *iPtr,
- Command *cmdPtr, CONST char *oldName,
- CONST char* newName, int flags));
-static void DeleteInterpProc _ANSI_ARGS_((Tcl_Interp *interp));
-static void ProcessUnexpectedResult _ANSI_ARGS_((
- Tcl_Interp *interp, int returnCode));
-static int StringTraceProc _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp* interp,
- int level,
- CONST char* command,
- Tcl_Command commandInfo,
- int objc,
- Tcl_Obj *CONST objv[]));
-static void StringTraceDeleteProc _ANSI_ARGS_((ClientData clientData));
-
-#ifdef TCL_TIP280
-/* TIP #280 - Modified token based evaluation, with line information */
-static int EvalEx _ANSI_ARGS_((Tcl_Interp *interp, CONST char *script,
- int numBytes, int flags, int line,
- int* clNextOuter, CONST char* outerScript));
-
-static int EvalTokensStandard _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Token *tokenPtr,
- int count, int line,
- int* clNextOuter, CONST char* outerScript));
+#if (FLT_RADIX == 2) && (DBL_MANT_DIG == 53) && (DBL_MAX_EXP == 1024)
+# define IEEE_FLOATING_POINT
+/* Largest odd integer that can be represented exactly in a double */
+# define MAX_EXACT 9007199254740991.0
#endif
+/*
+ * The following structure defines the client data for a math function
+ * registered with Tcl_CreateMathFunc
+ */
+
+typedef struct OldMathFuncData {
+ Tcl_MathProc *proc; /* Handler function */
+ int numArgs; /* Number of args expected */
+ Tcl_ValueType *argTypes; /* Types of the args */
+ ClientData clientData; /* Client data for the handler function */
+} OldMathFuncData;
+
+/*
+ * Static functions in this file:
+ */
+
+static char * CallCommandTraces(Interp *iPtr, Command *cmdPtr,
+ const char *oldName, const char *newName, int flags);
+static int CheckDoubleResult(Tcl_Interp *interp, double dResult);
+static void DeleteInterpProc(Tcl_Interp *interp);
+static void DeleteOpCmdClientData(ClientData clientData);
+static Tcl_Obj *GetCommandSource(Interp *iPtr, const char *command,
+ int numChars, int objc, Tcl_Obj *const objv[]);
+static void ProcessUnexpectedResult(Tcl_Interp *interp, int returnCode);
+static int OldMathFuncProc(ClientData clientData, Tcl_Interp *interp,
+ int argc, Tcl_Obj *const *objv);
+static void OldMathFuncDeleteProc(ClientData clientData);
+static int ExprAbsFunc(ClientData clientData, Tcl_Interp *interp,
+ int argc, Tcl_Obj *const *objv);
+static int ExprBinaryFunc(ClientData clientData, Tcl_Interp *interp,
+ int argc, Tcl_Obj *const *objv);
+static int ExprBoolFunc(ClientData clientData, Tcl_Interp *interp,
+ int argc, Tcl_Obj *const *objv);
+static int ExprCeilFunc(ClientData clientData, Tcl_Interp *interp,
+ int argc, Tcl_Obj *const *objv);
+static int ExprDoubleFunc(ClientData clientData, Tcl_Interp *interp,
+ int argc, Tcl_Obj *const *objv);
+static int ExprEntierFunc(ClientData clientData, Tcl_Interp *interp,
+ int argc, Tcl_Obj *const *objv);
+static int ExprFloorFunc(ClientData clientData, Tcl_Interp *interp,
+ int argc, Tcl_Obj *const *objv);
+static int ExprIntFunc(ClientData clientData, Tcl_Interp *interp,
+ int argc, Tcl_Obj *const *objv);
+static int ExprIsqrtFunc(ClientData clientData, Tcl_Interp *interp,
+ int argc, Tcl_Obj *const *objv);
+static int ExprRandFunc(ClientData clientData, Tcl_Interp *interp,
+ int argc, Tcl_Obj *const *objv);
+static int ExprRoundFunc(ClientData clientData, Tcl_Interp *interp,
+ int argc, Tcl_Obj *const *objv);
+static int ExprSqrtFunc(ClientData clientData, Tcl_Interp *interp,
+ int argc, Tcl_Obj *const *objv);
+static int ExprSrandFunc(ClientData clientData, Tcl_Interp *interp,
+ int argc, Tcl_Obj *const *objv);
+static int ExprUnaryFunc(ClientData clientData, Tcl_Interp *interp,
+ int argc, Tcl_Obj *const *objv);
+static int ExprWideFunc(ClientData clientData, Tcl_Interp *interp,
+ int argc, Tcl_Obj *const *objv);
+static void MathFuncWrongNumArgs(Tcl_Interp *interp, int expected,
+ int actual, Tcl_Obj *const *objv);
#ifdef USE_DTRACE
static int DTraceObjCmd(ClientData dummy, Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]);
+ Tcl_Obj *const objv[]);
#endif
extern TclStubs tclStubs;
/*
- * The following structure defines the commands in the Tcl core.
+ * The following structure define the commands in the Tcl core.
*/
typedef struct {
- char *name; /* Name of object-based command. */
- Tcl_CmdProc *proc; /* String-based procedure for command. */
- Tcl_ObjCmdProc *objProc; /* Object-based procedure for command. */
- CompileProc *compileProc; /* Procedure called to compile command. */
- int isSafe; /* If non-zero, command will be present
- * in safe interpreter. Otherwise it will
- * be hidden. */
+ const char *name; /* Name of object-based command. */
+ Tcl_ObjCmdProc *objProc; /* Object-based function for command. */
+ CompileProc *compileProc; /* Function called to compile command. */
+ int isSafe; /* If non-zero, command will be present in
+ * safe interpreter. Otherwise it will be
+ * hidden. */
} CmdInfo;
/*
- * The built-in commands, and the procedures that implement them:
+ * The built-in commands, and the functions that implement them:
*/
-static CmdInfo builtInCmds[] = {
- /*
- * Commands in the generic core. Note that at least one of the proc or
- * objProc members should be non-NULL. This avoids infinitely recursive
- * calls between TclInvokeObjectCommand and TclInvokeStringCommand if a
- * command name is computed at runtime and results in the name of a
- * compiled command.
- */
-
- {"append", (Tcl_CmdProc *) NULL, Tcl_AppendObjCmd,
- TclCompileAppendCmd, 1},
- {"array", (Tcl_CmdProc *) NULL, Tcl_ArrayObjCmd,
- (CompileProc *) NULL, 1},
- {"binary", (Tcl_CmdProc *) NULL, Tcl_BinaryObjCmd,
- (CompileProc *) NULL, 1},
- {"break", (Tcl_CmdProc *) NULL, Tcl_BreakObjCmd,
- TclCompileBreakCmd, 1},
- {"case", (Tcl_CmdProc *) NULL, Tcl_CaseObjCmd,
- (CompileProc *) NULL, 1},
- {"catch", (Tcl_CmdProc *) NULL, Tcl_CatchObjCmd,
- TclCompileCatchCmd, 1},
- {"clock", (Tcl_CmdProc *) NULL, Tcl_ClockObjCmd,
- (CompileProc *) NULL, 1},
- {"concat", (Tcl_CmdProc *) NULL, Tcl_ConcatObjCmd,
- (CompileProc *) NULL, 1},
- {"continue", (Tcl_CmdProc *) NULL, Tcl_ContinueObjCmd,
- TclCompileContinueCmd, 1},
- {"encoding", (Tcl_CmdProc *) NULL, Tcl_EncodingObjCmd,
- (CompileProc *) NULL, 0},
- {"error", (Tcl_CmdProc *) NULL, Tcl_ErrorObjCmd,
- (CompileProc *) NULL, 1},
- {"eval", (Tcl_CmdProc *) NULL, Tcl_EvalObjCmd,
- (CompileProc *) NULL, 1},
- {"exit", (Tcl_CmdProc *) NULL, Tcl_ExitObjCmd,
- (CompileProc *) NULL, 0},
- {"expr", (Tcl_CmdProc *) NULL, Tcl_ExprObjCmd,
- TclCompileExprCmd, 1},
- {"fcopy", (Tcl_CmdProc *) NULL, Tcl_FcopyObjCmd,
- (CompileProc *) NULL, 1},
- {"fileevent", (Tcl_CmdProc *) NULL, Tcl_FileEventObjCmd,
- (CompileProc *) NULL, 1},
- {"for", (Tcl_CmdProc *) NULL, Tcl_ForObjCmd,
- TclCompileForCmd, 1},
- {"foreach", (Tcl_CmdProc *) NULL, Tcl_ForeachObjCmd,
- TclCompileForeachCmd, 1},
- {"format", (Tcl_CmdProc *) NULL, Tcl_FormatObjCmd,
- (CompileProc *) NULL, 1},
- {"global", (Tcl_CmdProc *) NULL, Tcl_GlobalObjCmd,
- (CompileProc *) NULL, 1},
- {"if", (Tcl_CmdProc *) NULL, Tcl_IfObjCmd,
- TclCompileIfCmd, 1},
- {"incr", (Tcl_CmdProc *) NULL, Tcl_IncrObjCmd,
- TclCompileIncrCmd, 1},
- {"info", (Tcl_CmdProc *) NULL, Tcl_InfoObjCmd,
- (CompileProc *) NULL, 1},
- {"join", (Tcl_CmdProc *) NULL, Tcl_JoinObjCmd,
- (CompileProc *) NULL, 1},
- {"lappend", (Tcl_CmdProc *) NULL, Tcl_LappendObjCmd,
- TclCompileLappendCmd, 1},
- {"lindex", (Tcl_CmdProc *) NULL, Tcl_LindexObjCmd,
- TclCompileLindexCmd, 1},
- {"linsert", (Tcl_CmdProc *) NULL, Tcl_LinsertObjCmd,
- (CompileProc *) NULL, 1},
- {"list", (Tcl_CmdProc *) NULL, Tcl_ListObjCmd,
- TclCompileListCmd, 1},
- {"llength", (Tcl_CmdProc *) NULL, Tcl_LlengthObjCmd,
- TclCompileLlengthCmd, 1},
- {"load", (Tcl_CmdProc *) NULL, Tcl_LoadObjCmd,
- (CompileProc *) NULL, 0},
- {"lrange", (Tcl_CmdProc *) NULL, Tcl_LrangeObjCmd,
- (CompileProc *) NULL, 1},
- {"lreplace", (Tcl_CmdProc *) NULL, Tcl_LreplaceObjCmd,
- (CompileProc *) NULL, 1},
- {"lsearch", (Tcl_CmdProc *) NULL, Tcl_LsearchObjCmd,
- (CompileProc *) NULL, 1},
- {"lset", (Tcl_CmdProc *) NULL, Tcl_LsetObjCmd,
- TclCompileLsetCmd, 1},
- {"lsort", (Tcl_CmdProc *) NULL, Tcl_LsortObjCmd,
- (CompileProc *) NULL, 1},
- {"namespace", (Tcl_CmdProc *) NULL, Tcl_NamespaceObjCmd,
- (CompileProc *) NULL, 1},
- {"package", (Tcl_CmdProc *) NULL, Tcl_PackageObjCmd,
- (CompileProc *) NULL, 1},
- {"proc", (Tcl_CmdProc *) NULL, Tcl_ProcObjCmd,
- (CompileProc *) NULL, 1},
- {"regexp", (Tcl_CmdProc *) NULL, Tcl_RegexpObjCmd,
- TclCompileRegexpCmd, 1},
- {"regsub", (Tcl_CmdProc *) NULL, Tcl_RegsubObjCmd,
- (CompileProc *) NULL, 1},
- {"rename", (Tcl_CmdProc *) NULL, Tcl_RenameObjCmd,
- (CompileProc *) NULL, 1},
- {"return", (Tcl_CmdProc *) NULL, Tcl_ReturnObjCmd,
- TclCompileReturnCmd, 1},
- {"scan", (Tcl_CmdProc *) NULL, Tcl_ScanObjCmd,
- (CompileProc *) NULL, 1},
- {"set", (Tcl_CmdProc *) NULL, Tcl_SetObjCmd,
- TclCompileSetCmd, 1},
- {"split", (Tcl_CmdProc *) NULL, Tcl_SplitObjCmd,
- (CompileProc *) NULL, 1},
- {"string", (Tcl_CmdProc *) NULL, Tcl_StringObjCmd,
- TclCompileStringCmd, 1},
- {"subst", (Tcl_CmdProc *) NULL, Tcl_SubstObjCmd,
- (CompileProc *) NULL, 1},
- {"switch", (Tcl_CmdProc *) NULL, Tcl_SwitchObjCmd,
- (CompileProc *) NULL, 1},
- {"trace", (Tcl_CmdProc *) NULL, Tcl_TraceObjCmd,
- (CompileProc *) NULL, 1},
- {"unset", (Tcl_CmdProc *) NULL, Tcl_UnsetObjCmd,
- (CompileProc *) NULL, 1},
- {"uplevel", (Tcl_CmdProc *) NULL, Tcl_UplevelObjCmd,
- (CompileProc *) NULL, 1},
- {"upvar", (Tcl_CmdProc *) NULL, Tcl_UpvarObjCmd,
- (CompileProc *) NULL, 1},
- {"variable", (Tcl_CmdProc *) NULL, Tcl_VariableObjCmd,
- (CompileProc *) NULL, 1},
- {"while", (Tcl_CmdProc *) NULL, Tcl_WhileObjCmd,
- TclCompileWhileCmd, 1},
-
- /*
- * Commands in the UNIX core:
- */
-
-#ifndef TCL_GENERIC_ONLY
- {"after", (Tcl_CmdProc *) NULL, Tcl_AfterObjCmd,
- (CompileProc *) NULL, 1},
- {"cd", (Tcl_CmdProc *) NULL, Tcl_CdObjCmd,
- (CompileProc *) NULL, 0},
- {"close", (Tcl_CmdProc *) NULL, Tcl_CloseObjCmd,
- (CompileProc *) NULL, 1},
- {"eof", (Tcl_CmdProc *) NULL, Tcl_EofObjCmd,
- (CompileProc *) NULL, 1},
- {"fblocked", (Tcl_CmdProc *) NULL, Tcl_FblockedObjCmd,
- (CompileProc *) NULL, 1},
- {"fconfigure", (Tcl_CmdProc *) NULL, Tcl_FconfigureObjCmd,
- (CompileProc *) NULL, 0},
- {"file", (Tcl_CmdProc *) NULL, Tcl_FileObjCmd,
- (CompileProc *) NULL, 0},
- {"flush", (Tcl_CmdProc *) NULL, Tcl_FlushObjCmd,
- (CompileProc *) NULL, 1},
- {"gets", (Tcl_CmdProc *) NULL, Tcl_GetsObjCmd,
- (CompileProc *) NULL, 1},
- {"glob", (Tcl_CmdProc *) NULL, Tcl_GlobObjCmd,
- (CompileProc *) NULL, 0},
- {"open", (Tcl_CmdProc *) NULL, Tcl_OpenObjCmd,
- (CompileProc *) NULL, 0},
- {"pid", (Tcl_CmdProc *) NULL, Tcl_PidObjCmd,
- (CompileProc *) NULL, 1},
- {"puts", (Tcl_CmdProc *) NULL, Tcl_PutsObjCmd,
- (CompileProc *) NULL, 1},
- {"pwd", (Tcl_CmdProc *) NULL, Tcl_PwdObjCmd,
- (CompileProc *) NULL, 0},
- {"read", (Tcl_CmdProc *) NULL, Tcl_ReadObjCmd,
- (CompileProc *) NULL, 1},
- {"seek", (Tcl_CmdProc *) NULL, Tcl_SeekObjCmd,
- (CompileProc *) NULL, 1},
- {"socket", (Tcl_CmdProc *) NULL, Tcl_SocketObjCmd,
- (CompileProc *) NULL, 0},
- {"tell", (Tcl_CmdProc *) NULL, Tcl_TellObjCmd,
- (CompileProc *) NULL, 1},
- {"time", (Tcl_CmdProc *) NULL, Tcl_TimeObjCmd,
- (CompileProc *) NULL, 1},
- {"update", (Tcl_CmdProc *) NULL, Tcl_UpdateObjCmd,
- (CompileProc *) NULL, 1},
- {"vwait", (Tcl_CmdProc *) NULL, Tcl_VwaitObjCmd,
- (CompileProc *) NULL, 1},
-
-#ifdef MAC_TCL
- {"beep", (Tcl_CmdProc *) NULL, Tcl_BeepObjCmd,
- (CompileProc *) NULL, 0},
- {"echo", Tcl_EchoCmd, (Tcl_ObjCmdProc *) NULL,
- (CompileProc *) NULL, 0},
- {"ls", (Tcl_CmdProc *) NULL, Tcl_LsObjCmd,
- (CompileProc *) NULL, 0},
- {"resource", (Tcl_CmdProc *) NULL, Tcl_ResourceObjCmd,
- (CompileProc *) NULL, 1},
- {"source", (Tcl_CmdProc *) NULL, Tcl_MacSourceObjCmd,
- (CompileProc *) NULL, 0},
-#else
- {"exec", (Tcl_CmdProc *) NULL, Tcl_ExecObjCmd,
- (CompileProc *) NULL, 0},
- {"source", (Tcl_CmdProc *) NULL, Tcl_SourceObjCmd,
- (CompileProc *) NULL, 0},
-#endif /* MAC_TCL */
-
-#endif /* TCL_GENERIC_ONLY */
- {NULL, (Tcl_CmdProc *) NULL, (Tcl_ObjCmdProc *) NULL,
- (CompileProc *) NULL, 0}
+static const CmdInfo builtInCmds[] = {
+ /*
+ * Commands in the generic core.
+ */
+
+ {"append", Tcl_AppendObjCmd, TclCompileAppendCmd, 1},
+ {"apply", Tcl_ApplyObjCmd, NULL, 1},
+ {"array", Tcl_ArrayObjCmd, NULL, 1},
+ {"binary", Tcl_BinaryObjCmd, NULL, 1},
+ {"break", Tcl_BreakObjCmd, TclCompileBreakCmd, 1},
+#ifndef EXCLUDE_OBSOLETE_COMMANDS
+ {"case", Tcl_CaseObjCmd, NULL, 1},
+#endif
+ {"catch", Tcl_CatchObjCmd, TclCompileCatchCmd, 1},
+ {"concat", Tcl_ConcatObjCmd, NULL, 1},
+ {"continue", Tcl_ContinueObjCmd, TclCompileContinueCmd, 1},
+ {"error", Tcl_ErrorObjCmd, NULL, 1},
+ {"eval", Tcl_EvalObjCmd, NULL, 1},
+ {"expr", Tcl_ExprObjCmd, TclCompileExprCmd, 1},
+ {"for", Tcl_ForObjCmd, TclCompileForCmd, 1},
+ {"foreach", Tcl_ForeachObjCmd, TclCompileForeachCmd, 1},
+ {"format", Tcl_FormatObjCmd, NULL, 1},
+ {"global", Tcl_GlobalObjCmd, TclCompileGlobalCmd, 1},
+ {"if", Tcl_IfObjCmd, TclCompileIfCmd, 1},
+ {"incr", Tcl_IncrObjCmd, TclCompileIncrCmd, 1},
+ {"join", Tcl_JoinObjCmd, NULL, 1},
+ {"lappend", Tcl_LappendObjCmd, TclCompileLappendCmd, 1},
+ {"lassign", Tcl_LassignObjCmd, TclCompileLassignCmd, 1},
+ {"lindex", Tcl_LindexObjCmd, TclCompileLindexCmd, 1},
+ {"linsert", Tcl_LinsertObjCmd, NULL, 1},
+ {"list", Tcl_ListObjCmd, TclCompileListCmd, 1},
+ {"llength", Tcl_LlengthObjCmd, TclCompileLlengthCmd, 1},
+ {"lrange", Tcl_LrangeObjCmd, NULL, 1},
+ {"lrepeat", Tcl_LrepeatObjCmd, NULL, 1},
+ {"lreplace", Tcl_LreplaceObjCmd, NULL, 1},
+ {"lreverse", Tcl_LreverseObjCmd, NULL, 1},
+ {"lsearch", Tcl_LsearchObjCmd, NULL, 1},
+ {"lset", Tcl_LsetObjCmd, TclCompileLsetCmd, 1},
+ {"lsort", Tcl_LsortObjCmd, NULL, 1},
+ {"namespace", Tcl_NamespaceObjCmd, TclCompileNamespaceCmd, 1},
+ {"package", Tcl_PackageObjCmd, NULL, 1},
+ {"proc", Tcl_ProcObjCmd, NULL, 1},
+ {"regexp", Tcl_RegexpObjCmd, TclCompileRegexpCmd, 1},
+ {"regsub", Tcl_RegsubObjCmd, NULL, 1},
+ {"rename", Tcl_RenameObjCmd, NULL, 1},
+ {"return", Tcl_ReturnObjCmd, TclCompileReturnCmd, 1},
+ {"scan", Tcl_ScanObjCmd, NULL, 1},
+ {"set", Tcl_SetObjCmd, TclCompileSetCmd, 1},
+ {"split", Tcl_SplitObjCmd, NULL, 1},
+ {"subst", Tcl_SubstObjCmd, NULL, 1},
+ {"switch", Tcl_SwitchObjCmd, TclCompileSwitchCmd, 1},
+ {"trace", Tcl_TraceObjCmd, NULL, 1},
+ {"unset", Tcl_UnsetObjCmd, NULL, 1},
+ {"uplevel", Tcl_UplevelObjCmd, NULL, 1},
+ {"upvar", Tcl_UpvarObjCmd, TclCompileUpvarCmd, 1},
+ {"variable", Tcl_VariableObjCmd, TclCompileVariableCmd, 1},
+ {"while", Tcl_WhileObjCmd, TclCompileWhileCmd, 1},
+
+ /*
+ * Commands in the OS-interface. Note that many of these are unsafe.
+ */
+
+ {"after", Tcl_AfterObjCmd, NULL, 1},
+ {"cd", Tcl_CdObjCmd, NULL, 0},
+ {"close", Tcl_CloseObjCmd, NULL, 1},
+ {"eof", Tcl_EofObjCmd, NULL, 1},
+ {"encoding", Tcl_EncodingObjCmd, NULL, 0},
+ {"exec", Tcl_ExecObjCmd, NULL, 0},
+ {"exit", Tcl_ExitObjCmd, NULL, 0},
+ {"fblocked", Tcl_FblockedObjCmd, NULL, 1},
+ {"fconfigure", Tcl_FconfigureObjCmd, NULL, 0},
+ {"fcopy", Tcl_FcopyObjCmd, NULL, 1},
+ {"file", Tcl_FileObjCmd, NULL, 0},
+ {"fileevent", Tcl_FileEventObjCmd, NULL, 1},
+ {"flush", Tcl_FlushObjCmd, NULL, 1},
+ {"gets", Tcl_GetsObjCmd, NULL, 1},
+ {"glob", Tcl_GlobObjCmd, NULL, 0},
+ {"load", Tcl_LoadObjCmd, NULL, 0},
+ {"open", Tcl_OpenObjCmd, NULL, 0},
+ {"pid", Tcl_PidObjCmd, NULL, 1},
+ {"puts", Tcl_PutsObjCmd, NULL, 1},
+ {"pwd", Tcl_PwdObjCmd, NULL, 0},
+ {"read", Tcl_ReadObjCmd, NULL, 1},
+ {"seek", Tcl_SeekObjCmd, NULL, 1},
+ {"socket", Tcl_SocketObjCmd, NULL, 0},
+ {"source", Tcl_SourceObjCmd, NULL, 0},
+ {"tell", Tcl_TellObjCmd, NULL, 1},
+ {"time", Tcl_TimeObjCmd, NULL, 1},
+ {"unload", Tcl_UnloadObjCmd, NULL, 0},
+ {"update", Tcl_UpdateObjCmd, NULL, 1},
+ {"vwait", Tcl_VwaitObjCmd, NULL, 1},
+ {NULL, NULL, NULL, 0}
};
/*
- * The following structure holds the client data for string-based
- * trace procs
+ * Math functions. All are safe.
*/
-typedef struct StringTraceData {
- ClientData clientData; /* Client data from Tcl_CreateTrace */
- Tcl_CmdTraceProc* proc; /* Trace procedure from Tcl_CreateTrace */
-} StringTraceData;
+typedef struct {
+ const char *name; /* Name of the function. The full name is
+ * "::tcl::mathfunc::<name>". */
+ Tcl_ObjCmdProc *objCmdProc; /* Function that evaluates the function */
+ ClientData clientData; /* Client data for the function */
+} BuiltinFuncDef;
+static const BuiltinFuncDef BuiltinFuncTable[] = {
+ { "abs", ExprAbsFunc, NULL },
+ { "acos", ExprUnaryFunc, (ClientData) acos },
+ { "asin", ExprUnaryFunc, (ClientData) asin },
+ { "atan", ExprUnaryFunc, (ClientData) atan },
+ { "atan2", ExprBinaryFunc, (ClientData) atan2 },
+ { "bool", ExprBoolFunc, NULL },
+ { "ceil", ExprCeilFunc, NULL },
+ { "cos", ExprUnaryFunc, (ClientData) cos },
+ { "cosh", ExprUnaryFunc, (ClientData) cosh },
+ { "double", ExprDoubleFunc, NULL },
+ { "entier", ExprEntierFunc, NULL },
+ { "exp", ExprUnaryFunc, (ClientData) exp },
+ { "floor", ExprFloorFunc, NULL },
+ { "fmod", ExprBinaryFunc, (ClientData) fmod },
+ { "hypot", ExprBinaryFunc, (ClientData) hypot },
+ { "int", ExprIntFunc, NULL },
+ { "isqrt", ExprIsqrtFunc, NULL },
+ { "log", ExprUnaryFunc, (ClientData) log },
+ { "log10", ExprUnaryFunc, (ClientData) log10 },
+ { "pow", ExprBinaryFunc, (ClientData) pow },
+ { "rand", ExprRandFunc, NULL },
+ { "round", ExprRoundFunc, NULL },
+ { "sin", ExprUnaryFunc, (ClientData) sin },
+ { "sinh", ExprUnaryFunc, (ClientData) sinh },
+ { "sqrt", ExprSqrtFunc, NULL },
+ { "srand", ExprSrandFunc, NULL },
+ { "tan", ExprUnaryFunc, (ClientData) tan },
+ { "tanh", ExprUnaryFunc, (ClientData) tanh },
+ { "wide", ExprWideFunc, NULL },
+ { NULL, NULL, NULL }
+};
+
+/*
+ * TIP#174's math operators. All are safe.
+ */
+
+typedef struct {
+ const char *name; /* Name of object-based command. */
+ Tcl_ObjCmdProc *objProc; /* Object-based function for command. */
+ CompileProc *compileProc; /* Function called to compile command. */
+ union {
+ int numArgs;
+ int identity;
+ } i;
+ const char *expected; /* For error message, what argument(s)
+ * were expected. */
+} OpCmdInfo;
+static const OpCmdInfo mathOpCmds[] = {
+ { "~", TclSingleOpCmd, TclCompileInvertOpCmd,
+ /* numArgs */ {1}, "integer"},
+ { "!", TclSingleOpCmd, TclCompileNotOpCmd,
+ /* numArgs */ {1}, "boolean"},
+ { "+", TclVariadicOpCmd, TclCompileAddOpCmd,
+ /* identity */ {0}, NULL},
+ { "*", TclVariadicOpCmd, TclCompileMulOpCmd,
+ /* identity */ {1}, NULL},
+ { "&", TclVariadicOpCmd, TclCompileAndOpCmd,
+ /* identity */ {-1}, NULL},
+ { "|", TclVariadicOpCmd, TclCompileOrOpCmd,
+ /* identity */ {0}, NULL},
+ { "^", TclVariadicOpCmd, TclCompileXorOpCmd,
+ /* identity */ {0}, NULL},
+ { "**", TclVariadicOpCmd, TclCompilePowOpCmd,
+ /* identity */ {1}, NULL},
+ { "<<", TclSingleOpCmd, TclCompileLshiftOpCmd,
+ /* numArgs */ {2}, "integer shift"},
+ { ">>", TclSingleOpCmd, TclCompileRshiftOpCmd,
+ /* numArgs */ {2}, "integer shift"},
+ { "%", TclSingleOpCmd, TclCompileModOpCmd,
+ /* numArgs */ {2}, "integer integer"},
+ { "!=", TclSingleOpCmd, TclCompileNeqOpCmd,
+ /* numArgs */ {2}, "value value"},
+ { "ne", TclSingleOpCmd, TclCompileStrneqOpCmd,
+ /* numArgs */ {2}, "value value"},
+ { "in", TclSingleOpCmd, TclCompileInOpCmd,
+ /* numArgs */ {2}, "value list"},
+ { "ni", TclSingleOpCmd, TclCompileNiOpCmd,
+ /* numArgs */ {2}, "value list"},
+ { "-", TclNoIdentOpCmd, TclCompileMinusOpCmd,
+ /* unused */ {0}, "value ?value ...?"},
+ { "/", TclNoIdentOpCmd, TclCompileDivOpCmd,
+ /* unused */ {0}, "value ?value ...?"},
+ { "<", TclSortingOpCmd, TclCompileLessOpCmd,
+ /* unused */ {0}, NULL},
+ { "<=", TclSortingOpCmd, TclCompileLeqOpCmd,
+ /* unused */ {0}, NULL},
+ { ">", TclSortingOpCmd, TclCompileGreaterOpCmd,
+ /* unused */ {0}, NULL},
+ { ">=", TclSortingOpCmd, TclCompileGeqOpCmd,
+ /* unused */ {0}, NULL},
+ { "==", TclSortingOpCmd, TclCompileEqOpCmd,
+ /* unused */ {0}, NULL},
+ { "eq", TclSortingOpCmd, TclCompileStreqOpCmd,
+ /* unused */ {0}, NULL},
+ { NULL, NULL, NULL,
+ {0}, NULL}
+};
+
+/*
+ * Macros for stack checks. The goal of these macros is to allow the size of
+ * the stack to be checked (so preventing overflow) in a *cheap* way. Note
+ * that the check needs to be (amortized) cheap since it is on the critical
+ * path for recursion.
+ */
+
+#if defined(TCL_NO_STACK_CHECK)
+/*
+ * Stack check disabled: make them noops.
+ */
+
+# define CheckCStack(interp, localIntPtr) 1
+# define GetCStackParams(iPtr) /* do nothing */
+#elif defined(TCL_CROSS_COMPILE)
+
+/*
+ * This variable is static and only set *once*, during library initialization.
+ * It therefore needs no thread guards.
+ */
+
+static int stackGrowsDown = 1;
+# define GetCStackParams(iPtr) \
+ stackGrowsDown = TclpGetCStackParams(&((iPtr)->stackBound))
+# define CheckCStack(iPtr, localIntPtr) \
+ (stackGrowsDown \
+ ? ((localIntPtr) > (iPtr)->stackBound) \
+ : ((localIntPtr) < (iPtr)->stackBound) \
+ )
+#else /* !TCL_NO_STACK_CHECK && !TCL_CROSS_COMPILE */
+# define GetCStackParams(iPtr) \
+ TclpGetCStackParams(&((iPtr)->stackBound))
+# ifdef TCL_STACK_GROWS_UP
+# define CheckCStack(iPtr, localIntPtr) \
+ (!(iPtr)->stackBound || (localIntPtr) < (iPtr)->stackBound)
+# else /* TCL_STACK_GROWS_UP */
+# define CheckCStack(iPtr, localIntPtr) \
+ ((localIntPtr) > (iPtr)->stackBound)
+# endif /* TCL_STACK_GROWS_UP */
+#endif /* TCL_NO_STACK_CHECK/TCL_CROSS_COMPILE */
/*
*----------------------------------------------------------------------
@@ -284,28 +367,26 @@ typedef struct StringTraceData {
* Create a new TCL command interpreter.
*
* Results:
- * The return value is a token for the interpreter, which may be
- * used in calls to procedures like Tcl_CreateCmd, Tcl_Eval, or
- * Tcl_DeleteInterp.
+ * The return value is a token for the interpreter, which may be used in
+ * calls to functions like Tcl_CreateCmd, Tcl_Eval, or Tcl_DeleteInterp.
*
* Side effects:
- * The command interpreter is initialized with the built-in commands
- * and with the variables documented in tclvars(n).
+ * The command interpreter is initialized with the built-in commands and
+ * with the variables documented in tclvars(n).
*
*----------------------------------------------------------------------
*/
Tcl_Interp *
-Tcl_CreateInterp()
+Tcl_CreateInterp(void)
{
Interp *iPtr;
Tcl_Interp *interp;
Command *cmdPtr;
- BuiltinFunc *builtinFuncPtr;
- MathFunc *mathFuncPtr;
- Tcl_HashEntry *hPtr;
- CmdInfo *cmdInfoPtr;
- int i;
+ const BuiltinFuncDef *builtinFuncPtr;
+ const OpCmdInfo *opcmdInfoPtr;
+ const CmdInfo *cmdInfoPtr;
+ Tcl_Namespace *mathfuncNSPtr, *mathopNSPtr;
union {
char c[sizeof(short)];
short s;
@@ -313,65 +394,76 @@ Tcl_CreateInterp()
#ifdef TCL_COMPILE_STATS
ByteCodeStats *statsPtr;
#endif /* TCL_COMPILE_STATS */
+ char mathFuncName[32];
+ CallFrame *framePtr;
+ int result;
- TclInitSubsystems(NULL);
+ TclInitSubsystems();
/*
- * Panic if someone updated the CallFrame structure without
- * also updating the Tcl_CallFrame structure (or vice versa).
- */
+ * Panic if someone updated the CallFrame structure without also updating
+ * the Tcl_CallFrame structure (or vice versa).
+ */
if (sizeof(Tcl_CallFrame) < sizeof(CallFrame)) {
/*NOTREACHED*/
- panic("Tcl_CallFrame must not be smaller than CallFrame");
+ Tcl_Panic("Tcl_CallFrame must not be smaller than CallFrame");
}
/*
* Initialize support for namespaces and create the global namespace
- * (whose name is ""; an alias is "::"). This also initializes the
- * Tcl object type table and other object management code.
+ * (whose name is ""; an alias is "::"). This also initializes the Tcl
+ * object type table and other object management code.
*/
iPtr = (Interp *) ckalloc(sizeof(Interp));
interp = (Tcl_Interp *) iPtr;
- iPtr->result = iPtr->resultSpace;
- iPtr->freeProc = NULL;
- iPtr->errorLine = 0;
- iPtr->objResultPtr = Tcl_NewObj();
+ iPtr->result = iPtr->resultSpace;
+ iPtr->freeProc = NULL;
+ iPtr->errorLine = 0;
+ iPtr->objResultPtr = Tcl_NewObj();
Tcl_IncrRefCount(iPtr->objResultPtr);
- iPtr->handle = TclHandleCreate(iPtr);
- iPtr->globalNsPtr = NULL;
- iPtr->hiddenCmdTablePtr = NULL;
- iPtr->interpInfo = NULL;
- Tcl_InitHashTable(&iPtr->mathFuncTable, TCL_STRING_KEYS);
+ iPtr->handle = TclHandleCreate(iPtr);
+ iPtr->globalNsPtr = NULL;
+ iPtr->hiddenCmdTablePtr = NULL;
+ iPtr->interpInfo = NULL;
iPtr->numLevels = 0;
iPtr->maxNestingDepth = MAX_NESTING_DEPTH;
- iPtr->framePtr = NULL;
- iPtr->varFramePtr = NULL;
+ iPtr->framePtr = NULL; /* Initialise as soon as :: is available */
+ iPtr->varFramePtr = NULL; /* Initialise as soon as :: is available */
-#ifdef TCL_TIP280
/*
* TIP #280 - Initialize the arrays used to extend the ByteCode and
* Proc structures.
*/
- iPtr->cmdFramePtr = NULL;
- iPtr->linePBodyPtr = (Tcl_HashTable*) ckalloc (sizeof (Tcl_HashTable));
- iPtr->lineBCPtr = (Tcl_HashTable*) ckalloc (sizeof (Tcl_HashTable));
- iPtr->lineLAPtr = (Tcl_HashTable*) ckalloc (sizeof (Tcl_HashTable));
- iPtr->lineLABCPtr = (Tcl_HashTable*) ckalloc (sizeof (Tcl_HashTable));
+
+ iPtr->cmdFramePtr = NULL;
+ iPtr->linePBodyPtr = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
+ iPtr->lineBCPtr = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
+ iPtr->lineLAPtr = (Tcl_HashTable*) ckalloc (sizeof (Tcl_HashTable));
+ iPtr->lineLABCPtr = (Tcl_HashTable*) ckalloc (sizeof (Tcl_HashTable));
Tcl_InitHashTable(iPtr->linePBodyPtr, TCL_ONE_WORD_KEYS);
- Tcl_InitHashTable(iPtr->lineBCPtr, TCL_ONE_WORD_KEYS);
- Tcl_InitHashTable(iPtr->lineLAPtr, TCL_ONE_WORD_KEYS);
- Tcl_InitHashTable(iPtr->lineLABCPtr, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(iPtr->lineBCPtr, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(iPtr->lineLAPtr, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(iPtr->lineLABCPtr, TCL_ONE_WORD_KEYS);
iPtr->scriptCLLocPtr = NULL;
-#endif
iPtr->activeVarTracePtr = NULL;
- iPtr->returnCode = TCL_OK;
+
+ iPtr->returnOpts = NULL;
iPtr->errorInfo = NULL;
+ TclNewLiteralStringObj(iPtr->eiVar, "::errorInfo");
+ Tcl_IncrRefCount(iPtr->eiVar);
iPtr->errorCode = NULL;
+ TclNewLiteralStringObj(iPtr->ecVar, "::errorCode");
+ Tcl_IncrRefCount(iPtr->ecVar);
+ iPtr->returnLevel = 1;
+ iPtr->returnCode = TCL_OK;
+
+ iPtr->rootFramePtr = NULL; /* Initialise as soon as :: is available */
+ iPtr->lookupNsPtr = NULL;
iPtr->appendResult = NULL;
iPtr->appendAvl = 0;
@@ -379,14 +471,15 @@ Tcl_CreateInterp()
Tcl_InitHashTable(&iPtr->packageTable, TCL_STRING_KEYS);
iPtr->packageUnknown = NULL;
-#ifdef TCL_TIP268
+
/* TIP #268 */
- iPtr->packagePrefer = (getenv ("TCL_PKG_PREFER_LATEST") == NULL ?
- PKG_PREFER_STABLE :
- PKG_PREFER_LATEST);
-#endif
+ if (getenv("TCL_PKG_PREFER_LATEST") == NULL) {
+ iPtr->packagePrefer = PKG_PREFER_STABLE;
+ } else {
+ iPtr->packagePrefer = PKG_PREFER_LATEST;
+ }
+
iPtr->cmdCount = 0;
- iPtr->termOffset = 0;
TclInitLiteralTable(&(iPtr->literalTable));
iPtr->compileEpoch = 0;
iPtr->compiledProcPtr = NULL;
@@ -398,19 +491,56 @@ Tcl_CreateInterp()
iPtr->tracesForbiddingInline = 0;
iPtr->activeCmdTracePtr = NULL;
iPtr->activeInterpTracePtr = NULL;
- iPtr->assocData = (Tcl_HashTable *) NULL;
- iPtr->execEnvPtr = NULL; /* set after namespaces initialized */
- iPtr->emptyObjPtr = Tcl_NewObj(); /* another empty object */
+ iPtr->assocData = NULL;
+ iPtr->execEnvPtr = NULL; /* Set after namespaces initialized. */
+ iPtr->emptyObjPtr = Tcl_NewObj();
+ /* Another empty object. */
Tcl_IncrRefCount(iPtr->emptyObjPtr);
iPtr->resultSpace[0] = 0;
iPtr->threadId = Tcl_GetCurrentThread();
- iPtr->globalNsPtr = NULL; /* force creation of global ns below */
+ /* TIP #378 */
+#ifdef TCL_INTERP_DEBUG_FRAME
+ iPtr->flags |= INTERP_DEBUG_FRAME;
+#else
+ if (getenv("TCL_INTERP_DEBUG_FRAME") != NULL) {
+ iPtr->flags |= INTERP_DEBUG_FRAME;
+ }
+#endif
+
+ /*
+ * Initialise the tables for variable traces and searches *before*
+ * creating the global ns - so that the trace on errorInfo can be
+ * recorded.
+ */
+
+ Tcl_InitHashTable(&iPtr->varTraces, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(&iPtr->varSearches, TCL_ONE_WORD_KEYS);
+
+ iPtr->globalNsPtr = NULL; /* Force creation of global ns below. */
iPtr->globalNsPtr = (Namespace *) Tcl_CreateNamespace(interp, "",
- (ClientData) NULL, (Tcl_NamespaceDeleteProc *) NULL);
+ NULL, NULL);
if (iPtr->globalNsPtr == NULL) {
- panic("Tcl_CreateInterp: can't create global namespace");
+ Tcl_Panic("Tcl_CreateInterp: can't create global namespace");
+ }
+
+ /*
+ * Initialise the rootCallframe. It cannot be allocated on the stack, as
+ * it has to be in place before TclCreateExecEnv tries to use a variable.
+ */
+
+ /* This is needed to satisfy GCC 3.3's strict aliasing rules */
+ framePtr = (CallFrame *) ckalloc(sizeof(CallFrame));
+ result = Tcl_PushCallFrame(interp, (Tcl_CallFrame *) framePtr,
+ (Tcl_Namespace *) iPtr->globalNsPtr, /*isProcCallFrame*/ 0);
+ if (result != TCL_OK) {
+ Tcl_Panic("Tcl_CreateInterp: failed to push the root stack frame");
}
+ framePtr->objc = 0;
+
+ iPtr->framePtr = framePtr;
+ iPtr->varFramePtr = framePtr;
+ iPtr->rootFramePtr = framePtr;
/*
* Initialize support for code compilation and execution. We call
@@ -422,6 +552,12 @@ Tcl_CreateInterp()
iPtr->execEnvPtr = TclCreateExecEnv(interp);
/*
+ * TIP #219, Tcl Channel Reflection API support.
+ */
+
+ iPtr->chanMsg = NULL;
+
+ /*
* Initialize the compilation and execution statistics kept for this
* interpreter.
*/
@@ -431,31 +567,28 @@ Tcl_CreateInterp()
statsPtr->numExecutions = 0;
statsPtr->numCompilations = 0;
statsPtr->numByteCodesFreed = 0;
- (VOID *) memset(statsPtr->instructionCount, 0,
+ (void) memset(statsPtr->instructionCount, 0,
sizeof(statsPtr->instructionCount));
statsPtr->totalSrcBytes = 0.0;
statsPtr->totalByteCodeBytes = 0.0;
statsPtr->currentSrcBytes = 0.0;
statsPtr->currentByteCodeBytes = 0.0;
- (VOID *) memset(statsPtr->srcCount, 0, sizeof(statsPtr->srcCount));
- (VOID *) memset(statsPtr->byteCodeCount, 0,
- sizeof(statsPtr->byteCodeCount));
- (VOID *) memset(statsPtr->lifetimeCount, 0,
- sizeof(statsPtr->lifetimeCount));
-
- statsPtr->currentInstBytes = 0.0;
- statsPtr->currentLitBytes = 0.0;
+ (void) memset(statsPtr->srcCount, 0, sizeof(statsPtr->srcCount));
+ (void) memset(statsPtr->byteCodeCount, 0, sizeof(statsPtr->byteCodeCount));
+ (void) memset(statsPtr->lifetimeCount, 0, sizeof(statsPtr->lifetimeCount));
+
+ statsPtr->currentInstBytes = 0.0;
+ statsPtr->currentLitBytes = 0.0;
statsPtr->currentExceptBytes = 0.0;
- statsPtr->currentAuxBytes = 0.0;
+ statsPtr->currentAuxBytes = 0.0;
statsPtr->currentCmdMapBytes = 0.0;
-
- statsPtr->numLiteralsCreated = 0;
- statsPtr->totalLitStringBytes = 0.0;
+
+ statsPtr->numLiteralsCreated = 0;
+ statsPtr->totalLitStringBytes = 0.0;
statsPtr->currentLitStringBytes = 0.0;
- (VOID *) memset(statsPtr->literalCount, 0,
- sizeof(statsPtr->literalCount));
-#endif /* TCL_COMPILE_STATS */
+ (void) memset(statsPtr->literalCount, 0, sizeof(statsPtr->literalCount));
+#endif /* TCL_COMPILE_STATS */
/*
* Initialise the stub table pointer.
@@ -463,54 +596,74 @@ Tcl_CreateInterp()
iPtr->stubTable = &tclStubs;
-
+ /*
+ * Initialize the ensemble error message rewriting support.
+ */
+
+ iPtr->ensembleRewrite.sourceObjs = NULL;
+ iPtr->ensembleRewrite.numRemovedObjs = 0;
+ iPtr->ensembleRewrite.numInsertedObjs = 0;
+
+ /*
+ * TIP#143: Initialise the resource limit support.
+ */
+
+ TclInitLimitSupport(interp);
+
+ /*
+ * Initialise the thread-specific data ekeko.
+ */
+
+#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
+ iPtr->allocCache = TclpGetAllocCache();
+#else
+ iPtr->allocCache = NULL;
+#endif
+ iPtr->pendingObjDataPtr = NULL;
+ iPtr->asyncReadyPtr = TclGetAsyncReadyPtr();
+
+ /*
+ * Insure that the stack checking mechanism for this interp is
+ * initialized.
+ */
+
+ GetCStackParams(iPtr);
+
/*
* Create the core commands. Do it here, rather than calling
- * Tcl_CreateCommand, because it's faster (there's no need to check for
- * a pre-existing command by the same name). If a command has a
- * Tcl_CmdProc but no Tcl_ObjCmdProc, set the Tcl_ObjCmdProc to
- * TclInvokeStringCommand. This is an object-based wrapper procedure
- * that extracts strings, calls the string procedure, and creates an
- * object for the result. Similarly, if a command has a Tcl_ObjCmdProc
- * but no Tcl_CmdProc, set the Tcl_CmdProc to TclInvokeObjectCommand.
- */
-
- for (cmdInfoPtr = builtInCmds; cmdInfoPtr->name != NULL;
- cmdInfoPtr++) {
- int new;
+ * Tcl_CreateCommand, because it's faster (there's no need to check for a
+ * pre-existing command by the same name). If a command has a Tcl_CmdProc
+ * but no Tcl_ObjCmdProc, set the Tcl_ObjCmdProc to
+ * TclInvokeStringCommand. This is an object-based wrapper function that
+ * extracts strings, calls the string function, and creates an object for
+ * the result. Similarly, if a command has a Tcl_ObjCmdProc but no
+ * Tcl_CmdProc, set the Tcl_CmdProc to TclInvokeObjectCommand.
+ */
+
+ for (cmdInfoPtr = builtInCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) {
+ int isNew;
Tcl_HashEntry *hPtr;
- if ((cmdInfoPtr->proc == (Tcl_CmdProc *) NULL)
- && (cmdInfoPtr->objProc == (Tcl_ObjCmdProc *) NULL)
- && (cmdInfoPtr->compileProc == (CompileProc *) NULL)) {
- panic("Tcl_CreateInterp: builtin command with NULL string and object command procs and a NULL compile proc\n");
+ if ((cmdInfoPtr->objProc == NULL)
+ && (cmdInfoPtr->compileProc == NULL)) {
+ Tcl_Panic("builtin command with NULL object command proc and a NULL compile proc");
}
-
+
hPtr = Tcl_CreateHashEntry(&iPtr->globalNsPtr->cmdTable,
- cmdInfoPtr->name, &new);
- if (new) {
+ cmdInfoPtr->name, &isNew);
+ if (isNew) {
cmdPtr = (Command *) ckalloc(sizeof(Command));
cmdPtr->hPtr = hPtr;
cmdPtr->nsPtr = iPtr->globalNsPtr;
cmdPtr->refCount = 1;
cmdPtr->cmdEpoch = 0;
cmdPtr->compileProc = cmdInfoPtr->compileProc;
- if (cmdInfoPtr->proc == (Tcl_CmdProc *) NULL) {
- cmdPtr->proc = TclInvokeObjectCommand;
- cmdPtr->clientData = (ClientData) cmdPtr;
- } else {
- cmdPtr->proc = cmdInfoPtr->proc;
- cmdPtr->clientData = (ClientData) NULL;
- }
- if (cmdInfoPtr->objProc == (Tcl_ObjCmdProc *) NULL) {
- cmdPtr->objProc = TclInvokeStringCommand;
- cmdPtr->objClientData = (ClientData) cmdPtr;
- } else {
- cmdPtr->objProc = cmdInfoPtr->objProc;
- cmdPtr->objClientData = (ClientData) NULL;
- }
+ cmdPtr->proc = TclInvokeObjectCommand;
+ cmdPtr->clientData = cmdPtr;
+ cmdPtr->objProc = cmdInfoPtr->objProc;
+ cmdPtr->objClientData = NULL;
cmdPtr->deleteProc = NULL;
- cmdPtr->deleteData = (ClientData) NULL;
+ cmdPtr->deleteData = NULL;
cmdPtr->flags = 0;
cmdPtr->importRefPtr = NULL;
cmdPtr->tracePtr = NULL;
@@ -518,6 +671,44 @@ Tcl_CreateInterp()
}
}
+ /*
+ * Create the "chan", "dict", "info" and "string" ensembles. Note that all
+ * these commands (and their subcommands that are not present in the
+ * global namespace) are wholly safe.
+ */
+
+ TclInitChanCmd(interp);
+ TclInitDictCmd(interp);
+ TclInitInfoCmd(interp);
+ TclInitStringCmd(interp);
+
+ /*
+ * Register "clock" subcommands. These *do* go through
+ * Tcl_CreateObjCommand, since they aren't in the global namespace and
+ * involve ensembles.
+ */
+
+ TclClockInit(interp);
+
+ /*
+ * Register the built-in functions. This is empty now that they are
+ * implemented as commands in the ::tcl::mathfunc namespace.
+ */
+
+ /*
+ * Register the default [interp bgerror] handler.
+ */
+
+ Tcl_CreateObjCommand(interp, "::tcl::Bgerror",
+ TclDefaultBgErrorHandlerObjCmd, NULL, NULL);
+
+ /*
+ * Create an unsupported command for debugging bytecode.
+ */
+
+ Tcl_CreateObjCommand(interp, "::tcl::unsupported::disassemble",
+ Tcl_DisassembleObjCmd, NULL, NULL);
+
#ifdef USE_DTRACE
/*
* Register the tcl::dtrace command.
@@ -530,57 +721,61 @@ Tcl_CreateInterp()
* Register the builtin math functions.
*/
- i = 0;
- for (builtinFuncPtr = tclBuiltinFuncTable; builtinFuncPtr->name != NULL;
+ mathfuncNSPtr = Tcl_CreateNamespace(interp, "::tcl::mathfunc", NULL,NULL);
+ if (mathfuncNSPtr == NULL) {
+ Tcl_Panic("Can't create math function namespace");
+ }
+ strcpy(mathFuncName, "::tcl::mathfunc::");
+#define MATH_FUNC_PREFIX_LEN 17 /* == strlen("::tcl::mathfunc::") */
+ for (builtinFuncPtr = BuiltinFuncTable; builtinFuncPtr->name != NULL;
builtinFuncPtr++) {
- Tcl_CreateMathFunc((Tcl_Interp *) iPtr, builtinFuncPtr->name,
- builtinFuncPtr->numArgs, builtinFuncPtr->argTypes,
- (Tcl_MathProc *) NULL, (ClientData) 0);
- hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable,
- builtinFuncPtr->name);
- if (hPtr == NULL) {
- panic("Tcl_CreateInterp: Tcl_CreateMathFunc incorrectly registered '%s'", builtinFuncPtr->name);
- return NULL;
+ strcpy(mathFuncName+MATH_FUNC_PREFIX_LEN, builtinFuncPtr->name);
+ Tcl_CreateObjCommand(interp, mathFuncName,
+ builtinFuncPtr->objCmdProc, builtinFuncPtr->clientData, NULL);
+ Tcl_Export(interp, mathfuncNSPtr, builtinFuncPtr->name, 0);
+ }
+
+ /*
+ * Register the mathematical "operator" commands. [TIP #174]
+ */
+
+ mathopNSPtr = Tcl_CreateNamespace(interp, "::tcl::mathop", NULL, NULL);
+#define MATH_OP_PREFIX_LEN 15 /* == strlen("::tcl::mathop::") */
+ if (mathopNSPtr == NULL) {
+ Tcl_Panic("can't create math operator namespace");
+ }
+ (void) Tcl_Export(interp, mathopNSPtr, "*", 1);
+ strcpy(mathFuncName, "::tcl::mathop::");
+ for (opcmdInfoPtr=mathOpCmds ; opcmdInfoPtr->name!=NULL ; opcmdInfoPtr++){
+ TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)
+ ckalloc(sizeof(TclOpCmdClientData));
+
+ occdPtr->op = opcmdInfoPtr->name;
+ occdPtr->i.numArgs = opcmdInfoPtr->i.numArgs;
+ occdPtr->expected = opcmdInfoPtr->expected;
+ strcpy(mathFuncName + MATH_OP_PREFIX_LEN, opcmdInfoPtr->name);
+ cmdPtr = (Command *) Tcl_CreateObjCommand(interp, mathFuncName,
+ opcmdInfoPtr->objProc, occdPtr, DeleteOpCmdClientData);
+ if (cmdPtr == NULL) {
+ Tcl_Panic("failed to create math operator %s",
+ opcmdInfoPtr->name);
+ } else if (opcmdInfoPtr->compileProc != NULL) {
+ cmdPtr->compileProc = opcmdInfoPtr->compileProc;
}
- mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
- mathFuncPtr->builtinFuncIndex = i;
- i++;
}
- iPtr->flags |= EXPR_INITIALIZED;
/*
* Do Multiple/Safe Interps Tcl init stuff
*/
TclInterpInit(interp);
+ TclSetupEnv(interp);
/*
- * We used to create the "errorInfo" and "errorCode" global vars at this
- * point because so much of the Tcl implementation assumes they already
- * exist. This is not quite enough, however, since they can be unset
- * at any time.
- *
- * There are 2 choices:
- * + Check every place where a GetVar of those is used
- * and the NULL result is not checked (like in tclLoad.c)
- * + Make SetVar,... NULL friendly
- * We choose the second option because :
- * + It is easy and low cost to check for NULL pointer before
- * calling strlen()
- * + It can be helpfull to other people using those API
- * + Passing a NULL value to those closest 'meaning' is empty string
- * (specially with the new objects where 0 bytes strings are ok)
- * So the following init is commented out: -- dl
- *
- * (void) Tcl_SetVar2((Tcl_Interp *)iPtr, "errorInfo", (char *) NULL,
- * "", TCL_GLOBAL_ONLY);
- * (void) Tcl_SetVar2((Tcl_Interp *)iPtr, "errorCode", (char *) NULL,
- * "NONE", TCL_GLOBAL_ONLY);
+ * TIP #59: Make embedded configuration information available.
*/
-#ifndef TCL_GENERIC_ONLY
- TclSetupEnv(interp);
-#endif
+ TclInitEmbeddedConfigurationInformation(interp);
/*
* Compute the byte order of this machine.
@@ -594,62 +789,66 @@ Tcl_CreateInterp()
Tcl_SetVar2Ex(interp, "tcl_platform", "wordSize",
Tcl_NewLongObj((long) sizeof(long)), TCL_GLOBAL_ONLY);
+ /* TIP #291 */
+ Tcl_SetVar2Ex(interp, "tcl_platform", "pointerSize",
+ Tcl_NewLongObj((long) sizeof(void *)), TCL_GLOBAL_ONLY);
+
/*
* Set up other variables such as tcl_version and tcl_library
*/
Tcl_SetVar(interp, "tcl_patchLevel", TCL_PATCH_LEVEL, TCL_GLOBAL_ONLY);
Tcl_SetVar(interp, "tcl_version", TCL_VERSION, TCL_GLOBAL_ONLY);
- Tcl_TraceVar2(interp, "tcl_precision", (char *) NULL,
+ Tcl_TraceVar2(interp, "tcl_precision", NULL,
TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- TclPrecTraceProc, (ClientData) NULL);
+ TclPrecTraceProc, NULL);
TclpSetVariables(interp);
#ifdef TCL_THREADS
/*
- * The existence of the "threaded" element of the tcl_platform array indicates
- * that this particular Tcl shell has been compiled with threads turned on.
- * Using "info exists tcl_platform(threaded)" a Tcl script can introspect on the
- * interpreter level of thread safety.
+ * The existence of the "threaded" element of the tcl_platform array
+ * indicates that this particular Tcl shell has been compiled with threads
+ * turned on. Using "info exists tcl_platform(threaded)" a Tcl script can
+ * introspect on the interpreter level of thread safety.
*/
-
- Tcl_SetVar2(interp, "tcl_platform", "threaded", "1",
- TCL_GLOBAL_ONLY);
+ Tcl_SetVar2(interp, "tcl_platform", "threaded", "1", TCL_GLOBAL_ONLY);
#endif
/*
* Register Tcl's version number.
- * TIP#268: Expose information about its status,
- * for runtime switches in the core library
- * and tests.
+ * TIP #268: Full patchlevel instead of just major.minor
*/
- Tcl_PkgProvideEx(interp, "Tcl", TCL_VERSION, (ClientData) &tclStubs);
+ Tcl_PkgProvideEx(interp, "Tcl", TCL_PATCH_LEVEL, &tclStubs);
-#ifdef TCL_TIP268
- Tcl_SetVar2(interp, "tcl_platform", "tip,268", "1",
- TCL_GLOBAL_ONLY);
-#endif
-#ifdef TCL_TIP280
- Tcl_SetVar2(interp, "tcl_platform", "tip,280", "1",
- TCL_GLOBAL_ONLY);
-#endif
#ifdef Tcl_InitStubs
#undef Tcl_InitStubs
#endif
Tcl_InitStubs(interp, TCL_VERSION, 1);
+ if (TclTommath_Init(interp) != TCL_OK) {
+ Tcl_Panic("%s", Tcl_GetString(Tcl_GetObjResult(interp)));
+ }
+
return interp;
}
+
+static void
+DeleteOpCmdClientData(
+ ClientData clientData)
+{
+ TclOpCmdClientData *occdPtr = clientData;
+
+ ckfree((char *) occdPtr);
+}
/*
*----------------------------------------------------------------------
*
* TclHideUnsafeCommands --
*
- * Hides base commands that are not marked as safe from this
- * interpreter.
+ * Hides base commands that are not marked as safe from this interpreter.
*
* Results:
* TCL_OK if it succeeds, TCL_ERROR else.
@@ -661,18 +860,18 @@ Tcl_CreateInterp()
*/
int
-TclHideUnsafeCommands(interp)
- Tcl_Interp *interp; /* Hide commands in this interpreter. */
+TclHideUnsafeCommands(
+ Tcl_Interp *interp) /* Hide commands in this interpreter. */
{
- register CmdInfo *cmdInfoPtr;
+ register const CmdInfo *cmdInfoPtr;
- if (interp == (Tcl_Interp *) NULL) {
- return TCL_ERROR;
+ if (interp == NULL) {
+ return TCL_ERROR;
}
for (cmdInfoPtr = builtInCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) {
- if (!cmdInfoPtr->isSafe) {
- Tcl_HideCommand(interp, cmdInfoPtr->name, cmdInfoPtr->name);
- }
+ if (!cmdInfoPtr->isSafe) {
+ Tcl_HideCommand(interp, cmdInfoPtr->name, cmdInfoPtr->name);
+ }
}
return TCL_OK;
}
@@ -682,36 +881,34 @@ TclHideUnsafeCommands(interp)
*
* Tcl_CallWhenDeleted --
*
- * Arrange for a procedure to be called before a given
- * interpreter is deleted. The procedure is called as soon
- * as Tcl_DeleteInterp is called; if Tcl_CallWhenDeleted is
- * called on an interpreter that has already been deleted,
- * the procedure will be called when the last Tcl_Release is
+ * Arrange for a function to be called before a given interpreter is
+ * deleted. The function is called as soon as Tcl_DeleteInterp is called;
+ * if Tcl_CallWhenDeleted is called on an interpreter that has already
+ * been deleted, the function will be called when the last Tcl_Release is
* done on the interpreter.
*
* Results:
* None.
*
* Side effects:
- * When Tcl_DeleteInterp is invoked to delete interp,
- * proc will be invoked. See the manual entry for
- * details.
+ * When Tcl_DeleteInterp is invoked to delete interp, proc will be
+ * invoked. See the manual entry for details.
*
*--------------------------------------------------------------
*/
void
-Tcl_CallWhenDeleted(interp, proc, clientData)
- Tcl_Interp *interp; /* Interpreter to watch. */
- Tcl_InterpDeleteProc *proc; /* Procedure to call when interpreter
- * is about to be deleted. */
- ClientData clientData; /* One-word value to pass to proc. */
+Tcl_CallWhenDeleted(
+ Tcl_Interp *interp, /* Interpreter to watch. */
+ Tcl_InterpDeleteProc *proc, /* Function to call when interpreter is about
+ * to be deleted. */
+ ClientData clientData) /* One-word value to pass to proc. */
{
Interp *iPtr = (Interp *) interp;
static Tcl_ThreadDataKey assocDataCounterKey;
int *assocDataCounterPtr =
Tcl_GetThreadData(&assocDataCounterKey, (int)sizeof(int));
- int new;
+ int isNew;
char buffer[32 + TCL_INTEGER_SPACE];
AssocData *dPtr = (AssocData *) ckalloc(sizeof(AssocData));
Tcl_HashEntry *hPtr;
@@ -719,11 +916,11 @@ Tcl_CallWhenDeleted(interp, proc, clientData)
sprintf(buffer, "Assoc Data Key #%d", *assocDataCounterPtr);
(*assocDataCounterPtr)++;
- if (iPtr->assocData == (Tcl_HashTable *) NULL) {
- iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
- Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);
+ if (iPtr->assocData == NULL) {
+ iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
+ Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);
}
- hPtr = Tcl_CreateHashEntry(iPtr->assocData, buffer, &new);
+ hPtr = Tcl_CreateHashEntry(iPtr->assocData, buffer, &isNew);
dPtr->proc = proc;
dPtr->clientData = clientData;
Tcl_SetHashValue(hPtr, dPtr);
@@ -734,27 +931,26 @@ Tcl_CallWhenDeleted(interp, proc, clientData)
*
* Tcl_DontCallWhenDeleted --
*
- * Cancel the arrangement for a procedure to be called when
- * a given interpreter is deleted.
+ * Cancel the arrangement for a function to be called when a given
+ * interpreter is deleted.
*
* Results:
* None.
*
* Side effects:
- * If proc and clientData were previously registered as a
- * callback via Tcl_CallWhenDeleted, they are unregistered.
- * If they weren't previously registered then nothing
- * happens.
+ * If proc and clientData were previously registered as a callback via
+ * Tcl_CallWhenDeleted, they are unregistered. If they weren't previously
+ * registered then nothing happens.
*
*--------------------------------------------------------------
*/
void
-Tcl_DontCallWhenDeleted(interp, proc, clientData)
- Tcl_Interp *interp; /* Interpreter to watch. */
- Tcl_InterpDeleteProc *proc; /* Procedure to call when interpreter
- * is about to be deleted. */
- ClientData clientData; /* One-word value to pass to proc. */
+Tcl_DontCallWhenDeleted(
+ Tcl_Interp *interp, /* Interpreter to watch. */
+ Tcl_InterpDeleteProc *proc, /* Function to call when interpreter is about
+ * to be deleted. */
+ ClientData clientData) /* One-word value to pass to proc. */
{
Interp *iPtr = (Interp *) interp;
Tcl_HashTable *hTablePtr;
@@ -763,17 +959,17 @@ Tcl_DontCallWhenDeleted(interp, proc, clientData)
AssocData *dPtr;
hTablePtr = iPtr->assocData;
- if (hTablePtr == (Tcl_HashTable *) NULL) {
- return;
+ if (hTablePtr == NULL) {
+ return;
}
for (hPtr = Tcl_FirstHashEntry(hTablePtr, &hSearch); hPtr != NULL;
hPtr = Tcl_NextHashEntry(&hSearch)) {
- dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
- if ((dPtr->proc == proc) && (dPtr->clientData == clientData)) {
- ckfree((char *) dPtr);
- Tcl_DeleteHashEntry(hPtr);
- return;
- }
+ dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
+ if ((dPtr->proc == proc) && (dPtr->clientData == clientData)) {
+ ckfree((char *) dPtr);
+ Tcl_DeleteHashEntry(hPtr);
+ return;
+ }
}
}
@@ -783,9 +979,9 @@ Tcl_DontCallWhenDeleted(interp, proc, clientData)
* Tcl_SetAssocData --
*
* Creates a named association between user-specified data, a delete
- * function and this interpreter. If the association already exists
- * the data is overwritten with the new data. The delete function will
- * be invoked when the interpreter is deleted.
+ * function and this interpreter. If the association already exists the
+ * data is overwritten with the new data. The delete function will be
+ * invoked when the interpreter is deleted.
*
* Results:
* None.
@@ -797,27 +993,27 @@ Tcl_DontCallWhenDeleted(interp, proc, clientData)
*/
void
-Tcl_SetAssocData(interp, name, proc, clientData)
- Tcl_Interp *interp; /* Interpreter to associate with. */
- CONST char *name; /* Name for association. */
- Tcl_InterpDeleteProc *proc; /* Proc to call when interpreter is
- * about to be deleted. */
- ClientData clientData; /* One-word value to pass to proc. */
+Tcl_SetAssocData(
+ Tcl_Interp *interp, /* Interpreter to associate with. */
+ const char *name, /* Name for association. */
+ Tcl_InterpDeleteProc *proc, /* Proc to call when interpreter is about to
+ * be deleted. */
+ ClientData clientData) /* One-word value to pass to proc. */
{
Interp *iPtr = (Interp *) interp;
AssocData *dPtr;
Tcl_HashEntry *hPtr;
- int new;
+ int isNew;
- if (iPtr->assocData == (Tcl_HashTable *) NULL) {
- iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
- Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);
+ if (iPtr->assocData == NULL) {
+ iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
+ Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);
}
- hPtr = Tcl_CreateHashEntry(iPtr->assocData, name, &new);
- if (new == 0) {
- dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
+ hPtr = Tcl_CreateHashEntry(iPtr->assocData, name, &isNew);
+ if (isNew == 0) {
+ dPtr = Tcl_GetHashValue(hPtr);
} else {
- dPtr = (AssocData *) ckalloc(sizeof(AssocData));
+ dPtr = (AssocData *) ckalloc(sizeof(AssocData));
}
dPtr->proc = proc;
dPtr->clientData = clientData;
@@ -830,8 +1026,8 @@ Tcl_SetAssocData(interp, name, proc, clientData)
*
* Tcl_DeleteAssocData --
*
- * Deletes a named association of user-specified data with
- * the specified interpreter.
+ * Deletes a named association of user-specified data with the specified
+ * interpreter.
*
* Results:
* None.
@@ -843,24 +1039,24 @@ Tcl_SetAssocData(interp, name, proc, clientData)
*/
void
-Tcl_DeleteAssocData(interp, name)
- Tcl_Interp *interp; /* Interpreter to associate with. */
- CONST char *name; /* Name of association. */
+Tcl_DeleteAssocData(
+ Tcl_Interp *interp, /* Interpreter to associate with. */
+ const char *name) /* Name of association. */
{
Interp *iPtr = (Interp *) interp;
AssocData *dPtr;
Tcl_HashEntry *hPtr;
- if (iPtr->assocData == (Tcl_HashTable *) NULL) {
- return;
+ if (iPtr->assocData == NULL) {
+ return;
}
hPtr = Tcl_FindHashEntry(iPtr->assocData, name);
- if (hPtr == (Tcl_HashEntry *) NULL) {
- return;
+ if (hPtr == NULL) {
+ return;
}
- dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
+ dPtr = Tcl_GetHashValue(hPtr);
if (dPtr->proc != NULL) {
- (dPtr->proc) (dPtr->clientData, interp);
+ dPtr->proc(dPtr->clientData, interp);
}
ckfree((char *) dPtr);
Tcl_DeleteHashEntry(hPtr);
@@ -871,8 +1067,8 @@ Tcl_DeleteAssocData(interp, name)
*
* Tcl_GetAssocData --
*
- * Returns the client data associated with this name in the
- * specified interpreter.
+ * Returns the client data associated with this name in the specified
+ * interpreter.
*
* Results:
* The client data in the AssocData record denoted by the named
@@ -885,26 +1081,27 @@ Tcl_DeleteAssocData(interp, name)
*/
ClientData
-Tcl_GetAssocData(interp, name, procPtr)
- Tcl_Interp *interp; /* Interpreter associated with. */
- CONST char *name; /* Name of association. */
- Tcl_InterpDeleteProc **procPtr; /* Pointer to place to store address
- * of current deletion callback. */
+Tcl_GetAssocData(
+ Tcl_Interp *interp, /* Interpreter associated with. */
+ const char *name, /* Name of association. */
+ Tcl_InterpDeleteProc **procPtr)
+ /* Pointer to place to store address of
+ * current deletion callback. */
{
Interp *iPtr = (Interp *) interp;
AssocData *dPtr;
Tcl_HashEntry *hPtr;
- if (iPtr->assocData == (Tcl_HashTable *) NULL) {
- return (ClientData) NULL;
+ if (iPtr->assocData == NULL) {
+ return NULL;
}
hPtr = Tcl_FindHashEntry(iPtr->assocData, name);
- if (hPtr == (Tcl_HashEntry *) NULL) {
- return (ClientData) NULL;
+ if (hPtr == NULL) {
+ return NULL;
}
- dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
- if (procPtr != (Tcl_InterpDeleteProc **) NULL) {
- *procPtr = dPtr->proc;
+ dPtr = Tcl_GetHashValue(hPtr);
+ if (procPtr != NULL) {
+ *procPtr = dPtr->proc;
}
return dPtr->clientData;
}
@@ -914,8 +1111,8 @@ Tcl_GetAssocData(interp, name, procPtr)
*
* Tcl_InterpDeleted --
*
- * Returns nonzero if the interpreter has been deleted with a call
- * to Tcl_DeleteInterp.
+ * Returns nonzero if the interpreter has been deleted with a call to
+ * Tcl_DeleteInterp.
*
* Results:
* Nonzero if the interpreter is deleted, zero otherwise.
@@ -927,8 +1124,8 @@ Tcl_GetAssocData(interp, name, procPtr)
*/
int
-Tcl_InterpDeleted(interp)
- Tcl_Interp *interp;
+Tcl_InterpDeleted(
+ Tcl_Interp *interp)
{
return (((Interp *) interp)->flags & DELETED) ? 1 : 0;
}
@@ -938,11 +1135,11 @@ Tcl_InterpDeleted(interp)
*
* Tcl_DeleteInterp --
*
- * Ensures that the interpreter will be deleted eventually. If there
- * are no Tcl_Preserve calls in effect for this interpreter, it is
- * deleted immediately, otherwise the interpreter is deleted when
- * the last Tcl_Preserve is matched by a call to Tcl_Release. In either
- * case, the procedure runs the currently registered deletion callbacks.
+ * Ensures that the interpreter will be deleted eventually. If there are
+ * no Tcl_Preserve calls in effect for this interpreter, it is deleted
+ * immediately, otherwise the interpreter is deleted when the last
+ * Tcl_Preserve is matched by a call to Tcl_Release. In either case, the
+ * function runs the currently registered deletion callbacks.
*
* Results:
* None.
@@ -957,9 +1154,9 @@ Tcl_InterpDeleted(interp)
*/
void
-Tcl_DeleteInterp(interp)
- Tcl_Interp *interp; /* Token for command interpreter (returned
- * by a previous call to Tcl_CreateInterp). */
+Tcl_DeleteInterp(
+ Tcl_Interp *interp) /* Token for command interpreter (returned by
+ * a previous call to Tcl_CreateInterp). */
{
Interp *iPtr = (Interp *) interp;
@@ -968,21 +1165,22 @@ Tcl_DeleteInterp(interp)
*/
if (iPtr->flags & DELETED) {
- return;
+ return;
}
-
+
/*
* Mark the interpreter as deleted. No further evals will be allowed.
+ * Increase the compileEpoch as a signal to compiled bytecodes.
*/
iPtr->flags |= DELETED;
+ iPtr->compileEpoch++;
/*
* Ensure that the interpreter is eventually deleted.
*/
- Tcl_EventuallyFree((ClientData) interp,
- (Tcl_FreeProc *) DeleteInterpProc);
+ Tcl_EventuallyFree(interp, (Tcl_FreeProc *) DeleteInterpProc);
}
/*
@@ -990,25 +1188,25 @@ Tcl_DeleteInterp(interp)
*
* DeleteInterpProc --
*
- * Helper procedure to delete an interpreter. This procedure is
- * called when the last call to Tcl_Preserve on this interpreter
- * is matched by a call to Tcl_Release. The procedure cleans up
- * all resources used in the interpreter and calls all currently
- * registered interpreter deletion callbacks.
+ * Helper function to delete an interpreter. This function is called when
+ * the last call to Tcl_Preserve on this interpreter is matched by a call
+ * to Tcl_Release. The function cleans up all resources used in the
+ * interpreter and calls all currently registered interpreter deletion
+ * callbacks.
*
* Results:
* None.
*
* Side effects:
- * Whatever the interpreter deletion callbacks do. Frees resources
- * used by the interpreter.
+ * Whatever the interpreter deletion callbacks do. Frees resources used
+ * by the interpreter.
*
*----------------------------------------------------------------------
*/
static void
-DeleteInterpProc(interp)
- Tcl_Interp *interp; /* Interpreter to delete. */
+DeleteInterpProc(
+ Tcl_Interp *interp) /* Interpreter to delete. */
{
Interp *iPtr = (Interp *) interp;
Tcl_HashEntry *hPtr;
@@ -1019,120 +1217,137 @@ DeleteInterpProc(interp)
/*
* Punt if there is an error in the Tcl_Release/Tcl_Preserve matchup.
*/
-
+
if (iPtr->numLevels > 0) {
- panic("DeleteInterpProc called with active evals");
+ Tcl_Panic("DeleteInterpProc called with active evals");
}
/*
- * The interpreter should already be marked deleted; otherwise how
- * did we get here?
+ * The interpreter should already be marked deleted; otherwise how did we
+ * get here?
*/
if (!(iPtr->flags & DELETED)) {
- panic("DeleteInterpProc called on interpreter not marked deleted");
+ Tcl_Panic("DeleteInterpProc called on interpreter not marked deleted");
}
- TclHandleFree(iPtr->handle);
+ /*
+ * TIP #219, Tcl Channel Reflection API. Discard a leftover state.
+ */
+
+ if (iPtr->chanMsg != NULL) {
+ Tcl_DecrRefCount(iPtr->chanMsg);
+ iPtr->chanMsg = NULL;
+ }
+
+ /*
+ * Shut down all limit handler callback scripts that call back into this
+ * interpreter. Then eliminate all limit handlers for this interpreter.
+ */
+
+ TclRemoveScriptLimitCallbacks(interp);
+ TclLimitRemoveAllHandlers(interp);
/*
- * Dismantle everything in the global namespace except for the
- * "errorInfo" and "errorCode" variables. These remain until the
- * namespace is actually destroyed, in case any errors occur.
- *
* Dismantle the namespace here, before we clear the assocData. If any
* background errors occur here, they will be deleted below.
+ *
+ * Dismantle the namespace after freeing the iPtr->handle so that each
+ * bytecode releases its literals without caring to update the literal
+ * table, as it will be freed later in this function without further use.
*/
-
+
+ TclHandleFree(iPtr->handle);
TclTeardownNamespace(iPtr->globalNsPtr);
/*
* Delete all the hidden commands.
*/
-
+
hTablePtr = iPtr->hiddenCmdTablePtr;
if (hTablePtr != NULL) {
/*
- * Non-pernicious deletion. The deletion callbacks will not be
- * allowed to create any new hidden or non-hidden commands.
+ * Non-pernicious deletion. The deletion callbacks will not be allowed
+ * to create any new hidden or non-hidden commands.
* Tcl_DeleteCommandFromToken() will remove the entry from the
* hiddenCmdTablePtr.
*/
-
+
hPtr = Tcl_FirstHashEntry(hTablePtr, &search);
- for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ for (; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
Tcl_DeleteCommandFromToken(interp,
(Tcl_Command) Tcl_GetHashValue(hPtr));
}
Tcl_DeleteHashTable(hTablePtr);
ckfree((char *) hTablePtr);
}
+
/*
- * Tear down the math function table.
+ * Invoke deletion callbacks; note that a callback can create new
+ * callbacks, so we iterate.
*/
- for (hPtr = Tcl_FirstHashEntry(&iPtr->mathFuncTable, &search);
- hPtr != NULL;
- hPtr = Tcl_NextHashEntry(&search)) {
- ckfree((char *) Tcl_GetHashValue(hPtr));
+ while (iPtr->assocData != NULL) {
+ AssocData *dPtr;
+
+ hTablePtr = iPtr->assocData;
+ iPtr->assocData = NULL;
+ for (hPtr = Tcl_FirstHashEntry(hTablePtr, &search);
+ hPtr != NULL;
+ hPtr = Tcl_FirstHashEntry(hTablePtr, &search)) {
+ dPtr = Tcl_GetHashValue(hPtr);
+ Tcl_DeleteHashEntry(hPtr);
+ if (dPtr->proc != NULL) {
+ dPtr->proc(dPtr->clientData, interp);
+ }
+ ckfree((char *) dPtr);
+ }
+ Tcl_DeleteHashTable(hTablePtr);
+ ckfree((char *) hTablePtr);
}
- Tcl_DeleteHashTable(&iPtr->mathFuncTable);
/*
- * Invoke deletion callbacks; note that a callback can create new
- * callbacks, so we iterate.
+ * Pop the root frame pointer and finish deleting the global
+ * namespace. The order is important [Bug 1658572].
*/
- while (iPtr->assocData != (Tcl_HashTable *) NULL) {
- AssocData *dPtr;
-
- hTablePtr = iPtr->assocData;
- iPtr->assocData = (Tcl_HashTable *) NULL;
- for (hPtr = Tcl_FirstHashEntry(hTablePtr, &search);
- hPtr != NULL;
- hPtr = Tcl_FirstHashEntry(hTablePtr, &search)) {
- dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
- Tcl_DeleteHashEntry(hPtr);
- if (dPtr->proc != NULL) {
- (*dPtr->proc)(dPtr->clientData, interp);
- }
- ckfree((char *) dPtr);
- }
- Tcl_DeleteHashTable(hTablePtr);
- ckfree((char *) hTablePtr);
- }
-
- /*
- * Finish deleting the global namespace.
- */
-
+ if (iPtr->framePtr != iPtr->rootFramePtr) {
+ Tcl_Panic("DeleteInterpProc: popping rootCallFrame with other frames on top");
+ }
+ Tcl_PopCallFrame(interp);
+ ckfree((char *) iPtr->rootFramePtr);
+ iPtr->rootFramePtr = NULL;
Tcl_DeleteNamespace((Tcl_Namespace *) iPtr->globalNsPtr);
/*
- * Free up the result *after* deleting variables, since variable
- * deletion could have transferred ownership of the result string
- * to Tcl.
+ * Free up the result *after* deleting variables, since variable deletion
+ * could have transferred ownership of the result string to Tcl.
*/
Tcl_FreeResult(interp);
interp->result = NULL;
Tcl_DecrRefCount(iPtr->objResultPtr);
iPtr->objResultPtr = NULL;
- if (iPtr->errorInfo != NULL) {
- ckfree(iPtr->errorInfo);
- iPtr->errorInfo = NULL;
+ Tcl_DecrRefCount(iPtr->ecVar);
+ if (iPtr->errorCode) {
+ Tcl_DecrRefCount(iPtr->errorCode);
+ iPtr->errorCode = NULL;
+ }
+ Tcl_DecrRefCount(iPtr->eiVar);
+ if (iPtr->errorInfo) {
+ Tcl_DecrRefCount(iPtr->errorInfo);
+ iPtr->errorInfo = NULL;
}
- if (iPtr->errorCode != NULL) {
- ckfree(iPtr->errorCode);
- iPtr->errorCode = NULL;
+ if (iPtr->returnOpts) {
+ Tcl_DecrRefCount(iPtr->returnOpts);
}
if (iPtr->appendResult != NULL) {
ckfree(iPtr->appendResult);
- iPtr->appendResult = NULL;
+ iPtr->appendResult = NULL;
}
TclFreePackageInfo(iPtr);
while (iPtr->tracePtr != NULL) {
- Tcl_DeleteTrace((Tcl_Interp*) iPtr, (Tcl_Trace) iPtr->tracePtr);
+ Tcl_DeleteTrace((Tcl_Interp *) iPtr, (Tcl_Trace) iPtr->tracePtr);
}
if (iPtr->execEnvPtr != NULL) {
TclDeleteExecEnv(iPtr->execEnvPtr);
@@ -1145,9 +1360,9 @@ DeleteInterpProc(interp)
nextResPtr = resPtr->nextPtr;
ckfree(resPtr->name);
ckfree((char *) resPtr);
- resPtr = nextResPtr;
+ resPtr = nextResPtr;
}
-
+
/*
* Free up literal objects created for scripts compiled by the
* interpreter.
@@ -1155,60 +1370,59 @@ DeleteInterpProc(interp)
TclDeleteLiteralTable(interp, &(iPtr->literalTable));
-#ifdef TCL_TIP280
- /* TIP #280 - Release the arrays for ByteCode/Proc extension, and contents.
+ /*
+ * TIP #280 - Release the arrays for ByteCode/Proc extension, and
+ * contents.
*/
+
{
- Tcl_HashEntry *hPtr;
+ Tcl_HashEntry *hPtr;
Tcl_HashSearch hSearch;
- CmdFrame* cfPtr;
- ExtCmdLoc* eclPtr;
- int i;
+ int i;
for (hPtr = Tcl_FirstHashEntry(iPtr->linePBodyPtr, &hSearch);
- hPtr != NULL;
- hPtr = Tcl_NextHashEntry(&hSearch)) {
-
- cfPtr = (CmdFrame*) Tcl_GetHashValue (hPtr);
+ hPtr != NULL;
+ hPtr = Tcl_NextHashEntry(&hSearch)) {
+ CmdFrame *cfPtr = Tcl_GetHashValue(hPtr);
if (cfPtr->type == TCL_LOCATION_SOURCE) {
- Tcl_DecrRefCount (cfPtr->data.eval.path);
+ Tcl_DecrRefCount(cfPtr->data.eval.path);
}
- ckfree ((char*) cfPtr->line);
- ckfree ((char*) cfPtr);
- Tcl_DeleteHashEntry (hPtr);
-
+ ckfree((char *) cfPtr->line);
+ ckfree((char *) cfPtr);
+ Tcl_DeleteHashEntry(hPtr);
}
- Tcl_DeleteHashTable (iPtr->linePBodyPtr);
- ckfree ((char*) iPtr->linePBodyPtr);
+ Tcl_DeleteHashTable(iPtr->linePBodyPtr);
+ ckfree((char *) iPtr->linePBodyPtr);
iPtr->linePBodyPtr = NULL;
- /* See also tclCompile.c, TclCleanupByteCode */
+ /*
+ * See also tclCompile.c, TclCleanupByteCode
+ */
for (hPtr = Tcl_FirstHashEntry(iPtr->lineBCPtr, &hSearch);
- hPtr != NULL;
- hPtr = Tcl_NextHashEntry(&hSearch)) {
-
- eclPtr = (ExtCmdLoc*) Tcl_GetHashValue (hPtr);
+ hPtr != NULL;
+ hPtr = Tcl_NextHashEntry(&hSearch)) {
+ ExtCmdLoc *eclPtr = (ExtCmdLoc *) Tcl_GetHashValue(hPtr);
if (eclPtr->type == TCL_LOCATION_SOURCE) {
- Tcl_DecrRefCount (eclPtr->path);
+ Tcl_DecrRefCount(eclPtr->path);
}
for (i=0; i< eclPtr->nuloc; i++) {
- ckfree ((char*) eclPtr->loc[i].line);
+ ckfree((char *) eclPtr->loc[i].line);
}
- if (eclPtr->loc != NULL) {
- ckfree ((char*) eclPtr->loc);
+ if (eclPtr->loc != NULL) {
+ ckfree((char *) eclPtr->loc);
}
Tcl_DeleteHashTable (&eclPtr->litInfo);
- ckfree ((char*) eclPtr);
- Tcl_DeleteHashEntry (hPtr);
+ ckfree((char *) eclPtr);
+ Tcl_DeleteHashEntry(hPtr);
}
- Tcl_DeleteHashTable (iPtr->lineBCPtr);
- ckfree((char*) iPtr->lineBCPtr);
+ Tcl_DeleteHashTable(iPtr->lineBCPtr);
+ ckfree((char *) iPtr->lineBCPtr);
iPtr->lineBCPtr = NULL;
/*
@@ -1244,7 +1458,10 @@ DeleteInterpProc(interp)
ckfree((char*) iPtr->lineLABCPtr);
iPtr->lineLABCPtr = NULL;
}
-#endif
+
+ Tcl_DeleteHashTable(&iPtr->varTraces);
+ Tcl_DeleteHashTable(&iPtr->varSearches);
+
ckfree((char *) iPtr);
}
@@ -1253,79 +1470,77 @@ DeleteInterpProc(interp)
*
* Tcl_HideCommand --
*
- * Makes a command hidden so that it cannot be invoked from within
- * an interpreter, only from within an ancestor.
+ * Makes a command hidden so that it cannot be invoked from within an
+ * interpreter, only from within an ancestor.
*
* Results:
- * A standard Tcl result; also leaves a message in the interp's result
- * if an error occurs.
+ * A standard Tcl result; also leaves a message in the interp's result if
+ * an error occurs.
*
* Side effects:
- * Removes a command from the command table and create an entry
- * into the hidden command table under the specified token name.
+ * Removes a command from the command table and create an entry into the
+ * hidden command table under the specified token name.
*
*---------------------------------------------------------------------------
*/
int
-Tcl_HideCommand(interp, cmdName, hiddenCmdToken)
- Tcl_Interp *interp; /* Interpreter in which to hide command. */
- CONST char *cmdName; /* Name of command to hide. */
- CONST char *hiddenCmdToken; /* Token name of the to-be-hidden command. */
+Tcl_HideCommand(
+ Tcl_Interp *interp, /* Interpreter in which to hide command. */
+ const char *cmdName, /* Name of command to hide. */
+ const char *hiddenCmdToken) /* Token name of the to-be-hidden command. */
{
Interp *iPtr = (Interp *) interp;
Tcl_Command cmd;
Command *cmdPtr;
Tcl_HashTable *hiddenCmdTablePtr;
Tcl_HashEntry *hPtr;
- int new;
+ int isNew;
if (iPtr->flags & DELETED) {
+ /*
+ * The interpreter is being deleted. Do not create any new structures,
+ * because it is not safe to modify the interpreter.
+ */
- /*
- * The interpreter is being deleted. Do not create any new
- * structures, because it is not safe to modify the interpreter.
- */
-
- return TCL_ERROR;
+ return TCL_ERROR;
}
/*
* Disallow hiding of commands that are currently in a namespace or
- * renaming (as part of hiding) into a namespace.
- *
- * (because the current implementation with a single global table
- * and the needed uniqueness of names cause problems with namespaces)
+ * renaming (as part of hiding) into a namespace (because the current
+ * implementation with a single global table and the needed uniqueness of
+ * names cause problems with namespaces).
*
- * we don't need to check for "::" in cmdName because the real check is
- * on the nsPtr below.
+ * We don't need to check for "::" in cmdName because the real check is on
+ * the nsPtr below.
*
- * hiddenCmdToken is just a string which is not interpreted in any way.
- * It may contain :: but the string is not interpreted as a namespace
+ * hiddenCmdToken is just a string which is not interpreted in any way. It
+ * may contain :: but the string is not interpreted as a namespace
* qualifier command name. Thus, hiding foo::bar to foo::bar and then
* trying to expose or invoke ::foo::bar will NOT work; but if the
* application always uses the same strings it will get consistent
* behaviour.
*
- * But as we currently limit ourselves to the global namespace only
- * for the source, in order to avoid potential confusion,
- * lets prevent "::" in the token too. --dl
+ * But as we currently limit ourselves to the global namespace only for
+ * the source, in order to avoid potential confusion, lets prevent "::" in
+ * the token too. - dl
*/
if (strstr(hiddenCmdToken, "::") != NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "cannot use namespace qualifiers in hidden command",
- " token (rename)", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp,
+ "cannot use namespace qualifiers in hidden command"
+ " token (rename)", NULL);
+ return TCL_ERROR;
}
/*
- * Find the command to hide. An error is returned if cmdName can't
- * be found. Look up the command only from the global namespace.
- * Full path of the command must be given if using namespaces.
+ * Find the command to hide. An error is returned if cmdName can't be
+ * found. Look up the command only from the global namespace. Full path of
+ * the command must be given if using namespaces.
*/
- cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL,
+ cmd = Tcl_FindCommand(interp, cmdName, NULL,
/*flags*/ TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
if (cmd == (Tcl_Command) NULL) {
return TCL_ERROR;
@@ -1336,22 +1551,21 @@ Tcl_HideCommand(interp, cmdName, hiddenCmdToken)
* Check that the command is really in global namespace
*/
- if ( cmdPtr->nsPtr != iPtr->globalNsPtr ) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "can only hide global namespace commands",
- " (use rename then hide)", (char *) NULL);
- return TCL_ERROR;
+ if (cmdPtr->nsPtr != iPtr->globalNsPtr) {
+ Tcl_AppendResult(interp, "can only hide global namespace commands"
+ " (use rename then hide)", NULL);
+ return TCL_ERROR;
}
-
+
/*
* Initialize the hidden command table if necessary.
*/
hiddenCmdTablePtr = iPtr->hiddenCmdTablePtr;
if (hiddenCmdTablePtr == NULL) {
- hiddenCmdTablePtr = (Tcl_HashTable *)
- ckalloc((unsigned) sizeof(Tcl_HashTable));
- Tcl_InitHashTable(hiddenCmdTablePtr, TCL_STRING_KEYS);
+ hiddenCmdTablePtr = (Tcl_HashTable *)
+ ckalloc((unsigned) sizeof(Tcl_HashTable));
+ Tcl_InitHashTable(hiddenCmdTablePtr, TCL_STRING_KEYS);
iPtr->hiddenCmdTablePtr = hiddenCmdTablePtr;
}
@@ -1360,20 +1574,18 @@ Tcl_HideCommand(interp, cmdName, hiddenCmdToken)
* hiddenCmdToken if a hidden command with the name hiddenCmdToken already
* exists.
*/
-
- hPtr = Tcl_CreateHashEntry(hiddenCmdTablePtr, hiddenCmdToken, &new);
- if (!new) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "hidden command named \"", hiddenCmdToken, "\" already exists",
- (char *) NULL);
- return TCL_ERROR;
+
+ hPtr = Tcl_CreateHashEntry(hiddenCmdTablePtr, hiddenCmdToken, &isNew);
+ if (!isNew) {
+ Tcl_AppendResult(interp, "hidden command named \"", hiddenCmdToken,
+ "\" already exists", NULL);
+ return TCL_ERROR;
}
/*
- * Nb : This code is currently 'like' a rename to a specialy set apart
- * name table. Changes here and in TclRenameCommand must
- * be kept in synch untill the common parts are actually
- * factorized out.
+ * NB: This code is currently 'like' a rename to a specialy set apart name
+ * table. Changes here and in TclRenameCommand must be kept in synch until
+ * the common parts are actually factorized out.
*/
/*
@@ -1383,26 +1595,34 @@ Tcl_HideCommand(interp, cmdName, hiddenCmdToken)
*/
if (cmdPtr->hPtr != NULL) {
- Tcl_DeleteHashEntry(cmdPtr->hPtr);
- cmdPtr->hPtr = (Tcl_HashEntry *) NULL;
+ Tcl_DeleteHashEntry(cmdPtr->hPtr);
+ cmdPtr->hPtr = NULL;
cmdPtr->cmdEpoch++;
}
/*
- * Now link the hash table entry with the command structure.
- * We ensured above that the nsPtr was right.
+ * The list of command exported from the namespace might have changed.
+ * However, we do not need to recompute this just yet; next time we need
+ * the info will be soon enough.
*/
-
+
+ TclInvalidateNsCmdLookup(cmdPtr->nsPtr);
+
+ /*
+ * Now link the hash table entry with the command structure. We ensured
+ * above that the nsPtr was right.
+ */
+
cmdPtr->hPtr = hPtr;
- Tcl_SetHashValue(hPtr, (ClientData) cmdPtr);
+ Tcl_SetHashValue(hPtr, cmdPtr);
/*
- * If the command being hidden has a compile procedure, increment the
- * interpreter's compileEpoch to invalidate its compiled code. This
- * makes sure that we don't later try to execute old code compiled with
- * command-specific (i.e., inline) bytecodes for the now-hidden
- * command. This field is checked in Tcl_EvalObj and ObjInterpProc,
- * and code whose compilation epoch doesn't match is recompiled.
+ * If the command being hidden has a compile function, increment the
+ * interpreter's compileEpoch to invalidate its compiled code. This makes
+ * sure that we don't later try to execute old code compiled with
+ * command-specific (i.e., inline) bytecodes for the now-hidden command.
+ * This field is checked in Tcl_EvalObj and ObjInterpProc, and code whose
+ * compilation epoch doesn't match is recompiled.
*/
if (cmdPtr->compileProc != NULL) {
@@ -1416,12 +1636,12 @@ Tcl_HideCommand(interp, cmdName, hiddenCmdToken)
*
* Tcl_ExposeCommand --
*
- * Makes a previously hidden command callable from inside the
- * interpreter instead of only by its ancestors.
+ * Makes a previously hidden command callable from inside the interpreter
+ * instead of only by its ancestors.
*
* Results:
- * A standard Tcl result. If an error occurs, a message is left
- * in the interp's result.
+ * A standard Tcl result. If an error occurs, a message is left in the
+ * interp's result.
*
* Side effects:
* Moves commands from one hash table to another.
@@ -1430,40 +1650,38 @@ Tcl_HideCommand(interp, cmdName, hiddenCmdToken)
*/
int
-Tcl_ExposeCommand(interp, hiddenCmdToken, cmdName)
- Tcl_Interp *interp; /* Interpreter in which to make command
- * callable. */
- CONST char *hiddenCmdToken; /* Name of hidden command. */
- CONST char *cmdName; /* Name of to-be-exposed command. */
+Tcl_ExposeCommand(
+ Tcl_Interp *interp, /* Interpreter in which to make command
+ * callable. */
+ const char *hiddenCmdToken, /* Name of hidden command. */
+ const char *cmdName) /* Name of to-be-exposed command. */
{
Interp *iPtr = (Interp *) interp;
Command *cmdPtr;
Namespace *nsPtr;
Tcl_HashEntry *hPtr;
Tcl_HashTable *hiddenCmdTablePtr;
- int new;
+ int isNew;
if (iPtr->flags & DELETED) {
- /*
- * The interpreter is being deleted. Do not create any new
- * structures, because it is not safe to modify the interpreter.
- */
-
- return TCL_ERROR;
+ /*
+ * The interpreter is being deleted. Do not create any new structures,
+ * because it is not safe to modify the interpreter.
+ */
+
+ return TCL_ERROR;
}
/*
- * Check that we have a regular name for the command
- * (that the user is not trying to do an expose and a rename
- * (to another namespace) at the same time)
+ * Check that we have a regular name for the command (that the user is not
+ * trying to do an expose and a rename (to another namespace) at the same
+ * time).
*/
if (strstr(cmdName, "::") != NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "can not expose to a namespace ",
- "(use expose to toplevel, then rename)",
- (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "cannot expose to a namespace "
+ "(use expose to toplevel, then rename)", NULL);
+ return TCL_ERROR;
}
/*
@@ -1475,82 +1693,90 @@ Tcl_ExposeCommand(interp, hiddenCmdToken, cmdName)
if (hiddenCmdTablePtr != NULL) {
hPtr = Tcl_FindHashEntry(hiddenCmdTablePtr, hiddenCmdToken);
}
- if (hPtr == (Tcl_HashEntry *) NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "unknown hidden command \"", hiddenCmdToken,
- "\"", (char *) NULL);
- return TCL_ERROR;
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "unknown hidden command \"", hiddenCmdToken,
+ "\"", NULL);
+ return TCL_ERROR;
}
- cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
-
+ cmdPtr = Tcl_GetHashValue(hPtr);
/*
- * Check that we have a true global namespace
- * command (enforced by Tcl_HideCommand() but let's double
- * check. (If it was not, we would not really know how to
- * handle it).
+ * Check that we have a true global namespace command (enforced by
+ * Tcl_HideCommand() but let's double check. (If it was not, we would not
+ * really know how to handle it).
*/
- if ( cmdPtr->nsPtr != iPtr->globalNsPtr ) {
- /*
- * This case is theoritically impossible,
- * we might rather panic() than 'nicely' erroring out ?
+
+ if (cmdPtr->nsPtr != iPtr->globalNsPtr) {
+ /*
+ * This case is theoritically impossible, we might rather Tcl_Panic()
+ * than 'nicely' erroring out ?
*/
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "trying to expose a non global command name space command",
- (char *) NULL);
- return TCL_ERROR;
+
+ Tcl_AppendResult(interp,
+ "trying to expose a non global command name space command",
+ NULL);
+ return TCL_ERROR;
}
-
- /* This is the global table */
+
+ /*
+ * This is the global table.
+ */
+
nsPtr = cmdPtr->nsPtr;
/*
- * It is an error to overwrite an existing exposed command as a result
- * of exposing a previously hidden command.
+ * It is an error to overwrite an existing exposed command as a result of
+ * exposing a previously hidden command.
*/
- hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, cmdName, &new);
- if (!new) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "exposed command \"", cmdName,
- "\" already exists", (char *) NULL);
- return TCL_ERROR;
+ hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, cmdName, &isNew);
+ if (!isNew) {
+ Tcl_AppendResult(interp, "exposed command \"", cmdName,
+ "\" already exists", NULL);
+ return TCL_ERROR;
}
/*
+ * The list of command exported from the namespace might have changed.
+ * However, we do not need to recompute this just yet; next time we need
+ * the info will be soon enough.
+ */
+
+ TclInvalidateNsCmdLookup(nsPtr);
+
+ /*
* Remove the hash entry for the command from the interpreter hidden
* command table.
*/
if (cmdPtr->hPtr != NULL) {
- Tcl_DeleteHashEntry(cmdPtr->hPtr);
- cmdPtr->hPtr = NULL;
+ Tcl_DeleteHashEntry(cmdPtr->hPtr);
+ cmdPtr->hPtr = NULL;
}
/*
- * Now link the hash table entry with the command structure.
- * This is like creating a new command, so deal with any shadowing
- * of commands in the global namespace.
+ * Now link the hash table entry with the command structure. This is like
+ * creating a new command, so deal with any shadowing of commands in the
+ * global namespace.
*/
-
+
cmdPtr->hPtr = hPtr;
- Tcl_SetHashValue(hPtr, (ClientData) cmdPtr);
+ Tcl_SetHashValue(hPtr, cmdPtr);
/*
- * Not needed as we are only in the global namespace
- * (but would be needed again if we supported namespace command hiding)
+ * Not needed as we are only in the global namespace (but would be needed
+ * again if we supported namespace command hiding)
*
* TclResetShadowedCmdRefs(interp, cmdPtr);
*/
-
/*
- * If the command being exposed has a compile procedure, increment
- * interpreter's compileEpoch to invalidate its compiled code. This
- * makes sure that we don't later try to execute old code compiled
- * assuming the command is hidden. This field is checked in Tcl_EvalObj
- * and ObjInterpProc, and code whose compilation epoch doesn't match is
+ * If the command being exposed has a compile function, increment
+ * interpreter's compileEpoch to invalidate its compiled code. This makes
+ * sure that we don't later try to execute old code compiled assuming the
+ * command is hidden. This field is checked in Tcl_EvalObj and
+ * ObjInterpProc, and code whose compilation epoch doesn't match is
* recompiled.
*/
@@ -1568,94 +1794,103 @@ Tcl_ExposeCommand(interp, hiddenCmdToken, cmdName)
* Define a new command in a command table.
*
* Results:
- * The return value is a token for the command, which can
- * be used in future calls to Tcl_GetCommandName.
+ * The return value is a token for the command, which can be used in
+ * future calls to Tcl_GetCommandName.
*
* Side effects:
* If a command named cmdName already exists for interp, it is deleted.
* In the future, when cmdName is seen as the name of a command by
* Tcl_Eval, proc will be called. To support the bytecode interpreter,
* the command is created with a wrapper Tcl_ObjCmdProc
- * (TclInvokeStringCommand) that eventially calls proc. When the
- * command is deleted from the table, deleteProc will be called.
- * See the manual entry for details on the calling sequence.
+ * (TclInvokeStringCommand) that eventially calls proc. When the command
+ * is deleted from the table, deleteProc will be called. See the manual
+ * entry for details on the calling sequence.
*
*----------------------------------------------------------------------
*/
Tcl_Command
-Tcl_CreateCommand(interp, cmdName, proc, clientData, deleteProc)
- Tcl_Interp *interp; /* Token for command interpreter returned by
- * a previous call to Tcl_CreateInterp. */
- CONST char *cmdName; /* Name of command. If it contains namespace
+Tcl_CreateCommand(
+ Tcl_Interp *interp, /* Token for command interpreter returned by a
+ * previous call to Tcl_CreateInterp. */
+ const char *cmdName, /* Name of command. If it contains namespace
* qualifiers, the new command is put in the
- * specified namespace; otherwise it is put
- * in the global namespace. */
- Tcl_CmdProc *proc; /* Procedure to associate with cmdName. */
- ClientData clientData; /* Arbitrary value passed to string proc. */
- Tcl_CmdDeleteProc *deleteProc;
- /* If not NULL, gives a procedure to call
- * when this command is deleted. */
+ * specified namespace; otherwise it is put in
+ * the global namespace. */
+ Tcl_CmdProc *proc, /* Function to associate with cmdName. */
+ ClientData clientData, /* Arbitrary value passed to string proc. */
+ Tcl_CmdDeleteProc *deleteProc)
+ /* If not NULL, gives a function to call when
+ * this command is deleted. */
{
Interp *iPtr = (Interp *) interp;
ImportRef *oldRefPtr = NULL;
Namespace *nsPtr, *dummy1, *dummy2;
Command *cmdPtr, *refCmdPtr;
Tcl_HashEntry *hPtr;
- CONST char *tail;
- int new;
+ const char *tail;
+ int isNew;
ImportedCmdData *dataPtr;
if (iPtr->flags & DELETED) {
/*
- * The interpreter is being deleted. Don't create any new
- * commands; it's not safe to muck with the interpreter anymore.
+ * The interpreter is being deleted. Don't create any new commands;
+ * it's not safe to muck with the interpreter anymore.
*/
return (Tcl_Command) NULL;
}
/*
- * Determine where the command should reside. If its name contains
- * namespace qualifiers, we put it in the specified namespace;
- * otherwise, we always put it in the global namespace.
+ * Determine where the command should reside. If its name contains
+ * namespace qualifiers, we put it in the specified namespace; otherwise,
+ * we always put it in the global namespace.
*/
if (strstr(cmdName, "::") != NULL) {
- TclGetNamespaceForQualName(interp, cmdName, (Namespace *) NULL,
- CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
- if ((nsPtr == NULL) || (tail == NULL)) {
+ TclGetNamespaceForQualName(interp, cmdName, NULL,
+ TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
+ if ((nsPtr == NULL) || (tail == NULL)) {
return (Tcl_Command) NULL;
}
} else {
nsPtr = iPtr->globalNsPtr;
tail = cmdName;
}
-
- hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new);
- if (!new) {
+
+ hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
+ if (!isNew) {
/*
- * Command already exists. Delete the old one.
- * Be careful to preserve any existing import links so we can
- * restore them down below. That way, you can redefine a
- * command and its import status will remain intact.
+ * Command already exists. Delete the old one. Be careful to preserve
+ * any existing import links so we can restore them down below. That
+ * way, you can redefine a command and its import status will remain
+ * intact.
*/
- cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
+ cmdPtr = Tcl_GetHashValue(hPtr);
oldRefPtr = cmdPtr->importRefPtr;
cmdPtr->importRefPtr = NULL;
Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
- hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new);
- if (!new) {
+ hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
+ if (!isNew) {
/*
- * If the deletion callback recreated the command, just throw
- * away the new command (if we try to delete it again, we
- * could get stuck in an infinite loop).
+ * If the deletion callback recreated the command, just throw away
+ * the new command (if we try to delete it again, we could get
+ * stuck in an infinite loop).
*/
- ckfree((char*) Tcl_GetHashValue(hPtr));
+ ckfree((char *) Tcl_GetHashValue(hPtr));
}
+ } else {
+ /*
+ * The list of command exported from the namespace might have changed.
+ * However, we do not need to recompute this just yet; next time we
+ * need the info will be soon enough.
+ */
+
+ TclInvalidateNsCmdLookup(nsPtr);
+ TclInvalidateNsPath(nsPtr);
}
cmdPtr = (Command *) ckalloc(sizeof(Command));
Tcl_SetHashValue(hPtr, cmdPtr);
@@ -1663,9 +1898,9 @@ Tcl_CreateCommand(interp, cmdName, proc, clientData, deleteProc)
cmdPtr->nsPtr = nsPtr;
cmdPtr->refCount = 1;
cmdPtr->cmdEpoch = 0;
- cmdPtr->compileProc = (CompileProc *) NULL;
+ cmdPtr->compileProc = NULL;
cmdPtr->objProc = TclInvokeStringCommand;
- cmdPtr->objClientData = (ClientData) cmdPtr;
+ cmdPtr->objClientData = cmdPtr;
cmdPtr->proc = proc;
cmdPtr->clientData = clientData;
cmdPtr->deleteProc = deleteProc;
@@ -1675,15 +1910,15 @@ Tcl_CreateCommand(interp, cmdName, proc, clientData, deleteProc)
cmdPtr->tracePtr = NULL;
/*
- * Plug in any existing import references found above. Be sure
- * to update all of these references to point to the new command.
+ * Plug in any existing import references found above. Be sure to update
+ * all of these references to point to the new command.
*/
if (oldRefPtr != NULL) {
cmdPtr->importRefPtr = oldRefPtr;
while (oldRefPtr != NULL) {
refCmdPtr = oldRefPtr->importedCmdPtr;
- dataPtr = (ImportedCmdData*)refCmdPtr->objClientData;
+ dataPtr = refCmdPtr->objClientData;
dataPtr->realCmdPtr = cmdPtr;
oldRefPtr = oldRefPtr->nextPtr;
}
@@ -1695,7 +1930,7 @@ Tcl_CreateCommand(interp, cmdName, proc, clientData, deleteProc)
* shadowed commands are found, invalidate all cached command references
* in the affected namespaces.
*/
-
+
TclResetShadowedCmdRefs(interp, cmdPtr);
return (Tcl_Command) cmdPtr;
}
@@ -1708,70 +1943,70 @@ Tcl_CreateCommand(interp, cmdName, proc, clientData, deleteProc)
* Define a new object-based command in a command table.
*
* Results:
- * The return value is a token for the command, which can
- * be used in future calls to Tcl_GetCommandName.
+ * The return value is a token for the command, which can be used in
+ * future calls to Tcl_GetCommandName.
*
* Side effects:
* If no command named "cmdName" already exists for interp, one is
- * created. Otherwise, if a command does exist, then if the
- * object-based Tcl_ObjCmdProc is TclInvokeStringCommand, we assume
- * Tcl_CreateCommand was called previously for the same command and
- * just set its Tcl_ObjCmdProc to the argument "proc"; otherwise, we
- * delete the old command.
+ * created. Otherwise, if a command does exist, then if the object-based
+ * Tcl_ObjCmdProc is TclInvokeStringCommand, we assume Tcl_CreateCommand
+ * was called previously for the same command and just set its
+ * Tcl_ObjCmdProc to the argument "proc"; otherwise, we delete the old
+ * command.
*
* In the future, during bytecode evaluation when "cmdName" is seen as
* the name of a command by Tcl_EvalObj or Tcl_Eval, the object-based
* Tcl_ObjCmdProc proc will be called. When the command is deleted from
- * the table, deleteProc will be called. See the manual entry for
- * details on the calling sequence.
+ * the table, deleteProc will be called. See the manual entry for details
+ * on the calling sequence.
*
*----------------------------------------------------------------------
*/
Tcl_Command
-Tcl_CreateObjCommand(interp, cmdName, proc, clientData, deleteProc)
- Tcl_Interp *interp; /* Token for command interpreter (returned
- * by previous call to Tcl_CreateInterp). */
- CONST char *cmdName; /* Name of command. If it contains namespace
+Tcl_CreateObjCommand(
+ Tcl_Interp *interp, /* Token for command interpreter (returned by
+ * previous call to Tcl_CreateInterp). */
+ const char *cmdName, /* Name of command. If it contains namespace
* qualifiers, the new command is put in the
- * specified namespace; otherwise it is put
- * in the global namespace. */
- Tcl_ObjCmdProc *proc; /* Object-based procedure to associate with
+ * specified namespace; otherwise it is put in
+ * the global namespace. */
+ Tcl_ObjCmdProc *proc, /* Object-based function to associate with
* name. */
- ClientData clientData; /* Arbitrary value to pass to object
- * procedure. */
- Tcl_CmdDeleteProc *deleteProc;
- /* If not NULL, gives a procedure to call
- * when this command is deleted. */
+ ClientData clientData, /* Arbitrary value to pass to object
+ * function. */
+ Tcl_CmdDeleteProc *deleteProc)
+ /* If not NULL, gives a function to call when
+ * this command is deleted. */
{
Interp *iPtr = (Interp *) interp;
ImportRef *oldRefPtr = NULL;
Namespace *nsPtr, *dummy1, *dummy2;
Command *cmdPtr, *refCmdPtr;
Tcl_HashEntry *hPtr;
- CONST char *tail;
- int new;
+ const char *tail;
+ int isNew;
ImportedCmdData *dataPtr;
if (iPtr->flags & DELETED) {
/*
- * The interpreter is being deleted. Don't create any new
- * commands; it's not safe to muck with the interpreter anymore.
+ * The interpreter is being deleted. Don't create any new commands;
+ * it's not safe to muck with the interpreter anymore.
*/
return (Tcl_Command) NULL;
}
/*
- * Determine where the command should reside. If its name contains
- * namespace qualifiers, we put it in the specified namespace;
- * otherwise, we always put it in the global namespace.
+ * Determine where the command should reside. If its name contains
+ * namespace qualifiers, we put it in the specified namespace; otherwise,
+ * we always put it in the global namespace.
*/
if (strstr(cmdName, "::") != NULL) {
- TclGetNamespaceForQualName(interp, cmdName, (Namespace *) NULL,
- CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
- if ((nsPtr == NULL) || (tail == NULL)) {
+ TclGetNamespaceForQualName(interp, cmdName, NULL,
+ TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
+ if ((nsPtr == NULL) || (tail == NULL)) {
return (Tcl_Command) NULL;
}
} else {
@@ -1779,45 +2014,54 @@ Tcl_CreateObjCommand(interp, cmdName, proc, clientData, deleteProc)
tail = cmdName;
}
- hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new);
- if (!new) {
- cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
+ hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
+ TclInvalidateNsPath(nsPtr);
+ if (!isNew) {
+ cmdPtr = Tcl_GetHashValue(hPtr);
/*
* Command already exists. If its object-based Tcl_ObjCmdProc is
* TclInvokeStringCommand, we just set its Tcl_ObjCmdProc to the
- * argument "proc". Otherwise, we delete the old command.
+ * argument "proc". Otherwise, we delete the old command.
*/
if (cmdPtr->objProc == TclInvokeStringCommand) {
cmdPtr->objProc = proc;
cmdPtr->objClientData = clientData;
- cmdPtr->deleteProc = deleteProc;
- cmdPtr->deleteData = clientData;
+ cmdPtr->deleteProc = deleteProc;
+ cmdPtr->deleteData = clientData;
return (Tcl_Command) cmdPtr;
}
/*
- * Otherwise, we delete the old command. Be careful to preserve
- * any existing import links so we can restore them down below.
- * That way, you can redefine a command and its import status
- * will remain intact.
+ * Otherwise, we delete the old command. Be careful to preserve any
+ * existing import links so we can restore them down below. That way,
+ * you can redefine a command and its import status will remain
+ * intact.
*/
oldRefPtr = cmdPtr->importRefPtr;
cmdPtr->importRefPtr = NULL;
Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
- hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new);
- if (!new) {
+ hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew);
+ if (!isNew) {
/*
- * If the deletion callback recreated the command, just throw
- * away the new command (if we try to delete it again, we
- * could get stuck in an infinite loop).
+ * If the deletion callback recreated the command, just throw away
+ * the new command (if we try to delete it again, we could get
+ * stuck in an infinite loop).
*/
- ckfree((char *) Tcl_GetHashValue(hPtr));
+ ckfree(Tcl_GetHashValue(hPtr));
}
+ } else {
+ /*
+ * The list of command exported from the namespace might have changed.
+ * However, we do not need to recompute this just yet; next time we
+ * need the info will be soon enough.
+ */
+
+ TclInvalidateNsCmdLookup(nsPtr);
}
cmdPtr = (Command *) ckalloc(sizeof(Command));
Tcl_SetHashValue(hPtr, cmdPtr);
@@ -1825,11 +2069,11 @@ Tcl_CreateObjCommand(interp, cmdName, proc, clientData, deleteProc)
cmdPtr->nsPtr = nsPtr;
cmdPtr->refCount = 1;
cmdPtr->cmdEpoch = 0;
- cmdPtr->compileProc = (CompileProc *) NULL;
+ cmdPtr->compileProc = NULL;
cmdPtr->objProc = proc;
cmdPtr->objClientData = clientData;
cmdPtr->proc = TclInvokeObjectCommand;
- cmdPtr->clientData = (ClientData) cmdPtr;
+ cmdPtr->clientData = cmdPtr;
cmdPtr->deleteProc = deleteProc;
cmdPtr->deleteData = clientData;
cmdPtr->flags = 0;
@@ -1837,27 +2081,27 @@ Tcl_CreateObjCommand(interp, cmdName, proc, clientData, deleteProc)
cmdPtr->tracePtr = NULL;
/*
- * Plug in any existing import references found above. Be sure
- * to update all of these references to point to the new command.
+ * Plug in any existing import references found above. Be sure to update
+ * all of these references to point to the new command.
*/
if (oldRefPtr != NULL) {
cmdPtr->importRefPtr = oldRefPtr;
while (oldRefPtr != NULL) {
refCmdPtr = oldRefPtr->importedCmdPtr;
- dataPtr = (ImportedCmdData*)refCmdPtr->objClientData;
+ dataPtr = refCmdPtr->objClientData;
dataPtr->realCmdPtr = cmdPtr;
oldRefPtr = oldRefPtr->nextPtr;
}
}
-
+
/*
* We just created a command, so in its namespace and all of its parent
* namespaces, it may shadow global commands with the same name. If any
* shadowed commands are found, invalidate all cached command references
* in the affected namespaces.
*/
-
+
TclResetShadowedCmdRefs(interp, cmdPtr);
return (Tcl_Command) cmdPtr;
}
@@ -1868,10 +2112,10 @@ Tcl_CreateObjCommand(interp, cmdName, proc, clientData, deleteProc)
* TclInvokeStringCommand --
*
* "Wrapper" Tcl_ObjCmdProc used to call an existing string-based
- * Tcl_CmdProc if no object-based procedure exists for a command. A
- * pointer to this procedure is stored as the Tcl_ObjCmdProc in a
- * Command structure. It simply turns around and calls the string
- * Tcl_CmdProc in the Command structure.
+ * Tcl_CmdProc if no object-based function exists for a command. A
+ * pointer to this function is stored as the Tcl_ObjCmdProc in a Command
+ * structure. It simply turns around and calls the string Tcl_CmdProc in
+ * the Command structure.
*
* Results:
* A standard Tcl object result value.
@@ -1884,35 +2128,16 @@ Tcl_CreateObjCommand(interp, cmdName, proc, clientData, deleteProc)
*/
int
-TclInvokeStringCommand(clientData, interp, objc, objv)
- ClientData clientData; /* Points to command's Command structure. */
- Tcl_Interp *interp; /* Current interpreter. */
- register int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+TclInvokeStringCommand(
+ ClientData clientData, /* Points to command's Command structure. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ register int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- register Command *cmdPtr = (Command *) clientData;
- register int i;
- int result;
-
- /*
- * This procedure generates an argv array for the string arguments. It
- * starts out with stack-allocated space but uses dynamically-allocated
- * storage if needed.
- */
-
-#define NUM_ARGS 20
- CONST char *(argStorage[NUM_ARGS]);
- CONST char **argv = argStorage;
-
- /*
- * Create the string argument array "argv". Make sure argv is large
- * enough to hold the objc arguments plus 1 extra for the zero
- * end-of-argv word.
- */
-
- if ((objc + 1) > NUM_ARGS) {
- argv = (CONST char **) ckalloc((unsigned)(objc + 1) * sizeof(char *));
- }
+ Command *cmdPtr = clientData;
+ int i, result;
+ const char **argv = (const char **)
+ TclStackAlloc(interp, (unsigned)(objc + 1) * sizeof(char *));
for (i = 0; i < objc; i++) {
argv[i] = Tcl_GetString(objv[i]);
@@ -1925,15 +2150,8 @@ TclInvokeStringCommand(clientData, interp, objc, objv)
result = (*cmdPtr->proc)(cmdPtr->clientData, interp, objc, argv);
- /*
- * Free the argv array if malloc'ed storage was used.
- */
-
- if (argv != argStorage) {
- ckfree((char *) argv);
- }
+ TclStackFree(interp, (void *) argv);
return result;
-#undef NUM_ARGS
}
/*
@@ -1942,10 +2160,10 @@ TclInvokeStringCommand(clientData, interp, objc, objv)
* TclInvokeObjectCommand --
*
* "Wrapper" Tcl_CmdProc used to call an existing object-based
- * Tcl_ObjCmdProc if no string-based procedure exists for a command.
- * A pointer to this procedure is stored as the Tcl_CmdProc in a
- * Command structure. It simply turns around and calls the object
- * Tcl_ObjCmdProc in the Command structure.
+ * Tcl_ObjCmdProc if no string-based function exists for a command. A
+ * pointer to this function is stored as the Tcl_CmdProc in a Command
+ * structure. It simply turns around and calls the object Tcl_ObjCmdProc
+ * in the Command structure.
*
* Results:
* A standard Tcl string result value.
@@ -1958,42 +2176,21 @@ TclInvokeStringCommand(clientData, interp, objc, objv)
*/
int
-TclInvokeObjectCommand(clientData, interp, argc, argv)
- ClientData clientData; /* Points to command's Command structure. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- register CONST char **argv; /* Argument strings. */
+TclInvokeObjectCommand(
+ ClientData clientData, /* Points to command's Command structure. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ register const char **argv) /* Argument strings. */
{
Command *cmdPtr = (Command *) clientData;
- register Tcl_Obj *objPtr;
- register int i;
- int length, result;
-
- /*
- * This procedure generates an objv array for object arguments that hold
- * the argv strings. It starts out with stack-allocated space but uses
- * dynamically-allocated storage if needed.
- */
-
-#define NUM_ARGS 20
- Tcl_Obj *(argStorage[NUM_ARGS]);
- register Tcl_Obj **objv = argStorage;
-
- /*
- * Create the object argument array "objv". Make sure objv is large
- * enough to hold the objc arguments plus 1 extra for the zero
- * end-of-objv word.
- */
-
- if (argc > NUM_ARGS) {
- objv = (Tcl_Obj **)
- ckalloc((unsigned)(argc * sizeof(Tcl_Obj *)));
- }
+ Tcl_Obj *objPtr;
+ int i, length, result;
+ Tcl_Obj **objv = (Tcl_Obj **)
+ TclStackAlloc(interp, (unsigned)(argc * sizeof(Tcl_Obj *)));
for (i = 0; i < argc; i++) {
length = strlen(argv[i]);
- TclNewObj(objPtr);
- TclInitStringRep(objPtr, argv[i], length);
+ TclNewStringObj(objPtr, argv[i], length);
Tcl_IncrRefCount(objPtr);
objv[i] = objPtr;
}
@@ -2005,27 +2202,23 @@ TclInvokeObjectCommand(clientData, interp, argc, argv)
result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, argc, objv);
/*
- * Move the interpreter's object result to the string result,
- * then reset the object result.
+ * Move the interpreter's object result to the string result, then reset
+ * the object result.
*/
- Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
- TCL_VOLATILE);
-
+ (void) Tcl_GetStringResult(interp);
+
/*
- * Decrement the ref counts for the argument objects created above,
- * then free the objv array if malloc'ed storage was used.
+ * Decrement the ref counts for the argument objects created above, then
+ * free the objv array if malloc'ed storage was used.
*/
for (i = 0; i < argc; i++) {
objPtr = objv[i];
Tcl_DecrRefCount(objPtr);
}
- if (objv != argStorage) {
- ckfree((char *) objv);
- }
+ TclStackFree(interp, objv);
return result;
-#undef NUM_ARGS
}
/*
@@ -2033,65 +2226,64 @@ TclInvokeObjectCommand(clientData, interp, argc, argv)
*
* TclRenameCommand --
*
- * Called to give an existing Tcl command a different name. Both the
- * old command name and the new command name can have "::" namespace
- * qualifiers. If the new command has a different namespace context,
- * the command will be moved to that namespace and will execute in
- * the context of that new namespace.
+ * Called to give an existing Tcl command a different name. Both the old
+ * command name and the new command name can have "::" namespace
+ * qualifiers. If the new command has a different namespace context, the
+ * command will be moved to that namespace and will execute in the
+ * context of that new namespace.
*
- * If the new command name is NULL or the null string, the command is
- * deleted.
+ * If the new command name is NULL or the null string, the command is
+ * deleted.
*
* Results:
- * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
+ * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
*
* Side effects:
- * If anything goes wrong, an error message is returned in the
- * interpreter's result object.
+ * If anything goes wrong, an error message is returned in the
+ * interpreter's result object.
*
*----------------------------------------------------------------------
*/
int
-TclRenameCommand(interp, oldName, newName)
- Tcl_Interp *interp; /* Current interpreter. */
- char *oldName; /* Existing command name. */
- char *newName; /* New command name. */
+TclRenameCommand(
+ Tcl_Interp *interp, /* Current interpreter. */
+ const char *oldName, /* Existing command name. */
+ const char *newName) /* New command name. */
{
Interp *iPtr = (Interp *) interp;
- CONST char *newTail;
+ const char *newTail;
Namespace *cmdNsPtr, *newNsPtr, *dummy1, *dummy2;
Tcl_Command cmd;
Command *cmdPtr;
Tcl_HashEntry *hPtr, *oldHPtr;
- int new, result;
- Tcl_Obj* oldFullName;
+ int isNew, result;
+ Tcl_Obj *oldFullName;
Tcl_DString newFullName;
/*
- * Find the existing command. An error is returned if cmdName can't
- * be found.
+ * Find the existing command. An error is returned if cmdName can't be
+ * found.
*/
- cmd = Tcl_FindCommand(interp, oldName, (Tcl_Namespace *) NULL,
- /*flags*/ 0);
+ cmd = Tcl_FindCommand(interp, oldName, NULL, /*flags*/ 0);
cmdPtr = (Command *) cmd;
if (cmdPtr == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "can't ",
- ((newName == NULL)||(*newName == '\0'))? "delete":"rename",
- " \"", oldName, "\": command doesn't exist", (char *) NULL);
+ Tcl_AppendResult(interp, "can't ",
+ ((newName == NULL)||(*newName == '\0'))? "delete":"rename",
+ " \"", oldName, "\": command doesn't exist", NULL);
return TCL_ERROR;
}
cmdNsPtr = cmdPtr->nsPtr;
oldFullName = Tcl_NewObj();
- Tcl_IncrRefCount( oldFullName );
- Tcl_GetCommandFullName( interp, cmd, oldFullName );
+ Tcl_IncrRefCount(oldFullName);
+ Tcl_GetCommandFullName(interp, cmd, oldFullName);
/*
* If the new command name is NULL or empty, delete the command. Do this
* with Tcl_DeleteCommandFromToken, since we already have the command.
*/
-
+
if ((newName == NULL) || (*newName == '\0')) {
Tcl_DeleteCommandFromToken(interp, cmd);
result = TCL_OK;
@@ -2099,101 +2291,106 @@ TclRenameCommand(interp, oldName, newName)
}
/*
- * Make sure that the destination command does not already exist.
- * The rename operation is like creating a command, so we should
- * automatically create the containing namespaces just like
- * Tcl_CreateCommand would.
+ * Make sure that the destination command does not already exist. The
+ * rename operation is like creating a command, so we should automatically
+ * create the containing namespaces just like Tcl_CreateCommand would.
*/
- TclGetNamespaceForQualName(interp, newName, (Namespace *) NULL,
- CREATE_NS_IF_UNKNOWN, &newNsPtr, &dummy1, &dummy2, &newTail);
+ TclGetNamespaceForQualName(interp, newName, NULL,
+ TCL_CREATE_NS_IF_UNKNOWN, &newNsPtr, &dummy1, &dummy2, &newTail);
if ((newNsPtr == NULL) || (newTail == NULL)) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "can't rename to \"", newName, "\": bad command name",
- (char *) NULL);
+ Tcl_AppendResult(interp, "can't rename to \"", newName,
+ "\": bad command name", NULL);
result = TCL_ERROR;
goto done;
}
if (Tcl_FindHashEntry(&newNsPtr->cmdTable, newTail) != NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "can't rename to \"", newName,
- "\": command already exists", (char *) NULL);
+ Tcl_AppendResult(interp, "can't rename to \"", newName,
+ "\": command already exists", NULL);
result = TCL_ERROR;
goto done;
}
/*
- * Warning: any changes done in the code here are likely
- * to be needed in Tcl_HideCommand() code too.
- * (until the common parts are extracted out) --dl
+ * Warning: any changes done in the code here are likely to be needed in
+ * Tcl_HideCommand() code too (until the common parts are extracted out).
+ * - dl
*/
/*
- * Put the command in the new namespace so we can check for an alias
- * loop. Since we are adding a new command to a namespace, we must
- * handle any shadowing of the global commands that this might create.
+ * Put the command in the new namespace so we can check for an alias loop.
+ * Since we are adding a new command to a namespace, we must handle any
+ * shadowing of the global commands that this might create.
*/
-
+
oldHPtr = cmdPtr->hPtr;
- hPtr = Tcl_CreateHashEntry(&newNsPtr->cmdTable, newTail, &new);
- Tcl_SetHashValue(hPtr, (ClientData) cmdPtr);
+ hPtr = Tcl_CreateHashEntry(&newNsPtr->cmdTable, newTail, &isNew);
+ Tcl_SetHashValue(hPtr, cmdPtr);
cmdPtr->hPtr = hPtr;
cmdPtr->nsPtr = newNsPtr;
TclResetShadowedCmdRefs(interp, cmdPtr);
/*
- * Now check for an alias loop. If we detect one, put everything back
- * the way it was and report the error.
+ * Now check for an alias loop. If we detect one, put everything back the
+ * way it was and report the error.
*/
result = TclPreventAliasLoop(interp, interp, (Tcl_Command) cmdPtr);
if (result != TCL_OK) {
- Tcl_DeleteHashEntry(cmdPtr->hPtr);
- cmdPtr->hPtr = oldHPtr;
- cmdPtr->nsPtr = cmdNsPtr;
+ Tcl_DeleteHashEntry(cmdPtr->hPtr);
+ cmdPtr->hPtr = oldHPtr;
+ cmdPtr->nsPtr = cmdNsPtr;
goto done;
}
/*
- * Script for rename traces can delete the command "oldName".
- * Therefore increment the reference count for cmdPtr so that
- * it's Command structure is freed only towards the end of this
- * function by calling TclCleanupCommand.
+ * The list of command exported from the namespace might have changed.
+ * However, we do not need to recompute this just yet; next time we need
+ * the info will be soon enough. These might refer to the same variable,
+ * but that's no big deal.
+ */
+
+ TclInvalidateNsCmdLookup(cmdNsPtr);
+ TclInvalidateNsCmdLookup(cmdPtr->nsPtr);
+
+ /*
+ * Script for rename traces can delete the command "oldName". Therefore
+ * increment the reference count for cmdPtr so that it's Command structure
+ * is freed only towards the end of this function by calling
+ * TclCleanupCommand.
*
- * The trace procedure needs to get a fully qualified name for
- * old and new commands [Tcl bug #651271], or else there's no way
- * for the trace procedure to get the namespace from which the old
- * command is being renamed!
+ * The trace function needs to get a fully qualified name for old and new
+ * commands [Tcl bug #651271], or else there's no way for the trace
+ * function to get the namespace from which the old command is being
+ * renamed!
*/
- Tcl_DStringInit( &newFullName );
- Tcl_DStringAppend( &newFullName, newNsPtr->fullName, -1 );
- if ( newNsPtr != iPtr->globalNsPtr ) {
- Tcl_DStringAppend( &newFullName, "::", 2 );
+ Tcl_DStringInit(&newFullName);
+ Tcl_DStringAppend(&newFullName, newNsPtr->fullName, -1);
+ if (newNsPtr != iPtr->globalNsPtr) {
+ Tcl_DStringAppend(&newFullName, "::", 2);
}
- Tcl_DStringAppend( &newFullName, newTail, -1 );
+ Tcl_DStringAppend(&newFullName, newTail, -1);
cmdPtr->refCount++;
- CallCommandTraces( iPtr, cmdPtr,
- Tcl_GetString( oldFullName ),
- Tcl_DStringValue( &newFullName ),
- TCL_TRACE_RENAME);
- Tcl_DStringFree( &newFullName );
+ CallCommandTraces(iPtr, cmdPtr, Tcl_GetString(oldFullName),
+ Tcl_DStringValue(&newFullName), TCL_TRACE_RENAME);
+ Tcl_DStringFree(&newFullName);
/*
- * The new command name is okay, so remove the command from its
- * current namespace. This is like deleting the command, so bump
- * the cmdEpoch to invalidate any cached references to the command.
+ * The new command name is okay, so remove the command from its current
+ * namespace. This is like deleting the command, so bump the cmdEpoch to
+ * invalidate any cached references to the command.
*/
-
+
Tcl_DeleteHashEntry(oldHPtr);
cmdPtr->cmdEpoch++;
/*
- * If the command being renamed has a compile procedure, increment the
- * interpreter's compileEpoch to invalidate its compiled code. This
- * makes sure that we don't later try to execute old code compiled for
- * the now-renamed command.
+ * If the command being renamed has a compile function, increment the
+ * interpreter's compileEpoch to invalidate its compiled code. This makes
+ * sure that we don't later try to execute old code compiled for the
+ * now-renamed command.
*/
if (cmdPtr->compileProc != NULL) {
@@ -2201,14 +2398,15 @@ TclRenameCommand(interp, oldName, newName)
}
/*
- * Now free the Command structure, if the "oldName" command has
- * been deleted by invocation of rename traces.
+ * Now free the Command structure, if the "oldName" command has been
+ * deleted by invocation of rename traces.
*/
- TclCleanupCommand(cmdPtr);
+
+ TclCleanupCommandMacro(cmdPtr);
result = TCL_OK;
- done:
- TclDecrRefCount( oldFullName );
+ done:
+ TclDecrRefCount(oldFullName);
return result;
}
@@ -2217,16 +2415,15 @@ TclRenameCommand(interp, oldName, newName)
*
* Tcl_SetCommandInfo --
*
- * Modifies various information about a Tcl command. Note that
- * this procedure will not change a command's namespace; use
- * Tcl_RenameCommand to do that. Also, the isNativeObjectProc
- * member of *infoPtr is ignored.
+ * Modifies various information about a Tcl command. Note that this
+ * function will not change a command's namespace; use TclRenameCommand
+ * to do that. Also, the isNativeObjectProc member of *infoPtr is
+ * ignored.
*
* Results:
- * If cmdName exists in interp, then the information at *infoPtr
- * is stored with the command in place of the current information
- * and 1 is returned. If the command doesn't exist then 0 is
- * returned.
+ * If cmdName exists in interp, then the information at *infoPtr is
+ * stored with the command in place of the current information and 1 is
+ * returned. If the command doesn't exist then 0 is returned.
*
* Side effects:
* None.
@@ -2235,20 +2432,17 @@ TclRenameCommand(interp, oldName, newName)
*/
int
-Tcl_SetCommandInfo(interp, cmdName, infoPtr)
- Tcl_Interp *interp; /* Interpreter in which to look
- * for command. */
- CONST char *cmdName; /* Name of desired command. */
- CONST Tcl_CmdInfo *infoPtr; /* Where to find information
- * to store in the command. */
+Tcl_SetCommandInfo(
+ Tcl_Interp *interp, /* Interpreter in which to look for
+ * command. */
+ const char *cmdName, /* Name of desired command. */
+ const Tcl_CmdInfo *infoPtr) /* Where to find information to store in the
+ * command. */
{
Tcl_Command cmd;
- cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL,
- /*flags*/ 0);
-
- return Tcl_SetCommandInfoFromToken( cmd, infoPtr );
-
+ cmd = Tcl_FindCommand(interp, cmdName, NULL, /*flags*/ 0);
+ return Tcl_SetCommandInfoFromToken(cmd, infoPtr);
}
/*
@@ -2256,16 +2450,15 @@ Tcl_SetCommandInfo(interp, cmdName, infoPtr)
*
* Tcl_SetCommandInfoFromToken --
*
- * Modifies various information about a Tcl command. Note that
- * this procedure will not change a command's namespace; use
- * Tcl_RenameCommand to do that. Also, the isNativeObjectProc
- * member of *infoPtr is ignored.
+ * Modifies various information about a Tcl command. Note that this
+ * function will not change a command's namespace; use TclRenameCommand
+ * to do that. Also, the isNativeObjectProc member of *infoPtr is
+ * ignored.
*
* Results:
- * If cmdName exists in interp, then the information at *infoPtr
- * is stored with the command in place of the current information
- * and 1 is returned. If the command doesn't exist then 0 is
- * returned.
+ * If cmdName exists in interp, then the information at *infoPtr is
+ * stored with the command in place of the current information and 1 is
+ * returned. If the command doesn't exist then 0 is returned.
*
* Side effects:
* None.
@@ -2274,11 +2467,11 @@ Tcl_SetCommandInfo(interp, cmdName, infoPtr)
*/
int
-Tcl_SetCommandInfoFromToken( cmd, infoPtr )
- Tcl_Command cmd;
- CONST Tcl_CmdInfo* infoPtr;
+Tcl_SetCommandInfoFromToken(
+ Tcl_Command cmd,
+ const Tcl_CmdInfo *infoPtr)
{
- Command* cmdPtr; /* Internal representation of the command */
+ Command *cmdPtr; /* Internal representation of the command */
if (cmd == (Tcl_Command) NULL) {
return 0;
@@ -2287,13 +2480,13 @@ Tcl_SetCommandInfoFromToken( cmd, infoPtr )
/*
* The isNativeObjectProc and nsPtr members of *infoPtr are ignored.
*/
-
+
cmdPtr = (Command *) cmd;
cmdPtr->proc = infoPtr->proc;
cmdPtr->clientData = infoPtr->clientData;
- if (infoPtr->objProc == (Tcl_ObjCmdProc *) NULL) {
+ if (infoPtr->objProc == NULL) {
cmdPtr->objProc = TclInvokeStringCommand;
- cmdPtr->objClientData = (ClientData) cmdPtr;
+ cmdPtr->objClientData = cmdPtr;
} else {
cmdPtr->objProc = infoPtr->objProc;
cmdPtr->objClientData = infoPtr->objClientData;
@@ -2311,10 +2504,9 @@ Tcl_SetCommandInfoFromToken( cmd, infoPtr )
* Returns various information about a Tcl command.
*
* Results:
- * If cmdName exists in interp, then *infoPtr is modified to
- * hold information about cmdName and 1 is returned. If the
- * command doesn't exist then 0 is returned and *infoPtr isn't
- * modified.
+ * If cmdName exists in interp, then *infoPtr is modified to hold
+ * information about cmdName and 1 is returned. If the command doesn't
+ * exist then 0 is returned and *infoPtr isn't modified.
*
* Side effects:
* None.
@@ -2323,20 +2515,17 @@ Tcl_SetCommandInfoFromToken( cmd, infoPtr )
*/
int
-Tcl_GetCommandInfo(interp, cmdName, infoPtr)
- Tcl_Interp *interp; /* Interpreter in which to look
- * for command. */
- CONST char *cmdName; /* Name of desired command. */
- Tcl_CmdInfo *infoPtr; /* Where to store information about
- * command. */
+Tcl_GetCommandInfo(
+ Tcl_Interp *interp, /* Interpreter in which to look for
+ * command. */
+ const char *cmdName, /* Name of desired command. */
+ Tcl_CmdInfo *infoPtr) /* Where to store information about
+ * command. */
{
Tcl_Command cmd;
- cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL,
- /*flags*/ 0);
-
- return Tcl_GetCommandInfoFromToken( cmd, infoPtr );
-
+ cmd = Tcl_FindCommand(interp, cmdName, NULL, /*flags*/ 0);
+ return Tcl_GetCommandInfoFromToken(cmd, infoPtr);
}
/*
@@ -2347,9 +2536,9 @@ Tcl_GetCommandInfo(interp, cmdName, infoPtr)
* Returns various information about a Tcl command.
*
* Results:
- * Copies information from the command identified by 'cmd' into
- * a caller-supplied structure and returns 1. If the 'cmd' is
- * NULL, leaves the structure untouched and returns 0.
+ * Copies information from the command identified by 'cmd' into a
+ * caller-supplied structure and returns 1. If the 'cmd' is NULL, leaves
+ * the structure untouched and returns 0.
*
* Side effects:
* None.
@@ -2358,14 +2547,13 @@ Tcl_GetCommandInfo(interp, cmdName, infoPtr)
*/
int
-Tcl_GetCommandInfoFromToken( cmd, infoPtr )
- Tcl_Command cmd;
- Tcl_CmdInfo* infoPtr;
+Tcl_GetCommandInfoFromToken(
+ Tcl_Command cmd,
+ Tcl_CmdInfo *infoPtr)
{
+ Command *cmdPtr; /* Internal representation of the command */
- Command* cmdPtr; /* Internal representation of the command */
-
- if ( cmd == (Tcl_Command) NULL ) {
+ if (cmd == (Tcl_Command) NULL) {
return 0;
}
@@ -2386,7 +2574,6 @@ Tcl_GetCommandInfoFromToken( cmd, infoPtr )
infoPtr->namespacePtr = (Tcl_Namespace *) cmdPtr->nsPtr;
return 1;
-
}
/*
@@ -2394,9 +2581,8 @@ Tcl_GetCommandInfoFromToken( cmd, infoPtr )
*
* Tcl_GetCommandName --
*
- * Given a token returned by Tcl_CreateCommand, this procedure
- * returns the current name of the command (which may have changed
- * due to renaming).
+ * Given a token returned by Tcl_CreateCommand, this function returns the
+ * current name of the command (which may have changed due to renaming).
*
* Results:
* The return value is the name of the given command.
@@ -2407,25 +2593,25 @@ Tcl_GetCommandInfoFromToken( cmd, infoPtr )
*----------------------------------------------------------------------
*/
-CONST char *
-Tcl_GetCommandName(interp, command)
- Tcl_Interp *interp; /* Interpreter containing the command. */
- Tcl_Command command; /* Token for command returned by a previous
- * call to Tcl_CreateCommand. The command
- * must not have been deleted. */
+const char *
+Tcl_GetCommandName(
+ Tcl_Interp *interp, /* Interpreter containing the command. */
+ Tcl_Command command) /* Token for command returned by a previous
+ * call to Tcl_CreateCommand. The command must
+ * not have been deleted. */
{
Command *cmdPtr = (Command *) command;
if ((cmdPtr == NULL) || (cmdPtr->hPtr == NULL)) {
-
/*
* This should only happen if command was "created" after the
- * interpreter began to be deleted, so there isn't really any
- * command. Just return an empty string.
+ * interpreter began to be deleted, so there isn't really any command.
+ * Just return an empty string.
*/
return "";
}
+
return Tcl_GetHashKey(cmdPtr->hPtr->tablePtr, cmdPtr->hPtr);
}
@@ -2434,28 +2620,28 @@ Tcl_GetCommandName(interp, command)
*
* Tcl_GetCommandFullName --
*
- * Given a token returned by, e.g., Tcl_CreateCommand or
- * Tcl_FindCommand, this procedure appends to an object the command's
- * full name, qualified by a sequence of parent namespace names. The
- * command's fully-qualified name may have changed due to renaming.
+ * Given a token returned by, e.g., Tcl_CreateCommand or Tcl_FindCommand,
+ * this function appends to an object the command's full name, qualified
+ * by a sequence of parent namespace names. The command's fully-qualified
+ * name may have changed due to renaming.
*
* Results:
* None.
*
* Side effects:
* The command's fully-qualified name is appended to the string
- * representation of objPtr.
+ * representation of objPtr.
*
*----------------------------------------------------------------------
*/
void
-Tcl_GetCommandFullName(interp, command, objPtr)
- Tcl_Interp *interp; /* Interpreter containing the command. */
- Tcl_Command command; /* Token for command returned by a previous
- * call to Tcl_CreateCommand. The command
- * must not have been deleted. */
- Tcl_Obj *objPtr; /* Points to the object onto which the
+Tcl_GetCommandFullName(
+ Tcl_Interp *interp, /* Interpreter containing the command. */
+ Tcl_Command command, /* Token for command returned by a previous
+ * call to Tcl_CreateCommand. The command must
+ * not have been deleted. */
+ Tcl_Obj *objPtr) /* Points to the object onto which the
* command's full name is appended. */
{
@@ -2478,7 +2664,7 @@ Tcl_GetCommandFullName(interp, command, objPtr)
if (cmdPtr->hPtr != NULL) {
name = Tcl_GetHashKey(cmdPtr->hPtr->tablePtr, cmdPtr->hPtr);
Tcl_AppendToObj(objPtr, name, -1);
- }
+ }
}
}
@@ -2490,30 +2676,28 @@ Tcl_GetCommandFullName(interp, command, objPtr)
* Remove the given command from the given interpreter.
*
* Results:
- * 0 is returned if the command was deleted successfully.
- * -1 is returned if there didn't exist a command by that name.
+ * 0 is returned if the command was deleted successfully. -1 is returned
+ * if there didn't exist a command by that name.
*
* Side effects:
- * cmdName will no longer be recognized as a valid command for
- * interp.
+ * cmdName will no longer be recognized as a valid command for interp.
*
*----------------------------------------------------------------------
*/
int
-Tcl_DeleteCommand(interp, cmdName)
- Tcl_Interp *interp; /* Token for command interpreter (returned
- * by a previous Tcl_CreateInterp call). */
- CONST char *cmdName; /* Name of command to remove. */
+Tcl_DeleteCommand(
+ Tcl_Interp *interp, /* Token for command interpreter (returned by
+ * a previous Tcl_CreateInterp call). */
+ const char *cmdName) /* Name of command to remove. */
{
Tcl_Command cmd;
/*
- * Find the desired command and delete it.
+ * Find the desired command and delete it.
*/
- cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL,
- /*flags*/ 0);
+ cmd = Tcl_FindCommand(interp, cmdName, NULL, /*flags*/ 0);
if (cmd == (Tcl_Command) NULL) {
return -1;
}
@@ -2525,26 +2709,26 @@ Tcl_DeleteCommand(interp, cmdName)
*
* Tcl_DeleteCommandFromToken --
*
- * Removes the given command from the given interpreter. This procedure
- * resembles Tcl_DeleteCommand, but takes a Tcl_Command token instead
- * of a command name for efficiency.
+ * Removes the given command from the given interpreter. This function
+ * resembles Tcl_DeleteCommand, but takes a Tcl_Command token instead of
+ * a command name for efficiency.
*
* Results:
- * 0 is returned if the command was deleted successfully.
- * -1 is returned if there didn't exist a command by that name.
+ * 0 is returned if the command was deleted successfully. -1 is returned
+ * if there didn't exist a command by that name.
*
* Side effects:
- * The command specified by "cmd" will no longer be recognized as a
- * valid command for "interp".
+ * The command specified by "cmd" will no longer be recognized as a valid
+ * command for "interp".
*
*----------------------------------------------------------------------
*/
int
-Tcl_DeleteCommandFromToken(interp, cmd)
- Tcl_Interp *interp; /* Token for command interpreter returned by
- * a previous call to Tcl_CreateInterp. */
- Tcl_Command cmd; /* Token for command to delete. */
+Tcl_DeleteCommandFromToken(
+ Tcl_Interp *interp, /* Token for command interpreter returned by a
+ * previous call to Tcl_CreateInterp. */
+ Tcl_Command cmd) /* Token for command to delete. */
{
Interp *iPtr = (Interp *) interp;
Command *cmdPtr = (Command *) cmd;
@@ -2552,73 +2736,90 @@ Tcl_DeleteCommandFromToken(interp, cmd)
Tcl_Command importCmd;
/*
- * The code here is tricky. We can't delete the hash table entry
- * before invoking the deletion callback because there are cases
- * where the deletion callback needs to invoke the command (e.g.
- * object systems such as OTcl). However, this means that the
- * callback could try to delete or rename the command. The deleted
- * flag allows us to detect these cases and skip nested deletes.
+ * Bump the command epoch counter. This will invalidate all cached
+ * references that point to this command.
+ */
+
+ cmdPtr->cmdEpoch++;
+
+ /*
+ * The code here is tricky. We can't delete the hash table entry before
+ * invoking the deletion callback because there are cases where the
+ * deletion callback needs to invoke the command (e.g. object systems such
+ * as OTcl). However, this means that the callback could try to delete or
+ * rename the command. The deleted flag allows us to detect these cases
+ * and skip nested deletes.
*/
if (cmdPtr->flags & CMD_IS_DELETED) {
/*
- * Another deletion is already in progress. Remove the hash
- * table entry now, but don't invoke a callback or free the
- * command structure.
+ * Another deletion is already in progress. Remove the hash table
+ * entry now, but don't invoke a callback or free the command
+ * structure. Take care to only remove the hash entry if it has not
+ * already been removed; otherwise if we manage to hit this function
+ * three times, everything goes up in smoke. [Bug 1220058]
*/
- Tcl_DeleteHashEntry(cmdPtr->hPtr);
- cmdPtr->hPtr = NULL;
+ if (cmdPtr->hPtr != NULL) {
+ Tcl_DeleteHashEntry(cmdPtr->hPtr);
+ cmdPtr->hPtr = NULL;
+ }
return 0;
}
- /*
- * We must delete this command, even though both traces and
- * delete procs may try to avoid this (renaming the command etc).
- * Also traces and delete procs may try to delete the command
- * themsevles. This flag declares that a delete is in progress
- * and that recursive deletes should be ignored.
- */
- cmdPtr->flags |= CMD_IS_DELETED;
-
/*
- * Bump the command epoch counter. This will invalidate all cached
- * references that point to this command.
+ * We must delete this command, even though both traces and delete procs
+ * may try to avoid this (renaming the command etc). Also traces and
+ * delete procs may try to delete the command themsevles. This flag
+ * declares that a delete is in progress and that recursive deletes should
+ * be ignored.
*/
-
- cmdPtr->cmdEpoch++;
+
+ cmdPtr->flags |= CMD_IS_DELETED;
/*
- * Call trace procedures for the command being deleted. Then delete
- * its traces.
+ * Call trace functions for the command being deleted. Then delete its
+ * traces.
*/
if (cmdPtr->tracePtr != NULL) {
CommandTrace *tracePtr;
CallCommandTraces(iPtr,cmdPtr,NULL,NULL,TCL_TRACE_DELETE);
- /* Now delete these traces */
+
+ /*
+ * Now delete these traces.
+ */
+
tracePtr = cmdPtr->tracePtr;
while (tracePtr != NULL) {
CommandTrace *nextPtr = tracePtr->nextPtr;
if ((--tracePtr->refCount) <= 0) {
- ckfree((char*)tracePtr);
+ ckfree((char *) tracePtr);
}
tracePtr = nextPtr;
}
cmdPtr->tracePtr = NULL;
}
-
+
/*
- * If the command being deleted has a compile procedure, increment the
- * interpreter's compileEpoch to invalidate its compiled code. This
- * makes sure that we don't later try to execute old code compiled with
- * command-specific (i.e., inline) bytecodes for the now-deleted
- * command. This field is checked in Tcl_EvalObj and ObjInterpProc, and
- * code whose compilation epoch doesn't match is recompiled.
+ * The list of command exported from the namespace might have changed.
+ * However, we do not need to recompute this just yet; next time we need
+ * the info will be soon enough.
+ */
+
+ TclInvalidateNsCmdLookup(cmdPtr->nsPtr);
+
+ /*
+ * If the command being deleted has a compile function, increment the
+ * interpreter's compileEpoch to invalidate its compiled code. This makes
+ * sure that we don't later try to execute old code compiled with
+ * command-specific (i.e., inline) bytecodes for the now-deleted command.
+ * This field is checked in Tcl_EvalObj and ObjInterpProc, and code whose
+ * compilation epoch doesn't match is recompiled.
*/
if (cmdPtr->compileProc != NULL) {
- iPtr->compileEpoch++;
+ iPtr->compileEpoch++;
}
if (cmdPtr->deleteProc != NULL) {
@@ -2628,15 +2829,15 @@ Tcl_DeleteCommandFromToken(interp, cmd)
* data will be a pointer to a ImportedCmdData structure describing
* the "real" command that this imported command refers to.
*/
-
+
/*
* If you are getting a crash during the call to deleteProc and
- * cmdPtr->deleteProc is a pointer to the function free(), the
- * most likely cause is that your extension allocated memory
- * for the clientData argument to Tcl_CreateObjCommand() with
- * the ckalloc() macro and you are now trying to deallocate
- * this memory with free() instead of ckfree(). You should
- * pass a pointer to your own method that calls ckfree().
+ * cmdPtr->deleteProc is a pointer to the function free(), the most
+ * likely cause is that your extension allocated memory for the
+ * clientData argument to Tcl_CreateObjCommand() with the ckalloc()
+ * macro and you are now trying to deallocate this memory with free()
+ * instead of ckfree(). You should pass a pointer to your own method
+ * that calls ckfree().
*/
(*cmdPtr->deleteProc)(cmdPtr->deleteData);
@@ -2649,78 +2850,77 @@ Tcl_DeleteCommandFromToken(interp, cmd)
*/
for (refPtr = cmdPtr->importRefPtr; refPtr != NULL;
- refPtr = nextRefPtr) {
+ refPtr = nextRefPtr) {
nextRefPtr = refPtr->nextPtr;
importCmd = (Tcl_Command) refPtr->importedCmdPtr;
- Tcl_DeleteCommandFromToken(interp, importCmd);
+ Tcl_DeleteCommandFromToken(interp, importCmd);
}
/*
- * Don't use hPtr to delete the hash entry here, because it's
- * possible that the deletion callback renamed the command.
- * Instead, use cmdPtr->hptr, and make sure that no-one else
- * has already deleted the hash entry.
+ * Don't use hPtr to delete the hash entry here, because it's possible
+ * that the deletion callback renamed the command. Instead, use
+ * cmdPtr->hptr, and make sure that no-one else has already deleted the
+ * hash entry.
*/
if (cmdPtr->hPtr != NULL) {
Tcl_DeleteHashEntry(cmdPtr->hPtr);
+ cmdPtr->hPtr = NULL;
}
/*
* Mark the Command structure as no longer valid. This allows
* TclExecuteByteCode to recognize when a Command has logically been
* deleted and a pointer to this Command structure cached in a CmdName
- * object is invalid. TclExecuteByteCode will look up the command again
- * in the interpreter's command hashtable.
+ * object is invalid. TclExecuteByteCode will look up the command again in
+ * the interpreter's command hashtable.
*/
cmdPtr->objProc = NULL;
/*
- * Now free the Command structure, unless there is another reference to
- * it from a CmdName Tcl object in some ByteCode code sequence. In that
- * case, delay the cleanup until all references are either discarded
- * (when a ByteCode is freed) or replaced by a new reference (when a
- * cached CmdName Command reference is found to be invalid and
- * TclExecuteByteCode looks up the command in the command hashtable).
+ * Now free the Command structure, unless there is another reference to it
+ * from a CmdName Tcl object in some ByteCode code sequence. In that case,
+ * delay the cleanup until all references are either discarded (when a
+ * ByteCode is freed) or replaced by a new reference (when a cached
+ * CmdName Command reference is found to be invalid and TclExecuteByteCode
+ * looks up the command in the command hashtable).
*/
-
- TclCleanupCommand(cmdPtr);
+
+ TclCleanupCommandMacro(cmdPtr);
return 0;
}
static char *
-CallCommandTraces(iPtr, cmdPtr, oldName, newName, flags)
- Interp *iPtr; /* Interpreter containing command. */
- Command *cmdPtr; /* Command whose traces are to be
- * invoked. */
- CONST char *oldName; /* Command's old name, or NULL if we
- * must get the name from cmdPtr */
- CONST char *newName; /* Command's new name, or NULL if
- * the command is not being renamed */
- int flags; /* Flags indicating the type of traces
- * to trigger, either TCL_TRACE_DELETE
- * or TCL_TRACE_RENAME. */
+CallCommandTraces(
+ Interp *iPtr, /* Interpreter containing command. */
+ Command *cmdPtr, /* Command whose traces are to be invoked. */
+ const char *oldName, /* Command's old name, or NULL if we must get
+ * the name from cmdPtr */
+ const char *newName, /* Command's new name, or NULL if the command
+ * is not being renamed */
+ int flags) /* Flags indicating the type of traces to
+ * trigger, either TCL_TRACE_DELETE or
+ * TCL_TRACE_RENAME. */
{
register CommandTrace *tracePtr;
ActiveCommandTrace active;
char *result;
Tcl_Obj *oldNamePtr = NULL;
- int mask = (TCL_TRACE_DELETE | TCL_TRACE_RENAME); /* Safety */
-
- flags &= mask;
+ Tcl_InterpState state = NULL;
if (cmdPtr->flags & CMD_TRACE_ACTIVE) {
- /*
- * While a rename trace is active, we will not process any more
- * rename traces; while a delete trace is active we will never
- * reach here -- because Tcl_DeleteCommandFromToken checks for the
- * condition (cmdPtr->flags & CMD_IS_DELETED) and returns immediately
- * when a command deletion is in progress. For all other traces,
- * delete traces will not be invoked but a call to TraceCommandProc
- * will ensure that tracePtr->clientData is freed whenever the
- * command "oldName" is deleted.
+ /*
+ * While a rename trace is active, we will not process any more rename
+ * traces; while a delete trace is active we will never reach here -
+ * because Tcl_DeleteCommandFromToken checks for the condition
+ * (cmdPtr->flags & CMD_IS_DELETED) and returns immediately when a
+ * command deletion is in progress. For all other traces, delete
+ * traces will not be invoked but a call to TraceCommandProc will
+ * ensure that tracePtr->clientData is freed whenever the command
+ * "oldName" is deleted.
*/
+
if (cmdPtr->flags & TCL_TRACE_RENAME) {
flags &= ~TCL_TRACE_RENAME;
}
@@ -2730,7 +2930,7 @@ CallCommandTraces(iPtr, cmdPtr, oldName, newName, flags)
}
cmdPtr->flags |= CMD_TRACE_ACTIVE;
cmdPtr->refCount++;
-
+
result = NULL;
active.nextPtr = iPtr->activeCmdTracePtr;
active.reverseScan = 0;
@@ -2740,37 +2940,41 @@ CallCommandTraces(iPtr, cmdPtr, oldName, newName, flags)
flags |= TCL_TRACE_DESTROYED;
}
active.cmdPtr = cmdPtr;
-
- Tcl_Preserve((ClientData) iPtr);
-
- for (tracePtr = cmdPtr->tracePtr; tracePtr != NULL;
- tracePtr = active.nextTracePtr) {
- int traceFlags = (tracePtr->flags & mask);
+ Tcl_Preserve(iPtr);
+
+ for (tracePtr = cmdPtr->tracePtr; tracePtr != NULL;
+ tracePtr = active.nextTracePtr) {
active.nextTracePtr = tracePtr->nextPtr;
- if (!(traceFlags & flags)) {
+ if (!(tracePtr->flags & flags)) {
continue;
}
- cmdPtr->flags |= traceFlags;
+ cmdPtr->flags |= tracePtr->flags;
if (oldName == NULL) {
TclNewObj(oldNamePtr);
Tcl_IncrRefCount(oldNamePtr);
- Tcl_GetCommandFullName((Tcl_Interp *) iPtr,
- (Tcl_Command) cmdPtr, oldNamePtr);
+ Tcl_GetCommandFullName((Tcl_Interp *) iPtr,
+ (Tcl_Command) cmdPtr, oldNamePtr);
oldName = TclGetString(oldNamePtr);
}
tracePtr->refCount++;
+ if (state == NULL) {
+ state = Tcl_SaveInterpState((Tcl_Interp *) iPtr, TCL_OK);
+ }
(*tracePtr->traceProc)(tracePtr->clientData,
(Tcl_Interp *) iPtr, oldName, newName, flags);
- cmdPtr->flags &= ~traceFlags;
+ cmdPtr->flags &= ~tracePtr->flags;
if ((--tracePtr->refCount) <= 0) {
- ckfree((char*)tracePtr);
+ ckfree((char *) tracePtr);
}
}
+ if (state) {
+ Tcl_RestoreInterpState((Tcl_Interp *) iPtr, state);
+ }
+
/*
- * If a new object was created to hold the full oldName,
- * free it now.
+ * If a new object was created to hold the full oldName, free it now.
*/
if (oldNamePtr != NULL) {
@@ -2778,26 +2982,55 @@ CallCommandTraces(iPtr, cmdPtr, oldName, newName, flags)
}
/*
- * Restore the variable's flags, remove the record of our active
- * traces, and then return.
+ * Restore the variable's flags, remove the record of our active traces,
+ * and then return.
*/
cmdPtr->flags &= ~CMD_TRACE_ACTIVE;
cmdPtr->refCount--;
iPtr->activeCmdTracePtr = active.nextPtr;
- Tcl_Release((ClientData) iPtr);
+ Tcl_Release(iPtr);
return result;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetCommandSource --
+ *
+ * This function returns a Tcl_Obj with the full source string for the
+ * command. This insures that traces get a correct NUL-terminated command
+ * string.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+GetCommandSource(
+ Interp *iPtr,
+ const char *command,
+ int numChars,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ if (!command) {
+ return Tcl_NewListObj(objc, objv);
+ }
+ if (command == (char *) -1) {
+ command = TclGetSrcInfoForCmd(iPtr, &numChars);
+ }
+ return Tcl_NewStringObj(command, numChars);
+}
/*
*----------------------------------------------------------------------
*
* TclCleanupCommand --
*
- * This procedure frees up a Command structure unless it is still
+ * This function frees up a Command structure unless it is still
* referenced from an interpreter's command hashtable or from a CmdName
* Tcl object representing the name of a command in a ByteCode
- * instruction sequence.
+ * instruction sequence.
*
* Results:
* None.
@@ -2811,8 +3044,8 @@ CallCommandTraces(iPtr, cmdPtr, oldName, newName, flags)
*/
void
-TclCleanupCommand(cmdPtr)
- register Command *cmdPtr; /* Points to the Command structure to
+TclCleanupCommand(
+ register Command *cmdPtr) /* Points to the Command structure to
* be freed. */
{
cmdPtr->refCount--;
@@ -2826,18 +3059,17 @@ TclCleanupCommand(cmdPtr)
*
* Tcl_CreateMathFunc --
*
- * Creates a new math function for expressions in a given
- * interpreter.
+ * Creates a new math function for expressions in a given interpreter.
*
* Results:
* None.
*
* Side effects:
- * The function defined by "name" is created or redefined. If the
- * function already exists then its definition is replaced; this
- * includes the builtin functions. Redefining a builtin function forces
- * all existing code to be invalidated since that code may be compiled
- * using an instruction specific to the replaced function. In addition,
+ * The Tcl function defined by "name" is created or redefined. If the
+ * function already exists then its definition is replaced; this includes
+ * the builtin functions. Redefining a builtin function forces all
+ * existing code to be invalidated since that code may be compiled using
+ * an instruction specific to the replaced function. In addition,
* redefioning a non-builtin function will force existing code to be
* invalidated if the number of arguments has changed.
*
@@ -2845,65 +3077,205 @@ TclCleanupCommand(cmdPtr)
*/
void
-Tcl_CreateMathFunc(interp, name, numArgs, argTypes, proc, clientData)
- Tcl_Interp *interp; /* Interpreter in which function is
- * to be available. */
- CONST char *name; /* Name of function (e.g. "sin"). */
- int numArgs; /* Nnumber of arguments required by
- * function. */
- Tcl_ValueType *argTypes; /* Array of types acceptable for
- * each argument. */
- Tcl_MathProc *proc; /* Procedure that implements the
- * math function. */
- ClientData clientData; /* Additional value to pass to the
- * function. */
+Tcl_CreateMathFunc(
+ Tcl_Interp *interp, /* Interpreter in which function is to be
+ * available. */
+ const char *name, /* Name of function (e.g. "sin"). */
+ int numArgs, /* Nnumber of arguments required by
+ * function. */
+ Tcl_ValueType *argTypes, /* Array of types acceptable for each
+ * argument. */
+ Tcl_MathProc *proc, /* C function that implements the math
+ * function. */
+ ClientData clientData) /* Additional value to pass to the
+ * function. */
{
- Interp *iPtr = (Interp *) interp;
- Tcl_HashEntry *hPtr;
- MathFunc *mathFuncPtr;
- int new, i;
+ Tcl_DString bigName;
+ OldMathFuncData *data = (OldMathFuncData *)
+ ckalloc(sizeof(OldMathFuncData));
+
+ data->proc = proc;
+ data->numArgs = numArgs;
+ data->argTypes = (Tcl_ValueType *)
+ ckalloc(numArgs * sizeof(Tcl_ValueType));
+ memcpy(data->argTypes, argTypes, numArgs * sizeof(Tcl_ValueType));
+ data->clientData = clientData;
+
+ Tcl_DStringInit(&bigName);
+ Tcl_DStringAppend(&bigName, "::tcl::mathfunc::", -1);
+ Tcl_DStringAppend(&bigName, name, -1);
+
+ Tcl_CreateObjCommand(interp, Tcl_DStringValue(&bigName),
+ OldMathFuncProc, data, OldMathFuncDeleteProc);
+ Tcl_DStringFree(&bigName);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * OldMathFuncProc --
+ *
+ * Dispatch to a math function created with Tcl_CreateMathFunc
+ *
+ * Results:
+ * Returns a standard Tcl result.
+ *
+ * Side effects:
+ * Whatever the math function does.
+ *
+ *----------------------------------------------------------------------
+ */
- hPtr = Tcl_CreateHashEntry(&iPtr->mathFuncTable, name, &new);
- if (new) {
- Tcl_SetHashValue(hPtr, ckalloc(sizeof(MathFunc)));
+static int
+OldMathFuncProc(
+ ClientData clientData, /* Ponter to OldMathFuncData describing the
+ * function being called */
+ Tcl_Interp *interp, /* Tcl interpreter */
+ int objc, /* Actual parameter count */
+ Tcl_Obj *const *objv) /* Parameter vector */
+{
+ Tcl_Obj *valuePtr;
+ OldMathFuncData *dataPtr = clientData;
+ Tcl_Value funcResult, *args;
+ int result;
+ int j, k;
+ double d;
+
+ /*
+ * Check argument count.
+ */
+
+ if (objc != dataPtr->numArgs + 1) {
+ MathFuncWrongNumArgs(interp, dataPtr->numArgs+1, objc, objv);
+ return TCL_ERROR;
}
- mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
- if (!new) {
- if (mathFuncPtr->builtinFuncIndex >= 0) {
- /*
- * We are redefining a builtin math function. Invalidate the
- * interpreter's existing code by incrementing its
- * compileEpoch member. This field is checked in Tcl_EvalObj
- * and ObjInterpProc, and code whose compilation epoch doesn't
- * match is recompiled. Newly compiled code will no longer
- * treat the function as builtin.
- */
+ /*
+ * Convert arguments from Tcl_Obj's to Tcl_Value's.
+ */
- iPtr->compileEpoch++;
- } else {
+ args = (Tcl_Value *) ckalloc(dataPtr->numArgs * sizeof(Tcl_Value));
+ for (j = 1, k = 0; j < objc; ++j, ++k) {
+
+ /* TODO: Convert to TclGetNumberFromObj() ? */
+ valuePtr = objv[j];
+ result = Tcl_GetDoubleFromObj(NULL, valuePtr, &d);
+#ifdef ACCEPT_NAN
+ if ((result != TCL_OK) && (valuePtr->typePtr == &tclDoubleType)) {
+ d = valuePtr->internalRep.doubleValue;
+ result = TCL_OK;
+ }
+#endif
+ if (result != TCL_OK) {
/*
- * A non-builtin function is being redefined. We must invalidate
- * existing code if the number of arguments has changed. This
- * is because existing code was compiled assuming that number.
+ * We have a non-numeric argument.
*/
- if (numArgs != mathFuncPtr->numArgs) {
- iPtr->compileEpoch++;
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "argument to math function didn't have numeric value",-1));
+ TclCheckBadOctal(interp, Tcl_GetString(valuePtr));
+ ckfree((char *)args);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Copy the object's numeric value to the argument record, converting
+ * it if necessary.
+ *
+ * NOTE: no bignum support; use the new mathfunc interface for that.
+ */
+
+ args[k].type = dataPtr->argTypes[k];
+ switch (args[k].type) {
+ case TCL_EITHER:
+ if (Tcl_GetLongFromObj(NULL, valuePtr, &(args[k].intValue))
+ == TCL_OK) {
+ args[k].type = TCL_INT;
+ break;
+ }
+ if (Tcl_GetWideIntFromObj(interp, valuePtr, &(args[k].wideValue))
+ == TCL_OK) {
+ args[k].type = TCL_WIDE_INT;
+ break;
+ }
+ args[k].type = TCL_DOUBLE;
+ /* FALLTHROUGH */
+
+ case TCL_DOUBLE:
+ args[k].doubleValue = d;
+ break;
+ case TCL_INT:
+ if (ExprIntFunc(NULL, interp, 2, &(objv[j-1])) != TCL_OK) {
+ ckfree((char *)args);
+ return TCL_ERROR;
+ }
+ valuePtr = Tcl_GetObjResult(interp);
+ Tcl_GetLongFromObj(NULL, valuePtr, &(args[k].intValue));
+ Tcl_ResetResult(interp);
+ break;
+ case TCL_WIDE_INT:
+ if (ExprWideFunc(NULL, interp, 2, &(objv[j-1])) != TCL_OK) {
+ ckfree((char *)args);
+ return TCL_ERROR;
}
+ valuePtr = Tcl_GetObjResult(interp);
+ Tcl_GetWideIntFromObj(NULL, valuePtr, &(args[k].wideValue));
+ Tcl_ResetResult(interp);
+ break;
}
}
-
- mathFuncPtr->builtinFuncIndex = -1; /* can't be a builtin function */
- if (numArgs > MAX_MATH_ARGS) {
- numArgs = MAX_MATH_ARGS;
+
+ /*
+ * Call the function.
+ */
+
+ errno = 0;
+ result = (*dataPtr->proc)(dataPtr->clientData, interp, args, &funcResult);
+ ckfree((char *)args);
+ if (result != TCL_OK) {
+ return result;
}
- mathFuncPtr->numArgs = numArgs;
- for (i = 0; i < numArgs; i++) {
- mathFuncPtr->argTypes[i] = argTypes[i];
+
+ /*
+ * Return the result of the call.
+ */
+
+ if (funcResult.type == TCL_INT) {
+ TclNewLongObj(valuePtr, funcResult.intValue);
+ } else if (funcResult.type == TCL_WIDE_INT) {
+ valuePtr = Tcl_NewWideIntObj(funcResult.wideValue);
+ } else {
+ return CheckDoubleResult(interp, funcResult.doubleValue);
}
- mathFuncPtr->proc = proc;
- mathFuncPtr->clientData = clientData;
+ Tcl_SetObjResult(interp, valuePtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * OldMathFuncDeleteProc --
+ *
+ * Cleans up after deleting a math function registered with
+ * Tcl_CreateMathFunc
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Frees allocated memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+OldMathFuncDeleteProc(
+ ClientData clientData)
+{
+ OldMathFuncData *dataPtr = clientData;
+
+ ckfree((void *) dataPtr->argTypes);
+ ckfree((void *) dataPtr);
}
/*
@@ -2915,64 +3287,80 @@ Tcl_CreateMathFunc(interp, name, numArgs, argTypes, proc, clientData)
* interpreter.
*
* Results:
- * TCL_OK if it succeeds, TCL_ERROR else (leaving an error message
- * in the interpreter result if that happens.)
+ * TCL_OK if it succeeds, TCL_ERROR else (leaving an error message in the
+ * interpreter result if that happens.)
*
* Side effects:
- * If this function succeeds, the variables pointed to by the
- * numArgsPtr and argTypePtr arguments will be updated to detail the
- * arguments allowed by the function. The variable pointed to by the
- * procPtr argument will be set to NULL if the function is a builtin
- * function, and will be set to the address of the C function used to
- * implement the math function otherwise (in which case the variable
- * pointed to by the clientDataPtr argument will also be updated.)
+ * If this function succeeds, the variables pointed to by the numArgsPtr
+ * and argTypePtr arguments will be updated to detail the arguments
+ * allowed by the function. The variable pointed to by the procPtr
+ * argument will be set to NULL if the function is a builtin function,
+ * and will be set to the address of the C function used to implement the
+ * math function otherwise (in which case the variable pointed to by the
+ * clientDataPtr argument will also be updated.)
*
*----------------------------------------------------------------------
*/
int
-Tcl_GetMathFuncInfo(interp, name, numArgsPtr, argTypesPtr, procPtr,
- clientDataPtr)
- Tcl_Interp *interp;
- CONST char *name;
- int *numArgsPtr;
- Tcl_ValueType **argTypesPtr;
- Tcl_MathProc **procPtr;
- ClientData *clientDataPtr;
+Tcl_GetMathFuncInfo(
+ Tcl_Interp *interp,
+ const char *name,
+ int *numArgsPtr,
+ Tcl_ValueType **argTypesPtr,
+ Tcl_MathProc **procPtr,
+ ClientData *clientDataPtr)
{
- Interp *iPtr = (Interp *) interp;
- Tcl_HashEntry *hPtr;
- MathFunc *mathFuncPtr;
- Tcl_ValueType *argTypes;
- int i,numArgs;
+ Tcl_Obj *cmdNameObj;
+ Command *cmdPtr;
- hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, name);
- if (hPtr == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "math function \"", name, "\" not known in this interpreter",
- (char *) NULL);
+ /*
+ * Get the command that implements the math function.
+ */
+
+ TclNewLiteralStringObj(cmdNameObj, "tcl::mathfunc::");
+ Tcl_AppendToObj(cmdNameObj, name, -1);
+ Tcl_IncrRefCount(cmdNameObj);
+ cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, cmdNameObj);
+ Tcl_DecrRefCount(cmdNameObj);
+
+ /*
+ * Report unknown functions.
+ */
+
+ if (cmdPtr == NULL) {
+ Tcl_Obj *message;
+
+ TclNewLiteralStringObj(message, "unknown math function \"");
+ Tcl_AppendToObj(message, name, -1);
+ Tcl_AppendToObj(message, "\"", 1);
+ Tcl_SetObjResult(interp, message);
+ *numArgsPtr = -1;
+ *argTypesPtr = NULL;
+ *procPtr = NULL;
+ *clientDataPtr = NULL;
return TCL_ERROR;
}
- mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
- *numArgsPtr = numArgs = mathFuncPtr->numArgs;
- if (numArgs == 0) {
- /* Avoid doing zero-sized allocs... */
- numArgs = 1;
- }
- *argTypesPtr = argTypes =
- (Tcl_ValueType *)ckalloc(numArgs * sizeof(Tcl_ValueType));
- for (i = 0; i < mathFuncPtr->numArgs; i++) {
- argTypes[i] = mathFuncPtr->argTypes[i];
- }
+ /*
+ * Retrieve function info for user defined functions; return dummy
+ * information for builtins.
+ */
+
+ if (cmdPtr->objProc == &OldMathFuncProc) {
+ OldMathFuncData *dataPtr = cmdPtr->clientData;
- if (mathFuncPtr->builtinFuncIndex == -1) {
- *procPtr = (Tcl_MathProc *) NULL;
+ *procPtr = dataPtr->proc;
+ *numArgsPtr = dataPtr->numArgs;
+ *argTypesPtr = dataPtr->argTypes;
+ *clientDataPtr = dataPtr->clientData;
} else {
- *procPtr = mathFuncPtr->proc;
- *clientDataPtr = mathFuncPtr->clientData;
+ *procPtr = NULL;
+ *numArgsPtr = -1;
+ *argTypesPtr = NULL;
+ *procPtr = NULL;
+ *clientDataPtr = NULL;
}
-
return TCL_OK;
}
@@ -2985,9 +3373,9 @@ Tcl_GetMathFuncInfo(interp, name, numArgsPtr, argTypesPtr, procPtr,
* interpreter.
*
* Results:
- * A pointer to a Tcl_Obj structure with a reference count of zero,
- * or NULL in the case of an error (in which case a suitable error
- * message will be left in the interpreter result.)
+ * A pointer to a Tcl_Obj structure with a reference count of zero, or
+ * NULL in the case of an error (in which case a suitable error message
+ * will be left in the interpreter result.)
*
* Side effects:
* None.
@@ -2996,28 +3384,46 @@ Tcl_GetMathFuncInfo(interp, name, numArgsPtr, argTypesPtr, procPtr,
*/
Tcl_Obj *
-Tcl_ListMathFuncs(interp, pattern)
- Tcl_Interp *interp;
- CONST char *pattern;
+Tcl_ListMathFuncs(
+ Tcl_Interp *interp,
+ const char *pattern)
{
- Interp *iPtr = (Interp *) interp;
- Tcl_Obj *resultList = Tcl_NewObj();
- register Tcl_HashEntry *hPtr;
- Tcl_HashSearch hSearch;
- CONST char *name;
-
- for (hPtr = Tcl_FirstHashEntry(&iPtr->mathFuncTable, &hSearch);
- hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) {
- name = Tcl_GetHashKey(&iPtr->mathFuncTable, hPtr);
- if ((pattern == NULL || Tcl_StringMatch(name, pattern)) &&
- /* I don't expect this to fail, but... */
- Tcl_ListObjAppendElement(interp, resultList,
- Tcl_NewStringObj(name,-1)) != TCL_OK) {
- Tcl_DecrRefCount(resultList);
- return NULL;
+ Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
+ Namespace *nsPtr;
+ Namespace *dummy1NsPtr;
+ Namespace *dummy2NsPtr;
+ const char *dummyNamePtr;
+ Tcl_Obj *result = Tcl_NewObj();
+
+ TclGetNamespaceForQualName(interp, "::tcl::mathfunc",
+ globalNsPtr, TCL_FIND_ONLY_NS | TCL_GLOBAL_ONLY,
+ &nsPtr, &dummy1NsPtr, &dummy2NsPtr, &dummyNamePtr);
+ if (nsPtr == NULL) {
+ return result;
+ }
+
+ if ((pattern != NULL) && TclMatchIsTrivial(pattern)) {
+ if (Tcl_FindHashEntry(&nsPtr->cmdTable, pattern) != NULL) {
+ Tcl_ListObjAppendElement(NULL, result,
+ Tcl_NewStringObj(pattern, -1));
+ }
+ } else {
+ Tcl_HashSearch cmdHashSearch;
+ Tcl_HashEntry *cmdHashEntry =
+ Tcl_FirstHashEntry(&nsPtr->cmdTable,&cmdHashSearch);
+
+ for (; cmdHashEntry != NULL;
+ cmdHashEntry = Tcl_NextHashEntry(&cmdHashSearch)) {
+ const char *cmdNamePtr =
+ Tcl_GetHashKey(&nsPtr->cmdTable, cmdHashEntry);
+
+ if (pattern == NULL || Tcl_StringMatch(cmdNamePtr, pattern)) {
+ Tcl_ListObjAppendElement(NULL, result,
+ Tcl_NewStringObj(cmdNamePtr, -1));
+ }
}
}
- return resultList;
+ return result;
}
/*
@@ -3025,13 +3431,12 @@ Tcl_ListMathFuncs(interp, pattern)
*
* TclInterpReady --
*
- * Check if an interpreter is ready to eval commands or scripts,
- * i.e., if it was not deleted and if the nesting level is not
- * too high.
+ * Check if an interpreter is ready to eval commands or scripts, i.e., if
+ * it was not deleted and if the nesting level is not too high.
*
* Results:
- * The return value is TCL_OK if it the interpreter is ready,
- * TCL_ERROR otherwise.
+ * The return value is TCL_OK if it the interpreter is ready, TCL_ERROR
+ * otherwise.
*
* Side effects:
* The interpreters object and string results are cleared.
@@ -3039,15 +3444,18 @@ Tcl_ListMathFuncs(interp, pattern)
*----------------------------------------------------------------------
*/
-int
-TclInterpReady(interp)
- Tcl_Interp *interp;
+int
+TclInterpReady(
+ Tcl_Interp *interp)
{
+#if !defined(TCL_NO_STACK_CHECK)
+ int localInt; /* used for checking the stack */
+#endif
register Interp *iPtr = (Interp *) interp;
/*
- * Reset both the interpreter's string and object results and clear
- * out any previous error information.
+ * Reset both the interpreter's string and object results and clear out
+ * any previous error information.
*/
Tcl_ResetResult(interp);
@@ -3055,46 +3463,53 @@ TclInterpReady(interp)
/*
* If the interpreter has been deleted, return an error.
*/
-
+
if (iPtr->flags & DELETED) {
Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "attempt to call eval in deleted interpreter", -1);
- Tcl_SetErrorCode(interp, "CORE", "IDELETE",
- "attempt to call eval in deleted interpreter",
- (char *) NULL);
+ Tcl_AppendResult(interp,
+ "attempt to call eval in deleted interpreter", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "IDELETE",
+ "attempt to call eval in deleted interpreter", NULL);
return TCL_ERROR;
}
/*
- * Check depth of nested calls to Tcl_Eval: if this gets too large,
- * it's probably because of an infinite loop somewhere.
+ * Check depth of nested calls to Tcl_Eval: if this gets too large, it's
+ * probably because of an infinite loop somewhere.
*/
- if (((iPtr->numLevels) > iPtr->maxNestingDepth)
- || (TclpCheckStackSpace() == 0)) {
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "too many nested evaluations (infinite loop?)", -1);
- return TCL_ERROR;
+ if (((iPtr->numLevels) <= iPtr->maxNestingDepth)
+ && CheckCStack(iPtr, &localInt)) {
+ return TCL_OK;
}
- return TCL_OK;
+ if (!CheckCStack(iPtr, &localInt)) {
+ Tcl_AppendResult(interp,
+ "out of stack space (infinite loop?)", NULL);
+ } else {
+ Tcl_AppendResult(interp,
+ "too many nested evaluations (infinite loop?)", NULL);
+ }
+ return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
- * TclEvalObjvInternal --
+ * TclEvalObjvInternal
*
- * This procedure evaluates a Tcl command that has already been
- * parsed into words, with one Tcl_Obj holding each word. The caller
- * is responsible for managing the iPtr->numLevels.
+ * This function evaluates a Tcl command that has already been parsed
+ * into words, with one Tcl_Obj holding each word. The caller is
+ * responsible for managing the iPtr->numLevels.
+ *
+ * TclEvalObjvInternal is the backend for Tcl_EvalObjv, the bytecode
+ * engine also calls it directly.
*
* Results:
- * The return value is a standard Tcl completion code such as
- * TCL_OK or TCL_ERROR. A result or error message is left in
- * interp's result. If an error occurs, this procedure does
- * NOT add any information to the errorInfo variable.
+ * The return value is a standard Tcl completion code such as TCL_OK or
+ * TCL_ERROR. A result or error message is left in interp's result. If an
+ * error occurs, this function does NOT add any information to the
+ * errorInfo variable.
*
* Side effects:
* Depends on the command.
@@ -3103,39 +3518,39 @@ TclInterpReady(interp)
*/
int
-TclEvalObjvInternal(interp, objc, objv, command, length, flags)
- Tcl_Interp *interp; /* Interpreter in which to evaluate the
- * command. Also used for error
- * reporting. */
- int objc; /* Number of words in command. */
- Tcl_Obj *CONST objv[]; /* An array of pointers to objects that are
+TclEvalObjvInternal(
+ Tcl_Interp *interp, /* Interpreter in which to evaluate the
+ * command. Also used for error reporting. */
+ int objc, /* Number of words in command. */
+ Tcl_Obj *const objv[], /* An array of pointers to objects that are
* the words that make up the command. */
- CONST char *command; /* Points to the beginning of the string
- * representation of the command; this
- * is used for traces. If the string
- * representation of the command is
- * unknown, an empty string should be
- * supplied. If it is NULL, no traces will
- * be called. */
- int length; /* Number of bytes in command; if -1, all
+ const char *command, /* Points to the beginning of the string
+ * representation of the command; this is used
+ * for traces. NULL if the string
+ * representation of the command is unknown is
+ * to be generated from (objc,objv), -1 if it
+ * is to be generated from bytecode
+ * source. This is only needed the traces. */
+ int length, /* Number of bytes in command; if -1, all
* characters up to the first null byte are
* used. */
- int flags; /* Collection of OR-ed bits that control
- * the evaluation of the script. Only
+ int flags) /* Collection of OR-ed bits that control the
+ * evaluation of the script. Only
* TCL_EVAL_GLOBAL and TCL_EVAL_INVOKE are
* currently supported. */
-
{
Command *cmdPtr;
Interp *iPtr = (Interp *) interp;
Tcl_Obj **newObjv;
int i;
- CallFrame *savedVarFramePtr; /* Saves old copy of iPtr->varFramePtr
- * in case TCL_EVAL_GLOBAL was set. */
+ CallFrame *savedVarFramePtr = NULL;
+ CallFrame *varFramePtr = iPtr->varFramePtr;
int code = TCL_OK;
int traceCode = TCL_OK;
- int checkTraces = 1;
+ int checkTraces = 1, traced;
Namespace *savedNsPtr = NULL;
+ Namespace *lookupNsPtr = iPtr->lookupNsPtr;
+ Tcl_Obj *commandPtr = NULL;
if (TclInterpReady(interp) == TCL_ERROR) {
return TCL_ERROR;
@@ -3145,93 +3560,107 @@ TclEvalObjvInternal(interp, objc, objv, command, length, flags)
return TCL_OK;
}
+ /*
+ * If any execution traces rename or delete the current command, we may
+ * need (at most) two passes here.
+ */
+
+ reparseBecauseOfTraces:
/*
- * If any execution traces rename or delete the current command,
- * we may need (at most) two passes here.
+ * Configure evaluation context to match the requested flags.
*/
- savedVarFramePtr = iPtr->varFramePtr;
- while (1) {
-
- /* Configure evaluation context to match the requested flags */
- if (flags & TCL_EVAL_GLOBAL) {
- iPtr->varFramePtr = NULL;
- } else if ((flags & TCL_EVAL_INVOKE) && iPtr->varFramePtr) {
- savedNsPtr = iPtr->varFramePtr->nsPtr;
- iPtr->varFramePtr->nsPtr = iPtr->globalNsPtr;
- }
-
- /*
- * Find the procedure to execute this command. If there isn't one,
- * then see if there is a command "unknown". If so, create a new
- * word array with "unknown" as the first word and the original
- * command words as arguments. Then call ourselves recursively
- * to execute it.
- */
- cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[0]);
- if (cmdPtr == NULL) {
- newObjv = (Tcl_Obj **) ckalloc((unsigned)
- ((objc + 1) * sizeof (Tcl_Obj *)));
- for (i = objc-1; i >= 0; i--) {
- newObjv[i+1] = objv[i];
- }
- newObjv[0] = Tcl_NewStringObj("::unknown", -1);
- Tcl_IncrRefCount(newObjv[0]);
- cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, newObjv[0]);
- if (cmdPtr == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "invalid command name \"", Tcl_GetString(objv[0]), "\"",
- (char *) NULL);
- code = TCL_ERROR;
+ if (flags) {
+ if (flags & TCL_EVAL_INVOKE) {
+ savedNsPtr = varFramePtr->nsPtr;
+ if (lookupNsPtr) {
+ varFramePtr->nsPtr = lookupNsPtr;
+ iPtr->lookupNsPtr = NULL;
} else {
- iPtr->numLevels++;
- code = TclEvalObjvInternal(interp, objc+1, newObjv,
- command, length, 0);
- iPtr->numLevels--;
+ varFramePtr->nsPtr = iPtr->globalNsPtr;
}
- Tcl_DecrRefCount(newObjv[0]);
- ckfree((char *) newObjv);
- if (savedNsPtr) {
- iPtr->varFramePtr->nsPtr = savedNsPtr;
+ } else if ((flags & TCL_EVAL_GLOBAL)
+ && (varFramePtr != iPtr->rootFramePtr) && !savedVarFramePtr) {
+ varFramePtr = iPtr->rootFramePtr;
+ savedVarFramePtr = iPtr->varFramePtr;
+ iPtr->varFramePtr = varFramePtr;
+ }
+ }
+
+ /*
+ * Find the function to execute this command. If there isn't one, then see
+ * if there is an unknown command handler registered for this namespace.
+ * If so, create a new word array with the handler as the first words and
+ * the original command words as arguments. Then call ourselves
+ * recursively to execute it.
+ */
+
+ cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[0]);
+ if (!cmdPtr) {
+ goto notFound;
+ }
+
+ if (savedNsPtr) {
+ varFramePtr->nsPtr = savedNsPtr;
+ } else if (iPtr->ensembleRewrite.sourceObjs) {
+ /*
+ * TCL_EVAL_INVOKE was not set: clear rewrite rules
+ */
+
+ iPtr->ensembleRewrite.sourceObjs = NULL;
+ }
+
+ /*
+ * Call trace functions if needed.
+ */
+
+ traced = (iPtr->tracePtr || (cmdPtr->flags & CMD_HAS_EXEC_TRACES));
+ if (traced && checkTraces) {
+ int cmdEpoch = cmdPtr->cmdEpoch;
+ int newEpoch;
+
+ /*
+ * Insure that we have a correct nul-terminated command string for the
+ * trace code.
+ */
+
+ commandPtr = GetCommandSource(iPtr, command, length, objc, objv);
+ command = TclGetStringFromObj(commandPtr, &length);
+
+ /*
+ * Execute any command or execution traces. Note that we bump up the
+ * command's reference count for the duration of the calling of the
+ * traces so that the structure doesn't go away underneath our feet.
+ */
+
+ cmdPtr->refCount++;
+ if (iPtr->tracePtr && (traceCode == TCL_OK)) {
+ traceCode = TclCheckInterpTraces(interp, command, length,
+ cmdPtr, code, TCL_TRACE_ENTER_EXEC, objc, objv);
+ }
+ if ((cmdPtr->flags & CMD_HAS_EXEC_TRACES) && (traceCode == TCL_OK)) {
+ traceCode = TclCheckExecutionTraces(interp, command, length,
+ cmdPtr, code, TCL_TRACE_ENTER_EXEC, objc, objv);
+ }
+ newEpoch = cmdPtr->cmdEpoch;
+ TclCleanupCommandMacro(cmdPtr);
+
+ /*
+ * If the traces modified/deleted the command or any existing traces,
+ * they will update the command's epoch. When that happens, set
+ * checkTraces is set to 0 to prevent the re-calling of traces (and
+ * any possible infinite loop) and we go back to re-find the command
+ * implementation.
+ */
+
+ if (cmdEpoch != newEpoch) {
+ checkTraces = 0;
+ if (commandPtr) {
+ Tcl_DecrRefCount(commandPtr);
}
- goto done;
- }
- if (savedNsPtr) {
- iPtr->varFramePtr->nsPtr = savedNsPtr;
+ goto reparseBecauseOfTraces;
}
-
- /*
- * Call trace procedures if needed.
- */
- if ((checkTraces) && (command != NULL)) {
- int cmdEpoch = cmdPtr->cmdEpoch;
- int newEpoch;
-
- cmdPtr->refCount++;
- /*
- * If the first set of traces modifies/deletes the command or
- * any existing traces, then the set checkTraces to 0 and
- * go through this while loop one more time.
- */
- if (iPtr->tracePtr != NULL && traceCode == TCL_OK) {
- traceCode = TclCheckInterpTraces(interp, command, length,
- cmdPtr, code, TCL_TRACE_ENTER_EXEC, objc, objv);
- }
- if ((cmdPtr->flags & CMD_HAS_EXEC_TRACES)
- && (traceCode == TCL_OK)) {
- traceCode = TclCheckExecutionTraces(interp, command, length,
- cmdPtr, code, TCL_TRACE_ENTER_EXEC, objc, objv);
- }
- newEpoch = cmdPtr->cmdEpoch;
- TclCleanupCommand(cmdPtr);
- if (cmdEpoch != newEpoch) {
- /* The command has been modified in some way */
- checkTraces = 0;
- continue;
- }
- }
- break;
}
#ifdef USE_DTRACE
@@ -3245,14 +3674,24 @@ TclEvalObjvInternal(interp, objc, objv, command, length, flags)
TCL_DTRACE_CMD_ARGS(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7],
a[8], a[9]);
}
+ if (TCL_DTRACE_CMD_INFO_ENABLED() && iPtr->cmdFramePtr) {
+ Tcl_Obj *info = TclInfoFrame(interp, iPtr->cmdFramePtr);
+ char *a[4]; int i[2];
+
+ TclDTraceInfo(info, a, i);
+ TCL_DTRACE_CMD_INFO(a[0], a[1], a[2], a[3], i[0], i[1]);
+ TclDecrRefCount(info);
+ }
#endif /* USE_DTRACE */
/*
* Finally, invoke the command's Tcl_ObjCmdProc.
*/
+
cmdPtr->refCount++;
iPtr->cmdCount++;
- if ( code == TCL_OK && traceCode == TCL_OK) {
+ if (code == TCL_OK && traceCode == TCL_OK
+ && !TclLimitExceeded(iPtr->limit)) {
if (TCL_DTRACE_CMD_ENTRY_ENABLED()) {
TCL_DTRACE_CMD_ENTRY(TclGetString(objv[0]), objc - 1,
(Tcl_Obj **)(objv + 1));
@@ -3262,48 +3701,58 @@ TclEvalObjvInternal(interp, objc, objv, command, length, flags)
TCL_DTRACE_CMD_RETURN(TclGetString(objv[0]), code);
}
}
- if (Tcl_AsyncReady()) {
+
+ if (TclAsyncReady(iPtr)) {
code = Tcl_AsyncInvoke(interp, code);
}
+ if (code == TCL_OK && TclLimitReady(iPtr->limit)) {
+ code = Tcl_LimitCheck(interp);
+ }
/*
* Call 'leave' command traces
*/
- if (!(cmdPtr->flags & CMD_IS_DELETED)) {
- int saveErrFlags = iPtr->flags
- & (ERR_IN_PROGRESS | ERR_ALREADY_LOGGED | ERROR_CODE_SET);
- if ((cmdPtr->flags & CMD_HAS_EXEC_TRACES) && (traceCode == TCL_OK)) {
- traceCode = TclCheckExecutionTraces (interp, command, length,
- cmdPtr, code, TCL_TRACE_LEAVE_EXEC, objc, objv);
- }
- if (iPtr->tracePtr != NULL && traceCode == TCL_OK) {
- traceCode = TclCheckInterpTraces(interp, command, length,
- cmdPtr, code, TCL_TRACE_LEAVE_EXEC, objc, objv);
- }
- if (traceCode == TCL_OK) {
- iPtr->flags |= saveErrFlags;
+
+ if (traced) {
+ if (!(cmdPtr->flags & CMD_IS_DELETED)) {
+ if ((cmdPtr->flags & CMD_HAS_EXEC_TRACES) && traceCode == TCL_OK){
+ traceCode = TclCheckExecutionTraces(interp, command, length,
+ cmdPtr, code, TCL_TRACE_LEAVE_EXEC, objc, objv);
+ }
+ if (iPtr->tracePtr != NULL && traceCode == TCL_OK) {
+ traceCode = TclCheckInterpTraces(interp, command, length,
+ cmdPtr, code, TCL_TRACE_LEAVE_EXEC, objc, objv);
+ }
+ }
+
+ /*
+ * If one of the trace invocation resulted in error, then change the
+ * result code accordingly. Note, that the interp->result should
+ * already be set correctly by the call to TraceExecutionProc.
+ */
+
+ if (traceCode != TCL_OK) {
+ code = traceCode;
+ }
+ if (commandPtr) {
+ Tcl_DecrRefCount(commandPtr);
}
}
- TclCleanupCommand(cmdPtr);
/*
- * If one of the trace invocation resulted in error, then
- * change the result code accordingly. Note, that the
- * interp->result should already be set correctly by the
- * call to TraceExecutionProc.
+ * Decrement the reference count of cmdPtr and deallocate it if it has
+ * dropped to zero.
*/
- if (traceCode != TCL_OK) {
- code = traceCode;
- }
-
+ TclCleanupCommandMacro(cmdPtr);
+
/*
- * If the interpreter has a non-empty string result, the result
- * object is either empty or stale because some procedure set
- * interp->result directly. If so, move the string result to the
- * result object, then reset the string result.
+ * If the interpreter has a non-empty string result, the result object is
+ * either empty or stale because some function set interp->result
+ * directly. If so, move the string result to the result object, then
+ * reset the string result.
*/
-
+
if (*(iPtr->result) != 0) {
(void) Tcl_GetObjResult(interp);
}
@@ -3313,532 +3762,213 @@ TclEvalObjvInternal(interp, objc, objv, command, length, flags)
Tcl_Obj *r;
r = Tcl_GetObjResult(interp);
- TCL_DTRACE_CMD_RESULT(TclGetString(objv[0]), code, TclGetString(r), r);
+ TCL_DTRACE_CMD_RESULT(TclGetString(objv[0]), code, TclGetString(r),r);
}
#endif /* USE_DTRACE */
- done:
- iPtr->varFramePtr = savedVarFramePtr;
+ done:
+ if (savedVarFramePtr) {
+ iPtr->varFramePtr = savedVarFramePtr;
+ }
return code;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_EvalObjv --
- *
- * This procedure evaluates a Tcl command that has already been
- * parsed into words, with one Tcl_Obj holding each word.
- *
- * Results:
- * The return value is a standard Tcl completion code such as
- * TCL_OK or TCL_ERROR. A result or error message is left in
- * interp's result.
- *
- * Side effects:
- * Depends on the command.
- *
- *----------------------------------------------------------------------
- */
-int
-Tcl_EvalObjv(interp, objc, objv, flags)
- Tcl_Interp *interp; /* Interpreter in which to evaluate the
- * command. Also used for error
- * reporting. */
- int objc; /* Number of words in command. */
- Tcl_Obj *CONST objv[]; /* An array of pointers to objects that are
- * the words that make up the command. */
- int flags; /* Collection of OR-ed bits that control
- * the evaluation of the script. Only
- * TCL_EVAL_GLOBAL and TCL_EVAL_INVOKE
- * are currently supported. */
-{
- Interp *iPtr = (Interp *)interp;
- Trace *tracePtr;
- Tcl_DString cmdBuf;
- char *cmdString = ""; /* A command string is only necessary for
- * command traces or error logs; it will be
- * generated to replace this default value if
- * necessary. */
- int cmdLen = 0; /* a non-zero value indicates that a command
- * string was generated. */
- int code = TCL_OK;
- int i;
- int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS);
-
- for (tracePtr = iPtr->tracePtr; tracePtr; tracePtr = tracePtr->nextPtr) {
- if ((tracePtr->level == 0) || (iPtr->numLevels <= tracePtr->level)) {
- /*
- * The command may be needed for an execution trace. Generate a
- * command string.
- */
-
- Tcl_DStringInit(&cmdBuf);
- for (i = 0; i < objc; i++) {
- Tcl_DStringAppendElement(&cmdBuf, Tcl_GetString(objv[i]));
+ notFound:
+ {
+ Namespace *currNsPtr = NULL; /* Used to check for and invoke any
+ * registered unknown command handler
+ * for the current namespace (TIP
+ * 181). */
+ int newObjc, handlerObjc;
+ Tcl_Obj **handlerObjv;
+
+ currNsPtr = varFramePtr->nsPtr;
+ if ((currNsPtr == NULL) || (currNsPtr->unknownHandlerPtr == NULL)) {
+ currNsPtr = iPtr->globalNsPtr;
+ if (currNsPtr == NULL) {
+ Tcl_Panic("TclEvalObjvInternal: NULL global namespace pointer");
}
- cmdString = Tcl_DStringValue(&cmdBuf);
- cmdLen = Tcl_DStringLength(&cmdBuf);
- break;
}
- }
- iPtr->numLevels++;
- code = TclEvalObjvInternal(interp, objc, objv, cmdString, cmdLen, flags);
- iPtr->numLevels--;
+ /*
+ * Check to see if the resolution namespace has lost its unknown
+ * handler. If so, reset it to "::unknown".
+ */
- /*
- * If we are again at the top level, process any unusual
- * return code returned by the evaluated code.
- */
-
- if (iPtr->numLevels == 0) {
- if (code == TCL_RETURN) {
- code = TclUpdateReturnInfo(iPtr);
+ if (currNsPtr->unknownHandlerPtr == NULL) {
+ TclNewLiteralStringObj(currNsPtr->unknownHandlerPtr, "::unknown");
+ Tcl_IncrRefCount(currNsPtr->unknownHandlerPtr);
}
- if ((code != TCL_OK) && (code != TCL_ERROR)
- && !allowExceptions) {
- ProcessUnexpectedResult(interp, code);
- code = TCL_ERROR;
+
+ /*
+ * Get the list of words for the unknown handler and allocate enough
+ * space to hold both the handler prefix and all words of the command
+ * invokation itself.
+ */
+
+ Tcl_ListObjGetElements(NULL, currNsPtr->unknownHandlerPtr,
+ &handlerObjc, &handlerObjv);
+ newObjc = objc + handlerObjc;
+ newObjv = (Tcl_Obj **) TclStackAlloc(interp,
+ (int) sizeof(Tcl_Obj *) * newObjc);
+
+ /*
+ * Copy command prefix from unknown handler and add on the real
+ * command's full argument list. Note that we only use memcpy() once
+ * because we have to increment the reference count of all the handler
+ * arguments anyway.
+ */
+
+ for (i = 0; i < handlerObjc; ++i) {
+ newObjv[i] = handlerObjv[i];
+ Tcl_IncrRefCount(newObjv[i]);
}
- }
-
- if ((code == TCL_ERROR) && !(flags & TCL_EVAL_INVOKE)) {
+ memcpy(newObjv+handlerObjc, objv, sizeof(Tcl_Obj *) * (unsigned)objc);
- /*
- * If there was an error, a command string will be needed for the
- * error log: generate it now if it was not done previously.
+ /*
+ * Look up and invoke the handler (by recursive call to this
+ * function). If there is no handler at all, instead of doing the
+ * recursive call we just generate a generic error message; it would
+ * be an infinite-recursion nightmare otherwise.
*/
- if (cmdLen == 0) {
- Tcl_DStringInit(&cmdBuf);
- for (i = 0; i < objc; i++) {
- Tcl_DStringAppendElement(&cmdBuf, Tcl_GetString(objv[i]));
- }
- cmdString = Tcl_DStringValue(&cmdBuf);
- cmdLen = Tcl_DStringLength(&cmdBuf);
+ cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, newObjv[0]);
+ if (cmdPtr == NULL) {
+ Tcl_AppendResult(interp, "invalid command name \"",
+ TclGetString(objv[0]), "\"", NULL);
+ code = TCL_ERROR;
+ } else {
+ iPtr->numLevels++;
+ code = TclEvalObjvInternal(interp, newObjc, newObjv, command,
+ length, 0);
+ iPtr->numLevels--;
}
- Tcl_LogCommandInfo(interp, cmdString, cmdString, cmdLen);
- }
- if (cmdLen != 0) {
- Tcl_DStringFree(&cmdBuf);
+ /*
+ * Release any resources we locked and allocated during the handler
+ * call.
+ */
+
+ for (i = 0; i < handlerObjc; ++i) {
+ Tcl_DecrRefCount(newObjv[i]);
+ }
+ TclStackFree(interp, newObjv);
+ if (savedNsPtr) {
+ varFramePtr->nsPtr = savedNsPtr;
+ }
+ goto done;
}
- return code;
}
/*
*----------------------------------------------------------------------
*
- * Tcl_LogCommandInfo --
+ * Tcl_EvalObjv --
*
- * This procedure is invoked after an error occurs in an interpreter.
- * It adds information to the "errorInfo" variable to describe the
- * command that was being executed when the error occurred.
+ * This function evaluates a Tcl command that has already been parsed
+ * into words, with one Tcl_Obj holding each word.
*
* Results:
- * None.
+ * The return value is a standard Tcl completion code such as TCL_OK or
+ * TCL_ERROR. A result or error message is left in interp's result.
*
* Side effects:
- * Information about the command is added to errorInfo and the
- * line number stored internally in the interpreter is set. If this
- * is the first call to this procedure or Tcl_AddObjErrorInfo since
- * an error occurred, then old information in errorInfo is
- * deleted.
+ * Depends on the command.
*
*----------------------------------------------------------------------
*/
-void
-Tcl_LogCommandInfo(interp, script, command, length)
- Tcl_Interp *interp; /* Interpreter in which to log information. */
- CONST char *script; /* First character in script containing
- * command (must be <= command). */
- CONST char *command; /* First character in command that
- * generated the error. */
- int length; /* Number of bytes in command (-1 means
- * use all bytes up to first null byte). */
+int
+Tcl_EvalObjv(
+ Tcl_Interp *interp, /* Interpreter in which to evaluate the
+ * command. Also used for error reporting. */
+ int objc, /* Number of words in command. */
+ Tcl_Obj *const objv[], /* An array of pointers to objects that are
+ * the words that make up the command. */
+ int flags) /* Collection of OR-ed bits that control the
+ * evaluation of the script. Only
+ * TCL_EVAL_GLOBAL and TCL_EVAL_INVOKE are
+ * currently supported. */
{
- char buffer[200];
- register CONST char *p;
- char *ellipsis = "";
Interp *iPtr = (Interp *) interp;
+ int code = TCL_OK;
+ int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS);
+
+ iPtr->numLevels++;
+ code = TclEvalObjvInternal(interp, objc, objv, NULL, 0, flags);
+ iPtr->numLevels--;
+
+ if (code == TCL_OK) {
+ return code;
+ } else {
- if (iPtr->flags & ERR_ALREADY_LOGGED) {
/*
- * Someone else has already logged error information for this
- * command; we shouldn't add anything more.
+ * If we are again at the top level, process any unusual return code
+ * returned by the evaluated code.
*/
- return;
- }
+ if (iPtr->numLevels == 0) {
+ if (code == TCL_RETURN) {
+ code = TclUpdateReturnInfo(iPtr);
+ }
+ if ((code != TCL_ERROR) && !allowExceptions) {
+ ProcessUnexpectedResult(interp, code);
+ code = TCL_ERROR;
+ }
+ }
- /*
- * Compute the line number where the error occurred.
- */
+ if ((code == TCL_ERROR) && !(flags & TCL_EVAL_INVOKE)) {
+ /*
+ * If there was an error, a command string will be needed for the
+ * error log: generate it now. Do not worry too much about doing
+ * it expensively.
+ */
- iPtr->errorLine = 1;
- for (p = script; p != command; p++) {
- if (*p == '\n') {
- iPtr->errorLine++;
- }
- }
+ Tcl_Obj *listPtr;
+ char *cmdString;
+ int cmdLen;
- /*
- * Create an error message to add to errorInfo, including up to a
- * maximum number of characters of the command.
- */
+ listPtr = Tcl_NewListObj(objc, objv);
+ cmdString = Tcl_GetStringFromObj(listPtr, &cmdLen);
+ Tcl_LogCommandInfo(interp, cmdString, cmdString, cmdLen);
+ Tcl_DecrRefCount(listPtr);
+ }
- if (length < 0) {
- length = strlen(command);
- }
- if (length > 150) {
- length = 150;
- ellipsis = "...";
- }
- while ( (command[length] & 0xC0) == 0x80 ) {
- /*
- * Back up truncation point so that we don't truncate in the
- * middle of a multi-byte character (in UTF-8)
- */
- length--;
- ellipsis = "...";
- }
- if (!(iPtr->flags & ERR_IN_PROGRESS)) {
- sprintf(buffer, "\n while executing\n\"%.*s%s\"",
- length, command, ellipsis);
- } else {
- sprintf(buffer, "\n invoked from within\n\"%.*s%s\"",
- length, command, ellipsis);
+ return code;
}
- Tcl_AddObjErrorInfo(interp, buffer, -1);
- iPtr->flags &= ~ERR_ALREADY_LOGGED;
}
/*
*----------------------------------------------------------------------
*
- * Tcl_EvalTokensStandard, EvalTokensStandard --
+ * Tcl_EvalTokensStandard --
+ *
+ * Given an array of tokens parsed from a Tcl command (e.g., the tokens
+ * that make up a word or the index for an array variable) this function
+ * evaluates the tokens and concatenates their values to form a single
+ * result value.
*
- * Given an array of tokens parsed from a Tcl command (e.g., the
- * tokens that make up a word or the index for an array variable)
- * this procedure evaluates the tokens and concatenates their
- * values to form a single result value.
- *
* Results:
- * The return value is a standard Tcl completion code such as
- * TCL_OK or TCL_ERROR. A result or error message is left in
- * interp's result.
+ * The return value is a standard Tcl completion code such as TCL_OK or
+ * TCL_ERROR. A result or error message is left in interp's result.
*
* Side effects:
* Depends on the array of tokens being evaled.
*
- * TIP #280 : Keep public API, internally extended API.
*----------------------------------------------------------------------
*/
int
-Tcl_EvalTokensStandard(interp, tokenPtr, count)
- Tcl_Interp *interp; /* Interpreter in which to lookup
- * variables, execute nested commands,
- * and report errors. */
- Tcl_Token *tokenPtr; /* Pointer to first in an array of tokens
- * to evaluate and concatenate. */
- int count; /* Number of tokens to consider at tokenPtr.
+Tcl_EvalTokensStandard(
+ Tcl_Interp *interp, /* Interpreter in which to lookup variables,
+ * execute nested commands, and report
+ * errors. */
+ Tcl_Token *tokenPtr, /* Pointer to first in an array of tokens to
+ * evaluate and concatenate. */
+ int count) /* Number of tokens to consider at tokenPtr.
* Must be at least 1. */
{
-#ifdef TCL_TIP280
- return EvalTokensStandard (interp, tokenPtr, count, 1, NULL, NULL);
-}
-
-static int
-EvalTokensStandard(interp, tokenPtr, count, line, clNextOuter, outerScript)
- Tcl_Interp *interp; /* Interpreter in which to lookup
- * variables, execute nested commands,
- * and report errors. */
- Tcl_Token *tokenPtr; /* Pointer to first in an array of tokens
- * to evaluate and concatenate. */
- int count; /* Number of tokens to consider at tokenPtr.
- * Must be at least 1. */
- int line; /* The line the script starts on. */
- int* clNextOuter; /* Information about an outer context for */
- CONST char* outerScript; /* continuation line data. This is set by
- * EvalEx() to properly handle [...]-nested
- * commands. The 'outerScript' refers to the
- * most-outer script containing the embedded
- * command, which is refered to by 'script'. The
- * 'clNextOuter' refers to the current entry in
- * the table of continuation lines in this
- * "master script", and the character offsets are
- * relative to the 'outerScript' as well.
- *
- * If outerScript == script, then this call is for
- * words in the outer-most script/command. See
- * Tcl_EvalEx() and TclEvalObjEx() for the places
- * generating arguments for which this is true.
- */
-{
-#endif
- Tcl_Obj *resultPtr, *indexPtr, *valuePtr;
- char buffer[TCL_UTF_MAX];
-#ifdef TCL_MEM_DEBUG
-# define MAX_VAR_CHARS 5
-#else
-# define MAX_VAR_CHARS 30
-#endif
- char nameBuffer[MAX_VAR_CHARS+1];
- char *varName, *index;
- CONST char *p = NULL; /* Initialized to avoid compiler warning. */
- int length, code;
-#ifdef TCL_TIP280
-#define NUM_STATIC_POS 20
- int isLiteral, maxNumCL, numCL, i, adjust;
- int* clPosition = NULL;
- Interp* iPtr = (Interp*) interp;
- int inFile = iPtr->evalFlags & TCL_EVAL_FILE;
-#endif
-
- /*
- * The only tricky thing about this procedure is that it attempts to
- * avoid object creation and string copying whenever possible. For
- * example, if the value is just a nested command, then use the
- * command's result object directly.
- */
-
- code = TCL_OK;
- resultPtr = NULL;
- Tcl_ResetResult(interp);
-#ifdef TCL_TIP280
- /*
- * For the handling of continuation lines in literals we first check if
- * this is actually a literal. For if not we can forego the additional
- * processing. Otherwise we pre-allocate a small table to store the
- * locations of all continuation lines we find in this literal, if
- * any. The table is extended if needed.
- */
-
- numCL = 0;
- maxNumCL = 0;
- isLiteral = 1;
- for (i=0 ; i < count; i++) {
- if ((tokenPtr[i].type != TCL_TOKEN_TEXT) &&
- (tokenPtr[i].type != TCL_TOKEN_BS)) {
- isLiteral = 0;
- break;
- }
- }
-
- if (isLiteral) {
- maxNumCL = NUM_STATIC_POS;
- clPosition = (int*) ckalloc (maxNumCL*sizeof(int));
- }
- adjust = 0;
-#endif
- for ( ; count > 0; count--, tokenPtr++) {
- valuePtr = NULL;
-
- /*
- * The switch statement below computes the next value to be
- * concat to the result, as either a range of text or an
- * object.
- */
-
- switch (tokenPtr->type) {
- case TCL_TOKEN_TEXT:
- p = tokenPtr->start;
- length = tokenPtr->size;
- break;
-
- case TCL_TOKEN_BS:
- length = TclParseBackslash(tokenPtr->start, tokenPtr->size,
- (int *) NULL, buffer);
- p = buffer;
-#ifdef TCL_TIP280
- /*
- * If the backslash sequence we found is in a literal, and
- * represented a continuation line, we compute and store its
- * location (as char offset to the beginning of the _result_
- * script). We may have to extend the table of locations.
- *
- * Note that the continuation line information is relevant
- * even if the word we are processing is not a literal, as it
- * can affect nested commands. See the branch for
- * TCL_TOKEN_COMMAND below, where the adjustment we are
- * tracking here is taken into account. The good thing is that
- * we do not need a table of everything, just the number of
- * lines we have to add as correction.
- */
-
- if ((length == 1) && (buffer[0] == ' ') &&
- (tokenPtr->start[1] == '\n')) {
- if (isLiteral) {
- int clPos;
- if (resultPtr == 0) {
- clPos = 0;
- } else {
- Tcl_GetStringFromObj(resultPtr, &clPos);
- }
-
- if (numCL >= maxNumCL) {
- maxNumCL *= 2;
- clPosition = (int*) ckrealloc ((char*)clPosition,
- maxNumCL*sizeof(int));
- }
- clPosition[numCL] = clPos;
- numCL ++;
- }
- adjust ++;
- }
-#endif
- break;
-
- case TCL_TOKEN_COMMAND: {
- Interp *iPtr = (Interp *) interp;
- iPtr->numLevels++;
- code = TclInterpReady(interp);
- if (code == TCL_OK) {
-#ifndef TCL_TIP280
- code = Tcl_EvalEx(interp,
- tokenPtr->start+1, tokenPtr->size-2, 0);
-#else
- /* TIP #280: Transfer line information to nested command */
- TclAdvanceContinuations (&line, &clNextOuter,
- tokenPtr->start - outerScript);
- code = EvalEx(interp,
- tokenPtr->start+1, tokenPtr->size-2, 0,
- line + adjust, clNextOuter, outerScript);
-
- /*
- * Restore flag reset by the nested eval for future
- * bracketed commands and their CmdFrame setup
- */
- if (inFile) {
- iPtr->evalFlags |= TCL_EVAL_FILE;
- }
-#endif
- }
- iPtr->numLevels--;
- if (code != TCL_OK) {
- goto done;
- }
- valuePtr = Tcl_GetObjResult(interp);
- break;
- }
-
- case TCL_TOKEN_VARIABLE:
- if (tokenPtr->numComponents == 1) {
- indexPtr = NULL;
- index = NULL;
- } else {
-#ifndef TCL_TIP280
- code = Tcl_EvalTokensStandard(interp, tokenPtr+2,
- tokenPtr->numComponents - 1);
-#else
- /* TIP #280: Transfer line information to nested command */
- code = EvalTokensStandard(interp, tokenPtr+2,
- tokenPtr->numComponents - 1, line, NULL, NULL);
-#endif
- if (code != TCL_OK) {
- goto done;
- }
- indexPtr = Tcl_GetObjResult(interp);
- Tcl_IncrRefCount(indexPtr);
- index = Tcl_GetString(indexPtr);
- }
-
- /*
- * We have to make a copy of the variable name in order
- * to have a null-terminated string. We can't make a
- * temporary modification to the script to null-terminate
- * the name, because a trace callback might potentially
- * reuse the script and be affected by the null character.
- */
-
- if (tokenPtr[1].size <= MAX_VAR_CHARS) {
- varName = nameBuffer;
- } else {
- varName = ckalloc((unsigned) (tokenPtr[1].size + 1));
- }
- strncpy(varName, tokenPtr[1].start, (size_t) tokenPtr[1].size);
- varName[tokenPtr[1].size] = 0;
- valuePtr = Tcl_GetVar2Ex(interp, varName, index,
- TCL_LEAVE_ERR_MSG);
- if (varName != nameBuffer) {
- ckfree(varName);
- }
- if (indexPtr != NULL) {
- Tcl_DecrRefCount(indexPtr);
- }
- if (valuePtr == NULL) {
- code = TCL_ERROR;
- goto done;
- }
- count -= tokenPtr->numComponents;
- tokenPtr += tokenPtr->numComponents;
- break;
-
- default:
- panic("unexpected token type in Tcl_EvalTokensStandard");
- }
-
- /*
- * If valuePtr isn't NULL, the next piece of text comes from that
- * object; otherwise, take length bytes starting at p.
- */
-
- if (resultPtr == NULL) {
- if (valuePtr != NULL) {
- resultPtr = valuePtr;
- } else {
- resultPtr = Tcl_NewStringObj(p, length);
- }
- Tcl_IncrRefCount(resultPtr);
- } else {
- if (Tcl_IsShared(resultPtr)) {
- Tcl_DecrRefCount(resultPtr);
- resultPtr = Tcl_DuplicateObj(resultPtr);
- Tcl_IncrRefCount(resultPtr);
- }
- if (valuePtr != NULL) {
- p = Tcl_GetStringFromObj(valuePtr, &length);
- }
- Tcl_AppendToObj(resultPtr, p, length);
- }
- }
- if (resultPtr != NULL) {
- Tcl_SetObjResult(interp, resultPtr);
-#ifdef TCL_TIP280
- /*
- * If the code found continuation lines (which implies that this word
- * is a literal), then we store the accumulated table of locations in
- * the thread-global data structure for the bytecode compiler to find
- * later, assuming that the literal is a script which will be
- * compiled.
- */
-
- if (numCL) {
- TclContinuationsEnter(resultPtr, numCL, clPosition);
- }
-
- /*
- * Release the temp table we used to collect the locations of
- * continuation lines, if any.
- */
-
- if (maxNumCL) {
- ckfree ((char*) clPosition);
- }
-#endif
- } else {
- code = TCL_ERROR;
- }
-
- done:
- if (resultPtr != NULL) {
- Tcl_DecrRefCount(resultPtr);
- }
- return code;
+ return TclSubstTokens(interp, tokenPtr, count, /* numLeftPtr */ NULL, 1,
+ NULL, NULL);
}
/*
@@ -3846,67 +3976,62 @@ EvalTokensStandard(interp, tokenPtr, count, line, clNextOuter, outerScript)
*
* Tcl_EvalTokens --
*
- * Given an array of tokens parsed from a Tcl command (e.g., the
- * tokens that make up a word or the index for an array variable)
- * this procedure evaluates the tokens and concatenates their
- * values to form a single result value.
+ * Given an array of tokens parsed from a Tcl command (e.g., the tokens
+ * that make up a word or the index for an array variable) this function
+ * evaluates the tokens and concatenates their values to form a single
+ * result value.
*
* Results:
- * The return value is a pointer to a newly allocated Tcl_Obj
- * containing the value of the array of tokens. The reference
- * count of the returned object has been incremented. If an error
- * occurs in evaluating the tokens then a NULL value is returned
- * and an error message is left in interp's result.
+ * The return value is a pointer to a newly allocated Tcl_Obj containing
+ * the value of the array of tokens. The reference count of the returned
+ * object has been incremented. If an error occurs in evaluating the
+ * tokens then a NULL value is returned and an error message is left in
+ * interp's result.
*
* Side effects:
* A new object is allocated to hold the result.
*
*----------------------------------------------------------------------
*
- * This uses a non-standard return convention; its use is now deprecated.
- * It is a wrapper for the new function Tcl_EvalTokensStandard, and is not
- * used in the core any longer. It is only kept for backward compatibility.
+ * This uses a non-standard return convention; its use is now deprecated. It
+ * is a wrapper for the new function Tcl_EvalTokensStandard, and is not used
+ * in the core any longer. It is only kept for backward compatibility.
*/
Tcl_Obj *
-Tcl_EvalTokens(interp, tokenPtr, count)
- Tcl_Interp *interp; /* Interpreter in which to lookup
- * variables, execute nested commands,
- * and report errors. */
- Tcl_Token *tokenPtr; /* Pointer to first in an array of tokens
- * to evaluate and concatenate. */
- int count; /* Number of tokens to consider at tokenPtr.
+Tcl_EvalTokens(
+ Tcl_Interp *interp, /* Interpreter in which to lookup variables,
+ * execute nested commands, and report
+ * errors. */
+ Tcl_Token *tokenPtr, /* Pointer to first in an array of tokens to
+ * evaluate and concatenate. */
+ int count) /* Number of tokens to consider at tokenPtr.
* Must be at least 1. */
{
- int code;
Tcl_Obj *resPtr;
-
- code = Tcl_EvalTokensStandard(interp, tokenPtr, count);
- if (code == TCL_OK) {
- resPtr = Tcl_GetObjResult(interp);
- Tcl_IncrRefCount(resPtr);
- Tcl_ResetResult(interp);
- return resPtr;
- } else {
+
+ if (Tcl_EvalTokensStandard(interp, tokenPtr, count) != TCL_OK) {
return NULL;
}
+ resPtr = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(resPtr);
+ Tcl_ResetResult(interp);
+ return resPtr;
}
-
/*
*----------------------------------------------------------------------
*
- * Tcl_EvalEx, EvalEx --
+ * Tcl_EvalEx, TclEvalEx --
*
- * This procedure evaluates a Tcl script without using the compiler
- * or byte-code interpreter. It just parses the script, creates
- * values for each word of each command, then calls EvalObjv
- * to execute each command.
+ * This function evaluates a Tcl script without using the compiler or
+ * byte-code interpreter. It just parses the script, creates values for
+ * each word of each command, then calls EvalObjv to execute each
+ * command.
*
* Results:
- * The return value is a standard Tcl completion code such as
- * TCL_OK or TCL_ERROR. A result or error message is left in
- * interp's result.
+ * The return value is a standard Tcl completion code such as TCL_OK or
+ * TCL_ERROR. A result or error message is left in interp's result.
*
* Side effects:
* Depends on the script.
@@ -3916,38 +4041,35 @@ Tcl_EvalTokens(interp, tokenPtr, count)
*/
int
-Tcl_EvalEx(interp, script, numBytes, flags)
- Tcl_Interp *interp; /* Interpreter in which to evaluate the
- * script. Also used for error reporting. */
- CONST char *script; /* First character of script to evaluate. */
- int numBytes; /* Number of bytes in script. If < 0, the
+Tcl_EvalEx(
+ Tcl_Interp *interp, /* Interpreter in which to evaluate the
+ * script. Also used for error reporting. */
+ const char *script, /* First character of script to evaluate. */
+ int numBytes, /* Number of bytes in script. If < 0, the
* script consists of all bytes up to the
* first null character. */
- int flags; /* Collection of OR-ed bits that control
- * the evaluation of the script. Only
- * TCL_EVAL_GLOBAL is currently
- * supported. */
+ int flags) /* Collection of OR-ed bits that control the
+ * evaluation of the script. Only
+ * TCL_EVAL_GLOBAL is currently supported. */
{
-#ifdef TCL_TIP280
- return EvalEx (interp, script, numBytes, flags, 1, NULL, script);
+ return TclEvalEx(interp, script, numBytes, flags, 1, NULL, script);
}
-static int
-EvalEx(interp, script, numBytes, flags, line, clNextOuter, outerScript)
- Tcl_Interp *interp; /* Interpreter in which to evaluate the
- * script. Also used for error reporting. */
- CONST char *script; /* First character of script to evaluate. */
- int numBytes; /* Number of bytes in script. If < 0, the
+int
+TclEvalEx(
+ Tcl_Interp *interp, /* Interpreter in which to evaluate the
+ * script. Also used for error reporting. */
+ const char *script, /* First character of script to evaluate. */
+ int numBytes, /* Number of bytes in script. If < 0, the
* script consists of all bytes up to the
- * first null character. */
- int flags; /* Collection of OR-ed bits that control
- * the evaluation of the script. Only
- * TCL_EVAL_GLOBAL is currently
- * supported. */
- int line; /* The line the script starts on. */
- int* clNextOuter; /* Information about an outer context for */
- CONST char* outerScript; /* continuation line data. This is set only in
- * EvalTokensStandard(), to properly handle
+ * first NUL character. */
+ int flags, /* Collection of OR-ed bits that control the
+ * evaluation of the script. Only
+ * TCL_EVAL_GLOBAL is currently supported. */
+ int line, /* The line the script starts on. */
+ int* clNextOuter, /* Information about an outer context for */
+ CONST char* outerScript) /* continuation line data. This is set only in
+ * TclSubstTokens(), to properly handle
* [...]-nested commands. The 'outerScript'
* refers to the most-outer script containing the
* embedded command, which is refered to by
@@ -3963,31 +4085,32 @@ EvalEx(interp, script, numBytes, flags, line, clNextOuter, outerScript)
* generating arguments for which this is true.
*/
{
-#endif
Interp *iPtr = (Interp *) interp;
- CONST char *p, *next;
- Tcl_Parse parse;
-#define NUM_STATIC_OBJS 20
- Tcl_Obj *staticObjArray[NUM_STATIC_OBJS], **objv;
+ const char *p, *next;
+ const unsigned int minObjs = 20;
+ Tcl_Obj **objv, **objvSpace;
+ int *expand, *lines, *lineSpace;
Tcl_Token *tokenPtr;
- int code = TCL_OK;
- int i, commandLength, bytesLeft, nested;
- CallFrame *savedVarFramePtr; /* Saves old copy of iPtr->varFramePtr
- * in case TCL_EVAL_GLOBAL was set. */
+ int commandLength, bytesLeft, expandRequested, code = TCL_OK;
+ CallFrame *savedVarFramePtr;/* Saves old copy of iPtr->varFramePtr in case
+ * TCL_EVAL_GLOBAL was set. */
int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS);
-
- /*
- * The variables below keep track of how much state has been
- * allocated while evaluating the script, so that it can be freed
- * properly if an error occurs.
- */
-
- int gotParse = 0, objectsUsed = 0;
-
-#ifdef TCL_TIP280
- /* TIP #280 Structures for tracking of command locations. */
- CmdFrame eeFrame;
-
+ int gotParse = 0;
+ unsigned int i, objectsUsed = 0;
+ /* These variables keep track of how much
+ * state has been allocated while evaluating
+ * the script, so that it can be freed
+ * properly if an error occurs. */
+ Tcl_Parse *parsePtr = (Tcl_Parse *)
+ TclStackAlloc(interp, sizeof(Tcl_Parse));
+ CmdFrame *eeFramePtr = (CmdFrame *)
+ TclStackAlloc(interp, sizeof(CmdFrame));
+ Tcl_Obj **stackObjArray = (Tcl_Obj **)
+ TclStackAlloc(interp, minObjs * sizeof(Tcl_Obj *));
+ int *expandStack = (int *) TclStackAlloc(interp, minObjs * sizeof(int));
+ int *linesStack = (int *) TclStackAlloc(interp, minObjs * sizeof(int));
+ /* TIP #280 Structures for tracking of command
+ * locations. */
/*
* Pointer for the tracking of invisible continuation lines. Initialized
* only if the caller gave us a table of locations to track, via
@@ -4005,7 +4128,6 @@ EvalEx(interp, script, numBytes, flags, line, clNextOuter, outerScript)
clNext = &iPtr->scriptCLLocPtr->loc[0];
}
}
-#endif
if (numBytes < 0) {
numBytes = strlen(script);
@@ -4014,112 +4136,102 @@ EvalEx(interp, script, numBytes, flags, line, clNextOuter, outerScript)
savedVarFramePtr = iPtr->varFramePtr;
if (flags & TCL_EVAL_GLOBAL) {
- iPtr->varFramePtr = NULL;
+ iPtr->varFramePtr = iPtr->rootFramePtr;
}
/*
- * Each iteration through the following loop parses the next
- * command from the script and then executes it.
+ * Each iteration through the following loop parses the next command from
+ * the script and then executes it.
*/
- objv = staticObjArray;
+ objv = objvSpace = stackObjArray;
+ lines = lineSpace = linesStack;
+ expand = expandStack;
p = script;
bytesLeft = numBytes;
- if (iPtr->evalFlags & TCL_BRACKET_TERM) {
- nested = 1;
- } else {
- nested = 0;
- }
-#ifdef TCL_TIP280
- /* TIP #280 Initialize tracking. Do not push on the frame stack yet. */
/*
- * We may cont. counting based on a specific context (CTX), or open a new
- * context, either for a sourced script, or 'eval'. For sourced files we
- * always have a path object, even if nothing was specified in the interp
- * itself. That makes code using it simpler as NULL checks can be left
- * out. Sourced file without path in the 'scriptFile' is possible during
- * Tcl initialization.
+ * TIP #280 Initialize tracking. Do not push on the frame stack yet.
+ *
+ * We may continue counting based on a specific context (CTX), or open a
+ * new context, either for a sourced script, or 'eval'. For sourced files
+ * we always have a path object, even if nothing was specified in the
+ * interp itself. That makes code using it simpler as NULL checks can be
+ * left out. Sourced file without path in the 'scriptFile' is possible
+ * during Tcl initialization.
*/
if (iPtr->evalFlags & TCL_EVAL_CTX) {
- /* Path information comes out of the context. */
+ /*
+ * Path information comes out of the context.
+ */
- eeFrame.type = TCL_LOCATION_SOURCE;
- eeFrame.data.eval.path = iPtr->invokeCmdFramePtr->data.eval.path;
- Tcl_IncrRefCount (eeFrame.data.eval.path);
+ eeFramePtr->type = TCL_LOCATION_SOURCE;
+ eeFramePtr->data.eval.path = iPtr->invokeCmdFramePtr->data.eval.path;
+ Tcl_IncrRefCount(eeFramePtr->data.eval.path);
} else if (iPtr->evalFlags & TCL_EVAL_FILE) {
- /* Set up for a sourced file */
+ /*
+ * Set up for a sourced file.
+ */
- eeFrame.type = TCL_LOCATION_SOURCE;
+ eeFramePtr->type = TCL_LOCATION_SOURCE;
if (iPtr->scriptFile) {
- /* Normalization here, to have the correct pwd. Should have
+ /*
+ * Normalization here, to have the correct pwd. Should have
* negligible impact on performance, as the norm should have been
* done already by the 'source' invoking us, and it caches the
- * result
+ * result.
*/
- Tcl_Obj* norm = Tcl_FSGetNormalizedPath (interp, iPtr->scriptFile);
- if (!norm) {
- /* Error message in the interp result */
- return TCL_ERROR;
+ Tcl_Obj *norm = Tcl_FSGetNormalizedPath(interp, iPtr->scriptFile);
+
+ if (norm == NULL) {
+ /*
+ * Error message in the interp result.
+ */
+ code = TCL_ERROR;
+ goto error;
}
- eeFrame.data.eval.path = norm;
+ eeFramePtr->data.eval.path = norm;
} else {
- eeFrame.data.eval.path = Tcl_NewStringObj ("",-1);
+ TclNewLiteralStringObj(eeFramePtr->data.eval.path, "");
}
- Tcl_IncrRefCount (eeFrame.data.eval.path);
+ Tcl_IncrRefCount(eeFramePtr->data.eval.path);
} else {
- /* Set up for plain eval */
+ /*
+ * Set up for plain eval.
+ */
- eeFrame.type = TCL_LOCATION_EVAL;
- eeFrame.data.eval.path = NULL;
+ eeFramePtr->type = TCL_LOCATION_EVAL;
+ eeFramePtr->data.eval.path = NULL;
}
- eeFrame.level = (iPtr->cmdFramePtr == NULL
- ? 1
- : iPtr->cmdFramePtr->level + 1);
- eeFrame.framePtr = iPtr->framePtr;
- eeFrame.nextPtr = iPtr->cmdFramePtr;
- eeFrame.nline = 0;
- eeFrame.line = NULL;
-#endif
+ eeFramePtr->level = iPtr->cmdFramePtr ? iPtr->cmdFramePtr->level + 1 : 1;
+ eeFramePtr->framePtr = iPtr->framePtr;
+ eeFramePtr->nextPtr = iPtr->cmdFramePtr;
+ eeFramePtr->nline = 0;
+ eeFramePtr->line = NULL;
iPtr->evalFlags = 0;
do {
- if (Tcl_ParseCommand(interp, p, bytesLeft, nested, &parse)
- != TCL_OK) {
+ if (Tcl_ParseCommand(interp, p, bytesLeft, 0, parsePtr) != TCL_OK) {
code = TCL_ERROR;
goto error;
}
- gotParse = 1;
-
- if (nested && parse.term == (script + numBytes)) {
- /*
- * A nested script can only terminate in ']'. If
- * the parsing got terminated at the end of the script,
- * there was no closing ']'. Report the syntax error.
- */
- code = TCL_ERROR;
- goto error;
- }
-
-#ifdef TCL_TIP280
/*
* TIP #280 Track lines. The parser may have skipped text till it
- * found the command we are now at. We have count the lines in this
+ * found the command we are now at. We have to count the lines in this
* block, and do not forget invisible continuation lines.
*/
- TclAdvanceLines (&line, p, parse.commandStart);
+ TclAdvanceLines(&line, p, parsePtr->commandStart);
TclAdvanceContinuations (&line, &clNext,
- parse.commandStart - outerScript);
-#endif
+ parsePtr->commandStart - outerScript);
- if (parse.numWords > 0) {
-#ifdef TCL_TIP280
+ gotParse = 1;
+ if (parsePtr->numWords > 0) {
/*
* TIP #280. Track lines within the words of the current
* command. We use a separate pointer into the table of
@@ -4127,77 +4239,138 @@ EvalEx(interp, script, numBytes, flags, line, clNextOuter, outerScript)
* per-command parsing.
*/
- int wordLine = line;
- CONST char* wordStart = parse.commandStart;
+ int wordLine = line;
+ const char *wordStart = parsePtr->commandStart;
int* wordCLNext = clNext;
-#endif
/*
* Generate an array of objects for the words of the command.
*/
-
- if (parse.numWords <= NUM_STATIC_OBJS) {
- objv = staticObjArray;
- } else {
- objv = (Tcl_Obj **) ckalloc((unsigned)
- (parse.numWords * sizeof (Tcl_Obj *)));
- }
-#ifdef TCL_TIP280
- eeFrame.nline = parse.numWords;
- eeFrame.line = (int*) ckalloc((unsigned)
- (parse.numWords * sizeof (int)));
-#endif
+ unsigned int objectsNeeded = 0;
+ unsigned int numWords = parsePtr->numWords;
- for (objectsUsed = 0, tokenPtr = parse.tokenPtr;
- objectsUsed < parse.numWords;
- objectsUsed++, tokenPtr += (tokenPtr->numComponents + 1)) {
-#ifndef TCL_TIP280
- code = Tcl_EvalTokensStandard(interp, tokenPtr+1,
- tokenPtr->numComponents);
-#else
- /*
- * TIP #280. Track lines to current word. Save the
- * information on a per-word basis, signaling dynamic words as
- * needed. Make the information available to the recursively
- * called evaluator as well, including the type of context
- * (source vs. eval).
+ if (numWords > minObjs) {
+ expand = (int *) ckalloc(numWords * sizeof(int));
+ objvSpace = (Tcl_Obj **)
+ ckalloc(numWords * sizeof(Tcl_Obj *));
+ lineSpace = (int *) ckalloc(numWords * sizeof(int));
+ }
+ expandRequested = 0;
+ objv = objvSpace;
+ lines = lineSpace;
+
+ for (objectsUsed = 0, tokenPtr = parsePtr->tokenPtr;
+ objectsUsed < numWords;
+ objectsUsed++, tokenPtr += tokenPtr->numComponents+1) {
+ /*
+ * TIP #280. Track lines to current word. Save the information
+ * on a per-word basis, signaling dynamic words as needed.
+ * Make the information available to the recursively called
+ * evaluator as well, including the type of context (source
+ * vs. eval).
*/
- TclAdvanceLines (&wordLine, wordStart, tokenPtr->start);
+ TclAdvanceLines(&wordLine, wordStart, tokenPtr->start);
TclAdvanceContinuations (&wordLine, &wordCLNext,
tokenPtr->start - outerScript);
wordStart = tokenPtr->start;
- eeFrame.line [objectsUsed] = (TclWordKnownAtCompileTime (tokenPtr)
- ? wordLine
- : -1);
+ lines[objectsUsed] = TclWordKnownAtCompileTime(tokenPtr, NULL)
+ ? wordLine : -1;
- if (eeFrame.type == TCL_LOCATION_SOURCE) {
+ if (eeFramePtr->type == TCL_LOCATION_SOURCE) {
iPtr->evalFlags |= TCL_EVAL_FILE;
}
- code = EvalTokensStandard(interp, tokenPtr+1,
- tokenPtr->numComponents, wordLine,
- wordCLNext, outerScript);
+ code = TclSubstTokens(interp, tokenPtr+1,
+ tokenPtr->numComponents, NULL, wordLine,
+ wordCLNext, outerScript);
iPtr->evalFlags = 0;
-#endif
- if (code == TCL_OK) {
- objv[objectsUsed] = Tcl_GetObjResult(interp);
- Tcl_IncrRefCount(objv[objectsUsed]);
-#ifdef TCL_TIP280
- if (wordCLNext) {
- TclContinuationsEnterDerived (objv[objectsUsed],
- wordStart - outerScript, wordCLNext);
+ if (code != TCL_OK) {
+ goto error;
+ }
+ objv[objectsUsed] = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(objv[objectsUsed]);
+ if (tokenPtr->type == TCL_TOKEN_EXPAND_WORD) {
+ int numElements;
+
+ code = TclListObjLength(interp, objv[objectsUsed],
+ &numElements);
+ if (code == TCL_ERROR) {
+ /*
+ * Attempt to expand a non-list.
+ */
+
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (expanding word %d)", objectsUsed));
+ Tcl_DecrRefCount(objv[objectsUsed]);
+ goto error;
}
-#endif
+ expandRequested = 1;
+ expand[objectsUsed] = 1;
+
+ objectsNeeded += (numElements ? numElements : 1);
} else {
- goto error;
+ expand[objectsUsed] = 0;
+ objectsNeeded++;
+ }
+
+ if (wordCLNext) {
+ TclContinuationsEnterDerived (objv[objectsUsed],
+ wordStart - outerScript, wordCLNext);
+ }
+ } /* for loop */
+ if (expandRequested) {
+ /*
+ * Some word expansion was requested. Check for objv resize.
+ */
+
+ Tcl_Obj **copy = objvSpace;
+ int *lcopy = lineSpace;
+ int wordIdx = numWords;
+ int objIdx = objectsNeeded - 1;
+
+ if ((numWords > minObjs) || (objectsNeeded > minObjs)) {
+ objv = objvSpace = (Tcl_Obj **)
+ ckalloc(objectsNeeded * sizeof(Tcl_Obj *));
+ lines = lineSpace = (int *)
+ ckalloc(objectsNeeded * sizeof(int));
+ }
+
+ objectsUsed = 0;
+ while (wordIdx--) {
+ if (expand[wordIdx]) {
+ int numElements;
+ Tcl_Obj **elements, *temp = copy[wordIdx];
+
+ Tcl_ListObjGetElements(NULL, temp, &numElements,
+ &elements);
+ objectsUsed += numElements;
+ while (numElements--) {
+ lines[objIdx] = -1;
+ objv[objIdx--] = elements[numElements];
+ Tcl_IncrRefCount(elements[numElements]);
+ }
+ Tcl_DecrRefCount(temp);
+ } else {
+ lines[objIdx] = lcopy[wordIdx];
+ objv[objIdx--] = copy[wordIdx];
+ objectsUsed++;
+ }
+ }
+ objv += objIdx+1;
+
+ if (copy != stackObjArray) {
+ ckfree((char *) copy);
+ }
+ if (lcopy != linesStack) {
+ ckfree((char *) lcopy);
}
}
-
+
/*
* Execute the command and free the objects for its words.
*
@@ -4208,29 +4381,28 @@ EvalEx(interp, script, numBytes, flags, line, clNextOuter, outerScript)
* have been executed.
*/
-#ifdef TCL_TIP280
- eeFrame.cmd.str.cmd = parse.commandStart;
- eeFrame.cmd.str.len = parse.commandSize;
+ eeFramePtr->cmd.str.cmd = parsePtr->commandStart;
+ eeFramePtr->cmd.str.len = parsePtr->commandSize;
- if (parse.term == parse.commandStart + parse.commandSize - 1) {
- eeFrame.cmd.str.len --;
+ if (parsePtr->term ==
+ parsePtr->commandStart + parsePtr->commandSize - 1) {
+ eeFramePtr->cmd.str.len--;
}
- TclArgumentEnter (interp, objv, objectsUsed, &eeFrame);
- iPtr->cmdFramePtr = &eeFrame;
-#endif
- iPtr->numLevels++;
- code = TclEvalObjvInternal(interp, objectsUsed, objv,
- parse.commandStart, parse.commandSize, 0);
+ eeFramePtr->nline = objectsUsed;
+ eeFramePtr->line = lines;
+
+ TclArgumentEnter (interp, objv, objectsUsed, eeFramePtr);
+ iPtr->cmdFramePtr = eeFramePtr;
+ iPtr->numLevels++;
+ code = TclEvalObjvInternal(interp, objectsUsed, objv,
+ parsePtr->commandStart, parsePtr->commandSize, 0);
iPtr->numLevels--;
-#ifdef TCL_TIP280
iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr;
TclArgumentRelease (interp, objv, objectsUsed);
- ckfree ((char*) eeFrame.line);
- eeFrame.line = NULL;
- eeFrame.nline = 0;
-#endif
+ eeFramePtr->line = NULL;
+ eeFramePtr->nline = 0;
if (code != TCL_OK) {
goto error;
@@ -4239,9 +4411,21 @@ EvalEx(interp, script, numBytes, flags, line, clNextOuter, outerScript)
Tcl_DecrRefCount(objv[i]);
}
objectsUsed = 0;
- if (objv != staticObjArray) {
- ckfree((char *) objv);
- objv = staticObjArray;
+ if (objvSpace != stackObjArray) {
+ ckfree((char *) objvSpace);
+ objvSpace = stackObjArray;
+ ckfree((char *) lineSpace);
+ lineSpace = linesStack;
+ }
+
+ /*
+ * Free expand separately since objvSpace could have been
+ * reallocated above.
+ */
+
+ if (expand != expandStack) {
+ ckfree((char *) expand);
+ expand = expandStack;
}
}
@@ -4252,214 +4436,91 @@ EvalEx(interp, script, numBytes, flags, line, clNextOuter, outerScript)
* executed command.
*/
- next = parse.commandStart + parse.commandSize;
+ next = parsePtr->commandStart + parsePtr->commandSize;
bytesLeft -= next - p;
p = next;
-#ifdef TCL_TIP280
- TclAdvanceLines (&line, parse.commandStart, p);
-#endif
- Tcl_FreeParse(&parse);
+ TclAdvanceLines(&line, parsePtr->commandStart, p);
+ Tcl_FreeParse(parsePtr);
gotParse = 0;
- if (nested && (*parse.term == ']')) {
- /*
- * We get here in the special case where the TCL_BRACKET_TERM
- * flag was set in the interpreter and the latest parsed command
- * was terminated by the matching close-bracket we seek.
- * Return immediately.
- */
-
- iPtr->termOffset = (p - 1) - script;
- iPtr->varFramePtr = savedVarFramePtr;
-#ifndef TCL_TIP280
- return TCL_OK;
-#else
- code = TCL_OK;
- goto cleanup_return;
-#endif
- }
} while (bytesLeft > 0);
-
- if (nested) {
- /*
- * This nested script did not terminate in ']', it is an error.
- */
-
- code = TCL_ERROR;
- goto error;
- }
-
- iPtr->termOffset = p - script;
iPtr->varFramePtr = savedVarFramePtr;
-#ifndef TCL_TIP280
- return TCL_OK;
-#else
code = TCL_OK;
goto cleanup_return;
-#endif
- error:
+ error:
/*
- * Generate various pieces of error information, such as the line
- * number where the error occurred and information to add to the
- * errorInfo variable. Then free resources that had been allocated
- * to the command.
+ * Generate and log various pieces of error information.
*/
if (iPtr->numLevels == 0) {
if (code == TCL_RETURN) {
code = TclUpdateReturnInfo(iPtr);
}
- if ((code != TCL_OK) && (code != TCL_ERROR)
- && !allowExceptions) {
+ if ((code != TCL_OK) && (code != TCL_ERROR) && !allowExceptions) {
ProcessUnexpectedResult(interp, code);
code = TCL_ERROR;
}
}
- if ((code == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
- commandLength = parse.commandSize;
- if (parse.term == parse.commandStart + commandLength - 1) {
+ if ((code == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
+ commandLength = parsePtr->commandSize;
+ if (parsePtr->term == parsePtr->commandStart + commandLength - 1) {
/*
* The terminator character (such as ; or ]) of the command where
* the error occurred is the last character in the parsed command.
* Reduce the length by one so that the error message doesn't
* include the terminator character.
*/
-
+
commandLength -= 1;
}
- Tcl_LogCommandInfo(interp, script, parse.commandStart, commandLength);
+ Tcl_LogCommandInfo(interp, script, parsePtr->commandStart,
+ commandLength);
}
-
+ iPtr->flags &= ~ERR_ALREADY_LOGGED;
+
+ /*
+ * Then free resources that had been allocated to the command.
+ */
+
for (i = 0; i < objectsUsed; i++) {
Tcl_DecrRefCount(objv[i]);
}
if (gotParse) {
- Tcl_FreeParse(&parse);
+ Tcl_FreeParse(parsePtr);
}
- if (objv != staticObjArray) {
- ckfree((char *) objv);
+ if (objvSpace != stackObjArray) {
+ ckfree((char *) objvSpace);
+ ckfree((char *) lineSpace);
}
- iPtr->varFramePtr = savedVarFramePtr;
-
- /*
- * All that's left to do before returning is to set iPtr->termOffset
- * to point past the end of the script we just evaluated.
- */
-
- next = parse.commandStart + parse.commandSize;
- bytesLeft -= next - p;
- p = next;
-
- if (!nested) {
- iPtr->termOffset = p - script;
-#ifndef TCL_TIP280
- return code;
-#else
- goto cleanup_return;
-#endif
+ if (expand != expandStack) {
+ ckfree((char *) expand);
}
+ iPtr->varFramePtr = savedVarFramePtr;
+ cleanup_return:
/*
- * When we are nested (the TCL_BRACKET_TERM flag was set in the
- * interpreter), we must find the matching close-bracket to
- * end the script we are evaluating.
- *
- * When our return code is TCL_CONTINUE or TCL_RETURN, we want
- * to correctly set iPtr->termOffset to point to that matching
- * close-bracket so our caller can move to the part of the
- * string beyond the script we were asked to evaluate.
- * So we try to parse past the rest of the commands.
+ * TIP #280. Release the local CmdFrame, and its contents.
*/
- next = NULL;
- while (bytesLeft && (*parse.term != ']')) {
- if (TCL_OK != Tcl_ParseCommand(NULL, p, bytesLeft, 1, &parse)) {
- /*
- * Syntax error. Set the termOffset to the beginning of
- * the last command parsed.
- */
-
- if (next == NULL) {
- iPtr->termOffset = (parse.commandStart - 1) - script;
- } else {
- iPtr->termOffset = (next - 1) - script;
- }
-#ifndef TCL_TIP280
- return code;
-#else
- goto cleanup_return;
-#endif
- }
- next = parse.commandStart + parse.commandSize;
- bytesLeft -= next - p;
- p = next;
- next = parse.commandStart;
- Tcl_FreeParse(&parse);
- }
-
- if (bytesLeft) {
- /*
- * parse.term points to the close-bracket.
- */
-
- iPtr->termOffset = parse.term - script;
- } else if (parse.term == script + numBytes) {
- /*
- * There was no close-bracket. Syntax error.
- */
-
- iPtr->termOffset = parse.term - script;
- Tcl_SetObjResult(interp,
- Tcl_NewStringObj("missing close-bracket", -1));
-#ifndef TCL_TIP280
- return TCL_ERROR;
-#else
- code = TCL_ERROR;
- goto cleanup_return;
-#endif
- } else if (*parse.term != ']') {
- /*
- * There was no close-bracket. Syntax error.
- */
-
- iPtr->termOffset = (parse.term + 1) - script;
- Tcl_SetObjResult(interp,
- Tcl_NewStringObj("missing close-bracket", -1));
-#ifndef TCL_TIP280
- return TCL_ERROR;
-#else
- code = TCL_ERROR;
- goto cleanup_return;
-#endif
- } else {
- /*
- * parse.term points to the close-bracket.
- */
- iPtr->termOffset = parse.term - script;
+ if (eeFramePtr->type == TCL_LOCATION_SOURCE) {
+ Tcl_DecrRefCount(eeFramePtr->data.eval.path);
}
+ TclStackFree(interp, linesStack);
+ TclStackFree(interp, expandStack);
+ TclStackFree(interp, stackObjArray);
+ TclStackFree(interp, eeFramePtr);
+ TclStackFree(interp, parsePtr);
-#ifdef TCL_TIP280
- cleanup_return:
- /* TIP #280. Release the local CmdFrame, and its contents. */
-
- if (eeFrame.line != NULL) {
- ckfree ((char*) eeFrame.line);
- }
- if (eeFrame.type == TCL_LOCATION_SOURCE) {
- Tcl_DecrRefCount (eeFrame.data.eval.path);
- }
-#endif
return code;
}
-#ifdef TCL_TIP280
/*
*----------------------------------------------------------------------
*
* TclAdvanceLines --
*
- * This procedure is a helper which counts the number of lines
- * in a block of text and advances an external counter.
+ * This function is a helper which counts the number of lines in a block
+ * of text and advances an external counter.
*
* Results:
* None.
@@ -4472,15 +4533,16 @@ EvalEx(interp, script, numBytes, flags, line, clNextOuter, outerScript)
*/
void
-TclAdvanceLines (line,start,end)
- int* line;
- CONST char* start;
- CONST char* end;
+TclAdvanceLines(
+ int *line,
+ const char *start,
+ const char *end)
{
- CONST char* p;
+ register const char *p;
+
for (p = start; p < end; p++) {
- if (*p == '\n') {
- (*line) ++;
+ if (*p == '\n') {
+ (*line)++;
}
}
}
@@ -4514,11 +4576,11 @@ TclAdvanceContinuations (line,clNextPtrPtr,loc)
/*
* Track the invisible continuation lines embedded in a script, if
* any. Here they are just spaces (already). They were removed by
- * EvalTokensStandard() via TclParseBackslash().
+ * TclSubstTokens() via TclParseBackslash().
*
- * *clNextPtrPtr <=> We have continuation lines to track.
- * **clNextPtrPtr >= 0 <=> We are not beyond the last possible location.
- * loc >= **clNextPtrPtr <=> We stepped beyond the current cont. line.
+ * *clNextPtrPtr <=> We have continuation lines to track.
+ * **clNextPtrPtr >= 0 <=> We are not beyond the last possible location.
+ * loc >= **clNextPtrPtr <=> We stepped beyond the current cont. line.
*/
while (*clNextPtrPtr && (**clNextPtrPtr >= 0) && (loc >= **clNextPtrPtr)) {
@@ -4657,7 +4719,7 @@ TclArgumentRelease(interp,objv,objc)
*
* This procedure is a helper for the TIP #280 uplevel extension.
* It enters location references for the literal arguments of commands
- * in bytecode about to be executed. Only the first entry has the actual
+ * in bytecode about to be invoked. Only the first entry has the actual
* data, further entries simply count the usage up.
*
* Results:
@@ -4671,7 +4733,7 @@ TclArgumentRelease(interp,objv,objc)
*/
void
-TclArgumentBCEnter(interp, objv, objc, codePtr, cfPtr, pc)
+TclArgumentBCEnter(interp,objv,objc,codePtr,cfPtr,pc)
Tcl_Interp* interp;
Tcl_Obj* objv[];
int objc;
@@ -4684,12 +4746,12 @@ TclArgumentBCEnter(interp, objv, objc, codePtr, cfPtr, pc)
if (hePtr) {
ExtCmdLoc* eclPtr = (ExtCmdLoc*) Tcl_GetHashValue (hePtr);
- hePtr = Tcl_FindHashEntry(&eclPtr->litInfo, (char*) pc);
+ hePtr = Tcl_FindHashEntry(&eclPtr->litInfo, INT2PTR(pc));
if (hePtr) {
- int word;
- int cmd = (int) Tcl_GetHashValue(hePtr);
+ int cmd = PTR2INT(Tcl_GetHashValue(hePtr));
ECL* ePtr = &eclPtr->loc[cmd];
+ int word;
/*
* A few truths ...
@@ -4701,6 +4763,10 @@ TclArgumentBCEnter(interp, objv, objc, codePtr, cfPtr, pc)
* have to save them at compile time.
*/
+ if (ePtr->nline != objc) {
+ Tcl_Panic ("TIP 280 data structure inconsistency");
+ }
+
for (word = 1; word < objc; word++) {
if (ePtr->line[word] >= 0) {
int isnew;
@@ -4757,7 +4823,7 @@ TclArgumentBCEnter(interp, objv, objc, codePtr, cfPtr, pc)
*/
void
-TclArgumentBCRelease(interp, objv, objc, codePtr, pc)
+TclArgumentBCRelease(interp,objv,objc,codePtr,pc)
Tcl_Interp* interp;
Tcl_Obj* objv[];
int objc;
@@ -4769,10 +4835,10 @@ TclArgumentBCRelease(interp, objv, objc, codePtr, pc)
if (hePtr) {
ExtCmdLoc* eclPtr = (ExtCmdLoc*) Tcl_GetHashValue (hePtr);
- hePtr = Tcl_FindHashEntry(&eclPtr->litInfo, (char*) pc);
+ hePtr = Tcl_FindHashEntry(&eclPtr->litInfo, INT2PTR(pc));
if (hePtr) {
- int cmd = (int) Tcl_GetHashValue(hePtr);
+ int cmd = PTR2INT(Tcl_GetHashValue(hePtr));
ECL* ePtr = &eclPtr->loc[cmd];
int word;
@@ -4786,7 +4852,7 @@ TclArgumentBCRelease(interp, objv, objc, codePtr, pc)
(char *) objv[word]);
if (hPtr) {
CFWordBC* cfwPtr = (CFWordBC*) Tcl_GetHashValue (hPtr);
-
+
if (cfwPtr->prevPtr) {
Tcl_SetHashValue(hPtr, cfwPtr->prevPtr);
} else {
@@ -4831,16 +4897,16 @@ TclArgumentGet(interp,obj,cfPtrPtr,wordPtr)
CmdFrame* framePtr;
/*
- * An object which either has no string rep guaranteed to have been
- * generated dynamically: bail out, this cannot have a usable absolute
- * location. _Do not touch_ the information the set up by the caller. It
- * knows better than us.
+ * An object which either has no string rep or else is a canonical list is
+ * guaranteed to have been generated dynamically: bail out, this cannot
+ * have a usable absolute location. _Do not touch_ the information the set
+ * up by the caller. It knows better than us.
*/
- if (!obj->bytes) {
+ if ((obj->bytes == NULL) || TclListObjIsCanonical(obj)) {
return;
}
-
+
/*
* First look for location information recorded in the argument
* stack. That is nearest.
@@ -4860,36 +4926,34 @@ TclArgumentGet(interp,obj,cfPtrPtr,wordPtr)
*/
hPtr = Tcl_FindHashEntry (iPtr->lineLABCPtr, (char *) obj);
+
if (hPtr) {
CFWordBC* cfwPtr = (CFWordBC*) Tcl_GetHashValue (hPtr);
framePtr = cfwPtr->framePtr;
- framePtr->data.tebc.pc = (char*) ((ByteCode*)
- framePtr->data.tebc.codePtr)->codeStart + cfwPtr->pc;
+ framePtr->data.tebc.pc = (char *) (((ByteCode*)
+ framePtr->data.tebc.codePtr)->codeStart + cfwPtr->pc);
*cfPtrPtr = cfwPtr->framePtr;
*wordPtr = cfwPtr->word;
return;
}
}
-#endif
/*
*----------------------------------------------------------------------
*
* Tcl_Eval --
*
- * Execute a Tcl command in a string. This procedure executes the
- * script directly, rather than compiling it to bytecodes. Before
- * the arrival of the bytecode compiler in Tcl 8.0 Tcl_Eval was
- * the main procedure used for executing Tcl commands, but nowadays
- * it isn't used much.
+ * Execute a Tcl command in a string. This function executes the script
+ * directly, rather than compiling it to bytecodes. Before the arrival of
+ * the bytecode compiler in Tcl 8.0 Tcl_Eval was the main function used
+ * for executing Tcl commands, but nowadays it isn't used much.
*
* Results:
- * The return value is one of the return codes defined in tcl.h
- * (such as TCL_OK), and interp's result contains a value
- * to supplement the return code. The value of the result
- * will persist only until the next call to Tcl_Eval or Tcl_EvalObj:
- * you must copy it or lose it!
+ * The return value is one of the return codes defined in tcl.h (such as
+ * TCL_OK), and interp's result contains a value to supplement the return
+ * code. The value of the result will persist only until the next call to
+ * Tcl_Eval or Tcl_EvalObj: you must copy it or lose it!
*
* Side effects:
* Can be almost arbitrary, depending on the commands in the script.
@@ -4898,21 +4962,20 @@ TclArgumentGet(interp,obj,cfPtrPtr,wordPtr)
*/
int
-Tcl_Eval(interp, string)
- Tcl_Interp *interp; /* Token for command interpreter (returned
- * by previous call to Tcl_CreateInterp). */
- CONST char *string; /* Pointer to TCL command to execute. */
+Tcl_Eval(
+ Tcl_Interp *interp, /* Token for command interpreter (returned by
+ * previous call to Tcl_CreateInterp). */
+ const char *script) /* Pointer to TCL command to execute. */
{
- int code = Tcl_EvalEx(interp, string, -1, 0);
+ int code = Tcl_EvalEx(interp, script, -1, 0);
/*
- * For backwards compatibility with old C code that predates the
- * object system in Tcl 8.0, we have to mirror the object result
- * back into the string result (some callers may expect it there).
+ * For backwards compatibility with old C code that predates the object
+ * system in Tcl 8.0, we have to mirror the object result back into the
+ * string result (some callers may expect it there).
*/
- Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
- TCL_VOLATILE);
+ (void) Tcl_GetStringResult(interp);
return code;
}
@@ -4935,18 +4998,18 @@ Tcl_Eval(interp, string)
#undef Tcl_EvalObj
int
-Tcl_EvalObj(interp, objPtr)
- Tcl_Interp * interp;
- Tcl_Obj * objPtr;
+Tcl_EvalObj(
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr)
{
return Tcl_EvalObjEx(interp, objPtr, 0);
}
#undef Tcl_GlobalEvalObj
int
-Tcl_GlobalEvalObj(interp, objPtr)
- Tcl_Interp * interp;
- Tcl_Obj * objPtr;
+Tcl_GlobalEvalObj(
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr)
{
return Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL);
}
@@ -4957,322 +5020,272 @@ Tcl_GlobalEvalObj(interp, objPtr)
* Tcl_EvalObjEx, TclEvalObjEx --
*
* Execute Tcl commands stored in a Tcl object. These commands are
- * compiled into bytecodes if necessary, unless TCL_EVAL_DIRECT
- * is specified.
+ * compiled into bytecodes if necessary, unless TCL_EVAL_DIRECT is
+ * specified.
*
* Results:
- * The return value is one of the return codes defined in tcl.h
- * (such as TCL_OK), and the interpreter's result contains a value
- * to supplement the return code.
+ * The return value is one of the return codes defined in tcl.h (such as
+ * TCL_OK), and the interpreter's result contains a value to supplement
+ * the return code.
*
* Side effects:
- * The object is converted, if necessary, to a ByteCode object that
- * holds the bytecode instructions for the commands. Executing the
- * commands will almost certainly have side effects that depend
- * on those commands.
- *
- * Just as in Tcl_Eval, interp->termOffset is set to the offset of the
- * last character executed in the objPtr's string.
+ * The object is converted, if necessary, to a ByteCode object that holds
+ * the bytecode instructions for the commands. Executing the commands
+ * will almost certainly have side effects that depend on those commands.
*
* TIP #280 : Keep public API, internally extended API.
*----------------------------------------------------------------------
*/
int
-Tcl_EvalObjEx(interp, objPtr, flags)
- Tcl_Interp *interp; /* Token for command interpreter
- * (returned by a previous call to
- * Tcl_CreateInterp). */
- register Tcl_Obj *objPtr; /* Pointer to object containing
- * commands to execute. */
- int flags; /* Collection of OR-ed bits that
- * control the evaluation of the
- * script. Supported values are
- * TCL_EVAL_GLOBAL and
- * TCL_EVAL_DIRECT. */
+Tcl_EvalObjEx(
+ Tcl_Interp *interp, /* Token for command interpreter (returned by
+ * a previous call to Tcl_CreateInterp). */
+ register Tcl_Obj *objPtr, /* Pointer to object containing commands to
+ * execute. */
+ int flags) /* Collection of OR-ed bits that control the
+ * evaluation of the script. Supported values
+ * are TCL_EVAL_GLOBAL and TCL_EVAL_DIRECT. */
{
-#ifdef TCL_TIP280
- return TclEvalObjEx (interp, objPtr, flags, NULL, 0);
+ return TclEvalObjEx(interp, objPtr, flags, NULL, 0);
}
int
-TclEvalObjEx(interp, objPtr, flags, invoker, word)
- Tcl_Interp *interp; /* Token for command interpreter
- * (returned by a previous call to
- * Tcl_CreateInterp). */
- register Tcl_Obj *objPtr; /* Pointer to object containing
- * commands to execute. */
- int flags; /* Collection of OR-ed bits that
- * control the evaluation of the
- * script. Supported values are
- * TCL_EVAL_GLOBAL and
- * TCL_EVAL_DIRECT. */
- CONST CmdFrame* invoker; /* Frame of the command doing the eval */
- int word; /* Index of the word which is in objPtr */
+TclEvalObjEx(
+ Tcl_Interp *interp, /* Token for command interpreter (returned by
+ * a previous call to Tcl_CreateInterp). */
+ register Tcl_Obj *objPtr, /* Pointer to object containing commands to
+ * execute. */
+ int flags, /* Collection of OR-ed bits that control the
+ * evaluation of the script. Supported values
+ * are TCL_EVAL_GLOBAL and TCL_EVAL_DIRECT. */
+ const CmdFrame *invoker, /* Frame of the command doing the eval. */
+ int word) /* Index of the word which is in objPtr. */
{
-#endif
register Interp *iPtr = (Interp *) interp;
char *script;
int numSrcBytes;
int result;
- CallFrame *savedVarFramePtr; /* Saves old copy of iPtr->varFramePtr
- * in case TCL_EVAL_GLOBAL was set. */
- int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS);
+ CallFrame *savedVarFramePtr;/* Saves old copy of iPtr->varFramePtr in case
+ * TCL_EVAL_GLOBAL was set. */
Tcl_IncrRefCount(objPtr);
- if ((iPtr->flags & USE_EVAL_DIRECT) || (flags & TCL_EVAL_DIRECT)) {
+ /* Pure List Optimization (no string representation). In this case, we can
+ * safely use Tcl_EvalObjv instead and get an appreciable improvement in
+ * execution speed. This is because it allows us to avoid a setFromAny
+ * step that would just pack everything into a string and back out again.
+ *
+ * This also preserves any associations between list elements and location
+ * information for such elements.
+ *
+ * This restriction has been relaxed a bit by storing in lists whether
+ * they are "canonical" or not (a canonical list being one that is either
+ * pure or that has its string rep derived by UpdateStringOfList from the
+ * internal rep).
+ */
+
+ if (TclListObjIsCanonical(objPtr)) {
+ /*
+ * TIP #280 Structures for tracking lines. As we know that this is
+ * dynamic execution we ignore the invoker, even if known.
+ */
+
+ int nelements;
+ Tcl_Obj **elements, *copyPtr = TclListObjCopy(NULL, objPtr);
+ CmdFrame *eoFramePtr = (CmdFrame *)
+ TclStackAlloc(interp, sizeof(CmdFrame));
+
+ eoFramePtr->type = TCL_LOCATION_EVAL_LIST;
+ eoFramePtr->level = (iPtr->cmdFramePtr == NULL? 1
+ : iPtr->cmdFramePtr->level + 1);
+ eoFramePtr->framePtr = iPtr->framePtr;
+ eoFramePtr->nextPtr = iPtr->cmdFramePtr;
+
+ eoFramePtr->nline = 0;
+ eoFramePtr->line = NULL;
+
+ eoFramePtr->cmd.listPtr = objPtr;
+ Tcl_IncrRefCount(eoFramePtr->cmd.listPtr);
+ eoFramePtr->data.eval.path = NULL;
+
+ /*
+ * TIP #280 We do _not_ compute all the line numbers for the words
+ * in the command. For the eval of a pure list the most sensible
+ * choice is to put all words on line 1. Given that we neither
+ * need memory for them nor compute anything. 'line' is left
+ * NULL. The two places using this information (TclInfoFrame, and
+ * TclInitCompileEnv), are special-cased to use the proper line
+ * number directly instead of accessing the 'line' array.
+ */
+
+ Tcl_ListObjGetElements(NULL, copyPtr, &nelements, &elements);
+
+ iPtr->cmdFramePtr = eoFramePtr;
+ result = Tcl_EvalObjv(interp, nelements, elements, flags);
+
+ Tcl_DecrRefCount(copyPtr);
+ iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr;
+ Tcl_DecrRefCount(eoFramePtr->cmd.listPtr);
+ TclStackFree(interp, eoFramePtr);
+ } else if (flags & TCL_EVAL_DIRECT) {
/*
* We're not supposed to use the compiler or byte-code interpreter.
- * Let Tcl_EvalEx evaluate the command directly (and probably
- * more slowly).
+ * Let Tcl_EvalEx evaluate the command directly (and probably more
+ * slowly).
+ */
+
+ /*
+ * TIP #280. Propagate context as much as we can. Especially if the
+ * script to evaluate is a single literal it makes sense to look if
+ * our context is one with absolute line numbers we can then track
+ * into the literal itself too.
*
- * Pure List Optimization (no string representation). In this
- * case, we can safely use Tcl_EvalObjv instead and get an
- * appreciable improvement in execution speed. This is because it
- * allows us to avoid a setFromAny step that would just pack
- * everything into a string and back out again.
+ * See also tclCompile.c, TclInitCompileEnv, for the equivalent code
+ * in the bytecode compiler.
+ */
+
+ /*
+ * Now we check if we have data about invisible continuation lines for
+ * the script, and make it available to the direct script parser and
+ * evaluator we are about to call, if so.
*
- * USE_EVAL_DIRECT is a special flag used for testing purpose only
- * (ensure we go into the TCL_EVAL_DIRECT path, avoiding opt)
+ * It may be possible that the script Tcl_Obj* can be free'd while the
+ * evaluator is using it, leading to the release of the associated
+ * ContLineLoc structure as well. To ensure that the latter doesn't
+ * happen we set a lock on it. We release this lock later in this
+ * function, after the evaluator is done. The relevant "lineCLPtr"
+ * hashtable is managed in the file "tclObj.c".
+ *
+ * Another important action is to save (and later restore) the
+ * continuation line information of the caller, in case we are
+ * executing nested commands in the eval/direct path.
*/
- if (!(iPtr->flags & USE_EVAL_DIRECT) &&
- (objPtr->typePtr == &tclListType) && /* is a list... */
- (objPtr->bytes == NULL) /* ...without a string rep */) {
- register List *listRepPtr =
- (List *) objPtr->internalRep.twoPtrValue.ptr1;
- int i, objc = listRepPtr->elemCount;
-
-#define TEOE_PREALLOC 10
- Tcl_Obj *staticObjv[TEOE_PREALLOC], **objv = staticObjv;
-
-#ifdef TCL_TIP280
- /* TIP #280 Structures for tracking lines.
- * As we know that this is dynamic execution we ignore the
- * invoker, even if known.
- */
- CmdFrame eoFrame;
-
- eoFrame.type = TCL_LOCATION_EVAL_LIST;
- eoFrame.level = (iPtr->cmdFramePtr == NULL ?
- 1 :
- iPtr->cmdFramePtr->level + 1);
- eoFrame.framePtr = iPtr->framePtr;
- eoFrame.nextPtr = iPtr->cmdFramePtr;
- eoFrame.nline = 0;
- eoFrame.line = NULL;
-
- /* NOTE: Getting the string rep of the list to eval to fill the
- * command information required by 'info frame' implies that
- * further calls for the same list would not be optimized, as it
- * would not be 'pure' anymore. It would also be a waste of time
- * as most of the time this information is not needed at all. What
- * we do instead is to keep the list obj itself around and have
- * 'info frame' sort it out.
- */
- eoFrame.cmd.listPtr = objPtr;
- Tcl_IncrRefCount (eoFrame.cmd.listPtr);
- eoFrame.data.eval.path = NULL;
-#endif
- if (objc > TEOE_PREALLOC) {
- objv = (Tcl_Obj **) ckalloc(objc*sizeof(Tcl_Obj *));
- }
-#undef TEOE_PREALLOC
- /*
- * Copy the list elements here, to avoid a segfault if
- * objPtr loses its List internal rep [Bug 1119369].
- *
- * TIP #280 We do _not_ compute all the line numbers for the words
- * in the command. For the eval of a pure list the most sensible
- * choice is to put all words on line 1. Given that we neither
- * need memory for them nor compute anything. 'line' is left
- * NULL. The two places using this information (TclInfoFrame, and
- * TclInitCompileEnv), are special-cased to use the proper line
- * number directly instead of accessing the 'line' array.
- */
+ ContLineLoc* saveCLLocPtr = iPtr->scriptCLLocPtr;
+ ContLineLoc* clLocPtr = TclContinuationsGet (objPtr);
- for (i=0; i < objc; i++) {
- objv[i] = listRepPtr->elements[i];
- Tcl_IncrRefCount(objv[i]);
- }
+ if (clLocPtr) {
+ iPtr->scriptCLLocPtr = clLocPtr;
+ Tcl_Preserve (iPtr->scriptCLLocPtr);
+ } else {
+ iPtr->scriptCLLocPtr = NULL;
+ }
-#ifdef TCL_TIP280
- iPtr->cmdFramePtr = &eoFrame;
-#endif
- result = Tcl_EvalObjv(interp, objc, objv, flags);
-#ifdef TCL_TIP280
- iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr;
- Tcl_DecrRefCount (eoFrame.cmd.listPtr);
-#endif
+ if (invoker == NULL) {
+ /*
+ * No context, force opening of our own.
+ */
- for (i=0; i < objc; i++) {
- TclDecrRefCount(objv[i]);
- }
- if (objv != staticObjv) {
- ckfree((char *) objv);
- }
-#ifdef TCL_TIP280
- ckfree ((char*) eoFrame.line);
- eoFrame.line = NULL;
- eoFrame.nline = 0;
-#endif
- } else {
-#ifndef TCL_TIP280
script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
result = Tcl_EvalEx(interp, script, numSrcBytes, flags);
-#else
+ } else {
/*
- * TIP #280. Propagate context as much as we can. Especially if
- * the script to evaluate is a single literal it makes sense to
- * look if our context is one with absolute line numbers we can
- * then track into the literal itself too.
+ * We have an invoker, describing the command asking for the
+ * evaluation of a subordinate script. This script may originate
+ * in a literal word, or from a variable, etc. Using the line
+ * array we now check if we have good line information for the
+ * relevant word. The type of context is relevant as well. In a
+ * non-'source' context we don't have to try tracking lines.
*
- * See also tclCompile.c, TclInitCompileEnv, for the equivalent
- * code in the bytecode compiler.
+ * First see if the word exists and is a literal. If not we go
+ * through the easy dynamic branch. No need to perform more
+ * complex invokations.
*/
- /*
- * Now we check if we have data about invisible continuation lines
- * for the script, and make it available to the direct script
- * parser and evaluator we are about to call, if so.
- *
- * It may be possible that the script Tcl_Obj* can be free'd while
- * the evaluator is using it, leading to the release of the
- * associated ContLineLoc structure as well. To ensure that the
- * latter doesn't happen we set a lock on it. We release this lock
- * later in this function, after the evaluator is done. The
- * relevant "lineCLPtr" hashtable is managed in the file
- * "tclObj.c".
- *
- * Another important action is to save (and later restore) the
- * continuation line information of the caller, in case we are
- * executing nested commands in the eval/direct path.
- */
+ int pc = 0;
+ CmdFrame *ctxPtr = (CmdFrame *)
+ TclStackAlloc(interp, sizeof(CmdFrame));
- ContLineLoc* saveCLLocPtr = iPtr->scriptCLLocPtr;
- ContLineLoc* clLocPtr = TclContinuationsGet (objPtr);
+ *ctxPtr = *invoker;
+ if (invoker->type == TCL_LOCATION_BC) {
+ /*
+ * Note: Type BC => ctxPtr->data.eval.path is not used.
+ * ctxPtr->data.tebc.codePtr is used instead.
+ */
- if (clLocPtr) {
- iPtr->scriptCLLocPtr = clLocPtr;
- Tcl_Preserve (iPtr->scriptCLLocPtr);
- } else {
- iPtr->scriptCLLocPtr = NULL;
+ TclGetSrcInfoForPc(ctxPtr);
+ pc = 1;
}
- if (invoker == NULL) {
- /* No context, force opening of our own */
- script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
- result = Tcl_EvalEx(interp, script, numSrcBytes, flags);
- } else {
- /* We have an invoker, describing the command asking for the
- * evaluation of a subordinate script. This script may
- * originate in a literal word, or from a variable, etc. Using
- * the line array we now check if we have good line
- * information for the relevant word. The type of context is
- * relevant as well. In a non-'source' context we don't have
- * to try tracking lines.
- *
- * First see if the word exists and is a literal. If not we go
- * through the easy dynamic branch. No need to perform more
- * complex invokations.
- */
+ script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
- CmdFrame ctx = *invoker;
- int pc = 0;
+ if ((ctxPtr->nline <= word) ||
+ (ctxPtr->line[word] < 0) ||
+ (ctxPtr->type != TCL_LOCATION_SOURCE)) {
+ /*
+ * Dynamic script, or dynamic context, force our own
+ * context.
+ */
- if (invoker->type == TCL_LOCATION_BC) {
- /* Note: Type BC => ctx.data.eval.path is not used.
- * ctx.data.tebc.codePtr is used instead.
- */
- TclGetSrcInfoForPc (&ctx);
- pc = 1;
- }
+ result = Tcl_EvalEx(interp, script, numSrcBytes, flags);
- script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
+ } else {
+ /*
+ * Absolute context to reuse.
+ */
- if ((ctx.nline <= word) ||
- (ctx.line[word] < 0) ||
- (ctx.type != TCL_LOCATION_SOURCE)) {
- /* Dynamic script, or dynamic context, force our own
- * context */
+ iPtr->invokeCmdFramePtr = ctxPtr;
+ iPtr->evalFlags |= TCL_EVAL_CTX;
- result = Tcl_EvalEx(interp, script, numSrcBytes, flags);
- } else {
- /* Absolute context available to reuse. */
+ result = TclEvalEx(interp, script, numSrcBytes, flags,
+ ctxPtr->line[word], NULL, script);
+ }
- iPtr->invokeCmdFramePtr = &ctx;
- iPtr->evalFlags |= TCL_EVAL_CTX;
+ if (pc && (ctxPtr->type == TCL_LOCATION_SOURCE)) {
+ /*
+ * Death of SrcInfo reference.
+ */
- result = EvalEx(interp, script, numSrcBytes, flags,
- ctx.line [word], NULL, script);
- }
- if (pc && (ctx.type == TCL_LOCATION_SOURCE)) {
- /* Death of SrcInfo reference. */
- Tcl_DecrRefCount(ctx.data.eval.path);
- }
+ Tcl_DecrRefCount(ctxPtr->data.eval.path);
}
+ TclStackFree(interp, ctxPtr);
+ }
- /*
- * Now release the lock on the continuation line information, if
- * any, and restore the caller's settings.
- */
+ /*
+ * Now release the lock on the continuation line information, if
+ * any, and restore the caller's settings.
+ */
- if (iPtr->scriptCLLocPtr) {
- Tcl_Release (iPtr->scriptCLLocPtr);
- }
- iPtr->scriptCLLocPtr = saveCLLocPtr;
-#endif
+ if (iPtr->scriptCLLocPtr) {
+ Tcl_Release (iPtr->scriptCLLocPtr);
}
+ iPtr->scriptCLLocPtr = saveCLLocPtr;
} else {
/*
* Let the compiler/engine subsystem do the evaluation.
*
- * TIP #280 The invoker provides us with the context for the
- * script. We transfer this to the byte code compiler.
+ * TIP #280 The invoker provides us with the context for the script.
+ * We transfer this to the byte code compiler.
*/
+ int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS);
savedVarFramePtr = iPtr->varFramePtr;
if (flags & TCL_EVAL_GLOBAL) {
- iPtr->varFramePtr = NULL;
+ iPtr->varFramePtr = iPtr->rootFramePtr;
}
-#ifndef TCL_TIP280
- result = TclCompEvalObj(interp, objPtr);
-#else
result = TclCompEvalObj(interp, objPtr, invoker, word);
-#endif
/*
- * If we are again at the top level, process any unusual
- * return code returned by the evaluated code.
+ * If we are again at the top level, process any unusual return code
+ * returned by the evaluated code.
*/
-
+
if (iPtr->numLevels == 0) {
if (result == TCL_RETURN) {
result = TclUpdateReturnInfo(iPtr);
}
- if ((result != TCL_OK) && (result != TCL_ERROR)
- && !allowExceptions) {
+ if ((result != TCL_OK) && (result != TCL_ERROR)
+ && !allowExceptions) {
ProcessUnexpectedResult(interp, result);
result = TCL_ERROR;
-
- /*
- * If an error was created here, record information about
- * what was being executed when the error occurred. Remove
- * the extra \n added by tclMain.c in the command sent to
- * Tcl_LogCommandInfo [Bug 833150].
- */
-
- if (!(iPtr->flags & ERR_ALREADY_LOGGED)) {
- script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
- Tcl_LogCommandInfo(interp, script, script, --numSrcBytes);
- iPtr->flags &= ~ERR_ALREADY_LOGGED;
- }
+ script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
+ Tcl_LogCommandInfo(interp, script, script, numSrcBytes);
}
}
iPtr->evalFlags = 0;
- iPtr->varFramePtr = savedVarFramePtr;
+ iPtr->varFramePtr = savedVarFramePtr;
}
TclDecrRefCount(objPtr);
@@ -5284,39 +5297,37 @@ TclEvalObjEx(interp, objPtr, flags, invoker, word)
*
* ProcessUnexpectedResult --
*
- * Procedure called by Tcl_EvalObj to set the interpreter's result
- * value to an appropriate error message when the code it evaluates
- * returns an unexpected result code (not TCL_OK and not TCL_ERROR) to
- * the topmost evaluation level.
+ * Function called by Tcl_EvalObj to set the interpreter's result value
+ * to an appropriate error message when the code it evaluates returns an
+ * unexpected result code (not TCL_OK and not TCL_ERROR) to the topmost
+ * evaluation level.
*
* Results:
* None.
*
* Side effects:
- * The interpreter result is set to an error message appropriate to
- * the result code.
+ * The interpreter result is set to an error message appropriate to the
+ * result code.
*
*----------------------------------------------------------------------
*/
static void
-ProcessUnexpectedResult(interp, returnCode)
- Tcl_Interp *interp; /* The interpreter in which the unexpected
+ProcessUnexpectedResult(
+ Tcl_Interp *interp, /* The interpreter in which the unexpected
* result code was returned. */
- int returnCode; /* The unexpected result code. */
+ int returnCode) /* The unexpected result code. */
{
Tcl_ResetResult(interp);
if (returnCode == TCL_BREAK) {
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "invoked \"break\" outside of a loop", -1);
+ Tcl_AppendResult(interp,
+ "invoked \"break\" outside of a loop", NULL);
} else if (returnCode == TCL_CONTINUE) {
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "invoked \"continue\" outside of a loop", -1);
+ Tcl_AppendResult(interp,
+ "invoked \"continue\" outside of a loop", NULL);
} else {
- char buf[30 + TCL_INTEGER_SPACE];
-
- sprintf(buf, "command returned bad code: %d", returnCode);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "command returned bad code: %d", returnCode));
}
}
@@ -5325,15 +5336,15 @@ ProcessUnexpectedResult(interp, returnCode)
*
* Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean --
*
- * Procedures to evaluate an expression and return its value in a
+ * Functions to evaluate an expression and return its value in a
* particular form.
*
* Results:
- * Each of the procedures below returns a standard Tcl result. If an
- * error occurs then an error message is left in the interp's result.
- * Otherwise the value of the expression, in the appropriate form,
- * is stored at *ptr. If the expression had a result that was
- * incompatible with the desired form then an error is returned.
+ * Each of the functions below returns a standard Tcl result. If an error
+ * occurs then an error message is left in the interp's result. Otherwise
+ * the value of the expression, in the appropriate form, is stored at
+ * *ptr. If the expression had a result that was incompatible with the
+ * desired form then an error is returned.
*
* Side effects:
* None.
@@ -5342,197 +5353,92 @@ ProcessUnexpectedResult(interp, returnCode)
*/
int
-Tcl_ExprLong(interp, string, ptr)
- Tcl_Interp *interp; /* Context in which to evaluate the
+Tcl_ExprLong(
+ Tcl_Interp *interp, /* Context in which to evaluate the
* expression. */
- CONST char *string; /* Expression to evaluate. */
- long *ptr; /* Where to store result. */
+ const char *exprstring, /* Expression to evaluate. */
+ long *ptr) /* Where to store result. */
{
register Tcl_Obj *exprPtr;
- Tcl_Obj *resultPtr;
- int length = strlen(string);
int result = TCL_OK;
-
- if (length > 0) {
- exprPtr = Tcl_NewStringObj(string, length);
- Tcl_IncrRefCount(exprPtr);
- result = Tcl_ExprObj(interp, exprPtr, &resultPtr);
- if (result == TCL_OK) {
- /*
- * Store an integer based on the expression result.
- */
-
- if (resultPtr->typePtr == &tclIntType) {
- *ptr = resultPtr->internalRep.longValue;
- } else if (resultPtr->typePtr == &tclDoubleType) {
- *ptr = (long) resultPtr->internalRep.doubleValue;
- } else if (resultPtr->typePtr == &tclWideIntType) {
-#ifndef TCL_WIDE_INT_IS_LONG
- /*
- * See Tcl_GetIntFromObj for conversion comments.
- */
- Tcl_WideInt w = resultPtr->internalRep.wideValue;
- if ((w >= -(Tcl_WideInt)(ULONG_MAX))
- && (w <= (Tcl_WideInt)(ULONG_MAX))) {
- *ptr = Tcl_WideAsLong(w);
- } else {
- Tcl_SetResult(interp,
- "integer value too large to represent as non-long integer",
- TCL_STATIC);
- result = TCL_ERROR;
- }
-#else
- *ptr = resultPtr->internalRep.longValue;
-#endif
- } else {
- Tcl_SetResult(interp,
- "expression didn't have numeric value", TCL_STATIC);
- result = TCL_ERROR;
- }
- Tcl_DecrRefCount(resultPtr); /* discard the result object */
- } else {
- /*
- * Move the interpreter's object result to the string result,
- * then reset the object result.
- */
-
- Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
- TCL_VOLATILE);
- }
- Tcl_DecrRefCount(exprPtr); /* discard the expression object */
- } else {
+ if (*exprstring == '\0') {
/*
- * An empty string. Just set the result integer to 0.
+ * Legacy compatibility - return 0 for the zero-length string.
*/
-
+
*ptr = 0;
+ } else {
+ exprPtr = Tcl_NewStringObj(exprstring, -1);
+ Tcl_IncrRefCount(exprPtr);
+ result = Tcl_ExprLongObj(interp, exprPtr, ptr);
+ Tcl_DecrRefCount(exprPtr);
+ if (result != TCL_OK) {
+ (void) Tcl_GetStringResult(interp);
+ }
}
return result;
}
int
-Tcl_ExprDouble(interp, string, ptr)
- Tcl_Interp *interp; /* Context in which to evaluate the
+Tcl_ExprDouble(
+ Tcl_Interp *interp, /* Context in which to evaluate the
* expression. */
- CONST char *string; /* Expression to evaluate. */
- double *ptr; /* Where to store result. */
+ const char *exprstring, /* Expression to evaluate. */
+ double *ptr) /* Where to store result. */
{
register Tcl_Obj *exprPtr;
- Tcl_Obj *resultPtr;
- int length = strlen(string);
int result = TCL_OK;
- if (length > 0) {
- exprPtr = Tcl_NewStringObj(string, length);
- Tcl_IncrRefCount(exprPtr);
- result = Tcl_ExprObj(interp, exprPtr, &resultPtr);
- if (result == TCL_OK) {
- /*
- * Store a double based on the expression result.
- */
-
- if (resultPtr->typePtr == &tclIntType) {
- *ptr = (double) resultPtr->internalRep.longValue;
- } else if (resultPtr->typePtr == &tclDoubleType) {
- *ptr = resultPtr->internalRep.doubleValue;
- } else if (resultPtr->typePtr == &tclWideIntType) {
-#ifndef TCL_WIDE_INT_IS_LONG
- /*
- * See Tcl_GetIntFromObj for conversion comments.
- */
- Tcl_WideInt w = resultPtr->internalRep.wideValue;
- if ((w >= -(Tcl_WideInt)(ULONG_MAX))
- && (w <= (Tcl_WideInt)(ULONG_MAX))) {
- *ptr = (double) Tcl_WideAsLong(w);
- } else {
- Tcl_SetResult(interp,
- "integer value too large to represent as non-long integer",
- TCL_STATIC);
- result = TCL_ERROR;
- }
-#else
- *ptr = (double) resultPtr->internalRep.longValue;
-#endif
- } else {
- Tcl_SetResult(interp,
- "expression didn't have numeric value", TCL_STATIC);
- result = TCL_ERROR;
- }
- Tcl_DecrRefCount(resultPtr); /* discard the result object */
- } else {
- /*
- * Move the interpreter's object result to the string result,
- * then reset the object result.
- */
-
- Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
- TCL_VOLATILE);
- }
- Tcl_DecrRefCount(exprPtr); /* discard the expression object */
- } else {
+ if (*exprstring == '\0') {
/*
- * An empty string. Just set the result double to 0.0.
+ * Legacy compatibility - return 0 for the zero-length string.
*/
-
+
*ptr = 0.0;
+ } else {
+ exprPtr = Tcl_NewStringObj(exprstring, -1);
+ Tcl_IncrRefCount(exprPtr);
+ result = Tcl_ExprDoubleObj(interp, exprPtr, ptr);
+ Tcl_DecrRefCount(exprPtr);
+ /* Discard the expression object. */
+ if (result != TCL_OK) {
+ (void) Tcl_GetStringResult(interp);
+ }
}
return result;
}
int
-Tcl_ExprBoolean(interp, string, ptr)
- Tcl_Interp *interp; /* Context in which to evaluate the
- * expression. */
- CONST char *string; /* Expression to evaluate. */
- int *ptr; /* Where to store 0/1 result. */
+Tcl_ExprBoolean(
+ Tcl_Interp *interp, /* Context in which to evaluate the
+ * expression. */
+ const char *exprstring, /* Expression to evaluate. */
+ int *ptr) /* Where to store 0/1 result. */
{
- register Tcl_Obj *exprPtr;
- Tcl_Obj *resultPtr;
- int length = strlen(string);
- int result = TCL_OK;
+ if (*exprstring == '\0') {
+ /*
+ * An empty string. Just set the result boolean to 0 (false).
+ */
- if (length > 0) {
- exprPtr = Tcl_NewStringObj(string, length);
- Tcl_IncrRefCount(exprPtr);
- result = Tcl_ExprObj(interp, exprPtr, &resultPtr);
- if (result == TCL_OK) {
- /*
- * Store a boolean based on the expression result.
- */
+ *ptr = 0;
+ return TCL_OK;
+ } else {
+ int result;
+ Tcl_Obj *exprPtr = Tcl_NewStringObj(exprstring, -1);
- if (resultPtr->typePtr == &tclIntType) {
- *ptr = (resultPtr->internalRep.longValue != 0);
- } else if (resultPtr->typePtr == &tclDoubleType) {
- *ptr = (resultPtr->internalRep.doubleValue != 0.0);
- } else if (resultPtr->typePtr == &tclWideIntType) {
-#ifndef TCL_WIDE_INT_IS_LONG
- *ptr = (resultPtr->internalRep.wideValue != 0);
-#else
- *ptr = (resultPtr->internalRep.longValue != 0);
-#endif
- } else {
- result = Tcl_GetBooleanFromObj(interp, resultPtr, ptr);
- }
- Tcl_DecrRefCount(resultPtr); /* discard the result object */
- }
+ Tcl_IncrRefCount(exprPtr);
+ result = Tcl_ExprBooleanObj(interp, exprPtr, ptr);
+ Tcl_DecrRefCount(exprPtr);
if (result != TCL_OK) {
/*
- * Move the interpreter's object result to the string result,
- * then reset the object result.
+ * Move the interpreter's object result to the string result, then
+ * reset the object result.
*/
- Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
- TCL_VOLATILE);
+ (void) Tcl_GetStringResult(interp);
}
- Tcl_DecrRefCount(exprPtr); /* discard the expression object */
- } else {
- /*
- * An empty string. Just set the result boolean to 0 (false).
- */
-
- *ptr = 0;
+ return result;
}
- return result;
}
/*
@@ -5540,16 +5446,15 @@ Tcl_ExprBoolean(interp, string, ptr)
*
* Tcl_ExprLongObj, Tcl_ExprDoubleObj, Tcl_ExprBooleanObj --
*
- * Procedures to evaluate an expression in an object and return its
- * value in a particular form.
+ * Functions to evaluate an expression in an object and return its value
+ * in a particular form.
*
* Results:
- * Each of the procedures below returns a standard Tcl result
- * object. If an error occurs then an error message is left in the
- * interpreter's result. Otherwise the value of the expression, in the
- * appropriate form, is stored at *ptr. If the expression had a result
- * that was incompatible with the desired form then an error is
- * returned.
+ * Each of the functions below returns a standard Tcl result object. If
+ * an error occurs then an error message is left in the interpreter's
+ * result. Otherwise the value of the expression, in the appropriate
+ * form, is stored at *ptr. If the expression had a result that was
+ * incompatible with the desired form then an error is returned.
*
* Side effects:
* None.
@@ -5558,230 +5463,117 @@ Tcl_ExprBoolean(interp, string, ptr)
*/
int
-Tcl_ExprLongObj(interp, objPtr, ptr)
- Tcl_Interp *interp; /* Context in which to evaluate the
- * expression. */
- register Tcl_Obj *objPtr; /* Expression to evaluate. */
- long *ptr; /* Where to store long result. */
+Tcl_ExprLongObj(
+ Tcl_Interp *interp, /* Context in which to evaluate the
+ * expression. */
+ register Tcl_Obj *objPtr, /* Expression to evaluate. */
+ long *ptr) /* Where to store long result. */
{
Tcl_Obj *resultPtr;
- int result;
+ int result, type;
+ double d;
+ ClientData internalPtr;
result = Tcl_ExprObj(interp, objPtr, &resultPtr);
- if (result == TCL_OK) {
- if (resultPtr->typePtr == &tclIntType) {
- *ptr = resultPtr->internalRep.longValue;
- } else if (resultPtr->typePtr == &tclDoubleType) {
- *ptr = (long) resultPtr->internalRep.doubleValue;
- } else {
- result = Tcl_GetLongFromObj(interp, resultPtr, ptr);
- if (result != TCL_OK) {
- return result;
- }
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (TclGetNumberFromObj(interp, resultPtr, &internalPtr, &type) != TCL_OK){
+ return TCL_ERROR;
+ }
+
+ switch (type) {
+ case TCL_NUMBER_DOUBLE: {
+ mp_int big;
+
+ d = *((const double *) internalPtr);
+ Tcl_DecrRefCount(resultPtr);
+ if (Tcl_InitBignumFromDouble(interp, d, &big) != TCL_OK) {
+ return TCL_ERROR;
}
- Tcl_DecrRefCount(resultPtr); /* discard the result object */
+ resultPtr = Tcl_NewBignumObj(&big);
+ /* FALLTHROUGH */
}
+ case TCL_NUMBER_LONG:
+ case TCL_NUMBER_WIDE:
+ case TCL_NUMBER_BIG:
+ result = TclGetLongFromObj(interp, resultPtr, ptr);
+ break;
+
+ case TCL_NUMBER_NAN:
+ Tcl_GetDoubleFromObj(interp, resultPtr, &d);
+ result = TCL_ERROR;
+ }
+
+ Tcl_DecrRefCount(resultPtr);/* Discard the result object. */
return result;
}
int
-Tcl_ExprDoubleObj(interp, objPtr, ptr)
- Tcl_Interp *interp; /* Context in which to evaluate the
- * expression. */
- register Tcl_Obj *objPtr; /* Expression to evaluate. */
- double *ptr; /* Where to store double result. */
+Tcl_ExprDoubleObj(
+ Tcl_Interp *interp, /* Context in which to evaluate the
+ * expression. */
+ register Tcl_Obj *objPtr, /* Expression to evaluate. */
+ double *ptr) /* Where to store double result. */
{
Tcl_Obj *resultPtr;
- int result;
+ int result, type;
+ ClientData internalPtr;
result = Tcl_ExprObj(interp, objPtr, &resultPtr);
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ result = TclGetNumberFromObj(interp, resultPtr, &internalPtr, &type);
if (result == TCL_OK) {
- if (resultPtr->typePtr == &tclIntType) {
- *ptr = (double) resultPtr->internalRep.longValue;
- } else if (resultPtr->typePtr == &tclDoubleType) {
- *ptr = resultPtr->internalRep.doubleValue;
- } else {
+ switch (type) {
+ case TCL_NUMBER_NAN:
+#ifndef ACCEPT_NAN
+ result = Tcl_GetDoubleFromObj(interp, resultPtr, ptr);
+ break;
+#endif
+ case TCL_NUMBER_DOUBLE:
+ *ptr = *((const double *) internalPtr);
+ result = TCL_OK;
+ break;
+ default:
result = Tcl_GetDoubleFromObj(interp, resultPtr, ptr);
- if (result != TCL_OK) {
- return result;
- }
}
- Tcl_DecrRefCount(resultPtr); /* discard the result object */
}
+ Tcl_DecrRefCount(resultPtr);/* Discard the result object. */
return result;
}
int
-Tcl_ExprBooleanObj(interp, objPtr, ptr)
- Tcl_Interp *interp; /* Context in which to evaluate the
- * expression. */
- register Tcl_Obj *objPtr; /* Expression to evaluate. */
- int *ptr; /* Where to store 0/1 result. */
+Tcl_ExprBooleanObj(
+ Tcl_Interp *interp, /* Context in which to evaluate the
+ * expression. */
+ register Tcl_Obj *objPtr, /* Expression to evaluate. */
+ int *ptr) /* Where to store 0/1 result. */
{
Tcl_Obj *resultPtr;
int result;
result = Tcl_ExprObj(interp, objPtr, &resultPtr);
if (result == TCL_OK) {
- if (resultPtr->typePtr == &tclIntType) {
- *ptr = (resultPtr->internalRep.longValue != 0);
- } else if (resultPtr->typePtr == &tclDoubleType) {
- *ptr = (resultPtr->internalRep.doubleValue != 0.0);
- } else {
- result = Tcl_GetBooleanFromObj(interp, resultPtr, ptr);
- }
- Tcl_DecrRefCount(resultPtr); /* discard the result object */
- }
- return result;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclInvoke --
- *
- * Invokes a Tcl command, given an argv/argc, from either the
- * exposed or the hidden sets of commands in the given interpreter.
- * NOTE: The command is invoked in the current stack frame of
- * the interpreter, thus it can modify local variables.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * Whatever the command does.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclInvoke(interp, argc, argv, flags)
- Tcl_Interp *interp; /* Where to invoke the command. */
- int argc; /* Count of args. */
- register CONST char **argv; /* The arg strings; argv[0] is the name of
- * the command to invoke. */
- int flags; /* Combination of flags controlling the
- * call: TCL_INVOKE_HIDDEN and
- * TCL_INVOKE_NO_UNKNOWN. */
-{
- register Tcl_Obj *objPtr;
- register int i;
- int length, result;
-
- /*
- * This procedure generates an objv array for object arguments that hold
- * the argv strings. It starts out with stack-allocated space but uses
- * dynamically-allocated storage if needed.
- */
-
-#define NUM_ARGS 20
- Tcl_Obj *(objStorage[NUM_ARGS]);
- register Tcl_Obj **objv = objStorage;
-
- /*
- * Create the object argument array "objv". Make sure objv is large
- * enough to hold the objc arguments plus 1 extra for the zero
- * end-of-objv word.
- */
-
- if ((argc + 1) > NUM_ARGS) {
- objv = (Tcl_Obj **)
- ckalloc((unsigned)(argc + 1) * sizeof(Tcl_Obj *));
- }
-
- for (i = 0; i < argc; i++) {
- length = strlen(argv[i]);
- objv[i] = Tcl_NewStringObj(argv[i], length);
- Tcl_IncrRefCount(objv[i]);
- }
- objv[argc] = 0;
-
- /*
- * Use TclObjInterpProc to actually invoke the command.
- */
-
- result = TclObjInvoke(interp, argc, objv, flags);
-
- /*
- * Move the interpreter's object result to the string result,
- * then reset the object result.
- */
-
- Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
- TCL_VOLATILE);
-
- /*
- * Decrement the ref counts on the objv elements since we are done
- * with them.
- */
-
- for (i = 0; i < argc; i++) {
- objPtr = objv[i];
- Tcl_DecrRefCount(objPtr);
- }
-
- /*
- * Free the objv array if malloc'ed storage was used.
- */
-
- if (objv != objStorage) {
- ckfree((char *) objv);
+ result = Tcl_GetBooleanFromObj(interp, resultPtr, ptr);
+ Tcl_DecrRefCount(resultPtr);
+ /* Discard the result object. */
}
return result;
-#undef NUM_ARGS
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclGlobalInvoke --
- *
- * Invokes a Tcl command, given an argv/argc, from either the
- * exposed or hidden sets of commands in the given interpreter.
- * NOTE: The command is invoked in the global stack frame of
- * the interpreter, thus it cannot see any current state on
- * the stack for that interpreter.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * Whatever the command does.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclGlobalInvoke(interp, argc, argv, flags)
- Tcl_Interp *interp; /* Where to invoke the command. */
- int argc; /* Count of args. */
- register CONST char **argv; /* The arg strings; argv[0] is the name of
- * the command to invoke. */
- int flags; /* Combination of flags controlling the
- * call: TCL_INVOKE_HIDDEN and
- * TCL_INVOKE_NO_UNKNOWN. */
-{
- register Interp *iPtr = (Interp *) interp;
- int result;
- CallFrame *savedVarFramePtr;
-
- savedVarFramePtr = iPtr->varFramePtr;
- iPtr->varFramePtr = NULL;
- result = TclInvoke(interp, argc, argv, flags);
- iPtr->varFramePtr = savedVarFramePtr;
- return result;
}
/*
*----------------------------------------------------------------------
*
- * TclObjInvokeGlobal --
+ * TclObjInvokeNamespace --
*
- * Object version: Invokes a Tcl command, given an objv/objc, from
- * either the exposed or hidden set of commands in the given
- * interpreter.
+ * Object version: Invokes a Tcl command, given an objv/objc, from either
+ * the exposed or hidden set of commands in the given interpreter.
* NOTE: The command is invoked in the global stack frame of the
- * interpreter, thus it cannot see any current state on the
+ * interpreter or namespace, thus it cannot see any current state on the
* stack of that interpreter.
*
* Results:
@@ -5794,25 +5586,33 @@ TclGlobalInvoke(interp, argc, argv, flags)
*/
int
-TclObjInvokeGlobal(interp, objc, objv, flags)
- Tcl_Interp *interp; /* Interpreter in which command is to be
+TclObjInvokeNamespace(
+ Tcl_Interp *interp, /* Interpreter in which command is to be
* invoked. */
- int objc; /* Count of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects; objv[0] points to the
+ int objc, /* Count of arguments. */
+ Tcl_Obj *const objv[], /* Argument objects; objv[0] points to the
* name of the command to invoke. */
- int flags; /* Combination of flags controlling the
- * call: TCL_INVOKE_HIDDEN,
- * TCL_INVOKE_NO_UNKNOWN, or
- * TCL_INVOKE_NO_TRACEBACK. */
+ Tcl_Namespace *nsPtr, /* The namespace to use. */
+ int flags) /* Combination of flags controlling the call:
+ * TCL_INVOKE_HIDDEN, TCL_INVOKE_NO_UNKNOWN,
+ * or TCL_INVOKE_NO_TRACEBACK. */
{
- register Interp *iPtr = (Interp *) interp;
int result;
- CallFrame *savedVarFramePtr;
+ Tcl_CallFrame *framePtr;
+
+ /*
+ * Make the specified namespace the current namespace and invoke the
+ * command.
+ */
+
+ result = TclPushStackFrame(interp, &framePtr, nsPtr, /*isProcFrame*/0);
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
- savedVarFramePtr = iPtr->varFramePtr;
- iPtr->varFramePtr = NULL;
result = TclObjInvoke(interp, objc, objv, flags);
- iPtr->varFramePtr = savedVarFramePtr;
+
+ TclPopStackFrame(interp);
return result;
}
@@ -5821,8 +5621,8 @@ TclObjInvokeGlobal(interp, objc, objv, flags)
*
* TclObjInvoke --
*
- * Invokes a Tcl command, given an objv/objc, from either the
- * exposed or the hidden sets of commands in the given interpreter.
+ * Invokes a Tcl command, given an objv/objc, from either the exposed or
+ * the hidden sets of commands in the given interpreter.
*
* Results:
* A standard Tcl object result.
@@ -5834,165 +5634,77 @@ TclObjInvokeGlobal(interp, objc, objv, flags)
*/
int
-TclObjInvoke(interp, objc, objv, flags)
- Tcl_Interp *interp; /* Interpreter in which command is to be
+TclObjInvoke(
+ Tcl_Interp *interp, /* Interpreter in which command is to be
* invoked. */
- int objc; /* Count of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects; objv[0] points to the
+ int objc, /* Count of arguments. */
+ Tcl_Obj *const objv[], /* Argument objects; objv[0] points to the
* name of the command to invoke. */
- int flags; /* Combination of flags controlling the
- * call: TCL_INVOKE_HIDDEN,
- * TCL_INVOKE_NO_UNKNOWN, or
- * TCL_INVOKE_NO_TRACEBACK. */
+ int flags) /* Combination of flags controlling the call:
+ * TCL_INVOKE_HIDDEN, TCL_INVOKE_NO_UNKNOWN,
+ * or TCL_INVOKE_NO_TRACEBACK. */
{
register Interp *iPtr = (Interp *) interp;
Tcl_HashTable *hTblPtr; /* Table of hidden commands. */
char *cmdName; /* Name of the command from objv[0]. */
- register Tcl_HashEntry *hPtr;
- Tcl_Command cmd;
+ Tcl_HashEntry *hPtr = NULL;
Command *cmdPtr;
- int localObjc; /* Used to invoke "unknown" if the */
- Tcl_Obj **localObjv = NULL; /* command is not found. */
- register int i;
int result;
- if (interp == (Tcl_Interp *) NULL) {
- return TCL_ERROR;
+ if (interp == NULL) {
+ return TCL_ERROR;
+ }
+
+ if ((objc < 1) || (objv == NULL)) {
+ Tcl_AppendResult(interp, "illegal argument vector", NULL);
+ return TCL_ERROR;
}
- if ((objc < 1) || (objv == (Tcl_Obj **) NULL)) {
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "illegal argument vector", -1);
- return TCL_ERROR;
+ if ((flags & TCL_INVOKE_HIDDEN) == 0) {
+ Tcl_Panic("TclObjInvoke: called without TCL_INVOKE_HIDDEN");
}
- cmdName = Tcl_GetString(objv[0]);
- if (flags & TCL_INVOKE_HIDDEN) {
- /*
- * We never invoke "unknown" for hidden commands.
- */
-
- hPtr = NULL;
- hTblPtr = ((Interp *) interp)->hiddenCmdTablePtr;
- if (hTblPtr != NULL) {
- hPtr = Tcl_FindHashEntry(hTblPtr, cmdName);
- }
- if (hPtr == NULL) {
- Tcl_ResetResult(interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "invalid hidden command name \"", cmdName, "\"",
- (char *) NULL);
- return TCL_ERROR;
- }
- cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
- } else {
- cmdPtr = NULL;
- cmd = Tcl_FindCommand(interp, cmdName,
- (Tcl_Namespace *) NULL, /*flags*/ TCL_GLOBAL_ONLY);
- if (cmd != (Tcl_Command) NULL) {
- cmdPtr = (Command *) cmd;
- }
- if (cmdPtr == NULL) {
- if (!(flags & TCL_INVOKE_NO_UNKNOWN)) {
- cmd = Tcl_FindCommand(interp, "unknown",
- (Tcl_Namespace *) NULL, /*flags*/ TCL_GLOBAL_ONLY);
- if (cmd != (Tcl_Command) NULL) {
- cmdPtr = (Command *) cmd;
- }
- if (cmdPtr != NULL) {
- localObjc = (objc + 1);
- localObjv = (Tcl_Obj **)
- ckalloc((unsigned) (sizeof(Tcl_Obj *) * localObjc));
- localObjv[0] = Tcl_NewStringObj("unknown", -1);
- Tcl_IncrRefCount(localObjv[0]);
- for (i = 0; i < objc; i++) {
- localObjv[i+1] = objv[i];
- }
- objc = localObjc;
- objv = localObjv;
- }
- }
-
- /*
- * Check again if we found the command. If not, "unknown" is
- * not present and we cannot help, or the caller said not to
- * call "unknown" (they specified TCL_INVOKE_NO_UNKNOWN).
- */
-
- if (cmdPtr == NULL) {
- Tcl_ResetResult(interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "invalid command name \"", cmdName, "\"",
- (char *) NULL);
- return TCL_ERROR;
- }
- }
- }
-
- /*
- * Invoke the command procedure. First reset the interpreter's string
- * and object results to their default empty values since they could
- * have gotten changed by earlier invocations.
+ if (TclInterpReady(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ cmdName = TclGetString(objv[0]);
+ hTblPtr = iPtr->hiddenCmdTablePtr;
+ if (hTblPtr != NULL) {
+ hPtr = Tcl_FindHashEntry(hTblPtr, cmdName);
+ }
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "invalid hidden command name \"",
+ cmdName, "\"", NULL);
+ return TCL_ERROR;
+ }
+ cmdPtr = Tcl_GetHashValue(hPtr);
+
+ /*
+ * Invoke the command function.
*/
- Tcl_ResetResult(interp);
iPtr->cmdCount++;
- result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, objc, objv);
+ result = cmdPtr->objProc(cmdPtr->objClientData, interp, objc, objv);
/*
- * If an error occurred, record information about what was being
- * executed when the error occurred.
+ * If an error occurred, record information about what was being executed
+ * when the error occurred.
*/
if ((result == TCL_ERROR)
&& ((flags & TCL_INVOKE_NO_TRACEBACK) == 0)
&& ((iPtr->flags & ERR_ALREADY_LOGGED) == 0)) {
- Tcl_Obj *msg;
-
- if (!(iPtr->flags & ERR_IN_PROGRESS)) {
- msg = Tcl_NewStringObj("\n while invoking\n\"", -1);
- } else {
- msg = Tcl_NewStringObj("\n invoked from within\n\"", -1);
- }
- Tcl_IncrRefCount(msg);
- for (i = 0; i < objc; i++) {
- CONST char *bytes;
- int length;
-
- Tcl_AppendObjToObj(msg, objv[i]);
- bytes = Tcl_GetStringFromObj(msg, &length);
- if (length > 100) {
- /*
- * Back up truncation point so that we don't truncate
- * in the middle of a multi-byte character.
- */
- length = 100;
- while ( (bytes[length] & 0xC0) == 0x80 ) {
- length--;
- }
- Tcl_SetObjLength(msg, length);
- Tcl_AppendToObj(msg, "...", -1);
- break;
- }
- if (i != (objc - 1)) {
- Tcl_AppendToObj(msg, " ", -1);
- }
- }
-
- Tcl_AppendToObj(msg, "\"", -1);
- Tcl_AddObjErrorInfo(interp, Tcl_GetString(msg), -1);
- Tcl_DecrRefCount(msg);
+ int length;
+ Tcl_Obj *command = Tcl_NewListObj(objc, objv);
+ const char *cmdString;
+
+ Tcl_IncrRefCount(command);
+ cmdString = Tcl_GetStringFromObj(command, &length);
+ Tcl_LogCommandInfo(interp, cmdString, cmdString, length);
+ Tcl_DecrRefCount(command);
iPtr->flags &= ~ERR_ALREADY_LOGGED;
}
-
- /*
- * Free any locally allocated storage used to call "unknown".
- */
-
- if (localObjv != (Tcl_Obj **) NULL) {
- Tcl_DecrRefCount(localObjv[0]);
- ckfree((char *) localObjv);
- }
return result;
}
@@ -6006,413 +5718,81 @@ TclObjInvoke(interp, objc, objv, flags)
*
* Results:
* A standard Tcl result. If the result is TCL_OK, then the interp's
- * result is set to the string value of the expression. If the result
- * is TCL_ERROR, then the interp's result contains an error message.
+ * result is set to the string value of the expression. If the result is
+ * TCL_ERROR, then the interp's result contains an error message.
*
* Side effects:
* A Tcl object is allocated to hold a copy of the expression string.
- * This expression object is passed to Tcl_ExprObj and then
- * deallocated.
+ * This expression object is passed to Tcl_ExprObj and then deallocated.
*
*---------------------------------------------------------------------------
*/
int
-Tcl_ExprString(interp, string)
- Tcl_Interp *interp; /* Context in which to evaluate the
+Tcl_ExprString(
+ Tcl_Interp *interp, /* Context in which to evaluate the
* expression. */
- CONST char *string; /* Expression to evaluate. */
+ const char *expr) /* Expression to evaluate. */
{
- register Tcl_Obj *exprPtr;
- Tcl_Obj *resultPtr;
- int length = strlen(string);
- char buf[TCL_DOUBLE_SPACE];
- int result = TCL_OK;
-
- if (length > 0) {
- TclNewObj(exprPtr);
- TclInitStringRep(exprPtr, string, length);
- Tcl_IncrRefCount(exprPtr);
+ int code = TCL_OK;
- result = Tcl_ExprObj(interp, exprPtr, &resultPtr);
- if (result == TCL_OK) {
- /*
- * Set the interpreter's string result from the result object.
- */
-
- if (resultPtr->typePtr == &tclIntType) {
- sprintf(buf, "%ld", resultPtr->internalRep.longValue);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
- } else if (resultPtr->typePtr == &tclDoubleType) {
- Tcl_PrintDouble((Tcl_Interp *) NULL,
- resultPtr->internalRep.doubleValue, buf);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
- } else {
- /*
- * Set interpreter's string result from the result object.
- */
-
- Tcl_SetResult(interp, TclGetString(resultPtr),
- TCL_VOLATILE);
- }
- Tcl_DecrRefCount(resultPtr); /* discard the result object */
- } else {
- /*
- * Move the interpreter's object result to the string result,
- * then reset the object result.
- */
-
- Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
- TCL_VOLATILE);
- }
- Tcl_DecrRefCount(exprPtr); /* discard the expression object */
- } else {
+ if (expr[0] == '\0') {
/*
* An empty string. Just set the interpreter's result to 0.
*/
-
- Tcl_SetResult(interp, "0", TCL_VOLATILE);
- }
- return result;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_CreateObjTrace --
- *
- * Arrange for a procedure to be called to trace command execution.
- *
- * Results:
- * The return value is a token for the trace, which may be passed
- * to Tcl_DeleteTrace to eliminate the trace.
- *
- * Side effects:
- * From now on, proc will be called just before a command procedure
- * is called to execute a Tcl command. Calls to proc will have the
- * following form:
- *
- * void proc( ClientData clientData,
- * Tcl_Interp* interp,
- * int level,
- * CONST char* command,
- * Tcl_Command commandInfo,
- * int objc,
- * Tcl_Obj *CONST objv[] );
- *
- * The 'clientData' and 'interp' arguments to 'proc' will be the
- * same as the arguments to Tcl_CreateObjTrace. The 'level'
- * argument gives the nesting depth of command interpretation within
- * the interpreter. The 'command' argument is the ASCII text of
- * the command being evaluated -- before any substitutions are
- * performed. The 'commandInfo' argument gives a handle to the
- * command procedure that will be evaluated. The 'objc' and 'objv'
- * parameters give the parameter vector that will be passed to the
- * command procedure. proc does not return a value.
- *
- * It is permissible for 'proc' to call Tcl_SetCommandTokenInfo
- * to change the command procedure or client data for the command
- * being evaluated, and these changes will take effect with the
- * current evaluation.
- *
- * The 'level' argument specifies the maximum nesting level of calls
- * to be traced. If the execution depth of the interpreter exceeds
- * 'level', the trace callback is not executed.
- *
- * The 'flags' argument is either zero or the value,
- * TCL_ALLOW_INLINE_COMPILATION. If the TCL_ALLOW_INLINE_COMPILATION
- * flag is not present, the bytecode compiler will not generate inline
- * code for Tcl's built-in commands. This behavior will have a significant
- * impact on performance, but will ensure that all command evaluations are
- * traced. If the TCL_ALLOW_INLINE_COMPILATION flag is present, the
- * bytecode compiler will have its normal behavior of compiling in-line
- * code for some of Tcl's built-in commands. In this case, the tracing
- * will be imprecise -- in-line code will not be traced -- but run-time
- * performance will be improved. The latter behavior is desired for
- * many applications such as profiling of run time.
- *
- * When the trace is deleted, the 'delProc' procedure will be invoked,
- * passing it the original client data.
- *
- *----------------------------------------------------------------------
- */
-Tcl_Trace
-Tcl_CreateObjTrace( interp, level, flags, proc, clientData, delProc )
- Tcl_Interp* interp; /* Tcl interpreter */
- int level; /* Maximum nesting level */
- int flags; /* Flags, see above */
- Tcl_CmdObjTraceProc* proc; /* Trace callback */
- ClientData clientData; /* Client data for the callback */
- Tcl_CmdObjTraceDeleteProc* delProc;
- /* Procedure to call when trace is deleted */
-{
- register Trace *tracePtr;
- register Interp *iPtr = (Interp *) interp;
-
- /* Test if this trace allows inline compilation of commands */
-
- if (!(flags & TCL_ALLOW_INLINE_COMPILATION)) {
- if (iPtr->tracesForbiddingInline == 0) {
-
- /*
- * When the first trace forbidding inline compilation is
- * created, invalidate existing compiled code for this
- * interpreter and arrange (by setting the
- * DONT_COMPILE_CMDS_INLINE flag) that when compiling new
- * code, no commands will be compiled inline (i.e., into
- * an inline sequence of instructions). We do this because
- * commands that were compiled inline will never result in
- * a command trace being called.
- */
-
- iPtr->compileEpoch++;
- iPtr->flags |= DONT_COMPILE_CMDS_INLINE;
+ Tcl_SetResult(interp, "0", TCL_VOLATILE);
+ } else {
+ Tcl_Obj *resultPtr, *exprObj = Tcl_NewStringObj(expr, -1);
+
+ Tcl_IncrRefCount(exprObj);
+ code = Tcl_ExprObj(interp, exprObj, &resultPtr);
+ Tcl_DecrRefCount(exprObj);
+ if (code == TCL_OK) {
+ Tcl_SetObjResult(interp, resultPtr);
+ Tcl_DecrRefCount(resultPtr);
}
- iPtr->tracesForbiddingInline++;
- }
-
- tracePtr = (Trace *) ckalloc(sizeof(Trace));
- tracePtr->level = level;
- tracePtr->proc = proc;
- tracePtr->clientData = clientData;
- tracePtr->delProc = delProc;
- tracePtr->nextPtr = iPtr->tracePtr;
- tracePtr->flags = flags;
- iPtr->tracePtr = tracePtr;
-
- return (Tcl_Trace) tracePtr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_CreateTrace --
- *
- * Arrange for a procedure to be called to trace command execution.
- *
- * Results:
- * The return value is a token for the trace, which may be passed
- * to Tcl_DeleteTrace to eliminate the trace.
- *
- * Side effects:
- * From now on, proc will be called just before a command procedure
- * is called to execute a Tcl command. Calls to proc will have the
- * following form:
- *
- * void
- * proc(clientData, interp, level, command, cmdProc, cmdClientData,
- * argc, argv)
- * ClientData clientData;
- * Tcl_Interp *interp;
- * int level;
- * char *command;
- * int (*cmdProc)();
- * ClientData cmdClientData;
- * int argc;
- * char **argv;
- * {
- * }
- *
- * The clientData and interp arguments to proc will be the same
- * as the corresponding arguments to this procedure. Level gives
- * the nesting level of command interpretation for this interpreter
- * (0 corresponds to top level). Command gives the ASCII text of
- * the raw command, cmdProc and cmdClientData give the procedure that
- * will be called to process the command and the ClientData value it
- * will receive, and argc and argv give the arguments to the
- * command, after any argument parsing and substitution. Proc
- * does not return a value.
- *
- *----------------------------------------------------------------------
- */
-Tcl_Trace
-Tcl_CreateTrace(interp, level, proc, clientData)
- Tcl_Interp *interp; /* Interpreter in which to create trace. */
- int level; /* Only call proc for commands at nesting
- * level<=argument level (1=>top level). */
- Tcl_CmdTraceProc *proc; /* Procedure to call before executing each
- * command. */
- ClientData clientData; /* Arbitrary value word to pass to proc. */
-{
- StringTraceData* data;
- data = (StringTraceData*) ckalloc( sizeof( *data ));
- data->clientData = clientData;
- data->proc = proc;
- return Tcl_CreateObjTrace( interp, level, 0, StringTraceProc,
- (ClientData) data, StringTraceDeleteProc );
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * StringTraceProc --
- *
- * Invoke a string-based trace procedure from an object-based
- * callback.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Whatever the string-based trace procedure does.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-StringTraceProc( clientData, interp, level, command, commandInfo, objc, objv )
- ClientData clientData;
- Tcl_Interp* interp;
- int level;
- CONST char* command;
- Tcl_Command commandInfo;
- int objc;
- Tcl_Obj *CONST *objv;
-{
- StringTraceData* data = (StringTraceData*) clientData;
- Command* cmdPtr = (Command*) commandInfo;
-
- CONST char** argv; /* Args to pass to string trace proc */
-
- int i;
+ /*
+ * Force the string rep of the interp result.
+ */
- /*
- * This is a bit messy because we have to emulate the old trace
- * interface, which uses strings for everything.
- */
-
- argv = (CONST char **) ckalloc((unsigned) ( (objc + 1)
- * sizeof(CONST char *) ));
- for (i = 0; i < objc; i++) {
- argv[i] = Tcl_GetString(objv[i]);
+ (void) Tcl_GetStringResult(interp);
}
- argv[objc] = 0;
-
- /*
- * Invoke the command procedure. Note that we cast away const-ness
- * on two parameters for compatibility with legacy code; the code
- * MUST NOT modify either command or argv.
- */
-
- ( data->proc )( data->clientData, interp, level,
- (char*) command, cmdPtr->proc, cmdPtr->clientData,
- objc, argv );
- ckfree( (char*) argv );
-
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * StringTraceDeleteProc --
- *
- * Clean up memory when a string-based trace is deleted.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Allocated memory is returned to the system.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-StringTraceDeleteProc( clientData )
- ClientData clientData;
-{
- ckfree( (char*) clientData );
+ return code;
}
/*
*----------------------------------------------------------------------
*
- * Tcl_DeleteTrace --
+ * Tcl_AppendObjToErrorInfo --
*
- * Remove a trace.
+ * Add a Tcl_Obj value to the errorInfo field that describes the current
+ * error.
*
* Results:
* None.
*
* Side effects:
- * From now on there will be no more calls to the procedure given
- * in trace.
+ * The value of the Tcl_obj is appended to the errorInfo field. If we are
+ * just starting to log an error, errorInfo is initialized from the error
+ * message in the interpreter's result.
*
*----------------------------------------------------------------------
*/
void
-Tcl_DeleteTrace(interp, trace)
- Tcl_Interp *interp; /* Interpreter that contains trace. */
- Tcl_Trace trace; /* Token for trace (returned previously by
- * Tcl_CreateTrace). */
+Tcl_AppendObjToErrorInfo(
+ Tcl_Interp *interp, /* Interpreter to which error information
+ * pertains. */
+ Tcl_Obj *objPtr) /* Message to record. */
{
- Interp *iPtr = (Interp *) interp;
- Trace *prevPtr, *tracePtr = (Trace *) trace;
- register Trace **tracePtr2 = &(iPtr->tracePtr);
- ActiveInterpTrace *activePtr;
-
- /*
- * Locate the trace entry in the interpreter's trace list,
- * and remove it from the list.
- */
+ int length;
+ const char *message = TclGetStringFromObj(objPtr, &length);
- prevPtr = NULL;
- while ((*tracePtr2) != NULL && (*tracePtr2) != tracePtr) {
- prevPtr = *tracePtr2;
- tracePtr2 = &((*tracePtr2)->nextPtr);
- }
- if (*tracePtr2 == NULL) {
- return;
- }
- (*tracePtr2) = (*tracePtr2)->nextPtr;
-
- /*
- * The code below makes it possible to delete traces while traces
- * are active: it makes sure that the deleted trace won't be
- * processed by TclCheckInterpTraces.
- */
-
- for (activePtr = iPtr->activeInterpTracePtr; activePtr != NULL;
- activePtr = activePtr->nextPtr) {
- if (activePtr->nextTracePtr == tracePtr) {
- if (activePtr->reverseScan) {
- activePtr->nextTracePtr = prevPtr;
- } else {
- activePtr->nextTracePtr = tracePtr->nextPtr;
- }
- }
- }
-
- /*
- * If the trace forbids bytecode compilation, change the interpreter's
- * state. If bytecode compilation is now permitted, flag the fact and
- * advance the compilation epoch so that procs will be recompiled to
- * take advantage of it.
- */
-
- if (!(tracePtr->flags & TCL_ALLOW_INLINE_COMPILATION)) {
- iPtr->tracesForbiddingInline--;
- if (iPtr->tracesForbiddingInline == 0) {
- iPtr->flags &= ~DONT_COMPILE_CMDS_INLINE;
- iPtr->compileEpoch++;
- }
- }
-
- /*
- * Execute any delete callback.
- */
-
- if (tracePtr->delProc != NULL) {
- (tracePtr->delProc)(tracePtr->clientData);
- }
-
- /* Delete the trace object */
-
- Tcl_EventuallyFree((char*)tracePtr, TCL_DYNAMIC);
+ Tcl_IncrRefCount(objPtr);
+ Tcl_AddObjErrorInfo(interp, message, length);
+ Tcl_DecrRefCount(objPtr);
}
/*
@@ -6420,27 +5800,25 @@ Tcl_DeleteTrace(interp, trace)
*
* Tcl_AddErrorInfo --
*
- * Add information to the "errorInfo" variable that describes the
- * current error.
+ * Add information to the errorInfo field that describes the current
+ * error.
*
* Results:
* None.
*
* Side effects:
- * The contents of message are added to the "errorInfo" variable.
- * If Tcl_Eval has been called since the current value of errorInfo
- * was set, errorInfo is cleared before adding the new message.
- * If we are just starting to log an error, errorInfo is initialized
- * from the error message in the interpreter's result.
+ * The contents of message are appended to the errorInfo field. If we are
+ * just starting to log an error, errorInfo is initialized from the error
+ * message in the interpreter's result.
*
*----------------------------------------------------------------------
*/
void
-Tcl_AddErrorInfo(interp, message)
- Tcl_Interp *interp; /* Interpreter to which error information
+Tcl_AddErrorInfo(
+ Tcl_Interp *interp, /* Interpreter to which error information
* pertains. */
- CONST char *message; /* Message to record. */
+ const char *message) /* Message to record. */
{
Tcl_AddObjErrorInfo(interp, message, -1);
}
@@ -6450,67 +5828,56 @@ Tcl_AddErrorInfo(interp, message)
*
* Tcl_AddObjErrorInfo --
*
- * Add information to the "errorInfo" variable that describes the
- * current error. This routine differs from Tcl_AddErrorInfo by
- * taking a byte pointer and length.
+ * Add information to the errorInfo field that describes the current
+ * error. This routine differs from Tcl_AddErrorInfo by taking a byte
+ * pointer and length.
*
* Results:
* None.
*
* Side effects:
- * "length" bytes from "message" are added to the "errorInfo" variable.
- * If "length" is negative, use bytes up to the first NULL byte.
- * If Tcl_EvalObj has been called since the current value of errorInfo
- * was set, errorInfo is cleared before adding the new message.
- * If we are just starting to log an error, errorInfo is initialized
- * from the error message in the interpreter's result.
+ * "length" bytes from "message" are appended to the errorInfo field. If
+ * "length" is negative, use bytes up to the first NULL byte. If we are
+ * just starting to log an error, errorInfo is initialized from the error
+ * message in the interpreter's result.
*
*----------------------------------------------------------------------
*/
void
-Tcl_AddObjErrorInfo(interp, message, length)
- Tcl_Interp *interp; /* Interpreter to which error information
+Tcl_AddObjErrorInfo(
+ Tcl_Interp *interp, /* Interpreter to which error information
* pertains. */
- CONST char *message; /* Points to the first byte of an array of
+ const char *message, /* Points to the first byte of an array of
* bytes of the message. */
- int length; /* The number of bytes in the message.
- * If < 0, then append all bytes up to a
- * NULL byte. */
+ int length) /* The number of bytes in the message. If < 0,
+ * then append all bytes up to a NULL byte. */
{
register Interp *iPtr = (Interp *) interp;
- Tcl_Obj *objPtr;
-
+
/*
- * If we are just starting to log an error, errorInfo is initialized
- * from the error message in the interpreter's result.
+ * If we are just starting to log an error, errorInfo is initialized from
+ * the error message in the interpreter's result.
*/
- if (!(iPtr->flags & ERR_IN_PROGRESS)) { /* just starting to log error */
- iPtr->flags |= ERR_IN_PROGRESS;
+ iPtr->flags |= ERR_LEGACY_COPY;
+ if (iPtr->errorInfo == NULL) {
+ if (iPtr->result[0] != 0) {
+ /*
+ * The interp's string result is set, apparently by some extension
+ * making a deprecated direct write to it. That extension may
+ * expect interp->result to continue to be set, so we'll take
+ * special pains to avoid clearing it, until we drop support for
+ * interp->result completely.
+ */
- if (iPtr->result[0] == 0) {
- Tcl_ObjSetVar2(interp, iPtr->execEnvPtr->errorInfo, NULL,
- iPtr->objResultPtr, TCL_GLOBAL_ONLY);
- } else { /* use the string result */
- objPtr = Tcl_NewStringObj(interp->result, -1);
- Tcl_IncrRefCount(objPtr);
- Tcl_ObjSetVar2(interp, iPtr->execEnvPtr->errorInfo, NULL,
- objPtr, TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(objPtr);
+ iPtr->errorInfo = Tcl_NewStringObj(interp->result, -1);
+ } else {
+ iPtr->errorInfo = iPtr->objResultPtr;
}
-
- /*
- * If the errorCode variable wasn't set by the code that generated
- * the error, set it to "NONE".
- */
-
- if (!(iPtr->flags & ERROR_CODE_SET)) {
- objPtr = Tcl_NewStringObj("NONE", -1);
- Tcl_IncrRefCount(objPtr);
- Tcl_ObjSetVar2(interp, iPtr->execEnvPtr->errorCode, NULL,
- objPtr, TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(objPtr);
+ Tcl_IncrRefCount(iPtr->errorInfo);
+ if (!iPtr->errorCode) {
+ Tcl_SetErrorCode(interp, "NONE", NULL);
}
}
@@ -6519,11 +5886,12 @@ Tcl_AddObjErrorInfo(interp, message, length)
*/
if (length != 0) {
- objPtr = Tcl_NewStringObj(message, length);
- Tcl_IncrRefCount(objPtr);
- Tcl_ObjSetVar2(interp, iPtr->execEnvPtr->errorInfo, NULL,
- objPtr, (TCL_GLOBAL_ONLY | TCL_APPEND_VALUE));
- Tcl_DecrRefCount(objPtr); /* free msg object appended above */
+ if (Tcl_IsShared(iPtr->errorInfo)) {
+ Tcl_DecrRefCount(iPtr->errorInfo);
+ iPtr->errorInfo = Tcl_DuplicateObj(iPtr->errorInfo);
+ Tcl_IncrRefCount(iPtr->errorInfo);
+ }
+ Tcl_AppendToObj(iPtr->errorInfo, message, length);
}
}
@@ -6532,12 +5900,12 @@ Tcl_AddObjErrorInfo(interp, message, length)
*
* Tcl_VarEvalVA --
*
- * Given a variable number of string arguments, concatenate them
- * all together and execute the result as a Tcl command.
+ * Given a variable number of string arguments, concatenate them all
+ * together and execute the result as a Tcl command.
*
* Results:
- * A standard Tcl return result. An error message or other result may
- * be left in the interp's result.
+ * A standard Tcl return result. An error message or other result may be
+ * left in the interp's result.
*
* Side effects:
* Depends on what was done by the command.
@@ -6546,19 +5914,18 @@ Tcl_AddObjErrorInfo(interp, message, length)
*/
int
-Tcl_VarEvalVA (interp, argList)
- Tcl_Interp *interp; /* Interpreter in which to evaluate command. */
- va_list argList; /* Variable argument list. */
+Tcl_VarEvalVA(
+ Tcl_Interp *interp, /* Interpreter in which to evaluate command. */
+ va_list argList) /* Variable argument list. */
{
Tcl_DString buf;
char *string;
int result;
/*
- * Copy the strings one after the other into a single larger
- * string. Use stack-allocated space for small commands, but if
- * the command gets too large than call ckalloc to create the
- * space.
+ * Copy the strings one after the other into a single larger string. Use
+ * stack-allocated space for small commands, but if the command gets too
+ * large than call ckalloc to create the space.
*/
Tcl_DStringInit(&buf);
@@ -6580,27 +5947,28 @@ Tcl_VarEvalVA (interp, argList)
*
* Tcl_VarEval --
*
- * Given a variable number of string arguments, concatenate them
- * all together and execute the result as a Tcl command.
+ * Given a variable number of string arguments, concatenate them all
+ * together and execute the result as a Tcl command.
*
* Results:
- * A standard Tcl return result. An error message or other
- * result may be left in interp->result.
+ * A standard Tcl return result. An error message or other result may be
+ * left in interp->result.
*
* Side effects:
* Depends on what was done by the command.
*
*----------------------------------------------------------------------
*/
- /* VARARGS2 */ /* ARGSUSED */
+ /* ARGSUSED */
int
-Tcl_VarEval TCL_VARARGS_DEF(Tcl_Interp *,arg1)
+Tcl_VarEval(
+ Tcl_Interp *interp,
+ ...)
{
- Tcl_Interp *interp;
va_list argList;
int result;
- interp = TCL_VARARGS_START(Tcl_Interp *,arg1,argList);
+ va_start(argList, interp);
result = Tcl_VarEvalVA(interp, argList);
va_end(argList);
@@ -6608,36 +5976,35 @@ Tcl_VarEval TCL_VARARGS_DEF(Tcl_Interp *,arg1)
}
/*
- *---------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*
* Tcl_GlobalEval --
*
* Evaluate a command at global level in an interpreter.
*
* Results:
- * A standard Tcl result is returned, and the interp's result is
- * modified accordingly.
+ * A standard Tcl result is returned, and the interp's result is modified
+ * accordingly.
*
* Side effects:
- * The command string is executed in interp, and the execution
- * is carried out in the variable context of global level (no
- * procedures active), just as if an "uplevel #0" command were
- * being executed.
+ * The command string is executed in interp, and the execution is carried
+ * out in the variable context of global level (no functions active),
+ * just as if an "uplevel #0" command were being executed.
*
- ---------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*/
int
-Tcl_GlobalEval(interp, command)
- Tcl_Interp *interp; /* Interpreter in which to evaluate command. */
- CONST char *command; /* Command to evaluate. */
+Tcl_GlobalEval(
+ Tcl_Interp *interp, /* Interpreter in which to evaluate command. */
+ const char *command) /* Command to evaluate. */
{
register Interp *iPtr = (Interp *) interp;
int result;
CallFrame *savedVarFramePtr;
savedVarFramePtr = iPtr->varFramePtr;
- iPtr->varFramePtr = NULL;
+ iPtr->varFramePtr = iPtr->rootFramePtr;
result = Tcl_Eval(interp, command);
iPtr->varFramePtr = savedVarFramePtr;
return result;
@@ -6648,8 +6015,8 @@ Tcl_GlobalEval(interp, command)
*
* Tcl_SetRecursionLimit --
*
- * Set the maximum number of recursive calls that may be active
- * for an interpreter at once.
+ * Set the maximum number of recursive calls that may be active for an
+ * interpreter at once.
*
* Results:
* The return value is the old limit on nesting for interp.
@@ -6661,10 +6028,10 @@ Tcl_GlobalEval(interp, command)
*/
int
-Tcl_SetRecursionLimit(interp, depth)
- Tcl_Interp *interp; /* Interpreter whose nesting limit
- * is to be set. */
- int depth; /* New value for maximimum depth. */
+Tcl_SetRecursionLimit(
+ Tcl_Interp *interp, /* Interpreter whose nesting limit is to be
+ * set. */
+ int depth) /* New value for maximimum depth. */
{
Interp *iPtr = (Interp *) interp;
int old;
@@ -6681,39 +6048,36 @@ Tcl_SetRecursionLimit(interp, depth)
*
* Tcl_AllowExceptions --
*
- * Sets a flag in an interpreter so that exceptions can occur
- * in the next call to Tcl_Eval without them being turned into
- * errors.
+ * Sets a flag in an interpreter so that exceptions can occur in the next
+ * call to Tcl_Eval without them being turned into errors.
*
* Results:
* None.
*
* Side effects:
- * The TCL_ALLOW_EXCEPTIONS flag gets set in the interpreter's
- * evalFlags structure. See the reference documentation for
- * more details.
+ * The TCL_ALLOW_EXCEPTIONS flag gets set in the interpreter's evalFlags
+ * structure. See the reference documentation for more details.
*
*----------------------------------------------------------------------
*/
void
-Tcl_AllowExceptions(interp)
- Tcl_Interp *interp; /* Interpreter in which to set flag. */
+Tcl_AllowExceptions(
+ Tcl_Interp *interp) /* Interpreter in which to set flag. */
{
Interp *iPtr = (Interp *) interp;
iPtr->evalFlags |= TCL_ALLOW_EXCEPTIONS;
}
-
/*
*----------------------------------------------------------------------
*
- * Tcl_GetVersion
+ * Tcl_GetVersion --
*
- * Get the Tcl major, minor, and patchlevel version numbers and
- * the release type. A patch is a release type TCL_FINAL_RELEASE
- * with a patchLevel > 0.
+ * Get the Tcl major, minor, and patchlevel version numbers and the
+ * release type. A patch is a release type TCL_FINAL_RELEASE with a
+ * patchLevel > 0.
*
* Results:
* None.
@@ -6725,24 +6089,898 @@ Tcl_AllowExceptions(interp)
*/
void
-Tcl_GetVersion(majorV, minorV, patchLevelV, type)
- int *majorV;
- int *minorV;
- int *patchLevelV;
- int *type;
+Tcl_GetVersion(
+ int *majorV,
+ int *minorV,
+ int *patchLevelV,
+ int *type)
{
if (majorV != NULL) {
- *majorV = TCL_MAJOR_VERSION;
+ *majorV = TCL_MAJOR_VERSION;
}
if (minorV != NULL) {
- *minorV = TCL_MINOR_VERSION;
+ *minorV = TCL_MINOR_VERSION;
}
if (patchLevelV != NULL) {
- *patchLevelV = TCL_RELEASE_SERIAL;
+ *patchLevelV = TCL_RELEASE_SERIAL;
}
if (type != NULL) {
- *type = TCL_RELEASE_LEVEL;
+ *type = TCL_RELEASE_LEVEL;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Math Functions --
+ *
+ * This page contains the functions that implement all of the built-in
+ * math functions for expressions.
+ *
+ * Results:
+ * Each function returns TCL_OK if it succeeds and pushes an Tcl object
+ * holding the result. If it fails it returns TCL_ERROR and leaves an
+ * error message in the interpreter's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ExprCeilFunc(
+ ClientData clientData, /* Ignored */
+ Tcl_Interp *interp, /* The interpreter in which to execute the
+ * function. */
+ int objc, /* Actual parameter count. */
+ Tcl_Obj *const *objv) /* Actual parameter list. */
+{
+ int code;
+ double d;
+ mp_int big;
+
+ if (objc != 2) {
+ MathFuncWrongNumArgs(interp, 2, objc, objv);
+ return TCL_ERROR;
}
+ code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
+#ifdef ACCEPT_NAN
+ if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) {
+ Tcl_SetObjResult(interp, objv[1]);
+ return TCL_OK;
+ }
+#endif
+ if (code != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetBignumFromObj(NULL, objv[1], &big) == TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(TclCeil(&big)));
+ mp_clear(&big);
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(ceil(d)));
+ }
+ return TCL_OK;
+}
+
+static int
+ExprFloorFunc(
+ ClientData clientData, /* Ignored */
+ Tcl_Interp *interp, /* The interpreter in which to execute the
+ * function. */
+ int objc, /* Actual parameter count. */
+ Tcl_Obj *const *objv) /* Actual parameter list. */
+{
+ int code;
+ double d;
+ mp_int big;
+
+ if (objc != 2) {
+ MathFuncWrongNumArgs(interp, 2, objc, objv);
+ return TCL_ERROR;
+ }
+ code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
+#ifdef ACCEPT_NAN
+ if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) {
+ Tcl_SetObjResult(interp, objv[1]);
+ return TCL_OK;
+ }
+#endif
+ if (code != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetBignumFromObj(NULL, objv[1], &big) == TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(TclFloor(&big)));
+ mp_clear(&big);
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(floor(d)));
+ }
+ return TCL_OK;
+}
+
+static int
+ExprIsqrtFunc(
+ ClientData clientData, /* Ignored */
+ Tcl_Interp *interp, /* The interpreter in which to execute. */
+ int objc, /* Actual parameter count. */
+ Tcl_Obj *const *objv) /* Actual parameter list. */
+{
+ ClientData ptr;
+ int type;
+ double d;
+ Tcl_WideInt w;
+ mp_int big;
+ int exact = 0; /* Flag == 1 if the argument can be
+ * represented in a double as an exact
+ * integer. */
+
+ /*
+ * Check syntax.
+ */
+
+ if (objc != 2) {
+ MathFuncWrongNumArgs(interp, 2, objc, objv);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Make sure that the arg is a number.
+ */
+
+ if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch (type) {
+ case TCL_NUMBER_NAN:
+ Tcl_GetDoubleFromObj(interp, objv[1], &d);
+ return TCL_ERROR;
+ case TCL_NUMBER_DOUBLE:
+ d = *((const double *) ptr);
+ if (d < 0) {
+ goto negarg;
+ }
+#ifdef IEEE_FLOATING_POINT
+ if (d <= MAX_EXACT) {
+ exact = 1;
+ }
+#endif
+ if (!exact) {
+ if (Tcl_InitBignumFromDouble(interp, d, &big) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ break;
+ case TCL_NUMBER_BIG:
+ if (Tcl_GetBignumFromObj(interp, objv[1], &big) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (SIGN(&big) == MP_NEG) {
+ mp_clear(&big);
+ goto negarg;
+ }
+ break;
+ default:
+ if (Tcl_GetWideIntFromObj(interp, objv[1], &w) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (w < 0) {
+ goto negarg;
+ }
+ d = (double) w;
+#ifdef IEEE_FLOATING_POINT
+ if (d < MAX_EXACT) {
+ exact = 1;
+ }
+#endif
+ if (!exact) {
+ Tcl_GetBignumFromObj(interp, objv[1], &big);
+ }
+ break;
+ }
+
+ if (exact) {
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) sqrt(d)));
+ } else {
+ mp_int root;
+
+ mp_init(&root);
+ mp_sqrt(&big, &root);
+ mp_clear(&big);
+ Tcl_SetObjResult(interp, Tcl_NewBignumObj(&root));
+ }
+
+ return TCL_OK;
+
+ negarg:
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("square root of negative argument", -1));
+ return TCL_ERROR;
+}
+
+static int
+ExprSqrtFunc(
+ ClientData clientData, /* Ignored */
+ Tcl_Interp *interp, /* The interpreter in which to execute the
+ * function. */
+ int objc, /* Actual parameter count. */
+ Tcl_Obj *const *objv) /* Actual parameter list. */
+{
+ int code;
+ double d;
+ mp_int big;
+
+ if (objc != 2) {
+ MathFuncWrongNumArgs(interp, 2, objc, objv);
+ return TCL_ERROR;
+ }
+ code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
+#ifdef ACCEPT_NAN
+ if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) {
+ Tcl_SetObjResult(interp, objv[1]);
+ return TCL_OK;
+ }
+#endif
+ if (code != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((d >= 0.0) && TclIsInfinite(d)
+ && (Tcl_GetBignumFromObj(NULL, objv[1], &big) == TCL_OK)) {
+ mp_int root;
+
+ mp_init(&root);
+ mp_sqrt(&big, &root);
+ mp_clear(&big);
+ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(TclBignumToDouble(&root)));
+ mp_clear(&root);
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(sqrt(d)));
+ }
+ return TCL_OK;
+}
+
+static int
+ExprUnaryFunc(
+ ClientData clientData, /* Contains the address of a function that
+ * takes one double argument and returns a
+ * double result. */
+ Tcl_Interp *interp, /* The interpreter in which to execute the
+ * function. */
+ int objc, /* Actual parameter count */
+ Tcl_Obj *const *objv) /* Actual parameter list */
+{
+ int code;
+ double d;
+ double (*func)(double) = (double (*)(double)) clientData;
+
+ if (objc != 2) {
+ MathFuncWrongNumArgs(interp, 2, objc, objv);
+ return TCL_ERROR;
+ }
+ code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
+#ifdef ACCEPT_NAN
+ if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) {
+ d = objv[1]->internalRep.doubleValue;
+ Tcl_ResetResult(interp);
+ code = TCL_OK;
+ }
+#endif
+ if (code != TCL_OK) {
+ return TCL_ERROR;
+ }
+ errno = 0;
+ return CheckDoubleResult(interp, (*func)(d));
+}
+
+static int
+CheckDoubleResult(
+ Tcl_Interp *interp,
+ double dResult)
+{
+#ifndef ACCEPT_NAN
+ if (TclIsNaN(dResult)) {
+ TclExprFloatError(interp, dResult);
+ return TCL_ERROR;
+ }
+#endif
+ if ((errno == ERANGE) && ((dResult == 0.0) || TclIsInfinite(dResult))) {
+ /*
+ * When ERANGE signals under/overflow, just accept 0.0 or +/-Inf
+ */
+ } else if (errno != 0) {
+ /*
+ * Report other errno values as errors.
+ */
+
+ TclExprFloatError(interp, dResult);
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(dResult));
+ return TCL_OK;
+}
+
+static int
+ExprBinaryFunc(
+ ClientData clientData, /* Contains the address of a function that
+ * takes two double arguments and returns a
+ * double result. */
+ Tcl_Interp *interp, /* The interpreter in which to execute the
+ * function. */
+ int objc, /* Actual parameter count. */
+ Tcl_Obj *const *objv) /* Parameter vector. */
+{
+ int code;
+ double d1, d2;
+ double (*func)(double, double) = (double (*)(double, double)) clientData;
+
+ if (objc != 3) {
+ MathFuncWrongNumArgs(interp, 3, objc, objv);
+ return TCL_ERROR;
+ }
+ code = Tcl_GetDoubleFromObj(interp, objv[1], &d1);
+#ifdef ACCEPT_NAN
+ if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) {
+ d1 = objv[1]->internalRep.doubleValue;
+ Tcl_ResetResult(interp);
+ code = TCL_OK;
+ }
+#endif
+ if (code != TCL_OK) {
+ return TCL_ERROR;
+ }
+ code = Tcl_GetDoubleFromObj(interp, objv[2], &d2);
+#ifdef ACCEPT_NAN
+ if ((code != TCL_OK) && (objv[2]->typePtr == &tclDoubleType)) {
+ d2 = objv[2]->internalRep.doubleValue;
+ Tcl_ResetResult(interp);
+ code = TCL_OK;
+ }
+#endif
+ if (code != TCL_OK) {
+ return TCL_ERROR;
+ }
+ errno = 0;
+ return CheckDoubleResult(interp, (*func)(d1, d2));
+}
+
+static int
+ExprAbsFunc(
+ ClientData clientData, /* Ignored. */
+ Tcl_Interp *interp, /* The interpreter in which to execute the
+ * function. */
+ int objc, /* Actual parameter count. */
+ Tcl_Obj *const *objv) /* Parameter vector. */
+{
+ ClientData ptr;
+ int type;
+ mp_int big;
+
+ if (objc != 2) {
+ MathFuncWrongNumArgs(interp, 2, objc, objv);
+ return TCL_ERROR;
+ }
+
+ if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (type == TCL_NUMBER_LONG) {
+ long l = *((const long *) ptr);
+
+ if (l > (long)0) {
+ goto unChanged;
+ } else if (l == (long)0) {
+ const char *string = objv[1]->bytes;
+ if (string) {
+ while (*string != '0') {
+ if (*string == '-') {
+ Tcl_SetObjResult(interp, Tcl_NewLongObj(0));
+ return TCL_OK;
+ }
+ string++;
+ }
+ }
+ goto unChanged;
+ } else if (l == LONG_MIN) {
+ TclBNInitBignumFromLong(&big, l);
+ goto tooLarge;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewLongObj(-l));
+ return TCL_OK;
+ }
+
+ if (type == TCL_NUMBER_DOUBLE) {
+ double d = *((const double *) ptr);
+ static const double poszero = 0.0;
+
+ /* We need to distinguish here between positive 0.0 and
+ * negative -0.0, see Bug ID #2954959.
+ */
+ if (d == -0.0) {
+ if (!memcmp(&d, &poszero, sizeof(double))) {
+ goto unChanged;
+ }
+ } else {
+ if (d > -0.0) {
+ goto unChanged;
+ }
+ }
+ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(-d));
+ return TCL_OK;
+ }
+
+#ifndef NO_WIDE_TYPE
+ if (type == TCL_NUMBER_WIDE) {
+ Tcl_WideInt w = *((const Tcl_WideInt *) ptr);
+
+ if (w >= (Tcl_WideInt)0) {
+ goto unChanged;
+ }
+ if (w == LLONG_MIN) {
+ TclBNInitBignumFromWideInt(&big, w);
+ goto tooLarge;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-w));
+ return TCL_OK;
+ }
+#endif
+
+ if (type == TCL_NUMBER_BIG) {
+ /* TODO: const correctness ? */
+ if (mp_cmp_d((mp_int *) ptr, 0) == MP_LT) {
+ Tcl_GetBignumFromObj(NULL, objv[1], &big);
+ tooLarge:
+ mp_neg(&big, &big);
+ Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big));
+ } else {
+ unChanged:
+ Tcl_SetObjResult(interp, objv[1]);
+ }
+ return TCL_OK;
+ }
+
+ if (type == TCL_NUMBER_NAN) {
+#ifdef ACCEPT_NAN
+ Tcl_SetObjResult(interp, objv[1]);
+ return TCL_OK;
+#else
+ double d;
+ Tcl_GetDoubleFromObj(interp, objv[1], &d);
+ return TCL_ERROR;
+#endif
+ }
+ return TCL_OK;
+}
+
+static int
+ExprBoolFunc(
+ ClientData clientData, /* Ignored. */
+ Tcl_Interp *interp, /* The interpreter in which to execute the
+ * function. */
+ int objc, /* Actual parameter count. */
+ Tcl_Obj *const *objv) /* Actual parameter vector. */
+{
+ int value;
+
+ if (objc != 2) {
+ MathFuncWrongNumArgs(interp, 2, objc, objv);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetBooleanFromObj(interp, objv[1], &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value));
+ return TCL_OK;
+}
+
+static int
+ExprDoubleFunc(
+ ClientData clientData, /* Ignored. */
+ Tcl_Interp *interp, /* The interpreter in which to execute the
+ * function. */
+ int objc, /* Actual parameter count. */
+ Tcl_Obj *const *objv) /* Actual parameter vector. */
+{
+ double dResult;
+ if (objc != 2) {
+ MathFuncWrongNumArgs(interp, 2, objc, objv);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetDoubleFromObj(interp, objv[1], &dResult) != TCL_OK) {
+#ifdef ACCEPT_NAN
+ if (objv[1]->typePtr == &tclDoubleType) {
+ Tcl_SetObjResult(interp, objv[1]);
+ return TCL_OK;
+ }
+#endif
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(dResult));
+ return TCL_OK;
+}
+
+static int
+ExprEntierFunc(
+ ClientData clientData, /* Ignored. */
+ Tcl_Interp *interp, /* The interpreter in which to execute the
+ * function. */
+ int objc, /* Actual parameter count. */
+ Tcl_Obj *const *objv) /* Actual parameter vector. */
+{
+ double d;
+ int type;
+ ClientData ptr;
+
+ if (objc != 2) {
+ MathFuncWrongNumArgs(interp, 2, objc, objv);
+ return TCL_ERROR;
+ }
+ if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (type == TCL_NUMBER_DOUBLE) {
+ d = *((const double *) ptr);
+ if ((d >= (double)LONG_MAX) || (d <= (double)LONG_MIN)) {
+ mp_int big;
+
+ if (Tcl_InitBignumFromDouble(interp, d, &big) != TCL_OK) {
+ /* Infinity */
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big));
+ return TCL_OK;
+ } else {
+ long result = (long) d;
+
+ Tcl_SetObjResult(interp, Tcl_NewLongObj(result));
+ return TCL_OK;
+ }
+ }
+
+ if (type != TCL_NUMBER_NAN) {
+ /*
+ * All integers are already of integer type.
+ */
+
+ Tcl_SetObjResult(interp, objv[1]);
+ return TCL_OK;
+ }
+
+ /*
+ * Get the error message for NaN.
+ */
+
+ Tcl_GetDoubleFromObj(interp, objv[1], &d);
+ return TCL_ERROR;
+}
+
+static int
+ExprIntFunc(
+ ClientData clientData, /* Ignored. */
+ Tcl_Interp *interp, /* The interpreter in which to execute the
+ * function. */
+ int objc, /* Actual parameter count. */
+ Tcl_Obj *const *objv) /* Actual parameter vector. */
+{
+ long iResult;
+ Tcl_Obj *objPtr;
+ if (ExprEntierFunc(NULL, interp, objc, objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ objPtr = Tcl_GetObjResult(interp);
+ if (TclGetLongFromObj(NULL, objPtr, &iResult) != TCL_OK) {
+ /*
+ * Truncate the bignum; keep only bits in long range.
+ */
+
+ mp_int big;
+
+ Tcl_GetBignumFromObj(NULL, objPtr, &big);
+ mp_mod_2d(&big, (int) CHAR_BIT * sizeof(long), &big);
+ objPtr = Tcl_NewBignumObj(&big);
+ Tcl_IncrRefCount(objPtr);
+ TclGetLongFromObj(NULL, objPtr, &iResult);
+ Tcl_DecrRefCount(objPtr);
+ }
+ Tcl_SetObjResult(interp, Tcl_NewLongObj(iResult));
+ return TCL_OK;
+}
+
+static int
+ExprWideFunc(
+ ClientData clientData, /* Ignored. */
+ Tcl_Interp *interp, /* The interpreter in which to execute the
+ * function. */
+ int objc, /* Actual parameter count. */
+ Tcl_Obj *const *objv) /* Actual parameter vector. */
+{
+ Tcl_WideInt wResult;
+ Tcl_Obj *objPtr;
+ if (ExprEntierFunc(NULL, interp, objc, objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ objPtr = Tcl_GetObjResult(interp);
+ if (Tcl_GetWideIntFromObj(NULL, objPtr, &wResult) != TCL_OK) {
+ /*
+ * Truncate the bignum; keep only bits in wide int range.
+ */
+
+ mp_int big;
+
+ Tcl_GetBignumFromObj(NULL, objPtr, &big);
+ mp_mod_2d(&big, (int) CHAR_BIT * sizeof(Tcl_WideInt), &big);
+ objPtr = Tcl_NewBignumObj(&big);
+ Tcl_IncrRefCount(objPtr);
+ Tcl_GetWideIntFromObj(NULL, objPtr, &wResult);
+ Tcl_DecrRefCount(objPtr);
+ }
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(wResult));
+ return TCL_OK;
+}
+
+static int
+ExprRandFunc(
+ ClientData clientData, /* Ignored. */
+ Tcl_Interp *interp, /* The interpreter in which to execute the
+ * function. */
+ int objc, /* Actual parameter count. */
+ Tcl_Obj *const *objv) /* Actual parameter vector. */
+{
+ Interp *iPtr = (Interp *) interp;
+ double dResult;
+ long tmp; /* Algorithm assumes at least 32 bits. Only
+ * long guarantees that. See below. */
+ Tcl_Obj *oResult;
+
+ if (objc != 1) {
+ MathFuncWrongNumArgs(interp, 1, objc, objv);
+ return TCL_ERROR;
+ }
+
+ if (!(iPtr->flags & RAND_SEED_INITIALIZED)) {
+ iPtr->flags |= RAND_SEED_INITIALIZED;
+
+ /*
+ * Take into consideration the thread this interp is running in order
+ * to insure different seeds in different threads (bug #416643)
+ */
+
+ iPtr->randSeed = TclpGetClicks() + ((long)Tcl_GetCurrentThread()<<12);
+
+ /*
+ * Make sure 1 <= randSeed <= (2^31) - 2. See below.
+ */
+
+ iPtr->randSeed &= (unsigned long) 0x7fffffff;
+ if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) {
+ iPtr->randSeed ^= 123459876;
+ }
+ }
+
+ /*
+ * Generate the random number using the linear congruential generator
+ * defined by the following recurrence:
+ * seed = ( IA * seed ) mod IM
+ * where IA is 16807 and IM is (2^31) - 1. The recurrence maps a seed in
+ * the range [1, IM - 1] to a new seed in that same range. The recurrence
+ * maps IM to 0, and maps 0 back to 0, so those two values must not be
+ * allowed as initial values of seed.
+ *
+ * In order to avoid potential problems with integer overflow, the
+ * recurrence is implemented in terms of additional constants IQ and IR
+ * such that
+ * IM = IA*IQ + IR
+ * None of the operations in the implementation overflows a 32-bit signed
+ * integer, and the C type long is guaranteed to be at least 32 bits wide.
+ *
+ * For more details on how this algorithm works, refer to the following
+ * papers:
+ *
+ * S.K. Park & K.W. Miller, "Random number generators: good ones are hard
+ * to find," Comm ACM 31(10):1192-1201, Oct 1988
+ *
+ * W.H. Press & S.A. Teukolsky, "Portable random number generators,"
+ * Computers in Physics 6(5):522-524, Sep/Oct 1992.
+ */
+
+#define RAND_IA 16807
+#define RAND_IM 2147483647
+#define RAND_IQ 127773
+#define RAND_IR 2836
+#define RAND_MASK 123459876
+
+ tmp = iPtr->randSeed/RAND_IQ;
+ iPtr->randSeed = RAND_IA*(iPtr->randSeed - tmp*RAND_IQ) - RAND_IR*tmp;
+ if (iPtr->randSeed < 0) {
+ iPtr->randSeed += RAND_IM;
+ }
+
+ /*
+ * Since the recurrence keeps seed values in the range [1, RAND_IM - 1],
+ * dividing by RAND_IM yields a double in the range (0, 1).
+ */
+
+ dResult = iPtr->randSeed * (1.0/RAND_IM);
+
+ /*
+ * Push a Tcl object with the result.
+ */
+
+ TclNewDoubleObj(oResult, dResult);
+ Tcl_SetObjResult(interp, oResult);
+ return TCL_OK;
+}
+
+static int
+ExprRoundFunc(
+ ClientData clientData, /* Ignored. */
+ Tcl_Interp *interp, /* The interpreter in which to execute the
+ * function. */
+ int objc, /* Actual parameter count. */
+ Tcl_Obj *const *objv) /* Parameter vector. */
+{
+ double d;
+ ClientData ptr;
+ int type;
+
+ if (objc != 2) {
+ MathFuncWrongNumArgs(interp, 2, objc, objv);
+ return TCL_ERROR;
+ }
+
+ if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (type == TCL_NUMBER_DOUBLE) {
+ double fractPart, intPart;
+ long max = LONG_MAX, min = LONG_MIN;
+
+ fractPart = modf(*((const double *) ptr), &intPart);
+ if (fractPart <= -0.5) {
+ min++;
+ } else if (fractPart >= 0.5) {
+ max--;
+ }
+ if ((intPart >= (double)max) || (intPart <= (double)min)) {
+ mp_int big;
+
+ if (Tcl_InitBignumFromDouble(interp, intPart, &big) != TCL_OK) {
+ /* Infinity */
+ return TCL_ERROR;
+ }
+ if (fractPart <= -0.5) {
+ mp_sub_d(&big, 1, &big);
+ } else if (fractPart >= 0.5) {
+ mp_add_d(&big, 1, &big);
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big));
+ return TCL_OK;
+ } else {
+ long result = (long)intPart;
+
+ if (fractPart <= -0.5) {
+ result--;
+ } else if (fractPart >= 0.5) {
+ result++;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewLongObj(result));
+ return TCL_OK;
+ }
+ }
+
+ if (type != TCL_NUMBER_NAN) {
+ /*
+ * All integers are already rounded
+ */
+
+ Tcl_SetObjResult(interp, objv[1]);
+ return TCL_OK;
+ }
+
+ /*
+ * Get the error message for NaN.
+ */
+
+ Tcl_GetDoubleFromObj(interp, objv[1], &d);
+ return TCL_ERROR;
+}
+
+static int
+ExprSrandFunc(
+ ClientData clientData, /* Ignored. */
+ Tcl_Interp *interp, /* The interpreter in which to execute the
+ * function. */
+ int objc, /* Actual parameter count. */
+ Tcl_Obj *const *objv) /* Parameter vector. */
+{
+ Interp *iPtr = (Interp *) interp;
+ long i = 0; /* Initialized to avoid compiler warning. */
+
+ /*
+ * Convert argument and use it to reset the seed.
+ */
+
+ if (objc != 2) {
+ MathFuncWrongNumArgs(interp, 2, objc, objv);
+ return TCL_ERROR;
+ }
+
+ if (TclGetLongFromObj(NULL, objv[1], &i) != TCL_OK) {
+ Tcl_Obj *objPtr;
+ mp_int big;
+
+ if (Tcl_GetBignumFromObj(interp, objv[1], &big) != TCL_OK) {
+ /* TODO: more ::errorInfo here? or in caller? */
+ return TCL_ERROR;
+ }
+
+ mp_mod_2d(&big, (int) CHAR_BIT * sizeof(long), &big);
+ objPtr = Tcl_NewBignumObj(&big);
+ Tcl_IncrRefCount(objPtr);
+ TclGetLongFromObj(NULL, objPtr, &i);
+ Tcl_DecrRefCount(objPtr);
+ }
+
+ /*
+ * Reset the seed. Make sure 1 <= randSeed <= 2^31 - 2. See comments in
+ * ExprRandFunc() for more details.
+ */
+
+ iPtr->flags |= RAND_SEED_INITIALIZED;
+ iPtr->randSeed = i;
+ iPtr->randSeed &= (unsigned long) 0x7fffffff;
+ if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) {
+ iPtr->randSeed ^= 123459876;
+ }
+
+ /*
+ * To avoid duplicating the random number generation code we simply clean
+ * up our state and call the real random number function. That function
+ * will always succeed.
+ */
+
+ return ExprRandFunc(clientData, interp, 1, objv);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MathFuncWrongNumArgs --
+ *
+ * Generate an error message when a math function presents the wrong
+ * number of arguments.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * An error message is stored in the interpreter result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MathFuncWrongNumArgs(
+ Tcl_Interp *interp, /* Tcl interpreter */
+ int expected, /* Formal parameter count. */
+ int found, /* Actual parameter count. */
+ Tcl_Obj *const *objv) /* Actual parameter vector. */
+{
+ const char *name = Tcl_GetString(objv[0]);
+ const char *tail = name + strlen(name);
+
+ while (tail > name+1) {
+ --tail;
+ if (*tail == ':' && tail[-1] == ':') {
+ name = tail+1;
+ break;
+ }
+ }
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "too %s arguments for math function \"%s\"",
+ (found < expected ? "few" : "many"), name));
}
#ifdef USE_DTRACE
@@ -6767,7 +7005,7 @@ DTraceObjCmd(
ClientData dummy, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
- Tcl_Obj *CONST objv[]) /* Argument objects. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
if (TCL_DTRACE_TCL_PROBE_ENABLED()) {
char *a[10];
@@ -6781,6 +7019,60 @@ DTraceObjCmd(
}
return TCL_OK;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclDTraceInfo --
+ *
+ * Extract information from a TIP280 dict for use by DTrace probes.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclDTraceInfo(
+ Tcl_Obj *info,
+ char **args,
+ int *argsi)
+{
+ static Tcl_Obj *keys[7] = { NULL };
+ Tcl_Obj **k = keys, *val;
+ int i;
+
+ if (!*k) {
+ TclNewLiteralStringObj(keys[0], "cmd");
+ TclNewLiteralStringObj(keys[1], "type");
+ TclNewLiteralStringObj(keys[2], "proc");
+ TclNewLiteralStringObj(keys[3], "file");
+ TclNewLiteralStringObj(keys[4], "lambda");
+ TclNewLiteralStringObj(keys[5], "line");
+ TclNewLiteralStringObj(keys[6], "level");
+ }
+ for (i = 0; i < 4; i++) {
+ Tcl_DictObjGet(NULL, info, *k++, &val);
+ args[i] = val ? TclGetString(val) : NULL;
+ }
+ if (!args[2]) {
+ Tcl_DictObjGet(NULL, info, *k, &val);
+ args[2] = val ? TclGetString(val) : NULL;
+ }
+ k++;
+ for (i = 0; i < 2; i++) {
+ Tcl_DictObjGet(NULL, info, *k++, &val);
+ if (val) {
+ TclGetIntFromObj(NULL, val, &(argsi[i]));
+ } else {
+ argsi[i] = 0;
+ }
+ }
+}
TCL_DTRACE_DEBUG_LOG()
diff --git a/generic/tclBinary.c b/generic/tclBinary.c
index 8d258b3..90d392b 100644
--- a/generic/tclBinary.c
+++ b/generic/tclBinary.c
@@ -1,4 +1,4 @@
-/*
+/*
* tclBinary.c --
*
* This file contains the implementation of the "binary" Tcl built-in
@@ -7,12 +7,13 @@
* Copyright (c) 1997 by 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.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
+#include "tommath.h"
+
#include <math.h>
/*
@@ -24,21 +25,27 @@
#define BINARY_NOCOUNT -2 /* No count was specified in format. */
/*
- * The following defines the maximum number of different (integer)
- * numbers placed in the object cache by 'binary scan' before it bails
- * out and switches back to Plan A (creating a new object for each
- * value.) Theoretically, it would be possible to keep the cache
- * about for the values that are already in it, but that makes the
- * code slower in practise when overflow happens, and makes little
- * odds the rest of the time (as measured on my machine.) It is also
- * slower (on the sample I tried at least) to grow the cache to hold
- * all items we might want to put in it; presumably the extra cost of
- * managing the memory for the enlarged table outweighs the benefit
- * from allocating fewer objects. This is probably because as the
- * number of objects increases, the likelihood of reuse of any
- * particular one drops, and there is very little gain from larger
- * maximum cache sizes (the value below is chosen to allow caching to
- * work in full with conversion of bytes.) - DKF
+ * The following flags may be ORed together and returned by GetFormatSpec
+ */
+
+#define BINARY_SIGNED 0 /* Field to be read as signed data */
+#define BINARY_UNSIGNED 1 /* Field to be read as unsigned data */
+
+/*
+ * The following defines the maximum number of different (integer) numbers
+ * placed in the object cache by 'binary scan' before it bails out and
+ * switches back to Plan A (creating a new object for each value.)
+ * Theoretically, it would be possible to keep the cache about for the values
+ * that are already in it, but that makes the code slower in practise when
+ * overflow happens, and makes little odds the rest of the time (as measured
+ * on my machine.) It is also slower (on the sample I tried at least) to grow
+ * the cache to hold all items we might want to put in it; presumably the
+ * extra cost of managing the memory for the enlarged table outweighs the
+ * benefit from allocating fewer objects. This is probably because as the
+ * number of objects increases, the likelihood of reuse of any particular one
+ * drops, and there is very little gain from larger maximum cache sizes (the
+ * value below is chosen to allow caching to work in full with conversion of
+ * bytes.) - DKF
*/
#define BINARY_SCAN_MAX_CACHE 260
@@ -47,46 +54,46 @@
* Prototypes for local procedures defined in this file:
*/
-static void DupByteArrayInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
- Tcl_Obj *copyPtr));
-static int FormatNumber _ANSI_ARGS_((Tcl_Interp *interp, int type,
- Tcl_Obj *src, unsigned char **cursorPtr));
-static void CopyNumber _ANSI_ARGS_((CONST VOID *from, VOID *to,
- unsigned int length));
-static void FreeByteArrayInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr));
-static int GetFormatSpec _ANSI_ARGS_((char **formatPtr,
- char *cmdPtr, int *countPtr));
-static Tcl_Obj * ScanNumber _ANSI_ARGS_((unsigned char *buffer,
- int type, Tcl_HashTable **numberCachePtr));
-static int SetByteArrayFromAny _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
-static void UpdateStringOfByteArray _ANSI_ARGS_((Tcl_Obj *listPtr));
-static void DeleteScanNumberCache _ANSI_ARGS_((
- Tcl_HashTable *numberCachePtr));
+static void DupByteArrayInternalRep(Tcl_Obj *srcPtr,
+ Tcl_Obj *copyPtr);
+static int FormatNumber(Tcl_Interp *interp, int type,
+ Tcl_Obj *src, unsigned char **cursorPtr);
+static void FreeByteArrayInternalRep(Tcl_Obj *objPtr);
+static int GetFormatSpec(char **formatPtr, char *cmdPtr,
+ int *countPtr, int *flagsPtr);
+static Tcl_Obj * ScanNumber(unsigned char *buffer, int type,
+ int flags, Tcl_HashTable **numberCachePtr);
+static int SetByteArrayFromAny(Tcl_Interp *interp,
+ Tcl_Obj *objPtr);
+static void UpdateStringOfByteArray(Tcl_Obj *listPtr);
+static void DeleteScanNumberCache(Tcl_HashTable *numberCachePtr);
+static int NeedReversing(int format);
+static void CopyNumber(const void *from, void *to,
+ unsigned int length, int type);
/*
- * The following object type represents an array of bytes. An array of
- * bytes is not equivalent to an internationalized string. Conceptually, a
- * string is an array of 16-bit quantities organized as a sequence of properly
- * formed UTF-8 characters, while a ByteArray is an array of 8-bit quantities.
+ * The following object type represents an array of bytes. An array of bytes
+ * is not equivalent to an internationalized string. Conceptually, a string is
+ * an array of 16-bit quantities organized as a sequence of properly formed
+ * UTF-8 characters, while a ByteArray is an array of 8-bit quantities.
* Accessor functions are provided to convert a ByteArray to a String or a
- * String to a ByteArray. Two or more consecutive bytes in an array of bytes
+ * String to a ByteArray. Two or more consecutive bytes in an array of bytes
* may look like a single UTF-8 character if the array is casually treated as
- * a string. But obtaining the String from a ByteArray is guaranteed to
- * produced properly formed UTF-8 sequences so that there is a one-to-one
- * map between bytes and characters.
+ * a string. But obtaining the String from a ByteArray is guaranteed to
+ * produced properly formed UTF-8 sequences so that there is a one-to-one map
+ * between bytes and characters.
*
* Converting a ByteArray to a String proceeds by casting each byte in the
* array to a 16-bit quantity, treating that number as a Unicode character,
- * and storing the UTF-8 version of that Unicode character in the String.
- * For ByteArrays consisting entirely of values 1..127, the corresponding
- * String representation is the same as the ByteArray representation.
+ * and storing the UTF-8 version of that Unicode character in the String. For
+ * ByteArrays consisting entirely of values 1..127, the corresponding String
+ * representation is the same as the ByteArray representation.
*
* Converting a String to a ByteArray proceeds by getting the Unicode
- * representation of each character in the String, casting it to a
- * byte by truncating the upper 8 bits, and then storing the byte in the
- * ByteArray. Converting from ByteArray to String and back to ByteArray
- * is not lossy, but converting an arbitrary String to a ByteArray may be.
+ * representation of each character in the String, casting it to a byte by
+ * truncating the upper 8 bits, and then storing the byte in the ByteArray.
+ * Converting from ByteArray to String and back to ByteArray is not lossy, but
+ * converting an arbitrary String to a ByteArray may be.
*/
Tcl_ObjType tclByteArrayType = {
@@ -98,10 +105,10 @@ Tcl_ObjType tclByteArrayType = {
};
/*
- * The following structure is the internal rep for a ByteArray object.
- * Keeps track of how much memory has been used and how much has been
- * allocated for the byte array to enable growing and shrinking of the
- * ByteArray object with fewer mallocs.
+ * The following structure is the internal rep for a ByteArray object. Keeps
+ * track of how much memory has been used and how much has been allocated for
+ * the byte array to enable growing and shrinking of the ByteArray object with
+ * fewer mallocs.
*/
typedef struct ByteArray {
@@ -109,12 +116,12 @@ typedef struct ByteArray {
* array. */
int allocated; /* The amount of space actually allocated
* minus 1 byte. */
- unsigned char bytes[4]; /* The array of bytes. The actual size of
- * this field depends on the 'allocated' field
+ unsigned char bytes[4]; /* The array of bytes. The actual size of this
+ * field depends on the 'allocated' field
* above. */
} ByteArray;
-#define BYTEARRAY_SIZE(len) \
+#define BYTEARRAY_SIZE(len) \
((unsigned) (sizeof(ByteArray) - 4 + (len)))
#define GET_BYTEARRAY(objPtr) \
((ByteArray *) (objPtr)->internalRep.otherValuePtr)
@@ -123,34 +130,32 @@ typedef struct ByteArray {
/*
- *---------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*
* Tcl_NewByteArrayObj --
*
- * This procedure is creates a new ByteArray object and initializes
- * it from the given array of bytes.
+ * This procedure is creates a new ByteArray object and initializes it
+ * from the given array of bytes.
*
* Results:
- * The newly create object is returned. This object will have no
- * initial string representation. The returned object has a ref count
- * of 0.
+ * The newly create object is returned. This object will have no initial
+ * string representation. The returned object has a ref count of 0.
*
* Side effects:
* Memory allocated for new object and copy of byte array argument.
*
- *---------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*/
#ifdef TCL_MEM_DEBUG
#undef Tcl_NewByteArrayObj
-
Tcl_Obj *
-Tcl_NewByteArrayObj(bytes, length)
- CONST unsigned char *bytes; /* The array of bytes used to initialize
- * the new object. */
- int length; /* Length of the array of bytes, which must
- * be >= 0. */
+Tcl_NewByteArrayObj(
+ const unsigned char *bytes, /* The array of bytes used to initialize the
+ * new object. */
+ int length) /* Length of the array of bytes, which must be
+ * >= 0. */
{
return Tcl_DbNewByteArrayObj(bytes, length, "unknown", 0);
}
@@ -158,11 +163,11 @@ Tcl_NewByteArrayObj(bytes, length)
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
-Tcl_NewByteArrayObj(bytes, length)
- CONST unsigned char *bytes; /* The array of bytes used to initialize
- * the new object. */
- int length; /* Length of the array of bytes, which must
- * be >= 0. */
+Tcl_NewByteArrayObj(
+ const unsigned char *bytes, /* The array of bytes used to initialize the
+ * new object. */
+ int length) /* Length of the array of bytes, which must be
+ * >= 0. */
{
Tcl_Obj *objPtr;
@@ -173,7 +178,7 @@ Tcl_NewByteArrayObj(bytes, length)
#endif /* TCL_MEM_DEBUG */
/*
- *---------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*
* Tcl_DbNewByteArrayObj --
*
@@ -188,28 +193,27 @@ Tcl_NewByteArrayObj(bytes, length)
* result of calling Tcl_NewByteArrayObj.
*
* Results:
- * The newly create object is returned. This object will have no
- * initial string representation. The returned object has a ref count
- * of 0.
+ * The newly create object is returned. This object will have no initial
+ * string representation. The returned object has a ref count of 0.
*
* Side effects:
* Memory allocated for new object and copy of byte array argument.
*
- *---------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*/
#ifdef TCL_MEM_DEBUG
Tcl_Obj *
-Tcl_DbNewByteArrayObj(bytes, length, file, line)
- CONST unsigned char *bytes; /* The array of bytes used to initialize
- * the new object. */
- int length; /* Length of the array of bytes, which must
- * be >= 0. */
- CONST char *file; /* The name of the source file calling this
+Tcl_DbNewByteArrayObj(
+ const unsigned char *bytes, /* The array of bytes used to initialize the
+ * new object. */
+ int length, /* Length of the array of bytes, which must be
+ * >= 0. */
+ const char *file, /* The name of the source file calling this
* procedure; used for debugging. */
- int line; /* Line number in the source file; used
- * for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
Tcl_Obj *objPtr;
@@ -221,15 +225,15 @@ Tcl_DbNewByteArrayObj(bytes, length, file, line)
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
-Tcl_DbNewByteArrayObj(bytes, length, file, line)
- CONST unsigned char *bytes; /* The array of bytes used to initialize
- * the new object. */
- int length; /* Length of the array of bytes, which must
- * be >= 0. */
- CONST char *file; /* The name of the source file calling this
+Tcl_DbNewByteArrayObj(
+ const unsigned char *bytes, /* The array of bytes used to initialize the
+ * new object. */
+ int length, /* Length of the array of bytes, which must be
+ * >= 0. */
+ const char *file, /* The name of the source file calling this
* procedure; used for debugging. */
- int line; /* Line number in the source file; used
- * for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
return Tcl_NewByteArrayObj(bytes, length);
}
@@ -247,36 +251,32 @@ Tcl_DbNewByteArrayObj(bytes, length, file, line)
* None.
*
* Side effects:
- * The object's old string rep and internal rep is freed.
- * Memory allocated for copy of byte array argument.
+ * The object's old string rep and internal rep is freed. Memory
+ * allocated for copy of byte array argument.
*
*----------------------------------------------------------------------
*/
void
-Tcl_SetByteArrayObj(objPtr, bytes, length)
- Tcl_Obj *objPtr; /* Object to initialize as a ByteArray. */
- CONST unsigned char *bytes; /* The array of bytes to use as the new
+Tcl_SetByteArrayObj(
+ Tcl_Obj *objPtr, /* Object to initialize as a ByteArray. */
+ const unsigned char *bytes, /* The array of bytes to use as the new
* value. */
- int length; /* Length of the array of bytes, which must
- * be >= 0. */
+ int length) /* Length of the array of bytes, which must be
+ * >= 0. */
{
- Tcl_ObjType *typePtr;
ByteArray *byteArrayPtr;
if (Tcl_IsShared(objPtr)) {
- panic("Tcl_SetByteArrayObj called with shared object");
- }
- typePtr = objPtr->typePtr;
- if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
- (*typePtr->freeIntRepProc)(objPtr);
+ Tcl_Panic("%s called with shared object", "Tcl_SetByteArrayObj");
}
+ TclFreeIntRep(objPtr);
Tcl_InvalidateStringRep(objPtr);
byteArrayPtr = (ByteArray *) ckalloc(BYTEARRAY_SIZE(length));
byteArrayPtr->used = length;
byteArrayPtr->allocated = length;
- memcpy((VOID *) byteArrayPtr->bytes, (VOID *) bytes, (size_t) length);
+ memcpy(byteArrayPtr->bytes, bytes, (size_t) length);
objPtr->typePtr = &tclByteArrayType;
SET_BYTEARRAY(objPtr, byteArrayPtr);
@@ -287,28 +287,30 @@ Tcl_SetByteArrayObj(objPtr, bytes, length)
*
* Tcl_GetByteArrayFromObj --
*
- * Attempt to get the array of bytes from the Tcl object. If the
- * object is not already a ByteArray object, an attempt will be
- * made to convert it to one.
+ * Attempt to get the array of bytes from the Tcl object. If the object
+ * is not already a ByteArray object, an attempt will be made to convert
+ * it to one.
*
* Results:
* Pointer to array of bytes representing the ByteArray object.
*
* Side effects:
- * Frees old internal rep. Allocates memory for new internal rep.
+ * Frees old internal rep. Allocates memory for new internal rep.
*
*----------------------------------------------------------------------
*/
unsigned char *
-Tcl_GetByteArrayFromObj(objPtr, lengthPtr)
- Tcl_Obj *objPtr; /* The ByteArray object. */
- int *lengthPtr; /* If non-NULL, filled with length of the
+Tcl_GetByteArrayFromObj(
+ Tcl_Obj *objPtr, /* The ByteArray object. */
+ int *lengthPtr) /* If non-NULL, filled with length of the
* array of bytes in the ByteArray object. */
{
ByteArray *baPtr;
-
- SetByteArrayFromAny(NULL, objPtr);
+
+ if (objPtr->typePtr != &tclByteArrayType) {
+ SetByteArrayFromAny(NULL, objPtr);
+ }
baPtr = GET_BYTEARRAY(objPtr);
if (lengthPtr != NULL) {
@@ -322,32 +324,32 @@ Tcl_GetByteArrayFromObj(objPtr, lengthPtr)
*
* Tcl_SetByteArrayLength --
*
- * This procedure changes the length of the byte array for this
- * object. Once the caller has set the length of the array, it
- * is acceptable to directly modify the bytes in the array up until
- * Tcl_GetStringFromObj() has been called on this object.
+ * This procedure changes the length of the byte array for this object.
+ * Once the caller has set the length of the array, it is acceptable to
+ * directly modify the bytes in the array up until Tcl_GetStringFromObj()
+ * has been called on this object.
*
* Results:
* The new byte array of the specified length.
*
* Side effects:
- * Allocates enough memory for an array of bytes of the requested
- * size. When growing the array, the old array is copied to the
- * new array; new bytes are undefined. When shrinking, the
- * old array is truncated to the specified length.
+ * Allocates enough memory for an array of bytes of the requested size.
+ * When growing the array, the old array is copied to the new array; new
+ * bytes are undefined. When shrinking, the old array is truncated to the
+ * specified length.
*
- *---------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*/
unsigned char *
-Tcl_SetByteArrayLength(objPtr, length)
- Tcl_Obj *objPtr; /* The ByteArray object. */
- int length; /* New length for internal byte array. */
+Tcl_SetByteArrayLength(
+ Tcl_Obj *objPtr, /* The ByteArray object. */
+ int length) /* New length for internal byte array. */
{
- ByteArray *byteArrayPtr, *newByteArrayPtr;
-
+ ByteArray *byteArrayPtr;
+
if (Tcl_IsShared(objPtr)) {
- panic("Tcl_SetObjLength called with shared object");
+ Tcl_Panic("%s called with shared object", "Tcl_SetByteArrayLength");
}
if (objPtr->typePtr != &tclByteArrayType) {
SetByteArrayFromAny(NULL, objPtr);
@@ -355,13 +357,9 @@ Tcl_SetByteArrayLength(objPtr, length)
byteArrayPtr = GET_BYTEARRAY(objPtr);
if (length > byteArrayPtr->allocated) {
- newByteArrayPtr = (ByteArray *) ckalloc(BYTEARRAY_SIZE(length));
- newByteArrayPtr->used = length;
- newByteArrayPtr->allocated = length;
- memcpy((VOID *) newByteArrayPtr->bytes,
- (VOID *) byteArrayPtr->bytes, (size_t) byteArrayPtr->used);
- ckfree((char *) byteArrayPtr);
- byteArrayPtr = newByteArrayPtr;
+ byteArrayPtr = (ByteArray *) ckrealloc(
+ (char *) byteArrayPtr, BYTEARRAY_SIZE(length));
+ byteArrayPtr->allocated = length;
SET_BYTEARRAY(objPtr, byteArrayPtr);
}
Tcl_InvalidateStringRep(objPtr);
@@ -370,7 +368,7 @@ Tcl_SetByteArrayLength(objPtr, length)
}
/*
- *---------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*
* SetByteArrayFromAny --
*
@@ -382,24 +380,22 @@ Tcl_SetByteArrayLength(objPtr, length)
* Side effects:
* A ByteArray object is stored as the internal rep of objPtr.
*
- *---------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*/
static int
-SetByteArrayFromAny(interp, objPtr)
- Tcl_Interp *interp; /* Not used. */
- Tcl_Obj *objPtr; /* The object to convert to type ByteArray. */
+SetByteArrayFromAny(
+ Tcl_Interp *interp, /* Not used. */
+ Tcl_Obj *objPtr) /* The object to convert to type ByteArray. */
{
- Tcl_ObjType *typePtr;
int length;
char *src, *srcEnd;
unsigned char *dst;
ByteArray *byteArrayPtr;
Tcl_UniChar ch;
-
- typePtr = objPtr->typePtr;
- if (typePtr != &tclByteArrayType) {
- src = Tcl_GetStringFromObj(objPtr, &length);
+
+ if (objPtr->typePtr != &tclByteArrayType) {
+ src = TclGetStringFromObj(objPtr, &length);
srcEnd = src + length;
byteArrayPtr = (ByteArray *) ckalloc(BYTEARRAY_SIZE(length));
@@ -411,9 +407,7 @@ SetByteArrayFromAny(interp, objPtr)
byteArrayPtr->used = dst - byteArrayPtr->bytes;
byteArrayPtr->allocated = length;
- if ((typePtr != NULL) && (typePtr->freeIntRepProc) != NULL) {
- (*typePtr->freeIntRepProc)(objPtr);
- }
+ TclFreeIntRep(objPtr);
objPtr->typePtr = &tclByteArrayType;
SET_BYTEARRAY(objPtr, byteArrayPtr);
}
@@ -432,26 +426,26 @@ SetByteArrayFromAny(interp, objPtr)
* None.
*
* Side effects:
- * Frees memory.
+ * Frees memory.
*
*----------------------------------------------------------------------
*/
static void
-FreeByteArrayInternalRep(objPtr)
- Tcl_Obj *objPtr; /* Object with internal rep to free. */
+FreeByteArrayInternalRep(
+ Tcl_Obj *objPtr) /* Object with internal rep to free. */
{
ckfree((char *) GET_BYTEARRAY(objPtr));
+ objPtr->typePtr = NULL;
}
/*
- *---------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*
* DupByteArrayInternalRep --
*
- * Initialize the internal representation of a ByteArray Tcl_Obj
- * to a copy of the internal representation of an existing ByteArray
- * object.
+ * Initialize the internal representation of a ByteArray Tcl_Obj to a
+ * copy of the internal representation of an existing ByteArray object.
*
* Results:
* None.
@@ -459,16 +453,16 @@ FreeByteArrayInternalRep(objPtr)
* Side effects:
* Allocates memory.
*
- *---------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*/
static void
-DupByteArrayInternalRep(srcPtr, copyPtr)
- Tcl_Obj *srcPtr; /* Object with internal rep to copy. */
- Tcl_Obj *copyPtr; /* Object with internal rep to set. */
+DupByteArrayInternalRep(
+ Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
+ Tcl_Obj *copyPtr) /* Object with internal rep to set. */
{
int length;
- ByteArray *srcArrayPtr, *copyArrayPtr;
+ ByteArray *srcArrayPtr, *copyArrayPtr;
srcArrayPtr = GET_BYTEARRAY(srcPtr);
length = srcArrayPtr->used;
@@ -476,38 +470,37 @@ DupByteArrayInternalRep(srcPtr, copyPtr)
copyArrayPtr = (ByteArray *) ckalloc(BYTEARRAY_SIZE(length));
copyArrayPtr->used = length;
copyArrayPtr->allocated = length;
- memcpy((VOID *) copyArrayPtr->bytes, (VOID *) srcArrayPtr->bytes,
- (size_t) length);
+ memcpy(copyArrayPtr->bytes, srcArrayPtr->bytes, (size_t) length);
SET_BYTEARRAY(copyPtr, copyArrayPtr);
copyPtr->typePtr = &tclByteArrayType;
}
/*
- *---------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*
* UpdateStringOfByteArray --
*
- * Update the string representation for a ByteArray data object.
- * Note: This procedure does not invalidate an existing old string rep
- * so storage will be lost if this has not already been done.
+ * Update the string representation for a ByteArray data object. Note:
+ * This procedure does not invalidate an existing old string rep so
+ * storage will be lost if this has not already been done.
*
* Results:
* None.
*
* Side effects:
- * The object's string is set to a valid string that results from
- * the ByteArray-to-string conversion.
+ * The object's string is set to a valid string that results from the
+ * ByteArray-to-string conversion.
*
- * The object becomes a string object -- the internal rep is
- * discarded and the typePtr becomes NULL.
+ * The object becomes a string object -- the internal rep is discarded
+ * and the typePtr becomes NULL.
*
- *---------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*/
static void
-UpdateStringOfByteArray(objPtr)
- Tcl_Obj *objPtr; /* ByteArray object whose string rep to
+UpdateStringOfByteArray(
+ Tcl_Obj *objPtr) /* ByteArray object whose string rep to
* update. */
{
int i, length, size;
@@ -522,20 +515,23 @@ UpdateStringOfByteArray(objPtr)
/*
* How much space will string rep need?
*/
-
+
size = length;
- for (i = 0; i < length; i++) {
+ for (i = 0; i < length && size >= 0; i++) {
if ((src[i] == 0) || (src[i] > 127)) {
size++;
}
}
+ if (size < 0) {
+ Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
+ }
dst = (char *) ckalloc((unsigned) (size + 1));
objPtr->bytes = dst;
objPtr->length = size;
if (size == length) {
- memcpy((VOID *) dst, (VOID *) src, (size_t) size);
+ memcpy(dst, src, (size_t) size);
dst[size] = '\0';
} else {
for (i = 0; i < length; i++) {
@@ -562,11 +558,11 @@ UpdateStringOfByteArray(objPtr)
*/
int
-Tcl_BinaryObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_BinaryObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
int arg; /* Index of next argument to consume. */
int value = 0; /* Current integer value to be packed.
@@ -574,19 +570,21 @@ Tcl_BinaryObjCmd(dummy, interp, objc, objv)
char cmd; /* Current format character. */
int count; /* Count associated with current format
* character. */
+ int flags; /* Format field flags */
char *format; /* Pointer to current position in format
* string. */
- Tcl_Obj *resultPtr; /* Object holding result buffer. */
+ Tcl_Obj *resultPtr = NULL; /* Object holding result buffer. */
unsigned char *buffer; /* Start of result buffer. */
unsigned char *cursor; /* Current position within result buffer. */
unsigned char *maxPos; /* Greatest position within result buffer that
* cursor has visited.*/
- char *errorString, *errorValue, *str;
+ const char *errorString;
+ char *errorValue, *str;
int offset, size, length, index;
- static CONST char *options[] = {
- "format", "scan", NULL
+ static const char *options[] = {
+ "format", "scan", NULL
};
- enum options {
+ enum options {
BINARY_FORMAT, BINARY_SCAN
};
@@ -601,760 +599,765 @@ Tcl_BinaryObjCmd(dummy, interp, objc, objv)
}
switch ((enum options) index) {
- case BINARY_FORMAT: {
- if (objc < 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "formatString ?arg arg ...?");
- return TCL_ERROR;
- }
+ case BINARY_FORMAT:
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "formatString ?arg arg ...?");
+ return TCL_ERROR;
+ }
- /*
- * To avoid copying the data, we format the string in two passes.
- * The first pass computes the size of the output buffer. The
- * second pass places the formatted data into the buffer.
- */
+ /*
+ * To avoid copying the data, we format the string in two passes. The
+ * first pass computes the size of the output buffer. The second pass
+ * places the formatted data into the buffer.
+ */
- format = Tcl_GetString(objv[2]);
- arg = 3;
- offset = 0;
- length = 0;
- while (*format != '\0') {
- str = format;
- if (!GetFormatSpec(&format, &cmd, &count)) {
- break;
+ format = TclGetString(objv[2]);
+ arg = 3;
+ offset = 0;
+ length = 0;
+ while (*format != '\0') {
+ str = format;
+ flags = 0;
+ if (!GetFormatSpec(&format, &cmd, &count, &flags)) {
+ break;
+ }
+ switch (cmd) {
+ case 'a':
+ case 'A':
+ case 'b':
+ case 'B':
+ case 'h':
+ case 'H':
+ /*
+ * For string-type specifiers, the count corresponds to the
+ * number of bytes in a single argument.
+ */
+
+ if (arg >= objc) {
+ goto badIndex;
+ }
+ if (count == BINARY_ALL) {
+ Tcl_GetByteArrayFromObj(objv[arg], &count);
+ } else if (count == BINARY_NOCOUNT) {
+ count = 1;
+ }
+ arg++;
+ if (cmd == 'a' || cmd == 'A') {
+ offset += count;
+ } else if (cmd == 'b' || cmd == 'B') {
+ offset += (count + 7) / 8;
+ } else {
+ offset += (count + 1) / 2;
+ }
+ break;
+ case 'c':
+ size = 1;
+ goto doNumbers;
+ case 't':
+ case 's':
+ case 'S':
+ size = 2;
+ goto doNumbers;
+ case 'n':
+ case 'i':
+ case 'I':
+ size = 4;
+ goto doNumbers;
+ case 'm':
+ case 'w':
+ case 'W':
+ size = 8;
+ goto doNumbers;
+ case 'r':
+ case 'R':
+ case 'f':
+ size = sizeof(float);
+ goto doNumbers;
+ case 'q':
+ case 'Q':
+ case 'd':
+ size = sizeof(double);
+
+ doNumbers:
+ if (arg >= objc) {
+ goto badIndex;
}
- switch (cmd) {
- case 'a':
- case 'A':
- case 'b':
- case 'B':
- case 'h':
- case 'H': {
- /*
- * For string-type specifiers, the count corresponds
- * to the number of bytes in a single argument.
- */
-
- if (arg >= objc) {
- goto badIndex;
- }
- if (count == BINARY_ALL) {
- Tcl_GetByteArrayFromObj(objv[arg], &count);
- } else if (count == BINARY_NOCOUNT) {
- count = 1;
- }
- arg++;
- if (cmd == 'a' || cmd == 'A') {
- offset += count;
- } else if (cmd == 'b' || cmd == 'B') {
- offset += (count + 7) / 8;
- } else {
- offset += (count + 1) / 2;
- }
- break;
- }
- case 'c': {
- size = 1;
- goto doNumbers;
- }
- case 's':
- case 'S': {
- size = 2;
- goto doNumbers;
- }
- case 'i':
- case 'I': {
- size = 4;
- goto doNumbers;
- }
- case 'w':
- case 'W': {
- size = 8;
- goto doNumbers;
- }
- case 'f': {
- size = sizeof(float);
- goto doNumbers;
- }
- case 'd': {
- size = sizeof(double);
-
- doNumbers:
- if (arg >= objc) {
- goto badIndex;
- }
- /*
- * For number-type specifiers, the count corresponds
- * to the number of elements in the list stored in
- * a single argument. If no count is specified, then
- * the argument is taken as a single non-list value.
- */
+ /*
+ * For number-type specifiers, the count corresponds to the
+ * number of elements in the list stored in a single argument.
+ * If no count is specified, then the argument is taken as a
+ * single non-list value.
+ */
- if (count == BINARY_NOCOUNT) {
- arg++;
- count = 1;
- } else {
- int listc;
- Tcl_Obj **listv;
- if (Tcl_ListObjGetElements(interp, objv[arg++],
- &listc, &listv) != TCL_OK) {
- return TCL_ERROR;
- }
- if (count == BINARY_ALL) {
- count = listc;
- } else if (count > listc) {
- Tcl_AppendResult(interp,
- "number of elements in list does not match count",
- (char *) NULL);
- return TCL_ERROR;
- }
- }
- offset += count*size;
- break;
- }
- case 'x': {
- if (count == BINARY_ALL) {
- Tcl_AppendResult(interp,
- "cannot use \"*\" in format string with \"x\"",
- (char *) NULL);
- return TCL_ERROR;
- } else if (count == BINARY_NOCOUNT) {
- count = 1;
- }
- offset += count;
- break;
- }
- case 'X': {
- if (count == BINARY_NOCOUNT) {
- count = 1;
- }
- if ((count > offset) || (count == BINARY_ALL)) {
- count = offset;
- }
- if (offset > length) {
- length = offset;
- }
- offset -= count;
- break;
- }
- case '@': {
- if (offset > length) {
- length = offset;
- }
- if (count == BINARY_ALL) {
- offset = length;
- } else if (count == BINARY_NOCOUNT) {
- goto badCount;
- } else {
- offset = count;
- }
- break;
+ if (count == BINARY_NOCOUNT) {
+ arg++;
+ count = 1;
+ } else {
+ int listc;
+ Tcl_Obj **listv;
+
+ /* The macro evals its args more than once: avoid arg++ */
+ if (TclListObjGetElements(interp, objv[arg], &listc,
+ &listv) != TCL_OK) {
+ return TCL_ERROR;
}
- default: {
- errorString = str;
- goto badField;
+ arg++;
+
+ if (count == BINARY_ALL) {
+ count = listc;
+ } else if (count > listc) {
+ Tcl_AppendResult(interp,
+ "number of elements in list does not match count",
+ NULL);
+ return TCL_ERROR;
}
}
+ offset += count*size;
+ break;
+
+ case 'x':
+ if (count == BINARY_ALL) {
+ Tcl_AppendResult(interp,
+ "cannot use \"*\" in format string with \"x\"",
+ NULL);
+ return TCL_ERROR;
+ } else if (count == BINARY_NOCOUNT) {
+ count = 1;
+ }
+ offset += count;
+ break;
+ case 'X':
+ if (count == BINARY_NOCOUNT) {
+ count = 1;
+ }
+ if ((count > offset) || (count == BINARY_ALL)) {
+ count = offset;
+ }
+ if (offset > length) {
+ length = offset;
+ }
+ offset -= count;
+ break;
+ case '@':
+ if (offset > length) {
+ length = offset;
+ }
+ if (count == BINARY_ALL) {
+ offset = length;
+ } else if (count == BINARY_NOCOUNT) {
+ goto badCount;
+ } else {
+ offset = count;
+ }
+ break;
+ default:
+ errorString = str;
+ goto badField;
}
- if (offset > length) {
- length = offset;
- }
- if (length == 0) {
- return TCL_OK;
- }
+ }
+ if (offset > length) {
+ length = offset;
+ }
+ if (length == 0) {
+ return TCL_OK;
+ }
- /*
- * Prepare the result object by preallocating the caclulated
- * number of bytes and filling with nulls.
- */
+ /*
+ * Prepare the result object by preallocating the caclulated number of
+ * bytes and filling with nulls.
+ */
- resultPtr = Tcl_GetObjResult(interp);
- if (Tcl_IsShared(resultPtr)) {
- TclNewObj(resultPtr);
- Tcl_SetObjResult(interp, resultPtr);
- }
- buffer = Tcl_SetByteArrayLength(resultPtr, length);
- memset((VOID *) buffer, 0, (size_t) length);
+ resultPtr = Tcl_NewObj();
+ buffer = Tcl_SetByteArrayLength(resultPtr, length);
+ memset(buffer, 0, (size_t) length);
- /*
- * Pack the data into the result object. Note that we can skip
- * the error checking during this pass, since we have already
- * parsed the string once.
- */
+ /*
+ * Pack the data into the result object. Note that we can skip the
+ * error checking during this pass, since we have already parsed the
+ * string once.
+ */
- arg = 3;
- format = Tcl_GetString(objv[2]);
- cursor = buffer;
- maxPos = cursor;
- while (*format != 0) {
- if (!GetFormatSpec(&format, &cmd, &count)) {
- break;
+ arg = 3;
+ format = TclGetString(objv[2]);
+ cursor = buffer;
+ maxPos = cursor;
+ while (*format != 0) {
+ flags = 0;
+ if (!GetFormatSpec(&format, &cmd, &count, &flags)) {
+ break;
+ }
+ if ((count == 0) && (cmd != '@')) {
+ if (cmd != 'x') {
+ arg++;
}
- if ((count == 0) && (cmd != '@')) {
- if (cmd != 'x') {
- arg++;
- }
- continue;
+ continue;
+ }
+ switch (cmd) {
+ case 'a':
+ case 'A': {
+ char pad = (char) (cmd == 'a' ? '\0' : ' ');
+ unsigned char *bytes;
+
+ bytes = Tcl_GetByteArrayFromObj(objv[arg++], &length);
+
+ if (count == BINARY_ALL) {
+ count = length;
+ } else if (count == BINARY_NOCOUNT) {
+ count = 1;
}
- switch (cmd) {
- case 'a':
- case 'A': {
- char pad = (char) (cmd == 'a' ? '\0' : ' ');
- unsigned char *bytes;
-
- bytes = Tcl_GetByteArrayFromObj(objv[arg++], &length);
-
- if (count == BINARY_ALL) {
- count = length;
- } else if (count == BINARY_NOCOUNT) {
- count = 1;
+ if (length >= count) {
+ memcpy(cursor, bytes, (size_t) count);
+ } else {
+ memcpy(cursor, bytes, (size_t) length);
+ memset(cursor + length, pad, (size_t) (count - length));
+ }
+ cursor += count;
+ break;
+ }
+ case 'b':
+ case 'B': {
+ unsigned char *last;
+
+ str = TclGetStringFromObj(objv[arg], &length);
+ arg++;
+ if (count == BINARY_ALL) {
+ count = length;
+ } else if (count == BINARY_NOCOUNT) {
+ count = 1;
+ }
+ last = cursor + ((count + 7) / 8);
+ if (count > length) {
+ count = length;
+ }
+ value = 0;
+ errorString = "binary";
+ if (cmd == 'B') {
+ for (offset = 0; offset < count; offset++) {
+ value <<= 1;
+ if (str[offset] == '1') {
+ value |= 1;
+ } else if (str[offset] != '0') {
+ errorValue = str;
+ Tcl_DecrRefCount(resultPtr);
+ goto badValue;
}
- if (length >= count) {
- memcpy((VOID *) cursor, (VOID *) bytes,
- (size_t) count);
- } else {
- memcpy((VOID *) cursor, (VOID *) bytes,
- (size_t) length);
- memset((VOID *) (cursor + length), pad,
- (size_t) (count - length));
+ if (((offset + 1) % 8) == 0) {
+ *cursor++ = (unsigned char) value;
+ value = 0;
}
- cursor += count;
- break;
}
- case 'b':
- case 'B': {
- unsigned char *last;
-
- str = Tcl_GetStringFromObj(objv[arg++], &length);
- if (count == BINARY_ALL) {
- count = length;
- } else if (count == BINARY_NOCOUNT) {
- count = 1;
- }
- last = cursor + ((count + 7) / 8);
- if (count > length) {
- count = length;
- }
- value = 0;
- errorString = "binary";
- if (cmd == 'B') {
- for (offset = 0; offset < count; offset++) {
- value <<= 1;
- if (str[offset] == '1') {
- value |= 1;
- } else if (str[offset] != '0') {
- errorValue = str;
- goto badValue;
- }
- if (((offset + 1) % 8) == 0) {
- *cursor++ = (unsigned char) value;
- value = 0;
- }
- }
- } else {
- for (offset = 0; offset < count; offset++) {
- value >>= 1;
- if (str[offset] == '1') {
- value |= 128;
- } else if (str[offset] != '0') {
- errorValue = str;
- goto badValue;
- }
- if (!((offset + 1) % 8)) {
- *cursor++ = (unsigned char) value;
- value = 0;
- }
- }
+ } else {
+ for (offset = 0; offset < count; offset++) {
+ value >>= 1;
+ if (str[offset] == '1') {
+ value |= 128;
+ } else if (str[offset] != '0') {
+ errorValue = str;
+ Tcl_DecrRefCount(resultPtr);
+ goto badValue;
}
- if ((offset % 8) != 0) {
- if (cmd == 'B') {
- value <<= 8 - (offset % 8);
- } else {
- value >>= 8 - (offset % 8);
- }
+ if (!((offset + 1) % 8)) {
*cursor++ = (unsigned char) value;
+ value = 0;
}
- while (cursor < last) {
- *cursor++ = '\0';
- }
- break;
}
- case 'h':
- case 'H': {
- unsigned char *last;
- int c;
-
- str = Tcl_GetStringFromObj(objv[arg++], &length);
- if (count == BINARY_ALL) {
- count = length;
- } else if (count == BINARY_NOCOUNT) {
- count = 1;
+ }
+ if ((offset % 8) != 0) {
+ if (cmd == 'B') {
+ value <<= 8 - (offset % 8);
+ } else {
+ value >>= 8 - (offset % 8);
+ }
+ *cursor++ = (unsigned char) value;
+ }
+ while (cursor < last) {
+ *cursor++ = '\0';
+ }
+ break;
+ }
+ case 'h':
+ case 'H': {
+ unsigned char *last;
+ int c;
+
+ str = TclGetStringFromObj(objv[arg], &length);
+ arg++;
+ if (count == BINARY_ALL) {
+ count = length;
+ } else if (count == BINARY_NOCOUNT) {
+ count = 1;
+ }
+ last = cursor + ((count + 1) / 2);
+ if (count > length) {
+ count = length;
+ }
+ value = 0;
+ errorString = "hexadecimal";
+ if (cmd == 'H') {
+ for (offset = 0; offset < count; offset++) {
+ value <<= 4;
+ if (!isxdigit(UCHAR(str[offset]))) { /* INTL: digit */
+ errorValue = str;
+ Tcl_DecrRefCount(resultPtr);
+ goto badValue;
}
- last = cursor + ((count + 1) / 2);
- if (count > length) {
- count = length;
+ c = str[offset] - '0';
+ if (c > 9) {
+ c += ('0' - 'A') + 10;
}
- value = 0;
- errorString = "hexadecimal";
- if (cmd == 'H') {
- for (offset = 0; offset < count; offset++) {
- value <<= 4;
- if (!isxdigit(UCHAR(str[offset]))) { /* INTL: digit */
- errorValue = str;
- goto badValue;
- }
- c = str[offset] - '0';
- if (c > 9) {
- c += ('0' - 'A') + 10;
- }
- if (c > 16) {
- c += ('A' - 'a');
- }
- value |= (c & 0xf);
- if (offset % 2) {
- *cursor++ = (char) value;
- value = 0;
- }
- }
- } else {
- for (offset = 0; offset < count; offset++) {
- value >>= 4;
-
- if (!isxdigit(UCHAR(str[offset]))) { /* INTL: digit */
- errorValue = str;
- goto badValue;
- }
- c = str[offset] - '0';
- if (c > 9) {
- c += ('0' - 'A') + 10;
- }
- if (c > 16) {
- c += ('A' - 'a');
- }
- value |= ((c << 4) & 0xf0);
- if (offset % 2) {
- *cursor++ = (unsigned char)(value & 0xff);
- value = 0;
- }
- }
+ if (c > 16) {
+ c += ('A' - 'a');
}
+ value |= (c & 0xf);
if (offset % 2) {
- if (cmd == 'H') {
- value <<= 4;
- } else {
- value >>= 4;
- }
- *cursor++ = (unsigned char) value;
+ *cursor++ = (char) value;
+ value = 0;
}
+ }
+ } else {
+ for (offset = 0; offset < count; offset++) {
+ value >>= 4;
- while (cursor < last) {
- *cursor++ = '\0';
+ if (!isxdigit(UCHAR(str[offset]))) { /* INTL: digit */
+ errorValue = str;
+ Tcl_DecrRefCount(resultPtr);
+ goto badValue;
}
- break;
- }
- case 'c':
- case 's':
- case 'S':
- case 'i':
- case 'I':
- case 'w':
- case 'W':
- case 'd':
- case 'f': {
- int listc, i;
- Tcl_Obj **listv;
-
- if (count == BINARY_NOCOUNT) {
- /*
- * Note that we are casting away the const-ness of
- * objv, but this is safe since we aren't going to
- * modify the array.
- */
-
- listv = (Tcl_Obj**)(objv + arg);
- listc = 1;
- count = 1;
- } else {
- Tcl_ListObjGetElements(interp, objv[arg],
- &listc, &listv);
- if (count == BINARY_ALL) {
- count = listc;
- }
+ c = str[offset] - '0';
+ if (c > 9) {
+ c += ('0' - 'A') + 10;
}
- arg++;
- for (i = 0; i < count; i++) {
- if (FormatNumber(interp, cmd, listv[i], &cursor)
- != TCL_OK) {
- return TCL_ERROR;
- }
+ if (c > 16) {
+ c += ('A' - 'a');
}
- break;
- }
- case 'x': {
- if (count == BINARY_NOCOUNT) {
- count = 1;
+ value |= ((c << 4) & 0xf0);
+ if (offset % 2) {
+ *cursor++ = (unsigned char)(value & 0xff);
+ value = 0;
}
- memset(cursor, 0, (size_t) count);
- cursor += count;
- break;
}
- case 'X': {
- if (cursor > maxPos) {
- maxPos = cursor;
- }
- if (count == BINARY_NOCOUNT) {
- count = 1;
- }
- if ((count == BINARY_ALL)
- || (count > (cursor - buffer))) {
- cursor = buffer;
- } else {
- cursor -= count;
- }
- break;
+ }
+ if (offset % 2) {
+ if (cmd == 'H') {
+ value <<= 4;
+ } else {
+ value >>= 4;
}
- case '@': {
- if (cursor > maxPos) {
- maxPos = cursor;
- }
- if (count == BINARY_ALL) {
- cursor = maxPos;
- } else {
- cursor = buffer + count;
- }
- break;
+ *cursor++ = (unsigned char) value;
+ }
+
+ while (cursor < last) {
+ *cursor++ = '\0';
+ }
+ break;
+ }
+ case 'c':
+ case 't':
+ case 's':
+ case 'S':
+ case 'n':
+ case 'i':
+ case 'I':
+ case 'm':
+ case 'w':
+ case 'W':
+ case 'r':
+ case 'R':
+ case 'd':
+ case 'q':
+ case 'Q':
+ case 'f': {
+ int listc, i;
+ Tcl_Obj **listv;
+
+ if (count == BINARY_NOCOUNT) {
+ /*
+ * Note that we are casting away the const-ness of objv,
+ * but this is safe since we aren't going to modify the
+ * array.
+ */
+
+ listv = (Tcl_Obj**)(objv + arg);
+ listc = 1;
+ count = 1;
+ } else {
+ TclListObjGetElements(interp, objv[arg], &listc, &listv);
+ if (count == BINARY_ALL) {
+ count = listc;
}
}
+ arg++;
+ for (i = 0; i < count; i++) {
+ if (FormatNumber(interp, cmd, listv[i], &cursor)!=TCL_OK) {
+ Tcl_DecrRefCount(resultPtr);
+ return TCL_ERROR;
+ }
+ }
+ break;
+ }
+ case 'x':
+ if (count == BINARY_NOCOUNT) {
+ count = 1;
+ }
+ memset(cursor, 0, (size_t) count);
+ cursor += count;
+ break;
+ case 'X':
+ if (cursor > maxPos) {
+ maxPos = cursor;
+ }
+ if (count == BINARY_NOCOUNT) {
+ count = 1;
+ }
+ if ((count == BINARY_ALL) || (count > (cursor - buffer))) {
+ cursor = buffer;
+ } else {
+ cursor -= count;
+ }
+ break;
+ case '@':
+ if (cursor > maxPos) {
+ maxPos = cursor;
+ }
+ if (count == BINARY_ALL) {
+ cursor = maxPos;
+ } else {
+ cursor = buffer + count;
+ }
+ break;
}
- break;
}
- case BINARY_SCAN: {
- int i;
- Tcl_Obj *valuePtr, *elementPtr;
- Tcl_HashTable numberCacheHash;
- Tcl_HashTable *numberCachePtr;
-
- if (objc < 4) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "value formatString ?varName varName ...?");
- return TCL_ERROR;
+ Tcl_SetObjResult(interp, resultPtr);
+ break;
+ case BINARY_SCAN: {
+ int i;
+ Tcl_Obj *valuePtr, *elementPtr;
+ Tcl_HashTable numberCacheHash;
+ Tcl_HashTable *numberCachePtr;
+
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "value formatString ?varName varName ...?");
+ return TCL_ERROR;
+ }
+ numberCachePtr = &numberCacheHash;
+ Tcl_InitHashTable(numberCachePtr, TCL_ONE_WORD_KEYS);
+ buffer = Tcl_GetByteArrayFromObj(objv[2], &length);
+ format = TclGetString(objv[3]);
+ cursor = buffer;
+ arg = 4;
+ offset = 0;
+ while (*format != '\0') {
+ str = format;
+ flags = 0;
+ if (!GetFormatSpec(&format, &cmd, &count, &flags)) {
+ goto done;
}
- numberCachePtr = &numberCacheHash;
- Tcl_InitHashTable(numberCachePtr, TCL_ONE_WORD_KEYS);
- buffer = Tcl_GetByteArrayFromObj(objv[2], &length);
- format = Tcl_GetString(objv[3]);
- cursor = buffer;
- arg = 4;
- offset = 0;
- while (*format != '\0') {
- str = format;
- if (!GetFormatSpec(&format, &cmd, &count)) {
- goto done;
+ switch (cmd) {
+ case 'a':
+ case 'A': {
+ unsigned char *src;
+
+ if (arg >= objc) {
+ DeleteScanNumberCache(numberCachePtr);
+ goto badIndex;
+ }
+ if (count == BINARY_ALL) {
+ count = length - offset;
+ } else {
+ if (count == BINARY_NOCOUNT) {
+ count = 1;
+ }
+ if (count > (length - offset)) {
+ goto done;
+ }
}
- switch (cmd) {
- case 'a':
- case 'A': {
- unsigned char *src;
-
- if (arg >= objc) {
- DeleteScanNumberCache(numberCachePtr);
- goto badIndex;
- }
- if (count == BINARY_ALL) {
- count = length - offset;
- } else {
- if (count == BINARY_NOCOUNT) {
- count = 1;
- }
- if (count > (length - offset)) {
- goto done;
- }
- }
- src = buffer + offset;
- size = count;
+ src = buffer + offset;
+ size = count;
- /*
- * Trim trailing nulls and spaces, if necessary.
- */
+ /*
+ * Trim trailing nulls and spaces, if necessary.
+ */
- if (cmd == 'A') {
- while (size > 0) {
- if (src[size-1] != '\0' && src[size-1] != ' ') {
- break;
- }
- size--;
- }
- }
- valuePtr = Tcl_NewByteArrayObj(src, size);
- Tcl_IncrRefCount(valuePtr);
- resultPtr = Tcl_ObjSetVar2(interp, objv[arg],
- NULL, valuePtr, TCL_LEAVE_ERR_MSG);
- Tcl_DecrRefCount(valuePtr);
- arg++;
- if (resultPtr == NULL) {
- DeleteScanNumberCache(numberCachePtr);
- return TCL_ERROR;
+ if (cmd == 'A') {
+ while (size > 0) {
+ if (src[size-1] != '\0' && src[size-1] != ' ') {
+ break;
}
- offset += count;
- break;
+ size--;
}
- case 'b':
- case 'B': {
- unsigned char *src;
- char *dest;
-
- if (arg >= objc) {
- DeleteScanNumberCache(numberCachePtr);
- goto badIndex;
- }
- if (count == BINARY_ALL) {
- count = (length - offset) * 8;
- } else {
- if (count == BINARY_NOCOUNT) {
- count = 1;
- }
- if (count > (length - offset) * 8) {
- goto done;
- }
- }
- src = buffer + offset;
- valuePtr = Tcl_NewObj();
- Tcl_SetObjLength(valuePtr, count);
- dest = Tcl_GetString(valuePtr);
-
- if (cmd == 'b') {
- for (i = 0; i < count; i++) {
- if (i % 8) {
- value >>= 1;
- } else {
- value = *src++;
- }
- *dest++ = (char) ((value & 1) ? '1' : '0');
- }
- } else {
- for (i = 0; i < count; i++) {
- if (i % 8) {
- value <<= 1;
- } else {
- value = *src++;
- }
- *dest++ = (char) ((value & 0x80) ? '1' : '0');
- }
- }
+ }
- Tcl_IncrRefCount(valuePtr);
- resultPtr = Tcl_ObjSetVar2(interp, objv[arg],
- NULL, valuePtr, TCL_LEAVE_ERR_MSG);
- Tcl_DecrRefCount(valuePtr);
- arg++;
- if (resultPtr == NULL) {
- DeleteScanNumberCache(numberCachePtr);
- return TCL_ERROR;
- }
- offset += (count + 7 ) / 8;
- break;
+ /*
+ * Have to do this #ifdef-fery because (as part of defining
+ * Tcl_NewByteArrayObj) we removed the #def that hides this
+ * stuff normally. If this code ever gets copied to another
+ * file, it should be changed back to the simpler version.
+ */
+
+#ifdef TCL_MEM_DEBUG
+ valuePtr = Tcl_DbNewByteArrayObj(src, size, __FILE__,__LINE__);
+#else
+ valuePtr = Tcl_NewByteArrayObj(src, size);
+#endif /* TCL_MEM_DEBUG */
+
+ resultPtr = Tcl_ObjSetVar2(interp, objv[arg], NULL, valuePtr,
+ TCL_LEAVE_ERR_MSG);
+ arg++;
+ if (resultPtr == NULL) {
+ DeleteScanNumberCache(numberCachePtr);
+ return TCL_ERROR;
+ }
+ offset += count;
+ break;
+ }
+ case 'b':
+ case 'B': {
+ unsigned char *src;
+ char *dest;
+
+ if (arg >= objc) {
+ DeleteScanNumberCache(numberCachePtr);
+ goto badIndex;
+ }
+ if (count == BINARY_ALL) {
+ count = (length - offset) * 8;
+ } else {
+ if (count == BINARY_NOCOUNT) {
+ count = 1;
}
- case 'h':
- case 'H': {
- char *dest;
- unsigned char *src;
- int i;
- static char hexdigit[] = "0123456789abcdef";
-
- if (arg >= objc) {
- DeleteScanNumberCache(numberCachePtr);
- goto badIndex;
- }
- if (count == BINARY_ALL) {
- count = (length - offset)*2;
+ if (count > (length - offset) * 8) {
+ goto done;
+ }
+ }
+ src = buffer + offset;
+ valuePtr = Tcl_NewObj();
+ Tcl_SetObjLength(valuePtr, count);
+ dest = TclGetString(valuePtr);
+
+ if (cmd == 'b') {
+ for (i = 0; i < count; i++) {
+ if (i % 8) {
+ value >>= 1;
} else {
- if (count == BINARY_NOCOUNT) {
- count = 1;
- }
- if (count > (length - offset)*2) {
- goto done;
- }
+ value = *src++;
}
- src = buffer + offset;
- valuePtr = Tcl_NewObj();
- Tcl_SetObjLength(valuePtr, count);
- dest = Tcl_GetString(valuePtr);
-
- if (cmd == 'h') {
- for (i = 0; i < count; i++) {
- if (i % 2) {
- value >>= 4;
- } else {
- value = *src++;
- }
- *dest++ = hexdigit[value & 0xf];
- }
+ *dest++ = (char) ((value & 1) ? '1' : '0');
+ }
+ } else {
+ for (i = 0; i < count; i++) {
+ if (i % 8) {
+ value <<= 1;
} else {
- for (i = 0; i < count; i++) {
- if (i % 2) {
- value <<= 4;
- } else {
- value = *src++;
- }
- *dest++ = hexdigit[(value >> 4) & 0xf];
- }
+ value = *src++;
}
-
- Tcl_IncrRefCount(valuePtr);
- resultPtr = Tcl_ObjSetVar2(interp, objv[arg],
- NULL, valuePtr, TCL_LEAVE_ERR_MSG);
- Tcl_DecrRefCount(valuePtr);
- arg++;
- if (resultPtr == NULL) {
- DeleteScanNumberCache(numberCachePtr);
- return TCL_ERROR;
- }
- offset += (count + 1) / 2;
- break;
- }
- case 'c': {
- size = 1;
- goto scanNumber;
- }
- case 's':
- case 'S': {
- size = 2;
- goto scanNumber;
+ *dest++ = (char) ((value & 0x80) ? '1' : '0');
}
- case 'i':
- case 'I': {
- size = 4;
- goto scanNumber;
- }
- case 'w':
- case 'W': {
- size = 8;
- goto scanNumber;
+ }
+
+ resultPtr = Tcl_ObjSetVar2(interp, objv[arg], NULL, valuePtr,
+ TCL_LEAVE_ERR_MSG);
+ arg++;
+ if (resultPtr == NULL) {
+ DeleteScanNumberCache(numberCachePtr);
+ return TCL_ERROR;
+ }
+ offset += (count + 7) / 8;
+ break;
+ }
+ case 'h':
+ case 'H': {
+ char *dest;
+ unsigned char *src;
+ int i;
+ static const char hexdigit[] = "0123456789abcdef";
+
+ if (arg >= objc) {
+ DeleteScanNumberCache(numberCachePtr);
+ goto badIndex;
+ }
+ if (count == BINARY_ALL) {
+ count = (length - offset)*2;
+ } else {
+ if (count == BINARY_NOCOUNT) {
+ count = 1;
}
- case 'f': {
- size = sizeof(float);
- goto scanNumber;
+ if (count > (length - offset)*2) {
+ goto done;
}
- case 'd': {
- unsigned char *src;
-
- size = sizeof(double);
- /* fall through */
-
- scanNumber:
- if (arg >= objc) {
- DeleteScanNumberCache(numberCachePtr);
- goto badIndex;
- }
- if (count == BINARY_NOCOUNT) {
- if ((length - offset) < size) {
- goto done;
- }
- valuePtr = ScanNumber(buffer+offset, cmd,
- &numberCachePtr);
- offset += size;
+ }
+ src = buffer + offset;
+ valuePtr = Tcl_NewObj();
+ Tcl_SetObjLength(valuePtr, count);
+ dest = TclGetString(valuePtr);
+
+ if (cmd == 'h') {
+ for (i = 0; i < count; i++) {
+ if (i % 2) {
+ value >>= 4;
} else {
- if (count == BINARY_ALL) {
- count = (length - offset) / size;
- }
- if ((length - offset) < (count * size)) {
- goto done;
- }
- valuePtr = Tcl_NewObj();
- src = buffer+offset;
- for (i = 0; i < count; i++) {
- elementPtr = ScanNumber(src, cmd,
- &numberCachePtr);
- src += size;
- Tcl_ListObjAppendElement(NULL, valuePtr,
- elementPtr);
- }
- offset += count*size;
+ value = *src++;
}
-
- Tcl_IncrRefCount(valuePtr);
- resultPtr = Tcl_ObjSetVar2(interp, objv[arg],
- NULL, valuePtr, TCL_LEAVE_ERR_MSG);
- Tcl_DecrRefCount(valuePtr);
- arg++;
- if (resultPtr == NULL) {
- DeleteScanNumberCache(numberCachePtr);
- return TCL_ERROR;
- }
- break;
+ *dest++ = hexdigit[value & 0xf];
}
- case 'x': {
- if (count == BINARY_NOCOUNT) {
- count = 1;
- }
- if ((count == BINARY_ALL)
- || (count > (length - offset))) {
- offset = length;
+ } else {
+ for (i = 0; i < count; i++) {
+ if (i % 2) {
+ value <<= 4;
} else {
- offset += count;
+ value = *src++;
}
- break;
+ *dest++ = hexdigit[(value >> 4) & 0xf];
}
- case 'X': {
- if (count == BINARY_NOCOUNT) {
- count = 1;
- }
- if ((count == BINARY_ALL) || (count > offset)) {
- offset = 0;
- } else {
- offset -= count;
- }
- break;
+ }
+
+ resultPtr = Tcl_ObjSetVar2(interp, objv[arg], NULL, valuePtr,
+ TCL_LEAVE_ERR_MSG);
+ arg++;
+ if (resultPtr == NULL) {
+ DeleteScanNumberCache(numberCachePtr);
+ return TCL_ERROR;
+ }
+ offset += (count + 1) / 2;
+ break;
+ }
+ case 'c':
+ size = 1;
+ goto scanNumber;
+ case 't':
+ case 's':
+ case 'S':
+ size = 2;
+ goto scanNumber;
+ case 'n':
+ case 'i':
+ case 'I':
+ size = 4;
+ goto scanNumber;
+ case 'm':
+ case 'w':
+ case 'W':
+ size = 8;
+ goto scanNumber;
+ case 'r':
+ case 'R':
+ case 'f':
+ size = sizeof(float);
+ goto scanNumber;
+ case 'q':
+ case 'Q':
+ case 'd': {
+ unsigned char *src;
+
+ size = sizeof(double);
+ /* fall through */
+
+ scanNumber:
+ if (arg >= objc) {
+ DeleteScanNumberCache(numberCachePtr);
+ goto badIndex;
+ }
+ if (count == BINARY_NOCOUNT) {
+ if ((length - offset) < size) {
+ goto done;
}
- case '@': {
- if (count == BINARY_NOCOUNT) {
- DeleteScanNumberCache(numberCachePtr);
- goto badCount;
- }
- if ((count == BINARY_ALL) || (count > length)) {
- offset = length;
- } else {
- offset = count;
- }
- break;
+ valuePtr = ScanNumber(buffer+offset, cmd, flags,
+ &numberCachePtr);
+ offset += size;
+ } else {
+ if (count == BINARY_ALL) {
+ count = (length - offset) / size;
+ }
+ if ((length - offset) < (count * size)) {
+ goto done;
}
- default: {
- DeleteScanNumberCache(numberCachePtr);
- errorString = str;
- goto badField;
+ valuePtr = Tcl_NewObj();
+ src = buffer+offset;
+ for (i = 0; i < count; i++) {
+ elementPtr = ScanNumber(src, cmd, flags,
+ &numberCachePtr);
+ src += size;
+ Tcl_ListObjAppendElement(NULL, valuePtr, elementPtr);
}
+ offset += count*size;
+ }
+
+ resultPtr = Tcl_ObjSetVar2(interp, objv[arg], NULL, valuePtr,
+ TCL_LEAVE_ERR_MSG);
+ arg++;
+ if (resultPtr == NULL) {
+ DeleteScanNumberCache(numberCachePtr);
+ return TCL_ERROR;
+ }
+ break;
+ }
+ case 'x':
+ if (count == BINARY_NOCOUNT) {
+ count = 1;
+ }
+ if ((count == BINARY_ALL) || (count > (length - offset))) {
+ offset = length;
+ } else {
+ offset += count;
+ }
+ break;
+ case 'X':
+ if (count == BINARY_NOCOUNT) {
+ count = 1;
+ }
+ if ((count == BINARY_ALL) || (count > offset)) {
+ offset = 0;
+ } else {
+ offset -= count;
+ }
+ break;
+ case '@':
+ if (count == BINARY_NOCOUNT) {
+ DeleteScanNumberCache(numberCachePtr);
+ goto badCount;
}
+ if ((count == BINARY_ALL) || (count > length)) {
+ offset = length;
+ } else {
+ offset = count;
+ }
+ break;
+ default:
+ DeleteScanNumberCache(numberCachePtr);
+ errorString = str;
+ goto badField;
}
+ }
- /*
- * Set the result to the last position of the cursor.
- */
+ /*
+ * Set the result to the last position of the cursor.
+ */
- done:
- Tcl_ResetResult(interp);
- Tcl_SetLongObj(Tcl_GetObjResult(interp), arg - 4);
- DeleteScanNumberCache(numberCachePtr);
- break;
- }
+ done:
+ Tcl_SetObjResult(interp, Tcl_NewLongObj(arg - 4));
+ DeleteScanNumberCache(numberCachePtr);
+ break;
+ }
}
return TCL_OK;
- badValue:
+ badValue:
Tcl_ResetResult(interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "expected ", errorString,
+ Tcl_AppendResult(interp, "expected ", errorString,
" string but got \"", errorValue, "\" instead", NULL);
return TCL_ERROR;
- badCount:
+ badCount:
errorString = "missing count for \"@\" field specifier";
goto error;
- badIndex:
+ badIndex:
errorString = "not enough arguments for all format specifiers";
goto error;
- badField:
+ badField:
{
Tcl_UniChar ch;
char buf[TCL_UTF_MAX + 1];
@@ -1365,7 +1368,7 @@ Tcl_BinaryObjCmd(dummy, interp, objc, objv)
return TCL_ERROR;
}
- error:
+ error:
Tcl_AppendResult(interp, errorString, NULL);
return TCL_ERROR;
}
@@ -1375,15 +1378,15 @@ Tcl_BinaryObjCmd(dummy, interp, objc, objv)
*
* GetFormatSpec --
*
- * This function parses the format strings used in the binary
- * format and scan commands.
+ * This function parses the format strings used in the binary format and
+ * scan commands.
*
* Results:
- * Moves the formatPtr to the start of the next command. Returns
- * the current command character and count in cmdPtr and countPtr.
- * The count is set to BINARY_ALL if the count character was '*'
- * or BINARY_NOCOUNT if no count was specified. Returns 1 on
- * success, or 0 if the string did not have a format specifier.
+ * Moves the formatPtr to the start of the next command. Returns the
+ * current command character and count in cmdPtr and countPtr. The count
+ * is set to BINARY_ALL if the count character was '*' or BINARY_NOCOUNT
+ * if no count was specified. Returns 1 on success, or 0 if the string
+ * did not have a format specifier.
*
* Side effects:
* None.
@@ -1392,10 +1395,11 @@ Tcl_BinaryObjCmd(dummy, interp, objc, objv)
*/
static int
-GetFormatSpec(formatPtr, cmdPtr, countPtr)
- char **formatPtr; /* Pointer to format string. */
- char *cmdPtr; /* Pointer to location of command char. */
- int *countPtr; /* Pointer to repeat count value. */
+GetFormatSpec(
+ char **formatPtr, /* Pointer to format string. */
+ char *cmdPtr, /* Pointer to location of command char. */
+ int *countPtr, /* Pointer to repeat count value. */
+ int *flagsPtr) /* Pointer to field flags */
{
/*
* Skip any leading blanks.
@@ -1419,6 +1423,10 @@ GetFormatSpec(formatPtr, cmdPtr, countPtr)
*cmdPtr = **formatPtr;
(*formatPtr)++;
+ if (**formatPtr == 'u') {
+ (*formatPtr)++;
+ (*flagsPtr) |= BINARY_UNSIGNED;
+ }
if (**formatPtr == '*') {
(*formatPtr)++;
(*countPtr) = BINARY_ALL;
@@ -1433,13 +1441,193 @@ GetFormatSpec(formatPtr, cmdPtr, countPtr)
/*
*----------------------------------------------------------------------
*
+ * NeedReversing --
+ *
+ * This routine determines, if bytes of a number need to be re-ordered,
+ * and returns a numeric code indicating the re-ordering to be done.
+ * This depends on the endiannes of the machine and the desired format.
+ * It is in effect a table (whose contents depend on the endianness of
+ * the system) describing whether a value needs reversing or not. Anyone
+ * porting the code to a big-endian platform should take care to make
+ * sure that they define WORDS_BIGENDIAN though this is already done by
+ * configure for the Unix build; little-endian platforms (including
+ * Windows) don't need to do anything.
+ *
+ * Results:
+ * 0 No re-ordering needed.
+ * 1 Reverse the bytes: 01234567 <-> 76543210 (little to big)
+ * 2 Apply this re-ordering: 01234567 <-> 45670123 (Nokia to little)
+ * 3 Apply this re-ordering: 01234567 <-> 32107654 (Nokia to big)
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NeedReversing(
+ int format)
+{
+ switch (format) {
+ /* native floats and doubles: never reverse */
+ case 'd':
+ case 'f':
+ /* big endian ints: never reverse */
+ case 'I':
+ case 'S':
+ case 'W':
+#ifdef WORDS_BIGENDIAN
+ /* native ints: reverse if we're little-endian */
+ case 'n':
+ case 't':
+ case 'm':
+ /* f: reverse if we're little-endian */
+ case 'Q':
+ case 'R':
+#else /* !WORDS_BIGENDIAN */
+ /* small endian floats: reverse if we're big-endian */
+ case 'r':
+#endif /* WORDS_BIGENDIAN */
+ return 0;
+
+#ifdef WORDS_BIGENDIAN
+ /* small endian floats: reverse if we're big-endian */
+ case 'q':
+ case 'r':
+#else /* !WORDS_BIGENDIAN */
+ /* native ints: reverse if we're little-endian */
+ case 'n':
+ case 't':
+ case 'm':
+ /* f: reverse if we're little-endian */
+ case 'R':
+#endif /* WORDS_BIGENDIAN */
+ /* small endian ints: always reverse */
+ case 'i':
+ case 's':
+ case 'w':
+ return 1;
+
+#ifndef WORDS_BIGENDIAN
+ /*
+ * The Q and q formats need special handling to account for the unusual
+ * byte ordering of 8-byte floats on Nokia 770 systems, which claim to be
+ * little-endian, but also reverse word order.
+ */
+
+ case 'Q':
+ if (TclNokia770Doubles()) {
+ return 3;
+ }
+ return 1;
+ case 'q':
+ if (TclNokia770Doubles()) {
+ return 2;
+ }
+ return 0;
+#endif
+ }
+
+ Tcl_Panic("unexpected fallthrough");
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CopyNumber --
+ *
+ * This routine is called by FormatNumber and ScanNumber to copy a
+ * floating-point number. If required, bytes are reversed while copying.
+ * The behaviour is only fully defined when used with IEEE float and
+ * double values (guaranteed to be 4 and 8 bytes long, respectively.)
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Copies length bytes
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CopyNumber(
+ const void *from, /* source */
+ void *to, /* destination */
+ unsigned int length, /* Number of bytes to copy */
+ int type) /* What type of thing are we copying? */
+{
+ switch (NeedReversing(type)) {
+ case 0:
+ memcpy(to, from, length);
+ break;
+ case 1: {
+ const unsigned char *fromPtr = from;
+ unsigned char *toPtr = to;
+
+ switch (length) {
+ case 4:
+ toPtr[0] = fromPtr[3];
+ toPtr[1] = fromPtr[2];
+ toPtr[2] = fromPtr[1];
+ toPtr[3] = fromPtr[0];
+ break;
+ case 8:
+ toPtr[0] = fromPtr[7];
+ toPtr[1] = fromPtr[6];
+ toPtr[2] = fromPtr[5];
+ toPtr[3] = fromPtr[4];
+ toPtr[4] = fromPtr[3];
+ toPtr[5] = fromPtr[2];
+ toPtr[6] = fromPtr[1];
+ toPtr[7] = fromPtr[0];
+ break;
+ }
+ break;
+ }
+ case 2: {
+ const unsigned char *fromPtr = from;
+ unsigned char *toPtr = to;
+
+ toPtr[0] = fromPtr[4];
+ toPtr[1] = fromPtr[5];
+ toPtr[2] = fromPtr[6];
+ toPtr[3] = fromPtr[7];
+ toPtr[4] = fromPtr[0];
+ toPtr[5] = fromPtr[1];
+ toPtr[6] = fromPtr[2];
+ toPtr[7] = fromPtr[3];
+ break;
+ }
+ case 3: {
+ const unsigned char *fromPtr = from;
+ unsigned char *toPtr = to;
+
+ toPtr[0] = fromPtr[3];
+ toPtr[1] = fromPtr[2];
+ toPtr[2] = fromPtr[1];
+ toPtr[3] = fromPtr[0];
+ toPtr[4] = fromPtr[7];
+ toPtr[5] = fromPtr[6];
+ toPtr[6] = fromPtr[5];
+ toPtr[7] = fromPtr[4];
+ break;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* FormatNumber --
*
- * This routine is called by Tcl_BinaryObjCmd to format a number
- * into a location pointed at by cursor.
+ * This routine is called by Tcl_BinaryObjCmd to format a number into a
+ * location pointed at by cursor.
*
* Results:
- * A standard Tcl result.
+ * A standard Tcl result.
*
* Side effects:
* Moves the cursor to the next location to be written into.
@@ -1448,64 +1636,79 @@ GetFormatSpec(formatPtr, cmdPtr, countPtr)
*/
static int
-FormatNumber(interp, type, src, cursorPtr)
- Tcl_Interp *interp; /* Current interpreter, used to report
+FormatNumber(
+ Tcl_Interp *interp, /* Current interpreter, used to report
* errors. */
- int type; /* Type of number to format. */
- Tcl_Obj *src; /* Number to format. */
- unsigned char **cursorPtr; /* Pointer to index into destination buffer. */
+ int type, /* Type of number to format. */
+ Tcl_Obj *src, /* Number to format. */
+ unsigned char **cursorPtr) /* Pointer to index into destination buffer. */
{
long value;
double dvalue;
Tcl_WideInt wvalue;
+ float fvalue;
switch (type) {
case 'd':
- case 'f':
+ case 'q':
+ case 'Q':
/*
- * For floating point types, we need to copy the data using
- * memcpy to avoid alignment issues.
+ * Double-precision floating point values. Tcl_GetDoubleFromObj
+ * returns TCL_ERROR for NaN, but we can check by comparing the
+ * object's type pointer.
*/
if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) {
- return TCL_ERROR;
+ if (src->typePtr != &tclDoubleType) {
+ return TCL_ERROR;
+ }
+ dvalue = src->internalRep.doubleValue;
}
- if (type == 'd') {
- /*
- * Can't just memcpy() here. [Bug 1116542]
- */
-
- CopyNumber(&dvalue, *cursorPtr, sizeof(double));
- *cursorPtr += sizeof(double);
- } else {
- float fvalue;
+ CopyNumber(&dvalue, *cursorPtr, sizeof(double), type);
+ *cursorPtr += sizeof(double);
+ return TCL_OK;
- /*
- * Because some compilers will generate floating point exceptions
- * on an overflow cast (e.g. Borland), we restrict the values
- * to the valid range for float.
- */
+ case 'f':
+ case 'r':
+ case 'R':
+ /*
+ * Single-precision floating point values. Tcl_GetDoubleFromObj
+ * returns TCL_ERROR for NaN, but we can check by comparing the
+ * object's type pointer.
+ */
- if (fabs(dvalue) > (double)FLT_MAX) {
- fvalue = (dvalue >= 0.0) ? FLT_MAX : -FLT_MAX;
- } else {
- fvalue = (float) dvalue;
+ if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) {
+ if (src->typePtr != &tclDoubleType) {
+ return TCL_ERROR;
}
- memcpy((VOID *) *cursorPtr, (VOID *) &fvalue, sizeof(float));
- *cursorPtr += sizeof(float);
+ dvalue = src->internalRep.doubleValue;
+ }
+
+ /*
+ * Because some compilers will generate floating point exceptions on
+ * an overflow cast (e.g. Borland), we restrict the values to the
+ * valid range for float.
+ */
+
+ if (fabs(dvalue) > (double)FLT_MAX) {
+ fvalue = (dvalue >= 0.0) ? FLT_MAX : -FLT_MAX;
+ } else {
+ fvalue = (float) dvalue;
}
+ CopyNumber(&fvalue, *cursorPtr, sizeof(float), type);
+ *cursorPtr += sizeof(float);
return TCL_OK;
/*
- * Next cases separate from other integer cases because we
- * need a different API to get a wide.
+ * 64-bit integer values.
*/
case 'w':
case 'W':
+ case 'm':
if (Tcl_GetWideIntFromObj(interp, src, &wvalue) != TCL_OK) {
return TCL_ERROR;
}
- if (type == 'w') {
+ if (NeedReversing(type)) {
*(*cursorPtr)++ = (unsigned char) wvalue;
*(*cursorPtr)++ = (unsigned char) (wvalue >> 8);
*(*cursorPtr)++ = (unsigned char) (wvalue >> 16);
@@ -1525,170 +1728,221 @@ FormatNumber(interp, type, src, cursorPtr)
*(*cursorPtr)++ = (unsigned char) wvalue;
}
return TCL_OK;
- default:
- if (Tcl_GetLongFromObj(interp, src, &value) != TCL_OK) {
+
+ /*
+ * 32-bit integer values.
+ */
+ case 'i':
+ case 'I':
+ case 'n':
+ if (TclGetLongFromObj(interp, src, &value) != TCL_OK) {
return TCL_ERROR;
}
- if (type == 'c') {
- *(*cursorPtr)++ = (unsigned char) value;
- } else if (type == 's') {
- *(*cursorPtr)++ = (unsigned char) value;
- *(*cursorPtr)++ = (unsigned char) (value >> 8);
- } else if (type == 'S') {
- *(*cursorPtr)++ = (unsigned char) (value >> 8);
- *(*cursorPtr)++ = (unsigned char) value;
- } else if (type == 'i') {
+ if (NeedReversing(type)) {
*(*cursorPtr)++ = (unsigned char) value;
*(*cursorPtr)++ = (unsigned char) (value >> 8);
*(*cursorPtr)++ = (unsigned char) (value >> 16);
*(*cursorPtr)++ = (unsigned char) (value >> 24);
- } else if (type == 'I') {
+ } else {
*(*cursorPtr)++ = (unsigned char) (value >> 24);
*(*cursorPtr)++ = (unsigned char) (value >> 16);
*(*cursorPtr)++ = (unsigned char) (value >> 8);
*(*cursorPtr)++ = (unsigned char) value;
}
return TCL_OK;
+
+ /*
+ * 16-bit integer values.
+ */
+ case 's':
+ case 'S':
+ case 't':
+ if (TclGetLongFromObj(interp, src, &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (NeedReversing(type)) {
+ *(*cursorPtr)++ = (unsigned char) value;
+ *(*cursorPtr)++ = (unsigned char) (value >> 8);
+ } else {
+ *(*cursorPtr)++ = (unsigned char) (value >> 8);
+ *(*cursorPtr)++ = (unsigned char) value;
+ }
+ return TCL_OK;
+
+ /*
+ * 8-bit integer values.
+ */
+ case 'c':
+ if (TclGetLongFromObj(interp, src, &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(*cursorPtr)++ = (unsigned char) value;
+ return TCL_OK;
+
+ default:
+ Tcl_Panic("unexpected fallthrough");
+ return TCL_ERROR;
}
}
-/* Ugly workaround for old and broken compiler! */
-static void
-CopyNumber(from, to, length)
- CONST VOID *from;
- VOID *to;
- unsigned int length;
-{
- memcpy(to, from, length);
-}
-
/*
*----------------------------------------------------------------------
*
* ScanNumber --
*
- * This routine is called by Tcl_BinaryObjCmd to scan a number
- * out of a buffer.
+ * This routine is called by Tcl_BinaryObjCmd to scan a number out of a
+ * buffer.
*
* Results:
- * Returns a newly created object containing the scanned number.
- * This object has a ref count of zero.
+ * Returns a newly created object containing the scanned number. This
+ * object has a ref count of zero.
*
* Side effects:
- * Might reuse an object in the number cache, place a new object
- * in the cache, or delete the cache and set the reference to
- * it (itself passed in by reference) to NULL.
+ * Might reuse an object in the number cache, place a new object in the
+ * cache, or delete the cache and set the reference to it (itself passed
+ * in by reference) to NULL.
*
*----------------------------------------------------------------------
*/
static Tcl_Obj *
-ScanNumber(buffer, type, numberCachePtrPtr)
- unsigned char *buffer; /* Buffer to scan number from. */
- int type; /* Format character from "binary scan" */
- Tcl_HashTable **numberCachePtrPtr;
+ScanNumber(
+ unsigned char *buffer, /* Buffer to scan number from. */
+ int type, /* Format character from "binary scan" */
+ int flags, /* Format field flags */
+ Tcl_HashTable **numberCachePtrPtr)
/* Place to look for cache of scanned
* value objects, or NULL if too many
* different numbers have been scanned. */
{
long value;
+ float fvalue;
+ double dvalue;
Tcl_WideUInt uwvalue;
/*
* We cannot rely on the compiler to properly sign extend integer values
* when we cast from smaller values to larger values because we don't know
- * the exact size of the integer types. So, we have to handle sign
+ * the exact size of the integer types. So, we have to handle sign
* extension explicitly by checking the high bit and padding with 1's as
- * needed.
+ * needed. This practice is disabled if the BINARY_UNSIGNED flag is set.
*/
switch (type) {
- case 'c':
- /*
- * Characters need special handling. We want to produce a
- * signed result, but on some platforms (such as AIX) chars
- * are unsigned. To deal with this, check for a value that
- * should be negative but isn't.
- */
+ case 'c':
+ /*
+ * Characters need special handling. We want to produce a signed
+ * result, but on some platforms (such as AIX) chars are unsigned. To
+ * deal with this, check for a value that should be negative but
+ * isn't.
+ */
- value = buffer[0];
+ value = buffer[0];
+ if (!(flags & BINARY_UNSIGNED)) {
if (value & 0x80) {
value |= -0x100;
}
- goto returnNumericObject;
+ }
+ goto returnNumericObject;
+
+ /*
+ * 16-bit numeric values. We need the sign extension trick (see above)
+ * here as well.
+ */
- case 's':
+ case 's':
+ case 'S':
+ case 't':
+ if (NeedReversing(type)) {
value = (long) (buffer[0] + (buffer[1] << 8));
- goto shortValue;
- case 'S':
+ } else {
value = (long) (buffer[1] + (buffer[0] << 8));
- shortValue:
+ }
+ if (!(flags & BINARY_UNSIGNED)) {
if (value & 0x8000) {
value |= -0x10000;
}
- goto returnNumericObject;
+ }
+ goto returnNumericObject;
- case 'i':
- value = (long) (buffer[0]
+ /*
+ * 32-bit numeric values.
+ */
+
+ case 'i':
+ case 'I':
+ case 'n':
+ if (NeedReversing(type)) {
+ value = (long) (buffer[0]
+ (buffer[1] << 8)
+ (buffer[2] << 16)
- + (buffer[3] << 24));
- goto intValue;
- case 'I':
+ + (((long)buffer[3]) << 24));
+ } else {
value = (long) (buffer[3]
+ (buffer[2] << 8)
+ (buffer[1] << 16)
- + (buffer[0] << 24));
- intValue:
- /*
- * Check to see if the value was sign extended properly on
- * systems where an int is more than 32-bits.
- */
+ + (((long)buffer[0]) << 24));
+ }
+
+ /*
+ * Check to see if the value was sign extended properly on systems
+ * where an int is more than 32-bits.
+ * We avoid caching unsigned integers as we cannot distinguish between
+ * 32bit signed and unsigned in the hash (short and char are ok).
+ */
+
+ if (flags & BINARY_UNSIGNED) {
+ return Tcl_NewWideIntObj((Tcl_WideInt)(unsigned long)value);
+ }
+ if ((value & (((unsigned int)1)<<31)) && (value > 0)) {
+ value -= (((unsigned int)1)<<31);
+ value -= (((unsigned int)1)<<31);
+ }
+
+ returnNumericObject:
+ if (*numberCachePtrPtr == NULL) {
+ return Tcl_NewLongObj(value);
+ } else {
+ register Tcl_HashTable *tablePtr = *numberCachePtrPtr;
+ register Tcl_HashEntry *hPtr;
+ int isNew;
- if ((value & (((unsigned int)1)<<31)) && (value > 0)) {
- value -= (((unsigned int)1)<<31);
- value -= (((unsigned int)1)<<31);
+ hPtr = Tcl_CreateHashEntry(tablePtr, (char *)value, &isNew);
+ if (!isNew) {
+ return (Tcl_Obj *) Tcl_GetHashValue(hPtr);
}
- returnNumericObject:
- if (*numberCachePtrPtr == NULL) {
- return Tcl_NewLongObj(value);
- } else {
- register Tcl_HashTable *tablePtr = *numberCachePtrPtr;
- register Tcl_HashEntry *hPtr;
- int isNew;
-
- hPtr = Tcl_CreateHashEntry(tablePtr, (char *)value, &isNew);
- if (!isNew) {
- return (Tcl_Obj *) Tcl_GetHashValue(hPtr);
- }
- if (tablePtr->numEntries > BINARY_SCAN_MAX_CACHE) {
- /*
- * We've overflowed the cache! Someone's parsing
- * a LOT of varied binary data in a single call!
- * Bail out by switching back to the old behaviour
- * for the rest of the scan.
- *
- * Note that anyone just using the 'c' conversion
- * (for bytes) cannot trigger this.
- */
- DeleteScanNumberCache(tablePtr);
- *numberCachePtrPtr = NULL;
- return Tcl_NewLongObj(value);
- } else {
- register Tcl_Obj *objPtr = Tcl_NewLongObj(value);
+ if (tablePtr->numEntries <= BINARY_SCAN_MAX_CACHE) {
+ register Tcl_Obj *objPtr = Tcl_NewLongObj(value);
- Tcl_IncrRefCount(objPtr);
- Tcl_SetHashValue(hPtr, (ClientData) objPtr);
- return objPtr;
- }
+ Tcl_IncrRefCount(objPtr);
+ Tcl_SetHashValue(hPtr, (ClientData) objPtr);
+ return objPtr;
}
/*
- * Do not cache wide values; they are already too large to
- * use as keys.
+ * We've overflowed the cache! Someone's parsing a LOT of varied
+ * binary data in a single call! Bail out by switching back to the
+ * old behaviour for the rest of the scan.
+ *
+ * Note that anyone just using the 'c' conversion (for bytes)
+ * cannot trigger this.
*/
- case 'w':
- uwvalue = ((Tcl_WideUInt) buffer[0])
+
+ DeleteScanNumberCache(tablePtr);
+ *numberCachePtrPtr = NULL;
+ return Tcl_NewLongObj(value);
+ }
+
+ /*
+ * Do not cache wide (64-bit) values; they are already too large to
+ * use as keys.
+ */
+
+ case 'w':
+ case 'W':
+ case 'm':
+ if (NeedReversing(type)) {
+ uwvalue = ((Tcl_WideUInt) buffer[0])
| (((Tcl_WideUInt) buffer[1]) << 8)
| (((Tcl_WideUInt) buffer[2]) << 16)
| (((Tcl_WideUInt) buffer[3]) << 24)
@@ -1696,9 +1950,8 @@ ScanNumber(buffer, type, numberCachePtrPtr)
| (((Tcl_WideUInt) buffer[5]) << 40)
| (((Tcl_WideUInt) buffer[6]) << 48)
| (((Tcl_WideUInt) buffer[7]) << 56);
- return Tcl_NewWideIntObj((Tcl_WideInt) uwvalue);
- case 'W':
- uwvalue = ((Tcl_WideUInt) buffer[7])
+ } else {
+ uwvalue = ((Tcl_WideUInt) buffer[7])
| (((Tcl_WideUInt) buffer[6]) << 8)
| (((Tcl_WideUInt) buffer[5]) << 16)
| (((Tcl_WideUInt) buffer[4]) << 24)
@@ -1706,23 +1959,42 @@ ScanNumber(buffer, type, numberCachePtrPtr)
| (((Tcl_WideUInt) buffer[2]) << 40)
| (((Tcl_WideUInt) buffer[1]) << 48)
| (((Tcl_WideUInt) buffer[0]) << 56);
- return Tcl_NewWideIntObj((Tcl_WideInt) uwvalue);
-
- /*
- * Do not cache double values; they are already too large
- * to use as keys and the values stored are utterly
- * incompatible too.
- */
- case 'f': {
- float fvalue;
- memcpy((VOID *) &fvalue, (VOID *) buffer, sizeof(float));
- return Tcl_NewDoubleObj(fvalue);
}
- case 'd': {
- double dvalue;
- memcpy((VOID *) &dvalue, (VOID *) buffer, sizeof(double));
- return Tcl_NewDoubleObj(dvalue);
+ if (flags & BINARY_UNSIGNED) {
+ Tcl_Obj *bigObj = NULL;
+ mp_int big;
+
+ TclBNInitBignumFromWideUInt(&big, uwvalue);
+ bigObj = Tcl_NewBignumObj(&big);
+ return bigObj;
}
+ return Tcl_NewWideIntObj((Tcl_WideInt) uwvalue);
+
+ /*
+ * Do not cache double values; they are already too large to use as
+ * keys and the values stored are utterly incompatible with the
+ * integer part of the cache.
+ */
+
+ /*
+ * 32-bit IEEE single-precision floating point.
+ */
+
+ case 'f':
+ case 'R':
+ case 'r':
+ CopyNumber(buffer, &fvalue, sizeof(float), type);
+ return Tcl_NewDoubleObj(fvalue);
+
+ /*
+ * 64-bit IEEE double-precision floating point.
+ */
+
+ case 'd':
+ case 'Q':
+ case 'q':
+ CopyNumber(buffer, &dvalue, sizeof(double), type);
+ return Tcl_NewDoubleObj(dvalue);
}
return NULL;
}
@@ -1731,7 +2003,7 @@ ScanNumber(buffer, type, numberCachePtrPtr)
*----------------------------------------------------------------------
*
* DeleteScanNumberCache --
- *
+ *
* Deletes the hash table acting as a scan number cache.
*
* Results:
@@ -1744,10 +2016,11 @@ ScanNumber(buffer, type, numberCachePtrPtr)
*/
static void
-DeleteScanNumberCache(numberCachePtr)
- Tcl_HashTable *numberCachePtr; /* Pointer to the hash table, or
- * NULL (when the cache has already
- * been deleted due to overflow.) */
+DeleteScanNumberCache(
+ Tcl_HashTable *numberCachePtr)
+ /* Pointer to the hash table, or NULL (when
+ * the cache has already been deleted due to
+ * overflow.) */
{
Tcl_HashEntry *hEntry;
Tcl_HashSearch search;
@@ -1758,7 +2031,7 @@ DeleteScanNumberCache(numberCachePtr)
hEntry = Tcl_FirstHashEntry(numberCachePtr, &search);
while (hEntry != NULL) {
- register Tcl_Obj *value = (Tcl_Obj *) Tcl_GetHashValue(hEntry);
+ register Tcl_Obj *value = Tcl_GetHashValue(hEntry);
if (value != NULL) {
Tcl_DecrRefCount(value);
@@ -1767,3 +2040,11 @@ DeleteScanNumberCache(numberCachePtr)
}
Tcl_DeleteHashTable(numberCachePtr);
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclCkalloc.c b/generic/tclCkalloc.c
index e81eaea..c374ce5 100644
--- a/generic/tclCkalloc.c
+++ b/generic/tclCkalloc.c
@@ -1,21 +1,21 @@
/*
* tclCkalloc.c --
*
- * Interface to malloc and free that provides support for debugging problems
- * involving overwritten, double freeing memory and loss of memory.
+ * Interface to malloc and free that provides support for debugging
+ * problems involving overwritten, double freeing memory and loss of
+ * memory.
*
* Copyright (c) 1991-1994 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.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* This code contributed by Karl Lehenbauer and Mark Diekhans
*/
#include "tclInt.h"
-#include "tclPort.h"
#define FALSE 0
#define TRUE 1
@@ -28,29 +28,29 @@
*/
typedef struct MemTag {
- int refCount; /* Number of mem_headers referencing
- * this tag. */
- char string[4]; /* Actual size of string will be as
- * large as needed for actual tag. This
- * must be the last field in the structure. */
+ int refCount; /* Number of mem_headers referencing this
+ * tag. */
+ char string[4]; /* Actual size of string will be as large as
+ * needed for actual tag. This must be the
+ * last field in the structure. */
} MemTag;
#define TAG_SIZE(bytesInString) ((unsigned) sizeof(MemTag) + bytesInString - 3)
-static MemTag *curTagPtr = NULL;/* Tag to use in all future mem_headers
- * (set by "memory tag" command). */
+static MemTag *curTagPtr = NULL;/* Tag to use in all future mem_headers (set
+ * by "memory tag" command). */
/*
- * One of the following structures is allocated just before each
- * dynamically allocated chunk of memory, both to record information
- * about the chunk and to help detect chunk under-runs.
+ * One of the following structures is allocated just before each dynamically
+ * allocated chunk of memory, both to record information about the chunk and
+ * to help detect chunk under-runs.
*/
#define LOW_GUARD_SIZE (8 + (32 - (sizeof(long) + sizeof(int)))%8)
struct mem_header {
struct mem_header *flink;
struct mem_header *blink;
- MemTag *tagPtr; /* Tag from "memory tag" command; may be
+ MemTag *tagPtr; /* Tag from "memory tag" command; may be
* NULL. */
CONST char *file;
long length;
@@ -59,9 +59,8 @@ struct mem_header {
/* Aligns body on 8-byte boundary, plus
* provides at least 8 additional guard bytes
* to detect underruns. */
- char body[1]; /* First byte of client's space. Actual
- * size of this field will be larger than
- * one. */
+ char body[1]; /* First byte of client's space. Actual size
+ * of this field will be larger than one. */
};
static struct mem_header *allocHead = NULL; /* List of allocated structures */
@@ -69,16 +68,16 @@ static struct mem_header *allocHead = NULL; /* List of allocated structures */
#define GUARD_VALUE 0141
/*
- * The following macro determines the amount of guard space *above* each
- * chunk of memory.
+ * The following macro determines the amount of guard space *above* each chunk
+ * of memory.
*/
#define HIGH_GUARD_SIZE 8
/*
* The following macro computes the offset of the "body" field within
- * mem_header. It is used to get back to the header pointer from the
- * body pointer that's used by clients.
+ * mem_header. It is used to get back to the header pointer from the body
+ * pointer that's used by clients.
*/
#define BODY_OFFSET \
@@ -86,25 +85,25 @@ static struct mem_header *allocHead = NULL; /* List of allocated structures */
static int total_mallocs = 0;
static int total_frees = 0;
-static int current_bytes_malloced = 0;
-static int maximum_bytes_malloced = 0;
+static size_t current_bytes_malloced = 0;
+static size_t maximum_bytes_malloced = 0;
static int current_malloc_packets = 0;
static int maximum_malloc_packets = 0;
static int break_on_malloc = 0;
static int trace_on_at_malloc = 0;
-static int alloc_tracing = FALSE;
-static int init_malloced_bodies = TRUE;
+static int alloc_tracing = FALSE;
+static int init_malloced_bodies = TRUE;
#ifdef MEM_VALIDATE
- static int validate_memory = TRUE;
+static int validate_memory = TRUE;
#else
- static int validate_memory = FALSE;
+static int validate_memory = FALSE;
#endif
/*
- * The following variable indicates to TclFinalizeMemorySubsystem()
- * that it should dump out the state of memory before exiting. If the
- * value is non-NULL, it gives the name of the file in which to
- * dump memory usage information.
+ * The following variable indicates to TclFinalizeMemorySubsystem() that it
+ * should dump out the state of memory before exiting. If the value is
+ * non-NULL, it gives the name of the file in which to dump memory usage
+ * information.
*/
char *tclMemDumpFileName = NULL;
@@ -114,10 +113,11 @@ static char dumpFile[100]; /* Records where to dump memory allocation
* information. */
/*
- * Mutex to serialize allocations. This is a low-level mutex that must
- * be explicitly initialized. This is necessary because the self
- * initializing mutexes use ckalloc...
+ * Mutex to serialize allocations. This is a low-level mutex that must be
+ * explicitly initialized. This is necessary because the self initializing
+ * mutexes use ckalloc...
*/
+
static Tcl_Mutex *ckallocMutexPtr;
static int ckallocInit = 0;
@@ -125,26 +125,27 @@ static int ckallocInit = 0;
* Prototypes for procedures defined in this file:
*/
-static int CheckmemCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, CONST char *argv[]));
-static int MemoryCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static void ValidateMemory _ANSI_ARGS_((
- struct mem_header *memHeaderP, CONST char *file,
- int line, int nukeGuards));
+static int CheckmemCmd(ClientData clientData, Tcl_Interp *interp,
+ int argc, CONST char *argv[]);
+static int MemoryCmd(ClientData clientData, Tcl_Interp *interp,
+ int argc, CONST char *argv[]);
+static void ValidateMemory(struct mem_header *memHeaderP,
+ CONST char *file, int line, int nukeGuards);
/*
*----------------------------------------------------------------------
*
* TclInitDbCkalloc --
- * Initialize the locks used by the allocator.
- * This is only appropriate to call in a single threaded environment,
- * such as during TclInitSubsystems.
+ *
+ * Initialize the locks used by the allocator. This is only appropriate
+ * to call in a single threaded environment, such as during
+ * TclInitSubsystems.
*
*----------------------------------------------------------------------
*/
+
void
-TclInitDbCkalloc()
+TclInitDbCkalloc(void)
{
if (!ckallocInit) {
ckallocInit = 1;
@@ -156,29 +157,40 @@ TclInitDbCkalloc()
*----------------------------------------------------------------------
*
* TclDumpMemoryInfo --
- * Display the global memory management statistics.
+ *
+ * Display the global memory management statistics.
*
*----------------------------------------------------------------------
*/
-void
-TclDumpMemoryInfo(outFile)
- FILE *outFile;
+
+int
+TclDumpMemoryInfo(ClientData clientData, int flags)
{
- fprintf(outFile,"total mallocs %10d\n",
- total_mallocs);
- fprintf(outFile,"total frees %10d\n",
- total_frees);
- fprintf(outFile,"current packets allocated %10d\n",
- current_malloc_packets);
- fprintf(outFile,"current bytes allocated %10d\n",
- current_bytes_malloced);
- fprintf(outFile,"maximum packets allocated %10d\n",
- maximum_malloc_packets);
- fprintf(outFile,"maximum bytes allocated %10d\n",
- maximum_bytes_malloced);
+ char buf[1024];
+
+ if (clientData == NULL) { return 0; }
+ sprintf(buf,
+ "total mallocs %10d\n"
+ "total frees %10d\n"
+ "current packets allocated %10d\n"
+ "current bytes allocated %10lu\n"
+ "maximum packets allocated %10d\n"
+ "maximum bytes allocated %10lu\n",
+ total_mallocs,
+ total_frees,
+ current_malloc_packets,
+ (unsigned long)current_bytes_malloced,
+ maximum_malloc_packets,
+ (unsigned long)maximum_bytes_malloced);
+ if (flags == 0) {
+ fprintf((FILE *)clientData, buf);
+ } else {
+ /* Assume objPtr to append to */
+ Tcl_AppendToObj((Tcl_Obj *) clientData, buf, -1);
+ }
+ return 1;
}
-
/*
*----------------------------------------------------------------------
*
@@ -197,67 +209,68 @@ TclDumpMemoryInfo(outFile)
*/
static void
-ValidateMemory(memHeaderP, file, line, nukeGuards)
- struct mem_header *memHeaderP; /* Memory chunk to validate */
- CONST char *file; /* File containing the call to
- * Tcl_ValidateAllMemory */
- int line; /* Line number of call to
- * Tcl_ValidateAllMemory */
- int nukeGuards; /* If non-zero, indicates that the
- * memory guards are to be reset to 0
- * after they have been printed */
+ValidateMemory(
+ struct mem_header *memHeaderP,
+ /* Memory chunk to validate */
+ CONST char *file, /* File containing the call to
+ * Tcl_ValidateAllMemory */
+ int line, /* Line number of call to
+ * Tcl_ValidateAllMemory */
+ int nukeGuards) /* If non-zero, indicates that the memory
+ * guards are to be reset to 0 after they have
+ * been printed */
{
unsigned char *hiPtr;
- int idx;
- int guard_failed = FALSE;
+ size_t idx;
+ int guard_failed = FALSE;
int byte;
for (idx = 0; idx < LOW_GUARD_SIZE; idx++) {
- byte = *(memHeaderP->low_guard + idx);
- if (byte != GUARD_VALUE) {
- guard_failed = TRUE;
- fflush(stdout);
+ byte = *(memHeaderP->low_guard + idx);
+ if (byte != GUARD_VALUE) {
+ guard_failed = TRUE;
+ fflush(stdout);
byte &= 0xff;
- fprintf(stderr, "low guard byte %d is 0x%x \t%c\n", idx, byte,
+ fprintf(stderr, "low guard byte %d is 0x%x \t%c\n", (int)idx, byte,
(isprint(UCHAR(byte)) ? byte : ' ')); /* INTL: bytes */
- }
+ }
}
if (guard_failed) {
- TclDumpMemoryInfo (stderr);
- fprintf(stderr, "low guard failed at %lx, %s %d\n",
- (long unsigned int) memHeaderP->body, file, line);
- fflush(stderr); /* In case name pointer is bad. */
- fprintf(stderr, "%ld bytes allocated at (%s %d)\n", memHeaderP->length,
+ TclDumpMemoryInfo((ClientData) stderr, 0);
+ fprintf(stderr, "low guard failed at %lx, %s %d\n",
+ (long unsigned int) memHeaderP->body, file, line);
+ fflush(stderr); /* In case name pointer is bad. */
+ fprintf(stderr, "%ld bytes allocated at (%s %d)\n", memHeaderP->length,
memHeaderP->file, memHeaderP->line);
- panic ("Memory validation failure");
+ Tcl_Panic("Memory validation failure");
}
hiPtr = (unsigned char *)memHeaderP->body + memHeaderP->length;
for (idx = 0; idx < HIGH_GUARD_SIZE; idx++) {
- byte = *(hiPtr + idx);
- if (byte != GUARD_VALUE) {
- guard_failed = TRUE;
- fflush (stdout);
+ byte = *(hiPtr + idx);
+ if (byte != GUARD_VALUE) {
+ guard_failed = TRUE;
+ fflush(stdout);
byte &= 0xff;
- fprintf(stderr, "hi guard byte %d is 0x%x \t%c\n", idx, byte,
+ fprintf(stderr, "hi guard byte %d is 0x%x \t%c\n", (int)idx, byte,
(isprint(UCHAR(byte)) ? byte : ' ')); /* INTL: bytes */
- }
+ }
}
if (guard_failed) {
- TclDumpMemoryInfo (stderr);
- fprintf(stderr, "high guard failed at %lx, %s %d\n",
- (long unsigned int) memHeaderP->body, file, line);
- fflush(stderr); /* In case name pointer is bad. */
- fprintf(stderr, "%ld bytes allocated at (%s %d)\n",
+ TclDumpMemoryInfo((ClientData) stderr, 0);
+ fprintf(stderr, "high guard failed at %lx, %s %d\n",
+ (long unsigned int) memHeaderP->body, file, line);
+ fflush(stderr); /* In case name pointer is bad. */
+ fprintf(stderr, "%ld bytes allocated at (%s %d)\n",
memHeaderP->length, memHeaderP->file,
memHeaderP->line);
- panic("Memory validation failure");
+ Tcl_Panic("Memory validation failure");
}
if (nukeGuards) {
- memset ((char *) memHeaderP->low_guard, 0, LOW_GUARD_SIZE);
- memset ((char *) hiPtr, 0, HIGH_GUARD_SIZE);
+ memset(memHeaderP->low_guard, 0, LOW_GUARD_SIZE);
+ memset(hiPtr, 0, HIGH_GUARD_SIZE);
}
}
@@ -277,10 +290,13 @@ ValidateMemory(memHeaderP, file, line, nukeGuards)
*
*----------------------------------------------------------------------
*/
+
void
-Tcl_ValidateAllMemory (file, line)
- CONST char *file; /* File from which Tcl_ValidateAllMemory was called */
- int line; /* Line number of call to Tcl_ValidateAllMemory */
+Tcl_ValidateAllMemory(
+ CONST char *file, /* File from which Tcl_ValidateAllMemory was
+ * called. */
+ int line) /* Line number of call to
+ * Tcl_ValidateAllMemory */
{
struct mem_header *memScanP;
@@ -289,7 +305,7 @@ Tcl_ValidateAllMemory (file, line)
}
Tcl_MutexLock(ckallocMutexPtr);
for (memScanP = allocHead; memScanP != NULL; memScanP = memScanP->flink) {
- ValidateMemory(memScanP, file, line, FALSE);
+ ValidateMemory(memScanP, file, line, FALSE);
}
Tcl_MutexUnlock(ckallocMutexPtr);
}
@@ -303,17 +319,19 @@ Tcl_ValidateAllMemory (file, line)
* information will be written to stderr.
*
* Results:
- * Return TCL_ERROR if an error accessing the file occurs, `errno'
- * will have the file error number left in it.
+ * Return TCL_ERROR if an error accessing the file occurs, `errno' will
+ * have the file error number left in it.
+ *
*----------------------------------------------------------------------
*/
+
int
-Tcl_DumpActiveMemory (fileName)
- CONST char *fileName; /* Name of the file to write info to */
+Tcl_DumpActiveMemory(
+ CONST char *fileName) /* Name of the file to write info to */
{
- FILE *fileP;
+ FILE *fileP;
struct mem_header *memScanP;
- char *address;
+ char *address;
if (fileName == NULL) {
fileP = stderr;
@@ -326,18 +344,18 @@ Tcl_DumpActiveMemory (fileName)
Tcl_MutexLock(ckallocMutexPtr);
for (memScanP = allocHead; memScanP != NULL; memScanP = memScanP->flink) {
- address = &memScanP->body [0];
- fprintf(fileP, "%8lx - %8lx %7ld @ %s %d %s",
+ address = &memScanP->body [0];
+ fprintf(fileP, "%8lx - %8lx %7ld @ %s %d %s",
(long unsigned int) address,
- (long unsigned int) address + memScanP->length - 1,
- memScanP->length, memScanP->file, memScanP->line,
- (memScanP->tagPtr == NULL) ? "" : memScanP->tagPtr->string);
+ (long unsigned int) address + memScanP->length - 1,
+ memScanP->length, memScanP->file, memScanP->line,
+ (memScanP->tagPtr == NULL) ? "" : memScanP->tagPtr->string);
(void) fputc('\n', fileP);
}
Tcl_MutexUnlock(ckallocMutexPtr);
if (fileP != stderr) {
- fclose (fileP);
+ fclose(fileP);
}
return TCL_OK;
}
@@ -347,53 +365,54 @@ Tcl_DumpActiveMemory (fileName)
*
* Tcl_DbCkalloc - debugging ckalloc
*
- * Allocate the requested amount of space plus some extra for
- * guard bands at both ends of the request, plus a size, panicing
- * if there isn't enough space, then write in the guard bands
- * and return the address of the space in the middle that the
- * user asked for.
+ * Allocate the requested amount of space plus some extra for guard bands
+ * at both ends of the request, plus a size, panicing if there isn't
+ * enough space, then write in the guard bands and return the address of
+ * the space in the middle that the user asked for.
*
- * The second and third arguments are file and line, these contain
- * the filename and line number corresponding to the caller.
- * These are sent by the ckalloc macro; it uses the preprocessor
- * autodefines __FILE__ and __LINE__.
+ * The second and third arguments are file and line, these contain the
+ * filename and line number corresponding to the caller. These are sent
+ * by the ckalloc macro; it uses the preprocessor autodefines __FILE__
+ * and __LINE__.
*
*----------------------------------------------------------------------
*/
+
char *
-Tcl_DbCkalloc(size, file, line)
- unsigned int size;
- CONST char *file;
- int line;
+Tcl_DbCkalloc(
+ unsigned int size,
+ CONST char *file,
+ int line)
{
struct mem_header *result = NULL;
- if (validate_memory)
- Tcl_ValidateAllMemory (file, line);
-
+ if (validate_memory) {
+ Tcl_ValidateAllMemory(file, line);
+ }
/* Don't let size argument to TclpAlloc overflow */
- if (size <= UINT_MAX - HIGH_GUARD_SIZE - sizeof(struct mem_header)) {
+ if (size <= UINT_MAX - HIGH_GUARD_SIZE -sizeof(struct mem_header)) {
result = (struct mem_header *) TclpAlloc((unsigned)size +
sizeof(struct mem_header) + HIGH_GUARD_SIZE);
}
if (result == NULL) {
- fflush(stdout);
- TclDumpMemoryInfo(stderr);
- panic("unable to alloc %u bytes, %s line %d", size, file, line);
+ fflush(stdout);
+ TclDumpMemoryInfo((ClientData) stderr, 0);
+ Tcl_Panic("unable to alloc %u bytes, %s line %d", size, file, line);
}
/*
- * Fill in guard zones and size. Also initialize the contents of
- * the block with bogus bytes to detect uses of initialized data.
- * Link into allocated list.
+ * Fill in guard zones and size. Also initialize the contents of the block
+ * with bogus bytes to detect uses of initialized data. Link into
+ * allocated list.
*/
+
if (init_malloced_bodies) {
- memset ((VOID *) result, GUARD_VALUE,
+ memset(result, GUARD_VALUE,
size + sizeof(struct mem_header) + HIGH_GUARD_SIZE);
} else {
- memset ((char *) result->low_guard, GUARD_VALUE, LOW_GUARD_SIZE);
- memset (result->body + size, GUARD_VALUE, HIGH_GUARD_SIZE);
+ memset(result->low_guard, GUARD_VALUE, LOW_GUARD_SIZE);
+ memset(result->body + size, GUARD_VALUE, HIGH_GUARD_SIZE);
}
if (!ckallocInit) {
TclInitDbCkalloc();
@@ -409,56 +428,61 @@ Tcl_DbCkalloc(size, file, line)
result->flink = allocHead;
result->blink = NULL;
- if (allocHead != NULL)
- allocHead->blink = result;
+ if (allocHead != NULL) {
+ allocHead->blink = result;
+ }
allocHead = result;
total_mallocs++;
if (trace_on_at_malloc && (total_mallocs >= trace_on_at_malloc)) {
- (void) fflush(stdout);
- fprintf(stderr, "reached malloc trace enable point (%d)\n",
- total_mallocs);
- fflush(stderr);
- alloc_tracing = TRUE;
- trace_on_at_malloc = 0;
+ (void) fflush(stdout);
+ fprintf(stderr, "reached malloc trace enable point (%d)\n",
+ total_mallocs);
+ fflush(stderr);
+ alloc_tracing = TRUE;
+ trace_on_at_malloc = 0;
}
- if (alloc_tracing)
- fprintf(stderr,"ckalloc %lx %u %s %d\n",
+ if (alloc_tracing) {
+ fprintf(stderr,"ckalloc %lx %u %s %d\n",
(long unsigned int) result->body, size, file, line);
+ }
if (break_on_malloc && (total_mallocs >= break_on_malloc)) {
- break_on_malloc = 0;
- (void) fflush(stdout);
- fprintf(stderr,"reached malloc break limit (%d)\n",
- total_mallocs);
- fprintf(stderr, "program will now enter C debugger\n");
- (void) fflush(stderr);
+ break_on_malloc = 0;
+ (void) fflush(stdout);
+ fprintf(stderr,"reached malloc break limit (%d)\n",
+ total_mallocs);
+ fprintf(stderr, "program will now enter C debugger\n");
+ (void) fflush(stderr);
abort();
}
current_malloc_packets++;
- if (current_malloc_packets > maximum_malloc_packets)
- maximum_malloc_packets = current_malloc_packets;
+ if (current_malloc_packets > maximum_malloc_packets) {
+ maximum_malloc_packets = current_malloc_packets;
+ }
current_bytes_malloced += size;
- if (current_bytes_malloced > maximum_bytes_malloced)
- maximum_bytes_malloced = current_bytes_malloced;
+ if (current_bytes_malloced > maximum_bytes_malloced) {
+ maximum_bytes_malloced = current_bytes_malloced;
+ }
Tcl_MutexUnlock(ckallocMutexPtr);
return result->body;
}
-
+
char *
-Tcl_AttemptDbCkalloc(size, file, line)
- unsigned int size;
- CONST char *file;
- int line;
+Tcl_AttemptDbCkalloc(
+ unsigned int size,
+ CONST char *file,
+ int line)
{
struct mem_header *result = NULL;
- if (validate_memory)
- Tcl_ValidateAllMemory (file, line);
+ if (validate_memory) {
+ Tcl_ValidateAllMemory(file, line);
+ }
/* Don't let size argument to TclpAlloc overflow */
if (size <= UINT_MAX - HIGH_GUARD_SIZE - sizeof(struct mem_header)) {
@@ -466,22 +490,22 @@ Tcl_AttemptDbCkalloc(size, file, line)
sizeof(struct mem_header) + HIGH_GUARD_SIZE);
}
if (result == NULL) {
- fflush(stdout);
- TclDumpMemoryInfo(stderr);
+ fflush(stdout);
+ TclDumpMemoryInfo((ClientData) stderr, 0);
return NULL;
}
/*
- * Fill in guard zones and size. Also initialize the contents of
- * the block with bogus bytes to detect uses of initialized data.
- * Link into allocated list.
+ * Fill in guard zones and size. Also initialize the contents of the block
+ * with bogus bytes to detect uses of initialized data. Link into
+ * allocated list.
*/
if (init_malloced_bodies) {
- memset ((VOID *) result, GUARD_VALUE,
+ memset(result, GUARD_VALUE,
size + sizeof(struct mem_header) + HIGH_GUARD_SIZE);
} else {
- memset ((char *) result->low_guard, GUARD_VALUE, LOW_GUARD_SIZE);
- memset (result->body + size, GUARD_VALUE, HIGH_GUARD_SIZE);
+ memset(result->low_guard, GUARD_VALUE, LOW_GUARD_SIZE);
+ memset(result->body + size, GUARD_VALUE, HIGH_GUARD_SIZE);
}
if (!ckallocInit) {
TclInitDbCkalloc();
@@ -497,71 +521,73 @@ Tcl_AttemptDbCkalloc(size, file, line)
result->flink = allocHead;
result->blink = NULL;
- if (allocHead != NULL)
- allocHead->blink = result;
+ if (allocHead != NULL) {
+ allocHead->blink = result;
+ }
allocHead = result;
total_mallocs++;
if (trace_on_at_malloc && (total_mallocs >= trace_on_at_malloc)) {
- (void) fflush(stdout);
- fprintf(stderr, "reached malloc trace enable point (%d)\n",
- total_mallocs);
- fflush(stderr);
- alloc_tracing = TRUE;
- trace_on_at_malloc = 0;
+ (void) fflush(stdout);
+ fprintf(stderr, "reached malloc trace enable point (%d)\n",
+ total_mallocs);
+ fflush(stderr);
+ alloc_tracing = TRUE;
+ trace_on_at_malloc = 0;
}
- if (alloc_tracing)
- fprintf(stderr,"ckalloc %lx %u %s %d\n",
+ if (alloc_tracing) {
+ fprintf(stderr,"ckalloc %lx %u %s %d\n",
(long unsigned int) result->body, size, file, line);
+ }
if (break_on_malloc && (total_mallocs >= break_on_malloc)) {
- break_on_malloc = 0;
- (void) fflush(stdout);
- fprintf(stderr,"reached malloc break limit (%d)\n",
- total_mallocs);
- fprintf(stderr, "program will now enter C debugger\n");
- (void) fflush(stderr);
+ break_on_malloc = 0;
+ (void) fflush(stdout);
+ fprintf(stderr,"reached malloc break limit (%d)\n",
+ total_mallocs);
+ fprintf(stderr, "program will now enter C debugger\n");
+ (void) fflush(stderr);
abort();
}
current_malloc_packets++;
- if (current_malloc_packets > maximum_malloc_packets)
- maximum_malloc_packets = current_malloc_packets;
+ if (current_malloc_packets > maximum_malloc_packets) {
+ maximum_malloc_packets = current_malloc_packets;
+ }
current_bytes_malloced += size;
- if (current_bytes_malloced > maximum_bytes_malloced)
- maximum_bytes_malloced = current_bytes_malloced;
+ if (current_bytes_malloced > maximum_bytes_malloced) {
+ maximum_bytes_malloced = current_bytes_malloced;
+ }
Tcl_MutexUnlock(ckallocMutexPtr);
return result->body;
}
-
/*
*----------------------------------------------------------------------
*
* Tcl_DbCkfree - debugging ckfree
*
- * Verify that the low and high guards are intact, and if so
- * then free the buffer else panic.
+ * Verify that the low and high guards are intact, and if so then free
+ * the buffer else Tcl_Panic.
*
- * The guards are erased after being checked to catch duplicate
- * frees.
+ * The guards are erased after being checked to catch duplicate frees.
*
- * The second and third arguments are file and line, these contain
- * the filename and line number corresponding to the caller.
- * These are sent by the ckfree macro; it uses the preprocessor
- * autodefines __FILE__ and __LINE__.
+ * The second and third arguments are file and line, these contain the
+ * filename and line number corresponding to the caller. These are sent
+ * by the ckfree macro; it uses the preprocessor autodefines __FILE__ and
+ * __LINE__.
*
*----------------------------------------------------------------------
*/
int
-Tcl_DbCkfree(ptr, file, line)
- char *ptr;
- CONST char *file;
- int line;
+Tcl_DbCkfree(
+ char *ptr,
+ CONST char *file,
+ int line)
{
struct mem_header *memp;
@@ -570,28 +596,28 @@ Tcl_DbCkfree(ptr, file, line)
}
/*
- * The following cast is *very* tricky. Must convert the pointer
- * to an integer before doing arithmetic on it, because otherwise
- * the arithmetic will be done differently (and incorrectly) on
- * word-addressed machines such as Crays (will subtract only bytes,
- * even though BODY_OFFSET is in words on these machines).
+ * The following cast is *very* tricky. Must convert the pointer to an
+ * integer before doing arithmetic on it, because otherwise the arithmetic
+ * will be done differently (and incorrectly) on word-addressed machines
+ * such as Crays (will subtract only bytes, even though BODY_OFFSET is in
+ * words on these machines).
*/
memp = (struct mem_header *) (((size_t) ptr) - BODY_OFFSET);
if (alloc_tracing) {
- fprintf(stderr, "ckfree %lx %ld %s %d\n",
+ fprintf(stderr, "ckfree %lx %ld %s %d\n",
(long unsigned int) memp->body, memp->length, file, line);
}
if (validate_memory) {
- Tcl_ValidateAllMemory(file, line);
+ Tcl_ValidateAllMemory(file, line);
}
Tcl_MutexLock(ckallocMutexPtr);
ValidateMemory(memp, file, line, TRUE);
if (init_malloced_bodies) {
- memset((VOID *) ptr, GUARD_VALUE, (size_t) memp->length);
+ memset(ptr, GUARD_VALUE, (size_t) memp->length);
}
total_frees++;
@@ -608,12 +634,16 @@ Tcl_DbCkfree(ptr, file, line)
/*
* Delink from allocated list
*/
- if (memp->flink != NULL)
- memp->flink->blink = memp->blink;
- if (memp->blink != NULL)
- memp->blink->flink = memp->flink;
- if (allocHead == memp)
- allocHead = memp->flink;
+
+ if (memp->flink != NULL) {
+ memp->flink->blink = memp->blink;
+ }
+ if (memp->blink != NULL) {
+ memp->blink->flink = memp->flink;
+ }
+ if (allocHead == memp) {
+ allocHead = memp->flink;
+ }
TclpFree((char *) memp);
Tcl_MutexUnlock(ckallocMutexPtr);
@@ -625,21 +655,22 @@ Tcl_DbCkfree(ptr, file, line)
*
* Tcl_DbCkrealloc - debugging ckrealloc
*
- * Reallocate a chunk of memory by allocating a new one of the
- * right size, copying the old data to the new location, and then
- * freeing the old memory space, using all the memory checking
- * features of this package.
+ * Reallocate a chunk of memory by allocating a new one of the right
+ * size, copying the old data to the new location, and then freeing the
+ * old memory space, using all the memory checking features of this
+ * package.
*
*--------------------------------------------------------------------
*/
+
char *
-Tcl_DbCkrealloc(ptr, size, file, line)
- char *ptr;
- unsigned int size;
- CONST char *file;
- int line;
+Tcl_DbCkrealloc(
+ char *ptr,
+ unsigned int size,
+ CONST char *file,
+ int line)
{
- char *new;
+ char *newPtr;
unsigned int copySize;
struct mem_header *memp;
@@ -648,8 +679,7 @@ Tcl_DbCkrealloc(ptr, size, file, line)
}
/*
- * See comment from Tcl_DbCkfree before you change the following
- * line.
+ * See comment from Tcl_DbCkfree before you change the following line.
*/
memp = (struct mem_header *) (((size_t) ptr) - BODY_OFFSET);
@@ -658,20 +688,20 @@ Tcl_DbCkrealloc(ptr, size, file, line)
if (copySize > (unsigned int) memp->length) {
copySize = memp->length;
}
- new = Tcl_DbCkalloc(size, file, line);
- memcpy((VOID *) new, (VOID *) ptr, (size_t) copySize);
+ newPtr = Tcl_DbCkalloc(size, file, line);
+ memcpy(newPtr, ptr, (size_t) copySize);
Tcl_DbCkfree(ptr, file, line);
- return new;
+ return newPtr;
}
-
+
char *
-Tcl_AttemptDbCkrealloc(ptr, size, file, line)
- char *ptr;
- unsigned int size;
- CONST char *file;
- int line;
+Tcl_AttemptDbCkrealloc(
+ char *ptr,
+ unsigned int size,
+ CONST char *file,
+ int line)
{
- char *new;
+ char *newPtr;
unsigned int copySize;
struct mem_header *memp;
@@ -680,8 +710,7 @@ Tcl_AttemptDbCkrealloc(ptr, size, file, line)
}
/*
- * See comment from Tcl_DbCkfree before you change the following
- * line.
+ * See comment from Tcl_DbCkfree before you change the following line.
*/
memp = (struct mem_header *) (((size_t) ptr) - BODY_OFFSET);
@@ -690,13 +719,13 @@ Tcl_AttemptDbCkrealloc(ptr, size, file, line)
if (copySize > (unsigned int) memp->length) {
copySize = memp->length;
}
- new = Tcl_AttemptDbCkalloc(size, file, line);
- if (new == NULL) {
+ newPtr = Tcl_AttemptDbCkalloc(size, file, line);
+ if (newPtr == NULL) {
return NULL;
}
- memcpy((VOID *) new, (VOID *) ptr, (size_t) copySize);
+ memcpy(newPtr, ptr, (size_t) copySize);
Tcl_DbCkfree(ptr, file, line);
- return new;
+ return newPtr;
}
@@ -705,8 +734,8 @@ Tcl_AttemptDbCkrealloc(ptr, size, file, line)
*
* Tcl_Alloc, et al. --
*
- * These functions are defined in terms of the debugging versions
- * when TCL_MEM_DEBUG is set.
+ * These functions are defined in terms of the debugging versions when
+ * TCL_MEM_DEBUG is set.
*
* Results:
* Same as the debug versions.
@@ -724,37 +753,37 @@ Tcl_AttemptDbCkrealloc(ptr, size, file, line)
#undef Tcl_AttemptRealloc
char *
-Tcl_Alloc(size)
- unsigned int size;
+Tcl_Alloc(
+ unsigned int size)
{
return Tcl_DbCkalloc(size, "unknown", 0);
}
char *
-Tcl_AttemptAlloc(size)
- unsigned int size;
+Tcl_AttemptAlloc(
+ unsigned int size)
{
return Tcl_AttemptDbCkalloc(size, "unknown", 0);
}
void
-Tcl_Free(ptr)
- char *ptr;
+Tcl_Free(
+ char *ptr)
{
Tcl_DbCkfree(ptr, "unknown", 0);
}
char *
-Tcl_Realloc(ptr, size)
- char *ptr;
- unsigned int size;
+Tcl_Realloc(
+ char *ptr,
+ unsigned int size)
{
return Tcl_DbCkrealloc(ptr, size, "unknown", 0);
}
char *
-Tcl_AttemptRealloc(ptr, size)
- char *ptr;
- unsigned int size;
+Tcl_AttemptRealloc(
+ char *ptr,
+ unsigned int size)
{
return Tcl_AttemptDbCkrealloc(ptr, size, "unknown", 0);
}
@@ -763,8 +792,9 @@ Tcl_AttemptRealloc(ptr, size)
*----------------------------------------------------------------------
*
* MemoryCmd --
- * Implements the Tcl "memory" command, which provides Tcl-level
- * control of Tcl memory debugging information.
+ *
+ * Implements the Tcl "memory" command, which provides Tcl-level control
+ * of Tcl memory debugging information.
* memory active $file
* memory break_on_malloc $count
* memory info
@@ -776,33 +806,34 @@ Tcl_AttemptRealloc(ptr, size)
* memory validate on|off
*
* Results:
- * Standard TCL results.
+ * Standard TCL results.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
static int
-MemoryCmd (clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- CONST char **argv;
+MemoryCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int argc,
+ CONST char *argv[])
{
CONST char *fileName;
+ FILE *fileP;
Tcl_DString buffer;
int result;
size_t len;
if (argc < 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " option [args..]\"", (char *) NULL);
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " option [args..]\"", NULL);
return TCL_ERROR;
}
if ((strcmp(argv[1],"active") == 0) || (strcmp(argv[1],"display") == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " ", argv[1], " file\"", (char *) NULL);
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " ", argv[1], " file\"", NULL);
return TCL_ERROR;
}
fileName = Tcl_TranslateFileName(interp, argv[2], &buffer);
@@ -812,43 +843,61 @@ MemoryCmd (clientData, interp, argc, argv)
result = Tcl_DumpActiveMemory (fileName);
Tcl_DStringFree(&buffer);
if (result != TCL_OK) {
- Tcl_AppendResult(interp, "error accessing ", argv[2],
- (char *) NULL);
+ Tcl_AppendResult(interp, "error accessing ", argv[2], NULL);
return TCL_ERROR;
}
return TCL_OK;
}
if (strcmp(argv[1],"break_on_malloc") == 0) {
- if (argc != 3) {
- goto argError;
+ if (argc != 3) {
+ goto argError;
}
- if (Tcl_GetInt(interp, argv[2], &break_on_malloc) != TCL_OK) {
+ if (Tcl_GetInt(interp, argv[2], &break_on_malloc) != TCL_OK) {
return TCL_ERROR;
}
- return TCL_OK;
+ return TCL_OK;
}
if (strcmp(argv[1],"info") == 0) {
- char buf[400];
- sprintf(buf, "%-25s %10d\n%-25s %10d\n%-25s %10d\n%-25s %10d\n%-25s %10d\n%-25s %10d\n",
- "total mallocs", total_mallocs, "total frees", total_frees,
- "current packets allocated", current_malloc_packets,
- "current bytes allocated", current_bytes_malloced,
- "maximum packets allocated", maximum_malloc_packets,
- "maximum bytes allocated", maximum_bytes_malloced);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
- return TCL_OK;
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "%-25s %10d\n%-25s %10d\n%-25s %10d\n%-25s %10lu\n%-25s %10d\n%-25s %10lu\n",
+ "total mallocs", total_mallocs, "total frees", total_frees,
+ "current packets allocated", current_malloc_packets,
+ "current bytes allocated", current_bytes_malloced,
+ "maximum packets allocated", maximum_malloc_packets,
+ "maximum bytes allocated", maximum_bytes_malloced));
+ return TCL_OK;
}
if (strcmp(argv[1],"init") == 0) {
- if (argc != 3) {
- goto bad_suboption;
+ if (argc != 3) {
+ goto bad_suboption;
+ }
+ init_malloced_bodies = (strcmp(argv[2],"on") == 0);
+ return TCL_OK;
+ }
+ if (strcmp(argv[1],"objs") == 0) {
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " objs file\"", NULL);
+ return TCL_ERROR;
+ }
+ fileName = Tcl_TranslateFileName(interp, argv[2], &buffer);
+ if (fileName == NULL) {
+ return TCL_ERROR;
+ }
+ fileP = fopen(fileName, "w");
+ if (fileP == NULL) {
+ Tcl_AppendResult(interp, "cannot open output file", NULL);
+ return TCL_ERROR;
}
- init_malloced_bodies = (strcmp(argv[2],"on") == 0);
- return TCL_OK;
+ TclDbDumpActiveObjects(fileP);
+ fclose(fileP);
+ Tcl_DStringFree(&buffer);
+ return TCL_OK;
}
if (strcmp(argv[1],"onexit") == 0) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " onexit file\"", (char *) NULL);
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " onexit file\"", NULL);
return TCL_ERROR;
}
fileName = Tcl_TranslateFileName(interp, argv[2], &buffer);
@@ -863,7 +912,7 @@ MemoryCmd (clientData, interp, argc, argv)
if (strcmp(argv[1],"tag") == 0) {
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " tag string\"", (char *) NULL);
+ " tag string\"", NULL);
return TCL_ERROR;
}
if ((curTagPtr != NULL) && (curTagPtr->refCount == 0)) {
@@ -876,43 +925,43 @@ MemoryCmd (clientData, interp, argc, argv)
return TCL_OK;
}
if (strcmp(argv[1],"trace") == 0) {
- if (argc != 3) {
- goto bad_suboption;
+ if (argc != 3) {
+ goto bad_suboption;
}
- alloc_tracing = (strcmp(argv[2],"on") == 0);
- return TCL_OK;
+ alloc_tracing = (strcmp(argv[2],"on") == 0);
+ return TCL_OK;
}
if (strcmp(argv[1],"trace_on_at_malloc") == 0) {
- if (argc != 3) {
- goto argError;
+ if (argc != 3) {
+ goto argError;
}
- if (Tcl_GetInt(interp, argv[2], &trace_on_at_malloc) != TCL_OK) {
+ if (Tcl_GetInt(interp, argv[2], &trace_on_at_malloc) != TCL_OK) {
return TCL_ERROR;
}
return TCL_OK;
}
if (strcmp(argv[1],"validate") == 0) {
- if (argc != 3) {
+ if (argc != 3) {
goto bad_suboption;
}
- validate_memory = (strcmp(argv[2],"on") == 0);
- return TCL_OK;
+ validate_memory = (strcmp(argv[2],"on") == 0);
+ return TCL_OK;
}
Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": should be active, break_on_malloc, info, init, onexit, ",
- "tag, trace, trace_on_at_malloc, or validate", (char *) NULL);
+ "\": should be active, break_on_malloc, info, init, onexit, "
+ "tag, trace, trace_on_at_malloc, or validate", NULL);
return TCL_ERROR;
-argError:
+ argError:
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ", argv[1], " count\"", (char *) NULL);
+ " ", argv[1], " count\"", NULL);
return TCL_ERROR;
-bad_suboption:
+ bad_suboption:
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ", argv[1], " on|off\"", (char *) NULL);
+ " ", argv[1], " on|off\"", NULL);
return TCL_ERROR;
}
@@ -921,10 +970,9 @@ bad_suboption:
*
* CheckmemCmd --
*
- * This is the command procedure for the "checkmem" command, which
- * causes the application to exit after printing information about
- * memory usage to the file passed to this command as its first
- * argument.
+ * This is the command procedure for the "checkmem" command, which causes
+ * the application to exit after printing information about memory usage
+ * to the file passed to this command as its first argument.
*
* Results:
* Returns a standard Tcl completion code.
@@ -936,15 +984,15 @@ bad_suboption:
*/
static int
-CheckmemCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Interpreter for evaluation. */
- int argc; /* Number of arguments. */
- CONST char *argv[]; /* String values of arguments. */
+CheckmemCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter for evaluation. */
+ int argc, /* Number of arguments. */
+ CONST char *argv[]) /* String values of arguments. */
{
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " fileName\"", (char *) NULL);
+ " fileName\"", NULL);
return TCL_ERROR;
}
tclMemDumpFileName = dumpFile;
@@ -957,8 +1005,7 @@ CheckmemCmd(clientData, interp, argc, argv)
*
* Tcl_InitMemory --
*
- * Create the "memory" and "checkmem" commands in the given
- * interpreter.
+ * Create the "memory" and "checkmem" commands in the given interpreter.
*
* Results:
* None.
@@ -970,14 +1017,13 @@ CheckmemCmd(clientData, interp, argc, argv)
*/
void
-Tcl_InitMemory(interp)
- Tcl_Interp *interp; /* Interpreter in which commands should be added */
+Tcl_InitMemory(
+ Tcl_Interp *interp) /* Interpreter in which commands should be
+ * added */
{
TclInitDbCkalloc();
- Tcl_CreateCommand (interp, "memory", MemoryCmd, (ClientData) NULL,
- (Tcl_CmdDeleteProc *) NULL);
- Tcl_CreateCommand(interp, "checkmem", CheckmemCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
+ Tcl_CreateCommand(interp, "memory", MemoryCmd, (ClientData) NULL, NULL);
+ Tcl_CreateCommand(interp, "checkmem", CheckmemCmd, (ClientData) 0, NULL);
}
@@ -994,47 +1040,50 @@ Tcl_InitMemory(interp)
*----------------------------------------------------------------------
*
* Tcl_Alloc --
- * Interface to TclpAlloc when TCL_MEM_DEBUG is disabled. It does check
- * that memory was actually allocated.
+ *
+ * Interface to TclpAlloc when TCL_MEM_DEBUG is disabled. It does check
+ * that memory was actually allocated.
*
*----------------------------------------------------------------------
*/
char *
-Tcl_Alloc (size)
- unsigned int size;
+Tcl_Alloc(
+ unsigned int size)
{
char *result;
result = TclpAlloc(size);
+
/*
- * Most systems will not alloc(0), instead bumping it to one so
- * that NULL isn't returned. Some systems (AIX, Tru64) will alloc(0)
- * by returning NULL, so we have to check that the NULL we get is
- * not in response to alloc(0).
+ * Most systems will not alloc(0), instead bumping it to one so that NULL
+ * isn't returned. Some systems (AIX, Tru64) will alloc(0) by returning
+ * NULL, so we have to check that the NULL we get is not in response to
+ * alloc(0).
*
- * The ANSI spec actually says that systems either return NULL *or*
- * a special pointer on failure, but we only check for NULL
+ * The ANSI spec actually says that systems either return NULL *or* a
+ * special pointer on failure, but we only check for NULL
*/
+
if ((result == NULL) && size) {
- panic("unable to alloc %u bytes", size);
+ Tcl_Panic("unable to alloc %u bytes", size);
}
return result;
}
char *
-Tcl_DbCkalloc(size, file, line)
- unsigned int size;
- CONST char *file;
- int line;
+Tcl_DbCkalloc(
+ unsigned int size,
+ CONST char *file,
+ int line)
{
char *result;
result = (char *) TclpAlloc(size);
if ((result == NULL) && size) {
- fflush(stdout);
- panic("unable to alloc %u bytes, %s line %d", size, file, line);
+ fflush(stdout);
+ Tcl_Panic("unable to alloc %u bytes, %s line %d", size, file, line);
}
return result;
}
@@ -1043,15 +1092,16 @@ Tcl_DbCkalloc(size, file, line)
*----------------------------------------------------------------------
*
* Tcl_AttemptAlloc --
- * Interface to TclpAlloc when TCL_MEM_DEBUG is disabled. It does not
- * check that memory was actually allocated.
+ *
+ * Interface to TclpAlloc when TCL_MEM_DEBUG is disabled. It does not
+ * check that memory was actually allocated.
*
*----------------------------------------------------------------------
*/
char *
-Tcl_AttemptAlloc (size)
- unsigned int size;
+Tcl_AttemptAlloc(
+ unsigned int size)
{
char *result;
@@ -1060,57 +1110,57 @@ Tcl_AttemptAlloc (size)
}
char *
-Tcl_AttemptDbCkalloc(size, file, line)
- unsigned int size;
- CONST char *file;
- int line;
+Tcl_AttemptDbCkalloc(
+ unsigned int size,
+ CONST char *file,
+ int line)
{
char *result;
result = (char *) TclpAlloc(size);
return result;
}
-
/*
*----------------------------------------------------------------------
*
* Tcl_Realloc --
- * Interface to TclpRealloc when TCL_MEM_DEBUG is disabled. It does
- * check that memory was actually allocated.
+ *
+ * Interface to TclpRealloc when TCL_MEM_DEBUG is disabled. It does check
+ * that memory was actually allocated.
*
*----------------------------------------------------------------------
*/
char *
-Tcl_Realloc(ptr, size)
- char *ptr;
- unsigned int size;
+Tcl_Realloc(
+ char *ptr,
+ unsigned int size)
{
char *result;
result = TclpRealloc(ptr, size);
if ((result == NULL) && size) {
- panic("unable to realloc %u bytes", size);
+ Tcl_Panic("unable to realloc %u bytes", size);
}
return result;
}
char *
-Tcl_DbCkrealloc(ptr, size, file, line)
- char *ptr;
- unsigned int size;
- CONST char *file;
- int line;
+Tcl_DbCkrealloc(
+ char *ptr,
+ unsigned int size,
+ CONST char *file,
+ int line)
{
char *result;
result = (char *) TclpRealloc(ptr, size);
if ((result == NULL) && size) {
- fflush(stdout);
- panic("unable to realloc %u bytes, %s line %d", size, file, line);
+ fflush(stdout);
+ Tcl_Panic("unable to realloc %u bytes, %s line %d", size, file, line);
}
return result;
}
@@ -1119,16 +1169,17 @@ Tcl_DbCkrealloc(ptr, size, file, line)
*----------------------------------------------------------------------
*
* Tcl_AttemptRealloc --
- * Interface to TclpRealloc when TCL_MEM_DEBUG is disabled. It does
- * not check that memory was actually allocated.
+ *
+ * Interface to TclpRealloc when TCL_MEM_DEBUG is disabled. It does not
+ * check that memory was actually allocated.
*
*----------------------------------------------------------------------
*/
char *
-Tcl_AttemptRealloc(ptr, size)
- char *ptr;
- unsigned int size;
+Tcl_AttemptRealloc(
+ char *ptr,
+ unsigned int size)
{
char *result;
@@ -1137,11 +1188,11 @@ Tcl_AttemptRealloc(ptr, size)
}
char *
-Tcl_AttemptDbCkrealloc(ptr, size, file, line)
- char *ptr;
- unsigned int size;
- CONST char *file;
- int line;
+Tcl_AttemptDbCkrealloc(
+ char *ptr,
+ unsigned int size,
+ CONST char *file,
+ int line)
{
char *result;
@@ -1153,25 +1204,26 @@ Tcl_AttemptDbCkrealloc(ptr, size, file, line)
*----------------------------------------------------------------------
*
* Tcl_Free --
- * Interface to TclpFree when TCL_MEM_DEBUG is disabled. Done here
- * rather in the macro to keep some modules from being compiled with
- * TCL_MEM_DEBUG enabled and some with it disabled.
+ *
+ * Interface to TclpFree when TCL_MEM_DEBUG is disabled. Done here rather
+ * in the macro to keep some modules from being compiled with
+ * TCL_MEM_DEBUG enabled and some with it disabled.
*
*----------------------------------------------------------------------
*/
void
-Tcl_Free (ptr)
- char *ptr;
+Tcl_Free(
+ char *ptr)
{
TclpFree(ptr);
}
int
-Tcl_DbCkfree(ptr, file, line)
- char *ptr;
- CONST char *file;
- int line;
+Tcl_DbCkfree(
+ char *ptr,
+ CONST char *file,
+ int line)
{
TclpFree(ptr);
return 0;
@@ -1181,36 +1233,37 @@ Tcl_DbCkfree(ptr, file, line)
*----------------------------------------------------------------------
*
* Tcl_InitMemory --
- * Dummy initialization for memory command, which is only available
- * if TCL_MEM_DEBUG is on.
+ *
+ * Dummy initialization for memory command, which is only available if
+ * TCL_MEM_DEBUG is on.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
void
-Tcl_InitMemory(interp)
- Tcl_Interp *interp;
+Tcl_InitMemory(
+ Tcl_Interp *interp)
{
}
int
-Tcl_DumpActiveMemory(fileName)
- CONST char *fileName;
+Tcl_DumpActiveMemory(
+ CONST char *fileName)
{
return TCL_OK;
}
void
-Tcl_ValidateAllMemory(file, line)
- CONST char *file;
- int line;
+Tcl_ValidateAllMemory(
+ CONST char *file,
+ int line)
{
}
-void
-TclDumpMemoryInfo(outFile)
- FILE *outFile;
+int
+TclDumpMemoryInfo(ClientData clientData, int flags)
{
+ return 1;
}
#endif /* TCL_MEM_DEBUG */
@@ -1220,23 +1273,22 @@ TclDumpMemoryInfo(outFile)
*
* TclFinalizeMemorySubsystem --
*
- * This procedure is called to finalize all the structures that
- * are used by the memory allocator on a per-process basis.
+ * This procedure is called to finalize all the structures that are used
+ * by the memory allocator on a per-process basis.
*
* Results:
* None.
*
* Side effects:
- * This subsystem is self-initializing, since memory can be
- * allocated before Tcl is formally initialized. After this call,
- * this subsystem has been reset to its initial state and is
- * usable again.
+ * This subsystem is self-initializing, since memory can be allocated
+ * before Tcl is formally initialized. After this call, this subsystem
+ * has been reset to its initial state and is usable again.
*
*---------------------------------------------------------------------------
*/
void
-TclFinalizeMemorySubsystem()
+TclFinalizeMemorySubsystem(void)
{
#ifdef TCL_MEM_DEBUG
if (tclMemDumpFileName != NULL) {
@@ -1244,12 +1296,15 @@ TclFinalizeMemorySubsystem()
} else if (onExitMemDumpFileName != NULL) {
Tcl_DumpActiveMemory(onExitMemDumpFileName);
}
+
Tcl_MutexLock(ckallocMutexPtr);
+
if (curTagPtr != NULL) {
TclpFree((char *) curTagPtr);
curTagPtr = NULL;
}
allocHead = NULL;
+
Tcl_MutexUnlock(ckallocMutexPtr);
#endif
@@ -1257,3 +1312,11 @@ TclFinalizeMemorySubsystem()
TclFinalizeAllocSubsystem();
#endif
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclClock.c b/generic/tclClock.c
index 2c00a07..5b95ae6 100644
--- a/generic/tclClock.c
+++ b/generic/tclClock.c
@@ -1,23 +1,136 @@
-/*
+/*
* tclClock.c --
*
- * Contains the time and date related commands. This code
- * is derived from the time and date facilities of TclX,
- * by Mark Diekhans and Karl Lehenbauer.
+ * Contains the time and date related commands. This code is derived from
+ * the time and date facilities of TclX, by Mark Diekhans and Karl
+ * Lehenbauer.
*
* Copyright 1991-1995 Karl Lehenbauer and Mark Diekhans.
* Copyright (c) 1995 Sun Microsystems, Inc.
+ * Copyright (c) 2004 by Kevin B. Kenny. All rights reserved.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
-#include "tcl.h"
#include "tclInt.h"
-#include "tclPort.h"
/*
- * The date parsing stuff uses lexx and has tons o statics.
+ * Windows has mktime. The configurators do not check.
+ */
+
+#ifdef __WIN32__
+#define HAVE_MKTIME 1
+#endif
+
+/*
+ * Constants
+ */
+
+#define JULIAN_DAY_POSIX_EPOCH 2440588
+#define SECONDS_PER_DAY 86400
+#define JULIAN_SEC_POSIX_EPOCH (((Tcl_WideInt) JULIAN_DAY_POSIX_EPOCH) \
+ * SECONDS_PER_DAY)
+#define FOUR_CENTURIES 146097 /* days */
+#define JDAY_1_JAN_1_CE_JULIAN 1721424
+#define JDAY_1_JAN_1_CE_GREGORIAN 1721426
+#define ONE_CENTURY_GREGORIAN 36524 /* days */
+#define FOUR_YEARS 1461 /* days */
+#define ONE_YEAR 365 /* days */
+
+/*
+ * Table of the days in each month, leap and common years
+ */
+
+static const int hath[2][12] = {
+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+ {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
+};
+static const int daysInPriorMonths[2][13] = {
+ {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
+ {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
+};
+
+/*
+ * Enumeration of the string literals used in [clock]
+ */
+
+typedef enum ClockLiteral {
+ LIT__NIL,
+ LIT__DEFAULT_FORMAT,
+ LIT_BCE, LIT_C,
+ LIT_CANNOT_USE_GMT_AND_TIMEZONE,
+ LIT_CE,
+ LIT_DAYOFMONTH, LIT_DAYOFWEEK, LIT_DAYOFYEAR,
+ LIT_ERA, LIT_GMT, LIT_GREGORIAN,
+ LIT_INTEGER_VALUE_TOO_LARGE,
+ LIT_ISO8601WEEK, LIT_ISO8601YEAR,
+ LIT_JULIANDAY, LIT_LOCALSECONDS,
+ LIT_MONTH,
+ LIT_SECONDS, LIT_TZNAME, LIT_TZOFFSET,
+ LIT_YEAR,
+ LIT__END
+} ClockLiteral;
+static const char *const literals[] = {
+ "",
+ "%a %b %d %H:%M:%S %Z %Y",
+ "BCE", "C",
+ "cannot use -gmt and -timezone in same call",
+ "CE",
+ "dayOfMonth", "dayOfWeek", "dayOfYear",
+ "era", ":GMT", "gregorian",
+ "integer value too large to represent",
+ "iso8601Week", "iso8601Year",
+ "julianDay", "localSeconds",
+ "month",
+ "seconds", "tzName", "tzOffset",
+ "year"
+};
+
+/*
+ * Structure containing the client data for [clock]
+ */
+
+typedef struct ClockClientData {
+ int refCount; /* Number of live references */
+ Tcl_Obj** literals; /* Pool of object literals */
+} ClockClientData;
+
+/*
+ * Structure containing the fields used in [clock format] and [clock scan]
+ */
+
+typedef struct TclDateFields {
+ Tcl_WideInt seconds; /* Time expressed in seconds from the Posix
+ * epoch */
+ Tcl_WideInt localSeconds; /* Local time expressed in nominal seconds
+ * from the Posix epoch */
+ int tzOffset; /* Time zone offset in seconds east of
+ * Greenwich */
+ Tcl_Obj* tzName; /* Time zone name */
+ int julianDay; /* Julian Day Number in local time zone */
+ enum {BCE=1, CE=0} era; /* Era */
+ int gregorian; /* Flag == 1 if the date is Gregorian */
+ int year; /* Year of the era */
+ int dayOfYear; /* Day of the year (1 January == 1) */
+ int month; /* Month number */
+ int dayOfMonth; /* Day of the month */
+ int iso8601Year; /* ISO8601 week-based year */
+ int iso8601Week; /* ISO8601 week number */
+ int dayOfWeek; /* Day of the week */
+} TclDateFields;
+static const char* eras[] = { "CE", "BCE", NULL };
+
+/*
+ * Thread specific data block holding a 'struct tm' for the 'gmtime' and
+ * 'localtime' library calls.
+ */
+
+static Tcl_ThreadDataKey tmKey;
+
+/*
+ * Mutex protecting 'gmtime', 'localtime' and 'mktime' calls and the statics
+ * in the date parsing code.
*/
TCL_DECLARE_MUTEX(clockMutex)
@@ -26,366 +139,1914 @@ TCL_DECLARE_MUTEX(clockMutex)
* Function prototypes for local procedures in this file:
*/
-static int FormatClock _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_WideInt clockVal, int useGMT,
- char *format));
+static int ConvertUTCToLocal(Tcl_Interp*,
+ TclDateFields*, Tcl_Obj*, int);
+static int ConvertUTCToLocalUsingTable(Tcl_Interp*,
+ TclDateFields*, int, Tcl_Obj *const[]);
+static int ConvertUTCToLocalUsingC(Tcl_Interp*,
+ TclDateFields*, int);
+static int ConvertLocalToUTC(Tcl_Interp*,
+ TclDateFields*, Tcl_Obj*, int);
+static int ConvertLocalToUTCUsingTable(Tcl_Interp*,
+ TclDateFields*, int, Tcl_Obj *const[]);
+static int ConvertLocalToUTCUsingC(Tcl_Interp*,
+ TclDateFields*, int);
+static Tcl_Obj* LookupLastTransition(Tcl_Interp*, Tcl_WideInt,
+ int, Tcl_Obj *const *);
+static void GetYearWeekDay(TclDateFields*, int);
+static void GetGregorianEraYearDay(TclDateFields*, int);
+static void GetMonthDay(TclDateFields*);
+static void GetJulianDayFromEraYearWeekDay(TclDateFields*, int);
+static void GetJulianDayFromEraYearMonthDay(TclDateFields*, int);
+static int IsGregorianLeapYear(TclDateFields*);
+static int WeekdayOnOrBefore(int, int);
+static int ClockClicksObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int ClockConvertlocaltoutcObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int ClockGetdatefieldsObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int ClockGetjuliandayfromerayearmonthdayObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int ClockGetjuliandayfromerayearweekdayObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int ClockGetenvObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int ClockMicrosecondsObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int ClockMillisecondsObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int ClockParseformatargsObjCmd(
+ ClientData clientData, Tcl_Interp* interp,
+ int objc, Tcl_Obj *const objv[]);
+static int ClockSecondsObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static struct tm * ThreadSafeLocalTime(const time_t *);
+static void TzsetIfNecessary(void);
+static void ClockDeleteCmdProc(ClientData);
+
+/*
+ * Structure containing description of "native" clock commands to create.
+ */
+
+struct ClockCommand {
+ const char *name; /* The tail of the command name. The full name
+ * is "::tcl::clock::<name>". When NULL marks
+ * the end of the table. */
+ Tcl_ObjCmdProc *objCmdProc; /* Function that implements the command. This
+ * will always have the ClockClientData sent
+ * to it, but may well ignore this data. */
+};
+
+static const struct ClockCommand clockCommands[] = {
+ { "clicks", ClockClicksObjCmd },
+ { "getenv", ClockGetenvObjCmd },
+ { "microseconds", ClockMicrosecondsObjCmd },
+ { "milliseconds", ClockMillisecondsObjCmd },
+ { "seconds", ClockSecondsObjCmd },
+ { "Oldscan", TclClockOldscanObjCmd },
+ { "ConvertLocalToUTC", ClockConvertlocaltoutcObjCmd },
+ { "GetDateFields", ClockGetdatefieldsObjCmd },
+ { "GetJulianDayFromEraYearMonthDay",
+ ClockGetjuliandayfromerayearmonthdayObjCmd },
+ { "GetJulianDayFromEraYearWeekDay",
+ ClockGetjuliandayfromerayearweekdayObjCmd },
+ { "ParseFormatArgs", ClockParseformatargsObjCmd },
+ { NULL, NULL }
+};
/*
- *-------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*
- * Tcl_ClockObjCmd --
+ * TclClockInit --
*
- * This procedure is invoked to process the "clock" Tcl command.
- * See the user documentation for details on what it does.
+ * Registers the 'clock' subcommands with the Tcl interpreter and
+ * initializes its client data (which consists mostly of constant
+ * Tcl_Obj's that it is too much trouble to keep recreating).
*
* Results:
- * A standard Tcl result.
+ * None.
*
* Side effects:
- * See the user documentation.
+ * Installs the commands and creates the client data
*
- *-------------------------------------------------------------------------
+ *----------------------------------------------------------------------
+ */
+
+void
+TclClockInit(
+ Tcl_Interp *interp) /* Tcl interpreter */
+{
+ const struct ClockCommand *clockCmdPtr;
+ char cmdName[50]; /* Buffer large enough to hold the string
+ *::tcl::clock::GetJulianDayFromEraYearMonthDay
+ * plus a terminating NULL. */
+ ClockClientData *data;
+ int i;
+
+ /*
+ * Safe interps get [::clock] as alias to a master, so do not need their
+ * own copies of the support routines.
+ */
+
+ if (Tcl_IsSafe(interp)) {
+ return;
+ }
+
+ /*
+ * Create the client data, which is a refcounted literal pool.
+ */
+
+ data = (ClockClientData *) ckalloc(sizeof(ClockClientData));
+ data->refCount = 0;
+ data->literals = (Tcl_Obj**) ckalloc(LIT__END * sizeof(Tcl_Obj*));
+ for (i = 0; i < LIT__END; ++i) {
+ data->literals[i] = Tcl_NewStringObj(literals[i], -1);
+ Tcl_IncrRefCount(data->literals[i]);
+ }
+
+ /*
+ * Install the commands.
+ */
+
+ strcpy(cmdName, "::tcl::clock::");
+#define TCL_CLOCK_PREFIX_LEN 14 /* == strlen("::tcl::clock::") */
+ for (clockCmdPtr=clockCommands ; clockCmdPtr->name!=NULL ; clockCmdPtr++) {
+ strcpy(cmdName + TCL_CLOCK_PREFIX_LEN, clockCmdPtr->name);
+ data->refCount++;
+ Tcl_CreateObjCommand(interp, cmdName, clockCmdPtr->objCmdProc, data,
+ ClockDeleteCmdProc);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ClockConvertlocaltoutcObjCmd --
+ *
+ * Tcl command that converts a UTC time to a local time by whatever means
+ * is available.
+ *
+ * Usage:
+ * ::tcl::clock::ConvertUTCToLocal dictionary tzdata changeover
+ *
+ * Parameters:
+ * dict - Dictionary containing a 'localSeconds' entry.
+ * tzdata - Time zone data
+ * changeover - Julian Day of the adoption of the Gregorian calendar.
+ *
+ * Results:
+ * Returns a standard Tcl result.
+ *
+ * Side effects:
+ * On success, sets the interpreter result to the given dictionary
+ * augmented with a 'seconds' field giving the UTC time. On failure,
+ * leaves an error message in the interpreter result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ClockConvertlocaltoutcObjCmd(
+ ClientData clientData, /* Client data */
+ Tcl_Interp* interp, /* Tcl interpreter */
+ int objc, /* Parameter count */
+ Tcl_Obj *const *objv) /* Parameter vector */
+{
+ ClockClientData* data = (ClockClientData*) clientData;
+ Tcl_Obj* const * literals = data->literals;
+ Tcl_Obj* secondsObj;
+ Tcl_Obj* dict;
+ int changeover;
+ TclDateFields fields;
+ int created = 0;
+ int status;
+
+ /*
+ * Check params and convert time.
+ */
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "dict tzdata changeover");
+ return TCL_ERROR;
+ }
+ dict = objv[1];
+ if (Tcl_DictObjGet(interp, dict, literals[LIT_LOCALSECONDS],
+ &secondsObj)!= TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (secondsObj == NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("key \"localseconds\" not "
+ "found in dictionary", -1));
+ return TCL_ERROR;
+ }
+ if ((Tcl_GetWideIntFromObj(interp, secondsObj,
+ &(fields.localSeconds)) != TCL_OK)
+ || (TclGetIntFromObj(interp, objv[3], &changeover) != TCL_OK)
+ || ConvertLocalToUTC(interp, &fields, objv[2], changeover)) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Copy-on-write; set the 'seconds' field in the dictionary and place the
+ * modified dictionary in the interpreter result.
+ */
+
+ if (Tcl_IsShared(dict)) {
+ dict = Tcl_DuplicateObj(dict);
+ created = 1;
+ Tcl_IncrRefCount(dict);
+ }
+ status = Tcl_DictObjPut(interp, dict, literals[LIT_SECONDS],
+ Tcl_NewWideIntObj(fields.seconds));
+ if (status == TCL_OK) {
+ Tcl_SetObjResult(interp, dict);
+ }
+ if (created) {
+ Tcl_DecrRefCount(dict);
+ }
+ return status;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ClockGetdatefieldsObjCmd --
+ *
+ * Tcl command that determines the values that [clock format] will use in
+ * formatting a date, and populates a dictionary with them.
+ *
+ * Usage:
+ * ::tcl::clock::GetDateFields seconds tzdata changeover
+ *
+ * Parameters:
+ * seconds - Time expressed in seconds from the Posix epoch.
+ * tzdata - Time zone data of the time zone in which time is to
+ * be expressed.
+ * changeover - Julian Day Number at which the current locale adopted
+ * the Gregorian calendar
+ *
+ * Results:
+ * Returns a dictonary populated with the fields:
+ * seconds - Seconds from the Posix epoch
+ * localSeconds - Nominal seconds from the Posix epoch in
+ * the local time zone.
+ * tzOffset - Time zone offset in seconds east of Greenwich
+ * tzName - Time zone name
+ * julianDay - Julian Day Number in the local time zone
+ *
+ *----------------------------------------------------------------------
*/
int
-Tcl_ClockObjCmd (client, interp, objc, objv)
- ClientData client; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument values. */
+ClockGetdatefieldsObjCmd(
+ ClientData clientData, /* Opaque pointer to literal pool, etc. */
+ Tcl_Interp* interp, /* Tcl interpreter */
+ int objc, /* Parameter count */
+ Tcl_Obj *const *objv) /* Parameter vector */
{
- Tcl_Obj *resultPtr;
- int index;
- Tcl_Obj *CONST *objPtr;
- int useGMT = 0;
- char *format = "%a %b %d %X %Z %Y";
- int dummy;
- Tcl_WideInt baseClock, clockVal;
- long zone;
- Tcl_Obj *baseObjPtr = NULL;
- char *scanStr;
- int n;
-
- static CONST char *switches[] =
- {"clicks", "format", "scan", "seconds", (char *) NULL};
- enum command { COMMAND_CLICKS, COMMAND_FORMAT, COMMAND_SCAN,
- COMMAND_SECONDS
- };
- static CONST char *formatSwitches[] = {"-format", "-gmt", (char *) NULL};
- static CONST char *scanSwitches[] = {"-base", "-gmt", (char *) NULL};
+ TclDateFields fields;
+ Tcl_Obj* dict;
+ ClockClientData* data = (ClockClientData*) clientData;
+ Tcl_Obj* const * literals = data->literals;
+ int changeover;
+
+ /*
+ * Check params.
+ */
- resultPtr = Tcl_GetObjResult(interp);
- if (objc < 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "seconds tzdata changeover");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetWideIntFromObj(interp, objv[1], &(fields.seconds)) != TCL_OK
+ || TclGetIntFromObj(interp, objv[3], &changeover) != TCL_OK) {
return TCL_ERROR;
}
- if (Tcl_GetIndexFromObj(interp, objv[1], switches, "option", 0, &index)
- != TCL_OK) {
+ /*
+ * fields.seconds could be an unsigned number that overflowed. Make
+ * sure that it isn't.
+ */
+
+ if (objv[1]->typePtr == &tclBignumType) {
+ Tcl_SetObjResult(interp, literals[LIT_INTEGER_VALUE_TOO_LARGE]);
return TCL_ERROR;
}
- switch ((enum command) index) {
- case COMMAND_CLICKS: { /* clicks */
- int forceMilli = 0;
-
- if (objc == 3) {
- format = Tcl_GetStringFromObj(objv[2], &n);
- if ( ( n >= 2 )
- && ( strncmp( format, "-milliseconds",
- (unsigned int) n) == 0 ) ) {
- forceMilli = 1;
- } else {
- Tcl_AppendStringsToObj(resultPtr,
- "bad switch \"", format,
- "\": must be -milliseconds", (char *) NULL);
- return TCL_ERROR;
- }
- } else if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, "?-milliseconds?");
- return TCL_ERROR;
+
+ /*
+ * Convert UTC time to local.
+ */
+
+ if (ConvertUTCToLocal(interp, &fields, objv[2], changeover) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Extract Julian day.
+ */
+
+ fields.julianDay = (int) ((fields.localSeconds + JULIAN_SEC_POSIX_EPOCH)
+ / SECONDS_PER_DAY);
+
+ /*
+ * Convert to Julian or Gregorian calendar.
+ */
+
+ GetGregorianEraYearDay(&fields, changeover);
+ GetMonthDay(&fields);
+ GetYearWeekDay(&fields, changeover);
+
+ dict = Tcl_NewDictObj();
+ Tcl_DictObjPut(NULL, dict, literals[LIT_LOCALSECONDS],
+ Tcl_NewWideIntObj(fields.localSeconds));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_SECONDS],
+ Tcl_NewWideIntObj(fields.seconds));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_TZNAME], fields.tzName);
+ Tcl_DecrRefCount(fields.tzName);
+ Tcl_DictObjPut(NULL, dict, literals[LIT_TZOFFSET],
+ Tcl_NewIntObj(fields.tzOffset));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_JULIANDAY],
+ Tcl_NewIntObj(fields.julianDay));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_GREGORIAN],
+ Tcl_NewIntObj(fields.gregorian));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_ERA],
+ literals[fields.era ? LIT_BCE : LIT_CE]);
+ Tcl_DictObjPut(NULL, dict, literals[LIT_YEAR],
+ Tcl_NewIntObj(fields.year));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_DAYOFYEAR],
+ Tcl_NewIntObj(fields.dayOfYear));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_MONTH],
+ Tcl_NewIntObj(fields.month));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_DAYOFMONTH],
+ Tcl_NewIntObj(fields.dayOfMonth));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_ISO8601YEAR],
+ Tcl_NewIntObj(fields.iso8601Year));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_ISO8601WEEK],
+ Tcl_NewIntObj(fields.iso8601Week));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_DAYOFWEEK],
+ Tcl_NewIntObj(fields.dayOfWeek));
+ Tcl_SetObjResult(interp, dict);
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ClockGetjuliandayfromerayearmonthdayObjCmd --
+ *
+ * Tcl command that converts a time from era-year-month-day to a Julian
+ * Day Number.
+ *
+ * Parameters:
+ * dict - Dictionary that contains 'era', 'year', 'month' and
+ * 'dayOfMonth' keys.
+ * changeover - Julian Day of changeover to the Gregorian calendar
+ *
+ * Results:
+ * Result is either TCL_OK, with the interpreter result being the
+ * dictionary augmented with a 'julianDay' key, or TCL_ERROR,
+ * with the result being an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ClockGetjuliandayfromerayearmonthdayObjCmd (
+ ClientData clientData, /* Opaque pointer to literal pool, etc. */
+ Tcl_Interp* interp, /* Tcl interpreter */
+ int objc, /* Parameter count */
+ Tcl_Obj *const *objv) /* Parameter vector */
+{
+ TclDateFields fields;
+ Tcl_Obj* dict;
+ ClockClientData* data = (ClockClientData*) clientData;
+ Tcl_Obj* const * literals = data->literals;
+ Tcl_Obj* fieldPtr;
+ int changeover;
+ int copied = 0;
+ int status;
+ int era = 0;
+
+ /*
+ * Check params.
+ */
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "dict changeover");
+ return TCL_ERROR;
+ }
+ dict = objv[1];
+ if (Tcl_DictObjGet(interp, dict, literals[LIT_ERA], &fieldPtr) != TCL_OK
+ || Tcl_GetIndexFromObj(interp, fieldPtr, eras, "era", TCL_EXACT,
+ &era) != TCL_OK
+ || Tcl_DictObjGet(interp, dict, literals[LIT_YEAR],
+ &fieldPtr) != TCL_OK
+ || TclGetIntFromObj(interp, fieldPtr, &(fields.year)) != TCL_OK
+ || Tcl_DictObjGet(interp, dict, literals[LIT_MONTH],
+ &fieldPtr) != TCL_OK
+ || TclGetIntFromObj(interp, fieldPtr, &(fields.month)) != TCL_OK
+ || Tcl_DictObjGet(interp, dict, literals[LIT_DAYOFMONTH],
+ &fieldPtr) != TCL_OK
+ || TclGetIntFromObj(interp, fieldPtr,
+ &(fields.dayOfMonth)) != TCL_OK
+ || TclGetIntFromObj(interp, objv[2], &changeover) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ fields.era = era;
+
+ /*
+ * Get Julian day.
+ */
+
+ GetJulianDayFromEraYearMonthDay(&fields, changeover);
+
+ /*
+ * Store Julian day in the dictionary - copy on write.
+ */
+
+ if (Tcl_IsShared(dict)) {
+ dict = Tcl_DuplicateObj(dict);
+ Tcl_IncrRefCount(dict);
+ copied = 1;
+ }
+ status = Tcl_DictObjPut(interp, dict, literals[LIT_JULIANDAY],
+ Tcl_NewIntObj(fields.julianDay));
+ if (status == TCL_OK) {
+ Tcl_SetObjResult(interp, dict);
+ }
+ if (copied) {
+ Tcl_DecrRefCount(dict);
+ }
+ return status;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ClockGetjuliandayfromerayearweekdayObjCmd --
+ *
+ * Tcl command that converts a time from the ISO calendar to a Julian Day
+ * Number.
+ *
+ * Parameters:
+ * dict - Dictionary that contains 'era', 'iso8601Year', 'iso8601Week'
+ * and 'dayOfWeek' keys.
+ * changeover - Julian Day of changeover to the Gregorian calendar
+ *
+ * Results:
+ * Result is either TCL_OK, with the interpreter result being the
+ * dictionary augmented with a 'julianDay' key, or TCL_ERROR, with the
+ * result being an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ClockGetjuliandayfromerayearweekdayObjCmd (
+ ClientData clientData, /* Opaque pointer to literal pool, etc. */
+ Tcl_Interp* interp, /* Tcl interpreter */
+ int objc, /* Parameter count */
+ Tcl_Obj *const *objv) /* Parameter vector */
+{
+ TclDateFields fields;
+ Tcl_Obj* dict;
+ ClockClientData* data = (ClockClientData*) clientData;
+ Tcl_Obj* const * literals = data->literals;
+ Tcl_Obj* fieldPtr;
+ int changeover;
+ int copied = 0;
+ int status;
+ int era = 0;
+
+ /*
+ * Check params.
+ */
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "dict changeover");
+ return TCL_ERROR;
+ }
+ dict = objv[1];
+ if (Tcl_DictObjGet(interp, dict, literals[LIT_ERA], &fieldPtr) != TCL_OK
+ || Tcl_GetIndexFromObj(interp, fieldPtr, eras, "era", TCL_EXACT,
+ &era) != TCL_OK
+ || Tcl_DictObjGet(interp, dict, literals[LIT_ISO8601YEAR],
+ &fieldPtr) != TCL_OK
+ || TclGetIntFromObj(interp, fieldPtr,
+ &(fields.iso8601Year)) != TCL_OK
+ || Tcl_DictObjGet(interp, dict, literals[LIT_ISO8601WEEK],
+ &fieldPtr) != TCL_OK
+ || TclGetIntFromObj(interp, fieldPtr,
+ &(fields.iso8601Week)) != TCL_OK
+ || Tcl_DictObjGet(interp, dict, literals[LIT_DAYOFWEEK],
+ &fieldPtr) != TCL_OK
+ || TclGetIntFromObj(interp, fieldPtr,
+ &(fields.dayOfWeek)) != TCL_OK
+ || TclGetIntFromObj(interp, objv[2], &changeover) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ fields.era = era;
+
+ /*
+ * Get Julian day.
+ */
+
+ GetJulianDayFromEraYearWeekDay(&fields, changeover);
+
+ /*
+ * Store Julian day in the dictionary - copy on write.
+ */
+
+ if (Tcl_IsShared(dict)) {
+ dict = Tcl_DuplicateObj(dict);
+ Tcl_IncrRefCount(dict);
+ copied = 1;
+ }
+ status = Tcl_DictObjPut(interp, dict, literals[LIT_JULIANDAY],
+ Tcl_NewIntObj(fields.julianDay));
+ if (status == TCL_OK) {
+ Tcl_SetObjResult(interp, dict);
+ }
+ if (copied) {
+ Tcl_DecrRefCount(dict);
+ }
+ return status;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConvertLocalToUTC --
+ *
+ * Converts a time (in a TclDateFields structure) from the local wall
+ * clock to UTC.
+ *
+ * Results:
+ * Returns a standard Tcl result.
+ *
+ * Side effects:
+ * Populates the 'seconds' field if successful; stores an error message
+ * in the interpreter result on failure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConvertLocalToUTC(
+ Tcl_Interp* interp, /* Tcl interpreter */
+ TclDateFields* fields, /* Fields of the time */
+ Tcl_Obj* tzdata, /* Time zone data */
+ int changeover) /* Julian Day of the Gregorian transition */
+{
+ int rowc; /* Number of rows in tzdata */
+ Tcl_Obj** rowv; /* Pointers to the rows */
+
+ /*
+ * Unpack the tz data.
+ */
+
+ if (TclListObjGetElements(interp, tzdata, &rowc, &rowv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Special case: If the time zone is :localtime, the tzdata will be empty.
+ * Use 'mktime' to convert the time to local
+ */
+
+ if (rowc == 0) {
+ return ConvertLocalToUTCUsingC(interp, fields, changeover);
+ } else {
+ return ConvertLocalToUTCUsingTable(interp, fields, rowc, rowv);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConvertLocalToUTCUsingTable --
+ *
+ * Converts a time (in a TclDateFields structure) from local time in a
+ * given time zone to UTC.
+ *
+ * Results:
+ * Returns a standard Tcl result.
+ *
+ * Side effects:
+ * Stores an error message in the interpreter if an error occurs; if
+ * successful, stores the 'seconds' field in 'fields.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConvertLocalToUTCUsingTable(
+ Tcl_Interp* interp, /* Tcl interpreter */
+ TclDateFields* fields, /* Time to convert, with 'seconds' filled in */
+ int rowc, /* Number of points at which time changes */
+ Tcl_Obj *const rowv[]) /* Points at which time changes */
+{
+ Tcl_Obj* row;
+ int cellc;
+ Tcl_Obj** cellv;
+ int have[8];
+ int nHave = 0;
+ int i;
+ int found;
+
+ /*
+ * Perform an initial lookup assuming that local == UTC, and locate the
+ * last time conversion prior to that time. Get the offset from that row,
+ * and look up again. Continue until we find an offset that we found
+ * before. This definition, rather than "the same offset" ensures that we
+ * don't enter an endless loop, as would otherwise happen when trying to
+ * convert a non-existent time such as 02:30 during the US Spring Daylight
+ * Saving Time transition.
+ */
+
+ found = 0;
+ fields->tzOffset = 0;
+ fields->seconds = fields->localSeconds;
+ while (!found) {
+ row = LookupLastTransition(interp, fields->seconds, rowc, rowv);
+ if ((row == NULL)
+ || TclListObjGetElements(interp, row, &cellc,
+ &cellv) != TCL_OK
+ || TclGetIntFromObj(interp, cellv[1],
+ &(fields->tzOffset)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ found = 0;
+ for (i = 0; !found && i < nHave; ++i) {
+ if (have[i] == fields->tzOffset) {
+ found = 1;
+ break;
}
- if (forceMilli) {
- /*
- * We can enforce at least millisecond granularity
- */
- Tcl_Time time;
- Tcl_GetTime(&time);
- Tcl_SetLongObj(resultPtr,
- (long) (time.sec*1000 + time.usec/1000));
- } else {
- Tcl_SetLongObj(resultPtr, (long) TclpGetClicks());
+ }
+ if (!found) {
+ if (nHave == 8) {
+ Tcl_Panic("loop in ConvertLocalToUTCUsingTable");
}
- return TCL_OK;
+ have[nHave] = fields->tzOffset;
+ ++nHave;
}
+ fields->seconds = fields->localSeconds - fields->tzOffset;
+ }
+ fields->tzOffset = have[i];
+ fields->seconds = fields->localSeconds - fields->tzOffset;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConvertLocalToUTCUsingC --
+ *
+ * Converts a time from local wall clock to UTC when the local time zone
+ * cannot be determined. Uses 'mktime' to do the job.
+ *
+ * Results:
+ * Returns a standard Tcl result.
+ *
+ * Side effects:
+ * Stores an error message in the interpreter if an error occurs; if
+ * successful, stores the 'seconds' field in 'fields.
+ *
+ *----------------------------------------------------------------------
+ */
- case COMMAND_FORMAT: /* format */
- if ((objc < 3) || (objc > 7)) {
- wrongFmtArgs:
- Tcl_WrongNumArgs(interp, 2, objv,
- "clockval ?-format string? ?-gmt boolean?");
- return TCL_ERROR;
- }
+static int
+ConvertLocalToUTCUsingC(
+ Tcl_Interp* interp, /* Tcl interpreter */
+ TclDateFields* fields, /* Time to convert, with 'seconds' filled in */
+ int changeover) /* Julian Day of the Gregorian transition */
+{
+ struct tm timeVal;
+ int localErrno;
+ int secondOfDay;
+ Tcl_WideInt jsec;
- if (Tcl_GetWideIntFromObj(interp, objv[2], &clockVal)
- != TCL_OK) {
- return TCL_ERROR;
- }
-
- objPtr = objv+3;
- objc -= 3;
- while (objc > 1) {
- if (Tcl_GetIndexFromObj(interp, objPtr[0], formatSwitches,
- "switch", 0, &index) != TCL_OK) {
- return TCL_ERROR;
- }
- switch (index) {
- case 0: /* -format */
- format = Tcl_GetStringFromObj(objPtr[1], &dummy);
- break;
- case 1: /* -gmt */
- if (Tcl_GetBooleanFromObj(interp, objPtr[1],
- &useGMT) != TCL_OK) {
- return TCL_ERROR;
- }
- break;
- }
- objPtr += 2;
- objc -= 2;
- }
- if (objc != 0) {
- goto wrongFmtArgs;
- }
- return FormatClock(interp, clockVal, useGMT,
- format);
-
- case COMMAND_SCAN: /* scan */
- if ((objc < 3) || (objc > 7)) {
- wrongScanArgs:
- Tcl_WrongNumArgs(interp, 2, objv,
- "dateString ?-base clockValue? ?-gmt boolean?");
- return TCL_ERROR;
- }
+ /*
+ * Convert the given time to a date.
+ */
- objPtr = objv+3;
- objc -= 3;
- while (objc > 1) {
- if (Tcl_GetIndexFromObj(interp, objPtr[0], scanSwitches,
- "switch", 0, &index) != TCL_OK) {
- return TCL_ERROR;
- }
- switch (index) {
- case 0: /* -base */
- baseObjPtr = objPtr[1];
- break;
- case 1: /* -gmt */
- if (Tcl_GetBooleanFromObj(interp, objPtr[1],
- &useGMT) != TCL_OK) {
- return TCL_ERROR;
- }
- break;
- }
- objPtr += 2;
- objc -= 2;
- }
- if (objc != 0) {
- goto wrongScanArgs;
- }
+ jsec = fields->localSeconds + JULIAN_SEC_POSIX_EPOCH;
+ fields->julianDay = (int) (jsec / SECONDS_PER_DAY);
+ secondOfDay = (int)(jsec % SECONDS_PER_DAY);
+ if (secondOfDay < 0) {
+ secondOfDay += SECONDS_PER_DAY;
+ --fields->julianDay;
+ }
+ GetGregorianEraYearDay(fields, changeover);
+ GetMonthDay(fields);
- if (baseObjPtr != NULL) {
- if (Tcl_GetWideIntFromObj(interp, baseObjPtr,
- &baseClock) != TCL_OK) {
- return TCL_ERROR;
- }
- } else {
- baseClock = TclpGetSeconds();
- }
+ /*
+ * Convert the date/time to a 'struct tm'.
+ */
- if (useGMT) {
- zone = -50000; /* Force GMT */
- } else {
- zone = TclpGetTimeZone(baseClock);
- }
+ timeVal.tm_year = fields->year - 1900;
+ timeVal.tm_mon = fields->month - 1;
+ timeVal.tm_mday = fields->dayOfMonth;
+ timeVal.tm_hour = (secondOfDay / 3600) % 24;
+ timeVal.tm_min = (secondOfDay / 60) % 60;
+ timeVal.tm_sec = secondOfDay % 60;
+ timeVal.tm_isdst = -1;
+ timeVal.tm_wday = -1;
+ timeVal.tm_yday = -1;
- scanStr = Tcl_GetStringFromObj(objv[2], &dummy);
- Tcl_MutexLock(&clockMutex);
- if (TclGetDate(scanStr, baseClock, zone,
- &clockVal) < 0) {
- Tcl_MutexUnlock(&clockMutex);
- Tcl_AppendStringsToObj(resultPtr,
- "unable to convert date-time string \"",
- scanStr, "\"", (char *) NULL);
- return TCL_ERROR;
- }
- Tcl_MutexUnlock(&clockMutex);
+ /*
+ * Get local time. It is rumored that mktime is not thread safe on some
+ * platforms, so seize a mutex before attempting this.
+ */
- Tcl_SetWideIntObj(resultPtr, clockVal);
- return TCL_OK;
+ TzsetIfNecessary();
+ Tcl_MutexLock(&clockMutex);
+ errno = 0;
+ fields->seconds = (Tcl_WideInt) mktime(&timeVal);
+ localErrno = errno;
+ Tcl_MutexUnlock(&clockMutex);
- case COMMAND_SECONDS: /* seconds */
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- return TCL_ERROR;
- }
- Tcl_SetLongObj(resultPtr, (long) TclpGetSeconds());
- return TCL_OK;
- default:
- return TCL_ERROR; /* Should never be reached. */
+ /*
+ * If conversion fails, report an error.
+ */
+
+ if (localErrno != 0
+ || (fields->seconds == -1 && timeVal.tm_yday == -1)) {
+ Tcl_SetResult(interp, "time value too large/small to represent",
+ TCL_STATIC);
+ return TCL_ERROR;
}
+ return TCL_OK;
}
/*
- *-----------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*
- * FormatClock --
+ * ConvertUTCToLocal --
*
- * Formats a time value based on seconds into a human readable
- * string.
+ * Converts a time (in a TclDateFields structure) from UTC to local time.
*
* Results:
- * Standard Tcl result.
+ * Returns a standard Tcl result.
*
* Side effects:
- * None.
+ * Populates the 'tzName' and 'tzOffset' fields.
*
- *-----------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*/
static int
-FormatClock(interp, clockVal, useGMT, format)
- Tcl_Interp *interp; /* Current interpreter. */
- Tcl_WideInt clockVal; /* Time in seconds. */
- int useGMT; /* Boolean */
- char *format; /* Format string */
+ConvertUTCToLocal(
+ Tcl_Interp* interp, /* Tcl interpreter */
+ TclDateFields* fields, /* Fields of the time */
+ Tcl_Obj* tzdata, /* Time zone data */
+ int changeover) /* Julian Day of the Gregorian transition */
{
- struct tm *timeDataPtr;
- Tcl_DString buffer, uniBuffer;
- int bufSize;
- char *p;
- int result;
- time_t tclockVal;
-#if !defined(HAVE_TM_ZONE) && !defined(WIN32)
- TIMEZONE_t savedTimeZone = 0; /* lint. */
- char *savedTZEnv = NULL; /* lint. */
-#endif
+ int rowc; /* Number of rows in tzdata */
+ Tcl_Obj** rowv; /* Pointers to the rows */
-#ifdef HAVE_TZSET
/*
- * Some systems forgot to call tzset in localtime, make sure its done.
+ * Unpack the tz data.
*/
- static int calledTzset = 0;
- Tcl_MutexLock(&clockMutex);
- if (!calledTzset) {
- tzset();
- calledTzset = 1;
+ if (TclListObjGetElements(interp, tzdata, &rowc, &rowv) != TCL_OK) {
+ return TCL_ERROR;
}
- Tcl_MutexUnlock(&clockMutex);
-#endif
/*
- * If the user gave us -format "", just return now
+ * Special case: If the time zone is :localtime, the tzdata will be empty.
+ * Use 'localtime' to convert the time to local
+ */
+
+ if (rowc == 0) {
+ return ConvertUTCToLocalUsingC(interp, fields, changeover);
+ } else {
+ return ConvertUTCToLocalUsingTable(interp, fields, rowc, rowv);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConvertUTCToLocalUsingTable --
+ *
+ * Converts UTC to local time, given a table of transition points
+ *
+ * Results:
+ * Returns a standard Tcl result
+ *
+ * Side effects:
+ * On success, fills fields->tzName, fields->tzOffset and
+ * fields->localSeconds. On failure, places an error message in the
+ * interpreter result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConvertUTCToLocalUsingTable(
+ Tcl_Interp* interp, /* Tcl interpreter */
+ TclDateFields* fields, /* Fields of the date */
+ int rowc, /* Number of rows in the conversion table
+ * (>= 1) */
+ Tcl_Obj *const rowv[]) /* Rows of the conversion table */
+{
+ Tcl_Obj* row; /* Row containing the current information */
+ int cellc; /* Count of cells in the row (must be 4) */
+ Tcl_Obj** cellv; /* Pointers to the cells */
+
+ /*
+ * Look up the nearest transition time.
+ */
+
+ row = LookupLastTransition(interp, fields->seconds, rowc, rowv);
+ if (row == NULL ||
+ TclListObjGetElements(interp, row, &cellc, &cellv) != TCL_OK ||
+ TclGetIntFromObj(interp,cellv[1],&(fields->tzOffset)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Convert the time.
+ */
+
+ fields->tzName = cellv[3];
+ Tcl_IncrRefCount(fields->tzName);
+ fields->localSeconds = fields->seconds + fields->tzOffset;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConvertUTCToLocalUsingC --
+ *
+ * Converts UTC to localtime in cases where the local time zone is not
+ * determinable, using the C 'localtime' function to do it.
+ *
+ * Results:
+ * Returns a standard Tcl result.
+ *
+ * Side effects:
+ * On success, fills fields->tzName, fields->tzOffset and
+ * fields->localSeconds. On failure, places an error message in the
+ * interpreter result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConvertUTCToLocalUsingC(
+ Tcl_Interp* interp, /* Tcl interpreter */
+ TclDateFields* fields, /* Time to convert, with 'seconds' filled in */
+ int changeover) /* Julian Day of the Gregorian transition */
+{
+ time_t tock;
+ struct tm* timeVal; /* Time after conversion */
+ int diff; /* Time zone diff local-Greenwich */
+ char buffer[8]; /* Buffer for time zone name */
+
+ /*
+ * Use 'localtime' to determine local year, month, day, time of day.
+ */
+
+ tock = (time_t) fields->seconds;
+ if ((Tcl_WideInt) tock != fields->seconds) {
+ Tcl_AppendResult(interp,
+ "number too large to represent as a Posix time", NULL);
+ Tcl_SetErrorCode(interp, "CLOCK", "argTooLarge", NULL);
+ return TCL_ERROR;
+ }
+ TzsetIfNecessary();
+ timeVal = ThreadSafeLocalTime(&tock);
+ if (timeVal == NULL) {
+ Tcl_AppendResult(interp,
+ "localtime failed (clock value may be too "
+ "large/small to represent)", NULL);
+ Tcl_SetErrorCode(interp, "CLOCK", "localtimeFailed", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Fill in the date in 'fields' and use it to derive Julian Day.
+ */
+
+ fields->era = CE;
+ fields->year = timeVal->tm_year + 1900;
+ fields->month = timeVal->tm_mon + 1;
+ fields->dayOfMonth = timeVal->tm_mday;
+ GetJulianDayFromEraYearMonthDay(fields, changeover);
+
+ /*
+ * Convert that value to seconds.
+ */
+
+ fields->localSeconds = (((fields->julianDay * (Tcl_WideInt) 24
+ + timeVal->tm_hour) * 60 + timeVal->tm_min) * 60
+ + timeVal->tm_sec) - JULIAN_SEC_POSIX_EPOCH;
+
+ /*
+ * Determine a time zone offset and name; just use +hhmm for the name.
+ */
+
+ diff = (int) (fields->localSeconds - fields->seconds);
+ fields->tzOffset = diff;
+ if (diff < 0) {
+ *buffer = '-';
+ diff = -diff;
+ } else {
+ *buffer = '+';
+ }
+ sprintf(buffer+1, "%02d", diff / 3600);
+ diff %= 3600;
+ sprintf(buffer+3, "%02d", diff / 60);
+ diff %= 60;
+ if (diff > 0) {
+ sprintf(buffer+5, "%02d", diff);
+ }
+ fields->tzName = Tcl_NewStringObj(buffer, -1);
+ Tcl_IncrRefCount(fields->tzName);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * LookupLastTransition --
+ *
+ * Given a UTC time and a tzdata array, looks up the last transition on
+ * or before the given time.
+ *
+ * Results:
+ * Returns a pointer to the row, or NULL if an error occurs.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj*
+LookupLastTransition(
+ Tcl_Interp* interp, /* Interpreter for error messages */
+ Tcl_WideInt tick, /* Time from the epoch */
+ int rowc, /* Number of rows of tzdata */
+ Tcl_Obj *const *rowv) /* Rows in tzdata */
+{
+ int l;
+ int u;
+ Tcl_Obj* compObj;
+ Tcl_WideInt compVal;
+
+ /*
+ * Examine the first row to make sure we're in bounds.
*/
- if (*format == '\0') {
- return TCL_OK;
+
+ if (Tcl_ListObjIndex(interp, rowv[0], 0, &compObj) != TCL_OK
+ || Tcl_GetWideIntFromObj(interp, compObj, &compVal) != TCL_OK) {
+ return NULL;
+ }
+
+ /*
+ * Bizarre case - first row doesn't begin at MIN_WIDE_INT. Return it
+ * anyway.
+ */
+
+ if (tick < compVal) {
+ return rowv[0];
}
-#if !defined(HAVE_TM_ZONE) && !defined(WIN32)
/*
- * This is a kludge for systems not having the timezone string in
- * struct tm. No matter what was specified, they use the local
- * timezone string. Since this kludge requires fiddling with the
- * TZ environment variable, it will mess up if done on multiple
- * threads at once. Protect it with a the clock mutex.
+ * Binary-search to find the transition.
*/
- Tcl_MutexLock( &clockMutex );
- if (useGMT) {
- CONST char *varValue;
+ l = 0;
+ u = rowc-1;
+ while (l < u) {
+ int m = (l + u + 1) / 2;
- varValue = Tcl_GetVar2(interp, "env", "TZ", TCL_GLOBAL_ONLY);
- if (varValue != NULL) {
- savedTZEnv = strcpy(ckalloc(strlen(varValue) + 1), varValue);
- } else {
- savedTZEnv = NULL;
+ if (Tcl_ListObjIndex(interp, rowv[m], 0, &compObj) != TCL_OK ||
+ Tcl_GetWideIntFromObj(interp, compObj, &compVal) != TCL_OK) {
+ return NULL;
+ }
+ if (tick >= compVal) {
+ l = m;
+ } else {
+ u = m-1;
}
- Tcl_SetVar2(interp, "env", "TZ", "GMT0", TCL_GLOBAL_ONLY);
- savedTimeZone = timezone;
- timezone = 0;
- tzset();
}
-#endif
+ return rowv[l];
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetYearWeekDay --
+ *
+ * Given a date with Julian Calendar Day, compute the year, week, and day
+ * in the ISO8601 calendar.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Stores 'iso8601Year', 'iso8601Week' and 'dayOfWeek' in the date
+ * fields.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GetYearWeekDay(
+ TclDateFields* fields, /* Date to convert, must have 'julianDay' */
+ int changeover) /* Julian Day Number of the Gregorian
+ * transition */
+{
+ TclDateFields temp;
+ int dayOfFiscalYear;
- tclockVal = (time_t) clockVal;
- timeDataPtr = TclpGetDate((TclpTime_t) &tclockVal, useGMT);
-
/*
- * Make a guess at the upper limit on the substituted string size
- * based on the number of percents in the string.
+ * Find the given date, minus three days, plus one year. That date's
+ * iso8601 year is an upper bound on the ISO8601 year of the given date.
*/
- for (bufSize = 1, p = format; *p != '\0'; p++) {
- if (*p == '%') {
- bufSize += 40;
- if (p[1] == 'c') {
- bufSize += 226;
- }
+ temp.julianDay = fields->julianDay - 3;
+ GetGregorianEraYearDay(&temp, changeover);
+ if (temp.era == BCE) {
+ temp.iso8601Year = temp.year - 1;
+ } else {
+ temp.iso8601Year = temp.year + 1;
+ }
+ temp.iso8601Week = 1;
+ temp.dayOfWeek = 1;
+ GetJulianDayFromEraYearWeekDay(&temp, changeover);
+
+ /*
+ * temp.julianDay is now the start of an ISO8601 year, either the one
+ * corresponding to the given date, or the one after. If we guessed high,
+ * move one year earlier
+ */
+
+ if (fields->julianDay < temp.julianDay) {
+ if (temp.era == BCE) {
+ temp.iso8601Year += 1;
} else {
- bufSize++;
+ temp.iso8601Year -= 1;
}
+ GetJulianDayFromEraYearWeekDay(&temp, changeover);
}
- Tcl_DStringInit(&uniBuffer);
- Tcl_UtfToExternalDString(NULL, format, -1, &uniBuffer);
- Tcl_DStringInit(&buffer);
- Tcl_DStringSetLength(&buffer, bufSize);
- /* If we haven't locked the clock mutex up above, lock it now. */
+ fields->iso8601Year = temp.iso8601Year;
+ dayOfFiscalYear = fields->julianDay - temp.julianDay;
+ fields->iso8601Week = (dayOfFiscalYear / 7) + 1;
+ fields->dayOfWeek = (dayOfFiscalYear + 1) % 7;
+ if (fields->dayOfWeek < 1) {
+ fields->dayOfWeek += 7;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetGregorianEraYearDay --
+ *
+ * Given a Julian Day Number, extracts the year and day of the year and
+ * puts them into TclDateFields, along with the era (BCE or CE) and a
+ * flag indicating whether the date is Gregorian or Julian.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Stores 'era', 'gregorian', 'year', and 'dayOfYear'.
+ *
+ *----------------------------------------------------------------------
+ */
-#if defined(HAVE_TM_ZONE) || defined(WIN32)
- Tcl_MutexLock(&clockMutex);
-#endif
- result = TclpStrftime(buffer.string, (unsigned int) bufSize,
- Tcl_DStringValue(&uniBuffer), timeDataPtr, useGMT);
-#if defined(HAVE_TM_ZONE) || defined(WIN32)
- Tcl_MutexUnlock(&clockMutex);
-#endif
- Tcl_DStringFree(&uniBuffer);
-
-#if !defined(HAVE_TM_ZONE) && !defined(WIN32)
- if (useGMT) {
- if (savedTZEnv != NULL) {
- Tcl_SetVar2(interp, "env", "TZ", savedTZEnv, TCL_GLOBAL_ONLY);
- ckfree(savedTZEnv);
- } else {
- Tcl_UnsetVar2(interp, "env", "TZ", TCL_GLOBAL_ONLY);
- }
- timezone = savedTimeZone;
- tzset();
- }
- Tcl_MutexUnlock( &clockMutex );
-#endif
+static void
+GetGregorianEraYearDay(
+ TclDateFields* fields, /* Date fields containing 'julianDay' */
+ int changeover) /* Gregorian transition date */
+{
+ int jday = fields->julianDay;
+ int day;
+ int year;
+ int n;
- if (result == 0) {
+ if (jday >= changeover) {
/*
- * A zero return is the error case (can also mean the strftime
- * didn't get enough space to write into). We know it doesn't
- * mean that we wrote zero chars because the check for an empty
- * format string is above.
+ * Gregorian calendar.
*/
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "bad format string \"", format, "\"", (char *) NULL);
+
+ fields->gregorian = 1;
+ year = 1;
+
+ /*
+ * n = Number of 400-year cycles since 1 January, 1 CE in the
+ * proleptic Gregorian calendar. day = remaining days.
+ */
+
+ day = jday - JDAY_1_JAN_1_CE_GREGORIAN;
+ n = day / FOUR_CENTURIES;
+ day %= FOUR_CENTURIES;
+ if (day < 0) {
+ day += FOUR_CENTURIES;
+ --n;
+ }
+ year += 400 * n;
+
+ /*
+ * n = number of centuries since the start of (year);
+ * day = remaining days
+ */
+
+ n = day / ONE_CENTURY_GREGORIAN;
+ day %= ONE_CENTURY_GREGORIAN;
+ if (n > 3) {
+ /*
+ * 31 December in the last year of a 400-year cycle.
+ */
+
+ n = 3;
+ day += ONE_CENTURY_GREGORIAN;
+ }
+ year += 100 * n;
+
+ } else {
+ /*
+ * Julian calendar.
+ */
+
+ fields->gregorian = 0;
+ year = 1;
+ day = jday - JDAY_1_JAN_1_CE_JULIAN;
+
+ }
+
+ /*
+ * n = number of 4-year cycles; days = remaining days.
+ */
+
+ n = day / FOUR_YEARS;
+ day %= FOUR_YEARS;
+ if (day < 0) {
+ day += FOUR_YEARS;
+ --n;
+ }
+ year += 4 * n;
+
+ /*
+ * n = number of years; days = remaining days.
+ */
+
+ n = day / ONE_YEAR;
+ day %= ONE_YEAR;
+ if (n > 3) {
+ /*
+ * 31 December of a leap year.
+ */
+
+ n = 3;
+ day += 365;
+ }
+ year += n;
+
+ /*
+ * store era/year/day back into fields.
+ */
+
+ if (year <= 0) {
+ fields->era = BCE;
+ fields->year = 1 - year;
+ } else {
+ fields->era = CE;
+ fields->year = year;
+ }
+ fields->dayOfYear = day + 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetMonthDay --
+ *
+ * Given a date as year and day-of-year, find month and day.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Stores 'month' and 'dayOfMonth' in the 'fields' structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GetMonthDay(
+ TclDateFields* fields) /* Date to convert */
+{
+ int day = fields->dayOfYear;
+ int month;
+ const int* h = hath[IsGregorianLeapYear(fields)];
+
+ for (month = 0; month < 12 && day > h[month]; ++month) {
+ day -= h[month];
+ }
+ fields->month = month+1;
+ fields->dayOfMonth = day;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetJulianDayFromEraYearWeekDay --
+ *
+ * Given a TclDateFields structure containing era, ISO8601 year, ISO8601
+ * week, and day of week, computes the Julian Day Number.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Stores 'julianDay' in the fields.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GetJulianDayFromEraYearWeekDay(
+ TclDateFields* fields, /* Date to convert */
+ int changeover) /* Julian Day Number of the Gregorian
+ * transition */
+{
+ int firstMonday; /* Julian day number of week 1, day 1 in the
+ * given year */
+
+ /*
+ * Find January 4 in the ISO8601 year, which will always be in week 1.
+ */
+
+ TclDateFields firstWeek;
+ firstWeek.era = fields->era;
+ firstWeek.year = fields->iso8601Year;
+ firstWeek.month = 1;
+ firstWeek.dayOfMonth = 4;
+ GetJulianDayFromEraYearMonthDay(&firstWeek, changeover);
+
+ /*
+ * Find Monday of week 1.
+ */
+
+ firstMonday = WeekdayOnOrBefore(1, firstWeek.julianDay);
+
+ /*
+ * Advance to the given week and day.
+ */
+
+ fields->julianDay = firstMonday + 7 * (fields->iso8601Week - 1)
+ + fields->dayOfWeek - 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetJulianDayFromEraYearMonthDay --
+ *
+ * Given era, year, month, and dayOfMonth (in TclDateFields), and the
+ * Gregorian transition date, computes the Julian Day Number.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Stores day number in 'julianDay'
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GetJulianDayFromEraYearMonthDay(
+ TclDateFields* fields, /* Date to convert */
+ int changeover) /* Gregorian transition date as a Julian Day */
+{
+ int year; int ym1;
+ int month; int mm1;
+ int q; int r;
+ int ym1o4; int ym1o100; int ym1o400;
+
+ if (fields->era == BCE) {
+ year = 1 - fields->year;
+ } else {
+ year = fields->year;
+ }
+
+ /*
+ * Reduce month modulo 12.
+ */
+
+ month = fields->month;
+ mm1 = month - 1;
+ q = mm1 / 12;
+ r = (mm1 % 12);
+ if (r < 0) {
+ r += 12;
+ q -= 1;
+ }
+ year += q;
+ month = r + 1;
+ ym1 = year - 1;
+
+ /*
+ * Adjust the year after reducing the month.
+ */
+
+ fields->gregorian = 1;
+ if (year < 1) {
+ fields->era = BCE;
+ fields->year = 1-year;
+ } else {
+ fields->era = CE;
+ fields->year = year;
+ }
+
+ /*
+ * Try an initial conversion in the Gregorian calendar.
+ */
+
+ ym1o4 = ym1 / 4;
+ if (ym1 % 4 < 0) {
+ --ym1o4;
+ }
+ ym1o100 = ym1 / 100;
+ if (ym1 % 100 < 0) {
+ --ym1o100;
+ }
+ ym1o400 = ym1 / 400;
+ if (ym1 % 400 < 0) {
+ --ym1o400;
+ }
+ fields->julianDay = JDAY_1_JAN_1_CE_GREGORIAN - 1
+ + fields->dayOfMonth
+ + daysInPriorMonths[IsGregorianLeapYear(fields)][month - 1]
+ + (ONE_YEAR * ym1)
+ + ym1o4
+ - ym1o100
+ + ym1o400;
+
+ /*
+ * If the resulting date is before the Gregorian changeover, convert in
+ * the Julian calendar instead.
+ */
+
+ if (fields->julianDay < changeover) {
+ fields->gregorian = 0;
+ fields->julianDay = JDAY_1_JAN_1_CE_JULIAN - 1
+ + fields->dayOfMonth
+ + daysInPriorMonths[year%4 == 0][month - 1]
+ + (ONE_YEAR * ym1)
+ + ym1o4;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * IsGregorianLeapYear --
+ *
+ * Tests whether a given year is a leap year, in either Julian or
+ * Gregorian calendar.
+ *
+ * Results:
+ * Returns 1 for a leap year, 0 otherwise.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+IsGregorianLeapYear(
+ TclDateFields* fields) /* Date to test */
+{
+ int year;
+
+ if (fields->era == BCE) {
+ year = 1 - fields->year;
+ } else {
+ year = fields->year;
+ }
+ if (year%4 != 0) {
+ return 0;
+ } else if (!(fields->gregorian)) {
+ return 1;
+ } else if (year%400 == 0) {
+ return 1;
+ } else if (year%100 == 0) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WeekdayOnOrBefore --
+ *
+ * Finds the Julian Day Number of a given day of the week that falls on
+ * or before a given date, expressed as Julian Day Number.
+ *
+ * Results:
+ * Returns the Julian Day Number
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WeekdayOnOrBefore(
+ int dayOfWeek, /* Day of week; Sunday == 0 or 7 */
+ int julianDay) /* Reference date */
+{
+ int k = (dayOfWeek + 6) % 7;
+ if (k < 0) {
+ k += 7;
+ }
+ return julianDay - ((julianDay - k) % 7);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ClockGetenvObjCmd --
+ *
+ * Tcl command that reads an environment variable from the system
+ *
+ * Usage:
+ * ::tcl::clock::getEnv NAME
+ *
+ * Parameters:
+ * NAME - Name of the environment variable desired
+ *
+ * Results:
+ * Returns a standard Tcl result. Returns an error if the variable does
+ * not exist, with a message left in the interpreter. Returns TCL_OK and
+ * the value of the variable if the variable does exist,
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+ClockGetenvObjCmd(
+ ClientData clientData,
+ Tcl_Interp* interp,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ const char* varName;
+ const char* varValue;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "name");
return TCL_ERROR;
}
+ varName = TclGetString(objv[1]);
+ varValue = getenv(varName);
+ if (varValue == NULL) {
+ varValue = "";
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(varValue, -1));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ThreadSafeLocalTime --
+ *
+ * Wrapper around the 'localtime' library function to make it thread
+ * safe.
+ *
+ * Results:
+ * Returns a pointer to a 'struct tm' in thread-specific data.
+ *
+ * Side effects:
+ * Invokes localtime or localtime_r as appropriate.
+ *
+ *----------------------------------------------------------------------
+ */
+static struct tm *
+ThreadSafeLocalTime(
+ const time_t *timePtr) /* Pointer to the number of seconds since the
+ * local system's epoch */
+{
/*
- * Convert the time to UTF from external encoding [Bug: 3345]
+ * Get a thread-local buffer to hold the returned time.
*/
- Tcl_DStringInit(&uniBuffer);
- Tcl_ExternalToUtfDString(NULL, buffer.string, -1, &uniBuffer);
- Tcl_SetStringObj(Tcl_GetObjResult(interp), uniBuffer.string, -1);
+ struct tm *tmPtr = (struct tm *)
+ Tcl_GetThreadData(&tmKey, (int) sizeof(struct tm));
+#ifdef HAVE_LOCALTIME_R
+ localtime_r(timePtr, tmPtr);
+#else
+ struct tm *sysTmPtr;
- Tcl_DStringFree(&uniBuffer);
- Tcl_DStringFree(&buffer);
+ Tcl_MutexLock(&clockMutex);
+ sysTmPtr = localtime(timePtr);
+ if (sysTmPtr == NULL) {
+ Tcl_MutexUnlock(&clockMutex);
+ return NULL;
+ } else {
+ memcpy((void *) tmPtr, (void *) localtime(timePtr), sizeof(struct tm));
+ Tcl_MutexUnlock(&clockMutex);
+ }
+#endif
+ return tmPtr;
+}
+
+/*----------------------------------------------------------------------
+ *
+ * ClockClicksObjCmd --
+ *
+ * Returns a high-resolution counter.
+ *
+ * Results:
+ * Returns a standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ * This function implements the 'clock clicks' Tcl command. Refer to the user
+ * documentation for details on what it does.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+ClockClicksObjCmd(
+ ClientData clientData, /* Client data is unused */
+ Tcl_Interp* interp, /* Tcl interpreter */
+ int objc, /* Parameter count */
+ Tcl_Obj* const* objv) /* Parameter values */
+{
+ static const char *clicksSwitches[] = {
+ "-milliseconds", "-microseconds", NULL
+ };
+ enum ClicksSwitch {
+ CLICKS_MILLIS, CLICKS_MICROS, CLICKS_NATIVE
+ };
+ int index = CLICKS_NATIVE;
+ Tcl_Time now;
+
+ switch (objc) {
+ case 1:
+ break;
+ case 2:
+ if (Tcl_GetIndexFromObj(interp, objv[1], clicksSwitches, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ default:
+ Tcl_WrongNumArgs(interp, 1, objv, "?option?");
+ return TCL_ERROR;
+ }
+
+ switch (index) {
+ case CLICKS_MILLIS:
+ Tcl_GetTime(&now);
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt)
+ now.sec * 1000 + now.usec / 1000));
+ break;
+ case CLICKS_NATIVE: {
+#ifndef TCL_WIDE_CLICKS
+ unsigned long clicks = TclpGetClicks();
+#else
+ Tcl_WideInt clicks = TclpGetWideClicks();
+#endif
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) clicks));
+ break;
+ }
+ case CLICKS_MICROS:
+ Tcl_GetTime(&now);
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
+ ((Tcl_WideInt) now.sec * 1000000) + now.usec));
+ break;
+ }
+
+ return TCL_OK;
+}
+
+/*----------------------------------------------------------------------
+ *
+ * ClockMillisecondsObjCmd -
+ *
+ * Returns a count of milliseconds since the epoch.
+ *
+ * Results:
+ * Returns a standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ * This function implements the 'clock milliseconds' Tcl command. Refer to the
+ * user documentation for details on what it does.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+ClockMillisecondsObjCmd(
+ ClientData clientData, /* Client data is unused */
+ Tcl_Interp* interp, /* Tcl interpreter */
+ int objc, /* Parameter count */
+ Tcl_Obj* const* objv) /* Parameter values */
+{
+ Tcl_Time now;
+
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, NULL);
+ return TCL_ERROR;
+ }
+ Tcl_GetTime(&now);
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj( (Tcl_WideInt)
+ now.sec * 1000 + now.usec / 1000));
return TCL_OK;
}
+
+/*----------------------------------------------------------------------
+ *
+ * ClockMicrosecondsObjCmd -
+ *
+ * Returns a count of microseconds since the epoch.
+ *
+ * Results:
+ * Returns a standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ * This function implements the 'clock microseconds' Tcl command. Refer to the
+ * user documentation for details on what it does.
+ *
+ *----------------------------------------------------------------------
+ */
+int
+ClockMicrosecondsObjCmd(
+ ClientData clientData, /* Client data is unused */
+ Tcl_Interp* interp, /* Tcl interpreter */
+ int objc, /* Parameter count */
+ Tcl_Obj* const* objv) /* Parameter values */
+{
+ Tcl_Time now;
+
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, NULL);
+ return TCL_ERROR;
+ }
+ Tcl_GetTime(&now);
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
+ ((Tcl_WideInt) now.sec * 1000000) + now.usec));
+ return TCL_OK;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * ClockParseformatargsObjCmd --
+ *
+ * Parses the arguments for [clock format].
+ *
+ * Results:
+ * Returns a standard Tcl result, whose value is a four-element
+ * list comprising the time format, the locale, and the timezone.
+ *
+ * This function exists because the loop that parses the [clock format]
+ * options is a known performance "hot spot", and is implemented in an
+ * effort to speed that particular code up.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+ClockParseformatargsObjCmd(
+ ClientData clientData, /* Client data containing literal pool */
+ Tcl_Interp* interp, /* Tcl interpreter */
+ int objc, /* Parameter count */
+ Tcl_Obj *const objv[] /* Parameter vector */
+) {
+
+ ClockClientData* dataPtr = (ClockClientData*) clientData;
+ Tcl_Obj** litPtr = dataPtr->literals;
+
+ /* Format, locale and timezone */
+
+ Tcl_Obj* results[3];
+#define formatObj results[0]
+#define localeObj results[1]
+#define timezoneObj results[2]
+ int gmtFlag = 0;
+
+ /* Command line options expected */
+
+ static const char* options[] = {
+ "-format", "-gmt", "-locale",
+ "-timezone", NULL };
+ enum optionInd {
+ CLOCK_FORMAT_FORMAT, CLOCK_FORMAT_GMT, CLOCK_FORMAT_LOCALE,
+ CLOCK_FORMAT_TIMEZONE
+ };
+ int optionIndex; /* Index of an option */
+ int saw = 0; /* Flag == 1 if option was seen already */
+ Tcl_WideInt clockVal; /* Clock value - just used to parse */
+ int i;
+
+ /* Args consist of a time followed by keyword-value pairs */
+
+ if (objc < 2 || (objc % 2) != 0) {
+ Tcl_WrongNumArgs(interp, 0, objv,
+ "clock format clockval ?-format string? "
+ "?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?");
+ Tcl_SetErrorCode(interp, "CLOCK", "wrongNumArgs", NULL);
+ return TCL_ERROR;
+ }
+
+ /* Extract values for the keywords */
+
+ formatObj = litPtr[LIT__DEFAULT_FORMAT];
+ localeObj = litPtr[LIT_C];
+ timezoneObj = litPtr[LIT__NIL];
+ for (i = 2; i < objc; i+=2) {
+ if (Tcl_GetIndexFromObj(interp, objv[i], options, "switch", 0,
+ &optionIndex) != TCL_OK) {
+ Tcl_SetErrorCode(interp, "CLOCK", "badSwitch",
+ Tcl_GetString(objv[i]), NULL);
+ return TCL_ERROR;
+ }
+ switch (optionIndex) {
+ case CLOCK_FORMAT_FORMAT:
+ formatObj = objv[i+1];
+ break;
+ case CLOCK_FORMAT_GMT:
+ if (Tcl_GetBooleanFromObj(interp, objv[i+1], &gmtFlag) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case CLOCK_FORMAT_LOCALE:
+ localeObj = objv[i+1];
+ break;
+ case CLOCK_FORMAT_TIMEZONE:
+ timezoneObj = objv[i+1];
+ break;
+ }
+ saw |= (1 << optionIndex);
+ }
+
+ /* Check options */
+
+ if (Tcl_GetWideIntFromObj(interp, objv[1], &clockVal) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((saw & (1 << CLOCK_FORMAT_GMT))
+ && (saw & (1 << CLOCK_FORMAT_TIMEZONE))) {
+ Tcl_SetObjResult(interp, litPtr[LIT_CANNOT_USE_GMT_AND_TIMEZONE]);
+ Tcl_SetErrorCode(interp, "CLOCK", "gmtWithTimezone", NULL);
+ return TCL_ERROR;
+ }
+ if (gmtFlag) {
+ timezoneObj = litPtr[LIT_GMT];
+ }
+
+ /* Return options as a list */
+
+ Tcl_SetObjResult(interp, Tcl_NewListObj(3, results));
+ return TCL_OK;
+
+#undef timezoneObj
+#undef localeObj
+#undef formatObj
+
+}
+
+/*----------------------------------------------------------------------
+ *
+ * ClockSecondsObjCmd -
+ *
+ * Returns a count of microseconds since the epoch.
+ *
+ * Results:
+ * Returns a standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ * This function implements the 'clock seconds' Tcl command. Refer to the user
+ * documentation for details on what it does.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+ClockSecondsObjCmd(
+ ClientData clientData, /* Client data is unused */
+ Tcl_Interp* interp, /* Tcl interpreter */
+ int objc, /* Parameter count */
+ Tcl_Obj* const* objv) /* Parameter values */
+{
+ Tcl_Time now;
+
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, NULL);
+ return TCL_ERROR;
+ }
+ Tcl_GetTime(&now);
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) now.sec));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TzsetIfNecessary --
+ *
+ * Calls the tzset() library function if the contents of the TZ
+ * environment variable has changed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Calls tzset.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TzsetIfNecessary(void)
+{
+ static char* tzWas = NULL; /* Previous value of TZ, protected by
+ * clockMutex. */
+ const char* tzIsNow; /* Current value of TZ */
+
+ Tcl_MutexLock(&clockMutex);
+ tzIsNow = getenv("TZ");
+ if (tzIsNow != NULL && (tzWas == NULL || strcmp(tzIsNow, tzWas) != 0)) {
+ tzset();
+ if (tzWas != NULL) {
+ ckfree(tzWas);
+ }
+ tzWas = ckalloc(strlen(tzIsNow) + 1);
+ strcpy(tzWas, tzIsNow);
+ } else if (tzIsNow == NULL && tzWas != NULL) {
+ tzset();
+ ckfree(tzWas);
+ tzWas = NULL;
+ }
+ Tcl_MutexUnlock(&clockMutex);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ClockDeleteCmdProc --
+ *
+ * Remove a reference to the clock client data, and clean up memory
+ * when it's all gone.
+ *
+ * Results:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ClockDeleteCmdProc(
+ ClientData clientData) /* Opaque pointer to the client data */
+{
+ ClockClientData *data = (ClockClientData*) clientData;
+ int i;
+
+ --(data->refCount);
+ if (data->refCount == 0) {
+ for (i = 0; i < LIT__END; ++i) {
+ Tcl_DecrRefCount(data->literals[i]);
+ }
+ ckfree((char*) (data->literals));
+ ckfree((char*) data);
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclCmdAH.c b/generic/tclCmdAH.c
index 5e231f6..d8db34e 100644
--- a/generic/tclCmdAH.c
+++ b/generic/tclCmdAH.c
@@ -1,45 +1,45 @@
-/*
+/*
* tclCmdAH.c --
*
- * This file contains the top-level command routines for most of
- * the Tcl built-in commands whose names begin with the letters
- * A to H.
+ * This file contains the top-level command routines for most of the Tcl
+ * built-in commands whose names begin with the letters A to H.
*
* Copyright (c) 1987-1993 The Regents of the University of California.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
#include <locale.h>
/*
* Prototypes for local procedures defined in this file:
*/
-static int CheckAccess _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr, int mode));
-static int GetStatBuf _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr, Tcl_FSStatProc *statProc,
- Tcl_StatBuf *statPtr));
-static char * GetTypeFromMode _ANSI_ARGS_((int mode));
-static int StoreStatData _ANSI_ARGS_((Tcl_Interp *interp,
- char *varName, Tcl_StatBuf *statPtr));
+static int CheckAccess(Tcl_Interp *interp, Tcl_Obj *pathPtr,
+ int mode);
+static int EncodingDirsObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]);
+static int GetStatBuf(Tcl_Interp *interp, Tcl_Obj *pathPtr,
+ Tcl_FSStatProc *statProc, Tcl_StatBuf *statPtr);
+static char * GetTypeFromMode(int mode);
+static int StoreStatData(Tcl_Interp *interp, Tcl_Obj *varName,
+ Tcl_StatBuf *statPtr);
/*
*----------------------------------------------------------------------
*
* Tcl_BreakObjCmd --
*
- * This procedure is invoked to process the "break" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "break" Tcl command. See the
+ * user documentation for details on what it does.
*
- * With the bytecode compiler, this procedure is only called when
- * a command name is computed at runtime, and is "break" or the name
- * to which "break" was renamed: e.g., "set z break; $z"
+ * With the bytecode compiler, this procedure is only called when a
+ * command name is computed at runtime, and is "break" or the name to
+ * which "break" was renamed: e.g., "set z break; $z"
*
* Results:
* A standard Tcl result.
@@ -52,11 +52,11 @@ static int StoreStatData _ANSI_ARGS_((Tcl_Interp *interp,
/* ARGSUSED */
int
-Tcl_BreakObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_BreakObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, NULL);
@@ -70,8 +70,9 @@ Tcl_BreakObjCmd(dummy, interp, objc, objv)
*
* Tcl_CaseObjCmd --
*
- * This procedure is invoked to process the "case" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "case" Tcl command. See the
+ * user documentation for details on what it does. THIS COMMAND IS
+ * OBSOLETE AND DEPRECATED. SLATED FOR REMOVAL IN TCL 9.0.
*
* Results:
* A standard Tcl object result.
@@ -84,15 +85,15 @@ Tcl_BreakObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_CaseObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_CaseObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
register int i;
int body, result, caseObjc;
- char *string, *arg;
+ char *stringPtr, *arg;
Tcl_Obj *CONST *caseObjv;
Tcl_Obj *armPtr;
@@ -102,10 +103,10 @@ Tcl_CaseObjCmd(dummy, interp, objc, objv)
return TCL_ERROR;
}
- string = Tcl_GetString(objv[1]);
+ stringPtr = TclGetString(objv[1]);
body = -1;
- arg = Tcl_GetString(objv[2]);
+ arg = TclGetString(objv[2]);
if (strcmp(arg, "in") == 0) {
i = 3;
} else {
@@ -115,14 +116,14 @@ Tcl_CaseObjCmd(dummy, interp, objc, objv)
caseObjv = objv + i;
/*
- * If all of the pattern/command pairs are lumped into a single
- * argument, split them out again.
+ * If all of the pattern/command pairs are lumped into a single argument,
+ * split them out again.
*/
if (caseObjc == 1) {
Tcl_Obj **newObjv;
-
- Tcl_ListObjGetElements(interp, caseObjv[0], &caseObjc, &newObjv);
+
+ TclListObjGetElements(interp, caseObjv[0], &caseObjc, &newObjv);
caseObjv = newObjv;
}
@@ -134,17 +135,16 @@ Tcl_CaseObjCmd(dummy, interp, objc, objv)
if (i == (caseObjc - 1)) {
Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "extra case pattern with no body", -1);
+ Tcl_AppendResult(interp, "extra case pattern with no body", NULL);
return TCL_ERROR;
}
/*
- * Check for special case of single pattern (no list) with
- * no backslash sequences.
+ * Check for special case of single pattern (no list) with no
+ * backslash sequences.
*/
- pat = Tcl_GetString(caseObjv[i]);
+ pat = TclGetString(caseObjv[i]);
for (p = (unsigned char *) pat; *p != '\0'; p++) {
if (isspace(*p) || (*p == '\\')) { /* INTL: ISO space, UCHAR */
break;
@@ -154,17 +154,16 @@ Tcl_CaseObjCmd(dummy, interp, objc, objv)
if ((*pat == 'd') && (strcmp(pat, "default") == 0)) {
body = i + 1;
}
- if (Tcl_StringMatch(string, pat)) {
+ if (Tcl_StringMatch(stringPtr, pat)) {
body = i + 1;
goto match;
}
continue;
}
-
/*
- * Break up pattern lists, then check each of the patterns
- * in the list.
+ * Break up pattern lists, then check each of the patterns in the
+ * list.
*/
result = Tcl_SplitList(interp, pat, &patObjc, &patObjv);
@@ -172,7 +171,7 @@ Tcl_CaseObjCmd(dummy, interp, objc, objv)
return result;
}
for (j = 0; j < patObjc; j++) {
- if (Tcl_StringMatch(string, patObjv[j])) {
+ if (Tcl_StringMatch(stringPtr, patObjv[j])) {
body = i + 1;
break;
}
@@ -183,18 +182,14 @@ Tcl_CaseObjCmd(dummy, interp, objc, objv)
}
}
- match:
+ match:
if (body != -1) {
armPtr = caseObjv[body - 1];
result = Tcl_EvalObjEx(interp, caseObjv[body], 0);
if (result == TCL_ERROR) {
- char msg[100 + TCL_INTEGER_SPACE];
-
- arg = Tcl_GetString(armPtr);
- sprintf(msg,
- "\n (\"%.50s\" arm line %d)", arg,
- interp->errorLine);
- Tcl_AddObjErrorInfo(interp, msg, -1);
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (\"%.50s\" arm line %d)",
+ TclGetString(armPtr), interp->errorLine));
}
return result;
}
@@ -211,7 +206,7 @@ Tcl_CaseObjCmd(dummy, interp, objc, objv)
*
* Tcl_CatchObjCmd --
*
- * This object-based procedure is invoked to process the "catch" Tcl
+ * This object-based procedure is invoked to process the "catch" Tcl
* command. See the user documentation for details on what it does.
*
* Results:
@@ -225,53 +220,69 @@ Tcl_CaseObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_CatchObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_CatchObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
Tcl_Obj *varNamePtr = NULL;
+ Tcl_Obj *optionVarNamePtr = NULL;
int result;
-#ifdef TCL_TIP280
- Interp* iPtr = (Interp*) interp;
-#endif
+ Interp *iPtr = (Interp *) interp;
- if ((objc != 2) && (objc != 3)) {
- Tcl_WrongNumArgs(interp, 1, objv, "command ?varName?");
+ if ((objc < 2) || (objc > 4)) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "script ?resultVarName? ?optionVarName?");
return TCL_ERROR;
}
- if (objc == 3) {
+ if (objc >= 3) {
varNamePtr = objv[2];
}
+ if (objc == 4) {
+ optionVarNamePtr = objv[3];
+ }
-#ifndef TCL_TIP280
- result = Tcl_EvalObjEx(interp, objv[1], 0);
-#else
- /* TIP #280. Make invoking context available to caught script */
- result = TclEvalObjEx(interp, objv[1], 0, iPtr->cmdFramePtr,1);
-#endif
-
- if (objc == 3) {
- if (Tcl_ObjSetVar2(interp, varNamePtr, NULL,
- Tcl_GetObjResult(interp), 0) == NULL) {
+ /*
+ * TIP #280. Make invoking context available to caught script.
+ */
+
+ result = TclEvalObjEx(interp, objv[1], 0, iPtr->cmdFramePtr, 1);
+
+ /*
+ * We disable catch in interpreters where the limit has been exceeded.
+ */
+
+ if (Tcl_LimitExceeded(interp)) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (\"catch\" body line %d)", interp->errorLine));
+ return TCL_ERROR;
+ }
+
+ if (objc >= 3) {
+ if (NULL == Tcl_ObjSetVar2(interp, varNamePtr, NULL,
+ Tcl_GetObjResult(interp), 0)) {
Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "couldn't save command result in variable", -1);
+ Tcl_AppendResult(interp,
+ "couldn't save command result in variable", NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (objc == 4) {
+ Tcl_Obj *options = Tcl_GetReturnOptions(interp, result);
+ if (NULL == Tcl_ObjSetVar2(interp, optionVarNamePtr, NULL,
+ options, 0)) {
+ Tcl_DecrRefCount(options);
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp,
+ "couldn't save return options in variable", NULL);
return TCL_ERROR;
}
}
-
- /*
- * Set the interpreter's object result to an integer object holding the
- * integer Tcl_EvalObj result. Note that we don't bother generating a
- * string representation. We reset the interpreter's object result
- * to an unshared empty object and then set it to be an integer object.
- */
Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), result);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(result));
return TCL_OK;
}
@@ -280,8 +291,8 @@ Tcl_CatchObjCmd(dummy, interp, objc, objv)
*
* Tcl_CdObjCmd --
*
- * This procedure is invoked to process the "cd" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "cd" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -294,11 +305,11 @@ Tcl_CatchObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_CdObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_CdObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
Tcl_Obj *dir;
int result;
@@ -311,7 +322,7 @@ Tcl_CdObjCmd(dummy, interp, objc, objv)
if (objc == 2) {
dir = objv[1];
} else {
- dir = Tcl_NewStringObj("~",1);
+ TclNewLiteralStringObj(dir, "~");
Tcl_IncrRefCount(dir);
}
if (Tcl_FSConvertToPathType(interp, dir) != TCL_OK) {
@@ -320,7 +331,7 @@ Tcl_CdObjCmd(dummy, interp, objc, objv)
result = Tcl_FSChdir(dir);
if (result != TCL_OK) {
Tcl_AppendResult(interp, "couldn't change working directory to \"",
- Tcl_GetString(dir), "\": ", Tcl_PosixError(interp), (char *) NULL);
+ TclGetString(dir), "\": ", Tcl_PosixError(interp), NULL);
result = TCL_ERROR;
}
}
@@ -349,11 +360,11 @@ Tcl_CdObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_ConcatObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_ConcatObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
if (objc >= 2) {
Tcl_SetObjResult(interp, Tcl_ConcatObj(objc-1, objv+1));
@@ -364,14 +375,14 @@ Tcl_ConcatObjCmd(dummy, interp, objc, objv)
/*
*----------------------------------------------------------------------
*
- * Tcl_ContinueObjCmd -
+ * Tcl_ContinueObjCmd --
*
- * This procedure is invoked to process the "continue" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "continue" Tcl command. See
+ * the user documentation for details on what it does.
*
- * With the bytecode compiler, this procedure is only called when
- * a command name is computed at runtime, and is "continue" or the name
- * to which "continue" was renamed: e.g., "set z continue; $z"
+ * With the bytecode compiler, this procedure is only called when a
+ * command name is computed at runtime, and is "continue" or the name to
+ * which "continue" was renamed: e.g., "set z continue; $z"
*
* Results:
* A standard Tcl result.
@@ -384,11 +395,11 @@ Tcl_ConcatObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_ContinueObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_ContinueObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, NULL);
@@ -414,29 +425,25 @@ Tcl_ContinueObjCmd(dummy, interp, objc, objv)
*/
int
-Tcl_EncodingObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_EncodingObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
- int index, length;
- Tcl_Encoding encoding;
- char *string;
- Tcl_DString ds;
- Tcl_Obj *resultPtr;
+ int index;
static CONST char *optionStrings[] = {
- "convertfrom", "convertto", "names", "system",
+ "convertfrom", "convertto", "dirs", "names", "system",
NULL
};
enum options {
- ENC_CONVERTFROM, ENC_CONVERTTO, ENC_NAMES, ENC_SYSTEM
+ ENC_CONVERTFROM, ENC_CONVERTTO, ENC_DIRS, ENC_NAMES, ENC_SYSTEM
};
if (objc < 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
- return TCL_ERROR;
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
&index) != TCL_OK) {
@@ -444,79 +451,121 @@ Tcl_EncodingObjCmd(dummy, interp, objc, objv)
}
switch ((enum options) index) {
- case ENC_CONVERTTO:
- case ENC_CONVERTFROM: {
- Tcl_Obj *data;
- if (objc == 3) {
- encoding = Tcl_GetEncoding(interp, NULL);
- data = objv[2];
- } else if (objc == 4) {
- if (TclGetEncodingFromObj(interp, objv[2], &encoding)
- != TCL_OK) {
- return TCL_ERROR;
- }
- data = objv[3];
- } else {
- Tcl_WrongNumArgs(interp, 2, objv, "?encoding? data");
+ case ENC_CONVERTTO:
+ case ENC_CONVERTFROM: {
+ Tcl_Obj *data;
+ Tcl_DString ds;
+ Tcl_Encoding encoding;
+ int length;
+ char *stringPtr;
+
+ if (objc == 3) {
+ encoding = Tcl_GetEncoding(interp, NULL);
+ data = objv[2];
+ } else if (objc == 4) {
+ if (Tcl_GetEncodingFromObj(interp, objv[2], &encoding) != TCL_OK) {
return TCL_ERROR;
}
-
- if ((enum options) index == ENC_CONVERTFROM) {
- /*
- * Treat the string as binary data.
- */
+ data = objv[3];
+ } else {
+ Tcl_WrongNumArgs(interp, 2, objv, "?encoding? data");
+ return TCL_ERROR;
+ }
- string = (char *) Tcl_GetByteArrayFromObj(data, &length);
- Tcl_ExternalToUtfDString(encoding, string, length, &ds);
+ if ((enum options) index == ENC_CONVERTFROM) {
+ /*
+ * Treat the string as binary data.
+ */
- /*
- * Note that we cannot use Tcl_DStringResult here because
- * it will truncate the string at the first null byte.
- */
+ stringPtr = (char *) Tcl_GetByteArrayFromObj(data, &length);
+ Tcl_ExternalToUtfDString(encoding, stringPtr, length, &ds);
- Tcl_SetStringObj(Tcl_GetObjResult(interp),
- Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
- Tcl_DStringFree(&ds);
- } else {
- /*
- * Store the result as binary data.
- */
+ /*
+ * Note that we cannot use Tcl_DStringResult here because it will
+ * truncate the string at the first null byte.
+ */
- string = Tcl_GetStringFromObj(data, &length);
- Tcl_UtfToExternalDString(encoding, string, length, &ds);
- resultPtr = Tcl_GetObjResult(interp);
- Tcl_SetByteArrayObj(resultPtr,
- (unsigned char *) Tcl_DStringValue(&ds),
- Tcl_DStringLength(&ds));
- Tcl_DStringFree(&ds);
- }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)));
+ Tcl_DStringFree(&ds);
+ } else {
+ /*
+ * Store the result as binary data.
+ */
- Tcl_FreeEncoding(encoding);
- break;
+ stringPtr = TclGetStringFromObj(data, &length);
+ Tcl_UtfToExternalDString(encoding, stringPtr, length, &ds);
+ Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(
+ (unsigned char *) Tcl_DStringValue(&ds),
+ Tcl_DStringLength(&ds)));
+ Tcl_DStringFree(&ds);
}
- case ENC_NAMES: {
- if (objc > 2) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- return TCL_ERROR;
- }
- Tcl_GetEncodingNames(interp);
- break;
+
+ Tcl_FreeEncoding(encoding);
+ break;
+ }
+ case ENC_DIRS:
+ return EncodingDirsObjCmd(dummy, interp, objc-1, objv+1);
+ case ENC_NAMES:
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return TCL_ERROR;
}
- case ENC_SYSTEM: {
- if (objc > 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "?encoding?");
- return TCL_ERROR;
- }
- if (objc == 2) {
- Tcl_SetStringObj(Tcl_GetObjResult(interp),
- Tcl_GetEncodingName(NULL), -1);
- } else {
- return Tcl_SetSystemEncoding(interp,
- Tcl_GetStringFromObj(objv[2], NULL));
- }
- break;
+ Tcl_GetEncodingNames(interp);
+ break;
+ case ENC_SYSTEM:
+ if (objc > 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?encoding?");
+ return TCL_ERROR;
+ }
+ if (objc == 2) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ Tcl_GetEncodingName(NULL), -1));
+ } else {
+ return Tcl_SetSystemEncoding(interp, TclGetString(objv[2]));
}
+ break;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EncodingDirsObjCmd --
+ *
+ * This command manipulates the encoding search path.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Can set the encoding search path.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+EncodingDirsObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
+{
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "?dirList?");
+ return TCL_ERROR;
}
+ if (objc == 1) {
+ Tcl_SetObjResult(interp, Tcl_GetEncodingSearchPath());
+ return TCL_OK;
+ }
+ if (Tcl_SetEncodingSearchPath(objv[1]) == TCL_ERROR) {
+ Tcl_AppendResult(interp, "expected directory list but got \"",
+ TclGetString(objv[1]), "\"", NULL);
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, objv[1]);
return TCL_OK;
}
@@ -525,8 +574,8 @@ Tcl_EncodingObjCmd(dummy, interp, objc, objv)
*
* Tcl_ErrorObjCmd --
*
- * This procedure is invoked to process the "error" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "error" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl object result.
@@ -539,36 +588,35 @@ Tcl_EncodingObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_ErrorObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_ErrorObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
- Interp *iPtr = (Interp *) interp;
- char *info;
- int infoLen;
+ Tcl_Obj *options, *optName;
if ((objc < 2) || (objc > 4)) {
Tcl_WrongNumArgs(interp, 1, objv, "message ?errorInfo? ?errorCode?");
return TCL_ERROR;
}
-
- if (objc >= 3) { /* process the optional info argument */
- info = Tcl_GetStringFromObj(objv[2], &infoLen);
- if (infoLen > 0) {
- Tcl_AddObjErrorInfo(interp, info, infoLen);
- iPtr->flags |= ERR_ALREADY_LOGGED;
- }
+
+ TclNewLiteralStringObj(options, "-code error -level 0");
+
+ if (objc >= 3) { /* Process the optional info argument */
+ TclNewLiteralStringObj(optName, "-errorinfo");
+ Tcl_ListObjAppendElement(NULL, options, optName);
+ Tcl_ListObjAppendElement(NULL, options, objv[2]);
}
-
- if (objc == 4) {
- Tcl_SetVar2Ex(interp, "errorCode", NULL, objv[3], TCL_GLOBAL_ONLY);
- iPtr->flags |= ERROR_CODE_SET;
+
+ if (objc >= 4) { /* Process the optional code argument */
+ TclNewLiteralStringObj(optName, "-errorcode");
+ Tcl_ListObjAppendElement(NULL, options, optName);
+ Tcl_ListObjAppendElement(NULL, options, objv[3]);
}
-
+
Tcl_SetObjResult(interp, objv[1]);
- return TCL_ERROR;
+ return Tcl_SetReturnOptions(interp, options);
}
/*
@@ -576,7 +624,7 @@ Tcl_ErrorObjCmd(dummy, interp, objc, objv)
*
* Tcl_EvalObjCmd --
*
- * This object-based procedure is invoked to process the "eval" Tcl
+ * This object-based procedure is invoked to process the "eval" Tcl
* command. See the user documentation for details on what it does.
*
* Results:
@@ -590,53 +638,50 @@ Tcl_ErrorObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_EvalObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_EvalObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
int result;
register Tcl_Obj *objPtr;
-#ifdef TCL_TIP280
- Interp* iPtr = (Interp*) interp;
-#endif
+ Interp *iPtr = (Interp *) interp;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "arg ?arg ...?");
return TCL_ERROR;
}
-
+
if (objc == 2) {
-#ifndef TCL_TIP280
- result = Tcl_EvalObjEx(interp, objv[1], TCL_EVAL_DIRECT);
-#else
- /* TIP #280. Make argument location available to eval'd script */
+ /*
+ * TIP #280. Make argument location available to eval'd script.
+ */
+
CmdFrame* invoker = iPtr->cmdFramePtr;
int word = 1;
TclArgumentGet (interp, objv[1], &invoker, &word);
+
result = TclEvalObjEx(interp, objv[1], TCL_EVAL_DIRECT,
- invoker, word);
-#endif
+ invoker, word);
} else {
/*
* More than one argument: concatenate them together with spaces
- * between, then evaluate the result. Tcl_EvalObjEx will delete
- * the object when it decrements its refcount after eval'ing it.
+ * between, then evaluate the result. Tcl_EvalObjEx will delete the
+ * object when it decrements its refcount after eval'ing it.
*/
- objPtr = Tcl_ConcatObj(objc-1, objv+1);
-#ifndef TCL_TIP280
- result = Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_DIRECT);
-#else
- /* TIP #280. Make invoking context available to eval'd script */
+
+ objPtr = Tcl_ConcatObj(objc-1, objv+1);
+
+ /*
+ * TIP #280. Make invoking context available to eval'd script.
+ */
+
result = TclEvalObjEx(interp, objPtr, TCL_EVAL_DIRECT, NULL, 0);
-#endif
}
if (result == TCL_ERROR) {
- char msg[32 + TCL_INTEGER_SPACE];
-
- sprintf(msg, "\n (\"eval\" body line %d)", interp->errorLine);
- Tcl_AddObjErrorInfo(interp, msg, -1);
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (\"eval\" body line %d)", interp->errorLine));
}
return result;
}
@@ -646,8 +691,8 @@ Tcl_EvalObjCmd(dummy, interp, objc, objv)
*
* Tcl_ExitObjCmd --
*
- * This procedure is invoked to process the "exit" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "exit" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl object result.
@@ -660,11 +705,11 @@ Tcl_EvalObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_ExitObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_ExitObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
int value;
@@ -672,7 +717,7 @@ Tcl_ExitObjCmd(dummy, interp, objc, objv)
Tcl_WrongNumArgs(interp, 1, objv, "?returnCode?");
return TCL_ERROR;
}
-
+
if (objc == 1) {
value = 0;
} else if (Tcl_GetIntFromObj(interp, objv[1], &value) != TCL_OK) {
@@ -680,7 +725,7 @@ Tcl_ExitObjCmd(dummy, interp, objc, objv)
}
Tcl_Exit(value);
/*NOTREACHED*/
- return TCL_OK; /* Better not ever reach this! */
+ return TCL_OK; /* Better not ever reach this! */
}
/*
@@ -692,8 +737,8 @@ Tcl_ExitObjCmd(dummy, interp, objc, objv)
* command. See the user documentation for details on what it does.
*
* With the bytecode compiler, this procedure is called in two
- * circumstances: 1) to execute expr commands that are too complicated
- * or too unsafe to try compiling directly into an inline sequence of
+ * circumstances: 1) to execute expr commands that are too complicated or
+ * too unsafe to try compiling directly into an inline sequence of
* instructions, and 2) to execute commands where the command name is
* computed at runtime and is "expr" or the name to which "expr" was
* renamed (e.g., "set z expr; $z 2+3")
@@ -709,16 +754,14 @@ Tcl_ExitObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_ExprObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
-{
- register Tcl_Obj *objPtr;
+Tcl_ExprObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
+{
Tcl_Obj *resultPtr;
- register char *bytes;
- int length, i, result;
+ int result;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "arg ?arg ...?");
@@ -727,42 +770,18 @@ Tcl_ExprObjCmd(dummy, interp, objc, objv)
if (objc == 2) {
result = Tcl_ExprObj(interp, objv[1], &resultPtr);
- if (result == TCL_OK) {
- Tcl_SetObjResult(interp, resultPtr);
- Tcl_DecrRefCount(resultPtr); /* done with the result object */
- }
- return result;
- }
-
- /*
- * Create a new object holding the concatenated argument strings.
- */
-
- /*** QUESTION: Do we need to copy the slow way? ***/
- bytes = Tcl_GetStringFromObj(objv[1], &length);
- objPtr = Tcl_NewStringObj(bytes, length);
- Tcl_IncrRefCount(objPtr);
- for (i = 2; i < objc; i++) {
- Tcl_AppendToObj(objPtr, " ", 1);
- bytes = Tcl_GetStringFromObj(objv[i], &length);
- Tcl_AppendToObj(objPtr, bytes, length);
+ } else {
+ Tcl_Obj *objPtr = Tcl_ConcatObj(objc-1, objv+1);
+ Tcl_IncrRefCount(objPtr);
+ result = Tcl_ExprObj(interp, objPtr, &resultPtr);
+ Tcl_DecrRefCount(objPtr);
}
- /*
- * Evaluate the concatenated string object.
- */
-
- result = Tcl_ExprObj(interp, objPtr, &resultPtr);
if (result == TCL_OK) {
Tcl_SetObjResult(interp, resultPtr);
- Tcl_DecrRefCount(resultPtr); /* done with the result object */
+ Tcl_DecrRefCount(resultPtr); /* Done with the result object */
}
- /*
- * Free allocated resources.
- */
-
- Tcl_DecrRefCount(objPtr);
return result;
}
@@ -771,12 +790,11 @@ Tcl_ExprObjCmd(dummy, interp, objc, objv)
*
* Tcl_FileObjCmd --
*
- * This procedure is invoked to process the "file" Tcl command.
- * See the user documentation for details on what it does.
- * PLEASE NOTE THAT THIS FAILS WITH FILENAMES AND PATHS WITH
- * EMBEDDED NULLS, WHICH COULD THEORETICALLY HAPPEN ON A MAC.
- * With the object-based Tcl_FS APIs, the above NOTE may no
- * longer be true. In any case this assertion should be tested.
+ * This procedure is invoked to process the "file" Tcl command. See the
+ * user documentation for details on what it does. PLEASE NOTE THAT THIS
+ * FAILS WITH FILENAMES AND PATHS WITH EMBEDDED NULLS. With the
+ * object-based Tcl_FS APIs, the above NOTE may no longer be true. In any
+ * case this assertion should be tested.
*
* Results:
* A standard Tcl result.
@@ -789,610 +807,569 @@ Tcl_ExprObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_FileObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_FileObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
- int index;
+ int index, value;
+ Tcl_StatBuf buf;
+ struct utimbuf tval;
-/*
- * This list of constants should match the fileOption string array below.
- */
+ /*
+ * This list of constants should match the fileOption string array below.
+ */
static CONST char *fileOptions[] = {
"atime", "attributes", "channels", "copy",
"delete",
"dirname", "executable", "exists", "extension",
"isdirectory", "isfile", "join", "link",
- "lstat", "mtime", "mkdir", "nativename",
+ "lstat", "mtime", "mkdir", "nativename",
"normalize", "owned",
"pathtype", "readable", "readlink", "rename",
- "rootname", "separator", "size", "split",
- "stat", "system",
+ "rootname", "separator", "size", "split",
+ "stat", "system",
"tail", "type", "volumes", "writable",
- (char *) NULL
+ NULL
};
enum options {
FCMD_ATIME, FCMD_ATTRIBUTES, FCMD_CHANNELS, FCMD_COPY,
FCMD_DELETE,
FCMD_DIRNAME, FCMD_EXECUTABLE, FCMD_EXISTS, FCMD_EXTENSION,
- FCMD_ISDIRECTORY, FCMD_ISFILE, FCMD_JOIN, FCMD_LINK,
- FCMD_LSTAT, FCMD_MTIME, FCMD_MKDIR, FCMD_NATIVENAME,
- FCMD_NORMALIZE, FCMD_OWNED,
+ FCMD_ISDIRECTORY, FCMD_ISFILE, FCMD_JOIN, FCMD_LINK,
+ FCMD_LSTAT, FCMD_MTIME, FCMD_MKDIR, FCMD_NATIVENAME,
+ FCMD_NORMALIZE, FCMD_OWNED,
FCMD_PATHTYPE, FCMD_READABLE, FCMD_READLINK, FCMD_RENAME,
- FCMD_ROOTNAME, FCMD_SEPARATOR, FCMD_SIZE, FCMD_SPLIT,
- FCMD_STAT, FCMD_SYSTEM,
+ FCMD_ROOTNAME, FCMD_SEPARATOR, FCMD_SIZE, FCMD_SPLIT,
+ FCMD_STAT, FCMD_SYSTEM,
FCMD_TAIL, FCMD_TYPE, FCMD_VOLUMES, FCMD_WRITABLE
};
if (objc < 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
- return TCL_ERROR;
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[1], fileOptions, "option", 0,
&index) != TCL_OK) {
- return TCL_ERROR;
+ return TCL_ERROR;
}
switch ((enum options) index) {
- case FCMD_ATIME: {
- Tcl_StatBuf buf;
- struct utimbuf tval;
- if ((objc < 3) || (objc > 4)) {
- Tcl_WrongNumArgs(interp, 2, objv, "name ?time?");
- return TCL_ERROR;
- }
- if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
+ case FCMD_ATIME:
+ case FCMD_MTIME:
+ if ((objc < 3) || (objc > 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "name ?time?");
+ return TCL_ERROR;
+ }
+ if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc == 4) {
+ /*
+ * Need separate variable for reading longs from an object on
+ * 64-bit platforms. [Bug #698146]
+ */
+
+ long newTime;
+
+ if (TclGetLongFromObj(interp, objv[3], &newTime) != TCL_OK) {
return TCL_ERROR;
}
- if (objc == 4) {
- long newTime;
- if (Tcl_GetLongFromObj(interp, objv[3], &newTime) != TCL_OK) {
- return TCL_ERROR;
- }
+ if (index == FCMD_ATIME) {
tval.actime = newTime;
tval.modtime = buf.st_mtime;
- if (Tcl_FSUtime(objv[2], &tval) != 0) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "could not set access time for file \"",
- Tcl_GetString(objv[2]), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
- return TCL_ERROR;
- }
- /*
- * Do another stat to ensure that the we return the
- * new recognized atime - hopefully the same as the
- * one we sent in. However, fs's like FAT don't
- * even know what atime is.
- */
- if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
- return TCL_ERROR;
- }
+ } else { /* index == FCMD_MTIME */
+ tval.actime = buf.st_atime;
+ tval.modtime = newTime;
}
- Tcl_SetLongObj(Tcl_GetObjResult(interp), (long) buf.st_atime);
- return TCL_OK;
- }
- case FCMD_ATTRIBUTES: {
- return TclFileAttrsCmd(interp, objc, objv);
- }
- case FCMD_CHANNELS: {
- if ((objc < 2) || (objc > 3)) {
- Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
+
+ if (Tcl_FSUtime(objv[2], &tval) != 0) {
+ Tcl_AppendResult(interp, "could not set ",
+ (index == FCMD_ATIME ? "access" : "modification"),
+ " time for file \"", TclGetString(objv[2]), "\": ",
+ Tcl_PosixError(interp), NULL);
return TCL_ERROR;
}
- return Tcl_GetChannelNamesEx(interp,
- ((objc == 2) ? NULL : Tcl_GetString(objv[2])));
- }
- case FCMD_COPY: {
- return TclFileCopyCmd(interp, objc, objv);
- }
- case FCMD_DELETE: {
- return TclFileDeleteCmd(interp, objc, objv);
- }
- case FCMD_DIRNAME: {
- Tcl_Obj *dirPtr;
- if (objc != 3) {
- goto only3Args;
- }
- dirPtr = TclFileDirname(interp, objv[2]);
- if (dirPtr == NULL) {
- return TCL_ERROR;
- } else {
- Tcl_SetObjResult(interp, dirPtr);
- Tcl_DecrRefCount(dirPtr);
- return TCL_OK;
+
+ /*
+ * Do another stat to ensure that the we return the new recognized
+ * atime - hopefully the same as the one we sent in. However, fs's
+ * like FAT don't even know what atime is.
+ */
+
+ if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
+ return TCL_ERROR;
}
}
- case FCMD_EXECUTABLE: {
- if (objc != 3) {
- goto only3Args;
- }
- return CheckAccess(interp, objv[2], X_OK);
+
+ Tcl_SetObjResult(interp, Tcl_NewLongObj((long)
+ (index == FCMD_ATIME ? buf.st_atime : buf.st_mtime)));
+ return TCL_OK;
+ case FCMD_ATTRIBUTES:
+ return TclFileAttrsCmd(interp, objc, objv);
+ case FCMD_CHANNELS:
+ if ((objc < 2) || (objc > 3)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
+ return TCL_ERROR;
}
- case FCMD_EXISTS: {
- if (objc != 3) {
- goto only3Args;
- }
- return CheckAccess(interp, objv[2], F_OK);
+ return Tcl_GetChannelNamesEx(interp,
+ ((objc == 2) ? NULL : TclGetString(objv[2])));
+ case FCMD_COPY:
+ return TclFileCopyCmd(interp, objc, objv);
+ case FCMD_DELETE:
+ return TclFileDeleteCmd(interp, objc, objv);
+ case FCMD_DIRNAME: {
+ Tcl_Obj *dirPtr;
+
+ if (objc != 3) {
+ goto only3Args;
}
- case FCMD_EXTENSION: {
- char *fileName, *extension;
- if (objc != 3) {
- goto only3Args;
- }
- fileName = Tcl_GetString(objv[2]);
- extension = TclGetExtension(fileName);
- if (extension != NULL) {
- Tcl_SetStringObj(Tcl_GetObjResult(interp), extension, -1);
- }
+ dirPtr = TclPathPart(interp, objv[2], TCL_PATH_DIRNAME);
+ if (dirPtr == NULL) {
+ return TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, dirPtr);
+ Tcl_DecrRefCount(dirPtr);
return TCL_OK;
}
- case FCMD_ISDIRECTORY: {
- int value;
- Tcl_StatBuf buf;
-
- if (objc != 3) {
- goto only3Args;
- }
- value = 0;
- if (GetStatBuf(NULL, objv[2], Tcl_FSStat, &buf) == TCL_OK) {
- value = S_ISDIR(buf.st_mode);
- }
- Tcl_SetBooleanObj(Tcl_GetObjResult(interp), value);
+ }
+ case FCMD_EXECUTABLE:
+ if (objc != 3) {
+ goto only3Args;
+ }
+ return CheckAccess(interp, objv[2], X_OK);
+ case FCMD_EXISTS:
+ if (objc != 3) {
+ goto only3Args;
+ }
+ return CheckAccess(interp, objv[2], F_OK);
+ case FCMD_EXTENSION: {
+ Tcl_Obj *ext;
+
+ if (objc != 3) {
+ goto only3Args;
+ }
+ ext = TclPathPart(interp, objv[2], TCL_PATH_EXTENSION);
+ if (ext != NULL) {
+ Tcl_SetObjResult(interp, ext);
+ Tcl_DecrRefCount(ext);
return TCL_OK;
+ } else {
+ return TCL_ERROR;
}
- case FCMD_ISFILE: {
- int value;
- Tcl_StatBuf buf;
-
- if (objc != 3) {
- goto only3Args;
- }
- value = 0;
- if (GetStatBuf(NULL, objv[2], Tcl_FSStat, &buf) == TCL_OK) {
- value = S_ISREG(buf.st_mode);
- }
- Tcl_SetBooleanObj(Tcl_GetObjResult(interp), value);
- return TCL_OK;
+ }
+ case FCMD_ISDIRECTORY:
+ if (objc != 3) {
+ goto only3Args;
+ }
+ value = 0;
+ if (GetStatBuf(NULL, objv[2], Tcl_FSStat, &buf) == TCL_OK) {
+ value = S_ISDIR(buf.st_mode);
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value));
+ return TCL_OK;
+ case FCMD_ISFILE:
+ if (objc != 3) {
+ goto only3Args;
+ }
+ value = 0;
+ if (GetStatBuf(NULL, objv[2], Tcl_FSStat, &buf) == TCL_OK) {
+ value = S_ISREG(buf.st_mode);
}
- case FCMD_JOIN: {
- Tcl_Obj *resObj;
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value));
+ return TCL_OK;
+ case FCMD_OWNED:
+ if (objc != 3) {
+ goto only3Args;
+ }
+ value = 0;
+ if (GetStatBuf(NULL, objv[2], Tcl_FSStat, &buf) == TCL_OK) {
+ /*
+ * For Windows, there are no user ids associated with a file, so
+ * we always return 1.
+ */
- if (objc < 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "name ?name ...?");
- return TCL_ERROR;
- }
- resObj = Tcl_FSJoinToPath(NULL, objc - 2, objv + 2);
- Tcl_SetObjResult(interp, resObj);
- return TCL_OK;
+#if defined(__WIN32__)
+ value = 1;
+#else
+ value = (geteuid() == buf.st_uid);
+#endif
}
- case FCMD_LINK: {
- Tcl_Obj *contents;
- int index;
-
- if (objc < 3 || objc > 5) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-linktype? linkname ?target?");
- return TCL_ERROR;
- }
-
- /* Index of the 'source' argument */
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value));
+ return TCL_OK;
+ case FCMD_JOIN: {
+ Tcl_Obj *resObj;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "name ?name ...?");
+ return TCL_ERROR;
+ }
+ resObj = Tcl_FSJoinToPath(NULL, objc - 2, objv + 2);
+ Tcl_SetObjResult(interp, resObj);
+ return TCL_OK;
+ }
+ case FCMD_LINK: {
+ Tcl_Obj *contents;
+ int index;
+
+ if (objc < 3 || objc > 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-linktype? linkname ?target?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Index of the 'source' argument.
+ */
+
+ if (objc == 5) {
+ index = 3;
+ } else {
+ index = 2;
+ }
+
+ if (objc > 3) {
+ int linkAction;
if (objc == 5) {
- index = 3;
- } else {
- index = 2;
- }
-
- if (objc > 3) {
- int linkAction;
- if (objc == 5) {
- /* We have a '-linktype' argument */
- static CONST char *linkTypes[] = {
- "-symbolic", "-hard", NULL
- };
- if (Tcl_GetIndexFromObj(interp, objv[2], linkTypes,
- "switch", 0, &linkAction) != TCL_OK) {
- return TCL_ERROR;
- }
- if (linkAction == 0) {
- linkAction = TCL_CREATE_SYMBOLIC_LINK;
- } else {
- linkAction = TCL_CREATE_HARD_LINK;
- }
- } else {
- linkAction = TCL_CREATE_SYMBOLIC_LINK|TCL_CREATE_HARD_LINK;
- }
- if (Tcl_FSConvertToPathType(interp, objv[index]) != TCL_OK) {
+ /*
+ * We have a '-linktype' argument.
+ */
+
+ static CONST char *linkTypes[] = {
+ "-symbolic", "-hard", NULL
+ };
+ if (Tcl_GetIndexFromObj(interp, objv[2], linkTypes, "switch",
+ 0, &linkAction) != TCL_OK) {
return TCL_ERROR;
}
- /* Create link from source to target */
- contents = Tcl_FSLink(objv[index], objv[index+1], linkAction);
- if (contents == NULL) {
- /*
- * We handle two common error cases specially, and
- * for all other errors, we use the standard posix
- * error message.
- */
- if (errno == EEXIST) {
- Tcl_AppendResult(interp, "could not create new link \"",
- Tcl_GetString(objv[index]),
- "\": that path already exists", (char *) NULL);
- } else if (errno == ENOENT) {
- Tcl_AppendResult(interp, "could not create new link \"",
- Tcl_GetString(objv[index]),
- "\" since target \"",
- Tcl_GetString(objv[index+1]),
- "\" doesn't exist",
- (char *) NULL);
- } else {
- Tcl_AppendResult(interp, "could not create new link \"",
- Tcl_GetString(objv[index]), "\" pointing to \"",
- Tcl_GetString(objv[index+1]), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
- }
- return TCL_ERROR;
+ if (linkAction == 0) {
+ linkAction = TCL_CREATE_SYMBOLIC_LINK;
+ } else {
+ linkAction = TCL_CREATE_HARD_LINK;
}
} else {
- if (Tcl_FSConvertToPathType(interp, objv[index]) != TCL_OK) {
- return TCL_ERROR;
- }
- /* Read link */
- contents = Tcl_FSLink(objv[index], NULL, 0);
- if (contents == NULL) {
- Tcl_AppendResult(interp, "could not read link \"",
- Tcl_GetString(objv[index]), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
- return TCL_ERROR;
- }
- }
- Tcl_SetObjResult(interp, contents);
- if (objc == 3) {
- /*
- * If we are reading a link, we need to free this
- * result refCount. If we are creating a link, this
- * will just be objv[index+1], and so we don't own it.
- */
- Tcl_DecrRefCount(contents);
+ linkAction = TCL_CREATE_SYMBOLIC_LINK|TCL_CREATE_HARD_LINK;
}
- return TCL_OK;
- }
- case FCMD_LSTAT: {
- char *varName;
- Tcl_StatBuf buf;
-
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "name varName");
- return TCL_ERROR;
- }
- if (GetStatBuf(interp, objv[2], Tcl_FSLstat, &buf) != TCL_OK) {
+ if (Tcl_FSConvertToPathType(interp, objv[index]) != TCL_OK) {
return TCL_ERROR;
}
- varName = Tcl_GetString(objv[3]);
- return StoreStatData(interp, varName, &buf);
- }
- case FCMD_MTIME: {
- Tcl_StatBuf buf;
- struct utimbuf tval;
- if ((objc < 3) || (objc > 4)) {
- Tcl_WrongNumArgs(interp, 2, objv, "name ?time?");
- return TCL_ERROR;
- }
- if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
- return TCL_ERROR;
- }
- if (objc == 4) {
- long newTime;
+ /*
+ * Create link from source to target.
+ */
- if (Tcl_GetLongFromObj(interp, objv[3], &newTime) != TCL_OK) {
- return TCL_ERROR;
- }
- tval.actime = buf.st_atime;
- tval.modtime = newTime;
- if (Tcl_FSUtime(objv[2], &tval) != 0) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "could not set modification time for file \"",
- Tcl_GetString(objv[2]), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
- return TCL_ERROR;
- }
+ contents = Tcl_FSLink(objv[index], objv[index+1], linkAction);
+ if (contents == NULL) {
/*
- * Do another stat to ensure that the we return the
- * new recognized atime - hopefully the same as the
- * one we sent in. However, fs's like FAT don't
- * even know what atime is.
+ * We handle three common error cases specially, and for all
+ * other errors, we use the standard posix error message.
*/
- if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
- return TCL_ERROR;
+
+ if (errno == EEXIST) {
+ Tcl_AppendResult(interp, "could not create new link \"",
+ TclGetString(objv[index]),
+ "\": that path already exists", NULL);
+ } else if (errno == ENOENT) {
+ /*
+ * There are two cases here: either the target doesn't
+ * exist, or the directory of the src doesn't exist.
+ */
+
+ int access;
+ Tcl_Obj *dirPtr = TclPathPart(interp, objv[index],
+ TCL_PATH_DIRNAME);
+
+ if (dirPtr == NULL) {
+ return TCL_ERROR;
+ }
+ access = Tcl_FSAccess(dirPtr, F_OK);
+ Tcl_DecrRefCount(dirPtr);
+ if (access != 0) {
+ Tcl_AppendResult(interp,
+ "could not create new link \"",
+ TclGetString(objv[index]),
+ "\": no such file or directory", NULL);
+ } else {
+ Tcl_AppendResult(interp,
+ "could not create new link \"",
+ TclGetString(objv[index]), "\": target \"",
+ TclGetString(objv[index+1]),
+ "\" doesn't exist", NULL);
+ }
+ } else {
+ Tcl_AppendResult(interp,
+ "could not create new link \"",
+ TclGetString(objv[index]), "\" pointing to \"",
+ TclGetString(objv[index+1]), "\": ",
+ Tcl_PosixError(interp), NULL);
}
- }
- Tcl_SetLongObj(Tcl_GetObjResult(interp), (long) buf.st_mtime);
- return TCL_OK;
- }
- case FCMD_MKDIR: {
- if (objc < 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "name ?name ...?");
return TCL_ERROR;
}
- return TclFileMakeDirsCmd(interp, objc, objv);
- }
- case FCMD_NATIVENAME: {
- CONST char *fileName;
- Tcl_DString ds;
-
- if (objc != 3) {
- goto only3Args;
- }
- fileName = Tcl_GetString(objv[2]);
- fileName = Tcl_TranslateFileName(interp, fileName, &ds);
- if (fileName == NULL) {
+ } else {
+ if (Tcl_FSConvertToPathType(interp, objv[index]) != TCL_OK) {
return TCL_ERROR;
}
- Tcl_SetStringObj(Tcl_GetObjResult(interp), fileName,
- Tcl_DStringLength(&ds));
- Tcl_DStringFree(&ds);
- return TCL_OK;
- }
- case FCMD_NORMALIZE: {
- Tcl_Obj *fileName;
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "filename");
- return TCL_ERROR;
- }
+ /*
+ * Read link
+ */
- fileName = Tcl_FSGetNormalizedPath(interp, objv[2]);
- if (fileName == NULL) {
+ contents = Tcl_FSLink(objv[index], NULL, 0);
+ if (contents == NULL) {
+ Tcl_AppendResult(interp, "could not read link \"",
+ TclGetString(objv[index]), "\": ",
+ Tcl_PosixError(interp), NULL);
return TCL_ERROR;
}
- Tcl_SetObjResult(interp, fileName);
- return TCL_OK;
}
- case FCMD_OWNED: {
- int value;
- Tcl_StatBuf buf;
-
- if (objc != 3) {
- goto only3Args;
- }
- value = 0;
- if (GetStatBuf(NULL, objv[2], Tcl_FSStat, &buf) == TCL_OK) {
- /*
- * For Windows and Macintosh, there are no user ids
- * associated with a file, so we always return 1.
- */
+ Tcl_SetObjResult(interp, contents);
+ if (objc == 3) {
+ /*
+ * If we are reading a link, we need to free this result refCount.
+ * If we are creating a link, this will just be objv[index+1], and
+ * so we don't own it.
+ */
-#if (defined(__WIN32__) || defined(MAC_TCL))
- value = 1;
-#else
- value = (geteuid() == buf.st_uid);
-#endif
- }
- Tcl_SetBooleanObj(Tcl_GetObjResult(interp), value);
- return TCL_OK;
+ Tcl_DecrRefCount(contents);
}
- case FCMD_PATHTYPE: {
- if (objc != 3) {
- goto only3Args;
- }
- switch (Tcl_FSGetPathType(objv[2])) {
- case TCL_PATH_ABSOLUTE:
- Tcl_SetStringObj(Tcl_GetObjResult(interp), "absolute", -1);
- break;
- case TCL_PATH_RELATIVE:
- Tcl_SetStringObj(Tcl_GetObjResult(interp), "relative", -1);
- break;
- case TCL_PATH_VOLUME_RELATIVE:
- Tcl_SetStringObj(Tcl_GetObjResult(interp),
- "volumerelative", -1);
- break;
- }
- return TCL_OK;
+ return TCL_OK;
+ }
+ case FCMD_LSTAT:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "name varName");
+ return TCL_ERROR;
}
- case FCMD_READABLE: {
- if (objc != 3) {
- goto only3Args;
- }
- return CheckAccess(interp, objv[2], R_OK);
+ if (GetStatBuf(interp, objv[2], Tcl_FSLstat, &buf) != TCL_OK) {
+ return TCL_ERROR;
}
- case FCMD_READLINK: {
- Tcl_Obj *contents;
-
- if (objc != 3) {
- goto only3Args;
- }
-
- if (Tcl_FSConvertToPathType(interp, objv[2]) != TCL_OK) {
- return TCL_ERROR;
- }
-
- contents = Tcl_FSLink(objv[2], NULL, 0);
+ return StoreStatData(interp, objv[3], &buf);
+ case FCMD_STAT:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "name varName");
+ return TCL_ERROR;
+ }
+ if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return StoreStatData(interp, objv[3], &buf);
+ case FCMD_SIZE:
+ if (objc != 3) {
+ goto only3Args;
+ }
+ if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp,
+ Tcl_NewWideIntObj((Tcl_WideInt) buf.st_size));
+ return TCL_OK;
+ case FCMD_TYPE:
+ if (objc != 3) {
+ goto only3Args;
+ }
+ if (GetStatBuf(interp, objv[2], Tcl_FSLstat, &buf) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ GetTypeFromMode((unsigned short) buf.st_mode), -1));
+ return TCL_OK;
+ case FCMD_MKDIR:
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "name ?name ...?");
+ return TCL_ERROR;
+ }
+ return TclFileMakeDirsCmd(interp, objc, objv);
+ case FCMD_NATIVENAME: {
+ CONST char *fileName;
+ Tcl_DString ds;
- if (contents == NULL) {
- Tcl_AppendResult(interp, "could not readlink \"",
- Tcl_GetString(objv[2]), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
- return TCL_ERROR;
- }
- Tcl_SetObjResult(interp, contents);
- Tcl_DecrRefCount(contents);
- return TCL_OK;
+ if (objc != 3) {
+ goto only3Args;
}
- case FCMD_RENAME: {
- return TclFileRenameCmd(interp, objc, objv);
+ fileName = TclGetString(objv[2]);
+ fileName = Tcl_TranslateFileName(interp, fileName, &ds);
+ if (fileName == NULL) {
+ return TCL_ERROR;
}
- case FCMD_ROOTNAME: {
- int length;
- char *fileName, *extension;
-
- if (objc != 3) {
- goto only3Args;
- }
- fileName = Tcl_GetStringFromObj(objv[2], &length);
- extension = TclGetExtension(fileName);
- if (extension == NULL) {
- Tcl_SetObjResult(interp, objv[2]);
- } else {
- Tcl_SetStringObj(Tcl_GetObjResult(interp), fileName,
- (int) (length - strlen(extension)));
- }
- return TCL_OK;
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(fileName,
+ Tcl_DStringLength(&ds)));
+ Tcl_DStringFree(&ds);
+ return TCL_OK;
+ }
+ case FCMD_NORMALIZE: {
+ Tcl_Obj *fileName;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "filename");
+ return TCL_ERROR;
}
- case FCMD_SEPARATOR: {
- if ((objc < 2) || (objc > 3)) {
- Tcl_WrongNumArgs(interp, 2, objv, "?name?");
- return TCL_ERROR;
- }
- if (objc == 2) {
- char *separator = NULL; /* lint */
- switch (tclPlatform) {
- case TCL_PLATFORM_UNIX:
- separator = "/";
- break;
- case TCL_PLATFORM_WINDOWS:
- separator = "\\";
- break;
- case TCL_PLATFORM_MAC:
- separator = ":";
- break;
- }
- Tcl_SetObjResult(interp, Tcl_NewStringObj(separator,1));
- } else {
- Tcl_Obj *separatorObj = Tcl_FSPathSeparator(objv[2]);
- if (separatorObj != NULL) {
- Tcl_SetObjResult(interp, separatorObj);
- } else {
- Tcl_SetObjResult(interp,
- Tcl_NewStringObj("Unrecognised path",-1));
- return TCL_ERROR;
- }
- }
- return TCL_OK;
+
+ fileName = Tcl_FSGetNormalizedPath(interp, objv[2]);
+ if (fileName == NULL) {
+ return TCL_ERROR;
}
- case FCMD_SIZE: {
- Tcl_StatBuf buf;
-
- if (objc != 3) {
- goto only3Args;
- }
- if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
- return TCL_ERROR;
- }
- Tcl_SetWideIntObj(Tcl_GetObjResult(interp),
- (Tcl_WideInt) buf.st_size);
- return TCL_OK;
+ Tcl_SetObjResult(interp, fileName);
+ return TCL_OK;
+ }
+ case FCMD_PATHTYPE: {
+ Tcl_Obj *typeName;
+
+ if (objc != 3) {
+ goto only3Args;
}
- case FCMD_SPLIT: {
- if (objc != 3) {
- goto only3Args;
- }
- Tcl_SetObjResult(interp, Tcl_FSSplitPath(objv[2], NULL));
+
+ switch (Tcl_FSGetPathType(objv[2])) {
+ case TCL_PATH_ABSOLUTE:
+ TclNewLiteralStringObj(typeName, "absolute");
+ break;
+ case TCL_PATH_RELATIVE:
+ TclNewLiteralStringObj(typeName, "relative");
+ break;
+ case TCL_PATH_VOLUME_RELATIVE:
+ TclNewLiteralStringObj(typeName, "volumerelative");
+ break;
+ default:
return TCL_OK;
}
- case FCMD_STAT: {
- char *varName;
- Tcl_StatBuf buf;
-
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 1, objv, "stat name varName");
- return TCL_ERROR;
- }
- if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
- return TCL_ERROR;
- }
- varName = Tcl_GetString(objv[3]);
- return StoreStatData(interp, varName, &buf);
+ Tcl_SetObjResult(interp, typeName);
+ return TCL_OK;
+ }
+ case FCMD_READABLE:
+ if (objc != 3) {
+ goto only3Args;
}
- case FCMD_SYSTEM: {
- Tcl_Obj* fsInfo;
- if (objc != 3) {
- goto only3Args;
- }
- fsInfo = Tcl_FSFileSystemInfo(objv[2]);
- if (fsInfo != NULL) {
- Tcl_SetObjResult(interp, fsInfo);
- return TCL_OK;
- } else {
- Tcl_SetObjResult(interp,
- Tcl_NewStringObj("Unrecognised path",-1));
- return TCL_ERROR;
- }
+ return CheckAccess(interp, objv[2], R_OK);
+ case FCMD_READLINK: {
+ Tcl_Obj *contents;
+
+ if (objc != 3) {
+ goto only3Args;
}
- case FCMD_TAIL: {
- int splitElements;
- Tcl_Obj *splitPtr;
- if (objc != 3) {
- goto only3Args;
- }
- /*
- * The behaviour we want here is slightly different to
- * the standard Tcl_FSSplitPath in the handling of home
- * directories; Tcl_FSSplitPath preserves the "~" while
- * this code computes the actual full path name, if we
- * had just a single component.
- */
- splitPtr = Tcl_FSSplitPath(objv[2], &splitElements);
- if ((splitElements == 1) && (Tcl_GetString(objv[2])[0] == '~')) {
- Tcl_DecrRefCount(splitPtr);
- splitPtr = Tcl_FSGetNormalizedPath(interp, objv[2]);
- if (splitPtr == NULL) {
- return TCL_ERROR;
- }
- splitPtr = Tcl_FSSplitPath(splitPtr, &splitElements);
- }
+ if (Tcl_FSConvertToPathType(interp, objv[2]) != TCL_OK) {
+ return TCL_ERROR;
+ }
- /*
- * Return the last component, unless it is the only component,
- * and it is the root of an absolute path.
- */
+ contents = Tcl_FSLink(objv[2], NULL, 0);
- if (splitElements > 0) {
- if ((splitElements > 1)
- || (Tcl_FSGetPathType(objv[2]) == TCL_PATH_RELATIVE)) {
-
- Tcl_Obj *tail = NULL;
- Tcl_ListObjIndex(NULL, splitPtr, splitElements-1, &tail);
- Tcl_SetObjResult(interp, tail);
- }
- }
- Tcl_DecrRefCount(splitPtr);
+ if (contents == NULL) {
+ Tcl_AppendResult(interp, "could not readlink \"",
+ TclGetString(objv[2]), "\": ", Tcl_PosixError(interp),
+ NULL);
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, contents);
+ Tcl_DecrRefCount(contents);
+ return TCL_OK;
+ }
+ case FCMD_RENAME:
+ return TclFileRenameCmd(interp, objc, objv);
+ case FCMD_ROOTNAME: {
+ Tcl_Obj *root;
+
+ if (objc != 3) {
+ goto only3Args;
+ }
+ root = TclPathPart(interp, objv[2], TCL_PATH_ROOT);
+ if (root != NULL) {
+ Tcl_SetObjResult(interp, root);
+ Tcl_DecrRefCount(root);
return TCL_OK;
+ } else {
+ return TCL_ERROR;
+ }
+ }
+ case FCMD_SEPARATOR:
+ if ((objc < 2) || (objc > 3)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?name?");
+ return TCL_ERROR;
}
- case FCMD_TYPE: {
- Tcl_StatBuf buf;
+ if (objc == 2) {
+ char *separator = NULL; /* lint */
- if (objc != 3) {
- goto only3Args;
+ switch (tclPlatform) {
+ case TCL_PLATFORM_UNIX:
+ separator = "/";
+ break;
+ case TCL_PLATFORM_WINDOWS:
+ separator = "\\";
+ break;
}
- if (GetStatBuf(interp, objv[2], Tcl_FSLstat, &buf) != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(separator, 1));
+ } else {
+ Tcl_Obj *separatorObj = Tcl_FSPathSeparator(objv[2]);
+
+ if (separatorObj == NULL) {
+ Tcl_SetResult(interp, "Unrecognised path", TCL_STATIC);
return TCL_ERROR;
}
- Tcl_SetStringObj(Tcl_GetObjResult(interp),
- GetTypeFromMode((unsigned short) buf.st_mode), -1);
- return TCL_OK;
+ Tcl_SetObjResult(interp, separatorObj);
}
- case FCMD_VOLUMES: {
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- return TCL_ERROR;
- }
- Tcl_SetObjResult(interp, Tcl_FSListVolumes());
- return TCL_OK;
+ return TCL_OK;
+ case FCMD_SPLIT: {
+ Tcl_Obj *res;
+
+ if (objc != 3) {
+ goto only3Args;
}
- case FCMD_WRITABLE: {
- if (objc != 3) {
- goto only3Args;
+ res = Tcl_FSSplitPath(objv[2], NULL);
+ if (res == NULL) {
+ /* How can the interp be NULL here?! DKF */
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "could not read \"",
+ TclGetString(objv[2]),
+ "\": no such file or directory", NULL);
}
- return CheckAccess(interp, objv[2], W_OK);
+ return TCL_ERROR;
}
+ Tcl_SetObjResult(interp, res);
+ return TCL_OK;
}
+ case FCMD_SYSTEM: {
+ Tcl_Obj *fsInfo;
- only3Args:
+ if (objc != 3) {
+ goto only3Args;
+ }
+ fsInfo = Tcl_FSFileSystemInfo(objv[2]);
+ if (fsInfo == NULL) {
+ Tcl_SetResult(interp, "Unrecognised path", TCL_STATIC);
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, fsInfo);
+ return TCL_OK;
+ }
+ case FCMD_TAIL: {
+ Tcl_Obj *dirPtr;
+
+ if (objc != 3) {
+ goto only3Args;
+ }
+ dirPtr = TclPathPart(interp, objv[2], TCL_PATH_TAIL);
+ if (dirPtr == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, dirPtr);
+ Tcl_DecrRefCount(dirPtr);
+ return TCL_OK;
+ }
+ case FCMD_VOLUMES:
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_FSListVolumes());
+ return TCL_OK;
+ case FCMD_WRITABLE:
+ if (objc != 3) {
+ goto only3Args;
+ }
+ return CheckAccess(interp, objv[2], W_OK);
+ }
+
+ only3Args:
Tcl_WrongNumArgs(interp, 2, objv, "name");
return TCL_ERROR;
}
@@ -1402,35 +1379,35 @@ Tcl_FileObjCmd(dummy, interp, objc, objv)
*
* CheckAccess --
*
- * Utility procedure used by Tcl_FileObjCmd() to query file
- * attributes available through the access() system call.
+ * Utility procedure used by Tcl_FileObjCmd() to query file attributes
+ * available through the access() system call.
*
* Results:
- * Always returns TCL_OK. Sets interp's result to boolean true or
- * false depending on whether the file has the specified attribute.
+ * Always returns TCL_OK. Sets interp's result to boolean true or false
+ * depending on whether the file has the specified attribute.
*
* Side effects:
* None.
*
*---------------------------------------------------------------------------
*/
-
+
static int
-CheckAccess(interp, objPtr, mode)
- Tcl_Interp *interp; /* Interp for status return. Must not be
+CheckAccess(
+ Tcl_Interp *interp, /* Interp for status return. Must not be
* NULL. */
- Tcl_Obj *objPtr; /* Name of file to check. */
- int mode; /* Attribute to check; passed as argument to
+ Tcl_Obj *pathPtr, /* Name of file to check. */
+ int mode) /* Attribute to check; passed as argument to
* access(). */
{
int value;
-
- if (Tcl_FSConvertToPathType(interp, objPtr) != TCL_OK) {
+
+ if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) {
value = 0;
} else {
- value = (Tcl_FSAccess(objPtr, mode) == 0);
+ value = (Tcl_FSAccess(pathPtr, mode) == 0);
}
- Tcl_SetBooleanObj(Tcl_GetObjResult(interp), value);
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value));
return TCL_OK;
}
@@ -1440,14 +1417,14 @@ CheckAccess(interp, objPtr, mode)
*
* GetStatBuf --
*
- * Utility procedure used by Tcl_FileObjCmd() to query file
- * attributes available through the stat() or lstat() system call.
+ * Utility procedure used by Tcl_FileObjCmd() to query file attributes
+ * available through the stat() or lstat() system call.
*
* Results:
- * The return value is TCL_OK if the specified file exists and can
- * be stat'ed, TCL_ERROR otherwise. If TCL_ERROR is returned, an
- * error message is left in interp's result. If TCL_OK is returned,
- * *statPtr is filled with information about the specified file.
+ * The return value is TCL_OK if the specified file exists and can be
+ * stat'ed, TCL_ERROR otherwise. If TCL_ERROR is returned, an error
+ * message is left in interp's result. If TCL_OK is returned, *statPtr is
+ * filled with information about the specified file.
*
* Side effects:
* None.
@@ -1456,27 +1433,27 @@ CheckAccess(interp, objPtr, mode)
*/
static int
-GetStatBuf(interp, objPtr, statProc, statPtr)
- Tcl_Interp *interp; /* Interp for error return. May be NULL. */
- Tcl_Obj *objPtr; /* Path name to examine. */
- Tcl_FSStatProc *statProc; /* Either stat() or lstat() depending on
+GetStatBuf(
+ Tcl_Interp *interp, /* Interp for error return. May be NULL. */
+ Tcl_Obj *pathPtr, /* Path name to examine. */
+ Tcl_FSStatProc *statProc, /* Either stat() or lstat() depending on
* desired behavior. */
- Tcl_StatBuf *statPtr; /* Filled with info about file obtained by
+ Tcl_StatBuf *statPtr) /* Filled with info about file obtained by
* calling (*statProc)(). */
{
int status;
-
- if (Tcl_FSConvertToPathType(interp, objPtr) != TCL_OK) {
+
+ if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) {
return TCL_ERROR;
}
- status = (*statProc)(objPtr, statPtr);
-
+ status = (*statProc)(pathPtr, statPtr);
+
if (status < 0) {
if (interp != NULL) {
Tcl_AppendResult(interp, "could not read \"",
- Tcl_GetString(objPtr), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ TclGetString(pathPtr), "\": ",
+ Tcl_PosixError(interp), NULL);
}
return TCL_ERROR;
}
@@ -1488,13 +1465,13 @@ GetStatBuf(interp, objPtr, statProc, statPtr)
*
* StoreStatData --
*
- * This is a utility procedure that breaks out the fields of a
- * "stat" structure and stores them in textual form into the
- * elements of an associative array.
+ * This is a utility procedure that breaks out the fields of a "stat"
+ * structure and stores them in textual form into the elements of an
+ * associative array.
*
* Results:
- * Returns a standard Tcl return value. If an error occurs then
- * a message is left in interp's result.
+ * Returns a standard Tcl return value. If an error occurs then a message
+ * is left in interp's result.
*
* Side effects:
* Elements of the associative array given by "varName" are modified.
@@ -1503,56 +1480,59 @@ GetStatBuf(interp, objPtr, statProc, statPtr)
*/
static int
-StoreStatData(interp, varName, statPtr)
- Tcl_Interp *interp; /* Interpreter for error reports. */
- char *varName; /* Name of associative array variable
- * in which to store stat results. */
- Tcl_StatBuf *statPtr; /* Pointer to buffer containing
- * stat data to store in varName. */
+StoreStatData(
+ Tcl_Interp *interp, /* Interpreter for error reports. */
+ Tcl_Obj *varName, /* Name of associative array variable in which
+ * to store stat results. */
+ Tcl_StatBuf *statPtr) /* Pointer to buffer containing stat data to
+ * store in varName. */
{
- Tcl_Obj *var = Tcl_NewStringObj(varName, -1);
- Tcl_Obj *field = Tcl_NewObj();
- Tcl_Obj *value;
+ Tcl_Obj *field, *value;
register unsigned short mode;
/*
* Assume Tcl_ObjSetVar2() does not keep a copy of the field name!
+ *
+ * Might be a better idea to call Tcl_SetVar2Ex() instead, except we want
+ * to have an object (i.e. possibly cached) array variable name but a
+ * string element name, so no API exists. Messy.
*/
+
#define STORE_ARY(fieldName, object) \
- Tcl_SetStringObj(field, (fieldName), -1); \
- value = (object); \
- if (Tcl_ObjSetVar2(interp,var,field,value,TCL_LEAVE_ERR_MSG) == NULL) { \
- Tcl_DecrRefCount(var); \
- Tcl_DecrRefCount(field); \
- Tcl_DecrRefCount(value); \
- return TCL_ERROR; \
- }
-
- Tcl_IncrRefCount(var);
- Tcl_IncrRefCount(field);
- STORE_ARY("dev", Tcl_NewLongObj((long)statPtr->st_dev));
+ TclNewLiteralStringObj(field, fieldName); \
+ Tcl_IncrRefCount(field); \
+ value = (object); \
+ if (Tcl_ObjSetVar2(interp,varName,field,value,TCL_LEAVE_ERR_MSG)==NULL) { \
+ TclDecrRefCount(field); \
+ return TCL_ERROR; \
+ } \
+ TclDecrRefCount(field);
+
/*
- * Watch out porters; the inode is meant to be an *unsigned* value,
- * so the cast might fail when there isn't a real arithmentic 'long
- * long' type...
+ * Watch out porters; the inode is meant to be an *unsigned* value, so the
+ * cast might fail when there isn't a real arithmentic 'long long' type...
*/
- STORE_ARY("ino", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_ino));
- STORE_ARY("nlink", Tcl_NewLongObj((long)statPtr->st_nlink));
- STORE_ARY("uid", Tcl_NewLongObj((long)statPtr->st_uid));
- STORE_ARY("gid", Tcl_NewLongObj((long)statPtr->st_gid));
- STORE_ARY("size", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_size));
-#ifdef HAVE_ST_BLOCKS
- STORE_ARY("blocks",Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_blocks));
+
+ STORE_ARY("dev", Tcl_NewLongObj((long)statPtr->st_dev));
+ STORE_ARY("ino", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_ino));
+ STORE_ARY("nlink", Tcl_NewLongObj((long)statPtr->st_nlink));
+ STORE_ARY("uid", Tcl_NewLongObj((long)statPtr->st_uid));
+ STORE_ARY("gid", Tcl_NewLongObj((long)statPtr->st_gid));
+ STORE_ARY("size", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_size));
+#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
+ STORE_ARY("blocks", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_blocks));
#endif
- STORE_ARY("atime", Tcl_NewLongObj((long)statPtr->st_atime));
- STORE_ARY("mtime", Tcl_NewLongObj((long)statPtr->st_mtime));
- STORE_ARY("ctime", Tcl_NewLongObj((long)statPtr->st_ctime));
+#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
+ STORE_ARY("blksize", Tcl_NewLongObj((long)statPtr->st_blksize));
+#endif
+ STORE_ARY("atime", Tcl_NewLongObj((long)statPtr->st_atime));
+ STORE_ARY("mtime", Tcl_NewLongObj((long)statPtr->st_mtime));
+ STORE_ARY("ctime", Tcl_NewLongObj((long)statPtr->st_ctime));
mode = (unsigned short) statPtr->st_mode;
- STORE_ARY("mode", Tcl_NewIntObj(mode));
- STORE_ARY("type", Tcl_NewStringObj(GetTypeFromMode(mode), -1));
+ STORE_ARY("mode", Tcl_NewIntObj(mode));
+ STORE_ARY("type", Tcl_NewStringObj(GetTypeFromMode(mode), -1));
#undef STORE_ARY
- Tcl_DecrRefCount(var);
- Tcl_DecrRefCount(field);
+
return TCL_OK;
}
@@ -1561,8 +1541,7 @@ StoreStatData(interp, varName, statPtr)
*
* GetTypeFromMode --
*
- * Given a mode word, returns a string identifying the type of a
- * file.
+ * Given a mode word, returns a string identifying the type of a file.
*
* Results:
* A static text string giving the file type from mode.
@@ -1574,8 +1553,8 @@ StoreStatData(interp, varName, statPtr)
*/
static char *
-GetTypeFromMode(mode)
- int mode;
+GetTypeFromMode(
+ int mode)
{
if (S_ISREG(mode)) {
return "file";
@@ -1604,103 +1583,98 @@ GetTypeFromMode(mode)
*
* Tcl_ForObjCmd --
*
- * This procedure is invoked to process the "for" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "for" Tcl command. See the
+ * user documentation for details on what it does.
*
- * With the bytecode compiler, this procedure is only called when
- * a command name is computed at runtime, and is "for" or the name
- * to which "for" was renamed: e.g.,
+ * With the bytecode compiler, this procedure is only called when a
+ * command name is computed at runtime, and is "for" or the name to which
+ * "for" was renamed: e.g.,
* "set z for; $z {set i 0} {$i<100} {incr i} {puts $i}"
*
* Results:
- * A standard Tcl result.
+ * A standard Tcl result.
*
* Side effects:
- * See the user documentation.
+ * See the user documentation.
*
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
+ /* ARGSUSED */
int
-Tcl_ForObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_ForObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
int result, value;
-#ifdef TCL_TIP280
- Interp* iPtr = (Interp*) interp;
-#endif
+ Interp *iPtr = (Interp *) interp;
if (objc != 5) {
- Tcl_WrongNumArgs(interp, 1, objv, "start test next command");
- return TCL_ERROR;
+ Tcl_WrongNumArgs(interp, 1, objv, "start test next command");
+ return TCL_ERROR;
}
-#ifndef TCL_TIP280
- result = Tcl_EvalObjEx(interp, objv[1], 0);
-#else
- /* TIP #280. Make invoking context available to initial script */
- result = TclEvalObjEx(interp, objv[1], 0, iPtr->cmdFramePtr,1);
-#endif
+ /*
+ * TIP #280. Make invoking context available to initial script.
+ */
+
+ result = TclEvalObjEx(interp, objv[1], 0, iPtr->cmdFramePtr, 1);
if (result != TCL_OK) {
- if (result == TCL_ERROR) {
- Tcl_AddErrorInfo(interp, "\n (\"for\" initial command)");
- }
- return result;
+ if (result == TCL_ERROR) {
+ Tcl_AddErrorInfo(interp, "\n (\"for\" initial command)");
+ }
+ return result;
}
while (1) {
/*
* We need to reset the result before passing it off to
- * Tcl_ExprBooleanObj. Otherwise, any error message will be appended
+ * Tcl_ExprBooleanObj. Otherwise, any error message will be appended
* to the result of the last evaluation.
*/
Tcl_ResetResult(interp);
- result = Tcl_ExprBooleanObj(interp, objv[2], &value);
- if (result != TCL_OK) {
- return result;
- }
- if (!value) {
- break;
- }
-#ifndef TCL_TIP280
- result = Tcl_EvalObjEx(interp, objv[4], 0);
-#else
- /* TIP #280. Make invoking context available to loop body */
- result = TclEvalObjEx(interp, objv[4], 0, iPtr->cmdFramePtr,4);
-#endif
- if ((result != TCL_OK) && (result != TCL_CONTINUE)) {
- if (result == TCL_ERROR) {
- char msg[32 + TCL_INTEGER_SPACE];
-
- sprintf(msg, "\n (\"for\" body line %d)",interp->errorLine);
- Tcl_AddErrorInfo(interp, msg);
- }
- break;
- }
-#ifndef TCL_TIP280
- result = Tcl_EvalObjEx(interp, objv[3], 0);
-#else
- /* TIP #280. Make invoking context available to next script */
- result = TclEvalObjEx(interp, objv[3], 0, iPtr->cmdFramePtr,3);
-#endif
+ result = Tcl_ExprBooleanObj(interp, objv[2], &value);
+ if (result != TCL_OK) {
+ return result;
+ }
+ if (!value) {
+ break;
+ }
+
+ /*
+ * TIP #280. Make invoking context available to loop body.
+ */
+
+ result = TclEvalObjEx(interp, objv[4], 0, iPtr->cmdFramePtr, 4);
+ if ((result != TCL_OK) && (result != TCL_CONTINUE)) {
+ if (result == TCL_ERROR) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (\"for\" body line %d)", interp->errorLine));
+ }
+ break;
+ }
+
+ /*
+ * TIP #280. Make invoking context available to next script.
+ */
+
+ result = TclEvalObjEx(interp, objv[3], 0, iPtr->cmdFramePtr, 3);
if (result == TCL_BREAK) {
- break;
- } else if (result != TCL_OK) {
- if (result == TCL_ERROR) {
- Tcl_AddErrorInfo(interp, "\n (\"for\" loop-end command)");
- }
- return result;
- }
+ break;
+ } else if (result != TCL_OK) {
+ if (result == TCL_ERROR) {
+ Tcl_AddErrorInfo(interp, "\n (\"for\" loop-end command)");
+ }
+ return result;
+ }
}
if (result == TCL_BREAK) {
- result = TCL_OK;
+ result = TCL_OK;
}
if (result == TCL_OK) {
- Tcl_ResetResult(interp);
+ Tcl_ResetResult(interp);
}
return result;
}
@@ -1711,7 +1685,7 @@ Tcl_ForObjCmd(dummy, interp, objc, objv)
* Tcl_ForeachObjCmd --
*
* This object-based procedure is invoked to process the "foreach" Tcl
- * command. See the user documentation for details on what it does.
+ * command. See the user documentation for details on what it does.
*
* Results:
* A standard Tcl object result.
@@ -1724,45 +1698,27 @@ Tcl_ForObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_ForeachObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_ForeachObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
int result = TCL_OK;
int i; /* i selects a value list */
int j, maxj; /* Number of loop iterations */
int v; /* v selects a loop variable */
- int numLists; /* Count of value lists */
+ int numLists = (objc-2)/2; /* Count of value lists */
Tcl_Obj *bodyPtr;
+ Interp *iPtr = (Interp *) interp;
- /*
- * We copy the argument object pointers into a local array to avoid
- * the problem that "objv" might become invalid. It is a pointer into
- * the evaluation stack and that stack might be grown and reallocated
- * if the loop body requires a large amount of stack space.
- */
-
-#define NUM_ARGS 9
- Tcl_Obj *(argObjStorage[NUM_ARGS]);
- Tcl_Obj **argObjv = argObjStorage;
-
-#define STATIC_LIST_SIZE 4
- int indexArray[STATIC_LIST_SIZE];
- int varcListArray[STATIC_LIST_SIZE];
- Tcl_Obj **varvListArray[STATIC_LIST_SIZE];
- int argcListArray[STATIC_LIST_SIZE];
- Tcl_Obj **argvListArray[STATIC_LIST_SIZE];
-
- int *index = indexArray; /* Array of value list indices */
- int *varcList = varcListArray; /* # loop variables per list */
- Tcl_Obj ***varvList = varvListArray; /* Array of var name lists */
- int *argcList = argcListArray; /* Array of value list sizes */
- Tcl_Obj ***argvList = argvListArray; /* Array of value lists */
-#ifdef TCL_TIP280
- Interp* iPtr = (Interp*) interp;
-#endif
+ int *index; /* Array of value list indices */
+ int *varcList; /* # loop variables per list */
+ Tcl_Obj ***varvList; /* Array of var name lists */
+ Tcl_Obj **vCopyList; /* Copies of var name list arguments */
+ int *argcList; /* Array of value list sizes */
+ Tcl_Obj ***argvList; /* Array of value lists */
+ Tcl_Obj **aCopyList; /* Copies of value list arguments */
if (objc < 4 || (objc%2 != 0)) {
Tcl_WrongNumArgs(interp, 1, objv,
@@ -1771,65 +1727,54 @@ Tcl_ForeachObjCmd(dummy, interp, objc, objv)
}
/*
- * Create the object argument array "argObjv". Make sure argObjv is
- * large enough to hold the objc arguments.
+ * Manage numList parallel value lists.
+ * argvList[i] is a value list counted by argcList[i]l;
+ * varvList[i] is the list of variables associated with the value list;
+ * varcList[i] is the number of variables associated with the value list;
+ * index[i] is the current pointer into the value list argvList[i].
*/
- if (objc > NUM_ARGS) {
- argObjv = (Tcl_Obj **) ckalloc(objc * sizeof(Tcl_Obj *));
- }
- for (i = 0; i < objc; i++) {
- argObjv[i] = objv[i];
- }
+ index = (int *) TclStackAlloc(interp, 3 * numLists * sizeof(int));
+ varcList = index + numLists;
+ argcList = varcList + numLists;
+ memset(index, 0, 3 * numLists * sizeof(int));
- /*
- * Manage numList parallel value lists.
- * argvList[i] is a value list counted by argcList[i]
- * varvList[i] is the list of variables associated with the value list
- * varcList[i] is the number of variables associated with the value list
- * index[i] is the current pointer into the value list argvList[i]
- */
+ varvList = (Tcl_Obj ***)
+ TclStackAlloc(interp, 2 * numLists * sizeof(Tcl_Obj **));
+ argvList = varvList + numLists;
+ memset(varvList, 0, 2 * numLists * sizeof(Tcl_Obj **));
- numLists = (objc-2)/2;
- if (numLists > STATIC_LIST_SIZE) {
- index = (int *) ckalloc(numLists * sizeof(int));
- varcList = (int *) ckalloc(numLists * sizeof(int));
- varvList = (Tcl_Obj ***) ckalloc(numLists * sizeof(Tcl_Obj **));
- argcList = (int *) ckalloc(numLists * sizeof(int));
- argvList = (Tcl_Obj ***) ckalloc(numLists * sizeof(Tcl_Obj **));
- }
- for (i = 0; i < numLists; i++) {
- index[i] = 0;
- varcList[i] = 0;
- varvList[i] = (Tcl_Obj **) NULL;
- argcList[i] = 0;
- argvList[i] = (Tcl_Obj **) NULL;
- }
+ vCopyList = (Tcl_Obj **)
+ TclStackAlloc(interp, 2 * numLists * sizeof(Tcl_Obj *));
+ aCopyList = vCopyList + numLists;
+ memset(vCopyList, 0, 2 * numLists * sizeof(Tcl_Obj *));
/*
- * Break up the value lists and variable lists into elements
+ * Break up the value lists and variable lists into elements.
*/
maxj = 0;
- for (i = 0; i < numLists; i++) {
- result = Tcl_ListObjGetElements(interp, argObjv[1+i*2],
- &varcList[i], &varvList[i]);
- if (result != TCL_OK) {
+ for (i=0 ; i<numLists ; i++) {
+
+ vCopyList[i] = TclListObjCopy(interp, objv[1+i*2]);
+ if (vCopyList[i] == NULL) {
+ result = TCL_ERROR;
goto done;
}
+ TclListObjGetElements(NULL, vCopyList[i], &varcList[i], &varvList[i]);
if (varcList[i] < 1) {
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "foreach varlist is empty", -1);
+ Tcl_AppendResult(interp, "foreach varlist is empty", NULL);
result = TCL_ERROR;
goto done;
}
-
- result = Tcl_ListObjGetElements(interp, argObjv[2+i*2],
- &argcList[i], &argvList[i]);
- if (result != TCL_OK) {
+
+ aCopyList[i] = TclListObjCopy(interp, objv[2+i*2]);
+ if (aCopyList[i] == NULL) {
+ result = TCL_ERROR;
goto done;
}
-
+ TclListObjGetElements(NULL, aCopyList[i], &argcList[i], &argvList[i]);
+
j = argcList[i] / varcList[i];
if ((argcList[i] % varcList[i]) != 0) {
j++;
@@ -1840,64 +1785,39 @@ Tcl_ForeachObjCmd(dummy, interp, objc, objv)
}
/*
- * Iterate maxj times through the lists in parallel
- * If some value lists run out of values, set loop vars to ""
+ * Iterate maxj times through the lists in parallel. If some value lists
+ * run out of values, set loop vars to ""
*/
-
- bodyPtr = argObjv[objc-1];
- for (j = 0; j < maxj; j++) {
- for (i = 0; i < numLists; i++) {
- /*
- * Refetch the list members; we assume that the sizes are
- * the same, but the array of elements might be different
- * if the internal rep of the objects has been lost and
- * recreated (it is too difficult to accurately tell when
- * this happens, which can lead to some wierd crashes,
- * like Bug #494348...)
- */
- result = Tcl_ListObjGetElements(interp, argObjv[1+i*2],
- &varcList[i], &varvList[i]);
- if (result != TCL_OK) {
- panic("Tcl_ForeachObjCmd: could not reconvert variable list %d to a list object\n", i);
- }
- result = Tcl_ListObjGetElements(interp, argObjv[2+i*2],
- &argcList[i], &argvList[i]);
- if (result != TCL_OK) {
- panic("Tcl_ForeachObjCmd: could not reconvert value list %d to a list object\n", i);
- }
-
- for (v = 0; v < varcList[i]; v++) {
+ bodyPtr = objv[objc-1];
+ for (j=0 ; j<maxj ; j++) {
+ for (i=0 ; i<numLists ; i++) {
+ for (v=0 ; v<varcList[i] ; v++) {
int k = index[i]++;
Tcl_Obj *valuePtr, *varValuePtr;
-
+
if (k < argcList[i]) {
valuePtr = argvList[i][k];
} else {
- valuePtr = Tcl_NewObj(); /* empty string */
+ valuePtr = Tcl_NewObj(); /* Empty string */
}
- Tcl_IncrRefCount(valuePtr);
- varValuePtr = Tcl_ObjSetVar2(interp, varvList[i][v],
- NULL, valuePtr, 0);
- Tcl_DecrRefCount(valuePtr);
+ varValuePtr = Tcl_ObjSetVar2(interp, varvList[i][v], NULL,
+ valuePtr, TCL_LEAVE_ERR_MSG);
if (varValuePtr == NULL) {
- Tcl_ResetResult(interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "couldn't set loop variable: \"",
- Tcl_GetString(varvList[i][v]), "\"", (char *) NULL);
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (setting foreach loop variable \"%s\")",
+ TclGetString(varvList[i][v])));
result = TCL_ERROR;
goto done;
}
-
}
}
-#ifndef TCL_TIP280
- result = Tcl_EvalObjEx(interp, bodyPtr, 0);
-#else
- /* TIP #280. Make invoking context available to loop body */
- result = TclEvalObjEx(interp, bodyPtr, 0, iPtr->cmdFramePtr,objc-1);
-#endif
+ /*
+ * TIP #280. Make invoking context available to loop body.
+ */
+
+ result = TclEvalObjEx(interp, bodyPtr, 0, iPtr->cmdFramePtr, objc-1);
if (result != TCL_OK) {
if (result == TCL_CONTINUE) {
result = TCL_OK;
@@ -1905,11 +1825,9 @@ Tcl_ForeachObjCmd(dummy, interp, objc, objv)
result = TCL_OK;
break;
} else if (result == TCL_ERROR) {
- char msg[32 + TCL_INTEGER_SPACE];
-
- sprintf(msg, "\n (\"foreach\" body line %d)",
- interp->errorLine);
- Tcl_AddObjErrorInfo(interp, msg, -1);
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (\"foreach\" body line %d)",
+ interp->errorLine));
break;
} else {
break;
@@ -1920,20 +1838,19 @@ Tcl_ForeachObjCmd(dummy, interp, objc, objv)
Tcl_ResetResult(interp);
}
- done:
- if (numLists > STATIC_LIST_SIZE) {
- ckfree((char *) index);
- ckfree((char *) varcList);
- ckfree((char *) argcList);
- ckfree((char *) varvList);
- ckfree((char *) argvList);
- }
- if (argObjv != argObjStorage) {
- ckfree((char *) argObjv);
+ done:
+ for (i=0 ; i<numLists ; i++) {
+ if (vCopyList[i]) {
+ Tcl_DecrRefCount(vCopyList[i]);
+ }
+ if (aCopyList[i]) {
+ Tcl_DecrRefCount(aCopyList[i]);
+ }
}
+ TclStackFree(interp, vCopyList); /* Tcl_Obj * arrays */
+ TclStackFree(interp, varvList); /* Tcl_Obj ** arrays */
+ TclStackFree(interp, index); /* int arrays */
return result;
-#undef STATIC_LIST_SIZE
-#undef NUM_ARGS
}
/*
@@ -1941,8 +1858,8 @@ Tcl_ForeachObjCmd(dummy, interp, objc, objv)
*
* Tcl_FormatObjCmd --
*
- * This procedure is invoked to process the "format" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "format" Tcl command. See
+ * the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -1955,493 +1872,25 @@ Tcl_ForeachObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_FormatObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_FormatObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
- char *format; /* Used to read characters from the format
- * string. */
- int formatLen; /* The length of the format string */
- char *endPtr; /* Points to the last char in format array */
- char newFormat[43]; /* A new format specifier is generated here. */
- int width; /* Field width from field specifier, or 0 if
- * no width given. */
- int precision; /* Field precision from field specifier, or 0
- * if no precision given. */
- int size; /* Number of bytes needed for result of
- * conversion, based on type of conversion
- * ("e", "s", etc.), width, and precision. */
- long intValue; /* Used to hold value to pass to sprintf, if
- * it's a one-word integer or char value */
- char *ptrValue = NULL; /* Used to hold value to pass to sprintf, if
- * it's a one-word value. */
- double doubleValue; /* Used to hold value to pass to sprintf if
- * it's a double value. */
- Tcl_WideInt wideValue; /* Used to hold value to pass to sprintf if
- * it's a 'long long' value. */
- int whichValue; /* Indicates which of intValue, ptrValue,
- * or doubleValue has the value to pass to
- * sprintf, according to the following
- * definitions: */
-# define INT_VALUE 0
-# define CHAR_VALUE 1
-# define PTR_VALUE 2
-# define DOUBLE_VALUE 3
-# define STRING_VALUE 4
-# define WIDE_VALUE 5
-# define MAX_FLOAT_SIZE 320
-
- Tcl_Obj *resultPtr; /* Where result is stored finally. */
- char staticBuf[MAX_FLOAT_SIZE + 1];
- /* A static buffer to copy the format results
- * into */
- char *dst = staticBuf; /* The buffer that sprintf writes into each
- * time the format processes a specifier */
- int dstSize = MAX_FLOAT_SIZE;
- /* The size of the dst buffer */
- int noPercent; /* Special case for speed: indicates there's
- * no field specifier, just a string to copy.*/
- int objIndex; /* Index of argument to substitute next. */
- int gotXpg = 0; /* Non-zero means that an XPG3 %n$-style
- * specifier has been seen. */
- int gotSequential = 0; /* Non-zero means that a regular sequential
- * (non-XPG3) conversion specifier has been
- * seen. */
- int useShort; /* Value to be printed is short (half word). */
- char *end; /* Used to locate end of numerical fields. */
- int stringLen = 0; /* Length of string in characters rather
- * than bytes. Used for %s substitution. */
- int gotMinus; /* Non-zero indicates that a minus flag has
- * been seen in the current field. */
- int gotPrecision; /* Non-zero indicates that a precision has
- * been set for the current field. */
- int gotZero; /* Non-zero indicates that a zero flag has
- * been seen in the current field. */
- int useWide; /* Value to be printed is Tcl_WideInt. */
-
- /*
- * This procedure is a bit nasty. The goal is to use sprintf to
- * do most of the dirty work. There are several problems:
- * 1. this procedure can't trust its arguments.
- * 2. we must be able to provide a large enough result area to hold
- * whatever's generated. This is hard to estimate.
- * 3. there's no way to move the arguments from objv to the call
- * to sprintf in a reasonable way. This is particularly nasty
- * because some of the arguments may be two-word values (doubles
- * and wide-ints).
- * So, what happens here is to scan the format string one % group
- * at a time, making many individual calls to sprintf.
- */
+ Tcl_Obj *resultPtr; /* Where result is stored finally. */
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "formatString ?arg arg ...?");
return TCL_ERROR;
}
- format = Tcl_GetStringFromObj(objv[1], &formatLen);
- endPtr = format + formatLen;
- resultPtr = Tcl_NewObj();
- objIndex = 2;
-
- while (format < endPtr) {
- register char *newPtr = newFormat;
-
- width = precision = noPercent = useShort = 0;
- gotZero = gotMinus = gotPrecision = 0;
- useWide = 0;
- whichValue = PTR_VALUE;
-
- /*
- * Get rid of any characters before the next field specifier.
- */
- if (*format != '%') {
- ptrValue = format;
- while ((*format != '%') && (format < endPtr)) {
- format++;
- }
- size = format - ptrValue;
- noPercent = 1;
- goto doField;
- }
-
- if (format[1] == '%') {
- ptrValue = format;
- size = 1;
- noPercent = 1;
- format += 2;
- goto doField;
- }
-
- /*
- * Parse off a field specifier, compute how many characters
- * will be needed to store the result, and substitute for
- * "*" size specifiers.
- */
- *newPtr = '%';
- newPtr++;
- format++;
- if (isdigit(UCHAR(*format))) { /* INTL: Tcl source. */
- int tmp;
-
- /*
- * Check for an XPG3-style %n$ specification. Note: there
- * must not be a mixture of XPG3 specs and non-XPG3 specs
- * in the same format string.
- */
-
- tmp = strtoul(format, &end, 10); /* INTL: "C" locale. */
- if (*end != '$') {
- goto notXpg;
- }
- format = end+1;
- gotXpg = 1;
- if (gotSequential) {
- goto mixedXPG;
- }
- objIndex = tmp+1;
- if ((objIndex < 2) || (objIndex >= objc)) {
- goto badIndex;
- }
- goto xpgCheckDone;
- }
-
- notXpg:
- gotSequential = 1;
- if (gotXpg) {
- goto mixedXPG;
- }
-
- xpgCheckDone:
- while ((*format == '-') || (*format == '#') || (*format == '0')
- || (*format == ' ') || (*format == '+')) {
- if (*format == '-') {
- gotMinus = 1;
- }
- if (*format == '0') {
- /*
- * This will be handled by sprintf for numbers, but we
- * need to do the char/string ones ourselves
- */
- gotZero = 1;
- }
- *newPtr = *format;
- newPtr++;
- format++;
- }
- if (isdigit(UCHAR(*format))) { /* INTL: Tcl source. */
- width = strtoul(format, &end, 10); /* INTL: Tcl source. */
- format = end;
- } else if (*format == '*') {
- if (objIndex >= objc) {
- goto badIndex;
- }
- if (Tcl_GetIntFromObj(interp, /* INTL: Tcl source. */
- objv[objIndex], &width) != TCL_OK) {
- goto fmtError;
- }
- if (width < 0) {
- width = -width;
- *newPtr = '-';
- gotMinus = 1;
- newPtr++;
- }
- objIndex++;
- format++;
- }
- if (width > 100000) {
- /*
- * Don't allow arbitrarily large widths: could cause core
- * dump when we try to allocate a zillion bytes of memory
- * below.
- */
-
- width = 100000;
- } else if (width < 0) {
- width = 0;
- }
- if (width != 0) {
- TclFormatInt(newPtr, width); /* INTL: printf format. */
- while (*newPtr != 0) {
- newPtr++;
- }
- }
- if (*format == '.') {
- *newPtr = '.';
- newPtr++;
- format++;
- gotPrecision = 1;
- }
- if (isdigit(UCHAR(*format))) { /* INTL: Tcl source. */
- precision = strtoul(format, &end, 10); /* INTL: "C" locale. */
- format = end;
- } else if (*format == '*') {
- if (objIndex >= objc) {
- goto badIndex;
- }
- if (Tcl_GetIntFromObj(interp, /* INTL: Tcl source. */
- objv[objIndex], &precision) != TCL_OK) {
- goto fmtError;
- }
- objIndex++;
- format++;
- }
- if (gotPrecision) {
- TclFormatInt(newPtr, precision); /* INTL: printf format. */
- while (*newPtr != 0) {
- newPtr++;
- }
- }
- if (*format == 'l') {
- useWide = 1;
- /*
- * Only add a 'll' modifier for integer values as it makes
- * some libc's go into spasm otherwise. [Bug #702622]
- */
- switch (format[1]) {
- case 'i':
- case 'd':
- case 'o':
- case 'u':
- case 'x':
- case 'X':
- strcpy(newPtr, TCL_LL_MODIFIER);
- newPtr += TCL_LL_MODIFIER_SIZE;
- }
- format++;
- } else if (*format == 'h') {
- useShort = 1;
- *newPtr = 'h';
- newPtr++;
- format++;
- }
- *newPtr = *format;
- newPtr++;
- *newPtr = 0;
- if (objIndex >= objc) {
- goto badIndex;
- }
- switch (*format) {
- case 'i':
- newPtr[-1] = 'd';
- case 'd':
- case 'o':
- case 'u':
- case 'x':
- case 'X':
- if (useWide) {
- if (Tcl_GetWideIntFromObj(interp, /* INTL: Tcl source. */
- objv[objIndex], &wideValue) != TCL_OK) {
- goto fmtError;
- }
- whichValue = WIDE_VALUE;
- size = 40 + precision;
- break;
- }
- if (Tcl_GetLongFromObj(interp, /* INTL: Tcl source. */
- objv[objIndex], &intValue) != TCL_OK) {
- if (Tcl_GetWideIntFromObj(interp, /* INTL: Tcl source. */
- objv[objIndex], &wideValue) != TCL_OK) {
- goto fmtError;
- }
- intValue = Tcl_WideAsLong(wideValue);
- }
-
-#if (LONG_MAX > INT_MAX)
- if (!useShort) {
- /*
- * Add the 'l' for long format type because we are on an
- * LP64 archtecture and we are really going to pass a long
- * argument to sprintf.
- *
- * Do not add this if we're going to pass in a short (i.e.
- * if we've got an 'h' modifier already in the string); some
- * libc implementations of sprintf() do not like it at all.
- * [Bug 1154163]
- */
- newPtr++;
- *newPtr = 0;
- newPtr[-1] = newPtr[-2];
- newPtr[-2] = 'l';
- }
-#endif /* LONG_MAX > INT_MAX */
- whichValue = INT_VALUE;
- size = 40 + precision;
- break;
- case 's':
- /*
- * Compute the length of the string in characters and add
- * any additional space required by the field width. All
- * of the extra characters will be spaces, so one byte per
- * character is adequate.
- */
-
- whichValue = STRING_VALUE;
- ptrValue = Tcl_GetStringFromObj(objv[objIndex], &size);
- stringLen = Tcl_NumUtfChars(ptrValue, size);
- if (gotPrecision && (precision < stringLen)) {
- stringLen = precision;
- }
- size = Tcl_UtfAtIndex(ptrValue, stringLen) - ptrValue;
- if (width > stringLen) {
- size += (width - stringLen);
- }
- break;
- case 'c':
- if (Tcl_GetLongFromObj(interp, /* INTL: Tcl source. */
- objv[objIndex], &intValue) != TCL_OK) {
- goto fmtError;
- }
- whichValue = CHAR_VALUE;
- size = width + TCL_UTF_MAX;
- break;
- case 'e':
- case 'E':
- case 'f':
- case 'g':
- case 'G':
- if (Tcl_GetDoubleFromObj(interp, /* INTL: Tcl source. */
- objv[objIndex], &doubleValue) != TCL_OK) {
- goto fmtError;
- }
- whichValue = DOUBLE_VALUE;
- size = MAX_FLOAT_SIZE;
- if (precision > 10) {
- size += precision;
- }
- break;
- case 0:
- Tcl_SetResult(interp,
- "format string ended in middle of field specifier",
- TCL_STATIC);
- goto fmtError;
- default:
- {
- char buf[40];
-
- sprintf(buf, "bad field specifier \"%c\"", *format);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
- goto fmtError;
- }
- }
- objIndex++;
- format++;
-
- /*
- * Make sure that there's enough space to hold the formatted
- * result, then format it.
- */
-
- doField:
- if (width > size) {
- size = width;
- }
- if (noPercent) {
- Tcl_AppendToObj(resultPtr, ptrValue, size);
- } else {
- if (size > dstSize) {
- if (dst != staticBuf) {
- ckfree(dst);
- }
- dst = (char *) ckalloc((unsigned) (size + 1));
- dstSize = size;
- }
- switch (whichValue) {
- case DOUBLE_VALUE:
- sprintf(dst, newFormat, doubleValue); /* INTL: user locale. */
- break;
- case WIDE_VALUE:
- sprintf(dst, newFormat, wideValue);
- break;
- case INT_VALUE:
- if (useShort) {
- sprintf(dst, newFormat, (short) intValue);
- } else {
- sprintf(dst, newFormat, intValue);
- }
- break;
- case CHAR_VALUE: {
- char *ptr;
- char padChar = (gotZero ? '0' : ' ');
- ptr = dst;
- if (!gotMinus) {
- for ( ; --width > 0; ptr++) {
- *ptr = padChar;
- }
- }
- ptr += Tcl_UniCharToUtf(intValue, ptr);
- for ( ; --width > 0; ptr++) {
- *ptr = padChar;
- }
- *ptr = '\0';
- break;
- }
- case STRING_VALUE: {
- char *ptr;
- char padChar = (gotZero ? '0' : ' ');
- int pad;
-
- ptr = dst;
- if (width > stringLen) {
- pad = width - stringLen;
- } else {
- pad = 0;
- }
-
- if (!gotMinus) {
- while (pad > 0) {
- *ptr++ = padChar;
- pad--;
- }
- }
-
- size = Tcl_UtfAtIndex(ptrValue, stringLen) - ptrValue;
- if (size) {
- memcpy(ptr, ptrValue, (size_t) size);
- ptr += size;
- }
- while (pad > 0) {
- *ptr++ = padChar;
- pad--;
- }
- *ptr = '\0';
- break;
- }
- default:
- sprintf(dst, newFormat, ptrValue);
- break;
- }
- Tcl_AppendToObj(resultPtr, dst, -1);
- }
+ resultPtr = Tcl_Format(interp, TclGetString(objv[1]), objc-2, objv+2);
+ if (resultPtr == NULL) {
+ return TCL_ERROR;
}
-
Tcl_SetObjResult(interp, resultPtr);
- if (dst != staticBuf) {
- ckfree(dst);
- }
return TCL_OK;
-
- mixedXPG:
- Tcl_SetResult(interp,
- "cannot mix \"%\" and \"%n$\" conversion specifiers", TCL_STATIC);
- goto fmtError;
-
- badIndex:
- if (gotXpg) {
- Tcl_SetResult(interp,
- "\"%n$\" argument index out of range", TCL_STATIC);
- } else {
- Tcl_SetResult(interp,
- "not enough arguments for all format specifiers", TCL_STATIC);
- }
-
- fmtError:
- if (dst != staticBuf) {
- ckfree(dst);
- }
- Tcl_DecrRefCount(resultPtr);
- return TCL_ERROR;
}
/*
@@ -2451,4 +1900,3 @@ Tcl_FormatObjCmd(dummy, interp, objc, objv)
* fill-column: 78
* End:
*/
-
diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c
index 21dbdc8..13db6d5 100644
--- a/generic/tclCmdIL.c
+++ b/generic/tclCmdIL.c
@@ -1,62 +1,80 @@
-/*
+/*
* tclCmdIL.c --
*
- * This file contains the top-level command routines for most of
- * the Tcl built-in commands whose names begin with the letters
- * I through L. It contains only commands in the generic core
- * (i.e. those that don't depend much upon UNIX facilities).
+ * This file contains the top-level command routines for most of the Tcl
+ * built-in commands whose names begin with the letters I through L. It
+ * contains only commands in the generic core (i.e. those that don't
+ * depend much upon UNIX facilities).
*
* Copyright (c) 1987-1993 The Regents of the University of California.
* Copyright (c) 1993-1997 Lucent Technologies.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
* Copyright (c) 1998-1999 by Scriptics Corporation.
- * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
+ * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
+ * Copyright (c) 2005 Donal K. Fellows.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
#include "tclRegexp.h"
/*
- * During execution of the "lsort" command, structures of the following
- * type are used to arrange the objects being sorted into a collection
- * of linked lists.
+ * During execution of the "lsort" command, structures of the following type
+ * are used to arrange the objects being sorted into a collection of linked
+ * lists.
*/
typedef struct SortElement {
- Tcl_Obj *objPtr; /* Object being sorted. */
- int count; /* number of same elements in list */
- struct SortElement *nextPtr; /* Next element in the list, or
- * NULL for end of list. */
+ union {
+ char *strValuePtr;
+ long intValue;
+ double doubleValue;
+ Tcl_Obj *objValuePtr;
+ } index;
+ Tcl_Obj *objPtr; /* Object being sorted, or its index. */
+ struct SortElement *nextPtr;/* Next element in the list, or NULL for end
+ * of list. */
} SortElement;
/*
- * The "lsort" command needs to pass certain information down to the
- * function that compares two list elements, and the comparison function
- * needs to pass success or failure information back up to the top-level
- * "lsort" command. The following structure is used to pass this
- * information.
+ * These function pointer types are used with the "lsearch" and "lsort"
+ * commands to facilitate the "-nocase" option.
+ */
+
+typedef int (*SortStrCmpFn_t) (const char *, const char *);
+typedef int (*SortMemCmpFn_t) (const void *, const void *, size_t);
+
+/*
+ * The "lsort" command needs to pass certain information down to the function
+ * that compares two list elements, and the comparison function needs to pass
+ * success or failure information back up to the top-level "lsort" command.
+ * The following structure is used to pass this information.
*/
typedef struct SortInfo {
int isIncreasing; /* Nonzero means sort in increasing order. */
- int sortMode; /* The sort mode. One of SORTMODE_*
- * values defined below */
- Tcl_Obj *compareCmdPtr; /* The Tcl comparison command when sortMode
- * is SORTMODE_COMMAND. Pre-initialized to
- * hold base of command.*/
- int index; /* If the -index option was specified, this
- * holds the index of the list element
- * to extract for comparison. If -index
- * wasn't specified, this is -1. */
- Tcl_Interp *interp; /* The interpreter in which the sortis
- * being done. */
- int resultCode; /* Completion code for the lsort command.
- * If an error occurs during the sort this
- * is changed from TCL_OK to TCL_ERROR. */
+ int sortMode; /* The sort mode. One of SORTMODE_* values
+ * defined below. */
+ Tcl_Obj *compareCmdPtr; /* The Tcl comparison command when sortMode is
+ * SORTMODE_COMMAND. Pre-initialized to hold
+ * base of command. */
+ int *indexv; /* If the -index option was specified, this
+ * holds the indexes contained in the list
+ * supplied as an argument to that option.
+ * NULL if no indexes supplied, and points to
+ * singleIndex field when only one
+ * supplied. */
+ int indexc; /* Number of indexes in indexv array. */
+ int singleIndex; /* Static space for common index case. */
+ int unique;
+ int numElements;
+ Tcl_Interp *interp; /* The interpreter in which the sort is being
+ * done. */
+ int resultCode; /* Completion code for the lsort command. If
+ * an error occurs during the sort this is
+ * changed from TCL_OK to TCL_ERROR. */
} SortInfo;
/*
@@ -64,115 +82,113 @@ typedef struct SortInfo {
* following values.
*/
-#define SORTMODE_ASCII 0
-#define SORTMODE_INTEGER 1
-#define SORTMODE_REAL 2
-#define SORTMODE_COMMAND 3
-#define SORTMODE_DICTIONARY 4
+#define SORTMODE_ASCII 0
+#define SORTMODE_INTEGER 1
+#define SORTMODE_REAL 2
+#define SORTMODE_COMMAND 3
+#define SORTMODE_DICTIONARY 4
+#define SORTMODE_ASCII_NC 8
/*
- * Magic values for the index field of the SortInfo structure.
- * Note that the index "end-1" will be translated to SORTIDX_END-1, etc.
+ * Magic values for the index field of the SortInfo structure. Note that the
+ * index "end-1" will be translated to SORTIDX_END-1, etc.
*/
-#define SORTIDX_NONE -1 /* Not indexed; use whole value. */
-#define SORTIDX_END -2 /* Indexed from end. */
+
+#define SORTIDX_NONE -1 /* Not indexed; use whole value. */
+#define SORTIDX_END -2 /* Indexed from end. */
/*
* Forward declarations for procedures defined in this file:
*/
-static void AppendLocals _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *listPtr, CONST char *pattern,
- int includeLinks));
-static int DictionaryCompare _ANSI_ARGS_((char *left,
- char *right));
-static int InfoArgsCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int InfoBodyCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int InfoCmdCountCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int InfoCommandsCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int InfoCompleteCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int InfoDefaultCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int InfoExistsCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-#ifdef TCL_TIP280
+static int DictionaryCompare(char *left, char *right);
+static int InfoArgsCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[]);
+static int InfoBodyCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[]);
+static int InfoCmdCountCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[]);
+static int InfoCommandsCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[]);
+static int InfoCompleteCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[]);
+static int InfoDefaultCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[]);
/* TIP #280 - New 'info' subcommand 'frame' */
-static int InfoFrameCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-#endif
-static int InfoFunctionsCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int InfoGlobalsCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int InfoHostnameCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int InfoLevelCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int InfoLibraryCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int InfoLoadedCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int InfoLocalsCmd _ANSI_ARGS_((ClientData dummy,
+static int InfoFrameCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[]);
+static int InfoFunctionsCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[]);
+static int InfoHostnameCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[]);
+static int InfoLevelCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[]);
+static int InfoLibraryCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[]);
+static int InfoLoadedCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[]);
+static int InfoNameOfExecutableCmd(ClientData dummy,
Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int InfoNameOfExecutableCmd _ANSI_ARGS_((
- ClientData dummy, Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int InfoPatchLevelCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int InfoProcsCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int InfoScriptCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int InfoSharedlibCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int InfoTclVersionCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int InfoVarsCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static SortElement * MergeSort _ANSI_ARGS_((SortElement *headPt,
- SortInfo *infoPtr));
-static SortElement * MergeLists _ANSI_ARGS_((SortElement *leftPtr,
- SortElement *rightPtr, SortInfo *infoPtr));
-static int SortCompare _ANSI_ARGS_((Tcl_Obj *firstPtr,
- Tcl_Obj *second, SortInfo *infoPtr));
+ Tcl_Obj *CONST objv[]);
+static int InfoPatchLevelCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[]);
+static int InfoProcsCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[]);
+static int InfoScriptCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[]);
+static int InfoSharedlibCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[]);
+static int InfoTclVersionCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[]);
+static SortElement * MergeLists(SortElement *leftPtr, SortElement *rightPtr,
+ SortInfo *infoPtr);
+static int SortCompare(SortElement *firstPtr, SortElement *second,
+ SortInfo *infoPtr);
+static Tcl_Obj * SelectObjFromSublist(Tcl_Obj *firstPtr,
+ SortInfo *infoPtr);
+
+/*
+ * Array of values describing how to implement each standard subcommand of the
+ * "info" command.
+ */
+
+static const EnsembleImplMap defaultInfoMap[] = {
+ {"args", InfoArgsCmd, NULL},
+ {"body", InfoBodyCmd, NULL},
+ {"cmdcount", InfoCmdCountCmd, NULL},
+ {"commands", InfoCommandsCmd, NULL},
+ {"complete", InfoCompleteCmd, NULL},
+ {"default", InfoDefaultCmd, NULL},
+ {"exists", TclInfoExistsCmd, TclCompileInfoExistsCmd},
+ {"frame", InfoFrameCmd, NULL},
+ {"functions", InfoFunctionsCmd, NULL},
+ {"globals", TclInfoGlobalsCmd, NULL},
+ {"hostname", InfoHostnameCmd, NULL},
+ {"level", InfoLevelCmd, NULL},
+ {"library", InfoLibraryCmd, NULL},
+ {"loaded", InfoLoadedCmd, NULL},
+ {"locals", TclInfoLocalsCmd, NULL},
+ {"nameofexecutable", InfoNameOfExecutableCmd, NULL},
+ {"patchlevel", InfoPatchLevelCmd, NULL},
+ {"procs", InfoProcsCmd, NULL},
+ {"script", InfoScriptCmd, NULL},
+ {"sharedlibextension", InfoSharedlibCmd, NULL},
+ {"tclversion", InfoTclVersionCmd, NULL},
+ {"vars", TclInfoVarsCmd, NULL},
+ {NULL, NULL, NULL}
+};
/*
*----------------------------------------------------------------------
*
* Tcl_IfObjCmd --
*
- * This procedure is invoked to process the "if" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "if" Tcl command. See the
+ * user documentation for details on what it does.
*
- * With the bytecode compiler, this procedure is only called when
- * a command name is computed at runtime, and is "if" or the name
- * to which "if" was renamed: e.g., "set z if; $z 1 {puts foo}"
+ * With the bytecode compiler, this procedure is only called when a
+ * command name is computed at runtime, and is "if" or the name to which
+ * "if" was renamed: e.g., "set z if; $z 1 {puts foo}"
*
* Results:
* A standard Tcl result.
@@ -183,34 +199,32 @@ static int SortCompare _ANSI_ARGS_((Tcl_Obj *firstPtr,
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
int
-Tcl_IfObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_IfObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
- int thenScriptIndex = 0; /* then script to be evaled after syntax check */
-#ifdef TCL_TIP280
- Interp* iPtr = (Interp*) interp;
-#endif
+ int thenScriptIndex = 0; /* "then" script to be evaled after syntax
+ * check. */
+ Interp *iPtr = (Interp *) interp;
int i, result, value;
char *clause;
+
i = 1;
while (1) {
/*
- * At this point in the loop, objv and objc refer to an expression
- * to test, either for the main expression or an expression
- * following an "elseif". The arguments after the expression must
- * be "then" (optional) and a script to execute if the expression is
- * true.
+ * At this point in the loop, objv and objc refer to an expression to
+ * test, either for the main expression or an expression following an
+ * "elseif". The arguments after the expression must be "then"
+ * (optional) and a script to execute if the expression is true.
*/
if (i >= objc) {
- clause = Tcl_GetString(objv[i-1]);
- Tcl_AppendResult(interp, "wrong # args: no expression after \"",
- clause, "\" argument", (char *) NULL);
+ clause = TclGetString(objv[i-1]);
+ Tcl_AppendResult(interp, "wrong # args: ",
+ "no expression after \"", clause, "\" argument", NULL);
return TCL_ERROR;
}
if (!thenScriptIndex) {
@@ -221,13 +235,13 @@ Tcl_IfObjCmd(dummy, interp, objc, objv)
}
i++;
if (i >= objc) {
- missingScript:
- clause = Tcl_GetString(objv[i-1]);
- Tcl_AppendResult(interp, "wrong # args: no script following \"",
- clause, "\" argument", (char *) NULL);
+ missingScript:
+ clause = TclGetString(objv[i-1]);
+ Tcl_AppendResult(interp, "wrong # args: ",
+ "no script following \"", clause, "\" argument", NULL);
return TCL_ERROR;
}
- clause = Tcl_GetString(objv[i]);
+ clause = TclGetString(objv[i]);
if ((i < objc) && (strcmp(clause, "then") == 0)) {
i++;
}
@@ -238,26 +252,25 @@ Tcl_IfObjCmd(dummy, interp, objc, objv)
thenScriptIndex = i;
value = 0;
}
-
+
/*
- * The expression evaluated to false. Skip the command, then
- * see if there is an "else" or "elseif" clause.
+ * The expression evaluated to false. Skip the command, then see if
+ * there is an "else" or "elseif" clause.
*/
i++;
if (i >= objc) {
if (thenScriptIndex) {
-#ifndef TCL_TIP280
- return Tcl_EvalObjEx(interp, objv[thenScriptIndex], 0);
-#else
- /* TIP #280. Make invoking context available to branch */
+ /*
+ * TIP #280. Make invoking context available to branch.
+ */
+
return TclEvalObjEx(interp, objv[thenScriptIndex], 0,
- iPtr->cmdFramePtr,thenScriptIndex);
-#endif
+ iPtr->cmdFramePtr, thenScriptIndex);
}
return TCL_OK;
}
- clause = Tcl_GetString(objv[i]);
+ clause = TclGetString(objv[i]);
if ((clause[0] == 'e') && (strcmp(clause, "elseif") == 0)) {
i++;
continue;
@@ -266,40 +279,33 @@ Tcl_IfObjCmd(dummy, interp, objc, objv)
}
/*
- * Couldn't find a "then" or "elseif" clause to execute. Check now
- * for an "else" clause. We know that there's at least one more
- * argument when we get here.
+ * Couldn't find a "then" or "elseif" clause to execute. Check now for an
+ * "else" clause. We know that there's at least one more argument when we
+ * get here.
*/
if (strcmp(clause, "else") == 0) {
i++;
if (i >= objc) {
- Tcl_AppendResult(interp,
- "wrong # args: no script following \"else\" argument",
- (char *) NULL);
+ Tcl_AppendResult(interp, "wrong # args: ",
+ "no script following \"else\" argument", NULL);
return TCL_ERROR;
}
}
if (i < objc - 1) {
- Tcl_AppendResult(interp,
- "wrong # args: extra words after \"else\" clause in \"if\" command",
- (char *) NULL);
+ Tcl_AppendResult(interp, "wrong # args: ",
+ "extra words after \"else\" clause in \"if\" command", NULL);
return TCL_ERROR;
}
if (thenScriptIndex) {
-#ifndef TCL_TIP280
- return Tcl_EvalObjEx(interp, objv[thenScriptIndex], 0);
-#else
- /* TIP #280. Make invoking context available to branch/else */
+ /*
+ * TIP #280. Make invoking context available to branch/else.
+ */
+
return TclEvalObjEx(interp, objv[thenScriptIndex], 0,
- iPtr->cmdFramePtr,thenScriptIndex);
-#endif
+ iPtr->cmdFramePtr, thenScriptIndex);
}
-#ifndef TCL_TIP280
- return Tcl_EvalObjEx(interp, objv[i], 0);
-#else
- return TclEvalObjEx(interp, objv[i], 0, iPtr->cmdFramePtr,i);
-#endif
+ return TclEvalObjEx(interp, objv[i], 0, iPtr->cmdFramePtr, i);
}
/*
@@ -307,12 +313,12 @@ Tcl_IfObjCmd(dummy, interp, objc, objv)
*
* Tcl_IncrObjCmd --
*
- * This procedure is invoked to process the "incr" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "incr" Tcl command. See the
+ * user documentation for details on what it does.
*
- * With the bytecode compiler, this procedure is only called when
- * a command name is computed at runtime, and is "incr" or the name
- * to which "incr" was renamed: e.g., "set z incr; $z i -1"
+ * With the bytecode compiler, this procedure is only called when a
+ * command name is computed at runtime, and is "incr" or the name to
+ * which "incr" was renamed: e.g., "set z incr; $z i -1"
*
* Results:
* A standard Tcl result.
@@ -323,64 +329,30 @@ Tcl_IfObjCmd(dummy, interp, objc, objv)
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
int
-Tcl_IncrObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_IncrObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
- long incrAmount;
- Tcl_Obj *newValuePtr;
-
+ Tcl_Obj *newValuePtr, *incrPtr;
+
if ((objc != 2) && (objc != 3)) {
- Tcl_WrongNumArgs(interp, 1, objv, "varName ?increment?");
+ Tcl_WrongNumArgs(interp, 1, objv, "varName ?increment?");
return TCL_ERROR;
}
- /*
- * Calculate the amount to increment by.
- */
-
- if (objc == 2) {
- incrAmount = 1;
+ if (objc == 3) {
+ incrPtr = objv[2];
} else {
- if (Tcl_GetLongFromObj(interp, objv[2], &incrAmount) != TCL_OK) {
- Tcl_AddErrorInfo(interp, "\n (reading increment)");
- return TCL_ERROR;
- }
- /*
- * Need to be a bit cautious to ensure that [expr]-like rules
- * are enforced for interpretation of wide integers, despite
- * the fact that the underlying API itself is a 'long' only one.
- */
- if (objv[2]->typePtr == &tclIntType) {
- incrAmount = objv[2]->internalRep.longValue;
- } else if (objv[2]->typePtr == &tclWideIntType) {
- TclGetLongFromWide(incrAmount,objv[2]);
- } else {
- Tcl_WideInt wide;
-
- if (Tcl_GetWideIntFromObj(interp, objv[2], &wide) != TCL_OK) {
- Tcl_AddErrorInfo(interp, "\n (reading increment)");
- return TCL_ERROR;
- }
- incrAmount = Tcl_WideAsLong(wide);
- if ((wide <= Tcl_LongAsWide(LONG_MAX))
- && (wide >= Tcl_LongAsWide(LONG_MIN))) {
- objv[2]->typePtr = &tclIntType;
- objv[2]->internalRep.longValue = incrAmount;
- }
- }
+ incrPtr = Tcl_NewIntObj(1);
}
-
- /*
- * Increment the variable's value.
- */
+ Tcl_IncrRefCount(incrPtr);
+ newValuePtr = TclIncrObjVar2(interp, objv[1], NULL,
+ incrPtr, TCL_LEAVE_ERR_MSG);
+ Tcl_DecrRefCount(incrPtr);
- newValuePtr = TclIncrVar2(interp, objv[1], (Tcl_Obj *) NULL, incrAmount,
- TCL_LEAVE_ERR_MSG);
if (newValuePtr == NULL) {
return TCL_ERROR;
}
@@ -391,141 +363,31 @@ Tcl_IncrObjCmd(dummy, interp, objc, objv)
*/
Tcl_SetObjResult(interp, newValuePtr);
- return TCL_OK;
+ return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * Tcl_InfoObjCmd --
+ * TclInitInfoCmd --
*
- * This procedure is invoked to process the "info" Tcl command.
- * See the user documentation for details on what it does.
+ * This function is called to create the "info" Tcl command. See the user
+ * documentation for details on what it does.
*
* Results:
- * A standard Tcl result.
+ * FIXME
*
* Side effects:
- * See the user documentation.
+ * none
*
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
-int
-Tcl_InfoObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Arbitrary value passed to the command. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_Command
+TclInitInfoCmd(
+ Tcl_Interp *interp) /* Current interpreter. */
{
- static CONST char *subCmds[] = {
- "args", "body", "cmdcount", "commands",
- "complete", "default", "exists",
-#ifdef TCL_TIP280
- "frame",
-#endif
- "functions",
- "globals", "hostname", "level", "library", "loaded",
- "locals", "nameofexecutable", "patchlevel", "procs",
- "script", "sharedlibextension", "tclversion", "vars",
- (char *) NULL};
- enum ISubCmdIdx {
- IArgsIdx, IBodyIdx, ICmdCountIdx, ICommandsIdx,
- ICompleteIdx, IDefaultIdx, IExistsIdx,
-#ifdef TCL_TIP280
- IFrameIdx,
-#endif
- IFunctionsIdx,
- IGlobalsIdx, IHostnameIdx, ILevelIdx, ILibraryIdx, ILoadedIdx,
- ILocalsIdx, INameOfExecutableIdx, IPatchLevelIdx, IProcsIdx,
- IScriptIdx, ISharedLibExtensionIdx, ITclVersionIdx, IVarsIdx
- };
- int index, result;
-
- if (objc < 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
- return TCL_ERROR;
- }
-
- result = Tcl_GetIndexFromObj(interp, objv[1], subCmds, "option", 0,
- (int *) &index);
- if (result != TCL_OK) {
- return result;
- }
-
- switch (index) {
- case IArgsIdx:
- result = InfoArgsCmd(clientData, interp, objc, objv);
- break;
- case IBodyIdx:
- result = InfoBodyCmd(clientData, interp, objc, objv);
- break;
- case ICmdCountIdx:
- result = InfoCmdCountCmd(clientData, interp, objc, objv);
- break;
- case ICommandsIdx:
- result = InfoCommandsCmd(clientData, interp, objc, objv);
- break;
- case ICompleteIdx:
- result = InfoCompleteCmd(clientData, interp, objc, objv);
- break;
- case IDefaultIdx:
- result = InfoDefaultCmd(clientData, interp, objc, objv);
- break;
- case IExistsIdx:
- result = InfoExistsCmd(clientData, interp, objc, objv);
- break;
-#ifdef TCL_TIP280
- case IFrameIdx:
- /* TIP #280 - New method 'frame' */
- result = InfoFrameCmd(clientData, interp, objc, objv);
- break;
-#endif
- case IFunctionsIdx:
- result = InfoFunctionsCmd(clientData, interp, objc, objv);
- break;
- case IGlobalsIdx:
- result = InfoGlobalsCmd(clientData, interp, objc, objv);
- break;
- case IHostnameIdx:
- result = InfoHostnameCmd(clientData, interp, objc, objv);
- break;
- case ILevelIdx:
- result = InfoLevelCmd(clientData, interp, objc, objv);
- break;
- case ILibraryIdx:
- result = InfoLibraryCmd(clientData, interp, objc, objv);
- break;
- case ILoadedIdx:
- result = InfoLoadedCmd(clientData, interp, objc, objv);
- break;
- case ILocalsIdx:
- result = InfoLocalsCmd(clientData, interp, objc, objv);
- break;
- case INameOfExecutableIdx:
- result = InfoNameOfExecutableCmd(clientData, interp, objc, objv);
- break;
- case IPatchLevelIdx:
- result = InfoPatchLevelCmd(clientData, interp, objc, objv);
- break;
- case IProcsIdx:
- result = InfoProcsCmd(clientData, interp, objc, objv);
- break;
- case IScriptIdx:
- result = InfoScriptCmd(clientData, interp, objc, objv);
- break;
- case ISharedLibExtensionIdx:
- result = InfoSharedlibCmd(clientData, interp, objc, objv);
- break;
- case ITclVersionIdx:
- result = InfoTclVersionCmd(clientData, interp, objc, objv);
- break;
- case IVarsIdx:
- result = InfoVarsCmd(clientData, interp, objc, objv);
- break;
- }
- return result;
+ return TclMakeEnsemble(interp, "info", defaultInfoMap);
}
/*
@@ -533,27 +395,27 @@ Tcl_InfoObjCmd(clientData, interp, objc, objv)
*
* InfoArgsCmd --
*
- * Called to implement the "info args" command that returns the
- * argument list for a procedure. Handles the following syntax:
+ * Called to implement the "info args" command that returns the argument
+ * list for a procedure. Handles the following syntax:
*
- * info args procName
+ * info args procName
*
* Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
*
* Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-InfoArgsCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+InfoArgsCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
register Interp *iPtr = (Interp *) interp;
char *name;
@@ -561,30 +423,29 @@ InfoArgsCmd(dummy, interp, objc, objv)
CompiledLocal *localPtr;
Tcl_Obj *listObjPtr;
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "procname");
- return TCL_ERROR;
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "procname");
+ return TCL_ERROR;
}
- name = Tcl_GetString(objv[2]);
+ name = TclGetString(objv[1]);
procPtr = TclFindProc(iPtr, name);
if (procPtr == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "\"", name, "\" isn't a procedure", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "\"", name, "\" isn't a procedure", NULL);
+ return TCL_ERROR;
}
/*
* Build a return list containing the arguments.
*/
-
- listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+
+ listObjPtr = Tcl_NewListObj(0, NULL);
for (localPtr = procPtr->firstLocalPtr; localPtr != NULL;
- localPtr = localPtr->nextPtr) {
- if (TclIsVarArgument(localPtr)) {
- Tcl_ListObjAppendElement(interp, listObjPtr,
+ localPtr = localPtr->nextPtr) {
+ if (TclIsVarArgument(localPtr)) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
Tcl_NewStringObj(localPtr->name, -1));
- }
+ }
}
Tcl_SetObjResult(interp, listObjPtr);
return TCL_OK;
@@ -595,65 +456,65 @@ InfoArgsCmd(dummy, interp, objc, objv)
*
* InfoBodyCmd --
*
- * Called to implement the "info body" command that returns the body
- * for a procedure. Handles the following syntax:
+ * Called to implement the "info body" command that returns the body for
+ * a procedure. Handles the following syntax:
*
- * info body procName
+ * info body procName
*
* Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
*
* Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-InfoBodyCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+InfoBodyCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
register Interp *iPtr = (Interp *) interp;
char *name;
Proc *procPtr;
Tcl_Obj *bodyPtr, *resultPtr;
-
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "procname");
- return TCL_ERROR;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "procname");
+ return TCL_ERROR;
}
- name = Tcl_GetString(objv[2]);
+ name = TclGetString(objv[1]);
procPtr = TclFindProc(iPtr, name);
if (procPtr == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "\"", name, "\" isn't a procedure", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "\"", name, "\" isn't a procedure", NULL);
+ return TCL_ERROR;
}
- /*
+ /*
* Here we used to return procPtr->bodyPtr, except when the body was
- * bytecompiled - in that case, the return was a copy of the body's
- * string rep. In order to better isolate the implementation details
- * of the compiler/engine subsystem, we now always return a copy of
- * the string rep. It is important to return a copy so that later
- * manipulations of the object do not invalidate the internal rep.
+ * bytecompiled - in that case, the return was a copy of the body's string
+ * rep. In order to better isolate the implementation details of the
+ * compiler/engine subsystem, we now always return a copy of the string
+ * rep. It is important to return a copy so that later manipulations of
+ * the object do not invalidate the internal rep.
*/
bodyPtr = procPtr->bodyPtr;
if (bodyPtr->bytes == NULL) {
/*
- * The string rep might not be valid if the procedure has
- * never been run before. [Bug #545644]
+ * The string rep might not be valid if the procedure has never been
+ * run before. [Bug #545644]
*/
- (void) Tcl_GetString(bodyPtr);
+
+ (void) TclGetString(bodyPtr);
}
resultPtr = Tcl_NewStringObj(bodyPtr->bytes, bodyPtr->length);
-
+
Tcl_SetObjResult(interp, resultPtr);
return TCL_OK;
}
@@ -663,37 +524,37 @@ InfoBodyCmd(dummy, interp, objc, objv)
*
* InfoCmdCountCmd --
*
- * Called to implement the "info cmdcount" command that returns the
- * number of commands that have been executed. Handles the following
- * syntax:
+ * Called to implement the "info cmdcount" command that returns the
+ * number of commands that have been executed. Handles the following
+ * syntax:
*
- * info cmdcount
+ * info cmdcount
*
* Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
*
* Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-InfoCmdCountCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+InfoCmdCountCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
Interp *iPtr = (Interp *) interp;
-
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- return TCL_ERROR;
+
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, NULL);
+ return TCL_ERROR;
}
- Tcl_SetIntObj(Tcl_GetObjResult(interp), iPtr->cmdCount);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(iPtr->cmdCount));
return TCL_OK;
}
@@ -702,31 +563,31 @@ InfoCmdCountCmd(dummy, interp, objc, objv)
*
* InfoCommandsCmd --
*
- * Called to implement the "info commands" command that returns the
- * list of commands in the interpreter that match an optional pattern.
- * The pattern, if any, consists of an optional sequence of namespace
- * names separated by "::" qualifiers, which is followed by a
- * glob-style pattern that restricts which commands are returned.
- * Handles the following syntax:
+ * Called to implement the "info commands" command that returns the list
+ * of commands in the interpreter that match an optional pattern. The
+ * pattern, if any, consists of an optional sequence of namespace names
+ * separated by "::" qualifiers, which is followed by a glob-style
+ * pattern that restricts which commands are returned. Handles the
+ * following syntax:
*
- * info commands ?pattern?
+ * info commands ?pattern?
*
* Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
*
* Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-InfoCommandsCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+InfoCommandsCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
char *cmdName, *pattern;
CONST char *simplePattern;
@@ -734,42 +595,42 @@ InfoCommandsCmd(dummy, interp, objc, objv)
Tcl_HashSearch search;
Namespace *nsPtr;
Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
- Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+ Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
Tcl_Obj *listPtr, *elemObjPtr;
- int specificNsInPattern = 0; /* Init. to avoid compiler warning. */
+ int specificNsInPattern = 0;/* Init. to avoid compiler warning. */
Tcl_Command cmd;
+ int i;
/*
- * Get the pattern and find the "effective namespace" in which to
- * list commands.
+ * Get the pattern and find the "effective namespace" in which to list
+ * commands.
*/
- if (objc == 2) {
- simplePattern = NULL;
+ if (objc == 1) {
+ simplePattern = NULL;
nsPtr = currNsPtr;
specificNsInPattern = 0;
- } else if (objc == 3) {
+ } else if (objc == 2) {
/*
* From the pattern, get the effective namespace and the simple
- * pattern (no namespace qualifiers or ::'s) at the end. If an
- * error was found while parsing the pattern, return it. Otherwise,
- * if the namespace wasn't found, just leave nsPtr NULL: we will
- * return an empty list since no commands there can be found.
+ * pattern (no namespace qualifiers or ::'s) at the end. If an error
+ * was found while parsing the pattern, return it. Otherwise, if the
+ * namespace wasn't found, just leave nsPtr NULL: we will return an
+ * empty list since no commands there can be found.
*/
Namespace *dummy1NsPtr, *dummy2NsPtr;
-
- pattern = Tcl_GetString(objv[2]);
- TclGetNamespaceForQualName(interp, pattern, (Namespace *) NULL,
- /*flags*/ 0, &nsPtr, &dummy1NsPtr, &dummy2NsPtr, &simplePattern);
+ pattern = TclGetString(objv[1]);
+ TclGetNamespaceForQualName(interp, pattern, (Namespace *) NULL, 0,
+ &nsPtr, &dummy1NsPtr, &dummy2NsPtr, &simplePattern);
- if (nsPtr != NULL) { /* we successfully found the pattern's ns */
+ if (nsPtr != NULL) { /* We successfully found the pattern's ns. */
specificNsInPattern = (strcmp(simplePattern, pattern) != 0);
}
} else {
- Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
- return TCL_ERROR;
+ Tcl_WrongNumArgs(interp, 1, objv, "?pattern?");
+ return TCL_ERROR;
}
/*
@@ -781,20 +642,20 @@ InfoCommandsCmd(dummy, interp, objc, objv)
}
/*
- * Scan through the effective namespace's command table and create a
- * list with all commands that match the pattern. If a specific
- * namespace was requested in the pattern, qualify the command names
- * with the namespace name.
+ * Scan through the effective namespace's command table and create a list
+ * with all commands that match the pattern. If a specific namespace was
+ * requested in the pattern, qualify the command names with the namespace
+ * name.
*/
- listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+ listPtr = Tcl_NewListObj(0, NULL);
if (simplePattern != NULL && TclMatchIsTrivial(simplePattern)) {
/*
- * Special case for when the pattern doesn't include any of
- * glob's special characters. This lets us avoid scans of any
- * hash tables.
+ * Special case for when the pattern doesn't include any of glob's
+ * special characters. This lets us avoid scans of any hash tables.
*/
+
entryPtr = Tcl_FindHashEntry(&nsPtr->cmdTable, simplePattern);
if (entryPtr != NULL) {
if (specificNsInPattern) {
@@ -806,21 +667,48 @@ InfoCommandsCmd(dummy, interp, objc, objv)
elemObjPtr = Tcl_NewStringObj(cmdName, -1);
}
Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
- } else if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
- entryPtr = Tcl_FindHashEntry(&globalNsPtr->cmdTable,
- simplePattern);
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+ }
+ if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
+ Tcl_HashTable *tablePtr = NULL; /* Quell warning. */
+
+ for (i=0 ; i<nsPtr->commandPathLength ; i++) {
+ Namespace *pathNsPtr = nsPtr->commandPathArray[i].nsPtr;
+
+ if (pathNsPtr == NULL) {
+ continue;
+ }
+ tablePtr = &pathNsPtr->cmdTable;
+ entryPtr = Tcl_FindHashEntry(tablePtr, simplePattern);
+ if (entryPtr != NULL) {
+ break;
+ }
+ }
+ if (entryPtr == NULL) {
+ tablePtr = &globalNsPtr->cmdTable;
+ entryPtr = Tcl_FindHashEntry(tablePtr, simplePattern);
+ }
if (entryPtr != NULL) {
- cmdName = Tcl_GetHashKey(&globalNsPtr->cmdTable, entryPtr);
+ cmdName = Tcl_GetHashKey(tablePtr, entryPtr);
Tcl_ListObjAppendElement(interp, listPtr,
Tcl_NewStringObj(cmdName, -1));
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
}
}
- } else {
+ } else if (nsPtr->commandPathLength == 0 || specificNsInPattern) {
+ /*
+ * The pattern is non-trivial, but either there is no explicit path or
+ * there is an explicit namespace in the pattern. In both cases, the
+ * old matching scheme is perfect.
+ */
+
entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
while (entryPtr != NULL) {
cmdName = Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr);
if ((simplePattern == NULL)
- || Tcl_StringMatch(cmdName, simplePattern)) {
+ || Tcl_StringMatch(cmdName, simplePattern)) {
if (specificNsInPattern) {
cmd = (Tcl_Command) Tcl_GetHashValue(entryPtr);
elemObjPtr = Tcl_NewObj();
@@ -835,19 +723,19 @@ InfoCommandsCmd(dummy, interp, objc, objv)
/*
* If the effective namespace isn't the global :: namespace, and a
- * specific namespace wasn't requested in the pattern, then add in
- * all global :: commands that match the simple pattern. Of course,
- * we add in only those commands that aren't hidden by a command in
- * the effective namespace.
+ * specific namespace wasn't requested in the pattern, then add in all
+ * global :: commands that match the simple pattern. Of course, we add
+ * in only those commands that aren't hidden by a command in the
+ * effective namespace.
*/
-
+
if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
entryPtr = Tcl_FirstHashEntry(&globalNsPtr->cmdTable, &search);
while (entryPtr != NULL) {
cmdName = Tcl_GetHashKey(&globalNsPtr->cmdTable, entryPtr);
if ((simplePattern == NULL)
- || Tcl_StringMatch(cmdName, simplePattern)) {
- if (Tcl_FindHashEntry(&nsPtr->cmdTable, cmdName) == NULL) {
+ || Tcl_StringMatch(cmdName, simplePattern)) {
+ if (Tcl_FindHashEntry(&nsPtr->cmdTable,cmdName) == NULL) {
Tcl_ListObjAppendElement(interp, listPtr,
Tcl_NewStringObj(cmdName, -1));
}
@@ -855,8 +743,97 @@ InfoCommandsCmd(dummy, interp, objc, objv)
entryPtr = Tcl_NextHashEntry(&search);
}
}
+ } else {
+ /*
+ * The pattern is non-trivial (can match more than one command name),
+ * there is an explicit path, and there is no explicit namespace in
+ * the pattern. This means that we have to traverse the path to
+ * discover all the commands defined.
+ */
+
+ Tcl_HashTable addedCommandsTable;
+ int isNew;
+ int foundGlobal = (nsPtr == globalNsPtr);
+
+ /*
+ * We keep a hash of the objects already added to the result list.
+ */
+
+ Tcl_InitObjHashTable(&addedCommandsTable);
+
+ entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
+ while (entryPtr != NULL) {
+ cmdName = Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr);
+ if ((simplePattern == NULL)
+ || Tcl_StringMatch(cmdName, simplePattern)) {
+ elemObjPtr = Tcl_NewStringObj(cmdName, -1);
+ Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
+ (void) Tcl_CreateHashEntry(&addedCommandsTable,
+ (char *)elemObjPtr, &isNew);
+ }
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+
+ /*
+ * Search the path next.
+ */
+
+ for (i=0 ; i<nsPtr->commandPathLength ; i++) {
+ Namespace *pathNsPtr = nsPtr->commandPathArray[i].nsPtr;
+
+ if (pathNsPtr == NULL) {
+ continue;
+ }
+ if (pathNsPtr == globalNsPtr) {
+ foundGlobal = 1;
+ }
+ entryPtr = Tcl_FirstHashEntry(&pathNsPtr->cmdTable, &search);
+ while (entryPtr != NULL) {
+ cmdName = Tcl_GetHashKey(&pathNsPtr->cmdTable, entryPtr);
+ if ((simplePattern == NULL)
+ || Tcl_StringMatch(cmdName, simplePattern)) {
+ elemObjPtr = Tcl_NewStringObj(cmdName, -1);
+ (void) Tcl_CreateHashEntry(&addedCommandsTable,
+ (char *) elemObjPtr, &isNew);
+ if (isNew) {
+ Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
+ } else {
+ TclDecrRefCount(elemObjPtr);
+ }
+ }
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+ }
+
+ /*
+ * If the effective namespace isn't the global :: namespace, and a
+ * specific namespace wasn't requested in the pattern, then add in all
+ * global :: commands that match the simple pattern. Of course, we add
+ * in only those commands that aren't hidden by a command in the
+ * effective namespace.
+ */
+
+ if (!foundGlobal) {
+ entryPtr = Tcl_FirstHashEntry(&globalNsPtr->cmdTable, &search);
+ while (entryPtr != NULL) {
+ cmdName = Tcl_GetHashKey(&globalNsPtr->cmdTable, entryPtr);
+ if ((simplePattern == NULL)
+ || Tcl_StringMatch(cmdName, simplePattern)) {
+ elemObjPtr = Tcl_NewStringObj(cmdName, -1);
+ if (Tcl_FindHashEntry(&addedCommandsTable,
+ (char *) elemObjPtr) == NULL) {
+ Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
+ } else {
+ TclDecrRefCount(elemObjPtr);
+ }
+ }
+ entryPtr = Tcl_NextHashEntry(&search);
+ }
+ }
+
+ Tcl_DeleteHashTable(&addedCommandsTable);
}
-
+
Tcl_SetObjResult(interp, listPtr);
return TCL_OK;
}
@@ -866,40 +843,36 @@ InfoCommandsCmd(dummy, interp, objc, objv)
*
* InfoCompleteCmd --
*
- * Called to implement the "info complete" command that determines
- * whether a string is a complete Tcl command. Handles the following
- * syntax:
+ * Called to implement the "info complete" command that determines
+ * whether a string is a complete Tcl command. Handles the following
+ * syntax:
*
- * info complete command
+ * info complete command
*
* Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
*
* Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-InfoCompleteCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+InfoCompleteCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "command");
- return TCL_ERROR;
- }
-
- if (TclObjCommandComplete(objv[2])) {
- Tcl_SetIntObj(Tcl_GetObjResult(interp), 1);
- } else {
- Tcl_SetIntObj(Tcl_GetObjResult(interp), 0);
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "command");
+ return TCL_ERROR;
}
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
+ TclObjCommandComplete(objv[1])));
return TCL_OK;
}
@@ -908,28 +881,27 @@ InfoCompleteCmd(dummy, interp, objc, objv)
*
* InfoDefaultCmd --
*
- * Called to implement the "info default" command that returns the
- * default value for a procedure argument. Handles the following
- * syntax:
+ * Called to implement the "info default" command that returns the
+ * default value for a procedure argument. Handles the following syntax:
*
- * info default procName arg varName
+ * info default procName arg varName
*
* Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
*
* Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-InfoDefaultCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+InfoDefaultCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
Interp *iPtr = (Interp *) interp;
char *procName, *argName, *varName;
@@ -937,484 +909,447 @@ InfoDefaultCmd(dummy, interp, objc, objv)
CompiledLocal *localPtr;
Tcl_Obj *valueObjPtr;
- if (objc != 5) {
- Tcl_WrongNumArgs(interp, 2, objv, "procname arg varname");
- return TCL_ERROR;
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "procname arg varname");
+ return TCL_ERROR;
}
- procName = Tcl_GetString(objv[2]);
- argName = Tcl_GetString(objv[3]);
+ procName = TclGetString(objv[1]);
+ argName = TclGetString(objv[2]);
procPtr = TclFindProc(iPtr, procName);
if (procPtr == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "\"", procName, "\" isn't a procedure", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "\"", procName, "\" isn't a procedure",NULL);
+ return TCL_ERROR;
}
for (localPtr = procPtr->firstLocalPtr; localPtr != NULL;
- localPtr = localPtr->nextPtr) {
- if (TclIsVarArgument(localPtr)
+ localPtr = localPtr->nextPtr) {
+ if (TclIsVarArgument(localPtr)
&& (strcmp(argName, localPtr->name) == 0)) {
- if (localPtr->defValuePtr != NULL) {
- valueObjPtr = Tcl_ObjSetVar2(interp, objv[4], NULL,
+ if (localPtr->defValuePtr != NULL) {
+ valueObjPtr = Tcl_ObjSetVar2(interp, objv[3], NULL,
localPtr->defValuePtr, 0);
- if (valueObjPtr == NULL) {
- defStoreError:
- varName = Tcl_GetString(objv[4]);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "couldn't store default value in variable \"",
- varName, "\"", (char *) NULL);
- return TCL_ERROR;
- }
- Tcl_SetIntObj(Tcl_GetObjResult(interp), 1);
- } else {
- Tcl_Obj *nullObjPtr = Tcl_NewObj();
- Tcl_IncrRefCount(nullObjPtr);
- valueObjPtr = Tcl_ObjSetVar2(interp, objv[4], NULL,
+ if (valueObjPtr == NULL) {
+ goto defStoreError;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(1));
+ } else {
+ Tcl_Obj *nullObjPtr = Tcl_NewObj();
+ valueObjPtr = Tcl_ObjSetVar2(interp, objv[3], NULL,
nullObjPtr, 0);
- Tcl_DecrRefCount(nullObjPtr); /* free unneeded obj */
- if (valueObjPtr == NULL) {
- goto defStoreError;
- }
- Tcl_SetIntObj(Tcl_GetObjResult(interp), 0);
- }
- return TCL_OK;
- }
- }
-
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "procedure \"", procName, "\" doesn't have an argument \"",
- argName, "\"", (char *) NULL);
+ if (valueObjPtr == NULL) {
+ goto defStoreError;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
+ }
+ return TCL_OK;
+ }
+ }
+
+ Tcl_AppendResult(interp, "procedure \"", procName,
+ "\" doesn't have an argument \"", argName, "\"", NULL);
+ return TCL_ERROR;
+
+ defStoreError:
+ varName = TclGetString(objv[3]);
+ Tcl_AppendResult(interp, "couldn't store default value in variable \"",
+ varName, "\"", NULL);
return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
- * InfoExistsCmd --
+ * TclInfoExistsCmd --
*
- * Called to implement the "info exists" command that determines
- * whether a variable exists. Handles the following syntax:
+ * Called to implement the "info exists" command that determines whether
+ * a variable exists. Handles the following syntax:
*
- * info exists varName
+ * info exists varName
*
* Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
*
* Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
*
*----------------------------------------------------------------------
*/
-static int
-InfoExistsCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+int
+TclInfoExistsCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
char *varName;
Var *varPtr;
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "varName");
- return TCL_ERROR;
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "varName");
+ return TCL_ERROR;
}
- varName = Tcl_GetString(objv[2]);
+ varName = TclGetString(objv[1]);
varPtr = TclVarTraceExists(interp, varName);
- if ((varPtr != NULL) && !TclIsVarUndefined(varPtr)) {
- Tcl_SetIntObj(Tcl_GetObjResult(interp), 1);
- } else {
- Tcl_SetIntObj(Tcl_GetObjResult(interp), 0);
- }
+
+ Tcl_SetObjResult(interp,
+ Tcl_NewBooleanObj(varPtr && varPtr->value.objPtr));
return TCL_OK;
}
-#ifdef TCL_TIP280
/*
*----------------------------------------------------------------------
*
* InfoFrameCmd --
* TIP #280
*
- * Called to implement the "info frame" command that returns the
- * location of either the currently executing command, or its caller.
- * Handles the following syntax:
+ * Called to implement the "info frame" command that returns the location
+ * of either the currently executing command, or its caller. Handles the
+ * following syntax:
*
- * info frame ?number?
+ * info frame ?number?
*
* Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
*
* Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-InfoFrameCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+InfoFrameCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
Interp *iPtr = (Interp *) interp;
+ int level;
+ CmdFrame *framePtr;
- if (objc == 2) {
- /* just "info frame" */
- int levels = (iPtr->cmdFramePtr == NULL
- ? 0
- : iPtr->cmdFramePtr->level);
+ if (objc == 1) {
+ /*
+ * Just "info frame".
+ */
+
+ int levels =
+ (iPtr->cmdFramePtr == NULL ? 0 : iPtr->cmdFramePtr->level);
Tcl_SetObjResult(interp, Tcl_NewIntObj (levels));
- return TCL_OK;
-
- } else if (objc == 3) {
- /* "info frame level" */
- int level;
- CmdFrame *framePtr;
-
- if (Tcl_GetIntFromObj(interp, objv[2], &level) != TCL_OK) {
- return TCL_ERROR;
- }
- if (level <= 0) {
- /* Relative adressing */
-
- if (iPtr->cmdFramePtr == NULL) {
- levelError:
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "bad level \"",
- Tcl_GetString(objv[2]),
- "\"", (char *) NULL);
- return TCL_ERROR;
- }
- /* Convert to absolute. */
-
- level += iPtr->cmdFramePtr->level;
- }
- for (framePtr = iPtr->cmdFramePtr;
- framePtr != NULL;
- framePtr = framePtr->nextPtr) {
+ return TCL_OK;
+ } else if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "?number?");
+ return TCL_ERROR;
+ }
- if (framePtr->level == level) {
- break;
- }
- }
- if (framePtr == NULL) {
- goto levelError;
- }
+ /*
+ * We've got "info frame level" and must parse the level first.
+ */
+ if (TclGetIntFromObj(interp, objv[1], &level) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (level <= 0) {
/*
- * Pull the information and construct the dictionary to return, as
- * list. Regarding use of the CmdFrame fields see tclInt.h, and its
- * definition.
+ * Negative levels are adressing relative to the current frame's
+ * depth.
*/
- {
- Tcl_Obj* lv [20]; /* Keep uptodate when more keys are added to the dict */
- int lc = 0;
+ if (iPtr->cmdFramePtr == NULL) {
+ levelError:
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "bad level \"",
+ TclGetString(objv[1]), "\"", NULL);
+ return TCL_ERROR;
+ }
- /* This array is indexed by the TCL_LOCATION_... values, except
- * for _LAST.
- */
+ /*
+ * Convert to absolute.
+ */
- static CONST char* typeString [TCL_LOCATION_LAST] = {
- "eval", "eval", "eval", "precompiled", "source", "proc"
- };
+ level += iPtr->cmdFramePtr->level;
+ }
- Proc* procPtr = framePtr->framePtr ? framePtr->framePtr->procPtr : NULL;
+ for (framePtr = iPtr->cmdFramePtr; framePtr != NULL;
+ framePtr = framePtr->nextPtr) {
+ if (framePtr->level == level) {
+ break;
+ }
+ }
+ if (framePtr == NULL) {
+ goto levelError;
+ }
- switch (framePtr->type) {
- case TCL_LOCATION_EVAL:
- /* Evaluation, dynamic script. Type, line, cmd, the latter
- * through str. */
+ Tcl_SetObjResult(interp, TclInfoFrame(interp, framePtr));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclInfoFrame --
+ *
+ * Core of InfoFrameCmd, returns TIP280 dict for a given frame.
+ *
+ * Results:
+ * Returns TIP280 dict.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
- lv [lc ++] = Tcl_NewStringObj ("type",-1);
- lv [lc ++] = Tcl_NewStringObj (typeString [framePtr->type],-1);
- lv [lc ++] = Tcl_NewStringObj ("line",-1);
- lv [lc ++] = Tcl_NewIntObj (framePtr->line[0]);
- lv [lc ++] = Tcl_NewStringObj ("cmd",-1);
- lv [lc ++] = Tcl_NewStringObj (framePtr->cmd.str.cmd,
- framePtr->cmd.str.len);
- break;
+Tcl_Obj *
+TclInfoFrame(
+ Tcl_Interp *interp, /* Current interpreter. */
+ CmdFrame *framePtr) /* Frame to get info for. */
+{
+ Interp *iPtr = (Interp *) interp;
+ Tcl_Obj *lv[20]; /* Keep uptodate when more keys are added to
+ * the dict. */
+ int lc = 0;
+ /*
+ * This array is indexed by the TCL_LOCATION_... values, except
+ * for _LAST.
+ */
+ static CONST char *typeString[TCL_LOCATION_LAST] = {
+ "eval", "eval", "eval", "precompiled", "source", "proc"
+ };
+ Tcl_Obj *tmpObj;
+ Proc *procPtr =
+ framePtr->framePtr ? framePtr->framePtr->procPtr : NULL;
- case TCL_LOCATION_EVAL_LIST:
- /* List optimized evaluation. Type, line, cmd, the latter
- * through listPtr, possibly a frame. */
+ /*
+ * Pull the information and construct the dictionary to return, as list.
+ * Regarding use of the CmdFrame fields see tclInt.h, and its definition.
+ */
- lv [lc ++] = Tcl_NewStringObj ("type",-1);
- lv [lc ++] = Tcl_NewStringObj (typeString [framePtr->type],-1);
- lv [lc ++] = Tcl_NewStringObj ("line",-1);
- lv [lc ++] = Tcl_NewIntObj (1);
+#define ADD_PAIR(name, value) \
+ TclNewLiteralStringObj(tmpObj, name); \
+ lv[lc++] = tmpObj; \
+ lv[lc++] = (value)
- /* We put a duplicate of the command list obj into the result
- * to ensure that the 'pure List'-property of the command
- * itself is not destroyed. Otherwise the query here would
- * disable the list optimization path in Tcl_EvalObjEx.
- */
+ switch (framePtr->type) {
+ case TCL_LOCATION_EVAL:
+ /*
+ * Evaluation, dynamic script. Type, line, cmd, the latter through
+ * str.
+ */
- lv [lc ++] = Tcl_NewStringObj ("cmd",-1);
- lv [lc ++] = Tcl_DuplicateObj (framePtr->cmd.listPtr);
- break;
+ ADD_PAIR("type", Tcl_NewStringObj(typeString[framePtr->type], -1));
+ ADD_PAIR("line", Tcl_NewIntObj(framePtr->line[0]));
+ ADD_PAIR("cmd", Tcl_NewStringObj(framePtr->cmd.str.cmd,
+ framePtr->cmd.str.len));
+ break;
- case TCL_LOCATION_PREBC:
- /* Precompiled. Result contains the type as signal, nothing
- * else */
+ case TCL_LOCATION_EVAL_LIST:
+ /*
+ * List optimized evaluation. Type, line, cmd, the latter through
+ * listPtr, possibly a frame.
+ */
- lv [lc ++] = Tcl_NewStringObj ("type",-1);
- lv [lc ++] = Tcl_NewStringObj (typeString [framePtr->type],-1);
- break;
+ ADD_PAIR("type", Tcl_NewStringObj(typeString[framePtr->type], -1));
+ ADD_PAIR("line", Tcl_NewIntObj(1));
- case TCL_LOCATION_BC: {
- /* Execution of bytecode. Talk to the BC engine to fill out
- * the frame. */
+ /*
+ * We put a duplicate of the command list obj into the result to
+ * ensure that the 'pure List'-property of the command itself is not
+ * destroyed. Otherwise the query here would disable the list
+ * optimization path in Tcl_EvalObjEx.
+ */
- CmdFrame f = *framePtr;
+ ADD_PAIR("cmd", Tcl_DuplicateObj(framePtr->cmd.listPtr));
+ break;
- /* Note: Type BC => f.data.eval.path is not used.
- * f.data.tebc.codePtr is used instead.
- */
+ case TCL_LOCATION_PREBC:
+ /*
+ * Precompiled. Result contains the type as signal, nothing else.
+ */
- TclGetSrcInfoForPc (&f);
- /* Now filled: cmd.str.(cmd,len), line */
- /* Possibly modified: type, path! */
+ ADD_PAIR("type", Tcl_NewStringObj(typeString[framePtr->type], -1));
+ break;
- lv [lc ++] = Tcl_NewStringObj ("type",-1);
- lv [lc ++] = Tcl_NewStringObj (typeString [f.type],-1);
- lv [lc ++] = Tcl_NewStringObj ("line",-1);
- lv [lc ++] = Tcl_NewIntObj (f.line[0]);
+ case TCL_LOCATION_BC: {
+ /*
+ * Execution of bytecode. Talk to the BC engine to fill out the frame.
+ */
- if (f.type == TCL_LOCATION_SOURCE) {
- lv [lc ++] = Tcl_NewStringObj ("file",-1);
- lv [lc ++] = f.data.eval.path;
- /* Death of reference by TclGetSrcInfoForPc */
- Tcl_DecrRefCount (f.data.eval.path);
- }
+ CmdFrame *fPtr;
- lv [lc ++] = Tcl_NewStringObj ("cmd",-1);
- lv [lc ++] = Tcl_NewStringObj (f.cmd.str.cmd, f.cmd.str.len);
- break;
- }
+ fPtr = (CmdFrame *) TclStackAlloc(interp, sizeof(CmdFrame));
+ *fPtr = *framePtr;
- case TCL_LOCATION_SOURCE:
- /* Evaluation of a script file */
-
- lv [lc ++] = Tcl_NewStringObj ("type",-1);
- lv [lc ++] = Tcl_NewStringObj (typeString [framePtr->type],-1);
- lv [lc ++] = Tcl_NewStringObj ("line",-1);
- lv [lc ++] = Tcl_NewIntObj (framePtr->line[0]);
- lv [lc ++] = Tcl_NewStringObj ("file",-1);
- lv [lc ++] = framePtr->data.eval.path;
- /* Refcount framePtr->data.eval.path goes up when lv
- * is converted into the result list object.
- */
- lv [lc ++] = Tcl_NewStringObj ("cmd",-1);
- lv [lc ++] = Tcl_NewStringObj (framePtr->cmd.str.cmd,
- framePtr->cmd.str.len);
- break;
+ /*
+ * Note:
+ * Type BC => f.data.eval.path is not used.
+ * f.data.tebc.codePtr is used instead.
+ */
- case TCL_LOCATION_PROC:
- Tcl_Panic ("TCL_LOCATION_PROC found in standard frame");
- break;
- }
+ TclGetSrcInfoForPc(fPtr);
+
+ /*
+ * Now filled: cmd.str.(cmd,len), line
+ * Possibly modified: type, path!
+ */
+
+ ADD_PAIR("type", Tcl_NewStringObj(typeString[fPtr->type], -1));
+ if (fPtr->line) {
+ ADD_PAIR("line", Tcl_NewIntObj(fPtr->line[0]));
+ }
+
+ if (fPtr->type == TCL_LOCATION_SOURCE) {
+ ADD_PAIR("file", fPtr->data.eval.path);
/*
- * 'proc'. Common to all frame types. Conditional on having an
- * associated Procedure CallFrame.
+ * Death of reference by TclGetSrcInfoForPc.
*/
- if (procPtr != NULL) {
- Tcl_HashEntry* namePtr = procPtr->cmdPtr->hPtr;
- /*
- * ITcl seems to provide us with weird, maybe bogus Command
- * structures (methods?) which may have no HashEntry pointing
- * to the name information, or a HashEntry without owning
- * HashTable. Therefore check again that our data is valid.
- */
- if (namePtr && namePtr->tablePtr) {
- char* procName = Tcl_GetHashKey (namePtr->tablePtr, namePtr);
- char* nsName = procPtr->cmdPtr->nsPtr->fullName;
+ Tcl_DecrRefCount(fPtr->data.eval.path);
+ }
- lv [lc ++] = Tcl_NewStringObj ("proc",-1);
- lv [lc ++] = Tcl_NewStringObj (nsName,-1);
+ ADD_PAIR("cmd",
+ Tcl_NewStringObj(fPtr->cmd.str.cmd, fPtr->cmd.str.len));
+ TclStackFree(interp, fPtr);
+ break;
+ }
- if (strcmp (nsName, "::") != 0) {
- Tcl_AppendToObj (lv [lc-1], "::", -1);
- }
- Tcl_AppendToObj (lv [lc-1], procName, -1);
- }
- }
+ case TCL_LOCATION_SOURCE:
+ /*
+ * Evaluation of a script file.
+ */
- /* 'level'. Common to all frame types. Conditional on having an
- * associated _visible_ CallFrame */
+ ADD_PAIR("type", Tcl_NewStringObj(typeString[framePtr->type], -1));
+ ADD_PAIR("line", Tcl_NewIntObj(framePtr->line[0]));
+ ADD_PAIR("file", framePtr->data.eval.path);
- if ((framePtr->framePtr != NULL) && (iPtr->varFramePtr != NULL)) {
- CallFrame* current = framePtr->framePtr;
- CallFrame* top = iPtr->varFramePtr;
- CallFrame* idx;
+ /*
+ * Refcount framePtr->data.eval.path goes up when lv is converted into
+ * the result list object.
+ */
- for (idx = top;
- idx != NULL;
- idx = idx->callerVarPtr) {
- if (idx == current) {
- int c = framePtr->framePtr->level;
- int t = iPtr->varFramePtr->level;
+ ADD_PAIR("cmd", Tcl_NewStringObj(framePtr->cmd.str.cmd,
+ framePtr->cmd.str.len));
+ break;
- lv [lc ++] = Tcl_NewStringObj ("level",-1);
- lv [lc ++] = Tcl_NewIntObj (t - c);
- break;
- }
- }
+ case TCL_LOCATION_PROC:
+ Tcl_Panic("TCL_LOCATION_PROC found in standard frame");
+ break;
+ }
+
+ /*
+ * 'proc'. Common to all frame types. Conditional on having an associated
+ * Procedure CallFrame.
+ */
+
+ if (procPtr != NULL) {
+ Tcl_HashEntry *namePtr = procPtr->cmdPtr->hPtr;
+
+ if (namePtr) {
+ /*
+ * This is a regular command.
+ */
+
+ char *procName = Tcl_GetHashKey(namePtr->tablePtr, namePtr);
+ char *nsName = procPtr->cmdPtr->nsPtr->fullName;
+
+ ADD_PAIR("proc", Tcl_NewStringObj(nsName, -1));
+
+ if (strcmp(nsName, "::") != 0) {
+ Tcl_AppendToObj(lv[lc-1], "::", -1);
}
+ Tcl_AppendToObj(lv[lc-1], procName, -1);
+ } else if (procPtr->cmdPtr->clientData) {
+ ExtraFrameInfo *efiPtr = procPtr->cmdPtr->clientData;
+ int i;
- Tcl_SetObjResult(interp, Tcl_NewListObj (lc, lv));
- return TCL_OK;
+ /*
+ * This is a non-standard command. Luckily, it's told us how to
+ * render extra information about its frame.
+ */
+
+ for (i=0 ; i<efiPtr->length ; i++) {
+ lv[lc++] = Tcl_NewStringObj(efiPtr->fields[i].name, -1);
+ if (efiPtr->fields[i].proc) {
+ lv[lc++] =
+ efiPtr->fields[i].proc(efiPtr->fields[i].clientData);
+ } else {
+ lv[lc++] = efiPtr->fields[i].clientData;
+ }
+ }
}
}
- Tcl_WrongNumArgs(interp, 2, objv, "?number?");
+ /*
+ * 'level'. Common to all frame types. Conditional on having an associated
+ * _visible_ CallFrame.
+ */
- return TCL_ERROR;
-}
-#endif
-
-/*
- *----------------------------------------------------------------------
- *
- * InfoFunctionsCmd --
- *
- * Called to implement the "info functions" command that returns the
- * list of math functions matching an optional pattern. Handles the
- * following syntax:
- *
- * info functions ?pattern?
- *
- * Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
- *
- * Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
- *
- *----------------------------------------------------------------------
- */
+ if ((framePtr->framePtr != NULL) && (iPtr->varFramePtr != NULL)) {
+ CallFrame *current = framePtr->framePtr;
+ CallFrame *top = iPtr->varFramePtr;
+ CallFrame *idx;
-static int
-InfoFunctionsCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
-{
- char *pattern;
- Tcl_Obj *listPtr;
+ for (idx=top ; idx!=NULL ; idx=idx->callerVarPtr) {
+ if (idx == current) {
+ int c = framePtr->framePtr->level;
+ int t = iPtr->varFramePtr->level;
- if (objc == 2) {
- pattern = NULL;
- } else if (objc == 3) {
- pattern = Tcl_GetString(objv[2]);
- } else {
- Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
- return TCL_ERROR;
+ ADD_PAIR("level", Tcl_NewIntObj(t - c));
+ break;
+ }
+ }
}
- listPtr = Tcl_ListMathFuncs(interp, pattern);
- if (listPtr == NULL) {
- return TCL_ERROR;
- }
- Tcl_SetObjResult(interp, listPtr);
- return TCL_OK;
+ return Tcl_NewListObj(lc, lv);
}
/*
*----------------------------------------------------------------------
*
- * InfoGlobalsCmd --
+ * InfoFunctionsCmd --
*
- * Called to implement the "info globals" command that returns the list
- * of global variables matching an optional pattern. Handles the
- * following syntax:
+ * Called to implement the "info functions" command that returns the list
+ * of math functions matching an optional pattern. Handles the following
+ * syntax:
*
- * info globals ?pattern?
+ * info functions ?pattern?
*
* Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
*
* Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-InfoGlobalsCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+InfoFunctionsCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
- char *varName, *pattern;
- Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
- register Tcl_HashEntry *entryPtr;
- Tcl_HashSearch search;
- Var *varPtr;
- Tcl_Obj *listPtr;
+ char *pattern;
- if (objc == 2) {
- pattern = NULL;
- } else if (objc == 3) {
- pattern = Tcl_GetString(objv[2]);
- /*
- * Strip leading global-namespace qualifiers. [Bug 1057461]
- */
- if (pattern[0] == ':' && pattern[1] == ':') {
- while (*pattern == ':') {
- pattern++;
- }
- }
+ if (objc == 1) {
+ pattern = NULL;
+ } else if (objc == 2) {
+ pattern = TclGetString(objv[1]);
} else {
- Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
- return TCL_ERROR;
+ Tcl_WrongNumArgs(interp, 1, objv, "?pattern?");
+ return TCL_ERROR;
}
- /*
- * Scan through the global :: namespace's variable table and create a
- * list of all global variables that match the pattern.
- */
-
- listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
- if (pattern != NULL && TclMatchIsTrivial(pattern)) {
- entryPtr = Tcl_FindHashEntry(&globalNsPtr->varTable, pattern);
- if (entryPtr != NULL) {
- varPtr = (Var *) Tcl_GetHashValue(entryPtr);
- if (!TclIsVarUndefined(varPtr)) {
- Tcl_ListObjAppendElement(interp, listPtr,
- Tcl_NewStringObj(pattern, -1));
- }
- }
- } else {
- for (entryPtr = Tcl_FirstHashEntry(&globalNsPtr->varTable, &search);
- entryPtr != NULL;
- entryPtr = Tcl_NextHashEntry(&search)) {
- varPtr = (Var *) Tcl_GetHashValue(entryPtr);
- if (TclIsVarUndefined(varPtr)) {
- continue;
- }
- varName = Tcl_GetHashKey(&globalNsPtr->varTable, entryPtr);
- if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) {
- Tcl_ListObjAppendElement(interp, listPtr,
- Tcl_NewStringObj(varName, -1));
- }
- }
- }
- Tcl_SetObjResult(interp, listPtr);
+ Tcl_SetObjResult(interp, Tcl_ListMathFuncs(interp, pattern));
return TCL_OK;
}
@@ -1423,43 +1358,42 @@ InfoGlobalsCmd(dummy, interp, objc, objv)
*
* InfoHostnameCmd --
*
- * Called to implement the "info hostname" command that returns the
- * host name. Handles the following syntax:
+ * Called to implement the "info hostname" command that returns the host
+ * name. Handles the following syntax:
*
- * info hostname
+ * info hostname
*
* Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
*
* Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-InfoHostnameCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+InfoHostnameCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
CONST char *name;
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- return TCL_ERROR;
+
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, NULL);
+ return TCL_ERROR;
}
name = Tcl_GetHostName();
if (name) {
- Tcl_SetStringObj(Tcl_GetObjResult(interp), name, -1);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(name, -1));
return TCL_OK;
- } else {
- Tcl_SetStringObj(Tcl_GetObjResult(interp),
- "unable to determine name of host", -1);
- return TCL_ERROR;
}
+ Tcl_SetResult(interp, "unable to determine name of host", TCL_STATIC);
+ return TCL_ERROR;
}
/*
@@ -1467,71 +1401,69 @@ InfoHostnameCmd(dummy, interp, objc, objv)
*
* InfoLevelCmd --
*
- * Called to implement the "info level" command that returns
- * information about the call stack. Handles the following syntax:
+ * Called to implement the "info level" command that returns information
+ * about the call stack. Handles the following syntax:
*
- * info level ?number?
+ * info level ?number?
*
* Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
*
* Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-InfoLevelCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+InfoLevelCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
Interp *iPtr = (Interp *) interp;
- int level;
- CallFrame *framePtr;
- Tcl_Obj *listPtr;
- if (objc == 2) { /* just "info level" */
- if (iPtr->varFramePtr == NULL) {
- Tcl_SetIntObj(Tcl_GetObjResult(interp), 0);
- } else {
- Tcl_SetIntObj(Tcl_GetObjResult(interp), iPtr->varFramePtr->level);
- }
- return TCL_OK;
- } else if (objc == 3) {
- if (Tcl_GetIntFromObj(interp, objv[2], &level) != TCL_OK) {
- return TCL_ERROR;
- }
- if (level <= 0) {
- if (iPtr->varFramePtr == NULL) {
- levelError:
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "bad level \"",
- Tcl_GetString(objv[2]),
- "\"", (char *) NULL);
- return TCL_ERROR;
- }
- level += iPtr->varFramePtr->level;
- }
- for (framePtr = iPtr->varFramePtr; framePtr != NULL;
- framePtr = framePtr->callerVarPtr) {
- if (framePtr->level == level) {
- break;
- }
- }
- if (framePtr == NULL) {
- goto levelError;
- }
-
- listPtr = Tcl_NewListObj(framePtr->objc, framePtr->objv);
- Tcl_SetObjResult(interp, listPtr);
- return TCL_OK;
- }
-
- Tcl_WrongNumArgs(interp, 2, objv, "?number?");
+ if (objc == 1) { /* Just "info level" */
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(iPtr->varFramePtr->level));
+ return TCL_OK;
+ }
+
+ if (objc == 2) {
+ int level;
+ CallFrame *framePtr, *rootFramePtr = iPtr->rootFramePtr;
+
+ if (TclGetIntFromObj(interp, objv[1], &level) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (level <= 0) {
+ if (iPtr->varFramePtr == rootFramePtr) {
+ goto levelError;
+ }
+ level += iPtr->varFramePtr->level;
+ }
+ for (framePtr=iPtr->varFramePtr ; framePtr!=rootFramePtr;
+ framePtr=framePtr->callerVarPtr) {
+ if (framePtr->level == level) {
+ break;
+ }
+ }
+ if (framePtr == rootFramePtr) {
+ goto levelError;
+ }
+
+ Tcl_SetObjResult(interp,
+ Tcl_NewListObj(framePtr->objc, framePtr->objv));
+ return TCL_OK;
+ }
+
+ Tcl_WrongNumArgs(interp, 1, objv, "?number?");
+ return TCL_ERROR;
+
+ levelError:
+ Tcl_AppendResult(interp, "bad level \"", TclGetString(objv[1]), "\"",
+ NULL);
return TCL_ERROR;
}
@@ -1540,43 +1472,42 @@ InfoLevelCmd(dummy, interp, objc, objv)
*
* InfoLibraryCmd --
*
- * Called to implement the "info library" command that returns the
- * library directory for the Tcl installation. Handles the following
- * syntax:
+ * Called to implement the "info library" command that returns the
+ * library directory for the Tcl installation. Handles the following
+ * syntax:
*
- * info library
+ * info library
*
* Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
*
* Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-InfoLibraryCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+InfoLibraryCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
CONST char *libDirName;
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- return TCL_ERROR;
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, NULL);
+ return TCL_ERROR;
}
libDirName = Tcl_GetVar(interp, "tcl_library", TCL_GLOBAL_ONLY);
if (libDirName != NULL) {
- Tcl_SetStringObj(Tcl_GetObjResult(interp), libDirName, -1);
- return TCL_OK;
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(libDirName, -1));
+ return TCL_OK;
}
- Tcl_SetStringObj(Tcl_GetObjResult(interp),
- "no library has been specified for Tcl", -1);
+ Tcl_SetResult(interp, "no library has been specified for Tcl",TCL_STATIC);
return TCL_ERROR;
}
@@ -1585,174 +1516,42 @@ InfoLibraryCmd(dummy, interp, objc, objv)
*
* InfoLoadedCmd --
*
- * Called to implement the "info loaded" command that returns the
- * packages that have been loaded into an interpreter. Handles the
- * following syntax:
+ * Called to implement the "info loaded" command that returns the
+ * packages that have been loaded into an interpreter. Handles the
+ * following syntax:
*
- * info loaded ?interp?
+ * info loaded ?interp?
*
* Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
*
* Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-InfoLoadedCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+InfoLoadedCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
char *interpName;
- int result;
- if ((objc != 2) && (objc != 3)) {
- Tcl_WrongNumArgs(interp, 2, objv, "?interp?");
- return TCL_ERROR;
+ if ((objc != 1) && (objc != 2)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "?interp?");
+ return TCL_ERROR;
}
- if (objc == 2) { /* get loaded pkgs in all interpreters */
+ if (objc == 1) { /* Get loaded pkgs in all interpreters. */
interpName = NULL;
- } else { /* get pkgs just in specified interp */
- interpName = Tcl_GetString(objv[2]);
- }
- result = TclGetLoadedPackages(interp, interpName);
- return result;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * InfoLocalsCmd --
- *
- * Called to implement the "info locals" command to return a list of
- * local variables that match an optional pattern. Handles the
- * following syntax:
- *
- * info locals ?pattern?
- *
- * Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
- *
- * Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-InfoLocalsCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
-{
- Interp *iPtr = (Interp *) interp;
- char *pattern;
- Tcl_Obj *listPtr;
-
- if (objc == 2) {
- pattern = NULL;
- } else if (objc == 3) {
- pattern = Tcl_GetString(objv[2]);
- } else {
- Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
- return TCL_ERROR;
- }
-
- if (iPtr->varFramePtr == NULL || !iPtr->varFramePtr->isProcCallFrame) {
- return TCL_OK;
- }
-
- /*
- * Return a list containing names of first the compiled locals (i.e. the
- * ones stored in the call frame), then the variables in the local hash
- * table (if one exists).
- */
-
- listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
- AppendLocals(interp, listPtr, pattern, 0);
- Tcl_SetObjResult(interp, listPtr);
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * AppendLocals --
- *
- * Append the local variables for the current frame to the
- * specified list object.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-AppendLocals(interp, listPtr, pattern, includeLinks)
- Tcl_Interp *interp; /* Current interpreter. */
- Tcl_Obj *listPtr; /* List object to append names to. */
- CONST char *pattern; /* Pattern to match against. */
- int includeLinks; /* 1 if upvars should be included, else 0. */
-{
- Interp *iPtr = (Interp *) interp;
- CompiledLocal *localPtr;
- Var *varPtr;
- int i, localVarCt;
- char *varName;
- Tcl_HashTable *localVarTablePtr;
- register Tcl_HashEntry *entryPtr;
- Tcl_HashSearch search;
-
- localPtr = iPtr->varFramePtr->procPtr->firstLocalPtr;
- localVarCt = iPtr->varFramePtr->numCompiledLocals;
- varPtr = iPtr->varFramePtr->compiledLocals;
- localVarTablePtr = iPtr->varFramePtr->varTablePtr;
-
- for (i = 0; i < localVarCt; i++) {
- /*
- * Skip nameless (temporary) variables and undefined variables
- */
-
- if (!TclIsVarTemporary(localPtr) && !TclIsVarUndefined(varPtr)
- && (includeLinks || !TclIsVarLink(varPtr))) {
- varName = varPtr->name;
- if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) {
- Tcl_ListObjAppendElement(interp, listPtr,
- Tcl_NewStringObj(varName, -1));
- }
- }
- varPtr++;
- localPtr = localPtr->nextPtr;
- }
-
- if (localVarTablePtr != NULL) {
- for (entryPtr = Tcl_FirstHashEntry(localVarTablePtr, &search);
- entryPtr != NULL;
- entryPtr = Tcl_NextHashEntry(&search)) {
- varPtr = (Var *) Tcl_GetHashValue(entryPtr);
- if (!TclIsVarUndefined(varPtr)
- && (includeLinks || !TclIsVarLink(varPtr))) {
- varName = Tcl_GetHashKey(localVarTablePtr, entryPtr);
- if ((pattern == NULL)
- || Tcl_StringMatch(varName, pattern)) {
- Tcl_ListObjAppendElement(interp, listPtr,
- Tcl_NewStringObj(varName, -1));
- }
- }
- }
+ } else { /* Get pkgs just in specified interp. */
+ interpName = TclGetString(objv[1]);
}
+ return TclGetLoadedPackages(interp, interpName);
}
/*
@@ -1760,41 +1559,34 @@ AppendLocals(interp, listPtr, pattern, includeLinks)
*
* InfoNameOfExecutableCmd --
*
- * Called to implement the "info nameofexecutable" command that returns
- * the name of the binary file running this application. Handles the
- * following syntax:
+ * Called to implement the "info nameofexecutable" command that returns
+ * the name of the binary file running this application. Handles the
+ * following syntax:
*
- * info nameofexecutable
+ * info nameofexecutable
*
* Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
*
* Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-InfoNameOfExecutableCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+InfoNameOfExecutableCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
- CONST char *nameOfExecutable;
-
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- return TCL_ERROR;
- }
-
- nameOfExecutable = Tcl_GetNameOfExecutable();
-
- if (nameOfExecutable != NULL) {
- Tcl_SetStringObj(Tcl_GetObjResult(interp), nameOfExecutable, -1);
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, NULL);
+ return TCL_ERROR;
}
+ Tcl_SetObjResult(interp, TclGetObjNameOfExecutable());
return TCL_OK;
}
@@ -1803,41 +1595,41 @@ InfoNameOfExecutableCmd(dummy, interp, objc, objv)
*
* InfoPatchLevelCmd --
*
- * Called to implement the "info patchlevel" command that returns the
- * default value for an argument to a procedure. Handles the following
- * syntax:
+ * Called to implement the "info patchlevel" command that returns the
+ * default value for an argument to a procedure. Handles the following
+ * syntax:
*
- * info patchlevel
+ * info patchlevel
*
* Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
*
* Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-InfoPatchLevelCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+InfoPatchLevelCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
CONST char *patchlevel;
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- return TCL_ERROR;
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, NULL);
+ return TCL_ERROR;
}
patchlevel = Tcl_GetVar(interp, "tcl_patchLevel",
- (TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
+ (TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
if (patchlevel != NULL) {
- Tcl_SetStringObj(Tcl_GetObjResult(interp), patchlevel, -1);
- return TCL_OK;
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(patchlevel, -1));
+ return TCL_OK;
}
return TCL_ERROR;
}
@@ -1847,31 +1639,31 @@ InfoPatchLevelCmd(dummy, interp, objc, objv)
*
* InfoProcsCmd --
*
- * Called to implement the "info procs" command that returns the
- * list of procedures in the interpreter that match an optional pattern.
- * The pattern, if any, consists of an optional sequence of namespace
- * names separated by "::" qualifiers, which is followed by a
- * glob-style pattern that restricts which commands are returned.
- * Handles the following syntax:
+ * Called to implement the "info procs" command that returns the list of
+ * procedures in the interpreter that match an optional pattern. The
+ * pattern, if any, consists of an optional sequence of namespace names
+ * separated by "::" qualifiers, which is followed by a glob-style
+ * pattern that restricts which commands are returned. Handles the
+ * following syntax:
*
- * info procs ?pattern?
+ * info procs ?pattern?
*
* Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
*
* Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-InfoProcsCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+InfoProcsCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
char *cmdName, *pattern;
CONST char *simplePattern;
@@ -1879,44 +1671,44 @@ InfoProcsCmd(dummy, interp, objc, objv)
#ifdef INFO_PROCS_SEARCH_GLOBAL_NS
Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
#endif
- Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+ Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
Tcl_Obj *listPtr, *elemObjPtr;
- int specificNsInPattern = 0; /* Init. to avoid compiler warning. */
+ int specificNsInPattern = 0;/* Init. to avoid compiler warning. */
register Tcl_HashEntry *entryPtr;
Tcl_HashSearch search;
Command *cmdPtr, *realCmdPtr;
/*
- * Get the pattern and find the "effective namespace" in which to
- * list procs.
+ * Get the pattern and find the "effective namespace" in which to list
+ * procs.
*/
- if (objc == 2) {
+ if (objc == 1) {
simplePattern = NULL;
nsPtr = currNsPtr;
specificNsInPattern = 0;
- } else if (objc == 3) {
+ } else if (objc == 2) {
/*
* From the pattern, get the effective namespace and the simple
- * pattern (no namespace qualifiers or ::'s) at the end. If an
- * error was found while parsing the pattern, return it. Otherwise,
- * if the namespace wasn't found, just leave nsPtr NULL: we will
- * return an empty list since no commands there can be found.
+ * pattern (no namespace qualifiers or ::'s) at the end. If an error
+ * was found while parsing the pattern, return it. Otherwise, if the
+ * namespace wasn't found, just leave nsPtr NULL: we will return an
+ * empty list since no commands there can be found.
*/
Namespace *dummy1NsPtr, *dummy2NsPtr;
- pattern = Tcl_GetString(objv[2]);
+ pattern = TclGetString(objv[1]);
TclGetNamespaceForQualName(interp, pattern, (Namespace *) NULL,
/*flags*/ 0, &nsPtr, &dummy1NsPtr, &dummy2NsPtr,
&simplePattern);
- if (nsPtr != NULL) { /* we successfully found the pattern's ns */
+ if (nsPtr != NULL) { /* We successfully found the pattern's ns. */
specificNsInPattern = (strcmp(simplePattern, pattern) != 0);
}
} else {
- Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
- return TCL_ERROR;
+ Tcl_WrongNumArgs(interp, 1, objv, "?pattern?");
+ return TCL_ERROR;
}
if (nsPtr == NULL) {
@@ -1924,13 +1716,13 @@ InfoProcsCmd(dummy, interp, objc, objv)
}
/*
- * Scan through the effective namespace's command table and create a
- * list with all procs that match the pattern. If a specific
- * namespace was requested in the pattern, qualify the command names
- * with the namespace name.
+ * Scan through the effective namespace's command table and create a list
+ * with all procs that match the pattern. If a specific namespace was
+ * requested in the pattern, qualify the command names with the namespace
+ * name.
*/
- listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+ listPtr = Tcl_NewListObj(0, NULL);
#ifndef INFO_PROCS_SEARCH_GLOBAL_NS
if (simplePattern != NULL && TclMatchIsTrivial(simplePattern)) {
entryPtr = Tcl_FindHashEntry(&nsPtr->cmdTable, simplePattern);
@@ -1944,7 +1736,7 @@ InfoProcsCmd(dummy, interp, objc, objv)
goto simpleProcOK;
}
} else {
- simpleProcOK:
+ simpleProcOK:
if (specificNsInPattern) {
elemObjPtr = Tcl_NewObj();
Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr,
@@ -1962,7 +1754,7 @@ InfoProcsCmd(dummy, interp, objc, objv)
while (entryPtr != NULL) {
cmdName = Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr);
if ((simplePattern == NULL)
- || Tcl_StringMatch(cmdName, simplePattern)) {
+ || Tcl_StringMatch(cmdName, simplePattern)) {
cmdPtr = (Command *) Tcl_GetHashValue(entryPtr);
if (!TclIsProc(cmdPtr)) {
@@ -1972,7 +1764,7 @@ InfoProcsCmd(dummy, interp, objc, objv)
goto procOK;
}
} else {
- procOK:
+ procOK:
if (specificNsInPattern) {
elemObjPtr = Tcl_NewObj();
Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr,
@@ -1988,35 +1780,36 @@ InfoProcsCmd(dummy, interp, objc, objv)
/*
* If the effective namespace isn't the global :: namespace, and a
- * specific namespace wasn't requested in the pattern, then add in
- * all global :: procs that match the simple pattern. Of course,
- * we add in only those procs that aren't hidden by a proc in
- * the effective namespace.
+ * specific namespace wasn't requested in the pattern, then add in all
+ * global :: procs that match the simple pattern. Of course, we add in
+ * only those procs that aren't hidden by a proc in the effective
+ * namespace.
*/
#ifdef INFO_PROCS_SEARCH_GLOBAL_NS
/*
- * If "info procs" worked like "info commands", returning the
- * commands also seen in the global namespace, then you would
- * include this code. As this could break backwards compatibilty
- * with 8.0-8.2, we decided not to "fix" it in 8.3, leaving the
- * behavior slightly different.
+ * If "info procs" worked like "info commands", returning the commands
+ * also seen in the global namespace, then you would include this
+ * code. As this could break backwards compatibilty with 8.0-8.2, we
+ * decided not to "fix" it in 8.3, leaving the behavior slightly
+ * different.
*/
+
if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
entryPtr = Tcl_FirstHashEntry(&globalNsPtr->cmdTable, &search);
while (entryPtr != NULL) {
cmdName = Tcl_GetHashKey(&globalNsPtr->cmdTable, entryPtr);
if ((simplePattern == NULL)
- || Tcl_StringMatch(cmdName, simplePattern)) {
- if (Tcl_FindHashEntry(&nsPtr->cmdTable, cmdName) == NULL) {
+ || Tcl_StringMatch(cmdName, simplePattern)) {
+ if (Tcl_FindHashEntry(&nsPtr->cmdTable,cmdName) == NULL) {
cmdPtr = (Command *) Tcl_GetHashValue(entryPtr);
realCmdPtr = (Command *) TclGetOriginalCommand(
- (Tcl_Command) cmdPtr);
+ (Tcl_Command) cmdPtr);
if (TclIsProc(cmdPtr) || ((realCmdPtr != NULL)
&& TclIsProc(realCmdPtr))) {
Tcl_ListObjAppendElement(interp, listPtr,
- Tcl_NewStringObj(cmdName, -1));
+ Tcl_NewStringObj(cmdName, -1));
}
}
}
@@ -2035,47 +1828,46 @@ InfoProcsCmd(dummy, interp, objc, objv)
*
* InfoScriptCmd --
*
- * Called to implement the "info script" command that returns the
- * script file that is currently being evaluated. Handles the
- * following syntax:
+ * Called to implement the "info script" command that returns the script
+ * file that is currently being evaluated. Handles the following syntax:
*
- * info script ?newName?
+ * info script ?newName?
*
* If newName is specified, it will set that as the internal name.
*
* Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
*
* Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message. It may change the
- * internal script filename.
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message. It may change the internal
+ * script filename.
*
*----------------------------------------------------------------------
*/
static int
-InfoScriptCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+InfoScriptCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
Interp *iPtr = (Interp *) interp;
- if ((objc != 2) && (objc != 3)) {
- Tcl_WrongNumArgs(interp, 2, objv, "?filename?");
- return TCL_ERROR;
+ if ((objc != 1) && (objc != 2)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "?filename?");
+ return TCL_ERROR;
}
- if (objc == 3) {
+ if (objc == 2) {
if (iPtr->scriptFile != NULL) {
Tcl_DecrRefCount(iPtr->scriptFile);
}
- iPtr->scriptFile = objv[2];
+ iPtr->scriptFile = objv[1];
Tcl_IncrRefCount(iPtr->scriptFile);
}
if (iPtr->scriptFile != NULL) {
- Tcl_SetObjResult(interp, iPtr->scriptFile);
+ Tcl_SetObjResult(interp, iPtr->scriptFile);
}
return TCL_OK;
}
@@ -2085,36 +1877,36 @@ InfoScriptCmd(dummy, interp, objc, objv)
*
* InfoSharedlibCmd --
*
- * Called to implement the "info sharedlibextension" command that
- * returns the file extension used for shared libraries. Handles the
- * following syntax:
+ * Called to implement the "info sharedlibextension" command that returns
+ * the file extension used for shared libraries. Handles the following
+ * syntax:
*
- * info sharedlibextension
+ * info sharedlibextension
*
* Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
*
* Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-InfoSharedlibCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+InfoSharedlibCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- return TCL_ERROR;
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, NULL);
+ return TCL_ERROR;
}
-
+
#ifdef TCL_SHLIB_EXT
- Tcl_SetStringObj(Tcl_GetObjResult(interp), TCL_SHLIB_EXT, -1);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(TCL_SHLIB_EXT, -1));
#endif
return TCL_OK;
}
@@ -2124,40 +1916,40 @@ InfoSharedlibCmd(dummy, interp, objc, objv)
*
* InfoTclVersionCmd --
*
- * Called to implement the "info tclversion" command that returns the
- * version number for this Tcl library. Handles the following syntax:
+ * Called to implement the "info tclversion" command that returns the
+ * version number for this Tcl library. Handles the following syntax:
*
- * info tclversion
+ * info tclversion
*
* Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
*
* Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-InfoTclVersionCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+InfoTclVersionCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
- CONST char *version;
+ Tcl_Obj *version;
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- return TCL_ERROR;
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, NULL);
+ return TCL_ERROR;
}
- version = Tcl_GetVar(interp, "tcl_version",
- (TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
+ version = Tcl_GetVar2Ex(interp, "tcl_version", NULL,
+ (TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
if (version != NULL) {
- Tcl_SetStringObj(Tcl_GetObjResult(interp), version, -1);
- return TCL_OK;
+ Tcl_SetObjResult(interp, version);
+ return TCL_OK;
}
return TCL_ERROR;
}
@@ -2165,204 +1957,67 @@ InfoTclVersionCmd(dummy, interp, objc, objv)
/*
*----------------------------------------------------------------------
*
- * InfoVarsCmd --
- *
- * Called to implement the "info vars" command that returns the
- * list of variables in the interpreter that match an optional pattern.
- * The pattern, if any, consists of an optional sequence of namespace
- * names separated by "::" qualifiers, which is followed by a
- * glob-style pattern that restricts which variables are returned.
- * Handles the following syntax:
+ * Tcl_JoinObjCmd --
*
- * info vars ?pattern?
+ * This procedure is invoked to process the "join" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
- * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ * A standard Tcl object result.
*
* Side effects:
- * Returns a result in the interpreter's result object. If there is
- * an error, the result is an error message.
+ * See the user documentation.
*
*----------------------------------------------------------------------
*/
-static int
-InfoVarsCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+int
+Tcl_JoinObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* The argument objects. */
{
- Interp *iPtr = (Interp *) interp;
- char *varName, *pattern;
- CONST char *simplePattern;
- register Tcl_HashEntry *entryPtr;
- Tcl_HashSearch search;
- Var *varPtr;
- Namespace *nsPtr;
- Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
- Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
- Tcl_Obj *listPtr, *elemObjPtr;
- int specificNsInPattern = 0; /* Init. to avoid compiler warning. */
-
- /*
- * Get the pattern and find the "effective namespace" in which to
- * list variables. We only use this effective namespace if there's
- * no active Tcl procedure frame.
- */
-
- if (objc == 2) {
- simplePattern = NULL;
- nsPtr = currNsPtr;
- specificNsInPattern = 0;
- } else if (objc == 3) {
- /*
- * From the pattern, get the effective namespace and the simple
- * pattern (no namespace qualifiers or ::'s) at the end. If an
- * error was found while parsing the pattern, return it. Otherwise,
- * if the namespace wasn't found, just leave nsPtr NULL: we will
- * return an empty list since no variables there can be found.
- */
+ int listLen, i;
+ Tcl_Obj *resObjPtr, *joinObjPtr, **elemPtrs;
- Namespace *dummy1NsPtr, *dummy2NsPtr;
-
- pattern = Tcl_GetString(objv[2]);
- TclGetNamespaceForQualName(interp, pattern, (Namespace *) NULL,
- /*flags*/ 0, &nsPtr, &dummy1NsPtr, &dummy2NsPtr,
- &simplePattern);
-
- if (nsPtr != NULL) { /* we successfully found the pattern's ns */
- specificNsInPattern = (strcmp(simplePattern, pattern) != 0);
- }
- } else {
- Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
- return TCL_ERROR;
+ if ((objc < 2) || (objc > 3)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "list ?joinString?");
+ return TCL_ERROR;
}
/*
- * If the namespace specified in the pattern wasn't found, just return.
+ * Make sure the list argument is a list object and get its length and a
+ * pointer to its array of element pointers.
*/
- if (nsPtr == NULL) {
- return TCL_OK;
+ if (TclListObjGetElements(interp, objv[1], &listLen,
+ &elemPtrs) != TCL_OK) {
+ return TCL_ERROR;
}
-
- listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
-
- if ((iPtr->varFramePtr == NULL)
- || !iPtr->varFramePtr->isProcCallFrame
- || specificNsInPattern) {
- /*
- * There is no frame pointer, the frame pointer was pushed only
- * to activate a namespace, or we are in a procedure call frame
- * but a specific namespace was specified. Create a list containing
- * only the variables in the effective namespace's variable table.
- */
-
- if (simplePattern != NULL && TclMatchIsTrivial(simplePattern)) {
- /*
- * If we can just do hash lookups, that simplifies things
- * a lot.
- */
- entryPtr = Tcl_FindHashEntry(&nsPtr->varTable, simplePattern);
- if (entryPtr != NULL) {
- varPtr = (Var *) Tcl_GetHashValue(entryPtr);
- if (!TclIsVarUndefined(varPtr)
- || (varPtr->flags & VAR_NAMESPACE_VAR)) {
- if (specificNsInPattern) {
- elemObjPtr = Tcl_NewObj();
- Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr,
- elemObjPtr);
- } else {
- elemObjPtr = Tcl_NewStringObj(simplePattern, -1);
- }
- Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
- }
- } else if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
- entryPtr = Tcl_FindHashEntry(&globalNsPtr->varTable,
- simplePattern);
- if (entryPtr != NULL) {
- varPtr = (Var *) Tcl_GetHashValue(entryPtr);
- if (!TclIsVarUndefined(varPtr)
- || (varPtr->flags & VAR_NAMESPACE_VAR)) {
- Tcl_ListObjAppendElement(interp, listPtr,
- Tcl_NewStringObj(simplePattern, -1));
- }
- }
- }
- } else {
- /*
- * Have to scan the tables of variables.
- */
+ joinObjPtr = (objc == 2) ? Tcl_NewStringObj(" ", 1) : objv[2];
+ Tcl_IncrRefCount(joinObjPtr);
- entryPtr = Tcl_FirstHashEntry(&nsPtr->varTable, &search);
- while (entryPtr != NULL) {
- varPtr = (Var *) Tcl_GetHashValue(entryPtr);
- if (!TclIsVarUndefined(varPtr)
- || (varPtr->flags & VAR_NAMESPACE_VAR)) {
- varName = Tcl_GetHashKey(&nsPtr->varTable, entryPtr);
- if ((simplePattern == NULL)
- || Tcl_StringMatch(varName, simplePattern)) {
- if (specificNsInPattern) {
- elemObjPtr = Tcl_NewObj();
- Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr,
- elemObjPtr);
- } else {
- elemObjPtr = Tcl_NewStringObj(varName, -1);
- }
- Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
- }
- }
- entryPtr = Tcl_NextHashEntry(&search);
- }
-
- /*
- * If the effective namespace isn't the global ::
- * namespace, and a specific namespace wasn't requested in
- * the pattern (i.e., the pattern only specifies variable
- * names), then add in all global :: variables that match
- * the simple pattern. Of course, add in only those
- * variables that aren't hidden by a variable in the
- * effective namespace.
- */
-
- if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
- entryPtr = Tcl_FirstHashEntry(&globalNsPtr->varTable, &search);
- while (entryPtr != NULL) {
- varPtr = (Var *) Tcl_GetHashValue(entryPtr);
- if (!TclIsVarUndefined(varPtr)
- || (varPtr->flags & VAR_NAMESPACE_VAR)) {
- varName = Tcl_GetHashKey(&globalNsPtr->varTable,
- entryPtr);
- if ((simplePattern == NULL)
- || Tcl_StringMatch(varName, simplePattern)) {
- if (Tcl_FindHashEntry(&nsPtr->varTable,
- varName) == NULL) {
- Tcl_ListObjAppendElement(interp, listPtr,
- Tcl_NewStringObj(varName, -1));
- }
- }
- }
- entryPtr = Tcl_NextHashEntry(&search);
- }
- }
+ resObjPtr = Tcl_NewObj();
+ for (i = 0; i < listLen; i++) {
+ if (i > 0) {
+ Tcl_AppendObjToObj(resObjPtr, joinObjPtr);
}
- } else if (((Interp *)interp)->varFramePtr->procPtr != NULL) {
- AppendLocals(interp, listPtr, simplePattern, 1);
+ Tcl_AppendObjToObj(resObjPtr, elemPtrs[i]);
}
-
- Tcl_SetObjResult(interp, listPtr);
+ Tcl_DecrRefCount(joinObjPtr);
+ Tcl_SetObjResult(interp, resObjPtr);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * Tcl_JoinObjCmd --
+ * Tcl_LassignObjCmd --
*
- * This procedure is invoked to process the "join" Tcl command.
- * See the user documentation for details on what it does.
+ * This object-based procedure is invoked to process the "lassign" Tcl
+ * command. See the user documentation for details on what it does.
*
* Results:
* A standard Tcl object result.
@@ -2373,54 +2028,59 @@ InfoVarsCmd(dummy, interp, objc, objv)
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
int
-Tcl_JoinObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* The argument objects. */
+Tcl_LassignObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
- char *joinString, *bytes;
- int joinLength, listLen, length, i, result;
- Tcl_Obj **elemPtrs;
- Tcl_Obj *resObjPtr;
+ Tcl_Obj *listCopyPtr;
+ Tcl_Obj **listObjv; /* The contents of the list. */
+ int listObjc; /* The length of the list. */
+ int code = TCL_OK;
- if (objc == 2) {
- joinString = " ";
- joinLength = 1;
- } else if (objc == 3) {
- joinString = Tcl_GetStringFromObj(objv[2], &joinLength);
- } else {
- Tcl_WrongNumArgs(interp, 1, objv, "list ?joinString?");
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "list varName ?varName ...?");
return TCL_ERROR;
}
- /*
- * Make sure the list argument is a list object and get its length and
- * a pointer to its array of element pointers.
- */
-
- result = Tcl_ListObjGetElements(interp, objv[1], &listLen, &elemPtrs);
- if (result != TCL_OK) {
- return result;
+ listCopyPtr = TclListObjCopy(interp, objv[1]);
+ if (listCopyPtr == NULL) {
+ return TCL_ERROR;
}
- /*
- * Now concatenate strings to form the "joined" result. We append
- * directly into the interpreter's result object.
- */
+ TclListObjGetElements(NULL, listCopyPtr, &listObjc, &listObjv);
- resObjPtr = Tcl_GetObjResult(interp);
+ objc -= 2;
+ objv += 2;
+ while (code == TCL_OK && objc > 0 && listObjc > 0) {
+ if (NULL == Tcl_ObjSetVar2(interp, *objv++, NULL,
+ *listObjv++, TCL_LEAVE_ERR_MSG)) {
+ code = TCL_ERROR;
+ }
+ objc--; listObjc--;
+ }
- for (i = 0; i < listLen; i++) {
- bytes = Tcl_GetStringFromObj(elemPtrs[i], &length);
- if (i > 0) {
- Tcl_AppendToObj(resObjPtr, joinString, joinLength);
+ if (code == TCL_OK && objc > 0) {
+ Tcl_Obj *emptyObj;
+ TclNewObj(emptyObj);
+ Tcl_IncrRefCount(emptyObj);
+ while (code == TCL_OK && objc-- > 0) {
+ if (NULL == Tcl_ObjSetVar2(interp, *objv++, NULL,
+ emptyObj, TCL_LEAVE_ERR_MSG)) {
+ code = TCL_ERROR;
+ }
}
- Tcl_AppendToObj(resObjPtr, bytes, length);
+ Tcl_DecrRefCount(emptyObj);
}
- return TCL_OK;
+
+ if (code == TCL_OK && listObjc > 0) {
+ Tcl_SetObjResult(interp, Tcl_NewListObj(listObjc, listObjv));
+ }
+
+ Tcl_DecrRefCount(listCopyPtr);
+ return code;
}
/*
@@ -2440,16 +2100,15 @@ Tcl_JoinObjCmd(dummy, interp, objc, objv)
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
int
-Tcl_LindexObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_LindexObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
- Tcl_Obj *elemPtr; /* Pointer to the element being extracted */
+ Tcl_Obj *elemPtr; /* Pointer to the element being extracted. */
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "list ?index...?");
@@ -2457,31 +2116,27 @@ Tcl_LindexObjCmd(dummy, interp, objc, objv)
}
/*
- * If objc == 3, then objv[ 2 ] may be either a single index or
- * a list of indices: go to TclLindexList to determine which.
- * If objc >= 4, or objc == 2, then objv[ 2 .. objc-2 ] are all
- * single indices and processed as such in TclLindexFlat.
+ * If objc==3, then objv[2] may be either a single index or a list of
+ * indices: go to TclLindexList to determine which. If objc>=4, or
+ * objc==2, then objv[2 .. objc-2] are all single indices and processed as
+ * such in TclLindexFlat.
*/
- if ( objc == 3 ) {
-
- elemPtr = TclLindexList( interp, objv[ 1 ], objv[ 2 ] );
-
+ if (objc == 3) {
+ elemPtr = TclLindexList(interp, objv[1], objv[2]);
} else {
-
- elemPtr = TclLindexFlat( interp, objv[ 1 ], objc-2, objv+2 );
-
+ elemPtr = TclLindexFlat(interp, objv[1], objc-2, objv+2);
}
-
+
/*
- * Set the interpreter's object result to the last element extracted
+ * Set the interpreter's object result to the last element extracted.
*/
- if ( elemPtr == NULL ) {
+ if (elemPtr == NULL) {
return TCL_ERROR;
} else {
Tcl_SetObjResult(interp, elemPtr);
- Tcl_DecrRefCount( elemPtr );
+ Tcl_DecrRefCount(elemPtr);
return TCL_OK;
}
}
@@ -2489,306 +2144,14 @@ Tcl_LindexObjCmd(dummy, interp, objc, objv)
/*
*----------------------------------------------------------------------
*
- * TclLindexList --
- *
- * This procedure handles the 'lindex' command when objc==3.
- *
- * Results:
- * Returns a pointer to the object extracted, or NULL if an
- * error occurred.
- *
- * Side effects:
- * None.
- *
- * If objv[1] can be parsed as a list, TclLindexList handles extraction
- * of the desired element locally. Otherwise, it invokes
- * TclLindexFlat to treat objv[1] as a scalar.
- *
- * The reference count of the returned object includes one reference
- * corresponding to the pointer returned. Thus, the calling code will
- * usually do something like:
- * Tcl_SetObjResult( interp, result );
- * Tcl_DecrRefCount( result );
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_Obj *
-TclLindexList( interp, listPtr, argPtr )
- Tcl_Interp* interp; /* Tcl interpreter */
- Tcl_Obj* listPtr; /* List being unpacked */
- Tcl_Obj* argPtr; /* Index or index list */
-{
-
- Tcl_Obj **elemPtrs; /* Elements of the list being manipulated. */
- int listLen; /* Length of the list being manipulated. */
- int index; /* Index into the list */
- int result; /* Result returned from a Tcl library call */
- int i; /* Current index number */
- Tcl_Obj** indices; /* Array of list indices */
- int indexCount; /* Size of the array of list indices */
- Tcl_Obj* oldListPtr; /* Temp location to preserve the list
- * pointer when replacing it with a sublist */
-
- /*
- * Determine whether argPtr designates a list or a single index.
- * We have to be careful about the order of the checks to avoid
- * repeated shimmering; see TIP#22 and TIP#33 for the details.
- */
-
- if ( argPtr->typePtr != &tclListType
- && TclGetIntForIndex( NULL , argPtr, 0, &index ) == TCL_OK ) {
-
- /*
- * argPtr designates a single index.
- */
-
- return TclLindexFlat( interp, listPtr, 1, &argPtr );
-
- } else if ( Tcl_ListObjGetElements( NULL, argPtr, &indexCount, &indices )
- != TCL_OK ) {
-
- /*
- * argPtr designates something that is neither an index nor a
- * well-formed list. Report the error via TclLindexFlat.
- */
-
- return TclLindexFlat( interp, listPtr, 1, &argPtr );
- }
-
- /*
- * Record the reference to the list that we are maintaining in
- * the activation record.
- */
-
- Tcl_IncrRefCount( listPtr );
-
- /*
- * argPtr designates a list, and the 'else if' above has parsed it
- * into indexCount and indices.
- */
-
- for ( i = 0; i < indexCount; ++i ) {
-
- /*
- * Convert the current listPtr to a list if necessary.
- */
-
- result = Tcl_ListObjGetElements( interp, listPtr,
- &listLen, &elemPtrs);
- if (result != TCL_OK) {
- Tcl_DecrRefCount( listPtr );
- return NULL;
- }
-
- /*
- * Get the index from indices[ i ]
- */
-
- result = TclGetIntForIndex( interp, indices[ i ],
- /*endValue*/ (listLen - 1),
- &index );
- if ( result != TCL_OK ) {
- /*
- * Index could not be parsed
- */
-
- Tcl_DecrRefCount( listPtr );
- return NULL;
-
- } else if ( index < 0
- || index >= listLen ) {
- /*
- * Index is out of range
- */
- Tcl_DecrRefCount( listPtr );
- listPtr = Tcl_NewObj();
- Tcl_IncrRefCount( listPtr );
- return listPtr;
- }
-
- /*
- * Make sure listPtr still refers to a list object.
- * If it shared a Tcl_Obj structure with the arguments, then
- * it might have just been converted to something else.
- */
-
- if (listPtr->typePtr != &tclListType) {
- result = Tcl_ListObjGetElements(interp, listPtr, &listLen,
- &elemPtrs);
- if (result != TCL_OK) {
- Tcl_DecrRefCount( listPtr );
- return NULL;
- }
- }
-
- /*
- * Extract the pointer to the appropriate element
- */
-
- oldListPtr = listPtr;
- listPtr = elemPtrs[ index ];
- Tcl_IncrRefCount( listPtr );
- Tcl_DecrRefCount( oldListPtr );
-
- /*
- * The work we did above may have caused the internal rep
- * of *argPtr to change to something else. Get it back.
- */
-
- result = Tcl_ListObjGetElements( interp, argPtr,
- &indexCount, &indices );
- if ( result != TCL_OK ) {
- /*
- * This can't happen unless some extension corrupted a Tcl_Obj.
- */
- Tcl_DecrRefCount( listPtr );
- return NULL;
- }
-
- } /* end for */
-
- /*
- * Return the last object extracted. Its reference count will include
- * the reference being returned.
- */
-
- return listPtr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclLindexFlat --
- *
- * This procedure handles the 'lindex' command, given that the
- * arguments to the command are known to be a flat list.
- *
- * Results:
- * Returns a standard Tcl result.
- *
- * Side effects:
- * None.
- *
- * This procedure is called from either tclExecute.c or
- * Tcl_LindexObjCmd whenever either is presented with
- * objc == 2 or objc >= 4. It is also called from TclLindexList
- * for the objc==3 case once it is determined that objv[2] cannot
- * be parsed as a list.
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_Obj *
-TclLindexFlat( interp, listPtr, indexCount, indexArray )
- Tcl_Interp* interp; /* Tcl interpreter */
- Tcl_Obj* listPtr; /* Tcl object representing the list */
- int indexCount; /* Count of indices */
- Tcl_Obj* CONST indexArray[];
- /* Array of pointers to Tcl objects
- * representing the indices in the
- * list */
-{
-
- int i; /* Current list index */
- int result; /* Result of Tcl library calls */
- int listLen; /* Length of the current list being
- * processed */
- Tcl_Obj** elemPtrs; /* Array of pointers to the elements
- * of the current list */
- int index; /* Parsed version of the current element
- * of indexArray */
- Tcl_Obj* oldListPtr; /* Temporary to hold listPtr so that
- * its ref count can be decremented. */
-
- /*
- * Record the reference to the 'listPtr' object that we are
- * maintaining in the C activation record.
- */
-
- Tcl_IncrRefCount( listPtr );
-
- for ( i = 0; i < indexCount; ++i ) {
-
- /*
- * Convert the current listPtr to a list if necessary.
- */
-
- result = Tcl_ListObjGetElements(interp, listPtr,
- &listLen, &elemPtrs);
- if (result != TCL_OK) {
- Tcl_DecrRefCount( listPtr );
- return NULL;
- }
-
- /*
- * Get the index from objv[i]
- */
-
- result = TclGetIntForIndex( interp, indexArray[ i ],
- /*endValue*/ (listLen - 1),
- &index );
- if ( result != TCL_OK ) {
-
- /* Index could not be parsed */
-
- Tcl_DecrRefCount( listPtr );
- return NULL;
-
- } else if ( index < 0
- || index >= listLen ) {
-
- /*
- * Index is out of range
- */
-
- Tcl_DecrRefCount( listPtr );
- listPtr = Tcl_NewObj();
- Tcl_IncrRefCount( listPtr );
- return listPtr;
- }
-
- /*
- * Make sure listPtr still refers to a list object.
- * It might have been converted to something else above
- * if objv[1] overlaps with one of the other parameters.
- */
-
- if (listPtr->typePtr != &tclListType) {
- result = Tcl_ListObjGetElements(interp, listPtr, &listLen,
- &elemPtrs);
- if (result != TCL_OK) {
- Tcl_DecrRefCount( listPtr );
- return NULL;
- }
- }
-
- /*
- * Extract the pointer to the appropriate element
- */
-
- oldListPtr = listPtr;
- listPtr = elemPtrs[ index ];
- Tcl_IncrRefCount( listPtr );
- Tcl_DecrRefCount( oldListPtr );
-
- }
-
- return listPtr;
-
-}
-
-/*
- *----------------------------------------------------------------------
- *
* Tcl_LinsertObjCmd --
*
* This object-based procedure is invoked to process the "linsert" Tcl
* command. See the user documentation for details on what it does.
*
* Results:
- * A new Tcl list object formed by inserting zero or more elements
- * into a list.
+ * A new Tcl list object formed by inserting zero or more elements into a
+ * list.
*
* Side effects:
* See the user documentation.
@@ -2796,34 +2159,33 @@ TclLindexFlat( interp, listPtr, indexCount, indexArray )
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
int
-Tcl_LinsertObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- register int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_LinsertObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ register int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
Tcl_Obj *listPtr;
- int index, isDuplicate, len, result;
+ int index, len, result;
if (objc < 4) {
Tcl_WrongNumArgs(interp, 1, objv, "list index element ?element ...?");
return TCL_ERROR;
}
- result = Tcl_ListObjLength(interp, objv[1], &len);
+ result = TclListObjLength(interp, objv[1], &len);
if (result != TCL_OK) {
return result;
}
/*
- * Get the index. "end" is interpreted to be the index after the last
+ * Get the index. "end" is interpreted to be the index after the last
* element, such that using it will cause any inserted elements to be
* appended to the list.
*/
- result = TclGetIntForIndex(interp, objv[2], /*end*/ len, &index);
+ result = TclGetIntForIndexM(interp, objv[2], /*end*/ len, &index);
if (result != TCL_OK) {
return result;
}
@@ -2832,33 +2194,25 @@ Tcl_LinsertObjCmd(dummy, interp, objc, objv)
}
/*
- * If the list object is unshared we can modify it directly. Otherwise
- * we create a copy to modify: this is "copy on write".
+ * If the list object is unshared we can modify it directly. Otherwise we
+ * create a copy to modify: this is "copy on write".
*/
listPtr = objv[1];
- isDuplicate = 0;
if (Tcl_IsShared(listPtr)) {
- listPtr = Tcl_DuplicateObj(listPtr);
- isDuplicate = 1;
+ listPtr = TclListObjCopy(NULL, listPtr);
}
if ((objc == 4) && (index == len)) {
/*
* Special case: insert one element at the end of the list.
*/
- result = Tcl_ListObjAppendElement(interp, listPtr, objv[3]);
- } else if (objc > 3) {
- result = Tcl_ListObjReplace(interp, listPtr, index, 0,
- (objc-3), &(objv[3]));
- }
- if (result != TCL_OK) {
- if (isDuplicate) {
- Tcl_DecrRefCount(listPtr); /* free unneeded obj */
- }
- return result;
+
+ Tcl_ListObjAppendElement(NULL, listPtr, objv[3]);
+ } else {
+ Tcl_ListObjReplace(NULL, listPtr, index, 0, (objc-3), &(objv[3]));
}
-
+
/*
* Set the interpreter's object result.
*/
@@ -2872,8 +2226,8 @@ Tcl_LinsertObjCmd(dummy, interp, objc, objv)
*
* Tcl_ListObjCmd --
*
- * This procedure is invoked to process the "list" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "list" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl object result.
@@ -2884,21 +2238,21 @@ Tcl_LinsertObjCmd(dummy, interp, objc, objv)
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
int
-Tcl_ListObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- register int objc; /* Number of arguments. */
- register Tcl_Obj *CONST objv[]; /* The argument objects. */
+Tcl_ListObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ register int objc, /* Number of arguments. */
+ register Tcl_Obj *CONST objv[])
+ /* The argument objects. */
{
/*
* If there are no list elements, the result is an empty object.
- * Otherwise modify the interpreter's result object to be a list object.
+ * Otherwise set the interpreter's result object to be a list object.
*/
-
+
if (objc > 1) {
- Tcl_SetListObj(Tcl_GetObjResult(interp), (objc-1), &(objv[1]));
+ Tcl_SetObjResult(interp, Tcl_NewListObj((objc-1), &(objv[1])));
}
return TCL_OK;
}
@@ -2909,7 +2263,7 @@ Tcl_ListObjCmd(dummy, interp, objc, objv)
* Tcl_LlengthObjCmd --
*
* This object-based procedure is invoked to process the "llength" Tcl
- * command. See the user documentation for details on what it does.
+ * command. See the user documentation for details on what it does.
*
* Results:
* A standard Tcl object result.
@@ -2920,13 +2274,13 @@ Tcl_ListObjCmd(dummy, interp, objc, objv)
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
int
-Tcl_LlengthObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- register Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_LlengthObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ register Tcl_Obj *CONST objv[])
+ /* Argument objects. */
{
int listLen, result;
@@ -2935,17 +2289,17 @@ Tcl_LlengthObjCmd(dummy, interp, objc, objv)
return TCL_ERROR;
}
- result = Tcl_ListObjLength(interp, objv[1], &listLen);
+ result = TclListObjLength(interp, objv[1], &listLen);
if (result != TCL_OK) {
return result;
}
/*
* Set the interpreter's object result to an integer object holding the
- * length.
+ * length.
*/
- Tcl_SetIntObj(Tcl_GetObjResult(interp), listLen);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(listLen));
return TCL_OK;
}
@@ -2954,8 +2308,8 @@ Tcl_LlengthObjCmd(dummy, interp, objc, objv)
*
* Tcl_LrangeObjCmd --
*
- * This procedure is invoked to process the "lrange" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "lrange" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl object result.
@@ -2966,17 +2320,16 @@ Tcl_LlengthObjCmd(dummy, interp, objc, objv)
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
int
-Tcl_LrangeObjCmd(notUsed, interp, objc, objv)
- ClientData notUsed; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- register Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_LrangeObjCmd(
+ ClientData notUsed, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ register Tcl_Obj *CONST objv[])
+ /* Argument objects. */
{
- Tcl_Obj *listPtr;
- Tcl_Obj **elemPtrs;
- int listLen, first, last, numElems, result;
+ Tcl_Obj *listPtr, **elemPtrs;
+ int listLen, first, result;
if (objc != 4) {
Tcl_WrongNumArgs(interp, 1, objv, "list first last");
@@ -2984,62 +2337,143 @@ Tcl_LrangeObjCmd(notUsed, interp, objc, objv)
}
/*
- * Make sure the list argument is a list object and get its length and
- * a pointer to its array of element pointers.
+ * Make sure the list argument is a list object and get its length and a
+ * pointer to its array of element pointers.
*/
- listPtr = objv[1];
- result = Tcl_ListObjGetElements(interp, listPtr, &listLen, &elemPtrs);
- if (result != TCL_OK) {
- return result;
+ listPtr = TclListObjCopy(interp, objv[1]);
+ if (listPtr == NULL) {
+ return TCL_ERROR;
}
+ TclListObjGetElements(NULL, listPtr, &listLen, &elemPtrs);
- /*
- * Get the first and last indexes.
- */
-
- result = TclGetIntForIndex(interp, objv[2], /*endValue*/ (listLen - 1),
+ result = TclGetIntForIndexM(interp, objv[2], /*endValue*/ listLen - 1,
&first);
- if (result != TCL_OK) {
- return result;
- }
- if (first < 0) {
- first = 0;
+ if (result == TCL_OK) {
+ int last;
+
+ if (first < 0) {
+ first = 0;
+ }
+
+ result = TclGetIntForIndexM(interp, objv[3], /*endValue*/ listLen - 1,
+ &last);
+ if (result == TCL_OK) {
+ if (last >= listLen) {
+ last = (listLen - 1);
+ }
+
+ if (first <= last) {
+ int numElems = (last - first + 1);
+
+ Tcl_SetObjResult(interp,
+ Tcl_NewListObj(numElems, &(elemPtrs[first])));
+ }
+ }
}
- result = TclGetIntForIndex(interp, objv[3], /*endValue*/ (listLen - 1),
- &last);
- if (result != TCL_OK) {
- return result;
+ Tcl_DecrRefCount(listPtr);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LrepeatObjCmd --
+ *
+ * This procedure is invoked to process the "lrepeat" Tcl command. See
+ * the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl object result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_LrepeatObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ register int objc, /* Number of arguments. */
+ register Tcl_Obj *CONST objv[])
+ /* The argument objects. */
+{
+ int elementCount, i, totalElems;
+ Tcl_Obj *listPtr, **dataArray;
+ List *listRepPtr;
+
+ /*
+ * Check arguments for legality:
+ * lrepeat posInt value ?value ...?
+ */
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "positiveCount value ?value ...?");
+ return TCL_ERROR;
}
- if (last >= listLen) {
- last = (listLen - 1);
+ if (TCL_ERROR == TclGetIntFromObj(interp, objv[1], &elementCount)) {
+ return TCL_ERROR;
}
-
- if (first > last) {
- return TCL_OK; /* the result is an empty object */
+ if (elementCount < 1) {
+ Tcl_AppendResult(interp, "must have a count of at least 1", NULL);
+ return TCL_ERROR;
}
/*
- * Make sure listPtr still refers to a list object. It might have been
- * converted to an int above if the argument objects were shared.
- */
+ * Skip forward to the interesting arguments now we've finished parsing.
+ */
+
+ objc -= 2;
+ objv += 2;
- if (listPtr->typePtr != &tclListType) {
- result = Tcl_ListObjGetElements(interp, listPtr, &listLen,
- &elemPtrs);
- if (result != TCL_OK) {
- return result;
- }
+ /* Final sanity check. Do not exceed limits on max list length. */
+
+ if (objc > LIST_MAX/elementCount) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "max length of a Tcl list (%d elements) exceeded", LIST_MAX));
+ return TCL_ERROR;
}
+ totalElems = objc * elementCount;
/*
- * Extract a range of fields. We modify the interpreter's result object
- * to be a list object containing the specified elements.
+ * Get an empty list object that is allocated large enough to hold each
+ * init value elementCount times.
*/
- numElems = (last - first + 1);
- Tcl_SetListObj(Tcl_GetObjResult(interp), numElems, &(elemPtrs[first]));
+ listPtr = Tcl_NewListObj(totalElems, NULL);
+ listRepPtr = ListRepPtr(listPtr);
+ listRepPtr->elemCount = elementCount*objc;
+ dataArray = &listRepPtr->elements;
+
+ /*
+ * Set the elements. Note that we handle the common degenerate case of a
+ * single value being repeated separately to permit the compiler as much
+ * room as possible to optimize a loop that might be run a very large
+ * number of times.
+ */
+
+ if (objc == 1) {
+ register Tcl_Obj *tmpPtr = objv[0];
+
+ tmpPtr->refCount += elementCount;
+ for (i=0 ; i<elementCount ; i++) {
+ dataArray[i] = tmpPtr;
+ }
+ } else {
+ int j, k = 0;
+
+ for (i=0 ; i<elementCount ; i++) {
+ for (j=0 ; j<objc ; j++) {
+ Tcl_IncrRefCount(objv[j]);
+ dataArray[k++] = objv[j];
+ }
+ }
+ }
+
+ Tcl_SetObjResult(interp, listPtr);
return TCL_OK;
}
@@ -3048,12 +2482,12 @@ Tcl_LrangeObjCmd(notUsed, interp, objc, objv)
*
* Tcl_LreplaceObjCmd --
*
- * This object-based procedure is invoked to process the "lreplace"
- * Tcl command. See the user documentation for details on what it does.
+ * This object-based procedure is invoked to process the "lreplace" Tcl
+ * command. See the user documentation for details on what it does.
*
* Results:
- * A new Tcl list object formed by replacing zero or more elements of
- * a list.
+ * A new Tcl list object formed by replacing zero or more elements of a
+ * list.
*
* Side effects:
* See the user documentation.
@@ -3061,16 +2495,15 @@ Tcl_LrangeObjCmd(notUsed, interp, objc, objv)
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
int
-Tcl_LreplaceObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_LreplaceObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
register Tcl_Obj *listPtr;
- int isDuplicate, first, last, listLen, numToDelete, result;
+ int first, last, listLen, numToDelete, result;
if (objc < 4) {
Tcl_WrongNumArgs(interp, 1, objv,
@@ -3078,42 +2511,41 @@ Tcl_LreplaceObjCmd(dummy, interp, objc, objv)
return TCL_ERROR;
}
- result = Tcl_ListObjLength(interp, objv[1], &listLen);
+ result = TclListObjLength(interp, objv[1], &listLen);
if (result != TCL_OK) {
return result;
}
/*
- * Get the first and last indexes. "end" is interpreted to be the index
- * for the last element, such that using it will cause that element to
- * be included for deletion.
+ * Get the first and last indexes. "end" is interpreted to be the index
+ * for the last element, such that using it will cause that element to be
+ * included for deletion.
*/
- result = TclGetIntForIndex(interp, objv[2], /*end*/ (listLen - 1), &first);
+ result = TclGetIntForIndexM(interp, objv[2], /*end*/ listLen-1, &first);
if (result != TCL_OK) {
return result;
}
- result = TclGetIntForIndex(interp, objv[3], /*end*/ (listLen - 1), &last);
+ result = TclGetIntForIndexM(interp, objv[3], /*end*/ listLen-1, &last);
if (result != TCL_OK) {
return result;
}
- if (first < 0) {
+ if (first < 0) {
first = 0;
}
/*
* Complain if the user asked for a start element that is greater than the
- * list length. This won't ever trigger for the "end*" case as that will
+ * list length. This won't ever trigger for the "end-*" case as that will
* be properly constrained by TclGetIntForIndex because we use listLen-1
* (to allow for replacing the last elem).
*/
if ((first >= listLen) && (listLen > 0)) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "list doesn't contain element ",
- Tcl_GetString(objv[2]), (int *) NULL);
+ Tcl_AppendResult(interp, "list doesn't contain element ",
+ TclGetString(objv[2]), NULL);
return TCL_ERROR;
}
if (last >= listLen) {
@@ -3126,35 +2558,109 @@ Tcl_LreplaceObjCmd(dummy, interp, objc, objv)
}
/*
- * If the list object is unshared we can modify it directly, otherwise
- * we create a copy to modify: this is "copy on write".
+ * If the list object is unshared we can modify it directly, otherwise we
+ * create a copy to modify: this is "copy on write".
*/
listPtr = objv[1];
- isDuplicate = 0;
if (Tcl_IsShared(listPtr)) {
- listPtr = Tcl_DuplicateObj(listPtr);
- isDuplicate = 1;
+ listPtr = TclListObjCopy(NULL, listPtr);
}
- if (objc > 4) {
- result = Tcl_ListObjReplace(interp, listPtr, first, numToDelete,
- (objc-4), &(objv[4]));
- } else {
- result = Tcl_ListObjReplace(interp, listPtr, first, numToDelete,
- 0, NULL);
+
+ /*
+ * Note that we call Tcl_ListObjReplace even when numToDelete == 0 and
+ * objc == 4. In this case, the list value of listPtr is not changed (no
+ * elements are removed or added), but by making the call we are assured
+ * we end up with a list in canonical form. Resist any temptation to
+ * optimize this case away.
+ */
+
+ Tcl_ListObjReplace(NULL, listPtr, first, numToDelete, objc-4, &(objv[4]));
+
+ /*
+ * Set the interpreter's object result.
+ */
+
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LreverseObjCmd --
+ *
+ * This procedure is invoked to process the "lreverse" Tcl command. See
+ * the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_LreverseObjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument values. */
+{
+ Tcl_Obj **elemv;
+ int elemc, i, j;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "list");
+ return TCL_ERROR;
}
- if (result != TCL_OK) {
- if (isDuplicate) {
- Tcl_DecrRefCount(listPtr); /* free unneeded obj */
- }
- return result;
+ if (TclListObjGetElements(interp, objv[1], &elemc, &elemv) != TCL_OK) {
+ return TCL_ERROR;
}
/*
- * Set the interpreter's object result.
+ * If the list is empty, just return it [Bug 1876793]
*/
- Tcl_SetObjResult(interp, listPtr);
+ if (!elemc) {
+ Tcl_SetObjResult(interp, objv[1]);
+ return TCL_OK;
+ }
+
+ if (Tcl_IsShared(objv[1])
+ || (ListRepPtr(objv[1])->refCount > 1)) { /* Bug 1675044 */
+ Tcl_Obj *resultObj, **dataArray;
+ List *listRepPtr;
+
+ resultObj = Tcl_NewListObj(elemc, NULL);
+ listRepPtr = ListRepPtr(resultObj);
+ listRepPtr->elemCount = elemc;
+ dataArray = &listRepPtr->elements;
+
+ for (i=0,j=elemc-1 ; i<elemc ; i++,j--) {
+ dataArray[j] = elemv[i];
+ Tcl_IncrRefCount(elemv[i]);
+ }
+
+ Tcl_SetObjResult(interp, resultObj);
+ } else {
+
+ /*
+ * Not shared, so swap "in place". This relies on Tcl_LOGE above
+ * returning a pointer to the live array of Tcl_Obj values.
+ */
+
+ for (i=0,j=elemc-1 ; i<j ; i++,j--) {
+ Tcl_Obj *tmp = elemv[i];
+
+ elemv[i] = elemv[j];
+ elemv[j] = tmp;
+ }
+ TclInvalidateStringRep(objv[1]);
+ Tcl_SetObjResult(interp, objv[1]);
+ }
return TCL_OK;
}
@@ -3163,8 +2669,8 @@ Tcl_LreplaceObjCmd(dummy, interp, objc, objv)
*
* Tcl_LsearchObjCmd --
*
- * This procedure is invoked to process the "lsearch" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "lsearch" Tcl command. See
+ * the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -3176,30 +2682,34 @@ Tcl_LreplaceObjCmd(dummy, interp, objc, objv)
*/
int
-Tcl_LsearchObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument values. */
+Tcl_LsearchObjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument values. */
{
char *bytes, *patternBytes;
int i, match, mode, index, result, listc, length, elemLen;
- int dataType, isIncreasing, lower, upper, patInt, objInt;
- int offset, allMatches, inlineReturn, negatedMatch;
+ int dataType, isIncreasing, lower, upper, patInt, objInt, offset;
+ int allMatches, inlineReturn, negatedMatch, returnSubindices, noCase;
double patDouble, objDouble;
- Tcl_Obj *patObj, **listv, *listPtr, *startPtr;
+ SortInfo sortInfo;
+ Tcl_Obj *patObj, **listv, *listPtr, *startPtr, *itemPtr;
+ SortStrCmpFn_t strCmpFn = strcmp;
Tcl_RegExp regexp = NULL;
static CONST char *options[] = {
- "-all", "-ascii", "-decreasing", "-dictionary",
- "-exact", "-glob", "-increasing", "-inline",
- "-integer", "-not", "-real", "-regexp",
- "-sorted", "-start", NULL
+ "-all", "-ascii", "-decreasing", "-dictionary",
+ "-exact", "-glob", "-increasing", "-index",
+ "-inline", "-integer", "-nocase", "-not",
+ "-real", "-regexp", "-sorted", "-start",
+ "-subindices", NULL
};
enum options {
LSEARCH_ALL, LSEARCH_ASCII, LSEARCH_DECREASING, LSEARCH_DICTIONARY,
- LSEARCH_EXACT, LSEARCH_GLOB, LSEARCH_INCREASING, LSEARCH_INLINE,
- LSEARCH_INTEGER, LSEARCH_NOT, LSEARCH_REAL, LSEARCH_REGEXP,
- LSEARCH_SORTED, LSEARCH_START
+ LSEARCH_EXACT, LSEARCH_GLOB, LSEARCH_INCREASING, LSEARCH_INDEX,
+ LSEARCH_INLINE, LSEARCH_INTEGER, LSEARCH_NOCASE, LSEARCH_NOT,
+ LSEARCH_REAL, LSEARCH_REGEXP, LSEARCH_SORTED, LSEARCH_START,
+ LSEARCH_SUBINDICES
};
enum datatypes {
ASCII, DICTIONARY, INTEGER, REAL
@@ -3213,10 +2723,19 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv)
isIncreasing = 1;
allMatches = 0;
inlineReturn = 0;
+ returnSubindices = 0;
negatedMatch = 0;
listPtr = NULL;
startPtr = NULL;
offset = 0;
+ noCase = 0;
+ sortInfo.compareCmdPtr = NULL;
+ sortInfo.isIncreasing = 1;
+ sortInfo.sortMode = 0;
+ sortInfo.interp = interp;
+ sortInfo.resultCode = TCL_OK;
+ sortInfo.indexv = NULL;
+ sortInfo.indexc = 0;
if (objc < 3) {
Tcl_WrongNumArgs(interp, 1, objv, "?options? list pattern");
@@ -3226,9 +2745,12 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv)
for (i = 1; i < objc-2; i++) {
if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0, &index)
!= TCL_OK) {
- if (startPtr) {
+ if (startPtr != NULL) {
Tcl_DecrRefCount(startPtr);
}
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
return TCL_ERROR;
}
switch ((enum options) index) {
@@ -3240,6 +2762,7 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv)
break;
case LSEARCH_DECREASING: /* -decreasing */
isIncreasing = 0;
+ sortInfo.isIncreasing = 0;
break;
case LSEARCH_DICTIONARY: /* -dictionary */
dataType = DICTIONARY;
@@ -3252,6 +2775,7 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv)
break;
case LSEARCH_INCREASING: /* -increasing */
isIncreasing = 1;
+ sortInfo.isIncreasing = 1;
break;
case LSEARCH_INLINE: /* -inline */
inlineReturn = 1;
@@ -3259,6 +2783,10 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv)
case LSEARCH_INTEGER: /* -integer */
dataType = INTEGER;
break;
+ case LSEARCH_NOCASE: /* -nocase */
+ strCmpFn = strcasecmp;
+ noCase = 1;
+ break;
case LSEARCH_NOT: /* -not */
negatedMatch = 1;
break;
@@ -3271,88 +2799,183 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv)
case LSEARCH_SORTED: /* -sorted */
mode = SORTED;
break;
+ case LSEARCH_SUBINDICES: /* -subindices */
+ returnSubindices = 1;
+ break;
case LSEARCH_START: /* -start */
/*
- * If there was a previous -start option, release its saved
- * index because it will either be replaced or there will be
- * an error.
+ * If there was a previous -start option, release its saved index
+ * because it will either be replaced or there will be an error.
*/
- if (startPtr) {
+
+ if (startPtr != NULL) {
Tcl_DecrRefCount(startPtr);
}
if (i > objc-4) {
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
Tcl_AppendResult(interp, "missing starting index", NULL);
return TCL_ERROR;
}
i++;
if (objv[i] == objv[objc - 2]) {
/*
- * Take copy to prevent shimmering problems. Note
- * that it does not matter if the index obj is also a
- * component of the list being searched. We only need
- * to copy where the list and the index are
- * one-and-the-same.
+ * Take copy to prevent shimmering problems. Note that it does
+ * not matter if the index obj is also a component of the list
+ * being searched. We only need to copy where the list and the
+ * index are one-and-the-same.
*/
+
startPtr = Tcl_DuplicateObj(objv[i]);
} else {
startPtr = objv[i];
Tcl_IncrRefCount(startPtr);
}
+ break;
+ case LSEARCH_INDEX: { /* -index */
+ Tcl_Obj **indices;
+ int j;
+
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ if (i > objc-4) {
+ if (startPtr != NULL) {
+ Tcl_DecrRefCount(startPtr);
+ }
+ Tcl_AppendResult(interp,
+ "\"-index\" option must be followed by list index",
+ NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Store the extracted indices for processing by sublist
+ * extraction. Note that we don't do this using objects because
+ * that has shimmering problems.
+ */
+
+ i++;
+ if (TclListObjGetElements(interp, objv[i],
+ &sortInfo.indexc, &indices) != TCL_OK) {
+ if (startPtr != NULL) {
+ Tcl_DecrRefCount(startPtr);
+ }
+ return TCL_ERROR;
+ }
+ switch (sortInfo.indexc) {
+ case 0:
+ sortInfo.indexv = NULL;
+ break;
+ case 1:
+ sortInfo.indexv = &sortInfo.singleIndex;
+ break;
+ default:
+ sortInfo.indexv = (int *)
+ ckalloc(sizeof(int) * sortInfo.indexc);
+ }
+
+ /*
+ * Fill the array by parsing each index. We don't know whether
+ * their scale is sensible yet, but we at least perform the
+ * syntactic check here.
+ */
+
+ for (j=0 ; j<sortInfo.indexc ; j++) {
+ if (TclGetIntForIndexM(interp, indices[j], SORTIDX_END,
+ &sortInfo.indexv[j]) != TCL_OK) {
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (-index option item number %d)", j));
+ return TCL_ERROR;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ /*
+ * Subindices only make sense if asked for with -index option set.
+ */
+
+ if (returnSubindices && sortInfo.indexc==0) {
+ if (startPtr != NULL) {
+ Tcl_DecrRefCount(startPtr);
}
+ Tcl_AppendResult(interp,
+ "-subindices cannot be used without -index option", NULL);
+ return TCL_ERROR;
}
if ((enum modes) mode == REGEXP) {
/*
* We can shimmer regexp/list if listv[i] == pattern, so get the
* regexp rep before the list rep. First time round, omit the interp
- * and hope that the compilation will succeed. If it fails, we'll
- * recompile in "expensive" mode with a place to put error messages.
+ * and hope that the compilation will succeed. If it fails, we'll
+ * recompile in "expensive" mode with a place to put error messages.
*/
regexp = Tcl_GetRegExpFromObj(NULL, objv[objc - 1],
- TCL_REG_ADVANCED | TCL_REG_NOSUB);
+ TCL_REG_ADVANCED | TCL_REG_NOSUB |
+ (noCase ? TCL_REG_NOCASE : 0));
if (regexp == NULL) {
- /*
- * Failed to compile the RE. Try again without the TCL_REG_NOSUB
- * flag in case the RE had sub-expressions in it [Bug 1366683].
- * If this fails, an error message will be left in the
- * interpreter.
- */
-
- regexp = Tcl_GetRegExpFromObj(interp, objv[objc - 1],
- TCL_REG_ADVANCED);
+ /*
+ * Failed to compile the RE. Try again without the TCL_REG_NOSUB
+ * flag in case the RE had sub-expressions in it [Bug 1366683]. If
+ * this fails, an error message will be left in the interpreter.
+ */
+
+ regexp = Tcl_GetRegExpFromObj(interp, objv[objc - 1],
+ TCL_REG_ADVANCED | (noCase ? TCL_REG_NOCASE : 0));
}
if (regexp == NULL) {
- if (startPtr) {
+ if (startPtr != NULL) {
Tcl_DecrRefCount(startPtr);
}
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
return TCL_ERROR;
}
}
/*
- * Make sure the list argument is a list object and get its length and
- * a pointer to its array of element pointers.
+ * Make sure the list argument is a list object and get its length and a
+ * pointer to its array of element pointers.
*/
- result = Tcl_ListObjGetElements(interp, objv[objc - 2], &listc, &listv);
+ result = TclListObjGetElements(interp, objv[objc - 2], &listc, &listv);
if (result != TCL_OK) {
- if (startPtr) {
+ if (startPtr != NULL) {
Tcl_DecrRefCount(startPtr);
}
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
return result;
}
/*
* Get the user-specified start offset.
*/
+
if (startPtr) {
- result = TclGetIntForIndex(interp, startPtr, listc-1, &offset);
+ result = TclGetIntForIndexM(interp, startPtr, listc-1, &offset);
Tcl_DecrRefCount(startPtr);
if (result != TCL_OK) {
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
return result;
}
+ if (offset < 0) {
+ offset = 0;
+ }
/*
* If the search started past the end of the list, we just return a
@@ -3360,6 +2983,9 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv)
*/
if (offset > listc-1) {
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
if (allMatches || inlineReturn) {
Tcl_ResetResult(interp);
} else {
@@ -3367,9 +2993,6 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv)
}
return TCL_OK;
}
- if (offset < 0) {
- offset = 0;
- }
}
patObj = objv[objc - 1];
@@ -3378,59 +3001,91 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv)
switch ((enum datatypes) dataType) {
case ASCII:
case DICTIONARY:
- patternBytes = Tcl_GetStringFromObj(patObj, &length);
+ patternBytes = TclGetStringFromObj(patObj, &length);
break;
case INTEGER:
- result = Tcl_GetIntFromObj(interp, patObj, &patInt);
+ result = TclGetIntFromObj(interp, patObj, &patInt);
if (result != TCL_OK) {
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
return result;
}
- Tcl_ListObjGetElements(NULL, objv[objc - 2], &listc, &listv);
+
+ /*
+ * List representation might have been shimmered; restore it. [Bug
+ * 1844789]
+ */
+
+ TclListObjGetElements(NULL, objv[objc - 2], &listc, &listv);
break;
case REAL:
result = Tcl_GetDoubleFromObj(interp, patObj, &patDouble);
if (result != TCL_OK) {
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
return result;
}
- Tcl_ListObjGetElements(NULL, objv[objc - 2], &listc, &listv);
+
+ /*
+ * List representation might have been shimmered; restore it. [Bug
+ * 1844789]
+ */
+
+ TclListObjGetElements(NULL, objv[objc - 2], &listc, &listv);
break;
}
} else {
- patternBytes = Tcl_GetStringFromObj(patObj, &length);
+ patternBytes = TclGetStringFromObj(patObj, &length);
}
/*
- * Set default index value to -1, indicating failure; if we find the
- * item in the course of our search, index will be set to the correct
- * value.
+ * Set default index value to -1, indicating failure; if we find the item
+ * in the course of our search, index will be set to the correct value.
*/
+
index = -1;
match = 0;
if ((enum modes) mode == SORTED && !allMatches && !negatedMatch) {
/*
- * If the data is sorted, we can do a more intelligent search.
- * Note that there is no point in being smart when -all was
- * specified; in that case, we have to look at all items anyway,
- * and there is no sense in doing this when the match sense is
- * inverted.
+ * If the data is sorted, we can do a more intelligent search. Note
+ * that there is no point in being smart when -all was specified; in
+ * that case, we have to look at all items anyway, and there is no
+ * sense in doing this when the match sense is inverted.
*/
+
lower = offset - 1;
upper = listc;
- while (lower + 1 != upper) {
+ while (lower + 1 != upper && sortInfo.resultCode == TCL_OK) {
i = (lower + upper)/2;
+ if (sortInfo.indexc != 0) {
+ itemPtr = SelectObjFromSublist(listv[i], &sortInfo);
+ if (sortInfo.resultCode != TCL_OK) {
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return sortInfo.resultCode;
+ }
+ } else {
+ itemPtr = listv[i];
+ }
switch ((enum datatypes) dataType) {
case ASCII:
- bytes = Tcl_GetString(listv[i]);
- match = strcmp(patternBytes, bytes);
+ bytes = TclGetString(itemPtr);
+ match = strCmpFn(patternBytes, bytes);
break;
case DICTIONARY:
- bytes = Tcl_GetString(listv[i]);
+ bytes = TclGetString(itemPtr);
match = DictionaryCompare(patternBytes, bytes);
break;
case INTEGER:
- result = Tcl_GetIntFromObj(interp, listv[i], &objInt);
+ result = TclGetIntFromObj(interp, itemPtr, &objInt);
if (result != TCL_OK) {
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
return result;
}
if (patInt == objInt) {
@@ -3442,8 +3097,11 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv)
}
break;
case REAL:
- result = Tcl_GetDoubleFromObj(interp, listv[i], &objDouble);
+ result = Tcl_GetDoubleFromObj(interp, itemPtr, &objDouble);
if (result != TCL_OK) {
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
return result;
}
if (patDouble == objDouble) {
@@ -3457,17 +3115,19 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv)
}
if (match == 0) {
/*
- * Normally, binary search is written to stop when it
- * finds a match. If there are duplicates of an element in
- * the list, our first match might not be the first occurance.
- * Consider: 0 0 0 1 1 1 2 2 2
- * To maintain consistancy with standard lsearch semantics,
- * we must find the leftmost occurance of the pattern in the
- * list. Thus we don't just stop searching here. This
+ * Normally, binary search is written to stop when it finds a
+ * match. If there are duplicates of an element in the list,
+ * our first match might not be the first occurance.
+ * Consider: 0 0 0 1 1 1 2 2 2
+ *
+ * To maintain consistancy with standard lsearch semantics, we
+ * must find the leftmost occurance of the pattern in the
+ * list. Thus we don't just stop searching here. This
* variation means that a search always makes log n
- * comparisons (normal binary search might "get lucky" with
- * an early comparison).
+ * comparisons (normal binary search might "get lucky" with an
+ * early comparison).
*/
+
index = i;
upper = i;
} else if (match > 0) {
@@ -3492,83 +3152,138 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv)
* - our matching sense is negated
* - we're building a list of all matched items
*/
+
if (allMatches) {
- listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+ listPtr = Tcl_NewListObj(0, NULL);
}
for (i = offset; i < listc; i++) {
match = 0;
+ if (sortInfo.indexc != 0) {
+ itemPtr = SelectObjFromSublist(listv[i], &sortInfo);
+ if (sortInfo.resultCode != TCL_OK) {
+ if (listPtr != NULL) {
+ Tcl_DecrRefCount(listPtr);
+ }
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return sortInfo.resultCode;
+ }
+ } else {
+ itemPtr = listv[i];
+ }
+
switch ((enum modes) mode) {
case SORTED:
case EXACT:
switch ((enum datatypes) dataType) {
case ASCII:
- bytes = Tcl_GetStringFromObj(listv[i], &elemLen);
+ bytes = TclGetStringFromObj(itemPtr, &elemLen);
if (length == elemLen) {
- match = (memcmp(bytes, patternBytes,
- (size_t) length) == 0);
+ /*
+ * This split allows for more optimal compilation of
+ * memcmp/strcasecmp.
+ */
+
+ if (noCase) {
+ match = (strcasecmp(bytes, patternBytes) == 0);
+ } else {
+ match = (memcmp(bytes, patternBytes,
+ (size_t) length) == 0);
+ }
}
break;
+
case DICTIONARY:
- bytes = Tcl_GetString(listv[i]);
+ bytes = TclGetString(itemPtr);
match = (DictionaryCompare(bytes, patternBytes) == 0);
break;
+
case INTEGER:
- result = Tcl_GetIntFromObj(interp, listv[i], &objInt);
+ result = TclGetIntFromObj(interp, itemPtr, &objInt);
if (result != TCL_OK) {
- if (listPtr) {
+ if (listPtr != NULL) {
Tcl_DecrRefCount(listPtr);
}
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
return result;
}
match = (objInt == patInt);
break;
+
case REAL:
- result = Tcl_GetDoubleFromObj(interp, listv[i],
- &objDouble);
+ result = Tcl_GetDoubleFromObj(interp,itemPtr, &objDouble);
if (result != TCL_OK) {
if (listPtr) {
Tcl_DecrRefCount(listPtr);
}
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
return result;
}
match = (objDouble == patDouble);
break;
}
break;
+
case GLOB:
- match = Tcl_StringMatch(Tcl_GetString(listv[i]),
- patternBytes);
+ match = Tcl_StringCaseMatch(TclGetString(itemPtr),
+ patternBytes, noCase);
break;
+
case REGEXP:
- match = Tcl_RegExpExecObj(interp, regexp, listv[i], 0, 0, 0);
+ match = Tcl_RegExpExecObj(interp, regexp, itemPtr, 0, 0, 0);
if (match < 0) {
Tcl_DecrRefCount(patObj);
- if (listPtr) {
+ if (listPtr != NULL) {
Tcl_DecrRefCount(listPtr);
}
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
return TCL_ERROR;
}
break;
}
+
/*
- * Invert match condition for -not
+ * Invert match condition for -not.
*/
+
if (negatedMatch) {
match = !match;
}
- if (match != 0) {
- if (!allMatches) {
- index = i;
- break;
- } else if (inlineReturn) {
- /*
- * Note that these appends are not expected to fail.
- */
- Tcl_ListObjAppendElement(interp, listPtr, listv[i]);
+ if (!match) {
+ continue;
+ }
+ if (!allMatches) {
+ index = i;
+ break;
+ } else if (inlineReturn) {
+ /*
+ * Note that these appends are not expected to fail.
+ */
+
+ if (returnSubindices && (sortInfo.indexc != 0)) {
+ itemPtr = SelectObjFromSublist(listv[i], &sortInfo);
} else {
- Tcl_ListObjAppendElement(interp, listPtr,
- Tcl_NewIntObj(i));
+ itemPtr = listv[i];
+ }
+ Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
+ } else if (returnSubindices) {
+ int j;
+
+ itemPtr = Tcl_NewIntObj(i);
+ for (j=0 ; j<sortInfo.indexc ; j++) {
+ Tcl_ListObjAppendElement(interp, itemPtr,
+ Tcl_NewIntObj(sortInfo.indexv[j]));
}
+ Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
+ } else {
+ Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewIntObj(i));
}
}
}
@@ -3576,19 +3291,40 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv)
/*
* Return everything or a single value.
*/
+
if (allMatches) {
Tcl_SetObjResult(interp, listPtr);
} else if (!inlineReturn) {
- Tcl_SetIntObj(Tcl_GetObjResult(interp), index);
+ if (returnSubindices) {
+ int j;
+
+ itemPtr = Tcl_NewIntObj(index);
+ for (j=0 ; j<sortInfo.indexc ; j++) {
+ Tcl_ListObjAppendElement(interp, itemPtr,
+ Tcl_NewIntObj(sortInfo.indexv[j]));
+ }
+ Tcl_SetObjResult(interp, itemPtr);
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
+ }
} else if (index < 0) {
/*
- * Is this superfluous? The result should be a blank object
- * by default...
+ * Is this superfluous? The result should be a blank object by
+ * default...
*/
+
Tcl_SetObjResult(interp, Tcl_NewObj());
} else {
Tcl_SetObjResult(interp, listv[index]);
}
+
+ /*
+ * Cleanup the index list array.
+ */
+
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
return TCL_OK;
}
@@ -3597,8 +3333,8 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv)
*
* Tcl_LsetObjCmd --
*
- * This procedure is invoked to process the "lset" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "lset" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -3610,66 +3346,71 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv)
*/
int
-Tcl_LsetObjCmd( clientData, interp, objc, objv )
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument values. */
+Tcl_LsetObjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument values. */
{
+ Tcl_Obj *listPtr; /* Pointer to the list being altered. */
+ Tcl_Obj *finalValuePtr; /* Value finally assigned to the variable. */
- Tcl_Obj* listPtr; /* Pointer to the list being altered. */
- Tcl_Obj* finalValuePtr; /* Value finally assigned to the variable */
-
- /* Check parameter count */
+ /*
+ * Check parameter count.
+ */
- if ( objc < 3 ) {
- Tcl_WrongNumArgs( interp, 1, objv, "listVar index ?index...? value" );
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "listVar ?index? ?index...? value");
return TCL_ERROR;
}
- /* Look up the list variable's value */
+ /*
+ * Look up the list variable's value.
+ */
- listPtr = Tcl_ObjGetVar2( interp, objv[ 1 ], (Tcl_Obj*) NULL,
- TCL_LEAVE_ERR_MSG );
- if ( listPtr == NULL ) {
+ listPtr = Tcl_ObjGetVar2(interp, objv[1], (Tcl_Obj *) NULL,
+ TCL_LEAVE_ERR_MSG);
+ if (listPtr == NULL) {
return TCL_ERROR;
}
- /*
- * Substitute the value in the value. Return either the value or
- * else an unshared copy of it.
+ /*
+ * Substitute the value in the value. Return either the value or else an
+ * unshared copy of it.
*/
- if ( objc == 4 ) {
- finalValuePtr = TclLsetList( interp, listPtr,
- objv[ 2 ], objv[ 3 ] );
+ if (objc == 4) {
+ finalValuePtr = TclLsetList(interp, listPtr, objv[2], objv[3]);
} else {
- finalValuePtr = TclLsetFlat( interp, listPtr,
- objc-3, objv+2, objv[ objc-1 ] );
+ finalValuePtr = TclLsetFlat(interp, listPtr, objc-3, objv+2,
+ objv[objc-1]);
}
/*
* If substitution has failed, bail out.
*/
- if ( finalValuePtr == NULL ) {
+ if (finalValuePtr == NULL) {
return TCL_ERROR;
}
- /* Finally, update the variable so that traces fire. */
+ /*
+ * Finally, update the variable so that traces fire.
+ */
- listPtr = Tcl_ObjSetVar2( interp, objv[1], NULL, finalValuePtr,
- TCL_LEAVE_ERR_MSG );
- Tcl_DecrRefCount( finalValuePtr );
- if ( listPtr == NULL ) {
+ listPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, finalValuePtr,
+ TCL_LEAVE_ERR_MSG);
+ Tcl_DecrRefCount(finalValuePtr);
+ if (listPtr == NULL) {
return TCL_ERROR;
}
- /* Return the new value of the variable as the interpreter result. */
+ /*
+ * Return the new value of the variable as the interpreter result.
+ */
- Tcl_SetObjResult( interp, listPtr );
+ Tcl_SetObjResult(interp, listPtr);
return TCL_OK;
-
}
/*
@@ -3677,8 +3418,8 @@ Tcl_LsetObjCmd( clientData, interp, objc, objv )
*
* Tcl_LsortObjCmd --
*
- * This procedure is invoked to process the "lsort" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "lsort" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -3690,27 +3431,34 @@ Tcl_LsetObjCmd( clientData, interp, objc, objv )
*/
int
-Tcl_LsortObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument values. */
+Tcl_LsortObjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument values. */
{
- int i, index, unique;
- Tcl_Obj *resultPtr;
- int length;
- Tcl_Obj *cmdPtr, **listObjPtrs;
- SortElement *elementArray;
- SortElement *elementPtr;
- SortInfo sortInfo; /* Information about this sort that
- * needs to be passed to the
- * comparison function */
+ int i, j, index, indices, length, nocase = 0, sortMode, indexc;
+ Tcl_Obj *resultPtr, *cmdPtr, **listObjPtrs, *listObj, *indexPtr;
+ SortElement *elementArray, *elementPtr;
+ SortInfo sortInfo; /* Information about this sort that needs to
+ * be passed to the comparison function. */
static CONST char *switches[] = {
"-ascii", "-command", "-decreasing", "-dictionary", "-increasing",
- "-index", "-integer", "-real", "-unique", (char *) NULL
+ "-index", "-indices", "-integer", "-nocase", "-real", "-unique", NULL
+ };
+ enum Lsort_Switches {
+ LSORT_ASCII, LSORT_COMMAND, LSORT_DECREASING, LSORT_DICTIONARY,
+ LSORT_INCREASING, LSORT_INDEX, LSORT_INDICES, LSORT_INTEGER,
+ LSORT_NOCASE, LSORT_REAL, LSORT_UNIQUE
};
- resultPtr = Tcl_GetObjResult(interp);
+ /*
+ * The subList array below holds pointers to temporary lists built during
+ * the merge sort. Element i of the array holds a list of length 2**i.
+ */
+# define NUM_LISTS 30
+ SortElement *subList[NUM_LISTS+1];
+
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "?options? list");
return TCL_ERROR;
@@ -3722,199 +3470,312 @@ Tcl_LsortObjCmd(clientData, interp, objc, objv)
sortInfo.isIncreasing = 1;
sortInfo.sortMode = SORTMODE_ASCII;
- sortInfo.index = SORTIDX_NONE;
+ sortInfo.indexv = NULL;
+ sortInfo.indexc = 0;
+ sortInfo.unique = 0;
sortInfo.interp = interp;
- sortInfo.resultCode = TCL_OK;
+ sortInfo.resultCode = TCL_OK;
cmdPtr = NULL;
- unique = 0;
+ indices = 0;
for (i = 1; i < objc-1; i++) {
- if (Tcl_GetIndexFromObj(interp, objv[i], switches, "option", 0, &index)
- != TCL_OK) {
+ if (Tcl_GetIndexFromObj(interp, objv[i], switches, "option", 0,
+ &index) != TCL_OK) {
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
return TCL_ERROR;
}
- switch (index) {
- case 0: /* -ascii */
- sortInfo.sortMode = SORTMODE_ASCII;
- break;
- case 1: /* -command */
- if (i == (objc-2)) {
- Tcl_AppendToObj(resultPtr,
- "\"-command\" option must be followed by comparison command",
- -1);
- return TCL_ERROR;
+ switch ((enum Lsort_Switches) index) {
+ case LSORT_ASCII:
+ sortInfo.sortMode = SORTMODE_ASCII;
+ break;
+ case LSORT_COMMAND:
+ if (i == (objc-2)) {
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
}
- sortInfo.sortMode = SORTMODE_COMMAND;
- cmdPtr = objv[i+1];
- i++;
- break;
- case 2: /* -decreasing */
- sortInfo.isIncreasing = 0;
- break;
- case 3: /* -dictionary */
- sortInfo.sortMode = SORTMODE_DICTIONARY;
+ Tcl_AppendResult(interp,
+ "\"-command\" option must be followed "
+ "by comparison command", NULL);
+ return TCL_ERROR;
+ }
+ sortInfo.sortMode = SORTMODE_COMMAND;
+ cmdPtr = objv[i+1];
+ i++;
+ break;
+ case LSORT_DECREASING:
+ sortInfo.isIncreasing = 0;
+ break;
+ case LSORT_DICTIONARY:
+ sortInfo.sortMode = SORTMODE_DICTIONARY;
+ break;
+ case LSORT_INCREASING:
+ sortInfo.isIncreasing = 1;
+ break;
+ case LSORT_INDEX: {
+ Tcl_Obj **indices;
+
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ if (i == (objc-2)) {
+ Tcl_AppendResult(interp, "\"-index\" option must be "
+ "followed by list index", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Take copy to prevent shimmering problems.
+ */
+
+ if (TclListObjGetElements(interp, objv[i+1], &sortInfo.indexc,
+ &indices) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch (sortInfo.indexc) {
+ case 0:
+ sortInfo.indexv = NULL;
break;
- case 4: /* -increasing */
- sortInfo.isIncreasing = 1;
+ case 1:
+ sortInfo.indexv = &sortInfo.singleIndex;
break;
- case 5: /* -index */
- if (i == (objc-2)) {
- Tcl_AppendToObj(resultPtr,
- "\"-index\" option must be followed by list index",
- -1);
- return TCL_ERROR;
- }
- if (TclGetIntForIndex(interp, objv[i+1], SORTIDX_END,
- &sortInfo.index) != TCL_OK) {
+ default:
+ sortInfo.indexv = (int *)
+ ckalloc(sizeof(int) * sortInfo.indexc);
+ }
+
+ /*
+ * Fill the array by parsing each index. We don't know whether
+ * their scale is sensible yet, but we at least perform the
+ * syntactic check here.
+ */
+
+ for (j=0 ; j<sortInfo.indexc ; j++) {
+ if (TclGetIntForIndexM(interp, indices[j], SORTIDX_END,
+ &sortInfo.indexv[j]) != TCL_OK) {
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (-index option item number %d)", j));
return TCL_ERROR;
}
- i++;
- break;
- case 6: /* -integer */
- sortInfo.sortMode = SORTMODE_INTEGER;
- break;
- case 7: /* -real */
- sortInfo.sortMode = SORTMODE_REAL;
- break;
- case 8: /* -unique */
- unique = 1;
- break;
+ }
+ i++;
+ break;
}
+ case LSORT_INTEGER:
+ sortInfo.sortMode = SORTMODE_INTEGER;
+ break;
+ case LSORT_NOCASE:
+ nocase = 1;
+ break;
+ case LSORT_REAL:
+ sortInfo.sortMode = SORTMODE_REAL;
+ break;
+ case LSORT_UNIQUE:
+ sortInfo.unique = 1;
+ break;
+ case LSORT_INDICES:
+ indices = 1;
+ break;
+ }
+ }
+ if (nocase && (sortInfo.sortMode == SORTMODE_ASCII)) {
+ sortInfo.sortMode = SORTMODE_ASCII_NC;
}
+
+ listObj = objv[objc-1];
+
if (sortInfo.sortMode == SORTMODE_COMMAND) {
+ Tcl_Obj *newCommandPtr, *newObjPtr;
+
/*
- * The existing command is a list. We want to flatten it, append
- * two dummy arguments on the end, and replace these arguments
- * later.
+ * When sorting using a command, we are reentrant and therefore might
+ * have the representation of the list being sorted shimmered out from
+ * underneath our feet. Take a copy (cheap) to prevent this. [Bug
+ * 1675116]
*/
- Tcl_Obj *newCommandPtr = Tcl_DuplicateObj(cmdPtr);
- Tcl_Obj *newObjPtr = Tcl_NewObj();
+ listObj = TclListObjCopy(interp, listObj);
+ if (listObj == NULL) {
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
+ return TCL_ERROR;
+ }
+
+ /*
+ * The existing command is a list. We want to flatten it, append two
+ * dummy arguments on the end, and replace these arguments later.
+ */
+ newCommandPtr = Tcl_DuplicateObj(cmdPtr);
+ TclNewObj(newObjPtr);
Tcl_IncrRefCount(newCommandPtr);
if (Tcl_ListObjAppendElement(interp, newCommandPtr, newObjPtr)
!= TCL_OK) {
- Tcl_DecrRefCount(newCommandPtr);
+ TclDecrRefCount(newCommandPtr);
+ TclDecrRefCount(listObj);
Tcl_IncrRefCount(newObjPtr);
- Tcl_DecrRefCount(newObjPtr);
+ TclDecrRefCount(newObjPtr);
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
+ }
return TCL_ERROR;
}
Tcl_ListObjAppendElement(interp, newCommandPtr, Tcl_NewObj());
sortInfo.compareCmdPtr = newCommandPtr;
}
- sortInfo.resultCode = Tcl_ListObjGetElements(interp, objv[objc-1],
+ sortInfo.resultCode = TclListObjGetElements(interp, listObj,
&length, &listObjPtrs);
if (sortInfo.resultCode != TCL_OK || length <= 0) {
goto done;
}
- elementArray = (SortElement *) ckalloc(length * sizeof(SortElement));
- for (i=0; i < length; i++){
- elementArray[i].objPtr = listObjPtrs[i];
- elementArray[i].count = 0;
- elementArray[i].nextPtr = &elementArray[i+1];
-
+ sortInfo.numElements = length;
+
+ indexc = sortInfo.indexc;
+ sortMode = sortInfo.sortMode;
+ if ((sortMode == SORTMODE_ASCII_NC)
+ || (sortMode == SORTMODE_DICTIONARY)) {
/*
- * When sorting using a command, we are reentrant and therefore might
- * have the representation of the list being sorted shimmered out from
- * underneath our feet. Increment the reference counts of the elements
- * to sort to prevent this. [Bug 1675116]
+ * For this function's purpose all string-based modes are equivalent
*/
+
+ sortMode = SORTMODE_ASCII;
+ }
- Tcl_IncrRefCount(elementArray[i].objPtr);
+ /*
+ * Initialize the sublists. After the following loop, subList[i] will
+ * contain a sorted sublist of length 2**i. Use one extra subList at the
+ * end, always at NULL, to indicate the end of the lists.
+ */
+
+ for (j=0 ; j<=NUM_LISTS ; j++) {
+ subList[j] = NULL;
}
- elementArray[length-1].nextPtr = NULL;
- elementPtr = MergeSort(elementArray, &sortInfo);
- if (sortInfo.resultCode == TCL_OK) {
- /*
- * Note: must clear the interpreter's result object: it could
- * have been set by the -command script.
- */
- Tcl_ResetResult(interp);
- resultPtr = Tcl_GetObjResult(interp);
- if (unique) {
- for (; elementPtr != NULL; elementPtr = elementPtr->nextPtr){
- if (elementPtr->count == 0) {
- Tcl_ListObjAppendElement(interp, resultPtr,
- elementPtr->objPtr);
- }
+ /*
+ * The following loop creates a SortElement for each list element and
+ * begins sorting it into the sublists as it appears.
+ */
+
+ elementArray = (SortElement *) ckalloc( length * sizeof(SortElement));
+
+ for (i=0; i < length; i++){
+ if (indexc) {
+ /*
+ * If this is an indexed sort, retrieve the corresponding element
+ */
+ indexPtr = SelectObjFromSublist(listObjPtrs[i], &sortInfo);
+ if (sortInfo.resultCode != TCL_OK) {
+ goto done1;
}
} else {
- for (; elementPtr != NULL; elementPtr = elementPtr->nextPtr){
- Tcl_ListObjAppendElement(interp, resultPtr,
- elementPtr->objPtr);
+ indexPtr = listObjPtrs[i];
+ }
+
+ /*
+ * Determine the "value" of this object for sorting purposes
+ */
+
+ if (sortMode == SORTMODE_ASCII) {
+ elementArray[i].index.strValuePtr = TclGetString(indexPtr);
+ } else if (sortMode == SORTMODE_INTEGER) {
+ long a;
+ if (TclGetLongFromObj(sortInfo.interp, indexPtr, &a) != TCL_OK) {
+ sortInfo.resultCode = TCL_ERROR;
+ goto done1;
+ }
+ elementArray[i].index.intValue = a;
+ } else if (sortInfo.sortMode == SORTMODE_REAL) {
+ double a;
+ if (Tcl_GetDoubleFromObj(sortInfo.interp, indexPtr, &a) != TCL_OK) {
+ sortInfo.resultCode = TCL_ERROR;
+ goto done1;
}
+ elementArray[i].index.doubleValue = a;
+ } else {
+ elementArray[i].index.objValuePtr = indexPtr;
}
- }
- for (i=0; i<length; i++) {
- Tcl_DecrRefCount(elementArray[i].objPtr);
- }
- ckfree((char*) elementArray);
- done:
- if (sortInfo.sortMode == SORTMODE_COMMAND) {
- Tcl_DecrRefCount(sortInfo.compareCmdPtr);
- sortInfo.compareCmdPtr = NULL;
+ /*
+ * Determine the representation of this element in the result: either
+ * the objPtr itself, or its index in the original list.
+ */
+
+ elementArray[i].objPtr = (indices ? INT2PTR(i) : listObjPtrs[i]);
+
+ /*
+ * Merge this element in the pre-existing sublists (and merge together
+ * sublists when we have two of the same size).
+ */
+
+ elementArray[i].nextPtr = NULL;
+ elementPtr = &elementArray[i];
+ for (j=0 ; subList[j] ; j++) {
+ elementPtr = MergeLists(subList[j], elementPtr, &sortInfo);
+ subList[j] = NULL;
+ }
+ if (j >= NUM_LISTS) {
+ j = NUM_LISTS-1;
+ }
+ subList[j] = elementPtr;
}
- return sortInfo.resultCode;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * MergeSort -
- *
- * This procedure sorts a linked list of SortElement structures
- * use the merge-sort algorithm.
- *
- * Results:
- * A pointer to the head of the list after sorting is returned.
- *
- * Side effects:
- * None, unless a user-defined comparison command does something
- * weird.
- *
- *----------------------------------------------------------------------
- */
-static SortElement *
-MergeSort(headPtr, infoPtr)
- SortElement *headPtr; /* First element on the list */
- SortInfo *infoPtr; /* Information needed by the
- * comparison operator */
-{
/*
- * The subList array below holds pointers to temporary lists built
- * during the merge sort. Element i of the array holds a list of
- * length 2**i.
+ * Merge all sublists
*/
+
+ elementPtr = subList[0];
+ for (j=1 ; j<NUM_LISTS ; j++) {
+ elementPtr = MergeLists(subList[j], elementPtr, &sortInfo);
+ }
-# define NUM_LISTS 30
- SortElement *subList[NUM_LISTS];
- SortElement *elementPtr;
- int i;
- for(i = 0; i < NUM_LISTS; i++){
- subList[i] = NULL;
- }
- while (headPtr != NULL) {
- elementPtr = headPtr;
- headPtr = headPtr->nextPtr;
- elementPtr->nextPtr = 0;
- for (i = 0; (i < NUM_LISTS) && (subList[i] != NULL); i++){
- elementPtr = MergeLists(subList[i], elementPtr, infoPtr);
- subList[i] = NULL;
- }
- if (i >= NUM_LISTS) {
- i = NUM_LISTS-1;
+ /*
+ * Now store the sorted elements in the result list.
+ */
+
+ if (sortInfo.resultCode == TCL_OK) {
+ List *listRepPtr;
+ Tcl_Obj **newArray, *objPtr;
+ int i;
+
+ resultPtr = Tcl_NewListObj(sortInfo.numElements, NULL);
+ listRepPtr = ListRepPtr(resultPtr);
+ newArray = &listRepPtr->elements;
+ if (indices) {
+ for (i = 0; elementPtr != NULL ; elementPtr = elementPtr->nextPtr){
+ objPtr = Tcl_NewIntObj(PTR2INT(elementPtr->objPtr));
+ newArray[i++] = objPtr;
+ Tcl_IncrRefCount(objPtr);
+ }
+ } else {
+ for (i = 0; elementPtr != NULL ; elementPtr = elementPtr->nextPtr){
+ objPtr = elementPtr->objPtr;
+ newArray[i++] = objPtr;
+ Tcl_IncrRefCount(objPtr);
+ }
}
- subList[i] = elementPtr;
+ listRepPtr->elemCount = i;
+ Tcl_SetObjResult(interp, resultPtr);
}
- elementPtr = NULL;
- for (i = 0; i < NUM_LISTS; i++){
- elementPtr = MergeLists(subList[i], elementPtr, infoPtr);
+
+ done1:
+ ckfree((char *)elementArray);
+
+ done:
+ if (sortInfo.sortMode == SORTMODE_COMMAND) {
+ TclDecrRefCount(sortInfo.compareCmdPtr);
+ TclDecrRefCount(listObj);
+ sortInfo.compareCmdPtr = NULL;
+ }
+ if (sortInfo.indexc > 1) {
+ ckfree((char *) sortInfo.indexv);
}
- return elementPtr;
+ return sortInfo.resultCode;
}
/*
@@ -3926,65 +3787,91 @@ MergeSort(headPtr, infoPtr)
* into a single sorted list.
*
* Results:
- * The unified list of SortElement structures.
+ * The unified list of SortElement structures.
*
* Side effects:
- * None, unless a user-defined comparison command does something
- * weird.
- *
+ * If infoPtr->unique is set then infoPtr->numElements may be updated.
+ * Possibly others, if a user-defined comparison command does something
+ * weird.
+ *
+ * Note:
+ * If infoPtr->unique is set, the merge assumes that there are no
+ * "repeated" elements in each of the left and right lists. In that case,
+ * if any element of the left list is equivalent to one in the right list
+ * it is omitted from the merged list.
+ * This simplified mechanism works because of the special way
+ * our MergeSort creates the sublists to be merged and will fail to
+ * eliminate all repeats in the general case where they are already
+ * present in either the left or right list. A general code would need to
+ * skip adjacent initial repeats in the left and right lists before
+ * comparing their initial elements, at each step.
*----------------------------------------------------------------------
*/
static SortElement *
-MergeLists(leftPtr, rightPtr, infoPtr)
- SortElement *leftPtr; /* First list to be merged; may be
- * NULL. */
- SortElement *rightPtr; /* Second list to be merged; may be
- * NULL. */
- SortInfo *infoPtr; /* Information needed by the
- * comparison operator. */
+MergeLists(
+ SortElement *leftPtr, /* First list to be merged; may be NULL. */
+ SortElement *rightPtr, /* Second list to be merged; may be NULL. */
+ SortInfo *infoPtr) /* Information needed by the comparison
+ * operator. */
{
- SortElement *headPtr;
- SortElement *tailPtr;
+ SortElement *headPtr, *tailPtr;
int cmp;
if (leftPtr == NULL) {
- return rightPtr;
+ return rightPtr;
}
if (rightPtr == NULL) {
- return leftPtr;
+ return leftPtr;
}
- cmp = SortCompare(leftPtr->objPtr, rightPtr->objPtr, infoPtr);
- if (cmp > 0) {
+ cmp = SortCompare(leftPtr, rightPtr, infoPtr);
+ if (cmp > 0 || (cmp == 0 && infoPtr->unique)) {
+ if (cmp == 0) {
+ infoPtr->numElements--;
+ leftPtr = leftPtr->nextPtr;
+ }
tailPtr = rightPtr;
rightPtr = rightPtr->nextPtr;
} else {
- if (cmp == 0) {
- leftPtr->count++;
- }
tailPtr = leftPtr;
leftPtr = leftPtr->nextPtr;
}
headPtr = tailPtr;
- while ((leftPtr != NULL) && (rightPtr != NULL)) {
- cmp = SortCompare(leftPtr->objPtr, rightPtr->objPtr, infoPtr);
- if (cmp > 0) {
- tailPtr->nextPtr = rightPtr;
- tailPtr = rightPtr;
- rightPtr = rightPtr->nextPtr;
- } else {
- if (cmp == 0) {
- leftPtr->count++;
+ if (!infoPtr->unique) {
+ while ((leftPtr != NULL) && (rightPtr != NULL)) {
+ cmp = SortCompare(leftPtr, rightPtr, infoPtr);
+ if (cmp > 0) {
+ tailPtr->nextPtr = rightPtr;
+ tailPtr = rightPtr;
+ rightPtr = rightPtr->nextPtr;
+ } else {
+ tailPtr->nextPtr = leftPtr;
+ tailPtr = leftPtr;
+ leftPtr = leftPtr->nextPtr;
+ }
+ }
+ } else {
+ while ((leftPtr != NULL) && (rightPtr != NULL)) {
+ cmp = SortCompare(leftPtr, rightPtr, infoPtr);
+ if (cmp >= 0) {
+ if (cmp == 0) {
+ infoPtr->numElements--;
+ leftPtr = leftPtr->nextPtr;
+ }
+ tailPtr->nextPtr = rightPtr;
+ tailPtr = rightPtr;
+ rightPtr = rightPtr->nextPtr;
+ } else {
+ tailPtr->nextPtr = leftPtr;
+ tailPtr = leftPtr;
+ leftPtr = leftPtr->nextPtr;
}
- tailPtr->nextPtr = leftPtr;
- tailPtr = leftPtr;
- leftPtr = leftPtr->nextPtr;
}
}
if (leftPtr != NULL) {
- tailPtr->nextPtr = leftPtr;
+ tailPtr->nextPtr = leftPtr;
} else {
- tailPtr->nextPtr = rightPtr;
+ tailPtr->nextPtr = rightPtr;
}
return headPtr;
}
@@ -3998,163 +3885,98 @@ MergeLists(leftPtr, rightPtr, infoPtr)
* ordering between two elements.
*
* Results:
- * A negative results means the the first element comes before the
- * second, and a positive results means that the second element
- * should come first. A result of zero means the two elements
- * are equal and it doesn't matter which comes first.
+ * A negative results means the the first element comes before the
+ * second, and a positive results means that the second element should
+ * come first. A result of zero means the two elements are equal and it
+ * doesn't matter which comes first.
*
* Side effects:
- * None, unless a user-defined comparison command does something
- * weird.
+ * None, unless a user-defined comparison command does something weird.
*
*----------------------------------------------------------------------
*/
static int
-SortCompare(objPtr1, objPtr2, infoPtr)
- Tcl_Obj *objPtr1, *objPtr2; /* Values to be compared. */
- SortInfo *infoPtr; /* Information passed from the
- * top-level "lsort" command */
+SortCompare(
+ SortElement *elemPtr1, SortElement *elemPtr2,
+ /* Values to be compared. */
+ SortInfo *infoPtr) /* Information passed from the top-level
+ * "lsort" command. */
{
- int order, listLen, index;
- Tcl_Obj *objPtr;
- char buffer[TCL_INTEGER_SPACE];
-
- order = 0;
- if (infoPtr->resultCode != TCL_OK) {
- /*
- * Once an error has occurred, skip any future comparisons
- * so as to preserve the error message in sortInterp->result.
- */
-
- return order;
- }
- if (infoPtr->index != SORTIDX_NONE) {
- /*
- * The "-index" option was specified. Treat each object as a
- * list, extract the requested element from each list, and
- * compare the elements, not the lists. "end"-relative indices
- * are signaled here with large negative values.
- */
-
- if (Tcl_ListObjLength(infoPtr->interp, objPtr1, &listLen) != TCL_OK) {
- infoPtr->resultCode = TCL_ERROR;
- return order;
- }
- if (infoPtr->index < SORTIDX_NONE) {
- index = listLen + infoPtr->index + 1;
- } else {
- index = infoPtr->index;
- }
+ int order = 0;
- if (Tcl_ListObjIndex(infoPtr->interp, objPtr1, index, &objPtr)
- != TCL_OK) {
- infoPtr->resultCode = TCL_ERROR;
- return order;
- }
- if (objPtr == NULL) {
- objPtr = objPtr1;
- missingElement:
- TclFormatInt(buffer, infoPtr->index);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(infoPtr->interp),
- "element ", buffer, " missing from sublist \"",
- Tcl_GetString(objPtr), "\"", (char *) NULL);
- infoPtr->resultCode = TCL_ERROR;
- return order;
- }
- objPtr1 = objPtr;
-
- if (Tcl_ListObjLength(infoPtr->interp, objPtr2, &listLen) != TCL_OK) {
- infoPtr->resultCode = TCL_ERROR;
- return order;
- }
- if (infoPtr->index < SORTIDX_NONE) {
- index = listLen + infoPtr->index + 1;
- } else {
- index = infoPtr->index;
- }
-
- if (Tcl_ListObjIndex(infoPtr->interp, objPtr2, index, &objPtr)
- != TCL_OK) {
- infoPtr->resultCode = TCL_ERROR;
- return order;
- }
- if (objPtr == NULL) {
- objPtr = objPtr2;
- goto missingElement;
- }
- objPtr2 = objPtr;
- }
if (infoPtr->sortMode == SORTMODE_ASCII) {
- order = strcmp(Tcl_GetString(objPtr1), Tcl_GetString(objPtr2));
+ order = strcmp(elemPtr1->index.strValuePtr,
+ elemPtr2->index.strValuePtr);
+ } else if (infoPtr->sortMode == SORTMODE_ASCII_NC) {
+ order = strcasecmp(elemPtr1->index.strValuePtr,
+ elemPtr2->index.strValuePtr);
} else if (infoPtr->sortMode == SORTMODE_DICTIONARY) {
- order = DictionaryCompare(
- Tcl_GetString(objPtr1), Tcl_GetString(objPtr2));
+ order = DictionaryCompare(elemPtr1->index.strValuePtr,
+ elemPtr2->index.strValuePtr);
} else if (infoPtr->sortMode == SORTMODE_INTEGER) {
long a, b;
- if ((Tcl_GetLongFromObj(infoPtr->interp, objPtr1, &a) != TCL_OK)
- || (Tcl_GetLongFromObj(infoPtr->interp, objPtr2, &b)
- != TCL_OK)) {
- infoPtr->resultCode = TCL_ERROR;
- return order;
- }
- if (a > b) {
- order = 1;
- } else if (b > a) {
- order = -1;
- }
+ a = elemPtr1->index.intValue;
+ b = elemPtr2->index.intValue;
+ order = ((a >= b) - (a <= b));
} else if (infoPtr->sortMode == SORTMODE_REAL) {
double a, b;
- if ((Tcl_GetDoubleFromObj(infoPtr->interp, objPtr1, &a) != TCL_OK)
- || (Tcl_GetDoubleFromObj(infoPtr->interp, objPtr2, &b)
- != TCL_OK)) {
- infoPtr->resultCode = TCL_ERROR;
- return order;
- }
- if (a > b) {
- order = 1;
- } else if (b > a) {
- order = -1;
- }
+ a = elemPtr1->index.doubleValue;
+ b = elemPtr2->index.doubleValue;
+ order = ((a >= b) - (a <= b));
} else {
Tcl_Obj **objv, *paramObjv[2];
int objc;
+ Tcl_Obj *objPtr1, *objPtr2;
+
+ if (infoPtr->resultCode != TCL_OK) {
+ /*
+ * Once an error has occurred, skip any future comparisons so as
+ * to preserve the error message in sortInterp->result.
+ */
+
+ return 0;
+ }
+
+ objPtr1 = elemPtr1->index.objValuePtr;
+ objPtr2 = elemPtr2->index.objValuePtr;
+
paramObjv[0] = objPtr1;
paramObjv[1] = objPtr2;
- /*
- * We made space in the command list for the two things to
- * compare. Replace them and evaluate the result.
+ /*
+ * We made space in the command list for the two things to compare.
+ * Replace them and evaluate the result.
*/
- Tcl_ListObjLength(infoPtr->interp, infoPtr->compareCmdPtr, &objc);
+ TclListObjLength(infoPtr->interp, infoPtr->compareCmdPtr, &objc);
Tcl_ListObjReplace(infoPtr->interp, infoPtr->compareCmdPtr, objc - 2,
2, 2, paramObjv);
- Tcl_ListObjGetElements(infoPtr->interp, infoPtr->compareCmdPtr,
+ TclListObjGetElements(infoPtr->interp, infoPtr->compareCmdPtr,
&objc, &objv);
infoPtr->resultCode = Tcl_EvalObjv(infoPtr->interp, objc, objv, 0);
-
- if (infoPtr->resultCode != TCL_OK) {
+
+ if (infoPtr->resultCode != TCL_OK) {
Tcl_AddErrorInfo(infoPtr->interp,
"\n (-compare command)");
- return order;
+ return 0;
}
/*
* Parse the result of the command.
*/
- if (Tcl_GetIntFromObj(infoPtr->interp,
+ if (TclGetIntFromObj(infoPtr->interp,
Tcl_GetObjResult(infoPtr->interp), &order) != TCL_OK) {
Tcl_ResetResult(infoPtr->interp);
- Tcl_AppendToObj(Tcl_GetObjResult(infoPtr->interp),
- "-compare command returned non-integer result", -1);
+ Tcl_AppendResult(infoPtr->interp,
+ "-compare command returned non-integer result", NULL);
infoPtr->resultCode = TCL_ERROR;
- return order;
+ return 0;
}
}
if (!infoPtr->isIncreasing) {
@@ -4168,18 +3990,18 @@ SortCompare(objPtr1, objPtr2, infoPtr)
*
* DictionaryCompare
*
- * This function compares two strings as if they were being used in
- * an index or card catalog. The case of alphabetic characters is
- * ignored, except to break ties. Thus "B" comes before "b" but
- * after "a". Also, integers embedded in the strings compare in
- * numerical order. In other words, "x10y" comes after "x9y", not
- * before it as it would when using strcmp().
+ * This function compares two strings as if they were being used in an
+ * index or card catalog. The case of alphabetic characters is ignored,
+ * except to break ties. Thus "B" comes before "b" but after "a". Also,
+ * integers embedded in the strings compare in numerical order. In other
+ * words, "x10y" comes after "x9y", not * before it as it would when
+ * using strcmp().
*
* Results:
- * A negative result means that the first element comes before the
- * second, and a positive result means that the second element
- * should come first. A result of zero means the two elements
- * are equal and it doesn't matter which comes first.
+ * A negative result means that the first element comes before the
+ * second, and a positive result means that the second element should
+ * come first. A result of zero means the two elements are equal and it
+ * doesn't matter which comes first.
*
* Side effects:
* None.
@@ -4188,22 +4010,21 @@ SortCompare(objPtr1, objPtr2, infoPtr)
*/
static int
-DictionaryCompare(left, right)
- char *left, *right; /* The strings to compare */
+DictionaryCompare(
+ char *left, char *right) /* The strings to compare. */
{
Tcl_UniChar uniLeft, uniRight, uniLeftLower, uniRightLower;
int diff, zeros;
int secondaryDiff = 0;
while (1) {
- if (isdigit(UCHAR(*right)) /* INTL: digit */
- && isdigit(UCHAR(*left))) { /* INTL: digit */
+ if (isdigit(UCHAR(*right)) /* INTL: digit */
+ && isdigit(UCHAR(*left))) { /* INTL: digit */
/*
- * There are decimal numbers embedded in the two
- * strings. Compare them as numbers, rather than
- * strings. If one number has more leading zeros than
- * the other, the number with more leading zeros sorts
- * later, but only as a secondary choice.
+ * There are decimal numbers embedded in the two strings. Compare
+ * them as numbers, rather than strings. If one number has more
+ * leading zeros than the other, the number with more leading
+ * zeros sorts later, but only as a secondary choice.
*/
zeros = 0;
@@ -4220,10 +4041,10 @@ DictionaryCompare(left, right)
}
/*
- * The code below compares the numbers in the two
- * strings without ever converting them to integers. It
- * does this by first comparing the lengths of the
- * numbers and then comparing the digit values.
+ * The code below compares the numbers in the two strings without
+ * ever converting them to integers. It does this by first
+ * comparing the lengths of the numbers and then comparing the
+ * digit values.
*/
diff = 0;
@@ -4233,13 +4054,13 @@ DictionaryCompare(left, right)
}
right++;
left++;
- if (!isdigit(UCHAR(*right))) { /* INTL: digit */
- if (isdigit(UCHAR(*left))) { /* INTL: digit */
+ if (!isdigit(UCHAR(*right))) { /* INTL: digit */
+ if (isdigit(UCHAR(*left))) { /* INTL: digit */
return 1;
} else {
/*
- * The two numbers have the same length. See
- * if their values are different.
+ * The two numbers have the same length. See if their
+ * values are different.
*/
if (diff != 0) {
@@ -4247,7 +4068,7 @@ DictionaryCompare(left, right)
}
break;
}
- } else if (!isdigit(UCHAR(*left))) { /* INTL: digit */
+ } else if (!isdigit(UCHAR(*left))) { /* INTL: digit */
return -1;
}
}
@@ -4255,7 +4076,7 @@ DictionaryCompare(left, right)
}
/*
- * Convert character to Unicode for comparison purposes. If either
+ * Convert character to Unicode for comparison purposes. If either
* string is at the terminating null, do a byte-wise comparison and
* bail out immediately.
*/
@@ -4263,12 +4084,14 @@ DictionaryCompare(left, right)
if ((*left != '\0') && (*right != '\0')) {
left += Tcl_UtfToUniChar(left, &uniLeft);
right += Tcl_UtfToUniChar(right, &uniRight);
+
/*
* Convert both chars to lower for the comparison, because
- * dictionary sorts are case insensitve. Covert to lower, not
+ * dictionary sorts are case insensitve. Covert to lower, not
* upper, so chars between Z and a will sort before A (where most
- * other interesting punctuations occur)
+ * other interesting punctuations occur).
*/
+
uniLeftLower = Tcl_UniCharToLower(uniLeft);
uniRightLower = Tcl_UniCharToLower(uniRight);
} else {
@@ -4276,18 +4099,18 @@ DictionaryCompare(left, right)
break;
}
- diff = uniLeftLower - uniRightLower;
- if (diff) {
+ diff = uniLeftLower - uniRightLower;
+ if (diff) {
return diff;
- } else if (secondaryDiff == 0) {
- if (Tcl_UniCharIsUpper(uniLeft) &&
- Tcl_UniCharIsLower(uniRight)) {
+ }
+ if (secondaryDiff == 0) {
+ if (Tcl_UniCharIsUpper(uniLeft) && Tcl_UniCharIsLower(uniRight)) {
secondaryDiff = -1;
} else if (Tcl_UniCharIsUpper(uniRight)
&& Tcl_UniCharIsLower(uniLeft)) {
secondaryDiff = 1;
}
- }
+ }
}
if (diff == 0) {
diff = secondaryDiff;
@@ -4296,10 +4119,90 @@ DictionaryCompare(left, right)
}
/*
+ *----------------------------------------------------------------------
+ *
+ * SelectObjFromSublist --
+ *
+ * This procedure is invoked from lsearch and SortCompare. It is used for
+ * implementing the -index option, for the lsort and lsearch commands.
+ *
+ * Results:
+ * Returns NULL if a failure occurs, and sets the result in the infoPtr.
+ * Otherwise returns the Tcl_Obj* to the item.
+ *
+ * Side effects:
+ * None.
+ *
+ * Note:
+ * No reference counting is done, as the result is only used internally
+ * and never passed directly to user code.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+SelectObjFromSublist(
+ Tcl_Obj *objPtr, /* Obj to select sublist from. */
+ SortInfo *infoPtr) /* Information passed from the top-level
+ * "lsearch" or "lsort" command. */
+{
+ int i;
+
+ /*
+ * Quick check for case when no "-index" option is there.
+ */
+
+ if (infoPtr->indexc == 0) {
+ return objPtr;
+ }
+
+ /*
+ * Iterate over the indices, traversing through the nested sublists as we
+ * go.
+ */
+
+ for (i=0 ; i<infoPtr->indexc ; i++) {
+ int listLen, index;
+ Tcl_Obj *currentObj;
+
+ if (TclListObjLength(infoPtr->interp, objPtr, &listLen) != TCL_OK) {
+ infoPtr->resultCode = TCL_ERROR;
+ return NULL;
+ }
+ index = infoPtr->indexv[i];
+
+ /*
+ * Adjust for end-based indexing.
+ */
+
+ if (index < SORTIDX_NONE) {
+ index += listLen + 1;
+ }
+
+ if (Tcl_ListObjIndex(infoPtr->interp, objPtr, index,
+ &currentObj) != TCL_OK) {
+ infoPtr->resultCode = TCL_ERROR;
+ return NULL;
+ }
+ if (currentObj == NULL) {
+ char buffer[TCL_INTEGER_SPACE];
+
+ TclFormatInt(buffer, index);
+ Tcl_AppendResult(infoPtr->interp, "element ", buffer,
+ " missing from sublist \"", TclGetString(objPtr), "\"",
+ NULL);
+ infoPtr->resultCode = TCL_ERROR;
+ return NULL;
+ }
+ objPtr = currentObj;
+ }
+ return objPtr;
+}
+
+/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
*/
-
diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c
index ccf3bc6..60a9414 100644
--- a/generic/tclCmdMZ.c
+++ b/generic/tclCmdMZ.c
@@ -1,153 +1,34 @@
-/*
+/*
* tclCmdMZ.c --
*
- * This file contains the top-level command routines for most of
- * the Tcl built-in commands whose names begin with the letters
- * M to Z. It contains only commands in the generic core (i.e.
- * those that don't depend much upon UNIX facilities).
+ * This file contains the top-level command routines for most of the Tcl
+ * built-in commands whose names begin with the letters M to Z. It
+ * contains only commands in the generic core (i.e. those that don't
+ * depend much upon UNIX facilities).
*
* Copyright (c) 1987-1993 The Regents of the University of California.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
* Copyright (c) 1998-2000 Scriptics Corporation.
* Copyright (c) 2002 ActiveState Corporation.
+ * Copyright (c) 2003 Donal K. Fellows.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
#include "tclRegexp.h"
-#include "tclCompile.h"
-
-/*
- * Structures used to hold information about variable traces:
- */
-
-typedef struct {
- int flags; /* Operations for which Tcl command is
- * to be invoked. */
- size_t length; /* Number of non-NULL chars. in command. */
- char command[4]; /* Space for Tcl command to invoke. Actual
- * size will be as large as necessary to
- * hold command. This field must be the
- * last in the structure, so that it can
- * be larger than 4 bytes. */
-} TraceVarInfo;
-
-typedef struct {
- VarTrace trace;
- TraceVarInfo tvar;
-} CompoundVarTrace;
-
-/*
- * Structure used to hold information about command traces:
- */
-
-typedef struct {
- int flags; /* Operations for which Tcl command is
- * to be invoked. */
- size_t length; /* Number of non-NULL chars. in command. */
- Tcl_Trace stepTrace; /* Used for execution traces, when tracing
- * inside the given command */
- int startLevel; /* Used for bookkeeping with step execution
- * traces, store the level at which the step
- * trace was invoked */
- char *startCmd; /* Used for bookkeeping with step execution
- * traces, store the command name which invoked
- * step trace */
- int curFlags; /* Trace flags for the current command */
- int curCode; /* Return code for the current command */
- int refCount; /* Used to ensure this structure is
- * not deleted too early. Keeps track
- * of how many pieces of code have
- * a pointer to this structure. */
- char command[4]; /* Space for Tcl command to invoke. Actual
- * size will be as large as necessary to
- * hold command. This field must be the
- * last in the structure, so that it can
- * be larger than 4 bytes. */
-} TraceCommandInfo;
-
-/*
- * Used by command execution traces. Note that we assume in the code
- * that the first two defines are exactly 4 times the
- * 'TCL_TRACE_ENTER_EXEC' and 'TCL_TRACE_LEAVE_EXEC' constants.
- *
- * TCL_TRACE_ENTER_DURING_EXEC - Trace each command inside the command
- * currently being traced, before execution.
- * TCL_TRACE_LEAVE_DURING_EXEC - Trace each command inside the command
- * currently being traced, after execution.
- * TCL_TRACE_ANY_EXEC - OR'd combination of all EXEC flags.
- * TCL_TRACE_EXEC_IN_PROGRESS - The callback procedure on this trace
- * is currently executing. Therefore we
- * don't let further traces execute.
- * TCL_TRACE_EXEC_DIRECT - This execution trace is triggered directly
- * by the command being traced, not because
- * of an internal trace.
- * The flags 'TCL_TRACE_DESTROYED' and 'TCL_INTERP_DESTROYED' may also
- * be used in command execution traces.
- */
-#define TCL_TRACE_ENTER_DURING_EXEC 4
-#define TCL_TRACE_LEAVE_DURING_EXEC 8
-#define TCL_TRACE_ANY_EXEC 15
-#define TCL_TRACE_EXEC_IN_PROGRESS 0x10
-#define TCL_TRACE_EXEC_DIRECT 0x20
-
-/*
- * Forward declarations for procedures defined in this file:
- */
-
-typedef int (Tcl_TraceTypeObjCmd) _ANSI_ARGS_((Tcl_Interp *interp,
- int optionIndex, int objc, Tcl_Obj *CONST objv[]));
-
-Tcl_TraceTypeObjCmd TclTraceVariableObjCmd;
-Tcl_TraceTypeObjCmd TclTraceCommandObjCmd;
-Tcl_TraceTypeObjCmd TclTraceExecutionObjCmd;
-/*
- * Each subcommand has a number of 'types' to which it can apply.
- * Currently 'execution', 'command' and 'variable' are the only
- * types supported. These three arrays MUST be kept in sync!
- * In the future we may provide an API to add to the list of
- * supported trace types.
- */
-static CONST char *traceTypeOptions[] = {
- "execution", "command", "variable", (char*) NULL
-};
-static Tcl_TraceTypeObjCmd* traceSubCmds[] = {
- TclTraceExecutionObjCmd,
- TclTraceCommandObjCmd,
- TclTraceVariableObjCmd,
-};
-
-/*
- * Declarations for local procedures to this file:
- */
-static int CallTraceProcedure _ANSI_ARGS_((Tcl_Interp *interp,
- Trace *tracePtr, Command *cmdPtr,
- CONST char *command, int numChars,
- int objc, Tcl_Obj *CONST objv[]));
-static char * TraceVarProc _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, CONST char *name1,
- CONST char *name2, int flags));
-static void TraceCommandProc _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, CONST char *oldName,
- CONST char *newName, int flags));
-static Tcl_CmdObjTraceProc TraceExecutionProc;
-
-#ifdef TCL_TIP280
-static void ListLines _ANSI_ARGS_((Tcl_Obj* listObj, int line,
- int n, int* lines,
- Tcl_Obj* const* elems));
-#endif
+static int UniCharIsAscii(int character);
+static int UniCharIsHexDigit(int character);
+
/*
*----------------------------------------------------------------------
*
* Tcl_PwdObjCmd --
*
- * This procedure is invoked to process the "pwd" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "pwd" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -158,13 +39,12 @@ static void ListLines _ANSI_ARGS_((Tcl_Obj* listObj, int line,
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
int
-Tcl_PwdObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_PwdObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
Tcl_Obj *retVal;
@@ -187,8 +67,8 @@ Tcl_PwdObjCmd(dummy, interp, objc, objv)
*
* Tcl_RegexpObjCmd --
*
- * This procedure is invoked to process the "regexp" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "regexp" Tcl command. See
+ * the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -199,23 +79,22 @@ Tcl_PwdObjCmd(dummy, interp, objc, objv)
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
int
-Tcl_RegexpObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_RegexpObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
int i, indices, match, about, offset, all, doinline, numMatchesSaved;
- int cflags, eflags, stringLength;
+ int cflags, eflags, stringLength, matchLength;
Tcl_RegExp regExpr;
- Tcl_Obj *objPtr, *resultPtr;
+ Tcl_Obj *objPtr, *startIndex = NULL, *resultPtr = NULL;
Tcl_RegExpInfo info;
static CONST char *options[] = {
"-all", "-about", "-indices", "-inline",
"-expanded", "-line", "-linestop", "-lineanchor",
- "-nocase", "-start", "--", (char *) NULL
+ "-nocase", "-start", "--", NULL
};
enum options {
REGEXP_ALL, REGEXP_ABOUT, REGEXP_INDICES, REGEXP_INLINE,
@@ -223,165 +102,177 @@ Tcl_RegexpObjCmd(dummy, interp, objc, objv)
REGEXP_NOCASE, REGEXP_START, REGEXP_LAST
};
- indices = 0;
- about = 0;
- cflags = TCL_REG_ADVANCED;
- eflags = 0;
- offset = 0;
- all = 0;
- doinline = 0;
-
+ indices = 0;
+ about = 0;
+ cflags = TCL_REG_ADVANCED;
+ eflags = 0;
+ offset = 0;
+ all = 0;
+ doinline = 0;
+
for (i = 1; i < objc; i++) {
char *name;
int index;
- name = Tcl_GetString(objv[i]);
+ name = TclGetString(objv[i]);
if (name[0] != '-') {
break;
}
if (Tcl_GetIndexFromObj(interp, objv[i], options, "switch", TCL_EXACT,
&index) != TCL_OK) {
- return TCL_ERROR;
+ goto optionError;
}
switch ((enum options) index) {
- case REGEXP_ALL: {
- all = 1;
- break;
- }
- case REGEXP_INDICES: {
- indices = 1;
- break;
- }
- case REGEXP_INLINE: {
- doinline = 1;
- break;
- }
- case REGEXP_NOCASE: {
- cflags |= TCL_REG_NOCASE;
- break;
- }
- case REGEXP_ABOUT: {
- about = 1;
- break;
- }
- case REGEXP_EXPANDED: {
- cflags |= TCL_REG_EXPANDED;
- break;
- }
- case REGEXP_LINE: {
- cflags |= TCL_REG_NEWLINE;
- break;
- }
- case REGEXP_LINESTOP: {
- cflags |= TCL_REG_NLSTOP;
- break;
+ case REGEXP_ALL:
+ all = 1;
+ break;
+ case REGEXP_INDICES:
+ indices = 1;
+ break;
+ case REGEXP_INLINE:
+ doinline = 1;
+ break;
+ case REGEXP_NOCASE:
+ cflags |= TCL_REG_NOCASE;
+ break;
+ case REGEXP_ABOUT:
+ about = 1;
+ break;
+ case REGEXP_EXPANDED:
+ cflags |= TCL_REG_EXPANDED;
+ break;
+ case REGEXP_LINE:
+ cflags |= TCL_REG_NEWLINE;
+ break;
+ case REGEXP_LINESTOP:
+ cflags |= TCL_REG_NLSTOP;
+ break;
+ case REGEXP_LINEANCHOR:
+ cflags |= TCL_REG_NLANCH;
+ break;
+ case REGEXP_START: {
+ int temp;
+ if (++i >= objc) {
+ goto endOfForLoop;
}
- case REGEXP_LINEANCHOR: {
- cflags |= TCL_REG_NLANCH;
- break;
+ if (TclGetIntForIndexM(interp, objv[i], 0, &temp) != TCL_OK) {
+ goto optionError;
}
- case REGEXP_START: {
- if (++i >= objc) {
- goto endOfForLoop;
- }
- if (Tcl_GetIntFromObj(interp, objv[i], &offset) != TCL_OK) {
- return TCL_ERROR;
- }
- if (offset < 0) {
- offset = 0;
- }
- break;
- }
- case REGEXP_LAST: {
- i++;
- goto endOfForLoop;
+ if (startIndex) {
+ Tcl_DecrRefCount(startIndex);
}
+ startIndex = objv[i];
+ Tcl_IncrRefCount(startIndex);
+ break;
+ }
+ case REGEXP_LAST:
+ i++;
+ goto endOfForLoop;
}
}
- endOfForLoop:
+ endOfForLoop:
if ((objc - i) < (2 - about)) {
- Tcl_WrongNumArgs(interp, 1, objv,
- "?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?");
- return TCL_ERROR;
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?");
+ goto optionError;
}
objc -= i;
objv += i;
+ /*
+ * Check if the user requested -inline, but specified match variables; a
+ * no-no.
+ */
+
if (doinline && ((objc - 2) != 0)) {
- /*
- * User requested -inline, but specified match variables - a no-no.
- */
- Tcl_AppendResult(interp, "regexp match variables not allowed",
- " when using -inline", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "regexp match variables not allowed"
+ " when using -inline", NULL);
+ goto optionError;
}
/*
* Handle the odd about case separately.
*/
+
if (about) {
regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags);
if ((regExpr == NULL) || (TclRegAbout(interp, regExpr) < 0)) {
+ optionError:
+ if (startIndex) {
+ Tcl_DecrRefCount(startIndex);
+ }
return TCL_ERROR;
}
return TCL_OK;
}
/*
- * Get the length of the string that we are matching against so
- * we can do the termination test for -all matches. Do this before
- * getting the regexp to avoid shimmering problems.
+ * Get the length of the string that we are matching against so we can do
+ * the termination test for -all matches. Do this before getting the
+ * regexp to avoid shimmering problems.
*/
+
objPtr = objv[1];
stringLength = Tcl_GetCharLength(objPtr);
+ if (startIndex) {
+ TclGetIntForIndexM(NULL, startIndex, stringLength, &offset);
+ Tcl_DecrRefCount(startIndex);
+ if (offset < 0) {
+ offset = 0;
+ }
+ }
+
regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags);
if (regExpr == NULL) {
return TCL_ERROR;
}
- if (offset > 0) {
- /*
- * Add flag if using offset (string is part of a larger string),
- * so that "^" won't match.
- */
- eflags |= TCL_REG_NOTBOL;
- }
-
objc -= 2;
objv += 2;
- resultPtr = Tcl_GetObjResult(interp);
if (doinline) {
/*
* Save all the subexpressions, as we will return them as a list
*/
+
numMatchesSaved = -1;
} else {
/*
- * Save only enough subexpressions for matches we want to keep,
- * expect in the case of -all, where we need to keep at least
- * one to know where to move the offset.
+ * Save only enough subexpressions for matches we want to keep, expect
+ * in the case of -all, where we need to keep at least one to know
+ * where to move the offset.
*/
+
numMatchesSaved = (objc == 0) ? all : objc;
}
/*
- * The following loop is to handle multiple matches within the
- * same source string; each iteration handles one match. If "-all"
- * hasn't been specified then the loop body only gets executed once.
- * We terminate the loop when the starting offset is past the end of the
- * string.
+ * The following loop is to handle multiple matches within the same source
+ * string; each iteration handles one match. If "-all" hasn't been
+ * specified then the loop body only gets executed once. We terminate the
+ * loop when the starting offset is past the end of the string.
*/
while (1) {
- match = Tcl_RegExpExecObj(interp, regExpr, objPtr,
- offset /* offset */, numMatchesSaved, eflags
- | ((offset > 0 &&
- (Tcl_GetUniChar(objPtr,offset-1) != (Tcl_UniChar)'\n'))
- ? TCL_REG_NOTBOL : 0));
+ /*
+ * Pass either 0 or TCL_REG_NOTBOL in the eflags. Passing
+ * TCL_REG_NOTBOL indicates that the character at offset should not be
+ * considered the start of the line. If for example the pattern {^} is
+ * passed and -start is positive, then the pattern will not match the
+ * start of the string unless the previous character is a newline.
+ */
+ if ((offset == 0) || ((offset > 0) &&
+ (Tcl_GetUniChar(objPtr, offset-1) == (Tcl_UniChar)'\n'))) {
+ eflags = 0;
+ } else {
+ eflags = TCL_REG_NOTBOL;
+ }
+
+ match = Tcl_RegExpExecObj(interp, regExpr, objPtr, offset,
+ numMatchesSaved, eflags);
if (match < 0) {
return TCL_ERROR;
}
@@ -391,16 +282,16 @@ Tcl_RegexpObjCmd(dummy, interp, objc, objv)
* We want to set the value of the intepreter result only when
* this is the first time through the loop.
*/
+
if (all <= 1) {
/*
- * If inlining, set the interpreter's object result to an
- * empty list, otherwise set it to an integer object w/
- * value 0.
+ * If inlining, the interpreter's object result remains an
+ * empty list, otherwise set it to an integer object w/ value
+ * 0.
*/
- if (doinline) {
- Tcl_SetListObj(resultPtr, 0, NULL);
- } else {
- Tcl_SetIntObj(resultPtr, 0);
+
+ if (!doinline) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
}
return TCL_OK;
}
@@ -408,17 +299,21 @@ Tcl_RegexpObjCmd(dummy, interp, objc, objv)
}
/*
- * If additional variable names have been specified, return
- * index information in those variables.
+ * If additional variable names have been specified, return index
+ * information in those variables.
*/
Tcl_RegExpGetInfo(regExpr, &info);
if (doinline) {
/*
- * It's the number of substitutions, plus one for the matchVar
- * at index 0
+ * It's the number of substitutions, plus one for the matchVar at
+ * index 0
*/
+
objc = info.nsubs + 1;
+ if (all <= 1) {
+ resultPtr = Tcl_NewObj();
+ }
}
for (i = 0; i < objc; i++) {
Tcl_Obj *newPtr;
@@ -428,12 +323,13 @@ Tcl_RegexpObjCmd(dummy, interp, objc, objv)
Tcl_Obj *objs[2];
/*
- * Only adjust the match area if there was a match for
- * that area. (Scriptics Bug 4391/SF Bug #219232)
+ * Only adjust the match area if there was a match for that
+ * area. (Scriptics Bug 4391/SF Bug #219232)
*/
+
if (i <= info.nsubs && info.matches[i].start >= 0) {
start = offset + info.matches[i].start;
- end = offset + info.matches[i].end;
+ end = offset + info.matches[i].end;
/*
* Adjust index so it refers to the last character in the
@@ -445,7 +341,7 @@ Tcl_RegexpObjCmd(dummy, interp, objc, objv)
}
} else {
start = -1;
- end = -1;
+ end = -1;
}
objs[0] = Tcl_NewLongObj(start);
@@ -465,6 +361,7 @@ Tcl_RegexpObjCmd(dummy, interp, objc, objv)
if (Tcl_ListObjAppendElement(interp, resultPtr, newPtr)
!= TCL_OK) {
Tcl_DecrRefCount(newPtr);
+ Tcl_DecrRefCount(resultPtr);
return TCL_ERROR;
}
} else {
@@ -472,8 +369,7 @@ Tcl_RegexpObjCmd(dummy, interp, objc, objv)
valuePtr = Tcl_ObjSetVar2(interp, objv[i], NULL, newPtr, 0);
if (valuePtr == NULL) {
Tcl_AppendResult(interp, "couldn't set variable \"",
- Tcl_GetString(objv[i]), "\"", (char *) NULL);
- Tcl_DecrRefCount(newPtr);
+ TclGetString(objv[i]), "\"", NULL);
return TCL_ERROR;
}
}
@@ -482,37 +378,44 @@ Tcl_RegexpObjCmd(dummy, interp, objc, objv)
if (all == 0) {
break;
}
+
/*
- * Adjust the offset to the character just after the last one
- * in the matchVar and increment all to count how many times
- * we are making a match. We always increment the offset by at least
- * one to prevent endless looping (as in the case:
- * regexp -all {a*} a). Otherwise, when we match the NULL string at
- * the end of the input string, we will loop indefinately (because the
- * length of the match is 0, so offset never changes).
+ * Adjust the offset to the character just after the last one in the
+ * matchVar and increment all to count how many times we are making a
+ * match. We always increment the offset by at least one to prevent
+ * endless looping (as in the case: regexp -all {a*} a). Otherwise,
+ * when we match the NULL string at the end of the input string, we
+ * will loop indefinately (because the length of the match is 0, so
+ * offset never changes).
*/
- if (info.matches[0].end == 0) {
+
+ matchLength = info.matches[0].end - info.matches[0].start;
+ offset += info.matches[0].end;
+
+ /*
+ * A match of length zero could happen for {^} {$} or {.*} and in
+ * these cases we always want to bump the index up one.
+ */
+
+ if (matchLength == 0) {
offset++;
}
- offset += info.matches[0].end;
all++;
- eflags |= TCL_REG_NOTBOL;
if (offset >= stringLength) {
break;
}
}
/*
- * Set the interpreter's object result to an integer object
- * with value 1 if -all wasn't specified, otherwise it's all-1
- * (the number of times through the while - 1).
- * Get the resultPtr again as the Tcl_ObjSetVar2 above may have
- * cause the result to change. [Patch #558324] (watson).
+ * Set the interpreter's object result to an integer object with value 1
+ * if -all wasn't specified, otherwise it's all-1 (the number of times
+ * through the while - 1).
*/
- if (!doinline) {
- resultPtr = Tcl_GetObjResult(interp);
- Tcl_SetIntObj(resultPtr, (all ? all-1 : 1));
+ if (doinline) {
+ Tcl_SetObjResult(interp, resultPtr);
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(all ? all-1 : 1));
}
return TCL_OK;
}
@@ -522,8 +425,8 @@ Tcl_RegexpObjCmd(dummy, interp, objc, objv)
*
* Tcl_RegsubObjCmd --
*
- * This procedure is invoked to process the "regsub" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "regsub" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -534,19 +437,18 @@ Tcl_RegexpObjCmd(dummy, interp, objc, objv)
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
int
-Tcl_RegsubObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_RegsubObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
int idx, result, cflags, all, wlen, wsublen, numMatches, offset;
int start, end, subStart, subEnd, match;
Tcl_RegExp regExpr;
Tcl_RegExpInfo info;
- Tcl_Obj *resultPtr, *subPtr, *objPtr;
+ Tcl_Obj *resultPtr, *subPtr, *objPtr, *startIndex = NULL;
Tcl_UniChar ch, *wsrc, *wfirstChar, *wstring, *wsubspec, *wend;
static CONST char *options[] = {
@@ -568,95 +470,107 @@ Tcl_RegsubObjCmd(dummy, interp, objc, objv)
for (idx = 1; idx < objc; idx++) {
char *name;
int index;
-
- name = Tcl_GetString(objv[idx]);
+
+ name = TclGetString(objv[idx]);
if (name[0] != '-') {
break;
}
if (Tcl_GetIndexFromObj(interp, objv[idx], options, "switch",
TCL_EXACT, &index) != TCL_OK) {
- return TCL_ERROR;
+ goto optionError;
}
switch ((enum options) index) {
- case REGSUB_ALL: {
- all = 1;
- break;
- }
- case REGSUB_NOCASE: {
- cflags |= TCL_REG_NOCASE;
- break;
- }
- case REGSUB_EXPANDED: {
- cflags |= TCL_REG_EXPANDED;
- break;
- }
- case REGSUB_LINE: {
- cflags |= TCL_REG_NEWLINE;
- break;
- }
- case REGSUB_LINESTOP: {
- cflags |= TCL_REG_NLSTOP;
- break;
- }
- case REGSUB_LINEANCHOR: {
- cflags |= TCL_REG_NLANCH;
- break;
+ case REGSUB_ALL:
+ all = 1;
+ break;
+ case REGSUB_NOCASE:
+ cflags |= TCL_REG_NOCASE;
+ break;
+ case REGSUB_EXPANDED:
+ cflags |= TCL_REG_EXPANDED;
+ break;
+ case REGSUB_LINE:
+ cflags |= TCL_REG_NEWLINE;
+ break;
+ case REGSUB_LINESTOP:
+ cflags |= TCL_REG_NLSTOP;
+ break;
+ case REGSUB_LINEANCHOR:
+ cflags |= TCL_REG_NLANCH;
+ break;
+ case REGSUB_START: {
+ int temp;
+ if (++idx >= objc) {
+ goto endOfForLoop;
}
- case REGSUB_START: {
- if (++idx >= objc) {
- goto endOfForLoop;
- }
- if (Tcl_GetIntFromObj(interp, objv[idx], &offset) != TCL_OK) {
- return TCL_ERROR;
- }
- if (offset < 0) {
- offset = 0;
- }
- break;
+ if (TclGetIntForIndexM(interp, objv[idx], 0, &temp) != TCL_OK) {
+ goto optionError;
}
- case REGSUB_LAST: {
- idx++;
- goto endOfForLoop;
+ if (startIndex) {
+ Tcl_DecrRefCount(startIndex);
}
+ startIndex = objv[idx];
+ Tcl_IncrRefCount(startIndex);
+ break;
+ }
+ case REGSUB_LAST:
+ idx++;
+ goto endOfForLoop;
}
}
- endOfForLoop:
+
+ endOfForLoop:
if (objc-idx < 3 || objc-idx > 4) {
Tcl_WrongNumArgs(interp, 1, objv,
"?switches? exp string subSpec ?varName?");
+ optionError:
+ if (startIndex) {
+ Tcl_DecrRefCount(startIndex);
+ }
return TCL_ERROR;
}
objc -= idx;
objv += idx;
+ if (startIndex) {
+ int stringLength = Tcl_GetCharLength(objv[1]);
+
+ TclGetIntForIndexM(NULL, startIndex, stringLength, &offset);
+ Tcl_DecrRefCount(startIndex);
+ if (offset < 0) {
+ offset = 0;
+ }
+ }
+
if (all && (offset == 0)
- && (strpbrk(Tcl_GetString(objv[2]), "&\\") == NULL)
- && (strpbrk(Tcl_GetString(objv[0]), "*+?{}()[].\\|^$") == NULL)) {
+ && (strpbrk(TclGetString(objv[2]), "&\\") == NULL)
+ && (strpbrk(TclGetString(objv[0]), "*+?{}()[].\\|^$") == NULL)) {
/*
- * This is a simple one pair string map situation. We make use of
- * a slightly modified version of the one pair STR_MAP code.
+ * This is a simple one pair string map situation. We make use of a
+ * slightly modified version of the one pair STR_MAP code.
*/
+
int slen, nocase;
- int (*strCmpFn)_ANSI_ARGS_((CONST Tcl_UniChar *, CONST Tcl_UniChar *,
- unsigned long));
+ int (*strCmpFn)(CONST Tcl_UniChar*,CONST Tcl_UniChar*,unsigned long);
Tcl_UniChar *p, wsrclc;
numMatches = 0;
- nocase = (cflags & TCL_REG_NOCASE);
- strCmpFn = nocase ? Tcl_UniCharNcasecmp : Tcl_UniCharNcmp;
+ nocase = (cflags & TCL_REG_NOCASE);
+ strCmpFn = nocase ? Tcl_UniCharNcasecmp : Tcl_UniCharNcmp;
- wsrc = Tcl_GetUnicodeFromObj(objv[0], &slen);
- wstring = Tcl_GetUnicodeFromObj(objv[1], &wlen);
+ wsrc = Tcl_GetUnicodeFromObj(objv[0], &slen);
+ wstring = Tcl_GetUnicodeFromObj(objv[1], &wlen);
wsubspec = Tcl_GetUnicodeFromObj(objv[2], &wsublen);
- wend = wstring + wlen - (slen ? slen - 1 : 0);
- result = TCL_OK;
+ wend = wstring + wlen - (slen ? slen - 1 : 0);
+ result = TCL_OK;
if (slen == 0) {
/*
- * regsub behavior for "" matches between each character.
- * 'string map' skips the "" case.
+ * regsub behavior for "" matches between each character. 'string
+ * map' skips the "" case.
*/
+
if (wstring < wend) {
resultPtr = Tcl_NewUnicodeObj(wstring, 0);
Tcl_IncrRefCount(resultPtr);
@@ -670,10 +584,9 @@ Tcl_RegsubObjCmd(dummy, interp, objc, objv)
} else {
wsrclc = Tcl_UniCharToLower(*wsrc);
for (p = wfirstChar = wstring; wstring < wend; wstring++) {
- if (((*wstring == *wsrc) ||
- (nocase && (Tcl_UniCharToLower(*wstring) ==
- wsrclc))) &&
- ((slen == 1) || (strCmpFn(wstring, wsrc,
+ if ((*wstring == *wsrc ||
+ (nocase && Tcl_UniCharToLower(*wstring)==wsrclc)) &&
+ (slen==1 || (strCmpFn(wstring, wsrc,
(unsigned long) slen) == 0))) {
if (numMatches == 0) {
resultPtr = Tcl_NewUnicodeObj(wstring, 0);
@@ -707,9 +620,9 @@ Tcl_RegsubObjCmd(dummy, interp, objc, objv)
}
/*
- * Make sure to avoid problems where the objects are shared. This
- * can cause RegExpObj <> UnicodeObj shimmering that causes data
- * corruption. [Bug #461322]
+ * Make sure to avoid problems where the objects are shared. This can
+ * cause RegExpObj <> UnicodeObj shimmering that causes data corruption.
+ * [Bug #461322]
*/
if (objv[1] == objv[0]) {
@@ -728,27 +641,27 @@ Tcl_RegsubObjCmd(dummy, interp, objc, objv)
result = TCL_OK;
/*
- * The following loop is to handle multiple matches within the
- * same source string; each iteration handles one match and its
- * corresponding substitution. If "-all" hasn't been specified
- * then the loop body only gets executed once. We must use
- * 'offset <= wlen' in particular for the case where the regexp
- * pattern can match the empty string - this is useful when
- * doing, say, 'regsub -- ^ $str ...' when $str might be empty.
+ * The following loop is to handle multiple matches within the same source
+ * string; each iteration handles one match and its corresponding
+ * substitution. If "-all" hasn't been specified then the loop body only
+ * gets executed once. We must use 'offset <= wlen' in particular for the
+ * case where the regexp pattern can match the empty string - this is
+ * useful when doing, say, 'regsub -- ^ $str ...' when $str might be
+ * empty.
*/
numMatches = 0;
for ( ; offset <= wlen; ) {
/*
- * The flags argument is set if string is part of a larger string,
- * so that "^" won't match.
+ * The flags argument is set if string is part of a larger string, so
+ * that "^" won't match.
*/
match = Tcl_RegExpExecObj(interp, regExpr, objPtr, offset,
10 /* matches */, ((offset > 0 &&
- (wstring[offset-1] != (Tcl_UniChar)'\n'))
- ? TCL_REG_NOTBOL : 0));
+ (wstring[offset-1] != (Tcl_UniChar)'\n'))
+ ? TCL_REG_NOTBOL : 0));
if (match < 0) {
result = TCL_ERROR;
@@ -762,9 +675,10 @@ Tcl_RegsubObjCmd(dummy, interp, objc, objv)
Tcl_IncrRefCount(resultPtr);
if (offset > 0) {
/*
- * Copy the initial portion of the string in if an offset
- * was specified.
+ * Copy the initial portion of the string in if an offset was
+ * specified.
*/
+
Tcl_AppendUnicodeToObj(resultPtr, wstring, offset);
}
}
@@ -782,7 +696,7 @@ Tcl_RegsubObjCmd(dummy, interp, objc, objv)
/*
* Append the subSpec argument to the variable, making appropriate
- * substitutions. This code is a bit hairy because of the backslash
+ * substitutions. This code is a bit hairy because of the backslash
* conventions and because the code saves up ranges of characters in
* subSpec to reduce the number of calls to Tcl_SetVar.
*/
@@ -810,10 +724,12 @@ Tcl_RegsubObjCmd(dummy, interp, objc, objv)
} else {
continue;
}
+
if (wfirstChar != wsrc) {
Tcl_AppendUnicodeToObj(resultPtr, wfirstChar,
wsrc - wfirstChar);
}
+
if (idx <= info.nsubs) {
subStart = info.matches[idx].start;
subEnd = info.matches[idx].end;
@@ -822,18 +738,21 @@ Tcl_RegsubObjCmd(dummy, interp, objc, objv)
wstring + offset + subStart, subEnd - subStart);
}
}
+
if (*wsrc == '\\') {
wsrc++;
}
wfirstChar = wsrc + 1;
}
+
if (wfirstChar != wsrc) {
Tcl_AppendUnicodeToObj(resultPtr, wfirstChar, wsrc - wfirstChar);
}
+
if (end == 0) {
/*
- * Always consume at least one character of the input string
- * in order to prevent infinite loops.
+ * Always consume at least one character of the input string in
+ * order to prevent infinite loops.
*/
if (offset < wlen) {
@@ -844,10 +763,10 @@ Tcl_RegsubObjCmd(dummy, interp, objc, objv)
offset += end;
if (start == end) {
/*
- * We matched an empty string, which means we must go
- * forward one more step so we don't match again at the
- * same spot.
+ * We matched an empty string, which means we must go forward
+ * one more step so we don't match again at the same spot.
*/
+
if (offset < wlen) {
Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, 1);
}
@@ -863,12 +782,14 @@ Tcl_RegsubObjCmd(dummy, interp, objc, objv)
* Copy the portion of the source string after the last match to the
* result variable.
*/
- regsubDone:
+
+ regsubDone:
if (numMatches == 0) {
/*
- * On zero matches, just ignore the offset, since it shouldn't
- * matter to us in this case, and the user may have skewed it.
+ * On zero matches, just ignore the offset, since it shouldn't matter
+ * to us in this case, and the user may have skewed it.
*/
+
resultPtr = objv[1];
Tcl_IncrRefCount(resultPtr);
} else if (offset < wlen) {
@@ -877,27 +798,34 @@ Tcl_RegsubObjCmd(dummy, interp, objc, objv)
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);
+ TclGetString(objv[3]), "\"", NULL);
result = TCL_ERROR;
} else {
/*
* Set the interpreter's object result to an integer object
- * holding the number of matches.
+ * holding the number of matches.
*/
- Tcl_SetIntObj(Tcl_GetObjResult(interp), numMatches);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(numMatches));
}
} else {
/*
* No varname supplied, so just return the modified string.
*/
+
Tcl_SetObjResult(interp, resultPtr);
}
- done:
- if (objPtr && (objv[1] == objv[0])) { Tcl_DecrRefCount(objPtr); }
- if (subPtr && (objv[2] == objv[0])) { Tcl_DecrRefCount(subPtr); }
- if (resultPtr) { Tcl_DecrRefCount(resultPtr); }
+ done:
+ if (objPtr && (objv[1] == objv[0])) {
+ Tcl_DecrRefCount(objPtr);
+ }
+ if (subPtr && (objv[2] == objv[0])) {
+ Tcl_DecrRefCount(subPtr);
+ }
+ if (resultPtr) {
+ Tcl_DecrRefCount(resultPtr);
+ }
return result;
}
@@ -906,8 +834,8 @@ Tcl_RegsubObjCmd(dummy, interp, objc, objv)
*
* Tcl_RenameObjCmd --
*
- * This procedure is invoked to process the "rename" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "rename" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl object result.
@@ -918,23 +846,22 @@ Tcl_RegsubObjCmd(dummy, interp, objc, objv)
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
int
-Tcl_RenameObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Arbitrary value passed to the command. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_RenameObjCmd(
+ ClientData dummy, /* Arbitrary value passed to the command. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
char *oldName, *newName;
-
+
if (objc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, "oldName newName");
return TCL_ERROR;
}
- oldName = Tcl_GetString(objv[1]);
- newName = Tcl_GetString(objv[2]);
+ oldName = TclGetString(objv[1]);
+ newName = TclGetString(objv[2]);
return TclRenameCommand(interp, oldName, newName);
}
@@ -955,83 +882,34 @@ Tcl_RenameObjCmd(dummy, interp, objc, objv)
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
int
-Tcl_ReturnObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_ReturnObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
- Interp *iPtr = (Interp *) interp;
- int optionLen, argLen, code, result;
-
- if (iPtr->errorInfo != NULL) {
- ckfree(iPtr->errorInfo);
- iPtr->errorInfo = NULL;
- }
- if (iPtr->errorCode != NULL) {
- ckfree(iPtr->errorCode);
- iPtr->errorCode = NULL;
- }
- code = TCL_OK;
-
- for (objv++, objc--; objc > 1; objv += 2, objc -= 2) {
- char *option = Tcl_GetStringFromObj(objv[0], &optionLen);
- char *arg = Tcl_GetStringFromObj(objv[1], &argLen);
-
- if (strcmp(option, "-code") == 0) {
- register int c = arg[0];
- if ((c == 'o') && (strcmp(arg, "ok") == 0)) {
- code = TCL_OK;
- } else if ((c == 'e') && (strcmp(arg, "error") == 0)) {
- code = TCL_ERROR;
- } else if ((c == 'r') && (strcmp(arg, "return") == 0)) {
- code = TCL_RETURN;
- } else if ((c == 'b') && (strcmp(arg, "break") == 0)) {
- code = TCL_BREAK;
- } else if ((c == 'c') && (strcmp(arg, "continue") == 0)) {
- code = TCL_CONTINUE;
- } else {
- result = Tcl_GetIntFromObj((Tcl_Interp *) NULL, objv[1],
- &code);
- if (result != TCL_OK) {
- Tcl_ResetResult(interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "bad completion code \"",
- Tcl_GetString(objv[1]),
- "\": must be ok, error, return, break, ",
- "continue, or an integer", (char *) NULL);
- return result;
- }
- }
- } else if (strcmp(option, "-errorinfo") == 0) {
- iPtr->errorInfo =
- (char *) ckalloc((unsigned) (strlen(arg) + 1));
- strcpy(iPtr->errorInfo, arg);
- } else if (strcmp(option, "-errorcode") == 0) {
- iPtr->errorCode =
- (char *) ckalloc((unsigned) (strlen(arg) + 1));
- strcpy(iPtr->errorCode, arg);
- } else {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "bad option \"", option,
- "\": must be -code, -errorcode, or -errorinfo",
- (char *) NULL);
- return TCL_ERROR;
- }
+ int code, level;
+ Tcl_Obj *returnOpts;
+
+ /*
+ * General syntax: [return ?-option value ...? ?result?]
+ * An even number of words means an explicit result argument is present.
+ */
+
+ int explicitResult = (0 == (objc % 2));
+ int numOptionWords = objc - 1 - explicitResult;
+
+ if (TCL_ERROR == TclMergeReturnOptions(interp, numOptionWords, objv+1,
+ &returnOpts, &code, &level)) {
+ return TCL_ERROR;
}
-
- if (objc == 1) {
- /*
- * Set the interpreter's object result. An inline version of
- * Tcl_SetObjResult.
- */
- Tcl_SetObjResult(interp, objv[0]);
+ code = TclProcessReturn(interp, code, level, returnOpts);
+ if (explicitResult) {
+ Tcl_SetObjResult(interp, objv[objc-1]);
}
- iPtr->returnCode = code;
- return TCL_RETURN;
+ return code;
}
/*
@@ -1039,8 +917,8 @@ Tcl_ReturnObjCmd(dummy, interp, objc, objv)
*
* Tcl_SourceObjCmd --
*
- * This procedure is invoked to process the "source" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "source" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl object result.
@@ -1051,20 +929,37 @@ Tcl_ReturnObjCmd(dummy, interp, objc, objv)
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
int
-Tcl_SourceObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_SourceObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "fileName");
+ CONST char *encodingName = NULL;
+ Tcl_Obj *fileName;
+
+ if (objc != 2 && objc !=4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "?-encoding name? fileName");
return TCL_ERROR;
}
- return Tcl_FSEvalFile(interp, objv[1]);
+ fileName = objv[objc-1];
+
+ if (objc == 4) {
+ static CONST char *options[] = {
+ "-encoding", NULL
+ };
+ int index;
+
+ if (TCL_ERROR == Tcl_GetIndexFromObj(interp, objv[1], options,
+ "option", TCL_EXACT, &index)) {
+ return TCL_ERROR;
+ }
+ encodingName = TclGetString(objv[2]);
+ }
+
+ return Tcl_FSEvalFileEx(interp, fileName, encodingName);
}
/*
@@ -1072,8 +967,8 @@ Tcl_SourceObjCmd(dummy, interp, objc, objv)
*
* Tcl_SplitObjCmd --
*
- * This procedure is invoked to process the "split" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "split" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -1084,17 +979,16 @@ Tcl_SourceObjCmd(dummy, interp, objc, objv)
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
int
-Tcl_SplitObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_SplitObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
Tcl_UniChar ch;
int len;
- char *splitChars, *string, *end;
+ char *splitChars, *stringPtr, *end;
int splitCharLen, stringLen;
Tcl_Obj *listPtr, *objPtr;
@@ -1102,16 +996,16 @@ Tcl_SplitObjCmd(dummy, interp, objc, objv)
splitChars = " \n\t\r";
splitCharLen = 4;
} else if (objc == 3) {
- splitChars = Tcl_GetStringFromObj(objv[2], &splitCharLen);
+ splitChars = TclGetStringFromObj(objv[2], &splitCharLen);
} else {
Tcl_WrongNumArgs(interp, 1, objv, "string ?splitChars?");
return TCL_ERROR;
}
- string = Tcl_GetStringFromObj(objv[1], &stringLen);
- end = string + stringLen;
- listPtr = Tcl_GetObjResult(interp);
-
+ stringPtr = TclGetStringFromObj(objv[1], &stringLen);
+ end = stringPtr + stringLen;
+ listPtr = Tcl_NewObj();
+
if (stringLen == 0) {
/*
* Do nothing.
@@ -1124,87 +1018,92 @@ Tcl_SplitObjCmd(dummy, interp, objc, objv)
/*
* Handle the special case of splitting on every character.
*
- * Uses a hash table to ensure that each kind of character has
- * only one Tcl_Obj instance (multiply-referenced) in the
- * final list. This is a *major* win when splitting on a long
- * string (especially in the megabyte range!) - DKF
+ * Uses a hash table to ensure that each kind of character has only
+ * one Tcl_Obj instance (multiply-referenced) in the final list. This
+ * is a *major* win when splitting on a long string (especially in the
+ * megabyte range!) - DKF
*/
Tcl_InitHashTable(&charReuseTable, TCL_ONE_WORD_KEYS);
- for ( ; string < end; string += len) {
- len = TclUtfToUniChar(string, &ch);
- /* Assume Tcl_UniChar is an integral type... */
- hPtr = Tcl_CreateHashEntry(&charReuseTable, (char*)0 + ch, &isNew);
+
+ for ( ; stringPtr < end; stringPtr += len) {
+ len = TclUtfToUniChar(stringPtr, &ch);
+
+ /*
+ * Assume Tcl_UniChar is an integral type...
+ */
+
+ hPtr = Tcl_CreateHashEntry(&charReuseTable, (char*)0+ch, &isNew);
if (isNew) {
- objPtr = Tcl_NewStringObj(string, len);
- /* Don't need to fiddle with refcount... */
+ TclNewStringObj(objPtr, stringPtr, len);
+
+ /*
+ * Don't need to fiddle with refcount...
+ */
+
Tcl_SetHashValue(hPtr, (ClientData) objPtr);
} else {
- objPtr = (Tcl_Obj*) Tcl_GetHashValue(hPtr);
+ objPtr = (Tcl_Obj *) Tcl_GetHashValue(hPtr);
}
Tcl_ListObjAppendElement(NULL, listPtr, objPtr);
}
Tcl_DeleteHashTable(&charReuseTable);
+
} else if (splitCharLen == 1) {
char *p;
/*
- * Handle the special case of splitting on a single character.
- * This is only true for the one-char ASCII case, as one unicode
- * char is > 1 byte in length.
+ * Handle the special case of splitting on a single character. This is
+ * only true for the one-char ASCII case, as one unicode char is > 1
+ * byte in length.
*/
- while (*string && (p = strchr(string, (int) *splitChars)) != NULL) {
- objPtr = Tcl_NewStringObj(string, p - string);
+ while (*stringPtr && (p=strchr(stringPtr,(int)*splitChars)) != NULL) {
+ objPtr = Tcl_NewStringObj(stringPtr, p - stringPtr);
Tcl_ListObjAppendElement(NULL, listPtr, objPtr);
- string = p + 1;
+ stringPtr = p + 1;
}
- objPtr = Tcl_NewStringObj(string, end - string);
+ TclNewStringObj(objPtr, stringPtr, end - stringPtr);
Tcl_ListObjAppendElement(NULL, listPtr, objPtr);
} else {
char *element, *p, *splitEnd;
int splitLen;
Tcl_UniChar splitChar;
-
+
/*
- * Normal case: split on any of a given set of characters.
- * Discard instances of the split characters.
+ * Normal case: split on any of a given set of characters. Discard
+ * instances of the split characters.
*/
splitEnd = splitChars + splitCharLen;
- for (element = string; string < end; string += len) {
- len = TclUtfToUniChar(string, &ch);
+ for (element = stringPtr; stringPtr < end; stringPtr += len) {
+ len = TclUtfToUniChar(stringPtr, &ch);
for (p = splitChars; p < splitEnd; p += splitLen) {
splitLen = TclUtfToUniChar(p, &splitChar);
if (ch == splitChar) {
- objPtr = Tcl_NewStringObj(element, string - element);
+ TclNewStringObj(objPtr, element, stringPtr - element);
Tcl_ListObjAppendElement(NULL, listPtr, objPtr);
- element = string + len;
+ element = stringPtr + len;
break;
}
}
}
- objPtr = Tcl_NewStringObj(element, string - element);
+
+ TclNewStringObj(objPtr, element, stringPtr - element);
Tcl_ListObjAppendElement(NULL, listPtr, objPtr);
}
+ Tcl_SetObjResult(interp, listPtr);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * Tcl_StringObjCmd --
- *
- * This procedure is invoked to process the "string" Tcl command.
- * See the user documentation for details on what it does. Note
- * that this command only functions correctly on properly formed
- * Tcl UTF strings.
+ * StringFirstCmd --
*
- * Note that the primary methods here (equal, compare, match, ...)
- * have bytecode equivalents. You will find the code for those in
- * tclExecute.c. The code here will only be used in the non-bc
- * case (like in an 'eval').
+ * This procedure is invoked to process the "string first" Tcl command.
+ * See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -1215,1248 +1114,882 @@ Tcl_SplitObjCmd(dummy, interp, objc, objv)
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
-int
-Tcl_StringObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+static int
+StringFirstCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- int index, left, right;
- Tcl_Obj *resultPtr;
- char *string1, *string2;
- int length1, length2;
- static CONST char *options[] = {
- "bytelength", "compare", "equal", "first",
- "index", "is", "last", "length",
- "map", "match", "range", "repeat",
- "replace", "tolower", "toupper", "totitle",
- "trim", "trimleft", "trimright",
- "wordend", "wordstart", (char *) NULL
- };
- enum options {
- STR_BYTELENGTH, STR_COMPARE, STR_EQUAL, STR_FIRST,
- STR_INDEX, STR_IS, STR_LAST, STR_LENGTH,
- STR_MAP, STR_MATCH, STR_RANGE, STR_REPEAT,
- STR_REPLACE, STR_TOLOWER, STR_TOUPPER, STR_TOTITLE,
- STR_TRIM, STR_TRIMLEFT, STR_TRIMRIGHT,
- STR_WORDEND, STR_WORDSTART
- };
-
- if (objc < 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
- return TCL_ERROR;
- }
-
- if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0,
- &index) != TCL_OK) {
+ Tcl_UniChar *ustring1, *ustring2;
+ int match, start, length1, length2;
+
+ if (objc < 3 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "needleString haystackString ?startIndex?");
return TCL_ERROR;
}
- resultPtr = Tcl_GetObjResult(interp);
- switch ((enum options) index) {
- case STR_EQUAL:
- case STR_COMPARE: {
- /*
- * Remember to keep code here in some sync with the
- * byte-compiled versions in tclExecute.c (INST_STR_EQ,
- * INST_STR_NEQ and INST_STR_CMP as well as the expr string
- * comparison in INST_EQ/INST_NEQ/INST_LT/...).
- */
- int i, match, length, nocase = 0, reqlength = -1;
- int (*strCmpFn)();
-
- if (objc < 4 || objc > 7) {
- str_cmp_args:
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-nocase? ?-length int? string1 string2");
- return TCL_ERROR;
- }
-
- for (i = 2; i < objc-2; i++) {
- string2 = Tcl_GetStringFromObj(objv[i], &length2);
- if ((length2 > 1)
- && strncmp(string2, "-nocase", (size_t)length2) == 0) {
- nocase = 1;
- } else if ((length2 > 1)
- && strncmp(string2, "-length", (size_t)length2) == 0) {
- if (i+1 >= objc-2) {
- goto str_cmp_args;
- }
- if (Tcl_GetIntFromObj(interp, objv[++i],
- &reqlength) != TCL_OK) {
- return TCL_ERROR;
- }
- } else {
- Tcl_AppendStringsToObj(resultPtr, "bad option \"",
- string2, "\": must be -nocase or -length",
- (char *) NULL);
- return TCL_ERROR;
- }
- }
+ /*
+ * We are searching string2 for the sequence string1.
+ */
- /*
- * From now on, we only access the two objects at the end
- * of the argument array.
- */
- objv += objc-2;
+ match = -1;
+ start = 0;
+ length2 = -1;
- if ((reqlength == 0) || (objv[0] == objv[1])) {
- /*
- * Alway match at 0 chars of if it is the same obj.
- */
+ ustring1 = Tcl_GetUnicodeFromObj(objv[1], &length1);
+ ustring2 = Tcl_GetUnicodeFromObj(objv[2], &length2);
- Tcl_SetBooleanObj(resultPtr,
- ((enum options) index == STR_EQUAL));
- break;
- } else if (!nocase && objv[0]->typePtr == &tclByteArrayType &&
- objv[1]->typePtr == &tclByteArrayType) {
- /*
- * Use binary versions of comparisons since that won't
- * cause undue type conversions and it is much faster.
- * Only do this if we're case-sensitive (which is all
- * that really makes sense with byte arrays anyway, and
- * we have no memcasecmp() for some reason... :^)
- */
- string1 = (char*) Tcl_GetByteArrayFromObj(objv[0], &length1);
- string2 = (char*) Tcl_GetByteArrayFromObj(objv[1], &length2);
- strCmpFn = memcmp;
- } else if ((objv[0]->typePtr == &tclStringType)
- && (objv[1]->typePtr == &tclStringType)) {
- /*
- * Do a unicode-specific comparison if both of the args
- * are of String type. In benchmark testing this proved
- * the most efficient check between the unicode and
- * string comparison operations.
- */
- string1 = (char*) Tcl_GetUnicodeFromObj(objv[0], &length1);
- string2 = (char*) Tcl_GetUnicodeFromObj(objv[1], &length2);
- strCmpFn = nocase ? Tcl_UniCharNcasecmp : Tcl_UniCharNcmp;
- } else {
- /*
- * As a catch-all we will work with UTF-8. We cannot use
- * memcmp() as that is unsafe with any string containing
- * NULL (\xC0\x80 in Tcl's utf rep). We can use the more
- * efficient TclpUtfNcmp2 if we are case-sensitive and no
- * specific length was requested.
- */
- string1 = (char*) Tcl_GetStringFromObj(objv[0], &length1);
- string2 = (char*) Tcl_GetStringFromObj(objv[1], &length2);
- if ((reqlength < 0) && !nocase) {
- strCmpFn = TclpUtfNcmp2;
- } else {
- length1 = Tcl_NumUtfChars(string1, length1);
- length2 = Tcl_NumUtfChars(string2, length2);
- strCmpFn = nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp;
- }
- }
-
- if (((enum options) index == STR_EQUAL)
- && (reqlength < 0) && (length1 != length2)) {
- match = 1; /* this will be reversed below */
- } else {
- length = (length1 < length2) ? length1 : length2;
- if (reqlength > 0 && reqlength < length) {
- length = reqlength;
- } else if (reqlength < 0) {
- /*
- * The requested length is negative, so we ignore it by
- * setting it to length + 1 so we correct the match var.
- */
- reqlength = length + 1;
- }
- match = strCmpFn(string1, string2, (unsigned) length);
- if ((match == 0) && (reqlength > length)) {
- match = length1 - length2;
- }
- }
+ if (objc == 4) {
+ /*
+ * If a startIndex is specified, we will need to fast forward to that
+ * point in the string before we think about a match.
+ */
- if ((enum options) index == STR_EQUAL) {
- Tcl_SetBooleanObj(resultPtr, (match) ? 0 : 1);
- } else {
- Tcl_SetIntObj(resultPtr, ((match > 0) ? 1 :
- (match < 0) ? -1 : 0));
- }
- break;
+ if (TclGetIntForIndexM(interp, objv[3], length2-1, &start) != TCL_OK){
+ return TCL_ERROR;
}
- case STR_FIRST: {
- Tcl_UniChar *ustring1, *ustring2;
- int match, start;
- if (objc < 4 || objc > 5) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "subString string ?startIndex?");
- return TCL_ERROR;
- }
+ /*
+ * Reread to prevent shimmering problems.
+ */
+
+ ustring1 = Tcl_GetUnicodeFromObj(objv[1], &length1);
+ ustring2 = Tcl_GetUnicodeFromObj(objv[2], &length2);
+ if (start >= length2) {
+ goto str_first_done;
+ } else if (start > 0) {
+ ustring2 += start;
+ length2 -= start;
+ } else if (start < 0) {
/*
- * We are searching string2 for the sequence string1.
+ * Invalid start index mapped to string start; Bug #423581
*/
- match = -1;
start = 0;
- length2 = -1;
-
- ustring1 = Tcl_GetUnicodeFromObj(objv[2], &length1);
- ustring2 = Tcl_GetUnicodeFromObj(objv[3], &length2);
+ }
+ }
- if (objc == 5) {
- /*
- * If a startIndex is specified, we will need to fast
- * forward to that point in the string before we think
- * about a match
- */
- if (TclGetIntForIndex(interp, objv[4], length2 - 1,
- &start) != TCL_OK) {
- return TCL_ERROR;
- }
- if (start >= length2) {
- goto str_first_done;
- } else if (start > 0) {
- ustring2 += start;
- length2 -= start;
- } else if (start < 0) {
- /*
- * Invalid start index mapped to string start;
- * Bug #423581
- */
- start = 0;
- }
- }
+ /*
+ * If the length of the needle is more than the length of the haystack, it
+ * cannot be contained in there so we can avoid searching. [Bug 2960021]
+ */
- if (length1 > 0) {
- register Tcl_UniChar *p, *end;
+ if (length1 > 0 && length1 <= length2) {
+ register Tcl_UniChar *p, *end;
- end = ustring2 + length2 - length1 + 1;
- for (p = ustring2; p < end; p++) {
- /*
- * Scan forward to find the first character.
- */
- if ((*p == *ustring1) &&
- (TclUniCharNcmp(ustring1, p,
- (unsigned long) length1) == 0)) {
- match = p - ustring2;
- break;
- }
- }
- }
+ end = ustring2 + length2 - length1 + 1;
+ for (p = ustring2; p < end; p++) {
/*
- * Compute the character index of the matching string by
- * counting the number of characters before the match.
+ * Scan forward to find the first character.
*/
- if ((match != -1) && (objc == 5)) {
- match += start;
- }
- str_first_done:
- Tcl_SetIntObj(resultPtr, match);
- break;
- }
- case STR_INDEX: {
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "string charIndex");
- return TCL_ERROR;
+ if ((*p == *ustring1) && (TclUniCharNcmp(ustring1, p,
+ (unsigned long) length1) == 0)) {
+ match = p - ustring2;
+ break;
}
+ }
+ }
- /*
- * If we have a ByteArray object, avoid indexing in the
- * Utf string since the byte array contains one byte per
- * character. Otherwise, use the Unicode string rep to
- * get the index'th char.
- */
+ /*
+ * Compute the character index of the matching string by counting the
+ * number of characters before the match.
+ */
- if (objv[2]->typePtr == &tclByteArrayType) {
- string1 = (char *) Tcl_GetByteArrayFromObj(objv[2], &length1);
+ if ((match != -1) && (objc == 4)) {
+ match += start;
+ }
- if (TclGetIntForIndex(interp, objv[3], length1 - 1,
- &index) != TCL_OK) {
- return TCL_ERROR;
- }
- if ((index >= 0) && (index < length1)) {
- Tcl_SetByteArrayObj(resultPtr,
- (unsigned char *)(&string1[index]), 1);
- }
- } else {
- /*
- * Get Unicode char length to calulate what 'end' means.
- */
- length1 = Tcl_GetCharLength(objv[2]);
+ str_first_done:
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(match));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringLastCmd --
+ *
+ * This procedure is invoked to process the "string last" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
- if (TclGetIntForIndex(interp, objv[3], length1 - 1,
- &index) != TCL_OK) {
- return TCL_ERROR;
- }
- if ((index >= 0) && (index < length1)) {
- char buf[TCL_UTF_MAX];
- Tcl_UniChar ch;
+static int
+StringLastCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tcl_UniChar *ustring1, *ustring2, *p;
+ int match, start, length1, length2;
- ch = Tcl_GetUniChar(objv[2], index);
- length1 = Tcl_UniCharToUtf(ch, buf);
- Tcl_SetStringObj(resultPtr, buf, length1);
- }
- }
- break;
- }
- case STR_IS: {
- char *end;
- Tcl_UniChar ch;
+ if (objc < 3 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "needleString haystackString ?startIndex?");
+ return TCL_ERROR;
+ }
- /*
- * The UniChar comparison function
- */
+ /*
+ * We are searching string2 for the sequence string1.
+ */
- int (*chcomp)_ANSI_ARGS_((int)) = NULL;
- int i, failat = 0, result = 1, strict = 0;
- Tcl_Obj *objPtr, *failVarObj = NULL;
-
- static CONST char *isOptions[] = {
- "alnum", "alpha", "ascii", "control",
- "boolean", "digit", "double", "false",
- "graph", "integer", "lower", "print",
- "punct", "space", "true", "upper",
- "wordchar", "xdigit", (char *) NULL
- };
- enum isOptions {
- STR_IS_ALNUM, STR_IS_ALPHA, STR_IS_ASCII, STR_IS_CONTROL,
- STR_IS_BOOL, STR_IS_DIGIT, STR_IS_DOUBLE, STR_IS_FALSE,
- STR_IS_GRAPH, STR_IS_INT, STR_IS_LOWER, STR_IS_PRINT,
- STR_IS_PUNCT, STR_IS_SPACE, STR_IS_TRUE, STR_IS_UPPER,
- STR_IS_WORD, STR_IS_XDIGIT
- };
-
- if (objc < 4 || objc > 7) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "class ?-strict? ?-failindex var? str");
- return TCL_ERROR;
- }
- if (Tcl_GetIndexFromObj(interp, objv[2], isOptions, "class", 0,
- &index) != TCL_OK) {
- return TCL_ERROR;
- }
- if (objc != 4) {
- for (i = 3; i < objc-1; i++) {
- string2 = Tcl_GetStringFromObj(objv[i], &length2);
- if ((length2 > 1) &&
- strncmp(string2, "-strict", (size_t) length2) == 0) {
- strict = 1;
- } else if ((length2 > 1) &&
- strncmp(string2, "-failindex",
- (size_t) length2) == 0) {
- if (i+1 >= objc-1) {
- Tcl_WrongNumArgs(interp, 3, objv,
- "?-strict? ?-failindex var? str");
- return TCL_ERROR;
- }
- failVarObj = objv[++i];
- } else {
- Tcl_AppendStringsToObj(resultPtr, "bad option \"",
- string2, "\": must be -strict or -failindex",
- (char *) NULL);
- return TCL_ERROR;
- }
- }
- }
+ match = -1;
+ start = 0;
+ length2 = -1;
- /*
- * We get the objPtr so that we can short-cut for some classes
- * by checking the object type (int and double), but we need
- * the string otherwise, because we don't want any conversion
- * of type occuring (as, for example, Tcl_Get*FromObj would do
- */
- objPtr = objv[objc-1];
- string1 = Tcl_GetStringFromObj(objPtr, &length1);
- if (length1 == 0) {
- if (strict) {
- result = 0;
- }
- goto str_is_done;
- }
- end = string1 + length1;
+ ustring1 = Tcl_GetUnicodeFromObj(objv[1], &length1);
+ ustring2 = Tcl_GetUnicodeFromObj(objv[2], &length2);
- /*
- * When entering here, result == 1 and failat == 0
- */
- switch ((enum isOptions) index) {
- case STR_IS_ALNUM:
- chcomp = Tcl_UniCharIsAlnum;
- break;
- case STR_IS_ALPHA:
- chcomp = Tcl_UniCharIsAlpha;
- break;
- case STR_IS_ASCII:
- for (; string1 < end; string1++, failat++) {
- /*
- * This is a valid check in unicode, because all
- * bytes < 0xC0 are single byte chars (but isascii
- * limits that def'n to 0x80).
- */
- if (*((unsigned char *)string1) >= 0x80) {
- result = 0;
- break;
- }
- }
- break;
- case STR_IS_BOOL:
- case STR_IS_TRUE:
- case STR_IS_FALSE:
- /* Optimizers, beware Bug 1187123 ! */
- if ((Tcl_GetBoolean(NULL, string1, &i)
- == TCL_ERROR) ||
- (((enum isOptions) index == STR_IS_TRUE) &&
- i == 0) ||
- (((enum isOptions) index == STR_IS_FALSE) &&
- i != 0)) {
- result = 0;
- }
- break;
- case STR_IS_CONTROL:
- chcomp = Tcl_UniCharIsControl;
- break;
- case STR_IS_DIGIT:
- chcomp = Tcl_UniCharIsDigit;
- break;
- case STR_IS_DOUBLE: {
- char *stop;
+ if (objc == 4) {
+ /*
+ * If a startIndex is specified, we will need to restrict the string
+ * range to that char index in the string
+ */
- if ((objPtr->typePtr == &tclDoubleType) ||
- (objPtr->typePtr == &tclIntType)) {
- break;
- }
- /*
- * This is adapted from Tcl_GetDouble
- *
- * The danger in this function is that
- * "12345678901234567890" is an acceptable 'double',
- * but will later be interp'd as an int by something
- * like [expr]. Therefore, we check to see if it looks
- * like an int, and if so we do a range check on it.
- * If strtoul gets to the end, we know we either
- * received an acceptable int, or over/underflow
- */
- if (TclLooksLikeInt(string1, length1)) {
- errno = 0;
-#ifdef TCL_WIDE_INT_IS_LONG
- strtoul(string1, &stop, 0); /* INTL: Tcl source. */
-#else
- strtoull(string1, &stop, 0); /* INTL: Tcl source. */
-#endif
- if (stop == end) {
- if (errno == ERANGE) {
- result = 0;
- failat = -1;
- }
- break;
- }
- }
- errno = 0;
- strtod(string1, &stop); /* INTL: Tcl source. */
- if (errno == ERANGE) {
- /*
- * if (errno == ERANGE), then it was an over/underflow
- * problem, but in this method, we only want to know
- * yes or no, so bad flow returns 0 (false) and sets
- * the failVarObj to the string length.
- */
- result = 0;
- failat = -1;
- } else if (stop == string1) {
- /*
- * In this case, nothing like a number was found
- */
- result = 0;
- failat = 0;
- } else {
- /*
- * Assume we sucked up one char per byte
- * and then we go onto SPACE, since we are
- * allowed trailing whitespace
- */
- failat = stop - string1;
- string1 = stop;
- chcomp = Tcl_UniCharIsSpace;
- }
- break;
- }
- case STR_IS_GRAPH:
- chcomp = Tcl_UniCharIsGraph;
- break;
- case STR_IS_INT: {
- char *stop;
- long int l = 0;
+ if (TclGetIntForIndexM(interp, objv[3], length2-1, &start) != TCL_OK){
+ return TCL_ERROR;
+ }
- if (TCL_OK == Tcl_GetIntFromObj(NULL, objPtr, &i)) {
- break;
- }
- /*
- * Like STR_IS_DOUBLE, but we use strtoul.
- * Since Tcl_GetIntFromObj already failed,
- * we set result to 0.
- */
- result = 0;
- errno = 0;
- l = strtol(string1, &stop, 0); /* INTL: Tcl source. */
- if ((errno == ERANGE) || (l > INT_MAX) || (l < INT_MIN)) {
- /*
- * if (errno == ERANGE), then it was an over/underflow
- * problem, but in this method, we only want to know
- * yes or no, so bad flow returns 0 (false) and sets
- * the failVarObj to the string length.
- */
- failat = -1;
+ /*
+ * Reread to prevent shimmering problems.
+ */
- } else if (stop == string1) {
- /*
- * In this case, nothing like a number was found
- */
- failat = 0;
- } else {
- /*
- * Assume we sucked up one char per byte
- * and then we go onto SPACE, since we are
- * allowed trailing whitespace
- */
- failat = stop - string1;
- string1 = stop;
- chcomp = Tcl_UniCharIsSpace;
- }
- break;
- }
- case STR_IS_LOWER:
- chcomp = Tcl_UniCharIsLower;
- break;
- case STR_IS_PRINT:
- chcomp = Tcl_UniCharIsPrint;
- break;
- case STR_IS_PUNCT:
- chcomp = Tcl_UniCharIsPunct;
- break;
- case STR_IS_SPACE:
- chcomp = Tcl_UniCharIsSpace;
- break;
- case STR_IS_UPPER:
- chcomp = Tcl_UniCharIsUpper;
- break;
- case STR_IS_WORD:
- chcomp = Tcl_UniCharIsWordChar;
- break;
- case STR_IS_XDIGIT: {
- for (; string1 < end; string1++, failat++) {
- /* INTL: We assume unicode is bad for this class */
- if ((*((unsigned char *)string1) >= 0xC0) ||
- !isxdigit(*(unsigned char *)string1)) {
- result = 0;
- break;
- }
- }
- break;
- }
- }
- if (chcomp != NULL) {
- for (; string1 < end; string1 += length2, failat++) {
- length2 = TclUtfToUniChar(string1, &ch);
- if (!chcomp(ch)) {
- result = 0;
- break;
- }
- }
- }
- str_is_done:
- /*
- * Only set the failVarObj when we will return 0
- * and we have indicated a valid fail index (>= 0)
- */
- if ((result == 0) && (failVarObj != NULL)) {
- Tcl_Obj *resPtr, *tmpPtr = Tcl_NewIntObj(failat);
-
- Tcl_IncrRefCount(tmpPtr);
- resPtr = Tcl_ObjSetVar2(interp, failVarObj, NULL, tmpPtr,
- TCL_LEAVE_ERR_MSG);
- Tcl_DecrRefCount(tmpPtr);
- if (resPtr == NULL) {
- return TCL_ERROR;
- }
- }
- Tcl_SetBooleanObj(resultPtr, result);
- break;
+ ustring1 = Tcl_GetUnicodeFromObj(objv[1], &length1);
+ ustring2 = Tcl_GetUnicodeFromObj(objv[2], &length2);
+
+ if (start < 0) {
+ goto str_last_done;
+ } else if (start < length2) {
+ p = ustring2 + start + 1 - length1;
+ } else {
+ p = ustring2 + length2 - length1;
}
- case STR_LAST: {
- Tcl_UniChar *ustring1, *ustring2, *p;
- int match, start;
+ } else {
+ p = ustring2 + length2 - length1;
+ }
- if (objc < 4 || objc > 5) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "subString string ?startIndex?");
- return TCL_ERROR;
- }
+ /*
+ * If the length of the needle is more than the length of the haystack, it
+ * cannot be contained in there so we can avoid searching. [Bug 2960021]
+ */
+ if (length1 > 0 && length1 <= length2) {
+ for (; p >= ustring2; p--) {
/*
- * We are searching string2 for the sequence string1.
+ * Scan backwards to find the first character.
*/
- match = -1;
- start = 0;
- length2 = -1;
+ if ((*p == *ustring1) && !memcmp(ustring1, p,
+ sizeof(Tcl_UniChar) * (size_t)length1)) {
+ match = p - ustring2;
+ break;
+ }
+ }
+ }
- ustring1 = Tcl_GetUnicodeFromObj(objv[2], &length1);
- ustring2 = Tcl_GetUnicodeFromObj(objv[3], &length2);
+ str_last_done:
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(match));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringIndexCmd --
+ *
+ * This procedure is invoked to process the "string index" Tcl command.
+ * See the user documentation for details on what it does. Note that this
+ * command only functions correctly on properly formed Tcl UTF strings.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
- if (objc == 5) {
- /*
- * If a startIndex is specified, we will need to restrict
- * the string range to that char index in the string
- */
- if (TclGetIntForIndex(interp, objv[4], length2 - 1,
- &start) != TCL_OK) {
- return TCL_ERROR;
- }
- if (start < 0) {
- goto str_last_done;
- } else if (start < length2) {
- p = ustring2 + start + 1 - length1;
- } else {
- p = ustring2 + length2 - length1;
- }
- } else {
- p = ustring2 + length2 - length1;
- }
+static int
+StringIndexCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int length, index;
- if (length1 > 0) {
- for (; p >= ustring2; p--) {
- /*
- * Scan backwards to find the first character.
- */
- if ((*p == *ustring1) &&
- (memcmp((char *) ustring1, (char *) p, (size_t)
- (length1 * sizeof(Tcl_UniChar))) == 0)) {
- match = p - ustring2;
- break;
- }
- }
- }
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "string charIndex");
+ return TCL_ERROR;
+ }
- str_last_done:
- Tcl_SetIntObj(resultPtr, match);
- break;
+ /*
+ * If we have a ByteArray object, avoid indexing in the Utf string since
+ * the byte array contains one byte per character. Otherwise, use the
+ * Unicode string rep to get the index'th char.
+ */
+
+ if (objv[1]->typePtr == &tclByteArrayType) {
+ const unsigned char *string =
+ Tcl_GetByteArrayFromObj(objv[1], &length);
+
+ if (TclGetIntForIndexM(interp, objv[2], length-1, &index) != TCL_OK){
+ return TCL_ERROR;
}
- case STR_BYTELENGTH:
- case STR_LENGTH: {
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "string");
- return TCL_ERROR;
- }
+ string = Tcl_GetByteArrayFromObj(objv[1], &length);
+ if ((index >= 0) && (index < length)) {
+ Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(string + index, 1));
+ }
+ } else {
+ /*
+ * Get Unicode char length to calulate what 'end' means.
+ */
- if ((enum options) index == STR_BYTELENGTH) {
- (void) Tcl_GetStringFromObj(objv[2], &length1);
- } else {
- /*
- * If we have a ByteArray object, avoid recomputing the
- * string since the byte array contains one byte per
- * character. Otherwise, use the Unicode string rep to
- * calculate the length.
- */
+ length = Tcl_GetCharLength(objv[1]);
- if (objv[2]->typePtr == &tclByteArrayType) {
- (void) Tcl_GetByteArrayFromObj(objv[2], &length1);
- } else {
- length1 = Tcl_GetCharLength(objv[2]);
- }
- }
- Tcl_SetIntObj(resultPtr, length1);
- break;
+ if (TclGetIntForIndexM(interp, objv[2], length-1, &index) != TCL_OK){
+ return TCL_ERROR;
}
- case STR_MAP: {
- int mapElemc, nocase = 0, copySource = 0;
- Tcl_Obj **mapElemv, *sourceObj;
- Tcl_UniChar *ustring1, *ustring2, *p, *end;
- int (*strCmpFn)_ANSI_ARGS_((CONST Tcl_UniChar*,
- CONST Tcl_UniChar*, unsigned long));
-
- if (objc < 4 || objc > 5) {
- Tcl_WrongNumArgs(interp, 2, objv, "?-nocase? charMap string");
- return TCL_ERROR;
- }
+ if ((index >= 0) && (index < length)) {
+ char buf[TCL_UTF_MAX];
+ Tcl_UniChar ch;
- if (objc == 5) {
- string2 = Tcl_GetStringFromObj(objv[2], &length2);
- if ((length2 > 1) &&
- strncmp(string2, "-nocase", (size_t) length2) == 0) {
- nocase = 1;
- } else {
- Tcl_AppendStringsToObj(resultPtr, "bad option \"",
- string2, "\": must be -nocase",
- (char *) NULL);
- return TCL_ERROR;
- }
- }
+ ch = Tcl_GetUniChar(objv[1], index);
+ length = Tcl_UniCharToUtf(ch, buf);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, length));
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringIsCmd --
+ *
+ * This procedure is invoked to process the "string is" Tcl command. See
+ * the user documentation for details on what it does. Note that this
+ * command only functions correctly on properly formed Tcl UTF strings.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
- if (Tcl_ListObjGetElements(interp, objv[objc-2], &mapElemc,
- &mapElemv) != TCL_OK) {
- return TCL_ERROR;
- }
- if (mapElemc == 0) {
- /*
- * empty charMap, just return whatever string was given
- */
- Tcl_SetObjResult(interp, objv[objc-1]);
- return TCL_OK;
- } else if (mapElemc & 1) {
- /*
- * The charMap must be an even number of key/value items
- */
- Tcl_SetStringObj(resultPtr, "char map list unbalanced", -1);
- return TCL_ERROR;
- }
+static int
+StringIsCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ const char *string1, *end, *stop;
+ Tcl_UniChar ch;
+ int (*chcomp)(int) = NULL; /* The UniChar comparison function. */
+ int i, failat = 0, result = 1, strict = 0, index, length1, length2;
+ Tcl_Obj *objPtr, *failVarObj = NULL;
+ Tcl_WideInt w;
+
+ static const char *isClasses[] = {
+ "alnum", "alpha", "ascii", "control",
+ "boolean", "digit", "double", "false",
+ "graph", "integer", "list", "lower",
+ "print", "punct", "space", "true",
+ "upper", "wideinteger", "wordchar", "xdigit",
+ NULL
+ };
+ enum isClasses {
+ STR_IS_ALNUM, STR_IS_ALPHA, STR_IS_ASCII, STR_IS_CONTROL,
+ STR_IS_BOOL, STR_IS_DIGIT, STR_IS_DOUBLE, STR_IS_FALSE,
+ STR_IS_GRAPH, STR_IS_INT, STR_IS_LIST, STR_IS_LOWER,
+ STR_IS_PRINT, STR_IS_PUNCT, STR_IS_SPACE, STR_IS_TRUE,
+ STR_IS_UPPER, STR_IS_WIDE, STR_IS_WORD, STR_IS_XDIGIT
+ };
+ static const char *isOptions[] = {
+ "-strict", "-failindex", NULL
+ };
+ enum isOptions {
+ OPT_STRICT, OPT_FAILIDX
+ };
- /*
- * Take a copy of the source string object if it is the
- * same as the map string to cut out nasty sharing
- * crashes. [Bug 1018562]
- */
- if (objv[objc-2] == objv[objc-1]) {
- sourceObj = Tcl_DuplicateObj(objv[objc-1]);
- copySource = 1;
- } else {
- sourceObj = objv[objc-1];
+ if (objc < 3 || objc > 6) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "class ?-strict? ?-failindex var? str");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[1], isClasses, "class", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (objc != 3) {
+ for (i = 2; i < objc-1; i++) {
+ int idx2;
+
+ if (Tcl_GetIndexFromObj(interp, objv[i], isOptions, "option", 0,
+ &idx2) != TCL_OK) {
+ return TCL_ERROR;
}
- ustring1 = Tcl_GetUnicodeFromObj(sourceObj, &length1);
- if (length1 == 0) {
- /*
- * Empty input string, just stop now
- */
- if (copySource) {
- Tcl_DecrRefCount(sourceObj);
+ switch ((enum isOptions) idx2) {
+ case OPT_STRICT:
+ strict = 1;
+ break;
+ case OPT_FAILIDX:
+ if (i+1 >= objc-1) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-strict? ?-failindex var? str");
+ return TCL_ERROR;
}
+ failVarObj = objv[++i];
break;
}
- end = ustring1 + length1;
+ }
+ }
+
+ /*
+ * We get the objPtr so that we can short-cut for some classes by checking
+ * the object type (int and double), but we need the string otherwise,
+ * because we don't want any conversion of type occuring (as, for example,
+ * Tcl_Get*FromObj would do).
+ */
- strCmpFn = nocase ? Tcl_UniCharNcasecmp : Tcl_UniCharNcmp;
+ objPtr = objv[objc-1];
- /*
- * Force result to be Unicode
- */
- Tcl_SetUnicodeObj(resultPtr, ustring1, 0);
+ /*
+ * When entering here, result == 1 and failat == 0.
+ */
- if (mapElemc == 2) {
- /*
- * Special case for one map pair which avoids the extra
- * for loop and extra calls to get Unicode data. The
- * algorithm is otherwise identical to the multi-pair case.
- * This will be >30% faster on larger strings.
- */
- int mapLen;
- Tcl_UniChar *mapString, u2lc;
-
- ustring2 = Tcl_GetUnicodeFromObj(mapElemv[0], &length2);
- p = ustring1;
- if ((length2 > length1) || (length2 == 0)) {
- /* match string is either longer than input or empty */
- ustring1 = end;
- } else {
- mapString = Tcl_GetUnicodeFromObj(mapElemv[1], &mapLen);
- u2lc = (nocase ? Tcl_UniCharToLower(*ustring2) : 0);
- for (; ustring1 < end; ustring1++) {
- if (((*ustring1 == *ustring2) ||
- (nocase && (Tcl_UniCharToLower(*ustring1) ==
- u2lc))) &&
- ((length2 == 1) || strCmpFn(ustring1, ustring2,
- (unsigned long) length2) == 0)) {
- if (p != ustring1) {
- Tcl_AppendUnicodeToObj(resultPtr, p,
- ustring1 - p);
- p = ustring1 + length2;
- } else {
- p += length2;
- }
- ustring1 = p - 1;
-
- Tcl_AppendUnicodeToObj(resultPtr, mapString,
- mapLen);
- }
- }
- }
+ switch ((enum isClasses) index) {
+ case STR_IS_ALNUM:
+ chcomp = Tcl_UniCharIsAlnum;
+ break;
+ case STR_IS_ALPHA:
+ chcomp = Tcl_UniCharIsAlpha;
+ break;
+ case STR_IS_ASCII:
+ chcomp = UniCharIsAscii;
+ break;
+ case STR_IS_BOOL:
+ case STR_IS_TRUE:
+ case STR_IS_FALSE:
+ if (TCL_OK != Tcl_ConvertToType(NULL, objPtr, &tclBooleanType)) {
+ if (strict) {
+ result = 0;
} else {
- Tcl_UniChar **mapStrings, *u2lc = NULL;
- int *mapLens;
- /*
- * Precompute pointers to the unicode string and length.
- * This saves us repeated function calls later,
- * significantly speeding up the algorithm. We only need
- * the lowercase first char in the nocase case.
- */
- mapStrings = (Tcl_UniChar **) ckalloc((mapElemc * 2)
- * sizeof(Tcl_UniChar *));
- mapLens = (int *) ckalloc((mapElemc * 2) * sizeof(int));
- if (nocase) {
- u2lc = (Tcl_UniChar *)
- ckalloc((mapElemc) * sizeof(Tcl_UniChar));
- }
- for (index = 0; index < mapElemc; index++) {
- mapStrings[index] = Tcl_GetUnicodeFromObj(mapElemv[index],
- &(mapLens[index]));
- if (nocase && ((index % 2) == 0)) {
- u2lc[index/2] = Tcl_UniCharToLower(*mapStrings[index]);
- }
- }
- for (p = ustring1; ustring1 < end; ustring1++) {
- for (index = 0; index < mapElemc; index += 2) {
- /*
- * Get the key string to match on.
- */
- ustring2 = mapStrings[index];
- length2 = mapLens[index];
- if ((length2 > 0) && ((*ustring1 == *ustring2) ||
- (nocase && (Tcl_UniCharToLower(*ustring1) ==
- u2lc[index/2]))) &&
- /* restrict max compare length */
- ((end - ustring1) >= length2) &&
- ((length2 == 1) || strCmpFn(ustring2, ustring1,
- (unsigned long) length2) == 0)) {
- if (p != ustring1) {
- /*
- * Put the skipped chars onto the result first
- */
- Tcl_AppendUnicodeToObj(resultPtr, p,
- ustring1 - p);
- p = ustring1 + length2;
- } else {
- p += length2;
- }
- /*
- * Adjust len to be full length of matched string
- */
- ustring1 = p - 1;
-
- /*
- * Append the map value to the unicode string
- */
- Tcl_AppendUnicodeToObj(resultPtr,
- mapStrings[index+1], mapLens[index+1]);
- break;
- }
- }
- }
- ckfree((char *) mapStrings);
- ckfree((char *) mapLens);
- if (nocase) {
- ckfree((char *) u2lc);
- }
- }
- if (p != ustring1) {
- /*
- * Put the rest of the unmapped chars onto result
- */
- Tcl_AppendUnicodeToObj(resultPtr, p, ustring1 - p);
- }
- if (copySource) {
- Tcl_DecrRefCount(sourceObj);
- }
+ string1 = TclGetStringFromObj(objPtr, &length1);
+ result = length1 == 0;
+ }
+ } else if (((index == STR_IS_TRUE) &&
+ objPtr->internalRep.longValue == 0)
+ || ((index == STR_IS_FALSE) &&
+ objPtr->internalRep.longValue != 0)) {
+ result = 0;
+ }
+ break;
+ case STR_IS_CONTROL:
+ chcomp = Tcl_UniCharIsControl;
+ break;
+ case STR_IS_DIGIT:
+ chcomp = Tcl_UniCharIsDigit;
+ break;
+ case STR_IS_DOUBLE: {
+ /* TODO */
+ if ((objPtr->typePtr == &tclDoubleType) ||
+ (objPtr->typePtr == &tclIntType) ||
+#ifndef NO_WIDE_TYPE
+ (objPtr->typePtr == &tclWideIntType) ||
+#endif
+ (objPtr->typePtr == &tclBignumType)) {
break;
}
- case STR_MATCH: {
- Tcl_UniChar *ustring1, *ustring2;
- int nocase = 0;
-
- if (objc < 4 || objc > 5) {
- Tcl_WrongNumArgs(interp, 2, objv, "?-nocase? pattern string");
- return TCL_ERROR;
+ string1 = TclGetStringFromObj(objPtr, &length1);
+ if (length1 == 0) {
+ if (strict) {
+ result = 0;
}
-
- if (objc == 5) {
- string2 = Tcl_GetStringFromObj(objv[2], &length2);
- if ((length2 > 1) &&
- strncmp(string2, "-nocase", (size_t) length2) == 0) {
- nocase = 1;
- } else {
- Tcl_AppendStringsToObj(resultPtr, "bad option \"",
- string2, "\": must be -nocase",
- (char *) NULL);
- return TCL_ERROR;
- }
+ goto str_is_done;
+ }
+ end = string1 + length1;
+ if (TclParseNumber(NULL, objPtr, NULL, NULL, -1,
+ (const char **) &stop, 0) != TCL_OK) {
+ result = 0;
+ failat = 0;
+ } else {
+ failat = stop - string1;
+ if (stop < end) {
+ result = 0;
+ TclFreeIntRep(objPtr);
+ objPtr->typePtr = NULL;
}
- ustring1 = Tcl_GetUnicodeFromObj(objv[objc-1], &length1);
- ustring2 = Tcl_GetUnicodeFromObj(objv[objc-2], &length2);
- Tcl_SetBooleanObj(resultPtr, TclUniCharMatch(ustring1, length1,
- ustring2, length2, nocase));
+ }
+ break;
+ }
+ case STR_IS_GRAPH:
+ chcomp = Tcl_UniCharIsGraph;
+ break;
+ case STR_IS_INT:
+ if (TCL_OK == TclGetIntFromObj(NULL, objPtr, &i)) {
+ break;
+ }
+ goto failedIntParse;
+ case STR_IS_WIDE:
+ if (TCL_OK == Tcl_GetWideIntFromObj(NULL, objPtr, &w)) {
break;
}
- case STR_RANGE: {
- int first, last;
- if (objc != 5) {
- Tcl_WrongNumArgs(interp, 2, objv, "string first last");
- return TCL_ERROR;
+ failedIntParse:
+ string1 = TclGetStringFromObj(objPtr, &length1);
+ if (length1 == 0) {
+ if (strict) {
+ result = 0;
}
-
+ goto str_is_done;
+ }
+ result = 0;
+ if (failVarObj == NULL) {
/*
- * If we have a ByteArray object, avoid indexing in the
- * Utf string since the byte array contains one byte per
- * character. Otherwise, use the Unicode string rep to
- * get the range.
+ * Don't bother computing the failure point if we're not going to
+ * return it.
*/
- if (objv[2]->typePtr == &tclByteArrayType) {
- string1 = (char *)Tcl_GetByteArrayFromObj(objv[2], &length1);
- length1--;
+ break;
+ }
+ end = string1 + length1;
+ if (TclParseNumber(NULL, objPtr, NULL, NULL, -1,
+ (const char **) &stop, TCL_PARSE_INTEGER_ONLY) == TCL_OK) {
+ if (stop == end) {
+ /*
+ * Entire string parses as an integer, but rejected by
+ * Tcl_Get(Wide)IntFromObj() so we must have overflowed the
+ * target type, and our convention is to return failure at
+ * index -1 in that situation.
+ */
+
+ failat = -1;
} else {
/*
- * Get the length in actual characters.
+ * Some prefix parsed as an integer, but not the whole string,
+ * so return failure index as the point where parsing stopped.
+ * Clear out the internal rep, since keeping it would leave
+ * *objPtr in an inconsistent state.
*/
- string1 = NULL;
- length1 = Tcl_GetCharLength(objv[2]) - 1;
- }
- if ((TclGetIntForIndex(interp, objv[3], length1, &first) != TCL_OK)
- || (TclGetIntForIndex(interp, objv[4], length1,
- &last) != TCL_OK)) {
- return TCL_ERROR;
+ failat = stop - string1;
+ TclFreeIntRep(objPtr);
+ objPtr->typePtr = NULL;
}
+ } else {
+ /*
+ * No prefix is a valid integer. Fail at beginning.
+ */
- if (first < 0) {
- first = 0;
- }
- if (last >= length1) {
- last = length1;
- }
- if (last >= first) {
- if (string1 != NULL) {
- int numBytes = last - first + 1;
- resultPtr = Tcl_NewByteArrayObj(
- (unsigned char *) &string1[first], numBytes);
- Tcl_SetObjResult(interp, resultPtr);
- } else {
- Tcl_SetObjResult(interp,
- Tcl_GetRange(objv[2], first, last));
- }
- }
+ failat = 0;
+ }
+ break;
+ case STR_IS_LIST:
+ /*
+ * We ignore the strictness here, since empty strings are always
+ * well-formed lists.
+ */
+
+ if (TCL_OK == TclListObjLength(NULL, objPtr, &length2)) {
break;
}
- case STR_REPEAT: {
- int count;
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "string count");
- return TCL_ERROR;
- }
+ if (failVarObj != NULL) {
+ /*
+ * Need to figure out where the list parsing failed, which is
+ * fairly expensive. This is adapted from the core of
+ * SetListFromAny().
+ */
- if (Tcl_GetIntFromObj(interp, objv[3], &count) != TCL_OK) {
- return TCL_ERROR;
- }
+ const char *elemStart, *nextElem;
+ int lenRemain, elemSize;
+ register const char *p;
+
+ string1 = TclGetStringFromObj(objPtr, &length1);
+ end = string1 + length1;
+ failat = -1;
+ for (p=string1, lenRemain=length1; lenRemain > 0;
+ p=nextElem, lenRemain=end-nextElem) {
+ if (TCL_ERROR == TclFindElement(NULL, p, lenRemain,
+ &elemStart, &nextElem, &elemSize, NULL)) {
+ Tcl_Obj *tmpStr;
- if (count == 1) {
- Tcl_SetObjResult(interp, objv[2]);
- } else if (count > 1) {
- string1 = Tcl_GetStringFromObj(objv[2], &length1);
- if (length1 > 0) {
- /*
- * Only build up a string that has data. Instead of
- * building it up with repeated appends, we just allocate
- * the necessary space once and copy the string value in.
- * Check for overflow with back-division. [Bug #714106]
- */
- length2 = length1 * count;
- if ((length2 / count) != length1) {
- char buf[TCL_INTEGER_SPACE+1];
- sprintf(buf, "%d", INT_MAX);
- Tcl_AppendStringsToObj(resultPtr,
- "string size overflow, must be less than ",
- buf, (char *) NULL);
- return TCL_ERROR;
- }
/*
- * Include space for the NULL
+ * This is the simplest way of getting the number of
+ * characters parsed. Note that this is not the same as
+ * the number of bytes when parsing strings with non-ASCII
+ * characters in them.
+ *
+ * Skip leading spaces first. This is only really an issue
+ * if it is the first "element" that has the failure.
*/
- string2 = (char *) ckalloc((size_t) length2+1);
- for (index = 0; index < count; index++) {
- memcpy(string2 + (length1 * index), string1,
- (size_t) length1);
+
+ while (TclIsSpaceProc(*p)) {
+ p++;
}
- string2[length2] = '\0';
- /*
- * We have to directly assign this instead of using
- * Tcl_SetStringObj (and indirectly TclInitStringRep)
- * because that makes another copy of the data.
- */
- resultPtr = Tcl_NewObj();
- resultPtr->bytes = string2;
- resultPtr->length = length2;
- Tcl_SetObjResult(interp, resultPtr);
+ TclNewStringObj(tmpStr, string1, p-string1);
+ failat = Tcl_GetCharLength(tmpStr);
+ TclDecrRefCount(tmpStr);
+ break;
}
}
- break;
}
- case STR_REPLACE: {
- Tcl_UniChar *ustring1;
- int first, last;
-
- if (objc < 5 || objc > 6) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "string first last ?string?");
- return TCL_ERROR;
+ result = 0;
+ break;
+ case STR_IS_LOWER:
+ chcomp = Tcl_UniCharIsLower;
+ break;
+ case STR_IS_PRINT:
+ chcomp = Tcl_UniCharIsPrint;
+ break;
+ case STR_IS_PUNCT:
+ chcomp = Tcl_UniCharIsPunct;
+ break;
+ case STR_IS_SPACE:
+ chcomp = Tcl_UniCharIsSpace;
+ break;
+ case STR_IS_UPPER:
+ chcomp = Tcl_UniCharIsUpper;
+ break;
+ case STR_IS_WORD:
+ chcomp = Tcl_UniCharIsWordChar;
+ break;
+ case STR_IS_XDIGIT:
+ chcomp = UniCharIsHexDigit;
+ break;
+ }
+
+ if (chcomp != NULL) {
+ string1 = TclGetStringFromObj(objPtr, &length1);
+ if (length1 == 0) {
+ if (strict) {
+ result = 0;
+ }
+ goto str_is_done;
+ }
+ end = string1 + length1;
+ for (; string1 < end; string1 += length2, failat++) {
+ length2 = TclUtfToUniChar(string1, &ch);
+ if (!chcomp(ch)) {
+ result = 0;
+ break;
}
+ }
+ }
- ustring1 = Tcl_GetUnicodeFromObj(objv[2], &length1);
- length1--;
+ /*
+ * Only set the failVarObj when we will return 0 and we have indicated a
+ * valid fail index (>= 0).
+ */
- if ((TclGetIntForIndex(interp, objv[3], length1, &first) != TCL_OK)
- || (TclGetIntForIndex(interp, objv[4], length1,
- &last) != TCL_OK)) {
- return TCL_ERROR;
- }
+ str_is_done:
+ if ((result == 0) && (failVarObj != NULL) &&
+ Tcl_ObjSetVar2(interp, failVarObj, NULL, Tcl_NewIntObj(failat),
+ TCL_LEAVE_ERR_MSG) == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result));
+ return TCL_OK;
+}
- if ((last < first) || (last < 0) || (first > length1)) {
- Tcl_SetObjResult(interp, objv[2]);
- } else {
- if (first < 0) {
- first = 0;
- }
+static int
+UniCharIsAscii(
+ int character)
+{
+ return (character >= 0) && (character < 0x80);
+}
- Tcl_SetUnicodeObj(resultPtr, ustring1, first);
- if (objc == 6) {
- Tcl_AppendObjToObj(resultPtr, objv[5]);
- }
- if (last < length1) {
- Tcl_AppendUnicodeToObj(resultPtr, ustring1 + last + 1,
- length1 - last);
- }
- }
- break;
- }
- case STR_TOLOWER:
- case STR_TOUPPER:
- case STR_TOTITLE:
- if (objc < 3 || objc > 5) {
- Tcl_WrongNumArgs(interp, 2, objv, "string ?first? ?last?");
- return TCL_ERROR;
- }
+static int
+UniCharIsHexDigit(
+ int character)
+{
+ return (character >= 0) && (character < 0x80) && isxdigit(character);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringMapCmd --
+ *
+ * This procedure is invoked to process the "string map" Tcl command. See
+ * the user documentation for details on what it does. Note that this
+ * command only functions correctly on properly formed Tcl UTF strings.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
- string1 = Tcl_GetStringFromObj(objv[2], &length1);
+static int
+StringMapCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int length1, length2, mapElemc, index;
+ int nocase = 0, mapWithDict = 0, copySource = 0;
+ Tcl_Obj **mapElemv, *sourceObj, *resultPtr;
+ Tcl_UniChar *ustring1, *ustring2, *p, *end;
+ int (*strCmpFn)(const Tcl_UniChar*, const Tcl_UniChar*, unsigned long);
+
+ if (objc < 3 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "?-nocase? charMap string");
+ return TCL_ERROR;
+ }
- if (objc == 3) {
- /*
- * Since the result object is not a shared object, it is
- * safe to copy the string into the result and do the
- * conversion in place. The conversion may change the length
- * of the string, so reset the length after conversion.
- */
+ if (objc == 4) {
+ const char *string = TclGetStringFromObj(objv[1], &length2);
- Tcl_SetStringObj(resultPtr, string1, length1);
- if ((enum options) index == STR_TOLOWER) {
- length1 = Tcl_UtfToLower(Tcl_GetString(resultPtr));
- } else if ((enum options) index == STR_TOUPPER) {
- length1 = Tcl_UtfToUpper(Tcl_GetString(resultPtr));
- } else {
- length1 = Tcl_UtfToTitle(Tcl_GetString(resultPtr));
- }
- Tcl_SetObjLength(resultPtr, length1);
- } else {
- int first, last;
- CONST char *start, *end;
+ if ((length2 > 1) &&
+ strncmp(string, "-nocase", (size_t) length2) == 0) {
+ nocase = 1;
+ } else {
+ Tcl_AppendResult(interp, "bad option \"", string,
+ "\": must be -nocase", NULL);
+ return TCL_ERROR;
+ }
+ }
- length1 = Tcl_NumUtfChars(string1, length1) - 1;
- if (TclGetIntForIndex(interp, objv[3], length1,
- &first) != TCL_OK) {
- return TCL_ERROR;
- }
- if (first < 0) {
- first = 0;
- }
- last = first;
- if ((objc == 5) && (TclGetIntForIndex(interp, objv[4], length1,
- &last) != TCL_OK)) {
- return TCL_ERROR;
- }
- if (last >= length1) {
- last = length1;
- }
- if (last < first) {
- Tcl_SetObjResult(interp, objv[2]);
- break;
- }
- start = Tcl_UtfAtIndex(string1, first);
- end = Tcl_UtfAtIndex(start, last - first + 1);
- length2 = end-start;
- string2 = ckalloc((size_t) length2+1);
- memcpy(string2, start, (size_t) length2);
- string2[length2] = '\0';
- if ((enum options) index == STR_TOLOWER) {
- length2 = Tcl_UtfToLower(string2);
- } else if ((enum options) index == STR_TOUPPER) {
- length2 = Tcl_UtfToUpper(string2);
- } else {
- length2 = Tcl_UtfToTitle(string2);
- }
- Tcl_SetStringObj(resultPtr, string1, start - string1);
- Tcl_AppendToObj(resultPtr, string2, length2);
- Tcl_AppendToObj(resultPtr, end, -1);
- ckfree(string2);
- }
- break;
+ /*
+ * This test is tricky, but has to be that way or you get other strange
+ * inconsistencies (see test string-10.20 for illustration why!)
+ */
- case STR_TRIM: {
- Tcl_UniChar ch, trim;
- register CONST char *p, *end;
- char *check, *checkEnd;
- int offset;
-
- left = 1;
- right = 1;
-
- dotrim:
- if (objc == 4) {
- string2 = Tcl_GetStringFromObj(objv[3], &length2);
- } else if (objc == 3) {
- string2 = " \t\n\r";
- length2 = strlen(string2);
- } else {
- Tcl_WrongNumArgs(interp, 2, objv, "string ?chars?");
- return TCL_ERROR;
- }
- string1 = Tcl_GetStringFromObj(objv[2], &length1);
- checkEnd = string2 + length2;
+ if (objv[objc-2]->typePtr == &tclDictType && objv[objc-2]->bytes == NULL){
+ int i, done;
+ Tcl_DictSearch search;
- if (left) {
- end = string1 + length1;
- /*
- * The outer loop iterates over the string. The inner
- * loop iterates over the trim characters. The loops
- * terminate as soon as a non-trim character is discovered
- * and string1 is left pointing at the first non-trim
- * character.
- */
+ /*
+ * We know the type exactly, so all dict operations will succeed for
+ * sure. This shortens this code quite a bit.
+ */
- for (p = string1; p < end; p += offset) {
- offset = TclUtfToUniChar(p, &ch);
-
- for (check = string2; ; ) {
- if (check >= checkEnd) {
- p = end;
- break;
- }
- check += TclUtfToUniChar(check, &trim);
- if (ch == trim) {
- length1 -= offset;
- string1 += offset;
- break;
- }
- }
- }
- }
- if (right) {
- end = string1;
+ Tcl_DictObjSize(interp, objv[objc-2], &mapElemc);
+ if (mapElemc == 0) {
+ /*
+ * Empty charMap, just return whatever string was given.
+ */
- /*
- * The outer loop iterates over the string. The inner
- * loop iterates over the trim characters. The loops
- * terminate as soon as a non-trim character is discovered
- * and length1 marks the last non-trim character.
- */
+ Tcl_SetObjResult(interp, objv[objc-1]);
+ return TCL_OK;
+ }
- for (p = string1 + length1; p > end; ) {
- p = Tcl_UtfPrev(p, string1);
- offset = TclUtfToUniChar(p, &ch);
- for (check = string2; ; ) {
- if (check >= checkEnd) {
- p = end;
- break;
- }
- check += TclUtfToUniChar(check, &trim);
- if (ch == trim) {
- length1 -= offset;
- break;
- }
- }
- }
- }
- Tcl_SetStringObj(resultPtr, string1, length1);
- break;
+ mapElemc *= 2;
+ mapWithDict = 1;
+
+ /*
+ * Copy the dictionary out into an array; that's the easiest way to
+ * adapt this code...
+ */
+
+ mapElemv = (Tcl_Obj **)
+ TclStackAlloc(interp, sizeof(Tcl_Obj *) * mapElemc);
+ Tcl_DictObjFirst(interp, objv[objc-2], &search, mapElemv+0,
+ mapElemv+1, &done);
+ for (i=2 ; i<mapElemc ; i+=2) {
+ Tcl_DictObjNext(&search, mapElemv+i, mapElemv+i+1, &done);
}
- case STR_TRIMLEFT: {
- left = 1;
- right = 0;
- goto dotrim;
+ Tcl_DictObjDone(&search);
+ } else {
+ if (TclListObjGetElements(interp, objv[objc-2], &mapElemc,
+ &mapElemv) != TCL_OK) {
+ return TCL_ERROR;
}
- case STR_TRIMRIGHT: {
- left = 0;
- right = 1;
- goto dotrim;
+ if (mapElemc == 0) {
+ /*
+ * empty charMap, just return whatever string was given.
+ */
+
+ Tcl_SetObjResult(interp, objv[objc-1]);
+ return TCL_OK;
+ } else if (mapElemc & 1) {
+ /*
+ * The charMap must be an even number of key/value items.
+ */
+
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("char map list unbalanced", -1));
+ return TCL_ERROR;
}
- case STR_WORDEND: {
- int cur;
- Tcl_UniChar ch;
- CONST char *p, *end;
- int numChars;
-
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "string index");
- return TCL_ERROR;
- }
+ }
- string1 = Tcl_GetStringFromObj(objv[2], &length1);
- numChars = Tcl_NumUtfChars(string1, length1);
- if (TclGetIntForIndex(interp, objv[3], numChars-1,
- &index) != TCL_OK) {
- return TCL_ERROR;
- }
- if (index < 0) {
- index = 0;
- }
- if (index < numChars) {
- p = Tcl_UtfAtIndex(string1, index);
- end = string1+length1;
- for (cur = index; p < end; cur++) {
- p += TclUtfToUniChar(p, &ch);
- if (!Tcl_UniCharIsWordChar(ch)) {
- break;
+ /*
+ * Take a copy of the source string object if it is the same as the map
+ * string to cut out nasty sharing crashes. [Bug 1018562]
+ */
+
+ if (objv[objc-2] == objv[objc-1]) {
+ sourceObj = Tcl_DuplicateObj(objv[objc-1]);
+ copySource = 1;
+ } else {
+ sourceObj = objv[objc-1];
+ }
+ ustring1 = Tcl_GetUnicodeFromObj(sourceObj, &length1);
+ if (length1 == 0) {
+ /*
+ * Empty input string, just stop now.
+ */
+
+ goto done;
+ }
+ end = ustring1 + length1;
+
+ strCmpFn = (nocase ? Tcl_UniCharNcasecmp : Tcl_UniCharNcmp);
+
+ /*
+ * Force result to be Unicode
+ */
+
+ resultPtr = Tcl_NewUnicodeObj(ustring1, 0);
+
+ if (mapElemc == 2) {
+ /*
+ * Special case for one map pair which avoids the extra for loop and
+ * extra calls to get Unicode data. The algorithm is otherwise
+ * identical to the multi-pair case. This will be >30% faster on
+ * larger strings.
+ */
+
+ int mapLen;
+ Tcl_UniChar *mapString, u2lc;
+
+ ustring2 = Tcl_GetUnicodeFromObj(mapElemv[0], &length2);
+ p = ustring1;
+ if ((length2 > length1) || (length2 == 0)) {
+ /*
+ * Match string is either longer than input or empty.
+ */
+
+ ustring1 = end;
+ } else {
+ mapString = Tcl_GetUnicodeFromObj(mapElemv[1], &mapLen);
+ u2lc = (nocase ? Tcl_UniCharToLower(*ustring2) : 0);
+ for (; ustring1 < end; ustring1++) {
+ if (((*ustring1 == *ustring2) ||
+ (nocase&&Tcl_UniCharToLower(*ustring1)==u2lc)) &&
+ (length2==1 || strCmpFn(ustring1, ustring2,
+ (unsigned long) length2) == 0)) {
+ if (p != ustring1) {
+ Tcl_AppendUnicodeToObj(resultPtr, p, ustring1-p);
+ p = ustring1 + length2;
+ } else {
+ p += length2;
}
+ ustring1 = p - 1;
+
+ Tcl_AppendUnicodeToObj(resultPtr, mapString, mapLen);
}
- if (cur == index) {
- cur++;
- }
- } else {
- cur = numChars;
}
- Tcl_SetIntObj(resultPtr, cur);
- break;
}
- case STR_WORDSTART: {
- int cur;
- Tcl_UniChar ch;
- CONST char *p;
- int numChars;
-
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "string index");
- return TCL_ERROR;
- }
+ } else {
+ Tcl_UniChar **mapStrings, *u2lc = NULL;
+ int *mapLens;
- string1 = Tcl_GetStringFromObj(objv[2], &length1);
- numChars = Tcl_NumUtfChars(string1, length1);
- if (TclGetIntForIndex(interp, objv[3], numChars-1,
- &index) != TCL_OK) {
- return TCL_ERROR;
- }
- if (index >= numChars) {
- index = numChars - 1;
+ /*
+ * Precompute pointers to the unicode string and length. This saves us
+ * repeated function calls later, significantly speeding up the
+ * algorithm. We only need the lowercase first char in the nocase
+ * case.
+ */
+
+ mapStrings = (Tcl_UniChar **) TclStackAlloc(interp,
+ mapElemc * 2 * sizeof(Tcl_UniChar *));
+ mapLens = (int *) TclStackAlloc(interp, mapElemc * 2 * sizeof(int));
+ if (nocase) {
+ u2lc = (Tcl_UniChar *) TclStackAlloc(interp,
+ mapElemc * sizeof(Tcl_UniChar));
+ }
+ for (index = 0; index < mapElemc; index++) {
+ mapStrings[index] = Tcl_GetUnicodeFromObj(mapElemv[index],
+ mapLens+index);
+ if (nocase && ((index % 2) == 0)) {
+ u2lc[index/2] = Tcl_UniCharToLower(*mapStrings[index]);
}
- cur = 0;
- if (index > 0) {
- p = Tcl_UtfAtIndex(string1, index);
- for (cur = index; cur >= 0; cur--) {
- TclUtfToUniChar(p, &ch);
- if (!Tcl_UniCharIsWordChar(ch)) {
- break;
+ }
+ for (p = ustring1; ustring1 < end; ustring1++) {
+ for (index = 0; index < mapElemc; index += 2) {
+ /*
+ * Get the key string to match on.
+ */
+
+ ustring2 = mapStrings[index];
+ length2 = mapLens[index];
+ if ((length2 > 0) && ((*ustring1 == *ustring2) || (nocase &&
+ (Tcl_UniCharToLower(*ustring1) == u2lc[index/2]))) &&
+ /* Restrict max compare length. */
+ (end-ustring1 >= length2) && ((length2 == 1) ||
+ !strCmpFn(ustring2, ustring1, (unsigned) length2))) {
+ if (p != ustring1) {
+ /*
+ * Put the skipped chars onto the result first.
+ */
+
+ Tcl_AppendUnicodeToObj(resultPtr, p, ustring1-p);
+ p = ustring1 + length2;
+ } else {
+ p += length2;
}
- p = Tcl_UtfPrev(p, string1);
- }
- if (cur != index) {
- cur += 1;
+
+ /*
+ * Adjust len to be full length of matched string.
+ */
+
+ ustring1 = p - 1;
+
+ /*
+ * Append the map value to the unicode string.
+ */
+
+ Tcl_AppendUnicodeToObj(resultPtr,
+ mapStrings[index+1], mapLens[index+1]);
+ break;
}
}
- Tcl_SetIntObj(resultPtr, cur);
- break;
}
+ if (nocase) {
+ TclStackFree(interp, u2lc);
+ }
+ TclStackFree(interp, mapLens);
+ TclStackFree(interp, mapStrings);
+ }
+ if (p != ustring1) {
+ /*
+ * Put the rest of the unmapped chars onto result.
+ */
+
+ Tcl_AppendUnicodeToObj(resultPtr, p, ustring1 - p);
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ done:
+ if (mapWithDict) {
+ TclStackFree(interp, mapElemv);
+ }
+ if (copySource) {
+ Tcl_DecrRefCount(sourceObj);
}
return TCL_OK;
}
@@ -2464,11 +1997,11 @@ Tcl_StringObjCmd(dummy, interp, objc, objv)
/*
*----------------------------------------------------------------------
*
- * Tcl_SubstObjCmd --
+ * StringMatchCmd --
*
- * This procedure is invoked to process the "subst" Tcl command.
- * See the user documentation for details on what it does. This
- * command relies on Tcl_SubstObj() for its implementation.
+ * This procedure is invoked to process the "string match" Tcl command.
+ * See the user documentation for details on what it does. Note that this
+ * command only functions correctly on properly formed Tcl UTF strings.
*
* Results:
* A standard Tcl result.
@@ -2479,94 +2012,49 @@ Tcl_StringObjCmd(dummy, interp, objc, objv)
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
-int
-Tcl_SubstObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+static int
+StringMatchCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- static CONST char *substOptions[] = {
- "-nobackslashes", "-nocommands", "-novariables", (char *) NULL
- };
- enum substOptions {
- SUBST_NOBACKSLASHES, SUBST_NOCOMMANDS, SUBST_NOVARS
- };
- Tcl_Obj *resultPtr;
- int optionIndex, flags, i;
+ int nocase = 0;
- /*
- * Parse command-line options.
- */
-
- flags = TCL_SUBST_ALL;
- for (i = 1; i < (objc-1); i++) {
- if (Tcl_GetIndexFromObj(interp, objv[i], substOptions,
- "switch", 0, &optionIndex) != TCL_OK) {
-
- return TCL_ERROR;
- }
- switch (optionIndex) {
- case SUBST_NOBACKSLASHES: {
- flags &= ~TCL_SUBST_BACKSLASHES;
- break;
- }
- case SUBST_NOCOMMANDS: {
- flags &= ~TCL_SUBST_COMMANDS;
- break;
- }
- case SUBST_NOVARS: {
- flags &= ~TCL_SUBST_VARIABLES;
- break;
- }
- default: {
- panic("Tcl_SubstObjCmd: bad option index to SubstOptions");
- }
- }
- }
- if (i != (objc-1)) {
- Tcl_WrongNumArgs(interp, 1, objv,
- "?-nobackslashes? ?-nocommands? ?-novariables? string");
+ if (objc < 3 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "?-nocase? pattern string");
return TCL_ERROR;
}
- /*
- * Perform the substitution.
- */
- resultPtr = Tcl_SubstObj(interp, objv[i], flags);
+ if (objc == 4) {
+ int length;
+ const char *string = TclGetStringFromObj(objv[1], &length);
- if (resultPtr == NULL) {
- return TCL_ERROR;
+ if ((length > 1) &&
+ strncmp(string, "-nocase", (size_t) length) == 0) {
+ nocase = TCL_MATCH_NOCASE;
+ } else {
+ Tcl_AppendResult(interp, "bad option \"", string,
+ "\": must be -nocase", NULL);
+ return TCL_ERROR;
+ }
}
- Tcl_SetObjResult(interp, resultPtr);
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
+ TclStringMatchObj(objv[objc-1], objv[objc-2], nocase)));
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * Tcl_SubstObj --
- *
- * This function performs the substitutions specified on the
- * given string as described in the user documentation for the
- * "subst" Tcl command. This code is heavily based on an
- * implementation by Andrew Payne. Note that if a command
- * substitution returns TCL_CONTINUE or TCL_RETURN from its
- * evaluation and is not completely well-formed, the results are
- * not defined (or at least hard to characterise.) This fault
- * will be fixed at some point, but the cost of the only sane
- * fix (well-formedness check first) is such that you need to
- * "precompile and cache" to stop everyone from being hit with
- * the consequences every time through. Note that the current
- * behaviour is not a security hole; it just restarts parsing
- * the string following the substitution in a mildly surprising
- * place, and it is a very bad idea to count on this remaining
- * the same in future...
+ * StringRangeCmd --
+ *
+ * This procedure is invoked to process the "string range" Tcl command.
+ * See the user documentation for details on what it does. Note that this
+ * command only functions correctly on properly formed Tcl UTF strings.
*
* Results:
- * A Tcl_Obj* containing the substituted string, or NULL to
- * indicate that an error occurred.
+ * A standard Tcl result.
*
* Side effects:
* See the user documentation.
@@ -2574,144 +2062,77 @@ Tcl_SubstObjCmd(dummy, interp, objc, objv)
*----------------------------------------------------------------------
*/
-Tcl_Obj *
-Tcl_SubstObj(interp, objPtr, flags)
- Tcl_Interp *interp;
- Tcl_Obj *objPtr;
- int flags;
+static int
+StringRangeCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- Tcl_Obj *resultObj;
- char *p, *old;
- int length;
+ const unsigned char *string;
+ int length, first, last;
- old = p = Tcl_GetStringFromObj(objPtr, &length);
- resultObj = Tcl_NewStringObj("", 0);
- while (length) {
- switch (*p) {
- case '\\':
- if (flags & TCL_SUBST_BACKSLASHES) {
- char buf[TCL_UTF_MAX];
- int count;
-
- if (p != old) {
- Tcl_AppendToObj(resultObj, old, p-old);
- }
- Tcl_AppendToObj(resultObj, buf,
- TclParseBackslash(p, length, &count, buf));
- p += count; length -= count;
- old = p;
- } else {
- p++; length--;
- }
- break;
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "string first last");
+ return TCL_ERROR;
+ }
- case '$':
- if (flags & TCL_SUBST_VARIABLES) {
- Tcl_Parse parse;
- int code;
+ /*
+ * If we have a ByteArray object, avoid indexing in the Utf string since
+ * the byte array contains one byte per character. Otherwise, use the
+ * Unicode string rep to get the range.
+ */
- /*
- * Code is simpler overall if we (effectively) inline
- * Tcl_ParseVar, particularly as that allows us to use
- * a non-string interface when we come to appending
- * the variable contents to the result object. There
- * are a few other optimisations that doing this
- * enables (like being able to continue the run of
- * unsubstituted characters straight through if a '$'
- * does not precede a variable name.)
- */
- if (Tcl_ParseVarName(interp, p, length, &parse, 0) != TCL_OK) {
- goto errorResult;
- }
- if (parse.numTokens == 1) {
- /*
- * There isn't a variable name after all: the $ is
- * just a $.
- */
- p++; length--;
- break;
- }
- if (p != old) {
- Tcl_AppendToObj(resultObj, old, p-old);
- }
- p += parse.tokenPtr->size;
- length -= parse.tokenPtr->size;
- code = Tcl_EvalTokensStandard(interp, parse.tokenPtr,
- parse.numTokens);
- if (code == TCL_ERROR) {
- goto errorResult;
- }
- if (code == TCL_BREAK) {
- Tcl_ResetResult(interp);
- return resultObj;
- }
- if (code != TCL_CONTINUE) {
- Tcl_AppendObjToObj(resultObj, Tcl_GetObjResult(interp));
- }
- Tcl_ResetResult(interp);
- old = p;
- } else {
- p++; length--;
- }
- break;
+ if (objv[1]->typePtr == &tclByteArrayType) {
+ string = Tcl_GetByteArrayFromObj(objv[1], &length);
+ length--;
+ } else {
+ /*
+ * Get the length in actual characters.
+ */
- case '[':
- if (flags & TCL_SUBST_COMMANDS) {
- Interp *iPtr = (Interp *) interp;
- int code;
+ string = NULL;
+ length = Tcl_GetCharLength(objv[1]) - 1;
+ }
- if (p != old) {
- Tcl_AppendToObj(resultObj, old, p-old);
- }
- iPtr->evalFlags = TCL_BRACKET_TERM;
- iPtr->numLevels++;
- code = TclInterpReady(interp);
- if (code == TCL_OK) {
- code = Tcl_EvalEx(interp, p+1, length-1, 0);
- }
- iPtr->numLevels--;
- switch (code) {
- case TCL_ERROR:
- goto errorResult;
- case TCL_BREAK:
- Tcl_ResetResult(interp);
- return resultObj;
- default:
- Tcl_AppendObjToObj(resultObj, Tcl_GetObjResult(interp));
- case TCL_CONTINUE:
- Tcl_ResetResult(interp);
- old = p = (p+1 + iPtr->termOffset + 1);
- length -= (iPtr->termOffset + 2);
- }
- } else {
- p++; length--;
- }
- break;
- default:
- p++; length--;
- break;
- }
+ if (TclGetIntForIndexM(interp, objv[2], length, &first) != TCL_OK ||
+ TclGetIntForIndexM(interp, objv[3], length, &last) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (first < 0) {
+ first = 0;
}
- if (p != old) {
- Tcl_AppendToObj(resultObj, old, p-old);
+ if (last >= length) {
+ last = length;
}
- return resultObj;
+ if (last >= first) {
+ if (string != NULL) {
+ /*
+ * Reread the string to prevent shimmering nasties.
+ */
- errorResult:
- Tcl_DecrRefCount(resultObj);
- return NULL;
+ string = Tcl_GetByteArrayFromObj(objv[1], &length);
+ Tcl_SetObjResult(interp,
+ Tcl_NewByteArrayObj(string+first, last - first + 1));
+ } else {
+ Tcl_SetObjResult(interp, Tcl_GetRange(objv[1], first, last));
+ }
+ }
+ return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * Tcl_SwitchObjCmd --
+ * StringReptCmd --
*
- * This object-based procedure is invoked to process the "switch" Tcl
- * command. See the user documentation for details on what it does.
+ * This procedure is invoked to process the "string repeat" Tcl command.
+ * See the user documentation for details on what it does. Note that this
+ * command only functions correctly on properly formed Tcl UTF strings.
*
* Results:
- * A standard Tcl object result.
+ * A standard Tcl result.
*
* Side effects:
* See the user documentation.
@@ -2719,263 +2140,159 @@ Tcl_SubstObj(interp, objPtr, flags)
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
-int
-Tcl_SwitchObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+static int
+StringReptCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- int i, j, index, mode, matched, result, splitObjs;
- char *string, *pattern;
- Tcl_Obj *stringObj;
- Tcl_Obj *CONST *savedObjv = objv;
-#ifdef TCL_TIP280
- Interp* iPtr = (Interp*) interp;
- int pc = 0;
- int bidx = 0; /* Index of body argument */
- Tcl_Obj* blist = NULL; /* List obj which is the body */
- CmdFrame ctx; /* Copy of the topmost cmdframe,
- * to allow us to mess with the
- * line information */
-#endif
- static CONST char *options[] = {
- "-exact", "-glob", "-regexp", "--",
- NULL
- };
- enum options {
- OPT_EXACT, OPT_GLOB, OPT_REGEXP, OPT_LAST
- };
+ const char *string1;
+ char *string2;
+ int count, index, length1, length2;
+ Tcl_Obj *resultPtr;
- mode = OPT_EXACT;
- for (i = 1; i < objc; i++) {
- string = Tcl_GetString(objv[i]);
- if (string[0] != '-') {
- break;
- }
- if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
- &index) != TCL_OK) {
- return TCL_ERROR;
- }
- if (index == OPT_LAST) {
- i++;
- break;
- }
- mode = index;
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "string count");
+ return TCL_ERROR;
}
- if (objc - i < 2) {
- Tcl_WrongNumArgs(interp, 1, objv,
- "?switches? string pattern body ... ?default body?");
+ if (TclGetIntFromObj(interp, objv[2], &count) != TCL_OK) {
return TCL_ERROR;
}
- stringObj = objv[i];
- objc -= i + 1;
- objv += i + 1;
-#ifdef TCL_TIP280
- bidx = i+1; /* First after the match string */
-#endif
-
/*
- * If all of the pattern/command pairs are lumped into a single
- * argument, split them out again.
- *
- * TIP #280: Determine the lines the words in the list start at, based on
- * the same data for the list word itself. The cmdFramePtr line information
- * is manipulated directly.
+ * Check for cases that allow us to skip copying stuff.
*/
- splitObjs = 0;
- if (objc == 1) {
- Tcl_Obj **listv;
-#ifdef TCL_TIP280
- blist = objv[0];
-#endif
- if (Tcl_ListObjGetElements(interp, objv[0], &objc, &listv) != TCL_OK) {
- return TCL_ERROR;
- }
+ if (count == 1) {
+ Tcl_SetObjResult(interp, objv[1]);
+ goto done;
+ } else if (count < 1) {
+ goto done;
+ }
+ string1 = TclGetStringFromObj(objv[1], &length1);
+ if (length1 <= 0) {
+ goto done;
+ }
- /*
- * Ensure that the list is non-empty.
- */
+ /*
+ * Only build up a string that has data. Instead of building it up with
+ * repeated appends, we just allocate the necessary space once and copy
+ * the string value in.
+ *
+ * We have to worry about overflow [Bugs 714106, 2561746].
+ * At this point we know 1 <= length1 <= INT_MAX and 2 <= count <= INT_MAX.
+ * We need to keep 2 <= length2 <= INT_MAX.
+ */
- if (objc < 1) {
- Tcl_WrongNumArgs(interp, 1, savedObjv,
- "?switches? string {pattern body ... ?default body?}");
- return TCL_ERROR;
- }
- objv = listv;
- splitObjs = 1;
+ if (count > (INT_MAX / length1)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "result exceeds max size for a Tcl value (%d bytes)", INT_MAX));
+ return TCL_ERROR;
}
+ length2 = length1 * count;
/*
- * Complain if there is an odd number of words in the list of
- * patterns and bodies.
+ * Include space for the NUL.
*/
- if (objc % 2) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "extra switch pattern with no body", NULL);
-
+ string2 = attemptckalloc((unsigned) length2 + 1);
+ if (string2 == NULL) {
/*
- * Check if this can be due to a badly placed comment
- * in the switch block.
- *
- * The following is an heuristic to detect the infamous
- * "comment in switch" error: just check if a pattern
- * begins with '#'.
+ * Alloc failed. Note that in this case we try to do an error message
+ * since this is a case that's most likely when the alloc is large and
+ * that's easy to do with this API. Note that if we fail allocating a
+ * short string, this will likely keel over too (and fatally).
*/
- if (splitObjs) {
- for (i=0 ; i<objc ; i+=2) {
- if (Tcl_GetString(objv[i])[0] == '#') {
- Tcl_AppendResult(interp, ", this may be due to a ",
- "comment incorrectly placed outside of a ",
- "switch body - see the \"switch\" ",
- "documentation", NULL);
- break;
- }
- }
- }
-
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "string size overflow, out of memory allocating %u bytes",
+ length2 + 1));
return TCL_ERROR;
}
+ for (index = 0; index < count; index++) {
+ memcpy(string2 + (length1 * index), string1, (size_t) length1);
+ }
+ string2[length2] = '\0';
/*
- * Complain if the last body is a continuation. Note that this
- * check assumes that the list is non-empty!
+ * We have to directly assign this instead of using Tcl_SetStringObj (and
+ * indirectly TclInitStringRep) because that makes another copy of the
+ * data.
*/
- if (strcmp(Tcl_GetString(objv[objc-1]), "-") == 0) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "no body specified for pattern \"",
- Tcl_GetString(objv[objc-2]), "\"", NULL);
- return TCL_ERROR;
- }
-
- for (i = 0; i < objc; i += 2) {
- /*
- * See if the pattern matches the string.
- */
-
- pattern = Tcl_GetString(objv[i]);
-
- matched = 0;
- if ((i == objc - 2)
- && (*pattern == 'd')
- && (strcmp(pattern, "default") == 0)) {
- matched = 1;
- } else {
- switch (mode) {
- case OPT_EXACT:
- matched = (strcmp(Tcl_GetString(stringObj), pattern) == 0);
- break;
- case OPT_GLOB:
- matched = Tcl_StringMatch(Tcl_GetString(stringObj),
- pattern);
- break;
- case OPT_REGEXP:
- matched = Tcl_RegExpMatchObj(interp, stringObj, objv[i]);
- if (matched < 0) {
- return TCL_ERROR;
- }
- break;
- }
- }
- if (matched == 0) {
- continue;
- }
+ TclNewObj(resultPtr);
+ resultPtr->bytes = string2;
+ resultPtr->length = length2;
+ Tcl_SetObjResult(interp, resultPtr);
- /*
- * We've got a match. Find a body to execute, skipping bodies
- * that are "-".
- *
- * TIP#280: Now is also the time to determine a line number for the
- * single-word case.
- */
+ done:
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringRplcCmd --
+ *
+ * This procedure is invoked to process the "string replace" Tcl command.
+ * See the user documentation for details on what it does. Note that this
+ * command only functions correctly on properly formed Tcl UTF strings.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
-#ifdef TCL_TIP280
- ctx = *iPtr->cmdFramePtr;
+static int
+StringRplcCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tcl_UniChar *ustring;
+ int first, last, length;
- if (splitObjs) {
- /* We have to perform the GetSrc and other type dependent handling
- * of the frame here because we are munging with the line numbers,
- * something the other commands like if, etc. are not doing. Them
- * are fine with simply passing the CmdFrame through and having
- * the special handling done in 'info frame', or the bc compiler
- */
+ if (objc < 4 || objc > 5) {
+ Tcl_WrongNumArgs(interp, 1, objv, "string first last ?string?");
+ return TCL_ERROR;
+ }
- if (ctx.type == TCL_LOCATION_BC) {
- /* Note: Type BC => ctx.data.eval.path is not used.
- * ctx.data.tebc.codePtr is used instead.
- */
- TclGetSrcInfoForPc (&ctx);
- pc = 1;
- /* The line information in the cmdFrame is now a copy we do
- * not own */
- }
+ ustring = Tcl_GetUnicodeFromObj(objv[1], &length);
+ length--;
- if (ctx.type == TCL_LOCATION_SOURCE) {
- int bline = ctx.line [bidx];
- if (bline >= 0) {
- ctx.line = (int*) ckalloc (objc * sizeof(int));
- ctx.nline = objc;
+ if (TclGetIntForIndexM(interp, objv[2], length, &first) != TCL_OK ||
+ TclGetIntForIndexM(interp, objv[3], length, &last) != TCL_OK){
+ return TCL_ERROR;
+ }
- ListLines (blist, bline, objc, ctx.line, objv);
- } else {
- int k;
- /* Dynamic code word ... All elements are relative to themselves */
+ if ((last < first) || (last < 0) || (first > length)) {
+ Tcl_SetObjResult(interp, objv[1]);
+ } else {
+ Tcl_Obj *resultPtr;
- ctx.line = (int*) ckalloc (objc * sizeof(int));
- ctx.nline = objc;
- for (k=0; k < objc; k++) {ctx.line[k] = -1;}
- }
- } else {
- int k;
- /* Anything else ... No information, or dynamic ... */
+ ustring = Tcl_GetUnicodeFromObj(objv[1], &length);
+ length--;
- ctx.line = (int*) ckalloc (objc * sizeof(int));
- ctx.nline = objc;
- for (k=0; k < objc; k++) {ctx.line[k] = -1;}
- }
+ if (first < 0) {
+ first = 0;
}
-#endif
- for (j = i + 1; ; j += 2) {
- if (j >= objc) {
- /*
- * This shouldn't happen since we've checked that the
- * last body is not a continuation...
- */
- panic("fall-out when searching for body to match pattern");
- }
- if (strcmp(Tcl_GetString(objv[j]), "-") != 0) {
- break;
- }
+ resultPtr = Tcl_NewUnicodeObj(ustring, first);
+ if (objc == 5) {
+ Tcl_AppendObjToObj(resultPtr, objv[4]);
}
-#ifndef TCL_TIP280
- result = Tcl_EvalObjEx(interp, objv[j], 0);
-#else
- /* TIP #280. Make invoking context available to switch branch */
- result = TclEvalObjEx(interp, objv[j], 0, &ctx, splitObjs ? j : bidx+j);
- if (splitObjs) {
- ckfree ((char*) ctx.line);
- if (pc && (ctx.type == TCL_LOCATION_SOURCE)) {
- /* Death of SrcInfo reference */
- Tcl_DecrRefCount (ctx.data.eval.path);
- }
- }
-#endif
- if (result == TCL_ERROR) {
- char msg[100 + TCL_INTEGER_SPACE];
-
- sprintf(msg, "\n (\"%.50s\" arm line %d)", pattern,
- interp->errorLine);
- Tcl_AddObjErrorInfo(interp, msg, -1);
+ if (last < length) {
+ Tcl_AppendUnicodeToObj(resultPtr, ustring + last + 1,
+ length - last);
}
- return result;
+ Tcl_SetObjResult(interp, resultPtr);
}
return TCL_OK;
}
@@ -2983,13 +2300,14 @@ Tcl_SwitchObjCmd(dummy, interp, objc, objv)
/*
*----------------------------------------------------------------------
*
- * Tcl_TimeObjCmd --
+ * StringRevCmd --
*
- * This object-based procedure is invoked to process the "time" Tcl
- * command. See the user documentation for details on what it does.
+ * This procedure is invoked to process the "string reverse" Tcl command.
+ * See the user documentation for details on what it does. Note that this
+ * command only functions correctly on properly formed Tcl UTF strings.
*
* Results:
- * A standard Tcl object result.
+ * A standard Tcl result.
*
* Side effects:
* See the user documentation.
@@ -2997,1919 +2315,1618 @@ Tcl_SwitchObjCmd(dummy, interp, objc, objv)
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
-int
-Tcl_TimeObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+static int
+StringRevCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- register Tcl_Obj *objPtr;
- Tcl_Obj *objs[4];
- register int i, result;
- int count;
- double totalMicroSec;
- Tcl_Time start, stop;
-
- if (objc == 2) {
- count = 1;
- } else if (objc == 3) {
- result = Tcl_GetIntFromObj(interp, objv[2], &count);
- if (result != TCL_OK) {
- return result;
- }
- } else {
- Tcl_WrongNumArgs(interp, 1, objv, "command ?count?");
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "string");
return TCL_ERROR;
}
-
- objPtr = objv[1];
- i = count;
- Tcl_GetTime(&start);
- while (i-- > 0) {
- result = Tcl_EvalObjEx(interp, objPtr, 0);
- if (result != TCL_OK) {
- return result;
- }
- }
- Tcl_GetTime(&stop);
-
- totalMicroSec = ( ( (double) ( stop.sec - start.sec ) ) * 1.0e6
- + ( stop.usec - start.usec ) );
- if (count <= 1) {
- /* Use int obj since we know time is not fractional [Bug 1202178] */
- objs[0] = Tcl_NewIntObj((count <= 0) ? 0 : (int) totalMicroSec);
- } else {
- objs[0] = Tcl_NewDoubleObj(totalMicroSec/count);
- }
- objs[1] = Tcl_NewStringObj("microseconds", -1);
- objs[2] = Tcl_NewStringObj("per", -1);
- objs[3] = Tcl_NewStringObj("iteration", -1);
- Tcl_SetObjResult(interp, Tcl_NewListObj(4, objs));
+
+ Tcl_SetObjResult(interp, TclStringObjReverse(objv[1]));
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * Tcl_TraceObjCmd --
- *
- * This procedure is invoked to process the "trace" Tcl command.
- * See the user documentation for details on what it does.
- *
- * Standard syntax as of Tcl 8.4 is
- *
- * trace {add|info|remove} {command|variable} name ops cmd
+ * StringStartCmd --
*
+ * This procedure is invoked to process the "string wordstart" Tcl
+ * command. See the user documentation for details on what it does. Note
+ * that this command only functions correctly on properly formed Tcl UTF
+ * strings.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
+ *
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
-int
-Tcl_TraceObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+static int
+StringStartCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- int optionIndex;
- char *name, *flagOps, *p;
- /* Main sub commands to 'trace' */
- static CONST char *traceOptions[] = {
- "add", "info", "remove",
-#ifndef TCL_REMOVE_OBSOLETE_TRACES
- "variable", "vdelete", "vinfo",
-#endif
- (char *) NULL
- };
- /* 'OLD' options are pre-Tcl-8.4 style */
- enum traceOptions {
- TRACE_ADD, TRACE_INFO, TRACE_REMOVE,
-#ifndef TCL_REMOVE_OBSOLETE_TRACES
- TRACE_OLD_VARIABLE, TRACE_OLD_VDELETE, TRACE_OLD_VINFO
-#endif
- };
+ Tcl_UniChar ch;
+ const char *p, *string;
+ int cur, index, length, numChars;
- if (objc < 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "string index");
return TCL_ERROR;
}
- if (Tcl_GetIndexFromObj(interp, objv[1], traceOptions,
- "option", 0, &optionIndex) != TCL_OK) {
+ string = TclGetStringFromObj(objv[1], &length);
+ numChars = Tcl_NumUtfChars(string, length);
+ if (TclGetIntForIndexM(interp, objv[2], numChars-1, &index) != TCL_OK) {
return TCL_ERROR;
}
- switch ((enum traceOptions) optionIndex) {
- case TRACE_ADD:
- case TRACE_REMOVE:
- case TRACE_INFO: {
- /*
- * All sub commands of trace add/remove must take at least
- * one more argument. Beyond that we let the subcommand itself
- * control the argument structure.
- */
- int typeIndex;
- if (objc < 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "type ?arg arg ...?");
- return TCL_ERROR;
- }
- if (Tcl_GetIndexFromObj(interp, objv[2], traceTypeOptions,
- "option", 0, &typeIndex) != TCL_OK) {
- return TCL_ERROR;
- }
- return (traceSubCmds[typeIndex])(interp, optionIndex, objc, objv);
- }
-#ifndef TCL_REMOVE_OBSOLETE_TRACES
- case TRACE_OLD_VARIABLE:
- case TRACE_OLD_VDELETE: {
- Tcl_Obj *copyObjv[6];
- Tcl_Obj *opsList;
- int code, numFlags;
-
- if (objc != 5) {
- Tcl_WrongNumArgs(interp, 2, objv, "name ops command");
- return TCL_ERROR;
- }
-
- opsList = Tcl_NewObj();
- Tcl_IncrRefCount(opsList);
- flagOps = Tcl_GetStringFromObj(objv[3], &numFlags);
- if (numFlags == 0) {
- Tcl_DecrRefCount(opsList);
- goto badVarOps;
- }
- for (p = flagOps; *p != 0; p++) {
- if (*p == 'r') {
- Tcl_ListObjAppendElement(NULL, opsList,
- Tcl_NewStringObj("read", -1));
- } else if (*p == 'w') {
- Tcl_ListObjAppendElement(NULL, opsList,
- Tcl_NewStringObj("write", -1));
- } else if (*p == 'u') {
- Tcl_ListObjAppendElement(NULL, opsList,
- Tcl_NewStringObj("unset", -1));
- } else if (*p == 'a') {
- Tcl_ListObjAppendElement(NULL, opsList,
- Tcl_NewStringObj("array", -1));
- } else {
- Tcl_DecrRefCount(opsList);
- goto badVarOps;
- }
- }
- copyObjv[0] = NULL;
- memcpy(copyObjv+1, objv, objc*sizeof(Tcl_Obj *));
- copyObjv[4] = opsList;
- if (optionIndex == TRACE_OLD_VARIABLE) {
- code = (traceSubCmds[2])(interp,TRACE_ADD,objc+1,copyObjv);
- } else {
- code = (traceSubCmds[2])(interp,TRACE_REMOVE,objc+1,copyObjv);
+ string = TclGetStringFromObj(objv[1], &length);
+ if (index >= numChars) {
+ index = numChars - 1;
+ }
+ cur = 0;
+ if (index > 0) {
+ p = Tcl_UtfAtIndex(string, index);
+ for (cur = index; cur >= 0; cur--) {
+ TclUtfToUniChar(p, &ch);
+ if (!Tcl_UniCharIsWordChar(ch)) {
+ break;
}
- Tcl_DecrRefCount(opsList);
- return code;
+ p = Tcl_UtfPrev(p, string);
}
- case TRACE_OLD_VINFO: {
- ClientData clientData;
- char ops[5];
- Tcl_Obj *resultListPtr, *pairObjPtr, *elemObjPtr;
-
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "name");
- return TCL_ERROR;
- }
- resultListPtr = Tcl_GetObjResult(interp);
- clientData = 0;
- name = Tcl_GetString(objv[2]);
- while ((clientData = Tcl_VarTraceInfo(interp, name, 0,
- TraceVarProc, clientData)) != 0) {
-
- TraceVarInfo *tvarPtr = (TraceVarInfo *) clientData;
-
- pairObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
- p = ops;
- if (tvarPtr->flags & TCL_TRACE_READS) {
- *p = 'r';
- p++;
- }
- if (tvarPtr->flags & TCL_TRACE_WRITES) {
- *p = 'w';
- p++;
- }
- if (tvarPtr->flags & TCL_TRACE_UNSETS) {
- *p = 'u';
- p++;
- }
- if (tvarPtr->flags & TCL_TRACE_ARRAY) {
- *p = 'a';
- p++;
- }
- *p = '\0';
-
- /*
- * Build a pair (2-item list) with the ops string as
- * the first obj element and the tvarPtr->command string
- * as the second obj element. Append the pair (as an
- * element) to the end of the result object list.
- */
-
- elemObjPtr = Tcl_NewStringObj(ops, -1);
- Tcl_ListObjAppendElement(NULL, pairObjPtr, elemObjPtr);
- elemObjPtr = Tcl_NewStringObj(tvarPtr->command, -1);
- Tcl_ListObjAppendElement(NULL, pairObjPtr, elemObjPtr);
- Tcl_ListObjAppendElement(interp, resultListPtr, pairObjPtr);
- }
- Tcl_SetObjResult(interp, resultListPtr);
- break;
+ if (cur != index) {
+ cur += 1;
}
-#endif /* TCL_REMOVE_OBSOLETE_TRACES */
}
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(cur));
return TCL_OK;
-
- badVarOps:
- Tcl_AppendResult(interp, "bad operations \"", flagOps,
- "\": should be one or more of rwua", (char *) NULL);
- return TCL_ERROR;
}
-
/*
*----------------------------------------------------------------------
*
- * TclTraceExecutionObjCmd --
+ * StringEndCmd --
*
- * Helper function for Tcl_TraceObjCmd; implements the
- * [trace {add|remove|info} execution ...] subcommands.
- * See the user documentation for details on what these do.
+ * This procedure is invoked to process the "string wordend" Tcl command.
+ * See the user documentation for details on what it does. Note that this
+ * command only functions correctly on properly formed Tcl UTF strings.
*
* Results:
- * Standard Tcl result.
+ * A standard Tcl result.
*
* Side effects:
- * Depends on the operation (add, remove, or info) being performed;
- * may add or remove command traces on a command.
+ * See the user documentation.
*
*----------------------------------------------------------------------
*/
-int
-TclTraceExecutionObjCmd(interp, optionIndex, objc, objv)
- Tcl_Interp *interp; /* Current interpreter. */
- int optionIndex; /* Add, info or remove */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+static int
+StringEndCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- int commandLength, index;
- char *name, *command;
- size_t length;
- enum traceOptions { TRACE_ADD, TRACE_INFO, TRACE_REMOVE };
- static CONST char *opStrings[] = { "enter", "leave",
- "enterstep", "leavestep", (char *) NULL };
- enum operations { TRACE_EXEC_ENTER, TRACE_EXEC_LEAVE,
- TRACE_EXEC_ENTER_STEP, TRACE_EXEC_LEAVE_STEP };
-
- switch ((enum traceOptions) optionIndex) {
- case TRACE_ADD:
- case TRACE_REMOVE: {
- int flags = 0;
- int i, listLen, result;
- Tcl_Obj **elemPtrs;
- if (objc != 6) {
- Tcl_WrongNumArgs(interp, 3, objv, "name opList command");
- return TCL_ERROR;
- }
- /*
- * Make sure the ops argument is a list object; get its length and
- * a pointer to its array of element pointers.
- */
-
- result = Tcl_ListObjGetElements(interp, objv[4], &listLen,
- &elemPtrs);
- if (result != TCL_OK) {
- return result;
- }
- if (listLen == 0) {
- Tcl_SetResult(interp, "bad operation list \"\": must be "
- "one or more of enter, leave, enterstep, or leavestep",
- TCL_STATIC);
- return TCL_ERROR;
- }
- for (i = 0; i < listLen; i++) {
- if (Tcl_GetIndexFromObj(interp, elemPtrs[i], opStrings,
- "operation", TCL_EXACT, &index) != TCL_OK) {
- return TCL_ERROR;
- }
- switch ((enum operations) index) {
- case TRACE_EXEC_ENTER:
- flags |= TCL_TRACE_ENTER_EXEC;
- break;
- case TRACE_EXEC_LEAVE:
- flags |= TCL_TRACE_LEAVE_EXEC;
- break;
- case TRACE_EXEC_ENTER_STEP:
- flags |= TCL_TRACE_ENTER_DURING_EXEC;
- break;
- case TRACE_EXEC_LEAVE_STEP:
- flags |= TCL_TRACE_LEAVE_DURING_EXEC;
- break;
- }
- }
- command = Tcl_GetStringFromObj(objv[5], &commandLength);
- length = (size_t) commandLength;
- if ((enum traceOptions) optionIndex == TRACE_ADD) {
- TraceCommandInfo *tcmdPtr;
- tcmdPtr = (TraceCommandInfo *) ckalloc((unsigned)
- (sizeof(TraceCommandInfo) - sizeof(tcmdPtr->command)
- + length + 1));
- tcmdPtr->flags = flags;
- tcmdPtr->stepTrace = NULL;
- tcmdPtr->startLevel = 0;
- tcmdPtr->startCmd = NULL;
- tcmdPtr->length = length;
- tcmdPtr->refCount = 1;
- flags |= TCL_TRACE_DELETE;
- if (flags & (TCL_TRACE_ENTER_DURING_EXEC |
- TCL_TRACE_LEAVE_DURING_EXEC)) {
- flags |= (TCL_TRACE_ENTER_EXEC |
- TCL_TRACE_LEAVE_EXEC);
- }
- memcpy(tcmdPtr->command, command, length + 1);
- name = Tcl_GetString(objv[3]);
- if (Tcl_TraceCommand(interp, name, flags, TraceCommandProc,
- (ClientData) tcmdPtr) != TCL_OK) {
- ckfree((char *) tcmdPtr);
- return TCL_ERROR;
- }
- } else {
- /*
- * Search through all of our traces on this command to
- * see if there's one with the given command. If so, then
- * delete the first one that matches.
- */
-
- TraceCommandInfo *tcmdPtr;
- ClientData clientData = NULL;
- name = Tcl_GetString(objv[3]);
-
- /* First ensure the name given is valid */
- if (Tcl_FindCommand(interp, name, NULL,
- TCL_LEAVE_ERR_MSG) == NULL) {
- return TCL_ERROR;
- }
-
- while ((clientData = Tcl_CommandTraceInfo(interp, name, 0,
- TraceCommandProc, clientData)) != NULL) {
- tcmdPtr = (TraceCommandInfo *) clientData;
- /*
- * In checking the 'flags' field we must remove any
- * extraneous flags which may have been temporarily
- * added by various pieces of the trace mechanism.
- */
- if ((tcmdPtr->length == length)
- && ((tcmdPtr->flags & (TCL_TRACE_ANY_EXEC |
- TCL_TRACE_RENAME |
- TCL_TRACE_DELETE)) == flags)
- && (strncmp(command, tcmdPtr->command,
- (size_t) length) == 0)) {
- flags |= TCL_TRACE_DELETE;
- if (flags & (TCL_TRACE_ENTER_DURING_EXEC |
- TCL_TRACE_LEAVE_DURING_EXEC)) {
- flags |= (TCL_TRACE_ENTER_EXEC |
- TCL_TRACE_LEAVE_EXEC);
- }
- Tcl_UntraceCommand(interp, name,
- flags, TraceCommandProc, clientData);
- if (tcmdPtr->stepTrace != NULL) {
- /*
- * We need to remove the interpreter-wide trace
- * which we created to allow 'step' traces.
- */
- Tcl_DeleteTrace(interp, tcmdPtr->stepTrace);
- tcmdPtr->stepTrace = NULL;
- if (tcmdPtr->startCmd != NULL) {
- ckfree((char *)tcmdPtr->startCmd);
- }
- }
- if (tcmdPtr->flags & TCL_TRACE_EXEC_IN_PROGRESS) {
- /* Postpone deletion */
- tcmdPtr->flags = 0;
- }
- tcmdPtr->refCount--;
- if (tcmdPtr->refCount < 0) {
- Tcl_Panic("TclTraceExecutionObjCmd: negative TraceCommandInfo refCount");
- }
- if (tcmdPtr->refCount == 0) {
- ckfree((char*)tcmdPtr);
- }
- break;
- }
- }
- }
- break;
- }
- case TRACE_INFO: {
- ClientData clientData;
- Tcl_Obj *resultListPtr, *eachTraceObjPtr, *elemObjPtr;
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 3, objv, "name");
- return TCL_ERROR;
- }
-
- clientData = NULL;
- name = Tcl_GetString(objv[3]);
-
- /* First ensure the name given is valid */
- if (Tcl_FindCommand(interp, name, NULL,
- TCL_LEAVE_ERR_MSG) == NULL) {
- return TCL_ERROR;
- }
-
- resultListPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
- while ((clientData = Tcl_CommandTraceInfo(interp, name, 0,
- TraceCommandProc, clientData)) != NULL) {
- int numOps = 0;
-
- TraceCommandInfo *tcmdPtr = (TraceCommandInfo *) clientData;
+ Tcl_UniChar ch;
+ const char *p, *end, *string;
+ int cur, index, length, numChars;
- /*
- * Build a list with the ops list as the first obj
- * element and the tcmdPtr->command string as the
- * second obj element. Append this list (as an
- * element) to the end of the result object list.
- */
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "string index");
+ return TCL_ERROR;
+ }
- elemObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
- Tcl_IncrRefCount(elemObjPtr);
- if (tcmdPtr->flags & TCL_TRACE_ENTER_EXEC) {
- Tcl_ListObjAppendElement(NULL, elemObjPtr,
- Tcl_NewStringObj("enter",5));
- }
- if (tcmdPtr->flags & TCL_TRACE_LEAVE_EXEC) {
- Tcl_ListObjAppendElement(NULL, elemObjPtr,
- Tcl_NewStringObj("leave",5));
- }
- if (tcmdPtr->flags & TCL_TRACE_ENTER_DURING_EXEC) {
- Tcl_ListObjAppendElement(NULL, elemObjPtr,
- Tcl_NewStringObj("enterstep",9));
- }
- if (tcmdPtr->flags & TCL_TRACE_LEAVE_DURING_EXEC) {
- Tcl_ListObjAppendElement(NULL, elemObjPtr,
- Tcl_NewStringObj("leavestep",9));
- }
- Tcl_ListObjLength(NULL, elemObjPtr, &numOps);
- if (0 == numOps) {
- Tcl_DecrRefCount(elemObjPtr);
- continue;
- }
- eachTraceObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
- Tcl_ListObjAppendElement(NULL, eachTraceObjPtr, elemObjPtr);
- Tcl_DecrRefCount(elemObjPtr);
- elemObjPtr = NULL;
-
- Tcl_ListObjAppendElement(NULL, eachTraceObjPtr,
- Tcl_NewStringObj(tcmdPtr->command, -1));
- Tcl_ListObjAppendElement(interp, resultListPtr,
- eachTraceObjPtr);
+ string = TclGetStringFromObj(objv[1], &length);
+ numChars = Tcl_NumUtfChars(string, length);
+ if (TclGetIntForIndexM(interp, objv[2], numChars-1, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ string = TclGetStringFromObj(objv[1], &length);
+ if (index < 0) {
+ index = 0;
+ }
+ if (index < numChars) {
+ p = Tcl_UtfAtIndex(string, index);
+ end = string+length;
+ for (cur = index; p < end; cur++) {
+ p += TclUtfToUniChar(p, &ch);
+ if (!Tcl_UniCharIsWordChar(ch)) {
+ break;
}
- Tcl_SetObjResult(interp, resultListPtr);
- break;
}
+ if (cur == index) {
+ cur++;
+ }
+ } else {
+ cur = numChars;
}
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(cur));
return TCL_OK;
}
-
/*
*----------------------------------------------------------------------
*
- * TclTraceCommandObjCmd --
+ * StringEqualCmd --
*
- * Helper function for Tcl_TraceObjCmd; implements the
- * [trace {add|info|remove} command ...] subcommands.
- * See the user documentation for details on what these do.
+ * This procedure is invoked to process the "string equal" Tcl command.
+ * See the user documentation for details on what it does. Note that this
+ * command only functions correctly on properly formed Tcl UTF strings.
*
* Results:
- * Standard Tcl result.
+ * A standard Tcl result.
*
* Side effects:
- * Depends on the operation (add, remove, or info) being performed;
- * may add or remove command traces on a command.
+ * See the user documentation.
*
*----------------------------------------------------------------------
*/
-int
-TclTraceCommandObjCmd(interp, optionIndex, objc, objv)
- Tcl_Interp *interp; /* Current interpreter. */
- int optionIndex; /* Add, info or remove */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+static int
+StringEqualCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- int commandLength, index;
- char *name, *command;
- size_t length;
- enum traceOptions { TRACE_ADD, TRACE_INFO, TRACE_REMOVE };
- static CONST char *opStrings[] = { "delete", "rename", (char *) NULL };
- enum operations { TRACE_CMD_DELETE, TRACE_CMD_RENAME };
-
- switch ((enum traceOptions) optionIndex) {
- case TRACE_ADD:
- case TRACE_REMOVE: {
- int flags = 0;
- int i, listLen, result;
- Tcl_Obj **elemPtrs;
- if (objc != 6) {
- Tcl_WrongNumArgs(interp, 3, objv, "name opList command");
- return TCL_ERROR;
- }
- /*
- * Make sure the ops argument is a list object; get its length and
- * a pointer to its array of element pointers.
- */
+ /*
+ * Remember to keep code here in some sync with the byte-compiled versions
+ * in tclExecute.c (INST_STR_EQ, INST_STR_NEQ and INST_STR_CMP as well as
+ * the expr string comparison in INST_EQ/INST_NEQ/INST_LT/...).
+ */
- result = Tcl_ListObjGetElements(interp, objv[4], &listLen,
- &elemPtrs);
- if (result != TCL_OK) {
- return result;
+ char *string1, *string2;
+ int length1, length2, i, match, length, nocase = 0, reqlength = -1;
+ typedef int (*strCmpFn_t)(const char *, const char *, unsigned int);
+ strCmpFn_t strCmpFn;
+
+ if (objc < 3 || objc > 6) {
+ str_cmp_args:
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "?-nocase? ?-length int? string1 string2");
+ return TCL_ERROR;
+ }
+
+ for (i = 1; i < objc-2; i++) {
+ string2 = TclGetStringFromObj(objv[i], &length2);
+ if ((length2 > 1) && !strncmp(string2, "-nocase", (size_t)length2)) {
+ nocase = 1;
+ } else if ((length2 > 1)
+ && !strncmp(string2, "-length", (size_t)length2)) {
+ if (i+1 >= objc-2) {
+ goto str_cmp_args;
}
- if (listLen == 0) {
- Tcl_SetResult(interp, "bad operation list \"\": must be "
- "one or more of delete or rename", TCL_STATIC);
+ ++i;
+ if (TclGetIntFromObj(interp, objv[i], &reqlength) != TCL_OK) {
return TCL_ERROR;
}
- for (i = 0; i < listLen; i++) {
- if (Tcl_GetIndexFromObj(interp, elemPtrs[i], opStrings,
- "operation", TCL_EXACT, &index) != TCL_OK) {
- return TCL_ERROR;
- }
- switch ((enum operations) index) {
- case TRACE_CMD_RENAME:
- flags |= TCL_TRACE_RENAME;
- break;
- case TRACE_CMD_DELETE:
- flags |= TCL_TRACE_DELETE;
- break;
- }
- }
- command = Tcl_GetStringFromObj(objv[5], &commandLength);
- length = (size_t) commandLength;
- if ((enum traceOptions) optionIndex == TRACE_ADD) {
- TraceCommandInfo *tcmdPtr;
- tcmdPtr = (TraceCommandInfo *) ckalloc((unsigned)
- (sizeof(TraceCommandInfo) - sizeof(tcmdPtr->command)
- + length + 1));
- tcmdPtr->flags = flags;
- tcmdPtr->stepTrace = NULL;
- tcmdPtr->startLevel = 0;
- tcmdPtr->startCmd = NULL;
- tcmdPtr->length = length;
- tcmdPtr->refCount = 1;
- flags |= TCL_TRACE_DELETE;
- memcpy(tcmdPtr->command, command, length + 1);
- name = Tcl_GetString(objv[3]);
- if (Tcl_TraceCommand(interp, name, flags, TraceCommandProc,
- (ClientData) tcmdPtr) != TCL_OK) {
- ckfree((char *) tcmdPtr);
- return TCL_ERROR;
- }
- } else {
- /*
- * Search through all of our traces on this command to
- * see if there's one with the given command. If so, then
- * delete the first one that matches.
- */
-
- TraceCommandInfo *tcmdPtr;
- ClientData clientData = NULL;
- name = Tcl_GetString(objv[3]);
-
- /* First ensure the name given is valid */
- if (Tcl_FindCommand(interp, name, NULL,
- TCL_LEAVE_ERR_MSG) == NULL) {
- return TCL_ERROR;
- }
-
- while ((clientData = Tcl_CommandTraceInfo(interp, name, 0,
- TraceCommandProc, clientData)) != NULL) {
- tcmdPtr = (TraceCommandInfo *) clientData;
- if ((tcmdPtr->length == length)
- && (tcmdPtr->flags == flags)
- && (strncmp(command, tcmdPtr->command,
- (size_t) length) == 0)) {
- Tcl_UntraceCommand(interp, name,
- flags | TCL_TRACE_DELETE,
- TraceCommandProc, clientData);
- tcmdPtr->flags |= TCL_TRACE_DESTROYED;
- tcmdPtr->refCount--;
- if (tcmdPtr->refCount < 0) {
- Tcl_Panic("TclTraceCommandObjCmd: negative TraceCommandInfo refCount");
- }
- if (tcmdPtr->refCount == 0) {
- ckfree((char *) tcmdPtr);
- }
- break;
- }
- }
- }
- break;
+ } else {
+ Tcl_AppendResult(interp, "bad option \"", string2,
+ "\": must be -nocase or -length", NULL);
+ return TCL_ERROR;
}
- case TRACE_INFO: {
- ClientData clientData;
- Tcl_Obj *resultListPtr, *eachTraceObjPtr, *elemObjPtr;
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 3, objv, "name");
- return TCL_ERROR;
- }
+ }
- clientData = NULL;
- name = Tcl_GetString(objv[3]);
-
- /* First ensure the name given is valid */
- if (Tcl_FindCommand(interp, name, NULL,
- TCL_LEAVE_ERR_MSG) == NULL) {
- return TCL_ERROR;
- }
-
- resultListPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
- while ((clientData = Tcl_CommandTraceInfo(interp, name, 0,
- TraceCommandProc, clientData)) != NULL) {
- int numOps = 0;
+ /*
+ * From now on, we only access the two objects at the end of the argument
+ * array.
+ */
- TraceCommandInfo *tcmdPtr = (TraceCommandInfo *) clientData;
+ objv += objc-2;
- /*
- * Build a list with the ops list as
- * the first obj element and the tcmdPtr->command string
- * as the second obj element. Append this list (as an
- * element) to the end of the result object list.
- */
+ if ((reqlength == 0) || (objv[0] == objv[1])) {
+ /*
+ * Always match at 0 chars of if it is the same obj.
+ */
- elemObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
- Tcl_IncrRefCount(elemObjPtr);
- if (tcmdPtr->flags & TCL_TRACE_RENAME) {
- Tcl_ListObjAppendElement(NULL, elemObjPtr,
- Tcl_NewStringObj("rename",6));
- }
- if (tcmdPtr->flags & TCL_TRACE_DELETE) {
- Tcl_ListObjAppendElement(NULL, elemObjPtr,
- Tcl_NewStringObj("delete",6));
- }
- Tcl_ListObjLength(NULL, elemObjPtr, &numOps);
- if (0 == numOps) {
- Tcl_DecrRefCount(elemObjPtr);
- continue;
- }
- eachTraceObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
- Tcl_ListObjAppendElement(NULL, eachTraceObjPtr, elemObjPtr);
- Tcl_DecrRefCount(elemObjPtr);
-
- elemObjPtr = Tcl_NewStringObj(tcmdPtr->command, -1);
- Tcl_ListObjAppendElement(NULL, eachTraceObjPtr, elemObjPtr);
- Tcl_ListObjAppendElement(interp, resultListPtr,
- eachTraceObjPtr);
- }
- Tcl_SetObjResult(interp, resultListPtr);
- break;
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
+ return TCL_OK;
+ }
+
+ if (!nocase && objv[0]->typePtr == &tclByteArrayType &&
+ objv[1]->typePtr == &tclByteArrayType) {
+ /*
+ * Use binary versions of comparisons since that won't cause undue
+ * type conversions and it is much faster. Only do this if we're
+ * case-sensitive (which is all that really makes sense with byte
+ * arrays anyway, and we have no memcasecmp() for some reason... :^)
+ */
+
+ string1 = (char *) Tcl_GetByteArrayFromObj(objv[0], &length1);
+ string2 = (char *) Tcl_GetByteArrayFromObj(objv[1], &length2);
+ strCmpFn = (strCmpFn_t) memcmp;
+ } else if ((objv[0]->typePtr == &tclStringType)
+ && (objv[1]->typePtr == &tclStringType)) {
+ /*
+ * Do a unicode-specific comparison if both of the args are of String
+ * type. In benchmark testing this proved the most efficient check
+ * between the unicode and string comparison operations.
+ */
+
+ string1 = (char *) Tcl_GetUnicodeFromObj(objv[0], &length1);
+ string2 = (char *) Tcl_GetUnicodeFromObj(objv[1], &length2);
+ strCmpFn = (strCmpFn_t)
+ (nocase ? Tcl_UniCharNcasecmp : Tcl_UniCharNcmp);
+ } else {
+ /*
+ * As a catch-all we will work with UTF-8. We cannot use memcmp() as
+ * that is unsafe with any string containing NUL (\xC0\x80 in Tcl's
+ * utf rep). We can use the more efficient TclpUtfNcmp2 if we are
+ * case-sensitive and no specific length was requested.
+ */
+
+ string1 = (char *) TclGetStringFromObj(objv[0], &length1);
+ string2 = (char *) TclGetStringFromObj(objv[1], &length2);
+ if ((reqlength < 0) && !nocase) {
+ strCmpFn = (strCmpFn_t) TclpUtfNcmp2;
+ } else {
+ length1 = Tcl_NumUtfChars(string1, length1);
+ length2 = Tcl_NumUtfChars(string2, length2);
+ strCmpFn = (strCmpFn_t) (nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp);
+ }
+ }
+
+ if ((reqlength < 0) && (length1 != length2)) {
+ match = 1; /* This will be reversed below. */
+ } else {
+ length = (length1 < length2) ? length1 : length2;
+ if (reqlength > 0 && reqlength < length) {
+ length = reqlength;
+ } else if (reqlength < 0) {
+ /*
+ * The requested length is negative, so we ignore it by setting it
+ * to length + 1 so we correct the match var.
+ */
+
+ reqlength = length + 1;
+ }
+
+ match = strCmpFn(string1, string2, (unsigned) length);
+ if ((match == 0) && (reqlength > length)) {
+ match = length1 - length2;
}
}
+
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(match ? 0 : 1));
return TCL_OK;
}
-
/*
*----------------------------------------------------------------------
*
- * TclTraceVariableObjCmd --
+ * StringCmpCmd --
*
- * Helper function for Tcl_TraceObjCmd; implements the
- * [trace {add|info|remove} variable ...] subcommands.
- * See the user documentation for details on what these do.
+ * This procedure is invoked to process the "string compare" Tcl command.
+ * See the user documentation for details on what it does. Note that this
+ * command only functions correctly on properly formed Tcl UTF strings.
*
* Results:
- * Standard Tcl result.
+ * A standard Tcl result.
*
* Side effects:
- * Depends on the operation (add, remove, or info) being performed;
- * may add or remove variable traces on a variable.
+ * See the user documentation.
*
*----------------------------------------------------------------------
*/
-int
-TclTraceVariableObjCmd(interp, optionIndex, objc, objv)
- Tcl_Interp *interp; /* Current interpreter. */
- int optionIndex; /* Add, info or remove */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+static int
+StringCmpCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- int commandLength, index;
- char *name, *command;
- size_t length;
- enum traceOptions { TRACE_ADD, TRACE_INFO, TRACE_REMOVE };
- static CONST char *opStrings[] = { "array", "read", "unset", "write",
- (char *) NULL };
- enum operations { TRACE_VAR_ARRAY, TRACE_VAR_READ, TRACE_VAR_UNSET,
- TRACE_VAR_WRITE };
-
- switch ((enum traceOptions) optionIndex) {
- case TRACE_ADD:
- case TRACE_REMOVE: {
- int flags = 0;
- int i, listLen, result;
- Tcl_Obj **elemPtrs;
- if (objc != 6) {
- Tcl_WrongNumArgs(interp, 3, objv, "name opList command");
- return TCL_ERROR;
- }
- /*
- * Make sure the ops argument is a list object; get its length and
- * a pointer to its array of element pointers.
- */
+ /*
+ * Remember to keep code here in some sync with the byte-compiled versions
+ * in tclExecute.c (INST_STR_EQ, INST_STR_NEQ and INST_STR_CMP as well as
+ * the expr string comparison in INST_EQ/INST_NEQ/INST_LT/...).
+ */
- result = Tcl_ListObjGetElements(interp, objv[4], &listLen,
- &elemPtrs);
- if (result != TCL_OK) {
- return result;
- }
- if (listLen == 0) {
- Tcl_SetResult(interp, "bad operation list \"\": must be "
- "one or more of array, read, unset, or write",
- TCL_STATIC);
- return TCL_ERROR;
- }
- for (i = 0; i < listLen ; i++) {
- if (Tcl_GetIndexFromObj(interp, elemPtrs[i], opStrings,
- "operation", TCL_EXACT, &index) != TCL_OK) {
- return TCL_ERROR;
- }
- switch ((enum operations) index) {
- case TRACE_VAR_ARRAY:
- flags |= TCL_TRACE_ARRAY;
- break;
- case TRACE_VAR_READ:
- flags |= TCL_TRACE_READS;
- break;
- case TRACE_VAR_UNSET:
- flags |= TCL_TRACE_UNSETS;
- break;
- case TRACE_VAR_WRITE:
- flags |= TCL_TRACE_WRITES;
- break;
- }
- }
- command = Tcl_GetStringFromObj(objv[5], &commandLength);
- length = (size_t) commandLength;
- if ((enum traceOptions) optionIndex == TRACE_ADD) {
- /*
- * This code essentially mallocs together the VarTrace and the
- * TraceVarInfo, then inlines the Tcl_TraceVar(). This is
- * necessary in order to have the TraceVarInfo to be freed
- * automatically when the VarTrace is freed [Bug 1348775]
- */
+ char *string1, *string2;
+ int length1, length2, i, match, length, nocase = 0, reqlength = -1;
+ typedef int (*strCmpFn_t)(const char *, const char *, unsigned int);
+ strCmpFn_t strCmpFn;
- CompoundVarTrace *compTracePtr;
- TraceVarInfo *tvarPtr;
- Var *varPtr, *arrayPtr;
- VarTrace *tracePtr;
- int flagMask;
-
- compTracePtr = (CompoundVarTrace *) ckalloc((unsigned)
- (sizeof(CompoundVarTrace) - sizeof(tvarPtr->command)
- + length + 1));
- tracePtr = &(compTracePtr->trace);
- tvarPtr = &(compTracePtr->tvar);
- tvarPtr->flags = flags;
- if (objv[0] == NULL) {
- tvarPtr->flags |= TCL_TRACE_OLD_STYLE;
- }
- tvarPtr->length = length;
- flags |= TCL_TRACE_UNSETS | TCL_TRACE_RESULT_OBJECT;
- memcpy(tvarPtr->command, command, length + 1);
- name = Tcl_GetString(objv[3]);
- flagMask = TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY;
- varPtr = TclLookupVar(interp, name, NULL,
- (flags & flagMask) | TCL_LEAVE_ERR_MSG, "trace",
- /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
- if (varPtr == NULL) {
- ckfree((char *) tracePtr);
- return TCL_ERROR;
- }
- flagMask = TCL_TRACE_READS | TCL_TRACE_WRITES
- | TCL_TRACE_UNSETS | TCL_TRACE_ARRAY
- | TCL_TRACE_RESULT_DYNAMIC | TCL_TRACE_RESULT_OBJECT;
-#ifndef TCL_REMOVE_OBSOLETE_TRACES
- flagMask |= TCL_TRACE_OLD_STYLE;
-#endif
- tracePtr->traceProc = TraceVarProc;
- tracePtr->clientData = (ClientData) tvarPtr;
- tracePtr->flags = flags & flagMask;
- tracePtr->nextPtr = varPtr->tracePtr;
- varPtr->tracePtr = tracePtr;
- } else {
- /*
- * Search through all of our traces on this variable to
- * see if there's one with the given command. If so, then
- * delete the first one that matches.
- */
-
- TraceVarInfo *tvarPtr;
- ClientData clientData = 0;
- name = Tcl_GetString(objv[3]);
- while ((clientData = Tcl_VarTraceInfo(interp, name, 0,
- TraceVarProc, clientData)) != 0) {
- tvarPtr = (TraceVarInfo *) clientData;
- if ((tvarPtr->length == length)
- && ((tvarPtr->flags & ~TCL_TRACE_OLD_STYLE)==flags)
- && (strncmp(command, tvarPtr->command,
- (size_t) length) == 0)) {
- Tcl_UntraceVar2(interp, name, NULL,
- flags | TCL_TRACE_UNSETS | TCL_TRACE_RESULT_OBJECT,
- TraceVarProc, clientData);
- break;
- }
- }
+ if (objc < 3 || objc > 6) {
+ str_cmp_args:
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "?-nocase? ?-length int? string1 string2");
+ return TCL_ERROR;
+ }
+
+ for (i = 1; i < objc-2; i++) {
+ string2 = TclGetStringFromObj(objv[i], &length2);
+ if ((length2 > 1) && !strncmp(string2, "-nocase", (size_t)length2)) {
+ nocase = 1;
+ } else if ((length2 > 1)
+ && !strncmp(string2, "-length", (size_t)length2)) {
+ if (i+1 >= objc-2) {
+ goto str_cmp_args;
}
- break;
- }
- case TRACE_INFO: {
- ClientData clientData;
- Tcl_Obj *resultListPtr, *eachTraceObjPtr, *elemObjPtr;
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 3, objv, "name");
+ ++i;
+ if (TclGetIntFromObj(interp, objv[i], &reqlength) != TCL_OK) {
return TCL_ERROR;
}
+ } else {
+ Tcl_AppendResult(interp, "bad option \"", string2,
+ "\": must be -nocase or -length", NULL);
+ return TCL_ERROR;
+ }
+ }
- resultListPtr = Tcl_GetObjResult(interp);
- clientData = 0;
- name = Tcl_GetString(objv[3]);
- while ((clientData = Tcl_VarTraceInfo(interp, name, 0,
- TraceVarProc, clientData)) != 0) {
+ /*
+ * From now on, we only access the two objects at the end of the argument
+ * array.
+ */
- TraceVarInfo *tvarPtr = (TraceVarInfo *) clientData;
+ objv += objc-2;
- /*
- * Build a list with the ops list as
- * the first obj element and the tcmdPtr->command string
- * as the second obj element. Append this list (as an
- * element) to the end of the result object list.
- */
+ if ((reqlength == 0) || (objv[0] == objv[1])) {
+ /*
+ * Always match at 0 chars of if it is the same obj.
+ */
- elemObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
- if (tvarPtr->flags & TCL_TRACE_ARRAY) {
- Tcl_ListObjAppendElement(NULL, elemObjPtr,
- Tcl_NewStringObj("array", 5));
- }
- if (tvarPtr->flags & TCL_TRACE_READS) {
- Tcl_ListObjAppendElement(NULL, elemObjPtr,
- Tcl_NewStringObj("read", 4));
- }
- if (tvarPtr->flags & TCL_TRACE_WRITES) {
- Tcl_ListObjAppendElement(NULL, elemObjPtr,
- Tcl_NewStringObj("write", 5));
- }
- if (tvarPtr->flags & TCL_TRACE_UNSETS) {
- Tcl_ListObjAppendElement(NULL, elemObjPtr,
- Tcl_NewStringObj("unset", 5));
- }
- eachTraceObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
- Tcl_ListObjAppendElement(NULL, eachTraceObjPtr, elemObjPtr);
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
+ return TCL_OK;
+ }
- elemObjPtr = Tcl_NewStringObj(tvarPtr->command, -1);
- Tcl_ListObjAppendElement(NULL, eachTraceObjPtr, elemObjPtr);
- Tcl_ListObjAppendElement(interp, resultListPtr,
- eachTraceObjPtr);
- }
- Tcl_SetObjResult(interp, resultListPtr);
- break;
+ if (!nocase && objv[0]->typePtr == &tclByteArrayType &&
+ objv[1]->typePtr == &tclByteArrayType) {
+ /*
+ * Use binary versions of comparisons since that won't cause undue
+ * type conversions and it is much faster. Only do this if we're
+ * case-sensitive (which is all that really makes sense with byte
+ * arrays anyway, and we have no memcasecmp() for some reason... :^)
+ */
+
+ string1 = (char *) Tcl_GetByteArrayFromObj(objv[0], &length1);
+ string2 = (char *) Tcl_GetByteArrayFromObj(objv[1], &length2);
+ strCmpFn = (strCmpFn_t) memcmp;
+ } else if ((objv[0]->typePtr == &tclStringType)
+ && (objv[1]->typePtr == &tclStringType)) {
+ /*
+ * Do a unicode-specific comparison if both of the args are of String
+ * type. In benchmark testing this proved the most efficient check
+ * between the unicode and string comparison operations.
+ */
+
+ string1 = (char *) Tcl_GetUnicodeFromObj(objv[0], &length1);
+ string2 = (char *) Tcl_GetUnicodeFromObj(objv[1], &length2);
+ strCmpFn = (strCmpFn_t)
+ (nocase ? Tcl_UniCharNcasecmp : Tcl_UniCharNcmp);
+ } else {
+ /*
+ * As a catch-all we will work with UTF-8. We cannot use memcmp() as
+ * that is unsafe with any string containing NUL (\xC0\x80 in Tcl's
+ * utf rep). We can use the more efficient TclpUtfNcmp2 if we are
+ * case-sensitive and no specific length was requested.
+ */
+
+ string1 = (char *) TclGetStringFromObj(objv[0], &length1);
+ string2 = (char *) TclGetStringFromObj(objv[1], &length2);
+ if ((reqlength < 0) && !nocase) {
+ strCmpFn = (strCmpFn_t) TclpUtfNcmp2;
+ } else {
+ length1 = Tcl_NumUtfChars(string1, length1);
+ length2 = Tcl_NumUtfChars(string2, length2);
+ strCmpFn = (strCmpFn_t) (nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp);
}
}
+
+ length = (length1 < length2) ? length1 : length2;
+ if (reqlength > 0 && reqlength < length) {
+ length = reqlength;
+ } else if (reqlength < 0) {
+ /*
+ * The requested length is negative, so we ignore it by setting it to
+ * length + 1 so we correct the match var.
+ */
+
+ reqlength = length + 1;
+ }
+
+ match = strCmpFn(string1, string2, (unsigned) length);
+ if ((match == 0) && (reqlength > length)) {
+ match = length1 - length2;
+ }
+
+ Tcl_SetObjResult(interp,
+ Tcl_NewIntObj((match > 0) ? 1 : (match < 0) ? -1 : 0));
return TCL_OK;
}
-
/*
*----------------------------------------------------------------------
*
- * Tcl_CommandTraceInfo --
+ * StringBytesCmd --
*
- * Return the clientData value associated with a trace on a
- * command. This procedure can also be used to step through
- * all of the traces on a particular command that have the
- * same trace procedure.
+ * This procedure is invoked to process the "string bytelength" Tcl
+ * command. See the user documentation for details on what it does. Note
+ * that this command only functions correctly on properly formed Tcl UTF
+ * strings.
*
* Results:
- * The return value is the clientData value associated with
- * a trace on the given command. Information will only be
- * returned for a trace with proc as trace procedure. If
- * the clientData argument is NULL then the first such trace is
- * returned; otherwise, the next relevant one after the one
- * given by clientData will be returned. If the command
- * doesn't exist then an error message is left in the interpreter
- * and NULL is returned. Also, if there are no (more) traces for
- * the given command, NULL is returned.
+ * A standard Tcl result.
*
* Side effects:
- * None.
+ * See the user documentation.
*
*----------------------------------------------------------------------
*/
-ClientData
-Tcl_CommandTraceInfo(interp, cmdName, flags, proc, prevClientData)
- Tcl_Interp *interp; /* Interpreter containing command. */
- CONST char *cmdName; /* Name of command. */
- int flags; /* OR-ed combo or TCL_GLOBAL_ONLY,
- * TCL_NAMESPACE_ONLY (can be 0). */
- Tcl_CommandTraceProc *proc; /* Procedure assocated with trace. */
- ClientData prevClientData; /* If non-NULL, gives last value returned
- * by this procedure, so this call will
- * return the next trace after that one.
- * If NULL, this call will return the
- * first trace. */
+static int
+StringBytesCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- Command *cmdPtr;
- register CommandTrace *tracePtr;
+ int length;
- cmdPtr = (Command*)Tcl_FindCommand(interp, cmdName,
- NULL, TCL_LEAVE_ERR_MSG);
- if (cmdPtr == NULL) {
- return NULL;
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "string");
+ return TCL_ERROR;
}
- /*
- * Find the relevant trace, if any, and return its clientData.
- */
-
- tracePtr = cmdPtr->tracePtr;
- if (prevClientData != NULL) {
- for ( ; tracePtr != NULL; tracePtr = tracePtr->nextPtr) {
- if ((tracePtr->clientData == prevClientData)
- && (tracePtr->traceProc == proc)) {
- tracePtr = tracePtr->nextPtr;
- break;
- }
- }
- }
- for ( ; tracePtr != NULL; tracePtr = tracePtr->nextPtr) {
- if (tracePtr->traceProc == proc) {
- return tracePtr->clientData;
- }
- }
- return NULL;
+ (void) TclGetStringFromObj(objv[1], &length);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(length));
+ return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * Tcl_TraceCommand --
+ * StringLenCmd --
*
- * Arrange for rename/deletes to a command to cause a
- * procedure to be invoked, which can monitor the operations.
- *
- * Also optionally arrange for execution of that command
- * to cause a procedure to be invoked.
+ * This procedure is invoked to process the "string length" Tcl command.
+ * See the user documentation for details on what it does. Note that this
+ * command only functions correctly on properly formed Tcl UTF strings.
*
* Results:
- * A standard Tcl return value.
+ * A standard Tcl result.
*
* Side effects:
- * A trace is set up on the command given by cmdName, such that
- * future changes to the command will be intermediated by
- * proc. See the manual entry for complete details on the calling
- * sequence for proc.
+ * See the user documentation.
*
*----------------------------------------------------------------------
*/
-int
-Tcl_TraceCommand(interp, cmdName, flags, proc, clientData)
- Tcl_Interp *interp; /* Interpreter in which command is
- * to be traced. */
- CONST char *cmdName; /* Name of command. */
- int flags; /* OR-ed collection of bits, including any
- * of TCL_TRACE_RENAME, TCL_TRACE_DELETE,
- * and any of the TRACE_*_EXEC flags */
- Tcl_CommandTraceProc *proc; /* Procedure to call when specified ops are
- * invoked upon varName. */
- ClientData clientData; /* Arbitrary argument to pass to proc. */
+static int
+StringLenCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- Command *cmdPtr;
- register CommandTrace *tracePtr;
+ int length;
- cmdPtr = (Command*)Tcl_FindCommand(interp, cmdName,
- NULL, TCL_LEAVE_ERR_MSG);
- if (cmdPtr == NULL) {
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "string");
return TCL_ERROR;
}
/*
- * Set up trace information.
+ * If we have a ByteArray object, avoid recomputing the string since the
+ * byte array contains one byte per character. Otherwise, use the Unicode
+ * string rep to calculate the length.
*/
- tracePtr = (CommandTrace *) ckalloc(sizeof(CommandTrace));
- tracePtr->traceProc = proc;
- tracePtr->clientData = clientData;
- tracePtr->flags = flags & (TCL_TRACE_RENAME | TCL_TRACE_DELETE
- | TCL_TRACE_ANY_EXEC);
- tracePtr->nextPtr = cmdPtr->tracePtr;
- tracePtr->refCount = 1;
- cmdPtr->tracePtr = tracePtr;
- if (tracePtr->flags & TCL_TRACE_ANY_EXEC) {
- cmdPtr->flags |= CMD_HAS_EXEC_TRACES;
+ if (objv[1]->typePtr == &tclByteArrayType) {
+ (void) Tcl_GetByteArrayFromObj(objv[1], &length);
+ } else {
+ length = Tcl_GetCharLength(objv[1]);
}
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(length));
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * Tcl_UntraceCommand --
+ * StringLowerCmd --
*
- * Remove a previously-created trace for a command.
+ * This procedure is invoked to process the "string tolower" Tcl command.
+ * See the user documentation for details on what it does. Note that this
+ * command only functions correctly on properly formed Tcl UTF strings.
*
* Results:
- * None.
+ * A standard Tcl result.
*
* Side effects:
- * If there exists a trace for the command given by cmdName
- * with the given flags, proc, and clientData, then that trace
- * is removed.
+ * See the user documentation.
*
*----------------------------------------------------------------------
*/
-void
-Tcl_UntraceCommand(interp, cmdName, flags, proc, clientData)
- Tcl_Interp *interp; /* Interpreter containing command. */
- CONST char *cmdName; /* Name of command. */
- int flags; /* OR-ed collection of bits, including any
- * of TCL_TRACE_RENAME, TCL_TRACE_DELETE,
- * and any of the TRACE_*_EXEC flags */
- Tcl_CommandTraceProc *proc; /* Procedure assocated with trace. */
- ClientData clientData; /* Arbitrary argument to pass to proc. */
+static int
+StringLowerCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- register CommandTrace *tracePtr;
- CommandTrace *prevPtr;
- Command *cmdPtr;
- Interp *iPtr = (Interp *) interp;
- ActiveCommandTrace *activePtr;
- int hasExecTraces = 0;
-
- cmdPtr = (Command*)Tcl_FindCommand(interp, cmdName,
- NULL, TCL_LEAVE_ERR_MSG);
- if (cmdPtr == NULL) {
- return;
+ int length1, length2;
+ char *string1, *string2;
+
+ if (objc < 2 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "string ?first? ?last?");
+ return TCL_ERROR;
}
- flags &= (TCL_TRACE_RENAME | TCL_TRACE_DELETE | TCL_TRACE_ANY_EXEC);
+ string1 = TclGetStringFromObj(objv[1], &length1);
+
+ if (objc == 2) {
+ Tcl_Obj *resultPtr = Tcl_NewStringObj(string1, length1);
+
+ length1 = Tcl_UtfToLower(TclGetString(resultPtr));
+ Tcl_SetObjLength(resultPtr, length1);
+ Tcl_SetObjResult(interp, resultPtr);
+ } else {
+ int first, last;
+ const char *start, *end;
+ Tcl_Obj *resultPtr;
- for (tracePtr = cmdPtr->tracePtr, prevPtr = NULL; ;
- prevPtr = tracePtr, tracePtr = tracePtr->nextPtr) {
- if (tracePtr == NULL) {
- return;
+ length1 = Tcl_NumUtfChars(string1, length1) - 1;
+ if (TclGetIntForIndexM(interp,objv[2],length1, &first) != TCL_OK) {
+ return TCL_ERROR;
}
- if ((tracePtr->traceProc == proc)
- && ((tracePtr->flags & (TCL_TRACE_RENAME | TCL_TRACE_DELETE |
- TCL_TRACE_ANY_EXEC)) == flags)
- && (tracePtr->clientData == clientData)) {
- if (tracePtr->flags & TCL_TRACE_ANY_EXEC) {
- hasExecTraces = 1;
- }
- break;
+ if (first < 0) {
+ first = 0;
}
- }
-
- /*
- * The code below makes it possible to delete traces while traces
- * are active: it makes sure that the deleted trace won't be
- * processed by CallCommandTraces.
- */
+ last = first;
- for (activePtr = iPtr->activeCmdTracePtr; activePtr != NULL;
- activePtr = activePtr->nextPtr) {
- if (activePtr->nextTracePtr == tracePtr) {
- if (activePtr->reverseScan) {
- activePtr->nextTracePtr = prevPtr;
- } else {
- activePtr->nextTracePtr = tracePtr->nextPtr;
- }
+ if ((objc == 4) && (TclGetIntForIndexM(interp, objv[3], length1,
+ &last) != TCL_OK)) {
+ return TCL_ERROR;
}
- }
- if (prevPtr == NULL) {
- cmdPtr->tracePtr = tracePtr->nextPtr;
- } else {
- prevPtr->nextPtr = tracePtr->nextPtr;
- }
- tracePtr->flags = 0;
-
- if ((--tracePtr->refCount) <= 0) {
- ckfree((char*)tracePtr);
- }
-
- if (hasExecTraces) {
- for (tracePtr = cmdPtr->tracePtr, prevPtr = NULL; tracePtr != NULL ;
- prevPtr = tracePtr, tracePtr = tracePtr->nextPtr) {
- if (tracePtr->flags & TCL_TRACE_ANY_EXEC) {
- return;
- }
+
+ if (last >= length1) {
+ last = length1;
}
- /*
- * None of the remaining traces on this command are execution
- * traces. We therefore remove this flag:
- */
- cmdPtr->flags &= ~CMD_HAS_EXEC_TRACES;
+ if (last < first) {
+ Tcl_SetObjResult(interp, objv[1]);
+ return TCL_OK;
+ }
+
+ string1 = TclGetStringFromObj(objv[1], &length1);
+ start = Tcl_UtfAtIndex(string1, first);
+ end = Tcl_UtfAtIndex(start, last - first + 1);
+ resultPtr = Tcl_NewStringObj(string1, end - string1);
+ string2 = TclGetString(resultPtr) + (start - string1);
+
+ length2 = Tcl_UtfToLower(string2);
+ Tcl_SetObjLength(resultPtr, length2 + (start - string1));
+
+ Tcl_AppendToObj(resultPtr, end, -1);
+ Tcl_SetObjResult(interp, resultPtr);
}
+
+ return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * TraceCommandProc --
+ * StringUpperCmd --
*
- * This procedure is called to handle command changes that have
- * been traced using the "trace" command, when using the
- * 'rename' or 'delete' options.
+ * This procedure is invoked to process the "string toupper" Tcl command.
+ * See the user documentation for details on what it does. Note that this
+ * command only functions correctly on properly formed Tcl UTF strings.
*
* Results:
- * None.
+ * A standard Tcl result.
*
* Side effects:
- * Depends on the command associated with the trace.
+ * See the user documentation.
*
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
-static void
-TraceCommandProc(clientData, interp, oldName, newName, flags)
- ClientData clientData; /* Information about the command trace. */
- Tcl_Interp *interp; /* Interpreter containing command. */
- CONST char *oldName; /* Name of command being changed. */
- CONST char *newName; /* New name of command. Empty string
- * or NULL means command is being deleted
- * (renamed to ""). */
- int flags; /* OR-ed bits giving operation and other
- * information. */
+static int
+StringUpperCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- Interp *iPtr = (Interp *) interp;
- int stateCode;
- Tcl_SavedResult state;
- TraceCommandInfo *tcmdPtr = (TraceCommandInfo *) clientData;
- int code;
- Tcl_DString cmd;
-
- tcmdPtr->refCount++;
-
- if ((tcmdPtr->flags & flags) && !Tcl_InterpDeleted(interp)) {
- /*
- * Generate a command to execute by appending list elements
- * for the old and new command name and the operation.
- */
+ int length1, length2;
+ char *string1, *string2;
- Tcl_DStringInit(&cmd);
- Tcl_DStringAppend(&cmd, tcmdPtr->command, (int) tcmdPtr->length);
- Tcl_DStringAppendElement(&cmd, oldName);
- Tcl_DStringAppendElement(&cmd, (newName ? newName : ""));
- if (flags & TCL_TRACE_RENAME) {
- Tcl_DStringAppend(&cmd, " rename", 7);
- } else if (flags & TCL_TRACE_DELETE) {
- Tcl_DStringAppend(&cmd, " delete", 7);
- }
+ if (objc < 2 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "string ?first? ?last?");
+ return TCL_ERROR;
+ }
- /*
- * Execute the command. Save the interp's result used for the
- * command, including the value of iPtr->returnCode which may be
- * modified when Tcl_Eval is invoked. We discard any object
- * result the command returns.
- *
- * Add the TCL_TRACE_DESTROYED flag to tcmdPtr to indicate to
- * other areas that this will be destroyed by us, otherwise a
- * double-free might occur depending on what the eval does.
- */
+ string1 = TclGetStringFromObj(objv[1], &length1);
- Tcl_SaveResult(interp, &state);
- stateCode = iPtr->returnCode;
- if (flags & TCL_TRACE_DESTROYED) {
- tcmdPtr->flags |= TCL_TRACE_DESTROYED;
+ if (objc == 2) {
+ Tcl_Obj *resultPtr = Tcl_NewStringObj(string1, length1);
+
+ length1 = Tcl_UtfToUpper(TclGetString(resultPtr));
+ Tcl_SetObjLength(resultPtr, length1);
+ Tcl_SetObjResult(interp, resultPtr);
+ } else {
+ int first, last;
+ const char *start, *end;
+ Tcl_Obj *resultPtr;
+
+ length1 = Tcl_NumUtfChars(string1, length1) - 1;
+ if (TclGetIntForIndexM(interp,objv[2],length1, &first) != TCL_OK) {
+ return TCL_ERROR;
}
+ if (first < 0) {
+ first = 0;
+ }
+ last = first;
- code = Tcl_EvalEx(interp, Tcl_DStringValue(&cmd),
- Tcl_DStringLength(&cmd), 0);
- if (code != TCL_OK) {
- /* We ignore errors in these traced commands */
+ if ((objc == 4) && (TclGetIntForIndexM(interp, objv[3], length1,
+ &last) != TCL_OK)) {
+ return TCL_ERROR;
}
- Tcl_RestoreResult(interp, &state);
- iPtr->returnCode = stateCode;
-
- Tcl_DStringFree(&cmd);
+ if (last >= length1) {
+ last = length1;
+ }
+ if (last < first) {
+ Tcl_SetObjResult(interp, objv[1]);
+ return TCL_OK;
+ }
+
+ string1 = TclGetStringFromObj(objv[1], &length1);
+ start = Tcl_UtfAtIndex(string1, first);
+ end = Tcl_UtfAtIndex(start, last - first + 1);
+ resultPtr = Tcl_NewStringObj(string1, end - string1);
+ string2 = TclGetString(resultPtr) + (start - string1);
+
+ length2 = Tcl_UtfToUpper(string2);
+ Tcl_SetObjLength(resultPtr, length2 + (start - string1));
+
+ Tcl_AppendToObj(resultPtr, end, -1);
+ Tcl_SetObjResult(interp, resultPtr);
}
- /*
- * We delete when the trace was destroyed or if this is a delete trace,
- * because command deletes are unconditional, so the trace must go away.
- */
- if (flags & (TCL_TRACE_DESTROYED | TCL_TRACE_DELETE)) {
- int untraceFlags = tcmdPtr->flags;
-
- if (tcmdPtr->stepTrace != NULL) {
- Tcl_DeleteTrace(interp, tcmdPtr->stepTrace);
- tcmdPtr->stepTrace = NULL;
- if (tcmdPtr->startCmd != NULL) {
- ckfree((char *)tcmdPtr->startCmd);
- }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringTitleCmd --
+ *
+ * This procedure is invoked to process the "string totitle" Tcl command.
+ * See the user documentation for details on what it does. Note that this
+ * command only functions correctly on properly formed Tcl UTF strings.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+StringTitleCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int length1, length2;
+ char *string1, *string2;
+
+ if (objc < 2 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "string ?first? ?last?");
+ return TCL_ERROR;
+ }
+
+ string1 = TclGetStringFromObj(objv[1], &length1);
+
+ if (objc == 2) {
+ Tcl_Obj *resultPtr = Tcl_NewStringObj(string1, length1);
+
+ length1 = Tcl_UtfToTitle(TclGetString(resultPtr));
+ Tcl_SetObjLength(resultPtr, length1);
+ Tcl_SetObjResult(interp, resultPtr);
+ } else {
+ int first, last;
+ const char *start, *end;
+ Tcl_Obj *resultPtr;
+
+ length1 = Tcl_NumUtfChars(string1, length1) - 1;
+ if (TclGetIntForIndexM(interp,objv[2],length1, &first) != TCL_OK) {
+ return TCL_ERROR;
}
- if (tcmdPtr->flags & TCL_TRACE_EXEC_IN_PROGRESS) {
- /* Postpone deletion, until exec trace returns */
- tcmdPtr->flags = 0;
+ if (first < 0) {
+ first = 0;
}
+ last = first;
- /*
- * We need to construct the same flags for Tcl_UntraceCommand
- * as were passed to Tcl_TraceCommand. Reproduce the processing
- * of [trace add execution/command]. Be careful to keep this
- * code in sync with that.
- */
+ if ((objc == 4) && (TclGetIntForIndexM(interp, objv[3], length1,
+ &last) != TCL_OK)) {
+ return TCL_ERROR;
+ }
- if (untraceFlags & TCL_TRACE_ANY_EXEC) {
- untraceFlags |= TCL_TRACE_DELETE;
- if (untraceFlags & (TCL_TRACE_ENTER_DURING_EXEC
- | TCL_TRACE_LEAVE_DURING_EXEC)) {
- untraceFlags |= (TCL_TRACE_ENTER_EXEC | TCL_TRACE_LEAVE_EXEC);
- }
- } else if (untraceFlags & TCL_TRACE_RENAME) {
- untraceFlags |= TCL_TRACE_DELETE;
+ if (last >= length1) {
+ last = length1;
+ }
+ if (last < first) {
+ Tcl_SetObjResult(interp, objv[1]);
+ return TCL_OK;
}
- /*
- * Remove the trace since TCL_TRACE_DESTROYED tells us to, or the
- * command we're tracing has just gone away. Then decrement the
- * clientData refCount that was set up by trace creation.
- *
- * Note that we save the (return) state of the interpreter to prevent
- * bizarre error messages.
- */
+ string1 = TclGetStringFromObj(objv[1], &length1);
+ start = Tcl_UtfAtIndex(string1, first);
+ end = Tcl_UtfAtIndex(start, last - first + 1);
+ resultPtr = Tcl_NewStringObj(string1, end - string1);
+ string2 = TclGetString(resultPtr) + (start - string1);
- Tcl_SaveResult(interp, &state);
- stateCode = iPtr->returnCode;
- Tcl_UntraceCommand(interp, oldName, untraceFlags,
- TraceCommandProc, clientData);
- Tcl_RestoreResult(interp, &state);
- iPtr->returnCode = stateCode;
+ length2 = Tcl_UtfToTitle(string2);
+ Tcl_SetObjLength(resultPtr, length2 + (start - string1));
- tcmdPtr->refCount--;
- }
- tcmdPtr->refCount--;
- if (tcmdPtr->refCount < 0) {
- Tcl_Panic("TraceCommandProc: negative TraceCommandInfo refCount");
- }
- if (tcmdPtr->refCount == 0) {
- ckfree((char*)tcmdPtr);
+ Tcl_AppendToObj(resultPtr, end, -1);
+ Tcl_SetObjResult(interp, resultPtr);
}
- return;
+
+ return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * TclCheckExecutionTraces --
+ * StringTrimCmd --
*
- * Checks on all current command execution traces, and invokes
- * procedures which have been registered. This procedure can be
- * used by other code which performs execution to unify the
- * tracing system, so that execution traces will function for that
- * other code.
- *
- * For instance extensions like [incr Tcl] which use their
- * own execution technique can make use of Tcl's tracing.
- *
- * This procedure is called by 'TclEvalObjvInternal'
+ * This procedure is invoked to process the "string trim" Tcl command.
+ * See the user documentation for details on what it does. Note that this
+ * command only functions correctly on properly formed Tcl UTF strings.
*
* Results:
- * The return value is a standard Tcl completion code such as
- * TCL_OK or TCL_ERROR, etc.
+ * A standard Tcl result.
*
* Side effects:
- * Those side effects made by any trace procedures called.
+ * See the user documentation.
*
*----------------------------------------------------------------------
*/
-int
-TclCheckExecutionTraces(interp, command, numChars, cmdPtr, code,
- traceFlags, objc, objv)
- Tcl_Interp *interp; /* The current interpreter. */
- CONST char *command; /* Pointer to beginning of the current
- * command string. */
- int numChars; /* The number of characters in 'command'
- * which are part of the command string. */
- Command *cmdPtr; /* Points to command's Command struct. */
- int code; /* The current result code. */
- int traceFlags; /* Current tracing situation. */
- int objc; /* Number of arguments for the command. */
- Tcl_Obj *CONST objv[]; /* Pointers to Tcl_Obj of each argument. */
+
+static int
+StringTrimCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- Interp *iPtr = (Interp *) interp;
- CommandTrace *tracePtr, *lastTracePtr;
- ActiveCommandTrace active;
- int curLevel;
- int traceCode = TCL_OK;
- TraceCommandInfo* tcmdPtr;
-
- if (command == NULL || cmdPtr->tracePtr == NULL) {
- return traceCode;
- }
-
- curLevel = ((iPtr->varFramePtr == NULL) ? 0 : iPtr->varFramePtr->level);
-
- active.nextPtr = iPtr->activeCmdTracePtr;
- iPtr->activeCmdTracePtr = &active;
-
- active.cmdPtr = cmdPtr;
- lastTracePtr = NULL;
- for (tracePtr = cmdPtr->tracePtr;
- (traceCode == TCL_OK) && (tracePtr != NULL);
- tracePtr = active.nextTracePtr) {
- if (traceFlags & TCL_TRACE_LEAVE_EXEC) {
- /* execute the trace command in order of creation for "leave" */
- active.reverseScan = 1;
- active.nextTracePtr = NULL;
- tracePtr = cmdPtr->tracePtr;
- while (tracePtr->nextPtr != lastTracePtr) {
- active.nextTracePtr = tracePtr;
- tracePtr = tracePtr->nextPtr;
- }
- } else {
- active.reverseScan = 0;
- active.nextTracePtr = tracePtr->nextPtr;
- }
- if (tracePtr->traceProc == TraceCommandProc) {
- tcmdPtr = (TraceCommandInfo*)tracePtr->clientData;
- if (tcmdPtr->flags != 0) {
- tcmdPtr->curFlags = traceFlags | TCL_TRACE_EXEC_DIRECT;
- tcmdPtr->curCode = code;
- tcmdPtr->refCount++;
- traceCode = TraceExecutionProc((ClientData)tcmdPtr, interp,
- curLevel, command, (Tcl_Command)cmdPtr, objc, objv);
- tcmdPtr->refCount--;
- if (tcmdPtr->refCount < 0) {
- Tcl_Panic("TclCheckExecutionTraces: negative TraceCommandInfo refCount");
- }
- if (tcmdPtr->refCount == 0) {
- ckfree((char*)tcmdPtr);
- }
- }
- }
- if (active.nextTracePtr) {
- lastTracePtr = active.nextTracePtr->nextPtr;
- }
+ const char *string1, *string2;
+ int triml, trimr, length1, length2;
+
+ if (objc == 3) {
+ string2 = TclGetStringFromObj(objv[2], &length2);
+ } else if (objc == 2) {
+ string2 = " \t\n\r";
+ length2 = strlen(string2);
+ } else {
+ Tcl_WrongNumArgs(interp, 1, objv, "string ?chars?");
+ return TCL_ERROR;
}
- iPtr->activeCmdTracePtr = active.nextPtr;
- return(traceCode);
+ string1 = TclGetStringFromObj(objv[1], &length1);
+
+ triml = TclTrimLeft(string1, length1, string2, length2);
+ trimr = TclTrimRight(string1 + triml, length1 - triml, string2, length2);
+
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj(string1 + triml, length1 - triml - trimr));
+ return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * TclCheckInterpTraces --
+ * StringTrimLCmd --
*
- * Checks on all current traces, and invokes procedures which
- * have been registered. This procedure can be used by other
- * code which performs execution to unify the tracing system.
- * For instance extensions like [incr Tcl] which use their
- * own execution technique can make use of Tcl's tracing.
- *
- * This procedure is called by 'TclEvalObjvInternal'
+ * This procedure is invoked to process the "string trimleft" Tcl
+ * command. See the user documentation for details on what it does. Note
+ * that this command only functions correctly on properly formed Tcl UTF
+ * strings.
*
* Results:
- * The return value is a standard Tcl completion code such as
- * TCL_OK or TCL_ERROR, etc.
+ * A standard Tcl result.
*
* Side effects:
- * Those side effects made by any trace procedures called.
+ * See the user documentation.
*
*----------------------------------------------------------------------
*/
-int
-TclCheckInterpTraces(interp, command, numChars, cmdPtr, code,
- traceFlags, objc, objv)
- Tcl_Interp *interp; /* The current interpreter. */
- CONST char *command; /* Pointer to beginning of the current
- * command string. */
- int numChars; /* The number of characters in 'command'
- * which are part of the command string. */
- Command *cmdPtr; /* Points to command's Command struct. */
- int code; /* The current result code. */
- int traceFlags; /* Current tracing situation. */
- int objc; /* Number of arguments for the command. */
- Tcl_Obj *CONST objv[]; /* Pointers to Tcl_Obj of each argument. */
+
+static int
+StringTrimLCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- Interp *iPtr = (Interp *) interp;
- Trace *tracePtr, *lastTracePtr;
- ActiveInterpTrace active;
- int curLevel;
- int traceCode = TCL_OK;
-
- if (command == NULL || iPtr->tracePtr == NULL ||
- (iPtr->flags & INTERP_TRACE_IN_PROGRESS)) {
- return(traceCode);
- }
-
- curLevel = iPtr->numLevels;
-
- active.nextPtr = iPtr->activeInterpTracePtr;
- iPtr->activeInterpTracePtr = &active;
-
- lastTracePtr = NULL;
- for ( tracePtr = iPtr->tracePtr;
- (traceCode == TCL_OK) && (tracePtr != NULL);
- tracePtr = active.nextTracePtr) {
- if (traceFlags & TCL_TRACE_ENTER_EXEC) {
- /*
- * Execute the trace command in reverse order of creation
- * for "enterstep" operation. The order is changed for
- * "enterstep" instead of for "leavestep" as was done in
- * TclCheckExecutionTraces because for step traces,
- * Tcl_CreateObjTrace creates one more linked list of traces
- * which results in one more reversal of trace invocation.
- */
- active.reverseScan = 1;
- active.nextTracePtr = NULL;
- tracePtr = iPtr->tracePtr;
- while (tracePtr->nextPtr != lastTracePtr) {
- active.nextTracePtr = tracePtr;
- tracePtr = tracePtr->nextPtr;
- }
- if (active.nextTracePtr) {
- lastTracePtr = active.nextTracePtr->nextPtr;
- }
- } else {
- active.reverseScan = 0;
- active.nextTracePtr = tracePtr->nextPtr;
- }
- if (tracePtr->level > 0 && curLevel > tracePtr->level) {
- continue;
- }
- if (!(tracePtr->flags & TCL_TRACE_EXEC_IN_PROGRESS)) {
- /*
- * The proc invoked might delete the traced command which
- * which might try to free tracePtr. We want to use tracePtr
- * until the end of this if section, so we use
- * Tcl_Preserve() and Tcl_Release() to be sure it is not
- * freed while we still need it.
- */
- Tcl_Preserve((ClientData) tracePtr);
- tracePtr->flags |= TCL_TRACE_EXEC_IN_PROGRESS;
-
- if (tracePtr->flags & (TCL_TRACE_ENTER_EXEC | TCL_TRACE_LEAVE_EXEC)) {
- /* New style trace */
- if (tracePtr->flags & traceFlags) {
- if (tracePtr->proc == TraceExecutionProc) {
- TraceCommandInfo *tcmdPtr =
- (TraceCommandInfo *) tracePtr->clientData;
- tcmdPtr->curFlags = traceFlags;
- tcmdPtr->curCode = code;
- }
- traceCode = (tracePtr->proc)(tracePtr->clientData,
- interp, curLevel, command, (Tcl_Command)cmdPtr,
- objc, objv);
- }
- } else {
- /* Old-style trace */
-
- if (traceFlags & TCL_TRACE_ENTER_EXEC) {
- /*
- * Old-style interpreter-wide traces only trigger
- * before the command is executed.
- */
- traceCode = CallTraceProcedure(interp, tracePtr, cmdPtr,
- command, numChars, objc, objv);
- }
- }
- tracePtr->flags &= ~TCL_TRACE_EXEC_IN_PROGRESS;
- Tcl_Release((ClientData) tracePtr);
- }
+ const char *string1, *string2;
+ int trim, length1, length2;
+
+ if (objc == 3) {
+ string2 = TclGetStringFromObj(objv[2], &length2);
+ } else if (objc == 2) {
+ string2 = " \t\n\r";
+ length2 = strlen(string2);
+ } else {
+ Tcl_WrongNumArgs(interp, 1, objv, "string ?chars?");
+ return TCL_ERROR;
}
- iPtr->activeInterpTracePtr = active.nextPtr;
- return(traceCode);
+ string1 = TclGetStringFromObj(objv[1], &length1);
+
+ trim = TclTrimLeft(string1, length1, string2, length2);
+
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(string1+trim, length1-trim));
+ return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * CallTraceProcedure --
+ * StringTrimRCmd --
*
- * Invokes a trace procedure registered with an interpreter. These
- * procedures trace command execution. Currently this trace procedure
- * is called with the address of the string-based Tcl_CmdProc for the
- * command, not the Tcl_ObjCmdProc.
+ * This procedure is invoked to process the "string trimright" Tcl
+ * command. See the user documentation for details on what it does. Note
+ * that this command only functions correctly on properly formed Tcl UTF
+ * strings.
*
* Results:
- * None.
+ * A standard Tcl result.
*
* Side effects:
- * Those side effects made by the trace procedure.
+ * See the user documentation.
*
*----------------------------------------------------------------------
*/
static int
-CallTraceProcedure(interp, tracePtr, cmdPtr, command, numChars, objc, objv)
- Tcl_Interp *interp; /* The current interpreter. */
- register Trace *tracePtr; /* Describes the trace procedure to call. */
- Command *cmdPtr; /* Points to command's Command struct. */
- CONST char *command; /* Points to the first character of the
- * command's source before substitutions. */
- int numChars; /* The number of characters in the
- * command's source. */
- register int objc; /* Number of arguments for the command. */
- Tcl_Obj *CONST objv[]; /* Pointers to Tcl_Obj of each argument. */
+StringTrimRCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- Interp *iPtr = (Interp *) interp;
- char *commandCopy;
- int traceCode;
+ const char *string1, *string2;
+ int trim, length1, length2;
+
+ if (objc == 3) {
+ string2 = TclGetStringFromObj(objv[2], &length2);
+ } else if (objc == 2) {
+ string2 = " \t\n\r";
+ length2 = strlen(string2);
+ } else {
+ Tcl_WrongNumArgs(interp, 1, objv, "string ?chars?");
+ return TCL_ERROR;
+ }
+ string1 = TclGetStringFromObj(objv[1], &length1);
- /*
- * Copy the command characters into a new string.
- */
+ trim = TclTrimRight(string1, length1, string2, length2);
- commandCopy = (char *) ckalloc((unsigned) (numChars + 1));
- memcpy((VOID *) commandCopy, (VOID *) command, (size_t) numChars);
- commandCopy[numChars] = '\0';
-
- /*
- * Call the trace procedure then free allocated storage.
- */
-
- traceCode = (tracePtr->proc)( tracePtr->clientData, (Tcl_Interp*) iPtr,
- iPtr->numLevels, commandCopy,
- (Tcl_Command) cmdPtr, objc, objv );
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(string1, length1-trim));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclInitStringCmd --
+ *
+ * This procedure creates the "string" Tcl command. See the user
+ * documentation for details on what it does. Note that this command only
+ * functions correctly on properly formed Tcl UTF strings.
+ *
+ * Also note that the primary methods here (equal, compare, match, ...)
+ * have bytecode equivalents. You will find the code for those in
+ * tclExecute.c. The code here will only be used in the non-bc case (like
+ * in an 'eval').
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
- ckfree((char *) commandCopy);
- return(traceCode);
+Tcl_Command
+TclInitStringCmd(
+ Tcl_Interp *interp) /* Current interpreter. */
+{
+ static const EnsembleImplMap stringImplMap[] = {
+ {"bytelength", StringBytesCmd, NULL},
+ {"compare", StringCmpCmd, TclCompileStringCmpCmd},
+ {"equal", StringEqualCmd, TclCompileStringEqualCmd},
+ {"first", StringFirstCmd, NULL},
+ {"index", StringIndexCmd, TclCompileStringIndexCmd},
+ {"is", StringIsCmd, NULL},
+ {"last", StringLastCmd, NULL},
+ {"length", StringLenCmd, TclCompileStringLenCmd},
+ {"map", StringMapCmd, NULL},
+ {"match", StringMatchCmd, TclCompileStringMatchCmd},
+ {"range", StringRangeCmd, NULL},
+ {"repeat", StringReptCmd, NULL},
+ {"replace", StringRplcCmd, NULL},
+ {"reverse", StringRevCmd, NULL},
+ {"tolower", StringLowerCmd, NULL},
+ {"toupper", StringUpperCmd, NULL},
+ {"totitle", StringTitleCmd, NULL},
+ {"trim", StringTrimCmd, NULL},
+ {"trimleft", StringTrimLCmd, NULL},
+ {"trimright", StringTrimRCmd, NULL},
+ {"wordend", StringEndCmd, NULL},
+ {"wordstart", StringStartCmd, NULL},
+ {NULL}
+ };
+
+ return TclMakeEnsemble(interp, "string", stringImplMap);
}
/*
*----------------------------------------------------------------------
*
- * CommandObjTraceDeleted --
+ * Tcl_SubstObjCmd --
*
- * Ensure the trace is correctly deleted by decrementing its
- * refCount and only deleting if no other references exist.
+ * This procedure is invoked to process the "subst" Tcl command. See the
+ * user documentation for details on what it does. This command relies on
+ * Tcl_SubstObj() for its implementation.
*
* Results:
- * None.
+ * A standard Tcl result.
*
* Side effects:
- * May release memory.
+ * See the user documentation.
*
*----------------------------------------------------------------------
*/
-static void
-CommandObjTraceDeleted(ClientData clientData) {
- TraceCommandInfo* tcmdPtr = (TraceCommandInfo*)clientData;
- tcmdPtr->refCount--;
- if (tcmdPtr->refCount < 0) {
- Tcl_Panic("CommandObjTraceDeleted: negative TraceCommandInfo refCount");
+
+int
+Tcl_SubstObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
+{
+ static CONST char *substOptions[] = {
+ "-nobackslashes", "-nocommands", "-novariables", NULL
+ };
+ enum substOptions {
+ SUBST_NOBACKSLASHES, SUBST_NOCOMMANDS, SUBST_NOVARS
+ };
+ Tcl_Obj *resultPtr;
+ int flags, i;
+
+ /*
+ * Parse command-line options.
+ */
+
+ flags = TCL_SUBST_ALL;
+ for (i = 1; i < (objc-1); i++) {
+ int optionIndex;
+
+ if (Tcl_GetIndexFromObj(interp, objv[i], substOptions, "switch", 0,
+ &optionIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch (optionIndex) {
+ case SUBST_NOBACKSLASHES:
+ flags &= ~TCL_SUBST_BACKSLASHES;
+ break;
+ case SUBST_NOCOMMANDS:
+ flags &= ~TCL_SUBST_COMMANDS;
+ break;
+ case SUBST_NOVARS:
+ flags &= ~TCL_SUBST_VARIABLES;
+ break;
+ default:
+ Tcl_Panic("Tcl_SubstObjCmd: bad option index to SubstOptions");
+ }
}
- if (tcmdPtr->refCount == 0) {
- ckfree((char*)tcmdPtr);
+ if (i != objc-1) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "?-nobackslashes? ?-nocommands? ?-novariables? string");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Perform the substitution.
+ */
+
+ resultPtr = Tcl_SubstObj(interp, objv[i], flags);
+
+ if (resultPtr == NULL) {
+ return TCL_ERROR;
}
+ Tcl_SetObjResult(interp, resultPtr);
+ return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * TraceExecutionProc --
+ * Tcl_SwitchObjCmd --
*
- * This procedure is invoked whenever code relevant to a
- * 'trace execution' command is executed. It is called in one
- * of two ways in Tcl's core:
- *
- * (i) by the TclCheckExecutionTraces, when an execution trace
- * has been triggered.
- * (ii) by TclCheckInterpTraces, when a prior execution trace has
- * created a trace of the internals of a procedure, passing in
- * this procedure as the one to be called.
+ * This object-based procedure is invoked to process the "switch" Tcl
+ * command. See the user documentation for details on what it does.
*
* Results:
- * The return value is a standard Tcl completion code such as
- * TCL_OK or TCL_ERROR, etc.
+ * A standard Tcl object result.
*
* Side effects:
- * May invoke an arbitrary Tcl procedure, and may create or
- * delete an interpreter-wide trace.
+ * See the user documentation.
*
*----------------------------------------------------------------------
*/
-static int
-TraceExecutionProc(ClientData clientData, Tcl_Interp *interp,
- int level, CONST char* command, Tcl_Command cmdInfo,
- int objc, struct Tcl_Obj *CONST objv[]) {
- int call = 0;
+
+int
+Tcl_SwitchObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
+{
+ int i,j, index, mode, foundmode, result, splitObjs, numMatchesSaved;
+ int noCase, patternLength;
+ char *pattern;
+ Tcl_Obj *stringObj, *indexVarObj, *matchVarObj;
+ Tcl_Obj *CONST *savedObjv = objv;
+ Tcl_RegExp regExpr = NULL;
Interp *iPtr = (Interp *) interp;
- TraceCommandInfo* tcmdPtr = (TraceCommandInfo*)clientData;
- int flags = tcmdPtr->curFlags;
- int code = tcmdPtr->curCode;
- int traceCode = TCL_OK;
-
- if (tcmdPtr->flags & TCL_TRACE_EXEC_IN_PROGRESS) {
- /*
- * Inside any kind of execution trace callback, we do
- * not allow any further execution trace callbacks to
- * be called for the same trace.
- */
- return traceCode;
+ int pc = 0;
+ int bidx = 0; /* Index of body argument. */
+ Tcl_Obj *blist = NULL; /* List obj which is the body */
+ CmdFrame *ctxPtr; /* Copy of the topmost cmdframe, to allow us
+ * to mess with the line information */
+
+ /*
+ * If you add options that make -e and -g not unique prefixes of -exact or
+ * -glob, you *must* fix TclCompileSwitchCmd's option parser as well.
+ */
+
+ static CONST char *options[] = {
+ "-exact", "-glob", "-indexvar", "-matchvar", "-nocase", "-regexp",
+ "--", NULL
+ };
+ enum options {
+ OPT_EXACT, OPT_GLOB, OPT_INDEXV, OPT_MATCHV, OPT_NOCASE, OPT_REGEXP,
+ OPT_LAST
+ };
+ typedef int (*strCmpFn_t)(const char *, const char *);
+ strCmpFn_t strCmpFn = strcmp;
+
+ mode = OPT_EXACT;
+ foundmode = 0;
+ indexVarObj = NULL;
+ matchVarObj = NULL;
+ numMatchesSaved = 0;
+ noCase = 0;
+ for (i = 1; i < objc-2; i++) {
+ if (TclGetString(objv[i])[0] != '-') {
+ break;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum options) index) {
+ /*
+ * General options.
+ */
+
+ case OPT_LAST:
+ i++;
+ goto finishedOptions;
+ case OPT_NOCASE:
+ strCmpFn = strcasecmp;
+ noCase = 1;
+ break;
+
+ /*
+ * Handle the different switch mode options.
+ */
+
+ default:
+ if (foundmode) {
+ /*
+ * Mode already set via -exact, -glob, or -regexp.
+ */
+
+ Tcl_AppendResult(interp, "bad option \"",
+ TclGetString(objv[i]), "\": ", options[mode],
+ " option already found", NULL);
+ return TCL_ERROR;
+ } else {
+ foundmode = 1;
+ mode = index;
+ break;
+ }
+
+ /*
+ * Check for TIP#75 options specifying the variables to write
+ * regexp information into.
+ */
+
+ case OPT_INDEXV:
+ i++;
+ if (i >= objc-2) {
+ Tcl_AppendResult(interp, "missing variable name argument to ",
+ "-indexvar", " option", NULL);
+ return TCL_ERROR;
+ }
+ indexVarObj = objv[i];
+ numMatchesSaved = -1;
+ break;
+ case OPT_MATCHV:
+ i++;
+ if (i >= objc-2) {
+ Tcl_AppendResult(interp, "missing variable name argument to ",
+ "-matchvar", " option", NULL);
+ return TCL_ERROR;
+ }
+ matchVarObj = objv[i];
+ numMatchesSaved = -1;
+ break;
+ }
}
-
- if (!Tcl_InterpDeleted(interp)) {
+
+ finishedOptions:
+ if (objc - i < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "?switches? string pattern body ... ?default body?");
+ return TCL_ERROR;
+ }
+ if (indexVarObj != NULL && mode != OPT_REGEXP) {
+ Tcl_AppendResult(interp,
+ "-indexvar option requires -regexp option", NULL);
+ return TCL_ERROR;
+ }
+ if (matchVarObj != NULL && mode != OPT_REGEXP) {
+ Tcl_AppendResult(interp,
+ "-matchvar option requires -regexp option", NULL);
+ return TCL_ERROR;
+ }
+
+ stringObj = objv[i];
+ objc -= i + 1;
+ objv += i + 1;
+ bidx = i + 1; /* First after the match string. */
+
+ /*
+ * If all of the pattern/command pairs are lumped into a single argument,
+ * split them out again.
+ *
+ * TIP #280: Determine the lines the words in the list start at, based on
+ * the same data for the list word itself. The cmdFramePtr line
+ * information is manipulated directly.
+ */
+
+ splitObjs = 0;
+ if (objc == 1) {
+ Tcl_Obj **listv;
+ blist = objv[0];
+
+ if (TclListObjGetElements(interp, objv[0], &objc, &listv) != TCL_OK){
+ return TCL_ERROR;
+ }
+
/*
- * Check whether the current call is going to eval arbitrary
- * Tcl code with a generated trace, or whether we are only
- * going to setup interpreter-wide traces to implement the
- * 'step' traces. This latter situation can happen if
- * we create a command trace without either before or after
- * operations, but with either of the step operations.
+ * Ensure that the list is non-empty.
*/
- if (flags & TCL_TRACE_EXEC_DIRECT) {
- call = flags & tcmdPtr->flags
- & (TCL_TRACE_ENTER_EXEC | TCL_TRACE_LEAVE_EXEC);
- } else {
- call = 1;
+
+ if (objc < 1) {
+ Tcl_WrongNumArgs(interp, 1, savedObjv,
+ "?switches? string {pattern body ... ?default body?}");
+ return TCL_ERROR;
}
+ objv = listv;
+ splitObjs = 1;
+ }
+
+ /*
+ * Complain if there is an odd number of words in the list of patterns and
+ * bodies.
+ */
+
+ if (objc % 2) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "extra switch pattern with no body", NULL);
+
/*
- * First, if we have returned back to the level at which we
- * created an interpreter trace for enterstep and/or leavestep
- * execution traces, we remove it here.
+ * Check if this can be due to a badly placed comment in the switch
+ * block.
+ *
+ * The following is an heuristic to detect the infamous "comment in
+ * switch" error: just check if a pattern begins with '#'.
*/
- if (flags & TCL_TRACE_LEAVE_EXEC) {
- if ((tcmdPtr->stepTrace != NULL) && (level == tcmdPtr->startLevel)
- && (strcmp(command, tcmdPtr->startCmd) == 0)) {
- Tcl_DeleteTrace(interp, tcmdPtr->stepTrace);
- tcmdPtr->stepTrace = NULL;
- if (tcmdPtr->startCmd != NULL) {
- ckfree((char *)tcmdPtr->startCmd);
- }
+
+ if (splitObjs) {
+ for (i=0 ; i<objc ; i+=2) {
+ if (TclGetString(objv[i])[0] == '#') {
+ Tcl_AppendResult(interp, ", this may be due to a "
+ "comment incorrectly placed outside of a "
+ "switch body - see the \"switch\" "
+ "documentation", NULL);
+ break;
+ }
}
}
-
+
+ return TCL_ERROR;
+ }
+
+ /*
+ * Complain if the last body is a continuation. Note that this check
+ * assumes that the list is non-empty!
+ */
+
+ if (strcmp(TclGetString(objv[objc-1]), "-") == 0) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "no body specified for pattern \"",
+ TclGetString(objv[objc-2]), "\"", NULL);
+ return TCL_ERROR;
+ }
+
+ for (i = 0; i < objc; i += 2) {
/*
- * Second, create the tcl callback, if required.
+ * See if the pattern matches the string.
*/
- if (call) {
- Tcl_SavedResult state;
- int stateCode, i, saveInterpFlags;
- Tcl_DString cmd;
- Tcl_DString sub;
-
- Tcl_DStringInit(&cmd);
- Tcl_DStringAppend(&cmd, tcmdPtr->command, (int)tcmdPtr->length);
- /* Append command with arguments */
- Tcl_DStringInit(&sub);
- for (i = 0; i < objc; i++) {
- char* str;
- int len;
- str = Tcl_GetStringFromObj(objv[i],&len);
- Tcl_DStringAppendElement(&sub, str);
- }
- Tcl_DStringAppendElement(&cmd, Tcl_DStringValue(&sub));
- Tcl_DStringFree(&sub);
- if (flags & TCL_TRACE_ENTER_EXEC) {
- /* Append trace operation */
- if (flags & TCL_TRACE_EXEC_DIRECT) {
- Tcl_DStringAppendElement(&cmd, "enter");
- } else {
- Tcl_DStringAppendElement(&cmd, "enterstep");
+ pattern = TclGetStringFromObj(objv[i], &patternLength);
+
+ if ((i == objc - 2) && (*pattern == 'd')
+ && (strcmp(pattern, "default") == 0)) {
+ Tcl_Obj *emptyObj = NULL;
+
+ /*
+ * If either indexVarObj or matchVarObj are non-NULL, we're in
+ * REGEXP mode but have reached the default clause anyway. TIP#75
+ * specifies that we set the variables to empty lists (== empty
+ * objects) in that case.
+ */
+
+ if (indexVarObj != NULL) {
+ TclNewObj(emptyObj);
+ if (Tcl_ObjSetVar2(interp, indexVarObj, NULL, emptyObj,
+ TCL_LEAVE_ERR_MSG) == NULL) {
+ return TCL_ERROR;
}
- } else if (flags & TCL_TRACE_LEAVE_EXEC) {
- Tcl_Obj* resultCode;
- char* resultCodeStr;
-
- /* Append result code */
- resultCode = Tcl_NewIntObj(code);
- resultCodeStr = Tcl_GetString(resultCode);
- Tcl_DStringAppendElement(&cmd, resultCodeStr);
- Tcl_DecrRefCount(resultCode);
-
- /* Append result string */
- Tcl_DStringAppendElement(&cmd, Tcl_GetStringResult(interp));
- /* Append trace operation */
- if (flags & TCL_TRACE_EXEC_DIRECT) {
- Tcl_DStringAppendElement(&cmd, "leave");
+ }
+ if (matchVarObj != NULL) {
+ if (emptyObj == NULL) {
+ TclNewObj(emptyObj);
+ }
+ if (Tcl_ObjSetVar2(interp, matchVarObj, NULL, emptyObj,
+ TCL_LEAVE_ERR_MSG) == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ goto matchFound;
+ } else {
+ switch (mode) {
+ case OPT_EXACT:
+ if (strCmpFn(TclGetString(stringObj), pattern) == 0) {
+ goto matchFound;
+ }
+ break;
+ case OPT_GLOB:
+ if (Tcl_StringCaseMatch(TclGetString(stringObj), pattern,
+ noCase)) {
+ goto matchFound;
+ }
+ break;
+ case OPT_REGEXP:
+ regExpr = Tcl_GetRegExpFromObj(interp, objv[i],
+ TCL_REG_ADVANCED | (noCase ? TCL_REG_NOCASE : 0));
+ if (regExpr == NULL) {
+ return TCL_ERROR;
} else {
- Tcl_DStringAppendElement(&cmd, "leavestep");
+ int matched = Tcl_RegExpExecObj(interp, regExpr,
+ stringObj, 0, numMatchesSaved, 0);
+
+ if (matched < 0) {
+ return TCL_ERROR;
+ } else if (matched) {
+ goto matchFoundRegexp;
+ }
}
- } else {
- panic("TraceExecutionProc: bad flag combination");
+ break;
}
-
- /*
- * Execute the command. Save the interp's result used for
- * the command, including the value of iPtr->returnCode which
- * may be modified when Tcl_Eval is invoked. We discard any
- * object result the command returns.
- */
+ }
+ }
+ return TCL_OK;
- Tcl_SaveResult(interp, &state);
- stateCode = iPtr->returnCode;
-
- saveInterpFlags = iPtr->flags;
- iPtr->flags |= INTERP_TRACE_IN_PROGRESS;
- tcmdPtr->flags |= TCL_TRACE_EXEC_IN_PROGRESS;
- tcmdPtr->refCount++;
- /*
- * This line can have quite arbitrary side-effects,
- * including deleting the trace, the command being
- * traced, or even the interpreter.
- */
- traceCode = Tcl_Eval(interp, Tcl_DStringValue(&cmd));
- tcmdPtr->flags &= ~TCL_TRACE_EXEC_IN_PROGRESS;
+ matchFoundRegexp:
+ /*
+ * We are operating in REGEXP mode and we need to store information about
+ * what we matched in some user-nominated arrays. So build the lists of
+ * values and indices to write here. [TIP#75]
+ */
- /*
- * Restore the interp tracing flag to prevent cmd traces
- * from affecting interp traces
- */
- iPtr->flags = saveInterpFlags;;
- if (tcmdPtr->flags == 0) {
- flags |= TCL_TRACE_DESTROYED;
+ if (numMatchesSaved) {
+ Tcl_RegExpInfo info;
+ Tcl_Obj *matchesObj, *indicesObj = NULL;
+
+ Tcl_RegExpGetInfo(regExpr, &info);
+ if (matchVarObj != NULL) {
+ TclNewObj(matchesObj);
+ } else {
+ matchesObj = NULL;
+ }
+ if (indexVarObj != NULL) {
+ TclNewObj(indicesObj);
+ }
+
+ for (j=0 ; j<=info.nsubs ; j++) {
+ if (indexVarObj != NULL) {
+ Tcl_Obj *rangeObjAry[2];
+
+ rangeObjAry[0] = Tcl_NewLongObj(info.matches[j].start);
+ rangeObjAry[1] = Tcl_NewLongObj(info.matches[j].end);
+
+ /*
+ * Never fails; the object is always clean at this point.
+ */
+
+ Tcl_ListObjAppendElement(NULL, indicesObj,
+ Tcl_NewListObj(2, rangeObjAry));
}
-
- if (traceCode == TCL_OK) {
- /* Restore result if trace execution was successful */
- Tcl_RestoreResult(interp, &state);
- iPtr->returnCode = stateCode;
- } else {
- Tcl_DiscardResult(&state);
+
+ if (matchVarObj != NULL) {
+ Tcl_Obj *substringObj;
+
+ substringObj = Tcl_GetRange(stringObj,
+ info.matches[j].start, info.matches[j].end-1);
+
+ /*
+ * Never fails; the object is always clean at this point.
+ */
+
+ Tcl_ListObjAppendElement(NULL, matchesObj, substringObj);
}
+ }
- Tcl_DStringFree(&cmd);
+ if (indexVarObj != NULL) {
+ if (Tcl_ObjSetVar2(interp, indexVarObj, NULL, indicesObj,
+ TCL_LEAVE_ERR_MSG) == NULL) {
+ /*
+ * Careful! Check to see if we have allocated the list of
+ * matched strings; if so (but there was an error assigning
+ * the indices list) we have a potential memory leak because
+ * the match list has not been written to a variable. Except
+ * that we'll clean that up right now.
+ */
+
+ if (matchesObj != NULL) {
+ Tcl_DecrRefCount(matchesObj);
+ }
+ return TCL_ERROR;
+ }
+ }
+ if (matchVarObj != NULL) {
+ if (Tcl_ObjSetVar2(interp, matchVarObj, NULL, matchesObj,
+ TCL_LEAVE_ERR_MSG) == NULL) {
+ /*
+ * Unlike above, if indicesObj is non-NULL at this point, it
+ * will have been written to a variable already and will hence
+ * not be leaked.
+ */
+
+ return TCL_ERROR;
+ }
}
-
+ }
+
+ /*
+ * We've got a match. Find a body to execute, skipping bodies that are
+ * "-".
+ */
+
+ matchFound:
+ ctxPtr = (CmdFrame *) TclStackAlloc(interp, sizeof(CmdFrame));
+ *ctxPtr = *iPtr->cmdFramePtr;
+
+ if (splitObjs) {
/*
- * Third, if there are any step execution traces for this proc,
- * we register an interpreter trace to invoke enterstep and/or
- * leavestep traces.
- * We also need to save the current stack level and the proc
- * string in startLevel and startCmd so that we can delete this
- * interpreter trace when it reaches the end of this proc.
+ * We have to perform the GetSrc and other type dependent handling of
+ * the frame here because we are munging with the line numbers,
+ * something the other commands like if, etc. are not doing. Them are
+ * fine with simply passing the CmdFrame through and having the
+ * special handling done in 'info frame', or the bc compiler
*/
- if ((flags & TCL_TRACE_ENTER_EXEC) && (tcmdPtr->stepTrace == NULL)
- && (tcmdPtr->flags & (TCL_TRACE_ENTER_DURING_EXEC |
- TCL_TRACE_LEAVE_DURING_EXEC))) {
- tcmdPtr->startLevel = level;
- tcmdPtr->startCmd =
- (char *) ckalloc((unsigned) (strlen(command) + 1));
- strcpy(tcmdPtr->startCmd, command);
- tcmdPtr->refCount++;
- tcmdPtr->stepTrace = Tcl_CreateObjTrace(interp, 0,
- (tcmdPtr->flags & TCL_TRACE_ANY_EXEC) >> 2,
- TraceExecutionProc, (ClientData)tcmdPtr,
- CommandObjTraceDeleted);
+
+ if (ctxPtr->type == TCL_LOCATION_BC) {
+ /*
+ * Type BC => ctxPtr->data.eval.path is not used.
+ * ctxPtr->data.tebc.codePtr is used instead.
+ */
+
+ TclGetSrcInfoForPc(ctxPtr);
+ pc = 1;
+
+ /*
+ * The line information in the cmdFrame is now a copy we do not
+ * own.
+ */
}
- }
- if (flags & TCL_TRACE_DESTROYED) {
- if (tcmdPtr->stepTrace != NULL) {
- Tcl_DeleteTrace(interp, tcmdPtr->stepTrace);
- tcmdPtr->stepTrace = NULL;
- if (tcmdPtr->startCmd != NULL) {
- ckfree((char *)tcmdPtr->startCmd);
+
+ if (ctxPtr->type == TCL_LOCATION_SOURCE && ctxPtr->line[bidx] >= 0) {
+ int bline = ctxPtr->line[bidx];
+
+ ctxPtr->line = (int *) ckalloc(objc * sizeof(int));
+ ctxPtr->nline = objc;
+ TclListLines(blist, bline, objc, ctxPtr->line, objv);
+ } else {
+ /*
+ * This is either a dynamic code word, when all elements are
+ * relative to themselves, or something else less expected and
+ * where we have no information. The result is the same in both
+ * cases; tell the code to come that it doesn't know where it is,
+ * which triggers reversion to the old behavior.
+ */
+
+ int k;
+
+ ctxPtr->line = (int *) ckalloc(objc * sizeof(int));
+ ctxPtr->nline = objc;
+ for (k=0; k < objc; k++) {
+ ctxPtr->line[k] = -1;
}
}
}
- if (call) {
- tcmdPtr->refCount--;
- if (tcmdPtr->refCount < 0) {
- Tcl_Panic("TraceExecutionProc: negative TraceCommandInfo refCount");
+
+ for (j = i + 1; ; j += 2) {
+ if (j >= objc) {
+ /*
+ * This shouldn't happen since we've checked that the last body is
+ * not a continuation...
+ */
+
+ Tcl_Panic("fall-out when searching for body to match pattern");
}
- if (tcmdPtr->refCount == 0) {
- ckfree((char*)tcmdPtr);
+ if (strcmp(TclGetString(objv[j]), "-") != 0) {
+ break;
}
}
- return traceCode;
+
+ /*
+ * TIP #280: Make invoking context available to switch branch.
+ */
+
+ result = TclEvalObjEx(interp, objv[j], 0, ctxPtr, splitObjs ? j : bidx+j);
+ if (splitObjs) {
+ ckfree((char *) ctxPtr->line);
+ if (pc && (ctxPtr->type == TCL_LOCATION_SOURCE)) {
+ /*
+ * Death of SrcInfo reference.
+ */
+
+ Tcl_DecrRefCount(ctxPtr->data.eval.path);
+ }
+ }
+
+ /*
+ * Generate an error message if necessary.
+ */
+
+ if (result == TCL_ERROR) {
+ int limit = 50;
+ int overflow = (patternLength > limit);
+
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (\"%.*s%s\" arm line %d)",
+ (overflow ? limit : patternLength), pattern,
+ (overflow ? "..." : ""), interp->errorLine));
+ }
+ TclStackFree(interp, ctxPtr);
+ return result;
}
/*
*----------------------------------------------------------------------
*
- * TraceVarProc --
+ * Tcl_TimeObjCmd --
*
- * This procedure is called to handle variable accesses that have
- * been traced using the "trace" command.
+ * This object-based procedure is invoked to process the "time" Tcl
+ * command. See the user documentation for details on what it does.
*
* Results:
- * Normally returns NULL. If the trace command returns an error,
- * then this procedure returns an error string.
+ * A standard Tcl object result.
*
* Side effects:
- * Depends on the command associated with the trace.
+ * See the user documentation.
*
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
-static char *
-TraceVarProc(clientData, interp, name1, name2, flags)
- ClientData clientData; /* Information about the variable trace. */
- Tcl_Interp *interp; /* Interpreter containing variable. */
- CONST char *name1; /* Name of variable or array. */
- CONST char *name2; /* Name of element within array; NULL means
- * scalar variable is being referenced. */
- int flags; /* OR-ed bits giving operation and other
- * information. */
+int
+Tcl_TimeObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
- Tcl_SavedResult state;
- TraceVarInfo *tvarPtr = (TraceVarInfo *) clientData;
- char *result;
- int code, destroy = 0;
- Tcl_DString cmd;
-
- /*
- * We might call Tcl_Eval() below, and that might evaluate [trace
- * vdelete] which might try to free tvarPtr. However we do not
- * need to protect anything here; it's done by our caller because
- * the TraceVarInfo is really part of a CompoundVarTrace. [Bug 1348775]
- */
+ register Tcl_Obj *objPtr;
+ Tcl_Obj *objs[4];
+ register int i, result;
+ int count;
+ double totalMicroSec;
+#ifndef TCL_WIDE_CLICKS
+ Tcl_Time start, stop;
+#else
+ Tcl_WideInt start, stop;
+#endif
- result = NULL;
- if ((tvarPtr->flags & flags) && !Tcl_InterpDeleted(interp)) {
- if (tvarPtr->length != (size_t) 0) {
- /*
- * Generate a command to execute by appending list elements
- * for the two variable names and the operation.
- */
+ if (objc == 2) {
+ count = 1;
+ } else if (objc == 3) {
+ result = TclGetIntFromObj(interp, objv[2], &count);
+ if (result != TCL_OK) {
+ return result;
+ }
+ } else {
+ Tcl_WrongNumArgs(interp, 1, objv, "command ?count?");
+ return TCL_ERROR;
+ }
- Tcl_DStringInit(&cmd);
- Tcl_DStringAppend(&cmd, tvarPtr->command, (int) tvarPtr->length);
- Tcl_DStringAppendElement(&cmd, name1);
- Tcl_DStringAppendElement(&cmd, (name2 ? name2 : ""));
-#ifndef TCL_REMOVE_OBSOLETE_TRACES
- if (tvarPtr->flags & TCL_TRACE_OLD_STYLE) {
- if (flags & TCL_TRACE_ARRAY) {
- Tcl_DStringAppend(&cmd, " a", 2);
- } else if (flags & TCL_TRACE_READS) {
- Tcl_DStringAppend(&cmd, " r", 2);
- } else if (flags & TCL_TRACE_WRITES) {
- Tcl_DStringAppend(&cmd, " w", 2);
- } else if (flags & TCL_TRACE_UNSETS) {
- Tcl_DStringAppend(&cmd, " u", 2);
- }
- } else {
+ objPtr = objv[1];
+ i = count;
+#ifndef TCL_WIDE_CLICKS
+ Tcl_GetTime(&start);
+#else
+ start = TclpGetWideClicks();
#endif
- if (flags & TCL_TRACE_ARRAY) {
- Tcl_DStringAppend(&cmd, " array", 6);
- } else if (flags & TCL_TRACE_READS) {
- Tcl_DStringAppend(&cmd, " read", 5);
- } else if (flags & TCL_TRACE_WRITES) {
- Tcl_DStringAppend(&cmd, " write", 6);
- } else if (flags & TCL_TRACE_UNSETS) {
- Tcl_DStringAppend(&cmd, " unset", 6);
- }
-#ifndef TCL_REMOVE_OBSOLETE_TRACES
- }
+ while (i-- > 0) {
+ result = Tcl_EvalObjEx(interp, objPtr, 0);
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
+#ifndef TCL_WIDE_CLICKS
+ Tcl_GetTime(&stop);
+ totalMicroSec = ((double) (stop.sec - start.sec)) * 1.0e6
+ + (stop.usec - start.usec);
+#else
+ stop = TclpGetWideClicks();
+ totalMicroSec = ((double) TclpWideClicksToNanoseconds(stop - start))/1.0e3;
#endif
-
- /*
- * Execute the command. Save the interp's result used for
- * the command. We discard any object result the command returns.
- *
- * Add the TCL_TRACE_DESTROYED flag to tvarPtr to indicate to
- * other areas that this will be destroyed by us, otherwise a
- * double-free might occur depending on what the eval does.
- */
- Tcl_SaveResult(interp, &state);
- if ((flags & TCL_TRACE_DESTROYED)
- && !(tvarPtr->flags & TCL_TRACE_DESTROYED)) {
- destroy = 1;
- tvarPtr->flags |= TCL_TRACE_DESTROYED;
- }
+ if (count <= 1) {
+ /*
+ * Use int obj since we know time is not fractional. [Bug 1202178]
+ */
- code = Tcl_EvalEx(interp, Tcl_DStringValue(&cmd),
- Tcl_DStringLength(&cmd), 0);
- if (code != TCL_OK) { /* copy error msg to result */
- register Tcl_Obj *errMsgObj = Tcl_GetObjResult(interp);
- Tcl_IncrRefCount(errMsgObj);
- result = (char *) errMsgObj;
- }
+ objs[0] = Tcl_NewIntObj((count <= 0) ? 0 : (int) totalMicroSec);
+ } else {
+ objs[0] = Tcl_NewDoubleObj(totalMicroSec/count);
+ }
- Tcl_RestoreResult(interp, &state);
+ /*
+ * Construct the result as a list because many programs have always parsed
+ * as such (extracting the first element, typically).
+ */
- Tcl_DStringFree(&cmd);
- }
- }
- if (destroy) {
- if (result != NULL) {
- register Tcl_Obj *errMsgObj = (Tcl_Obj *) result;
+ TclNewLiteralStringObj(objs[1], "microseconds");
+ TclNewLiteralStringObj(objs[2], "per");
+ TclNewLiteralStringObj(objs[3], "iteration");
+ Tcl_SetObjResult(interp, Tcl_NewListObj(4, objs));
- Tcl_DecrRefCount(errMsgObj);
- result = NULL;
- }
- }
- return result;
+ return TCL_OK;
}
/*
@@ -4917,108 +3934,115 @@ TraceVarProc(clientData, interp, name1, name2, flags)
*
* Tcl_WhileObjCmd --
*
- * This procedure is invoked to process the "while" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "while" Tcl command. See the
+ * user documentation for details on what it does.
*
- * With the bytecode compiler, this procedure is only called when
- * a command name is computed at runtime, and is "while" or the name
- * to which "while" was renamed: e.g., "set z while; $z {$i<100} {}"
+ * With the bytecode compiler, this procedure is only called when a
+ * command name is computed at runtime, and is "while" or the name to
+ * which "while" was renamed: e.g., "set z while; $z {$i<100} {}"
*
* Results:
- * A standard Tcl result.
+ * A standard Tcl result.
*
* Side effects:
- * See the user documentation.
+ * See the user documentation.
*
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
int
-Tcl_WhileObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_WhileObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
int result, value;
-#ifdef TCL_TIP280
- Interp* iPtr = (Interp*) interp;
-#endif
+ Interp *iPtr = (Interp *) interp;
if (objc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, "test command");
- return TCL_ERROR;
+ return TCL_ERROR;
}
while (1) {
- result = Tcl_ExprBooleanObj(interp, objv[1], &value);
- if (result != TCL_OK) {
- return result;
- }
- if (!value) {
- break;
- }
-#ifndef TCL_TIP280
- result = Tcl_EvalObjEx(interp, objv[2], 0);
-#else
- /* TIP #280. */
- result = TclEvalObjEx(interp, objv[2], 0, iPtr->cmdFramePtr,2);
-#endif
- if ((result != TCL_OK) && (result != TCL_CONTINUE)) {
- if (result == TCL_ERROR) {
- char msg[32 + TCL_INTEGER_SPACE];
+ result = Tcl_ExprBooleanObj(interp, objv[1], &value);
+ if (result != TCL_OK) {
+ return result;
+ }
+ if (!value) {
+ break;
+ }
- sprintf(msg, "\n (\"while\" body line %d)",
- interp->errorLine);
- Tcl_AddErrorInfo(interp, msg);
- }
- break;
- }
+ /* TIP #280. */
+ result = TclEvalObjEx(interp, objv[2], 0, iPtr->cmdFramePtr, 2);
+ if ((result != TCL_OK) && (result != TCL_CONTINUE)) {
+ if (result == TCL_ERROR) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (\"while\" body line %d)", interp->errorLine));
+ }
+ break;
+ }
}
if (result == TCL_BREAK) {
- result = TCL_OK;
+ result = TCL_OK;
}
if (result == TCL_OK) {
- Tcl_ResetResult(interp);
+ Tcl_ResetResult(interp);
}
return result;
}
-#ifdef TCL_TIP280
-static void
-ListLines(listObj, line, n, lines, elems)
- Tcl_Obj* listObj; /* Pointer to obj holding a string with list structure.
- * Assumed to be valid. Assumed to contain n elements.
- */
- int line; /* line the list as a whole starts on */
- int n; /* #elements in lines */
- int* lines; /* Array of line numbers, to fill */
- Tcl_Obj* const* elems; /* The list elems as Tcl_Obj*, in need of derived
- * continuation data */
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclListLines --
+ *
+ * ???
+ *
+ * Results:
+ * Filled in array of line numbers?
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclListLines(
+ Tcl_Obj* listObj, /* Pointer to obj holding a string with list
+ * structure. Assumed to be valid. Assumed to
+ * contain n elements.
+ */
+ int line, /* Line the list as a whole starts on. */
+ int n, /* #elements in lines */
+ int *lines, /* Array of line numbers, to fill. */
+ Tcl_Obj* const* elems) /* The list elems as Tcl_Obj*, in need of
+ * derived continuation data */
{
- int i;
CONST char* listStr = Tcl_GetString (listObj);
CONST char* listHead = listStr;
- int length = strlen( listStr);
- CONST char* element = NULL;
- CONST char* next = NULL;
+ int i, length = strlen(listStr);
+ CONST char *element = NULL, *next = NULL;
ContLineLoc* clLocPtr = TclContinuationsGet(listObj);
- int* clNext = (clLocPtr ? &clLocPtr->loc[0] : NULL);
+ int* clNext = (clLocPtr ? &clLocPtr->loc[0] : NULL);
for (i = 0; i < n; i++) {
TclFindElement(NULL, listStr, length, &element, &next, NULL, NULL);
- TclAdvanceLines (&line, listStr, element); /* Leading whitespace */
+ TclAdvanceLines(&line, listStr, element);
+ /* Leading whitespace */
TclAdvanceContinuations (&line, &clNext, element - listHead);
- if (clNext) {
- TclContinuationsEnterDerived (elems[i], element - listHead, clNext);
+ if (elems && clNext) {
+ TclContinuationsEnterDerived (elems[i], element - listHead,
+ clNext);
}
-
- lines [i] = line;
- length -= (next - listStr);
- TclAdvanceLines (&line, element, next); /* Element */
- listStr = next;
+ lines[i] = line;
+ length -= (next - listStr);
+ TclAdvanceLines(&line, element, next);
+ /* Element */
+ listStr = next;
if (*element == 0) {
/* ASSERT i == n */
@@ -5026,7 +4050,6 @@ ListLines(listObj, line, n, lines, elems)
}
}
}
-#endif
/*
* Local Variables:
@@ -5035,4 +4058,3 @@ ListLines(listObj, line, n, lines, elems)
* fill-column: 78
* End:
*/
-
diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c
index a39370e..f2d1bfb 100644
--- a/generic/tclCompCmds.c
+++ b/generic/tclCompCmds.c
@@ -1,54 +1,49 @@
-/*
+/*
* tclCompCmds.c --
*
- * This file contains compilation procedures that compile various
- * Tcl commands into a sequence of instructions ("bytecodes").
+ * This file contains compilation procedures that compile various Tcl
+ * commands into a sequence of instructions ("bytecodes").
*
* Copyright (c) 1997-1998 Sun Microsystems, Inc.
* Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
* Copyright (c) 2002 ActiveState Corporation.
+ * Copyright (c) 2004-2006 by Donal K. Fellows.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
#include "tclCompile.h"
/*
- * Prototypes for procedures defined later in this file:
+ * Macro that encapsulates an efficiency trick that avoids a function call for
+ * the simplest of compiles. The ANSI C "prototype" for this macro is:
+ *
+ * static void CompileWord(CompileEnv *envPtr, Tcl_Token *tokenPtr,
+ * Tcl_Interp *interp, int word);
*/
-static ClientData DupForeachInfo _ANSI_ARGS_((ClientData clientData));
-static void FreeForeachInfo _ANSI_ARGS_((ClientData clientData));
-#ifndef TCL_TIP280
-static int TclPushVarName _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Token *varTokenPtr, CompileEnv *envPtr, int flags,
- int *localIndexPtr, int *simpleVarNamePtr, int *isScalarPtr));
-
-#define TclPushVarNameWord(i,v,e,f,l,s,sc,word) \
- TclPushVarName (i,v,e,f,l,s,sc) /* ignoring word */
-
-#define DefineLineInformation /**/
-#define SetLineInformation(word) /**/
-#else
-static int TclPushVarName _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Token *varTokenPtr, CompileEnv *envPtr, int flags,
- int *localIndexPtr, int *simpleVarNamePtr, int *isScalarPtr,
- int line, int* clNext));
-
-#define TclPushVarNameWord(i,v,e,f,l,s,sc,word) \
- TclPushVarName (i,v,e,f,l,s,sc, \
- mapPtr->loc [eclIndex].line [(word)], \
- mapPtr->loc [eclIndex].next [(word)])
+#define CompileWord(envPtr, tokenPtr, interp, word) \
+ if ((tokenPtr)->type == TCL_TOKEN_SIMPLE_WORD) { \
+ TclEmitPush(TclRegisterNewLiteral((envPtr), (tokenPtr)[1].start, \
+ (tokenPtr)[1].size), (envPtr)); \
+ } else { \
+ envPtr->line = mapPtr->loc[eclIndex].line[word]; \
+ envPtr->clNext = mapPtr->loc[eclIndex].next[word]; \
+ TclCompileTokens((interp), (tokenPtr)+1, (tokenPtr)->numComponents, \
+ (envPtr)); \
+ }
-/* TIP #280 : Remember the per-word line information of the current
- * command. An index is used instead of a pointer as recursive compilation may
- * reallocate, i.e. move, the array. This is also the reason to save the nuloc
- * now, it may change during the course of the function.
+/*
+ * TIP #280: Remember the per-word line information of the current command. An
+ * index is used instead of a pointer as recursive compilation may reallocate,
+ * i.e. move, the array. This is also the reason to save the nuloc now, it may
+ * change during the course of the function.
*
- * Macros to encapsulate the variable definition and setup, and their use.
+ * Macro to encapsulate the variable definition and setup.
*/
+
#define DefineLineInformation \
ExtCmdLoc *mapPtr = envPtr->extCmdMapPtr; \
int eclIndex = mapPtr->nuloc - 1
@@ -56,23 +51,163 @@ static int TclPushVarName _ANSI_ARGS_((Tcl_Interp *interp,
#define SetLineInformation(word) \
envPtr->line = mapPtr->loc [eclIndex].line [(word)]; \
envPtr->clNext = mapPtr->loc [eclIndex].next [(word)]
-#endif
/*
- * Flags bits used by TclPushVarName.
+ * Convenience macro for use when compiling bodies of commands. The ANSI C
+ * "prototype" for this macro is:
+ *
+ * static void CompileBody(CompileEnv *envPtr, Tcl_Token *tokenPtr,
+ * Tcl_Interp *interp);
+ */
+
+#define CompileBody(envPtr, tokenPtr, interp) \
+ TclCompileCmdWord((interp), (tokenPtr)+1, (tokenPtr)->numComponents, \
+ (envPtr))
+
+/*
+ * Convenience macro for use when compiling tokens to be pushed. The ANSI C
+ * "prototype" for this macro is:
+ *
+ * static void CompileTokens(CompileEnv *envPtr, Tcl_Token *tokenPtr,
+ * Tcl_Interp *interp);
+ */
+
+#define CompileTokens(envPtr, tokenPtr, interp) \
+ TclCompileTokens((interp), (tokenPtr)+1, (tokenPtr)->numComponents, \
+ (envPtr));
+/*
+ * Convenience macro for use when pushing literals. The ANSI C "prototype" for
+ * this macro is:
+ *
+ * static void PushLiteral(CompileEnv *envPtr,
+ * const char *string, int length);
+ */
+
+#define PushLiteral(envPtr, string, length) \
+ TclEmitPush(TclRegisterNewLiteral((envPtr), (string), (length)), (envPtr))
+
+/*
+ * Macro to advance to the next token; it is more mnemonic than the address
+ * arithmetic that it replaces. The ANSI C "prototype" for this macro is:
+ *
+ * static Tcl_Token * TokenAfter(Tcl_Token *tokenPtr);
+ */
+
+#define TokenAfter(tokenPtr) \
+ ((tokenPtr) + ((tokenPtr)->numComponents + 1))
+
+/*
+ * Macro to get the offset to the next instruction to be issued. The ANSI C
+ * "prototype" for this macro is:
+ *
+ * static int CurrentOffset(CompileEnv *envPtr);
+ */
+
+#define CurrentOffset(envPtr) \
+ ((envPtr)->codeNext - (envPtr)->codeStart)
+
+/*
+ * Note: the exceptDepth is a bit of a misnomer: TEBC only needs the
+ * maximal depth of nested CATCH ranges in order to alloc runtime
+ * memory. These macros should compute precisely that? OTOH, the nesting depth
+ * of LOOP ranges is an interesting datum for debugging purposes, and that is
+ * what we compute now.
+ *
+ * static int DeclareExceptionRange(CompileEnv *envPtr, int type);
+ * static int ExceptionRangeStarts(CompileEnv *envPtr, int index);
+ * static void ExceptionRangeEnds(CompileEnv *envPtr, int index);
+ * static void ExceptionRangeTarget(CompileEnv *envPtr, int index, LABEL);
+ */
+
+#define DeclareExceptionRange(envPtr, type) \
+ (TclCreateExceptRange((type), (envPtr)))
+#define ExceptionRangeStarts(envPtr, index) \
+ (((envPtr)->exceptDepth++), \
+ ((envPtr)->maxExceptDepth = \
+ TclMax((envPtr)->exceptDepth, (envPtr)->maxExceptDepth)), \
+ ((envPtr)->exceptArrayPtr[(index)].codeOffset = CurrentOffset(envPtr)))
+#define ExceptionRangeEnds(envPtr, index) \
+ (((envPtr)->exceptDepth--), \
+ ((envPtr)->exceptArrayPtr[(index)].numCodeBytes = \
+ CurrentOffset(envPtr) - (envPtr)->exceptArrayPtr[(index)].codeOffset))
+#define ExceptionRangeTarget(envPtr, index, targetType) \
+ ((envPtr)->exceptArrayPtr[(index)].targetType = CurrentOffset(envPtr))
+
+/*
+ * Prototypes for procedures defined later in this file:
*/
-#define TCL_CREATE_VAR 1 /* Create a compiled local if none is found */
-#define TCL_NO_LARGE_INDEX 2 /* Do not return localIndex value > 255 */
+static ClientData DupDictUpdateInfo(ClientData clientData);
+static void FreeDictUpdateInfo(ClientData clientData);
+static void PrintDictUpdateInfo(ClientData clientData,
+ Tcl_Obj *appendObj, ByteCode *codePtr,
+ unsigned int pcOffset);
+static ClientData DupForeachInfo(ClientData clientData);
+static void FreeForeachInfo(ClientData clientData);
+static void PrintForeachInfo(ClientData clientData,
+ Tcl_Obj *appendObj, ByteCode *codePtr,
+ unsigned int pcOffset);
+static ClientData DupJumptableInfo(ClientData clientData);
+static void FreeJumptableInfo(ClientData clientData);
+static void PrintJumptableInfo(ClientData clientData,
+ Tcl_Obj *appendObj, ByteCode *codePtr,
+ unsigned int pcOffset);
+static int PushVarName(Tcl_Interp *interp,
+ Tcl_Token *varTokenPtr, CompileEnv *envPtr,
+ int flags, int *localIndexPtr,
+ int *simpleVarNamePtr, int *isScalarPtr,
+ int line, int* clNext);
+static int CompileAssociativeBinaryOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, const char *identity,
+ int instruction, CompileEnv *envPtr);
+static int CompileComparisonOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, int instruction,
+ CompileEnv *envPtr);
+static int CompileStrictlyBinaryOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, int instruction,
+ CompileEnv *envPtr);
+static int CompileUnaryOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, int instruction,
+ CompileEnv *envPtr);
+static void CompileReturnInternal(CompileEnv *envPtr,
+ unsigned char op, int code, int level,
+ Tcl_Obj *returnOpts);
+
+#define PushVarNameWord(i,v,e,f,l,s,sc,word) \
+ PushVarName (i,v,e,f,l,s,sc, \
+ mapPtr->loc [eclIndex].line [(word)], \
+ mapPtr->loc [eclIndex].next [(word)])
+
+/*
+ * Flags bits used by PushVarName.
+ */
+
+#define TCL_CREATE_VAR 1 /* Create a compiled local if none is found */
+#define TCL_NO_LARGE_INDEX 2 /* Do not return localIndex value > 255 */
/*
* The structures below define the AuxData types defined in this file.
*/
AuxDataType tclForeachInfoType = {
- "ForeachInfo", /* name */
- DupForeachInfo, /* dupProc */
- FreeForeachInfo /* freeProc */
+ "ForeachInfo", /* name */
+ DupForeachInfo, /* dupProc */
+ FreeForeachInfo, /* freeProc */
+ PrintForeachInfo /* printProc */
+};
+
+AuxDataType tclJumptableInfoType = {
+ "JumptableInfo", /* name */
+ DupJumptableInfo, /* dupProc */
+ FreeJumptableInfo, /* freeProc */
+ PrintJumptableInfo /* printProc */
+};
+
+AuxDataType tclDictUpdateInfoType = {
+ "DictUpdateInfo", /* name */
+ DupDictUpdateInfo, /* dupProc */
+ FreeDictUpdateInfo, /* freeProc */
+ PrintDictUpdateInfo /* printProc */
};
/*
@@ -83,89 +218,68 @@ AuxDataType tclForeachInfoType = {
* Procedure called to compile the "append" command.
*
* Results:
- * The return value is a standard Tcl result, which is normally TCL_OK
- * unless there was an error while parsing string. If an error occurs
- * then the interpreter's result contains a standard error message. If
- * compilation fails because the command requires a second level of
- * substitutions, TCL_OUT_LINE_COMPILE is returned indicating that the
- * command should be compiled "out of line" by emitting code to
- * invoke its command procedure (Tcl_AppendObjCmd) at runtime.
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
*
* Side effects:
- * Instructions are added to envPtr to execute the "append" command
- * at runtime.
+ * Instructions are added to envPtr to execute the "append" command at
+ * runtime.
*
*----------------------------------------------------------------------
*/
int
-TclCompileAppendCmd(interp, parsePtr, envPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Parse *parsePtr; /* Points to a parse structure for the
- * command created by Tcl_ParseCommand. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
+TclCompileAppendCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
{
Tcl_Token *varTokenPtr, *valueTokenPtr;
int simpleVarName, isScalar, localIndex, numWords;
- int code = TCL_OK;
-
- DefineLineInformation;
+ DefineLineInformation; /* TIP #280 */
numWords = parsePtr->numWords;
if (numWords == 1) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "wrong # args: should be \"append varName ?value value ...?\"",
- -1);
return TCL_ERROR;
} else if (numWords == 2) {
/*
- * append varName === set varName
+ * append varName == set varName
*/
- return TclCompileSetCmd(interp, parsePtr, envPtr);
+
+ return TclCompileSetCmd(interp, parsePtr, cmdPtr, envPtr);
} else if (numWords > 3) {
/*
- * APPEND instructions currently only handle one value
+ * APPEND instructions currently only handle one value.
*/
- return TCL_OUT_LINE_COMPILE;
+
+ return TCL_ERROR;
}
/*
- * Decide if we can use a frame slot for the var/array name or if we
- * need to emit code to compute and push the name at runtime. We use a
- * frame slot (entry in the array of local vars) if we are compiling a
- * procedure body and if the name is simple text that does not include
- * namespace qualifiers.
+ * Decide if we can use a frame slot for the var/array name or if we need
+ * to emit code to compute and push the name at runtime. We use a frame
+ * slot (entry in the array of local vars) if we are compiling a procedure
+ * body and if the name is simple text that does not include namespace
+ * qualifiers.
*/
- varTokenPtr = parsePtr->tokenPtr
- + (parsePtr->tokenPtr->numComponents + 1);
+ varTokenPtr = TokenAfter(parsePtr->tokenPtr);
- code = TclPushVarNameWord(interp, varTokenPtr, envPtr, TCL_CREATE_VAR,
- &localIndex, &simpleVarName, &isScalar, 1);
- if (code != TCL_OK) {
- goto done;
- }
+ PushVarNameWord(interp, varTokenPtr, envPtr, TCL_CREATE_VAR,
+ &localIndex, &simpleVarName, &isScalar, 1);
/*
- * We are doing an assignment, otherwise TclCompileSetCmd was called,
- * so push the new value. This will need to be extended to push a
- * value for each argument.
+ * We are doing an assignment, otherwise TclCompileSetCmd was called, so
+ * push the new value. This will need to be extended to push a value for
+ * each argument.
*/
if (numWords > 2) {
- valueTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
- if (valueTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
- TclEmitPush(TclRegisterNewLiteral(envPtr,
- valueTokenPtr[1].start, valueTokenPtr[1].size), envPtr);
- } else {
- SetLineInformation (2);
- code = TclCompileTokens(interp, valueTokenPtr+1,
- valueTokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- goto done;
- }
- }
+ valueTokenPtr = TokenAfter(varTokenPtr);
+ CompileWord(envPtr, valueTokenPtr, interp, 2);
}
/*
@@ -174,32 +288,27 @@ TclCompileAppendCmd(interp, parsePtr, envPtr)
if (simpleVarName) {
if (isScalar) {
- if (localIndex >= 0) {
- if (localIndex <= 255) {
- TclEmitInstInt1(INST_APPEND_SCALAR1, localIndex, envPtr);
- } else {
- TclEmitInstInt4(INST_APPEND_SCALAR4, localIndex, envPtr);
- }
- } else {
+ if (localIndex < 0) {
TclEmitOpcode(INST_APPEND_STK, envPtr);
+ } else if (localIndex <= 255) {
+ TclEmitInstInt1(INST_APPEND_SCALAR1, localIndex, envPtr);
+ } else {
+ TclEmitInstInt4(INST_APPEND_SCALAR4, localIndex, envPtr);
}
} else {
- if (localIndex >= 0) {
- if (localIndex <= 255) {
- TclEmitInstInt1(INST_APPEND_ARRAY1, localIndex, envPtr);
- } else {
- TclEmitInstInt4(INST_APPEND_ARRAY4, localIndex, envPtr);
- }
- } else {
+ if (localIndex < 0) {
TclEmitOpcode(INST_APPEND_ARRAY_STK, envPtr);
+ } else if (localIndex <= 255) {
+ TclEmitInstInt1(INST_APPEND_ARRAY1, localIndex, envPtr);
+ } else {
+ TclEmitInstInt4(INST_APPEND_ARRAY4, localIndex, envPtr);
}
}
} else {
TclEmitOpcode(INST_APPEND_STK, envPtr);
}
- done:
- return code;
+ return TCL_OK;
}
/*
@@ -210,28 +319,26 @@ TclCompileAppendCmd(interp, parsePtr, envPtr)
* Procedure called to compile the "break" command.
*
* Results:
- * The return value is a standard Tcl result, which is TCL_OK unless
- * there was an error during compilation. If an error occurs then
- * the interpreter's result contains a standard error message.
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
*
* Side effects:
- * Instructions are added to envPtr to execute the "break" command
- * at runtime.
+ * Instructions are added to envPtr to execute the "break" command at
+ * runtime.
*
*----------------------------------------------------------------------
*/
int
-TclCompileBreakCmd(interp, parsePtr, envPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Parse *parsePtr; /* Points to a parse structure for the
- * command created by Tcl_ParseCommand. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
+TclCompileBreakCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
{
if (parsePtr->numWords != 1) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "wrong # args: should be \"break\"", -1);
return TCL_ERROR;
}
@@ -251,172 +358,239 @@ TclCompileBreakCmd(interp, parsePtr, envPtr)
* Procedure called to compile the "catch" command.
*
* Results:
- * The return value is a standard Tcl result, which is TCL_OK if
- * compilation was successful. If an error occurs then the
- * interpreter's result contains a standard error message and TCL_ERROR
- * is returned. If the command is too complex for TclCompileCatchCmd,
- * TCL_OUT_LINE_COMPILE is returned indicating that the catch command
- * should be compiled "out of line" by emitting code to invoke its
- * command procedure at runtime.
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
*
* Side effects:
- * Instructions are added to envPtr to execute the "catch" command
- * at runtime.
+ * Instructions are added to envPtr to execute the "catch" command at
+ * runtime.
*
*----------------------------------------------------------------------
*/
int
-TclCompileCatchCmd(interp, parsePtr, envPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Parse *parsePtr; /* Points to a parse structure for the
- * command created by Tcl_ParseCommand. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
+TclCompileCatchCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
{
JumpFixup jumpFixup;
- Tcl_Token *cmdTokenPtr, *nameTokenPtr;
- CONST char *name;
- int localIndex, nameChars, range, startOffset, jumpDist;
- int code;
- int savedStackDepth = envPtr->currStackDepth;
+ Tcl_Token *cmdTokenPtr, *resultNameTokenPtr, *optsNameTokenPtr;
+ const char *name;
+ int resultIndex, optsIndex, nameChars, range;
+ int initStackDepth = envPtr->currStackDepth;
+ int savedStackDepth;
+ DefineLineInformation; /* TIP #280 */
- DefineLineInformation;
+ /*
+ * If syntax does not match what we expect for [catch], do not compile.
+ * Let runtime checks determine if syntax has changed.
+ */
- if ((parsePtr->numWords != 2) && (parsePtr->numWords != 3)) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "wrong # args: should be \"catch command ?varName?\"", -1);
+ if ((parsePtr->numWords < 2) || (parsePtr->numWords > 4)) {
return TCL_ERROR;
}
/*
- * If a variable was specified and the catch command is at global level
- * (not in a procedure), don't compile it inline: the payoff is
- * too small.
+ * If variables were specified and the catch command is at global level
+ * (not in a procedure), don't compile it inline: the payoff is too small.
*/
- if ((parsePtr->numWords == 3) && (envPtr->procPtr == NULL)) {
- return TCL_OUT_LINE_COMPILE;
+ if ((parsePtr->numWords >= 3) && (envPtr->procPtr == NULL)) {
+ return TCL_ERROR;
}
/*
- * Make sure the variable name, if any, has no substitutions and just
- * refers to a local scaler.
+ * Make sure the variable names, if any, have no substitutions and just
+ * refer to local scalars.
*/
- localIndex = -1;
- cmdTokenPtr = parsePtr->tokenPtr
- + (parsePtr->tokenPtr->numComponents + 1);
- if (parsePtr->numWords == 3) {
- nameTokenPtr = cmdTokenPtr + (cmdTokenPtr->numComponents + 1);
- if (nameTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
- name = nameTokenPtr[1].start;
- nameChars = nameTokenPtr[1].size;
+ resultIndex = optsIndex = -1;
+ cmdTokenPtr = TokenAfter(parsePtr->tokenPtr);
+ if (parsePtr->numWords >= 3) {
+ resultNameTokenPtr = TokenAfter(cmdTokenPtr);
+ /* DGP */
+ if (resultNameTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
+ return TCL_ERROR;
+ }
+
+ name = resultNameTokenPtr[1].start;
+ nameChars = resultNameTokenPtr[1].size;
+ if (!TclIsLocalScalar(name, nameChars)) {
+ return TCL_ERROR;
+ }
+ resultIndex = TclFindCompiledLocal(resultNameTokenPtr[1].start,
+ resultNameTokenPtr[1].size, /*create*/ 1, envPtr->procPtr);
+ if (resultIndex < 0) {
+ return TCL_ERROR;
+ }
+
+ /* DKF */
+ if (parsePtr->numWords == 4) {
+ optsNameTokenPtr = TokenAfter(resultNameTokenPtr);
+ if (optsNameTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
+ return TCL_ERROR;
+ }
+ name = optsNameTokenPtr[1].start;
+ nameChars = optsNameTokenPtr[1].size;
if (!TclIsLocalScalar(name, nameChars)) {
- return TCL_OUT_LINE_COMPILE;
+ return TCL_ERROR;
+ }
+ optsIndex = TclFindCompiledLocal(optsNameTokenPtr[1].start,
+ optsNameTokenPtr[1].size, /*create*/ 1, envPtr->procPtr);
+ if (optsIndex < 0) {
+ return TCL_ERROR;
}
- localIndex = TclFindCompiledLocal(nameTokenPtr[1].start,
- nameTokenPtr[1].size, /*create*/ 1,
- /*flags*/ VAR_SCALAR, envPtr->procPtr);
- } else {
- return TCL_OUT_LINE_COMPILE;
}
}
/*
- * We will compile the catch command. Emit a beginCatch instruction at
- * the start of the catch body: the subcommand it controls.
+ * We will compile the catch command. Declare the exception range
+ * that it uses.
*/
-
- envPtr->exceptDepth++;
- envPtr->maxExceptDepth =
- TclMax(envPtr->exceptDepth, envPtr->maxExceptDepth);
- range = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr);
- TclEmitInstInt4(INST_BEGIN_CATCH4, range, envPtr);
+
+ range = DeclareExceptionRange(envPtr, CATCH_EXCEPTION_RANGE);
/*
- * If the body is a simple word, compile the instructions to
- * eval it. Otherwise, compile instructions to substitute its
- * text without catching, a catch instruction that resets the
- * stack to what it was before substituting the body, and then
- * an instruction to eval the body. Care has to be taken to
- * register the correct startOffset for the catch range so that
- * errors in the substitution are not catched [Bug 219184]
+ * If the body is a simple word, compile a BEGIN_CATCH instruction,
+ * followed by the instructions to eval the body.
+ * Otherwise, compile instructions to substitute the body text before
+ * starting the catch, then BEGIN_CATCH, and then EVAL_STK to
+ * evaluate the substituted body.
+ * Care has to be taken to make sure that substitution happens outside
+ * the catch range so that errors in the substitution are not caught.
+ * [Bug 219184]
+ * The reason for duplicating the script is that EVAL_STK would otherwise
+ * begin by undeflowing the stack below the mark set by BEGIN_CATCH4.
*/
- SetLineInformation (1);
+ SetLineInformation(1);
if (cmdTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
- startOffset = (envPtr->codeNext - envPtr->codeStart);
- code = TclCompileCmdWord(interp, cmdTokenPtr+1, 1, envPtr);
+ savedStackDepth = envPtr->currStackDepth;
+ TclEmitInstInt4(INST_BEGIN_CATCH4, range, envPtr);
+ ExceptionRangeStarts(envPtr, range);
+ CompileBody(envPtr, cmdTokenPtr, interp);
} else {
- code = TclCompileTokens(interp, cmdTokenPtr+1,
- cmdTokenPtr->numComponents, envPtr);
- startOffset = (envPtr->codeNext - envPtr->codeStart);
+ CompileTokens(envPtr, cmdTokenPtr, interp);
+ savedStackDepth = envPtr->currStackDepth;
+ TclEmitInstInt4(INST_BEGIN_CATCH4, range, envPtr);
+ ExceptionRangeStarts(envPtr, range);
+ TclEmitOpcode(INST_DUP, envPtr);
TclEmitOpcode(INST_EVAL_STK, envPtr);
}
- envPtr->exceptArrayPtr[range].codeOffset = startOffset;
+ /* Stack at this point:
+ * nonsimple: script <mark> result
+ * simple: <mark> result
+ */
- if (code != TCL_OK) {
- code = TCL_OUT_LINE_COMPILE;
- goto done;
- }
- envPtr->exceptArrayPtr[range].numCodeBytes =
- (envPtr->codeNext - envPtr->codeStart) - startOffset;
-
/*
- * The "no errors" epilogue code: store the body's result into the
- * variable (if any), push "0" (TCL_OK) as the catch's "no error"
+ * Emit the "no errors" epilogue: push "0" (TCL_OK) as the catch
* result, and jump around the "error case" code.
*/
- if (localIndex != -1) {
- if (localIndex <= 255) {
- TclEmitInstInt1(INST_STORE_SCALAR1, localIndex, envPtr);
+ PushLiteral(envPtr, "0", 1);
+ TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup);
+ /* Stack at this point: ?script? <mark> result TCL_OK */
+
+ /*
+ * Emit the "error case" epilogue. Push the interpreter result
+ * and the return code.
+ */
+
+ envPtr->currStackDepth = savedStackDepth;
+ ExceptionRangeTarget(envPtr, range, catchOffset);
+ /* Stack at this point: ?script? */
+ TclEmitOpcode(INST_PUSH_RESULT, envPtr);
+ TclEmitOpcode(INST_PUSH_RETURN_CODE, envPtr);
+
+ /*
+ * Update the target of the jump after the "no errors" code.
+ */
+
+ /* Stack at this point: ?script? result returnCode */
+ if (TclFixupForwardJumpToHere(envPtr, &jumpFixup, 127)) {
+ Tcl_Panic("TclCompileCatchCmd: bad jump distance %d",
+ (int) (CurrentOffset(envPtr) - jumpFixup.codeOffset));
+ }
+
+ /* Push the return options if the caller wants them */
+
+ if (optsIndex != -1) {
+ TclEmitOpcode(INST_PUSH_RETURN_OPTIONS, envPtr);
+ }
+
+ /*
+ * End the catch
+ */
+
+ ExceptionRangeEnds(envPtr, range);
+ TclEmitOpcode(INST_END_CATCH, envPtr);
+
+ /*
+ * At this point, the top of the stack is inconveniently ordered:
+ * ?script? result returnCode ?returnOptions?
+ * Reverse the stack to bring the result to the top.
+ */
+
+ if (optsIndex != -1) {
+ TclEmitInstInt4(INST_REVERSE, 3, envPtr);
+ } else {
+ TclEmitInstInt4(INST_REVERSE, 2, envPtr);
+ }
+
+ /*
+ * Store the result if requested, and remove it from the stack
+ */
+
+ if (resultIndex != -1) {
+ if (resultIndex <= 255) {
+ TclEmitInstInt1(INST_STORE_SCALAR1, resultIndex, envPtr);
} else {
- TclEmitInstInt4(INST_STORE_SCALAR4, localIndex, envPtr);
+ TclEmitInstInt4(INST_STORE_SCALAR4, resultIndex, envPtr);
}
}
TclEmitOpcode(INST_POP, envPtr);
- TclEmitPush(TclRegisterNewLiteral(envPtr, "0", 1), envPtr);
- TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup);
/*
- * The "error case" code: store the body's result into the variable (if
- * any), then push the error result code. The initial PC offset here is
- * the catch's error target.
+ * Stack is now ?script? ?returnOptions? returnCode.
+ * If the options dict has been requested, it is buried on the stack
+ * under the return code. Reverse the stack to bring it to the top,
+ * store it and remove it from the stack.
*/
- envPtr->currStackDepth = savedStackDepth;
- envPtr->exceptArrayPtr[range].catchOffset =
- (envPtr->codeNext - envPtr->codeStart);
- if (localIndex != -1) {
- TclEmitOpcode(INST_PUSH_RESULT, envPtr);
- if (localIndex <= 255) {
- TclEmitInstInt1(INST_STORE_SCALAR1, localIndex, envPtr);
+ if (optsIndex != -1) {
+ TclEmitInstInt4(INST_REVERSE, 2, envPtr);
+ if (optsIndex <= 255) {
+ TclEmitInstInt1(INST_STORE_SCALAR1, optsIndex, envPtr);
} else {
- TclEmitInstInt4(INST_STORE_SCALAR4, localIndex, envPtr);
+ TclEmitInstInt4(INST_STORE_SCALAR4, optsIndex, envPtr);
}
TclEmitOpcode(INST_POP, envPtr);
}
- TclEmitOpcode(INST_PUSH_RETURN_CODE, envPtr);
-
/*
- * Update the target of the jump after the "no errors" code, then emit
- * an endCatch instruction at the end of the catch command.
+ * Stack is now ?script? result. Get rid of the subst'ed script
+ * if it's hanging arond.
*/
- jumpDist = (envPtr->codeNext - envPtr->codeStart)
- - jumpFixup.codeOffset;
- if (TclFixupForwardJump(envPtr, &jumpFixup, jumpDist, 127)) {
- panic("TclCompileCatchCmd: bad jump distance %d\n", jumpDist);
+ if (cmdTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
+ TclEmitInstInt4(INST_REVERSE, 2, envPtr);
+ TclEmitOpcode(INST_POP, envPtr);
}
- TclEmitOpcode(INST_END_CATCH, envPtr);
- done:
- envPtr->currStackDepth = savedStackDepth + 1;
- envPtr->exceptDepth--;
- return code;
+ /*
+ * Result of all this, on either branch, should have been to leave
+ * one operand -- the return code -- on the stack.
+ */
+
+ if (envPtr->currStackDepth != initStackDepth + 1) {
+ Tcl_Panic("in TclCompileCatchCmd, currStackDepth = %d should be %d",
+ envPtr->currStackDepth, initStackDepth+1);
+ }
+ return TCL_OK;
}
/*
@@ -427,32 +601,30 @@ TclCompileCatchCmd(interp, parsePtr, envPtr)
* Procedure called to compile the "continue" command.
*
* Results:
- * The return value is a standard Tcl result, which is TCL_OK unless
- * there was an error while parsing string. If an error occurs then
- * the interpreter's result contains a standard error message.
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
*
* Side effects:
- * Instructions are added to envPtr to execute the "continue" command
- * at runtime.
+ * Instructions are added to envPtr to execute the "continue" command at
+ * runtime.
*
*----------------------------------------------------------------------
*/
int
-TclCompileContinueCmd(interp, parsePtr, envPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Parse *parsePtr; /* Points to a parse structure for the
- * command created by Tcl_ParseCommand. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
+TclCompileContinueCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
{
/*
* There should be no argument after the "continue".
*/
if (parsePtr->numWords != 1) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "wrong # args: should be \"continue\"", -1);
return TCL_ERROR;
}
@@ -467,45 +639,788 @@ TclCompileContinueCmd(interp, parsePtr, envPtr)
/*
*----------------------------------------------------------------------
*
+ * TclCompileDict*Cmd --
+ *
+ * Functions called to compile "dict" sucommands.
+ *
+ * Results:
+ * All return TCL_OK for a successful compile, and TCL_ERROR to defer
+ * evaluation to runtime.
+ *
+ * Side effects:
+ * Instructions are added to envPtr to execute the "dict" subcommand at
+ * runtime.
+ *
+ * Notes:
+ * The following commands are in fairly common use and are possibly worth
+ * bytecoding:
+ * dict append
+ * dict create [*]
+ * dict exists [*]
+ * dict for
+ * dict get [*]
+ * dict incr
+ * dict keys [*]
+ * dict lappend
+ * dict set
+ * dict unset
+ *
+ * In practice, those that are pure-value operators (marked with [*]) can
+ * probably be left alone (except perhaps [dict get] which is very very
+ * common) and [dict update] should be considered instead (really big
+ * win!)
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileDictSetCmd(
+ Tcl_Interp *interp, /* Used for looking up stuff. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ Tcl_Token *tokenPtr;
+ int numWords, i;
+ Proc *procPtr = envPtr->procPtr;
+ DefineLineInformation; /* TIP #280 */
+ Tcl_Token *varTokenPtr;
+ int dictVarIndex, nameChars;
+ const char *name;
+
+ /*
+ * There must be at least one argument after the command.
+ */
+
+ if (parsePtr->numWords < 4 || procPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * The dictionary variable must be a local scalar that is knowable at
+ * compile time; anything else exceeds the complexity of the opcode. So
+ * discover what the index is.
+ */
+
+ varTokenPtr = TokenAfter(parsePtr->tokenPtr);
+ if (varTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
+ return TCL_ERROR;
+ }
+ name = varTokenPtr[1].start;
+ nameChars = varTokenPtr[1].size;
+ if (!TclIsLocalScalar(name, nameChars)) {
+ return TCL_ERROR;
+ }
+ dictVarIndex = TclFindCompiledLocal(name, nameChars, 1, procPtr);
+
+ /*
+ * Remaining words (key path and value to set) can be handled normally.
+ */
+
+ tokenPtr = TokenAfter(varTokenPtr);
+ numWords = parsePtr->numWords-1;
+ for (i=1 ; i<numWords ; i++) {
+ CompileWord(envPtr, tokenPtr, interp, i);
+ tokenPtr = TokenAfter(tokenPtr);
+ }
+
+ /*
+ * Now emit the instruction to do the dict manipulation.
+ */
+
+ TclEmitInstInt4( INST_DICT_SET, numWords-2, envPtr);
+ TclEmitInt4( dictVarIndex, envPtr);
+ return TCL_OK;
+}
+
+int
+TclCompileDictIncrCmd(
+ Tcl_Interp *interp, /* Used for looking up stuff. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ Proc *procPtr = envPtr->procPtr;
+ DefineLineInformation; /* TIP #280 */
+ Tcl_Token *varTokenPtr, *keyTokenPtr;
+ int dictVarIndex, nameChars, incrAmount;
+ const char *name;
+
+ /*
+ * There must be at least two arguments after the command.
+ */
+
+ if (parsePtr->numWords < 3 || parsePtr->numWords > 4 || procPtr == NULL) {
+ return TCL_ERROR;
+ }
+ varTokenPtr = TokenAfter(parsePtr->tokenPtr);
+ keyTokenPtr = TokenAfter(varTokenPtr);
+
+ /*
+ * Parse the increment amount, if present.
+ */
+
+ if (parsePtr->numWords == 4) {
+ const char *word;
+ int numBytes, code;
+ Tcl_Token *incrTokenPtr;
+ Tcl_Obj *intObj;
+
+ incrTokenPtr = TokenAfter(keyTokenPtr);
+ if (incrTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
+ return TCL_ERROR;
+ }
+ word = incrTokenPtr[1].start;
+ numBytes = incrTokenPtr[1].size;
+
+ intObj = Tcl_NewStringObj(word, numBytes);
+ Tcl_IncrRefCount(intObj);
+ code = TclGetIntFromObj(NULL, intObj, &incrAmount);
+ TclDecrRefCount(intObj);
+ if (code != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ incrAmount = 1;
+ }
+
+ /*
+ * The dictionary variable must be a local scalar that is knowable at
+ * compile time; anything else exceeds the complexity of the opcode. So
+ * discover what the index is.
+ */
+
+ if (varTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
+ return TCL_ERROR;
+ }
+ name = varTokenPtr[1].start;
+ nameChars = varTokenPtr[1].size;
+ if (!TclIsLocalScalar(name, nameChars)) {
+ return TCL_ERROR;
+ }
+ dictVarIndex = TclFindCompiledLocal(name, nameChars, 1, procPtr);
+
+ /*
+ * Emit the key and the code to actually do the increment.
+ */
+
+ CompileWord(envPtr, keyTokenPtr, interp, 3);
+ TclEmitInstInt4( INST_DICT_INCR_IMM, incrAmount, envPtr);
+ TclEmitInt4( dictVarIndex, envPtr);
+ return TCL_OK;
+}
+
+int
+TclCompileDictGetCmd(
+ Tcl_Interp *interp, /* Used for looking up stuff. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ Tcl_Token *tokenPtr;
+ int numWords, i;
+ DefineLineInformation; /* TIP #280 */
+
+ /*
+ * There must be at least two arguments after the command (the single-arg
+ * case is legal, but too special and magic for us to deal with here).
+ */
+
+ if (parsePtr->numWords < 3) {
+ return TCL_ERROR;
+ }
+ tokenPtr = TokenAfter(parsePtr->tokenPtr);
+ numWords = parsePtr->numWords-1;
+
+ /*
+ * Only compile this because we need INST_DICT_GET anyway.
+ */
+
+ for (i=0 ; i<numWords ; i++) {
+ CompileWord(envPtr, tokenPtr, interp, i);
+ tokenPtr = TokenAfter(tokenPtr);
+ }
+ TclEmitInstInt4(INST_DICT_GET, numWords-1, envPtr);
+ return TCL_OK;
+}
+
+int
+TclCompileDictForCmd(
+ Tcl_Interp *interp, /* Used for looking up stuff. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ Proc *procPtr = envPtr->procPtr;
+ DefineLineInformation; /* TIP #280 */
+ Tcl_Token *varsTokenPtr, *dictTokenPtr, *bodyTokenPtr;
+ int keyVarIndex, valueVarIndex, nameChars, loopRange, catchRange;
+ int infoIndex, jumpDisplacement, bodyTargetOffset, emptyTargetOffset;
+ int numVars, endTargetOffset;
+ int savedStackDepth = envPtr->currStackDepth;
+ /* Needed because jumps confuse the stack
+ * space calculator. */
+ const char **argv;
+ Tcl_DString buffer;
+
+ /*
+ * There must be at least three argument after the command.
+ */
+
+ if (parsePtr->numWords != 4 || procPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ varsTokenPtr = TokenAfter(parsePtr->tokenPtr);
+ dictTokenPtr = TokenAfter(varsTokenPtr);
+ bodyTokenPtr = TokenAfter(dictTokenPtr);
+ if (varsTokenPtr->type != TCL_TOKEN_SIMPLE_WORD ||
+ bodyTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Check we've got a pair of variables and that they are local variables.
+ * Then extract their indices in the LVT.
+ */
+
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer, varsTokenPtr[1].start, varsTokenPtr[1].size);
+ if (Tcl_SplitList(NULL, Tcl_DStringValue(&buffer), &numVars,
+ &argv) != TCL_OK) {
+ Tcl_DStringFree(&buffer);
+ return TCL_ERROR;
+ }
+ Tcl_DStringFree(&buffer);
+ if (numVars != 2) {
+ ckfree((char *) argv);
+ return TCL_ERROR;
+ }
+
+ nameChars = strlen(argv[0]);
+ if (!TclIsLocalScalar(argv[0], nameChars)) {
+ ckfree((char *) argv);
+ return TCL_ERROR;
+ }
+ keyVarIndex = TclFindCompiledLocal(argv[0], nameChars, 1, procPtr);
+
+ nameChars = strlen(argv[1]);
+ if (!TclIsLocalScalar(argv[1], nameChars)) {
+ ckfree((char *) argv);
+ return TCL_ERROR;
+ }
+ valueVarIndex = TclFindCompiledLocal(argv[1], nameChars, 1, procPtr);
+ ckfree((char *) argv);
+
+ /*
+ * Allocate a temporary variable to store the iterator reference. The
+ * variable will contain a Tcl_DictSearch reference which will be
+ * allocated by INST_DICT_FIRST and disposed when the variable is unset
+ * (at which point it should also have been finished with).
+ */
+
+ infoIndex = TclFindCompiledLocal(NULL, 0, 1, procPtr);
+
+ /*
+ * Preparation complete; issue instructions. Note that this code issues
+ * fixed-sized jumps. That simplifies things a lot!
+ *
+ * First up, get the dictionary and start the iteration. No catching of
+ * errors at this point.
+ */
+
+ CompileWord(envPtr, dictTokenPtr, interp, 3);
+ TclEmitInstInt4( INST_DICT_FIRST, infoIndex, envPtr);
+ emptyTargetOffset = CurrentOffset(envPtr);
+ TclEmitInstInt4( INST_JUMP_TRUE4, 0, envPtr);
+
+ /*
+ * Now we catch errors from here on so that we can finalize the search
+ * started by Tcl_DictObjFirst above.
+ */
+
+ catchRange = DeclareExceptionRange(envPtr, CATCH_EXCEPTION_RANGE);
+ TclEmitInstInt4( INST_BEGIN_CATCH4, catchRange, envPtr);
+ ExceptionRangeStarts(envPtr, catchRange);
+
+ /*
+ * Inside the iteration, write the loop variables.
+ */
+
+ bodyTargetOffset = CurrentOffset(envPtr);
+ TclEmitInstInt4( INST_STORE_SCALAR4, keyVarIndex, envPtr);
+ TclEmitOpcode( INST_POP, envPtr);
+ TclEmitInstInt4( INST_STORE_SCALAR4, valueVarIndex, envPtr);
+ TclEmitOpcode( INST_POP, envPtr);
+
+ /*
+ * Set up the loop exception targets.
+ */
+
+ loopRange = DeclareExceptionRange(envPtr, LOOP_EXCEPTION_RANGE);
+ ExceptionRangeStarts(envPtr, loopRange);
+
+ /*
+ * Compile the loop body itself. It should be stack-neutral.
+ */
+
+ SetLineInformation (4);
+ CompileBody(envPtr, bodyTokenPtr, interp);
+ TclEmitOpcode( INST_POP, envPtr);
+
+ /*
+ * Both exception target ranges (error and loop) end here.
+ */
+
+ ExceptionRangeEnds(envPtr, loopRange);
+ ExceptionRangeEnds(envPtr, catchRange);
+
+ /*
+ * Continue (or just normally process) by getting the next pair of items
+ * from the dictionary and jumping back to the code to write them into
+ * variables if there is another pair.
+ */
+
+ ExceptionRangeTarget(envPtr, loopRange, continueOffset);
+ TclEmitInstInt4( INST_DICT_NEXT, infoIndex, envPtr);
+ jumpDisplacement = bodyTargetOffset - CurrentOffset(envPtr);
+ TclEmitInstInt4( INST_JUMP_FALSE4, jumpDisplacement, envPtr);
+ TclEmitOpcode( INST_POP, envPtr);
+ TclEmitOpcode( INST_POP, envPtr);
+
+ /*
+ * Now do the final cleanup for the no-error case (this is where we break
+ * out of the loop to) by force-terminating the iteration (if not already
+ * terminated), ditching the exception info and jumping to the last
+ * instruction for this command. In theory, this could be done using the
+ * "finally" clause (next generated) but this is faster.
+ */
+
+ ExceptionRangeTarget(envPtr, loopRange, breakOffset);
+ TclEmitInstInt4( INST_DICT_DONE, infoIndex, envPtr);
+ TclEmitOpcode( INST_END_CATCH, envPtr);
+ endTargetOffset = CurrentOffset(envPtr);
+ TclEmitInstInt4( INST_JUMP4, 0, envPtr);
+
+ /*
+ * Error handler "finally" clause, which force-terminates the iteration
+ * and rethrows the error.
+ */
+
+ ExceptionRangeTarget(envPtr, catchRange, catchOffset);
+ TclEmitOpcode( INST_PUSH_RETURN_OPTIONS, envPtr);
+ TclEmitOpcode( INST_PUSH_RESULT, envPtr);
+ TclEmitInstInt4( INST_DICT_DONE, infoIndex, envPtr);
+ TclEmitOpcode( INST_END_CATCH, envPtr);
+ TclEmitOpcode( INST_RETURN_STK, envPtr);
+
+ /*
+ * Otherwise we're done (the jump after the DICT_FIRST points here) and we
+ * need to pop the bogus key/value pair (pushed to keep stack calculations
+ * easy!) Note that we skip the END_CATCH. [Bug 1382528]
+ */
+
+ envPtr->currStackDepth = savedStackDepth+2;
+ jumpDisplacement = CurrentOffset(envPtr) - emptyTargetOffset;
+ TclUpdateInstInt4AtPc(INST_JUMP_TRUE4, jumpDisplacement,
+ envPtr->codeStart + emptyTargetOffset);
+ TclEmitOpcode( INST_POP, envPtr);
+ TclEmitOpcode( INST_POP, envPtr);
+ TclEmitInstInt4( INST_DICT_DONE, infoIndex, envPtr);
+
+ /*
+ * Final stage of the command (normal case) is that we push an empty
+ * object. This is done last to promote peephole optimization when it's
+ * dropped immediately.
+ */
+
+ jumpDisplacement = CurrentOffset(envPtr) - endTargetOffset;
+ TclUpdateInstInt4AtPc(INST_JUMP4, jumpDisplacement,
+ envPtr->codeStart + endTargetOffset);
+ PushLiteral(envPtr, "", 0);
+ return TCL_OK;
+}
+
+int
+TclCompileDictUpdateCmd(
+ Tcl_Interp *interp, /* Used for looking up stuff. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ Proc *procPtr = envPtr->procPtr;
+ DefineLineInformation; /* TIP #280 */
+ const char *name;
+ int i, nameChars, dictIndex, numVars, range, infoIndex;
+ Tcl_Token **keyTokenPtrs, *dictVarTokenPtr, *bodyTokenPtr, *tokenPtr;
+ DictUpdateInfo *duiPtr;
+ JumpFixup jumpFixup;
+
+ /*
+ * There must be at least one argument after the command.
+ */
+
+ if (parsePtr->numWords < 5 || procPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Parse the command. Expect the following:
+ * dict update <lit(eral)> <any> <lit> ?<any> <lit> ...? <lit>
+ */
+
+ if ((parsePtr->numWords - 1) & 1) {
+ return TCL_ERROR;
+ }
+ numVars = (parsePtr->numWords - 3) / 2;
+
+ /*
+ * The dictionary variable must be a local scalar that is knowable at
+ * compile time; anything else exceeds the complexity of the opcode. So
+ * discover what the index is.
+ */
+
+ dictVarTokenPtr = TokenAfter(parsePtr->tokenPtr);
+ if (dictVarTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
+ return TCL_ERROR;
+ }
+ name = dictVarTokenPtr[1].start;
+ nameChars = dictVarTokenPtr[1].size;
+ if (!TclIsLocalScalar(name, nameChars)) {
+ return TCL_ERROR;
+ }
+ dictIndex = TclFindCompiledLocal(name, nameChars, 1, procPtr);
+
+ /*
+ * Assemble the instruction metadata. This is complex enough that it is
+ * represented as auxData; it holds an ordered list of variable indices
+ * that are to be used.
+ */
+
+ duiPtr = (DictUpdateInfo *)
+ ckalloc(sizeof(DictUpdateInfo) + sizeof(int) * (numVars - 1));
+ duiPtr->length = numVars;
+ keyTokenPtrs = (Tcl_Token **) TclStackAlloc(interp,
+ sizeof(Tcl_Token *) * numVars);
+ tokenPtr = TokenAfter(dictVarTokenPtr);
+
+ for (i=0 ; i<numVars ; i++) {
+ /*
+ * Put keys to one side for later compilation to bytecode.
+ */
+
+ keyTokenPtrs[i] = tokenPtr;
+
+ /*
+ * Variables first need to be checked for sanity.
+ */
+
+ tokenPtr = TokenAfter(tokenPtr);
+ if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
+ ckfree((char *) duiPtr);
+ TclStackFree(interp, keyTokenPtrs);
+ return TCL_ERROR;
+ }
+ name = tokenPtr[1].start;
+ nameChars = tokenPtr[1].size;
+ if (!TclIsLocalScalar(name, nameChars)) {
+ ckfree((char *) duiPtr);
+ TclStackFree(interp, keyTokenPtrs);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Stash the index in the auxiliary data.
+ */
+
+ duiPtr->varIndices[i] =
+ TclFindCompiledLocal(name, nameChars, 1, procPtr);
+ tokenPtr = TokenAfter(tokenPtr);
+ }
+ if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
+ ckfree((char *) duiPtr);
+ TclStackFree(interp, keyTokenPtrs);
+ return TCL_ERROR;
+ }
+ bodyTokenPtr = tokenPtr;
+
+ /*
+ * The list of variables to bind is stored in auxiliary data so that it
+ * can't be snagged by literal sharing and forced to shimmer dangerously.
+ */
+
+ infoIndex = TclCreateAuxData(duiPtr, &tclDictUpdateInfoType, envPtr);
+
+ for (i=0 ; i<numVars ; i++) {
+ CompileWord(envPtr, keyTokenPtrs[i], interp, i);
+ }
+ TclEmitInstInt4( INST_LIST, numVars, envPtr);
+ TclEmitInstInt4( INST_DICT_UPDATE_START, dictIndex, envPtr);
+ TclEmitInt4( infoIndex, envPtr);
+
+ range = DeclareExceptionRange(envPtr, CATCH_EXCEPTION_RANGE);
+ TclEmitInstInt4( INST_BEGIN_CATCH4, range, envPtr);
+
+ ExceptionRangeStarts(envPtr, range);
+ CompileBody(envPtr, bodyTokenPtr, interp);
+ ExceptionRangeEnds(envPtr, range);
+
+ /*
+ * Normal termination code: the stack has the key list below the result of
+ * the body evaluation: swap them and finish the update code.
+ */
+
+ TclEmitOpcode( INST_END_CATCH, envPtr);
+ TclEmitInstInt4( INST_REVERSE, 2, envPtr);
+ TclEmitInstInt4( INST_DICT_UPDATE_END, dictIndex, envPtr);
+ TclEmitInt4( infoIndex, envPtr);
+
+ /*
+ * Jump around the exceptional termination code.
+ */
+
+ TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup);
+
+ /*
+ * Termination code for non-ok returns: stash the result and return
+ * options in the stack, bring up the key list, finish the update code,
+ * and finally return with the catched return data
+ */
+
+ ExceptionRangeTarget(envPtr, range, catchOffset);
+ TclEmitOpcode( INST_PUSH_RESULT, envPtr);
+ TclEmitOpcode( INST_PUSH_RETURN_OPTIONS, envPtr);
+ TclEmitOpcode( INST_END_CATCH, envPtr);
+ TclEmitInstInt4( INST_REVERSE, 3, envPtr);
+
+ TclEmitInstInt4( INST_DICT_UPDATE_END, dictIndex, envPtr);
+ TclEmitInt4( infoIndex, envPtr);
+ TclEmitOpcode( INST_RETURN_STK, envPtr);
+
+ if (TclFixupForwardJumpToHere(envPtr, &jumpFixup, 127)) {
+ Tcl_Panic("TclCompileDictCmd(update): bad jump distance %d",
+ (int) (CurrentOffset(envPtr) - jumpFixup.codeOffset));
+ }
+ TclStackFree(interp, keyTokenPtrs);
+ return TCL_OK;
+}
+
+int
+TclCompileDictAppendCmd(
+ Tcl_Interp *interp, /* Used for looking up stuff. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ Proc *procPtr = envPtr->procPtr;
+ DefineLineInformation; /* TIP #280 */
+ Tcl_Token *tokenPtr;
+ int i, dictVarIndex;
+
+ /*
+ * There must be at least two argument after the command. And we impose an
+ * (arbirary) safe limit; anyone exceeding it should stop worrying about
+ * speed quite so much. ;-)
+ */
+
+ if (parsePtr->numWords<4 || parsePtr->numWords>100 || procPtr==NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Get the index of the local variable that we will be working with.
+ */
+
+ tokenPtr = TokenAfter(parsePtr->tokenPtr);
+ if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
+ return TCL_ERROR;
+ } else {
+ register const char *name = tokenPtr[1].start;
+ register int nameChars = tokenPtr[1].size;
+
+ if (!TclIsLocalScalar(name, nameChars)) {
+ return TCL_ERROR;
+ }
+ dictVarIndex = TclFindCompiledLocal(name, nameChars, 1, procPtr);
+ }
+
+ /*
+ * Produce the string to concatenate onto the dictionary entry.
+ */
+
+ tokenPtr = TokenAfter(tokenPtr);
+ for (i=2 ; i<parsePtr->numWords ; i++) {
+ CompileWord(envPtr, tokenPtr, interp, i);
+ tokenPtr = TokenAfter(tokenPtr);
+ }
+ if (parsePtr->numWords > 4) {
+ TclEmitInstInt1(INST_CONCAT1, parsePtr->numWords-3, envPtr);
+ }
+
+ /*
+ * Do the concatenation.
+ */
+
+ TclEmitInstInt4(INST_DICT_APPEND, dictVarIndex, envPtr);
+ return TCL_OK;
+}
+
+int
+TclCompileDictLappendCmd(
+ Tcl_Interp *interp, /* Used for looking up stuff. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ Proc *procPtr = envPtr->procPtr;
+ DefineLineInformation; /* TIP #280 */
+ Tcl_Token *varTokenPtr, *keyTokenPtr, *valueTokenPtr;
+ int dictVarIndex, nameChars;
+ const char *name;
+
+ /*
+ * There must be three arguments after the command.
+ */
+
+ if (parsePtr->numWords != 4 || procPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ varTokenPtr = TokenAfter(parsePtr->tokenPtr);
+ keyTokenPtr = TokenAfter(varTokenPtr);
+ valueTokenPtr = TokenAfter(keyTokenPtr);
+ if (varTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
+ return TCL_ERROR;
+ }
+ name = varTokenPtr[1].start;
+ nameChars = varTokenPtr[1].size;
+ if (!TclIsLocalScalar(name, nameChars)) {
+ return TCL_ERROR;
+ }
+ dictVarIndex = TclFindCompiledLocal(name, nameChars, 1, procPtr);
+ CompileWord(envPtr, keyTokenPtr, interp, 3);
+ CompileWord(envPtr, valueTokenPtr, interp, 4);
+ TclEmitInstInt4( INST_DICT_LAPPEND, dictVarIndex, envPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupDictUpdateInfo, FreeDictUpdateInfo --
+ *
+ * Functions to duplicate, release and print the aux data created for use
+ * with the INST_DICT_UPDATE_START and INST_DICT_UPDATE_END instructions.
+ *
+ * Results:
+ * DupDictUpdateInfo: a copy of the auxiliary data
+ * FreeDictUpdateInfo: none
+ * PrintDictUpdateInfo: none
+ *
+ * Side effects:
+ * DupDictUpdateInfo: allocates memory
+ * FreeDictUpdateInfo: releases memory
+ * PrintDictUpdateInfo: none
+ *
+ *----------------------------------------------------------------------
+ */
+
+static ClientData
+DupDictUpdateInfo(
+ ClientData clientData)
+{
+ DictUpdateInfo *dui1Ptr, *dui2Ptr;
+ unsigned len;
+
+ dui1Ptr = clientData;
+ len = sizeof(DictUpdateInfo) + sizeof(int) * (dui1Ptr->length - 1);
+ dui2Ptr = (DictUpdateInfo *) ckalloc(len);
+ memcpy(dui2Ptr, dui1Ptr, len);
+ return dui2Ptr;
+}
+
+static void
+FreeDictUpdateInfo(
+ ClientData clientData)
+{
+ ckfree(clientData);
+}
+
+static void
+PrintDictUpdateInfo(
+ ClientData clientData,
+ Tcl_Obj *appendObj,
+ ByteCode *codePtr,
+ unsigned int pcOffset)
+{
+ DictUpdateInfo *duiPtr = clientData;
+ int i;
+
+ for (i=0 ; i<duiPtr->length ; i++) {
+ if (i) {
+ Tcl_AppendToObj(appendObj, ", ", -1);
+ }
+ Tcl_AppendPrintfToObj(appendObj, "%%v%u", duiPtr->varIndices[i]);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TclCompileExprCmd --
*
* Procedure called to compile the "expr" command.
*
* Results:
- * The return value is a standard Tcl result, which is TCL_OK
- * unless there was an error while parsing string. If an error occurs
- * then the interpreter's result contains a standard error message.
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
*
* Side effects:
- * Instructions are added to envPtr to execute the "expr" command
- * at runtime.
+ * Instructions are added to envPtr to execute the "expr" command at
+ * runtime.
*
*----------------------------------------------------------------------
*/
int
-TclCompileExprCmd(interp, parsePtr, envPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Parse *parsePtr; /* Points to a parse structure for the
- * command created by Tcl_ParseCommand. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
+TclCompileExprCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
{
Tcl_Token *firstWordPtr;
- DefineLineInformation;
-
if (parsePtr->numWords == 1) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "wrong # args: should be \"expr arg ?arg ...?\"", -1);
- return TCL_ERROR;
+ return TCL_ERROR;
}
- SetLineInformation (1);
- firstWordPtr = parsePtr->tokenPtr
- + (parsePtr->tokenPtr->numComponents + 1);
- return TclCompileExprWords(interp, firstWordPtr, (parsePtr->numWords-1),
- envPtr);
+ /*
+ * TIP #280: Use the per-word line information of the current command.
+ */
+
+ envPtr->line = envPtr->extCmdMapPtr->loc[
+ envPtr->extCmdMapPtr->nuloc-1].line[1];
+
+ firstWordPtr = TokenAfter(parsePtr->tokenPtr);
+ TclCompileExprWords(interp, firstWordPtr, parsePtr->numWords-1, envPtr);
+ return TCL_OK;
}
/*
@@ -516,36 +1431,33 @@ TclCompileExprCmd(interp, parsePtr, envPtr)
* Procedure called to compile the "for" command.
*
* Results:
- * The return value is a standard Tcl result, which is TCL_OK unless
- * there was an error while parsing string. If an error occurs then
- * the interpreter's result contains a standard error message.
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
*
* Side effects:
- * Instructions are added to envPtr to execute the "for" command
- * at runtime.
+ * Instructions are added to envPtr to execute the "for" command at
+ * runtime.
*
*----------------------------------------------------------------------
*/
+
int
-TclCompileForCmd(interp, parsePtr, envPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Parse *parsePtr; /* Points to a parse structure for the
- * command created by Tcl_ParseCommand. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
+TclCompileForCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
{
Tcl_Token *startTokenPtr, *testTokenPtr, *nextTokenPtr, *bodyTokenPtr;
JumpFixup jumpEvalCondFixup;
int testCodeOffset, bodyCodeOffset, nextCodeOffset, jumpDist;
- int bodyRange, nextRange, code;
- char buffer[32 + TCL_INTEGER_SPACE];
+ int bodyRange, nextRange;
int savedStackDepth = envPtr->currStackDepth;
-
- DefineLineInformation;
+ DefineLineInformation; /* TIP #280 */
if (parsePtr->numWords != 5) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "wrong # args: should be \"for start test next command\"", -1);
return TCL_ERROR;
}
@@ -555,11 +1467,10 @@ TclCompileForCmd(interp, parsePtr, envPtr)
* execute or execute forever, as in "for {} "$x > 5" {incr x} {}".
*/
- startTokenPtr = parsePtr->tokenPtr
- + (parsePtr->tokenPtr->numComponents + 1);
- testTokenPtr = startTokenPtr + (startTokenPtr->numComponents + 1);
+ startTokenPtr = TokenAfter(parsePtr->tokenPtr);
+ testTokenPtr = TokenAfter(startTokenPtr);
if (testTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
- return TCL_OUT_LINE_COMPILE;
+ return TCL_ERROR;
}
/*
@@ -567,23 +1478,20 @@ TclCompileForCmd(interp, parsePtr, envPtr)
* in order to insure correct behaviour [Bug 219166]
*/
- nextTokenPtr = testTokenPtr + (testTokenPtr->numComponents + 1);
- bodyTokenPtr = nextTokenPtr + (nextTokenPtr->numComponents + 1);
- if ((nextTokenPtr->type != TCL_TOKEN_SIMPLE_WORD)
+ nextTokenPtr = TokenAfter(testTokenPtr);
+ bodyTokenPtr = TokenAfter(nextTokenPtr);
+ if ((nextTokenPtr->type != TCL_TOKEN_SIMPLE_WORD)
|| (bodyTokenPtr->type != TCL_TOKEN_SIMPLE_WORD)) {
- return TCL_OUT_LINE_COMPILE;
+ return TCL_ERROR;
}
/*
- * Create ExceptionRange records for the body and the "next" command.
- * The "next" command's ExceptionRange supports break but not continue
- * (and has a -1 continueOffset).
+ * Create ExceptionRange records for the body and the "next" command. The
+ * "next" command's ExceptionRange supports break but not continue (and
+ * has a -1 continueOffset).
*/
- envPtr->exceptDepth++;
- envPtr->maxExceptDepth =
- TclMax(envPtr->exceptDepth, envPtr->maxExceptDepth);
- bodyRange = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr);
+ bodyRange = DeclareExceptionRange(envPtr, LOOP_EXCEPTION_RANGE);
nextRange = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr);
/*
@@ -591,17 +1499,9 @@ TclCompileForCmd(interp, parsePtr, envPtr)
*/
SetLineInformation (1);
- code = TclCompileCmdWord(interp, startTokenPtr+1,
- startTokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- if (code == TCL_ERROR) {
- Tcl_AddObjErrorInfo(interp,
- "\n (\"for\" initial command)", -1);
- }
- goto done;
- }
+ CompileBody(envPtr, startTokenPtr, interp);
TclEmitOpcode(INST_POP, envPtr);
-
+
/*
* Jump to the evaluation of the condition. This code uses the "loop
* rotation" optimisation (which eliminates one branch from the loop).
@@ -620,46 +1520,23 @@ TclCompileForCmd(interp, parsePtr, envPtr)
* Compile the loop body.
*/
- bodyCodeOffset = (envPtr->codeNext - envPtr->codeStart);
-
+ bodyCodeOffset = ExceptionRangeStarts(envPtr, bodyRange);
SetLineInformation (4);
- code = TclCompileCmdWord(interp, bodyTokenPtr+1,
- bodyTokenPtr->numComponents, envPtr);
+ CompileBody(envPtr, bodyTokenPtr, interp);
+ ExceptionRangeEnds(envPtr, bodyRange);
envPtr->currStackDepth = savedStackDepth + 1;
- if (code != TCL_OK) {
- if (code == TCL_ERROR) {
- sprintf(buffer, "\n (\"for\" body line %d)",
- interp->errorLine);
- Tcl_AddObjErrorInfo(interp, buffer, -1);
- }
- goto done;
- }
- envPtr->exceptArrayPtr[bodyRange].numCodeBytes =
- (envPtr->codeNext - envPtr->codeStart) - bodyCodeOffset;
TclEmitOpcode(INST_POP, envPtr);
-
/*
* Compile the "next" subcommand.
*/
- nextCodeOffset = (envPtr->codeNext - envPtr->codeStart);
-
- SetLineInformation (3);
envPtr->currStackDepth = savedStackDepth;
- code = TclCompileCmdWord(interp, nextTokenPtr+1,
- nextTokenPtr->numComponents, envPtr);
+ nextCodeOffset = ExceptionRangeStarts(envPtr, nextRange);
+ SetLineInformation (3);
+ CompileBody(envPtr, nextTokenPtr, interp);
+ ExceptionRangeEnds(envPtr, nextRange);
envPtr->currStackDepth = savedStackDepth + 1;
- if (code != TCL_OK) {
- if (code == TCL_ERROR) {
- Tcl_AddObjErrorInfo(interp,
- "\n (\"for\" loop-end command)", -1);
- }
- goto done;
- }
- envPtr->exceptArrayPtr[nextRange].numCodeBytes =
- (envPtr->codeNext - envPtr->codeStart)
- - nextCodeOffset;
TclEmitOpcode(INST_POP, envPtr);
envPtr->currStackDepth = savedStackDepth;
@@ -668,7 +1545,7 @@ TclCompileForCmd(interp, parsePtr, envPtr)
* terminates the for.
*/
- testCodeOffset = (envPtr->codeNext - envPtr->codeStart);
+ testCodeOffset = CurrentOffset(envPtr);
jumpDist = testCodeOffset - jumpEvalCondFixup.codeOffset;
if (TclFixupForwardJump(envPtr, &jumpEvalCondFixup, jumpDist, 127)) {
@@ -676,27 +1553,22 @@ TclCompileForCmd(interp, parsePtr, envPtr)
nextCodeOffset += 3;
testCodeOffset += 3;
}
+
SetLineInformation (2);
envPtr->currStackDepth = savedStackDepth;
- code = TclCompileExprWords(interp, testTokenPtr, 1, envPtr);
- if (code != TCL_OK) {
- if (code == TCL_ERROR) {
- Tcl_AddObjErrorInfo(interp,
- "\n (\"for\" test expression)", -1);
- }
- goto done;
- }
+ TclCompileExprWords(interp, testTokenPtr, 1, envPtr);
envPtr->currStackDepth = savedStackDepth + 1;
-
- jumpDist = (envPtr->codeNext - envPtr->codeStart) - bodyCodeOffset;
+
+ jumpDist = CurrentOffset(envPtr) - bodyCodeOffset;
if (jumpDist > 127) {
TclEmitInstInt4(INST_JUMP_TRUE4, -jumpDist, envPtr);
} else {
TclEmitInstInt1(INST_JUMP_TRUE1, -jumpDist, envPtr);
}
-
+
/*
- * Set the loop's offsets and break target.
+ * Fix the starting points of the exception ranges (may have moved due to
+ * jump type modification) and set where the exceptions target.
*/
envPtr->exceptArrayPtr[bodyRange].codeOffset = bodyCodeOffset;
@@ -704,21 +1576,17 @@ TclCompileForCmd(interp, parsePtr, envPtr)
envPtr->exceptArrayPtr[nextRange].codeOffset = nextCodeOffset;
- envPtr->exceptArrayPtr[bodyRange].breakOffset =
- envPtr->exceptArrayPtr[nextRange].breakOffset =
- (envPtr->codeNext - envPtr->codeStart);
-
+ ExceptionRangeTarget(envPtr, bodyRange, breakOffset);
+ ExceptionRangeTarget(envPtr, nextRange, breakOffset);
+
/*
* The for command's result is an empty string.
*/
envPtr->currStackDepth = savedStackDepth;
- TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
- code = TCL_OK;
+ PushLiteral(envPtr, "", 0);
- done:
- envPtr->exceptDepth--;
- return code;
+ return TCL_OK;
}
/*
@@ -729,27 +1597,24 @@ TclCompileForCmd(interp, parsePtr, envPtr)
* Procedure called to compile the "foreach" command.
*
* Results:
- * The return value is a standard Tcl result, which is TCL_OK if
- * compilation was successful. If an error occurs then the
- * interpreter's result contains a standard error message and TCL_ERROR
- * is returned. If the command is too complex for TclCompileForeachCmd,
- * TCL_OUT_LINE_COMPILE is returned indicating that the foreach command
- * should be compiled "out of line" by emitting code to invoke its
- * command procedure at runtime.
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
*
* Side effects:
- * Instructions are added to envPtr to execute the "foreach" command
- * at runtime.
+ * Instructions are added to envPtr to execute the "foreach" command at
+ * runtime.
*
-n*----------------------------------------------------------------------
+ *----------------------------------------------------------------------
*/
int
-TclCompileForeachCmd(interp, parsePtr, envPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Parse *parsePtr; /* Points to a parse structure for the
- * command created by Tcl_ParseCommand. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
+TclCompileForeachCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
{
Proc *procPtr = envPtr->procPtr;
ForeachInfo *infoPtr; /* Points to the structure describing this
@@ -762,28 +1627,19 @@ TclCompileForeachCmd(interp, parsePtr, envPtr)
Tcl_Token *tokenPtr, *bodyTokenPtr;
unsigned char *jumpPc;
JumpFixup jumpFalseFixup;
- int jumpDist, jumpBackDist, jumpBackOffset, infoIndex, range;
+ int jumpBackDist, jumpBackOffset, infoIndex, range, bodyIndex;
int numWords, numLists, numVars, loopIndex, tempVar, i, j, code;
- char buffer[32 + TCL_INTEGER_SPACE];
int savedStackDepth = envPtr->currStackDepth;
-
-#ifdef TCL_TIP280
- int bodyIndex;
-#endif
+ DefineLineInformation; /* TIP #280 */
/*
* We parse the variable list argument words and create two arrays:
- * varcList[i] is number of variables in i-th var list
- * varvList[i] points to array of var names in i-th var list
+ * varcList[i] is number of variables in i-th var list.
+ * varvList[i] points to array of var names in i-th var list.
*/
-#define STATIC_VAR_LIST_SIZE 5
- int varcListStaticSpace[STATIC_VAR_LIST_SIZE];
- CONST char **varvListStaticSpace[STATIC_VAR_LIST_SIZE];
- int *varcList = varcListStaticSpace;
- CONST char ***varvList = varvListStaticSpace;
-
- DefineLineInformation;
+ int *varcList;
+ const char ***varvList;
/*
* If the foreach command isn't in a procedure, don't compile it inline:
@@ -791,129 +1647,120 @@ TclCompileForeachCmd(interp, parsePtr, envPtr)
*/
if (procPtr == NULL) {
- return TCL_OUT_LINE_COMPILE;
+ return TCL_ERROR;
}
numWords = parsePtr->numWords;
if ((numWords < 4) || (numWords%2 != 0)) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "wrong # args: should be \"foreach varList list ?varList list ...? command\"", -1);
- return TCL_ERROR;
+ return TCL_ERROR;
}
/*
- * Bail out if the body requires substitutions
- * in order to insure correct behaviour [Bug 219166]
+ * Bail out if the body requires substitutions in order to insure correct
+ * behaviour. [Bug 219166]
*/
- for (i = 0, tokenPtr = parsePtr->tokenPtr;
- i < numWords-1;
- i++, tokenPtr += (tokenPtr->numComponents + 1)) {
+
+ for (i = 0, tokenPtr = parsePtr->tokenPtr; i < numWords-1; i++) {
+ tokenPtr = TokenAfter(tokenPtr);
}
bodyTokenPtr = tokenPtr;
if (bodyTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
- return TCL_OUT_LINE_COMPILE;
+ return TCL_ERROR;
}
-#ifdef TCL_TIP280
+
bodyIndex = i-1;
-#endif
/*
* Allocate storage for the varcList and varvList arrays if necessary.
*/
numLists = (numWords - 2)/2;
- if (numLists > STATIC_VAR_LIST_SIZE) {
- varcList = (int *) ckalloc(numLists * sizeof(int));
- varvList = (CONST char ***) ckalloc(numLists * sizeof(CONST char **));
- }
- for (loopIndex = 0; loopIndex < numLists; loopIndex++) {
- varcList[loopIndex] = 0;
- varvList[loopIndex] = NULL;
- }
-
- /*
- * Set the exception stack depth.
- */
-
- envPtr->exceptDepth++;
- envPtr->maxExceptDepth =
- TclMax(envPtr->exceptDepth, envPtr->maxExceptDepth);
+ varcList = (int *) TclStackAlloc(interp, numLists * sizeof(int));
+ memset(varcList, 0, numLists * sizeof(int));
+ varvList = (const char ***) TclStackAlloc(interp,
+ numLists * sizeof(const char **));
+ memset((char*) varvList, 0, numLists * sizeof(const char **));
/*
- * Break up each var list and set the varcList and varvList arrays.
- * Don't compile the foreach inline if any var name needs substitutions
- * or isn't a scalar, or if any var list needs substitutions.
+ * Break up each var list and set the varcList and varvList arrays. Don't
+ * compile the foreach inline if any var name needs substitutions or isn't
+ * a scalar, or if any var list needs substitutions.
*/
loopIndex = 0;
for (i = 0, tokenPtr = parsePtr->tokenPtr;
i < numWords-1;
- i++, tokenPtr += (tokenPtr->numComponents + 1)) {
- if (i%2 == 1) {
- if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
- code = TCL_OUT_LINE_COMPILE;
- goto done;
- } else {
- /* Lots of copying going on here. Need a ListObj wizard
- * to show a better way. */
-
- Tcl_DString varList;
-
- Tcl_DStringInit(&varList);
- Tcl_DStringAppend(&varList, tokenPtr[1].start,
- tokenPtr[1].size);
- code = Tcl_SplitList(interp, Tcl_DStringValue(&varList),
- &varcList[loopIndex], &varvList[loopIndex]);
- Tcl_DStringFree(&varList);
- if (code != TCL_OK) {
- goto done;
- }
- numVars = varcList[loopIndex];
+ i++, tokenPtr = TokenAfter(tokenPtr)) {
+ Tcl_DString varList;
- /*
- * If the variable list is empty, we can enter an infinite
- * loop when the interpreted version would not. Take care to
- * ensure this does not happen. [Bug 1671138]
- */
+ if (i%2 != 1) {
+ continue;
+ }
+ if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
+ code = TCL_ERROR;
+ goto done;
+ }
- if (numVars == 0) {
- code = TCL_OUT_LINE_COMPILE;
- goto done;
- }
+ /*
+ * Lots of copying going on here. Need a ListObj wizard to show a
+ * better way.
+ */
- for (j = 0; j < numVars; j++) {
- CONST char *varName = varvList[loopIndex][j];
- if (!TclIsLocalScalar(varName, (int) strlen(varName))) {
- code = TCL_OUT_LINE_COMPILE;
- goto done;
- }
- }
+ Tcl_DStringInit(&varList);
+ Tcl_DStringAppend(&varList, tokenPtr[1].start, tokenPtr[1].size);
+ code = Tcl_SplitList(interp, Tcl_DStringValue(&varList),
+ &varcList[loopIndex], &varvList[loopIndex]);
+ Tcl_DStringFree(&varList);
+ if (code != TCL_OK) {
+ code = TCL_ERROR;
+ goto done;
+ }
+ numVars = varcList[loopIndex];
+
+ /*
+ * If the variable list is empty, we can enter an infinite loop when
+ * the interpreted version would not. Take care to ensure this does
+ * not happen. [Bug 1671138]
+ */
+
+ if (numVars == 0) {
+ code = TCL_ERROR;
+ goto done;
+ }
+
+ for (j = 0; j < numVars; j++) {
+ const char *varName = varvList[loopIndex][j];
+
+ if (!TclIsLocalScalar(varName, (int) strlen(varName))) {
+ code = TCL_ERROR;
+ goto done;
}
- loopIndex++;
}
+ loopIndex++;
}
/*
- * We will compile the foreach command.
- * Reserve (numLists + 1) temporary variables:
+ * We will compile the foreach command. Reserve (numLists + 1) temporary
+ * variables:
* - numLists temps to hold each value list
* - 1 temp for the loop counter (index of next element in each list)
+ *
* At this time we don't try to reuse temporaries; if there are two
* nonoverlapping foreach loops, they don't share any temps.
*/
+ code = TCL_OK;
firstValueTemp = -1;
for (loopIndex = 0; loopIndex < numLists; loopIndex++) {
tempVar = TclFindCompiledLocal(NULL, /*nameChars*/ 0,
- /*create*/ 1, /*flags*/ VAR_SCALAR, procPtr);
+ /*create*/ 1, procPtr);
if (loopIndex == 0) {
firstValueTemp = tempVar;
}
}
loopCtTemp = TclFindCompiledLocal(NULL, /*nameChars*/ 0,
- /*create*/ 1, /*flags*/ VAR_SCALAR, procPtr);
-
+ /*create*/ 1, procPtr);
+
/*
* Create and initialize the ForeachInfo and ForeachVarList data
* structures describing this command. Then create a AuxData record
@@ -921,7 +1768,7 @@ TclCompileForeachCmd(interp, parsePtr, envPtr)
*/
infoPtr = (ForeachInfo *) ckalloc((unsigned)
- (sizeof(ForeachInfo) + (numLists * sizeof(ForeachVarList *))));
+ sizeof(ForeachInfo) + numLists*sizeof(ForeachVarList *));
infoPtr->numLists = numLists;
infoPtr->firstValueTemp = firstValueTemp;
infoPtr->loopCtTemp = loopCtTemp;
@@ -929,36 +1776,36 @@ TclCompileForeachCmd(interp, parsePtr, envPtr)
ForeachVarList *varListPtr;
numVars = varcList[loopIndex];
varListPtr = (ForeachVarList *) ckalloc((unsigned)
- sizeof(ForeachVarList) + (numVars * sizeof(int)));
+ sizeof(ForeachVarList) + numVars*sizeof(int));
varListPtr->numVars = numVars;
for (j = 0; j < numVars; j++) {
- CONST char *varName = varvList[loopIndex][j];
+ const char *varName = varvList[loopIndex][j];
int nameChars = strlen(varName);
+
varListPtr->varIndexes[j] = TclFindCompiledLocal(varName,
- nameChars, /*create*/ 1, /*flags*/ VAR_SCALAR, procPtr);
+ nameChars, /*create*/ 1, procPtr);
}
infoPtr->varLists[loopIndex] = varListPtr;
}
- infoIndex = TclCreateAuxData((ClientData) infoPtr, &tclForeachInfoType, envPtr);
+ infoIndex = TclCreateAuxData(infoPtr, &tclForeachInfoType, envPtr);
+
+ /*
+ * Create an exception record to handle [break] and [continue].
+ */
+
+ range = DeclareExceptionRange(envPtr, LOOP_EXCEPTION_RANGE);
/*
* Evaluate then store each value list in the associated temporary.
*/
- range = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr);
-
loopIndex = 0;
for (i = 0, tokenPtr = parsePtr->tokenPtr;
i < numWords-1;
- i++, tokenPtr += (tokenPtr->numComponents + 1)) {
+ i++, tokenPtr = TokenAfter(tokenPtr)) {
if ((i%2 == 0) && (i > 0)) {
SetLineInformation (i);
- code = TclCompileTokens(interp, tokenPtr+1,
- tokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- goto done;
- }
-
+ CompileTokens(envPtr, tokenPtr, interp);
tempVar = (firstValueTemp + loopIndex);
if (tempVar <= 255) {
TclEmitInstInt1(INST_STORE_SCALAR1, tempVar, envPtr);
@@ -975,50 +1822,36 @@ TclCompileForeachCmd(interp, parsePtr, envPtr)
*/
TclEmitInstInt4(INST_FOREACH_START4, infoIndex, envPtr);
-
+
/*
* Top of loop code: assign each loop variable and check whether
* to terminate the loop.
*/
- envPtr->exceptArrayPtr[range].continueOffset =
- (envPtr->codeNext - envPtr->codeStart);
+ ExceptionRangeTarget(envPtr, range, continueOffset);
TclEmitInstInt4(INST_FOREACH_STEP4, infoIndex, envPtr);
TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpFalseFixup);
-
+
/*
* Inline compile the loop body.
*/
SetLineInformation (bodyIndex);
- envPtr->exceptArrayPtr[range].codeOffset =
- (envPtr->codeNext - envPtr->codeStart);
- code = TclCompileCmdWord(interp, bodyTokenPtr+1,
- bodyTokenPtr->numComponents, envPtr);
+ ExceptionRangeStarts(envPtr, range);
+ CompileBody(envPtr, bodyTokenPtr, interp);
+ ExceptionRangeEnds(envPtr, range);
envPtr->currStackDepth = savedStackDepth + 1;
- if (code != TCL_OK) {
- if (code == TCL_ERROR) {
- sprintf(buffer, "\n (\"foreach\" body line %d)",
- interp->errorLine);
- Tcl_AddObjErrorInfo(interp, buffer, -1);
- }
- goto done;
- }
- envPtr->exceptArrayPtr[range].numCodeBytes =
- (envPtr->codeNext - envPtr->codeStart)
- - envPtr->exceptArrayPtr[range].codeOffset;
TclEmitOpcode(INST_POP, envPtr);
-
+
/*
- * Jump back to the test at the top of the loop. Generate a 4 byte jump
- * if the distance to the test is > 120 bytes. This is conservative and
+ * Jump back to the test at the top of the loop. Generate a 4 byte jump if
+ * the distance to the test is > 120 bytes. This is conservative and
* ensures that we won't have to replace this jump if we later need to
* replace the ifFalse jump with a 4 byte jump.
*/
- jumpBackOffset = (envPtr->codeNext - envPtr->codeStart);
- jumpBackDist =
- (jumpBackOffset - envPtr->exceptArrayPtr[range].continueOffset);
+ jumpBackOffset = CurrentOffset(envPtr);
+ jumpBackDist = jumpBackOffset-envPtr->exceptArrayPtr[range].continueOffset;
if (jumpBackDist > 120) {
TclEmitInstInt4(INST_JUMP4, -jumpBackDist, envPtr);
} else {
@@ -1029,9 +1862,7 @@ TclCompileForeachCmd(interp, parsePtr, envPtr)
* Fix the target of the jump after the foreach_step test.
*/
- jumpDist = (envPtr->codeNext - envPtr->codeStart)
- - jumpFalseFixup.codeOffset;
- if (TclFixupForwardJump(envPtr, &jumpFalseFixup, jumpDist, 127)) {
+ if (TclFixupForwardJumpToHere(envPtr, &jumpFalseFixup, 127)) {
/*
* Update the loop body's starting PC offset since it moved down.
*/
@@ -1057,28 +1888,24 @@ TclCompileForeachCmd(interp, parsePtr, envPtr)
* Set the loop's break target.
*/
- envPtr->exceptArrayPtr[range].breakOffset =
- (envPtr->codeNext - envPtr->codeStart);
-
+ ExceptionRangeTarget(envPtr, range, breakOffset);
+
/*
* The foreach command's result is an empty string.
*/
envPtr->currStackDepth = savedStackDepth;
- TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
+ PushLiteral(envPtr, "", 0);
envPtr->currStackDepth = savedStackDepth + 1;
- done:
+ done:
for (loopIndex = 0; loopIndex < numLists; loopIndex++) {
- if (varvList[loopIndex] != (CONST char **) NULL) {
+ if (varvList[loopIndex] != NULL) {
ckfree((char *) varvList[loopIndex]);
}
}
- if (varcList != varcListStaticSpace) {
- ckfree((char *) varcList);
- ckfree((char *) varvList);
- }
- envPtr->exceptDepth--;
+ TclStackFree(interp, (void *)varvList);
+ TclStackFree(interp, varcList);
return code;
}
@@ -1087,8 +1914,8 @@ TclCompileForeachCmd(interp, parsePtr, envPtr)
*
* DupForeachInfo --
*
- * This procedure duplicates a ForeachInfo structure created as
- * auxiliary data during the compilation of a foreach command.
+ * This procedure duplicates a ForeachInfo structure created as auxiliary
+ * data during the compilation of a foreach command.
*
* Results:
* A pointer to a newly allocated copy of the existing ForeachInfo
@@ -1096,42 +1923,41 @@ TclCompileForeachCmd(interp, parsePtr, envPtr)
*
* Side effects:
* Storage for the copied ForeachInfo record is allocated. If the
- * original ForeachInfo structure pointed to any ForeachVarList
- * records, these structures are also copied and pointers to them
- * are stored in the new ForeachInfo record.
+ * original ForeachInfo structure pointed to any ForeachVarList records,
+ * these structures are also copied and pointers to them are stored in
+ * the new ForeachInfo record.
*
*----------------------------------------------------------------------
*/
static ClientData
-DupForeachInfo(clientData)
- ClientData clientData; /* The foreach command's compilation
- * auxiliary data to duplicate. */
+DupForeachInfo(
+ ClientData clientData) /* The foreach command's compilation auxiliary
+ * data to duplicate. */
{
- register ForeachInfo *srcPtr = (ForeachInfo *) clientData;
+ register ForeachInfo *srcPtr = clientData;
ForeachInfo *dupPtr;
register ForeachVarList *srcListPtr, *dupListPtr;
- int numLists = srcPtr->numLists;
- int numVars, i, j;
-
+ int numVars, i, j, numLists = srcPtr->numLists;
+
dupPtr = (ForeachInfo *) ckalloc((unsigned)
- (sizeof(ForeachInfo) + (numLists * sizeof(ForeachVarList *))));
+ sizeof(ForeachInfo) + numLists*sizeof(ForeachVarList *));
dupPtr->numLists = numLists;
dupPtr->firstValueTemp = srcPtr->firstValueTemp;
dupPtr->loopCtTemp = srcPtr->loopCtTemp;
-
+
for (i = 0; i < numLists; i++) {
srcListPtr = srcPtr->varLists[i];
numVars = srcListPtr->numVars;
dupListPtr = (ForeachVarList *) ckalloc((unsigned)
- sizeof(ForeachVarList) + numVars*sizeof(int));
+ sizeof(ForeachVarList) + numVars*sizeof(int));
dupListPtr->numVars = numVars;
for (j = 0; j < numVars; j++) {
dupListPtr->varIndexes[j] = srcListPtr->varIndexes[j];
}
dupPtr->varLists[i] = dupListPtr;
}
- return (ClientData) dupPtr;
+ return dupPtr;
}
/*
@@ -1154,11 +1980,11 @@ DupForeachInfo(clientData)
*/
static void
-FreeForeachInfo(clientData)
- ClientData clientData; /* The foreach command's compilation
- * auxiliary data to free. */
+FreeForeachInfo(
+ ClientData clientData) /* The foreach command's compilation auxiliary
+ * data to free. */
{
- register ForeachInfo *infoPtr = (ForeachInfo *) clientData;
+ register ForeachInfo *infoPtr = clientData;
register ForeachVarList *listPtr;
int numLists = infoPtr->numLists;
register int i;
@@ -1173,58 +1999,111 @@ FreeForeachInfo(clientData)
/*
*----------------------------------------------------------------------
*
+ * PrintForeachInfo --
+ *
+ * Function to write a human-readable representation of a ForeachInfo
+ * structure to stdout for debugging.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+PrintForeachInfo(
+ ClientData clientData,
+ Tcl_Obj *appendObj,
+ ByteCode *codePtr,
+ unsigned int pcOffset)
+{
+ register ForeachInfo *infoPtr = clientData;
+ register ForeachVarList *varsPtr;
+ int i, j;
+
+ Tcl_AppendToObj(appendObj, "data=[", -1);
+
+ for (i=0 ; i<infoPtr->numLists ; i++) {
+ if (i) {
+ Tcl_AppendToObj(appendObj, ", ", -1);
+ }
+ Tcl_AppendPrintfToObj(appendObj, "%%v%u",
+ (unsigned) (infoPtr->firstValueTemp + i));
+ }
+ Tcl_AppendPrintfToObj(appendObj, "], loop=%%v%u",
+ (unsigned) infoPtr->loopCtTemp);
+ for (i=0 ; i<infoPtr->numLists ; i++) {
+ if (i) {
+ Tcl_AppendToObj(appendObj, ",", -1);
+ }
+ Tcl_AppendPrintfToObj(appendObj, "\n\t\t it%%v%u\t[",
+ (unsigned) (infoPtr->firstValueTemp + i));
+ varsPtr = infoPtr->varLists[i];
+ for (j=0 ; j<varsPtr->numVars ; j++) {
+ if (j) {
+ Tcl_AppendToObj(appendObj, ", ", -1);
+ }
+ Tcl_AppendPrintfToObj(appendObj, "%%v%u",
+ (unsigned) varsPtr->varIndexes[j]);
+ }
+ Tcl_AppendToObj(appendObj, "]", -1);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TclCompileIfCmd --
*
* Procedure called to compile the "if" command.
*
* Results:
- * The return value is a standard Tcl result, which is TCL_OK if
- * compilation was successful. If an error occurs then the
- * interpreter's result contains a standard error message and TCL_ERROR
- * is returned. If the command is too complex for TclCompileIfCmd,
- * TCL_OUT_LINE_COMPILE is returned indicating that the if command
- * should be compiled "out of line" by emitting code to invoke its
- * command procedure at runtime.
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
*
* Side effects:
- * Instructions are added to envPtr to execute the "if" command
- * at runtime.
+ * Instructions are added to envPtr to execute the "if" command at
+ * runtime.
*
*----------------------------------------------------------------------
*/
+
int
-TclCompileIfCmd(interp, parsePtr, envPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Parse *parsePtr; /* Points to a parse structure for the
- * command created by Tcl_ParseCommand. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
+TclCompileIfCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
{
JumpFixupArray jumpFalseFixupArray;
/* Used to fix the ifFalse jump after each
* test when its target PC is determined. */
JumpFixupArray jumpEndFixupArray;
- /* Used to fix the jump after each "then"
- * body to the end of the "if" when that PC
- * is determined. */
+ /* Used to fix the jump after each "then" body
+ * to the end of the "if" when that PC is
+ * determined. */
Tcl_Token *tokenPtr, *testTokenPtr;
- int jumpDist, jumpFalseDist;
- int jumpIndex = 0; /* avoid compiler warning. */
- int numWords, wordIdx, numBytes, j, code;
- CONST char *word;
- char buffer[100];
+ int jumpIndex = 0; /* Avoid compiler warning. */
+ int jumpFalseDist, numWords, wordIdx, numBytes, j, code;
+ const char *word;
int savedStackDepth = envPtr->currStackDepth;
- /* Saved stack depth at the start of the first
+ /* Saved stack depth at the start of the first
* test; the envPtr current depth is restored
* to this value at the start of each test. */
- int realCond = 1; /* set to 0 for static conditions: "if 0 {..}" */
- int boolVal; /* value of static condition */
- int compileScripts = 1;
-
- DefineLineInformation;
+ int realCond = 1; /* Set to 0 for static conditions:
+ * "if 0 {..}" */
+ int boolVal; /* Value of static condition. */
+ int compileScripts = 1;
+ DefineLineInformation; /* TIP #280 */
/*
- * Only compile the "if" command if all arguments are simple
- * words, in order to insure correct substitution [Bug 219166]
+ * Only compile the "if" command if all arguments are simple words, in
+ * order to insure correct substitution [Bug 219166]
*/
tokenPtr = parsePtr->tokenPtr;
@@ -1233,19 +2112,18 @@ TclCompileIfCmd(interp, parsePtr, envPtr)
for (wordIdx = 0; wordIdx < numWords; wordIdx++) {
if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
- return TCL_OUT_LINE_COMPILE;
+ return TCL_ERROR;
}
- tokenPtr += 2;
+ tokenPtr = TokenAfter(tokenPtr);
}
-
TclInitJumpFixupArray(&jumpFalseFixupArray);
TclInitJumpFixupArray(&jumpEndFixupArray);
code = TCL_OK;
/*
- * Each iteration of this loop compiles one "if expr ?then? body"
- * or "elseif expr ?then? body" clause.
+ * Each iteration of this loop compiles one "if expr ?then? body" or
+ * "elseif expr ?then? body" clause.
*/
tokenPtr = parsePtr->tokenPtr;
@@ -1258,84 +2136,66 @@ TclCompileIfCmd(interp, parsePtr, envPtr)
word = tokenPtr[1].start;
numBytes = tokenPtr[1].size;
if ((tokenPtr == parsePtr->tokenPtr)
- || ((numBytes == 6) && (strncmp(word, "elseif", 6) == 0))) {
- tokenPtr += (tokenPtr->numComponents + 1);
+ || ((numBytes == 6) && (strncmp(word, "elseif", 6) == 0))) {
+ tokenPtr = TokenAfter(tokenPtr);
wordIdx++;
} else {
break;
}
if (wordIdx >= numWords) {
- sprintf(buffer,
- "wrong # args: no expression after \"%.*s\" argument",
- (numBytes > 50 ? 50 : numBytes), word);
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp), buffer, -1);
code = TCL_ERROR;
goto done;
}
/*
- * Compile the test expression then emit the conditional jump
- * around the "then" part.
+ * Compile the test expression then emit the conditional jump around
+ * the "then" part.
*/
-
+
envPtr->currStackDepth = savedStackDepth;
testTokenPtr = tokenPtr;
-
if (realCond) {
/*
- * Find out if the condition is a constant.
+ * Find out if the condition is a constant.
*/
-
+
Tcl_Obj *boolObj = Tcl_NewStringObj(testTokenPtr[1].start,
testTokenPtr[1].size);
Tcl_IncrRefCount(boolObj);
code = Tcl_GetBooleanFromObj(NULL, boolObj, &boolVal);
- Tcl_DecrRefCount(boolObj);
+ TclDecrRefCount(boolObj);
if (code == TCL_OK) {
/*
- * A static condition
+ * A static condition.
*/
+
realCond = 0;
if (!boolVal) {
compileScripts = 0;
}
} else {
- Tcl_ResetResult(interp);
SetLineInformation (wordIdx);
- code = TclCompileExprWords(interp, testTokenPtr, 1, envPtr);
- if (code != TCL_OK) {
- if (code == TCL_ERROR) {
- Tcl_AddObjErrorInfo(interp,
- "\n (\"if\" test expression)", -1);
- }
- goto done;
- }
+ Tcl_ResetResult(interp);
+ TclCompileExprWords(interp, testTokenPtr, 1, envPtr);
if (jumpFalseFixupArray.next >= jumpFalseFixupArray.end) {
TclExpandJumpFixupArray(&jumpFalseFixupArray);
}
jumpIndex = jumpFalseFixupArray.next;
jumpFalseFixupArray.next++;
TclEmitForwardJump(envPtr, TCL_FALSE_JUMP,
- &(jumpFalseFixupArray.fixup[jumpIndex]));
+ jumpFalseFixupArray.fixup+jumpIndex);
}
+ code = TCL_OK;
}
-
/*
* Skip over the optional "then" before the then clause.
*/
- tokenPtr = testTokenPtr + (testTokenPtr->numComponents + 1);
+ tokenPtr = TokenAfter(testTokenPtr);
wordIdx++;
if (wordIdx >= numWords) {
- sprintf(buffer,
- "wrong # args: no script following \"%.*s\" argument",
- (testTokenPtr->size > 50 ? 50 : testTokenPtr->size),
- testTokenPtr->start);
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp), buffer, -1);
code = TCL_ERROR;
goto done;
}
@@ -1343,12 +2203,9 @@ TclCompileIfCmd(interp, parsePtr, envPtr)
word = tokenPtr[1].start;
numBytes = tokenPtr[1].size;
if ((numBytes == 4) && (strncmp(word, "then", 4) == 0)) {
- tokenPtr += (tokenPtr->numComponents + 1);
+ tokenPtr = TokenAfter(tokenPtr);
wordIdx++;
if (wordIdx >= numWords) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "wrong # args: no script following \"then\" argument", -1);
code = TCL_ERROR;
goto done;
}
@@ -1362,85 +2219,72 @@ TclCompileIfCmd(interp, parsePtr, envPtr)
if (compileScripts) {
SetLineInformation (wordIdx);
envPtr->currStackDepth = savedStackDepth;
- code = TclCompileCmdWord(interp, tokenPtr+1,
- tokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- if (code == TCL_ERROR) {
- sprintf(buffer, "\n (\"if\" then script line %d)",
- interp->errorLine);
- Tcl_AddObjErrorInfo(interp, buffer, -1);
- }
- goto done;
- }
+ CompileBody(envPtr, tokenPtr, interp);
}
if (realCond) {
/*
- * Jump to the end of the "if" command. Both jumpFalseFixupArray and
- * jumpEndFixupArray are indexed by "jumpIndex".
+ * Jump to the end of the "if" command. Both jumpFalseFixupArray
+ * and jumpEndFixupArray are indexed by "jumpIndex".
*/
-
+
if (jumpEndFixupArray.next >= jumpEndFixupArray.end) {
TclExpandJumpFixupArray(&jumpEndFixupArray);
}
jumpEndFixupArray.next++;
TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP,
- &(jumpEndFixupArray.fixup[jumpIndex]));
-
+ jumpEndFixupArray.fixup+jumpIndex);
+
/*
- * Fix the target of the jumpFalse after the test. Generate a 4 byte
- * jump if the distance is > 120 bytes. This is conservative, and
- * ensures that we won't have to replace this jump if we later also
- * need to replace the proceeding jump to the end of the "if" with a
- * 4 byte jump.
+ * Fix the target of the jumpFalse after the test. Generate a 4
+ * byte jump if the distance is > 120 bytes. This is conservative,
+ * and ensures that we won't have to replace this jump if we later
+ * also need to replace the proceeding jump to the end of the "if"
+ * with a 4 byte jump.
*/
- jumpDist = (envPtr->codeNext - envPtr->codeStart)
- - jumpFalseFixupArray.fixup[jumpIndex].codeOffset;
- if (TclFixupForwardJump(envPtr,
- &(jumpFalseFixupArray.fixup[jumpIndex]), jumpDist, 120)) {
+ if (TclFixupForwardJumpToHere(envPtr,
+ jumpFalseFixupArray.fixup+jumpIndex, 120)) {
/*
* Adjust the code offset for the proceeding jump to the end
* of the "if" command.
*/
-
+
jumpEndFixupArray.fixup[jumpIndex].codeOffset += 3;
}
} else if (boolVal) {
- /*
- *We were processing an "if 1 {...}"; stop compiling
- * scripts
+ /*
+ * We were processing an "if 1 {...}"; stop compiling scripts.
*/
compileScripts = 0;
} else {
- /*
- *We were processing an "if 0 {...}"; reset so that
- * the rest (elseif, else) is compiled correctly
+ /*
+ * We were processing an "if 0 {...}"; reset so that the rest
+ * (elseif, else) is compiled correctly.
*/
realCond = 1;
compileScripts = 1;
- }
+ }
- tokenPtr += (tokenPtr->numComponents + 1);
+ tokenPtr = TokenAfter(tokenPtr);
wordIdx++;
}
/*
- * Restore the current stack depth in the environment; the
- * "else" clause (or its default) will add 1 to this.
+ * Restore the current stack depth in the environment; the "else" clause
+ * (or its default) will add 1 to this.
*/
envPtr->currStackDepth = savedStackDepth;
/*
- * Check for the optional else clause. Do not compile
- * anything if this was an "if 1 {...}" case.
+ * Check for the optional else clause. Do not compile anything if this was
+ * an "if 1 {...}" case.
*/
- if ((wordIdx < numWords)
- && (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD)) {
+ if ((wordIdx < numWords) && (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD)) {
/*
* There is an else clause. Skip over the optional "else" word.
*/
@@ -1448,12 +2292,9 @@ TclCompileIfCmd(interp, parsePtr, envPtr)
word = tokenPtr[1].start;
numBytes = tokenPtr[1].size;
if ((numBytes == 4) && (strncmp(word, "else", 4) == 0)) {
- tokenPtr += (tokenPtr->numComponents + 1);
+ tokenPtr = TokenAfter(tokenPtr);
wordIdx++;
if (wordIdx >= numWords) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "wrong # args: no script following \"else\" argument", -1);
code = TCL_ERROR;
goto done;
}
@@ -1463,28 +2304,17 @@ TclCompileIfCmd(interp, parsePtr, envPtr)
/*
* Compile the else command body.
*/
+
SetLineInformation (wordIdx);
- code = TclCompileCmdWord(interp, tokenPtr+1,
- tokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- if (code == TCL_ERROR) {
- sprintf(buffer, "\n (\"if\" else script line %d)",
- interp->errorLine);
- Tcl_AddObjErrorInfo(interp, buffer, -1);
- }
- goto done;
- }
+ CompileBody(envPtr, tokenPtr, interp);
}
/*
* Make sure there are no words after the else clause.
*/
-
+
wordIdx++;
if (wordIdx < numWords) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "wrong # args: extra words after \"else\" clause in \"if\" command", -1);
code = TCL_ERROR;
goto done;
}
@@ -1494,28 +2324,27 @@ TclCompileIfCmd(interp, parsePtr, envPtr)
*/
if (compileScripts) {
- TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
+ PushLiteral(envPtr, "", 0);
}
}
/*
* Fix the unconditional jumps to the end of the "if" command.
*/
-
+
for (j = jumpEndFixupArray.next; j > 0; j--) {
- jumpIndex = (j - 1); /* i.e. process the closest jump first */
- jumpDist = (envPtr->codeNext - envPtr->codeStart)
- - jumpEndFixupArray.fixup[jumpIndex].codeOffset;
- if (TclFixupForwardJump(envPtr,
- &(jumpEndFixupArray.fixup[jumpIndex]), jumpDist, 127)) {
+ jumpIndex = (j - 1); /* i.e. process the closest jump first. */
+ if (TclFixupForwardJumpToHere(envPtr,
+ jumpEndFixupArray.fixup+jumpIndex, 127)) {
/*
- * Adjust the immediately preceeding "ifFalse" jump. We moved
- * it's target (just after this jump) down three bytes.
+ * Adjust the immediately preceeding "ifFalse" jump. We moved it's
+ * target (just after this jump) down three bytes.
*/
unsigned char *ifFalsePc = envPtr->codeStart
- + jumpFalseFixupArray.fixup[jumpIndex].codeOffset;
+ + jumpFalseFixupArray.fixup[jumpIndex].codeOffset;
unsigned char opCode = *ifFalsePc;
+
if (opCode == INST_JUMP_FALSE1) {
jumpFalseDist = TclGetInt1AtPtr(ifFalsePc + 1);
jumpFalseDist += 3;
@@ -1525,7 +2354,7 @@ TclCompileIfCmd(interp, parsePtr, envPtr)
jumpFalseDist += 3;
TclStoreInt4AtPtr(jumpFalseDist, (ifFalsePc + 1));
} else {
- panic("TclCompileIfCmd: unexpected opcode updating ifFalse jump");
+ Tcl_Panic("TclCompileIfCmd: unexpected opcode \"%d\" updating ifFalse jump", (int) opCode);
}
}
}
@@ -1534,7 +2363,7 @@ TclCompileIfCmd(interp, parsePtr, envPtr)
* Free the jumpFixupArray array if malloc'ed storage was used.
*/
- done:
+ done:
envPtr->currStackDepth = savedStackDepth + 1;
TclFreeJumpFixupArray(&jumpFalseFixupArray);
TclFreeJumpFixupArray(&jumpEndFixupArray);
@@ -1549,50 +2378,37 @@ TclCompileIfCmd(interp, parsePtr, envPtr)
* Procedure called to compile the "incr" command.
*
* Results:
- * The return value is a standard Tcl result, which is TCL_OK if
- * compilation was successful. If an error occurs then the
- * interpreter's result contains a standard error message and TCL_ERROR
- * is returned. If the command is too complex for TclCompileIncrCmd,
- * TCL_OUT_LINE_COMPILE is returned indicating that the incr command
- * should be compiled "out of line" by emitting code to invoke its
- * command procedure at runtime.
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
*
* Side effects:
- * Instructions are added to envPtr to execute the "incr" command
- * at runtime.
+ * Instructions are added to envPtr to execute the "incr" command at
+ * runtime.
*
*----------------------------------------------------------------------
*/
int
-TclCompileIncrCmd(interp, parsePtr, envPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Parse *parsePtr; /* Points to a parse structure for the
- * command created by Tcl_ParseCommand. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
+TclCompileIncrCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
{
Tcl_Token *varTokenPtr, *incrTokenPtr;
int simpleVarName, isScalar, localIndex, haveImmValue, immValue;
- int code = TCL_OK;
-
- DefineLineInformation;
+ DefineLineInformation; /* TIP #280 */
if ((parsePtr->numWords != 2) && (parsePtr->numWords != 3)) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "wrong # args: should be \"incr varName ?increment?\"", -1);
return TCL_ERROR;
}
- varTokenPtr = parsePtr->tokenPtr
- + (parsePtr->tokenPtr->numComponents + 1);
+ varTokenPtr = TokenAfter(parsePtr->tokenPtr);
- code = TclPushVarNameWord(interp, varTokenPtr, envPtr,
- (TCL_NO_LARGE_INDEX | TCL_CREATE_VAR),
- &localIndex, &simpleVarName, &isScalar, 1);
- if (code != TCL_OK) {
- goto done;
- }
+ PushVarNameWord(interp, varTokenPtr, envPtr, TCL_NO_LARGE_INDEX|TCL_CREATE_VAR,
+ &localIndex, &simpleVarName, &isScalar, 1);
/*
* If an increment is given, push it, but see first if it's a small
@@ -1602,44 +2418,29 @@ TclCompileIncrCmd(interp, parsePtr, envPtr)
haveImmValue = 0;
immValue = 1;
if (parsePtr->numWords == 3) {
- incrTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
+ incrTokenPtr = TokenAfter(varTokenPtr);
if (incrTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
- CONST char *word = incrTokenPtr[1].start;
+ const char *word = incrTokenPtr[1].start;
int numBytes = incrTokenPtr[1].size;
-
- /*
- * Note there is a danger that modifying the string could have
- * undesirable side effects. In this case, TclLooksLikeInt has
- * no dependencies on shared strings so we should be safe.
- */
-
- if (TclLooksLikeInt(word, numBytes)) {
- int code;
- Tcl_Obj *intObj = Tcl_NewStringObj(word, numBytes);
- Tcl_IncrRefCount(intObj);
- code = Tcl_GetIntFromObj(NULL, intObj, &immValue);
- Tcl_DecrRefCount(intObj);
- if ((code == TCL_OK)
- && (-127 <= immValue) && (immValue <= 127)) {
- haveImmValue = 1;
- }
+ int code;
+ Tcl_Obj *intObj = Tcl_NewStringObj(word, numBytes);
+ Tcl_IncrRefCount(intObj);
+ code = TclGetIntFromObj(NULL, intObj, &immValue);
+ TclDecrRefCount(intObj);
+ if ((code == TCL_OK) && (-127 <= immValue) && (immValue <= 127)) {
+ haveImmValue = 1;
}
if (!haveImmValue) {
- TclEmitPush(
- TclRegisterNewLiteral(envPtr, word, numBytes), envPtr);
+ PushLiteral(envPtr, word, numBytes);
}
} else {
SetLineInformation (2);
- code = TclCompileTokens(interp, incrTokenPtr+1,
- incrTokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- goto done;
- }
+ CompileTokens(envPtr, incrTokenPtr, interp);
}
- } else { /* no incr amount given so use 1 */
+ } else { /* No incr amount given so use 1. */
haveImmValue = 1;
}
-
+
/*
* Emit the instruction to increment the variable.
*/
@@ -1676,16 +2477,15 @@ TclCompileIncrCmd(interp, parsePtr, envPtr)
}
}
}
- } else { /* non-simple variable name */
+ } else { /* Non-simple variable name. */
if (haveImmValue) {
TclEmitInstInt1(INST_INCR_STK_IMM, immValue, envPtr);
} else {
TclEmitOpcode(INST_INCR_STK, envPtr);
}
}
-
- done:
- return code;
+
+ return TCL_OK;
}
/*
@@ -1696,53 +2496,47 @@ TclCompileIncrCmd(interp, parsePtr, envPtr)
* Procedure called to compile the "lappend" command.
*
* Results:
- * The return value is a standard Tcl result, which is normally TCL_OK
- * unless there was an error while parsing string. If an error occurs
- * then the interpreter's result contains a standard error message. If
- * compilation fails because the command requires a second level of
- * substitutions, TCL_OUT_LINE_COMPILE is returned indicating that the
- * command should be compiled "out of line" by emitting code to
- * invoke its command procedure (Tcl_LappendObjCmd) at runtime.
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
*
* Side effects:
- * Instructions are added to envPtr to execute the "lappend" command
- * at runtime.
+ * Instructions are added to envPtr to execute the "lappend" command at
+ * runtime.
*
*----------------------------------------------------------------------
*/
int
-TclCompileLappendCmd(interp, parsePtr, envPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Parse *parsePtr; /* Points to a parse structure for the
- * command created by Tcl_ParseCommand. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
+TclCompileLappendCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
{
- Tcl_Token *varTokenPtr, *valueTokenPtr;
+ Tcl_Token *varTokenPtr;
int simpleVarName, isScalar, localIndex, numWords;
- int code = TCL_OK;
-
- DefineLineInformation;
+ DefineLineInformation; /* TIP #280 */
/*
* If we're not in a procedure, don't compile.
*/
+
if (envPtr->procPtr == NULL) {
- return TCL_OUT_LINE_COMPILE;
+ return TCL_ERROR;
}
numWords = parsePtr->numWords;
if (numWords == 1) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "wrong # args: should be \"lappend varName ?value value ...?\"", -1);
return TCL_ERROR;
}
if (numWords != 3) {
/*
- * LAPPEND instructions currently only handle one value appends
+ * LAPPEND instructions currently only handle one value appends.
*/
- return TCL_OUT_LINE_COMPILE;
+
+ return TCL_ERROR;
}
/*
@@ -1750,36 +2544,22 @@ TclCompileLappendCmd(interp, parsePtr, envPtr)
* need to emit code to compute and push the name at runtime. We use a
* frame slot (entry in the array of local vars) if we are compiling a
* procedure body and if the name is simple text that does not include
- * namespace qualifiers.
+ * namespace qualifiers.
*/
- varTokenPtr = parsePtr->tokenPtr
- + (parsePtr->tokenPtr->numComponents + 1);
+ varTokenPtr = TokenAfter(parsePtr->tokenPtr);
- code = TclPushVarNameWord(interp, varTokenPtr, envPtr, TCL_CREATE_VAR,
- &localIndex, &simpleVarName, &isScalar, 1);
- if (code != TCL_OK) {
- goto done;
- }
+ PushVarNameWord(interp, varTokenPtr, envPtr, TCL_CREATE_VAR,
+ &localIndex, &simpleVarName, &isScalar, 1);
/*
- * If we are doing an assignment, push the new value.
- * In the no values case, create an empty object.
+ * If we are doing an assignment, push the new value. In the no values
+ * case, create an empty object.
*/
if (numWords > 2) {
- valueTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
- if (valueTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
- TclEmitPush(TclRegisterNewLiteral(envPtr,
- valueTokenPtr[1].start, valueTokenPtr[1].size), envPtr);
- } else {
- SetLineInformation (2);
- code = TclCompileTokens(interp, valueTokenPtr+1,
- valueTokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- goto done;
- }
- }
+ Tcl_Token *valueTokenPtr = TokenAfter(varTokenPtr);
+ CompileWord(envPtr, valueTokenPtr, interp, 2);
}
/*
@@ -1790,112 +2570,239 @@ TclCompileLappendCmd(interp, parsePtr, envPtr)
* The *_STK opcodes should be refactored to make better use of existing
* LOAD/STORE instructions.
*/
+
if (simpleVarName) {
if (isScalar) {
- if (localIndex >= 0) {
- if (localIndex <= 255) {
- TclEmitInstInt1(INST_LAPPEND_SCALAR1, localIndex, envPtr);
- } else {
- TclEmitInstInt4(INST_LAPPEND_SCALAR4, localIndex, envPtr);
- }
- } else {
+ if (localIndex < 0) {
TclEmitOpcode(INST_LAPPEND_STK, envPtr);
+ } else if (localIndex <= 255) {
+ TclEmitInstInt1(INST_LAPPEND_SCALAR1, localIndex, envPtr);
+ } else {
+ TclEmitInstInt4(INST_LAPPEND_SCALAR4, localIndex, envPtr);
}
} else {
- if (localIndex >= 0) {
- if (localIndex <= 255) {
- TclEmitInstInt1(INST_LAPPEND_ARRAY1, localIndex, envPtr);
- } else {
- TclEmitInstInt4(INST_LAPPEND_ARRAY4, localIndex, envPtr);
- }
- } else {
+ if (localIndex < 0) {
TclEmitOpcode(INST_LAPPEND_ARRAY_STK, envPtr);
+ } else if (localIndex <= 255) {
+ TclEmitInstInt1(INST_LAPPEND_ARRAY1, localIndex, envPtr);
+ } else {
+ TclEmitInstInt4(INST_LAPPEND_ARRAY4, localIndex, envPtr);
}
}
} else {
TclEmitOpcode(INST_LAPPEND_STK, envPtr);
}
- done:
- return code;
+ return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * TclCompileLindexCmd --
+ * TclCompileLassignCmd --
*
- * Procedure called to compile the "lindex" command.
+ * Procedure called to compile the "lassign" command.
*
* Results:
- * The return value is a standard Tcl result, which is TCL_OK if the
- * compilation was successful. If the command cannot be byte-compiled,
- * TCL_OUT_LINE_COMPILE is returned. If an error occurs then the
- * interpreter's result contains an error message, and TCL_ERROR is
- * returned.
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
*
* Side effects:
- * Instructions are added to envPtr to execute the "lindex" command
- * at runtime.
+ * Instructions are added to envPtr to execute the "lassign" command at
+ * runtime.
*
*----------------------------------------------------------------------
*/
int
-TclCompileLindexCmd(interp, parsePtr, envPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Parse *parsePtr; /* Points to a parse structure for the
- * command created by Tcl_ParseCommand. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
+TclCompileLassignCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
{
- Tcl_Token *varTokenPtr;
- int code, i;
- int numWords;
-
- DefineLineInformation;
+ Tcl_Token *tokenPtr;
+ int simpleVarName, isScalar, localIndex, numWords, idx;
+ DefineLineInformation; /* TIP #280 */
numWords = parsePtr->numWords;
/*
- * Quit if too few args
+ * Check for command syntax error, but we'll punt that to runtime.
*/
- if ( numWords <= 1 ) {
- return TCL_OUT_LINE_COMPILE;
+ if (numWords < 3) {
+ return TCL_ERROR;
}
- varTokenPtr = parsePtr->tokenPtr
- + (parsePtr->tokenPtr->numComponents + 1);
-
/*
- * Push the operands onto the stack.
+ * Generate code to push list being taken apart by [lassign].
*/
-
- for ( i = 1 ; i < numWords ; i++ ) {
- if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
- TclEmitPush(
- TclRegisterNewLiteral( envPtr, varTokenPtr[1].start,
- varTokenPtr[1].size), envPtr);
- } else {
- SetLineInformation (i);
- code = TclCompileTokens(interp, varTokenPtr+1,
- varTokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- return code;
+
+ tokenPtr = TokenAfter(parsePtr->tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, 1);
+
+ /*
+ * Generate code to assign values from the list to variables.
+ */
+
+ for (idx=0 ; idx<numWords-2 ; idx++) {
+ tokenPtr = TokenAfter(tokenPtr);
+
+ /*
+ * Generate the next variable name.
+ */
+
+ PushVarNameWord(interp, tokenPtr, envPtr, TCL_CREATE_VAR, &localIndex,
+ &simpleVarName, &isScalar, idx+2);
+
+ /*
+ * Emit instructions to get the idx'th item out of the list value on
+ * the stack and assign it to the variable.
+ */
+
+ if (simpleVarName) {
+ if (isScalar) {
+ if (localIndex >= 0) {
+ TclEmitOpcode(INST_DUP, envPtr);
+ TclEmitInstInt4(INST_LIST_INDEX_IMM, idx, envPtr);
+ if (localIndex <= 255) {
+ TclEmitInstInt1(INST_STORE_SCALAR1,localIndex,envPtr);
+ } else {
+ TclEmitInstInt4(INST_STORE_SCALAR4,localIndex,envPtr);
+ }
+ } else {
+ TclEmitInstInt4(INST_OVER, 1, envPtr);
+ TclEmitInstInt4(INST_LIST_INDEX_IMM, idx, envPtr);
+ TclEmitOpcode(INST_STORE_SCALAR_STK, envPtr);
+ }
+ } else {
+ if (localIndex >= 0) {
+ TclEmitInstInt4(INST_OVER, 1, envPtr);
+ TclEmitInstInt4(INST_LIST_INDEX_IMM, idx, envPtr);
+ if (localIndex <= 255) {
+ TclEmitInstInt1(INST_STORE_ARRAY1, localIndex, envPtr);
+ } else {
+ TclEmitInstInt4(INST_STORE_ARRAY4, localIndex, envPtr);
+ }
+ } else {
+ TclEmitInstInt4(INST_OVER, 2, envPtr);
+ TclEmitInstInt4(INST_LIST_INDEX_IMM, idx, envPtr);
+ TclEmitOpcode(INST_STORE_ARRAY_STK, envPtr);
+ }
}
+ } else {
+ TclEmitInstInt4(INST_OVER, 1, envPtr);
+ TclEmitInstInt4(INST_LIST_INDEX_IMM, idx, envPtr);
+ TclEmitOpcode(INST_STORE_STK, envPtr);
}
- varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
+ TclEmitOpcode(INST_POP, envPtr);
}
-
+
/*
- * Emit INST_LIST_INDEX if objc==3, or INST_LIST_INDEX_MULTI
- * if there are multiple index args.
+ * Generate code to leave the rest of the list on the stack.
*/
- if ( numWords == 3 ) {
- TclEmitOpcode( INST_LIST_INDEX, envPtr );
+ TclEmitInstInt4(INST_LIST_RANGE_IMM, idx, envPtr);
+ TclEmitInt4(-2, envPtr); /* -2 == "end" */
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileLindexCmd --
+ *
+ * Procedure called to compile the "lindex" command.
+ *
+ * Results:
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
+ *
+ * Side effects:
+ * Instructions are added to envPtr to execute the "lindex" command at
+ * runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileLindexCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ Tcl_Token *idxTokenPtr, *valTokenPtr;
+ int i, numWords = parsePtr->numWords;
+ DefineLineInformation; /* TIP #280 */
+
+ /*
+ * Quit if too few args.
+ */
+
+ if (numWords <= 1) {
+ return TCL_ERROR;
+ }
+
+ valTokenPtr = TokenAfter(parsePtr->tokenPtr);
+ if (numWords != 3) {
+ goto emitComplexLindex;
+ }
+
+ idxTokenPtr = TokenAfter(valTokenPtr);
+ if (idxTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
+ Tcl_Obj *tmpObj;
+ int idx, result;
+
+ tmpObj = Tcl_NewStringObj(idxTokenPtr[1].start, idxTokenPtr[1].size);
+ result = TclGetIntFromObj(NULL, tmpObj, &idx);
+ TclDecrRefCount(tmpObj);
+
+ if (result == TCL_OK && idx >= 0) {
+ /*
+ * All checks have been completed, and we have exactly this
+ * construct:
+ * lindex <arbitraryValue> <posInt>
+ * This is best compiled as a push of the arbitrary value followed
+ * by an "immediate lindex" which is the most efficient variety.
+ */
+
+ CompileWord(envPtr, valTokenPtr, interp, 1);
+ TclEmitInstInt4(INST_LIST_INDEX_IMM, idx, envPtr);
+ return TCL_OK;
+ }
+
+ /*
+ * If the conversion failed or the value was negative, we just keep on
+ * going with the more complex compilation.
+ */
+ }
+
+ /*
+ * Push the operands onto the stack.
+ */
+
+ emitComplexLindex:
+ for (i=1 ; i<numWords ; i++) {
+ CompileWord(envPtr, valTokenPtr, interp, i);
+ valTokenPtr = TokenAfter(valTokenPtr);
+ }
+
+ /*
+ * Emit INST_LIST_INDEX if objc==3, or INST_LIST_INDEX_MULTI if there are
+ * multiple index args.
+ */
+
+ if (numWords == 3) {
+ TclEmitOpcode(INST_LIST_INDEX, envPtr);
} else {
- TclEmitInstInt4( INST_LIST_INDEX_MULTI, numWords-1, envPtr );
+ TclEmitInstInt4(INST_LIST_INDEX_MULTI, numWords-1, envPtr);
}
return TCL_OK;
@@ -1909,67 +2816,55 @@ TclCompileLindexCmd(interp, parsePtr, envPtr)
* Procedure called to compile the "list" command.
*
* Results:
- * The return value is a standard Tcl result, which is normally TCL_OK
- * unless there was an error while parsing string. If an error occurs
- * then the interpreter's result contains a standard error message. If
- * compilation fails because the command requires a second level of
- * substitutions, TCL_OUT_LINE_COMPILE is returned indicating that the
- * command should be compiled "out of line" by emitting code to
- * invoke its command procedure (Tcl_ListObjCmd) at runtime.
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
*
* Side effects:
- * Instructions are added to envPtr to execute the "list" command
- * at runtime.
+ * Instructions are added to envPtr to execute the "list" command at
+ * runtime.
*
*----------------------------------------------------------------------
*/
int
-TclCompileListCmd(interp, parsePtr, envPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Parse *parsePtr; /* Points to a parse structure for the
- * command created by Tcl_ParseCommand. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
+TclCompileListCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
{
- DefineLineInformation;
+ DefineLineInformation; /* TIP #280 */
/*
* If we're not in a procedure, don't compile.
*/
+
if (envPtr->procPtr == NULL) {
- return TCL_OUT_LINE_COMPILE;
+ return TCL_ERROR;
}
if (parsePtr->numWords == 1) {
/*
- * Empty args case
+ * [list] without arguments just pushes an empty object.
*/
- TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
+ PushLiteral(envPtr, "", 0);
} else {
/*
* Push the all values onto the stack.
*/
+
Tcl_Token *valueTokenPtr;
- int i, code, numWords;
+ int i, numWords;
numWords = parsePtr->numWords;
- valueTokenPtr = parsePtr->tokenPtr
- + (parsePtr->tokenPtr->numComponents + 1);
+ valueTokenPtr = TokenAfter(parsePtr->tokenPtr);
for (i = 1; i < numWords; i++) {
- if (valueTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
- TclEmitPush(TclRegisterNewLiteral(envPtr,
- valueTokenPtr[1].start, valueTokenPtr[1].size), envPtr);
- } else {
- SetLineInformation (i);
- code = TclCompileTokens(interp, valueTokenPtr+1,
- valueTokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- return code;
- }
- }
- valueTokenPtr = valueTokenPtr + (valueTokenPtr->numComponents + 1);
+ CompileWord(envPtr, valueTokenPtr, interp, i);
+ valueTokenPtr = TokenAfter(valueTokenPtr);
}
TclEmitInstInt4(INST_LIST, numWords - 1, envPtr);
}
@@ -1985,54 +2880,34 @@ TclCompileListCmd(interp, parsePtr, envPtr)
* Procedure called to compile the "llength" command.
*
* Results:
- * The return value is a standard Tcl result, which is TCL_OK if the
- * compilation was successful. If the command cannot be byte-compiled,
- * TCL_OUT_LINE_COMPILE is returned. If an error occurs then the
- * interpreter's result contains an error message, and TCL_ERROR is
- * returned.
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
*
* Side effects:
- * Instructions are added to envPtr to execute the "llength" command
- * at runtime.
+ * Instructions are added to envPtr to execute the "llength" command at
+ * runtime.
*
*----------------------------------------------------------------------
*/
int
-TclCompileLlengthCmd(interp, parsePtr, envPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Parse *parsePtr; /* Points to a parse structure for the
- * command created by Tcl_ParseCommand. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
+TclCompileLlengthCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
{
Tcl_Token *varTokenPtr;
- int code;
-
- DefineLineInformation;
+ DefineLineInformation; /* TIP #280 */
if (parsePtr->numWords != 2) {
- Tcl_SetResult(interp, "wrong # args: should be \"llength list\"",
- TCL_STATIC);
return TCL_ERROR;
}
- varTokenPtr = parsePtr->tokenPtr
- + (parsePtr->tokenPtr->numComponents + 1);
+ varTokenPtr = TokenAfter(parsePtr->tokenPtr);
- if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
- /*
- * We could simply count the number of elements here and push
- * that value, but that is too rare a case to waste the code space.
- */
- TclEmitPush(TclRegisterNewLiteral(envPtr, varTokenPtr[1].start,
- varTokenPtr[1].size), envPtr);
- } else {
- SetLineInformation (1);
- code = TclCompileTokens(interp, varTokenPtr+1,
- varTokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- return code;
- }
- }
+ CompileWord(envPtr, varTokenPtr, interp, 1);
TclEmitOpcode(INST_LIST_LENGTH, envPtr);
return TCL_OK;
}
@@ -2045,197 +2920,175 @@ TclCompileLlengthCmd(interp, parsePtr, envPtr)
* Procedure called to compile the "lset" command.
*
* Results:
- * The return value is a standard Tcl result, which is TCL_OK if
- * the compilation was successful. If the "lset" command is too
- * complex for this function, then TCL_OUT_LINE_COMPILE is returned,
- * indicating that the command should be compiled "out of line"
- * (that is, not byte-compiled). If an error occurs, TCL_ERROR is
- * returned, and the interpreter result contains an error message.
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
*
* Side effects:
- * Instructions are added to envPtr to execute the "lset" command
- * at runtime.
+ * Instructions are added to envPtr to execute the "lset" command at
+ * runtime.
*
* The general template for execution of the "lset" command is:
- * (1) Instructions to push the variable name, unless the
- * variable is local to the stack frame.
- * (2) If the variable is an array element, instructions
- * to push the array element name.
- * (3) Instructions to push each of zero or more "index" arguments
- * to the stack, followed with the "newValue" element.
- * (4) Instructions to duplicate the variable name and/or array
- * element name onto the top of the stack, if either was
- * pushed at steps (1) and (2).
- * (5) The appropriate INST_LOAD_* instruction to place the
- * original value of the list variable at top of stack.
+ * (1) Instructions to push the variable name, unless the variable is
+ * local to the stack frame.
+ * (2) If the variable is an array element, instructions to push the
+ * array element name.
+ * (3) Instructions to push each of zero or more "index" arguments to the
+ * stack, followed with the "newValue" element.
+ * (4) Instructions to duplicate the variable name and/or array element
+ * name onto the top of the stack, if either was pushed at steps (1)
+ * and (2).
+ * (5) The appropriate INST_LOAD_* instruction to place the original
+ * value of the list variable at top of stack.
* (6) At this point, the stack contains:
- * varName? arrayElementName? index1 index2 ... newValue oldList
+ * varName? arrayElementName? index1 index2 ... newValue oldList
* The compiler emits one of INST_LSET_FLAT or INST_LSET_LIST
- * according as whether there is exactly one index element (LIST)
- * or either zero or else two or more (FLAT). This instruction
- * removes everything from the stack except for the two names
- * and pushes the new value of the variable.
- * (7) Finally, INST_STORE_* stores the new value in the variable
- * and cleans up the stack.
+ * according as whether there is exactly one index element (LIST) or
+ * either zero or else two or more (FLAT). This instruction removes
+ * everything from the stack except for the two names and pushes the
+ * new value of the variable.
+ * (7) Finally, INST_STORE_* stores the new value in the variable and
+ * cleans up the stack.
*
*----------------------------------------------------------------------
*/
int
-TclCompileLsetCmd( interp, parsePtr, envPtr )
- Tcl_Interp* interp; /* Tcl interpreter for error reporting */
- Tcl_Parse* parsePtr; /* Points to a parse structure for
- * the command */
- CompileEnv* envPtr; /* Holds the resulting instructions */
+TclCompileLsetCmd(
+ Tcl_Interp *interp, /* Tcl interpreter for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the
+ * command. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds the resulting instructions. */
{
-
- int tempDepth; /* Depth used for emitting one part
- * of the code burst. */
- Tcl_Token* varTokenPtr; /* Pointer to the Tcl_Token representing
- * the parse of the variable name */
-
- int result; /* Status return from library calls */
-
- int localIndex; /* Index of var in local var table */
- int simpleVarName; /* Flag == 1 if var name is simple */
- int isScalar; /* Flag == 1 if scalar, 0 if array */
-
+ int tempDepth; /* Depth used for emitting one part of the
+ * code burst. */
+ Tcl_Token *varTokenPtr; /* Pointer to the Tcl_Token representing the
+ * parse of the variable name. */
+ int localIndex; /* Index of var in local var table. */
+ int simpleVarName; /* Flag == 1 if var name is simple. */
+ int isScalar; /* Flag == 1 if scalar, 0 if array. */
int i;
+ DefineLineInformation; /* TIP #280 */
- DefineLineInformation;
+ /*
+ * Check argument count.
+ */
- /* Check argument count */
+ if (parsePtr->numWords < 3) {
+ /*
+ * Fail at run time, not in compilation.
+ */
- if ( parsePtr->numWords < 3 ) {
- /* Fail at run time, not in compilation */
- return TCL_OUT_LINE_COMPILE;
+ return TCL_ERROR;
}
/*
- * Decide if we can use a frame slot for the var/array name or if we
- * need to emit code to compute and push the name at runtime. We use a
- * frame slot (entry in the array of local vars) if we are compiling a
- * procedure body and if the name is simple text that does not include
- * namespace qualifiers.
+ * Decide if we can use a frame slot for the var/array name or if we need
+ * to emit code to compute and push the name at runtime. We use a frame
+ * slot (entry in the array of local vars) if we are compiling a procedure
+ * body and if the name is simple text that does not include namespace
+ * qualifiers.
*/
- varTokenPtr = parsePtr->tokenPtr
- + (parsePtr->tokenPtr->numComponents + 1);
- result = TclPushVarNameWord( interp, varTokenPtr, envPtr,
- TCL_CREATE_VAR, &localIndex, &simpleVarName, &isScalar, 1);
- if (result != TCL_OK) {
- return result;
- }
+ varTokenPtr = TokenAfter(parsePtr->tokenPtr);
+ PushVarNameWord(interp, varTokenPtr, envPtr, TCL_CREATE_VAR,
+ &localIndex, &simpleVarName, &isScalar, 1);
- /* Push the "index" args and the new element value. */
-
- for ( i = 2; i < parsePtr->numWords; ++i ) {
-
- /* Advance to next arg */
-
- varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
-
- /* Push an arg */
+ /*
+ * Push the "index" args and the new element value.
+ */
- if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
- TclEmitPush(TclRegisterNewLiteral( envPtr, varTokenPtr[1].start,
- varTokenPtr[1].size), envPtr);
- } else {
- SetLineInformation (i);
- result = TclCompileTokens(interp, varTokenPtr+1,
- varTokenPtr->numComponents, envPtr);
- if ( result != TCL_OK ) {
- return result;
- }
- }
+ for (i=2 ; i<parsePtr->numWords ; ++i) {
+ varTokenPtr = TokenAfter(varTokenPtr);
+ CompileWord(envPtr, varTokenPtr, interp, i);
}
/*
- * Duplicate the variable name if it's been pushed.
+ * Duplicate the variable name if it's been pushed.
*/
- if ( !simpleVarName || localIndex < 0 ) {
- if ( !simpleVarName || isScalar ) {
+ if (!simpleVarName || localIndex < 0) {
+ if (!simpleVarName || isScalar) {
tempDepth = parsePtr->numWords - 2;
} else {
tempDepth = parsePtr->numWords - 1;
}
- TclEmitInstInt4( INST_OVER, tempDepth, envPtr );
+ TclEmitInstInt4(INST_OVER, tempDepth, envPtr);
}
/*
- * Duplicate an array index if one's been pushed
+ * Duplicate an array index if one's been pushed.
*/
- if ( simpleVarName && !isScalar ) {
- if ( localIndex < 0 ) {
+ if (simpleVarName && !isScalar) {
+ if (localIndex < 0) {
tempDepth = parsePtr->numWords - 1;
} else {
tempDepth = parsePtr->numWords - 2;
}
- TclEmitInstInt4( INST_OVER, tempDepth, envPtr );
+ TclEmitInstInt4(INST_OVER, tempDepth, envPtr);
}
/*
* Emit code to load the variable's value.
*/
- if ( !simpleVarName ) {
- TclEmitOpcode( INST_LOAD_STK, envPtr );
- } else if ( isScalar ) {
- if ( localIndex < 0 ) {
- TclEmitOpcode( INST_LOAD_SCALAR_STK, envPtr );
- } else if ( localIndex < 0x100 ) {
- TclEmitInstInt1( INST_LOAD_SCALAR1, localIndex, envPtr );
+ if (!simpleVarName) {
+ TclEmitOpcode(INST_LOAD_STK, envPtr);
+ } else if (isScalar) {
+ if (localIndex < 0) {
+ TclEmitOpcode(INST_LOAD_SCALAR_STK, envPtr);
+ } else if (localIndex < 0x100) {
+ TclEmitInstInt1(INST_LOAD_SCALAR1, localIndex, envPtr);
} else {
- TclEmitInstInt4( INST_LOAD_SCALAR4, localIndex, envPtr );
+ TclEmitInstInt4(INST_LOAD_SCALAR4, localIndex, envPtr);
}
} else {
- if ( localIndex < 0 ) {
- TclEmitOpcode( INST_LOAD_ARRAY_STK, envPtr );
- } else if ( localIndex < 0x100 ) {
- TclEmitInstInt1( INST_LOAD_ARRAY1, localIndex, envPtr );
+ if (localIndex < 0) {
+ TclEmitOpcode(INST_LOAD_ARRAY_STK, envPtr);
+ } else if (localIndex < 0x100) {
+ TclEmitInstInt1(INST_LOAD_ARRAY1, localIndex, envPtr);
} else {
- TclEmitInstInt4( INST_LOAD_ARRAY4, localIndex, envPtr );
+ TclEmitInstInt4(INST_LOAD_ARRAY4, localIndex, envPtr);
}
}
/*
- * Emit the correct variety of 'lset' instruction
+ * Emit the correct variety of 'lset' instruction.
*/
- if ( parsePtr->numWords == 4 ) {
- TclEmitOpcode( INST_LSET_LIST, envPtr );
+ if (parsePtr->numWords == 4) {
+ TclEmitOpcode(INST_LSET_LIST, envPtr);
} else {
- TclEmitInstInt4( INST_LSET_FLAT, (parsePtr->numWords - 1), envPtr );
+ TclEmitInstInt4(INST_LSET_FLAT, parsePtr->numWords-1, envPtr);
}
/*
- * Emit code to put the value back in the variable
+ * Emit code to put the value back in the variable.
*/
- if ( !simpleVarName ) {
- TclEmitOpcode( INST_STORE_STK, envPtr );
- } else if ( isScalar ) {
- if ( localIndex < 0 ) {
- TclEmitOpcode( INST_STORE_SCALAR_STK, envPtr );
- } else if ( localIndex < 0x100 ) {
- TclEmitInstInt1( INST_STORE_SCALAR1, localIndex, envPtr );
+ if (!simpleVarName) {
+ TclEmitOpcode(INST_STORE_STK, envPtr);
+ } else if (isScalar) {
+ if (localIndex < 0) {
+ TclEmitOpcode(INST_STORE_SCALAR_STK, envPtr);
+ } else if (localIndex < 0x100) {
+ TclEmitInstInt1(INST_STORE_SCALAR1, localIndex, envPtr);
} else {
- TclEmitInstInt4( INST_STORE_SCALAR4, localIndex, envPtr );
+ TclEmitInstInt4(INST_STORE_SCALAR4, localIndex, envPtr);
}
} else {
- if ( localIndex < 0 ) {
- TclEmitOpcode( INST_STORE_ARRAY_STK, envPtr );
- } else if ( localIndex < 0x100 ) {
- TclEmitInstInt1( INST_STORE_ARRAY1, localIndex, envPtr );
+ if (localIndex < 0) {
+ TclEmitOpcode(INST_STORE_ARRAY_STK, envPtr);
+ } else if (localIndex < 0x100) {
+ TclEmitInstInt1(INST_STORE_ARRAY1, localIndex, envPtr);
} else {
- TclEmitInstInt4( INST_STORE_ARRAY4, localIndex, envPtr );
+ TclEmitInstInt4(INST_STORE_ARRAY4, localIndex, envPtr);
}
}
-
- return TCL_OK;
+ return TCL_OK;
}
/*
@@ -2246,193 +3099,155 @@ TclCompileLsetCmd( interp, parsePtr, envPtr )
* Procedure called to compile the "regexp" command.
*
* Results:
- * The return value is a standard Tcl result, which is TCL_OK if
- * the compilation was successful. If the "regexp" command is too
- * complex for this function, then TCL_OUT_LINE_COMPILE is returned,
- * indicating that the command should be compiled "out of line"
- * (that is, not byte-compiled). If an error occurs, TCL_ERROR is
- * returned, and the interpreter result contains an error message.
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
*
* Side effects:
- * Instructions are added to envPtr to execute the "regexp" command
- * at runtime.
+ * Instructions are added to envPtr to execute the "regexp" command at
+ * runtime.
*
*----------------------------------------------------------------------
*/
int
-TclCompileRegexpCmd(interp, parsePtr, envPtr)
- Tcl_Interp* interp; /* Tcl interpreter for error reporting */
- Tcl_Parse* parsePtr; /* Points to a parse structure for
- * the command */
- CompileEnv* envPtr; /* Holds the resulting instructions */
-{
- Tcl_Token *varTokenPtr; /* Pointer to the Tcl_Token representing
- * the parse of the RE or string */
- int i, len, code, nocase, anchorLeft, anchorRight, start;
+TclCompileRegexpCmd(
+ Tcl_Interp *interp, /* Tcl interpreter for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the
+ * command. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds the resulting instructions. */
+{
+ Tcl_Token *varTokenPtr; /* Pointer to the Tcl_Token representing the
+ * parse of the RE or string. */
+ int i, len, nocase, exact, sawLast, simple;
char *str;
-
- DefineLineInformation;
+ DefineLineInformation; /* TIP #280 */
/*
- * We are only interested in compiling simple regexp cases.
- * Currently supported compile cases are:
+ * We are only interested in compiling simple regexp cases. Currently
+ * supported compile cases are:
* regexp ?-nocase? ?--? staticString $var
* regexp ?-nocase? ?--? {^staticString$} $var
*/
+
if (parsePtr->numWords < 3) {
- return TCL_OUT_LINE_COMPILE;
+ return TCL_ERROR;
}
+ simple = 0;
nocase = 0;
+ sawLast = 0;
varTokenPtr = parsePtr->tokenPtr;
/*
- * We only look for -nocase and -- as options. Everything else
- * gets pushed to runtime execution. This is different than regexp's
- * runtime option handling, but satisfies our stricter needs.
+ * We only look for -nocase and -- as options. Everything else gets pushed
+ * to runtime execution. This is different than regexp's runtime option
+ * handling, but satisfies our stricter needs.
*/
+
for (i = 1; i < parsePtr->numWords - 2; i++) {
- varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
+ varTokenPtr = TokenAfter(varTokenPtr);
if (varTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
- /* Not a simple string - punt to runtime. */
- return TCL_OUT_LINE_COMPILE;
+ /*
+ * Not a simple string, so punt to runtime.
+ */
+
+ return TCL_ERROR;
}
str = (char *) varTokenPtr[1].start;
len = varTokenPtr[1].size;
if ((len == 2) && (str[0] == '-') && (str[1] == '-')) {
+ sawLast++;
i++;
break;
- } else if ((len > 1)
- && (strncmp(str, "-nocase", (unsigned) len) == 0)) {
+ } else if ((len > 1) && (strncmp(str,"-nocase",(unsigned)len) == 0)) {
nocase = 1;
} else {
- /* Not an option we recognize. */
- return TCL_OUT_LINE_COMPILE;
+ /*
+ * Not an option we recognize.
+ */
+
+ return TCL_ERROR;
}
}
if ((parsePtr->numWords - i) != 2) {
- /* We don't support capturing to variables */
- return TCL_OUT_LINE_COMPILE;
+ /*
+ * We don't support capturing to variables.
+ */
+
+ return TCL_ERROR;
}
/*
- * Get the regexp string. If it is not a simple string, punt to runtime.
- * If it has a '-', it could be an incorrectly formed regexp command.
+ * Get the regexp string. If it is not a simple string or can't be
+ * converted to a glob pattern, push the word for the INST_REGEXP.
+ * Keep changes here in sync with TclCompileSwitchCmd Switch_Regexp.
*/
- varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
- str = (char *) varTokenPtr[1].start;
- len = varTokenPtr[1].size;
- if ((varTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) || (*str == '-')) {
- return TCL_OUT_LINE_COMPILE;
- }
- if (len == 0) {
+ varTokenPtr = TokenAfter(varTokenPtr);
+
+ if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
+ Tcl_DString ds;
+
+ str = (char *) varTokenPtr[1].start;
+ len = varTokenPtr[1].size;
/*
- * The semantics of regexp are always match on re == "".
+ * If it has a '-', it could be an incorrectly formed regexp command.
*/
- TclEmitPush(TclRegisterNewLiteral(envPtr, "1", 1), envPtr);
- return TCL_OK;
- }
-
- /*
- * Make a copy of the string that is null-terminated for checks which
- * require such.
- */
- str = (char *) ckalloc((unsigned) len + 1);
- strncpy(str, varTokenPtr[1].start, (size_t) len);
- str[len] = '\0';
- start = 0;
- /*
- * Check for anchored REs (ie ^foo$), so we can use string equal if
- * possible. Do not alter the start of str so we can free it correctly.
- */
- if (str[0] == '^') {
- start++;
- anchorLeft = 1;
- } else {
- anchorLeft = 0;
- }
- if ((str[len-1] == '$') && ((len == 1) || (str[len-2] != '\\'))) {
- anchorRight = 1;
- str[--len] = '\0';
- } else {
- anchorRight = 0;
- }
+ if ((*str == '-') && !sawLast) {
+ return TCL_ERROR;
+ }
- /*
- * On the first (pattern) arg, check to see if any RE special characters
- * are in the word. If not, this is the same as 'string equal'.
- */
- if ((len > (1+start)) && (str[start] == '.') && (str[start+1] == '*')) {
- start += 2;
- anchorLeft = 0;
- }
- if ((len > (2+start)) && (str[len-3] != '\\')
- && (str[len-2] == '.') && (str[len-1] == '*')) {
- len -= 2;
- str[len] = '\0';
- anchorRight = 0;
- }
+ if (len == 0) {
+ /*
+ * The semantics of regexp are always match on re == "".
+ */
- /*
- * Don't do anything with REs with other special chars. Also check if
- * this is a bad RE (do this at the end because it can be expensive).
- * If so, let it complain at runtime.
- */
- if ((strpbrk(str + start, "*+?{}()[].\\|^$") != NULL)
- || (Tcl_RegExpCompile(NULL, str) == NULL)) {
- ckfree((char *) str);
- return TCL_OUT_LINE_COMPILE;
- }
+ PushLiteral(envPtr, "1", 1);
+ return TCL_OK;
+ }
- if (anchorLeft && anchorRight) {
- TclEmitPush(TclRegisterNewLiteral(envPtr, str+start, len-start),
- envPtr);
- } else {
/*
- * This needs to find the substring anywhere in the string, so
- * use string match and *foo*, with appropriate anchoring.
+ * Attempt to convert pattern to glob. If successful, push the
+ * converted pattern as a literal.
*/
- char *newStr = ckalloc((unsigned) len + 3);
- len -= start;
- if (anchorLeft) {
- strncpy(newStr, str + start, (size_t) len);
- } else {
- newStr[0] = '*';
- strncpy(newStr + 1, str + start, (size_t) len++);
- }
- if (!anchorRight) {
- newStr[len++] = '*';
+
+ if (TclReToGlob(NULL, varTokenPtr[1].start, len, &ds, &exact)
+ == TCL_OK) {
+ simple = 1;
+ PushLiteral(envPtr, Tcl_DStringValue(&ds),Tcl_DStringLength(&ds));
+ Tcl_DStringFree(&ds);
}
- newStr[len] = '\0';
- TclEmitPush(TclRegisterNewLiteral(envPtr, newStr, len), envPtr);
- ckfree((char *) newStr);
}
- ckfree((char *) str);
+
+ if (!simple) {
+ CompileWord(envPtr, varTokenPtr, interp, parsePtr->numWords-2);
+ }
/*
- * Push the string arg
+ * Push the string arg.
*/
- varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
- if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
- TclEmitPush(TclRegisterNewLiteral(envPtr,
- varTokenPtr[1].start, varTokenPtr[1].size), envPtr);
- } else {
- SetLineInformation (parsePtr->numWords-1);
- code = TclCompileTokens(interp, varTokenPtr+1,
- varTokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- return code;
- }
- }
- if (anchorLeft && anchorRight && !nocase) {
- TclEmitOpcode(INST_STR_EQ, envPtr);
+ varTokenPtr = TokenAfter(varTokenPtr);
+ CompileWord(envPtr, varTokenPtr, interp, parsePtr->numWords-1);
+
+ if (simple) {
+ if (exact && !nocase) {
+ TclEmitOpcode(INST_STR_EQ, envPtr);
+ } else {
+ TclEmitInstInt1(INST_STR_MATCH, nocase, envPtr);
+ }
} else {
- TclEmitInstInt1(INST_STR_MATCH, nocase, envPtr);
+ /*
+ * Pass correct RE compile flags. We use only Int1 (8-bit), but
+ * that handles all the flags we want to pass.
+ * Don't use TCL_REG_NOSUB as we may have backrefs.
+ */
+ int cflags = TCL_REG_ADVANCED | (nocase ? TCL_REG_NOCASE : 0);
+ TclEmitInstInt1(INST_REGEXP, cflags, envPtr);
}
return TCL_OK;
@@ -2446,117 +3261,191 @@ TclCompileRegexpCmd(interp, parsePtr, envPtr)
* Procedure called to compile the "return" command.
*
* Results:
- * The return value is a standard Tcl result, which is TCL_OK if the
- * compilation was successful. If the particular return command is
- * too complex for this function (ie, return with any flags like "-code"
- * or "-errorinfo"), TCL_OUT_LINE_COMPILE is returned, indicating that
- * the command should be compiled "out of line" (eg, not byte compiled).
- * If an error occurs then the interpreter's result contains a standard
- * error message.
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
*
* Side effects:
- * Instructions are added to envPtr to execute the "return" command
- * at runtime.
+ * Instructions are added to envPtr to execute the "return" command at
+ * runtime.
*
*----------------------------------------------------------------------
*/
int
-TclCompileReturnCmd(interp, parsePtr, envPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Parse *parsePtr; /* Points to a parse structure for the
- * command created by Tcl_ParseCommand. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
+TclCompileReturnCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
{
- Tcl_Token *varTokenPtr;
- int code;
- int index = envPtr->exceptArrayNext - 1;
-
- DefineLineInformation;
+ /*
+ * General syntax: [return ?-option value ...? ?result?]
+ * An even number of words means an explicit result argument is present.
+ */
+ int level, code, objc, size, status = TCL_OK;
+ int numWords = parsePtr->numWords;
+ int explicitResult = (0 == (numWords % 2));
+ int numOptionWords = numWords - 1 - explicitResult;
+ Tcl_Obj *returnOpts, **objv;
+ Tcl_Token *wordTokenPtr = TokenAfter(parsePtr->tokenPtr);
+ DefineLineInformation; /* TIP #280 */
/*
- * If we're not in a procedure, don't compile.
+ * Check for special case which can always be compiled:
+ * return -options <opts> <msg>
+ * Unlike the normal [return] compilation, this version does everything at
+ * runtime so it can handle arbitrary words and not just literals. Note
+ * that if INST_RETURN_STK wasn't already needed for something else
+ * ('finally' clause processing) this piece of code would not be present.
*/
- if (envPtr->procPtr == NULL) {
- return TCL_OUT_LINE_COMPILE;
+ if ((numWords == 4) && (wordTokenPtr->type == TCL_TOKEN_SIMPLE_WORD)
+ && (wordTokenPtr[1].size == 8)
+ && (strncmp(wordTokenPtr[1].start, "-options", 8) == 0)) {
+ Tcl_Token *optsTokenPtr = TokenAfter(wordTokenPtr);
+ Tcl_Token *msgTokenPtr = TokenAfter(optsTokenPtr);
+
+ CompileWord(envPtr, optsTokenPtr, interp, 2);
+ CompileWord(envPtr, msgTokenPtr, interp, 3);
+ TclEmitOpcode(INST_RETURN_STK, envPtr);
+ return TCL_OK;
}
/*
- * Look back through the ExceptionRanges of the current CompileEnv,
- * from exceptArrayPtr[(exceptArrayNext - 1)] down to
- * exceptArrayPtr[0] to see if any of them is an enclosing [catch].
- * If there's an enclosing [catch], don't compile.
+ * Allocate some working space.
+ */
+
+ objv = (Tcl_Obj **) TclStackAlloc(interp,
+ numOptionWords * sizeof(Tcl_Obj *));
+
+ /*
+ * Scan through the return options. If any are unknown at compile time,
+ * there is no value in bytecompiling. Save the option values known in an
+ * objv array for merging into a return options dictionary.
*/
- while (index >= 0) {
- ExceptionRange range = envPtr->exceptArrayPtr[index];
- if ((range.type == CATCH_EXCEPTION_RANGE)
- && (range.catchOffset == -1)) {
- return TCL_OUT_LINE_COMPILE;
+ for (objc = 0; objc < numOptionWords; objc++) {
+ objv[objc] = Tcl_NewObj();
+ Tcl_IncrRefCount(objv[objc]);
+ if (!TclWordKnownAtCompileTime(wordTokenPtr, objv[objc])) {
+ objc++;
+ status = TCL_ERROR;
+ goto cleanup;
}
- index--;
+ wordTokenPtr = TokenAfter(wordTokenPtr);
+ }
+ status = TclMergeReturnOptions(interp, objc, objv,
+ &returnOpts, &code, &level);
+ cleanup:
+ while (--objc >= 0) {
+ TclDecrRefCount(objv[objc]);
}
+ TclStackFree(interp, objv);
+ if (TCL_ERROR == status) {
+ /*
+ * Something was bogus in the return options. Clear the error message,
+ * and report back to the compiler that this must be interpreted at
+ * runtime.
+ */
- switch (parsePtr->numWords) {
- case 1: {
- /*
- * Simple case: [return]
- * Just push the literal string "".
- */
- TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
- break;
- }
- case 2: {
- /*
- * More complex cases:
- * [return "foo"]
- * [return $value]
- * [return [otherCmd]]
- */
- varTokenPtr = parsePtr->tokenPtr
- + (parsePtr->tokenPtr->numComponents + 1);
- if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
- /*
- * [return "foo"] case: the parse token is a simple word,
- * so just push it.
- */
- TclEmitPush(TclRegisterNewLiteral(envPtr, varTokenPtr[1].start,
- varTokenPtr[1].size), envPtr);
- } else {
- /*
- * Parse token is more complex, so compile it; this handles the
- * variable reference and nested command cases. If the
- * parse token can be byte-compiled, then this instance of
- * "return" will be byte-compiled; otherwise it will be
- * out line compiled.
- */
- SetLineInformation (1);
- code = TclCompileTokens(interp, varTokenPtr+1,
- varTokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- return code;
- }
+ Tcl_ResetResult(interp);
+ return TCL_ERROR;
+ }
+
+ /*
+ * All options are known at compile time, so we're going to bytecompile.
+ * Emit instructions to push the result on the stack.
+ */
+
+ if (explicitResult) {
+ CompileWord(envPtr, wordTokenPtr, interp, numWords-1);
+ } else {
+ /*
+ * No explict result argument, so default result is empty string.
+ */
+
+ PushLiteral(envPtr, "", 0);
+ }
+
+ /*
+ * Check for optimization: When [return] is in a proc, and there's no
+ * enclosing [catch], and there are no return options, then the INST_DONE
+ * instruction is equivalent, and may be more efficient.
+ */
+
+ if (numOptionWords == 0 && envPtr->procPtr != NULL) {
+ /*
+ * We have default return options and we're in a proc ...
+ */
+
+ int index = envPtr->exceptArrayNext - 1;
+ int enclosingCatch = 0;
+
+ while (index >= 0) {
+ ExceptionRange range = envPtr->exceptArrayPtr[index];
+ if ((range.type == CATCH_EXCEPTION_RANGE)
+ && (range.catchOffset == -1)) {
+ enclosingCatch = 1;
+ break;
}
- break;
+ index--;
}
- default: {
+ if (!enclosingCatch) {
/*
- * Most complex return cases: everything else, including
- * [return -code error], etc.
+ * ... and there is no enclosing catch. Issue the maximally
+ * efficient exit instruction.
*/
- return TCL_OUT_LINE_COMPILE;
+
+ Tcl_DecrRefCount(returnOpts);
+ TclEmitOpcode(INST_DONE, envPtr);
+ return TCL_OK;
}
}
+ /* Optimize [return -level 0 $x]. */
+ Tcl_DictObjSize(NULL, returnOpts, &size);
+ if (size == 0 && level == 0 && code == TCL_OK) {
+ Tcl_DecrRefCount(returnOpts);
+ return TCL_OK;
+ }
+
/*
- * The INST_DONE opcode actually causes the branching out of the
- * subroutine, and takes the top stack item as the return result
- * (which is why we pushed the value above).
+ * Could not use the optimization, so we push the return options dict, and
+ * emit the INST_RETURN_IMM instruction with code and level as operands.
*/
- TclEmitOpcode(INST_DONE, envPtr);
+
+ CompileReturnInternal(envPtr, INST_RETURN_IMM, code, level, returnOpts);
return TCL_OK;
}
+
+static void
+CompileReturnInternal(
+ CompileEnv *envPtr,
+ unsigned char op,
+ int code,
+ int level,
+ Tcl_Obj *returnOpts)
+{
+ TclEmitPush(TclAddLiteralObj(envPtr, returnOpts, NULL), envPtr);
+ TclEmitInstInt4(op, code, envPtr);
+ TclEmitInt4(level, envPtr);
+}
+
+void
+TclCompileSyntaxError(
+ Tcl_Interp *interp,
+ CompileEnv *envPtr)
+{
+ Tcl_Obj *msg = Tcl_GetObjResult(interp);
+ int numBytes;
+ const char *bytes = TclGetStringFromObj(msg, &numBytes);
+
+ TclEmitPush(TclRegisterNewLiteral(envPtr, bytes, numBytes), envPtr);
+ CompileReturnInternal(envPtr, INST_SYNTAX, TCL_ERROR, 0,
+ Tcl_GetReturnOptions(interp, TCL_ERROR));
+}
/*
*----------------------------------------------------------------------
@@ -2566,77 +3455,54 @@ TclCompileReturnCmd(interp, parsePtr, envPtr)
* Procedure called to compile the "set" command.
*
* Results:
- * The return value is a standard Tcl result, which is normally TCL_OK
- * unless there was an error while parsing string. If an error occurs
- * then the interpreter's result contains a standard error message. If
- * compilation fails because the set command requires a second level of
- * substitutions, TCL_OUT_LINE_COMPILE is returned indicating that the
- * set command should be compiled "out of line" by emitting code to
- * invoke its command procedure (Tcl_SetCmd) at runtime.
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
*
* Side effects:
- * Instructions are added to envPtr to execute the "set" command
- * at runtime.
+ * Instructions are added to envPtr to execute the "set" command at
+ * runtime.
*
*----------------------------------------------------------------------
*/
int
-TclCompileSetCmd(interp, parsePtr, envPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Parse *parsePtr; /* Points to a parse structure for the
- * command created by Tcl_ParseCommand. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
+TclCompileSetCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
{
Tcl_Token *varTokenPtr, *valueTokenPtr;
int isAssignment, isScalar, simpleVarName, localIndex, numWords;
- int code = TCL_OK;
-
- DefineLineInformation;
+ DefineLineInformation; /* TIP #280 */
numWords = parsePtr->numWords;
if ((numWords != 2) && (numWords != 3)) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "wrong # args: should be \"set varName ?newValue?\"", -1);
- return TCL_ERROR;
+ return TCL_ERROR;
}
isAssignment = (numWords == 3);
/*
- * Decide if we can use a frame slot for the var/array name or if we
- * need to emit code to compute and push the name at runtime. We use a
- * frame slot (entry in the array of local vars) if we are compiling a
- * procedure body and if the name is simple text that does not include
- * namespace qualifiers.
+ * Decide if we can use a frame slot for the var/array name or if we need
+ * to emit code to compute and push the name at runtime. We use a frame
+ * slot (entry in the array of local vars) if we are compiling a procedure
+ * body and if the name is simple text that does not include namespace
+ * qualifiers.
*/
- varTokenPtr = parsePtr->tokenPtr
- + (parsePtr->tokenPtr->numComponents + 1);
-
- code = TclPushVarNameWord(interp, varTokenPtr, envPtr, TCL_CREATE_VAR,
- &localIndex, &simpleVarName, &isScalar, 1);
- if (code != TCL_OK) {
- goto done;
- }
+ varTokenPtr = TokenAfter(parsePtr->tokenPtr);
+ PushVarNameWord(interp, varTokenPtr, envPtr, TCL_CREATE_VAR,
+ &localIndex, &simpleVarName, &isScalar, 1);
/*
* If we are doing an assignment, push the new value.
*/
if (isAssignment) {
- valueTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
- if (valueTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
- TclEmitPush(TclRegisterNewLiteral(envPtr, valueTokenPtr[1].start,
- valueTokenPtr[1].size), envPtr);
- } else {
- SetLineInformation (2);
- code = TclCompileTokens(interp, valueTokenPtr+1,
- valueTokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- goto done;
- }
- }
+ valueTokenPtr = TokenAfter(varTokenPtr);
+ CompileWord(envPtr, valueTokenPtr, interp, 2);
}
/*
@@ -2645,351 +3511,1158 @@ TclCompileSetCmd(interp, parsePtr, envPtr)
if (simpleVarName) {
if (isScalar) {
- if (localIndex >= 0) {
- if (localIndex <= 255) {
- TclEmitInstInt1((isAssignment?
- INST_STORE_SCALAR1 : INST_LOAD_SCALAR1),
- localIndex, envPtr);
- } else {
- TclEmitInstInt4((isAssignment?
- INST_STORE_SCALAR4 : INST_LOAD_SCALAR4),
- localIndex, envPtr);
- }
- } else {
+ if (localIndex < 0) {
TclEmitOpcode((isAssignment?
- INST_STORE_SCALAR_STK : INST_LOAD_SCALAR_STK), envPtr);
+ INST_STORE_SCALAR_STK : INST_LOAD_SCALAR_STK), envPtr);
+ } else if (localIndex <= 255) {
+ TclEmitInstInt1((isAssignment?
+ INST_STORE_SCALAR1 : INST_LOAD_SCALAR1),
+ localIndex, envPtr);
+ } else {
+ TclEmitInstInt4((isAssignment?
+ INST_STORE_SCALAR4 : INST_LOAD_SCALAR4),
+ localIndex, envPtr);
}
} else {
- if (localIndex >= 0) {
- if (localIndex <= 255) {
- TclEmitInstInt1((isAssignment?
- INST_STORE_ARRAY1 : INST_LOAD_ARRAY1),
- localIndex, envPtr);
- } else {
- TclEmitInstInt4((isAssignment?
- INST_STORE_ARRAY4 : INST_LOAD_ARRAY4),
- localIndex, envPtr);
- }
- } else {
+ if (localIndex < 0) {
TclEmitOpcode((isAssignment?
- INST_STORE_ARRAY_STK : INST_LOAD_ARRAY_STK), envPtr);
+ INST_STORE_ARRAY_STK : INST_LOAD_ARRAY_STK), envPtr);
+ } else if (localIndex <= 255) {
+ TclEmitInstInt1((isAssignment?
+ INST_STORE_ARRAY1 : INST_LOAD_ARRAY1),
+ localIndex, envPtr);
+ } else {
+ TclEmitInstInt4((isAssignment?
+ INST_STORE_ARRAY4 : INST_LOAD_ARRAY4),
+ localIndex, envPtr);
}
}
} else {
TclEmitOpcode((isAssignment? INST_STORE_STK : INST_LOAD_STK), envPtr);
}
-
- done:
- return code;
+
+ return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * TclCompileStringCmd --
+ * TclCompileStringCmpCmd --
*
- * Procedure called to compile the "string" command.
+ * Procedure called to compile the simplest and most common form of the
+ * "string compare" command.
*
* Results:
- * The return value is a standard Tcl result, which is TCL_OK if the
- * compilation was successful. If the command cannot be byte-compiled,
- * TCL_OUT_LINE_COMPILE is returned. If an error occurs then the
- * interpreter's result contains an error message, and TCL_ERROR is
- * returned.
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
*
* Side effects:
- * Instructions are added to envPtr to execute the "string" command
+ * Instructions are added to envPtr to execute the "string compare"
+ * command at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileStringCmpCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ DefineLineInformation; /* TIP #280 */
+ Tcl_Token *tokenPtr;
+
+ /*
+ * We don't support any flags; the bytecode isn't that sophisticated.
+ */
+
+ if (parsePtr->numWords != 3) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Push the two operands onto the stack and then the test.
+ */
+
+ tokenPtr = TokenAfter(parsePtr->tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, 1);
+ tokenPtr = TokenAfter(tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, 2);
+ TclEmitOpcode(INST_STR_CMP, envPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileStringEqualCmd --
+ *
+ * Procedure called to compile the simplest and most common form of the
+ * "string equal" command.
+ *
+ * Results:
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
+ *
+ * Side effects:
+ * Instructions are added to envPtr to execute the "string equal" command
* at runtime.
*
*----------------------------------------------------------------------
*/
int
-TclCompileStringCmd(interp, parsePtr, envPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Parse *parsePtr; /* Points to a parse structure for the
- * command created by Tcl_ParseCommand. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
-{
- Tcl_Token *opTokenPtr, *varTokenPtr;
- Tcl_Obj *opObj;
- int index;
- int code;
-
- static CONST char *options[] = {
- "bytelength", "compare", "equal", "first",
- "index", "is", "last", "length",
- "map", "match", "range", "repeat",
- "replace", "tolower", "toupper", "totitle",
- "trim", "trimleft", "trimright",
- "wordend", "wordstart", (char *) NULL
- };
- enum options {
- STR_BYTELENGTH, STR_COMPARE, STR_EQUAL, STR_FIRST,
- STR_INDEX, STR_IS, STR_LAST, STR_LENGTH,
- STR_MAP, STR_MATCH, STR_RANGE, STR_REPEAT,
- STR_REPLACE, STR_TOLOWER, STR_TOUPPER, STR_TOTITLE,
- STR_TRIM, STR_TRIMLEFT, STR_TRIMRIGHT,
- STR_WORDEND, STR_WORDSTART
- };
-
- DefineLineInformation;
+TclCompileStringEqualCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ DefineLineInformation; /* TIP #280 */
+ Tcl_Token *tokenPtr;
- if (parsePtr->numWords < 2) {
- /* Fail at run time, not in compilation */
- return TCL_OUT_LINE_COMPILE;
+ /*
+ * We don't support any flags; the bytecode isn't that sophisticated.
+ */
+
+ if (parsePtr->numWords != 3) {
+ return TCL_ERROR;
}
- opTokenPtr = parsePtr->tokenPtr
- + (parsePtr->tokenPtr->numComponents + 1);
- opObj = Tcl_NewStringObj(opTokenPtr->start, opTokenPtr->size);
- if (Tcl_GetIndexFromObj(interp, opObj, options, "option", 0,
- &index) != TCL_OK) {
- Tcl_DecrRefCount(opObj);
- Tcl_ResetResult(interp);
- return TCL_OUT_LINE_COMPILE;
- }
- Tcl_DecrRefCount(opObj);
-
- varTokenPtr = opTokenPtr + (opTokenPtr->numComponents + 1);
-
- switch ((enum options) index) {
- case STR_BYTELENGTH:
- case STR_FIRST:
- case STR_IS:
- case STR_LAST:
- case STR_MAP:
- case STR_RANGE:
- case STR_REPEAT:
- case STR_REPLACE:
- case STR_TOLOWER:
- case STR_TOUPPER:
- case STR_TOTITLE:
- case STR_TRIM:
- case STR_TRIMLEFT:
- case STR_TRIMRIGHT:
- case STR_WORDEND:
- case STR_WORDSTART:
+ /*
+ * Push the two operands onto the stack and then the test.
+ */
+
+ tokenPtr = TokenAfter(parsePtr->tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, 1);
+ tokenPtr = TokenAfter(tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, 2);
+ TclEmitOpcode(INST_STR_EQ, envPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileStringIndexCmd --
+ *
+ * Procedure called to compile the simplest and most common form of the
+ * "string index" command.
+ *
+ * Results:
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
+ *
+ * Side effects:
+ * Instructions are added to envPtr to execute the "string index" command
+ * at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileStringIndexCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ DefineLineInformation; /* TIP #280 */
+ Tcl_Token *tokenPtr;
+
+ if (parsePtr->numWords != 3) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Push the two operands onto the stack and then the index operation.
+ */
+
+ tokenPtr = TokenAfter(parsePtr->tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, 1);
+ tokenPtr = TokenAfter(tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, 2);
+ TclEmitOpcode(INST_STR_INDEX, envPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileStringMatchCmd --
+ *
+ * Procedure called to compile the simplest and most common form of the
+ * "string match" command.
+ *
+ * Results:
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
+ *
+ * Side effects:
+ * Instructions are added to envPtr to execute the "string match" command
+ * at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileStringMatchCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ DefineLineInformation; /* TIP #280 */
+ Tcl_Token *tokenPtr;
+ int i, length, exactMatch = 0, nocase = 0;
+ const char *str;
+
+ if (parsePtr->numWords < 3 || parsePtr->numWords > 4) {
+ return TCL_ERROR;
+ }
+ tokenPtr = TokenAfter(parsePtr->tokenPtr);
+
+ /*
+ * Check if we have a -nocase flag.
+ */
+
+ if (parsePtr->numWords == 4) {
+ if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
+ return TCL_ERROR;
+ }
+ str = tokenPtr[1].start;
+ length = tokenPtr[1].size;
+ if ((length <= 1) || strncmp(str, "-nocase", (size_t) length)) {
/*
- * All other cases: compile out of line.
+ * Fail at run time, not in compilation.
*/
- return TCL_OUT_LINE_COMPILE;
- case STR_COMPARE:
- case STR_EQUAL: {
- int i;
+ return TCL_ERROR;
+ }
+ nocase = 1;
+ tokenPtr = TokenAfter(tokenPtr);
+ }
+
+ /*
+ * Push the strings to match against each other.
+ */
+
+ for (i = 0; i < 2; i++) {
+ if (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
+ str = tokenPtr[1].start;
+ length = tokenPtr[1].size;
+ if (!nocase && (i == 0)) {
+ /*
+ * Trivial matches can be done by 'string equal'. If -nocase
+ * was specified, we can't do this because INST_STR_EQ has no
+ * support for nocase.
+ */
+
+ Tcl_Obj *copy = Tcl_NewStringObj(str, length);
+
+ Tcl_IncrRefCount(copy);
+ exactMatch = TclMatchIsTrivial(TclGetString(copy));
+ TclDecrRefCount(copy);
+ }
+ PushLiteral(envPtr, str, length);
+ } else {
+ SetLineInformation (i+1+nocase);
+ CompileTokens(envPtr, tokenPtr, interp);
+ }
+ tokenPtr = TokenAfter(tokenPtr);
+ }
+
+ /*
+ * Push the matcher.
+ */
+
+ if (exactMatch) {
+ TclEmitOpcode(INST_STR_EQ, envPtr);
+ } else {
+ TclEmitInstInt1(INST_STR_MATCH, nocase, envPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileStringLenCmd --
+ *
+ * Procedure called to compile the simplest and most common form of the
+ * "string length" command.
+ *
+ * Results:
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
+ *
+ * Side effects:
+ * Instructions are added to envPtr to execute the "string length"
+ * command at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileStringLenCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ DefineLineInformation; /* TIP #280 */
+ Tcl_Token *tokenPtr;
+
+ if (parsePtr->numWords != 2) {
+ return TCL_ERROR;
+ }
+
+ tokenPtr = TokenAfter(parsePtr->tokenPtr);
+ if (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
+ /*
+ * Here someone is asking for the length of a static string. Just push
+ * the actual character (not byte) length.
+ */
+
+ char buf[TCL_INTEGER_SPACE];
+ int len = Tcl_NumUtfChars(tokenPtr[1].start, tokenPtr[1].size);
+
+ len = sprintf(buf, "%d", len);
+ PushLiteral(envPtr, buf, len);
+ } else {
+ SetLineInformation (1);
+ CompileTokens(envPtr, tokenPtr, interp);
+ TclEmitOpcode(INST_STR_LEN, envPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileSwitchCmd --
+ *
+ * Procedure called to compile the "switch" command.
+ *
+ * Results:
+ * Returns TCL_OK for successful compile, or TCL_ERROR to defer
+ * evaluation to runtime (either when it is too complex to get the
+ * semantics right, or when we know for sure that it is an error but need
+ * the error to happen at the right time).
+ *
+ * Side effects:
+ * Instructions are added to envPtr to execute the "switch" command at
+ * runtime.
+ *
+ * FIXME:
+ * Stack depths are probably not calculated correctly.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileSwitchCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ Tcl_Token *tokenPtr; /* Pointer to tokens in command. */
+ int numWords; /* Number of words in command. */
+
+ Tcl_Token *valueTokenPtr; /* Token for the value to switch on. */
+ enum {Switch_Exact, Switch_Glob, Switch_Regexp} mode;
+ /* What kind of switch are we doing? */
+
+ Tcl_Token *bodyTokenArray; /* Array of real pattern list items. */
+ Tcl_Token **bodyToken; /* Array of pointers to pattern list items. */
+ int *bodyLines; /* Array of line numbers for body list
+ * items. */
+ int** bodyNext;
+ int foundDefault; /* Flag to indicate whether a "default" clause
+ * is present. */
+
+ JumpFixup *fixupArray; /* Array of forward-jump fixup records. */
+ int *fixupTargetArray; /* Array of places for fixups to point at. */
+ int fixupCount; /* Number of places to fix up. */
+ int contFixIndex; /* Where the first of the jumps due to a group
+ * of continuation bodies starts, or -1 if
+ * there aren't any. */
+ int contFixCount; /* Number of continuation bodies pointing to
+ * the current (or next) real body. */
+
+ int savedStackDepth = envPtr->currStackDepth;
+ int noCase; /* Has the -nocase flag been given? */
+ int foundMode = 0; /* Have we seen a mode flag yet? */
+ int i, valueIndex;
+ DefineLineInformation; /* TIP #280 */
+ int* clNext = envPtr->clNext;
+
+ /*
+ * Only handle the following versions:
+ * switch ?--? word {pattern body ...}
+ * switch -exact ?--? word {pattern body ...}
+ * switch -glob ?--? word {pattern body ...}
+ * switch -regexp ?--? word {pattern body ...}
+ * switch -- word simpleWordPattern simpleWordBody ...
+ * switch -exact -- word simpleWordPattern simpleWordBody ...
+ * switch -glob -- word simpleWordPattern simpleWordBody ...
+ * switch -regexp -- word simpleWordPattern simpleWordBody ...
+ * When the mode is -glob, can also handle a -nocase flag.
+ *
+ * First off, we don't care how the command's word was generated; we're
+ * compiling it anyway! So skip it...
+ */
+
+ tokenPtr = TokenAfter(parsePtr->tokenPtr);
+ valueIndex = 1;
+ numWords = parsePtr->numWords-1;
+
+ /*
+ * Check for options.
+ */
+
+ noCase = 0;
+ mode = Switch_Exact;
+ if (numWords == 2) {
+ /*
+ * There's just the switch value and the bodies list. In that case, we
+ * can skip all option parsing and move on to consider switch values
+ * and the body list.
+ */
+
+ goto finishedOptionParse;
+ }
+
+ /*
+ * There must be at least one option, --, because without that there is no
+ * way to statically avoid the problems you get from strings-to-be-matched
+ * that start with a - (the interpreted code falls apart if it encounters
+ * them, so we punt if we *might* encounter them as that is the easiest
+ * way of emulating the behaviour).
+ */
+
+ for (; numWords>=3 ; tokenPtr=TokenAfter(tokenPtr),numWords--) {
+ register unsigned size = tokenPtr[1].size;
+ register const char *chrs = tokenPtr[1].start;
+
+ /*
+ * We only process literal options, and we assume that -e, -g and -n
+ * are unique prefixes of -exact, -glob and -nocase respectively (true
+ * at time of writing). Note that -exact and -glob may only be given
+ * at most once or we bail out (error case).
+ */
+
+ if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD || size < 2) {
+ return TCL_ERROR;
+ }
+
+ if ((size <= 6) && !memcmp(chrs, "-exact", size)) {
+ if (foundMode) {
+ return TCL_ERROR;
+ }
+ mode = Switch_Exact;
+ foundMode = 1;
+ valueIndex++;
+ continue;
+ } else if ((size <= 5) && !memcmp(chrs, "-glob", size)) {
+ if (foundMode) {
+ return TCL_ERROR;
+ }
+ mode = Switch_Glob;
+ foundMode = 1;
+ valueIndex++;
+ continue;
+ } else if ((size <= 7) && !memcmp(chrs, "-regexp", size)) {
+ if (foundMode) {
+ return TCL_ERROR;
+ }
+ mode = Switch_Regexp;
+ foundMode = 1;
+ valueIndex++;
+ continue;
+ } else if ((size <= 7) && !memcmp(chrs, "-nocase", size)) {
+ noCase = 1;
+ valueIndex++;
+ continue;
+ } else if ((size == 2) && !memcmp(chrs, "--", 2)) {
+ valueIndex++;
+ break;
+ }
+
+ /*
+ * The switch command has many flags we cannot compile at all (e.g.
+ * all the RE-related ones) which we must have encountered. Either
+ * that or we have run off the end. The action here is the same: punt
+ * to interpreted version.
+ */
+
+ return TCL_ERROR;
+ }
+ if (numWords < 3) {
+ return TCL_ERROR;
+ }
+ tokenPtr = TokenAfter(tokenPtr);
+ numWords--;
+ if (noCase && (mode == Switch_Exact)) {
+ /*
+ * Can't compile this case; no opcode for case-insensitive equality!
+ */
+
+ return TCL_ERROR;
+ }
+
+ /*
+ * The value to test against is going to always get pushed on the stack.
+ * But not yet; we need to verify that the rest of the command is
+ * compilable too.
+ */
+
+ finishedOptionParse:
+ valueTokenPtr = tokenPtr;
+ /* For valueIndex, see previous loop. */
+ tokenPtr = TokenAfter(tokenPtr);
+ numWords--;
+
+ /*
+ * Build an array of tokens for the matcher terms and script bodies. Note
+ * that in the case of the quoted bodies, this is tricky as we cannot use
+ * copies of the string from the input token for the generated tokens (it
+ * causes a crash during exception handling). When multiple tokens are
+ * available at this point, this is pretty easy.
+ */
+
+ if (numWords == 1) {
+ CONST char *bytes;
+ int maxLen, numBytes;
+ int bline; /* TIP #280: line of the pattern/action list,
+ * and start of list for when tracking the
+ * location. This list comes immediately after
+ * the value we switch on. */
+
+ if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
+ return TCL_ERROR;
+ }
+ bytes = tokenPtr[1].start;
+ numBytes = tokenPtr[1].size;
+
+ /* Allocate enough space to work in. */
+ maxLen = TclMaxListLength(bytes, numBytes, NULL);
+ if (maxLen < 2) {
+ return TCL_ERROR;
+ }
+ bodyTokenArray = (Tcl_Token *) ckalloc(sizeof(Tcl_Token) * maxLen);
+ bodyToken = (Tcl_Token **) ckalloc(sizeof(Tcl_Token *) * maxLen);
+ bodyLines = (int *) ckalloc(sizeof(int) * maxLen);
+ bodyNext = (int **) ckalloc(sizeof(int*) * maxLen);
+
+ bline = mapPtr->loc[eclIndex].line[valueIndex+1];
+ numWords = 0;
+
+ while (numBytes > 0) {
+ CONST char *prevBytes = bytes;
+ int literal;
+
+ if (TCL_OK != TclFindElement(NULL, bytes, numBytes,
+ &(bodyTokenArray[numWords].start), &bytes,
+ &(bodyTokenArray[numWords].size), &literal) || !literal) {
+ abort:
+ ckfree((char *) bodyToken);
+ ckfree((char *) bodyTokenArray);
+ ckfree((char *) bodyLines);
+ ckfree((char *) bodyNext);
+ return TCL_ERROR;
+ }
+
+ bodyTokenArray[numWords].type = TCL_TOKEN_TEXT;
+ bodyTokenArray[numWords].numComponents = 0;
+ bodyToken[numWords] = bodyTokenArray + numWords;
+
/*
- * If there are any flags to the command, we can't byte compile it
- * because the INST_STR_EQ bytecode doesn't support flags.
+ * TIP #280: Now determine the line the list element starts on
+ * (there is no need to do it earlier, due to the possibility of
+ * aborting, see above).
*/
- if (parsePtr->numWords != 4) {
- return TCL_OUT_LINE_COMPILE;
- }
+ TclAdvanceLines(&bline, prevBytes, bodyTokenArray[numWords].start);
+ TclAdvanceContinuations (&bline, &clNext,
+ bodyTokenArray[numWords].start - envPtr->source);
+ bodyLines[numWords] = bline;
+ bodyNext[numWords] = clNext;
+ TclAdvanceLines(&bline, bodyTokenArray[numWords].start, bytes);
+ TclAdvanceContinuations (&bline, &clNext, bytes - envPtr->source);
+ numBytes -= (bytes - prevBytes);
+ numWords++;
+ }
+ if (numWords % 2) {
+ goto abort;
+ }
+ } else if (numWords % 2 || numWords == 0) {
+ /*
+ * Odd number of words (>1) available, or no words at all available.
+ * Both are error cases, so punt and let the interpreted-version
+ * generate the error message. Note that the second case probably
+ * should get caught earlier, but it's easy to check here again anyway
+ * because it'd cause a nasty crash otherwise.
+ */
+
+ return TCL_ERROR;
+ } else {
+ /*
+ * Multi-word definition of patterns & actions.
+ */
+
+ bodyToken = (Tcl_Token **) ckalloc(sizeof(Tcl_Token *) * numWords);
+ bodyLines = (int *) ckalloc(sizeof(int) * numWords);
+ bodyNext = (int **) ckalloc(sizeof(int*) * numWords);
+ bodyTokenArray = NULL;
+ for (i=0 ; i<numWords ; i++) {
/*
- * Push the two operands onto the stack.
+ * We only handle the very simplest case. Anything more complex is
+ * a good reason to go to the interpreted case anyway due to
+ * traces, etc.
*/
- for (i = 0; i < 2; i++) {
- if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
- TclEmitPush(TclRegisterNewLiteral(envPtr,
- varTokenPtr[1].start, varTokenPtr[1].size), envPtr);
- } else {
- SetLineInformation (i);
- code = TclCompileTokens(interp, varTokenPtr+1,
- varTokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- return code;
- }
- }
- varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
+ if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
+ ckfree((char *) bodyToken);
+ ckfree((char *) bodyLines);
+ ckfree((char *) bodyNext);
+ return TCL_ERROR;
}
+ bodyToken[i] = tokenPtr+1;
- TclEmitOpcode(((((enum options) index) == STR_COMPARE) ?
- INST_STR_CMP : INST_STR_EQ), envPtr);
- return TCL_OK;
+ /*
+ * TIP #280: Copy line information from regular cmd info.
+ */
+
+ bodyLines[i] = mapPtr->loc[eclIndex].line[valueIndex+1+i];
+ bodyNext[i] = mapPtr->loc[eclIndex].next[valueIndex+1+i];
+ tokenPtr = TokenAfter(tokenPtr);
}
- case STR_INDEX: {
- int i;
+ }
- if (parsePtr->numWords != 4) {
- /* Fail at run time, not in compilation */
- return TCL_OUT_LINE_COMPILE;
- }
+ /*
+ * Fall back to interpreted if the last body is a continuation (it's
+ * illegal, but this makes the error happen at the right time).
+ */
+
+ if (bodyToken[numWords-1]->size == 1 &&
+ bodyToken[numWords-1]->start[0] == '-') {
+ ckfree((char *) bodyToken);
+ ckfree((char *) bodyLines);
+ ckfree((char *) bodyNext);
+ if (bodyTokenArray != NULL) {
+ ckfree((char *) bodyTokenArray);
+ }
+ return TCL_ERROR;
+ }
+
+ /*
+ * Now we commit to generating code; the parsing stage per se is done.
+ * First, we push the value we're matching against on the stack.
+ */
+
+ SetLineInformation (valueIndex);
+ CompileTokens(envPtr, valueTokenPtr, interp);
+
+ /*
+ * Check if we can generate a jump table, since if so that's faster than
+ * doing an explicit compare with each body. Note that we're definitely
+ * over-conservative with determining whether we can do the jump table,
+ * but it handles the most common case well enough.
+ */
+
+ if (mode == Switch_Exact) {
+ JumptableInfo *jtPtr;
+ int infoIndex, isNew, *finalFixups, numRealBodies = 0, jumpLocation;
+ int mustGenerate, jumpToDefault;
+ Tcl_DString buffer;
+ Tcl_HashEntry *hPtr;
+
+ /*
+ * Compile the switch by using a jump table, which is basically a
+ * hashtable that maps from literal values to match against to the
+ * offset (relative to the INST_JUMP_TABLE instruction) to jump to.
+ * The jump table itself is independent of any invokation of the
+ * bytecode, and as such is stored in an auxData block.
+ *
+ * Start by allocating the jump table itself, plus some workspace.
+ */
+ jtPtr = (JumptableInfo *) ckalloc(sizeof(JumptableInfo));
+ Tcl_InitHashTable(&jtPtr->hashTable, TCL_STRING_KEYS);
+ infoIndex = TclCreateAuxData(jtPtr, &tclJumptableInfoType, envPtr);
+ finalFixups = (int *) ckalloc(sizeof(int) * (numWords/2));
+ foundDefault = 0;
+ mustGenerate = 1;
+
+ /*
+ * Next, issue the instruction to do the jump, together with what we
+ * want to do if things do not work out (jump to either the default
+ * clause or the "default" default, which just sets the result to
+ * empty). Note that we will come back and rewrite the jump's offset
+ * parameter when we know what it should be, and that all jumps we
+ * issue are of the wide kind because that makes the code much easier
+ * to debug!
+ */
+
+ jumpLocation = CurrentOffset(envPtr);
+ TclEmitInstInt4(INST_JUMP_TABLE, infoIndex, envPtr);
+ jumpToDefault = CurrentOffset(envPtr);
+ TclEmitInstInt4(INST_JUMP4, 0, envPtr);
+
+ for (i=0 ; i<numWords ; i+=2) {
/*
- * Push the two operands onto the stack.
+ * For each arm, we must first work out what to do with the match
+ * term.
*/
- for (i = 0; i < 2; i++) {
- if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
- TclEmitPush(TclRegisterNewLiteral(envPtr,
- varTokenPtr[1].start, varTokenPtr[1].size), envPtr);
- } else {
- SetLineInformation (i);
- code = TclCompileTokens(interp, varTokenPtr+1,
- varTokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- return code;
- }
+ if (i!=numWords-2 || bodyToken[numWords-2]->size != 7 ||
+ memcmp(bodyToken[numWords-2]->start, "default", 7)) {
+ /*
+ * This is not a default clause, so insert the current
+ * location as a target in the jump table (assuming it isn't
+ * already there, which would indicate that this clause is
+ * probably masked by an earlier one). Note that we use a
+ * Tcl_DString here simply because the hash API does not let
+ * us specify the string length.
+ */
+
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer, bodyToken[i]->start,
+ bodyToken[i]->size);
+ hPtr = Tcl_CreateHashEntry(&jtPtr->hashTable,
+ Tcl_DStringValue(&buffer), &isNew);
+ if (isNew) {
+ /*
+ * First time we've encountered this match clause, so it
+ * must point to here.
+ */
+
+ Tcl_SetHashValue(hPtr, (ClientData)
+ (CurrentOffset(envPtr) - jumpLocation));
}
- varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
+ Tcl_DStringFree(&buffer);
+ } else {
+ /*
+ * This is a default clause, so patch up the fallthrough from
+ * the INST_JUMP_TABLE instruction to here.
+ */
+
+ foundDefault = 1;
+ isNew = 1;
+ TclStoreInt4AtPtr(CurrentOffset(envPtr)-jumpToDefault,
+ envPtr->codeStart+jumpToDefault+1);
}
- TclEmitOpcode(INST_STR_INDEX, envPtr);
- return TCL_OK;
- }
- case STR_LENGTH: {
- if (parsePtr->numWords != 3) {
- /* Fail at run time, not in compilation */
- return TCL_OUT_LINE_COMPILE;
+ /*
+ * Now, for each arm we must deal with the body of the clause.
+ *
+ * If this is a continuation body (never true of a final clause,
+ * whether default or not) we're done because the next jump target
+ * will also point here, so we advance to the next clause.
+ */
+
+ if (bodyToken[i+1]->size == 1 && bodyToken[i+1]->start[0] == '-') {
+ mustGenerate = 1;
+ continue;
}
- if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
+ /*
+ * Also skip this arm if its only match clause is masked. (We
+ * could probably be more aggressive about this, but that would be
+ * much more difficult to get right.)
+ */
+
+ if (!isNew && !mustGenerate) {
+ continue;
+ }
+ mustGenerate = 0;
+
+ /*
+ * Compile the body of the arm.
+ */
+
+ envPtr->line = bodyLines[i+1]; /* TIP #280 */
+ envPtr->clNext = bodyNext[i+1]; /* TIP #280 */
+ TclCompileCmdWord(interp, bodyToken[i+1], 1, envPtr);
+
+ /*
+ * Compile a jump in to the end of the command if this body is
+ * anything other than a user-supplied default arm (to either skip
+ * over the remaining bodies or the code that generates an empty
+ * result).
+ */
+
+ if (i+2 < numWords || !foundDefault) {
+ finalFixups[numRealBodies++] = CurrentOffset(envPtr);
+
/*
- * Here someone is asking for the length of a static string.
- * Just push the actual character (not byte) length.
+ * Easier by far to issue this jump as a fixed-width jump.
+ * Otherwise we'd need to do a lot more (and more awkward)
+ * rewriting when we fixed this all up.
*/
- char buf[TCL_INTEGER_SPACE];
- int len = Tcl_NumUtfChars(varTokenPtr[1].start,
- varTokenPtr[1].size);
- len = sprintf(buf, "%d", len);
- TclEmitPush(TclRegisterNewLiteral(envPtr, buf, len), envPtr);
- return TCL_OK;
- } else {
- SetLineInformation (2);
- code = TclCompileTokens(interp, varTokenPtr+1,
- varTokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- return code;
- }
+
+ TclEmitInstInt4(INST_JUMP4, 0, envPtr);
}
- TclEmitOpcode(INST_STR_LEN, envPtr);
- return TCL_OK;
}
- case STR_MATCH: {
- int i, length, exactMatch = 0, nocase = 0;
- CONST char *str;
- if (parsePtr->numWords < 4 || parsePtr->numWords > 5) {
- /* Fail at run time, not in compilation */
- return TCL_OUT_LINE_COMPILE;
- }
+ /*
+ * We're at the end. If we've not already done so through the
+ * processing of a user-supplied default clause, add in a "default"
+ * default clause now.
+ */
- if (parsePtr->numWords == 5) {
- if (varTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
- return TCL_OUT_LINE_COMPILE;
- }
- str = varTokenPtr[1].start;
- length = varTokenPtr[1].size;
- if ((length > 1) &&
- strncmp(str, "-nocase", (size_t) length) == 0) {
- nocase = 1;
- } else {
- /* Fail at run time, not in compilation */
- return TCL_OUT_LINE_COMPILE;
- }
- varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
- }
+ if (!foundDefault) {
+ TclStoreInt4AtPtr(CurrentOffset(envPtr)-jumpToDefault,
+ envPtr->codeStart+jumpToDefault+1);
+ PushLiteral(envPtr, "", 0);
+ }
+
+ /*
+ * No more instructions to be issued; everything that needs to jump to
+ * the end of the command is fixed up at this point.
+ */
+
+ for (i=0 ; i<numRealBodies ; i++) {
+ TclStoreInt4AtPtr(CurrentOffset(envPtr)-finalFixups[i],
+ envPtr->codeStart+finalFixups[i]+1);
+ }
- for (i = 0; i < 2; i++) {
- if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
- str = varTokenPtr[1].start;
- length = varTokenPtr[1].size;
- if (!nocase && (i == 0)) {
+ /*
+ * Clean up all our temporary space and return.
+ */
+
+ ckfree((char *) finalFixups);
+ ckfree((char *) bodyToken);
+ ckfree((char *) bodyLines);
+ ckfree((char *) bodyNext);
+ if (bodyTokenArray != NULL) {
+ ckfree((char *) bodyTokenArray);
+ }
+ return TCL_OK;
+ }
+
+ /*
+ * Generate a test for each arm.
+ */
+
+ contFixIndex = -1;
+ contFixCount = 0;
+ fixupArray = (JumpFixup *) ckalloc(sizeof(JumpFixup) * numWords);
+ fixupTargetArray = (int *) ckalloc(sizeof(int) * numWords);
+ memset(fixupTargetArray, 0, numWords * sizeof(int));
+ fixupCount = 0;
+ foundDefault = 0;
+ for (i=0 ; i<numWords ; i+=2) {
+ int nextArmFixupIndex = -1;
+
+ envPtr->currStackDepth = savedStackDepth + 1;
+ if (i!=numWords-2 || bodyToken[numWords-2]->size != 7 ||
+ memcmp(bodyToken[numWords-2]->start, "default", 7)) {
+ /*
+ * Generate the test for the arm.
+ */
+
+ switch (mode) {
+ case Switch_Exact:
+ TclEmitOpcode(INST_DUP, envPtr);
+ TclCompileTokens(interp, bodyToken[i], 1, envPtr);
+ TclEmitOpcode(INST_STR_EQ, envPtr);
+ break;
+ case Switch_Glob:
+ TclCompileTokens(interp, bodyToken[i], 1, envPtr);
+ TclEmitInstInt4(INST_OVER, 1, envPtr);
+ TclEmitInstInt1(INST_STR_MATCH, noCase, envPtr);
+ break;
+ case Switch_Regexp: {
+ int simple = 0, exact = 0;
+
+ /*
+ * Keep in sync with TclCompileRegexpCmd.
+ */
+
+ if (bodyToken[i]->type == TCL_TOKEN_TEXT) {
+ Tcl_DString ds;
+
+ if (bodyToken[i]->size == 0) {
/*
- * On the first (pattern) arg, check to see if any
- * glob special characters are in the word '*[]?\\'.
- * If not, this is the same as 'string equal'. We
- * can use strpbrk here because the glob chars are all
- * in the ascii-7 range. If -nocase was specified,
- * we can't do this because INST_STR_EQ has no support
- * for nocase.
+ * The semantics of regexps are that they always match
+ * when the RE == "".
*/
- Tcl_Obj *copy = Tcl_NewStringObj(str, length);
- Tcl_IncrRefCount(copy);
- exactMatch = (strpbrk(Tcl_GetString(copy),
- "*[]?\\") == NULL);
- Tcl_DecrRefCount(copy);
+
+ PushLiteral(envPtr, "1", 1);
+ break;
}
- TclEmitPush(
- TclRegisterNewLiteral(envPtr, str, length), envPtr);
- } else {
- SetLineInformation (i);
- code = TclCompileTokens(interp, varTokenPtr+1,
- varTokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- return code;
+
+ /*
+ * Attempt to convert pattern to glob. If successful, push
+ * the converted pattern.
+ */
+
+ if (TclReToGlob(NULL, bodyToken[i]->start,
+ bodyToken[i]->size, &ds, &exact) == TCL_OK) {
+ simple = 1;
+ PushLiteral(envPtr, Tcl_DStringValue(&ds),
+ Tcl_DStringLength(&ds));
+ Tcl_DStringFree(&ds);
}
}
- varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
+ if (!simple) {
+ TclCompileTokens(interp, bodyToken[i], 1, envPtr);
+ }
+
+ TclEmitInstInt4(INST_OVER, 1, envPtr);
+ if (simple) {
+ if (exact && !noCase) {
+ TclEmitOpcode(INST_STR_EQ, envPtr);
+ } else {
+ TclEmitInstInt1(INST_STR_MATCH, noCase, envPtr);
+ }
+ } else {
+ /*
+ * Pass correct RE compile flags. We use only Int1
+ * (8-bit), but that handles all the flags we want to
+ * pass. Don't use TCL_REG_NOSUB as we may have backrefs
+ * or capture vars.
+ */
+
+ int cflags = TCL_REG_ADVANCED
+ | (noCase ? TCL_REG_NOCASE : 0);
+
+ TclEmitInstInt1(INST_REGEXP, cflags, envPtr);
+ }
+ break;
+ }
+ default:
+ Tcl_Panic("unknown switch mode: %d", mode);
}
- if (exactMatch) {
- TclEmitOpcode(INST_STR_EQ, envPtr);
- } else {
- TclEmitInstInt1(INST_STR_MATCH, nocase, envPtr);
+ /*
+ * In a fall-through case, we will jump on _true_ to the place
+ * where the body starts (generated later, with guarantee of this
+ * ensured earlier; the final body is never a fall-through).
+ */
+
+ if (bodyToken[i+1]->size==1 && bodyToken[i+1]->start[0]=='-') {
+ if (contFixIndex == -1) {
+ contFixIndex = fixupCount;
+ contFixCount = 0;
+ }
+ TclEmitForwardJump(envPtr, TCL_TRUE_JUMP,
+ fixupArray+contFixIndex+contFixCount);
+ fixupCount++;
+ contFixCount++;
+ continue;
}
- return TCL_OK;
+
+ TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, fixupArray+fixupCount);
+ nextArmFixupIndex = fixupCount;
+ fixupCount++;
+ } else {
+ /*
+ * Got a default clause; set a flag to inhibit the generation of
+ * the jump after the body and the cleanup of the intermediate
+ * value that we are switching against.
+ *
+ * Note that default clauses (which are always terminal clauses)
+ * cannot be fall-through clauses as well, since the last clause
+ * is never a fall-through clause (which we have already
+ * verified).
+ */
+
+ foundDefault = 1;
+ }
+
+ /*
+ * Generate the body for the arm. This is guaranteed not to be a
+ * fall-through case, but it might have preceding fall-through cases,
+ * so we must process those first.
+ */
+
+ if (contFixIndex != -1) {
+ int j;
+
+ for (j=0 ; j<contFixCount ; j++) {
+ fixupTargetArray[contFixIndex+j] = CurrentOffset(envPtr);
+ }
+ contFixIndex = -1;
+ }
+
+ /*
+ * Now do the actual compilation. Note that we do not use CompileBody
+ * because we may have synthesized the tokens in a non-standard
+ * pattern.
+ */
+
+ TclEmitOpcode(INST_POP, envPtr);
+ envPtr->currStackDepth = savedStackDepth + 1;
+ envPtr->line = bodyLines[i+1]; /* TIP #280 */
+ envPtr->clNext = bodyNext[i+1]; /* TIP #280 */
+ TclCompileCmdWord(interp, bodyToken[i+1], 1, envPtr);
+
+ if (!foundDefault) {
+ TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP,
+ fixupArray+fixupCount);
+ fixupCount++;
+ fixupTargetArray[nextArmFixupIndex] = CurrentOffset(envPtr);
+ }
+ }
+
+ /*
+ * Clean up all our temporary space and return.
+ */
+
+ ckfree((char *) bodyToken);
+ ckfree((char *) bodyLines);
+ ckfree((char *) bodyNext);
+ if (bodyTokenArray != NULL) {
+ ckfree((char *) bodyTokenArray);
+ }
+
+ /*
+ * Discard the value we are matching against unless we've had a default
+ * clause (in which case it will already be gone due to the code at the
+ * start of processing an arm, guaranteed) and make the result of the
+ * command an empty string.
+ */
+
+ if (!foundDefault) {
+ TclEmitOpcode(INST_POP, envPtr);
+ PushLiteral(envPtr, "", 0);
+ }
+
+ /*
+ * Do jump fixups for arms that were executed. First, fill in the jumps of
+ * all jumps that don't point elsewhere to point to here.
+ */
+
+ for (i=0 ; i<fixupCount ; i++) {
+ if (fixupTargetArray[i] == 0) {
+ fixupTargetArray[i] = envPtr->codeNext-envPtr->codeStart;
}
}
+ /*
+ * Now scan backwards over all the jumps (all of which are forward jumps)
+ * doing each one. When we do one and there is a size changes, we must
+ * scan back over all the previous ones and see if they need adjusting
+ * before proceeding with further jump fixups (the interleaved nature of
+ * all the jumps makes this impossible to do without nested loops).
+ */
+
+ for (i=fixupCount-1 ; i>=0 ; i--) {
+ if (TclFixupForwardJump(envPtr, &fixupArray[i],
+ fixupTargetArray[i] - fixupArray[i].codeOffset, 127)) {
+ int j;
+
+ for (j=i-1 ; j>=0 ; j--) {
+ if (fixupTargetArray[j] > fixupArray[i].codeOffset) {
+ fixupTargetArray[j] += 3;
+ }
+ }
+ }
+ }
+ ckfree((char *) fixupArray);
+ ckfree((char *) fixupTargetArray);
+
+ envPtr->currStackDepth = savedStackDepth + 1;
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * TclCompileVariableCmd --
+ * DupJumptableInfo, FreeJumptableInfo --
*
- * Procedure called to reserve the local variables for the
- * "variable" command. The command itself is *not* compiled.
+ * Functions to duplicate, release and print a jump-table created for use
+ * with the INST_JUMP_TABLE instruction.
*
* Results:
- * Always returns TCL_OUT_LINE_COMPILE.
+ * DupJumptableInfo: a copy of the jump-table
+ * FreeJumptableInfo: none
+ * PrintJumptableInfo: none
*
* Side effects:
- * Indexed local variables are added to the environment.
+ * DupJumptableInfo: allocates memory
+ * FreeJumptableInfo: releases memory
+ * PrintJumptableInfo: none
*
*----------------------------------------------------------------------
*/
-int
-TclCompileVariableCmd(interp, parsePtr, envPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Parse *parsePtr; /* Points to a parse structure for the
- * command created by Tcl_ParseCommand. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
+
+static ClientData
+DupJumptableInfo(
+ ClientData clientData)
{
- Tcl_Token *varTokenPtr;
- int i, numWords;
- CONST char *varName, *tail;
-
- if (envPtr->procPtr == NULL) {
- return TCL_OUT_LINE_COMPILE;
+ JumptableInfo *jtPtr = clientData;
+ JumptableInfo *newJtPtr = (JumptableInfo *)
+ ckalloc(sizeof(JumptableInfo));
+ Tcl_HashEntry *hPtr, *newHPtr;
+ Tcl_HashSearch search;
+ int isNew;
+
+ Tcl_InitHashTable(&newJtPtr->hashTable, TCL_STRING_KEYS);
+ hPtr = Tcl_FirstHashEntry(&jtPtr->hashTable, &search);
+ while (hPtr != NULL) {
+ newHPtr = Tcl_CreateHashEntry(&newJtPtr->hashTable,
+ Tcl_GetHashKey(&jtPtr->hashTable, hPtr), &isNew);
+ Tcl_SetHashValue(newHPtr, Tcl_GetHashValue(hPtr));
}
+ return newJtPtr;
+}
- numWords = parsePtr->numWords;
-
- varTokenPtr = parsePtr->tokenPtr
- + (parsePtr->tokenPtr->numComponents + 1);
- for (i = 1; i < numWords; i += 2) {
- if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
- varName = varTokenPtr[1].start;
- tail = varName + varTokenPtr[1].size - 1;
- if ((*tail == ')') || (tail < varName)) continue;
- while ((tail > varName) && ((*tail != ':') || (*(tail-1) != ':'))) {
- tail--;
- }
- if ((*tail == ':') && (tail > varName)) {
- tail++;
+static void
+FreeJumptableInfo(
+ ClientData clientData)
+{
+ JumptableInfo *jtPtr = clientData;
+
+ Tcl_DeleteHashTable(&jtPtr->hashTable);
+ ckfree((char *) jtPtr);
+}
+
+static void
+PrintJumptableInfo(
+ ClientData clientData,
+ Tcl_Obj *appendObj,
+ ByteCode *codePtr,
+ unsigned int pcOffset)
+{
+ register JumptableInfo *jtPtr = clientData;
+ Tcl_HashEntry *hPtr;
+ Tcl_HashSearch search;
+ const char *keyPtr;
+ int offset, i = 0;
+
+ hPtr = Tcl_FirstHashEntry(&jtPtr->hashTable, &search);
+ for (; hPtr ; hPtr = Tcl_NextHashEntry(&search)) {
+ keyPtr = Tcl_GetHashKey(&jtPtr->hashTable, hPtr);
+ offset = PTR2INT(Tcl_GetHashValue(hPtr));
+
+ if (i++) {
+ Tcl_AppendToObj(appendObj, ", ", -1);
+ if (i%4==0) {
+ Tcl_AppendToObj(appendObj, "\n\t\t", -1);
}
- (void) TclFindCompiledLocal(tail, (tail-varName+1),
- /*create*/ 1, /*flags*/ 0, envPtr->procPtr);
- varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
}
+ Tcl_AppendPrintfToObj(appendObj, "\"%s\"->pc %d",
+ keyPtr, pcOffset + offset);
}
- return TCL_OUT_LINE_COMPILE;
}
/*
@@ -3000,99 +4673,87 @@ TclCompileVariableCmd(interp, parsePtr, envPtr)
* Procedure called to compile the "while" command.
*
* Results:
- * The return value is a standard Tcl result, which is TCL_OK if
- * compilation was successful. If an error occurs then the
- * interpreter's result contains a standard error message and TCL_ERROR
- * is returned. If compilation failed because the command is too
- * complex for TclCompileWhileCmd, TCL_OUT_LINE_COMPILE is returned
- * indicating that the while command should be compiled "out of line"
- * by emitting code to invoke its command procedure at runtime.
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
*
* Side effects:
- * Instructions are added to envPtr to execute the "while" command
- * at runtime.
+ * Instructions are added to envPtr to execute the "while" command at
+ * runtime.
*
*----------------------------------------------------------------------
*/
int
-TclCompileWhileCmd(interp, parsePtr, envPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Parse *parsePtr; /* Points to a parse structure for the
- * command created by Tcl_ParseCommand. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
+TclCompileWhileCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
{
Tcl_Token *testTokenPtr, *bodyTokenPtr;
JumpFixup jumpEvalCondFixup;
- int testCodeOffset, bodyCodeOffset, jumpDist;
- int range, code;
- char buffer[32 + TCL_INTEGER_SPACE];
+ int testCodeOffset, bodyCodeOffset, jumpDist, range, code, boolVal;
int savedStackDepth = envPtr->currStackDepth;
- int loopMayEnd = 1; /* This is set to 0 if it is recognized as
- * an infinite loop. */
+ int loopMayEnd = 1; /* This is set to 0 if it is recognized as an
+ * infinite loop. */
Tcl_Obj *boolObj;
- int boolVal;
-
- DefineLineInformation;
+ DefineLineInformation; /* TIP #280 */
if (parsePtr->numWords != 3) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "wrong # args: should be \"while test command\"", -1);
return TCL_ERROR;
}
/*
- * If the test expression requires substitutions, don't compile the
- * while command inline. E.g., the expression might cause the loop to
- * never execute or execute forever, as in "while "$x < 5" {}".
+ * If the test expression requires substitutions, don't compile the while
+ * command inline. E.g., the expression might cause the loop to never
+ * execute or execute forever, as in "while "$x < 5" {}".
*
- * Bail out also if the body expression requires substitutions
- * in order to insure correct behaviour [Bug 219166]
+ * Bail out also if the body expression requires substitutions in order to
+ * insure correct behaviour [Bug 219166]
*/
- testTokenPtr = parsePtr->tokenPtr
- + (parsePtr->tokenPtr->numComponents + 1);
- bodyTokenPtr = testTokenPtr + (testTokenPtr->numComponents + 1);
+ testTokenPtr = TokenAfter(parsePtr->tokenPtr);
+ bodyTokenPtr = TokenAfter(testTokenPtr);
+
if ((testTokenPtr->type != TCL_TOKEN_SIMPLE_WORD)
|| (bodyTokenPtr->type != TCL_TOKEN_SIMPLE_WORD)) {
- return TCL_OUT_LINE_COMPILE;
+ return TCL_ERROR;
}
/*
- * Find out if the condition is a constant.
+ * Find out if the condition is a constant.
*/
boolObj = Tcl_NewStringObj(testTokenPtr[1].start, testTokenPtr[1].size);
Tcl_IncrRefCount(boolObj);
code = Tcl_GetBooleanFromObj(NULL, boolObj, &boolVal);
- Tcl_DecrRefCount(boolObj);
+ TclDecrRefCount(boolObj);
if (code == TCL_OK) {
if (boolVal) {
/*
- * it is an infinite loop
+ * It is an infinite loop; flag it so that we generate a more
+ * efficient body.
*/
- loopMayEnd = 0;
+ loopMayEnd = 0;
} else {
/*
- * This is an empty loop: "while 0 {...}" or such.
- * Compile no bytecodes.
+ * This is an empty loop: "while 0 {...}" or such. Compile no
+ * bytecodes.
*/
goto pushResult;
}
}
- /*
+ /*
* Create a ExceptionRange record for the loop body. This is used to
* implement break and continue.
*/
- envPtr->exceptDepth++;
- envPtr->maxExceptDepth =
- TclMax(envPtr->exceptDepth, envPtr->maxExceptDepth);
- range = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr);
+ range = DeclareExceptionRange(envPtr, LOOP_EXCEPTION_RANGE);
/*
* Jump to the evaluation of the condition. This code uses the "loop
@@ -3110,31 +4771,26 @@ TclCompileWhileCmd(interp, parsePtr, envPtr)
if (loopMayEnd) {
TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpEvalCondFixup);
- testCodeOffset = 0; /* avoid compiler warning */
+ testCodeOffset = 0; /* Avoid compiler warning. */
} else {
- testCodeOffset = (envPtr->codeNext - envPtr->codeStart);
+ /*
+ * Make sure that the first command in the body is preceded by an
+ * INST_START_CMD, and hence counted properly. [Bug 1752146]
+ */
+
+ envPtr->atCmdStart = 0;
+ testCodeOffset = CurrentOffset(envPtr);
}
-
/*
* Compile the loop body.
*/
SetLineInformation (2);
- bodyCodeOffset = (envPtr->codeNext - envPtr->codeStart);
- code = TclCompileCmdWord(interp, bodyTokenPtr+1,
- bodyTokenPtr->numComponents, envPtr);
+ bodyCodeOffset = ExceptionRangeStarts(envPtr, range);
+ CompileBody(envPtr, bodyTokenPtr, interp);
+ ExceptionRangeEnds(envPtr, range);
envPtr->currStackDepth = savedStackDepth + 1;
- if (code != TCL_OK) {
- if (code == TCL_ERROR) {
- sprintf(buffer, "\n (\"while\" body line %d)",
- interp->errorLine);
- Tcl_AddObjErrorInfo(interp, buffer, -1);
- }
- goto error;
- }
- envPtr->exceptArrayPtr[range].numCodeBytes =
- (envPtr->codeNext - envPtr->codeStart) - bodyCodeOffset;
TclEmitOpcode(INST_POP, envPtr);
/*
@@ -3143,7 +4799,7 @@ TclCompileWhileCmd(interp, parsePtr, envPtr)
*/
if (loopMayEnd) {
- testCodeOffset = (envPtr->codeNext - envPtr->codeStart);
+ testCodeOffset = CurrentOffset(envPtr);
jumpDist = testCodeOffset - jumpEvalCondFixup.codeOffset;
if (TclFixupForwardJump(envPtr, &jumpEvalCondFixup, jumpDist, 127)) {
bodyCodeOffset += 3;
@@ -3151,113 +4807,86 @@ TclCompileWhileCmd(interp, parsePtr, envPtr)
}
envPtr->currStackDepth = savedStackDepth;
SetLineInformation (1);
- code = TclCompileExprWords(interp, testTokenPtr, 1, envPtr);
- if (code != TCL_OK) {
- if (code == TCL_ERROR) {
- Tcl_AddObjErrorInfo(interp,
- "\n (\"while\" test expression)", -1);
- }
- goto error;
- }
+ TclCompileExprWords(interp, testTokenPtr, 1, envPtr);
envPtr->currStackDepth = savedStackDepth + 1;
-
- jumpDist = (envPtr->codeNext - envPtr->codeStart) - bodyCodeOffset;
+
+ jumpDist = CurrentOffset(envPtr) - bodyCodeOffset;
if (jumpDist > 127) {
TclEmitInstInt4(INST_JUMP_TRUE4, -jumpDist, envPtr);
} else {
TclEmitInstInt1(INST_JUMP_TRUE1, -jumpDist, envPtr);
}
} else {
- jumpDist = (envPtr->codeNext - envPtr->codeStart) - bodyCodeOffset;
+ jumpDist = CurrentOffset(envPtr) - bodyCodeOffset;
if (jumpDist > 127) {
TclEmitInstInt4(INST_JUMP4, -jumpDist, envPtr);
} else {
TclEmitInstInt1(INST_JUMP1, -jumpDist, envPtr);
- }
+ }
}
-
/*
* Set the loop's body, continue and break offsets.
*/
envPtr->exceptArrayPtr[range].continueOffset = testCodeOffset;
envPtr->exceptArrayPtr[range].codeOffset = bodyCodeOffset;
- envPtr->exceptArrayPtr[range].breakOffset =
- (envPtr->codeNext - envPtr->codeStart);
-
+ ExceptionRangeTarget(envPtr, range, breakOffset);
+
/*
* The while command's result is an empty string.
*/
- pushResult:
+ pushResult:
envPtr->currStackDepth = savedStackDepth;
- TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
- envPtr->exceptDepth--;
+ PushLiteral(envPtr, "", 0);
return TCL_OK;
-
- error:
- envPtr->exceptDepth--;
- return code;
}
/*
*----------------------------------------------------------------------
*
- * TclPushVarName --
+ * PushVarName --
*
- * Procedure used in the compiling where pushing a variable name
- * is necessary (append, lappend, set).
+ * Procedure used in the compiling where pushing a variable name is
+ * necessary (append, lappend, set).
*
* Results:
- * The return value is a standard Tcl result, which is normally TCL_OK
- * unless there was an error while parsing string. If an error occurs
- * then the interpreter's result contains a standard error message.
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
*
* Side effects:
- * Instructions are added to envPtr to execute the "set" command
- * at runtime.
+ * Instructions are added to envPtr to execute the "set" command at
+ * runtime.
*
*----------------------------------------------------------------------
*/
static int
-TclPushVarName(interp, varTokenPtr, envPtr, flags, localIndexPtr,
-#ifndef TCL_TIP280
- simpleVarNamePtr, isScalarPtr)
-#else
- simpleVarNamePtr, isScalarPtr, line, clNext)
-#endif
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Token *varTokenPtr; /* Points to a variable token. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
- int flags; /* takes TCL_CREATE_VAR or
- * TCL_NO_LARGE_INDEX */
- int *localIndexPtr; /* must not be NULL */
- int *simpleVarNamePtr; /* must not be NULL */
- int *isScalarPtr; /* must not be NULL */
-#ifdef TCL_TIP280
- int line; /* line the token starts on */
- int* clNext;
-#endif
-{
- register CONST char *p;
- CONST char *name, *elName;
+PushVarName(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Token *varTokenPtr, /* Points to a variable token. */
+ CompileEnv *envPtr, /* Holds resulting instructions. */
+ int flags, /* TCL_CREATE_VAR or TCL_NO_LARGE_INDEX. */
+ int *localIndexPtr, /* Must not be NULL. */
+ int *simpleVarNamePtr, /* Must not be NULL. */
+ int *isScalarPtr, /* Must not be NULL. */
+ int line, /* Line the token starts on. */
+ int* clNext) /* Reference to offset of next hidden cont. line */
+{
+ register const char *p;
+ const char *name, *elName;
register int i, n;
- int nameChars, elNameChars, simpleVarName, localIndex;
- int code = TCL_OK;
-
Tcl_Token *elemTokenPtr = NULL;
- int elemTokenCount = 0;
- int allocedTokens = 0;
- int removedParen = 0;
+ int nameChars, elNameChars, simpleVarName, localIndex;
+ int elemTokenCount = 0, allocedTokens = 0, removedParen = 0;
/*
- * Decide if we can use a frame slot for the var/array name or if we
- * need to emit code to compute and push the name at runtime. We use a
- * frame slot (entry in the array of local vars) if we are compiling a
- * procedure body and if the name is simple text that does not include
- * namespace qualifiers.
+ * Decide if we can use a frame slot for the var/array name or if we need
+ * to emit code to compute and push the name at runtime. We use a frame
+ * slot (entry in the array of local vars) if we are compiling a procedure
+ * body and if the name is simple text that does not include namespace
+ * qualifiers.
*/
simpleVarName = 0;
@@ -3267,8 +4896,8 @@ TclPushVarName(interp, varTokenPtr, envPtr, flags, localIndexPtr,
/*
* Check not only that the type is TCL_TOKEN_SIMPLE_WORD, but whether
- * curly braces surround the variable name.
- * This really matters for array elements to handle things like
+ * curly braces surround the variable name. This really matters for array
+ * elements to handle things like
* set {x($foo)} 5
* which raises an undefined var error if we are not careful here.
*/
@@ -3279,31 +4908,33 @@ TclPushVarName(interp, varTokenPtr, envPtr, flags, localIndexPtr,
* A simple variable name. Divide it up into "name" and "elName"
* strings. If it is not a local variable, look it up at runtime.
*/
+
simpleVarName = 1;
name = varTokenPtr[1].start;
nameChars = varTokenPtr[1].size;
- if ( *(name + nameChars - 1) == ')') {
- /*
+ if (name[nameChars-1] == ')') {
+ /*
* last char is ')' => potential array reference.
*/
- for (i = 0, p = name; i < nameChars; i++, p++) {
+ for (i=0,p=name ; i<nameChars ; i++,p++) {
if (*p == '(') {
elName = p + 1;
elNameChars = nameChars - i - 2;
- nameChars = i ;
+ nameChars = i;
break;
}
}
if ((elName != NULL) && elNameChars) {
/*
- * An array element, the element name is a simple
- * string: assemble the corresponding token.
+ * An array element, the element name is a simple string:
+ * assemble the corresponding token.
*/
- elemTokenPtr = (Tcl_Token *) ckalloc(sizeof(Tcl_Token));
+ elemTokenPtr = (Tcl_Token *) TclStackAlloc(interp,
+ sizeof(Tcl_Token));
allocedTokens = 1;
elemTokenPtr->type = TCL_TOKEN_TEXT;
elemTokenPtr->start = elName;
@@ -3314,28 +4945,28 @@ TclPushVarName(interp, varTokenPtr, envPtr, flags, localIndexPtr,
}
} else if (((n = varTokenPtr->numComponents) > 1)
&& (varTokenPtr[1].type == TCL_TOKEN_TEXT)
- && (varTokenPtr[n].type == TCL_TOKEN_TEXT)
- && (varTokenPtr[n].start[varTokenPtr[n].size - 1] == ')')) {
+ && (varTokenPtr[n].type == TCL_TOKEN_TEXT)
+ && (varTokenPtr[n].start[varTokenPtr[n].size - 1] == ')')) {
- /*
- * Check for parentheses inside first token
+ /*
+ * Check for parentheses inside first token.
*/
- simpleVarName = 0;
- for (i = 0, p = varTokenPtr[1].start;
- i < varTokenPtr[1].size; i++, p++) {
- if (*p == '(') {
- simpleVarName = 1;
- break;
- }
- }
- if (simpleVarName) {
+ simpleVarName = 0;
+ for (i = 0, p = varTokenPtr[1].start;
+ i < varTokenPtr[1].size; i++, p++) {
+ if (*p == '(') {
+ simpleVarName = 1;
+ break;
+ }
+ }
+ if (simpleVarName) {
int remainingChars;
/*
- * Check the last token: if it is just ')', do not count
- * it. Otherwise, remove the ')' and flag so that it is
- * restored at the end.
+ * Check the last token: if it is just ')', do not count it.
+ * Otherwise, remove the ')' and flag so that it is restored at
+ * the end.
*/
if (varTokenPtr[n].size == 1) {
@@ -3345,39 +4976,40 @@ TclPushVarName(interp, varTokenPtr, envPtr, flags, localIndexPtr,
removedParen = n;
}
- name = varTokenPtr[1].start;
- nameChars = p - varTokenPtr[1].start;
- elName = p + 1;
- remainingChars = (varTokenPtr[2].start - p) - 1;
- elNameChars = (varTokenPtr[n].start - p) + varTokenPtr[n].size - 2;
+ name = varTokenPtr[1].start;
+ nameChars = p - varTokenPtr[1].start;
+ elName = p + 1;
+ remainingChars = (varTokenPtr[2].start - p) - 1;
+ elNameChars = (varTokenPtr[n].start - p) + varTokenPtr[n].size - 2;
if (remainingChars) {
/*
- * Make a first token with the extra characters in the first
+ * Make a first token with the extra characters in the first
* token.
*/
- elemTokenPtr = (Tcl_Token *) ckalloc(n * sizeof(Tcl_Token));
+ elemTokenPtr = (Tcl_Token *) TclStackAlloc(interp,
+ n * sizeof(Tcl_Token));
allocedTokens = 1;
elemTokenPtr->type = TCL_TOKEN_TEXT;
elemTokenPtr->start = elName;
elemTokenPtr->size = remainingChars;
elemTokenPtr->numComponents = 0;
elemTokenCount = n;
-
+
/*
* Copy the remaining tokens.
*/
-
- memcpy((void *) (elemTokenPtr+1), (void *) (&varTokenPtr[2]),
- ((n-1) * sizeof(Tcl_Token)));
+
+ memcpy(elemTokenPtr+1, varTokenPtr+2,
+ (n-1) * sizeof(Tcl_Token));
} else {
/*
* Use the already available tokens.
*/
-
+
elemTokenPtr = &varTokenPtr[2];
- elemTokenCount = n - 1;
+ elemTokenCount = n - 1;
}
}
}
@@ -3396,23 +5028,25 @@ TclPushVarName(interp, varTokenPtr, envPtr, flags, localIndexPtr,
}
/*
- * Look up the var name's index in the array of local vars in the
- * proc frame. If retrieving the var's value and it doesn't already
- * exist, push its name and look it up at runtime.
+ * Look up the var name's index in the array of local vars in the proc
+ * frame. If retrieving the var's value and it doesn't already exist,
+ * push its name and look it up at runtime.
*/
if ((envPtr->procPtr != NULL) && !hasNsQualifiers) {
localIndex = TclFindCompiledLocal(name, nameChars,
- /*create*/ (flags & TCL_CREATE_VAR),
- /*flags*/ ((elName==NULL)? VAR_SCALAR : VAR_ARRAY),
+ /*create*/ flags & TCL_CREATE_VAR,
envPtr->procPtr);
if ((flags & TCL_NO_LARGE_INDEX) && (localIndex > 255)) {
- /* we'll push the name */
+ /*
+ * We'll push the name.
+ */
+
localIndex = -1;
}
}
if (localIndex < 0) {
- TclEmitPush(TclRegisterNewLiteral(envPtr, name, nameChars), envPtr);
+ PushLiteral(envPtr, name, nameChars);
}
/*
@@ -3421,17 +5055,11 @@ TclPushVarName(interp, varTokenPtr, envPtr, flags, localIndexPtr,
if (elName != NULL) {
if (elNameChars) {
-#ifdef TCL_TIP280
- envPtr->line = line;
- envPtr->clNext = clNext;
-#endif
- code = TclCompileTokens(interp, elemTokenPtr,
- elemTokenCount, envPtr);
- if (code != TCL_OK) {
- goto done;
- }
+ envPtr->line = line;
+ envPtr->clNext = clNext;
+ TclCompileTokens(interp, elemTokenPtr, elemTokenCount, envPtr);
} else {
- TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
+ PushLiteral(envPtr, "", 0);
}
}
} else {
@@ -3439,28 +5067,1404 @@ TclPushVarName(interp, varTokenPtr, envPtr, flags, localIndexPtr,
* The var name isn't simple: compile and push it.
*/
-#ifdef TCL_TIP280
- envPtr->line = line;
- envPtr->clNext = clNext;
-#endif
- code = TclCompileTokens(interp, varTokenPtr+1,
- varTokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- goto done;
- }
+ envPtr->line = line;
+ envPtr->clNext = clNext;
+ CompileTokens(envPtr, varTokenPtr, interp);
}
- done:
if (removedParen) {
++varTokenPtr[removedParen].size;
}
if (allocedTokens) {
- ckfree((char *) elemTokenPtr);
+ TclStackFree(interp, elemTokenPtr);
}
- *localIndexPtr = localIndex;
- *simpleVarNamePtr = simpleVarName;
- *isScalarPtr = (elName == NULL);
- return code;
+ *localIndexPtr = localIndex;
+ *simpleVarNamePtr = simpleVarName;
+ *isScalarPtr = (elName == NULL);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileUnaryOpCmd --
+ *
+ * Utility routine to compile the unary operator commands.
+ *
+ * Results:
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
+ *
+ * Side effects:
+ * Instructions are added to envPtr to execute the compiled command at
+ * runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileUnaryOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ int instruction,
+ CompileEnv *envPtr)
+{
+ Tcl_Token *tokenPtr;
+ DefineLineInformation; /* TIP #280 */
+
+ if (parsePtr->numWords != 2) {
+ return TCL_ERROR;
+ }
+ tokenPtr = TokenAfter(parsePtr->tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, 1);
+ TclEmitOpcode(instruction, envPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileAssociativeBinaryOpCmd --
+ *
+ * Utility routine to compile the binary operator commands that accept an
+ * arbitrary number of arguments, and that are associative operations.
+ * Because of the associativity, we may combine operations from right to
+ * left, saving us any effort of re-ordering the arguments on the stack
+ * after substitutions are completed.
+ *
+ * Results:
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
+ *
+ * Side effects:
+ * Instructions are added to envPtr to execute the compiled command at
+ * runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileAssociativeBinaryOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ const char *identity,
+ int instruction,
+ CompileEnv *envPtr)
+{
+ Tcl_Token *tokenPtr = parsePtr->tokenPtr;
+ DefineLineInformation; /* TIP #280 */
+ int words;
+
+ for (words=1 ; words<parsePtr->numWords ; words++) {
+ tokenPtr = TokenAfter(tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, words);
+ }
+ if (parsePtr->numWords <= 2) {
+ PushLiteral(envPtr, identity, -1);
+ words++;
+ }
+ if (words > 3) {
+ /*
+ * Reverse order of arguments to get precise agreement with
+ * [expr] in calcuations, including roundoff errors.
+ */
+ TclEmitInstInt4(INST_REVERSE, words-1, envPtr);
+ }
+ while (--words > 1) {
+ TclEmitOpcode(instruction, envPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileStrictlyBinaryOpCmd --
+ *
+ * Utility routine to compile the binary operator commands, that strictly
+ * accept exactly two arguments.
+ *
+ * Results:
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
+ *
+ * Side effects:
+ * Instructions are added to envPtr to execute the compiled command at
+ * runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileStrictlyBinaryOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ int instruction,
+ CompileEnv *envPtr)
+{
+ if (parsePtr->numWords != 3) {
+ return TCL_ERROR;
+ }
+ return CompileAssociativeBinaryOpCmd(interp, parsePtr,
+ NULL, instruction, envPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileComparisonOpCmd --
+ *
+ * Utility routine to compile the n-ary comparison operator commands.
+ *
+ * Results:
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
+ *
+ * Side effects:
+ * Instructions are added to envPtr to execute the compiled command at
+ * runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CompileComparisonOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ int instruction,
+ CompileEnv *envPtr)
+{
+ Tcl_Token *tokenPtr;
+ DefineLineInformation; /* TIP #280 */
+
+ if (parsePtr->numWords < 3) {
+ PushLiteral(envPtr, "1", 1);
+ } else if (parsePtr->numWords == 3) {
+ tokenPtr = TokenAfter(parsePtr->tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, 1);
+ tokenPtr = TokenAfter(tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, 2);
+ TclEmitOpcode(instruction, envPtr);
+ } else if (envPtr->procPtr == NULL) {
+ /*
+ * No local variable space!
+ */
+
+ return TCL_ERROR;
+ } else {
+ int tmpIndex = TclFindCompiledLocal(NULL, 0, 1, envPtr->procPtr);
+ int words;
+
+ tokenPtr = TokenAfter(parsePtr->tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, 1);
+ tokenPtr = TokenAfter(tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, 2);
+ if (tmpIndex <= 255) {
+ TclEmitInstInt1(INST_STORE_SCALAR1, tmpIndex, envPtr);
+ } else {
+ TclEmitInstInt4(INST_STORE_SCALAR4, tmpIndex, envPtr);
+ }
+ TclEmitOpcode(instruction, envPtr);
+ for (words=3 ; words<parsePtr->numWords ;) {
+ if (tmpIndex <= 255) {
+ TclEmitInstInt1(INST_LOAD_SCALAR1, tmpIndex, envPtr);
+ } else {
+ TclEmitInstInt4(INST_LOAD_SCALAR4, tmpIndex, envPtr);
+ }
+ tokenPtr = TokenAfter(tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, words);
+ if (++words < parsePtr->numWords) {
+ if (tmpIndex <= 255) {
+ TclEmitInstInt1(INST_STORE_SCALAR1, tmpIndex, envPtr);
+ } else {
+ TclEmitInstInt4(INST_STORE_SCALAR4, tmpIndex, envPtr);
+ }
+ }
+ TclEmitOpcode(instruction, envPtr);
+ }
+ for (; words>3 ; words--) {
+ TclEmitOpcode(INST_BITAND, envPtr);
+ }
+
+ /*
+ * Drop the value from the temp variable; retaining that reference
+ * might be expensive elsewhere.
+ */
+
+ PushLiteral(envPtr, "", 0);
+ if (tmpIndex <= 255) {
+ TclEmitInstInt1(INST_STORE_SCALAR1, tmpIndex, envPtr);
+ } else {
+ TclEmitInstInt4(INST_STORE_SCALAR4, tmpIndex, envPtr);
+ }
+ TclEmitOpcode(INST_POP, envPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompile*OpCmd --
+ *
+ * Procedures called to compile the corresponding "::tcl::mathop::*"
+ * commands. These are all wrappers around the utility operator command
+ * compiler functions, except for the compilers for subtraction and
+ * division, which are special.
+ *
+ * Results:
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
+ *
+ * Side effects:
+ * Instructions are added to envPtr to execute the compiled command at
+ * runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileInvertOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ return CompileUnaryOpCmd(interp, parsePtr, INST_BITNOT, envPtr);
+}
+
+int
+TclCompileNotOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ return CompileUnaryOpCmd(interp, parsePtr, INST_LNOT, envPtr);
+}
+
+int
+TclCompileAddOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ return CompileAssociativeBinaryOpCmd(interp, parsePtr, "0", INST_ADD,
+ envPtr);
+}
+
+int
+TclCompileMulOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ return CompileAssociativeBinaryOpCmd(interp, parsePtr, "1", INST_MULT,
+ envPtr);
+}
+
+int
+TclCompileAndOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ return CompileAssociativeBinaryOpCmd(interp, parsePtr, "-1", INST_BITAND,
+ envPtr);
+}
+
+int
+TclCompileOrOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ return CompileAssociativeBinaryOpCmd(interp, parsePtr, "0", INST_BITOR,
+ envPtr);
+}
+
+int
+TclCompileXorOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ return CompileAssociativeBinaryOpCmd(interp, parsePtr, "0", INST_BITXOR,
+ envPtr);
+}
+
+int
+TclCompilePowOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ /*
+ * This one has its own implementation because the ** operator is
+ * the only one with right associativity.
+ */
+ Tcl_Token *tokenPtr = parsePtr->tokenPtr;
+ DefineLineInformation; /* TIP #280 */
+ int words;
+
+ for (words=1 ; words<parsePtr->numWords ; words++) {
+ tokenPtr = TokenAfter(tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, words);
+ }
+ if (parsePtr->numWords <= 2) {
+ PushLiteral(envPtr, "1", 1);
+ words++;
+ }
+ while (--words > 1) {
+ TclEmitOpcode(INST_EXPON, envPtr);
+ }
+ return TCL_OK;
+}
+
+int
+TclCompileLshiftOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_LSHIFT, envPtr);
+}
+
+int
+TclCompileRshiftOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_RSHIFT, envPtr);
+}
+
+int
+TclCompileModOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_MOD, envPtr);
+}
+
+int
+TclCompileNeqOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_NEQ, envPtr);
+}
+
+int
+TclCompileStrneqOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_STR_NEQ, envPtr);
+}
+
+int
+TclCompileInOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_LIST_IN, envPtr);
+}
+
+int
+TclCompileNiOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_LIST_NOT_IN,
+ envPtr);
+}
+
+int
+TclCompileLessOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ return CompileComparisonOpCmd(interp, parsePtr, INST_LT, envPtr);
+}
+
+int
+TclCompileLeqOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ return CompileComparisonOpCmd(interp, parsePtr, INST_LE, envPtr);
+}
+
+int
+TclCompileGreaterOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ return CompileComparisonOpCmd(interp, parsePtr, INST_GT, envPtr);
+}
+
+int
+TclCompileGeqOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ return CompileComparisonOpCmd(interp, parsePtr, INST_GE, envPtr);
+}
+
+int
+TclCompileEqOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ return CompileComparisonOpCmd(interp, parsePtr, INST_EQ, envPtr);
+}
+
+int
+TclCompileStreqOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ return CompileComparisonOpCmd(interp, parsePtr, INST_STR_EQ, envPtr);
+}
+
+int
+TclCompileMinusOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ Tcl_Token *tokenPtr = parsePtr->tokenPtr;
+ DefineLineInformation; /* TIP #280 */
+ int words;
+
+ if (parsePtr->numWords == 1) {
+ /* Fallback to direct eval to report syntax error */
+ return TCL_ERROR;
+ }
+ for (words=1 ; words<parsePtr->numWords ; words++) {
+ tokenPtr = TokenAfter(tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, words);
+ }
+ if (words == 2) {
+ TclEmitOpcode(INST_UMINUS, envPtr);
+ return TCL_OK;
+ }
+ if (words == 3) {
+ TclEmitOpcode(INST_SUB, envPtr);
+ return TCL_OK;
+ }
+ /*
+ * Reverse order of arguments to get precise agreement with
+ * [expr] in calcuations, including roundoff errors.
+ */
+ TclEmitInstInt4(INST_REVERSE, words-1, envPtr);
+ while (--words > 1) {
+ TclEmitInstInt4(INST_REVERSE, 2, envPtr);
+ TclEmitOpcode(INST_SUB, envPtr);
+ }
+ return TCL_OK;
+}
+
+int
+TclCompileDivOpCmd(
+ Tcl_Interp *interp,
+ Tcl_Parse *parsePtr,
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr)
+{
+ Tcl_Token *tokenPtr = parsePtr->tokenPtr;
+ DefineLineInformation; /* TIP #280 */
+ int words;
+
+ if (parsePtr->numWords == 1) {
+ /* Fallback to direct eval to report syntax error */
+ return TCL_ERROR;
+ }
+ if (parsePtr->numWords == 2) {
+ PushLiteral(envPtr, "1.0", 3);
+ }
+ for (words=1 ; words<parsePtr->numWords ; words++) {
+ tokenPtr = TokenAfter(tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, words);
+ }
+ if (words <= 3) {
+ TclEmitOpcode(INST_DIV, envPtr);
+ return TCL_OK;
+ }
+ /*
+ * Reverse order of arguments to get precise agreement with
+ * [expr] in calcuations, including roundoff errors.
+ */
+ TclEmitInstInt4(INST_REVERSE, words-1, envPtr);
+ while (--words > 1) {
+ TclEmitInstInt4(INST_REVERSE, 2, envPtr);
+ TclEmitOpcode(INST_DIV, envPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * IndexTailVarIfKnown --
+ *
+ * Procedure used in compiling [global] and [variable] commands. It
+ * inspects the variable name described by varTokenPtr and, if the tail
+ * is known at compile time, defines a corresponding local variable.
+ *
+ * Results:
+ * Returns the variable's index in the table of compiled locals if the
+ * tail is known at compile time, or -1 otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+IndexTailVarIfKnown(
+ Tcl_Interp *interp,
+ Tcl_Token *varTokenPtr, /* Token representing the variable name */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ Tcl_Obj *tailPtr;
+ const char *tailName, *p;
+ int len, n = varTokenPtr->numComponents;
+ Tcl_Token *lastTokenPtr;
+ int full, localIndex;
+
+ /*
+ * Determine if the tail is (a) known at compile time, and (b) not an
+ * array element. Should any of these fail, return an error so that
+ * the non-compiled command will be called at runtime.
+ * In order for the tail to be known at compile time, the last token
+ * in the word has to be constant and contain "::" if it is not the
+ * only one.
+ */
+
+ if (envPtr->procPtr == NULL) {
+ return -1;
+ }
+
+ TclNewObj(tailPtr);
+ if (TclWordKnownAtCompileTime(varTokenPtr, tailPtr)) {
+ full = 1;
+ lastTokenPtr = varTokenPtr;
+ } else {
+ full = 0;
+ lastTokenPtr = varTokenPtr + n;
+ if (!TclWordKnownAtCompileTime(lastTokenPtr, tailPtr)) {
+ Tcl_DecrRefCount(tailPtr);
+ return -1;
+ }
+ }
+
+ tailName = TclGetStringFromObj(tailPtr, &len);
+
+ if (len) {
+ if (*(tailName+len-1) == ')') {
+ /*
+ * Possible array: bail out
+ */
+
+ Tcl_DecrRefCount(tailPtr);
+ return -1;
+ }
+
+ /*
+ * Get the tail: immediately after the last '::'
+ */
+
+ for(p = tailName + len -1; p > tailName; p--) {
+ if ((*p == ':') && (*(p-1) == ':')) {
+ p++;
+ break;
+ }
+ }
+ if (!full && (p == tailName)) {
+ /*
+ * No :: in the last component
+ */
+ Tcl_DecrRefCount(tailPtr);
+ return -1;
+ }
+ len -= p - tailName;
+ tailName = p;
+ }
+
+ localIndex = TclFindCompiledLocal(tailName, len,
+ /*create*/ TCL_CREATE_VAR,
+ envPtr->procPtr);
+ Tcl_DecrRefCount(tailPtr);
+ return localIndex;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileUpvarCmd --
+ *
+ * Procedure called to compile the "upvar" command.
+ *
+ * Results:
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
+ *
+ * Side effects:
+ * Instructions are added to envPtr to execute the "upvar" command at
+ * runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileUpvarCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ Tcl_Token *tokenPtr, *otherTokenPtr, *localTokenPtr;
+ int simpleVarName, isScalar, localIndex, numWords, i;
+ DefineLineInformation; /* TIP #280 */
+ Tcl_Obj *objPtr = Tcl_NewObj();
+
+ if (envPtr->procPtr == NULL) {
+ Tcl_DecrRefCount(objPtr);
+ return TCL_ERROR;
+ }
+
+ numWords = parsePtr->numWords;
+ if (numWords < 3) {
+ Tcl_DecrRefCount(objPtr);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Push the frame index if it is known at compile time
+ */
+
+ tokenPtr = TokenAfter(parsePtr->tokenPtr);
+ if(TclWordKnownAtCompileTime(tokenPtr, objPtr)) {
+ CallFrame *framePtr;
+ Tcl_ObjType *newTypePtr, *typePtr = objPtr->typePtr;
+
+ /*
+ * Attempt to convert to a level reference. Note that TclObjGetFrame
+ * only changes the obj type when a conversion was successful.
+ */
+
+ TclObjGetFrame(interp, objPtr, &framePtr);
+ newTypePtr = objPtr->typePtr;
+ Tcl_DecrRefCount(objPtr);
+
+ if (newTypePtr != typePtr) {
+ if(numWords%2) {
+ return TCL_ERROR;
+ }
+ CompileWord(envPtr, tokenPtr, interp, 1);
+ otherTokenPtr = TokenAfter(tokenPtr);
+ i = 4;
+ } else {
+ if(!(numWords%2)) {
+ return TCL_ERROR;
+ }
+ PushLiteral(envPtr, "1", 1);
+ otherTokenPtr = tokenPtr;
+ i = 3;
+ }
+ } else {
+ Tcl_DecrRefCount(objPtr);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Loop over the (otherVar, thisVar) pairs. If any of the thisVar is not a
+ * local variable, return an error so that the non-compiled command will
+ * be called at runtime.
+ */
+
+ for(; i<=numWords; i+=2, otherTokenPtr = TokenAfter(localTokenPtr)) {
+ localTokenPtr = TokenAfter(otherTokenPtr);
+
+ CompileWord(envPtr, otherTokenPtr, interp, 1);
+ PushVarNameWord(interp, localTokenPtr, envPtr, TCL_CREATE_VAR,
+ &localIndex, &simpleVarName, &isScalar, 1);
+
+ if((localIndex < 0) || !isScalar) {
+ return TCL_ERROR;
+ }
+ TclEmitInstInt4(INST_UPVAR, localIndex, envPtr);
+ }
+
+ /*
+ * Pop the frame index, and set the result to empty
+ */
+
+ TclEmitOpcode(INST_POP, envPtr);
+ PushLiteral(envPtr, "", 0);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileNamespaceCmd --
+ *
+ * Procedure called to compile the "namespace" command; currently, only
+ * the subcommand "namespace upvar" is compiled to bytecodes.
+ *
+ * Results:
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
+ *
+ * Side effects:
+ * Instructions are added to envPtr to execute the "namespace upvar"
+ * command at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileNamespaceCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ Tcl_Token *tokenPtr, *otherTokenPtr, *localTokenPtr;
+ int simpleVarName, isScalar, localIndex, numWords, i;
+ DefineLineInformation; /* TIP #280 */
+
+ if (envPtr->procPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Only compile [namespace upvar ...]: needs an odd number of args, >=5
+ */
+
+ numWords = parsePtr->numWords;
+ if (!(numWords%2) || (numWords < 5)) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Check if the second argument is "upvar"
+ */
+
+ tokenPtr = TokenAfter(parsePtr->tokenPtr);
+ if ((tokenPtr->size != 5) /* 5 == strlen("upvar") */
+ || strncmp(tokenPtr->start, "upvar", 5)) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Push the namespace
+ */
+
+ tokenPtr = TokenAfter(tokenPtr);
+ CompileWord(envPtr, tokenPtr, interp, 1);
+
+ /*
+ * Loop over the (otherVar, thisVar) pairs. If any of the thisVar is not a
+ * local variable, return an error so that the non-compiled command will
+ * be called at runtime.
+ */
+
+ localTokenPtr = tokenPtr;
+ for(i=4; i<=numWords; i+=2) {
+ otherTokenPtr = TokenAfter(localTokenPtr);
+ localTokenPtr = TokenAfter(otherTokenPtr);
+
+ CompileWord(envPtr, otherTokenPtr, interp, 1);
+ PushVarNameWord(interp, localTokenPtr, envPtr, TCL_CREATE_VAR,
+ &localIndex, &simpleVarName, &isScalar, 1);
+
+ if((localIndex < 0) || !isScalar) {
+ return TCL_ERROR;
+ }
+ TclEmitInstInt4(INST_NSUPVAR, localIndex, envPtr);
+ }
+
+ /*
+ * Pop the namespace, and set the result to empty
+ */
+
+ TclEmitOpcode(INST_POP, envPtr);
+ PushLiteral(envPtr, "", 0);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileGlobalCmd --
+ *
+ * Procedure called to compile the "global" command.
+ *
+ * Results:
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
+ *
+ * Side effects:
+ * Instructions are added to envPtr to execute the "global" command at
+ * runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileGlobalCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ Tcl_Token *varTokenPtr;
+ int localIndex, numWords, i;
+ DefineLineInformation; /* TIP #280 */
+
+ numWords = parsePtr->numWords;
+ if (numWords < 2) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * 'global' has no effect outside of proc bodies; handle that at runtime
+ */
+
+ if (envPtr->procPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Push the namespace
+ */
+
+ PushLiteral(envPtr, "::", 2);
+
+ /*
+ * Loop over the variables.
+ */
+
+ varTokenPtr = TokenAfter(parsePtr->tokenPtr);
+ for(i=2; i<=numWords; varTokenPtr = TokenAfter(varTokenPtr),i++) {
+ localIndex = IndexTailVarIfKnown(interp, varTokenPtr, envPtr);
+
+ if(localIndex < 0) {
+ return TCL_ERROR;
+ }
+
+ CompileWord(envPtr, varTokenPtr, interp, 1);
+ TclEmitInstInt4(INST_NSUPVAR, localIndex, envPtr);
+ }
+
+ /*
+ * Pop the namespace, and set the result to empty
+ */
+
+ TclEmitOpcode(INST_POP, envPtr);
+ PushLiteral(envPtr, "", 0);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileVariableCmd --
+ *
+ * Procedure called to compile the "variable" command.
+ *
+ * Results:
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
+ *
+ * Side effects:
+ * Instructions are added to envPtr to execute the "variable" command at
+ * runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileVariableCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ Tcl_Token *varTokenPtr, *valueTokenPtr;
+ int localIndex, numWords, i;
+ DefineLineInformation; /* TIP #280 */
+
+ numWords = parsePtr->numWords;
+ if (numWords < 2) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Bail out if not compiling a proc body
+ */
+
+ if (envPtr->procPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Loop over the (var, value) pairs.
+ */
+
+ valueTokenPtr = parsePtr->tokenPtr;
+ for(i=2; i<=numWords; i+=2) {
+ varTokenPtr = TokenAfter(valueTokenPtr);
+ valueTokenPtr = TokenAfter(varTokenPtr);
+
+ localIndex = IndexTailVarIfKnown(interp, varTokenPtr, envPtr);
+
+ if(localIndex < 0) {
+ return TCL_ERROR;
+ }
+
+ CompileWord(envPtr, varTokenPtr, interp, 1);
+ TclEmitInstInt4(INST_VARIABLE, localIndex, envPtr);
+
+ if (i != numWords) {
+ /*
+ * A value has been given: set the variable, pop the value
+ */
+
+ CompileWord(envPtr, valueTokenPtr, interp, 1);
+ TclEmitInstInt4(INST_STORE_SCALAR4, localIndex, envPtr);
+ TclEmitOpcode(INST_POP, envPtr);
+ }
+ }
+
+ /*
+ * Set the result to empty
+ */
+
+ PushLiteral(envPtr, "", 0);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileEnsemble --
+ *
+ * Procedure called to compile an ensemble command. Note that most
+ * ensembles are not compiled, since modifying a compiled ensemble causes
+ * a invalidation of all existing bytecode (expensive!) which is not
+ * normally warranted.
+ *
+ * Results:
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
+ *
+ * Side effects:
+ * Instructions are added to envPtr to execute the subcommands of the
+ * ensemble at runtime if a compile-time mapping is possible.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileEnsemble(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ Tcl_Token *tokenPtr;
+ Tcl_Obj *mapObj, *subcmdObj, *targetCmdObj, *listObj, **elems;
+ Tcl_Command ensemble = (Tcl_Command) cmdPtr;
+ Tcl_Parse synthetic;
+ int len, numBytes, result, flags = 0, i;
+ const char *word;
+
+ if (parsePtr->numWords < 2) {
+ return TCL_ERROR;
+ }
+
+ tokenPtr = TokenAfter(parsePtr->tokenPtr);
+ if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
+ /*
+ * Too hard.
+ */
+
+ return TCL_ERROR;
+ }
+
+ word = tokenPtr[1].start;
+ numBytes = tokenPtr[1].size;
+
+ /*
+ * There's a sporting chance we'll be able to compile this. But now we
+ * must check properly. To do that, check that we're compiling an ensemble
+ * that has a compilable command as its appropriate subcommand.
+ */
+
+ if (Tcl_GetEnsembleMappingDict(NULL, ensemble, &mapObj) != TCL_OK
+ || mapObj == NULL) {
+ /*
+ * Either not an ensemble or a mapping isn't installed. Crud. Too hard
+ * to proceed.
+ */
+
+ return TCL_ERROR;
+ }
+
+ /*
+ * Next, get the flags. We need them on several code paths.
+ */
+
+ (void) Tcl_GetEnsembleFlags(NULL, ensemble, &flags);
+
+ /*
+ * Check to see if there's also a subcommand list; must check to see if
+ * the subcommand we are calling is in that list if it exists, since that
+ * list filters the entries in the map.
+ */
+
+ (void) Tcl_GetEnsembleSubcommandList(NULL, ensemble, &listObj);
+ if (listObj != NULL) {
+ int sclen;
+ const char *str;
+ Tcl_Obj *matchObj = NULL;
+
+ if (Tcl_ListObjGetElements(NULL, listObj, &len, &elems) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ for (i=0 ; i<len ; i++) {
+ str = Tcl_GetStringFromObj(elems[i], &sclen);
+ if (sclen==numBytes && !memcmp(word, str, (unsigned) numBytes)) {
+ /*
+ * Exact match! Excellent!
+ */
+
+ result = Tcl_DictObjGet(NULL, mapObj,elems[i], &targetCmdObj);
+ if (result != TCL_OK || targetCmdObj == NULL) {
+ return TCL_ERROR;
+ }
+ goto doneMapLookup;
+ }
+
+ /*
+ * Check to see if we've got a prefix match. A single prefix match
+ * is fine, and allows us to refine our dictionary lookup, but
+ * multiple prefix matches is a Bad Thing and will prevent us from
+ * making progress. Note that we cannot do the lookup immediately
+ * in the prefix case; might be another entry later in the list
+ * that causes things to fail.
+ */
+
+ if ((flags & TCL_ENSEMBLE_PREFIX)
+ && strncmp(word, str, (unsigned) numBytes) == 0) {
+ if (matchObj != NULL) {
+ return TCL_ERROR;
+ }
+ matchObj = elems[i];
+ }
+ }
+ if (matchObj != NULL) {
+ result = Tcl_DictObjGet(NULL, mapObj, matchObj, &targetCmdObj);
+ if (result != TCL_OK || targetCmdObj == NULL) {
+ return TCL_ERROR;
+ }
+ goto doneMapLookup;
+ }
+ return TCL_ERROR;
+ } else {
+ /*
+ * No map, so check the dictionary directly.
+ */
+
+ TclNewStringObj(subcmdObj, word, numBytes);
+ result = Tcl_DictObjGet(NULL, mapObj, subcmdObj, &targetCmdObj);
+ TclDecrRefCount(subcmdObj);
+ if (result == TCL_OK && targetCmdObj != NULL) {
+ /*
+ * Got it. Skip the fiddling around with prefixes.
+ */
+
+ goto doneMapLookup;
+ }
+
+ /*
+ * We've not literally got a valid subcommand. But maybe we have a
+ * prefix. Check if prefix matches are allowed.
+ */
+
+ if (flags & TCL_ENSEMBLE_PREFIX) {
+ Tcl_DictSearch s;
+ int done, matched;
+ Tcl_Obj *tmpObj;
+
+ /*
+ * Iterate over the keys in the dictionary, checking to see if
+ * we're a prefix.
+ */
+
+ Tcl_DictObjFirst(NULL,mapObj,&s,&subcmdObj,&tmpObj,&done);
+ matched = 0;
+ while (!done) {
+ if (strncmp(TclGetString(subcmdObj), word,
+ (unsigned) numBytes) == 0) {
+ if (matched++) {
+ /*
+ * Must have matched twice! Not unique, so no point
+ * looking further.
+ */
+
+ break;
+ }
+ targetCmdObj = tmpObj;
+ }
+ Tcl_DictObjNext(&s, &subcmdObj, &tmpObj, &done);
+ }
+ Tcl_DictObjDone(&s);
+
+ /*
+ * If we have anything other than a single match, we've failed the
+ * unique prefix check.
+ */
+
+ if (matched != 1) {
+ return TCL_ERROR;
+ }
+ } else {
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * OK, we definitely map to something. But what?
+ *
+ * The command we map to is the first word out of the map element. Note
+ * that we also reject dealing with multi-element rewrites if we are in a
+ * safe interpreter, as there is otherwise a (highly gnarly!) way to make
+ * Tcl crash open to exploit.
+ */
+
+ doneMapLookup:
+ if (Tcl_ListObjGetElements(NULL, targetCmdObj, &len, &elems) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (len > 1 && Tcl_IsSafe(interp)) {
+ return TCL_ERROR;
+ }
+ targetCmdObj = elems[0];
+
+ Tcl_IncrRefCount(targetCmdObj);
+ cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, targetCmdObj);
+ TclDecrRefCount(targetCmdObj);
+ if (cmdPtr == NULL || cmdPtr->compileProc == NULL) {
+ /*
+ * Maps to an undefined command or a command without a compiler.
+ * Cannot compile.
+ */
+
+ return TCL_ERROR;
+ }
+
+ /*
+ * Now we've done the mapping process, can now actually try to compile.
+ * We do this by handing off to the subcommand's actual compiler. But to
+ * do that, we have to perform some trickery to rewrite the arguments.
+ */
+
+ TclParseInit(interp, NULL, 0, &synthetic);
+ synthetic.numWords = parsePtr->numWords - 2 + len;
+ TclGrowParseTokenArray(&synthetic, 2*len);
+ synthetic.numTokens = 2*len;
+
+ /*
+ * Now we have the space to work in, install something rewritten. Note
+ * that we are here praying for all our might that none of these words are
+ * a script; the error detection code will crash if that happens and there
+ * is nothing we can do to avoid it!
+ */
+
+ for (i=0 ; i<len ; i++) {
+ int sclen;
+ const char *str = Tcl_GetStringFromObj(elems[i], &sclen);
+
+ synthetic.tokenPtr[2*i].type = TCL_TOKEN_SIMPLE_WORD;
+ synthetic.tokenPtr[2*i].start = str;
+ synthetic.tokenPtr[2*i].size = sclen;
+ synthetic.tokenPtr[2*i].numComponents = 1;
+
+ synthetic.tokenPtr[2*i+1].type = TCL_TOKEN_TEXT;
+ synthetic.tokenPtr[2*i+1].start = str;
+ synthetic.tokenPtr[2*i+1].size = sclen;
+ synthetic.tokenPtr[2*i+1].numComponents = 0;
+ }
+
+ /*
+ * Copy over the real argument tokens.
+ */
+
+ for (i=len; i<synthetic.numWords; i++) {
+ int toCopy;
+ tokenPtr = TokenAfter(tokenPtr);
+ toCopy = tokenPtr->numComponents + 1;
+ TclGrowParseTokenArray(&synthetic, toCopy);
+ memcpy(synthetic.tokenPtr + synthetic.numTokens, tokenPtr,
+ sizeof(Tcl_Token) * toCopy);
+ synthetic.numTokens += toCopy;
+ }
+
+ /*
+ * Hand off compilation to the subcommand compiler. At last!
+ */
+
+ result = cmdPtr->compileProc(interp, &synthetic, cmdPtr, envPtr);
+
+ /*
+ * Clean up if necessary.
+ */
+
+ Tcl_FreeParse(&synthetic);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileInfoExistsCmd --
+ *
+ * Procedure called to compile the "info exists" subcommand.
+ *
+ * Results:
+ * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer
+ * evaluation to runtime.
+ *
+ * Side effects:
+ * Instructions are added to envPtr to execute the "info exists"
+ * subcommand at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileInfoExistsCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ Tcl_Token *tokenPtr;
+ int isScalar, simpleVarName, localIndex;
+ DefineLineInformation; /* TIP #280 */
+
+ if (parsePtr->numWords != 2) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Decide if we can use a frame slot for the var/array name or if we need
+ * to emit code to compute and push the name at runtime. We use a frame
+ * slot (entry in the array of local vars) if we are compiling a procedure
+ * body and if the name is simple text that does not include namespace
+ * qualifiers.
+ */
+
+ tokenPtr = TokenAfter(parsePtr->tokenPtr);
+ PushVarNameWord(interp, tokenPtr, envPtr, TCL_CREATE_VAR, &localIndex,
+ &simpleVarName, &isScalar, 1);
+
+ /*
+ * Emit instruction to check the variable for existence.
+ */
+
+ if (simpleVarName) {
+ if (isScalar) {
+ if (localIndex < 0) {
+ TclEmitOpcode(INST_EXIST_STK, envPtr);
+ } else {
+ TclEmitInstInt4(INST_EXIST_SCALAR, localIndex, envPtr);
+ }
+ } else {
+ if (localIndex < 0) {
+ TclEmitOpcode(INST_EXIST_ARRAY_STK, envPtr);
+ } else {
+ TclEmitInstInt4(INST_EXIST_ARRAY, localIndex, envPtr);
+ }
+ }
+ } else {
+ TclEmitOpcode(INST_EXIST_STK, envPtr);
+ }
+
+ return TCL_OK;
}
/*
@@ -3470,4 +6474,3 @@ TclPushVarName(interp, varTokenPtr, envPtr, flags, localIndexPtr,
* fill-column: 78
* End:
*/
-
diff --git a/generic/tclCompExpr.c b/generic/tclCompExpr.c
index 68533c5..d5300db 100644
--- a/generic/tclCompExpr.c
+++ b/generic/tclCompExpr.c
@@ -1,696 +1,1995 @@
-/*
+/*
* tclCompExpr.c --
*
- * This file contains the code to compile Tcl expressions.
+ * This file contains the code to parse and compile Tcl expressions
+ * and implementations of the Tcl commands corresponding to expression
+ * operators, such as the command ::tcl::mathop::+ .
*
- * Copyright (c) 1997 Sun Microsystems, Inc.
- * Copyright (c) 1998-2000 by Scriptics Corporation.
+ * Contributions from Don Porter, NIST, 2006-2007. (not subject to US copyright)
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclCompile.h"
+#include "tclCompile.h" /* CompileEnv */
+
+/*
+ * Expression parsing takes place in the routine ParseExpr(). It takes a
+ * string as input, parses that string, and generates a representation of
+ * the expression in the form of a tree of operators, a list of literals,
+ * a list of function names, and an array of Tcl_Token's within a Tcl_Parse
+ * struct. The tree is composed of OpNodes.
+ */
+
+typedef struct OpNode {
+ int left; /* "Pointer" to the left operand. */
+ int right; /* "Pointer" to the right operand. */
+ union {
+ int parent; /* "Pointer" to the parent operand. */
+ int prev; /* "Pointer" joining incomplete tree stack */
+ } p;
+ unsigned char lexeme; /* Code that identifies the operator. */
+ unsigned char precedence; /* Precedence of the operator */
+ unsigned char mark; /* Mark used to control traversal. */
+ unsigned char constant; /* Flag marking constant subexpressions. */
+} OpNode;
+
+/*
+ * The storage for the tree is dynamically allocated array of OpNodes. The
+ * array is grown as parsing needs dictate according to a scheme similar to
+ * Tcl's string growth algorithm, so that the resizing costs are O(N) and so
+ * that we use at least half the memory allocated as expressions get large.
+ *
+ * Each OpNode in the tree represents an operator in the expression, either
+ * unary or binary. When parsing is completed successfully, a binary operator
+ * OpNode will have its left and right fields filled with "pointers" to its
+ * left and right operands. A unary operator OpNode will have its right field
+ * filled with a pointer to its single operand. When an operand is a
+ * subexpression the "pointer" takes the form of the index -- a non-negative
+ * integer -- into the OpNode storage array where the root of that
+ * subexpression parse tree is found.
+ *
+ * Non-operator elements of the expression do not get stored in the OpNode
+ * tree. They are stored in the other structures according to their type.
+ * Literal values get appended to the literal list. Elements that denote
+ * forms of quoting or substitution known to the Tcl parser get stored as
+ * Tcl_Tokens. These non-operator elements of the expression are the
+ * leaves of the completed parse tree. When an operand of an OpNode is
+ * one of these leaf elements, the following negative integer codes are used
+ * to indicate which kind of elements it is.
+ */
+
+enum OperandTypes {
+ OT_LITERAL = -3, /* Operand is a literal in the literal list */
+ OT_TOKENS = -2, /* Operand is sequence of Tcl_Tokens */
+ OT_EMPTY = -1 /* "Operand" is an empty string. This is a
+ * special case used only to represent the
+ * EMPTY lexeme. See below. */
+};
/*
- * The stuff below is a bit of a hack so that this file can be used in
- * environments that include no UNIX, i.e. no errno: just arrange to use
- * the errno from tclExecute.c here.
+ * Readable macros to test whether a "pointer" value points to an operator.
+ * They operate on the "non-negative integer -> operator; negative integer ->
+ * a non-operator OperandType" distinction.
+ */
+
+#define IsOperator(l) ((l) >= 0)
+#define NotOperator(l) ((l) < 0)
+
+/*
+ * Note that it is sufficient to store in the tree just the type of leaf
+ * operand, without any explicit pointer to which leaf. This is true because
+ * the traversals of the completed tree we perform are known to visit
+ * the leaves in the same order as the original parse.
+ *
+ * In a completed parse tree, those OpNodes that are themselves (roots of
+ * subexpression trees that are) operands of some operator store in their
+ * p.parent field a "pointer" to the OpNode of that operator. The p.parent
+ * field permits a traversal of the tree within a * non-recursive routine
+ * (ConvertTreeToTokens() and CompileExprTree()). This means that even
+ * expression trees of great depth pose no risk of blowing the C stack.
+ *
+ * While the parse tree is being constructed, the same memory space is used
+ * to hold the p.prev field which chains together a stack of incomplete
+ * trees awaiting their right operands.
+ *
+ * The lexeme field is filled in with the lexeme of the operator that is
+ * returned by the ParseLexeme() routine. Only lexemes for unary and
+ * binary operators get stored in an OpNode. Other lexmes get different
+ * treatement.
+ *
+ * The precedence field provides a place to store the precedence of the
+ * operator, so it need not be looked up again and again.
+ *
+ * The mark field is use to control the traversal of the tree, so
+ * that it can be done non-recursively. The mark values are:
*/
-#ifndef TCL_GENERIC_ONLY
-#include "tclPort.h"
-#else
-#define NO_ERRNO_H
-#endif
+enum Marks {
+ MARK_LEFT, /* Next step of traversal is to visit left subtree */
+ MARK_RIGHT, /* Next step of traversal is to visit right subtree */
+ MARK_PARENT /* Next step of traversal is to return to parent */
+};
-#ifdef NO_ERRNO_H
-extern int errno; /* Use errno from tclExecute.c. */
-#define ERANGE 34
-#endif
+/*
+ * The constant field is a boolean flag marking which subexpressions are
+ * completely known at compile time, and are eligible for computing then
+ * rather than waiting until run time.
+ */
/*
- * Boolean variable that controls whether expression compilation tracing
- * is enabled.
+ * Each lexeme belongs to one of four categories, which determine
+ * its place in the parse tree. We use the two high bits of the
+ * (unsigned char) value to store a NODE_TYPE code.
*/
-#ifdef TCL_COMPILE_DEBUG
-static int traceExprComp = 0;
-#endif /* TCL_COMPILE_DEBUG */
+#define NODE_TYPE 0xC0
+
+/*
+ * The four category values are LEAF, UNARY, and BINARY, explained below,
+ * and "uncategorized", which is used either temporarily, until context
+ * determines which of the other three categories is correct, or for
+ * lexemes like INVALID, which aren't really lexemes at all, but indicators
+ * of a parsing error. Note that the codes must be distinct to distinguish
+ * categories, but need not take the form of a bit array.
+ */
+#define BINARY 0x40 /* This lexeme is a binary operator. An
+ * OpNode representing it should go into the
+ * parse tree, and two operands should be
+ * parsed for it in the expression. */
+#define UNARY 0x80 /* This lexeme is a unary operator. An OpNode
+ * representing it should go into the parse
+ * tree, and one operand should be parsed for
+ * it in the expression. */
+#define LEAF 0xC0 /* This lexeme is a leaf operand in the parse
+ * tree. No OpNode will be placed in the tree
+ * for it. Either a literal value will be
+ * appended to the list of literals in this
+ * expression, or appropriate Tcl_Tokens will
+ * be appended in a Tcl_Parse struct to
+ * represent those leaves that require some
+ * form of substitution.
+ */
+
+/* Uncategorized lexemes */
+
+#define PLUS 1 /* Ambiguous. Resolves to UNARY_PLUS or
+ * BINARY_PLUS according to context. */
+#define MINUS 2 /* Ambiguous. Resolves to UNARY_MINUS or
+ * BINARY_MINUS according to context. */
+#define BAREWORD 3 /* Ambigous. Resolves to BOOLEAN or to
+ * FUNCTION or a parse error according to
+ * context and value. */
+#define INCOMPLETE 4 /* A parse error. Used only when the single
+ * "=" is encountered. */
+#define INVALID 5 /* A parse error. Used when any punctuation
+ * appears that's not a supported operator. */
+
+/* Leaf lexemes */
+
+#define NUMBER ( LEAF | 1) /* For literal numbers */
+#define SCRIPT ( LEAF | 2) /* Script substitution; [foo] */
+#define BOOLEAN ( LEAF | BAREWORD) /* For literal booleans */
+#define BRACED ( LEAF | 4) /* Braced string; {foo bar} */
+#define VARIABLE ( LEAF | 5) /* Variable substitution; $x */
+#define QUOTED ( LEAF | 6) /* Quoted string; "foo $bar [soom]" */
+#define EMPTY ( LEAF | 7) /* Used only for an empty argument
+ * list to a function. Represents
+ * the empty string within parens in
+ * the expression: rand() */
+
+/* Unary operator lexemes */
+
+#define UNARY_PLUS ( UNARY | PLUS)
+#define UNARY_MINUS ( UNARY | MINUS)
+#define FUNCTION ( UNARY | BAREWORD) /* This is a bit of "creative
+ * interpretation" on the part of the
+ * parser. A function call is parsed
+ * into the parse tree according to
+ * the perspective that the function
+ * name is a unary operator and its
+ * argument list, enclosed in parens,
+ * is its operand. The additional
+ * requirements not implied generally
+ * by treatment as a unary operator --
+ * for example, the requirement that
+ * the operand be enclosed in parens --
+ * are hard coded in the relevant
+ * portions of ParseExpr(). We trade
+ * off the need to include such
+ * exceptional handling in the code
+ * against the need we would otherwise
+ * have for more lexeme categories. */
+#define START ( UNARY | 4) /* This lexeme isn't parsed from the
+ * expression text at all. It
+ * represents the start of the
+ * expression and sits at the root of
+ * the parse tree where it serves as
+ * the start/end point of traversals. */
+#define OPEN_PAREN ( UNARY | 5) /* Another bit of creative
+ * interpretation, where we treat "("
+ * as a unary operator with the
+ * sub-expression between it and its
+ * matching ")" as its operand. See
+ * CLOSE_PAREN below. */
+#define NOT ( UNARY | 6)
+#define BIT_NOT ( UNARY | 7)
+
+/* Binary operator lexemes */
+
+#define BINARY_PLUS ( BINARY | PLUS)
+#define BINARY_MINUS ( BINARY | MINUS)
+#define COMMA ( BINARY | 3) /* The "," operator is a low precedence
+ * binary operator that separates the
+ * arguments in a function call. The
+ * additional constraint that this
+ * operator can only legally appear
+ * at the right places within a
+ * function call argument list are
+ * hard coded within ParseExpr(). */
+#define MULT ( BINARY | 4)
+#define DIVIDE ( BINARY | 5)
+#define MOD ( BINARY | 6)
+#define LESS ( BINARY | 7)
+#define GREATER ( BINARY | 8)
+#define BIT_AND ( BINARY | 9)
+#define BIT_XOR ( BINARY | 10)
+#define BIT_OR ( BINARY | 11)
+#define QUESTION ( BINARY | 12) /* These two lexemes make up the */
+#define COLON ( BINARY | 13) /* ternary conditional operator,
+ * $x ? $y : $z . We treat them as
+ * two binary operators to avoid
+ * another lexeme category, and
+ * code the additional constraints
+ * directly in ParseExpr(). For
+ * instance, the right operand of
+ * a "?" operator must be a ":"
+ * operator. */
+#define LEFT_SHIFT ( BINARY | 14)
+#define RIGHT_SHIFT ( BINARY | 15)
+#define LEQ ( BINARY | 16)
+#define GEQ ( BINARY | 17)
+#define EQUAL ( BINARY | 18)
+#define NEQ ( BINARY | 19)
+#define AND ( BINARY | 20)
+#define OR ( BINARY | 21)
+#define STREQ ( BINARY | 22)
+#define STRNEQ ( BINARY | 23)
+#define EXPON ( BINARY | 24) /* Unlike the other binary operators,
+ * EXPON is right associative and this
+ * distinction is coded directly in
+ * ParseExpr(). */
+#define IN_LIST ( BINARY | 25)
+#define NOT_IN_LIST ( BINARY | 26)
+#define CLOSE_PAREN ( BINARY | 27) /* By categorizing the CLOSE_PAREN
+ * lexeme as a BINARY operator, the
+ * normal parsing rules for binary
+ * operators assure that a close paren
+ * will not directly follow another
+ * operator, and the machinery already
+ * in place to connect operands to
+ * operators according to precedence
+ * performs most of the work of
+ * matching open and close parens for
+ * us. In the end though, a close
+ * paren is not really a binary
+ * operator, and some special coding
+ * in ParseExpr() make sure we never
+ * put an actual CLOSE_PAREN node
+ * in the parse tree. The
+ * sub-expression between parens
+ * becomes the single argument of
+ * the matching OPEN_PAREN unary
+ * operator. */
+#define END ( BINARY | 28) /* This lexeme represents the end of
+ * the string being parsed. Treating
+ * it as a binary operator follows the
+ * same logic as the CLOSE_PAREN lexeme
+ * and END pairs with START, in the
+ * same way that CLOSE_PAREN pairs with
+ * OPEN_PAREN. */
/*
- * The ExprInfo structure describes the state of compiling an expression.
- * A pointer to an ExprInfo record is passed among the routines in
- * this module.
+ * When ParseExpr() builds the parse tree it must choose which operands to
+ * connect to which operators. This is done according to operator precedence.
+ * The greater an operator's precedence the greater claim it has to link to
+ * an available operand. The Precedence enumeration lists the precedence
+ * values used by Tcl expression operators, from lowest to highest claim.
+ * Each precedence level is commented with the operators that hold that
+ * precedence.
*/
-typedef struct ExprInfo {
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Parse *parsePtr; /* Structure filled with information about
- * the parsed expression. */
- CONST char *expr; /* The expression that was originally passed
- * to TclCompileExpr. */
- CONST char *lastChar; /* Points just after last byte of expr. */
- int hasOperators; /* Set 1 if the expr has operators; 0 if
- * expr is only a primary. If 1 after
- * compiling an expr, a tryCvtToNumeric
- * instruction is emitted to convert the
- * primary to a number if possible. */
-} ExprInfo;
+enum Precedence {
+ PREC_END = 1, /* END */
+ PREC_START, /* START */
+ PREC_CLOSE_PAREN, /* ")" */
+ PREC_OPEN_PAREN, /* "(" */
+ PREC_COMMA, /* "," */
+ PREC_CONDITIONAL, /* "?", ":" */
+ PREC_OR, /* "||" */
+ PREC_AND, /* "&&" */
+ PREC_BIT_OR, /* "|" */
+ PREC_BIT_XOR, /* "^" */
+ PREC_BIT_AND, /* "&" */
+ PREC_EQUAL, /* "==", "!=", "eq", "ne", "in", "ni" */
+ PREC_COMPARE, /* "<", ">", "<=", ">=" */
+ PREC_SHIFT, /* "<<", ">>" */
+ PREC_ADD, /* "+", "-" */
+ PREC_MULT, /* "*", "/", "%" */
+ PREC_EXPON, /* "**" */
+ PREC_UNARY /* "+", "-", FUNCTION, "!", "~" */
+};
/*
- * Definitions of numeric codes representing each expression operator.
- * The order of these must match the entries in the operatorTable below.
- * Also the codes for the relational operators (OP_LESS, OP_GREATER,
- * OP_LE, OP_GE, OP_EQ, and OP_NE) must be consecutive and in that order.
- * Note that OP_PLUS and OP_MINUS represent both unary and binary operators.
+ * Here the same information contained in the comments above is stored
+ * in inverted form, so that given a lexeme, one can quickly look up
+ * its precedence value.
*/
-#define OP_MULT 0
-#define OP_DIVIDE 1
-#define OP_MOD 2
-#define OP_PLUS 3
-#define OP_MINUS 4
-#define OP_LSHIFT 5
-#define OP_RSHIFT 6
-#define OP_LESS 7
-#define OP_GREATER 8
-#define OP_LE 9
-#define OP_GE 10
-#define OP_EQ 11
-#define OP_NEQ 12
-#define OP_BITAND 13
-#define OP_BITXOR 14
-#define OP_BITOR 15
-#define OP_LAND 16
-#define OP_LOR 17
-#define OP_QUESTY 18
-#define OP_LNOT 19
-#define OP_BITNOT 20
-#define OP_STREQ 21
-#define OP_STRNEQ 22
+static const unsigned char prec[] = {
+ /* Non-operator lexemes */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,
+ /* Binary operator lexemes */
+ PREC_ADD, /* BINARY_PLUS */
+ PREC_ADD, /* BINARY_MINUS */
+ PREC_COMMA, /* COMMA */
+ PREC_MULT, /* MULT */
+ PREC_MULT, /* DIVIDE */
+ PREC_MULT, /* MOD */
+ PREC_COMPARE, /* LESS */
+ PREC_COMPARE, /* GREATER */
+ PREC_BIT_AND, /* BIT_AND */
+ PREC_BIT_XOR, /* BIT_XOR */
+ PREC_BIT_OR, /* BIT_OR */
+ PREC_CONDITIONAL, /* QUESTION */
+ PREC_CONDITIONAL, /* COLON */
+ PREC_SHIFT, /* LEFT_SHIFT */
+ PREC_SHIFT, /* RIGHT_SHIFT */
+ PREC_COMPARE, /* LEQ */
+ PREC_COMPARE, /* GEQ */
+ PREC_EQUAL, /* EQUAL */
+ PREC_EQUAL, /* NEQ */
+ PREC_AND, /* AND */
+ PREC_OR, /* OR */
+ PREC_EQUAL, /* STREQ */
+ PREC_EQUAL, /* STRNEQ */
+ PREC_EXPON, /* EXPON */
+ PREC_EQUAL, /* IN_LIST */
+ PREC_EQUAL, /* NOT_IN_LIST */
+ PREC_CLOSE_PAREN, /* CLOSE_PAREN */
+ PREC_END, /* END */
+ /* Expansion room for more binary operators */
+ 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,
+ /* Unary operator lexemes */
+ PREC_UNARY, /* UNARY_PLUS */
+ PREC_UNARY, /* UNARY_MINUS */
+ PREC_UNARY, /* FUNCTION */
+ PREC_START, /* START */
+ PREC_OPEN_PAREN, /* OPEN_PAREN */
+ PREC_UNARY, /* NOT*/
+ PREC_UNARY, /* BIT_NOT*/
+};
/*
- * Table describing the expression operators. Entries in this table must
- * correspond to the definitions of numeric codes for operators just above.
+ * A table mapping lexemes to bytecode instructions, used by CompileExprTree().
*/
-static int opTableInitialized = 0; /* 0 means not yet initialized. */
-
-TCL_DECLARE_MUTEX(opMutex)
-
-typedef struct OperatorDesc {
- char *name; /* Name of the operator. */
- int numOperands; /* Number of operands. 0 if the operator
- * requires special handling. */
- int instruction; /* Instruction opcode for the operator.
- * Ignored if numOperands is 0. */
-} OperatorDesc;
-
-static OperatorDesc operatorTable[] = {
- {"*", 2, INST_MULT},
- {"/", 2, INST_DIV},
- {"%", 2, INST_MOD},
- {"+", 0},
- {"-", 0},
- {"<<", 2, INST_LSHIFT},
- {">>", 2, INST_RSHIFT},
- {"<", 2, INST_LT},
- {">", 2, INST_GT},
- {"<=", 2, INST_LE},
- {">=", 2, INST_GE},
- {"==", 2, INST_EQ},
- {"!=", 2, INST_NEQ},
- {"&", 2, INST_BITAND},
- {"^", 2, INST_BITXOR},
- {"|", 2, INST_BITOR},
- {"&&", 0},
- {"||", 0},
- {"?", 0},
- {"!", 1, INST_LNOT},
- {"~", 1, INST_BITNOT},
- {"eq", 2, INST_STR_EQ},
- {"ne", 2, INST_STR_NEQ},
- {NULL}
+static const unsigned char instruction[] = {
+ /* Non-operator lexemes */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,
+ /* Binary operator lexemes */
+ INST_ADD, /* BINARY_PLUS */
+ INST_SUB, /* BINARY_MINUS */
+ 0, /* COMMA */
+ INST_MULT, /* MULT */
+ INST_DIV, /* DIVIDE */
+ INST_MOD, /* MOD */
+ INST_LT, /* LESS */
+ INST_GT, /* GREATER */
+ INST_BITAND, /* BIT_AND */
+ INST_BITXOR, /* BIT_XOR */
+ INST_BITOR, /* BIT_OR */
+ 0, /* QUESTION */
+ 0, /* COLON */
+ INST_LSHIFT, /* LEFT_SHIFT */
+ INST_RSHIFT, /* RIGHT_SHIFT */
+ INST_LE, /* LEQ */
+ INST_GE, /* GEQ */
+ INST_EQ, /* EQUAL */
+ INST_NEQ, /* NEQ */
+ 0, /* AND */
+ 0, /* OR */
+ INST_STR_EQ, /* STREQ */
+ INST_STR_NEQ, /* STRNEQ */
+ INST_EXPON, /* EXPON */
+ INST_LIST_IN, /* IN_LIST */
+ INST_LIST_NOT_IN, /* NOT_IN_LIST */
+ 0, /* CLOSE_PAREN */
+ 0, /* END */
+ /* Expansion room for more binary operators */
+ 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,
+ /* Unary operator lexemes */
+ INST_UPLUS, /* UNARY_PLUS */
+ INST_UMINUS, /* UNARY_MINUS */
+ 0, /* FUNCTION */
+ 0, /* START */
+ 0, /* OPEN_PAREN */
+ INST_LNOT, /* NOT*/
+ INST_BITNOT, /* BIT_NOT*/
};
/*
- * Hashtable used to map the names of expression operators to the index
- * of their OperatorDesc description.
+ * A table mapping a byte value to the corresponding lexeme for use by
+ * ParseLexeme().
*/
-static Tcl_HashTable opHashTable;
+static unsigned char Lexeme[] = {
+ INVALID /* NUL */, INVALID /* SOH */,
+ INVALID /* STX */, INVALID /* ETX */,
+ INVALID /* EOT */, INVALID /* ENQ */,
+ INVALID /* ACK */, INVALID /* BEL */,
+ INVALID /* BS */, INVALID /* HT */,
+ INVALID /* LF */, INVALID /* VT */,
+ INVALID /* FF */, INVALID /* CR */,
+ INVALID /* SO */, INVALID /* SI */,
+ INVALID /* DLE */, INVALID /* DC1 */,
+ INVALID /* DC2 */, INVALID /* DC3 */,
+ INVALID /* DC4 */, INVALID /* NAK */,
+ INVALID /* SYN */, INVALID /* ETB */,
+ INVALID /* CAN */, INVALID /* EM */,
+ INVALID /* SUB */, INVALID /* ESC */,
+ INVALID /* FS */, INVALID /* GS */,
+ INVALID /* RS */, INVALID /* US */,
+ INVALID /* SPACE */, 0 /* ! or != */,
+ QUOTED /* " */, INVALID /* # */,
+ VARIABLE /* $ */, MOD /* % */,
+ 0 /* & or && */, INVALID /* ' */,
+ OPEN_PAREN /* ( */, CLOSE_PAREN /* ) */,
+ 0 /* * or ** */, PLUS /* + */,
+ COMMA /* , */, MINUS /* - */,
+ 0 /* . */, DIVIDE /* / */,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0-9 */
+ COLON /* : */, INVALID /* ; */,
+ 0 /* < or << or <= */,
+ 0 /* == or INVALID */,
+ 0 /* > or >> or >= */,
+ QUESTION /* ? */, INVALID /* @ */,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A-M */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* N-Z */
+ SCRIPT /* [ */, INVALID /* \ */,
+ INVALID /* ] */, BIT_XOR /* ^ */,
+ INVALID /* _ */, INVALID /* ` */,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* a-m */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* n-z */
+ BRACED /* { */, 0 /* | or || */,
+ INVALID /* } */, BIT_NOT /* ~ */,
+ INVALID /* DEL */
+};
/*
- * Declarations for local procedures to this file:
+ * The JumpList struct is used to create a stack of data needed for the
+ * TclEmitForwardJump() and TclFixupForwardJump() calls that are performed
+ * when compiling the short-circuiting operators QUESTION/COLON, AND, and OR.
+ * Keeping a stack permits the CompileExprTree() routine to be non-recursive.
*/
-static int CompileCondExpr _ANSI_ARGS_((
- Tcl_Token *exprTokenPtr, ExprInfo *infoPtr,
- CompileEnv *envPtr, Tcl_Token **endPtrPtr));
-static int CompileLandOrLorExpr _ANSI_ARGS_((
- Tcl_Token *exprTokenPtr, int opIndex,
- ExprInfo *infoPtr, CompileEnv *envPtr,
- Tcl_Token **endPtrPtr));
-static int CompileMathFuncCall _ANSI_ARGS_((
- Tcl_Token *exprTokenPtr, CONST char *funcName,
- ExprInfo *infoPtr, CompileEnv *envPtr,
- Tcl_Token **endPtrPtr));
-static int CompileSubExpr _ANSI_ARGS_((
- Tcl_Token *exprTokenPtr, ExprInfo *infoPtr,
- CompileEnv *envPtr));
-static void LogSyntaxError _ANSI_ARGS_((ExprInfo *infoPtr));
+typedef struct JumpList {
+ JumpFixup jump; /* Pass this argument to matching calls of
+ * TclEmitForwardJump() and
+ * TclFixupForwardJump(). */
+ int depth; /* Remember the currStackDepth of the
+ * CompileEnv here. */
+ int offset; /* Data used to compute jump lengths to pass
+ * to TclFixupForwardJump() */
+ int convert; /* Temporary storage used to compute whether
+ * numeric conversion will be needed following
+ * the operator we're compiling. */
+ struct JumpList *next; /* Point to next item on the stack */
+} JumpList;
/*
- * Macro used to debug the execution of the expression compiler.
+ * Declarations for local functions to this file:
*/
-#ifdef TCL_COMPILE_DEBUG
-#define TRACE(exprBytes, exprLength, tokenBytes, tokenLength) \
- if (traceExprComp) { \
- fprintf(stderr, "CompileSubExpr: \"%.*s\", token \"%.*s\"\n", \
- (exprLength), (exprBytes), (tokenLength), (tokenBytes)); \
- }
-#else
-#define TRACE(exprBytes, exprLength, tokenBytes, tokenLength)
-#endif /* TCL_COMPILE_DEBUG */
+static void CompileExprTree(Tcl_Interp *interp, OpNode *nodes,
+ int index, Tcl_Obj *const **litObjvPtr,
+ Tcl_Obj *const *funcObjv, Tcl_Token *tokenPtr,
+ CompileEnv *envPtr, int optimize);
+static void ConvertTreeToTokens(const char *start, int numBytes,
+ OpNode *nodes, Tcl_Token *tokenPtr,
+ Tcl_Parse *parsePtr);
+static int ExecConstantExprTree(Tcl_Interp *interp, OpNode *nodes,
+ int index, Tcl_Obj * const **litObjvPtr);
+static int ParseExpr(Tcl_Interp *interp, const char *start,
+ int numBytes, OpNode **opTreePtr,
+ Tcl_Obj *litList, Tcl_Obj *funcList,
+ Tcl_Parse *parsePtr, int parseOnly);
+static int ParseLexeme(const char *start, int numBytes,
+ unsigned char *lexemePtr, Tcl_Obj **literalPtr);
+
/*
*----------------------------------------------------------------------
*
- * TclCompileExpr --
+ * ParseExpr --
*
- * This procedure compiles a string containing a Tcl expression into
- * Tcl bytecodes. This procedure is the top-level interface to the
- * the expression compilation module, and is used by such public
- * procedures as Tcl_ExprString, Tcl_ExprStringObj, Tcl_ExprLong,
- * Tcl_ExprDouble, Tcl_ExprBoolean, and Tcl_ExprBooleanObj.
+ * Given a string, the numBytes bytes starting at start, this function
+ * parses it as a Tcl expression and constructs a tree representing
+ * the structure of the expression. The caller must pass in empty
+ * lists as the funcList and litList arguments. The elements of the
+ * parsed expression are returned to the caller as that tree, a list of
+ * literal values, a list of function names, and in Tcl_Tokens
+ * added to a Tcl_Parse struct passed in by the caller.
*
* Results:
- * The return value is TCL_OK on a successful compilation and TCL_ERROR
- * on failure. If TCL_ERROR is returned, then the interpreter's result
- * contains an error message.
+ * If the string is successfully parsed as a valid Tcl expression, TCL_OK
+ * is returned, and data about the expression structure is written to
+ * the last four arguments. If the string cannot be parsed as a valid
+ * Tcl expression, TCL_ERROR is returned, and if interp is non-NULL, an
+ * error message is written to interp.
*
* Side effects:
- * Adds instructions to envPtr to evaluate the expression at runtime.
+ * Memory will be allocated. If TCL_OK is returned, the caller must
+ * clean up the returned data structures. The (OpNode *) value written
+ * to opTreePtr should be passed to ckfree() and the parsePtr argument
+ * should be passed to Tcl_FreeParse(). The elements appended to the
+ * litList and funcList will automatically be freed whenever the
+ * refcount on those lists indicates they can be freed.
*
*----------------------------------------------------------------------
*/
-int
-TclCompileExpr(interp, script, numBytes, envPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- CONST char *script; /* The source script to compile. */
- int numBytes; /* Number of bytes in script. If < 0, the
- * string consists of all bytes up to the
- * first null character. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
+static int
+ParseExpr(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ const char *start, /* Start of source string to parse. */
+ int numBytes, /* Number of bytes in string. */
+ OpNode **opTreePtr, /* Points to space where a pointer to the
+ * allocated OpNode tree should go. */
+ Tcl_Obj *litList, /* List to append literals to. */
+ Tcl_Obj *funcList, /* List to append function names to. */
+ Tcl_Parse *parsePtr, /* Structure to fill with tokens representing
+ * those operands that require run time
+ * substitutions. */
+ int parseOnly) /* A boolean indicating whether the caller's
+ * aim is just a parse, or whether it will go
+ * on to compile the expression. Different
+ * optimizations are appropriate for the
+ * two scenarios. */
{
- ExprInfo info;
- Tcl_Parse parse;
- Tcl_HashEntry *hPtr;
- int new, i, code;
+ OpNode *nodes = NULL; /* Pointer to the OpNode storage array where
+ * we build the parse tree. */
+ int nodesAvailable = 64; /* Initial size of the storage array. This
+ * value establishes a minimum tree memory cost
+ * of only about 1 kibyte, and is large enough
+ * for most expressions to parse with no need
+ * for array growth and reallocation. */
+ int nodesUsed = 0; /* Number of OpNodes filled. */
+ int scanned = 0; /* Capture number of byte scanned by
+ * parsing routines. */
+ int lastParsed; /* Stores info about what the lexeme parsed
+ * the previous pass through the parsing loop
+ * was. If it was an operator, lastParsed is
+ * the index of the OpNode for that operator.
+ * If it was not an operator, lastParsed holds
+ * an OperandTypes value encoding what we
+ * need to know about it. */
+ int incomplete; /* Index of the most recent incomplete tree
+ * in the OpNode array. Heads a stack of
+ * incomplete trees linked by p.prev. */
+ int complete = OT_EMPTY; /* "Index" of the complete tree (that is, a
+ * complete subexpression) determined at the
+ * moment. OT_EMPTY is a nonsense value
+ * used only to silence compiler warnings.
+ * During a parse, complete will always hold
+ * an index or an OperandTypes value pointing
+ * to an actual leaf at the time the complete
+ * tree is needed. */
+
+ /* These variables control generation of the error message. */
+ Tcl_Obj *msg = NULL; /* The error message. */
+ Tcl_Obj *post = NULL; /* In a few cases, an additional postscript
+ * for the error message, supplying more
+ * information after the error msg and
+ * location have been reported. */
+ const char *mark = "_@_"; /* In the portion of the complete error message
+ * where the error location is reported, this
+ * "mark" substring is inserted into the
+ * string being parsed to aid in pinpointing
+ * the location of the syntax error in the
+ * expression. */
+ int insertMark = 0; /* A boolean controlling whether the "mark"
+ * should be inserted. */
+ const int limit = 25; /* Portions of the error message are
+ * constructed out of substrings of the
+ * original expression. In order to keep the
+ * error message readable, we impose this limit
+ * on the substring size we extract. */
+
+ TclParseInit(interp, start, numBytes, parsePtr);
+
+ nodes = (OpNode *) attemptckalloc(nodesAvailable * sizeof(OpNode));
+ if (nodes == NULL) {
+ TclNewLiteralStringObj(msg, "not enough memory to parse expression");
+ goto error;
+ }
+
+ /* Initialize the parse tree with the special "START" node. */
+ nodes->lexeme = START;
+ nodes->precedence = prec[START];
+ nodes->mark = MARK_RIGHT;
+ nodes->constant = 1;
+ incomplete = lastParsed = nodesUsed;
+ nodesUsed++;
/*
- * If this is the first time we've been called, initialize the table
- * of expression operators.
+ * Main parsing loop parses one lexeme per iteration. We exit the
+ * loop only when there's a syntax error with a "goto error" which
+ * takes us to the error handling code following the loop, or when
+ * we've successfully completed the parse and we return to the caller.
*/
- if (numBytes < 0) {
- numBytes = (script? strlen(script) : 0);
- }
- if (!opTableInitialized) {
- Tcl_MutexLock(&opMutex);
- if (!opTableInitialized) {
- Tcl_InitHashTable(&opHashTable, TCL_STRING_KEYS);
- for (i = 0; operatorTable[i].name != NULL; i++) {
- hPtr = Tcl_CreateHashEntry(&opHashTable,
- operatorTable[i].name, &new);
- if (new) {
- Tcl_SetHashValue(hPtr, (ClientData) i);
- }
+ while (1) {
+ OpNode *nodePtr; /* Points to the OpNode we may fill this
+ * pass through the loop. */
+ unsigned char lexeme; /* The lexeme we parse this iteration. */
+ Tcl_Obj *literal; /* Filled by the ParseLexeme() call when
+ * a literal is parsed that has a Tcl_Obj
+ * rep worth preserving. */
+ const char *lastStart = start - scanned;
+ /* Compute where the lexeme parsed the
+ * previous pass through the loop began.
+ * This is helpful for detecting invalid
+ * octals and providing more complete error
+ * messages. */
+
+ /*
+ * Each pass through this loop adds up to one more OpNode. Allocate
+ * space for one if required.
+ */
+
+ if (nodesUsed >= nodesAvailable) {
+ int size = nodesUsed * 2;
+ OpNode *newPtr;
+
+ do {
+ newPtr = (OpNode *) attemptckrealloc((char *) nodes,
+ (unsigned int) size * sizeof(OpNode));
+ } while ((newPtr == NULL)
+ && ((size -= (size - nodesUsed) / 2) > nodesUsed));
+ if (newPtr == NULL) {
+ TclNewLiteralStringObj(msg,
+ "not enough memory to parse expression");
+ goto error;
}
- opTableInitialized = 1;
+ nodesAvailable = size;
+ nodes = newPtr;
}
- Tcl_MutexUnlock(&opMutex);
- }
+ nodePtr = nodes + nodesUsed;
+
+ /* Skip white space between lexemes. */
+ scanned = TclParseAllWhiteSpace(start, numBytes);
+ start += scanned;
+ numBytes -= scanned;
+
+ scanned = ParseLexeme(start, numBytes, &lexeme, &literal);
+
+ /* Use context to categorize the lexemes that are ambiguous. */
+ if ((NODE_TYPE & lexeme) == 0) {
+ switch (lexeme) {
+ case INVALID:
+ msg = Tcl_ObjPrintf(
+ "invalid character \"%.*s\"", scanned, start);
+ goto error;
+ case INCOMPLETE:
+ msg = Tcl_ObjPrintf(
+ "incomplete operator \"%.*s\"", scanned, start);
+ goto error;
+ case BAREWORD:
+
+ /*
+ * Most barewords in an expression are a syntax error.
+ * The exceptions are that when a bareword is followed by
+ * an open paren, it might be a function call, and when the
+ * bareword is a legal literal boolean value, we accept that
+ * as well.
+ */
+
+ if (start[scanned+TclParseAllWhiteSpace(
+ start+scanned, numBytes-scanned)] == '(') {
+ lexeme = FUNCTION;
- /*
- * Initialize the structure containing information abvout this
- * expression compilation.
- */
+ /*
+ * When we compile the expression we'll need the function
+ * name, and there's no place in the parse tree to store
+ * it, so we keep a separate list of all the function
+ * names we've parsed in the order we found them.
+ */
+
+ Tcl_ListObjAppendElement(NULL, funcList, literal);
+ } else {
+ int b;
+ if (Tcl_GetBooleanFromObj(NULL, literal, &b) == TCL_OK) {
+ lexeme = BOOLEAN;
+ } else {
+ Tcl_DecrRefCount(literal);
+ msg = Tcl_ObjPrintf(
+ "invalid bareword \"%.*s%s\"",
+ (scanned < limit) ? scanned : limit - 3, start,
+ (scanned < limit) ? "" : "...");
+ post = Tcl_ObjPrintf(
+ "should be \"$%.*s%s\" or \"{%.*s%s}\"",
+ (scanned < limit) ? scanned : limit - 3,
+ start, (scanned < limit) ? "" : "...",
+ (scanned < limit) ? scanned : limit - 3,
+ start, (scanned < limit) ? "" : "...");
+ Tcl_AppendPrintfToObj(post,
+ " or \"%.*s%s(...)\" or ...",
+ (scanned < limit) ? scanned : limit - 3,
+ start, (scanned < limit) ? "" : "...");
+ if (NotOperator(lastParsed)) {
+ if ((lastStart[0] == '0')
+ && ((lastStart[1] == 'o')
+ || (lastStart[1] == 'O'))
+ && (lastStart[2] >= '0')
+ && (lastStart[2] <= '9')) {
+ const char *end = lastStart + 2;
+ Tcl_Obj* copy;
+ while (isdigit(UCHAR(*end))) {
+ end++;
+ }
+ copy = Tcl_NewStringObj(lastStart,
+ end - lastStart);
+ if (TclCheckBadOctal(NULL,
+ Tcl_GetString(copy))) {
+ Tcl_AppendToObj(post,
+ "(invalid octal number?)", -1);
+ }
+ Tcl_DecrRefCount(copy);
+ }
+ scanned = 0;
+ insertMark = 1;
+ parsePtr->errorType = TCL_PARSE_BAD_NUMBER;
+ }
+ goto error;
+ }
+ }
+ break;
+ case PLUS:
+ case MINUS:
+ if (IsOperator(lastParsed)) {
+
+ /*
+ * A "+" or "-" coming just after another operator
+ * must be interpreted as a unary operator.
+ */
+
+ lexeme |= UNARY;
+ } else {
+ lexeme |= BINARY;
+ }
+ }
+ } /* Uncategorized lexemes */
+
+ /* Handle lexeme based on its category. */
+ switch (NODE_TYPE & lexeme) {
+
+ /*
+ * Each LEAF results in either a literal getting appended to the
+ * litList, or a sequence of Tcl_Tokens representing a Tcl word
+ * getting appended to the parsePtr->tokens. No OpNode is filled
+ * for this lexeme.
+ */
+
+ case LEAF: {
+ Tcl_Token *tokenPtr;
+ const char *end = start;
+ int wordIndex;
+ int code = TCL_OK;
+
+ /*
+ * A leaf operand appearing just after something that's not an
+ * operator is a syntax error.
+ */
+
+ if (NotOperator(lastParsed)) {
+ msg = Tcl_ObjPrintf("missing operator at %s", mark);
+ if (lastStart[0] == '0') {
+ Tcl_Obj *copy = Tcl_NewStringObj(lastStart,
+ start + scanned - lastStart);
+ if (TclCheckBadOctal(NULL, Tcl_GetString(copy))) {
+ TclNewLiteralStringObj(post,
+ "looks like invalid octal number");
+ }
+ Tcl_DecrRefCount(copy);
+ }
+ scanned = 0;
+ insertMark = 1;
+ parsePtr->errorType = TCL_PARSE_BAD_NUMBER;
+
+ /* Free any literal to avoid a memleak. */
+ if ((lexeme == NUMBER) || (lexeme == BOOLEAN)) {
+ Tcl_DecrRefCount(literal);
+ }
+ goto error;
+ }
+
+ switch (lexeme) {
+ case NUMBER:
+ case BOOLEAN:
+ /*
+ * TODO: Consider using a dict or hash to collapse all
+ * duplicate literals into a single representative value.
+ * (Like what is done with [split $s {}]).
+ * Pro: ~75% memory saving on expressions like
+ * {1+1+1+1+1+.....+1} (Convert "pointer + Tcl_Obj" cost
+ * to "pointer" cost only)
+ * Con: Cost of the dict store/retrieve on every literal
+ * in every expression when expressions like the above
+ * tend to be uncommon.
+ * The memory savings is temporary; Compiling to bytecode
+ * will collapse things as literals are registered
+ * anyway, so the savings applies only to the time
+ * between parsing and compiling. Possibly important
+ * due to high-water mark nature of memory allocation.
+ */
+ Tcl_ListObjAppendElement(NULL, litList, literal);
+ complete = lastParsed = OT_LITERAL;
+ start += scanned;
+ numBytes -= scanned;
+ continue;
+
+ default:
+ break;
+ }
+
+ /*
+ * Remaining LEAF cases may involve filling Tcl_Tokens, so
+ * make room for at least 2 more tokens.
+ */
+
+ TclGrowParseTokenArray(parsePtr, 2);
+ wordIndex = parsePtr->numTokens;
+ tokenPtr = parsePtr->tokenPtr + wordIndex;
+ tokenPtr->type = TCL_TOKEN_WORD;
+ tokenPtr->start = start;
+ parsePtr->numTokens++;
+
+ switch (lexeme) {
+ case QUOTED:
+ code = Tcl_ParseQuotedString(NULL, start, numBytes,
+ parsePtr, 1, &end);
+ scanned = end - start;
+ break;
+
+ case BRACED:
+ code = Tcl_ParseBraces(NULL, start, numBytes,
+ parsePtr, 1, &end);
+ scanned = end - start;
+ break;
+
+ case VARIABLE:
+ code = Tcl_ParseVarName(NULL, start, numBytes, parsePtr, 1);
+
+ /*
+ * Handle the quirk that Tcl_ParseVarName reports a successful
+ * parse even when it gets only a "$" with no variable name.
+ */
+
+ tokenPtr = parsePtr->tokenPtr + wordIndex + 1;
+ if (code == TCL_OK && tokenPtr->type != TCL_TOKEN_VARIABLE) {
+ TclNewLiteralStringObj(msg, "invalid character \"$\"");
+ goto error;
+ }
+ scanned = tokenPtr->size;
+ break;
+
+ case SCRIPT: {
+ Tcl_Parse *nestedPtr =
+ (Tcl_Parse *) TclStackAlloc(interp, sizeof(Tcl_Parse));
+
+ tokenPtr = parsePtr->tokenPtr + parsePtr->numTokens;
+ tokenPtr->type = TCL_TOKEN_COMMAND;
+ tokenPtr->start = start;
+ tokenPtr->numComponents = 0;
+
+ end = start + numBytes;
+ start++;
+ while (1) {
+ code = Tcl_ParseCommand(interp, start, (end - start), 1,
+ nestedPtr);
+ if (code != TCL_OK) {
+ parsePtr->term = nestedPtr->term;
+ parsePtr->errorType = nestedPtr->errorType;
+ parsePtr->incomplete = nestedPtr->incomplete;
+ break;
+ }
+ start = (nestedPtr->commandStart + nestedPtr->commandSize);
+ Tcl_FreeParse(nestedPtr);
+ if ((nestedPtr->term < end) && (*(nestedPtr->term) == ']')
+ && !(nestedPtr->incomplete)) {
+ break;
+ }
+
+ if (start == end) {
+ TclNewLiteralStringObj(msg, "missing close-bracket");
+ parsePtr->term = tokenPtr->start;
+ parsePtr->errorType = TCL_PARSE_MISSING_BRACKET;
+ parsePtr->incomplete = 1;
+ code = TCL_ERROR;
+ break;
+ }
+ }
+ TclStackFree(interp, nestedPtr);
+ end = start;
+ start = tokenPtr->start;
+ scanned = end - start;
+ tokenPtr->size = scanned;
+ parsePtr->numTokens++;
+ break;
+ }
+ }
+ if (code != TCL_OK) {
+
+ /*
+ * Here we handle all the syntax errors generated by
+ * the Tcl_Token generating parsing routines called in the
+ * switch just above. If the value of parsePtr->incomplete
+ * is 1, then the error was an unbalanced '[', '(', '{',
+ * or '"' and parsePtr->term is pointing to that unbalanced
+ * character. If the value of parsePtr->incomplete is 0,
+ * then the error is one of lacking whitespace following a
+ * quoted word, for example: expr {[an error {foo}bar]},
+ * and parsePtr->term points to where the whitespace is
+ * missing. We reset our values of start and scanned so that
+ * when our error message is constructed, the location of
+ * the syntax error is sure to appear in it, even if the
+ * quoted expression is truncated.
+ */
+
+ start = parsePtr->term;
+ scanned = parsePtr->incomplete;
+ goto error;
+ }
+
+ tokenPtr = parsePtr->tokenPtr + wordIndex;
+ tokenPtr->size = scanned;
+ tokenPtr->numComponents = parsePtr->numTokens - wordIndex - 1;
+ if (!parseOnly && ((lexeme == QUOTED) || (lexeme == BRACED))) {
+
+ /*
+ * When this expression is destined to be compiled, and a
+ * braced or quoted word within an expression is known at
+ * compile time (no runtime substitutions in it), we can
+ * store it as a literal rather than in its tokenized form.
+ * This is an advantage since the compiled bytecode is going
+ * to need the argument in Tcl_Obj form eventually, so it's
+ * just as well to get there now. Another advantage is that
+ * with this conversion, larger constant expressions might
+ * be grown and optimized.
+ *
+ * On the contrary, if the end goal of this parse is to
+ * fill a Tcl_Parse for a caller of Tcl_ParseExpr(), then it's
+ * wasteful to convert to a literal only to convert back again
+ * later.
+ */
+
+ literal = Tcl_NewObj();
+ if (TclWordKnownAtCompileTime(tokenPtr, literal)) {
+ Tcl_ListObjAppendElement(NULL, litList, literal);
+ complete = lastParsed = OT_LITERAL;
+ parsePtr->numTokens = wordIndex;
+ break;
+ }
+ Tcl_DecrRefCount(literal);
+ }
+ complete = lastParsed = OT_TOKENS;
+ break;
+ } /* case LEAF */
+
+ case UNARY:
+
+ /*
+ * A unary operator appearing just after something that's not an
+ * operator is a syntax error -- something trying to be the left
+ * operand of an operator that doesn't take one.
+ */
+
+ if (NotOperator(lastParsed)) {
+ msg = Tcl_ObjPrintf("missing operator at %s", mark);
+ scanned = 0;
+ insertMark = 1;
+ goto error;
+ }
+
+ /* Create an OpNode for the unary operator */
+ nodePtr->lexeme = lexeme;
+ nodePtr->precedence = prec[lexeme];
+ nodePtr->mark = MARK_RIGHT;
+
+ /*
+ * A FUNCTION cannot be a constant expression, because Tcl allows
+ * functions to return variable results with the same arguments;
+ * for example, rand(). Other unary operators can root a constant
+ * expression, so long as the argument is a constant expression.
+ */
+
+ nodePtr->constant = (lexeme != FUNCTION);
+
+ /*
+ * This unary operator is a new incomplete tree, so push it
+ * onto our stack of incomplete trees. Also remember it as
+ * the last lexeme we parsed.
+ */
+
+ nodePtr->p.prev = incomplete;
+ incomplete = lastParsed = nodesUsed;
+ nodesUsed++;
+ break;
+
+ case BINARY: {
+ OpNode *incompletePtr;
+ unsigned char precedence = prec[lexeme];
+
+ /*
+ * A binary operator appearing just after another operator is a
+ * syntax error -- one of the two operators is missing an operand.
+ */
+
+ if (IsOperator(lastParsed)) {
+ if ((lexeme == CLOSE_PAREN)
+ && (nodePtr[-1].lexeme == OPEN_PAREN)) {
+ if (nodePtr[-2].lexeme == FUNCTION) {
+
+ /*
+ * Normally, "()" is a syntax error, but as a special
+ * case accept it as an argument list for a function.
+ * Treat this as a special LEAF lexeme, and restart
+ * the parsing loop with zero characters scanned.
+ * We'll parse the ")" again the next time through,
+ * but with the OT_EMPTY leaf as the subexpression
+ * between the parens.
+ */
+
+ scanned = 0;
+ complete = lastParsed = OT_EMPTY;
+ break;
+ }
+ msg = Tcl_ObjPrintf("empty subexpression at %s", mark);
+ scanned = 0;
+ insertMark = 1;
+ goto error;
+ }
+
+ if (nodePtr[-1].precedence > precedence) {
+ if (nodePtr[-1].lexeme == OPEN_PAREN) {
+ TclNewLiteralStringObj(msg, "unbalanced open paren");
+ parsePtr->errorType = TCL_PARSE_MISSING_PAREN;
+ } else if (nodePtr[-1].lexeme == COMMA) {
+ msg = Tcl_ObjPrintf(
+ "missing function argument at %s", mark);
+ scanned = 0;
+ insertMark = 1;
+ } else if (nodePtr[-1].lexeme == START) {
+ TclNewLiteralStringObj(msg, "empty expression");
+ }
+ } else {
+ if (lexeme == CLOSE_PAREN) {
+ TclNewLiteralStringObj(msg, "unbalanced close paren");
+ } else if ((lexeme == COMMA)
+ && (nodePtr[-1].lexeme == OPEN_PAREN)
+ && (nodePtr[-2].lexeme == FUNCTION)) {
+ msg = Tcl_ObjPrintf(
+ "missing function argument at %s", mark);
+ scanned = 0;
+ insertMark = 1;
+ }
+ }
+ if (msg == NULL) {
+ msg = Tcl_ObjPrintf("missing operand at %s", mark);
+ scanned = 0;
+ insertMark = 1;
+ }
+ goto error;
+ }
- info.interp = interp;
- info.parsePtr = &parse;
- info.expr = script;
- info.lastChar = (script + numBytes);
- info.hasOperators = 0;
+ /*
+ * Here is where the tree comes together. At this point, we
+ * have a stack of incomplete trees corresponding to
+ * substrings that are incomplete expressions, followed by
+ * a complete tree corresponding to a substring that is itself
+ * a complete expression, followed by the binary operator we have
+ * just parsed. The incomplete trees can each be completed by
+ * adding a right operand.
+ *
+ * To illustrate with an example, when we parse the expression
+ * "1+2*3-4" and we reach this point having just parsed the "-"
+ * operator, we have these incomplete trees: START, "1+", and
+ * "2*". Next we have the complete subexpression "3". Last is
+ * the "-" we've just parsed.
+ *
+ * The next step is to join our complete tree to an operator.
+ * The choice is governed by the precedence and associativity
+ * of the competing operators. If we connect it as the right
+ * operand of our most recent incomplete tree, we get a new
+ * complete tree, and we can repeat the process. The while
+ * loop following repeats this until precedence indicates it
+ * is time to join the complete tree as the left operand of
+ * the just parsed binary operator.
+ *
+ * Continuing the example, the first pass through the loop
+ * will join "3" to "2*"; the next pass will join "2*3" to
+ * "1+". Then we'll exit the loop and join "1+2*3" to "-".
+ * When we return to parse another lexeme, our stack of
+ * incomplete trees is START and "1+2*3-".
+ */
+
+ while (1) {
+ incompletePtr = nodes + incomplete;
+
+ if (incompletePtr->precedence < precedence) {
+ break;
+ }
+
+ if (incompletePtr->precedence == precedence) {
+
+ /* Right association rules for exponentiation. */
+ if (lexeme == EXPON) {
+ break;
+ }
+
+ /*
+ * Special association rules for the conditional operators.
+ * The "?" and ":" operators have equal precedence, but
+ * must be linked up in sensible pairs.
+ */
+
+ if ((incompletePtr->lexeme == QUESTION)
+ && (NotOperator(complete)
+ || (nodes[complete].lexeme != COLON))) {
+ break;
+ }
+ if ((incompletePtr->lexeme == COLON)
+ && (lexeme == QUESTION)) {
+ break;
+ }
+ }
+
+ /* Some special syntax checks... */
+
+ /* Parens must balance */
+ if ((incompletePtr->lexeme == OPEN_PAREN)
+ && (lexeme != CLOSE_PAREN)) {
+ TclNewLiteralStringObj(msg, "unbalanced open paren");
+ parsePtr->errorType = TCL_PARSE_MISSING_PAREN;
+ goto error;
+ }
+
+ /* Right operand of "?" must be ":" */
+ if ((incompletePtr->lexeme == QUESTION)
+ && (NotOperator(complete)
+ || (nodes[complete].lexeme != COLON))) {
+ msg = Tcl_ObjPrintf(
+ "missing operator \":\" at %s", mark);
+ scanned = 0;
+ insertMark = 1;
+ goto error;
+ }
+
+ /* Operator ":" may only be right operand of "?" */
+ if (IsOperator(complete)
+ && (nodes[complete].lexeme == COLON)
+ && (incompletePtr->lexeme != QUESTION)) {
+ TclNewLiteralStringObj(msg,
+ "unexpected operator \":\" "
+ "without preceding \"?\"");
+ goto error;
+ }
+
+ /*
+ * Attach complete tree as right operand of most recent
+ * incomplete tree.
+ */
+
+ incompletePtr->right = complete;
+ if (IsOperator(complete)) {
+ nodes[complete].p.parent = incomplete;
+ incompletePtr->constant = incompletePtr->constant
+ && nodes[complete].constant;
+ } else {
+ incompletePtr->constant = incompletePtr->constant
+ && (complete == OT_LITERAL);
+ }
+
+ /*
+ * The QUESTION/COLON and FUNCTION/OPEN_PAREN combinations each
+ * make up a single operator. Force them to agree whether they
+ * have a constant expression.
+ */
+
+ if ((incompletePtr->lexeme == QUESTION)
+ || (incompletePtr->lexeme == FUNCTION)) {
+ nodes[complete].constant = incompletePtr->constant;
+ }
+
+ if (incompletePtr->lexeme == START) {
+
+ /*
+ * Completing the START tree indicates we're done.
+ * Transfer the parse tree to the caller and return.
+ */
+
+ *opTreePtr = nodes;
+ return TCL_OK;
+ }
+
+ /*
+ * With a right operand attached, last incomplete tree has
+ * become the complete tree. Pop it from the incomplete
+ * tree stack.
+ */
+
+ complete = incomplete;
+ incomplete = incompletePtr->p.prev;
+
+ /* CLOSE_PAREN can only close one OPEN_PAREN. */
+ if (incompletePtr->lexeme == OPEN_PAREN) {
+ break;
+ }
+ }
+
+ /* More syntax checks... */
+
+ /* Parens must balance. */
+ if (lexeme == CLOSE_PAREN) {
+ if (incompletePtr->lexeme != OPEN_PAREN) {
+ TclNewLiteralStringObj(msg, "unbalanced close paren");
+ goto error;
+ }
+ }
+
+ /* Commas must appear only in function argument lists. */
+ if (lexeme == COMMA) {
+ if ((incompletePtr->lexeme != OPEN_PAREN)
+ || (incompletePtr[-1].lexeme != FUNCTION)) {
+ TclNewLiteralStringObj(msg,
+ "unexpected \",\" outside function argument list");
+ goto error;
+ }
+ }
+
+ /* Operator ":" may only be right operand of "?" */
+ if (IsOperator(complete) && (nodes[complete].lexeme == COLON)) {
+ TclNewLiteralStringObj(msg,
+ "unexpected operator \":\" without preceding \"?\"");
+ goto error;
+ }
+
+ /* Create no node for a CLOSE_PAREN lexeme. */
+ if (lexeme == CLOSE_PAREN) {
+ break;
+ }
+
+ /* Link complete tree as left operand of new node. */
+ nodePtr->lexeme = lexeme;
+ nodePtr->precedence = precedence;
+ nodePtr->mark = MARK_LEFT;
+ nodePtr->left = complete;
+
+ /*
+ * The COMMA operator cannot be optimized, since the function
+ * needs all of its arguments, and optimization would reduce
+ * the number. Other binary operators root constant expressions
+ * when both arguments are constant expressions.
+ */
+
+ nodePtr->constant = (lexeme != COMMA);
+
+ if (IsOperator(complete)) {
+ nodes[complete].p.parent = nodesUsed;
+ nodePtr->constant = nodePtr->constant
+ && nodes[complete].constant;
+ } else {
+ nodePtr->constant = nodePtr->constant
+ && (complete == OT_LITERAL);
+ }
+
+ /*
+ * With a left operand attached and a right operand missing,
+ * the just-parsed binary operator is root of a new incomplete
+ * tree. Push it onto the stack of incomplete trees.
+ */
+
+ nodePtr->p.prev = incomplete;
+ incomplete = lastParsed = nodesUsed;
+ nodesUsed++;
+ break;
+ } /* case BINARY */
+ } /* lexeme handler */
+
+ /* Advance past the just-parsed lexeme */
+ start += scanned;
+ numBytes -= scanned;
+ } /* main parsing loop */
+
+ error:
/*
- * Parse the expression then compile it.
+ * We only get here if there's been an error.
+ * Any errors that didn't get a suitable parsePtr->errorType,
+ * get recorded as syntax errors.
*/
- code = Tcl_ParseExpr(interp, script, numBytes, &parse);
- if (code != TCL_OK) {
- goto done;
+ if (parsePtr->errorType == TCL_PARSE_SUCCESS) {
+ parsePtr->errorType = TCL_PARSE_SYNTAX;
}
-#ifdef TCL_TIP280
- /* TIP #280 : Track Lines within the expression */
- TclAdvanceLines (&envPtr->line, script, parse.tokenPtr->start);
-#endif
-
- code = CompileSubExpr(parse.tokenPtr, &info, envPtr);
- if (code != TCL_OK) {
- Tcl_FreeParse(&parse);
- goto done;
+ /* Free any partial parse tree we've built. */
+ if (nodes != NULL) {
+ ckfree((char*) nodes);
}
-
- if (!info.hasOperators) {
+
+ if (interp == NULL) {
+
+ /* Nowhere to report an error message, so just free it */
+ if (msg) {
+ Tcl_DecrRefCount(msg);
+ }
+ } else {
+
+ /*
+ * Construct the complete error message. Start with the simple
+ * error message, pulled from the interp result if necessary...
+ */
+
+ if (msg == NULL) {
+ msg = Tcl_GetObjResult(interp);
+ }
+
/*
- * Attempt to convert the primary's object to an int or double.
- * This is done in order to support Tcl's policy of interpreting
- * operands if at all possible as first integers, else
- * floating-point numbers.
+ * Add a detailed quote from the bad expression, displaying and
+ * sometimes marking the precise location of the syntax error.
*/
-
- TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr);
+
+ Tcl_AppendPrintfToObj(msg, "\nin expression \"%s%.*s%.*s%s%s%.*s%s\"",
+ ((start - limit) < parsePtr->string) ? "" : "...",
+ ((start - limit) < parsePtr->string)
+ ? (int) (start - parsePtr->string) : limit - 3,
+ ((start - limit) < parsePtr->string)
+ ? parsePtr->string : start - limit + 3,
+ (scanned < limit) ? scanned : limit - 3, start,
+ (scanned < limit) ? "" : "...", insertMark ? mark : "",
+ (start + scanned + limit > parsePtr->end)
+ ? (int) (parsePtr->end - start) - scanned : limit-3,
+ start + scanned,
+ (start + scanned + limit > parsePtr->end) ? "" : "...");
+
+ /* Next, append any postscript message. */
+ if (post != NULL) {
+ Tcl_AppendToObj(msg, ";\n", -1);
+ Tcl_AppendObjToObj(msg, post);
+ Tcl_DecrRefCount(post);
+ }
+ Tcl_SetObjResult(interp, msg);
+
+ /* Finally, place context information in the errorInfo. */
+ numBytes = parsePtr->end - parsePtr->string;
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (parsing expression \"%.*s%s\")",
+ (numBytes < limit) ? numBytes : limit - 3,
+ parsePtr->string, (numBytes < limit) ? "" : "..."));
}
- Tcl_FreeParse(&parse);
- done:
- return code;
+ return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
- * TclFinalizeCompilation --
+ * ConvertTreeToTokens --
*
- * Clean up the compilation environment so it can later be
- * properly reinitialized. This procedure is called by Tcl_Finalize().
+ * Given a string, the numBytes bytes starting at start, and an OpNode
+ * tree and Tcl_Token array created by passing that same string to
+ * ParseExpr(), this function writes into *parsePtr the sequence of
+ * Tcl_Tokens needed so to satisfy the historical interface provided
+ * by Tcl_ParseExpr(). Note that this routine exists only for the sake
+ * of the public Tcl_ParseExpr() routine. It is not used by Tcl itself
+ * at all.
*
* Results:
* None.
*
* Side effects:
- * Cleans up the compilation environment. At the moment, just the
- * table of expression operators is freed.
+ * The Tcl_Parse *parsePtr is filled with Tcl_Tokens representing the
+ * parsed expression.
*
*----------------------------------------------------------------------
*/
-void
-TclFinalizeCompilation()
+static void
+ConvertTreeToTokens(
+ const char *start,
+ int numBytes,
+ OpNode *nodes,
+ Tcl_Token *tokenPtr,
+ Tcl_Parse *parsePtr)
{
- Tcl_MutexLock(&opMutex);
- if (opTableInitialized) {
- Tcl_DeleteHashTable(&opHashTable);
- opTableInitialized = 0;
- }
- Tcl_MutexUnlock(&opMutex);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * CompileSubExpr --
- *
- * Given a pointer to a TCL_TOKEN_SUB_EXPR token describing a
- * subexpression, this procedure emits instructions to evaluate the
- * subexpression at runtime.
- *
- * Results:
- * The return value is TCL_OK on a successful compilation and TCL_ERROR
- * on failure. If TCL_ERROR is returned, then the interpreter's result
- * contains an error message.
- *
- * Side effects:
- * Adds instructions to envPtr to evaluate the subexpression.
- *
- *----------------------------------------------------------------------
- */
+ int subExprTokenIdx = 0;
+ OpNode *nodePtr = nodes;
+ int next = nodePtr->right;
-static int
-CompileSubExpr(exprTokenPtr, infoPtr, envPtr)
- Tcl_Token *exprTokenPtr; /* Points to TCL_TOKEN_SUB_EXPR token
- * to compile. */
- ExprInfo *infoPtr; /* Describes the compilation state for the
- * expression being compiled. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
-{
- Tcl_Interp *interp = infoPtr->interp;
- Tcl_Token *tokenPtr, *endPtr = NULL; /* silence gcc 4 warning */
- Tcl_Token *afterSubexprPtr;
- OperatorDesc *opDescPtr;
- Tcl_HashEntry *hPtr;
- CONST char *operator;
- Tcl_DString opBuf;
- int objIndex, opIndex, length, code;
- char buffer[TCL_UTF_MAX];
-
- if (exprTokenPtr->type != TCL_TOKEN_SUB_EXPR) {
- panic("CompileSubExpr: token type %d not TCL_TOKEN_SUB_EXPR\n",
- exprTokenPtr->type);
- }
- code = TCL_OK;
+ while (1) {
+ Tcl_Token *subExprTokenPtr;
+ int scanned, parentIdx;
+ unsigned char lexeme;
- /*
- * Switch on the type of the first token after the subexpression token.
- * After processing it, advance tokenPtr to point just after the
- * subexpression's last token.
- */
-
- tokenPtr = exprTokenPtr+1;
- TRACE(exprTokenPtr->start, exprTokenPtr->size,
- tokenPtr->start, tokenPtr->size);
- switch (tokenPtr->type) {
- case TCL_TOKEN_WORD:
- code = TclCompileTokens(interp, tokenPtr+1,
- tokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- goto done;
- }
- tokenPtr += (tokenPtr->numComponents + 1);
+ /*
+ * Advance the mark so the next exit from this node won't retrace
+ * steps over ground already covered.
+ */
+
+ nodePtr->mark++;
+
+ /* Handle next child node or leaf */
+ switch (next) {
+ case OT_EMPTY:
+
+ /* No tokens and no characters for the OT_EMPTY leaf. */
break;
-
- case TCL_TOKEN_TEXT:
- if (tokenPtr->size > 0) {
- objIndex = TclRegisterNewLiteral(envPtr, tokenPtr->start,
- tokenPtr->size);
- } else {
- objIndex = TclRegisterNewLiteral(envPtr, "", 0);
- }
- TclEmitPush(objIndex, envPtr);
- tokenPtr += 1;
+
+ case OT_LITERAL:
+
+ /* Skip any white space that comes before the literal */
+ scanned = TclParseAllWhiteSpace(start, numBytes);
+ start +=scanned;
+ numBytes -= scanned;
+
+ /* Reparse the literal to get pointers into source string */
+ scanned = ParseLexeme(start, numBytes, &lexeme, NULL);
+
+ TclGrowParseTokenArray(parsePtr, 2);
+ subExprTokenPtr = parsePtr->tokenPtr + parsePtr->numTokens;
+ subExprTokenPtr->type = TCL_TOKEN_SUB_EXPR;
+ subExprTokenPtr->start = start;
+ subExprTokenPtr->size = scanned;
+ subExprTokenPtr->numComponents = 1;
+ subExprTokenPtr[1].type = TCL_TOKEN_TEXT;
+ subExprTokenPtr[1].start = start;
+ subExprTokenPtr[1].size = scanned;
+ subExprTokenPtr[1].numComponents = 0;
+
+ parsePtr->numTokens += 2;
+ start +=scanned;
+ numBytes -= scanned;
break;
-
- case TCL_TOKEN_BS:
- length = TclParseBackslash(tokenPtr->start, tokenPtr->size,
- (int *) NULL, buffer);
- if (length > 0) {
- objIndex = TclRegisterNewLiteral(envPtr, buffer, length);
+
+ case OT_TOKENS: {
+
+ /*
+ * tokenPtr points to a token sequence that came from parsing
+ * a Tcl word. A Tcl word is made up of a sequence of one or
+ * more elements. When the word is only a single element, it's
+ * been the historical practice to replace the TCL_TOKEN_WORD
+ * token directly with a TCL_TOKEN_SUB_EXPR token. However,
+ * when the word has multiple elements, a TCL_TOKEN_WORD token
+ * is kept as a grouping device so that TCL_TOKEN_SUB_EXPR
+ * always has only one element. Wise or not, these are the
+ * rules the Tcl expr parser has followed, and for the sake
+ * of those few callers of Tcl_ParseExpr() we do not change
+ * them now. Internally, we can do better.
+ */
+
+ int toCopy = tokenPtr->numComponents + 1;
+
+ if (tokenPtr->numComponents == tokenPtr[1].numComponents + 1) {
+
+ /*
+ * Single element word. Copy tokens and convert the leading
+ * token to TCL_TOKEN_SUB_EXPR.
+ */
+
+ TclGrowParseTokenArray(parsePtr, toCopy);
+ subExprTokenPtr = parsePtr->tokenPtr + parsePtr->numTokens;
+ memcpy(subExprTokenPtr, tokenPtr,
+ (size_t) toCopy * sizeof(Tcl_Token));
+ subExprTokenPtr->type = TCL_TOKEN_SUB_EXPR;
+ parsePtr->numTokens += toCopy;
} else {
- objIndex = TclRegisterNewLiteral(envPtr, "", 0);
+
+ /*
+ * Multiple element word. Create a TCL_TOKEN_SUB_EXPR
+ * token to lead, with fields initialized from the leading
+ * token, then copy entire set of word tokens.
+ */
+
+ TclGrowParseTokenArray(parsePtr, toCopy+1);
+ subExprTokenPtr = parsePtr->tokenPtr + parsePtr->numTokens;
+ *subExprTokenPtr = *tokenPtr;
+ subExprTokenPtr->type = TCL_TOKEN_SUB_EXPR;
+ subExprTokenPtr->numComponents++;
+ subExprTokenPtr++;
+ memcpy(subExprTokenPtr, tokenPtr,
+ (size_t) toCopy * sizeof(Tcl_Token));
+ parsePtr->numTokens += toCopy + 1;
}
- TclEmitPush(objIndex, envPtr);
- tokenPtr += 1;
+
+ scanned = tokenPtr->start + tokenPtr->size - start;
+ start +=scanned;
+ numBytes -= scanned;
+ tokenPtr += toCopy;
break;
-
- case TCL_TOKEN_COMMAND:
- code = TclCompileScript(interp, tokenPtr->start+1,
- tokenPtr->size-2, /*nested*/ 0, envPtr);
- if (code != TCL_OK) {
- goto done;
+ }
+
+ default:
+
+ /* Advance to the child node, which is an operator. */
+ nodePtr = nodes + next;
+
+ /* Skip any white space that comes before the subexpression */
+ scanned = TclParseAllWhiteSpace(start, numBytes);
+ start +=scanned;
+ numBytes -= scanned;
+
+ /* Generate tokens for the operator / subexpression... */
+ switch (nodePtr->lexeme) {
+ case OPEN_PAREN:
+ case COMMA:
+ case COLON:
+
+ /*
+ * Historical practice has been to have no Tcl_Tokens for
+ * these operators.
+ */
+
+ break;
+
+ default: {
+
+ /*
+ * Remember the index of the last subexpression we were
+ * working on -- that of our parent. We'll stack it later.
+ */
+
+ parentIdx = subExprTokenIdx;
+
+ /*
+ * Verify space for the two leading Tcl_Tokens representing
+ * the subexpression rooted by this operator. The first
+ * Tcl_Token will be of type TCL_TOKEN_SUB_EXPR; the second
+ * of type TCL_TOKEN_OPERATOR.
+ */
+
+ TclGrowParseTokenArray(parsePtr, 2);
+ subExprTokenIdx = parsePtr->numTokens;
+ subExprTokenPtr = parsePtr->tokenPtr + subExprTokenIdx;
+ parsePtr->numTokens += 2;
+ subExprTokenPtr->type = TCL_TOKEN_SUB_EXPR;
+ subExprTokenPtr[1].type = TCL_TOKEN_OPERATOR;
+
+ /*
+ * Our current position scanning the string is the starting
+ * point for this subexpression.
+ */
+
+ subExprTokenPtr->start = start;
+
+ /*
+ * Eventually, we know that the numComponents field of the
+ * Tcl_Token of type TCL_TOKEN_OPERATOR will be 0. This means
+ * we can make other use of this field for now to track the
+ * stack of subexpressions we have pending.
+ */
+
+ subExprTokenPtr[1].numComponents = parentIdx;
+ break;
}
- tokenPtr += 1;
- break;
-
- case TCL_TOKEN_VARIABLE:
- code = TclCompileTokens(interp, tokenPtr, 1, envPtr);
- if (code != TCL_OK) {
- goto done;
}
- tokenPtr += (tokenPtr->numComponents + 1);
break;
-
- case TCL_TOKEN_SUB_EXPR:
- code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
- if (code != TCL_OK) {
- goto done;
- }
- tokenPtr += (tokenPtr->numComponents + 1);
+ }
+
+ /* Determine which way to exit the node on this pass. */
+ router:
+ switch (nodePtr->mark) {
+ case MARK_LEFT:
+ next = nodePtr->left;
break;
-
- case TCL_TOKEN_OPERATOR:
+
+ case MARK_RIGHT:
+ next = nodePtr->right;
+
+ /* Skip any white space that comes before the operator */
+ scanned = TclParseAllWhiteSpace(start, numBytes);
+ start +=scanned;
+ numBytes -= scanned;
+
/*
- * Look up the operator. If the operator isn't found, treat it
- * as a math function.
+ * Here we scan from the string the operator corresponding to
+ * nodePtr->lexeme.
*/
- Tcl_DStringInit(&opBuf);
- operator = Tcl_DStringAppend(&opBuf,
- tokenPtr->start, tokenPtr->size);
- hPtr = Tcl_FindHashEntry(&opHashTable, operator);
- if (hPtr == NULL) {
- code = CompileMathFuncCall(exprTokenPtr, operator, infoPtr,
- envPtr, &endPtr);
- Tcl_DStringFree(&opBuf);
- if (code != TCL_OK) {
- goto done;
- }
- tokenPtr = endPtr;
+
+ scanned = ParseLexeme(start, numBytes, &lexeme, NULL);
+
+ switch(nodePtr->lexeme) {
+ case OPEN_PAREN:
+ case COMMA:
+ case COLON:
+
+ /* No tokens for these lexemes -> nothing to do. */
break;
- }
- Tcl_DStringFree(&opBuf);
- opIndex = (int) Tcl_GetHashValue(hPtr);
- opDescPtr = &(operatorTable[opIndex]);
- /*
- * If the operator is "normal", compile it using information
- * from the operator table.
- */
+ default:
- if (opDescPtr->numOperands > 0) {
- tokenPtr++;
- code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
- if (code != TCL_OK) {
- goto done;
- }
- tokenPtr += (tokenPtr->numComponents + 1);
+ /*
+ * Record in the TCL_TOKEN_OPERATOR token the pointers into
+ * the string marking where the operator is.
+ */
- if (opDescPtr->numOperands == 2) {
- code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
- if (code != TCL_OK) {
- goto done;
- }
- tokenPtr += (tokenPtr->numComponents + 1);
- }
- TclEmitOpcode(opDescPtr->instruction, envPtr);
- infoPtr->hasOperators = 1;
+ subExprTokenPtr = parsePtr->tokenPtr + subExprTokenIdx;
+ subExprTokenPtr[1].start = start;
+ subExprTokenPtr[1].size = scanned;
break;
}
-
- /*
- * The operator requires special treatment, and is either
- * "+" or "-", or one of "&&", "||" or "?".
- */
-
- switch (opIndex) {
- case OP_PLUS:
- case OP_MINUS:
- tokenPtr++;
- code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
- if (code != TCL_OK) {
- goto done;
- }
- tokenPtr += (tokenPtr->numComponents + 1);
-
- /*
- * Check whether the "+" or "-" is unary.
- */
-
- afterSubexprPtr = exprTokenPtr
- + exprTokenPtr->numComponents+1;
- if (tokenPtr == afterSubexprPtr) {
- TclEmitOpcode(((opIndex==OP_PLUS)?
- INST_UPLUS : INST_UMINUS),
- envPtr);
- break;
- }
-
- /*
- * The "+" or "-" is binary.
- */
-
- code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
- if (code != TCL_OK) {
- goto done;
- }
- tokenPtr += (tokenPtr->numComponents + 1);
- TclEmitOpcode(((opIndex==OP_PLUS)? INST_ADD : INST_SUB),
- envPtr);
- break;
- case OP_LAND:
- case OP_LOR:
- code = CompileLandOrLorExpr(exprTokenPtr, opIndex,
- infoPtr, envPtr, &endPtr);
- if (code != TCL_OK) {
- goto done;
- }
- tokenPtr = endPtr;
- break;
-
- case OP_QUESTY:
- code = CompileCondExpr(exprTokenPtr, infoPtr,
- envPtr, &endPtr);
- if (code != TCL_OK) {
- goto done;
- }
- tokenPtr = endPtr;
- break;
-
- default:
- panic("CompileSubExpr: unexpected operator %d requiring special treatment\n",
- opIndex);
- } /* end switch on operator requiring special treatment */
- infoPtr->hasOperators = 1;
+ start +=scanned;
+ numBytes -= scanned;
break;
- default:
- panic("CompileSubExpr: unexpected token type %d\n",
- tokenPtr->type);
- }
+ case MARK_PARENT:
+ switch (nodePtr->lexeme) {
+ case START:
- /*
- * Verify that the subexpression token had the required number of
- * subtokens: that we've advanced tokenPtr just beyond the
- * subexpression's last token. For example, a "*" subexpression must
- * contain the tokens for exactly two operands.
- */
-
- if (tokenPtr != (exprTokenPtr + exprTokenPtr->numComponents+1)) {
- LogSyntaxError(infoPtr);
- code = TCL_ERROR;
+ /* When we get back to the START node, we're done. */
+ return;
+
+ case COMMA:
+ case COLON:
+
+ /* No tokens for these lexemes -> nothing to do. */
+ break;
+
+ case OPEN_PAREN:
+
+ /* Skip past matching close paren. */
+ scanned = TclParseAllWhiteSpace(start, numBytes);
+ start +=scanned;
+ numBytes -= scanned;
+ scanned = ParseLexeme(start, numBytes, &lexeme, NULL);
+ start +=scanned;
+ numBytes -= scanned;
+ break;
+
+ default: {
+
+ /*
+ * Before we leave this node/operator/subexpression for the
+ * last time, finish up its tokens....
+ *
+ * Our current position scanning the string is where the
+ * substring for the subexpression ends.
+ */
+
+ subExprTokenPtr = parsePtr->tokenPtr + subExprTokenIdx;
+ subExprTokenPtr->size = start - subExprTokenPtr->start;
+
+ /*
+ * All the Tcl_Tokens allocated and filled belong to
+ * this subexpresion. The first token is the leading
+ * TCL_TOKEN_SUB_EXPR token, and all the rest (one fewer)
+ * are its components.
+ */
+
+ subExprTokenPtr->numComponents =
+ (parsePtr->numTokens - subExprTokenIdx) - 1;
+
+ /*
+ * Finally, as we return up the tree to our parent, pop the
+ * parent subexpression off our subexpression stack, and
+ * fill in the zero numComponents for the operator Tcl_Token.
+ */
+
+ parentIdx = subExprTokenPtr[1].numComponents;
+ subExprTokenPtr[1].numComponents = 0;
+ subExprTokenIdx = parentIdx;
+ break;
+ }
+ }
+
+ /* Since we're returning to parent, skip child handling code. */
+ nodePtr = nodes + nodePtr->p.parent;
+ goto router;
+ }
}
-
- done:
- return code;
}
/*
*----------------------------------------------------------------------
*
- * CompileLandOrLorExpr --
+ * Tcl_ParseExpr --
*
- * This procedure compiles a Tcl logical and ("&&") or logical or
- * ("||") subexpression.
+ * Given a string, the numBytes bytes starting at start, this function
+ * parses it as a Tcl expression and stores information about the
+ * structure of the expression in the Tcl_Parse struct indicated by the
+ * caller.
*
* Results:
- * The return value is TCL_OK on a successful compilation and TCL_ERROR
- * on failure. If TCL_OK is returned, a pointer to the token just after
- * the last one in the subexpression is stored at the address in
- * endPtrPtr. If TCL_ERROR is returned, then the interpreter's result
- * contains an error message.
+ * If the string is successfully parsed as a valid Tcl expression, TCL_OK
+ * is returned, and data about the expression structure is written to
+ * *parsePtr. If the string cannot be parsed as a valid Tcl expression,
+ * TCL_ERROR is returned, and if interp is non-NULL, an error message is
+ * written to interp.
*
* Side effects:
- * Adds instructions to envPtr to evaluate the expression at runtime.
+ * If there is insufficient space in parsePtr to hold all the information
+ * about the expression, then additional space is malloc-ed. If the
+ * function returns TCL_OK then the caller must eventually invoke
+ * Tcl_FreeParse to release any additional space that was allocated.
*
*----------------------------------------------------------------------
*/
-static int
-CompileLandOrLorExpr(exprTokenPtr, opIndex, infoPtr, envPtr, endPtrPtr)
- Tcl_Token *exprTokenPtr; /* Points to TCL_TOKEN_SUB_EXPR token
- * containing the "&&" or "||" operator. */
- int opIndex; /* A code describing the expression
- * operator: either OP_LAND or OP_LOR. */
- ExprInfo *infoPtr; /* Describes the compilation state for the
- * expression being compiled. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
- Tcl_Token **endPtrPtr; /* If successful, a pointer to the token
- * just after the last token in the
- * subexpression is stored here. */
+int
+Tcl_ParseExpr(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ const char *start, /* Start of source string to parse. */
+ int numBytes, /* Number of bytes in string. If < 0, the
+ * string consists of all bytes up to the
+ * first null character. */
+ Tcl_Parse *parsePtr) /* Structure to fill with information about
+ * the parsed expression; any previous
+ * information in the structure is ignored. */
{
- JumpFixup shortCircuitFixup; /* Used to fix up the short circuit jump
- * after the first subexpression. */
- JumpFixup lhsTrueFixup, lhsEndFixup;
- /* Used to fix up jumps used to convert the
- * first operand to 0 or 1. */
- Tcl_Token *tokenPtr;
- int dist, code;
- int savedStackDepth = envPtr->currStackDepth;
+ int code;
+ OpNode *opTree = NULL; /* Will point to the tree of operators */
+ Tcl_Obj *litList = Tcl_NewObj(); /* List to hold the literals */
+ Tcl_Obj *funcList = Tcl_NewObj(); /* List to hold the functon names*/
+ Tcl_Parse *exprParsePtr =
+ (Tcl_Parse *) TclStackAlloc(interp, sizeof(Tcl_Parse));
+ /* Holds the Tcl_Tokens of substitutions */
- /*
- * Emit code for the first operand.
- */
+ if (numBytes < 0) {
+ numBytes = (start ? strlen(start) : 0);
+ }
+
+ code = ParseExpr(interp, start, numBytes, &opTree, litList,
+ funcList, exprParsePtr, 1 /* parseOnly */);
+ Tcl_DecrRefCount(funcList);
+ Tcl_DecrRefCount(litList);
- tokenPtr = exprTokenPtr+2;
- code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
- if (code != TCL_OK) {
- goto done;
+ TclParseInit(interp, start, numBytes, parsePtr);
+ if (code == TCL_OK) {
+ ConvertTreeToTokens(start, numBytes,
+ opTree, exprParsePtr->tokenPtr, parsePtr);
+ } else {
+ parsePtr->term = exprParsePtr->term;
+ parsePtr->errorType = exprParsePtr->errorType;
}
- tokenPtr += (tokenPtr->numComponents + 1);
- /*
- * Convert the first operand to the result that Tcl requires:
- * "0" or "1". Eventually we'll use a new instruction for this.
- */
-
- TclEmitForwardJump(envPtr, TCL_TRUE_JUMP, &lhsTrueFixup);
- TclEmitPush(TclRegisterNewLiteral(envPtr, "0", 1), envPtr);
- TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &lhsEndFixup);
- dist = (envPtr->codeNext - envPtr->codeStart) - lhsTrueFixup.codeOffset;
- if (TclFixupForwardJump(envPtr, &lhsTrueFixup, dist, 127)) {
- badDist:
- panic("CompileLandOrLorExpr: bad jump distance %d\n", dist);
+ Tcl_FreeParse(exprParsePtr);
+ TclStackFree(interp, exprParsePtr);
+ ckfree((char *) opTree);
+ return code;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ParseLexeme --
+ *
+ * Parse a single lexeme from the start of a string, scanning no more
+ * than numBytes bytes.
+ *
+ * Results:
+ * Returns the number of bytes scanned to produce the lexeme.
+ *
+ * Side effects:
+ * Code identifying lexeme parsed is writen to *lexemePtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ParseLexeme(
+ const char *start, /* Start of lexeme to parse. */
+ int numBytes, /* Number of bytes in string. */
+ unsigned char *lexemePtr, /* Write code of parsed lexeme to this
+ * storage. */
+ Tcl_Obj **literalPtr) /* Write corresponding literal value to this
+ storage, if non-NULL. */
+{
+ const char *end;
+ int scanned;
+ Tcl_UniChar ch;
+ Tcl_Obj *literal = NULL;
+ unsigned char byte;
+
+ if (numBytes == 0) {
+ *lexemePtr = END;
+ return 0;
}
- envPtr->currStackDepth = savedStackDepth;
- TclEmitPush(TclRegisterNewLiteral(envPtr, "1", 1), envPtr);
- dist = (envPtr->codeNext - envPtr->codeStart) - lhsEndFixup.codeOffset;
- if (TclFixupForwardJump(envPtr, &lhsEndFixup, dist, 127)) {
- goto badDist;
+ byte = (unsigned char)(*start);
+ if (byte < sizeof(Lexeme) && Lexeme[byte] != 0) {
+ *lexemePtr = Lexeme[byte];
+ return 1;
}
+ switch (byte) {
+ case '*':
+ if ((numBytes > 1) && (start[1] == '*')) {
+ *lexemePtr = EXPON;
+ return 2;
+ }
+ *lexemePtr = MULT;
+ return 1;
- /*
- * Emit the "short circuit" jump around the rest of the expression.
- * Duplicate the "0" or "1" on top of the stack first to keep the
- * jump from consuming it.
- */
+ case '=':
+ if ((numBytes > 1) && (start[1] == '=')) {
+ *lexemePtr = EQUAL;
+ return 2;
+ }
+ *lexemePtr = INCOMPLETE;
+ return 1;
+
+ case '!':
+ if ((numBytes > 1) && (start[1] == '=')) {
+ *lexemePtr = NEQ;
+ return 2;
+ }
+ *lexemePtr = NOT;
+ return 1;
- TclEmitOpcode(INST_DUP, envPtr);
- TclEmitForwardJump(envPtr,
- ((opIndex==OP_LAND)? TCL_FALSE_JUMP : TCL_TRUE_JUMP),
- &shortCircuitFixup);
+ case '&':
+ if ((numBytes > 1) && (start[1] == '&')) {
+ *lexemePtr = AND;
+ return 2;
+ }
+ *lexemePtr = BIT_AND;
+ return 1;
- /*
- * Emit code for the second operand.
- */
+ case '|':
+ if ((numBytes > 1) && (start[1] == '|')) {
+ *lexemePtr = OR;
+ return 2;
+ }
+ *lexemePtr = BIT_OR;
+ return 1;
+
+ case '<':
+ if (numBytes > 1) {
+ switch (start[1]) {
+ case '<':
+ *lexemePtr = LEFT_SHIFT;
+ return 2;
+ case '=':
+ *lexemePtr = LEQ;
+ return 2;
+ }
+ }
+ *lexemePtr = LESS;
+ return 1;
+
+ case '>':
+ if (numBytes > 1) {
+ switch (start[1]) {
+ case '>':
+ *lexemePtr = RIGHT_SHIFT;
+ return 2;
+ case '=':
+ *lexemePtr = GEQ;
+ return 2;
+ }
+ }
+ *lexemePtr = GREATER;
+ return 1;
- code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
- if (code != TCL_OK) {
- goto done;
- }
- tokenPtr += (tokenPtr->numComponents + 1);
+ case 'i':
+ if ((numBytes > 1) && (start[1] == 'n')
+ && ((numBytes == 2) || !isalpha(UCHAR(start[2])))) {
- /*
- * Emit a "logical and" or "logical or" instruction. This does not try
- * to "short- circuit" the evaluation of both operands, but instead
- * ensures that we either have a "1" or a "0" result.
- */
+ /*
+ * Must make this check so we can tell the difference between
+ * the "in" operator and the "int" function name and the
+ * "infinity" numeric value.
+ */
- TclEmitOpcode(((opIndex==OP_LAND)? INST_LAND : INST_LOR), envPtr);
+ *lexemePtr = IN_LIST;
+ return 2;
+ }
+ break;
- /*
- * Now that we know the target of the forward jump, update it with the
- * correct distance.
- */
+ case 'e':
+ if ((numBytes > 1) && (start[1] == 'q')
+ && ((numBytes == 2) || !isalpha(UCHAR(start[2])))) {
+ *lexemePtr = STREQ;
+ return 2;
+ }
+ break;
+
+ case 'n':
+ if ((numBytes > 1) && ((numBytes == 2) || !isalpha(UCHAR(start[2])))) {
+ switch (start[1]) {
+ case 'e':
+ *lexemePtr = STRNEQ;
+ return 2;
+ case 'i':
+ *lexemePtr = NOT_IN_LIST;
+ return 2;
+ }
+ }
+ }
- dist = (envPtr->codeNext - envPtr->codeStart)
- - shortCircuitFixup.codeOffset;
- TclFixupForwardJump(envPtr, &shortCircuitFixup, dist, 127);
- *endPtrPtr = tokenPtr;
+ literal = Tcl_NewObj();
+ if (TclParseNumber(NULL, literal, NULL, start, numBytes, &end,
+ TCL_PARSE_NO_WHITESPACE) == TCL_OK) {
+ TclInitStringRep(literal, start, end-start);
+ *lexemePtr = NUMBER;
+ if (literalPtr) {
+ *literalPtr = literal;
+ } else {
+ Tcl_DecrRefCount(literal);
+ }
+ return (end-start);
+ }
- done:
- envPtr->currStackDepth = savedStackDepth + 1;
- return code;
+ if (Tcl_UtfCharComplete(start, numBytes)) {
+ scanned = Tcl_UtfToUniChar(start, &ch);
+ } else {
+ char utfBytes[TCL_UTF_MAX];
+ memcpy(utfBytes, start, (size_t) numBytes);
+ utfBytes[numBytes] = '\0';
+ scanned = Tcl_UtfToUniChar(utfBytes, &ch);
+ }
+ if (!isalpha(UCHAR(ch))) {
+ *lexemePtr = INVALID;
+ Tcl_DecrRefCount(literal);
+ return scanned;
+ }
+ end = start;
+ while (isalnum(UCHAR(ch)) || (UCHAR(ch) == '_')) {
+ end += scanned;
+ numBytes -= scanned;
+ if (Tcl_UtfCharComplete(end, numBytes)) {
+ scanned = Tcl_UtfToUniChar(end, &ch);
+ } else {
+ char utfBytes[TCL_UTF_MAX];
+ memcpy(utfBytes, end, (size_t) numBytes);
+ utfBytes[numBytes] = '\0';
+ scanned = Tcl_UtfToUniChar(utfBytes, &ch);
+ }
+ }
+ *lexemePtr = BAREWORD;
+ if (literalPtr) {
+ Tcl_SetStringObj(literal, start, (int) (end-start));
+ *literalPtr = literal;
+ } else {
+ Tcl_DecrRefCount(literal);
+ }
+ return (end-start);
}
/*
*----------------------------------------------------------------------
*
- * CompileCondExpr --
+ * TclCompileExpr --
*
- * This procedure compiles a Tcl conditional expression:
- * condExpr ::= lorExpr ['?' condExpr ':' condExpr]
+ * This procedure compiles a string containing a Tcl expression into Tcl
+ * bytecodes.
*
* Results:
- * The return value is TCL_OK on a successful compilation and TCL_ERROR
- * on failure. If TCL_OK is returned, a pointer to the token just after
- * the last one in the subexpression is stored at the address in
- * endPtrPtr. If TCL_ERROR is returned, then the interpreter's result
- * contains an error message.
+ * None.
*
* Side effects:
* Adds instructions to envPtr to evaluate the expression at runtime.
@@ -698,269 +1997,680 @@ CompileLandOrLorExpr(exprTokenPtr, opIndex, infoPtr, envPtr, endPtrPtr)
*----------------------------------------------------------------------
*/
+void
+TclCompileExpr(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ const char *script, /* The source script to compile. */
+ int numBytes, /* Number of bytes in script. */
+ CompileEnv *envPtr, /* Holds resulting instructions. */
+ int optimize) /* 0 for one-off expressions */
+{
+ OpNode *opTree = NULL; /* Will point to the tree of operators */
+ Tcl_Obj *litList = Tcl_NewObj(); /* List to hold the literals */
+ Tcl_Obj *funcList = Tcl_NewObj(); /* List to hold the functon names*/
+ Tcl_Parse *parsePtr =
+ (Tcl_Parse *) TclStackAlloc(interp, sizeof(Tcl_Parse));
+ /* Holds the Tcl_Tokens of substitutions */
+
+ int code = ParseExpr(interp, script, numBytes, &opTree, litList,
+ funcList, parsePtr, 0 /* parseOnly */);
+
+ if (code == TCL_OK) {
+
+ /* Valid parse; compile the tree. */
+ int objc;
+ Tcl_Obj *const *litObjv;
+ Tcl_Obj **funcObjv;
+
+ /* TIP #280 : Track Lines within the expression */
+ TclAdvanceLines(&envPtr->line, script,
+ script + TclParseAllWhiteSpace(script, numBytes));
+
+ TclListObjGetElements(NULL, litList, &objc, (Tcl_Obj ***)&litObjv);
+ TclListObjGetElements(NULL, funcList, &objc, &funcObjv);
+ CompileExprTree(interp, opTree, 0, &litObjv, funcObjv,
+ parsePtr->tokenPtr, envPtr, optimize);
+ } else {
+ TclCompileSyntaxError(interp, envPtr);
+ }
+
+ Tcl_FreeParse(parsePtr);
+ TclStackFree(interp, parsePtr);
+ Tcl_DecrRefCount(funcList);
+ Tcl_DecrRefCount(litList);
+ ckfree((char *) opTree);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ExecConstantExprTree --
+ * Compiles and executes bytecode for the subexpression tree at index
+ * in the nodes array. This subexpression must be constant, made up
+ * of only constant operators (not functions) and literals.
+ *
+ * Results:
+ * A standard Tcl return code and result left in interp.
+ *
+ * Side effects:
+ * Consumes subtree of nodes rooted at index. Advances the pointer
+ * *litObjvPtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
static int
-CompileCondExpr(exprTokenPtr, infoPtr, envPtr, endPtrPtr)
- Tcl_Token *exprTokenPtr; /* Points to TCL_TOKEN_SUB_EXPR token
- * containing the "?" operator. */
- ExprInfo *infoPtr; /* Describes the compilation state for the
- * expression being compiled. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
- Tcl_Token **endPtrPtr; /* If successful, a pointer to the token
- * just after the last token in the
- * subexpression is stored here. */
+ExecConstantExprTree(
+ Tcl_Interp *interp,
+ OpNode *nodes,
+ int index,
+ Tcl_Obj *const **litObjvPtr)
{
- JumpFixup jumpAroundThenFixup, jumpAroundElseFixup;
- /* Used to update or replace one-byte jumps
- * around the then and else expressions when
- * their target PCs are determined. */
- Tcl_Token *tokenPtr;
- int elseCodeOffset, dist, code;
- int savedStackDepth = envPtr->currStackDepth;
+ CompileEnv *envPtr;
+ ByteCode *byteCodePtr;
+ int code;
+ Tcl_Obj *byteCodeObj = Tcl_NewObj();
/*
- * Emit code for the test.
+ * Note we are compiling an expression with literal arguments. This means
+ * there can be no [info frame] calls when we execute the resulting
+ * bytecode, so there's no need to tend to TIP 280 issues.
*/
- tokenPtr = exprTokenPtr+2;
- code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
- if (code != TCL_OK) {
- goto done;
- }
- tokenPtr += (tokenPtr->numComponents + 1);
-
- /*
- * Emit the jump to the "else" expression if the test was false.
- */
-
- TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpAroundThenFixup);
+ envPtr = (CompileEnv *) TclStackAlloc(interp, sizeof(CompileEnv));
+ TclInitCompileEnv(interp, envPtr, NULL, 0, NULL, 0);
+ CompileExprTree(interp, nodes, index, litObjvPtr, NULL, NULL, envPtr,
+ 0 /* optimize */);
+ TclEmitOpcode(INST_DONE, envPtr);
+ Tcl_IncrRefCount(byteCodeObj);
+ TclInitByteCodeObj(byteCodeObj, envPtr);
+ TclFreeCompileEnv(envPtr);
+ TclStackFree(interp, envPtr);
+ byteCodePtr = (ByteCode *) byteCodeObj->internalRep.otherValuePtr;
+ code = TclExecuteByteCode(interp, byteCodePtr);
+ Tcl_DecrRefCount(byteCodeObj);
+ return code;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompileExprTree --
+ * Compiles and writes to envPtr instructions for the subexpression
+ * tree at index in the nodes array. (*litObjvPtr) must point to the
+ * proper location in a corresponding literals list. Likewise, when
+ * non-NULL, funcObjv and tokenPtr must point into matching arrays of
+ * function names and Tcl_Token's derived from earlier call to
+ * ParseExpr(). When optimize is true, any constant subexpressions
+ * will be precomputed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Adds instructions to envPtr to evaluate the expression at runtime.
+ * Consumes subtree of nodes rooted at index. Advances the pointer
+ * *litObjvPtr.
+ *
+ *----------------------------------------------------------------------
+ */
- /*
- * Compile the "then" expression. Note that if a subexpression is only
- * a primary, we need to try to convert it to numeric. We do this to
- * support Tcl's policy of interpreting operands if at all possible as
- * first integers, else floating-point numbers.
- */
+static void
+CompileExprTree(
+ Tcl_Interp *interp,
+ OpNode *nodes,
+ int index,
+ Tcl_Obj *const **litObjvPtr,
+ Tcl_Obj *const *funcObjv,
+ Tcl_Token *tokenPtr,
+ CompileEnv *envPtr,
+ int optimize)
+{
+ OpNode *nodePtr = nodes + index;
+ OpNode *rootPtr = nodePtr;
+ int numWords = 0;
+ JumpList *jumpPtr = NULL;
+ int convert = 1;
+
+ while (1) {
+ int next;
+ JumpList *freePtr, *newJump;
+
+ if (nodePtr->mark == MARK_LEFT) {
+ next = nodePtr->left;
+
+ switch (nodePtr->lexeme) {
+ case QUESTION:
+ newJump = (JumpList *) TclStackAlloc(interp, sizeof(JumpList));
+ newJump->next = jumpPtr;
+ jumpPtr = newJump;
+ newJump = (JumpList *) TclStackAlloc(interp, sizeof(JumpList));
+ newJump->next = jumpPtr;
+ jumpPtr = newJump;
+ jumpPtr->depth = envPtr->currStackDepth;
+ convert = 1;
+ break;
+ case AND:
+ case OR:
+ newJump = (JumpList *) TclStackAlloc(interp, sizeof(JumpList));
+ newJump->next = jumpPtr;
+ jumpPtr = newJump;
+ newJump = (JumpList *) TclStackAlloc(interp, sizeof(JumpList));
+ newJump->next = jumpPtr;
+ jumpPtr = newJump;
+ newJump = (JumpList *) TclStackAlloc(interp, sizeof(JumpList));
+ newJump->next = jumpPtr;
+ jumpPtr = newJump;
+ jumpPtr->depth = envPtr->currStackDepth;
+ break;
+ }
+ } else if (nodePtr->mark == MARK_RIGHT) {
+ next = nodePtr->right;
+
+ switch (nodePtr->lexeme) {
+ case FUNCTION: {
+ Tcl_DString cmdName;
+ const char *p;
+ int length;
+
+ Tcl_DStringInit(&cmdName);
+ Tcl_DStringAppend(&cmdName, "tcl::mathfunc::", -1);
+ p = TclGetStringFromObj(*funcObjv, &length);
+ funcObjv++;
+ Tcl_DStringAppend(&cmdName, p, length);
+ TclEmitPush(TclRegisterNewNSLiteral(envPtr,
+ Tcl_DStringValue(&cmdName),
+ Tcl_DStringLength(&cmdName)), envPtr);
+ Tcl_DStringFree(&cmdName);
+
+ /*
+ * Start a count of the number of words in this function
+ * command invocation. In case there's already a count
+ * in progress (nested functions), save it in our unused
+ * "left" field for restoring later.
+ */
+
+ nodePtr->left = numWords;
+ numWords = 2; /* Command plus one argument */
+ break;
+ }
+ case QUESTION:
+ TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &(jumpPtr->jump));
+ break;
+ case COLON:
+ TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP,
+ &(jumpPtr->next->jump));
+ envPtr->currStackDepth = jumpPtr->depth;
+ jumpPtr->offset = (envPtr->codeNext - envPtr->codeStart);
+ jumpPtr->convert = convert;
+ convert = 1;
+ break;
+ case AND:
+ TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &(jumpPtr->jump));
+ break;
+ case OR:
+ TclEmitForwardJump(envPtr, TCL_TRUE_JUMP, &(jumpPtr->jump));
+ break;
+ }
+ } else {
+ switch (nodePtr->lexeme) {
+ case START:
+ case QUESTION:
+ if (convert && (nodePtr == rootPtr)) {
+ TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr);
+ }
+ break;
+ case OPEN_PAREN:
- infoPtr->hasOperators = 0;
- code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
- if (code != TCL_OK) {
- goto done;
- }
- tokenPtr += (tokenPtr->numComponents + 1);
- if (!infoPtr->hasOperators) {
- TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr);
- }
+ /* do nothing */
+ break;
+ case FUNCTION:
- /*
- * Emit an unconditional jump around the "else" condExpr.
- */
-
- TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP,
- &jumpAroundElseFixup);
+ /*
+ * Use the numWords count we've kept to invoke the
+ * function command with the correct number of arguments.
+ */
- /*
- * Compile the "else" expression.
- */
+ if (numWords < 255) {
+ TclEmitInstInt1(INST_INVOKE_STK1, numWords, envPtr);
+ } else {
+ TclEmitInstInt4(INST_INVOKE_STK4, numWords, envPtr);
+ }
- envPtr->currStackDepth = savedStackDepth;
- elseCodeOffset = (envPtr->codeNext - envPtr->codeStart);
- infoPtr->hasOperators = 0;
- code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
- if (code != TCL_OK) {
- goto done;
- }
- tokenPtr += (tokenPtr->numComponents + 1);
- if (!infoPtr->hasOperators) {
- TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr);
+ /* Restore any saved numWords value. */
+ numWords = nodePtr->left;
+ convert = 1;
+ break;
+ case COMMA:
+
+ /* Each comma implies another function argument. */
+ numWords++;
+ break;
+ case COLON:
+ if (TclFixupForwardJump(envPtr, &(jumpPtr->next->jump),
+ (envPtr->codeNext - envPtr->codeStart)
+ - jumpPtr->next->jump.codeOffset, 127)) {
+ jumpPtr->offset += 3;
+ }
+ TclFixupForwardJump(envPtr, &(jumpPtr->jump),
+ jumpPtr->offset - jumpPtr->jump.codeOffset, 127);
+ convert |= jumpPtr->convert;
+ envPtr->currStackDepth = jumpPtr->depth + 1;
+ freePtr = jumpPtr;
+ jumpPtr = jumpPtr->next;
+ TclStackFree(interp, freePtr);
+ freePtr = jumpPtr;
+ jumpPtr = jumpPtr->next;
+ TclStackFree(interp, freePtr);
+ break;
+ case AND:
+ case OR:
+ TclEmitForwardJump(envPtr, (nodePtr->lexeme == AND)
+ ? TCL_FALSE_JUMP : TCL_TRUE_JUMP,
+ &(jumpPtr->next->jump));
+ TclEmitPush(TclRegisterNewLiteral(envPtr,
+ (nodePtr->lexeme == AND) ? "1" : "0", 1), envPtr);
+ TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP,
+ &(jumpPtr->next->next->jump));
+ TclFixupForwardJumpToHere(envPtr, &(jumpPtr->next->jump), 127);
+ if (TclFixupForwardJumpToHere(envPtr, &(jumpPtr->jump), 127)) {
+ jumpPtr->next->next->jump.codeOffset += 3;
+ }
+ TclEmitPush(TclRegisterNewLiteral(envPtr,
+ (nodePtr->lexeme == AND) ? "0" : "1", 1), envPtr);
+ TclFixupForwardJumpToHere(envPtr, &(jumpPtr->next->next->jump),
+ 127);
+ convert = 0;
+ envPtr->currStackDepth = jumpPtr->depth + 1;
+ freePtr = jumpPtr;
+ jumpPtr = jumpPtr->next;
+ TclStackFree(interp, freePtr);
+ freePtr = jumpPtr;
+ jumpPtr = jumpPtr->next;
+ TclStackFree(interp, freePtr);
+ freePtr = jumpPtr;
+ jumpPtr = jumpPtr->next;
+ TclStackFree(interp, freePtr);
+ break;
+ default:
+ TclEmitOpcode(instruction[nodePtr->lexeme], envPtr);
+ convert = 0;
+ break;
+ }
+ if (nodePtr == rootPtr) {
+
+ /* We're done */
+ return;
+ }
+ nodePtr = nodes + nodePtr->p.parent;
+ continue;
+ }
+
+ nodePtr->mark++;
+ switch (next) {
+ case OT_EMPTY:
+ numWords = 1; /* No arguments, so just the command */
+ break;
+ case OT_LITERAL: {
+ Tcl_Obj *const *litObjv = *litObjvPtr;
+ Tcl_Obj *literal = *litObjv;
+
+ if (optimize) {
+ int length, index;
+ const char *bytes = TclGetStringFromObj(literal, &length);
+ LiteralEntry *lePtr;
+ Tcl_Obj *objPtr;
+
+ index = TclRegisterNewLiteral(envPtr, bytes, length);
+ lePtr = envPtr->literalArrayPtr + index;
+ objPtr = lePtr->objPtr;
+ if ((objPtr->typePtr == NULL) && (literal->typePtr != NULL)) {
+ /*
+ * Would like to do this:
+ *
+ * lePtr->objPtr = literal;
+ * Tcl_IncrRefCount(literal);
+ * Tcl_DecrRefCount(objPtr);
+ *
+ * However, the design of the "global" and "local"
+ * LiteralTable does not permit the value of lePtr->objPtr
+ * to change. So rather than replace lePtr->objPtr, we
+ * do surgery to transfer our desired intrep into it.
+ *
+ */
+ objPtr->typePtr = literal->typePtr;
+ objPtr->internalRep = literal->internalRep;
+ literal->typePtr = NULL;
+ }
+ TclEmitPush(index, envPtr);
+ } else {
+ /*
+ * When optimize==0, we know the expression is a one-off
+ * and there's nothing to be gained from sharing literals
+ * when they won't live long, and the copies we have already
+ * have an appropriate intrep. In this case, skip literal
+ * registration that would enable sharing, and use the routine
+ * that preserves intreps.
+ */
+ TclEmitPush(TclAddLiteralObj(envPtr, literal, NULL), envPtr);
+ }
+ (*litObjvPtr)++;
+ break;
+ }
+ case OT_TOKENS:
+ TclCompileTokens(interp, tokenPtr+1, tokenPtr->numComponents,
+ envPtr);
+ tokenPtr += tokenPtr->numComponents + 1;
+ break;
+ default:
+ if (optimize && nodes[next].constant) {
+ Tcl_InterpState save = Tcl_SaveInterpState(interp, TCL_OK);
+ if (ExecConstantExprTree(interp, nodes, next, litObjvPtr)
+ == TCL_OK) {
+ TclEmitPush(TclAddLiteralObj(envPtr,
+ Tcl_GetObjResult(interp), NULL), envPtr);
+ } else {
+ TclCompileSyntaxError(interp, envPtr);
+ }
+ Tcl_RestoreInterpState(interp, save);
+ convert = 0;
+ } else {
+ nodePtr = nodes + next;
+ }
+ }
}
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclSingleOpCmd --
+ * Implements the commands: ~, !, <<, >>, %, !=, ne, in, ni
+ * in the ::tcl::mathop namespace. These commands have no
+ * extension to arbitrary arguments; they accept only exactly one
+ * or exactly two arguments as suitable for the operator.
+ *
+ * Results:
+ * A standard Tcl return code and result left in interp.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
- /*
- * Fix up the second jump around the "else" expression.
- */
+int
+TclSingleOpCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)clientData;
+ unsigned char lexeme;
+ OpNode nodes[2];
+ Tcl_Obj *const *litObjv = objv + 1;
+
+ if (objc != 1+occdPtr->i.numArgs) {
+ Tcl_WrongNumArgs(interp, 1, objv, occdPtr->expected);
+ return TCL_ERROR;
+ }
- dist = (envPtr->codeNext - envPtr->codeStart)
- - jumpAroundElseFixup.codeOffset;
- if (TclFixupForwardJump(envPtr, &jumpAroundElseFixup, dist, 127)) {
- /*
- * Update the else expression's starting code offset since it
- * moved down 3 bytes too.
- */
-
- elseCodeOffset += 3;
+ ParseLexeme(occdPtr->op, strlen(occdPtr->op), &lexeme, NULL);
+ nodes[0].lexeme = START;
+ nodes[0].mark = MARK_RIGHT;
+ nodes[0].right = 1;
+ nodes[1].lexeme = lexeme;
+ if (objc == 2) {
+ nodes[1].mark = MARK_RIGHT;
+ } else {
+ nodes[1].mark = MARK_LEFT;
+ nodes[1].left = OT_LITERAL;
}
-
- /*
- * Fix up the first jump to the "else" expression if the test was false.
- */
-
- dist = (elseCodeOffset - jumpAroundThenFixup.codeOffset);
- TclFixupForwardJump(envPtr, &jumpAroundThenFixup, dist, 127);
- *endPtrPtr = tokenPtr;
+ nodes[1].right = OT_LITERAL;
+ nodes[1].p.parent = 0;
- done:
- envPtr->currStackDepth = savedStackDepth + 1;
- return code;
+ return ExecConstantExprTree(interp, nodes, 0, &litObjv);
}
/*
*----------------------------------------------------------------------
*
- * CompileMathFuncCall --
- *
- * This procedure compiles a call on a math function in an expression:
- * mathFuncCall ::= funcName '(' [condExpr {',' condExpr}] ')'
+ * TclSortingOpCmd --
+ * Implements the commands: <, <=, >, >=, ==, eq
+ * in the ::tcl::mathop namespace. These commands are defined for
+ * arbitrary number of arguments by computing the AND of the base
+ * operator applied to all neighbor argument pairs.
*
* Results:
- * The return value is TCL_OK on a successful compilation and TCL_ERROR
- * on failure. If TCL_OK is returned, a pointer to the token just after
- * the last one in the subexpression is stored at the address in
- * endPtrPtr. If TCL_ERROR is returned, then the interpreter's result
- * contains an error message.
+ * A standard Tcl return code and result left in interp.
*
* Side effects:
- * Adds instructions to envPtr to evaluate the math function at
- * runtime.
+ * None.
*
*----------------------------------------------------------------------
*/
-static int
-CompileMathFuncCall(exprTokenPtr, funcName, infoPtr, envPtr, endPtrPtr)
- Tcl_Token *exprTokenPtr; /* Points to TCL_TOKEN_SUB_EXPR token
- * containing the math function call. */
- CONST char *funcName; /* Name of the math function. */
- ExprInfo *infoPtr; /* Describes the compilation state for the
- * expression being compiled. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
- Tcl_Token **endPtrPtr; /* If successful, a pointer to the token
- * just after the last token in the
- * subexpression is stored here. */
+int
+TclSortingOpCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const objv[])
{
- Tcl_Interp *interp = infoPtr->interp;
- Interp *iPtr = (Interp *) interp;
- MathFunc *mathFuncPtr;
- Tcl_HashEntry *hPtr;
- Tcl_Token *tokenPtr, *afterSubexprPtr;
- int code, i;
+ int code = TCL_OK;
- /*
- * Look up the MathFunc record for the function.
- */
+ if (objc < 3) {
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
+ } else {
+ TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)clientData;
+ Tcl_Obj **litObjv = (Tcl_Obj **) TclStackAlloc(interp,
+ 2*(objc-2)*sizeof(Tcl_Obj *));
+ OpNode *nodes = (OpNode *) TclStackAlloc(interp,
+ 2*(objc-2)*sizeof(OpNode));
+ unsigned char lexeme;
+ int i, lastAnd = 1;
+ Tcl_Obj *const *litObjPtrPtr = litObjv;
+
+ ParseLexeme(occdPtr->op, strlen(occdPtr->op), &lexeme, NULL);
+
+ litObjv[0] = objv[1];
+ nodes[0].lexeme = START;
+ nodes[0].mark = MARK_RIGHT;
+ for (i=2; i<objc-1; i++) {
+ litObjv[2*(i-1)-1] = objv[i];
+ nodes[2*(i-1)-1].lexeme = lexeme;
+ nodes[2*(i-1)-1].mark = MARK_LEFT;
+ nodes[2*(i-1)-1].left = OT_LITERAL;
+ nodes[2*(i-1)-1].right = OT_LITERAL;
+
+ litObjv[2*(i-1)] = objv[i];
+ nodes[2*(i-1)].lexeme = AND;
+ nodes[2*(i-1)].mark = MARK_LEFT;
+ nodes[2*(i-1)].left = lastAnd;
+ nodes[lastAnd].p.parent = 2*(i-1);
+
+ nodes[2*(i-1)].right = 2*(i-1)+1;
+ nodes[2*(i-1)+1].p.parent= 2*(i-1);
+
+ lastAnd = 2*(i-1);
+ }
+ litObjv[2*(objc-2)-1] = objv[objc-1];
- code = TCL_OK;
- hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, funcName);
- if (hPtr == NULL) {
- Tcl_ResetResult(interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "unknown math function \"", funcName, "\"", (char *) NULL);
- code = TCL_ERROR;
- goto done;
- }
- mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
+ nodes[2*(objc-2)-1].lexeme = lexeme;
+ nodes[2*(objc-2)-1].mark = MARK_LEFT;
+ nodes[2*(objc-2)-1].left = OT_LITERAL;
+ nodes[2*(objc-2)-1].right = OT_LITERAL;
- /*
- * If not a builtin function, push an object with the function's name.
- */
+ nodes[0].right = lastAnd;
+ nodes[lastAnd].p.parent = 0;
- if (mathFuncPtr->builtinFuncIndex < 0) {
- TclEmitPush(TclRegisterNewLiteral(envPtr, funcName, -1), envPtr);
+ code = ExecConstantExprTree(interp, nodes, 0, &litObjPtrPtr);
+
+ TclStackFree(interp, nodes);
+ TclStackFree(interp, litObjv);
}
+ return code;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclVariadicOpCmd --
+ * Implements the commands: +, *, &, |, ^, **
+ * in the ::tcl::mathop namespace. These commands are defined for
+ * arbitrary number of arguments by repeatedly applying the base
+ * operator with suitable associative rules. When fewer than two
+ * arguments are provided, suitable identity values are returned.
+ *
+ * Results:
+ * A standard Tcl return code and result left in interp.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
- /*
- * Compile any arguments for the function.
- */
+int
+TclVariadicOpCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)clientData;
+ unsigned char lexeme;
+ int code;
- tokenPtr = exprTokenPtr+2;
- afterSubexprPtr = exprTokenPtr + (exprTokenPtr->numComponents + 1);
- if (mathFuncPtr->numArgs > 0) {
- for (i = 0; i < mathFuncPtr->numArgs; i++) {
- if (tokenPtr == afterSubexprPtr) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "too few arguments for math function", -1);
- code = TCL_ERROR;
- goto done;
- }
- code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
- if (code != TCL_OK) {
- goto done;
+ if (objc < 2) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(occdPtr->i.identity));
+ return TCL_OK;
+ }
+
+ ParseLexeme(occdPtr->op, strlen(occdPtr->op), &lexeme, NULL);
+ lexeme |= BINARY;
+
+ if (objc == 2) {
+ Tcl_Obj *litObjv[2];
+ OpNode nodes[2];
+ int decrMe = 0;
+ Tcl_Obj *const *litObjPtrPtr = litObjv;
+
+ if (lexeme == EXPON) {
+ litObjv[1] = Tcl_NewIntObj(occdPtr->i.identity);
+ Tcl_IncrRefCount(litObjv[1]);
+ decrMe = 1;
+ litObjv[0] = objv[1];
+ nodes[0].lexeme = START;
+ nodes[0].mark = MARK_RIGHT;
+ nodes[0].right = 1;
+ nodes[1].lexeme = lexeme;
+ nodes[1].mark = MARK_LEFT;
+ nodes[1].left = OT_LITERAL;
+ nodes[1].right = OT_LITERAL;
+ nodes[1].p.parent = 0;
+ } else {
+ if (lexeme == DIVIDE) {
+ litObjv[0] = Tcl_NewDoubleObj(1.0);
+ } else {
+ litObjv[0] = Tcl_NewIntObj(occdPtr->i.identity);
}
- tokenPtr += (tokenPtr->numComponents + 1);
+ Tcl_IncrRefCount(litObjv[0]);
+ litObjv[1] = objv[1];
+ nodes[0].lexeme = START;
+ nodes[0].mark = MARK_RIGHT;
+ nodes[0].right = 1;
+ nodes[1].lexeme = lexeme;
+ nodes[1].mark = MARK_LEFT;
+ nodes[1].left = OT_LITERAL;
+ nodes[1].right = OT_LITERAL;
+ nodes[1].p.parent = 0;
}
- if (tokenPtr != afterSubexprPtr) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "too many arguments for math function", -1);
- code = TCL_ERROR;
- goto done;
- }
- } else if (tokenPtr != afterSubexprPtr) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "too many arguments for math function", -1);
- code = TCL_ERROR;
- goto done;
- }
-
- /*
- * Compile the call on the math function. Note that the "objc" argument
- * count for non-builtin functions is incremented by 1 to include the
- * function name itself.
- */
- if (mathFuncPtr->builtinFuncIndex >= 0) { /* a builtin function */
- /*
- * Adjust the current stack depth by the number of arguments
- * of the builtin function. This cannot be handled by the
- * TclEmitInstInt1 macro as the number of arguments is not
- * passed as an operand.
- */
+ code = ExecConstantExprTree(interp, nodes, 0, &litObjPtrPtr);
- if (envPtr->maxStackDepth < envPtr->currStackDepth) {
- envPtr->maxStackDepth = envPtr->currStackDepth;
- }
- TclEmitInstInt1(INST_CALL_BUILTIN_FUNC1,
- mathFuncPtr->builtinFuncIndex, envPtr);
- envPtr->currStackDepth -= mathFuncPtr->numArgs;
+ Tcl_DecrRefCount(litObjv[decrMe]);
+ return code;
} else {
- TclEmitInstInt1(INST_CALL_FUNC1, (mathFuncPtr->numArgs+1), envPtr);
- }
- *endPtrPtr = afterSubexprPtr;
+ Tcl_Obj *const *litObjv = objv + 1;
+ OpNode *nodes = (OpNode *) TclStackAlloc(interp,
+ (objc-1)*sizeof(OpNode));
+ int i, lastOp = OT_LITERAL;
+
+ nodes[0].lexeme = START;
+ nodes[0].mark = MARK_RIGHT;
+ if (lexeme == EXPON) {
+ for (i=objc-2; i>0; i-- ) {
+ nodes[i].lexeme = lexeme;
+ nodes[i].mark = MARK_LEFT;
+ nodes[i].left = OT_LITERAL;
+ nodes[i].right = lastOp;
+ if (lastOp >= 0) {
+ nodes[lastOp].p.parent = i;
+ }
+ lastOp = i;
+ }
+ } else {
+ for (i=1; i<objc-1; i++ ) {
+ nodes[i].lexeme = lexeme;
+ nodes[i].mark = MARK_LEFT;
+ nodes[i].left = lastOp;
+ if (lastOp >= 0) {
+ nodes[lastOp].p.parent = i;
+ }
+ nodes[i].right = OT_LITERAL;
+ lastOp = i;
+ }
+ }
+ nodes[0].right = lastOp;
+ nodes[lastOp].p.parent = 0;
- done:
- return code;
+ code = ExecConstantExprTree(interp, nodes, 0, &litObjv);
+
+ TclStackFree(interp, nodes);
+
+ return code;
+ }
}
/*
*----------------------------------------------------------------------
*
- * LogSyntaxError --
- *
- * This procedure is invoked after an error occurs when compiling an
- * expression. It sets the interpreter result to an error message
- * describing the error.
+ * TclNoIdentOpCmd --
+ * Implements the commands: -, /
+ * in the ::tcl::mathop namespace. These commands are defined for
+ * arbitrary non-zero number of arguments by repeatedly applying
+ * the base operator with suitable associative rules. When no
+ * arguments are provided, an error is raised.
*
* Results:
- * None.
+ * A standard Tcl return code and result left in interp.
*
* Side effects:
- * Sets the interpreter result to an error message describing the
- * expression that was being compiled when the error occurred.
+ * None.
*
*----------------------------------------------------------------------
*/
-static void
-LogSyntaxError(infoPtr)
- ExprInfo *infoPtr; /* Describes the compilation state for the
- * expression being compiled. */
+int
+TclNoIdentOpCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const objv[])
{
- int numBytes = (infoPtr->lastChar - infoPtr->expr);
- char buffer[100];
-
- sprintf(buffer, "syntax error in expression \"%.*s\"",
- ((numBytes > 60)? 60 : numBytes), infoPtr->expr);
- Tcl_ResetResult(infoPtr->interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(infoPtr->interp),
- buffer, (char *) NULL);
+ TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)clientData;
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, occdPtr->expected);
+ return TCL_ERROR;
+ }
+ return TclVariadicOpCmd(clientData, interp, objc, objv);
}
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclCompile.c b/generic/tclCompile.c
index e281a0a..6d64feb 100644
--- a/generic/tclCompile.c
+++ b/generic/tclCompile.c
@@ -1,15 +1,15 @@
-/*
+/*
* tclCompile.c --
*
- * This file contains procedures that compile Tcl commands or parts
- * of commands (like quoted strings or nested sub-commands) into a
- * sequence of instructions ("bytecodes").
+ * This file contains procedures that compile Tcl commands or parts of
+ * commands (like quoted strings or nested sub-commands) into a sequence
+ * of instructions ("bytecodes").
*
* Copyright (c) 1996-1998 Sun Microsystems, Inc.
- * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
+ * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
@@ -18,7 +18,7 @@
/*
* Table of all AuxData types.
*/
-
+
static Tcl_HashTable auxDataTypeTable;
static int auxDataTypeTableInitialized; /* 0 means not yet initialized. */
@@ -40,10 +40,10 @@ static int traceInitialized = 0;
/*
* A table describing the Tcl bytecode instructions. Entries in this table
- * must correspond to the instruction opcode definitions in tclCompile.h.
- * The names "op1" and "op4" refer to an instruction's one or four byte
- * first operand. Similarly, "stktop" and "stknext" refer to the topmost
- * and next to topmost stack elements.
+ * must correspond to the instruction opcode definitions in tclCompile.h. The
+ * names "op1" and "op4" refer to an instruction's one or four byte first
+ * operand. Similarly, "stktop" and "stknext" refer to the topmost and next to
+ * topmost stack elements.
*
* Note that the load, store, and incr instructions do not distinguish local
* from global variables; the bytecode interpreter at runtime uses the
@@ -51,222 +51,352 @@ static int traceInitialized = 0;
*/
InstructionDesc tclInstructionTable[] = {
- /* Name Bytes stackEffect #Opnds Operand types Stack top, next */
- {"done", 1, -1, 0, {OPERAND_NONE}},
+ /* Name Bytes stackEffect #Opnds Operand types */
+ {"done", 1, -1, 0, {OPERAND_NONE}},
/* Finish ByteCode execution and return stktop (top stack item) */
- {"push1", 2, +1, 1, {OPERAND_UINT1}},
+ {"push1", 2, +1, 1, {OPERAND_UINT1}},
/* Push object at ByteCode objArray[op1] */
- {"push4", 5, +1, 1, {OPERAND_UINT4}},
+ {"push4", 5, +1, 1, {OPERAND_UINT4}},
/* Push object at ByteCode objArray[op4] */
- {"pop", 1, -1, 0, {OPERAND_NONE}},
+ {"pop", 1, -1, 0, {OPERAND_NONE}},
/* Pop the topmost stack object */
- {"dup", 1, +1, 0, {OPERAND_NONE}},
+ {"dup", 1, +1, 0, {OPERAND_NONE}},
/* Duplicate the topmost stack object and push the result */
- {"concat1", 2, INT_MIN, 1, {OPERAND_UINT1}},
+ {"concat1", 2, INT_MIN, 1, {OPERAND_UINT1}},
/* Concatenate the top op1 items and push result */
- {"invokeStk1", 2, INT_MIN, 1, {OPERAND_UINT1}},
+ {"invokeStk1", 2, INT_MIN, 1, {OPERAND_UINT1}},
/* Invoke command named objv[0]; <objc,objv> = <op1,top op1> */
- {"invokeStk4", 5, INT_MIN, 1, {OPERAND_UINT4}},
+ {"invokeStk4", 5, INT_MIN, 1, {OPERAND_UINT4}},
/* Invoke command named objv[0]; <objc,objv> = <op4,top op4> */
- {"evalStk", 1, 0, 0, {OPERAND_NONE}},
+ {"evalStk", 1, 0, 0, {OPERAND_NONE}},
/* Evaluate command in stktop using Tcl_EvalObj. */
- {"exprStk", 1, 0, 0, {OPERAND_NONE}},
+ {"exprStk", 1, 0, 0, {OPERAND_NONE}},
/* Execute expression in stktop using Tcl_ExprStringObj. */
-
- {"loadScalar1", 2, 1, 1, {OPERAND_UINT1}},
+
+ {"loadScalar1", 2, 1, 1, {OPERAND_LVT1}},
/* Load scalar variable at index op1 <= 255 in call frame */
- {"loadScalar4", 5, 1, 1, {OPERAND_UINT4}},
+ {"loadScalar4", 5, 1, 1, {OPERAND_LVT4}},
/* Load scalar variable at index op1 >= 256 in call frame */
- {"loadScalarStk", 1, 0, 0, {OPERAND_NONE}},
+ {"loadScalarStk", 1, 0, 0, {OPERAND_NONE}},
/* Load scalar variable; scalar's name is stktop */
- {"loadArray1", 2, 0, 1, {OPERAND_UINT1}},
+ {"loadArray1", 2, 0, 1, {OPERAND_LVT1}},
/* Load array element; array at slot op1<=255, element is stktop */
- {"loadArray4", 5, 0, 1, {OPERAND_UINT4}},
+ {"loadArray4", 5, 0, 1, {OPERAND_LVT4}},
/* Load array element; array at slot op1 > 255, element is stktop */
- {"loadArrayStk", 1, -1, 0, {OPERAND_NONE}},
+ {"loadArrayStk", 1, -1, 0, {OPERAND_NONE}},
/* Load array element; element is stktop, array name is stknext */
- {"loadStk", 1, 0, 0, {OPERAND_NONE}},
+ {"loadStk", 1, 0, 0, {OPERAND_NONE}},
/* Load general variable; unparsed variable name is stktop */
- {"storeScalar1", 2, 0, 1, {OPERAND_UINT1}},
+ {"storeScalar1", 2, 0, 1, {OPERAND_LVT1}},
/* Store scalar variable at op1<=255 in frame; value is stktop */
- {"storeScalar4", 5, 0, 1, {OPERAND_UINT4}},
+ {"storeScalar4", 5, 0, 1, {OPERAND_LVT4}},
/* Store scalar variable at op1 > 255 in frame; value is stktop */
- {"storeScalarStk", 1, -1, 0, {OPERAND_NONE}},
+ {"storeScalarStk", 1, -1, 0, {OPERAND_NONE}},
/* Store scalar; value is stktop, scalar name is stknext */
- {"storeArray1", 2, -1, 1, {OPERAND_UINT1}},
+ {"storeArray1", 2, -1, 1, {OPERAND_LVT1}},
/* Store array element; array at op1<=255, value is top then elem */
- {"storeArray4", 5, -1, 1, {OPERAND_UINT4}},
+ {"storeArray4", 5, -1, 1, {OPERAND_LVT4}},
/* Store array element; array at op1>=256, value is top then elem */
- {"storeArrayStk", 1, -2, 0, {OPERAND_NONE}},
+ {"storeArrayStk", 1, -2, 0, {OPERAND_NONE}},
/* Store array element; value is stktop, then elem, array names */
- {"storeStk", 1, -1, 0, {OPERAND_NONE}},
+ {"storeStk", 1, -1, 0, {OPERAND_NONE}},
/* Store general variable; value is stktop, then unparsed name */
-
- {"incrScalar1", 2, 0, 1, {OPERAND_UINT1}},
+
+ {"incrScalar1", 2, 0, 1, {OPERAND_LVT1}},
/* Incr scalar at index op1<=255 in frame; incr amount is stktop */
- {"incrScalarStk", 1, -1, 0, {OPERAND_NONE}},
+ {"incrScalarStk", 1, -1, 0, {OPERAND_NONE}},
/* Incr scalar; incr amount is stktop, scalar's name is stknext */
- {"incrArray1", 2, -1, 1, {OPERAND_UINT1}},
+ {"incrArray1", 2, -1, 1, {OPERAND_LVT1}},
/* Incr array elem; arr at slot op1<=255, amount is top then elem */
- {"incrArrayStk", 1, -2, 0, {OPERAND_NONE}},
+ {"incrArrayStk", 1, -2, 0, {OPERAND_NONE}},
/* Incr array element; amount is top then elem then array names */
- {"incrStk", 1, -1, 0, {OPERAND_NONE}},
+ {"incrStk", 1, -1, 0, {OPERAND_NONE}},
/* Incr general variable; amount is stktop then unparsed var name */
- {"incrScalar1Imm", 3, +1, 2, {OPERAND_UINT1, OPERAND_INT1}},
+ {"incrScalar1Imm", 3, +1, 2, {OPERAND_LVT1, OPERAND_INT1}},
/* Incr scalar at slot op1 <= 255; amount is 2nd operand byte */
- {"incrScalarStkImm", 2, 0, 1, {OPERAND_INT1}},
+ {"incrScalarStkImm", 2, 0, 1, {OPERAND_INT1}},
/* Incr scalar; scalar name is stktop; incr amount is op1 */
- {"incrArray1Imm", 3, 0, 2, {OPERAND_UINT1, OPERAND_INT1}},
+ {"incrArray1Imm", 3, 0, 2, {OPERAND_LVT1, OPERAND_INT1}},
/* Incr array elem; array at slot op1 <= 255, elem is stktop,
* amount is 2nd operand byte */
- {"incrArrayStkImm", 2, -1, 1, {OPERAND_INT1}},
+ {"incrArrayStkImm", 2, -1, 1, {OPERAND_INT1}},
/* Incr array element; elem is top then array name, amount is op1 */
- {"incrStkImm", 2, 0, 1, {OPERAND_INT1}},
+ {"incrStkImm", 2, 0, 1, {OPERAND_INT1}},
/* Incr general variable; unparsed name is top, amount is op1 */
-
- {"jump1", 2, 0, 1, {OPERAND_INT1}},
+
+ {"jump1", 2, 0, 1, {OPERAND_INT1}},
/* Jump relative to (pc + op1) */
- {"jump4", 5, 0, 1, {OPERAND_INT4}},
+ {"jump4", 5, 0, 1, {OPERAND_INT4}},
/* Jump relative to (pc + op4) */
- {"jumpTrue1", 2, -1, 1, {OPERAND_INT1}},
+ {"jumpTrue1", 2, -1, 1, {OPERAND_INT1}},
/* Jump relative to (pc + op1) if stktop expr object is true */
- {"jumpTrue4", 5, -1, 1, {OPERAND_INT4}},
+ {"jumpTrue4", 5, -1, 1, {OPERAND_INT4}},
/* Jump relative to (pc + op4) if stktop expr object is true */
- {"jumpFalse1", 2, -1, 1, {OPERAND_INT1}},
+ {"jumpFalse1", 2, -1, 1, {OPERAND_INT1}},
/* Jump relative to (pc + op1) if stktop expr object is false */
- {"jumpFalse4", 5, -1, 1, {OPERAND_INT4}},
+ {"jumpFalse4", 5, -1, 1, {OPERAND_INT4}},
/* Jump relative to (pc + op4) if stktop expr object is false */
- {"lor", 1, -1, 0, {OPERAND_NONE}},
+ {"lor", 1, -1, 0, {OPERAND_NONE}},
/* Logical or: push (stknext || stktop) */
- {"land", 1, -1, 0, {OPERAND_NONE}},
+ {"land", 1, -1, 0, {OPERAND_NONE}},
/* Logical and: push (stknext && stktop) */
- {"bitor", 1, -1, 0, {OPERAND_NONE}},
+ {"bitor", 1, -1, 0, {OPERAND_NONE}},
/* Bitwise or: push (stknext | stktop) */
- {"bitxor", 1, -1, 0, {OPERAND_NONE}},
+ {"bitxor", 1, -1, 0, {OPERAND_NONE}},
/* Bitwise xor push (stknext ^ stktop) */
- {"bitand", 1, -1, 0, {OPERAND_NONE}},
+ {"bitand", 1, -1, 0, {OPERAND_NONE}},
/* Bitwise and: push (stknext & stktop) */
- {"eq", 1, -1, 0, {OPERAND_NONE}},
+ {"eq", 1, -1, 0, {OPERAND_NONE}},
/* Equal: push (stknext == stktop) */
- {"neq", 1, -1, 0, {OPERAND_NONE}},
+ {"neq", 1, -1, 0, {OPERAND_NONE}},
/* Not equal: push (stknext != stktop) */
- {"lt", 1, -1, 0, {OPERAND_NONE}},
+ {"lt", 1, -1, 0, {OPERAND_NONE}},
/* Less: push (stknext < stktop) */
- {"gt", 1, -1, 0, {OPERAND_NONE}},
+ {"gt", 1, -1, 0, {OPERAND_NONE}},
/* Greater: push (stknext || stktop) */
- {"le", 1, -1, 0, {OPERAND_NONE}},
- /* Logical or: push (stknext || stktop) */
- {"ge", 1, -1, 0, {OPERAND_NONE}},
- /* Logical or: push (stknext || stktop) */
- {"lshift", 1, -1, 0, {OPERAND_NONE}},
+ {"le", 1, -1, 0, {OPERAND_NONE}},
+ /* Less or equal: push (stknext || stktop) */
+ {"ge", 1, -1, 0, {OPERAND_NONE}},
+ /* Greater or equal: push (stknext || stktop) */
+ {"lshift", 1, -1, 0, {OPERAND_NONE}},
/* Left shift: push (stknext << stktop) */
- {"rshift", 1, -1, 0, {OPERAND_NONE}},
+ {"rshift", 1, -1, 0, {OPERAND_NONE}},
/* Right shift: push (stknext >> stktop) */
- {"add", 1, -1, 0, {OPERAND_NONE}},
+ {"add", 1, -1, 0, {OPERAND_NONE}},
/* Add: push (stknext + stktop) */
- {"sub", 1, -1, 0, {OPERAND_NONE}},
+ {"sub", 1, -1, 0, {OPERAND_NONE}},
/* Sub: push (stkext - stktop) */
- {"mult", 1, -1, 0, {OPERAND_NONE}},
+ {"mult", 1, -1, 0, {OPERAND_NONE}},
/* Multiply: push (stknext * stktop) */
- {"div", 1, -1, 0, {OPERAND_NONE}},
+ {"div", 1, -1, 0, {OPERAND_NONE}},
/* Divide: push (stknext / stktop) */
- {"mod", 1, -1, 0, {OPERAND_NONE}},
+ {"mod", 1, -1, 0, {OPERAND_NONE}},
/* Mod: push (stknext % stktop) */
- {"uplus", 1, 0, 0, {OPERAND_NONE}},
+ {"uplus", 1, 0, 0, {OPERAND_NONE}},
/* Unary plus: push +stktop */
- {"uminus", 1, 0, 0, {OPERAND_NONE}},
+ {"uminus", 1, 0, 0, {OPERAND_NONE}},
/* Unary minus: push -stktop */
- {"bitnot", 1, 0, 0, {OPERAND_NONE}},
+ {"bitnot", 1, 0, 0, {OPERAND_NONE}},
/* Bitwise not: push ~stktop */
- {"not", 1, 0, 0, {OPERAND_NONE}},
+ {"not", 1, 0, 0, {OPERAND_NONE}},
/* Logical not: push !stktop */
- {"callBuiltinFunc1", 2, 1, 1, {OPERAND_UINT1}},
+ {"callBuiltinFunc1", 2, 1, 1, {OPERAND_UINT1}},
/* Call builtin math function with index op1; any args are on stk */
- {"callFunc1", 2, INT_MIN, 1, {OPERAND_UINT1}},
- /* Call non-builtin func objv[0]; <objc,objv>=<op1,top op1> */
- {"tryCvtToNumeric", 1, 0, 0, {OPERAND_NONE}},
+ {"callFunc1", 2, INT_MIN, 1, {OPERAND_UINT1}},
+ /* Call non-builtin func objv[0]; <objc,objv>=<op1,top op1> */
+ {"tryCvtToNumeric", 1, 0, 0, {OPERAND_NONE}},
/* Try converting stktop to first int then double if possible. */
- {"break", 1, 0, 0, {OPERAND_NONE}},
+ {"break", 1, 0, 0, {OPERAND_NONE}},
/* Abort closest enclosing loop; if none, return TCL_BREAK code. */
- {"continue", 1, 0, 0, {OPERAND_NONE}},
- /* Skip to next iteration of closest enclosing loop; if none,
- * return TCL_CONTINUE code. */
+ {"continue", 1, 0, 0, {OPERAND_NONE}},
+ /* Skip to next iteration of closest enclosing loop; if none, return
+ * TCL_CONTINUE code. */
- {"foreach_start4", 5, 0, 1, {OPERAND_UINT4}},
+ {"foreach_start4", 5, 0, 1, {OPERAND_AUX4}},
/* Initialize execution of a foreach loop. Operand is aux data index
* of the ForeachInfo structure for the foreach command. */
- {"foreach_step4", 5, +1, 1, {OPERAND_UINT4}},
+ {"foreach_step4", 5, +1, 1, {OPERAND_AUX4}},
/* "Step" or begin next iteration of foreach loop. Push 0 if to
- * terminate loop, else push 1. */
+ * terminate loop, else push 1. */
- {"beginCatch4", 5, 0, 1, {OPERAND_UINT4}},
- /* Record start of catch with the operand's exception index.
- * Push the current stack depth onto a special catch stack. */
- {"endCatch", 1, 0, 0, {OPERAND_NONE}},
+ {"beginCatch4", 5, 0, 1, {OPERAND_UINT4}},
+ /* Record start of catch with the operand's exception index. Push the
+ * current stack depth onto a special catch stack. */
+ {"endCatch", 1, 0, 0, {OPERAND_NONE}},
/* End of last catch. Pop the bytecode interpreter's catch stack. */
- {"pushResult", 1, +1, 0, {OPERAND_NONE}},
+ {"pushResult", 1, +1, 0, {OPERAND_NONE}},
/* Push the interpreter's object result onto the stack. */
- {"pushReturnCode", 1, +1, 0, {OPERAND_NONE}},
- /* Push interpreter's return code (e.g. TCL_OK or TCL_ERROR) as
- * a new object onto the stack. */
- {"streq", 1, -1, 0, {OPERAND_NONE}},
+ {"pushReturnCode", 1, +1, 0, {OPERAND_NONE}},
+ /* Push interpreter's return code (e.g. TCL_OK or TCL_ERROR) as a new
+ * object onto the stack. */
+
+ {"streq", 1, -1, 0, {OPERAND_NONE}},
/* Str Equal: push (stknext eq stktop) */
- {"strneq", 1, -1, 0, {OPERAND_NONE}},
+ {"strneq", 1, -1, 0, {OPERAND_NONE}},
/* Str !Equal: push (stknext neq stktop) */
- {"strcmp", 1, -1, 0, {OPERAND_NONE}},
+ {"strcmp", 1, -1, 0, {OPERAND_NONE}},
/* Str Compare: push (stknext cmp stktop) */
- {"strlen", 1, 0, 0, {OPERAND_NONE}},
+ {"strlen", 1, 0, 0, {OPERAND_NONE}},
/* Str Length: push (strlen stktop) */
- {"strindex", 1, -1, 0, {OPERAND_NONE}},
+ {"strindex", 1, -1, 0, {OPERAND_NONE}},
/* Str Index: push (strindex stknext stktop) */
- {"strmatch", 2, -1, 1, {OPERAND_INT1}},
+ {"strmatch", 2, -1, 1, {OPERAND_INT1}},
/* Str Match: push (strmatch stknext stktop) opnd == nocase */
- {"list", 5, INT_MIN, 1, {OPERAND_UINT4}},
+
+ {"list", 5, INT_MIN, 1, {OPERAND_UINT4}},
/* List: push (stk1 stk2 ... stktop) */
- {"listindex", 1, -1, 0, {OPERAND_NONE}},
+ {"listIndex", 1, -1, 0, {OPERAND_NONE}},
/* List Index: push (listindex stknext stktop) */
- {"listlength", 1, 0, 0, {OPERAND_NONE}},
+ {"listLength", 1, 0, 0, {OPERAND_NONE}},
/* List Len: push (listlength stktop) */
- {"appendScalar1", 2, 0, 1, {OPERAND_UINT1}},
+
+ {"appendScalar1", 2, 0, 1, {OPERAND_LVT1}},
/* Append scalar variable at op1<=255 in frame; value is stktop */
- {"appendScalar4", 5, 0, 1, {OPERAND_UINT4}},
+ {"appendScalar4", 5, 0, 1, {OPERAND_LVT4}},
/* Append scalar variable at op1 > 255 in frame; value is stktop */
- {"appendArray1", 2, -1, 1, {OPERAND_UINT1}},
+ {"appendArray1", 2, -1, 1, {OPERAND_LVT1}},
/* Append array element; array at op1<=255, value is top then elem */
- {"appendArray4", 5, -1, 1, {OPERAND_UINT4}},
+ {"appendArray4", 5, -1, 1, {OPERAND_LVT4}},
/* Append array element; array at op1>=256, value is top then elem */
- {"appendArrayStk", 1, -2, 0, {OPERAND_NONE}},
+ {"appendArrayStk", 1, -2, 0, {OPERAND_NONE}},
/* Append array element; value is stktop, then elem, array names */
- {"appendStk", 1, -1, 0, {OPERAND_NONE}},
+ {"appendStk", 1, -1, 0, {OPERAND_NONE}},
/* Append general variable; value is stktop, then unparsed name */
- {"lappendScalar1", 2, 0, 1, {OPERAND_UINT1}},
+ {"lappendScalar1", 2, 0, 1, {OPERAND_LVT1}},
/* Lappend scalar variable at op1<=255 in frame; value is stktop */
- {"lappendScalar4", 5, 0, 1, {OPERAND_UINT4}},
+ {"lappendScalar4", 5, 0, 1, {OPERAND_LVT4}},
/* Lappend scalar variable at op1 > 255 in frame; value is stktop */
- {"lappendArray1", 2, -1, 1, {OPERAND_UINT1}},
+ {"lappendArray1", 2, -1, 1, {OPERAND_LVT1}},
/* Lappend array element; array at op1<=255, value is top then elem */
- {"lappendArray4", 5, -1, 1, {OPERAND_UINT4}},
+ {"lappendArray4", 5, -1, 1, {OPERAND_LVT4}},
/* Lappend array element; array at op1>=256, value is top then elem */
- {"lappendArrayStk", 1, -2, 0, {OPERAND_NONE}},
+ {"lappendArrayStk", 1, -2, 0, {OPERAND_NONE}},
/* Lappend array element; value is stktop, then elem, array names */
- {"lappendStk", 1, -1, 0, {OPERAND_NONE}},
+ {"lappendStk", 1, -1, 0, {OPERAND_NONE}},
/* Lappend general variable; value is stktop, then unparsed name */
- {"lindexMulti", 5, INT_MIN, 1, {OPERAND_UINT4}},
- /* Lindex with generalized args, operand is number of stacked objs
- * used: (operand-1) entries from stktop are the indices; then list
- * to process. */
- {"over", 5, +1, 1, {OPERAND_UINT4}},
- /* Duplicate the arg-th element from top of stack (TOS=0) */
- {"lsetList", 1, -2, 0, {OPERAND_NONE}},
- /* Four-arg version of 'lset'. stktop is old value; next is
- * new element value, next is the index list; pushes new value */
- {"lsetFlat", 5, INT_MIN, 1, {OPERAND_UINT4}},
- /* Three- or >=5-arg version of 'lset', operand is number of
- * stacked objs: stktop is old value, next is new element value, next
- * come (operand-2) indices; pushes the new value.
+
+ {"lindexMulti", 5, INT_MIN, 1, {OPERAND_UINT4}},
+ /* Lindex with generalized args, operand is number of stacked objs
+ * used: (operand-1) entries from stktop are the indices; then list to
+ * process. */
+ {"over", 5, +1, 1, {OPERAND_UINT4}},
+ /* Duplicate the arg-th element from top of stack (TOS=0) */
+ {"lsetList", 1, -2, 0, {OPERAND_NONE}},
+ /* Four-arg version of 'lset'. stktop is old value; next is new
+ * element value, next is the index list; pushes new value */
+ {"lsetFlat", 5, INT_MIN, 1, {OPERAND_UINT4}},
+ /* Three- or >=5-arg version of 'lset', operand is number of stacked
+ * objs: stktop is old value, next is new element value, next come
+ * (operand-2) indices; pushes the new value.
*/
+
+ {"returnImm", 9, -1, 2, {OPERAND_INT4, OPERAND_UINT4}},
+ /* Compiled [return], code, level are operands; options and result
+ * are on the stack. */
+ {"expon", 1, -1, 0, {OPERAND_NONE}},
+ /* Binary exponentiation operator: push (stknext ** stktop) */
+
+ /*
+ * NOTE: the stack effects of expandStkTop and invokeExpanded are wrong -
+ * but it cannot be done right at compile time, the stack effect is only
+ * known at run time. The value for invokeExpanded is estimated better at
+ * compile time.
+ * See the comments further down in this file, where INST_INVOKE_EXPANDED
+ * is emitted.
+ */
+ {"expandStart", 1, 0, 0, {OPERAND_NONE}},
+ /* Start of command with {*} (expanded) arguments */
+ {"expandStkTop", 5, 0, 1, {OPERAND_UINT4}},
+ /* Expand the list at stacktop: push its elements on the stack */
+ {"invokeExpanded", 1, 0, 0, {OPERAND_NONE}},
+ /* Invoke the command marked by the last 'expandStart' */
+
+ {"listIndexImm", 5, 0, 1, {OPERAND_IDX4}},
+ /* List Index: push (lindex stktop op4) */
+ {"listRangeImm", 9, 0, 2, {OPERAND_IDX4, OPERAND_IDX4}},
+ /* List Range: push (lrange stktop op4 op4) */
+ {"startCommand", 9, 0, 2, {OPERAND_INT4,OPERAND_UINT4}},
+ /* Start of bytecoded command: op is the length of the cmd's code, op2
+ * is number of commands here */
+
+ {"listIn", 1, -1, 0, {OPERAND_NONE}},
+ /* List containment: push [lsearch stktop stknext]>=0) */
+ {"listNotIn", 1, -1, 0, {OPERAND_NONE}},
+ /* List negated containment: push [lsearch stktop stknext]<0) */
+
+ {"pushReturnOpts", 1, +1, 0, {OPERAND_NONE}},
+ /* Push the interpreter's return option dictionary as an object on the
+ * stack. */
+ {"returnStk", 1, -2, 0, {OPERAND_NONE}},
+ /* Compiled [return]; options and result are on the stack, code and
+ * level are in the options. */
+
+ {"dictGet", 5, INT_MIN, 1, {OPERAND_UINT4}},
+ /* The top op4 words (min 1) are a key path into the dictionary just
+ * below the keys on the stack, and all those values are replaced by
+ * the value read out of that key-path (like [dict get]).
+ * Stack: ... dict key1 ... keyN => ... value */
+ {"dictSet", 9, INT_MIN, 2, {OPERAND_UINT4, OPERAND_LVT4}},
+ /* Update a dictionary value such that the keys are a path pointing to
+ * the value. op4#1 = numKeys, op4#2 = LVTindex
+ * Stack: ... key1 ... keyN value => ... newDict */
+ {"dictUnset", 9, INT_MIN, 2, {OPERAND_UINT4, OPERAND_LVT4}},
+ /* Update a dictionary value such that the keys are not a path pointing
+ * to any value. op4#1 = numKeys, op4#2 = LVTindex
+ * Stack: ... key1 ... keyN => ... newDict */
+ {"dictIncrImm", 9, 0, 2, {OPERAND_INT4, OPERAND_LVT4}},
+ /* Update a dictionary value such that the value pointed to by key is
+ * incremented by some value (or set to it if the key isn't in the
+ * dictionary at all). op4#1 = incrAmount, op4#2 = LVTindex
+ * Stack: ... key => ... newDict */
+ {"dictAppend", 5, -1, 1, {OPERAND_LVT4}},
+ /* Update a dictionary value such that the value pointed to by key has
+ * some value string-concatenated onto it. op4 = LVTindex
+ * Stack: ... key valueToAppend => ... newDict */
+ {"dictLappend", 5, -1, 1, {OPERAND_LVT4}},
+ /* Update a dictionary value such that the value pointed to by key has
+ * some value list-appended onto it. op4 = LVTindex
+ * Stack: ... key valueToAppend => ... newDict */
+ {"dictFirst", 5, +2, 1, {OPERAND_LVT4}},
+ /* Begin iterating over the dictionary, using the local scalar
+ * indicated by op4 to hold the iterator state. If doneBool is true,
+ * dictDone *must* be called later on.
+ * Stack: ... dict => ... value key doneBool */
+ {"dictNext", 5, +3, 1, {OPERAND_LVT4}},
+ /* Get the next iteration from the iterator in op4's local scalar.
+ * Stack: ... => ... value key doneBool */
+ {"dictDone", 5, 0, 1, {OPERAND_LVT4}},
+ /* Terminate the iterator in op4's local scalar. */
+ {"dictUpdateStart", 9, 0, 2, {OPERAND_LVT4, OPERAND_AUX4}},
+ /* Create the variables (described in the aux data referred to by the
+ * second immediate argument) to mirror the state of the dictionary in
+ * the variable referred to by the first immediate argument. The list
+ * of keys (popped from the stack) must be the same length as the list
+ * of variables.
+ * Stack: ... keyList => ... */
+ {"dictUpdateEnd", 9, -1, 2, {OPERAND_LVT4, OPERAND_AUX4}},
+ /* Reflect the state of local variables (described in the aux data
+ * referred to by the second immediate argument) back to the state of
+ * the dictionary in the variable referred to by the first immediate
+ * argument. The list of keys (popped from the stack) must be the same
+ * length as the list of variables.
+ * Stack: ... keyList => ... */
+ {"jumpTable", 5, -1, 1, {OPERAND_AUX4}},
+ /* Jump according to the jump-table (in AuxData as indicated by the
+ * operand) and the argument popped from the list. Always executes the
+ * next instruction if no match against the table's entries was found.
+ * Stack: ... value => ...
+ * Note that the jump table contains offsets relative to the PC when
+ * it points to this instruction; the code is relocatable. */
+ {"upvar", 5, 0, 1, {OPERAND_LVT4}},
+ /* finds level and otherName in stack, links to local variable at
+ * index op1. Leaves the level on stack. */
+ {"nsupvar", 5, 0, 1, {OPERAND_LVT4}},
+ /* finds namespace and otherName in stack, links to local variable at
+ * index op1. Leaves the namespace on stack. */
+ {"variable", 5, 0, 1, {OPERAND_LVT4}},
+ /* finds namespace and otherName in stack, links to local variable at
+ * index op1. Leaves the namespace on stack. */
+ {"syntax", 9, -1, 2, {OPERAND_INT4, OPERAND_UINT4}},
+ /* Compiled bytecodes to signal syntax error. */
+ {"reverse", 5, 0, 1, {OPERAND_UINT4}},
+ /* Reverse the order of the arg elements at the top of stack */
+
+ {"regexp", 2, -1, 1, {OPERAND_INT1}},
+ /* Regexp: push (regexp stknext stktop) opnd == nocase */
+
+ {"existScalar", 5, 1, 1, {OPERAND_LVT4}},
+ /* Test if scalar variable at index op1 in call frame exists */
+ {"existArray", 5, 0, 1, {OPERAND_LVT4}},
+ /* Test if array element exists; array at slot op1, element is
+ * stktop */
+ {"existArrayStk", 1, -1, 0, {OPERAND_NONE}},
+ /* Test if array element exists; element is stktop, array name is
+ * stknext */
+ {"existStk", 1, 0, 0, {OPERAND_NONE}},
+ /* Test if general variable exists; unparsed variable name is stktop*/
{0}
};
@@ -274,53 +404,45 @@ InstructionDesc tclInstructionTable[] = {
* Prototypes for procedures defined later in this file:
*/
-static void DupByteCodeInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
- Tcl_Obj *copyPtr));
-static unsigned char * EncodeCmdLocMap _ANSI_ARGS_((
- CompileEnv *envPtr, ByteCode *codePtr,
- unsigned char *startPtr));
-static void EnterCmdExtentData _ANSI_ARGS_((
- CompileEnv *envPtr, int cmdNumber,
- int numSrcBytes, int numCodeBytes));
-static void EnterCmdStartData _ANSI_ARGS_((
- CompileEnv *envPtr, int cmdNumber,
- int srcOffset, int codeOffset));
-static void FreeByteCodeInternalRep _ANSI_ARGS_((
- Tcl_Obj *objPtr));
-static int GetCmdLocEncodingSize _ANSI_ARGS_((
- CompileEnv *envPtr));
-static void LogCompilationInfo _ANSI_ARGS_((Tcl_Interp *interp,
- CONST char *script, CONST char *command,
- int length));
+static void DupByteCodeInternalRep(Tcl_Obj *srcPtr,
+ Tcl_Obj *copyPtr);
+static unsigned char * EncodeCmdLocMap(CompileEnv *envPtr,
+ ByteCode *codePtr, unsigned char *startPtr);
+static void EnterCmdExtentData(CompileEnv *envPtr,
+ int cmdNumber, int numSrcBytes, int numCodeBytes);
+static void EnterCmdStartData(CompileEnv *envPtr,
+ int cmdNumber, int srcOffset, int codeOffset);
+static void FreeByteCodeInternalRep(Tcl_Obj *objPtr);
+static int GetCmdLocEncodingSize(CompileEnv *envPtr);
#ifdef TCL_COMPILE_STATS
-static void RecordByteCodeStats _ANSI_ARGS_((
- ByteCode *codePtr));
+static void RecordByteCodeStats(ByteCode *codePtr);
#endif /* TCL_COMPILE_STATS */
-static int SetByteCodeFromAny _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
-
-#ifdef TCL_TIP280
-/* TIP #280 : Helper for building the per-word line information of all
- * compiled commands */
-static void EnterCmdWordData _ANSI_ARGS_((
- ExtCmdLoc *eclPtr, int srcOffset, Tcl_Token* tokenPtr,
- CONST char* cmd, int len, int numWords, int line,
- int* clNext, int** lines, CompileEnv* envPtr));
-static void ReleaseCmdWordData _ANSI_ARGS_((ExtCmdLoc* eclPtr));
-#endif
-
+static int SetByteCodeFromAny(Tcl_Interp *interp,
+ Tcl_Obj *objPtr);
+static int FormatInstruction(ByteCode *codePtr,
+ unsigned char *pc, Tcl_Obj *bufferObj);
+static void PrintSourceToObj(Tcl_Obj *appendObj,
+ const char *stringPtr, int maxChars);
+/*
+ * TIP #280: Helper for building the per-word line information of all compiled
+ * commands.
+ */
+static void EnterCmdWordData(ExtCmdLoc *eclPtr, int srcOffset,
+ Tcl_Token *tokenPtr, const char *cmd, int len,
+ int numWords, int line, int* clNext, int **lines,
+ CompileEnv* envPtr);
/*
- * The structure below defines the bytecode Tcl object type by
- * means of procedures that can be invoked by generic object code.
+ * The structure below defines the bytecode Tcl object type by means of
+ * procedures that can be invoked by generic object code.
*/
Tcl_ObjType tclByteCodeType = {
- "bytecode", /* name */
- FreeByteCodeInternalRep, /* freeIntRepProc */
- DupByteCodeInternalRep, /* dupIntRepProc */
- (Tcl_UpdateStringProc *) NULL, /* updateStringProc */
- SetByteCodeFromAny /* setFromAnyProc */
+ "bytecode", /* name */
+ FreeByteCodeInternalRep, /* freeIntRepProc */
+ DupByteCodeInternalRep, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ SetByteCodeFromAny /* setFromAnyProc */
};
/*
@@ -330,10 +452,10 @@ Tcl_ObjType tclByteCodeType = {
*
* Part of the bytecode Tcl object type implementation. Attempts to
* generate an byte code internal form for the Tcl object "objPtr" by
- * compiling its string representation. This function also takes
- * a hook procedure that will be invoked to perform any needed post
- * processing on the compilation results before generating byte
- * codes. interp is compilation context and may not be NULL.
+ * compiling its string representation. This function also takes a hook
+ * procedure that will be invoked to perform any needed post processing
+ * on the compilation results before generating byte codes. interp is
+ * compilation context and may not be NULL.
*
* Results:
* The return value is a standard Tcl object result. If an error occurs
@@ -342,61 +464,51 @@ Tcl_ObjType tclByteCodeType = {
*
* Side effects:
* Frees the old internal representation. If no error occurs, then the
- * compiled code is stored as "objPtr"s bytecode representation.
- * Also, if debugging, initializes the "tcl_traceCompile" Tcl variable
- * used to trace compilations.
+ * compiled code is stored as "objPtr"s bytecode representation. Also, if
+ * debugging, initializes the "tcl_traceCompile" Tcl variable used to
+ * trace compilations.
*
*----------------------------------------------------------------------
*/
int
-TclSetByteCodeFromAny(interp, objPtr, hookProc, clientData)
- Tcl_Interp *interp; /* The interpreter for which the code is
- * being compiled. Must not be NULL. */
- Tcl_Obj *objPtr; /* The object to make a ByteCode object. */
- CompileHookProc *hookProc; /* Procedure to invoke after compilation. */
- ClientData clientData; /* Hook procedure private data. */
+TclSetByteCodeFromAny(
+ Tcl_Interp *interp, /* The interpreter for which the code is being
+ * compiled. Must not be NULL. */
+ Tcl_Obj *objPtr, /* The object to make a ByteCode object. */
+ CompileHookProc *hookProc, /* Procedure to invoke after compilation. */
+ ClientData clientData) /* Hook procedure private data. */
{
Interp *iPtr = (Interp *) interp;
- CompileEnv compEnv; /* Compilation environment structure
- * allocated in frame. */
- LiteralTable *localTablePtr = &(compEnv.localLitTable);
+ CompileEnv compEnv; /* Compilation environment structure allocated
+ * in frame. */
register AuxData *auxDataPtr;
LiteralEntry *entryPtr;
register int i;
- int length, nested, result;
- char *string;
-#ifdef TCL_TIP280
+ int length, result = TCL_OK;
+ const char *stringPtr;
ContLineLoc* clLocPtr;
-#endif
+
#ifdef TCL_COMPILE_DEBUG
if (!traceInitialized) {
- if (Tcl_LinkVar(interp, "tcl_traceCompile",
- (char *) &tclTraceCompile, TCL_LINK_INT) != TCL_OK) {
- panic("SetByteCodeFromAny: unable to create link for tcl_traceCompile variable");
- }
- traceInitialized = 1;
+ if (Tcl_LinkVar(interp, "tcl_traceCompile",
+ (char *) &tclTraceCompile, TCL_LINK_INT) != TCL_OK) {
+ Tcl_Panic("SetByteCodeFromAny: unable to create link for tcl_traceCompile variable");
+ }
+ traceInitialized = 1;
}
#endif
- if (iPtr->evalFlags & TCL_BRACKET_TERM) {
- nested = 1;
- } else {
- nested = 0;
- }
- string = Tcl_GetStringFromObj(objPtr, &length);
-#ifndef TCL_TIP280
- TclInitCompileEnv(interp, &compEnv, string, length);
-#else
+ stringPtr = TclGetStringFromObj(objPtr, &length);
+
/*
- * TIP #280. Pick up the CmdFrame in which the BC compiler was invoked
- * and use to initialize the tracking in the compiler. This information
- * was stored by TclCompEvalObj (tclExecute.c), and ProcCompileProc
- * (tclProc.c).
+ * TIP #280: Pick up the CmdFrame in which the BC compiler was invoked and
+ * use to initialize the tracking in the compiler. This information was
+ * stored by TclCompEvalObj and ProcCompileProc.
*/
- TclInitCompileEnv(interp, &compEnv, string, length,
- iPtr->invokeCmdFramePtr, iPtr->invokeWord);
+ TclInitCompileEnv(interp, &compEnv, stringPtr, length,
+ iPtr->invokeCmdFramePtr, iPtr->invokeWord);
/*
* Now we check if we have data about invisible continuation lines for the
* script, and make it available to the compile environment, if so.
@@ -415,45 +527,43 @@ TclSetByteCodeFromAny(interp, objPtr, hookProc, clientData)
compEnv.clNext = &compEnv.clLoc->loc[0];
Tcl_Preserve (compEnv.clLoc);
}
-#endif
- result = TclCompileScript(interp, string, length, nested, &compEnv);
- if (result == TCL_OK) {
- /*
- * Successful compilation. Add a "done" instruction at the end.
- */
+ TclCompileScript(interp, stringPtr, length, &compEnv);
- compEnv.numSrcBytes = iPtr->termOffset;
- TclEmitOpcode(INST_DONE, &compEnv);
+ /*
+ * Successful compilation. Add a "done" instruction at the end.
+ */
- /*
- * Invoke the compilation hook procedure if one exists.
- */
+ TclEmitOpcode(INST_DONE, &compEnv);
- if (hookProc) {
- result = (*hookProc)(interp, &compEnv, clientData);
- }
+ /*
+ * Invoke the compilation hook procedure if one exists.
+ */
+
+ if (hookProc) {
+ result = (*hookProc)(interp, &compEnv, clientData);
+ }
+
+ /*
+ * Change the object into a ByteCode object. Ownership of the literal
+ * objects and aux data items is given to the ByteCode object.
+ */
- /*
- * Change the object into a ByteCode object. Ownership of the literal
- * objects and aux data items is given to the ByteCode object.
- */
-
#ifdef TCL_COMPILE_DEBUG
- TclVerifyLocalLiteralTable(&compEnv);
+ TclVerifyLocalLiteralTable(&compEnv);
#endif /*TCL_COMPILE_DEBUG*/
- TclInitByteCodeObj(objPtr, &compEnv);
+ TclInitByteCodeObj(objPtr, &compEnv);
#ifdef TCL_COMPILE_DEBUG
- if (tclTraceCompile >= 2) {
- TclPrintByteCodeObj(interp, objPtr);
- }
-#endif /* TCL_COMPILE_DEBUG */
+ if (tclTraceCompile >= 2) {
+ TclPrintByteCodeObj(interp, objPtr);
+ fflush(stdout);
}
-
+#endif /* TCL_COMPILE_DEBUG */
+
if (result != TCL_OK) {
/*
- * Compilation errors.
+ * Handle any error from the hookProc
*/
entryPtr = compEnv.literalArrayPtr;
@@ -474,14 +584,6 @@ TclSetByteCodeFromAny(interp, objPtr, hookProc, clientData)
}
}
-
- /*
- * Free storage allocated during compilation.
- */
-
- if (localTablePtr->buckets != localTablePtr->staticBuckets) {
- ckfree((char *) localTablePtr->buckets);
- }
TclFreeCompileEnv(&compEnv);
return result;
}
@@ -502,24 +604,24 @@ TclSetByteCodeFromAny(interp, objPtr, hookProc, clientData)
*
* Side effects:
* Frees the old internal representation. If no error occurs, then the
- * compiled code is stored as "objPtr"s bytecode representation.
- * Also, if debugging, initializes the "tcl_traceCompile" Tcl variable
- * used to trace compilations.
+ * compiled code is stored as "objPtr"s bytecode representation. Also, if
+ * debugging, initializes the "tcl_traceCompile" Tcl variable used to
+ * trace compilations.
*
*----------------------------------------------------------------------
*/
static int
-SetByteCodeFromAny(interp, objPtr)
- Tcl_Interp *interp; /* The interpreter for which the code is
- * being compiled. Must not be NULL. */
- Tcl_Obj *objPtr; /* The object to make a ByteCode object. */
+SetByteCodeFromAny(
+ Tcl_Interp *interp, /* The interpreter for which the code is being
+ * compiled. Must not be NULL. */
+ Tcl_Obj *objPtr) /* The object to make a ByteCode object. */
{
if (interp == NULL) {
return TCL_ERROR;
}
- return TclSetByteCodeFromAny(interp, objPtr,
- (CompileHookProc *) NULL, (ClientData) NULL);
+ (void) TclSetByteCodeFromAny(interp, objPtr, NULL, (ClientData) NULL);
+ return TCL_OK;
}
/*
@@ -527,8 +629,8 @@ SetByteCodeFromAny(interp, objPtr)
*
* DupByteCodeInternalRep --
*
- * Part of the bytecode Tcl object type implementation. However, it
- * does not copy the internal representation of a bytecode Tcl_Obj, but
+ * Part of the bytecode Tcl object type implementation. However, it does
+ * not copy the internal representation of a bytecode Tcl_Obj, but
* instead leaves the new object untyped (with a NULL type pointer).
* Code will be compiled for the new object only if necessary.
*
@@ -542,9 +644,9 @@ SetByteCodeFromAny(interp, objPtr)
*/
static void
-DupByteCodeInternalRep(srcPtr, copyPtr)
- Tcl_Obj *srcPtr; /* Object with internal rep to copy. */
- Tcl_Obj *copyPtr; /* Object with internal rep to set. */
+DupByteCodeInternalRep(
+ Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
+ Tcl_Obj *copyPtr) /* Object with internal rep to set. */
{
return;
}
@@ -554,28 +656,27 @@ DupByteCodeInternalRep(srcPtr, copyPtr)
*
* FreeByteCodeInternalRep --
*
- * Part of the bytecode Tcl object type implementation. Frees the
- * storage associated with a bytecode object's internal representation
- * unless its code is actively being executed.
+ * Part of the bytecode Tcl object type implementation. Frees the storage
+ * associated with a bytecode object's internal representation unless its
+ * code is actively being executed.
*
* Results:
* None.
*
* Side effects:
- * The bytecode object's internal rep is marked invalid and its
- * code gets freed unless the code is actively being executed.
- * In that case the cleanup is delayed until the last execution
- * of the code completes.
+ * The bytecode object's internal rep is marked invalid and its code gets
+ * freed unless the code is actively being executed. In that case the
+ * cleanup is delayed until the last execution of the code completes.
*
*----------------------------------------------------------------------
*/
static void
-FreeByteCodeInternalRep(objPtr)
- register Tcl_Obj *objPtr; /* Object whose internal rep to free. */
+FreeByteCodeInternalRep(
+ register Tcl_Obj *objPtr) /* Object whose internal rep to free. */
{
- register ByteCode *codePtr =
- (ByteCode *) objPtr->internalRep.otherValuePtr;
+ register ByteCode *codePtr = (ByteCode *)
+ objPtr->internalRep.otherValuePtr;
codePtr->refCount--;
if (codePtr->refCount <= 0) {
@@ -598,24 +699,22 @@ FreeByteCodeInternalRep(objPtr)
* None.
*
* Side effects:
- * Frees objPtr's bytecode internal representation and sets its type
- * and objPtr->internalRep.otherValuePtr NULL. Also releases its
- * literals and frees its auxiliary data items.
+ * Frees objPtr's bytecode internal representation and sets its type and
+ * objPtr->internalRep.otherValuePtr NULL. Also releases its literals and
+ * frees its auxiliary data items.
*
*----------------------------------------------------------------------
*/
void
-TclCleanupByteCode(codePtr)
- register ByteCode *codePtr; /* Points to the ByteCode to free. */
+TclCleanupByteCode(
+ register ByteCode *codePtr) /* Points to the ByteCode to free. */
{
Tcl_Interp *interp = (Tcl_Interp *) *codePtr->interpHandle;
-#ifdef TCL_TIP280
- Interp* iPtr = (Interp*) interp;
-#endif
+ Interp *iPtr = (Interp *) interp;
int numLitObjects = codePtr->numLitObjects;
int numAuxDataItems = codePtr->numAuxDataItems;
- register Tcl_Obj **objArrayPtr;
+ register Tcl_Obj **objArrayPtr, *objPtr;
register AuxData *auxDataPtr;
int i;
#ifdef TCL_COMPILE_STATS
@@ -631,13 +730,13 @@ TclCleanupByteCode(codePtr)
statsPtr->currentSrcBytes -= (double) codePtr->numSrcBytes;
statsPtr->currentByteCodeBytes -= (double) codePtr->structureSize;
- statsPtr->currentInstBytes -= (double) codePtr->numCodeBytes;
- statsPtr->currentLitBytes -=
- (double) (codePtr->numLitObjects * sizeof(Tcl_Obj *));
- statsPtr->currentExceptBytes -=
- (double) (codePtr->numExceptRanges * sizeof(ExceptionRange));
- statsPtr->currentAuxBytes -=
- (double) (codePtr->numAuxDataItems * sizeof(AuxData));
+ statsPtr->currentInstBytes -= (double) codePtr->numCodeBytes;
+ statsPtr->currentLitBytes -= (double)
+ codePtr->numLitObjects * sizeof(Tcl_Obj *);
+ statsPtr->currentExceptBytes -= (double)
+ codePtr->numExceptRanges * sizeof(ExceptionRange);
+ statsPtr->currentAuxBytes -= (double)
+ codePtr->numAuxDataItems * sizeof(AuxData);
statsPtr->currentCmdMapBytes -= (double) codePtr->numCmdLocBytes;
Tcl_GetTime(&destroyTime);
@@ -645,9 +744,9 @@ TclCleanupByteCode(codePtr)
if (lifetimeSec > 2000) { /* avoid overflow */
lifetimeSec = 2000;
}
- lifetimeMicroSec =
- 1000000*lifetimeSec + (destroyTime.usec - codePtr->createTime.usec);
-
+ lifetimeMicroSec = 1000000 * lifetimeSec +
+ (destroyTime.usec - codePtr->createTime.usec);
+
log2 = TclLog2(lifetimeMicroSec);
if (log2 > 31) {
log2 = 31;
@@ -657,21 +756,28 @@ TclCleanupByteCode(codePtr)
#endif /* TCL_COMPILE_STATS */
/*
- * A single heap object holds the ByteCode structure and its code,
- * object, command location, and auxiliary data arrays. This means we
- * only need to 1) decrement the ref counts of the LiteralEntry's in
- * its literal array, 2) call the free procs for the auxiliary data
- * items, and 3) free the ByteCode structure's heap object.
+ * A single heap object holds the ByteCode structure and its code, object,
+ * command location, and auxiliary data arrays. This means we only need to
+ * 1) decrement the ref counts of the LiteralEntry's in its literal array,
+ * 2) call the free procs for the auxiliary data items, 3) free the
+ * localCache if it is unused, and finally 4) free the ByteCode
+ * structure's heap object.
+ *
+ * The case for TCL_BYTECODE_PRECOMPILED (precompiled ByteCodes, like
+ * those generated from tbcload) is special, as they doesn't make use of
+ * the global literal table. They instead maintain private references to
+ * their literals which must be decremented.
*
- * The case for TCL_BYTECODE_PRECOMPILED (precompiled ByteCodes,
- * like those generated from tbcload) is special, as they doesn't
- * make use of the global literal table. They instead maintain
- * private references to their literals which must be decremented.
+ * In order to insure a proper and efficient cleanup of the literal array
+ * when it contains non-shared literals [Bug 983660], we also distinguish
+ * the case of an interpreter being deleted (signaled by interp == NULL).
+ * Also, as the interp deletion will remove the global literal table
+ * anyway, we avoid the extra cost of updating it for each literal being
+ * released.
*/
- if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
- register Tcl_Obj *objPtr;
-
+ if ((codePtr->flags & TCL_BYTECODE_PRECOMPILED) || (interp == NULL)) {
+
objArrayPtr = codePtr->objArrayPtr;
for (i = 0; i < numLitObjects; i++) {
objPtr = *objArrayPtr;
@@ -681,36 +787,30 @@ TclCleanupByteCode(codePtr)
objArrayPtr++;
}
codePtr->numLitObjects = 0;
- } else if (interp != NULL) {
- /*
- * If the interp has already been freed, then Tcl will have already
- * forcefully released all the literals used by ByteCodes compiled
- * with respect to that interp.
- */
-
+ } else {
objArrayPtr = codePtr->objArrayPtr;
for (i = 0; i < numLitObjects; i++) {
/*
* TclReleaseLiteral sets a ByteCode's object array entry NULL to
* indicate that it has already freed the literal.
*/
-
- if (*objArrayPtr != NULL) {
- TclReleaseLiteral(interp, *objArrayPtr);
+
+ objPtr = *objArrayPtr;
+ if (objPtr != NULL) {
+ TclReleaseLiteral(interp, objPtr);
}
objArrayPtr++;
}
}
-
+
auxDataPtr = codePtr->auxDataArrayPtr;
for (i = 0; i < numAuxDataItems; i++) {
if (auxDataPtr->type->freeProc != NULL) {
- (*auxDataPtr->type->freeProc)(auxDataPtr->clientData);
+ (auxDataPtr->type->freeProc)(auxDataPtr->clientData);
}
auxDataPtr++;
}
-#ifdef TCL_TIP280
/*
* TIP #280. Release the location data associated with this byte code
* structure, if any. NOTE: The interp we belong to may be gone already,
@@ -720,43 +820,37 @@ TclCleanupByteCode(codePtr)
*/
if (iPtr) {
- Tcl_HashEntry* hePtr = Tcl_FindHashEntry (iPtr->lineBCPtr, (char *) codePtr);
+ Tcl_HashEntry *hePtr = Tcl_FindHashEntry(iPtr->lineBCPtr,
+ (char *) codePtr);
if (hePtr) {
- ExtCmdLoc* eclPtr = (ExtCmdLoc*) Tcl_GetHashValue (hePtr);
+ ExtCmdLoc *eclPtr = Tcl_GetHashValue(hePtr);
+ int i;
- ReleaseCmdWordData (eclPtr);
- Tcl_DeleteHashEntry (hePtr);
- }
- }
-#endif
+ if (eclPtr->type == TCL_LOCATION_SOURCE) {
+ Tcl_DecrRefCount(eclPtr->path);
+ }
+ for (i=0 ; i<eclPtr->nuloc ; i++) {
+ ckfree((char *) eclPtr->loc[i].line);
+ }
- TclHandleRelease(codePtr->interpHandle);
- ckfree((char *) codePtr);
-}
+ if (eclPtr->loc != NULL) {
+ ckfree((char *) eclPtr->loc);
+ }
-#ifdef TCL_TIP280
-static void
-ReleaseCmdWordData (eclPtr)
- ExtCmdLoc* eclPtr;
-{
- int i;
+ Tcl_DeleteHashTable (&eclPtr->litInfo);
- if (eclPtr->type == TCL_LOCATION_SOURCE) {
- Tcl_DecrRefCount (eclPtr->path);
- }
- for (i=0; i < eclPtr->nuloc; i++) {
- ckfree ((char*) eclPtr->loc[i].line);
+ ckfree((char *) eclPtr);
+ Tcl_DeleteHashEntry(hePtr);
+ }
}
- if (eclPtr->loc != NULL) {
- ckfree ((char*) eclPtr->loc);
+ if (codePtr->localCachePtr && (--codePtr->localCachePtr->refCount == 0)) {
+ TclFreeLocalCache(interp, codePtr->localCachePtr);
}
- Tcl_DeleteHashTable (&eclPtr->litInfo);
-
- ckfree ((char*) eclPtr);
+ TclHandleRelease(codePtr->interpHandle);
+ ckfree((char *) codePtr);
}
-#endif
/*
*----------------------------------------------------------------------
@@ -776,27 +870,21 @@ ReleaseCmdWordData (eclPtr)
*/
void
-#ifndef TCL_TIP280
-TclInitCompileEnv(interp, envPtr, string, numBytes)
-#else
-TclInitCompileEnv(interp, envPtr, string, numBytes, invoker, word)
-#endif
- Tcl_Interp *interp; /* The interpreter for which a CompileEnv
- * structure is initialized. */
- register CompileEnv *envPtr; /* Points to the CompileEnv structure to
- * initialize. */
- char *string; /* The source string to be compiled. */
- int numBytes; /* Number of bytes in source string. */
-#ifdef TCL_TIP280
- CONST CmdFrame* invoker; /* Location context invoking the bcc */
- int word; /* Index of the word in that context
- * getting compiled */
-#endif
+TclInitCompileEnv(
+ Tcl_Interp *interp, /* The interpreter for which a CompileEnv
+ * structure is initialized. */
+ register CompileEnv *envPtr,/* Points to the CompileEnv structure to
+ * initialize. */
+ const char *stringPtr, /* The source string to be compiled. */
+ int numBytes, /* Number of bytes in source string. */
+ const CmdFrame *invoker, /* Location context invoking the bcc */
+ int word) /* Index of the word in that context getting
+ * compiled */
{
Interp *iPtr = (Interp *) interp;
-
+
envPtr->iPtr = iPtr;
- envPtr->source = string;
+ envPtr->source = stringPtr;
envPtr->numSrcBytes = numBytes;
envPtr->procPtr = iPtr->compiledProcPtr;
iPtr->compiledProcPtr = NULL;
@@ -816,17 +904,17 @@ TclInitCompileEnv(interp, envPtr, string, numBytes, invoker, word)
envPtr->literalArrayNext = 0;
envPtr->literalArrayEnd = COMPILEENV_INIT_NUM_OBJECTS;
envPtr->mallocedLiteralArray = 0;
-
+
envPtr->exceptArrayPtr = envPtr->staticExceptArraySpace;
envPtr->exceptArrayNext = 0;
envPtr->exceptArrayEnd = COMPILEENV_INIT_EXCEPT_RANGES;
envPtr->mallocedExceptArray = 0;
-
+
envPtr->cmdMapPtr = envPtr->staticCmdMapSpace;
envPtr->cmdMapEnd = COMPILEENV_INIT_CMD_MAP_SIZE;
envPtr->mallocedCmdMap = 0;
+ envPtr->atCmdStart = 1;
-#ifdef TCL_TIP280
/*
* TIP #280: Set up the extended command location information, based on
* the context invoking the byte code compiler. This structure is used to
@@ -836,11 +924,11 @@ TclInitCompileEnv(interp, envPtr, string, numBytes, invoker, word)
* non-compiling evaluator
*/
- envPtr->extCmdMapPtr = (ExtCmdLoc*) ckalloc (sizeof (ExtCmdLoc));
- envPtr->extCmdMapPtr->loc = NULL;
- envPtr->extCmdMapPtr->nloc = 0;
+ envPtr->extCmdMapPtr = (ExtCmdLoc *) ckalloc(sizeof(ExtCmdLoc));
+ envPtr->extCmdMapPtr->loc = NULL;
+ envPtr->extCmdMapPtr->nloc = 0;
envPtr->extCmdMapPtr->nuloc = 0;
- envPtr->extCmdMapPtr->path = NULL;
+ envPtr->extCmdMapPtr->path = NULL;
Tcl_InitHashTable(&envPtr->extCmdMapPtr->litInfo, TCL_ONE_WORD_KEYS);
if (invoker == NULL ||
@@ -850,61 +938,75 @@ TclInitCompileEnv(interp, envPtr, string, numBytes, invoker, word)
* dynamic context.
*/
- envPtr->line = 1;
- envPtr->extCmdMapPtr->type = (envPtr->procPtr
- ? TCL_LOCATION_PROC
- : TCL_LOCATION_BC);
+ envPtr->line = 1;
+ envPtr->extCmdMapPtr->type =
+ (envPtr->procPtr ? TCL_LOCATION_PROC : TCL_LOCATION_BC);
} else {
- /* Initialize the compiler using the context, making counting absolute
- * to that context. Note that the context can be byte code
- * execution. In that case we have to fill out the missing pieces
- * (line, path, ...). Which may make change the type as well.
+ /*
+ * Initialize the compiler using the context, making counting absolute
+ * to that context. Note that the context can be byte code execution.
+ * In that case we have to fill out the missing pieces (line, path,
+ * ...) which may make change the type as well.
*/
- CmdFrame ctx = *invoker;
- int pc = 0;
+ CmdFrame* ctxPtr = (CmdFrame *) TclStackAlloc(interp, sizeof(CmdFrame));
+ int pc = 0;
+
+ *ctxPtr = *invoker;
if (invoker->type == TCL_LOCATION_BC) {
- /* Note: Type BC => ctx.data.eval.path is not used.
+ /*
+ * Note: Type BC => ctx.data.eval.path is not used.
* ctx.data.tebc.codePtr is used instead.
- */
- TclGetSrcInfoForPc (&ctx);
+ */
+
+ TclGetSrcInfoForPc(ctxPtr);
pc = 1;
}
- if ((ctx.nline <= word) || (ctx.line[word] < 0)) {
- /* Word is not a literal, relative counting */
+ if ((ctxPtr->nline <= word) || (ctxPtr->line[word] < 0)) {
+ /*
+ * Word is not a literal, relative counting.
+ */
- envPtr->line = 1;
- envPtr->extCmdMapPtr->type = (envPtr->procPtr
- ? TCL_LOCATION_PROC
- : TCL_LOCATION_BC);
+ envPtr->line = 1;
+ envPtr->extCmdMapPtr->type =
+ (envPtr->procPtr ? TCL_LOCATION_PROC : TCL_LOCATION_BC);
- if (pc && (ctx.type == TCL_LOCATION_SOURCE)) {
+ if (pc && (ctxPtr->type == TCL_LOCATION_SOURCE)) {
/*
* The reference made by 'TclGetSrcInfoForPc' is dead.
*/
- Tcl_DecrRefCount(ctx.data.eval.path);
+ Tcl_DecrRefCount(ctxPtr->data.eval.path);
}
} else {
- envPtr->line = ctx.line [word];
- envPtr->extCmdMapPtr->type = ctx.type;
- envPtr->extCmdMapPtr->path = ctx.data.eval.path;
+ envPtr->line = ctxPtr->line[word];
+ envPtr->extCmdMapPtr->type = ctxPtr->type;
+
+ if (ctxPtr->type == TCL_LOCATION_SOURCE) {
+ envPtr->extCmdMapPtr->path = ctxPtr->data.eval.path;
- if (ctx.type == TCL_LOCATION_SOURCE) {
if (pc) {
- /* The reference 'TclGetSrcInfoForPc' made is transfered */
- ctx.data.eval.path = NULL;
+ /*
+ * The reference 'TclGetSrcInfoForPc' made is transfered.
+ */
+
+ ctxPtr->data.eval.path = NULL;
} else {
- /* We have a new reference here */
- Tcl_IncrRefCount (ctx.data.eval.path);
+ /*
+ * We have a new reference here.
+ */
+
+ Tcl_IncrRefCount(ctxPtr->data.eval.path);
}
}
}
- /* ctx going out of scope */
+ TclStackFree(interp, ctxPtr);
}
+ envPtr->extCmdMapPtr->start = envPtr->line;
+
/*
* Initialize the data about invisible continuation lines as empty,
* i.e. not used. The caller (TclSetByteCodeFromAny) will set this up, if
@@ -913,7 +1015,6 @@ TclInitCompileEnv(interp, envPtr, string, numBytes, invoker, word)
envPtr->clLoc = NULL;
envPtr->clNext = NULL;
-#endif
envPtr->auxDataArrayPtr = envPtr->staticAuxDataArraySpace;
envPtr->auxDataArrayNext = 0;
@@ -931,22 +1032,26 @@ TclInitCompileEnv(interp, envPtr, string, numBytes, invoker, word)
*
* Results:
* None.
- *
+ *
* Side effects:
- * Allocated storage in the CompileEnv structure is freed. Note that
- * its local literal table is not deleted and its literal objects are
- * not released. In addition, storage referenced by its auxiliary data
- * items is not freed. This is done so that, when compilation is
- * successful, "ownership" of these objects and aux data items is
- * handed over to the corresponding ByteCode structure.
+ * Allocated storage in the CompileEnv structure is freed. Note that its
+ * local literal table is not deleted and its literal objects are not
+ * released. In addition, storage referenced by its auxiliary data items
+ * is not freed. This is done so that, when compilation is successful,
+ * "ownership" of these objects and aux data items is handed over to the
+ * corresponding ByteCode structure.
*
*----------------------------------------------------------------------
*/
void
-TclFreeCompileEnv(envPtr)
- register CompileEnv *envPtr; /* Points to the CompileEnv structure. */
+TclFreeCompileEnv(
+ register CompileEnv *envPtr)/* Points to the CompileEnv structure. */
{
+ if (envPtr->localLitTable.buckets != envPtr->localLitTable.staticBuckets) {
+ ckfree((char *) envPtr->localLitTable.buckets);
+ envPtr->localLitTable.buckets = envPtr->localLitTable.staticBuckets;
+ }
if (envPtr->mallocedCodeArray) {
ckfree((char *) envPtr->codeStart);
}
@@ -962,7 +1067,10 @@ TclFreeCompileEnv(envPtr)
if (envPtr->mallocedAuxDataArray) {
ckfree((char *) envPtr->auxDataArrayPtr);
}
-#ifdef TCL_TIP280
+ if (envPtr->extCmdMapPtr) {
+ ckfree((char *) envPtr->extCmdMapPtr);
+ }
+
/*
* If we used data about invisible continuation lines, then now is the
* time to release on our hold on it. The lock was set in function
@@ -972,13 +1080,8 @@ TclFreeCompileEnv(envPtr)
if (envPtr->clLoc) {
Tcl_Release (envPtr->clLoc);
}
- if (envPtr->extCmdMapPtr) {
- ReleaseCmdWordData (envPtr->extCmdMapPtr);
- }
-#endif
}
-#ifdef TCL_TIP280
/*
*----------------------------------------------------------------------
*
@@ -996,35 +1099,67 @@ TclFreeCompileEnv(envPtr)
* it is worthwhile to compile at all.
*
* Side effects:
- * None.
+ * When returning true, appends the known value of the word to the
+ * unshared Tcl_Obj (*valuePtr), unless valuePtr is NULL.
*
- * TIP #280
*----------------------------------------------------------------------
*/
int
-TclWordKnownAtCompileTime (tokenPtr)
- Tcl_Token* tokenPtr;
+TclWordKnownAtCompileTime(
+ Tcl_Token *tokenPtr, /* Points to Tcl_Token we should check */
+ Tcl_Obj *valuePtr) /* If not NULL, points to an unshared Tcl_Obj
+ * to which we should append the known value
+ * of the word. */
{
- int i;
- Tcl_Token* sub;
+ int numComponents = tokenPtr->numComponents;
+ Tcl_Obj *tempPtr = NULL;
- if (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {return 1;};
- if (tokenPtr->type != TCL_TOKEN_WORD) {return 0;};
+ if (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
+ if (valuePtr != NULL) {
+ Tcl_AppendToObj(valuePtr, tokenPtr[1].start, tokenPtr[1].size);
+ }
+ return 1;
+ }
+ if (tokenPtr->type != TCL_TOKEN_WORD) {
+ return 0;
+ }
+ tokenPtr++;
+ if (valuePtr != NULL) {
+ tempPtr = Tcl_NewObj();
+ Tcl_IncrRefCount(tempPtr);
+ }
+ while (numComponents--) {
+ switch (tokenPtr->type) {
+ case TCL_TOKEN_TEXT:
+ if (tempPtr != NULL) {
+ Tcl_AppendToObj(tempPtr, tokenPtr->start, tokenPtr->size);
+ }
+ break;
- /* Check the sub tokens of the word. It is a literal if we find
- * only BS and TEXT tokens */
+ case TCL_TOKEN_BS:
+ if (tempPtr != NULL) {
+ char utfBuf[TCL_UTF_MAX];
+ int length = TclParseBackslash(tokenPtr->start,
+ tokenPtr->size, NULL, utfBuf);
+ Tcl_AppendToObj(tempPtr, utfBuf, length);
+ }
+ break;
- for (i=0, sub = tokenPtr + 1;
- i < tokenPtr->numComponents;
- i++, sub ++) {
- if (sub->type == TCL_TOKEN_TEXT) continue;
- if (sub->type == TCL_TOKEN_BS) continue;
- return 0;
+ default:
+ if (tempPtr != NULL) {
+ Tcl_DecrRefCount(tempPtr);
+ }
+ return 0;
+ }
+ tokenPtr++;
+ }
+ if (valuePtr != NULL) {
+ Tcl_AppendObjToObj(valuePtr, tempPtr);
+ Tcl_DecrRefCount(tempPtr);
}
return 1;
}
-#endif
/*
*----------------------------------------------------------------------
@@ -1038,55 +1173,44 @@ TclWordKnownAtCompileTime (tokenPtr)
* on failure. If TCL_ERROR is returned, then the interpreter's result
* contains an error message.
*
- * interp->termOffset is set to the offset of the character in the
- * script just after the last one successfully processed; this will be
- * the offset of the ']' if (flags & TCL_BRACKET_TERM).
- *
* Side effects:
* Adds instructions to envPtr to evaluate the script at runtime.
*
*----------------------------------------------------------------------
*/
-int
-TclCompileScript(interp, script, numBytes, nested, envPtr)
- Tcl_Interp *interp; /* Used for error and status reporting.
- * Also serves as context for finding and
- * compiling commands. May not be NULL. */
- CONST char *script; /* The source script to compile. */
- int numBytes; /* Number of bytes in script. If < 0, the
+void
+TclCompileScript(
+ Tcl_Interp *interp, /* Used for error and status reporting. Also
+ * serves as context for finding and compiling
+ * commands. May not be NULL. */
+ const char *script, /* The source script to compile. */
+ int numBytes, /* Number of bytes in script. If < 0, the
* script consists of all bytes up to the
* first null character. */
- int nested; /* Non-zero means this is a nested command:
- * close bracket ']' should be considered a
- * command terminator. If zero, close
- * bracket has no special meaning. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
{
Interp *iPtr = (Interp *) interp;
- Tcl_Parse parse;
int lastTopLevelCmdIndex = -1;
/* Index of most recent toplevel command in
- * the command location table. Initialized
- * to avoid compiler warning. */
+ * the command location table. Initialized to
+ * avoid compiler warning. */
int startCodeOffset = -1; /* Offset of first byte of current command's
- * code. Init. to avoid compiler warning. */
+ * code. Init. to avoid compiler warning. */
unsigned char *entryCodeNext = envPtr->codeNext;
- CONST char *p, *next;
+ const char *p, *next;
Namespace *cmdNsPtr;
Command *cmdPtr;
Tcl_Token *tokenPtr;
- int bytesLeft, isFirstCmd, gotParse, wordIdx, currCmdIndex;
- int commandLength, objIndex, code;
+ int bytesLeft, isFirstCmd, wordIdx, currCmdIndex;
+ int commandLength, objIndex;
Tcl_DString ds;
-
-#ifdef TCL_TIP280
/* TIP #280 */
- ExtCmdLoc* eclPtr = envPtr->extCmdMapPtr;
- int* wlines = NULL;
- int wlineat, cmdLine;
+ ExtCmdLoc *eclPtr = envPtr->extCmdMapPtr;
+ int *wlines, wlineat, cmdLine;
int* clNext;
-#endif
+ Tcl_Parse *parsePtr = (Tcl_Parse *)
+ TclStackAlloc(interp, sizeof(Tcl_Parse));
Tcl_DStringInit(&ds);
@@ -1096,70 +1220,39 @@ TclCompileScript(interp, script, numBytes, nested, envPtr)
Tcl_ResetResult(interp);
isFirstCmd = 1;
+ if (envPtr->procPtr != NULL) {
+ cmdNsPtr = envPtr->procPtr->cmdPtr->nsPtr;
+ } else {
+ cmdNsPtr = NULL; /* use current NS */
+ }
+
/*
- * Each iteration through the following loop compiles the next
- * command from the script.
+ * Each iteration through the following loop compiles the next command
+ * from the script.
*/
p = script;
bytesLeft = numBytes;
- gotParse = 0;
-#ifdef TCL_TIP280
cmdLine = envPtr->line;
- clNext = envPtr->clNext;
-#endif
-
+ clNext = envPtr->clNext;
do {
- if (Tcl_ParseCommand(interp, p, bytesLeft, nested, &parse) != TCL_OK) {
- code = TCL_ERROR;
- goto error;
- }
- gotParse = 1;
- if (nested) {
+ if (Tcl_ParseCommand(interp, p, bytesLeft, 0, parsePtr) != TCL_OK) {
/*
- * This is an unusual situation where the caller has passed us
- * a non-zero value for "nested". How unusual? Well, this
- * procedure, TclCompileScript, is internal to Tcl, so all
- * callers should be within Tcl itself. All but one of those
- * callers explicitly pass in (nested = 0). The exceptional
- * caller is TclSetByteCodeFromAny, which will pass in
- * (nested = 1) if and only if the flag TCL_BRACKET_TERM
- * is set in the evalFlags field of interp.
- *
- * It appears that the TCL_BRACKET_TERM flag is only ever set
- * by Tcl_SubstObj, and it immediately calls Tcl_EvalEx
- * which clears the flag before passing the interp along.
- * So, I don't think this procedure, TclCompileScript, is
- * **ever** called with (nested != 0).
- * (The testsuite indeed doesn't exercise this code. MS)
- *
- * This means that the branches in this procedure that are
- * only active when (nested != 0) are probably never exercised.
- * This means that any bugs in them go unnoticed, and any bug
- * fixes in them have a semi-theoretical nature.
- *
- * All that said, the spec for this procedure says it should
- * handle the (nested != 0) case, so here's an attempt to fix
- * bugs (Tcl Bug 681841) in that case. Just in case some
- * callers eventually come along and expect it to work...
+ * Compile bytecodes to report the parse error at runtime.
*/
- if (parse.term == (script + numBytes)) {
- /*
- * The (nested != 0) case is meant to indicate that the
- * caller found an open bracket ([) and asked us to
- * parse and compile Tcl commands up to the matching
- * close bracket (]). We have to detect and handle
- * the case where the close bracket is missing.
- */
-
- Tcl_SetObjResult(interp,
- Tcl_NewStringObj("missing close-bracket", -1));
- code = TCL_ERROR;
- goto error;
- }
+ Tcl_LogCommandInfo(interp, script, parsePtr->commandStart,
+ /* Drop the command terminator (";","]") if appropriate */
+ (parsePtr->term ==
+ parsePtr->commandStart + parsePtr->commandSize - 1)?
+ parsePtr->commandSize - 1 : parsePtr->commandSize);
+ TclCompileSyntaxError(interp, envPtr);
+ break;
}
- if (parse.numWords > 0) {
+ if (parsePtr->numWords > 0) {
+ int expand = 0; /* Set if there are dynamic expansions to
+ * handle */
+
/*
* If not the first command, pop the previous command's result
* and, if we're compiling a top level command, update the last
@@ -1168,195 +1261,294 @@ TclCompileScript(interp, script, numBytes, nested, envPtr)
if (!isFirstCmd) {
TclEmitOpcode(INST_POP, envPtr);
- if (!nested) {
- envPtr->cmdMapPtr[lastTopLevelCmdIndex].numCodeBytes =
- (envPtr->codeNext - envPtr->codeStart)
- - startCodeOffset;
- }
+ envPtr->cmdMapPtr[lastTopLevelCmdIndex].numCodeBytes =
+ (envPtr->codeNext - envPtr->codeStart)
+ - startCodeOffset;
}
/*
* Determine the actual length of the command.
*/
- commandLength = parse.commandSize;
- if (parse.term == parse.commandStart + commandLength - 1) {
+ commandLength = parsePtr->commandSize;
+ if (parsePtr->term == parsePtr->commandStart + commandLength - 1) {
/*
- * The command terminator character (such as ; or ]) is
- * the last character in the parsed command. Reduce the
- * length by one so that the trace message doesn't include
- * the terminator character.
+ * The command terminator character (such as ; or ]) is the
+ * last character in the parsed command. Reduce the length by
+ * one so that the trace message doesn't include the
+ * terminator character.
*/
-
+
commandLength -= 1;
}
#ifdef TCL_COMPILE_DEBUG
/*
- * If tracing, print a line for each top level command compiled.
- */
+ * If tracing, print a line for each top level command compiled.
+ */
- if ((tclTraceCompile >= 1)
- && !nested && (envPtr->procPtr == NULL)) {
+ if ((tclTraceCompile >= 1) && (envPtr->procPtr == NULL)) {
fprintf(stdout, " Compiling: ");
- TclPrintSource(stdout, parse.commandStart,
+ TclPrintSource(stdout, parsePtr->commandStart,
TclMin(commandLength, 55));
fprintf(stdout, "\n");
}
#endif
+
/*
- * Each iteration of the following loop compiles one word
- * from the command.
+ * Check whether expansion has been requested for any of the
+ * words.
*/
-
+
+ for (wordIdx = 0, tokenPtr = parsePtr->tokenPtr;
+ wordIdx < parsePtr->numWords;
+ wordIdx++, tokenPtr += (tokenPtr->numComponents + 1)) {
+ if (tokenPtr->type == TCL_TOKEN_EXPAND_WORD) {
+ expand = 1;
+ break;
+ }
+ }
+
envPtr->numCommands++;
currCmdIndex = (envPtr->numCommands - 1);
- if (!nested) {
- lastTopLevelCmdIndex = currCmdIndex;
- }
+ lastTopLevelCmdIndex = currCmdIndex;
startCodeOffset = (envPtr->codeNext - envPtr->codeStart);
EnterCmdStartData(envPtr, currCmdIndex,
- (parse.commandStart - envPtr->source), startCodeOffset);
+ parsePtr->commandStart - envPtr->source, startCodeOffset);
-#ifdef TCL_TIP280
- /* TIP #280. Scan the words and compute the extended location
+ /*
+ * Should only start issuing instructions after the "command has
+ * started" so that the command range is correct in the bytecode.
+ */
+
+ if (expand) {
+ TclEmitOpcode(INST_EXPAND_START, envPtr);
+ }
+
+ /*
+ * TIP #280. Scan the words and compute the extended location
* information. The map first contain full per-word line
* information for use by the compiler. This is later replaced by
* a reduced form which signals non-literal words, stored in
* 'wlines'.
*/
- TclAdvanceLines (&cmdLine, p, parse.commandStart);
+ TclAdvanceLines(&cmdLine, p, parsePtr->commandStart);
TclAdvanceContinuations (&cmdLine, &clNext,
- parse.commandStart - envPtr->source);
- EnterCmdWordData (eclPtr, (parse.commandStart - envPtr->source),
- parse.tokenPtr, parse.commandStart,
- parse.commandSize, parse.numWords,
- cmdLine, clNext, &wlines, envPtr);
+ parsePtr->commandStart - envPtr->source);
+ EnterCmdWordData(eclPtr, parsePtr->commandStart - envPtr->source,
+ parsePtr->tokenPtr, parsePtr->commandStart,
+ parsePtr->commandSize, parsePtr->numWords, cmdLine,
+ clNext, &wlines, envPtr);
wlineat = eclPtr->nuloc - 1;
-#endif
- for (wordIdx = 0, tokenPtr = parse.tokenPtr;
- wordIdx < parse.numWords;
- wordIdx++, tokenPtr += (tokenPtr->numComponents + 1)) {
-#ifdef TCL_TIP280
- envPtr->line = eclPtr->loc [wlineat].line [wordIdx];
+ /*
+ * Each iteration of the following loop compiles one word from the
+ * command.
+ */
+
+ for (wordIdx = 0, tokenPtr = parsePtr->tokenPtr;
+ wordIdx < parsePtr->numWords; wordIdx++,
+ tokenPtr += (tokenPtr->numComponents + 1)) {
+
+ envPtr->line = eclPtr->loc[wlineat].line[wordIdx];
envPtr->clNext = eclPtr->loc [wlineat].next [wordIdx];
-#endif
- if (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
+
+ if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
/*
- * If this is the first word and the command has a
- * compile procedure, let it compile the command.
+ * The word is not a simple string of characters.
*/
- if (wordIdx == 0) {
- if (envPtr->procPtr != NULL) {
- cmdNsPtr = envPtr->procPtr->cmdPtr->nsPtr;
- } else {
- cmdNsPtr = NULL; /* use current NS */
- }
+ TclCompileTokens(interp, tokenPtr+1,
+ tokenPtr->numComponents, envPtr);
+ if (tokenPtr->type == TCL_TOKEN_EXPAND_WORD) {
+ TclEmitInstInt4(INST_EXPAND_STKTOP,
+ envPtr->currStackDepth, envPtr);
+ }
+ continue;
+ }
+
+ /*
+ * This is a simple string of literal characters (i.e. we know
+ * it absolutely and can use it directly). If this is the
+ * first word and the command has a compile procedure, let it
+ * compile the command.
+ */
+
+ if ((wordIdx == 0) && !expand) {
+ /*
+ * We copy the string before trying to find the command by
+ * name. We used to modify the string in place, but this
+ * is not safe because the name resolution handlers could
+ * have side effects that rely on the unmodified string.
+ */
+
+ Tcl_DStringSetLength(&ds, 0);
+ Tcl_DStringAppend(&ds, tokenPtr[1].start,tokenPtr[1].size);
+
+ cmdPtr = (Command *) Tcl_FindCommand(interp,
+ Tcl_DStringValue(&ds),
+ (Tcl_Namespace *) cmdNsPtr, /*flags*/ 0);
+
+ if ((cmdPtr != NULL)
+ && (cmdPtr->compileProc != NULL)
+ && !(cmdPtr->flags & CMD_HAS_EXEC_TRACES)
+ && !(iPtr->flags & DONT_COMPILE_CMDS_INLINE)) {
+ int savedNumCmds = envPtr->numCommands;
+ unsigned savedCodeNext =
+ envPtr->codeNext - envPtr->codeStart;
+ int update = 0, code;
/*
- * We copy the string before trying to find the command
- * by name. We used to modify the string in place, but
- * this is not safe because the name resolution
- * handlers could have side effects that rely on the
- * unmodified string.
+ * Mark the start of the command; the proper bytecode
+ * length will be updated later. There is no need to
+ * do this for the first bytecode in the compile env,
+ * as the check is done before calling
+ * TclExecuteByteCode(). Do emit an INST_START_CMD in
+ * special cases where the first bytecode is in a
+ * loop, to insure that the corresponding command is
+ * counted properly. Compilers for commands able to
+ * produce such a beast (currently 'while 1' only) set
+ * envPtr->atCmdStart to 0 in order to signal this
+ * case. [Bug 1752146]
+ *
+ * Note that the environment is initialised with
+ * atCmdStart=1 to avoid emitting ISC for the first
+ * command.
*/
- Tcl_DStringSetLength(&ds, 0);
- Tcl_DStringAppend(&ds, tokenPtr[1].start,
- tokenPtr[1].size);
-
- cmdPtr = (Command *) Tcl_FindCommand(interp,
- Tcl_DStringValue(&ds),
- (Tcl_Namespace *) cmdNsPtr, /*flags*/ 0);
-
- if ((cmdPtr != NULL)
- && (cmdPtr->compileProc != NULL)
- && !(cmdPtr->flags & CMD_HAS_EXEC_TRACES)
- && !(iPtr->flags & DONT_COMPILE_CMDS_INLINE)) {
- int savedNumCmds = envPtr->numCommands;
- unsigned int savedCodeNext =
- envPtr->codeNext - envPtr->codeStart;
-
- code = (*(cmdPtr->compileProc))(interp, &parse,
- envPtr);
- if (code == TCL_OK) {
- goto finishCommand;
- } else if (code == TCL_OUT_LINE_COMPILE) {
+ if (envPtr->atCmdStart) {
+ if (savedCodeNext != 0) {
/*
- * Restore numCommands and codeNext to their correct
- * values, removing any commands compiled before
- * TCL_OUT_LINE_COMPILE [Bugs 705406 and 735055]
+ * Increase the number of commands being
+ * started at the current point. Note that
+ * this depends on the exact layout of the
+ * INST_START_CMD's operands, so be careful!
*/
- envPtr->numCommands = savedNumCmds;
- envPtr->codeNext = envPtr->codeStart + savedCodeNext;
- } else { /* an error */
+
+ unsigned char *fixPtr = envPtr->codeNext - 4;
+
+ TclStoreInt4AtPtr(TclGetUInt4AtPtr(fixPtr)+1,
+ fixPtr);
+ }
+ } else {
+ TclEmitInstInt4(INST_START_CMD, 0, envPtr);
+ TclEmitInt4(1, envPtr);
+ update = 1;
+ }
+
+ code = (cmdPtr->compileProc)(interp, parsePtr,
+ cmdPtr, envPtr);
+
+ if (code == TCL_OK) {
+ if (update) {
/*
- * There was a compilation error, the last
- * command did not get compiled into (*envPtr).
- * Decrement the number of commands
- * claimed to be in (*envPtr).
+ * Fix the bytecode length.
*/
- envPtr->numCommands--;
- goto log;
+
+ unsigned char *fixPtr = envPtr->codeStart
+ + savedCodeNext + 1;
+ unsigned fixLen = envPtr->codeNext
+ - envPtr->codeStart - savedCodeNext;
+
+ TclStoreInt4AtPtr(fixLen, fixPtr);
}
- }
+ goto finishCommand;
+ } else {
+ if (envPtr->atCmdStart && savedCodeNext != 0) {
+ /*
+ * Decrease the number of commands being
+ * started at the current point. Note that
+ * this depends on the exact layout of the
+ * INST_START_CMD's operands, so be careful!
+ */
- /*
- * No compile procedure so push the word. If the
- * command was found, push a CmdName object to
- * reduce runtime lookups.
- */
+ unsigned char *fixPtr = envPtr->codeNext - 4;
+
+ TclStoreInt4AtPtr(TclGetUInt4AtPtr(fixPtr)-1,
+ fixPtr);
+ }
+
+ /*
+ * Restore numCommands and codeNext to their
+ * correct values, removing any commands compiled
+ * before the failure to produce bytecode got
+ * reported. [Bugs 705406 and 735055]
+ */
- objIndex = TclRegisterNewLiteral(envPtr,
- tokenPtr[1].start, tokenPtr[1].size);
- if (cmdPtr != NULL) {
- TclSetCmdNameObj(interp,
- envPtr->literalArrayPtr[objIndex].objPtr,
- cmdPtr);
+ envPtr->numCommands = savedNumCmds;
+ envPtr->codeNext = envPtr->codeStart+savedCodeNext;
}
- } else {
- /* Simple argument word of a command. We reach this if
- * and only if the command word was not compiled for
- * whatever reason. Register the literal's location
- * for use by uplevel, etc. commands, should they
- * encounter it unmodified. We care only if the we are
- * in a context which already allows absolute
- * counting.
+ }
+
+ /*
+ * No compile procedure so push the word. If the command
+ * was found, push a CmdName object to reduce runtime
+ * lookups. Avoid sharing this literal among different
+ * namespaces to reduce shimmering.
+ */
+
+ objIndex = TclRegisterNewNSLiteral(envPtr,
+ tokenPtr[1].start, tokenPtr[1].size);
+ if (cmdPtr != NULL) {
+ TclSetCmdNameObj(interp,
+ envPtr->literalArrayPtr[objIndex].objPtr,cmdPtr);
+ }
+ if ((wordIdx == 0) && (parsePtr->numWords == 1)) {
+ /*
+ * Single word script: unshare the command name to
+ * avoid shimmering between bytecode and cmdName
+ * representations [Bug 458361]
*/
- objIndex = TclRegisterNewLiteral(envPtr,
- tokenPtr[1].start, tokenPtr[1].size);
-#ifdef TCL_TIP280
- if (envPtr->clNext) {
- TclContinuationsEnterDerived (envPtr->literalArrayPtr[objIndex].objPtr,
- tokenPtr[1].start - envPtr->source,
- eclPtr->loc [wlineat].next [wordIdx]);
- }
-#endif
+ TclHideLiteral(interp, envPtr, objIndex);
}
- TclEmitPush(objIndex, envPtr);
} else {
/*
- * The word is not a simple string of characters.
+ * Simple argument word of a command. We reach this if and
+ * only if the command word was not compiled for whatever
+ * reason. Register the literal's location for use by
+ * uplevel, etc. commands, should they encounter it
+ * unmodified. We care only if the we are in a context
+ * which already allows absolute counting.
*/
- code = TclCompileTokens(interp, tokenPtr+1,
- tokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- goto log;
+ objIndex = TclRegisterNewLiteral(envPtr,
+ tokenPtr[1].start, tokenPtr[1].size);
+
+ if (envPtr->clNext) {
+ TclContinuationsEnterDerived (envPtr->literalArrayPtr[objIndex].objPtr,
+ tokenPtr[1].start - envPtr->source,
+ eclPtr->loc [wlineat].next [wordIdx]);
}
}
- }
+ TclEmitPush(objIndex, envPtr);
+ } /* for loop */
/*
- * Emit an invoke instruction for the command. We skip this
- * if a compile procedure was found for the command.
+ * Emit an invoke instruction for the command. We skip this if a
+ * compile procedure was found for the command.
*/
-
- if (wordIdx > 0) {
-#ifdef TCL_TIP280
+
+ if (expand) {
+ /*
+ * The stack depth during argument expansion can only be
+ * managed at runtime, as the number of elements in the
+ * expanded lists is not known at compile time. We adjust here
+ * the stack depth estimate so that it is correct after the
+ * command with expanded arguments returns.
+ *
+ * The end effect of this command's invocation is that all the
+ * words of the command are popped from the stack, and the
+ * result is pushed: the stack top changes by (1-wordIdx).
+ *
+ * Note that the estimates are not correct while the command
+ * is being prepared and run, INST_EXPAND_STKTOP is not
+ * stack-neutral in general.
+ */
+
+ TclEmitOpcode(INST_INVOKE_EXPANDED, envPtr);
+ TclAdjustStackDepth((1-wordIdx), envPtr);
+ } else if (wordIdx > 0) {
/*
* Save PC -> command map for the TclArgumentBC* functions.
*/
@@ -1364,8 +1556,8 @@ TclCompileScript(interp, script, numBytes, nested, envPtr)
int isnew;
Tcl_HashEntry* hePtr = Tcl_CreateHashEntry(&eclPtr->litInfo,
(char*) (envPtr->codeNext - envPtr->codeStart), &isnew);
- Tcl_SetHashValue(hePtr, (char*) wlineat);
-#endif
+ Tcl_SetHashValue(hePtr, INT2PTR(wlineat));
+
if (wordIdx <= 255) {
TclEmitInstInt1(INST_INVOKE_STK1, wordIdx, envPtr);
} else {
@@ -1378,115 +1570,57 @@ TclCompileScript(interp, script, numBytes, nested, envPtr)
* offsets of the source and code for the command.
*/
- finishCommand:
+ finishCommand:
EnterCmdExtentData(envPtr, currCmdIndex, commandLength,
(envPtr->codeNext-envPtr->codeStart) - startCodeOffset);
isFirstCmd = 0;
-#ifdef TCL_TIP280
- /* TIP #280: Free full form of per-word line data and insert
- * the reduced form now
+ /*
+ * TIP #280: Free full form of per-word line data and insert the
+ * reduced form now
*/
- ckfree ((char*) eclPtr->loc [wlineat].line);
- ckfree ((char*) eclPtr->loc [wlineat].next);
- eclPtr->loc [wlineat].line = wlines;
- eclPtr->loc [wlineat].next = NULL;
- wlines = NULL;
-#endif
- } /* end if parse.numWords > 0 */
+
+ ckfree((char *) eclPtr->loc[wlineat].line);
+ ckfree((char *) eclPtr->loc[wlineat].next);
+ eclPtr->loc[wlineat].line = wlines;
+ eclPtr->loc[wlineat].next = NULL;
+ } /* end if parsePtr->numWords > 0 */
/*
* Advance to the next command in the script.
*/
- next = parse.commandStart + parse.commandSize;
- bytesLeft -= (next - p);
+ next = parsePtr->commandStart + parsePtr->commandSize;
+ bytesLeft -= next - p;
p = next;
-#ifdef TCL_TIP280
- /* TIP #280 : Track lines in the just compiled command */
- TclAdvanceLines (&cmdLine, parse.commandStart, p);
+
+ /*
+ * TIP #280: Track lines in the just compiled command.
+ */
+
+ TclAdvanceLines(&cmdLine, parsePtr->commandStart, p);
TclAdvanceContinuations (&cmdLine, &clNext, p - envPtr->source);
-#endif
- Tcl_FreeParse(&parse);
- gotParse = 0;
- if (nested && (*parse.term == ']')) {
- /*
- * We get here in the special case where TCL_BRACKET_TERM was
- * set in the interpreter and the latest parsed command was
- * terminated by the matching close-bracket we were looking for.
- * Stop compilation.
- */
-
- break;
- }
+ Tcl_FreeParse(parsePtr);
} while (bytesLeft > 0);
/*
* If the source script yielded no instructions (e.g., if it was empty),
* push an empty string as the command's result.
- */
-
- if (envPtr->codeNext == entryCodeNext) {
- TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0),
- envPtr);
- }
-
- if (nested) {
- /*
- * When (nested != 0) back up 1 character to have
- * iPtr->termOffset indicate the offset to the matching
- * close-bracket.
- */
-
- iPtr->termOffset = (p - 1) - script;
- } else {
- iPtr->termOffset = (p - script);
- }
- Tcl_DStringFree(&ds);
- return TCL_OK;
-
- error:
- /*
- * Generate various pieces of error information, such as the line
- * number where the error occurred and information to add to the
- * errorInfo variable. Then free resources that had been allocated
- * to the command.
+ *
+ * WARNING: push an unshared object! If the script being compiled is a
+ * shared empty string, it will otherwise be self-referential and cause
+ * difficulties with literal management [Bugs 467523, 983660]. We used to
+ * have special code in TclReleaseLiteral to handle this particular
+ * self-reference, but now opt for avoiding its creation altogether.
*/
- commandLength = parse.commandSize;
- if (parse.term == parse.commandStart + commandLength - 1) {
- /*
- * The terminator character (such as ; or ]) of the command where
- * the error occurred is the last character in the parsed command.
- * Reduce the length by one so that the error message doesn't
- * include the terminator character.
- */
-
- commandLength -= 1;
- }
-
- log:
-#ifdef TCL_TIP280
- /* TIP #280: Free the per-word line data left over from parsing an
- * erroneous command, if any.
- */
- if (wlines) {
- ckfree ((char*) eclPtr->loc [wlineat].line);
- ckfree ((char*) eclPtr->loc [wlineat].next);
- ckfree ((char*) wlines);
- eclPtr->loc [wlineat].line = NULL;
- eclPtr->loc [wlineat].next = NULL;
- wlines = NULL;
+ if (envPtr->codeNext == entryCodeNext) {
+ TclEmitPush(TclAddLiteralObj(envPtr, Tcl_NewObj(), NULL), envPtr);
}
-#endif
- LogCompilationInfo(interp, script, parse.commandStart, commandLength);
- if (gotParse) {
- Tcl_FreeParse(&parse);
- }
- iPtr->termOffset = (p - script);
+ envPtr->numSrcBytes = (p - script);
+ TclStackFree(interp, parsePtr);
Tcl_DStringFree(&ds);
- return code;
}
/*
@@ -1495,38 +1629,37 @@ TclCompileScript(interp, script, numBytes, nested, envPtr)
* TclCompileTokens --
*
* Given an array of tokens parsed from a Tcl command (e.g., the tokens
- * that make up a word) this procedure emits instructions to evaluate
- * the tokens and concatenate their values to form a single result
- * value on the interpreter's runtime evaluation stack.
+ * that make up a word) this procedure emits instructions to evaluate the
+ * tokens and concatenate their values to form a single result value on
+ * the interpreter's runtime evaluation stack.
*
* Results:
* The return value is a standard Tcl result. If an error occurs, an
* error message is left in the interpreter's result.
- *
+ *
* Side effects:
- * Instructions are added to envPtr to push and evaluate the tokens
- * at runtime.
+ * Instructions are added to envPtr to push and evaluate the tokens at
+ * runtime.
*
*----------------------------------------------------------------------
*/
-int
-TclCompileTokens(interp, tokenPtr, count, envPtr)
- Tcl_Interp *interp; /* Used for error and status reporting. */
- Tcl_Token *tokenPtr; /* Pointer to first in an array of tokens
- * to compile. */
- int count; /* Number of tokens to consider at tokenPtr.
+void
+TclCompileTokens(
+ Tcl_Interp *interp, /* Used for error and status reporting. */
+ Tcl_Token *tokenPtr, /* Pointer to first in an array of tokens to
+ * compile. */
+ int count, /* Number of tokens to consider at tokenPtr.
* Must be at least 1. */
- CompileEnv *envPtr; /* Holds the resulting instructions. */
+ CompileEnv *envPtr) /* Holds the resulting instructions. */
{
Tcl_DString textBuffer; /* Holds concatenated chars from adjacent
* TCL_TOKEN_TEXT, TCL_TOKEN_BS tokens. */
char buffer[TCL_UTF_MAX];
- CONST char *name, *p;
+ const char *name, *p;
int numObjsToConcat, nameBytes, localVarName, localVar;
- int length, i, code;
+ int length, i;
unsigned char *entryCodeNext = envPtr->codeNext;
-#ifdef TCL_TIP280
#define NUM_STATIC_POS 20
int isLiteral, maxNumCL, numCL;
int* clPosition = NULL;
@@ -1539,7 +1672,7 @@ TclCompileTokens(interp, tokenPtr, count, envPtr)
* any. The table is extended if needed.
*
* Note: Different to the equivalent code in function
- * 'EvalTokensStandard()' (see file "tclBasic.c") we do not seem to need
+ * 'TclSubstTokens()' (see file "tclParse.c") we do not seem to need
* the 'adjust' variable. We also do not seem to need code which merges
* continuation line information of multiple words which concat'd at
* runtime. Either that or I have not managed to find a test case for
@@ -1562,186 +1695,166 @@ TclCompileTokens(interp, tokenPtr, count, envPtr)
maxNumCL = NUM_STATIC_POS;
clPosition = (int*) ckalloc (maxNumCL*sizeof(int));
}
-#endif
Tcl_DStringInit(&textBuffer);
numObjsToConcat = 0;
for ( ; count > 0; count--, tokenPtr++) {
switch (tokenPtr->type) {
- case TCL_TOKEN_TEXT:
- Tcl_DStringAppend(&textBuffer, tokenPtr->start,
- tokenPtr->size);
- break;
+ case TCL_TOKEN_TEXT:
+ Tcl_DStringAppend(&textBuffer, tokenPtr->start, tokenPtr->size);
+ break;
- case TCL_TOKEN_BS:
- length = TclParseBackslash(tokenPtr->start, tokenPtr->size,
- (int *) NULL, buffer);
- Tcl_DStringAppend(&textBuffer, buffer, length);
+ case TCL_TOKEN_BS:
+ length = TclParseBackslash(tokenPtr->start, tokenPtr->size,
+ NULL, buffer);
+ Tcl_DStringAppend(&textBuffer, buffer, length);
-#ifdef TCL_TIP280
- /*
- * If the backslash sequence we found is in a literal, and
- * represented a continuation line, we compute and store its
- * location (as char offset to the beginning of the _result_
- * script). We may have to extend the table of locations.
- *
- * Note that the continuation line information is relevant
- * even if the word we are processing is not a literal, as it
- * can affect nested commands. See the branch for
- * TCL_TOKEN_COMMAND below, where the adjustment we are
- * tracking here is taken into account. The good thing is that
- * we do not need a table of everything, just the number of
- * lines we have to add as correction.
- */
+ /*
+ * If the backslash sequence we found is in a literal, and
+ * represented a continuation line, we compute and store its
+ * location (as char offset to the beginning of the _result_
+ * script). We may have to extend the table of locations.
+ *
+ * Note that the continuation line information is relevant even if
+ * the word we are processing is not a literal, as it can affect
+ * nested commands. See the branch for TCL_TOKEN_COMMAND below,
+ * where the adjustment we are tracking here is taken into
+ * account. The good thing is that we do not need a table of
+ * everything, just the number of lines we have to add as
+ * correction.
+ */
- if ((length == 1) && (buffer[0] == ' ') &&
- (tokenPtr->start[1] == '\n')) {
- if (isLiteral) {
- int clPos = Tcl_DStringLength (&textBuffer);
+ if ((length == 1) && (buffer[0] == ' ') &&
+ (tokenPtr->start[1] == '\n')) {
+ if (isLiteral) {
+ int clPos = Tcl_DStringLength (&textBuffer);
- if (numCL >= maxNumCL) {
- maxNumCL *= 2;
- clPosition = (int*) ckrealloc ((char*)clPosition,
- maxNumCL*sizeof(int));
- }
- clPosition[numCL] = clPos;
- numCL ++;
+ if (numCL >= maxNumCL) {
+ maxNumCL *= 2;
+ clPosition = (int*) ckrealloc ((char*)clPosition,
+ maxNumCL*sizeof(int));
}
+ clPosition[numCL] = clPos;
+ numCL ++;
}
-#endif
- break;
+ }
+ break;
- case TCL_TOKEN_COMMAND:
- /*
- * Push any accumulated chars appearing before the command.
- */
-
- if (Tcl_DStringLength(&textBuffer) > 0) {
- int literal;
-
- literal = TclRegisterLiteral(envPtr,
- Tcl_DStringValue(&textBuffer),
- Tcl_DStringLength(&textBuffer), /*onHeap*/ 0);
- TclEmitPush(literal, envPtr);
- numObjsToConcat++;
- Tcl_DStringFree(&textBuffer);
-#ifdef TCL_TIP280
- if (numCL) {
- TclContinuationsEnter(envPtr->literalArrayPtr[literal].objPtr,
- numCL, clPosition);
- }
- numCL = 0;
-#endif
- }
-
- code = TclCompileScript(interp, tokenPtr->start+1,
- tokenPtr->size-2, /*nested*/ 0, envPtr);
- if (code != TCL_OK) {
- goto error;
- }
+ case TCL_TOKEN_COMMAND:
+ /*
+ * Push any accumulated chars appearing before the command.
+ */
+
+ if (Tcl_DStringLength(&textBuffer) > 0) {
+ int literal = TclRegisterNewLiteral(envPtr,
+ Tcl_DStringValue(&textBuffer),
+ Tcl_DStringLength(&textBuffer));
+
+ TclEmitPush(literal, envPtr);
numObjsToConcat++;
- break;
+ Tcl_DStringFree(&textBuffer);
- case TCL_TOKEN_VARIABLE:
- /*
- * Push any accumulated chars appearing before the $<var>.
- */
-
- if (Tcl_DStringLength(&textBuffer) > 0) {
- int literal;
-
- literal = TclRegisterLiteral(envPtr,
- Tcl_DStringValue(&textBuffer),
- Tcl_DStringLength(&textBuffer), /*onHeap*/ 0);
- TclEmitPush(literal, envPtr);
- numObjsToConcat++;
- Tcl_DStringFree(&textBuffer);
+ if (numCL) {
+ TclContinuationsEnter(envPtr->literalArrayPtr[literal].objPtr,
+ numCL, clPosition);
}
-
- /*
- * Determine how the variable name should be handled: if it contains
- * any namespace qualifiers it is not a local variable (localVarName=-1);
- * if it looks like an array element and the token has a single component,
- * it should not be created here [Bug 569438] (localVarName=0); otherwise,
- * the local variable can safely be created (localVarName=1).
- */
-
- name = tokenPtr[1].start;
- nameBytes = tokenPtr[1].size;
- localVarName = -1;
- if (envPtr->procPtr != NULL) {
- localVarName = 1;
- for (i = 0, p = name; i < nameBytes; i++, p++) {
- if ((*p == ':') && (i < (nameBytes-1))
- && (*(p+1) == ':')) {
- localVarName = -1;
- break;
- } else if ((*p == '(')
- && (tokenPtr->numComponents == 1)
- && (*(name + nameBytes - 1) == ')')) {
- localVarName = 0;
- break;
- }
+ numCL = 0;
+ }
+
+ TclCompileScript(interp, tokenPtr->start+1,
+ tokenPtr->size-2, envPtr);
+ numObjsToConcat++;
+ break;
+
+ case TCL_TOKEN_VARIABLE:
+ /*
+ * Push any accumulated chars appearing before the $<var>.
+ */
+
+ if (Tcl_DStringLength(&textBuffer) > 0) {
+ int literal;
+
+ literal = TclRegisterNewLiteral(envPtr,
+ Tcl_DStringValue(&textBuffer),
+ Tcl_DStringLength(&textBuffer));
+ TclEmitPush(literal, envPtr);
+ numObjsToConcat++;
+ Tcl_DStringFree(&textBuffer);
+ }
+
+ /*
+ * Determine how the variable name should be handled: if it
+ * contains any namespace qualifiers it is not a local variable
+ * (localVarName=-1); if it looks like an array element and the
+ * token has a single component, it should not be created here
+ * [Bug 569438] (localVarName=0); otherwise, the local variable
+ * can safely be created (localVarName=1).
+ */
+
+ name = tokenPtr[1].start;
+ nameBytes = tokenPtr[1].size;
+ localVarName = -1;
+ if (envPtr->procPtr != NULL) {
+ localVarName = 1;
+ for (i = 0, p = name; i < nameBytes; i++, p++) {
+ if ((*p == ':') && (i < nameBytes-1) && (*(p+1) == ':')) {
+ localVarName = -1;
+ break;
+ } else if ((*p == '(')
+ && (tokenPtr->numComponents == 1)
+ && (*(name + nameBytes - 1) == ')')) {
+ localVarName = 0;
+ break;
}
}
+ }
- /*
- * Either push the variable's name, or find its index in
- * the array of local variables in a procedure frame.
- */
+ /*
+ * Either push the variable's name, or find its index in the array
+ * of local variables in a procedure frame.
+ */
- localVar = -1;
- if (localVarName != -1) {
- localVar = TclFindCompiledLocal(name, nameBytes,
- localVarName, /*flags*/ 0, envPtr->procPtr);
- }
+ localVar = -1;
+ if (localVarName != -1) {
+ localVar = TclFindCompiledLocal(name, nameBytes, localVarName,
+ envPtr->procPtr);
+ }
+ if (localVar < 0) {
+ TclEmitPush(TclRegisterNewLiteral(envPtr, name, nameBytes),
+ envPtr);
+ }
+
+ /*
+ * Emit instructions to load the variable.
+ */
+
+ if (tokenPtr->numComponents == 1) {
if (localVar < 0) {
- TclEmitPush(TclRegisterNewLiteral(envPtr, name, nameBytes),
- envPtr);
+ TclEmitOpcode(INST_LOAD_SCALAR_STK, envPtr);
+ } else if (localVar <= 255) {
+ TclEmitInstInt1(INST_LOAD_SCALAR1, localVar, envPtr);
+ } else {
+ TclEmitInstInt4(INST_LOAD_SCALAR4, localVar, envPtr);
}
-
- /*
- * Emit instructions to load the variable.
- */
-
- if (tokenPtr->numComponents == 1) {
- if (localVar < 0) {
- TclEmitOpcode(INST_LOAD_SCALAR_STK, envPtr);
- } else if (localVar <= 255) {
- TclEmitInstInt1(INST_LOAD_SCALAR1, localVar,
- envPtr);
- } else {
- TclEmitInstInt4(INST_LOAD_SCALAR4, localVar,
- envPtr);
- }
+ } else {
+ TclCompileTokens(interp, tokenPtr+2,
+ tokenPtr->numComponents-1, envPtr);
+ if (localVar < 0) {
+ TclEmitOpcode(INST_LOAD_ARRAY_STK, envPtr);
+ } else if (localVar <= 255) {
+ TclEmitInstInt1(INST_LOAD_ARRAY1, localVar, envPtr);
} else {
- code = TclCompileTokens(interp, tokenPtr+2,
- tokenPtr->numComponents-1, envPtr);
- if (code != TCL_OK) {
- char errorBuffer[150];
- sprintf(errorBuffer,
- "\n (parsing index for array \"%.*s\")",
- ((nameBytes > 100)? 100 : nameBytes), name);
- Tcl_AddObjErrorInfo(interp, errorBuffer, -1);
- goto error;
- }
- if (localVar < 0) {
- TclEmitOpcode(INST_LOAD_ARRAY_STK, envPtr);
- } else if (localVar <= 255) {
- TclEmitInstInt1(INST_LOAD_ARRAY1, localVar,
- envPtr);
- } else {
- TclEmitInstInt4(INST_LOAD_ARRAY4, localVar,
- envPtr);
- }
+ TclEmitInstInt4(INST_LOAD_ARRAY4, localVar, envPtr);
}
- numObjsToConcat++;
- count -= tokenPtr->numComponents;
- tokenPtr += tokenPtr->numComponents;
- break;
+ }
+ numObjsToConcat++;
+ count -= tokenPtr->numComponents;
+ tokenPtr += tokenPtr->numComponents;
+ break;
- default:
- panic("Unexpected token type in TclCompileTokens");
+ default:
+ Tcl_Panic("Unexpected token type in TclCompileTokens: %d; %.*s",
+ tokenPtr->type, tokenPtr->size, tokenPtr->start);
}
}
@@ -1752,18 +1865,16 @@ TclCompileTokens(interp, tokenPtr, count, envPtr)
if (Tcl_DStringLength(&textBuffer) > 0) {
int literal;
- literal = TclRegisterLiteral(envPtr, Tcl_DStringValue(&textBuffer),
- Tcl_DStringLength(&textBuffer), /*onHeap*/ 0);
+ literal = TclRegisterNewLiteral(envPtr, Tcl_DStringValue(&textBuffer),
+ Tcl_DStringLength(&textBuffer));
TclEmitPush(literal, envPtr);
numObjsToConcat++;
-#ifdef TCL_TIP280
if (numCL) {
TclContinuationsEnter(envPtr->literalArrayPtr[literal].objPtr,
numCL, clPosition);
}
numCL = 0;
-#endif
}
/*
@@ -1781,16 +1892,12 @@ TclCompileTokens(interp, tokenPtr, count, envPtr)
/*
* If the tokens yielded no instructions, push an empty string.
*/
-
+
if (envPtr->codeNext == entryCodeNext) {
- TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0),
- envPtr);
+ TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
}
- code = TCL_OK;
-
- error:
Tcl_DStringFree(&textBuffer);
-#ifdef TCL_TIP280
+
/*
* Release the temp table we used to collect the locations of
* continuation lines, if any.
@@ -1799,8 +1906,6 @@ TclCompileTokens(interp, tokenPtr, count, envPtr)
if (maxNumCL) {
ckfree ((char*) clPosition);
}
-#endif
- return code;
}
/*
@@ -1811,53 +1916,45 @@ TclCompileTokens(interp, tokenPtr, count, envPtr)
* Given an array of parse tokens for a word containing one or more Tcl
* commands, emit inline instructions to execute them. This procedure
* differs from TclCompileTokens in that a simple word such as a loop
- * body enclosed in braces is not just pushed as a string, but is
- * itself parsed into tokens and compiled.
+ * body enclosed in braces is not just pushed as a string, but is itself
+ * parsed into tokens and compiled.
*
* Results:
* The return value is a standard Tcl result. If an error occurs, an
* error message is left in the interpreter's result.
- *
+ *
* Side effects:
* Instructions are added to envPtr to execute the tokens at runtime.
*
*----------------------------------------------------------------------
*/
-int
-TclCompileCmdWord(interp, tokenPtr, count, envPtr)
- Tcl_Interp *interp; /* Used for error and status reporting. */
- Tcl_Token *tokenPtr; /* Pointer to first in an array of tokens
- * for a command word to compile inline. */
- int count; /* Number of tokens to consider at tokenPtr.
+void
+TclCompileCmdWord(
+ Tcl_Interp *interp, /* Used for error and status reporting. */
+ Tcl_Token *tokenPtr, /* Pointer to first in an array of tokens for
+ * a command word to compile inline. */
+ int count, /* Number of tokens to consider at tokenPtr.
* Must be at least 1. */
- CompileEnv *envPtr; /* Holds the resulting instructions. */
+ CompileEnv *envPtr) /* Holds the resulting instructions. */
{
- int code;
-
- /*
- * Handle the common case: if there is a single text token, compile it
- * into an inline sequence of instructions.
- */
-
if ((count == 1) && (tokenPtr->type == TCL_TOKEN_TEXT)) {
- code = TclCompileScript(interp, tokenPtr->start, tokenPtr->size,
- /*nested*/ 0, envPtr);
- return code;
- }
+ /*
+ * Handle the common case: if there is a single text token, compile it
+ * into an inline sequence of instructions.
+ */
- /*
- * Multiple tokens or the single token involves substitutions. Emit
- * instructions to invoke the eval command procedure at runtime on the
- * result of evaluating the tokens.
- */
+ TclCompileScript(interp, tokenPtr->start, tokenPtr->size, envPtr);
+ } else {
+ /*
+ * Multiple tokens or the single token involves substitutions. Emit
+ * instructions to invoke the eval command procedure at runtime on the
+ * result of evaluating the tokens.
+ */
- code = TclCompileTokens(interp, tokenPtr, count, envPtr);
- if (code != TCL_OK) {
- return code;
+ TclCompileTokens(interp, tokenPtr, count, envPtr);
+ TclEmitOpcode(INST_EVAL_STK, envPtr);
}
- TclEmitOpcode(INST_EVAL_STK, envPtr);
- return TCL_OK;
}
/*
@@ -1874,42 +1971,37 @@ TclCompileCmdWord(interp, tokenPtr, count, envPtr)
* Results:
* The return value is a standard Tcl result. If an error occurs, an
* error message is left in the interpreter's result.
- *
+ *
* Side effects:
* Instructions are added to envPtr to execute the expression.
*
*----------------------------------------------------------------------
*/
-int
-TclCompileExprWords(interp, tokenPtr, numWords, envPtr)
- Tcl_Interp *interp; /* Used for error and status reporting. */
- Tcl_Token *tokenPtr; /* Points to first in an array of word
- * tokens tokens for the expression to
- * compile inline. */
- int numWords; /* Number of word tokens starting at
- * tokenPtr. Must be at least 1. Each word
- * token contains one or more subtokens. */
- CompileEnv *envPtr; /* Holds the resulting instructions. */
+void
+TclCompileExprWords(
+ Tcl_Interp *interp, /* Used for error and status reporting. */
+ Tcl_Token *tokenPtr, /* Points to first in an array of word tokens
+ * tokens for the expression to compile
+ * inline. */
+ int numWords, /* Number of word tokens starting at tokenPtr.
+ * Must be at least 1. Each word token
+ * contains one or more subtokens. */
+ CompileEnv *envPtr) /* Holds the resulting instructions. */
{
Tcl_Token *wordPtr;
- int numBytes, i, code;
- CONST char *script;
-
- code = TCL_OK;
+ int i, concatItems;
/*
- * If the expression is a single word that doesn't require
- * substitutions, just compile its string into inline instructions.
+ * If the expression is a single word that doesn't require substitutions,
+ * just compile its string into inline instructions.
*/
if ((numWords == 1) && (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD)) {
- script = tokenPtr[1].start;
- numBytes = tokenPtr[1].size;
- code = TclCompileExpr(interp, script, numBytes, envPtr);
- return code;
+ TclCompileExpr(interp, tokenPtr[1].start, tokenPtr[1].size, envPtr, 1);
+ return;
}
-
+
/*
* Emit code to call the expr command proc at runtime. Concatenate the
* (already substituted once) expr tokens with a space between each.
@@ -1917,30 +2009,68 @@ TclCompileExprWords(interp, tokenPtr, numWords, envPtr)
wordPtr = tokenPtr;
for (i = 0; i < numWords; i++) {
- code = TclCompileTokens(interp, wordPtr+1, wordPtr->numComponents,
- envPtr);
- if (code != TCL_OK) {
- break;
- }
+ TclCompileTokens(interp, wordPtr+1, wordPtr->numComponents, envPtr);
if (i < (numWords - 1)) {
- TclEmitPush(TclRegisterLiteral(envPtr, " ", 1, /*onHeap*/ 0),
- envPtr);
+ TclEmitPush(TclRegisterNewLiteral(envPtr, " ", 1), envPtr);
}
wordPtr += (wordPtr->numComponents + 1);
}
- if (code == TCL_OK) {
- int concatItems = 2*numWords - 1;
- while (concatItems > 255) {
- TclEmitInstInt1(INST_CONCAT1, 255, envPtr);
- concatItems -= 254;
- }
- if (concatItems > 1) {
- TclEmitInstInt1(INST_CONCAT1, concatItems, envPtr);
- }
- TclEmitOpcode(INST_EXPR_STK, envPtr);
+ concatItems = 2*numWords - 1;
+ while (concatItems > 255) {
+ TclEmitInstInt1(INST_CONCAT1, 255, envPtr);
+ concatItems -= 254;
+ }
+ if (concatItems > 1) {
+ TclEmitInstInt1(INST_CONCAT1, concatItems, envPtr);
}
+ TclEmitOpcode(INST_EXPR_STK, envPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCompileNoOp --
+ *
+ * Function called to compile no-op's
+ *
+ * Results:
+ * The return value is TCL_OK, indicating successful compilation.
+ *
+ * Side effects:
+ * Instructions are added to envPtr to execute a no-op at runtime. No
+ * result is pushed onto the stack: the compiler has to take care of this
+ * itself if the last compiled command is a NoOp.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCompileNoOp(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Parse *parsePtr, /* Points to a parse structure for the command
+ * created by Tcl_ParseCommand. */
+ Command *cmdPtr, /* Points to defintion of command being
+ * compiled. */
+ CompileEnv *envPtr) /* Holds resulting instructions. */
+{
+ Tcl_Token *tokenPtr;
+ int i;
+ int savedStackDepth = envPtr->currStackDepth;
+
+ tokenPtr = parsePtr->tokenPtr;
+ for(i = 1; i < parsePtr->numWords; i++) {
+ tokenPtr = tokenPtr + tokenPtr->numComponents + 1;
+ envPtr->currStackDepth = savedStackDepth;
- return code;
+ if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
+ TclCompileTokens(interp, tokenPtr+1, tokenPtr->numComponents,
+ envPtr);
+ TclEmitOpcode(INST_POP, envPtr);
+ }
+ }
+ envPtr->currStackDepth = savedStackDepth;
+ TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
+ return TCL_OK;
}
/*
@@ -1949,10 +2079,10 @@ TclCompileExprWords(interp, tokenPtr, numWords, envPtr)
* TclInitByteCodeObj --
*
* Create a ByteCode structure and initialize it from a CompileEnv
- * compilation environment structure. The ByteCode structure is
- * smaller and contains just that information needed to execute
- * the bytecode instructions resulting from compiling a Tcl script.
- * The resulting structure is placed in the specified object.
+ * compilation environment structure. The ByteCode structure is smaller
+ * and contains just that information needed to execute the bytecode
+ * instructions resulting from compiling a Tcl script. The resulting
+ * structure is placed in the specified object.
*
* Results:
* A newly constructed ByteCode object is stored in the internal
@@ -1960,21 +2090,21 @@ TclCompileExprWords(interp, tokenPtr, numWords, envPtr)
*
* Side effects:
* A single heap object is allocated to hold the new ByteCode structure
- * and its code, object, command location, and aux data arrays. Note
- * that "ownership" (i.e., the pointers to) the Tcl objects and aux
- * data items will be handed over to the new ByteCode structure from
- * the CompileEnv structure.
+ * and its code, object, command location, and aux data arrays. Note that
+ * "ownership" (i.e., the pointers to) the Tcl objects and aux data items
+ * will be handed over to the new ByteCode structure from the CompileEnv
+ * structure.
*
*----------------------------------------------------------------------
*/
void
-TclInitByteCodeObj(objPtr, envPtr)
- Tcl_Obj *objPtr; /* Points object that should be
- * initialized, and whose string rep
- * contains the source code. */
- register CompileEnv *envPtr; /* Points to the CompileEnv structure from
- * which to create a ByteCode structure. */
+TclInitByteCodeObj(
+ Tcl_Obj *objPtr, /* Points object that should be initialized,
+ * and whose string rep contains the source
+ * code. */
+ register CompileEnv *envPtr)/* Points to the CompileEnv structure from
+ * which to create a ByteCode structure. */
{
register ByteCode *codePtr;
size_t codeBytes, objArrayBytes, exceptArrayBytes, cmdLocBytes;
@@ -1985,10 +2115,7 @@ TclInitByteCodeObj(objPtr, envPtr)
#endif
int numLitObjects = envPtr->literalArrayNext;
Namespace *namespacePtr;
- int i;
-#ifdef TCL_TIP280
- int new;
-#endif
+ int i, isNew;
Interp *iPtr;
iPtr = envPtr->iPtr;
@@ -1998,24 +2125,24 @@ TclInitByteCodeObj(objPtr, envPtr)
exceptArrayBytes = (envPtr->exceptArrayNext * sizeof(ExceptionRange));
auxDataArrayBytes = (envPtr->auxDataArrayNext * sizeof(AuxData));
cmdLocBytes = GetCmdLocEncodingSize(envPtr);
-
+
/*
* Compute the total number of bytes needed for this bytecode.
*/
structureSize = sizeof(ByteCode);
- structureSize += TCL_ALIGN(codeBytes); /* align object array */
- structureSize += TCL_ALIGN(objArrayBytes); /* align exc range arr */
+ structureSize += TCL_ALIGN(codeBytes); /* align object array */
+ structureSize += TCL_ALIGN(objArrayBytes); /* align exc range arr */
structureSize += TCL_ALIGN(exceptArrayBytes); /* align AuxData array */
structureSize += auxDataArrayBytes;
structureSize += cmdLocBytes;
if (envPtr->iPtr->varFramePtr != NULL) {
- namespacePtr = envPtr->iPtr->varFramePtr->nsPtr;
+ namespacePtr = envPtr->iPtr->varFramePtr->nsPtr;
} else {
- namespacePtr = envPtr->iPtr->globalNsPtr;
+ namespacePtr = envPtr->iPtr->globalNsPtr;
}
-
+
p = (unsigned char *) ckalloc((size_t) structureSize);
codePtr = (ByteCode *) p;
codePtr->interpHandle = TclHandlePreserve(iPtr->handle);
@@ -2023,7 +2150,11 @@ TclInitByteCodeObj(objPtr, envPtr)
codePtr->nsPtr = namespacePtr;
codePtr->nsEpoch = namespacePtr->resolverEpoch;
codePtr->refCount = 1;
- codePtr->flags = 0;
+ if (namespacePtr->compiledVarResProc || iPtr->resolverPtr) {
+ codePtr->flags = TCL_BYTECODE_RESOLVE_VARS;
+ } else {
+ codePtr->flags = 0;
+ }
codePtr->source = envPtr->source;
codePtr->procPtr = envPtr->procPtr;
@@ -2039,28 +2170,26 @@ TclInitByteCodeObj(objPtr, envPtr)
p += sizeof(ByteCode);
codePtr->codeStart = p;
- memcpy((VOID *) p, (VOID *) envPtr->codeStart, (size_t) codeBytes);
-
- p += TCL_ALIGN(codeBytes); /* align object array */
+ memcpy(p, envPtr->codeStart, (size_t) codeBytes);
+
+ p += TCL_ALIGN(codeBytes); /* align object array */
codePtr->objArrayPtr = (Tcl_Obj **) p;
for (i = 0; i < numLitObjects; i++) {
codePtr->objArrayPtr[i] = envPtr->literalArrayPtr[i].objPtr;
}
- p += TCL_ALIGN(objArrayBytes); /* align exception range array */
+ p += TCL_ALIGN(objArrayBytes); /* align exception range array */
if (exceptArrayBytes > 0) {
codePtr->exceptArrayPtr = (ExceptionRange *) p;
- memcpy((VOID *) p, (VOID *) envPtr->exceptArrayPtr,
- (size_t) exceptArrayBytes);
+ memcpy(p, envPtr->exceptArrayPtr, (size_t) exceptArrayBytes);
} else {
codePtr->exceptArrayPtr = NULL;
}
-
- p += TCL_ALIGN(exceptArrayBytes); /* align AuxData array */
+
+ p += TCL_ALIGN(exceptArrayBytes); /* align AuxData array */
if (auxDataArrayBytes > 0) {
codePtr->auxDataArrayPtr = (AuxData *) p;
- memcpy((VOID *) p, (VOID *) envPtr->auxDataArrayPtr,
- (size_t) auxDataArrayBytes);
+ memcpy(p, envPtr->auxDataArrayPtr, (size_t) auxDataArrayBytes);
} else {
codePtr->auxDataArrayPtr = NULL;
}
@@ -2070,11 +2199,11 @@ TclInitByteCodeObj(objPtr, envPtr)
EncodeCmdLocMap(envPtr, codePtr, (unsigned char *) p);
#else
nextPtr = EncodeCmdLocMap(envPtr, codePtr, (unsigned char *) p);
- if (((size_t)(nextPtr - p)) != cmdLocBytes) {
- panic("TclInitByteCodeObj: encoded cmd location bytes %ld != expected size %ld\n", (nextPtr - p), cmdLocBytes);
+ if (((size_t)(nextPtr - p)) != cmdLocBytes) {
+ Tcl_Panic("TclInitByteCodeObj: encoded cmd location bytes %d != expected size %d", (nextPtr - p), cmdLocBytes);
}
#endif
-
+
/*
* Record various compilation-related statistics about the new ByteCode
* structure. Don't include overhead for statistics-related fields.
@@ -2084,115 +2213,29 @@ TclInitByteCodeObj(objPtr, envPtr)
codePtr->structureSize = structureSize
- (sizeof(size_t) + sizeof(Tcl_Time));
Tcl_GetTime(&(codePtr->createTime));
-
+
RecordByteCodeStats(codePtr);
#endif /* TCL_COMPILE_STATS */
-
+
/*
- * Free the old internal rep then convert the object to a
- * bytecode object by making its internal rep point to the just
- * compiled ByteCode.
+ * Free the old internal rep then convert the object to a bytecode object
+ * by making its internal rep point to the just compiled ByteCode.
*/
-
- if ((objPtr->typePtr != NULL) &&
- (objPtr->typePtr->freeIntRepProc != NULL)) {
- (*objPtr->typePtr->freeIntRepProc)(objPtr);
- }
- objPtr->internalRep.otherValuePtr = (VOID *) codePtr;
+
+ TclFreeIntRep(objPtr);
+ objPtr->internalRep.otherValuePtr = (void *) codePtr;
objPtr->typePtr = &tclByteCodeType;
-#ifdef TCL_TIP280
- /* TIP #280. Associate the extended per-word line information with the
+ /*
+ * TIP #280. Associate the extended per-word line information with the
* byte code object (internal rep), for use with the bc compiler.
*/
- Tcl_SetHashValue (Tcl_CreateHashEntry (iPtr->lineBCPtr, (char*) codePtr, &new),
- envPtr->extCmdMapPtr);
+ Tcl_SetHashValue(Tcl_CreateHashEntry(iPtr->lineBCPtr, (char *) codePtr,
+ &isNew), envPtr->extCmdMapPtr);
envPtr->extCmdMapPtr = NULL;
-#endif
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * LogCompilationInfo --
- *
- * This procedure is invoked after an error occurs during compilation.
- * It adds information to the "errorInfo" variable to describe the
- * command that was being compiled when the error occurred.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Information about the command is added to errorInfo and the
- * line number stored internally in the interpreter is set. If this
- * is the first call to this procedure or Tcl_AddObjErrorInfo since
- * an error occurred, then old information in errorInfo is
- * deleted.
- *
- *----------------------------------------------------------------------
- */
-static void
-LogCompilationInfo(interp, script, command, length)
- Tcl_Interp *interp; /* Interpreter in which to log the
- * information. */
- CONST char *script; /* First character in script containing
- * command (must be <= command). */
- CONST char *command; /* First character in command that
- * generated the error. */
- int length; /* Number of bytes in command (-1 means
- * use all bytes up to first null byte). */
-{
- char buffer[200];
- register CONST char *p;
- char *ellipsis = "";
- Interp *iPtr = (Interp *) interp;
-
- if (iPtr->flags & ERR_ALREADY_LOGGED) {
- /*
- * Someone else has already logged error information for this
- * command; we shouldn't add anything more.
- */
-
- return;
- }
-
- /*
- * Compute the line number where the error occurred.
- */
-
- iPtr->errorLine = 1;
- for (p = script; p != command; p++) {
- if (*p == '\n') {
- iPtr->errorLine++;
- }
- }
-
- /*
- * Create an error message to add to errorInfo, including up to a
- * maximum number of characters of the command.
- */
-
- if (length < 0) {
- length = strlen(command);
- }
- if (length > 150) {
- length = 150;
- ellipsis = "...";
- }
- while ( (command[length] & 0xC0) == 0x80 ) {
- /*
- * Back up truncation point so that we don't truncate in the
- * middle of a multi-byte character (in UTF-8)
- */
- length--;
- ellipsis = "...";
- }
- sprintf(buffer, "\n while compiling\n\"%.*s%s\"",
- length, command, ellipsis);
- Tcl_AddObjErrorInfo(interp, buffer, -1);
+ codePtr->localCachePtr = NULL;
}
/*
@@ -2209,30 +2252,26 @@ LogCompilationInfo(interp, script, command, length)
* Results:
* If create is 0 and the name is non-NULL, then if the variable is
* found, the index of its entry in the procedure's array of local
- * variables is returned; otherwise -1 is returned. If name is NULL,
- * the index of a new temporary variable is returned. Finally, if
- * create is 1 and name is non-NULL, the index of a new entry is
- * returned.
+ * variables is returned; otherwise -1 is returned. If name is NULL, the
+ * index of a new temporary variable is returned. Finally, if create is 1
+ * and name is non-NULL, the index of a new entry is returned.
*
* Side effects:
- * Creates and registers a new local variable if create is 1 and
- * the variable is unknown, or if the name is NULL.
+ * Creates and registers a new local variable if create is 1 and the
+ * variable is unknown, or if the name is NULL.
*
*----------------------------------------------------------------------
*/
int
-TclFindCompiledLocal(name, nameBytes, create, flags, procPtr)
- register CONST char *name; /* Points to first character of the name of
- * a scalar or array variable. If NULL, a
+TclFindCompiledLocal(
+ register const char *name, /* Points to first character of the name of a
+ * scalar or array variable. If NULL, a
* temporary var should be created. */
- int nameBytes; /* Number of bytes in the name. */
- int create; /* If 1, allocate a local frame entry for
- * the variable if it is new. */
- int flags; /* Flag bits for the compiled local if
- * created. Only VAR_SCALAR, VAR_ARRAY, and
- * VAR_LINK make sense. */
- register Proc *procPtr; /* Points to structure describing procedure
+ int nameBytes, /* Number of bytes in the name. */
+ int create, /* If 1, allocate a local frame entry for the
+ * variable if it is new. */
+ register Proc *procPtr) /* Points to structure describing procedure
* containing the variable reference. */
{
register CompiledLocal *localPtr;
@@ -2244,14 +2283,16 @@ TclFindCompiledLocal(name, nameBytes, create, flags, procPtr)
* name already exist?
*/
- if (name != NULL) {
+ if (name != NULL) {
int localCt = procPtr->numCompiledLocals;
+
localPtr = procPtr->firstLocalPtr;
for (i = 0; i < localCt; i++) {
if (!TclIsVarTemporary(localPtr)) {
char *localName = localPtr->name;
- if ((nameBytes == localPtr->nameLength)
- && (strncmp(name, localName, (unsigned) nameBytes) == 0)) {
+
+ if ((nameBytes == localPtr->nameLength) &&
+ (strncmp(name,localName,(unsigned)nameBytes) == 0)) {
return i;
}
}
@@ -2262,12 +2303,12 @@ TclFindCompiledLocal(name, nameBytes, create, flags, procPtr)
/*
* Create a new variable if appropriate.
*/
-
+
if (create || (name == NULL)) {
localVar = procPtr->numCompiledLocals;
- localPtr = (CompiledLocal *) ckalloc((unsigned)
- (sizeof(CompiledLocal) - sizeof(localPtr->name)
- + nameBytes+1));
+ localPtr = (CompiledLocal *) ckalloc((unsigned)
+ (sizeof(CompiledLocal) - sizeof(localPtr->name)
+ + nameBytes + 1));
if (procPtr->firstLocalPtr == NULL) {
procPtr->firstLocalPtr = procPtr->lastLocalPtr = localPtr;
} else {
@@ -2277,7 +2318,7 @@ TclFindCompiledLocal(name, nameBytes, create, flags, procPtr)
localPtr->nextPtr = NULL;
localPtr->nameLength = nameBytes;
localPtr->frameIndex = localVar;
- localPtr->flags = flags | VAR_UNDEFINED;
+ localPtr->flags = 0;
if (name == NULL) {
localPtr->flags |= VAR_TEMPORARY;
}
@@ -2285,8 +2326,7 @@ TclFindCompiledLocal(name, nameBytes, create, flags, procPtr)
localPtr->resolveInfo = NULL;
if (name != NULL) {
- memcpy((VOID *) localPtr->name, (VOID *) name,
- (size_t) nameBytes);
+ memcpy(localPtr->name, name, (size_t) nameBytes);
}
localPtr->name[nameBytes] = '\0';
procPtr->numCompiledLocals++;
@@ -2297,167 +2337,56 @@ TclFindCompiledLocal(name, nameBytes, create, flags, procPtr)
/*
*----------------------------------------------------------------------
*
- * TclInitCompiledLocals --
- *
- * This routine is invoked in order to initialize the compiled
- * locals table for a new call frame.
- *
- * Results:
- * None.
- *
- * Side effects:
- * May invoke various name resolvers in order to determine which
- * variables are being referenced at runtime.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclInitCompiledLocals(interp, framePtr, nsPtr)
- Tcl_Interp *interp; /* Current interpreter. */
- CallFrame *framePtr; /* Call frame to initialize. */
- Namespace *nsPtr; /* Pointer to current namespace. */
-{
- register CompiledLocal *localPtr;
- Interp *iPtr = (Interp*) interp;
- Tcl_ResolvedVarInfo *vinfo, *resVarInfo;
- Var *varPtr = framePtr->compiledLocals;
- Var *resolvedVarPtr;
- ResolverScheme *resPtr;
- int result;
-
- /*
- * Initialize the array of local variables stored in the call frame.
- * Some variables may have special resolution rules. In that case,
- * we call their "resolver" procs to get our hands on the variable,
- * and we make the compiled local a link to the real variable.
- */
-
- for (localPtr = framePtr->procPtr->firstLocalPtr;
- localPtr != NULL;
- localPtr = localPtr->nextPtr) {
-
- /*
- * Check to see if this local is affected by namespace or
- * interp resolvers. The resolver to use is cached for the
- * next invocation of the procedure.
- */
-
- if (!(localPtr->flags & (VAR_ARGUMENT|VAR_TEMPORARY|VAR_RESOLVED))
- && (nsPtr->compiledVarResProc || iPtr->resolverPtr)) {
- resPtr = iPtr->resolverPtr;
-
- if (nsPtr->compiledVarResProc) {
- result = (*nsPtr->compiledVarResProc)(nsPtr->interp,
- localPtr->name, localPtr->nameLength,
- (Tcl_Namespace *) nsPtr, &vinfo);
- } else {
- result = TCL_CONTINUE;
- }
-
- while ((result == TCL_CONTINUE) && resPtr) {
- if (resPtr->compiledVarResProc) {
- result = (*resPtr->compiledVarResProc)(nsPtr->interp,
- localPtr->name, localPtr->nameLength,
- (Tcl_Namespace *) nsPtr, &vinfo);
- }
- resPtr = resPtr->nextPtr;
- }
- if (result == TCL_OK) {
- localPtr->resolveInfo = vinfo;
- localPtr->flags |= VAR_RESOLVED;
- }
- }
-
- /*
- * Now invoke the resolvers to determine the exact variables that
- * should be used.
- */
-
- resVarInfo = localPtr->resolveInfo;
- resolvedVarPtr = NULL;
-
- if (resVarInfo && resVarInfo->fetchProc) {
- resolvedVarPtr = (Var*) (*resVarInfo->fetchProc)(interp,
- resVarInfo);
- }
-
- if (resolvedVarPtr) {
- varPtr->name = localPtr->name; /* will be just '\0' if temp var */
- varPtr->nsPtr = NULL;
- varPtr->hPtr = NULL;
- varPtr->refCount = 0;
- varPtr->tracePtr = NULL;
- varPtr->searchPtr = NULL;
- varPtr->flags = 0;
- TclSetVarLink(varPtr);
- varPtr->value.linkPtr = resolvedVarPtr;
- resolvedVarPtr->refCount++;
- } else {
- varPtr->value.objPtr = NULL;
- varPtr->name = localPtr->name; /* will be just '\0' if temp var */
- varPtr->nsPtr = NULL;
- varPtr->hPtr = NULL;
- varPtr->refCount = 0;
- varPtr->tracePtr = NULL;
- varPtr->searchPtr = NULL;
- varPtr->flags = localPtr->flags;
- }
- varPtr++;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
* TclExpandCodeArray --
*
- * Procedure that uses malloc to allocate more storage for a
- * CompileEnv's code array.
+ * Procedure that uses malloc to allocate more storage for a CompileEnv's
+ * code array.
*
* Results:
- * None.
+ * None.
*
* Side effects:
- * The byte code array in *envPtr is reallocated to a new array of
- * double the size, and if envPtr->mallocedCodeArray is non-zero the
- * old array is freed. Byte codes are copied from the old array to the
- * new one.
+ * The byte code array in *envPtr is reallocated to a new array of double
+ * the size, and if envPtr->mallocedCodeArray is non-zero the old array
+ * is freed. Byte codes are copied from the old array to the new one.
*
*----------------------------------------------------------------------
*/
void
-TclExpandCodeArray(envArgPtr)
- void *envArgPtr; /* Points to the CompileEnv whose code array
+TclExpandCodeArray(
+ void *envArgPtr) /* Points to the CompileEnv whose code array
* must be enlarged. */
{
- CompileEnv *envPtr = (CompileEnv*) envArgPtr; /* Points to the CompileEnv whose code array
- * must be enlarged. */
+ CompileEnv *envPtr = (CompileEnv *) envArgPtr;
+ /* The CompileEnv containing the code array to
+ * be doubled in size. */
/*
* envPtr->codeNext is equal to envPtr->codeEnd. The currently defined
- * code bytes are stored between envPtr->codeStart and
- * (envPtr->codeNext - 1) [inclusive].
+ * code bytes are stored between envPtr->codeStart and envPtr->codeNext-1
+ * [inclusive].
*/
-
+
size_t currBytes = (envPtr->codeNext - envPtr->codeStart);
- size_t newBytes = 2*(envPtr->codeEnd - envPtr->codeStart);
- unsigned char *newPtr = (unsigned char *) ckalloc((unsigned) newBytes);
+ size_t newBytes = 2*(envPtr->codeEnd - envPtr->codeStart);
- /*
- * Copy from old code array to new, free old code array if needed, and
- * mark new code array as malloced.
- */
-
- memcpy((VOID *) newPtr, (VOID *) envPtr->codeStart, currBytes);
if (envPtr->mallocedCodeArray) {
- ckfree((char *) envPtr->codeStart);
+ envPtr->codeStart = (unsigned char *)
+ ckrealloc((char *)envPtr->codeStart, newBytes);
+ } else {
+ /*
+ * envPtr->codeStart isn't a ckalloc'd pointer, so we must
+ * code a ckrealloc equivalent for ourselves.
+ */
+ unsigned char *newPtr = (unsigned char *) ckalloc((unsigned) newBytes);
+ memcpy(newPtr, envPtr->codeStart, currBytes);
+ envPtr->codeStart = newPtr;
+ envPtr->mallocedCodeArray = 1;
}
- envPtr->codeStart = newPtr;
- envPtr->codeNext = (newPtr + currBytes);
- envPtr->codeEnd = (newPtr + newBytes);
- envPtr->mallocedCodeArray = 1;
+
+ envPtr->codeNext = (envPtr->codeStart + currBytes);
+ envPtr->codeEnd = (envPtr->codeStart + newBytes);
}
/*
@@ -2465,37 +2394,37 @@ TclExpandCodeArray(envArgPtr)
*
* EnterCmdStartData --
*
- * Registers the starting source and bytecode location of a
- * command. This information is used at runtime to map between
- * instruction pc and source locations.
+ * Registers the starting source and bytecode location of a command. This
+ * information is used at runtime to map between instruction pc and
+ * source locations.
*
* Results:
* None.
*
* Side effects:
* Inserts source and code location information into the compilation
- * environment envPtr for the command at index cmdIndex. The
- * compilation environment's CmdLocation array is grown if necessary.
+ * environment envPtr for the command at index cmdIndex. The compilation
+ * environment's CmdLocation array is grown if necessary.
*
*----------------------------------------------------------------------
*/
static void
-EnterCmdStartData(envPtr, cmdIndex, srcOffset, codeOffset)
- CompileEnv *envPtr; /* Points to the compilation environment
+EnterCmdStartData(
+ CompileEnv *envPtr, /* Points to the compilation environment
* structure in which to enter command
* location information. */
- int cmdIndex; /* Index of the command whose start data
- * is being set. */
- int srcOffset; /* Offset of first char of the command. */
- int codeOffset; /* Offset of first byte of command code. */
+ int cmdIndex, /* Index of the command whose start data is
+ * being set. */
+ int srcOffset, /* Offset of first char of the command. */
+ int codeOffset) /* Offset of first byte of command code. */
{
CmdLocation *cmdLocPtr;
-
+
if ((cmdIndex < 0) || (cmdIndex >= envPtr->numCommands)) {
- panic("EnterCmdStartData: bad command index %d\n", cmdIndex);
+ Tcl_Panic("EnterCmdStartData: bad command index %d", cmdIndex);
}
-
+
if (cmdIndex >= envPtr->cmdMapEnd) {
/*
* Expand the command location array by allocating more storage from
@@ -2504,28 +2433,29 @@ EnterCmdStartData(envPtr, cmdIndex, srcOffset, codeOffset)
*/
size_t currElems = envPtr->cmdMapEnd;
- size_t newElems = 2*currElems;
+ size_t newElems = 2*currElems;
size_t currBytes = currElems * sizeof(CmdLocation);
- size_t newBytes = newElems * sizeof(CmdLocation);
- CmdLocation *newPtr = (CmdLocation *) ckalloc((unsigned) newBytes);
-
- /*
- * Copy from old command location array to new, free old command
- * location array if needed, and mark new array as malloced.
- */
-
- memcpy((VOID *) newPtr, (VOID *) envPtr->cmdMapPtr, currBytes);
+ size_t newBytes = newElems * sizeof(CmdLocation);
+
if (envPtr->mallocedCmdMap) {
- ckfree((char *) envPtr->cmdMapPtr);
+ envPtr->cmdMapPtr = (CmdLocation *)
+ ckrealloc((char *) envPtr->cmdMapPtr, newBytes);
+ } else {
+ /*
+ * envPtr->cmdMapPtr isn't a ckalloc'd pointer, so we must
+ * code a ckrealloc equivalent for ourselves.
+ */
+ CmdLocation *newPtr = (CmdLocation *) ckalloc((unsigned) newBytes);
+ memcpy(newPtr, envPtr->cmdMapPtr, currBytes);
+ envPtr->cmdMapPtr = newPtr;
+ envPtr->mallocedCmdMap = 1;
}
- envPtr->cmdMapPtr = (CmdLocation *) newPtr;
envPtr->cmdMapEnd = newElems;
- envPtr->mallocedCmdMap = 1;
}
if (cmdIndex > 0) {
if (codeOffset < envPtr->cmdMapPtr[cmdIndex-1].codeOffset) {
- panic("EnterCmdStartData: cmd map not sorted by code offset");
+ Tcl_Panic("EnterCmdStartData: cmd map not sorted by code offset");
}
}
@@ -2550,32 +2480,32 @@ EnterCmdStartData(envPtr, cmdIndex, srcOffset, codeOffset)
*
* Side effects:
* Inserts source and code length information into the compilation
- * environment envPtr for the command at index cmdIndex. Starting
- * source and bytecode information for the command must already
- * have been registered.
+ * environment envPtr for the command at index cmdIndex. Starting source
+ * and bytecode information for the command must already have been
+ * registered.
*
*----------------------------------------------------------------------
*/
static void
-EnterCmdExtentData(envPtr, cmdIndex, numSrcBytes, numCodeBytes)
- CompileEnv *envPtr; /* Points to the compilation environment
+EnterCmdExtentData(
+ CompileEnv *envPtr, /* Points to the compilation environment
* structure in which to enter command
* location information. */
- int cmdIndex; /* Index of the command whose source and
- * code length data is being set. */
- int numSrcBytes; /* Number of command source chars. */
- int numCodeBytes; /* Offset of last byte of command code. */
+ int cmdIndex, /* Index of the command whose source and code
+ * length data is being set. */
+ int numSrcBytes, /* Number of command source chars. */
+ int numCodeBytes) /* Offset of last byte of command code. */
{
CmdLocation *cmdLocPtr;
if ((cmdIndex < 0) || (cmdIndex >= envPtr->numCommands)) {
- panic("EnterCmdExtentData: bad command index %d\n", cmdIndex);
+ Tcl_Panic("EnterCmdExtentData: bad command index %d", cmdIndex);
}
-
+
if (cmdIndex > envPtr->cmdMapEnd) {
- panic("EnterCmdExtentData: missing start data for command %d\n",
- cmdIndex);
+ Tcl_Panic("EnterCmdExtentData: missing start data for command %d",
+ cmdIndex);
}
cmdLocPtr = &(envPtr->cmdMapPtr[cmdIndex]);
@@ -2583,105 +2513,86 @@ EnterCmdExtentData(envPtr, cmdIndex, numSrcBytes, numCodeBytes)
cmdLocPtr->numCodeBytes = numCodeBytes;
}
-#ifdef TCL_TIP280
/*
*----------------------------------------------------------------------
* TIP #280
*
* EnterCmdWordData --
*
- * Registers the lines for the words of a command. This information
- * is used at runtime by 'info frame'.
+ * Registers the lines for the words of a command. This information is
+ * used at runtime by 'info frame'.
*
* Results:
* None.
*
* Side effects:
- * Inserts word location information into the compilation
- * environment envPtr for the command at index cmdIndex. The
- * compilation environment's ExtCmdLoc.ECL array is grown if necessary.
+ * Inserts word location information into the compilation environment
+ * envPtr for the command at index cmdIndex. The compilation
+ * environment's ExtCmdLoc.ECL array is grown if necessary.
*
*----------------------------------------------------------------------
*/
static void
-EnterCmdWordData(eclPtr, srcOffset, tokenPtr, cmd, len, numWords, line, clNext, wlines, envPtr)
- ExtCmdLoc *eclPtr; /* Points to the map environment
- * structure in which to enter command
- * location information. */
- int srcOffset; /* Offset of first char of the command. */
- Tcl_Token* tokenPtr;
- CONST char* cmd;
- int len;
- int numWords;
- int line;
- int* clNext;
- int** wlines;
- CompileEnv* envPtr;
-{
- ECL* ePtr;
- int wordIdx;
- CONST char* last;
- int wordLine;
- int* wordNext;
- int* wwlines;
+EnterCmdWordData(
+ ExtCmdLoc *eclPtr, /* Points to the map environment structure in
+ * which to enter command location
+ * information. */
+ int srcOffset, /* Offset of first char of the command. */
+ Tcl_Token *tokenPtr,
+ const char *cmd,
+ int len,
+ int numWords,
+ int line,
+ int* clNext,
+ int **wlines,
+ CompileEnv* envPtr)
+{
+ ECL *ePtr;
+ const char *last;
+ int wordIdx, wordLine, *wwlines;
+ int* wordNext;
if (eclPtr->nuloc >= eclPtr->nloc) {
/*
- * Expand the ECL array by allocating more storage from the
- * heap. The currently allocated ECL entries are stored from
- * eclPtr->loc[0] up to eclPtr->loc[eclPtr->nuloc-1] (inclusive).
+ * Expand the ECL array by allocating more storage from the heap. The
+ * currently allocated ECL entries are stored from eclPtr->loc[0] up
+ * to eclPtr->loc[eclPtr->nuloc-1] (inclusive).
*/
size_t currElems = eclPtr->nloc;
- size_t newElems = (currElems ? 2*currElems : 1);
- size_t currBytes = currElems * sizeof(ECL);
- size_t newBytes = newElems * sizeof(ECL);
- ECL * newPtr = (ECL *) ckalloc((unsigned) newBytes);
+ size_t newElems = (currElems ? 2*currElems : 1);
+ size_t newBytes = newElems * sizeof(ECL);
- /*
- * Copy from old ECL array to new, free old ECL array if
- * needed.
- */
-
- if (currBytes) {
- memcpy((VOID *) newPtr, (VOID *) eclPtr->loc, currBytes);
- }
- if (eclPtr->loc != NULL) {
- ckfree((char *) eclPtr->loc);
- }
- eclPtr->loc = (ECL *) newPtr;
+ eclPtr->loc = (ECL *) ckrealloc((char *)(eclPtr->loc), newBytes);
eclPtr->nloc = newElems;
}
- ePtr = &eclPtr->loc [eclPtr->nuloc];
+ ePtr = &eclPtr->loc[eclPtr->nuloc];
ePtr->srcOffset = srcOffset;
- ePtr->line = (int*) ckalloc (numWords * sizeof (int));
- ePtr->next = (int**) ckalloc (numWords * sizeof (int*));
- ePtr->nline = numWords;
- wwlines = (int*) ckalloc (numWords * sizeof (int));
+ ePtr->line = (int *) ckalloc(numWords * sizeof(int));
+ ePtr->next = (int**) ckalloc (numWords * sizeof (int*));
+ ePtr->nline = numWords;
+ wwlines = (int *) ckalloc(numWords * sizeof(int));
- last = cmd;
+ last = cmd;
wordLine = line;
wordNext = clNext;
- for (wordIdx = 0;
- wordIdx < numWords;
- wordIdx++, tokenPtr += (tokenPtr->numComponents + 1)) {
+ for (wordIdx=0 ; wordIdx<numWords;
+ wordIdx++, tokenPtr += tokenPtr->numComponents + 1) {
TclAdvanceLines (&wordLine, last, tokenPtr->start);
TclAdvanceContinuations (&wordLine, &wordNext,
tokenPtr->start - envPtr->source);
- wwlines [wordIdx] = (TclWordKnownAtCompileTime (tokenPtr)
- ? wordLine
- : -1);
- ePtr->line [wordIdx] = wordLine;
- ePtr->next [wordIdx] = wordNext;
+ wwlines[wordIdx] =
+ (TclWordKnownAtCompileTime(tokenPtr, NULL) ? wordLine : -1);
+ ePtr->line[wordIdx] = wordLine;
+ ePtr->next[wordIdx] = wordNext;
last = tokenPtr->start;
}
*wlines = wwlines;
eclPtr->nuloc ++;
}
-#endif
/*
*----------------------------------------------------------------------
@@ -2695,55 +2606,53 @@ EnterCmdWordData(eclPtr, srcOffset, tokenPtr, cmd, len, numWords, line, clNext,
* Returns the index for the newly created ExceptionRange.
*
* Side effects:
- * If there is not enough room in the CompileEnv's ExceptionRange
- * array, the array in expanded: a new array of double the size is
- * allocated, if envPtr->mallocedExceptArray is non-zero the old
- * array is freed, and ExceptionRange entries are copied from the old
- * array to the new one.
+ * If there is not enough room in the CompileEnv's ExceptionRange array,
+ * the array in expanded: a new array of double the size is allocated, if
+ * envPtr->mallocedExceptArray is non-zero the old array is freed, and
+ * ExceptionRange entries are copied from the old array to the new one.
*
*----------------------------------------------------------------------
*/
int
-TclCreateExceptRange(type, envPtr)
- ExceptionRangeType type; /* The kind of ExceptionRange desired. */
- register CompileEnv *envPtr;/* Points to CompileEnv for which to
- * create a new ExceptionRange structure. */
+TclCreateExceptRange(
+ ExceptionRangeType type, /* The kind of ExceptionRange desired. */
+ register CompileEnv *envPtr)/* Points to CompileEnv for which to create a
+ * new ExceptionRange structure. */
{
register ExceptionRange *rangePtr;
int index = envPtr->exceptArrayNext;
-
+
if (index >= envPtr->exceptArrayEnd) {
- /*
+ /*
* Expand the ExceptionRange array. The currently allocated entries
* are stored between elements 0 and (envPtr->exceptArrayNext - 1)
* [inclusive].
*/
-
+
size_t currBytes =
- envPtr->exceptArrayNext * sizeof(ExceptionRange);
+ envPtr->exceptArrayNext * sizeof(ExceptionRange);
int newElems = 2*envPtr->exceptArrayEnd;
size_t newBytes = newElems * sizeof(ExceptionRange);
- ExceptionRange *newPtr = (ExceptionRange *)
- ckalloc((unsigned) newBytes);
-
- /*
- * Copy from old ExceptionRange array to new, free old
- * ExceptionRange array if needed, and mark the new ExceptionRange
- * array as malloced.
- */
-
- memcpy((VOID *) newPtr, (VOID *) envPtr->exceptArrayPtr,
- currBytes);
+
if (envPtr->mallocedExceptArray) {
- ckfree((char *) envPtr->exceptArrayPtr);
+ envPtr->exceptArrayPtr = (ExceptionRange *)
+ ckrealloc((char *)(envPtr->exceptArrayPtr), newBytes);
+ } else {
+ /*
+ * envPtr->exceptArrayPtr isn't a ckalloc'd pointer, so we must
+ * code a ckrealloc equivalent for ourselves.
+ */
+ ExceptionRange *newPtr = (ExceptionRange *)
+ ckalloc((unsigned) newBytes);
+ memcpy(newPtr, envPtr->exceptArrayPtr, currBytes);
+ envPtr->exceptArrayPtr = newPtr;
+ envPtr->mallocedExceptArray = 1;
}
- envPtr->exceptArrayPtr = (ExceptionRange *) newPtr;
envPtr->exceptArrayEnd = newElems;
- envPtr->mallocedExceptArray = 1;
}
envPtr->exceptArrayNext++;
-
+
rangePtr = &(envPtr->exceptArrayPtr[index]);
rangePtr->type = type;
rangePtr->nestingLevel = envPtr->exceptDepth;
@@ -2760,8 +2669,8 @@ TclCreateExceptRange(type, envPtr)
*
* TclCreateAuxData --
*
- * Procedure that allocates and initializes a new AuxData structure in
- * a CompileEnv's array of compilation auxiliary data records. These
+ * Procedure that allocates and initializes a new AuxData structure in a
+ * CompileEnv's array of compilation auxiliary data records. These
* AuxData records hold information created during compilation by
* CompileProcs and used by instructions during execution.
*
@@ -2769,56 +2678,57 @@ TclCreateExceptRange(type, envPtr)
* Returns the index for the newly created AuxData structure.
*
* Side effects:
- * If there is not enough room in the CompileEnv's AuxData array,
- * the AuxData array in expanded: a new array of double the size
- * is allocated, if envPtr->mallocedAuxDataArray is non-zero
- * the old array is freed, and AuxData entries are copied from
- * the old array to the new one.
+ * If there is not enough room in the CompileEnv's AuxData array, the
+ * AuxData array in expanded: a new array of double the size is
+ * allocated, if envPtr->mallocedAuxDataArray is non-zero the old array
+ * is freed, and AuxData entries are copied from the old array to the new
+ * one.
*
*----------------------------------------------------------------------
*/
int
-TclCreateAuxData(clientData, typePtr, envPtr)
- ClientData clientData; /* The compilation auxiliary data to store
- * in the new aux data record. */
- AuxDataType *typePtr; /* Pointer to the type to attach to this AuxData */
- register CompileEnv *envPtr;/* Points to the CompileEnv for which a new
+TclCreateAuxData(
+ ClientData clientData, /* The compilation auxiliary data to store in
+ * the new aux data record. */
+ AuxDataType *typePtr, /* Pointer to the type to attach to this
+ * AuxData */
+ register CompileEnv *envPtr)/* Points to the CompileEnv for which a new
* aux data structure is to be allocated. */
{
int index; /* Index for the new AuxData structure. */
register AuxData *auxDataPtr;
/* Points to the new AuxData structure */
-
+
index = envPtr->auxDataArrayNext;
if (index >= envPtr->auxDataArrayEnd) {
- /*
+ /*
* Expand the AuxData array. The currently allocated entries are
* stored between elements 0 and (envPtr->auxDataArrayNext - 1)
* [inclusive].
*/
-
+
size_t currBytes = envPtr->auxDataArrayNext * sizeof(AuxData);
int newElems = 2*envPtr->auxDataArrayEnd;
size_t newBytes = newElems * sizeof(AuxData);
- AuxData *newPtr = (AuxData *) ckalloc((unsigned) newBytes);
-
- /*
- * Copy from old AuxData array to new, free old AuxData array if
- * needed, and mark the new AuxData array as malloced.
- */
-
- memcpy((VOID *) newPtr, (VOID *) envPtr->auxDataArrayPtr,
- currBytes);
+
if (envPtr->mallocedAuxDataArray) {
- ckfree((char *) envPtr->auxDataArrayPtr);
+ envPtr->auxDataArrayPtr = (AuxData *)
+ ckrealloc((char *)(envPtr->auxDataArrayPtr), newBytes);
+ } else {
+ /*
+ * envPtr->auxDataArrayPtr isn't a ckalloc'd pointer, so we must
+ * code a ckrealloc equivalent for ourselves.
+ */
+ AuxData *newPtr = (AuxData *) ckalloc((unsigned) newBytes);
+ memcpy(newPtr, envPtr->auxDataArrayPtr, currBytes);
+ envPtr->auxDataArrayPtr = newPtr;
+ envPtr->mallocedAuxDataArray = 1;
}
- envPtr->auxDataArrayPtr = newPtr;
envPtr->auxDataArrayEnd = newElems;
- envPtr->mallocedAuxDataArray = 1;
}
envPtr->auxDataArrayNext++;
-
+
auxDataPtr = &(envPtr->auxDataArrayPtr[index]);
auxDataPtr->clientData = clientData;
auxDataPtr->type = typePtr;
@@ -2830,8 +2740,8 @@ TclCreateAuxData(clientData, typePtr, envPtr)
*
* TclInitJumpFixupArray --
*
- * Initializes a JumpFixupArray structure to hold some number of
- * jump fixup entries.
+ * Initializes a JumpFixupArray structure to hold some number of jump
+ * fixup entries.
*
* Results:
* None.
@@ -2843,10 +2753,10 @@ TclCreateAuxData(clientData, typePtr, envPtr)
*/
void
-TclInitJumpFixupArray(fixupArrayPtr)
- register JumpFixupArray *fixupArrayPtr;
- /* Points to the JumpFixupArray structure
- * to initialize. */
+TclInitJumpFixupArray(
+ register JumpFixupArray *fixupArrayPtr)
+ /* Points to the JumpFixupArray structure to
+ * initialize. */
{
fixupArrayPtr->fixup = fixupArrayPtr->staticFixupSpace;
fixupArrayPtr->next = 0;
@@ -2859,8 +2769,8 @@ TclInitJumpFixupArray(fixupArrayPtr)
*
* TclExpandJumpFixupArray --
*
- * Procedure that uses malloc to allocate more storage for a
- * jump fixup array.
+ * Procedure that uses malloc to allocate more storage for a jump fixup
+ * array.
*
* Results:
* None.
@@ -2868,41 +2778,42 @@ TclInitJumpFixupArray(fixupArrayPtr)
* Side effects:
* The jump fixup array in *fixupArrayPtr is reallocated to a new array
* of double the size, and if fixupArrayPtr->mallocedArray is non-zero
- * the old array is freed. Jump fixup structures are copied from the
- * old array to the new one.
+ * the old array is freed. Jump fixup structures are copied from the old
+ * array to the new one.
*
*----------------------------------------------------------------------
*/
void
-TclExpandJumpFixupArray(fixupArrayPtr)
- register JumpFixupArray *fixupArrayPtr;
- /* Points to the JumpFixupArray structure
- * to enlarge. */
+TclExpandJumpFixupArray(
+ register JumpFixupArray *fixupArrayPtr)
+ /* Points to the JumpFixupArray structure
+ * to enlarge. */
{
/*
- * The currently allocated jump fixup entries are stored from fixup[0]
- * up to fixup[fixupArrayPtr->fixupNext] (*not* inclusive). We assume
+ * The currently allocated jump fixup entries are stored from fixup[0] up
+ * to fixup[fixupArrayPtr->fixupNext] (*not* inclusive). We assume
* fixupArrayPtr->fixupNext is equal to fixupArrayPtr->fixupEnd.
*/
size_t currBytes = fixupArrayPtr->next * sizeof(JumpFixup);
int newElems = 2*(fixupArrayPtr->end + 1);
size_t newBytes = newElems * sizeof(JumpFixup);
- JumpFixup *newPtr = (JumpFixup *) ckalloc((unsigned) newBytes);
- /*
- * Copy from the old array to new, free the old array if needed,
- * and mark the new array as malloced.
- */
-
- memcpy((VOID *) newPtr, (VOID *) fixupArrayPtr->fixup, currBytes);
if (fixupArrayPtr->mallocedArray) {
- ckfree((char *) fixupArrayPtr->fixup);
+ fixupArrayPtr->fixup = (JumpFixup *)
+ ckrealloc((char *)(fixupArrayPtr->fixup), newBytes);
+ } else {
+ /*
+ * fixupArrayPtr->fixup isn't a ckalloc'd pointer, so we must
+ * code a ckrealloc equivalent for ourselves.
+ */
+ JumpFixup *newPtr = (JumpFixup *) ckalloc((unsigned) newBytes);
+ memcpy(newPtr, fixupArrayPtr->fixup, currBytes);
+ fixupArrayPtr->fixup = newPtr;
+ fixupArrayPtr->mallocedArray = 1;
}
- fixupArrayPtr->fixup = (JumpFixup *) newPtr;
fixupArrayPtr->end = newElems;
- fixupArrayPtr->mallocedArray = 1;
}
/*
@@ -2922,10 +2833,10 @@ TclExpandJumpFixupArray(fixupArrayPtr)
*/
void
-TclFreeJumpFixupArray(fixupArrayPtr)
- register JumpFixupArray *fixupArrayPtr;
- /* Points to the JumpFixupArray structure
- * to free. */
+TclFreeJumpFixupArray(
+ register JumpFixupArray *fixupArrayPtr)
+ /* Points to the JumpFixupArray structure to
+ * free. */
{
if (fixupArrayPtr->mallocedArray) {
ckfree((char *) fixupArrayPtr->fixup);
@@ -2940,27 +2851,27 @@ TclFreeJumpFixupArray(fixupArrayPtr)
* Procedure to emit a two-byte forward jump of kind "jumpType". Since
* the jump may later have to be grown to five bytes if the jump target
* is more than, say, 127 bytes away, this procedure also initializes a
- * JumpFixup record with information about the jump.
+ * JumpFixup record with information about the jump.
*
* Results:
* None.
*
* Side effects:
- * The JumpFixup record pointed to by "jumpFixupPtr" is initialized
- * with information needed later if the jump is to be grown. Also,
- * a two byte jump of the designated type is emitted at the current
- * point in the bytecode stream.
+ * The JumpFixup record pointed to by "jumpFixupPtr" is initialized with
+ * information needed later if the jump is to be grown. Also, a two byte
+ * jump of the designated type is emitted at the current point in the
+ * bytecode stream.
*
*----------------------------------------------------------------------
*/
void
-TclEmitForwardJump(envPtr, jumpType, jumpFixupPtr)
- CompileEnv *envPtr; /* Points to the CompileEnv structure that
+TclEmitForwardJump(
+ CompileEnv *envPtr, /* Points to the CompileEnv structure that
* holds the resulting instruction. */
- TclJumpType jumpType; /* Indicates the kind of jump: if true or
+ TclJumpType jumpType, /* Indicates the kind of jump: if true or
* false or unconditional. */
- JumpFixup *jumpFixupPtr; /* Points to the JumpFixup structure to
+ JumpFixup *jumpFixupPtr) /* Points to the JumpFixup structure to
* initialize with information about this
* forward jump. */
{
@@ -2968,15 +2879,15 @@ TclEmitForwardJump(envPtr, jumpType, jumpFixupPtr)
* Initialize the JumpFixup structure:
* - codeOffset is offset of first byte of jump below
* - cmdIndex is index of the command after the current one
- * - exceptIndex is the index of the first ExceptionRange after
- * the current one.
+ * - exceptIndex is the index of the first ExceptionRange after the
+ * current one.
*/
-
+
jumpFixupPtr->jumpType = jumpType;
jumpFixupPtr->codeOffset = (envPtr->codeNext - envPtr->codeStart);
jumpFixupPtr->cmdIndex = envPtr->numCommands;
jumpFixupPtr->exceptIndex = envPtr->exceptArrayNext;
-
+
switch (jumpType) {
case TCL_UNCONDITIONAL_JUMP:
TclEmitInstInt1(INST_JUMP1, 0, envPtr);
@@ -2995,43 +2906,41 @@ TclEmitForwardJump(envPtr, jumpType, jumpFixupPtr)
*
* TclFixupForwardJump --
*
- * Procedure that updates a previously-emitted forward jump to jump
- * a specified number of bytes, "jumpDist". If necessary, the jump is
- * grown from two to five bytes; this is done if the jump distance is
- * greater than "distThreshold" (normally 127 bytes). The jump is
- * described by a JumpFixup record previously initialized by
- * TclEmitForwardJump.
+ * Procedure that updates a previously-emitted forward jump to jump a
+ * specified number of bytes, "jumpDist". If necessary, the jump is grown
+ * from two to five bytes; this is done if the jump distance is greater
+ * than "distThreshold" (normally 127 bytes). The jump is described by a
+ * JumpFixup record previously initialized by TclEmitForwardJump.
*
* Results:
* 1 if the jump was grown and subsequent instructions had to be moved;
- * otherwise 0. This result is returned to allow callers to update
- * any additional code offsets they may hold.
+ * otherwise 0. This result is returned to allow callers to update any
+ * additional code offsets they may hold.
*
* Side effects:
* The jump may be grown and subsequent instructions moved. If this
* happens, the code offsets for any commands and any ExceptionRange
- * records between the jump and the current code address will be
- * updated to reflect the moved code. Also, the bytecode instruction
- * array in the CompileEnv structure may be grown and reallocated.
+ * records between the jump and the current code address will be updated
+ * to reflect the moved code. Also, the bytecode instruction array in the
+ * CompileEnv structure may be grown and reallocated.
*
*----------------------------------------------------------------------
*/
int
-TclFixupForwardJump(envPtr, jumpFixupPtr, jumpDist, distThreshold)
- CompileEnv *envPtr; /* Points to the CompileEnv structure that
+TclFixupForwardJump(
+ CompileEnv *envPtr, /* Points to the CompileEnv structure that
* holds the resulting instruction. */
- JumpFixup *jumpFixupPtr; /* Points to the JumpFixup structure that
+ JumpFixup *jumpFixupPtr, /* Points to the JumpFixup structure that
* describes the forward jump. */
- int jumpDist; /* Jump distance to set in jump
- * instruction. */
- int distThreshold; /* Maximum distance before the two byte
- * jump is grown to five bytes. */
+ int jumpDist, /* Jump distance to set in jump instr. */
+ int distThreshold) /* Maximum distance before the two byte jump
+ * is grown to five bytes. */
{
unsigned char *jumpPc, *p;
int firstCmd, lastCmd, firstRange, lastRange, k;
- unsigned int numBytes;
-
+ unsigned numBytes;
+
if (jumpDist <= distThreshold) {
jumpPc = (envPtr->codeStart + jumpFixupPtr->codeOffset);
switch (jumpFixupPtr->jumpType) {
@@ -3049,14 +2958,14 @@ TclFixupForwardJump(envPtr, jumpFixupPtr, jumpDist, distThreshold)
}
/*
- * We must grow the jump then move subsequent instructions down.
- * Note that if we expand the space for generated instructions,
- * code addresses might change; be careful about updating any of
- * these addresses held in variables.
+ * We must grow the jump then move subsequent instructions down. Note that
+ * if we expand the space for generated instructions, code addresses might
+ * change; be careful about updating any of these addresses held in
+ * variables.
*/
-
+
if ((envPtr->codeNext + 3) > envPtr->codeEnd) {
- TclExpandCodeArray(envPtr);
+ TclExpandCodeArray(envPtr);
}
jumpPc = (envPtr->codeStart + jumpFixupPtr->codeOffset);
numBytes = envPtr->codeNext-jumpPc-2;
@@ -3076,26 +2985,26 @@ TclFixupForwardJump(envPtr, jumpFixupPtr, jumpDist, distThreshold)
TclUpdateInstInt4AtPc(INST_JUMP_FALSE4, jumpDist, jumpPc);
break;
}
-
+
/*
- * Adjust the code offsets for any commands and any ExceptionRange
- * records between the jump and the current code address.
+ * Adjust the code offsets for any commands and any ExceptionRange records
+ * between the jump and the current code address.
*/
-
+
firstCmd = jumpFixupPtr->cmdIndex;
- lastCmd = (envPtr->numCommands - 1);
+ lastCmd = (envPtr->numCommands - 1);
if (firstCmd < lastCmd) {
for (k = firstCmd; k <= lastCmd; k++) {
(envPtr->cmdMapPtr[k]).codeOffset += 3;
}
}
-
+
firstRange = jumpFixupPtr->exceptIndex;
- lastRange = (envPtr->exceptArrayNext - 1);
+ lastRange = (envPtr->exceptArrayNext - 1);
for (k = firstRange; k <= lastRange; k++) {
ExceptionRange *rangePtr = &(envPtr->exceptArrayPtr[k]);
rangePtr->codeOffset += 3;
-
+
switch (rangePtr->type) {
case LOOP_EXCEPTION_RANGE:
rangePtr->breakOffset += 3;
@@ -3107,10 +3016,74 @@ TclFixupForwardJump(envPtr, jumpFixupPtr, jumpDist, distThreshold)
rangePtr->catchOffset += 3;
break;
default:
- panic("TclFixupForwardJump: bad ExceptionRange type %d\n",
- rangePtr->type);
+ Tcl_Panic("TclFixupForwardJump: bad ExceptionRange type %d",
+ rangePtr->type);
}
}
+
+ /*
+ * TIP #280: Adjust the mapping from PC values to the per-command
+ * information about arguments and their line numbers.
+ *
+ * Note: We cannot simply remove an out-of-date entry and then reinsert
+ * with the proper PC, because then we might overwrite another entry which
+ * was at that location. Therefore we pull (copy + delete) all effected
+ * entries (beyond the fixed PC) into an array, update them there, and at
+ * last reinsert them all.
+ */
+
+ {
+ ExtCmdLoc* eclPtr = envPtr->extCmdMapPtr;
+
+ /* A helper structure */
+
+ typedef struct {
+ int pc;
+ int cmd;
+ } MAP;
+
+ /*
+ * And the helper array. At most the whole hashtable is placed into
+ * this.
+ */
+
+ MAP *map = (MAP*) ckalloc (sizeof(MAP) * eclPtr->litInfo.numEntries);
+
+ Tcl_HashSearch hSearch;
+ Tcl_HashEntry* hPtr;
+ int n, k, isnew;
+
+ /*
+ * Phase I: Locate the affected entries, and save them in adjusted
+ * form to the array. This removes them from the hash.
+ */
+
+ for (n = 0, hPtr = Tcl_FirstHashEntry(&eclPtr->litInfo, &hSearch);
+ hPtr != NULL;
+ hPtr = Tcl_NextHashEntry(&hSearch)) {
+
+ map [n].cmd = PTR2INT(Tcl_GetHashValue(hPtr));
+ map [n].pc = PTR2INT(Tcl_GetHashKey (&eclPtr->litInfo,hPtr));
+
+ if (map[n].pc >= (jumpFixupPtr->codeOffset + 2)) {
+ Tcl_DeleteHashEntry(hPtr);
+ map [n].pc += 3;
+ n++;
+ }
+ }
+
+ /*
+ * Phase II: Re-insert the modified entries into the hash.
+ */
+
+ for (k=0;k<n;k++) {
+ hPtr = Tcl_CreateHashEntry(&eclPtr->litInfo, INT2PTR(map[k].pc), &isnew);
+ Tcl_SetHashValue(hPtr, INT2PTR(map[k].cmd));
+ }
+
+ ckfree ((char *) map);
+ }
+
return 1; /* the jump was grown */
}
@@ -3119,9 +3092,9 @@ TclFixupForwardJump(envPtr, jumpFixupPtr, jumpDist, distThreshold)
*
* TclGetInstructionTable --
*
- * Returns a pointer to the table describing Tcl bytecode instructions.
- * This procedure is defined so that clients can access the pointer from
- * outside the TCL DLLs.
+ * Returns a pointer to the table describing Tcl bytecode instructions.
+ * This procedure is defined so that clients can access the pointer from
+ * outside the TCL DLLs.
*
* Results:
* Returns a pointer to the global instruction table, same as the
@@ -3134,7 +3107,7 @@ TclFixupForwardJump(envPtr, jumpFixupPtr, jumpDist, distThreshold)
*/
void * /* == InstructionDesc* == */
-TclGetInstructionTable()
+TclGetInstructionTable(void)
{
return &tclInstructionTable[0];
}
@@ -3144,32 +3117,32 @@ TclGetInstructionTable()
*
* TclRegisterAuxDataType --
*
- * This procedure is called to register a new AuxData type
- * in the table of all AuxData types supported by Tcl.
+ * This procedure is called to register a new AuxData type in the table
+ * of all AuxData types supported by Tcl.
*
* Results:
* None.
*
* Side effects:
* The type is registered in the AuxData type table. If there was already
- * a type with the same name as in typePtr, it is replaced with the
- * new type.
+ * a type with the same name as in typePtr, it is replaced with the new
+ * type.
*
*--------------------------------------------------------------
*/
void
-TclRegisterAuxDataType(typePtr)
- AuxDataType *typePtr; /* Information about object type;
- * storage must be statically
- * allocated (must live forever). */
+TclRegisterAuxDataType(
+ AuxDataType *typePtr) /* Information about object type; storage must
+ * be statically allocated (must live forever;
+ * will not be deallocated). */
{
register Tcl_HashEntry *hPtr;
- int new;
+ int isNew;
Tcl_MutexLock(&tableMutex);
if (!auxDataTypeTableInitialized) {
- TclInitAuxDataTypeTable();
+ TclInitAuxDataTypeTable();
}
/*
@@ -3177,17 +3150,17 @@ TclRegisterAuxDataType(typePtr)
*/
hPtr = Tcl_FindHashEntry(&auxDataTypeTable, typePtr->name);
- if (hPtr != (Tcl_HashEntry *) NULL) {
- Tcl_DeleteHashEntry(hPtr);
+ if (hPtr != NULL) {
+ Tcl_DeleteHashEntry(hPtr);
}
/*
* Now insert the new object type.
*/
- hPtr = Tcl_CreateHashEntry(&auxDataTypeTable, typePtr->name, &new);
- if (new) {
- Tcl_SetHashValue(hPtr, typePtr);
+ hPtr = Tcl_CreateHashEntry(&auxDataTypeTable, typePtr->name, &isNew);
+ if (isNew) {
+ Tcl_SetHashValue(hPtr, typePtr);
}
Tcl_MutexUnlock(&tableMutex);
}
@@ -3210,20 +3183,20 @@ TclRegisterAuxDataType(typePtr)
*/
AuxDataType *
-TclGetAuxDataType(typeName)
- char *typeName; /* Name of AuxData type to look up. */
+TclGetAuxDataType(
+ char *typeName) /* Name of AuxData type to look up. */
{
register Tcl_HashEntry *hPtr;
AuxDataType *typePtr = NULL;
Tcl_MutexLock(&tableMutex);
if (!auxDataTypeTableInitialized) {
- TclInitAuxDataTypeTable();
+ TclInitAuxDataTypeTable();
}
hPtr = Tcl_FindHashEntry(&auxDataTypeTable, typeName);
- if (hPtr != (Tcl_HashEntry *) NULL) {
- typePtr = (AuxDataType *) Tcl_GetHashValue(hPtr);
+ if (hPtr != NULL) {
+ typePtr = (AuxDataType *) Tcl_GetHashValue(hPtr);
}
Tcl_MutexUnlock(&tableMutex);
@@ -3235,8 +3208,8 @@ TclGetAuxDataType(typeName)
*
* TclInitAuxDataTypeTable --
*
- * This procedure is invoked to perform once-only initialization of
- * the AuxData type table. It also registers the AuxData types defined in
+ * This procedure is invoked to perform once-only initialization of the
+ * AuxData type table. It also registers the AuxData types defined in
* this file.
*
* Results:
@@ -3250,7 +3223,7 @@ TclGetAuxDataType(typeName)
*/
void
-TclInitAuxDataTypeTable()
+TclInitAuxDataTypeTable(void)
{
/*
* The table mutex must already be held before this routine is invoked.
@@ -3260,10 +3233,11 @@ TclInitAuxDataTypeTable()
Tcl_InitHashTable(&auxDataTypeTable, TCL_STRING_KEYS);
/*
- * There is only one AuxData type at this time, so register it here.
+ * There are only two AuxData type at this time, so register them here.
*/
TclRegisterAuxDataType(&tclForeachInfoType);
+ TclRegisterAuxDataType(&tclJumptableInfoType);
}
/*
@@ -3271,10 +3245,10 @@ TclInitAuxDataTypeTable()
*
* TclFinalizeAuxDataTypeTable --
*
- * This procedure is called by Tcl_Finalize after all exit handlers
- * have been run to free up storage associated with the table of AuxData
- * types. This procedure is called by TclFinalizeExecution() which
- * is called by Tcl_Finalize().
+ * This procedure is called by Tcl_Finalize after all exit handlers have
+ * been run to free up storage associated with the table of AuxData
+ * types. This procedure is called by TclFinalizeExecution() which is
+ * called by Tcl_Finalize().
*
* Results:
* None.
@@ -3286,12 +3260,12 @@ TclInitAuxDataTypeTable()
*/
void
-TclFinalizeAuxDataTypeTable()
+TclFinalizeAuxDataTypeTable(void)
{
Tcl_MutexLock(&tableMutex);
if (auxDataTypeTableInitialized) {
- Tcl_DeleteHashTable(&auxDataTypeTable);
- auxDataTypeTableInitialized = 0;
+ Tcl_DeleteHashTable(&auxDataTypeTable);
+ auxDataTypeTableInitialized = 0;
}
Tcl_MutexUnlock(&tableMutex);
}
@@ -3314,18 +3288,18 @@ TclFinalizeAuxDataTypeTable()
*/
static int
-GetCmdLocEncodingSize(envPtr)
- CompileEnv *envPtr; /* Points to compilation environment
- * structure containing the CmdLocation
- * structure to encode. */
+GetCmdLocEncodingSize(
+ CompileEnv *envPtr) /* Points to compilation environment structure
+ * containing the CmdLocation structure to
+ * encode. */
{
register CmdLocation *mapPtr = envPtr->cmdMapPtr;
int numCmds = envPtr->numCommands;
int codeDelta, codeLen, srcDelta, srcLen;
int codeDeltaNext, codeLengthNext, srcDeltaNext, srcLengthNext;
/* The offsets in their respective byte
- * sequences where the next encoded offset
- * or length should go. */
+ * sequences where the next encoded offset or
+ * length should go. */
int prevCodeOffset, prevSrcOffset, i;
codeDeltaNext = codeLengthNext = srcDeltaNext = srcLengthNext = 0;
@@ -3333,7 +3307,7 @@ GetCmdLocEncodingSize(envPtr)
for (i = 0; i < numCmds; i++) {
codeDelta = (mapPtr[i].codeOffset - prevCodeOffset);
if (codeDelta < 0) {
- panic("GetCmdLocEncodingSize: bad code offset");
+ Tcl_Panic("GetCmdLocEncodingSize: bad code offset");
} else if (codeDelta <= 127) {
codeDeltaNext++;
} else {
@@ -3343,7 +3317,7 @@ GetCmdLocEncodingSize(envPtr)
codeLen = mapPtr[i].numCodeBytes;
if (codeLen < 0) {
- panic("GetCmdLocEncodingSize: bad code length");
+ Tcl_Panic("GetCmdLocEncodingSize: bad code length");
} else if (codeLen <= 127) {
codeLengthNext++;
} else {
@@ -3360,7 +3334,7 @@ GetCmdLocEncodingSize(envPtr)
srcLen = mapPtr[i].numSrcBytes;
if (srcLen < 0) {
- panic("GetCmdLocEncodingSize: bad source length");
+ Tcl_Panic("GetCmdLocEncodingSize: bad source length");
} else if (srcLen <= 127) {
srcLengthNext++;
} else {
@@ -3376,8 +3350,8 @@ GetCmdLocEncodingSize(envPtr)
*
* EncodeCmdLocMap --
*
- * Encode the command location information for some compiled code into
- * a ByteCode structure. The encoded command location map is stored as
+ * Encode the command location information for some compiled code into a
+ * ByteCode structure. The encoded command location map is stored as
* three adjacent byte sequences.
*
* Results:
@@ -3385,30 +3359,30 @@ GetCmdLocEncodingSize(envPtr)
* information.
*
* Side effects:
- * The encoded information is stored into the block of memory headed
- * by codePtr. Also records pointers to the start of the four byte
- * sequences in fields in codePtr's ByteCode header structure.
+ * The encoded information is stored into the block of memory headed by
+ * codePtr. Also records pointers to the start of the four byte sequences
+ * in fields in codePtr's ByteCode header structure.
*
*----------------------------------------------------------------------
*/
static unsigned char *
-EncodeCmdLocMap(envPtr, codePtr, startPtr)
- CompileEnv *envPtr; /* Points to compilation environment
- * structure containing the CmdLocation
- * structure to encode. */
- ByteCode *codePtr; /* ByteCode in which to encode envPtr's
+EncodeCmdLocMap(
+ CompileEnv *envPtr, /* Points to compilation environment structure
+ * containing the CmdLocation structure to
+ * encode. */
+ ByteCode *codePtr, /* ByteCode in which to encode envPtr's
* command location information. */
- unsigned char *startPtr; /* Points to the first byte in codePtr's
- * memory block where the location
- * information is to be stored. */
+ unsigned char *startPtr) /* Points to the first byte in codePtr's
+ * memory block where the location information
+ * is to be stored. */
{
register CmdLocation *mapPtr = envPtr->cmdMapPtr;
int numCmds = envPtr->numCommands;
register unsigned char *p = startPtr;
int codeDelta, codeLen, srcDelta, srcLen, prevOffset;
register int i;
-
+
/*
* Encode the code offset for each command as a sequence of deltas.
*/
@@ -3418,7 +3392,7 @@ EncodeCmdLocMap(envPtr, codePtr, startPtr)
for (i = 0; i < numCmds; i++) {
codeDelta = (mapPtr[i].codeOffset - prevOffset);
if (codeDelta < 0) {
- panic("EncodeCmdLocMap: bad code offset");
+ Tcl_Panic("EncodeCmdLocMap: bad code offset");
} else if (codeDelta <= 127) {
TclStoreInt1AtPtr(codeDelta, p);
p++;
@@ -3439,7 +3413,7 @@ EncodeCmdLocMap(envPtr, codePtr, startPtr)
for (i = 0; i < numCmds; i++) {
codeLen = mapPtr[i].numCodeBytes;
if (codeLen < 0) {
- panic("EncodeCmdLocMap: bad code length");
+ Tcl_Panic("EncodeCmdLocMap: bad code length");
} else if (codeLen <= 127) {
TclStoreInt1AtPtr(codeLen, p);
p++;
@@ -3479,7 +3453,7 @@ EncodeCmdLocMap(envPtr, codePtr, startPtr)
for (i = 0; i < numCmds; i++) {
srcLen = mapPtr[i].numSrcBytes;
if (srcLen < 0) {
- panic("EncodeCmdLocMap: bad source length");
+ Tcl_Panic("EncodeCmdLocMap: bad source length");
} else if (srcLen <= 127) {
TclStoreInt1AtPtr(srcLen, p);
p++;
@@ -3490,7 +3464,7 @@ EncodeCmdLocMap(envPtr, codePtr, startPtr)
p += 4;
}
}
-
+
return p;
}
@@ -3500,8 +3474,8 @@ EncodeCmdLocMap(envPtr, codePtr, startPtr)
*
* TclPrintByteCodeObj --
*
- * This procedure prints ("disassembles") the instructions of a
- * bytecode object to stdout.
+ * This procedure prints ("disassembles") the instructions of a bytecode
+ * object to stdout.
*
* Results:
* None.
@@ -3513,19 +3487,140 @@ EncodeCmdLocMap(envPtr, codePtr, startPtr)
*/
void
-TclPrintByteCodeObj(interp, objPtr)
- Tcl_Interp *interp; /* Used only for Tcl_GetStringFromObj. */
- Tcl_Obj *objPtr; /* The bytecode object to disassemble. */
+TclPrintByteCodeObj(
+ Tcl_Interp *interp, /* Used only for Tcl_GetStringFromObj. */
+ Tcl_Obj *objPtr) /* The bytecode object to disassemble. */
{
- ByteCode* codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
+ Tcl_Obj *bufPtr = TclDisassembleByteCodeObj(objPtr);
+
+ fprintf(stdout, "\n%s", TclGetString(bufPtr));
+ Tcl_DecrRefCount(bufPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclPrintInstruction --
+ *
+ * This procedure prints ("disassembles") one instruction from a bytecode
+ * object to stdout.
+ *
+ * Results:
+ * Returns the length in bytes of the current instruiction.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclPrintInstruction(
+ ByteCode *codePtr, /* Bytecode containing the instruction. */
+ unsigned char *pc) /* Points to first byte of instruction. */
+{
+ Tcl_Obj *bufferObj;
+ int numBytes;
+
+ TclNewObj(bufferObj);
+ numBytes = FormatInstruction(codePtr, pc, bufferObj);
+ fprintf(stdout, "%s", TclGetString(bufferObj));
+ Tcl_DecrRefCount(bufferObj);
+ return numBytes;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclPrintObject --
+ *
+ * This procedure prints up to a specified number of characters from the
+ * argument Tcl object's string representation to a specified file.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Outputs characters to the specified file.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclPrintObject(
+ FILE *outFile, /* The file to print the source to. */
+ Tcl_Obj *objPtr, /* Points to the Tcl object whose string
+ * representation should be printed. */
+ int maxChars) /* Maximum number of chars to print. */
+{
+ char *bytes;
+ int length;
+
+ bytes = Tcl_GetStringFromObj(objPtr, &length);
+ TclPrintSource(outFile, bytes, TclMin(length, maxChars));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclPrintSource --
+ *
+ * This procedure prints up to a specified number of characters from the
+ * argument string to a specified file. It tries to produce legible
+ * output by adding backslashes as necessary.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Outputs characters to the specified file.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclPrintSource(
+ FILE *outFile, /* The file to print the source to. */
+ const char *stringPtr, /* The string to print. */
+ int maxChars) /* Maximum number of chars to print. */
+{
+ Tcl_Obj *bufferObj;
+
+ TclNewObj(bufferObj);
+ PrintSourceToObj(bufferObj, stringPtr, maxChars);
+ fprintf(outFile, "%s", TclGetString(bufferObj));
+ Tcl_DecrRefCount(bufferObj);
+}
+#endif /* TCL_COMPILE_DEBUG */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclDisassembleByteCodeObj --
+ *
+ * Given an object which is of bytecode type, return a disassembled
+ * version of the bytecode (in a new refcount 0 object). No guarantees
+ * are made about the details of the contents of the result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclDisassembleByteCodeObj(
+ Tcl_Obj *objPtr) /* The bytecode object to disassemble. */
+{
+ ByteCode *codePtr = objPtr->internalRep.otherValuePtr;
unsigned char *codeStart, *codeLimit, *pc;
unsigned char *codeDeltaNext, *codeLengthNext;
unsigned char *srcDeltaNext, *srcLengthNext;
int codeOffset, codeLen, srcOffset, srcLen, numCmds, delta, i;
Interp *iPtr = (Interp *) *codePtr->interpHandle;
+ Tcl_Obj *bufferObj;
+ char ptrBuf1[20], ptrBuf2[20];
+ TclNewObj(bufferObj);
if (codePtr->refCount <= 0) {
- return; /* already freed */
+ return bufferObj; /* Already freed. */
}
codeStart = codePtr->codeStart;
@@ -3536,62 +3631,70 @@ TclPrintByteCodeObj(interp, objPtr)
* Print header lines describing the ByteCode.
*/
- fprintf(stdout, "\nByteCode 0x%x, refCt %u, epoch %u, interp 0x%x (epoch %u)\n",
- (unsigned int) codePtr, codePtr->refCount,
- codePtr->compileEpoch, (unsigned int) iPtr,
+ sprintf(ptrBuf1, "%p", codePtr);
+ sprintf(ptrBuf2, "%p", iPtr);
+ Tcl_AppendPrintfToObj(bufferObj,
+ "ByteCode 0x%s, refCt %u, epoch %u, interp 0x%s (epoch %u)\n",
+ ptrBuf1, codePtr->refCount, codePtr->compileEpoch, ptrBuf2,
iPtr->compileEpoch);
- fprintf(stdout, " Source ");
- TclPrintSource(stdout, codePtr->source,
+ Tcl_AppendToObj(bufferObj, " Source ", -1);
+ PrintSourceToObj(bufferObj, codePtr->source,
TclMin(codePtr->numSrcBytes, 55));
- fprintf(stdout, "\n Cmds %d, src %d, inst %d, litObjs %u, aux %d, stkDepth %u, code/src %.2f\n",
+ Tcl_AppendPrintfToObj(bufferObj,
+ "\n Cmds %d, src %d, inst %d, litObjs %u, aux %d, stkDepth %u, code/src %.2f\n",
numCmds, codePtr->numSrcBytes, codePtr->numCodeBytes,
codePtr->numLitObjects, codePtr->numAuxDataItems,
codePtr->maxStackDepth,
#ifdef TCL_COMPILE_STATS
- (codePtr->numSrcBytes?
- ((float)codePtr->structureSize)/((float)codePtr->numSrcBytes) : 0.0));
-#else
- 0.0);
+ codePtr->numSrcBytes?
+ codePtr->structureSize/(float)codePtr->numSrcBytes :
#endif
+ 0.0);
+
#ifdef TCL_COMPILE_STATS
- fprintf(stdout,
- " Code %u = header %u+inst %d+litObj %lu+exc %lu+aux %lu+cmdMap %d\n",
- (unsigned int)codePtr->structureSize,
- (unsigned int)(sizeof(ByteCode) - (sizeof(size_t) + sizeof(Tcl_Time))),
+ Tcl_AppendPrintfToObj(bufferObj,
+ " Code %lu = header %lu+inst %d+litObj %lu+exc %lu+aux %lu+cmdMap %d\n",
+ (unsigned long) codePtr->structureSize,
+ (unsigned long) (sizeof(ByteCode) - sizeof(size_t) - sizeof(Tcl_Time)),
codePtr->numCodeBytes,
- (unsigned long)(codePtr->numLitObjects * sizeof(Tcl_Obj *)),
- (unsigned long)(codePtr->numExceptRanges * sizeof(ExceptionRange)),
- (unsigned long)(codePtr->numAuxDataItems * sizeof(AuxData)),
+ (unsigned long) (codePtr->numLitObjects * sizeof(Tcl_Obj *)),
+ (unsigned long) (codePtr->numExceptRanges*sizeof(ExceptionRange)),
+ (unsigned long) (codePtr->numAuxDataItems * sizeof(AuxData)),
codePtr->numCmdLocBytes);
#endif /* TCL_COMPILE_STATS */
-
+
/*
* If the ByteCode is the compiled body of a Tcl procedure, print
* information about that procedure. Note that we don't know the
* procedure's name since ByteCode's can be shared among procedures.
*/
-
+
if (codePtr->procPtr != NULL) {
Proc *procPtr = codePtr->procPtr;
int numCompiledLocals = procPtr->numCompiledLocals;
- fprintf(stdout,
- " Proc 0x%x, refCt %d, args %d, compiled locals %d\n",
- (unsigned int) procPtr, procPtr->refCount, procPtr->numArgs,
+
+ sprintf(ptrBuf1, "%p", procPtr);
+ Tcl_AppendPrintfToObj(bufferObj,
+ " Proc 0x%s, refCt %d, args %d, compiled locals %d\n",
+ ptrBuf1, procPtr->refCount, procPtr->numArgs,
numCompiledLocals);
if (numCompiledLocals > 0) {
CompiledLocal *localPtr = procPtr->firstLocalPtr;
+
for (i = 0; i < numCompiledLocals; i++) {
- fprintf(stdout, " slot %d%s%s%s%s%s%s", i,
- ((localPtr->flags & VAR_SCALAR)? ", scalar" : ""),
- ((localPtr->flags & VAR_ARRAY)? ", array" : ""),
- ((localPtr->flags & VAR_LINK)? ", link" : ""),
- ((localPtr->flags & VAR_ARGUMENT)? ", arg" : ""),
- ((localPtr->flags & VAR_TEMPORARY)? ", temp" : ""),
- ((localPtr->flags & VAR_RESOLVED)? ", resolved" : ""));
+ Tcl_AppendPrintfToObj(bufferObj,
+ " slot %d%s%s%s%s%s%s", i,
+ (localPtr->flags & (VAR_ARRAY|VAR_LINK)) ? "" : ", scalar",
+ (localPtr->flags & VAR_ARRAY) ? ", array" : "",
+ (localPtr->flags & VAR_LINK) ? ", link" : "",
+ (localPtr->flags & VAR_ARGUMENT) ? ", arg" : "",
+ (localPtr->flags & VAR_TEMPORARY) ? ", temp" : "",
+ (localPtr->flags & VAR_RESOLVED) ? ", resolved" : "");
if (TclIsVarTemporary(localPtr)) {
- fprintf(stdout, "\n");
+ Tcl_AppendToObj(bufferObj, "\n", -1);
} else {
- fprintf(stdout, ", \"%s\"\n", localPtr->name);
+ Tcl_AppendPrintfToObj(bufferObj, ", \"%s\"\n",
+ localPtr->name);
}
localPtr = localPtr->nextPtr;
}
@@ -3603,58 +3706,60 @@ TclPrintByteCodeObj(interp, objPtr)
*/
if (codePtr->numExceptRanges > 0) {
- fprintf(stdout, " Exception ranges %d, depth %d:\n",
- codePtr->numExceptRanges, codePtr->maxExceptDepth);
+ Tcl_AppendPrintfToObj(bufferObj, " Exception ranges %d, depth %d:\n",
+ codePtr->numExceptRanges, codePtr->maxExceptDepth);
for (i = 0; i < codePtr->numExceptRanges; i++) {
ExceptionRange *rangePtr = &(codePtr->exceptArrayPtr[i]);
- fprintf(stdout, " %d: level %d, %s, pc %d-%d, ",
+
+ Tcl_AppendPrintfToObj(bufferObj,
+ " %d: level %d, %s, pc %d-%d, ",
i, rangePtr->nestingLevel,
- ((rangePtr->type == LOOP_EXCEPTION_RANGE)
- ? "loop" : "catch"),
+ (rangePtr->type==LOOP_EXCEPTION_RANGE ? "loop" : "catch"),
rangePtr->codeOffset,
(rangePtr->codeOffset + rangePtr->numCodeBytes - 1));
switch (rangePtr->type) {
case LOOP_EXCEPTION_RANGE:
- fprintf(stdout, "continue %d, break %d\n",
- rangePtr->continueOffset, rangePtr->breakOffset);
+ Tcl_AppendPrintfToObj(bufferObj, "continue %d, break %d\n",
+ rangePtr->continueOffset, rangePtr->breakOffset);
break;
case CATCH_EXCEPTION_RANGE:
- fprintf(stdout, "catch %d\n", rangePtr->catchOffset);
+ Tcl_AppendPrintfToObj(bufferObj, "catch %d\n",
+ rangePtr->catchOffset);
break;
default:
- panic("TclPrintByteCodeObj: bad ExceptionRange type %d\n",
- rangePtr->type);
+ Tcl_Panic("TclDisassembleByteCodeObj: bad ExceptionRange type %d",
+ rangePtr->type);
}
}
}
-
+
/*
- * If there were no commands (e.g., an expression or an empty string
- * was compiled), just print all instructions and return.
+ * If there were no commands (e.g., an expression or an empty string was
+ * compiled), just print all instructions and return.
*/
if (numCmds == 0) {
pc = codeStart;
while (pc < codeLimit) {
- fprintf(stdout, " ");
- pc += TclPrintInstruction(codePtr, pc);
+ Tcl_AppendToObj(bufferObj, " ", -1);
+ pc += FormatInstruction(codePtr, pc, bufferObj);
}
- return;
+ return bufferObj;
}
-
+
/*
- * Print table showing the code offset, source offset, and source
- * length for each command. These are encoded as a sequence of bytes.
+ * Print table showing the code offset, source offset, and source length
+ * for each command. These are encoded as a sequence of bytes.
*/
- fprintf(stdout, " Commands %d:", numCmds);
+ Tcl_AppendPrintfToObj(bufferObj, " Commands %d:", numCmds);
codeDeltaNext = codePtr->codeDeltaStart;
codeLengthNext = codePtr->codeLengthStart;
- srcDeltaNext = codePtr->srcDeltaStart;
+ srcDeltaNext = codePtr->srcDeltaStart;
srcLengthNext = codePtr->srcLengthStart;
codeOffset = srcOffset = 0;
for (i = 0; i < numCmds; i++) {
- if ((unsigned int) (*codeDeltaNext) == (unsigned int) 0xFF) {
+ if ((unsigned) *codeDeltaNext == (unsigned) 0xFF) {
codeDeltaNext++;
delta = TclGetInt4AtPtr(codeDeltaNext);
codeDeltaNext += 4;
@@ -3664,7 +3769,7 @@ TclPrintByteCodeObj(interp, objPtr)
}
codeOffset += delta;
- if ((unsigned int) (*codeLengthNext) == (unsigned int) 0xFF) {
+ if ((unsigned) *codeLengthNext == (unsigned) 0xFF) {
codeLengthNext++;
codeLen = TclGetInt4AtPtr(codeLengthNext);
codeLengthNext += 4;
@@ -3672,8 +3777,8 @@ TclPrintByteCodeObj(interp, objPtr)
codeLen = TclGetInt1AtPtr(codeLengthNext);
codeLengthNext++;
}
-
- if ((unsigned int) (*srcDeltaNext) == (unsigned int) 0xFF) {
+
+ if ((unsigned) *srcDeltaNext == (unsigned) 0xFF) {
srcDeltaNext++;
delta = TclGetInt4AtPtr(srcDeltaNext);
srcDeltaNext += 4;
@@ -3683,7 +3788,7 @@ TclPrintByteCodeObj(interp, objPtr)
}
srcOffset += delta;
- if ((unsigned int) (*srcLengthNext) == (unsigned int) 0xFF) {
+ if ((unsigned) *srcLengthNext == (unsigned) 0xFF) {
srcLengthNext++;
srcLen = TclGetInt4AtPtr(srcLengthNext);
srcLengthNext += 4;
@@ -3691,29 +3796,29 @@ TclPrintByteCodeObj(interp, objPtr)
srcLen = TclGetInt1AtPtr(srcLengthNext);
srcLengthNext++;
}
-
- fprintf(stdout, "%s%4d: pc %d-%d, src %d-%d",
+
+ Tcl_AppendPrintfToObj(bufferObj, "%s%4d: pc %d-%d, src %d-%d",
((i % 2)? " " : "\n "),
(i+1), codeOffset, (codeOffset + codeLen - 1),
srcOffset, (srcOffset + srcLen - 1));
}
if (numCmds > 0) {
- fprintf(stdout, "\n");
+ Tcl_AppendToObj(bufferObj, "\n", -1);
}
-
+
/*
- * Print each instruction. If the instruction corresponds to the start
- * of a command, print the command's source. Note that we don't need
- * the code length here.
+ * Print each instruction. If the instruction corresponds to the start of
+ * a command, print the command's source. Note that we don't need the code
+ * length here.
*/
codeDeltaNext = codePtr->codeDeltaStart;
- srcDeltaNext = codePtr->srcDeltaStart;
+ srcDeltaNext = codePtr->srcDeltaStart;
srcLengthNext = codePtr->srcLengthStart;
codeOffset = srcOffset = 0;
pc = codeStart;
for (i = 0; i < numCmds; i++) {
- if ((unsigned int) (*codeDeltaNext) == (unsigned int) 0xFF) {
+ if ((unsigned) *codeDeltaNext == (unsigned) 0xFF) {
codeDeltaNext++;
delta = TclGetInt4AtPtr(codeDeltaNext);
codeDeltaNext += 4;
@@ -3723,7 +3828,7 @@ TclPrintByteCodeObj(interp, objPtr)
}
codeOffset += delta;
- if ((unsigned int) (*srcDeltaNext) == (unsigned int) 0xFF) {
+ if ((unsigned) *srcDeltaNext == (unsigned) 0xFF) {
srcDeltaNext++;
delta = TclGetInt4AtPtr(srcDeltaNext);
srcDeltaNext += 4;
@@ -3733,7 +3838,7 @@ TclPrintByteCodeObj(interp, objPtr)
}
srcOffset += delta;
- if ((unsigned int) (*srcLengthNext) == (unsigned int) 0xFF) {
+ if ((unsigned) *srcLengthNext == (unsigned) 0xFF) {
srcLengthNext++;
srcLen = TclGetInt4AtPtr(srcLengthNext);
srcLengthNext += 4;
@@ -3745,16 +3850,16 @@ TclPrintByteCodeObj(interp, objPtr)
/*
* Print instructions before command i.
*/
-
+
while ((pc-codeStart) < codeOffset) {
- fprintf(stdout, " ");
- pc += TclPrintInstruction(codePtr, pc);
+ Tcl_AppendToObj(bufferObj, " ", -1);
+ pc += FormatInstruction(codePtr, pc, bufferObj);
}
- fprintf(stdout, " Command %d: ", (i+1));
- TclPrintSource(stdout, (codePtr->source + srcOffset),
- TclMin(srcLen, 55));
- fprintf(stdout, "\n");
+ Tcl_AppendPrintfToObj(bufferObj, " Command %d: ", i+1);
+ PrintSourceToObj(bufferObj, (codePtr->source + srcOffset),
+ TclMin(srcLen, 55));
+ Tcl_AppendToObj(bufferObj, "\n", -1);
}
if (pc < codeLimit) {
/*
@@ -3762,225 +3867,201 @@ TclPrintByteCodeObj(interp, objPtr)
*/
while (pc < codeLimit) {
- fprintf(stdout, " ");
- pc += TclPrintInstruction(codePtr, pc);
+ Tcl_AppendToObj(bufferObj, " ", -1);
+ pc += FormatInstruction(codePtr, pc, bufferObj);
}
}
+ return bufferObj;
}
-#endif /* TCL_COMPILE_DEBUG */
/*
*----------------------------------------------------------------------
*
- * TclPrintInstruction --
- *
- * This procedure prints ("disassembles") one instruction from a
- * bytecode object to stdout.
- *
- * Results:
- * Returns the length in bytes of the current instruiction.
+ * FormatInstruction --
*
- * Side effects:
- * None.
+ * Appends a representation of a bytecode instruction to a Tcl_Obj.
*
*----------------------------------------------------------------------
*/
-int
-TclPrintInstruction(codePtr, pc)
- ByteCode* codePtr; /* Bytecode containing the instruction. */
- unsigned char *pc; /* Points to first byte of instruction. */
+static int
+FormatInstruction(
+ ByteCode *codePtr, /* Bytecode containing the instruction. */
+ unsigned char *pc, /* Points to first byte of instruction. */
+ Tcl_Obj *bufferObj) /* Object to append instruction info to. */
{
Proc *procPtr = codePtr->procPtr;
unsigned char opCode = *pc;
register InstructionDesc *instDesc = &tclInstructionTable[opCode];
unsigned char *codeStart = codePtr->codeStart;
- unsigned int pcOffset = (pc - codeStart);
- int opnd, i, j;
-
- fprintf(stdout, "(%u) %s ", pcOffset, instDesc->name);
+ unsigned pcOffset = pc - codeStart;
+ int opnd = 0, i, j, numBytes = 1;
+ int localCt = procPtr ? procPtr->numCompiledLocals : 0;
+ CompiledLocal *localPtr = procPtr ? procPtr->firstLocalPtr : NULL;
+ char suffixBuffer[128]; /* Additional info to print after main opcode
+ * and immediates. */
+ char *suffixSrc = NULL;
+ Tcl_Obj *suffixObj = NULL;
+ AuxData *auxPtr = NULL;
+
+ suffixBuffer[0] = '\0';
+ Tcl_AppendPrintfToObj(bufferObj, "(%u) %s ", pcOffset, instDesc->name);
for (i = 0; i < instDesc->numOperands; i++) {
switch (instDesc->opTypes[i]) {
case OPERAND_INT1:
- opnd = TclGetInt1AtPtr(pc+1+i);
- if ((i == 0) && ((opCode == INST_JUMP1)
- || (opCode == INST_JUMP_TRUE1)
- || (opCode == INST_JUMP_FALSE1))) {
- fprintf(stdout, "%d # pc %u", opnd, (pcOffset + opnd));
- } else {
- fprintf(stdout, "%d", opnd);
+ opnd = TclGetInt1AtPtr(pc+numBytes); numBytes++;
+ if (opCode == INST_JUMP1 || opCode == INST_JUMP_TRUE1
+ || opCode == INST_JUMP_FALSE1) {
+ sprintf(suffixBuffer, "pc %u", pcOffset+opnd);
}
+ Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd);
break;
case OPERAND_INT4:
- opnd = TclGetInt4AtPtr(pc+1+i);
- if ((i == 0) && ((opCode == INST_JUMP4)
- || (opCode == INST_JUMP_TRUE4)
- || (opCode == INST_JUMP_FALSE4))) {
- fprintf(stdout, "%d # pc %u", opnd, (pcOffset + opnd));
- } else {
- fprintf(stdout, "%d", opnd);
+ opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4;
+ if (opCode == INST_JUMP4 || opCode == INST_JUMP_TRUE4
+ || opCode == INST_JUMP_FALSE4) {
+ sprintf(suffixBuffer, "pc %u", pcOffset+opnd);
+ } else if (opCode == INST_START_CMD) {
+ sprintf(suffixBuffer, "next cmd at pc %u", pcOffset+opnd);
}
+ Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd);
break;
case OPERAND_UINT1:
- opnd = TclGetUInt1AtPtr(pc+1+i);
- if ((i == 0) && (opCode == INST_PUSH1)) {
- fprintf(stdout, "%u # ", (unsigned int) opnd);
- TclPrintObject(stdout, codePtr->objArrayPtr[opnd], 40);
- } else if ((i == 0) && ((opCode == INST_LOAD_SCALAR1)
- || (opCode == INST_LOAD_ARRAY1)
- || (opCode == INST_STORE_SCALAR1)
- || (opCode == INST_STORE_ARRAY1))) {
- int localCt = procPtr->numCompiledLocals;
- CompiledLocal *localPtr = procPtr->firstLocalPtr;
- if (opnd >= localCt) {
- panic("TclPrintInstruction: bad local var index %u (%u locals)\n",
- (unsigned int) opnd, localCt);
- return instDesc->numBytes;
- }
- for (j = 0; j < opnd; j++) {
- localPtr = localPtr->nextPtr;
- }
- if (TclIsVarTemporary(localPtr)) {
- fprintf(stdout, "%u # temp var %u",
- (unsigned int) opnd, (unsigned int) opnd);
- } else {
- fprintf(stdout, "%u # var ", (unsigned int) opnd);
- TclPrintSource(stdout, localPtr->name, 40);
- }
- } else {
- fprintf(stdout, "%u ", (unsigned int) opnd);
+ opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++;
+ if (opCode == INST_PUSH1) {
+ suffixObj = codePtr->objArrayPtr[opnd];
}
+ Tcl_AppendPrintfToObj(bufferObj, "%u ", (unsigned) opnd);
break;
+ case OPERAND_AUX4:
case OPERAND_UINT4:
- opnd = TclGetUInt4AtPtr(pc+1+i);
+ opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4;
if (opCode == INST_PUSH4) {
- fprintf(stdout, "%u # ", opnd);
- TclPrintObject(stdout, codePtr->objArrayPtr[opnd], 40);
- } else if ((i == 0) && ((opCode == INST_LOAD_SCALAR4)
- || (opCode == INST_LOAD_ARRAY4)
- || (opCode == INST_STORE_SCALAR4)
- || (opCode == INST_STORE_ARRAY4))) {
- int localCt = procPtr->numCompiledLocals;
- CompiledLocal *localPtr = procPtr->firstLocalPtr;
+ suffixObj = codePtr->objArrayPtr[opnd];
+ } else if (opCode == INST_START_CMD && opnd != 1) {
+ sprintf(suffixBuffer+strlen(suffixBuffer),
+ ", %u cmds start here", opnd);
+ }
+ Tcl_AppendPrintfToObj(bufferObj, "%u ", (unsigned) opnd);
+ if (instDesc->opTypes[i] == OPERAND_AUX4) {
+ auxPtr = &codePtr->auxDataArrayPtr[opnd];
+ }
+ break;
+ case OPERAND_IDX4:
+ opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4;
+ if (opnd >= -1) {
+ Tcl_AppendPrintfToObj(bufferObj, "%d ", opnd);
+ } else if (opnd == -2) {
+ Tcl_AppendPrintfToObj(bufferObj, "end ");
+ } else {
+ Tcl_AppendPrintfToObj(bufferObj, "end-%d ", -2-opnd);
+ }
+ break;
+ case OPERAND_LVT1:
+ opnd = TclGetUInt1AtPtr(pc+numBytes);
+ numBytes++;
+ goto printLVTindex;
+ case OPERAND_LVT4:
+ opnd = TclGetUInt4AtPtr(pc+numBytes);
+ numBytes += 4;
+ printLVTindex:
+ if (localPtr != NULL) {
if (opnd >= localCt) {
- panic("TclPrintInstruction: bad local var index %u (%u locals)\n",
- (unsigned int) opnd, localCt);
- return instDesc->numBytes;
+ Tcl_Panic("FormatInstruction: bad local var index %u (%u locals)",
+ (unsigned) opnd, localCt);
}
for (j = 0; j < opnd; j++) {
localPtr = localPtr->nextPtr;
}
if (TclIsVarTemporary(localPtr)) {
- fprintf(stdout, "%u # temp var %u",
- (unsigned int) opnd, (unsigned int) opnd);
+ sprintf(suffixBuffer, "temp var %u", (unsigned) opnd);
} else {
- fprintf(stdout, "%u # var ", (unsigned int) opnd);
- TclPrintSource(stdout, localPtr->name, 40);
+ sprintf(suffixBuffer, "var ");
+ suffixSrc = localPtr->name;
}
- } else {
- fprintf(stdout, "%u ", (unsigned int) opnd);
}
+ Tcl_AppendPrintfToObj(bufferObj, "%%v%u ", (unsigned) opnd);
break;
case OPERAND_NONE:
default:
break;
}
}
- fprintf(stdout, "\n");
- return instDesc->numBytes;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclPrintObject --
- *
- * This procedure prints up to a specified number of characters from
- * the argument Tcl object's string representation to a specified file.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Outputs characters to the specified file.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclPrintObject(outFile, objPtr, maxChars)
- FILE *outFile; /* The file to print the source to. */
- Tcl_Obj *objPtr; /* Points to the Tcl object whose string
- * representation should be printed. */
- int maxChars; /* Maximum number of chars to print. */
-{
- char *bytes;
- int length;
-
- bytes = Tcl_GetStringFromObj(objPtr, &length);
- TclPrintSource(outFile, bytes, TclMin(length, maxChars));
+ if (suffixObj) {
+ char *bytes;
+ int length;
+
+ Tcl_AppendToObj(bufferObj, "\t# ", -1);
+ bytes = Tcl_GetStringFromObj(codePtr->objArrayPtr[opnd], &length);
+ PrintSourceToObj(bufferObj, bytes, TclMin(length, 40));
+ } else if (suffixBuffer[0]) {
+ Tcl_AppendPrintfToObj(bufferObj, "\t# %s", suffixBuffer);
+ if (suffixSrc) {
+ PrintSourceToObj(bufferObj, suffixSrc, 40);
+ }
+ }
+ Tcl_AppendToObj(bufferObj, "\n", -1);
+ if (auxPtr && auxPtr->type->printProc) {
+ Tcl_AppendToObj(bufferObj, "\t\t[", -1);
+ auxPtr->type->printProc(auxPtr->clientData, bufferObj, codePtr,
+ pcOffset);
+ Tcl_AppendToObj(bufferObj, "]\n", -1);
+ }
+ return numBytes;
}
/*
*----------------------------------------------------------------------
*
- * TclPrintSource --
+ * PrintSourceToObj --
*
- * This procedure prints up to a specified number of characters from
- * the argument string to a specified file. It tries to produce legible
- * output by adding backslashes as necessary.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Outputs characters to the specified file.
+ * Appends a quoted representation of a string to a Tcl_Obj.
*
*----------------------------------------------------------------------
*/
-void
-TclPrintSource(outFile, string, maxChars)
- FILE *outFile; /* The file to print the source to. */
- CONST char *string; /* The string to print. */
- int maxChars; /* Maximum number of chars to print. */
+static void
+PrintSourceToObj(
+ Tcl_Obj *appendObj, /* The object to print the source to. */
+ const char *stringPtr, /* The string to print. */
+ int maxChars) /* Maximum number of chars to print. */
{
- register CONST char *p;
+ register const char *p;
register int i = 0;
- if (string == NULL) {
- fprintf(outFile, "\"\"");
+ if (stringPtr == NULL) {
+ Tcl_AppendToObj(appendObj, "\"\"", -1);
return;
}
- fprintf(outFile, "\"");
- p = string;
+ Tcl_AppendToObj(appendObj, "\"", -1);
+ p = stringPtr;
for (; (*p != '\0') && (i < maxChars); p++, i++) {
switch (*p) {
- case '"':
- fprintf(outFile, "\\\"");
- continue;
- case '\f':
- fprintf(outFile, "\\f");
- continue;
- case '\n':
- fprintf(outFile, "\\n");
- continue;
- case '\r':
- fprintf(outFile, "\\r");
- continue;
- case '\t':
- fprintf(outFile, "\\t");
- continue;
- case '\v':
- fprintf(outFile, "\\v");
- continue;
- default:
- fprintf(outFile, "%c", *p);
- continue;
+ case '"':
+ Tcl_AppendToObj(appendObj, "\\\"", -1);
+ continue;
+ case '\f':
+ Tcl_AppendToObj(appendObj, "\\f", -1);
+ continue;
+ case '\n':
+ Tcl_AppendToObj(appendObj, "\\n", -1);
+ continue;
+ case '\r':
+ Tcl_AppendToObj(appendObj, "\\r", -1);
+ continue;
+ case '\t':
+ Tcl_AppendToObj(appendObj, "\\t", -1);
+ continue;
+ case '\v':
+ Tcl_AppendToObj(appendObj, "\\v", -1);
+ continue;
+ default:
+ Tcl_AppendPrintfToObj(appendObj, "%c", *p);
+ continue;
}
}
- fprintf(outFile, "\"");
+ Tcl_AppendToObj(appendObj, "\"", -1);
}
#ifdef TCL_COMPILE_STATS
@@ -3998,15 +4079,15 @@ TclPrintSource(outFile, string, maxChars)
*
* Side effects:
* Accumulates aggregate code-related statistics in the interpreter's
- * ByteCodeStats structure. Records statistics specific to a ByteCode
- * in its ByteCode structure.
+ * ByteCodeStats structure. Records statistics specific to a ByteCode in
+ * its ByteCode structure.
*
*----------------------------------------------------------------------
*/
void
-RecordByteCodeStats(codePtr)
- ByteCode *codePtr; /* Points to ByteCode structure with info
+RecordByteCodeStats(
+ ByteCode *codePtr) /* Points to ByteCode structure with info
* to add to accumulated statistics. */
{
Interp *iPtr = (Interp *) *codePtr->interpHandle;
@@ -4018,21 +4099,21 @@ RecordByteCodeStats(codePtr)
}
statsPtr->numCompilations++;
- statsPtr->totalSrcBytes += (double) codePtr->numSrcBytes;
- statsPtr->totalByteCodeBytes += (double) codePtr->structureSize;
- statsPtr->currentSrcBytes += (double) codePtr->numSrcBytes;
+ statsPtr->totalSrcBytes += (double) codePtr->numSrcBytes;
+ statsPtr->totalByteCodeBytes += (double) codePtr->structureSize;
+ statsPtr->currentSrcBytes += (double) codePtr->numSrcBytes;
statsPtr->currentByteCodeBytes += (double) codePtr->structureSize;
-
+
statsPtr->srcCount[TclLog2(codePtr->numSrcBytes)]++;
statsPtr->byteCodeCount[TclLog2((int)(codePtr->structureSize))]++;
- statsPtr->currentInstBytes += (double) codePtr->numCodeBytes;
- statsPtr->currentLitBytes +=
- (double) (codePtr->numLitObjects * sizeof(Tcl_Obj *));
- statsPtr->currentExceptBytes +=
- (double) (codePtr->numExceptRanges * sizeof(ExceptionRange));
- statsPtr->currentAuxBytes +=
- (double) (codePtr->numAuxDataItems * sizeof(AuxData));
+ statsPtr->currentInstBytes += (double) codePtr->numCodeBytes;
+ statsPtr->currentLitBytes += (double)
+ codePtr->numLitObjects * sizeof(Tcl_Obj *);
+ statsPtr->currentExceptBytes += (double)
+ codePtr->numExceptRanges * sizeof(ExceptionRange);
+ statsPtr->currentAuxBytes += (double)
+ codePtr->numAuxDataItems * sizeof(AuxData);
statsPtr->currentCmdMapBytes += (double) codePtr->numCmdLocBytes;
}
#endif /* TCL_COMPILE_STATS */
@@ -4044,4 +4125,3 @@ RecordByteCodeStats(codePtr)
* fill-column: 78
* End:
*/
-
diff --git a/generic/tclCompile.h b/generic/tclCompile.h
index 31c1b94..c035a03 100644
--- a/generic/tclCompile.h
+++ b/generic/tclCompile.h
@@ -3,24 +3,19 @@
*
* Copyright (c) 1996-1998 Sun Microsystems, Inc.
* Copyright (c) 1998-2000 by Scriptics Corporation.
- * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
+ * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
* Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#ifndef _TCLCOMPILATION
#define _TCLCOMPILATION 1
-#ifndef _TCLINT
#include "tclInt.h"
-#endif /* _TCLINT */
-#ifdef BUILD_tcl
-# undef TCL_STORAGE_CLASS
-# define TCL_STORAGE_CLASS DLLEXPORT
-#endif
+struct ByteCode; /* Forward declaration. */
/*
*------------------------------------------------------------------------
@@ -39,10 +34,8 @@
* This variable is linked to the Tcl variable "tcl_traceCompile".
*/
-extern int tclTraceCompile;
-#endif
+MODULE_SCOPE int tclTraceCompile;
-#ifdef TCL_COMPILE_DEBUG
/*
* Variable that controls whether execution tracing is enabled and, if so,
* what level of tracing is desired:
@@ -53,9 +46,9 @@ extern int tclTraceCompile;
* This variable is linked to the Tcl variable "tcl_traceExec".
*/
-extern int tclTraceExec;
+MODULE_SCOPE int tclTraceExec;
#endif
-
+
/*
*------------------------------------------------------------------------
* Data structures related to compilation.
@@ -63,54 +56,55 @@ extern int tclTraceExec;
*/
/*
- * The structure used to implement Tcl "exceptions" (exceptional returns):
- * for example, those generated in loops by the break and continue commands,
- * and those generated by scripts and caught by the catch command. This
- * ExceptionRange structure describes a range of code (e.g., a loop body),
- * the kind of exceptions (e.g., a break or continue) that might occur, and
- * the PC offsets to jump to if a matching exception does occur. Exception
- * ranges can nest so this structure includes a nesting level that is used
- * at runtime to find the closest exception range surrounding a PC. For
- * example, when a break command is executed, the ExceptionRange structure
- * for the most deeply nested loop, if any, is found and used. These
- * structures are also generated for the "next" subcommands of for loops
- * since a break there terminates the for command. This means a for command
- * actually generates two LoopInfo structures.
+ * The structure used to implement Tcl "exceptions" (exceptional returns): for
+ * example, those generated in loops by the break and continue commands, and
+ * those generated by scripts and caught by the catch command. This
+ * ExceptionRange structure describes a range of code (e.g., a loop body), the
+ * kind of exceptions (e.g., a break or continue) that might occur, and the PC
+ * offsets to jump to if a matching exception does occur. Exception ranges can
+ * nest so this structure includes a nesting level that is used at runtime to
+ * find the closest exception range surrounding a PC. For example, when a
+ * break command is executed, the ExceptionRange structure for the most deeply
+ * nested loop, if any, is found and used. These structures are also generated
+ * for the "next" subcommands of for loops since a break there terminates the
+ * for command. This means a for command actually generates two LoopInfo
+ * structures.
*/
typedef enum {
- LOOP_EXCEPTION_RANGE, /* Exception's range is part of a loop.
- * Break and continue "exceptions" cause
- * jumps to appropriate PC offsets. */
- CATCH_EXCEPTION_RANGE /* Exception's range is controlled by a
- * catch command. Errors in the range cause
- * a jump to a catch PC offset. */
+ LOOP_EXCEPTION_RANGE, /* Exception's range is part of a loop. Break
+ * and continue "exceptions" cause jumps to
+ * appropriate PC offsets. */
+ CATCH_EXCEPTION_RANGE /* Exception's range is controlled by a catch
+ * command. Errors in the range cause a jump
+ * to a catch PC offset. */
} ExceptionRangeType;
typedef struct ExceptionRange {
ExceptionRangeType type; /* The kind of ExceptionRange. */
- int nestingLevel; /* Static depth of the exception range.
- * Used to find the most deeply-nested
- * range surrounding a PC at runtime. */
- int codeOffset; /* Offset of the first instruction byte of
- * the code range. */
+ int nestingLevel; /* Static depth of the exception range. Used
+ * to find the most deeply-nested range
+ * surrounding a PC at runtime. */
+ int codeOffset; /* Offset of the first instruction byte of the
+ * code range. */
int numCodeBytes; /* Number of bytes in the code range. */
int breakOffset; /* If LOOP_EXCEPTION_RANGE, the target PC
* offset for a break command in the range. */
int continueOffset; /* If LOOP_EXCEPTION_RANGE and not -1, the
* target PC offset for a continue command in
- * the code range. Otherwise, ignore this range
- * when processing a continue command. */
+ * the code range. Otherwise, ignore this
+ * range when processing a continue
+ * command. */
int catchOffset; /* If a CATCH_EXCEPTION_RANGE, the target PC
* offset for any "exception" in range. */
} ExceptionRange;
/*
* Structure used to map between instruction pc and source locations. It
- * defines for each compiled Tcl command its code's starting offset and
- * its source's starting offset and length. Note that the code offset
- * increases monotonically: that is, the table is sorted in code offset
- * order. The source offset is not monotonic.
+ * defines for each compiled Tcl command its code's starting offset and its
+ * source's starting offset and length. Note that the code offset increases
+ * monotonically: that is, the table is sorted in code offset order. The
+ * source offset is not monotonic.
*/
typedef struct CmdLocation {
@@ -120,80 +114,90 @@ typedef struct CmdLocation {
int numSrcBytes; /* Number of command source chars. */
} CmdLocation;
-#ifdef TCL_TIP280
/*
* TIP #280
- * Structure to record additional location information for byte code.
- * This information is internal and not saved. I.e. tbcload'ed code
- * will not have this information. It records the lines for all words
- * of all commands found in the byte code. The association with a
- * ByteCode structure BC is done through the 'lineBCPtr' HashTable in
- * Interp, keyed by the address of BC. Also recorded is information
- * coming from the context, i.e. type of the frame and associated
- * information, like the path of a sourced file.
+ * Structure to record additional location information for byte code. This
+ * information is internal and not saved. i.e. tbcload'ed code will not have
+ * this information. It records the lines for all words of all commands found
+ * in the byte code. The association with a ByteCode structure BC is done
+ * through the 'lineBCPtr' HashTable in Interp, keyed by the address of BC.
+ * Also recorded is information coming from the context, i.e. type of the
+ * frame and associated information, like the path of a sourced file.
*/
typedef struct ECL {
- int srcOffset; /* cmd location to find the entry */
- int nline; /* Number of words in the command */
- int* line; /* line information for all words in the command */
- int** next; /* Transient information during compile, ICL tracking */
+ int srcOffset; /* Command location to find the entry. */
+ int nline; /* Number of words in the command */
+ int *line; /* Line information for all words in the
+ * command. */
+ int** next; /* Transient information used by the compiler
+ * for tracking of hidden continuation
+ * lines. */
} ECL;
typedef struct ExtCmdLoc {
- int type; /* Context type */
- Tcl_Obj* path; /* Path of the sourced file the command is in */
- ECL* loc; /* Command word locations (lines) */
- int nloc; /* Number of allocated entries in 'loc' */
- int nuloc; /* Number of used entries in 'loc' */
- Tcl_HashTable litInfo; /* Indexed by bytecode 'PC', to have the
- * information accessible per command and
- * argument, not per whole bytecode. Value is
- * index of command in 'loc', giving us the
- * literals to associate with line
- * information as command argument, see
- * TclArgumentBCEnter() */
+ int type; /* Context type. */
+ int start; /* Starting line for compiled script. Needed
+ * for the extended recompile check in
+ * TclCompEvalObj. */
+
+ Tcl_Obj *path; /* Path of the sourced file the command is
+ * in. */
+ ECL *loc; /* Command word locations (lines). */
+ int nloc; /* Number of allocated entries in 'loc'. */
+ int nuloc; /* Number of used entries in 'loc'. */
+ Tcl_HashTable litInfo; /* Indexed by bytecode 'PC', to have the
+ * information accessible per command and
+ * argument, not per whole bytecode. Value is
+ * index of command in 'loc', giving us the
+ * literals to associate with line information
+ * as command argument, see
+ * TclArgumentBCEnter() */
} ExtCmdLoc;
-#endif
/*
- * CompileProcs need the ability to record information during compilation
- * that can be used by bytecode instructions during execution. The AuxData
- * structure provides this "auxiliary data" mechanism. An arbitrary number
- * of these structures can be stored in the ByteCode record (during
- * compilation they are stored in a CompileEnv structure). Each AuxData
- * record holds one word of client-specified data (often a pointer) and is
- * given an index that instructions can later use to look up the structure
- * and its data.
+ * CompileProcs need the ability to record information during compilation that
+ * can be used by bytecode instructions during execution. The AuxData
+ * structure provides this "auxiliary data" mechanism. An arbitrary number of
+ * these structures can be stored in the ByteCode record (during compilation
+ * they are stored in a CompileEnv structure). Each AuxData record holds one
+ * word of client-specified data (often a pointer) and is given an index that
+ * instructions can later use to look up the structure and its data.
*
* The following definitions declare the types of procedures that are called
* to duplicate or free this auxiliary data when the containing ByteCode
- * objects are duplicated and freed. Pointers to these procedures are kept
- * in the AuxData structure.
+ * objects are duplicated and freed. Pointers to these procedures are kept in
+ * the AuxData structure.
*/
-typedef ClientData (AuxDataDupProc) _ANSI_ARGS_((ClientData clientData));
-typedef void (AuxDataFreeProc) _ANSI_ARGS_((ClientData clientData));
+typedef ClientData (AuxDataDupProc) (ClientData clientData);
+typedef void (AuxDataFreeProc) (ClientData clientData);
+typedef void (AuxDataPrintProc)(ClientData clientData,
+ Tcl_Obj *appendObj, struct ByteCode *codePtr,
+ unsigned int pcOffset);
/*
* We define a separate AuxDataType struct to hold type-related information
* for the AuxData structure. This separation makes it possible for clients
- * outside of the TCL core to manipulate (in a limited fashion!) AuxData;
- * for example, it makes it possible to pickle and unpickle AuxData structs.
+ * outside of the TCL core to manipulate (in a limited fashion!) AuxData; for
+ * example, it makes it possible to pickle and unpickle AuxData structs.
*/
typedef struct AuxDataType {
- char *name; /* the name of the type. Types can be
- * registered and found by name */
- AuxDataDupProc *dupProc; /* Callback procedure to invoke when the
- * aux data is duplicated (e.g., when the
- * ByteCode structure containing the aux
- * data is duplicated). NULL means just
- * copy the source clientData bits; no
- * proc need be called. */
- AuxDataFreeProc *freeProc; /* Callback procedure to invoke when the
- * aux data is freed. NULL means no
- * proc need be called. */
+ char *name; /* The name of the type. Types can be
+ * registered and found by name */
+ AuxDataDupProc *dupProc; /* Callback procedure to invoke when the aux
+ * data is duplicated (e.g., when the ByteCode
+ * structure containing the aux data is
+ * duplicated). NULL means just copy the
+ * source clientData bits; no proc need be
+ * called. */
+ AuxDataFreeProc *freeProc; /* Callback procedure to invoke when the aux
+ * data is freed. NULL means no proc need be
+ * called. */
+ AuxDataPrintProc *printProc;/* Callback function to invoke when printing
+ * the aux data as part of debugging. NULL
+ * means that the data can't be printed. */
} AuxDataType;
/*
@@ -203,8 +207,8 @@ typedef struct AuxDataType {
*/
typedef struct AuxData {
- AuxDataType *type; /* pointer to the AuxData type associated with
- * this ClientData. */
+ AuxDataType *type; /* Pointer to the AuxData type associated with
+ * this ClientData. */
ClientData clientData; /* The compilation data itself. */
} AuxData;
@@ -222,90 +226,91 @@ typedef struct AuxData {
typedef struct CompileEnv {
Interp *iPtr; /* Interpreter containing the code being
- * compiled. Commands and their compile
- * procs are specific to an interpreter so
- * the code emitted will depend on the
- * interpreter. */
- char *source; /* The source string being compiled by
+ * compiled. Commands and their compile procs
+ * are specific to an interpreter so the code
+ * emitted will depend on the interpreter. */
+ const char *source; /* The source string being compiled by
* SetByteCodeFromAny. This pointer is not
* owned by the CompileEnv and must not be
* freed or changed by it. */
int numSrcBytes; /* Number of bytes in source. */
- Proc *procPtr; /* If a procedure is being compiled, a
- * pointer to its Proc structure; otherwise
- * NULL. Used to compile local variables.
- * Set from information provided by
- * ObjInterpProc in tclProc.c. */
+ Proc *procPtr; /* If a procedure is being compiled, a pointer
+ * to its Proc structure; otherwise NULL. Used
+ * to compile local variables. Set from
+ * information provided by ObjInterpProc in
+ * tclProc.c. */
int numCommands; /* Number of commands compiled. */
- int exceptDepth; /* Current exception range nesting level;
- * -1 if not in any range currently. */
- int maxExceptDepth; /* Max nesting level of exception ranges;
- * -1 if no ranges have been compiled. */
- int maxStackDepth; /* Maximum number of stack elements needed
- * to execute the code. Set by compilation
+ int exceptDepth; /* Current exception range nesting level; -1
+ * if not in any range currently. */
+ int maxExceptDepth; /* Max nesting level of exception ranges; -1
+ * if no ranges have been compiled. */
+ int maxStackDepth; /* Maximum number of stack elements needed to
+ * execute the code. Set by compilation
* procedures before returning. */
- int currStackDepth; /* Current stack depth. */
- LiteralTable localLitTable; /* Contains LiteralEntry's describing
- * all Tcl objects referenced by this
- * compiled code. Indexed by the string
- * representations of the literals. Used to
- * avoid creating duplicate objects. */
+ int currStackDepth; /* Current stack depth. */
+ LiteralTable localLitTable; /* Contains LiteralEntry's describing all Tcl
+ * objects referenced by this compiled code.
+ * Indexed by the string representations of
+ * the literals. Used to avoid creating
+ * duplicate objects. */
unsigned char *codeStart; /* Points to the first byte of the code. */
unsigned char *codeNext; /* Points to next code array byte to use. */
- unsigned char *codeEnd; /* Points just after the last allocated
- * code array byte. */
- int mallocedCodeArray; /* Set 1 if code array was expanded
- * and codeStart points into the heap.*/
+ unsigned char *codeEnd; /* Points just after the last allocated code
+ * array byte. */
+ int mallocedCodeArray; /* Set 1 if code array was expanded and
+ * codeStart points into the heap.*/
LiteralEntry *literalArrayPtr;
/* Points to start of LiteralEntry array. */
int literalArrayNext; /* Index of next free object array entry. */
int literalArrayEnd; /* Index just after last obj array entry. */
- int mallocedLiteralArray; /* 1 if object array was expanded and
- * objArray points into the heap, else 0. */
+ int mallocedLiteralArray; /* 1 if object array was expanded and objArray
+ * points into the heap, else 0. */
ExceptionRange *exceptArrayPtr;
/* Points to start of the ExceptionRange
* array. */
int exceptArrayNext; /* Next free ExceptionRange array index.
- * exceptArrayNext is the number of ranges
- * and (exceptArrayNext-1) is the index of
- * the current range's array entry. */
- int exceptArrayEnd; /* Index after the last ExceptionRange
- * array entry. */
- int mallocedExceptArray; /* 1 if ExceptionRange array was expanded
- * and exceptArrayPtr points in heap,
- * else 0. */
+ * exceptArrayNext is the number of ranges and
+ * (exceptArrayNext-1) is the index of the
+ * current range's array entry. */
+ int exceptArrayEnd; /* Index after the last ExceptionRange array
+ * entry. */
+ int mallocedExceptArray; /* 1 if ExceptionRange array was expanded and
+ * exceptArrayPtr points in heap, else 0. */
CmdLocation *cmdMapPtr; /* Points to start of CmdLocation array.
- * numCommands is the index of the next
- * entry to use; (numCommands-1) is the
- * entry index for the last command. */
+ * numCommands is the index of the next entry
+ * to use; (numCommands-1) is the entry index
+ * for the last command. */
int cmdMapEnd; /* Index after last CmdLocation entry. */
int mallocedCmdMap; /* 1 if command map array was expanded and
* cmdMapPtr points in the heap, else 0. */
- AuxData *auxDataArrayPtr; /* Points to auxiliary data array start. */
+ AuxData *auxDataArrayPtr; /* Points to auxiliary data array start. */
int auxDataArrayNext; /* Next free compile aux data array index.
- * auxDataArrayNext is the number of aux
- * data items and (auxDataArrayNext-1) is
- * index of current aux data array entry. */
+ * auxDataArrayNext is the number of aux data
+ * items and (auxDataArrayNext-1) is index of
+ * current aux data array entry. */
int auxDataArrayEnd; /* Index after last aux data array entry. */
int mallocedAuxDataArray; /* 1 if aux data array was expanded and
* auxDataArrayPtr points in heap else 0. */
unsigned char staticCodeSpace[COMPILEENV_INIT_CODE_BYTES];
- /* Initial storage for code. */
+ /* Initial storage for code. */
LiteralEntry staticLiteralSpace[COMPILEENV_INIT_NUM_OBJECTS];
- /* Initial storage of LiteralEntry array. */
+ /* Initial storage of LiteralEntry array. */
ExceptionRange staticExceptArraySpace[COMPILEENV_INIT_EXCEPT_RANGES];
- /* Initial ExceptionRange array storage. */
+ /* Initial ExceptionRange array storage. */
CmdLocation staticCmdMapSpace[COMPILEENV_INIT_CMD_MAP_SIZE];
- /* Initial storage for cmd location map. */
+ /* Initial storage for cmd location map. */
AuxData staticAuxDataArraySpace[COMPILEENV_INIT_AUX_DATA_SIZE];
- /* Initial storage for aux data array. */
-#ifdef TCL_TIP280
+ /* Initial storage for aux data array. */
/* TIP #280 */
- ExtCmdLoc* extCmdMapPtr; /* Extended command location information
- * for 'info frame'. */
- int line; /* First line of the script, based on the
+ ExtCmdLoc *extCmdMapPtr; /* Extended command location information for
+ * 'info frame'. */
+ int line; /* First line of the script, based on the
* invoking context, then the line of the
* command currently compiled. */
+ int atCmdStart; /* Flag to say whether an INST_START_CMD
+ * should be issued; they should never be
+ * issued repeatedly, as that is significantly
+ * inefficient. */
ContLineLoc* clLoc; /* If not NULL, the table holding the
* locations of the invisible continuation
* lines in the input script, to adjust the
@@ -313,26 +318,33 @@ typedef struct CompileEnv {
int* clNext; /* If not NULL, it refers to the next slot in
* clLoc to check for an invisible
* continuation line. */
-#endif
} CompileEnv;
/*
- * The structure defining the bytecode instructions resulting from compiling
- * a Tcl script. Note that this structure is variable length: a single heap
- * object is allocated to hold the ByteCode structure immediately followed
- * by the code bytes, the literal object array, the ExceptionRange array,
- * the CmdLocation map, and the compilation AuxData array.
+ * The structure defining the bytecode instructions resulting from compiling a
+ * Tcl script. Note that this structure is variable length: a single heap
+ * object is allocated to hold the ByteCode structure immediately followed by
+ * the code bytes, the literal object array, the ExceptionRange array, the
+ * CmdLocation map, and the compilation AuxData array.
*/
/*
* A PRECOMPILED bytecode struct is one that was generated from a compiled
* image rather than implicitly compiled from source
*/
+
#define TCL_BYTECODE_PRECOMPILED 0x0001
+/*
+ * When a bytecode is compiled, interp or namespace resolvers have not been
+ * applied yet: this is indicated by the TCL_BYTECODE_RESOLVE_VARS flag.
+ */
+
+#define TCL_BYTECODE_RESOLVE_VARS 0x0002
+
typedef struct ByteCode {
TclHandle interpHandle; /* Handle for interpreter containing the
- * compiled code. Commands and their compile
+ * compiled code. Commands and their compile
* procs are specific to an interpreter so the
* code emitted will depend on the
* interpreter. */
@@ -340,25 +352,25 @@ typedef struct ByteCode {
* ByteCode was compiled. Used to invalidate
* code when, e.g., commands with compile
* procs are redefined. */
- Namespace *nsPtr; /* Namespace context in which this code
- * was compiled. If the code is executed
- * if a different namespace, it must be
+ Namespace *nsPtr; /* Namespace context in which this code was
+ * compiled. If the code is executed if a
+ * different namespace, it must be
* recompiled. */
int nsEpoch; /* Value of nsPtr->resolverEpoch when this
* ByteCode was compiled. Used to invalidate
* code when new namespace resolution rules
* are put into effect. */
- int refCount; /* Reference count: set 1 when created
- * plus 1 for each execution of the code
- * currently active. This structure can be
- * freed when refCount becomes zero. */
+ int refCount; /* Reference count: set 1 when created plus 1
+ * for each execution of the code currently
+ * active. This structure can be freed when
+ * refCount becomes zero. */
unsigned int flags; /* flags describing state for the codebyte.
- * this variable holds ORed values from the
- * TCL_BYTECODE_ masks defined above */
- char *source; /* The source string from which this
- * ByteCode was compiled. Note that this
- * pointer is not owned by the ByteCode and
- * must not be freed or modified by it. */
+ * this variable holds ORed values from the
+ * TCL_BYTECODE_ masks defined above */
+ const char *source; /* The source string from which this ByteCode
+ * was compiled. Note that this pointer is not
+ * owned by the ByteCode and must not be freed
+ * or modified by it. */
Proc *procPtr; /* If the ByteCode was compiled from a
* procedure body, this is a pointer to its
* Proc structure; otherwise NULL. This
@@ -374,71 +386,72 @@ typedef struct ByteCode {
int numLitObjects; /* Number of objects in literal array. */
int numExceptRanges; /* Number of ExceptionRange array elems. */
int numAuxDataItems; /* Number of AuxData items. */
- int numCmdLocBytes; /* Number of bytes needed for encoded
- * command location information. */
+ int numCmdLocBytes; /* Number of bytes needed for encoded command
+ * location information. */
int maxExceptDepth; /* Maximum nesting level of ExceptionRanges;
* -1 if no ranges were compiled. */
- int maxStackDepth; /* Maximum number of stack elements needed
- * to execute the code. */
- unsigned char *codeStart; /* Points to the first byte of the code.
- * This is just after the final ByteCode
- * member cmdMapPtr. */
- Tcl_Obj **objArrayPtr; /* Points to the start of the literal
- * object array. This is just after the
- * last code byte. */
+ int maxStackDepth; /* Maximum number of stack elements needed to
+ * execute the code. */
+ unsigned char *codeStart; /* Points to the first byte of the code. This
+ * is just after the final ByteCode member
+ * cmdMapPtr. */
+ Tcl_Obj **objArrayPtr; /* Points to the start of the literal object
+ * array. This is just after the last code
+ * byte. */
ExceptionRange *exceptArrayPtr;
/* Points to the start of the ExceptionRange
- * array. This is just after the last
- * object in the object array. */
- AuxData *auxDataArrayPtr; /* Points to the start of the auxiliary data
- * array. This is just after the last entry
- * in the ExceptionRange array. */
+ * array. This is just after the last object
+ * in the object array. */
+ AuxData *auxDataArrayPtr; /* Points to the start of the auxiliary data
+ * array. This is just after the last entry in
+ * the ExceptionRange array. */
unsigned char *codeDeltaStart;
- /* Points to the first of a sequence of
- * bytes that encode the change in the
- * starting offset of each command's code.
- * If -127<=delta<=127, it is encoded as 1
- * byte, otherwise 0xFF (128) appears and
- * the delta is encoded by the next 4 bytes.
- * Code deltas are always positive. This
- * sequence is just after the last entry in
- * the AuxData array. */
+ /* Points to the first of a sequence of bytes
+ * that encode the change in the starting
+ * offset of each command's code. If -127 <=
+ * delta <= 127, it is encoded as 1 byte,
+ * otherwise 0xFF (128) appears and the delta
+ * is encoded by the next 4 bytes. Code deltas
+ * are always positive. This sequence is just
+ * after the last entry in the AuxData
+ * array. */
unsigned char *codeLengthStart;
- /* Points to the first of a sequence of
- * bytes that encode the length of each
- * command's code. The encoding is the same
- * as for code deltas. Code lengths are
- * always positive. This sequence is just
- * after the last entry in the code delta
- * sequence. */
+ /* Points to the first of a sequence of bytes
+ * that encode the length of each command's
+ * code. The encoding is the same as for code
+ * deltas. Code lengths are always positive.
+ * This sequence is just after the last entry
+ * in the code delta sequence. */
unsigned char *srcDeltaStart;
- /* Points to the first of a sequence of
- * bytes that encode the change in the
- * starting offset of each command's source.
- * The encoding is the same as for code
- * deltas. Source deltas can be negative.
- * This sequence is just after the last byte
- * in the code length sequence. */
+ /* Points to the first of a sequence of bytes
+ * that encode the change in the starting
+ * offset of each command's source. The
+ * encoding is the same as for code deltas.
+ * Source deltas can be negative. This
+ * sequence is just after the last byte in the
+ * code length sequence. */
unsigned char *srcLengthStart;
- /* Points to the first of a sequence of
- * bytes that encode the length of each
- * command's source. The encoding is the
- * same as for code deltas. Source lengths
- * are always positive. This sequence is
- * just after the last byte in the source
- * delta sequence. */
+ /* Points to the first of a sequence of bytes
+ * that encode the length of each command's
+ * source. The encoding is the same as for
+ * code deltas. Source lengths are always
+ * positive. This sequence is just after the
+ * last byte in the source delta sequence. */
+ LocalCache *localCachePtr; /* Pointer to the start of the cached variable
+ * names and initialisation data for local
+ * variables. */
#ifdef TCL_COMPILE_STATS
Tcl_Time createTime; /* Absolute time when the ByteCode was
* created. */
#endif /* TCL_COMPILE_STATS */
} ByteCode;
-
+
/*
- * Opcodes for the Tcl bytecode instructions. These must correspond to
- * the entries in the table of instruction descriptions,
- * tclInstructionTable, in tclCompile.c. Also, the order and number of
- * the expression opcodes (e.g., INST_LOR) must match the entries in
- * the array operatorStrings in tclExecute.c.
+ * Opcodes for the Tcl bytecode instructions. These must correspond to the
+ * entries in the table of instruction descriptions, tclInstructionTable, in
+ * tclCompile.c. Also, the order and number of the expression opcodes (e.g.,
+ * INST_LOR) must match the entries in the array operatorStrings in
+ * tclExecute.c.
*/
/* Opcodes 0 to 9 */
@@ -487,7 +500,7 @@ typedef struct ByteCode {
#define INST_JUMP_TRUE1 36
#define INST_JUMP_TRUE4 37
#define INST_JUMP_FALSE1 38
-#define INST_JUMP_FALSE4 39
+#define INST_JUMP_FALSE4 39
/* Opcodes 40 to 64 */
#define INST_LOR 40
@@ -564,24 +577,104 @@ typedef struct ByteCode {
#define INST_LIST_INDEX_MULTI 94
/*
- * TIP #33 - 'lset' command. Code gen also required a Forth-like
- * OVER operation.
+ * TIP #33 - 'lset' command. Code gen also required a Forth-like
+ * OVER operation.
*/
-#define INST_OVER 95
+#define INST_OVER 95
#define INST_LSET_LIST 96
-#define INST_LSET_FLAT 97
+#define INST_LSET_FLAT 97
-/* The last opcode */
-#define LAST_INST_OPCODE 97
+/* TIP#90 - 'return' command. */
+
+#define INST_RETURN_IMM 98
+
+/* TIP#123 - exponentiation operator. */
+
+#define INST_EXPON 99
+
+/* TIP #157 - {*}... (word expansion) language syntax support. */
+
+#define INST_EXPAND_START 100
+#define INST_EXPAND_STKTOP 101
+#define INST_INVOKE_EXPANDED 102
+
+/*
+ * TIP #57 - 'lassign' command. Code generation requires immediate
+ * LINDEX and LRANGE operators.
+ */
+
+#define INST_LIST_INDEX_IMM 103
+#define INST_LIST_RANGE_IMM 104
+
+#define INST_START_CMD 105
+
+#define INST_LIST_IN 106
+#define INST_LIST_NOT_IN 107
+
+#define INST_PUSH_RETURN_OPTIONS 108
+#define INST_RETURN_STK 109
+
+/*
+ * Dictionary (TIP#111) related commands.
+ */
+
+#define INST_DICT_GET 110
+#define INST_DICT_SET 111
+#define INST_DICT_UNSET 112
+#define INST_DICT_INCR_IMM 113
+#define INST_DICT_APPEND 114
+#define INST_DICT_LAPPEND 115
+#define INST_DICT_FIRST 116
+#define INST_DICT_NEXT 117
+#define INST_DICT_DONE 118
+#define INST_DICT_UPDATE_START 119
+#define INST_DICT_UPDATE_END 120
/*
- * Table describing the Tcl bytecode instructions: their name (for
- * displaying code), total number of code bytes required (including
- * operand bytes), and a description of the type of each operand.
- * These operand types include signed and unsigned integers of length
- * one and four bytes. The unsigned integers are used for indexes or
- * for, e.g., the count of objects to push in a "push" instruction.
+ * Instruction to support jumps defined by tables (instead of the classic
+ * [switch] technique of chained comparisons).
+ */
+
+#define INST_JUMP_TABLE 121
+
+/*
+ * Instructions to support compilation of global, variable, upvar and
+ * [namespace upvar].
+ */
+
+#define INST_UPVAR 122
+#define INST_NSUPVAR 123
+#define INST_VARIABLE 124
+
+/* Instruction to support compiling syntax error to bytecode */
+
+#define INST_SYNTAX 125
+
+/* Instruction to reverse N items on top of stack */
+
+#define INST_REVERSE 126
+
+/* regexp instruction */
+
+#define INST_REGEXP 127
+
+/* For [info exists] compilation */
+#define INST_EXIST_SCALAR 128
+#define INST_EXIST_ARRAY 129
+#define INST_EXIST_ARRAY_STK 130
+#define INST_EXIST_STK 131
+
+/* The last opcode */
+#define LAST_INST_OPCODE 131
+
+/*
+ * Table describing the Tcl bytecode instructions: their name (for displaying
+ * code), total number of code bytes required (including operand bytes), and a
+ * description of the type of each operand. These operand types include signed
+ * and unsigned integers of length one and four bytes. The unsigned integers
+ * are used for indexes or for, e.g., the count of objects to push in a "push"
+ * instruction.
*/
#define MAX_INSTRUCTION_OPERANDS 2
@@ -591,94 +684,43 @@ typedef enum InstOperandType {
OPERAND_INT1, /* One byte signed integer. */
OPERAND_INT4, /* Four byte signed integer. */
OPERAND_UINT1, /* One byte unsigned integer. */
- OPERAND_UINT4 /* Four byte unsigned integer. */
+ OPERAND_UINT4, /* Four byte unsigned integer. */
+ OPERAND_IDX4, /* Four byte signed index (actually an
+ * integer, but displayed differently.) */
+ OPERAND_LVT1, /* One byte unsigned index into the local
+ * variable table. */
+ OPERAND_LVT4, /* Four byte unsigned index into the local
+ * variable table. */
+ OPERAND_AUX4 /* Four byte unsigned index into the aux data
+ * table. */
} InstOperandType;
typedef struct InstructionDesc {
char *name; /* Name of instruction. */
int numBytes; /* Total number of bytes for instruction. */
- int stackEffect; /* The worst-case balance stack effect of the
- * instruction, used for stack requirements
+ int stackEffect; /* The worst-case balance stack effect of the
+ * instruction, used for stack requirements
* computations. The value INT_MIN signals
- * that the instruction's worst case effect
- * is (1-opnd1).
- */
+ * that the instruction's worst case effect is
+ * (1-opnd1). */
int numOperands; /* Number of operands. */
InstOperandType opTypes[MAX_INSTRUCTION_OPERANDS];
/* The type of each operand. */
} InstructionDesc;
-extern InstructionDesc tclInstructionTable[];
-
-/*
- * Definitions of the values of the INST_CALL_BUILTIN_FUNC instruction's
- * operand byte. Each value denotes a builtin Tcl math function. These
- * values must correspond to the entries in the tclBuiltinFuncTable array
- * below and to the values stored in the tclInt.h MathFunc structure's
- * builtinFuncIndex field.
- */
-
-#define BUILTIN_FUNC_ACOS 0
-#define BUILTIN_FUNC_ASIN 1
-#define BUILTIN_FUNC_ATAN 2
-#define BUILTIN_FUNC_ATAN2 3
-#define BUILTIN_FUNC_CEIL 4
-#define BUILTIN_FUNC_COS 5
-#define BUILTIN_FUNC_COSH 6
-#define BUILTIN_FUNC_EXP 7
-#define BUILTIN_FUNC_FLOOR 8
-#define BUILTIN_FUNC_FMOD 9
-#define BUILTIN_FUNC_HYPOT 10
-#define BUILTIN_FUNC_LOG 11
-#define BUILTIN_FUNC_LOG10 12
-#define BUILTIN_FUNC_POW 13
-#define BUILTIN_FUNC_SIN 14
-#define BUILTIN_FUNC_SINH 15
-#define BUILTIN_FUNC_SQRT 16
-#define BUILTIN_FUNC_TAN 17
-#define BUILTIN_FUNC_TANH 18
-#define BUILTIN_FUNC_ABS 19
-#define BUILTIN_FUNC_DOUBLE 20
-#define BUILTIN_FUNC_INT 21
-#define BUILTIN_FUNC_RAND 22
-#define BUILTIN_FUNC_ROUND 23
-#define BUILTIN_FUNC_SRAND 24
-#define BUILTIN_FUNC_WIDE 25
-
-#define LAST_BUILTIN_FUNC 25
-
-/*
- * Table describing the built-in math functions. Entries in this table are
- * indexed by the values of the INST_CALL_BUILTIN_FUNC instruction's
- * operand byte.
- */
-
-typedef int (CallBuiltinFuncProc) _ANSI_ARGS_((Tcl_Interp *interp,
- ExecEnv *eePtr, ClientData clientData));
-
-typedef struct {
- char *name; /* Name of function. */
- int numArgs; /* Number of arguments for function. */
- Tcl_ValueType argTypes[MAX_MATH_ARGS];
- /* Acceptable types for each argument. */
- CallBuiltinFuncProc *proc; /* Procedure implementing this function. */
- ClientData clientData; /* Additional argument to pass to the
- * function when invoking it. */
-} BuiltinFunc;
-
-extern BuiltinFunc tclBuiltinFuncTable[];
+MODULE_SCOPE InstructionDesc tclInstructionTable[];
/*
* Compilation of some Tcl constructs such as if commands and the logical or
- * (||) and logical and (&&) operators in expressions requires the
- * generation of forward jumps. Since the PC target of these jumps isn't
- * known when the jumps are emitted, we record the offset of each jump in an
- * array of JumpFixup structures. There is one array for each sequence of
- * jumps to one target PC. When we learn the target PC, we update the jumps
- * with the correct distance. Also, if the distance is too great (> 127
- * bytes), we replace the single-byte jump with a four byte jump
- * instruction, move the instructions after the jump down, and update the
- * code offsets for any commands between the jump and the target.
+ * (||) and logical and (&&) operators in expressions requires the generation
+ * of forward jumps. Since the PC target of these jumps isn't known when the
+ * jumps are emitted, we record the offset of each jump in an array of
+ * JumpFixup structures. There is one array for each sequence of jumps to one
+ * target PC. When we learn the target PC, we update the jumps with the
+ * correct distance. Also, if the distance is too great (> 127 bytes), we
+ * replace the single-byte jump with a four byte jump instruction, move the
+ * instructions after the jump down, and update the code offsets for any
+ * commands between the jump and the target.
*/
typedef enum {
@@ -697,14 +739,14 @@ typedef struct JumpFixup {
* commands if the two-byte jump at jumpPc
* must be replaced with a five-byte one. */
int exceptIndex; /* Index of the first range entry in the
- * ExceptionRange array after the current
- * one. This field is used to adjust the
- * code offsets in subsequent ExceptionRange
+ * ExceptionRange array after the current one.
+ * This field is used to adjust the code
+ * offsets in subsequent ExceptionRange
* records when a jump is grown from 2 bytes
* to 5 bytes. */
} JumpFixup;
-#define JUMPFIXUP_INIT_ENTRIES 10
+#define JUMPFIXUP_INIT_ENTRIES 10
typedef struct JumpFixupArray {
JumpFixup *fixup; /* Points to start of jump fixup array. */
@@ -717,21 +759,21 @@ typedef struct JumpFixupArray {
} JumpFixupArray;
/*
- * The structure describing one variable list of a foreach command. Note
- * that only foreach commands inside procedure bodies are compiled inline so
- * a ForeachVarList structure always describes local variables. Furthermore,
+ * The structure describing one variable list of a foreach command. Note that
+ * only foreach commands inside procedure bodies are compiled inline so a
+ * ForeachVarList structure always describes local variables. Furthermore,
* only scalar variables are supported for inline-compiled foreach loops.
*/
typedef struct ForeachVarList {
int numVars; /* The number of variables in the list. */
int varIndexes[1]; /* An array of the indexes ("slot numbers")
- * for each variable in the procedure's
- * array of local variables. Only scalar
- * variables are supported. The actual
- * size of this field will be large enough
- * to numVars indexes. THIS MUST BE THE
- * LAST FIELD IN THE STRUCTURE! */
+ * for each variable in the procedure's array
+ * of local variables. Only scalar variables
+ * are supported. The actual size of this
+ * field will be large enough to numVars
+ * indexes. THIS MUST BE THE LAST FIELD IN THE
+ * STRUCTURE! */
} ForeachVarList;
/*
@@ -743,281 +785,360 @@ typedef struct ForeachVarList {
typedef struct ForeachInfo {
int numLists; /* The number of both the variable and value
* lists of the foreach command. */
- int firstValueTemp; /* Index of the first temp var in a proc
- * frame used to point to a value list. */
- int loopCtTemp; /* Index of temp var in a proc frame
- * holding the loop's iteration count. Used
- * to determine next value list element to
- * assign each loop var. */
+ int firstValueTemp; /* Index of the first temp var in a proc frame
+ * used to point to a value list. */
+ int loopCtTemp; /* Index of temp var in a proc frame holding
+ * the loop's iteration count. Used to
+ * determine next value list element to assign
+ * each loop var. */
ForeachVarList *varLists[1];/* An array of pointers to ForeachVarList
* structures describing each var list. The
* actual size of this field will be large
- * enough to numVars indexes. THIS MUST BE
- * THE LAST FIELD IN THE STRUCTURE! */
+ * enough to numVars indexes. THIS MUST BE THE
+ * LAST FIELD IN THE STRUCTURE! */
} ForeachInfo;
-extern AuxDataType tclForeachInfoType;
+MODULE_SCOPE AuxDataType tclForeachInfoType;
+
+/*
+ * Structure used to hold information about a switch command that is needed
+ * during program execution. These structures are stored in CompileEnv and
+ * ByteCode structures as auxiliary data.
+ */
+
+typedef struct JumptableInfo {
+ Tcl_HashTable hashTable; /* Hash that maps strings to signed ints (PC
+ * offsets). */
+} JumptableInfo;
+
+MODULE_SCOPE AuxDataType tclJumptableInfoType;
+
+/*
+ * Structure used to hold information about a [dict update] command that is
+ * needed during program execution. These structures are stored in CompileEnv
+ * and ByteCode structures as auxiliary data.
+ */
+
+typedef struct {
+ int length; /* Size of array */
+ int varIndices[1]; /* Array of variable indices to manage when
+ * processing the start and end of a [dict
+ * update]. There is really more than one
+ * entry, and the structure is allocated to
+ * take account of this. MUST BE LAST FIELD IN
+ * STRUCTURE. */
+} DictUpdateInfo;
+
+MODULE_SCOPE AuxDataType tclDictUpdateInfoType;
+/*
+ * ClientData type used by the math operator commands.
+ */
+typedef struct {
+ const char *op; /* Do not call it 'operator': C++ reserved */
+ const char *expected;
+ union {
+ int numArgs;
+ int identity;
+ } i;
+} TclOpCmdClientData;
+
/*
*----------------------------------------------------------------
* Procedures exported by tclBasic.c to be used within the engine.
*----------------------------------------------------------------
*/
-EXTERN int TclEvalObjvInternal _ANSI_ARGS_((Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[], CONST char *command, int length,
- int flags));
-EXTERN int TclInterpReady _ANSI_ARGS_((Tcl_Interp *interp));
-
-
+MODULE_SCOPE int TclEvalObjvInternal(Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[],
+ CONST char *command, int length, int flags);
/*
*----------------------------------------------------------------
* Procedures exported by the engine to be used by tclBasic.c
*----------------------------------------------------------------
*/
-#ifndef TCL_TIP280
-EXTERN int TclCompEvalObj _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
-#else
-EXTERN int TclCompEvalObj _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr, CONST CmdFrame* invoker,
- int word));
-#endif
+MODULE_SCOPE int TclCompEvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ const CmdFrame *invoker, int word);
/*
*----------------------------------------------------------------
- * Procedures shared among Tcl bytecode compilation and execution
- * modules but not used outside:
+ * Procedures shared among Tcl bytecode compilation and execution modules but
+ * not used outside:
*----------------------------------------------------------------
*/
-EXTERN void TclCleanupByteCode _ANSI_ARGS_((ByteCode *codePtr));
-EXTERN int TclCompileCmdWord _ANSI_ARGS_((Tcl_Interp *interp,
+MODULE_SCOPE void TclCleanupByteCode(ByteCode *codePtr);
+MODULE_SCOPE void TclCompileCmdWord(Tcl_Interp *interp,
Tcl_Token *tokenPtr, int count,
- CompileEnv *envPtr));
-EXTERN int TclCompileExpr _ANSI_ARGS_((Tcl_Interp *interp,
- CONST char *script, int numBytes,
- CompileEnv *envPtr));
-EXTERN int TclCompileExprWords _ANSI_ARGS_((Tcl_Interp *interp,
+ CompileEnv *envPtr);
+MODULE_SCOPE void TclCompileExpr(Tcl_Interp *interp, CONST char *script,
+ int numBytes, CompileEnv *envPtr, int optimize);
+MODULE_SCOPE void TclCompileExprWords(Tcl_Interp *interp,
Tcl_Token *tokenPtr, int numWords,
- CompileEnv *envPtr));
-EXTERN int TclCompileScript _ANSI_ARGS_((Tcl_Interp *interp,
- CONST char *script, int numBytes, int nested,
- CompileEnv *envPtr));
-EXTERN int TclCompileTokens _ANSI_ARGS_((Tcl_Interp *interp,
+ CompileEnv *envPtr);
+MODULE_SCOPE void TclCompileScript(Tcl_Interp *interp,
+ CONST char *script, int numBytes,
+ CompileEnv *envPtr);
+MODULE_SCOPE void TclCompileSyntaxError(Tcl_Interp *interp,
+ CompileEnv *envPtr);
+MODULE_SCOPE void TclCompileTokens(Tcl_Interp *interp,
Tcl_Token *tokenPtr, int count,
- CompileEnv *envPtr));
-EXTERN int TclCreateAuxData _ANSI_ARGS_((ClientData clientData,
- AuxDataType *typePtr, CompileEnv *envPtr));
-EXTERN int TclCreateExceptRange _ANSI_ARGS_((
- ExceptionRangeType type, CompileEnv *envPtr));
-EXTERN ExecEnv * TclCreateExecEnv _ANSI_ARGS_((Tcl_Interp *interp));
-EXTERN void TclDeleteExecEnv _ANSI_ARGS_((ExecEnv *eePtr));
-EXTERN void TclDeleteLiteralTable _ANSI_ARGS_((
- Tcl_Interp *interp, LiteralTable *tablePtr));
-EXTERN void TclEmitForwardJump _ANSI_ARGS_((CompileEnv *envPtr,
- TclJumpType jumpType, JumpFixup *jumpFixupPtr));
-EXTERN ExceptionRange * TclGetExceptionRangeForPc _ANSI_ARGS_((
- unsigned char *pc, int catchOnly,
- ByteCode* codePtr));
-EXTERN void TclExpandJumpFixupArray _ANSI_ARGS_((
- JumpFixupArray *fixupArrayPtr));
-EXTERN void TclFinalizeAuxDataTypeTable _ANSI_ARGS_((void));
-EXTERN int TclFindCompiledLocal _ANSI_ARGS_((CONST char *name,
- int nameChars, int create, int flags,
- Proc *procPtr));
-EXTERN LiteralEntry * TclLookupLiteralEntry _ANSI_ARGS_((
- Tcl_Interp *interp, Tcl_Obj *objPtr));
-EXTERN int TclFixupForwardJump _ANSI_ARGS_((
- CompileEnv *envPtr, JumpFixup *jumpFixupPtr,
- int jumpDist, int distThreshold));
-EXTERN void TclFreeCompileEnv _ANSI_ARGS_((CompileEnv *envPtr));
-EXTERN void TclFreeJumpFixupArray _ANSI_ARGS_((
- JumpFixupArray *fixupArrayPtr));
-EXTERN void TclInitAuxDataTypeTable _ANSI_ARGS_((void));
-EXTERN void TclInitByteCodeObj _ANSI_ARGS_((Tcl_Obj *objPtr,
- CompileEnv *envPtr));
-EXTERN void TclInitCompilation _ANSI_ARGS_((void));
-#ifndef TCL_TIP280
-EXTERN void TclInitCompileEnv _ANSI_ARGS_((Tcl_Interp *interp,
- CompileEnv *envPtr, char *string,
- int numBytes));
-#else
-EXTERN void TclInitCompileEnv _ANSI_ARGS_((Tcl_Interp *interp,
- CompileEnv *envPtr, char *string,
- int numBytes, CONST CmdFrame* invoker, int word));
-#endif
-EXTERN void TclInitJumpFixupArray _ANSI_ARGS_((
- JumpFixupArray *fixupArrayPtr));
-EXTERN void TclInitLiteralTable _ANSI_ARGS_((
- LiteralTable *tablePtr));
+ CompileEnv *envPtr);
+MODULE_SCOPE int TclCreateAuxData(ClientData clientData,
+ AuxDataType *typePtr, CompileEnv *envPtr);
+MODULE_SCOPE int TclCreateExceptRange(ExceptionRangeType type,
+ CompileEnv *envPtr);
+MODULE_SCOPE ExecEnv * TclCreateExecEnv(Tcl_Interp *interp);
+MODULE_SCOPE Tcl_Obj * TclCreateLiteral(Interp *iPtr, char *bytes,
+ int length, unsigned int hash, int *newPtr,
+ Namespace *nsPtr, int flags,
+ LiteralEntry **globalPtrPtr);
+MODULE_SCOPE void TclDeleteExecEnv(ExecEnv *eePtr);
+MODULE_SCOPE void TclDeleteLiteralTable(Tcl_Interp *interp,
+ LiteralTable *tablePtr);
+MODULE_SCOPE void TclEmitForwardJump(CompileEnv *envPtr,
+ TclJumpType jumpType, JumpFixup *jumpFixupPtr);
+MODULE_SCOPE ExceptionRange * TclGetExceptionRangeForPc(unsigned char *pc,
+ int catchOnly, ByteCode* codePtr);
+MODULE_SCOPE void TclExpandJumpFixupArray(JumpFixupArray *fixupArrayPtr);
+MODULE_SCOPE int TclExecuteByteCode(Tcl_Interp *interp,
+ ByteCode *codePtr);
+MODULE_SCOPE void TclFinalizeAuxDataTypeTable(void);
+MODULE_SCOPE int TclFindCompiledLocal(CONST char *name, int nameChars,
+ int create, Proc *procPtr);
+MODULE_SCOPE LiteralEntry * TclLookupLiteralEntry(Tcl_Interp *interp,
+ Tcl_Obj *objPtr);
+MODULE_SCOPE int TclFixupForwardJump(CompileEnv *envPtr,
+ JumpFixup *jumpFixupPtr, int jumpDist,
+ int distThreshold);
+MODULE_SCOPE void TclFreeCompileEnv(CompileEnv *envPtr);
+MODULE_SCOPE void TclFreeJumpFixupArray(JumpFixupArray *fixupArrayPtr);
+MODULE_SCOPE void TclInitAuxDataTypeTable(void);
+MODULE_SCOPE void TclInitByteCodeObj(Tcl_Obj *objPtr,
+ CompileEnv *envPtr);
+MODULE_SCOPE void TclInitCompilation(void);
+MODULE_SCOPE void TclInitCompileEnv(Tcl_Interp *interp,
+ CompileEnv *envPtr, const char *string,
+ int numBytes, CONST CmdFrame* invoker, int word);
+MODULE_SCOPE void TclInitJumpFixupArray(JumpFixupArray *fixupArrayPtr);
+MODULE_SCOPE void TclInitLiteralTable(LiteralTable *tablePtr);
#ifdef TCL_COMPILE_STATS
-EXTERN char * TclLiteralStats _ANSI_ARGS_((
- LiteralTable *tablePtr));
-EXTERN int TclLog2 _ANSI_ARGS_((int value));
+MODULE_SCOPE char * TclLiteralStats(LiteralTable *tablePtr);
+MODULE_SCOPE int TclLog2(int value);
#endif
#ifdef TCL_COMPILE_DEBUG
-EXTERN void TclPrintByteCodeObj _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
+MODULE_SCOPE void TclPrintByteCodeObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr);
#endif
-EXTERN int TclPrintInstruction _ANSI_ARGS_((ByteCode* codePtr,
- unsigned char *pc));
-EXTERN void TclPrintObject _ANSI_ARGS_((FILE *outFile,
- Tcl_Obj *objPtr, int maxChars));
-EXTERN void TclPrintSource _ANSI_ARGS_((FILE *outFile,
- CONST char *string, int maxChars));
-EXTERN void TclRegisterAuxDataType _ANSI_ARGS_((AuxDataType *typePtr));
-EXTERN int TclRegisterLiteral _ANSI_ARGS_((CompileEnv *envPtr,
- char *bytes, int length, int onHeap));
-EXTERN void TclReleaseLiteral _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
-EXTERN void TclSetCmdNameObj _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr, Command *cmdPtr));
+MODULE_SCOPE int TclPrintInstruction(ByteCode* codePtr,
+ unsigned char *pc);
+MODULE_SCOPE void TclPrintObject(FILE *outFile,
+ Tcl_Obj *objPtr, int maxChars);
+MODULE_SCOPE void TclPrintSource(FILE *outFile,
+ CONST char *string, int maxChars);
+MODULE_SCOPE void TclRegisterAuxDataType(AuxDataType *typePtr);
+MODULE_SCOPE int TclRegisterLiteral(CompileEnv *envPtr,
+ char *bytes, int length, int flags);
+MODULE_SCOPE void TclReleaseLiteral(Tcl_Interp *interp, Tcl_Obj *objPtr);
+MODULE_SCOPE int TclSingleOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]);
+MODULE_SCOPE int TclSortingOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]);
+MODULE_SCOPE int TclVariadicOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]);
+MODULE_SCOPE int TclNoIdentOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]);
#ifdef TCL_COMPILE_DEBUG
-EXTERN void TclVerifyGlobalLiteralTable _ANSI_ARGS_((
- Interp *iPtr));
-EXTERN void TclVerifyLocalLiteralTable _ANSI_ARGS_((
- CompileEnv *envPtr));
+MODULE_SCOPE void TclVerifyGlobalLiteralTable(Interp *iPtr);
+MODULE_SCOPE void TclVerifyLocalLiteralTable(CompileEnv *envPtr);
#endif
-EXTERN int TclCompileVariableCmd _ANSI_ARGS_((
- Tcl_Interp *interp, Tcl_Parse *parsePtr, CompileEnv *envPtr));
-
+MODULE_SCOPE int TclWordKnownAtCompileTime(Tcl_Token *tokenPtr,
+ Tcl_Obj *valuePtr);
+
/*
*----------------------------------------------------------------
- * Macros used by Tcl bytecode compilation and execution modules
- * inside the Tcl core but not used outside.
+ * Macros and flag values used by Tcl bytecode compilation and execution
+ * modules inside the Tcl core but not used outside.
*----------------------------------------------------------------
*/
+#define LITERAL_ON_HEAP 0x01
+#define LITERAL_NS_SCOPE 0x02
+
/*
- * Form of TclRegisterLiteral with onHeap == 0.
- * In that case, it is safe to cast away CONSTness, and it
- * is cleanest to do that here, all in one place.
+ * Form of TclRegisterLiteral with onHeap == 0. In that case, it is safe to
+ * cast away CONSTness, and it is cleanest to do that here, all in one place.
+ *
+ * int TclRegisterNewLiteral(CompileEnv *envPtr, const char *bytes,
+ * int length);
*/
#define TclRegisterNewLiteral(envPtr, bytes, length) \
- TclRegisterLiteral(envPtr, (char *)(bytes), length, /*onHeap*/ 0)
+ TclRegisterLiteral(envPtr, (char *)(bytes), length, /*flags*/ 0)
/*
- * Macro used to update the stack requirements.
- * It is called by the macros TclEmitOpCode, TclEmitInst1 and
- * TclEmitInst4.
- * Remark that the very last instruction of a bytecode always
- * reduces the stack level: INST_DONE or INST_POP, so that the
- * maxStackdepth is always updated.
+ * Form of TclRegisterNSLiteral with onHeap == 0. In that case, it is safe to
+ * cast away CONSTness, and it is cleanest to do that here, all in one place.
+ *
+ * int TclRegisterNewNSLiteral(CompileEnv *envPtr, const char *bytes,
+ * int length);
+ */
+
+#define TclRegisterNewNSLiteral(envPtr, bytes, length) \
+ TclRegisterLiteral(envPtr, (char *)(bytes), length, \
+ /*flags*/ LITERAL_NS_SCOPE)
+
+/*
+ * Macro used to manually adjust the stack requirements; used in cases where
+ * the stack effect cannot be computed from the opcode and its operands, but
+ * is still known at compile time.
+ *
+ * void TclAdjustStackDepth(int delta, CompileEnv *envPtr);
+ */
+
+#define TclAdjustStackDepth(delta, envPtr) \
+ if ((delta) < 0) {\
+ if((envPtr)->maxStackDepth < (envPtr)->currStackDepth) {\
+ (envPtr)->maxStackDepth = (envPtr)->currStackDepth;\
+ }\
+ }\
+ (envPtr)->currStackDepth += (delta)
+
+/*
+ * Macro used to update the stack requirements. It is called by the macros
+ * TclEmitOpCode, TclEmitInst1 and TclEmitInst4.
+ * Remark that the very last instruction of a bytecode always reduces the
+ * stack level: INST_DONE or INST_POP, so that the maxStackdepth is always
+ * updated.
+ *
+ * void TclUpdateStackReqs(unsigned char op, int i, CompileEnv *envPtr);
*/
#define TclUpdateStackReqs(op, i, envPtr) \
{\
int delta = tclInstructionTable[(op)].stackEffect;\
if (delta) {\
- if (delta < 0) {\
- if((envPtr)->maxStackDepth < (envPtr)->currStackDepth) {\
- (envPtr)->maxStackDepth = (envPtr)->currStackDepth;\
- }\
- if (delta == INT_MIN) {\
- delta = 1 - (i);\
- }\
+ if (delta == INT_MIN) {\
+ delta = 1 - (i);\
}\
- (envPtr)->currStackDepth += delta;\
+ TclAdjustStackDepth(delta, envPtr);\
}\
}
/*
- * Macro to emit an opcode byte into a CompileEnv's code array.
- * The ANSI C "prototype" for this macro is:
+ * Macro to emit an opcode byte into a CompileEnv's code array. The ANSI C
+ * "prototype" for this macro is:
*
- * EXTERN void TclEmitOpcode _ANSI_ARGS_((unsigned char op,
- * CompileEnv *envPtr));
+ * void TclEmitOpcode(unsigned char op, CompileEnv *envPtr);
*/
#define TclEmitOpcode(op, envPtr) \
- if ((envPtr)->codeNext == (envPtr)->codeEnd) \
- TclExpandCodeArray(envPtr); \
+ if ((envPtr)->codeNext == (envPtr)->codeEnd) { \
+ TclExpandCodeArray(envPtr); \
+ } \
*(envPtr)->codeNext++ = (unsigned char) (op);\
+ (envPtr)->atCmdStart = ((op) == INST_START_CMD); \
TclUpdateStackReqs(op, 0, envPtr)
/*
- * Macro to emit an integer operand.
- * The ANSI C "prototype" for this macro is:
+ * Macros to emit an integer operand. The ANSI C "prototype" for these macros
+ * are:
*
- * EXTERN void TclEmitInt1 _ANSI_ARGS_((int i, CompileEnv *envPtr));
+ * void TclEmitInt1(int i, CompileEnv *envPtr);
+ * void TclEmitInt4(int i, CompileEnv *envPtr);
*/
#define TclEmitInt1(i, envPtr) \
- if ((envPtr)->codeNext == (envPtr)->codeEnd) \
- TclExpandCodeArray(envPtr); \
+ if ((envPtr)->codeNext == (envPtr)->codeEnd) { \
+ TclExpandCodeArray(envPtr); \
+ } \
*(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i))
+#define TclEmitInt4(i, envPtr) \
+ if (((envPtr)->codeNext + 4) > (envPtr)->codeEnd) { \
+ TclExpandCodeArray(envPtr); \
+ } \
+ *(envPtr)->codeNext++ = \
+ (unsigned char) ((unsigned int) (i) >> 24); \
+ *(envPtr)->codeNext++ = \
+ (unsigned char) ((unsigned int) (i) >> 16); \
+ *(envPtr)->codeNext++ = \
+ (unsigned char) ((unsigned int) (i) >> 8); \
+ *(envPtr)->codeNext++ = \
+ (unsigned char) ((unsigned int) (i) )
+
/*
* Macros to emit an instruction with signed or unsigned integer operands.
* Four byte integers are stored in "big-endian" order with the high order
- * byte stored at the lowest address.
- * The ANSI C "prototypes" for these macros are:
+ * byte stored at the lowest address. The ANSI C "prototypes" for these macros
+ * are:
*
- * EXTERN void TclEmitInstInt1 _ANSI_ARGS_((unsigned char op, int i,
- * CompileEnv *envPtr));
- * EXTERN void TclEmitInstInt4 _ANSI_ARGS_((unsigned char op, int i,
- * CompileEnv *envPtr));
+ * void TclEmitInstInt1(unsigned char op, int i, CompileEnv *envPtr);
+ * void TclEmitInstInt4(unsigned char op, int i, CompileEnv *envPtr);
*/
-
#define TclEmitInstInt1(op, i, envPtr) \
if (((envPtr)->codeNext + 2) > (envPtr)->codeEnd) { \
- TclExpandCodeArray(envPtr); \
+ TclExpandCodeArray(envPtr); \
} \
*(envPtr)->codeNext++ = (unsigned char) (op); \
*(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i));\
+ (envPtr)->atCmdStart = ((op) == INST_START_CMD); \
TclUpdateStackReqs(op, i, envPtr)
#define TclEmitInstInt4(op, i, envPtr) \
if (((envPtr)->codeNext + 5) > (envPtr)->codeEnd) { \
- TclExpandCodeArray(envPtr); \
+ TclExpandCodeArray(envPtr); \
} \
*(envPtr)->codeNext++ = (unsigned char) (op); \
*(envPtr)->codeNext++ = \
- (unsigned char) ((unsigned int) (i) >> 24); \
+ (unsigned char) ((unsigned int) (i) >> 24); \
*(envPtr)->codeNext++ = \
- (unsigned char) ((unsigned int) (i) >> 16); \
+ (unsigned char) ((unsigned int) (i) >> 16); \
*(envPtr)->codeNext++ = \
- (unsigned char) ((unsigned int) (i) >> 8); \
+ (unsigned char) ((unsigned int) (i) >> 8); \
*(envPtr)->codeNext++ = \
- (unsigned char) ((unsigned int) (i) );\
+ (unsigned char) ((unsigned int) (i) );\
+ (envPtr)->atCmdStart = ((op) == INST_START_CMD); \
TclUpdateStackReqs(op, i, envPtr)
-
+
/*
* Macro to push a Tcl object onto the Tcl evaluation stack. It emits the
- * object's one or four byte array index into the CompileEnv's code
- * array. These support, respectively, a maximum of 256 (2**8) and 2**32
- * objects in a CompileEnv. The ANSI C "prototype" for this macro is:
+ * object's one or four byte array index into the CompileEnv's code array.
+ * These support, respectively, a maximum of 256 (2**8) and 2**32 objects in a
+ * CompileEnv. The ANSI C "prototype" for this macro is:
*
- * EXTERN void TclEmitPush _ANSI_ARGS_((int objIndex, CompileEnv *envPtr));
+ * void TclEmitPush(int objIndex, CompileEnv *envPtr);
*/
#define TclEmitPush(objIndex, envPtr) \
{\
- register int objIndexCopy = (objIndex);\
- if (objIndexCopy <= 255) { \
+ register int objIndexCopy = (objIndex);\
+ if (objIndexCopy <= 255) { \
TclEmitInstInt1(INST_PUSH1, objIndexCopy, (envPtr)); \
- } else { \
+ } else { \
TclEmitInstInt4(INST_PUSH4, objIndexCopy, (envPtr)); \
}\
}
/*
- * Macros to update a (signed or unsigned) integer starting at a pointer.
- * The two variants depend on the number of bytes. The ANSI C "prototypes"
- * for these macros are:
+ * Macros to update a (signed or unsigned) integer starting at a pointer. The
+ * two variants depend on the number of bytes. The ANSI C "prototypes" for
+ * these macros are:
*
- * EXTERN void TclStoreInt1AtPtr _ANSI_ARGS_((int i, unsigned char *p));
- * EXTERN void TclStoreInt4AtPtr _ANSI_ARGS_((int i, unsigned char *p));
+ * void TclStoreInt1AtPtr(int i, unsigned char *p);
+ * void TclStoreInt4AtPtr(int i, unsigned char *p);
*/
-
+
#define TclStoreInt1AtPtr(i, p) \
*(p) = (unsigned char) ((unsigned int) (i))
-
+
#define TclStoreInt4AtPtr(i, p) \
*(p) = (unsigned char) ((unsigned int) (i) >> 24); \
*(p+1) = (unsigned char) ((unsigned int) (i) >> 16); \
@@ -1025,14 +1146,12 @@ EXTERN int TclCompileVariableCmd _ANSI_ARGS_((
*(p+3) = (unsigned char) ((unsigned int) (i) )
/*
- * Macros to update instructions at a particular pc with a new op code
- * and a (signed or unsigned) int operand. The ANSI C "prototypes" for
- * these macros are:
+ * Macros to update instructions at a particular pc with a new op code and a
+ * (signed or unsigned) int operand. The ANSI C "prototypes" for these macros
+ * are:
*
- * EXTERN void TclUpdateInstInt1AtPc _ANSI_ARGS_((unsigned char op, int i,
- * unsigned char *pc));
- * EXTERN void TclUpdateInstInt4AtPc _ANSI_ARGS_((unsigned char op, int i,
- * unsigned char *pc));
+ * void TclUpdateInstInt1AtPc(unsigned char op, int i, unsigned char *pc);
+ * void TclUpdateInstInt4AtPc(unsigned char op, int i, unsigned char *pc);
*/
#define TclUpdateInstInt1AtPc(op, i, pc) \
@@ -1042,26 +1161,39 @@ EXTERN int TclCompileVariableCmd _ANSI_ARGS_((
#define TclUpdateInstInt4AtPc(op, i, pc) \
*(pc) = (unsigned char) (op); \
TclStoreInt4AtPtr((i), ((pc)+1))
-
+
+/*
+ * Macro to fix up a forward jump to point to the current code-generation
+ * position in the bytecode being created (the most common case). The ANSI C
+ * "prototypes" for this macro is:
+ *
+ * int TclFixupForwardJumpToHere(CompileEnv *envPtr, JumpFixup *fixupPtr,
+ * int threshold);
+ */
+
+#define TclFixupForwardJumpToHere(envPtr, fixupPtr, threshold) \
+ TclFixupForwardJump((envPtr), (fixupPtr), \
+ (envPtr)->codeNext-(envPtr)->codeStart-(fixupPtr)->codeOffset, \
+ (threshold))
+
/*
* Macros to get a signed integer (GET_INT{1,2}) or an unsigned int
- * (GET_UINT{1,2}) from a pointer. There are two variants for each
- * return type that depend on the number of bytes fetched.
- * The ANSI C "prototypes" for these macros are:
+ * (GET_UINT{1,2}) from a pointer. There are two variants for each return type
+ * that depend on the number of bytes fetched. The ANSI C "prototypes" for
+ * these macros are:
*
- * EXTERN int TclGetInt1AtPtr _ANSI_ARGS_((unsigned char *p));
- * EXTERN int TclGetInt4AtPtr _ANSI_ARGS_((unsigned char *p));
- * EXTERN unsigned int TclGetUInt1AtPtr _ANSI_ARGS_((unsigned char *p));
- * EXTERN unsigned int TclGetUInt4AtPtr _ANSI_ARGS_((unsigned char *p));
+ * int TclGetInt1AtPtr(unsigned char *p);
+ * int TclGetInt4AtPtr(unsigned char *p);
+ * unsigned int TclGetUInt1AtPtr(unsigned char *p);
+ * unsigned int TclGetUInt4AtPtr(unsigned char *p);
*/
/*
- * The TclGetInt1AtPtr macro is tricky because we want to do sign
- * extension on the 1-byte value. Unfortunately the "char" type isn't
- * signed on all platforms so sign-extension doesn't always happen
- * automatically. Sometimes we can explicitly declare the pointer to be
- * signed, but other times we have to explicitly sign-extend the value
- * in software.
+ * The TclGetInt1AtPtr macro is tricky because we want to do sign extension on
+ * the 1-byte value. Unfortunately the "char" type isn't signed on all
+ * platforms so sign-extension doesn't always happen automatically. Sometimes
+ * we can explicitly declare the pointer to be signed, but other times we have
+ * to explicitly sign-extend the value in software.
*/
#ifndef __CHAR_UNSIGNED__
@@ -1069,29 +1201,29 @@ EXTERN int TclCompileVariableCmd _ANSI_ARGS_((
#else
# ifdef HAVE_SIGNED_CHAR
# define TclGetInt1AtPtr(p) ((int) *((signed char *) p))
-# else
+# else
# define TclGetInt1AtPtr(p) (((int) *((char *) p)) \
| ((*(p) & 0200) ? (-256) : 0))
-# endif
+# endif
#endif
#define TclGetInt4AtPtr(p) (((int) TclGetInt1AtPtr(p) << 24) | \
- (*((p)+1) << 16) | \
+ (*((p)+1) << 16) | \
(*((p)+2) << 8) | \
(*((p)+3)))
#define TclGetUInt1AtPtr(p) ((unsigned int) *(p))
#define TclGetUInt4AtPtr(p) ((unsigned int) (*(p) << 24) | \
- (*((p)+1) << 16) | \
- (*((p)+2) << 8) | \
- (*((p)+3)))
+ (*((p)+1) << 16) | \
+ (*((p)+2) << 8) | \
+ (*((p)+3)))
/*
- * Macros used to compute the minimum and maximum of two integers.
- * The ANSI C "prototypes" for these macros are:
+ * Macros used to compute the minimum and maximum of two integers. The ANSI C
+ * "prototypes" for these macros are:
*
- * EXTERN int TclMin _ANSI_ARGS_((int i, int j));
- * EXTERN int TclMax _ANSI_ARGS_((int i, int j));
+ * int TclMin(int i, int j);
+ * int TclMax(int i, int j);
*/
#define TclMin(i, j) ((((int) i) < ((int) j))? (i) : (j))
@@ -1137,21 +1269,27 @@ EXTERN int TclCompileVariableCmd _ANSI_ARGS_((
#define TCL_DTRACE_PROC_RETURN_ENABLED() unlikely(TCL_PROC_RETURN_ENABLED())
#define TCL_DTRACE_PROC_RESULT_ENABLED() unlikely(TCL_PROC_RESULT_ENABLED())
#define TCL_DTRACE_PROC_ARGS_ENABLED() unlikely(TCL_PROC_ARGS_ENABLED())
+#define TCL_DTRACE_PROC_INFO_ENABLED() unlikely(TCL_PROC_INFO_ENABLED())
#define TCL_DTRACE_PROC_ENTRY(a0, a1, a2) TCL_PROC_ENTRY(a0, a1, a2)
#define TCL_DTRACE_PROC_RETURN(a0, a1) TCL_PROC_RETURN(a0, a1)
#define TCL_DTRACE_PROC_RESULT(a0, a1, a2, a3) TCL_PROC_RESULT(a0, a1, a2, a3)
#define TCL_DTRACE_PROC_ARGS(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \
TCL_PROC_ARGS(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)
+#define TCL_DTRACE_PROC_INFO(a0, a1, a2, a3, a4, a5) \
+ TCL_PROC_INFO(a0, a1, a2, a3, a4, a5)
#define TCL_DTRACE_CMD_ENTRY_ENABLED() unlikely(TCL_CMD_ENTRY_ENABLED())
#define TCL_DTRACE_CMD_RETURN_ENABLED() unlikely(TCL_CMD_RETURN_ENABLED())
#define TCL_DTRACE_CMD_RESULT_ENABLED() unlikely(TCL_CMD_RESULT_ENABLED())
#define TCL_DTRACE_CMD_ARGS_ENABLED() unlikely(TCL_CMD_ARGS_ENABLED())
+#define TCL_DTRACE_CMD_INFO_ENABLED() unlikely(TCL_CMD_INFO_ENABLED())
#define TCL_DTRACE_CMD_ENTRY(a0, a1, a2) TCL_CMD_ENTRY(a0, a1, a2)
#define TCL_DTRACE_CMD_RETURN(a0, a1) TCL_CMD_RETURN(a0, a1)
#define TCL_DTRACE_CMD_RESULT(a0, a1, a2, a3) TCL_CMD_RESULT(a0, a1, a2, a3)
#define TCL_DTRACE_CMD_ARGS(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \
TCL_CMD_ARGS(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)
+#define TCL_DTRACE_CMD_INFO(a0, a1, a2, a3, a4, a5) \
+ TCL_CMD_INFO(a0, a1, a2, a3, a4, a5)
#define TCL_DTRACE_INST_START_ENABLED() unlikely(TCL_INST_START_ENABLED())
#define TCL_DTRACE_INST_DONE_ENABLED() unlikely(TCL_INST_DONE_ENABLED())
@@ -1164,25 +1302,31 @@ EXTERN int TclCompileVariableCmd _ANSI_ARGS_((
#define TCL_DTRACE_DEBUG_LOG()
+MODULE_SCOPE void TclDTraceInfo(Tcl_Obj *info, char **args, int *argsi);
+
#else /* USE_DTRACE */
#define TCL_DTRACE_PROC_ENTRY_ENABLED() 0
#define TCL_DTRACE_PROC_RETURN_ENABLED() 0
#define TCL_DTRACE_PROC_RESULT_ENABLED() 0
#define TCL_DTRACE_PROC_ARGS_ENABLED() 0
+#define TCL_DTRACE_PROC_INFO_ENABLED() 0
#define TCL_DTRACE_PROC_ENTRY(a0, a1, a2) {}
#define TCL_DTRACE_PROC_RETURN(a0, a1) {}
#define TCL_DTRACE_PROC_RESULT(a0, a1, a2, a3) {}
#define TCL_DTRACE_PROC_ARGS(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) {}
+#define TCL_DTRACE_PROC_INFO(a0, a1, a2, a3, a4, a5) {}
#define TCL_DTRACE_CMD_ENTRY_ENABLED() 0
#define TCL_DTRACE_CMD_RETURN_ENABLED() 0
#define TCL_DTRACE_CMD_RESULT_ENABLED() 0
#define TCL_DTRACE_CMD_ARGS_ENABLED() 0
+#define TCL_DTRACE_CMD_INFO_ENABLED() 0
#define TCL_DTRACE_CMD_ENTRY(a0, a1, a2) {}
#define TCL_DTRACE_CMD_RETURN(a0, a1) {}
#define TCL_DTRACE_CMD_RESULT(a0, a1, a2, a3) {}
#define TCL_DTRACE_CMD_ARGS(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) {}
+#define TCL_DTRACE_CMD_INFO(a0, a1, a2, a3, a4, a5) {}
#define TCL_DTRACE_INST_START_ENABLED() 0
#define TCL_DTRACE_INST_DONE_ENABLED() 0
@@ -1192,6 +1336,8 @@ EXTERN int TclCompileVariableCmd _ANSI_ARGS_((
#define TCL_DTRACE_TCL_PROBE_ENABLED() 0
#define TCL_DTRACE_TCL_PROBE(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) {}
+#define TclDTraceInfo(info, args, argsi) {*args = ""; *argsi = 0;}
+
#endif /* USE_DTRACE */
#else /* TCL_DTRACE_DEBUG */
@@ -1237,6 +1383,7 @@ MODULE_SCOPE void TclDTraceInfo(Tcl_Obj *info, char **args, int *argsi);
#define TCL_DTRACE_PROC_RETURN_ENABLED() 1
#define TCL_DTRACE_PROC_RESULT_ENABLED() 1
#define TCL_DTRACE_PROC_ARGS_ENABLED() 1
+#define TCL_DTRACE_PROC_INFO_ENABLED() 1
#define TCL_DTRACE_PROC_ENTRY(a0, a1, a2) \
tclDTraceDebugIndent++; \
TclDTraceDbgMsg("-> proc-entry", "%s %d %p", a0, a1, a2)
@@ -1248,11 +1395,15 @@ MODULE_SCOPE void TclDTraceInfo(Tcl_Obj *info, char **args, int *argsi);
#define TCL_DTRACE_PROC_ARGS(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \
TclDTraceDbgMsg(" | proc-args", "%s %s %s %s %s %s %s %s %s %s", a0, \
a1, a2, a3, a4, a5, a6, a7, a8, a9)
+#define TCL_DTRACE_PROC_INFO(a0, a1, a2, a3, a4, a5) \
+ TclDTraceDbgMsg(" | proc-info", "%s %s %s %s %d %d", a0, a1, \
+ a2, a3, a4, a5)
#define TCL_DTRACE_CMD_ENTRY_ENABLED() 1
#define TCL_DTRACE_CMD_RETURN_ENABLED() 1
#define TCL_DTRACE_CMD_RESULT_ENABLED() 1
#define TCL_DTRACE_CMD_ARGS_ENABLED() 1
+#define TCL_DTRACE_CMD_INFO_ENABLED() 1
#define TCL_DTRACE_CMD_ENTRY(a0, a1, a2) \
tclDTraceDebugIndent++; \
TclDTraceDbgMsg("-> cmd-entry", "%s %d %p", a0, a1, a2)
@@ -1264,6 +1415,9 @@ MODULE_SCOPE void TclDTraceInfo(Tcl_Obj *info, char **args, int *argsi);
#define TCL_DTRACE_CMD_ARGS(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \
TclDTraceDbgMsg(" | cmd-args", "%s %s %s %s %s %s %s %s %s %s", a0, \
a1, a2, a3, a4, a5, a6, a7, a8, a9)
+#define TCL_DTRACE_CMD_INFO(a0, a1, a2, a3, a4, a5) \
+ TclDTraceDbgMsg(" | cmd-info", "%s %s %s %s %d %d", a0, a1, \
+ a2, a3, a4, a5)
#define TCL_DTRACE_INST_START_ENABLED() TCL_DTRACE_DEBUG_INST_PROBES
#define TCL_DTRACE_INST_DONE_ENABLED() TCL_DTRACE_DEBUG_INST_PROBES
@@ -1280,7 +1434,12 @@ MODULE_SCOPE void TclDTraceInfo(Tcl_Obj *info, char **args, int *argsi);
#endif /* TCL_DTRACE_DEBUG */
-# undef TCL_STORAGE_CLASS
-# define TCL_STORAGE_CLASS DLLIMPORT
-
#endif /* _TCLCOMPILATION */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclConfig.c b/generic/tclConfig.c
new file mode 100644
index 0000000..251868e
--- /dev/null
+++ b/generic/tclConfig.c
@@ -0,0 +1,392 @@
+/*
+ * tclConfig.c --
+ *
+ * This file provides the facilities which allow Tcl and other packages
+ * to embed configuration information into their binary libraries.
+ *
+ * Copyright (c) 2002 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tclInt.h"
+
+/*
+ * Internal structure to hold embedded configuration information.
+ *
+ * Our structure is a two-level dictionary associated with the 'interp'. The
+ * first level is keyed with the package name and maps to the dictionary for
+ * that package. The package dictionary is keyed with metadata keys and maps
+ * to the metadata value for that key. This is package specific. The metadata
+ * values are in UTF-8, converted from the external representation given to us
+ * by the caller.
+ */
+
+#define ASSOC_KEY "tclPackageAboutDict"
+
+/*
+ * A ClientData struct for the QueryConfig command. Store the two bits
+ * of data we need; the package name for which we store a config dict,
+ * and the (Tcl_Interp *) in which it is stored.
+ */
+
+typedef struct QCCD {
+ Tcl_Obj *pkg;
+ Tcl_Interp *interp;
+} QCCD;
+
+/*
+ * Static functions in this file:
+ */
+
+static int QueryConfigObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ struct Tcl_Obj *CONST *objv);
+static void QueryConfigDelete(ClientData clientData);
+static Tcl_Obj * GetConfigDict(Tcl_Interp *interp);
+static void ConfigDictDeleteProc(ClientData clientData,
+ Tcl_Interp *interp);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_RegisterConfig --
+ *
+ * See TIP#59 for details on what this function does.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Creates namespace and cfg query command in it as per TIP #59.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_RegisterConfig(
+ Tcl_Interp *interp, /* Interpreter the configuration command is
+ * registered in. */
+ CONST char *pkgName, /* Name of the package registering the
+ * embedded configuration. ASCII, thus in
+ * UTF-8 too. */
+ Tcl_Config *configuration, /* Embedded configuration. */
+ CONST char *valEncoding) /* Name of the encoding used to store the
+ * configuration values, ASCII, thus UTF-8. */
+{
+ Tcl_Obj *pDB, *pkgDict;
+ Tcl_DString cmdName;
+ Tcl_Config *cfg;
+ Tcl_Encoding venc = Tcl_GetEncoding(NULL, valEncoding);
+ QCCD *cdPtr = (QCCD *)ckalloc(sizeof(QCCD));
+
+ cdPtr->interp = interp;
+ cdPtr->pkg = Tcl_NewStringObj(pkgName, -1);
+
+ /*
+ * Phase I: Adding the provided information to the internal database of
+ * package meta data. Only if we have an ok encoding.
+ *
+ * Phase II: Create a command for querying this database, specific to the
+ * package registerting its configuration. This is the approved interface
+ * in TIP 59. In the future a more general interface should be done, as
+ * followup to TIP 59. Simply because our database is now general across
+ * packages, and not a structure tied to one package.
+ *
+ * Note, the created command will have a reference through its clientdata.
+ */
+
+ Tcl_IncrRefCount(cdPtr->pkg);
+
+ /*
+ * For venc == NULL aka bogus encoding we skip the step setting up the
+ * dictionaries visible at Tcl level. I.e. they are not filled
+ */
+
+ if (venc != NULL) {
+ /*
+ * Retrieve package specific configuration...
+ */
+
+ pDB = GetConfigDict(interp);
+
+ if (Tcl_DictObjGet(interp, pDB, cdPtr->pkg, &pkgDict) != TCL_OK
+ || (pkgDict == NULL)) {
+ pkgDict = Tcl_NewDictObj();
+ } else if (Tcl_IsShared(pkgDict)) {
+ pkgDict = Tcl_DuplicateObj(pkgDict);
+ }
+
+ /*
+ * Extend the package configuration...
+ */
+
+ for (cfg=configuration ; cfg->key!=NULL && cfg->key[0]!='\0' ; cfg++) {
+ Tcl_DString conv;
+ CONST char *convValue =
+ Tcl_ExternalToUtfDString(venc, cfg->value, -1, &conv);
+
+ /*
+ * We know that the keys are in ASCII/UTF-8, so for them is no
+ * conversion required.
+ */
+
+ Tcl_DictObjPut(interp, pkgDict, Tcl_NewStringObj(cfg->key, -1),
+ Tcl_NewStringObj(convValue, -1));
+ Tcl_DStringFree(&conv);
+ }
+
+ /*
+ * We're now done with the encoding, so drop it.
+ */
+
+ Tcl_FreeEncoding(venc);
+
+ /*
+ * Write the changes back into the overall database.
+ */
+
+ Tcl_DictObjPut(interp, pDB, cdPtr->pkg, pkgDict);
+ }
+
+ /*
+ * Now create the interface command for retrieval of the package
+ * information.
+ */
+
+ Tcl_DStringInit(&cmdName);
+ Tcl_DStringAppend(&cmdName, "::", -1);
+ Tcl_DStringAppend(&cmdName, pkgName, -1);
+
+ /*
+ * The incomplete command name is the name of the namespace to place it
+ * in.
+ */
+
+ if (Tcl_FindNamespace(interp, Tcl_DStringValue(&cmdName), NULL,
+ TCL_GLOBAL_ONLY) == NULL) {
+ if (Tcl_CreateNamespace(interp, Tcl_DStringValue(&cmdName),
+ NULL, NULL) == NULL) {
+ Tcl_Panic("%s.\n%s: %s",
+ Tcl_GetStringResult(interp), "Tcl_RegisterConfig",
+ "Unable to create namespace for package configuration.");
+ }
+ }
+
+ Tcl_DStringAppend(&cmdName, "::pkgconfig", -1);
+
+ if (Tcl_CreateObjCommand(interp, Tcl_DStringValue(&cmdName),
+ QueryConfigObjCmd, (ClientData) cdPtr, QueryConfigDelete) == NULL) {
+ Tcl_Panic("%s: %s", "Tcl_RegisterConfig",
+ "Unable to create query command for package configuration");
+ }
+
+ Tcl_DStringFree(&cmdName);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * QueryConfigObjCmd --
+ *
+ * Implementation of "::<package>::pkgconfig", the command to query
+ * configuration information embedded into a binary library.
+ *
+ * Results:
+ * A standard tcl result.
+ *
+ * Side effects:
+ * See the manual for what this command does.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+QueryConfigObjCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ struct Tcl_Obj *CONST *objv)
+{
+ QCCD *cdPtr = (QCCD *) clientData;
+ Tcl_Obj *pkgName = cdPtr->pkg;
+ Tcl_Obj *pDB, *pkgDict, *val, *listPtr;
+ int n, index;
+ static CONST char *subcmdStrings[] = {
+ "get", "list", NULL
+ };
+ enum subcmds {
+ CFG_GET, CFG_LIST
+ };
+
+ if ((objc < 2) || (objc > 3)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?argument?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[1], subcmdStrings, "subcommand", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ pDB = GetConfigDict(interp);
+ if (Tcl_DictObjGet(interp, pDB, pkgName, &pkgDict) != TCL_OK
+ || pkgDict == NULL) {
+ /*
+ * Maybe a Tcl_Panic is better, because the package data has to be
+ * present.
+ */
+
+ Tcl_SetResult(interp, "package not known", TCL_STATIC);
+ return TCL_ERROR;
+ }
+
+ switch ((enum subcmds) index) {
+ case CFG_GET:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "key");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_DictObjGet(interp, pkgDict, objv [2], &val) != TCL_OK
+ || val == NULL) {
+ Tcl_SetResult(interp, "key not known", TCL_STATIC);
+ return TCL_ERROR;
+ }
+
+ Tcl_SetObjResult(interp, val);
+ return TCL_OK;
+
+ case CFG_LIST:
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return TCL_ERROR;
+ }
+
+ Tcl_DictObjSize(interp, pkgDict, &n);
+ listPtr = Tcl_NewListObj(n, NULL);
+
+ if (!listPtr) {
+ Tcl_SetResult(interp, "insufficient memory to create list",
+ TCL_STATIC);
+ return TCL_ERROR;
+ }
+
+ if (n) {
+ Tcl_DictSearch s;
+ Tcl_Obj *key;
+ int done;
+
+ for (Tcl_DictObjFirst(interp, pkgDict, &s, &key, NULL, &done);
+ !done; Tcl_DictObjNext(&s, &key, NULL, &done)) {
+ Tcl_ListObjAppendElement(NULL, listPtr, key);
+ }
+ }
+
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+
+ default:
+ Tcl_Panic("QueryConfigObjCmd: Unknown subcommand to 'pkgconfig'. This can't happen");
+ break;
+ }
+ return TCL_ERROR;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * QueryConfigDelete --
+ *
+ * Command delete function. Cleans up after the configuration query
+ * command when it is deleted by the user or during finalization.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Deallocates all non-transient memory allocated by Tcl_RegisterConfig.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static void
+QueryConfigDelete(
+ ClientData clientData)
+{
+ QCCD *cdPtr = (QCCD *) clientData;
+ Tcl_Obj *pkgName = cdPtr->pkg;
+ Tcl_Obj *pDB = GetConfigDict(cdPtr->interp);
+ Tcl_DictObjRemove(NULL, pDB, pkgName);
+ Tcl_DecrRefCount(pkgName);
+ ckfree((char *)cdPtr);
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * GetConfigDict --
+ *
+ * Retrieve the package metadata database from the interpreter.
+ * Initializes it, if not present yet.
+ *
+ * Results:
+ * A Tcl_Obj reference
+ *
+ * Side effects:
+ * May allocate a Tcl_Obj.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+GetConfigDict(
+ Tcl_Interp *interp)
+{
+ Tcl_Obj *pDB = Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
+
+ if (pDB == NULL) {
+ pDB = Tcl_NewDictObj();
+ Tcl_IncrRefCount(pDB);
+ Tcl_SetAssocData(interp, ASSOC_KEY, ConfigDictDeleteProc, pDB);
+ }
+
+ return pDB;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigDictDeleteProc --
+ *
+ * This function is associated with the "Package About dict" assoc data
+ * for an interpreter; it is invoked when the interpreter is deleted in
+ * order to free the information assoicated with any pending error
+ * reports.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The package metadata database is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ConfigDictDeleteProc(
+ ClientData clientData, /* Pointer to Tcl_Obj. */
+ Tcl_Interp *interp) /* Interpreter being deleted. */
+{
+ Tcl_Obj *pDB = (Tcl_Obj *) clientData;
+
+ Tcl_DecrRefCount(pDB);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclDTrace.d b/generic/tclDTrace.d
index 7792bda..bdbcb6e 100644
--- a/generic/tclDTrace.d
+++ b/generic/tclDTrace.d
@@ -51,6 +51,19 @@ provider tcl {
probe proc__args(char* name, char* arg1, char* arg2, char* arg3,
char* arg4, char* arg5, char* arg6, char* arg7, char* arg8,
char* arg9);
+ /*
+ * tcl*:::proc-info probe
+ * triggered before proc-entry probe, gives access to TIP 280
+ * information for the proc invocation (i.e. [info frame 0])
+ * arg0: TIP 280 cmd (string)
+ * arg1: TIP 280 type (string)
+ * arg2: TIP 280 proc (string)
+ * arg3: TIP 280 file (string)
+ * arg4: TIP 280 line (int)
+ * arg5: TIP 280 level (int)
+ */
+ probe proc__info(char* cmd, char* type, char* proc, char* file, int line,
+ int level);
/***************************** cmd probes ******************************/
/*
@@ -87,6 +100,19 @@ provider tcl {
probe cmd__args(char* name, char* arg1, char* arg2, char* arg3,
char* arg4, char* arg5, char* arg6, char* arg7, char* arg8,
char* arg9);
+ /*
+ * tcl*:::cmd-info probe
+ * triggered before cmd-entry probe, gives access to TIP 280
+ * information for the command invocation (i.e. [info frame 0])
+ * arg0: TIP 280 cmd (string)
+ * arg1: TIP 280 type (string)
+ * arg2: TIP 280 proc (string)
+ * arg3: TIP 280 file (string)
+ * arg4: TIP 280 line (int)
+ * arg5: TIP 280 level (int)
+ */
+ probe cmd__info(char* cmd, char* type, char* proc, char* file, int line,
+ int level);
/***************************** inst probes *****************************/
/*
@@ -157,6 +183,10 @@ struct Tcl_Obj {
void *ptr1;
void *ptr2;
} twoPtrValue;
+ struct {
+ void *ptr;
+ unsigned long value;
+ } ptrAndLongRep;
} internalRep;
};
diff --git a/generic/tclDate.c b/generic/tclDate.c
index 7354a6f..b77c7fd 100644
--- a/generic/tclDate.c
+++ b/generic/tclDate.c
@@ -1,663 +1,2567 @@
-/*
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.3"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 1
+
+/* Using locations. */
+#define YYLSP_NEEDED 1
+
+/* Substitute the variable and function names. */
+#define yyparse TclDateparse
+#define yylex TclDatelex
+#define yyerror TclDateerror
+#define yylval TclDatelval
+#define yychar TclDatechar
+#define yydebug TclDatedebug
+#define yynerrs TclDatenerrs
+#define yylloc TclDatelloc
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ tAGO = 258,
+ tDAY = 259,
+ tDAYZONE = 260,
+ tID = 261,
+ tMERIDIAN = 262,
+ tMONTH = 263,
+ tMONTH_UNIT = 264,
+ tSTARDATE = 265,
+ tSEC_UNIT = 266,
+ tSNUMBER = 267,
+ tUNUMBER = 268,
+ tZONE = 269,
+ tEPOCH = 270,
+ tDST = 271,
+ tISOBASE = 272,
+ tDAY_UNIT = 273,
+ tNEXT = 274
+ };
+#endif
+/* Tokens. */
+#define tAGO 258
+#define tDAY 259
+#define tDAYZONE 260
+#define tID 261
+#define tMERIDIAN 262
+#define tMONTH 263
+#define tMONTH_UNIT 264
+#define tSTARDATE 265
+#define tSEC_UNIT 266
+#define tSNUMBER 267
+#define tUNUMBER 268
+#define tZONE 269
+#define tEPOCH 270
+#define tDST 271
+#define tISOBASE 272
+#define tDAY_UNIT 273
+#define tNEXT 274
+
+
+
+
+/* Copy the first part of user declarations. */
+
+
+/*
* tclDate.c --
*
- * This file is generated from a yacc grammar defined in
- * the file tclGetDate.y. It should not be edited directly.
+ * This file is generated from a yacc grammar defined in the file
+ * tclGetDate.y. It should not be edited directly.
*
* Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
-
#include "tclInt.h"
-#include "tclPort.h"
-#if defined(MAC_TCL) && !defined(TCL_MAC_USE_MSL_EPOCH)
-# define EPOCH 1904
-# define START_OF_TIME 1904
-# define END_OF_TIME 2039
-#else
-# define EPOCH 1970
-# define START_OF_TIME 1902
-# define END_OF_TIME 2037
-#endif
+/*
+ * Bison generates several labels that happen to be unused. MS Visual C++
+ * doesn't like that, and complains. Tell it to shut up.
+ */
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4102 )
+#endif /* _MSC_VER */
+
+/*
+ * yyparse will accept a 'struct DateInfo' as its parameter; that's where the
+ * parsed fields will be returned.
+ */
+
+typedef struct DateInfo {
+
+ Tcl_Obj* messages; /* Error messages */
+ const char* separatrix; /* String separating messages */
+
+ time_t dateYear;
+ time_t dateMonth;
+ time_t dateDay;
+ int dateHaveDate;
+
+ time_t dateHour;
+ time_t dateMinutes;
+ time_t dateSeconds;
+ int dateMeridian;
+ int dateHaveTime;
+
+ time_t dateTimezone;
+ int dateDSTmode;
+ int dateHaveZone;
+
+ time_t dateRelMonth;
+ time_t dateRelDay;
+ time_t dateRelSeconds;
+ int dateHaveRel;
+
+ time_t dateMonthOrdinal;
+ int dateHaveOrdinalMonth;
+
+ time_t dateDayOrdinal;
+ time_t dateDayNumber;
+ int dateHaveDay;
+
+ const char *dateStart;
+ const char *dateInput;
+ time_t *dateRelPointer;
+
+ int dateDigitCount;
+} DateInfo;
+
+#define YYMALLOC ckalloc
+#define YYFREE(x) (ckfree((void*) (x)))
+
+#define yyDSTmode (info->dateDSTmode)
+#define yyDayOrdinal (info->dateDayOrdinal)
+#define yyDayNumber (info->dateDayNumber)
+#define yyMonthOrdinal (info->dateMonthOrdinal)
+#define yyHaveDate (info->dateHaveDate)
+#define yyHaveDay (info->dateHaveDay)
+#define yyHaveOrdinalMonth (info->dateHaveOrdinalMonth)
+#define yyHaveRel (info->dateHaveRel)
+#define yyHaveTime (info->dateHaveTime)
+#define yyHaveZone (info->dateHaveZone)
+#define yyTimezone (info->dateTimezone)
+#define yyDay (info->dateDay)
+#define yyMonth (info->dateMonth)
+#define yyYear (info->dateYear)
+#define yyHour (info->dateHour)
+#define yyMinutes (info->dateMinutes)
+#define yySeconds (info->dateSeconds)
+#define yyMeridian (info->dateMeridian)
+#define yyRelMonth (info->dateRelMonth)
+#define yyRelDay (info->dateRelDay)
+#define yyRelSeconds (info->dateRelSeconds)
+#define yyRelPointer (info->dateRelPointer)
+#define yyInput (info->dateInput)
+#define yyDigitCount (info->dateDigitCount)
+
+#define EPOCH 1970
+#define START_OF_TIME 1902
+#define END_OF_TIME 2037
/*
* The offset of tm_year of struct tm returned by localtime, gmtime, etc.
- * I don't know how universal this is; K&R II, the NetBSD manpages, and
- * ../compat/strftime.c all agree that tm_year is the year-1900. However,
- * some systems may have a different value. This #define should be the
- * same as in ../compat/strftime.c.
+ * Posix requires 1900.
*/
-#define TM_YEAR_BASE 1900
-#define HOUR(x) ((int) (60 * x))
-#define SECSPERDAY (24L * 60L * 60L)
-#define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0))
+#define TM_YEAR_BASE 1900
+
+#define HOUR(x) ((int) (60 * x))
+#define SECSPERDAY (24L * 60L * 60L)
+#define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0))
/*
- * An entry in the lexical lookup table.
+ * An entry in the lexical lookup table.
*/
+
typedef struct _TABLE {
- char *name;
- int type;
- time_t value;
+ const char *name;
+ int type;
+ time_t value;
} TABLE;
-
/*
- * Daylight-savings mode: on, off, or not yet known.
+ * Daylight-savings mode: on, off, or not yet known.
*/
+
typedef enum _DSTMODE {
DSTon, DSToff, DSTmaybe
} DSTMODE;
/*
- * Meridian: am, pm, or 24-hour style.
+ * Meridian: am, pm, or 24-hour style.
*/
+
typedef enum _MERIDIAN {
MERam, MERpm, MER24
} MERIDIAN;
-/*
- * Global variables. We could get rid of most of these by using a good
- * union as the yacc stack. (This routine was originally written before
- * yacc had the %union construct.) Maybe someday; right now we only use
- * the %union very rarely.
- */
-static char *TclDateInput;
-static DSTMODE TclDateDSTmode;
-static time_t TclDateDayOrdinal;
-static time_t TclDateDayNumber;
-static time_t TclDateMonthOrdinal;
-static int TclDateHaveDate;
-static int TclDateHaveDay;
-static int TclDateHaveOrdinalMonth;
-static int TclDateHaveRel;
-static int TclDateHaveTime;
-static int TclDateHaveZone;
-static time_t TclDateTimezone;
-static time_t TclDateDay;
-static time_t TclDateHour;
-static time_t TclDateMinutes;
-static time_t TclDateMonth;
-static time_t TclDateSeconds;
-static time_t TclDateYear;
-static MERIDIAN TclDateMeridian;
-static time_t TclDateRelMonth;
-static time_t TclDateRelDay;
-static time_t TclDateRelSeconds;
-static time_t *TclDateRelPointer;
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+
+{
+ time_t Number;
+ enum _MERIDIAN Meridian;
+}
+/* Line 187 of yacc.c. */
+
+ YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+/* Copy the second part of user declarations. */
+
+
/*
* Prototypes of internal functions.
*/
-static void TclDateerror _ANSI_ARGS_((char *s));
-static time_t ToSeconds _ANSI_ARGS_((time_t Hours, time_t Minutes,
- time_t Seconds, MERIDIAN Meridian));
-static int Convert _ANSI_ARGS_((time_t Month, time_t Day, time_t Year,
- time_t Hours, time_t Minutes, time_t Seconds,
- MERIDIAN Meridia, DSTMODE DSTmode, time_t *TimePtr));
-static time_t DSTcorrect _ANSI_ARGS_((time_t Start, time_t Future));
-static time_t NamedDay _ANSI_ARGS_((time_t Start, time_t DayOrdinal,
- time_t DayNumber));
-static time_t NamedMonth _ANSI_ARGS_((time_t Start, time_t MonthOrdinal,
- time_t MonthNumber));
-static int RelativeMonth _ANSI_ARGS_((time_t Start, time_t RelMonth,
- time_t *TimePtr));
-static int RelativeDay _ANSI_ARGS_((time_t Start, time_t RelDay,
- time_t *TimePtr));
-static int LookupWord _ANSI_ARGS_((char *buff));
-static int TclDatelex _ANSI_ARGS_((void));
-int
-TclDateparse _ANSI_ARGS_((void));
-typedef union
-#ifdef __cplusplus
- YYSTYPE
+static int LookupWord(YYSTYPE* yylvalPtr, char *buff);
+ static void TclDateerror(YYLTYPE* location,
+ DateInfo* info, const char *s);
+ static int TclDatelex(YYSTYPE* yylvalPtr, YYLTYPE* location,
+ DateInfo* info);
+static time_t ToSeconds(time_t Hours, time_t Minutes,
+ time_t Seconds, MERIDIAN Meridian);
+MODULE_SCOPE int yyparse(DateInfo*);
+
+
+
+/* Line 216 of yacc.c. */
+
+
+#ifdef short
+# undef short
#endif
- {
- time_t Number;
- enum _MERIDIAN Meridian;
-} YYSTYPE;
-# define tAGO 257
-# define tDAY 258
-# define tDAYZONE 259
-# define tID 260
-# define tMERIDIAN 261
-# define tMINUTE_UNIT 262
-# define tMONTH 263
-# define tMONTH_UNIT 264
-# define tSTARDATE 265
-# define tSEC_UNIT 266
-# define tSNUMBER 267
-# define tUNUMBER 268
-# define tZONE 269
-# define tEPOCH 270
-# define tDST 271
-# define tISOBASE 272
-# define tDAY_UNIT 273
-# define tNEXT 274
-
-
-
-
-#if defined(__cplusplus) || defined(__STDC__)
-
-#if defined(__cplusplus) && defined(__EXTERN_C__)
-extern "C" {
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
#endif
-#ifndef TclDateerror
-#if defined(__cplusplus)
- void TclDateerror(CONST char *);
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
#endif
-#ifndef TclDatelex
- int TclDatelex(void);
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
#endif
- int TclDateparse(void);
-#if defined(__cplusplus) && defined(__EXTERN_C__)
-}
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
#endif
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
#endif
-#define TclDateclearin TclDatechar = -1
-#define TclDateerrok TclDateerrflag = 0
-extern int TclDatechar;
-extern int TclDateerrflag;
-YYSTYPE TclDatelval;
-YYSTYPE TclDateval;
-typedef int TclDatetabelem;
-#ifndef YYMAXDEPTH
-#define YYMAXDEPTH 150
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int i)
+#else
+static int
+YYID (i)
+ int i;
#endif
-#if YYMAXDEPTH > 0
-int TclDate_TclDates[YYMAXDEPTH], *TclDates = TclDate_TclDates;
-YYSTYPE TclDate_TclDatev[YYMAXDEPTH], *TclDatev = TclDate_TclDatev;
-#else /* user does initial allocation */
-int *TclDates;
-YYSTYPE *TclDatev;
+{
+ return i;
+}
#endif
-static int TclDatemaxdepth = YYMAXDEPTH;
-# define YYERRCODE 256
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
+ && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss;
+ YYSTYPE yyvs;
+ YYLTYPE yyls;
+};
-/*
- * Month and day table.
- */
-static TABLE MonthDayTable[] = {
- { "january", tMONTH, 1 },
- { "february", tMONTH, 2 },
- { "march", tMONTH, 3 },
- { "april", tMONTH, 4 },
- { "may", tMONTH, 5 },
- { "june", tMONTH, 6 },
- { "july", tMONTH, 7 },
- { "august", tMONTH, 8 },
- { "september", tMONTH, 9 },
- { "sept", tMONTH, 9 },
- { "october", tMONTH, 10 },
- { "november", tMONTH, 11 },
- { "december", tMONTH, 12 },
- { "sunday", tDAY, 0 },
- { "monday", tDAY, 1 },
- { "tuesday", tDAY, 2 },
- { "tues", tDAY, 2 },
- { "wednesday", tDAY, 3 },
- { "wednes", tDAY, 3 },
- { "thursday", tDAY, 4 },
- { "thur", tDAY, 4 },
- { "thurs", tDAY, 4 },
- { "friday", tDAY, 5 },
- { "saturday", tDAY, 6 },
- { NULL }
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
+ + 2 * YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack, Stack, yysize); \
+ Stack = &yyptr->Stack; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 2
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 79
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 26
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 16
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 56
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 83
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 274
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 25, 22, 21, 24, 23, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 20, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19
};
-/*
- * Time units table.
- */
-static TABLE UnitsTable[] = {
- { "year", tMONTH_UNIT, 12 },
- { "month", tMONTH_UNIT, 1 },
- { "fortnight", tDAY_UNIT, 14 },
- { "week", tDAY_UNIT, 7 },
- { "day", tDAY_UNIT, 1 },
- { "hour", tSEC_UNIT, 60 * 60 },
- { "minute", tSEC_UNIT, 60 },
- { "min", tSEC_UNIT, 60 },
- { "second", tSEC_UNIT, 1 },
- { "sec", tSEC_UNIT, 1 },
- { NULL }
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint8 yyprhs[] =
+{
+ 0, 0, 3, 4, 7, 9, 11, 13, 15, 17,
+ 19, 21, 23, 25, 28, 33, 39, 46, 54, 57,
+ 59, 61, 63, 66, 69, 73, 76, 80, 86, 88,
+ 94, 100, 103, 108, 111, 113, 117, 120, 124, 128,
+ 136, 139, 144, 147, 149, 153, 156, 159, 163, 165,
+ 167, 169, 171, 173, 175, 177, 178
};
-/*
- * Assorted relative-time words.
- */
-static TABLE OtherTable[] = {
- { "tomorrow", tDAY_UNIT, 1 },
- { "yesterday", tDAY_UNIT, -1 },
- { "today", tDAY_UNIT, 0 },
- { "now", tSEC_UNIT, 0 },
- { "last", tUNUMBER, -1 },
- { "this", tSEC_UNIT, 0 },
- { "next", tNEXT, 1 },
-#if 0
- { "first", tUNUMBER, 1 },
- { "second", tUNUMBER, 2 },
- { "third", tUNUMBER, 3 },
- { "fourth", tUNUMBER, 4 },
- { "fifth", tUNUMBER, 5 },
- { "sixth", tUNUMBER, 6 },
- { "seventh", tUNUMBER, 7 },
- { "eighth", tUNUMBER, 8 },
- { "ninth", tUNUMBER, 9 },
- { "tenth", tUNUMBER, 10 },
- { "eleventh", tUNUMBER, 11 },
- { "twelfth", tUNUMBER, 12 },
-#endif
- { "ago", tAGO, 1 },
- { "epoch", tEPOCH, 0 },
- { "stardate", tSTARDATE, 0},
- { NULL }
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int8 yyrhs[] =
+{
+ 27, 0, -1, -1, 27, 28, -1, 29, -1, 30,
+ -1, 32, -1, 33, -1, 31, -1, 36, -1, 34,
+ -1, 35, -1, 40, -1, 13, 7, -1, 13, 20,
+ 13, 41, -1, 13, 20, 13, 21, 13, -1, 13,
+ 20, 13, 20, 13, 41, -1, 13, 20, 13, 20,
+ 13, 21, 13, -1, 14, 16, -1, 14, -1, 5,
+ -1, 4, -1, 4, 22, -1, 13, 4, -1, 38,
+ 13, 4, -1, 19, 4, -1, 13, 23, 13, -1,
+ 13, 23, 13, 23, 13, -1, 17, -1, 13, 21,
+ 8, 21, 13, -1, 13, 21, 13, 21, 13, -1,
+ 8, 13, -1, 8, 13, 22, 13, -1, 13, 8,
+ -1, 15, -1, 13, 8, 13, -1, 19, 8, -1,
+ 19, 13, 8, -1, 17, 14, 17, -1, 17, 14,
+ 13, 20, 13, 20, 13, -1, 17, 17, -1, 10,
+ 13, 24, 13, -1, 37, 3, -1, 37, -1, 38,
+ 13, 39, -1, 13, 39, -1, 19, 39, -1, 19,
+ 13, 39, -1, 39, -1, 21, -1, 25, -1, 11,
+ -1, 18, -1, 9, -1, 13, -1, -1, 7, -1
};
-/*
- * The timezone table. (Note: This table was modified to not use any floating
- * point constants to work around an SGI compiler bug).
- */
-static TABLE TimezoneTable[] = {
- { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
- { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
- { "utc", tZONE, HOUR( 0) },
- { "uct", tZONE, HOUR( 0) }, /* Universal Coordinated Time */
- { "wet", tZONE, HOUR( 0) }, /* Western European */
- { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
- { "wat", tZONE, HOUR( 1) }, /* West Africa */
- { "at", tZONE, HOUR( 2) }, /* Azores */
-#if 0
- /* For completeness. BST is also British Summer, and GST is
- * also Guam Standard. */
- { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
- { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 225, 225, 226, 229, 232, 235, 238, 241, 244,
+ 247, 251, 256, 259, 265, 271, 279, 285, 296, 300,
+ 304, 310, 314, 318, 322, 326, 332, 336, 341, 346,
+ 351, 356, 360, 365, 369, 374, 381, 385, 391, 400,
+ 409, 419, 433, 438, 441, 444, 447, 450, 453, 458,
+ 461, 466, 470, 474, 480, 498, 501
+};
#endif
- { "nft", tZONE, HOUR( 7/2) }, /* Newfoundland */
- { "nst", tZONE, HOUR( 7/2) }, /* Newfoundland Standard */
- { "ndt", tDAYZONE, HOUR( 7/2) }, /* Newfoundland Daylight */
- { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
- { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
- { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
- { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
- { "cst", tZONE, HOUR( 6) }, /* Central Standard */
- { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
- { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
- { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
- { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
- { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
- { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
- { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
- { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
- { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
- { "cat", tZONE, HOUR(10) }, /* Central Alaska */
- { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
- { "nt", tZONE, HOUR(11) }, /* Nome */
- { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
- { "cet", tZONE, -HOUR( 1) }, /* Central European */
- { "cest", tDAYZONE, -HOUR( 1) }, /* Central European Summer */
- { "met", tZONE, -HOUR( 1) }, /* Middle European */
- { "mewt", tZONE, -HOUR( 1) }, /* Middle European Winter */
- { "mest", tDAYZONE, -HOUR( 1) }, /* Middle European Summer */
- { "swt", tZONE, -HOUR( 1) }, /* Swedish Winter */
- { "sst", tDAYZONE, -HOUR( 1) }, /* Swedish Summer */
- { "fwt", tZONE, -HOUR( 1) }, /* French Winter */
- { "fst", tDAYZONE, -HOUR( 1) }, /* French Summer */
- { "eet", tZONE, -HOUR( 2) }, /* Eastern Europe, USSR Zone 1 */
- { "bt", tZONE, -HOUR( 3) }, /* Baghdad, USSR Zone 2 */
- { "it", tZONE, -HOUR( 7/2) }, /* Iran */
- { "zp4", tZONE, -HOUR( 4) }, /* USSR Zone 3 */
- { "zp5", tZONE, -HOUR( 5) }, /* USSR Zone 4 */
- { "ist", tZONE, -HOUR(11/2) }, /* Indian Standard */
- { "zp6", tZONE, -HOUR( 6) }, /* USSR Zone 5 */
-#if 0
- /* For completeness. NST is also Newfoundland Stanard, nad SST is
- * also Swedish Summer. */
- { "nst", tZONE, -HOUR(13/2) }, /* North Sumatra */
- { "sst", tZONE, -HOUR( 7) }, /* South Sumatra, USSR Zone 6 */
-#endif /* 0 */
- { "wast", tZONE, -HOUR( 7) }, /* West Australian Standard */
- { "wadt", tDAYZONE, -HOUR( 7) }, /* West Australian Daylight */
- { "jt", tZONE, -HOUR(15/2) }, /* Java (3pm in Cronusland!) */
- { "cct", tZONE, -HOUR( 8) }, /* China Coast, USSR Zone 7 */
- { "jst", tZONE, -HOUR( 9) }, /* Japan Standard, USSR Zone 8 */
- { "jdt", tDAYZONE, -HOUR( 9) }, /* Japan Daylight */
- { "kst", tZONE, -HOUR( 9) }, /* Korea Standard */
- { "kdt", tDAYZONE, -HOUR( 9) }, /* Korea Daylight */
- { "cast", tZONE, -HOUR(19/2) }, /* Central Australian Standard */
- { "cadt", tDAYZONE, -HOUR(19/2) }, /* Central Australian Daylight */
- { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
- { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
- { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
- { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
- { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
- { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
- { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
- /* ADDED BY Marco Nijdam */
- { "dst", tDST, HOUR( 0) }, /* DST on (hour is ignored) */
- /* End ADDED */
- { NULL }
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "tAGO", "tDAY", "tDAYZONE", "tID",
+ "tMERIDIAN", "tMONTH", "tMONTH_UNIT", "tSTARDATE", "tSEC_UNIT",
+ "tSNUMBER", "tUNUMBER", "tZONE", "tEPOCH", "tDST", "tISOBASE",
+ "tDAY_UNIT", "tNEXT", "':'", "'-'", "','", "'/'", "'.'", "'+'",
+ "$accept", "spec", "item", "time", "zone", "day", "date", "ordMonth",
+ "iso", "trek", "relspec", "relunits", "sign", "unit", "number",
+ "o_merid", 0
};
+#endif
-/*
- * Military timezone table.
- */
-static TABLE MilitaryTable[] = {
- { "a", tZONE, HOUR( 1) },
- { "b", tZONE, HOUR( 2) },
- { "c", tZONE, HOUR( 3) },
- { "d", tZONE, HOUR( 4) },
- { "e", tZONE, HOUR( 5) },
- { "f", tZONE, HOUR( 6) },
- { "g", tZONE, HOUR( 7) },
- { "h", tZONE, HOUR( 8) },
- { "i", tZONE, HOUR( 9) },
- { "k", tZONE, HOUR( 10) },
- { "l", tZONE, HOUR( 11) },
- { "m", tZONE, HOUR( 12) },
- { "n", tZONE, HOUR(- 1) },
- { "o", tZONE, HOUR(- 2) },
- { "p", tZONE, HOUR(- 3) },
- { "q", tZONE, HOUR(- 4) },
- { "r", tZONE, HOUR(- 5) },
- { "s", tZONE, HOUR(- 6) },
- { "t", tZONE, HOUR(- 7) },
- { "u", tZONE, HOUR(- 8) },
- { "v", tZONE, HOUR(- 9) },
- { "w", tZONE, HOUR(-10) },
- { "x", tZONE, HOUR(-11) },
- { "y", tZONE, HOUR(-12) },
- { "z", tZONE, HOUR( 0) },
- { NULL }
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 58, 45, 44, 47, 46, 43
};
+# endif
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 26, 27, 27, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 29, 29, 29, 29, 29, 30, 30,
+ 30, 31, 31, 31, 31, 31, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 33, 33, 34, 34,
+ 34, 35, 36, 36, 37, 37, 37, 37, 37, 38,
+ 38, 39, 39, 39, 40, 41, 41
+};
-/*
- * Dump error messages in the bit bucket.
- */
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 0, 2, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 2, 4, 5, 6, 7, 2, 1,
+ 1, 1, 2, 2, 3, 2, 3, 5, 1, 5,
+ 5, 2, 4, 2, 1, 3, 2, 3, 3, 7,
+ 2, 4, 2, 1, 3, 2, 2, 3, 1, 1,
+ 1, 1, 1, 1, 1, 0, 1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 2, 0, 1, 21, 20, 0, 53, 0, 51, 54,
+ 19, 34, 28, 52, 0, 49, 50, 3, 4, 5,
+ 8, 6, 7, 10, 11, 9, 43, 0, 48, 12,
+ 22, 31, 0, 23, 13, 33, 0, 0, 0, 45,
+ 18, 0, 40, 25, 36, 0, 46, 42, 0, 0,
+ 0, 35, 55, 0, 0, 26, 0, 38, 37, 47,
+ 24, 44, 32, 41, 56, 0, 0, 14, 0, 0,
+ 0, 0, 55, 15, 29, 30, 27, 0, 0, 16,
+ 0, 17, 39
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int8 yydefgoto[] =
+{
+ -1, 1, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 67
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -22
+static const yytype_int8 yypact[] =
+{
+ -22, 2, -22, -21, -22, -4, -22, 1, -22, 22,
+ 18, -22, 8, -22, 40, -22, -22, -22, -22, -22,
+ -22, -22, -22, -22, -22, -22, 32, 28, -22, -22,
+ -22, 24, 26, -22, -22, 42, 47, -5, 49, -22,
+ -22, 15, -22, -22, -22, 48, -22, -22, 43, 50,
+ 51, -22, 17, 44, 46, 45, 52, -22, -22, -22,
+ -22, -22, -22, -22, -22, 56, 57, -22, 58, 60,
+ 61, 62, -3, -22, -22, -22, -22, 59, 63, -22,
+ 64, -22, -22
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int8 yypgoto[] =
+{
+ -22, -22, -22, -22, -22, -22, -22, -22, -22, -22,
+ -22, -22, -22, -9, -22, 6
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -1
+static const yytype_uint8 yytable[] =
+{
+ 39, 30, 2, 53, 64, 46, 3, 4, 54, 31,
+ 5, 6, 7, 8, 32, 9, 10, 11, 78, 12,
+ 13, 14, 41, 15, 64, 42, 33, 16, 56, 34,
+ 35, 6, 57, 8, 40, 47, 59, 65, 66, 61,
+ 13, 48, 36, 37, 43, 38, 49, 60, 44, 6,
+ 50, 8, 6, 45, 8, 51, 58, 6, 13, 8,
+ 52, 13, 55, 62, 63, 68, 13, 69, 70, 72,
+ 73, 74, 71, 75, 76, 77, 81, 82, 79, 80
+};
+
+static const yytype_uint8 yycheck[] =
+{
+ 9, 22, 0, 8, 7, 14, 4, 5, 13, 13,
+ 8, 9, 10, 11, 13, 13, 14, 15, 21, 17,
+ 18, 19, 14, 21, 7, 17, 4, 25, 13, 7,
+ 8, 9, 17, 11, 16, 3, 45, 20, 21, 48,
+ 18, 13, 20, 21, 4, 23, 22, 4, 8, 9,
+ 24, 11, 9, 13, 11, 13, 8, 9, 18, 11,
+ 13, 18, 13, 13, 13, 21, 18, 21, 23, 13,
+ 13, 13, 20, 13, 13, 13, 13, 13, 72, 20
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 27, 0, 4, 5, 8, 9, 10, 11, 13,
+ 14, 15, 17, 18, 19, 21, 25, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 22, 13, 13, 4, 7, 8, 20, 21, 23, 39,
+ 16, 14, 17, 4, 8, 13, 39, 3, 13, 22,
+ 24, 13, 13, 8, 13, 13, 13, 17, 8, 39,
+ 4, 39, 13, 13, 7, 20, 21, 41, 21, 21,
+ 23, 20, 13, 13, 13, 13, 13, 13, 21, 41,
+ 20, 13, 13
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (&yylloc, info, YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval, &yylloc, info)
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value, Location, info); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
static void
-TclDateerror(s)
- char *s;
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, DateInfo* info)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, info)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ YYLTYPE const * const yylocationp;
+ DateInfo* info;
+#endif
{
+ if (!yyvaluep)
+ return;
+ YYUSE (yylocationp);
+ YYUSE (info);
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
}
-static time_t
-ToSeconds(Hours, Minutes, Seconds, Meridian)
- time_t Hours;
- time_t Minutes;
- time_t Seconds;
- MERIDIAN Meridian;
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, DateInfo* info)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, info)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ YYLTYPE const * const yylocationp;
+ DateInfo* info;
+#endif
{
- if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
- return -1;
- switch (Meridian) {
- case MER24:
- if (Hours < 0 || Hours > 23)
- return -1;
- return (Hours * 60L + Minutes) * 60L + Seconds;
- case MERam:
- if (Hours < 1 || Hours > 12)
- return -1;
- return ((Hours % 12) * 60L + Minutes) * 60L + Seconds;
- case MERpm:
- if (Hours < 1 || Hours > 12)
- return -1;
- return (((Hours % 12) + 12) * 60L + Minutes) * 60L + Seconds;
- }
- return -1; /* Should never be reached */
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ YY_LOCATION_PRINT (yyoutput, *yylocationp);
+ YYFPRINTF (yyoutput, ": ");
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, info);
+ YYFPRINTF (yyoutput, ")");
}
-/*
- *-----------------------------------------------------------------------------
- *
- * Convert --
- *
- * Convert a {month, day, year, hours, minutes, seconds, meridian, dst}
- * tuple into a clock seconds value.
- *
- * Results:
- * 0 or -1 indicating success or failure.
- *
- * Side effects:
- * Fills TimePtr with the computed value.
- *
- *-----------------------------------------------------------------------------
- */
-static int
-Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode, TimePtr)
- time_t Month;
- time_t Day;
- time_t Year;
- time_t Hours;
- time_t Minutes;
- time_t Seconds;
- MERIDIAN Meridian;
- DSTMODE DSTmode;
- time_t *TimePtr;
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+#else
+static void
+yy_stack_print (bottom, top)
+ yytype_int16 *bottom;
+ yytype_int16 *top;
+#endif
{
- static int DaysInMonth[12] = {
- 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
- };
- time_t tod;
- time_t Julian;
- int i;
+ YYFPRINTF (stderr, "Stack now");
+ for (; bottom <= top; ++bottom)
+ YYFPRINTF (stderr, " %d", *bottom);
+ YYFPRINTF (stderr, "\n");
+}
- /* Figure out how many days are in February for the given year.
- * Every year divisible by 4 is a leap year.
- * But, every year divisible by 100 is not a leap year.
- * But, every year divisible by 400 is a leap year after all.
- */
- DaysInMonth[1] = IsLeapYear(Year) ? 29 : 28;
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
- /* Check the inputs for validity */
- if (Month < 1 || Month > 12
- || Year < START_OF_TIME || Year > END_OF_TIME
- || Day < 1 || Day > DaysInMonth[(int)--Month])
- return -1;
- /* Start computing the value. First determine the number of days
- * represented by the date, then multiply by the number of seconds/day.
- */
- for (Julian = Day - 1, i = 0; i < Month; i++)
- Julian += DaysInMonth[i];
- if (Year >= EPOCH) {
- for (i = EPOCH; i < Year; i++)
- Julian += 365 + IsLeapYear(i);
- } else {
- for (i = (int)Year; i < EPOCH; i++)
- Julian -= 365 + IsLeapYear(i);
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, DateInfo* info)
+#else
+static void
+yy_reduce_print (yyvsp, yylsp, yyrule, info)
+ YYSTYPE *yyvsp;
+ YYLTYPE *yylsp;
+ int yyrule;
+ DateInfo* info;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ fprintf (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ , &(yylsp[(yyi + 1) - (yynrhs)]) , info);
+ fprintf (stderr, "\n");
}
- Julian *= SECSPERDAY;
+}
- /* Add the timezone offset ?? */
- Julian += TclDateTimezone * 60L;
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, yylsp, Rule, info); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
- /* Add the number of seconds represented by the time component */
- if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
- return -1;
- Julian += tod;
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
- /* Perform a preliminary DST compensation ?? */
- if (DSTmode == DSTon
- || (DSTmode == DSTmaybe && TclpGetDate((TclpTime_t)&Julian, 0)->tm_isdst))
- Julian -= 60 * 60;
- *TimePtr = Julian;
- return 0;
-}
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
-static time_t
-DSTcorrect(Start, Future)
- time_t Start;
- time_t Future;
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
{
- time_t StartDay;
- time_t FutureDay;
- StartDay = (TclpGetDate((TclpTime_t)&Start, 0)->tm_hour + 1) % 24;
- FutureDay = (TclpGetDate((TclpTime_t)&Future, 0)->tm_hour + 1) % 24;
- return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+ if (! yyres)
+ return yystrlen (yystr);
-static time_t
-NamedDay(Start, DayOrdinal, DayNumber)
- time_t Start;
- time_t DayOrdinal;
- time_t DayNumber;
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
{
- struct tm *tm;
- time_t now;
-
- now = Start;
- tm = TclpGetDate((TclpTime_t)&now, 0);
- now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
- now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
- return DSTcorrect(Start, now);
+ int yyn = yypact[yystate];
+
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
}
+#endif /* YYERROR_VERBOSE */
+
-static time_t
-NamedMonth(Start, MonthOrdinal, MonthNumber)
- time_t Start;
- time_t MonthOrdinal;
- time_t MonthNumber;
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, DateInfo* info)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep, yylocationp, info)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+ YYLTYPE *yylocationp;
+ DateInfo* info;
+#endif
{
- struct tm *tm;
- time_t now;
- int result;
-
- now = Start;
- tm = TclpGetDate((TclpTime_t)&now, 0);
- /* To compute the next n'th month, we use this alg:
- * add n to year value
- * if currentMonth < requestedMonth decrement year value by 1 (so that
- * doing next february from january gives us february of the current year)
- * set day to 1, time to 0
- */
- tm->tm_year += (int)MonthOrdinal;
- if (tm->tm_mon < MonthNumber - 1) {
- tm->tm_year--;
- }
- result = Convert(MonthNumber, (time_t) 1, tm->tm_year + TM_YEAR_BASE,
- (time_t) 0, (time_t) 0, (time_t) 0, MER24, DSTmaybe, &now);
- if (result < 0) {
- return 0;
+ YYUSE (yyvaluep);
+ YYUSE (yylocationp);
+ YYUSE (info);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
}
- return DSTcorrect(Start, now);
}
+
-static int
-RelativeMonth(Start, RelMonth, TimePtr)
- time_t Start;
- time_t RelMonth;
- time_t *TimePtr;
+/* Prevent warnings from -Wmissing-prototypes. */
+
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (DateInfo* info);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (DateInfo* info)
+#else
+int
+yyparse (info)
+ DateInfo* info;
+#endif
+#endif
{
- struct tm *tm;
- time_t Month;
- time_t Year;
- time_t Julian;
- int result;
-
- if (RelMonth == 0) {
- *TimePtr = 0;
- return 0;
+ /* The look-ahead symbol. */
+int yychar;
+
+/* The semantic value of the look-ahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+/* Location data for the look-ahead symbol. */
+YYLTYPE yylloc;
+
+ int yystate;
+ int yyn;
+ int yyresult;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+ /* Look-ahead token as an internal (translated) token number. */
+ int yytoken = 0;
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+ /* Three stacks and their tools:
+ `yyss': related to states,
+ `yyvs': related to semantic values,
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss = yyssa;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ YYSTYPE *yyvsp;
+
+ /* The location stack. */
+ YYLTYPE yylsa[YYINITDEPTH];
+ YYLTYPE *yyls = yylsa;
+ YYLTYPE *yylsp;
+ /* The locations where the error started and ended. */
+ YYLTYPE yyerror_range[2];
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
+
+ YYSIZE_T yystacksize = YYINITDEPTH;
+
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+ YYLTYPE yyloc;
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+ yylsp = yyls;
+#if YYLTYPE_IS_TRIVIAL
+ /* Initialize the default location before parsing starts. */
+ yylloc.first_line = yylloc.last_line = 1;
+ yylloc.first_column = yylloc.last_column = 0;
+#endif
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+ YYLTYPE *yyls1 = yyls;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yyls1, yysize * sizeof (*yylsp),
+ &yystacksize);
+ yyls = yyls1;
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss);
+ YYSTACK_RELOCATE (yyvs);
+ YYSTACK_RELOCATE (yyls);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+ yylsp = yyls + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
}
- tm = TclpGetDate((TclpTime_t)&Start, 0);
- Month = 12 * (tm->tm_year + TM_YEAR_BASE) + tm->tm_mon + RelMonth;
- Year = Month / 12;
- Month = Month % 12 + 1;
- result = Convert(Month, (time_t) tm->tm_mday, Year,
- (time_t) tm->tm_hour, (time_t) tm->tm_min, (time_t) tm->tm_sec,
- MER24, DSTmaybe, &Julian);
- /*
- * The Julian time returned above is behind by one day, if "month"
- * or "year" is used to specify relative time and the GMT flag is true.
- * This problem occurs only when the current time is closer to
- * midnight, the difference being not more than its time difference
- * with GMT. For example, in US/Pacific time zone, the problem occurs
- * whenever the current time is between midnight to 8:00am or 7:00amDST.
- * See Bug# 413397 for more details and sample script.
- * To resolve this bug, we simply add the number of seconds corresponding
- * to timezone difference with GMT to Julian time, if GMT flag is true.
- */
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
- if (TclDateTimezone == 0) {
- Julian += TclpGetTimeZone((unsigned long) Start) * 60L;
+ /* Do appropriate processing given the current state. Read a
+ look-ahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to look-ahead token. */
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a look-ahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
}
- /*
- * The following iteration takes into account the case were we jump
- * into a "short month". Far example, "one month from Jan 31" will
- * fail because there is no Feb 31. The code below will reduce the
- * day and try converting the date until we succed or the date equals
- * 28 (which always works unless the date is bad in another way).
- */
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
- while ((result != 0) && (tm->tm_mday > 28)) {
- tm->tm_mday--;
- result = Convert(Month, (time_t) tm->tm_mday, Year,
- (time_t) tm->tm_hour, (time_t) tm->tm_min, (time_t) tm->tm_sec,
- MER24, DSTmaybe, &Julian);
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
}
- if (result != 0) {
- return -1;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the look-ahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ *++yyvsp = yylval;
+ *++yylsp = yylloc;
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+ /* Default location. */
+ YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 4:
+
+ {
+ yyHaveTime++;
+ ;}
+ break;
+
+ case 5:
+
+ {
+ yyHaveZone++;
+ ;}
+ break;
+
+ case 6:
+
+ {
+ yyHaveDate++;
+ ;}
+ break;
+
+ case 7:
+
+ {
+ yyHaveOrdinalMonth++;
+ ;}
+ break;
+
+ case 8:
+
+ {
+ yyHaveDay++;
+ ;}
+ break;
+
+ case 9:
+
+ {
+ yyHaveRel++;
+ ;}
+ break;
+
+ case 10:
+
+ {
+ yyHaveTime++;
+ yyHaveDate++;
+ ;}
+ break;
+
+ case 11:
+
+ {
+ yyHaveTime++;
+ yyHaveDate++;
+ yyHaveRel++;
+ ;}
+ break;
+
+ case 13:
+
+ {
+ yyHour = (yyvsp[(1) - (2)].Number);
+ yyMinutes = 0;
+ yySeconds = 0;
+ yyMeridian = (yyvsp[(2) - (2)].Meridian);
+ ;}
+ break;
+
+ case 14:
+
+ {
+ yyHour = (yyvsp[(1) - (4)].Number);
+ yyMinutes = (yyvsp[(3) - (4)].Number);
+ yySeconds = 0;
+ yyMeridian = (yyvsp[(4) - (4)].Meridian);
+ ;}
+ break;
+
+ case 15:
+
+ {
+ yyHour = (yyvsp[(1) - (5)].Number);
+ yyMinutes = (yyvsp[(3) - (5)].Number);
+ yyMeridian = MER24;
+ yyDSTmode = DSToff;
+ yyTimezone = ((yyvsp[(5) - (5)].Number) % 100 + ((yyvsp[(5) - (5)].Number) / 100) * 60);
+ ++yyHaveZone;
+ ;}
+ break;
+
+ case 16:
+
+ {
+ yyHour = (yyvsp[(1) - (6)].Number);
+ yyMinutes = (yyvsp[(3) - (6)].Number);
+ yySeconds = (yyvsp[(5) - (6)].Number);
+ yyMeridian = (yyvsp[(6) - (6)].Meridian);
+ ;}
+ break;
+
+ case 17:
+
+ {
+ yyHour = (yyvsp[(1) - (7)].Number);
+ yyMinutes = (yyvsp[(3) - (7)].Number);
+ yySeconds = (yyvsp[(5) - (7)].Number);
+ yyMeridian = MER24;
+ yyDSTmode = DSToff;
+ yyTimezone = ((yyvsp[(7) - (7)].Number) % 100 + ((yyvsp[(7) - (7)].Number) / 100) * 60);
+ ++yyHaveZone;
+ ;}
+ break;
+
+ case 18:
+
+ {
+ yyTimezone = (yyvsp[(1) - (2)].Number);
+ yyDSTmode = DSTon;
+ ;}
+ break;
+
+ case 19:
+
+ {
+ yyTimezone = (yyvsp[(1) - (1)].Number);
+ yyDSTmode = DSToff;
+ ;}
+ break;
+
+ case 20:
+
+ {
+ yyTimezone = (yyvsp[(1) - (1)].Number);
+ yyDSTmode = DSTon;
+ ;}
+ break;
+
+ case 21:
+
+ {
+ yyDayOrdinal = 1;
+ yyDayNumber = (yyvsp[(1) - (1)].Number);
+ ;}
+ break;
+
+ case 22:
+
+ {
+ yyDayOrdinal = 1;
+ yyDayNumber = (yyvsp[(1) - (2)].Number);
+ ;}
+ break;
+
+ case 23:
+
+ {
+ yyDayOrdinal = (yyvsp[(1) - (2)].Number);
+ yyDayNumber = (yyvsp[(2) - (2)].Number);
+ ;}
+ break;
+
+ case 24:
+
+ {
+ yyDayOrdinal = (yyvsp[(1) - (3)].Number) * (yyvsp[(2) - (3)].Number);
+ yyDayNumber = (yyvsp[(3) - (3)].Number);
+ ;}
+ break;
+
+ case 25:
+
+ {
+ yyDayOrdinal = 2;
+ yyDayNumber = (yyvsp[(2) - (2)].Number);
+ ;}
+ break;
+
+ case 26:
+
+ {
+ yyMonth = (yyvsp[(1) - (3)].Number);
+ yyDay = (yyvsp[(3) - (3)].Number);
+ ;}
+ break;
+
+ case 27:
+
+ {
+ yyMonth = (yyvsp[(1) - (5)].Number);
+ yyDay = (yyvsp[(3) - (5)].Number);
+ yyYear = (yyvsp[(5) - (5)].Number);
+ ;}
+ break;
+
+ case 28:
+
+ {
+ yyYear = (yyvsp[(1) - (1)].Number) / 10000;
+ yyMonth = ((yyvsp[(1) - (1)].Number) % 10000)/100;
+ yyDay = (yyvsp[(1) - (1)].Number) % 100;
+ ;}
+ break;
+
+ case 29:
+
+ {
+ yyDay = (yyvsp[(1) - (5)].Number);
+ yyMonth = (yyvsp[(3) - (5)].Number);
+ yyYear = (yyvsp[(5) - (5)].Number);
+ ;}
+ break;
+
+ case 30:
+
+ {
+ yyMonth = (yyvsp[(3) - (5)].Number);
+ yyDay = (yyvsp[(5) - (5)].Number);
+ yyYear = (yyvsp[(1) - (5)].Number);
+ ;}
+ break;
+
+ case 31:
+
+ {
+ yyMonth = (yyvsp[(1) - (2)].Number);
+ yyDay = (yyvsp[(2) - (2)].Number);
+ ;}
+ break;
+
+ case 32:
+
+ {
+ yyMonth = (yyvsp[(1) - (4)].Number);
+ yyDay = (yyvsp[(2) - (4)].Number);
+ yyYear = (yyvsp[(4) - (4)].Number);
+ ;}
+ break;
+
+ case 33:
+
+ {
+ yyMonth = (yyvsp[(2) - (2)].Number);
+ yyDay = (yyvsp[(1) - (2)].Number);
+ ;}
+ break;
+
+ case 34:
+
+ {
+ yyMonth = 1;
+ yyDay = 1;
+ yyYear = EPOCH;
+ ;}
+ break;
+
+ case 35:
+
+ {
+ yyMonth = (yyvsp[(2) - (3)].Number);
+ yyDay = (yyvsp[(1) - (3)].Number);
+ yyYear = (yyvsp[(3) - (3)].Number);
+ ;}
+ break;
+
+ case 36:
+
+ {
+ yyMonthOrdinal = 1;
+ yyMonth = (yyvsp[(2) - (2)].Number);
+ ;}
+ break;
+
+ case 37:
+
+ {
+ yyMonthOrdinal = (yyvsp[(2) - (3)].Number);
+ yyMonth = (yyvsp[(3) - (3)].Number);
+ ;}
+ break;
+
+ case 38:
+
+ {
+ if ((yyvsp[(2) - (3)].Number) != HOUR( 7)) YYABORT;
+ yyYear = (yyvsp[(1) - (3)].Number) / 10000;
+ yyMonth = ((yyvsp[(1) - (3)].Number) % 10000)/100;
+ yyDay = (yyvsp[(1) - (3)].Number) % 100;
+ yyHour = (yyvsp[(3) - (3)].Number) / 10000;
+ yyMinutes = ((yyvsp[(3) - (3)].Number) % 10000)/100;
+ yySeconds = (yyvsp[(3) - (3)].Number) % 100;
+ ;}
+ break;
+
+ case 39:
+
+ {
+ if ((yyvsp[(2) - (7)].Number) != HOUR( 7)) YYABORT;
+ yyYear = (yyvsp[(1) - (7)].Number) / 10000;
+ yyMonth = ((yyvsp[(1) - (7)].Number) % 10000)/100;
+ yyDay = (yyvsp[(1) - (7)].Number) % 100;
+ yyHour = (yyvsp[(3) - (7)].Number);
+ yyMinutes = (yyvsp[(5) - (7)].Number);
+ yySeconds = (yyvsp[(7) - (7)].Number);
+ ;}
+ break;
+
+ case 40:
+
+ {
+ yyYear = (yyvsp[(1) - (2)].Number) / 10000;
+ yyMonth = ((yyvsp[(1) - (2)].Number) % 10000)/100;
+ yyDay = (yyvsp[(1) - (2)].Number) % 100;
+ yyHour = (yyvsp[(2) - (2)].Number) / 10000;
+ yyMinutes = ((yyvsp[(2) - (2)].Number) % 10000)/100;
+ yySeconds = (yyvsp[(2) - (2)].Number) % 100;
+ ;}
+ break;
+
+ case 41:
+
+ {
+ /*
+ * Offset computed year by -377 so that the returned years will be
+ * in a range accessible with a 32 bit clock seconds value.
+ */
+
+ yyYear = (yyvsp[(2) - (4)].Number)/1000 + 2323 - 377;
+ yyDay = 1;
+ yyMonth = 1;
+ yyRelDay += (((yyvsp[(2) - (4)].Number)%1000)*(365 + IsLeapYear(yyYear)))/1000;
+ yyRelSeconds += (yyvsp[(4) - (4)].Number) * 144 * 60;
+ ;}
+ break;
+
+ case 42:
+
+ {
+ yyRelSeconds *= -1;
+ yyRelMonth *= -1;
+ yyRelDay *= -1;
+ ;}
+ break;
+
+ case 44:
+
+ {
+ *yyRelPointer += (yyvsp[(1) - (3)].Number) * (yyvsp[(2) - (3)].Number) * (yyvsp[(3) - (3)].Number);
+ ;}
+ break;
+
+ case 45:
+
+ {
+ *yyRelPointer += (yyvsp[(1) - (2)].Number) * (yyvsp[(2) - (2)].Number);
+ ;}
+ break;
+
+ case 46:
+
+ {
+ *yyRelPointer += (yyvsp[(2) - (2)].Number);
+ ;}
+ break;
+
+ case 47:
+
+ {
+ *yyRelPointer += (yyvsp[(2) - (3)].Number) * (yyvsp[(3) - (3)].Number);
+ ;}
+ break;
+
+ case 48:
+
+ {
+ *yyRelPointer += (yyvsp[(1) - (1)].Number);
+ ;}
+ break;
+
+ case 49:
+
+ {
+ (yyval.Number) = -1;
+ ;}
+ break;
+
+ case 50:
+
+ {
+ (yyval.Number) = 1;
+ ;}
+ break;
+
+ case 51:
+
+ {
+ (yyval.Number) = (yyvsp[(1) - (1)].Number);
+ yyRelPointer = &yyRelSeconds;
+ ;}
+ break;
+
+ case 52:
+
+ {
+ (yyval.Number) = (yyvsp[(1) - (1)].Number);
+ yyRelPointer = &yyRelDay;
+ ;}
+ break;
+
+ case 53:
+
+ {
+ (yyval.Number) = (yyvsp[(1) - (1)].Number);
+ yyRelPointer = &yyRelMonth;
+ ;}
+ break;
+
+ case 54:
+
+ {
+ if (yyHaveTime && yyHaveDate && !yyHaveRel) {
+ yyYear = (yyvsp[(1) - (1)].Number);
+ } else {
+ yyHaveTime++;
+ if (yyDigitCount <= 2) {
+ yyHour = (yyvsp[(1) - (1)].Number);
+ yyMinutes = 0;
+ } else {
+ yyHour = (yyvsp[(1) - (1)].Number) / 100;
+ yyMinutes = (yyvsp[(1) - (1)].Number) % 100;
+ }
+ yySeconds = 0;
+ yyMeridian = MER24;
+ }
+ ;}
+ break;
+
+ case 55:
+
+ {
+ (yyval.Meridian) = MER24;
+ ;}
+ break;
+
+ case 56:
+
+ {
+ (yyval.Meridian) = (yyvsp[(1) - (1)].Meridian);
+ ;}
+ break;
+
+
+/* Line 1267 of yacc.c. */
+
+ default: break;
}
- *TimePtr = DSTcorrect(Start, Julian);
- return 0;
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+ *++yylsp = yyloc;
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (&yylloc, info, YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (&yylloc, info, yymsg);
+ }
+ else
+ {
+ yyerror (&yylloc, info, YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
+ }
+
+ yyerror_range[0] = yylloc;
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse look-ahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval, &yylloc, info);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse look-ahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ yyerror_range[0] = yylsp[1-yylen];
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+ yyerror_range[0] = *yylsp;
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp, yylsp, info);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ *++yyvsp = yylval;
+
+ yyerror_range[1] = yylloc;
+ /* Using YYLLOC is tempting, but would change the location of
+ the look-ahead. YYLOC is available though. */
+ YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);
+ *++yylsp = yyloc;
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#ifndef yyoverflow
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (&yylloc, info, YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEOF && yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, &yylloc, info);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp, yylsp, info);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
}
+
+
+MODULE_SCOPE int yychar;
+MODULE_SCOPE YYSTYPE yylval;
+MODULE_SCOPE int yynerrs;
+
/*
- *-----------------------------------------------------------------------------
- *
- * RelativeDay --
- *
- * Given a starting time and a number of days before or after, compute the
- * DST corrected difference between those dates.
- *
- * Results:
- * 1 or -1 indicating success or failure.
- *
- * Side effects:
- * Fills TimePtr with the computed value.
- *
- *-----------------------------------------------------------------------------
+ * Month and day table.
*/
-static int
-RelativeDay(Start, RelDay, TimePtr)
- time_t Start;
- time_t RelDay;
- time_t *TimePtr;
+static TABLE MonthDayTable[] = {
+ { "january", tMONTH, 1 },
+ { "february", tMONTH, 2 },
+ { "march", tMONTH, 3 },
+ { "april", tMONTH, 4 },
+ { "may", tMONTH, 5 },
+ { "june", tMONTH, 6 },
+ { "july", tMONTH, 7 },
+ { "august", tMONTH, 8 },
+ { "september", tMONTH, 9 },
+ { "sept", tMONTH, 9 },
+ { "october", tMONTH, 10 },
+ { "november", tMONTH, 11 },
+ { "december", tMONTH, 12 },
+ { "sunday", tDAY, 0 },
+ { "monday", tDAY, 1 },
+ { "tuesday", tDAY, 2 },
+ { "tues", tDAY, 2 },
+ { "wednesday", tDAY, 3 },
+ { "wednes", tDAY, 3 },
+ { "thursday", tDAY, 4 },
+ { "thur", tDAY, 4 },
+ { "thurs", tDAY, 4 },
+ { "friday", tDAY, 5 },
+ { "saturday", tDAY, 6 },
+ { NULL }
+};
+
+/*
+ * Time units table.
+ */
+
+static TABLE UnitsTable[] = {
+ { "year", tMONTH_UNIT, 12 },
+ { "month", tMONTH_UNIT, 1 },
+ { "fortnight", tDAY_UNIT, 14 },
+ { "week", tDAY_UNIT, 7 },
+ { "day", tDAY_UNIT, 1 },
+ { "hour", tSEC_UNIT, 60 * 60 },
+ { "minute", tSEC_UNIT, 60 },
+ { "min", tSEC_UNIT, 60 },
+ { "second", tSEC_UNIT, 1 },
+ { "sec", tSEC_UNIT, 1 },
+ { NULL }
+};
+
+/*
+ * Assorted relative-time words.
+ */
+
+static TABLE OtherTable[] = {
+ { "tomorrow", tDAY_UNIT, 1 },
+ { "yesterday", tDAY_UNIT, -1 },
+ { "today", tDAY_UNIT, 0 },
+ { "now", tSEC_UNIT, 0 },
+ { "last", tUNUMBER, -1 },
+ { "this", tSEC_UNIT, 0 },
+ { "next", tNEXT, 1 },
+#if 0
+ { "first", tUNUMBER, 1 },
+ { "second", tUNUMBER, 2 },
+ { "third", tUNUMBER, 3 },
+ { "fourth", tUNUMBER, 4 },
+ { "fifth", tUNUMBER, 5 },
+ { "sixth", tUNUMBER, 6 },
+ { "seventh", tUNUMBER, 7 },
+ { "eighth", tUNUMBER, 8 },
+ { "ninth", tUNUMBER, 9 },
+ { "tenth", tUNUMBER, 10 },
+ { "eleventh", tUNUMBER, 11 },
+ { "twelfth", tUNUMBER, 12 },
+#endif
+ { "ago", tAGO, 1 },
+ { "epoch", tEPOCH, 0 },
+ { "stardate", tSTARDATE, 0 },
+ { NULL }
+};
+
+/*
+ * The timezone table. (Note: This table was modified to not use any floating
+ * point constants to work around an SGI compiler bug).
+ */
+
+static TABLE TimezoneTable[] = {
+ { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
+ { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
+ { "utc", tZONE, HOUR( 0) },
+ { "uct", tZONE, HOUR( 0) }, /* Universal Coordinated Time */
+ { "wet", tZONE, HOUR( 0) }, /* Western European */
+ { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
+ { "wat", tZONE, HOUR( 1) }, /* West Africa */
+ { "at", tZONE, HOUR( 2) }, /* Azores */
+#if 0
+ /* For completeness. BST is also British Summer, and GST is
+ * also Guam Standard. */
+ { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
+ { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
+#endif
+ { "nft", tZONE, HOUR( 7/2) }, /* Newfoundland */
+ { "nst", tZONE, HOUR( 7/2) }, /* Newfoundland Standard */
+ { "ndt", tDAYZONE, HOUR( 7/2) }, /* Newfoundland Daylight */
+ { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
+ { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
+ { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
+ { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
+ { "cst", tZONE, HOUR( 6) }, /* Central Standard */
+ { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
+ { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
+ { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
+ { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
+ { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
+ { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
+ { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
+ { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
+ { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
+ { "cat", tZONE, HOUR(10) }, /* Central Alaska */
+ { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
+ { "nt", tZONE, HOUR(11) }, /* Nome */
+ { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
+ { "cet", tZONE, -HOUR( 1) }, /* Central European */
+ { "cest", tDAYZONE, -HOUR( 1) }, /* Central European Summer */
+ { "met", tZONE, -HOUR( 1) }, /* Middle European */
+ { "mewt", tZONE, -HOUR( 1) }, /* Middle European Winter */
+ { "mest", tDAYZONE, -HOUR( 1) }, /* Middle European Summer */
+ { "swt", tZONE, -HOUR( 1) }, /* Swedish Winter */
+ { "sst", tDAYZONE, -HOUR( 1) }, /* Swedish Summer */
+ { "fwt", tZONE, -HOUR( 1) }, /* French Winter */
+ { "fst", tDAYZONE, -HOUR( 1) }, /* French Summer */
+ { "eet", tZONE, -HOUR( 2) }, /* Eastern Europe, USSR Zone 1 */
+ { "bt", tZONE, -HOUR( 3) }, /* Baghdad, USSR Zone 2 */
+ { "it", tZONE, -HOUR( 7/2) }, /* Iran */
+ { "zp4", tZONE, -HOUR( 4) }, /* USSR Zone 3 */
+ { "zp5", tZONE, -HOUR( 5) }, /* USSR Zone 4 */
+ { "ist", tZONE, -HOUR(11/2) }, /* Indian Standard */
+ { "zp6", tZONE, -HOUR( 6) }, /* USSR Zone 5 */
+#if 0
+ /* For completeness. NST is also Newfoundland Stanard, nad SST is
+ * also Swedish Summer. */
+ { "nst", tZONE, -HOUR(13/2) }, /* North Sumatra */
+ { "sst", tZONE, -HOUR( 7) }, /* South Sumatra, USSR Zone 6 */
+#endif /* 0 */
+ { "wast", tZONE, -HOUR( 7) }, /* West Australian Standard */
+ { "wadt", tDAYZONE, -HOUR( 7) }, /* West Australian Daylight */
+ { "jt", tZONE, -HOUR(15/2) }, /* Java (3pm in Cronusland!) */
+ { "cct", tZONE, -HOUR( 8) }, /* China Coast, USSR Zone 7 */
+ { "jst", tZONE, -HOUR( 9) }, /* Japan Standard, USSR Zone 8 */
+ { "jdt", tDAYZONE, -HOUR( 9) }, /* Japan Daylight */
+ { "kst", tZONE, -HOUR( 9) }, /* Korea Standard */
+ { "kdt", tDAYZONE, -HOUR( 9) }, /* Korea Daylight */
+ { "cast", tZONE, -HOUR(19/2) }, /* Central Australian Standard */
+ { "cadt", tDAYZONE, -HOUR(19/2) }, /* Central Australian Daylight */
+ { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
+ { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
+ { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
+ { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
+ { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
+ { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
+ { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
+ /* ADDED BY Marco Nijdam */
+ { "dst", tDST, HOUR( 0) }, /* DST on (hour is ignored) */
+ /* End ADDED */
+ { NULL }
+};
+
+/*
+ * Military timezone table.
+ */
+
+static TABLE MilitaryTable[] = {
+ { "a", tZONE, -HOUR( 1) },
+ { "b", tZONE, -HOUR( 2) },
+ { "c", tZONE, -HOUR( 3) },
+ { "d", tZONE, -HOUR( 4) },
+ { "e", tZONE, -HOUR( 5) },
+ { "f", tZONE, -HOUR( 6) },
+ { "g", tZONE, -HOUR( 7) },
+ { "h", tZONE, -HOUR( 8) },
+ { "i", tZONE, -HOUR( 9) },
+ { "k", tZONE, -HOUR(10) },
+ { "l", tZONE, -HOUR(11) },
+ { "m", tZONE, -HOUR(12) },
+ { "n", tZONE, HOUR( 1) },
+ { "o", tZONE, HOUR( 2) },
+ { "p", tZONE, HOUR( 3) },
+ { "q", tZONE, HOUR( 4) },
+ { "r", tZONE, HOUR( 5) },
+ { "s", tZONE, HOUR( 6) },
+ { "t", tZONE, HOUR( 7) },
+ { "u", tZONE, HOUR( 8) },
+ { "v", tZONE, HOUR( 9) },
+ { "w", tZONE, HOUR( 10) },
+ { "x", tZONE, HOUR( 11) },
+ { "y", tZONE, HOUR( 12) },
+ { "z", tZONE, HOUR( 0) },
+ { NULL }
+};
+
+/*
+ * Dump error messages in the bit bucket.
+ */
+
+static void
+TclDateerror(
+ YYLTYPE* location,
+ DateInfo* infoPtr,
+ const char *s)
{
- time_t new;
+ Tcl_Obj* t;
+ Tcl_AppendToObj(infoPtr->messages, infoPtr->separatrix, -1);
+ Tcl_AppendToObj(infoPtr->messages, s, -1);
+ Tcl_AppendToObj(infoPtr->messages, " (characters ", -1);
+ t = Tcl_NewIntObj(location->first_column);
+ Tcl_IncrRefCount(t);
+ Tcl_AppendObjToObj(infoPtr->messages, t);
+ Tcl_DecrRefCount(t);
+ Tcl_AppendToObj(infoPtr->messages, "-", -1);
+ t = Tcl_NewIntObj(location->last_column);
+ Tcl_IncrRefCount(t);
+ Tcl_AppendObjToObj(infoPtr->messages, t);
+ Tcl_DecrRefCount(t);
+ Tcl_AppendToObj(infoPtr->messages, ")", -1);
+ infoPtr->separatrix = "\n";
+}
- new = Start + (RelDay * 60 * 60 * 24);
- *TimePtr = DSTcorrect(Start, new);
- return 1;
+static time_t
+ToSeconds(
+ time_t Hours,
+ time_t Minutes,
+ time_t Seconds,
+ MERIDIAN Meridian)
+{
+ if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59) {
+ return -1;
+ }
+ switch (Meridian) {
+ case MER24:
+ if (Hours < 0 || Hours > 23) {
+ return -1;
+ }
+ return (Hours * 60L + Minutes) * 60L + Seconds;
+ case MERam:
+ if (Hours < 1 || Hours > 12) {
+ return -1;
+ }
+ return ((Hours % 12) * 60L + Minutes) * 60L + Seconds;
+ case MERpm:
+ if (Hours < 1 || Hours > 12) {
+ return -1;
+ }
+ return (((Hours % 12) + 12) * 60L + Minutes) * 60L + Seconds;
+ }
+ return -1; /* Should never be reached */
}
static int
-LookupWord(buff)
- char *buff;
+LookupWord(
+ YYSTYPE* yylvalPtr,
+ char *buff)
{
register char *p;
register char *q;
register TABLE *tp;
- int i;
- int abbrev;
+ int i, abbrev;
/*
* Make it lowercase.
@@ -666,1208 +2570,347 @@ LookupWord(buff)
Tcl_UtfToLower(buff);
if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
- TclDatelval.Meridian = MERam;
- return tMERIDIAN;
+ yylvalPtr->Meridian = MERam;
+ return tMERIDIAN;
}
if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
- TclDatelval.Meridian = MERpm;
- return tMERIDIAN;
+ yylvalPtr->Meridian = MERpm;
+ return tMERIDIAN;
}
/*
* See if we have an abbreviation for a month.
*/
+
if (strlen(buff) == 3) {
- abbrev = 1;
+ abbrev = 1;
} else if (strlen(buff) == 4 && buff[3] == '.') {
- abbrev = 1;
- buff[3] = '\0';
+ abbrev = 1;
+ buff[3] = '\0';
} else {
- abbrev = 0;
+ abbrev = 0;
}
for (tp = MonthDayTable; tp->name; tp++) {
- if (abbrev) {
- if (strncmp(buff, tp->name, 3) == 0) {
- TclDatelval.Number = tp->value;
- return tp->type;
- }
- } else if (strcmp(buff, tp->name) == 0) {
- TclDatelval.Number = tp->value;
- return tp->type;
- }
+ if (abbrev) {
+ if (strncmp(buff, tp->name, 3) == 0) {
+ yylvalPtr->Number = tp->value;
+ return tp->type;
+ }
+ } else if (strcmp(buff, tp->name) == 0) {
+ yylvalPtr->Number = tp->value;
+ return tp->type;
+ }
}
for (tp = TimezoneTable; tp->name; tp++) {
- if (strcmp(buff, tp->name) == 0) {
- TclDatelval.Number = tp->value;
- return tp->type;
- }
+ if (strcmp(buff, tp->name) == 0) {
+ yylvalPtr->Number = tp->value;
+ return tp->type;
+ }
}
for (tp = UnitsTable; tp->name; tp++) {
- if (strcmp(buff, tp->name) == 0) {
- TclDatelval.Number = tp->value;
- return tp->type;
- }
+ if (strcmp(buff, tp->name) == 0) {
+ yylvalPtr->Number = tp->value;
+ return tp->type;
+ }
}
/*
* Strip off any plural and try the units table again.
*/
+
i = strlen(buff) - 1;
- if (buff[i] == 's') {
- buff[i] = '\0';
- for (tp = UnitsTable; tp->name; tp++) {
- if (strcmp(buff, tp->name) == 0) {
- TclDatelval.Number = tp->value;
- return tp->type;
- }
+ if (i > 0 && buff[i] == 's') {
+ buff[i] = '\0';
+ for (tp = UnitsTable; tp->name; tp++) {
+ if (strcmp(buff, tp->name) == 0) {
+ yylvalPtr->Number = tp->value;
+ return tp->type;
+ }
}
}
for (tp = OtherTable; tp->name; tp++) {
- if (strcmp(buff, tp->name) == 0) {
- TclDatelval.Number = tp->value;
- return tp->type;
- }
+ if (strcmp(buff, tp->name) == 0) {
+ yylvalPtr->Number = tp->value;
+ return tp->type;
+ }
}
/*
* Military timezones.
*/
+
if (buff[1] == '\0' && !(*buff & 0x80)
- && isalpha(UCHAR(*buff))) { /* INTL: ISO only */
- for (tp = MilitaryTable; tp->name; tp++) {
- if (strcmp(buff, tp->name) == 0) {
- TclDatelval.Number = tp->value;
- return tp->type;
- }
+ && isalpha(UCHAR(*buff))) { /* INTL: ISO only */
+ for (tp = MilitaryTable; tp->name; tp++) {
+ if (strcmp(buff, tp->name) == 0) {
+ yylvalPtr->Number = tp->value;
+ return tp->type;
+ }
}
}
/*
* Drop out any periods and try the timezone table again.
*/
- for (i = 0, p = q = buff; *q; q++)
- if (*q != '.') {
- *p++ = *q;
- } else {
- i++;
+
+ for (i = 0, p = q = buff; *q; q++) {
+ if (*q != '.') {
+ *p++ = *q;
+ } else {
+ i++;
}
+ }
*p = '\0';
if (i) {
- for (tp = TimezoneTable; tp->name; tp++) {
- if (strcmp(buff, tp->name) == 0) {
- TclDatelval.Number = tp->value;
- return tp->type;
- }
+ for (tp = TimezoneTable; tp->name; tp++) {
+ if (strcmp(buff, tp->name) == 0) {
+ yylvalPtr->Number = tp->value;
+ return tp->type;
+ }
}
}
-
+
return tID;
}
-
static int
-TclDatelex()
+TclDatelex(
+ YYSTYPE* yylvalPtr,
+ YYLTYPE* location,
+ DateInfo *info)
{
- register char c;
- register char *p;
- char buff[20];
- int Count;
+ register char c;
+ register char *p;
+ char buff[20];
+ int Count;
+ location->first_column = yyInput - info->dateStart;
for ( ; ; ) {
- while (isspace(UCHAR(*TclDateInput))) {
- TclDateInput++;
+ while (isspace(UCHAR(*yyInput))) {
+ yyInput++;
}
- if (isdigit(UCHAR(c = *TclDateInput))) { /* INTL: digit */
- /* convert the string into a number; count the number of digits */
+ if (isdigit(UCHAR(c = *yyInput))) { /* INTL: digit */
+ /*
+ * Convert the string into a number; count the number of digits.
+ */
+
Count = 0;
- for (TclDatelval.Number = 0;
- isdigit(UCHAR(c = *TclDateInput++)); ) { /* INTL: digit */
- TclDatelval.Number = 10 * TclDatelval.Number + c - '0';
+ for (yylvalPtr->Number = 0;
+ isdigit(UCHAR(c = *yyInput++)); ) { /* INTL: digit */
+ yylvalPtr->Number = 10 * yylvalPtr->Number + c - '0';
Count++;
}
- TclDateInput--;
- /* A number with 6 or more digits is considered an ISO 8601 base */
+ yyInput--;
+ yyDigitCount = Count;
+
+ /*
+ * A number with 6 or more digits is considered an ISO 8601 base.
+ */
+
if (Count >= 6) {
+ location->last_column = yyInput - info->dateStart - 1;
return tISOBASE;
} else {
+ location->last_column = yyInput - info->dateStart - 1;
return tUNUMBER;
}
- }
- if (!(c & 0x80) && isalpha(UCHAR(c))) { /* INTL: ISO only. */
- for (p = buff; isalpha(UCHAR(c = *TclDateInput++)) /* INTL: ISO only. */
+ }
+ if (!(c & 0x80) && isalpha(UCHAR(c))) { /* INTL: ISO only. */
+ for (p = buff; isalpha(UCHAR(c = *yyInput++)) /* INTL: ISO only. */
|| c == '.'; ) {
- if (p < &buff[sizeof buff - 1]) {
- *p++ = c;
+ if (p < &buff[sizeof buff - 1]) {
+ *p++ = c;
}
}
- *p = '\0';
- TclDateInput--;
- return LookupWord(buff);
- }
- if (c != '(') {
- return *TclDateInput++;
+ *p = '\0';
+ yyInput--;
+ location->last_column = yyInput - info->dateStart - 1;
+ return LookupWord(yylvalPtr, buff);
}
- Count = 0;
- do {
- c = *TclDateInput++;
- if (c == '\0') {
- return c;
+ if (c != '(') {
+ location->last_column = yyInput - info->dateStart;
+ return *yyInput++;
+ }
+ Count = 0;
+ do {
+ c = *yyInput++;
+ if (c == '\0') {
+ location->last_column = yyInput - info->dateStart - 1;
+ return c;
} else if (c == '(') {
- Count++;
+ Count++;
} else if (c == ')') {
- Count--;
+ Count--;
}
- } while (Count > 0);
+ } while (Count > 0);
}
}
-/*
- * Specify zone is of -50000 to force GMT. (This allows BST to work).
- */
-
int
-TclGetDate(p, now, zone, timePtr)
- char *p;
- Tcl_WideInt now;
- long zone;
- Tcl_WideInt *timePtr;
+TclClockOldscanObjCmd(
+ ClientData clientData, /* Unused */
+ Tcl_Interp *interp, /* Tcl interpreter */
+ int objc, /* Count of paraneters */
+ Tcl_Obj *CONST *objv) /* Parameters */
{
- struct tm *tm;
- time_t Start;
- time_t Time;
- time_t tod;
- int thisyear;
-
- TclDateInput = p;
- /* now has to be cast to a time_t for 64bit compliance */
- Start = (time_t) now;
- tm = TclpGetDate((TclpTime_t) &Start, (zone == -50000));
- thisyear = tm->tm_year + TM_YEAR_BASE;
- TclDateYear = thisyear;
- TclDateMonth = tm->tm_mon + 1;
- TclDateDay = tm->tm_mday;
- TclDateTimezone = zone;
- if (zone == -50000) {
- TclDateDSTmode = DSToff; /* assume GMT */
- TclDateTimezone = 0;
- } else {
- TclDateDSTmode = DSTmaybe;
+ Tcl_Obj *result, *resultElement;
+ int yr, mo, da;
+ DateInfo dateInfo;
+ DateInfo* info = &dateInfo;
+ int status;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "stringToParse baseYear baseMonth baseDay" );
+ return TCL_ERROR;
}
- TclDateHour = 0;
- TclDateMinutes = 0;
- TclDateSeconds = 0;
- TclDateMeridian = MER24;
- TclDateRelSeconds = 0;
- TclDateRelMonth = 0;
- TclDateRelDay = 0;
- TclDateRelPointer = NULL;
-
- TclDateHaveDate = 0;
- TclDateHaveDay = 0;
- TclDateHaveOrdinalMonth = 0;
- TclDateHaveRel = 0;
- TclDateHaveTime = 0;
- TclDateHaveZone = 0;
-
- if (TclDateparse() || TclDateHaveTime > 1 || TclDateHaveZone > 1 || TclDateHaveDate > 1 ||
- TclDateHaveDay > 1 || TclDateHaveOrdinalMonth > 1) {
- return -1;
+
+ yyInput = Tcl_GetString( objv[1] );
+ dateInfo.dateStart = yyInput;
+
+ yyHaveDate = 0;
+ if (Tcl_GetIntFromObj(interp, objv[2], &yr) != TCL_OK
+ || Tcl_GetIntFromObj(interp, objv[3], &mo) != TCL_OK
+ || Tcl_GetIntFromObj(interp, objv[4], &da) != TCL_OK) {
+ return TCL_ERROR;
}
-
- if (TclDateHaveDate || TclDateHaveTime || TclDateHaveDay) {
- if (TclDateYear < 0) {
- TclDateYear = -TclDateYear;
- }
- /*
- * The following line handles years that are specified using
- * only two digits. The line of code below implements a policy
- * defined by the X/Open workgroup on the millinium rollover.
- * Note: some of those dates may not actually be valid on some
- * platforms. The POSIX standard startes that the dates 70-99
- * shall refer to 1970-1999 and 00-38 shall refer to 2000-2038.
- * This later definition should work on all platforms.
- */
-
- if (TclDateYear < 100) {
- if (TclDateYear >= 69) {
- TclDateYear += 1900;
- } else {
- TclDateYear += 2000;
- }
- }
- if (Convert(TclDateMonth, TclDateDay, TclDateYear, TclDateHour, TclDateMinutes, TclDateSeconds,
- TclDateMeridian, TclDateDSTmode, &Start) < 0) {
- return -1;
- }
- } else {
- Start = (time_t) now;
- if (!TclDateHaveRel) {
- Start -= ((tm->tm_hour * 60L * 60L) +
- tm->tm_min * 60L) + tm->tm_sec;
- }
+ yyYear = yr; yyMonth = mo; yyDay = da;
+
+ yyHaveTime = 0;
+ yyHour = 0; yyMinutes = 0; yySeconds = 0; yyMeridian = MER24;
+
+ yyHaveZone = 0;
+ yyTimezone = 0; yyDSTmode = DSTmaybe;
+
+ yyHaveOrdinalMonth = 0;
+ yyMonthOrdinal = 0;
+
+ yyHaveDay = 0;
+ yyDayOrdinal = 0; yyDayNumber = 0;
+
+ yyHaveRel = 0;
+ yyRelMonth = 0; yyRelDay = 0; yyRelSeconds = 0; yyRelPointer = NULL;
+
+ dateInfo.messages = Tcl_NewObj();
+ dateInfo.separatrix = "";
+ Tcl_IncrRefCount(dateInfo.messages);
+
+ status = yyparse(&dateInfo);
+ if (status == 1) {
+ Tcl_SetObjResult(interp, dateInfo.messages);
+ Tcl_DecrRefCount(dateInfo.messages);
+ return TCL_ERROR;
+ } else if (status == 2) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("memory exhausted", -1));
+ Tcl_DecrRefCount(dateInfo.messages);
+ return TCL_ERROR;
+ } else if (status != 0) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("Unknown status returned "
+ "from date parser. Please "
+ "report this error as a "
+ "bug in Tcl.", -1));
+ Tcl_DecrRefCount(dateInfo.messages);
+ return TCL_ERROR;
}
+ Tcl_DecrRefCount(dateInfo.messages);
- Start += TclDateRelSeconds;
- if (RelativeMonth(Start, TclDateRelMonth, &Time) < 0) {
- return -1;
+ if (yyHaveDate > 1) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("more than one date in string", -1));
+ return TCL_ERROR;
}
- Start += Time;
-
- if (RelativeDay(Start, TclDateRelDay, &Time) < 0) {
- return -1;
+ if (yyHaveTime > 1) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("more than one time of day in string", -1));
+ return TCL_ERROR;
}
- Start += Time;
-
- if (TclDateHaveDay && !TclDateHaveDate) {
- tod = NamedDay(Start, TclDateDayOrdinal, TclDateDayNumber);
- Start += tod;
+ if (yyHaveZone > 1) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("more than one time zone in string", -1));
+ return TCL_ERROR;
}
-
- if (TclDateHaveOrdinalMonth) {
- tod = NamedMonth(Start, TclDateMonthOrdinal, TclDateMonth);
- Start += tod;
+ if (yyHaveDay > 1) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("more than one weekday in string", -1));
+ return TCL_ERROR;
+ }
+ if (yyHaveOrdinalMonth > 1) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("more than one ordinal month in string", -1));
+ return TCL_ERROR;
}
-
- *timePtr = Start;
- return 0;
-}
-static CONST TclDatetabelem TclDateexca[] ={
--1, 1,
- 0, -1,
- -2, 0,
- };
-# define YYNPROD 56
-# define YYLAST 261
-static CONST TclDatetabelem TclDateact[]={
-
- 24, 40, 23, 36, 54, 81, 41, 28, 53, 26,
- 37, 42, 58, 38, 56, 28, 27, 26, 28, 33,
- 26, 32, 61, 50, 27, 80, 76, 27, 51, 75,
- 74, 73, 30, 72, 71, 70, 69, 52, 49, 48,
- 47, 45, 39, 62, 78, 46, 79, 68, 25, 65,
- 60, 67, 66, 55, 44, 21, 63, 11, 10, 9,
- 8, 35, 7, 6, 5, 4, 3, 43, 2, 1,
- 20, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 57, 0, 0, 59, 77, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 19, 14, 0, 0, 0,
- 16, 28, 22, 26, 0, 12, 13, 17, 0, 15,
- 27, 18, 31, 0, 0, 29, 0, 34, 28, 0,
- 26, 0, 0, 0, 0, 0, 0, 27, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,
- 64 };
-static CONST TclDatetabelem TclDatepact[]={
-
--10000000, -43,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,
--10000000,-10000000, -26, -268,-10000000, -259, -226,-10000000, -257, 10,
- -227, -212, -228,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,-10000000,
- -229,-10000000, -230, -240, -231,-10000000,-10000000, -264,-10000000, 9,
--10000000,-10000000, -249,-10000000,-10000000, -246,-10000000, 4, -2, 2,
- 7, 6,-10000000,-10000000, -11, -232,-10000000,-10000000,-10000000,-10000000,
- -233,-10000000, -234, -235,-10000000, -237, -238, -239, -242,-10000000,
--10000000,-10000000, -1,-10000000,-10000000,-10000000, -12,-10000000, -243, -263,
--10000000,-10000000 };
-static CONST TclDatetabelem TclDatepgo[]={
-
- 0, 48, 70, 22, 69, 68, 66, 65, 64, 63,
- 62, 60, 59, 58, 57, 55 };
-static CONST TclDatetabelem TclDater1[]={
-
- 0, 4, 4, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 6, 6, 6, 6, 6, 7, 7, 7,
- 10, 10, 10, 10, 10, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 9, 9, 12, 12, 12,
- 13, 11, 11, 15, 15, 15, 15, 15, 2, 2,
- 1, 1, 1, 14, 3, 3 };
-static CONST TclDatetabelem TclDater2[]={
-
- 0, 0, 4, 3, 3, 3, 3, 3, 3, 3,
- 3, 2, 5, 9, 11, 13, 15, 5, 3, 3,
- 3, 5, 5, 7, 5, 7, 11, 3, 11, 11,
- 5, 9, 5, 3, 7, 5, 7, 7, 15, 5,
- 9, 5, 2, 7, 5, 5, 7, 3, 3, 3,
- 3, 3, 3, 3, 1, 3 };
-static CONST TclDatetabelem TclDatechk[]={
-
--10000000, -4, -5, -6, -7, -8, -9, -10, -11, -12,
- -13, -14, 268, 269, 259, 272, 263, 270, 274, 258,
- -2, -15, 265, 45, 43, -1, 266, 273, 264, 261,
- 58, 258, 47, 45, 263, -1, 271, 269, 272, 268,
- 258, 263, 268, -1, 44, 268, 257, 268, 268, 268,
- 263, 268, 268, 272, 268, 44, 263, -1, 258, -1,
- 46, -3, 45, 58, 261, 47, 45, 45, 58, 268,
- 268, 268, 268, 268, 268, 268, 268, -3, 45, 58,
- 268, 268 };
-static CONST TclDatetabelem TclDatedef[]={
-
- 1, -2, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 53, 18, 19, 27, 0, 33, 0, 20,
- 0, 42, 0, 48, 49, 47, 50, 51, 52, 12,
- 0, 22, 0, 0, 32, 44, 17, 0, 39, 30,
- 24, 35, 0, 45, 21, 0, 41, 0, 54, 25,
- 0, 0, 34, 37, 0, 0, 36, 46, 23, 43,
- 0, 13, 0, 0, 55, 0, 0, 0, 0, 31,
- 40, 14, 54, 26, 28, 29, 0, 15, 0, 0,
- 16, 38 };
-typedef struct
-#ifdef __cplusplus
- TclDatetoktype
-#endif
-{ char *t_name; int t_val; } TclDatetoktype;
-#ifndef YYDEBUG
-# define YYDEBUG 0 /* don't allow debugging */
-#endif
-
-#if YYDEBUG
-
-TclDatetoktype TclDatetoks[] =
-{
- "tAGO", 257,
- "tDAY", 258,
- "tDAYZONE", 259,
- "tID", 260,
- "tMERIDIAN", 261,
- "tMINUTE_UNIT", 262,
- "tMONTH", 263,
- "tMONTH_UNIT", 264,
- "tSTARDATE", 265,
- "tSEC_UNIT", 266,
- "tSNUMBER", 267,
- "tUNUMBER", 268,
- "tZONE", 269,
- "tEPOCH", 270,
- "tDST", 271,
- "tISOBASE", 272,
- "tDAY_UNIT", 273,
- "tNEXT", 274,
- "-unknown-", -1 /* ends search */
-};
-
-char * TclDatereds[] =
-{
- "-no such reduction-",
- "spec : /* empty */",
- "spec : spec item",
- "item : time",
- "item : zone",
- "item : date",
- "item : ordMonth",
- "item : day",
- "item : relspec",
- "item : iso",
- "item : trek",
- "item : number",
- "time : tUNUMBER tMERIDIAN",
- "time : tUNUMBER ':' tUNUMBER o_merid",
- "time : tUNUMBER ':' tUNUMBER '-' tUNUMBER",
- "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid",
- "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER '-' tUNUMBER",
- "zone : tZONE tDST",
- "zone : tZONE",
- "zone : tDAYZONE",
- "day : tDAY",
- "day : tDAY ','",
- "day : tUNUMBER tDAY",
- "day : sign tUNUMBER tDAY",
- "day : tNEXT tDAY",
- "date : tUNUMBER '/' tUNUMBER",
- "date : tUNUMBER '/' tUNUMBER '/' tUNUMBER",
- "date : tISOBASE",
- "date : tUNUMBER '-' tMONTH '-' tUNUMBER",
- "date : tUNUMBER '-' tUNUMBER '-' tUNUMBER",
- "date : tMONTH tUNUMBER",
- "date : tMONTH tUNUMBER ',' tUNUMBER",
- "date : tUNUMBER tMONTH",
- "date : tEPOCH",
- "date : tUNUMBER tMONTH tUNUMBER",
- "ordMonth : tNEXT tMONTH",
- "ordMonth : tNEXT tUNUMBER tMONTH",
- "iso : tISOBASE tZONE tISOBASE",
- "iso : tISOBASE tZONE tUNUMBER ':' tUNUMBER ':' tUNUMBER",
- "iso : tISOBASE tISOBASE",
- "trek : tSTARDATE tUNUMBER '.' tUNUMBER",
- "relspec : relunits tAGO",
- "relspec : relunits",
- "relunits : sign tUNUMBER unit",
- "relunits : tUNUMBER unit",
- "relunits : tNEXT unit",
- "relunits : tNEXT tUNUMBER unit",
- "relunits : unit",
- "sign : '-'",
- "sign : '+'",
- "unit : tSEC_UNIT",
- "unit : tDAY_UNIT",
- "unit : tMONTH_UNIT",
- "number : tUNUMBER",
- "o_merid : /* empty */",
- "o_merid : tMERIDIAN",
-};
-#endif /* YYDEBUG */
-/*
- * Copyright (c) 1993 by Sun Microsystems, Inc.
- */
-
-
-/*
-** Skeleton parser driver for yacc output
-*/
-
-/*
-** yacc user known macros and defines
-*/
-#define YYERROR goto TclDateerrlab
-#define YYACCEPT return(0)
-#define YYABORT return(1)
-#define YYBACKUP( newtoken, newvalue )\
-{\
- if ( TclDatechar >= 0 || ( TclDater2[ TclDatetmp ] >> 1 ) != 1 )\
- {\
- TclDateerror( "syntax error - cannot backup" );\
- goto TclDateerrlab;\
- }\
- TclDatechar = newtoken;\
- TclDatestate = *TclDateps;\
- TclDatelval = newvalue;\
- goto TclDatenewstate;\
-}
-#define YYRECOVERING() (!!TclDateerrflag)
-#define YYNEW(type) malloc(sizeof(type) * TclDatenewmax)
-#define YYCOPY(to, from, type) \
- (type *) memcpy(to, (char *) from, TclDatemaxdepth * sizeof (type))
-#define YYENLARGE( from, type) \
- (type *) realloc((char *) from, TclDatenewmax * sizeof(type))
-#ifndef YYDEBUG
-# define YYDEBUG 1 /* make debugging available */
-#endif
-
-/*
-** user known globals
-*/
-int TclDatedebug; /* set to 1 to get debugging */
-
-/*
-** driver internal defines
-*/
-#define YYFLAG (-10000000)
-
-/*
-** global variables used by the parser
-*/
-YYSTYPE *TclDatepv; /* top of value stack */
-int *TclDateps; /* top of state stack */
-
-int TclDatestate; /* current state */
-int TclDatetmp; /* extra var (lasts between blocks) */
-int TclDatenerrs; /* number of errors */
-int TclDateerrflag; /* error recovery flag */
-int TclDatechar; /* current input token number */
+ result = Tcl_NewObj();
+ resultElement = Tcl_NewObj();
+ if (yyHaveDate) {
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) yyYear));
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) yyMonth));
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) yyDay));
+ }
+ Tcl_ListObjAppendElement(interp, result, resultElement);
+ if (yyHaveTime) {
+ Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj((int)
+ ToSeconds(yyHour, yyMinutes, yySeconds, yyMeridian)));
+ } else {
+ Tcl_ListObjAppendElement(interp, result, Tcl_NewObj());
+ }
+ resultElement = Tcl_NewObj();
+ if (yyHaveZone) {
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) -yyTimezone));
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj(1 - yyDSTmode));
+ }
+ Tcl_ListObjAppendElement(interp, result, resultElement);
+
+ resultElement = Tcl_NewObj();
+ if (yyHaveRel) {
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) yyRelMonth));
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) yyRelDay));
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) yyRelSeconds));
+ }
+ Tcl_ListObjAppendElement(interp, result, resultElement);
+
+ resultElement = Tcl_NewObj();
+ if (yyHaveDay && !yyHaveDate) {
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) yyDayOrdinal));
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) yyDayNumber));
+ }
+ Tcl_ListObjAppendElement(interp, result, resultElement);
+
+ resultElement = Tcl_NewObj();
+ if (yyHaveOrdinalMonth) {
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) yyMonthOrdinal));
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) yyMonth));
+ }
+ Tcl_ListObjAppendElement(interp, result, resultElement);
-#ifdef YYNMBCHARS
-#define YYLEX() TclDatecvtok(TclDatelex())
-/*
-** TclDatecvtok - return a token if i is a wchar_t value that exceeds 255.
-** If i<255, i itself is the token. If i>255 but the neither
-** of the 30th or 31st bit is on, i is already a token.
-*/
-#if defined(__STDC__) || defined(__cplusplus)
-int TclDatecvtok(int i)
-#else
-int TclDatecvtok(i) int i;
-#endif
-{
- int first = 0;
- int last = YYNMBCHARS - 1;
- int mid;
- wchar_t j;
-
- if(i&0x60000000){/*Must convert to a token. */
- if( TclDatembchars[last].character < i ){
- return i;/*Giving up*/
- }
- while ((last>=first)&&(first>=0)) {/*Binary search loop*/
- mid = (first+last)/2;
- j = TclDatembchars[mid].character;
- if( j==i ){/*Found*/
- return TclDatembchars[mid].tvalue;
- }else if( j<i ){
- first = mid + 1;
- }else{
- last = mid -1;
- }
- }
- /*No entry in the table.*/
- return i;/* Giving up.*/
- }else{/* i is already a token. */
- return i;
- }
+ Tcl_SetObjResult(interp, result);
+ return TCL_OK;
}
-#else/*!YYNMBCHARS*/
-#define YYLEX() TclDatelex()
-#endif/*!YYNMBCHARS*/
-
+
/*
-** TclDateparse - return 0 if worked, 1 if syntax error not recovered from
-*/
-#if defined(__STDC__) || defined(__cplusplus)
-int TclDateparse(void)
-#else
-int TclDateparse()
-#endif
-{
- register YYSTYPE *TclDatepvt = 0; /* top of value stack for $vars */
-
-#if defined(__cplusplus) || defined(lint)
-/*
- hacks to please C++ and lint - goto's inside
- switch should never be executed
-*/
- static int __yaccpar_lint_hack__ = 0;
- switch (__yaccpar_lint_hack__)
- {
- case 1: goto TclDateerrlab;
- case 2: goto TclDatenewstate;
- }
-#endif
-
- /*
- ** Initialize externals - TclDateparse may be called more than once
- */
- TclDatepv = &TclDatev[-1];
- TclDateps = &TclDates[-1];
- TclDatestate = 0;
- TclDatetmp = 0;
- TclDatenerrs = 0;
- TclDateerrflag = 0;
- TclDatechar = -1;
-
-#if YYMAXDEPTH <= 0
- if (TclDatemaxdepth <= 0)
- {
- if ((TclDatemaxdepth = YYEXPAND(0)) <= 0)
- {
- TclDateerror("yacc initialization error");
- YYABORT;
- }
- }
-#endif
-
- {
- register YYSTYPE *TclDate_pv; /* top of value stack */
- register int *TclDate_ps; /* top of state stack */
- register int TclDate_state; /* current state */
- register int TclDate_n; /* internal state number info */
- goto TclDatestack; /* moved from 6 lines above to here to please C++ */
-
- /*
- ** get globals into registers.
- ** branch to here only if YYBACKUP was called.
- */
- TclDate_pv = TclDatepv;
- TclDate_ps = TclDateps;
- TclDate_state = TclDatestate;
- goto TclDate_newstate;
-
- /*
- ** get globals into registers.
- ** either we just started, or we just finished a reduction
- */
- TclDatestack:
- TclDate_pv = TclDatepv;
- TclDate_ps = TclDateps;
- TclDate_state = TclDatestate;
-
- /*
- ** top of for (;;) loop while no reductions done
- */
- TclDate_stack:
- /*
- ** put a state and value onto the stacks
- */
-#if YYDEBUG
- /*
- ** if debugging, look up token value in list of value vs.
- ** name pairs. 0 and negative (-1) are special values.
- ** Note: linear search is used since time is not a real
- ** consideration while debugging.
- */
- if ( TclDatedebug )
- {
- register int TclDate_i;
-
- printf( "State %d, token ", TclDate_state );
- if ( TclDatechar == 0 )
- printf( "end-of-file\n" );
- else if ( TclDatechar < 0 )
- printf( "-none-\n" );
- else
- {
- for ( TclDate_i = 0; TclDatetoks[TclDate_i].t_val >= 0;
- TclDate_i++ )
- {
- if ( TclDatetoks[TclDate_i].t_val == TclDatechar )
- break;
- }
- printf( "%s\n", TclDatetoks[TclDate_i].t_name );
- }
- }
-#endif /* YYDEBUG */
- if ( ++TclDate_ps >= &TclDates[ TclDatemaxdepth ] ) /* room on stack? */
- {
- /*
- ** reallocate and recover. Note that pointers
- ** have to be reset, or bad things will happen
- */
- long TclDateps_index = (TclDate_ps - TclDates);
- long TclDatepv_index = (TclDate_pv - TclDatev);
- long TclDatepvt_index = (TclDatepvt - TclDatev);
- int TclDatenewmax;
-#ifdef YYEXPAND
- TclDatenewmax = YYEXPAND(TclDatemaxdepth);
-#else
- TclDatenewmax = 2 * TclDatemaxdepth; /* double table size */
- if (TclDatemaxdepth == YYMAXDEPTH) /* first time growth */
- {
- char *newTclDates = (char *)YYNEW(int);
- char *newTclDatev = (char *)YYNEW(YYSTYPE);
- if (newTclDates != 0 && newTclDatev != 0)
- {
- TclDates = YYCOPY(newTclDates, TclDates, int);
- TclDatev = YYCOPY(newTclDatev, TclDatev, YYSTYPE);
- }
- else
- TclDatenewmax = 0; /* failed */
- }
- else /* not first time */
- {
- TclDates = YYENLARGE(TclDates, int);
- TclDatev = YYENLARGE(TclDatev, YYSTYPE);
- if (TclDates == 0 || TclDatev == 0)
- TclDatenewmax = 0; /* failed */
- }
-#endif
- if (TclDatenewmax <= TclDatemaxdepth) /* tables not expanded */
- {
- TclDateerror( "yacc stack overflow" );
- YYABORT;
- }
- TclDatemaxdepth = TclDatenewmax;
-
- TclDate_ps = TclDates + TclDateps_index;
- TclDate_pv = TclDatev + TclDatepv_index;
- TclDatepvt = TclDatev + TclDatepvt_index;
- }
- *TclDate_ps = TclDate_state;
- *++TclDate_pv = TclDateval;
-
- /*
- ** we have a new state - find out what to do
- */
- TclDate_newstate:
- if ( ( TclDate_n = TclDatepact[ TclDate_state ] ) <= YYFLAG )
- goto TclDatedefault; /* simple state */
-#if YYDEBUG
- /*
- ** if debugging, need to mark whether new token grabbed
- */
- TclDatetmp = TclDatechar < 0;
-#endif
- if ( ( TclDatechar < 0 ) && ( ( TclDatechar = YYLEX() ) < 0 ) )
- TclDatechar = 0; /* reached EOF */
-#if YYDEBUG
- if ( TclDatedebug && TclDatetmp )
- {
- register int TclDate_i;
-
- printf( "Received token " );
- if ( TclDatechar == 0 )
- printf( "end-of-file\n" );
- else if ( TclDatechar < 0 )
- printf( "-none-\n" );
- else
- {
- for ( TclDate_i = 0; TclDatetoks[TclDate_i].t_val >= 0;
- TclDate_i++ )
- {
- if ( TclDatetoks[TclDate_i].t_val == TclDatechar )
- break;
- }
- printf( "%s\n", TclDatetoks[TclDate_i].t_name );
- }
- }
-#endif /* YYDEBUG */
- if ( ( ( TclDate_n += TclDatechar ) < 0 ) || ( TclDate_n >= YYLAST ) )
- goto TclDatedefault;
- if ( TclDatechk[ TclDate_n = TclDateact[ TclDate_n ] ] == TclDatechar ) /*valid shift*/
- {
- TclDatechar = -1;
- TclDateval = TclDatelval;
- TclDate_state = TclDate_n;
- if ( TclDateerrflag > 0 )
- TclDateerrflag--;
- goto TclDate_stack;
- }
-
- TclDatedefault:
- if ( ( TclDate_n = TclDatedef[ TclDate_state ] ) == -2 )
- {
-#if YYDEBUG
- TclDatetmp = TclDatechar < 0;
-#endif
- if ( ( TclDatechar < 0 ) && ( ( TclDatechar = YYLEX() ) < 0 ) )
- TclDatechar = 0; /* reached EOF */
-#if YYDEBUG
- if ( TclDatedebug && TclDatetmp )
- {
- register int TclDate_i;
-
- printf( "Received token " );
- if ( TclDatechar == 0 )
- printf( "end-of-file\n" );
- else if ( TclDatechar < 0 )
- printf( "-none-\n" );
- else
- {
- for ( TclDate_i = 0;
- TclDatetoks[TclDate_i].t_val >= 0;
- TclDate_i++ )
- {
- if ( TclDatetoks[TclDate_i].t_val
- == TclDatechar )
- {
- break;
- }
- }
- printf( "%s\n", TclDatetoks[TclDate_i].t_name );
- }
- }
-#endif /* YYDEBUG */
- /*
- ** look through exception table
- */
- {
- register CONST int *TclDatexi = TclDateexca;
-
- while ( ( *TclDatexi != -1 ) ||
- ( TclDatexi[1] != TclDate_state ) )
- {
- TclDatexi += 2;
- }
- while ( ( *(TclDatexi += 2) >= 0 ) &&
- ( *TclDatexi != TclDatechar ) )
- ;
- if ( ( TclDate_n = TclDatexi[1] ) < 0 )
- YYACCEPT;
- }
- }
-
- /*
- ** check for syntax error
- */
- if ( TclDate_n == 0 ) /* have an error */
- {
- /* no worry about speed here! */
- switch ( TclDateerrflag )
- {
- case 0: /* new error */
- TclDateerror( "syntax error" );
- goto skip_init;
- /*
- ** get globals into registers.
- ** we have a user generated syntax type error
- */
- TclDate_pv = TclDatepv;
- TclDate_ps = TclDateps;
- TclDate_state = TclDatestate;
- skip_init:
- TclDatenerrs++;
- /* FALLTHRU */
- case 1:
- case 2: /* incompletely recovered error */
- /* try again... */
- TclDateerrflag = 3;
- /*
- ** find state where "error" is a legal
- ** shift action
- */
- while ( TclDate_ps >= TclDates )
- {
- TclDate_n = TclDatepact[ *TclDate_ps ] + YYERRCODE;
- if ( TclDate_n >= 0 && TclDate_n < YYLAST &&
- TclDatechk[TclDateact[TclDate_n]] == YYERRCODE) {
- /*
- ** simulate shift of "error"
- */
- TclDate_state = TclDateact[ TclDate_n ];
- goto TclDate_stack;
- }
- /*
- ** current state has no shift on
- ** "error", pop stack
- */
-#if YYDEBUG
-# define _POP_ "Error recovery pops state %d, uncovers state %d\n"
- if ( TclDatedebug )
- printf( _POP_, *TclDate_ps,
- TclDate_ps[-1] );
-# undef _POP_
-#endif
- TclDate_ps--;
- TclDate_pv--;
- }
- /*
- ** there is no state on stack with "error" as
- ** a valid shift. give up.
- */
- YYABORT;
- case 3: /* no shift yet; eat a token */
-#if YYDEBUG
- /*
- ** if debugging, look up token in list of
- ** pairs. 0 and negative shouldn't occur,
- ** but since timing doesn't matter when
- ** debugging, it doesn't hurt to leave the
- ** tests here.
- */
- if ( TclDatedebug )
- {
- register int TclDate_i;
-
- printf( "Error recovery discards " );
- if ( TclDatechar == 0 )
- printf( "token end-of-file\n" );
- else if ( TclDatechar < 0 )
- printf( "token -none-\n" );
- else
- {
- for ( TclDate_i = 0;
- TclDatetoks[TclDate_i].t_val >= 0;
- TclDate_i++ )
- {
- if ( TclDatetoks[TclDate_i].t_val
- == TclDatechar )
- {
- break;
- }
- }
- printf( "token %s\n",
- TclDatetoks[TclDate_i].t_name );
- }
- }
-#endif /* YYDEBUG */
- if ( TclDatechar == 0 ) /* reached EOF. quit */
- YYABORT;
- TclDatechar = -1;
- goto TclDate_newstate;
- }
- }/* end if ( TclDate_n == 0 ) */
- /*
- ** reduction by production TclDate_n
- ** put stack tops, etc. so things right after switch
- */
-#if YYDEBUG
- /*
- ** if debugging, print the string that is the user's
- ** specification of the reduction which is just about
- ** to be done.
- */
- if ( TclDatedebug )
- printf( "Reduce by (%d) \"%s\"\n",
- TclDate_n, TclDatereds[ TclDate_n ] );
-#endif
- TclDatetmp = TclDate_n; /* value to switch over */
- TclDatepvt = TclDate_pv; /* $vars top of value stack */
- /*
- ** Look in goto table for next state
- ** Sorry about using TclDate_state here as temporary
- ** register variable, but why not, if it works...
- ** If TclDater2[ TclDate_n ] doesn't have the low order bit
- ** set, then there is no action to be done for
- ** this reduction. So, no saving & unsaving of
- ** registers done. The only difference between the
- ** code just after the if and the body of the if is
- ** the goto TclDate_stack in the body. This way the test
- ** can be made before the choice of what to do is needed.
- */
- {
- /* length of production doubled with extra bit */
- register int TclDate_len = TclDater2[ TclDate_n ];
-
- if ( !( TclDate_len & 01 ) )
- {
- TclDate_len >>= 1;
- TclDateval = ( TclDate_pv -= TclDate_len )[1]; /* $$ = $1 */
- TclDate_state = TclDatepgo[ TclDate_n = TclDater1[ TclDate_n ] ] +
- *( TclDate_ps -= TclDate_len ) + 1;
- if ( TclDate_state >= YYLAST ||
- TclDatechk[ TclDate_state =
- TclDateact[ TclDate_state ] ] != -TclDate_n )
- {
- TclDate_state = TclDateact[ TclDatepgo[ TclDate_n ] ];
- }
- goto TclDate_stack;
- }
- TclDate_len >>= 1;
- TclDateval = ( TclDate_pv -= TclDate_len )[1]; /* $$ = $1 */
- TclDate_state = TclDatepgo[ TclDate_n = TclDater1[ TclDate_n ] ] +
- *( TclDate_ps -= TclDate_len ) + 1;
- if ( TclDate_state >= YYLAST ||
- TclDatechk[ TclDate_state = TclDateact[ TclDate_state ] ] != -TclDate_n )
- {
- TclDate_state = TclDateact[ TclDatepgo[ TclDate_n ] ];
- }
- }
- /* save until reenter driver code */
- TclDatestate = TclDate_state;
- TclDateps = TclDate_ps;
- TclDatepv = TclDate_pv;
- }
- /*
- ** code supplied by user is placed in this switch
- */
- switch( TclDatetmp )
- {
-
-case 3:{
- TclDateHaveTime++;
- } break;
-case 4:{
- TclDateHaveZone++;
- } break;
-case 5:{
- TclDateHaveDate++;
- } break;
-case 6:{
- TclDateHaveOrdinalMonth++;
- } break;
-case 7:{
- TclDateHaveDay++;
- } break;
-case 8:{
- TclDateHaveRel++;
- } break;
-case 9:{
- TclDateHaveTime++;
- TclDateHaveDate++;
- } break;
-case 10:{
- TclDateHaveTime++;
- TclDateHaveDate++;
- TclDateHaveRel++;
- } break;
-case 12:{
- TclDateHour = TclDatepvt[-1].Number;
- TclDateMinutes = 0;
- TclDateSeconds = 0;
- TclDateMeridian = TclDatepvt[-0].Meridian;
- } break;
-case 13:{
- TclDateHour = TclDatepvt[-3].Number;
- TclDateMinutes = TclDatepvt[-1].Number;
- TclDateSeconds = 0;
- TclDateMeridian = TclDatepvt[-0].Meridian;
- } break;
-case 14:{
- TclDateHour = TclDatepvt[-4].Number;
- TclDateMinutes = TclDatepvt[-2].Number;
- TclDateMeridian = MER24;
- TclDateDSTmode = DSToff;
- TclDateTimezone = (TclDatepvt[-0].Number % 100 + (TclDatepvt[-0].Number / 100) * 60);
- } break;
-case 15:{
- TclDateHour = TclDatepvt[-5].Number;
- TclDateMinutes = TclDatepvt[-3].Number;
- TclDateSeconds = TclDatepvt[-1].Number;
- TclDateMeridian = TclDatepvt[-0].Meridian;
- } break;
-case 16:{
- TclDateHour = TclDatepvt[-6].Number;
- TclDateMinutes = TclDatepvt[-4].Number;
- TclDateSeconds = TclDatepvt[-2].Number;
- TclDateMeridian = MER24;
- TclDateDSTmode = DSToff;
- TclDateTimezone = (TclDatepvt[-0].Number % 100 + (TclDatepvt[-0].Number / 100) * 60);
- } break;
-case 17:{
- TclDateTimezone = TclDatepvt[-1].Number;
- TclDateDSTmode = DSTon;
- } break;
-case 18:{
- TclDateTimezone = TclDatepvt[-0].Number;
- TclDateDSTmode = DSToff;
- } break;
-case 19:{
- TclDateTimezone = TclDatepvt[-0].Number;
- TclDateDSTmode = DSTon;
- } break;
-case 20:{
- TclDateDayOrdinal = 1;
- TclDateDayNumber = TclDatepvt[-0].Number;
- } break;
-case 21:{
- TclDateDayOrdinal = 1;
- TclDateDayNumber = TclDatepvt[-1].Number;
- } break;
-case 22:{
- TclDateDayOrdinal = TclDatepvt[-1].Number;
- TclDateDayNumber = TclDatepvt[-0].Number;
- } break;
-case 23:{
- TclDateDayOrdinal = TclDatepvt[-2].Number * TclDatepvt[-1].Number;
- TclDateDayNumber = TclDatepvt[-0].Number;
- } break;
-case 24:{
- TclDateDayOrdinal = 2;
- TclDateDayNumber = TclDatepvt[-0].Number;
- } break;
-case 25:{
- TclDateMonth = TclDatepvt[-2].Number;
- TclDateDay = TclDatepvt[-0].Number;
- } break;
-case 26:{
- TclDateMonth = TclDatepvt[-4].Number;
- TclDateDay = TclDatepvt[-2].Number;
- TclDateYear = TclDatepvt[-0].Number;
- } break;
-case 27:{
- TclDateYear = TclDatepvt[-0].Number / 10000;
- TclDateMonth = (TclDatepvt[-0].Number % 10000)/100;
- TclDateDay = TclDatepvt[-0].Number % 100;
- } break;
-case 28:{
- TclDateDay = TclDatepvt[-4].Number;
- TclDateMonth = TclDatepvt[-2].Number;
- TclDateYear = TclDatepvt[-0].Number;
- } break;
-case 29:{
- TclDateMonth = TclDatepvt[-2].Number;
- TclDateDay = TclDatepvt[-0].Number;
- TclDateYear = TclDatepvt[-4].Number;
- } break;
-case 30:{
- TclDateMonth = TclDatepvt[-1].Number;
- TclDateDay = TclDatepvt[-0].Number;
- } break;
-case 31:{
- TclDateMonth = TclDatepvt[-3].Number;
- TclDateDay = TclDatepvt[-2].Number;
- TclDateYear = TclDatepvt[-0].Number;
- } break;
-case 32:{
- TclDateMonth = TclDatepvt[-0].Number;
- TclDateDay = TclDatepvt[-1].Number;
- } break;
-case 33:{
- TclDateMonth = 1;
- TclDateDay = 1;
- TclDateYear = EPOCH;
- } break;
-case 34:{
- TclDateMonth = TclDatepvt[-1].Number;
- TclDateDay = TclDatepvt[-2].Number;
- TclDateYear = TclDatepvt[-0].Number;
- } break;
-case 35:{
- TclDateMonthOrdinal = 1;
- TclDateMonth = TclDatepvt[-0].Number;
- } break;
-case 36:{
- TclDateMonthOrdinal = TclDatepvt[-1].Number;
- TclDateMonth = TclDatepvt[-0].Number;
- } break;
-case 37:{
- if (TclDatepvt[-1].Number != HOUR(- 7)) YYABORT;
- TclDateYear = TclDatepvt[-2].Number / 10000;
- TclDateMonth = (TclDatepvt[-2].Number % 10000)/100;
- TclDateDay = TclDatepvt[-2].Number % 100;
- TclDateHour = TclDatepvt[-0].Number / 10000;
- TclDateMinutes = (TclDatepvt[-0].Number % 10000)/100;
- TclDateSeconds = TclDatepvt[-0].Number % 100;
- } break;
-case 38:{
- if (TclDatepvt[-5].Number != HOUR(- 7)) YYABORT;
- TclDateYear = TclDatepvt[-6].Number / 10000;
- TclDateMonth = (TclDatepvt[-6].Number % 10000)/100;
- TclDateDay = TclDatepvt[-6].Number % 100;
- TclDateHour = TclDatepvt[-4].Number;
- TclDateMinutes = TclDatepvt[-2].Number;
- TclDateSeconds = TclDatepvt[-0].Number;
- } break;
-case 39:{
- TclDateYear = TclDatepvt[-1].Number / 10000;
- TclDateMonth = (TclDatepvt[-1].Number % 10000)/100;
- TclDateDay = TclDatepvt[-1].Number % 100;
- TclDateHour = TclDatepvt[-0].Number / 10000;
- TclDateMinutes = (TclDatepvt[-0].Number % 10000)/100;
- TclDateSeconds = TclDatepvt[-0].Number % 100;
- } break;
-case 40:{
- /*
- * Offset computed year by -377 so that the returned years will
- * be in a range accessible with a 32 bit clock seconds value
- */
- TclDateYear = TclDatepvt[-2].Number/1000 + 2323 - 377;
- TclDateDay = 1;
- TclDateMonth = 1;
- TclDateRelDay += ((TclDatepvt[-2].Number%1000)*(365 + IsLeapYear(TclDateYear)))/1000;
- TclDateRelSeconds += TclDatepvt[-0].Number * 144 * 60;
- } break;
-case 41:{
- TclDateRelSeconds *= -1;
- TclDateRelMonth *= -1;
- TclDateRelDay *= -1;
- } break;
-case 43:{ *TclDateRelPointer += TclDatepvt[-2].Number * TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break;
-case 44:{ *TclDateRelPointer += TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break;
-case 45:{ *TclDateRelPointer += TclDatepvt[-0].Number; } break;
-case 46:{ *TclDateRelPointer += TclDatepvt[-1].Number * TclDatepvt[-0].Number; } break;
-case 47:{ *TclDateRelPointer += TclDatepvt[-0].Number; } break;
-case 48:{ TclDateval.Number = -1; } break;
-case 49:{ TclDateval.Number = 1; } break;
-case 50:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelSeconds; } break;
-case 51:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelDay; } break;
-case 52:{ TclDateval.Number = TclDatepvt[-0].Number; TclDateRelPointer = &TclDateRelMonth; } break;
-case 53:{
- if (TclDateHaveTime && TclDateHaveDate && !TclDateHaveRel) {
- TclDateYear = TclDatepvt[-0].Number;
- } else {
- TclDateHaveTime++;
- if (TclDatepvt[-0].Number < 100) {
- TclDateHour = TclDatepvt[-0].Number;
- TclDateMinutes = 0;
- } else {
- TclDateHour = TclDatepvt[-0].Number / 100;
- TclDateMinutes = TclDatepvt[-0].Number % 100;
- }
- TclDateSeconds = 0;
- TclDateMeridian = MER24;
- }
- } break;
-case 54:{
- TclDateval.Meridian = MER24;
- } break;
-case 55:{
- TclDateval.Meridian = TclDatepvt[-0].Meridian;
- } break;
- }
- goto TclDatestack; /* reset registers in driver code */
-}
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclDecls.h b/generic/tclDecls.h
index 6f59b81..4517d01 100644
--- a/generic/tclDecls.h
+++ b/generic/tclDecls.h
@@ -12,6 +12,17 @@
#ifndef _TCLDECLS
#define _TCLDECLS
+#undef TCL_STORAGE_CLASS
+#ifdef BUILD_tcl
+# define TCL_STORAGE_CLASS DLLEXPORT
+#else
+# ifdef USE_TCL_STUBS
+# define TCL_STORAGE_CLASS
+# else
+# define TCL_STORAGE_CLASS DLLIMPORT
+# endif
+#endif
+
/*
* WARNING: This file is automatically generated by the tools/genStubs.tcl
* script. Any modifications to the function declarations below should be made
@@ -24,1630 +35,3379 @@
* Exported function declarations:
*/
+#ifndef Tcl_PkgProvideEx_TCL_DECLARED
+#define Tcl_PkgProvideEx_TCL_DECLARED
/* 0 */
-EXTERN int Tcl_PkgProvideEx _ANSI_ARGS_((Tcl_Interp* interp,
- CONST char* name, CONST char* version,
- ClientData clientData));
+EXTERN int Tcl_PkgProvideEx(Tcl_Interp *interp,
+ CONST char *name, CONST char *version,
+ ClientData clientData);
+#endif
+#ifndef Tcl_PkgRequireEx_TCL_DECLARED
+#define Tcl_PkgRequireEx_TCL_DECLARED
/* 1 */
-EXTERN CONST84_RETURN char * Tcl_PkgRequireEx _ANSI_ARGS_((
- Tcl_Interp * interp, CONST char * name,
- CONST char * version, int exact,
- ClientData * clientDataPtr));
+EXTERN CONST84_RETURN char * Tcl_PkgRequireEx(Tcl_Interp *interp,
+ CONST char *name, CONST char *version,
+ int exact, ClientData *clientDataPtr);
+#endif
+#ifndef Tcl_Panic_TCL_DECLARED
+#define Tcl_Panic_TCL_DECLARED
/* 2 */
-EXTERN void Tcl_Panic _ANSI_ARGS_(TCL_VARARGS(CONST char *,format));
+EXTERN void Tcl_Panic(CONST char *format, ...);
+#endif
+#ifndef Tcl_Alloc_TCL_DECLARED
+#define Tcl_Alloc_TCL_DECLARED
/* 3 */
-EXTERN char * Tcl_Alloc _ANSI_ARGS_((unsigned int size));
+EXTERN char * Tcl_Alloc(unsigned int size);
+#endif
+#ifndef Tcl_Free_TCL_DECLARED
+#define Tcl_Free_TCL_DECLARED
/* 4 */
-EXTERN void Tcl_Free _ANSI_ARGS_((char * ptr));
+EXTERN void Tcl_Free(char *ptr);
+#endif
+#ifndef Tcl_Realloc_TCL_DECLARED
+#define Tcl_Realloc_TCL_DECLARED
/* 5 */
-EXTERN char * Tcl_Realloc _ANSI_ARGS_((char * ptr,
- unsigned int size));
+EXTERN char * Tcl_Realloc(char *ptr, unsigned int size);
+#endif
+#ifndef Tcl_DbCkalloc_TCL_DECLARED
+#define Tcl_DbCkalloc_TCL_DECLARED
/* 6 */
-EXTERN char * Tcl_DbCkalloc _ANSI_ARGS_((unsigned int size,
- CONST char * file, int line));
+EXTERN char * Tcl_DbCkalloc(unsigned int size, CONST char *file,
+ int line);
+#endif
+#ifndef Tcl_DbCkfree_TCL_DECLARED
+#define Tcl_DbCkfree_TCL_DECLARED
/* 7 */
-EXTERN int Tcl_DbCkfree _ANSI_ARGS_((char * ptr,
- CONST char * file, int line));
+EXTERN int Tcl_DbCkfree(char *ptr, CONST char *file, int line);
+#endif
+#ifndef Tcl_DbCkrealloc_TCL_DECLARED
+#define Tcl_DbCkrealloc_TCL_DECLARED
/* 8 */
-EXTERN char * Tcl_DbCkrealloc _ANSI_ARGS_((char * ptr,
- unsigned int size, CONST char * file,
- int line));
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+EXTERN char * Tcl_DbCkrealloc(char *ptr, unsigned int size,
+ CONST char *file, int line);
+#endif
+#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
+#ifndef Tcl_CreateFileHandler_TCL_DECLARED
+#define Tcl_CreateFileHandler_TCL_DECLARED
/* 9 */
-EXTERN void Tcl_CreateFileHandler _ANSI_ARGS_((int fd, int mask,
- Tcl_FileProc * proc, ClientData clientData));
+EXTERN void Tcl_CreateFileHandler(int fd, int mask,
+ Tcl_FileProc *proc, ClientData clientData);
+#endif
#endif /* UNIX */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+#ifdef MAC_OSX_TCL /* MACOSX */
+#ifndef Tcl_CreateFileHandler_TCL_DECLARED
+#define Tcl_CreateFileHandler_TCL_DECLARED
+/* 9 */
+EXTERN void Tcl_CreateFileHandler(int fd, int mask,
+ Tcl_FileProc *proc, ClientData clientData);
+#endif
+#endif /* MACOSX */
+#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
+#ifndef Tcl_DeleteFileHandler_TCL_DECLARED
+#define Tcl_DeleteFileHandler_TCL_DECLARED
/* 10 */
-EXTERN void Tcl_DeleteFileHandler _ANSI_ARGS_((int fd));
+EXTERN void Tcl_DeleteFileHandler(int fd);
+#endif
#endif /* UNIX */
+#ifdef MAC_OSX_TCL /* MACOSX */
+#ifndef Tcl_DeleteFileHandler_TCL_DECLARED
+#define Tcl_DeleteFileHandler_TCL_DECLARED
+/* 10 */
+EXTERN void Tcl_DeleteFileHandler(int fd);
+#endif
+#endif /* MACOSX */
+#ifndef Tcl_SetTimer_TCL_DECLARED
+#define Tcl_SetTimer_TCL_DECLARED
/* 11 */
-EXTERN void Tcl_SetTimer _ANSI_ARGS_((Tcl_Time * timePtr));
+EXTERN void Tcl_SetTimer(Tcl_Time *timePtr);
+#endif
+#ifndef Tcl_Sleep_TCL_DECLARED
+#define Tcl_Sleep_TCL_DECLARED
/* 12 */
-EXTERN void Tcl_Sleep _ANSI_ARGS_((int ms));
+EXTERN void Tcl_Sleep(int ms);
+#endif
+#ifndef Tcl_WaitForEvent_TCL_DECLARED
+#define Tcl_WaitForEvent_TCL_DECLARED
/* 13 */
-EXTERN int Tcl_WaitForEvent _ANSI_ARGS_((Tcl_Time * timePtr));
+EXTERN int Tcl_WaitForEvent(Tcl_Time *timePtr);
+#endif
+#ifndef Tcl_AppendAllObjTypes_TCL_DECLARED
+#define Tcl_AppendAllObjTypes_TCL_DECLARED
/* 14 */
-EXTERN int Tcl_AppendAllObjTypes _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Obj * objPtr));
+EXTERN int Tcl_AppendAllObjTypes(Tcl_Interp *interp,
+ Tcl_Obj *objPtr);
+#endif
+#ifndef Tcl_AppendStringsToObj_TCL_DECLARED
+#define Tcl_AppendStringsToObj_TCL_DECLARED
/* 15 */
-EXTERN void Tcl_AppendStringsToObj _ANSI_ARGS_(TCL_VARARGS(Tcl_Obj *,objPtr));
+EXTERN void Tcl_AppendStringsToObj(Tcl_Obj *objPtr, ...);
+#endif
+#ifndef Tcl_AppendToObj_TCL_DECLARED
+#define Tcl_AppendToObj_TCL_DECLARED
/* 16 */
-EXTERN void Tcl_AppendToObj _ANSI_ARGS_((Tcl_Obj* objPtr,
- CONST char* bytes, int length));
+EXTERN void Tcl_AppendToObj(Tcl_Obj *objPtr, CONST char *bytes,
+ int length);
+#endif
+#ifndef Tcl_ConcatObj_TCL_DECLARED
+#define Tcl_ConcatObj_TCL_DECLARED
/* 17 */
-EXTERN Tcl_Obj * Tcl_ConcatObj _ANSI_ARGS_((int objc,
- Tcl_Obj *CONST objv[]));
+EXTERN Tcl_Obj * Tcl_ConcatObj(int objc, Tcl_Obj *CONST objv[]);
+#endif
+#ifndef Tcl_ConvertToType_TCL_DECLARED
+#define Tcl_ConvertToType_TCL_DECLARED
/* 18 */
-EXTERN int Tcl_ConvertToType _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * objPtr, Tcl_ObjType * typePtr));
+EXTERN int Tcl_ConvertToType(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, Tcl_ObjType *typePtr);
+#endif
+#ifndef Tcl_DbDecrRefCount_TCL_DECLARED
+#define Tcl_DbDecrRefCount_TCL_DECLARED
/* 19 */
-EXTERN void Tcl_DbDecrRefCount _ANSI_ARGS_((Tcl_Obj * objPtr,
- CONST char * file, int line));
+EXTERN void Tcl_DbDecrRefCount(Tcl_Obj *objPtr, CONST char *file,
+ int line);
+#endif
+#ifndef Tcl_DbIncrRefCount_TCL_DECLARED
+#define Tcl_DbIncrRefCount_TCL_DECLARED
/* 20 */
-EXTERN void Tcl_DbIncrRefCount _ANSI_ARGS_((Tcl_Obj * objPtr,
- CONST char * file, int line));
+EXTERN void Tcl_DbIncrRefCount(Tcl_Obj *objPtr, CONST char *file,
+ int line);
+#endif
+#ifndef Tcl_DbIsShared_TCL_DECLARED
+#define Tcl_DbIsShared_TCL_DECLARED
/* 21 */
-EXTERN int Tcl_DbIsShared _ANSI_ARGS_((Tcl_Obj * objPtr,
- CONST char * file, int line));
+EXTERN int Tcl_DbIsShared(Tcl_Obj *objPtr, CONST char *file,
+ int line);
+#endif
+#ifndef Tcl_DbNewBooleanObj_TCL_DECLARED
+#define Tcl_DbNewBooleanObj_TCL_DECLARED
/* 22 */
-EXTERN Tcl_Obj * Tcl_DbNewBooleanObj _ANSI_ARGS_((int boolValue,
- CONST char * file, int line));
+EXTERN Tcl_Obj * Tcl_DbNewBooleanObj(int boolValue, CONST char *file,
+ int line);
+#endif
+#ifndef Tcl_DbNewByteArrayObj_TCL_DECLARED
+#define Tcl_DbNewByteArrayObj_TCL_DECLARED
/* 23 */
-EXTERN Tcl_Obj * Tcl_DbNewByteArrayObj _ANSI_ARGS_((
- CONST unsigned char * bytes, int length,
- CONST char * file, int line));
+EXTERN Tcl_Obj * Tcl_DbNewByteArrayObj(CONST unsigned char *bytes,
+ int length, CONST char *file, int line);
+#endif
+#ifndef Tcl_DbNewDoubleObj_TCL_DECLARED
+#define Tcl_DbNewDoubleObj_TCL_DECLARED
/* 24 */
-EXTERN Tcl_Obj * Tcl_DbNewDoubleObj _ANSI_ARGS_((double doubleValue,
- CONST char * file, int line));
+EXTERN Tcl_Obj * Tcl_DbNewDoubleObj(double doubleValue,
+ CONST char *file, int line);
+#endif
+#ifndef Tcl_DbNewListObj_TCL_DECLARED
+#define Tcl_DbNewListObj_TCL_DECLARED
/* 25 */
-EXTERN Tcl_Obj * Tcl_DbNewListObj _ANSI_ARGS_((int objc,
- Tcl_Obj *CONST * objv, CONST char * file,
- int line));
+EXTERN Tcl_Obj * Tcl_DbNewListObj(int objc, Tcl_Obj *CONST *objv,
+ CONST char *file, int line);
+#endif
+#ifndef Tcl_DbNewLongObj_TCL_DECLARED
+#define Tcl_DbNewLongObj_TCL_DECLARED
/* 26 */
-EXTERN Tcl_Obj * Tcl_DbNewLongObj _ANSI_ARGS_((long longValue,
- CONST char * file, int line));
+EXTERN Tcl_Obj * Tcl_DbNewLongObj(long longValue, CONST char *file,
+ int line);
+#endif
+#ifndef Tcl_DbNewObj_TCL_DECLARED
+#define Tcl_DbNewObj_TCL_DECLARED
/* 27 */
-EXTERN Tcl_Obj * Tcl_DbNewObj _ANSI_ARGS_((CONST char * file,
- int line));
+EXTERN Tcl_Obj * Tcl_DbNewObj(CONST char *file, int line);
+#endif
+#ifndef Tcl_DbNewStringObj_TCL_DECLARED
+#define Tcl_DbNewStringObj_TCL_DECLARED
/* 28 */
-EXTERN Tcl_Obj * Tcl_DbNewStringObj _ANSI_ARGS_((CONST char * bytes,
- int length, CONST char * file, int line));
+EXTERN Tcl_Obj * Tcl_DbNewStringObj(CONST char *bytes, int length,
+ CONST char *file, int line);
+#endif
+#ifndef Tcl_DuplicateObj_TCL_DECLARED
+#define Tcl_DuplicateObj_TCL_DECLARED
/* 29 */
-EXTERN Tcl_Obj * Tcl_DuplicateObj _ANSI_ARGS_((Tcl_Obj * objPtr));
+EXTERN Tcl_Obj * Tcl_DuplicateObj(Tcl_Obj *objPtr);
+#endif
+#ifndef TclFreeObj_TCL_DECLARED
+#define TclFreeObj_TCL_DECLARED
/* 30 */
-EXTERN void TclFreeObj _ANSI_ARGS_((Tcl_Obj * objPtr));
+EXTERN void TclFreeObj(Tcl_Obj *objPtr);
+#endif
+#ifndef Tcl_GetBoolean_TCL_DECLARED
+#define Tcl_GetBoolean_TCL_DECLARED
/* 31 */
-EXTERN int Tcl_GetBoolean _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * str, int * boolPtr));
+EXTERN int Tcl_GetBoolean(Tcl_Interp *interp, CONST char *src,
+ int *boolPtr);
+#endif
+#ifndef Tcl_GetBooleanFromObj_TCL_DECLARED
+#define Tcl_GetBooleanFromObj_TCL_DECLARED
/* 32 */
-EXTERN int Tcl_GetBooleanFromObj _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Obj * objPtr,
- int * boolPtr));
+EXTERN int Tcl_GetBooleanFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, int *boolPtr);
+#endif
+#ifndef Tcl_GetByteArrayFromObj_TCL_DECLARED
+#define Tcl_GetByteArrayFromObj_TCL_DECLARED
/* 33 */
-EXTERN unsigned char * Tcl_GetByteArrayFromObj _ANSI_ARGS_((
- Tcl_Obj * objPtr, int * lengthPtr));
+EXTERN unsigned char * Tcl_GetByteArrayFromObj(Tcl_Obj *objPtr,
+ int *lengthPtr);
+#endif
+#ifndef Tcl_GetDouble_TCL_DECLARED
+#define Tcl_GetDouble_TCL_DECLARED
/* 34 */
-EXTERN int Tcl_GetDouble _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * str, double * doublePtr));
+EXTERN int Tcl_GetDouble(Tcl_Interp *interp, CONST char *src,
+ double *doublePtr);
+#endif
+#ifndef Tcl_GetDoubleFromObj_TCL_DECLARED
+#define Tcl_GetDoubleFromObj_TCL_DECLARED
/* 35 */
-EXTERN int Tcl_GetDoubleFromObj _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Obj * objPtr,
- double * doublePtr));
+EXTERN int Tcl_GetDoubleFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, double *doublePtr);
+#endif
+#ifndef Tcl_GetIndexFromObj_TCL_DECLARED
+#define Tcl_GetIndexFromObj_TCL_DECLARED
/* 36 */
-EXTERN int Tcl_GetIndexFromObj _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * objPtr, CONST84 char ** tablePtr,
- CONST char * msg, int flags, int * indexPtr));
+EXTERN int Tcl_GetIndexFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, CONST84 char **tablePtr,
+ CONST char *msg, int flags, int *indexPtr);
+#endif
+#ifndef Tcl_GetInt_TCL_DECLARED
+#define Tcl_GetInt_TCL_DECLARED
/* 37 */
-EXTERN int Tcl_GetInt _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * str, int * intPtr));
+EXTERN int Tcl_GetInt(Tcl_Interp *interp, CONST char *src,
+ int *intPtr);
+#endif
+#ifndef Tcl_GetIntFromObj_TCL_DECLARED
+#define Tcl_GetIntFromObj_TCL_DECLARED
/* 38 */
-EXTERN int Tcl_GetIntFromObj _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * objPtr, int * intPtr));
+EXTERN int Tcl_GetIntFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, int *intPtr);
+#endif
+#ifndef Tcl_GetLongFromObj_TCL_DECLARED
+#define Tcl_GetLongFromObj_TCL_DECLARED
/* 39 */
-EXTERN int Tcl_GetLongFromObj _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * objPtr, long * longPtr));
+EXTERN int Tcl_GetLongFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, long *longPtr);
+#endif
+#ifndef Tcl_GetObjType_TCL_DECLARED
+#define Tcl_GetObjType_TCL_DECLARED
/* 40 */
-EXTERN Tcl_ObjType * Tcl_GetObjType _ANSI_ARGS_((CONST char * typeName));
+EXTERN Tcl_ObjType * Tcl_GetObjType(CONST char *typeName);
+#endif
+#ifndef Tcl_GetStringFromObj_TCL_DECLARED
+#define Tcl_GetStringFromObj_TCL_DECLARED
/* 41 */
-EXTERN char * Tcl_GetStringFromObj _ANSI_ARGS_((Tcl_Obj * objPtr,
- int * lengthPtr));
+EXTERN char * Tcl_GetStringFromObj(Tcl_Obj *objPtr, int *lengthPtr);
+#endif
+#ifndef Tcl_InvalidateStringRep_TCL_DECLARED
+#define Tcl_InvalidateStringRep_TCL_DECLARED
/* 42 */
-EXTERN void Tcl_InvalidateStringRep _ANSI_ARGS_((
- Tcl_Obj * objPtr));
+EXTERN void Tcl_InvalidateStringRep(Tcl_Obj *objPtr);
+#endif
+#ifndef Tcl_ListObjAppendList_TCL_DECLARED
+#define Tcl_ListObjAppendList_TCL_DECLARED
/* 43 */
-EXTERN int Tcl_ListObjAppendList _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Obj * listPtr,
- Tcl_Obj * elemListPtr));
+EXTERN int Tcl_ListObjAppendList(Tcl_Interp *interp,
+ Tcl_Obj *listPtr, Tcl_Obj *elemListPtr);
+#endif
+#ifndef Tcl_ListObjAppendElement_TCL_DECLARED
+#define Tcl_ListObjAppendElement_TCL_DECLARED
/* 44 */
-EXTERN int Tcl_ListObjAppendElement _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Obj * listPtr,
- Tcl_Obj * objPtr));
+EXTERN int Tcl_ListObjAppendElement(Tcl_Interp *interp,
+ Tcl_Obj *listPtr, Tcl_Obj *objPtr);
+#endif
+#ifndef Tcl_ListObjGetElements_TCL_DECLARED
+#define Tcl_ListObjGetElements_TCL_DECLARED
/* 45 */
-EXTERN int Tcl_ListObjGetElements _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Obj * listPtr,
- int * objcPtr, Tcl_Obj *** objvPtr));
+EXTERN int Tcl_ListObjGetElements(Tcl_Interp *interp,
+ Tcl_Obj *listPtr, int *objcPtr,
+ Tcl_Obj ***objvPtr);
+#endif
+#ifndef Tcl_ListObjIndex_TCL_DECLARED
+#define Tcl_ListObjIndex_TCL_DECLARED
/* 46 */
-EXTERN int Tcl_ListObjIndex _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * listPtr, int index,
- Tcl_Obj ** objPtrPtr));
+EXTERN int Tcl_ListObjIndex(Tcl_Interp *interp,
+ Tcl_Obj *listPtr, int index,
+ Tcl_Obj **objPtrPtr);
+#endif
+#ifndef Tcl_ListObjLength_TCL_DECLARED
+#define Tcl_ListObjLength_TCL_DECLARED
/* 47 */
-EXTERN int Tcl_ListObjLength _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * listPtr, int * lengthPtr));
+EXTERN int Tcl_ListObjLength(Tcl_Interp *interp,
+ Tcl_Obj *listPtr, int *lengthPtr);
+#endif
+#ifndef Tcl_ListObjReplace_TCL_DECLARED
+#define Tcl_ListObjReplace_TCL_DECLARED
/* 48 */
-EXTERN int Tcl_ListObjReplace _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * listPtr, int first, int count,
- int objc, Tcl_Obj *CONST objv[]));
+EXTERN int Tcl_ListObjReplace(Tcl_Interp *interp,
+ Tcl_Obj *listPtr, int first, int count,
+ int objc, Tcl_Obj *CONST objv[]);
+#endif
+#ifndef Tcl_NewBooleanObj_TCL_DECLARED
+#define Tcl_NewBooleanObj_TCL_DECLARED
/* 49 */
-EXTERN Tcl_Obj * Tcl_NewBooleanObj _ANSI_ARGS_((int boolValue));
+EXTERN Tcl_Obj * Tcl_NewBooleanObj(int boolValue);
+#endif
+#ifndef Tcl_NewByteArrayObj_TCL_DECLARED
+#define Tcl_NewByteArrayObj_TCL_DECLARED
/* 50 */
-EXTERN Tcl_Obj * Tcl_NewByteArrayObj _ANSI_ARGS_((
- CONST unsigned char* bytes, int length));
+EXTERN Tcl_Obj * Tcl_NewByteArrayObj(CONST unsigned char *bytes,
+ int length);
+#endif
+#ifndef Tcl_NewDoubleObj_TCL_DECLARED
+#define Tcl_NewDoubleObj_TCL_DECLARED
/* 51 */
-EXTERN Tcl_Obj * Tcl_NewDoubleObj _ANSI_ARGS_((double doubleValue));
+EXTERN Tcl_Obj * Tcl_NewDoubleObj(double doubleValue);
+#endif
+#ifndef Tcl_NewIntObj_TCL_DECLARED
+#define Tcl_NewIntObj_TCL_DECLARED
/* 52 */
-EXTERN Tcl_Obj * Tcl_NewIntObj _ANSI_ARGS_((int intValue));
+EXTERN Tcl_Obj * Tcl_NewIntObj(int intValue);
+#endif
+#ifndef Tcl_NewListObj_TCL_DECLARED
+#define Tcl_NewListObj_TCL_DECLARED
/* 53 */
-EXTERN Tcl_Obj * Tcl_NewListObj _ANSI_ARGS_((int objc,
- Tcl_Obj *CONST objv[]));
+EXTERN Tcl_Obj * Tcl_NewListObj(int objc, Tcl_Obj *CONST objv[]);
+#endif
+#ifndef Tcl_NewLongObj_TCL_DECLARED
+#define Tcl_NewLongObj_TCL_DECLARED
/* 54 */
-EXTERN Tcl_Obj * Tcl_NewLongObj _ANSI_ARGS_((long longValue));
+EXTERN Tcl_Obj * Tcl_NewLongObj(long longValue);
+#endif
+#ifndef Tcl_NewObj_TCL_DECLARED
+#define Tcl_NewObj_TCL_DECLARED
/* 55 */
-EXTERN Tcl_Obj * Tcl_NewObj _ANSI_ARGS_((void));
+EXTERN Tcl_Obj * Tcl_NewObj(void);
+#endif
+#ifndef Tcl_NewStringObj_TCL_DECLARED
+#define Tcl_NewStringObj_TCL_DECLARED
/* 56 */
-EXTERN Tcl_Obj * Tcl_NewStringObj _ANSI_ARGS_((CONST char * bytes,
- int length));
+EXTERN Tcl_Obj * Tcl_NewStringObj(CONST char *bytes, int length);
+#endif
+#ifndef Tcl_SetBooleanObj_TCL_DECLARED
+#define Tcl_SetBooleanObj_TCL_DECLARED
/* 57 */
-EXTERN void Tcl_SetBooleanObj _ANSI_ARGS_((Tcl_Obj * objPtr,
- int boolValue));
+EXTERN void Tcl_SetBooleanObj(Tcl_Obj *objPtr, int boolValue);
+#endif
+#ifndef Tcl_SetByteArrayLength_TCL_DECLARED
+#define Tcl_SetByteArrayLength_TCL_DECLARED
/* 58 */
-EXTERN unsigned char * Tcl_SetByteArrayLength _ANSI_ARGS_((Tcl_Obj * objPtr,
- int length));
+EXTERN unsigned char * Tcl_SetByteArrayLength(Tcl_Obj *objPtr, int length);
+#endif
+#ifndef Tcl_SetByteArrayObj_TCL_DECLARED
+#define Tcl_SetByteArrayObj_TCL_DECLARED
/* 59 */
-EXTERN void Tcl_SetByteArrayObj _ANSI_ARGS_((Tcl_Obj * objPtr,
- CONST unsigned char * bytes, int length));
+EXTERN void Tcl_SetByteArrayObj(Tcl_Obj *objPtr,
+ CONST unsigned char *bytes, int length);
+#endif
+#ifndef Tcl_SetDoubleObj_TCL_DECLARED
+#define Tcl_SetDoubleObj_TCL_DECLARED
/* 60 */
-EXTERN void Tcl_SetDoubleObj _ANSI_ARGS_((Tcl_Obj * objPtr,
- double doubleValue));
+EXTERN void Tcl_SetDoubleObj(Tcl_Obj *objPtr, double doubleValue);
+#endif
+#ifndef Tcl_SetIntObj_TCL_DECLARED
+#define Tcl_SetIntObj_TCL_DECLARED
/* 61 */
-EXTERN void Tcl_SetIntObj _ANSI_ARGS_((Tcl_Obj * objPtr,
- int intValue));
+EXTERN void Tcl_SetIntObj(Tcl_Obj *objPtr, int intValue);
+#endif
+#ifndef Tcl_SetListObj_TCL_DECLARED
+#define Tcl_SetListObj_TCL_DECLARED
/* 62 */
-EXTERN void Tcl_SetListObj _ANSI_ARGS_((Tcl_Obj * objPtr,
- int objc, Tcl_Obj *CONST objv[]));
+EXTERN void Tcl_SetListObj(Tcl_Obj *objPtr, int objc,
+ Tcl_Obj *CONST objv[]);
+#endif
+#ifndef Tcl_SetLongObj_TCL_DECLARED
+#define Tcl_SetLongObj_TCL_DECLARED
/* 63 */
-EXTERN void Tcl_SetLongObj _ANSI_ARGS_((Tcl_Obj * objPtr,
- long longValue));
+EXTERN void Tcl_SetLongObj(Tcl_Obj *objPtr, long longValue);
+#endif
+#ifndef Tcl_SetObjLength_TCL_DECLARED
+#define Tcl_SetObjLength_TCL_DECLARED
/* 64 */
-EXTERN void Tcl_SetObjLength _ANSI_ARGS_((Tcl_Obj * objPtr,
- int length));
+EXTERN void Tcl_SetObjLength(Tcl_Obj *objPtr, int length);
+#endif
+#ifndef Tcl_SetStringObj_TCL_DECLARED
+#define Tcl_SetStringObj_TCL_DECLARED
/* 65 */
-EXTERN void Tcl_SetStringObj _ANSI_ARGS_((Tcl_Obj* objPtr,
- CONST char* bytes, int length));
+EXTERN void Tcl_SetStringObj(Tcl_Obj *objPtr, CONST char *bytes,
+ int length);
+#endif
+#ifndef Tcl_AddErrorInfo_TCL_DECLARED
+#define Tcl_AddErrorInfo_TCL_DECLARED
/* 66 */
-EXTERN void Tcl_AddErrorInfo _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * message));
+EXTERN void Tcl_AddErrorInfo(Tcl_Interp *interp,
+ CONST char *message);
+#endif
+#ifndef Tcl_AddObjErrorInfo_TCL_DECLARED
+#define Tcl_AddObjErrorInfo_TCL_DECLARED
/* 67 */
-EXTERN void Tcl_AddObjErrorInfo _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * message, int length));
+EXTERN void Tcl_AddObjErrorInfo(Tcl_Interp *interp,
+ CONST char *message, int length);
+#endif
+#ifndef Tcl_AllowExceptions_TCL_DECLARED
+#define Tcl_AllowExceptions_TCL_DECLARED
/* 68 */
-EXTERN void Tcl_AllowExceptions _ANSI_ARGS_((Tcl_Interp * interp));
+EXTERN void Tcl_AllowExceptions(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_AppendElement_TCL_DECLARED
+#define Tcl_AppendElement_TCL_DECLARED
/* 69 */
-EXTERN void Tcl_AppendElement _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * string));
+EXTERN void Tcl_AppendElement(Tcl_Interp *interp,
+ CONST char *element);
+#endif
+#ifndef Tcl_AppendResult_TCL_DECLARED
+#define Tcl_AppendResult_TCL_DECLARED
/* 70 */
-EXTERN void Tcl_AppendResult _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp));
+EXTERN void Tcl_AppendResult(Tcl_Interp *interp, ...);
+#endif
+#ifndef Tcl_AsyncCreate_TCL_DECLARED
+#define Tcl_AsyncCreate_TCL_DECLARED
/* 71 */
-EXTERN Tcl_AsyncHandler Tcl_AsyncCreate _ANSI_ARGS_((Tcl_AsyncProc * proc,
- ClientData clientData));
+EXTERN Tcl_AsyncHandler Tcl_AsyncCreate(Tcl_AsyncProc *proc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_AsyncDelete_TCL_DECLARED
+#define Tcl_AsyncDelete_TCL_DECLARED
/* 72 */
-EXTERN void Tcl_AsyncDelete _ANSI_ARGS_((Tcl_AsyncHandler async));
+EXTERN void Tcl_AsyncDelete(Tcl_AsyncHandler async);
+#endif
+#ifndef Tcl_AsyncInvoke_TCL_DECLARED
+#define Tcl_AsyncInvoke_TCL_DECLARED
/* 73 */
-EXTERN int Tcl_AsyncInvoke _ANSI_ARGS_((Tcl_Interp * interp,
- int code));
+EXTERN int Tcl_AsyncInvoke(Tcl_Interp *interp, int code);
+#endif
+#ifndef Tcl_AsyncMark_TCL_DECLARED
+#define Tcl_AsyncMark_TCL_DECLARED
/* 74 */
-EXTERN void Tcl_AsyncMark _ANSI_ARGS_((Tcl_AsyncHandler async));
+EXTERN void Tcl_AsyncMark(Tcl_AsyncHandler async);
+#endif
+#ifndef Tcl_AsyncReady_TCL_DECLARED
+#define Tcl_AsyncReady_TCL_DECLARED
/* 75 */
-EXTERN int Tcl_AsyncReady _ANSI_ARGS_((void));
+EXTERN int Tcl_AsyncReady(void);
+#endif
+#ifndef Tcl_BackgroundError_TCL_DECLARED
+#define Tcl_BackgroundError_TCL_DECLARED
/* 76 */
-EXTERN void Tcl_BackgroundError _ANSI_ARGS_((Tcl_Interp * interp));
+EXTERN void Tcl_BackgroundError(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_Backslash_TCL_DECLARED
+#define Tcl_Backslash_TCL_DECLARED
/* 77 */
-EXTERN char Tcl_Backslash _ANSI_ARGS_((CONST char * src,
- int * readPtr));
+EXTERN char Tcl_Backslash(CONST char *src, int *readPtr);
+#endif
+#ifndef Tcl_BadChannelOption_TCL_DECLARED
+#define Tcl_BadChannelOption_TCL_DECLARED
/* 78 */
-EXTERN int Tcl_BadChannelOption _ANSI_ARGS_((
- Tcl_Interp * interp, CONST char * optionName,
- CONST char * optionList));
+EXTERN int Tcl_BadChannelOption(Tcl_Interp *interp,
+ CONST char *optionName,
+ CONST char *optionList);
+#endif
+#ifndef Tcl_CallWhenDeleted_TCL_DECLARED
+#define Tcl_CallWhenDeleted_TCL_DECLARED
/* 79 */
-EXTERN void Tcl_CallWhenDeleted _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_InterpDeleteProc * proc,
- ClientData clientData));
+EXTERN void Tcl_CallWhenDeleted(Tcl_Interp *interp,
+ Tcl_InterpDeleteProc *proc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_CancelIdleCall_TCL_DECLARED
+#define Tcl_CancelIdleCall_TCL_DECLARED
/* 80 */
-EXTERN void Tcl_CancelIdleCall _ANSI_ARGS_((
- Tcl_IdleProc * idleProc,
- ClientData clientData));
+EXTERN void Tcl_CancelIdleCall(Tcl_IdleProc *idleProc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_Close_TCL_DECLARED
+#define Tcl_Close_TCL_DECLARED
/* 81 */
-EXTERN int Tcl_Close _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Channel chan));
+EXTERN int Tcl_Close(Tcl_Interp *interp, Tcl_Channel chan);
+#endif
+#ifndef Tcl_CommandComplete_TCL_DECLARED
+#define Tcl_CommandComplete_TCL_DECLARED
/* 82 */
-EXTERN int Tcl_CommandComplete _ANSI_ARGS_((CONST char * cmd));
+EXTERN int Tcl_CommandComplete(CONST char *cmd);
+#endif
+#ifndef Tcl_Concat_TCL_DECLARED
+#define Tcl_Concat_TCL_DECLARED
/* 83 */
-EXTERN char * Tcl_Concat _ANSI_ARGS_((int argc,
- CONST84 char * CONST * argv));
+EXTERN char * Tcl_Concat(int argc, CONST84 char *CONST *argv);
+#endif
+#ifndef Tcl_ConvertElement_TCL_DECLARED
+#define Tcl_ConvertElement_TCL_DECLARED
/* 84 */
-EXTERN int Tcl_ConvertElement _ANSI_ARGS_((CONST char * src,
- char * dst, int flags));
+EXTERN int Tcl_ConvertElement(CONST char *src, char *dst,
+ int flags);
+#endif
+#ifndef Tcl_ConvertCountedElement_TCL_DECLARED
+#define Tcl_ConvertCountedElement_TCL_DECLARED
/* 85 */
-EXTERN int Tcl_ConvertCountedElement _ANSI_ARGS_((
- CONST char * src, int length, char * dst,
- int flags));
+EXTERN int Tcl_ConvertCountedElement(CONST char *src,
+ int length, char *dst, int flags);
+#endif
+#ifndef Tcl_CreateAlias_TCL_DECLARED
+#define Tcl_CreateAlias_TCL_DECLARED
/* 86 */
-EXTERN int Tcl_CreateAlias _ANSI_ARGS_((Tcl_Interp * slave,
- CONST char * slaveCmd, Tcl_Interp * target,
- CONST char * targetCmd, int argc,
- CONST84 char * CONST * argv));
+EXTERN int Tcl_CreateAlias(Tcl_Interp *slave,
+ CONST char *slaveCmd, Tcl_Interp *target,
+ CONST char *targetCmd, int argc,
+ CONST84 char *CONST *argv);
+#endif
+#ifndef Tcl_CreateAliasObj_TCL_DECLARED
+#define Tcl_CreateAliasObj_TCL_DECLARED
/* 87 */
-EXTERN int Tcl_CreateAliasObj _ANSI_ARGS_((Tcl_Interp * slave,
- CONST char * slaveCmd, Tcl_Interp * target,
- CONST char * targetCmd, int objc,
- Tcl_Obj *CONST objv[]));
+EXTERN int Tcl_CreateAliasObj(Tcl_Interp *slave,
+ CONST char *slaveCmd, Tcl_Interp *target,
+ CONST char *targetCmd, int objc,
+ Tcl_Obj *CONST objv[]);
+#endif
+#ifndef Tcl_CreateChannel_TCL_DECLARED
+#define Tcl_CreateChannel_TCL_DECLARED
/* 88 */
-EXTERN Tcl_Channel Tcl_CreateChannel _ANSI_ARGS_((
- Tcl_ChannelType * typePtr,
- CONST char * chanName,
- ClientData instanceData, int mask));
+EXTERN Tcl_Channel Tcl_CreateChannel(Tcl_ChannelType *typePtr,
+ CONST char *chanName,
+ ClientData instanceData, int mask);
+#endif
+#ifndef Tcl_CreateChannelHandler_TCL_DECLARED
+#define Tcl_CreateChannelHandler_TCL_DECLARED
/* 89 */
-EXTERN void Tcl_CreateChannelHandler _ANSI_ARGS_((
- Tcl_Channel chan, int mask,
- Tcl_ChannelProc * proc,
- ClientData clientData));
+EXTERN void Tcl_CreateChannelHandler(Tcl_Channel chan, int mask,
+ Tcl_ChannelProc *proc, ClientData clientData);
+#endif
+#ifndef Tcl_CreateCloseHandler_TCL_DECLARED
+#define Tcl_CreateCloseHandler_TCL_DECLARED
/* 90 */
-EXTERN void Tcl_CreateCloseHandler _ANSI_ARGS_((Tcl_Channel chan,
- Tcl_CloseProc * proc, ClientData clientData));
+EXTERN void Tcl_CreateCloseHandler(Tcl_Channel chan,
+ Tcl_CloseProc *proc, ClientData clientData);
+#endif
+#ifndef Tcl_CreateCommand_TCL_DECLARED
+#define Tcl_CreateCommand_TCL_DECLARED
/* 91 */
-EXTERN Tcl_Command Tcl_CreateCommand _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * cmdName, Tcl_CmdProc * proc,
- ClientData clientData,
- Tcl_CmdDeleteProc * deleteProc));
+EXTERN Tcl_Command Tcl_CreateCommand(Tcl_Interp *interp,
+ CONST char *cmdName, Tcl_CmdProc *proc,
+ ClientData clientData,
+ Tcl_CmdDeleteProc *deleteProc);
+#endif
+#ifndef Tcl_CreateEventSource_TCL_DECLARED
+#define Tcl_CreateEventSource_TCL_DECLARED
/* 92 */
-EXTERN void Tcl_CreateEventSource _ANSI_ARGS_((
- Tcl_EventSetupProc * setupProc,
- Tcl_EventCheckProc * checkProc,
- ClientData clientData));
+EXTERN void Tcl_CreateEventSource(Tcl_EventSetupProc *setupProc,
+ Tcl_EventCheckProc *checkProc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_CreateExitHandler_TCL_DECLARED
+#define Tcl_CreateExitHandler_TCL_DECLARED
/* 93 */
-EXTERN void Tcl_CreateExitHandler _ANSI_ARGS_((
- Tcl_ExitProc * proc, ClientData clientData));
+EXTERN void Tcl_CreateExitHandler(Tcl_ExitProc *proc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_CreateInterp_TCL_DECLARED
+#define Tcl_CreateInterp_TCL_DECLARED
/* 94 */
-EXTERN Tcl_Interp * Tcl_CreateInterp _ANSI_ARGS_((void));
+EXTERN Tcl_Interp * Tcl_CreateInterp(void);
+#endif
+#ifndef Tcl_CreateMathFunc_TCL_DECLARED
+#define Tcl_CreateMathFunc_TCL_DECLARED
/* 95 */
-EXTERN void Tcl_CreateMathFunc _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * name, int numArgs,
- Tcl_ValueType * argTypes,
- Tcl_MathProc * proc, ClientData clientData));
+EXTERN void Tcl_CreateMathFunc(Tcl_Interp *interp,
+ CONST char *name, int numArgs,
+ Tcl_ValueType *argTypes, Tcl_MathProc *proc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_CreateObjCommand_TCL_DECLARED
+#define Tcl_CreateObjCommand_TCL_DECLARED
/* 96 */
-EXTERN Tcl_Command Tcl_CreateObjCommand _ANSI_ARGS_((
- Tcl_Interp * interp, CONST char * cmdName,
- Tcl_ObjCmdProc * proc, ClientData clientData,
- Tcl_CmdDeleteProc * deleteProc));
+EXTERN Tcl_Command Tcl_CreateObjCommand(Tcl_Interp *interp,
+ CONST char *cmdName, Tcl_ObjCmdProc *proc,
+ ClientData clientData,
+ Tcl_CmdDeleteProc *deleteProc);
+#endif
+#ifndef Tcl_CreateSlave_TCL_DECLARED
+#define Tcl_CreateSlave_TCL_DECLARED
/* 97 */
-EXTERN Tcl_Interp * Tcl_CreateSlave _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * slaveName, int isSafe));
+EXTERN Tcl_Interp * Tcl_CreateSlave(Tcl_Interp *interp,
+ CONST char *slaveName, int isSafe);
+#endif
+#ifndef Tcl_CreateTimerHandler_TCL_DECLARED
+#define Tcl_CreateTimerHandler_TCL_DECLARED
/* 98 */
-EXTERN Tcl_TimerToken Tcl_CreateTimerHandler _ANSI_ARGS_((int milliseconds,
- Tcl_TimerProc * proc, ClientData clientData));
+EXTERN Tcl_TimerToken Tcl_CreateTimerHandler(int milliseconds,
+ Tcl_TimerProc *proc, ClientData clientData);
+#endif
+#ifndef Tcl_CreateTrace_TCL_DECLARED
+#define Tcl_CreateTrace_TCL_DECLARED
/* 99 */
-EXTERN Tcl_Trace Tcl_CreateTrace _ANSI_ARGS_((Tcl_Interp * interp,
- int level, Tcl_CmdTraceProc * proc,
- ClientData clientData));
+EXTERN Tcl_Trace Tcl_CreateTrace(Tcl_Interp *interp, int level,
+ Tcl_CmdTraceProc *proc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_DeleteAssocData_TCL_DECLARED
+#define Tcl_DeleteAssocData_TCL_DECLARED
/* 100 */
-EXTERN void Tcl_DeleteAssocData _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * name));
+EXTERN void Tcl_DeleteAssocData(Tcl_Interp *interp,
+ CONST char *name);
+#endif
+#ifndef Tcl_DeleteChannelHandler_TCL_DECLARED
+#define Tcl_DeleteChannelHandler_TCL_DECLARED
/* 101 */
-EXTERN void Tcl_DeleteChannelHandler _ANSI_ARGS_((
- Tcl_Channel chan, Tcl_ChannelProc * proc,
- ClientData clientData));
+EXTERN void Tcl_DeleteChannelHandler(Tcl_Channel chan,
+ Tcl_ChannelProc *proc, ClientData clientData);
+#endif
+#ifndef Tcl_DeleteCloseHandler_TCL_DECLARED
+#define Tcl_DeleteCloseHandler_TCL_DECLARED
/* 102 */
-EXTERN void Tcl_DeleteCloseHandler _ANSI_ARGS_((Tcl_Channel chan,
- Tcl_CloseProc * proc, ClientData clientData));
+EXTERN void Tcl_DeleteCloseHandler(Tcl_Channel chan,
+ Tcl_CloseProc *proc, ClientData clientData);
+#endif
+#ifndef Tcl_DeleteCommand_TCL_DECLARED
+#define Tcl_DeleteCommand_TCL_DECLARED
/* 103 */
-EXTERN int Tcl_DeleteCommand _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * cmdName));
+EXTERN int Tcl_DeleteCommand(Tcl_Interp *interp,
+ CONST char *cmdName);
+#endif
+#ifndef Tcl_DeleteCommandFromToken_TCL_DECLARED
+#define Tcl_DeleteCommandFromToken_TCL_DECLARED
/* 104 */
-EXTERN int Tcl_DeleteCommandFromToken _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Command command));
+EXTERN int Tcl_DeleteCommandFromToken(Tcl_Interp *interp,
+ Tcl_Command command);
+#endif
+#ifndef Tcl_DeleteEvents_TCL_DECLARED
+#define Tcl_DeleteEvents_TCL_DECLARED
/* 105 */
-EXTERN void Tcl_DeleteEvents _ANSI_ARGS_((
- Tcl_EventDeleteProc * proc,
- ClientData clientData));
+EXTERN void Tcl_DeleteEvents(Tcl_EventDeleteProc *proc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_DeleteEventSource_TCL_DECLARED
+#define Tcl_DeleteEventSource_TCL_DECLARED
/* 106 */
-EXTERN void Tcl_DeleteEventSource _ANSI_ARGS_((
- Tcl_EventSetupProc * setupProc,
- Tcl_EventCheckProc * checkProc,
- ClientData clientData));
+EXTERN void Tcl_DeleteEventSource(Tcl_EventSetupProc *setupProc,
+ Tcl_EventCheckProc *checkProc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_DeleteExitHandler_TCL_DECLARED
+#define Tcl_DeleteExitHandler_TCL_DECLARED
/* 107 */
-EXTERN void Tcl_DeleteExitHandler _ANSI_ARGS_((
- Tcl_ExitProc * proc, ClientData clientData));
+EXTERN void Tcl_DeleteExitHandler(Tcl_ExitProc *proc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_DeleteHashEntry_TCL_DECLARED
+#define Tcl_DeleteHashEntry_TCL_DECLARED
/* 108 */
-EXTERN void Tcl_DeleteHashEntry _ANSI_ARGS_((
- Tcl_HashEntry * entryPtr));
+EXTERN void Tcl_DeleteHashEntry(Tcl_HashEntry *entryPtr);
+#endif
+#ifndef Tcl_DeleteHashTable_TCL_DECLARED
+#define Tcl_DeleteHashTable_TCL_DECLARED
/* 109 */
-EXTERN void Tcl_DeleteHashTable _ANSI_ARGS_((
- Tcl_HashTable * tablePtr));
+EXTERN void Tcl_DeleteHashTable(Tcl_HashTable *tablePtr);
+#endif
+#ifndef Tcl_DeleteInterp_TCL_DECLARED
+#define Tcl_DeleteInterp_TCL_DECLARED
/* 110 */
-EXTERN void Tcl_DeleteInterp _ANSI_ARGS_((Tcl_Interp * interp));
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
-/* 111 */
-EXTERN void Tcl_DetachPids _ANSI_ARGS_((int numPids,
- Tcl_Pid * pidPtr));
-#endif /* UNIX */
-#ifdef __WIN32__
+EXTERN void Tcl_DeleteInterp(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_DetachPids_TCL_DECLARED
+#define Tcl_DetachPids_TCL_DECLARED
/* 111 */
-EXTERN void Tcl_DetachPids _ANSI_ARGS_((int numPids,
- Tcl_Pid * pidPtr));
-#endif /* __WIN32__ */
+EXTERN void Tcl_DetachPids(int numPids, Tcl_Pid *pidPtr);
+#endif
+#ifndef Tcl_DeleteTimerHandler_TCL_DECLARED
+#define Tcl_DeleteTimerHandler_TCL_DECLARED
/* 112 */
-EXTERN void Tcl_DeleteTimerHandler _ANSI_ARGS_((
- Tcl_TimerToken token));
+EXTERN void Tcl_DeleteTimerHandler(Tcl_TimerToken token);
+#endif
+#ifndef Tcl_DeleteTrace_TCL_DECLARED
+#define Tcl_DeleteTrace_TCL_DECLARED
/* 113 */
-EXTERN void Tcl_DeleteTrace _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Trace trace));
+EXTERN void Tcl_DeleteTrace(Tcl_Interp *interp, Tcl_Trace trace);
+#endif
+#ifndef Tcl_DontCallWhenDeleted_TCL_DECLARED
+#define Tcl_DontCallWhenDeleted_TCL_DECLARED
/* 114 */
-EXTERN void Tcl_DontCallWhenDeleted _ANSI_ARGS_((
- Tcl_Interp * interp,
- Tcl_InterpDeleteProc * proc,
- ClientData clientData));
+EXTERN void Tcl_DontCallWhenDeleted(Tcl_Interp *interp,
+ Tcl_InterpDeleteProc *proc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_DoOneEvent_TCL_DECLARED
+#define Tcl_DoOneEvent_TCL_DECLARED
/* 115 */
-EXTERN int Tcl_DoOneEvent _ANSI_ARGS_((int flags));
+EXTERN int Tcl_DoOneEvent(int flags);
+#endif
+#ifndef Tcl_DoWhenIdle_TCL_DECLARED
+#define Tcl_DoWhenIdle_TCL_DECLARED
/* 116 */
-EXTERN void Tcl_DoWhenIdle _ANSI_ARGS_((Tcl_IdleProc * proc,
- ClientData clientData));
+EXTERN void Tcl_DoWhenIdle(Tcl_IdleProc *proc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_DStringAppend_TCL_DECLARED
+#define Tcl_DStringAppend_TCL_DECLARED
/* 117 */
-EXTERN char * Tcl_DStringAppend _ANSI_ARGS_((Tcl_DString * dsPtr,
- CONST char * str, int length));
+EXTERN char * Tcl_DStringAppend(Tcl_DString *dsPtr,
+ CONST char *bytes, int length);
+#endif
+#ifndef Tcl_DStringAppendElement_TCL_DECLARED
+#define Tcl_DStringAppendElement_TCL_DECLARED
/* 118 */
-EXTERN char * Tcl_DStringAppendElement _ANSI_ARGS_((
- Tcl_DString * dsPtr, CONST char * string));
+EXTERN char * Tcl_DStringAppendElement(Tcl_DString *dsPtr,
+ CONST char *element);
+#endif
+#ifndef Tcl_DStringEndSublist_TCL_DECLARED
+#define Tcl_DStringEndSublist_TCL_DECLARED
/* 119 */
-EXTERN void Tcl_DStringEndSublist _ANSI_ARGS_((
- Tcl_DString * dsPtr));
+EXTERN void Tcl_DStringEndSublist(Tcl_DString *dsPtr);
+#endif
+#ifndef Tcl_DStringFree_TCL_DECLARED
+#define Tcl_DStringFree_TCL_DECLARED
/* 120 */
-EXTERN void Tcl_DStringFree _ANSI_ARGS_((Tcl_DString * dsPtr));
+EXTERN void Tcl_DStringFree(Tcl_DString *dsPtr);
+#endif
+#ifndef Tcl_DStringGetResult_TCL_DECLARED
+#define Tcl_DStringGetResult_TCL_DECLARED
/* 121 */
-EXTERN void Tcl_DStringGetResult _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_DString * dsPtr));
+EXTERN void Tcl_DStringGetResult(Tcl_Interp *interp,
+ Tcl_DString *dsPtr);
+#endif
+#ifndef Tcl_DStringInit_TCL_DECLARED
+#define Tcl_DStringInit_TCL_DECLARED
/* 122 */
-EXTERN void Tcl_DStringInit _ANSI_ARGS_((Tcl_DString * dsPtr));
+EXTERN void Tcl_DStringInit(Tcl_DString *dsPtr);
+#endif
+#ifndef Tcl_DStringResult_TCL_DECLARED
+#define Tcl_DStringResult_TCL_DECLARED
/* 123 */
-EXTERN void Tcl_DStringResult _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_DString * dsPtr));
+EXTERN void Tcl_DStringResult(Tcl_Interp *interp,
+ Tcl_DString *dsPtr);
+#endif
+#ifndef Tcl_DStringSetLength_TCL_DECLARED
+#define Tcl_DStringSetLength_TCL_DECLARED
/* 124 */
-EXTERN void Tcl_DStringSetLength _ANSI_ARGS_((
- Tcl_DString * dsPtr, int length));
+EXTERN void Tcl_DStringSetLength(Tcl_DString *dsPtr, int length);
+#endif
+#ifndef Tcl_DStringStartSublist_TCL_DECLARED
+#define Tcl_DStringStartSublist_TCL_DECLARED
/* 125 */
-EXTERN void Tcl_DStringStartSublist _ANSI_ARGS_((
- Tcl_DString * dsPtr));
+EXTERN void Tcl_DStringStartSublist(Tcl_DString *dsPtr);
+#endif
+#ifndef Tcl_Eof_TCL_DECLARED
+#define Tcl_Eof_TCL_DECLARED
/* 126 */
-EXTERN int Tcl_Eof _ANSI_ARGS_((Tcl_Channel chan));
+EXTERN int Tcl_Eof(Tcl_Channel chan);
+#endif
+#ifndef Tcl_ErrnoId_TCL_DECLARED
+#define Tcl_ErrnoId_TCL_DECLARED
/* 127 */
-EXTERN CONST84_RETURN char * Tcl_ErrnoId _ANSI_ARGS_((void));
+EXTERN CONST84_RETURN char * Tcl_ErrnoId(void);
+#endif
+#ifndef Tcl_ErrnoMsg_TCL_DECLARED
+#define Tcl_ErrnoMsg_TCL_DECLARED
/* 128 */
-EXTERN CONST84_RETURN char * Tcl_ErrnoMsg _ANSI_ARGS_((int err));
+EXTERN CONST84_RETURN char * Tcl_ErrnoMsg(int err);
+#endif
+#ifndef Tcl_Eval_TCL_DECLARED
+#define Tcl_Eval_TCL_DECLARED
/* 129 */
-EXTERN int Tcl_Eval _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * string));
+EXTERN int Tcl_Eval(Tcl_Interp *interp, CONST char *script);
+#endif
+#ifndef Tcl_EvalFile_TCL_DECLARED
+#define Tcl_EvalFile_TCL_DECLARED
/* 130 */
-EXTERN int Tcl_EvalFile _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * fileName));
+EXTERN int Tcl_EvalFile(Tcl_Interp *interp,
+ CONST char *fileName);
+#endif
+#ifndef Tcl_EvalObj_TCL_DECLARED
+#define Tcl_EvalObj_TCL_DECLARED
/* 131 */
-EXTERN int Tcl_EvalObj _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * objPtr));
+EXTERN int Tcl_EvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr);
+#endif
+#ifndef Tcl_EventuallyFree_TCL_DECLARED
+#define Tcl_EventuallyFree_TCL_DECLARED
/* 132 */
-EXTERN void Tcl_EventuallyFree _ANSI_ARGS_((
- ClientData clientData,
- Tcl_FreeProc * freeProc));
+EXTERN void Tcl_EventuallyFree(ClientData clientData,
+ Tcl_FreeProc *freeProc);
+#endif
+#ifndef Tcl_Exit_TCL_DECLARED
+#define Tcl_Exit_TCL_DECLARED
/* 133 */
-EXTERN void Tcl_Exit _ANSI_ARGS_((int status));
+EXTERN void Tcl_Exit(int status);
+#endif
+#ifndef Tcl_ExposeCommand_TCL_DECLARED
+#define Tcl_ExposeCommand_TCL_DECLARED
/* 134 */
-EXTERN int Tcl_ExposeCommand _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * hiddenCmdToken,
- CONST char * cmdName));
+EXTERN int Tcl_ExposeCommand(Tcl_Interp *interp,
+ CONST char *hiddenCmdToken,
+ CONST char *cmdName);
+#endif
+#ifndef Tcl_ExprBoolean_TCL_DECLARED
+#define Tcl_ExprBoolean_TCL_DECLARED
/* 135 */
-EXTERN int Tcl_ExprBoolean _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * str, int * ptr));
+EXTERN int Tcl_ExprBoolean(Tcl_Interp *interp, CONST char *expr,
+ int *ptr);
+#endif
+#ifndef Tcl_ExprBooleanObj_TCL_DECLARED
+#define Tcl_ExprBooleanObj_TCL_DECLARED
/* 136 */
-EXTERN int Tcl_ExprBooleanObj _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * objPtr, int * ptr));
+EXTERN int Tcl_ExprBooleanObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, int *ptr);
+#endif
+#ifndef Tcl_ExprDouble_TCL_DECLARED
+#define Tcl_ExprDouble_TCL_DECLARED
/* 137 */
-EXTERN int Tcl_ExprDouble _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * str, double * ptr));
+EXTERN int Tcl_ExprDouble(Tcl_Interp *interp, CONST char *expr,
+ double *ptr);
+#endif
+#ifndef Tcl_ExprDoubleObj_TCL_DECLARED
+#define Tcl_ExprDoubleObj_TCL_DECLARED
/* 138 */
-EXTERN int Tcl_ExprDoubleObj _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * objPtr, double * ptr));
+EXTERN int Tcl_ExprDoubleObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, double *ptr);
+#endif
+#ifndef Tcl_ExprLong_TCL_DECLARED
+#define Tcl_ExprLong_TCL_DECLARED
/* 139 */
-EXTERN int Tcl_ExprLong _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * str, long * ptr));
+EXTERN int Tcl_ExprLong(Tcl_Interp *interp, CONST char *expr,
+ long *ptr);
+#endif
+#ifndef Tcl_ExprLongObj_TCL_DECLARED
+#define Tcl_ExprLongObj_TCL_DECLARED
/* 140 */
-EXTERN int Tcl_ExprLongObj _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * objPtr, long * ptr));
+EXTERN int Tcl_ExprLongObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ long *ptr);
+#endif
+#ifndef Tcl_ExprObj_TCL_DECLARED
+#define Tcl_ExprObj_TCL_DECLARED
/* 141 */
-EXTERN int Tcl_ExprObj _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * objPtr, Tcl_Obj ** resultPtrPtr));
+EXTERN int Tcl_ExprObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ Tcl_Obj **resultPtrPtr);
+#endif
+#ifndef Tcl_ExprString_TCL_DECLARED
+#define Tcl_ExprString_TCL_DECLARED
/* 142 */
-EXTERN int Tcl_ExprString _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * string));
+EXTERN int Tcl_ExprString(Tcl_Interp *interp, CONST char *expr);
+#endif
+#ifndef Tcl_Finalize_TCL_DECLARED
+#define Tcl_Finalize_TCL_DECLARED
/* 143 */
-EXTERN void Tcl_Finalize _ANSI_ARGS_((void));
+EXTERN void Tcl_Finalize(void);
+#endif
+#ifndef Tcl_FindExecutable_TCL_DECLARED
+#define Tcl_FindExecutable_TCL_DECLARED
/* 144 */
-EXTERN void Tcl_FindExecutable _ANSI_ARGS_((CONST char * argv0));
+EXTERN void Tcl_FindExecutable(CONST char *argv0);
+#endif
+#ifndef Tcl_FirstHashEntry_TCL_DECLARED
+#define Tcl_FirstHashEntry_TCL_DECLARED
/* 145 */
-EXTERN Tcl_HashEntry * Tcl_FirstHashEntry _ANSI_ARGS_((
- Tcl_HashTable * tablePtr,
- Tcl_HashSearch * searchPtr));
+EXTERN Tcl_HashEntry * Tcl_FirstHashEntry(Tcl_HashTable *tablePtr,
+ Tcl_HashSearch *searchPtr);
+#endif
+#ifndef Tcl_Flush_TCL_DECLARED
+#define Tcl_Flush_TCL_DECLARED
/* 146 */
-EXTERN int Tcl_Flush _ANSI_ARGS_((Tcl_Channel chan));
+EXTERN int Tcl_Flush(Tcl_Channel chan);
+#endif
+#ifndef Tcl_FreeResult_TCL_DECLARED
+#define Tcl_FreeResult_TCL_DECLARED
/* 147 */
-EXTERN void Tcl_FreeResult _ANSI_ARGS_((Tcl_Interp * interp));
+EXTERN void Tcl_FreeResult(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_GetAlias_TCL_DECLARED
+#define Tcl_GetAlias_TCL_DECLARED
/* 148 */
-EXTERN int Tcl_GetAlias _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * slaveCmd,
- Tcl_Interp ** targetInterpPtr,
- CONST84 char ** targetCmdPtr, int * argcPtr,
- CONST84 char *** argvPtr));
+EXTERN int Tcl_GetAlias(Tcl_Interp *interp,
+ CONST char *slaveCmd,
+ Tcl_Interp **targetInterpPtr,
+ CONST84 char **targetCmdPtr, int *argcPtr,
+ CONST84 char ***argvPtr);
+#endif
+#ifndef Tcl_GetAliasObj_TCL_DECLARED
+#define Tcl_GetAliasObj_TCL_DECLARED
/* 149 */
-EXTERN int Tcl_GetAliasObj _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * slaveCmd,
- Tcl_Interp ** targetInterpPtr,
- CONST84 char ** targetCmdPtr, int * objcPtr,
- Tcl_Obj *** objv));
+EXTERN int Tcl_GetAliasObj(Tcl_Interp *interp,
+ CONST char *slaveCmd,
+ Tcl_Interp **targetInterpPtr,
+ CONST84 char **targetCmdPtr, int *objcPtr,
+ Tcl_Obj ***objv);
+#endif
+#ifndef Tcl_GetAssocData_TCL_DECLARED
+#define Tcl_GetAssocData_TCL_DECLARED
/* 150 */
-EXTERN ClientData Tcl_GetAssocData _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * name,
- Tcl_InterpDeleteProc ** procPtr));
+EXTERN ClientData Tcl_GetAssocData(Tcl_Interp *interp,
+ CONST char *name,
+ Tcl_InterpDeleteProc **procPtr);
+#endif
+#ifndef Tcl_GetChannel_TCL_DECLARED
+#define Tcl_GetChannel_TCL_DECLARED
/* 151 */
-EXTERN Tcl_Channel Tcl_GetChannel _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * chanName, int * modePtr));
+EXTERN Tcl_Channel Tcl_GetChannel(Tcl_Interp *interp,
+ CONST char *chanName, int *modePtr);
+#endif
+#ifndef Tcl_GetChannelBufferSize_TCL_DECLARED
+#define Tcl_GetChannelBufferSize_TCL_DECLARED
/* 152 */
-EXTERN int Tcl_GetChannelBufferSize _ANSI_ARGS_((
- Tcl_Channel chan));
+EXTERN int Tcl_GetChannelBufferSize(Tcl_Channel chan);
+#endif
+#ifndef Tcl_GetChannelHandle_TCL_DECLARED
+#define Tcl_GetChannelHandle_TCL_DECLARED
/* 153 */
-EXTERN int Tcl_GetChannelHandle _ANSI_ARGS_((Tcl_Channel chan,
- int direction, ClientData * handlePtr));
+EXTERN int Tcl_GetChannelHandle(Tcl_Channel chan, int direction,
+ ClientData *handlePtr);
+#endif
+#ifndef Tcl_GetChannelInstanceData_TCL_DECLARED
+#define Tcl_GetChannelInstanceData_TCL_DECLARED
/* 154 */
-EXTERN ClientData Tcl_GetChannelInstanceData _ANSI_ARGS_((
- Tcl_Channel chan));
+EXTERN ClientData Tcl_GetChannelInstanceData(Tcl_Channel chan);
+#endif
+#ifndef Tcl_GetChannelMode_TCL_DECLARED
+#define Tcl_GetChannelMode_TCL_DECLARED
/* 155 */
-EXTERN int Tcl_GetChannelMode _ANSI_ARGS_((Tcl_Channel chan));
+EXTERN int Tcl_GetChannelMode(Tcl_Channel chan);
+#endif
+#ifndef Tcl_GetChannelName_TCL_DECLARED
+#define Tcl_GetChannelName_TCL_DECLARED
/* 156 */
-EXTERN CONST84_RETURN char * Tcl_GetChannelName _ANSI_ARGS_((
- Tcl_Channel chan));
+EXTERN CONST84_RETURN char * Tcl_GetChannelName(Tcl_Channel chan);
+#endif
+#ifndef Tcl_GetChannelOption_TCL_DECLARED
+#define Tcl_GetChannelOption_TCL_DECLARED
/* 157 */
-EXTERN int Tcl_GetChannelOption _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Channel chan,
- CONST char * optionName, Tcl_DString * dsPtr));
+EXTERN int Tcl_GetChannelOption(Tcl_Interp *interp,
+ Tcl_Channel chan, CONST char *optionName,
+ Tcl_DString *dsPtr);
+#endif
+#ifndef Tcl_GetChannelType_TCL_DECLARED
+#define Tcl_GetChannelType_TCL_DECLARED
/* 158 */
-EXTERN Tcl_ChannelType * Tcl_GetChannelType _ANSI_ARGS_((Tcl_Channel chan));
+EXTERN Tcl_ChannelType * Tcl_GetChannelType(Tcl_Channel chan);
+#endif
+#ifndef Tcl_GetCommandInfo_TCL_DECLARED
+#define Tcl_GetCommandInfo_TCL_DECLARED
/* 159 */
-EXTERN int Tcl_GetCommandInfo _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * cmdName, Tcl_CmdInfo * infoPtr));
+EXTERN int Tcl_GetCommandInfo(Tcl_Interp *interp,
+ CONST char *cmdName, Tcl_CmdInfo *infoPtr);
+#endif
+#ifndef Tcl_GetCommandName_TCL_DECLARED
+#define Tcl_GetCommandName_TCL_DECLARED
/* 160 */
-EXTERN CONST84_RETURN char * Tcl_GetCommandName _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Command command));
+EXTERN CONST84_RETURN char * Tcl_GetCommandName(Tcl_Interp *interp,
+ Tcl_Command command);
+#endif
+#ifndef Tcl_GetErrno_TCL_DECLARED
+#define Tcl_GetErrno_TCL_DECLARED
/* 161 */
-EXTERN int Tcl_GetErrno _ANSI_ARGS_((void));
+EXTERN int Tcl_GetErrno(void);
+#endif
+#ifndef Tcl_GetHostName_TCL_DECLARED
+#define Tcl_GetHostName_TCL_DECLARED
/* 162 */
-EXTERN CONST84_RETURN char * Tcl_GetHostName _ANSI_ARGS_((void));
+EXTERN CONST84_RETURN char * Tcl_GetHostName(void);
+#endif
+#ifndef Tcl_GetInterpPath_TCL_DECLARED
+#define Tcl_GetInterpPath_TCL_DECLARED
/* 163 */
-EXTERN int Tcl_GetInterpPath _ANSI_ARGS_((
- Tcl_Interp * askInterp,
- Tcl_Interp * slaveInterp));
+EXTERN int Tcl_GetInterpPath(Tcl_Interp *askInterp,
+ Tcl_Interp *slaveInterp);
+#endif
+#ifndef Tcl_GetMaster_TCL_DECLARED
+#define Tcl_GetMaster_TCL_DECLARED
/* 164 */
-EXTERN Tcl_Interp * Tcl_GetMaster _ANSI_ARGS_((Tcl_Interp * interp));
+EXTERN Tcl_Interp * Tcl_GetMaster(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_GetNameOfExecutable_TCL_DECLARED
+#define Tcl_GetNameOfExecutable_TCL_DECLARED
/* 165 */
-EXTERN CONST char * Tcl_GetNameOfExecutable _ANSI_ARGS_((void));
+EXTERN CONST char * Tcl_GetNameOfExecutable(void);
+#endif
+#ifndef Tcl_GetObjResult_TCL_DECLARED
+#define Tcl_GetObjResult_TCL_DECLARED
/* 166 */
-EXTERN Tcl_Obj * Tcl_GetObjResult _ANSI_ARGS_((Tcl_Interp * interp));
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+EXTERN Tcl_Obj * Tcl_GetObjResult(Tcl_Interp *interp);
+#endif
+#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
+#ifndef Tcl_GetOpenFile_TCL_DECLARED
+#define Tcl_GetOpenFile_TCL_DECLARED
/* 167 */
-EXTERN int Tcl_GetOpenFile _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * str, int forWriting,
- int checkUsage, ClientData * filePtr));
+EXTERN int Tcl_GetOpenFile(Tcl_Interp *interp,
+ CONST char *chanID, int forWriting,
+ int checkUsage, ClientData *filePtr);
+#endif
#endif /* UNIX */
+#ifdef MAC_OSX_TCL /* MACOSX */
+#ifndef Tcl_GetOpenFile_TCL_DECLARED
+#define Tcl_GetOpenFile_TCL_DECLARED
+/* 167 */
+EXTERN int Tcl_GetOpenFile(Tcl_Interp *interp,
+ CONST char *chanID, int forWriting,
+ int checkUsage, ClientData *filePtr);
+#endif
+#endif /* MACOSX */
+#ifndef Tcl_GetPathType_TCL_DECLARED
+#define Tcl_GetPathType_TCL_DECLARED
/* 168 */
-EXTERN Tcl_PathType Tcl_GetPathType _ANSI_ARGS_((CONST char * path));
+EXTERN Tcl_PathType Tcl_GetPathType(CONST char *path);
+#endif
+#ifndef Tcl_Gets_TCL_DECLARED
+#define Tcl_Gets_TCL_DECLARED
/* 169 */
-EXTERN int Tcl_Gets _ANSI_ARGS_((Tcl_Channel chan,
- Tcl_DString * dsPtr));
+EXTERN int Tcl_Gets(Tcl_Channel chan, Tcl_DString *dsPtr);
+#endif
+#ifndef Tcl_GetsObj_TCL_DECLARED
+#define Tcl_GetsObj_TCL_DECLARED
/* 170 */
-EXTERN int Tcl_GetsObj _ANSI_ARGS_((Tcl_Channel chan,
- Tcl_Obj * objPtr));
+EXTERN int Tcl_GetsObj(Tcl_Channel chan, Tcl_Obj *objPtr);
+#endif
+#ifndef Tcl_GetServiceMode_TCL_DECLARED
+#define Tcl_GetServiceMode_TCL_DECLARED
/* 171 */
-EXTERN int Tcl_GetServiceMode _ANSI_ARGS_((void));
+EXTERN int Tcl_GetServiceMode(void);
+#endif
+#ifndef Tcl_GetSlave_TCL_DECLARED
+#define Tcl_GetSlave_TCL_DECLARED
/* 172 */
-EXTERN Tcl_Interp * Tcl_GetSlave _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * slaveName));
+EXTERN Tcl_Interp * Tcl_GetSlave(Tcl_Interp *interp,
+ CONST char *slaveName);
+#endif
+#ifndef Tcl_GetStdChannel_TCL_DECLARED
+#define Tcl_GetStdChannel_TCL_DECLARED
/* 173 */
-EXTERN Tcl_Channel Tcl_GetStdChannel _ANSI_ARGS_((int type));
+EXTERN Tcl_Channel Tcl_GetStdChannel(int type);
+#endif
+#ifndef Tcl_GetStringResult_TCL_DECLARED
+#define Tcl_GetStringResult_TCL_DECLARED
/* 174 */
-EXTERN CONST84_RETURN char * Tcl_GetStringResult _ANSI_ARGS_((
- Tcl_Interp * interp));
+EXTERN CONST84_RETURN char * Tcl_GetStringResult(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_GetVar_TCL_DECLARED
+#define Tcl_GetVar_TCL_DECLARED
/* 175 */
-EXTERN CONST84_RETURN char * Tcl_GetVar _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * varName, int flags));
+EXTERN CONST84_RETURN char * Tcl_GetVar(Tcl_Interp *interp,
+ CONST char *varName, int flags);
+#endif
+#ifndef Tcl_GetVar2_TCL_DECLARED
+#define Tcl_GetVar2_TCL_DECLARED
/* 176 */
-EXTERN CONST84_RETURN char * Tcl_GetVar2 _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * part1, CONST char * part2,
- int flags));
+EXTERN CONST84_RETURN char * Tcl_GetVar2(Tcl_Interp *interp,
+ CONST char *part1, CONST char *part2,
+ int flags);
+#endif
+#ifndef Tcl_GlobalEval_TCL_DECLARED
+#define Tcl_GlobalEval_TCL_DECLARED
/* 177 */
-EXTERN int Tcl_GlobalEval _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * command));
+EXTERN int Tcl_GlobalEval(Tcl_Interp *interp,
+ CONST char *command);
+#endif
+#ifndef Tcl_GlobalEvalObj_TCL_DECLARED
+#define Tcl_GlobalEvalObj_TCL_DECLARED
/* 178 */
-EXTERN int Tcl_GlobalEvalObj _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * objPtr));
+EXTERN int Tcl_GlobalEvalObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr);
+#endif
+#ifndef Tcl_HideCommand_TCL_DECLARED
+#define Tcl_HideCommand_TCL_DECLARED
/* 179 */
-EXTERN int Tcl_HideCommand _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * cmdName,
- CONST char * hiddenCmdToken));
+EXTERN int Tcl_HideCommand(Tcl_Interp *interp,
+ CONST char *cmdName,
+ CONST char *hiddenCmdToken);
+#endif
+#ifndef Tcl_Init_TCL_DECLARED
+#define Tcl_Init_TCL_DECLARED
/* 180 */
-EXTERN int Tcl_Init _ANSI_ARGS_((Tcl_Interp * interp));
+EXTERN int Tcl_Init(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_InitHashTable_TCL_DECLARED
+#define Tcl_InitHashTable_TCL_DECLARED
/* 181 */
-EXTERN void Tcl_InitHashTable _ANSI_ARGS_((
- Tcl_HashTable * tablePtr, int keyType));
+EXTERN void Tcl_InitHashTable(Tcl_HashTable *tablePtr,
+ int keyType);
+#endif
+#ifndef Tcl_InputBlocked_TCL_DECLARED
+#define Tcl_InputBlocked_TCL_DECLARED
/* 182 */
-EXTERN int Tcl_InputBlocked _ANSI_ARGS_((Tcl_Channel chan));
+EXTERN int Tcl_InputBlocked(Tcl_Channel chan);
+#endif
+#ifndef Tcl_InputBuffered_TCL_DECLARED
+#define Tcl_InputBuffered_TCL_DECLARED
/* 183 */
-EXTERN int Tcl_InputBuffered _ANSI_ARGS_((Tcl_Channel chan));
+EXTERN int Tcl_InputBuffered(Tcl_Channel chan);
+#endif
+#ifndef Tcl_InterpDeleted_TCL_DECLARED
+#define Tcl_InterpDeleted_TCL_DECLARED
/* 184 */
-EXTERN int Tcl_InterpDeleted _ANSI_ARGS_((Tcl_Interp * interp));
+EXTERN int Tcl_InterpDeleted(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_IsSafe_TCL_DECLARED
+#define Tcl_IsSafe_TCL_DECLARED
/* 185 */
-EXTERN int Tcl_IsSafe _ANSI_ARGS_((Tcl_Interp * interp));
+EXTERN int Tcl_IsSafe(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_JoinPath_TCL_DECLARED
+#define Tcl_JoinPath_TCL_DECLARED
/* 186 */
-EXTERN char * Tcl_JoinPath _ANSI_ARGS_((int argc,
- CONST84 char * CONST * argv,
- Tcl_DString * resultPtr));
+EXTERN char * Tcl_JoinPath(int argc, CONST84 char *CONST *argv,
+ Tcl_DString *resultPtr);
+#endif
+#ifndef Tcl_LinkVar_TCL_DECLARED
+#define Tcl_LinkVar_TCL_DECLARED
/* 187 */
-EXTERN int Tcl_LinkVar _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * varName, char * addr, int type));
+EXTERN int Tcl_LinkVar(Tcl_Interp *interp, CONST char *varName,
+ char *addr, int type);
+#endif
/* Slot 188 is reserved */
+#ifndef Tcl_MakeFileChannel_TCL_DECLARED
+#define Tcl_MakeFileChannel_TCL_DECLARED
/* 189 */
-EXTERN Tcl_Channel Tcl_MakeFileChannel _ANSI_ARGS_((ClientData handle,
- int mode));
+EXTERN Tcl_Channel Tcl_MakeFileChannel(ClientData handle, int mode);
+#endif
+#ifndef Tcl_MakeSafe_TCL_DECLARED
+#define Tcl_MakeSafe_TCL_DECLARED
/* 190 */
-EXTERN int Tcl_MakeSafe _ANSI_ARGS_((Tcl_Interp * interp));
+EXTERN int Tcl_MakeSafe(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_MakeTcpClientChannel_TCL_DECLARED
+#define Tcl_MakeTcpClientChannel_TCL_DECLARED
/* 191 */
-EXTERN Tcl_Channel Tcl_MakeTcpClientChannel _ANSI_ARGS_((
- ClientData tcpSocket));
+EXTERN Tcl_Channel Tcl_MakeTcpClientChannel(ClientData tcpSocket);
+#endif
+#ifndef Tcl_Merge_TCL_DECLARED
+#define Tcl_Merge_TCL_DECLARED
/* 192 */
-EXTERN char * Tcl_Merge _ANSI_ARGS_((int argc,
- CONST84 char * CONST * argv));
+EXTERN char * Tcl_Merge(int argc, CONST84 char *CONST *argv);
+#endif
+#ifndef Tcl_NextHashEntry_TCL_DECLARED
+#define Tcl_NextHashEntry_TCL_DECLARED
/* 193 */
-EXTERN Tcl_HashEntry * Tcl_NextHashEntry _ANSI_ARGS_((
- Tcl_HashSearch * searchPtr));
+EXTERN Tcl_HashEntry * Tcl_NextHashEntry(Tcl_HashSearch *searchPtr);
+#endif
+#ifndef Tcl_NotifyChannel_TCL_DECLARED
+#define Tcl_NotifyChannel_TCL_DECLARED
/* 194 */
-EXTERN void Tcl_NotifyChannel _ANSI_ARGS_((Tcl_Channel channel,
- int mask));
+EXTERN void Tcl_NotifyChannel(Tcl_Channel channel, int mask);
+#endif
+#ifndef Tcl_ObjGetVar2_TCL_DECLARED
+#define Tcl_ObjGetVar2_TCL_DECLARED
/* 195 */
-EXTERN Tcl_Obj * Tcl_ObjGetVar2 _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr,
- int flags));
+EXTERN Tcl_Obj * Tcl_ObjGetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
+ Tcl_Obj *part2Ptr, int flags);
+#endif
+#ifndef Tcl_ObjSetVar2_TCL_DECLARED
+#define Tcl_ObjSetVar2_TCL_DECLARED
/* 196 */
-EXTERN Tcl_Obj * Tcl_ObjSetVar2 _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr,
- Tcl_Obj * newValuePtr, int flags));
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
-/* 197 */
-EXTERN Tcl_Channel Tcl_OpenCommandChannel _ANSI_ARGS_((
- Tcl_Interp * interp, int argc,
- CONST84 char ** argv, int flags));
-#endif /* UNIX */
-#ifdef __WIN32__
+EXTERN Tcl_Obj * Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
+ Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr,
+ int flags);
+#endif
+#ifndef Tcl_OpenCommandChannel_TCL_DECLARED
+#define Tcl_OpenCommandChannel_TCL_DECLARED
/* 197 */
-EXTERN Tcl_Channel Tcl_OpenCommandChannel _ANSI_ARGS_((
- Tcl_Interp * interp, int argc,
- CONST84 char ** argv, int flags));
-#endif /* __WIN32__ */
+EXTERN Tcl_Channel Tcl_OpenCommandChannel(Tcl_Interp *interp, int argc,
+ CONST84 char **argv, int flags);
+#endif
+#ifndef Tcl_OpenFileChannel_TCL_DECLARED
+#define Tcl_OpenFileChannel_TCL_DECLARED
/* 198 */
-EXTERN Tcl_Channel Tcl_OpenFileChannel _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * fileName,
- CONST char * modeString, int permissions));
+EXTERN Tcl_Channel Tcl_OpenFileChannel(Tcl_Interp *interp,
+ CONST char *fileName, CONST char *modeString,
+ int permissions);
+#endif
+#ifndef Tcl_OpenTcpClient_TCL_DECLARED
+#define Tcl_OpenTcpClient_TCL_DECLARED
/* 199 */
-EXTERN Tcl_Channel Tcl_OpenTcpClient _ANSI_ARGS_((Tcl_Interp * interp,
- int port, CONST char * address,
- CONST char * myaddr, int myport, int async));
+EXTERN Tcl_Channel Tcl_OpenTcpClient(Tcl_Interp *interp, int port,
+ CONST char *address, CONST char *myaddr,
+ int myport, int async);
+#endif
+#ifndef Tcl_OpenTcpServer_TCL_DECLARED
+#define Tcl_OpenTcpServer_TCL_DECLARED
/* 200 */
-EXTERN Tcl_Channel Tcl_OpenTcpServer _ANSI_ARGS_((Tcl_Interp * interp,
- int port, CONST char * host,
- Tcl_TcpAcceptProc * acceptProc,
- ClientData callbackData));
+EXTERN Tcl_Channel Tcl_OpenTcpServer(Tcl_Interp *interp, int port,
+ CONST char *host,
+ Tcl_TcpAcceptProc *acceptProc,
+ ClientData callbackData);
+#endif
+#ifndef Tcl_Preserve_TCL_DECLARED
+#define Tcl_Preserve_TCL_DECLARED
/* 201 */
-EXTERN void Tcl_Preserve _ANSI_ARGS_((ClientData data));
+EXTERN void Tcl_Preserve(ClientData data);
+#endif
+#ifndef Tcl_PrintDouble_TCL_DECLARED
+#define Tcl_PrintDouble_TCL_DECLARED
/* 202 */
-EXTERN void Tcl_PrintDouble _ANSI_ARGS_((Tcl_Interp * interp,
- double value, char * dst));
+EXTERN void Tcl_PrintDouble(Tcl_Interp *interp, double value,
+ char *dst);
+#endif
+#ifndef Tcl_PutEnv_TCL_DECLARED
+#define Tcl_PutEnv_TCL_DECLARED
/* 203 */
-EXTERN int Tcl_PutEnv _ANSI_ARGS_((CONST char * string));
+EXTERN int Tcl_PutEnv(CONST char *assignment);
+#endif
+#ifndef Tcl_PosixError_TCL_DECLARED
+#define Tcl_PosixError_TCL_DECLARED
/* 204 */
-EXTERN CONST84_RETURN char * Tcl_PosixError _ANSI_ARGS_((Tcl_Interp * interp));
+EXTERN CONST84_RETURN char * Tcl_PosixError(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_QueueEvent_TCL_DECLARED
+#define Tcl_QueueEvent_TCL_DECLARED
/* 205 */
-EXTERN void Tcl_QueueEvent _ANSI_ARGS_((Tcl_Event * evPtr,
- Tcl_QueuePosition position));
+EXTERN void Tcl_QueueEvent(Tcl_Event *evPtr,
+ Tcl_QueuePosition position);
+#endif
+#ifndef Tcl_Read_TCL_DECLARED
+#define Tcl_Read_TCL_DECLARED
/* 206 */
-EXTERN int Tcl_Read _ANSI_ARGS_((Tcl_Channel chan,
- char * bufPtr, int toRead));
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
-/* 207 */
-EXTERN void Tcl_ReapDetachedProcs _ANSI_ARGS_((void));
-#endif /* UNIX */
-#ifdef __WIN32__
+EXTERN int Tcl_Read(Tcl_Channel chan, char *bufPtr, int toRead);
+#endif
+#ifndef Tcl_ReapDetachedProcs_TCL_DECLARED
+#define Tcl_ReapDetachedProcs_TCL_DECLARED
/* 207 */
-EXTERN void Tcl_ReapDetachedProcs _ANSI_ARGS_((void));
-#endif /* __WIN32__ */
+EXTERN void Tcl_ReapDetachedProcs(void);
+#endif
+#ifndef Tcl_RecordAndEval_TCL_DECLARED
+#define Tcl_RecordAndEval_TCL_DECLARED
/* 208 */
-EXTERN int Tcl_RecordAndEval _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * cmd, int flags));
+EXTERN int Tcl_RecordAndEval(Tcl_Interp *interp,
+ CONST char *cmd, int flags);
+#endif
+#ifndef Tcl_RecordAndEvalObj_TCL_DECLARED
+#define Tcl_RecordAndEvalObj_TCL_DECLARED
/* 209 */
-EXTERN int Tcl_RecordAndEvalObj _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Obj * cmdPtr,
- int flags));
+EXTERN int Tcl_RecordAndEvalObj(Tcl_Interp *interp,
+ Tcl_Obj *cmdPtr, int flags);
+#endif
+#ifndef Tcl_RegisterChannel_TCL_DECLARED
+#define Tcl_RegisterChannel_TCL_DECLARED
/* 210 */
-EXTERN void Tcl_RegisterChannel _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Channel chan));
+EXTERN void Tcl_RegisterChannel(Tcl_Interp *interp,
+ Tcl_Channel chan);
+#endif
+#ifndef Tcl_RegisterObjType_TCL_DECLARED
+#define Tcl_RegisterObjType_TCL_DECLARED
/* 211 */
-EXTERN void Tcl_RegisterObjType _ANSI_ARGS_((
- Tcl_ObjType * typePtr));
+EXTERN void Tcl_RegisterObjType(Tcl_ObjType *typePtr);
+#endif
+#ifndef Tcl_RegExpCompile_TCL_DECLARED
+#define Tcl_RegExpCompile_TCL_DECLARED
/* 212 */
-EXTERN Tcl_RegExp Tcl_RegExpCompile _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * string));
+EXTERN Tcl_RegExp Tcl_RegExpCompile(Tcl_Interp *interp,
+ CONST char *pattern);
+#endif
+#ifndef Tcl_RegExpExec_TCL_DECLARED
+#define Tcl_RegExpExec_TCL_DECLARED
/* 213 */
-EXTERN int Tcl_RegExpExec _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_RegExp regexp, CONST char * str,
- CONST char * start));
+EXTERN int Tcl_RegExpExec(Tcl_Interp *interp, Tcl_RegExp regexp,
+ CONST char *text, CONST char *start);
+#endif
+#ifndef Tcl_RegExpMatch_TCL_DECLARED
+#define Tcl_RegExpMatch_TCL_DECLARED
/* 214 */
-EXTERN int Tcl_RegExpMatch _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * str, CONST char * pattern));
+EXTERN int Tcl_RegExpMatch(Tcl_Interp *interp, CONST char *text,
+ CONST char *pattern);
+#endif
+#ifndef Tcl_RegExpRange_TCL_DECLARED
+#define Tcl_RegExpRange_TCL_DECLARED
/* 215 */
-EXTERN void Tcl_RegExpRange _ANSI_ARGS_((Tcl_RegExp regexp,
- int index, CONST84 char ** startPtr,
- CONST84 char ** endPtr));
+EXTERN void Tcl_RegExpRange(Tcl_RegExp regexp, int index,
+ CONST84 char **startPtr,
+ CONST84 char **endPtr);
+#endif
+#ifndef Tcl_Release_TCL_DECLARED
+#define Tcl_Release_TCL_DECLARED
/* 216 */
-EXTERN void Tcl_Release _ANSI_ARGS_((ClientData clientData));
+EXTERN void Tcl_Release(ClientData clientData);
+#endif
+#ifndef Tcl_ResetResult_TCL_DECLARED
+#define Tcl_ResetResult_TCL_DECLARED
/* 217 */
-EXTERN void Tcl_ResetResult _ANSI_ARGS_((Tcl_Interp * interp));
+EXTERN void Tcl_ResetResult(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_ScanElement_TCL_DECLARED
+#define Tcl_ScanElement_TCL_DECLARED
/* 218 */
-EXTERN int Tcl_ScanElement _ANSI_ARGS_((CONST char * str,
- int * flagPtr));
+EXTERN int Tcl_ScanElement(CONST char *src, int *flagPtr);
+#endif
+#ifndef Tcl_ScanCountedElement_TCL_DECLARED
+#define Tcl_ScanCountedElement_TCL_DECLARED
/* 219 */
-EXTERN int Tcl_ScanCountedElement _ANSI_ARGS_((CONST char * str,
- int length, int * flagPtr));
+EXTERN int Tcl_ScanCountedElement(CONST char *src, int length,
+ int *flagPtr);
+#endif
+#ifndef Tcl_SeekOld_TCL_DECLARED
+#define Tcl_SeekOld_TCL_DECLARED
/* 220 */
-EXTERN int Tcl_SeekOld _ANSI_ARGS_((Tcl_Channel chan,
- int offset, int mode));
+EXTERN int Tcl_SeekOld(Tcl_Channel chan, int offset, int mode);
+#endif
+#ifndef Tcl_ServiceAll_TCL_DECLARED
+#define Tcl_ServiceAll_TCL_DECLARED
/* 221 */
-EXTERN int Tcl_ServiceAll _ANSI_ARGS_((void));
+EXTERN int Tcl_ServiceAll(void);
+#endif
+#ifndef Tcl_ServiceEvent_TCL_DECLARED
+#define Tcl_ServiceEvent_TCL_DECLARED
/* 222 */
-EXTERN int Tcl_ServiceEvent _ANSI_ARGS_((int flags));
+EXTERN int Tcl_ServiceEvent(int flags);
+#endif
+#ifndef Tcl_SetAssocData_TCL_DECLARED
+#define Tcl_SetAssocData_TCL_DECLARED
/* 223 */
-EXTERN void Tcl_SetAssocData _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * name,
- Tcl_InterpDeleteProc * proc,
- ClientData clientData));
+EXTERN void Tcl_SetAssocData(Tcl_Interp *interp,
+ CONST char *name, Tcl_InterpDeleteProc *proc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_SetChannelBufferSize_TCL_DECLARED
+#define Tcl_SetChannelBufferSize_TCL_DECLARED
/* 224 */
-EXTERN void Tcl_SetChannelBufferSize _ANSI_ARGS_((
- Tcl_Channel chan, int sz));
+EXTERN void Tcl_SetChannelBufferSize(Tcl_Channel chan, int sz);
+#endif
+#ifndef Tcl_SetChannelOption_TCL_DECLARED
+#define Tcl_SetChannelOption_TCL_DECLARED
/* 225 */
-EXTERN int Tcl_SetChannelOption _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Channel chan,
- CONST char * optionName,
- CONST char * newValue));
+EXTERN int Tcl_SetChannelOption(Tcl_Interp *interp,
+ Tcl_Channel chan, CONST char *optionName,
+ CONST char *newValue);
+#endif
+#ifndef Tcl_SetCommandInfo_TCL_DECLARED
+#define Tcl_SetCommandInfo_TCL_DECLARED
/* 226 */
-EXTERN int Tcl_SetCommandInfo _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * cmdName,
- CONST Tcl_CmdInfo * infoPtr));
+EXTERN int Tcl_SetCommandInfo(Tcl_Interp *interp,
+ CONST char *cmdName,
+ CONST Tcl_CmdInfo *infoPtr);
+#endif
+#ifndef Tcl_SetErrno_TCL_DECLARED
+#define Tcl_SetErrno_TCL_DECLARED
/* 227 */
-EXTERN void Tcl_SetErrno _ANSI_ARGS_((int err));
+EXTERN void Tcl_SetErrno(int err);
+#endif
+#ifndef Tcl_SetErrorCode_TCL_DECLARED
+#define Tcl_SetErrorCode_TCL_DECLARED
/* 228 */
-EXTERN void Tcl_SetErrorCode _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp));
+EXTERN void Tcl_SetErrorCode(Tcl_Interp *interp, ...);
+#endif
+#ifndef Tcl_SetMaxBlockTime_TCL_DECLARED
+#define Tcl_SetMaxBlockTime_TCL_DECLARED
/* 229 */
-EXTERN void Tcl_SetMaxBlockTime _ANSI_ARGS_((Tcl_Time * timePtr));
+EXTERN void Tcl_SetMaxBlockTime(Tcl_Time *timePtr);
+#endif
+#ifndef Tcl_SetPanicProc_TCL_DECLARED
+#define Tcl_SetPanicProc_TCL_DECLARED
/* 230 */
-EXTERN void Tcl_SetPanicProc _ANSI_ARGS_((
- Tcl_PanicProc * panicProc));
+EXTERN void Tcl_SetPanicProc(Tcl_PanicProc *panicProc);
+#endif
+#ifndef Tcl_SetRecursionLimit_TCL_DECLARED
+#define Tcl_SetRecursionLimit_TCL_DECLARED
/* 231 */
-EXTERN int Tcl_SetRecursionLimit _ANSI_ARGS_((
- Tcl_Interp * interp, int depth));
+EXTERN int Tcl_SetRecursionLimit(Tcl_Interp *interp, int depth);
+#endif
+#ifndef Tcl_SetResult_TCL_DECLARED
+#define Tcl_SetResult_TCL_DECLARED
/* 232 */
-EXTERN void Tcl_SetResult _ANSI_ARGS_((Tcl_Interp * interp,
- char * str, Tcl_FreeProc * freeProc));
+EXTERN void Tcl_SetResult(Tcl_Interp *interp, char *result,
+ Tcl_FreeProc *freeProc);
+#endif
+#ifndef Tcl_SetServiceMode_TCL_DECLARED
+#define Tcl_SetServiceMode_TCL_DECLARED
/* 233 */
-EXTERN int Tcl_SetServiceMode _ANSI_ARGS_((int mode));
+EXTERN int Tcl_SetServiceMode(int mode);
+#endif
+#ifndef Tcl_SetObjErrorCode_TCL_DECLARED
+#define Tcl_SetObjErrorCode_TCL_DECLARED
/* 234 */
-EXTERN void Tcl_SetObjErrorCode _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * errorObjPtr));
+EXTERN void Tcl_SetObjErrorCode(Tcl_Interp *interp,
+ Tcl_Obj *errorObjPtr);
+#endif
+#ifndef Tcl_SetObjResult_TCL_DECLARED
+#define Tcl_SetObjResult_TCL_DECLARED
/* 235 */
-EXTERN void Tcl_SetObjResult _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * resultObjPtr));
+EXTERN void Tcl_SetObjResult(Tcl_Interp *interp,
+ Tcl_Obj *resultObjPtr);
+#endif
+#ifndef Tcl_SetStdChannel_TCL_DECLARED
+#define Tcl_SetStdChannel_TCL_DECLARED
/* 236 */
-EXTERN void Tcl_SetStdChannel _ANSI_ARGS_((Tcl_Channel channel,
- int type));
+EXTERN void Tcl_SetStdChannel(Tcl_Channel channel, int type);
+#endif
+#ifndef Tcl_SetVar_TCL_DECLARED
+#define Tcl_SetVar_TCL_DECLARED
/* 237 */
-EXTERN CONST84_RETURN char * Tcl_SetVar _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * varName, CONST char * newValue,
- int flags));
+EXTERN CONST84_RETURN char * Tcl_SetVar(Tcl_Interp *interp,
+ CONST char *varName, CONST char *newValue,
+ int flags);
+#endif
+#ifndef Tcl_SetVar2_TCL_DECLARED
+#define Tcl_SetVar2_TCL_DECLARED
/* 238 */
-EXTERN CONST84_RETURN char * Tcl_SetVar2 _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * part1, CONST char * part2,
- CONST char * newValue, int flags));
+EXTERN CONST84_RETURN char * Tcl_SetVar2(Tcl_Interp *interp,
+ CONST char *part1, CONST char *part2,
+ CONST char *newValue, int flags);
+#endif
+#ifndef Tcl_SignalId_TCL_DECLARED
+#define Tcl_SignalId_TCL_DECLARED
/* 239 */
-EXTERN CONST84_RETURN char * Tcl_SignalId _ANSI_ARGS_((int sig));
+EXTERN CONST84_RETURN char * Tcl_SignalId(int sig);
+#endif
+#ifndef Tcl_SignalMsg_TCL_DECLARED
+#define Tcl_SignalMsg_TCL_DECLARED
/* 240 */
-EXTERN CONST84_RETURN char * Tcl_SignalMsg _ANSI_ARGS_((int sig));
+EXTERN CONST84_RETURN char * Tcl_SignalMsg(int sig);
+#endif
+#ifndef Tcl_SourceRCFile_TCL_DECLARED
+#define Tcl_SourceRCFile_TCL_DECLARED
/* 241 */
-EXTERN void Tcl_SourceRCFile _ANSI_ARGS_((Tcl_Interp * interp));
+EXTERN void Tcl_SourceRCFile(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_SplitList_TCL_DECLARED
+#define Tcl_SplitList_TCL_DECLARED
/* 242 */
-EXTERN int Tcl_SplitList _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * listStr, int * argcPtr,
- CONST84 char *** argvPtr));
+EXTERN int Tcl_SplitList(Tcl_Interp *interp,
+ CONST char *listStr, int *argcPtr,
+ CONST84 char ***argvPtr);
+#endif
+#ifndef Tcl_SplitPath_TCL_DECLARED
+#define Tcl_SplitPath_TCL_DECLARED
/* 243 */
-EXTERN void Tcl_SplitPath _ANSI_ARGS_((CONST char * path,
- int * argcPtr, CONST84 char *** argvPtr));
+EXTERN void Tcl_SplitPath(CONST char *path, int *argcPtr,
+ CONST84 char ***argvPtr);
+#endif
+#ifndef Tcl_StaticPackage_TCL_DECLARED
+#define Tcl_StaticPackage_TCL_DECLARED
/* 244 */
-EXTERN void Tcl_StaticPackage _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * pkgName,
- Tcl_PackageInitProc * initProc,
- Tcl_PackageInitProc * safeInitProc));
+EXTERN void Tcl_StaticPackage(Tcl_Interp *interp,
+ CONST char *pkgName,
+ Tcl_PackageInitProc *initProc,
+ Tcl_PackageInitProc *safeInitProc);
+#endif
+#ifndef Tcl_StringMatch_TCL_DECLARED
+#define Tcl_StringMatch_TCL_DECLARED
/* 245 */
-EXTERN int Tcl_StringMatch _ANSI_ARGS_((CONST char * str,
- CONST char * pattern));
+EXTERN int Tcl_StringMatch(CONST char *str, CONST char *pattern);
+#endif
+#ifndef Tcl_TellOld_TCL_DECLARED
+#define Tcl_TellOld_TCL_DECLARED
/* 246 */
-EXTERN int Tcl_TellOld _ANSI_ARGS_((Tcl_Channel chan));
+EXTERN int Tcl_TellOld(Tcl_Channel chan);
+#endif
+#ifndef Tcl_TraceVar_TCL_DECLARED
+#define Tcl_TraceVar_TCL_DECLARED
/* 247 */
-EXTERN int Tcl_TraceVar _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * varName, int flags,
- Tcl_VarTraceProc * proc,
- ClientData clientData));
+EXTERN int Tcl_TraceVar(Tcl_Interp *interp, CONST char *varName,
+ int flags, Tcl_VarTraceProc *proc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_TraceVar2_TCL_DECLARED
+#define Tcl_TraceVar2_TCL_DECLARED
/* 248 */
-EXTERN int Tcl_TraceVar2 _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * part1, CONST char * part2,
- int flags, Tcl_VarTraceProc * proc,
- ClientData clientData));
+EXTERN int Tcl_TraceVar2(Tcl_Interp *interp, CONST char *part1,
+ CONST char *part2, int flags,
+ Tcl_VarTraceProc *proc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_TranslateFileName_TCL_DECLARED
+#define Tcl_TranslateFileName_TCL_DECLARED
/* 249 */
-EXTERN char * Tcl_TranslateFileName _ANSI_ARGS_((
- Tcl_Interp * interp, CONST char * name,
- Tcl_DString * bufferPtr));
+EXTERN char * Tcl_TranslateFileName(Tcl_Interp *interp,
+ CONST char *name, Tcl_DString *bufferPtr);
+#endif
+#ifndef Tcl_Ungets_TCL_DECLARED
+#define Tcl_Ungets_TCL_DECLARED
/* 250 */
-EXTERN int Tcl_Ungets _ANSI_ARGS_((Tcl_Channel chan,
- CONST char * str, int len, int atHead));
+EXTERN int Tcl_Ungets(Tcl_Channel chan, CONST char *str,
+ int len, int atHead);
+#endif
+#ifndef Tcl_UnlinkVar_TCL_DECLARED
+#define Tcl_UnlinkVar_TCL_DECLARED
/* 251 */
-EXTERN void Tcl_UnlinkVar _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * varName));
+EXTERN void Tcl_UnlinkVar(Tcl_Interp *interp,
+ CONST char *varName);
+#endif
+#ifndef Tcl_UnregisterChannel_TCL_DECLARED
+#define Tcl_UnregisterChannel_TCL_DECLARED
/* 252 */
-EXTERN int Tcl_UnregisterChannel _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Channel chan));
+EXTERN int Tcl_UnregisterChannel(Tcl_Interp *interp,
+ Tcl_Channel chan);
+#endif
+#ifndef Tcl_UnsetVar_TCL_DECLARED
+#define Tcl_UnsetVar_TCL_DECLARED
/* 253 */
-EXTERN int Tcl_UnsetVar _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * varName, int flags));
+EXTERN int Tcl_UnsetVar(Tcl_Interp *interp, CONST char *varName,
+ int flags);
+#endif
+#ifndef Tcl_UnsetVar2_TCL_DECLARED
+#define Tcl_UnsetVar2_TCL_DECLARED
/* 254 */
-EXTERN int Tcl_UnsetVar2 _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * part1, CONST char * part2,
- int flags));
+EXTERN int Tcl_UnsetVar2(Tcl_Interp *interp, CONST char *part1,
+ CONST char *part2, int flags);
+#endif
+#ifndef Tcl_UntraceVar_TCL_DECLARED
+#define Tcl_UntraceVar_TCL_DECLARED
/* 255 */
-EXTERN void Tcl_UntraceVar _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * varName, int flags,
- Tcl_VarTraceProc * proc,
- ClientData clientData));
+EXTERN void Tcl_UntraceVar(Tcl_Interp *interp,
+ CONST char *varName, int flags,
+ Tcl_VarTraceProc *proc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_UntraceVar2_TCL_DECLARED
+#define Tcl_UntraceVar2_TCL_DECLARED
/* 256 */
-EXTERN void Tcl_UntraceVar2 _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * part1, CONST char * part2,
- int flags, Tcl_VarTraceProc * proc,
- ClientData clientData));
+EXTERN void Tcl_UntraceVar2(Tcl_Interp *interp,
+ CONST char *part1, CONST char *part2,
+ int flags, Tcl_VarTraceProc *proc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_UpdateLinkedVar_TCL_DECLARED
+#define Tcl_UpdateLinkedVar_TCL_DECLARED
/* 257 */
-EXTERN void Tcl_UpdateLinkedVar _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * varName));
+EXTERN void Tcl_UpdateLinkedVar(Tcl_Interp *interp,
+ CONST char *varName);
+#endif
+#ifndef Tcl_UpVar_TCL_DECLARED
+#define Tcl_UpVar_TCL_DECLARED
/* 258 */
-EXTERN int Tcl_UpVar _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * frameName, CONST char * varName,
- CONST char * localName, int flags));
+EXTERN int Tcl_UpVar(Tcl_Interp *interp, CONST char *frameName,
+ CONST char *varName, CONST char *localName,
+ int flags);
+#endif
+#ifndef Tcl_UpVar2_TCL_DECLARED
+#define Tcl_UpVar2_TCL_DECLARED
/* 259 */
-EXTERN int Tcl_UpVar2 _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * frameName, CONST char * part1,
- CONST char * part2, CONST char * localName,
- int flags));
+EXTERN int Tcl_UpVar2(Tcl_Interp *interp, CONST char *frameName,
+ CONST char *part1, CONST char *part2,
+ CONST char *localName, int flags);
+#endif
+#ifndef Tcl_VarEval_TCL_DECLARED
+#define Tcl_VarEval_TCL_DECLARED
/* 260 */
-EXTERN int Tcl_VarEval _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp));
+EXTERN int Tcl_VarEval(Tcl_Interp *interp, ...);
+#endif
+#ifndef Tcl_VarTraceInfo_TCL_DECLARED
+#define Tcl_VarTraceInfo_TCL_DECLARED
/* 261 */
-EXTERN ClientData Tcl_VarTraceInfo _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * varName, int flags,
- Tcl_VarTraceProc * procPtr,
- ClientData prevClientData));
+EXTERN ClientData Tcl_VarTraceInfo(Tcl_Interp *interp,
+ CONST char *varName, int flags,
+ Tcl_VarTraceProc *procPtr,
+ ClientData prevClientData);
+#endif
+#ifndef Tcl_VarTraceInfo2_TCL_DECLARED
+#define Tcl_VarTraceInfo2_TCL_DECLARED
/* 262 */
-EXTERN ClientData Tcl_VarTraceInfo2 _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * part1, CONST char * part2,
- int flags, Tcl_VarTraceProc * procPtr,
- ClientData prevClientData));
+EXTERN ClientData Tcl_VarTraceInfo2(Tcl_Interp *interp,
+ CONST char *part1, CONST char *part2,
+ int flags, Tcl_VarTraceProc *procPtr,
+ ClientData prevClientData);
+#endif
+#ifndef Tcl_Write_TCL_DECLARED
+#define Tcl_Write_TCL_DECLARED
/* 263 */
-EXTERN int Tcl_Write _ANSI_ARGS_((Tcl_Channel chan,
- CONST char * s, int slen));
+EXTERN int Tcl_Write(Tcl_Channel chan, CONST char *s, int slen);
+#endif
+#ifndef Tcl_WrongNumArgs_TCL_DECLARED
+#define Tcl_WrongNumArgs_TCL_DECLARED
/* 264 */
-EXTERN void Tcl_WrongNumArgs _ANSI_ARGS_((Tcl_Interp * interp,
- int objc, Tcl_Obj *CONST objv[],
- CONST char * message));
+EXTERN void Tcl_WrongNumArgs(Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[], CONST char *message);
+#endif
+#ifndef Tcl_DumpActiveMemory_TCL_DECLARED
+#define Tcl_DumpActiveMemory_TCL_DECLARED
/* 265 */
-EXTERN int Tcl_DumpActiveMemory _ANSI_ARGS_((
- CONST char * fileName));
+EXTERN int Tcl_DumpActiveMemory(CONST char *fileName);
+#endif
+#ifndef Tcl_ValidateAllMemory_TCL_DECLARED
+#define Tcl_ValidateAllMemory_TCL_DECLARED
/* 266 */
-EXTERN void Tcl_ValidateAllMemory _ANSI_ARGS_((CONST char * file,
- int line));
+EXTERN void Tcl_ValidateAllMemory(CONST char *file, int line);
+#endif
+#ifndef Tcl_AppendResultVA_TCL_DECLARED
+#define Tcl_AppendResultVA_TCL_DECLARED
/* 267 */
-EXTERN void Tcl_AppendResultVA _ANSI_ARGS_((Tcl_Interp * interp,
- va_list argList));
+EXTERN void Tcl_AppendResultVA(Tcl_Interp *interp,
+ va_list argList);
+#endif
+#ifndef Tcl_AppendStringsToObjVA_TCL_DECLARED
+#define Tcl_AppendStringsToObjVA_TCL_DECLARED
/* 268 */
-EXTERN void Tcl_AppendStringsToObjVA _ANSI_ARGS_((
- Tcl_Obj * objPtr, va_list argList));
+EXTERN void Tcl_AppendStringsToObjVA(Tcl_Obj *objPtr,
+ va_list argList);
+#endif
+#ifndef Tcl_HashStats_TCL_DECLARED
+#define Tcl_HashStats_TCL_DECLARED
/* 269 */
-EXTERN CONST84_RETURN char * Tcl_HashStats _ANSI_ARGS_((
- Tcl_HashTable * tablePtr));
+EXTERN char * Tcl_HashStats(Tcl_HashTable *tablePtr);
+#endif
+#ifndef Tcl_ParseVar_TCL_DECLARED
+#define Tcl_ParseVar_TCL_DECLARED
/* 270 */
-EXTERN CONST84_RETURN char * Tcl_ParseVar _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * str, CONST84 char ** termPtr));
+EXTERN CONST84_RETURN char * Tcl_ParseVar(Tcl_Interp *interp,
+ CONST char *start, CONST84 char **termPtr);
+#endif
+#ifndef Tcl_PkgPresent_TCL_DECLARED
+#define Tcl_PkgPresent_TCL_DECLARED
/* 271 */
-EXTERN CONST84_RETURN char * Tcl_PkgPresent _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * name, CONST char * version,
- int exact));
+EXTERN CONST84_RETURN char * Tcl_PkgPresent(Tcl_Interp *interp,
+ CONST char *name, CONST char *version,
+ int exact);
+#endif
+#ifndef Tcl_PkgPresentEx_TCL_DECLARED
+#define Tcl_PkgPresentEx_TCL_DECLARED
/* 272 */
-EXTERN CONST84_RETURN char * Tcl_PkgPresentEx _ANSI_ARGS_((
- Tcl_Interp * interp, CONST char * name,
- CONST char * version, int exact,
- ClientData * clientDataPtr));
+EXTERN CONST84_RETURN char * Tcl_PkgPresentEx(Tcl_Interp *interp,
+ CONST char *name, CONST char *version,
+ int exact, ClientData *clientDataPtr);
+#endif
+#ifndef Tcl_PkgProvide_TCL_DECLARED
+#define Tcl_PkgProvide_TCL_DECLARED
/* 273 */
-EXTERN int Tcl_PkgProvide _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * name, CONST char * version));
+EXTERN int Tcl_PkgProvide(Tcl_Interp *interp, CONST char *name,
+ CONST char *version);
+#endif
+#ifndef Tcl_PkgRequire_TCL_DECLARED
+#define Tcl_PkgRequire_TCL_DECLARED
/* 274 */
-EXTERN CONST84_RETURN char * Tcl_PkgRequire _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * name, CONST char * version,
- int exact));
+EXTERN CONST84_RETURN char * Tcl_PkgRequire(Tcl_Interp *interp,
+ CONST char *name, CONST char *version,
+ int exact);
+#endif
+#ifndef Tcl_SetErrorCodeVA_TCL_DECLARED
+#define Tcl_SetErrorCodeVA_TCL_DECLARED
/* 275 */
-EXTERN void Tcl_SetErrorCodeVA _ANSI_ARGS_((Tcl_Interp * interp,
- va_list argList));
+EXTERN void Tcl_SetErrorCodeVA(Tcl_Interp *interp,
+ va_list argList);
+#endif
+#ifndef Tcl_VarEvalVA_TCL_DECLARED
+#define Tcl_VarEvalVA_TCL_DECLARED
/* 276 */
-EXTERN int Tcl_VarEvalVA _ANSI_ARGS_((Tcl_Interp * interp,
- va_list argList));
+EXTERN int Tcl_VarEvalVA(Tcl_Interp *interp, va_list argList);
+#endif
+#ifndef Tcl_WaitPid_TCL_DECLARED
+#define Tcl_WaitPid_TCL_DECLARED
/* 277 */
-EXTERN Tcl_Pid Tcl_WaitPid _ANSI_ARGS_((Tcl_Pid pid, int * statPtr,
- int options));
+EXTERN Tcl_Pid Tcl_WaitPid(Tcl_Pid pid, int *statPtr, int options);
+#endif
+#ifndef Tcl_PanicVA_TCL_DECLARED
+#define Tcl_PanicVA_TCL_DECLARED
/* 278 */
-EXTERN void Tcl_PanicVA _ANSI_ARGS_((CONST char * format,
- va_list argList));
+EXTERN void Tcl_PanicVA(CONST char *format, va_list argList);
+#endif
+#ifndef Tcl_GetVersion_TCL_DECLARED
+#define Tcl_GetVersion_TCL_DECLARED
/* 279 */
-EXTERN void Tcl_GetVersion _ANSI_ARGS_((int * major, int * minor,
- int * patchLevel, int * type));
+EXTERN void Tcl_GetVersion(int *major, int *minor,
+ int *patchLevel, int *type);
+#endif
+#ifndef Tcl_InitMemory_TCL_DECLARED
+#define Tcl_InitMemory_TCL_DECLARED
/* 280 */
-EXTERN void Tcl_InitMemory _ANSI_ARGS_((Tcl_Interp * interp));
+EXTERN void Tcl_InitMemory(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_StackChannel_TCL_DECLARED
+#define Tcl_StackChannel_TCL_DECLARED
/* 281 */
-EXTERN Tcl_Channel Tcl_StackChannel _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_ChannelType * typePtr,
- ClientData instanceData, int mask,
- Tcl_Channel prevChan));
+EXTERN Tcl_Channel Tcl_StackChannel(Tcl_Interp *interp,
+ Tcl_ChannelType *typePtr,
+ ClientData instanceData, int mask,
+ Tcl_Channel prevChan);
+#endif
+#ifndef Tcl_UnstackChannel_TCL_DECLARED
+#define Tcl_UnstackChannel_TCL_DECLARED
/* 282 */
-EXTERN int Tcl_UnstackChannel _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Channel chan));
+EXTERN int Tcl_UnstackChannel(Tcl_Interp *interp,
+ Tcl_Channel chan);
+#endif
+#ifndef Tcl_GetStackedChannel_TCL_DECLARED
+#define Tcl_GetStackedChannel_TCL_DECLARED
/* 283 */
-EXTERN Tcl_Channel Tcl_GetStackedChannel _ANSI_ARGS_((Tcl_Channel chan));
+EXTERN Tcl_Channel Tcl_GetStackedChannel(Tcl_Channel chan);
+#endif
+#ifndef Tcl_SetMainLoop_TCL_DECLARED
+#define Tcl_SetMainLoop_TCL_DECLARED
/* 284 */
-EXTERN void Tcl_SetMainLoop _ANSI_ARGS_((Tcl_MainLoopProc * proc));
+EXTERN void Tcl_SetMainLoop(Tcl_MainLoopProc *proc);
+#endif
/* Slot 285 is reserved */
+#ifndef Tcl_AppendObjToObj_TCL_DECLARED
+#define Tcl_AppendObjToObj_TCL_DECLARED
/* 286 */
-EXTERN void Tcl_AppendObjToObj _ANSI_ARGS_((Tcl_Obj * objPtr,
- Tcl_Obj * appendObjPtr));
+EXTERN void Tcl_AppendObjToObj(Tcl_Obj *objPtr,
+ Tcl_Obj *appendObjPtr);
+#endif
+#ifndef Tcl_CreateEncoding_TCL_DECLARED
+#define Tcl_CreateEncoding_TCL_DECLARED
/* 287 */
-EXTERN Tcl_Encoding Tcl_CreateEncoding _ANSI_ARGS_((
- Tcl_EncodingType * typePtr));
+EXTERN Tcl_Encoding Tcl_CreateEncoding(CONST Tcl_EncodingType *typePtr);
+#endif
+#ifndef Tcl_CreateThreadExitHandler_TCL_DECLARED
+#define Tcl_CreateThreadExitHandler_TCL_DECLARED
/* 288 */
-EXTERN void Tcl_CreateThreadExitHandler _ANSI_ARGS_((
- Tcl_ExitProc * proc, ClientData clientData));
+EXTERN void Tcl_CreateThreadExitHandler(Tcl_ExitProc *proc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_DeleteThreadExitHandler_TCL_DECLARED
+#define Tcl_DeleteThreadExitHandler_TCL_DECLARED
/* 289 */
-EXTERN void Tcl_DeleteThreadExitHandler _ANSI_ARGS_((
- Tcl_ExitProc * proc, ClientData clientData));
+EXTERN void Tcl_DeleteThreadExitHandler(Tcl_ExitProc *proc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_DiscardResult_TCL_DECLARED
+#define Tcl_DiscardResult_TCL_DECLARED
/* 290 */
-EXTERN void Tcl_DiscardResult _ANSI_ARGS_((
- Tcl_SavedResult * statePtr));
+EXTERN void Tcl_DiscardResult(Tcl_SavedResult *statePtr);
+#endif
+#ifndef Tcl_EvalEx_TCL_DECLARED
+#define Tcl_EvalEx_TCL_DECLARED
/* 291 */
-EXTERN int Tcl_EvalEx _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * script, int numBytes, int flags));
+EXTERN int Tcl_EvalEx(Tcl_Interp *interp, CONST char *script,
+ int numBytes, int flags);
+#endif
+#ifndef Tcl_EvalObjv_TCL_DECLARED
+#define Tcl_EvalObjv_TCL_DECLARED
/* 292 */
-EXTERN int Tcl_EvalObjv _ANSI_ARGS_((Tcl_Interp * interp,
- int objc, Tcl_Obj *CONST objv[], int flags));
+EXTERN int Tcl_EvalObjv(Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[], int flags);
+#endif
+#ifndef Tcl_EvalObjEx_TCL_DECLARED
+#define Tcl_EvalObjEx_TCL_DECLARED
/* 293 */
-EXTERN int Tcl_EvalObjEx _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * objPtr, int flags));
+EXTERN int Tcl_EvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ int flags);
+#endif
+#ifndef Tcl_ExitThread_TCL_DECLARED
+#define Tcl_ExitThread_TCL_DECLARED
/* 294 */
-EXTERN void Tcl_ExitThread _ANSI_ARGS_((int status));
+EXTERN void Tcl_ExitThread(int status);
+#endif
+#ifndef Tcl_ExternalToUtf_TCL_DECLARED
+#define Tcl_ExternalToUtf_TCL_DECLARED
/* 295 */
-EXTERN int Tcl_ExternalToUtf _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Encoding encoding, CONST char * src,
- int srcLen, int flags,
- Tcl_EncodingState * statePtr, char * dst,
- int dstLen, int * srcReadPtr,
- int * dstWrotePtr, int * dstCharsPtr));
+EXTERN int Tcl_ExternalToUtf(Tcl_Interp *interp,
+ Tcl_Encoding encoding, CONST char *src,
+ int srcLen, int flags,
+ Tcl_EncodingState *statePtr, char *dst,
+ int dstLen, int *srcReadPtr,
+ int *dstWrotePtr, int *dstCharsPtr);
+#endif
+#ifndef Tcl_ExternalToUtfDString_TCL_DECLARED
+#define Tcl_ExternalToUtfDString_TCL_DECLARED
/* 296 */
-EXTERN char * Tcl_ExternalToUtfDString _ANSI_ARGS_((
- Tcl_Encoding encoding, CONST char * src,
- int srcLen, Tcl_DString * dsPtr));
+EXTERN char * Tcl_ExternalToUtfDString(Tcl_Encoding encoding,
+ CONST char *src, int srcLen,
+ Tcl_DString *dsPtr);
+#endif
+#ifndef Tcl_FinalizeThread_TCL_DECLARED
+#define Tcl_FinalizeThread_TCL_DECLARED
/* 297 */
-EXTERN void Tcl_FinalizeThread _ANSI_ARGS_((void));
+EXTERN void Tcl_FinalizeThread(void);
+#endif
+#ifndef Tcl_FinalizeNotifier_TCL_DECLARED
+#define Tcl_FinalizeNotifier_TCL_DECLARED
/* 298 */
-EXTERN void Tcl_FinalizeNotifier _ANSI_ARGS_((
- ClientData clientData));
+EXTERN void Tcl_FinalizeNotifier(ClientData clientData);
+#endif
+#ifndef Tcl_FreeEncoding_TCL_DECLARED
+#define Tcl_FreeEncoding_TCL_DECLARED
/* 299 */
-EXTERN void Tcl_FreeEncoding _ANSI_ARGS_((Tcl_Encoding encoding));
+EXTERN void Tcl_FreeEncoding(Tcl_Encoding encoding);
+#endif
+#ifndef Tcl_GetCurrentThread_TCL_DECLARED
+#define Tcl_GetCurrentThread_TCL_DECLARED
/* 300 */
-EXTERN Tcl_ThreadId Tcl_GetCurrentThread _ANSI_ARGS_((void));
+EXTERN Tcl_ThreadId Tcl_GetCurrentThread(void);
+#endif
+#ifndef Tcl_GetEncoding_TCL_DECLARED
+#define Tcl_GetEncoding_TCL_DECLARED
/* 301 */
-EXTERN Tcl_Encoding Tcl_GetEncoding _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * name));
+EXTERN Tcl_Encoding Tcl_GetEncoding(Tcl_Interp *interp, CONST char *name);
+#endif
+#ifndef Tcl_GetEncodingName_TCL_DECLARED
+#define Tcl_GetEncodingName_TCL_DECLARED
/* 302 */
-EXTERN CONST84_RETURN char * Tcl_GetEncodingName _ANSI_ARGS_((
- Tcl_Encoding encoding));
+EXTERN CONST84_RETURN char * Tcl_GetEncodingName(Tcl_Encoding encoding);
+#endif
+#ifndef Tcl_GetEncodingNames_TCL_DECLARED
+#define Tcl_GetEncodingNames_TCL_DECLARED
/* 303 */
-EXTERN void Tcl_GetEncodingNames _ANSI_ARGS_((
- Tcl_Interp * interp));
+EXTERN void Tcl_GetEncodingNames(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_GetIndexFromObjStruct_TCL_DECLARED
+#define Tcl_GetIndexFromObjStruct_TCL_DECLARED
/* 304 */
-EXTERN int Tcl_GetIndexFromObjStruct _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Obj * objPtr,
- CONST VOID * tablePtr, int offset,
- CONST char * msg, int flags, int * indexPtr));
+EXTERN int Tcl_GetIndexFromObjStruct(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, CONST VOID *tablePtr,
+ int offset, CONST char *msg, int flags,
+ int *indexPtr);
+#endif
+#ifndef Tcl_GetThreadData_TCL_DECLARED
+#define Tcl_GetThreadData_TCL_DECLARED
/* 305 */
-EXTERN VOID * Tcl_GetThreadData _ANSI_ARGS_((
- Tcl_ThreadDataKey * keyPtr, int size));
+EXTERN VOID * Tcl_GetThreadData(Tcl_ThreadDataKey *keyPtr,
+ int size);
+#endif
+#ifndef Tcl_GetVar2Ex_TCL_DECLARED
+#define Tcl_GetVar2Ex_TCL_DECLARED
/* 306 */
-EXTERN Tcl_Obj * Tcl_GetVar2Ex _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * part1, CONST char * part2,
- int flags));
+EXTERN Tcl_Obj * Tcl_GetVar2Ex(Tcl_Interp *interp, CONST char *part1,
+ CONST char *part2, int flags);
+#endif
+#ifndef Tcl_InitNotifier_TCL_DECLARED
+#define Tcl_InitNotifier_TCL_DECLARED
/* 307 */
-EXTERN ClientData Tcl_InitNotifier _ANSI_ARGS_((void));
+EXTERN ClientData Tcl_InitNotifier(void);
+#endif
+#ifndef Tcl_MutexLock_TCL_DECLARED
+#define Tcl_MutexLock_TCL_DECLARED
/* 308 */
-EXTERN void Tcl_MutexLock _ANSI_ARGS_((Tcl_Mutex * mutexPtr));
+EXTERN void Tcl_MutexLock(Tcl_Mutex *mutexPtr);
+#endif
+#ifndef Tcl_MutexUnlock_TCL_DECLARED
+#define Tcl_MutexUnlock_TCL_DECLARED
/* 309 */
-EXTERN void Tcl_MutexUnlock _ANSI_ARGS_((Tcl_Mutex * mutexPtr));
+EXTERN void Tcl_MutexUnlock(Tcl_Mutex *mutexPtr);
+#endif
+#ifndef Tcl_ConditionNotify_TCL_DECLARED
+#define Tcl_ConditionNotify_TCL_DECLARED
/* 310 */
-EXTERN void Tcl_ConditionNotify _ANSI_ARGS_((
- Tcl_Condition * condPtr));
+EXTERN void Tcl_ConditionNotify(Tcl_Condition *condPtr);
+#endif
+#ifndef Tcl_ConditionWait_TCL_DECLARED
+#define Tcl_ConditionWait_TCL_DECLARED
/* 311 */
-EXTERN void Tcl_ConditionWait _ANSI_ARGS_((
- Tcl_Condition * condPtr,
- Tcl_Mutex * mutexPtr, Tcl_Time * timePtr));
+EXTERN void Tcl_ConditionWait(Tcl_Condition *condPtr,
+ Tcl_Mutex *mutexPtr, Tcl_Time *timePtr);
+#endif
+#ifndef Tcl_NumUtfChars_TCL_DECLARED
+#define Tcl_NumUtfChars_TCL_DECLARED
/* 312 */
-EXTERN int Tcl_NumUtfChars _ANSI_ARGS_((CONST char * src,
- int len));
+EXTERN int Tcl_NumUtfChars(CONST char *src, int length);
+#endif
+#ifndef Tcl_ReadChars_TCL_DECLARED
+#define Tcl_ReadChars_TCL_DECLARED
/* 313 */
-EXTERN int Tcl_ReadChars _ANSI_ARGS_((Tcl_Channel channel,
- Tcl_Obj * objPtr, int charsToRead,
- int appendFlag));
+EXTERN int Tcl_ReadChars(Tcl_Channel channel, Tcl_Obj *objPtr,
+ int charsToRead, int appendFlag);
+#endif
+#ifndef Tcl_RestoreResult_TCL_DECLARED
+#define Tcl_RestoreResult_TCL_DECLARED
/* 314 */
-EXTERN void Tcl_RestoreResult _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_SavedResult * statePtr));
+EXTERN void Tcl_RestoreResult(Tcl_Interp *interp,
+ Tcl_SavedResult *statePtr);
+#endif
+#ifndef Tcl_SaveResult_TCL_DECLARED
+#define Tcl_SaveResult_TCL_DECLARED
/* 315 */
-EXTERN void Tcl_SaveResult _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_SavedResult * statePtr));
+EXTERN void Tcl_SaveResult(Tcl_Interp *interp,
+ Tcl_SavedResult *statePtr);
+#endif
+#ifndef Tcl_SetSystemEncoding_TCL_DECLARED
+#define Tcl_SetSystemEncoding_TCL_DECLARED
/* 316 */
-EXTERN int Tcl_SetSystemEncoding _ANSI_ARGS_((
- Tcl_Interp * interp, CONST char * name));
+EXTERN int Tcl_SetSystemEncoding(Tcl_Interp *interp,
+ CONST char *name);
+#endif
+#ifndef Tcl_SetVar2Ex_TCL_DECLARED
+#define Tcl_SetVar2Ex_TCL_DECLARED
/* 317 */
-EXTERN Tcl_Obj * Tcl_SetVar2Ex _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * part1, CONST char * part2,
- Tcl_Obj * newValuePtr, int flags));
+EXTERN Tcl_Obj * Tcl_SetVar2Ex(Tcl_Interp *interp, CONST char *part1,
+ CONST char *part2, Tcl_Obj *newValuePtr,
+ int flags);
+#endif
+#ifndef Tcl_ThreadAlert_TCL_DECLARED
+#define Tcl_ThreadAlert_TCL_DECLARED
/* 318 */
-EXTERN void Tcl_ThreadAlert _ANSI_ARGS_((Tcl_ThreadId threadId));
+EXTERN void Tcl_ThreadAlert(Tcl_ThreadId threadId);
+#endif
+#ifndef Tcl_ThreadQueueEvent_TCL_DECLARED
+#define Tcl_ThreadQueueEvent_TCL_DECLARED
/* 319 */
-EXTERN void Tcl_ThreadQueueEvent _ANSI_ARGS_((
- Tcl_ThreadId threadId, Tcl_Event* evPtr,
- Tcl_QueuePosition position));
+EXTERN void Tcl_ThreadQueueEvent(Tcl_ThreadId threadId,
+ Tcl_Event *evPtr, Tcl_QueuePosition position);
+#endif
+#ifndef Tcl_UniCharAtIndex_TCL_DECLARED
+#define Tcl_UniCharAtIndex_TCL_DECLARED
/* 320 */
-EXTERN Tcl_UniChar Tcl_UniCharAtIndex _ANSI_ARGS_((CONST char * src,
- int index));
+EXTERN Tcl_UniChar Tcl_UniCharAtIndex(CONST char *src, int index);
+#endif
+#ifndef Tcl_UniCharToLower_TCL_DECLARED
+#define Tcl_UniCharToLower_TCL_DECLARED
/* 321 */
-EXTERN Tcl_UniChar Tcl_UniCharToLower _ANSI_ARGS_((int ch));
+EXTERN Tcl_UniChar Tcl_UniCharToLower(int ch);
+#endif
+#ifndef Tcl_UniCharToTitle_TCL_DECLARED
+#define Tcl_UniCharToTitle_TCL_DECLARED
/* 322 */
-EXTERN Tcl_UniChar Tcl_UniCharToTitle _ANSI_ARGS_((int ch));
+EXTERN Tcl_UniChar Tcl_UniCharToTitle(int ch);
+#endif
+#ifndef Tcl_UniCharToUpper_TCL_DECLARED
+#define Tcl_UniCharToUpper_TCL_DECLARED
/* 323 */
-EXTERN Tcl_UniChar Tcl_UniCharToUpper _ANSI_ARGS_((int ch));
+EXTERN Tcl_UniChar Tcl_UniCharToUpper(int ch);
+#endif
+#ifndef Tcl_UniCharToUtf_TCL_DECLARED
+#define Tcl_UniCharToUtf_TCL_DECLARED
/* 324 */
-EXTERN int Tcl_UniCharToUtf _ANSI_ARGS_((int ch, char * buf));
+EXTERN int Tcl_UniCharToUtf(int ch, char *buf);
+#endif
+#ifndef Tcl_UtfAtIndex_TCL_DECLARED
+#define Tcl_UtfAtIndex_TCL_DECLARED
/* 325 */
-EXTERN CONST84_RETURN char * Tcl_UtfAtIndex _ANSI_ARGS_((CONST char * src,
- int index));
+EXTERN CONST84_RETURN char * Tcl_UtfAtIndex(CONST char *src, int index);
+#endif
+#ifndef Tcl_UtfCharComplete_TCL_DECLARED
+#define Tcl_UtfCharComplete_TCL_DECLARED
/* 326 */
-EXTERN int Tcl_UtfCharComplete _ANSI_ARGS_((CONST char * src,
- int len));
+EXTERN int Tcl_UtfCharComplete(CONST char *src, int length);
+#endif
+#ifndef Tcl_UtfBackslash_TCL_DECLARED
+#define Tcl_UtfBackslash_TCL_DECLARED
/* 327 */
-EXTERN int Tcl_UtfBackslash _ANSI_ARGS_((CONST char * src,
- int * readPtr, char * dst));
+EXTERN int Tcl_UtfBackslash(CONST char *src, int *readPtr,
+ char *dst);
+#endif
+#ifndef Tcl_UtfFindFirst_TCL_DECLARED
+#define Tcl_UtfFindFirst_TCL_DECLARED
/* 328 */
-EXTERN CONST84_RETURN char * Tcl_UtfFindFirst _ANSI_ARGS_((CONST char * src,
- int ch));
+EXTERN CONST84_RETURN char * Tcl_UtfFindFirst(CONST char *src, int ch);
+#endif
+#ifndef Tcl_UtfFindLast_TCL_DECLARED
+#define Tcl_UtfFindLast_TCL_DECLARED
/* 329 */
-EXTERN CONST84_RETURN char * Tcl_UtfFindLast _ANSI_ARGS_((CONST char * src,
- int ch));
+EXTERN CONST84_RETURN char * Tcl_UtfFindLast(CONST char *src, int ch);
+#endif
+#ifndef Tcl_UtfNext_TCL_DECLARED
+#define Tcl_UtfNext_TCL_DECLARED
/* 330 */
-EXTERN CONST84_RETURN char * Tcl_UtfNext _ANSI_ARGS_((CONST char * src));
+EXTERN CONST84_RETURN char * Tcl_UtfNext(CONST char *src);
+#endif
+#ifndef Tcl_UtfPrev_TCL_DECLARED
+#define Tcl_UtfPrev_TCL_DECLARED
/* 331 */
-EXTERN CONST84_RETURN char * Tcl_UtfPrev _ANSI_ARGS_((CONST char * src,
- CONST char * start));
+EXTERN CONST84_RETURN char * Tcl_UtfPrev(CONST char *src, CONST char *start);
+#endif
+#ifndef Tcl_UtfToExternal_TCL_DECLARED
+#define Tcl_UtfToExternal_TCL_DECLARED
/* 332 */
-EXTERN int Tcl_UtfToExternal _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Encoding encoding, CONST char * src,
- int srcLen, int flags,
- Tcl_EncodingState * statePtr, char * dst,
- int dstLen, int * srcReadPtr,
- int * dstWrotePtr, int * dstCharsPtr));
+EXTERN int Tcl_UtfToExternal(Tcl_Interp *interp,
+ Tcl_Encoding encoding, CONST char *src,
+ int srcLen, int flags,
+ Tcl_EncodingState *statePtr, char *dst,
+ int dstLen, int *srcReadPtr,
+ int *dstWrotePtr, int *dstCharsPtr);
+#endif
+#ifndef Tcl_UtfToExternalDString_TCL_DECLARED
+#define Tcl_UtfToExternalDString_TCL_DECLARED
/* 333 */
-EXTERN char * Tcl_UtfToExternalDString _ANSI_ARGS_((
- Tcl_Encoding encoding, CONST char * src,
- int srcLen, Tcl_DString * dsPtr));
+EXTERN char * Tcl_UtfToExternalDString(Tcl_Encoding encoding,
+ CONST char *src, int srcLen,
+ Tcl_DString *dsPtr);
+#endif
+#ifndef Tcl_UtfToLower_TCL_DECLARED
+#define Tcl_UtfToLower_TCL_DECLARED
/* 334 */
-EXTERN int Tcl_UtfToLower _ANSI_ARGS_((char * src));
+EXTERN int Tcl_UtfToLower(char *src);
+#endif
+#ifndef Tcl_UtfToTitle_TCL_DECLARED
+#define Tcl_UtfToTitle_TCL_DECLARED
/* 335 */
-EXTERN int Tcl_UtfToTitle _ANSI_ARGS_((char * src));
+EXTERN int Tcl_UtfToTitle(char *src);
+#endif
+#ifndef Tcl_UtfToUniChar_TCL_DECLARED
+#define Tcl_UtfToUniChar_TCL_DECLARED
/* 336 */
-EXTERN int Tcl_UtfToUniChar _ANSI_ARGS_((CONST char * src,
- Tcl_UniChar * chPtr));
+EXTERN int Tcl_UtfToUniChar(CONST char *src, Tcl_UniChar *chPtr);
+#endif
+#ifndef Tcl_UtfToUpper_TCL_DECLARED
+#define Tcl_UtfToUpper_TCL_DECLARED
/* 337 */
-EXTERN int Tcl_UtfToUpper _ANSI_ARGS_((char * src));
+EXTERN int Tcl_UtfToUpper(char *src);
+#endif
+#ifndef Tcl_WriteChars_TCL_DECLARED
+#define Tcl_WriteChars_TCL_DECLARED
/* 338 */
-EXTERN int Tcl_WriteChars _ANSI_ARGS_((Tcl_Channel chan,
- CONST char * src, int srcLen));
+EXTERN int Tcl_WriteChars(Tcl_Channel chan, CONST char *src,
+ int srcLen);
+#endif
+#ifndef Tcl_WriteObj_TCL_DECLARED
+#define Tcl_WriteObj_TCL_DECLARED
/* 339 */
-EXTERN int Tcl_WriteObj _ANSI_ARGS_((Tcl_Channel chan,
- Tcl_Obj * objPtr));
+EXTERN int Tcl_WriteObj(Tcl_Channel chan, Tcl_Obj *objPtr);
+#endif
+#ifndef Tcl_GetString_TCL_DECLARED
+#define Tcl_GetString_TCL_DECLARED
/* 340 */
-EXTERN char * Tcl_GetString _ANSI_ARGS_((Tcl_Obj * objPtr));
+EXTERN char * Tcl_GetString(Tcl_Obj *objPtr);
+#endif
+#ifndef Tcl_GetDefaultEncodingDir_TCL_DECLARED
+#define Tcl_GetDefaultEncodingDir_TCL_DECLARED
/* 341 */
-EXTERN CONST84_RETURN char * Tcl_GetDefaultEncodingDir _ANSI_ARGS_((void));
+EXTERN CONST84_RETURN char * Tcl_GetDefaultEncodingDir(void);
+#endif
+#ifndef Tcl_SetDefaultEncodingDir_TCL_DECLARED
+#define Tcl_SetDefaultEncodingDir_TCL_DECLARED
/* 342 */
-EXTERN void Tcl_SetDefaultEncodingDir _ANSI_ARGS_((
- CONST char * path));
+EXTERN void Tcl_SetDefaultEncodingDir(CONST char *path);
+#endif
+#ifndef Tcl_AlertNotifier_TCL_DECLARED
+#define Tcl_AlertNotifier_TCL_DECLARED
/* 343 */
-EXTERN void Tcl_AlertNotifier _ANSI_ARGS_((ClientData clientData));
+EXTERN void Tcl_AlertNotifier(ClientData clientData);
+#endif
+#ifndef Tcl_ServiceModeHook_TCL_DECLARED
+#define Tcl_ServiceModeHook_TCL_DECLARED
/* 344 */
-EXTERN void Tcl_ServiceModeHook _ANSI_ARGS_((int mode));
+EXTERN void Tcl_ServiceModeHook(int mode);
+#endif
+#ifndef Tcl_UniCharIsAlnum_TCL_DECLARED
+#define Tcl_UniCharIsAlnum_TCL_DECLARED
/* 345 */
-EXTERN int Tcl_UniCharIsAlnum _ANSI_ARGS_((int ch));
+EXTERN int Tcl_UniCharIsAlnum(int ch);
+#endif
+#ifndef Tcl_UniCharIsAlpha_TCL_DECLARED
+#define Tcl_UniCharIsAlpha_TCL_DECLARED
/* 346 */
-EXTERN int Tcl_UniCharIsAlpha _ANSI_ARGS_((int ch));
+EXTERN int Tcl_UniCharIsAlpha(int ch);
+#endif
+#ifndef Tcl_UniCharIsDigit_TCL_DECLARED
+#define Tcl_UniCharIsDigit_TCL_DECLARED
/* 347 */
-EXTERN int Tcl_UniCharIsDigit _ANSI_ARGS_((int ch));
+EXTERN int Tcl_UniCharIsDigit(int ch);
+#endif
+#ifndef Tcl_UniCharIsLower_TCL_DECLARED
+#define Tcl_UniCharIsLower_TCL_DECLARED
/* 348 */
-EXTERN int Tcl_UniCharIsLower _ANSI_ARGS_((int ch));
+EXTERN int Tcl_UniCharIsLower(int ch);
+#endif
+#ifndef Tcl_UniCharIsSpace_TCL_DECLARED
+#define Tcl_UniCharIsSpace_TCL_DECLARED
/* 349 */
-EXTERN int Tcl_UniCharIsSpace _ANSI_ARGS_((int ch));
+EXTERN int Tcl_UniCharIsSpace(int ch);
+#endif
+#ifndef Tcl_UniCharIsUpper_TCL_DECLARED
+#define Tcl_UniCharIsUpper_TCL_DECLARED
/* 350 */
-EXTERN int Tcl_UniCharIsUpper _ANSI_ARGS_((int ch));
+EXTERN int Tcl_UniCharIsUpper(int ch);
+#endif
+#ifndef Tcl_UniCharIsWordChar_TCL_DECLARED
+#define Tcl_UniCharIsWordChar_TCL_DECLARED
/* 351 */
-EXTERN int Tcl_UniCharIsWordChar _ANSI_ARGS_((int ch));
+EXTERN int Tcl_UniCharIsWordChar(int ch);
+#endif
+#ifndef Tcl_UniCharLen_TCL_DECLARED
+#define Tcl_UniCharLen_TCL_DECLARED
/* 352 */
-EXTERN int Tcl_UniCharLen _ANSI_ARGS_((CONST Tcl_UniChar * str));
+EXTERN int Tcl_UniCharLen(CONST Tcl_UniChar *uniStr);
+#endif
+#ifndef Tcl_UniCharNcmp_TCL_DECLARED
+#define Tcl_UniCharNcmp_TCL_DECLARED
/* 353 */
-EXTERN int Tcl_UniCharNcmp _ANSI_ARGS_((CONST Tcl_UniChar * cs,
- CONST Tcl_UniChar * ct, unsigned long n));
+EXTERN int Tcl_UniCharNcmp(CONST Tcl_UniChar *ucs,
+ CONST Tcl_UniChar *uct,
+ unsigned long numChars);
+#endif
+#ifndef Tcl_UniCharToUtfDString_TCL_DECLARED
+#define Tcl_UniCharToUtfDString_TCL_DECLARED
/* 354 */
-EXTERN char * Tcl_UniCharToUtfDString _ANSI_ARGS_((
- CONST Tcl_UniChar * string, int numChars,
- Tcl_DString * dsPtr));
+EXTERN char * Tcl_UniCharToUtfDString(CONST Tcl_UniChar *uniStr,
+ int uniLength, Tcl_DString *dsPtr);
+#endif
+#ifndef Tcl_UtfToUniCharDString_TCL_DECLARED
+#define Tcl_UtfToUniCharDString_TCL_DECLARED
/* 355 */
-EXTERN Tcl_UniChar * Tcl_UtfToUniCharDString _ANSI_ARGS_((
- CONST char * string, int length,
- Tcl_DString * dsPtr));
+EXTERN Tcl_UniChar * Tcl_UtfToUniCharDString(CONST char *src, int length,
+ Tcl_DString *dsPtr);
+#endif
+#ifndef Tcl_GetRegExpFromObj_TCL_DECLARED
+#define Tcl_GetRegExpFromObj_TCL_DECLARED
/* 356 */
-EXTERN Tcl_RegExp Tcl_GetRegExpFromObj _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Obj * patObj,
- int flags));
+EXTERN Tcl_RegExp Tcl_GetRegExpFromObj(Tcl_Interp *interp,
+ Tcl_Obj *patObj, int flags);
+#endif
+#ifndef Tcl_EvalTokens_TCL_DECLARED
+#define Tcl_EvalTokens_TCL_DECLARED
/* 357 */
-EXTERN Tcl_Obj * Tcl_EvalTokens _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Token * tokenPtr, int count));
+EXTERN Tcl_Obj * Tcl_EvalTokens(Tcl_Interp *interp,
+ Tcl_Token *tokenPtr, int count);
+#endif
+#ifndef Tcl_FreeParse_TCL_DECLARED
+#define Tcl_FreeParse_TCL_DECLARED
/* 358 */
-EXTERN void Tcl_FreeParse _ANSI_ARGS_((Tcl_Parse * parsePtr));
+EXTERN void Tcl_FreeParse(Tcl_Parse *parsePtr);
+#endif
+#ifndef Tcl_LogCommandInfo_TCL_DECLARED
+#define Tcl_LogCommandInfo_TCL_DECLARED
/* 359 */
-EXTERN void Tcl_LogCommandInfo _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * script, CONST char * command,
- int length));
+EXTERN void Tcl_LogCommandInfo(Tcl_Interp *interp,
+ CONST char *script, CONST char *command,
+ int length);
+#endif
+#ifndef Tcl_ParseBraces_TCL_DECLARED
+#define Tcl_ParseBraces_TCL_DECLARED
/* 360 */
-EXTERN int Tcl_ParseBraces _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * string, int numBytes,
- Tcl_Parse * parsePtr, int append,
- CONST84 char ** termPtr));
+EXTERN int Tcl_ParseBraces(Tcl_Interp *interp,
+ CONST char *start, int numBytes,
+ Tcl_Parse *parsePtr, int append,
+ CONST84 char **termPtr);
+#endif
+#ifndef Tcl_ParseCommand_TCL_DECLARED
+#define Tcl_ParseCommand_TCL_DECLARED
/* 361 */
-EXTERN int Tcl_ParseCommand _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * string, int numBytes,
- int nested, Tcl_Parse * parsePtr));
+EXTERN int Tcl_ParseCommand(Tcl_Interp *interp,
+ CONST char *start, int numBytes, int nested,
+ Tcl_Parse *parsePtr);
+#endif
+#ifndef Tcl_ParseExpr_TCL_DECLARED
+#define Tcl_ParseExpr_TCL_DECLARED
/* 362 */
-EXTERN int Tcl_ParseExpr _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * string, int numBytes,
- Tcl_Parse * parsePtr));
+EXTERN int Tcl_ParseExpr(Tcl_Interp *interp, CONST char *start,
+ int numBytes, Tcl_Parse *parsePtr);
+#endif
+#ifndef Tcl_ParseQuotedString_TCL_DECLARED
+#define Tcl_ParseQuotedString_TCL_DECLARED
/* 363 */
-EXTERN int Tcl_ParseQuotedString _ANSI_ARGS_((
- Tcl_Interp * interp, CONST char * string,
- int numBytes, Tcl_Parse * parsePtr,
- int append, CONST84 char ** termPtr));
+EXTERN int Tcl_ParseQuotedString(Tcl_Interp *interp,
+ CONST char *start, int numBytes,
+ Tcl_Parse *parsePtr, int append,
+ CONST84 char **termPtr);
+#endif
+#ifndef Tcl_ParseVarName_TCL_DECLARED
+#define Tcl_ParseVarName_TCL_DECLARED
/* 364 */
-EXTERN int Tcl_ParseVarName _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * string, int numBytes,
- Tcl_Parse * parsePtr, int append));
+EXTERN int Tcl_ParseVarName(Tcl_Interp *interp,
+ CONST char *start, int numBytes,
+ Tcl_Parse *parsePtr, int append);
+#endif
+#ifndef Tcl_GetCwd_TCL_DECLARED
+#define Tcl_GetCwd_TCL_DECLARED
/* 365 */
-EXTERN char * Tcl_GetCwd _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_DString * cwdPtr));
+EXTERN char * Tcl_GetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr);
+#endif
+#ifndef Tcl_Chdir_TCL_DECLARED
+#define Tcl_Chdir_TCL_DECLARED
/* 366 */
-EXTERN int Tcl_Chdir _ANSI_ARGS_((CONST char * dirName));
+EXTERN int Tcl_Chdir(CONST char *dirName);
+#endif
+#ifndef Tcl_Access_TCL_DECLARED
+#define Tcl_Access_TCL_DECLARED
/* 367 */
-EXTERN int Tcl_Access _ANSI_ARGS_((CONST char * path, int mode));
+EXTERN int Tcl_Access(CONST char *path, int mode);
+#endif
+#ifndef Tcl_Stat_TCL_DECLARED
+#define Tcl_Stat_TCL_DECLARED
/* 368 */
-EXTERN int Tcl_Stat _ANSI_ARGS_((CONST char * path,
- struct stat * bufPtr));
+EXTERN int Tcl_Stat(CONST char *path, struct stat *bufPtr);
+#endif
+#ifndef Tcl_UtfNcmp_TCL_DECLARED
+#define Tcl_UtfNcmp_TCL_DECLARED
/* 369 */
-EXTERN int Tcl_UtfNcmp _ANSI_ARGS_((CONST char * s1,
- CONST char * s2, unsigned long n));
+EXTERN int Tcl_UtfNcmp(CONST char *s1, CONST char *s2,
+ unsigned long n);
+#endif
+#ifndef Tcl_UtfNcasecmp_TCL_DECLARED
+#define Tcl_UtfNcasecmp_TCL_DECLARED
/* 370 */
-EXTERN int Tcl_UtfNcasecmp _ANSI_ARGS_((CONST char * s1,
- CONST char * s2, unsigned long n));
+EXTERN int Tcl_UtfNcasecmp(CONST char *s1, CONST char *s2,
+ unsigned long n);
+#endif
+#ifndef Tcl_StringCaseMatch_TCL_DECLARED
+#define Tcl_StringCaseMatch_TCL_DECLARED
/* 371 */
-EXTERN int Tcl_StringCaseMatch _ANSI_ARGS_((CONST char * str,
- CONST char * pattern, int nocase));
+EXTERN int Tcl_StringCaseMatch(CONST char *str,
+ CONST char *pattern, int nocase);
+#endif
+#ifndef Tcl_UniCharIsControl_TCL_DECLARED
+#define Tcl_UniCharIsControl_TCL_DECLARED
/* 372 */
-EXTERN int Tcl_UniCharIsControl _ANSI_ARGS_((int ch));
+EXTERN int Tcl_UniCharIsControl(int ch);
+#endif
+#ifndef Tcl_UniCharIsGraph_TCL_DECLARED
+#define Tcl_UniCharIsGraph_TCL_DECLARED
/* 373 */
-EXTERN int Tcl_UniCharIsGraph _ANSI_ARGS_((int ch));
+EXTERN int Tcl_UniCharIsGraph(int ch);
+#endif
+#ifndef Tcl_UniCharIsPrint_TCL_DECLARED
+#define Tcl_UniCharIsPrint_TCL_DECLARED
/* 374 */
-EXTERN int Tcl_UniCharIsPrint _ANSI_ARGS_((int ch));
+EXTERN int Tcl_UniCharIsPrint(int ch);
+#endif
+#ifndef Tcl_UniCharIsPunct_TCL_DECLARED
+#define Tcl_UniCharIsPunct_TCL_DECLARED
/* 375 */
-EXTERN int Tcl_UniCharIsPunct _ANSI_ARGS_((int ch));
+EXTERN int Tcl_UniCharIsPunct(int ch);
+#endif
+#ifndef Tcl_RegExpExecObj_TCL_DECLARED
+#define Tcl_RegExpExecObj_TCL_DECLARED
/* 376 */
-EXTERN int Tcl_RegExpExecObj _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_RegExp regexp, Tcl_Obj * objPtr,
- int offset, int nmatches, int flags));
+EXTERN int Tcl_RegExpExecObj(Tcl_Interp *interp,
+ Tcl_RegExp regexp, Tcl_Obj *textObj,
+ int offset, int nmatches, int flags);
+#endif
+#ifndef Tcl_RegExpGetInfo_TCL_DECLARED
+#define Tcl_RegExpGetInfo_TCL_DECLARED
/* 377 */
-EXTERN void Tcl_RegExpGetInfo _ANSI_ARGS_((Tcl_RegExp regexp,
- Tcl_RegExpInfo * infoPtr));
+EXTERN void Tcl_RegExpGetInfo(Tcl_RegExp regexp,
+ Tcl_RegExpInfo *infoPtr);
+#endif
+#ifndef Tcl_NewUnicodeObj_TCL_DECLARED
+#define Tcl_NewUnicodeObj_TCL_DECLARED
/* 378 */
-EXTERN Tcl_Obj * Tcl_NewUnicodeObj _ANSI_ARGS_((
- CONST Tcl_UniChar * unicode, int numChars));
+EXTERN Tcl_Obj * Tcl_NewUnicodeObj(CONST Tcl_UniChar *unicode,
+ int numChars);
+#endif
+#ifndef Tcl_SetUnicodeObj_TCL_DECLARED
+#define Tcl_SetUnicodeObj_TCL_DECLARED
/* 379 */
-EXTERN void Tcl_SetUnicodeObj _ANSI_ARGS_((Tcl_Obj * objPtr,
- CONST Tcl_UniChar * unicode, int numChars));
+EXTERN void Tcl_SetUnicodeObj(Tcl_Obj *objPtr,
+ CONST Tcl_UniChar *unicode, int numChars);
+#endif
+#ifndef Tcl_GetCharLength_TCL_DECLARED
+#define Tcl_GetCharLength_TCL_DECLARED
/* 380 */
-EXTERN int Tcl_GetCharLength _ANSI_ARGS_((Tcl_Obj * objPtr));
+EXTERN int Tcl_GetCharLength(Tcl_Obj *objPtr);
+#endif
+#ifndef Tcl_GetUniChar_TCL_DECLARED
+#define Tcl_GetUniChar_TCL_DECLARED
/* 381 */
-EXTERN Tcl_UniChar Tcl_GetUniChar _ANSI_ARGS_((Tcl_Obj * objPtr,
- int index));
+EXTERN Tcl_UniChar Tcl_GetUniChar(Tcl_Obj *objPtr, int index);
+#endif
+#ifndef Tcl_GetUnicode_TCL_DECLARED
+#define Tcl_GetUnicode_TCL_DECLARED
/* 382 */
-EXTERN Tcl_UniChar * Tcl_GetUnicode _ANSI_ARGS_((Tcl_Obj * objPtr));
+EXTERN Tcl_UniChar * Tcl_GetUnicode(Tcl_Obj *objPtr);
+#endif
+#ifndef Tcl_GetRange_TCL_DECLARED
+#define Tcl_GetRange_TCL_DECLARED
/* 383 */
-EXTERN Tcl_Obj * Tcl_GetRange _ANSI_ARGS_((Tcl_Obj * objPtr,
- int first, int last));
+EXTERN Tcl_Obj * Tcl_GetRange(Tcl_Obj *objPtr, int first, int last);
+#endif
+#ifndef Tcl_AppendUnicodeToObj_TCL_DECLARED
+#define Tcl_AppendUnicodeToObj_TCL_DECLARED
/* 384 */
-EXTERN void Tcl_AppendUnicodeToObj _ANSI_ARGS_((Tcl_Obj * objPtr,
- CONST Tcl_UniChar * unicode, int length));
+EXTERN void Tcl_AppendUnicodeToObj(Tcl_Obj *objPtr,
+ CONST Tcl_UniChar *unicode, int length);
+#endif
+#ifndef Tcl_RegExpMatchObj_TCL_DECLARED
+#define Tcl_RegExpMatchObj_TCL_DECLARED
/* 385 */
-EXTERN int Tcl_RegExpMatchObj _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * stringObj, Tcl_Obj * patternObj));
+EXTERN int Tcl_RegExpMatchObj(Tcl_Interp *interp,
+ Tcl_Obj *textObj, Tcl_Obj *patternObj);
+#endif
+#ifndef Tcl_SetNotifier_TCL_DECLARED
+#define Tcl_SetNotifier_TCL_DECLARED
/* 386 */
-EXTERN void Tcl_SetNotifier _ANSI_ARGS_((
- Tcl_NotifierProcs * notifierProcPtr));
+EXTERN void Tcl_SetNotifier(Tcl_NotifierProcs *notifierProcPtr);
+#endif
+#ifndef Tcl_GetAllocMutex_TCL_DECLARED
+#define Tcl_GetAllocMutex_TCL_DECLARED
/* 387 */
-EXTERN Tcl_Mutex * Tcl_GetAllocMutex _ANSI_ARGS_((void));
+EXTERN Tcl_Mutex * Tcl_GetAllocMutex(void);
+#endif
+#ifndef Tcl_GetChannelNames_TCL_DECLARED
+#define Tcl_GetChannelNames_TCL_DECLARED
/* 388 */
-EXTERN int Tcl_GetChannelNames _ANSI_ARGS_((Tcl_Interp * interp));
+EXTERN int Tcl_GetChannelNames(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_GetChannelNamesEx_TCL_DECLARED
+#define Tcl_GetChannelNamesEx_TCL_DECLARED
/* 389 */
-EXTERN int Tcl_GetChannelNamesEx _ANSI_ARGS_((
- Tcl_Interp * interp, CONST char * pattern));
+EXTERN int Tcl_GetChannelNamesEx(Tcl_Interp *interp,
+ CONST char *pattern);
+#endif
+#ifndef Tcl_ProcObjCmd_TCL_DECLARED
+#define Tcl_ProcObjCmd_TCL_DECLARED
/* 390 */
-EXTERN int Tcl_ProcObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp * interp, int objc,
- Tcl_Obj *CONST objv[]));
+EXTERN int Tcl_ProcObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]);
+#endif
+#ifndef Tcl_ConditionFinalize_TCL_DECLARED
+#define Tcl_ConditionFinalize_TCL_DECLARED
/* 391 */
-EXTERN void Tcl_ConditionFinalize _ANSI_ARGS_((
- Tcl_Condition * condPtr));
+EXTERN void Tcl_ConditionFinalize(Tcl_Condition *condPtr);
+#endif
+#ifndef Tcl_MutexFinalize_TCL_DECLARED
+#define Tcl_MutexFinalize_TCL_DECLARED
/* 392 */
-EXTERN void Tcl_MutexFinalize _ANSI_ARGS_((Tcl_Mutex * mutex));
+EXTERN void Tcl_MutexFinalize(Tcl_Mutex *mutex);
+#endif
+#ifndef Tcl_CreateThread_TCL_DECLARED
+#define Tcl_CreateThread_TCL_DECLARED
/* 393 */
-EXTERN int Tcl_CreateThread _ANSI_ARGS_((Tcl_ThreadId * idPtr,
- Tcl_ThreadCreateProc proc,
- ClientData clientData, int stackSize,
- int flags));
+EXTERN int Tcl_CreateThread(Tcl_ThreadId *idPtr,
+ Tcl_ThreadCreateProc proc,
+ ClientData clientData, int stackSize,
+ int flags);
+#endif
+#ifndef Tcl_ReadRaw_TCL_DECLARED
+#define Tcl_ReadRaw_TCL_DECLARED
/* 394 */
-EXTERN int Tcl_ReadRaw _ANSI_ARGS_((Tcl_Channel chan,
- char * dst, int bytesToRead));
+EXTERN int Tcl_ReadRaw(Tcl_Channel chan, char *dst,
+ int bytesToRead);
+#endif
+#ifndef Tcl_WriteRaw_TCL_DECLARED
+#define Tcl_WriteRaw_TCL_DECLARED
/* 395 */
-EXTERN int Tcl_WriteRaw _ANSI_ARGS_((Tcl_Channel chan,
- CONST char * src, int srcLen));
+EXTERN int Tcl_WriteRaw(Tcl_Channel chan, CONST char *src,
+ int srcLen);
+#endif
+#ifndef Tcl_GetTopChannel_TCL_DECLARED
+#define Tcl_GetTopChannel_TCL_DECLARED
/* 396 */
-EXTERN Tcl_Channel Tcl_GetTopChannel _ANSI_ARGS_((Tcl_Channel chan));
+EXTERN Tcl_Channel Tcl_GetTopChannel(Tcl_Channel chan);
+#endif
+#ifndef Tcl_ChannelBuffered_TCL_DECLARED
+#define Tcl_ChannelBuffered_TCL_DECLARED
/* 397 */
-EXTERN int Tcl_ChannelBuffered _ANSI_ARGS_((Tcl_Channel chan));
+EXTERN int Tcl_ChannelBuffered(Tcl_Channel chan);
+#endif
+#ifndef Tcl_ChannelName_TCL_DECLARED
+#define Tcl_ChannelName_TCL_DECLARED
/* 398 */
-EXTERN CONST84_RETURN char * Tcl_ChannelName _ANSI_ARGS_((
- Tcl_ChannelType * chanTypePtr));
+EXTERN CONST84_RETURN char * Tcl_ChannelName(
+ CONST Tcl_ChannelType *chanTypePtr);
+#endif
+#ifndef Tcl_ChannelVersion_TCL_DECLARED
+#define Tcl_ChannelVersion_TCL_DECLARED
/* 399 */
-EXTERN Tcl_ChannelTypeVersion Tcl_ChannelVersion _ANSI_ARGS_((
- Tcl_ChannelType * chanTypePtr));
+EXTERN Tcl_ChannelTypeVersion Tcl_ChannelVersion(
+ CONST Tcl_ChannelType *chanTypePtr);
+#endif
+#ifndef Tcl_ChannelBlockModeProc_TCL_DECLARED
+#define Tcl_ChannelBlockModeProc_TCL_DECLARED
/* 400 */
-EXTERN Tcl_DriverBlockModeProc * Tcl_ChannelBlockModeProc _ANSI_ARGS_((
- Tcl_ChannelType * chanTypePtr));
+EXTERN Tcl_DriverBlockModeProc * Tcl_ChannelBlockModeProc(
+ CONST Tcl_ChannelType *chanTypePtr);
+#endif
+#ifndef Tcl_ChannelCloseProc_TCL_DECLARED
+#define Tcl_ChannelCloseProc_TCL_DECLARED
/* 401 */
-EXTERN Tcl_DriverCloseProc * Tcl_ChannelCloseProc _ANSI_ARGS_((
- Tcl_ChannelType * chanTypePtr));
+EXTERN Tcl_DriverCloseProc * Tcl_ChannelCloseProc(
+ CONST Tcl_ChannelType *chanTypePtr);
+#endif
+#ifndef Tcl_ChannelClose2Proc_TCL_DECLARED
+#define Tcl_ChannelClose2Proc_TCL_DECLARED
/* 402 */
-EXTERN Tcl_DriverClose2Proc * Tcl_ChannelClose2Proc _ANSI_ARGS_((
- Tcl_ChannelType * chanTypePtr));
+EXTERN Tcl_DriverClose2Proc * Tcl_ChannelClose2Proc(
+ CONST Tcl_ChannelType *chanTypePtr);
+#endif
+#ifndef Tcl_ChannelInputProc_TCL_DECLARED
+#define Tcl_ChannelInputProc_TCL_DECLARED
/* 403 */
-EXTERN Tcl_DriverInputProc * Tcl_ChannelInputProc _ANSI_ARGS_((
- Tcl_ChannelType * chanTypePtr));
+EXTERN Tcl_DriverInputProc * Tcl_ChannelInputProc(
+ CONST Tcl_ChannelType *chanTypePtr);
+#endif
+#ifndef Tcl_ChannelOutputProc_TCL_DECLARED
+#define Tcl_ChannelOutputProc_TCL_DECLARED
/* 404 */
-EXTERN Tcl_DriverOutputProc * Tcl_ChannelOutputProc _ANSI_ARGS_((
- Tcl_ChannelType * chanTypePtr));
+EXTERN Tcl_DriverOutputProc * Tcl_ChannelOutputProc(
+ CONST Tcl_ChannelType *chanTypePtr);
+#endif
+#ifndef Tcl_ChannelSeekProc_TCL_DECLARED
+#define Tcl_ChannelSeekProc_TCL_DECLARED
/* 405 */
-EXTERN Tcl_DriverSeekProc * Tcl_ChannelSeekProc _ANSI_ARGS_((
- Tcl_ChannelType * chanTypePtr));
+EXTERN Tcl_DriverSeekProc * Tcl_ChannelSeekProc(
+ CONST Tcl_ChannelType *chanTypePtr);
+#endif
+#ifndef Tcl_ChannelSetOptionProc_TCL_DECLARED
+#define Tcl_ChannelSetOptionProc_TCL_DECLARED
/* 406 */
-EXTERN Tcl_DriverSetOptionProc * Tcl_ChannelSetOptionProc _ANSI_ARGS_((
- Tcl_ChannelType * chanTypePtr));
+EXTERN Tcl_DriverSetOptionProc * Tcl_ChannelSetOptionProc(
+ CONST Tcl_ChannelType *chanTypePtr);
+#endif
+#ifndef Tcl_ChannelGetOptionProc_TCL_DECLARED
+#define Tcl_ChannelGetOptionProc_TCL_DECLARED
/* 407 */
-EXTERN Tcl_DriverGetOptionProc * Tcl_ChannelGetOptionProc _ANSI_ARGS_((
- Tcl_ChannelType * chanTypePtr));
+EXTERN Tcl_DriverGetOptionProc * Tcl_ChannelGetOptionProc(
+ CONST Tcl_ChannelType *chanTypePtr);
+#endif
+#ifndef Tcl_ChannelWatchProc_TCL_DECLARED
+#define Tcl_ChannelWatchProc_TCL_DECLARED
/* 408 */
-EXTERN Tcl_DriverWatchProc * Tcl_ChannelWatchProc _ANSI_ARGS_((
- Tcl_ChannelType * chanTypePtr));
+EXTERN Tcl_DriverWatchProc * Tcl_ChannelWatchProc(
+ CONST Tcl_ChannelType *chanTypePtr);
+#endif
+#ifndef Tcl_ChannelGetHandleProc_TCL_DECLARED
+#define Tcl_ChannelGetHandleProc_TCL_DECLARED
/* 409 */
-EXTERN Tcl_DriverGetHandleProc * Tcl_ChannelGetHandleProc _ANSI_ARGS_((
- Tcl_ChannelType * chanTypePtr));
+EXTERN Tcl_DriverGetHandleProc * Tcl_ChannelGetHandleProc(
+ CONST Tcl_ChannelType *chanTypePtr);
+#endif
+#ifndef Tcl_ChannelFlushProc_TCL_DECLARED
+#define Tcl_ChannelFlushProc_TCL_DECLARED
/* 410 */
-EXTERN Tcl_DriverFlushProc * Tcl_ChannelFlushProc _ANSI_ARGS_((
- Tcl_ChannelType * chanTypePtr));
+EXTERN Tcl_DriverFlushProc * Tcl_ChannelFlushProc(
+ CONST Tcl_ChannelType *chanTypePtr);
+#endif
+#ifndef Tcl_ChannelHandlerProc_TCL_DECLARED
+#define Tcl_ChannelHandlerProc_TCL_DECLARED
/* 411 */
-EXTERN Tcl_DriverHandlerProc * Tcl_ChannelHandlerProc _ANSI_ARGS_((
- Tcl_ChannelType * chanTypePtr));
+EXTERN Tcl_DriverHandlerProc * Tcl_ChannelHandlerProc(
+ CONST Tcl_ChannelType *chanTypePtr);
+#endif
+#ifndef Tcl_JoinThread_TCL_DECLARED
+#define Tcl_JoinThread_TCL_DECLARED
/* 412 */
-EXTERN int Tcl_JoinThread _ANSI_ARGS_((Tcl_ThreadId threadId,
- int* result));
+EXTERN int Tcl_JoinThread(Tcl_ThreadId threadId, int *result);
+#endif
+#ifndef Tcl_IsChannelShared_TCL_DECLARED
+#define Tcl_IsChannelShared_TCL_DECLARED
/* 413 */
-EXTERN int Tcl_IsChannelShared _ANSI_ARGS_((Tcl_Channel channel));
+EXTERN int Tcl_IsChannelShared(Tcl_Channel channel);
+#endif
+#ifndef Tcl_IsChannelRegistered_TCL_DECLARED
+#define Tcl_IsChannelRegistered_TCL_DECLARED
/* 414 */
-EXTERN int Tcl_IsChannelRegistered _ANSI_ARGS_((
- Tcl_Interp* interp, Tcl_Channel channel));
+EXTERN int Tcl_IsChannelRegistered(Tcl_Interp *interp,
+ Tcl_Channel channel);
+#endif
+#ifndef Tcl_CutChannel_TCL_DECLARED
+#define Tcl_CutChannel_TCL_DECLARED
/* 415 */
-EXTERN void Tcl_CutChannel _ANSI_ARGS_((Tcl_Channel channel));
+EXTERN void Tcl_CutChannel(Tcl_Channel channel);
+#endif
+#ifndef Tcl_SpliceChannel_TCL_DECLARED
+#define Tcl_SpliceChannel_TCL_DECLARED
/* 416 */
-EXTERN void Tcl_SpliceChannel _ANSI_ARGS_((Tcl_Channel channel));
+EXTERN void Tcl_SpliceChannel(Tcl_Channel channel);
+#endif
+#ifndef Tcl_ClearChannelHandlers_TCL_DECLARED
+#define Tcl_ClearChannelHandlers_TCL_DECLARED
/* 417 */
-EXTERN void Tcl_ClearChannelHandlers _ANSI_ARGS_((
- Tcl_Channel channel));
+EXTERN void Tcl_ClearChannelHandlers(Tcl_Channel channel);
+#endif
+#ifndef Tcl_IsChannelExisting_TCL_DECLARED
+#define Tcl_IsChannelExisting_TCL_DECLARED
/* 418 */
-EXTERN int Tcl_IsChannelExisting _ANSI_ARGS_((
- CONST char* channelName));
+EXTERN int Tcl_IsChannelExisting(CONST char *channelName);
+#endif
+#ifndef Tcl_UniCharNcasecmp_TCL_DECLARED
+#define Tcl_UniCharNcasecmp_TCL_DECLARED
/* 419 */
-EXTERN int Tcl_UniCharNcasecmp _ANSI_ARGS_((
- CONST Tcl_UniChar * cs,
- CONST Tcl_UniChar * ct, unsigned long n));
+EXTERN int Tcl_UniCharNcasecmp(CONST Tcl_UniChar *ucs,
+ CONST Tcl_UniChar *uct,
+ unsigned long numChars);
+#endif
+#ifndef Tcl_UniCharCaseMatch_TCL_DECLARED
+#define Tcl_UniCharCaseMatch_TCL_DECLARED
/* 420 */
-EXTERN int Tcl_UniCharCaseMatch _ANSI_ARGS_((
- CONST Tcl_UniChar * ustr,
- CONST Tcl_UniChar * pattern, int nocase));
+EXTERN int Tcl_UniCharCaseMatch(CONST Tcl_UniChar *uniStr,
+ CONST Tcl_UniChar *uniPattern, int nocase);
+#endif
+#ifndef Tcl_FindHashEntry_TCL_DECLARED
+#define Tcl_FindHashEntry_TCL_DECLARED
/* 421 */
-EXTERN Tcl_HashEntry * Tcl_FindHashEntry _ANSI_ARGS_((
- Tcl_HashTable * tablePtr, CONST char * key));
+EXTERN Tcl_HashEntry * Tcl_FindHashEntry(Tcl_HashTable *tablePtr,
+ CONST char *key);
+#endif
+#ifndef Tcl_CreateHashEntry_TCL_DECLARED
+#define Tcl_CreateHashEntry_TCL_DECLARED
/* 422 */
-EXTERN Tcl_HashEntry * Tcl_CreateHashEntry _ANSI_ARGS_((
- Tcl_HashTable * tablePtr, CONST char * key,
- int * newPtr));
+EXTERN Tcl_HashEntry * Tcl_CreateHashEntry(Tcl_HashTable *tablePtr,
+ CONST char *key, int *newPtr);
+#endif
+#ifndef Tcl_InitCustomHashTable_TCL_DECLARED
+#define Tcl_InitCustomHashTable_TCL_DECLARED
/* 423 */
-EXTERN void Tcl_InitCustomHashTable _ANSI_ARGS_((
- Tcl_HashTable * tablePtr, int keyType,
- Tcl_HashKeyType * typePtr));
+EXTERN void Tcl_InitCustomHashTable(Tcl_HashTable *tablePtr,
+ int keyType, Tcl_HashKeyType *typePtr);
+#endif
+#ifndef Tcl_InitObjHashTable_TCL_DECLARED
+#define Tcl_InitObjHashTable_TCL_DECLARED
/* 424 */
-EXTERN void Tcl_InitObjHashTable _ANSI_ARGS_((
- Tcl_HashTable * tablePtr));
+EXTERN void Tcl_InitObjHashTable(Tcl_HashTable *tablePtr);
+#endif
+#ifndef Tcl_CommandTraceInfo_TCL_DECLARED
+#define Tcl_CommandTraceInfo_TCL_DECLARED
/* 425 */
-EXTERN ClientData Tcl_CommandTraceInfo _ANSI_ARGS_((
- Tcl_Interp * interp, CONST char * varName,
- int flags, Tcl_CommandTraceProc * procPtr,
- ClientData prevClientData));
+EXTERN ClientData Tcl_CommandTraceInfo(Tcl_Interp *interp,
+ CONST char *varName, int flags,
+ Tcl_CommandTraceProc *procPtr,
+ ClientData prevClientData);
+#endif
+#ifndef Tcl_TraceCommand_TCL_DECLARED
+#define Tcl_TraceCommand_TCL_DECLARED
/* 426 */
-EXTERN int Tcl_TraceCommand _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * varName, int flags,
- Tcl_CommandTraceProc * proc,
- ClientData clientData));
+EXTERN int Tcl_TraceCommand(Tcl_Interp *interp,
+ CONST char *varName, int flags,
+ Tcl_CommandTraceProc *proc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_UntraceCommand_TCL_DECLARED
+#define Tcl_UntraceCommand_TCL_DECLARED
/* 427 */
-EXTERN void Tcl_UntraceCommand _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * varName, int flags,
- Tcl_CommandTraceProc * proc,
- ClientData clientData));
+EXTERN void Tcl_UntraceCommand(Tcl_Interp *interp,
+ CONST char *varName, int flags,
+ Tcl_CommandTraceProc *proc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_AttemptAlloc_TCL_DECLARED
+#define Tcl_AttemptAlloc_TCL_DECLARED
/* 428 */
-EXTERN char * Tcl_AttemptAlloc _ANSI_ARGS_((unsigned int size));
+EXTERN char * Tcl_AttemptAlloc(unsigned int size);
+#endif
+#ifndef Tcl_AttemptDbCkalloc_TCL_DECLARED
+#define Tcl_AttemptDbCkalloc_TCL_DECLARED
/* 429 */
-EXTERN char * Tcl_AttemptDbCkalloc _ANSI_ARGS_((unsigned int size,
- CONST char * file, int line));
+EXTERN char * Tcl_AttemptDbCkalloc(unsigned int size,
+ CONST char *file, int line);
+#endif
+#ifndef Tcl_AttemptRealloc_TCL_DECLARED
+#define Tcl_AttemptRealloc_TCL_DECLARED
/* 430 */
-EXTERN char * Tcl_AttemptRealloc _ANSI_ARGS_((char * ptr,
- unsigned int size));
+EXTERN char * Tcl_AttemptRealloc(char *ptr, unsigned int size);
+#endif
+#ifndef Tcl_AttemptDbCkrealloc_TCL_DECLARED
+#define Tcl_AttemptDbCkrealloc_TCL_DECLARED
/* 431 */
-EXTERN char * Tcl_AttemptDbCkrealloc _ANSI_ARGS_((char * ptr,
- unsigned int size, CONST char * file,
- int line));
+EXTERN char * Tcl_AttemptDbCkrealloc(char *ptr, unsigned int size,
+ CONST char *file, int line);
+#endif
+#ifndef Tcl_AttemptSetObjLength_TCL_DECLARED
+#define Tcl_AttemptSetObjLength_TCL_DECLARED
/* 432 */
-EXTERN int Tcl_AttemptSetObjLength _ANSI_ARGS_((
- Tcl_Obj * objPtr, int length));
+EXTERN int Tcl_AttemptSetObjLength(Tcl_Obj *objPtr, int length);
+#endif
+#ifndef Tcl_GetChannelThread_TCL_DECLARED
+#define Tcl_GetChannelThread_TCL_DECLARED
/* 433 */
-EXTERN Tcl_ThreadId Tcl_GetChannelThread _ANSI_ARGS_((
- Tcl_Channel channel));
+EXTERN Tcl_ThreadId Tcl_GetChannelThread(Tcl_Channel channel);
+#endif
+#ifndef Tcl_GetUnicodeFromObj_TCL_DECLARED
+#define Tcl_GetUnicodeFromObj_TCL_DECLARED
/* 434 */
-EXTERN Tcl_UniChar * Tcl_GetUnicodeFromObj _ANSI_ARGS_((Tcl_Obj * objPtr,
- int * lengthPtr));
+EXTERN Tcl_UniChar * Tcl_GetUnicodeFromObj(Tcl_Obj *objPtr,
+ int *lengthPtr);
+#endif
+#ifndef Tcl_GetMathFuncInfo_TCL_DECLARED
+#define Tcl_GetMathFuncInfo_TCL_DECLARED
/* 435 */
-EXTERN int Tcl_GetMathFuncInfo _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * name, int * numArgsPtr,
- Tcl_ValueType ** argTypesPtr,
- Tcl_MathProc ** procPtr,
- ClientData * clientDataPtr));
+EXTERN int Tcl_GetMathFuncInfo(Tcl_Interp *interp,
+ CONST char *name, int *numArgsPtr,
+ Tcl_ValueType **argTypesPtr,
+ Tcl_MathProc **procPtr,
+ ClientData *clientDataPtr);
+#endif
+#ifndef Tcl_ListMathFuncs_TCL_DECLARED
+#define Tcl_ListMathFuncs_TCL_DECLARED
/* 436 */
-EXTERN Tcl_Obj * Tcl_ListMathFuncs _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * pattern));
+EXTERN Tcl_Obj * Tcl_ListMathFuncs(Tcl_Interp *interp,
+ CONST char *pattern);
+#endif
+#ifndef Tcl_SubstObj_TCL_DECLARED
+#define Tcl_SubstObj_TCL_DECLARED
/* 437 */
-EXTERN Tcl_Obj * Tcl_SubstObj _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * objPtr, int flags));
+EXTERN Tcl_Obj * Tcl_SubstObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ int flags);
+#endif
+#ifndef Tcl_DetachChannel_TCL_DECLARED
+#define Tcl_DetachChannel_TCL_DECLARED
/* 438 */
-EXTERN int Tcl_DetachChannel _ANSI_ARGS_((Tcl_Interp* interp,
- Tcl_Channel channel));
+EXTERN int Tcl_DetachChannel(Tcl_Interp *interp,
+ Tcl_Channel channel);
+#endif
+#ifndef Tcl_IsStandardChannel_TCL_DECLARED
+#define Tcl_IsStandardChannel_TCL_DECLARED
/* 439 */
-EXTERN int Tcl_IsStandardChannel _ANSI_ARGS_((
- Tcl_Channel channel));
+EXTERN int Tcl_IsStandardChannel(Tcl_Channel channel);
+#endif
+#ifndef Tcl_FSCopyFile_TCL_DECLARED
+#define Tcl_FSCopyFile_TCL_DECLARED
/* 440 */
-EXTERN int Tcl_FSCopyFile _ANSI_ARGS_((Tcl_Obj * srcPathPtr,
- Tcl_Obj * destPathPtr));
+EXTERN int Tcl_FSCopyFile(Tcl_Obj *srcPathPtr,
+ Tcl_Obj *destPathPtr);
+#endif
+#ifndef Tcl_FSCopyDirectory_TCL_DECLARED
+#define Tcl_FSCopyDirectory_TCL_DECLARED
/* 441 */
-EXTERN int Tcl_FSCopyDirectory _ANSI_ARGS_((
- Tcl_Obj * srcPathPtr, Tcl_Obj * destPathPtr,
- Tcl_Obj ** errorPtr));
+EXTERN int Tcl_FSCopyDirectory(Tcl_Obj *srcPathPtr,
+ Tcl_Obj *destPathPtr, Tcl_Obj **errorPtr);
+#endif
+#ifndef Tcl_FSCreateDirectory_TCL_DECLARED
+#define Tcl_FSCreateDirectory_TCL_DECLARED
/* 442 */
-EXTERN int Tcl_FSCreateDirectory _ANSI_ARGS_((Tcl_Obj * pathPtr));
+EXTERN int Tcl_FSCreateDirectory(Tcl_Obj *pathPtr);
+#endif
+#ifndef Tcl_FSDeleteFile_TCL_DECLARED
+#define Tcl_FSDeleteFile_TCL_DECLARED
/* 443 */
-EXTERN int Tcl_FSDeleteFile _ANSI_ARGS_((Tcl_Obj * pathPtr));
+EXTERN int Tcl_FSDeleteFile(Tcl_Obj *pathPtr);
+#endif
+#ifndef Tcl_FSLoadFile_TCL_DECLARED
+#define Tcl_FSLoadFile_TCL_DECLARED
/* 444 */
-EXTERN int Tcl_FSLoadFile _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * pathPtr, CONST char * sym1,
- CONST char * sym2,
- Tcl_PackageInitProc ** proc1Ptr,
- Tcl_PackageInitProc ** proc2Ptr,
- Tcl_LoadHandle * handlePtr,
- Tcl_FSUnloadFileProc ** unloadProcPtr));
+EXTERN int Tcl_FSLoadFile(Tcl_Interp *interp, Tcl_Obj *pathPtr,
+ CONST char *sym1, CONST char *sym2,
+ Tcl_PackageInitProc **proc1Ptr,
+ Tcl_PackageInitProc **proc2Ptr,
+ Tcl_LoadHandle *handlePtr,
+ Tcl_FSUnloadFileProc **unloadProcPtr);
+#endif
+#ifndef Tcl_FSMatchInDirectory_TCL_DECLARED
+#define Tcl_FSMatchInDirectory_TCL_DECLARED
/* 445 */
-EXTERN int Tcl_FSMatchInDirectory _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Obj * result,
- Tcl_Obj * pathPtr, CONST char * pattern,
- Tcl_GlobTypeData * types));
+EXTERN int Tcl_FSMatchInDirectory(Tcl_Interp *interp,
+ Tcl_Obj *result, Tcl_Obj *pathPtr,
+ CONST char *pattern, Tcl_GlobTypeData *types);
+#endif
+#ifndef Tcl_FSLink_TCL_DECLARED
+#define Tcl_FSLink_TCL_DECLARED
/* 446 */
-EXTERN Tcl_Obj * Tcl_FSLink _ANSI_ARGS_((Tcl_Obj * pathPtr,
- Tcl_Obj * toPtr, int linkAction));
+EXTERN Tcl_Obj * Tcl_FSLink(Tcl_Obj *pathPtr, Tcl_Obj *toPtr,
+ int linkAction);
+#endif
+#ifndef Tcl_FSRemoveDirectory_TCL_DECLARED
+#define Tcl_FSRemoveDirectory_TCL_DECLARED
/* 447 */
-EXTERN int Tcl_FSRemoveDirectory _ANSI_ARGS_((Tcl_Obj * pathPtr,
- int recursive, Tcl_Obj ** errorPtr));
+EXTERN int Tcl_FSRemoveDirectory(Tcl_Obj *pathPtr,
+ int recursive, Tcl_Obj **errorPtr);
+#endif
+#ifndef Tcl_FSRenameFile_TCL_DECLARED
+#define Tcl_FSRenameFile_TCL_DECLARED
/* 448 */
-EXTERN int Tcl_FSRenameFile _ANSI_ARGS_((Tcl_Obj * srcPathPtr,
- Tcl_Obj * destPathPtr));
+EXTERN int Tcl_FSRenameFile(Tcl_Obj *srcPathPtr,
+ Tcl_Obj *destPathPtr);
+#endif
+#ifndef Tcl_FSLstat_TCL_DECLARED
+#define Tcl_FSLstat_TCL_DECLARED
/* 449 */
-EXTERN int Tcl_FSLstat _ANSI_ARGS_((Tcl_Obj * pathPtr,
- Tcl_StatBuf * buf));
+EXTERN int Tcl_FSLstat(Tcl_Obj *pathPtr, Tcl_StatBuf *buf);
+#endif
+#ifndef Tcl_FSUtime_TCL_DECLARED
+#define Tcl_FSUtime_TCL_DECLARED
/* 450 */
-EXTERN int Tcl_FSUtime _ANSI_ARGS_((Tcl_Obj * pathPtr,
- struct utimbuf * tval));
+EXTERN int Tcl_FSUtime(Tcl_Obj *pathPtr, struct utimbuf *tval);
+#endif
+#ifndef Tcl_FSFileAttrsGet_TCL_DECLARED
+#define Tcl_FSFileAttrsGet_TCL_DECLARED
/* 451 */
-EXTERN int Tcl_FSFileAttrsGet _ANSI_ARGS_((Tcl_Interp * interp,
- int index, Tcl_Obj * pathPtr,
- Tcl_Obj ** objPtrRef));
+EXTERN int Tcl_FSFileAttrsGet(Tcl_Interp *interp, int index,
+ Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef);
+#endif
+#ifndef Tcl_FSFileAttrsSet_TCL_DECLARED
+#define Tcl_FSFileAttrsSet_TCL_DECLARED
/* 452 */
-EXTERN int Tcl_FSFileAttrsSet _ANSI_ARGS_((Tcl_Interp * interp,
- int index, Tcl_Obj * pathPtr,
- Tcl_Obj * objPtr));
+EXTERN int Tcl_FSFileAttrsSet(Tcl_Interp *interp, int index,
+ Tcl_Obj *pathPtr, Tcl_Obj *objPtr);
+#endif
+#ifndef Tcl_FSFileAttrStrings_TCL_DECLARED
+#define Tcl_FSFileAttrStrings_TCL_DECLARED
/* 453 */
-EXTERN CONST char ** Tcl_FSFileAttrStrings _ANSI_ARGS_((Tcl_Obj * pathPtr,
- Tcl_Obj ** objPtrRef));
+EXTERN CONST char ** Tcl_FSFileAttrStrings(Tcl_Obj *pathPtr,
+ Tcl_Obj **objPtrRef);
+#endif
+#ifndef Tcl_FSStat_TCL_DECLARED
+#define Tcl_FSStat_TCL_DECLARED
/* 454 */
-EXTERN int Tcl_FSStat _ANSI_ARGS_((Tcl_Obj * pathPtr,
- Tcl_StatBuf * buf));
+EXTERN int Tcl_FSStat(Tcl_Obj *pathPtr, Tcl_StatBuf *buf);
+#endif
+#ifndef Tcl_FSAccess_TCL_DECLARED
+#define Tcl_FSAccess_TCL_DECLARED
/* 455 */
-EXTERN int Tcl_FSAccess _ANSI_ARGS_((Tcl_Obj * pathPtr,
- int mode));
+EXTERN int Tcl_FSAccess(Tcl_Obj *pathPtr, int mode);
+#endif
+#ifndef Tcl_FSOpenFileChannel_TCL_DECLARED
+#define Tcl_FSOpenFileChannel_TCL_DECLARED
/* 456 */
-EXTERN Tcl_Channel Tcl_FSOpenFileChannel _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Obj * pathPtr,
- CONST char * modeString, int permissions));
+EXTERN Tcl_Channel Tcl_FSOpenFileChannel(Tcl_Interp *interp,
+ Tcl_Obj *pathPtr, CONST char *modeString,
+ int permissions);
+#endif
+#ifndef Tcl_FSGetCwd_TCL_DECLARED
+#define Tcl_FSGetCwd_TCL_DECLARED
/* 457 */
-EXTERN Tcl_Obj* Tcl_FSGetCwd _ANSI_ARGS_((Tcl_Interp * interp));
+EXTERN Tcl_Obj * Tcl_FSGetCwd(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_FSChdir_TCL_DECLARED
+#define Tcl_FSChdir_TCL_DECLARED
/* 458 */
-EXTERN int Tcl_FSChdir _ANSI_ARGS_((Tcl_Obj * pathPtr));
+EXTERN int Tcl_FSChdir(Tcl_Obj *pathPtr);
+#endif
+#ifndef Tcl_FSConvertToPathType_TCL_DECLARED
+#define Tcl_FSConvertToPathType_TCL_DECLARED
/* 459 */
-EXTERN int Tcl_FSConvertToPathType _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Obj * pathPtr));
+EXTERN int Tcl_FSConvertToPathType(Tcl_Interp *interp,
+ Tcl_Obj *pathPtr);
+#endif
+#ifndef Tcl_FSJoinPath_TCL_DECLARED
+#define Tcl_FSJoinPath_TCL_DECLARED
/* 460 */
-EXTERN Tcl_Obj* Tcl_FSJoinPath _ANSI_ARGS_((Tcl_Obj * listObj,
- int elements));
+EXTERN Tcl_Obj * Tcl_FSJoinPath(Tcl_Obj *listObj, int elements);
+#endif
+#ifndef Tcl_FSSplitPath_TCL_DECLARED
+#define Tcl_FSSplitPath_TCL_DECLARED
/* 461 */
-EXTERN Tcl_Obj* Tcl_FSSplitPath _ANSI_ARGS_((Tcl_Obj* pathPtr,
- int * lenPtr));
+EXTERN Tcl_Obj * Tcl_FSSplitPath(Tcl_Obj *pathPtr, int *lenPtr);
+#endif
+#ifndef Tcl_FSEqualPaths_TCL_DECLARED
+#define Tcl_FSEqualPaths_TCL_DECLARED
/* 462 */
-EXTERN int Tcl_FSEqualPaths _ANSI_ARGS_((Tcl_Obj* firstPtr,
- Tcl_Obj* secondPtr));
+EXTERN int Tcl_FSEqualPaths(Tcl_Obj *firstPtr,
+ Tcl_Obj *secondPtr);
+#endif
+#ifndef Tcl_FSGetNormalizedPath_TCL_DECLARED
+#define Tcl_FSGetNormalizedPath_TCL_DECLARED
/* 463 */
-EXTERN Tcl_Obj* Tcl_FSGetNormalizedPath _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Obj* pathObjPtr));
+EXTERN Tcl_Obj * Tcl_FSGetNormalizedPath(Tcl_Interp *interp,
+ Tcl_Obj *pathPtr);
+#endif
+#ifndef Tcl_FSJoinToPath_TCL_DECLARED
+#define Tcl_FSJoinToPath_TCL_DECLARED
/* 464 */
-EXTERN Tcl_Obj* Tcl_FSJoinToPath _ANSI_ARGS_((Tcl_Obj * basePtr,
- int objc, Tcl_Obj *CONST objv[]));
+EXTERN Tcl_Obj * Tcl_FSJoinToPath(Tcl_Obj *pathPtr, int objc,
+ Tcl_Obj *CONST objv[]);
+#endif
+#ifndef Tcl_FSGetInternalRep_TCL_DECLARED
+#define Tcl_FSGetInternalRep_TCL_DECLARED
/* 465 */
-EXTERN ClientData Tcl_FSGetInternalRep _ANSI_ARGS_((
- Tcl_Obj* pathObjPtr, Tcl_Filesystem * fsPtr));
+EXTERN ClientData Tcl_FSGetInternalRep(Tcl_Obj *pathPtr,
+ Tcl_Filesystem *fsPtr);
+#endif
+#ifndef Tcl_FSGetTranslatedPath_TCL_DECLARED
+#define Tcl_FSGetTranslatedPath_TCL_DECLARED
/* 466 */
-EXTERN Tcl_Obj* Tcl_FSGetTranslatedPath _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Obj* pathPtr));
+EXTERN Tcl_Obj * Tcl_FSGetTranslatedPath(Tcl_Interp *interp,
+ Tcl_Obj *pathPtr);
+#endif
+#ifndef Tcl_FSEvalFile_TCL_DECLARED
+#define Tcl_FSEvalFile_TCL_DECLARED
/* 467 */
-EXTERN int Tcl_FSEvalFile _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * fileName));
+EXTERN int Tcl_FSEvalFile(Tcl_Interp *interp, Tcl_Obj *fileName);
+#endif
+#ifndef Tcl_FSNewNativePath_TCL_DECLARED
+#define Tcl_FSNewNativePath_TCL_DECLARED
/* 468 */
-EXTERN Tcl_Obj* Tcl_FSNewNativePath _ANSI_ARGS_((
- Tcl_Filesystem* fromFilesystem,
- ClientData clientData));
+EXTERN Tcl_Obj * Tcl_FSNewNativePath(Tcl_Filesystem *fromFilesystem,
+ ClientData clientData);
+#endif
+#ifndef Tcl_FSGetNativePath_TCL_DECLARED
+#define Tcl_FSGetNativePath_TCL_DECLARED
/* 469 */
-EXTERN CONST char* Tcl_FSGetNativePath _ANSI_ARGS_((Tcl_Obj* pathObjPtr));
+EXTERN CONST char * Tcl_FSGetNativePath(Tcl_Obj *pathPtr);
+#endif
+#ifndef Tcl_FSFileSystemInfo_TCL_DECLARED
+#define Tcl_FSFileSystemInfo_TCL_DECLARED
/* 470 */
-EXTERN Tcl_Obj* Tcl_FSFileSystemInfo _ANSI_ARGS_((
- Tcl_Obj* pathObjPtr));
+EXTERN Tcl_Obj * Tcl_FSFileSystemInfo(Tcl_Obj *pathPtr);
+#endif
+#ifndef Tcl_FSPathSeparator_TCL_DECLARED
+#define Tcl_FSPathSeparator_TCL_DECLARED
/* 471 */
-EXTERN Tcl_Obj* Tcl_FSPathSeparator _ANSI_ARGS_((Tcl_Obj* pathObjPtr));
+EXTERN Tcl_Obj * Tcl_FSPathSeparator(Tcl_Obj *pathPtr);
+#endif
+#ifndef Tcl_FSListVolumes_TCL_DECLARED
+#define Tcl_FSListVolumes_TCL_DECLARED
/* 472 */
-EXTERN Tcl_Obj* Tcl_FSListVolumes _ANSI_ARGS_((void));
+EXTERN Tcl_Obj * Tcl_FSListVolumes(void);
+#endif
+#ifndef Tcl_FSRegister_TCL_DECLARED
+#define Tcl_FSRegister_TCL_DECLARED
/* 473 */
-EXTERN int Tcl_FSRegister _ANSI_ARGS_((ClientData clientData,
- Tcl_Filesystem * fsPtr));
+EXTERN int Tcl_FSRegister(ClientData clientData,
+ Tcl_Filesystem *fsPtr);
+#endif
+#ifndef Tcl_FSUnregister_TCL_DECLARED
+#define Tcl_FSUnregister_TCL_DECLARED
/* 474 */
-EXTERN int Tcl_FSUnregister _ANSI_ARGS_((Tcl_Filesystem * fsPtr));
+EXTERN int Tcl_FSUnregister(Tcl_Filesystem *fsPtr);
+#endif
+#ifndef Tcl_FSData_TCL_DECLARED
+#define Tcl_FSData_TCL_DECLARED
/* 475 */
-EXTERN ClientData Tcl_FSData _ANSI_ARGS_((Tcl_Filesystem * fsPtr));
+EXTERN ClientData Tcl_FSData(Tcl_Filesystem *fsPtr);
+#endif
+#ifndef Tcl_FSGetTranslatedStringPath_TCL_DECLARED
+#define Tcl_FSGetTranslatedStringPath_TCL_DECLARED
/* 476 */
-EXTERN CONST char* Tcl_FSGetTranslatedStringPath _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Obj* pathPtr));
+EXTERN CONST char * Tcl_FSGetTranslatedStringPath(Tcl_Interp *interp,
+ Tcl_Obj *pathPtr);
+#endif
+#ifndef Tcl_FSGetFileSystemForPath_TCL_DECLARED
+#define Tcl_FSGetFileSystemForPath_TCL_DECLARED
/* 477 */
-EXTERN Tcl_Filesystem* Tcl_FSGetFileSystemForPath _ANSI_ARGS_((
- Tcl_Obj* pathObjPtr));
+EXTERN Tcl_Filesystem * Tcl_FSGetFileSystemForPath(Tcl_Obj *pathPtr);
+#endif
+#ifndef Tcl_FSGetPathType_TCL_DECLARED
+#define Tcl_FSGetPathType_TCL_DECLARED
/* 478 */
-EXTERN Tcl_PathType Tcl_FSGetPathType _ANSI_ARGS_((Tcl_Obj * pathObjPtr));
+EXTERN Tcl_PathType Tcl_FSGetPathType(Tcl_Obj *pathPtr);
+#endif
+#ifndef Tcl_OutputBuffered_TCL_DECLARED
+#define Tcl_OutputBuffered_TCL_DECLARED
/* 479 */
-EXTERN int Tcl_OutputBuffered _ANSI_ARGS_((Tcl_Channel chan));
+EXTERN int Tcl_OutputBuffered(Tcl_Channel chan);
+#endif
+#ifndef Tcl_FSMountsChanged_TCL_DECLARED
+#define Tcl_FSMountsChanged_TCL_DECLARED
/* 480 */
-EXTERN void Tcl_FSMountsChanged _ANSI_ARGS_((
- Tcl_Filesystem * fsPtr));
+EXTERN void Tcl_FSMountsChanged(Tcl_Filesystem *fsPtr);
+#endif
+#ifndef Tcl_EvalTokensStandard_TCL_DECLARED
+#define Tcl_EvalTokensStandard_TCL_DECLARED
/* 481 */
-EXTERN int Tcl_EvalTokensStandard _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Token * tokenPtr,
- int count));
+EXTERN int Tcl_EvalTokensStandard(Tcl_Interp *interp,
+ Tcl_Token *tokenPtr, int count);
+#endif
+#ifndef Tcl_GetTime_TCL_DECLARED
+#define Tcl_GetTime_TCL_DECLARED
/* 482 */
-EXTERN void Tcl_GetTime _ANSI_ARGS_((Tcl_Time* timeBuf));
+EXTERN void Tcl_GetTime(Tcl_Time *timeBuf);
+#endif
+#ifndef Tcl_CreateObjTrace_TCL_DECLARED
+#define Tcl_CreateObjTrace_TCL_DECLARED
/* 483 */
-EXTERN Tcl_Trace Tcl_CreateObjTrace _ANSI_ARGS_((Tcl_Interp* interp,
- int level, int flags,
- Tcl_CmdObjTraceProc* objProc,
- ClientData clientData,
- Tcl_CmdObjTraceDeleteProc* delProc));
+EXTERN Tcl_Trace Tcl_CreateObjTrace(Tcl_Interp *interp, int level,
+ int flags, Tcl_CmdObjTraceProc *objProc,
+ ClientData clientData,
+ Tcl_CmdObjTraceDeleteProc *delProc);
+#endif
+#ifndef Tcl_GetCommandInfoFromToken_TCL_DECLARED
+#define Tcl_GetCommandInfoFromToken_TCL_DECLARED
/* 484 */
-EXTERN int Tcl_GetCommandInfoFromToken _ANSI_ARGS_((
- Tcl_Command token, Tcl_CmdInfo* infoPtr));
+EXTERN int Tcl_GetCommandInfoFromToken(Tcl_Command token,
+ Tcl_CmdInfo *infoPtr);
+#endif
+#ifndef Tcl_SetCommandInfoFromToken_TCL_DECLARED
+#define Tcl_SetCommandInfoFromToken_TCL_DECLARED
/* 485 */
-EXTERN int Tcl_SetCommandInfoFromToken _ANSI_ARGS_((
- Tcl_Command token,
- CONST Tcl_CmdInfo* infoPtr));
+EXTERN int Tcl_SetCommandInfoFromToken(Tcl_Command token,
+ CONST Tcl_CmdInfo *infoPtr);
+#endif
+#ifndef Tcl_DbNewWideIntObj_TCL_DECLARED
+#define Tcl_DbNewWideIntObj_TCL_DECLARED
/* 486 */
-EXTERN Tcl_Obj * Tcl_DbNewWideIntObj _ANSI_ARGS_((
- Tcl_WideInt wideValue, CONST char * file,
- int line));
+EXTERN Tcl_Obj * Tcl_DbNewWideIntObj(Tcl_WideInt wideValue,
+ CONST char *file, int line);
+#endif
+#ifndef Tcl_GetWideIntFromObj_TCL_DECLARED
+#define Tcl_GetWideIntFromObj_TCL_DECLARED
/* 487 */
-EXTERN int Tcl_GetWideIntFromObj _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Obj * objPtr,
- Tcl_WideInt * widePtr));
+EXTERN int Tcl_GetWideIntFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, Tcl_WideInt *widePtr);
+#endif
+#ifndef Tcl_NewWideIntObj_TCL_DECLARED
+#define Tcl_NewWideIntObj_TCL_DECLARED
/* 488 */
-EXTERN Tcl_Obj * Tcl_NewWideIntObj _ANSI_ARGS_((Tcl_WideInt wideValue));
+EXTERN Tcl_Obj * Tcl_NewWideIntObj(Tcl_WideInt wideValue);
+#endif
+#ifndef Tcl_SetWideIntObj_TCL_DECLARED
+#define Tcl_SetWideIntObj_TCL_DECLARED
/* 489 */
-EXTERN void Tcl_SetWideIntObj _ANSI_ARGS_((Tcl_Obj * objPtr,
- Tcl_WideInt wideValue));
+EXTERN void Tcl_SetWideIntObj(Tcl_Obj *objPtr,
+ Tcl_WideInt wideValue);
+#endif
+#ifndef Tcl_AllocStatBuf_TCL_DECLARED
+#define Tcl_AllocStatBuf_TCL_DECLARED
/* 490 */
-EXTERN Tcl_StatBuf * Tcl_AllocStatBuf _ANSI_ARGS_((void));
+EXTERN Tcl_StatBuf * Tcl_AllocStatBuf(void);
+#endif
+#ifndef Tcl_Seek_TCL_DECLARED
+#define Tcl_Seek_TCL_DECLARED
/* 491 */
-EXTERN Tcl_WideInt Tcl_Seek _ANSI_ARGS_((Tcl_Channel chan,
- Tcl_WideInt offset, int mode));
+EXTERN Tcl_WideInt Tcl_Seek(Tcl_Channel chan, Tcl_WideInt offset,
+ int mode);
+#endif
+#ifndef Tcl_Tell_TCL_DECLARED
+#define Tcl_Tell_TCL_DECLARED
/* 492 */
-EXTERN Tcl_WideInt Tcl_Tell _ANSI_ARGS_((Tcl_Channel chan));
+EXTERN Tcl_WideInt Tcl_Tell(Tcl_Channel chan);
+#endif
+#ifndef Tcl_ChannelWideSeekProc_TCL_DECLARED
+#define Tcl_ChannelWideSeekProc_TCL_DECLARED
/* 493 */
-EXTERN Tcl_DriverWideSeekProc * Tcl_ChannelWideSeekProc _ANSI_ARGS_((
- Tcl_ChannelType * chanTypePtr));
-/* Slot 494 is reserved */
-/* Slot 495 is reserved */
-/* Slot 496 is reserved */
-/* Slot 497 is reserved */
-/* Slot 498 is reserved */
-/* Slot 499 is reserved */
-/* Slot 500 is reserved */
-/* Slot 501 is reserved */
-/* Slot 502 is reserved */
-/* Slot 503 is reserved */
-/* Slot 504 is reserved */
-/* Slot 505 is reserved */
-/* Slot 506 is reserved */
-/* Slot 507 is reserved */
-/* Slot 508 is reserved */
-/* Slot 509 is reserved */
-/* Slot 510 is reserved */
-/* Slot 511 is reserved */
-/* Slot 512 is reserved */
-/* Slot 513 is reserved */
-/* Slot 514 is reserved */
-/* Slot 515 is reserved */
-/* Slot 516 is reserved */
-/* Slot 517 is reserved */
-/* Slot 518 is reserved */
-/* Slot 519 is reserved */
-/* Slot 520 is reserved */
-/* Slot 521 is reserved */
-/* Slot 522 is reserved */
-/* Slot 523 is reserved */
-/* Slot 524 is reserved */
-/* Slot 525 is reserved */
-/* Slot 526 is reserved */
-/* Slot 527 is reserved */
-/* Slot 528 is reserved */
-/* Slot 529 is reserved */
-/* Slot 530 is reserved */
-/* Slot 531 is reserved */
-/* Slot 532 is reserved */
-/* Slot 533 is reserved */
-/* Slot 534 is reserved */
-/* Slot 535 is reserved */
-/* Slot 536 is reserved */
-/* Slot 537 is reserved */
-/* Slot 538 is reserved */
-/* Slot 539 is reserved */
-/* Slot 540 is reserved */
-/* Slot 541 is reserved */
-/* Slot 542 is reserved */
-/* Slot 543 is reserved */
-/* Slot 544 is reserved */
-/* Slot 545 is reserved */
-/* Slot 546 is reserved */
-/* Slot 547 is reserved */
-/* Slot 548 is reserved */
-/* Slot 549 is reserved */
-/* Slot 550 is reserved */
-/* Slot 551 is reserved */
-/* Slot 552 is reserved */
-/* Slot 553 is reserved */
+EXTERN Tcl_DriverWideSeekProc * Tcl_ChannelWideSeekProc(
+ CONST Tcl_ChannelType *chanTypePtr);
+#endif
+#ifndef Tcl_DictObjPut_TCL_DECLARED
+#define Tcl_DictObjPut_TCL_DECLARED
+/* 494 */
+EXTERN int Tcl_DictObjPut(Tcl_Interp *interp, Tcl_Obj *dictPtr,
+ Tcl_Obj *keyPtr, Tcl_Obj *valuePtr);
+#endif
+#ifndef Tcl_DictObjGet_TCL_DECLARED
+#define Tcl_DictObjGet_TCL_DECLARED
+/* 495 */
+EXTERN int Tcl_DictObjGet(Tcl_Interp *interp, Tcl_Obj *dictPtr,
+ Tcl_Obj *keyPtr, Tcl_Obj **valuePtrPtr);
+#endif
+#ifndef Tcl_DictObjRemove_TCL_DECLARED
+#define Tcl_DictObjRemove_TCL_DECLARED
+/* 496 */
+EXTERN int Tcl_DictObjRemove(Tcl_Interp *interp,
+ Tcl_Obj *dictPtr, Tcl_Obj *keyPtr);
+#endif
+#ifndef Tcl_DictObjSize_TCL_DECLARED
+#define Tcl_DictObjSize_TCL_DECLARED
+/* 497 */
+EXTERN int Tcl_DictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr,
+ int *sizePtr);
+#endif
+#ifndef Tcl_DictObjFirst_TCL_DECLARED
+#define Tcl_DictObjFirst_TCL_DECLARED
+/* 498 */
+EXTERN int Tcl_DictObjFirst(Tcl_Interp *interp,
+ Tcl_Obj *dictPtr, Tcl_DictSearch *searchPtr,
+ Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr,
+ int *donePtr);
+#endif
+#ifndef Tcl_DictObjNext_TCL_DECLARED
+#define Tcl_DictObjNext_TCL_DECLARED
+/* 499 */
+EXTERN void Tcl_DictObjNext(Tcl_DictSearch *searchPtr,
+ Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr,
+ int *donePtr);
+#endif
+#ifndef Tcl_DictObjDone_TCL_DECLARED
+#define Tcl_DictObjDone_TCL_DECLARED
+/* 500 */
+EXTERN void Tcl_DictObjDone(Tcl_DictSearch *searchPtr);
+#endif
+#ifndef Tcl_DictObjPutKeyList_TCL_DECLARED
+#define Tcl_DictObjPutKeyList_TCL_DECLARED
+/* 501 */
+EXTERN int Tcl_DictObjPutKeyList(Tcl_Interp *interp,
+ Tcl_Obj *dictPtr, int keyc,
+ Tcl_Obj *CONST *keyv, Tcl_Obj *valuePtr);
+#endif
+#ifndef Tcl_DictObjRemoveKeyList_TCL_DECLARED
+#define Tcl_DictObjRemoveKeyList_TCL_DECLARED
+/* 502 */
+EXTERN int Tcl_DictObjRemoveKeyList(Tcl_Interp *interp,
+ Tcl_Obj *dictPtr, int keyc,
+ Tcl_Obj *CONST *keyv);
+#endif
+#ifndef Tcl_NewDictObj_TCL_DECLARED
+#define Tcl_NewDictObj_TCL_DECLARED
+/* 503 */
+EXTERN Tcl_Obj * Tcl_NewDictObj(void);
+#endif
+#ifndef Tcl_DbNewDictObj_TCL_DECLARED
+#define Tcl_DbNewDictObj_TCL_DECLARED
+/* 504 */
+EXTERN Tcl_Obj * Tcl_DbNewDictObj(CONST char *file, int line);
+#endif
+#ifndef Tcl_RegisterConfig_TCL_DECLARED
+#define Tcl_RegisterConfig_TCL_DECLARED
+/* 505 */
+EXTERN void Tcl_RegisterConfig(Tcl_Interp *interp,
+ CONST char *pkgName,
+ Tcl_Config *configuration,
+ CONST char *valEncoding);
+#endif
+#ifndef Tcl_CreateNamespace_TCL_DECLARED
+#define Tcl_CreateNamespace_TCL_DECLARED
+/* 506 */
+EXTERN Tcl_Namespace * Tcl_CreateNamespace(Tcl_Interp *interp,
+ CONST char *name, ClientData clientData,
+ Tcl_NamespaceDeleteProc *deleteProc);
+#endif
+#ifndef Tcl_DeleteNamespace_TCL_DECLARED
+#define Tcl_DeleteNamespace_TCL_DECLARED
+/* 507 */
+EXTERN void Tcl_DeleteNamespace(Tcl_Namespace *nsPtr);
+#endif
+#ifndef Tcl_AppendExportList_TCL_DECLARED
+#define Tcl_AppendExportList_TCL_DECLARED
+/* 508 */
+EXTERN int Tcl_AppendExportList(Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr, Tcl_Obj *objPtr);
+#endif
+#ifndef Tcl_Export_TCL_DECLARED
+#define Tcl_Export_TCL_DECLARED
+/* 509 */
+EXTERN int Tcl_Export(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
+ CONST char *pattern, int resetListFirst);
+#endif
+#ifndef Tcl_Import_TCL_DECLARED
+#define Tcl_Import_TCL_DECLARED
+/* 510 */
+EXTERN int Tcl_Import(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
+ CONST char *pattern, int allowOverwrite);
+#endif
+#ifndef Tcl_ForgetImport_TCL_DECLARED
+#define Tcl_ForgetImport_TCL_DECLARED
+/* 511 */
+EXTERN int Tcl_ForgetImport(Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr, CONST char *pattern);
+#endif
+#ifndef Tcl_GetCurrentNamespace_TCL_DECLARED
+#define Tcl_GetCurrentNamespace_TCL_DECLARED
+/* 512 */
+EXTERN Tcl_Namespace * Tcl_GetCurrentNamespace(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_GetGlobalNamespace_TCL_DECLARED
+#define Tcl_GetGlobalNamespace_TCL_DECLARED
+/* 513 */
+EXTERN Tcl_Namespace * Tcl_GetGlobalNamespace(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_FindNamespace_TCL_DECLARED
+#define Tcl_FindNamespace_TCL_DECLARED
+/* 514 */
+EXTERN Tcl_Namespace * Tcl_FindNamespace(Tcl_Interp *interp,
+ CONST char *name,
+ Tcl_Namespace *contextNsPtr, int flags);
+#endif
+#ifndef Tcl_FindCommand_TCL_DECLARED
+#define Tcl_FindCommand_TCL_DECLARED
+/* 515 */
+EXTERN Tcl_Command Tcl_FindCommand(Tcl_Interp *interp, CONST char *name,
+ Tcl_Namespace *contextNsPtr, int flags);
+#endif
+#ifndef Tcl_GetCommandFromObj_TCL_DECLARED
+#define Tcl_GetCommandFromObj_TCL_DECLARED
+/* 516 */
+EXTERN Tcl_Command Tcl_GetCommandFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr);
+#endif
+#ifndef Tcl_GetCommandFullName_TCL_DECLARED
+#define Tcl_GetCommandFullName_TCL_DECLARED
+/* 517 */
+EXTERN void Tcl_GetCommandFullName(Tcl_Interp *interp,
+ Tcl_Command command, Tcl_Obj *objPtr);
+#endif
+#ifndef Tcl_FSEvalFileEx_TCL_DECLARED
+#define Tcl_FSEvalFileEx_TCL_DECLARED
+/* 518 */
+EXTERN int Tcl_FSEvalFileEx(Tcl_Interp *interp,
+ Tcl_Obj *fileName, CONST char *encodingName);
+#endif
+#ifndef Tcl_SetExitProc_TCL_DECLARED
+#define Tcl_SetExitProc_TCL_DECLARED
+/* 519 */
+EXTERN Tcl_ExitProc * Tcl_SetExitProc(Tcl_ExitProc *proc);
+#endif
+#ifndef Tcl_LimitAddHandler_TCL_DECLARED
+#define Tcl_LimitAddHandler_TCL_DECLARED
+/* 520 */
+EXTERN void Tcl_LimitAddHandler(Tcl_Interp *interp, int type,
+ Tcl_LimitHandlerProc *handlerProc,
+ ClientData clientData,
+ Tcl_LimitHandlerDeleteProc *deleteProc);
+#endif
+#ifndef Tcl_LimitRemoveHandler_TCL_DECLARED
+#define Tcl_LimitRemoveHandler_TCL_DECLARED
+/* 521 */
+EXTERN void Tcl_LimitRemoveHandler(Tcl_Interp *interp, int type,
+ Tcl_LimitHandlerProc *handlerProc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_LimitReady_TCL_DECLARED
+#define Tcl_LimitReady_TCL_DECLARED
+/* 522 */
+EXTERN int Tcl_LimitReady(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_LimitCheck_TCL_DECLARED
+#define Tcl_LimitCheck_TCL_DECLARED
+/* 523 */
+EXTERN int Tcl_LimitCheck(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_LimitExceeded_TCL_DECLARED
+#define Tcl_LimitExceeded_TCL_DECLARED
+/* 524 */
+EXTERN int Tcl_LimitExceeded(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_LimitSetCommands_TCL_DECLARED
+#define Tcl_LimitSetCommands_TCL_DECLARED
+/* 525 */
+EXTERN void Tcl_LimitSetCommands(Tcl_Interp *interp,
+ int commandLimit);
+#endif
+#ifndef Tcl_LimitSetTime_TCL_DECLARED
+#define Tcl_LimitSetTime_TCL_DECLARED
+/* 526 */
+EXTERN void Tcl_LimitSetTime(Tcl_Interp *interp,
+ Tcl_Time *timeLimitPtr);
+#endif
+#ifndef Tcl_LimitSetGranularity_TCL_DECLARED
+#define Tcl_LimitSetGranularity_TCL_DECLARED
+/* 527 */
+EXTERN void Tcl_LimitSetGranularity(Tcl_Interp *interp, int type,
+ int granularity);
+#endif
+#ifndef Tcl_LimitTypeEnabled_TCL_DECLARED
+#define Tcl_LimitTypeEnabled_TCL_DECLARED
+/* 528 */
+EXTERN int Tcl_LimitTypeEnabled(Tcl_Interp *interp, int type);
+#endif
+#ifndef Tcl_LimitTypeExceeded_TCL_DECLARED
+#define Tcl_LimitTypeExceeded_TCL_DECLARED
+/* 529 */
+EXTERN int Tcl_LimitTypeExceeded(Tcl_Interp *interp, int type);
+#endif
+#ifndef Tcl_LimitTypeSet_TCL_DECLARED
+#define Tcl_LimitTypeSet_TCL_DECLARED
+/* 530 */
+EXTERN void Tcl_LimitTypeSet(Tcl_Interp *interp, int type);
+#endif
+#ifndef Tcl_LimitTypeReset_TCL_DECLARED
+#define Tcl_LimitTypeReset_TCL_DECLARED
+/* 531 */
+EXTERN void Tcl_LimitTypeReset(Tcl_Interp *interp, int type);
+#endif
+#ifndef Tcl_LimitGetCommands_TCL_DECLARED
+#define Tcl_LimitGetCommands_TCL_DECLARED
+/* 532 */
+EXTERN int Tcl_LimitGetCommands(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_LimitGetTime_TCL_DECLARED
+#define Tcl_LimitGetTime_TCL_DECLARED
+/* 533 */
+EXTERN void Tcl_LimitGetTime(Tcl_Interp *interp,
+ Tcl_Time *timeLimitPtr);
+#endif
+#ifndef Tcl_LimitGetGranularity_TCL_DECLARED
+#define Tcl_LimitGetGranularity_TCL_DECLARED
+/* 534 */
+EXTERN int Tcl_LimitGetGranularity(Tcl_Interp *interp, int type);
+#endif
+#ifndef Tcl_SaveInterpState_TCL_DECLARED
+#define Tcl_SaveInterpState_TCL_DECLARED
+/* 535 */
+EXTERN Tcl_InterpState Tcl_SaveInterpState(Tcl_Interp *interp, int status);
+#endif
+#ifndef Tcl_RestoreInterpState_TCL_DECLARED
+#define Tcl_RestoreInterpState_TCL_DECLARED
+/* 536 */
+EXTERN int Tcl_RestoreInterpState(Tcl_Interp *interp,
+ Tcl_InterpState state);
+#endif
+#ifndef Tcl_DiscardInterpState_TCL_DECLARED
+#define Tcl_DiscardInterpState_TCL_DECLARED
+/* 537 */
+EXTERN void Tcl_DiscardInterpState(Tcl_InterpState state);
+#endif
+#ifndef Tcl_SetReturnOptions_TCL_DECLARED
+#define Tcl_SetReturnOptions_TCL_DECLARED
+/* 538 */
+EXTERN int Tcl_SetReturnOptions(Tcl_Interp *interp,
+ Tcl_Obj *options);
+#endif
+#ifndef Tcl_GetReturnOptions_TCL_DECLARED
+#define Tcl_GetReturnOptions_TCL_DECLARED
+/* 539 */
+EXTERN Tcl_Obj * Tcl_GetReturnOptions(Tcl_Interp *interp, int result);
+#endif
+#ifndef Tcl_IsEnsemble_TCL_DECLARED
+#define Tcl_IsEnsemble_TCL_DECLARED
+/* 540 */
+EXTERN int Tcl_IsEnsemble(Tcl_Command token);
+#endif
+#ifndef Tcl_CreateEnsemble_TCL_DECLARED
+#define Tcl_CreateEnsemble_TCL_DECLARED
+/* 541 */
+EXTERN Tcl_Command Tcl_CreateEnsemble(Tcl_Interp *interp,
+ CONST char *name,
+ Tcl_Namespace *namespacePtr, int flags);
+#endif
+#ifndef Tcl_FindEnsemble_TCL_DECLARED
+#define Tcl_FindEnsemble_TCL_DECLARED
+/* 542 */
+EXTERN Tcl_Command Tcl_FindEnsemble(Tcl_Interp *interp,
+ Tcl_Obj *cmdNameObj, int flags);
+#endif
+#ifndef Tcl_SetEnsembleSubcommandList_TCL_DECLARED
+#define Tcl_SetEnsembleSubcommandList_TCL_DECLARED
+/* 543 */
+EXTERN int Tcl_SetEnsembleSubcommandList(Tcl_Interp *interp,
+ Tcl_Command token, Tcl_Obj *subcmdList);
+#endif
+#ifndef Tcl_SetEnsembleMappingDict_TCL_DECLARED
+#define Tcl_SetEnsembleMappingDict_TCL_DECLARED
+/* 544 */
+EXTERN int Tcl_SetEnsembleMappingDict(Tcl_Interp *interp,
+ Tcl_Command token, Tcl_Obj *mapDict);
+#endif
+#ifndef Tcl_SetEnsembleUnknownHandler_TCL_DECLARED
+#define Tcl_SetEnsembleUnknownHandler_TCL_DECLARED
+/* 545 */
+EXTERN int Tcl_SetEnsembleUnknownHandler(Tcl_Interp *interp,
+ Tcl_Command token, Tcl_Obj *unknownList);
+#endif
+#ifndef Tcl_SetEnsembleFlags_TCL_DECLARED
+#define Tcl_SetEnsembleFlags_TCL_DECLARED
+/* 546 */
+EXTERN int Tcl_SetEnsembleFlags(Tcl_Interp *interp,
+ Tcl_Command token, int flags);
+#endif
+#ifndef Tcl_GetEnsembleSubcommandList_TCL_DECLARED
+#define Tcl_GetEnsembleSubcommandList_TCL_DECLARED
+/* 547 */
+EXTERN int Tcl_GetEnsembleSubcommandList(Tcl_Interp *interp,
+ Tcl_Command token, Tcl_Obj **subcmdListPtr);
+#endif
+#ifndef Tcl_GetEnsembleMappingDict_TCL_DECLARED
+#define Tcl_GetEnsembleMappingDict_TCL_DECLARED
+/* 548 */
+EXTERN int Tcl_GetEnsembleMappingDict(Tcl_Interp *interp,
+ Tcl_Command token, Tcl_Obj **mapDictPtr);
+#endif
+#ifndef Tcl_GetEnsembleUnknownHandler_TCL_DECLARED
+#define Tcl_GetEnsembleUnknownHandler_TCL_DECLARED
+/* 549 */
+EXTERN int Tcl_GetEnsembleUnknownHandler(Tcl_Interp *interp,
+ Tcl_Command token, Tcl_Obj **unknownListPtr);
+#endif
+#ifndef Tcl_GetEnsembleFlags_TCL_DECLARED
+#define Tcl_GetEnsembleFlags_TCL_DECLARED
+/* 550 */
+EXTERN int Tcl_GetEnsembleFlags(Tcl_Interp *interp,
+ Tcl_Command token, int *flagsPtr);
+#endif
+#ifndef Tcl_GetEnsembleNamespace_TCL_DECLARED
+#define Tcl_GetEnsembleNamespace_TCL_DECLARED
+/* 551 */
+EXTERN int Tcl_GetEnsembleNamespace(Tcl_Interp *interp,
+ Tcl_Command token,
+ Tcl_Namespace **namespacePtrPtr);
+#endif
+#ifndef Tcl_SetTimeProc_TCL_DECLARED
+#define Tcl_SetTimeProc_TCL_DECLARED
+/* 552 */
+EXTERN void Tcl_SetTimeProc(Tcl_GetTimeProc *getProc,
+ Tcl_ScaleTimeProc *scaleProc,
+ ClientData clientData);
+#endif
+#ifndef Tcl_QueryTimeProc_TCL_DECLARED
+#define Tcl_QueryTimeProc_TCL_DECLARED
+/* 553 */
+EXTERN void Tcl_QueryTimeProc(Tcl_GetTimeProc **getProc,
+ Tcl_ScaleTimeProc **scaleProc,
+ ClientData *clientData);
+#endif
+#ifndef Tcl_ChannelThreadActionProc_TCL_DECLARED
+#define Tcl_ChannelThreadActionProc_TCL_DECLARED
/* 554 */
-EXTERN Tcl_DriverThreadActionProc * Tcl_ChannelThreadActionProc _ANSI_ARGS_((
- Tcl_ChannelType * chanTypePtr));
-/* Slot 555 is reserved */
-/* Slot 556 is reserved */
-/* Slot 557 is reserved */
-/* Slot 558 is reserved */
-/* Slot 559 is reserved */
-/* Slot 560 is reserved */
-/* Slot 561 is reserved */
-/* Slot 562 is reserved */
-/* Slot 563 is reserved */
-/* Slot 564 is reserved */
-/* Slot 565 is reserved */
-/* Slot 566 is reserved */
-/* Slot 567 is reserved */
-/* Slot 568 is reserved */
-/* Slot 569 is reserved */
-/* Slot 570 is reserved */
-/* Slot 571 is reserved */
-/* Slot 572 is reserved */
+EXTERN Tcl_DriverThreadActionProc * Tcl_ChannelThreadActionProc(
+ CONST Tcl_ChannelType *chanTypePtr);
+#endif
+#ifndef Tcl_NewBignumObj_TCL_DECLARED
+#define Tcl_NewBignumObj_TCL_DECLARED
+/* 555 */
+EXTERN Tcl_Obj * Tcl_NewBignumObj(mp_int *value);
+#endif
+#ifndef Tcl_DbNewBignumObj_TCL_DECLARED
+#define Tcl_DbNewBignumObj_TCL_DECLARED
+/* 556 */
+EXTERN Tcl_Obj * Tcl_DbNewBignumObj(mp_int *value, CONST char *file,
+ int line);
+#endif
+#ifndef Tcl_SetBignumObj_TCL_DECLARED
+#define Tcl_SetBignumObj_TCL_DECLARED
+/* 557 */
+EXTERN void Tcl_SetBignumObj(Tcl_Obj *obj, mp_int *value);
+#endif
+#ifndef Tcl_GetBignumFromObj_TCL_DECLARED
+#define Tcl_GetBignumFromObj_TCL_DECLARED
+/* 558 */
+EXTERN int Tcl_GetBignumFromObj(Tcl_Interp *interp,
+ Tcl_Obj *obj, mp_int *value);
+#endif
+#ifndef Tcl_TakeBignumFromObj_TCL_DECLARED
+#define Tcl_TakeBignumFromObj_TCL_DECLARED
+/* 559 */
+EXTERN int Tcl_TakeBignumFromObj(Tcl_Interp *interp,
+ Tcl_Obj *obj, mp_int *value);
+#endif
+#ifndef Tcl_TruncateChannel_TCL_DECLARED
+#define Tcl_TruncateChannel_TCL_DECLARED
+/* 560 */
+EXTERN int Tcl_TruncateChannel(Tcl_Channel chan,
+ Tcl_WideInt length);
+#endif
+#ifndef Tcl_ChannelTruncateProc_TCL_DECLARED
+#define Tcl_ChannelTruncateProc_TCL_DECLARED
+/* 561 */
+EXTERN Tcl_DriverTruncateProc * Tcl_ChannelTruncateProc(
+ CONST Tcl_ChannelType *chanTypePtr);
+#endif
+#ifndef Tcl_SetChannelErrorInterp_TCL_DECLARED
+#define Tcl_SetChannelErrorInterp_TCL_DECLARED
+/* 562 */
+EXTERN void Tcl_SetChannelErrorInterp(Tcl_Interp *interp,
+ Tcl_Obj *msg);
+#endif
+#ifndef Tcl_GetChannelErrorInterp_TCL_DECLARED
+#define Tcl_GetChannelErrorInterp_TCL_DECLARED
+/* 563 */
+EXTERN void Tcl_GetChannelErrorInterp(Tcl_Interp *interp,
+ Tcl_Obj **msg);
+#endif
+#ifndef Tcl_SetChannelError_TCL_DECLARED
+#define Tcl_SetChannelError_TCL_DECLARED
+/* 564 */
+EXTERN void Tcl_SetChannelError(Tcl_Channel chan, Tcl_Obj *msg);
+#endif
+#ifndef Tcl_GetChannelError_TCL_DECLARED
+#define Tcl_GetChannelError_TCL_DECLARED
+/* 565 */
+EXTERN void Tcl_GetChannelError(Tcl_Channel chan, Tcl_Obj **msg);
+#endif
+#ifndef Tcl_InitBignumFromDouble_TCL_DECLARED
+#define Tcl_InitBignumFromDouble_TCL_DECLARED
+/* 566 */
+EXTERN int Tcl_InitBignumFromDouble(Tcl_Interp *interp,
+ double initval, mp_int *toInit);
+#endif
+#ifndef Tcl_GetNamespaceUnknownHandler_TCL_DECLARED
+#define Tcl_GetNamespaceUnknownHandler_TCL_DECLARED
+/* 567 */
+EXTERN Tcl_Obj * Tcl_GetNamespaceUnknownHandler(Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr);
+#endif
+#ifndef Tcl_SetNamespaceUnknownHandler_TCL_DECLARED
+#define Tcl_SetNamespaceUnknownHandler_TCL_DECLARED
+/* 568 */
+EXTERN int Tcl_SetNamespaceUnknownHandler(Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr, Tcl_Obj *handlerPtr);
+#endif
+#ifndef Tcl_GetEncodingFromObj_TCL_DECLARED
+#define Tcl_GetEncodingFromObj_TCL_DECLARED
+/* 569 */
+EXTERN int Tcl_GetEncodingFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, Tcl_Encoding *encodingPtr);
+#endif
+#ifndef Tcl_GetEncodingSearchPath_TCL_DECLARED
+#define Tcl_GetEncodingSearchPath_TCL_DECLARED
+/* 570 */
+EXTERN Tcl_Obj * Tcl_GetEncodingSearchPath(void);
+#endif
+#ifndef Tcl_SetEncodingSearchPath_TCL_DECLARED
+#define Tcl_SetEncodingSearchPath_TCL_DECLARED
+/* 571 */
+EXTERN int Tcl_SetEncodingSearchPath(Tcl_Obj *searchPath);
+#endif
+#ifndef Tcl_GetEncodingNameFromEnvironment_TCL_DECLARED
+#define Tcl_GetEncodingNameFromEnvironment_TCL_DECLARED
+/* 572 */
+EXTERN CONST char * Tcl_GetEncodingNameFromEnvironment(
+ Tcl_DString *bufPtr);
+#endif
+#ifndef Tcl_PkgRequireProc_TCL_DECLARED
+#define Tcl_PkgRequireProc_TCL_DECLARED
/* 573 */
-EXTERN int Tcl_PkgRequireProc _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * name, int objc,
- Tcl_Obj *CONST objv[],
- ClientData * clientDataPtr));
+EXTERN int Tcl_PkgRequireProc(Tcl_Interp *interp,
+ CONST char *name, int objc,
+ Tcl_Obj *CONST objv[],
+ ClientData *clientDataPtr);
+#endif
+#ifndef Tcl_AppendObjToErrorInfo_TCL_DECLARED
+#define Tcl_AppendObjToErrorInfo_TCL_DECLARED
+/* 574 */
+EXTERN void Tcl_AppendObjToErrorInfo(Tcl_Interp *interp,
+ Tcl_Obj *objPtr);
+#endif
+#ifndef Tcl_AppendLimitedToObj_TCL_DECLARED
+#define Tcl_AppendLimitedToObj_TCL_DECLARED
+/* 575 */
+EXTERN void Tcl_AppendLimitedToObj(Tcl_Obj *objPtr,
+ CONST char *bytes, int length, int limit,
+ CONST char *ellipsis);
+#endif
+#ifndef Tcl_Format_TCL_DECLARED
+#define Tcl_Format_TCL_DECLARED
+/* 576 */
+EXTERN Tcl_Obj * Tcl_Format(Tcl_Interp *interp, CONST char *format,
+ int objc, Tcl_Obj *CONST objv[]);
+#endif
+#ifndef Tcl_AppendFormatToObj_TCL_DECLARED
+#define Tcl_AppendFormatToObj_TCL_DECLARED
+/* 577 */
+EXTERN int Tcl_AppendFormatToObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, CONST char *format,
+ int objc, Tcl_Obj *CONST objv[]);
+#endif
+#ifndef Tcl_ObjPrintf_TCL_DECLARED
+#define Tcl_ObjPrintf_TCL_DECLARED
+/* 578 */
+EXTERN Tcl_Obj * Tcl_ObjPrintf(CONST char *format, ...);
+#endif
+#ifndef Tcl_AppendPrintfToObj_TCL_DECLARED
+#define Tcl_AppendPrintfToObj_TCL_DECLARED
+/* 579 */
+EXTERN void Tcl_AppendPrintfToObj(Tcl_Obj *objPtr,
+ CONST char *format, ...);
+#endif
typedef struct TclStubHooks {
struct TclPlatStubs *tclPlatStubs;
@@ -1659,628 +3419,610 @@ typedef struct TclStubs {
int magic;
struct TclStubHooks *hooks;
- int (*tcl_PkgProvideEx) _ANSI_ARGS_((Tcl_Interp* interp, CONST char* name, CONST char* version, ClientData clientData)); /* 0 */
- CONST84_RETURN char * (*tcl_PkgRequireEx) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, CONST char * version, int exact, ClientData * clientDataPtr)); /* 1 */
- void (*tcl_Panic) _ANSI_ARGS_(TCL_VARARGS(CONST char *,format)); /* 2 */
- char * (*tcl_Alloc) _ANSI_ARGS_((unsigned int size)); /* 3 */
- void (*tcl_Free) _ANSI_ARGS_((char * ptr)); /* 4 */
- char * (*tcl_Realloc) _ANSI_ARGS_((char * ptr, unsigned int size)); /* 5 */
- char * (*tcl_DbCkalloc) _ANSI_ARGS_((unsigned int size, CONST char * file, int line)); /* 6 */
- int (*tcl_DbCkfree) _ANSI_ARGS_((char * ptr, CONST char * file, int line)); /* 7 */
- char * (*tcl_DbCkrealloc) _ANSI_ARGS_((char * ptr, unsigned int size, CONST char * file, int line)); /* 8 */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
- void (*tcl_CreateFileHandler) _ANSI_ARGS_((int fd, int mask, Tcl_FileProc * proc, ClientData clientData)); /* 9 */
-#endif /* UNIX */
-#ifdef __WIN32__
- void *reserved9;
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
- void *reserved9;
-#endif /* MAC_TCL */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
- void (*tcl_DeleteFileHandler) _ANSI_ARGS_((int fd)); /* 10 */
+ int (*tcl_PkgProvideEx) (Tcl_Interp *interp, CONST char *name, CONST char *version, ClientData clientData); /* 0 */
+ CONST84_RETURN char * (*tcl_PkgRequireEx) (Tcl_Interp *interp, CONST char *name, CONST char *version, int exact, ClientData *clientDataPtr); /* 1 */
+ void (*tcl_Panic) (CONST char *format, ...); /* 2 */
+ char * (*tcl_Alloc) (unsigned int size); /* 3 */
+ void (*tcl_Free) (char *ptr); /* 4 */
+ char * (*tcl_Realloc) (char *ptr, unsigned int size); /* 5 */
+ char * (*tcl_DbCkalloc) (unsigned int size, CONST char *file, int line); /* 6 */
+ int (*tcl_DbCkfree) (char *ptr, CONST char *file, int line); /* 7 */
+ char * (*tcl_DbCkrealloc) (char *ptr, unsigned int size, CONST char *file, int line); /* 8 */
+#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
+ void (*tcl_CreateFileHandler) (int fd, int mask, Tcl_FileProc *proc, ClientData clientData); /* 9 */
#endif /* UNIX */
-#ifdef __WIN32__
- void *reserved10;
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
- void *reserved10;
-#endif /* MAC_TCL */
- void (*tcl_SetTimer) _ANSI_ARGS_((Tcl_Time * timePtr)); /* 11 */
- void (*tcl_Sleep) _ANSI_ARGS_((int ms)); /* 12 */
- int (*tcl_WaitForEvent) _ANSI_ARGS_((Tcl_Time * timePtr)); /* 13 */
- int (*tcl_AppendAllObjTypes) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr)); /* 14 */
- void (*tcl_AppendStringsToObj) _ANSI_ARGS_(TCL_VARARGS(Tcl_Obj *,objPtr)); /* 15 */
- void (*tcl_AppendToObj) _ANSI_ARGS_((Tcl_Obj* objPtr, CONST char* bytes, int length)); /* 16 */
- Tcl_Obj * (*tcl_ConcatObj) _ANSI_ARGS_((int objc, Tcl_Obj *CONST objv[])); /* 17 */
- int (*tcl_ConvertToType) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, Tcl_ObjType * typePtr)); /* 18 */
- void (*tcl_DbDecrRefCount) _ANSI_ARGS_((Tcl_Obj * objPtr, CONST char * file, int line)); /* 19 */
- void (*tcl_DbIncrRefCount) _ANSI_ARGS_((Tcl_Obj * objPtr, CONST char * file, int line)); /* 20 */
- int (*tcl_DbIsShared) _ANSI_ARGS_((Tcl_Obj * objPtr, CONST char * file, int line)); /* 21 */
- Tcl_Obj * (*tcl_DbNewBooleanObj) _ANSI_ARGS_((int boolValue, CONST char * file, int line)); /* 22 */
- Tcl_Obj * (*tcl_DbNewByteArrayObj) _ANSI_ARGS_((CONST unsigned char * bytes, int length, CONST char * file, int line)); /* 23 */
- Tcl_Obj * (*tcl_DbNewDoubleObj) _ANSI_ARGS_((double doubleValue, CONST char * file, int line)); /* 24 */
- Tcl_Obj * (*tcl_DbNewListObj) _ANSI_ARGS_((int objc, Tcl_Obj *CONST * objv, CONST char * file, int line)); /* 25 */
- Tcl_Obj * (*tcl_DbNewLongObj) _ANSI_ARGS_((long longValue, CONST char * file, int line)); /* 26 */
- Tcl_Obj * (*tcl_DbNewObj) _ANSI_ARGS_((CONST char * file, int line)); /* 27 */
- Tcl_Obj * (*tcl_DbNewStringObj) _ANSI_ARGS_((CONST char * bytes, int length, CONST char * file, int line)); /* 28 */
- Tcl_Obj * (*tcl_DuplicateObj) _ANSI_ARGS_((Tcl_Obj * objPtr)); /* 29 */
- void (*tclFreeObj) _ANSI_ARGS_((Tcl_Obj * objPtr)); /* 30 */
- int (*tcl_GetBoolean) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, int * boolPtr)); /* 31 */
- int (*tcl_GetBooleanFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, int * boolPtr)); /* 32 */
- unsigned char * (*tcl_GetByteArrayFromObj) _ANSI_ARGS_((Tcl_Obj * objPtr, int * lengthPtr)); /* 33 */
- int (*tcl_GetDouble) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, double * doublePtr)); /* 34 */
- int (*tcl_GetDoubleFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, double * doublePtr)); /* 35 */
- int (*tcl_GetIndexFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, CONST84 char ** tablePtr, CONST char * msg, int flags, int * indexPtr)); /* 36 */
- int (*tcl_GetInt) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, int * intPtr)); /* 37 */
- int (*tcl_GetIntFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, int * intPtr)); /* 38 */
- int (*tcl_GetLongFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, long * longPtr)); /* 39 */
- Tcl_ObjType * (*tcl_GetObjType) _ANSI_ARGS_((CONST char * typeName)); /* 40 */
- char * (*tcl_GetStringFromObj) _ANSI_ARGS_((Tcl_Obj * objPtr, int * lengthPtr)); /* 41 */
- void (*tcl_InvalidateStringRep) _ANSI_ARGS_((Tcl_Obj * objPtr)); /* 42 */
- int (*tcl_ListObjAppendList) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * listPtr, Tcl_Obj * elemListPtr)); /* 43 */
- int (*tcl_ListObjAppendElement) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * listPtr, Tcl_Obj * objPtr)); /* 44 */
- int (*tcl_ListObjGetElements) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * listPtr, int * objcPtr, Tcl_Obj *** objvPtr)); /* 45 */
- int (*tcl_ListObjIndex) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * listPtr, int index, Tcl_Obj ** objPtrPtr)); /* 46 */
- int (*tcl_ListObjLength) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * listPtr, int * lengthPtr)); /* 47 */
- int (*tcl_ListObjReplace) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * listPtr, int first, int count, int objc, Tcl_Obj *CONST objv[])); /* 48 */
- Tcl_Obj * (*tcl_NewBooleanObj) _ANSI_ARGS_((int boolValue)); /* 49 */
- Tcl_Obj * (*tcl_NewByteArrayObj) _ANSI_ARGS_((CONST unsigned char* bytes, int length)); /* 50 */
- Tcl_Obj * (*tcl_NewDoubleObj) _ANSI_ARGS_((double doubleValue)); /* 51 */
- Tcl_Obj * (*tcl_NewIntObj) _ANSI_ARGS_((int intValue)); /* 52 */
- Tcl_Obj * (*tcl_NewListObj) _ANSI_ARGS_((int objc, Tcl_Obj *CONST objv[])); /* 53 */
- Tcl_Obj * (*tcl_NewLongObj) _ANSI_ARGS_((long longValue)); /* 54 */
- Tcl_Obj * (*tcl_NewObj) _ANSI_ARGS_((void)); /* 55 */
- Tcl_Obj * (*tcl_NewStringObj) _ANSI_ARGS_((CONST char * bytes, int length)); /* 56 */
- void (*tcl_SetBooleanObj) _ANSI_ARGS_((Tcl_Obj * objPtr, int boolValue)); /* 57 */
- unsigned char * (*tcl_SetByteArrayLength) _ANSI_ARGS_((Tcl_Obj * objPtr, int length)); /* 58 */
- void (*tcl_SetByteArrayObj) _ANSI_ARGS_((Tcl_Obj * objPtr, CONST unsigned char * bytes, int length)); /* 59 */
- void (*tcl_SetDoubleObj) _ANSI_ARGS_((Tcl_Obj * objPtr, double doubleValue)); /* 60 */
- void (*tcl_SetIntObj) _ANSI_ARGS_((Tcl_Obj * objPtr, int intValue)); /* 61 */
- void (*tcl_SetListObj) _ANSI_ARGS_((Tcl_Obj * objPtr, int objc, Tcl_Obj *CONST objv[])); /* 62 */
- void (*tcl_SetLongObj) _ANSI_ARGS_((Tcl_Obj * objPtr, long longValue)); /* 63 */
- void (*tcl_SetObjLength) _ANSI_ARGS_((Tcl_Obj * objPtr, int length)); /* 64 */
- void (*tcl_SetStringObj) _ANSI_ARGS_((Tcl_Obj* objPtr, CONST char* bytes, int length)); /* 65 */
- void (*tcl_AddErrorInfo) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * message)); /* 66 */
- void (*tcl_AddObjErrorInfo) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * message, int length)); /* 67 */
- void (*tcl_AllowExceptions) _ANSI_ARGS_((Tcl_Interp * interp)); /* 68 */
- void (*tcl_AppendElement) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string)); /* 69 */
- void (*tcl_AppendResult) _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp)); /* 70 */
- Tcl_AsyncHandler (*tcl_AsyncCreate) _ANSI_ARGS_((Tcl_AsyncProc * proc, ClientData clientData)); /* 71 */
- void (*tcl_AsyncDelete) _ANSI_ARGS_((Tcl_AsyncHandler async)); /* 72 */
- int (*tcl_AsyncInvoke) _ANSI_ARGS_((Tcl_Interp * interp, int code)); /* 73 */
- void (*tcl_AsyncMark) _ANSI_ARGS_((Tcl_AsyncHandler async)); /* 74 */
- int (*tcl_AsyncReady) _ANSI_ARGS_((void)); /* 75 */
- void (*tcl_BackgroundError) _ANSI_ARGS_((Tcl_Interp * interp)); /* 76 */
- char (*tcl_Backslash) _ANSI_ARGS_((CONST char * src, int * readPtr)); /* 77 */
- int (*tcl_BadChannelOption) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * optionName, CONST char * optionList)); /* 78 */
- void (*tcl_CallWhenDeleted) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_InterpDeleteProc * proc, ClientData clientData)); /* 79 */
- void (*tcl_CancelIdleCall) _ANSI_ARGS_((Tcl_IdleProc * idleProc, ClientData clientData)); /* 80 */
- int (*tcl_Close) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan)); /* 81 */
- int (*tcl_CommandComplete) _ANSI_ARGS_((CONST char * cmd)); /* 82 */
- char * (*tcl_Concat) _ANSI_ARGS_((int argc, CONST84 char * CONST * argv)); /* 83 */
- int (*tcl_ConvertElement) _ANSI_ARGS_((CONST char * src, char * dst, int flags)); /* 84 */
- int (*tcl_ConvertCountedElement) _ANSI_ARGS_((CONST char * src, int length, char * dst, int flags)); /* 85 */
- int (*tcl_CreateAlias) _ANSI_ARGS_((Tcl_Interp * slave, CONST char * slaveCmd, Tcl_Interp * target, CONST char * targetCmd, int argc, CONST84 char * CONST * argv)); /* 86 */
- int (*tcl_CreateAliasObj) _ANSI_ARGS_((Tcl_Interp * slave, CONST char * slaveCmd, Tcl_Interp * target, CONST char * targetCmd, int objc, Tcl_Obj *CONST objv[])); /* 87 */
- Tcl_Channel (*tcl_CreateChannel) _ANSI_ARGS_((Tcl_ChannelType * typePtr, CONST char * chanName, ClientData instanceData, int mask)); /* 88 */
- void (*tcl_CreateChannelHandler) _ANSI_ARGS_((Tcl_Channel chan, int mask, Tcl_ChannelProc * proc, ClientData clientData)); /* 89 */
- void (*tcl_CreateCloseHandler) _ANSI_ARGS_((Tcl_Channel chan, Tcl_CloseProc * proc, ClientData clientData)); /* 90 */
- Tcl_Command (*tcl_CreateCommand) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * cmdName, Tcl_CmdProc * proc, ClientData clientData, Tcl_CmdDeleteProc * deleteProc)); /* 91 */
- void (*tcl_CreateEventSource) _ANSI_ARGS_((Tcl_EventSetupProc * setupProc, Tcl_EventCheckProc * checkProc, ClientData clientData)); /* 92 */
- void (*tcl_CreateExitHandler) _ANSI_ARGS_((Tcl_ExitProc * proc, ClientData clientData)); /* 93 */
- Tcl_Interp * (*tcl_CreateInterp) _ANSI_ARGS_((void)); /* 94 */
- void (*tcl_CreateMathFunc) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, int numArgs, Tcl_ValueType * argTypes, Tcl_MathProc * proc, ClientData clientData)); /* 95 */
- Tcl_Command (*tcl_CreateObjCommand) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * cmdName, Tcl_ObjCmdProc * proc, ClientData clientData, Tcl_CmdDeleteProc * deleteProc)); /* 96 */
- Tcl_Interp * (*tcl_CreateSlave) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * slaveName, int isSafe)); /* 97 */
- Tcl_TimerToken (*tcl_CreateTimerHandler) _ANSI_ARGS_((int milliseconds, Tcl_TimerProc * proc, ClientData clientData)); /* 98 */
- Tcl_Trace (*tcl_CreateTrace) _ANSI_ARGS_((Tcl_Interp * interp, int level, Tcl_CmdTraceProc * proc, ClientData clientData)); /* 99 */
- void (*tcl_DeleteAssocData) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name)); /* 100 */
- void (*tcl_DeleteChannelHandler) _ANSI_ARGS_((Tcl_Channel chan, Tcl_ChannelProc * proc, ClientData clientData)); /* 101 */
- void (*tcl_DeleteCloseHandler) _ANSI_ARGS_((Tcl_Channel chan, Tcl_CloseProc * proc, ClientData clientData)); /* 102 */
- int (*tcl_DeleteCommand) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * cmdName)); /* 103 */
- int (*tcl_DeleteCommandFromToken) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Command command)); /* 104 */
- void (*tcl_DeleteEvents) _ANSI_ARGS_((Tcl_EventDeleteProc * proc, ClientData clientData)); /* 105 */
- void (*tcl_DeleteEventSource) _ANSI_ARGS_((Tcl_EventSetupProc * setupProc, Tcl_EventCheckProc * checkProc, ClientData clientData)); /* 106 */
- void (*tcl_DeleteExitHandler) _ANSI_ARGS_((Tcl_ExitProc * proc, ClientData clientData)); /* 107 */
- void (*tcl_DeleteHashEntry) _ANSI_ARGS_((Tcl_HashEntry * entryPtr)); /* 108 */
- void (*tcl_DeleteHashTable) _ANSI_ARGS_((Tcl_HashTable * tablePtr)); /* 109 */
- void (*tcl_DeleteInterp) _ANSI_ARGS_((Tcl_Interp * interp)); /* 110 */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
- void (*tcl_DetachPids) _ANSI_ARGS_((int numPids, Tcl_Pid * pidPtr)); /* 111 */
+#ifdef __WIN32__ /* WIN */
+ VOID *reserved9;
+#endif /* WIN */
+#ifdef MAC_OSX_TCL /* MACOSX */
+ void (*tcl_CreateFileHandler) (int fd, int mask, Tcl_FileProc *proc, ClientData clientData); /* 9 */
+#endif /* MACOSX */
+#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
+ void (*tcl_DeleteFileHandler) (int fd); /* 10 */
#endif /* UNIX */
-#ifdef __WIN32__
- void (*tcl_DetachPids) _ANSI_ARGS_((int numPids, Tcl_Pid * pidPtr)); /* 111 */
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
- void *reserved111;
-#endif /* MAC_TCL */
- void (*tcl_DeleteTimerHandler) _ANSI_ARGS_((Tcl_TimerToken token)); /* 112 */
- void (*tcl_DeleteTrace) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Trace trace)); /* 113 */
- void (*tcl_DontCallWhenDeleted) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_InterpDeleteProc * proc, ClientData clientData)); /* 114 */
- int (*tcl_DoOneEvent) _ANSI_ARGS_((int flags)); /* 115 */
- void (*tcl_DoWhenIdle) _ANSI_ARGS_((Tcl_IdleProc * proc, ClientData clientData)); /* 116 */
- char * (*tcl_DStringAppend) _ANSI_ARGS_((Tcl_DString * dsPtr, CONST char * str, int length)); /* 117 */
- char * (*tcl_DStringAppendElement) _ANSI_ARGS_((Tcl_DString * dsPtr, CONST char * string)); /* 118 */
- void (*tcl_DStringEndSublist) _ANSI_ARGS_((Tcl_DString * dsPtr)); /* 119 */
- void (*tcl_DStringFree) _ANSI_ARGS_((Tcl_DString * dsPtr)); /* 120 */
- void (*tcl_DStringGetResult) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_DString * dsPtr)); /* 121 */
- void (*tcl_DStringInit) _ANSI_ARGS_((Tcl_DString * dsPtr)); /* 122 */
- void (*tcl_DStringResult) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_DString * dsPtr)); /* 123 */
- void (*tcl_DStringSetLength) _ANSI_ARGS_((Tcl_DString * dsPtr, int length)); /* 124 */
- void (*tcl_DStringStartSublist) _ANSI_ARGS_((Tcl_DString * dsPtr)); /* 125 */
- int (*tcl_Eof) _ANSI_ARGS_((Tcl_Channel chan)); /* 126 */
- CONST84_RETURN char * (*tcl_ErrnoId) _ANSI_ARGS_((void)); /* 127 */
- CONST84_RETURN char * (*tcl_ErrnoMsg) _ANSI_ARGS_((int err)); /* 128 */
- int (*tcl_Eval) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string)); /* 129 */
- int (*tcl_EvalFile) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * fileName)); /* 130 */
- int (*tcl_EvalObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr)); /* 131 */
- void (*tcl_EventuallyFree) _ANSI_ARGS_((ClientData clientData, Tcl_FreeProc * freeProc)); /* 132 */
- void (*tcl_Exit) _ANSI_ARGS_((int status)); /* 133 */
- int (*tcl_ExposeCommand) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * hiddenCmdToken, CONST char * cmdName)); /* 134 */
- int (*tcl_ExprBoolean) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, int * ptr)); /* 135 */
- int (*tcl_ExprBooleanObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, int * ptr)); /* 136 */
- int (*tcl_ExprDouble) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, double * ptr)); /* 137 */
- int (*tcl_ExprDoubleObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, double * ptr)); /* 138 */
- int (*tcl_ExprLong) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, long * ptr)); /* 139 */
- int (*tcl_ExprLongObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, long * ptr)); /* 140 */
- int (*tcl_ExprObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, Tcl_Obj ** resultPtrPtr)); /* 141 */
- int (*tcl_ExprString) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string)); /* 142 */
- void (*tcl_Finalize) _ANSI_ARGS_((void)); /* 143 */
- void (*tcl_FindExecutable) _ANSI_ARGS_((CONST char * argv0)); /* 144 */
- Tcl_HashEntry * (*tcl_FirstHashEntry) _ANSI_ARGS_((Tcl_HashTable * tablePtr, Tcl_HashSearch * searchPtr)); /* 145 */
- int (*tcl_Flush) _ANSI_ARGS_((Tcl_Channel chan)); /* 146 */
- void (*tcl_FreeResult) _ANSI_ARGS_((Tcl_Interp * interp)); /* 147 */
- int (*tcl_GetAlias) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * slaveCmd, Tcl_Interp ** targetInterpPtr, CONST84 char ** targetCmdPtr, int * argcPtr, CONST84 char *** argvPtr)); /* 148 */
- int (*tcl_GetAliasObj) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * slaveCmd, Tcl_Interp ** targetInterpPtr, CONST84 char ** targetCmdPtr, int * objcPtr, Tcl_Obj *** objv)); /* 149 */
- ClientData (*tcl_GetAssocData) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, Tcl_InterpDeleteProc ** procPtr)); /* 150 */
- Tcl_Channel (*tcl_GetChannel) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * chanName, int * modePtr)); /* 151 */
- int (*tcl_GetChannelBufferSize) _ANSI_ARGS_((Tcl_Channel chan)); /* 152 */
- int (*tcl_GetChannelHandle) _ANSI_ARGS_((Tcl_Channel chan, int direction, ClientData * handlePtr)); /* 153 */
- ClientData (*tcl_GetChannelInstanceData) _ANSI_ARGS_((Tcl_Channel chan)); /* 154 */
- int (*tcl_GetChannelMode) _ANSI_ARGS_((Tcl_Channel chan)); /* 155 */
- CONST84_RETURN char * (*tcl_GetChannelName) _ANSI_ARGS_((Tcl_Channel chan)); /* 156 */
- int (*tcl_GetChannelOption) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan, CONST char * optionName, Tcl_DString * dsPtr)); /* 157 */
- Tcl_ChannelType * (*tcl_GetChannelType) _ANSI_ARGS_((Tcl_Channel chan)); /* 158 */
- int (*tcl_GetCommandInfo) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * cmdName, Tcl_CmdInfo * infoPtr)); /* 159 */
- CONST84_RETURN char * (*tcl_GetCommandName) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Command command)); /* 160 */
- int (*tcl_GetErrno) _ANSI_ARGS_((void)); /* 161 */
- CONST84_RETURN char * (*tcl_GetHostName) _ANSI_ARGS_((void)); /* 162 */
- int (*tcl_GetInterpPath) _ANSI_ARGS_((Tcl_Interp * askInterp, Tcl_Interp * slaveInterp)); /* 163 */
- Tcl_Interp * (*tcl_GetMaster) _ANSI_ARGS_((Tcl_Interp * interp)); /* 164 */
- CONST char * (*tcl_GetNameOfExecutable) _ANSI_ARGS_((void)); /* 165 */
- Tcl_Obj * (*tcl_GetObjResult) _ANSI_ARGS_((Tcl_Interp * interp)); /* 166 */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
- int (*tcl_GetOpenFile) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, int forWriting, int checkUsage, ClientData * filePtr)); /* 167 */
+#ifdef __WIN32__ /* WIN */
+ VOID *reserved10;
+#endif /* WIN */
+#ifdef MAC_OSX_TCL /* MACOSX */
+ void (*tcl_DeleteFileHandler) (int fd); /* 10 */
+#endif /* MACOSX */
+ void (*tcl_SetTimer) (Tcl_Time *timePtr); /* 11 */
+ void (*tcl_Sleep) (int ms); /* 12 */
+ int (*tcl_WaitForEvent) (Tcl_Time *timePtr); /* 13 */
+ int (*tcl_AppendAllObjTypes) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 14 */
+ void (*tcl_AppendStringsToObj) (Tcl_Obj *objPtr, ...); /* 15 */
+ void (*tcl_AppendToObj) (Tcl_Obj *objPtr, CONST char *bytes, int length); /* 16 */
+ Tcl_Obj * (*tcl_ConcatObj) (int objc, Tcl_Obj *CONST objv[]); /* 17 */
+ int (*tcl_ConvertToType) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_ObjType *typePtr); /* 18 */
+ void (*tcl_DbDecrRefCount) (Tcl_Obj *objPtr, CONST char *file, int line); /* 19 */
+ void (*tcl_DbIncrRefCount) (Tcl_Obj *objPtr, CONST char *file, int line); /* 20 */
+ int (*tcl_DbIsShared) (Tcl_Obj *objPtr, CONST char *file, int line); /* 21 */
+ Tcl_Obj * (*tcl_DbNewBooleanObj) (int boolValue, CONST char *file, int line); /* 22 */
+ Tcl_Obj * (*tcl_DbNewByteArrayObj) (CONST unsigned char *bytes, int length, CONST char *file, int line); /* 23 */
+ Tcl_Obj * (*tcl_DbNewDoubleObj) (double doubleValue, CONST char *file, int line); /* 24 */
+ Tcl_Obj * (*tcl_DbNewListObj) (int objc, Tcl_Obj *CONST *objv, CONST char *file, int line); /* 25 */
+ Tcl_Obj * (*tcl_DbNewLongObj) (long longValue, CONST char *file, int line); /* 26 */
+ Tcl_Obj * (*tcl_DbNewObj) (CONST char *file, int line); /* 27 */
+ Tcl_Obj * (*tcl_DbNewStringObj) (CONST char *bytes, int length, CONST char *file, int line); /* 28 */
+ Tcl_Obj * (*tcl_DuplicateObj) (Tcl_Obj *objPtr); /* 29 */
+ void (*tclFreeObj) (Tcl_Obj *objPtr); /* 30 */
+ int (*tcl_GetBoolean) (Tcl_Interp *interp, CONST char *src, int *boolPtr); /* 31 */
+ int (*tcl_GetBooleanFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *boolPtr); /* 32 */
+ unsigned char * (*tcl_GetByteArrayFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 33 */
+ int (*tcl_GetDouble) (Tcl_Interp *interp, CONST char *src, double *doublePtr); /* 34 */
+ int (*tcl_GetDoubleFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, double *doublePtr); /* 35 */
+ int (*tcl_GetIndexFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, CONST84 char **tablePtr, CONST char *msg, int flags, int *indexPtr); /* 36 */
+ int (*tcl_GetInt) (Tcl_Interp *interp, CONST char *src, int *intPtr); /* 37 */
+ int (*tcl_GetIntFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *intPtr); /* 38 */
+ int (*tcl_GetLongFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, long *longPtr); /* 39 */
+ Tcl_ObjType * (*tcl_GetObjType) (CONST char *typeName); /* 40 */
+ char * (*tcl_GetStringFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 41 */
+ void (*tcl_InvalidateStringRep) (Tcl_Obj *objPtr); /* 42 */
+ int (*tcl_ListObjAppendList) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *elemListPtr); /* 43 */
+ int (*tcl_ListObjAppendElement) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *objPtr); /* 44 */
+ int (*tcl_ListObjGetElements) (Tcl_Interp *interp, Tcl_Obj *listPtr, int *objcPtr, Tcl_Obj ***objvPtr); /* 45 */
+ int (*tcl_ListObjIndex) (Tcl_Interp *interp, Tcl_Obj *listPtr, int index, Tcl_Obj **objPtrPtr); /* 46 */
+ int (*tcl_ListObjLength) (Tcl_Interp *interp, Tcl_Obj *listPtr, int *lengthPtr); /* 47 */
+ int (*tcl_ListObjReplace) (Tcl_Interp *interp, Tcl_Obj *listPtr, int first, int count, int objc, Tcl_Obj *CONST objv[]); /* 48 */
+ Tcl_Obj * (*tcl_NewBooleanObj) (int boolValue); /* 49 */
+ Tcl_Obj * (*tcl_NewByteArrayObj) (CONST unsigned char *bytes, int length); /* 50 */
+ Tcl_Obj * (*tcl_NewDoubleObj) (double doubleValue); /* 51 */
+ Tcl_Obj * (*tcl_NewIntObj) (int intValue); /* 52 */
+ Tcl_Obj * (*tcl_NewListObj) (int objc, Tcl_Obj *CONST objv[]); /* 53 */
+ Tcl_Obj * (*tcl_NewLongObj) (long longValue); /* 54 */
+ Tcl_Obj * (*tcl_NewObj) (void); /* 55 */
+ Tcl_Obj * (*tcl_NewStringObj) (CONST char *bytes, int length); /* 56 */
+ void (*tcl_SetBooleanObj) (Tcl_Obj *objPtr, int boolValue); /* 57 */
+ unsigned char * (*tcl_SetByteArrayLength) (Tcl_Obj *objPtr, int length); /* 58 */
+ void (*tcl_SetByteArrayObj) (Tcl_Obj *objPtr, CONST unsigned char *bytes, int length); /* 59 */
+ void (*tcl_SetDoubleObj) (Tcl_Obj *objPtr, double doubleValue); /* 60 */
+ void (*tcl_SetIntObj) (Tcl_Obj *objPtr, int intValue); /* 61 */
+ void (*tcl_SetListObj) (Tcl_Obj *objPtr, int objc, Tcl_Obj *CONST objv[]); /* 62 */
+ void (*tcl_SetLongObj) (Tcl_Obj *objPtr, long longValue); /* 63 */
+ void (*tcl_SetObjLength) (Tcl_Obj *objPtr, int length); /* 64 */
+ void (*tcl_SetStringObj) (Tcl_Obj *objPtr, CONST char *bytes, int length); /* 65 */
+ void (*tcl_AddErrorInfo) (Tcl_Interp *interp, CONST char *message); /* 66 */
+ void (*tcl_AddObjErrorInfo) (Tcl_Interp *interp, CONST char *message, int length); /* 67 */
+ void (*tcl_AllowExceptions) (Tcl_Interp *interp); /* 68 */
+ void (*tcl_AppendElement) (Tcl_Interp *interp, CONST char *element); /* 69 */
+ void (*tcl_AppendResult) (Tcl_Interp *interp, ...); /* 70 */
+ Tcl_AsyncHandler (*tcl_AsyncCreate) (Tcl_AsyncProc *proc, ClientData clientData); /* 71 */
+ void (*tcl_AsyncDelete) (Tcl_AsyncHandler async); /* 72 */
+ int (*tcl_AsyncInvoke) (Tcl_Interp *interp, int code); /* 73 */
+ void (*tcl_AsyncMark) (Tcl_AsyncHandler async); /* 74 */
+ int (*tcl_AsyncReady) (void); /* 75 */
+ void (*tcl_BackgroundError) (Tcl_Interp *interp); /* 76 */
+ char (*tcl_Backslash) (CONST char *src, int *readPtr); /* 77 */
+ int (*tcl_BadChannelOption) (Tcl_Interp *interp, CONST char *optionName, CONST char *optionList); /* 78 */
+ void (*tcl_CallWhenDeleted) (Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, ClientData clientData); /* 79 */
+ void (*tcl_CancelIdleCall) (Tcl_IdleProc *idleProc, ClientData clientData); /* 80 */
+ int (*tcl_Close) (Tcl_Interp *interp, Tcl_Channel chan); /* 81 */
+ int (*tcl_CommandComplete) (CONST char *cmd); /* 82 */
+ char * (*tcl_Concat) (int argc, CONST84 char *CONST *argv); /* 83 */
+ int (*tcl_ConvertElement) (CONST char *src, char *dst, int flags); /* 84 */
+ int (*tcl_ConvertCountedElement) (CONST char *src, int length, char *dst, int flags); /* 85 */
+ int (*tcl_CreateAlias) (Tcl_Interp *slave, CONST char *slaveCmd, Tcl_Interp *target, CONST char *targetCmd, int argc, CONST84 char *CONST *argv); /* 86 */
+ int (*tcl_CreateAliasObj) (Tcl_Interp *slave, CONST char *slaveCmd, Tcl_Interp *target, CONST char *targetCmd, int objc, Tcl_Obj *CONST objv[]); /* 87 */
+ Tcl_Channel (*tcl_CreateChannel) (Tcl_ChannelType *typePtr, CONST char *chanName, ClientData instanceData, int mask); /* 88 */
+ void (*tcl_CreateChannelHandler) (Tcl_Channel chan, int mask, Tcl_ChannelProc *proc, ClientData clientData); /* 89 */
+ void (*tcl_CreateCloseHandler) (Tcl_Channel chan, Tcl_CloseProc *proc, ClientData clientData); /* 90 */
+ Tcl_Command (*tcl_CreateCommand) (Tcl_Interp *interp, CONST char *cmdName, Tcl_CmdProc *proc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc); /* 91 */
+ void (*tcl_CreateEventSource) (Tcl_EventSetupProc *setupProc, Tcl_EventCheckProc *checkProc, ClientData clientData); /* 92 */
+ void (*tcl_CreateExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 93 */
+ Tcl_Interp * (*tcl_CreateInterp) (void); /* 94 */
+ void (*tcl_CreateMathFunc) (Tcl_Interp *interp, CONST char *name, int numArgs, Tcl_ValueType *argTypes, Tcl_MathProc *proc, ClientData clientData); /* 95 */
+ Tcl_Command (*tcl_CreateObjCommand) (Tcl_Interp *interp, CONST char *cmdName, Tcl_ObjCmdProc *proc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc); /* 96 */
+ Tcl_Interp * (*tcl_CreateSlave) (Tcl_Interp *interp, CONST char *slaveName, int isSafe); /* 97 */
+ Tcl_TimerToken (*tcl_CreateTimerHandler) (int milliseconds, Tcl_TimerProc *proc, ClientData clientData); /* 98 */
+ Tcl_Trace (*tcl_CreateTrace) (Tcl_Interp *interp, int level, Tcl_CmdTraceProc *proc, ClientData clientData); /* 99 */
+ void (*tcl_DeleteAssocData) (Tcl_Interp *interp, CONST char *name); /* 100 */
+ void (*tcl_DeleteChannelHandler) (Tcl_Channel chan, Tcl_ChannelProc *proc, ClientData clientData); /* 101 */
+ void (*tcl_DeleteCloseHandler) (Tcl_Channel chan, Tcl_CloseProc *proc, ClientData clientData); /* 102 */
+ int (*tcl_DeleteCommand) (Tcl_Interp *interp, CONST char *cmdName); /* 103 */
+ int (*tcl_DeleteCommandFromToken) (Tcl_Interp *interp, Tcl_Command command); /* 104 */
+ void (*tcl_DeleteEvents) (Tcl_EventDeleteProc *proc, ClientData clientData); /* 105 */
+ void (*tcl_DeleteEventSource) (Tcl_EventSetupProc *setupProc, Tcl_EventCheckProc *checkProc, ClientData clientData); /* 106 */
+ void (*tcl_DeleteExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 107 */
+ void (*tcl_DeleteHashEntry) (Tcl_HashEntry *entryPtr); /* 108 */
+ void (*tcl_DeleteHashTable) (Tcl_HashTable *tablePtr); /* 109 */
+ void (*tcl_DeleteInterp) (Tcl_Interp *interp); /* 110 */
+ void (*tcl_DetachPids) (int numPids, Tcl_Pid *pidPtr); /* 111 */
+ void (*tcl_DeleteTimerHandler) (Tcl_TimerToken token); /* 112 */
+ void (*tcl_DeleteTrace) (Tcl_Interp *interp, Tcl_Trace trace); /* 113 */
+ void (*tcl_DontCallWhenDeleted) (Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, ClientData clientData); /* 114 */
+ int (*tcl_DoOneEvent) (int flags); /* 115 */
+ void (*tcl_DoWhenIdle) (Tcl_IdleProc *proc, ClientData clientData); /* 116 */
+ char * (*tcl_DStringAppend) (Tcl_DString *dsPtr, CONST char *bytes, int length); /* 117 */
+ char * (*tcl_DStringAppendElement) (Tcl_DString *dsPtr, CONST char *element); /* 118 */
+ void (*tcl_DStringEndSublist) (Tcl_DString *dsPtr); /* 119 */
+ void (*tcl_DStringFree) (Tcl_DString *dsPtr); /* 120 */
+ void (*tcl_DStringGetResult) (Tcl_Interp *interp, Tcl_DString *dsPtr); /* 121 */
+ void (*tcl_DStringInit) (Tcl_DString *dsPtr); /* 122 */
+ void (*tcl_DStringResult) (Tcl_Interp *interp, Tcl_DString *dsPtr); /* 123 */
+ void (*tcl_DStringSetLength) (Tcl_DString *dsPtr, int length); /* 124 */
+ void (*tcl_DStringStartSublist) (Tcl_DString *dsPtr); /* 125 */
+ int (*tcl_Eof) (Tcl_Channel chan); /* 126 */
+ CONST84_RETURN char * (*tcl_ErrnoId) (void); /* 127 */
+ CONST84_RETURN char * (*tcl_ErrnoMsg) (int err); /* 128 */
+ int (*tcl_Eval) (Tcl_Interp *interp, CONST char *script); /* 129 */
+ int (*tcl_EvalFile) (Tcl_Interp *interp, CONST char *fileName); /* 130 */
+ int (*tcl_EvalObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 131 */
+ void (*tcl_EventuallyFree) (ClientData clientData, Tcl_FreeProc *freeProc); /* 132 */
+ void (*tcl_Exit) (int status); /* 133 */
+ int (*tcl_ExposeCommand) (Tcl_Interp *interp, CONST char *hiddenCmdToken, CONST char *cmdName); /* 134 */
+ int (*tcl_ExprBoolean) (Tcl_Interp *interp, CONST char *expr, int *ptr); /* 135 */
+ int (*tcl_ExprBooleanObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *ptr); /* 136 */
+ int (*tcl_ExprDouble) (Tcl_Interp *interp, CONST char *expr, double *ptr); /* 137 */
+ int (*tcl_ExprDoubleObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, double *ptr); /* 138 */
+ int (*tcl_ExprLong) (Tcl_Interp *interp, CONST char *expr, long *ptr); /* 139 */
+ int (*tcl_ExprLongObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, long *ptr); /* 140 */
+ int (*tcl_ExprObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj **resultPtrPtr); /* 141 */
+ int (*tcl_ExprString) (Tcl_Interp *interp, CONST char *expr); /* 142 */
+ void (*tcl_Finalize) (void); /* 143 */
+ void (*tcl_FindExecutable) (CONST char *argv0); /* 144 */
+ Tcl_HashEntry * (*tcl_FirstHashEntry) (Tcl_HashTable *tablePtr, Tcl_HashSearch *searchPtr); /* 145 */
+ int (*tcl_Flush) (Tcl_Channel chan); /* 146 */
+ void (*tcl_FreeResult) (Tcl_Interp *interp); /* 147 */
+ int (*tcl_GetAlias) (Tcl_Interp *interp, CONST char *slaveCmd, Tcl_Interp **targetInterpPtr, CONST84 char **targetCmdPtr, int *argcPtr, CONST84 char ***argvPtr); /* 148 */
+ int (*tcl_GetAliasObj) (Tcl_Interp *interp, CONST char *slaveCmd, Tcl_Interp **targetInterpPtr, CONST84 char **targetCmdPtr, int *objcPtr, Tcl_Obj ***objv); /* 149 */
+ ClientData (*tcl_GetAssocData) (Tcl_Interp *interp, CONST char *name, Tcl_InterpDeleteProc **procPtr); /* 150 */
+ Tcl_Channel (*tcl_GetChannel) (Tcl_Interp *interp, CONST char *chanName, int *modePtr); /* 151 */
+ int (*tcl_GetChannelBufferSize) (Tcl_Channel chan); /* 152 */
+ int (*tcl_GetChannelHandle) (Tcl_Channel chan, int direction, ClientData *handlePtr); /* 153 */
+ ClientData (*tcl_GetChannelInstanceData) (Tcl_Channel chan); /* 154 */
+ int (*tcl_GetChannelMode) (Tcl_Channel chan); /* 155 */
+ CONST84_RETURN char * (*tcl_GetChannelName) (Tcl_Channel chan); /* 156 */
+ int (*tcl_GetChannelOption) (Tcl_Interp *interp, Tcl_Channel chan, CONST char *optionName, Tcl_DString *dsPtr); /* 157 */
+ Tcl_ChannelType * (*tcl_GetChannelType) (Tcl_Channel chan); /* 158 */
+ int (*tcl_GetCommandInfo) (Tcl_Interp *interp, CONST char *cmdName, Tcl_CmdInfo *infoPtr); /* 159 */
+ CONST84_RETURN char * (*tcl_GetCommandName) (Tcl_Interp *interp, Tcl_Command command); /* 160 */
+ int (*tcl_GetErrno) (void); /* 161 */
+ CONST84_RETURN char * (*tcl_GetHostName) (void); /* 162 */
+ int (*tcl_GetInterpPath) (Tcl_Interp *askInterp, Tcl_Interp *slaveInterp); /* 163 */
+ Tcl_Interp * (*tcl_GetMaster) (Tcl_Interp *interp); /* 164 */
+ CONST char * (*tcl_GetNameOfExecutable) (void); /* 165 */
+ Tcl_Obj * (*tcl_GetObjResult) (Tcl_Interp *interp); /* 166 */
+#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
+ int (*tcl_GetOpenFile) (Tcl_Interp *interp, CONST char *chanID, int forWriting, int checkUsage, ClientData *filePtr); /* 167 */
#endif /* UNIX */
-#ifdef __WIN32__
- void *reserved167;
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
- void *reserved167;
-#endif /* MAC_TCL */
- Tcl_PathType (*tcl_GetPathType) _ANSI_ARGS_((CONST char * path)); /* 168 */
- int (*tcl_Gets) _ANSI_ARGS_((Tcl_Channel chan, Tcl_DString * dsPtr)); /* 169 */
- int (*tcl_GetsObj) _ANSI_ARGS_((Tcl_Channel chan, Tcl_Obj * objPtr)); /* 170 */
- int (*tcl_GetServiceMode) _ANSI_ARGS_((void)); /* 171 */
- Tcl_Interp * (*tcl_GetSlave) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * slaveName)); /* 172 */
- Tcl_Channel (*tcl_GetStdChannel) _ANSI_ARGS_((int type)); /* 173 */
- CONST84_RETURN char * (*tcl_GetStringResult) _ANSI_ARGS_((Tcl_Interp * interp)); /* 174 */
- CONST84_RETURN char * (*tcl_GetVar) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * varName, int flags)); /* 175 */
- CONST84_RETURN char * (*tcl_GetVar2) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * part1, CONST char * part2, int flags)); /* 176 */
- int (*tcl_GlobalEval) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * command)); /* 177 */
- int (*tcl_GlobalEvalObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr)); /* 178 */
- int (*tcl_HideCommand) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * cmdName, CONST char * hiddenCmdToken)); /* 179 */
- int (*tcl_Init) _ANSI_ARGS_((Tcl_Interp * interp)); /* 180 */
- void (*tcl_InitHashTable) _ANSI_ARGS_((Tcl_HashTable * tablePtr, int keyType)); /* 181 */
- int (*tcl_InputBlocked) _ANSI_ARGS_((Tcl_Channel chan)); /* 182 */
- int (*tcl_InputBuffered) _ANSI_ARGS_((Tcl_Channel chan)); /* 183 */
- int (*tcl_InterpDeleted) _ANSI_ARGS_((Tcl_Interp * interp)); /* 184 */
- int (*tcl_IsSafe) _ANSI_ARGS_((Tcl_Interp * interp)); /* 185 */
- char * (*tcl_JoinPath) _ANSI_ARGS_((int argc, CONST84 char * CONST * argv, Tcl_DString * resultPtr)); /* 186 */
- int (*tcl_LinkVar) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * varName, char * addr, int type)); /* 187 */
- void *reserved188;
- Tcl_Channel (*tcl_MakeFileChannel) _ANSI_ARGS_((ClientData handle, int mode)); /* 189 */
- int (*tcl_MakeSafe) _ANSI_ARGS_((Tcl_Interp * interp)); /* 190 */
- Tcl_Channel (*tcl_MakeTcpClientChannel) _ANSI_ARGS_((ClientData tcpSocket)); /* 191 */
- char * (*tcl_Merge) _ANSI_ARGS_((int argc, CONST84 char * CONST * argv)); /* 192 */
- Tcl_HashEntry * (*tcl_NextHashEntry) _ANSI_ARGS_((Tcl_HashSearch * searchPtr)); /* 193 */
- void (*tcl_NotifyChannel) _ANSI_ARGS_((Tcl_Channel channel, int mask)); /* 194 */
- Tcl_Obj * (*tcl_ObjGetVar2) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr, int flags)); /* 195 */
- Tcl_Obj * (*tcl_ObjSetVar2) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr, Tcl_Obj * newValuePtr, int flags)); /* 196 */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
- Tcl_Channel (*tcl_OpenCommandChannel) _ANSI_ARGS_((Tcl_Interp * interp, int argc, CONST84 char ** argv, int flags)); /* 197 */
-#endif /* UNIX */
-#ifdef __WIN32__
- Tcl_Channel (*tcl_OpenCommandChannel) _ANSI_ARGS_((Tcl_Interp * interp, int argc, CONST84 char ** argv, int flags)); /* 197 */
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
- void *reserved197;
-#endif /* MAC_TCL */
- Tcl_Channel (*tcl_OpenFileChannel) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * fileName, CONST char * modeString, int permissions)); /* 198 */
- Tcl_Channel (*tcl_OpenTcpClient) _ANSI_ARGS_((Tcl_Interp * interp, int port, CONST char * address, CONST char * myaddr, int myport, int async)); /* 199 */
- Tcl_Channel (*tcl_OpenTcpServer) _ANSI_ARGS_((Tcl_Interp * interp, int port, CONST char * host, Tcl_TcpAcceptProc * acceptProc, ClientData callbackData)); /* 200 */
- void (*tcl_Preserve) _ANSI_ARGS_((ClientData data)); /* 201 */
- void (*tcl_PrintDouble) _ANSI_ARGS_((Tcl_Interp * interp, double value, char * dst)); /* 202 */
- int (*tcl_PutEnv) _ANSI_ARGS_((CONST char * string)); /* 203 */
- CONST84_RETURN char * (*tcl_PosixError) _ANSI_ARGS_((Tcl_Interp * interp)); /* 204 */
- void (*tcl_QueueEvent) _ANSI_ARGS_((Tcl_Event * evPtr, Tcl_QueuePosition position)); /* 205 */
- int (*tcl_Read) _ANSI_ARGS_((Tcl_Channel chan, char * bufPtr, int toRead)); /* 206 */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
- void (*tcl_ReapDetachedProcs) _ANSI_ARGS_((void)); /* 207 */
-#endif /* UNIX */
-#ifdef __WIN32__
- void (*tcl_ReapDetachedProcs) _ANSI_ARGS_((void)); /* 207 */
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
- void *reserved207;
-#endif /* MAC_TCL */
- int (*tcl_RecordAndEval) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * cmd, int flags)); /* 208 */
- int (*tcl_RecordAndEvalObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * cmdPtr, int flags)); /* 209 */
- void (*tcl_RegisterChannel) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan)); /* 210 */
- void (*tcl_RegisterObjType) _ANSI_ARGS_((Tcl_ObjType * typePtr)); /* 211 */
- Tcl_RegExp (*tcl_RegExpCompile) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string)); /* 212 */
- int (*tcl_RegExpExec) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_RegExp regexp, CONST char * str, CONST char * start)); /* 213 */
- int (*tcl_RegExpMatch) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, CONST char * pattern)); /* 214 */
- void (*tcl_RegExpRange) _ANSI_ARGS_((Tcl_RegExp regexp, int index, CONST84 char ** startPtr, CONST84 char ** endPtr)); /* 215 */
- void (*tcl_Release) _ANSI_ARGS_((ClientData clientData)); /* 216 */
- void (*tcl_ResetResult) _ANSI_ARGS_((Tcl_Interp * interp)); /* 217 */
- int (*tcl_ScanElement) _ANSI_ARGS_((CONST char * str, int * flagPtr)); /* 218 */
- int (*tcl_ScanCountedElement) _ANSI_ARGS_((CONST char * str, int length, int * flagPtr)); /* 219 */
- int (*tcl_SeekOld) _ANSI_ARGS_((Tcl_Channel chan, int offset, int mode)); /* 220 */
- int (*tcl_ServiceAll) _ANSI_ARGS_((void)); /* 221 */
- int (*tcl_ServiceEvent) _ANSI_ARGS_((int flags)); /* 222 */
- void (*tcl_SetAssocData) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, Tcl_InterpDeleteProc * proc, ClientData clientData)); /* 223 */
- void (*tcl_SetChannelBufferSize) _ANSI_ARGS_((Tcl_Channel chan, int sz)); /* 224 */
- int (*tcl_SetChannelOption) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan, CONST char * optionName, CONST char * newValue)); /* 225 */
- int (*tcl_SetCommandInfo) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * cmdName, CONST Tcl_CmdInfo * infoPtr)); /* 226 */
- void (*tcl_SetErrno) _ANSI_ARGS_((int err)); /* 227 */
- void (*tcl_SetErrorCode) _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp)); /* 228 */
- void (*tcl_SetMaxBlockTime) _ANSI_ARGS_((Tcl_Time * timePtr)); /* 229 */
- void (*tcl_SetPanicProc) _ANSI_ARGS_((Tcl_PanicProc * panicProc)); /* 230 */
- int (*tcl_SetRecursionLimit) _ANSI_ARGS_((Tcl_Interp * interp, int depth)); /* 231 */
- void (*tcl_SetResult) _ANSI_ARGS_((Tcl_Interp * interp, char * str, Tcl_FreeProc * freeProc)); /* 232 */
- int (*tcl_SetServiceMode) _ANSI_ARGS_((int mode)); /* 233 */
- void (*tcl_SetObjErrorCode) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * errorObjPtr)); /* 234 */
- void (*tcl_SetObjResult) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * resultObjPtr)); /* 235 */
- void (*tcl_SetStdChannel) _ANSI_ARGS_((Tcl_Channel channel, int type)); /* 236 */
- CONST84_RETURN char * (*tcl_SetVar) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * varName, CONST char * newValue, int flags)); /* 237 */
- CONST84_RETURN char * (*tcl_SetVar2) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * part1, CONST char * part2, CONST char * newValue, int flags)); /* 238 */
- CONST84_RETURN char * (*tcl_SignalId) _ANSI_ARGS_((int sig)); /* 239 */
- CONST84_RETURN char * (*tcl_SignalMsg) _ANSI_ARGS_((int sig)); /* 240 */
- void (*tcl_SourceRCFile) _ANSI_ARGS_((Tcl_Interp * interp)); /* 241 */
- int (*tcl_SplitList) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * listStr, int * argcPtr, CONST84 char *** argvPtr)); /* 242 */
- void (*tcl_SplitPath) _ANSI_ARGS_((CONST char * path, int * argcPtr, CONST84 char *** argvPtr)); /* 243 */
- void (*tcl_StaticPackage) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * pkgName, Tcl_PackageInitProc * initProc, Tcl_PackageInitProc * safeInitProc)); /* 244 */
- int (*tcl_StringMatch) _ANSI_ARGS_((CONST char * str, CONST char * pattern)); /* 245 */
- int (*tcl_TellOld) _ANSI_ARGS_((Tcl_Channel chan)); /* 246 */
- int (*tcl_TraceVar) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * varName, int flags, Tcl_VarTraceProc * proc, ClientData clientData)); /* 247 */
- int (*tcl_TraceVar2) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * part1, CONST char * part2, int flags, Tcl_VarTraceProc * proc, ClientData clientData)); /* 248 */
- char * (*tcl_TranslateFileName) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, Tcl_DString * bufferPtr)); /* 249 */
- int (*tcl_Ungets) _ANSI_ARGS_((Tcl_Channel chan, CONST char * str, int len, int atHead)); /* 250 */
- void (*tcl_UnlinkVar) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * varName)); /* 251 */
- int (*tcl_UnregisterChannel) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan)); /* 252 */
- int (*tcl_UnsetVar) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * varName, int flags)); /* 253 */
- int (*tcl_UnsetVar2) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * part1, CONST char * part2, int flags)); /* 254 */
- void (*tcl_UntraceVar) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * varName, int flags, Tcl_VarTraceProc * proc, ClientData clientData)); /* 255 */
- void (*tcl_UntraceVar2) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * part1, CONST char * part2, int flags, Tcl_VarTraceProc * proc, ClientData clientData)); /* 256 */
- void (*tcl_UpdateLinkedVar) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * varName)); /* 257 */
- int (*tcl_UpVar) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * frameName, CONST char * varName, CONST char * localName, int flags)); /* 258 */
- int (*tcl_UpVar2) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * frameName, CONST char * part1, CONST char * part2, CONST char * localName, int flags)); /* 259 */
- int (*tcl_VarEval) _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp)); /* 260 */
- ClientData (*tcl_VarTraceInfo) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * varName, int flags, Tcl_VarTraceProc * procPtr, ClientData prevClientData)); /* 261 */
- ClientData (*tcl_VarTraceInfo2) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * part1, CONST char * part2, int flags, Tcl_VarTraceProc * procPtr, ClientData prevClientData)); /* 262 */
- int (*tcl_Write) _ANSI_ARGS_((Tcl_Channel chan, CONST char * s, int slen)); /* 263 */
- void (*tcl_WrongNumArgs) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[], CONST char * message)); /* 264 */
- int (*tcl_DumpActiveMemory) _ANSI_ARGS_((CONST char * fileName)); /* 265 */
- void (*tcl_ValidateAllMemory) _ANSI_ARGS_((CONST char * file, int line)); /* 266 */
- void (*tcl_AppendResultVA) _ANSI_ARGS_((Tcl_Interp * interp, va_list argList)); /* 267 */
- void (*tcl_AppendStringsToObjVA) _ANSI_ARGS_((Tcl_Obj * objPtr, va_list argList)); /* 268 */
- CONST84_RETURN char * (*tcl_HashStats) _ANSI_ARGS_((Tcl_HashTable * tablePtr)); /* 269 */
- CONST84_RETURN char * (*tcl_ParseVar) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, CONST84 char ** termPtr)); /* 270 */
- CONST84_RETURN char * (*tcl_PkgPresent) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, CONST char * version, int exact)); /* 271 */
- CONST84_RETURN char * (*tcl_PkgPresentEx) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, CONST char * version, int exact, ClientData * clientDataPtr)); /* 272 */
- int (*tcl_PkgProvide) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, CONST char * version)); /* 273 */
- CONST84_RETURN char * (*tcl_PkgRequire) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, CONST char * version, int exact)); /* 274 */
- void (*tcl_SetErrorCodeVA) _ANSI_ARGS_((Tcl_Interp * interp, va_list argList)); /* 275 */
- int (*tcl_VarEvalVA) _ANSI_ARGS_((Tcl_Interp * interp, va_list argList)); /* 276 */
- Tcl_Pid (*tcl_WaitPid) _ANSI_ARGS_((Tcl_Pid pid, int * statPtr, int options)); /* 277 */
- void (*tcl_PanicVA) _ANSI_ARGS_((CONST char * format, va_list argList)); /* 278 */
- void (*tcl_GetVersion) _ANSI_ARGS_((int * major, int * minor, int * patchLevel, int * type)); /* 279 */
- void (*tcl_InitMemory) _ANSI_ARGS_((Tcl_Interp * interp)); /* 280 */
- Tcl_Channel (*tcl_StackChannel) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_ChannelType * typePtr, ClientData instanceData, int mask, Tcl_Channel prevChan)); /* 281 */
- int (*tcl_UnstackChannel) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan)); /* 282 */
- Tcl_Channel (*tcl_GetStackedChannel) _ANSI_ARGS_((Tcl_Channel chan)); /* 283 */
- void (*tcl_SetMainLoop) _ANSI_ARGS_((Tcl_MainLoopProc * proc)); /* 284 */
- void *reserved285;
- void (*tcl_AppendObjToObj) _ANSI_ARGS_((Tcl_Obj * objPtr, Tcl_Obj * appendObjPtr)); /* 286 */
- Tcl_Encoding (*tcl_CreateEncoding) _ANSI_ARGS_((Tcl_EncodingType * typePtr)); /* 287 */
- void (*tcl_CreateThreadExitHandler) _ANSI_ARGS_((Tcl_ExitProc * proc, ClientData clientData)); /* 288 */
- void (*tcl_DeleteThreadExitHandler) _ANSI_ARGS_((Tcl_ExitProc * proc, ClientData clientData)); /* 289 */
- void (*tcl_DiscardResult) _ANSI_ARGS_((Tcl_SavedResult * statePtr)); /* 290 */
- int (*tcl_EvalEx) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * script, int numBytes, int flags)); /* 291 */
- int (*tcl_EvalObjv) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[], int flags)); /* 292 */
- int (*tcl_EvalObjEx) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, int flags)); /* 293 */
- void (*tcl_ExitThread) _ANSI_ARGS_((int status)); /* 294 */
- int (*tcl_ExternalToUtf) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Encoding encoding, CONST char * src, int srcLen, int flags, Tcl_EncodingState * statePtr, char * dst, int dstLen, int * srcReadPtr, int * dstWrotePtr, int * dstCharsPtr)); /* 295 */
- char * (*tcl_ExternalToUtfDString) _ANSI_ARGS_((Tcl_Encoding encoding, CONST char * src, int srcLen, Tcl_DString * dsPtr)); /* 296 */
- void (*tcl_FinalizeThread) _ANSI_ARGS_((void)); /* 297 */
- void (*tcl_FinalizeNotifier) _ANSI_ARGS_((ClientData clientData)); /* 298 */
- void (*tcl_FreeEncoding) _ANSI_ARGS_((Tcl_Encoding encoding)); /* 299 */
- Tcl_ThreadId (*tcl_GetCurrentThread) _ANSI_ARGS_((void)); /* 300 */
- Tcl_Encoding (*tcl_GetEncoding) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name)); /* 301 */
- CONST84_RETURN char * (*tcl_GetEncodingName) _ANSI_ARGS_((Tcl_Encoding encoding)); /* 302 */
- void (*tcl_GetEncodingNames) _ANSI_ARGS_((Tcl_Interp * interp)); /* 303 */
- int (*tcl_GetIndexFromObjStruct) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, CONST VOID * tablePtr, int offset, CONST char * msg, int flags, int * indexPtr)); /* 304 */
- VOID * (*tcl_GetThreadData) _ANSI_ARGS_((Tcl_ThreadDataKey * keyPtr, int size)); /* 305 */
- Tcl_Obj * (*tcl_GetVar2Ex) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * part1, CONST char * part2, int flags)); /* 306 */
- ClientData (*tcl_InitNotifier) _ANSI_ARGS_((void)); /* 307 */
- void (*tcl_MutexLock) _ANSI_ARGS_((Tcl_Mutex * mutexPtr)); /* 308 */
- void (*tcl_MutexUnlock) _ANSI_ARGS_((Tcl_Mutex * mutexPtr)); /* 309 */
- void (*tcl_ConditionNotify) _ANSI_ARGS_((Tcl_Condition * condPtr)); /* 310 */
- void (*tcl_ConditionWait) _ANSI_ARGS_((Tcl_Condition * condPtr, Tcl_Mutex * mutexPtr, Tcl_Time * timePtr)); /* 311 */
- int (*tcl_NumUtfChars) _ANSI_ARGS_((CONST char * src, int len)); /* 312 */
- int (*tcl_ReadChars) _ANSI_ARGS_((Tcl_Channel channel, Tcl_Obj * objPtr, int charsToRead, int appendFlag)); /* 313 */
- void (*tcl_RestoreResult) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_SavedResult * statePtr)); /* 314 */
- void (*tcl_SaveResult) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_SavedResult * statePtr)); /* 315 */
- int (*tcl_SetSystemEncoding) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name)); /* 316 */
- Tcl_Obj * (*tcl_SetVar2Ex) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * part1, CONST char * part2, Tcl_Obj * newValuePtr, int flags)); /* 317 */
- void (*tcl_ThreadAlert) _ANSI_ARGS_((Tcl_ThreadId threadId)); /* 318 */
- void (*tcl_ThreadQueueEvent) _ANSI_ARGS_((Tcl_ThreadId threadId, Tcl_Event* evPtr, Tcl_QueuePosition position)); /* 319 */
- Tcl_UniChar (*tcl_UniCharAtIndex) _ANSI_ARGS_((CONST char * src, int index)); /* 320 */
- Tcl_UniChar (*tcl_UniCharToLower) _ANSI_ARGS_((int ch)); /* 321 */
- Tcl_UniChar (*tcl_UniCharToTitle) _ANSI_ARGS_((int ch)); /* 322 */
- Tcl_UniChar (*tcl_UniCharToUpper) _ANSI_ARGS_((int ch)); /* 323 */
- int (*tcl_UniCharToUtf) _ANSI_ARGS_((int ch, char * buf)); /* 324 */
- CONST84_RETURN char * (*tcl_UtfAtIndex) _ANSI_ARGS_((CONST char * src, int index)); /* 325 */
- int (*tcl_UtfCharComplete) _ANSI_ARGS_((CONST char * src, int len)); /* 326 */
- int (*tcl_UtfBackslash) _ANSI_ARGS_((CONST char * src, int * readPtr, char * dst)); /* 327 */
- CONST84_RETURN char * (*tcl_UtfFindFirst) _ANSI_ARGS_((CONST char * src, int ch)); /* 328 */
- CONST84_RETURN char * (*tcl_UtfFindLast) _ANSI_ARGS_((CONST char * src, int ch)); /* 329 */
- CONST84_RETURN char * (*tcl_UtfNext) _ANSI_ARGS_((CONST char * src)); /* 330 */
- CONST84_RETURN char * (*tcl_UtfPrev) _ANSI_ARGS_((CONST char * src, CONST char * start)); /* 331 */
- int (*tcl_UtfToExternal) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Encoding encoding, CONST char * src, int srcLen, int flags, Tcl_EncodingState * statePtr, char * dst, int dstLen, int * srcReadPtr, int * dstWrotePtr, int * dstCharsPtr)); /* 332 */
- char * (*tcl_UtfToExternalDString) _ANSI_ARGS_((Tcl_Encoding encoding, CONST char * src, int srcLen, Tcl_DString * dsPtr)); /* 333 */
- int (*tcl_UtfToLower) _ANSI_ARGS_((char * src)); /* 334 */
- int (*tcl_UtfToTitle) _ANSI_ARGS_((char * src)); /* 335 */
- int (*tcl_UtfToUniChar) _ANSI_ARGS_((CONST char * src, Tcl_UniChar * chPtr)); /* 336 */
- int (*tcl_UtfToUpper) _ANSI_ARGS_((char * src)); /* 337 */
- int (*tcl_WriteChars) _ANSI_ARGS_((Tcl_Channel chan, CONST char * src, int srcLen)); /* 338 */
- int (*tcl_WriteObj) _ANSI_ARGS_((Tcl_Channel chan, Tcl_Obj * objPtr)); /* 339 */
- char * (*tcl_GetString) _ANSI_ARGS_((Tcl_Obj * objPtr)); /* 340 */
- CONST84_RETURN char * (*tcl_GetDefaultEncodingDir) _ANSI_ARGS_((void)); /* 341 */
- void (*tcl_SetDefaultEncodingDir) _ANSI_ARGS_((CONST char * path)); /* 342 */
- void (*tcl_AlertNotifier) _ANSI_ARGS_((ClientData clientData)); /* 343 */
- void (*tcl_ServiceModeHook) _ANSI_ARGS_((int mode)); /* 344 */
- int (*tcl_UniCharIsAlnum) _ANSI_ARGS_((int ch)); /* 345 */
- int (*tcl_UniCharIsAlpha) _ANSI_ARGS_((int ch)); /* 346 */
- int (*tcl_UniCharIsDigit) _ANSI_ARGS_((int ch)); /* 347 */
- int (*tcl_UniCharIsLower) _ANSI_ARGS_((int ch)); /* 348 */
- int (*tcl_UniCharIsSpace) _ANSI_ARGS_((int ch)); /* 349 */
- int (*tcl_UniCharIsUpper) _ANSI_ARGS_((int ch)); /* 350 */
- int (*tcl_UniCharIsWordChar) _ANSI_ARGS_((int ch)); /* 351 */
- int (*tcl_UniCharLen) _ANSI_ARGS_((CONST Tcl_UniChar * str)); /* 352 */
- int (*tcl_UniCharNcmp) _ANSI_ARGS_((CONST Tcl_UniChar * cs, CONST Tcl_UniChar * ct, unsigned long n)); /* 353 */
- char * (*tcl_UniCharToUtfDString) _ANSI_ARGS_((CONST Tcl_UniChar * string, int numChars, Tcl_DString * dsPtr)); /* 354 */
- Tcl_UniChar * (*tcl_UtfToUniCharDString) _ANSI_ARGS_((CONST char * string, int length, Tcl_DString * dsPtr)); /* 355 */
- Tcl_RegExp (*tcl_GetRegExpFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * patObj, int flags)); /* 356 */
- Tcl_Obj * (*tcl_EvalTokens) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Token * tokenPtr, int count)); /* 357 */
- void (*tcl_FreeParse) _ANSI_ARGS_((Tcl_Parse * parsePtr)); /* 358 */
- void (*tcl_LogCommandInfo) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * script, CONST char * command, int length)); /* 359 */
- int (*tcl_ParseBraces) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string, int numBytes, Tcl_Parse * parsePtr, int append, CONST84 char ** termPtr)); /* 360 */
- int (*tcl_ParseCommand) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string, int numBytes, int nested, Tcl_Parse * parsePtr)); /* 361 */
- int (*tcl_ParseExpr) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string, int numBytes, Tcl_Parse * parsePtr)); /* 362 */
- int (*tcl_ParseQuotedString) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string, int numBytes, Tcl_Parse * parsePtr, int append, CONST84 char ** termPtr)); /* 363 */
- int (*tcl_ParseVarName) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string, int numBytes, Tcl_Parse * parsePtr, int append)); /* 364 */
- char * (*tcl_GetCwd) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_DString * cwdPtr)); /* 365 */
- int (*tcl_Chdir) _ANSI_ARGS_((CONST char * dirName)); /* 366 */
- int (*tcl_Access) _ANSI_ARGS_((CONST char * path, int mode)); /* 367 */
- int (*tcl_Stat) _ANSI_ARGS_((CONST char * path, struct stat * bufPtr)); /* 368 */
- int (*tcl_UtfNcmp) _ANSI_ARGS_((CONST char * s1, CONST char * s2, unsigned long n)); /* 369 */
- int (*tcl_UtfNcasecmp) _ANSI_ARGS_((CONST char * s1, CONST char * s2, unsigned long n)); /* 370 */
- int (*tcl_StringCaseMatch) _ANSI_ARGS_((CONST char * str, CONST char * pattern, int nocase)); /* 371 */
- int (*tcl_UniCharIsControl) _ANSI_ARGS_((int ch)); /* 372 */
- int (*tcl_UniCharIsGraph) _ANSI_ARGS_((int ch)); /* 373 */
- int (*tcl_UniCharIsPrint) _ANSI_ARGS_((int ch)); /* 374 */
- int (*tcl_UniCharIsPunct) _ANSI_ARGS_((int ch)); /* 375 */
- int (*tcl_RegExpExecObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_RegExp regexp, Tcl_Obj * objPtr, int offset, int nmatches, int flags)); /* 376 */
- void (*tcl_RegExpGetInfo) _ANSI_ARGS_((Tcl_RegExp regexp, Tcl_RegExpInfo * infoPtr)); /* 377 */
- Tcl_Obj * (*tcl_NewUnicodeObj) _ANSI_ARGS_((CONST Tcl_UniChar * unicode, int numChars)); /* 378 */
- void (*tcl_SetUnicodeObj) _ANSI_ARGS_((Tcl_Obj * objPtr, CONST Tcl_UniChar * unicode, int numChars)); /* 379 */
- int (*tcl_GetCharLength) _ANSI_ARGS_((Tcl_Obj * objPtr)); /* 380 */
- Tcl_UniChar (*tcl_GetUniChar) _ANSI_ARGS_((Tcl_Obj * objPtr, int index)); /* 381 */
- Tcl_UniChar * (*tcl_GetUnicode) _ANSI_ARGS_((Tcl_Obj * objPtr)); /* 382 */
- Tcl_Obj * (*tcl_GetRange) _ANSI_ARGS_((Tcl_Obj * objPtr, int first, int last)); /* 383 */
- void (*tcl_AppendUnicodeToObj) _ANSI_ARGS_((Tcl_Obj * objPtr, CONST Tcl_UniChar * unicode, int length)); /* 384 */
- int (*tcl_RegExpMatchObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * stringObj, Tcl_Obj * patternObj)); /* 385 */
- void (*tcl_SetNotifier) _ANSI_ARGS_((Tcl_NotifierProcs * notifierProcPtr)); /* 386 */
- Tcl_Mutex * (*tcl_GetAllocMutex) _ANSI_ARGS_((void)); /* 387 */
- int (*tcl_GetChannelNames) _ANSI_ARGS_((Tcl_Interp * interp)); /* 388 */
- int (*tcl_GetChannelNamesEx) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * pattern)); /* 389 */
- int (*tcl_ProcObjCmd) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[])); /* 390 */
- void (*tcl_ConditionFinalize) _ANSI_ARGS_((Tcl_Condition * condPtr)); /* 391 */
- void (*tcl_MutexFinalize) _ANSI_ARGS_((Tcl_Mutex * mutex)); /* 392 */
- int (*tcl_CreateThread) _ANSI_ARGS_((Tcl_ThreadId * idPtr, Tcl_ThreadCreateProc proc, ClientData clientData, int stackSize, int flags)); /* 393 */
- int (*tcl_ReadRaw) _ANSI_ARGS_((Tcl_Channel chan, char * dst, int bytesToRead)); /* 394 */
- int (*tcl_WriteRaw) _ANSI_ARGS_((Tcl_Channel chan, CONST char * src, int srcLen)); /* 395 */
- Tcl_Channel (*tcl_GetTopChannel) _ANSI_ARGS_((Tcl_Channel chan)); /* 396 */
- int (*tcl_ChannelBuffered) _ANSI_ARGS_((Tcl_Channel chan)); /* 397 */
- CONST84_RETURN char * (*tcl_ChannelName) _ANSI_ARGS_((Tcl_ChannelType * chanTypePtr)); /* 398 */
- Tcl_ChannelTypeVersion (*tcl_ChannelVersion) _ANSI_ARGS_((Tcl_ChannelType * chanTypePtr)); /* 399 */
- Tcl_DriverBlockModeProc * (*tcl_ChannelBlockModeProc) _ANSI_ARGS_((Tcl_ChannelType * chanTypePtr)); /* 400 */
- Tcl_DriverCloseProc * (*tcl_ChannelCloseProc) _ANSI_ARGS_((Tcl_ChannelType * chanTypePtr)); /* 401 */
- Tcl_DriverClose2Proc * (*tcl_ChannelClose2Proc) _ANSI_ARGS_((Tcl_ChannelType * chanTypePtr)); /* 402 */
- Tcl_DriverInputProc * (*tcl_ChannelInputProc) _ANSI_ARGS_((Tcl_ChannelType * chanTypePtr)); /* 403 */
- Tcl_DriverOutputProc * (*tcl_ChannelOutputProc) _ANSI_ARGS_((Tcl_ChannelType * chanTypePtr)); /* 404 */
- Tcl_DriverSeekProc * (*tcl_ChannelSeekProc) _ANSI_ARGS_((Tcl_ChannelType * chanTypePtr)); /* 405 */
- Tcl_DriverSetOptionProc * (*tcl_ChannelSetOptionProc) _ANSI_ARGS_((Tcl_ChannelType * chanTypePtr)); /* 406 */
- Tcl_DriverGetOptionProc * (*tcl_ChannelGetOptionProc) _ANSI_ARGS_((Tcl_ChannelType * chanTypePtr)); /* 407 */
- Tcl_DriverWatchProc * (*tcl_ChannelWatchProc) _ANSI_ARGS_((Tcl_ChannelType * chanTypePtr)); /* 408 */
- Tcl_DriverGetHandleProc * (*tcl_ChannelGetHandleProc) _ANSI_ARGS_((Tcl_ChannelType * chanTypePtr)); /* 409 */
- Tcl_DriverFlushProc * (*tcl_ChannelFlushProc) _ANSI_ARGS_((Tcl_ChannelType * chanTypePtr)); /* 410 */
- Tcl_DriverHandlerProc * (*tcl_ChannelHandlerProc) _ANSI_ARGS_((Tcl_ChannelType * chanTypePtr)); /* 411 */
- int (*tcl_JoinThread) _ANSI_ARGS_((Tcl_ThreadId threadId, int* result)); /* 412 */
- int (*tcl_IsChannelShared) _ANSI_ARGS_((Tcl_Channel channel)); /* 413 */
- int (*tcl_IsChannelRegistered) _ANSI_ARGS_((Tcl_Interp* interp, Tcl_Channel channel)); /* 414 */
- void (*tcl_CutChannel) _ANSI_ARGS_((Tcl_Channel channel)); /* 415 */
- void (*tcl_SpliceChannel) _ANSI_ARGS_((Tcl_Channel channel)); /* 416 */
- void (*tcl_ClearChannelHandlers) _ANSI_ARGS_((Tcl_Channel channel)); /* 417 */
- int (*tcl_IsChannelExisting) _ANSI_ARGS_((CONST char* channelName)); /* 418 */
- int (*tcl_UniCharNcasecmp) _ANSI_ARGS_((CONST Tcl_UniChar * cs, CONST Tcl_UniChar * ct, unsigned long n)); /* 419 */
- int (*tcl_UniCharCaseMatch) _ANSI_ARGS_((CONST Tcl_UniChar * ustr, CONST Tcl_UniChar * pattern, int nocase)); /* 420 */
- Tcl_HashEntry * (*tcl_FindHashEntry) _ANSI_ARGS_((Tcl_HashTable * tablePtr, CONST char * key)); /* 421 */
- Tcl_HashEntry * (*tcl_CreateHashEntry) _ANSI_ARGS_((Tcl_HashTable * tablePtr, CONST char * key, int * newPtr)); /* 422 */
- void (*tcl_InitCustomHashTable) _ANSI_ARGS_((Tcl_HashTable * tablePtr, int keyType, Tcl_HashKeyType * typePtr)); /* 423 */
- void (*tcl_InitObjHashTable) _ANSI_ARGS_((Tcl_HashTable * tablePtr)); /* 424 */
- ClientData (*tcl_CommandTraceInfo) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * varName, int flags, Tcl_CommandTraceProc * procPtr, ClientData prevClientData)); /* 425 */
- int (*tcl_TraceCommand) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * varName, int flags, Tcl_CommandTraceProc * proc, ClientData clientData)); /* 426 */
- void (*tcl_UntraceCommand) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * varName, int flags, Tcl_CommandTraceProc * proc, ClientData clientData)); /* 427 */
- char * (*tcl_AttemptAlloc) _ANSI_ARGS_((unsigned int size)); /* 428 */
- char * (*tcl_AttemptDbCkalloc) _ANSI_ARGS_((unsigned int size, CONST char * file, int line)); /* 429 */
- char * (*tcl_AttemptRealloc) _ANSI_ARGS_((char * ptr, unsigned int size)); /* 430 */
- char * (*tcl_AttemptDbCkrealloc) _ANSI_ARGS_((char * ptr, unsigned int size, CONST char * file, int line)); /* 431 */
- int (*tcl_AttemptSetObjLength) _ANSI_ARGS_((Tcl_Obj * objPtr, int length)); /* 432 */
- Tcl_ThreadId (*tcl_GetChannelThread) _ANSI_ARGS_((Tcl_Channel channel)); /* 433 */
- Tcl_UniChar * (*tcl_GetUnicodeFromObj) _ANSI_ARGS_((Tcl_Obj * objPtr, int * lengthPtr)); /* 434 */
- int (*tcl_GetMathFuncInfo) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, int * numArgsPtr, Tcl_ValueType ** argTypesPtr, Tcl_MathProc ** procPtr, ClientData * clientDataPtr)); /* 435 */
- Tcl_Obj * (*tcl_ListMathFuncs) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * pattern)); /* 436 */
- Tcl_Obj * (*tcl_SubstObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, int flags)); /* 437 */
- int (*tcl_DetachChannel) _ANSI_ARGS_((Tcl_Interp* interp, Tcl_Channel channel)); /* 438 */
- int (*tcl_IsStandardChannel) _ANSI_ARGS_((Tcl_Channel channel)); /* 439 */
- int (*tcl_FSCopyFile) _ANSI_ARGS_((Tcl_Obj * srcPathPtr, Tcl_Obj * destPathPtr)); /* 440 */
- int (*tcl_FSCopyDirectory) _ANSI_ARGS_((Tcl_Obj * srcPathPtr, Tcl_Obj * destPathPtr, Tcl_Obj ** errorPtr)); /* 441 */
- int (*tcl_FSCreateDirectory) _ANSI_ARGS_((Tcl_Obj * pathPtr)); /* 442 */
- int (*tcl_FSDeleteFile) _ANSI_ARGS_((Tcl_Obj * pathPtr)); /* 443 */
- int (*tcl_FSLoadFile) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * pathPtr, CONST char * sym1, CONST char * sym2, Tcl_PackageInitProc ** proc1Ptr, Tcl_PackageInitProc ** proc2Ptr, Tcl_LoadHandle * handlePtr, Tcl_FSUnloadFileProc ** unloadProcPtr)); /* 444 */
- int (*tcl_FSMatchInDirectory) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * result, Tcl_Obj * pathPtr, CONST char * pattern, Tcl_GlobTypeData * types)); /* 445 */
- Tcl_Obj * (*tcl_FSLink) _ANSI_ARGS_((Tcl_Obj * pathPtr, Tcl_Obj * toPtr, int linkAction)); /* 446 */
- int (*tcl_FSRemoveDirectory) _ANSI_ARGS_((Tcl_Obj * pathPtr, int recursive, Tcl_Obj ** errorPtr)); /* 447 */
- int (*tcl_FSRenameFile) _ANSI_ARGS_((Tcl_Obj * srcPathPtr, Tcl_Obj * destPathPtr)); /* 448 */
- int (*tcl_FSLstat) _ANSI_ARGS_((Tcl_Obj * pathPtr, Tcl_StatBuf * buf)); /* 449 */
- int (*tcl_FSUtime) _ANSI_ARGS_((Tcl_Obj * pathPtr, struct utimbuf * tval)); /* 450 */
- int (*tcl_FSFileAttrsGet) _ANSI_ARGS_((Tcl_Interp * interp, int index, Tcl_Obj * pathPtr, Tcl_Obj ** objPtrRef)); /* 451 */
- int (*tcl_FSFileAttrsSet) _ANSI_ARGS_((Tcl_Interp * interp, int index, Tcl_Obj * pathPtr, Tcl_Obj * objPtr)); /* 452 */
- CONST char ** (*tcl_FSFileAttrStrings) _ANSI_ARGS_((Tcl_Obj * pathPtr, Tcl_Obj ** objPtrRef)); /* 453 */
- int (*tcl_FSStat) _ANSI_ARGS_((Tcl_Obj * pathPtr, Tcl_StatBuf * buf)); /* 454 */
- int (*tcl_FSAccess) _ANSI_ARGS_((Tcl_Obj * pathPtr, int mode)); /* 455 */
- Tcl_Channel (*tcl_FSOpenFileChannel) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * pathPtr, CONST char * modeString, int permissions)); /* 456 */
- Tcl_Obj* (*tcl_FSGetCwd) _ANSI_ARGS_((Tcl_Interp * interp)); /* 457 */
- int (*tcl_FSChdir) _ANSI_ARGS_((Tcl_Obj * pathPtr)); /* 458 */
- int (*tcl_FSConvertToPathType) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * pathPtr)); /* 459 */
- Tcl_Obj* (*tcl_FSJoinPath) _ANSI_ARGS_((Tcl_Obj * listObj, int elements)); /* 460 */
- Tcl_Obj* (*tcl_FSSplitPath) _ANSI_ARGS_((Tcl_Obj* pathPtr, int * lenPtr)); /* 461 */
- int (*tcl_FSEqualPaths) _ANSI_ARGS_((Tcl_Obj* firstPtr, Tcl_Obj* secondPtr)); /* 462 */
- Tcl_Obj* (*tcl_FSGetNormalizedPath) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj* pathObjPtr)); /* 463 */
- Tcl_Obj* (*tcl_FSJoinToPath) _ANSI_ARGS_((Tcl_Obj * basePtr, int objc, Tcl_Obj *CONST objv[])); /* 464 */
- ClientData (*tcl_FSGetInternalRep) _ANSI_ARGS_((Tcl_Obj* pathObjPtr, Tcl_Filesystem * fsPtr)); /* 465 */
- Tcl_Obj* (*tcl_FSGetTranslatedPath) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj* pathPtr)); /* 466 */
- int (*tcl_FSEvalFile) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * fileName)); /* 467 */
- Tcl_Obj* (*tcl_FSNewNativePath) _ANSI_ARGS_((Tcl_Filesystem* fromFilesystem, ClientData clientData)); /* 468 */
- CONST char* (*tcl_FSGetNativePath) _ANSI_ARGS_((Tcl_Obj* pathObjPtr)); /* 469 */
- Tcl_Obj* (*tcl_FSFileSystemInfo) _ANSI_ARGS_((Tcl_Obj* pathObjPtr)); /* 470 */
- Tcl_Obj* (*tcl_FSPathSeparator) _ANSI_ARGS_((Tcl_Obj* pathObjPtr)); /* 471 */
- Tcl_Obj* (*tcl_FSListVolumes) _ANSI_ARGS_((void)); /* 472 */
- int (*tcl_FSRegister) _ANSI_ARGS_((ClientData clientData, Tcl_Filesystem * fsPtr)); /* 473 */
- int (*tcl_FSUnregister) _ANSI_ARGS_((Tcl_Filesystem * fsPtr)); /* 474 */
- ClientData (*tcl_FSData) _ANSI_ARGS_((Tcl_Filesystem * fsPtr)); /* 475 */
- CONST char* (*tcl_FSGetTranslatedStringPath) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj* pathPtr)); /* 476 */
- Tcl_Filesystem* (*tcl_FSGetFileSystemForPath) _ANSI_ARGS_((Tcl_Obj* pathObjPtr)); /* 477 */
- Tcl_PathType (*tcl_FSGetPathType) _ANSI_ARGS_((Tcl_Obj * pathObjPtr)); /* 478 */
- int (*tcl_OutputBuffered) _ANSI_ARGS_((Tcl_Channel chan)); /* 479 */
- void (*tcl_FSMountsChanged) _ANSI_ARGS_((Tcl_Filesystem * fsPtr)); /* 480 */
- int (*tcl_EvalTokensStandard) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Token * tokenPtr, int count)); /* 481 */
- void (*tcl_GetTime) _ANSI_ARGS_((Tcl_Time* timeBuf)); /* 482 */
- Tcl_Trace (*tcl_CreateObjTrace) _ANSI_ARGS_((Tcl_Interp* interp, int level, int flags, Tcl_CmdObjTraceProc* objProc, ClientData clientData, Tcl_CmdObjTraceDeleteProc* delProc)); /* 483 */
- int (*tcl_GetCommandInfoFromToken) _ANSI_ARGS_((Tcl_Command token, Tcl_CmdInfo* infoPtr)); /* 484 */
- int (*tcl_SetCommandInfoFromToken) _ANSI_ARGS_((Tcl_Command token, CONST Tcl_CmdInfo* infoPtr)); /* 485 */
- Tcl_Obj * (*tcl_DbNewWideIntObj) _ANSI_ARGS_((Tcl_WideInt wideValue, CONST char * file, int line)); /* 486 */
- int (*tcl_GetWideIntFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, Tcl_WideInt * widePtr)); /* 487 */
- Tcl_Obj * (*tcl_NewWideIntObj) _ANSI_ARGS_((Tcl_WideInt wideValue)); /* 488 */
- void (*tcl_SetWideIntObj) _ANSI_ARGS_((Tcl_Obj * objPtr, Tcl_WideInt wideValue)); /* 489 */
- Tcl_StatBuf * (*tcl_AllocStatBuf) _ANSI_ARGS_((void)); /* 490 */
- Tcl_WideInt (*tcl_Seek) _ANSI_ARGS_((Tcl_Channel chan, Tcl_WideInt offset, int mode)); /* 491 */
- Tcl_WideInt (*tcl_Tell) _ANSI_ARGS_((Tcl_Channel chan)); /* 492 */
- Tcl_DriverWideSeekProc * (*tcl_ChannelWideSeekProc) _ANSI_ARGS_((Tcl_ChannelType * chanTypePtr)); /* 493 */
- void *reserved494;
- void *reserved495;
- void *reserved496;
- void *reserved497;
- void *reserved498;
- void *reserved499;
- void *reserved500;
- void *reserved501;
- void *reserved502;
- void *reserved503;
- void *reserved504;
- void *reserved505;
- void *reserved506;
- void *reserved507;
- void *reserved508;
- void *reserved509;
- void *reserved510;
- void *reserved511;
- void *reserved512;
- void *reserved513;
- void *reserved514;
- void *reserved515;
- void *reserved516;
- void *reserved517;
- void *reserved518;
- void *reserved519;
- void *reserved520;
- void *reserved521;
- void *reserved522;
- void *reserved523;
- void *reserved524;
- void *reserved525;
- void *reserved526;
- void *reserved527;
- void *reserved528;
- void *reserved529;
- void *reserved530;
- void *reserved531;
- void *reserved532;
- void *reserved533;
- void *reserved534;
- void *reserved535;
- void *reserved536;
- void *reserved537;
- void *reserved538;
- void *reserved539;
- void *reserved540;
- void *reserved541;
- void *reserved542;
- void *reserved543;
- void *reserved544;
- void *reserved545;
- void *reserved546;
- void *reserved547;
- void *reserved548;
- void *reserved549;
- void *reserved550;
- void *reserved551;
- void *reserved552;
- void *reserved553;
- Tcl_DriverThreadActionProc * (*tcl_ChannelThreadActionProc) _ANSI_ARGS_((Tcl_ChannelType * chanTypePtr)); /* 554 */
- void *reserved555;
- void *reserved556;
- void *reserved557;
- void *reserved558;
- void *reserved559;
- void *reserved560;
- void *reserved561;
- void *reserved562;
- void *reserved563;
- void *reserved564;
- void *reserved565;
- void *reserved566;
- void *reserved567;
- void *reserved568;
- void *reserved569;
- void *reserved570;
- void *reserved571;
- void *reserved572;
- int (*tcl_PkgRequireProc) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, int objc, Tcl_Obj *CONST objv[], ClientData * clientDataPtr)); /* 573 */
+#ifdef __WIN32__ /* WIN */
+ VOID *reserved167;
+#endif /* WIN */
+#ifdef MAC_OSX_TCL /* MACOSX */
+ int (*tcl_GetOpenFile) (Tcl_Interp *interp, CONST char *chanID, int forWriting, int checkUsage, ClientData *filePtr); /* 167 */
+#endif /* MACOSX */
+ Tcl_PathType (*tcl_GetPathType) (CONST char *path); /* 168 */
+ int (*tcl_Gets) (Tcl_Channel chan, Tcl_DString *dsPtr); /* 169 */
+ int (*tcl_GetsObj) (Tcl_Channel chan, Tcl_Obj *objPtr); /* 170 */
+ int (*tcl_GetServiceMode) (void); /* 171 */
+ Tcl_Interp * (*tcl_GetSlave) (Tcl_Interp *interp, CONST char *slaveName); /* 172 */
+ Tcl_Channel (*tcl_GetStdChannel) (int type); /* 173 */
+ CONST84_RETURN char * (*tcl_GetStringResult) (Tcl_Interp *interp); /* 174 */
+ CONST84_RETURN char * (*tcl_GetVar) (Tcl_Interp *interp, CONST char *varName, int flags); /* 175 */
+ CONST84_RETURN char * (*tcl_GetVar2) (Tcl_Interp *interp, CONST char *part1, CONST char *part2, int flags); /* 176 */
+ int (*tcl_GlobalEval) (Tcl_Interp *interp, CONST char *command); /* 177 */
+ int (*tcl_GlobalEvalObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 178 */
+ int (*tcl_HideCommand) (Tcl_Interp *interp, CONST char *cmdName, CONST char *hiddenCmdToken); /* 179 */
+ int (*tcl_Init) (Tcl_Interp *interp); /* 180 */
+ void (*tcl_InitHashTable) (Tcl_HashTable *tablePtr, int keyType); /* 181 */
+ int (*tcl_InputBlocked) (Tcl_Channel chan); /* 182 */
+ int (*tcl_InputBuffered) (Tcl_Channel chan); /* 183 */
+ int (*tcl_InterpDeleted) (Tcl_Interp *interp); /* 184 */
+ int (*tcl_IsSafe) (Tcl_Interp *interp); /* 185 */
+ char * (*tcl_JoinPath) (int argc, CONST84 char *CONST *argv, Tcl_DString *resultPtr); /* 186 */
+ int (*tcl_LinkVar) (Tcl_Interp *interp, CONST char *varName, char *addr, int type); /* 187 */
+ VOID *reserved188;
+ Tcl_Channel (*tcl_MakeFileChannel) (ClientData handle, int mode); /* 189 */
+ int (*tcl_MakeSafe) (Tcl_Interp *interp); /* 190 */
+ Tcl_Channel (*tcl_MakeTcpClientChannel) (ClientData tcpSocket); /* 191 */
+ char * (*tcl_Merge) (int argc, CONST84 char *CONST *argv); /* 192 */
+ Tcl_HashEntry * (*tcl_NextHashEntry) (Tcl_HashSearch *searchPtr); /* 193 */
+ void (*tcl_NotifyChannel) (Tcl_Channel channel, int mask); /* 194 */
+ Tcl_Obj * (*tcl_ObjGetVar2) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags); /* 195 */
+ Tcl_Obj * (*tcl_ObjSetVar2) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags); /* 196 */
+ Tcl_Channel (*tcl_OpenCommandChannel) (Tcl_Interp *interp, int argc, CONST84 char **argv, int flags); /* 197 */
+ Tcl_Channel (*tcl_OpenFileChannel) (Tcl_Interp *interp, CONST char *fileName, CONST char *modeString, int permissions); /* 198 */
+ Tcl_Channel (*tcl_OpenTcpClient) (Tcl_Interp *interp, int port, CONST char *address, CONST char *myaddr, int myport, int async); /* 199 */
+ Tcl_Channel (*tcl_OpenTcpServer) (Tcl_Interp *interp, int port, CONST char *host, Tcl_TcpAcceptProc *acceptProc, ClientData callbackData); /* 200 */
+ void (*tcl_Preserve) (ClientData data); /* 201 */
+ void (*tcl_PrintDouble) (Tcl_Interp *interp, double value, char *dst); /* 202 */
+ int (*tcl_PutEnv) (CONST char *assignment); /* 203 */
+ CONST84_RETURN char * (*tcl_PosixError) (Tcl_Interp *interp); /* 204 */
+ void (*tcl_QueueEvent) (Tcl_Event *evPtr, Tcl_QueuePosition position); /* 205 */
+ int (*tcl_Read) (Tcl_Channel chan, char *bufPtr, int toRead); /* 206 */
+ void (*tcl_ReapDetachedProcs) (void); /* 207 */
+ int (*tcl_RecordAndEval) (Tcl_Interp *interp, CONST char *cmd, int flags); /* 208 */
+ int (*tcl_RecordAndEvalObj) (Tcl_Interp *interp, Tcl_Obj *cmdPtr, int flags); /* 209 */
+ void (*tcl_RegisterChannel) (Tcl_Interp *interp, Tcl_Channel chan); /* 210 */
+ void (*tcl_RegisterObjType) (Tcl_ObjType *typePtr); /* 211 */
+ Tcl_RegExp (*tcl_RegExpCompile) (Tcl_Interp *interp, CONST char *pattern); /* 212 */
+ int (*tcl_RegExpExec) (Tcl_Interp *interp, Tcl_RegExp regexp, CONST char *text, CONST char *start); /* 213 */
+ int (*tcl_RegExpMatch) (Tcl_Interp *interp, CONST char *text, CONST char *pattern); /* 214 */
+ void (*tcl_RegExpRange) (Tcl_RegExp regexp, int index, CONST84 char **startPtr, CONST84 char **endPtr); /* 215 */
+ void (*tcl_Release) (ClientData clientData); /* 216 */
+ void (*tcl_ResetResult) (Tcl_Interp *interp); /* 217 */
+ int (*tcl_ScanElement) (CONST char *src, int *flagPtr); /* 218 */
+ int (*tcl_ScanCountedElement) (CONST char *src, int length, int *flagPtr); /* 219 */
+ int (*tcl_SeekOld) (Tcl_Channel chan, int offset, int mode); /* 220 */
+ int (*tcl_ServiceAll) (void); /* 221 */
+ int (*tcl_ServiceEvent) (int flags); /* 222 */
+ void (*tcl_SetAssocData) (Tcl_Interp *interp, CONST char *name, Tcl_InterpDeleteProc *proc, ClientData clientData); /* 223 */
+ void (*tcl_SetChannelBufferSize) (Tcl_Channel chan, int sz); /* 224 */
+ int (*tcl_SetChannelOption) (Tcl_Interp *interp, Tcl_Channel chan, CONST char *optionName, CONST char *newValue); /* 225 */
+ int (*tcl_SetCommandInfo) (Tcl_Interp *interp, CONST char *cmdName, CONST Tcl_CmdInfo *infoPtr); /* 226 */
+ void (*tcl_SetErrno) (int err); /* 227 */
+ void (*tcl_SetErrorCode) (Tcl_Interp *interp, ...); /* 228 */
+ void (*tcl_SetMaxBlockTime) (Tcl_Time *timePtr); /* 229 */
+ void (*tcl_SetPanicProc) (Tcl_PanicProc *panicProc); /* 230 */
+ int (*tcl_SetRecursionLimit) (Tcl_Interp *interp, int depth); /* 231 */
+ void (*tcl_SetResult) (Tcl_Interp *interp, char *result, Tcl_FreeProc *freeProc); /* 232 */
+ int (*tcl_SetServiceMode) (int mode); /* 233 */
+ void (*tcl_SetObjErrorCode) (Tcl_Interp *interp, Tcl_Obj *errorObjPtr); /* 234 */
+ void (*tcl_SetObjResult) (Tcl_Interp *interp, Tcl_Obj *resultObjPtr); /* 235 */
+ void (*tcl_SetStdChannel) (Tcl_Channel channel, int type); /* 236 */
+ CONST84_RETURN char * (*tcl_SetVar) (Tcl_Interp *interp, CONST char *varName, CONST char *newValue, int flags); /* 237 */
+ CONST84_RETURN char * (*tcl_SetVar2) (Tcl_Interp *interp, CONST char *part1, CONST char *part2, CONST char *newValue, int flags); /* 238 */
+ CONST84_RETURN char * (*tcl_SignalId) (int sig); /* 239 */
+ CONST84_RETURN char * (*tcl_SignalMsg) (int sig); /* 240 */
+ void (*tcl_SourceRCFile) (Tcl_Interp *interp); /* 241 */
+ int (*tcl_SplitList) (Tcl_Interp *interp, CONST char *listStr, int *argcPtr, CONST84 char ***argvPtr); /* 242 */
+ void (*tcl_SplitPath) (CONST char *path, int *argcPtr, CONST84 char ***argvPtr); /* 243 */
+ void (*tcl_StaticPackage) (Tcl_Interp *interp, CONST char *pkgName, Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc); /* 244 */
+ int (*tcl_StringMatch) (CONST char *str, CONST char *pattern); /* 245 */
+ int (*tcl_TellOld) (Tcl_Channel chan); /* 246 */
+ int (*tcl_TraceVar) (Tcl_Interp *interp, CONST char *varName, int flags, Tcl_VarTraceProc *proc, ClientData clientData); /* 247 */
+ int (*tcl_TraceVar2) (Tcl_Interp *interp, CONST char *part1, CONST char *part2, int flags, Tcl_VarTraceProc *proc, ClientData clientData); /* 248 */
+ char * (*tcl_TranslateFileName) (Tcl_Interp *interp, CONST char *name, Tcl_DString *bufferPtr); /* 249 */
+ int (*tcl_Ungets) (Tcl_Channel chan, CONST char *str, int len, int atHead); /* 250 */
+ void (*tcl_UnlinkVar) (Tcl_Interp *interp, CONST char *varName); /* 251 */
+ int (*tcl_UnregisterChannel) (Tcl_Interp *interp, Tcl_Channel chan); /* 252 */
+ int (*tcl_UnsetVar) (Tcl_Interp *interp, CONST char *varName, int flags); /* 253 */
+ int (*tcl_UnsetVar2) (Tcl_Interp *interp, CONST char *part1, CONST char *part2, int flags); /* 254 */
+ void (*tcl_UntraceVar) (Tcl_Interp *interp, CONST char *varName, int flags, Tcl_VarTraceProc *proc, ClientData clientData); /* 255 */
+ void (*tcl_UntraceVar2) (Tcl_Interp *interp, CONST char *part1, CONST char *part2, int flags, Tcl_VarTraceProc *proc, ClientData clientData); /* 256 */
+ void (*tcl_UpdateLinkedVar) (Tcl_Interp *interp, CONST char *varName); /* 257 */
+ int (*tcl_UpVar) (Tcl_Interp *interp, CONST char *frameName, CONST char *varName, CONST char *localName, int flags); /* 258 */
+ int (*tcl_UpVar2) (Tcl_Interp *interp, CONST char *frameName, CONST char *part1, CONST char *part2, CONST char *localName, int flags); /* 259 */
+ int (*tcl_VarEval) (Tcl_Interp *interp, ...); /* 260 */
+ ClientData (*tcl_VarTraceInfo) (Tcl_Interp *interp, CONST char *varName, int flags, Tcl_VarTraceProc *procPtr, ClientData prevClientData); /* 261 */
+ ClientData (*tcl_VarTraceInfo2) (Tcl_Interp *interp, CONST char *part1, CONST char *part2, int flags, Tcl_VarTraceProc *procPtr, ClientData prevClientData); /* 262 */
+ int (*tcl_Write) (Tcl_Channel chan, CONST char *s, int slen); /* 263 */
+ void (*tcl_WrongNumArgs) (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], CONST char *message); /* 264 */
+ int (*tcl_DumpActiveMemory) (CONST char *fileName); /* 265 */
+ void (*tcl_ValidateAllMemory) (CONST char *file, int line); /* 266 */
+ void (*tcl_AppendResultVA) (Tcl_Interp *interp, va_list argList); /* 267 */
+ void (*tcl_AppendStringsToObjVA) (Tcl_Obj *objPtr, va_list argList); /* 268 */
+ char * (*tcl_HashStats) (Tcl_HashTable *tablePtr); /* 269 */
+ CONST84_RETURN char * (*tcl_ParseVar) (Tcl_Interp *interp, CONST char *start, CONST84 char **termPtr); /* 270 */
+ CONST84_RETURN char * (*tcl_PkgPresent) (Tcl_Interp *interp, CONST char *name, CONST char *version, int exact); /* 271 */
+ CONST84_RETURN char * (*tcl_PkgPresentEx) (Tcl_Interp *interp, CONST char *name, CONST char *version, int exact, ClientData *clientDataPtr); /* 272 */
+ int (*tcl_PkgProvide) (Tcl_Interp *interp, CONST char *name, CONST char *version); /* 273 */
+ CONST84_RETURN char * (*tcl_PkgRequire) (Tcl_Interp *interp, CONST char *name, CONST char *version, int exact); /* 274 */
+ void (*tcl_SetErrorCodeVA) (Tcl_Interp *interp, va_list argList); /* 275 */
+ int (*tcl_VarEvalVA) (Tcl_Interp *interp, va_list argList); /* 276 */
+ Tcl_Pid (*tcl_WaitPid) (Tcl_Pid pid, int *statPtr, int options); /* 277 */
+ void (*tcl_PanicVA) (CONST char *format, va_list argList); /* 278 */
+ void (*tcl_GetVersion) (int *major, int *minor, int *patchLevel, int *type); /* 279 */
+ void (*tcl_InitMemory) (Tcl_Interp *interp); /* 280 */
+ Tcl_Channel (*tcl_StackChannel) (Tcl_Interp *interp, Tcl_ChannelType *typePtr, ClientData instanceData, int mask, Tcl_Channel prevChan); /* 281 */
+ int (*tcl_UnstackChannel) (Tcl_Interp *interp, Tcl_Channel chan); /* 282 */
+ Tcl_Channel (*tcl_GetStackedChannel) (Tcl_Channel chan); /* 283 */
+ void (*tcl_SetMainLoop) (Tcl_MainLoopProc *proc); /* 284 */
+ VOID *reserved285;
+ void (*tcl_AppendObjToObj) (Tcl_Obj *objPtr, Tcl_Obj *appendObjPtr); /* 286 */
+ Tcl_Encoding (*tcl_CreateEncoding) (CONST Tcl_EncodingType *typePtr); /* 287 */
+ void (*tcl_CreateThreadExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 288 */
+ void (*tcl_DeleteThreadExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 289 */
+ void (*tcl_DiscardResult) (Tcl_SavedResult *statePtr); /* 290 */
+ int (*tcl_EvalEx) (Tcl_Interp *interp, CONST char *script, int numBytes, int flags); /* 291 */
+ int (*tcl_EvalObjv) (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int flags); /* 292 */
+ int (*tcl_EvalObjEx) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 293 */
+ void (*tcl_ExitThread) (int status); /* 294 */
+ int (*tcl_ExternalToUtf) (Tcl_Interp *interp, Tcl_Encoding encoding, CONST char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); /* 295 */
+ char * (*tcl_ExternalToUtfDString) (Tcl_Encoding encoding, CONST char *src, int srcLen, Tcl_DString *dsPtr); /* 296 */
+ void (*tcl_FinalizeThread) (void); /* 297 */
+ void (*tcl_FinalizeNotifier) (ClientData clientData); /* 298 */
+ void (*tcl_FreeEncoding) (Tcl_Encoding encoding); /* 299 */
+ Tcl_ThreadId (*tcl_GetCurrentThread) (void); /* 300 */
+ Tcl_Encoding (*tcl_GetEncoding) (Tcl_Interp *interp, CONST char *name); /* 301 */
+ CONST84_RETURN char * (*tcl_GetEncodingName) (Tcl_Encoding encoding); /* 302 */
+ void (*tcl_GetEncodingNames) (Tcl_Interp *interp); /* 303 */
+ int (*tcl_GetIndexFromObjStruct) (Tcl_Interp *interp, Tcl_Obj *objPtr, CONST VOID *tablePtr, int offset, CONST char *msg, int flags, int *indexPtr); /* 304 */
+ VOID * (*tcl_GetThreadData) (Tcl_ThreadDataKey *keyPtr, int size); /* 305 */
+ Tcl_Obj * (*tcl_GetVar2Ex) (Tcl_Interp *interp, CONST char *part1, CONST char *part2, int flags); /* 306 */
+ ClientData (*tcl_InitNotifier) (void); /* 307 */
+ void (*tcl_MutexLock) (Tcl_Mutex *mutexPtr); /* 308 */
+ void (*tcl_MutexUnlock) (Tcl_Mutex *mutexPtr); /* 309 */
+ void (*tcl_ConditionNotify) (Tcl_Condition *condPtr); /* 310 */
+ void (*tcl_ConditionWait) (Tcl_Condition *condPtr, Tcl_Mutex *mutexPtr, Tcl_Time *timePtr); /* 311 */
+ int (*tcl_NumUtfChars) (CONST char *src, int length); /* 312 */
+ int (*tcl_ReadChars) (Tcl_Channel channel, Tcl_Obj *objPtr, int charsToRead, int appendFlag); /* 313 */
+ void (*tcl_RestoreResult) (Tcl_Interp *interp, Tcl_SavedResult *statePtr); /* 314 */
+ void (*tcl_SaveResult) (Tcl_Interp *interp, Tcl_SavedResult *statePtr); /* 315 */
+ int (*tcl_SetSystemEncoding) (Tcl_Interp *interp, CONST char *name); /* 316 */
+ Tcl_Obj * (*tcl_SetVar2Ex) (Tcl_Interp *interp, CONST char *part1, CONST char *part2, Tcl_Obj *newValuePtr, int flags); /* 317 */
+ void (*tcl_ThreadAlert) (Tcl_ThreadId threadId); /* 318 */
+ void (*tcl_ThreadQueueEvent) (Tcl_ThreadId threadId, Tcl_Event *evPtr, Tcl_QueuePosition position); /* 319 */
+ Tcl_UniChar (*tcl_UniCharAtIndex) (CONST char *src, int index); /* 320 */
+ Tcl_UniChar (*tcl_UniCharToLower) (int ch); /* 321 */
+ Tcl_UniChar (*tcl_UniCharToTitle) (int ch); /* 322 */
+ Tcl_UniChar (*tcl_UniCharToUpper) (int ch); /* 323 */
+ int (*tcl_UniCharToUtf) (int ch, char *buf); /* 324 */
+ CONST84_RETURN char * (*tcl_UtfAtIndex) (CONST char *src, int index); /* 325 */
+ int (*tcl_UtfCharComplete) (CONST char *src, int length); /* 326 */
+ int (*tcl_UtfBackslash) (CONST char *src, int *readPtr, char *dst); /* 327 */
+ CONST84_RETURN char * (*tcl_UtfFindFirst) (CONST char *src, int ch); /* 328 */
+ CONST84_RETURN char * (*tcl_UtfFindLast) (CONST char *src, int ch); /* 329 */
+ CONST84_RETURN char * (*tcl_UtfNext) (CONST char *src); /* 330 */
+ CONST84_RETURN char * (*tcl_UtfPrev) (CONST char *src, CONST char *start); /* 331 */
+ int (*tcl_UtfToExternal) (Tcl_Interp *interp, Tcl_Encoding encoding, CONST char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); /* 332 */
+ char * (*tcl_UtfToExternalDString) (Tcl_Encoding encoding, CONST char *src, int srcLen, Tcl_DString *dsPtr); /* 333 */
+ int (*tcl_UtfToLower) (char *src); /* 334 */
+ int (*tcl_UtfToTitle) (char *src); /* 335 */
+ int (*tcl_UtfToUniChar) (CONST char *src, Tcl_UniChar *chPtr); /* 336 */
+ int (*tcl_UtfToUpper) (char *src); /* 337 */
+ int (*tcl_WriteChars) (Tcl_Channel chan, CONST char *src, int srcLen); /* 338 */
+ int (*tcl_WriteObj) (Tcl_Channel chan, Tcl_Obj *objPtr); /* 339 */
+ char * (*tcl_GetString) (Tcl_Obj *objPtr); /* 340 */
+ CONST84_RETURN char * (*tcl_GetDefaultEncodingDir) (void); /* 341 */
+ void (*tcl_SetDefaultEncodingDir) (CONST char *path); /* 342 */
+ void (*tcl_AlertNotifier) (ClientData clientData); /* 343 */
+ void (*tcl_ServiceModeHook) (int mode); /* 344 */
+ int (*tcl_UniCharIsAlnum) (int ch); /* 345 */
+ int (*tcl_UniCharIsAlpha) (int ch); /* 346 */
+ int (*tcl_UniCharIsDigit) (int ch); /* 347 */
+ int (*tcl_UniCharIsLower) (int ch); /* 348 */
+ int (*tcl_UniCharIsSpace) (int ch); /* 349 */
+ int (*tcl_UniCharIsUpper) (int ch); /* 350 */
+ int (*tcl_UniCharIsWordChar) (int ch); /* 351 */
+ int (*tcl_UniCharLen) (CONST Tcl_UniChar *uniStr); /* 352 */
+ int (*tcl_UniCharNcmp) (CONST Tcl_UniChar *ucs, CONST Tcl_UniChar *uct, unsigned long numChars); /* 353 */
+ char * (*tcl_UniCharToUtfDString) (CONST Tcl_UniChar *uniStr, int uniLength, Tcl_DString *dsPtr); /* 354 */
+ Tcl_UniChar * (*tcl_UtfToUniCharDString) (CONST char *src, int length, Tcl_DString *dsPtr); /* 355 */
+ Tcl_RegExp (*tcl_GetRegExpFromObj) (Tcl_Interp *interp, Tcl_Obj *patObj, int flags); /* 356 */
+ Tcl_Obj * (*tcl_EvalTokens) (Tcl_Interp *interp, Tcl_Token *tokenPtr, int count); /* 357 */
+ void (*tcl_FreeParse) (Tcl_Parse *parsePtr); /* 358 */
+ void (*tcl_LogCommandInfo) (Tcl_Interp *interp, CONST char *script, CONST char *command, int length); /* 359 */
+ int (*tcl_ParseBraces) (Tcl_Interp *interp, CONST char *start, int numBytes, Tcl_Parse *parsePtr, int append, CONST84 char **termPtr); /* 360 */
+ int (*tcl_ParseCommand) (Tcl_Interp *interp, CONST char *start, int numBytes, int nested, Tcl_Parse *parsePtr); /* 361 */
+ int (*tcl_ParseExpr) (Tcl_Interp *interp, CONST char *start, int numBytes, Tcl_Parse *parsePtr); /* 362 */
+ int (*tcl_ParseQuotedString) (Tcl_Interp *interp, CONST char *start, int numBytes, Tcl_Parse *parsePtr, int append, CONST84 char **termPtr); /* 363 */
+ int (*tcl_ParseVarName) (Tcl_Interp *interp, CONST char *start, int numBytes, Tcl_Parse *parsePtr, int append); /* 364 */
+ char * (*tcl_GetCwd) (Tcl_Interp *interp, Tcl_DString *cwdPtr); /* 365 */
+ int (*tcl_Chdir) (CONST char *dirName); /* 366 */
+ int (*tcl_Access) (CONST char *path, int mode); /* 367 */
+ int (*tcl_Stat) (CONST char *path, struct stat *bufPtr); /* 368 */
+ int (*tcl_UtfNcmp) (CONST char *s1, CONST char *s2, unsigned long n); /* 369 */
+ int (*tcl_UtfNcasecmp) (CONST char *s1, CONST char *s2, unsigned long n); /* 370 */
+ int (*tcl_StringCaseMatch) (CONST char *str, CONST char *pattern, int nocase); /* 371 */
+ int (*tcl_UniCharIsControl) (int ch); /* 372 */
+ int (*tcl_UniCharIsGraph) (int ch); /* 373 */
+ int (*tcl_UniCharIsPrint) (int ch); /* 374 */
+ int (*tcl_UniCharIsPunct) (int ch); /* 375 */
+ int (*tcl_RegExpExecObj) (Tcl_Interp *interp, Tcl_RegExp regexp, Tcl_Obj *textObj, int offset, int nmatches, int flags); /* 376 */
+ void (*tcl_RegExpGetInfo) (Tcl_RegExp regexp, Tcl_RegExpInfo *infoPtr); /* 377 */
+ Tcl_Obj * (*tcl_NewUnicodeObj) (CONST Tcl_UniChar *unicode, int numChars); /* 378 */
+ void (*tcl_SetUnicodeObj) (Tcl_Obj *objPtr, CONST Tcl_UniChar *unicode, int numChars); /* 379 */
+ int (*tcl_GetCharLength) (Tcl_Obj *objPtr); /* 380 */
+ Tcl_UniChar (*tcl_GetUniChar) (Tcl_Obj *objPtr, int index); /* 381 */
+ Tcl_UniChar * (*tcl_GetUnicode) (Tcl_Obj *objPtr); /* 382 */
+ Tcl_Obj * (*tcl_GetRange) (Tcl_Obj *objPtr, int first, int last); /* 383 */
+ void (*tcl_AppendUnicodeToObj) (Tcl_Obj *objPtr, CONST Tcl_UniChar *unicode, int length); /* 384 */
+ int (*tcl_RegExpMatchObj) (Tcl_Interp *interp, Tcl_Obj *textObj, Tcl_Obj *patternObj); /* 385 */
+ void (*tcl_SetNotifier) (Tcl_NotifierProcs *notifierProcPtr); /* 386 */
+ Tcl_Mutex * (*tcl_GetAllocMutex) (void); /* 387 */
+ int (*tcl_GetChannelNames) (Tcl_Interp *interp); /* 388 */
+ int (*tcl_GetChannelNamesEx) (Tcl_Interp *interp, CONST char *pattern); /* 389 */
+ int (*tcl_ProcObjCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); /* 390 */
+ void (*tcl_ConditionFinalize) (Tcl_Condition *condPtr); /* 391 */
+ void (*tcl_MutexFinalize) (Tcl_Mutex *mutex); /* 392 */
+ int (*tcl_CreateThread) (Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc proc, ClientData clientData, int stackSize, int flags); /* 393 */
+ int (*tcl_ReadRaw) (Tcl_Channel chan, char *dst, int bytesToRead); /* 394 */
+ int (*tcl_WriteRaw) (Tcl_Channel chan, CONST char *src, int srcLen); /* 395 */
+ Tcl_Channel (*tcl_GetTopChannel) (Tcl_Channel chan); /* 396 */
+ int (*tcl_ChannelBuffered) (Tcl_Channel chan); /* 397 */
+ CONST84_RETURN char * (*tcl_ChannelName) (CONST Tcl_ChannelType *chanTypePtr); /* 398 */
+ Tcl_ChannelTypeVersion (*tcl_ChannelVersion) (CONST Tcl_ChannelType *chanTypePtr); /* 399 */
+ Tcl_DriverBlockModeProc * (*tcl_ChannelBlockModeProc) (CONST Tcl_ChannelType *chanTypePtr); /* 400 */
+ Tcl_DriverCloseProc * (*tcl_ChannelCloseProc) (CONST Tcl_ChannelType *chanTypePtr); /* 401 */
+ Tcl_DriverClose2Proc * (*tcl_ChannelClose2Proc) (CONST Tcl_ChannelType *chanTypePtr); /* 402 */
+ Tcl_DriverInputProc * (*tcl_ChannelInputProc) (CONST Tcl_ChannelType *chanTypePtr); /* 403 */
+ Tcl_DriverOutputProc * (*tcl_ChannelOutputProc) (CONST Tcl_ChannelType *chanTypePtr); /* 404 */
+ Tcl_DriverSeekProc * (*tcl_ChannelSeekProc) (CONST Tcl_ChannelType *chanTypePtr); /* 405 */
+ Tcl_DriverSetOptionProc * (*tcl_ChannelSetOptionProc) (CONST Tcl_ChannelType *chanTypePtr); /* 406 */
+ Tcl_DriverGetOptionProc * (*tcl_ChannelGetOptionProc) (CONST Tcl_ChannelType *chanTypePtr); /* 407 */
+ Tcl_DriverWatchProc * (*tcl_ChannelWatchProc) (CONST Tcl_ChannelType *chanTypePtr); /* 408 */
+ Tcl_DriverGetHandleProc * (*tcl_ChannelGetHandleProc) (CONST Tcl_ChannelType *chanTypePtr); /* 409 */
+ Tcl_DriverFlushProc * (*tcl_ChannelFlushProc) (CONST Tcl_ChannelType *chanTypePtr); /* 410 */
+ Tcl_DriverHandlerProc * (*tcl_ChannelHandlerProc) (CONST Tcl_ChannelType *chanTypePtr); /* 411 */
+ int (*tcl_JoinThread) (Tcl_ThreadId threadId, int *result); /* 412 */
+ int (*tcl_IsChannelShared) (Tcl_Channel channel); /* 413 */
+ int (*tcl_IsChannelRegistered) (Tcl_Interp *interp, Tcl_Channel channel); /* 414 */
+ void (*tcl_CutChannel) (Tcl_Channel channel); /* 415 */
+ void (*tcl_SpliceChannel) (Tcl_Channel channel); /* 416 */
+ void (*tcl_ClearChannelHandlers) (Tcl_Channel channel); /* 417 */
+ int (*tcl_IsChannelExisting) (CONST char *channelName); /* 418 */
+ int (*tcl_UniCharNcasecmp) (CONST Tcl_UniChar *ucs, CONST Tcl_UniChar *uct, unsigned long numChars); /* 419 */
+ int (*tcl_UniCharCaseMatch) (CONST Tcl_UniChar *uniStr, CONST Tcl_UniChar *uniPattern, int nocase); /* 420 */
+ Tcl_HashEntry * (*tcl_FindHashEntry) (Tcl_HashTable *tablePtr, CONST char *key); /* 421 */
+ Tcl_HashEntry * (*tcl_CreateHashEntry) (Tcl_HashTable *tablePtr, CONST char *key, int *newPtr); /* 422 */
+ void (*tcl_InitCustomHashTable) (Tcl_HashTable *tablePtr, int keyType, Tcl_HashKeyType *typePtr); /* 423 */
+ void (*tcl_InitObjHashTable) (Tcl_HashTable *tablePtr); /* 424 */
+ ClientData (*tcl_CommandTraceInfo) (Tcl_Interp *interp, CONST char *varName, int flags, Tcl_CommandTraceProc *procPtr, ClientData prevClientData); /* 425 */
+ int (*tcl_TraceCommand) (Tcl_Interp *interp, CONST char *varName, int flags, Tcl_CommandTraceProc *proc, ClientData clientData); /* 426 */
+ void (*tcl_UntraceCommand) (Tcl_Interp *interp, CONST char *varName, int flags, Tcl_CommandTraceProc *proc, ClientData clientData); /* 427 */
+ char * (*tcl_AttemptAlloc) (unsigned int size); /* 428 */
+ char * (*tcl_AttemptDbCkalloc) (unsigned int size, CONST char *file, int line); /* 429 */
+ char * (*tcl_AttemptRealloc) (char *ptr, unsigned int size); /* 430 */
+ char * (*tcl_AttemptDbCkrealloc) (char *ptr, unsigned int size, CONST char *file, int line); /* 431 */
+ int (*tcl_AttemptSetObjLength) (Tcl_Obj *objPtr, int length); /* 432 */
+ Tcl_ThreadId (*tcl_GetChannelThread) (Tcl_Channel channel); /* 433 */
+ Tcl_UniChar * (*tcl_GetUnicodeFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 434 */
+ int (*tcl_GetMathFuncInfo) (Tcl_Interp *interp, CONST char *name, int *numArgsPtr, Tcl_ValueType **argTypesPtr, Tcl_MathProc **procPtr, ClientData *clientDataPtr); /* 435 */
+ Tcl_Obj * (*tcl_ListMathFuncs) (Tcl_Interp *interp, CONST char *pattern); /* 436 */
+ Tcl_Obj * (*tcl_SubstObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 437 */
+ int (*tcl_DetachChannel) (Tcl_Interp *interp, Tcl_Channel channel); /* 438 */
+ int (*tcl_IsStandardChannel) (Tcl_Channel channel); /* 439 */
+ int (*tcl_FSCopyFile) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr); /* 440 */
+ int (*tcl_FSCopyDirectory) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr, Tcl_Obj **errorPtr); /* 441 */
+ int (*tcl_FSCreateDirectory) (Tcl_Obj *pathPtr); /* 442 */
+ int (*tcl_FSDeleteFile) (Tcl_Obj *pathPtr); /* 443 */
+ int (*tcl_FSLoadFile) (Tcl_Interp *interp, Tcl_Obj *pathPtr, CONST char *sym1, CONST char *sym2, Tcl_PackageInitProc **proc1Ptr, Tcl_PackageInitProc **proc2Ptr, Tcl_LoadHandle *handlePtr, Tcl_FSUnloadFileProc **unloadProcPtr); /* 444 */
+ int (*tcl_FSMatchInDirectory) (Tcl_Interp *interp, Tcl_Obj *result, Tcl_Obj *pathPtr, CONST char *pattern, Tcl_GlobTypeData *types); /* 445 */
+ Tcl_Obj * (*tcl_FSLink) (Tcl_Obj *pathPtr, Tcl_Obj *toPtr, int linkAction); /* 446 */
+ int (*tcl_FSRemoveDirectory) (Tcl_Obj *pathPtr, int recursive, Tcl_Obj **errorPtr); /* 447 */
+ int (*tcl_FSRenameFile) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr); /* 448 */
+ int (*tcl_FSLstat) (Tcl_Obj *pathPtr, Tcl_StatBuf *buf); /* 449 */
+ int (*tcl_FSUtime) (Tcl_Obj *pathPtr, struct utimbuf *tval); /* 450 */
+ int (*tcl_FSFileAttrsGet) (Tcl_Interp *interp, int index, Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef); /* 451 */
+ int (*tcl_FSFileAttrsSet) (Tcl_Interp *interp, int index, Tcl_Obj *pathPtr, Tcl_Obj *objPtr); /* 452 */
+ CONST char ** (*tcl_FSFileAttrStrings) (Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef); /* 453 */
+ int (*tcl_FSStat) (Tcl_Obj *pathPtr, Tcl_StatBuf *buf); /* 454 */
+ int (*tcl_FSAccess) (Tcl_Obj *pathPtr, int mode); /* 455 */
+ Tcl_Channel (*tcl_FSOpenFileChannel) (Tcl_Interp *interp, Tcl_Obj *pathPtr, CONST char *modeString, int permissions); /* 456 */
+ Tcl_Obj * (*tcl_FSGetCwd) (Tcl_Interp *interp); /* 457 */
+ int (*tcl_FSChdir) (Tcl_Obj *pathPtr); /* 458 */
+ int (*tcl_FSConvertToPathType) (Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 459 */
+ Tcl_Obj * (*tcl_FSJoinPath) (Tcl_Obj *listObj, int elements); /* 460 */
+ Tcl_Obj * (*tcl_FSSplitPath) (Tcl_Obj *pathPtr, int *lenPtr); /* 461 */
+ int (*tcl_FSEqualPaths) (Tcl_Obj *firstPtr, Tcl_Obj *secondPtr); /* 462 */
+ Tcl_Obj * (*tcl_FSGetNormalizedPath) (Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 463 */
+ Tcl_Obj * (*tcl_FSJoinToPath) (Tcl_Obj *pathPtr, int objc, Tcl_Obj *CONST objv[]); /* 464 */
+ ClientData (*tcl_FSGetInternalRep) (Tcl_Obj *pathPtr, Tcl_Filesystem *fsPtr); /* 465 */
+ Tcl_Obj * (*tcl_FSGetTranslatedPath) (Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 466 */
+ int (*tcl_FSEvalFile) (Tcl_Interp *interp, Tcl_Obj *fileName); /* 467 */
+ Tcl_Obj * (*tcl_FSNewNativePath) (Tcl_Filesystem *fromFilesystem, ClientData clientData); /* 468 */
+ CONST char * (*tcl_FSGetNativePath) (Tcl_Obj *pathPtr); /* 469 */
+ Tcl_Obj * (*tcl_FSFileSystemInfo) (Tcl_Obj *pathPtr); /* 470 */
+ Tcl_Obj * (*tcl_FSPathSeparator) (Tcl_Obj *pathPtr); /* 471 */
+ Tcl_Obj * (*tcl_FSListVolumes) (void); /* 472 */
+ int (*tcl_FSRegister) (ClientData clientData, Tcl_Filesystem *fsPtr); /* 473 */
+ int (*tcl_FSUnregister) (Tcl_Filesystem *fsPtr); /* 474 */
+ ClientData (*tcl_FSData) (Tcl_Filesystem *fsPtr); /* 475 */
+ CONST char * (*tcl_FSGetTranslatedStringPath) (Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 476 */
+ Tcl_Filesystem * (*tcl_FSGetFileSystemForPath) (Tcl_Obj *pathPtr); /* 477 */
+ Tcl_PathType (*tcl_FSGetPathType) (Tcl_Obj *pathPtr); /* 478 */
+ int (*tcl_OutputBuffered) (Tcl_Channel chan); /* 479 */
+ void (*tcl_FSMountsChanged) (Tcl_Filesystem *fsPtr); /* 480 */
+ int (*tcl_EvalTokensStandard) (Tcl_Interp *interp, Tcl_Token *tokenPtr, int count); /* 481 */
+ void (*tcl_GetTime) (Tcl_Time *timeBuf); /* 482 */
+ Tcl_Trace (*tcl_CreateObjTrace) (Tcl_Interp *interp, int level, int flags, Tcl_CmdObjTraceProc *objProc, ClientData clientData, Tcl_CmdObjTraceDeleteProc *delProc); /* 483 */
+ int (*tcl_GetCommandInfoFromToken) (Tcl_Command token, Tcl_CmdInfo *infoPtr); /* 484 */
+ int (*tcl_SetCommandInfoFromToken) (Tcl_Command token, CONST Tcl_CmdInfo *infoPtr); /* 485 */
+ Tcl_Obj * (*tcl_DbNewWideIntObj) (Tcl_WideInt wideValue, CONST char *file, int line); /* 486 */
+ int (*tcl_GetWideIntFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_WideInt *widePtr); /* 487 */
+ Tcl_Obj * (*tcl_NewWideIntObj) (Tcl_WideInt wideValue); /* 488 */
+ void (*tcl_SetWideIntObj) (Tcl_Obj *objPtr, Tcl_WideInt wideValue); /* 489 */
+ Tcl_StatBuf * (*tcl_AllocStatBuf) (void); /* 490 */
+ Tcl_WideInt (*tcl_Seek) (Tcl_Channel chan, Tcl_WideInt offset, int mode); /* 491 */
+ Tcl_WideInt (*tcl_Tell) (Tcl_Channel chan); /* 492 */
+ Tcl_DriverWideSeekProc * (*tcl_ChannelWideSeekProc) (CONST Tcl_ChannelType *chanTypePtr); /* 493 */
+ int (*tcl_DictObjPut) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr, Tcl_Obj *valuePtr); /* 494 */
+ int (*tcl_DictObjGet) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr, Tcl_Obj **valuePtrPtr); /* 495 */
+ int (*tcl_DictObjRemove) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr); /* 496 */
+ int (*tcl_DictObjSize) (Tcl_Interp *interp, Tcl_Obj *dictPtr, int *sizePtr); /* 497 */
+ int (*tcl_DictObjFirst) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_DictSearch *searchPtr, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr); /* 498 */
+ void (*tcl_DictObjNext) (Tcl_DictSearch *searchPtr, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr); /* 499 */
+ void (*tcl_DictObjDone) (Tcl_DictSearch *searchPtr); /* 500 */
+ int (*tcl_DictObjPutKeyList) (Tcl_Interp *interp, Tcl_Obj *dictPtr, int keyc, Tcl_Obj *CONST *keyv, Tcl_Obj *valuePtr); /* 501 */
+ int (*tcl_DictObjRemoveKeyList) (Tcl_Interp *interp, Tcl_Obj *dictPtr, int keyc, Tcl_Obj *CONST *keyv); /* 502 */
+ Tcl_Obj * (*tcl_NewDictObj) (void); /* 503 */
+ Tcl_Obj * (*tcl_DbNewDictObj) (CONST char *file, int line); /* 504 */
+ void (*tcl_RegisterConfig) (Tcl_Interp *interp, CONST char *pkgName, Tcl_Config *configuration, CONST char *valEncoding); /* 505 */
+ Tcl_Namespace * (*tcl_CreateNamespace) (Tcl_Interp *interp, CONST char *name, ClientData clientData, Tcl_NamespaceDeleteProc *deleteProc); /* 506 */
+ void (*tcl_DeleteNamespace) (Tcl_Namespace *nsPtr); /* 507 */
+ int (*tcl_AppendExportList) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, Tcl_Obj *objPtr); /* 508 */
+ int (*tcl_Export) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, CONST char *pattern, int resetListFirst); /* 509 */
+ int (*tcl_Import) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, CONST char *pattern, int allowOverwrite); /* 510 */
+ int (*tcl_ForgetImport) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, CONST char *pattern); /* 511 */
+ Tcl_Namespace * (*tcl_GetCurrentNamespace) (Tcl_Interp *interp); /* 512 */
+ Tcl_Namespace * (*tcl_GetGlobalNamespace) (Tcl_Interp *interp); /* 513 */
+ Tcl_Namespace * (*tcl_FindNamespace) (Tcl_Interp *interp, CONST char *name, Tcl_Namespace *contextNsPtr, int flags); /* 514 */
+ Tcl_Command (*tcl_FindCommand) (Tcl_Interp *interp, CONST char *name, Tcl_Namespace *contextNsPtr, int flags); /* 515 */
+ Tcl_Command (*tcl_GetCommandFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 516 */
+ void (*tcl_GetCommandFullName) (Tcl_Interp *interp, Tcl_Command command, Tcl_Obj *objPtr); /* 517 */
+ int (*tcl_FSEvalFileEx) (Tcl_Interp *interp, Tcl_Obj *fileName, CONST char *encodingName); /* 518 */
+ Tcl_ExitProc * (*tcl_SetExitProc) (Tcl_ExitProc *proc); /* 519 */
+ void (*tcl_LimitAddHandler) (Tcl_Interp *interp, int type, Tcl_LimitHandlerProc *handlerProc, ClientData clientData, Tcl_LimitHandlerDeleteProc *deleteProc); /* 520 */
+ void (*tcl_LimitRemoveHandler) (Tcl_Interp *interp, int type, Tcl_LimitHandlerProc *handlerProc, ClientData clientData); /* 521 */
+ int (*tcl_LimitReady) (Tcl_Interp *interp); /* 522 */
+ int (*tcl_LimitCheck) (Tcl_Interp *interp); /* 523 */
+ int (*tcl_LimitExceeded) (Tcl_Interp *interp); /* 524 */
+ void (*tcl_LimitSetCommands) (Tcl_Interp *interp, int commandLimit); /* 525 */
+ void (*tcl_LimitSetTime) (Tcl_Interp *interp, Tcl_Time *timeLimitPtr); /* 526 */
+ void (*tcl_LimitSetGranularity) (Tcl_Interp *interp, int type, int granularity); /* 527 */
+ int (*tcl_LimitTypeEnabled) (Tcl_Interp *interp, int type); /* 528 */
+ int (*tcl_LimitTypeExceeded) (Tcl_Interp *interp, int type); /* 529 */
+ void (*tcl_LimitTypeSet) (Tcl_Interp *interp, int type); /* 530 */
+ void (*tcl_LimitTypeReset) (Tcl_Interp *interp, int type); /* 531 */
+ int (*tcl_LimitGetCommands) (Tcl_Interp *interp); /* 532 */
+ void (*tcl_LimitGetTime) (Tcl_Interp *interp, Tcl_Time *timeLimitPtr); /* 533 */
+ int (*tcl_LimitGetGranularity) (Tcl_Interp *interp, int type); /* 534 */
+ Tcl_InterpState (*tcl_SaveInterpState) (Tcl_Interp *interp, int status); /* 535 */
+ int (*tcl_RestoreInterpState) (Tcl_Interp *interp, Tcl_InterpState state); /* 536 */
+ void (*tcl_DiscardInterpState) (Tcl_InterpState state); /* 537 */
+ int (*tcl_SetReturnOptions) (Tcl_Interp *interp, Tcl_Obj *options); /* 538 */
+ Tcl_Obj * (*tcl_GetReturnOptions) (Tcl_Interp *interp, int result); /* 539 */
+ int (*tcl_IsEnsemble) (Tcl_Command token); /* 540 */
+ Tcl_Command (*tcl_CreateEnsemble) (Tcl_Interp *interp, CONST char *name, Tcl_Namespace *namespacePtr, int flags); /* 541 */
+ Tcl_Command (*tcl_FindEnsemble) (Tcl_Interp *interp, Tcl_Obj *cmdNameObj, int flags); /* 542 */
+ int (*tcl_SetEnsembleSubcommandList) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *subcmdList); /* 543 */
+ int (*tcl_SetEnsembleMappingDict) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *mapDict); /* 544 */
+ int (*tcl_SetEnsembleUnknownHandler) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *unknownList); /* 545 */
+ int (*tcl_SetEnsembleFlags) (Tcl_Interp *interp, Tcl_Command token, int flags); /* 546 */
+ int (*tcl_GetEnsembleSubcommandList) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **subcmdListPtr); /* 547 */
+ int (*tcl_GetEnsembleMappingDict) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **mapDictPtr); /* 548 */
+ int (*tcl_GetEnsembleUnknownHandler) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **unknownListPtr); /* 549 */
+ int (*tcl_GetEnsembleFlags) (Tcl_Interp *interp, Tcl_Command token, int *flagsPtr); /* 550 */
+ int (*tcl_GetEnsembleNamespace) (Tcl_Interp *interp, Tcl_Command token, Tcl_Namespace **namespacePtrPtr); /* 551 */
+ void (*tcl_SetTimeProc) (Tcl_GetTimeProc *getProc, Tcl_ScaleTimeProc *scaleProc, ClientData clientData); /* 552 */
+ void (*tcl_QueryTimeProc) (Tcl_GetTimeProc **getProc, Tcl_ScaleTimeProc **scaleProc, ClientData *clientData); /* 553 */
+ Tcl_DriverThreadActionProc * (*tcl_ChannelThreadActionProc) (CONST Tcl_ChannelType *chanTypePtr); /* 554 */
+ Tcl_Obj * (*tcl_NewBignumObj) (mp_int *value); /* 555 */
+ Tcl_Obj * (*tcl_DbNewBignumObj) (mp_int *value, CONST char *file, int line); /* 556 */
+ void (*tcl_SetBignumObj) (Tcl_Obj *obj, mp_int *value); /* 557 */
+ int (*tcl_GetBignumFromObj) (Tcl_Interp *interp, Tcl_Obj *obj, mp_int *value); /* 558 */
+ int (*tcl_TakeBignumFromObj) (Tcl_Interp *interp, Tcl_Obj *obj, mp_int *value); /* 559 */
+ int (*tcl_TruncateChannel) (Tcl_Channel chan, Tcl_WideInt length); /* 560 */
+ Tcl_DriverTruncateProc * (*tcl_ChannelTruncateProc) (CONST Tcl_ChannelType *chanTypePtr); /* 561 */
+ void (*tcl_SetChannelErrorInterp) (Tcl_Interp *interp, Tcl_Obj *msg); /* 562 */
+ void (*tcl_GetChannelErrorInterp) (Tcl_Interp *interp, Tcl_Obj **msg); /* 563 */
+ void (*tcl_SetChannelError) (Tcl_Channel chan, Tcl_Obj *msg); /* 564 */
+ void (*tcl_GetChannelError) (Tcl_Channel chan, Tcl_Obj **msg); /* 565 */
+ int (*tcl_InitBignumFromDouble) (Tcl_Interp *interp, double initval, mp_int *toInit); /* 566 */
+ Tcl_Obj * (*tcl_GetNamespaceUnknownHandler) (Tcl_Interp *interp, Tcl_Namespace *nsPtr); /* 567 */
+ int (*tcl_SetNamespaceUnknownHandler) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, Tcl_Obj *handlerPtr); /* 568 */
+ int (*tcl_GetEncodingFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Encoding *encodingPtr); /* 569 */
+ Tcl_Obj * (*tcl_GetEncodingSearchPath) (void); /* 570 */
+ int (*tcl_SetEncodingSearchPath) (Tcl_Obj *searchPath); /* 571 */
+ CONST char * (*tcl_GetEncodingNameFromEnvironment) (Tcl_DString *bufPtr); /* 572 */
+ int (*tcl_PkgRequireProc) (Tcl_Interp *interp, CONST char *name, int objc, Tcl_Obj *CONST objv[], ClientData *clientDataPtr); /* 573 */
+ void (*tcl_AppendObjToErrorInfo) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 574 */
+ void (*tcl_AppendLimitedToObj) (Tcl_Obj *objPtr, CONST char *bytes, int length, int limit, CONST char *ellipsis); /* 575 */
+ Tcl_Obj * (*tcl_Format) (Tcl_Interp *interp, CONST char *format, int objc, Tcl_Obj *CONST objv[]); /* 576 */
+ int (*tcl_AppendFormatToObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, CONST char *format, int objc, Tcl_Obj *CONST objv[]); /* 577 */
+ Tcl_Obj * (*tcl_ObjPrintf) (CONST char *format, ...); /* 578 */
+ void (*tcl_AppendPrintfToObj) (Tcl_Obj *objPtr, CONST char *format, ...); /* 579 */
} TclStubs;
#ifdef __cplusplus
@@ -2333,18 +4075,30 @@ extern TclStubs *tclStubsPtr;
#define Tcl_DbCkrealloc \
(tclStubsPtr->tcl_DbCkrealloc) /* 8 */
#endif
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
#ifndef Tcl_CreateFileHandler
#define Tcl_CreateFileHandler \
(tclStubsPtr->tcl_CreateFileHandler) /* 9 */
#endif
#endif /* UNIX */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+#ifdef MAC_OSX_TCL /* MACOSX */
+#ifndef Tcl_CreateFileHandler
+#define Tcl_CreateFileHandler \
+ (tclStubsPtr->tcl_CreateFileHandler) /* 9 */
+#endif
+#endif /* MACOSX */
+#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
#ifndef Tcl_DeleteFileHandler
#define Tcl_DeleteFileHandler \
(tclStubsPtr->tcl_DeleteFileHandler) /* 10 */
#endif
#endif /* UNIX */
+#ifdef MAC_OSX_TCL /* MACOSX */
+#ifndef Tcl_DeleteFileHandler
+#define Tcl_DeleteFileHandler \
+ (tclStubsPtr->tcl_DeleteFileHandler) /* 10 */
+#endif
+#endif /* MACOSX */
#ifndef Tcl_SetTimer
#define Tcl_SetTimer \
(tclStubsPtr->tcl_SetTimer) /* 11 */
@@ -2745,18 +4499,10 @@ extern TclStubs *tclStubsPtr;
#define Tcl_DeleteInterp \
(tclStubsPtr->tcl_DeleteInterp) /* 110 */
#endif
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
#ifndef Tcl_DetachPids
#define Tcl_DetachPids \
(tclStubsPtr->tcl_DetachPids) /* 111 */
#endif
-#endif /* UNIX */
-#ifdef __WIN32__
-#ifndef Tcl_DetachPids
-#define Tcl_DetachPids \
- (tclStubsPtr->tcl_DetachPids) /* 111 */
-#endif
-#endif /* __WIN32__ */
#ifndef Tcl_DeleteTimerHandler
#define Tcl_DeleteTimerHandler \
(tclStubsPtr->tcl_DeleteTimerHandler) /* 112 */
@@ -2977,12 +4723,18 @@ extern TclStubs *tclStubsPtr;
#define Tcl_GetObjResult \
(tclStubsPtr->tcl_GetObjResult) /* 166 */
#endif
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
#ifndef Tcl_GetOpenFile
#define Tcl_GetOpenFile \
(tclStubsPtr->tcl_GetOpenFile) /* 167 */
#endif
#endif /* UNIX */
+#ifdef MAC_OSX_TCL /* MACOSX */
+#ifndef Tcl_GetOpenFile
+#define Tcl_GetOpenFile \
+ (tclStubsPtr->tcl_GetOpenFile) /* 167 */
+#endif
+#endif /* MACOSX */
#ifndef Tcl_GetPathType
#define Tcl_GetPathType \
(tclStubsPtr->tcl_GetPathType) /* 168 */
@@ -3096,18 +4848,10 @@ extern TclStubs *tclStubsPtr;
#define Tcl_ObjSetVar2 \
(tclStubsPtr->tcl_ObjSetVar2) /* 196 */
#endif
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
#ifndef Tcl_OpenCommandChannel
#define Tcl_OpenCommandChannel \
(tclStubsPtr->tcl_OpenCommandChannel) /* 197 */
#endif
-#endif /* UNIX */
-#ifdef __WIN32__
-#ifndef Tcl_OpenCommandChannel
-#define Tcl_OpenCommandChannel \
- (tclStubsPtr->tcl_OpenCommandChannel) /* 197 */
-#endif
-#endif /* __WIN32__ */
#ifndef Tcl_OpenFileChannel
#define Tcl_OpenFileChannel \
(tclStubsPtr->tcl_OpenFileChannel) /* 198 */
@@ -3144,18 +4888,10 @@ extern TclStubs *tclStubsPtr;
#define Tcl_Read \
(tclStubsPtr->tcl_Read) /* 206 */
#endif
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
-#ifndef Tcl_ReapDetachedProcs
-#define Tcl_ReapDetachedProcs \
- (tclStubsPtr->tcl_ReapDetachedProcs) /* 207 */
-#endif
-#endif /* UNIX */
-#ifdef __WIN32__
#ifndef Tcl_ReapDetachedProcs
#define Tcl_ReapDetachedProcs \
(tclStubsPtr->tcl_ReapDetachedProcs) /* 207 */
#endif
-#endif /* __WIN32__ */
#ifndef Tcl_RecordAndEval
#define Tcl_RecordAndEval \
(tclStubsPtr->tcl_RecordAndEval) /* 208 */
@@ -4297,96 +6033,357 @@ extern TclStubs *tclStubsPtr;
#define Tcl_ChannelWideSeekProc \
(tclStubsPtr->tcl_ChannelWideSeekProc) /* 493 */
#endif
-/* Slot 494 is reserved */
-/* Slot 495 is reserved */
-/* Slot 496 is reserved */
-/* Slot 497 is reserved */
-/* Slot 498 is reserved */
-/* Slot 499 is reserved */
-/* Slot 500 is reserved */
-/* Slot 501 is reserved */
-/* Slot 502 is reserved */
-/* Slot 503 is reserved */
-/* Slot 504 is reserved */
-/* Slot 505 is reserved */
-/* Slot 506 is reserved */
-/* Slot 507 is reserved */
-/* Slot 508 is reserved */
-/* Slot 509 is reserved */
-/* Slot 510 is reserved */
-/* Slot 511 is reserved */
-/* Slot 512 is reserved */
-/* Slot 513 is reserved */
-/* Slot 514 is reserved */
-/* Slot 515 is reserved */
-/* Slot 516 is reserved */
-/* Slot 517 is reserved */
-/* Slot 518 is reserved */
-/* Slot 519 is reserved */
-/* Slot 520 is reserved */
-/* Slot 521 is reserved */
-/* Slot 522 is reserved */
-/* Slot 523 is reserved */
-/* Slot 524 is reserved */
-/* Slot 525 is reserved */
-/* Slot 526 is reserved */
-/* Slot 527 is reserved */
-/* Slot 528 is reserved */
-/* Slot 529 is reserved */
-/* Slot 530 is reserved */
-/* Slot 531 is reserved */
-/* Slot 532 is reserved */
-/* Slot 533 is reserved */
-/* Slot 534 is reserved */
-/* Slot 535 is reserved */
-/* Slot 536 is reserved */
-/* Slot 537 is reserved */
-/* Slot 538 is reserved */
-/* Slot 539 is reserved */
-/* Slot 540 is reserved */
-/* Slot 541 is reserved */
-/* Slot 542 is reserved */
-/* Slot 543 is reserved */
-/* Slot 544 is reserved */
-/* Slot 545 is reserved */
-/* Slot 546 is reserved */
-/* Slot 547 is reserved */
-/* Slot 548 is reserved */
-/* Slot 549 is reserved */
-/* Slot 550 is reserved */
-/* Slot 551 is reserved */
-/* Slot 552 is reserved */
-/* Slot 553 is reserved */
+#ifndef Tcl_DictObjPut
+#define Tcl_DictObjPut \
+ (tclStubsPtr->tcl_DictObjPut) /* 494 */
+#endif
+#ifndef Tcl_DictObjGet
+#define Tcl_DictObjGet \
+ (tclStubsPtr->tcl_DictObjGet) /* 495 */
+#endif
+#ifndef Tcl_DictObjRemove
+#define Tcl_DictObjRemove \
+ (tclStubsPtr->tcl_DictObjRemove) /* 496 */
+#endif
+#ifndef Tcl_DictObjSize
+#define Tcl_DictObjSize \
+ (tclStubsPtr->tcl_DictObjSize) /* 497 */
+#endif
+#ifndef Tcl_DictObjFirst
+#define Tcl_DictObjFirst \
+ (tclStubsPtr->tcl_DictObjFirst) /* 498 */
+#endif
+#ifndef Tcl_DictObjNext
+#define Tcl_DictObjNext \
+ (tclStubsPtr->tcl_DictObjNext) /* 499 */
+#endif
+#ifndef Tcl_DictObjDone
+#define Tcl_DictObjDone \
+ (tclStubsPtr->tcl_DictObjDone) /* 500 */
+#endif
+#ifndef Tcl_DictObjPutKeyList
+#define Tcl_DictObjPutKeyList \
+ (tclStubsPtr->tcl_DictObjPutKeyList) /* 501 */
+#endif
+#ifndef Tcl_DictObjRemoveKeyList
+#define Tcl_DictObjRemoveKeyList \
+ (tclStubsPtr->tcl_DictObjRemoveKeyList) /* 502 */
+#endif
+#ifndef Tcl_NewDictObj
+#define Tcl_NewDictObj \
+ (tclStubsPtr->tcl_NewDictObj) /* 503 */
+#endif
+#ifndef Tcl_DbNewDictObj
+#define Tcl_DbNewDictObj \
+ (tclStubsPtr->tcl_DbNewDictObj) /* 504 */
+#endif
+#ifndef Tcl_RegisterConfig
+#define Tcl_RegisterConfig \
+ (tclStubsPtr->tcl_RegisterConfig) /* 505 */
+#endif
+#ifndef Tcl_CreateNamespace
+#define Tcl_CreateNamespace \
+ (tclStubsPtr->tcl_CreateNamespace) /* 506 */
+#endif
+#ifndef Tcl_DeleteNamespace
+#define Tcl_DeleteNamespace \
+ (tclStubsPtr->tcl_DeleteNamespace) /* 507 */
+#endif
+#ifndef Tcl_AppendExportList
+#define Tcl_AppendExportList \
+ (tclStubsPtr->tcl_AppendExportList) /* 508 */
+#endif
+#ifndef Tcl_Export
+#define Tcl_Export \
+ (tclStubsPtr->tcl_Export) /* 509 */
+#endif
+#ifndef Tcl_Import
+#define Tcl_Import \
+ (tclStubsPtr->tcl_Import) /* 510 */
+#endif
+#ifndef Tcl_ForgetImport
+#define Tcl_ForgetImport \
+ (tclStubsPtr->tcl_ForgetImport) /* 511 */
+#endif
+#ifndef Tcl_GetCurrentNamespace
+#define Tcl_GetCurrentNamespace \
+ (tclStubsPtr->tcl_GetCurrentNamespace) /* 512 */
+#endif
+#ifndef Tcl_GetGlobalNamespace
+#define Tcl_GetGlobalNamespace \
+ (tclStubsPtr->tcl_GetGlobalNamespace) /* 513 */
+#endif
+#ifndef Tcl_FindNamespace
+#define Tcl_FindNamespace \
+ (tclStubsPtr->tcl_FindNamespace) /* 514 */
+#endif
+#ifndef Tcl_FindCommand
+#define Tcl_FindCommand \
+ (tclStubsPtr->tcl_FindCommand) /* 515 */
+#endif
+#ifndef Tcl_GetCommandFromObj
+#define Tcl_GetCommandFromObj \
+ (tclStubsPtr->tcl_GetCommandFromObj) /* 516 */
+#endif
+#ifndef Tcl_GetCommandFullName
+#define Tcl_GetCommandFullName \
+ (tclStubsPtr->tcl_GetCommandFullName) /* 517 */
+#endif
+#ifndef Tcl_FSEvalFileEx
+#define Tcl_FSEvalFileEx \
+ (tclStubsPtr->tcl_FSEvalFileEx) /* 518 */
+#endif
+#ifndef Tcl_SetExitProc
+#define Tcl_SetExitProc \
+ (tclStubsPtr->tcl_SetExitProc) /* 519 */
+#endif
+#ifndef Tcl_LimitAddHandler
+#define Tcl_LimitAddHandler \
+ (tclStubsPtr->tcl_LimitAddHandler) /* 520 */
+#endif
+#ifndef Tcl_LimitRemoveHandler
+#define Tcl_LimitRemoveHandler \
+ (tclStubsPtr->tcl_LimitRemoveHandler) /* 521 */
+#endif
+#ifndef Tcl_LimitReady
+#define Tcl_LimitReady \
+ (tclStubsPtr->tcl_LimitReady) /* 522 */
+#endif
+#ifndef Tcl_LimitCheck
+#define Tcl_LimitCheck \
+ (tclStubsPtr->tcl_LimitCheck) /* 523 */
+#endif
+#ifndef Tcl_LimitExceeded
+#define Tcl_LimitExceeded \
+ (tclStubsPtr->tcl_LimitExceeded) /* 524 */
+#endif
+#ifndef Tcl_LimitSetCommands
+#define Tcl_LimitSetCommands \
+ (tclStubsPtr->tcl_LimitSetCommands) /* 525 */
+#endif
+#ifndef Tcl_LimitSetTime
+#define Tcl_LimitSetTime \
+ (tclStubsPtr->tcl_LimitSetTime) /* 526 */
+#endif
+#ifndef Tcl_LimitSetGranularity
+#define Tcl_LimitSetGranularity \
+ (tclStubsPtr->tcl_LimitSetGranularity) /* 527 */
+#endif
+#ifndef Tcl_LimitTypeEnabled
+#define Tcl_LimitTypeEnabled \
+ (tclStubsPtr->tcl_LimitTypeEnabled) /* 528 */
+#endif
+#ifndef Tcl_LimitTypeExceeded
+#define Tcl_LimitTypeExceeded \
+ (tclStubsPtr->tcl_LimitTypeExceeded) /* 529 */
+#endif
+#ifndef Tcl_LimitTypeSet
+#define Tcl_LimitTypeSet \
+ (tclStubsPtr->tcl_LimitTypeSet) /* 530 */
+#endif
+#ifndef Tcl_LimitTypeReset
+#define Tcl_LimitTypeReset \
+ (tclStubsPtr->tcl_LimitTypeReset) /* 531 */
+#endif
+#ifndef Tcl_LimitGetCommands
+#define Tcl_LimitGetCommands \
+ (tclStubsPtr->tcl_LimitGetCommands) /* 532 */
+#endif
+#ifndef Tcl_LimitGetTime
+#define Tcl_LimitGetTime \
+ (tclStubsPtr->tcl_LimitGetTime) /* 533 */
+#endif
+#ifndef Tcl_LimitGetGranularity
+#define Tcl_LimitGetGranularity \
+ (tclStubsPtr->tcl_LimitGetGranularity) /* 534 */
+#endif
+#ifndef Tcl_SaveInterpState
+#define Tcl_SaveInterpState \
+ (tclStubsPtr->tcl_SaveInterpState) /* 535 */
+#endif
+#ifndef Tcl_RestoreInterpState
+#define Tcl_RestoreInterpState \
+ (tclStubsPtr->tcl_RestoreInterpState) /* 536 */
+#endif
+#ifndef Tcl_DiscardInterpState
+#define Tcl_DiscardInterpState \
+ (tclStubsPtr->tcl_DiscardInterpState) /* 537 */
+#endif
+#ifndef Tcl_SetReturnOptions
+#define Tcl_SetReturnOptions \
+ (tclStubsPtr->tcl_SetReturnOptions) /* 538 */
+#endif
+#ifndef Tcl_GetReturnOptions
+#define Tcl_GetReturnOptions \
+ (tclStubsPtr->tcl_GetReturnOptions) /* 539 */
+#endif
+#ifndef Tcl_IsEnsemble
+#define Tcl_IsEnsemble \
+ (tclStubsPtr->tcl_IsEnsemble) /* 540 */
+#endif
+#ifndef Tcl_CreateEnsemble
+#define Tcl_CreateEnsemble \
+ (tclStubsPtr->tcl_CreateEnsemble) /* 541 */
+#endif
+#ifndef Tcl_FindEnsemble
+#define Tcl_FindEnsemble \
+ (tclStubsPtr->tcl_FindEnsemble) /* 542 */
+#endif
+#ifndef Tcl_SetEnsembleSubcommandList
+#define Tcl_SetEnsembleSubcommandList \
+ (tclStubsPtr->tcl_SetEnsembleSubcommandList) /* 543 */
+#endif
+#ifndef Tcl_SetEnsembleMappingDict
+#define Tcl_SetEnsembleMappingDict \
+ (tclStubsPtr->tcl_SetEnsembleMappingDict) /* 544 */
+#endif
+#ifndef Tcl_SetEnsembleUnknownHandler
+#define Tcl_SetEnsembleUnknownHandler \
+ (tclStubsPtr->tcl_SetEnsembleUnknownHandler) /* 545 */
+#endif
+#ifndef Tcl_SetEnsembleFlags
+#define Tcl_SetEnsembleFlags \
+ (tclStubsPtr->tcl_SetEnsembleFlags) /* 546 */
+#endif
+#ifndef Tcl_GetEnsembleSubcommandList
+#define Tcl_GetEnsembleSubcommandList \
+ (tclStubsPtr->tcl_GetEnsembleSubcommandList) /* 547 */
+#endif
+#ifndef Tcl_GetEnsembleMappingDict
+#define Tcl_GetEnsembleMappingDict \
+ (tclStubsPtr->tcl_GetEnsembleMappingDict) /* 548 */
+#endif
+#ifndef Tcl_GetEnsembleUnknownHandler
+#define Tcl_GetEnsembleUnknownHandler \
+ (tclStubsPtr->tcl_GetEnsembleUnknownHandler) /* 549 */
+#endif
+#ifndef Tcl_GetEnsembleFlags
+#define Tcl_GetEnsembleFlags \
+ (tclStubsPtr->tcl_GetEnsembleFlags) /* 550 */
+#endif
+#ifndef Tcl_GetEnsembleNamespace
+#define Tcl_GetEnsembleNamespace \
+ (tclStubsPtr->tcl_GetEnsembleNamespace) /* 551 */
+#endif
+#ifndef Tcl_SetTimeProc
+#define Tcl_SetTimeProc \
+ (tclStubsPtr->tcl_SetTimeProc) /* 552 */
+#endif
+#ifndef Tcl_QueryTimeProc
+#define Tcl_QueryTimeProc \
+ (tclStubsPtr->tcl_QueryTimeProc) /* 553 */
+#endif
#ifndef Tcl_ChannelThreadActionProc
#define Tcl_ChannelThreadActionProc \
(tclStubsPtr->tcl_ChannelThreadActionProc) /* 554 */
#endif
-/* Slot 555 is reserved */
-/* Slot 556 is reserved */
-/* Slot 557 is reserved */
-/* Slot 558 is reserved */
-/* Slot 559 is reserved */
-/* Slot 560 is reserved */
-/* Slot 561 is reserved */
-/* Slot 562 is reserved */
-/* Slot 563 is reserved */
-/* Slot 564 is reserved */
-/* Slot 565 is reserved */
-/* Slot 566 is reserved */
-/* Slot 567 is reserved */
-/* Slot 568 is reserved */
-/* Slot 569 is reserved */
-/* Slot 570 is reserved */
-/* Slot 571 is reserved */
-/* Slot 572 is reserved */
+#ifndef Tcl_NewBignumObj
+#define Tcl_NewBignumObj \
+ (tclStubsPtr->tcl_NewBignumObj) /* 555 */
+#endif
+#ifndef Tcl_DbNewBignumObj
+#define Tcl_DbNewBignumObj \
+ (tclStubsPtr->tcl_DbNewBignumObj) /* 556 */
+#endif
+#ifndef Tcl_SetBignumObj
+#define Tcl_SetBignumObj \
+ (tclStubsPtr->tcl_SetBignumObj) /* 557 */
+#endif
+#ifndef Tcl_GetBignumFromObj
+#define Tcl_GetBignumFromObj \
+ (tclStubsPtr->tcl_GetBignumFromObj) /* 558 */
+#endif
+#ifndef Tcl_TakeBignumFromObj
+#define Tcl_TakeBignumFromObj \
+ (tclStubsPtr->tcl_TakeBignumFromObj) /* 559 */
+#endif
+#ifndef Tcl_TruncateChannel
+#define Tcl_TruncateChannel \
+ (tclStubsPtr->tcl_TruncateChannel) /* 560 */
+#endif
+#ifndef Tcl_ChannelTruncateProc
+#define Tcl_ChannelTruncateProc \
+ (tclStubsPtr->tcl_ChannelTruncateProc) /* 561 */
+#endif
+#ifndef Tcl_SetChannelErrorInterp
+#define Tcl_SetChannelErrorInterp \
+ (tclStubsPtr->tcl_SetChannelErrorInterp) /* 562 */
+#endif
+#ifndef Tcl_GetChannelErrorInterp
+#define Tcl_GetChannelErrorInterp \
+ (tclStubsPtr->tcl_GetChannelErrorInterp) /* 563 */
+#endif
+#ifndef Tcl_SetChannelError
+#define Tcl_SetChannelError \
+ (tclStubsPtr->tcl_SetChannelError) /* 564 */
+#endif
+#ifndef Tcl_GetChannelError
+#define Tcl_GetChannelError \
+ (tclStubsPtr->tcl_GetChannelError) /* 565 */
+#endif
+#ifndef Tcl_InitBignumFromDouble
+#define Tcl_InitBignumFromDouble \
+ (tclStubsPtr->tcl_InitBignumFromDouble) /* 566 */
+#endif
+#ifndef Tcl_GetNamespaceUnknownHandler
+#define Tcl_GetNamespaceUnknownHandler \
+ (tclStubsPtr->tcl_GetNamespaceUnknownHandler) /* 567 */
+#endif
+#ifndef Tcl_SetNamespaceUnknownHandler
+#define Tcl_SetNamespaceUnknownHandler \
+ (tclStubsPtr->tcl_SetNamespaceUnknownHandler) /* 568 */
+#endif
+#ifndef Tcl_GetEncodingFromObj
+#define Tcl_GetEncodingFromObj \
+ (tclStubsPtr->tcl_GetEncodingFromObj) /* 569 */
+#endif
+#ifndef Tcl_GetEncodingSearchPath
+#define Tcl_GetEncodingSearchPath \
+ (tclStubsPtr->tcl_GetEncodingSearchPath) /* 570 */
+#endif
+#ifndef Tcl_SetEncodingSearchPath
+#define Tcl_SetEncodingSearchPath \
+ (tclStubsPtr->tcl_SetEncodingSearchPath) /* 571 */
+#endif
+#ifndef Tcl_GetEncodingNameFromEnvironment
+#define Tcl_GetEncodingNameFromEnvironment \
+ (tclStubsPtr->tcl_GetEncodingNameFromEnvironment) /* 572 */
+#endif
#ifndef Tcl_PkgRequireProc
#define Tcl_PkgRequireProc \
(tclStubsPtr->tcl_PkgRequireProc) /* 573 */
#endif
+#ifndef Tcl_AppendObjToErrorInfo
+#define Tcl_AppendObjToErrorInfo \
+ (tclStubsPtr->tcl_AppendObjToErrorInfo) /* 574 */
+#endif
+#ifndef Tcl_AppendLimitedToObj
+#define Tcl_AppendLimitedToObj \
+ (tclStubsPtr->tcl_AppendLimitedToObj) /* 575 */
+#endif
+#ifndef Tcl_Format
+#define Tcl_Format \
+ (tclStubsPtr->tcl_Format) /* 576 */
+#endif
+#ifndef Tcl_AppendFormatToObj
+#define Tcl_AppendFormatToObj \
+ (tclStubsPtr->tcl_AppendFormatToObj) /* 577 */
+#endif
+#ifndef Tcl_ObjPrintf
+#define Tcl_ObjPrintf \
+ (tclStubsPtr->tcl_ObjPrintf) /* 578 */
+#endif
+#ifndef Tcl_AppendPrintfToObj
+#define Tcl_AppendPrintfToObj \
+ (tclStubsPtr->tcl_AppendPrintfToObj) /* 579 */
+#endif
#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */
/* !END!: Do not edit above this line. */
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLIMPORT
+
#endif /* _TCLDECLS */
diff --git a/generic/tclDictObj.c b/generic/tclDictObj.c
new file mode 100644
index 0000000..06c5754
--- /dev/null
+++ b/generic/tclDictObj.c
@@ -0,0 +1,3176 @@
+/*
+ * tclDictObj.c --
+ *
+ * This file contains functions that implement the Tcl dict object type
+ * and its accessor command.
+ *
+ * Copyright (c) 2002 by Donal K. Fellows.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tclInt.h"
+#include "tommath.h"
+
+/*
+ * Forward declaration.
+ */
+struct Dict;
+
+/*
+ * Prototypes for functions defined later in this file:
+ */
+
+static void DeleteDict(struct Dict *dict);
+static int DictAppendCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int DictCreateCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int DictExistsCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int DictFilterCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int DictForCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int DictGetCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int DictIncrCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int DictInfoCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int DictKeysCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int DictLappendCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int DictMergeCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int DictRemoveCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int DictReplaceCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int DictSetCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int DictSizeCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int DictUnsetCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int DictUpdateCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int DictValuesCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static int DictWithCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+static void DupDictInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
+static void FreeDictInternalRep(Tcl_Obj *dictPtr);
+static void InvalidateDictChain(Tcl_Obj *dictObj);
+static int SetDictFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
+static void UpdateStringOfDict(Tcl_Obj *dictPtr);
+static Tcl_HashEntry * AllocChainEntry(Tcl_HashTable *tablePtr,void *keyPtr);
+static inline void InitChainTable(struct Dict *dict);
+static inline void DeleteChainTable(struct Dict *dict);
+static inline Tcl_HashEntry *CreateChainEntry(struct Dict *dict,
+ Tcl_Obj *keyPtr, int *newPtr);
+static inline int DeleteChainEntry(struct Dict *dict, Tcl_Obj *keyPtr);
+
+/*
+ * Table of dict subcommand names and implementations.
+ */
+
+static const EnsembleImplMap implementationMap[] = {
+ {"append", DictAppendCmd, TclCompileDictAppendCmd },
+ {"create", DictCreateCmd, NULL },
+ {"exists", DictExistsCmd, NULL },
+ {"filter", DictFilterCmd, NULL },
+ {"for", DictForCmd, TclCompileDictForCmd },
+ {"get", DictGetCmd, TclCompileDictGetCmd },
+ {"incr", DictIncrCmd, TclCompileDictIncrCmd },
+ {"info", DictInfoCmd, NULL },
+ {"keys", DictKeysCmd, NULL },
+ {"lappend", DictLappendCmd, TclCompileDictLappendCmd },
+ {"merge", DictMergeCmd, NULL },
+ {"remove", DictRemoveCmd, NULL },
+ {"replace", DictReplaceCmd, NULL },
+ {"set", DictSetCmd, TclCompileDictSetCmd },
+ {"size", DictSizeCmd, NULL },
+ {"unset", DictUnsetCmd, NULL },
+ {"update", DictUpdateCmd, TclCompileDictUpdateCmd },
+ {"values", DictValuesCmd, NULL },
+ {"with", DictWithCmd, NULL },
+ {NULL}
+};
+
+/*
+ * Internal representation of the entries in the hash table that backs a
+ * dictionary.
+ */
+
+typedef struct ChainEntry {
+ Tcl_HashEntry entry;
+ struct ChainEntry *prevPtr;
+ struct ChainEntry *nextPtr;
+} ChainEntry;
+
+/*
+ * Internal representation of a dictionary.
+ *
+ * The internal representation of a dictionary object is a hash table (with
+ * Tcl_Objs for both keys and values), a reference count and epoch number for
+ * detecting concurrent modifications of the dictionary, and a pointer to the
+ * parent object (used when invalidating string reps of pathed dictionary
+ * trees) which is NULL in normal use. The fact that hash tables know (with
+ * appropriate initialisation) already about objects makes key management /so/
+ * much easier!
+ *
+ * Reference counts are used to enable safe iteration across hashes while
+ * allowing the type of the containing object to be modified.
+ */
+
+typedef struct Dict {
+ Tcl_HashTable table; /* Object hash table to store mapping in. */
+ ChainEntry *entryChainHead; /* Linked list of all entries in the
+ * dictionary. Used for doing traversal of the
+ * entries in the order that they are
+ * created. */
+ ChainEntry *entryChainTail; /* Other end of linked list of all entries in
+ * the dictionary. Used for doing traversal of
+ * the entries in the order that they are
+ * created. */
+ int epoch; /* Epoch counter */
+ int refcount; /* Reference counter (see above) */
+ Tcl_Obj *chain; /* Linked list used for invalidating the
+ * string representations of updated nested
+ * dictionaries. */
+} Dict;
+
+/*
+ * The structure below defines the dictionary object type by means of
+ * functions that can be invoked by generic object code.
+ */
+
+Tcl_ObjType tclDictType = {
+ "dict",
+ FreeDictInternalRep, /* freeIntRepProc */
+ DupDictInternalRep, /* dupIntRepProc */
+ UpdateStringOfDict, /* updateStringProc */
+ SetDictFromAny /* setFromAnyProc */
+};
+
+/*
+ * The type of the specially adapted version of the Tcl_Obj*-containing hash
+ * table defined in the tclObj.c code. This version differs in that it
+ * allocates a bit more space in each hash entry in order to hold the pointers
+ * used to keep the hash entries in a linked list.
+ *
+ * Note that this type of hash table is *only* suitable for direct use in
+ * *this* file. Everything else should use the dict iterator API.
+ */
+
+static Tcl_HashKeyType chainHashType = {
+ TCL_HASH_KEY_TYPE_VERSION,
+ 0,
+ TclHashObjKey,
+ TclCompareObjKeys,
+ AllocChainEntry,
+ TclFreeObjEntry
+};
+
+/***** START OF FUNCTIONS IMPLEMENTING DICT CORE API *****/
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AllocChainEntry --
+ *
+ * Allocate space for a Tcl_HashEntry containing the Tcl_Obj * key, and
+ * which has a bit of extra space afterwards for storing pointers to the
+ * rest of the chain of entries (the extra pointers are left NULL).
+ *
+ * Results:
+ * The return value is a pointer to the created entry.
+ *
+ * Side effects:
+ * Increments the reference count on the object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_HashEntry *
+AllocChainEntry(
+ Tcl_HashTable *tablePtr,
+ void *keyPtr)
+{
+ Tcl_Obj *objPtr = keyPtr;
+ ChainEntry *cPtr;
+
+ cPtr = (ChainEntry *) ckalloc(sizeof(ChainEntry));
+ cPtr->entry.key.oneWordValue = (char *) objPtr;
+ Tcl_IncrRefCount(objPtr);
+ cPtr->entry.clientData = NULL;
+ cPtr->prevPtr = cPtr->nextPtr = NULL;
+
+ return &cPtr->entry;
+}
+
+/*
+ * Helper functions that disguise most of the details relating to how the
+ * linked list of hash entries is managed. In particular, these manage the
+ * creation of the table and initializing of the chain, the deletion of the
+ * table and chain, the adding of an entry to the chain, and the removal of an
+ * entry from the chain.
+ */
+
+static inline void
+InitChainTable(
+ Dict *dict)
+{
+ Tcl_InitCustomHashTable(&dict->table, TCL_CUSTOM_PTR_KEYS,
+ &chainHashType);
+ dict->entryChainHead = dict->entryChainTail = NULL;
+}
+
+static inline void
+DeleteChainTable(
+ Dict *dict)
+{
+ ChainEntry *cPtr;
+
+ for (cPtr=dict->entryChainHead ; cPtr!=NULL ; cPtr=cPtr->nextPtr) {
+ Tcl_Obj *valuePtr = Tcl_GetHashValue(&cPtr->entry);
+
+ TclDecrRefCount(valuePtr);
+ }
+ Tcl_DeleteHashTable(&dict->table);
+}
+
+static inline Tcl_HashEntry *
+CreateChainEntry(
+ Dict *dict,
+ Tcl_Obj *keyPtr,
+ int *newPtr)
+{
+ ChainEntry *cPtr = (ChainEntry *)
+ Tcl_CreateHashEntry(&dict->table, (char *) keyPtr, newPtr);
+
+ /*
+ * If this is a new entry in the hash table, stitch it into the chain.
+ */
+
+ if (*newPtr) {
+ cPtr->nextPtr = NULL;
+ if (dict->entryChainHead == NULL) {
+ cPtr->prevPtr = NULL;
+ dict->entryChainHead = cPtr;
+ dict->entryChainTail = cPtr;
+ } else {
+ cPtr->prevPtr = dict->entryChainTail;
+ dict->entryChainTail->nextPtr = cPtr;
+ dict->entryChainTail = cPtr;
+ }
+ }
+
+ return &cPtr->entry;
+}
+
+static inline int
+DeleteChainEntry(
+ Dict *dict,
+ Tcl_Obj *keyPtr)
+{
+ ChainEntry *cPtr = (ChainEntry *)
+ Tcl_FindHashEntry(&dict->table, (char *) keyPtr);
+
+ if (cPtr == NULL) {
+ return 0;
+ } else {
+ Tcl_Obj *valuePtr = Tcl_GetHashValue(&cPtr->entry);
+ TclDecrRefCount(valuePtr);
+ }
+
+ /*
+ * Unstitch from the chain.
+ */
+
+ if (cPtr->nextPtr) {
+ cPtr->nextPtr->prevPtr = cPtr->prevPtr;
+ } else {
+ dict->entryChainTail = cPtr->prevPtr;
+ }
+ if (cPtr->prevPtr) {
+ cPtr->prevPtr->nextPtr = cPtr->nextPtr;
+ } else {
+ dict->entryChainHead = cPtr->nextPtr;
+ }
+
+ Tcl_DeleteHashEntry(&cPtr->entry);
+ return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupDictInternalRep --
+ *
+ * Initialize the internal representation of a dictionary Tcl_Obj to a
+ * copy of the internal representation of an existing dictionary object.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * "srcPtr"s dictionary internal rep pointer should not be NULL and we
+ * assume it is not NULL. We set "copyPtr"s internal rep to a pointer to
+ * a newly allocated dictionary rep that, in turn, points to "srcPtr"s
+ * key and value objects. Those objects are not actually copied but are
+ * shared between "srcPtr" and "copyPtr". The ref count of each key and
+ * value object is incremented.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DupDictInternalRep(
+ Tcl_Obj *srcPtr,
+ Tcl_Obj *copyPtr)
+{
+ Dict *oldDict = srcPtr->internalRep.otherValuePtr;
+ Dict *newDict = (Dict *) ckalloc(sizeof(Dict));
+ ChainEntry *cPtr;
+
+ /*
+ * Copy values across from the old hash table.
+ */
+
+ InitChainTable(newDict);
+ for (cPtr=oldDict->entryChainHead ; cPtr!=NULL ; cPtr=cPtr->nextPtr) {
+ void *key = Tcl_GetHashKey(&oldDict->table, &cPtr->entry);
+ Tcl_Obj *valuePtr = Tcl_GetHashValue(&cPtr->entry);
+ int n;
+ Tcl_HashEntry *hPtr = CreateChainEntry(newDict, key, &n);
+
+ /*
+ * Fill in the contents.
+ */
+
+ Tcl_SetHashValue(hPtr, (ClientData) valuePtr);
+ Tcl_IncrRefCount(valuePtr);
+ }
+
+ /*
+ * Initialise other fields.
+ */
+
+ newDict->epoch = 0;
+ newDict->chain = NULL;
+ newDict->refcount = 1;
+
+ /*
+ * Store in the object.
+ */
+
+ copyPtr->internalRep.otherValuePtr = newDict;
+ copyPtr->typePtr = &tclDictType;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeDictInternalRep --
+ *
+ * Deallocate the storage associated with a dictionary object's internal
+ * representation.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Frees the memory holding the dictionary's internal hash table unless
+ * it is locked by an iteration going over it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeDictInternalRep(
+ Tcl_Obj *dictPtr)
+{
+ Dict *dict = dictPtr->internalRep.otherValuePtr;
+
+ --dict->refcount;
+ if (dict->refcount <= 0) {
+ DeleteDict(dict);
+ }
+
+ dictPtr->internalRep.otherValuePtr = NULL; /* Belt and braces! */
+ dictPtr->typePtr = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteDict --
+ *
+ * Delete the structure that is used to implement a dictionary's internal
+ * representation. Called when either the dictionary object loses its
+ * internal representation or when the last iteration over the dictionary
+ * completes.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Decrements the reference count of all key and value objects in the
+ * dictionary, which may free them.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DeleteDict(
+ Dict *dict)
+{
+ DeleteChainTable(dict);
+ ckfree((char *) dict);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateStringOfDict --
+ *
+ * Update the string representation for a dictionary object. Note: This
+ * function does not invalidate an existing old string rep so storage
+ * will be lost if this has not already been done. This code is based on
+ * UpdateStringOfList in tclListObj.c
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The object's string is set to a valid string that results from the
+ * dict-to-string conversion. This string will be empty if the dictionary
+ * has no key/value pairs. The dictionary internal representation should
+ * not be NULL and we assume it is not NULL.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateStringOfDict(
+ Tcl_Obj *dictPtr)
+{
+#define LOCAL_SIZE 20
+ int localFlags[LOCAL_SIZE], *flagPtr = NULL;
+ Dict *dict = dictPtr->internalRep.otherValuePtr;
+ ChainEntry *cPtr;
+ Tcl_Obj *keyPtr, *valuePtr;
+ int i, length, bytesNeeded = 0;
+ char *elem, *dst;
+ const int maxFlags = UINT_MAX / sizeof(int);
+
+ /*
+ * This field is the most useful one in the whole hash structure, and it
+ * is not exposed by any API function...
+ */
+
+ int numElems = dict->table.numEntries * 2;
+
+ /* Handle empty list case first, simplifies what follows */
+ if (numElems == 0) {
+ dictPtr->bytes = tclEmptyStringRep;
+ dictPtr->length = 0;
+ return;
+ }
+
+ /*
+ * Pass 1: estimate space, gather flags.
+ */
+
+ if (numElems <= LOCAL_SIZE) {
+ flagPtr = localFlags;
+ } else if (numElems > maxFlags) {
+ Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
+ } else {
+ flagPtr = (int *) ckalloc((unsigned) numElems*sizeof(int));
+ }
+ for (i=0,cPtr=dict->entryChainHead; i<numElems; i+=2,cPtr=cPtr->nextPtr) {
+ /*
+ * Assume that cPtr is never NULL since we know the number of array
+ * elements already.
+ */
+
+ flagPtr[i] = ( i ? TCL_DONT_QUOTE_HASH : 0 );
+ keyPtr = (Tcl_Obj *) Tcl_GetHashKey(&dict->table, &cPtr->entry);
+ elem = TclGetStringFromObj(keyPtr, &length);
+ bytesNeeded += TclScanElement(elem, length, flagPtr+i);
+ if (bytesNeeded < 0) {
+ Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
+ }
+
+ flagPtr[i+1] = TCL_DONT_QUOTE_HASH;
+ valuePtr = Tcl_GetHashValue(&cPtr->entry);
+ elem = TclGetStringFromObj(valuePtr, &length);
+ bytesNeeded += TclScanElement(elem, length, flagPtr+i+1);
+ if (bytesNeeded < 0) {
+ Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
+ }
+ }
+ if (bytesNeeded > INT_MAX - numElems + 1) {
+ Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
+ }
+ bytesNeeded += numElems;
+
+ /*
+ * Pass 2: copy into string rep buffer.
+ */
+
+ dictPtr->length = bytesNeeded - 1;
+ dictPtr->bytes = ckalloc((unsigned) bytesNeeded);
+ dst = dictPtr->bytes;
+ for (i=0,cPtr=dict->entryChainHead; i<numElems; i+=2,cPtr=cPtr->nextPtr) {
+ flagPtr[i] |= ( i ? TCL_DONT_QUOTE_HASH : 0 );
+ keyPtr = (Tcl_Obj *) Tcl_GetHashKey(&dict->table, &cPtr->entry);
+ elem = TclGetStringFromObj(keyPtr, &length);
+ dst += TclConvertElement(elem, length, dst, flagPtr[i]);
+ *dst++ = ' ';
+
+ flagPtr[i+1] |= TCL_DONT_QUOTE_HASH;
+ valuePtr = Tcl_GetHashValue(&cPtr->entry);
+ elem = TclGetStringFromObj(valuePtr, &length);
+ dst += TclConvertElement(elem, length, dst, flagPtr[i+1]);
+ *dst++ = ' ';
+ }
+ dictPtr->bytes[dictPtr->length] = '\0';
+
+ if (flagPtr != localFlags) {
+ ckfree((char *) flagPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetDictFromAny --
+ *
+ * Convert a non-dictionary object into a dictionary object. This code is
+ * very closely related to SetListFromAny in tclListObj.c but does not
+ * actually guarantee that a dictionary object will have a string rep (as
+ * conversions from lists are handled with a special case.)
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * If the string can be converted, it loses any old internal
+ * representation that it had and gains a dictionary's internalRep.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetDictFromAny(
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr)
+{
+ Tcl_HashEntry *hPtr;
+ int isNew, result;
+ Dict *dict = (Dict *) ckalloc(sizeof(Dict));
+
+ InitChainTable(dict);
+
+ /*
+ * Since lists and dictionaries have very closely-related string
+ * representations (i.e. the same parsing code) we can safely special-case
+ * the conversion from lists to dictionaries.
+ */
+
+ if (objPtr->typePtr == &tclListType) {
+ int objc, i;
+ Tcl_Obj **objv;
+
+ /* Cannot fail, we already know the Tcl_ObjType is "list". */
+ TclListObjGetElements(NULL, objPtr, &objc, &objv);
+ if (objc & 1) {
+ goto missingValue;
+ }
+
+ for (i=0 ; i<objc ; i+=2) {
+
+ /* Store key and value in the hash table we're building. */
+ hPtr = CreateChainEntry(dict, objv[i], &isNew);
+ if (!isNew) {
+ Tcl_Obj *discardedValue = Tcl_GetHashValue(hPtr);
+
+ /*
+ * Not really a well-formed dictionary as there are duplicate
+ * keys, so better get the string rep here so that we can
+ * convert back.
+ */
+
+ (void) Tcl_GetString(objPtr);
+
+ TclDecrRefCount(discardedValue);
+ }
+ Tcl_SetHashValue(hPtr, objv[i+1]);
+ Tcl_IncrRefCount(objv[i+1]); /* Since hash now holds ref to it */
+ }
+ } else {
+ int length;
+ const char *nextElem = TclGetStringFromObj(objPtr, &length);
+ const char *limit = (nextElem + length);
+
+ while (nextElem < limit) {
+ Tcl_Obj *keyPtr, *valuePtr;
+ const char *elemStart;
+ int elemSize, literal;
+
+ result = TclFindElement(interp, nextElem, (limit - nextElem),
+ &elemStart, &nextElem, &elemSize, &literal);
+ if (result != TCL_OK) {
+ goto errorExit;
+ }
+ if (elemStart == limit) {
+ break;
+ }
+ if (nextElem == limit) {
+ goto missingValue;
+ }
+
+ if (literal) {
+ TclNewStringObj(keyPtr, elemStart, elemSize);
+ } else {
+ /* Avoid double copy */
+ TclNewObj(keyPtr);
+ keyPtr->bytes = ckalloc((unsigned) elemSize + 1);
+ keyPtr->length = TclCopyAndCollapse(elemSize, elemStart,
+ keyPtr->bytes);
+ }
+
+ result = TclFindElement(interp, nextElem, (limit - nextElem),
+ &elemStart, &nextElem, &elemSize, &literal);
+ if (result != TCL_OK) {
+ TclDecrRefCount(keyPtr);
+ goto errorExit;
+ }
+
+ if (literal) {
+ TclNewStringObj(valuePtr, elemStart, elemSize);
+ } else {
+ /* Avoid double copy */
+ TclNewObj(valuePtr);
+ valuePtr->bytes = ckalloc((unsigned) elemSize + 1);
+ valuePtr->length = TclCopyAndCollapse(elemSize, elemStart,
+ valuePtr->bytes);
+ }
+
+ /* Store key and value in the hash table we're building. */
+ hPtr = CreateChainEntry(dict, keyPtr, &isNew);
+ if (!isNew) {
+ Tcl_Obj *discardedValue = Tcl_GetHashValue(hPtr);
+
+ TclDecrRefCount(keyPtr);
+ TclDecrRefCount(discardedValue);
+ }
+ Tcl_SetHashValue(hPtr, valuePtr);
+ Tcl_IncrRefCount(valuePtr); /* since hash now holds ref to it */
+ }
+ }
+
+ /*
+ * Free the old internalRep before setting the new one. We do this as late
+ * as possible to allow the conversion code, in particular
+ * Tcl_GetStringFromObj, to use that old internalRep.
+ */
+
+ TclFreeIntRep(objPtr);
+ dict->epoch = 0;
+ dict->chain = NULL;
+ dict->refcount = 1;
+ objPtr->internalRep.otherValuePtr = dict;
+ objPtr->typePtr = &tclDictType;
+ return TCL_OK;
+
+ missingValue:
+ if (interp != NULL) {
+ Tcl_SetResult(interp, "missing value to go with key", TCL_STATIC);
+ }
+ result = TCL_ERROR;
+
+ errorExit:
+ DeleteChainTable(dict);
+ ckfree((char *) dict);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclTraceDictPath --
+ *
+ * Trace through a tree of dictionaries using the array of keys given. If
+ * the flags argument has the DICT_PATH_UPDATE flag is set, a
+ * backward-pointing chain of dictionaries is also built (in the Dict's
+ * chain field) and the chained dictionaries are made into unshared
+ * dictionaries (if they aren't already.)
+ *
+ * Results:
+ * The object at the end of the path, or NULL if there was an error. Note
+ * that this it is an error for an intermediate dictionary on the path to
+ * not exist. If the flags argument has the DICT_PATH_EXISTS set, a
+ * non-existent path gives a DICT_PATH_NON_EXISTENT result.
+ *
+ * Side effects:
+ * If the flags argument is zero or DICT_PATH_EXISTS, there are no side
+ * effects (other than potential conversion of objects to dictionaries.)
+ * If the flags argument is DICT_PATH_UPDATE, the following additional
+ * side effects occur. Shared dictionaries along the path are converted
+ * into unshared objects, and a backward-pointing chain is built using
+ * the chain fields of the dictionaries (for easy invalidation of string
+ * representations using InvalidateDictChain). If the flags argument has
+ * the DICT_PATH_CREATE bits set (and not the DICT_PATH_EXISTS bit),
+ * non-existant keys will be inserted with a value of an empty
+ * dictionary, resulting in the path being built.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclTraceDictPath(
+ Tcl_Interp *interp,
+ Tcl_Obj *dictPtr,
+ int keyc,
+ Tcl_Obj *const keyv[],
+ int flags)
+{
+ Dict *dict, *newDict;
+ int i;
+
+ if (dictPtr->typePtr != &tclDictType) {
+ if (SetDictFromAny(interp, dictPtr) != TCL_OK) {
+ return NULL;
+ }
+ }
+ dict = dictPtr->internalRep.otherValuePtr;
+ if (flags & DICT_PATH_UPDATE) {
+ dict->chain = NULL;
+ }
+
+ for (i=0 ; i<keyc ; i++) {
+ Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&dict->table, (char *)keyv[i]);
+ Tcl_Obj *tmpObj;
+
+ if (hPtr == NULL) {
+ int isNew; /* Dummy */
+
+ if (flags & DICT_PATH_EXISTS) {
+ return DICT_PATH_NON_EXISTENT;
+ }
+ if ((flags & DICT_PATH_CREATE) != DICT_PATH_CREATE) {
+ if (interp != NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "key \"", TclGetString(keyv[i]),
+ "\" not known in dictionary", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "DICT",
+ TclGetString(keyv[i]), NULL);
+ }
+ return NULL;
+ }
+
+ /*
+ * The next line should always set isNew to 1.
+ */
+
+ hPtr = CreateChainEntry(dict, keyv[i], &isNew);
+ tmpObj = Tcl_NewDictObj();
+ Tcl_IncrRefCount(tmpObj);
+ Tcl_SetHashValue(hPtr, tmpObj);
+ } else {
+ tmpObj = Tcl_GetHashValue(hPtr);
+ if (tmpObj->typePtr != &tclDictType) {
+ if (SetDictFromAny(interp, tmpObj) != TCL_OK) {
+ return NULL;
+ }
+ }
+ }
+
+ newDict = tmpObj->internalRep.otherValuePtr;
+ if (flags & DICT_PATH_UPDATE) {
+ if (Tcl_IsShared(tmpObj)) {
+ TclDecrRefCount(tmpObj);
+ tmpObj = Tcl_DuplicateObj(tmpObj);
+ Tcl_IncrRefCount(tmpObj);
+ Tcl_SetHashValue(hPtr, (ClientData) tmpObj);
+ dict->epoch++;
+ newDict = tmpObj->internalRep.otherValuePtr;
+ }
+
+ newDict->chain = dictPtr;
+ }
+ dict = newDict;
+ dictPtr = tmpObj;
+ }
+ return dictPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InvalidateDictChain --
+ *
+ * Go through a dictionary chain (built by an updating invokation of
+ * TclTraceDictPath) and invalidate the string representations of all the
+ * dictionaries on the chain.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * String reps are invalidated and epoch counters (for detecting illegal
+ * concurrent modifications) are updated through the chain of updated
+ * dictionaries.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InvalidateDictChain(
+ Tcl_Obj *dictObj)
+{
+ Dict *dict = dictObj->internalRep.otherValuePtr;
+
+ do {
+ Tcl_InvalidateStringRep(dictObj);
+ dict->epoch++;
+ dictObj = dict->chain;
+ if (dictObj == NULL) {
+ break;
+ }
+ dict->chain = NULL;
+ dict = dictObj->internalRep.otherValuePtr;
+ } while (dict != NULL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DictObjPut --
+ *
+ * Add a key,value pair to a dictionary, or update the value for a key if
+ * that key already has a mapping in the dictionary.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * The object pointed to by dictPtr is converted to a dictionary if it is
+ * not already one, and any string representation that it has is
+ * invalidated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_DictObjPut(
+ Tcl_Interp *interp,
+ Tcl_Obj *dictPtr,
+ Tcl_Obj *keyPtr,
+ Tcl_Obj *valuePtr)
+{
+ Dict *dict;
+ Tcl_HashEntry *hPtr;
+ int isNew;
+
+ if (Tcl_IsShared(dictPtr)) {
+ Tcl_Panic("%s called with shared object", "Tcl_DictObjPut");
+ }
+
+ if (dictPtr->typePtr != &tclDictType) {
+ int result = SetDictFromAny(interp, dictPtr);
+
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
+
+ if (dictPtr->bytes != NULL) {
+ Tcl_InvalidateStringRep(dictPtr);
+ }
+ dict = dictPtr->internalRep.otherValuePtr;
+ hPtr = CreateChainEntry(dict, keyPtr, &isNew);
+ Tcl_IncrRefCount(valuePtr);
+ if (!isNew) {
+ Tcl_Obj *oldValuePtr = Tcl_GetHashValue(hPtr);
+
+ TclDecrRefCount(oldValuePtr);
+ }
+ Tcl_SetHashValue(hPtr, valuePtr);
+ dict->epoch++;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DictObjGet --
+ *
+ * Given a key, get its value from the dictionary (or NULL if key is not
+ * found in dictionary.)
+ *
+ * Results:
+ * A standard Tcl result. The variable pointed to by valuePtrPtr is
+ * updated with the value for the key. Note that it is not an error for
+ * the key to have no mapping in the dictionary.
+ *
+ * Side effects:
+ * The object pointed to by dictPtr is converted to a dictionary if it is
+ * not already one.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_DictObjGet(
+ Tcl_Interp *interp,
+ Tcl_Obj *dictPtr,
+ Tcl_Obj *keyPtr,
+ Tcl_Obj **valuePtrPtr)
+{
+ Dict *dict;
+ Tcl_HashEntry *hPtr;
+
+ if (dictPtr->typePtr != &tclDictType) {
+ int result = SetDictFromAny(interp, dictPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
+
+ dict = dictPtr->internalRep.otherValuePtr;
+ hPtr = Tcl_FindHashEntry(&dict->table, (char *) keyPtr);
+ if (hPtr == NULL) {
+ *valuePtrPtr = NULL;
+ } else {
+ *valuePtrPtr = Tcl_GetHashValue(hPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DictObjRemove --
+ *
+ * Remove the key,value pair with the given key from the dictionary; the
+ * key does not need to be present in the dictionary.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * The object pointed to by dictPtr is converted to a dictionary if it is
+ * not already one, and any string representation that it has is
+ * invalidated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_DictObjRemove(
+ Tcl_Interp *interp,
+ Tcl_Obj *dictPtr,
+ Tcl_Obj *keyPtr)
+{
+ Dict *dict;
+
+ if (Tcl_IsShared(dictPtr)) {
+ Tcl_Panic("%s called with shared object", "Tcl_DictObjRemove");
+ }
+
+ if (dictPtr->typePtr != &tclDictType) {
+ int result = SetDictFromAny(interp, dictPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
+
+ if (dictPtr->bytes != NULL) {
+ Tcl_InvalidateStringRep(dictPtr);
+ }
+ dict = dictPtr->internalRep.otherValuePtr;
+ if (DeleteChainEntry(dict, keyPtr)) {
+ dict->epoch++;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DictObjSize --
+ *
+ * How many key,value pairs are there in the dictionary?
+ *
+ * Results:
+ * A standard Tcl result. Updates the variable pointed to by sizePtr with
+ * the number of key,value pairs in the dictionary.
+ *
+ * Side effects:
+ * The dictPtr object is converted to a dictionary type if it is not a
+ * dictionary already.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_DictObjSize(
+ Tcl_Interp *interp,
+ Tcl_Obj *dictPtr,
+ int *sizePtr)
+{
+ Dict *dict;
+
+ if (dictPtr->typePtr != &tclDictType) {
+ int result = SetDictFromAny(interp, dictPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
+
+ dict = dictPtr->internalRep.otherValuePtr;
+ *sizePtr = dict->table.numEntries;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DictObjFirst --
+ *
+ * Start a traversal of the dictionary. Caller must supply the search
+ * context, pointers for returning key and value, and a pointer to allow
+ * indication of whether the dictionary has been traversed (i.e. the
+ * dictionary is empty). The order of traversal is undefined.
+ *
+ * Results:
+ * A standard Tcl result. Updates the variables pointed to by keyPtrPtr,
+ * valuePtrPtr and donePtr. Either of keyPtrPtr and valuePtrPtr may be
+ * NULL, in which case the key/value is not made available to the caller.
+ *
+ * Side effects:
+ * The dictPtr object is converted to a dictionary type if it is not a
+ * dictionary already. The search context is initialised if the search
+ * has not finished. The dictionary's internal rep is Tcl_Preserve()d if
+ * the dictionary has at least one element.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_DictObjFirst(
+ Tcl_Interp *interp, /* For error messages, or NULL if no error
+ * messages desired. */
+ Tcl_Obj *dictPtr, /* Dictionary to traverse. */
+ Tcl_DictSearch *searchPtr, /* Pointer to a dict search context. */
+ Tcl_Obj **keyPtrPtr, /* Pointer to a variable to have the first key
+ * written into, or NULL. */
+ Tcl_Obj **valuePtrPtr, /* Pointer to a variable to have the first
+ * value written into, or NULL.*/
+ int *donePtr) /* Pointer to a variable which will have a 1
+ * written into when there are no further
+ * values in the dictionary, or a 0
+ * otherwise. */
+{
+ Dict *dict;
+ ChainEntry *cPtr;
+
+ if (dictPtr->typePtr != &tclDictType) {
+ int result = SetDictFromAny(interp, dictPtr);
+
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
+
+ dict = dictPtr->internalRep.otherValuePtr;
+ cPtr = dict->entryChainHead;
+ if (cPtr == NULL) {
+ searchPtr->epoch = -1;
+ *donePtr = 1;
+ } else {
+ *donePtr = 0;
+ searchPtr->dictionaryPtr = (Tcl_Dict) dict;
+ searchPtr->epoch = dict->epoch;
+ searchPtr->next = cPtr->nextPtr;
+ dict->refcount++;
+ if (keyPtrPtr != NULL) {
+ *keyPtrPtr = (Tcl_Obj *) Tcl_GetHashKey(&dict->table,
+ &cPtr->entry);
+ }
+ if (valuePtrPtr != NULL) {
+ *valuePtrPtr = Tcl_GetHashValue(&cPtr->entry);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DictObjNext --
+ *
+ * Continue a traversal of a dictionary previously started with
+ * Tcl_DictObjFirst. This function is safe against concurrent
+ * modification of the underlying object (including type shimmering),
+ * treating such situations as if the search has terminated, though it is
+ * up to the caller to ensure that the object itself is not disposed
+ * until the search has finished. It is _not_ safe against modifications
+ * from other threads.
+ *
+ * Results:
+ * Updates the variables pointed to by keyPtrPtr, valuePtrPtr and
+ * donePtr. Either of keyPtrPtr and valuePtrPtr may be NULL, in which
+ * case the key/value is not made available to the caller.
+ *
+ * Side effects:
+ * Removes a reference to the dictionary's internal rep if the search
+ * terminates.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DictObjNext(
+ Tcl_DictSearch *searchPtr, /* Pointer to a hash search context. */
+ Tcl_Obj **keyPtrPtr, /* Pointer to a variable to have the first key
+ * written into, or NULL. */
+ Tcl_Obj **valuePtrPtr, /* Pointer to a variable to have the first
+ * value written into, or NULL.*/
+ int *donePtr) /* Pointer to a variable which will have a 1
+ * written into when there are no further
+ * values in the dictionary, or a 0
+ * otherwise. */
+{
+ ChainEntry *cPtr;
+
+ /*
+ * If the searh is done; we do no work.
+ */
+
+ if (searchPtr->epoch == -1) {
+ *donePtr = 1;
+ return;
+ }
+
+ /*
+ * Bail out if the dictionary has had any elements added, modified or
+ * removed. This *shouldn't* happen, but...
+ */
+
+ if (((Dict *)searchPtr->dictionaryPtr)->epoch != searchPtr->epoch) {
+ Tcl_Panic("concurrent dictionary modification and search");
+ }
+
+ cPtr = searchPtr->next;
+ if (cPtr == NULL) {
+ Tcl_DictObjDone(searchPtr);
+ *donePtr = 1;
+ return;
+ }
+
+ searchPtr->next = cPtr->nextPtr;
+ *donePtr = 0;
+ if (keyPtrPtr != NULL) {
+ *keyPtrPtr = (Tcl_Obj *) Tcl_GetHashKey(
+ &((Dict *)searchPtr->dictionaryPtr)->table, &cPtr->entry);
+ }
+ if (valuePtrPtr != NULL) {
+ *valuePtrPtr = Tcl_GetHashValue(&cPtr->entry);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DictObjDone --
+ *
+ * Call this if you want to stop a search before you reach the end of the
+ * dictionary (e.g. because of abnormal termination of the search). It
+ * need not be used if the search reaches its natural end (i.e. if either
+ * Tcl_DictObjFirst or Tcl_DictObjNext sets its donePtr variable to 1).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Removes a reference to the dictionary's internal rep.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DictObjDone(
+ Tcl_DictSearch *searchPtr) /* Pointer to a hash search context. */
+{
+ Dict *dict;
+
+ if (searchPtr->epoch != -1) {
+ searchPtr->epoch = -1;
+ dict = (Dict *) searchPtr->dictionaryPtr;
+ dict->refcount--;
+ if (dict->refcount <= 0) {
+ DeleteDict(dict);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DictObjPutKeyList --
+ *
+ * Add a key...key,value pair to a dictionary tree. The main dictionary
+ * value must not be shared, though sub-dictionaries may be. All
+ * intermediate dictionaries on the path must exist.
+ *
+ * Results:
+ * A standard Tcl result. Note that in the error case, a message is left
+ * in interp unless that is NULL.
+ *
+ * Side effects:
+ * If the dictionary and any of its sub-dictionaries on the path have
+ * string representations, these are invalidated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_DictObjPutKeyList(
+ Tcl_Interp *interp,
+ Tcl_Obj *dictPtr,
+ int keyc,
+ Tcl_Obj *const keyv[],
+ Tcl_Obj *valuePtr)
+{
+ Dict *dict;
+ Tcl_HashEntry *hPtr;
+ int isNew;
+
+ if (Tcl_IsShared(dictPtr)) {
+ Tcl_Panic("%s called with shared object", "Tcl_DictObjPutKeyList");
+ }
+ if (keyc < 1) {
+ Tcl_Panic("%s called with empty key list", "Tcl_DictObjPutKeyList");
+ }
+
+ dictPtr = TclTraceDictPath(interp, dictPtr, keyc-1,keyv, DICT_PATH_CREATE);
+ if (dictPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ dict = dictPtr->internalRep.otherValuePtr;
+ hPtr = CreateChainEntry(dict, keyv[keyc-1], &isNew);
+ Tcl_IncrRefCount(valuePtr);
+ if (!isNew) {
+ Tcl_Obj *oldValuePtr = Tcl_GetHashValue(hPtr);
+ TclDecrRefCount(oldValuePtr);
+ }
+ Tcl_SetHashValue(hPtr, valuePtr);
+ InvalidateDictChain(dictPtr);
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DictObjRemoveKeyList --
+ *
+ * Remove a key...key,value pair from a dictionary tree (the value
+ * removed is implicit in the key path). The main dictionary value must
+ * not be shared, though sub-dictionaries may be. It is not an error if
+ * there is no value associated with the given key list, but all
+ * intermediate dictionaries on the key path must exist.
+ *
+ * Results:
+ * A standard Tcl result. Note that in the error case, a message is left
+ * in interp unless that is NULL.
+ *
+ * Side effects:
+ * If the dictionary and any of its sub-dictionaries on the key path have
+ * string representations, these are invalidated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_DictObjRemoveKeyList(
+ Tcl_Interp *interp,
+ Tcl_Obj *dictPtr,
+ int keyc,
+ Tcl_Obj *const keyv[])
+{
+ Dict *dict;
+
+ if (Tcl_IsShared(dictPtr)) {
+ Tcl_Panic("%s called with shared object", "Tcl_DictObjRemoveKeyList");
+ }
+ if (keyc < 1) {
+ Tcl_Panic("%s called with empty key list", "Tcl_DictObjRemoveKeyList");
+ }
+
+ dictPtr = TclTraceDictPath(interp, dictPtr, keyc-1,keyv, DICT_PATH_UPDATE);
+ if (dictPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ dict = dictPtr->internalRep.otherValuePtr;
+ DeleteChainEntry(dict, keyv[keyc-1]);
+ InvalidateDictChain(dictPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_NewDictObj --
+ *
+ * This function is normally called when not debugging: i.e., when
+ * TCL_MEM_DEBUG is not defined. It creates a new dict object without any
+ * content.
+ *
+ * When TCL_MEM_DEBUG is defined, this function just returns the result
+ * of calling the debugging version Tcl_DbNewDictObj.
+ *
+ * Results:
+ * A new dict object is returned; it has no keys defined in it. The new
+ * object's string representation is left NULL, and the ref count of the
+ * object is 0.
+ *
+ * Side Effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tcl_NewDictObj(void)
+{
+#ifdef TCL_MEM_DEBUG
+ return Tcl_DbNewDictObj("unknown", 0);
+#else /* !TCL_MEM_DEBUG */
+
+ Tcl_Obj *dictPtr;
+ Dict *dict;
+
+ TclNewObj(dictPtr);
+ Tcl_InvalidateStringRep(dictPtr);
+ dict = (Dict *) ckalloc(sizeof(Dict));
+ InitChainTable(dict);
+ dict->epoch = 0;
+ dict->chain = NULL;
+ dict->refcount = 1;
+ dictPtr->internalRep.otherValuePtr = dict;
+ dictPtr->typePtr = &tclDictType;
+ return dictPtr;
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DbNewDictObj --
+ *
+ * This function is normally called when debugging: i.e., when
+ * TCL_MEM_DEBUG is defined. It creates new dict objects. It is the same
+ * as the Tcl_NewDictObj function above except that it calls
+ * Tcl_DbCkalloc directly with the file name and line number from its
+ * caller. This simplifies debugging since then the [memory active]
+ * command will report the correct file name and line number when
+ * reporting objects that haven't been freed.
+ *
+ * When TCL_MEM_DEBUG is not defined, this function just returns the
+ * result of calling Tcl_NewDictObj.
+ *
+ * Results:
+ * A new dict object is returned; it has no keys defined in it. The new
+ * object's string representation is left NULL, and the ref count of the
+ * object is 0.
+ *
+ * Side Effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tcl_DbNewDictObj(
+ const char *file,
+ int line)
+{
+#ifdef TCL_MEM_DEBUG
+ Tcl_Obj *dictPtr;
+ Dict *dict;
+
+ TclDbNewObj(dictPtr, file, line);
+ Tcl_InvalidateStringRep(dictPtr);
+ dict = (Dict *) ckalloc(sizeof(Dict));
+ InitChainTable(dict);
+ dict->epoch = 0;
+ dict->chain = NULL;
+ dict->refcount = 1;
+ dictPtr->internalRep.otherValuePtr = dict;
+ dictPtr->typePtr = &tclDictType;
+ return dictPtr;
+#else /* !TCL_MEM_DEBUG */
+ return Tcl_NewDictObj();
+#endif
+}
+
+/***** START OF FUNCTIONS IMPLEMENTING TCL COMMANDS *****/
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictCreateCmd --
+ *
+ * This function implements the "dict create" Tcl command. See the user
+ * documentation for details on what it does, and TIP#111 for the formal
+ * specification.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictCreateCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Tcl_Obj *dictObj;
+ int i;
+
+ /*
+ * Must have an even number of arguments; note that number of preceding
+ * arguments (i.e. "dict create" is also even, which makes this much
+ * easier.)
+ */
+
+ if ((objc & 1) == 0) {
+ Tcl_WrongNumArgs(interp, 1, objv, "?key value ...?");
+ return TCL_ERROR;
+ }
+
+ dictObj = Tcl_NewDictObj();
+ for (i=1 ; i<objc ; i+=2) {
+ /*
+ * The next command is assumed to never fail...
+ */
+ Tcl_DictObjPut(interp, dictObj, objv[i], objv[i+1]);
+ }
+ Tcl_SetObjResult(interp, dictObj);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictGetCmd --
+ *
+ * This function implements the "dict get" Tcl command. See the user
+ * documentation for details on what it does, and TIP#111 for the formal
+ * specification.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictGetCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Tcl_Obj *dictPtr, *valuePtr = NULL;
+ int result;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "dictionary ?key key ...?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Test for the special case of no keys, which returns a *list* of all
+ * key,value pairs. We produce a copy here because that makes subsequent
+ * list handling more efficient.
+ */
+
+ if (objc == 2) {
+ Tcl_Obj *keyPtr, *listPtr;
+ Tcl_DictSearch search;
+ int done;
+
+ result = Tcl_DictObjFirst(interp, objv[1], &search,
+ &keyPtr, &valuePtr, &done);
+ if (result != TCL_OK) {
+ return result;
+ }
+ listPtr = Tcl_NewListObj(0, NULL);
+ while (!done) {
+ /*
+ * Assume these won't fail as we have complete control over the
+ * types of things here.
+ */
+
+ Tcl_ListObjAppendElement(interp, listPtr, keyPtr);
+ Tcl_ListObjAppendElement(interp, listPtr, valuePtr);
+
+ Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done);
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+ }
+
+ /*
+ * Loop through the list of keys, looking up the key at the current index
+ * in the current dictionary each time. Once we've done the lookup, we set
+ * the current dictionary to be the value we looked up (in case the value
+ * was not the last one and we are going through a chain of searches.)
+ * Note that this loop always executes at least once.
+ */
+
+ dictPtr = TclTraceDictPath(interp, objv[1], objc-3,objv+2, DICT_PATH_READ);
+ if (dictPtr == NULL) {
+ return TCL_ERROR;
+ }
+ result = Tcl_DictObjGet(interp, dictPtr, objv[objc-1], &valuePtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ if (valuePtr == NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "key \"", TclGetString(objv[objc-1]),
+ "\" not known in dictionary", NULL);
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, valuePtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictReplaceCmd --
+ *
+ * This function implements the "dict replace" Tcl command. See the user
+ * documentation for details on what it does, and TIP#111 for the formal
+ * specification.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictReplaceCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Tcl_Obj *dictPtr;
+ int i, result;
+ int allocatedDict = 0;
+
+ if ((objc < 2) || (objc & 1)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "dictionary ?key value ...?");
+ return TCL_ERROR;
+ }
+
+ dictPtr = objv[1];
+ if (Tcl_IsShared(dictPtr)) {
+ dictPtr = Tcl_DuplicateObj(dictPtr);
+ allocatedDict = 1;
+ }
+ for (i=2 ; i<objc ; i+=2) {
+ result = Tcl_DictObjPut(interp, dictPtr, objv[i], objv[i+1]);
+ if (result != TCL_OK) {
+ if (allocatedDict) {
+ TclDecrRefCount(dictPtr);
+ }
+ return TCL_ERROR;
+ }
+ }
+ Tcl_SetObjResult(interp, dictPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictRemoveCmd --
+ *
+ * This function implements the "dict remove" Tcl command. See the user
+ * documentation for details on what it does, and TIP#111 for the formal
+ * specification.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictRemoveCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Tcl_Obj *dictPtr;
+ int i, result;
+ int allocatedDict = 0;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "dictionary ?key ...?");
+ return TCL_ERROR;
+ }
+
+ dictPtr = objv[1];
+ if (Tcl_IsShared(dictPtr)) {
+ dictPtr = Tcl_DuplicateObj(dictPtr);
+ allocatedDict = 1;
+ }
+ for (i=2 ; i<objc ; i++) {
+ result = Tcl_DictObjRemove(interp, dictPtr, objv[i]);
+ if (result != TCL_OK) {
+ if (allocatedDict) {
+ TclDecrRefCount(dictPtr);
+ }
+ return TCL_ERROR;
+ }
+ }
+ Tcl_SetObjResult(interp, dictPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictMergeCmd --
+ *
+ * This function implements the "dict merge" Tcl command. See the user
+ * documentation for details on what it does, and TIP#163 for the formal
+ * specification.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictMergeCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Tcl_Obj *targetObj, *keyObj, *valueObj;
+ int allocatedDict = 0;
+ int i, done;
+ Tcl_DictSearch search;
+
+ if (objc == 1) {
+ /*
+ * No dictionary arguments; return default (empty value).
+ */
+
+ return TCL_OK;
+ }
+
+ /*
+ * Make sure first argument is a dictionary.
+ */
+
+ targetObj = objv[1];
+ if (targetObj->typePtr != &tclDictType) {
+ if (SetDictFromAny(interp, targetObj) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+
+ if (objc == 2) {
+ /*
+ * Single argument, return it.
+ */
+
+ Tcl_SetObjResult(interp, objv[1]);
+ return TCL_OK;
+ }
+
+ /*
+ * Normal behaviour: combining two (or more) dictionaries.
+ */
+
+ if (Tcl_IsShared(targetObj)) {
+ targetObj = Tcl_DuplicateObj(targetObj);
+ allocatedDict = 1;
+ }
+ for (i=2 ; i<objc ; i++) {
+ if (Tcl_DictObjFirst(interp, objv[i], &search, &keyObj, &valueObj,
+ &done) != TCL_OK) {
+ if (allocatedDict) {
+ TclDecrRefCount(targetObj);
+ }
+ return TCL_ERROR;
+ }
+ while (!done) {
+ /*
+ * Next line can't fail; already know we have a dictionary in
+ * targetObj.
+ */
+
+ Tcl_DictObjPut(NULL, targetObj, keyObj, valueObj);
+ Tcl_DictObjNext(&search, &keyObj, &valueObj, &done);
+ }
+ Tcl_DictObjDone(&search);
+ }
+ Tcl_SetObjResult(interp, targetObj);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictKeysCmd --
+ *
+ * This function implements the "dict keys" Tcl command. See the user
+ * documentation for details on what it does, and TIP#111 for the formal
+ * specification.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictKeysCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Tcl_Obj *listPtr;
+ char *pattern = NULL;
+
+ if (objc!=2 && objc!=3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "dictionary ?pattern?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * A direct check that we have a dictionary. We don't start the iteration
+ * yet because that might allocate memory or set locks that we do not
+ * need. [Bug 1705778, leak K04]
+ */
+
+ if (objv[1]->typePtr != &tclDictType) {
+ int result = SetDictFromAny(interp, objv[1]);
+
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
+
+ if (objc == 3) {
+ pattern = TclGetString(objv[2]);
+ }
+ listPtr = Tcl_NewListObj(0, NULL);
+ if ((pattern != NULL) && TclMatchIsTrivial(pattern)) {
+ Tcl_Obj *valuePtr = NULL;
+
+ Tcl_DictObjGet(interp, objv[1], objv[2], &valuePtr);
+ if (valuePtr != NULL) {
+ Tcl_ListObjAppendElement(NULL, listPtr, objv[2]);
+ }
+ } else {
+ Tcl_DictSearch search;
+ Tcl_Obj *keyPtr;
+ int done;
+
+ /*
+ * At this point, we know we have a dictionary (or at least something
+ * that can be represented; it could theoretically have shimmered away
+ * when the pattern was fetched, but that shouldn't be damaging) so we
+ * can start the iteration process without checking for failures.
+ */
+
+ Tcl_DictObjFirst(NULL, objv[1], &search, &keyPtr, NULL, &done);
+ for (; !done ; Tcl_DictObjNext(&search, &keyPtr, NULL, &done)) {
+ if (!pattern || Tcl_StringMatch(TclGetString(keyPtr), pattern)) {
+ Tcl_ListObjAppendElement(NULL, listPtr, keyPtr);
+ }
+ }
+ Tcl_DictObjDone(&search);
+ }
+
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictValuesCmd --
+ *
+ * This function implements the "dict values" Tcl command. See the user
+ * documentation for details on what it does, and TIP#111 for the formal
+ * specification.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictValuesCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Tcl_Obj *valuePtr, *listPtr;
+ Tcl_DictSearch search;
+ int done;
+ char *pattern;
+
+ if (objc!=2 && objc!=3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "dictionary ?pattern?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_DictObjFirst(interp, objv[1], &search, NULL, &valuePtr,
+ &done) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ pattern = TclGetString(objv[2]);
+ } else {
+ pattern = NULL;
+ }
+ listPtr = Tcl_NewListObj(0, NULL);
+ for (; !done ; Tcl_DictObjNext(&search, NULL, &valuePtr, &done)) {
+ if (pattern==NULL || Tcl_StringMatch(TclGetString(valuePtr),pattern)) {
+ /*
+ * Assume this operation always succeeds.
+ */
+
+ Tcl_ListObjAppendElement(interp, listPtr, valuePtr);
+ }
+ }
+ Tcl_DictObjDone(&search);
+
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictSizeCmd --
+ *
+ * This function implements the "dict size" Tcl command. See the user
+ * documentation for details on what it does, and TIP#111 for the formal
+ * specification.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictSizeCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ int result, size;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "dictionary");
+ return TCL_ERROR;
+ }
+ result = Tcl_DictObjSize(interp, objv[1], &size);
+ if (result == TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(size));
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictExistsCmd --
+ *
+ * This function implements the "dict exists" Tcl command. See the user
+ * documentation for details on what it does, and TIP#111 for the formal
+ * specification.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictExistsCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Tcl_Obj *dictPtr, *valuePtr;
+ int result;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "dictionary key ?key ...?");
+ return TCL_ERROR;
+ }
+
+ dictPtr = TclTraceDictPath(interp, objv[1], objc-3, objv+2,
+ DICT_PATH_EXISTS);
+ if (dictPtr == NULL) {
+ return TCL_ERROR;
+ }
+ if (dictPtr == DICT_PATH_NON_EXISTENT) {
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
+ return TCL_OK;
+ }
+ result = Tcl_DictObjGet(interp, dictPtr, objv[objc-1], &valuePtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(valuePtr != NULL));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictInfoCmd --
+ *
+ * This function implements the "dict info" Tcl command. See the user
+ * documentation for details on what it does, and TIP#111 for the formal
+ * specification.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictInfoCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Tcl_Obj *dictPtr;
+ Dict *dict;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "dictionary");
+ return TCL_ERROR;
+ }
+
+ dictPtr = objv[1];
+ if (dictPtr->typePtr != &tclDictType) {
+ int result = SetDictFromAny(interp, dictPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
+ dict = dictPtr->internalRep.otherValuePtr;
+
+ /*
+ * This next cast is actually OK.
+ */
+
+ Tcl_SetResult(interp, (char *) Tcl_HashStats(&dict->table), TCL_DYNAMIC);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictIncrCmd --
+ *
+ * This function implements the "dict incr" Tcl command. See the user
+ * documentation for details on what it does, and TIP#111 for the formal
+ * specification.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictIncrCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ int code = TCL_OK;
+ Tcl_Obj *dictPtr, *valuePtr = NULL;
+
+ if (objc < 3 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "varName key ?increment?");
+ return TCL_ERROR;
+ }
+
+ dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0);
+ if (dictPtr == NULL) {
+ /*
+ * Variable didn't yet exist. Create new dictionary value.
+ */
+
+ dictPtr = Tcl_NewDictObj();
+ } else if (Tcl_DictObjGet(interp, dictPtr, objv[2], &valuePtr) != TCL_OK) {
+ /*
+ * Variable contents are not a dict, report error.
+ */
+
+ return TCL_ERROR;
+ }
+ if (Tcl_IsShared(dictPtr)) {
+ /*
+ * A little internals surgery to avoid copying a string rep that will
+ * soon be no good.
+ */
+
+ char *saved = dictPtr->bytes;
+ Tcl_Obj *oldPtr = dictPtr;
+
+ dictPtr->bytes = NULL;
+ dictPtr = Tcl_DuplicateObj(dictPtr);
+ oldPtr->bytes = saved;
+ }
+ if (valuePtr == NULL) {
+ /*
+ * Key not in dictionary. Create new key with increment as value.
+ */
+
+ if (objc == 4) {
+ /*
+ * Verify increment is an integer.
+ */
+
+ mp_int increment;
+
+ code = Tcl_GetBignumFromObj(interp, objv[3], &increment);
+ if (code != TCL_OK) {
+ Tcl_AddErrorInfo(interp, "\n (reading increment)");
+ } else {
+ /*
+ * Remember to dispose with the bignum as we're not actually
+ * using it directly. [Bug 2874678]
+ */
+
+ mp_clear(&increment);
+ Tcl_DictObjPut(interp, dictPtr, objv[2], objv[3]);
+ }
+ } else {
+ Tcl_DictObjPut(interp, dictPtr, objv[2], Tcl_NewIntObj(1));
+ }
+ } else {
+ /*
+ * Key in dictionary. Increment its value with minimum dup.
+ */
+
+ if (Tcl_IsShared(valuePtr)) {
+ valuePtr = Tcl_DuplicateObj(valuePtr);
+ Tcl_DictObjPut(interp, dictPtr, objv[2], valuePtr);
+ }
+ if (objc == 4) {
+ code = TclIncrObj(interp, valuePtr, objv[3]);
+ } else {
+ Tcl_Obj *incrPtr = Tcl_NewIntObj(1);
+
+ Tcl_IncrRefCount(incrPtr);
+ code = TclIncrObj(interp, valuePtr, incrPtr);
+ Tcl_DecrRefCount(incrPtr);
+ }
+ }
+ if (code == TCL_OK) {
+ Tcl_InvalidateStringRep(dictPtr);
+ valuePtr = Tcl_ObjSetVar2(interp, objv[1], NULL,
+ dictPtr, TCL_LEAVE_ERR_MSG);
+ if (valuePtr == NULL) {
+ code = TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, valuePtr);
+ }
+ } else if (dictPtr->refCount == 0) {
+ Tcl_DecrRefCount(dictPtr);
+ }
+ return code;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictLappendCmd --
+ *
+ * This function implements the "dict lappend" Tcl command. See the user
+ * documentation for details on what it does, and TIP#111 for the formal
+ * specification.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictLappendCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Tcl_Obj *dictPtr, *valuePtr, *resultPtr;
+ int i, allocatedDict = 0, allocatedValue = 0;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "varName key ?value ...?");
+ return TCL_ERROR;
+ }
+
+ dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0);
+ if (dictPtr == NULL) {
+ allocatedDict = 1;
+ dictPtr = Tcl_NewDictObj();
+ } else if (Tcl_IsShared(dictPtr)) {
+ allocatedDict = 1;
+ dictPtr = Tcl_DuplicateObj(dictPtr);
+ }
+
+ if (Tcl_DictObjGet(interp, dictPtr, objv[2], &valuePtr) != TCL_OK) {
+ if (allocatedDict) {
+ TclDecrRefCount(dictPtr);
+ }
+ return TCL_ERROR;
+ }
+
+ if (valuePtr == NULL) {
+ valuePtr = Tcl_NewListObj(objc-3, objv+3);
+ allocatedValue = 1;
+ } else {
+ if (Tcl_IsShared(valuePtr)) {
+ allocatedValue = 1;
+ valuePtr = Tcl_DuplicateObj(valuePtr);
+ }
+
+ for (i=3 ; i<objc ; i++) {
+ if (Tcl_ListObjAppendElement(interp, valuePtr,
+ objv[i]) != TCL_OK) {
+ if (allocatedValue) {
+ TclDecrRefCount(valuePtr);
+ }
+ if (allocatedDict) {
+ TclDecrRefCount(dictPtr);
+ }
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ if (allocatedValue) {
+ Tcl_DictObjPut(interp, dictPtr, objv[2], valuePtr);
+ } else if (dictPtr->bytes != NULL) {
+ Tcl_InvalidateStringRep(dictPtr);
+ }
+
+ resultPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, dictPtr,
+ TCL_LEAVE_ERR_MSG);
+ if (resultPtr == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictAppendCmd --
+ *
+ * This function implements the "dict append" Tcl command. See the user
+ * documentation for details on what it does, and TIP#111 for the formal
+ * specification.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictAppendCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Tcl_Obj *dictPtr, *valuePtr, *resultPtr;
+ int i, allocatedDict = 0;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "varName key ?value ...?");
+ return TCL_ERROR;
+ }
+
+ dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0);
+ if (dictPtr == NULL) {
+ allocatedDict = 1;
+ dictPtr = Tcl_NewDictObj();
+ } else if (Tcl_IsShared(dictPtr)) {
+ allocatedDict = 1;
+ dictPtr = Tcl_DuplicateObj(dictPtr);
+ }
+
+ if (Tcl_DictObjGet(interp, dictPtr, objv[2], &valuePtr) != TCL_OK) {
+ if (allocatedDict) {
+ TclDecrRefCount(dictPtr);
+ }
+ return TCL_ERROR;
+ }
+
+ if (valuePtr == NULL) {
+ TclNewObj(valuePtr);
+ } else {
+ if (Tcl_IsShared(valuePtr)) {
+ valuePtr = Tcl_DuplicateObj(valuePtr);
+ }
+ }
+
+ for (i=3 ; i<objc ; i++) {
+ Tcl_AppendObjToObj(valuePtr, objv[i]);
+ }
+
+ Tcl_DictObjPut(interp, dictPtr, objv[2], valuePtr);
+
+ resultPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, dictPtr,
+ TCL_LEAVE_ERR_MSG);
+ if (resultPtr == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictForCmd --
+ *
+ * This function implements the "dict for" Tcl command. See the user
+ * documentation for details on what it does, and TIP#111 for the formal
+ * specification.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictForCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Interp *iPtr = (Interp *) interp;
+ Tcl_Obj *scriptObj, *keyVarObj, *valueVarObj;
+ Tcl_Obj **varv, *keyObj, *valueObj;
+ Tcl_DictSearch search;
+ int varc, done, result;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "{keyVar valueVar} dictionary script");
+ return TCL_ERROR;
+ }
+
+ if (TclListObjGetElements(interp, objv[1], &varc, &varv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (varc != 2) {
+ Tcl_SetResult(interp, "must have exactly two variable names",
+ TCL_STATIC);
+ return TCL_ERROR;
+ }
+ keyVarObj = varv[0];
+ valueVarObj = varv[1];
+ scriptObj = objv[3];
+
+ if (Tcl_DictObjFirst(interp, objv[2], &search, &keyObj, &valueObj,
+ &done) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Make sure that these objects (which we need throughout the body of the
+ * loop) don't vanish. Note that the dictionary internal rep is locked
+ * internally so that updates, shimmering, etc are not a problem.
+ */
+
+ Tcl_IncrRefCount(keyVarObj);
+ Tcl_IncrRefCount(valueVarObj);
+ Tcl_IncrRefCount(scriptObj);
+
+ result = TCL_OK;
+ while (!done) {
+ /*
+ * Stop the value from getting hit in any way by any traces on the key
+ * variable.
+ */
+
+ Tcl_IncrRefCount(valueObj);
+ if (Tcl_ObjSetVar2(interp, keyVarObj, NULL, keyObj, 0) == NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "couldn't set key variable: \"",
+ TclGetString(keyVarObj), "\"", NULL);
+ TclDecrRefCount(valueObj);
+ result = TCL_ERROR;
+ break;
+ }
+ TclDecrRefCount(valueObj);
+ if (Tcl_ObjSetVar2(interp, valueVarObj, NULL, valueObj, 0) == NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "couldn't set value variable: \"",
+ TclGetString(valueVarObj), "\"", NULL);
+ result = TCL_ERROR;
+ break;
+ }
+
+ /*
+ * TIP #280. Make invoking context available to loop body.
+ */
+
+ result = TclEvalObjEx(interp, scriptObj, 0, iPtr->cmdFramePtr, 3);
+ if (result == TCL_CONTINUE) {
+ result = TCL_OK;
+ } else if (result != TCL_OK) {
+ if (result == TCL_BREAK) {
+ result = TCL_OK;
+ } else if (result == TCL_ERROR) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (\"dict for\" body line %d)",
+ interp->errorLine));
+ }
+ break;
+ }
+
+ Tcl_DictObjNext(&search, &keyObj, &valueObj, &done);
+ }
+
+ /*
+ * Stop holding a reference to these objects.
+ */
+
+ TclDecrRefCount(keyVarObj);
+ TclDecrRefCount(valueVarObj);
+ TclDecrRefCount(scriptObj);
+
+ Tcl_DictObjDone(&search);
+ if (result == TCL_OK) {
+ Tcl_ResetResult(interp);
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictSetCmd --
+ *
+ * This function implements the "dict set" Tcl command. See the user
+ * documentation for details on what it does, and TIP#111 for the formal
+ * specification.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictSetCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Tcl_Obj *dictPtr, *resultPtr;
+ int result, allocatedDict = 0;
+
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "varName key ?key ...? value");
+ return TCL_ERROR;
+ }
+
+ dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0);
+ if (dictPtr == NULL) {
+ allocatedDict = 1;
+ dictPtr = Tcl_NewDictObj();
+ } else if (Tcl_IsShared(dictPtr)) {
+ allocatedDict = 1;
+ dictPtr = Tcl_DuplicateObj(dictPtr);
+ }
+
+ result = Tcl_DictObjPutKeyList(interp, dictPtr, objc-3, objv+2,
+ objv[objc-1]);
+ if (result != TCL_OK) {
+ if (allocatedDict) {
+ TclDecrRefCount(dictPtr);
+ }
+ return TCL_ERROR;
+ }
+
+ resultPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, dictPtr,
+ TCL_LEAVE_ERR_MSG);
+ if (resultPtr == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictUnsetCmd --
+ *
+ * This function implements the "dict unset" Tcl command. See the user
+ * documentation for details on what it does, and TIP#111 for the formal
+ * specification.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictUnsetCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Tcl_Obj *dictPtr, *resultPtr;
+ int result, allocatedDict = 0;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "varName key ?key ...?");
+ return TCL_ERROR;
+ }
+
+ dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0);
+ if (dictPtr == NULL) {
+ allocatedDict = 1;
+ dictPtr = Tcl_NewDictObj();
+ } else if (Tcl_IsShared(dictPtr)) {
+ allocatedDict = 1;
+ dictPtr = Tcl_DuplicateObj(dictPtr);
+ }
+
+ result = Tcl_DictObjRemoveKeyList(interp, dictPtr, objc-2, objv+2);
+ if (result != TCL_OK) {
+ if (allocatedDict) {
+ TclDecrRefCount(dictPtr);
+ }
+ return TCL_ERROR;
+ }
+
+ resultPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, dictPtr,
+ TCL_LEAVE_ERR_MSG);
+ if (resultPtr == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictFilterCmd --
+ *
+ * This function implements the "dict filter" Tcl command. See the user
+ * documentation for details on what it does, and TIP#111 for the formal
+ * specification.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictFilterCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Interp *iPtr = (Interp *) interp;
+ static const char *filters[] = {
+ "key", "script", "value", NULL
+ };
+ enum FilterTypes {
+ FILTER_KEYS, FILTER_SCRIPT, FILTER_VALUES
+ };
+ Tcl_Obj *scriptObj, *keyVarObj, *valueVarObj;
+ Tcl_Obj **varv, *keyObj, *valueObj, *resultObj, *boolObj;
+ Tcl_DictSearch search;
+ int index, varc, done, result, satisfied;
+ char *pattern;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "dictionary filterType ...");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[2], filters, "filterType",
+ 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum FilterTypes) index) {
+ case FILTER_KEYS:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "dictionary key globPattern");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create a dictionary whose keys all match a certain pattern.
+ */
+
+ if (Tcl_DictObjFirst(interp, objv[1], &search,
+ &keyObj, &valueObj, &done) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ pattern = TclGetString(objv[3]);
+ resultObj = Tcl_NewDictObj();
+ if (TclMatchIsTrivial(pattern)) {
+ /*
+ * Must release the search lock here to prevent a memory leak
+ * since we are not exhausing the search. [Bug 1705778, leak K05]
+ */
+
+ Tcl_DictObjDone(&search);
+ Tcl_DictObjGet(interp, objv[1], objv[3], &valueObj);
+ if (valueObj != NULL) {
+ Tcl_DictObjPut(interp, resultObj, objv[3], valueObj);
+ }
+ } else {
+ while (!done) {
+ if (Tcl_StringMatch(TclGetString(keyObj), pattern)) {
+ Tcl_DictObjPut(interp, resultObj, keyObj, valueObj);
+ }
+ Tcl_DictObjNext(&search, &keyObj, &valueObj, &done);
+ }
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ return TCL_OK;
+
+ case FILTER_VALUES:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "dictionary value globPattern");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create a dictionary whose values all match a certain pattern.
+ */
+
+ if (Tcl_DictObjFirst(interp, objv[1], &search,
+ &keyObj, &valueObj, &done) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ pattern = TclGetString(objv[3]);
+ resultObj = Tcl_NewDictObj();
+ while (!done) {
+ if (Tcl_StringMatch(TclGetString(valueObj), pattern)) {
+ Tcl_DictObjPut(interp, resultObj, keyObj, valueObj);
+ }
+ Tcl_DictObjNext(&search, &keyObj, &valueObj, &done);
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ return TCL_OK;
+
+ case FILTER_SCRIPT:
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "dictionary script {keyVar valueVar} filterScript");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create a dictionary whose key,value pairs all satisfy a script
+ * (i.e. get a true boolean result from its evaluation). Massive
+ * copying from the "dict for" implementation has occurred!
+ */
+
+ if (TclListObjGetElements(interp, objv[3], &varc, &varv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (varc != 2) {
+ Tcl_SetResult(interp, "must have exactly two variable names",
+ TCL_STATIC);
+ return TCL_ERROR;
+ }
+ keyVarObj = varv[0];
+ valueVarObj = varv[1];
+ scriptObj = objv[4];
+
+ /*
+ * Make sure that these objects (which we need throughout the body of
+ * the loop) don't vanish. Note that the dictionary internal rep is
+ * locked internally so that updates, shimmering, etc are not a
+ * problem.
+ */
+
+ Tcl_IncrRefCount(keyVarObj);
+ Tcl_IncrRefCount(valueVarObj);
+ Tcl_IncrRefCount(scriptObj);
+
+ result = Tcl_DictObjFirst(interp, objv[1],
+ &search, &keyObj, &valueObj, &done);
+ if (result != TCL_OK) {
+ TclDecrRefCount(keyVarObj);
+ TclDecrRefCount(valueVarObj);
+ TclDecrRefCount(scriptObj);
+ return TCL_ERROR;
+ }
+
+ resultObj = Tcl_NewDictObj();
+
+ while (!done) {
+ /*
+ * Stop the value from getting hit in any way by any traces on the
+ * key variable.
+ */
+
+ Tcl_IncrRefCount(keyObj);
+ Tcl_IncrRefCount(valueObj);
+ if (Tcl_ObjSetVar2(interp, keyVarObj, NULL, keyObj,
+ TCL_LEAVE_ERR_MSG) == NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "couldn't set key variable: \"",
+ TclGetString(keyVarObj), "\"", NULL);
+ result = TCL_ERROR;
+ goto abnormalResult;
+ }
+ if (Tcl_ObjSetVar2(interp, valueVarObj, NULL, valueObj,
+ TCL_LEAVE_ERR_MSG) == NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "couldn't set value variable: \"",
+ TclGetString(valueVarObj), "\"", NULL);
+ goto abnormalResult;
+ }
+
+ /*
+ * TIP #280. Make invoking context available to loop body.
+ */
+
+ result = TclEvalObjEx(interp, scriptObj, 0, iPtr->cmdFramePtr, 4);
+ switch (result) {
+ case TCL_OK:
+ boolObj = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(boolObj);
+ Tcl_ResetResult(interp);
+ if (Tcl_GetBooleanFromObj(interp, boolObj,
+ &satisfied) != TCL_OK) {
+ TclDecrRefCount(boolObj);
+ result = TCL_ERROR;
+ goto abnormalResult;
+ }
+ TclDecrRefCount(boolObj);
+ if (satisfied) {
+ Tcl_DictObjPut(interp, resultObj, keyObj, valueObj);
+ }
+ break;
+ case TCL_BREAK:
+ /*
+ * Force loop termination by calling Tcl_DictObjDone; this
+ * makes the next Tcl_DictObjNext say there is nothing more to
+ * do.
+ */
+
+ Tcl_ResetResult(interp);
+ Tcl_DictObjDone(&search);
+ case TCL_CONTINUE:
+ result = TCL_OK;
+ break;
+ case TCL_ERROR:
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (\"dict filter\" script line %d)",
+ interp->errorLine));
+ default:
+ goto abnormalResult;
+ }
+
+ TclDecrRefCount(keyObj);
+ TclDecrRefCount(valueObj);
+
+ Tcl_DictObjNext(&search, &keyObj, &valueObj, &done);
+ }
+
+ /*
+ * Stop holding a reference to these objects.
+ */
+
+ TclDecrRefCount(keyVarObj);
+ TclDecrRefCount(valueVarObj);
+ TclDecrRefCount(scriptObj);
+ Tcl_DictObjDone(&search);
+
+ if (result == TCL_OK) {
+ Tcl_SetObjResult(interp, resultObj);
+ } else {
+ TclDecrRefCount(resultObj);
+ }
+ return result;
+
+ abnormalResult:
+ Tcl_DictObjDone(&search);
+ TclDecrRefCount(keyObj);
+ TclDecrRefCount(valueObj);
+ TclDecrRefCount(keyVarObj);
+ TclDecrRefCount(valueVarObj);
+ TclDecrRefCount(scriptObj);
+ TclDecrRefCount(resultObj);
+ return result;
+ }
+ Tcl_Panic("unexpected fallthrough");
+ /* Control never reaches this point. */
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictUpdateCmd --
+ *
+ * This function implements the "dict update" Tcl command. See the user
+ * documentation for details on what it does, and TIP#212 for the formal
+ * specification.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictUpdateCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Interp *iPtr = (Interp *) interp;
+ Tcl_Obj *dictPtr, *objPtr;
+ int i, result, dummy;
+ Tcl_InterpState state;
+
+ if (objc < 5 || !(objc & 1)) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "varName key varName ?key varName ...? script");
+ return TCL_ERROR;
+ }
+
+ dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG);
+ if (dictPtr == NULL) {
+ return TCL_ERROR;
+ }
+ if (Tcl_DictObjSize(interp, dictPtr, &dummy) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_IncrRefCount(dictPtr);
+ for (i=2 ; i+2<objc ; i+=2) {
+ if (Tcl_DictObjGet(interp, dictPtr, objv[i], &objPtr) != TCL_OK) {
+ TclDecrRefCount(dictPtr);
+ return TCL_ERROR;
+ }
+ if (objPtr == NULL) {
+ /* ??? */
+ Tcl_UnsetVar(interp, Tcl_GetString(objv[i+1]), 0);
+ } else if (Tcl_ObjSetVar2(interp, objv[i+1], NULL, objPtr,
+ TCL_LEAVE_ERR_MSG) == NULL) {
+ TclDecrRefCount(dictPtr);
+ return TCL_ERROR;
+ }
+ }
+ TclDecrRefCount(dictPtr);
+
+ /*
+ * Execute the body.
+ */
+
+ result = TclEvalObjEx(interp, objv[objc-1], 0, iPtr->cmdFramePtr, objc-1);
+ if (result == TCL_ERROR) {
+ Tcl_AddErrorInfo(interp, "\n (body of \"dict update\")");
+ }
+
+ /*
+ * If the dictionary variable doesn't exist, drop everything silently.
+ */
+
+ dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0);
+ if (dictPtr == NULL) {
+ return result;
+ }
+
+ /*
+ * Double-check that it is still a dictionary.
+ */
+
+ state = Tcl_SaveInterpState(interp, result);
+ if (Tcl_DictObjSize(interp, dictPtr, &dummy) != TCL_OK) {
+ Tcl_DiscardInterpState(state);
+ return TCL_ERROR;
+ }
+
+ if (Tcl_IsShared(dictPtr)) {
+ dictPtr = Tcl_DuplicateObj(dictPtr);
+ }
+
+ /*
+ * Write back the values from the variables, treating failure to read as
+ * an instruction to remove the key.
+ */
+
+ for (i=2 ; i+2<objc ; i+=2) {
+ objPtr = Tcl_ObjGetVar2(interp, objv[i+1], NULL, 0);
+ if (objPtr == NULL) {
+ Tcl_DictObjRemove(interp, dictPtr, objv[i]);
+ } else if (objPtr == dictPtr) {
+ /*
+ * Someone is messing us around, trying to build a recursive
+ * structure. [Bug 1786481]
+ */
+
+ Tcl_DictObjPut(interp, dictPtr, objv[i],
+ Tcl_DuplicateObj(objPtr));
+ } else {
+ /* Shouldn't fail */
+ Tcl_DictObjPut(interp, dictPtr, objv[i], objPtr);
+ }
+ }
+
+ /*
+ * Write the dictionary back to its variable.
+ */
+
+ if (Tcl_ObjSetVar2(interp, objv[1], NULL, dictPtr,
+ TCL_LEAVE_ERR_MSG) == NULL) {
+ Tcl_DiscardInterpState(state);
+ return TCL_ERROR;
+ }
+
+ return Tcl_RestoreInterpState(interp, state);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DictWithCmd --
+ *
+ * This function implements the "dict with" Tcl command. See the user
+ * documentation for details on what it does, and TIP#212 for the formal
+ * specification.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DictWithCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Interp *iPtr = (Interp *) interp;
+ Tcl_Obj *dictPtr, *keysPtr, *keyPtr, *valPtr, **keyv, *leafPtr;
+ Tcl_DictSearch s;
+ Tcl_InterpState state;
+ int done, result, keyc, i, allocdict = 0;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "dictVar ?key ...? script");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Get the dictionary to open out.
+ */
+
+ dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG);
+ if (dictPtr == NULL) {
+ return TCL_ERROR;
+ }
+ if (objc > 3) {
+ dictPtr = TclTraceDictPath(interp, dictPtr, objc-3, objv+2,
+ DICT_PATH_READ);
+ if (dictPtr == NULL) {
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Go over the list of keys and write each corresponding value to a
+ * variable in the current context with the same name. Also keep a copy of
+ * the keys so we can write back properly later on even if the dictionary
+ * has been structurally modified.
+ */
+
+ if (Tcl_DictObjFirst(interp, dictPtr, &s, &keyPtr, &valPtr,
+ &done) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ TclNewObj(keysPtr);
+ Tcl_IncrRefCount(keysPtr);
+
+ for (; !done ; Tcl_DictObjNext(&s, &keyPtr, &valPtr, &done)) {
+ Tcl_ListObjAppendElement(NULL, keysPtr, keyPtr);
+ if (Tcl_ObjSetVar2(interp, keyPtr, NULL, valPtr,
+ TCL_LEAVE_ERR_MSG) == NULL) {
+ TclDecrRefCount(keysPtr);
+ Tcl_DictObjDone(&s);
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Execute the body, while making the invoking context available to the
+ * loop body (TIP#280).
+ */
+
+ result = TclEvalObjEx(interp, objv[objc-1], 0, iPtr->cmdFramePtr, objc-1);
+ if (result == TCL_ERROR) {
+ Tcl_AddErrorInfo(interp, "\n (body of \"dict with\")");
+ }
+
+ /*
+ * If the dictionary variable doesn't exist, drop everything silently.
+ */
+
+ dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0);
+ if (dictPtr == NULL) {
+ TclDecrRefCount(keysPtr);
+ return result;
+ }
+
+ /*
+ * Double-check that it is still a dictionary.
+ */
+
+ state = Tcl_SaveInterpState(interp, result);
+ if (Tcl_DictObjSize(interp, dictPtr, &i) != TCL_OK) {
+ TclDecrRefCount(keysPtr);
+ Tcl_DiscardInterpState(state);
+ return TCL_ERROR;
+ }
+
+ if (Tcl_IsShared(dictPtr)) {
+ dictPtr = Tcl_DuplicateObj(dictPtr);
+ allocdict = 1;
+ }
+
+ if (objc > 3) {
+ /*
+ * Want to get to the dictionary which we will update; need to do
+ * prepare-for-update de-sharing along the path *but* avoid generating
+ * an error on a non-existant path (we'll treat that the same as a
+ * non-existant variable. Luckily, the de-sharing operation isn't
+ * deeply damaging if we don't go on to update; it's just less than
+ * perfectly efficient (but no memory should be leaked).
+ */
+
+ leafPtr = TclTraceDictPath(interp, dictPtr, objc-3, objv+2,
+ DICT_PATH_EXISTS | DICT_PATH_UPDATE);
+ if (leafPtr == NULL) {
+ TclDecrRefCount(keysPtr);
+ if (allocdict) {
+ TclDecrRefCount(dictPtr);
+ }
+ Tcl_DiscardInterpState(state);
+ return TCL_ERROR;
+ }
+ if (leafPtr == DICT_PATH_NON_EXISTENT) {
+ TclDecrRefCount(keysPtr);
+ if (allocdict) {
+ TclDecrRefCount(dictPtr);
+ }
+ return Tcl_RestoreInterpState(interp, state);
+ }
+ } else {
+ leafPtr = dictPtr;
+ }
+
+ /*
+ * Now process our updates on the leaf dictionary.
+ */
+
+ TclListObjGetElements(NULL, keysPtr, &keyc, &keyv);
+ for (i=0 ; i<keyc ; i++) {
+ valPtr = Tcl_ObjGetVar2(interp, keyv[i], NULL, 0);
+ if (valPtr == NULL) {
+ Tcl_DictObjRemove(NULL, leafPtr, keyv[i]);
+ } else if (leafPtr == valPtr) {
+ /*
+ * Someone is messing us around, trying to build a recursive
+ * structure. [Bug 1786481]
+ */
+
+ Tcl_DictObjPut(NULL, leafPtr, keyv[i], Tcl_DuplicateObj(valPtr));
+ } else {
+ Tcl_DictObjPut(NULL, leafPtr, keyv[i], valPtr);
+ }
+ }
+ TclDecrRefCount(keysPtr);
+
+ /*
+ * Ensure that none of the dictionaries in the chain still have a string
+ * rep.
+ */
+
+ if (objc > 3) {
+ InvalidateDictChain(leafPtr);
+ }
+
+ /*
+ * Write back the outermost dictionary to the variable.
+ */
+
+ if (Tcl_ObjSetVar2(interp, objv[1], NULL, dictPtr,
+ TCL_LEAVE_ERR_MSG) == NULL) {
+ Tcl_DiscardInterpState(state);
+ return TCL_ERROR;
+ }
+ return Tcl_RestoreInterpState(interp, state);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclInitDictCmd --
+ *
+ * This function is create the "dict" Tcl command. See the user
+ * documentation for details on what it does, and TIP#111 for the formal
+ * specification.
+ *
+ * Results:
+ * A Tcl command handle.
+ *
+ * Side effects:
+ * May advance compilation epoch.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Command
+TclInitDictCmd(
+ Tcl_Interp *interp)
+{
+ return TclMakeEnsemble(interp, "dict", implementationMap);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c
index 9432c05..2e0d51f 100644
--- a/generic/tclEncoding.c
+++ b/generic/tclEncoding.c
@@ -5,43 +5,41 @@
*
* Copyright (c) 1996-1998 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
-typedef size_t (LengthProc)_ANSI_ARGS_((CONST char *src));
+typedef size_t (LengthProc)(CONST char *src);
/*
- * The following data structure represents an encoding, which describes how
- * to convert between various character sets and UTF-8.
+ * The following data structure represents an encoding, which describes how to
+ * convert between various character sets and UTF-8.
*/
typedef struct Encoding {
- char *name; /* Name of encoding. Malloced because (1)
- * hash table entry that owns this encoding
- * may be freed prior to this encoding being
- * freed, (2) string passed in the
- * Tcl_EncodingType structure may not be
- * persistent. */
+ char *name; /* Name of encoding. Malloced because (1) hash
+ * table entry that owns this encoding may be
+ * freed prior to this encoding being freed,
+ * (2) string passed in the Tcl_EncodingType
+ * structure may not be persistent. */
Tcl_EncodingConvertProc *toUtfProc;
- /* Procedure to convert from external
- * encoding into UTF-8. */
+ /* Function to convert from external encoding
+ * into UTF-8. */
Tcl_EncodingConvertProc *fromUtfProc;
- /* Procedure to convert from UTF-8 into
+ /* Function to convert from UTF-8 into
* external encoding. */
Tcl_EncodingFreeProc *freeProc;
- /* If non-NULL, procedure to call when this
+ /* If non-NULL, function to call when this
* encoding is deleted. */
int nullSize; /* Number of 0x00 bytes that signify
- * end-of-string in this encoding. This
- * number is used to determine the source
- * string length when the srcLen argument is
- * negative. This number can be 1 or 2. */
+ * end-of-string in this encoding. This number
+ * is used to determine the source string
+ * length when the srcLen argument is
+ * negative. This number can be 1 or 2. */
ClientData clientData; /* Arbitrary value associated with encoding
- * type. Passed to conversion procedures. */
+ * type. Passed to conversion functions. */
LengthProc *lengthProc; /* Function to compute length of
* null-terminated strings in this encoding.
* If nullSize is 1, this is strlen; if
@@ -54,15 +52,15 @@ typedef struct Encoding {
/*
* The following structure is the clientData for a dynamically-loaded,
- * table-driven encoding created by LoadTableEncoding(). It maps between
+ * table-driven encoding created by LoadTableEncoding(). It maps between
* Unicode and a single-byte, double-byte, or multibyte (1 or 2 bytes only)
* encoding.
*/
typedef struct TableEncodingData {
- int fallback; /* Character (in this encoding) to
- * substitute when this encoding cannot
- * represent a UTF-8 character. */
+ int fallback; /* Character (in this encoding) to substitute
+ * when this encoding cannot represent a UTF-8
+ * character. */
char prefixBytes[256]; /* If a byte in the input stream is a lead
* byte for a 2-byte sequence, the
* corresponding entry in this array is 1,
@@ -70,14 +68,15 @@ typedef struct TableEncodingData {
unsigned short **toUnicode; /* Two dimensional sparse matrix to map
* characters from the encoding to Unicode.
* Each element of the toUnicode array points
- * to an array of 256 shorts. If there is no
+ * to an array of 256 shorts. If there is no
* corresponding character in Unicode, the
- * value in the matrix is 0x0000. malloc'd. */
+ * value in the matrix is 0x0000.
+ * malloc'd. */
unsigned short **fromUnicode;
/* Two dimensional sparse matrix to map
* characters from Unicode to the encoding.
* Each element of the fromUnicode array
- * points to an array of 256 shorts. If there
+ * points to an array of 256 shorts. If there
* is no corresponding character the encoding,
* the value in the matrix is 0x0000.
* malloc'd. */
@@ -85,11 +84,11 @@ typedef struct TableEncodingData {
/*
* The following structures is the clientData for a dynamically-loaded,
- * escape-driven encoding that is itself comprised of other simpler
- * encodings. An example is "iso-2022-jp", which uses escape sequences to
- * switch between ascii, jis0208, jis0212, gb2312, and ksc5601. Note that
- * "escape-driven" does not necessarily mean that the ESCAPE character is
- * the character used for switching character sets.
+ * escape-driven encoding that is itself comprised of other simpler encodings.
+ * An example is "iso-2022-jp", which uses escape sequences to switch between
+ * ascii, jis0208, jis0212, gb2312, and ksc5601. Note that "escape-driven"
+ * does not necessarily mean that the ESCAPE character is the character used
+ * for switching character sets.
*/
typedef struct EscapeSubTable {
@@ -102,25 +101,25 @@ typedef struct EscapeSubTable {
} EscapeSubTable;
typedef struct EscapeEncodingData {
- int fallback; /* Character (in this encoding) to
- * substitute when this encoding cannot
- * represent a UTF-8 character. */
+ int fallback; /* Character (in this encoding) to substitute
+ * when this encoding cannot represent a UTF-8
+ * character. */
unsigned int initLen; /* Length of following string. */
char init[16]; /* String to emit or expect before first char
* in conversion. */
unsigned int finalLen; /* Length of following string. */
- char final[16]; /* String to emit or expect after last char
- * in conversion. */
- char prefixBytes[256]; /* If a byte in the input stream is the
- * first character of one of the escape
- * sequences in the following array, the
- * corresponding entry in this array is 1,
- * otherwise it is 0. */
+ char final[16]; /* String to emit or expect after last char in
+ * conversion. */
+ char prefixBytes[256]; /* If a byte in the input stream is the first
+ * character of one of the escape sequences in
+ * the following array, the corresponding
+ * entry in this array is 1, otherwise it is
+ * 0. */
int numSubTables; /* Length of following array. */
- EscapeSubTable subTables[1];/* Information about each EscapeSubTable
- * used by this encoding type. The actual
- * size will be as large as necessary to
- * hold all EscapeSubTables. */
+ EscapeSubTable subTables[1];/* Information about each EscapeSubTable used
+ * by this encoding type. The actual size will
+ * be as large as necessary to hold all
+ * EscapeSubTables. */
} EscapeEncodingData;
/*
@@ -134,27 +133,51 @@ typedef struct EscapeEncodingData {
#define ENCODING_ESCAPE 3
/*
- * Initialize the default encoding directory. If this variable contains
- * a non NULL value, it will be the first path used to locate the
- * system encoding files.
+ * A list of directories in which Tcl should look for *.enc files. This list
+ * is shared by all threads. Access is governed by a mutex lock.
*/
-char *tclDefaultEncodingDir = NULL;
+static TclInitProcessGlobalValueProc InitializeEncodingSearchPath;
+static ProcessGlobalValue encodingSearchPath = {
+ 0, 0, NULL, NULL, InitializeEncodingSearchPath, NULL, NULL
+};
-static int encodingsInitialized = 0;
+/*
+ * A map from encoding names to the directories in which their data files have
+ * been seen. The string value of the map is shared by all threads. Access to
+ * the shared string is governed by a mutex lock.
+ */
+
+static ProcessGlobalValue encodingFileMap = {
+ 0, 0, NULL, NULL, NULL, NULL, NULL
+};
/*
- * Hash table that keeps track of all loaded Encodings. Keys are
- * the string names that represent the encoding, values are (Encoding *).
+ * A list of directories making up the "library path". Historically this
+ * search path has served many uses, but the only one remaining is a base for
+ * the encodingSearchPath above. If the application does not explicitly set
+ * the encodingSearchPath, then it will be initialized by appending /encoding
+ * to each directory in this "libraryPath".
*/
-
+
+static ProcessGlobalValue libraryPath = {
+ 0, 0, NULL, NULL, TclpInitLibraryPath, NULL, NULL
+};
+
+static int encodingsInitialized = 0;
+
+/*
+ * Hash table that keeps track of all loaded Encodings. Keys are the string
+ * names that represent the encoding, values are (Encoding *).
+ */
+
static Tcl_HashTable encodingTable;
TCL_DECLARE_MUTEX(encodingMutex)
/*
- * The following are used to hold the default and current system encodings.
- * If NULL is passed to one of the conversion routines, the current setting
- * of the system encoding will be used to perform the conversion.
+ * The following are used to hold the default and current system encodings.
+ * If NULL is passed to one of the conversion routines, the current setting of
+ * the system encoding will be used to perform the conversion.
*/
static Tcl_Encoding defaultEncoding;
@@ -168,125 +191,129 @@ static Tcl_Encoding systemEncoding;
static unsigned short emptyPage[256];
/*
- * Procedures used only in this module.
+ * Functions used only in this module.
*/
-static int BinaryProc _ANSI_ARGS_((ClientData clientData,
+static int BinaryProc(ClientData clientData,
CONST char *src, int srcLen, int flags,
Tcl_EncodingState *statePtr, char *dst, int dstLen,
int *srcReadPtr, int *dstWrotePtr,
- int *dstCharsPtr));
-static void DupEncodingIntRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
- Tcl_Obj *dupPtr));
-static void EscapeFreeProc _ANSI_ARGS_((ClientData clientData));
-static int EscapeFromUtfProc _ANSI_ARGS_((ClientData clientData,
+ int *dstCharsPtr);
+static void DupEncodingIntRep(Tcl_Obj *srcPtr, Tcl_Obj *dupPtr);
+static void EscapeFreeProc(ClientData clientData);
+static int EscapeFromUtfProc(ClientData clientData,
CONST char *src, int srcLen, int flags,
Tcl_EncodingState *statePtr, char *dst, int dstLen,
int *srcReadPtr, int *dstWrotePtr,
- int *dstCharsPtr));
-static int EscapeToUtfProc _ANSI_ARGS_((ClientData clientData,
+ int *dstCharsPtr);
+static int EscapeToUtfProc(ClientData clientData,
CONST char *src, int srcLen, int flags,
Tcl_EncodingState *statePtr, char *dst, int dstLen,
int *srcReadPtr, int *dstWrotePtr,
- int *dstCharsPtr));
-static void FreeEncoding _ANSI_ARGS_((Tcl_Encoding encoding));
-static void FreeEncodingIntRep _ANSI_ARGS_((Tcl_Obj *objPtr));
-static Encoding * GetTableEncoding _ANSI_ARGS_((
- EscapeEncodingData *dataPtr, int state));
-static Tcl_Encoding LoadEncodingFile _ANSI_ARGS_((Tcl_Interp *interp,
- CONST char *name));
-static Tcl_Encoding LoadTableEncoding _ANSI_ARGS_((Tcl_Interp *interp,
- CONST char *name, int type, Tcl_Channel chan));
-static Tcl_Encoding LoadEscapeEncoding _ANSI_ARGS_((CONST char *name,
- Tcl_Channel chan));
-static Tcl_Channel OpenEncodingFile _ANSI_ARGS_((CONST char *dir,
- CONST char *name));
-static void TableFreeProc _ANSI_ARGS_((ClientData clientData));
-static int TableFromUtfProc _ANSI_ARGS_((ClientData clientData,
+ int *dstCharsPtr);
+static void FillEncodingFileMap(void);
+static void FreeEncoding(Tcl_Encoding encoding);
+static void FreeEncodingIntRep(Tcl_Obj *objPtr);
+static Encoding * GetTableEncoding(EscapeEncodingData *dataPtr,
+ int state);
+static Tcl_Encoding LoadEncodingFile(Tcl_Interp *interp, CONST char *name);
+static Tcl_Encoding LoadTableEncoding(CONST char *name, int type,
+ Tcl_Channel chan);
+static Tcl_Encoding LoadEscapeEncoding(CONST char *name, Tcl_Channel chan);
+static Tcl_Channel OpenEncodingFileChannel(Tcl_Interp *interp,
+ CONST char *name);
+static void TableFreeProc(ClientData clientData);
+static int TableFromUtfProc(ClientData clientData,
CONST char *src, int srcLen, int flags,
Tcl_EncodingState *statePtr, char *dst, int dstLen,
int *srcReadPtr, int *dstWrotePtr,
- int *dstCharsPtr));
-static int TableToUtfProc _ANSI_ARGS_((ClientData clientData,
+ int *dstCharsPtr);
+static int TableToUtfProc(ClientData clientData, CONST char *src,
+ int srcLen, int flags, Tcl_EncodingState *statePtr,
+ char *dst, int dstLen, int *srcReadPtr,
+ int *dstWrotePtr, int *dstCharsPtr);
+static size_t unilen(CONST char *src);
+static int UnicodeToUtfProc(ClientData clientData,
CONST char *src, int srcLen, int flags,
Tcl_EncodingState *statePtr, char *dst, int dstLen,
int *srcReadPtr, int *dstWrotePtr,
- int *dstCharsPtr));
-static size_t unilen _ANSI_ARGS_((CONST char *src));
-static int UnicodeToUtfProc _ANSI_ARGS_((ClientData clientData,
+ int *dstCharsPtr);
+static int UtfToUnicodeProc(ClientData clientData,
CONST char *src, int srcLen, int flags,
Tcl_EncodingState *statePtr, char *dst, int dstLen,
int *srcReadPtr, int *dstWrotePtr,
- int *dstCharsPtr));
-static int UtfToUnicodeProc _ANSI_ARGS_((ClientData clientData,
+ int *dstCharsPtr);
+static int UtfToUtfProc(ClientData clientData,
CONST char *src, int srcLen, int flags,
Tcl_EncodingState *statePtr, char *dst, int dstLen,
int *srcReadPtr, int *dstWrotePtr,
- int *dstCharsPtr));
-static int UtfToUtfProc _ANSI_ARGS_((ClientData clientData,
+ int *dstCharsPtr, int pureNullMode);
+static int UtfIntToUtfExtProc(ClientData clientData,
CONST char *src, int srcLen, int flags,
Tcl_EncodingState *statePtr, char *dst, int dstLen,
int *srcReadPtr, int *dstWrotePtr,
- int *dstCharsPtr, int pureNullMode));
-static int UtfIntToUtfExtProc _ANSI_ARGS_((ClientData clientData,
+ int *dstCharsPtr);
+static int UtfExtToUtfIntProc(ClientData clientData,
CONST char *src, int srcLen, int flags,
Tcl_EncodingState *statePtr, char *dst, int dstLen,
int *srcReadPtr, int *dstWrotePtr,
- int *dstCharsPtr));
-static int UtfExtToUtfIntProc _ANSI_ARGS_((ClientData clientData,
+ int *dstCharsPtr);
+static int Iso88591FromUtfProc(ClientData clientData,
CONST char *src, int srcLen, int flags,
Tcl_EncodingState *statePtr, char *dst, int dstLen,
int *srcReadPtr, int *dstWrotePtr,
- int *dstCharsPtr));
-static int TclFindEncodings _ANSI_ARGS_((CONST char *argv0));
+ int *dstCharsPtr);
+static int Iso88591ToUtfProc(ClientData clientData,
+ CONST char *src, int srcLen, int flags,
+ Tcl_EncodingState *statePtr, char *dst,
+ int dstLen, int *srcReadPtr, int *dstWrotePtr,
+ int *dstCharsPtr);
/*
- * A Tcl_ObjType for holding a cached Tcl_Encoding as the intrep.
- * This should help the lifetime of encodings be more useful.
+ * A Tcl_ObjType for holding a cached Tcl_Encoding in the otherValuePtr field
+ * of the intrep. This should help the lifetime of encodings be more useful.
* See concerns raised in [Bug 1077262].
*/
-static Tcl_ObjType EncodingType = {
+static Tcl_ObjType encodingType = {
"encoding", FreeEncodingIntRep, DupEncodingIntRep, NULL, NULL
};
-
/*
*----------------------------------------------------------------------
*
- * TclGetEncodingFromObj --
+ * Tcl_GetEncodingFromObj --
*
- * Writes to (*encodingPtr) the Tcl_Encoding value of (*objPtr),
- * if possible, and returns TCL_OK. If no such encoding exists,
- * TCL_ERROR is returned, and if interp is non-NULL, an error message
- * is written there.
+ * Writes to (*encodingPtr) the Tcl_Encoding value of (*objPtr), if
+ * possible, and returns TCL_OK. If no such encoding exists, TCL_ERROR is
+ * returned, and if interp is non-NULL, an error message is written
+ * there.
*
* Results:
- * Standard Tcl return code.
+ * Standard Tcl return code.
*
* Side effects:
* Caches the Tcl_Encoding value as the internal rep of (*objPtr).
*
*----------------------------------------------------------------------
*/
-int
-TclGetEncodingFromObj(interp, objPtr, encodingPtr)
- Tcl_Interp *interp;
- Tcl_Obj *objPtr;
- Tcl_Encoding *encodingPtr;
+
+int
+Tcl_GetEncodingFromObj(
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr,
+ Tcl_Encoding *encodingPtr)
{
CONST char *name = Tcl_GetString(objPtr);
- if (objPtr->typePtr != &EncodingType) {
+ if (objPtr->typePtr != &encodingType) {
Tcl_Encoding encoding = Tcl_GetEncoding(interp, name);
if (encoding == NULL) {
return TCL_ERROR;
}
- if (objPtr->typePtr && objPtr->typePtr->freeIntRepProc) {
- objPtr->typePtr->freeIntRepProc(objPtr);
- }
+ TclFreeIntRep(objPtr);
objPtr->internalRep.otherValuePtr = (VOID *) encoding;
- objPtr->typePtr = &EncodingType;
+ objPtr->typePtr = &encodingType;
}
*encodingPtr = Tcl_GetEncoding(NULL, name);
return TCL_OK;
@@ -297,15 +324,17 @@ TclGetEncodingFromObj(interp, objPtr, encodingPtr)
*
* FreeEncodingIntRep --
*
- * The Tcl_FreeInternalRepProc for the "encoding" Tcl_ObjType.
+ * The Tcl_FreeInternalRepProc for the "encoding" Tcl_ObjType.
*
*----------------------------------------------------------------------
*/
+
static void
-FreeEncodingIntRep(objPtr)
- Tcl_Obj *objPtr;
+FreeEncodingIntRep(
+ Tcl_Obj *objPtr)
{
Tcl_FreeEncoding((Tcl_Encoding) objPtr->internalRep.otherValuePtr);
+ objPtr->typePtr = NULL;
}
/*
@@ -313,26 +342,193 @@ FreeEncodingIntRep(objPtr)
*
* DupEncodingIntRep --
*
- * The Tcl_DupInternalRepProc for the "encoding" Tcl_ObjType.
+ * The Tcl_DupInternalRepProc for the "encoding" Tcl_ObjType.
*
*----------------------------------------------------------------------
*/
+
static void
-DupEncodingIntRep(srcPtr, dupPtr)
- Tcl_Obj *srcPtr;
- Tcl_Obj *dupPtr;
+DupEncodingIntRep(
+ Tcl_Obj *srcPtr,
+ Tcl_Obj *dupPtr)
{
dupPtr->internalRep.otherValuePtr = (VOID *)
Tcl_GetEncoding(NULL, srcPtr->bytes);
}
/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetEncodingSearchPath --
+ *
+ * Keeps the per-thread copy of the encoding search path current with
+ * changes to the global copy.
+ *
+ * Results:
+ * Returns a "list" (Tcl_Obj *) that contains the encoding search path.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tcl_GetEncodingSearchPath(void)
+{
+ return TclGetProcessGlobalValue(&encodingSearchPath);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetEncodingSearchPath --
+ *
+ * Keeps the per-thread copy of the encoding search path current with
+ * changes to the global copy.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_SetEncodingSearchPath(
+ Tcl_Obj *searchPath)
+{
+ int dummy;
+
+ if (TCL_ERROR == Tcl_ListObjLength(NULL, searchPath, &dummy)) {
+ return TCL_ERROR;
+ }
+ TclSetProcessGlobalValue(&encodingSearchPath, searchPath, NULL);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetLibraryPath --
+ *
+ * Keeps the per-thread copy of the library path current with changes to
+ * the global copy.
+ *
+ * Results:
+ * Returns a "list" (Tcl_Obj *) that contains the library path.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclGetLibraryPath(void)
+{
+ return TclGetProcessGlobalValue(&libraryPath);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclSetLibraryPath --
+ *
+ * Keeps the per-thread copy of the library path current with changes to
+ * the global copy.
+ *
+ * NOTE: this routine returns void, so there's no way to report the error
+ * that searchPath is not a valid list. In that case, this routine will
+ * silently do nothing.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclSetLibraryPath(
+ Tcl_Obj *path)
+{
+ int dummy;
+
+ if (TCL_ERROR == Tcl_ListObjLength(NULL, path, &dummy)) {
+ return;
+ }
+ TclSetProcessGlobalValue(&libraryPath, path, NULL);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FillEncodingFileMap --
+ *
+ * Called to bring the encoding file map in sync with the current value
+ * of the encoding search path.
+ *
+ * Scan the directories on the encoding search path, find the *.enc
+ * files, and store the found pathnames in a map associated with the
+ * encoding name.
+ *
+ * In particular, if $dir is on the encoding search path, and the file
+ * $dir/foo.enc is found, then store a "foo" -> $dir entry in the map.
+ * Later, any need for the "foo" encoding will quickly * be able to
+ * construct the $dir/foo.enc pathname for reading the encoding data.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Entries are added to the encoding file map.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+FillEncodingFileMap(void)
+{
+ int i, numDirs = 0;
+ Tcl_Obj *map, *searchPath;
+
+ searchPath = Tcl_GetEncodingSearchPath();
+ Tcl_IncrRefCount(searchPath);
+ Tcl_ListObjLength(NULL, searchPath, &numDirs);
+ map = Tcl_NewDictObj();
+ Tcl_IncrRefCount(map);
+
+ for (i = numDirs-1; i >= 0; i--) {
+ /*
+ * Iterate backwards through the search path so as we overwrite
+ * entries found, we favor files earlier on the search path.
+ */
+
+ int j, numFiles;
+ Tcl_Obj *directory, *matchFileList = Tcl_NewObj();
+ Tcl_Obj **filev;
+ Tcl_GlobTypeData readableFiles = {
+ TCL_GLOB_TYPE_FILE, TCL_GLOB_PERM_R, NULL, NULL
+ };
+
+ Tcl_ListObjIndex(NULL, searchPath, i, &directory);
+ Tcl_IncrRefCount(directory);
+ Tcl_IncrRefCount(matchFileList);
+ Tcl_FSMatchInDirectory(NULL, matchFileList, directory, "*.enc",
+ &readableFiles);
+
+ Tcl_ListObjGetElements(NULL, matchFileList, &numFiles, &filev);
+ for (j=0; j<numFiles; j++) {
+ Tcl_Obj *encodingName, *file;
+
+ file = TclPathPart(NULL, filev[j], TCL_PATH_TAIL);
+ encodingName = TclPathPart(NULL, file, TCL_PATH_ROOT);
+ Tcl_DictObjPut(NULL, map, encodingName, directory);
+ Tcl_DecrRefCount(file);
+ Tcl_DecrRefCount(encodingName);
+ }
+ Tcl_DecrRefCount(matchFileList);
+ Tcl_DecrRefCount(directory);
+ }
+ Tcl_DecrRefCount(searchPath);
+ TclSetProcessGlobalValue(&encodingFileMap, map, NULL);
+ Tcl_DecrRefCount(map);
+}
+
+/*
*---------------------------------------------------------------------------
*
* TclInitEncodingSubsystem --
*
* Initialize all resources used by this subsystem on a per-process
- * basis.
+ * basis.
*
* Results:
* None.
@@ -344,18 +540,22 @@ DupEncodingIntRep(srcPtr, dupPtr)
*/
void
-TclInitEncodingSubsystem()
+TclInitEncodingSubsystem(void)
{
Tcl_EncodingType type;
+ if (encodingsInitialized) {
+ return;
+ }
+
Tcl_MutexLock(&encodingMutex);
Tcl_InitHashTable(&encodingTable, TCL_STRING_KEYS);
Tcl_MutexUnlock(&encodingMutex);
-
+
/*
- * Create a few initial encodings. Note that the UTF-8 to UTF-8
- * translation is not a no-op, because it will turn a stream of
- * improperly formed UTF-8 into a properly formed stream.
+ * Create a few initial encodings. Note that the UTF-8 to UTF-8
+ * translation is not a no-op, because it will turn a stream of improperly
+ * formed UTF-8 into a properly formed stream.
*/
type.encodingName = "identity";
@@ -383,8 +583,53 @@ TclInitEncodingSubsystem()
type.nullSize = 2;
type.clientData = NULL;
Tcl_CreateEncoding(&type);
-}
+ /*
+ * Need the iso8859-1 encoding in order to process binary data, so force
+ * it to always be embedded. Note that this encoding *must* be a proper
+ * table encoding or some of the escape encodings crash! Hence the ugly
+ * code to duplicate the structure of a table encoding here.
+ */
+
+ {
+ TableEncodingData *dataPtr = (TableEncodingData *)
+ ckalloc(sizeof(TableEncodingData));
+ unsigned size;
+ unsigned short i;
+
+ memset(dataPtr, 0, sizeof(TableEncodingData));
+ dataPtr->fallback = '?';
+
+ size = 256*(sizeof(unsigned short *) + sizeof(unsigned short));
+ dataPtr->toUnicode = (unsigned short **) ckalloc(size);
+ memset(dataPtr->toUnicode, 0, size);
+ dataPtr->fromUnicode = (unsigned short **) ckalloc(size);
+ memset(dataPtr->fromUnicode, 0, size);
+
+ dataPtr->toUnicode[0] = (unsigned short *) (dataPtr->toUnicode + 256);
+ dataPtr->fromUnicode[0] = (unsigned short *)
+ (dataPtr->fromUnicode + 256);
+ for (i=1 ; i<256 ; i++) {
+ dataPtr->toUnicode[i] = emptyPage;
+ dataPtr->fromUnicode[i] = emptyPage;
+ }
+
+ for (i=0 ; i<256 ; i++) {
+ dataPtr->toUnicode[0][i] = i;
+ dataPtr->fromUnicode[0][i] = i;
+ }
+
+ type.encodingName = "iso8859-1";
+ type.toUtfProc = Iso88591ToUtfProc;
+ type.fromUtfProc = Iso88591FromUtfProc;
+ type.freeProc = TableFreeProc;
+ type.nullSize = 1;
+ type.clientData = dataPtr;
+ Tcl_CreateEncoding(&type);
+ }
+
+ encodingsInitialized = 1;
+}
/*
*----------------------------------------------------------------------
@@ -403,25 +648,28 @@ TclInitEncodingSubsystem()
*/
void
-TclFinalizeEncodingSubsystem()
+TclFinalizeEncodingSubsystem(void)
{
Tcl_HashSearch search;
Tcl_HashEntry *hPtr;
Tcl_MutexLock(&encodingMutex);
- encodingsInitialized = 0;
+ encodingsInitialized = 0;
FreeEncoding(systemEncoding);
+
hPtr = Tcl_FirstHashEntry(&encodingTable, &search);
while (hPtr != NULL) {
/*
* Call FreeEncoding instead of doing it directly to handle refcounts
- * like escape encodings use. [Bug #524674]
- * Make sure to call Tcl_FirstHashEntry repeatedly so that all
- * encodings are eventually cleaned up.
+ * like escape encodings use. [Bug 524674] Make sure to call
+ * Tcl_FirstHashEntry repeatedly so that all encodings are eventually
+ * cleaned up.
*/
+
FreeEncoding((Tcl_Encoding) Tcl_GetHashValue(hPtr));
hPtr = Tcl_FirstHashEntry(&encodingTable, &search);
}
+
Tcl_DeleteHashTable(&encodingTable);
Tcl_MutexUnlock(&encodingMutex);
}
@@ -431,18 +679,32 @@ TclFinalizeEncodingSubsystem()
*
* Tcl_GetDefaultEncodingDir --
*
+ * Legacy public interface to retrieve first directory in the encoding
+ * searchPath.
*
* Results:
+ * The directory pathname, as a string, or NULL for an empty encoding
+ * search path.
*
* Side effects:
+ * None.
*
*-------------------------------------------------------------------------
*/
CONST char *
-Tcl_GetDefaultEncodingDir()
+Tcl_GetDefaultEncodingDir(void)
{
- return tclDefaultEncodingDir;
+ int numDirs;
+ Tcl_Obj *first, *searchPath = Tcl_GetEncodingSearchPath();
+
+ Tcl_ListObjLength(NULL, searchPath, &numDirs);
+ if (numDirs == 0) {
+ return NULL;
+ }
+ Tcl_ListObjIndex(NULL, searchPath, 0, &first);
+
+ return Tcl_GetString(first);
}
/*
@@ -450,20 +712,28 @@ Tcl_GetDefaultEncodingDir()
*
* Tcl_SetDefaultEncodingDir --
*
+ * Legacy public interface to set the first directory in the encoding
+ * search path.
*
* Results:
+ * None.
*
* Side effects:
+ * Modifies the encoding search path.
*
*-------------------------------------------------------------------------
*/
void
-Tcl_SetDefaultEncodingDir(path)
- CONST char *path;
+Tcl_SetDefaultEncodingDir(
+ CONST char *path)
{
- tclDefaultEncodingDir = (char *)ckalloc((unsigned) strlen(path) + 1);
- strcpy(tclDefaultEncodingDir, path);
+ Tcl_Obj *searchPath = Tcl_GetEncodingSearchPath();
+ Tcl_Obj *directory = Tcl_NewStringObj(path, -1);
+
+ searchPath = Tcl_DuplicateObj(searchPath);
+ Tcl_ListObjReplace(NULL, searchPath, 0, 0, 1, &directory);
+ Tcl_SetEncodingSearchPath(searchPath);
}
/*
@@ -472,29 +742,29 @@ Tcl_SetDefaultEncodingDir(path)
* Tcl_GetEncoding --
*
* Given the name of a encoding, find the corresponding Tcl_Encoding
- * token. If the encoding did not already exist, Tcl attempts to
+ * token. If the encoding did not already exist, Tcl attempts to
* dynamically load an encoding by that name.
*
* Results:
- * Returns a token that represents the encoding. If the name didn't
- * refer to any known or loadable encoding, NULL is returned. If
- * NULL was returned, an error message is left in interp's result
- * object, unless interp was NULL.
+ * Returns a token that represents the encoding. If the name didn't refer
+ * to any known or loadable encoding, NULL is returned. If NULL was
+ * returned, an error message is left in interp's result object, unless
+ * interp was NULL.
*
* Side effects:
* The new encoding type is entered into a table visible to all
- * interpreters, keyed off the encoding's name. For each call to
- * this procedure, there should eventually be a call to
- * Tcl_FreeEncoding, so that the database can be cleaned up when
- * encodings aren't needed anymore.
+ * interpreters, keyed off the encoding's name. For each call to this
+ * function, there should eventually be a call to Tcl_FreeEncoding, so
+ * that the database can be cleaned up when encodings aren't needed
+ * anymore.
*
*-------------------------------------------------------------------------
*/
Tcl_Encoding
-Tcl_GetEncoding(interp, name)
- Tcl_Interp *interp; /* Interp for error reporting, if not NULL. */
- CONST char *name; /* The name of the desired encoding. */
+Tcl_GetEncoding(
+ Tcl_Interp *interp, /* Interp for error reporting, if not NULL. */
+ CONST char *name) /* The name of the desired encoding. */
{
Tcl_HashEntry *hPtr;
Encoding *encodingPtr;
@@ -515,6 +785,7 @@ Tcl_GetEncoding(interp, name)
return (Tcl_Encoding) encodingPtr;
}
Tcl_MutexUnlock(&encodingMutex);
+
return LoadEncodingFile(interp, name);
}
@@ -523,22 +794,22 @@ Tcl_GetEncoding(interp, name)
*
* Tcl_FreeEncoding --
*
- * This procedure is called to release an encoding allocated by
+ * This function is called to release an encoding allocated by
* Tcl_CreateEncoding() or Tcl_GetEncoding().
*
* Results:
* None.
*
* Side effects:
- * The reference count associated with the encoding is decremented
- * and the encoding may be deleted if nothing is using it anymore.
+ * The reference count associated with the encoding is decremented and
+ * the encoding may be deleted if nothing is using it anymore.
*
*---------------------------------------------------------------------------
*/
void
-Tcl_FreeEncoding(encoding)
- Tcl_Encoding encoding;
+Tcl_FreeEncoding(
+ Tcl_Encoding encoding)
{
Tcl_MutexLock(&encodingMutex);
FreeEncoding(encoding);
@@ -550,25 +821,25 @@ Tcl_FreeEncoding(encoding)
*
* FreeEncoding --
*
- * This procedure is called to release an encoding by procedures
- * that already have the encodingMutex.
+ * This function is called to release an encoding by functions that
+ * already have the encodingMutex.
*
* Results:
* None.
*
* Side effects:
- * The reference count associated with the encoding is decremented
- * and the encoding may be deleted if nothing is using it anymore.
+ * The reference count associated with the encoding is decremented and
+ * the encoding may be deleted if nothing is using it anymore.
*
*----------------------------------------------------------------------
*/
static void
-FreeEncoding(encoding)
- Tcl_Encoding encoding;
+FreeEncoding(
+ Tcl_Encoding encoding)
{
Encoding *encodingPtr;
-
+
encodingPtr = (Encoding *) encoding;
if (encodingPtr == NULL) {
return;
@@ -594,8 +865,8 @@ FreeEncoding(encoding)
*
* Tcl_GetEncodingName --
*
- * Given an encoding, return the name that was used to constuct
- * the encoding.
+ * Given an encoding, return the name that was used to constuct the
+ * encoding.
*
* Results:
* The name of the encoding.
@@ -607,16 +878,14 @@ FreeEncoding(encoding)
*/
CONST char *
-Tcl_GetEncodingName(encoding)
- Tcl_Encoding encoding; /* The encoding whose name to fetch. */
+Tcl_GetEncodingName(
+ Tcl_Encoding encoding) /* The encoding whose name to fetch. */
{
- Encoding *encodingPtr;
-
if (encoding == NULL) {
encoding = systemEncoding;
}
- encodingPtr = (Encoding *) encoding;
- return encodingPtr->name;
+
+ return ((Encoding *) encoding)->name;
}
/*
@@ -624,8 +893,8 @@ Tcl_GetEncodingName(encoding)
*
* Tcl_GetEncodingNames --
*
- * Get the list of all known encodings, including the ones stored
- * as files on disk in the encoding path.
+ * Get the list of all known encodings, including the ones stored as
+ * files on disk in the encoding path.
*
* Results:
* Modifies interp's result object to hold a list of all the available
@@ -638,102 +907,53 @@ Tcl_GetEncodingName(encoding)
*/
void
-Tcl_GetEncodingNames(interp)
- Tcl_Interp *interp; /* Interp to hold result. */
+Tcl_GetEncodingNames(
+ Tcl_Interp *interp) /* Interp to hold result. */
{
+ Tcl_HashTable table;
Tcl_HashSearch search;
Tcl_HashEntry *hPtr;
- Tcl_Obj *pathPtr, *resultPtr;
- int dummy;
+ Tcl_Obj *map, *name, *result = Tcl_NewObj();
+ Tcl_DictSearch mapSearch;
+ int dummy, done = 0;
- Tcl_HashTable table;
+ Tcl_InitObjHashTable(&table);
+
+ /*
+ * Copy encoding names from loaded encoding table to table.
+ */
Tcl_MutexLock(&encodingMutex);
- Tcl_InitHashTable(&table, TCL_STRING_KEYS);
- hPtr = Tcl_FirstHashEntry(&encodingTable, &search);
- while (hPtr != NULL) {
- Encoding *encodingPtr;
-
- encodingPtr = (Encoding *) Tcl_GetHashValue(hPtr);
- Tcl_CreateHashEntry(&table, encodingPtr->name, &dummy);
- hPtr = Tcl_NextHashEntry(&search);
+ for (hPtr = Tcl_FirstHashEntry(&encodingTable, &search); hPtr != NULL;
+ hPtr = Tcl_NextHashEntry(&search)) {
+ Encoding *encodingPtr = (Encoding *) Tcl_GetHashValue(hPtr);
+ Tcl_CreateHashEntry(&table,
+ (char *) Tcl_NewStringObj(encodingPtr->name, -1), &dummy);
}
Tcl_MutexUnlock(&encodingMutex);
- pathPtr = TclGetLibraryPath();
- if (pathPtr != NULL) {
- int i, objc;
- Tcl_Obj **objv;
- char globArgString[10];
- Tcl_Obj* encodingObj = Tcl_NewStringObj("encoding",-1);
- Tcl_IncrRefCount(encodingObj);
-
- objc = 0;
- Tcl_ListObjGetElements(NULL, pathPtr, &objc, &objv);
-
- for (i = 0; i < objc; i++) {
- Tcl_Obj *searchIn;
-
- /*
- * Construct the path from the element of pathPtr,
- * joined with 'encoding'.
- */
- searchIn = Tcl_FSJoinToPath(objv[i],1,&encodingObj);
- Tcl_IncrRefCount(searchIn);
- Tcl_ResetResult(interp);
+ FillEncodingFileMap();
+ map = TclGetProcessGlobalValue(&encodingFileMap);
- /*
- * TclGlob() changes the contents of globArgString, which causes
- * a segfault if we pass in a pointer to non-writeable memory.
- * TclGlob() puts its results directly into interp.
- */
+ /*
+ * Copy encoding names from encoding file map to table.
+ */
- strcpy(globArgString, "*.enc");
- /*
- * The GLOBMODE_TAILS flag returns just the tail of each file
- * which is the encoding name with a .enc extension
- */
- if ((TclGlob(interp, globArgString, searchIn,
- TCL_GLOBMODE_TAILS, NULL) == TCL_OK)) {
- int objc2 = 0;
- Tcl_Obj **objv2;
- int j;
-
- Tcl_ListObjGetElements(NULL, Tcl_GetObjResult(interp), &objc2,
- &objv2);
-
- for (j = 0; j < objc2; j++) {
- int length;
- char *string;
- string = Tcl_GetStringFromObj(objv2[j], &length);
- length -= 4;
- if (length > 0) {
- string[length] = '\0';
- Tcl_CreateHashEntry(&table, string, &dummy);
- string[length] = '.';
- }
- }
- }
- Tcl_DecrRefCount(searchIn);
- }
- Tcl_DecrRefCount(encodingObj);
+ Tcl_DictObjFirst(NULL, map, &mapSearch, &name, NULL, &done);
+ for (; !done; Tcl_DictObjNext(&mapSearch, &name, NULL, &done)) {
+ Tcl_CreateHashEntry(&table, (char *) name, &dummy);
}
/*
- * Clear any values placed in the result by globbing.
+ * Pull all encoding names from table into the result list.
*/
- Tcl_ResetResult(interp);
- resultPtr = Tcl_GetObjResult(interp);
-
- hPtr = Tcl_FirstHashEntry(&table, &search);
- while (hPtr != NULL) {
- Tcl_Obj *strPtr;
-
- strPtr = Tcl_NewStringObj(Tcl_GetHashKey(&table, hPtr), -1);
- Tcl_ListObjAppendElement(NULL, resultPtr, strPtr);
- hPtr = Tcl_NextHashEntry(&search);
+ for (hPtr = Tcl_FirstHashEntry(&table, &search); hPtr != NULL;
+ hPtr = Tcl_NextHashEntry(&search)) {
+ Tcl_ListObjAppendElement(NULL, result,
+ (Tcl_Obj *) Tcl_GetHashKey(&table, hPtr));
}
+ Tcl_SetObjResult(interp, result);
Tcl_DeleteHashTable(&table);
}
@@ -742,29 +962,29 @@ Tcl_GetEncodingNames(interp)
*
* Tcl_SetSystemEncoding --
*
- * Sets the default encoding that should be used whenever the user
- * passes a NULL value in to one of the conversion routines.
- * If the supplied name is NULL, the system encoding is reset to the
- * default system encoding.
+ * Sets the default encoding that should be used whenever the user passes
+ * a NULL value in to one of the conversion routines. If the supplied
+ * name is NULL, the system encoding is reset to the default system
+ * encoding.
*
* Results:
- * The return value is TCL_OK if the system encoding was successfully
- * set to the encoding specified by name, TCL_ERROR otherwise. If
- * TCL_ERROR is returned, an error message is left in interp's result
- * object, unless interp was NULL.
+ * The return value is TCL_OK if the system encoding was successfully set
+ * to the encoding specified by name, TCL_ERROR otherwise. If TCL_ERROR
+ * is returned, an error message is left in interp's result object,
+ * unless interp was NULL.
*
* Side effects:
- * The reference count of the new system encoding is incremented.
- * The reference count of the old system encoding is decremented and
- * it may be freed.
+ * The reference count of the new system encoding is incremented. The
+ * reference count of the old system encoding is decremented and it may
+ * be freed.
*
*------------------------------------------------------------------------
*/
int
-Tcl_SetSystemEncoding(interp, name)
- Tcl_Interp *interp; /* Interp for error reporting, if not NULL. */
- CONST char *name; /* The name of the desired encoding, or NULL
+Tcl_SetSystemEncoding(
+ Tcl_Interp *interp, /* Interp for error reporting, if not NULL. */
+ CONST char *name) /* The name of the desired encoding, or NULL
* to reset to default encoding. */
{
Tcl_Encoding encoding;
@@ -796,50 +1016,51 @@ Tcl_SetSystemEncoding(interp, name)
*
* Tcl_CreateEncoding --
*
- * This procedure is called to define a new encoding and the procedures
- * that are used to convert between the specified encoding and Unicode.
+ * This function is called to define a new encoding and the functions
+ * that are used to convert between the specified encoding and Unicode.
*
* Results:
- * Returns a token that represents the encoding. If an encoding with
- * the same name already existed, the old encoding token remains
- * valid and continues to behave as it used to, and will eventually
- * be garbage collected when the last reference to it goes away. Any
- * subsequent calls to Tcl_GetEncoding with the specified name will
- * retrieve the most recent encoding token.
+ * Returns a token that represents the encoding. If an encoding with the
+ * same name already existed, the old encoding token remains valid and
+ * continues to behave as it used to, and will eventually be garbage
+ * collected when the last reference to it goes away. Any subsequent
+ * calls to Tcl_GetEncoding with the specified name will retrieve the
+ * most recent encoding token.
*
* Side effects:
* The new encoding type is entered into a table visible to all
- * interpreters, keyed off the encoding's name. For each call to
- * this procedure, there should eventually be a call to
- * Tcl_FreeEncoding, so that the database can be cleaned up when
- * encodings aren't needed anymore.
+ * interpreters, keyed off the encoding's name. For each call to this
+ * function, there should eventually be a call to Tcl_FreeEncoding, so
+ * that the database can be cleaned up when encodings aren't needed
+ * anymore.
*
*---------------------------------------------------------------------------
- */
+ */
Tcl_Encoding
-Tcl_CreateEncoding(typePtr)
- Tcl_EncodingType *typePtr; /* The encoding type. */
+Tcl_CreateEncoding(
+ const Tcl_EncodingType *typePtr)
+ /* The encoding type. */
{
Tcl_HashEntry *hPtr;
- int new;
+ int isNew;
Encoding *encodingPtr;
char *name;
Tcl_MutexLock(&encodingMutex);
- hPtr = Tcl_CreateHashEntry(&encodingTable, typePtr->encodingName, &new);
- if (new == 0) {
+ hPtr = Tcl_CreateHashEntry(&encodingTable, typePtr->encodingName, &isNew);
+ if (isNew == 0) {
/*
- * Remove old encoding from hash table, but don't delete it until
- * last reference goes away.
+ * Remove old encoding from hash table, but don't delete it until last
+ * reference goes away.
*/
-
+
encodingPtr = (Encoding *) Tcl_GetHashValue(hPtr);
encodingPtr->hPtr = NULL;
}
name = ckalloc((unsigned) strlen(typePtr->encodingName) + 1);
-
+
encodingPtr = (Encoding *) ckalloc(sizeof(Encoding));
encodingPtr->name = strcpy(name, typePtr->encodingName);
encodingPtr->toUtfProc = typePtr->toUtfProc;
@@ -866,15 +1087,15 @@ Tcl_CreateEncoding(typePtr)
*
* Tcl_ExternalToUtfDString --
*
- * Convert a source buffer from the specified encoding into UTF-8.
- * If any of the bytes in the source buffer are invalid or cannot
- * be represented in the target encoding, a default fallback
- * character will be substituted.
+ * Convert a source buffer from the specified encoding into UTF-8. If any
+ * of the bytes in the source buffer are invalid or cannot be represented
+ * in the target encoding, a default fallback character will be
+ * substituted.
*
* Results:
* The converted bytes are stored in the DString, which is then NULL
- * terminated. The return value is a pointer to the value stored
- * in the DString.
+ * terminated. The return value is a pointer to the value stored in the
+ * DString.
*
* Side effects:
* None.
@@ -882,15 +1103,15 @@ Tcl_CreateEncoding(typePtr)
*-------------------------------------------------------------------------
*/
-char *
-Tcl_ExternalToUtfDString(encoding, src, srcLen, dstPtr)
- Tcl_Encoding encoding; /* The encoding for the source string, or
- * NULL for the default system encoding. */
- CONST char *src; /* Source string in specified encoding. */
- int srcLen; /* Source string length in bytes, or < 0 for
+char *
+Tcl_ExternalToUtfDString(
+ Tcl_Encoding encoding, /* The encoding for the source string, or NULL
+ * for the default system encoding. */
+ CONST char *src, /* Source string in specified encoding. */
+ int srcLen, /* Source string length in bytes, or < 0 for
* encoding-specific string length. */
- Tcl_DString *dstPtr; /* Uninitialized or free DString in which
- * the converted string is stored. */
+ Tcl_DString *dstPtr) /* Uninitialized or free DString in which the
+ * converted string is stored. */
{
char *dst;
Tcl_EncodingState state;
@@ -900,7 +1121,7 @@ Tcl_ExternalToUtfDString(encoding, src, srcLen, dstPtr)
Tcl_DStringInit(dstPtr);
dst = Tcl_DStringValue(dstPtr);
dstLen = dstPtr->spaceAvl - 1;
-
+
if (encoding == NULL) {
encoding = systemEncoding;
}
@@ -911,16 +1132,20 @@ Tcl_ExternalToUtfDString(encoding, src, srcLen, dstPtr)
} else if (srcLen < 0) {
srcLen = (*encodingPtr->lengthProc)(src);
}
+
flags = TCL_ENCODING_START | TCL_ENCODING_END;
+
while (1) {
result = (*encodingPtr->toUtfProc)(encodingPtr->clientData, src,
srcLen, flags, &state, dst, dstLen, &srcRead, &dstWrote,
&dstChars);
soFar = dst + dstWrote - Tcl_DStringValue(dstPtr);
+
if (result != TCL_CONVERT_NOSPACE) {
Tcl_DStringSetLength(dstPtr, soFar);
return Tcl_DStringValue(dstPtr);
}
+
flags &= ~TCL_ENCODING_START;
src += srcRead;
srcLen -= srcRead;
@@ -942,50 +1167,49 @@ Tcl_ExternalToUtfDString(encoding, src, srcLen, dstPtr)
*
* Results:
* The return value is one of TCL_OK, TCL_CONVERT_MULTIBYTE,
- * TCL_CONVERT_SYNTAX, TCL_CONVERT_UNKNOWN, or TCL_CONVERT_NOSPACE,
- * as documented in tcl.h.
+ * TCL_CONVERT_SYNTAX, TCL_CONVERT_UNKNOWN, or TCL_CONVERT_NOSPACE, as
+ * documented in tcl.h.
*
* Side effects:
- * The converted bytes are stored in the output buffer.
+ * The converted bytes are stored in the output buffer.
*
*-------------------------------------------------------------------------
*/
int
-Tcl_ExternalToUtf(interp, encoding, src, srcLen, flags, statePtr, dst,
- dstLen, srcReadPtr, dstWrotePtr, dstCharsPtr)
- Tcl_Interp *interp; /* Interp for error return, if not NULL. */
- Tcl_Encoding encoding; /* The encoding for the source string, or
- * NULL for the default system encoding. */
- CONST char *src; /* Source string in specified encoding. */
- int srcLen; /* Source string length in bytes, or < 0 for
+Tcl_ExternalToUtf(
+ Tcl_Interp *interp, /* Interp for error return, if not NULL. */
+ Tcl_Encoding encoding, /* The encoding for the source string, or NULL
+ * for the default system encoding. */
+ CONST char *src, /* Source string in specified encoding. */
+ int srcLen, /* Source string length in bytes, or < 0 for
* encoding-specific string length. */
- int flags; /* Conversion control flags. */
- Tcl_EncodingState *statePtr;/* Place for conversion routine to store
- * state information used during a piecewise
- * conversion. Contents of statePtr are
+ int flags, /* Conversion control flags. */
+ Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
+ * information used during a piecewise
+ * conversion. Contents of statePtr are
* initialized and/or reset by conversion
* routine under control of flags argument. */
- char *dst; /* Output buffer in which converted string
- * is stored. */
- int dstLen; /* The maximum length of output buffer in
+ char *dst, /* Output buffer in which converted string is
+ * stored. */
+ int dstLen, /* The maximum length of output buffer in
* bytes. */
- int *srcReadPtr; /* Filled with the number of bytes from the
- * source string that were converted. This
- * may be less than the original source length
- * if there was a problem converting some
- * source characters. */
- int *dstWrotePtr; /* Filled with the number of bytes that were
+ int *srcReadPtr, /* Filled with the number of bytes from the
+ * source string that were converted. This may
+ * be less than the original source length if
+ * there was a problem converting some source
+ * characters. */
+ int *dstWrotePtr, /* Filled with the number of bytes that were
* stored in the output buffer as a result of
* the conversion. */
- int *dstCharsPtr; /* Filled with the number of characters that
+ int *dstCharsPtr) /* Filled with the number of characters that
* correspond to the bytes stored in the
* output buffer. */
{
Encoding *encodingPtr;
int result, srcRead, dstWrote, dstChars;
Tcl_EncodingState state;
-
+
if (encoding == NULL) {
encoding = systemEncoding;
}
@@ -1012,8 +1236,8 @@ Tcl_ExternalToUtf(interp, encoding, src, srcLen, flags, statePtr, dst,
/*
* If there are any null characters in the middle of the buffer, they will
- * converted to the UTF-8 null character (\xC080). To get the actual
- * \0 at the end of the destination buffer, we need to append it manually.
+ * converted to the UTF-8 null character (\xC080). To get the actual \0 at
+ * the end of the destination buffer, we need to append it manually.
*/
dstLen--;
@@ -1021,6 +1245,7 @@ Tcl_ExternalToUtf(interp, encoding, src, srcLen, flags, statePtr, dst,
flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr,
dstCharsPtr);
dst[*dstWrotePtr] = '\0';
+
return result;
}
@@ -1029,15 +1254,15 @@ Tcl_ExternalToUtf(interp, encoding, src, srcLen, flags, statePtr, dst,
*
* Tcl_UtfToExternalDString --
*
- * Convert a source buffer from UTF-8 into the specified encoding.
- * If any of the bytes in the source buffer are invalid or cannot
- * be represented in the target encoding, a default fallback
- * character will be substituted.
+ * Convert a source buffer from UTF-8 into the specified encoding. If any
+ * of the bytes in the source buffer are invalid or cannot be represented
+ * in the target encoding, a default fallback character will be
+ * substituted.
*
* Results:
- * The converted bytes are stored in the DString, which is then
- * NULL terminated in an encoding-specific manner. The return value
- * is a pointer to the value stored in the DString.
+ * The converted bytes are stored in the DString, which is then NULL
+ * terminated in an encoding-specific manner. The return value is a
+ * pointer to the value stored in the DString.
*
* Side effects:
* None.
@@ -1046,20 +1271,20 @@ Tcl_ExternalToUtf(interp, encoding, src, srcLen, flags, statePtr, dst,
*/
char *
-Tcl_UtfToExternalDString(encoding, src, srcLen, dstPtr)
- Tcl_Encoding encoding; /* The encoding for the converted string,
- * or NULL for the default system encoding. */
- CONST char *src; /* Source string in UTF-8. */
- int srcLen; /* Source string length in bytes, or < 0 for
+Tcl_UtfToExternalDString(
+ Tcl_Encoding encoding, /* The encoding for the converted string, or
+ * NULL for the default system encoding. */
+ CONST char *src, /* Source string in UTF-8. */
+ int srcLen, /* Source string length in bytes, or < 0 for
* strlen(). */
- Tcl_DString *dstPtr; /* Uninitialized or free DString in which
- * the converted string is stored. */
+ Tcl_DString *dstPtr) /* Uninitialized or free DString in which the
+ * converted string is stored. */
{
char *dst;
Tcl_EncodingState state;
Encoding *encodingPtr;
int flags, dstLen, result, soFar, srcRead, dstWrote, dstChars;
-
+
Tcl_DStringInit(dstPtr);
dst = Tcl_DStringValue(dstPtr);
dstLen = dstPtr->spaceAvl - 1;
@@ -1080,13 +1305,15 @@ Tcl_UtfToExternalDString(encoding, src, srcLen, dstPtr)
srcLen, flags, &state, dst, dstLen, &srcRead, &dstWrote,
&dstChars);
soFar = dst + dstWrote - Tcl_DStringValue(dstPtr);
+
if (result != TCL_CONVERT_NOSPACE) {
if (encodingPtr->nullSize == 2) {
- Tcl_DStringSetLength(dstPtr, soFar + 1);
+ Tcl_DStringSetLength(dstPtr, soFar + 1);
}
Tcl_DStringSetLength(dstPtr, soFar);
return Tcl_DStringValue(dstPtr);
}
+
flags &= ~TCL_ENCODING_START;
src += srcRead;
srcLen -= srcRead;
@@ -1108,50 +1335,49 @@ Tcl_UtfToExternalDString(encoding, src, srcLen, dstPtr)
*
* Results:
* The return value is one of TCL_OK, TCL_CONVERT_MULTIBYTE,
- * TCL_CONVERT_SYNTAX, TCL_CONVERT_UNKNOWN, or TCL_CONVERT_NOSPACE,
- * as documented in tcl.h.
+ * TCL_CONVERT_SYNTAX, TCL_CONVERT_UNKNOWN, or TCL_CONVERT_NOSPACE, as
+ * documented in tcl.h.
*
* Side effects:
- * The converted bytes are stored in the output buffer.
+ * The converted bytes are stored in the output buffer.
*
*-------------------------------------------------------------------------
*/
int
-Tcl_UtfToExternal(interp, encoding, src, srcLen, flags, statePtr, dst,
- dstLen, srcReadPtr, dstWrotePtr, dstCharsPtr)
- Tcl_Interp *interp; /* Interp for error return, if not NULL. */
- Tcl_Encoding encoding; /* The encoding for the converted string,
- * or NULL for the default system encoding. */
- CONST char *src; /* Source string in UTF-8. */
- int srcLen; /* Source string length in bytes, or < 0 for
+Tcl_UtfToExternal(
+ Tcl_Interp *interp, /* Interp for error return, if not NULL. */
+ Tcl_Encoding encoding, /* The encoding for the converted string, or
+ * NULL for the default system encoding. */
+ CONST char *src, /* Source string in UTF-8. */
+ int srcLen, /* Source string length in bytes, or < 0 for
* strlen(). */
- int flags; /* Conversion control flags. */
- Tcl_EncodingState *statePtr;/* Place for conversion routine to store
- * state information used during a piecewise
- * conversion. Contents of statePtr are
+ int flags, /* Conversion control flags. */
+ Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
+ * information used during a piecewise
+ * conversion. Contents of statePtr are
* initialized and/or reset by conversion
* routine under control of flags argument. */
- char *dst; /* Output buffer in which converted string
+ char *dst, /* Output buffer in which converted string
* is stored. */
- int dstLen; /* The maximum length of output buffer in
+ int dstLen, /* The maximum length of output buffer in
* bytes. */
- int *srcReadPtr; /* Filled with the number of bytes from the
- * source string that were converted. This
- * may be less than the original source length
- * if there was a problem converting some
- * source characters. */
- int *dstWrotePtr; /* Filled with the number of bytes that were
+ int *srcReadPtr, /* Filled with the number of bytes from the
+ * source string that were converted. This may
+ * be less than the original source length if
+ * there was a problem converting some source
+ * characters. */
+ int *dstWrotePtr, /* Filled with the number of bytes that were
* stored in the output buffer as a result of
* the conversion. */
- int *dstCharsPtr; /* Filled with the number of characters that
+ int *dstCharsPtr) /* Filled with the number of characters that
* correspond to the bytes stored in the
* output buffer. */
{
Encoding *encodingPtr;
int result, srcRead, dstWrote, dstChars;
Tcl_EncodingState state;
-
+
if (encoding == NULL) {
encoding = systemEncoding;
}
@@ -1184,7 +1410,7 @@ Tcl_UtfToExternal(interp, encoding, src, srcLen, flags, statePtr, dst,
dst[*dstWrotePtr + 1] = '\0';
}
dst[*dstWrotePtr] = '\0';
-
+
return result;
}
@@ -1193,78 +1419,142 @@ Tcl_UtfToExternal(interp, encoding, src, srcLen, flags, statePtr, dst,
*
* Tcl_FindExecutable --
*
- * This procedure computes the absolute path name of the current
+ * This function computes the absolute path name of the current
* application, given its argv[0] value.
*
* Results:
* None.
*
* Side effects:
- * The variable tclExecutableName gets filled in with the file
- * name for the application, if we figured it out. If we couldn't
- * figure it out, tclExecutableName is set to NULL.
+ * The absolute pathname for the application is computed and stored to be
+ * returned later be [info nameofexecutable].
*
*---------------------------------------------------------------------------
*/
void
-Tcl_FindExecutable(argv0)
- CONST char *argv0; /* The value of the application's argv[0]
+Tcl_FindExecutable(
+ CONST char *argv0) /* The value of the application's argv[0]
* (native). */
{
- int mustCleanUtf;
- CONST char *name;
- Tcl_DString buffer, nameString;
+ TclInitSubsystems();
+ TclpSetInitialEncodings();
+ TclpFindExecutable(argv0);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * OpenEncodingFileChannel --
+ *
+ * Open the file believed to hold data for the encoding, "name".
+ *
+ * Results:
+ * Returns the readable Tcl_Channel from opening the file, or NULL if the
+ * file could not be successfully opened. If NULL was returned, an error
+ * message is left in interp's result object, unless interp was NULL.
+ *
+ * Side effects:
+ * Channel may be opened. Information about the filesystem may be cached
+ * to speed later calls.
+ *
+ *---------------------------------------------------------------------------
+ */
- TclInitSubsystems(argv0);
+static Tcl_Channel
+OpenEncodingFileChannel(
+ Tcl_Interp *interp, /* Interp for error reporting, if not NULL. */
+ CONST char *name) /* The name of the encoding file on disk and
+ * also the name for new encoding. */
+{
+ Tcl_Obj *nameObj = Tcl_NewStringObj(name, -1);
+ Tcl_Obj *fileNameObj = Tcl_DuplicateObj(nameObj);
+ Tcl_Obj *searchPath = Tcl_DuplicateObj(Tcl_GetEncodingSearchPath());
+ Tcl_Obj *map = TclGetProcessGlobalValue(&encodingFileMap);
+ Tcl_Obj **dir, *path, *directory = NULL;
+ Tcl_Channel chan = NULL;
+ int i, numDirs;
+
+ Tcl_ListObjGetElements(NULL, searchPath, &numDirs, &dir);
+ Tcl_IncrRefCount(nameObj);
+ Tcl_AppendToObj(fileNameObj, ".enc", -1);
+ Tcl_IncrRefCount(fileNameObj);
+ Tcl_DictObjGet(NULL, map, nameObj, &directory);
- if (argv0 == NULL) {
- goto done;
- }
- if (tclExecutableName != NULL) {
- ckfree(tclExecutableName);
- tclExecutableName = NULL;
+ /*
+ * Check that any cached directory is still on the encoding search path.
+ */
+
+ if (NULL != directory) {
+ int verified = 0;
+
+ for (i=0; i<numDirs && !verified; i++) {
+ if (dir[i] == directory) {
+ verified = 1;
+ }
+ }
+ if (!verified) {
+ CONST char *dirString = Tcl_GetString(directory);
+ for (i=0; i<numDirs && !verified; i++) {
+ if (strcmp(dirString, Tcl_GetString(dir[i])) == 0) {
+ verified = 1;
+ }
+ }
+ }
+ if (!verified) {
+ /*
+ * Directory no longer on the search path. Remove from cache.
+ */
+
+ map = Tcl_DuplicateObj(map);
+ Tcl_DictObjRemove(NULL, map, nameObj);
+ TclSetProcessGlobalValue(&encodingFileMap, map, NULL);
+ directory = NULL;
+ }
}
- if ((name = TclpFindExecutable(argv0)) == NULL) {
- goto done;
+
+ if (NULL != directory) {
+ /*
+ * Got a directory from the cache. Try to use it first.
+ */
+
+ Tcl_IncrRefCount(directory);
+ path = Tcl_FSJoinToPath(directory, 1, &fileNameObj);
+ Tcl_IncrRefCount(path);
+ Tcl_DecrRefCount(directory);
+ chan = Tcl_FSOpenFileChannel(NULL, path, "r", 0);
+ Tcl_DecrRefCount(path);
}
/*
- * The value returned from TclpNameOfExecutable is a UTF string that
- * is possibly dirty depending on when it was initialized.
- * TclFindEncodings will indicate whether we must "clean" the UTF (as
- * reported by the underlying system). To assure that the UTF string
- * is a properly encoded native string for this system, convert the
- * UTF string to the default native encoding before the default
- * encoding is initialized. Then, convert it back to UTF after the
- * system encoding is loaded.
+ * Scan the search path until we find it.
*/
-
- Tcl_UtfToExternalDString(NULL, name, -1, &buffer);
- mustCleanUtf = TclFindEncodings(argv0);
- /*
- * Now it is OK to convert the native string back to UTF and set
- * the value of the tclExecutableName.
- */
-
- if (mustCleanUtf) {
- Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&buffer), -1,
- &nameString);
- tclExecutableName = (char *)
- ckalloc((unsigned) (Tcl_DStringLength(&nameString) + 1));
- strcpy(tclExecutableName, Tcl_DStringValue(&nameString));
-
- Tcl_DStringFree(&nameString);
- } else {
- tclExecutableName = (char *) ckalloc((unsigned) (strlen(name) + 1));
- strcpy(tclExecutableName, name);
- }
- Tcl_DStringFree(&buffer);
- return;
-
- done:
- (void) TclFindEncodings(argv0);
+ for (i=0; i<numDirs && (chan == NULL); i++) {
+ path = Tcl_FSJoinToPath(dir[i], 1, &fileNameObj);
+ Tcl_IncrRefCount(path);
+ chan = Tcl_FSOpenFileChannel(NULL, path, "r", 0);
+ Tcl_DecrRefCount(path);
+ if (chan != NULL) {
+ /*
+ * Save directory in the cache.
+ */
+
+ map = Tcl_DuplicateObj(TclGetProcessGlobalValue(&encodingFileMap));
+ Tcl_DictObjPut(NULL, map, nameObj, dir[i]);
+ TclSetProcessGlobalValue(&encodingFileMap, map, NULL);
+ }
+ }
+
+ if ((NULL == chan) && (interp != NULL)) {
+ Tcl_AppendResult(interp, "unknown encoding \"", name, "\"", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENCODING", name, NULL);
+ }
+ Tcl_DecrRefCount(fileNameObj);
+ Tcl_DecrRefCount(nameObj);
+ Tcl_DecrRefCount(searchPath);
+
+ return chan;
}
/*
@@ -1272,50 +1562,34 @@ Tcl_FindExecutable(argv0)
*
* LoadEncodingFile --
*
- * Read a file that describes an encoding and create a new Encoding
- * from the data.
+ * Read a file that describes an encoding and create a new Encoding from
+ * the data.
*
* Results:
- * The return value is the newly loaded Encoding, or NULL if
- * the file didn't exist of was in the incorrect format. If NULL was
- * returned, an error message is left in interp's result object,
- * unless interp was NULL.
+ * The return value is the newly loaded Encoding, or NULL if the file
+ * didn't exist of was in the incorrect format. If NULL was returned, an
+ * error message is left in interp's result object, unless interp was
+ * NULL.
*
* Side effects:
- * File read from disk.
+ * File read from disk.
*
*---------------------------------------------------------------------------
*/
static Tcl_Encoding
-LoadEncodingFile(interp, name)
- Tcl_Interp *interp; /* Interp for error reporting, if not NULL. */
- CONST char *name; /* The name of the encoding file on disk
- * and also the name for new encoding. */
+LoadEncodingFile(
+ Tcl_Interp *interp, /* Interp for error reporting, if not NULL. */
+ CONST char *name) /* The name of the encoding file on disk and
+ * also the name for new encoding. */
{
- int objc, i, ch;
- Tcl_Obj **objv;
- Tcl_Obj *pathPtr;
- Tcl_Channel chan;
- Tcl_Encoding encoding;
-
- pathPtr = TclGetLibraryPath();
- if (pathPtr == NULL) {
- goto unknown;
- }
- objc = 0;
- Tcl_ListObjGetElements(NULL, pathPtr, &objc, &objv);
-
- chan = NULL;
- for (i = 0; i < objc; i++) {
- chan = OpenEncodingFile(Tcl_GetString(objv[i]), name);
- if (chan != NULL) {
- break;
- }
- }
+ Tcl_Channel chan = NULL;
+ Tcl_Encoding encoding = NULL;
+ int ch;
+ chan = OpenEncodingFileChannel(interp, name);
if (chan == NULL) {
- goto unknown;
+ return NULL;
}
Tcl_SetChannelOption(NULL, chan, "-encoding", "utf-8");
@@ -1332,89 +1606,26 @@ LoadEncodingFile(interp, name)
}
}
- encoding = NULL;
switch (ch) {
- case 'S': {
- encoding = LoadTableEncoding(interp, name, ENCODING_SINGLEBYTE,
- chan);
- break;
- }
- case 'D': {
- encoding = LoadTableEncoding(interp, name, ENCODING_DOUBLEBYTE,
- chan);
- break;
- }
- case 'M': {
- encoding = LoadTableEncoding(interp, name, ENCODING_MULTIBYTE,
- chan);
- break;
- }
- case 'E': {
- encoding = LoadEscapeEncoding(name, chan);
- break;
- }
+ case 'S':
+ encoding = LoadTableEncoding(name, ENCODING_SINGLEBYTE, chan);
+ break;
+ case 'D':
+ encoding = LoadTableEncoding(name, ENCODING_DOUBLEBYTE, chan);
+ break;
+ case 'M':
+ encoding = LoadTableEncoding(name, ENCODING_MULTIBYTE, chan);
+ break;
+ case 'E':
+ encoding = LoadEscapeEncoding(name, chan);
+ break;
}
if ((encoding == NULL) && (interp != NULL)) {
Tcl_AppendResult(interp, "invalid encoding file \"", name, "\"", NULL);
- if (ch == 'E') {
- Tcl_AppendResult(interp, " or missing sub-encoding", NULL);
- }
}
Tcl_Close(NULL, chan);
- return encoding;
- unknown:
- if (interp != NULL) {
- Tcl_AppendResult(interp, "unknown encoding \"", name, "\"", NULL);
- }
- return NULL;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * OpenEncodingFile --
- *
- * Look for the file encoding/<name>.enc in the specified
- * directory.
- *
- * Results:
- * Returns an open file channel if the file exists.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static Tcl_Channel
-OpenEncodingFile(dir, name)
- CONST char *dir;
- CONST char *name;
-
-{
- CONST char *argv[3];
- Tcl_DString pathString;
- CONST char *path;
- Tcl_Channel chan;
- Tcl_Obj *pathPtr;
-
- argv[0] = dir;
- argv[1] = "encoding";
- argv[2] = name;
-
- Tcl_DStringInit(&pathString);
- Tcl_JoinPath(3, argv, &pathString);
- path = Tcl_DStringAppend(&pathString, ".enc", -1);
- pathPtr = Tcl_NewStringObj(path,-1);
-
- Tcl_IncrRefCount(pathPtr);
- chan = Tcl_FSOpenFileChannel(NULL, pathPtr, "r", 0);
- Tcl_DecrRefCount(pathPtr);
-
- Tcl_DStringFree(&pathString);
-
- return chan;
+ return encoding;
}
/*
@@ -1422,17 +1633,17 @@ OpenEncodingFile(dir, name)
*
* LoadTableEncoding --
*
- * Helper function for LoadEncodingTable(). Loads a table to that
- * converts between Unicode and some other encoding and creates an
+ * Helper function for LoadEncodingTable(). Loads a table to that
+ * converts between Unicode and some other encoding and creates an
* encoding (using a TableEncoding structure) from that information.
*
- * File contains binary data, but begins with a marker to indicate
- * byte-ordering, so that same binary file can be read on either
- * endian platforms.
+ * File contains binary data, but begins with a marker to indicate
+ * byte-ordering, so that same binary file can be read on either endian
+ * platforms.
*
* Results:
- * The return value is the new encoding, or NULL if the encoding
- * could not be created (because the file contained invalid data).
+ * The return value is the new encoding, or NULL if the encoding could
+ * not be created (because the file contained invalid data).
*
* Side effects:
* None.
@@ -1441,11 +1652,10 @@ OpenEncodingFile(dir, name)
*/
static Tcl_Encoding
-LoadTableEncoding(interp, name, type, chan)
- Tcl_Interp *interp; /* Interp for temporary obj while reading. */
- CONST char *name; /* Name for new encoding. */
- int type; /* Type of encoding (ENCODING_?????). */
- Tcl_Channel chan; /* File containing new encoding. */
+LoadTableEncoding(
+ CONST char *name, /* Name for new encoding. */
+ int type, /* Type of encoding (ENCODING_?????). */
+ Tcl_Channel chan) /* File containing new encoding. */
{
Tcl_DString lineString;
Tcl_Obj *objPtr;
@@ -1507,9 +1717,9 @@ LoadTableEncoding(interp, name, type, chan)
dataPtr->fallback = fallback;
/*
- * Read the table that maps characters to Unicode. Performs a single
- * malloc to get the memory for the array and all the pages needed by
- * the array.
+ * Read the table that maps characters to Unicode. Performs a single
+ * malloc to get the memory for the array and all the pages needed by the
+ * array.
*/
size = 256 * sizeof(unsigned short *) + numPages * PAGESIZE;
@@ -1517,26 +1727,23 @@ LoadTableEncoding(interp, name, type, chan)
memset(dataPtr->toUnicode, 0, size);
pageMemPtr = (unsigned short *) (dataPtr->toUnicode + 256);
- if (interp == NULL) {
- objPtr = Tcl_NewObj();
- } else {
- objPtr = Tcl_GetObjResult(interp);
- }
+ TclNewObj(objPtr);
+ Tcl_IncrRefCount(objPtr);
for (i = 0; i < numPages; i++) {
int ch;
char *p;
Tcl_ReadChars(chan, objPtr, 3 + 16 * (16 * 4 + 1), 0);
p = Tcl_GetString(objPtr);
- hi = (staticHex[(unsigned int)p[0]] << 4) + staticHex[(unsigned int)p[1]];
+ hi = (staticHex[UCHAR(p[0])] << 4) + staticHex[UCHAR(p[1])];
dataPtr->toUnicode[hi] = pageMemPtr;
p += 2;
for (lo = 0; lo < 256; lo++) {
if ((lo & 0x0f) == 0) {
p++;
}
- ch = (staticHex[(unsigned int)p[0]] << 12) + (staticHex[(unsigned int)p[1]] << 8)
- + (staticHex[(unsigned int)p[2]] << 4) + staticHex[(unsigned int)p[3]];
+ ch = (staticHex[UCHAR(p[0])] << 12) + (staticHex[UCHAR(p[1])] << 8)
+ + (staticHex[UCHAR(p[2])] << 4) + staticHex[UCHAR(p[3])];
if (ch != 0) {
used[ch >> 8] = 1;
}
@@ -1545,12 +1752,8 @@ LoadTableEncoding(interp, name, type, chan)
p += 4;
}
}
- if (interp == NULL) {
- Tcl_DecrRefCount(objPtr);
- } else {
- Tcl_ResetResult(interp);
- }
-
+ TclDecrRefCount(objPtr);
+
if (type == ENCODING_DOUBLEBYTE) {
memset(dataPtr->prefixBytes, 1, sizeof(dataPtr->prefixBytes));
} else {
@@ -1562,10 +1765,10 @@ LoadTableEncoding(interp, name, type, chan)
}
/*
- * Invert toUnicode array to produce the fromUnicode array. Performs a
- * single malloc to get the memory for the array and all the pages
- * needed by the array. While reading in the toUnicode array, we
- * remembered what pages that would be needed for the fromUnicode array.
+ * Invert toUnicode array to produce the fromUnicode array. Performs a
+ * single malloc to get the memory for the array and all the pages needed
+ * by the array. While reading in the toUnicode array, we remembered what
+ * pages that would be needed for the fromUnicode array.
*/
if (symbol) {
@@ -1592,7 +1795,7 @@ LoadTableEncoding(interp, name, type, chan)
ch = dataPtr->toUnicode[hi][lo];
if (ch != 0) {
unsigned short *page;
-
+
page = dataPtr->fromUnicode[ch >> 8];
if (page == NULL) {
page = pageMemPtr;
@@ -1607,7 +1810,7 @@ LoadTableEncoding(interp, name, type, chan)
if (type == ENCODING_MULTIBYTE) {
/*
* If multibyte encodings don't have a backslash character, define
- * one. Otherwise, on Windows, native file names won't work because
+ * one. Otherwise, on Windows, native file names won't work because
* the backslash in the file name will map to the unknown character
* (question mark) when converting from UTF-8 to external encoding.
*/
@@ -1620,16 +1823,15 @@ LoadTableEncoding(interp, name, type, chan)
}
if (symbol) {
unsigned short *page;
-
+
/*
* Make a special symbol encoding that not only maps the symbol
* characters from their Unicode code points down into page 0, but
- * also ensure that the characters on page 0 map to themselves.
- * This is so that a symbol font can be used to display a simple
- * string like "abcd" and have alpha, beta, chi, delta show up,
- * rather than have "unknown" chars show up because strictly
- * speaking the symbol font doesn't have glyphs for those low ascii
- * chars.
+ * also ensure that the characters on page 0 map to themselves. This
+ * is so that a symbol font can be used to display a simple string
+ * like "abcd" and have alpha, beta, chi, delta show up, rather than
+ * have "unknown" chars show up because strictly speaking the symbol
+ * font doesn't have glyphs for those low ascii chars.
*/
page = dataPtr->fromUnicode[0];
@@ -1648,15 +1850,23 @@ LoadTableEncoding(interp, name, type, chan)
dataPtr->fromUnicode[hi] = emptyPage;
}
}
+
/*
- * For trailing 'R'everse encoding, see [Patch #689341]
+ * For trailing 'R'everse encoding, see [Patch 689341]
*/
+
Tcl_DStringInit(&lineString);
do {
int len;
- /* skip leading empty lines */
- while ((len = Tcl_Gets(chan, &lineString)) == 0)
- ;
+
+ /*
+ * Skip leading empty lines.
+ */
+
+ while ((len = Tcl_Gets(chan, &lineString)) == 0) {
+ /* empty body */
+ }
+
if (len < 0) {
break;
}
@@ -1665,16 +1875,17 @@ LoadTableEncoding(interp, name, type, chan)
break;
}
for (Tcl_DStringSetLength(&lineString, 0);
- (len = Tcl_Gets(chan, &lineString)) >= 0;
- Tcl_DStringSetLength(&lineString, 0)) {
+ (len = Tcl_Gets(chan, &lineString)) >= 0;
+ Tcl_DStringSetLength(&lineString, 0)) {
unsigned char* p;
int to, from;
+
if (len < 5) {
continue;
}
p = (unsigned char*) Tcl_DStringValue(&lineString);
to = (staticHex[p[0]] << 12) + (staticHex[p[1]] << 8)
- + (staticHex[p[2]] << 4) + staticHex[p[3]];
+ + (staticHex[p[2]] << 4) + staticHex[p[3]];
if (to == 0) {
continue;
}
@@ -1696,6 +1907,7 @@ LoadTableEncoding(interp, name, type, chan)
encType.freeProc = TableFreeProc;
encType.nullSize = (type == ENCODING_DOUBLEBYTE) ? 2 : 1;
encType.clientData = (ClientData) dataPtr;
+
return Tcl_CreateEncoding(&encType);
}
@@ -1704,16 +1916,16 @@ LoadTableEncoding(interp, name, type, chan)
*
* LoadEscapeEncoding --
*
- * Helper function for LoadEncodingTable(). Loads a state machine
- * that converts between Unicode and some other encoding.
+ * Helper function for LoadEncodingTable(). Loads a state machine that
+ * converts between Unicode and some other encoding.
*
- * File contains text data that describes the escape sequences that
- * are used to choose an encoding and the associated names for the
+ * File contains text data that describes the escape sequences that are
+ * used to choose an encoding and the associated names for the
* sub-encodings.
*
* Results:
- * The return value is the new encoding, or NULL if the encoding
- * could not be created (because the file contained invalid data).
+ * The return value is the new encoding, or NULL if the encoding could
+ * not be created (because the file contained invalid data).
*
* Side effects:
* None.
@@ -1722,11 +1934,11 @@ LoadTableEncoding(interp, name, type, chan)
*/
static Tcl_Encoding
-LoadEscapeEncoding(name, chan)
- CONST char *name; /* Name for new encoding. */
- Tcl_Channel chan; /* File containing new encoding. */
+LoadEscapeEncoding(
+ CONST char *name, /* Name for new encoding. */
+ Tcl_Channel chan) /* File containing new encoding. */
{
- int i, missingSubEncoding = 0;
+ int i;
unsigned int size;
Tcl_DString escapeData;
char init[16], final[16];
@@ -1742,18 +1954,18 @@ LoadEscapeEncoding(name, chan)
CONST char **argv;
char *line;
Tcl_DString lineString;
-
+
Tcl_DStringInit(&lineString);
if (Tcl_Gets(chan, &lineString) < 0) {
break;
}
line = Tcl_DStringValue(&lineString);
- if (Tcl_SplitList(NULL, line, &argc, &argv) != TCL_OK) {
+ if (Tcl_SplitList(NULL, line, &argc, &argv) != TCL_OK) {
continue;
}
if (argc >= 2) {
if (strcmp(argv[0], "name") == 0) {
- ;
+ /* do nothing */
} else if (strcmp(argv[0], "init") == 0) {
strncpy(init, argv[1], sizeof(init));
init[sizeof(init) - 1] = '\0';
@@ -1762,6 +1974,7 @@ LoadEscapeEncoding(name, chan)
final[sizeof(final) - 1] = '\0';
} else {
EscapeSubTable est;
+ Encoding *e;
strncpy(est.sequence, argv[1], sizeof(est.sequence));
est.sequence[sizeof(est.sequence) - 1] = '\0';
@@ -1771,36 +1984,33 @@ LoadEscapeEncoding(name, chan)
est.name[sizeof(est.name) - 1] = '\0';
/*
- * Load the subencodings first so we're never stuck
- * trying to use a half-loaded system encoding to
- * open/read a *.enc file.
+ * To avoid infinite recursion in [encoding system iso2022-*]
*/
- est.encodingPtr = (Encoding *) Tcl_GetEncoding(NULL, est.name);
- if ((est.encodingPtr == NULL)
- || (est.encodingPtr->toUtfProc != TableToUtfProc)) {
- missingSubEncoding = 1;
+ e = (Encoding *) Tcl_GetEncoding(NULL, est.name);
+ if (e && e->toUtfProc != TableToUtfProc &&
+ e->toUtfProc != Iso88591ToUtfProc) {
+ Tcl_FreeEncoding((Tcl_Encoding) e);
+ e = NULL;
}
+ est.encodingPtr = e;
Tcl_DStringAppend(&escapeData, (char *) &est, sizeof(est));
}
}
ckfree((char *) argv);
Tcl_DStringFree(&lineString);
}
- if (missingSubEncoding) {
- Tcl_DStringFree(&escapeData);
- return NULL;
- }
- size = sizeof(EscapeEncodingData)
- - sizeof(EscapeSubTable) + Tcl_DStringLength(&escapeData);
+ size = sizeof(EscapeEncodingData) - sizeof(EscapeSubTable)
+ + Tcl_DStringLength(&escapeData);
dataPtr = (EscapeEncodingData *) ckalloc(size);
dataPtr->initLen = strlen(init);
strcpy(dataPtr->init, init);
dataPtr->finalLen = strlen(final);
strcpy(dataPtr->final, final);
- dataPtr->numSubTables = Tcl_DStringLength(&escapeData) / sizeof(EscapeSubTable);
- memcpy((VOID *) dataPtr->subTables, (VOID *) Tcl_DStringValue(&escapeData),
+ dataPtr->numSubTables =
+ Tcl_DStringLength(&escapeData) / sizeof(EscapeSubTable);
+ memcpy(dataPtr->subTables, Tcl_DStringValue(&escapeData),
(size_t) Tcl_DStringLength(&escapeData));
Tcl_DStringFree(&escapeData);
@@ -1830,9 +2040,9 @@ LoadEscapeEncoding(name, chan)
*
* BinaryProc --
*
- * The default conversion when no other conversion is specified.
- * No translation is done; source bytes are copied directly to
- * destination bytes.
+ * The default conversion when no other conversion is specified. No
+ * translation is done; source bytes are copied directly to destination
+ * bytes.
*
* Results:
* Returns TCL_OK if conversion was successful.
@@ -1844,27 +2054,26 @@ LoadEscapeEncoding(name, chan)
*/
static int
-BinaryProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
- srcReadPtr, dstWrotePtr, dstCharsPtr)
- ClientData clientData; /* Not used. */
- CONST char *src; /* Source string (unknown encoding). */
- int srcLen; /* Source string length in bytes. */
- int flags; /* Conversion control flags. */
- Tcl_EncodingState *statePtr;/* Place for conversion routine to store
- * state information used during a piecewise
- * conversion. Contents of statePtr are
+BinaryProc(
+ ClientData clientData, /* Not used. */
+ CONST char *src, /* Source string (unknown encoding). */
+ int srcLen, /* Source string length in bytes. */
+ int flags, /* Conversion control flags. */
+ Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
+ * information used during a piecewise
+ * conversion. Contents of statePtr are
* initialized and/or reset by conversion
* routine under control of flags argument. */
- char *dst; /* Output buffer in which converted string
- * is stored. */
- int dstLen; /* The maximum length of output buffer in
+ char *dst, /* Output buffer in which converted string is
+ * stored. */
+ int dstLen, /* The maximum length of output buffer in
* bytes. */
- int *srcReadPtr; /* Filled with the number of bytes from the
+ int *srcReadPtr, /* Filled with the number of bytes from the
* source string that were converted. */
- int *dstWrotePtr; /* Filled with the number of bytes that were
+ int *dstWrotePtr, /* Filled with the number of bytes that were
* stored in the output buffer as a result of
* the conversion. */
- int *dstCharsPtr; /* Filled with the number of characters that
+ int *dstCharsPtr) /* Filled with the number of characters that
* correspond to the bytes stored in the
* output buffer. */
{
@@ -1883,18 +2092,17 @@ BinaryProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
*srcReadPtr = srcLen;
*dstWrotePtr = srcLen;
*dstCharsPtr = srcLen;
- memcpy((void *) dst, (void *) src, (size_t) srcLen);
+ memcpy(dst, src, (size_t) srcLen);
return result;
}
-
/*
*-------------------------------------------------------------------------
*
* UtfExtToUtfIntProc --
*
- * Convert from UTF-8 to UTF-8. While converting null-bytes from
- * the Tcl's internal representation (0xc0, 0x80) to the official
+ * Convert from UTF-8 to UTF-8. While converting null-bytes from the
+ * Tcl's internal representation (0xc0, 0x80) to the official
* representation (0x00). See UtfToUtfProc for details.
*
* Results:
@@ -1905,36 +2113,36 @@ BinaryProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
*
*-------------------------------------------------------------------------
*/
-static int
-UtfIntToUtfExtProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
- srcReadPtr, dstWrotePtr, dstCharsPtr)
- ClientData clientData; /* Not used. */
- CONST char *src; /* Source string in UTF-8. */
- int srcLen; /* Source string length in bytes. */
- int flags; /* Conversion control flags. */
- Tcl_EncodingState *statePtr;/* Place for conversion routine to store
- * state information used during a piecewise
- * conversion. Contents of statePtr are
+
+static int
+UtfIntToUtfExtProc(
+ ClientData clientData, /* Not used. */
+ CONST char *src, /* Source string in UTF-8. */
+ int srcLen, /* Source string length in bytes. */
+ int flags, /* Conversion control flags. */
+ Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
+ * information used during a piecewise
+ * conversion. Contents of statePtr are
* initialized and/or reset by conversion
* routine under control of flags argument. */
- char *dst; /* Output buffer in which converted string
+ char *dst, /* Output buffer in which converted string
* is stored. */
- int dstLen; /* The maximum length of output buffer in
+ int dstLen, /* The maximum length of output buffer in
* bytes. */
- int *srcReadPtr; /* Filled with the number of bytes from the
- * source string that were converted. This
- * may be less than the original source length
- * if there was a problem converting some
- * source characters. */
- int *dstWrotePtr; /* Filled with the number of bytes that were
+ int *srcReadPtr, /* Filled with the number of bytes from the
+ * source string that were converted. This may
+ * be less than the original source length if
+ * there was a problem converting some source
+ * characters. */
+ int *dstWrotePtr, /* Filled with the number of bytes that were
* stored in the output buffer as a result of
* the conversion. */
- int *dstCharsPtr; /* Filled with the number of characters that
+ int *dstCharsPtr) /* Filled with the number of characters that
* correspond to the bytes stored in the
* output buffer. */
{
return UtfToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
- srcReadPtr, dstWrotePtr, dstCharsPtr, 1);
+ srcReadPtr, dstWrotePtr, dstCharsPtr, 1);
}
/*
@@ -1942,9 +2150,9 @@ UtfIntToUtfExtProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
*
* UtfExtToUtfIntProc --
*
- * Convert from UTF-8 to UTF-8 while converting null-bytes from
- * the official representation (0x00) to Tcl's internal
- * representation (0xc0, 0x80). See UtfToUtfProc for details.
+ * Convert from UTF-8 to UTF-8 while converting null-bytes from the
+ * official representation (0x00) to Tcl's internal representation (0xc0,
+ * 0x80). See UtfToUtfProc for details.
*
* Results:
* Returns TCL_OK if conversion was successful.
@@ -1954,36 +2162,35 @@ UtfIntToUtfExtProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
*
*-------------------------------------------------------------------------
*/
-static int
-UtfExtToUtfIntProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
- srcReadPtr, dstWrotePtr, dstCharsPtr)
- ClientData clientData; /* Not used. */
- CONST char *src; /* Source string in UTF-8. */
- int srcLen; /* Source string length in bytes. */
- int flags; /* Conversion control flags. */
- Tcl_EncodingState *statePtr;/* Place for conversion routine to store
- * state information used during a piecewise
- * conversion. Contents of statePtr are
+static int
+UtfExtToUtfIntProc(
+ ClientData clientData, /* Not used. */
+ CONST char *src, /* Source string in UTF-8. */
+ int srcLen, /* Source string length in bytes. */
+ int flags, /* Conversion control flags. */
+ Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
+ * information used during a piecewise
+ * conversion. Contents of statePtr are
* initialized and/or reset by conversion
* routine under control of flags argument. */
- char *dst; /* Output buffer in which converted string
- * is stored. */
- int dstLen; /* The maximum length of output buffer in
+ char *dst, /* Output buffer in which converted string is
+ * stored. */
+ int dstLen, /* The maximum length of output buffer in
* bytes. */
- int *srcReadPtr; /* Filled with the number of bytes from the
- * source string that were converted. This
- * may be less than the original source length
- * if there was a problem converting some
- * source characters. */
- int *dstWrotePtr; /* Filled with the number of bytes that were
+ int *srcReadPtr, /* Filled with the number of bytes from the
+ * source string that were converted. This may
+ * be less than the original source length if
+ * there was a problem converting some source
+ * characters. */
+ int *dstWrotePtr, /* Filled with the number of bytes that were
* stored in the output buffer as a result of
* the conversion. */
- int *dstCharsPtr; /* Filled with the number of characters that
+ int *dstCharsPtr) /* Filled with the number of characters that
* correspond to the bytes stored in the
* output buffer. */
{
return UtfToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
- srcReadPtr, dstWrotePtr, dstCharsPtr, 0);
+ srcReadPtr, dstWrotePtr, dstCharsPtr, 0);
}
/*
@@ -1991,9 +2198,9 @@ UtfExtToUtfIntProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
*
* UtfToUtfProc --
*
- * Convert from UTF-8 to UTF-8. Note that the UTF-8 to UTF-8
- * translation is not a no-op, because it will turn a stream of
- * improperly formed UTF-8 into a properly formed stream.
+ * Convert from UTF-8 to UTF-8. Note that the UTF-8 to UTF-8 translation
+ * is not a no-op, because it will turn a stream of improperly formed
+ * UTF-8 into a properly formed stream.
*
* Results:
* Returns TCL_OK if conversion was successful.
@@ -2004,37 +2211,35 @@ UtfExtToUtfIntProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
*-------------------------------------------------------------------------
*/
-static int
-UtfToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
- srcReadPtr, dstWrotePtr, dstCharsPtr, pureNullMode)
- ClientData clientData; /* Not used. */
- CONST char *src; /* Source string in UTF-8. */
- int srcLen; /* Source string length in bytes. */
- int flags; /* Conversion control flags. */
- Tcl_EncodingState *statePtr;/* Place for conversion routine to store
- * state information used during a piecewise
- * conversion. Contents of statePtr are
+static int
+UtfToUtfProc(
+ ClientData clientData, /* Not used. */
+ CONST char *src, /* Source string in UTF-8. */
+ int srcLen, /* Source string length in bytes. */
+ int flags, /* Conversion control flags. */
+ Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
+ * information used during a piecewise
+ * conversion. Contents of statePtr are
* initialized and/or reset by conversion
* routine under control of flags argument. */
- char *dst; /* Output buffer in which converted string
- * is stored. */
- int dstLen; /* The maximum length of output buffer in
+ char *dst, /* Output buffer in which converted string is
+ * stored. */
+ int dstLen, /* The maximum length of output buffer in
* bytes. */
- int *srcReadPtr; /* Filled with the number of bytes from the
- * source string that were converted. This
- * may be less than the original source length
- * if there was a problem converting some
- * source characters. */
- int *dstWrotePtr; /* Filled with the number of bytes that were
+ int *srcReadPtr, /* Filled with the number of bytes from the
+ * source string that were converted. This may
+ * be less than the original source length if
+ * there was a problem converting some source
+ * characters. */
+ int *dstWrotePtr, /* Filled with the number of bytes that were
* stored in the output buffer as a result of
* the conversion. */
- int *dstCharsPtr; /* Filled with the number of characters that
+ int *dstCharsPtr, /* Filled with the number of characters that
* correspond to the bytes stored in the
* output buffer. */
- int pureNullMode; /* Convert embedded nulls from
- * internal representation to real
- * null-bytes or vice versa */
-
+ int pureNullMode) /* Convert embedded nulls from internal
+ * representation to real null-bytes or vice
+ * versa. */
{
CONST char *srcStart, *srcEnd, *srcClose;
char *dstStart, *dstEnd;
@@ -2042,7 +2247,7 @@ UtfToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
Tcl_UniChar ch;
result = TCL_OK;
-
+
srcStart = src;
srcEnd = src + srcLen;
srcClose = srcEnd;
@@ -2067,26 +2272,26 @@ UtfToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
result = TCL_CONVERT_NOSPACE;
break;
}
- if (UCHAR(*src) < 0x80 &&
- !(UCHAR(*src) == 0 && pureNullMode == 0)) {
+ if (UCHAR(*src) < 0x80 && !(UCHAR(*src) == 0 && pureNullMode == 0)) {
/*
- * Copy 7bit chatacters, but skip null-bytes when we are
- * in input mode, so that they get converted to 0xc080.
+ * Copy 7bit chatacters, but skip null-bytes when we are in input
+ * mode, so that they get converted to 0xc080.
*/
+
*dst++ = *src++;
- } else if (pureNullMode == 1 &&
- UCHAR(*src) == 0xc0 &&
- UCHAR(*(src+1)) == 0x80) {
- /*
+ } else if (pureNullMode == 1 && UCHAR(*src) == 0xc0 &&
+ UCHAR(*(src+1)) == 0x80) {
+ /*
* Convert 0xc080 to real nulls when we are in output mode.
*/
+
*dst++ = 0;
src += 2;
} else if (!Tcl_UtfCharComplete(src, srcEnd - src)) {
- /* Always check before using Tcl_UtfToUniChar. Not doing
- * can so cause it run beyond the endof the buffer! If we
- * happen such an incomplete char its bytes are made to
- * represent themselves.
+ /*
+ * Always check before using Tcl_UtfToUniChar. Not doing can so
+ * cause it run beyond the endof the buffer! If we happen such an
+ * incomplete char its byts are made to represent themselves.
*/
ch = (unsigned char) *src;
@@ -2098,7 +2303,7 @@ UtfToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
}
}
- *srcReadPtr = src - srcStart;
+ *srcReadPtr = src - srcStart;
*dstWrotePtr = dst - dstStart;
*dstCharsPtr = numChars;
return result;
@@ -2120,31 +2325,30 @@ UtfToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
*-------------------------------------------------------------------------
*/
-static int
-UnicodeToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
- srcReadPtr, dstWrotePtr, dstCharsPtr)
- ClientData clientData; /* Not used. */
- CONST char *src; /* Source string in Unicode. */
- int srcLen; /* Source string length in bytes. */
- int flags; /* Conversion control flags. */
- Tcl_EncodingState *statePtr;/* Place for conversion routine to store
- * state information used during a piecewise
- * conversion. Contents of statePtr are
+static int
+UnicodeToUtfProc(
+ ClientData clientData, /* Not used. */
+ CONST char *src, /* Source string in Unicode. */
+ int srcLen, /* Source string length in bytes. */
+ int flags, /* Conversion control flags. */
+ Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
+ * information used during a piecewise
+ * conversion. Contents of statePtr are
* initialized and/or reset by conversion
* routine under control of flags argument. */
- char *dst; /* Output buffer in which converted string
- * is stored. */
- int dstLen; /* The maximum length of output buffer in
+ char *dst, /* Output buffer in which converted string is
+ * stored. */
+ int dstLen, /* The maximum length of output buffer in
* bytes. */
- int *srcReadPtr; /* Filled with the number of bytes from the
- * source string that were converted. This
- * may be less than the original source length
- * if there was a problem converting some
- * source characters. */
- int *dstWrotePtr; /* Filled with the number of bytes that were
+ int *srcReadPtr, /* Filled with the number of bytes from the
+ * source string that were converted. This may
+ * be less than the original source length if
+ * there was a problem converting some source
+ * characters. */
+ int *dstWrotePtr, /* Filled with the number of bytes that were
* stored in the output buffer as a result of
* the conversion. */
- int *dstCharsPtr; /* Filled with the number of characters that
+ int *dstCharsPtr) /* Filled with the number of characters that
* correspond to the bytes stored in the
* output buffer. */
{
@@ -2206,31 +2410,31 @@ UnicodeToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
*-------------------------------------------------------------------------
*/
-static int
-UtfToUnicodeProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
- srcReadPtr, dstWrotePtr, dstCharsPtr)
- ClientData clientData; /* TableEncodingData that specifies encoding. */
- CONST char *src; /* Source string in UTF-8. */
- int srcLen; /* Source string length in bytes. */
- int flags; /* Conversion control flags. */
- Tcl_EncodingState *statePtr;/* Place for conversion routine to store
- * state information used during a piecewise
- * conversion. Contents of statePtr are
+static int
+UtfToUnicodeProc(
+ ClientData clientData, /* TableEncodingData that specifies
+ * encoding. */
+ CONST char *src, /* Source string in UTF-8. */
+ int srcLen, /* Source string length in bytes. */
+ int flags, /* Conversion control flags. */
+ Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
+ * information used during a piecewise
+ * conversion. Contents of statePtr are
* initialized and/or reset by conversion
* routine under control of flags argument. */
- char *dst; /* Output buffer in which converted string
- * is stored. */
- int dstLen; /* The maximum length of output buffer in
+ char *dst, /* Output buffer in which converted string is
+ * stored. */
+ int dstLen, /* The maximum length of output buffer in
* bytes. */
- int *srcReadPtr; /* Filled with the number of bytes from the
- * source string that were converted. This
- * may be less than the original source length
- * if there was a problem converting some
- * source characters. */
- int *dstWrotePtr; /* Filled with the number of bytes that were
+ int *srcReadPtr, /* Filled with the number of bytes from the
+ * source string that were converted. This may
+ * be less than the original source length if
+ * there was a problem converting some source
+ * characters. */
+ int *dstWrotePtr, /* Filled with the number of bytes that were
* stored in the output buffer as a result of
* the conversion. */
- int *dstCharsPtr; /* Filled with the number of characters that
+ int *dstCharsPtr) /* Filled with the number of characters that
* correspond to the bytes stored in the
* output buffer. */
{
@@ -2300,32 +2504,31 @@ UtfToUnicodeProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
*-------------------------------------------------------------------------
*/
-static int
-TableToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
- srcReadPtr, dstWrotePtr, dstCharsPtr)
- ClientData clientData; /* TableEncodingData that specifies
+static int
+TableToUtfProc(
+ ClientData clientData, /* TableEncodingData that specifies
* encoding. */
- CONST char *src; /* Source string in specified encoding. */
- int srcLen; /* Source string length in bytes. */
- int flags; /* Conversion control flags. */
- Tcl_EncodingState *statePtr;/* Place for conversion routine to store
- * state information used during a piecewise
- * conversion. Contents of statePtr are
+ CONST char *src, /* Source string in specified encoding. */
+ int srcLen, /* Source string length in bytes. */
+ int flags, /* Conversion control flags. */
+ Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
+ * information used during a piecewise
+ * conversion. Contents of statePtr are
* initialized and/or reset by conversion
* routine under control of flags argument. */
- char *dst; /* Output buffer in which converted string
- * is stored. */
- int dstLen; /* The maximum length of output buffer in
+ char *dst, /* Output buffer in which converted string is
+ * stored. */
+ int dstLen, /* The maximum length of output buffer in
* bytes. */
- int *srcReadPtr; /* Filled with the number of bytes from the
- * source string that were converted. This
- * may be less than the original source length
- * if there was a problem converting some
- * source characters. */
- int *dstWrotePtr; /* Filled with the number of bytes that were
+ int *srcReadPtr, /* Filled with the number of bytes from the
+ * source string that were converted. This may
+ * be less than the original source length if
+ * there was a problem converting some source
+ * characters. */
+ int *dstWrotePtr, /* Filled with the number of bytes that were
* stored in the output buffer as a result of
* the conversion. */
- int *dstCharsPtr; /* Filled with the number of characters that
+ int *dstCharsPtr) /* Filled with the number of characters that
* correspond to the bytes stored in the
* output buffer. */
{
@@ -2336,7 +2539,7 @@ TableToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
unsigned short **toUnicode;
unsigned short *pageZero;
TableEncodingData *dataPtr;
-
+
srcStart = src;
srcEnd = src + srcLen;
@@ -2350,10 +2553,10 @@ TableToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
result = TCL_OK;
for (numChars = 0; src < srcEnd; numChars++) {
- if (dst > dstEnd) {
- result = TCL_CONVERT_NOSPACE;
- break;
- }
+ if (dst > dstEnd) {
+ result = TCL_CONVERT_NOSPACE;
+ break;
+ }
byte = *((unsigned char *) src);
if (prefixBytes[byte]) {
src++;
@@ -2384,8 +2587,9 @@ TableToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
} else {
dst += Tcl_UniCharToUtf(ch, dst);
}
- src++;
+ src++;
}
+
*srcReadPtr = src - srcStart;
*dstWrotePtr = dst - dstStart;
*dstCharsPtr = numChars;
@@ -2409,32 +2613,31 @@ TableToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
*-------------------------------------------------------------------------
*/
-static int
-TableFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
- srcReadPtr, dstWrotePtr, dstCharsPtr)
- ClientData clientData; /* TableEncodingData that specifies
+static int
+TableFromUtfProc(
+ ClientData clientData, /* TableEncodingData that specifies
* encoding. */
- CONST char *src; /* Source string in UTF-8. */
- int srcLen; /* Source string length in bytes. */
- int flags; /* Conversion control flags. */
- Tcl_EncodingState *statePtr;/* Place for conversion routine to store
- * state information used during a piecewise
- * conversion. Contents of statePtr are
+ CONST char *src, /* Source string in UTF-8. */
+ int srcLen, /* Source string length in bytes. */
+ int flags, /* Conversion control flags. */
+ Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
+ * information used during a piecewise
+ * conversion. Contents of statePtr are
* initialized and/or reset by conversion
* routine under control of flags argument. */
- char *dst; /* Output buffer in which converted string
- * is stored. */
- int dstLen; /* The maximum length of output buffer in
+ char *dst, /* Output buffer in which converted string is
+ * stored. */
+ int dstLen, /* The maximum length of output buffer in
* bytes. */
- int *srcReadPtr; /* Filled with the number of bytes from the
- * source string that were converted. This
- * may be less than the original source length
- * if there was a problem converting some
- * source characters. */
- int *dstWrotePtr; /* Filled with the number of bytes that were
+ int *srcReadPtr, /* Filled with the number of bytes from the
+ * source string that were converted. This may
+ * be less than the original source length if
+ * there was a problem converting some source
+ * characters. */
+ int *dstWrotePtr, /* Filled with the number of bytes that were
* stored in the output buffer as a result of
* the conversion. */
- int *dstCharsPtr; /* Filled with the number of characters that
+ int *dstCharsPtr) /* Filled with the number of characters that
* correspond to the bytes stored in the
* output buffer. */
{
@@ -2444,13 +2647,13 @@ TableFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
int result, len, word, numChars;
TableEncodingData *dataPtr;
unsigned short **fromUnicode;
-
- result = TCL_OK;
+
+ result = TCL_OK;
dataPtr = (TableEncodingData *) clientData;
prefixBytes = dataPtr->prefixBytes;
fromUnicode = dataPtr->fromUnicode;
-
+
srcStart = src;
srcEnd = src + srcLen;
srcClose = srcEnd;
@@ -2475,9 +2678,10 @@ TableFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
#if TCL_UTF_MAX > 3
/*
- * This prevents a crash condition. More evaluation is required
- * for full support of int Tcl_UniChar. [Bug 1004065]
+ * This prevents a crash condition. More evaluation is required for
+ * full support of int Tcl_UniChar. [Bug 1004065]
*/
+
if (ch & 0xffff0000) {
word = 0;
} else
@@ -2489,7 +2693,7 @@ TableFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
result = TCL_CONVERT_UNKNOWN;
break;
}
- word = dataPtr->fallback;
+ word = dataPtr->fallback;
}
if (prefixBytes[(word >> 8)] != 0) {
if (dst + 1 > dstEnd) {
@@ -2506,9 +2710,194 @@ TableFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
}
dst[0] = (char) word;
dst++;
- }
+ }
src += len;
}
+
+ *srcReadPtr = src - srcStart;
+ *dstWrotePtr = dst - dstStart;
+ *dstCharsPtr = numChars;
+ return result;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * Iso88591ToUtfProc --
+ *
+ * Convert from the "iso8859-1" encoding into UTF-8.
+ *
+ * Results:
+ * Returns TCL_OK if conversion was successful.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static int
+Iso88591ToUtfProc(
+ ClientData clientData, /* Ignored. */
+ CONST char *src, /* Source string in specified encoding. */
+ int srcLen, /* Source string length in bytes. */
+ int flags, /* Conversion control flags. */
+ Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
+ * information used during a piecewise
+ * conversion. Contents of statePtr are
+ * initialized and/or reset by conversion
+ * routine under control of flags argument. */
+ char *dst, /* Output buffer in which converted string is
+ * stored. */
+ int dstLen, /* The maximum length of output buffer in
+ * bytes. */
+ int *srcReadPtr, /* Filled with the number of bytes from the
+ * source string that were converted. This may
+ * be less than the original source length if
+ * there was a problem converting some source
+ * characters. */
+ int *dstWrotePtr, /* Filled with the number of bytes that were
+ * stored in the output buffer as a result of
+ * the conversion. */
+ int *dstCharsPtr) /* Filled with the number of characters that
+ * correspond to the bytes stored in the
+ * output buffer. */
+{
+ CONST char *srcStart, *srcEnd;
+ char *dstEnd, *dstStart;
+ int result, numChars;
+
+ srcStart = src;
+ srcEnd = src + srcLen;
+
+ dstStart = dst;
+ dstEnd = dst + dstLen - TCL_UTF_MAX;
+
+ result = TCL_OK;
+ for (numChars = 0; src < srcEnd; numChars++) {
+ Tcl_UniChar ch;
+
+ if (dst > dstEnd) {
+ result = TCL_CONVERT_NOSPACE;
+ break;
+ }
+ ch = (Tcl_UniChar) *((unsigned char *) src);
+ /*
+ * Special case for 1-byte utf chars for speed.
+ */
+ if (ch && ch < 0x80) {
+ *dst++ = (char) ch;
+ } else {
+ dst += Tcl_UniCharToUtf(ch, dst);
+ }
+ src++;
+ }
+
+ *srcReadPtr = src - srcStart;
+ *dstWrotePtr = dst - dstStart;
+ *dstCharsPtr = numChars;
+ return result;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * Iso88591FromUtfProc --
+ *
+ * Convert from UTF-8 into the encoding "iso8859-1".
+ *
+ * Results:
+ * Returns TCL_OK if conversion was successful.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static int
+Iso88591FromUtfProc(
+ ClientData clientData, /* Ignored. */
+ CONST char *src, /* Source string in UTF-8. */
+ int srcLen, /* Source string length in bytes. */
+ int flags, /* Conversion control flags. */
+ Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
+ * information used during a piecewise
+ * conversion. Contents of statePtr are
+ * initialized and/or reset by conversion
+ * routine under control of flags argument. */
+ char *dst, /* Output buffer in which converted string is
+ * stored. */
+ int dstLen, /* The maximum length of output buffer in
+ * bytes. */
+ int *srcReadPtr, /* Filled with the number of bytes from the
+ * source string that were converted. This may
+ * be less than the original source length if
+ * there was a problem converting some source
+ * characters. */
+ int *dstWrotePtr, /* Filled with the number of bytes that were
+ * stored in the output buffer as a result of
+ * the conversion. */
+ int *dstCharsPtr) /* Filled with the number of characters that
+ * correspond to the bytes stored in the
+ * output buffer. */
+{
+ CONST char *srcStart, *srcEnd, *srcClose;
+ char *dstStart, *dstEnd;
+ int result, numChars;
+
+ result = TCL_OK;
+
+ srcStart = src;
+ srcEnd = src + srcLen;
+ srcClose = srcEnd;
+ if ((flags & TCL_ENCODING_END) == 0) {
+ srcClose -= TCL_UTF_MAX;
+ }
+
+ dstStart = dst;
+ dstEnd = dst + dstLen - 1;
+
+ for (numChars = 0; src < srcEnd; numChars++) {
+ Tcl_UniChar ch;
+ int len;
+
+ if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) {
+ /*
+ * If there is more string to follow, this will ensure that the
+ * last UTF-8 character in the source buffer hasn't been cut off.
+ */
+
+ result = TCL_CONVERT_MULTIBYTE;
+ break;
+ }
+ len = TclUtfToUniChar(src, &ch);
+
+ /*
+ * Check for illegal characters.
+ */
+
+ if (ch > 0xff) {
+ if (flags & TCL_ENCODING_STOPONERROR) {
+ result = TCL_CONVERT_UNKNOWN;
+ break;
+ }
+
+ /*
+ * Plunge on, using '?' as a fallback character.
+ */
+
+ ch = (Tcl_UniChar) '?';
+ }
+
+ if (dst > dstEnd) {
+ result = TCL_CONVERT_NOSPACE;
+ break;
+ }
+ *(dst++) = (char) ch;
+ src += len;
+ }
+
*srcReadPtr = src - srcStart;
*dstWrotePtr = dst - dstStart;
*dstCharsPtr = numChars;
@@ -2520,8 +2909,8 @@ TableFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
*
* TableFreeProc --
*
- * This procedure is invoked when an encoding is deleted. It deletes
- * the memory used by the TableEncodingData.
+ * This function is invoked when an encoding is deleted. It deletes the
+ * memory used by the TableEncodingData.
*
* Results:
* None.
@@ -2533,14 +2922,14 @@ TableFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
*/
static void
-TableFreeProc(clientData)
- ClientData clientData; /* TableEncodingData that specifies
+TableFreeProc(
+ ClientData clientData) /* TableEncodingData that specifies
* encoding. */
{
TableEncodingData *dataPtr;
/*
- * Make sure we aren't freeing twice on shutdown. [Bug #219314]
+ * Make sure we aren't freeing twice on shutdown. [Bug 219314]
*/
dataPtr = (TableEncodingData *) clientData;
@@ -2566,32 +2955,31 @@ TableFreeProc(clientData)
*-------------------------------------------------------------------------
*/
-static int
-EscapeToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
- srcReadPtr, dstWrotePtr, dstCharsPtr)
- ClientData clientData; /* EscapeEncodingData that specifies
+static int
+EscapeToUtfProc(
+ ClientData clientData, /* EscapeEncodingData that specifies
* encoding. */
- CONST char *src; /* Source string in specified encoding. */
- int srcLen; /* Source string length in bytes. */
- int flags; /* Conversion control flags. */
- Tcl_EncodingState *statePtr;/* Place for conversion routine to store
- * state information used during a piecewise
- * conversion. Contents of statePtr are
+ CONST char *src, /* Source string in specified encoding. */
+ int srcLen, /* Source string length in bytes. */
+ int flags, /* Conversion control flags. */
+ Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
+ * information used during a piecewise
+ * conversion. Contents of statePtr are
* initialized and/or reset by conversion
* routine under control of flags argument. */
- char *dst; /* Output buffer in which converted string
- * is stored. */
- int dstLen; /* The maximum length of output buffer in
+ char *dst, /* Output buffer in which converted string is
+ * stored. */
+ int dstLen, /* The maximum length of output buffer in
* bytes. */
- int *srcReadPtr; /* Filled with the number of bytes from the
- * source string that were converted. This
- * may be less than the original source length
- * if there was a problem converting some
- * source characters. */
- int *dstWrotePtr; /* Filled with the number of bytes that were
+ int *srcReadPtr, /* Filled with the number of bytes from the
+ * source string that were converted. This may
+ * be less than the original source length if
+ * there was a problem converting some source
+ * characters. */
+ int *dstWrotePtr, /* Filled with the number of bytes that were
* stored in the output buffer as a result of
* the conversion. */
- int *dstCharsPtr; /* Filled with the number of characters that
+ int *dstCharsPtr) /* Filled with the number of characters that
* correspond to the bytes stored in the
* output buffer. */
{
@@ -2618,7 +3006,7 @@ EscapeToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
dstStart = dst;
dstEnd = dst + dstLen - TCL_UTF_MAX;
- state = (int) *statePtr;
+ state = PTR2INT(*statePtr);
if (flags & TCL_ENCODING_START) {
state = 0;
}
@@ -2626,54 +3014,56 @@ EscapeToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
for (numChars = 0; src < srcEnd; ) {
int byte, hi, lo, ch;
- if (dst > dstEnd) {
- result = TCL_CONVERT_NOSPACE;
- break;
- }
+ if (dst > dstEnd) {
+ result = TCL_CONVERT_NOSPACE;
+ break;
+ }
byte = *((unsigned char *) src);
if (prefixBytes[byte]) {
unsigned int left, len, longest;
int checked, i;
EscapeSubTable *subTablePtr;
-
+
/*
- * Saw the beginning of an escape sequence.
+ * Saw the beginning of an escape sequence.
*/
-
+
left = srcEnd - src;
len = dataPtr->initLen;
longest = len;
checked = 0;
+
if (len <= left) {
checked++;
- if ((len > 0) &&
- (memcmp(src, dataPtr->init, len) == 0)) {
+ if ((len > 0) && (memcmp(src, dataPtr->init, len) == 0)) {
/*
* If we see initialization string, skip it, even if we're
- * not at the beginning of the buffer.
+ * not at the beginning of the buffer.
*/
-
+
src += len;
continue;
}
}
+
len = dataPtr->finalLen;
if (len > longest) {
longest = len;
}
+
if (len <= left) {
checked++;
- if ((len > 0) &&
- (memcmp(src, dataPtr->final, len) == 0)) {
+ if ((len > 0) && (memcmp(src, dataPtr->final, len) == 0)) {
/*
* If we see finalization string, skip it, even if we're
- * not at the end of the buffer.
+ * not at the end of the buffer.
*/
-
+
src += len;
continue;
}
}
+
subTablePtr = dataPtr->subTables;
for (i = 0; i < dataPtr->numSubTables; i++) {
len = subTablePtr->sequenceLen;
@@ -2682,7 +3072,7 @@ EscapeToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
}
if (len <= left) {
checked++;
- if ((len > 0) &&
+ if ((len > 0) &&
(memcmp(src, subTablePtr->sequence, len) == 0)) {
state = i;
encodingPtr = NULL;
@@ -2693,6 +3083,7 @@ EscapeToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
}
subTablePtr++;
}
+
if (subTablePtr == NULL) {
/*
* A match was found, the escape sequence was consumed, and
@@ -2703,9 +3094,9 @@ EscapeToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
}
/*
- * We have a split-up or unrecognized escape sequence. If we
- * checked all the sequences, then it's a syntax error,
- * otherwise we need more bytes to determine a match.
+ * We have a split-up or unrecognized escape sequence. If we
+ * checked all the sequences, then it's a syntax error, otherwise
+ * we need more bytes to determine a match.
*/
if ((checked == dataPtr->numSubTables + 2)
@@ -2733,6 +3124,7 @@ EscapeToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
tablePrefixBytes = tableDataPtr->prefixBytes;
tableToUnicode = tableDataPtr->toUnicode;
}
+
if (tablePrefixBytes[byte]) {
src++;
if (src >= srcEnd) {
@@ -2746,13 +3138,14 @@ EscapeToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
hi = 0;
lo = byte;
}
+
ch = tableToUnicode[hi][lo];
dst += Tcl_UniCharToUtf(ch, dst);
src++;
numChars++;
}
- *statePtr = (Tcl_EncodingState) state;
+ *statePtr = (Tcl_EncodingState) INT2PTR(state);
*srcReadPtr = src - srcStart;
*dstWrotePtr = dst - dstStart;
*dstCharsPtr = numChars;
@@ -2776,32 +3169,31 @@ EscapeToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
*-------------------------------------------------------------------------
*/
-static int
-EscapeFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
- srcReadPtr, dstWrotePtr, dstCharsPtr)
- ClientData clientData; /* EscapeEncodingData that specifies
+static int
+EscapeFromUtfProc(
+ ClientData clientData, /* EscapeEncodingData that specifies
* encoding. */
- CONST char *src; /* Source string in UTF-8. */
- int srcLen; /* Source string length in bytes. */
- int flags; /* Conversion control flags. */
- Tcl_EncodingState *statePtr;/* Place for conversion routine to store
- * state information used during a piecewise
- * conversion. Contents of statePtr are
+ CONST char *src, /* Source string in UTF-8. */
+ int srcLen, /* Source string length in bytes. */
+ int flags, /* Conversion control flags. */
+ Tcl_EncodingState *statePtr,/* Place for conversion routine to store state
+ * information used during a piecewise
+ * conversion. Contents of statePtr are
* initialized and/or reset by conversion
* routine under control of flags argument. */
- char *dst; /* Output buffer in which converted string
- * is stored. */
- int dstLen; /* The maximum length of output buffer in
+ char *dst, /* Output buffer in which converted string is
+ * stored. */
+ int dstLen, /* The maximum length of output buffer in
* bytes. */
- int *srcReadPtr; /* Filled with the number of bytes from the
- * source string that were converted. This
- * may be less than the original source length
- * if there was a problem converting some
- * source characters. */
- int *dstWrotePtr; /* Filled with the number of bytes that were
+ int *srcReadPtr, /* Filled with the number of bytes from the
+ * source string that were converted. This may
+ * be less than the original source length if
+ * there was a problem converting some source
+ * characters. */
+ int *dstWrotePtr, /* Filled with the number of bytes that were
* stored in the output buffer as a result of
* the conversion. */
- int *dstCharsPtr; /* Filled with the number of characters that
+ int *dstCharsPtr) /* Filled with the number of characters that
* correspond to the bytes stored in the
* output buffer. */
{
@@ -2813,8 +3205,8 @@ EscapeFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
TableEncodingData *tableDataPtr;
char *tablePrefixBytes;
unsigned short **tableFromUnicode;
-
- result = TCL_OK;
+
+ result = TCL_OK;
dataPtr = (EscapeEncodingData *) clientData;
@@ -2830,7 +3222,7 @@ EscapeFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
/*
* RFC1468 states that the text starts in ASCII, and switches to Japanese
- * characters, and that the text must end in ASCII. [Patch #474358]
+ * characters, and that the text must end in ASCII. [Patch 474358]
*/
if (flags & TCL_ENCODING_START) {
@@ -2840,11 +3232,10 @@ EscapeFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
*dstWrotePtr = 0;
return TCL_CONVERT_NOSPACE;
}
- memcpy((VOID *) dst, (VOID *) dataPtr->init,
- (size_t) dataPtr->initLen);
+ memcpy(dst, dataPtr->init, (size_t)dataPtr->initLen);
dst += dataPtr->initLen;
} else {
- state = (int) *statePtr;
+ state = PTR2INT(*statePtr);
}
encodingPtr = GetTableEncoding(dataPtr, state);
@@ -2856,7 +3247,7 @@ EscapeFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
unsigned int len;
int word;
Tcl_UniChar ch;
-
+
if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) {
/*
* If there is more string to follow, this will ensure that the
@@ -2872,7 +3263,7 @@ EscapeFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
if ((word == 0) && (ch != 0)) {
int oldState;
EscapeSubTable *subTablePtr;
-
+
oldState = state;
for (state = 0; state < dataPtr->numSubTables; state++) {
encodingPtr = GetTableEncoding(dataPtr, state);
@@ -2892,16 +3283,17 @@ EscapeFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
encodingPtr = GetTableEncoding(dataPtr, state);
tableDataPtr = (TableEncodingData *) encodingPtr->clientData;
word = tableDataPtr->fallback;
- }
-
+ }
+
tablePrefixBytes = tableDataPtr->prefixBytes;
tableFromUnicode = tableDataPtr->fromUnicode;
/*
* The state variable has the value of oldState when word is 0.
- * In this case, the escape sequense should not be copied to dst
+ * In this case, the escape sequense should not be copied to dst
* because the current character set is not changed.
*/
+
if (state != oldState) {
subTablePtr = &dataPtr->subTables[state];
if ((dst + subTablePtr->sequenceLen) > dstEnd) {
@@ -2911,11 +3303,12 @@ EscapeFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
* variable because this escape sequence must be written
* in the next conversion.
*/
+
state = oldState;
result = TCL_CONVERT_NOSPACE;
break;
}
- memcpy((VOID *) dst, (VOID *) subTablePtr->sequence,
+ memcpy(dst, subTablePtr->sequence,
(size_t) subTablePtr->sequenceLen);
dst += subTablePtr->sequenceLen;
}
@@ -2936,14 +3329,13 @@ EscapeFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
}
dst[0] = (char) word;
dst++;
- }
+ }
src += len;
}
if ((result == TCL_OK) && (flags & TCL_ENCODING_END)) {
unsigned int len = dataPtr->subTables[0].sequenceLen;
/*
- * [Bug 1516109].
* Certain encodings like iso2022-jp need to write
* an escape sequence after all characters have
* been converted. This logic checks that enough
@@ -2957,18 +3349,16 @@ EscapeFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
result = TCL_CONVERT_NOSPACE;
} else {
if (state) {
- memcpy((VOID *) dst, (VOID *) dataPtr->subTables[0].sequence,
- (size_t) len);
+ memcpy(dst, dataPtr->subTables[0].sequence, (size_t) len);
dst += len;
}
- memcpy((VOID *) dst, (VOID *) dataPtr->final,
- (size_t) dataPtr->finalLen);
+ memcpy(dst, dataPtr->final, (size_t) dataPtr->finalLen);
dst += dataPtr->finalLen;
state &= ~TCL_ENCODING_END;
}
}
- *statePtr = (Tcl_EncodingState) state;
+ *statePtr = (Tcl_EncodingState) INT2PTR(state);
*srcReadPtr = src - srcStart;
*dstWrotePtr = dst - dstStart;
*dstCharsPtr = numChars;
@@ -2980,8 +3370,8 @@ EscapeFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
*
* EscapeFreeProc --
*
- * This procedure is invoked when an EscapeEncodingData encoding is
- * deleted. It deletes the memory used by the encoding.
+ * This function is invoked when an EscapeEncodingData encoding is
+ * deleted. It deletes the memory used by the encoding.
*
* Results:
* None.
@@ -2993,8 +3383,9 @@ EscapeFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
*/
static void
-EscapeFreeProc(clientData)
- ClientData clientData; /* EscapeEncodingData that specifies encoding. */
+EscapeFreeProc(
+ ClientData clientData) /* EscapeEncodingData that specifies
+ * encoding. */
{
EscapeEncodingData *dataPtr;
EscapeSubTable *subTablePtr;
@@ -3030,7 +3421,7 @@ EscapeFreeProc(clientData)
*
* GetTableEncoding --
*
- * Helper function for the EscapeEncodingData conversions. Gets the
+ * Helper function for the EscapeEncodingData conversions. Gets the
* encoding (of type TextEncodingData) that represents the specified
* state.
*
@@ -3038,36 +3429,34 @@ EscapeFreeProc(clientData)
* The return value is the encoding.
*
* Side effects:
- * If the encoding that represents the specified state has not
- * already been used by this EscapeEncoding, it will be loaded
- * and cached in the dataPtr.
+ * If the encoding that represents the specified state has not already
+ * been used by this EscapeEncoding, it will be loaded and cached in the
+ * dataPtr.
*
*---------------------------------------------------------------------------
*/
static Encoding *
-GetTableEncoding(dataPtr, state)
- EscapeEncodingData *dataPtr;/* Contains names of encodings. */
- int state; /* Index in dataPtr of desired Encoding. */
+GetTableEncoding(
+ EscapeEncodingData *dataPtr,/* Contains names of encodings. */
+ int state) /* Index in dataPtr of desired Encoding. */
{
EscapeSubTable *subTablePtr;
Encoding *encodingPtr;
-
+
subTablePtr = &dataPtr->subTables[state];
encodingPtr = subTablePtr->encodingPtr;
+
if (encodingPtr == NULL) {
- /*
- * Now that escape encodings load their sub-encodings first, and
- * fail to load if any sub-encodings are missing, this branch should
- * never happen.
- */
encodingPtr = (Encoding *) Tcl_GetEncoding(NULL, subTablePtr->name);
- if ((encodingPtr == NULL)
- || (encodingPtr->toUtfProc != TableToUtfProc)) {
- panic("EscapeToUtfProc: invalid sub table");
+ if ((encodingPtr == NULL)
+ || (encodingPtr->toUtfProc != TableToUtfProc
+ && encodingPtr->toUtfProc != Iso88591ToUtfProc)) {
+ Tcl_Panic("EscapeToUtfProc: invalid sub table");
}
subTablePtr->encodingPtr = encodingPtr;
}
+
return encodingPtr;
}
@@ -3076,9 +3465,9 @@ GetTableEncoding(dataPtr, state)
*
* unilen --
*
- * A helper function for the Tcl_ExternalToUtf functions. This
- * function is similar to strlen for double-byte characters: it
- * returns the number of bytes in a 0x0000 terminated string.
+ * A helper function for the Tcl_ExternalToUtf functions. This function
+ * is similar to strlen for double-byte characters: it returns the number
+ * of bytes in a 0x0000 terminated string.
*
* Results:
* As above.
@@ -3090,8 +3479,8 @@ GetTableEncoding(dataPtr, state)
*/
static size_t
-unilen(src)
- CONST char *src;
+unilen(
+ CONST char *src)
{
unsigned short *p;
@@ -3105,83 +3494,76 @@ unilen(src)
/*
*-------------------------------------------------------------------------
*
- * TclFindEncodings --
+ * InitializeEncodingSearchPath --
*
- * Find and load the encoding file for this operating system.
- * Before this is called, Tcl makes assumptions about the
- * native string representation, but the true encoding is not
- * assured.
+ * This is the fallback routine that sets the default value of the
+ * encoding search path if the application has not set one via a call to
+ * Tcl_SetEncodingSearchPath() by the first time the search path is needed
+ * to load encoding data.
+ *
+ * The default encoding search path is produced by taking each directory
+ * in the library path, appending a subdirectory named "encoding", and if
+ * the resulting directory exists, adding it to the encoding search path.
*
* Results:
- * Return result of TclpInitLibraryPath, which reports whether the
- * path is clean (0) or dirty (1) UTF.
+ * None.
*
* Side effects:
- * Varied, see the respective initialization routines.
+ * Sets the encoding search path to an initial value.
*
*-------------------------------------------------------------------------
*/
-static int
-TclFindEncodings(argv0)
- CONST char *argv0; /* Name of executable from argv[0] to main()
- * in native multi-byte encoding. */
+static void
+InitializeEncodingSearchPath(
+ char **valuePtr,
+ int *lengthPtr,
+ Tcl_Encoding *encodingPtr)
{
- int mustCleanUtf = 0;
-
- if (encodingsInitialized == 0) {
- /*
- * Double check inside the mutex. There may be calls
- * back into this routine from some of the procedures below.
- */
-
- TclpInitLock();
- if (encodingsInitialized == 0) {
- char *native;
- Tcl_Obj *pathPtr;
- Tcl_DString libPath, buffer;
-
- /*
- * Have to set this bit here to avoid deadlock with the
- * routines below us that call into TclInitSubsystems.
- */
-
- encodingsInitialized = 1;
-
- native = TclpFindExecutable(argv0);
- mustCleanUtf = TclpInitLibraryPath(native);
-
- /*
- * The library path was set in the TclpInitLibraryPath routine.
- * The string set is a dirty UTF string. To preserve the value
- * convert the UTF string back to native before setting the new
- * default encoding.
- */
-
- pathPtr = TclGetLibraryPath();
- if ((pathPtr != NULL) && mustCleanUtf) {
- Tcl_UtfToExternalDString(NULL, Tcl_GetString(pathPtr), -1,
- &libPath);
- }
-
- TclpSetInitialEncodings();
-
- /*
- * Now convert the native string back to UTF.
- */
-
- if ((pathPtr != NULL) && mustCleanUtf) {
- Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&libPath), -1,
- &buffer);
- pathPtr = Tcl_NewStringObj(Tcl_DStringValue(&buffer), -1);
- TclSetLibraryPath(pathPtr);
-
- Tcl_DStringFree(&libPath);
- Tcl_DStringFree(&buffer);
- }
+ char *bytes;
+ int i, numDirs, numBytes;
+ Tcl_Obj *libPath, *encodingObj, *searchPath;
+
+ TclNewLiteralStringObj(encodingObj, "encoding");
+ TclNewObj(searchPath);
+ Tcl_IncrRefCount(encodingObj);
+ Tcl_IncrRefCount(searchPath);
+ libPath = TclGetLibraryPath();
+ Tcl_IncrRefCount(libPath);
+ Tcl_ListObjLength(NULL, libPath, &numDirs);
+
+ for (i = 0; i < numDirs; i++) {
+ Tcl_Obj *directory, *path;
+ Tcl_StatBuf stat;
+
+ Tcl_ListObjIndex(NULL, libPath, i, &directory);
+ path = Tcl_FSJoinToPath(directory, 1, &encodingObj);
+ Tcl_IncrRefCount(path);
+ if ((0 == Tcl_FSStat(path, &stat)) && S_ISDIR(stat.st_mode)) {
+ Tcl_ListObjAppendElement(NULL, searchPath, path);
}
- TclpInitUnlock();
+ Tcl_DecrRefCount(path);
+ }
+
+ Tcl_DecrRefCount(libPath);
+ Tcl_DecrRefCount(encodingObj);
+ *encodingPtr = libraryPath.encoding;
+ if (*encodingPtr) {
+ ((Encoding *)(*encodingPtr))->refCount++;
}
+ bytes = Tcl_GetStringFromObj(searchPath, &numBytes);
- return mustCleanUtf;
+ *lengthPtr = numBytes;
+ *valuePtr = ckalloc((unsigned int) numBytes + 1);
+ memcpy(*valuePtr, bytes, (size_t) numBytes + 1);
+ Tcl_DecrRefCount(searchPath);
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
+
diff --git a/generic/tclEnv.c b/generic/tclEnv.c
index 4ce1c3b..a516cce 100644
--- a/generic/tclEnv.c
+++ b/generic/tclEnv.c
@@ -1,56 +1,55 @@
-/*
+/*
* tclEnv.c --
*
- * Tcl support for environment variables, including a setenv
- * procedure. This file contains the generic portion of the
- * environment module. It is primarily responsible for keeping
- * the "env" arrays in sync with the system environment variables.
+ * Tcl support for environment variables, including a setenv function.
+ * This file contains the generic portion of the environment module. It
+ * is primarily responsible for keeping the "env" arrays in sync with the
+ * system environment variables.
*
* Copyright (c) 1991-1994 The Regents of the University of California.
* Copyright (c) 1994-1998 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
-TCL_DECLARE_MUTEX(envMutex) /* To serialize access to environ */
+TCL_DECLARE_MUTEX(envMutex) /* To serialize access to environ. */
-static int cacheSize = 0; /* Number of env strings in environCache. */
-static char **environCache = NULL;
- /* Array containing all of the environment
+static struct {
+ int cacheSize; /* Number of env strings in cache. */
+ char **cache; /* Array containing all of the environment
* strings that Tcl has allocated. */
-
#ifndef USE_PUTENV
-static char **ourEnviron = NULL;/* Cache of the array that we allocate.
- * We need to track this in case another
+ char **ourEnviron; /* Cache of the array that we allocate. We
+ * need to track this in case another
* subsystem swaps around the environ array
- * like we do.
- */
-static int environSize = 0; /* Non-zero means that the environ array was
+ * like we do. */
+ int ourEnvironSize; /* Non-zero means that the environ array was
* malloced and has this many total entries
* allocated to it (not all may be in use at
- * once). Zero means that the environment
+ * once). Zero means that the environment
* array is in its original static state. */
#endif
+} env;
/*
- * Declarations for local procedures defined in this file:
+ * Declarations for local functions defined in this file:
*/
-static char * EnvTraceProc _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, CONST char *name1,
- CONST char *name2, int flags));
-static void ReplaceString _ANSI_ARGS_((CONST char *oldStr,
- char *newStr));
-void TclSetEnv _ANSI_ARGS_((CONST char *name,
- CONST char *value));
-void TclUnsetEnv _ANSI_ARGS_((CONST char *name));
-
-#if defined (__CYGWIN__) && defined(__WIN32__)
-static void TclCygwinPutenv _ANSI_ARGS_((CONST char *string));
+static char * EnvTraceProc(ClientData clientData, Tcl_Interp *interp,
+ const char *name1, const char *name2, int flags);
+static void ReplaceString(const char *oldStr, char *newStr);
+MODULE_SCOPE void TclSetEnv(const char *name, const char *value);
+MODULE_SCOPE void TclUnsetEnv(const char *name);
+
+#if defined(__CYGWIN__)
+/* On Cygwin, the environment is imported from the Cygwin DLL. */
+ DLLIMPORT extern int cygwin_posix_to_win32_path_list_buf_size(char *value);
+ DLLIMPORT extern void cygwin_posix_to_win32_path_list(char *buf, char *value);
+# define putenv TclCygwinPutenv
+static void TclCygwinPutenv(char *string);
#endif
/*
@@ -58,27 +57,26 @@ static void TclCygwinPutenv _ANSI_ARGS_((CONST char *string));
*
* TclSetupEnv --
*
- * This procedure is invoked for an interpreter to make environment
- * variables accessible from that interpreter via the "env"
- * associative array.
+ * This function is invoked for an interpreter to make environment
+ * variables accessible from that interpreter via the "env" associative
+ * array.
*
* Results:
* None.
*
* Side effects:
- * The interpreter is added to a list of interpreters managed
- * by us, so that its view of envariables can be kept consistent
- * with the view in other interpreters. If this is the first
- * call to TclSetupEnv, then additional initialization happens,
- * such as copying the environment to dynamically-allocated space
- * for ease of management.
+ * The interpreter is added to a list of interpreters managed by us, so
+ * that its view of envariables can be kept consistent with the view in
+ * other interpreters. If this is the first call to TclSetupEnv, then
+ * additional initialization happens, such as copying the environment to
+ * dynamically-allocated space for ease of management.
*
*----------------------------------------------------------------------
*/
void
-TclSetupEnv(interp)
- Tcl_Interp *interp; /* Interpreter whose "env" array is to be
+TclSetupEnv(
+ Tcl_Interp *interp) /* Interpreter whose "env" array is to be
* managed. */
{
Tcl_DString envString;
@@ -86,28 +84,27 @@ TclSetupEnv(interp)
int i;
/*
- * Synchronize the values in the environ array with the contents
- * of the Tcl "env" variable. To do this:
+ * Synchronize the values in the environ array with the contents of the
+ * Tcl "env" variable. To do this:
* 1) Remove the trace that fires when the "env" var is unset.
* 2) Unset the "env" variable.
- * 3) If there are no environ variables, create an empty "env"
- * array. Otherwise populate the array with current values.
+ * 3) If there are no environ variables, create an empty "env" array.
+ * Otherwise populate the array with current values.
* 4) Add a trace that synchronizes the "env" array.
*/
-
- Tcl_UntraceVar2(interp, "env", (char *) NULL,
+
+ Tcl_UntraceVar2(interp, "env", NULL,
TCL_GLOBAL_ONLY | TCL_TRACE_WRITES | TCL_TRACE_UNSETS |
- TCL_TRACE_READS | TCL_TRACE_ARRAY, EnvTraceProc,
- (ClientData) NULL);
-
- Tcl_UnsetVar2(interp, "env", (char *) NULL, TCL_GLOBAL_ONLY);
-
+ TCL_TRACE_READS | TCL_TRACE_ARRAY, EnvTraceProc, NULL);
+
+ Tcl_UnsetVar2(interp, "env", NULL, TCL_GLOBAL_ONLY);
+
if (environ[0] == NULL) {
Tcl_Obj *varNamePtr;
-
- varNamePtr = Tcl_NewStringObj("env", -1);
+
+ TclNewLiteralStringObj(varNamePtr, "env");
Tcl_IncrRefCount(varNamePtr);
- TclArraySet(interp, varNamePtr, NULL);
+ TclArraySet(interp, varNamePtr, NULL);
Tcl_DecrRefCount(varNamePtr);
} else {
Tcl_MutexLock(&envMutex);
@@ -117,23 +114,23 @@ TclSetupEnv(interp)
if (p2 == NULL) {
/*
* This condition seem to happen occasionally under some
- * versions of Solaris; ignore the entry.
+ * versions of Solaris, or when encoding accidents swallow the
+ * '='; ignore the entry.
*/
-
+
continue;
}
p2++;
p2[-1] = '\0';
- Tcl_SetVar2(interp, "env", p1, p2, TCL_GLOBAL_ONLY);
+ Tcl_SetVar2(interp, "env", p1, p2, TCL_GLOBAL_ONLY);
Tcl_DStringFree(&envString);
}
Tcl_MutexUnlock(&envMutex);
}
- Tcl_TraceVar2(interp, "env", (char *) NULL,
+ Tcl_TraceVar2(interp, "env", NULL,
TCL_GLOBAL_ONLY | TCL_TRACE_WRITES | TCL_TRACE_UNSETS |
- TCL_TRACE_READS | TCL_TRACE_ARRAY, EnvTraceProc,
- (ClientData) NULL);
+ TCL_TRACE_READS | TCL_TRACE_ARRAY, EnvTraceProc, NULL);
}
/*
@@ -141,12 +138,12 @@ TclSetupEnv(interp)
*
* TclSetEnv --
*
- * Set an environment variable, replacing an existing value
- * or creating a new variable if there doesn't exist a variable
- * by the given name. This procedure is intended to be a
- * stand-in for the UNIX "setenv" procedure so that applications
- * using that procedure will interface properly to Tcl. To make
- * it a stand-in, the Makefile must define "TclSetEnv" to "setenv".
+ * Set an environment variable, replacing an existing value or creating a
+ * new variable if there doesn't exist a variable by the given name. This
+ * function is intended to be a stand-in for the UNIX "setenv" function
+ * so that applications using that function will interface properly to
+ * Tcl. To make it a stand-in, the Makefile must define "TclSetEnv" to
+ * "setenv".
*
* Results:
* None.
@@ -158,20 +155,20 @@ TclSetupEnv(interp)
*/
void
-TclSetEnv(name, value)
- CONST char *name; /* Name of variable whose value is to be
- * set (UTF-8). */
- CONST char *value; /* New value for variable (UTF-8). */
+TclSetEnv(
+ const char *name, /* Name of variable whose value is to be set
+ * (UTF-8). */
+ const char *value) /* New value for variable (UTF-8). */
{
Tcl_DString envString;
int index, length, nameLength;
char *p, *oldValue;
- CONST char *p2;
+ const char *p2;
/*
- * Figure out where the entry is going to go. If the name doesn't
- * already exist, enlarge the array if necessary to make room. If the
- * name exists, free its old entry.
+ * Figure out where the entry is going to go. If the name doesn't already
+ * exist, enlarge the array if necessary to make room. If the name exists,
+ * free its old entry.
*/
Tcl_MutexLock(&envMutex);
@@ -181,40 +178,39 @@ TclSetEnv(name, value)
#ifndef USE_PUTENV
/*
* We need to handle the case where the environment may be changed
- * outside our control. environSize is only valid if the current
+ * outside our control. ourEnvironSize is only valid if the current
* environment is the one we allocated. [Bug 979640]
*/
- if ((ourEnviron != environ) || ((length + 2) > environSize)) {
- char **newEnviron;
-
- newEnviron = (char **) ckalloc((unsigned)
- ((length + 5) * sizeof(char *)));
- memcpy((VOID *) newEnviron, (VOID *) environ,
- length*sizeof(char *));
- if ((environSize != 0) && (ourEnviron != NULL)) {
- ckfree((char *) ourEnviron);
+
+ if ((env.ourEnviron != environ) || (length+2 > env.ourEnvironSize)) {
+ char **newEnviron = (char **)
+ ckalloc(((unsigned) length + 5) * sizeof(char *));
+
+ memcpy(newEnviron, environ, length * sizeof(char *));
+ if ((env.ourEnvironSize != 0) && (env.ourEnviron != NULL)) {
+ ckfree((char *) env.ourEnviron);
}
- environ = ourEnviron = newEnviron;
- environSize = length + 5;
+ environ = env.ourEnviron = newEnviron;
+ env.ourEnvironSize = length + 5;
}
index = length;
environ[index + 1] = NULL;
-#endif
+#endif /* USE_PUTENV */
oldValue = NULL;
nameLength = strlen(name);
} else {
- CONST char *env;
+ const char *env;
/*
- * Compare the new value to the existing value. If they're
- * the same then quit immediately (e.g. don't rewrite the
- * value or propagate it to other interpreters). Otherwise,
- * when there are N interpreters there will be N! propagations
- * of the same value among the interpreters.
+ * Compare the new value to the existing value. If they're the same
+ * then quit immediately (e.g. don't rewrite the value or propagate it
+ * to other interpreters). Otherwise, when there are N interpreters
+ * there will be N! propagations of the same value among the
+ * interpreters.
*/
env = Tcl_ExternalToUtfDString(NULL, environ[index], -1, &envString);
- if (strcmp(value, (env + length + 1)) == 0) {
+ if (strcmp(value, env + (length + 1)) == 0) {
Tcl_DStringFree(&envString);
Tcl_MutexUnlock(&envMutex);
return;
@@ -226,12 +222,12 @@ TclSetEnv(name, value)
}
/*
- * Create a new entry. Build a complete UTF string that contains
- * a "name=value" pattern. Then convert the string to the native
- * encoding, and set the environ array value.
+ * Create a new entry. Build a complete UTF string that contains a
+ * "name=value" pattern. Then convert the string to the native encoding,
+ * and set the environ array value.
*/
- p = (char *) ckalloc((unsigned) (nameLength + strlen(value) + 2));
+ p = ckalloc((unsigned) nameLength + strlen(value) + 2);
strcpy(p, name);
p[nameLength] = '=';
strcpy(p+nameLength+1, value);
@@ -240,8 +236,8 @@ TclSetEnv(name, value)
/*
* Copy the native string to heap memory.
*/
-
- p = (char *) ckrealloc(p, (unsigned) (strlen(p2) + 1));
+
+ p = ckrealloc(p, strlen(p2) + 1);
strcpy(p, p2);
Tcl_DStringFree(&envString);
@@ -254,32 +250,35 @@ TclSetEnv(name, value)
index = TclpFindVariable(name, &length);
#else
environ[index] = p;
-#endif
+#endif /* USE_PUTENV */
/*
- * Watch out for versions of putenv that copy the string (e.g. VC++).
- * In this case we need to free the string immediately. Otherwise
- * update the string in the cache.
+ * Watch out for versions of putenv that copy the string (e.g. VC++). In
+ * this case we need to free the string immediately. Otherwise update the
+ * string in the cache.
*/
if ((index != -1) && (environ[index] == p)) {
ReplaceString(oldValue, p);
#ifdef HAVE_PUTENV_THAT_COPIES
} else {
- /* This putenv() copies instead of taking ownership */
+ /*
+ * This putenv() copies instead of taking ownership.
+ */
+
ckfree(p);
-#endif
+#endif /* HAVE_PUTENV_THAT_COPIES */
}
Tcl_MutexUnlock(&envMutex);
-
+
if (!strcmp(name, "HOME")) {
- /*
- * If the user's home directory has changed, we must invalidate
- * the filesystem cache, because '~' expansions will now be
- * incorrect.
+ /*
+ * If the user's home directory has changed, we must invalidate the
+ * filesystem cache, because '~' expansions will now be incorrect.
*/
- Tcl_FSMountsChanged(NULL);
+
+ Tcl_FSMountsChanged(NULL);
}
}
@@ -288,44 +287,42 @@ TclSetEnv(name, value)
*
* Tcl_PutEnv --
*
- * Set an environment variable. Similar to setenv except that
- * the information is passed in a single string of the form
- * NAME=value, rather than as separate name strings. This procedure
- * is intended to be a stand-in for the UNIX "putenv" procedure
- * so that applications using that procedure will interface
- * properly to Tcl. To make it a stand-in, the Makefile will
- * define "Tcl_PutEnv" to "putenv".
+ * Set an environment variable. Similar to setenv except that the
+ * information is passed in a single string of the form NAME=value,
+ * rather than as separate name strings. This function is intended to be
+ * a stand-in for the UNIX "putenv" function so that applications using
+ * that function will interface properly to Tcl. To make it a stand-in,
+ * the Makefile will define "Tcl_PutEnv" to "putenv".
*
* Results:
* None.
*
* Side effects:
- * The environ array gets updated, as do all of the interpreters
- * that we manage.
+ * The environ array gets updated, as do all of the interpreters that we
+ * manage.
*
*----------------------------------------------------------------------
*/
int
-Tcl_PutEnv(string)
- CONST char *string; /* Info about environment variable in the
- * form NAME=value. (native) */
+Tcl_PutEnv(
+ const char *assignment) /* Info about environment variable in the form
+ * NAME=value. (native) */
{
- Tcl_DString nameString;
- CONST char *name;
+ Tcl_DString nameString;
+ const char *name;
char *value;
- if (string == NULL) {
+ if (assignment == NULL) {
return 0;
}
/*
- * First convert the native string to UTF. Then separate the
- * string into name and value parts, and call TclSetEnv to do
- * all of the real work.
+ * First convert the native string to UTF. Then separate the string into
+ * name and value parts, and call TclSetEnv to do all of the real work.
*/
- name = Tcl_ExternalToUtfDString(NULL, string, -1, &nameString);
+ name = Tcl_ExternalToUtfDString(NULL, assignment, -1, &nameString);
value = strchr(name, '=');
if ((value != NULL) && (value != name)) {
@@ -342,11 +339,10 @@ Tcl_PutEnv(string)
*
* TclUnsetEnv --
*
- * Remove an environment variable, updating the "env" arrays
- * in all interpreters managed by us. This function is intended
- * to replace the UNIX "unsetenv" function (but to do this the
- * Makefile must be modified to redefine "TclUnsetEnv" to
- * "unsetenv".
+ * Remove an environment variable, updating the "env" arrays in all
+ * interpreters managed by us. This function is intended to replace the
+ * UNIX "unsetenv" function (but to do this the Makefile must be modified
+ * to redefine "TclUnsetEnv" to "unsetenv".
*
* Results:
* None.
@@ -358,8 +354,8 @@ Tcl_PutEnv(string)
*/
void
-TclUnsetEnv(name)
- CONST char *name; /* Name of variable to remove (UTF-8). */
+TclUnsetEnv(
+ const char *name) /* Name of variable to remove (UTF-8). */
{
char *oldValue;
int length;
@@ -369,20 +365,21 @@ TclUnsetEnv(name)
char *string;
#else
char **envPtr;
-#endif
+#endif /* USE_PUTENV_FOR_UNSET */
Tcl_MutexLock(&envMutex);
index = TclpFindVariable(name, &length);
/*
- * First make sure that the environment variable exists to avoid
- * doing needless work and to avoid recursion on the unset.
+ * First make sure that the environment variable exists to avoid doing
+ * needless work and to avoid recursion on the unset.
*/
if (index == -1) {
Tcl_MutexUnlock(&envMutex);
return;
}
+
/*
* Remember the old value so we can free it if Tcl created the string.
*/
@@ -390,8 +387,8 @@ TclUnsetEnv(name)
oldValue = environ[index];
/*
- * Update the system environment. This must be done before we
- * update the interpreters or we will recurse.
+ * Update the system environment. This must be done before we update the
+ * interpreters or we will recurse.
*/
#ifdef USE_PUTENV_FOR_UNSET
@@ -399,39 +396,43 @@ TclUnsetEnv(name)
* For those platforms that support putenv to unset, Linux indicates
* that no = should be included, and Windows requires it.
*/
-#ifdef WIN32
- string = ckalloc((unsigned int) length+2);
- memcpy((VOID *) string, (VOID *) name, (size_t) length);
+
+#if defined(__WIN32__) || defined(__CYGWIN__)
+ string = ckalloc((unsigned) length+2);
+ memcpy(string, name, (size_t) length);
string[length] = '=';
string[length+1] = '\0';
#else
- string = ckalloc((unsigned int) length+1);
- memcpy((VOID *) string, (VOID *) name, (size_t) length);
+ string = ckalloc((unsigned) length+1);
+ memcpy(string, name, (size_t) length);
string[length] = '\0';
-#endif
+#endif /* WIN32 */
Tcl_UtfToExternalDString(NULL, string, -1, &envString);
- string = ckrealloc(string, (unsigned) (Tcl_DStringLength(&envString)+1));
+ string = ckrealloc(string, (unsigned) Tcl_DStringLength(&envString)+1);
strcpy(string, Tcl_DStringValue(&envString));
Tcl_DStringFree(&envString);
putenv(string);
/*
- * Watch out for versions of putenv that copy the string (e.g. VC++).
- * In this case we need to free the string immediately. Otherwise
- * update the string in the cache.
+ * Watch out for versions of putenv that copy the string (e.g. VC++). In
+ * this case we need to free the string immediately. Otherwise update the
+ * string in the cache.
*/
if (environ[index] == string) {
ReplaceString(oldValue, string);
#ifdef HAVE_PUTENV_THAT_COPIES
} else {
- /* This putenv() copies instead of taking ownership */
+ /*
+ * This putenv() copies instead of taking ownership.
+ */
+
ckfree(string);
-#endif
+#endif /* HAVE_PUTENV_THAT_COPIES */
}
-#else
+#else /* !USE_PUTENV_FOR_UNSET */
for (envPtr = environ+index+1; ; envPtr++) {
envPtr[-1] = *envPtr;
if (*envPtr == NULL) {
@@ -439,7 +440,7 @@ TclUnsetEnv(name)
}
}
ReplaceString(oldValue, NULL);
-#endif
+#endif /* USE_PUTENV_FOR_UNSET */
Tcl_MutexUnlock(&envMutex);
}
@@ -453,10 +454,10 @@ TclUnsetEnv(name)
*
* Results:
* The result is a pointer to a string specifying the value of the
- * environment variable, or NULL if that environment variable does
- * not exist. Storage for the result string is allocated in valuePtr;
- * the caller must call Tcl_DStringFree() when the result is no
- * longer needed.
+ * environment variable, or NULL if that environment variable does not
+ * exist. Storage for the result string is allocated in valuePtr; the
+ * caller must call Tcl_DStringFree() when the result is no longer
+ * needed.
*
* Side effects:
* None.
@@ -464,23 +465,23 @@ TclUnsetEnv(name)
*----------------------------------------------------------------------
*/
-CONST char *
-TclGetEnv(name, valuePtr)
- CONST char *name; /* Name of environment variable to find
+const char *
+TclGetEnv(
+ const char *name, /* Name of environment variable to find
* (UTF-8). */
- Tcl_DString *valuePtr; /* Uninitialized or free DString in which
- * the value of the environment variable is
+ Tcl_DString *valuePtr) /* Uninitialized or free DString in which the
+ * value of the environment variable is
* stored. */
{
int length, index;
- CONST char *result;
+ const char *result;
Tcl_MutexLock(&envMutex);
index = TclpFindVariable(name, &length);
result = NULL;
if (index != -1) {
Tcl_DString envStr;
-
+
result = Tcl_ExternalToUtfDString(NULL, environ[index], -1, &envStr);
result += length;
if (*result == '=') {
@@ -502,32 +503,31 @@ TclGetEnv(name, valuePtr)
*
* EnvTraceProc --
*
- * This procedure is invoked whenever an environment variable
- * is read, modified or deleted. It propagates the change to the global
- * "environ" array.
+ * This function is invoked whenever an environment variable is read,
+ * modified or deleted. It propagates the change to the global "environ"
+ * array.
*
* Results:
* Always returns NULL to indicate success.
*
* Side effects:
- * Environment variable changes get propagated. If the whole
- * "env" array is deleted, then we stop managing things for
- * this interpreter (usually this happens because the whole
- * interpreter is being deleted).
+ * Environment variable changes get propagated. If the whole "env" array
+ * is deleted, then we stop managing things for this interpreter (usually
+ * this happens because the whole interpreter is being deleted).
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
static char *
-EnvTraceProc(clientData, interp, name1, name2, flags)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Interpreter whose "env" variable is
- * being modified. */
- CONST char *name1; /* Better be "env". */
- CONST char *name2; /* Name of variable being modified, or NULL
- * if whole array is being deleted (UTF-8). */
- int flags; /* Indicates what's happening. */
+EnvTraceProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter whose "env" variable is being
+ * modified. */
+ const char *name1, /* Better be "env". */
+ const char *name2, /* Name of variable being modified, or NULL if
+ * whole array is being deleted (UTF-8). */
+ int flags) /* Indicates what's happening. */
{
/*
* For array traces, let TclSetupEnv do all the work.
@@ -541,7 +541,7 @@ EnvTraceProc(clientData, interp, name1, name2, flags)
/*
* If name2 is NULL, then return and do nothing.
*/
-
+
if (name2 == NULL) {
return NULL;
}
@@ -551,8 +551,8 @@ EnvTraceProc(clientData, interp, name1, name2, flags)
*/
if (flags & TCL_TRACE_WRITES) {
- CONST char *value;
-
+ const char *value;
+
value = Tcl_GetVar2(interp, "env", name2, TCL_GLOBAL_ONLY);
TclSetEnv(name2, value);
}
@@ -563,9 +563,8 @@ EnvTraceProc(clientData, interp, name1, name2, flags)
if (flags & TCL_TRACE_READS) {
Tcl_DString valueString;
- CONST char *value;
+ const char *value = TclGetEnv(name2, &valueString);
- value = TclGetEnv(name2, &valueString);
if (value == NULL) {
return "no such variable";
}
@@ -588,9 +587,9 @@ EnvTraceProc(clientData, interp, name1, name2, flags)
*
* ReplaceString --
*
- * Replace one string with another in the environment variable
- * cache. The cache keeps track of all of the environment
- * variables that Tcl has modified so they can be freed later.
+ * Replace one string with another in the environment variable cache. The
+ * cache keeps track of all of the environment variables that Tcl has
+ * modified so they can be freed later.
*
* Results:
* None.
@@ -602,61 +601,54 @@ EnvTraceProc(clientData, interp, name1, name2, flags)
*/
static void
-ReplaceString(oldStr, newStr)
- CONST char *oldStr; /* Old environment string. */
- char *newStr; /* New environment string. */
+ReplaceString(
+ const char *oldStr, /* Old environment string. */
+ char *newStr) /* New environment string. */
{
int i;
- char **newCache;
/*
- * Check to see if the old value was allocated by Tcl. If so,
- * it needs to be deallocated to avoid memory leaks. Note that this
- * algorithm is O(n), not O(1). This will result in n-squared behavior
- * if lots of environment changes are being made.
+ * Check to see if the old value was allocated by Tcl. If so, it needs to
+ * be deallocated to avoid memory leaks. Note that this algorithm is O(n),
+ * not O(1). This will result in n-squared behavior if lots of environment
+ * changes are being made.
*/
- for (i = 0; i < cacheSize; i++) {
- if ((environCache[i] == oldStr) || (environCache[i] == NULL)) {
+ for (i = 0; i < env.cacheSize; i++) {
+ if (env.cache[i]==oldStr || env.cache[i]==NULL) {
break;
}
}
- if (i < cacheSize) {
+ if (i < env.cacheSize) {
/*
* Replace or delete the old value.
*/
- if (environCache[i]) {
- ckfree(environCache[i]);
+ if (env.cache[i]) {
+ ckfree(env.cache[i]);
}
if (newStr) {
- environCache[i] = newStr;
+ env.cache[i] = newStr;
} else {
- for (; i < cacheSize-1; i++) {
- environCache[i] = environCache[i+1];
+ for (; i < env.cacheSize-1; i++) {
+ env.cache[i] = env.cache[i+1];
}
- environCache[cacheSize-1] = NULL;
+ env.cache[env.cacheSize-1] = NULL;
}
} else {
- int allocatedSize = (cacheSize + 5) * sizeof(char *);
-
/*
* We need to grow the cache in order to hold the new string.
*/
- newCache = (char **) ckalloc((unsigned) allocatedSize);
- (VOID *) memset(newCache, (int) 0, (size_t) allocatedSize);
+ const int growth = 5;
- if (environCache) {
- memcpy((VOID *) newCache, (VOID *) environCache,
- (size_t) (cacheSize * sizeof(char*)));
- ckfree((char *) environCache);
- }
- environCache = newCache;
- environCache[cacheSize] = newStr;
- environCache[cacheSize+1] = NULL;
- cacheSize += 5;
+ env.cache = (char **) ckrealloc((char *) env.cache,
+ (env.cacheSize + growth) * sizeof(char *));
+ env.cache[env.cacheSize] = newStr;
+ (void) memset(env.cache+env.cacheSize+1, (int) 0,
+ (size_t) (growth-1) * sizeof(char*));
+ env.cacheSize += growth;
}
}
@@ -665,9 +657,9 @@ ReplaceString(oldStr, newStr)
*
* TclFinalizeEnvironment --
*
- * This function releases any storage allocated by this module
- * that isn't still in use by the global environment. Any
- * strings that are still in the environment will be leaked.
+ * This function releases any storage allocated by this module that isn't
+ * still in use by the global environment. Any strings that are still in
+ * the environment will be leaked.
*
* Results:
* None.
@@ -679,29 +671,27 @@ ReplaceString(oldStr, newStr)
*/
void
-TclFinalizeEnvironment()
+TclFinalizeEnvironment(void)
{
/*
* For now we just deallocate the cache array and none of the environment
- * strings. This may leak more memory that strictly necessary, since some
- * of the strings may no longer be in the environment. However,
+ * strings. This may leak more memory that strictly necessary, since some
+ * of the strings may no longer be in the environment. However,
* determining which ones are ok to delete is n-squared, and is pretty
* unlikely, so we don't bother.
*/
- if (environCache) {
- ckfree((char *) environCache);
- environCache = NULL;
- cacheSize = 0;
+ if (env.cache) {
+ ckfree((char *) env.cache);
+ env.cache = NULL;
+ env.cacheSize = 0;
#ifndef USE_PUTENV
- environSize = 0;
+ env.ourEnvironSize = 0;
#endif
}
}
-#if defined(__CYGWIN__) && defined(__WIN32__)
-
-#include <windows.h>
+#if defined(__CYGWIN__)
/*
* When using cygwin, when an environment variable changes, we need to synch
@@ -711,31 +701,38 @@ TclFinalizeEnvironment()
*/
static void
-TclCygwinPutenv(str)
- const char *str;
+TclCygwinPutenv(
+ char *str)
{
char *name, *value;
- /* Get the name and value, so that we can change the environment
- variable for Windows. */
- name = (char *) alloca (strlen (str) + 1);
- strcpy (name, str);
- for (value = name; *value != '=' && *value != '\0'; ++value)
- ;
+ /*
+ * Get the name and value, so that we can change the environment variable
+ * for Windows.
+ */
+
+ name = alloca(strlen(str) + 1);
+ strcpy(name, str);
+ for (value=name ; *value!='=' && *value!='\0' ; ++value) {
+ /* Empty body */
+ }
if (*value == '\0') {
- /* Can't happen. */
- return;
- }
+ /* Can't happen. */
+ return;
+ }
*value = '\0';
++value;
if (*value == '\0') {
value = NULL;
}
- /* Set the cygwin environment variable. */
+ /*
+ * Set the cygwin environment variable.
+ */
+
#undef putenv
if (value == NULL) {
- unsetenv (name);
+ unsetenv(name);
} else {
putenv(str);
}
@@ -748,34 +745,56 @@ TclCygwinPutenv(str)
* may have set the path to a Windows path, or, worse, appended or
* prepended a Windows path to PATH.
*/
- if (strcmp (name, "PATH") != 0) {
- /* If this is Path, eliminate any PATH variable, to prevent any
- confusion. */
- if (strcmp (name, "Path") == 0) {
- SetEnvironmentVariable ("PATH", (char *) NULL);
- unsetenv ("PATH");
+
+ if (strcmp(name, "PATH") != 0) {
+ /*
+ * If this is Path, eliminate any PATH variable, to prevent any
+ * confusion.
+ */
+
+ if (strcmp(name, "Path") == 0) {
+#ifdef __WIN32__
+ SetEnvironmentVariable("PATH", NULL);
+#endif
+ unsetenv("PATH");
}
- SetEnvironmentVariable (name, value);
+#ifdef __WIN32__
+ SetEnvironmentVariable(name, value);
+#endif
} else {
char *buf;
- /* Eliminate any Path variable, to prevent any confusion. */
- SetEnvironmentVariable ("Path", (char *) NULL);
- unsetenv ("Path");
+ /*
+ * Eliminate any Path variable, to prevent any confusion.
+ */
+
+#ifdef __WIN32__
+ SetEnvironmentVariable("Path", NULL);
+#endif
+ unsetenv("Path");
if (value == NULL) {
buf = NULL;
} else {
int size;
- size = cygwin_posix_to_win32_path_list_buf_size (value);
- buf = (char *) alloca (size + 1);
- cygwin_posix_to_win32_path_list (value, buf);
+ size = cygwin_posix_to_win32_path_list_buf_size(value);
+ buf = alloca(size + 1);
+ cygwin_posix_to_win32_path_list(value, buf);
}
- SetEnvironmentVariable (name, buf);
+#ifdef __WIN32__
+ SetEnvironmentVariable(name, buf);
+#endif
}
}
-
-#endif /* __CYGWIN__ && __WIN32__ */
+#endif /* __CYGWIN__ */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclEvent.c b/generic/tclEvent.c
index 06b3a4c..7daa7bb 100644
--- a/generic/tclEvent.c
+++ b/generic/tclEvent.c
@@ -1,50 +1,45 @@
-/*
+/*
* tclEvent.c --
*
* This file implements some general event related interfaces including
- * background errors, exit handlers, and the "vwait" and "update"
- * command procedures.
+ * background errors, exit handlers, and the "vwait" and "update" command
+ * functions.
*
* Copyright (c) 1990-1994 The Regents of the University of California.
* Copyright (c) 1994-1998 Sun Microsystems, Inc.
+ * Copyright (c) 2004 by Zoran Vasiljevic.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
/*
- * The data structure below is used to report background errors. One
- * such structure is allocated for each error; it holds information
- * about the interpreter and the error until bgerror can be invoked
- * later as an idle handler.
+ * The data structure below is used to report background errors. One such
+ * structure is allocated for each error; it holds information about the
+ * interpreter and the error until an idle handler command can be invoked.
*/
typedef struct BgError {
- Tcl_Interp *interp; /* Interpreter in which error occurred. NULL
- * means this error report has been cancelled
- * (a previous report generated a break). */
- char *errorMsg; /* Copy of the error message (the interp's
- * result when the error occurred).
- * Malloc-ed. */
- char *errorInfo; /* Value of the errorInfo variable
- * (malloc-ed). */
- char *errorCode; /* Value of the errorCode variable
- * (malloc-ed). */
- struct BgError *nextPtr; /* Next in list of all pending error
- * reports for this interpreter, or NULL
- * for end of list. */
+ Tcl_Obj *errorMsg; /* Copy of the error message (the interp's
+ * result when the error occurred). */
+ Tcl_Obj *returnOpts; /* Active return options when the error
+ * occurred */
+ struct BgError *nextPtr; /* Next in list of all pending error reports
+ * for this interpreter, or NULL for end of
+ * list. */
} BgError;
/*
- * One of the structures below is associated with the "tclBgError"
- * assoc data for each interpreter. It keeps track of the head and
- * tail of the list of pending background errors for the interpreter.
+ * One of the structures below is associated with the "tclBgError" assoc data
+ * for each interpreter. It keeps track of the head and tail of the list of
+ * pending background errors for the interpreter.
*/
typedef struct ErrAssocData {
+ Tcl_Interp *interp; /* Interpreter in which error occurred. */
+ Tcl_Obj *cmdPrefix; /* First word(s) of the handler command */
BgError *firstBgPtr; /* First in list of all background errors
* waiting to be processed for this
* interpreter (NULL if none). */
@@ -59,16 +54,15 @@ typedef struct ErrAssocData {
*/
typedef struct ExitHandler {
- Tcl_ExitProc *proc; /* Procedure to call when process exits. */
+ Tcl_ExitProc *proc; /* Function to call when process exits. */
ClientData clientData; /* One word of information to pass to proc. */
- struct ExitHandler *nextPtr;/* Next in list of all exit handlers for
- * this application, or NULL for end of list. */
+ struct ExitHandler *nextPtr;/* Next in list of all exit handlers for this
+ * application, or NULL for end of list. */
} ExitHandler;
/*
- * There is both per-process and per-thread exit handlers.
- * The first list is controlled by a mutex. The other is in
- * thread local storage.
+ * There is both per-process and per-thread exit handlers. The first list is
+ * controlled by a mutex. The other is in thread local storage.
*/
static ExitHandler *firstExitPtr = NULL;
@@ -81,128 +75,96 @@ TCL_DECLARE_MUTEX(exitMutex)
/*
* This variable is set to 1 when Tcl_Finalize is called, and at the end of
- * its work, it is reset to 0. The variable is checked by TclInExit() to
- * allow different behavior for exit-time processing, e.g. in closing of
- * files and pipes.
+ * its work, it is reset to 0. The variable is checked by TclInExit() to allow
+ * different behavior for exit-time processing, e.g. in closing of files and
+ * pipes.
*/
static int inFinalize = 0;
static int subsystemsInitialized = 0;
-typedef struct ThreadSpecificData {
- ExitHandler *firstExitPtr; /* First in list of all exit handlers for
- * this thread. */
- int inExit; /* True when this thread is exiting. This
- * is used as a hack to decide to close
- * the standard channels. */
- Tcl_Obj *tclLibraryPath; /* Path(s) to the Tcl library */
-} ThreadSpecificData;
-static Tcl_ThreadDataKey dataKey;
-
/*
- * Common string for the library path for sharing across threads.
- * This is ckalloc'd and cleared in Tcl_Finalize.
+ * This variable contains the application wide exit handler. It will be
+ * called by Tcl_Exit instead of the C-runtime exit if this variable is set
+ * to a non-NULL value.
*/
-static char *tclLibraryPathStr = NULL;
+static Tcl_ExitProc *appExitPtr = NULL;
-#ifdef TCL_THREADS
+typedef struct ThreadSpecificData {
+ ExitHandler *firstExitPtr; /* First in list of all exit handlers for this
+ * thread. */
+ int inExit; /* True when this thread is exiting. This is
+ * used as a hack to decide to close the
+ * standard channels. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+#ifdef TCL_THREADS
typedef struct {
Tcl_ThreadCreateProc *proc; /* Main() function of the thread */
ClientData clientData; /* The one argument to Main() */
} ThreadClientData;
-static Tcl_ThreadCreateType NewThreadProc _ANSI_ARGS_((
- ClientData clientData));
-#endif
+static Tcl_ThreadCreateType NewThreadProc(ClientData clientData);
+#endif /* TCL_THREADS */
/*
- * Prototypes for procedures referenced only in this file:
+ * Prototypes for functions referenced only in this file:
*/
-static void BgErrorDeleteProc _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp));
-static void HandleBgErrors _ANSI_ARGS_((ClientData clientData));
-static char * VwaitVarProc _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, CONST char *name1,
- CONST char *name2, int flags));
+static void BgErrorDeleteProc(ClientData clientData,
+ Tcl_Interp *interp);
+static void HandleBgErrors(ClientData clientData);
+static char * VwaitVarProc(ClientData clientData, Tcl_Interp *interp,
+ CONST char *name1, CONST char *name2, int flags);
/*
*----------------------------------------------------------------------
*
* Tcl_BackgroundError --
*
- * This procedure is invoked to handle errors that occur in Tcl
- * commands that are invoked in "background" (e.g. from event or
- * timer bindings).
+ * This function is invoked to handle errors that occur in Tcl commands
+ * that are invoked in "background" (e.g. from event or timer bindings).
*
* Results:
* None.
*
* Side effects:
- * The command "bgerror" is invoked later as an idle handler to
- * process the error, passing it the error message. If that fails,
- * then an error message is output on stderr.
+ * A handler command is invoked later as an idle handler to process the
+ * error, passing it the interp result and return options.
*
*----------------------------------------------------------------------
*/
void
-Tcl_BackgroundError(interp)
- Tcl_Interp *interp; /* Interpreter in which an error has
+Tcl_BackgroundError(
+ Tcl_Interp *interp) /* Interpreter in which an error has
+ * occurred. */
+{
+ TclBackgroundException(interp, TCL_ERROR);
+}
+void
+TclBackgroundException(
+ Tcl_Interp *interp, /* Interpreter in which an exception has
* occurred. */
+ int code) /* The exception code value */
{
BgError *errPtr;
- CONST char *errResult, *varValue;
ErrAssocData *assocPtr;
- int length;
- /*
- * The Tcl_AddErrorInfo call below (with an empty string) ensures that
- * errorInfo gets properly set. It's needed in cases where the error
- * came from a utility procedure like Tcl_GetVar instead of Tcl_Eval;
- * in these cases errorInfo still won't have been set when this
- * procedure is called.
- */
-
- Tcl_AddErrorInfo(interp, "");
+ if (code == TCL_OK) {
+ return;
+ }
- errResult = Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &length);
-
errPtr = (BgError *) ckalloc(sizeof(BgError));
- errPtr->interp = interp;
- errPtr->errorMsg = (char *) ckalloc((unsigned) (length + 1));
- memcpy(errPtr->errorMsg, errResult, (size_t) (length + 1));
- varValue = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
- if (varValue == NULL) {
- varValue = errPtr->errorMsg;
- }
- errPtr->errorInfo = (char *) ckalloc((unsigned) (strlen(varValue) + 1));
- strcpy(errPtr->errorInfo, varValue);
- varValue = Tcl_GetVar(interp, "errorCode", TCL_GLOBAL_ONLY);
- if (varValue == NULL) {
- varValue = "";
- }
- errPtr->errorCode = (char *) ckalloc((unsigned) (strlen(varValue) + 1));
- strcpy(errPtr->errorCode, varValue);
+ errPtr->errorMsg = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(errPtr->errorMsg);
+ errPtr->returnOpts = Tcl_GetReturnOptions(interp, code);
+ Tcl_IncrRefCount(errPtr->returnOpts);
errPtr->nextPtr = NULL;
- assocPtr = (ErrAssocData *) Tcl_GetAssocData(interp, "tclBgError",
- (Tcl_InterpDeleteProc **) NULL);
- if (assocPtr == NULL) {
-
- /*
- * This is the first time a background error has occurred in
- * this interpreter. Create associated data to keep track of
- * pending error reports.
- */
-
- assocPtr = (ErrAssocData *) ckalloc(sizeof(ErrAssocData));
- assocPtr->firstBgPtr = NULL;
- assocPtr->lastBgPtr = NULL;
- Tcl_SetAssocData(interp, "tclBgError", BgErrorDeleteProc,
- (ClientData) assocPtr);
- }
+ (void) TclGetBgErrorHandler(interp);
+ assocPtr = (ErrAssocData *) Tcl_GetAssocData(interp, "tclBgError", NULL);
if (assocPtr->firstBgPtr == NULL) {
assocPtr->firstBgPtr = errPtr;
Tcl_DoWhenIdle(HandleBgErrors, (ClientData) assocPtr);
@@ -218,145 +180,383 @@ Tcl_BackgroundError(interp)
*
* HandleBgErrors --
*
- * This procedure is invoked as an idle handler to process all of
- * the accumulated background errors.
+ * This function is invoked as an idle handler to process all of the
+ * accumulated background errors.
*
* Results:
* None.
*
* Side effects:
- * Depends on what actions "bgerror" takes for the errors.
+ * Depends on what actions the handler command takes for the errors.
*
*----------------------------------------------------------------------
*/
static void
-HandleBgErrors(clientData)
- ClientData clientData; /* Pointer to ErrAssocData structure. */
+HandleBgErrors(
+ ClientData clientData) /* Pointer to ErrAssocData structure. */
{
- Tcl_Interp *interp;
- CONST char *argv[2];
- int code;
- BgError *errPtr;
ErrAssocData *assocPtr = (ErrAssocData *) clientData;
- Tcl_Channel errChannel;
+ Tcl_Interp *interp = assocPtr->interp;
+ BgError *errPtr;
+
+ /*
+ * Not bothering to save/restore the interp state. Assume that any code
+ * that has interp state it needs to keep will make its own
+ * Tcl_SaveInterpState call before calling something like Tcl_DoOneEvent()
+ * that could lead us here.
+ */
Tcl_Preserve((ClientData) assocPtr);
-
+ Tcl_Preserve((ClientData) interp);
while (assocPtr->firstBgPtr != NULL) {
- interp = assocPtr->firstBgPtr->interp;
- if (interp == NULL) {
- goto doneWithInterp;
- }
+ int code, prefixObjc;
+ Tcl_Obj **prefixObjv, **tempObjv;
/*
- * Restore important state variables to what they were at
- * the time the error occurred.
+ * Note we copy the handler command prefix each pass through, so
+ * we do support one handler setting another handler.
*/
- Tcl_SetVar(interp, "errorInfo", assocPtr->firstBgPtr->errorInfo,
- TCL_GLOBAL_ONLY);
- Tcl_SetVar(interp, "errorCode", assocPtr->firstBgPtr->errorCode,
- TCL_GLOBAL_ONLY);
+ Tcl_Obj *copyObj = TclListObjCopy(NULL, assocPtr->cmdPrefix);
+
+ errPtr = assocPtr->firstBgPtr;
+
+ Tcl_ListObjGetElements(NULL, copyObj, &prefixObjc, &prefixObjv);
+ tempObjv = (Tcl_Obj **) ckalloc((prefixObjc+2)*sizeof(Tcl_Obj *));
+ memcpy(tempObjv, prefixObjv, prefixObjc*sizeof(Tcl_Obj *));
+ tempObjv[prefixObjc] = errPtr->errorMsg;
+ tempObjv[prefixObjc+1] = errPtr->returnOpts;
+ Tcl_AllowExceptions(interp);
+ code = Tcl_EvalObjv(interp, prefixObjc+2, tempObjv, TCL_EVAL_GLOBAL);
/*
- * Create and invoke the bgerror command.
+ * Discard the command and the information about the error report.
*/
- argv[0] = "bgerror";
- argv[1] = assocPtr->firstBgPtr->errorMsg;
-
- Tcl_AllowExceptions(interp);
- Tcl_Preserve((ClientData) interp);
- code = TclGlobalInvoke(interp, 2, argv, 0);
- if (code == TCL_ERROR) {
-
- /*
- * If the interpreter is safe, we look for a hidden command
- * named "bgerror" and call that with the error information.
- * Otherwise, simply ignore the error. The rationale is that
- * this could be an error caused by a malicious applet trying
- * to cause an infinite barrage of error messages. The hidden
- * "bgerror" command can be used by a security policy to
- * interpose on such attacks and e.g. kill the applet after a
- * few attempts.
- */
-
- if (Tcl_IsSafe(interp)) {
- Tcl_SavedResult save;
-
- Tcl_SaveResult(interp, &save);
- TclGlobalInvoke(interp, 2, argv, TCL_INVOKE_HIDDEN);
- Tcl_RestoreResult(interp, &save);
-
- goto doneWithInterp;
- }
-
- /*
- * We have to get the error output channel at the latest possible
- * time, because the eval (above) might have changed the channel.
- */
-
- errChannel = Tcl_GetStdChannel(TCL_STDERR);
- if (errChannel != (Tcl_Channel) NULL) {
- char *string;
- int len;
-
- string = Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &len);
- if (Tcl_FindCommand(interp, "bgerror", NULL, TCL_GLOBAL_ONLY) == NULL) {
- Tcl_WriteChars(errChannel, assocPtr->firstBgPtr->errorInfo, -1);
- Tcl_WriteChars(errChannel, "\n", -1);
- } else {
- Tcl_WriteChars(errChannel,
- "bgerror failed to handle background error.\n",
- -1);
- Tcl_WriteChars(errChannel, " Original error: ", -1);
- Tcl_WriteChars(errChannel, assocPtr->firstBgPtr->errorMsg,
- -1);
- Tcl_WriteChars(errChannel, "\n", -1);
- Tcl_WriteChars(errChannel, " Error in bgerror: ", -1);
- Tcl_WriteChars(errChannel, string, len);
- Tcl_WriteChars(errChannel, "\n", -1);
- }
- Tcl_Flush(errChannel);
- }
- } else if (code == TCL_BREAK) {
+ Tcl_DecrRefCount(copyObj);
+ Tcl_DecrRefCount(errPtr->errorMsg);
+ Tcl_DecrRefCount(errPtr->returnOpts);
+ assocPtr->firstBgPtr = errPtr->nextPtr;
+ ckfree((char *) errPtr);
+ ckfree((char *) tempObjv);
+ if (code == TCL_BREAK) {
/*
* Break means cancel any remaining error reports for this
* interpreter.
*/
- for (errPtr = assocPtr->firstBgPtr; errPtr != NULL;
- errPtr = errPtr->nextPtr) {
- if (errPtr->interp == interp) {
- errPtr->interp = NULL;
+ while (assocPtr->firstBgPtr != NULL) {
+ errPtr = assocPtr->firstBgPtr;
+ assocPtr->firstBgPtr = errPtr->nextPtr;
+ Tcl_DecrRefCount(errPtr->errorMsg);
+ Tcl_DecrRefCount(errPtr->returnOpts);
+ ckfree((char *) errPtr);
+ }
+ } else if ((code == TCL_ERROR) && !Tcl_IsSafe(interp)) {
+ Tcl_Channel errChannel = Tcl_GetStdChannel(TCL_STDERR);
+
+ if (errChannel != (Tcl_Channel) NULL) {
+ Tcl_Obj *options = Tcl_GetReturnOptions(interp, code);
+ Tcl_Obj *keyPtr, *valuePtr;
+
+ TclNewLiteralStringObj(keyPtr, "-errorinfo");
+ Tcl_IncrRefCount(keyPtr);
+ Tcl_DictObjGet(NULL, options, keyPtr, &valuePtr);
+ Tcl_DecrRefCount(keyPtr);
+
+ Tcl_WriteChars(errChannel,
+ "error in background error handler:\n", -1);
+ if (valuePtr) {
+ Tcl_WriteObj(errChannel, valuePtr);
+ } else {
+ Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
}
+ Tcl_WriteChars(errChannel, "\n", 1);
+ Tcl_Flush(errChannel);
+ Tcl_DecrRefCount(options);
}
}
+ }
+ assocPtr->lastBgPtr = NULL;
+ Tcl_Release((ClientData) interp);
+ Tcl_Release((ClientData) assocPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclDefaultBgErrorHandlerObjCmd --
+ *
+ * This function is invoked to process the "::tcl::Bgerror" Tcl command.
+ * It is the default handler command registered with [interp bgerror] for
+ * the sake of compatibility with older Tcl releases.
+ *
+ * Results:
+ * A standard Tcl object result.
+ *
+ * Side effects:
+ * Depends on what actions the "bgerror" command takes for the errors.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclDefaultBgErrorHandlerObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
+{
+ Tcl_Obj *keyPtr, *valuePtr;
+ Tcl_Obj *tempObjv[2];
+ int code, level;
+ Tcl_InterpState saved;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "msg options");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Check for a valid return options dictionary.
+ */
+
+ TclNewLiteralStringObj(keyPtr, "-level");
+ Tcl_IncrRefCount(keyPtr);
+ Tcl_DictObjGet(NULL, objv[2], keyPtr, &valuePtr);
+ Tcl_DecrRefCount(keyPtr);
+ if (valuePtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "missing return option \"-level\"", -1));
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIntFromObj(interp, valuePtr, &level) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ TclNewLiteralStringObj(keyPtr, "-code");
+ Tcl_IncrRefCount(keyPtr);
+ Tcl_DictObjGet(NULL, objv[2], keyPtr, &valuePtr);
+ Tcl_DecrRefCount(keyPtr);
+ if (valuePtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "missing return option \"-code\"", -1));
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIntFromObj(interp, valuePtr, &code) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ if (level != 0) {
+ /* We're handling a TCL_RETURN exception */
+ code = TCL_RETURN;
+ }
+ if (code == TCL_OK) {
/*
- * Discard the command and the information about the error report.
+ * Somehow we got to exception handling with no exception.
+ * (Pass TCL_OK to TclBackgroundException()?)
+ * Just return without doing anything.
*/
+ return TCL_OK;
+ }
+
+ /* Construct the bgerror command */
+ TclNewLiteralStringObj(tempObjv[0], "bgerror");
+ Tcl_IncrRefCount(tempObjv[0]);
+
+ /*
+ * Determine error message argument. Check the return options in case
+ * a non-error exception brought us here.
+ */
+
+ switch (code) {
+ case TCL_ERROR:
+ tempObjv[1] = objv[1];
+ break;
+ case TCL_BREAK:
+ TclNewLiteralStringObj(tempObjv[1],
+ "invoked \"break\" outside of a loop");
+ break;
+ case TCL_CONTINUE:
+ TclNewLiteralStringObj(tempObjv[1],
+ "invoked \"continue\" outside of a loop");
+ break;
+ default:
+ tempObjv[1] = Tcl_ObjPrintf("command returned bad code: %d", code);
+ break;
+ }
+ Tcl_IncrRefCount(tempObjv[1]);
+
+ if (code != TCL_ERROR) {
+ Tcl_SetObjResult(interp, tempObjv[1]);
+ }
-doneWithInterp:
+ TclNewLiteralStringObj(keyPtr, "-errorcode");
+ Tcl_IncrRefCount(keyPtr);
+ Tcl_DictObjGet(NULL, objv[2], keyPtr, &valuePtr);
+ Tcl_DecrRefCount(keyPtr);
+ if (valuePtr) {
+ Tcl_SetObjErrorCode(interp, valuePtr);
+ }
+
+ TclNewLiteralStringObj(keyPtr, "-errorinfo");
+ Tcl_IncrRefCount(keyPtr);
+ Tcl_DictObjGet(NULL, objv[2], keyPtr, &valuePtr);
+ Tcl_DecrRefCount(keyPtr);
+ if (valuePtr) {
+ Tcl_AppendObjToErrorInfo(interp, valuePtr);
+ }
+
+ if (code == TCL_ERROR) {
+ Tcl_SetObjResult(interp, tempObjv[1]);
+ }
+
+ /*
+ * Save interpreter state so we can restore it if multiple handler
+ * attempts are needed.
+ */
+
+ saved = Tcl_SaveInterpState(interp, code);
+
+ /* Invoke the bgerror command. */
+ Tcl_AllowExceptions(interp);
+ code = Tcl_EvalObjv(interp, 2, tempObjv, TCL_EVAL_GLOBAL);
+ if (code == TCL_ERROR) {
+ /*
+ * If the interpreter is safe, we look for a hidden command named
+ * "bgerror" and call that with the error information. Otherwise,
+ * simply ignore the error. The rationale is that this could be an
+ * error caused by a malicious applet trying to cause an infinite
+ * barrage of error messages. The hidden "bgerror" command can be used
+ * by a security policy to interpose on such attacks and e.g. kill the
+ * applet after a few attempts.
+ */
- if (assocPtr->firstBgPtr) {
- ckfree(assocPtr->firstBgPtr->errorMsg);
- ckfree(assocPtr->firstBgPtr->errorInfo);
- ckfree(assocPtr->firstBgPtr->errorCode);
- errPtr = assocPtr->firstBgPtr->nextPtr;
- ckfree((char *) assocPtr->firstBgPtr);
- assocPtr->firstBgPtr = errPtr;
+ if (Tcl_IsSafe(interp)) {
+ Tcl_RestoreInterpState(interp, saved);
+ TclObjInvoke(interp, 2, tempObjv, TCL_INVOKE_HIDDEN);
+ } else {
+ Tcl_Channel errChannel = Tcl_GetStdChannel(TCL_STDERR);
+ if (errChannel != (Tcl_Channel) NULL) {
+ Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);
+
+ Tcl_IncrRefCount(resultPtr);
+ if (Tcl_FindCommand(interp, "bgerror", NULL,
+ TCL_GLOBAL_ONLY) == NULL) {
+ Tcl_RestoreInterpState(interp, saved);
+ Tcl_WriteObj(errChannel, Tcl_GetVar2Ex(interp,
+ "errorInfo", NULL, TCL_GLOBAL_ONLY));
+ Tcl_WriteChars(errChannel, "\n", -1);
+ } else {
+ Tcl_DiscardInterpState(saved);
+ Tcl_WriteChars(errChannel,
+ "bgerror failed to handle background error.\n",-1);
+ Tcl_WriteChars(errChannel, " Original error: ", -1);
+ Tcl_WriteObj(errChannel, tempObjv[1]);
+ Tcl_WriteChars(errChannel, "\n", -1);
+ Tcl_WriteChars(errChannel, " Error in bgerror: ", -1);
+ Tcl_WriteObj(errChannel, resultPtr);
+ Tcl_WriteChars(errChannel, "\n", -1);
+ }
+ Tcl_DecrRefCount(resultPtr);
+ Tcl_Flush(errChannel);
+ } else {
+ Tcl_DiscardInterpState(saved);
+ }
}
-
- if (interp != NULL) {
- Tcl_Release((ClientData) interp);
- }
+ code = TCL_OK;
+ } else {
+ Tcl_DiscardInterpState(saved);
}
- assocPtr->lastBgPtr = NULL;
- Tcl_Release((ClientData) assocPtr);
+ Tcl_DecrRefCount(tempObjv[0]);
+ Tcl_DecrRefCount(tempObjv[1]);
+ Tcl_ResetResult(interp);
+ return code;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclSetBgErrorHandler --
+ *
+ * This function sets the command prefix to be used to handle background
+ * errors in interp.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Error handler is registered.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclSetBgErrorHandler(
+ Tcl_Interp *interp,
+ Tcl_Obj *cmdPrefix)
+{
+ ErrAssocData *assocPtr = (ErrAssocData *)
+ Tcl_GetAssocData(interp, "tclBgError", NULL);
+
+ if (cmdPrefix == NULL) {
+ Tcl_Panic("TclSetBgErrorHandler: NULL cmdPrefix argument");
+ }
+ if (assocPtr == NULL) {
+ /*
+ * First access: initialize.
+ */
+
+ assocPtr = (ErrAssocData *) ckalloc(sizeof(ErrAssocData));
+ assocPtr->interp = interp;
+ assocPtr->cmdPrefix = NULL;
+ assocPtr->firstBgPtr = NULL;
+ assocPtr->lastBgPtr = NULL;
+ Tcl_SetAssocData(interp, "tclBgError", BgErrorDeleteProc,
+ (ClientData) assocPtr);
+ }
+ if (assocPtr->cmdPrefix) {
+ Tcl_DecrRefCount(assocPtr->cmdPrefix);
+ }
+ assocPtr->cmdPrefix = cmdPrefix;
+ Tcl_IncrRefCount(assocPtr->cmdPrefix);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetBgErrorHandler --
+ *
+ * This function retrieves the command prefix currently used to handle
+ * background errors in interp.
+ *
+ * Results:
+ * A (Tcl_Obj *) to a list of words (command prefix).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclGetBgErrorHandler(
+ Tcl_Interp *interp)
+{
+ ErrAssocData *assocPtr = (ErrAssocData *)
+ Tcl_GetAssocData(interp, "tclBgError", NULL);
+
+ if (assocPtr == NULL) {
+ Tcl_Obj *bgerrorObj;
+
+ TclNewLiteralStringObj(bgerrorObj, "::tcl::Bgerror");
+ TclSetBgErrorHandler(interp, bgerrorObj);
+ assocPtr = (ErrAssocData *)
+ Tcl_GetAssocData(interp, "tclBgError", NULL);
+ }
+ return assocPtr->cmdPrefix;
}
/*
@@ -364,25 +564,24 @@ doneWithInterp:
*
* BgErrorDeleteProc --
*
- * This procedure is associated with the "tclBgError" assoc data
- * for an interpreter; it is invoked when the interpreter is
- * deleted in order to free the information assoicated with any
- * pending error reports.
+ * This function is associated with the "tclBgError" assoc data for an
+ * interpreter; it is invoked when the interpreter is deleted in order to
+ * free the information assoicated with any pending error reports.
*
* Results:
* None.
*
* Side effects:
- * Background error information is freed: if there were any
- * pending error reports, they are cancelled.
+ * Background error information is freed: if there were any pending error
+ * reports, they are cancelled.
*
*----------------------------------------------------------------------
*/
static void
-BgErrorDeleteProc(clientData, interp)
- ClientData clientData; /* Pointer to ErrAssocData structure. */
- Tcl_Interp *interp; /* Interpreter being deleted. */
+BgErrorDeleteProc(
+ ClientData clientData, /* Pointer to ErrAssocData structure. */
+ Tcl_Interp *interp) /* Interpreter being deleted. */
{
ErrAssocData *assocPtr = (ErrAssocData *) clientData;
BgError *errPtr;
@@ -390,12 +589,12 @@ BgErrorDeleteProc(clientData, interp)
while (assocPtr->firstBgPtr != NULL) {
errPtr = assocPtr->firstBgPtr;
assocPtr->firstBgPtr = errPtr->nextPtr;
- ckfree(errPtr->errorMsg);
- ckfree(errPtr->errorInfo);
- ckfree(errPtr->errorCode);
+ Tcl_DecrRefCount(errPtr->errorMsg);
+ Tcl_DecrRefCount(errPtr->returnOpts);
ckfree((char *) errPtr);
}
Tcl_CancelIdleCall(HandleBgErrors, (ClientData) assocPtr);
+ Tcl_DecrRefCount(assocPtr->cmdPrefix);
Tcl_EventuallyFree((ClientData) assocPtr, TCL_DYNAMIC);
}
@@ -404,23 +603,23 @@ BgErrorDeleteProc(clientData, interp)
*
* Tcl_CreateExitHandler --
*
- * Arrange for a given procedure to be invoked just before the
- * application exits.
+ * Arrange for a given function to be invoked just before the application
+ * exits.
*
* Results:
* None.
*
* Side effects:
- * Proc will be invoked with clientData as argument when the
- * application exits.
+ * Proc will be invoked with clientData as argument when the application
+ * exits.
*
*----------------------------------------------------------------------
*/
void
-Tcl_CreateExitHandler(proc, clientData)
- Tcl_ExitProc *proc; /* Procedure to invoke. */
- ClientData clientData; /* Arbitrary value to pass to proc. */
+Tcl_CreateExitHandler(
+ Tcl_ExitProc *proc, /* Function to invoke. */
+ ClientData clientData) /* Arbitrary value to pass to proc. */
{
ExitHandler *exitPtr;
@@ -471,24 +670,23 @@ TclCreateLateExitHandler(
*
* Tcl_DeleteExitHandler --
*
- * This procedure cancels an existing exit handler matching proc
- * and clientData, if such a handler exits.
+ * This function cancels an existing exit handler matching proc and
+ * clientData, if such a handler exits.
*
* Results:
* None.
*
* Side effects:
- * If there is an exit handler corresponding to proc and clientData
- * then it is cancelled; if no such handler exists then nothing
- * happens.
+ * If there is an exit handler corresponding to proc and clientData then
+ * it is cancelled; if no such handler exists then nothing happens.
*
*----------------------------------------------------------------------
*/
void
-Tcl_DeleteExitHandler(proc, clientData)
- Tcl_ExitProc *proc; /* Procedure that was previously registered. */
- ClientData clientData; /* Arbitrary value to pass to proc. */
+Tcl_DeleteExitHandler(
+ Tcl_ExitProc *proc, /* Function that was previously registered. */
+ ClientData clientData) /* Arbitrary value to pass to proc. */
{
ExitHandler *exitPtr, *prevPtr;
@@ -558,23 +756,23 @@ TclDeleteLateExitHandler(
*
* Tcl_CreateThreadExitHandler --
*
- * Arrange for a given procedure to be invoked just before the
- * current thread exits.
+ * Arrange for a given function to be invoked just before the current
+ * thread exits.
*
* Results:
* None.
*
* Side effects:
- * Proc will be invoked with clientData as argument when the
- * application exits.
+ * Proc will be invoked with clientData as argument when the application
+ * exits.
*
*----------------------------------------------------------------------
*/
void
-Tcl_CreateThreadExitHandler(proc, clientData)
- Tcl_ExitProc *proc; /* Procedure to invoke. */
- ClientData clientData; /* Arbitrary value to pass to proc. */
+Tcl_CreateThreadExitHandler(
+ Tcl_ExitProc *proc, /* Function to invoke. */
+ ClientData clientData) /* Arbitrary value to pass to proc. */
{
ExitHandler *exitPtr;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -591,24 +789,23 @@ Tcl_CreateThreadExitHandler(proc, clientData)
*
* Tcl_DeleteThreadExitHandler --
*
- * This procedure cancels an existing exit handler matching proc
- * and clientData, if such a handler exits.
+ * This function cancels an existing exit handler matching proc and
+ * clientData, if such a handler exits.
*
* Results:
* None.
*
* Side effects:
- * If there is an exit handler corresponding to proc and clientData
- * then it is cancelled; if no such handler exists then nothing
- * happens.
+ * If there is an exit handler corresponding to proc and clientData then
+ * it is cancelled; if no such handler exists then nothing happens.
*
*----------------------------------------------------------------------
*/
void
-Tcl_DeleteThreadExitHandler(proc, clientData)
- Tcl_ExitProc *proc; /* Procedure that was previously registered. */
- ClientData clientData; /* Arbitrary value to pass to proc. */
+Tcl_DeleteThreadExitHandler(
+ Tcl_ExitProc *proc, /* Function that was previously registered. */
+ ClientData clientData) /* Arbitrary value to pass to proc. */
{
ExitHandler *exitPtr, *prevPtr;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -631,113 +828,85 @@ Tcl_DeleteThreadExitHandler(proc, clientData)
/*
*----------------------------------------------------------------------
*
- * Tcl_Exit --
+ * Tcl_SetExitProc --
*
- * This procedure is called to terminate the application.
+ * This function sets the application wide exit handler that will be
+ * called by Tcl_Exit in place of the C-runtime exit. If the application
+ * wide exit handler is NULL, the C-runtime exit will be used instead.
*
* Results:
- * None.
+ * The previously set application wide exit handler.
*
* Side effects:
- * All existing exit handlers are invoked, then the application
- * ends.
+ * Sets the application wide exit handler to the specified value.
*
*----------------------------------------------------------------------
*/
-void
-Tcl_Exit(status)
- int status; /* Exit status for application; typically
- * 0 for normal return, 1 for error return. */
-{
- Tcl_Finalize();
- TclpExit(status);
-}
-
-/*
- *-------------------------------------------------------------------------
- *
- * TclSetLibraryPath --
- *
- * Set the path that will be used for searching for init.tcl and
- * encodings when an interp is being created.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Changing the library path will affect what directories are
- * examined when looking for encodings for all interps from that
- * point forward.
- *
- * The refcount of the new library path is incremented and the
- * refcount of the old path is decremented.
- *
- *-------------------------------------------------------------------------
- */
-
-void
-TclSetLibraryPath(pathPtr)
- Tcl_Obj *pathPtr; /* A Tcl list object whose elements are
- * the new library path. */
+Tcl_ExitProc *
+Tcl_SetExitProc(
+ Tcl_ExitProc *proc) /* New exit handler for app or NULL */
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- const char *toDupe;
- int size;
-
- if (pathPtr != NULL) {
- Tcl_IncrRefCount(pathPtr);
- }
- if (tsdPtr->tclLibraryPath != NULL) {
- Tcl_DecrRefCount(tsdPtr->tclLibraryPath);
- }
- tsdPtr->tclLibraryPath = pathPtr;
+ Tcl_ExitProc *prevExitProc;
/*
- * No mutex locking is needed here as up the stack we're within
- * TclpInitLock().
+ * Swap the old exit proc for the new one, saving the old one for our
+ * return value.
*/
- if (tclLibraryPathStr != NULL) {
- ckfree(tclLibraryPathStr);
- }
- toDupe = Tcl_GetStringFromObj(pathPtr, &size);
- tclLibraryPathStr = ckalloc((unsigned)size+1);
- memcpy(tclLibraryPathStr, toDupe, (unsigned)size+1);
+
+ Tcl_MutexLock(&exitMutex);
+ prevExitProc = appExitPtr;
+ appExitPtr = proc;
+ Tcl_MutexUnlock(&exitMutex);
+
+ return prevExitProc;
}
/*
- *-------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*
- * TclGetLibraryPath --
+ * Tcl_Exit --
*
- * Return a Tcl list object whose elements are the library path.
- * The caller should not modify the contents of the returned object.
+ * This function is called to terminate the application.
*
* Results:
- * As above.
+ * None.
*
* Side effects:
- * None.
+ * All existing exit handlers are invoked, then the application ends.
*
- *-------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*/
-Tcl_Obj *
-TclGetLibraryPath()
+void
+Tcl_Exit(
+ int status) /* Exit status for application; typically 0
+ * for normal return, 1 for error return. */
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ Tcl_ExitProc *currentAppExitPtr;
- if (tsdPtr->tclLibraryPath == NULL) {
+ Tcl_MutexLock(&exitMutex);
+ currentAppExitPtr = appExitPtr;
+ Tcl_MutexUnlock(&exitMutex);
+
+ if (currentAppExitPtr) {
+ /*
+ * Warning: this code SHOULD NOT return, as there is code that depends
+ * on Tcl_Exit never returning. In fact, we will Tcl_Panic if anyone
+ * returns, so critical is this dependcy.
+ */
+
+ currentAppExitPtr((ClientData) INT2PTR(status));
+ Tcl_Panic("AppExitProc returned unexpectedly");
+ } else {
/*
- * Grab the shared string and place it into a new thread specific
- * Tcl_Obj.
+ * Use default handling.
*/
- tsdPtr->tclLibraryPath = Tcl_NewStringObj(tclLibraryPathStr, -1);
- /* take ownership */
- Tcl_IncrRefCount(tsdPtr->tclLibraryPath);
+ Tcl_Finalize();
+ TclpExit(status);
+ Tcl_Panic("OS exit failed!");
}
- return tsdPtr->tclLibraryPath;
}
/*
@@ -745,17 +914,16 @@ TclGetLibraryPath()
*
* TclInitSubsystems --
*
- * Initialize various subsytems in Tcl. This should be called the
- * first time an interp is created, or before any of the subsystems
- * are used. This function ensures an order for the initialization
- * of subsystems:
+ * Initialize various subsytems in Tcl. This should be called the first
+ * time an interp is created, or before any of the subsystems are used.
+ * This function ensures an order for the initialization of subsystems:
*
- * 1. that cannot be initialized in lazy order because they are
- * mutually dependent.
+ * 1. that cannot be initialized in lazy order because they are mutually
+ * dependent.
*
- * 2. so that they can be finalized in a known order w/o causing
- * the subsequent re-initialization of a subsystem in the act of
- * shutting down another.
+ * 2. so that they can be finalized in a known order w/o causing the
+ * subsequent re-initialization of a subsystem in the act of shutting
+ * down another.
*
* Results:
* None.
@@ -767,74 +935,55 @@ TclGetLibraryPath()
*/
void
-TclInitSubsystems(argv0)
- CONST char *argv0; /* Name of executable from argv[0] to main()
- * in native multi-byte encoding. */
+TclInitSubsystems(void)
{
- ThreadSpecificData *tsdPtr;
-
if (inFinalize != 0) {
- panic("TclInitSubsystems called while finalizing");
+ Tcl_Panic("TclInitSubsystems called while finalizing");
}
- /*
- * Grab the thread local storage pointer before doing anything because
- * the initialization routines will be registering exit handlers.
- * We use this pointer to detect if this is the first time this
- * thread has created an interpreter.
- */
-
- tsdPtr = (ThreadSpecificData *) TclThreadDataKeyGet(&dataKey);
-
if (subsystemsInitialized == 0) {
- /*
- * Double check inside the mutex. There are definitly calls
- * back into this routine from some of the procedures below.
+ /*
+ * Double check inside the mutex. There are definitly calls back into
+ * this routine from some of the functions below.
*/
TclpInitLock();
if (subsystemsInitialized == 0) {
/*
- * Have to set this bit here to avoid deadlock with the
- * routines below us that call into TclInitSubsystems.
+ * Have to set this bit here to avoid deadlock with the routines
+ * below us that call into TclInitSubsystems.
*/
subsystemsInitialized = 1;
- tclExecutableName = NULL;
-
/*
* Initialize locks used by the memory allocators before anything
* interesting happens so we can use the allocators in the
* implementation of self-initializing locks.
*/
+ TclInitThreadStorage(); /* Creates master hash table for
+ * thread local storage */
#if USE_TCLALLOC
- TclInitAlloc(); /* process wide mutex init */
+ TclInitAlloc(); /* Process wide mutex init */
#endif
#ifdef TCL_MEM_DEBUG
- TclInitDbCkalloc(); /* process wide mutex init */
+ TclInitDbCkalloc(); /* Process wide mutex init */
#endif
- TclpInitPlatform(); /* creates signal handler(s) */
- TclInitObjSubsystem(); /* register obj types, create mutexes */
- TclInitIOSubsystem(); /* inits a tsd key (noop) */
- TclInitEncodingSubsystem(); /* process wide encoding init */
- TclInitNamespaceSubsystem(); /* register ns obj type (mutexed) */
+ TclpInitPlatform(); /* Creates signal handler(s) */
+ TclInitDoubleConversion(); /* Initializes constants for
+ * converting to/from double. */
+ TclInitObjSubsystem(); /* Register obj types, create
+ * mutexes. */
+ TclInitIOSubsystem(); /* Inits a tsd key (noop). */
+ TclInitEncodingSubsystem(); /* Process wide encoding init. */
+ TclpSetInterfaces();
+ TclInitNamespaceSubsystem();/* Register ns obj type (mutexed). */
}
TclpInitUnlock();
}
-
- if (tsdPtr == NULL) {
- /*
- * First time this thread has created an interpreter.
- * We fetch the key again just in case no exit handlers were
- * registered by this point.
- */
-
- (void) TCL_TSD_INIT(&dataKey);
- TclInitNotifier();
- }
+ TclInitNotifier();
}
/*
@@ -842,10 +991,9 @@ TclInitSubsystems(argv0)
*
* Tcl_Finalize --
*
- * Shut down Tcl. First calls registered exit handlers, then
- * carefully shuts down various subsystems.
- * Called by Tcl_Exit or when the Tcl shared library is being
- * unloaded.
+ * Shut down Tcl. First calls registered exit handlers, then carefully
+ * shuts down various subsystems. Called by Tcl_Exit or when the Tcl
+ * shared library is being unloaded.
*
* Results:
* None.
@@ -857,10 +1005,10 @@ TclInitSubsystems(argv0)
*/
void
-Tcl_Finalize()
+Tcl_Finalize(void)
{
ExitHandler *exitPtr;
-
+
/*
* Invoke exit handlers first.
*/
@@ -869,10 +1017,9 @@ Tcl_Finalize()
inFinalize = 1;
for (exitPtr = firstExitPtr; exitPtr != NULL; exitPtr = firstExitPtr) {
/*
- * Be careful to remove the handler from the list before
- * invoking its callback. This protects us against
- * double-freeing if the callback should call
- * Tcl_DeleteExitHandler on itself.
+ * Be careful to remove the handler from the list before invoking its
+ * callback. This protects us against double-freeing if the callback
+ * should call Tcl_DeleteExitHandler on itself.
*/
firstExitPtr = exitPtr->nextPtr;
@@ -880,27 +1027,29 @@ Tcl_Finalize()
(*exitPtr->proc)(exitPtr->clientData);
ckfree((char *) exitPtr);
Tcl_MutexLock(&exitMutex);
- }
+ }
firstExitPtr = NULL;
Tcl_MutexUnlock(&exitMutex);
TclpInitLock();
- if (subsystemsInitialized != 0) {
- subsystemsInitialized = 0;
+ if (subsystemsInitialized == 0) {
+ goto alreadyFinalized;
+ }
+ subsystemsInitialized = 0;
- /*
- * Ensure the thread-specific data is initialised as it is
- * used in Tcl_FinalizeThread()
- */
+ /*
+ * Ensure the thread-specific data is initialised as it is used in
+ * Tcl_FinalizeThread()
+ */
- (void) TCL_TSD_INIT(&dataKey);
+ (void) TCL_TSD_INIT(&dataKey);
- /*
- * Clean up after the current thread now, after exit handlers.
- * In particular, the testexithandler command sets up something
- * that writes to standard output, which gets closed.
- * Note that there is no thread-local storage after this call.
- */
+ /*
+ * Clean up after the current thread now, after exit handlers. In
+ * particular, the testexithandler command sets up something that writes
+ * to standard output, which gets closed. Note that there is no
+ * thread-local storage or IO subsystem after this call.
+ */
Tcl_FinalizeThread();
@@ -930,110 +1079,114 @@ Tcl_Finalize()
* after the exit handlers, because there are order dependencies.
*/
- TclFinalizeCompilation();
- TclFinalizeExecution();
- TclFinalizeEnvironment();
+ TclFinalizeExecution();
+ TclFinalizeEnvironment();
- /*
- * Finalizing the filesystem must come after anything which
- * might conceivably interact with the 'Tcl_FS' API.
- */
+ /*
+ * Finalizing the filesystem must come after anything which might
+ * conceivably interact with the 'Tcl_FS' API.
+ */
- TclFinalizeFilesystem();
+ TclFinalizeFilesystem();
- /*
- * Undo all the Tcl_ObjType registrations, and reset the master list
- * of free Tcl_Obj's. After this returns, no more Tcl_Obj's should
- * be allocated or freed.
- *
- * Note in particular that TclFinalizeObjects() must follow
- * TclFinalizeFilesystem() because TclFinalizeFilesystem free's
- * the Tcl_Obj that holds the path of the current working directory.
- */
+ /*
+ * Undo all Tcl_ObjType registrations, and reset the master list of free
+ * Tcl_Obj's. After this returns, no more Tcl_Obj's should be allocated or
+ * freed.
+ *
+ * Note in particular that TclFinalizeObjects() must follow
+ * TclFinalizeFilesystem() because TclFinalizeFilesystem free's the
+ * Tcl_Obj that holds the path of the current working directory.
+ */
- TclFinalizeObjects();
+ TclFinalizeObjects();
- /*
- * We must be sure the encoding finalization doesn't need
- * to examine the filesystem in any way. Since it only
- * needs to clean up internal data structures, this is
- * fine.
- */
- TclFinalizeEncodingSubsystem();
+ /*
+ * We must be sure the encoding finalization doesn't need to examine the
+ * filesystem in any way. Since it only needs to clean up internal data
+ * structures, this is fine.
+ */
- if (tclExecutableName != NULL) {
- ckfree(tclExecutableName);
- tclExecutableName = NULL;
- }
- if (tclNativeExecutableName != NULL) {
- ckfree(tclNativeExecutableName);
- tclNativeExecutableName = NULL;
- }
- if (tclDefaultEncodingDir != NULL) {
- ckfree(tclDefaultEncodingDir);
- tclDefaultEncodingDir = NULL;
- }
- if (tclLibraryPathStr != NULL) {
- ckfree(tclLibraryPathStr);
- tclLibraryPathStr = NULL;
- }
-
- Tcl_SetPanicProc(NULL);
+ TclFinalizeEncodingSubsystem();
- /*
- * There have been several bugs in the past that cause
- * exit handlers to be established during Tcl_Finalize
- * processing. Such exit handlers leave malloc'ed memory,
- * and Tcl_FinalizeThreadAlloc or Tcl_FinalizeMemorySubsystem
- * will result in a corrupted heap. The result can be a
- * mysterious crash on process exit. Check here that
- * nobody's done this.
- */
+ Tcl_SetPanicProc(NULL);
-#ifdef TCL_MEM_DEBUG
- if ( firstExitPtr != NULL ) {
- Tcl_Panic( "exit handlers were created during Tcl_Finalize" );
- }
-#endif
+ /*
+ * Repeat finalization of the thread local storage once more. Although
+ * this step is already done by the Tcl_FinalizeThread call above, series
+ * of events happening afterwards may re-initialize TSD slots. Those need
+ * to be finalized again, otherwise we're leaking memory chunks. Very
+ * important to note is that things happening afterwards should not
+ * reference anything which may re-initialize TSD's. This includes freeing
+ * Tcl_Objs's, among other things.
+ *
+ * This fixes the Tcl Bug #990552.
+ */
- TclFinalizePreserve();
+ TclFinalizeThreadData();
- /*
- * Free synchronization objects. There really should only be one
- * thread alive at this moment.
- */
+ /*
+ * Now we can free constants for conversions to/from double.
+ */
+
+ TclFinalizeDoubleConversion();
+
+ /*
+ * There have been several bugs in the past that cause exit handlers to be
+ * established during Tcl_Finalize processing. Such exit handlers leave
+ * malloc'ed memory, and Tcl_FinalizeThreadAlloc or
+ * Tcl_FinalizeMemorySubsystem will result in a corrupted heap. The result
+ * can be a mysterious crash on process exit. Check here that nobody's
+ * done this.
+ */
+
+ if (firstExitPtr != NULL) {
+ Tcl_Panic("exit handlers were created during Tcl_Finalize");
+ }
+
+ TclFinalizePreserve();
+
+ /*
+ * Free synchronization objects. There really should only be one thread
+ * alive at this moment.
+ */
- TclFinalizeSynchronization();
+ TclFinalizeSynchronization();
-#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) && !defined(TCL_MEM_DEBUG) && !defined(PURIFY)
- TclFinalizeThreadAlloc();
+ /*
+ * Close down the thread-specific object allocator.
+ */
+
+#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
+ TclFinalizeThreadAlloc();
#endif
- /*
- * We defer unloading of packages until very late
- * to avoid memory access issues. Both exit callbacks and
- * synchronization variables may be stored in packages.
- *
- * Note that TclFinalizeLoad unloads packages in the reverse
- * of the order they were loaded in (i.e. last to be loaded
- * is the first to be unloaded). This can be important for
- * correct unloading when dependencies exist.
- *
- * Once load has been finalized, we will have deleted any
- * temporary copies of shared libraries and can therefore
- * reset the filesystem to its original state.
- */
+ /*
+ * We defer unloading of packages until very late to avoid memory access
+ * issues. Both exit callbacks and synchronization variables may be stored
+ * in packages.
+ *
+ * Note that TclFinalizeLoad unloads packages in the reverse of the order
+ * they were loaded in (i.e. last to be loaded is the first to be
+ * unloaded). This can be important for correct unloading when
+ * dependencies exist.
+ *
+ * Once load has been finalized, we will have deleted any temporary copies
+ * of shared libraries and can therefore reset the filesystem to its
+ * original state.
+ */
- TclFinalizeLoad();
- TclResetFilesystem();
-
- /*
- * At this point, there should no longer be any ckalloc'ed memory.
- */
+ TclFinalizeLoad();
+ TclResetFilesystem();
- TclFinalizeMemorySubsystem();
- inFinalize = 0;
- }
+ /*
+ * At this point, there should no longer be any ckalloc'ed memory.
+ */
+
+ TclFinalizeMemorySubsystem();
+ inFinalize = 0;
+
+ alreadyFinalized:
TclFinalizeLock();
}
@@ -1042,8 +1195,8 @@ Tcl_Finalize()
*
* Tcl_FinalizeThread --
*
- * Runs the exit handlers to allow Tcl to clean up its state
- * about a particular thread.
+ * Runs the exit handlers to allow Tcl to clean up its state about a
+ * particular thread.
*
* Results:
* None.
@@ -1055,30 +1208,26 @@ Tcl_Finalize()
*/
void
-Tcl_FinalizeThread()
+Tcl_FinalizeThread(void)
{
ExitHandler *exitPtr;
ThreadSpecificData *tsdPtr;
+ /*
+ * We use TclThreadDataKeyGet here, rather than Tcl_GetThreadData, because
+ * we don't want to initialize the data block if it hasn't been
+ * initialized already.
+ */
+
tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
if (tsdPtr != NULL) {
tsdPtr->inExit = 1;
- /*
- * Clean up the library path now, before we invalidate thread-local
- * storage or calling thread exit handlers.
- */
-
- if (tsdPtr->tclLibraryPath != NULL) {
- Tcl_DecrRefCount(tsdPtr->tclLibraryPath);
- tsdPtr->tclLibraryPath = NULL;
- }
-
for (exitPtr = tsdPtr->firstExitPtr; exitPtr != NULL;
exitPtr = tsdPtr->firstExitPtr) {
/*
* Be careful to remove the handler from the list before invoking
- * its callback. This protects us against double-freeing if the
+ * its callback. This protects us against double-freeing if the
* callback should call Tcl_DeleteThreadExitHandler on itself.
*/
@@ -1089,14 +1238,15 @@ Tcl_FinalizeThread()
TclFinalizeIOSubsystem();
TclFinalizeNotifier();
TclFinalizeAsync();
+ TclFinalizeThreadObjects();
}
/*
* Blow away all thread local storage blocks.
*
- * Note that Tcl API allows creation of threads which do not use any
- * Tcl interp or other Tcl subsytems. Those threads might, however,
- * use thread local storage, so we must unconditionally finalize it.
+ * Note that Tcl API allows creation of threads which do not use any Tcl
+ * interp or other Tcl subsytems. Those threads might, however, use thread
+ * local storage, so we must unconditionally finalize it.
*
* Fix [Bug #571002]
*/
@@ -1121,7 +1271,7 @@ Tcl_FinalizeThread()
*/
int
-TclInExit()
+TclInExit(void)
{
return inFinalize;
}
@@ -1143,7 +1293,7 @@ TclInExit()
*/
int
-TclInThreadExit()
+TclInThreadExit(void)
{
ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
TclThreadDataKeyGet(&dataKey);
@@ -1159,8 +1309,8 @@ TclInThreadExit()
*
* Tcl_VwaitObjCmd --
*
- * This procedure is invoked to process the "vwait" Tcl command.
- * See the user documentation for details on what it does.
+ * This function is invoked to process the "vwait" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -1173,17 +1323,17 @@ TclInThreadExit()
/* ARGSUSED */
int
-Tcl_VwaitObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_VwaitObjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
int done, foundEvent;
char *nameString;
if (objc != 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "name");
+ Tcl_WrongNumArgs(interp, 1, objv, "name");
return TCL_ERROR;
}
nameString = Tcl_GetString(objv[1]);
@@ -1196,20 +1346,27 @@ Tcl_VwaitObjCmd(clientData, interp, objc, objv)
foundEvent = 1;
while (!done && foundEvent) {
foundEvent = Tcl_DoOneEvent(TCL_ALL_EVENTS);
+ if (Tcl_LimitExceeded(interp)) {
+ break;
+ }
}
Tcl_UntraceVar(interp, nameString,
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
VwaitVarProc, (ClientData) &done);
/*
- * Clear out the interpreter's result, since it may have been set
- * by event handlers.
+ * Clear out the interpreter's result, since it may have been set by event
+ * handlers.
*/
Tcl_ResetResult(interp);
if (!foundEvent) {
Tcl_AppendResult(interp, "can't wait for variable \"", nameString,
- "\": would wait forever", (char *) NULL);
+ "\": would wait forever", NULL);
+ return TCL_ERROR;
+ }
+ if (!done) {
+ Tcl_AppendResult(interp, "limit exceeded", NULL);
return TCL_ERROR;
}
return TCL_OK;
@@ -1217,17 +1374,17 @@ Tcl_VwaitObjCmd(clientData, interp, objc, objv)
/* ARGSUSED */
static char *
-VwaitVarProc(clientData, interp, name1, name2, flags)
- ClientData clientData; /* Pointer to integer to set to 1. */
- Tcl_Interp *interp; /* Interpreter containing variable. */
- CONST char *name1; /* Name of variable. */
- CONST char *name2; /* Second part of variable name. */
- int flags; /* Information about what happened. */
+VwaitVarProc(
+ ClientData clientData, /* Pointer to integer to set to 1. */
+ Tcl_Interp *interp, /* Interpreter containing variable. */
+ CONST char *name1, /* Name of variable. */
+ CONST char *name2, /* Second part of variable name. */
+ int flags) /* Information about what happened. */
{
int *donePtr = (int *) clientData;
*donePtr = 1;
- return (char *) NULL;
+ return NULL;
}
/*
@@ -1235,8 +1392,8 @@ VwaitVarProc(clientData, interp, name1, name2, flags)
*
* Tcl_UpdateObjCmd --
*
- * This procedure is invoked to process the "update" Tcl command.
- * See the user documentation for details on what it does.
+ * This function is invoked to process the "update" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -1249,15 +1406,15 @@ VwaitVarProc(clientData, interp, name1, name2, flags)
/* ARGSUSED */
int
-Tcl_UpdateObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_UpdateObjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
int optionIndex;
int flags = 0; /* Initialized to avoid compiler warning. */
- static CONST char *updateOptions[] = {"idletasks", (char *) NULL};
+ static CONST char *updateOptions[] = {"idletasks", NULL};
enum updateOptions {REGEXP_IDLETASKS};
if (objc == 1) {
@@ -1268,37 +1425,39 @@ Tcl_UpdateObjCmd(clientData, interp, objc, objv)
return TCL_ERROR;
}
switch ((enum updateOptions) optionIndex) {
- case REGEXP_IDLETASKS: {
- flags = TCL_WINDOW_EVENTS|TCL_IDLE_EVENTS|TCL_DONT_WAIT;
- break;
- }
- default: {
- panic("Tcl_UpdateObjCmd: bad option index to UpdateOptions");
- }
+ case REGEXP_IDLETASKS:
+ flags = TCL_WINDOW_EVENTS|TCL_IDLE_EVENTS|TCL_DONT_WAIT;
+ break;
+ default:
+ Tcl_Panic("Tcl_UpdateObjCmd: bad option index to UpdateOptions");
}
} else {
- Tcl_WrongNumArgs(interp, 1, objv, "?idletasks?");
+ Tcl_WrongNumArgs(interp, 1, objv, "?idletasks?");
return TCL_ERROR;
}
-
+
while (Tcl_DoOneEvent(flags) != 0) {
- /* Empty loop body */
+ if (Tcl_LimitExceeded(interp)) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "limit exceeded", NULL);
+ return TCL_ERROR;
+ }
}
/*
- * Must clear the interpreter's result because event handlers could
- * have executed commands.
+ * Must clear the interpreter's result because event handlers could have
+ * executed commands.
*/
Tcl_ResetResult(interp);
return TCL_OK;
}
-
+
#ifdef TCL_THREADS
/*
*-----------------------------------------------------------------------------
*
- * NewThreadProc --
+ * NewThreadProc --
*
* Bootstrap function of a new Tcl thread.
*
@@ -1312,34 +1471,36 @@ Tcl_UpdateObjCmd(clientData, interp, objc, objv)
*/
static Tcl_ThreadCreateType
-NewThreadProc(ClientData clientData)
+NewThreadProc(
+ ClientData clientData)
{
ThreadClientData *cdPtr;
ClientData threadClientData;
Tcl_ThreadCreateProc *threadProc;
- cdPtr = (ThreadClientData*)clientData;
+ cdPtr = (ThreadClientData *) clientData;
threadProc = cdPtr->proc;
threadClientData = cdPtr->clientData;
- ckfree((char*)clientData); /* Allocated in Tcl_CreateThread() */
+ ckfree((char *) clientData); /* Allocated in Tcl_CreateThread() */
(*threadProc)(threadClientData);
TCL_THREAD_CREATE_RETURN;
}
#endif
+
/*
*----------------------------------------------------------------------
*
* Tcl_CreateThread --
*
- * This procedure creates a new thread. This actually belongs
- * to the tclThread.c file but since we use some private
- * data structures local to this file, it is placed here.
+ * This function creates a new thread. This actually belongs to the
+ * tclThread.c file but since we use some private data structures local
+ * to this file, it is placed here.
*
* Results:
- * TCL_OK if the thread could be created. The thread ID is
- * returned in a parameter.
+ * TCL_OK if the thread could be created. The thread ID is returned in a
+ * parameter.
*
* Side effects:
* A new thread is created.
@@ -1348,24 +1509,32 @@ NewThreadProc(ClientData clientData)
*/
int
-Tcl_CreateThread(idPtr, proc, clientData, stackSize, flags)
- Tcl_ThreadId *idPtr; /* Return, the ID of the thread */
- Tcl_ThreadCreateProc proc; /* Main() function of the thread */
- ClientData clientData; /* The one argument to Main() */
- int stackSize; /* Size of stack for the new thread */
- int flags; /* Flags controlling behaviour of
- * the new thread */
+Tcl_CreateThread(
+ Tcl_ThreadId *idPtr, /* Return, the ID of the thread */
+ Tcl_ThreadCreateProc proc, /* Main() function of the thread */
+ ClientData clientData, /* The one argument to Main() */
+ int stackSize, /* Size of stack for the new thread */
+ int flags) /* Flags controlling behaviour of the new
+ * thread. */
{
#ifdef TCL_THREADS
ThreadClientData *cdPtr;
- cdPtr = (ThreadClientData*)ckalloc(sizeof(ThreadClientData));
+ cdPtr = (ThreadClientData *) ckalloc(sizeof(ThreadClientData));
cdPtr->proc = proc;
cdPtr->clientData = clientData;
- return TclpThreadCreate(idPtr, NewThreadProc, (ClientData)cdPtr,
- stackSize, flags);
+ return TclpThreadCreate(idPtr, NewThreadProc, (ClientData) cdPtr,
+ stackSize, flags);
#else
return TCL_ERROR;
#endif /* TCL_THREADS */
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclExecute.c b/generic/tclExecute.c
index 1c9d99d..dc87d70 100644
--- a/generic/tclExecute.c
+++ b/generic/tclExecute.c
@@ -1,63 +1,46 @@
-/*
+/*
* tclExecute.c --
*
- * This file contains procedures that execute byte-compiled Tcl
- * commands.
+ * This file contains procedures that execute byte-compiled Tcl commands.
*
* Copyright (c) 1996-1997 Sun Microsystems, Inc.
* Copyright (c) 1998-2000 by Scriptics Corporation.
- * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
+ * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
+ * Copyright (c) 2002-2005 by Miguel Sofer.
+ * Copyright (c) 2005-2007 by Donal K. Fellows.
+ * Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
#include "tclCompile.h"
+#include "tommath.h"
-#ifndef TCL_NO_MATH
-# include "tclMath.h"
-#endif
+#include <math.h>
+#include <float.h>
/*
- * The stuff below is a bit of a hack so that this file can be used
- * in environments that include no UNIX, i.e. no errno. Just define
- * errno here.
+ * Hack to determine whether we may expect IEEE floating point. The hack is
+ * formally incorrect in that non-IEEE platforms might have the same precision
+ * and range, but VAX, IBM, and Cray do not; are there any other floating
+ * point units that we might care about?
*/
-#ifndef TCL_GENERIC_ONLY
-# include "tclPort.h"
-#else /* TCL_GENERIC_ONLY */
-# ifndef NO_FLOAT_H
-# include <float.h>
-# else /* NO_FLOAT_H */
-# ifndef NO_VALUES_H
-# include <values.h>
-# endif /* !NO_VALUES_H */
-# endif /* !NO_FLOAT_H */
-# define NO_ERRNO_H
-#endif /* !TCL_GENERIC_ONLY */
-
-#ifdef NO_ERRNO_H
-int errno;
-# define EDOM 33
-# define ERANGE 34
+#if (FLT_RADIX == 2) && (DBL_MANT_DIG == 53) && (DBL_MAX_EXP == 1024)
+#define IEEE_FLOATING_POINT
#endif
/*
- * Need DBL_MAX for IS_INF() macro...
- */
-#ifndef DBL_MAX
-# ifdef MAXDOUBLE
-# define DBL_MAX MAXDOUBLE
-# else /* !MAXDOUBLE */
-/*
- * This value is from the Solaris headers, but doubles seem to be the
- * same size everywhere. Long doubles aren't, but we don't use those.
+ * A mask (should be 2**n-1) that is used to work out when the bytecode engine
+ * should call Tcl_AsyncReady() to see whether there is a signal that needs
+ * handling.
*/
-# define DBL_MAX 1.79769313486231570e+308
-# endif /* MAXDOUBLE */
-#endif /* !DBL_MAX */
+
+#ifndef ASYNC_CHECK_COUNT_MASK
+# define ASYNC_CHECK_COUNT_MASK 63
+#endif /* !ASYNC_CHECK_COUNT_MASK */
/*
* Boolean flag indicating whether the Tcl bytecode interpreter has been
@@ -85,22 +68,25 @@ int tclTraceExec = 0;
* Mapping from expression instruction opcodes to strings; used for error
* messages. Note that these entries must match the order and number of the
* expression opcodes (e.g., INST_LOR) in tclCompile.h.
+ *
+ * Does not include the string for INST_EXPON (and beyond), as that is
+ * disjoint for backward-compatability reasons.
*/
-static char *operatorStrings[] = {
+static const char *operatorStrings[] = {
"||", "&&", "|", "^", "&", "==", "!=", "<", ">", "<=", ">=", "<<", ">>",
"+", "-", "*", "/", "%", "+", "-", "~", "!",
"BUILTIN FUNCTION", "FUNCTION",
- "", "", "", "", "", "", "", "", "eq", "ne",
+ "", "", "", "", "", "", "", "", "eq", "ne"
};
/*
* Mapping from Tcl result codes to strings; used for error and debugging
- * messages.
+ * messages.
*/
#ifdef TCL_COMPILE_DEBUG
-static char *resultStrings[] = {
+static const char *resultStrings[] = {
"TCL_OK", "TCL_ERROR", "TCL_RETURN", "TCL_BREAK", "TCL_CONTINUE"
};
#endif
@@ -111,70 +97,142 @@ static char *resultStrings[] = {
#ifdef TCL_COMPILE_STATS
long tclObjsAlloced = 0;
-long tclObjsFreed = 0;
-#define TCL_MAX_SHARED_OBJ_STATS 5
+long tclObjsFreed = 0;
long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS] = { 0, 0, 0, 0, 0 };
#endif /* TCL_COMPILE_STATS */
/*
- * Macros for testing floating-point values for certain special cases. Test
- * for not-a-number by comparing a value against itself; test for infinity
- * by comparing against the largest floating-point value.
+ * Support pre-8.5 bytecodes unless specifically requested otherwise.
+ */
+
+#ifndef TCL_SUPPORT_84_BYTECODE
+#define TCL_SUPPORT_84_BYTECODE 1
+#endif
+
+#if TCL_SUPPORT_84_BYTECODE
+/*
+ * We need to know the tclBuiltinFuncTable to support translation of pre-8.5
+ * math functions to the namespace-based ::tcl::mathfunc::op in 8.5+.
*/
-#define IS_NAN(v) ((v) != (v))
-#define IS_INF(v) (((v) > DBL_MAX) || ((v) < -DBL_MAX))
+typedef struct {
+ char *name; /* Name of function. */
+ int numArgs; /* Number of arguments for function. */
+} BuiltinFunc;
/*
- * The new macro for ending an instruction; note that a
- * reasonable C-optimiser will resolve all branches
- * at compile time. (result) is always a constant; the macro
- * NEXT_INST_F handles constant (nCleanup), NEXT_INST_V is
- * resolved at runtime for variable (nCleanup).
+ * Table describing the built-in math functions. Entries in this table are
+ * indexed by the values of the INST_CALL_BUILTIN_FUNC instruction's
+ * operand byte.
+ */
+
+static BuiltinFunc tclBuiltinFuncTable[] = {
+ {"acos", 1},
+ {"asin", 1},
+ {"atan", 1},
+ {"atan2", 2},
+ {"ceil", 1},
+ {"cos", 1},
+ {"cosh", 1},
+ {"exp", 1},
+ {"floor", 1},
+ {"fmod", 2},
+ {"hypot", 2},
+ {"log", 1},
+ {"log10", 1},
+ {"pow", 2},
+ {"sin", 1},
+ {"sinh", 1},
+ {"sqrt", 1},
+ {"tan", 1},
+ {"tanh", 1},
+ {"abs", 1},
+ {"double", 1},
+ {"int", 1},
+ {"rand", 0},
+ {"round", 1},
+ {"srand", 1},
+ {"wide", 1},
+ {0},
+};
+
+#define LAST_BUILTIN_FUNC 25
+#endif
+
+/*
+ * These variable-access macros have to coincide with those in tclVar.c
+ */
+
+#define VarHashGetValue(hPtr) \
+ ((Var *) ((char *)hPtr - TclOffset(VarInHash, entry)))
+
+static inline Var *
+VarHashCreateVar(
+ TclVarHashTable *tablePtr,
+ Tcl_Obj *key,
+ int *newPtr)
+{
+ Tcl_HashEntry *hPtr = Tcl_CreateHashEntry((Tcl_HashTable *) tablePtr,
+ (char *) key, newPtr);
+
+ if (!hPtr) {
+ return NULL;
+ }
+ return VarHashGetValue(hPtr);
+}
+
+#define VarHashFindVar(tablePtr, key) \
+ VarHashCreateVar((tablePtr), (key), NULL)
+
+/*
+ * The new macro for ending an instruction; note that a reasonable C-optimiser
+ * will resolve all branches at compile time. (result) is always a constant;
+ * the macro NEXT_INST_F handles constant (nCleanup), NEXT_INST_V is resolved
+ * at runtime for variable (nCleanup).
*
* ARGUMENTS:
* pcAdjustment: how much to increment pc
* nCleanup: how many objects to remove from the stack
- * result: 0 indicates no object should be pushed on the
- * stack; otherwise, push objResultPtr. If (result < 0),
- * objResultPtr already has the correct reference count.
+ * resultHandling: 0 indicates no object should be pushed on the stack;
+ * otherwise, push objResultPtr. If (result < 0), objResultPtr already
+ * has the correct reference count.
*/
-#define NEXT_INST_F(pcAdjustment, nCleanup, result) \
- if (nCleanup == 0) {\
- if (result != 0) {\
- if ((result) > 0) {\
- PUSH_OBJECT(objResultPtr);\
- } else {\
- stackPtr[++stackTop] = objResultPtr;\
- }\
- } \
- pc += (pcAdjustment);\
- goto cleanup0;\
- } else if (result != 0) {\
- if ((result) > 0) {\
- Tcl_IncrRefCount(objResultPtr);\
- }\
- pc += (pcAdjustment);\
- switch (nCleanup) {\
- case 1: goto cleanup1_pushObjResultPtr;\
- case 2: goto cleanup2_pushObjResultPtr;\
- default: panic("ERROR: bad usage of macro NEXT_INST_F");\
- }\
- } else {\
- pc += (pcAdjustment);\
- switch (nCleanup) {\
- case 1: goto cleanup1;\
- case 2: goto cleanup2;\
- default: panic("ERROR: bad usage of macro NEXT_INST_F");\
- }\
- }
-
-#define NEXT_INST_V(pcAdjustment, nCleanup, result) \
+#define NEXT_INST_F(pcAdjustment, nCleanup, resultHandling) \
+ if (nCleanup == 0) {\
+ if (resultHandling != 0) {\
+ if ((resultHandling) > 0) {\
+ PUSH_OBJECT(objResultPtr);\
+ } else {\
+ *(++tosPtr) = objResultPtr;\
+ }\
+ } \
+ pc += (pcAdjustment);\
+ goto cleanup0;\
+ } else if (resultHandling != 0) {\
+ if ((resultHandling) > 0) {\
+ Tcl_IncrRefCount(objResultPtr);\
+ }\
+ pc += (pcAdjustment);\
+ switch (nCleanup) {\
+ case 1: goto cleanup1_pushObjResultPtr;\
+ case 2: goto cleanup2_pushObjResultPtr;\
+ default: Tcl_Panic("bad usage of macro NEXT_INST_F");\
+ }\
+ } else {\
+ pc += (pcAdjustment);\
+ switch (nCleanup) {\
+ case 1: goto cleanup1;\
+ case 2: goto cleanup2;\
+ default: Tcl_Panic("bad usage of macro NEXT_INST_F");\
+ }\
+ }
+
+#define NEXT_INST_V(pcAdjustment, nCleanup, resultHandling) \
pc += (pcAdjustment);\
cleanup = (nCleanup);\
- if (result) {\
- if ((result) > 0) {\
+ if (resultHandling) {\
+ if ((resultHandling) > 0) {\
Tcl_IncrRefCount(objResultPtr);\
}\
goto cleanupV_pushObjResultPtr;\
@@ -182,7 +240,6 @@ long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS] = { 0, 0, 0, 0, 0 };
goto cleanupV;\
}
-
/*
* Macros used to cache often-referenced Tcl evaluation stack information
* in local variables. Note that a DECACHE_STACK_INFO()-CACHE_STACK_INFO()
@@ -192,46 +249,52 @@ long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS] = { 0, 0, 0, 0, 0 };
*/
#define CACHE_STACK_INFO() \
- stackPtr = eePtr->stackPtr; \
- stackTop = eePtr->stackTop
+ checkInterp = 1
#define DECACHE_STACK_INFO() \
- eePtr->stackTop = stackTop
-
+ esPtr->tosPtr = tosPtr
/*
* Macros used to access items on the Tcl evaluation stack. PUSH_OBJECT
* increments the object's ref count since it makes the stack have another
* reference pointing to the object. However, POP_OBJECT does not decrement
- * the ref count. This is because the stack may hold the only reference to
- * the object, so the object would be destroyed if its ref count were
- * decremented before the caller had a chance to, e.g., store it in a
- * variable. It is the caller's responsibility to decrement the ref count
- * when it is finished with an object.
+ * the ref count. This is because the stack may hold the only reference to the
+ * object, so the object would be destroyed if its ref count were decremented
+ * before the caller had a chance to, e.g., store it in a variable. It is the
+ * caller's responsibility to decrement the ref count when it is finished with
+ * an object.
*
* WARNING! It is essential that objPtr only appear once in the PUSH_OBJECT
- * macro. The actual parameter might be an expression with side effects,
- * and this ensures that it will be executed only once.
+ * macro. The actual parameter might be an expression with side effects, and
+ * this ensures that it will be executed only once.
*/
-
+
#define PUSH_OBJECT(objPtr) \
- Tcl_IncrRefCount(stackPtr[++stackTop] = (objPtr))
-
-#define POP_OBJECT() \
- (stackPtr[stackTop--])
+ Tcl_IncrRefCount(*(++tosPtr) = (objPtr))
+
+#define POP_OBJECT() *(tosPtr--)
+
+#define OBJ_AT_TOS *tosPtr
+
+#define OBJ_UNDER_TOS *(tosPtr-1)
+
+#define OBJ_AT_DEPTH(n) *(tosPtr-(n))
+
+#define CURR_DEPTH (tosPtr - initTosPtr)
/*
* Macros used to trace instruction execution. The macros TRACE,
- * TRACE_WITH_OBJ, and O2S are only used inside TclExecuteByteCode.
- * O2S is only used in TRACE* calls to get a string from an object.
+ * TRACE_WITH_OBJ, and O2S are only used inside TclExecuteByteCode. O2S is
+ * only used in TRACE* calls to get a string from an object.
*/
#ifdef TCL_COMPILE_DEBUG
# define TRACE(a) \
if (traceInstructions) { \
- fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels, stackTop, \
- (unsigned int)(pc - codePtr->codeStart), \
- GetOpcodeName(pc)); \
+ fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels, \
+ (int) CURR_DEPTH, \
+ (unsigned)(pc - codePtr->codeStart), \
+ GetOpcodeName(pc)); \
printf a; \
}
# define TRACE_APPEND(a) \
@@ -240,18 +303,19 @@ long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS] = { 0, 0, 0, 0, 0 };
}
# define TRACE_WITH_OBJ(a, objPtr) \
if (traceInstructions) { \
- fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels, stackTop, \
- (unsigned int)(pc - codePtr->codeStart), \
- GetOpcodeName(pc)); \
+ fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels, \
+ (int) CURR_DEPTH, \
+ (unsigned)(pc - codePtr->codeStart), \
+ GetOpcodeName(pc)); \
printf a; \
- TclPrintObject(stdout, objPtr, 30); \
- fprintf(stdout, "\n"); \
+ TclPrintObject(stdout, objPtr, 30); \
+ fprintf(stdout, "\n"); \
}
# define O2S(objPtr) \
(objPtr ? TclGetString(objPtr) : "")
#else /* !TCL_COMPILE_DEBUG */
# define TRACE(a)
-# define TRACE_APPEND(a)
+# define TRACE_APPEND(a)
# define TRACE_WITH_OBJ(a, objPtr)
# define O2S(objPtr)
#endif /* TCL_COMPILE_DEBUG */
@@ -263,147 +327,308 @@ long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS] = { 0, 0, 0, 0, 0 };
#define TCL_DTRACE_INST_NEXT() \
if (TCL_DTRACE_INST_DONE_ENABLED()) {\
if (curInstName) {\
- TCL_DTRACE_INST_DONE(curInstName, stackTop - initStackTop,\
- stackPtr + stackTop);\
+ TCL_DTRACE_INST_DONE(curInstName, (int) CURR_DEPTH, tosPtr);\
}\
curInstName = tclInstructionTable[*pc].name;\
if (TCL_DTRACE_INST_START_ENABLED()) {\
- TCL_DTRACE_INST_START(curInstName, stackTop - initStackTop,\
- stackPtr + stackTop);\
+ TCL_DTRACE_INST_START(curInstName, (int) CURR_DEPTH, tosPtr);\
}\
} else if (TCL_DTRACE_INST_START_ENABLED()) {\
- TCL_DTRACE_INST_START(tclInstructionTable[*pc].name,\
- stackTop - initStackTop, stackPtr + stackTop);\
+ TCL_DTRACE_INST_START(tclInstructionTable[*pc].name, (int) CURR_DEPTH,\
+ tosPtr);\
}
#define TCL_DTRACE_INST_LAST() \
if (TCL_DTRACE_INST_DONE_ENABLED() && curInstName) {\
- TCL_DTRACE_INST_DONE(curInstName, stackTop - initStackTop,\
- stackPtr + stackTop);\
+ TCL_DTRACE_INST_DONE(curInstName, (int) CURR_DEPTH, tosPtr);\
}
/*
- * Macro to read a string containing either a wide or an int and
- * decide which it is while decoding it at the same time. This
- * enforces the policy that integer constants between LONG_MIN and
- * LONG_MAX (inclusive) are represented by normal longs, and integer
- * constants outside that range are represented by wide ints.
+ * Macro used in this file to save a function call for common uses of
+ * TclGetNumberFromObj(). The ANSI C "prototype" is:
*
- * GET_WIDE_OR_INT is the same as REQUIRE_WIDE_OR_INT except it never
- * generates an error message.
+ * MODULE_SCOPE int GetNumberFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ * ClientData *ptrPtr, int *tPtr);
*/
-#define REQUIRE_WIDE_OR_INT(resultVar, objPtr, longVar, wideVar) \
- (resultVar) = Tcl_GetWideIntFromObj(interp, (objPtr), &(wideVar)); \
- if ((resultVar) == TCL_OK && (wideVar) >= Tcl_LongAsWide(LONG_MIN) \
- && (wideVar) <= Tcl_LongAsWide(LONG_MAX)) { \
- (objPtr)->typePtr = &tclIntType; \
- (objPtr)->internalRep.longValue = (longVar) \
- = Tcl_WideAsLong(wideVar); \
- }
-#define GET_WIDE_OR_INT(resultVar, objPtr, longVar, wideVar) \
- (resultVar) = Tcl_GetWideIntFromObj((Tcl_Interp *) NULL, (objPtr), \
- &(wideVar)); \
- if ((resultVar) == TCL_OK && (wideVar) >= Tcl_LongAsWide(LONG_MIN) \
- && (wideVar) <= Tcl_LongAsWide(LONG_MAX)) { \
- (objPtr)->typePtr = &tclIntType; \
- (objPtr)->internalRep.longValue = (longVar) \
- = Tcl_WideAsLong(wideVar); \
- }
+
+#ifdef NO_WIDE_TYPE
+
+#define GetNumberFromObj(interp, objPtr, ptrPtr, tPtr) \
+ (((objPtr)->typePtr == &tclIntType) \
+ ? (*(tPtr) = TCL_NUMBER_LONG, \
+ *(ptrPtr) = (ClientData) \
+ (&((objPtr)->internalRep.longValue)), TCL_OK) : \
+ ((objPtr)->typePtr == &tclDoubleType) \
+ ? (((TclIsNaN((objPtr)->internalRep.doubleValue)) \
+ ? (*(tPtr) = TCL_NUMBER_NAN) \
+ : (*(tPtr) = TCL_NUMBER_DOUBLE)), \
+ *(ptrPtr) = (ClientData) \
+ (&((objPtr)->internalRep.doubleValue)), TCL_OK) : \
+ ((((objPtr)->typePtr == NULL) && ((objPtr)->bytes == NULL)) || \
+ (((objPtr)->bytes != NULL) && ((objPtr)->length == 0))) \
+ ? TCL_ERROR : \
+ TclGetNumberFromObj((interp), (objPtr), (ptrPtr), (tPtr)))
+
+#else
+
+#define GetNumberFromObj(interp, objPtr, ptrPtr, tPtr) \
+ (((objPtr)->typePtr == &tclIntType) \
+ ? (*(tPtr) = TCL_NUMBER_LONG, \
+ *(ptrPtr) = (ClientData) \
+ (&((objPtr)->internalRep.longValue)), TCL_OK) : \
+ ((objPtr)->typePtr == &tclWideIntType) \
+ ? (*(tPtr) = TCL_NUMBER_WIDE, \
+ *(ptrPtr) = (ClientData) \
+ (&((objPtr)->internalRep.wideValue)), TCL_OK) : \
+ ((objPtr)->typePtr == &tclDoubleType) \
+ ? (((TclIsNaN((objPtr)->internalRep.doubleValue)) \
+ ? (*(tPtr) = TCL_NUMBER_NAN) \
+ : (*(tPtr) = TCL_NUMBER_DOUBLE)), \
+ *(ptrPtr) = (ClientData) \
+ (&((objPtr)->internalRep.doubleValue)), TCL_OK) : \
+ ((((objPtr)->typePtr == NULL) && ((objPtr)->bytes == NULL)) || \
+ (((objPtr)->bytes != NULL) && ((objPtr)->length == 0))) \
+ ? TCL_ERROR : \
+ TclGetNumberFromObj((interp), (objPtr), (ptrPtr), (tPtr)))
+
+#endif
+
/*
- * Combined with REQUIRE_WIDE_OR_INT, this gets a long value from
- * an obj.
+ * Macro used in this file to save a function call for common uses of
+ * Tcl_GetBooleanFromObj(). The ANSI C "prototype" is:
+ *
+ * MODULE_SCOPE int TclGetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ * int *boolPtr);
*/
-#define FORCE_LONG(objPtr, longVar, wideVar) \
- if ((objPtr)->typePtr == &tclWideIntType) { \
- (longVar) = Tcl_WideAsLong(wideVar); \
- }
-#define IS_INTEGER_TYPE(typePtr) \
- ((typePtr) == &tclIntType || (typePtr) == &tclWideIntType)
-#define IS_NUMERIC_TYPE(typePtr) \
- (IS_INTEGER_TYPE(typePtr) || (typePtr) == &tclDoubleType)
-#define W0 Tcl_LongAsWide(0)
+#define TclGetBooleanFromObj(interp, objPtr, boolPtr) \
+ ((((objPtr)->typePtr == &tclIntType) \
+ || ((objPtr)->typePtr == &tclBooleanType)) \
+ ? (*(boolPtr) = ((objPtr)->internalRep.longValue!=0), TCL_OK) \
+ : Tcl_GetBooleanFromObj((interp), (objPtr), (boolPtr)))
+
/*
- * For tracing that uses wide values.
+ * Macro used in this file to save a function call for common uses of
+ * Tcl_GetWideIntFromObj(). The ANSI C "prototype" is:
+ *
+ * MODULE_SCOPE int TclGetWideIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ * Tcl_WideInt *wideIntPtr);
*/
-#define LLD "%" TCL_LL_MODIFIER "d"
-#ifndef TCL_WIDE_INT_IS_LONG
+#ifdef NO_WIDE_TYPE
+#define TclGetWideIntFromObj(interp, objPtr, wideIntPtr) \
+ (((objPtr)->typePtr == &tclIntType) \
+ ? (*(wideIntPtr) = (Tcl_WideInt) \
+ ((objPtr)->internalRep.longValue), TCL_OK) : \
+ Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr)))
+#else
+#define TclGetWideIntFromObj(interp, objPtr, wideIntPtr) \
+ (((objPtr)->typePtr == &tclWideIntType) \
+ ? (*(wideIntPtr) = (objPtr)->internalRep.wideValue, TCL_OK) : \
+ ((objPtr)->typePtr == &tclIntType) \
+ ? (*(wideIntPtr) = (Tcl_WideInt) \
+ ((objPtr)->internalRep.longValue), TCL_OK) : \
+ Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr)))
+#endif
+
/*
- * Extract a double value from a general numeric object.
+ * Macro used to make the check for type overflow more mnemonic. This works by
+ * comparing sign bits; the rest of the word is irrelevant. The ANSI C
+ * "prototype" (where inttype_t is any integer type) is:
+ *
+ * MODULE_SCOPE int Overflowing(inttype_t a, inttype_t b, inttype_t sum);
+ *
+ * Check first the condition most likely to fail in usual code (at least for
+ * usage in [incr]: do the first summand and the sum have != signs?
*/
-#define GET_DOUBLE_VALUE(doubleVar, objPtr, typePtr) \
- if ((typePtr) == &tclIntType) { \
- (doubleVar) = (double) (objPtr)->internalRep.longValue; \
- } else if ((typePtr) == &tclWideIntType) { \
- (doubleVar) = Tcl_WideAsDouble((objPtr)->internalRep.wideValue);\
- } else { \
- (doubleVar) = (objPtr)->internalRep.doubleValue; \
- }
-#else /* TCL_WIDE_INT_IS_LONG */
-#define GET_DOUBLE_VALUE(doubleVar, objPtr, typePtr) \
- if (((typePtr) == &tclIntType) || ((typePtr) == &tclWideIntType)) { \
- (doubleVar) = (double) (objPtr)->internalRep.longValue; \
- } else { \
- (doubleVar) = (objPtr)->internalRep.doubleValue; \
- }
-#endif /* TCL_WIDE_INT_IS_LONG */
+
+#define Overflowing(a,b,sum) ((((a)^(sum)) < 0) && (((a)^(b)) >= 0))
+
+/*
+ * Custom object type only used in this file; values of its type should never
+ * be seen by user scripts.
+ */
+
+static Tcl_ObjType dictIteratorType = {
+ "dictIterator",
+ NULL, NULL, NULL, NULL
+};
+
+/*
+ * Auxiliary tables used to compute powers of small integers
+ */
+
+#if (LONG_MAX == 0x7fffffff)
+
+/*
+ * Maximum base that, when raised to powers 2, 3, ... 8, fits in a 32-bit
+ * signed integer
+ */
+
+static const long MaxBase32[] = {46340, 1290, 215, 73, 35, 21, 14};
+static const size_t MaxBase32Size = sizeof(MaxBase32)/sizeof(long);
+
+/*
+ * Table giving 3, 4, ..., 11, raised to the powers 9, 10, ..., as far as they
+ * fit in a 32-bit signed integer. Exp32Index[i] gives the starting index of
+ * powers of i+3; Exp32Value[i] gives the corresponding powers.
+ */
+
+static const unsigned short Exp32Index[] = {
+ 0, 11, 18, 23, 26, 29, 31, 32, 33
+};
+static const size_t Exp32IndexSize = sizeof(Exp32Index)/sizeof(unsigned short);
+static const long Exp32Value[] = {
+ 19683, 59049, 177147, 531441, 1594323, 4782969, 14348907, 43046721,
+ 129140163, 387420489, 1162261467, 262144, 1048576, 4194304,
+ 16777216, 67108864, 268435456, 1073741824, 1953125, 9765625,
+ 48828125, 244140625, 1220703125, 10077696, 60466176, 362797056,
+ 40353607, 282475249, 1977326743, 134217728, 1073741824, 387420489,
+ 1000000000
+};
+static const size_t Exp32ValueSize = sizeof(Exp32Value)/sizeof(long);
+
+#endif /* LONG_MAX == 0x7fffffff -- 32 bit machine */
+
+#if (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG)
+
+/*
+ * Maximum base that, when raised to powers 2, 3, ..., 16, fits in a
+ * Tcl_WideInt.
+ */
+
+static const Tcl_WideInt MaxBase64[] = {
+ (Tcl_WideInt)46340*65536+62259, /* 3037000499 == isqrt(2**63-1) */
+ (Tcl_WideInt)2097151, (Tcl_WideInt)55108, (Tcl_WideInt)6208,
+ (Tcl_WideInt)1448, (Tcl_WideInt)511, (Tcl_WideInt)234, (Tcl_WideInt)127,
+ (Tcl_WideInt)78, (Tcl_WideInt)52, (Tcl_WideInt)38, (Tcl_WideInt)28,
+ (Tcl_WideInt)22, (Tcl_WideInt)18, (Tcl_WideInt)15
+};
+static const size_t MaxBase64Size = sizeof(MaxBase64)/sizeof(Tcl_WideInt);
+
+/*
+ *Table giving 3, 4, ..., 13 raised to powers greater than 16 when the
+ * results fit in a 64-bit signed integer.
+ */
+
+static const unsigned short Exp64Index[] = {
+ 0, 23, 38, 49, 57, 63, 67, 70, 72, 74, 75, 76
+};
+static const size_t Exp64IndexSize = sizeof(Exp64Index)/sizeof(unsigned short);
+static const Tcl_WideInt Exp64Value[] = {
+ (Tcl_WideInt)243*243*243*3*3,
+ (Tcl_WideInt)243*243*243*3*3*3,
+ (Tcl_WideInt)243*243*243*3*3*3*3,
+ (Tcl_WideInt)243*243*243*243,
+ (Tcl_WideInt)243*243*243*243*3,
+ (Tcl_WideInt)243*243*243*243*3*3,
+ (Tcl_WideInt)243*243*243*243*3*3*3,
+ (Tcl_WideInt)243*243*243*243*3*3*3*3,
+ (Tcl_WideInt)243*243*243*243*243,
+ (Tcl_WideInt)243*243*243*243*243*3,
+ (Tcl_WideInt)243*243*243*243*243*3*3,
+ (Tcl_WideInt)243*243*243*243*243*3*3*3,
+ (Tcl_WideInt)243*243*243*243*243*3*3*3*3,
+ (Tcl_WideInt)243*243*243*243*243*243,
+ (Tcl_WideInt)243*243*243*243*243*243*3,
+ (Tcl_WideInt)243*243*243*243*243*243*3*3,
+ (Tcl_WideInt)243*243*243*243*243*243*3*3*3,
+ (Tcl_WideInt)243*243*243*243*243*243*3*3*3*3,
+ (Tcl_WideInt)243*243*243*243*243*243*243,
+ (Tcl_WideInt)243*243*243*243*243*243*243*3,
+ (Tcl_WideInt)243*243*243*243*243*243*243*3*3,
+ (Tcl_WideInt)243*243*243*243*243*243*243*3*3*3,
+ (Tcl_WideInt)243*243*243*243*243*243*243*3*3*3*3,
+ (Tcl_WideInt)1024*1024*1024*4*4,
+ (Tcl_WideInt)1024*1024*1024*4*4*4,
+ (Tcl_WideInt)1024*1024*1024*4*4*4*4,
+ (Tcl_WideInt)1024*1024*1024*1024,
+ (Tcl_WideInt)1024*1024*1024*1024*4,
+ (Tcl_WideInt)1024*1024*1024*1024*4*4,
+ (Tcl_WideInt)1024*1024*1024*1024*4*4*4,
+ (Tcl_WideInt)1024*1024*1024*1024*4*4*4*4,
+ (Tcl_WideInt)1024*1024*1024*1024*1024,
+ (Tcl_WideInt)1024*1024*1024*1024*1024*4,
+ (Tcl_WideInt)1024*1024*1024*1024*1024*4*4,
+ (Tcl_WideInt)1024*1024*1024*1024*1024*4*4*4,
+ (Tcl_WideInt)1024*1024*1024*1024*1024*4*4*4*4,
+ (Tcl_WideInt)1024*1024*1024*1024*1024*1024,
+ (Tcl_WideInt)1024*1024*1024*1024*1024*1024*4,
+ (Tcl_WideInt)3125*3125*3125*5*5,
+ (Tcl_WideInt)3125*3125*3125*5*5*5,
+ (Tcl_WideInt)3125*3125*3125*5*5*5*5,
+ (Tcl_WideInt)3125*3125*3125*3125,
+ (Tcl_WideInt)3125*3125*3125*3125*5,
+ (Tcl_WideInt)3125*3125*3125*3125*5*5,
+ (Tcl_WideInt)3125*3125*3125*3125*5*5*5,
+ (Tcl_WideInt)3125*3125*3125*3125*5*5*5*5,
+ (Tcl_WideInt)3125*3125*3125*3125*3125,
+ (Tcl_WideInt)3125*3125*3125*3125*3125*5,
+ (Tcl_WideInt)3125*3125*3125*3125*3125*5*5,
+ (Tcl_WideInt)7776*7776*7776*6*6,
+ (Tcl_WideInt)7776*7776*7776*6*6*6,
+ (Tcl_WideInt)7776*7776*7776*6*6*6*6,
+ (Tcl_WideInt)7776*7776*7776*7776,
+ (Tcl_WideInt)7776*7776*7776*7776*6,
+ (Tcl_WideInt)7776*7776*7776*7776*6*6,
+ (Tcl_WideInt)7776*7776*7776*7776*6*6*6,
+ (Tcl_WideInt)7776*7776*7776*7776*6*6*6*6,
+ (Tcl_WideInt)16807*16807*16807*7*7,
+ (Tcl_WideInt)16807*16807*16807*7*7*7,
+ (Tcl_WideInt)16807*16807*16807*7*7*7*7,
+ (Tcl_WideInt)16807*16807*16807*16807,
+ (Tcl_WideInt)16807*16807*16807*16807*7,
+ (Tcl_WideInt)16807*16807*16807*16807*7*7,
+ (Tcl_WideInt)32768*32768*32768*8*8,
+ (Tcl_WideInt)32768*32768*32768*8*8*8,
+ (Tcl_WideInt)32768*32768*32768*8*8*8*8,
+ (Tcl_WideInt)32768*32768*32768*32768,
+ (Tcl_WideInt)59049*59049*59049*9*9,
+ (Tcl_WideInt)59049*59049*59049*9*9*9,
+ (Tcl_WideInt)59049*59049*59049*9*9*9*9,
+ (Tcl_WideInt)100000*100000*100000*10*10,
+ (Tcl_WideInt)100000*100000*100000*10*10*10,
+ (Tcl_WideInt)161051*161051*161051*11*11,
+ (Tcl_WideInt)161051*161051*161051*11*11*11,
+ (Tcl_WideInt)248832*248832*248832*12*12,
+ (Tcl_WideInt)371293*371293*371293*13*13
+};
+static const size_t Exp64ValueSize = sizeof(Exp64Value)/sizeof(Tcl_WideInt);
+
+#endif
/*
* Declarations for local procedures to this file:
*/
-static int TclExecuteByteCode _ANSI_ARGS_((Tcl_Interp *interp,
- ByteCode *codePtr));
-static void DupExprCodeInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
- Tcl_Obj *copyPtr));
-static int ExprAbsFunc _ANSI_ARGS_((Tcl_Interp *interp,
- ExecEnv *eePtr, ClientData clientData));
-static int ExprBinaryFunc _ANSI_ARGS_((Tcl_Interp *interp,
- ExecEnv *eePtr, ClientData clientData));
-static int ExprCallMathFunc _ANSI_ARGS_((Tcl_Interp *interp,
- ExecEnv *eePtr, int objc, Tcl_Obj **objv));
-static int ExprDoubleFunc _ANSI_ARGS_((Tcl_Interp *interp,
- ExecEnv *eePtr, ClientData clientData));
-static int ExprIntFunc _ANSI_ARGS_((Tcl_Interp *interp,
- ExecEnv *eePtr, ClientData clientData));
-static int ExprRandFunc _ANSI_ARGS_((Tcl_Interp *interp,
- ExecEnv *eePtr, ClientData clientData));
-static int ExprRoundFunc _ANSI_ARGS_((Tcl_Interp *interp,
- ExecEnv *eePtr, ClientData clientData));
-static int ExprSrandFunc _ANSI_ARGS_((Tcl_Interp *interp,
- ExecEnv *eePtr, ClientData clientData));
-static int ExprUnaryFunc _ANSI_ARGS_((Tcl_Interp *interp,
- ExecEnv *eePtr, ClientData clientData));
-static int ExprWideFunc _ANSI_ARGS_((Tcl_Interp *interp,
- ExecEnv *eePtr, ClientData clientData));
#ifdef TCL_COMPILE_STATS
-static int EvalStatsCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
+static int EvalStatsCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
#endif /* TCL_COMPILE_STATS */
-static void FreeExprCodeInternalRep _ANSI_ARGS_ ((Tcl_Obj *objPtr));
-#ifdef TCL_COMPILE_DEBUG
-static char * GetOpcodeName _ANSI_ARGS_((unsigned char *pc));
-#endif /* TCL_COMPILE_DEBUG */
-static ExceptionRange * GetExceptRangeForPc _ANSI_ARGS_((unsigned char *pc,
- int catchOnly, ByteCode* codePtr));
-static char * GetSrcInfoForPc _ANSI_ARGS_((unsigned char *pc,
- ByteCode* codePtr, int *lengthPtr));
-static void GrowEvaluationStack _ANSI_ARGS_((ExecEnv *eePtr));
-static void IllegalExprOperandType _ANSI_ARGS_((
- Tcl_Interp *interp, unsigned char *pc,
- Tcl_Obj *opndPtr));
-static void InitByteCodeExecution _ANSI_ARGS_((
- Tcl_Interp *interp));
#ifdef TCL_COMPILE_DEBUG
-static void PrintByteCodeInfo _ANSI_ARGS_((ByteCode *codePtr));
-static char * StringForResultCode _ANSI_ARGS_((int result));
-static void ValidatePcAndStackTop _ANSI_ARGS_((
- ByteCode *codePtr, unsigned char *pc,
- int stackTop, int stackLowerBound));
+static char * GetOpcodeName(unsigned char *pc);
+static void PrintByteCodeInfo(ByteCode *codePtr);
+static const char * StringForResultCode(int result);
+static void ValidatePcAndStackTop(ByteCode *codePtr,
+ unsigned char *pc, int stackTop,
+ int stackLowerBound, int checkStack);
#endif /* TCL_COMPILE_DEBUG */
-static int VerifyExprObjType _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
+static void DeleteExecStack(ExecStack *esPtr);
+static void DupExprCodeInternalRep(Tcl_Obj *srcPtr,
+ Tcl_Obj *copyPtr);
+static void FreeExprCodeInternalRep(Tcl_Obj *objPtr);
+static ExceptionRange * GetExceptRangeForPc(unsigned char *pc, int catchOnly,
+ ByteCode *codePtr);
+static const char * GetSrcInfoForPc(unsigned char *pc, ByteCode *codePtr,
+ int *lengthPtr);
+static Tcl_Obj ** GrowEvaluationStack(ExecEnv *eePtr, int growth,
+ int move);
+static void IllegalExprOperandType(Tcl_Interp *interp,
+ unsigned char *pc, Tcl_Obj *opndPtr);
+static void InitByteCodeExecution(Tcl_Interp *interp);
+/* Useful elsewhere, make available in tclInt.h or stubs? */
+static Tcl_Obj ** StackAllocWords(Tcl_Interp *interp, int numWords);
+static Tcl_Obj ** StackReallocWords(Tcl_Interp *interp, int numWords);
/*
* The structure below defines a bytecode Tcl object type to hold the
@@ -417,44 +642,6 @@ static Tcl_ObjType exprCodeType = {
NULL, /* updateStringProc */
NULL /* setFromAnyProc */
};
-
-/*
- * Table describing the built-in math functions. Entries in this table are
- * indexed by the values of the INST_CALL_BUILTIN_FUNC instruction's
- * operand byte.
- */
-
-BuiltinFunc tclBuiltinFuncTable[] = {
-#ifndef TCL_NO_MATH
- {"acos", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) acos},
- {"asin", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) asin},
- {"atan", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) atan},
- {"atan2", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) atan2},
- {"ceil", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) ceil},
- {"cos", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) cos},
- {"cosh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) cosh},
- {"exp", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) exp},
- {"floor", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) floor},
- {"fmod", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) fmod},
- {"hypot", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) hypot},
- {"log", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) log},
- {"log10", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) log10},
- {"pow", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) pow},
- {"sin", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sin},
- {"sinh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sinh},
- {"sqrt", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sqrt},
- {"tan", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) tan},
- {"tanh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) tanh},
-#endif
- {"abs", 1, {TCL_EITHER}, ExprAbsFunc, 0},
- {"double", 1, {TCL_EITHER}, ExprDoubleFunc, 0},
- {"int", 1, {TCL_EITHER}, ExprIntFunc, 0},
- {"rand", 0, {TCL_EITHER}, ExprRandFunc, 0}, /* NOTE: rand takes no args. */
- {"round", 1, {TCL_EITHER}, ExprRoundFunc, 0},
- {"srand", 1, {TCL_INT}, ExprSrandFunc, 0},
- {"wide", 1, {TCL_EITHER}, ExprWideFunc, 0},
- {0},
-};
/*
*----------------------------------------------------------------------
@@ -469,29 +656,28 @@ BuiltinFunc tclBuiltinFuncTable[] = {
*
* Side effects:
* This procedure initializes the array of instruction names. If
- * compiling with the TCL_COMPILE_STATS flag, it initializes the
- * array that counts the executions of each instruction and it
- * creates the "evalstats" command. It also establishes the link
- * between the Tcl "tcl_traceExec" and C "tclTraceExec" variables.
+ * compiling with the TCL_COMPILE_STATS flag, it initializes the array
+ * that counts the executions of each instruction and it creates the
+ * "evalstats" command. It also establishes the link between the Tcl
+ * "tcl_traceExec" and C "tclTraceExec" variables.
*
*----------------------------------------------------------------------
*/
static void
-InitByteCodeExecution(interp)
- Tcl_Interp *interp; /* Interpreter for which the Tcl variable
+InitByteCodeExecution(
+ Tcl_Interp *interp) /* Interpreter for which the Tcl variable
* "tcl_traceExec" is linked to control
* instruction tracing. */
{
#ifdef TCL_COMPILE_DEBUG
if (Tcl_LinkVar(interp, "tcl_traceExec", (char *) &tclTraceExec,
- TCL_LINK_INT) != TCL_OK) {
- panic("InitByteCodeExecution: can't create link for tcl_traceExec variable");
+ TCL_LINK_INT) != TCL_OK) {
+ Tcl_Panic("InitByteCodeExecution: can't create link for tcl_traceExec variable");
}
#endif
-#ifdef TCL_COMPILE_STATS
- Tcl_CreateObjCommand(interp, "evalstats", EvalStatsCmd,
- (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
+#ifdef TCL_COMPILE_STATS
+ Tcl_CreateObjCommand(interp, "evalstats", EvalStatsCmd, NULL, NULL);
#endif /* TCL_COMPILE_STATS */
}
@@ -501,18 +687,18 @@ InitByteCodeExecution(interp)
* TclCreateExecEnv --
*
* This procedure creates a new execution environment for Tcl bytecode
- * execution. An ExecEnv points to a Tcl evaluation stack. An ExecEnv
- * is typically created once for each Tcl interpreter (Interp
- * structure) and recursively passed to TclExecuteByteCode to execute
- * ByteCode sequences for nested commands.
+ * execution. An ExecEnv points to a Tcl evaluation stack. An ExecEnv is
+ * typically created once for each Tcl interpreter (Interp structure) and
+ * recursively passed to TclExecuteByteCode to execute ByteCode sequences
+ * for nested commands.
*
* Results:
* A newly allocated ExecEnv is returned. This points to an empty
* evaluation stack of the standard initial size.
*
* Side effects:
- * The bytecode interpreter is also initialized here, as this
- * procedure will be called before any call to TclExecuteByteCode.
+ * The bytecode interpreter is also initialized here, as this procedure
+ * will be called before any call to TclExecuteByteCode.
*
*----------------------------------------------------------------------
*/
@@ -520,33 +706,25 @@ InitByteCodeExecution(interp)
#define TCL_STACK_INITIAL_SIZE 2000
ExecEnv *
-TclCreateExecEnv(interp)
- Tcl_Interp *interp; /* Interpreter for which the execution
+TclCreateExecEnv(
+ Tcl_Interp *interp) /* Interpreter for which the execution
* environment is being created. */
{
ExecEnv *eePtr = (ExecEnv *) ckalloc(sizeof(ExecEnv));
- Tcl_Obj **stackPtr;
-
- stackPtr = (Tcl_Obj **)
- ckalloc((size_t) (TCL_STACK_INITIAL_SIZE * sizeof(Tcl_Obj *)));
-
- /*
- * Use the bottom pointer to keep a reference count; the
- * execution environment holds a reference.
- */
-
- stackPtr++;
- eePtr->stackPtr = stackPtr;
- stackPtr[-1] = (Tcl_Obj *) ((char *) 1);
+ ExecStack *esPtr = (ExecStack *) ckalloc(sizeof(ExecStack)
+ + (size_t) (TCL_STACK_INITIAL_SIZE-1) * sizeof(Tcl_Obj *));
- eePtr->stackTop = -1;
- eePtr->stackEnd = (TCL_STACK_INITIAL_SIZE - 2);
+ eePtr->execStackPtr = esPtr;
+ TclNewBooleanObj(eePtr->constants[0], 0);
+ Tcl_IncrRefCount(eePtr->constants[0]);
+ TclNewBooleanObj(eePtr->constants[1], 1);
+ Tcl_IncrRefCount(eePtr->constants[1]);
- eePtr->errorInfo = Tcl_NewStringObj("::errorInfo", -1);
- Tcl_IncrRefCount(eePtr->errorInfo);
-
- eePtr->errorCode = Tcl_NewStringObj("::errorCode", -1);
- Tcl_IncrRefCount(eePtr->errorCode);
+ esPtr->prevPtr = NULL;
+ esPtr->nextPtr = NULL;
+ esPtr->markerPtr = NULL;
+ esPtr->endPtr = &esPtr->stackWords[TCL_STACK_INITIAL_SIZE-1];
+ esPtr->tosPtr = &esPtr->stackWords[-1];
Tcl_MutexLock(&execMutex);
if (!execInitialized) {
@@ -571,23 +749,50 @@ TclCreateExecEnv(interp)
* None.
*
* Side effects:
- * Storage for an ExecEnv and its contained storage (e.g. the
- * evaluation stack) is freed.
+ * Storage for an ExecEnv and its contained storage (e.g. the evaluation
+ * stack) is freed.
*
*----------------------------------------------------------------------
*/
+static void
+DeleteExecStack(
+ ExecStack *esPtr)
+{
+ if (esPtr->markerPtr) {
+ Tcl_Panic("freeing an execStack which is still in use");
+ }
+
+ if (esPtr->prevPtr) {
+ esPtr->prevPtr->nextPtr = esPtr->nextPtr;
+ }
+ if (esPtr->nextPtr) {
+ esPtr->nextPtr->prevPtr = esPtr->prevPtr;
+ }
+ ckfree((char *) esPtr);
+}
+
void
-TclDeleteExecEnv(eePtr)
- ExecEnv *eePtr; /* Execution environment to free. */
+TclDeleteExecEnv(
+ ExecEnv *eePtr) /* Execution environment to free. */
{
- if (eePtr->stackPtr[-1] == (Tcl_Obj *) ((char *) 1)) {
- ckfree((char *) (eePtr->stackPtr-1));
- } else {
- panic("ERROR: freeing an execEnv whose stack is still in use.\n");
+ ExecStack *esPtr = eePtr->execStackPtr, *tmpPtr;
+
+ /*
+ * Delete all stacks in this exec env.
+ */
+
+ while (esPtr->nextPtr) {
+ esPtr = esPtr->nextPtr;
+ }
+ while (esPtr) {
+ tmpPtr = esPtr;
+ esPtr = tmpPtr->prevPtr;
+ DeleteExecStack(tmpPtr);
}
- TclDecrRefCount(eePtr->errorInfo);
- TclDecrRefCount(eePtr->errorCode);
+
+ TclDecrRefCount(eePtr->constants[0]);
+ TclDecrRefCount(eePtr->constants[1]);
ckfree((char *) eePtr);
}
@@ -596,21 +801,21 @@ TclDeleteExecEnv(eePtr)
*
* TclFinalizeExecution --
*
- * Finalizes the execution environment setup so that it can be
- * later reinitialized.
+ * Finalizes the execution environment setup so that it can be later
+ * reinitialized.
*
* Results:
* None.
*
* Side effects:
- * After this call, the next time TclCreateExecEnv will be called
- * it will call InitByteCodeExecution.
+ * After this call, the next time TclCreateExecEnv will be called it will
+ * call InitByteCodeExecution.
*
*----------------------------------------------------------------------
*/
void
-TclFinalizeExecution()
+TclFinalizeExecution(void)
{
Tcl_MutexLock(&execMutex);
execInitialized = 0;
@@ -619,69 +824,326 @@ TclFinalizeExecution()
}
/*
+ * Auxiliary code to insure that GrowEvaluationStack always returns correctly
+ * aligned memory.
+ *
+ * WALLOCALIGN represents the alignment reqs in words, just as TCL_ALLOCALIGN
+ * represents the reqs in bytes. This assumes that TCL_ALLOCALIGN is a
+ * multiple of the wordsize 'sizeof(Tcl_Obj *)'.
+ */
+
+#define WALLOCALIGN \
+ (TCL_ALLOCALIGN/sizeof(Tcl_Obj *))
+
+/*
+ * OFFSET computes how many words have to be skipped until the next aligned
+ * word. Note that we are only interested in the low order bits of ptr, so
+ * that any possible information loss in PTR2INT is of no consequence.
+ */
+
+static inline int
+OFFSET(
+ void *ptr)
+{
+ int mask = TCL_ALLOCALIGN-1;
+ int base = PTR2INT(ptr) & mask;
+ return (TCL_ALLOCALIGN - base)/sizeof(Tcl_Obj *);
+}
+
+/*
+ * Given a marker, compute where the following aligned memory starts.
+ */
+
+#define MEMSTART(markerPtr) \
+ ((markerPtr) + OFFSET(markerPtr))
+
+
+/*
*----------------------------------------------------------------------
*
* GrowEvaluationStack --
*
- * This procedure grows a Tcl evaluation stack stored in an ExecEnv.
+ * This procedure grows a Tcl evaluation stack stored in an ExecEnv,
+ * copying over the words since the last mark if so requested. A mark is
+ * set at the beginning of the new area when no copying is requested.
*
* Results:
- * None.
+ * Returns a pointer to the first usable word in the (possibly) grown
+ * stack.
*
* Side effects:
- * The size of the evaluation stack is doubled.
+ * The size of the evaluation stack may be grown, a marker is set
*
*----------------------------------------------------------------------
*/
-static void
-GrowEvaluationStack(eePtr)
- register ExecEnv *eePtr; /* Points to the ExecEnv with an evaluation
- * stack to enlarge. */
+static Tcl_Obj **
+GrowEvaluationStack(
+ ExecEnv *eePtr, /* Points to the ExecEnv with an evaluation
+ * stack to enlarge. */
+ int growth, /* How much larger than the current used
+ * size. */
+ int move) /* 1 if move words since last marker. */
{
+ ExecStack *esPtr = eePtr->execStackPtr, *oldPtr = NULL;
+ int newBytes, newElems, currElems;
+ int needed = growth - (esPtr->endPtr - esPtr->tosPtr);
+ Tcl_Obj **markerPtr = esPtr->markerPtr, **memStart;
+ int moveWords = 0;
+
+ if (move) {
+ if (!markerPtr) {
+ Tcl_Panic("STACK: Reallocating with no previous alloc");
+ }
+ if (needed <= 0) {
+ return MEMSTART(markerPtr);
+ }
+ } else {
+ Tcl_Obj **tmpMarkerPtr = esPtr->tosPtr + 1;
+ int offset = OFFSET(tmpMarkerPtr);
+
+ if (needed + offset < 0) {
+ /*
+ * Put a marker pointing to the previous marker in this stack, and
+ * store it in esPtr as the current marker. Return a pointer to
+ * the start of aligned memory.
+ */
+
+ esPtr->markerPtr = tmpMarkerPtr;
+ memStart = tmpMarkerPtr + offset;
+ esPtr->tosPtr = memStart - 1;
+ *esPtr->markerPtr = (Tcl_Obj *) markerPtr;
+ return memStart;
+ }
+ }
+
/*
- * The current Tcl stack elements are stored from eePtr->stackPtr[0]
- * to eePtr->stackPtr[eePtr->stackEnd] (inclusive).
+ * Reset move to hold the number of words to be moved to new stack (if
+ * any) and growth to hold the complete stack requirements: add one for
+ * the marker, (WALLOCALIGN-1) for the maximal possible offset.
*/
- int currElems = (eePtr->stackEnd + 1);
- int newElems = 2*currElems;
- int currBytes = currElems * sizeof(Tcl_Obj *);
- int newBytes = 2*currBytes;
- Tcl_Obj **newStackPtr = (Tcl_Obj **) ckalloc((unsigned) newBytes);
- Tcl_Obj **oldStackPtr = eePtr->stackPtr;
+ if (move) {
+ moveWords = esPtr->tosPtr - MEMSTART(markerPtr) + 1;
+ }
+ needed = growth + moveWords + WALLOCALIGN;
/*
- * We keep the stack reference count as a (char *), as that
- * works nicely as a portable pointer-sized counter.
+ * Check if there is enough room in the next stack (if there is one, it
+ * should be both empty and the last one!)
*/
- char *refCount = (char *) oldStackPtr[-1];
+ if (esPtr->nextPtr) {
+ oldPtr = esPtr;
+ esPtr = oldPtr->nextPtr;
+ currElems = esPtr->endPtr - &esPtr->stackWords[-1];
+ if (esPtr->markerPtr || (esPtr->tosPtr != &esPtr->stackWords[-1])) {
+ Tcl_Panic("STACK: Stack after current is in use");
+ }
+ if (esPtr->nextPtr) {
+ Tcl_Panic("STACK: Stack after current is not last");
+ }
+ if (needed <= currElems) {
+ goto newStackReady;
+ }
+ DeleteExecStack(esPtr);
+ esPtr = oldPtr;
+ } else {
+ currElems = esPtr->endPtr - &esPtr->stackWords[-1];
+ }
/*
- * Copy the existing stack items to the new stack space, free the old
- * storage if appropriate, and record the refCount of the new stack
- * held by the environment.
+ * We need to allocate a new stack! It needs to store 'growth' words,
+ * including the elements to be copied over and the new marker.
*/
-
- newStackPtr++;
- memcpy((VOID *) newStackPtr, (VOID *) oldStackPtr,
- (size_t) currBytes);
- if (refCount == (char *) 1) {
- ckfree((VOID *) (oldStackPtr-1));
- } else {
- /*
- * Remove the reference corresponding to the
- * environment pointer.
- */
-
- oldStackPtr[-1] = (Tcl_Obj *) (refCount-1);
+ newElems = 2*currElems;
+ while (needed > newElems) {
+ newElems *= 2;
}
+ newBytes = sizeof (ExecStack) + (newElems-1) * sizeof(Tcl_Obj *);
- eePtr->stackPtr = newStackPtr;
- eePtr->stackEnd = (newElems - 2); /* index of last usable item */
- newStackPtr[-1] = (Tcl_Obj *) ((char *) 1);
+ oldPtr = esPtr;
+ esPtr = (ExecStack *) ckalloc(newBytes);
+
+ oldPtr->nextPtr = esPtr;
+ esPtr->prevPtr = oldPtr;
+ esPtr->nextPtr = NULL;
+ esPtr->endPtr = &esPtr->stackWords[newElems-1];
+
+ newStackReady:
+ eePtr->execStackPtr = esPtr;
+
+ /*
+ * Store a NULL marker at the beginning of the stack, to indicate that
+ * this is the first marker in this stack and that rewinding to here
+ * should actually be a return to the previous stack.
+ */
+
+ esPtr->stackWords[0] = NULL;
+ esPtr->markerPtr = &esPtr->stackWords[0];
+ memStart = MEMSTART(esPtr->markerPtr);
+ esPtr->tosPtr = memStart - 1;
+
+ if (move) {
+ memcpy(memStart, MEMSTART(markerPtr), moveWords*sizeof(Tcl_Obj *));
+ esPtr->tosPtr += moveWords;
+ oldPtr->markerPtr = (Tcl_Obj **) *markerPtr;
+ oldPtr->tosPtr = markerPtr-1;
+ }
+
+ /*
+ * Free the old stack if it is now unused.
+ */
+
+ if (!oldPtr->markerPtr) {
+ DeleteExecStack(oldPtr);
+ }
+
+ return memStart;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TclStackAlloc, TclStackRealloc, TclStackFree --
+ *
+ * Allocate memory from the execution stack; it has to be returned later
+ * with a call to TclStackFree.
+ *
+ * Results:
+ * A pointer to the first byte allocated, or panics if the allocation did
+ * not succeed.
+ *
+ * Side effects:
+ * The execution stack may be grown.
+ *
+ *--------------------------------------------------------------
+ */
+
+static Tcl_Obj **
+StackAllocWords(
+ Tcl_Interp *interp,
+ int numWords)
+{
+ /*
+ * Note that GrowEvaluationStack sets a marker in the stack. This marker
+ * is read when rewinding, e.g., by TclStackFree.
+ */
+
+ Interp *iPtr = (Interp *) interp;
+ ExecEnv *eePtr = iPtr->execEnvPtr;
+ Tcl_Obj **resPtr = GrowEvaluationStack(eePtr, numWords, 0);
+
+ eePtr->execStackPtr->tosPtr += numWords;
+ return resPtr;
+}
+
+static Tcl_Obj **
+StackReallocWords(
+ Tcl_Interp *interp,
+ int numWords)
+{
+ Interp *iPtr = (Interp *) interp;
+ ExecEnv *eePtr = iPtr->execEnvPtr;
+ Tcl_Obj **resPtr = GrowEvaluationStack(eePtr, numWords, 1);
+
+ eePtr->execStackPtr->tosPtr += numWords;
+ return resPtr;
+}
+
+void
+TclStackFree(
+ Tcl_Interp *interp,
+ void *freePtr)
+{
+ Interp *iPtr = (Interp *) interp;
+ ExecEnv *eePtr;
+ ExecStack *esPtr;
+ Tcl_Obj **markerPtr;
+
+ if (iPtr == NULL || iPtr->execEnvPtr == NULL) {
+ Tcl_Free((char *) freePtr);
+ return;
+ }
+
+ /*
+ * Rewind the stack to the previous marker position. The current marker,
+ * as set in the last call to GrowEvaluationStack, contains a pointer to
+ * the previous marker.
+ */
+
+ eePtr = iPtr->execEnvPtr;
+ esPtr = eePtr->execStackPtr;
+ markerPtr = esPtr->markerPtr;
+
+ if (MEMSTART(markerPtr) != (Tcl_Obj **)freePtr) {
+ Tcl_Panic("TclStackFree: incorrect freePtr. Call out of sequence?");
+ }
+
+ esPtr->tosPtr = markerPtr-1;
+ esPtr->markerPtr = (Tcl_Obj **) *markerPtr;
+ if (*markerPtr) {
+ return;
+ }
+
+ /*
+ * Return to previous stack.
+ */
+
+ esPtr->tosPtr = &esPtr->stackWords[-1];
+ if (esPtr->prevPtr) {
+ eePtr->execStackPtr = esPtr->prevPtr;
+ }
+ if (esPtr->nextPtr) {
+ if (!esPtr->prevPtr) {
+ eePtr->execStackPtr = esPtr->nextPtr;
+ }
+ DeleteExecStack(esPtr);
+ }
+}
+
+void *
+TclStackAlloc(
+ Tcl_Interp *interp,
+ int numBytes)
+{
+ Interp *iPtr = (Interp *) interp;
+ int numWords = (numBytes + (sizeof(Tcl_Obj *) - 1))/sizeof(Tcl_Obj *);
+
+ if (iPtr == NULL || iPtr->execEnvPtr == NULL) {
+ return (void *) Tcl_Alloc(numBytes);
+ }
+
+ return (void *) StackAllocWords(interp, numWords);
+}
+
+void *
+TclStackRealloc(
+ Tcl_Interp *interp,
+ void *ptr,
+ int numBytes)
+{
+ Interp *iPtr = (Interp *) interp;
+ ExecEnv *eePtr;
+ ExecStack *esPtr;
+ Tcl_Obj **markerPtr;
+ int numWords;
+
+ if (iPtr == NULL || iPtr->execEnvPtr == NULL) {
+ return (void *) Tcl_Realloc((char *) ptr, numBytes);
+ }
+
+ eePtr = iPtr->execEnvPtr;
+ esPtr = eePtr->execStackPtr;
+ markerPtr = esPtr->markerPtr;
+
+ if (MEMSTART(markerPtr) != (Tcl_Obj **)ptr) {
+ Tcl_Panic("TclStackRealloc: incorrect ptr. Call out of sequence?");
+ }
+
+ numWords = (numBytes + (sizeof(Tcl_Obj *) - 1))/sizeof(Tcl_Obj *);
+ return (void *) StackReallocWords(interp, numWords);
}
/*
@@ -692,159 +1154,88 @@ GrowEvaluationStack(eePtr)
* Evaluate an expression in a Tcl_Obj.
*
* Results:
- * A standard Tcl object result. If the result is other than TCL_OK,
- * then the interpreter's result contains an error message. If the
- * result is TCL_OK, then a pointer to the expression's result value
- * object is stored in resultPtrPtr. In that case, the object's ref
- * count is incremented to reflect the reference returned to the
- * caller; the caller is then responsible for the resulting object
- * and must, for example, decrement the ref count when it is finished
- * with the object.
+ * A standard Tcl object result. If the result is other than TCL_OK, then
+ * the interpreter's result contains an error message. If the result is
+ * TCL_OK, then a pointer to the expression's result value object is
+ * stored in resultPtrPtr. In that case, the object's ref count is
+ * incremented to reflect the reference returned to the caller; the
+ * caller is then responsible for the resulting object and must, for
+ * example, decrement the ref count when it is finished with the object.
*
* Side effects:
- * Any side effects caused by subcommands in the expression, if any.
- * The interpreter result is not modified unless there is an error.
+ * Any side effects caused by subcommands in the expression, if any. The
+ * interpreter result is not modified unless there is an error.
*
*--------------------------------------------------------------
*/
int
-Tcl_ExprObj(interp, objPtr, resultPtrPtr)
- Tcl_Interp *interp; /* Context in which to evaluate the
+Tcl_ExprObj(
+ Tcl_Interp *interp, /* Context in which to evaluate the
* expression. */
- register Tcl_Obj *objPtr; /* Points to Tcl object containing
- * expression to evaluate. */
- Tcl_Obj **resultPtrPtr; /* Where the Tcl_Obj* that is the expression
+ register Tcl_Obj *objPtr, /* Points to Tcl object containing expression
+ * to evaluate. */
+ Tcl_Obj **resultPtrPtr) /* Where the Tcl_Obj* that is the expression
* result is stored if no errors occur. */
{
Interp *iPtr = (Interp *) interp;
- CompileEnv compEnv; /* Compilation environment structure
- * allocated in frame. */
- LiteralTable *localTablePtr = &(compEnv.localLitTable);
+ CompileEnv compEnv; /* Compilation environment structure allocated
+ * in frame. */
register ByteCode *codePtr = NULL;
- /* Tcl Internal type of bytecode.
- * Initialized to avoid compiler warning. */
- AuxData *auxDataPtr;
- LiteralEntry *entryPtr;
- Tcl_Obj *saveObjPtr;
- char *string;
- int length, i, result;
+ /* Tcl Internal type of bytecode. Initialized
+ * to avoid compiler warning. */
+ int result;
/*
- * First handle some common expressions specially.
+ * Execute the expression after first saving the interpreter's result.
*/
- string = Tcl_GetStringFromObj(objPtr, &length);
- if (length == 1) {
- if (*string == '0') {
- *resultPtrPtr = Tcl_NewLongObj(0);
- Tcl_IncrRefCount(*resultPtrPtr);
- return TCL_OK;
- } else if (*string == '1') {
- *resultPtrPtr = Tcl_NewLongObj(1);
- Tcl_IncrRefCount(*resultPtrPtr);
- return TCL_OK;
- }
- } else if ((length == 2) && (*string == '!')) {
- if (*(string+1) == '0') {
- *resultPtrPtr = Tcl_NewLongObj(1);
- Tcl_IncrRefCount(*resultPtrPtr);
- return TCL_OK;
- } else if (*(string+1) == '1') {
- *resultPtrPtr = Tcl_NewLongObj(0);
- Tcl_IncrRefCount(*resultPtrPtr);
- return TCL_OK;
- }
- }
-
- /*
- * Compile and execute the expression after saving the interp's result.
- */
-
- saveObjPtr = Tcl_GetObjResult(interp);
+ Tcl_Obj *saveObjPtr = Tcl_GetObjResult(interp);
Tcl_IncrRefCount(saveObjPtr);
/*
* Get the expression ByteCode from the object. If it exists, make sure it
* is valid in the current context.
*/
-
if (objPtr->typePtr == &exprCodeType) {
- Namespace *namespacePtr = iPtr->varFramePtr ?
- iPtr->varFramePtr->nsPtr : iPtr->globalNsPtr;
+ Namespace *namespacePtr = iPtr->varFramePtr->nsPtr;
codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
if (((Interp *) *codePtr->interpHandle != iPtr)
- || (codePtr->compileEpoch != iPtr->compileEpoch)
- || (codePtr->nsPtr != namespacePtr)
- || (codePtr->nsEpoch != namespacePtr->resolverEpoch)) {
+ || (codePtr->compileEpoch != iPtr->compileEpoch)
+ || (codePtr->nsPtr != namespacePtr)
+ || (codePtr->nsEpoch != namespacePtr->resolverEpoch)) {
objPtr->typePtr->freeIntRepProc(objPtr);
objPtr->typePtr = (Tcl_ObjType *) NULL;
}
}
if (objPtr->typePtr != &exprCodeType) {
-#ifndef TCL_TIP280
- TclInitCompileEnv(interp, &compEnv, string, length);
-#else
- /* TIP #280 : No invoker (yet) - Expression compilation */
- TclInitCompileEnv(interp, &compEnv, string, length, NULL, 0);
-#endif
- result = TclCompileExpr(interp, string, length, &compEnv);
-
/*
- * Free the compilation environment's literal table bucket array if
- * it was dynamically allocated.
+ * TIP #280: No invoker (yet) - Expression compilation.
*/
- if (localTablePtr->buckets != localTablePtr->staticBuckets) {
- ckfree((char *) localTablePtr->buckets);
- }
-
- if (result != TCL_OK) {
- /*
- * Compilation errors. Free storage allocated for compilation.
- */
+ int length;
+ const char *string = TclGetStringFromObj(objPtr, &length);
-#ifdef TCL_COMPILE_DEBUG
- TclVerifyLocalLiteralTable(&compEnv);
-#endif /*TCL_COMPILE_DEBUG*/
- entryPtr = compEnv.literalArrayPtr;
- for (i = 0; i < compEnv.literalArrayNext; i++) {
- TclReleaseLiteral(interp, entryPtr->objPtr);
- entryPtr++;
- }
-#ifdef TCL_COMPILE_DEBUG
- TclVerifyGlobalLiteralTable(iPtr);
-#endif /*TCL_COMPILE_DEBUG*/
-
- auxDataPtr = compEnv.auxDataArrayPtr;
- for (i = 0; i < compEnv.auxDataArrayNext; i++) {
- if (auxDataPtr->type->freeProc != NULL) {
- auxDataPtr->type->freeProc(auxDataPtr->clientData);
- }
- auxDataPtr++;
- }
- TclFreeCompileEnv(&compEnv);
- goto done;
- }
+ TclInitCompileEnv(interp, &compEnv, string, length, NULL, 0);
+ TclCompileExpr(interp, string, length, &compEnv, 0);
/*
- * Successful compilation. If the expression yielded no
- * instructions, push an zero object as the expression's result.
+ * Successful compilation. If the expression yielded no instructions,
+ * push an zero object as the expression's result.
*/
-
+
if (compEnv.codeNext == compEnv.codeStart) {
- TclEmitPush(TclRegisterLiteral(&compEnv, "0", 1, /*onHeap*/ 0),
- &compEnv);
+ TclEmitPush(TclRegisterNewLiteral(&compEnv, "0", 1),
+ &compEnv);
}
-
+
/*
* Add a "done" instruction as the last instruction and change the
- * object into a ByteCode object. Ownership of the literal objects
- * and aux data items is given to the ByteCode object.
+ * object into a ByteCode object. Ownership of the literal objects and
+ * aux data items is given to the ByteCode object.
*/
- compEnv.numSrcBytes = iPtr->termOffset;
TclEmitOpcode(INST_DONE, &compEnv);
TclInitByteCodeObj(objPtr, &compEnv);
objPtr->typePtr = &exprCodeType;
@@ -853,6 +1244,7 @@ Tcl_ExprObj(interp, objPtr, resultPtrPtr)
#ifdef TCL_COMPILE_DEBUG
if (tclTraceCompile == 2) {
TclPrintByteCodeObj(interp, objPtr);
+ fflush(stdout);
}
#endif /* TCL_COMPILE_DEBUG */
}
@@ -863,30 +1255,29 @@ Tcl_ExprObj(interp, objPtr, resultPtrPtr)
* Increment the code's ref count while it is being executed. If
* afterwards no references to it remain, free the code.
*/
-
+
codePtr->refCount++;
result = TclExecuteByteCode(interp, codePtr);
codePtr->refCount--;
if (codePtr->refCount <= 0) {
TclCleanupByteCode(codePtr);
}
-
+
/*
- * If the expression evaluated successfully, store a pointer to its
- * value object in resultPtrPtr then restore the old interpreter result.
- * We increment the object's ref count to reflect the reference that we
- * are returning to the caller. We also decrement the ref count of the
- * interpreter's result object after calling Tcl_SetResult since we
- * next store into that field directly.
+ * If the expression evaluated successfully, store a pointer to its value
+ * object in resultPtrPtr then restore the old interpreter result. We
+ * increment the object's ref count to reflect the reference that we are
+ * returning to the caller. We also decrement the ref count of the
+ * interpreter's result object after calling Tcl_SetResult since we next
+ * store into that field directly.
*/
-
+
if (result == TCL_OK) {
*resultPtrPtr = iPtr->objResultPtr;
Tcl_IncrRefCount(iPtr->objResultPtr);
-
+
Tcl_SetObjResult(interp, saveObjPtr);
}
-done:
TclDecrRefCount(saveObjPtr);
return result;
}
@@ -900,14 +1291,14 @@ done:
* bytecode. We do not copy the bytecode intrep. Instead, we
* return without setting copyPtr->typePtr, so the copy is a plain
* string copy of the expression value, and if it is to be used
- * as a compiled expression, it will just need a recompile.
+ * as a compiled expression, it will just need a recompile.
*
* This makes sense, because with Tcl's copy-on-write practices,
* the usual (only?) time Tcl_DuplicateObj() will be called is
* when the copy is about to be modified, which would invalidate
- * any copied bytecode anyway. The only reason it might make sense
- * to copy the bytecode is if we had some modifying routines that
- * operated directly on the intrep, like we do for lists and dicts.
+ * any copied bytecode anyway. The only reason it might make sense
+ * to copy the bytecode is if we had some modifying routines that
+ * operated directly on the intrep, like we do for lists and dicts.
*
* Results:
* None.
@@ -932,7 +1323,7 @@ DupExprCodeInternalRep(
* FreeExprCodeInternalRep --
*
* Part of the Tcl object type implementation for Tcl expression
- * bytecode. Frees the storage allocated to hold the internal rep,
+ * bytecode. Frees the storage allocated to hold the internal rep,
* unless ref counts indicate bytecode execution is still in progress.
*
* Results:
@@ -962,14 +1353,13 @@ FreeExprCodeInternalRep(
*
* TclCompEvalObj --
*
- * This procedure evaluates the script contained in a Tcl_Obj by
- * first compiling it and then passing it to TclExecuteByteCode.
+ * This procedure evaluates the script contained in a Tcl_Obj by first
+ * compiling it and then passing it to TclExecuteByteCode.
*
* Results:
- * The return value is one of the return codes defined in tcl.h
- * (such as TCL_OK), and interp->objResultPtr refers to a Tcl object
- * that either contains the result of executing the code or an
- * error message.
+ * The return value is one of the return codes defined in tcl.h (such as
+ * TCL_OK), and interp->objResultPtr refers to a Tcl object that either
+ * contains the result of executing the code or an error message.
*
* Side effects:
* Almost certainly, depending on the ByteCode's instructions.
@@ -978,174 +1368,327 @@ FreeExprCodeInternalRep(
*/
int
-#ifndef TCL_TIP280
-TclCompEvalObj(interp, objPtr)
-#else
-TclCompEvalObj(interp, objPtr, invoker, word)
-#endif
- Tcl_Interp *interp;
- Tcl_Obj *objPtr;
-#ifdef TCL_TIP280
- CONST CmdFrame* invoker; /* Frame of the command doing the eval */
- int word; /* Index of the word which is in objPtr */
-#endif
+TclCompEvalObj(
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr,
+ const CmdFrame *invoker,
+ int word)
{
register Interp *iPtr = (Interp *) interp;
- register ByteCode* codePtr; /* Tcl Internal type of bytecode. */
- int oldCount = iPtr->cmdCount; /* Used to tell whether any commands
- * at all were executed. */
- char *script;
- int numSrcBytes;
+ register ByteCode *codePtr; /* Tcl Internal type of bytecode. */
int result;
Namespace *namespacePtr;
-
/*
- * Check that the interpreter is ready to execute scripts
+ * Check that the interpreter is ready to execute scripts. Note that we
+ * manage the interp's runlevel here: it is a small white lie (maybe), but
+ * saves a ++/-- pair at each invocation. Amazingly enough, the impact on
+ * performance is noticeable.
*/
iPtr->numLevels++;
if (TclInterpReady(interp) == TCL_ERROR) {
- iPtr->numLevels--;
- return TCL_ERROR;
+ result = TCL_ERROR;
+ goto done;
}
- if (iPtr->varFramePtr != NULL) {
- namespacePtr = iPtr->varFramePtr->nsPtr;
- } else {
- namespacePtr = iPtr->globalNsPtr;
- }
+ namespacePtr = iPtr->varFramePtr->nsPtr;
- /*
- * If the object is not already of tclByteCodeType, compile it (and
- * reset the compilation flags in the interpreter; this should be
- * done after any compilation).
- * Otherwise, check that it is "fresh" enough.
+ /*
+ * If the object is not already of tclByteCodeType, compile it (and reset
+ * the compilation flags in the interpreter; this should be done after any
+ * compilation). Otherwise, check that it is "fresh" enough.
*/
- if (objPtr->typePtr != &tclByteCodeType) {
- recompileObj:
- iPtr->errorLine = 1;
-
-#ifdef TCL_TIP280
- /* TIP #280. Remember the invoker for a moment in the interpreter
- * structures so that the byte code compiler can pick it up when
- * initializing the compilation environment, i.e. the extended
- * location information.
- */
-
- iPtr->invokeCmdFramePtr = invoker;
- iPtr->invokeWord = word;
-#endif
- result = tclByteCodeType.setFromAnyProc(interp, objPtr);
-#ifdef TCL_TIP280
- iPtr->invokeCmdFramePtr = NULL;
-#endif
-
- if (result != TCL_OK) {
- iPtr->numLevels--;
- return result;
- }
- codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
- } else {
+ if (objPtr->typePtr == &tclByteCodeType) {
/*
- * Make sure the Bytecode hasn't been invalidated by, e.g., someone
- * redefining a command with a compile procedure (this might make the
- * compiled code wrong).
- * The object needs to be recompiled if it was compiled in/for a
- * different interpreter, or for a different namespace, or for the
- * same namespace but with different name resolution rules.
- * Precompiled objects, however, are immutable and therefore
- * they are not recompiled, even if the epoch has changed.
+ * Make sure the Bytecode hasn't been invalidated by, e.g., someone
+ * redefining a command with a compile procedure (this might make the
+ * compiled code wrong). The object needs to be recompiled if it was
+ * compiled in/for a different interpreter, or for a different
+ * namespace, or for the same namespace but with different name
+ * resolution rules. Precompiled objects, however, are immutable and
+ * therefore they are not recompiled, even if the epoch has changed.
*
* To be pedantically correct, we should also check that the
* originating procPtr is the same as the current context procPtr
- * (assuming one exists at all - none for global level). This
- * code is #def'ed out because [info body] was changed to never
- * return a bytecode type object, which should obviate us from
- * the extra checks here.
+ * (assuming one exists at all - none for global level). This code is
+ * #def'ed out because [info body] was changed to never return a
+ * bytecode type object, which should obviate us from the extra checks
+ * here.
*/
+
codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
if (((Interp *) *codePtr->interpHandle != iPtr)
- || (codePtr->compileEpoch != iPtr->compileEpoch)
-#ifdef CHECK_PROC_ORIGINATION /* [Bug: 3412 Pedantic] */
- || (codePtr->procPtr != NULL && !(iPtr->varFramePtr &&
- iPtr->varFramePtr->procPtr == codePtr->procPtr))
-#endif
- || (codePtr->nsPtr != namespacePtr)
- || (codePtr->nsEpoch != namespacePtr->resolverEpoch)) {
- if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
- if ((Interp *) *codePtr->interpHandle != iPtr) {
- panic("Tcl_EvalObj: compiled script jumped interps");
- }
- codePtr->compileEpoch = iPtr->compileEpoch;
- } else {
+ || (codePtr->compileEpoch != iPtr->compileEpoch)
+ || (codePtr->nsPtr != namespacePtr)
+ || (codePtr->nsEpoch != namespacePtr->resolverEpoch)) {
+ if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
+ if ((Interp *) *codePtr->interpHandle != iPtr) {
+ Tcl_Panic("Tcl_EvalObj: compiled script jumped interps");
+ }
+ codePtr->compileEpoch = iPtr->compileEpoch;
+ } else {
/*
- * This byteCode is invalid: free it and recompile
+ * This byteCode is invalid: free it and recompile.
*/
- tclByteCodeType.freeIntRepProc(objPtr);
+
+ objPtr->typePtr->freeIntRepProc(objPtr);
goto recompileObj;
}
}
- }
- /*
- * Execute the commands. If the code was compiled from an empty string,
- * don't bother executing the code.
- */
+ /*
+ * #280.
+ * Literal sharing fix. This part of the fix is not required by 8.4
+ * because it eval-directs any literals, so just saving the argument
+ * locations per command in bytecode is enough, embedded 'eval'
+ * commands, etc. get the correct information.
+ *
+ * It had be backported for 8.5 because we can force the separate
+ * compiling of a literal (in a proc body) by putting it into a control
+ * command with dynamic pieces, and then such literal may be shared
+ * and require their line-information to be reset, as for 8.6, as
+ * described below.
+ *
+ * In 8.6 all the embedded script are compiled, and the resulting
+ * bytecode stored in the literal. Now the shared literal has bytecode
+ * with location data for _one_ particular location this literal is
+ * found at. If we get executed from a different location the bytecode
+ * has to be recompiled to get the correct locations. Not doing this
+ * will execute the saved bytecode with data for a different location,
+ * causing 'info frame' to point to the wrong place in the sources.
+ *
+ * Future optimizations ...
+ * (1) Save the location data (ExtCmdLoc) keyed by start line. In that
+ * case we recompile once per location of the literal, but not
+ * continously, because the moment we have all locations we do not
+ * need to recompile any longer.
+ *
+ * (2) Alternative: Do not recompile, tell the execution engine the
+ * offset between saved starting line and actual one. Then modify
+ * the users to adjust the locations they have by this offset.
+ *
+ * (3) Alternative 2: Do not fully recompile, adjust just the location
+ * information.
+ */
+
+ if (invoker) {
+ Tcl_HashEntry *hePtr =
+ Tcl_FindHashEntry(iPtr->lineBCPtr, (char *) codePtr);
+
+ if (hePtr) {
+ ExtCmdLoc *eclPtr = Tcl_GetHashValue(hePtr);
+ int redo = 0;
+ CmdFrame *ctxPtr = TclStackAlloc(interp,sizeof(CmdFrame));
+
+ *ctxPtr = *invoker;
+
+ if (invoker->type == TCL_LOCATION_BC) {
+ /*
+ * Note: Type BC => ctx.data.eval.path is not used.
+ * ctx.data.tebc.codePtr used instead
+ */
+
+ TclGetSrcInfoForPc(ctxPtr);
+ if (ctxPtr->type == TCL_LOCATION_SOURCE) {
+ /*
+ * The reference made by 'TclGetSrcInfoForPc' is
+ * dead.
+ */
+
+ Tcl_DecrRefCount(ctxPtr->data.eval.path);
+ ctxPtr->data.eval.path = NULL;
+ }
+ }
+
+ if (word < ctxPtr->nline) {
+ /*
+ * Note: We do not care if the line[word] is -1. This
+ * is a difference and requires a recompile (location
+ * changed from absolute to relative, literal is used
+ * fixed and through variable)
+ *
+ * Example:
+ * test info-32.0 using literal of info-24.8
+ * (dict with ... vs set body ...).
+ */
+
+ redo = ((eclPtr->type == TCL_LOCATION_SOURCE)
+ && (eclPtr->start != ctxPtr->line[word]))
+ || ((eclPtr->type == TCL_LOCATION_BC)
+ && (ctxPtr->type == TCL_LOCATION_SOURCE));
+ }
+
+ TclStackFree(interp, ctxPtr);
+
+ if (redo) {
+ goto recompileObj;
+ }
+ }
+ }
- numSrcBytes = codePtr->numSrcBytes;
- if ((numSrcBytes > 0) || (codePtr->flags & TCL_BYTECODE_PRECOMPILED)) {
/*
* Increment the code's ref count while it is being executed. If
* afterwards no references to it remain, free the code.
*/
-
+
+ runCompiledObj:
codePtr->refCount++;
result = TclExecuteByteCode(interp, codePtr);
codePtr->refCount--;
if (codePtr->refCount <= 0) {
TclCleanupByteCode(codePtr);
}
- } else {
- result = TCL_OK;
+ goto done;
}
- iPtr->numLevels--;
+ recompileObj:
+ iPtr->errorLine = 1;
/*
- * If no commands at all were executed, check for asynchronous
- * handlers so that they at least get one change to execute.
- * This is needed to handle event loops written in Tcl with
- * empty bodies.
+ * TIP #280. Remember the invoker for a moment in the interpreter
+ * structures so that the byte code compiler can pick it up when
+ * initializing the compilation environment, i.e. the extended location
+ * information.
*/
- if ((oldCount == iPtr->cmdCount) && Tcl_AsyncReady()) {
- result = Tcl_AsyncInvoke(interp, result);
-
+ iPtr->invokeCmdFramePtr = invoker;
+ iPtr->invokeWord = word;
+ tclByteCodeType.setFromAnyProc(interp, objPtr);
+ iPtr->invokeCmdFramePtr = NULL;
+ codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
+ goto runCompiledObj;
+ done:
+ iPtr->numLevels--;
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclIncrObj --
+ *
+ * Increment an integeral value in a Tcl_Obj by an integeral value held
+ * in another Tcl_Obj. Caller is responsible for making sure we can
+ * update the first object.
+ *
+ * Results:
+ * TCL_ERROR if either object is non-integer, and TCL_OK otherwise. On
+ * error, an error message is left in the interpreter (if it is not NULL,
+ * of course).
+ *
+ * Side effects:
+ * valuePtr gets the new incrmented value.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclIncrObj(
+ Tcl_Interp *interp,
+ Tcl_Obj *valuePtr,
+ Tcl_Obj *incrPtr)
+{
+ ClientData ptr1, ptr2;
+ int type1, type2;
+ mp_int value, incr;
+
+ if (Tcl_IsShared(valuePtr)) {
+ Tcl_Panic("%s called with shared object", "TclIncrObj");
+ }
+
+ if (GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) {
/*
- * If an error occurred, record information about what was being
- * executed when the error occurred.
+ * Produce error message (reparse?!)
*/
-
- if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
- script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
- Tcl_LogCommandInfo(interp, script, script, numSrcBytes);
+
+ return TclGetIntFromObj(interp, valuePtr, &type1);
+ }
+ if (GetNumberFromObj(NULL, incrPtr, &ptr2, &type2) != TCL_OK) {
+ /*
+ * Produce error message (reparse?!)
+ */
+
+ TclGetIntFromObj(interp, incrPtr, &type1);
+ Tcl_AddErrorInfo(interp, "\n (reading increment)");
+ return TCL_ERROR;
+ }
+
+ if ((type1 == TCL_NUMBER_LONG) && (type2 == TCL_NUMBER_LONG)) {
+ long augend = *((const long *) ptr1);
+ long addend = *((const long *) ptr2);
+ long sum = augend + addend;
+
+ /*
+ * Overflow when (augend and sum have different sign) and (augend and
+ * addend have the same sign). This is encapsulated in the Overflowing
+ * macro.
+ */
+
+ if (!Overflowing(augend, addend, sum)) {
+ TclSetLongObj(valuePtr, sum);
+ return TCL_OK;
+ }
+#ifndef NO_WIDE_TYPE
+ {
+ Tcl_WideInt w1 = (Tcl_WideInt) augend;
+ Tcl_WideInt w2 = (Tcl_WideInt) addend;
+
+ /*
+ * We know the sum value is outside the long range, so we use the
+ * macro form that doesn't range test again.
+ */
+
+ TclSetWideIntObj(valuePtr, w1 + w2);
+ return TCL_OK;
}
+#endif
}
- /*
- * Set the interpreter's termOffset member to the offset of the
- * character just after the last one executed. We approximate the offset
- * of the last character executed by using the number of characters
- * compiled.
- */
+ if ((type1 == TCL_NUMBER_DOUBLE) || (type1 == TCL_NUMBER_NAN)) {
+ /*
+ * Produce error message (reparse?!)
+ */
+
+ return TclGetIntFromObj(interp, valuePtr, &type1);
+ }
+ if ((type2 == TCL_NUMBER_DOUBLE) || (type2 == TCL_NUMBER_NAN)) {
+ /*
+ * Produce error message (reparse?!)
+ */
- iPtr->termOffset = numSrcBytes;
- iPtr->flags &= ~ERR_ALREADY_LOGGED;
+ TclGetIntFromObj(interp, incrPtr, &type1);
+ Tcl_AddErrorInfo(interp, "\n (reading increment)");
+ return TCL_ERROR;
+ }
- return result;
+#ifndef NO_WIDE_TYPE
+ if ((type1 != TCL_NUMBER_BIG) && (type2 != TCL_NUMBER_BIG)) {
+ Tcl_WideInt w1, w2, sum;
+
+ TclGetWideIntFromObj(NULL, valuePtr, &w1);
+ TclGetWideIntFromObj(NULL, incrPtr, &w2);
+ sum = w1 + w2;
+
+ /*
+ * Check for overflow.
+ */
+
+ if (!Overflowing(w1, w2, sum)) {
+ Tcl_SetWideIntObj(valuePtr, sum);
+ return TCL_OK;
+ }
+ }
+#endif
+
+ Tcl_TakeBignumFromObj(interp, valuePtr, &value);
+ Tcl_GetBignumFromObj(interp, incrPtr, &incr);
+ mp_add(&value, &incr, &value);
+ mp_clear(&incr);
+ Tcl_SetBignumObj(valuePtr, &value);
+ return TCL_OK;
}
/*
@@ -1153,59 +1696,86 @@ TclCompEvalObj(interp, objPtr, invoker, word)
*
* TclExecuteByteCode --
*
- * This procedure executes the instructions of a ByteCode structure.
- * It returns when a "done" instruction is executed or an error occurs.
+ * This procedure executes the instructions of a ByteCode structure. It
+ * returns when a "done" instruction is executed or an error occurs.
*
* Results:
- * The return value is one of the return codes defined in tcl.h
- * (such as TCL_OK), and interp->objResultPtr refers to a Tcl object
- * that either contains the result of executing the code or an
- * error message.
+ * The return value is one of the return codes defined in tcl.h (such as
+ * TCL_OK), and interp->objResultPtr refers to a Tcl object that either
+ * contains the result of executing the code or an error message.
*
* Side effects:
* Almost certainly, depending on the ByteCode's instructions.
*
*----------------------------------------------------------------------
*/
-
-static int
-TclExecuteByteCode(interp, codePtr)
- Tcl_Interp *interp; /* Token for command interpreter. */
- ByteCode *codePtr; /* The bytecode sequence to interpret. */
+
+int
+TclExecuteByteCode(
+ Tcl_Interp *interp, /* Token for command interpreter. */
+ ByteCode *codePtr) /* The bytecode sequence to interpret. */
{
- Interp *iPtr = (Interp *) interp;
- ExecEnv *eePtr = iPtr->execEnvPtr;
- /* Points to the execution environment. */
- register Tcl_Obj **stackPtr = eePtr->stackPtr;
- /* Cached evaluation stack base pointer. */
- register int stackTop = eePtr->stackTop;
- /* Cached top index of evaluation stack. */
+ /*
+ * Compiler cast directive - not a real variable.
+ * Interp *iPtr = (Interp *) interp;
+ */
+#define iPtr ((Interp *) interp)
+
+ /*
+ * Check just the read-traced/write-traced bit of a variable.
+ */
+
+#define ReadTraced(varPtr) ((varPtr)->flags & VAR_TRACED_READ)
+#define WriteTraced(varPtr) ((varPtr)->flags & VAR_TRACED_WRITE)
+
+ /*
+ * Constants: variables that do not change during the execution, used
+ * sporadically.
+ */
+
+ ExecStack *esPtr;
+ Tcl_Obj **initTosPtr; /* Stack top at start of execution. */
+ ptrdiff_t *initCatchTop; /* Catch stack top at start of execution. */
+ Var *compiledLocals;
+ Namespace *namespacePtr;
+ CmdFrame *bcFramePtr; /* TIP #280: Structure for tracking lines. */
+ Tcl_Obj **constants = &iPtr->execEnvPtr->constants[0];
+
+ /*
+ * Globals: variables that store state, must remain valid at all times.
+ */
+
+ ptrdiff_t *catchTop;
+ register Tcl_Obj **tosPtr; /* Cached pointer to top of evaluation
+ * stack. */
register unsigned char *pc = codePtr->codeStart;
/* The current program counter. */
- int opnd; /* Current instruction's operand byte(s). */
- int pcAdjustment; /* Hold pc adjustment after instruction. */
- int initStackTop = stackTop;/* Stack top at start of execution. */
- ExceptionRange *rangePtr; /* Points to closest loop or catch exception
- * range enclosing the pc. Used by various
- * instructions and processCatch to
- * process break, continue, and errors. */
- int result = TCL_OK; /* Return code returned after execution. */
- int storeFlags;
- Tcl_Obj *valuePtr, *value2Ptr, *objPtr;
- char *bytes;
- int length;
- long i = 0; /* Init. avoids compiler warning. */
- Tcl_WideInt w;
+ int instructionCount = 0; /* Counter that is used to work out when to
+ * call Tcl_AsyncReady() */
+ Tcl_Obj *expandNestList = NULL;
+ int checkInterp = 0; /* Indicates when a check of interp readyness
+ * is necessary. Set by CACHE_STACK_INFO() */
+
+ /*
+ * Transfer variables - needed only between opcodes, but not while
+ * executing an instruction.
+ */
+
register int cleanup;
Tcl_Obj *objResultPtr;
- char *part1, *part2;
- Var *varPtr, *arrayPtr;
- CallFrame *varFramePtr = iPtr->varFramePtr;
-#ifdef TCL_TIP280
- /* TIP #280 : Structures for tracking lines */
- CmdFrame bcFrame;
-#endif
+ /*
+ * Result variable - needed only when going to checkForcatch or other
+ * error handlers; also used as local in some opcodes.
+ */
+
+ int result = TCL_OK; /* Return code returned after execution. */
+
+ /*
+ * Locals - variables that are used within opcodes or bounded sections of
+ * the file (jumps between opcodes within a family).
+ * NOTE: These are now defined locally where needed.
+ */
#ifdef TCL_COMPILE_DEBUG
int traceInstructions = (tclTraceExec == 3);
@@ -1214,307 +1784,604 @@ TclExecuteByteCode(interp, codePtr)
char *curInstName = NULL;
/*
- * This procedure uses a stack to hold information about catch commands.
- * This information is the current operand stack top when starting to
- * execute the code for each catch command. It starts out with stack-
- * allocated space but uses dynamically-allocated storage if needed.
+ * The execution uses a unified stack: first the catch stack, immediately
+ * above it a CmdFrame, then the execution stack.
+ *
+ * Make sure the catch stack is large enough to hold the maximum number of
+ * catch commands that could ever be executing at the same time (this will
+ * be no more than the exception range array's depth). Make sure the
+ * execution stack is large enough to execute this ByteCode.
*/
-#define STATIC_CATCH_STACK_SIZE 4
- int (catchStackStorage[STATIC_CATCH_STACK_SIZE]);
- int *catchStackPtr = catchStackStorage;
- int catchTop = -1;
-
-#ifdef TCL_TIP280
- /* TIP #280 : Initialize the frame. Do not push it yet. */
-
- bcFrame.type = ((codePtr->flags & TCL_BYTECODE_PRECOMPILED)
- ? TCL_LOCATION_PREBC
- : TCL_LOCATION_BC);
- bcFrame.level = (iPtr->cmdFramePtr == NULL ?
- 1 :
- iPtr->cmdFramePtr->level + 1);
- bcFrame.framePtr = iPtr->framePtr;
- bcFrame.nextPtr = iPtr->cmdFramePtr;
- bcFrame.nline = 0;
- bcFrame.line = NULL;
-
- bcFrame.data.tebc.codePtr = codePtr;
- bcFrame.data.tebc.pc = NULL;
- bcFrame.cmd.str.cmd = NULL;
- bcFrame.cmd.str.len = 0;
-#endif
+ catchTop = initCatchTop = (ptrdiff_t *) (
+ GrowEvaluationStack(iPtr->execEnvPtr,
+ (sizeof(CmdFrame) + sizeof(Tcl_Obj *) - 1)/sizeof(Tcl_Obj *) +
+ codePtr->maxExceptDepth + codePtr->maxStackDepth, 0) - 1);
+ bcFramePtr = (CmdFrame *) (initCatchTop + codePtr->maxExceptDepth + 1);
+ tosPtr = initTosPtr = ((Tcl_Obj **) (bcFramePtr + 1)) - 1;
+ esPtr = iPtr->execEnvPtr->execStackPtr;
+
+ /*
+ * TIP #280: Initialize the frame. Do not push it yet.
+ */
+
+ bcFramePtr->type = ((codePtr->flags & TCL_BYTECODE_PRECOMPILED)
+ ? TCL_LOCATION_PREBC : TCL_LOCATION_BC);
+ bcFramePtr->level = (iPtr->cmdFramePtr ? iPtr->cmdFramePtr->level+1 : 1);
+ bcFramePtr->framePtr = iPtr->framePtr;
+ bcFramePtr->nextPtr = iPtr->cmdFramePtr;
+ bcFramePtr->nline = 0;
+ bcFramePtr->line = NULL;
+
+ bcFramePtr->data.tebc.codePtr = codePtr;
+ bcFramePtr->data.tebc.pc = NULL;
+ bcFramePtr->cmd.str.cmd = NULL;
+ bcFramePtr->cmd.str.len = 0;
#ifdef TCL_COMPILE_DEBUG
if (tclTraceExec >= 2) {
PrintByteCodeInfo(codePtr);
- fprintf(stdout, " Starting stack top=%d\n", eePtr->stackTop);
+ fprintf(stdout, " Starting stack top=%d\n", (int) CURR_DEPTH);
fflush(stdout);
}
- opnd = 0; /* Init. avoids compiler warning. */
#endif
-
+
#ifdef TCL_COMPILE_STATS
iPtr->stats.numExecutions++;
#endif
- /*
- * Make sure the catch stack is large enough to hold the maximum number
- * of catch commands that could ever be executing at the same time. This
- * will be no more than the exception range array's depth.
- */
-
- if (codePtr->maxExceptDepth > STATIC_CATCH_STACK_SIZE) {
- catchStackPtr = (int *)
- ckalloc(codePtr->maxExceptDepth * sizeof(int));
- }
-
- /*
- * Make sure the stack has enough room to execute this ByteCode.
- */
-
- while ((stackTop + codePtr->maxStackDepth) > eePtr->stackEnd) {
- GrowEvaluationStack(eePtr);
- stackPtr = eePtr->stackPtr;
- }
+ namespacePtr = iPtr->varFramePtr->nsPtr;
+ compiledLocals = iPtr->varFramePtr->compiledLocals;
/*
- * Loop executing instructions until a "done" instruction, a
- * TCL_RETURN, or some error.
+ * Loop executing instructions until a "done" instruction, a TCL_RETURN,
+ * or some error.
*/
goto cleanup0;
-
/*
- * Targets for standard instruction endings; unrolled
- * for speed in the most frequent cases (instructions that
- * consume up to two stack elements).
+ * Targets for standard instruction endings; unrolled for speed in the
+ * most frequent cases (instructions that consume up to two stack
+ * elements).
*
- * This used to be a "for(;;)" loop, with each instruction doing
- * its own cleanup.
+ * This used to be a "for(;;)" loop, with each instruction doing its own
+ * cleanup.
*/
-
+
+ {
+ Tcl_Obj *valuePtr;
+
cleanupV_pushObjResultPtr:
- switch (cleanup) {
- case 0:
- stackPtr[++stackTop] = (objResultPtr);
+ switch (cleanup) {
+ case 0:
+ *(++tosPtr) = (objResultPtr);
goto cleanup0;
- default:
+ default:
cleanup -= 2;
while (cleanup--) {
valuePtr = POP_OBJECT();
TclDecrRefCount(valuePtr);
}
- case 2:
- cleanup2_pushObjResultPtr:
+ case 2:
+ cleanup2_pushObjResultPtr:
valuePtr = POP_OBJECT();
TclDecrRefCount(valuePtr);
- case 1:
- cleanup1_pushObjResultPtr:
- valuePtr = stackPtr[stackTop];
+ case 1:
+ cleanup1_pushObjResultPtr:
+ valuePtr = OBJ_AT_TOS;
TclDecrRefCount(valuePtr);
- }
- stackPtr[stackTop] = objResultPtr;
- goto cleanup0;
-
+ }
+ OBJ_AT_TOS = objResultPtr;
+ goto cleanup0;
+
cleanupV:
- switch (cleanup) {
- default:
+ switch (cleanup) {
+ default:
cleanup -= 2;
while (cleanup--) {
valuePtr = POP_OBJECT();
TclDecrRefCount(valuePtr);
}
- case 2:
- cleanup2:
+ case 2:
+ cleanup2:
valuePtr = POP_OBJECT();
TclDecrRefCount(valuePtr);
- case 1:
- cleanup1:
+ case 1:
+ cleanup1:
valuePtr = POP_OBJECT();
TclDecrRefCount(valuePtr);
- case 0:
+ case 0:
/*
- * We really want to do nothing now, but this is needed
- * for some compilers (SunPro CC)
+ * We really want to do nothing now, but this is needed for some
+ * compilers (SunPro CC).
*/
+
break;
+ }
}
+ cleanup0:
- cleanup0:
-
#ifdef TCL_COMPILE_DEBUG
- ValidatePcAndStackTop(codePtr, pc, stackTop, initStackTop);
+ /*
+ * Skip the stack depth check if an expansion is in progress.
+ */
+
+ ValidatePcAndStackTop(codePtr, pc, CURR_DEPTH, 0,
+ /*checkStack*/ expandNestList == NULL);
if (traceInstructions) {
- fprintf(stdout, "%2d: %2d ", iPtr->numLevels, stackTop);
+ fprintf(stdout, "%2d: %2d ", iPtr->numLevels, (int) CURR_DEPTH);
TclPrintInstruction(codePtr, pc);
fflush(stdout);
}
#endif /* TCL_COMPILE_DEBUG */
-
-#ifdef TCL_COMPILE_STATS
+
+#ifdef TCL_COMPILE_STATS
iPtr->stats.instructionCount[*pc]++;
#endif
+ /*
+ * Check for asynchronous handlers [Bug 746722]; we do the check every
+ * ASYNC_CHECK_COUNT_MASK instruction, of the form (2**n-1).
+ */
+
+ if ((instructionCount++ & ASYNC_CHECK_COUNT_MASK) == 0) {
+ /*
+ * Check for asynchronous handlers [Bug 746722]; we do the check every
+ * ASYNC_CHECK_COUNT_MASK instruction, of the form (2**n-<1).
+ */
+
+ if (TclAsyncReady(iPtr)) {
+ int localResult;
+
+ DECACHE_STACK_INFO();
+ localResult = Tcl_AsyncInvoke(interp, result);
+ CACHE_STACK_INFO();
+ if (localResult == TCL_ERROR) {
+ result = localResult;
+ goto checkForCatch;
+ }
+ }
+ if (TclLimitReady(iPtr->limit)) {
+ int localResult;
+
+ DECACHE_STACK_INFO();
+ localResult = Tcl_LimitCheck(interp);
+ CACHE_STACK_INFO();
+ if (localResult == TCL_ERROR) {
+ result = localResult;
+ goto checkForCatch;
+ }
+ }
+ }
+
TCL_DTRACE_INST_NEXT();
+ /*
+ * These two instructions account for 26% of all instructions (according
+ * to measurements on tclbench by Ben Vitale
+ * [http://www.cs.toronto.edu/syslab/pubs/tcl2005-vitale-zaleski.pdf]
+ * Resolving them before the switch reduces the cost of branch
+ * mispredictions, seems to improve runtime by 5% to 15%, and (amazingly!)
+ * reduces total obj size.
+ */
+
+ if (*pc == INST_LOAD_SCALAR1) {
+ goto instLoadScalar1;
+ } else if (*pc == INST_PUSH1) {
+ goto instPush1Peephole;
+ }
+
switch (*pc) {
+ case INST_SYNTAX:
+ case INST_RETURN_IMM: {
+ int code = TclGetInt4AtPtr(pc+1);
+ int level = TclGetUInt4AtPtr(pc+5);
+
+ /*
+ * OBJ_AT_TOS is returnOpts, OBJ_UNDER_TOS is resultObjPtr.
+ */
+
+ TRACE(("%u %u => ", code, level));
+ result = TclProcessReturn(interp, code, level, OBJ_AT_TOS);
+ if (result == TCL_OK) {
+ TRACE_APPEND(("continuing to next instruction (result=\"%.30s\")",
+ O2S(objResultPtr)));
+ NEXT_INST_F(9, 1, 0);
+ } else {
+ Tcl_SetObjResult(interp, OBJ_UNDER_TOS);
+ if (*pc == INST_SYNTAX) {
+ iPtr->flags &= ~ERR_ALREADY_LOGGED;
+ }
+ cleanup = 2;
+ goto processExceptionReturn;
+ }
+ }
+
+ case INST_RETURN_STK:
+ TRACE(("=> "));
+ objResultPtr = POP_OBJECT();
+ result = Tcl_SetReturnOptions(interp, OBJ_AT_TOS);
+ Tcl_DecrRefCount(OBJ_AT_TOS);
+ OBJ_AT_TOS = objResultPtr;
+ if (result == TCL_OK) {
+ TRACE_APPEND(("continuing to next instruction (result=\"%.30s\")",
+ O2S(objResultPtr)));
+ NEXT_INST_F(1, 0, 0);
+ } else {
+ Tcl_SetObjResult(interp, objResultPtr);
+ cleanup = 1;
+ goto processExceptionReturn;
+ }
+
case INST_DONE:
- if (stackTop <= initStackTop) {
- stackTop--;
+ if (tosPtr > initTosPtr) {
+ /*
+ * Set the interpreter's object result to point to the topmost
+ * object from the stack, and check for a possible [catch]. The
+ * stackTop's level and refCount will be handled by "processCatch"
+ * or "abnormalReturn".
+ */
+
+ Tcl_SetObjResult(interp, OBJ_AT_TOS);
+#ifdef TCL_COMPILE_DEBUG
+ TRACE_WITH_OBJ(("=> return code=%d, result=", result),
+ iPtr->objResultPtr);
+ if (traceInstructions) {
+ fprintf(stdout, "\n");
+ }
+#endif
+ goto checkForCatch;
+ } else {
+ (void) POP_OBJECT();
goto abnormalReturn;
}
-
+
+ case INST_PUSH1:
+ instPush1Peephole:
+ PUSH_OBJECT(codePtr->objArrayPtr[TclGetUInt1AtPtr(pc+1)]);
+ TRACE_WITH_OBJ(("%u => ", TclGetInt1AtPtr(pc+1)), OBJ_AT_TOS);
+ pc += 2;
+#if !TCL_COMPILE_DEBUG
/*
- * Set the interpreter's object result to point to the
- * topmost object from the stack, and check for a possible
- * [catch]. The stackTop's level and refCount will be handled
- * by "processCatch" or "abnormalReturn".
+ * Runtime peephole optimisation: check if we are pushing again.
*/
- valuePtr = stackPtr[stackTop];
- Tcl_SetObjResult(interp, valuePtr);
-#ifdef TCL_COMPILE_DEBUG
- TRACE_WITH_OBJ(("=> return code=%d, result=", result),
- iPtr->objResultPtr);
- if (traceInstructions) {
- fprintf(stdout, "\n");
+ if (*pc == INST_PUSH1) {
+ TCL_DTRACE_INST_NEXT();
+ goto instPush1Peephole;
}
#endif
- goto checkForCatch;
-
- case INST_PUSH1:
- objResultPtr = codePtr->objArrayPtr[TclGetUInt1AtPtr(pc+1)];
- TRACE_WITH_OBJ(("%u => ", TclGetInt1AtPtr(pc+1)), objResultPtr);
- NEXT_INST_F(2, 0, 1);
+ NEXT_INST_F(0, 0, 0);
case INST_PUSH4:
objResultPtr = codePtr->objArrayPtr[TclGetUInt4AtPtr(pc+1)];
TRACE_WITH_OBJ(("%u => ", TclGetUInt4AtPtr(pc+1)), objResultPtr);
NEXT_INST_F(5, 0, 1);
- case INST_POP:
- TRACE_WITH_OBJ(("=> discarding "), stackPtr[stackTop]);
+ case INST_POP: {
+ Tcl_Obj *valuePtr;
+
+ TRACE_WITH_OBJ(("=> discarding "), OBJ_AT_TOS);
valuePtr = POP_OBJECT();
TclDecrRefCount(valuePtr);
- NEXT_INST_F(1, 0, 0);
-
+
+ /*
+ * Runtime peephole optimisation: an INST_POP is scheduled at the end
+ * of most commands. If the next instruction is an INST_START_CMD,
+ * fall through to it.
+ */
+
+ pc++;
+#if !TCL_COMPILE_DEBUG
+ if (*pc == INST_START_CMD) {
+ TCL_DTRACE_INST_NEXT();
+ goto instStartCmdPeephole;
+ }
+#endif
+ NEXT_INST_F(0, 0, 0);
+ }
+
+ case INST_START_CMD:
+#if !TCL_COMPILE_DEBUG
+ instStartCmdPeephole:
+#endif
+ /*
+ * Remark that if the interpreter is marked for deletion its
+ * compileEpoch is modified, so that the epoch check also verifies
+ * that the interp is not deleted. If no outside call has been made
+ * since the last check, it is safe to omit the check.
+ */
+
+ iPtr->cmdCount += TclGetUInt4AtPtr(pc+5);
+ if (!checkInterp) {
+ instStartCmdOK:
+ NEXT_INST_F(9, 0, 0);
+ } else if (((codePtr->compileEpoch == iPtr->compileEpoch)
+ && (codePtr->nsEpoch == namespacePtr->resolverEpoch))
+ || (codePtr->flags & TCL_BYTECODE_PRECOMPILED)) {
+ checkInterp = 0;
+ goto instStartCmdOK;
+ } else {
+ const char *bytes;
+ int length, opnd;
+ Tcl_Obj *newObjResultPtr;
+
+ bytes = GetSrcInfoForPc(pc, codePtr, &length);
+ DECACHE_STACK_INFO();
+ result = Tcl_EvalEx(interp, bytes, length, 0);
+ CACHE_STACK_INFO();
+ if (result != TCL_OK) {
+ cleanup = 0;
+ if (result == TCL_ERROR) {
+ /*
+ * Tcl_EvalEx already did the task of logging
+ * the error to the stack trace for us, so set
+ * a flag to prevent the TEBC exception handling
+ * machinery from trying to do it again.
+ * Tcl Bug 2037338. See test execute-8.4.
+ */
+ iPtr->flags |= ERR_ALREADY_LOGGED;
+ }
+ goto processExceptionReturn;
+ }
+ opnd = TclGetUInt4AtPtr(pc+1);
+ objResultPtr = Tcl_GetObjResult(interp);
+ TclNewObj(newObjResultPtr);
+ Tcl_IncrRefCount(newObjResultPtr);
+ iPtr->objResultPtr = newObjResultPtr;
+ NEXT_INST_V(opnd, 0, -1);
+ }
+
case INST_DUP:
- objResultPtr = stackPtr[stackTop];
+ objResultPtr = OBJ_AT_TOS;
TRACE_WITH_OBJ(("=> "), objResultPtr);
NEXT_INST_F(1, 0, 1);
- case INST_OVER:
- opnd = TclGetUInt4AtPtr( pc+1 );
- objResultPtr = stackPtr[ stackTop - opnd ];
+ case INST_OVER: {
+ int opnd;
+
+ opnd = TclGetUInt4AtPtr(pc+1);
+ objResultPtr = OBJ_AT_DEPTH(opnd);
TRACE_WITH_OBJ(("=> "), objResultPtr);
NEXT_INST_F(5, 0, 1);
+ }
+
+ case INST_REVERSE: {
+ int opnd;
+ Tcl_Obj **a, **b;
+
+ opnd = TclGetUInt4AtPtr(pc+1);
+ a = tosPtr-(opnd-1);
+ b = tosPtr;
+ while (a<b) {
+ Tcl_Obj *temp = *a;
+ *a = *b;
+ *b = temp;
+ a++; b--;
+ }
+ NEXT_INST_F(5, 0, 0);
+ }
+
+ case INST_CONCAT1: {
+ int opnd, length, appendLen = 0;
+ char *bytes, *p;
+ Tcl_Obj **currPtr;
- case INST_CONCAT1:
opnd = TclGetUInt1AtPtr(pc+1);
- {
- int totalLen = 0;
-
- /*
- * Peephole optimisation for appending an empty string.
- * This enables replacing 'K $x [set x{}]' by '$x[set x{}]'
- * for fastest execution. Avoid doing the optimisation for wide
- * ints - a case where equal strings may refer to different values
- * (see [Bug 1251791]).
- */
- if ((opnd == 2) && (stackPtr[stackTop-1]->typePtr != &tclWideIntType)) {
- Tcl_GetStringFromObj(stackPtr[stackTop], &length);
- if (length == 0) {
- /* Just drop the top item from the stack */
- NEXT_INST_F(2, 1, 0);
- }
+ /*
+ * Compute the length to be appended.
+ */
+
+ for (currPtr=&OBJ_AT_DEPTH(opnd-2);
+ appendLen >= 0 && currPtr<=&OBJ_AT_TOS; currPtr++) {
+ bytes = TclGetStringFromObj(*currPtr, &length);
+ if (bytes != NULL) {
+ appendLen += length;
}
+ }
+
+ if (appendLen < 0) {
+ /* TODO: convert panic to error ? */
+ Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
+ }
+ /*
+ * If nothing is to be appended, just return the first object by
+ * dropping all the others from the stack; this saves both the
+ * computation and copy of the string rep of the first object,
+ * enabling the fast '$x[set x {}]' idiom for 'K $x [set x {}]'.
+ */
+
+ if (appendLen == 0) {
+ TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
+ NEXT_INST_V(2, (opnd-1), 0);
+ }
+
+ /*
+ * If the first object is shared, we need a new obj for the result;
+ * otherwise, we can reuse the first object. In any case, make sure it
+ * has enough room to accomodate all the concatenated bytes. Note that
+ * if it is unshared its bytes are copied by ckrealloc, so that we set
+ * the loop parameters to avoid copying them again: p points to the
+ * end of the already copied bytes, currPtr to the second object.
+ */
+
+ objResultPtr = OBJ_AT_DEPTH(opnd-1);
+ bytes = TclGetStringFromObj(objResultPtr, &length);
+ if (length + appendLen < 0) {
+ /* TODO: convert panic to error ? */
+ Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
+ }
+#if !TCL_COMPILE_DEBUG
+ if (bytes != tclEmptyStringRep && !Tcl_IsShared(objResultPtr)) {
+ TclFreeIntRep(objResultPtr);
+ objResultPtr->typePtr = NULL;
+ objResultPtr->bytes = ckrealloc(bytes, (length + appendLen + 1));
+ objResultPtr->length = length + appendLen;
+ p = TclGetString(objResultPtr) + length;
+ currPtr = &OBJ_AT_DEPTH(opnd - 2);
+ } else {
+#endif
+ p = (char *) ckalloc((unsigned) (length + appendLen + 1));
+ TclNewObj(objResultPtr);
+ objResultPtr->bytes = p;
+ objResultPtr->length = length + appendLen;
+ currPtr = &OBJ_AT_DEPTH(opnd - 1);
+#if !TCL_COMPILE_DEBUG
+ }
+#endif
+
+ /*
+ * Append the remaining characters.
+ */
+
+ for (; currPtr <= &OBJ_AT_TOS; currPtr++) {
+ bytes = TclGetStringFromObj(*currPtr, &length);
+ if (bytes != NULL) {
+ memcpy(p, bytes, (size_t) length);
+ p += length;
+ }
+ }
+ *p = '\0';
+
+ TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
+ NEXT_INST_V(2, opnd, 1);
+ }
+
+ case INST_EXPAND_START: {
+ /*
+ * Push an element to the expandNestList. This records the current
+ * stack depth - i.e., the point in the stack where the expanded
+ * command starts.
+ *
+ * Use a Tcl_Obj as linked list element; slight mem waste, but faster
+ * allocation than ckalloc. This also abuses the Tcl_Obj structure, as
+ * we do not define a special tclObjType for it. It is not dangerous
+ * as the obj is never passed anywhere, so that all manipulations are
+ * performed here and in INST_INVOKE_EXPANDED (in case of an expansion
+ * error, also in INST_EXPAND_STKTOP).
+ */
+
+ Tcl_Obj *objPtr;
+
+ TclNewObj(objPtr);
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) CURR_DEPTH;
+ objPtr->internalRep.twoPtrValue.ptr2 = (VOID *) expandNestList;
+ expandNestList = objPtr;
+ NEXT_INST_F(1, 0, 0);
+ }
+
+ case INST_EXPAND_STKTOP: {
+ int objc, length, i;
+ Tcl_Obj **objv, *valuePtr;
+ ptrdiff_t moved;
+
+ /*
+ * Make sure that the element at stackTop is a list; if not, just
+ * leave with an error. Note that the element from the expand list
+ * will be removed at checkForCatch.
+ */
+
+ valuePtr = OBJ_AT_TOS;
+ if (TclListObjGetElements(interp, valuePtr, &objc, &objv) != TCL_OK){
+ TRACE_WITH_OBJ(("%.30s => ERROR: ", O2S(valuePtr)),
+ Tcl_GetObjResult(interp));
+ result = TCL_ERROR;
+ goto checkForCatch;
+ }
+ (void) POP_OBJECT();
+
+ /*
+ * Make sure there is enough room in the stack to expand this list
+ * *and* process the rest of the command (at least up to the next
+ * argument expansion or command end). The operand is the current
+ * stack depth, as seen by the compiler.
+ */
+
+ length = objc + (codePtr->maxStackDepth - TclGetInt4AtPtr(pc+1));
+ DECACHE_STACK_INFO();
+ moved = (GrowEvaluationStack(iPtr->execEnvPtr, length, 1) - 1)
+ - (Tcl_Obj **) initCatchTop;
+
+ if (moved) {
/*
- * Concatenate strings (with no separators) from the top
- * opnd items on the stack starting with the deepest item.
- * First, determine how many characters are needed.
+ * Change the global data to point to the new stack.
*/
- for (i = (stackTop - (opnd-1));
- totalLen >= 0 && i <= stackTop; i++) {
- bytes = Tcl_GetStringFromObj(stackPtr[i], &length);
- if (bytes != NULL) {
- totalLen += length;
- }
- }
+ initCatchTop += moved;
+ catchTop += moved;
+ initTosPtr += moved;
+ tosPtr += moved;
+ esPtr = iPtr->execEnvPtr->execStackPtr;
+ }
- if (totalLen < 0) {
- Tcl_Panic("max size for a Tcl value (%d bytes) exceeded",
- INT_MAX);
- }
+ /*
+ * Expand the list at stacktop onto the stack; free the list. Knowing
+ * that it has a freeIntRepProc we use Tcl_DecrRefCount().
+ */
+
+ for (i = 0; i < objc; i++) {
+ PUSH_OBJECT(objv[i]);
+ }
+ Tcl_DecrRefCount(valuePtr);
+ NEXT_INST_F(5, 0, 0);
+ }
+
+ {
+ /*
+ * INVOCATION BLOCK
+ */
+
+ int objc, pcAdjustment;
+
+ case INST_INVOKE_EXPANDED:
+ {
+ Tcl_Obj *objPtr = expandNestList;
+
+ expandNestList = (Tcl_Obj *) objPtr->internalRep.twoPtrValue.ptr2;
+ objc = CURR_DEPTH
+ - (ptrdiff_t) objPtr->internalRep.twoPtrValue.ptr1;
+ TclDecrRefCount(objPtr);
+ }
+
+ if (objc) {
+ pcAdjustment = 1;
+ goto doInvocation;
+ } else {
/*
- * Initialize the new append string object by appending the
- * strings of the opnd stack objects. Also pop the objects.
+ * Nothing was expanded, return {}.
*/
TclNewObj(objResultPtr);
- if (totalLen > 0) {
- char *p = (char *) ckalloc((unsigned) (totalLen + 1));
- objResultPtr->bytes = p;
- objResultPtr->length = totalLen;
- for (i = (stackTop - (opnd-1)); i <= stackTop; i++) {
- valuePtr = stackPtr[i];
- bytes = Tcl_GetStringFromObj(valuePtr, &length);
- if (bytes != NULL) {
- memcpy((VOID *) p, (VOID *) bytes,
- (size_t) length);
- p += length;
- }
- }
- *p = '\0';
- }
-
- TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
- NEXT_INST_V(2, opnd, 1);
+ NEXT_INST_F(1, 0, 1);
}
-
+
case INST_INVOKE_STK4:
- opnd = TclGetUInt4AtPtr(pc+1);
+ objc = TclGetUInt4AtPtr(pc+1);
pcAdjustment = 5;
goto doInvocation;
case INST_INVOKE_STK1:
- opnd = TclGetUInt1AtPtr(pc+1);
+ objc = TclGetUInt1AtPtr(pc+1);
pcAdjustment = 2;
-
+
doInvocation:
{
- int objc = opnd; /* The number of arguments. */
- Tcl_Obj **objv; /* The array of argument objects. */
-
- /*
- * We keep the stack reference count as a (char *), as that
- * works nicely as a portable pointer-sized counter.
- */
-
- char **preservedStackRefCountPtr;
-
- /*
- * Reference to memory block containing
- * objv array (must be kept live throughout
- * trace and command invokations.)
- */
-
- objv = &(stackPtr[stackTop - (objc-1)]);
+ Tcl_Obj **objv = &OBJ_AT_DEPTH(objc-1);
#ifdef TCL_COMPILE_DEBUG
if (tclTraceExec >= 2) {
+ int i;
+
if (traceInstructions) {
strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
TRACE(("%u => call ", objc));
} else {
- fprintf(stdout, "%d: (%u) invoking ",
- iPtr->numLevels,
- (unsigned int)(pc - codePtr->codeStart));
+ fprintf(stdout, "%d: (%u) invoking ", iPtr->numLevels,
+ (unsigned)(pc - codePtr->codeStart));
}
for (i = 0; i < objc; i++) {
TclPrintObject(stdout, objv[i], 15);
@@ -1525,142 +2392,189 @@ TclExecuteByteCode(interp, codePtr)
}
#endif /*TCL_COMPILE_DEBUG*/
- /*
- * If trace procedures will be called, we need a
- * command string to pass to TclEvalObjvInternal; note
- * that a copy of the string will be made there to
- * include the ending \0.
- */
-
- bytes = NULL;
- length = 0;
- if (iPtr->tracePtr != NULL) {
- Trace *tracePtr, *nextTracePtr;
-
- for (tracePtr = iPtr->tracePtr; tracePtr != NULL;
- tracePtr = nextTracePtr) {
- nextTracePtr = tracePtr->nextPtr;
- if (tracePtr->level == 0 ||
- iPtr->numLevels <= tracePtr->level) {
- /*
- * Traces will be called: get command string
- */
-
- bytes = GetSrcInfoForPc(pc, codePtr, &length);
- break;
- }
- }
- } else {
- Command *cmdPtr;
- cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[0]);
- if ((cmdPtr != NULL) && (cmdPtr->flags & CMD_HAS_EXEC_TRACES)) {
- bytes = GetSrcInfoForPc(pc, codePtr, &length);
- }
- }
-
/*
- * A reference to part of the stack vector itself
- * escapes our control: increase its refCount
- * to stop it from being deallocated by a recursive
- * call to ourselves. The extra variable is needed
- * because all others are liable to change due to the
- * trace procedures.
+ * Reset the instructionCount variable, since we're about to check
+ * for async stuff anyway while processing TclEvalObjvInternal.
*/
- preservedStackRefCountPtr = (char **) (stackPtr-1);
- ++*preservedStackRefCountPtr;
+ instructionCount = 1;
/*
* Finally, let TclEvalObjvInternal handle the command.
*
- * TIP #280 : Record the last piece of info needed by
+ * TIP #280: Record the last piece of info needed by
* 'TclGetSrcInfoForPc', and push the frame.
*/
-#ifdef TCL_TIP280
- bcFrame.data.tebc.pc = (char*) pc;
- iPtr->cmdFramePtr = &bcFrame;
- TclArgumentBCEnter((Tcl_Interp*) iPtr, objv, objc,
- codePtr, &bcFrame,
- pc - codePtr->codeStart);
-#endif
+ bcFramePtr->data.tebc.pc = (char *) pc;
+ iPtr->cmdFramePtr = bcFramePtr;
+ if (iPtr->flags & INTERP_DEBUG_FRAME) {
+ TclArgumentBCEnter((Tcl_Interp *) iPtr, objv, objc,
+ codePtr, bcFramePtr, pc - codePtr->codeStart);
+ }
DECACHE_STACK_INFO();
- Tcl_ResetResult(interp);
- result = TclEvalObjvInternal(interp, objc, objv, bytes, length, 0);
+ result = TclEvalObjvInternal(interp, objc, objv,
+ /* call from TEBC */(char *) -1, -1, 0);
CACHE_STACK_INFO();
-#ifdef TCL_TIP280
- TclArgumentBCRelease((Tcl_Interp*) iPtr, objv, objc,
- codePtr,
- pc - codePtr->codeStart);
+ if (iPtr->flags & INTERP_DEBUG_FRAME) {
+ TclArgumentBCRelease((Tcl_Interp *) iPtr, objv, objc,
+ codePtr, pc - codePtr->codeStart);
+ }
iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr;
-#endif
-
- /*
- * If the old stack is going to be released, it is
- * safe to do so now, since no references to objv are
- * going to be used from now on.
- */
-
- --*preservedStackRefCountPtr;
- if (*preservedStackRefCountPtr == (char *) 0) {
- ckfree((VOID *) preservedStackRefCountPtr);
- }
if (result == TCL_OK) {
+ Tcl_Obj *objPtr;
+
+#ifndef TCL_COMPILE_DEBUG
+ if (*(pc+pcAdjustment) == INST_POP) {
+ NEXT_INST_V((pcAdjustment+1), objc, 0);
+ }
+#endif
/*
- * Push the call's object result and continue execution
- * with the next instruction.
+ * Push the call's object result and continue execution with
+ * the next instruction.
*/
TRACE_WITH_OBJ(("%u => ... after \"%.20s\": TCL_OK, result=",
- objc, cmdNameBuf), Tcl_GetObjResult(interp));
+ objc, cmdNameBuf), Tcl_GetObjResult(interp));
objResultPtr = Tcl_GetObjResult(interp);
/*
- * Reset the interp's result to avoid possible duplications
- * of large objects [Bug 781585]. We do not call
- * Tcl_ResetResult() to avoid any side effects caused by
- * the resetting of errorInfo and errorCode [Bug 804681],
- * which are not needed here. We chose instead to manipulate
- * the interp's object result directly.
+ * Reset the interp's result to avoid possible duplications of
+ * large objects [Bug 781585]. We do not call Tcl_ResetResult
+ * to avoid any side effects caused by the resetting of
+ * errorInfo and errorCode [Bug 804681], which are not needed
+ * here. We chose instead to manipulate the interp's object
+ * result directly.
*
* Note that the result object is now in objResultPtr, it
- * keeps the refCount it had in its role of iPtr->objResultPtr.
+ * keeps the refCount it had in its role of
+ * iPtr->objResultPtr.
*/
- {
- Tcl_Obj *newObjResultPtr;
- TclNewObj(newObjResultPtr);
- Tcl_IncrRefCount(newObjResultPtr);
- iPtr->objResultPtr = newObjResultPtr;
- }
- NEXT_INST_V(pcAdjustment, opnd, -1);
+ TclNewObj(objPtr);
+ Tcl_IncrRefCount(objPtr);
+ iPtr->objResultPtr = objPtr;
+ NEXT_INST_V(pcAdjustment, objc, -1);
} else {
- cleanup = opnd;
+ cleanup = objc;
goto processExceptionReturn;
}
}
- case INST_EVAL_STK:
+#if TCL_SUPPORT_84_BYTECODE
+ case INST_CALL_BUILTIN_FUNC1: {
/*
- * Note to maintainers: it is important that INST_EVAL_STK
- * pop its argument from the stack before jumping to
- * checkForCatch! DO NOT OPTIMISE!
+ * Call one of the built-in pre-8.5 Tcl math functions. This
+ * translates to INST_INVOKE_STK1 with the first argument of
+ * ::tcl::mathfunc::$objv[0]. We need to insert the named math
+ * function into the stack.
*/
- objPtr = stackPtr[stackTop];
- DECACHE_STACK_INFO();
-#ifndef TCL_TIP280
- result = TclCompEvalObj(interp, objPtr);
+ int opnd, numArgs;
+ Tcl_Obj *objPtr;
+
+ opnd = TclGetUInt1AtPtr(pc+1);
+ if ((opnd < 0) || (opnd > LAST_BUILTIN_FUNC)) {
+ TRACE(("UNRECOGNIZED BUILTIN FUNC CODE %d\n", opnd));
+ Tcl_Panic("TclExecuteByteCode: unrecognized builtin function code %d", opnd);
+ }
+
+ objPtr = Tcl_NewStringObj("::tcl::mathfunc::", 17);
+ Tcl_AppendToObj(objPtr, tclBuiltinFuncTable[opnd].name, -1);
+
+ /*
+ * Only 0, 1 or 2 args.
+ */
+
+ numArgs = tclBuiltinFuncTable[opnd].numArgs;
+ if (numArgs == 0) {
+ PUSH_OBJECT(objPtr);
+ } else if (numArgs == 1) {
+ Tcl_Obj *tmpPtr1 = POP_OBJECT();
+ PUSH_OBJECT(objPtr);
+ PUSH_OBJECT(tmpPtr1);
+ Tcl_DecrRefCount(tmpPtr1);
+ } else {
+ Tcl_Obj *tmpPtr1, *tmpPtr2;
+ tmpPtr2 = POP_OBJECT();
+ tmpPtr1 = POP_OBJECT();
+ PUSH_OBJECT(objPtr);
+ PUSH_OBJECT(tmpPtr1);
+ PUSH_OBJECT(tmpPtr2);
+ Tcl_DecrRefCount(tmpPtr1);
+ Tcl_DecrRefCount(tmpPtr2);
+ }
+
+ objc = numArgs + 1;
+ pcAdjustment = 2;
+ goto doInvocation;
+ }
+
+ case INST_CALL_FUNC1: {
+ /*
+ * Call a non-builtin Tcl math function previously registered by a
+ * call to Tcl_CreateMathFunc pre-8.5. This is essentially
+ * INST_INVOKE_STK1 converting the first arg to
+ * ::tcl::mathfunc::$objv[0].
+ */
+
+ Tcl_Obj *tmpPtr, *objPtr;
+
+ /*
+ * Number of arguments. The function name is the 0-th argument.
+ */
+
+ objc = TclGetUInt1AtPtr(pc+1);
+
+ objPtr = OBJ_AT_DEPTH(objc-1);
+ tmpPtr = Tcl_NewStringObj("::tcl::mathfunc::", 17);
+ Tcl_AppendObjToObj(tmpPtr, objPtr);
+ Tcl_DecrRefCount(objPtr);
+
+ /*
+ * Variation of PUSH_OBJECT.
+ */
+
+ OBJ_AT_DEPTH(objc-1) = tmpPtr;
+ Tcl_IncrRefCount(tmpPtr);
+
+ pcAdjustment = 2;
+ goto doInvocation;
+ }
#else
- /* TIP #280: The invoking context is left NULL for a dynamically
+ /*
+ * INST_CALL_BUILTIN_FUNC1 and INST_CALL_FUNC1 were made obsolete by the
+ * changes to add a ::tcl::mathfunc namespace in 8.5. Optional support
+ * remains for existing bytecode precompiled files.
+ */
+
+ case INST_CALL_BUILTIN_FUNC1:
+ Tcl_Panic("TclExecuteByteCode: obsolete INST_CALL_BUILTIN_FUNC1 found");
+ case INST_CALL_FUNC1:
+ Tcl_Panic("TclExecuteByteCode: obsolete INST_CALL_FUNC1 found");
+#endif
+ }
+
+ case INST_EVAL_STK: {
+ /*
+ * Note to maintainers: it is important that INST_EVAL_STK pop its
+ * argument from the stack before jumping to checkForCatch! DO NOT
+ * OPTIMISE!
+ */
+
+ Tcl_Obj *objPtr = OBJ_AT_TOS;
+
+ DECACHE_STACK_INFO();
+
+ /*
+ * TIP #280: The invoking context is left NULL for a dynamically
* constructed command. We cannot match its lines to the outer
* context.
*/
- result = TclCompEvalObj(interp, objPtr, NULL,0);
-#endif
+ result = TclCompEvalObj(interp, objPtr, NULL, 0);
CACHE_STACK_INFO();
if (result == TCL_OK) {
/*
@@ -1669,69 +2583,75 @@ TclExecuteByteCode(interp, codePtr)
objResultPtr = Tcl_GetObjResult(interp);
TRACE_WITH_OBJ(("\"%.30s\" => ", O2S(objPtr)),
- Tcl_GetObjResult(interp));
+ Tcl_GetObjResult(interp));
/*
- * Reset the interp's result to avoid possible duplications
- * of large objects [Bug 781585]. We do not call
- * Tcl_ResetResult() to avoid any side effects caused by
- * the resetting of errorInfo and errorCode [Bug 804681],
- * which are not needed here. We chose instead to manipulate
- * the interp's object result directly.
+ * Reset the interp's result to avoid possible duplications of
+ * large objects [Bug 781585]. We do not call Tcl_ResetResult to
+ * avoid any side effects caused by the resetting of errorInfo and
+ * errorCode [Bug 804681], which are not needed here. We chose
+ * instead to manipulate the interp's object result directly.
*
- * Note that the result object is now in objResultPtr, it
- * keeps the refCount it had in its role of iPtr->objResultPtr.
+ * Note that the result object is now in objResultPtr, it keeps
+ * the refCount it had in its role of iPtr->objResultPtr.
*/
- {
- Tcl_Obj *newObjResultPtr;
- TclNewObj(newObjResultPtr);
- Tcl_IncrRefCount(newObjResultPtr);
- iPtr->objResultPtr = newObjResultPtr;
- }
+ TclNewObj(objPtr);
+ Tcl_IncrRefCount(objPtr);
+ iPtr->objResultPtr = objPtr;
NEXT_INST_F(1, 1, -1);
} else {
cleanup = 1;
goto processExceptionReturn;
}
+ }
+
+ case INST_EXPR_STK: {
+ Tcl_Obj *objPtr, *valuePtr;
- case INST_EXPR_STK:
- objPtr = stackPtr[stackTop];
+ objPtr = OBJ_AT_TOS;
DECACHE_STACK_INFO();
- Tcl_ResetResult(interp);
+ /*Tcl_ResetResult(interp);*/
result = Tcl_ExprObj(interp, objPtr, &valuePtr);
CACHE_STACK_INFO();
- if (result != TCL_OK) {
- TRACE_WITH_OBJ(("\"%.30s\" => ERROR: ",
- O2S(objPtr)), Tcl_GetObjResult(interp));
+ if (result == TCL_OK) {
+ objResultPtr = valuePtr;
+ TRACE_WITH_OBJ(("\"%.30s\" => ", O2S(objPtr)), valuePtr);
+ NEXT_INST_F(1, 1, -1); /* Already has right refct. */
+ } else {
+ TRACE_WITH_OBJ(("\"%.30s\" => ERROR: ", O2S(objPtr)),
+ Tcl_GetObjResult(interp));
goto checkForCatch;
}
- objResultPtr = valuePtr;
- TRACE_WITH_OBJ(("\"%.30s\" => ", O2S(objPtr)), valuePtr);
- NEXT_INST_F(1, 1, -1); /* already has right refct */
+ }
/*
* ---------------------------------------------------------
- * Start of INST_LOAD instructions.
+ * Start of INST_LOAD instructions.
*
- * WARNING: more 'goto' here than your doctor recommended!
- * The different instructions set the value of some variables
- * and then jump to somme common execution code.
+ * WARNING: more 'goto' here than your doctor recommended! The different
+ * instructions set the value of some variables and then jump to some
+ * common execution code.
*/
+ {
+ int opnd, pcAdjustment;
+ Tcl_Obj *part1Ptr, *part2Ptr;
+ Var *varPtr, *arrayPtr;
+ Tcl_Obj *objPtr;
case INST_LOAD_SCALAR1:
+ instLoadScalar1:
opnd = TclGetUInt1AtPtr(pc+1);
- varPtr = &(varFramePtr->compiledLocals[opnd]);
- part1 = varPtr->name;
+ varPtr = &(compiledLocals[opnd]);
while (TclIsVarLink(varPtr)) {
varPtr = varPtr->value.linkPtr;
}
TRACE(("%u => ", opnd));
- if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)
- && (varPtr->tracePtr == NULL)) {
+ if (TclIsVarDirectReadable(varPtr)) {
/*
* No errors, no traces: just get the value.
*/
+
objResultPtr = varPtr->value.objPtr;
TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
NEXT_INST_F(2, 0, 1);
@@ -1739,22 +2659,21 @@ TclExecuteByteCode(interp, codePtr)
pcAdjustment = 2;
cleanup = 0;
arrayPtr = NULL;
- part2 = NULL;
+ part1Ptr = part2Ptr = NULL;
goto doCallPtrGetVar;
case INST_LOAD_SCALAR4:
opnd = TclGetUInt4AtPtr(pc+1);
- varPtr = &(varFramePtr->compiledLocals[opnd]);
- part1 = varPtr->name;
+ varPtr = &(compiledLocals[opnd]);
while (TclIsVarLink(varPtr)) {
varPtr = varPtr->value.linkPtr;
}
TRACE(("%u => ", opnd));
- if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)
- && (varPtr->tracePtr == NULL)) {
+ if (TclIsVarDirectReadable(varPtr)) {
/*
* No errors, no traces: just get the value.
*/
+
objResultPtr = varPtr->value.objPtr;
TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
NEXT_INST_F(5, 0, 1);
@@ -1762,46 +2681,7 @@ TclExecuteByteCode(interp, codePtr)
pcAdjustment = 5;
cleanup = 0;
arrayPtr = NULL;
- part2 = NULL;
- goto doCallPtrGetVar;
-
- case INST_LOAD_ARRAY_STK:
- cleanup = 2;
- part2 = Tcl_GetString(stackPtr[stackTop]); /* element name */
- objPtr = stackPtr[stackTop-1]; /* array name */
- TRACE(("\"%.30s(%.30s)\" => ", O2S(objPtr), part2));
- goto doLoadStk;
-
- case INST_LOAD_STK:
- case INST_LOAD_SCALAR_STK:
- cleanup = 1;
- part2 = NULL;
- objPtr = stackPtr[stackTop]; /* variable name */
- TRACE(("\"%.30s\" => ", O2S(objPtr)));
-
- doLoadStk:
- part1 = TclGetString(objPtr);
- varPtr = TclObjLookupVar(interp, objPtr, part2,
- TCL_LEAVE_ERR_MSG, "read",
- /*createPart1*/ 0,
- /*createPart2*/ 1, &arrayPtr);
- if (varPtr == NULL) {
- TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
- result = TCL_ERROR;
- goto checkForCatch;
- }
- if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)
- && (varPtr->tracePtr == NULL)
- && ((arrayPtr == NULL)
- || (arrayPtr->tracePtr == NULL))) {
- /*
- * No errors, no traces: just get the value.
- */
- objResultPtr = varPtr->value.objPtr;
- TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
- NEXT_INST_V(1, cleanup, 1);
- }
- pcAdjustment = 1;
+ part1Ptr = part2Ptr = NULL;
goto doCallPtrGetVar;
case INST_LOAD_ARRAY4:
@@ -1812,143 +2692,267 @@ TclExecuteByteCode(interp, codePtr)
case INST_LOAD_ARRAY1:
opnd = TclGetUInt1AtPtr(pc+1);
pcAdjustment = 2;
-
+
doLoadArray:
- part2 = TclGetString(stackPtr[stackTop]);
- arrayPtr = &(varFramePtr->compiledLocals[opnd]);
- part1 = arrayPtr->name;
+ part1Ptr = NULL;
+ part2Ptr = OBJ_AT_TOS;
+ arrayPtr = &(compiledLocals[opnd]);
while (TclIsVarLink(arrayPtr)) {
arrayPtr = arrayPtr->value.linkPtr;
}
- TRACE(("%u \"%.30s\" => ", opnd, part2));
- varPtr = TclLookupArrayElement(interp, part1, part2,
- TCL_LEAVE_ERR_MSG, "read", 0, 1, arrayPtr);
+ TRACE(("%u \"%.30s\" => ", opnd, O2S(part2Ptr)));
+ if (TclIsVarArray(arrayPtr) && !ReadTraced(arrayPtr)) {
+ varPtr = VarHashFindVar(arrayPtr->value.tablePtr, part2Ptr);
+ if (varPtr && TclIsVarDirectReadable(varPtr)) {
+ /*
+ * No errors, no traces: just get the value.
+ */
+
+ objResultPtr = varPtr->value.objPtr;
+ TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
+ NEXT_INST_F(pcAdjustment, 1, 1);
+ }
+ }
+ varPtr = TclLookupArrayElement(interp, part1Ptr, part2Ptr,
+ TCL_LEAVE_ERR_MSG, "read", 0, 1, arrayPtr, opnd);
if (varPtr == NULL) {
- TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
+ TRACE_APPEND(("ERROR: %.30s\n",
+ O2S(Tcl_GetObjResult(interp))));
result = TCL_ERROR;
goto checkForCatch;
}
- if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)
- && (varPtr->tracePtr == NULL)
- && ((arrayPtr == NULL)
- || (arrayPtr->tracePtr == NULL))) {
- /*
- * No errors, no traces: just get the value.
- */
- objResultPtr = varPtr->value.objPtr;
- TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
- NEXT_INST_F(pcAdjustment, 1, 1);
- }
cleanup = 1;
goto doCallPtrGetVar;
+ case INST_LOAD_ARRAY_STK:
+ cleanup = 2;
+ part2Ptr = OBJ_AT_TOS; /* element name */
+ objPtr = OBJ_UNDER_TOS; /* array name */
+ TRACE(("\"%.30s(%.30s)\" => ", O2S(objPtr), O2S(part2Ptr)));
+ goto doLoadStk;
+
+ case INST_LOAD_STK:
+ case INST_LOAD_SCALAR_STK:
+ cleanup = 1;
+ part2Ptr = NULL;
+ objPtr = OBJ_AT_TOS; /* variable name */
+ TRACE(("\"%.30s\" => ", O2S(objPtr)));
+
+ doLoadStk:
+ part1Ptr = objPtr;
+ varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr,
+ TCL_LEAVE_ERR_MSG, "read", /*createPart1*/0, /*createPart2*/1,
+ &arrayPtr);
+ if (varPtr) {
+ if (TclIsVarDirectReadable2(varPtr, arrayPtr)) {
+ /*
+ * No errors, no traces: just get the value.
+ */
+
+ objResultPtr = varPtr->value.objPtr;
+ TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
+ NEXT_INST_V(1, cleanup, 1);
+ }
+ pcAdjustment = 1;
+ opnd = -1;
+ goto doCallPtrGetVar;
+ } else {
+ TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
+ result = TCL_ERROR;
+ goto checkForCatch;
+ }
+
doCallPtrGetVar:
/*
- * There are either errors or the variable is traced:
- * call TclPtrGetVar to process fully.
+ * There are either errors or the variable is traced: call
+ * TclPtrGetVar to process fully.
*/
DECACHE_STACK_INFO();
- objResultPtr = TclPtrGetVar(interp, varPtr, arrayPtr, part1,
- part2, TCL_LEAVE_ERR_MSG);
+ objResultPtr = TclPtrGetVar(interp, varPtr, arrayPtr,
+ part1Ptr, part2Ptr, TCL_LEAVE_ERR_MSG, opnd);
CACHE_STACK_INFO();
- if (objResultPtr == NULL) {
+ if (objResultPtr) {
+ TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
+ NEXT_INST_V(pcAdjustment, cleanup, 1);
+ } else {
TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
result = TCL_ERROR;
goto checkForCatch;
}
- TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
- NEXT_INST_V(pcAdjustment, cleanup, 1);
+ }
/*
- * End of INST_LOAD instructions.
+ * End of INST_LOAD instructions.
* ---------------------------------------------------------
*/
/*
* ---------------------------------------------------------
- * Start of INST_STORE and related instructions.
+ * Start of INST_STORE and related instructions.
*
- * WARNING: more 'goto' here than your doctor recommended!
- * The different instructions set the value of some variables
- * and then jump to somme common execution code.
+ * WARNING: more 'goto' here than your doctor recommended! The different
+ * instructions set the value of some variables and then jump to somme
+ * common execution code.
*/
+ {
+ int opnd, pcAdjustment, storeFlags;
+ Tcl_Obj *part1Ptr, *part2Ptr;
+ Var *varPtr, *arrayPtr;
+ Tcl_Obj *objPtr, *valuePtr;
+
+ case INST_STORE_ARRAY4:
+ opnd = TclGetUInt4AtPtr(pc+1);
+ pcAdjustment = 5;
+ goto doStoreArrayDirect;
+
+ case INST_STORE_ARRAY1:
+ opnd = TclGetUInt1AtPtr(pc+1);
+ pcAdjustment = 2;
+
+ doStoreArrayDirect:
+ valuePtr = OBJ_AT_TOS;
+ part2Ptr = OBJ_UNDER_TOS;
+ arrayPtr = &(compiledLocals[opnd]);
+ TRACE(("%u \"%.30s\" <- \"%.30s\" => ", opnd, O2S(part2Ptr),
+ O2S(valuePtr)));
+ while (TclIsVarLink(arrayPtr)) {
+ arrayPtr = arrayPtr->value.linkPtr;
+ }
+ if (TclIsVarArray(arrayPtr) && !WriteTraced(arrayPtr)) {
+ varPtr = VarHashFindVar(arrayPtr->value.tablePtr, part2Ptr);
+ if (varPtr && TclIsVarDirectWritable(varPtr)) {
+ tosPtr--;
+ Tcl_DecrRefCount(OBJ_AT_TOS);
+ OBJ_AT_TOS = valuePtr;
+ goto doStoreVarDirect;
+ }
+ }
+ cleanup = 2;
+ storeFlags = TCL_LEAVE_ERR_MSG;
+ part1Ptr = NULL;
+ goto doStoreArrayDirectFailed;
+
+ case INST_STORE_SCALAR4:
+ opnd = TclGetUInt4AtPtr(pc+1);
+ pcAdjustment = 5;
+ goto doStoreScalarDirect;
+
+ case INST_STORE_SCALAR1:
+ opnd = TclGetUInt1AtPtr(pc+1);
+ pcAdjustment = 2;
+
+ doStoreScalarDirect:
+ valuePtr = OBJ_AT_TOS;
+ varPtr = &(compiledLocals[opnd]);
+ TRACE(("%u <- \"%.30s\" => ", opnd, O2S(valuePtr)));
+ while (TclIsVarLink(varPtr)) {
+ varPtr = varPtr->value.linkPtr;
+ }
+ if (TclIsVarDirectWritable(varPtr)) {
+ doStoreVarDirect:
+ /*
+ * No traces, no errors, plain 'set': we can safely inline. The
+ * value *will* be set to what's requested, so that the stack top
+ * remains pointing to the same Tcl_Obj.
+ */
+
+ valuePtr = varPtr->value.objPtr;
+ if (valuePtr != NULL) {
+ TclDecrRefCount(valuePtr);
+ }
+ objResultPtr = OBJ_AT_TOS;
+ varPtr->value.objPtr = objResultPtr;
+#ifndef TCL_COMPILE_DEBUG
+ if (*(pc+pcAdjustment) == INST_POP) {
+ tosPtr--;
+ NEXT_INST_F((pcAdjustment+1), 0, 0);
+ }
+#else
+ TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
+#endif
+ Tcl_IncrRefCount(objResultPtr);
+ NEXT_INST_F(pcAdjustment, 0, 0);
+ }
+ storeFlags = TCL_LEAVE_ERR_MSG;
+ part1Ptr = NULL;
+ goto doStoreScalar;
+
case INST_LAPPEND_STK:
- valuePtr = stackPtr[stackTop]; /* value to append */
- part2 = NULL;
- storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
- | TCL_LIST_ELEMENT);
+ valuePtr = OBJ_AT_TOS; /* value to append */
+ part2Ptr = NULL;
+ storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
+ | TCL_LIST_ELEMENT);
goto doStoreStk;
case INST_LAPPEND_ARRAY_STK:
- valuePtr = stackPtr[stackTop]; /* value to append */
- part2 = TclGetString(stackPtr[stackTop - 1]);
- storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
- | TCL_LIST_ELEMENT);
+ valuePtr = OBJ_AT_TOS; /* value to append */
+ part2Ptr = OBJ_UNDER_TOS;
+ storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
+ | TCL_LIST_ELEMENT);
goto doStoreStk;
case INST_APPEND_STK:
- valuePtr = stackPtr[stackTop]; /* value to append */
- part2 = NULL;
+ valuePtr = OBJ_AT_TOS; /* value to append */
+ part2Ptr = NULL;
storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
goto doStoreStk;
case INST_APPEND_ARRAY_STK:
- valuePtr = stackPtr[stackTop]; /* value to append */
- part2 = TclGetString(stackPtr[stackTop - 1]);
+ valuePtr = OBJ_AT_TOS; /* value to append */
+ part2Ptr = OBJ_UNDER_TOS;
storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
goto doStoreStk;
case INST_STORE_ARRAY_STK:
- valuePtr = stackPtr[stackTop];
- part2 = TclGetString(stackPtr[stackTop - 1]);
+ valuePtr = OBJ_AT_TOS;
+ part2Ptr = OBJ_UNDER_TOS;
storeFlags = TCL_LEAVE_ERR_MSG;
goto doStoreStk;
case INST_STORE_STK:
case INST_STORE_SCALAR_STK:
- valuePtr = stackPtr[stackTop];
- part2 = NULL;
+ valuePtr = OBJ_AT_TOS;
+ part2Ptr = NULL;
storeFlags = TCL_LEAVE_ERR_MSG;
doStoreStk:
- objPtr = stackPtr[stackTop - 1 - (part2 != NULL)]; /* variable name */
- part1 = TclGetString(objPtr);
+ objPtr = OBJ_AT_DEPTH(1 + (part2Ptr != NULL)); /* variable name */
+ part1Ptr = objPtr;
#ifdef TCL_COMPILE_DEBUG
- if (part2 == NULL) {
- TRACE(("\"%.30s\" <- \"%.30s\" =>",
- part1, O2S(valuePtr)));
+ if (part2Ptr == NULL) {
+ TRACE(("\"%.30s\" <- \"%.30s\" =>", O2S(part1Ptr),O2S(valuePtr)));
} else {
TRACE(("\"%.30s(%.30s)\" <- \"%.30s\" => ",
- part1, part2, O2S(valuePtr)));
+ O2S(part1Ptr), O2S(part2Ptr), O2S(valuePtr)));
}
#endif
- varPtr = TclObjLookupVar(interp, objPtr, part2,
- TCL_LEAVE_ERR_MSG, "set",
- /*createPart1*/ 1,
- /*createPart2*/ 1, &arrayPtr);
- if (varPtr == NULL) {
+ varPtr = TclObjLookupVarEx(interp, objPtr,part2Ptr, TCL_LEAVE_ERR_MSG,
+ "set", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
+ if (varPtr) {
+ cleanup = ((part2Ptr == NULL)? 2 : 3);
+ pcAdjustment = 1;
+ opnd = -1;
+ goto doCallPtrSetVar;
+ } else {
TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
result = TCL_ERROR;
goto checkForCatch;
}
- cleanup = ((part2 == NULL)? 2 : 3);
- pcAdjustment = 1;
- goto doCallPtrSetVar;
case INST_LAPPEND_ARRAY4:
opnd = TclGetUInt4AtPtr(pc+1);
pcAdjustment = 5;
- storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
- | TCL_LIST_ELEMENT);
+ storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
+ | TCL_LIST_ELEMENT);
goto doStoreArray;
case INST_LAPPEND_ARRAY1:
opnd = TclGetUInt1AtPtr(pc+1);
pcAdjustment = 2;
- storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
- | TCL_LIST_ELEMENT);
+ storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
+ | TCL_LIST_ELEMENT);
goto doStoreArray;
case INST_APPEND_ARRAY4:
@@ -1963,49 +2967,41 @@ TclExecuteByteCode(interp, codePtr)
storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
goto doStoreArray;
- case INST_STORE_ARRAY4:
- opnd = TclGetUInt4AtPtr(pc+1);
- pcAdjustment = 5;
- storeFlags = TCL_LEAVE_ERR_MSG;
- goto doStoreArray;
-
- case INST_STORE_ARRAY1:
- opnd = TclGetUInt1AtPtr(pc+1);
- pcAdjustment = 2;
- storeFlags = TCL_LEAVE_ERR_MSG;
-
doStoreArray:
- valuePtr = stackPtr[stackTop];
- part2 = TclGetString(stackPtr[stackTop - 1]);
- arrayPtr = &(varFramePtr->compiledLocals[opnd]);
- part1 = arrayPtr->name;
- TRACE(("%u \"%.30s\" <- \"%.30s\" => ",
- opnd, part2, O2S(valuePtr)));
+ valuePtr = OBJ_AT_TOS;
+ part2Ptr = OBJ_UNDER_TOS;
+ arrayPtr = &(compiledLocals[opnd]);
+ TRACE(("%u \"%.30s\" <- \"%.30s\" => ", opnd, O2S(part2Ptr),
+ O2S(valuePtr)));
while (TclIsVarLink(arrayPtr)) {
arrayPtr = arrayPtr->value.linkPtr;
}
- varPtr = TclLookupArrayElement(interp, part1, part2,
- TCL_LEAVE_ERR_MSG, "set", 1, 1, arrayPtr);
- if (varPtr == NULL) {
+ cleanup = 2;
+ part1Ptr = NULL;
+
+ doStoreArrayDirectFailed:
+ varPtr = TclLookupArrayElement(interp, part1Ptr, part2Ptr,
+ TCL_LEAVE_ERR_MSG, "set", 1, 1, arrayPtr, opnd);
+ if (varPtr) {
+ goto doCallPtrSetVar;
+ } else {
TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
result = TCL_ERROR;
goto checkForCatch;
}
- cleanup = 2;
- goto doCallPtrSetVar;
case INST_LAPPEND_SCALAR4:
opnd = TclGetUInt4AtPtr(pc+1);
pcAdjustment = 5;
- storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
- | TCL_LIST_ELEMENT);
+ storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
+ | TCL_LIST_ELEMENT);
goto doStoreScalar;
case INST_LAPPEND_SCALAR1:
opnd = TclGetUInt1AtPtr(pc+1);
- pcAdjustment = 2;
- storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
- | TCL_LIST_ELEMENT);
+ pcAdjustment = 2;
+ storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE
+ | TCL_LIST_ELEMENT);
goto doStoreScalar;
case INST_APPEND_SCALAR4:
@@ -2016,248 +3012,317 @@ TclExecuteByteCode(interp, codePtr)
case INST_APPEND_SCALAR1:
opnd = TclGetUInt1AtPtr(pc+1);
- pcAdjustment = 2;
+ pcAdjustment = 2;
storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
goto doStoreScalar;
- case INST_STORE_SCALAR4:
- opnd = TclGetUInt4AtPtr(pc+1);
- pcAdjustment = 5;
- storeFlags = TCL_LEAVE_ERR_MSG;
- goto doStoreScalar;
-
- case INST_STORE_SCALAR1:
- opnd = TclGetUInt1AtPtr(pc+1);
- pcAdjustment = 2;
- storeFlags = TCL_LEAVE_ERR_MSG;
-
doStoreScalar:
- valuePtr = stackPtr[stackTop];
- varPtr = &(varFramePtr->compiledLocals[opnd]);
- part1 = varPtr->name;
+ valuePtr = OBJ_AT_TOS;
+ varPtr = &(compiledLocals[opnd]);
TRACE(("%u <- \"%.30s\" => ", opnd, O2S(valuePtr)));
while (TclIsVarLink(varPtr)) {
varPtr = varPtr->value.linkPtr;
}
cleanup = 1;
arrayPtr = NULL;
- part2 = NULL;
+ part1Ptr = part2Ptr = NULL;
doCallPtrSetVar:
- if ((storeFlags == TCL_LEAVE_ERR_MSG)
- && !((varPtr->flags & VAR_IN_HASHTABLE)
- && (varPtr->hPtr == NULL))
- && (varPtr->tracePtr == NULL)
- && (TclIsVarScalar(varPtr)
- || TclIsVarUndefined(varPtr))
- && ((arrayPtr == NULL)
- || (arrayPtr->tracePtr == NULL))) {
- /*
- * No traces, no errors, plain 'set': we can safely inline.
- * The value *will* be set to what's requested, so that
- * the stack top remains pointing to the same Tcl_Obj.
- */
- valuePtr = varPtr->value.objPtr;
- objResultPtr = stackPtr[stackTop];
- if (valuePtr != objResultPtr) {
- if (valuePtr != NULL) {
- TclDecrRefCount(valuePtr);
- } else {
- TclSetVarScalar(varPtr);
- TclClearVarUndefined(varPtr);
- }
- varPtr->value.objPtr = objResultPtr;
- Tcl_IncrRefCount(objResultPtr);
- }
+ DECACHE_STACK_INFO();
+ objResultPtr = TclPtrSetVar(interp, varPtr, arrayPtr,
+ part1Ptr, part2Ptr, valuePtr, storeFlags, opnd);
+ CACHE_STACK_INFO();
+ if (objResultPtr) {
#ifndef TCL_COMPILE_DEBUG
if (*(pc+pcAdjustment) == INST_POP) {
NEXT_INST_V((pcAdjustment+1), cleanup, 0);
}
-#else
- TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
#endif
+ TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
NEXT_INST_V(pcAdjustment, cleanup, 1);
} else {
- DECACHE_STACK_INFO();
- objResultPtr = TclPtrSetVar(interp, varPtr, arrayPtr,
- part1, part2, valuePtr, storeFlags);
- CACHE_STACK_INFO();
- if (objResultPtr == NULL) {
- TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
- result = TCL_ERROR;
- goto checkForCatch;
- }
- }
-#ifndef TCL_COMPILE_DEBUG
- if (*(pc+pcAdjustment) == INST_POP) {
- NEXT_INST_V((pcAdjustment+1), cleanup, 0);
+ TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
+ result = TCL_ERROR;
+ goto checkForCatch;
}
-#endif
- TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
- NEXT_INST_V(pcAdjustment, cleanup, 1);
-
+ }
/*
- * End of INST_STORE and related instructions.
+ * End of INST_STORE and related instructions.
* ---------------------------------------------------------
*/
/*
* ---------------------------------------------------------
- * Start of INST_INCR instructions.
+ * Start of INST_INCR instructions.
*
- * WARNING: more 'goto' here than your doctor recommended!
- * The different instructions set the value of some variables
- * and then jump to somme common execution code.
+ * WARNING: more 'goto' here than your doctor recommended! The different
+ * instructions set the value of some variables and then jump to somme
+ * common execution code.
*/
+/*TODO: Consider more untangling here; merge with LOAD and STORE ? */
+
+ {
+ Tcl_Obj *objPtr, *incrPtr;
+ int opnd, pcAdjustment;
+#ifndef NO_WIDE_TYPE
+ Tcl_WideInt w;
+#endif
+ long i;
+ Tcl_Obj *part1Ptr, *part2Ptr;
+ Var *varPtr, *arrayPtr;
+
case INST_INCR_SCALAR1:
case INST_INCR_ARRAY1:
case INST_INCR_ARRAY_STK:
case INST_INCR_SCALAR_STK:
case INST_INCR_STK:
opnd = TclGetUInt1AtPtr(pc+1);
- valuePtr = stackPtr[stackTop];
- if (valuePtr->typePtr == &tclIntType) {
- i = valuePtr->internalRep.longValue;
- } else if (valuePtr->typePtr == &tclWideIntType) {
- TclGetLongFromWide(i,valuePtr);
- } else {
- REQUIRE_WIDE_OR_INT(result, valuePtr, i, w);
- if (result != TCL_OK) {
- TRACE_WITH_OBJ(("%u (by %s) => ERROR converting increment amount to int: ",
- opnd, O2S(valuePtr)), Tcl_GetObjResult(interp));
- DECACHE_STACK_INFO();
- Tcl_AddErrorInfo(interp, "\n (reading increment)");
- CACHE_STACK_INFO();
- goto checkForCatch;
- }
- FORCE_LONG(valuePtr, i, w);
- }
- stackTop--;
- TclDecrRefCount(valuePtr);
+ incrPtr = POP_OBJECT();
switch (*pc) {
- case INST_INCR_SCALAR1:
- pcAdjustment = 2;
- goto doIncrScalar;
- case INST_INCR_ARRAY1:
- pcAdjustment = 2;
- goto doIncrArray;
- default:
- pcAdjustment = 1;
- goto doIncrStk;
+ case INST_INCR_SCALAR1:
+ pcAdjustment = 2;
+ goto doIncrScalar;
+ case INST_INCR_ARRAY1:
+ pcAdjustment = 2;
+ goto doIncrArray;
+ default:
+ pcAdjustment = 1;
+ goto doIncrStk;
}
case INST_INCR_ARRAY_STK_IMM:
case INST_INCR_SCALAR_STK_IMM:
case INST_INCR_STK_IMM:
i = TclGetInt1AtPtr(pc+1);
+ incrPtr = Tcl_NewIntObj(i);
+ Tcl_IncrRefCount(incrPtr);
pcAdjustment = 2;
-
+
doIncrStk:
- if ((*pc == INST_INCR_ARRAY_STK_IMM)
- || (*pc == INST_INCR_ARRAY_STK)) {
- part2 = TclGetString(stackPtr[stackTop]);
- objPtr = stackPtr[stackTop - 1];
+ if ((*pc == INST_INCR_ARRAY_STK_IMM)
+ || (*pc == INST_INCR_ARRAY_STK)) {
+ part2Ptr = OBJ_AT_TOS;
+ objPtr = OBJ_UNDER_TOS;
TRACE(("\"%.30s(%.30s)\" (by %ld) => ",
- O2S(objPtr), part2, i));
+ O2S(objPtr), O2S(part2Ptr), i));
} else {
- part2 = NULL;
- objPtr = stackPtr[stackTop];
+ part2Ptr = NULL;
+ objPtr = OBJ_AT_TOS;
TRACE(("\"%.30s\" (by %ld) => ", O2S(objPtr), i));
}
- part1 = TclGetString(objPtr);
-
- varPtr = TclObjLookupVar(interp, objPtr, part2,
- TCL_LEAVE_ERR_MSG, "read", 0, 1, &arrayPtr);
- if (varPtr == NULL) {
- DECACHE_STACK_INFO();
+ part1Ptr = objPtr;
+ opnd = -1;
+ varPtr = TclObjLookupVarEx(interp, objPtr, part2Ptr,
+ TCL_LEAVE_ERR_MSG, "read", 1, 1, &arrayPtr);
+ if (varPtr) {
+ cleanup = ((part2Ptr == NULL)? 1 : 2);
+ goto doIncrVar;
+ } else {
Tcl_AddObjErrorInfo(interp,
- "\n (reading value of variable to increment)", -1);
- CACHE_STACK_INFO();
+ "\n (reading value of variable to increment)", -1);
TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
result = TCL_ERROR;
+ Tcl_DecrRefCount(incrPtr);
goto checkForCatch;
}
- cleanup = ((part2 == NULL)? 1 : 2);
- goto doIncrVar;
case INST_INCR_ARRAY1_IMM:
opnd = TclGetUInt1AtPtr(pc+1);
i = TclGetInt1AtPtr(pc+2);
+ incrPtr = Tcl_NewIntObj(i);
+ Tcl_IncrRefCount(incrPtr);
pcAdjustment = 3;
doIncrArray:
- part2 = TclGetString(stackPtr[stackTop]);
- arrayPtr = &(varFramePtr->compiledLocals[opnd]);
- part1 = arrayPtr->name;
+ part1Ptr = NULL;
+ part2Ptr = OBJ_AT_TOS;
+ arrayPtr = &(compiledLocals[opnd]);
+ cleanup = 1;
while (TclIsVarLink(arrayPtr)) {
arrayPtr = arrayPtr->value.linkPtr;
}
- TRACE(("%u \"%.30s\" (by %ld) => ",
- opnd, part2, i));
- varPtr = TclLookupArrayElement(interp, part1, part2,
- TCL_LEAVE_ERR_MSG, "read", 0, 1, arrayPtr);
- if (varPtr == NULL) {
+ TRACE(("%u \"%.30s\" (by %ld) => ", opnd, O2S(part2Ptr), i));
+ varPtr = TclLookupArrayElement(interp, part1Ptr, part2Ptr,
+ TCL_LEAVE_ERR_MSG, "read", 1, 1, arrayPtr, opnd);
+ if (varPtr) {
+ goto doIncrVar;
+ } else {
TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
result = TCL_ERROR;
+ Tcl_DecrRefCount(incrPtr);
goto checkForCatch;
}
- cleanup = 1;
- goto doIncrVar;
case INST_INCR_SCALAR1_IMM:
opnd = TclGetUInt1AtPtr(pc+1);
i = TclGetInt1AtPtr(pc+2);
pcAdjustment = 3;
+ cleanup = 0;
+ varPtr = &(compiledLocals[opnd]);
+ while (TclIsVarLink(varPtr)) {
+ varPtr = varPtr->value.linkPtr;
+ }
+
+ if (TclIsVarDirectModifyable(varPtr)) {
+ ClientData ptr;
+ int type;
+
+ objPtr = varPtr->value.objPtr;
+ if (GetNumberFromObj(NULL, objPtr, &ptr, &type) == TCL_OK) {
+ if (type == TCL_NUMBER_LONG) {
+ long augend = *((const long *)ptr);
+ long sum = augend + i;
+
+ /*
+ * Overflow when (augend and sum have different sign) and
+ * (augend and i have the same sign). This is encapsulated
+ * in the Overflowing macro.
+ */
+
+ if (!Overflowing(augend, i, sum)) {
+ TRACE(("%u %ld => ", opnd, i));
+ if (Tcl_IsShared(objPtr)) {
+ objPtr->refCount--; /* We know it's shared. */
+ TclNewLongObj(objResultPtr, sum);
+ Tcl_IncrRefCount(objResultPtr);
+ varPtr->value.objPtr = objResultPtr;
+ } else {
+ objResultPtr = objPtr;
+ TclSetLongObj(objPtr, sum);
+ }
+ goto doneIncr;
+ }
+#ifndef NO_WIDE_TYPE
+ {
+ w = (Tcl_WideInt)augend;
+
+ TRACE(("%u %ld => ", opnd, i));
+ if (Tcl_IsShared(objPtr)) {
+ objPtr->refCount--; /* We know it's shared. */
+ objResultPtr = Tcl_NewWideIntObj(w+i);
+ Tcl_IncrRefCount(objResultPtr);
+ varPtr->value.objPtr = objResultPtr;
+ } else {
+ objResultPtr = objPtr;
+
+ /*
+ * We know the sum value is outside the long
+ * range; use macro form that doesn't range test
+ * again.
+ */
+
+ TclSetWideIntObj(objPtr, w+i);
+ }
+ goto doneIncr;
+ }
+#endif
+ } /* end if (type == TCL_NUMBER_LONG) */
+#ifndef NO_WIDE_TYPE
+ if (type == TCL_NUMBER_WIDE) {
+ Tcl_WideInt sum;
+ w = *((const Tcl_WideInt *)ptr);
+ sum = w + i;
+
+ /*
+ * Check for overflow.
+ */
+
+ if (!Overflowing(w, i, sum)) {
+ TRACE(("%u %ld => ", opnd, i));
+ if (Tcl_IsShared(objPtr)) {
+ objPtr->refCount--; /* We know it's shared. */
+ objResultPtr = Tcl_NewWideIntObj(sum);
+ Tcl_IncrRefCount(objResultPtr);
+ varPtr->value.objPtr = objResultPtr;
+ } else {
+ objResultPtr = objPtr;
+
+ /*
+ * We *do not* know the sum value is outside the
+ * long range (wide + long can yield long); use
+ * the function call that checks range.
+ */
+
+ Tcl_SetWideIntObj(objPtr, sum);
+ }
+ goto doneIncr;
+ }
+ }
+#endif
+ }
+ if (Tcl_IsShared(objPtr)) {
+ objPtr->refCount--; /* We know it's shared */
+ objResultPtr = Tcl_DuplicateObj(objPtr);
+ Tcl_IncrRefCount(objResultPtr);
+ varPtr->value.objPtr = objResultPtr;
+ } else {
+ objResultPtr = objPtr;
+ }
+ TclNewLongObj(incrPtr, i);
+ result = TclIncrObj(interp, objResultPtr, incrPtr);
+ Tcl_DecrRefCount(incrPtr);
+ if (result == TCL_OK) {
+ goto doneIncr;
+ } else {
+ TRACE_APPEND(("ERROR: %.30s\n",
+ O2S(Tcl_GetObjResult(interp))));
+ goto checkForCatch;
+ }
+ }
+
+ /*
+ * All other cases, flow through to generic handling.
+ */
+
+ TclNewLongObj(incrPtr, i);
+ Tcl_IncrRefCount(incrPtr);
doIncrScalar:
- varPtr = &(varFramePtr->compiledLocals[opnd]);
- part1 = varPtr->name;
+ varPtr = &(compiledLocals[opnd]);
while (TclIsVarLink(varPtr)) {
varPtr = varPtr->value.linkPtr;
}
arrayPtr = NULL;
- part2 = NULL;
+ part1Ptr = part2Ptr = NULL;
cleanup = 0;
TRACE(("%u %ld => ", opnd, i));
-
doIncrVar:
- objPtr = varPtr->value.objPtr;
- if (TclIsVarScalar(varPtr)
- && !TclIsVarUndefined(varPtr)
- && (varPtr->tracePtr == NULL)
- && ((arrayPtr == NULL)
- || (arrayPtr->tracePtr == NULL))
- && (objPtr->typePtr == &tclIntType)) {
- /*
- * No errors, no traces, the variable already has an
- * integer value: inline processing.
- */
-
- i += objPtr->internalRep.longValue;
+ if (TclIsVarDirectModifyable2(varPtr, arrayPtr)) {
+ objPtr = varPtr->value.objPtr;
if (Tcl_IsShared(objPtr)) {
- objResultPtr = Tcl_NewLongObj(i);
- TclDecrRefCount(objPtr);
+ objPtr->refCount--; /* We know it's shared */
+ objResultPtr = Tcl_DuplicateObj(objPtr);
Tcl_IncrRefCount(objResultPtr);
varPtr->value.objPtr = objResultPtr;
} else {
- Tcl_SetLongObj(objPtr, i);
objResultPtr = objPtr;
}
- TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
+ result = TclIncrObj(interp, objResultPtr, incrPtr);
+ Tcl_DecrRefCount(incrPtr);
+ if (result == TCL_OK) {
+ goto doneIncr;
+ } else {
+ TRACE_APPEND(("ERROR: %.30s\n",
+ O2S(Tcl_GetObjResult(interp))));
+ goto checkForCatch;
+ }
} else {
DECACHE_STACK_INFO();
- objResultPtr = TclPtrIncrVar(interp, varPtr, arrayPtr, part1,
- part2, i, TCL_LEAVE_ERR_MSG);
+ objResultPtr = TclPtrIncrObjVar(interp, varPtr, arrayPtr,
+ part1Ptr, part2Ptr, incrPtr, TCL_LEAVE_ERR_MSG, opnd);
CACHE_STACK_INFO();
+ Tcl_DecrRefCount(incrPtr);
if (objResultPtr == NULL) {
- TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
+ TRACE_APPEND(("ERROR: %.30s\n",
+ O2S(Tcl_GetObjResult(interp))));
result = TCL_ERROR;
goto checkForCatch;
}
}
+ doneIncr:
TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
#ifndef TCL_COMPILE_DEBUG
if (*(pc+pcAdjustment) == INST_POP) {
@@ -2265,250 +3330,532 @@ TclExecuteByteCode(interp, codePtr)
}
#endif
NEXT_INST_V(pcAdjustment, cleanup, 1);
-
+ }
+
/*
- * End of INST_INCR instructions.
+ * End of INST_INCR instructions.
* ---------------------------------------------------------
*/
+ /*
+ * ---------------------------------------------------------
+ * Start of INST_EXIST instructions.
+ */
+ {
+ Tcl_Obj *part1Ptr, *part2Ptr;
+ Var *varPtr, *arrayPtr;
- case INST_JUMP1:
- opnd = TclGetInt1AtPtr(pc+1);
- TRACE(("%d => new pc %u\n", opnd,
- (unsigned int)(pc + opnd - codePtr->codeStart)));
- NEXT_INST_F(opnd, 0, 0);
+ case INST_EXIST_SCALAR: {
+ int opnd = TclGetUInt4AtPtr(pc+1);
- case INST_JUMP4:
- opnd = TclGetInt4AtPtr(pc+1);
- TRACE(("%d => new pc %u\n", opnd,
- (unsigned int)(pc + opnd - codePtr->codeStart)));
- NEXT_INST_F(opnd, 0, 0);
+ varPtr = &(compiledLocals[opnd]);
+ while (TclIsVarLink(varPtr)) {
+ varPtr = varPtr->value.linkPtr;
+ }
+ TRACE(("%u => ", opnd));
+ if (ReadTraced(varPtr)) {
+ DECACHE_STACK_INFO();
+ TclObjCallVarTraces(iPtr, NULL, varPtr, NULL, NULL,
+ TCL_TRACE_READS, 0, opnd);
+ CACHE_STACK_INFO();
+ if (TclIsVarUndefined(varPtr)) {
+ TclCleanupVar(varPtr, NULL);
+ varPtr = NULL;
+ }
+ }
- case INST_JUMP_FALSE4:
- opnd = 5; /* TRUE */
- pcAdjustment = TclGetInt4AtPtr(pc+1); /* FALSE */
- goto doJumpTrue;
+ /*
+ * Tricky! Arrays always exist.
+ */
- case INST_JUMP_TRUE4:
- opnd = TclGetInt4AtPtr(pc+1); /* TRUE */
- pcAdjustment = 5; /* FALSE */
- goto doJumpTrue;
+ objResultPtr = constants[!varPtr || TclIsVarUndefined(varPtr) ? 0 : 1];
+ TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
+ NEXT_INST_F(5, 0, 1);
+ }
- case INST_JUMP_FALSE1:
- opnd = 2; /* TRUE */
- pcAdjustment = TclGetInt1AtPtr(pc+1); /* FALSE */
- goto doJumpTrue;
+ case INST_EXIST_ARRAY: {
+ int opnd = TclGetUInt4AtPtr(pc+1);
+
+ part2Ptr = OBJ_AT_TOS;
+ arrayPtr = &(compiledLocals[opnd]);
+ while (TclIsVarLink(arrayPtr)) {
+ arrayPtr = arrayPtr->value.linkPtr;
+ }
+ TRACE(("%u \"%.30s\" => ", opnd, O2S(part2Ptr)));
+ if (TclIsVarArray(arrayPtr) && !ReadTraced(arrayPtr)) {
+ varPtr = VarHashFindVar(arrayPtr->value.tablePtr, part2Ptr);
+ if (!varPtr || !ReadTraced(varPtr)) {
+ goto doneExistArray;
+ }
+ }
+ varPtr = TclLookupArrayElement(interp, NULL, part2Ptr, 0, "access",
+ 0, 1, arrayPtr, opnd);
+ if (varPtr) {
+ if (ReadTraced(varPtr) || (arrayPtr && ReadTraced(arrayPtr))) {
+ DECACHE_STACK_INFO();
+ TclObjCallVarTraces(iPtr, arrayPtr, varPtr, NULL, part2Ptr,
+ TCL_TRACE_READS, 0, opnd);
+ CACHE_STACK_INFO();
+ }
+ if (TclIsVarUndefined(varPtr)) {
+ TclCleanupVar(varPtr, arrayPtr);
+ varPtr = NULL;
+ }
+ }
+ doneExistArray:
+ objResultPtr = constants[!varPtr || TclIsVarUndefined(varPtr) ? 0 : 1];
+ TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
+ NEXT_INST_F(5, 1, 1);
+ }
+
+ case INST_EXIST_ARRAY_STK:
+ cleanup = 2;
+ part2Ptr = OBJ_AT_TOS; /* element name */
+ part1Ptr = OBJ_UNDER_TOS; /* array name */
+ TRACE(("\"%.30s(%.30s)\" => ", O2S(part1Ptr), O2S(part2Ptr)));
+ goto doExistStk;
+
+ case INST_EXIST_STK:
+ cleanup = 1;
+ part2Ptr = NULL;
+ part1Ptr = OBJ_AT_TOS; /* variable name */
+ TRACE(("\"%.30s\" => ", O2S(part1Ptr)));
+
+ doExistStk:
+ varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, 0, "access",
+ /*createPart1*/0, /*createPart2*/1, &arrayPtr);
+ if (varPtr) {
+ if (ReadTraced(varPtr) || (arrayPtr && ReadTraced(arrayPtr))) {
+ DECACHE_STACK_INFO();
+ TclObjCallVarTraces(iPtr, arrayPtr, varPtr, part1Ptr,part2Ptr,
+ TCL_TRACE_READS, 0, -1);
+ CACHE_STACK_INFO();
+ }
+ if (TclIsVarUndefined(varPtr)) {
+ TclCleanupVar(varPtr, arrayPtr);
+ varPtr = NULL;
+ }
+ }
+ objResultPtr = constants[!varPtr || TclIsVarUndefined(varPtr) ? 0 : 1];
+ TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
+ NEXT_INST_V(1, cleanup, 1);
+ }
+
+ /*
+ * End of INST_EXIST instructions.
+ * ---------------------------------------------------------
+ */
+
+ case INST_UPVAR: {
+ int opnd;
+ Var *varPtr, *otherPtr;
+
+ TRACE_WITH_OBJ(("upvar "), OBJ_UNDER_TOS);
- case INST_JUMP_TRUE1:
- opnd = TclGetInt1AtPtr(pc+1); /* TRUE */
- pcAdjustment = 2; /* FALSE */
-
- doJumpTrue:
{
- int b;
-
- valuePtr = stackPtr[stackTop];
- if (valuePtr->typePtr == &tclIntType) {
- b = (valuePtr->internalRep.longValue != 0);
- } else if (valuePtr->typePtr == &tclDoubleType) {
- b = (valuePtr->internalRep.doubleValue != 0.0);
- } else if (valuePtr->typePtr == &tclWideIntType) {
- TclGetWide(w,valuePtr);
- b = (w != W0);
- } else {
- result = Tcl_GetBooleanFromObj(interp, valuePtr, &b);
- if (result != TCL_OK) {
- TRACE_WITH_OBJ(("%d => ERROR: ", opnd), Tcl_GetObjResult(interp));
- goto checkForCatch;
+ CallFrame *framePtr, *savedFramePtr;
+
+ result = TclObjGetFrame(interp, OBJ_UNDER_TOS, &framePtr);
+ if (result != -1) {
+ /*
+ * Locate the other variable.
+ */
+
+ savedFramePtr = iPtr->varFramePtr;
+ iPtr->varFramePtr = framePtr;
+ otherPtr = TclObjLookupVarEx(interp, OBJ_AT_TOS, NULL,
+ (TCL_LEAVE_ERR_MSG), "access",
+ /*createPart1*/ 1, /*createPart2*/ 1, &varPtr);
+ iPtr->varFramePtr = savedFramePtr;
+ if (otherPtr) {
+ result = TCL_OK;
+ goto doLinkVars;
}
}
-#ifndef TCL_COMPILE_DEBUG
- NEXT_INST_F((b? opnd : pcAdjustment), 1, 0);
-#else
- if (b) {
- if ((*pc == INST_JUMP_TRUE1) || (*pc == INST_JUMP_TRUE1)) {
- TRACE(("%d => %.20s true, new pc %u\n", opnd, O2S(valuePtr),
- (unsigned int)(pc+opnd - codePtr->codeStart)));
- } else {
- TRACE(("%d => %.20s true\n", pcAdjustment, O2S(valuePtr)));
- }
- NEXT_INST_F(opnd, 1, 0);
- } else {
- if ((*pc == INST_JUMP_TRUE1) || (*pc == INST_JUMP_TRUE1)) {
- TRACE(("%d => %.20s false\n", opnd, O2S(valuePtr)));
- } else {
- opnd = pcAdjustment;
- TRACE(("%d => %.20s false, new pc %u\n", opnd, O2S(valuePtr),
- (unsigned int)(pc + opnd - codePtr->codeStart)));
+ result = TCL_ERROR;
+ goto checkForCatch;
+ }
+
+ case INST_VARIABLE:
+ TRACE(("variable "));
+ otherPtr = TclObjLookupVarEx(interp, OBJ_AT_TOS, NULL,
+ (TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG), "access",
+ /*createPart1*/ 1, /*createPart2*/ 1, &varPtr);
+ if (otherPtr) {
+ /*
+ * Do the [variable] magic.
+ */
+
+ TclSetVarNamespaceVar(otherPtr);
+ result = TCL_OK;
+ goto doLinkVars;
+ }
+ result = TCL_ERROR;
+ goto checkForCatch;
+
+ case INST_NSUPVAR:
+ TRACE_WITH_OBJ(("nsupvar "), OBJ_UNDER_TOS);
+
+ {
+ Tcl_Namespace *nsPtr, *savedNsPtr;
+
+ result = TclGetNamespaceFromObj(interp, OBJ_UNDER_TOS, &nsPtr);
+ if (result == TCL_OK) {
+ /*
+ * Locate the other variable.
+ */
+
+ savedNsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr;
+ iPtr->varFramePtr->nsPtr = (Namespace *) nsPtr;
+ otherPtr = TclObjLookupVarEx(interp, OBJ_AT_TOS, NULL,
+ (TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG), "access",
+ /*createPart1*/ 1, /*createPart2*/ 1, &varPtr);
+ iPtr->varFramePtr->nsPtr = (Namespace *) savedNsPtr;
+ if (otherPtr) {
+ goto doLinkVars;
}
- NEXT_INST_F(pcAdjustment, 1, 0);
}
-#endif
+ result = TCL_ERROR;
+ goto checkForCatch;
}
-
- case INST_LOR:
- case INST_LAND:
- {
+
+ doLinkVars:
+
/*
- * Operands must be boolean or numeric. No int->double
- * conversions are performed.
+ * If we are here, the local variable has already been created: do the
+ * little work of TclPtrMakeUpvar that remains to be done right here
+ * if there are no errors; otherwise, let it handle the case.
*/
-
- int i1, i2;
- int iResult;
- char *s;
- Tcl_ObjType *t1Ptr, *t2Ptr;
-
- value2Ptr = stackPtr[stackTop];
- valuePtr = stackPtr[stackTop - 1];;
- t1Ptr = valuePtr->typePtr;
- t2Ptr = value2Ptr->typePtr;
-
- if ((t1Ptr == &tclIntType) || (t1Ptr == &tclBooleanType)) {
- i1 = (valuePtr->internalRep.longValue != 0);
- } else if (t1Ptr == &tclWideIntType) {
- TclGetWide(w,valuePtr);
- i1 = (w != W0);
- } else if (t1Ptr == &tclDoubleType) {
- i1 = (valuePtr->internalRep.doubleValue != 0.0);
- } else {
- s = Tcl_GetStringFromObj(valuePtr, &length);
- if (TclLooksLikeInt(s, length)) {
- GET_WIDE_OR_INT(result, valuePtr, i, w);
- if (valuePtr->typePtr == &tclIntType) {
- i1 = (i != 0);
- } else {
- i1 = (w != W0);
+
+ opnd = TclGetInt4AtPtr(pc+1);;
+ varPtr = &(compiledLocals[opnd]);
+ if ((varPtr != otherPtr) && !TclIsVarTraced(varPtr)
+ && (TclIsVarUndefined(varPtr) || TclIsVarLink(varPtr))) {
+ if (!TclIsVarUndefined(varPtr)) {
+ /*
+ * Then it is a defined link.
+ */
+
+ Var *linkPtr = varPtr->value.linkPtr;
+
+ if (linkPtr == otherPtr) {
+ goto doLinkVarsDone;
}
- } else {
- result = Tcl_GetBooleanFromObj((Tcl_Interp *) NULL,
- valuePtr, &i1);
- i1 = (i1 != 0);
+ if (TclIsVarInHash(linkPtr)) {
+ VarHashRefCount(linkPtr)--;
+ if (TclIsVarUndefined(linkPtr)) {
+ TclCleanupVar(linkPtr, NULL);
+ }
+ }
+ }
+ TclSetVarLink(varPtr);
+ varPtr->value.linkPtr = otherPtr;
+ if (TclIsVarInHash(otherPtr)) {
+ VarHashRefCount(otherPtr)++;
}
+ } else {
+ result = TclPtrObjMakeUpvar(interp, otherPtr, NULL, 0, opnd);
if (result != TCL_OK) {
- TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr),
- (t1Ptr? t1Ptr->name : "null")));
- DECACHE_STACK_INFO();
- IllegalExprOperandType(interp, pc, valuePtr);
- CACHE_STACK_INFO();
goto checkForCatch;
}
}
-
- if ((t2Ptr == &tclIntType) || (t2Ptr == &tclBooleanType)) {
- i2 = (value2Ptr->internalRep.longValue != 0);
- } else if (t2Ptr == &tclWideIntType) {
- TclGetWide(w,value2Ptr);
- i2 = (w != W0);
- } else if (t2Ptr == &tclDoubleType) {
- i2 = (value2Ptr->internalRep.doubleValue != 0.0);
- } else {
- s = Tcl_GetStringFromObj(value2Ptr, &length);
- if (TclLooksLikeInt(s, length)) {
- GET_WIDE_OR_INT(result, value2Ptr, i, w);
- if (value2Ptr->typePtr == &tclIntType) {
- i2 = (i != 0);
- } else {
- i2 = (w != W0);
- }
+
+ /*
+ * Do not pop the namespace or frame index, it may be needed for other
+ * variables - and [variable] did not push it at all.
+ */
+
+ doLinkVarsDone:
+ NEXT_INST_F(5, 1, 0);
+ }
+
+ case INST_JUMP1: {
+ int opnd = TclGetInt1AtPtr(pc+1);
+
+ TRACE(("%d => new pc %u\n", opnd,
+ (unsigned)(pc + opnd - codePtr->codeStart)));
+ NEXT_INST_F(opnd, 0, 0);
+ }
+
+ case INST_JUMP4: {
+ int opnd = TclGetInt4AtPtr(pc+1);
+
+ TRACE(("%d => new pc %u\n", opnd,
+ (unsigned)(pc + opnd - codePtr->codeStart)));
+ NEXT_INST_F(opnd, 0, 0);
+ }
+
+ {
+ int jmpOffset[2], b;
+ Tcl_Obj *valuePtr;
+
+ /* TODO: consider rewrite so we don't compute the offset we're not
+ * going to take. */
+ case INST_JUMP_FALSE4:
+ jmpOffset[0] = TclGetInt4AtPtr(pc+1); /* FALSE offset */
+ jmpOffset[1] = 5; /* TRUE offset*/
+ goto doCondJump;
+
+ case INST_JUMP_TRUE4:
+ jmpOffset[0] = 5;
+ jmpOffset[1] = TclGetInt4AtPtr(pc+1);
+ goto doCondJump;
+
+ case INST_JUMP_FALSE1:
+ jmpOffset[0] = TclGetInt1AtPtr(pc+1);
+ jmpOffset[1] = 2;
+ goto doCondJump;
+
+ case INST_JUMP_TRUE1:
+ jmpOffset[0] = 2;
+ jmpOffset[1] = TclGetInt1AtPtr(pc+1);
+
+ doCondJump:
+ valuePtr = OBJ_AT_TOS;
+
+ /* TODO - check claim that taking address of b harms performance */
+ /* TODO - consider optimization search for constants */
+ result = TclGetBooleanFromObj(interp, valuePtr, &b);
+ if (result != TCL_OK) {
+ TRACE_WITH_OBJ(("%d => ERROR: ", jmpOffset[
+ ((*pc == INST_JUMP_FALSE1) || (*pc == INST_JUMP_FALSE4))
+ ? 0 : 1]), Tcl_GetObjResult(interp));
+ goto checkForCatch;
+ }
+
+#ifdef TCL_COMPILE_DEBUG
+ if (b) {
+ if ((*pc == INST_JUMP_TRUE1) || (*pc == INST_JUMP_TRUE4)) {
+ TRACE(("%d => %.20s true, new pc %u\n", jmpOffset[1],
+ O2S(valuePtr),
+ (unsigned)(pc + jmpOffset[1] - codePtr->codeStart)));
} else {
- result = Tcl_GetBooleanFromObj((Tcl_Interp *) NULL, value2Ptr, &i2);
+ TRACE(("%d => %.20s true\n", jmpOffset[0], O2S(valuePtr)));
}
- if (result != TCL_OK) {
- TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(value2Ptr),
- (t2Ptr? t2Ptr->name : "null")));
- DECACHE_STACK_INFO();
- IllegalExprOperandType(interp, pc, value2Ptr);
- CACHE_STACK_INFO();
- goto checkForCatch;
+ } else {
+ if ((*pc == INST_JUMP_TRUE1) || (*pc == INST_JUMP_TRUE4)) {
+ TRACE(("%d => %.20s false\n", jmpOffset[0], O2S(valuePtr)));
+ } else {
+ TRACE(("%d => %.20s false, new pc %u\n", jmpOffset[0],
+ O2S(valuePtr),
+ (unsigned)(pc + jmpOffset[1] - codePtr->codeStart)));
}
}
+#endif
+ NEXT_INST_F(jmpOffset[b], 1, 0);
+ }
+
+ case INST_JUMP_TABLE: {
+ Tcl_HashEntry *hPtr;
+ JumptableInfo *jtPtr;
+ int opnd;
+
+ /*
+ * Jump to location looked up in a hashtable; fall through to next
+ * instr if lookup fails.
+ */
+
+ opnd = TclGetInt4AtPtr(pc+1);
+ jtPtr = (JumptableInfo *) codePtr->auxDataArrayPtr[opnd].clientData;
+ TRACE(("%d => %.20s ", opnd, O2S(OBJ_AT_TOS)));
+ hPtr = Tcl_FindHashEntry(&jtPtr->hashTable, TclGetString(OBJ_AT_TOS));
+ if (hPtr != NULL) {
+ int jumpOffset = PTR2INT(Tcl_GetHashValue(hPtr));
+
+ TRACE_APPEND(("found in table, new pc %u\n",
+ (unsigned)(pc - codePtr->codeStart + jumpOffset)));
+ NEXT_INST_F(jumpOffset, 1, 0);
+ } else {
+ TRACE_APPEND(("not found in table\n"));
+ NEXT_INST_F(5, 1, 0);
+ }
+ }
+
+ /*
+ * These two instructions are now redundant: the complete logic of the LOR
+ * and LAND is now handled by the expression compiler.
+ */
+ case INST_LOR:
+ case INST_LAND: {
/*
- * Reuse the valuePtr object already on stack if possible.
+ * Operands must be boolean or numeric. No int->double conversions are
+ * performed.
*/
-
+
+ int i1, i2, iResult;
+ Tcl_Obj *value2Ptr = OBJ_AT_TOS;
+ Tcl_Obj *valuePtr = OBJ_UNDER_TOS;
+
+ result = TclGetBooleanFromObj(NULL, valuePtr, &i1);
+ if (result != TCL_OK) {
+ TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr),
+ (valuePtr->typePtr? valuePtr->typePtr->name : "null")));
+ DECACHE_STACK_INFO();
+ IllegalExprOperandType(interp, pc, valuePtr);
+ CACHE_STACK_INFO();
+ goto checkForCatch;
+ }
+
+ result = TclGetBooleanFromObj(NULL, value2Ptr, &i2);
+ if (result != TCL_OK) {
+ TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(value2Ptr),
+ (value2Ptr->typePtr? value2Ptr->typePtr->name : "null")));
+ DECACHE_STACK_INFO();
+ IllegalExprOperandType(interp, pc, value2Ptr);
+ CACHE_STACK_INFO();
+ goto checkForCatch;
+ }
+
if (*pc == INST_LOR) {
iResult = (i1 || i2);
} else {
iResult = (i1 && i2);
}
- if (Tcl_IsShared(valuePtr)) {
- objResultPtr = Tcl_NewLongObj(iResult);
- TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), iResult));
- NEXT_INST_F(1, 2, 1);
- } else { /* reuse the valuePtr object */
- TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), iResult));
- Tcl_SetLongObj(valuePtr, iResult);
- NEXT_INST_F(1, 1, 0);
- }
+ objResultPtr = constants[iResult];
+ TRACE(("%.20s %.20s => %d\n", O2S(valuePtr),O2S(value2Ptr),iResult));
+ NEXT_INST_F(1, 2, 1);
}
/*
* ---------------------------------------------------------
- * Start of INST_LIST and related instructions.
+ * Start of INST_LIST and related instructions.
*/
- case INST_LIST:
+ case INST_LIST: {
/*
- * Pop the opnd (objc) top stack elements into a new list obj
- * and then decrement their ref counts.
+ * Pop the opnd (objc) top stack elements into a new list obj and then
+ * decrement their ref counts.
*/
+ int opnd;
+
opnd = TclGetUInt4AtPtr(pc+1);
- objResultPtr = Tcl_NewListObj(opnd, &(stackPtr[stackTop - (opnd-1)]));
+ objResultPtr = Tcl_NewListObj(opnd, &OBJ_AT_DEPTH(opnd-1));
TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
NEXT_INST_V(5, opnd, 1);
+ }
- case INST_LIST_LENGTH:
- valuePtr = stackPtr[stackTop];
+ case INST_LIST_LENGTH: {
+ Tcl_Obj *valuePtr;
+ int length;
- result = Tcl_ListObjLength(interp, valuePtr, &length);
- if (result != TCL_OK) {
+ valuePtr = OBJ_AT_TOS;
+
+ result = TclListObjLength(interp, valuePtr, &length);
+ if (result == TCL_OK) {
+ TclNewIntObj(objResultPtr, length);
+ TRACE(("%.20s => %d\n", O2S(valuePtr), length));
+ NEXT_INST_F(1, 1, 1);
+ } else {
TRACE_WITH_OBJ(("%.30s => ERROR: ", O2S(valuePtr)),
- Tcl_GetObjResult(interp));
+ Tcl_GetObjResult(interp));
goto checkForCatch;
}
- objResultPtr = Tcl_NewIntObj(length);
- TRACE(("%.20s => %d\n", O2S(valuePtr), length));
- NEXT_INST_F(1, 1, 1);
-
- case INST_LIST_INDEX:
+ }
+
+ case INST_LIST_INDEX: {
/*** lindex with objc == 3 ***/
-
+
+ /* Variables also for INST_LIST_INDEX_IMM */
+
+ int listc, idx, opnd, pcAdjustment;
+ Tcl_Obj **listv;
+ Tcl_Obj *valuePtr, *value2Ptr;
+
/*
- * Pop the two operands
+ * Pop the two operands.
*/
- value2Ptr = stackPtr[stackTop];
- valuePtr = stackPtr[stackTop- 1];
+
+ value2Ptr = OBJ_AT_TOS;
+ valuePtr = OBJ_UNDER_TOS;
/*
- * Extract the desired list element
+ * Extract the desired list element.
*/
+
+ result = TclListObjGetElements(interp, valuePtr, &listc, &listv);
+ if ((result == TCL_OK) && (value2Ptr->typePtr != &tclListType)
+ && (TclGetIntForIndexM(NULL , value2Ptr, listc-1,
+ &idx) == TCL_OK)) {
+ TclDecrRefCount(value2Ptr);
+ tosPtr--;
+ pcAdjustment = 1;
+ goto lindexFastPath;
+ }
+
objResultPtr = TclLindexList(interp, valuePtr, value2Ptr);
- if (objResultPtr == NULL) {
- TRACE_WITH_OBJ(("%.30s %.30s => ERROR: ", O2S(valuePtr), O2S(value2Ptr)),
- Tcl_GetObjResult(interp));
+ if (objResultPtr) {
+ /*
+ * Stash the list element on the stack.
+ */
+
+ TRACE(("%.20s %.20s => %s\n",
+ O2S(valuePtr), O2S(value2Ptr), O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, -1); /* Already has the correct refCount */
+ } else {
+ TRACE_WITH_OBJ(("%.30s %.30s => ERROR: ", O2S(valuePtr),
+ O2S(value2Ptr)), Tcl_GetObjResult(interp));
result = TCL_ERROR;
goto checkForCatch;
}
+ case INST_LIST_INDEX_IMM:
+ /*** lindex with objc==3 and index in bytecode stream ***/
+
+ pcAdjustment = 5;
+
/*
- * Stash the list element on the stack
+ * Pop the list and get the index.
*/
- TRACE(("%.20s %.20s => %s\n",
- O2S(valuePtr), O2S(value2Ptr), O2S(objResultPtr)));
- NEXT_INST_F(1, 2, -1); /* already has the correct refCount */
- case INST_LIST_INDEX_MULTI:
- {
+ valuePtr = OBJ_AT_TOS;
+ opnd = TclGetInt4AtPtr(pc+1);
+
+ /*
+ * Get the contents of the list, making sure that it really is a list
+ * in the process.
+ */
+
+ result = TclListObjGetElements(interp, valuePtr, &listc, &listv);
+
+ if (result == TCL_OK) {
+ /*
+ * Select the list item based on the index. Negative operand means
+ * end-based indexing.
+ */
+
+ if (opnd < -1) {
+ idx = opnd+1 + listc;
+ } else {
+ idx = opnd;
+ }
+
+ lindexFastPath:
+ if (idx >= 0 && idx < listc) {
+ objResultPtr = listv[idx];
+ } else {
+ TclNewObj(objResultPtr);
+ }
+
+ TRACE_WITH_OBJ(("\"%.30s\" %d => ", O2S(valuePtr), opnd),
+ objResultPtr);
+ NEXT_INST_F(pcAdjustment, 1, 1);
+ } else {
+ TRACE_WITH_OBJ(("\"%.30s\" %d => ERROR: ", O2S(valuePtr), opnd),
+ Tcl_GetObjResult(interp));
+ goto checkForCatch;
+ }
+ }
+
+ case INST_LIST_INDEX_MULTI: {
/*
* 'lindex' with multiple index args:
*
* Determine the count of index args.
*/
- int numIdx;
+ int numIdx, opnd;
opnd = TclGetUInt4AtPtr(pc+1);
numIdx = opnd-1;
@@ -2516,143 +3863,318 @@ TclExecuteByteCode(interp, codePtr)
/*
* Do the 'lindex' operation.
*/
- objResultPtr = TclLindexFlat(interp, stackPtr[stackTop - numIdx],
- numIdx, stackPtr + stackTop - numIdx + 1);
+
+ objResultPtr = TclLindexFlat(interp, OBJ_AT_DEPTH(numIdx),
+ numIdx, &OBJ_AT_DEPTH(numIdx - 1));
/*
- * Check for errors
+ * Check for errors.
*/
- if (objResultPtr == NULL) {
+
+ if (objResultPtr) {
+ /*
+ * Set result.
+ */
+
+ TRACE(("%d => %s\n", opnd, O2S(objResultPtr)));
+ NEXT_INST_V(5, opnd, -1);
+ } else {
TRACE_WITH_OBJ(("%d => ERROR: ", opnd), Tcl_GetObjResult(interp));
result = TCL_ERROR;
goto checkForCatch;
}
-
- /*
- * Set result
- */
- TRACE(("%d => %s\n", opnd, O2S(objResultPtr)));
- NEXT_INST_V(5, opnd, -1);
}
- case INST_LSET_FLAT:
- {
+ case INST_LSET_FLAT: {
/*
- * Lset with 3, 5, or more args. Get the number
- * of index args.
+ * Lset with 3, 5, or more args. Get the number of index args.
*/
- int numIdx;
- opnd = TclGetUInt4AtPtr( pc + 1 );
+ int numIdx,opnd;
+ Tcl_Obj *valuePtr, *value2Ptr;
+
+ opnd = TclGetUInt4AtPtr(pc + 1);
numIdx = opnd - 2;
/*
- * Get the old value of variable, and remove the stack ref.
- * This is safe because the variable still references the
- * object; the ref count will never go zero here.
+ * Get the old value of variable, and remove the stack ref. This is
+ * safe because the variable still references the object; the ref
+ * count will never go zero here - we can use the smaller macro
+ * Tcl_DecrRefCount.
*/
+
value2Ptr = POP_OBJECT();
- TclDecrRefCount(value2Ptr); /* This one should be done here */
+ Tcl_DecrRefCount(value2Ptr); /* This one should be done here */
/*
* Get the new element value.
*/
- valuePtr = stackPtr[stackTop];
+
+ valuePtr = OBJ_AT_TOS;
/*
- * Compute the new variable value
+ * Compute the new variable value.
*/
- objResultPtr = TclLsetFlat(interp, value2Ptr, numIdx,
- stackPtr + stackTop - numIdx, valuePtr);
+ objResultPtr = TclLsetFlat(interp, value2Ptr, numIdx,
+ &OBJ_AT_DEPTH(numIdx), valuePtr);
/*
- * Check for errors
+ * Check for errors.
*/
- if (objResultPtr == NULL) {
+
+ if (objResultPtr) {
+ /*
+ * Set result.
+ */
+
+ TRACE(("%d => %s\n", opnd, O2S(objResultPtr)));
+ NEXT_INST_V(5, (numIdx+1), -1);
+ } else {
TRACE_WITH_OBJ(("%d => ERROR: ", opnd), Tcl_GetObjResult(interp));
result = TCL_ERROR;
goto checkForCatch;
}
+ }
+ case INST_LSET_LIST: {
/*
- * Set result
+ * 'lset' with 4 args.
*/
- TRACE(("%d => %s\n", opnd, O2S(objResultPtr)));
- NEXT_INST_V(5, (numIdx+1), -1);
- }
- case INST_LSET_LIST:
+ Tcl_Obj *objPtr, *valuePtr, *value2Ptr;
+
/*
- * 'lset' with 4 args.
- *
- * Get the old value of variable, and remove the stack ref.
- * This is safe because the variable still references the
- * object; the ref count will never go zero here.
+ * Get the old value of variable, and remove the stack ref. This is
+ * safe because the variable still references the object; the ref
+ * count will never go zero here - we can use the smaller macro
+ * Tcl_DecrRefCount.
*/
- objPtr = POP_OBJECT();
- TclDecrRefCount(objPtr); /* This one should be done here */
-
+
+ objPtr = POP_OBJECT();
+ Tcl_DecrRefCount(objPtr); /* This one should be done here. */
+
/*
- * Get the new element value, and the index list
+ * Get the new element value, and the index list.
*/
- valuePtr = stackPtr[stackTop];
- value2Ptr = stackPtr[stackTop - 1];
-
+
+ valuePtr = OBJ_AT_TOS;
+ value2Ptr = OBJ_UNDER_TOS;
+
/*
- * Compute the new variable value
+ * Compute the new variable value.
*/
+
objResultPtr = TclLsetList(interp, objPtr, value2Ptr, valuePtr);
/*
- * Check for errors
+ * Check for errors.
*/
- if (objResultPtr == NULL) {
+
+ if (objResultPtr) {
+ /*
+ * Set result.
+ */
+
+ TRACE(("=> %s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, -1);
+ } else {
TRACE_WITH_OBJ(("\"%.30s\" => ERROR: ", O2S(value2Ptr)),
- Tcl_GetObjResult(interp));
+ Tcl_GetObjResult(interp));
result = TCL_ERROR;
goto checkForCatch;
}
+ }
+
+ case INST_LIST_RANGE_IMM: {
+ /*** lrange with objc==4 and both indices in bytecode stream ***/
+
+ int listc, fromIdx, toIdx;
+ Tcl_Obj **listv, *valuePtr;
+
+ /*
+ * Pop the list and get the indices.
+ */
+
+ valuePtr = OBJ_AT_TOS;
+ fromIdx = TclGetInt4AtPtr(pc+1);
+ toIdx = TclGetInt4AtPtr(pc+5);
+
+ /*
+ * Get the contents of the list, making sure that it really is a list
+ * in the process.
+ */
+ result = TclListObjGetElements(interp, valuePtr, &listc, &listv);
+
+ /*
+ * Skip a lot of work if we're about to throw the result away (common
+ * with uses of [lassign]).
+ */
+
+ if (result == TCL_OK) {
+#ifndef TCL_COMPILE_DEBUG
+ if (*(pc+9) == INST_POP) {
+ NEXT_INST_F(10, 1, 0);
+ }
+#endif
+ } else {
+ TRACE_WITH_OBJ(("\"%.30s\" %d %d => ERROR: ", O2S(valuePtr),
+ fromIdx, toIdx), Tcl_GetObjResult(interp));
+ goto checkForCatch;
+ }
/*
- * Set result
+ * Adjust the indices for end-based handling.
*/
- TRACE(("=> %s\n", O2S(objResultPtr)));
- NEXT_INST_F(1, 2, -1);
+
+ if (fromIdx < -1) {
+ fromIdx += 1+listc;
+ if (fromIdx < -1) {
+ fromIdx = -1;
+ }
+ } else if (fromIdx > listc) {
+ fromIdx = listc;
+ }
+ if (toIdx < -1) {
+ toIdx += 1+listc;
+ if (toIdx < -1) {
+ toIdx = -1;
+ }
+ } else if (toIdx > listc) {
+ toIdx = listc;
+ }
+
+ /*
+ * Check if we are referring to a valid, non-empty list range, and if
+ * so, build the list of elements in that range.
+ */
+
+ if (fromIdx<=toIdx && fromIdx<listc && toIdx>=0) {
+ if (fromIdx<0) {
+ fromIdx = 0;
+ }
+ if (toIdx >= listc) {
+ toIdx = listc-1;
+ }
+ objResultPtr = Tcl_NewListObj(toIdx-fromIdx+1, listv+fromIdx);
+ } else {
+ TclNewObj(objResultPtr);
+ }
+
+ TRACE_WITH_OBJ(("\"%.30s\" %d %d => ", O2S(valuePtr),
+ TclGetInt4AtPtr(pc+1), TclGetInt4AtPtr(pc+5)), objResultPtr);
+ NEXT_INST_F(9, 1, 1);
+ }
+
+ case INST_LIST_IN:
+ case INST_LIST_NOT_IN: {
+ /*
+ * Basic list containment operators.
+ */
+
+ int found, s1len, s2len, llen, i;
+ Tcl_Obj *valuePtr, *value2Ptr, *o;
+ char *s1;
+ const char *s2;
+
+ value2Ptr = OBJ_AT_TOS;
+ valuePtr = OBJ_UNDER_TOS;
+
+ /* TODO: Consider more efficient tests than strcmp() */
+ s1 = TclGetStringFromObj(valuePtr, &s1len);
+ result = TclListObjLength(interp, value2Ptr, &llen);
+ if (result != TCL_OK) {
+ TRACE_WITH_OBJ(("\"%.30s\" \"%.30s\" => ERROR: ", O2S(valuePtr),
+ O2S(value2Ptr)), Tcl_GetObjResult(interp));
+ goto checkForCatch;
+ }
+ found = 0;
+ if (llen > 0) {
+ /*
+ * An empty list doesn't match anything.
+ */
+
+ i = 0;
+ do {
+ Tcl_ListObjIndex(NULL, value2Ptr, i, &o);
+ if (o != NULL) {
+ s2 = TclGetStringFromObj(o, &s2len);
+ } else {
+ s2 = "";
+ }
+ if (s1len == s2len) {
+ found = (strcmp(s1, s2) == 0);
+ }
+ i++;
+ } while (i < llen && found == 0);
+ }
+
+ if (*pc == INST_LIST_NOT_IN) {
+ found = !found;
+ }
+
+ TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), found));
+
+ /*
+ * Peep-hole optimisation: if you're about to jump, do jump from here.
+ * We're saving the effort of pushing a boolean value only to pop it
+ * for branching.
+ */
+
+ pc++;
+#ifndef TCL_COMPILE_DEBUG
+ switch (*pc) {
+ case INST_JUMP_FALSE1:
+ NEXT_INST_F((found ? 2 : TclGetInt1AtPtr(pc+1)), 2, 0);
+ case INST_JUMP_TRUE1:
+ NEXT_INST_F((found ? TclGetInt1AtPtr(pc+1) : 2), 2, 0);
+ case INST_JUMP_FALSE4:
+ NEXT_INST_F((found ? 5 : TclGetInt4AtPtr(pc+1)), 2, 0);
+ case INST_JUMP_TRUE4:
+ NEXT_INST_F((found ? TclGetInt4AtPtr(pc+1) : 5), 2, 0);
+ }
+#endif
+ objResultPtr = constants[found];
+ NEXT_INST_F(0, 2, 1);
+ }
/*
- * End of INST_LIST and related instructions.
+ * End of INST_LIST and related instructions.
* ---------------------------------------------------------
*/
case INST_STR_EQ:
- case INST_STR_NEQ:
- {
+ case INST_STR_NEQ: {
/*
* String (in)equality check
+ * TODO: Consider merging into INST_STR_CMP
*/
+
int iResult;
+ Tcl_Obj *valuePtr, *value2Ptr;
- value2Ptr = stackPtr[stackTop];
- valuePtr = stackPtr[stackTop - 1];
+ value2Ptr = OBJ_AT_TOS;
+ valuePtr = OBJ_UNDER_TOS;
if (valuePtr == value2Ptr) {
/*
- * On the off-chance that the objects are the same,
- * we don't really have to think hard about equality.
+ * On the off-chance that the objects are the same, we don't
+ * really have to think hard about equality.
*/
+
iResult = (*pc == INST_STR_EQ);
} else {
char *s1, *s2;
int s1len, s2len;
- s1 = Tcl_GetStringFromObj(valuePtr, &s1len);
- s2 = Tcl_GetStringFromObj(value2Ptr, &s2len);
+ s1 = TclGetStringFromObj(valuePtr, &s1len);
+ s2 = TclGetStringFromObj(value2Ptr, &s2len);
if (s1len == s2len) {
/*
- * We only need to check (in)equality when
- * we have equal length strings.
+ * We only need to check (in)equality when we have equal
+ * length strings.
*/
+
if (*pc == INST_STR_NEQ) {
iResult = (strcmp(s1, s2) != 0);
} else {
@@ -2664,63 +4186,66 @@ TclExecuteByteCode(interp, codePtr)
}
}
- TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), iResult));
+ TRACE(("%.20s %.20s => %d\n", O2S(valuePtr),O2S(value2Ptr),iResult));
/*
- * Peep-hole optimisation: if you're about to jump, do jump
- * from here.
+ * Peep-hole optimisation: if you're about to jump, do jump from here.
*/
pc++;
#ifndef TCL_COMPILE_DEBUG
switch (*pc) {
- case INST_JUMP_FALSE1:
- NEXT_INST_F((iResult? 2 : TclGetInt1AtPtr(pc+1)), 2, 0);
- case INST_JUMP_TRUE1:
- NEXT_INST_F((iResult? TclGetInt1AtPtr(pc+1) : 2), 2, 0);
- case INST_JUMP_FALSE4:
- NEXT_INST_F((iResult? 5 : TclGetInt4AtPtr(pc+1)), 2, 0);
- case INST_JUMP_TRUE4:
- NEXT_INST_F((iResult? TclGetInt4AtPtr(pc+1) : 5), 2, 0);
+ case INST_JUMP_FALSE1:
+ NEXT_INST_F((iResult? 2 : TclGetInt1AtPtr(pc+1)), 2, 0);
+ case INST_JUMP_TRUE1:
+ NEXT_INST_F((iResult? TclGetInt1AtPtr(pc+1) : 2), 2, 0);
+ case INST_JUMP_FALSE4:
+ NEXT_INST_F((iResult? 5 : TclGetInt4AtPtr(pc+1)), 2, 0);
+ case INST_JUMP_TRUE4:
+ NEXT_INST_F((iResult? TclGetInt4AtPtr(pc+1) : 5), 2, 0);
}
#endif
- objResultPtr = Tcl_NewIntObj(iResult);
+ objResultPtr = constants[iResult];
NEXT_INST_F(0, 2, 1);
}
- case INST_STR_CMP:
- {
+ case INST_STR_CMP: {
/*
- * String compare
+ * String compare.
*/
- CONST char *s1, *s2;
+
+ const char *s1, *s2;
int s1len, s2len, iResult;
+ Tcl_Obj *valuePtr, *value2Ptr;
- value2Ptr = stackPtr[stackTop];
- valuePtr = stackPtr[stackTop - 1];
+ stringCompare:
+ value2Ptr = OBJ_AT_TOS;
+ valuePtr = OBJ_UNDER_TOS;
/*
- * The comparison function should compare up to the
- * minimum byte length only.
+ * The comparison function should compare up to the minimum byte
+ * length only.
*/
+
if (valuePtr == value2Ptr) {
/*
- * In the pure equality case, set lengths too for
- * the checks below (or we could goto beyond it).
+ * In the pure equality case, set lengths too for the checks below
+ * (or we could goto beyond it).
*/
+
iResult = s1len = s2len = 0;
} else if ((valuePtr->typePtr == &tclByteArrayType)
- && (value2Ptr->typePtr == &tclByteArrayType)) {
+ && (value2Ptr->typePtr == &tclByteArrayType)) {
s1 = (char *) Tcl_GetByteArrayFromObj(valuePtr, &s1len);
s2 = (char *) Tcl_GetByteArrayFromObj(value2Ptr, &s2len);
- iResult = memcmp(s1, s2,
- (size_t) ((s1len < s2len) ? s1len : s2len));
+ iResult = memcmp(s1, s2,
+ (size_t) ((s1len < s2len) ? s1len : s2len));
} else if (((valuePtr->typePtr == &tclStringType)
- && (value2Ptr->typePtr == &tclStringType))) {
+ && (value2Ptr->typePtr == &tclStringType))) {
/*
* Do a unicode-specific comparison if both of the args are of
- * String type. If the char length == byte length, we can do a
- * memcmp. In benchmark testing this proved the most efficient
+ * String type. If the char length == byte length, we can do a
+ * memcmp. In benchmark testing this proved the most efficient
* check between the unicode and string comparison operations.
*/
@@ -2736,64 +4261,96 @@ TclExecuteByteCode(interp, codePtr)
}
} else {
/*
- * We can't do a simple memcmp in order to handle the
- * special Tcl \xC0\x80 null encoding for utf-8.
+ * We can't do a simple memcmp in order to handle the special Tcl
+ * \xC0\x80 null encoding for utf-8.
*/
- s1 = Tcl_GetStringFromObj(valuePtr, &s1len);
- s2 = Tcl_GetStringFromObj(value2Ptr, &s2len);
+
+ s1 = TclGetStringFromObj(valuePtr, &s1len);
+ s2 = TclGetStringFromObj(value2Ptr, &s2len);
iResult = TclpUtfNcmp2(s1, s2,
- (size_t) ((s1len < s2len) ? s1len : s2len));
+ (size_t) ((s1len < s2len) ? s1len : s2len));
}
/*
* Make sure only -1,0,1 is returned
+ * TODO: consider peephole opt.
*/
+
if (iResult == 0) {
iResult = s1len - s2len;
}
+
+ if (*pc != INST_STR_CMP) {
+ /*
+ * Take care of the opcodes that goto'ed into here.
+ */
+
+ switch (*pc) {
+ case INST_EQ:
+ iResult = (iResult == 0);
+ break;
+ case INST_NEQ:
+ iResult = (iResult != 0);
+ break;
+ case INST_LT:
+ iResult = (iResult < 0);
+ break;
+ case INST_GT:
+ iResult = (iResult > 0);
+ break;
+ case INST_LE:
+ iResult = (iResult <= 0);
+ break;
+ case INST_GE:
+ iResult = (iResult >= 0);
+ break;
+ }
+ }
if (iResult < 0) {
- iResult = -1;
- } else if (iResult > 0) {
- iResult = 1;
+ TclNewIntObj(objResultPtr, -1);
+ TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), -1));
+ } else {
+ objResultPtr = constants[(iResult>0)];
+ TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr),
+ (iResult > 0)));
}
- objResultPtr = Tcl_NewIntObj(iResult);
- TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), iResult));
NEXT_INST_F(1, 2, 1);
}
- case INST_STR_LEN:
- {
- int length1;
-
- valuePtr = stackPtr[stackTop];
+ case INST_STR_LEN: {
+ int length;
+ Tcl_Obj *valuePtr;
+
+ valuePtr = OBJ_AT_TOS;
if (valuePtr->typePtr == &tclByteArrayType) {
- (void) Tcl_GetByteArrayFromObj(valuePtr, &length1);
+ (void) Tcl_GetByteArrayFromObj(valuePtr, &length);
} else {
- length1 = Tcl_GetCharLength(valuePtr);
+ length = Tcl_GetCharLength(valuePtr);
}
- objResultPtr = Tcl_NewIntObj(length1);
- TRACE(("%.20s => %d\n", O2S(valuePtr), length1));
+ TclNewIntObj(objResultPtr, length);
+ TRACE(("%.20s => %d\n", O2S(valuePtr), length));
NEXT_INST_F(1, 1, 1);
}
-
- case INST_STR_INDEX:
- {
+
+ case INST_STR_INDEX: {
/*
- * String compare
+ * String compare.
*/
- int index;
- bytes = NULL; /* lint */
- value2Ptr = stackPtr[stackTop];
- valuePtr = stackPtr[stackTop - 1];
+ int index, length;
+ char *bytes;
+ Tcl_Obj *valuePtr, *value2Ptr;
+
+ bytes = NULL; /* lint */
+ value2Ptr = OBJ_AT_TOS;
+ valuePtr = OBJ_UNDER_TOS;
/*
- * If we have a ByteArray object, avoid indexing in the
- * Utf string since the byte array contains one byte per
- * character. Otherwise, use the Unicode string rep to
- * get the index'th char.
+ * If we have a ByteArray object, avoid indexing in the Utf string
+ * since the byte array contains one byte per character. Otherwise,
+ * use the Unicode string rep to get the index'th char.
*/
if (valuePtr->typePtr == &tclByteArrayType) {
@@ -2802,10 +4359,11 @@ TclExecuteByteCode(interp, codePtr)
/*
* Get Unicode char length to calulate what 'end' means.
*/
+
length = Tcl_GetCharLength(valuePtr);
}
- result = TclGetIntForIndex(interp, value2Ptr, length - 1, &index);
+ result = TclGetIntForIndexM(interp, value2Ptr, length - 1, &index);
if (result != TCL_OK) {
goto checkForCatch;
}
@@ -2813,21 +4371,22 @@ TclExecuteByteCode(interp, codePtr)
if ((index >= 0) && (index < length)) {
if (valuePtr->typePtr == &tclByteArrayType) {
objResultPtr = Tcl_NewByteArrayObj((unsigned char *)
- (&bytes[index]), 1);
+ (&bytes[index]), 1);
} else if (valuePtr->bytes && length == valuePtr->length) {
- objResultPtr = Tcl_NewStringObj((CONST char *)
- (&valuePtr->bytes[index]), 1);
+ objResultPtr = Tcl_NewStringObj((const char *)
+ (&valuePtr->bytes[index]), 1);
} else {
char buf[TCL_UTF_MAX];
Tcl_UniChar ch;
ch = Tcl_GetUniChar(valuePtr, index);
+
/*
- * This could be:
- * Tcl_NewUnicodeObj((CONST Tcl_UniChar *)&ch, 1)
- * but creating the object as a string seems to be
- * faster in practical use.
+ * This could be: Tcl_NewUnicodeObj((const Tcl_UniChar *)&ch,
+ * 1) but creating the object as a string seems to be faster
+ * in practical use.
*/
+
length = Tcl_UniCharToUtf(ch, buf);
objResultPtr = Tcl_NewStringObj(buf, length);
}
@@ -2835,26 +4394,26 @@ TclExecuteByteCode(interp, codePtr)
TclNewObj(objResultPtr);
}
- TRACE(("%.20s %.20s => %s\n", O2S(valuePtr), O2S(value2Ptr),
- O2S(objResultPtr)));
+ TRACE(("%.20s %.20s => %s\n", O2S(valuePtr), O2S(value2Ptr),
+ O2S(objResultPtr)));
NEXT_INST_F(1, 2, 1);
}
- case INST_STR_MATCH:
- {
+ case INST_STR_MATCH: {
int nocase, match;
+ Tcl_Obj *valuePtr, *value2Ptr;
- nocase = TclGetInt1AtPtr(pc+1);
- valuePtr = stackPtr[stackTop]; /* String */
- value2Ptr = stackPtr[stackTop - 1]; /* Pattern */
+ nocase = TclGetInt1AtPtr(pc+1);
+ valuePtr = OBJ_AT_TOS; /* String */
+ value2Ptr = OBJ_UNDER_TOS; /* Pattern */
/*
- * Check that at least one of the objects is Unicode before
- * promoting both.
+ * Check that at least one of the objects is Unicode before promoting
+ * both.
*/
if ((valuePtr->typePtr == &tclStringType)
- || (value2Ptr->typePtr == &tclStringType)) {
+ || (value2Ptr->typePtr == &tclStringType)) {
Tcl_UniChar *ustring1, *ustring2;
int length1, length2;
@@ -2862,23 +4421,60 @@ TclExecuteByteCode(interp, codePtr)
ustring2 = Tcl_GetUnicodeFromObj(value2Ptr, &length2);
match = TclUniCharMatch(ustring1, length1, ustring2, length2,
nocase);
+ } else if ((valuePtr->typePtr == &tclByteArrayType) && !nocase) {
+ unsigned char *string1, *string2;
+ int length1, length2;
+
+ string1 = Tcl_GetByteArrayFromObj(valuePtr, &length1);
+ string2 = Tcl_GetByteArrayFromObj(value2Ptr, &length2);
+ match = TclByteArrayMatch(string1, length1, string2, length2, 0);
} else {
match = Tcl_StringCaseMatch(TclGetString(valuePtr),
TclGetString(value2Ptr), nocase);
}
/*
- * Reuse value2Ptr object already on stack if possible.
- * Adjustment is 2 due to the nocase byte
+ * Reuse value2Ptr object already on stack if possible. Adjustment is
+ * 2 due to the nocase byte
+ * TODO: consider peephole opt.
*/
TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), match));
- if (Tcl_IsShared(value2Ptr)) {
- objResultPtr = Tcl_NewIntObj(match);
+ objResultPtr = constants[match];
+ NEXT_INST_F(2, 2, 1);
+ }
+
+ case INST_REGEXP: {
+ int cflags, match;
+ Tcl_Obj *valuePtr, *value2Ptr;
+ Tcl_RegExp regExpr;
+
+ cflags = TclGetInt1AtPtr(pc+1); /* RE compile flages like NOCASE */
+ valuePtr = OBJ_AT_TOS; /* String */
+ value2Ptr = OBJ_UNDER_TOS; /* Pattern */
+
+ regExpr = Tcl_GetRegExpFromObj(interp, value2Ptr, cflags);
+ if (regExpr == NULL) {
+ match = -1;
+ } else {
+ match = Tcl_RegExpExecObj(interp, regExpr, valuePtr, 0, 0, 0);
+ }
+
+ /*
+ * Adjustment is 2 due to the nocase byte
+ */
+
+ if (match < 0) {
+ objResultPtr = Tcl_GetObjResult(interp);
+ TRACE_WITH_OBJ(("%.20s %.20s => ERROR: ",
+ O2S(valuePtr), O2S(value2Ptr)), objResultPtr);
+ result = TCL_ERROR;
+ goto checkForCatch;
+ } else {
+ TRACE(("%.20s %.20s => %d\n",
+ O2S(valuePtr), O2S(value2Ptr), match));
+ objResultPtr = constants[match];
NEXT_INST_F(2, 2, 1);
- } else { /* reuse the valuePtr object */
- Tcl_SetIntObj(value2Ptr, match);
- NEXT_INST_F(2, 1, 0);
}
}
@@ -2887,1441 +4483,2277 @@ TclExecuteByteCode(interp, codePtr)
case INST_LT:
case INST_GT:
case INST_LE:
- case INST_GE:
- {
- /*
- * Any type is allowed but the two operands must have the
- * same type. We will compute value op value2.
- */
-
- Tcl_ObjType *t1Ptr, *t2Ptr;
- char *s1 = NULL; /* Init. avoids compiler warning. */
- char *s2 = NULL; /* Init. avoids compiler warning. */
- long i2 = 0; /* Init. avoids compiler warning. */
- double d1 = 0.0; /* Init. avoids compiler warning. */
- double d2 = 0.0; /* Init. avoids compiler warning. */
- long iResult = 0; /* Init. avoids compiler warning. */
+ case INST_GE: {
+ Tcl_Obj *valuePtr = OBJ_UNDER_TOS;
+ Tcl_Obj *value2Ptr = OBJ_AT_TOS;
+ ClientData ptr1, ptr2;
+ int iResult = 0, compare = 0, type1, type2;
+ double d1, d2, tmp;
+ long l1, l2;
+ mp_int big1, big2;
+#ifndef NO_WIDE_TYPE
+ Tcl_WideInt w1, w2;
+#endif
- value2Ptr = stackPtr[stackTop];
- valuePtr = stackPtr[stackTop - 1];
+ if (GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) {
+ /*
+ * At least one non-numeric argument - compare as strings.
+ */
- /*
- * Be careful in the equal-object case; 'NaN' isn't supposed
- * to be equal to even itself. [Bug 761471]
- */
+ goto stringCompare;
+ }
+ if (type1 == TCL_NUMBER_NAN) {
+ /*
+ * NaN first arg: NaN != to everything, other compares are false.
+ */
- t1Ptr = valuePtr->typePtr;
+ iResult = (*pc == INST_NEQ);
+ goto foundResult;
+ }
if (valuePtr == value2Ptr) {
+ compare = MP_EQ;
+ goto convertComparison;
+ }
+ if (GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2) != TCL_OK) {
/*
- * If we are numeric already, we can proceed to the main
- * equality check right now. Otherwise, we need to try to
- * coerce to a numeric type so we can see if we've got a
- * NaN but haven't parsed it as numeric.
+ * At least one non-numeric argument - compare as strings.
*/
- if (!IS_NUMERIC_TYPE(t1Ptr)) {
- if (t1Ptr == &tclListType) {
- int length;
- /*
- * Only a list of length 1 can be NaN or such
- * things.
- */
- (void) Tcl_ListObjLength(NULL, valuePtr, &length);
- if (length == 1) {
- goto mustConvertForNaNCheck;
- }
- } else {
- /*
- * Too bad, we'll have to compute the string and
- * try the conversion
- */
- mustConvertForNaNCheck:
- s1 = Tcl_GetStringFromObj(valuePtr, &length);
- if (TclLooksLikeInt(s1, length)) {
- GET_WIDE_OR_INT(iResult, valuePtr, i, w);
- } else {
- (void) Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
- valuePtr, &d1);
- }
- t1Ptr = valuePtr->typePtr;
- }
- }
+ goto stringCompare;
+ }
+ if (type2 == TCL_NUMBER_NAN) {
+ /*
+ * NaN 2nd arg: NaN != to everything, other compares are false.
+ */
- switch (*pc) {
- case INST_EQ:
- case INST_LE:
- case INST_GE:
- iResult = !((t1Ptr == &tclDoubleType)
- && IS_NAN(valuePtr->internalRep.doubleValue));
- break;
- case INST_LT:
- case INST_GT:
- iResult = 0;
- break;
- case INST_NEQ:
- iResult = ((t1Ptr == &tclDoubleType)
- && IS_NAN(valuePtr->internalRep.doubleValue));
- break;
- }
+ iResult = (*pc == INST_NEQ);
goto foundResult;
}
+ switch (type1) {
+ case TCL_NUMBER_LONG:
+ l1 = *((const long *)ptr1);
+ switch (type2) {
+ case TCL_NUMBER_LONG:
+ l2 = *((const long *)ptr2);
+ longCompare:
+ compare = (l1 < l2) ? MP_LT : ((l1 > l2) ? MP_GT : MP_EQ);
+ break;
+#ifndef NO_WIDE_TYPE
+ case TCL_NUMBER_WIDE:
+ w2 = *((const Tcl_WideInt *)ptr2);
+ w1 = (Tcl_WideInt)l1;
+ goto wideCompare;
+#endif
+ case TCL_NUMBER_DOUBLE:
+ d2 = *((const double *)ptr2);
+ d1 = (double) l1;
- t2Ptr = value2Ptr->typePtr;
+ /*
+ * If the double has a fractional part, or if the long can be
+ * converted to double without loss of precision, then compare
+ * as doubles.
+ */
- /*
- * We only want to coerce numeric validation if neither type
- * is NULL. A NULL type means the arg is essentially an empty
- * object ("", {} or [list]).
- */
- if (!( (!t1Ptr && !valuePtr->bytes)
- || (valuePtr->bytes && !valuePtr->length)
- || (!t2Ptr && !value2Ptr->bytes)
- || (value2Ptr->bytes && !value2Ptr->length))) {
- if (!IS_NUMERIC_TYPE(t1Ptr)) {
- s1 = Tcl_GetStringFromObj(valuePtr, &length);
- if (TclLooksLikeInt(s1, length)) {
- GET_WIDE_OR_INT(iResult, valuePtr, i, w);
- } else {
- (void) Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
- valuePtr, &d1);
- }
- t1Ptr = valuePtr->typePtr;
- }
- if (!IS_NUMERIC_TYPE(t2Ptr)) {
- s2 = Tcl_GetStringFromObj(value2Ptr, &length);
- if (TclLooksLikeInt(s2, length)) {
- GET_WIDE_OR_INT(iResult, value2Ptr, i2, w);
- } else {
- (void) Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
- value2Ptr, &d2);
+ if (DBL_MANT_DIG > CHAR_BIT*sizeof(long)
+ || l1 == (long) d1
+ || modf(d2, &tmp) != 0.0) {
+ goto doubleCompare;
}
- t2Ptr = value2Ptr->typePtr;
- }
- }
- if (!IS_NUMERIC_TYPE(t1Ptr) || !IS_NUMERIC_TYPE(t2Ptr)) {
- /*
- * One operand is not numeric. Compare as strings. NOTE:
- * strcmp is not correct for \x00 < \x01, but that is
- * unlikely to occur here. We could use the TclUtfNCmp2
- * to handle this.
- */
- int s1len, s2len;
- s1 = Tcl_GetStringFromObj(valuePtr, &s1len);
- s2 = Tcl_GetStringFromObj(value2Ptr, &s2len);
- switch (*pc) {
- case INST_EQ:
- if (s1len == s2len) {
- iResult = (strcmp(s1, s2) == 0);
- } else {
- iResult = 0;
- }
- break;
- case INST_NEQ:
- if (s1len == s2len) {
- iResult = (strcmp(s1, s2) != 0);
- } else {
- iResult = 1;
- }
- break;
- case INST_LT:
- iResult = (strcmp(s1, s2) < 0);
- break;
- case INST_GT:
- iResult = (strcmp(s1, s2) > 0);
- break;
- case INST_LE:
- iResult = (strcmp(s1, s2) <= 0);
+
+ /*
+ * Otherwise, to make comparision based on full precision,
+ * need to convert the double to a suitably sized integer.
+ *
+ * Need this to get comparsions like
+ * expr 20000000000000003 < 20000000000000004.0
+ * right. Converting the first argument to double will yield
+ * two double values that are equivalent within double
+ * precision. Converting the double to an integer gets done
+ * exactly, then integer comparison can tell the difference.
+ */
+
+ if (d2 < (double)LONG_MIN) {
+ compare = MP_GT;
break;
- case INST_GE:
- iResult = (strcmp(s1, s2) >= 0);
+ }
+ if (d2 > (double)LONG_MAX) {
+ compare = MP_LT;
break;
+ }
+ l2 = (long) d2;
+ goto longCompare;
+ case TCL_NUMBER_BIG:
+ Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
+ if (mp_cmp_d(&big2, 0) == MP_LT) {
+ compare = MP_GT;
+ } else {
+ compare = MP_LT;
+ }
+ mp_clear(&big2);
}
- } else if ((t1Ptr == &tclDoubleType)
- || (t2Ptr == &tclDoubleType)) {
- /*
- * Compare as doubles.
- */
- if (t1Ptr == &tclDoubleType) {
- d1 = valuePtr->internalRep.doubleValue;
- GET_DOUBLE_VALUE(d2, value2Ptr, t2Ptr);
- } else { /* t1Ptr is integer, t2Ptr is double */
- GET_DOUBLE_VALUE(d1, valuePtr, t1Ptr);
- d2 = value2Ptr->internalRep.doubleValue;
- }
- switch (*pc) {
- case INST_EQ:
- iResult = d1 == d2;
- break;
- case INST_NEQ:
- iResult = d1 != d2;
- break;
- case INST_LT:
- iResult = d1 < d2;
- break;
- case INST_GT:
- iResult = d1 > d2;
- break;
- case INST_LE:
- iResult = d1 <= d2;
+ break;
+
+#ifndef NO_WIDE_TYPE
+ case TCL_NUMBER_WIDE:
+ w1 = *((const Tcl_WideInt *)ptr1);
+ switch (type2) {
+ case TCL_NUMBER_WIDE:
+ w2 = *((const Tcl_WideInt *)ptr2);
+ wideCompare:
+ compare = (w1 < w2) ? MP_LT : ((w1 > w2) ? MP_GT : MP_EQ);
+ break;
+ case TCL_NUMBER_LONG:
+ l2 = *((const long *)ptr2);
+ w2 = (Tcl_WideInt)l2;
+ goto wideCompare;
+ case TCL_NUMBER_DOUBLE:
+ d2 = *((const double *)ptr2);
+ d1 = (double) w1;
+ if (DBL_MANT_DIG > CHAR_BIT*sizeof(Tcl_WideInt)
+ || w1 == (Tcl_WideInt) d1
+ || modf(d2, &tmp) != 0.0) {
+ goto doubleCompare;
+ }
+ if (d2 < (double)LLONG_MIN) {
+ compare = MP_GT;
break;
- case INST_GE:
- iResult = d1 >= d2;
+ }
+ if (d2 > (double)LLONG_MAX) {
+ compare = MP_LT;
break;
+ }
+ w2 = (Tcl_WideInt) d2;
+ goto wideCompare;
+ case TCL_NUMBER_BIG:
+ Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
+ if (mp_cmp_d(&big2, 0) == MP_LT) {
+ compare = MP_GT;
+ } else {
+ compare = MP_LT;
+ }
+ mp_clear(&big2);
}
- } else if ((t1Ptr == &tclWideIntType)
- || (t2Ptr == &tclWideIntType)) {
- Tcl_WideInt w2;
- /*
- * Compare as wide ints (neither are doubles)
- */
- if (t1Ptr == &tclIntType) {
- w = Tcl_LongAsWide(valuePtr->internalRep.longValue);
- TclGetWide(w2,value2Ptr);
- } else if (t2Ptr == &tclIntType) {
- TclGetWide(w,valuePtr);
- w2 = Tcl_LongAsWide(value2Ptr->internalRep.longValue);
- } else {
- TclGetWide(w,valuePtr);
- TclGetWide(w2,value2Ptr);
- }
- switch (*pc) {
- case INST_EQ:
- iResult = w == w2;
+ break;
+#endif
+
+ case TCL_NUMBER_DOUBLE:
+ d1 = *((const double *)ptr1);
+ switch (type2) {
+ case TCL_NUMBER_DOUBLE:
+ d2 = *((const double *)ptr2);
+ doubleCompare:
+ compare = (d1 < d2) ? MP_LT : ((d1 > d2) ? MP_GT : MP_EQ);
+ break;
+ case TCL_NUMBER_LONG:
+ l2 = *((const long *)ptr2);
+ d2 = (double) l2;
+ if (DBL_MANT_DIG > CHAR_BIT*sizeof(long)
+ || l2 == (long) d2
+ || modf(d1, &tmp) != 0.0) {
+ goto doubleCompare;
+ }
+ if (d1 < (double)LONG_MIN) {
+ compare = MP_LT;
break;
- case INST_NEQ:
- iResult = w != w2;
+ }
+ if (d1 > (double)LONG_MAX) {
+ compare = MP_GT;
break;
- case INST_LT:
- iResult = w < w2;
+ }
+ l1 = (long) d1;
+ goto longCompare;
+#ifndef NO_WIDE_TYPE
+ case TCL_NUMBER_WIDE:
+ w2 = *((const Tcl_WideInt *)ptr2);
+ d2 = (double) w2;
+ if (DBL_MANT_DIG > CHAR_BIT*sizeof(Tcl_WideInt)
+ || w2 == (Tcl_WideInt) d2
+ || modf(d1, &tmp) != 0.0) {
+ goto doubleCompare;
+ }
+ if (d1 < (double)LLONG_MIN) {
+ compare = MP_LT;
break;
- case INST_GT:
- iResult = w > w2;
+ }
+ if (d1 > (double)LLONG_MAX) {
+ compare = MP_GT;
break;
- case INST_LE:
- iResult = w <= w2;
+ }
+ w1 = (Tcl_WideInt) d1;
+ goto wideCompare;
+#endif
+ case TCL_NUMBER_BIG:
+ if (TclIsInfinite(d1)) {
+ compare = (d1 > 0.0) ? MP_GT : MP_LT;
break;
- case INST_GE:
- iResult = w >= w2;
+ }
+ Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
+ if ((d1 < (double)LONG_MAX) && (d1 > (double)LONG_MIN)) {
+ if (mp_cmp_d(&big2, 0) == MP_LT) {
+ compare = MP_GT;
+ } else {
+ compare = MP_LT;
+ }
+ mp_clear(&big2);
break;
+ }
+ if (DBL_MANT_DIG > CHAR_BIT*sizeof(long)
+ && modf(d1, &tmp) != 0.0) {
+ d2 = TclBignumToDouble(&big2);
+ mp_clear(&big2);
+ goto doubleCompare;
+ }
+ Tcl_InitBignumFromDouble(NULL, d1, &big1);
+ goto bigCompare;
}
- } else {
- /*
- * Compare as ints.
- */
- i = valuePtr->internalRep.longValue;
- i2 = value2Ptr->internalRep.longValue;
- switch (*pc) {
- case INST_EQ:
- iResult = i == i2;
- break;
- case INST_NEQ:
- iResult = i != i2;
- break;
- case INST_LT:
- iResult = i < i2;
- break;
- case INST_GT:
- iResult = i > i2;
- break;
- case INST_LE:
- iResult = i <= i2;
+ break;
+
+ case TCL_NUMBER_BIG:
+ Tcl_TakeBignumFromObj(NULL, valuePtr, &big1);
+ switch (type2) {
+#ifndef NO_WIDE_TYPE
+ case TCL_NUMBER_WIDE:
+#endif
+ case TCL_NUMBER_LONG:
+ compare = mp_cmp_d(&big1, 0);
+ mp_clear(&big1);
+ break;
+ case TCL_NUMBER_DOUBLE:
+ d2 = *((const double *)ptr2);
+ if (TclIsInfinite(d2)) {
+ compare = (d2 > 0.0) ? MP_LT : MP_GT;
+ mp_clear(&big1);
break;
- case INST_GE:
- iResult = i >= i2;
+ }
+ if ((d2 < (double)LONG_MAX) && (d2 > (double)LONG_MIN)) {
+ compare = mp_cmp_d(&big1, 0);
+ mp_clear(&big1);
break;
+ }
+ if (DBL_MANT_DIG > CHAR_BIT*sizeof(long)
+ && modf(d2, &tmp) != 0.0) {
+ d1 = TclBignumToDouble(&big1);
+ mp_clear(&big1);
+ goto doubleCompare;
+ }
+ Tcl_InitBignumFromDouble(NULL, d2, &big2);
+ goto bigCompare;
+ case TCL_NUMBER_BIG:
+ Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
+ bigCompare:
+ compare = mp_cmp(&big1, &big2);
+ mp_clear(&big1);
+ mp_clear(&big2);
}
}
- foundResult:
- TRACE(("%.20s %.20s => %ld\n", O2S(valuePtr), O2S(value2Ptr), iResult));
+ /*
+ * Turn comparison outcome into appropriate result for opcode.
+ */
+
+ convertComparison:
+ switch (*pc) {
+ case INST_EQ:
+ iResult = (compare == MP_EQ);
+ break;
+ case INST_NEQ:
+ iResult = (compare != MP_EQ);
+ break;
+ case INST_LT:
+ iResult = (compare == MP_LT);
+ break;
+ case INST_GT:
+ iResult = (compare == MP_GT);
+ break;
+ case INST_LE:
+ iResult = (compare != MP_GT);
+ break;
+ case INST_GE:
+ iResult = (compare != MP_LT);
+ break;
+ }
/*
- * Peep-hole optimisation: if you're about to jump, do jump
- * from here.
+ * Peep-hole optimisation: if you're about to jump, do jump from here.
*/
+ foundResult:
pc++;
#ifndef TCL_COMPILE_DEBUG
switch (*pc) {
- case INST_JUMP_FALSE1:
- NEXT_INST_F((iResult? 2 : TclGetInt1AtPtr(pc+1)), 2, 0);
- case INST_JUMP_TRUE1:
- NEXT_INST_F((iResult? TclGetInt1AtPtr(pc+1) : 2), 2, 0);
- case INST_JUMP_FALSE4:
- NEXT_INST_F((iResult? 5 : TclGetInt4AtPtr(pc+1)), 2, 0);
- case INST_JUMP_TRUE4:
- NEXT_INST_F((iResult? TclGetInt4AtPtr(pc+1) : 5), 2, 0);
+ case INST_JUMP_FALSE1:
+ NEXT_INST_F((iResult? 2 : TclGetInt1AtPtr(pc+1)), 2, 0);
+ case INST_JUMP_TRUE1:
+ NEXT_INST_F((iResult? TclGetInt1AtPtr(pc+1) : 2), 2, 0);
+ case INST_JUMP_FALSE4:
+ NEXT_INST_F((iResult? 5 : TclGetInt4AtPtr(pc+1)), 2, 0);
+ case INST_JUMP_TRUE4:
+ NEXT_INST_F((iResult? TclGetInt4AtPtr(pc+1) : 5), 2, 0);
}
#endif
- objResultPtr = Tcl_NewIntObj(iResult);
+ objResultPtr = constants[iResult];
NEXT_INST_F(0, 2, 1);
}
case INST_MOD:
case INST_LSHIFT:
- case INST_RSHIFT:
- case INST_BITOR:
- case INST_BITXOR:
- case INST_BITAND:
- {
- /*
- * Only integers are allowed. We compute value op value2.
- */
-
- long i2 = 0, rem, negative;
- long iResult = 0; /* Init. avoids compiler warning. */
- Tcl_WideInt w2, wResult = W0;
- int doWide = 0;
-
- value2Ptr = stackPtr[stackTop];
- valuePtr = stackPtr[stackTop - 1];
- if (valuePtr->typePtr == &tclIntType) {
- i = valuePtr->internalRep.longValue;
- } else if (valuePtr->typePtr == &tclWideIntType) {
- TclGetWide(w,valuePtr);
- } else { /* try to convert to int */
- REQUIRE_WIDE_OR_INT(result, valuePtr, i, w);
- if (result != TCL_OK) {
- TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n",
- O2S(valuePtr), O2S(value2Ptr),
- (valuePtr->typePtr?
- valuePtr->typePtr->name : "null")));
- DECACHE_STACK_INFO();
- IllegalExprOperandType(interp, pc, valuePtr);
- CACHE_STACK_INFO();
- goto checkForCatch;
- }
+ case INST_RSHIFT: {
+ Tcl_Obj *value2Ptr = OBJ_AT_TOS;
+ Tcl_Obj *valuePtr = OBJ_UNDER_TOS;
+ ClientData ptr1, ptr2;
+ int invalid, shift, type1, type2;
+ long l1 = 0;
+
+ result = GetNumberFromObj(NULL, valuePtr, &ptr1, &type1);
+ if ((result != TCL_OK) || (type1 == TCL_NUMBER_DOUBLE)
+ || (type1 == TCL_NUMBER_NAN)) {
+ result = TCL_ERROR;
+ TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n", O2S(valuePtr),
+ O2S(value2Ptr), (valuePtr->typePtr?
+ valuePtr->typePtr->name : "null")));
+ DECACHE_STACK_INFO();
+ IllegalExprOperandType(interp, pc, valuePtr);
+ CACHE_STACK_INFO();
+ goto checkForCatch;
}
- if (value2Ptr->typePtr == &tclIntType) {
- i2 = value2Ptr->internalRep.longValue;
- } else if (value2Ptr->typePtr == &tclWideIntType) {
- TclGetWide(w2,value2Ptr);
- } else {
- REQUIRE_WIDE_OR_INT(result, value2Ptr, i2, w2);
- if (result != TCL_OK) {
- TRACE(("%.20s %.20s => ILLEGAL 2nd TYPE %s\n",
- O2S(valuePtr), O2S(value2Ptr),
- (value2Ptr->typePtr?
- value2Ptr->typePtr->name : "null")));
- DECACHE_STACK_INFO();
- IllegalExprOperandType(interp, pc, value2Ptr);
- CACHE_STACK_INFO();
- goto checkForCatch;
- }
+
+ result = GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2);
+ if ((result != TCL_OK) || (type2 == TCL_NUMBER_DOUBLE)
+ || (type2 == TCL_NUMBER_NAN)) {
+ result = TCL_ERROR;
+ TRACE(("%.20s %.20s => ILLEGAL 2nd TYPE %s\n", O2S(valuePtr),
+ O2S(value2Ptr), (value2Ptr->typePtr?
+ value2Ptr->typePtr->name : "null")));
+ DECACHE_STACK_INFO();
+ IllegalExprOperandType(interp, pc, value2Ptr);
+ CACHE_STACK_INFO();
+ goto checkForCatch;
}
- switch (*pc) {
- case INST_MOD:
- /*
- * This code is tricky: C doesn't guarantee much about
- * the quotient or remainder, but Tcl does. The
- * remainder always has the same sign as the divisor and
- * a smaller absolute value.
- */
- if (value2Ptr->typePtr == &tclWideIntType && w2 == W0) {
- if (valuePtr->typePtr == &tclIntType) {
- TRACE(("%ld "LLD" => DIVIDE BY ZERO\n", i, w2));
- } else {
- TRACE((LLD" "LLD" => DIVIDE BY ZERO\n", w, w2));
+ if (*pc == INST_MOD) {
+ /* TODO: Attempts to re-use unshared operands on stack */
+
+ long l2 = 0; /* silence gcc warning */
+
+ if (type2 == TCL_NUMBER_LONG) {
+ l2 = *((const long *)ptr2);
+ if (l2 == 0) {
+ TRACE(("%s %s => DIVIDE BY ZERO\n", O2S(valuePtr),
+ O2S(value2Ptr)));
+ goto divideByZero;
}
- goto divideByZero;
- }
- if (value2Ptr->typePtr == &tclIntType && i2 == 0) {
- if (valuePtr->typePtr == &tclIntType) {
- TRACE(("%ld %ld => DIVIDE BY ZERO\n", i, i2));
- } else {
- TRACE((LLD" %ld => DIVIDE BY ZERO\n", w, i2));
+ if ((l2 == 1) || (l2 == -1)) {
+ /*
+ * Div. by |1| always yields remainder of 0.
+ */
+
+ objResultPtr = constants[0];
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
}
- goto divideByZero;
}
- negative = 0;
- if (valuePtr->typePtr == &tclWideIntType
- || value2Ptr->typePtr == &tclWideIntType) {
- Tcl_WideInt wRemainder;
+ if (type1 == TCL_NUMBER_LONG) {
+ l1 = *((const long *)ptr1);
+ if (l1 == 0) {
+ /*
+ * 0 % (non-zero) always yields remainder of 0.
+ */
+
+ objResultPtr = constants[0];
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+ if (type2 == TCL_NUMBER_LONG) {
+ /*
+ * Both operands are long; do native calculation.
+ */
+
+ long lRemainder, lQuotient = l1 / l2;
+
+ /*
+ * Force Tcl's integer division rules.
+ * TODO: examine for logic simplification
+ */
+
+ if ((lQuotient < 0 || (lQuotient == 0 &&
+ ((l1 < 0 && l2 > 0) || (l1 > 0 && l2 < 0)))) &&
+ (lQuotient * l2 != l1)) {
+ lQuotient -= 1;
+ }
+ lRemainder = l1 - l2*lQuotient;
+ TclNewLongObj(objResultPtr, lRemainder);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+
/*
- * Promote to wide
+ * First operand fits in long; second does not, so the second
+ * has greater magnitude than first. No need to divide to
+ * determine the remainder.
*/
- if (valuePtr->typePtr == &tclIntType) {
- w = Tcl_LongAsWide(i);
- } else if (value2Ptr->typePtr == &tclIntType) {
- w2 = Tcl_LongAsWide(i2);
+
+#ifndef NO_WIDE_TYPE
+ if (type2 == TCL_NUMBER_WIDE) {
+ Tcl_WideInt w2 = *((const Tcl_WideInt *)ptr2);
+
+ if ((l1 > 0) ^ (w2 > (Tcl_WideInt)0)) {
+ /*
+ * Arguments are opposite sign; remainder is sum.
+ */
+
+ objResultPtr = Tcl_NewWideIntObj(w2+(Tcl_WideInt)l1);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+
+ /*
+ * Arguments are same sign; remainder is first operand.
+ */
+
+ TRACE(("%s\n", O2S(valuePtr)));
+ NEXT_INST_F(1, 1, 0);
}
- if (w2 < 0) {
- w2 = -w2;
- w = -w;
- negative = 1;
+#endif
+ {
+ mp_int big2;
+
+ Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
+
+ /* TODO: internals intrusion */
+ if ((l1 > 0) ^ (big2.sign == MP_ZPOS)) {
+ /*
+ * Arguments are opposite sign; remainder is sum.
+ */
+
+ mp_int big1;
+
+ TclBNInitBignumFromLong(&big1, l1);
+ mp_add(&big2, &big1, &big2);
+ mp_clear(&big1);
+ objResultPtr = Tcl_NewBignumObj(&big2);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+
+ /*
+ * Arguments are same sign; remainder is first operand.
+ */
+
+ mp_clear(&big2);
+ TRACE(("%s\n", O2S(valuePtr)));
+ NEXT_INST_F(1, 1, 0);
}
- wRemainder = w % w2;
- if (wRemainder < 0) {
- wRemainder += w2;
+ }
+#ifndef NO_WIDE_TYPE
+ if (type1 == TCL_NUMBER_WIDE) {
+ Tcl_WideInt w1 = *((const Tcl_WideInt *)ptr1);
+
+ if (type2 != TCL_NUMBER_BIG) {
+ Tcl_WideInt w2, wQuotient, wRemainder;
+
+ Tcl_GetWideIntFromObj(NULL, value2Ptr, &w2);
+ wQuotient = w1 / w2;
+
+ /*
+ * Force Tcl's integer division rules.
+ * TODO: examine for logic simplification
+ */
+
+ if (((wQuotient < (Tcl_WideInt) 0)
+ || ((wQuotient == (Tcl_WideInt) 0)
+ && ((w1 < (Tcl_WideInt)0 && w2 > (Tcl_WideInt)0)
+ || (w1 > (Tcl_WideInt)0 && w2 < (Tcl_WideInt)0))))
+ && (wQuotient * w2 != w1)) {
+ wQuotient -= (Tcl_WideInt) 1;
+ }
+ wRemainder = w1 - w2*wQuotient;
+ objResultPtr = Tcl_NewWideIntObj(wRemainder);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
}
- if (negative) {
- wRemainder = -wRemainder;
+ {
+ mp_int big2;
+ Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
+
+ /* TODO: internals intrusion */
+ if ((w1 > ((Tcl_WideInt) 0)) ^ (big2.sign == MP_ZPOS)) {
+ /*
+ * Arguments are opposite sign; remainder is sum.
+ */
+
+ mp_int big1;
+
+ TclBNInitBignumFromWideInt(&big1, w1);
+ mp_add(&big2, &big1, &big2);
+ mp_clear(&big1);
+ objResultPtr = Tcl_NewBignumObj(&big2);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+
+ /*
+ * Arguments are same sign; remainder is first operand.
+ */
+
+ mp_clear(&big2);
+ TRACE(("%s\n", O2S(valuePtr)));
+ NEXT_INST_F(1, 1, 0);
}
- wResult = wRemainder;
- doWide = 1;
- break;
- }
- if (i2 < 0) {
- i2 = -i2;
- i = -i;
- negative = 1;
}
- rem = i % i2;
- if (rem < 0) {
- rem += i2;
- }
- if (negative) {
- rem = -rem;
+#endif
+ {
+ mp_int big1, big2, bigResult, bigRemainder;
+
+ Tcl_GetBignumFromObj(NULL, valuePtr, &big1);
+ Tcl_GetBignumFromObj(NULL, value2Ptr, &big2);
+ mp_init(&bigResult);
+ mp_init(&bigRemainder);
+ mp_div(&big1, &big2, &bigResult, &bigRemainder);
+ if (!mp_iszero(&bigRemainder)
+ && (bigRemainder.sign != big2.sign)) {
+ /*
+ * Convert to Tcl's integer division rules.
+ */
+
+ mp_sub_d(&bigResult, 1, &bigResult);
+ mp_add(&bigRemainder, &big2, &bigRemainder);
+ }
+ mp_copy(&bigRemainder, &bigResult);
+ mp_clear(&bigRemainder);
+ mp_clear(&big1);
+ mp_clear(&big2);
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ if (Tcl_IsShared(valuePtr)) {
+ objResultPtr = Tcl_NewBignumObj(&bigResult);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+ Tcl_SetBignumObj(valuePtr, &bigResult);
+ TRACE(("%s\n", O2S(valuePtr)));
+ NEXT_INST_F(1, 1, 0);
}
- iResult = rem;
+ }
+
+ /*
+ * Reject negative shift argument.
+ */
+
+ switch (type2) {
+ case TCL_NUMBER_LONG:
+ invalid = (*((const long *)ptr2) < (long)0);
+ break;
+#ifndef NO_WIDE_TYPE
+ case TCL_NUMBER_WIDE:
+ invalid = (*((const Tcl_WideInt *)ptr2) < (Tcl_WideInt)0);
+ break;
+#endif
+ case TCL_NUMBER_BIG: {
+ mp_int big2;
+
+ Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
+ invalid = (mp_cmp_d(&big2, 0) == MP_LT);
+ mp_clear(&big2);
break;
- case INST_LSHIFT:
+ }
+ default:
+ /* Unused, here to silence compiler warning */
+ invalid = 0;
+ }
+ if (invalid) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("negative shift argument", -1));
+ result = TCL_ERROR;
+ goto checkForCatch;
+ }
+
+ /*
+ * Zero shifted any number of bits is still zero.
+ */
+
+ if ((type1==TCL_NUMBER_LONG) && (*((const long *)ptr1) == (long)0)) {
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ objResultPtr = constants[0];
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+
+ if (*pc == INST_LSHIFT) {
/*
- * Shifts are never usefully 64-bits wide!
+ * Large left shifts create integer overflow.
+ *
+ * BEWARE! Can't use Tcl_GetIntFromObj() here because that
+ * converts values in the (unsigned) range to their signed int
+ * counterparts, leading to incorrect results.
*/
- FORCE_LONG(value2Ptr, i2, w2);
- if (valuePtr->typePtr == &tclWideIntType) {
-#ifdef TCL_COMPILE_DEBUG
- w2 = Tcl_LongAsWide(i2);
-#endif /* TCL_COMPILE_DEBUG */
- wResult = w;
+
+ if ((type2 != TCL_NUMBER_LONG)
+ || (*((const long *)ptr2) > (long) INT_MAX)) {
/*
- * Shift in steps when the shift gets large to prevent
- * annoying compiler/processor bugs. [Bug 868467]
+ * Technically, we could hold the value (1 << (INT_MAX+1)) in
+ * an mp_int, but since we're using mp_mul_2d() to do the
+ * work, and it takes only an int argument, that's a good
+ * place to draw the line.
*/
- if (i2 >= 64) {
- wResult = Tcl_LongAsWide(0);
- } else if (i2 > 60) {
- wResult = w << 30;
- wResult <<= 30;
- wResult <<= i2-60;
- } else if (i2 > 30) {
- wResult = w << 30;
- wResult <<= i2-30;
- } else {
- wResult = w << i2;
- }
- doWide = 1;
- break;
+
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "integer value too large to represent", -1));
+ result = TCL_ERROR;
+ goto checkForCatch;
}
+ shift = (int)(*((const long *)ptr2));
+
/*
- * Shift in steps when the shift gets large to prevent
- * annoying compiler/processor bugs. [Bug 868467]
+ * Handle shifts within the native long range.
*/
- if (i2 >= 64) {
- iResult = 0;
- } else if (i2 > 60) {
- iResult = i << 30;
- iResult <<= 30;
- iResult <<= i2-60;
- } else if (i2 > 30) {
- iResult = i << 30;
- iResult <<= i2-30;
- } else {
- iResult = i << i2;
+
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ if ((type1 == TCL_NUMBER_LONG)
+ && (size_t) shift < CHAR_BIT*sizeof(long)
+ && ((l1 = *(const long *)ptr1) != 0)
+ && !((l1>0 ? l1 : ~l1)
+ & -(1L<<(CHAR_BIT*sizeof(long) - 1 - shift)))) {
+ TclNewLongObj(objResultPtr, (l1<<shift));
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
}
- break;
- case INST_RSHIFT:
+
/*
- * The following code is a bit tricky: it ensures that
- * right shifts propagate the sign bit even on machines
- * where ">>" won't do it by default.
+ * Handle shifts within the native wide range.
*/
+
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ if ((type1 != TCL_NUMBER_BIG)
+ && ((size_t)shift < CHAR_BIT*sizeof(Tcl_WideInt))) {
+ Tcl_WideInt w;
+
+ TclGetWideIntFromObj(NULL, valuePtr, &w);
+ if (!((w>0 ? w : ~w)
+ & -(((Tcl_WideInt)1)
+ << (CHAR_BIT*sizeof(Tcl_WideInt) - 1 - shift)))) {
+ objResultPtr = Tcl_NewWideIntObj(w<<shift);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+ }
+ } else {
/*
- * Shifts are never usefully 64-bits wide!
+ * Quickly force large right shifts to 0 or -1.
*/
- FORCE_LONG(value2Ptr, i2, w2);
- if (valuePtr->typePtr == &tclWideIntType) {
-#ifdef TCL_COMPILE_DEBUG
- w2 = Tcl_LongAsWide(i2);
-#endif /* TCL_COMPILE_DEBUG */
- if (w < 0) {
- wResult = ~w;
- } else {
- wResult = w;
- }
+
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ if ((type2 != TCL_NUMBER_LONG)
+ || (*(const long *)ptr2 > INT_MAX)) {
/*
- * Shift in steps when the shift gets large to prevent
- * annoying compiler/processor bugs. [Bug 868467]
+ * Again, technically, the value to be shifted could be an
+ * mp_int so huge that a right shift by (INT_MAX+1) bits could
+ * not take us to the result of 0 or -1, but since we're using
+ * mp_div_2d to do the work, and it takes only an int
+ * argument, we draw the line there.
*/
- if (i2 >= 64) {
- wResult = Tcl_LongAsWide(0);
- } else if (i2 > 60) {
- wResult >>= 30;
- wResult >>= 30;
- wResult >>= i2-60;
- } else if (i2 > 30) {
- wResult >>= 30;
- wResult >>= i2-30;
+
+ int zero;
+
+ switch (type1) {
+ case TCL_NUMBER_LONG:
+ zero = (*(const long *)ptr1 > 0L);
+ break;
+#ifndef NO_WIDE_TYPE
+ case TCL_NUMBER_WIDE:
+ zero = (*(const Tcl_WideInt *)ptr1 > (Tcl_WideInt)0);
+ break;
+#endif
+ case TCL_NUMBER_BIG: {
+ mp_int big1;
+ Tcl_TakeBignumFromObj(NULL, valuePtr, &big1);
+ zero = (mp_cmp_d(&big1, 0) == MP_GT);
+ mp_clear(&big1);
+ break;
+ }
+ default:
+ /* Unused, here to silence compiler warning. */
+ zero = 0;
+ }
+ if (zero) {
+ objResultPtr = constants[0];
+ } else {
+ TclNewIntObj(objResultPtr, -1);
+ }
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+ shift = (int)(*(const long *)ptr2);
+
+ /*
+ * Handle shifts within the native long range.
+ */
+
+ if (type1 == TCL_NUMBER_LONG) {
+ l1 = *((const long *)ptr1);
+ if ((size_t)shift >= CHAR_BIT*sizeof(long)) {
+ if (l1 >= (long)0) {
+ objResultPtr = constants[0];
+ } else {
+ TclNewIntObj(objResultPtr, -1);
+ }
} else {
- wResult >>= i2;
+ TclNewLongObj(objResultPtr, (l1 >> shift));
}
- if (w < 0) {
- wResult = ~wResult;
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+
+#ifndef NO_WIDE_TYPE
+ /*
+ * Handle shifts within the native wide range.
+ */
+
+ if (type1 == TCL_NUMBER_WIDE) {
+ Tcl_WideInt w = *(const Tcl_WideInt *)ptr1;
+
+ if ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideInt)) {
+ if (w >= (Tcl_WideInt)0) {
+ objResultPtr = constants[0];
+ } else {
+ TclNewIntObj(objResultPtr, -1);
+ }
+ } else {
+ objResultPtr = Tcl_NewWideIntObj(w >> shift);
}
- doWide = 1;
- break;
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
}
- if (i < 0) {
- iResult = ~i;
+#endif
+ }
+
+ {
+ mp_int big, bigResult, bigRemainder;
+
+ Tcl_TakeBignumFromObj(NULL, valuePtr, &big);
+
+ mp_init(&bigResult);
+ if (*pc == INST_LSHIFT) {
+ mp_mul_2d(&big, shift, &bigResult);
} else {
- iResult = i;
+ mp_init(&bigRemainder);
+ mp_div_2d(&big, shift, &bigResult, &bigRemainder);
+ if (mp_cmp_d(&bigRemainder, 0) == MP_LT) {
+ /*
+ * Convert to Tcl's integer division rules.
+ */
+
+ mp_sub_d(&bigResult, 1, &bigResult);
+ }
+ mp_clear(&bigRemainder);
+ }
+ mp_clear(&big);
+
+ if (!Tcl_IsShared(valuePtr)) {
+ Tcl_SetBignumObj(valuePtr, &bigResult);
+ TRACE(("%s\n", O2S(valuePtr)));
+ NEXT_INST_F(1, 1, 0);
}
+ objResultPtr = Tcl_NewBignumObj(&bigResult);
+ }
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+
+ case INST_BITOR:
+ case INST_BITXOR:
+ case INST_BITAND: {
+ ClientData ptr1, ptr2;
+ int type1, type2;
+ Tcl_Obj *value2Ptr = OBJ_AT_TOS;
+ Tcl_Obj *valuePtr = OBJ_UNDER_TOS;
+
+ result = GetNumberFromObj(NULL, valuePtr, &ptr1, &type1);
+ if ((result != TCL_OK)
+ || (type1 == TCL_NUMBER_NAN)
+ || (type1 == TCL_NUMBER_DOUBLE)) {
+ result = TCL_ERROR;
+ TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n", O2S(valuePtr),
+ O2S(value2Ptr), (valuePtr->typePtr?
+ valuePtr->typePtr->name : "null")));
+ DECACHE_STACK_INFO();
+ IllegalExprOperandType(interp, pc, valuePtr);
+ CACHE_STACK_INFO();
+ goto checkForCatch;
+ }
+ result = GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2);
+ if ((result != TCL_OK) || (type2 == TCL_NUMBER_NAN)
+ || (type2 == TCL_NUMBER_DOUBLE)) {
+ result = TCL_ERROR;
+ TRACE(("%.20s %.20s => ILLEGAL 2nd TYPE %s\n", O2S(valuePtr),
+ O2S(value2Ptr), (value2Ptr->typePtr?
+ value2Ptr->typePtr->name : "null")));
+ DECACHE_STACK_INFO();
+ IllegalExprOperandType(interp, pc, value2Ptr);
+ CACHE_STACK_INFO();
+ goto checkForCatch;
+ }
+
+ if ((type1 == TCL_NUMBER_BIG) || (type2 == TCL_NUMBER_BIG)) {
+ mp_int big1, big2, bigResult, *First, *Second;
+ int numPos;
+
+ Tcl_TakeBignumFromObj(NULL, valuePtr, &big1);
+ Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
+
/*
- * Shift in steps when the shift gets large to prevent
- * annoying compiler/processor bugs. [Bug 868467]
+ * Count how many positive arguments we have. If only one of the
+ * arguments is negative, store it in 'Second'.
*/
- if (i2 >= 64) {
- iResult = 0;
- } else if (i2 > 60) {
- iResult >>= 30;
- iResult >>= 30;
- iResult >>= i2-60;
- } else if (i2 > 30) {
- iResult >>= 30;
- iResult >>= i2-30;
+
+ if (mp_cmp_d(&big1, 0) != MP_LT) {
+ numPos = 1 + (mp_cmp_d(&big2, 0) != MP_LT);
+ First = &big1;
+ Second = &big2;
} else {
- iResult >>= i2;
- }
- if (i < 0) {
- iResult = ~iResult;
+ First = &big2;
+ Second = &big1;
+ numPos = (mp_cmp_d(First, 0) != MP_LT);
}
- break;
- case INST_BITOR:
- if (valuePtr->typePtr == &tclWideIntType
- || value2Ptr->typePtr == &tclWideIntType) {
- /*
- * Promote to wide
- */
- if (valuePtr->typePtr == &tclIntType) {
- w = Tcl_LongAsWide(i);
- } else if (value2Ptr->typePtr == &tclIntType) {
- w2 = Tcl_LongAsWide(i2);
+ mp_init(&bigResult);
+
+ switch (*pc) {
+ case INST_BITAND:
+ switch (numPos) {
+ case 2:
+ /*
+ * Both arguments positive, base case.
+ */
+
+ mp_and(First, Second, &bigResult);
+ break;
+ case 1:
+ /*
+ * First is positive; second negative:
+ * P & N = P & ~~N = P&~(-N-1) = P & (P ^ (-N-1))
+ */
+
+ mp_neg(Second, Second);
+ mp_sub_d(Second, 1, Second);
+ mp_xor(First, Second, &bigResult);
+ mp_and(First, &bigResult, &bigResult);
+ break;
+ case 0:
+ /*
+ * Both arguments negative:
+ * a & b = ~ (~a | ~b) = -(-a-1|-b-1)-1
+ */
+
+ mp_neg(First, First);
+ mp_sub_d(First, 1, First);
+ mp_neg(Second, Second);
+ mp_sub_d(Second, 1, Second);
+ mp_or(First, Second, &bigResult);
+ mp_neg(&bigResult, &bigResult);
+ mp_sub_d(&bigResult, 1, &bigResult);
+ break;
}
- wResult = w | w2;
- doWide = 1;
break;
- }
- iResult = i | i2;
- break;
- case INST_BITXOR:
- if (valuePtr->typePtr == &tclWideIntType
- || value2Ptr->typePtr == &tclWideIntType) {
- /*
- * Promote to wide
- */
- if (valuePtr->typePtr == &tclIntType) {
- w = Tcl_LongAsWide(i);
- } else if (value2Ptr->typePtr == &tclIntType) {
- w2 = Tcl_LongAsWide(i2);
+
+ case INST_BITOR:
+ switch (numPos) {
+ case 2:
+ /*
+ * Both arguments positive, base case.
+ */
+
+ mp_or(First, Second, &bigResult);
+ break;
+ case 1:
+ /*
+ * First is positive; second negative:
+ * N|P = ~(~N&~P) = ~((-N-1)&~P) = -((-N-1)&((-N-1)^P))-1
+ */
+
+ mp_neg(Second, Second);
+ mp_sub_d(Second, 1, Second);
+ mp_xor(First, Second, &bigResult);
+ mp_and(Second, &bigResult, &bigResult);
+ mp_neg(&bigResult, &bigResult);
+ mp_sub_d(&bigResult, 1, &bigResult);
+ break;
+ case 0:
+ /*
+ * Both arguments negative:
+ * a | b = ~ (~a & ~b) = -(-a-1&-b-1)-1
+ */
+
+ mp_neg(First, First);
+ mp_sub_d(First, 1, First);
+ mp_neg(Second, Second);
+ mp_sub_d(Second, 1, Second);
+ mp_and(First, Second, &bigResult);
+ mp_neg(&bigResult, &bigResult);
+ mp_sub_d(&bigResult, 1, &bigResult);
+ break;
}
- wResult = w ^ w2;
- doWide = 1;
break;
- }
- iResult = i ^ i2;
- break;
- case INST_BITAND:
- if (valuePtr->typePtr == &tclWideIntType
- || value2Ptr->typePtr == &tclWideIntType) {
- /*
- * Promote to wide
- */
- if (valuePtr->typePtr == &tclIntType) {
- w = Tcl_LongAsWide(i);
- } else if (value2Ptr->typePtr == &tclIntType) {
- w2 = Tcl_LongAsWide(i2);
+
+ case INST_BITXOR:
+ switch (numPos) {
+ case 2:
+ /*
+ * Both arguments positive, base case.
+ */
+
+ mp_xor(First, Second, &bigResult);
+ break;
+ case 1:
+ /*
+ * First is positive; second negative:
+ * P^N = ~(P^~N) = -(P^(-N-1))-1
+ */
+
+ mp_neg(Second, Second);
+ mp_sub_d(Second, 1, Second);
+ mp_xor(First, Second, &bigResult);
+ mp_neg(&bigResult, &bigResult);
+ mp_sub_d(&bigResult, 1, &bigResult);
+ break;
+ case 0:
+ /*
+ * Both arguments negative:
+ * a ^ b = (~a ^ ~b) = (-a-1^-b-1)
+ */
+
+ mp_neg(First, First);
+ mp_sub_d(First, 1, First);
+ mp_neg(Second, Second);
+ mp_sub_d(Second, 1, Second);
+ mp_xor(First, Second, &bigResult);
+ break;
}
- wResult = w & w2;
- doWide = 1;
break;
}
- iResult = i & i2;
- break;
+
+ mp_clear(&big1);
+ mp_clear(&big2);
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ if (Tcl_IsShared(valuePtr)) {
+ objResultPtr = Tcl_NewBignumObj(&bigResult);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+ Tcl_SetBignumObj(valuePtr, &bigResult);
+ TRACE(("%s\n", O2S(valuePtr)));
+ NEXT_INST_F(1, 1, 0);
}
- /*
- * Reuse the valuePtr object already on stack if possible.
- */
-
- if (Tcl_IsShared(valuePtr)) {
- if (doWide) {
+#ifndef NO_WIDE_TYPE
+ if ((type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_WIDE)) {
+ Tcl_WideInt wResult, w1, w2;
+
+ TclGetWideIntFromObj(NULL, valuePtr, &w1);
+ TclGetWideIntFromObj(NULL, value2Ptr, &w2);
+
+ switch (*pc) {
+ case INST_BITAND:
+ wResult = w1 & w2;
+ break;
+ case INST_BITOR:
+ wResult = w1 | w2;
+ break;
+ case INST_BITXOR:
+ wResult = w1 ^ w2;
+ break;
+ default:
+ /* Unused, here to silence compiler warning. */
+ wResult = 0;
+ }
+
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ if (Tcl_IsShared(valuePtr)) {
objResultPtr = Tcl_NewWideIntObj(wResult);
- TRACE((LLD" "LLD" => "LLD"\n", w, w2, wResult));
- } else {
- objResultPtr = Tcl_NewLongObj(iResult);
- TRACE(("%ld %ld => %ld\n", i, i2, iResult));
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
}
- NEXT_INST_F(1, 2, 1);
- } else { /* reuse the valuePtr object */
- if (doWide) {
- TRACE((LLD" "LLD" => "LLD"\n", w, w2, wResult));
- Tcl_SetWideIntObj(valuePtr, wResult);
- } else {
- TRACE(("%ld %ld => %ld\n", i, i2, iResult));
- Tcl_SetLongObj(valuePtr, iResult);
+ Tcl_SetWideIntObj(valuePtr, wResult);
+ TRACE(("%s\n", O2S(valuePtr)));
+ NEXT_INST_F(1, 1, 0);
+ }
+#endif
+ {
+ long lResult, l1 = *((const long *)ptr1);
+ long l2 = *((const long *)ptr2);
+
+ switch (*pc) {
+ case INST_BITAND:
+ lResult = l1 & l2;
+ break;
+ case INST_BITOR:
+ lResult = l1 | l2;
+ break;
+ case INST_BITXOR:
+ lResult = l1 ^ l2;
+ break;
+ default:
+ /* Unused, here to silence compiler warning. */
+ lResult = 0;
+ }
+
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ if (Tcl_IsShared(valuePtr)) {
+ TclNewLongObj(objResultPtr, lResult);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
}
+ TclSetLongObj(valuePtr, lResult);
+ TRACE(("%s\n", O2S(valuePtr)));
NEXT_INST_F(1, 1, 0);
}
}
+ case INST_EXPON:
case INST_ADD:
case INST_SUB:
- case INST_MULT:
case INST_DIV:
- {
- /*
- * Operands must be numeric and ints get converted to floats
- * if necessary. We compute value op value2.
- */
+ case INST_MULT: {
+ ClientData ptr1, ptr2;
+ int type1, type2;
+ Tcl_Obj *value2Ptr = OBJ_AT_TOS;
+ Tcl_Obj *valuePtr = OBJ_UNDER_TOS;
+
+ result = GetNumberFromObj(NULL, valuePtr, &ptr1, &type1);
+ if ((result != TCL_OK)
+#ifndef ACCEPT_NAN
+ || (type1 == TCL_NUMBER_NAN)
+#endif
+ ) {
+ result = TCL_ERROR;
+ TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n",
+ O2S(value2Ptr), O2S(valuePtr),
+ (valuePtr->typePtr? valuePtr->typePtr->name: "null")));
+ DECACHE_STACK_INFO();
+ IllegalExprOperandType(interp, pc, valuePtr);
+ CACHE_STACK_INFO();
+ goto checkForCatch;
+ }
- Tcl_ObjType *t1Ptr, *t2Ptr;
- long i2 = 0, quot, rem; /* Init. avoids compiler warning. */
- double d1, d2;
- long iResult = 0; /* Init. avoids compiler warning. */
- double dResult = 0.0; /* Init. avoids compiler warning. */
- int doDouble = 0; /* 1 if doing floating arithmetic */
- Tcl_WideInt w2, wquot, wrem;
- Tcl_WideInt wResult = W0; /* Init. avoids compiler warning. */
- int doWide = 0; /* 1 if doing wide arithmetic. */
-
- value2Ptr = stackPtr[stackTop];
- valuePtr = stackPtr[stackTop - 1];
- t1Ptr = valuePtr->typePtr;
- t2Ptr = value2Ptr->typePtr;
-
- if (t1Ptr == &tclIntType) {
- i = valuePtr->internalRep.longValue;
- } else if (t1Ptr == &tclWideIntType) {
- TclGetWide(w,valuePtr);
- } else if ((t1Ptr == &tclDoubleType)
- && (valuePtr->bytes == NULL)) {
+#ifdef ACCEPT_NAN
+ if (type1 == TCL_NUMBER_NAN) {
/*
- * We can only use the internal rep directly if there is
- * no string rep. Otherwise the string rep might actually
- * look like an integer, which is preferred.
+ * NaN first argument -> result is also NaN.
*/
- d1 = valuePtr->internalRep.doubleValue;
- } else {
- char *s = Tcl_GetStringFromObj(valuePtr, &length);
- if (TclLooksLikeInt(s, length)) {
- GET_WIDE_OR_INT(result, valuePtr, i, w);
- } else {
- result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
- valuePtr, &d1);
- }
- if (result != TCL_OK) {
- TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n",
- s, O2S(valuePtr),
- (valuePtr->typePtr?
- valuePtr->typePtr->name : "null")));
- DECACHE_STACK_INFO();
- IllegalExprOperandType(interp, pc, valuePtr);
- CACHE_STACK_INFO();
- goto checkForCatch;
- }
- t1Ptr = valuePtr->typePtr;
+ NEXT_INST_F(1, 1, 0);
}
+#endif
- if (t2Ptr == &tclIntType) {
- i2 = value2Ptr->internalRep.longValue;
- } else if (t2Ptr == &tclWideIntType) {
- TclGetWide(w2,value2Ptr);
- } else if ((t2Ptr == &tclDoubleType)
- && (value2Ptr->bytes == NULL)) {
+ result = GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2);
+ if ((result != TCL_OK)
+#ifndef ACCEPT_NAN
+ || (type2 == TCL_NUMBER_NAN)
+#endif
+ ) {
+ result = TCL_ERROR;
+ TRACE(("%.20s %.20s => ILLEGAL 2nd TYPE %s\n",
+ O2S(value2Ptr), O2S(valuePtr),
+ (value2Ptr->typePtr? value2Ptr->typePtr->name: "null")));
+ DECACHE_STACK_INFO();
+ IllegalExprOperandType(interp, pc, value2Ptr);
+ CACHE_STACK_INFO();
+ goto checkForCatch;
+ }
+
+#ifdef ACCEPT_NAN
+ if (type2 == TCL_NUMBER_NAN) {
/*
- * We can only use the internal rep directly if there is
- * no string rep. Otherwise the string rep might actually
- * look like an integer, which is preferred.
+ * NaN second argument -> result is also NaN.
*/
- d2 = value2Ptr->internalRep.doubleValue;
- } else {
- char *s = Tcl_GetStringFromObj(value2Ptr, &length);
- if (TclLooksLikeInt(s, length)) {
- GET_WIDE_OR_INT(result, value2Ptr, i2, w2);
- } else {
- result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
- value2Ptr, &d2);
- }
- if (result != TCL_OK) {
- TRACE(("%.20s %.20s => ILLEGAL 2nd TYPE %s\n",
- O2S(value2Ptr), s,
- (value2Ptr->typePtr?
- value2Ptr->typePtr->name : "null")));
- DECACHE_STACK_INFO();
- IllegalExprOperandType(interp, pc, value2Ptr);
- CACHE_STACK_INFO();
- goto checkForCatch;
- }
- t2Ptr = value2Ptr->typePtr;
+ objResultPtr = value2Ptr;
+ NEXT_INST_F(1, 2, 1);
}
+#endif
- if ((t1Ptr == &tclDoubleType) || (t2Ptr == &tclDoubleType)) {
+ if ((type1 == TCL_NUMBER_DOUBLE) || (type2 == TCL_NUMBER_DOUBLE)) {
/*
- * Do double arithmetic.
+ * At least one of the values is floating-point, so perform
+ * floating point calculations.
*/
- doDouble = 1;
- if (t1Ptr == &tclIntType) {
- d1 = i; /* promote value 1 to double */
- } else if (t2Ptr == &tclIntType) {
- d2 = i2; /* promote value 2 to double */
- } else if (t1Ptr == &tclWideIntType) {
- d1 = Tcl_WideAsDouble(w);
- } else if (t2Ptr == &tclWideIntType) {
- d2 = Tcl_WideAsDouble(w2);
- }
+
+ double d1, d2, dResult;
+
+ Tcl_GetDoubleFromObj(NULL, valuePtr, &d1);
+ Tcl_GetDoubleFromObj(NULL, value2Ptr, &d2);
+
switch (*pc) {
- case INST_ADD:
- dResult = d1 + d2;
- break;
- case INST_SUB:
- dResult = d1 - d2;
- break;
- case INST_MULT:
- dResult = d1 * d2;
- break;
- case INST_DIV:
- if (d2 == 0.0) {
- TRACE(("%.6g %.6g => DIVIDE BY ZERO\n", d1, d2));
- goto divideByZero;
- }
- dResult = d1 / d2;
- break;
+ case INST_ADD:
+ dResult = d1 + d2;
+ break;
+ case INST_SUB:
+ dResult = d1 - d2;
+ break;
+ case INST_MULT:
+ dResult = d1 * d2;
+ break;
+ case INST_DIV:
+#ifndef IEEE_FLOATING_POINT
+ if (d2 == 0.0) {
+ TRACE(("%.6g %.6g => DIVIDE BY ZERO\n", d1, d2));
+ goto divideByZero;
+ }
+#endif
+ /*
+ * We presume that we are running with zero-divide unmasked if
+ * we're on an IEEE box. Otherwise, this statement might cause
+ * demons to fly out our noses.
+ */
+
+ dResult = d1 / d2;
+ break;
+ case INST_EXPON:
+ if (d1==0.0 && d2<0.0) {
+ TRACE(("%.6g %.6g => EXPONENT OF ZERO\n", d1, d2));
+ goto exponOfZero;
+ }
+ dResult = pow(d1, d2);
+ break;
+ default:
+ /* Unused, here to silence compiler warning. */
+ dResult = 0;
}
-
+
+#ifndef ACCEPT_NAN
/*
* Check now for IEEE floating-point error.
*/
-
- if (IS_NAN(dResult) || IS_INF(dResult)) {
+
+ if (TclIsNaN(dResult)) {
TRACE(("%.20s %.20s => IEEE FLOATING PT ERROR\n",
- O2S(valuePtr), O2S(value2Ptr)));
+ O2S(valuePtr), O2S(value2Ptr)));
DECACHE_STACK_INFO();
TclExprFloatError(interp, dResult);
CACHE_STACK_INFO();
result = TCL_ERROR;
goto checkForCatch;
}
- } else if ((t1Ptr == &tclWideIntType)
- || (t2Ptr == &tclWideIntType)) {
- /*
- * Do wide integer arithmetic.
- */
- doWide = 1;
- if (t1Ptr == &tclIntType) {
- w = Tcl_LongAsWide(i);
- } else if (t2Ptr == &tclIntType) {
- w2 = Tcl_LongAsWide(i2);
+#endif
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ if (Tcl_IsShared(valuePtr)) {
+ TclNewDoubleObj(objResultPtr, dResult);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
}
- switch (*pc) {
- case INST_ADD:
- wResult = w + w2;
- break;
- case INST_SUB:
- wResult = w - w2;
- break;
- case INST_MULT:
- wResult = w * w2;
- break;
- case INST_DIV:
+ TclSetDoubleObj(valuePtr, dResult);
+ TRACE(("%s\n", O2S(valuePtr)));
+ NEXT_INST_F(1, 1, 0);
+ }
+
+ if ((sizeof(long) >= 2*sizeof(int)) && (*pc == INST_MULT)
+ && (type1 == TCL_NUMBER_LONG) && (type2 == TCL_NUMBER_LONG)) {
+ long l1 = *((const long *)ptr1);
+ long l2 = *((const long *)ptr2);
+
+ if ((l1 <= INT_MAX) && (l1 >= INT_MIN)
+ && (l2 <= INT_MAX) && (l2 >= INT_MIN)) {
+ long lResult = l1 * l2;
+
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ if (Tcl_IsShared(valuePtr)) {
+ TclNewLongObj(objResultPtr,lResult);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+ TclSetLongObj(valuePtr, lResult);
+ TRACE(("%s\n", O2S(valuePtr)));
+ NEXT_INST_F(1, 1, 0);
+ }
+ }
+
+ if ((sizeof(Tcl_WideInt) >= 2*sizeof(long)) && (*pc == INST_MULT)
+ && (type1 == TCL_NUMBER_LONG) && (type2 == TCL_NUMBER_LONG)) {
+ Tcl_WideInt w1, w2, wResult;
+ TclGetWideIntFromObj(NULL, valuePtr, &w1);
+ TclGetWideIntFromObj(NULL, value2Ptr, &w2);
+
+ wResult = w1 * w2;
+
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ if (Tcl_IsShared(valuePtr)) {
+ objResultPtr = Tcl_NewWideIntObj(wResult);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+ Tcl_SetWideIntObj(valuePtr, wResult);
+ TRACE(("%s\n", O2S(valuePtr)));
+ NEXT_INST_F(1, 1, 0);
+ }
+
+ /* TODO: Attempts to re-use unshared operands on stack. */
+ if (*pc == INST_EXPON) {
+ long l1 = 0, l2 = 0;
+ int oddExponent = 0, negativeExponent = 0;
+#if (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG)
+ Tcl_WideInt w1;
+#endif
+
+ if (type2 == TCL_NUMBER_LONG) {
+ l2 = *((const long *) ptr2);
+ if (l2 == 0) {
/*
- * This code is tricky: C doesn't guarantee much
- * about the quotient or remainder, but Tcl does.
- * The remainder always has the same sign as the
- * divisor and a smaller absolute value.
+ * Anything to the zero power is 1.
*/
- if (w2 == W0) {
- TRACE((LLD" "LLD" => DIVIDE BY ZERO\n", w, w2));
- goto divideByZero;
- }
- if (w2 < 0) {
- w2 = -w2;
- w = -w;
+
+ objResultPtr = constants[1];
+ NEXT_INST_F(1, 2, 1);
+ } else if (l2 == 1) {
+ /*
+ * Anything to the first power is itself
+ */
+ NEXT_INST_F(1, 1, 0);
+ }
+ }
+
+ switch (type2) {
+ case TCL_NUMBER_LONG: {
+ negativeExponent = (l2 < 0);
+ oddExponent = (int) (l2 & 1);
+ break;
+ }
+#ifndef NO_WIDE_TYPE
+ case TCL_NUMBER_WIDE: {
+ Tcl_WideInt w2 = *((const Tcl_WideInt *)ptr2);
+
+ negativeExponent = (w2 < 0);
+ oddExponent = (int) (w2 & (Tcl_WideInt)1);
+ break;
+ }
+#endif
+ case TCL_NUMBER_BIG: {
+ mp_int big2;
+
+ Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
+ negativeExponent = (mp_cmp_d(&big2, 0) == MP_LT);
+ mp_mod_2d(&big2, 1, &big2);
+ oddExponent = !mp_iszero(&big2);
+ mp_clear(&big2);
+ break;
+ }
+ }
+
+ if (type1 == TCL_NUMBER_LONG) {
+ l1 = *((const long *)ptr1);
+ }
+ if (negativeExponent) {
+ if (type1 == TCL_NUMBER_LONG) {
+ switch (l1) {
+ case 0:
+ /*
+ * Zero to a negative power is div by zero error.
+ */
+
+ TRACE(("%s %s => EXPONENT OF ZERO\n", O2S(valuePtr),
+ O2S(value2Ptr)));
+ goto exponOfZero;
+ case -1:
+ if (oddExponent) {
+ TclNewIntObj(objResultPtr, -1);
+ } else {
+ objResultPtr = constants[1];
+ }
+ NEXT_INST_F(1, 2, 1);
+ case 1:
+ /*
+ * 1 to any power is 1.
+ */
+
+ objResultPtr = constants[1];
+ NEXT_INST_F(1, 2, 1);
}
- wquot = w / w2;
- wrem = w % w2;
- if (wrem < W0) {
- wquot -= 1;
+ }
+
+ /*
+ * Integers with magnitude greater than 1 raise to a negative
+ * power yield the answer zero (see TIP 123).
+ */
+
+ objResultPtr = constants[0];
+ NEXT_INST_F(1, 2, 1);
+ }
+
+ if (type1 == TCL_NUMBER_LONG) {
+ switch (l1) {
+ case 0:
+ /*
+ * Zero to a positive power is zero.
+ */
+
+ objResultPtr = constants[0];
+ NEXT_INST_F(1, 2, 1);
+ case 1:
+ /*
+ * 1 to any power is 1.
+ */
+
+ objResultPtr = constants[1];
+ NEXT_INST_F(1, 2, 1);
+ case -1:
+ if (oddExponent) {
+ TclNewIntObj(objResultPtr, -1);
+ } else {
+ objResultPtr = constants[1];
}
- wResult = wquot;
- break;
+ NEXT_INST_F(1, 2, 1);
+ }
}
- } else {
/*
- * Do integer arithmetic.
+ * We refuse to accept exponent arguments that exceed
+ * one mp_digit which means the max exponent value is
+ * 2**28-1 = 0x0fffffff = 268435455, which fits into
+ * a signed 32 bit int which is within the range of the
+ * long int type. This means any numeric Tcl_Obj value
+ * not using TCL_NUMBER_LONG type must hold a value larger
+ * than we accept.
+ */
+ if (type2 != TCL_NUMBER_LONG) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("exponent too large", -1));
+ result = TCL_ERROR;
+ goto checkForCatch;
+ }
+
+ if (type1 == TCL_NUMBER_LONG) {
+ if (l1 == 2) {
+ /*
+ * Reduce small powers of 2 to shifts.
*/
- switch (*pc) {
- case INST_ADD:
- iResult = i + i2;
- break;
- case INST_SUB:
- iResult = i - i2;
- break;
- case INST_MULT:
- iResult = i * i2;
- break;
- case INST_DIV:
+
+ if ((unsigned long) l2 < CHAR_BIT * sizeof(long) - 1) {
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ TclNewLongObj(objResultPtr, (1L << l2));
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+#if !defined(TCL_WIDE_INT_IS_LONG)
+ if ((unsigned long)l2 < CHAR_BIT*sizeof(Tcl_WideInt) - 1){
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ objResultPtr =
+ Tcl_NewWideIntObj(((Tcl_WideInt) 1) << l2);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+#endif
+ goto overflow;
+ }
+ if (l1 == -2) {
+ int signum = oddExponent ? -1 : 1;
+
/*
- * This code is tricky: C doesn't guarantee much
- * about the quotient or remainder, but Tcl does.
- * The remainder always has the same sign as the
- * divisor and a smaller absolute value.
+ * Reduce small powers of 2 to shifts.
*/
- if (i2 == 0) {
- TRACE(("%ld %ld => DIVIDE BY ZERO\n", i, i2));
- goto divideByZero;
+
+ if ((unsigned long) l2 < CHAR_BIT * sizeof(long) - 1) {
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ TclNewLongObj(objResultPtr, signum * (1L << l2));
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
}
- if (i2 < 0) {
- i2 = -i2;
- i = -i;
+#if !defined(TCL_WIDE_INT_IS_LONG)
+ if ((unsigned long)l2 < CHAR_BIT*sizeof(Tcl_WideInt) - 1){
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ objResultPtr = Tcl_NewWideIntObj(
+ signum * (((Tcl_WideInt) 1) << l2));
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
}
- quot = i / i2;
- rem = i % i2;
- if (rem < 0) {
- quot -= 1;
+#endif
+ goto overflow;
+ }
+#if (LONG_MAX == 0x7fffffff)
+ if (l2 - 2 < (long)MaxBase32Size
+ && l1 <= MaxBase32[l2 - 2]
+ && l1 >= -MaxBase32[l2 - 2]) {
+ /*
+ * Small powers of 32-bit integers.
+ */
+
+ long lResult = l1 * l1; /* b**2 */
+ switch (l2) {
+ case 2:
+ break;
+ case 3:
+ lResult *= l1; /* b**3 */
+ break;
+ case 4:
+ lResult *= lResult; /* b**4 */
+ break;
+ case 5:
+ lResult *= lResult; /* b**4 */
+ lResult *= l1; /* b**5 */
+ break;
+ case 6:
+ lResult *= l1; /* b**3 */
+ lResult *= lResult; /* b**6 */
+ break;
+ case 7:
+ lResult *= l1; /* b**3 */
+ lResult *= lResult; /* b**6 */
+ lResult *= l1; /* b**7 */
+ break;
+ case 8:
+ lResult *= lResult; /* b**4 */
+ lResult *= lResult; /* b**8 */
+ break;
}
- iResult = quot;
- break;
- }
- }
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ if (Tcl_IsShared(valuePtr)) {
+ TclNewLongObj(objResultPtr, lResult);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+ Tcl_SetLongObj(valuePtr, lResult);
+ TRACE(("%s\n", O2S(valuePtr)));
+ NEXT_INST_F(1, 1, 0);
+ }
+ if (l1 - 3 >= 0 && l1 - 2 < (long)Exp32IndexSize
+ && l2 - 2 < (long)(Exp32ValueSize + MaxBase32Size)) {
- /*
- * Reuse the valuePtr object already on stack if possible.
- */
-
- if (Tcl_IsShared(valuePtr)) {
- if (doDouble) {
- objResultPtr = Tcl_NewDoubleObj(dResult);
- TRACE(("%.6g %.6g => %.6g\n", d1, d2, dResult));
- } else if (doWide) {
- objResultPtr = Tcl_NewWideIntObj(wResult);
- TRACE((LLD" "LLD" => "LLD"\n", w, w2, wResult));
- } else {
- objResultPtr = Tcl_NewLongObj(iResult);
- TRACE(("%ld %ld => %ld\n", i, i2, iResult));
- }
- NEXT_INST_F(1, 2, 1);
- } else { /* reuse the valuePtr object */
- if (doDouble) { /* NB: stack top is off by 1 */
- TRACE(("%.6g %.6g => %.6g\n", d1, d2, dResult));
- Tcl_SetDoubleObj(valuePtr, dResult);
- } else if (doWide) {
- TRACE((LLD" "LLD" => "LLD"\n", w, w2, wResult));
- Tcl_SetWideIntObj(valuePtr, wResult);
- } else {
- TRACE(("%ld %ld => %ld\n", i, i2, iResult));
- Tcl_SetLongObj(valuePtr, iResult);
- }
- NEXT_INST_F(1, 1, 0);
- }
- }
+ unsigned short base = Exp32Index[l1 - 3]
+ + (unsigned short) (l2 - 2 - MaxBase32Size);
+ if (base < Exp32Index[l1 - 2]) {
+ /*
+ * 32-bit number raised to intermediate power, done by
+ * table lookup.
+ */
- case INST_UPLUS:
- {
- /*
- * Operand must be numeric.
- */
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ if (Tcl_IsShared(valuePtr)) {
+ TclNewLongObj(objResultPtr, Exp32Value[base]);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+ Tcl_SetLongObj(valuePtr, Exp32Value[base]);
+ TRACE(("%s\n", O2S(valuePtr)));
+ NEXT_INST_F(1, 1, 0);
+ }
+ }
+ if (-l1 - 3 >= 0 && -l1 - 2 < (long)Exp32IndexSize
+ && l2 - 2 < (long)(Exp32ValueSize + MaxBase32Size)) {
+ unsigned short base = Exp32Index[-l1 - 3]
+ + (unsigned short) (l2 - 2 - MaxBase32Size);
+ if (base < Exp32Index[-l1 - 2]) {
+ long lResult = (oddExponent) ?
+ -Exp32Value[base] : Exp32Value[base];
- double d;
- Tcl_ObjType *tPtr;
-
- valuePtr = stackPtr[stackTop];
- tPtr = valuePtr->typePtr;
- if (!IS_INTEGER_TYPE(tPtr) && ((tPtr != &tclDoubleType)
- || (valuePtr->bytes != NULL))) {
- char *s = Tcl_GetStringFromObj(valuePtr, &length);
- if (TclLooksLikeInt(s, length)) {
- GET_WIDE_OR_INT(result, valuePtr, i, w);
- } else {
- result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, valuePtr, &d);
+ /*
+ * 32-bit number raised to intermediate power, done by
+ * table lookup.
+ */
+
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ if (Tcl_IsShared(valuePtr)) {
+ TclNewLongObj(objResultPtr, lResult);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+ Tcl_SetLongObj(valuePtr, lResult);
+ TRACE(("%s\n", O2S(valuePtr)));
+ NEXT_INST_F(1, 1, 0);
+ }
+ }
+#endif
}
- if (result != TCL_OK) {
- TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n",
- s, (tPtr? tPtr->name : "null")));
- DECACHE_STACK_INFO();
- IllegalExprOperandType(interp, pc, valuePtr);
- CACHE_STACK_INFO();
- goto checkForCatch;
+#if (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG)
+ if (type1 == TCL_NUMBER_LONG) {
+ w1 = l1;
+#ifndef NO_WIDE_TYPE
+ } else if (type1 == TCL_NUMBER_WIDE) {
+ w1 = *((const Tcl_WideInt*) ptr1);
+#endif
+ } else {
+ goto overflow;
}
- tPtr = valuePtr->typePtr;
- }
+ if (l2 - 2 < (long)MaxBase64Size
+ && w1 <= MaxBase64[l2 - 2]
+ && w1 >= -MaxBase64[l2 - 2]) {
+ /*
+ * Small powers of integers whose result is wide.
+ */
- /*
- * Ensure that the operand's string rep is the same as the
- * formatted version of its internal rep. This makes sure
- * that "expr +000123" yields "83", not "000123". We
- * implement this by _discarding_ the string rep since we
- * know it will be regenerated, if needed later, by
- * formatting the internal rep's value.
- */
+ Tcl_WideInt wResult = w1 * w1; /* b**2 */
- if (Tcl_IsShared(valuePtr)) {
- if (tPtr == &tclIntType) {
- i = valuePtr->internalRep.longValue;
- objResultPtr = Tcl_NewLongObj(i);
- } else if (tPtr == &tclWideIntType) {
- TclGetWide(w,valuePtr);
- objResultPtr = Tcl_NewWideIntObj(w);
- } else {
- d = valuePtr->internalRep.doubleValue;
- objResultPtr = Tcl_NewDoubleObj(d);
+ switch (l2) {
+ case 2:
+ break;
+ case 3:
+ wResult *= l1; /* b**3 */
+ break;
+ case 4:
+ wResult *= wResult; /* b**4 */
+ break;
+ case 5:
+ wResult *= wResult; /* b**4 */
+ wResult *= w1; /* b**5 */
+ break;
+ case 6:
+ wResult *= w1; /* b**3 */
+ wResult *= wResult; /* b**6 */
+ break;
+ case 7:
+ wResult *= w1; /* b**3 */
+ wResult *= wResult; /* b**6 */
+ wResult *= w1; /* b**7 */
+ break;
+ case 8:
+ wResult *= wResult; /* b**4 */
+ wResult *= wResult; /* b**8 */
+ break;
+ case 9:
+ wResult *= wResult; /* b**4 */
+ wResult *= wResult; /* b**8 */
+ wResult *= w1; /* b**9 */
+ break;
+ case 10:
+ wResult *= wResult; /* b**4 */
+ wResult *= w1; /* b**5 */
+ wResult *= wResult; /* b**10 */
+ break;
+ case 11:
+ wResult *= wResult; /* b**4 */
+ wResult *= w1; /* b**5 */
+ wResult *= wResult; /* b**10 */
+ wResult *= w1; /* b**11 */
+ break;
+ case 12:
+ wResult *= w1; /* b**3 */
+ wResult *= wResult; /* b**6 */
+ wResult *= wResult; /* b**12 */
+ break;
+ case 13:
+ wResult *= w1; /* b**3 */
+ wResult *= wResult; /* b**6 */
+ wResult *= wResult; /* b**12 */
+ wResult *= w1; /* b**13 */
+ break;
+ case 14:
+ wResult *= w1; /* b**3 */
+ wResult *= wResult; /* b**6 */
+ wResult *= w1; /* b**7 */
+ wResult *= wResult; /* b**14 */
+ break;
+ case 15:
+ wResult *= w1; /* b**3 */
+ wResult *= wResult; /* b**6 */
+ wResult *= w1; /* b**7 */
+ wResult *= wResult; /* b**14 */
+ wResult *= w1; /* b**15 */
+ break;
+ case 16:
+ wResult *= wResult; /* b**4 */
+ wResult *= wResult; /* b**8 */
+ wResult *= wResult; /* b**16 */
+ break;
+
+ }
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ objResultPtr = Tcl_NewWideIntObj(wResult);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
}
- TRACE_WITH_OBJ(("%s => ", O2S(objResultPtr)), objResultPtr);
- NEXT_INST_F(1, 1, 1);
- } else {
- Tcl_InvalidateStringRep(valuePtr);
- TRACE_WITH_OBJ(("%s => ", O2S(valuePtr)), valuePtr);
- NEXT_INST_F(1, 0, 0);
- }
- }
-
- case INST_UMINUS:
- case INST_LNOT:
- {
- /*
- * The operand must be numeric or a boolean string as
- * accepted by Tcl_GetBooleanFromObj(). If the operand
- * object is unshared modify it directly, otherwise
- * create a copy to modify: this is "copy on write".
- * Free any old string representation since it is now
- * invalid.
- */
- double d;
- int boolvar;
- Tcl_ObjType *tPtr;
+ /*
+ * Handle cases of powers > 16 that still fit in a 64-bit word by
+ * doing table lookup.
+ */
+ if (w1 - 3 >= 0 && w1 - 2 < (long)Exp64IndexSize
+ && l2 - 2 < (long)(Exp64ValueSize + MaxBase64Size)) {
+ unsigned short base = Exp64Index[w1 - 3]
+ + (unsigned short) (l2 - 2 - MaxBase64Size);
+
+ if (base < Exp64Index[w1 - 2]) {
+ /*
+ * 64-bit number raised to intermediate power, done by
+ * table lookup.
+ */
- valuePtr = stackPtr[stackTop];
- tPtr = valuePtr->typePtr;
- if (!IS_INTEGER_TYPE(tPtr) && ((tPtr != &tclDoubleType)
- || (valuePtr->bytes != NULL))) {
- if ((tPtr == &tclBooleanType) && (valuePtr->bytes == NULL)) {
- valuePtr->typePtr = &tclIntType;
- } else {
- char *s = Tcl_GetStringFromObj(valuePtr, &length);
- if (TclLooksLikeInt(s, length)) {
- GET_WIDE_OR_INT(result, valuePtr, i, w);
- } else {
- result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
- valuePtr, &d);
- }
- if (result == TCL_ERROR && *pc == INST_LNOT) {
- result = Tcl_GetBooleanFromObj((Tcl_Interp *)NULL,
- valuePtr, &boolvar);
- i = (long)boolvar; /* i is long, not int! */
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ if (Tcl_IsShared(valuePtr)) {
+ objResultPtr = Tcl_NewWideIntObj(Exp64Value[base]);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+ Tcl_SetWideIntObj(valuePtr, Exp64Value[base]);
+ TRACE(("%s\n", O2S(valuePtr)));
+ NEXT_INST_F(1, 1, 0);
}
- if (result != TCL_OK) {
- TRACE(("\"%.20s\" => ILLEGAL TYPE %s\n",
- s, (tPtr? tPtr->name : "null")));
- DECACHE_STACK_INFO();
- IllegalExprOperandType(interp, pc, valuePtr);
- CACHE_STACK_INFO();
- goto checkForCatch;
+ }
+
+ if (-w1 - 3 >= 0 && -w1 - 2 < (long)Exp64IndexSize
+ && l2 - 2 < (long)(Exp64ValueSize + MaxBase64Size)) {
+ unsigned short base = Exp64Index[-w1 - 3]
+ + (unsigned short) (l2 - 2 - MaxBase64Size);
+
+ if (base < Exp64Index[-w1 - 2]) {
+ Tcl_WideInt wResult = (oddExponent) ?
+ -Exp64Value[base] : Exp64Value[base];
+ /*
+ * 64-bit number raised to intermediate power, done by
+ * table lookup.
+ */
+
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ if (Tcl_IsShared(valuePtr)) {
+ objResultPtr = Tcl_NewWideIntObj(wResult);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+ Tcl_SetWideIntObj(valuePtr, wResult);
+ TRACE(("%s\n", O2S(valuePtr)));
+ NEXT_INST_F(1, 1, 0);
}
}
- tPtr = valuePtr->typePtr;
+#endif
+
+ goto overflow;
}
- if (Tcl_IsShared(valuePtr)) {
- /*
- * Create a new object.
- */
- if ((tPtr == &tclIntType) || (tPtr == &tclBooleanType)) {
- i = valuePtr->internalRep.longValue;
- objResultPtr = Tcl_NewLongObj(
- (*pc == INST_UMINUS)? -i : !i);
- TRACE_WITH_OBJ(("%ld => ", i), objResultPtr);
- } else if (tPtr == &tclWideIntType) {
- TclGetWide(w,valuePtr);
- if (*pc == INST_UMINUS) {
- objResultPtr = Tcl_NewWideIntObj(-w);
- } else {
- objResultPtr = Tcl_NewLongObj(w == W0);
+ if ((*pc != INST_MULT)
+ && (type1 != TCL_NUMBER_BIG) && (type2 != TCL_NUMBER_BIG)) {
+ Tcl_WideInt w1, w2, wResult;
+
+ TclGetWideIntFromObj(NULL, valuePtr, &w1);
+ TclGetWideIntFromObj(NULL, value2Ptr, &w2);
+
+ switch (*pc) {
+ case INST_ADD:
+ wResult = w1 + w2;
+#ifndef NO_WIDE_TYPE
+ if ((type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_WIDE))
+#endif
+ {
+ /*
+ * Check for overflow.
+ */
+
+ if (Overflowing(w1, w2, wResult)) {
+ goto overflow;
+ }
}
- TRACE_WITH_OBJ((LLD" => ", w), objResultPtr);
- } else {
- d = valuePtr->internalRep.doubleValue;
- if (*pc == INST_UMINUS) {
- objResultPtr = Tcl_NewDoubleObj(-d);
- } else {
+ break;
+
+ case INST_SUB:
+ wResult = w1 - w2;
+#ifndef NO_WIDE_TYPE
+ if ((type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_WIDE))
+#endif
+ {
/*
- * Should be able to use "!d", but apparently
- * some compilers can't handle it.
+ * Must check for overflow. The macro tests for overflows
+ * in sums by looking at the sign bits. As we have a
+ * subtraction here, we are adding -w2. As -w2 could in
+ * turn overflow, we test with ~w2 instead: it has the
+ * opposite sign bit to w2 so it does the job. Note that
+ * the only "bad" case (w2==0) is irrelevant for this
+ * macro, as in that case w1 and wResult have the same
+ * sign and there is no overflow anyway.
*/
- objResultPtr = Tcl_NewLongObj((d==0.0)? 1 : 0);
+
+ if (Overflowing(w1, ~w2, wResult)) {
+ goto overflow;
+ }
+ }
+ break;
+
+ case INST_DIV:
+ if (w2 == 0) {
+ TRACE(("%s %s => DIVIDE BY ZERO\n",
+ O2S(valuePtr), O2S(value2Ptr)));
+ goto divideByZero;
+ }
+
+ /*
+ * Need a bignum to represent (LLONG_MIN / -1)
+ */
+
+ if ((w1 == LLONG_MIN) && (w2 == -1)) {
+ goto overflow;
+ }
+ wResult = w1 / w2;
+
+ /*
+ * Force Tcl's integer division rules.
+ * TODO: examine for logic simplification
+ */
+
+ if (((wResult < 0) || ((wResult == 0) &&
+ ((w1 < 0 && w2 > 0) || (w1 > 0 && w2 < 0)))) &&
+ ((wResult * w2) != w1)) {
+ wResult -= 1;
}
- TRACE_WITH_OBJ(("%.6g => ", d), objResultPtr);
+ break;
+ default:
+ /*
+ * Unused, here to silence compiler warning.
+ */
+
+ wResult = 0;
}
- NEXT_INST_F(1, 1, 1);
- } else {
- /*
- * valuePtr is unshared. Modify it directly.
- */
- if ((tPtr == &tclIntType) || (tPtr == &tclBooleanType)) {
- i = valuePtr->internalRep.longValue;
- Tcl_SetLongObj(valuePtr,
- (*pc == INST_UMINUS)? -i : !i);
- TRACE_WITH_OBJ(("%ld => ", i), valuePtr);
- } else if (tPtr == &tclWideIntType) {
- TclGetWide(w,valuePtr);
- if (*pc == INST_UMINUS) {
- Tcl_SetWideIntObj(valuePtr, -w);
- } else {
- Tcl_SetLongObj(valuePtr, w == W0);
+
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ if (Tcl_IsShared(valuePtr)) {
+ objResultPtr = Tcl_NewWideIntObj(wResult);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+ Tcl_SetWideIntObj(valuePtr, wResult);
+ TRACE(("%s\n", O2S(valuePtr)));
+ NEXT_INST_F(1, 1, 0);
+ }
+
+ overflow:
+ {
+ mp_int big1, big2, bigResult, bigRemainder;
+
+ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr)));
+ Tcl_TakeBignumFromObj(NULL, valuePtr, &big1);
+ Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);
+ mp_init(&bigResult);
+ switch (*pc) {
+ case INST_ADD:
+ mp_add(&big1, &big2, &bigResult);
+ break;
+ case INST_SUB:
+ mp_sub(&big1, &big2, &bigResult);
+ break;
+ case INST_MULT:
+ mp_mul(&big1, &big2, &bigResult);
+ break;
+ case INST_DIV:
+ if (mp_iszero(&big2)) {
+ TRACE(("%s %s => DIVIDE BY ZERO\n", O2S(valuePtr),
+ O2S(value2Ptr)));
+ mp_clear(&big1);
+ mp_clear(&big2);
+ mp_clear(&bigResult);
+ goto divideByZero;
}
- TRACE_WITH_OBJ((LLD" => ", w), valuePtr);
- } else {
- d = valuePtr->internalRep.doubleValue;
- if (*pc == INST_UMINUS) {
- Tcl_SetDoubleObj(valuePtr, -d);
- } else {
+ mp_init(&bigRemainder);
+ mp_div(&big1, &big2, &bigResult, &bigRemainder);
+ /* TODO: internals intrusion */
+ if (!mp_iszero(&bigRemainder)
+ && (bigRemainder.sign != big2.sign)) {
/*
- * Should be able to use "!d", but apparently
- * some compilers can't handle it.
+ * Convert to Tcl's integer division rules.
*/
- Tcl_SetLongObj(valuePtr, (d==0.0)? 1 : 0);
+
+ mp_sub_d(&bigResult, 1, &bigResult);
+ mp_add(&bigRemainder, &big2, &bigRemainder);
}
- TRACE_WITH_OBJ(("%.6g => ", d), valuePtr);
+ mp_clear(&bigRemainder);
+ break;
+ case INST_EXPON:
+ if (big2.used > 1) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("exponent too large", -1));
+ mp_clear(&big1);
+ mp_clear(&big2);
+ mp_clear(&bigResult);
+ result = TCL_ERROR;
+ goto checkForCatch;
+ }
+ mp_expt_d(&big1, big2.dp[0], &bigResult);
+ break;
}
- NEXT_INST_F(1, 0, 0);
+ mp_clear(&big1);
+ mp_clear(&big2);
+ if (Tcl_IsShared(valuePtr)) {
+ objResultPtr = Tcl_NewBignumObj(&bigResult);
+ TRACE(("%s\n", O2S(objResultPtr)));
+ NEXT_INST_F(1, 2, 1);
+ }
+ Tcl_SetBignumObj(valuePtr, &bigResult);
+ TRACE(("%s\n", O2S(valuePtr)));
+ NEXT_INST_F(1, 1, 0);
}
}
- case INST_BITNOT:
- {
- /*
- * The operand must be an integer. If the operand object is
- * unshared modify it directly, otherwise modify a copy.
- * Free any old string representation since it is now
- * invalid.
- */
-
- Tcl_ObjType *tPtr;
-
- valuePtr = stackPtr[stackTop];
- tPtr = valuePtr->typePtr;
- if (!IS_INTEGER_TYPE(tPtr)) {
- REQUIRE_WIDE_OR_INT(result, valuePtr, i, w);
- if (result != TCL_OK) { /* try to convert to double */
- TRACE(("\"%.20s\" => ILLEGAL TYPE %s\n",
- O2S(valuePtr), (tPtr? tPtr->name : "null")));
- DECACHE_STACK_INFO();
- IllegalExprOperandType(interp, pc, valuePtr);
- CACHE_STACK_INFO();
- goto checkForCatch;
- }
+ case INST_LNOT: {
+ int b;
+ Tcl_Obj *valuePtr = OBJ_AT_TOS;
+
+ /* TODO - check claim that taking address of b harms performance */
+ /* TODO - consider optimization search for constants */
+ result = TclGetBooleanFromObj(NULL, valuePtr, &b);
+ if (result != TCL_OK) {
+ TRACE(("\"%.20s\" => ILLEGAL TYPE %s\n", O2S(valuePtr),
+ (valuePtr->typePtr? valuePtr->typePtr->name : "null")));
+ DECACHE_STACK_INFO();
+ IllegalExprOperandType(interp, pc, valuePtr);
+ CACHE_STACK_INFO();
+ goto checkForCatch;
}
-
- if (valuePtr->typePtr == &tclWideIntType) {
- TclGetWide(w,valuePtr);
+ /* TODO: Consider peephole opt. */
+ objResultPtr = constants[!b];
+ NEXT_INST_F(1, 1, 1);
+ }
+
+ case INST_BITNOT: {
+ mp_int big;
+ ClientData ptr;
+ int type;
+ Tcl_Obj *valuePtr = OBJ_AT_TOS;
+
+ result = GetNumberFromObj(NULL, valuePtr, &ptr, &type);
+ if ((result != TCL_OK)
+ || (type == TCL_NUMBER_NAN) || (type == TCL_NUMBER_DOUBLE)) {
+ /*
+ * ... ~$NonInteger => raise an error.
+ */
+
+ result = TCL_ERROR;
+ TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr),
+ (valuePtr->typePtr? valuePtr->typePtr->name : "null")));
+ DECACHE_STACK_INFO();
+ IllegalExprOperandType(interp, pc, valuePtr);
+ CACHE_STACK_INFO();
+ goto checkForCatch;
+ }
+ if (type == TCL_NUMBER_LONG) {
+ long l = *((const long *)ptr);
+
if (Tcl_IsShared(valuePtr)) {
- objResultPtr = Tcl_NewWideIntObj(~w);
- TRACE(("0x%" TCL_LL_MODIFIER "x => (%" TCL_LL_MODIFIER "u)\n",
- w, ~w));
+ TclNewLongObj(objResultPtr, ~l);
NEXT_INST_F(1, 1, 1);
- } else {
- /*
- * valuePtr is unshared. Modify it directly.
- */
- Tcl_SetWideIntObj(valuePtr, ~w);
- TRACE(("0x%" TCL_LL_MODIFIER "x => (%" TCL_LL_MODIFIER "u)\n",
- w, ~w));
- NEXT_INST_F(1, 0, 0);
}
- } else {
- i = valuePtr->internalRep.longValue;
+ TclSetLongObj(valuePtr, ~l);
+ NEXT_INST_F(1, 0, 0);
+ }
+#ifndef NO_WIDE_TYPE
+ if (type == TCL_NUMBER_WIDE) {
+ Tcl_WideInt w = *((const Tcl_WideInt *)ptr);
+
if (Tcl_IsShared(valuePtr)) {
- objResultPtr = Tcl_NewLongObj(~i);
- TRACE(("0x%lx => (%lu)\n", i, ~i));
+ objResultPtr = Tcl_NewWideIntObj(~w);
NEXT_INST_F(1, 1, 1);
- } else {
- /*
- * valuePtr is unshared. Modify it directly.
- */
- Tcl_SetLongObj(valuePtr, ~i);
- TRACE(("0x%lx => (%lu)\n", i, ~i));
- NEXT_INST_F(1, 0, 0);
}
+ Tcl_SetWideIntObj(valuePtr, ~w);
+ NEXT_INST_F(1, 0, 0);
}
+#endif
+ Tcl_TakeBignumFromObj(NULL, valuePtr, &big);
+ /* ~a = - a - 1 */
+ mp_neg(&big, &big);
+ mp_sub_d(&big, 1, &big);
+ if (Tcl_IsShared(valuePtr)) {
+ objResultPtr = Tcl_NewBignumObj(&big);
+ NEXT_INST_F(1, 1, 1);
+ }
+ Tcl_SetBignumObj(valuePtr, &big);
+ NEXT_INST_F(1, 0, 0);
}
- case INST_CALL_BUILTIN_FUNC1:
- opnd = TclGetUInt1AtPtr(pc+1);
- {
- /*
- * Call one of the built-in Tcl math functions.
- */
+ case INST_UMINUS: {
+ ClientData ptr;
+ int type;
+ Tcl_Obj *valuePtr = OBJ_AT_TOS;
- BuiltinFunc *mathFuncPtr;
-
- if ((opnd < 0) || (opnd > LAST_BUILTIN_FUNC)) {
- TRACE(("UNRECOGNIZED BUILTIN FUNC CODE %d\n", opnd));
- panic("TclExecuteByteCode: unrecognized builtin function code %d", opnd);
- }
- mathFuncPtr = &(tclBuiltinFuncTable[opnd]);
+ result = GetNumberFromObj(NULL, valuePtr, &ptr, &type);
+ if ((result != TCL_OK)
+#ifndef ACCEPT_NAN
+ || (type == TCL_NUMBER_NAN)
+#endif
+ ) {
+ result = TCL_ERROR;
+ TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr),
+ (valuePtr->typePtr? valuePtr->typePtr->name : "null")));
DECACHE_STACK_INFO();
- result = (*mathFuncPtr->proc)(interp, eePtr,
- mathFuncPtr->clientData);
+ IllegalExprOperandType(interp, pc, valuePtr);
CACHE_STACK_INFO();
- if (result != TCL_OK) {
- goto checkForCatch;
+ goto checkForCatch;
+ }
+ switch (type) {
+ case TCL_NUMBER_DOUBLE: {
+ double d;
+
+ if (Tcl_IsShared(valuePtr)) {
+ TclNewDoubleObj(objResultPtr, -(*((const double *)ptr)));
+ NEXT_INST_F(1, 1, 1);
}
- TRACE_WITH_OBJ(("%d => ", opnd), stackPtr[stackTop]);
+ d = *((const double *)ptr);
+ TclSetDoubleObj(valuePtr, -d);
+ NEXT_INST_F(1, 0, 0);
}
- NEXT_INST_F(2, 0, 0);
-
- case INST_CALL_FUNC1:
- opnd = TclGetUInt1AtPtr(pc+1);
- {
- /*
- * Call a non-builtin Tcl math function previously
- * registered by a call to Tcl_CreateMathFunc.
- */
-
- int objc = opnd; /* Number of arguments. The function name
- * is the 0-th argument. */
- Tcl_Obj **objv; /* The array of arguments. The function
- * name is objv[0]. */
+ case TCL_NUMBER_LONG: {
+ long l = *((const long *)ptr);
- objv = &(stackPtr[stackTop - (objc-1)]); /* "objv[0]" */
- DECACHE_STACK_INFO();
- result = ExprCallMathFunc(interp, eePtr, objc, objv);
- CACHE_STACK_INFO();
- if (result != TCL_OK) {
- goto checkForCatch;
+ if (l != LONG_MIN) {
+ if (Tcl_IsShared(valuePtr)) {
+ TclNewLongObj(objResultPtr, -l);
+ NEXT_INST_F(1, 1, 1);
+ }
+ TclSetLongObj(valuePtr, -l);
+ NEXT_INST_F(1, 0, 0);
}
- TRACE_WITH_OBJ(("%d => ", objc), stackPtr[stackTop]);
+ /* FALLTHROUGH */
}
- NEXT_INST_F(2, 0, 0);
+#ifndef NO_WIDE_TYPE
+ case TCL_NUMBER_WIDE: {
+ Tcl_WideInt w;
- case INST_TRY_CVT_TO_NUMERIC:
- {
- /*
- * Try to convert the topmost stack object to an int or
- * double object. This is done in order to support Tcl's
- * policy of interpreting operands if at all possible as
- * first integers, else floating-point numbers.
- */
-
- double d;
- char *s;
- Tcl_ObjType *tPtr;
- int converted, needNew;
-
- valuePtr = stackPtr[stackTop];
- tPtr = valuePtr->typePtr;
- converted = 0;
- if (!IS_INTEGER_TYPE(tPtr) && ((tPtr != &tclDoubleType)
- || (valuePtr->bytes != NULL))) {
- if ((tPtr == &tclBooleanType) && (valuePtr->bytes == NULL)) {
- valuePtr->typePtr = &tclIntType;
- converted = 1;
+ if (type == TCL_NUMBER_LONG) {
+ w = (Tcl_WideInt)(*((const long *)ptr));
} else {
- s = Tcl_GetStringFromObj(valuePtr, &length);
- if (TclLooksLikeInt(s, length)) {
- GET_WIDE_OR_INT(result, valuePtr, i, w);
- } else {
- result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
- valuePtr, &d);
- }
- if (result == TCL_OK) {
- converted = 1;
+ w = *((const Tcl_WideInt *)ptr);
+ }
+ if (w != LLONG_MIN) {
+ if (Tcl_IsShared(valuePtr)) {
+ objResultPtr = Tcl_NewWideIntObj(-w);
+ NEXT_INST_F(1, 1, 1);
}
- result = TCL_OK; /* reset the result variable */
+ Tcl_SetWideIntObj(valuePtr, -w);
+ NEXT_INST_F(1, 0, 0);
}
- tPtr = valuePtr->typePtr;
+ /* FALLTHROUGH */
}
+#endif
+ case TCL_NUMBER_BIG: {
+ mp_int big;
+ switch (type) {
+#ifdef NO_WIDE_TYPE
+ case TCL_NUMBER_LONG:
+ TclBNInitBignumFromLong(&big, *(const long *) ptr);
+ break;
+#else
+ case TCL_NUMBER_WIDE:
+ TclBNInitBignumFromWideInt(&big, *(const Tcl_WideInt *) ptr);
+ break;
+#endif
+ case TCL_NUMBER_BIG:
+ Tcl_TakeBignumFromObj(NULL, valuePtr, &big);
+ }
+ mp_neg(&big, &big);
+ if (Tcl_IsShared(valuePtr)) {
+ objResultPtr = Tcl_NewBignumObj(&big);
+ NEXT_INST_F(1, 1, 1);
+ }
+ Tcl_SetBignumObj(valuePtr, &big);
+ NEXT_INST_F(1, 0, 0);
+ }
+ case TCL_NUMBER_NAN:
+ /* -NaN => NaN */
+ NEXT_INST_F(1, 0, 0);
+ }
+ }
+
+ case INST_UPLUS:
+ case INST_TRY_CVT_TO_NUMERIC: {
/*
- * Ensure that the topmost stack object, if numeric, has a
- * string rep the same as the formatted version of its
- * internal rep. This is used, e.g., to make sure that "expr
- * {0001}" yields "1", not "0001". We implement this by
- * _discarding_ the string rep since we know it will be
- * regenerated, if needed later, by formatting the internal
- * rep's value. Also check if there has been an IEEE
- * floating point error.
+ * Try to convert the topmost stack object to numeric object. This is
+ * done in order to support [expr]'s policy of interpreting operands
+ * if at all possible as numbers first, then strings.
*/
-
- objResultPtr = valuePtr;
- needNew = 0;
- if (IS_NUMERIC_TYPE(tPtr)) {
- if (Tcl_IsShared(valuePtr)) {
- if (valuePtr->bytes != NULL) {
- /*
- * We only need to make a copy of the object
- * when it already had a string rep
- */
- needNew = 1;
- if (tPtr == &tclIntType) {
- i = valuePtr->internalRep.longValue;
- objResultPtr = Tcl_NewLongObj(i);
- } else if (tPtr == &tclWideIntType) {
- TclGetWide(w,valuePtr);
- objResultPtr = Tcl_NewWideIntObj(w);
- } else {
- d = valuePtr->internalRep.doubleValue;
- objResultPtr = Tcl_NewDoubleObj(d);
- }
- tPtr = objResultPtr->typePtr;
- }
+
+ ClientData ptr;
+ int type;
+ Tcl_Obj *valuePtr = OBJ_AT_TOS;
+
+ if (GetNumberFromObj(NULL, valuePtr, &ptr, &type) != TCL_OK) {
+ if (*pc == INST_UPLUS) {
+ /*
+ * ... +$NonNumeric => raise an error.
+ */
+
+ result = TCL_ERROR;
+ TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr),
+ (valuePtr->typePtr? valuePtr->typePtr->name:"null")));
+ DECACHE_STACK_INFO();
+ IllegalExprOperandType(interp, pc, valuePtr);
+ CACHE_STACK_INFO();
+ goto checkForCatch;
} else {
- Tcl_InvalidateStringRep(valuePtr);
+ /* ... TryConvertToNumeric($NonNumeric) is acceptable */
+ TRACE(("\"%.20s\" => not numeric\n", O2S(valuePtr)));
+ NEXT_INST_F(1, 0, 0);
}
-
- if (tPtr == &tclDoubleType) {
- d = objResultPtr->internalRep.doubleValue;
- if (IS_NAN(d) || IS_INF(d)) {
- TRACE(("\"%.20s\" => IEEE FLOATING PT ERROR\n",
- O2S(objResultPtr)));
- DECACHE_STACK_INFO();
- TclExprFloatError(interp, d);
- CACHE_STACK_INFO();
- result = TCL_ERROR;
- goto checkForCatch;
- }
+ }
+#ifndef ACCEPT_NAN
+ if (type == TCL_NUMBER_NAN) {
+ result = TCL_ERROR;
+ if (*pc == INST_UPLUS) {
+ /*
+ * ... +$NonNumeric => raise an error.
+ */
+
+ TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr),
+ (valuePtr->typePtr? valuePtr->typePtr->name:"null")));
+ DECACHE_STACK_INFO();
+ IllegalExprOperandType(interp, pc, valuePtr);
+ CACHE_STACK_INFO();
+ } else {
+ /*
+ * Numeric conversion of NaN -> error.
+ */
+
+ TRACE(("\"%.20s\" => IEEE FLOATING PT ERROR\n",
+ O2S(objResultPtr)));
+ DECACHE_STACK_INFO();
+ TclExprFloatError(interp, *((const double *)ptr));
+ CACHE_STACK_INFO();
}
- converted = converted; /* lint, converted not used. */
- TRACE(("\"%.20s\" => numeric, %s, %s\n", O2S(valuePtr),
- (converted? "converted" : "not converted"),
- (needNew? "new Tcl_Obj" : "same Tcl_Obj")));
- } else {
- TRACE(("\"%.20s\" => not numeric\n", O2S(valuePtr)));
+ goto checkForCatch;
}
- if (needNew) {
- NEXT_INST_F(1, 1, 1);
- } else {
+#endif
+
+ /*
+ * Ensure that the numeric value has a string rep the same as the
+ * formatted version of its internal rep. This is used, e.g., to make
+ * sure that "expr {0001}" yields "1", not "0001". We implement this
+ * by _discarding_ the string rep since we know it will be
+ * regenerated, if needed later, by formatting the internal rep's
+ * value.
+ */
+
+ if (valuePtr->bytes == NULL) {
+ TRACE(("\"%.20s\" => numeric, same Tcl_Obj\n", O2S(valuePtr)));
NEXT_INST_F(1, 0, 0);
}
+ if (Tcl_IsShared(valuePtr)) {
+ /*
+ * Here we do some surgery within the Tcl_Obj internals. We want
+ * to copy the intrep, but not the string, so we temporarily hide
+ * the string so we do not copy it.
+ */
+
+ char *savedString = valuePtr->bytes;
+
+ valuePtr->bytes = NULL;
+ objResultPtr = Tcl_DuplicateObj(valuePtr);
+ valuePtr->bytes = savedString;
+ TRACE(("\"%.20s\" => numeric, new Tcl_Obj\n", O2S(valuePtr)));
+ NEXT_INST_F(1, 1, 1);
+ }
+ TclInvalidateStringRep(valuePtr);
+ TRACE(("\"%.20s\" => numeric, same Tcl_Obj\n", O2S(valuePtr)));
+ NEXT_INST_F(1, 0, 0);
}
-
+
case INST_BREAK:
+ /*
DECACHE_STACK_INFO();
Tcl_ResetResult(interp);
CACHE_STACK_INFO();
+ */
result = TCL_BREAK;
cleanup = 0;
goto processExceptionReturn;
case INST_CONTINUE:
+ /*
DECACHE_STACK_INFO();
Tcl_ResetResult(interp);
CACHE_STACK_INFO();
+ */
result = TCL_CONTINUE;
cleanup = 0;
goto processExceptionReturn;
- case INST_FOREACH_START4:
- opnd = TclGetUInt4AtPtr(pc+1);
- {
- /*
- * Initialize the temporary local var that holds the count
- * of the number of iterations of the loop body to -1.
- */
+ case INST_FOREACH_START4: {
+ /*
+ * Initialize the temporary local var that holds the count of the
+ * number of iterations of the loop body to -1.
+ */
- ForeachInfo *infoPtr = (ForeachInfo *)
- codePtr->auxDataArrayPtr[opnd].clientData;
- int iterTmpIndex = infoPtr->loopCtTemp;
- Var *compiledLocals = iPtr->varFramePtr->compiledLocals;
- Var *iterVarPtr = &(compiledLocals[iterTmpIndex]);
- Tcl_Obj *oldValuePtr = iterVarPtr->value.objPtr;
+ int opnd, iterTmpIndex;
+ ForeachInfo *infoPtr;
+ Var *iterVarPtr;
+ Tcl_Obj *oldValuePtr;
- if (oldValuePtr == NULL) {
- iterVarPtr->value.objPtr = Tcl_NewLongObj(-1);
- Tcl_IncrRefCount(iterVarPtr->value.objPtr);
- } else {
- Tcl_SetLongObj(oldValuePtr, -1);
- }
- TclSetVarScalar(iterVarPtr);
- TclClearVarUndefined(iterVarPtr);
- TRACE(("%u => loop iter count temp %d\n",
- opnd, iterTmpIndex));
+ opnd = TclGetUInt4AtPtr(pc+1);
+ infoPtr = (ForeachInfo *) codePtr->auxDataArrayPtr[opnd].clientData;
+ iterTmpIndex = infoPtr->loopCtTemp;
+ iterVarPtr = &(compiledLocals[iterTmpIndex]);
+ oldValuePtr = iterVarPtr->value.objPtr;
+
+ if (oldValuePtr == NULL) {
+ TclNewLongObj(iterVarPtr->value.objPtr, -1);
+ Tcl_IncrRefCount(iterVarPtr->value.objPtr);
+ } else {
+ TclSetLongObj(oldValuePtr, -1);
}
-
+ TRACE(("%u => loop iter count temp %d\n", opnd, iterTmpIndex));
+
#ifndef TCL_COMPILE_DEBUG
- /*
- * Remark that the compiler ALWAYS sets INST_FOREACH_STEP4
- * immediately after INST_FOREACH_START4 - let us just fall
- * through instead of jumping back to the top.
+ /*
+ * Remark that the compiler ALWAYS sets INST_FOREACH_STEP4 immediately
+ * after INST_FOREACH_START4 - let us just fall through instead of
+ * jumping back to the top.
*/
pc += 5;
TCL_DTRACE_INST_NEXT();
#else
NEXT_INST_F(5, 0, 0);
-#endif
- case INST_FOREACH_STEP4:
+#endif
+ }
+
+ case INST_FOREACH_STEP4: {
+ /*
+ * "Step" a foreach loop (i.e., begin its next iteration) by assigning
+ * the next value list element to each loop var.
+ */
+
+ ForeachInfo *infoPtr;
+ ForeachVarList *varListPtr;
+ Tcl_Obj *listPtr,*valuePtr, *value2Ptr, **elements;
+ Var *iterVarPtr, *listVarPtr, *varPtr;
+ int opnd, numLists, iterNum, listTmpIndex, listLen, numVars;
+ int varIndex, valIndex, continueLoop, j;
+ long i;
+
opnd = TclGetUInt4AtPtr(pc+1);
- {
- /*
- * "Step" a foreach loop (i.e., begin its next iteration) by
- * assigning the next value list element to each loop var.
- */
+ infoPtr = (ForeachInfo *) codePtr->auxDataArrayPtr[opnd].clientData;
+ numLists = infoPtr->numLists;
- ForeachInfo *infoPtr = (ForeachInfo *)
- codePtr->auxDataArrayPtr[opnd].clientData;
- ForeachVarList *varListPtr;
- int numLists = infoPtr->numLists;
- Var *compiledLocals = iPtr->varFramePtr->compiledLocals;
- Tcl_Obj *listPtr;
- Var *iterVarPtr, *listVarPtr;
- int iterNum, listTmpIndex, listLen, numVars;
- int varIndex, valIndex, continueLoop, j;
+ /*
+ * Increment the temp holding the loop iteration number.
+ */
- /*
- * Increment the temp holding the loop iteration number.
- */
+ iterVarPtr = &(compiledLocals[infoPtr->loopCtTemp]);
+ valuePtr = iterVarPtr->value.objPtr;
+ iterNum = (valuePtr->internalRep.longValue + 1);
+ TclSetLongObj(valuePtr, iterNum);
- iterVarPtr = &(compiledLocals[infoPtr->loopCtTemp]);
- valuePtr = iterVarPtr->value.objPtr;
- iterNum = (valuePtr->internalRep.longValue + 1);
- Tcl_SetLongObj(valuePtr, iterNum);
-
- /*
- * Check whether all value lists are exhausted and we should
- * stop the loop.
- */
+ /*
+ * Check whether all value lists are exhausted and we should stop the
+ * loop.
+ */
- continueLoop = 0;
- listTmpIndex = infoPtr->firstValueTemp;
- for (i = 0; i < numLists; i++) {
- varListPtr = infoPtr->varLists[i];
- numVars = varListPtr->numVars;
-
- listVarPtr = &(compiledLocals[listTmpIndex]);
- listPtr = listVarPtr->value.objPtr;
- result = Tcl_ListObjLength(interp, listPtr, &listLen);
- if (result != TCL_OK) {
- TRACE_WITH_OBJ(("%u => ERROR converting list %ld, \"%s\": ",
- opnd, i, O2S(listPtr)), Tcl_GetObjResult(interp));
- goto checkForCatch;
- }
+ continueLoop = 0;
+ listTmpIndex = infoPtr->firstValueTemp;
+ for (i = 0; i < numLists; i++) {
+ varListPtr = infoPtr->varLists[i];
+ numVars = varListPtr->numVars;
+
+ listVarPtr = &(compiledLocals[listTmpIndex]);
+ listPtr = listVarPtr->value.objPtr;
+ result = TclListObjLength(interp, listPtr, &listLen);
+ if (result == TCL_OK) {
if (listLen > (iterNum * numVars)) {
continueLoop = 1;
}
listTmpIndex++;
+ } else {
+ TRACE_WITH_OBJ(("%u => ERROR converting list %ld, \"%s\": ",
+ opnd, i, O2S(listPtr)), Tcl_GetObjResult(interp));
+ goto checkForCatch;
}
+ }
- /*
- * If some var in some var list still has a remaining list
- * element iterate one more time. Assign to var the next
- * element from its value list. We already checked above
- * that each list temp holds a valid list object.
- */
-
- if (continueLoop) {
- listTmpIndex = infoPtr->firstValueTemp;
- for (i = 0; i < numLists; i++) {
- varListPtr = infoPtr->varLists[i];
- numVars = varListPtr->numVars;
+ /*
+ * If some var in some var list still has a remaining list element
+ * iterate one more time. Assign to var the next element from its
+ * value list. We already checked above that each list temp holds a
+ * valid list object (by calling Tcl_ListObjLength), but cannot rely
+ * on that check remaining valid: one list could have been shimmered
+ * as a side effect of setting a traced variable.
+ */
- listVarPtr = &(compiledLocals[listTmpIndex]);
- listPtr = listVarPtr->value.objPtr;
+ if (continueLoop) {
+ listTmpIndex = infoPtr->firstValueTemp;
+ for (i = 0; i < numLists; i++) {
+ varListPtr = infoPtr->varLists[i];
+ numVars = varListPtr->numVars;
- valIndex = (iterNum * numVars);
- for (j = 0; j < numVars; j++) {
- Tcl_Obj **elements;
+ listVarPtr = &(compiledLocals[listTmpIndex]);
+ listPtr = TclListObjCopy(NULL, listVarPtr->value.objPtr);
+ TclListObjGetElements(interp, listPtr, &listLen, &elements);
- /*
- * The call to TclPtrSetVar might shimmer listPtr,
- * so re-fetch pointers every iteration for safety.
- * See test foreach-10.1.
- */
+ valIndex = (iterNum * numVars);
+ for (j = 0; j < numVars; j++) {
+ if (valIndex >= listLen) {
+ TclNewObj(valuePtr);
+ } else {
+ valuePtr = elements[valIndex];
+ }
- Tcl_ListObjGetElements(NULL, listPtr,
- &listLen, &elements);
- if (valIndex >= listLen) {
- TclNewObj(valuePtr);
- } else {
- valuePtr = elements[valIndex];
- }
-
- varIndex = varListPtr->varIndexes[j];
- varPtr = &(varFramePtr->compiledLocals[varIndex]);
- part1 = varPtr->name;
- while (TclIsVarLink(varPtr)) {
- varPtr = varPtr->value.linkPtr;
- }
- if (!((varPtr->flags & VAR_IN_HASHTABLE) && (varPtr->hPtr == NULL))
- && (varPtr->tracePtr == NULL)
- && (TclIsVarScalar(varPtr) || TclIsVarUndefined(varPtr))) {
- value2Ptr = varPtr->value.objPtr;
- if (valuePtr != value2Ptr) {
- if (value2Ptr != NULL) {
- TclDecrRefCount(value2Ptr);
- } else {
- TclSetVarScalar(varPtr);
- TclClearVarUndefined(varPtr);
- }
- varPtr->value.objPtr = valuePtr;
- Tcl_IncrRefCount(valuePtr);
+ varIndex = varListPtr->varIndexes[j];
+ varPtr = &(compiledLocals[varIndex]);
+ while (TclIsVarLink(varPtr)) {
+ varPtr = varPtr->value.linkPtr;
+ }
+ if (TclIsVarDirectWritable(varPtr)) {
+ value2Ptr = varPtr->value.objPtr;
+ if (valuePtr != value2Ptr) {
+ if (value2Ptr != NULL) {
+ TclDecrRefCount(value2Ptr);
}
- } else {
- DECACHE_STACK_INFO();
+ varPtr->value.objPtr = valuePtr;
Tcl_IncrRefCount(valuePtr);
- value2Ptr = TclPtrSetVar(interp, varPtr, NULL, part1,
- NULL, valuePtr, TCL_LEAVE_ERR_MSG);
- TclDecrRefCount(valuePtr);
- CACHE_STACK_INFO();
- if (value2Ptr == NULL) {
- TRACE_WITH_OBJ(("%u => ERROR init. index temp %d: ",
- opnd, varIndex),
- Tcl_GetObjResult(interp));
- result = TCL_ERROR;
- goto checkForCatch;
- }
}
- valIndex++;
+ } else {
+ DECACHE_STACK_INFO();
+ value2Ptr = TclPtrSetVar(interp, varPtr, NULL, NULL,
+ NULL, valuePtr, TCL_LEAVE_ERR_MSG, varIndex);
+ CACHE_STACK_INFO();
+ if (value2Ptr == NULL) {
+ TRACE_WITH_OBJ((
+ "%u => ERROR init. index temp %d: ",
+ opnd,varIndex), Tcl_GetObjResult(interp));
+ result = TCL_ERROR;
+ TclDecrRefCount(listPtr);
+ goto checkForCatch;
+ }
}
- listTmpIndex++;
+ valIndex++;
}
+ TclDecrRefCount(listPtr);
+ listTmpIndex++;
}
- TRACE(("%u => %d lists, iter %d, %s loop\n", opnd, numLists,
- iterNum, (continueLoop? "continue" : "exit")));
+ }
+ TRACE(("%u => %d lists, iter %d, %s loop\n", opnd, numLists,
+ iterNum, (continueLoop? "continue" : "exit")));
- /*
- * Run-time peep-hole optimisation: the compiler ALWAYS follows
- * INST_FOREACH_STEP4 with an INST_JUMP_FALSE. We just skip that
- * instruction and jump direct from here.
- */
+ /*
+ * Run-time peep-hole optimisation: the compiler ALWAYS follows
+ * INST_FOREACH_STEP4 with an INST_JUMP_FALSE. We just skip that
+ * instruction and jump direct from here.
+ */
- pc += 5;
- if (*pc == INST_JUMP_FALSE1) {
- NEXT_INST_F((continueLoop? 2 : TclGetInt1AtPtr(pc+1)), 0, 0);
- } else {
- NEXT_INST_F((continueLoop? 5 : TclGetInt4AtPtr(pc+1)), 0, 0);
- }
+ pc += 5;
+ if (*pc == INST_JUMP_FALSE1) {
+ NEXT_INST_F((continueLoop? 2 : TclGetInt1AtPtr(pc+1)), 0, 0);
+ } else {
+ NEXT_INST_F((continueLoop? 5 : TclGetInt4AtPtr(pc+1)), 0, 0);
}
+ }
case INST_BEGIN_CATCH4:
/*
- * Record start of the catch command with exception range index
- * equal to the operand. Push the current stack depth onto the
- * special catch stack.
+ * Record start of the catch command with exception range index equal
+ * to the operand. Push the current stack depth onto the special catch
+ * stack.
*/
- catchStackPtr[++catchTop] = stackTop;
+
+ *(++catchTop) = CURR_DEPTH;
TRACE(("%u => catchTop=%d, stackTop=%d\n",
- TclGetUInt4AtPtr(pc+1), catchTop, stackTop));
+ TclGetUInt4AtPtr(pc+1), (int) (catchTop - initCatchTop - 1),
+ (int) CURR_DEPTH));
NEXT_INST_F(5, 0, 0);
case INST_END_CATCH:
catchTop--;
+ DECACHE_STACK_INFO();
+ Tcl_ResetResult(interp);
+ CACHE_STACK_INFO();
result = TCL_OK;
- TRACE(("=> catchTop=%d\n", catchTop));
+ TRACE(("=> catchTop=%d\n", (int) (catchTop - initCatchTop - 1)));
NEXT_INST_F(1, 0, 0);
-
+
case INST_PUSH_RESULT:
objResultPtr = Tcl_GetObjResult(interp);
- TRACE_WITH_OBJ(("=> "), Tcl_GetObjResult(interp));
+ TRACE_WITH_OBJ(("=> "), objResultPtr);
/*
* See the comments at INST_INVOKE_STK
*/
{
Tcl_Obj *newObjResultPtr;
+
TclNewObj(newObjResultPtr);
Tcl_IncrRefCount(newObjResultPtr);
iPtr->objResultPtr = newObjResultPtr;
@@ -4330,205 +6762,784 @@ TclExecuteByteCode(interp, codePtr)
NEXT_INST_F(1, 0, -1);
case INST_PUSH_RETURN_CODE:
- objResultPtr = Tcl_NewLongObj(result);
+ TclNewIntObj(objResultPtr, result);
TRACE(("=> %u\n", result));
NEXT_INST_F(1, 0, 1);
+ case INST_PUSH_RETURN_OPTIONS:
+ objResultPtr = Tcl_GetReturnOptions(interp, result);
+ TRACE_WITH_OBJ(("=> "), objResultPtr);
+ NEXT_INST_F(1, 0, 1);
+
+/* TODO: normalize "valPtr" to "valuePtr" */
+ {
+ int opnd, opnd2, allocateDict;
+ Tcl_Obj *dictPtr, *valPtr;
+ Var *varPtr;
+
+ case INST_DICT_GET:
+ opnd = TclGetUInt4AtPtr(pc+1);
+ TRACE(("%u => ", opnd));
+ dictPtr = OBJ_AT_DEPTH(opnd);
+ if (opnd > 1) {
+ dictPtr = TclTraceDictPath(interp, dictPtr, opnd-1,
+ &OBJ_AT_DEPTH(opnd-1), DICT_PATH_READ);
+ if (dictPtr == NULL) {
+ TRACE_WITH_OBJ((
+ "%u => ERROR tracing dictionary path into \"%s\": ",
+ opnd, O2S(OBJ_AT_DEPTH(opnd))),
+ Tcl_GetObjResult(interp));
+ result = TCL_ERROR;
+ goto checkForCatch;
+ }
+ }
+ result = Tcl_DictObjGet(interp, dictPtr, OBJ_AT_TOS, &objResultPtr);
+ if ((result == TCL_OK) && objResultPtr) {
+ TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
+ NEXT_INST_V(5, opnd+1, 1);
+ }
+ if (result != TCL_OK) {
+ TRACE_WITH_OBJ((
+ "%u => ERROR reading leaf dictionary key \"%s\": ",
+ opnd, O2S(dictPtr)), Tcl_GetObjResult(interp));
+ } else {
+ DECACHE_STACK_INFO();
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "key \"", TclGetString(OBJ_AT_TOS),
+ "\" not known in dictionary", NULL);
+ CACHE_STACK_INFO();
+ TRACE_WITH_OBJ(("%u => ERROR ", opnd), Tcl_GetObjResult(interp));
+ result = TCL_ERROR;
+ }
+ goto checkForCatch;
+
+ case INST_DICT_SET:
+ case INST_DICT_UNSET:
+ case INST_DICT_INCR_IMM:
+ opnd = TclGetUInt4AtPtr(pc+1);
+ opnd2 = TclGetUInt4AtPtr(pc+5);
+
+ varPtr = &(compiledLocals[opnd2]);
+ while (TclIsVarLink(varPtr)) {
+ varPtr = varPtr->value.linkPtr;
+ }
+ TRACE(("%u %u => ", opnd, opnd2));
+ if (TclIsVarDirectReadable(varPtr)) {
+ dictPtr = varPtr->value.objPtr;
+ } else {
+ DECACHE_STACK_INFO();
+ dictPtr = TclPtrGetVar(interp, varPtr, NULL,NULL,NULL, 0, opnd2);
+ CACHE_STACK_INFO();
+ }
+ if (dictPtr == NULL) {
+ TclNewObj(dictPtr);
+ allocateDict = 1;
+ } else {
+ allocateDict = Tcl_IsShared(dictPtr);
+ if (allocateDict) {
+ dictPtr = Tcl_DuplicateObj(dictPtr);
+ }
+ }
+
+ switch (*pc) {
+ case INST_DICT_SET:
+ cleanup = opnd + 1;
+ result = Tcl_DictObjPutKeyList(interp, dictPtr, opnd,
+ &OBJ_AT_DEPTH(opnd), OBJ_AT_TOS);
+ break;
+ case INST_DICT_INCR_IMM:
+ cleanup = 1;
+ opnd = TclGetInt4AtPtr(pc+1);
+ result = Tcl_DictObjGet(interp, dictPtr, OBJ_AT_TOS, &valPtr);
+ if (result != TCL_OK) {
+ break;
+ }
+ if (valPtr == NULL) {
+ Tcl_DictObjPut(NULL, dictPtr, OBJ_AT_TOS,Tcl_NewIntObj(opnd));
+ } else {
+ Tcl_Obj *incrPtr = Tcl_NewIntObj(opnd);
+
+ Tcl_IncrRefCount(incrPtr);
+ if (Tcl_IsShared(valPtr)) {
+ valPtr = Tcl_DuplicateObj(valPtr);
+ Tcl_DictObjPut(NULL, dictPtr, OBJ_AT_TOS, valPtr);
+ }
+ result = TclIncrObj(interp, valPtr, incrPtr);
+ if (result == TCL_OK) {
+ Tcl_InvalidateStringRep(dictPtr);
+ }
+ TclDecrRefCount(incrPtr);
+ }
+ break;
+ case INST_DICT_UNSET:
+ cleanup = opnd;
+ result = Tcl_DictObjRemoveKeyList(interp, dictPtr, opnd,
+ &OBJ_AT_DEPTH(opnd-1));
+ break;
+ default:
+ cleanup = 0; /* stop compiler warning */
+ Tcl_Panic("Should not happen!");
+ }
+
+ if (result != TCL_OK) {
+ if (allocateDict) {
+ TclDecrRefCount(dictPtr);
+ }
+ TRACE_WITH_OBJ(("%u %u => ERROR updating dictionary: ",
+ opnd, opnd2), Tcl_GetObjResult(interp));
+ goto checkForCatch;
+ }
+
+ if (TclIsVarDirectWritable(varPtr)) {
+ if (allocateDict) {
+ Tcl_Obj *oldValuePtr = varPtr->value.objPtr;
+
+ Tcl_IncrRefCount(dictPtr);
+ if (oldValuePtr != NULL) {
+ TclDecrRefCount(oldValuePtr);
+ }
+ varPtr->value.objPtr = dictPtr;
+ }
+ objResultPtr = dictPtr;
+ } else {
+ Tcl_IncrRefCount(dictPtr);
+ DECACHE_STACK_INFO();
+ objResultPtr = TclPtrSetVar(interp, varPtr, NULL, NULL, NULL,
+ dictPtr, TCL_LEAVE_ERR_MSG, opnd2);
+ CACHE_STACK_INFO();
+ TclDecrRefCount(dictPtr);
+ if (objResultPtr == NULL) {
+ TRACE_APPEND(("ERROR: %.30s\n",
+ O2S(Tcl_GetObjResult(interp))));
+ result = TCL_ERROR;
+ goto checkForCatch;
+ }
+ }
+#ifndef TCL_COMPILE_DEBUG
+ if (*(pc+9) == INST_POP) {
+ NEXT_INST_V(10, cleanup, 0);
+ }
+#endif
+ TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
+ NEXT_INST_V(9, cleanup, 1);
+
+ case INST_DICT_APPEND:
+ case INST_DICT_LAPPEND:
+ opnd = TclGetUInt4AtPtr(pc+1);
+
+ varPtr = &(compiledLocals[opnd]);
+ while (TclIsVarLink(varPtr)) {
+ varPtr = varPtr->value.linkPtr;
+ }
+ TRACE(("%u => ", opnd));
+ if (TclIsVarDirectReadable(varPtr)) {
+ dictPtr = varPtr->value.objPtr;
+ } else {
+ DECACHE_STACK_INFO();
+ dictPtr = TclPtrGetVar(interp, varPtr, NULL, NULL, NULL, 0, opnd);
+ CACHE_STACK_INFO();
+ }
+ if (dictPtr == NULL) {
+ TclNewObj(dictPtr);
+ allocateDict = 1;
+ } else {
+ allocateDict = Tcl_IsShared(dictPtr);
+ if (allocateDict) {
+ dictPtr = Tcl_DuplicateObj(dictPtr);
+ }
+ }
+
+ result = Tcl_DictObjGet(interp, dictPtr, OBJ_UNDER_TOS, &valPtr);
+ if (result != TCL_OK) {
+ if (allocateDict) {
+ TclDecrRefCount(dictPtr);
+ }
+ goto checkForCatch;
+ }
+
+ /*
+ * Note that a non-existent key results in a NULL valPtr, which is a
+ * case handled separately below. What we *can* say at this point is
+ * that the write-back will always succeed.
+ */
+
+ switch (*pc) {
+ case INST_DICT_APPEND:
+ if (valPtr == NULL) {
+ valPtr = OBJ_AT_TOS;
+ } else {
+ if (Tcl_IsShared(valPtr)) {
+ valPtr = Tcl_DuplicateObj(valPtr);
+ }
+ Tcl_AppendObjToObj(valPtr, OBJ_AT_TOS);
+ }
+ break;
+ case INST_DICT_LAPPEND:
+ /*
+ * More complex because list-append can fail.
+ */
+
+ if (valPtr == NULL) {
+ valPtr = Tcl_NewListObj(1, &OBJ_AT_TOS);
+ } else if (Tcl_IsShared(valPtr)) {
+ valPtr = Tcl_DuplicateObj(valPtr);
+ result = Tcl_ListObjAppendElement(interp, valPtr, OBJ_AT_TOS);
+ if (result != TCL_OK) {
+ TclDecrRefCount(valPtr);
+ if (allocateDict) {
+ TclDecrRefCount(dictPtr);
+ }
+ goto checkForCatch;
+ }
+ } else {
+ result = Tcl_ListObjAppendElement(interp, valPtr, OBJ_AT_TOS);
+ if (result != TCL_OK) {
+ if (allocateDict) {
+ TclDecrRefCount(dictPtr);
+ }
+ goto checkForCatch;
+ }
+ }
+ break;
+ default:
+ Tcl_Panic("Should not happen!");
+ }
+
+ Tcl_DictObjPut(NULL, dictPtr, OBJ_UNDER_TOS, valPtr);
+
+ if (TclIsVarDirectWritable(varPtr)) {
+ if (allocateDict) {
+ Tcl_Obj *oldValuePtr = varPtr->value.objPtr;
+
+ Tcl_IncrRefCount(dictPtr);
+ if (oldValuePtr != NULL) {
+ TclDecrRefCount(oldValuePtr);
+ }
+ varPtr->value.objPtr = dictPtr;
+ }
+ objResultPtr = dictPtr;
+ } else {
+ Tcl_IncrRefCount(dictPtr);
+ DECACHE_STACK_INFO();
+ objResultPtr = TclPtrSetVar(interp, varPtr, NULL, NULL, NULL,
+ dictPtr, TCL_LEAVE_ERR_MSG, opnd);
+ CACHE_STACK_INFO();
+ TclDecrRefCount(dictPtr);
+ if (objResultPtr == NULL) {
+ TRACE_APPEND(("ERROR: %.30s\n",
+ O2S(Tcl_GetObjResult(interp))));
+ result = TCL_ERROR;
+ goto checkForCatch;
+ }
+ }
+#ifndef TCL_COMPILE_DEBUG
+ if (*(pc+5) == INST_POP) {
+ NEXT_INST_F(6, 2, 0);
+ }
+#endif
+ TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
+ NEXT_INST_F(5, 2, 1);
+ }
+
+ {
+ int opnd, done;
+ Tcl_Obj *statePtr, *dictPtr, *keyPtr, *valuePtr, *emptyPtr;
+ Var *varPtr;
+ Tcl_DictSearch *searchPtr;
+
+ case INST_DICT_FIRST:
+ opnd = TclGetUInt4AtPtr(pc+1);
+ TRACE(("%u => ", opnd));
+ dictPtr = POP_OBJECT();
+ searchPtr = (Tcl_DictSearch *) ckalloc(sizeof(Tcl_DictSearch));
+ result = Tcl_DictObjFirst(interp, dictPtr, searchPtr, &keyPtr,
+ &valuePtr, &done);
+ if (result != TCL_OK) {
+ ckfree((char *) searchPtr);
+ goto checkForCatch;
+ }
+ TclNewObj(statePtr);
+ statePtr->typePtr = &dictIteratorType;
+ statePtr->internalRep.twoPtrValue.ptr1 = (void *) searchPtr;
+ statePtr->internalRep.twoPtrValue.ptr2 = (void *) dictPtr;
+ varPtr = (compiledLocals + opnd);
+ if (varPtr->value.objPtr) {
+ if (varPtr->value.objPtr->typePtr != &dictIteratorType) {
+ TclDecrRefCount(varPtr->value.objPtr);
+ } else {
+ Tcl_Panic("mis-issued dictFirst!");
+ }
+ }
+ varPtr->value.objPtr = statePtr;
+ Tcl_IncrRefCount(statePtr);
+ goto pushDictIteratorResult;
+
+ case INST_DICT_NEXT:
+ opnd = TclGetUInt4AtPtr(pc+1);
+ TRACE(("%u => ", opnd));
+ statePtr = compiledLocals[opnd].value.objPtr;
+ if (statePtr == NULL || statePtr->typePtr != &dictIteratorType) {
+ Tcl_Panic("mis-issued dictNext!");
+ }
+ searchPtr = (Tcl_DictSearch *) statePtr->internalRep.twoPtrValue.ptr1;
+ Tcl_DictObjNext(searchPtr, &keyPtr, &valuePtr, &done);
+ pushDictIteratorResult:
+ if (done) {
+ TclNewObj(emptyPtr);
+ PUSH_OBJECT(emptyPtr);
+ PUSH_OBJECT(emptyPtr);
+ } else {
+ PUSH_OBJECT(valuePtr);
+ PUSH_OBJECT(keyPtr);
+ }
+ TRACE_APPEND(("\"%.30s\" \"%.30s\" %d",
+ O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), done));
+ objResultPtr = constants[done];
+ /* TODO: consider opt like INST_FOREACH_STEP4 */
+ NEXT_INST_F(5, 0, 1);
+
+ case INST_DICT_DONE:
+ opnd = TclGetUInt4AtPtr(pc+1);
+ TRACE(("%u => ", opnd));
+ statePtr = compiledLocals[opnd].value.objPtr;
+ if (statePtr == NULL) {
+ Tcl_Panic("mis-issued dictDone!");
+ }
+
+ if (statePtr->typePtr == &dictIteratorType) {
+ /*
+ * First kill the search, and then release the reference to the
+ * dictionary that we were holding.
+ */
+
+ searchPtr = (Tcl_DictSearch *)
+ statePtr->internalRep.twoPtrValue.ptr1;
+ Tcl_DictObjDone(searchPtr);
+ ckfree((char *) searchPtr);
+
+ dictPtr = (Tcl_Obj *) statePtr->internalRep.twoPtrValue.ptr2;
+ TclDecrRefCount(dictPtr);
+
+ /*
+ * Set the internal variable to an empty object to signify that we
+ * don't hold an iterator.
+ */
+
+ TclDecrRefCount(statePtr);
+ TclNewObj(emptyPtr);
+ compiledLocals[opnd].value.objPtr = emptyPtr;
+ Tcl_IncrRefCount(emptyPtr);
+ }
+ NEXT_INST_F(5, 0, 0);
+ }
+
+ {
+ int opnd, opnd2, i, length, allocdict;
+ Tcl_Obj **keyPtrPtr, *dictPtr;
+ DictUpdateInfo *duiPtr;
+ Var *varPtr;
+
+ case INST_DICT_UPDATE_START:
+ opnd = TclGetUInt4AtPtr(pc+1);
+ opnd2 = TclGetUInt4AtPtr(pc+5);
+ varPtr = &(compiledLocals[opnd]);
+ duiPtr = codePtr->auxDataArrayPtr[opnd2].clientData;
+ while (TclIsVarLink(varPtr)) {
+ varPtr = varPtr->value.linkPtr;
+ }
+ TRACE(("%u => ", opnd));
+ if (TclIsVarDirectReadable(varPtr)) {
+ dictPtr = varPtr->value.objPtr;
+ } else {
+ DECACHE_STACK_INFO();
+ dictPtr = TclPtrGetVar(interp, varPtr, NULL, NULL, NULL,
+ TCL_LEAVE_ERR_MSG, opnd);
+ CACHE_STACK_INFO();
+ if (dictPtr == NULL) {
+ goto dictUpdateStartFailed;
+ }
+ }
+ if (TclListObjGetElements(interp, OBJ_AT_TOS, &length,
+ &keyPtrPtr) != TCL_OK) {
+ goto dictUpdateStartFailed;
+ }
+ if (length != duiPtr->length) {
+ Tcl_Panic("dictUpdateStart argument length mismatch");
+ }
+ for (i=0 ; i<length ; i++) {
+ Tcl_Obj *valPtr;
+
+ if (Tcl_DictObjGet(interp, dictPtr, keyPtrPtr[i],
+ &valPtr) != TCL_OK) {
+ goto dictUpdateStartFailed;
+ }
+ varPtr = &(compiledLocals[duiPtr->varIndices[i]]);
+ while (TclIsVarLink(varPtr)) {
+ varPtr = varPtr->value.linkPtr;
+ }
+ DECACHE_STACK_INFO();
+ if (valPtr == NULL) {
+ TclObjUnsetVar2(interp,
+ localName(iPtr->varFramePtr, duiPtr->varIndices[i]),
+ NULL, 0);
+ } else if (TclPtrSetVar(interp, varPtr, NULL, NULL, NULL,
+ valPtr, TCL_LEAVE_ERR_MSG,
+ duiPtr->varIndices[i]) == NULL) {
+ CACHE_STACK_INFO();
+ dictUpdateStartFailed:
+ result = TCL_ERROR;
+ goto checkForCatch;
+ }
+ CACHE_STACK_INFO();
+ }
+ NEXT_INST_F(9, 0, 0);
+
+ case INST_DICT_UPDATE_END:
+ opnd = TclGetUInt4AtPtr(pc+1);
+ opnd2 = TclGetUInt4AtPtr(pc+5);
+ varPtr = &(compiledLocals[opnd]);
+ duiPtr = codePtr->auxDataArrayPtr[opnd2].clientData;
+ while (TclIsVarLink(varPtr)) {
+ varPtr = varPtr->value.linkPtr;
+ }
+ TRACE(("%u => ", opnd));
+ if (TclIsVarDirectReadable(varPtr)) {
+ dictPtr = varPtr->value.objPtr;
+ } else {
+ DECACHE_STACK_INFO();
+ dictPtr = TclPtrGetVar(interp, varPtr, NULL, NULL, NULL, 0, opnd);
+ CACHE_STACK_INFO();
+ }
+ if (dictPtr == NULL) {
+ NEXT_INST_F(9, 1, 0);
+ }
+ if (Tcl_DictObjSize(interp, dictPtr, &length) != TCL_OK
+ || TclListObjGetElements(interp, OBJ_AT_TOS, &length,
+ &keyPtrPtr) != TCL_OK) {
+ result = TCL_ERROR;
+ goto checkForCatch;
+ }
+ allocdict = Tcl_IsShared(dictPtr);
+ if (allocdict) {
+ dictPtr = Tcl_DuplicateObj(dictPtr);
+ }
+ for (i=0 ; i<length ; i++) {
+ Tcl_Obj *valPtr;
+ Var *var2Ptr;
+
+ var2Ptr = &(compiledLocals[duiPtr->varIndices[i]]);
+ while (TclIsVarLink(var2Ptr)) {
+ var2Ptr = var2Ptr->value.linkPtr;
+ }
+ if (TclIsVarDirectReadable(var2Ptr)) {
+ valPtr = var2Ptr->value.objPtr;
+ } else {
+ DECACHE_STACK_INFO();
+ valPtr = TclPtrGetVar(interp, var2Ptr, NULL, NULL, NULL, 0,
+ duiPtr->varIndices[i]);
+ CACHE_STACK_INFO();
+ }
+ if (valPtr == NULL) {
+ Tcl_DictObjRemove(interp, dictPtr, keyPtrPtr[i]);
+ } else if (dictPtr == valPtr) {
+ Tcl_DictObjPut(interp, dictPtr, keyPtrPtr[i],
+ Tcl_DuplicateObj(valPtr));
+ } else {
+ Tcl_DictObjPut(interp, dictPtr, keyPtrPtr[i], valPtr);
+ }
+ }
+ if (TclIsVarDirectWritable(varPtr)) {
+ Tcl_IncrRefCount(dictPtr);
+ TclDecrRefCount(varPtr->value.objPtr);
+ varPtr->value.objPtr = dictPtr;
+ } else {
+ DECACHE_STACK_INFO();
+ objResultPtr = TclPtrSetVar(interp, varPtr, NULL, NULL, NULL,
+ dictPtr, TCL_LEAVE_ERR_MSG, opnd);
+ CACHE_STACK_INFO();
+ if (objResultPtr == NULL) {
+ if (allocdict) {
+ TclDecrRefCount(dictPtr);
+ }
+ result = TCL_ERROR;
+ goto checkForCatch;
+ }
+ }
+ NEXT_INST_F(9, 1, 0);
+ }
+
default:
- panic("TclExecuteByteCode: unrecognized opCode %u", *pc);
+ Tcl_Panic("TclExecuteByteCode: unrecognized opCode %u", *pc);
} /* end of switch on opCode */
/*
- * Division by zero in an expression. Control only reaches this
- * point by "goto divideByZero".
+ * Division by zero in an expression. Control only reaches this point by
+ * "goto divideByZero".
*/
-
+
divideByZero:
DECACHE_STACK_INFO();
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp), "divide by zero", -1);
- Tcl_SetErrorCode(interp, "ARITH", "DIVZERO", "divide by zero",
- (char *) NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("divide by zero", -1));
+ Tcl_SetErrorCode(interp, "ARITH", "DIVZERO", "divide by zero", NULL);
CACHE_STACK_INFO();
result = TCL_ERROR;
goto checkForCatch;
-
+
/*
- * An external evaluation (INST_INVOKE or INST_EVAL) returned
- * something different from TCL_OK, or else INST_BREAK or
- * INST_CONTINUE were called.
+ * Exponentiation of zero by negative number in an expression. Control
+ * only reaches this point by "goto exponOfZero".
*/
- processExceptionReturn:
-#if TCL_COMPILE_DEBUG
- switch (*pc) {
- case INST_INVOKE_STK1:
- case INST_INVOKE_STK4:
+ exponOfZero:
+ DECACHE_STACK_INFO();
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "exponentiation of zero by negative power", -1));
+ Tcl_SetErrorCode(interp, "ARITH", "DOMAIN",
+ "exponentiation of zero by negative power", NULL);
+ CACHE_STACK_INFO();
+ result = TCL_ERROR;
+ goto checkForCatch;
+
+ /*
+ * Block for variables needed to process exception returns.
+ */
+
+ {
+ ExceptionRange *rangePtr;
+ /* Points to closest loop or catch exception
+ * range enclosing the pc. Used by various
+ * instructions and processCatch to process
+ * break, continue, and errors. */
+ Tcl_Obj *valuePtr;
+ const char *bytes;
+ int length;
+#if TCL_COMPILE_DEBUG
+ int opnd;
+#endif
+
+ /*
+ * An external evaluation (INST_INVOKE or INST_EVAL) returned
+ * something different from TCL_OK, or else INST_BREAK or
+ * INST_CONTINUE were called.
+ */
+
+ processExceptionReturn:
+#if TCL_COMPILE_DEBUG
+ switch (*pc) {
+ case INST_INVOKE_STK1:
+ opnd = TclGetUInt1AtPtr(pc+1);
TRACE(("%u => ... after \"%.20s\": ", opnd, cmdNameBuf));
break;
- case INST_EVAL_STK:
+ case INST_INVOKE_STK4:
+ opnd = TclGetUInt4AtPtr(pc+1);
+ TRACE(("%u => ... after \"%.20s\": ", opnd, cmdNameBuf));
+ break;
+ case INST_EVAL_STK:
/*
- * Note that the object at stacktop has to be used
- * before doing the cleanup.
+ * Note that the object at stacktop has to be used before doing
+ * the cleanup.
*/
- TRACE(("\"%.30s\" => ", O2S(stackPtr[stackTop])));
+ TRACE(("\"%.30s\" => ", O2S(OBJ_AT_TOS)));
break;
- default:
+ default:
TRACE(("=> "));
- }
-#endif
- if ((result == TCL_CONTINUE) || (result == TCL_BREAK)) {
- rangePtr = GetExceptRangeForPc(pc, /*catchOnly*/ 0, codePtr);
- if (rangePtr == NULL) {
- TRACE_APPEND(("no encl. loop or catch, returning %s\n",
- StringForResultCode(result)));
- goto abnormalReturn;
- }
- if (rangePtr->type == CATCH_EXCEPTION_RANGE) {
- TRACE_APPEND(("%s ...\n", StringForResultCode(result)));
- goto processCatch;
}
- while (cleanup--) {
- valuePtr = POP_OBJECT();
- TclDecrRefCount(valuePtr);
+#endif
+ if ((result == TCL_CONTINUE) || (result == TCL_BREAK)) {
+ rangePtr = GetExceptRangeForPc(pc, /*catchOnly*/ 0, codePtr);
+ if (rangePtr == NULL) {
+ TRACE_APPEND(("no encl. loop or catch, returning %s\n",
+ StringForResultCode(result)));
+ goto abnormalReturn;
+ }
+ if (rangePtr->type == CATCH_EXCEPTION_RANGE) {
+ TRACE_APPEND(("%s ...\n", StringForResultCode(result)));
+ goto processCatch;
+ }
+ while (cleanup--) {
+ valuePtr = POP_OBJECT();
+ TclDecrRefCount(valuePtr);
+ }
+ if (result == TCL_BREAK) {
+ result = TCL_OK;
+ pc = (codePtr->codeStart + rangePtr->breakOffset);
+ TRACE_APPEND(("%s, range at %d, new pc %d\n",
+ StringForResultCode(result),
+ rangePtr->codeOffset, rangePtr->breakOffset));
+ NEXT_INST_F(0, 0, 0);
+ } else {
+ if (rangePtr->continueOffset == -1) {
+ TRACE_APPEND((
+ "%s, loop w/o continue, checking for catch\n",
+ StringForResultCode(result)));
+ goto checkForCatch;
+ }
+ result = TCL_OK;
+ pc = (codePtr->codeStart + rangePtr->continueOffset);
+ TRACE_APPEND(("%s, range at %d, new pc %d\n",
+ StringForResultCode(result),
+ rangePtr->codeOffset, rangePtr->continueOffset));
+ NEXT_INST_F(0, 0, 0);
+ }
+#if TCL_COMPILE_DEBUG
+ } else if (traceInstructions) {
+ if ((result != TCL_ERROR) && (result != TCL_RETURN)) {
+ Tcl_Obj *objPtr = Tcl_GetObjResult(interp);
+ TRACE_APPEND(("OTHER RETURN CODE %d, result= \"%s\"\n ",
+ result, O2S(objPtr)));
+ } else {
+ Tcl_Obj *objPtr = Tcl_GetObjResult(interp);
+ TRACE_APPEND(("%s, result= \"%s\"\n",
+ StringForResultCode(result), O2S(objPtr)));
+ }
+#endif
}
- if (result == TCL_BREAK) {
- result = TCL_OK;
- pc = (codePtr->codeStart + rangePtr->breakOffset);
- TRACE_APPEND(("%s, range at %d, new pc %d\n",
- StringForResultCode(result),
- rangePtr->codeOffset, rangePtr->breakOffset));
- NEXT_INST_F(0, 0, 0);
- } else {
- if (rangePtr->continueOffset == -1) {
- TRACE_APPEND(("%s, loop w/o continue, checking for catch\n",
- StringForResultCode(result)));
- goto checkForCatch;
- }
- result = TCL_OK;
- pc = (codePtr->codeStart + rangePtr->continueOffset);
- TRACE_APPEND(("%s, range at %d, new pc %d\n",
- StringForResultCode(result),
- rangePtr->codeOffset, rangePtr->continueOffset));
- NEXT_INST_F(0, 0, 0);
- }
-#if TCL_COMPILE_DEBUG
- } else if (traceInstructions) {
- if ((result != TCL_ERROR) && (result != TCL_RETURN)) {
- objPtr = Tcl_GetObjResult(interp);
- TRACE_APPEND(("OTHER RETURN CODE %d, result= \"%s\"\n ",
- result, O2S(objPtr)));
- } else {
- objPtr = Tcl_GetObjResult(interp);
- TRACE_APPEND(("%s, result= \"%s\"\n",
- StringForResultCode(result), O2S(objPtr)));
+
+ /*
+ * Execution has generated an "exception" such as TCL_ERROR. If the
+ * exception is an error, record information about what was being
+ * executed when the error occurred. Find the closest enclosing catch
+ * range, if any. If no enclosing catch range is found, stop execution
+ * and return the "exception" code.
+ */
+
+ checkForCatch:
+ if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
+ bytes = GetSrcInfoForPc(pc, codePtr, &length);
+ if (bytes != NULL) {
+ DECACHE_STACK_INFO();
+ Tcl_LogCommandInfo(interp, codePtr->source, bytes, length);
+ CACHE_STACK_INFO();
+ }
+ }
+ iPtr->flags &= ~ERR_ALREADY_LOGGED;
+
+ /*
+ * Clear all expansions that may have started after the last
+ * INST_BEGIN_CATCH.
+ */
+
+ while ((expandNestList != NULL) && ((catchTop == initCatchTop) ||
+ (*catchTop <=
+ (ptrdiff_t) expandNestList->internalRep.twoPtrValue.ptr1))) {
+ Tcl_Obj *objPtr = expandNestList->internalRep.twoPtrValue.ptr2;
+
+ TclDecrRefCount(expandNestList);
+ expandNestList = objPtr;
}
+
+ /*
+ * We must not catch an exceeded limit. Instead, it blows outwards
+ * until we either hit another interpreter (presumably where the limit
+ * is not exceeded) or we get to the top-level.
+ */
+
+ if (TclLimitExceeded(iPtr->limit)) {
+#ifdef TCL_COMPILE_DEBUG
+ if (traceInstructions) {
+ fprintf(stdout, " ... limit exceeded, returning %s\n",
+ StringForResultCode(result));
+ }
#endif
- }
-
- /*
- * Execution has generated an "exception" such as TCL_ERROR. If the
- * exception is an error, record information about what was being
- * executed when the error occurred. Find the closest enclosing
- * catch range, if any. If no enclosing catch range is found, stop
- * execution and return the "exception" code.
- */
-
- checkForCatch:
- if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
- bytes = GetSrcInfoForPc(pc, codePtr, &length);
- if (bytes != NULL) {
- DECACHE_STACK_INFO();
- Tcl_LogCommandInfo(interp, codePtr->source, bytes, length);
- CACHE_STACK_INFO();
- iPtr->flags |= ERR_ALREADY_LOGGED;
+ goto abnormalReturn;
}
- }
- if (catchTop == -1) {
+ if (catchTop == initCatchTop) {
#ifdef TCL_COMPILE_DEBUG
- if (traceInstructions) {
- fprintf(stdout, " ... no enclosing catch, returning %s\n",
- StringForResultCode(result));
+ if (traceInstructions) {
+ fprintf(stdout, " ... no enclosing catch, returning %s\n",
+ StringForResultCode(result));
+ }
+#endif
+ goto abnormalReturn;
}
+ rangePtr = GetExceptRangeForPc(pc, /*catchOnly*/ 1, codePtr);
+ if (rangePtr == NULL) {
+ /*
+ * This is only possible when compiling a [catch] that sends its
+ * script to INST_EVAL. Cannot correct the compiler without
+ * breakingcompat with previous .tbc compiled scripts.
+ */
+
+#ifdef TCL_COMPILE_DEBUG
+ if (traceInstructions) {
+ fprintf(stdout, " ... no enclosing catch, returning %s\n",
+ StringForResultCode(result));
+ }
#endif
- goto abnormalReturn;
- }
- rangePtr = GetExceptRangeForPc(pc, /*catchOnly*/ 1, codePtr);
- if (rangePtr == NULL) {
+ goto abnormalReturn;
+ }
+
/*
- * This is only possible when compiling a [catch] that sends its
- * script to INST_EVAL. Cannot correct the compiler without
- * breakingcompat with previous .tbc compiled scripts.
+ * A catch exception range (rangePtr) was found to handle an
+ * "exception". It was found either by checkForCatch just above or by
+ * an instruction during break, continue, or error processing. Jump to
+ * its catchOffset after unwinding the operand stack to the depth it
+ * had when starting to execute the range's catch command.
*/
+
+ processCatch:
+ while (CURR_DEPTH > *catchTop) {
+ valuePtr = POP_OBJECT();
+ TclDecrRefCount(valuePtr);
+ }
#ifdef TCL_COMPILE_DEBUG
if (traceInstructions) {
- fprintf(stdout, " ... no enclosing catch, returning %s\n",
- StringForResultCode(result));
+ fprintf(stdout, " ... found catch at %d, catchTop=%d, "
+ "unwound to %ld, new pc %u\n",
+ rangePtr->codeOffset, (int) (catchTop - initCatchTop - 1),
+ (long) *catchTop, (unsigned) rangePtr->catchOffset);
}
#endif
- goto abnormalReturn;
- }
+ pc = (codePtr->codeStart + rangePtr->catchOffset);
+ NEXT_INST_F(0, 0, 0); /* Restart the execution loop at pc. */
- /*
- * A catch exception range (rangePtr) was found to handle an
- * "exception". It was found either by checkForCatch just above or
- * by an instruction during break, continue, or error processing.
- * Jump to its catchOffset after unwinding the operand stack to
- * the depth it had when starting to execute the range's catch
- * command.
- */
+ /*
+ * end of infinite loop dispatching on instructions.
+ */
- processCatch:
- while (stackTop > catchStackPtr[catchTop]) {
- valuePtr = POP_OBJECT();
- TclDecrRefCount(valuePtr);
- }
-#ifdef TCL_COMPILE_DEBUG
- if (traceInstructions) {
- fprintf(stdout, " ... found catch at %d, catchTop=%d, unwound to %d, new pc %u\n",
- rangePtr->codeOffset, catchTop, catchStackPtr[catchTop],
- (unsigned int)(rangePtr->catchOffset));
- }
-#endif
- pc = (codePtr->codeStart + rangePtr->catchOffset);
- NEXT_INST_F(0, 0, 0); /* restart the execution loop at pc */
+ /*
+ * Abnormal return code. Restore the stack to state it had when
+ * starting to execute the ByteCode. Panic if the stack is below the
+ * initial level.
+ */
- /*
- * end of infinite loop dispatching on instructions.
- */
+ abnormalReturn:
+ TCL_DTRACE_INST_LAST();
+ while (tosPtr > initTosPtr) {
+ Tcl_Obj *objPtr = POP_OBJECT();
- /*
- * Abnormal return code. Restore the stack to state it had when starting
- * to execute the ByteCode. Panic if the stack is below the initial level.
- */
+ Tcl_DecrRefCount(objPtr);
+ }
- abnormalReturn:
- TCL_DTRACE_INST_LAST();
- while (stackTop > initStackTop) {
- valuePtr = POP_OBJECT();
- TclDecrRefCount(valuePtr);
- }
- if (stackTop < initStackTop) {
- fprintf(stderr, "\nTclExecuteByteCode: abnormal return at pc %u: stack top %d < entry stack top %d\n",
- (unsigned int)(pc - codePtr->codeStart),
- (unsigned int) stackTop,
- (unsigned int) initStackTop);
- panic("TclExecuteByteCode execution failure: end stack top < start stack top");
+ /*
+ * Clear all expansions.
+ */
+
+ while (expandNestList) {
+ Tcl_Obj *objPtr = expandNestList->internalRep.twoPtrValue.ptr2;
+
+ TclDecrRefCount(expandNestList);
+ expandNestList = objPtr;
+ }
+ if (tosPtr < initTosPtr) {
+ fprintf(stderr,
+ "\nTclExecuteByteCode: abnormal return at pc %u: "
+ "stack top %d < entry stack top %d\n",
+ (unsigned)(pc - codePtr->codeStart),
+ (unsigned) CURR_DEPTH, (unsigned) 0);
+ Tcl_Panic("TclExecuteByteCode execution failure: end stack top < start stack top");
+ }
}
-
+
/*
- * Free the catch stack array if malloc'ed storage was used.
+ * Restore the stack to the state it had previous to this bytecode.
*/
- if (catchStackPtr != catchStackStorage) {
- ckfree((char *) catchStackPtr);
- }
- eePtr->stackTop = initStackTop;
-
+ TclStackFree(interp, initCatchTop+1);
return result;
-#undef STATIC_CATCH_STACK_SIZE
+#undef iPtr
}
#ifdef TCL_COMPILE_DEBUG
@@ -4537,9 +7548,9 @@ TclExecuteByteCode(interp, codePtr)
*
* PrintByteCodeInfo --
*
- * This procedure prints a summary about a bytecode object to stdout.
- * It is called by TclExecuteByteCode when starting to execute the
- * bytecode object if tclTraceExec has the value 2 or more.
+ * This procedure prints a summary about a bytecode object to stdout. It
+ * is called by TclExecuteByteCode when starting to execute the bytecode
+ * object if tclTraceExec has the value 2 or more.
*
* Results:
* None.
@@ -4551,46 +7562,45 @@ TclExecuteByteCode(interp, codePtr)
*/
static void
-PrintByteCodeInfo(codePtr)
- register ByteCode *codePtr; /* The bytecode whose summary is printed
- * to stdout. */
+PrintByteCodeInfo(
+ register ByteCode *codePtr) /* The bytecode whose summary is printed to
+ * stdout. */
{
Proc *procPtr = codePtr->procPtr;
Interp *iPtr = (Interp *) *codePtr->interpHandle;
- fprintf(stdout, "\nExecuting ByteCode 0x%x, refCt %u, epoch %u, interp 0x%x (epoch %u)\n",
- (unsigned int) codePtr, codePtr->refCount,
- codePtr->compileEpoch, (unsigned int) iPtr,
+ fprintf(stdout, "\nExecuting ByteCode 0x%p, refCt %u, epoch %u, interp 0x%p (epoch %u)\n",
+ codePtr, codePtr->refCount, codePtr->compileEpoch, iPtr,
iPtr->compileEpoch);
-
+
fprintf(stdout, " Source: ");
TclPrintSource(stdout, codePtr->source, 60);
fprintf(stdout, "\n Cmds %d, src %d, inst %u, litObjs %u, aux %d, stkDepth %u, code/src %.2f\n",
- codePtr->numCommands, codePtr->numSrcBytes,
+ codePtr->numCommands, codePtr->numSrcBytes,
codePtr->numCodeBytes, codePtr->numLitObjects,
codePtr->numAuxDataItems, codePtr->maxStackDepth,
#ifdef TCL_COMPILE_STATS
- (codePtr->numSrcBytes?
- ((float)codePtr->structureSize)/((float)codePtr->numSrcBytes) : 0.0));
-#else
- 0.0);
+ codePtr->numSrcBytes?
+ ((float)codePtr->structureSize)/codePtr->numSrcBytes :
#endif
+ 0.0);
+
#ifdef TCL_COMPILE_STATS
- fprintf(stdout, " Code %u = header %u+inst %d+litObj %lu+exc %lu+aux %lu+cmdMap %d\n",
- (unsigned int)codePtr->structureSize,
- (unsigned int)(sizeof(ByteCode) - (sizeof(size_t) + sizeof(Tcl_Time))),
+ fprintf(stdout, " Code %lu = header %lu+inst %d+litObj %lu+exc %lu+aux %lu+cmdMap %d\n",
+ (unsigned long) codePtr->structureSize,
+ (unsigned long) (sizeof(ByteCode)-sizeof(size_t)-sizeof(Tcl_Time)),
codePtr->numCodeBytes,
- (unsigned long)(codePtr->numLitObjects * sizeof(Tcl_Obj *)),
- (unsigned long)(codePtr->numExceptRanges * sizeof(ExceptionRange)),
- (unsigned long)(codePtr->numAuxDataItems * sizeof(AuxData)),
+ (unsigned long) (codePtr->numLitObjects * sizeof(Tcl_Obj *)),
+ (unsigned long) (codePtr->numExceptRanges*sizeof(ExceptionRange)),
+ (unsigned long) (codePtr->numAuxDataItems * sizeof(AuxData)),
codePtr->numCmdLocBytes);
#endif /* TCL_COMPILE_STATS */
if (procPtr != NULL) {
fprintf(stdout,
- " Proc 0x%x, refCt %d, args %d, compiled locals %d\n",
- (unsigned int) procPtr, procPtr->refCount,
- procPtr->numArgs, procPtr->numCompiledLocals);
+ " Proc 0x%p, refCt %d, args %d, compiled locals %d\n",
+ procPtr, procPtr->refCount, procPtr->numArgs,
+ procPtr->numCompiledLocals);
}
}
#endif /* TCL_COMPILE_DEBUG */
@@ -4608,60 +7618,63 @@ PrintByteCodeInfo(codePtr)
* None.
*
* Side effects:
- * Prints a message to stderr and panics if either the pc or stack
- * top are invalid.
+ * Prints a message to stderr and panics if either the pc or stack top
+ * are invalid.
*
*----------------------------------------------------------------------
*/
#ifdef TCL_COMPILE_DEBUG
static void
-ValidatePcAndStackTop(codePtr, pc, stackTop, stackLowerBound)
- register ByteCode *codePtr; /* The bytecode whose summary is printed
- * to stdout. */
- unsigned char *pc; /* Points to first byte of a bytecode
+ValidatePcAndStackTop(
+ register ByteCode *codePtr, /* The bytecode whose summary is printed to
+ * stdout. */
+ unsigned char *pc, /* Points to first byte of a bytecode
* instruction. The program counter. */
- int stackTop; /* Current stack top. Must be between
+ int stackTop, /* Current stack top. Must be between
* stackLowerBound and stackUpperBound
* (inclusive). */
- int stackLowerBound; /* Smallest legal value for stackTop. */
+ int stackLowerBound, /* Smallest legal value for stackTop. */
+ int checkStack) /* 0 if the stack depth check should be
+ * skipped. */
{
- int stackUpperBound = stackLowerBound + codePtr->maxStackDepth;
- /* Greatest legal value for stackTop. */
- unsigned int relativePc = (unsigned int) (pc - codePtr->codeStart);
- unsigned int codeStart = (unsigned int) codePtr->codeStart;
- unsigned int codeEnd = (unsigned int)
+ int stackUpperBound = stackLowerBound + codePtr->maxStackDepth;
+ /* Greatest legal value for stackTop. */
+ unsigned relativePc = (unsigned) (pc - codePtr->codeStart);
+ unsigned long codeStart = (unsigned long) codePtr->codeStart;
+ unsigned long codeEnd = (unsigned long)
(codePtr->codeStart + codePtr->numCodeBytes);
unsigned char opCode = *pc;
- if (((unsigned int) pc < codeStart) || ((unsigned int) pc > codeEnd)) {
- fprintf(stderr, "\nBad instruction pc 0x%x in TclExecuteByteCode\n",
- (unsigned int) pc);
- panic("TclExecuteByteCode execution failure: bad pc");
+ if (((unsigned long) pc < codeStart) || ((unsigned long) pc > codeEnd)) {
+ fprintf(stderr, "\nBad instruction pc 0x%p in TclExecuteByteCode\n",
+ pc);
+ Tcl_Panic("TclExecuteByteCode execution failure: bad pc");
}
- if ((unsigned int) opCode > LAST_INST_OPCODE) {
+ if ((unsigned) opCode > LAST_INST_OPCODE) {
fprintf(stderr, "\nBad opcode %d at pc %u in TclExecuteByteCode\n",
- (unsigned int) opCode, relativePc);
- panic("TclExecuteByteCode execution failure: bad opcode");
+ (unsigned) opCode, relativePc);
+ Tcl_Panic("TclExecuteByteCode execution failure: bad opcode");
}
- if ((stackTop < stackLowerBound) || (stackTop > stackUpperBound)) {
+ if (checkStack &&
+ ((stackTop < stackLowerBound) || (stackTop > stackUpperBound))) {
int numChars;
- char *cmd = GetSrcInfoForPc(pc, codePtr, &numChars);
- char *ellipsis = "";
-
+ const char *cmd = GetSrcInfoForPc(pc, codePtr, &numChars);
+
fprintf(stderr, "\nBad stack top %d at pc %u in TclExecuteByteCode (min %i, max %i)",
stackTop, relativePc, stackLowerBound, stackUpperBound);
if (cmd != NULL) {
- if (numChars > 100) {
- numChars = 100;
- ellipsis = "...";
- }
- fprintf(stderr, "\n executing %.*s%s\n", numChars, cmd,
- ellipsis);
+ Tcl_Obj *message;
+
+ TclNewLiteralStringObj(message, "\n executing ");
+ Tcl_IncrRefCount(message);
+ Tcl_AppendLimitedToObj(message, cmd, numChars, 100, NULL);
+ fprintf(stderr,"%s\n", Tcl_GetString(message));
+ Tcl_DecrRefCount(message);
} else {
fprintf(stderr, "\n");
}
- panic("TclExecuteByteCode execution failure: bad stack top");
+ Tcl_Panic("TclExecuteByteCode execution failure: bad stack top");
}
}
#endif /* TCL_COMPILE_DEBUG */
@@ -4671,142 +7684,66 @@ ValidatePcAndStackTop(codePtr, pc, stackTop, stackLowerBound)
*
* IllegalExprOperandType --
*
- * Used by TclExecuteByteCode to add an error message to errorInfo
- * when an illegal operand type is detected by an expression
+ * Used by TclExecuteByteCode to append an error message to the interp
+ * result when an illegal operand type is detected by an expression
* instruction. The argument opndPtr holds the operand object in error.
*
* Results:
* None.
*
* Side effects:
- * An error message is appended to errorInfo.
+ * An error message is appended to the interp result.
*
*----------------------------------------------------------------------
*/
static void
-IllegalExprOperandType(interp, pc, opndPtr)
- Tcl_Interp *interp; /* Interpreter to which error information
+IllegalExprOperandType(
+ Tcl_Interp *interp, /* Interpreter to which error information
* pertains. */
- unsigned char *pc; /* Points to the instruction being executed
+ unsigned char *pc, /* Points to the instruction being executed
* when the illegal type was found. */
- Tcl_Obj *opndPtr; /* Points to the operand holding the value
+ Tcl_Obj *opndPtr) /* Points to the operand holding the value
* with the illegal type. */
{
- unsigned char opCode = *pc;
-
- Tcl_ResetResult(interp);
- if ((opndPtr->bytes == NULL) || (opndPtr->length == 0)) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "can't use empty string as operand of \"",
- operatorStrings[opCode - INST_LOR], "\"", (char *) NULL);
- } else {
- char *msg = "non-numeric string";
- char *s, *p;
- int length;
- int looksLikeInt = 0;
+ ClientData ptr;
+ int type;
+ unsigned char opcode = *pc;
+ const char *description, *operator = operatorStrings[opcode - INST_LOR];
- s = Tcl_GetStringFromObj(opndPtr, &length);
- p = s;
- /*
- * strtod() isn't at all consistent about detecting Inf and
- * NaN between platforms.
- */
- if (length == 3) {
- if ((s[0]=='n' || s[0]=='N') && (s[1]=='a' || s[1]=='A') &&
- (s[2]=='n' || s[2]=='N')) {
- msg = "non-numeric floating-point value";
- goto makeErrorMessage;
- }
- if ((s[0]=='i' || s[0]=='I') && (s[1]=='n' || s[1]=='N') &&
- (s[2]=='f' || s[2]=='F')) {
- msg = "infinite floating-point value";
- goto makeErrorMessage;
- }
- }
+ if (opcode == INST_EXPON) {
+ operator = "**";
+ }
- /*
- * We cannot use TclLooksLikeInt here because it passes strings
- * like "10;" [Bug 587140]. We'll accept as "looking like ints"
- * for the present purposes any string that looks formally like
- * a (decimal|octal|hex) integer.
- */
+ if (GetNumberFromObj(NULL, opndPtr, &ptr, &type) != TCL_OK) {
+ int numBytes;
+ const char *bytes = Tcl_GetStringFromObj(opndPtr, &numBytes);
- while (length && isspace(UCHAR(*p))) {
- length--;
- p++;
- }
- if (length && ((*p == '+') || (*p == '-'))) {
- length--;
- p++;
- }
- if (length) {
- if ((*p == '0') && ((*(p+1) == 'x') || (*(p+1) == 'X'))) {
- p += 2;
- length -= 2;
- looksLikeInt = ((length > 0) && isxdigit(UCHAR(*p)));
- if (looksLikeInt) {
- length--;
- p++;
- while (length && isxdigit(UCHAR(*p))) {
- length--;
- p++;
- }
- }
- } else {
- looksLikeInt = (length && isdigit(UCHAR(*p)));
- if (looksLikeInt) {
- length--;
- p++;
- while (length && isdigit(UCHAR(*p))) {
- length--;
- p++;
- }
- }
- }
- while (length && isspace(UCHAR(*p))) {
- length--;
- p++;
- }
- looksLikeInt = !length;
- }
- if (looksLikeInt) {
- /*
- * If something that looks like an integer could not be
- * converted, then it *must* be a bad octal or too large
- * to represent [Bug 542588].
- */
-
- if (TclCheckBadOctal(NULL, s)) {
- msg = "invalid octal number";
- } else {
- msg = "integer value too large to represent";
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
- "integer value too large to represent", (char *) NULL);
- }
+ if (numBytes == 0) {
+ description = "empty string";
+ } else if (TclCheckBadOctal(NULL, bytes)) {
+ description = "invalid octal number";
} else {
- /*
- * See if the operand can be interpreted as a double in
- * order to improve the error message.
- */
-
- double d;
-
- if (Tcl_GetDouble((Tcl_Interp *) NULL, s, &d) == TCL_OK) {
- msg = "floating-point value";
- }
+ description = "non-numeric string";
}
- makeErrorMessage:
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "can't use ",
- msg, " as operand of \"", operatorStrings[opCode - INST_LOR],
- "\"", (char *) NULL);
+ } else if (type == TCL_NUMBER_NAN) {
+ description = "non-numeric floating-point value";
+ } else if (type == TCL_NUMBER_DOUBLE) {
+ description = "floating-point value";
+ } else {
+ /* TODO: No caller needs this. Eliminate? */
+ description = "(big) integer";
}
+
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't use %s as operand of \"%s\"", description, operator));
+ Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", description, NULL);
}
/*
*----------------------------------------------------------------------
*
- * TclGetSrcInfoForPc, GetSrcInfoForPc --
+ * TclGetSrcInfoForPc, GetSrcInfoForPc, TclGetSrcInfoForCmd --
*
* Given a program counter value, finds the closest command in the
* bytecode code unit's CmdLocation array and returns information about
@@ -4816,85 +7753,98 @@ IllegalExprOperandType(interp, pc, opndPtr)
* Results:
* If a command is found that encloses the program counter value, a
* pointer to the command's source is returned and the length of the
- * source is stored at *lengthPtr. If multiple commands resulted in
- * code at pc, information about the closest enclosing command is
- * returned. If no matching command is found, NULL is returned and
- * *lengthPtr is unchanged.
+ * source is stored at *lengthPtr. If multiple commands resulted in code
+ * at pc, information about the closest enclosing command is returned. If
+ * no matching command is found, NULL is returned and *lengthPtr is
+ * unchanged.
*
* Side effects:
- * None.
+ * The CmdFrame at *cfPtr is updated.
*
*----------------------------------------------------------------------
*/
-#ifdef TCL_TIP280
+const char *
+TclGetSrcInfoForCmd(
+ Interp *iPtr,
+ int *lenPtr)
+{
+ CmdFrame *cfPtr = iPtr->cmdFramePtr;
+ ByteCode *codePtr = (ByteCode *) cfPtr->data.tebc.codePtr;
+
+ return GetSrcInfoForPc((unsigned char *) cfPtr->data.tebc.pc,
+ codePtr, lenPtr);
+}
+
void
-TclGetSrcInfoForPc (cfPtr)
- CmdFrame* cfPtr;
+TclGetSrcInfoForPc(
+ CmdFrame *cfPtr)
{
- ByteCode* codePtr = (ByteCode*) cfPtr->data.tebc.codePtr;
+ ByteCode *codePtr = (ByteCode *) cfPtr->data.tebc.codePtr;
if (cfPtr->cmd.str.cmd == NULL) {
- cfPtr->cmd.str.cmd = GetSrcInfoForPc((unsigned char*) cfPtr->data.tebc.pc,
- codePtr,
- &cfPtr->cmd.str.len);
+ cfPtr->cmd.str.cmd = GetSrcInfoForPc(
+ (unsigned char *) cfPtr->data.tebc.pc, codePtr,
+ &cfPtr->cmd.str.len);
}
if (cfPtr->cmd.str.cmd != NULL) {
- /* We now have the command. We can get the srcOffset back and
- * from there find the list of word locations for this command
+ /*
+ * We now have the command. We can get the srcOffset back and from
+ * there find the list of word locations for this command.
*/
- ExtCmdLoc* eclPtr;
- ECL* locPtr = NULL;
- int srcOffset;
+ ExtCmdLoc *eclPtr;
+ ECL *locPtr = NULL;
+ int srcOffset, i;
+ Interp *iPtr = (Interp *) *codePtr->interpHandle;
+ Tcl_HashEntry *hePtr =
+ Tcl_FindHashEntry(iPtr->lineBCPtr, (char *) codePtr);
- Interp* iPtr = (Interp*) *codePtr->interpHandle;
- Tcl_HashEntry* hePtr = Tcl_FindHashEntry (iPtr->lineBCPtr, (char *) codePtr);
-
- if (!hePtr) return;
+ if (!hePtr) {
+ return;
+ }
srcOffset = cfPtr->cmd.str.cmd - codePtr->source;
- eclPtr = (ExtCmdLoc*) Tcl_GetHashValue (hePtr);
+ eclPtr = (ExtCmdLoc *) Tcl_GetHashValue (hePtr);
- {
- int i;
- for (i=0; i < eclPtr->nuloc; i++) {
- if (eclPtr->loc [i].srcOffset == srcOffset) {
- locPtr = &(eclPtr->loc [i]);
- break;
- }
+ for (i=0; i < eclPtr->nuloc; i++) {
+ if (eclPtr->loc[i].srcOffset == srcOffset) {
+ locPtr = eclPtr->loc+i;
+ break;
}
}
+ if (locPtr == NULL) {
+ Tcl_Panic("LocSearch failure");
+ }
- if (locPtr == NULL) {Tcl_Panic ("LocSearch failure");}
-
- cfPtr->line = locPtr->line;
- cfPtr->nline = locPtr->nline;
- cfPtr->type = eclPtr->type;
+ cfPtr->line = locPtr->line;
+ cfPtr->nline = locPtr->nline;
+ cfPtr->type = eclPtr->type;
if (eclPtr->type == TCL_LOCATION_SOURCE) {
cfPtr->data.eval.path = eclPtr->path;
- Tcl_IncrRefCount (cfPtr->data.eval.path);
+ Tcl_IncrRefCount(cfPtr->data.eval.path);
}
- /* Do not set cfPtr->data.eval.path NULL for non-SOURCE
- * Needed for cfPtr->data.tebc.codePtr.
+
+ /*
+ * Do not set cfPtr->data.eval.path NULL for non-SOURCE. Needed for
+ * cfPtr->data.tebc.codePtr.
*/
}
}
-#endif
-static char *
-GetSrcInfoForPc(pc, codePtr, lengthPtr)
- unsigned char *pc; /* The program counter value for which to
+static const char *
+GetSrcInfoForPc(
+ unsigned char *pc, /* The program counter value for which to
* return the closest command's source info.
- * This points to a bytecode instruction
- * in codePtr's code. */
- ByteCode *codePtr; /* The bytecode sequence in which to look
- * up the command source for the pc. */
- int *lengthPtr; /* If non-NULL, the location where the
- * length of the command's source should be
- * stored. If NULL, no length is stored. */
+ * This points to a bytecode instruction in
+ * codePtr's code. */
+ ByteCode *codePtr, /* The bytecode sequence in which to look up
+ * the command source for the pc. */
+ int *lengthPtr) /* If non-NULL, the location where the length
+ * of the command's source should be stored.
+ * If NULL, no length is stored. */
{
register int pcOffset = (pc - codePtr->codeStart);
int numCmds = codePtr->numCommands;
@@ -4917,11 +7867,11 @@ GetSrcInfoForPc(pc, codePtr, lengthPtr)
codeDeltaNext = codePtr->codeDeltaStart;
codeLengthNext = codePtr->codeLengthStart;
- srcDeltaNext = codePtr->srcDeltaStart;
+ srcDeltaNext = codePtr->srcDeltaStart;
srcLengthNext = codePtr->srcLengthStart;
codeOffset = srcOffset = 0;
for (i = 0; i < numCmds; i++) {
- if ((unsigned int) (*codeDeltaNext) == (unsigned int) 0xFF) {
+ if ((unsigned) *codeDeltaNext == (unsigned) 0xFF) {
codeDeltaNext++;
delta = TclGetInt4AtPtr(codeDeltaNext);
codeDeltaNext += 4;
@@ -4931,7 +7881,7 @@ GetSrcInfoForPc(pc, codePtr, lengthPtr)
}
codeOffset += delta;
- if ((unsigned int) (*codeLengthNext) == (unsigned int) 0xFF) {
+ if ((unsigned) *codeLengthNext == (unsigned) 0xFF) {
codeLengthNext++;
codeLen = TclGetInt4AtPtr(codeLengthNext);
codeLengthNext += 4;
@@ -4941,7 +7891,7 @@ GetSrcInfoForPc(pc, codePtr, lengthPtr)
}
codeEnd = (codeOffset + codeLen - 1);
- if ((unsigned int) (*srcDeltaNext) == (unsigned int) 0xFF) {
+ if ((unsigned) *srcDeltaNext == (unsigned) 0xFF) {
srcDeltaNext++;
delta = TclGetInt4AtPtr(srcDeltaNext);
srcDeltaNext += 4;
@@ -4951,7 +7901,7 @@ GetSrcInfoForPc(pc, codePtr, lengthPtr)
}
srcOffset += delta;
- if ((unsigned int) (*srcLengthNext) == (unsigned int) 0xFF) {
+ if ((unsigned) *srcLengthNext == (unsigned) 0xFF) {
srcLengthNext++;
srcLen = TclGetInt4AtPtr(srcLengthNext);
srcLengthNext += 4;
@@ -4959,11 +7909,13 @@ GetSrcInfoForPc(pc, codePtr, lengthPtr)
srcLen = TclGetInt1AtPtr(srcLengthNext);
srcLengthNext++;
}
-
- if (codeOffset > pcOffset) { /* best cmd already found */
+
+ if (codeOffset > pcOffset) { /* Best cmd already found */
break;
- } else if (pcOffset <= codeEnd) { /* this cmd's code encloses pc */
+ }
+ if (pcOffset <= codeEnd) { /* This cmd's code encloses pc */
int dist = (pcOffset - codeOffset);
+
if (dist <= bestDist) {
bestDist = dist;
bestSrcOffset = srcOffset;
@@ -4975,7 +7927,7 @@ GetSrcInfoForPc(pc, codePtr, lengthPtr)
if (bestDist == INT_MAX) {
return NULL;
}
-
+
if (lengthPtr != NULL) {
*lengthPtr = bestSrcLength;
}
@@ -4991,15 +7943,14 @@ GetSrcInfoForPc(pc, codePtr, lengthPtr)
* ExceptionRange.
*
* Results:
- * In the normal case, catchOnly is 0 (false) and this procedure
- * returns a pointer to the most closely enclosing ExceptionRange
- * structure regardless of whether it is a loop or catch exception
- * range. This is appropriate when processing a TCL_BREAK or
- * TCL_CONTINUE, which will be "handled" either by a loop exception
- * range or a closer catch range. If catchOnly is nonzero, this
- * procedure ignores loop exception ranges and returns a pointer to the
- * closest catch range. If no matching ExceptionRange is found that
- * encloses pc, a NULL is returned.
+ * In the normal case, catchOnly is 0 (false) and this procedure returns
+ * a pointer to the most closely enclosing ExceptionRange structure
+ * regardless of whether it is a loop or catch exception range. This is
+ * appropriate when processing a TCL_BREAK or TCL_CONTINUE, which will be
+ * "handled" either by a loop exception range or a closer catch range. If
+ * catchOnly is nonzero, this procedure ignores loop exception ranges and
+ * returns a pointer to the closest catch range. If no matching
+ * ExceptionRange is found that encloses pc, a NULL is returned.
*
* Side effects:
* None.
@@ -5008,33 +7959,32 @@ GetSrcInfoForPc(pc, codePtr, lengthPtr)
*/
static ExceptionRange *
-GetExceptRangeForPc(pc, catchOnly, codePtr)
- unsigned char *pc; /* The program counter value for which to
+GetExceptRangeForPc(
+ unsigned char *pc, /* The program counter value for which to
* search for a closest enclosing exception
* range. This points to a bytecode
* instruction in codePtr's code. */
- int catchOnly; /* If 0, consider either loop or catch
+ int catchOnly, /* If 0, consider either loop or catch
* ExceptionRanges in search. If nonzero
- * consider only catch ranges (and ignore
- * any closer loop ranges). */
- ByteCode* codePtr; /* Points to the ByteCode in which to search
+ * consider only catch ranges (and ignore any
+ * closer loop ranges). */
+ ByteCode *codePtr) /* Points to the ByteCode in which to search
* for the enclosing ExceptionRange. */
{
ExceptionRange *rangeArrayPtr;
int numRanges = codePtr->numExceptRanges;
register ExceptionRange *rangePtr;
- int pcOffset = (pc - codePtr->codeStart);
+ int pcOffset = pc - codePtr->codeStart;
register int start;
if (numRanges == 0) {
return NULL;
}
- /*
- * This exploits peculiarities of our compiler: nested ranges
- * are always *after* their containing ranges, so that by scanning
- * backwards we are sure that the first matching range is indeed
- * the deepest.
+ /*
+ * This exploits peculiarities of our compiler: nested ranges are always
+ * *after* their containing ranges, so that by scanning backwards we are
+ * sure that the first matching range is indeed the deepest.
*/
rangeArrayPtr = codePtr->exceptArrayPtr;
@@ -5042,7 +7992,7 @@ GetExceptRangeForPc(pc, catchOnly, codePtr)
while (--rangePtr >= rangeArrayPtr) {
start = rangePtr->codeOffset;
if ((start <= pcOffset) &&
- (pcOffset < (start + rangePtr->numCodeBytes))) {
+ (pcOffset < (start + rangePtr->numCodeBytes))) {
if ((!catchOnly)
|| (rangePtr->type == CATCH_EXCEPTION_RANGE)) {
return rangePtr;
@@ -5057,9 +8007,9 @@ GetExceptRangeForPc(pc, catchOnly, codePtr)
*
* GetOpcodeName --
*
- * This procedure is called by the TRACE and TRACE_WITH_OBJ macros
- * used in TclExecuteByteCode when debugging. It returns the name of
- * the bytecode instruction at a specified instruction pc.
+ * This procedure is called by the TRACE and TRACE_WITH_OBJ macros used
+ * in TclExecuteByteCode when debugging. It returns the name of the
+ * bytecode instruction at a specified instruction pc.
*
* Results:
* A character string for the instruction.
@@ -5072,12 +8022,12 @@ GetExceptRangeForPc(pc, catchOnly, codePtr)
#ifdef TCL_COMPILE_DEBUG
static char *
-GetOpcodeName(pc)
- unsigned char *pc; /* Points to the instruction whose name
- * should be returned. */
+GetOpcodeName(
+ unsigned char *pc) /* Points to the instruction whose name should
+ * be returned. */
{
unsigned char opCode = *pc;
-
+
return tclInstructionTable[opCode].name;
}
#endif /* TCL_COMPILE_DEBUG */
@@ -5085,988 +8035,10 @@ GetOpcodeName(pc)
/*
*----------------------------------------------------------------------
*
- * VerifyExprObjType --
- *
- * This procedure is called by the math functions to verify that
- * the object is either an int or double, coercing it if necessary.
- * If an error occurs during conversion, an error message is left
- * in the interpreter's result unless "interp" is NULL.
- *
- * Results:
- * TCL_OK if it was int or double, TCL_ERROR otherwise
- *
- * Side effects:
- * objPtr is ensured to be of tclIntType, tclWideIntType or
- * tclDoubleType.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-VerifyExprObjType(interp, objPtr)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- Tcl_Obj *objPtr; /* Points to the object to type check. */
-{
- if (IS_NUMERIC_TYPE(objPtr->typePtr)) {
- return TCL_OK;
- } else {
- int length, result = TCL_OK;
- char *s = Tcl_GetStringFromObj(objPtr, &length);
-
- if (TclLooksLikeInt(s, length)) {
- long i;
- Tcl_WideInt w;
- GET_WIDE_OR_INT(result, objPtr, i, w);
- } else {
- double d;
- result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, objPtr, &d);
- }
- if ((result != TCL_OK) && (interp != NULL)) {
- Tcl_ResetResult(interp);
- if (TclCheckBadOctal((Tcl_Interp *) NULL, s)) {
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "argument to math function was an invalid octal number",
- -1);
- } else {
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "argument to math function didn't have numeric value",
- -1);
- }
- }
- return result;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Math Functions --
- *
- * This page contains the procedures that implement all of the
- * built-in math functions for expressions.
- *
- * Results:
- * Each procedure returns TCL_OK if it succeeds and pushes an
- * Tcl object holding the result. If it fails it returns TCL_ERROR
- * and leaves an error message in the interpreter's result.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ExprUnaryFunc(interp, eePtr, clientData)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- ExecEnv *eePtr; /* Points to the environment for executing
- * the function. */
- ClientData clientData; /* Contains the address of a procedure that
- * takes one double argument and returns a
- * double result. */
-{
- Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */
- register int stackTop; /* Cached top index of evaluation stack. */
- register Tcl_Obj *valuePtr;
- double d, dResult;
- int result;
-
- double (*func) _ANSI_ARGS_((double)) =
- (double (*)_ANSI_ARGS_((double))) clientData;
-
- /*
- * Set stackPtr and stackTop from eePtr.
- */
-
- result = TCL_OK;
- CACHE_STACK_INFO();
-
- /*
- * Pop the function's argument from the evaluation stack. Convert it
- * to a double if necessary.
- */
-
- valuePtr = POP_OBJECT();
-
- if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
- result = TCL_ERROR;
- goto done;
- }
-
- GET_DOUBLE_VALUE(d, valuePtr, valuePtr->typePtr);
-
- errno = 0;
- dResult = (*func)(d);
- if ((errno != 0) || IS_NAN(dResult) || IS_INF(dResult)) {
- TclExprFloatError(interp, dResult);
- result = TCL_ERROR;
- goto done;
- }
-
- /*
- * Push a Tcl object holding the result.
- */
-
- PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
-
- /*
- * Reflect the change to stackTop back in eePtr.
- */
-
- done:
- TclDecrRefCount(valuePtr);
- DECACHE_STACK_INFO();
- return result;
-}
-
-static int
-ExprBinaryFunc(interp, eePtr, clientData)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- ExecEnv *eePtr; /* Points to the environment for executing
- * the function. */
- ClientData clientData; /* Contains the address of a procedure that
- * takes two double arguments and
- * returns a double result. */
-{
- Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */
- register int stackTop; /* Cached top index of evaluation stack. */
- register Tcl_Obj *valuePtr, *value2Ptr;
- double d1, d2, dResult;
- int result;
-
- double (*func) _ANSI_ARGS_((double, double))
- = (double (*)_ANSI_ARGS_((double, double))) clientData;
-
- /*
- * Set stackPtr and stackTop from eePtr.
- */
-
- result = TCL_OK;
- CACHE_STACK_INFO();
-
- /*
- * Pop the function's two arguments from the evaluation stack. Convert
- * them to doubles if necessary.
- */
-
- value2Ptr = POP_OBJECT();
- valuePtr = POP_OBJECT();
-
- if ((VerifyExprObjType(interp, valuePtr) != TCL_OK) ||
- (VerifyExprObjType(interp, value2Ptr) != TCL_OK)) {
- result = TCL_ERROR;
- goto done;
- }
-
- GET_DOUBLE_VALUE(d1, valuePtr, valuePtr->typePtr);
- GET_DOUBLE_VALUE(d2, value2Ptr, value2Ptr->typePtr);
-
- errno = 0;
- dResult = (*func)(d1, d2);
- if ((errno != 0) || IS_NAN(dResult) || IS_INF(dResult)) {
- TclExprFloatError(interp, dResult);
- result = TCL_ERROR;
- goto done;
- }
-
- /*
- * Push a Tcl object holding the result.
- */
-
- PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
-
- /*
- * Reflect the change to stackTop back in eePtr.
- */
-
- done:
- TclDecrRefCount(valuePtr);
- TclDecrRefCount(value2Ptr);
- DECACHE_STACK_INFO();
- return result;
-}
-
-static int
-ExprAbsFunc(interp, eePtr, clientData)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- ExecEnv *eePtr; /* Points to the environment for executing
- * the function. */
- ClientData clientData; /* Ignored. */
-{
- Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */
- register int stackTop; /* Cached top index of evaluation stack. */
- register Tcl_Obj *valuePtr;
- long i, iResult;
- double d, dResult;
- int result;
-
- /*
- * Set stackPtr and stackTop from eePtr.
- */
-
- result = TCL_OK;
- CACHE_STACK_INFO();
-
- /*
- * Pop the argument from the evaluation stack.
- */
-
- valuePtr = POP_OBJECT();
-
- if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
- result = TCL_ERROR;
- goto done;
- }
-
- /*
- * Push a Tcl object with the result.
- */
- if (valuePtr->typePtr == &tclIntType) {
- i = valuePtr->internalRep.longValue;
- if (i < 0) {
- if (i == LONG_MIN) {
-#ifdef TCL_WIDE_INT_IS_LONG
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "integer value too large to represent", -1));
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
- "integer value too large to represent", (char *) NULL);
- result = TCL_ERROR;
- goto done;
-#else
- /*
- * Special case: abs(MIN_INT) must promote to wide.
- */
-
- PUSH_OBJECT( Tcl_NewWideIntObj(-(Tcl_WideInt) i) );
- result = TCL_OK;
- goto done;
-#endif
-
- }
- iResult = -i;
- } else {
- iResult = i;
- }
- PUSH_OBJECT(Tcl_NewLongObj(iResult));
- } else if (valuePtr->typePtr == &tclWideIntType) {
- Tcl_WideInt wResult, w;
- TclGetWide(w,valuePtr);
- if (w < W0) {
- wResult = -w;
- if (wResult < 0) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "integer value too large to represent", -1);
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
- "integer value too large to represent", (char *) NULL);
- result = TCL_ERROR;
- goto done;
- }
- } else {
- wResult = w;
- }
- PUSH_OBJECT(Tcl_NewWideIntObj(wResult));
- } else {
- d = valuePtr->internalRep.doubleValue;
- if (d < 0.0) {
- dResult = -d;
- } else if (d == -0.0) {
- /* We need to distinguish here between positive 0.0 and
- * negative -0.0, see Bug ID #2954959.
- */
- static const double poszero = 0.0;
- if (memcmp(&d, &poszero, sizeof(double))) {
- dResult = -d;
- } else {
- dResult = d;
- }
- } else {
- dResult = d;
- }
- if (IS_NAN(dResult) || IS_INF(dResult)) {
- TclExprFloatError(interp, dResult);
- result = TCL_ERROR;
- goto done;
- }
- PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
- }
-
- /*
- * Reflect the change to stackTop back in eePtr.
- */
-
- done:
- TclDecrRefCount(valuePtr);
- DECACHE_STACK_INFO();
- return result;
-}
-
-static int
-ExprDoubleFunc(interp, eePtr, clientData)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- ExecEnv *eePtr; /* Points to the environment for executing
- * the function. */
- ClientData clientData; /* Ignored. */
-{
- Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */
- register int stackTop; /* Cached top index of evaluation stack. */
- register Tcl_Obj *valuePtr;
- double dResult;
- int result;
-
- /*
- * Set stackPtr and stackTop from eePtr.
- */
-
- result = TCL_OK;
- CACHE_STACK_INFO();
-
- /*
- * Pop the argument from the evaluation stack.
- */
-
- valuePtr = POP_OBJECT();
-
- if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
- result = TCL_ERROR;
- goto done;
- }
-
- GET_DOUBLE_VALUE(dResult, valuePtr, valuePtr->typePtr);
-
- /*
- * Push a Tcl object with the result.
- */
-
- PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
-
- /*
- * Reflect the change to stackTop back in eePtr.
- */
-
- done:
- TclDecrRefCount(valuePtr);
- DECACHE_STACK_INFO();
- return result;
-}
-
-static int
-ExprIntFunc(interp, eePtr, clientData)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- ExecEnv *eePtr; /* Points to the environment for executing
- * the function. */
- ClientData clientData; /* Ignored. */
-{
- Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */
- register int stackTop; /* Cached top index of evaluation stack. */
- register Tcl_Obj *valuePtr;
- long iResult;
- double d;
- int result;
-
- /*
- * Set stackPtr and stackTop from eePtr.
- */
-
- result = TCL_OK;
- CACHE_STACK_INFO();
-
- /*
- * Pop the argument from the evaluation stack.
- */
-
- valuePtr = POP_OBJECT();
-
- if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
- result = TCL_ERROR;
- goto done;
- }
-
- if (valuePtr->typePtr == &tclIntType) {
- iResult = valuePtr->internalRep.longValue;
- } else if (valuePtr->typePtr == &tclWideIntType) {
- TclGetLongFromWide(iResult,valuePtr);
- } else {
- d = valuePtr->internalRep.doubleValue;
- if (d < 0.0) {
- if (d < (double) (long) LONG_MIN) {
- tooLarge:
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "integer value too large to represent", -1);
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
- "integer value too large to represent", (char *) NULL);
- result = TCL_ERROR;
- goto done;
- }
- } else {
- if (d > (double) LONG_MAX) {
- goto tooLarge;
- }
- }
- if (IS_NAN(d) || IS_INF(d)) {
- TclExprFloatError(interp, d);
- result = TCL_ERROR;
- goto done;
- }
- iResult = (long) d;
- }
-
- /*
- * Push a Tcl object with the result.
- */
-
- PUSH_OBJECT(Tcl_NewLongObj(iResult));
-
- /*
- * Reflect the change to stackTop back in eePtr.
- */
-
- done:
- TclDecrRefCount(valuePtr);
- DECACHE_STACK_INFO();
- return result;
-}
-
-static int
-ExprWideFunc(interp, eePtr, clientData)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- ExecEnv *eePtr; /* Points to the environment for executing
- * the function. */
- ClientData clientData; /* Ignored. */
-{
- Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */
- register int stackTop; /* Cached top index of evaluation stack. */
- register Tcl_Obj *valuePtr;
- Tcl_WideInt wResult;
- double d;
- int result;
-
- /*
- * Set stackPtr and stackTop from eePtr.
- */
-
- result = TCL_OK;
- CACHE_STACK_INFO();
-
- /*
- * Pop the argument from the evaluation stack.
- */
-
- valuePtr = POP_OBJECT();
-
- if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
- result = TCL_ERROR;
- goto done;
- }
-
- if (valuePtr->typePtr == &tclWideIntType) {
- TclGetWide(wResult,valuePtr);
- } else if (valuePtr->typePtr == &tclIntType) {
- wResult = Tcl_LongAsWide(valuePtr->internalRep.longValue);
- } else {
- d = valuePtr->internalRep.doubleValue;
- if (d < 0.0) {
- if (d < Tcl_WideAsDouble(LLONG_MIN)) {
- tooLarge:
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "integer value too large to represent", -1);
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
- "integer value too large to represent", (char *) NULL);
- result = TCL_ERROR;
- goto done;
- }
- } else {
- if (d > Tcl_WideAsDouble(LLONG_MAX)) {
- goto tooLarge;
- }
- }
- if (IS_NAN(d) || IS_INF(d)) {
- TclExprFloatError(interp, d);
- result = TCL_ERROR;
- goto done;
- }
- wResult = Tcl_DoubleAsWide(d);
- }
-
- /*
- * Push a Tcl object with the result.
- */
-
- PUSH_OBJECT(Tcl_NewWideIntObj(wResult));
-
- /*
- * Reflect the change to stackTop back in eePtr.
- */
-
- done:
- TclDecrRefCount(valuePtr);
- DECACHE_STACK_INFO();
- return result;
-}
-
-static int
-ExprRandFunc(interp, eePtr, clientData)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- ExecEnv *eePtr; /* Points to the environment for executing
- * the function. */
- ClientData clientData; /* Ignored. */
-{
- Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */
- register int stackTop; /* Cached top index of evaluation stack. */
- Interp *iPtr = (Interp *) interp;
- double dResult;
- long tmp; /* Algorithm assumes at least 32 bits.
- * Only long guarantees that. See below. */
-
- if (!(iPtr->flags & RAND_SEED_INITIALIZED)) {
- iPtr->flags |= RAND_SEED_INITIALIZED;
-
- /*
- * Take into consideration the thread this interp is running in order
- * to insure different seeds in different threads (bug #416643)
- */
-
- iPtr->randSeed = TclpGetClicks() + ((long)Tcl_GetCurrentThread()<<12);
-
- /*
- * Make sure 1 <= randSeed <= (2^31) - 2. See below.
- */
-
- iPtr->randSeed &= (unsigned long) 0x7fffffff;
- if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) {
- iPtr->randSeed ^= 123459876;
- }
- }
-
- /*
- * Set stackPtr and stackTop from eePtr.
- */
-
- CACHE_STACK_INFO();
-
- /*
- * Generate the random number using the linear congruential
- * generator defined by the following recurrence:
- * seed = ( IA * seed ) mod IM
- * where IA is 16807 and IM is (2^31) - 1. The recurrence maps
- * a seed in the range [1, IM - 1] to a new seed in that same range.
- * The recurrence maps IM to 0, and maps 0 back to 0, so those two
- * values must not be allowed as initial values of seed.
- *
- * In order to avoid potential problems with integer overflow, the
- * recurrence is implemented in terms of additional constants
- * IQ and IR such that
- * IM = IA*IQ + IR
- * None of the operations in the implementation overflows a 32-bit
- * signed integer, and the C type long is guaranteed to be at least
- * 32 bits wide.
- *
- * For more details on how this algorithm works, refer to the following
- * papers:
- *
- * S.K. Park & K.W. Miller, "Random number generators: good ones
- * are hard to find," Comm ACM 31(10):1192-1201, Oct 1988
- *
- * W.H. Press & S.A. Teukolsky, "Portable random number
- * generators," Computers in Physics 6(5):522-524, Sep/Oct 1992.
- */
-
-#define RAND_IA 16807
-#define RAND_IM 2147483647
-#define RAND_IQ 127773
-#define RAND_IR 2836
-#define RAND_MASK 123459876
-
- tmp = iPtr->randSeed/RAND_IQ;
- iPtr->randSeed = RAND_IA*(iPtr->randSeed - tmp*RAND_IQ) - RAND_IR*tmp;
- if (iPtr->randSeed < 0) {
- iPtr->randSeed += RAND_IM;
- }
-
- /*
- * Since the recurrence keeps seed values in the range [1, RAND_IM - 1],
- * dividing by RAND_IM yields a double in the range (0, 1).
- */
-
- dResult = iPtr->randSeed * (1.0/RAND_IM);
-
- /*
- * Push a Tcl object with the result.
- */
-
- PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
-
- /*
- * Reflect the change to stackTop back in eePtr.
- */
-
- DECACHE_STACK_INFO();
- return TCL_OK;
-}
-
-static int
-ExprRoundFunc(interp, eePtr, clientData)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- ExecEnv *eePtr; /* Points to the environment for executing
- * the function. */
- ClientData clientData; /* Ignored. */
-{
- Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */
- register int stackTop; /* Cached top index of evaluation stack. */
- Tcl_Obj *valuePtr, *resPtr;
- double d, f, i;
- int result;
-
- /*
- * Set stackPtr and stackTop from eePtr.
- */
-
- result = TCL_OK;
- CACHE_STACK_INFO();
-
- /*
- * Pop the argument from the evaluation stack.
- */
-
- valuePtr = POP_OBJECT();
-
- if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
- result = TCL_ERROR;
- goto done;
- }
-
- if ((valuePtr->typePtr == &tclIntType) ||
- (valuePtr->typePtr == &tclWideIntType)) {
- result = TCL_OK;
- resPtr = valuePtr;
- } else {
-
- /*
- * Round the number to the nearest integer. I'd like to use round(),
- * but it's C99 (or BSD), and not yet universal.
- */
-
- d = valuePtr->internalRep.doubleValue;
- f = modf(d, &i);
- if (d < 0.0) {
- if (f <= -0.5) {
- i += -1.0;
- }
- if (i <= Tcl_WideAsDouble(LLONG_MIN)) {
- goto tooLarge;
- } else if (i <= (double) LONG_MIN) {
- resPtr = Tcl_NewWideIntObj(Tcl_DoubleAsWide(i));
- } else {
- resPtr = Tcl_NewLongObj((long) i);
- }
- } else {
- if (f >= 0.5) {
- i += 1.0;
- }
- if (i >= Tcl_WideAsDouble(LLONG_MAX)) {
- goto tooLarge;
- } else if (i >= (double) LONG_MAX) {
- resPtr = Tcl_NewWideIntObj(Tcl_DoubleAsWide(i));
- } else {
- resPtr = Tcl_NewLongObj((long) i);
- }
- }
- }
-
- /*
- * Push the result object and free the argument Tcl_Obj.
- */
-
- PUSH_OBJECT(resPtr);
-
- done:
- TclDecrRefCount(valuePtr);
- DECACHE_STACK_INFO();
- return result;
-
- /*
- * Error return: result cannot be represented as an integer.
- */
-
- tooLarge:
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "integer value too large to represent", -1);
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
- "integer value too large to represent",
- (char *) NULL);
- result = TCL_ERROR;
- goto done;
-}
-
-static int
-ExprSrandFunc(interp, eePtr, clientData)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- ExecEnv *eePtr; /* Points to the environment for executing
- * the function. */
- ClientData clientData; /* Ignored. */
-{
- Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */
- register int stackTop; /* Cached top index of evaluation stack. */
- Interp *iPtr = (Interp *) interp;
- Tcl_Obj *valuePtr;
- long i = 0; /* Initialized to avoid compiler warning. */
-
- /*
- * Set stackPtr and stackTop from eePtr.
- */
-
- CACHE_STACK_INFO();
-
- /*
- * Pop the argument from the evaluation stack. Use the value
- * to reset the random number seed.
- */
-
- valuePtr = POP_OBJECT();
-
- if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
- goto badValue;
- }
-
- if (Tcl_GetLongFromObj(NULL, valuePtr, &i) != TCL_OK) {
- Tcl_WideInt w;
-
- if (Tcl_GetWideIntFromObj(interp, valuePtr, &w) != TCL_OK) {
- badValue:
- Tcl_AddErrorInfo(interp, "\n (argument to \"srand()\")");
- TclDecrRefCount(valuePtr);
- DECACHE_STACK_INFO();
- return TCL_ERROR;
- }
-
- i = Tcl_WideAsLong(w);
- }
-
- /*
- * Reset the seed. Make sure 1 <= randSeed <= 2^31 - 2.
- * See comments in ExprRandFunc() for more details.
- */
-
- iPtr->flags |= RAND_SEED_INITIALIZED;
- iPtr->randSeed = i;
- iPtr->randSeed &= (unsigned long) 0x7fffffff;
- if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) {
- iPtr->randSeed ^= 123459876;
- }
-
- /*
- * To avoid duplicating the random number generation code we simply
- * clean up our state and call the real random number function. That
- * function will always succeed.
- */
-
- TclDecrRefCount(valuePtr);
- DECACHE_STACK_INFO();
-
- ExprRandFunc(interp, eePtr, clientData);
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ExprCallMathFunc --
- *
- * This procedure is invoked to call a non-builtin math function
- * during the execution of an expression.
- *
- * Results:
- * TCL_OK is returned if all went well and the function's value
- * was computed successfully. If an error occurred, TCL_ERROR
- * is returned and an error message is left in the interpreter's
- * result. After a successful return this procedure pushes a Tcl object
- * holding the result.
- *
- * Side effects:
- * None, unless the called math function has side effects.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ExprCallMathFunc(interp, eePtr, objc, objv)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- ExecEnv *eePtr; /* Points to the environment for executing
- * the function. */
- int objc; /* Number of arguments. The function name is
- * the 0-th argument. */
- Tcl_Obj **objv; /* The array of arguments. The function name
- * is objv[0]. */
-{
- Interp *iPtr = (Interp *) interp;
- Tcl_Obj **stackPtr; /* Cached evaluation stack base pointer. */
- register int stackTop; /* Cached top index of evaluation stack. */
- char *funcName;
- Tcl_HashEntry *hPtr;
- MathFunc *mathFuncPtr; /* Information about math function. */
- Tcl_Value args[MAX_MATH_ARGS]; /* Arguments for function call. */
- Tcl_Value funcResult; /* Result of function call as Tcl_Value. */
- register Tcl_Obj *valuePtr;
- long i;
- double d;
- int j, k, result;
-
- Tcl_ResetResult(interp);
-
- /*
- * Set stackPtr and stackTop from eePtr.
- */
-
- CACHE_STACK_INFO();
-
- /*
- * Look up the MathFunc record for the function.
- */
-
- funcName = TclGetString(objv[0]);
- hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, funcName);
- if (hPtr == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "unknown math function \"", funcName, "\"", (char *) NULL);
- result = TCL_ERROR;
- goto done;
- }
- mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
- if (mathFuncPtr->numArgs != (objc-1)) {
- panic("ExprCallMathFunc: expected number of args %d != actual number %d",
- mathFuncPtr->numArgs, objc);
- result = TCL_ERROR;
- goto done;
- }
-
- /*
- * Collect the arguments for the function, if there are any, into the
- * array "args". Note that args[0] will have the Tcl_Value that
- * corresponds to objv[1].
- */
-
- for (j = 1, k = 0; j < objc; j++, k++) {
- valuePtr = objv[j];
-
- if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
- result = TCL_ERROR;
- goto done;
- }
-
- /*
- * Copy the object's numeric value to the argument record,
- * converting it if necessary.
- */
-
- if (valuePtr->typePtr == &tclIntType) {
- i = valuePtr->internalRep.longValue;
- if (mathFuncPtr->argTypes[k] == TCL_DOUBLE) {
- args[k].type = TCL_DOUBLE;
- args[k].doubleValue = i;
- } else if (mathFuncPtr->argTypes[k] == TCL_WIDE_INT) {
- args[k].type = TCL_WIDE_INT;
- args[k].wideValue = Tcl_LongAsWide(i);
- } else {
- args[k].type = TCL_INT;
- args[k].intValue = i;
- }
- } else if (valuePtr->typePtr == &tclWideIntType) {
- Tcl_WideInt w;
- TclGetWide(w,valuePtr);
- if (mathFuncPtr->argTypes[k] == TCL_DOUBLE) {
- args[k].type = TCL_DOUBLE;
- args[k].doubleValue = Tcl_WideAsDouble(w);
- } else if (mathFuncPtr->argTypes[k] == TCL_INT) {
- args[k].type = TCL_INT;
- args[k].intValue = Tcl_WideAsLong(w);
- } else {
- args[k].type = TCL_WIDE_INT;
- args[k].wideValue = w;
- }
- } else {
- d = valuePtr->internalRep.doubleValue;
- if (mathFuncPtr->argTypes[k] == TCL_INT) {
- args[k].type = TCL_INT;
- args[k].intValue = (long) d;
- } else if (mathFuncPtr->argTypes[k] == TCL_WIDE_INT) {
- args[k].type = TCL_WIDE_INT;
- args[k].wideValue = Tcl_DoubleAsWide(d);
- } else {
- args[k].type = TCL_DOUBLE;
- args[k].doubleValue = d;
- }
- }
- }
-
- /*
- * Invoke the function and copy its result back into valuePtr.
- */
-
- result = (*mathFuncPtr->proc)(mathFuncPtr->clientData, interp, args,
- &funcResult);
- if (result != TCL_OK) {
- goto done;
- }
-
- /*
- * Pop the objc top stack elements and decrement their ref counts.
- */
-
- k = (stackTop - (objc-1));
- while (stackTop >= k) {
- valuePtr = POP_OBJECT();
- TclDecrRefCount(valuePtr);
- }
-
- /*
- * Push the call's object result.
- */
-
- if (funcResult.type == TCL_INT) {
- PUSH_OBJECT(Tcl_NewLongObj(funcResult.intValue));
- } else if (funcResult.type == TCL_WIDE_INT) {
- PUSH_OBJECT(Tcl_NewWideIntObj(funcResult.wideValue));
- } else {
- d = funcResult.doubleValue;
- if (IS_NAN(d) || IS_INF(d)) {
- TclExprFloatError(interp, d);
- result = TCL_ERROR;
- goto done;
- }
- PUSH_OBJECT(Tcl_NewDoubleObj(d));
- }
-
- /*
- * Reflect the change to stackTop back in eePtr.
- */
-
- done:
- DECACHE_STACK_INFO();
- return result;
-}
-
-/*
- *----------------------------------------------------------------------
- *
* TclExprFloatError --
*
- * This procedure is called when an error occurs during a
- * floating-point operation. It reads errno and sets
- * interp->objResultPtr accordingly.
+ * This procedure is called when an error occurs during a floating-point
+ * operation. It reads errno and sets interp->objResultPtr accordingly.
*
* Results:
* interp->objResultPtr is set to hold an error message.
@@ -6078,34 +8050,34 @@ ExprCallMathFunc(interp, eePtr, objc, objv)
*/
void
-TclExprFloatError(interp, value)
- Tcl_Interp *interp; /* Where to store error message. */
- double value; /* Value returned after error; used to
+TclExprFloatError(
+ Tcl_Interp *interp, /* Where to store error message. */
+ double value) /* Value returned after error; used to
* distinguish underflows from overflows. */
{
- char *s;
+ const char *s;
- Tcl_ResetResult(interp);
- if ((errno == EDOM) || IS_NAN(value)) {
+ if ((errno == EDOM) || TclIsNaN(value)) {
s = "domain error: argument not in valid range";
- Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1);
- Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", s, (char *) NULL);
- } else if ((errno == ERANGE) || IS_INF(value)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
+ Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", s, NULL);
+ } else if ((errno == ERANGE) || TclIsInfinite(value)) {
if (value == 0.0) {
s = "floating-point value too small to represent";
- Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1);
- Tcl_SetErrorCode(interp, "ARITH", "UNDERFLOW", s, (char *) NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
+ Tcl_SetErrorCode(interp, "ARITH", "UNDERFLOW", s, NULL);
} else {
s = "floating-point value too large to represent";
- Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1);
- Tcl_SetErrorCode(interp, "ARITH", "OVERFLOW", s, (char *) NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
+ Tcl_SetErrorCode(interp, "ARITH", "OVERFLOW", s, NULL);
}
} else {
- char msg[64 + TCL_INTEGER_SPACE];
-
- sprintf(msg, "unknown floating-point error, errno = %d", errno);
- Tcl_AppendToObj(Tcl_GetObjResult(interp), msg, -1);
- Tcl_SetErrorCode(interp, "ARITH", "UNKNOWN", msg, (char *) NULL);
+ Tcl_Obj *objPtr = Tcl_ObjPrintf(
+ "unknown floating-point error, errno = %d", errno);
+
+ Tcl_SetErrorCode(interp, "ARITH", "UNKNOWN",
+ Tcl_GetString(objPtr), NULL);
+ Tcl_SetObjResult(interp, objPtr);
}
}
@@ -6119,8 +8091,8 @@ TclExprFloatError(interp, value)
* the log base 2 of an integer.
*
* Results:
- * Returns the log base 2 of the operand. If the argument is less
- * than or equal to zero, a zero is returned.
+ * Returns the log base 2 of the operand. If the argument is less than or
+ * equal to zero, a zero is returned.
*
* Side effects:
* None.
@@ -6129,9 +8101,9 @@ TclExprFloatError(interp, value)
*/
int
-TclLog2(value)
- register int value; /* The integer for which to compute the
- * log base 2. */
+TclLog2(
+ register int value) /* The integer for which to compute the log
+ * base 2. */
{
register int n = value;
register int result = 0;
@@ -6161,15 +8133,15 @@ TclLog2(value)
*/
static int
-EvalStatsCmd(unused, interp, objc, objv)
- ClientData unused; /* Unused. */
- Tcl_Interp *interp; /* The current interpreter. */
- int objc; /* The number of arguments. */
- Tcl_Obj *CONST objv[]; /* The argument strings. */
+EvalStatsCmd(
+ ClientData unused, /* Unused. */
+ Tcl_Interp *interp, /* The current interpreter. */
+ int objc, /* The number of arguments. */
+ Tcl_Obj *const objv[]) /* The argument strings. */
{
Interp *iPtr = (Interp *) interp;
- LiteralTable *globalTablePtr = &(iPtr->literalTable);
- ByteCodeStats *statsPtr = &(iPtr->stats);
+ LiteralTable *globalTablePtr = &iPtr->literalTable;
+ ByteCodeStats *statsPtr = &iPtr->stats;
double totalCodeBytes, currentCodeBytes;
double totalLiteralBytes, currentLiteralBytes;
double objBytesIfUnshared, strBytesIfUnshared, sharingBytesSaved;
@@ -6181,12 +8153,18 @@ EvalStatsCmd(unused, interp, objc, objv)
int decadeHigh, minSizeDecade, maxSizeDecade, length, i;
char *litTableStats;
LiteralEntry *entryPtr;
+ Tcl_Obj *objPtr;
+
+#define Percent(a,b) ((a) * 100.0 / (b))
+
+ objPtr = Tcl_NewObj();
+ Tcl_IncrRefCount(objPtr);
numInstructions = 0.0;
for (i = 0; i < 256; i++) {
- if (statsPtr->instructionCount[i] != 0) {
- numInstructions += statsPtr->instructionCount[i];
- }
+ if (statsPtr->instructionCount[i] != 0) {
+ numInstructions += statsPtr->instructionCount[i];
+ }
}
totalLiteralBytes = sizeof(LiteralTable)
@@ -6199,7 +8177,7 @@ EvalStatsCmd(unused, interp, objc, objv)
numCurrentByteCodes =
statsPtr->numCompilations - statsPtr->numByteCodesFreed;
currentHeaderBytes = numCurrentByteCodes
- * (sizeof(ByteCode) - (sizeof(size_t) + sizeof(Tcl_Time)));
+ * (sizeof(ByteCode) - sizeof(size_t) - sizeof(Tcl_Time));
literalMgmtBytes = sizeof(LiteralTable)
+ (iPtr->literalTable.numBuckets * sizeof(LiteralEntry *))
+ (iPtr->literalTable.numEntries * sizeof(LiteralEntry));
@@ -6207,94 +8185,93 @@ EvalStatsCmd(unused, interp, objc, objv)
+ iPtr->literalTable.numEntries * sizeof(Tcl_Obj)
+ statsPtr->currentLitStringBytes;
currentCodeBytes = statsPtr->currentByteCodeBytes + currentLiteralBytes;
-
+
/*
* Summary statistics, total and current source and ByteCode sizes.
*/
- fprintf(stdout, "\n----------------------------------------------------------------\n");
- fprintf(stdout,
- "Compilation and execution statistics for interpreter 0x%x\n",
- (unsigned int) iPtr);
+ Tcl_AppendPrintfToObj(objPtr, "\n----------------------------------------------------------------\n");
+ Tcl_AppendPrintfToObj(objPtr,
+ "Compilation and execution statistics for interpreter %#lx\n",
+ iPtr);
- fprintf(stdout, "\nNumber ByteCodes executed %ld\n",
+ Tcl_AppendPrintfToObj(objPtr, "\nNumber ByteCodes executed %ld\n",
statsPtr->numExecutions);
- fprintf(stdout, "Number ByteCodes compiled %ld\n",
+ Tcl_AppendPrintfToObj(objPtr, "Number ByteCodes compiled %ld\n",
statsPtr->numCompilations);
- fprintf(stdout, " Mean executions/compile %.1f\n",
- ((float)statsPtr->numExecutions) / ((float)statsPtr->numCompilations));
-
- fprintf(stdout, "\nInstructions executed %.0f\n",
+ Tcl_AppendPrintfToObj(objPtr, " Mean executions/compile %.1f\n",
+ statsPtr->numExecutions / (float)statsPtr->numCompilations);
+
+ Tcl_AppendPrintfToObj(objPtr, "\nInstructions executed %.0f\n",
numInstructions);
- fprintf(stdout, " Mean inst/compile %.0f\n",
+ Tcl_AppendPrintfToObj(objPtr, " Mean inst/compile %.0f\n",
numInstructions / statsPtr->numCompilations);
- fprintf(stdout, " Mean inst/execution %.0f\n",
+ Tcl_AppendPrintfToObj(objPtr, " Mean inst/execution %.0f\n",
numInstructions / statsPtr->numExecutions);
- fprintf(stdout, "\nTotal ByteCodes %ld\n",
+ Tcl_AppendPrintfToObj(objPtr, "\nTotal ByteCodes %ld\n",
statsPtr->numCompilations);
- fprintf(stdout, " Source bytes %.6g\n",
+ Tcl_AppendPrintfToObj(objPtr, " Source bytes %.6g\n",
statsPtr->totalSrcBytes);
- fprintf(stdout, " Code bytes %.6g\n",
+ Tcl_AppendPrintfToObj(objPtr, " Code bytes %.6g\n",
totalCodeBytes);
- fprintf(stdout, " ByteCode bytes %.6g\n",
+ Tcl_AppendPrintfToObj(objPtr, " ByteCode bytes %.6g\n",
statsPtr->totalByteCodeBytes);
- fprintf(stdout, " Literal bytes %.6g\n",
+ Tcl_AppendPrintfToObj(objPtr, " Literal bytes %.6g\n",
totalLiteralBytes);
- fprintf(stdout, " table %u + bkts %lu + entries %lu + objects %lu + strings %.6g\n",
- (unsigned int)sizeof(LiteralTable),
- (unsigned long)iPtr->literalTable.numBuckets * sizeof(LiteralEntry *),
- (unsigned long)statsPtr->numLiteralsCreated * sizeof(LiteralEntry),
- (unsigned long)statsPtr->numLiteralsCreated * sizeof(Tcl_Obj),
+ Tcl_AppendPrintfToObj(objPtr, " table %lu + bkts %lu + entries %lu + objects %lu + strings %.6g\n",
+ (unsigned long) sizeof(LiteralTable),
+ (unsigned long) (iPtr->literalTable.numBuckets * sizeof(LiteralEntry *)),
+ (unsigned long) (statsPtr->numLiteralsCreated * sizeof(LiteralEntry)),
+ (unsigned long) (statsPtr->numLiteralsCreated * sizeof(Tcl_Obj)),
statsPtr->totalLitStringBytes);
- fprintf(stdout, " Mean code/compile %.1f\n",
+ Tcl_AppendPrintfToObj(objPtr, " Mean code/compile %.1f\n",
totalCodeBytes / statsPtr->numCompilations);
- fprintf(stdout, " Mean code/source %.1f\n",
+ Tcl_AppendPrintfToObj(objPtr, " Mean code/source %.1f\n",
totalCodeBytes / statsPtr->totalSrcBytes);
- fprintf(stdout, "\nCurrent (active) ByteCodes %ld\n",
+ Tcl_AppendPrintfToObj(objPtr, "\nCurrent (active) ByteCodes %ld\n",
numCurrentByteCodes);
- fprintf(stdout, " Source bytes %.6g\n",
+ Tcl_AppendPrintfToObj(objPtr, " Source bytes %.6g\n",
statsPtr->currentSrcBytes);
- fprintf(stdout, " Code bytes %.6g\n",
+ Tcl_AppendPrintfToObj(objPtr, " Code bytes %.6g\n",
currentCodeBytes);
- fprintf(stdout, " ByteCode bytes %.6g\n",
+ Tcl_AppendPrintfToObj(objPtr, " ByteCode bytes %.6g\n",
statsPtr->currentByteCodeBytes);
- fprintf(stdout, " Literal bytes %.6g\n",
+ Tcl_AppendPrintfToObj(objPtr, " Literal bytes %.6g\n",
currentLiteralBytes);
- fprintf(stdout, " table %u + bkts %lu + entries %lu + objects %lu + strings %.6g\n",
- (unsigned int)sizeof(LiteralTable),
- (unsigned long)iPtr->literalTable.numBuckets * sizeof(LiteralEntry *),
- (unsigned long)iPtr->literalTable.numEntries * sizeof(LiteralEntry),
- (unsigned long)iPtr->literalTable.numEntries * sizeof(Tcl_Obj),
+ Tcl_AppendPrintfToObj(objPtr, " table %lu + bkts %lu + entries %lu + objects %lu + strings %.6g\n",
+ (unsigned long) sizeof(LiteralTable),
+ (unsigned long) (iPtr->literalTable.numBuckets * sizeof(LiteralEntry *)),
+ (unsigned long) (iPtr->literalTable.numEntries * sizeof(LiteralEntry)),
+ (unsigned long) (iPtr->literalTable.numEntries * sizeof(Tcl_Obj)),
statsPtr->currentLitStringBytes);
- fprintf(stdout, " Mean code/source %.1f\n",
+ Tcl_AppendPrintfToObj(objPtr, " Mean code/source %.1f\n",
currentCodeBytes / statsPtr->currentSrcBytes);
- fprintf(stdout, " Code + source bytes %.6g (%0.1f mean code/src)\n",
+ Tcl_AppendPrintfToObj(objPtr, " Code + source bytes %.6g (%0.1f mean code/src)\n",
(currentCodeBytes + statsPtr->currentSrcBytes),
(currentCodeBytes / statsPtr->currentSrcBytes) + 1.0);
/*
* Tcl_IsShared statistics check
*
- * This gives the refcount of each obj as Tcl_IsShared was called
- * for it. Shared objects must be duplicated before they can be
- * modified.
+ * This gives the refcount of each obj as Tcl_IsShared was called for it.
+ * Shared objects must be duplicated before they can be modified.
*/
numSharedMultX = 0;
- fprintf(stdout, "\nTcl_IsShared object check (all objects):\n");
- fprintf(stdout, " Object had refcount <=1 (not shared) %ld\n",
+ Tcl_AppendPrintfToObj(objPtr, "\nTcl_IsShared object check (all objects):\n");
+ Tcl_AppendPrintfToObj(objPtr, " Object had refcount <=1 (not shared) %ld\n",
tclObjsShared[1]);
for (i = 2; i < TCL_MAX_SHARED_OBJ_STATS; i++) {
- fprintf(stdout, " refcount ==%d %ld\n",
+ Tcl_AppendPrintfToObj(objPtr, " refcount ==%d %ld\n",
i, tclObjsShared[i]);
numSharedMultX += tclObjsShared[i];
}
- fprintf(stdout, " refcount >=%d %ld\n",
+ Tcl_AppendPrintfToObj(objPtr, " refcount >=%d %ld\n",
i, tclObjsShared[0]);
numSharedMultX += tclObjsShared[0];
- fprintf(stdout, " Total shared objects %d\n",
+ Tcl_AppendPrintfToObj(objPtr, " Total shared objects %d\n",
numSharedMultX);
/*
@@ -6304,14 +8281,14 @@ EvalStatsCmd(unused, interp, objc, objv)
numByteCodeLits = 0;
refCountSum = 0;
numSharedMultX = 0;
- numSharedOnce = 0;
- objBytesIfUnshared = 0.0;
- strBytesIfUnshared = 0.0;
+ numSharedOnce = 0;
+ objBytesIfUnshared = 0.0;
+ strBytesIfUnshared = 0.0;
strBytesSharedMultX = 0.0;
- strBytesSharedOnce = 0.0;
+ strBytesSharedOnce = 0.0;
for (i = 0; i < globalTablePtr->numBuckets; i++) {
for (entryPtr = globalTablePtr->buckets[i]; entryPtr != NULL;
- entryPtr = entryPtr->nextPtr) {
+ entryPtr = entryPtr->nextPtr) {
if (entryPtr->objPtr->typePtr == &tclByteCodeType) {
numByteCodeLits++;
}
@@ -6331,213 +8308,230 @@ EvalStatsCmd(unused, interp, objc, objv)
sharingBytesSaved = (objBytesIfUnshared + strBytesIfUnshared)
- currentLiteralBytes;
- fprintf(stdout, "\nTotal objects (all interps) %ld\n",
+ Tcl_AppendPrintfToObj(objPtr, "\nTotal objects (all interps) %ld\n",
tclObjsAlloced);
- fprintf(stdout, "Current objects %ld\n",
+ Tcl_AppendPrintfToObj(objPtr, "Current objects %ld\n",
(tclObjsAlloced - tclObjsFreed));
- fprintf(stdout, "Total literal objects %ld\n",
+ Tcl_AppendPrintfToObj(objPtr, "Total literal objects %ld\n",
statsPtr->numLiteralsCreated);
- fprintf(stdout, "\nCurrent literal objects %d (%0.1f%% of current objects)\n",
+ Tcl_AppendPrintfToObj(objPtr, "\nCurrent literal objects %d (%0.1f%% of current objects)\n",
globalTablePtr->numEntries,
- (globalTablePtr->numEntries * 100.0) / (tclObjsAlloced-tclObjsFreed));
- fprintf(stdout, " ByteCode literals %ld (%0.1f%% of current literals)\n",
+ Percent(globalTablePtr->numEntries, tclObjsAlloced-tclObjsFreed));
+ Tcl_AppendPrintfToObj(objPtr, " ByteCode literals %ld (%0.1f%% of current literals)\n",
numByteCodeLits,
- (numByteCodeLits * 100.0) / globalTablePtr->numEntries);
- fprintf(stdout, " Literals reused > 1x %d\n",
+ Percent(numByteCodeLits, globalTablePtr->numEntries));
+ Tcl_AppendPrintfToObj(objPtr, " Literals reused > 1x %d\n",
numSharedMultX);
- fprintf(stdout, " Mean reference count %.2f\n",
+ Tcl_AppendPrintfToObj(objPtr, " Mean reference count %.2f\n",
((double) refCountSum) / globalTablePtr->numEntries);
- fprintf(stdout, " Mean len, str reused >1x %.2f\n",
- (numSharedMultX? (strBytesSharedMultX/numSharedMultX) : 0.0));
- fprintf(stdout, " Mean len, str used 1x %.2f\n",
- (numSharedOnce? (strBytesSharedOnce/numSharedOnce) : 0.0));
- fprintf(stdout, " Total sharing savings %.6g (%0.1f%% of bytes if no sharing)\n",
+ Tcl_AppendPrintfToObj(objPtr, " Mean len, str reused >1x %.2f\n",
+ (numSharedMultX ? strBytesSharedMultX/numSharedMultX : 0.0));
+ Tcl_AppendPrintfToObj(objPtr, " Mean len, str used 1x %.2f\n",
+ (numSharedOnce ? strBytesSharedOnce/numSharedOnce : 0.0));
+ Tcl_AppendPrintfToObj(objPtr, " Total sharing savings %.6g (%0.1f%% of bytes if no sharing)\n",
sharingBytesSaved,
- (sharingBytesSaved * 100.0) / (objBytesIfUnshared + strBytesIfUnshared));
- fprintf(stdout, " Bytes with sharing %.6g\n",
+ Percent(sharingBytesSaved, objBytesIfUnshared+strBytesIfUnshared));
+ Tcl_AppendPrintfToObj(objPtr, " Bytes with sharing %.6g\n",
currentLiteralBytes);
- fprintf(stdout, " table %u + bkts %lu + entries %lu + objects %lu + strings %.6g\n",
- (unsigned int)sizeof(LiteralTable),
- (unsigned long)iPtr->literalTable.numBuckets * sizeof(LiteralEntry *),
- (unsigned long)iPtr->literalTable.numEntries * sizeof(LiteralEntry),
- (unsigned long)iPtr->literalTable.numEntries * sizeof(Tcl_Obj),
+ Tcl_AppendPrintfToObj(objPtr, " table %lu + bkts %lu + entries %lu + objects %lu + strings %.6g\n",
+ (unsigned long) sizeof(LiteralTable),
+ (unsigned long) (iPtr->literalTable.numBuckets * sizeof(LiteralEntry *)),
+ (unsigned long) (iPtr->literalTable.numEntries * sizeof(LiteralEntry)),
+ (unsigned long) (iPtr->literalTable.numEntries * sizeof(Tcl_Obj)),
statsPtr->currentLitStringBytes);
- fprintf(stdout, " Bytes if no sharing %.6g = objects %.6g + strings %.6g\n",
+ Tcl_AppendPrintfToObj(objPtr, " Bytes if no sharing %.6g = objects %.6g + strings %.6g\n",
(objBytesIfUnshared + strBytesIfUnshared),
objBytesIfUnshared, strBytesIfUnshared);
- fprintf(stdout, " String sharing savings %.6g = unshared %.6g - shared %.6g\n",
+ Tcl_AppendPrintfToObj(objPtr, " String sharing savings %.6g = unshared %.6g - shared %.6g\n",
(strBytesIfUnshared - statsPtr->currentLitStringBytes),
strBytesIfUnshared, statsPtr->currentLitStringBytes);
- fprintf(stdout, " Literal mgmt overhead %ld (%0.1f%% of bytes with sharing)\n",
+ Tcl_AppendPrintfToObj(objPtr, " Literal mgmt overhead %ld (%0.1f%% of bytes with sharing)\n",
literalMgmtBytes,
- (literalMgmtBytes * 100.0) / currentLiteralBytes);
- fprintf(stdout, " table %u + buckets %lu + entries %lu\n",
- (unsigned int)sizeof(LiteralTable),
- (unsigned long)iPtr->literalTable.numBuckets * sizeof(LiteralEntry *),
- (unsigned long)iPtr->literalTable.numEntries * sizeof(LiteralEntry));
+ Percent(literalMgmtBytes, currentLiteralBytes));
+ Tcl_AppendPrintfToObj(objPtr, " table %lu + buckets %lu + entries %lu\n",
+ (unsigned long) sizeof(LiteralTable),
+ (unsigned long) (iPtr->literalTable.numBuckets * sizeof(LiteralEntry *)),
+ (unsigned long) (iPtr->literalTable.numEntries * sizeof(LiteralEntry)));
/*
* Breakdown of current ByteCode space requirements.
*/
-
- fprintf(stdout, "\nBreakdown of current ByteCode requirements:\n");
- fprintf(stdout, " Bytes Pct of Avg per\n");
- fprintf(stdout, " total ByteCode\n");
- fprintf(stdout, "Total %12.6g 100.00%% %8.1f\n",
+
+ Tcl_AppendPrintfToObj(objPtr, "\nBreakdown of current ByteCode requirements:\n");
+ Tcl_AppendPrintfToObj(objPtr, " Bytes Pct of Avg per\n");
+ Tcl_AppendPrintfToObj(objPtr, " total ByteCode\n");
+ Tcl_AppendPrintfToObj(objPtr, "Total %12.6g 100.00%% %8.1f\n",
statsPtr->currentByteCodeBytes,
statsPtr->currentByteCodeBytes / numCurrentByteCodes);
- fprintf(stdout, "Header %12.6g %8.1f%% %8.1f\n",
+ Tcl_AppendPrintfToObj(objPtr, "Header %12.6g %8.1f%% %8.1f\n",
currentHeaderBytes,
- ((currentHeaderBytes * 100.0) / statsPtr->currentByteCodeBytes),
+ Percent(currentHeaderBytes, statsPtr->currentByteCodeBytes),
currentHeaderBytes / numCurrentByteCodes);
- fprintf(stdout, "Instructions %12.6g %8.1f%% %8.1f\n",
+ Tcl_AppendPrintfToObj(objPtr, "Instructions %12.6g %8.1f%% %8.1f\n",
statsPtr->currentInstBytes,
- ((statsPtr->currentInstBytes * 100.0) / statsPtr->currentByteCodeBytes),
+ Percent(statsPtr->currentInstBytes,statsPtr->currentByteCodeBytes),
statsPtr->currentInstBytes / numCurrentByteCodes);
- fprintf(stdout, "Literal ptr array %12.6g %8.1f%% %8.1f\n",
+ Tcl_AppendPrintfToObj(objPtr, "Literal ptr array %12.6g %8.1f%% %8.1f\n",
statsPtr->currentLitBytes,
- ((statsPtr->currentLitBytes * 100.0) / statsPtr->currentByteCodeBytes),
+ Percent(statsPtr->currentLitBytes,statsPtr->currentByteCodeBytes),
statsPtr->currentLitBytes / numCurrentByteCodes);
- fprintf(stdout, "Exception table %12.6g %8.1f%% %8.1f\n",
+ Tcl_AppendPrintfToObj(objPtr, "Exception table %12.6g %8.1f%% %8.1f\n",
statsPtr->currentExceptBytes,
- ((statsPtr->currentExceptBytes * 100.0) / statsPtr->currentByteCodeBytes),
+ Percent(statsPtr->currentExceptBytes,statsPtr->currentByteCodeBytes),
statsPtr->currentExceptBytes / numCurrentByteCodes);
- fprintf(stdout, "Auxiliary data %12.6g %8.1f%% %8.1f\n",
+ Tcl_AppendPrintfToObj(objPtr, "Auxiliary data %12.6g %8.1f%% %8.1f\n",
statsPtr->currentAuxBytes,
- ((statsPtr->currentAuxBytes * 100.0) / statsPtr->currentByteCodeBytes),
+ Percent(statsPtr->currentAuxBytes,statsPtr->currentByteCodeBytes),
statsPtr->currentAuxBytes / numCurrentByteCodes);
- fprintf(stdout, "Command map %12.6g %8.1f%% %8.1f\n",
+ Tcl_AppendPrintfToObj(objPtr, "Command map %12.6g %8.1f%% %8.1f\n",
statsPtr->currentCmdMapBytes,
- ((statsPtr->currentCmdMapBytes * 100.0) / statsPtr->currentByteCodeBytes),
+ Percent(statsPtr->currentCmdMapBytes,statsPtr->currentByteCodeBytes),
statsPtr->currentCmdMapBytes / numCurrentByteCodes);
/*
* Detailed literal statistics.
*/
-
- fprintf(stdout, "\nLiteral string sizes:\n");
- fprintf(stdout, " Up to length Percentage\n");
+
+ Tcl_AppendPrintfToObj(objPtr, "\nLiteral string sizes:\n");
+ Tcl_AppendPrintfToObj(objPtr, " Up to length Percentage\n");
maxSizeDecade = 0;
for (i = 31; i >= 0; i--) {
- if (statsPtr->literalCount[i] > 0) {
- maxSizeDecade = i;
+ if (statsPtr->literalCount[i] > 0) {
+ maxSizeDecade = i;
break;
- }
+ }
}
sum = 0;
for (i = 0; i <= maxSizeDecade; i++) {
decadeHigh = (1 << (i+1)) - 1;
sum += statsPtr->literalCount[i];
- fprintf(stdout, " %10d %8.0f%%\n",
- decadeHigh, (sum * 100.0) / statsPtr->numLiteralsCreated);
+ Tcl_AppendPrintfToObj(objPtr, " %10d %8.0f%%\n",
+ decadeHigh, Percent(sum, statsPtr->numLiteralsCreated));
}
litTableStats = TclLiteralStats(globalTablePtr);
- fprintf(stdout, "\nCurrent literal table statistics:\n%s\n",
- litTableStats);
+ Tcl_AppendPrintfToObj(objPtr, "\nCurrent literal table statistics:\n%s\n",
+ litTableStats);
ckfree((char *) litTableStats);
/*
* Source and ByteCode size distributions.
*/
- fprintf(stdout, "\nSource sizes:\n");
- fprintf(stdout, " Up to size Percentage\n");
+ Tcl_AppendPrintfToObj(objPtr, "\nSource sizes:\n");
+ Tcl_AppendPrintfToObj(objPtr, " Up to size Percentage\n");
minSizeDecade = maxSizeDecade = 0;
for (i = 0; i < 31; i++) {
- if (statsPtr->srcCount[i] > 0) {
+ if (statsPtr->srcCount[i] > 0) {
minSizeDecade = i;
break;
- }
+ }
}
for (i = 31; i >= 0; i--) {
- if (statsPtr->srcCount[i] > 0) {
- maxSizeDecade = i;
+ if (statsPtr->srcCount[i] > 0) {
+ maxSizeDecade = i;
break;
- }
+ }
}
sum = 0;
for (i = minSizeDecade; i <= maxSizeDecade; i++) {
decadeHigh = (1 << (i+1)) - 1;
sum += statsPtr->srcCount[i];
- fprintf(stdout, " %10d %8.0f%%\n",
- decadeHigh, (sum * 100.0) / statsPtr->numCompilations);
+ Tcl_AppendPrintfToObj(objPtr, " %10d %8.0f%%\n",
+ decadeHigh, Percent(sum, statsPtr->numCompilations));
}
- fprintf(stdout, "\nByteCode sizes:\n");
- fprintf(stdout, " Up to size Percentage\n");
+ Tcl_AppendPrintfToObj(objPtr, "\nByteCode sizes:\n");
+ Tcl_AppendPrintfToObj(objPtr, " Up to size Percentage\n");
minSizeDecade = maxSizeDecade = 0;
for (i = 0; i < 31; i++) {
- if (statsPtr->byteCodeCount[i] > 0) {
+ if (statsPtr->byteCodeCount[i] > 0) {
minSizeDecade = i;
break;
- }
+ }
}
for (i = 31; i >= 0; i--) {
- if (statsPtr->byteCodeCount[i] > 0) {
- maxSizeDecade = i;
+ if (statsPtr->byteCodeCount[i] > 0) {
+ maxSizeDecade = i;
break;
- }
+ }
}
sum = 0;
for (i = minSizeDecade; i <= maxSizeDecade; i++) {
decadeHigh = (1 << (i+1)) - 1;
sum += statsPtr->byteCodeCount[i];
- fprintf(stdout, " %10d %8.0f%%\n",
- decadeHigh, (sum * 100.0) / statsPtr->numCompilations);
+ Tcl_AppendPrintfToObj(objPtr, " %10d %8.0f%%\n",
+ decadeHigh, Percent(sum, statsPtr->numCompilations));
}
- fprintf(stdout, "\nByteCode longevity (excludes Current ByteCodes):\n");
- fprintf(stdout, " Up to ms Percentage\n");
+ Tcl_AppendPrintfToObj(objPtr, "\nByteCode longevity (excludes Current ByteCodes):\n");
+ Tcl_AppendPrintfToObj(objPtr, " Up to ms Percentage\n");
minSizeDecade = maxSizeDecade = 0;
for (i = 0; i < 31; i++) {
- if (statsPtr->lifetimeCount[i] > 0) {
+ if (statsPtr->lifetimeCount[i] > 0) {
minSizeDecade = i;
break;
- }
+ }
}
for (i = 31; i >= 0; i--) {
- if (statsPtr->lifetimeCount[i] > 0) {
- maxSizeDecade = i;
+ if (statsPtr->lifetimeCount[i] > 0) {
+ maxSizeDecade = i;
break;
- }
+ }
}
sum = 0;
for (i = minSizeDecade; i <= maxSizeDecade; i++) {
decadeHigh = (1 << (i+1)) - 1;
sum += statsPtr->lifetimeCount[i];
- fprintf(stdout, " %12.3f %8.0f%%\n",
- decadeHigh / 1000.0,
- (sum * 100.0) / statsPtr->numByteCodesFreed);
+ Tcl_AppendPrintfToObj(objPtr, " %12.3f %8.0f%%\n",
+ decadeHigh/1000.0, Percent(sum, statsPtr->numByteCodesFreed));
}
/*
* Instruction counts.
*/
- fprintf(stdout, "\nInstruction counts:\n");
+ Tcl_AppendPrintfToObj(objPtr, "\nInstruction counts:\n");
for (i = 0; i <= LAST_INST_OPCODE; i++) {
- if (statsPtr->instructionCount[i]) {
- fprintf(stdout, "%20s %8ld %6.1f%%\n",
- tclInstructionTable[i].name,
- statsPtr->instructionCount[i],
- (statsPtr->instructionCount[i]*100.0) / numInstructions);
- }
- }
-
- fprintf(stdout, "\nInstructions NEVER executed:\n");
- for (i = 0; i <= LAST_INST_OPCODE; i++) {
- if (statsPtr->instructionCount[i] == 0) {
- fprintf(stdout, "%20s\n", tclInstructionTable[i].name);
- }
+ Tcl_AppendPrintfToObj(objPtr, "%20s %8ld ",
+ tclInstructionTable[i].name, statsPtr->instructionCount[i]);
+ if (statsPtr->instructionCount[i]) {
+ Tcl_AppendPrintfToObj(objPtr, "%6.1f%%\n",
+ Percent(statsPtr->instructionCount[i], numInstructions));
+ } else {
+ Tcl_AppendPrintfToObj(objPtr, "0\n");
+ }
}
#ifdef TCL_MEM_DEBUG
- fprintf(stdout, "\nHeap Statistics:\n");
- TclDumpMemoryInfo(stdout);
+ Tcl_AppendPrintfToObj(objPtr, "\nHeap Statistics:\n");
+ TclDumpMemoryInfo((ClientData) objPtr, 1);
#endif
- fprintf(stdout, "\n----------------------------------------------------------------\n");
+ Tcl_AppendPrintfToObj(objPtr, "\n----------------------------------------------------------------\n");
+
+ if (objc == 1) {
+ Tcl_SetObjResult(interp, objPtr);
+ } else {
+ Tcl_Channel outChan;
+ char *str = Tcl_GetStringFromObj(objv[1], &length);
+
+ if (length) {
+ if (strcmp(str, "stdout") == 0) {
+ outChan = Tcl_GetStdChannel(TCL_STDOUT);
+ } else if (strcmp(str, "stderr") == 0) {
+ outChan = Tcl_GetStdChannel(TCL_STDERR);
+ } else {
+ outChan = Tcl_OpenFileChannel(NULL, str, "w", 0664);
+ }
+ } else {
+ outChan = Tcl_GetStdChannel(TCL_STDOUT);
+ }
+ if (outChan != NULL) {
+ Tcl_WriteObj(outChan, objPtr);
+ }
+ }
+ Tcl_DecrRefCount(objPtr);
return TCL_OK;
}
#endif /* TCL_COMPILE_STATS */
@@ -6548,15 +8542,15 @@ EvalStatsCmd(unused, interp, objc, objv)
*
* StringForResultCode --
*
- * Procedure that returns a human-readable string representing a
- * Tcl result code such as TCL_ERROR.
+ * Procedure that returns a human-readable string representing a Tcl
+ * result code such as TCL_ERROR.
*
* Results:
- * If the result code is one of the standard Tcl return codes, the
- * result is a string representing that code such as "TCL_ERROR".
- * Otherwise, the result string is that code formatted as a
- * sequence of decimal digit characters. Note that the resulting
- * string must not be modified by the caller.
+ * If the result code is one of the standard Tcl return codes, the result
+ * is a string representing that code such as "TCL_ERROR". Otherwise, the
+ * result string is that code formatted as a sequence of decimal digit
+ * characters. Note that the resulting string must not be modified by the
+ * caller.
*
* Side effects:
* None.
@@ -6564,13 +8558,13 @@ EvalStatsCmd(unused, interp, objc, objv)
*----------------------------------------------------------------------
*/
-static char *
-StringForResultCode(result)
- int result; /* The Tcl result code for which to
- * generate a string. */
+static const char *
+StringForResultCode(
+ int result) /* The Tcl result code for which to generate a
+ * string. */
{
static char buf[TCL_INTEGER_SPACE];
-
+
if ((result >= TCL_OK) && (result <= TCL_CONTINUE)) {
return resultStrings[result];
}
@@ -6586,4 +8580,3 @@ StringForResultCode(result)
* fill-column: 78
* End:
*/
-
diff --git a/generic/tclFCmd.c b/generic/tclFCmd.c
index 5af8630..2b4977b 100644
--- a/generic/tclFCmd.c
+++ b/generic/tclFCmd.c
@@ -1,41 +1,39 @@
/*
* tclFCmd.c
*
- * This file implements the generic portion of file manipulation
- * subcommands of the "file" command.
+ * This file implements the generic portion of file manipulation
+ * subcommands of the "file" command.
*
* Copyright (c) 1996-1998 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
/*
- * Declarations for local procedures defined in this file:
+ * Declarations for local functions defined in this file:
*/
-static int CopyRenameOneFile _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr,
- int copyFlag, int force));
-static Tcl_Obj * FileBasename _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *pathPtr));
-static int FileCopyRename _ANSI_ARGS_((Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[], int copyFlag));
-static int FileForceOption _ANSI_ARGS_((Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[], int *forcePtr));
+static int CopyRenameOneFile(Tcl_Interp *interp,
+ Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr,
+ int copyFlag, int force);
+static Tcl_Obj * FileBasename(Tcl_Interp *interp, Tcl_Obj *pathPtr);
+static int FileCopyRename(Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[], int copyFlag);
+static int FileForceOption(Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[], int *forcePtr);
/*
*---------------------------------------------------------------------------
*
* TclFileRenameCmd
*
- * This procedure implements the "rename" subcommand of the "file"
- * command. Filename arguments need to be translated to native
- * format before being passed to platform-specific code that
- * implements rename functionality.
+ * This function implements the "rename" subcommand of the "file"
+ * command. Filename arguments need to be translated to native format
+ * before being passed to platform-specific code that implements rename
+ * functionality.
*
* Results:
* A standard Tcl result.
@@ -47,10 +45,11 @@ static int FileForceOption _ANSI_ARGS_((Tcl_Interp *interp,
*/
int
-TclFileRenameCmd(interp, objc, objv)
- Tcl_Interp *interp; /* Interp for error reporting. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument strings passed to Tcl_FileCmd. */
+TclFileRenameCmd(
+ Tcl_Interp *interp, /* Interp for error reporting or recursive
+ * calls in the case of a tricky rename. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument strings passed to Tcl_FileCmd. */
{
return FileCopyRename(interp, objc, objv, 0);
}
@@ -60,10 +59,9 @@ TclFileRenameCmd(interp, objc, objv)
*
* TclFileCopyCmd
*
- * This procedure implements the "copy" subcommand of the "file"
- * command. Filename arguments need to be translated to native
- * format before being passed to platform-specific code that
- * implements copy functionality.
+ * This function implements the "copy" subcommand of the "file" command.
+ * Filename arguments need to be translated to native format before being
+ * passed to platform-specific code that implements copy functionality.
*
* Results:
* A standard Tcl result.
@@ -75,10 +73,11 @@ TclFileRenameCmd(interp, objc, objv)
*/
int
-TclFileCopyCmd(interp, objc, objv)
- Tcl_Interp *interp; /* Used for error reporting */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument strings passed to Tcl_FileCmd. */
+TclFileCopyCmd(
+ Tcl_Interp *interp, /* Used for error reporting or recursive calls
+ * in the case of a tricky copy. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument strings passed to Tcl_FileCmd. */
{
return FileCopyRename(interp, objc, objv, 1);
}
@@ -88,8 +87,8 @@ TclFileCopyCmd(interp, objc, objv)
*
* FileCopyRename --
*
- * Performs the work of TclFileRenameCmd and TclFileCopyCmd.
- * See comments for those procedures.
+ * Performs the work of TclFileRenameCmd and TclFileCopyCmd. See
+ * comments for those functions.
*
* Results:
* See above.
@@ -101,15 +100,15 @@ TclFileCopyCmd(interp, objc, objv)
*/
static int
-FileCopyRename(interp, objc, objv, copyFlag)
- Tcl_Interp *interp; /* Used for error reporting. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument strings passed to Tcl_FileCmd. */
- int copyFlag; /* If non-zero, copy source(s). Otherwise,
+FileCopyRename(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[], /* Argument strings passed to Tcl_FileCmd. */
+ int copyFlag) /* If non-zero, copy source(s). Otherwise,
* rename them. */
{
int i, result, force;
- Tcl_StatBuf statBuf;
+ Tcl_StatBuf statBuf;
Tcl_Obj *target;
i = FileForceOption(interp, objc - 2, objv + 2, &force);
@@ -118,10 +117,9 @@ FileCopyRename(interp, objc, objv, copyFlag)
}
i += 2;
if ((objc - i) < 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " ", Tcl_GetString(objv[1]),
- " ?options? source ?source ...? target\"",
- (char *) NULL);
+ Tcl_AppendResult(interp, "wrong # args: should be \"",
+ TclGetString(objv[0]), " ", TclGetString(objv[1]),
+ " ?options? source ?source ...? target\"", NULL);
return TCL_ERROR;
}
@@ -149,15 +147,14 @@ FileCopyRename(interp, objc, objv, copyFlag)
errno = ENOTDIR;
Tcl_PosixError(interp);
Tcl_AppendResult(interp, "error ",
- ((copyFlag) ? "copying" : "renaming"), ": target \"",
- Tcl_GetString(target), "\" is not a directory",
- (char *) NULL);
+ (copyFlag ? "copying" : "renaming"), ": target \"",
+ TclGetString(target), "\" is not a directory", NULL);
result = TCL_ERROR;
} else {
/*
- * Even though already have target == translated(objv[i+1]),
- * pass the original argument down, so if there's an error, the
- * error message will reflect the original arguments.
+ * Even though already have target == translated(objv[i+1]), pass
+ * the original argument down, so if there's an error, the error
+ * message will reflect the original arguments.
*/
result = CopyRenameOneFile(interp, objv[i], objv[i + 1], copyFlag,
@@ -165,17 +162,17 @@ FileCopyRename(interp, objc, objv, copyFlag)
}
return result;
}
-
+
/*
- * Move each source file into target directory. Extract the basename
- * from each source, and append it to the end of the target path.
+ * Move each source file into target directory. Extract the basename from
+ * each source, and append it to the end of the target path.
*/
- for ( ; i < objc - 1; i++) {
+ for ( ; i<objc-1 ; i++) {
Tcl_Obj *jargv[2];
Tcl_Obj *source, *newFileName;
Tcl_Obj *temp;
-
+
source = FileBasename(interp, objv[i]);
if (source == NULL) {
result = TCL_ERROR;
@@ -204,10 +201,9 @@ FileCopyRename(interp, objc, objv, copyFlag)
*
* TclFileMakeDirsCmd
*
- * This procedure implements the "mkdir" subcommand of the "file"
- * command. Filename arguments need to be translated to native
- * format before being passed to platform-specific code that
- * implements mkdir functionality.
+ * This function implements the "mkdir" subcommand of the "file" command.
+ * Filename arguments need to be translated to native format before being
+ * passed to platform-specific code that implements mkdir functionality.
*
* Results:
* A standard Tcl result.
@@ -217,11 +213,12 @@ FileCopyRename(interp, objc, objv, copyFlag)
*
*----------------------------------------------------------------------
*/
+
int
-TclFileMakeDirsCmd(interp, objc, objv)
- Tcl_Interp *interp; /* Used for error reporting. */
- int objc; /* Number of arguments */
- Tcl_Obj *CONST objv[]; /* Argument strings passed to Tcl_FileCmd. */
+TclFileMakeDirsCmd(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ int objc, /* Number of arguments */
+ Tcl_Obj *CONST objv[]) /* Argument strings passed to Tcl_FileCmd. */
{
Tcl_Obj *errfile;
int result, i, j, pobjc;
@@ -239,6 +236,7 @@ TclFileMakeDirsCmd(interp, objc, objv)
}
split = Tcl_FSSplitPath(objv[i],&pobjc);
+ Tcl_IncrRefCount(split);
if (pobjc == 0) {
errno = ENOENT;
errfile = objv[i];
@@ -247,10 +245,10 @@ TclFileMakeDirsCmd(interp, objc, objv)
for (j = 0; j < pobjc; j++) {
target = Tcl_FSJoinPath(split, j + 1);
Tcl_IncrRefCount(target);
+
/*
- * Call Tcl_FSStat() so that if target is a symlink that
- * points to a directory we will create subdirectories in
- * that directory.
+ * Call Tcl_FSStat() so that if target is a symlink that points to
+ * a directory we will create subdirectories in that directory.
*/
if (Tcl_FSStat(target, &statBuf) == 0) {
@@ -261,25 +259,27 @@ TclFileMakeDirsCmd(interp, objc, objv)
}
} else if (errno != ENOENT) {
/*
- * If Tcl_FSStat() failed and the error is anything
- * other than non-existence of the target, throw the
- * error.
+ * If Tcl_FSStat() failed and the error is anything other than
+ * non-existence of the target, throw the error.
*/
+
errfile = target;
goto done;
} else if (Tcl_FSCreateDirectory(target) != TCL_OK) {
/*
* Create might have failed because of being in a race
- * condition with another process trying to create the
- * same subdirectory.
+ * condition with another process trying to create the same
+ * subdirectory.
*/
+
if (errno == EEXIST) {
if ((Tcl_FSStat(target, &statBuf) == 0)
&& S_ISDIR(statBuf.st_mode)) {
/*
- * It is a directory that wasn't there before,
- * so keep going without error.
+ * It is a directory that wasn't there before, so keep
+ * going without error.
*/
+
Tcl_ResetResult(interp);
} else {
errfile = target;
@@ -290,7 +290,11 @@ TclFileMakeDirsCmd(interp, objc, objv)
goto done;
}
}
- /* Forget about this sub-path */
+
+ /*
+ * Forget about this sub-path.
+ */
+
Tcl_DecrRefCount(target);
target = NULL;
}
@@ -298,11 +302,10 @@ TclFileMakeDirsCmd(interp, objc, objv)
split = NULL;
}
- done:
+ done:
if (errfile != NULL) {
Tcl_AppendResult(interp, "can't create directory \"",
- Tcl_GetString(errfile), "\": ", Tcl_PosixError(interp),
- (char *) NULL);
+ TclGetString(errfile), "\": ", Tcl_PosixError(interp), NULL);
result = TCL_ERROR;
}
if (split != NULL) {
@@ -319,8 +322,8 @@ TclFileMakeDirsCmd(interp, objc, objv)
*
* TclFileDeleteCmd
*
- * This procedure implements the "delete" subcommand of the "file"
- * command.
+ * This function implements the "delete" subcommand of the "file"
+ * command.
*
* Results:
* A standard Tcl result.
@@ -332,24 +335,24 @@ TclFileMakeDirsCmd(interp, objc, objv)
*/
int
-TclFileDeleteCmd(interp, objc, objv)
- Tcl_Interp *interp; /* Used for error reporting */
- int objc; /* Number of arguments */
- Tcl_Obj *CONST objv[]; /* Argument strings passed to Tcl_FileCmd. */
+TclFileDeleteCmd(
+ Tcl_Interp *interp, /* Used for error reporting */
+ int objc, /* Number of arguments */
+ Tcl_Obj *CONST objv[]) /* Argument strings passed to Tcl_FileCmd. */
{
int i, force, result;
Tcl_Obj *errfile;
Tcl_Obj *errorBuffer = NULL;
-
+
i = FileForceOption(interp, objc - 2, objv + 2, &force);
if (i < 0) {
return TCL_ERROR;
}
i += 2;
if ((objc - i) < 1) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tcl_GetString(objv[0]), " ", Tcl_GetString(objv[1]),
- " ?options? file ?file ...?\"", (char *) NULL);
+ Tcl_AppendResult(interp, "wrong # args: should be \"",
+ TclGetString(objv[0]), " ", TclGetString(objv[1]),
+ " ?options? file ?file ...?\"", NULL);
return TCL_ERROR;
}
@@ -371,34 +374,39 @@ TclFileDeleteCmd(interp, objc, objv)
if (Tcl_FSLstat(objv[i], &statBuf) != 0) {
/*
- * Trying to delete a file that does not exist is not
- * considered an error, just a no-op
+ * Trying to delete a file that does not exist is not considered
+ * an error, just a no-op
*/
if (errno != ENOENT) {
result = TCL_ERROR;
}
} else if (S_ISDIR(statBuf.st_mode)) {
- /*
- * We own a reference count on errorBuffer, if it was set
- * as a result of this call.
+ /*
+ * We own a reference count on errorBuffer, if it was set as a
+ * result of this call.
*/
+
result = Tcl_FSRemoveDirectory(objv[i], force, &errorBuffer);
if (result != TCL_OK) {
if ((force == 0) && (errno == EEXIST)) {
- Tcl_AppendResult(interp, "error deleting \"",
- Tcl_GetString(objv[i]),
- "\": directory not empty", (char *) NULL);
+ Tcl_AppendResult(interp, "error deleting \"",
+ TclGetString(objv[i]), "\": directory not empty",
+ NULL);
Tcl_PosixError(interp);
goto done;
}
- /*
+ /*
* If possible, use the untranslated name for the file.
*/
-
+
errfile = errorBuffer;
- /* FS supposed to check between translated objv and errfile */
+
+ /*
+ * FS supposed to check between translated objv and errfile.
+ */
+
if (Tcl_FSEqualPaths(objv[i], errfile)) {
errfile = objv[i];
}
@@ -406,32 +414,34 @@ TclFileDeleteCmd(interp, objc, objv)
} else {
result = Tcl_FSDeleteFile(objv[i]);
}
-
+
if (result != TCL_OK) {
result = TCL_ERROR;
- /*
- * It is important that we break on error, otherwise we
- * might end up owning reference counts on numerous
- * errorBuffers.
+
+ /*
+ * It is important that we break on error, otherwise we might end
+ * up owning reference counts on numerous errorBuffers.
*/
+
break;
}
}
if (result != TCL_OK) {
if (errfile == NULL) {
- /*
- * We try to accomodate poor error results from our
- * Tcl_FS calls
+ /*
+ * We try to accomodate poor error results from our Tcl_FS calls.
*/
- Tcl_AppendResult(interp, "error deleting unknown file: ",
- Tcl_PosixError(interp), (char *) NULL);
+
+ Tcl_AppendResult(interp, "error deleting unknown file: ",
+ Tcl_PosixError(interp), NULL);
} else {
- Tcl_AppendResult(interp, "error deleting \"",
- Tcl_GetString(errfile), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ Tcl_AppendResult(interp, "error deleting \"",
+ TclGetString(errfile), "\": ", Tcl_PosixError(interp),
+ NULL);
}
- }
- done:
+ }
+
+ done:
if (errorBuffer != NULL) {
Tcl_DecrRefCount(errorBuffer);
}
@@ -443,37 +453,37 @@ TclFileDeleteCmd(interp, objc, objv)
*
* CopyRenameOneFile
*
- * Copies or renames specified source file or directory hierarchy
- * to the specified target.
+ * Copies or renames specified source file or directory hierarchy to the
+ * specified target.
*
* Results:
* A standard Tcl result.
*
* Side effects:
- * Target is overwritten if the force flag is set. Attempting to
- * copy/rename a file onto a directory or a directory onto a file
- * will always result in an error.
+ * Target is overwritten if the force flag is set. Attempting to
+ * copy/rename a file onto a directory or a directory onto a file will
+ * always result in an error.
*
*----------------------------------------------------------------------
*/
static int
-CopyRenameOneFile(interp, source, target, copyFlag, force)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Obj *source; /* Pathname of file to copy. May need to
- * be translated. */
- Tcl_Obj *target; /* Pathname of file to create/overwrite.
- * May need to be translated. */
- int copyFlag; /* If non-zero, copy files. Otherwise,
- * rename them. */
- int force; /* If non-zero, overwrite target file if it
- * exists. Otherwise, error if target already
+CopyRenameOneFile(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *source, /* Pathname of file to copy. May need to be
+ * translated. */
+ Tcl_Obj *target, /* Pathname of file to create/overwrite. May
+ * need to be translated. */
+ int copyFlag, /* If non-zero, copy files. Otherwise, rename
+ * them. */
+ int force) /* If non-zero, overwrite target file if it
+ * exists. Otherwise, error if target already
* exists. */
{
int result;
Tcl_Obj *errfile, *errorBuffer;
- /* If source is a link, then this is the real file/directory */
- Tcl_Obj *actualSource = NULL;
+ Tcl_Obj *actualSource=NULL; /* If source is a link, then this is the real
+ * file/directory. */
Tcl_StatBuf sourceStatBuf, targetStatBuf;
if (Tcl_FSConvertToPathType(interp, source) != TCL_OK) {
@@ -482,16 +492,15 @@ CopyRenameOneFile(interp, source, target, copyFlag, force)
if (Tcl_FSConvertToPathType(interp, target) != TCL_OK) {
return TCL_ERROR;
}
-
+
errfile = NULL;
errorBuffer = NULL;
result = TCL_ERROR;
-
+
/*
- * We want to copy/rename links and not the files they point to, so we
- * use lstat(). If target is a link, we also want to replace the
- * link and not the file it points to, so we also use lstat() on the
- * target.
+ * We want to copy/rename links and not the files they point to, so we use
+ * lstat(). If target is a link, we also want to replace the link and not
+ * the file it points to, so we also use lstat() on the target.
*/
if (Tcl_FSLstat(source, &sourceStatBuf) != 0) {
@@ -510,44 +519,65 @@ CopyRenameOneFile(interp, source, target, copyFlag, force)
goto done;
}
- /*
- * Prevent copying or renaming a file onto itself. Under Windows,
- * stat always returns 0 for st_ino. However, the Windows-specific
- * code knows how to deal with copying or renaming a file on top of
- * itself. It might be a good idea to write a stat that worked.
- */
-
- if ((sourceStatBuf.st_ino != 0) && (targetStatBuf.st_ino != 0)) {
- if ((sourceStatBuf.st_ino == targetStatBuf.st_ino) &&
- (sourceStatBuf.st_dev == targetStatBuf.st_dev)) {
- result = TCL_OK;
- goto done;
- }
- }
+ /*
+ * Prevent copying or renaming a file onto itself. On Windows since
+ * 8.5 we do get an inode number, however the unsigned short field is
+ * insufficient to accept the Win32 API file id so it is truncated to
+ * 16 bits and we get collisions. See bug #2015723.
+ */
+
+#ifndef WIN32
+ if ((sourceStatBuf.st_ino != 0) && (targetStatBuf.st_ino != 0)) {
+ if ((sourceStatBuf.st_ino == targetStatBuf.st_ino) &&
+ (sourceStatBuf.st_dev == targetStatBuf.st_dev)) {
+ result = TCL_OK;
+ goto done;
+ }
+ }
+#endif
/*
- * Prevent copying/renaming a file onto a directory and
- * vice-versa. This is a policy decision based on the fact that
- * existing implementations of copy and rename on all platforms
- * also prevent this.
+ * Prevent copying/renaming a file onto a directory and vice-versa.
+ * This is a policy decision based on the fact that existing
+ * implementations of copy and rename on all platforms also prevent
+ * this.
*/
if (S_ISDIR(sourceStatBuf.st_mode)
- && !S_ISDIR(targetStatBuf.st_mode)) {
+ && !S_ISDIR(targetStatBuf.st_mode)) {
errno = EISDIR;
- Tcl_AppendResult(interp, "can't overwrite file \"",
- Tcl_GetString(target), "\" with directory \"",
- Tcl_GetString(source), "\"", (char *) NULL);
+ Tcl_AppendResult(interp, "can't overwrite file \"",
+ TclGetString(target), "\" with directory \"",
+ TclGetString(source), "\"", NULL);
goto done;
}
if (!S_ISDIR(sourceStatBuf.st_mode)
- && S_ISDIR(targetStatBuf.st_mode)) {
+ && S_ISDIR(targetStatBuf.st_mode)) {
errno = EISDIR;
- Tcl_AppendResult(interp, "can't overwrite directory \"",
- Tcl_GetString(target), "\" with file \"",
- Tcl_GetString(source), "\"", (char *) NULL);
+ Tcl_AppendResult(interp, "can't overwrite directory \"",
+ TclGetString(target), "\" with file \"",
+ TclGetString(source), "\"", NULL);
goto done;
}
+
+ /*
+ * The destination exists, but appears to be ok to over-write, and
+ * -force is given. We now try to adjust permissions to ensure the
+ * operation succeeds. If we can't adjust permissions, we'll let the
+ * actual copy/rename return an error later.
+ */
+
+ {
+ Tcl_Obj *perm;
+ int index;
+
+ TclNewLiteralStringObj(perm, "u+w");
+ Tcl_IncrRefCount(perm);
+ if (TclFSFileAttrIndex(target, "-permissions", &index) == TCL_OK) {
+ Tcl_FSFileAttrsSet(NULL, index, target, perm);
+ }
+ Tcl_DecrRefCount(perm);
+ }
}
if (copyFlag == 0) {
@@ -555,62 +585,95 @@ CopyRenameOneFile(interp, source, target, copyFlag, force)
if (result == TCL_OK) {
goto done;
}
-
+
if (errno == EINVAL) {
- Tcl_AppendResult(interp, "error renaming \"",
- Tcl_GetString(source), "\" to \"",
- Tcl_GetString(target), "\": trying to rename a volume or ",
- "move a directory into itself", (char *) NULL);
+ Tcl_AppendResult(interp, "error renaming \"",
+ TclGetString(source), "\" to \"", TclGetString(target),
+ "\": trying to rename a volume or "
+ "move a directory into itself", NULL);
goto done;
} else if (errno != EXDEV) {
errfile = target;
goto done;
}
-
+
/*
- * The rename failed because the move was across file systems.
- * Fall through to copy file and then remove original. Note that
- * the low-level Tcl_FSRenameFileProc in the filesystem is allowed
- * to implement cross-filesystem moves itself, if it desires.
+ * The rename failed because the move was across file systems. Fall
+ * through to copy file and then remove original. Note that the
+ * low-level Tcl_FSRenameFileProc in the filesystem is allowed to
+ * implement cross-filesystem moves itself, if it desires.
*/
}
actualSource = source;
Tcl_IncrRefCount(actualSource);
+
+ /*
+ * Activate the following block to copy files instead of links. However
+ * Tcl's semantics currently say we should copy links, so any such change
+ * should be the subject of careful study on the consequences.
+ *
+ * Perhaps there could be an optional flag to 'file copy' to dictate which
+ * approach to use, with the default being _not_ to have this block
+ * active.
+ */
+
#if 0
#ifdef S_ISLNK
- /*
- * To add a flag to make 'copy' copy links instead of files, we could
- * add a condition to ignore this 'if' here.
- */
if (copyFlag && S_ISLNK(sourceStatBuf.st_mode)) {
- /*
- * We want to copy files not links. Therefore we must follow the
- * link. There are two purposes to this 'stat' call here. First
- * we want to know if the linked-file/dir actually exists, and
- * second, in the block of code which follows, some 20 lines
- * down, we want to check if the thing is a file or directory.
+ /*
+ * We want to copy files not links. Therefore we must follow the link.
+ * There are two purposes to this 'stat' call here. First we want to
+ * know if the linked-file/dir actually exists, and second, in the
+ * block of code which follows, some 20 lines down, we want to check
+ * if the thing is a file or directory.
*/
+
if (Tcl_FSStat(source, &sourceStatBuf) != 0) {
- /* Actual file doesn't exist */
- Tcl_AppendResult(interp,
- "error copying \"", Tcl_GetString(source),
- "\": the target of this link doesn't exist",
- (char *) NULL);
+ /*
+ * Actual file doesn't exist.
+ */
+
+ Tcl_AppendResult(interp, "error copying \"", TclGetString(source),
+ "\": the target of this link doesn't exist", NULL);
goto done;
} else {
int counter = 0;
+
while (1) {
Tcl_Obj *path = Tcl_FSLink(actualSource, NULL, 0);
if (path == NULL) {
break;
}
+
+ /*
+ * Now we want to check if this is a relative path, and if so,
+ * to make it absolute.
+ */
+
+ if (Tcl_FSGetPathType(path) == TCL_PATH_RELATIVE) {
+ Tcl_Obj *abs = Tcl_FSJoinToPath(actualSource, 1, &path);
+
+ if (abs == NULL) {
+ break;
+ }
+ Tcl_IncrRefCount(abs);
+ Tcl_DecrRefCount(path);
+ path = abs;
+ }
Tcl_DecrRefCount(actualSource);
actualSource = path;
counter++;
- /* Arbitrary limit of 20 links to follow */
+
+ /*
+ * Arbitrary limit of 20 links to follow.
+ */
+
if (counter > 20) {
- /* Too many links */
+ /*
+ * Too many links.
+ */
+
Tcl_SetErrno(EMLINK);
errfile = source;
goto done;
@@ -619,47 +682,43 @@ CopyRenameOneFile(interp, source, target, copyFlag, force)
/* Now 'actualSource' is the correct file */
}
}
-#endif
+#endif /* S_ISLNK */
#endif
if (S_ISDIR(sourceStatBuf.st_mode)) {
result = Tcl_FSCopyDirectory(actualSource, target, &errorBuffer);
if (result != TCL_OK) {
if (errno == EXDEV) {
- /*
+ /*
* The copy failed because we're trying to do a
- * cross-filesystem copy. We do this through our Tcl
- * library.
+ * cross-filesystem copy. We do this through our Tcl library.
*/
- Tcl_SavedResult savedResult;
- Tcl_Obj *copyCommand = Tcl_NewListObj(0,NULL);
- Tcl_IncrRefCount(copyCommand);
- Tcl_ListObjAppendElement(interp, copyCommand,
- Tcl_NewStringObj("::tcl::CopyDirectory",-1));
+
+ Tcl_Obj *copyCommand, *cmdObj, *opObj;
+
+ TclNewObj(copyCommand);
+ TclNewLiteralStringObj(cmdObj, "::tcl::CopyDirectory");
+ Tcl_ListObjAppendElement(interp, copyCommand, cmdObj);
if (copyFlag) {
- Tcl_ListObjAppendElement(interp, copyCommand,
- Tcl_NewStringObj("copying",-1));
+ TclNewLiteralStringObj(opObj, "copying");
} else {
- Tcl_ListObjAppendElement(interp, copyCommand,
- Tcl_NewStringObj("renaming",-1));
+ TclNewLiteralStringObj(opObj, "renaming");
}
+ Tcl_ListObjAppendElement(interp, copyCommand, opObj);
Tcl_ListObjAppendElement(interp, copyCommand, source);
Tcl_ListObjAppendElement(interp, copyCommand, target);
- Tcl_SaveResult(interp, &savedResult);
- result = Tcl_EvalObjEx(interp, copyCommand,
- TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT);
+ Tcl_IncrRefCount(copyCommand);
+ result = Tcl_EvalObjEx(interp, copyCommand,
+ TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT);
Tcl_DecrRefCount(copyCommand);
if (result != TCL_OK) {
- /*
- * There was an error in the Tcl-level copy.
- * We will pass on the Tcl error message and
- * can ensure this by setting errfile to NULL
+ /*
+ * There was an error in the Tcl-level copy. We will pass
+ * on the Tcl error message and can ensure this by setting
+ * errfile to NULL
*/
- Tcl_DiscardResult(&savedResult);
+
errfile = NULL;
- } else {
- /* The copy was successful */
- Tcl_RestoreResult(interp, &savedResult);
}
} else {
errfile = errorBuffer;
@@ -676,19 +735,22 @@ CopyRenameOneFile(interp, source, target, copyFlag, force)
result = TclCrossFilesystemCopy(interp, source, target);
}
if (result != TCL_OK) {
- /*
- * We could examine 'errno' to double-check if the problem
- * was with the target, but we checked the source above,
- * so it should be quite clear
+ /*
+ * We could examine 'errno' to double-check if the problem was
+ * with the target, but we checked the source above, so it should
+ * be quite clear
*/
+
errfile = target;
- /*
- * We now need to reset the result, because the above call,
- * if it failed, may have put an error message in place.
- * (Ideally we would prefer not to pass an interpreter in
- * above, but the channel IO code used by
- * TclCrossFilesystemCopy currently requires one)
+
+ /*
+ * We now need to reset the result, because the above call, if it
+ * failed, may have put an error message in place. (Ideally we
+ * would prefer not to pass an interpreter in above, but the
+ * channel IO code used by TclCrossFilesystemCopy currently
+ * requires one).
*/
+
Tcl_ResetResult(interp);
}
}
@@ -707,31 +769,26 @@ CopyRenameOneFile(interp, source, target, copyFlag, force)
}
}
if (result != TCL_OK) {
- Tcl_AppendResult(interp, "can't unlink \"",
- Tcl_GetString(errfile), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ Tcl_AppendResult(interp, "can't unlink \"", TclGetString(errfile),
+ "\": ", Tcl_PosixError(interp), NULL);
errfile = NULL;
}
}
-
- done:
+
+ done:
if (errfile != NULL) {
- Tcl_AppendResult(interp,
- ((copyFlag) ? "error copying \"" : "error renaming \""),
- Tcl_GetString(source), (char *) NULL);
+ Tcl_AppendResult(interp, "error ", (copyFlag ? "copying" : "renaming"),
+ " \"", TclGetString(source), NULL);
if (errfile != source) {
- Tcl_AppendResult(interp, "\" to \"", Tcl_GetString(target),
- (char *) NULL);
+ Tcl_AppendResult(interp, "\" to \"", TclGetString(target), NULL);
if (errfile != target) {
- Tcl_AppendResult(interp, "\": \"", Tcl_GetString(errfile),
- (char *) NULL);
+ Tcl_AppendResult(interp, "\": \"", TclGetString(errfile),NULL);
}
}
- Tcl_AppendResult(interp, "\": ", Tcl_PosixError(interp),
- (char *) NULL);
+ Tcl_AppendResult(interp, "\": ", Tcl_PosixError(interp), NULL);
}
if (errorBuffer != NULL) {
- Tcl_DecrRefCount(errorBuffer);
+ Tcl_DecrRefCount(errorBuffer);
}
if (actualSource != NULL) {
Tcl_DecrRefCount(actualSource);
@@ -744,14 +801,13 @@ CopyRenameOneFile(interp, source, target, copyFlag, force)
*
* FileForceOption --
*
- * Helps parse command line options for file commands that take
- * the "-force" and "--" options.
+ * Helps parse command line options for file commands that take the
+ * "-force" and "--" options.
*
* Results:
- * The return value is how many arguments from argv were consumed
- * by this function, or -1 if there was an error parsing the
- * options. If an error occurred, an error message is left in the
- * interp's result.
+ * The return value is how many arguments from argv were consumed by this
+ * function, or -1 if there was an error parsing the options. If an error
+ * occurred, an error message is left in the interp's result.
*
* Side effects:
* None.
@@ -760,29 +816,29 @@ CopyRenameOneFile(interp, source, target, copyFlag, force)
*/
static int
-FileForceOption(interp, objc, objv, forcePtr)
- Tcl_Interp *interp; /* Interp, for error return. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument strings. First command line
+FileForceOption(
+ Tcl_Interp *interp, /* Interp, for error return. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[], /* Argument strings. First command line
* option, if it exists, begins at 0. */
- int *forcePtr; /* If the "-force" was specified, *forcePtr
- * is filled with 1, otherwise with 0. */
+ int *forcePtr) /* If the "-force" was specified, *forcePtr is
+ * filled with 1, otherwise with 0. */
{
int force, i;
-
+
force = 0;
for (i = 0; i < objc; i++) {
- if (Tcl_GetString(objv[i])[0] != '-') {
+ if (TclGetString(objv[i])[0] != '-') {
break;
}
- if (strcmp(Tcl_GetString(objv[i]), "-force") == 0) {
+ if (strcmp(TclGetString(objv[i]), "-force") == 0) {
force = 1;
- } else if (strcmp(Tcl_GetString(objv[i]), "--") == 0) {
+ } else if (strcmp(TclGetString(objv[i]), "--") == 0) {
i++;
break;
} else {
- Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[i]),
- "\": should be -force or --", (char *)NULL);
+ Tcl_AppendResult(interp, "bad option \"", TclGetString(objv[i]),
+ "\": should be -force or --", NULL);
return -1;
}
}
@@ -796,13 +852,12 @@ FileForceOption(interp, objc, objv, forcePtr)
*
* Given a path in either tcl format (with / separators), or in the
* platform-specific format for the current platform, return all the
- * characters in the path after the last directory separator. But,
- * if path is the root directory, returns no characters.
+ * characters in the path after the last directory separator. But, if
+ * path is the root directory, returns no characters.
*
* Results:
- * Returns the string object that represents the basename. If there
- * is an error, an error message is left in interp, and NULL is
- * returned.
+ * Returns the string object that represents the basename. If there is an
+ * error, an error message is left in interp, and NULL is returned.
*
* Side effects:
* None.
@@ -811,23 +866,25 @@ FileForceOption(interp, objc, objv, forcePtr)
*/
static Tcl_Obj *
-FileBasename(interp, pathPtr)
- Tcl_Interp *interp; /* Interp, for error return. */
- Tcl_Obj *pathPtr; /* Path whose basename to extract. */
+FileBasename(
+ Tcl_Interp *interp, /* Interp, for error return. */
+ Tcl_Obj *pathPtr) /* Path whose basename to extract. */
{
int objc;
Tcl_Obj *splitPtr;
Tcl_Obj *resultPtr = NULL;
-
+
splitPtr = Tcl_FSSplitPath(pathPtr, &objc);
+ Tcl_IncrRefCount(splitPtr);
if (objc != 0) {
- if ((objc == 1) && (*Tcl_GetString(pathPtr) == '~')) {
+ if ((objc == 1) && (*TclGetString(pathPtr) == '~')) {
Tcl_DecrRefCount(splitPtr);
if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) {
return NULL;
}
splitPtr = Tcl_FSSplitPath(pathPtr, &objc);
+ Tcl_IncrRefCount(splitPtr);
}
/*
@@ -838,7 +895,7 @@ FileBasename(interp, pathPtr)
if (objc > 0) {
Tcl_ListObjIndex(NULL, splitPtr, objc-1, &resultPtr);
if ((objc == 1) &&
- (Tcl_FSGetPathType(resultPtr) != TCL_PATH_RELATIVE)) {
+ (Tcl_FSGetPathType(resultPtr) != TCL_PATH_RELATIVE)) {
resultPtr = NULL;
}
}
@@ -856,48 +913,46 @@ FileBasename(interp, pathPtr)
*
* TclFileAttrsCmd --
*
- * Sets or gets the platform-specific attributes of a file. The
- * objc-objv points to the file name with the rest of the command
- * line following. This routine uses platform-specific tables of
- * option strings and callbacks. The callback to get the
- * attributes take three parameters:
- * Tcl_Interp *interp; The interp to report errors with.
- * Since this is an object-based API,
- * the object form of the result should
- * be used.
+ * Sets or gets the platform-specific attributes of a file. The objc-objv
+ * points to the file name with the rest of the command line following.
+ * This routine uses platform-specific tables of option strings and
+ * callbacks. The callback to get the attributes take three parameters:
+ * Tcl_Interp *interp; The interp to report errors with. Since
+ * this is an object-based API, the object
+ * form of the result should be used.
* CONST char *fileName; This is extracted using
* Tcl_TranslateFileName.
- * TclObj **attrObjPtrPtr; A new object to hold the attribute
- * is allocated and put here.
+ * TclObj **attrObjPtrPtr; A new object to hold the attribute is
+ * allocated and put here.
* The first two parameters of the callback used to write out the
* attributes are the same. The third parameter is:
- * CONST *attrObjPtr; A pointer to the object that has
- * the new attribute.
- * They both return standard TCL errors; if the routine to get
- * an attribute fails, no object is allocated and *attrObjPtrPtr
- * is unchanged.
+ * CONST *attrObjPtr; A pointer to the object that has the new
+ * attribute.
+ * They both return standard TCL errors; if the routine to get an
+ * attribute fails, no object is allocated and *attrObjPtrPtr is
+ * unchanged.
*
* Results:
- * Standard TCL error.
+ * Standard TCL error.
*
* Side effects:
- * May set file attributes for the file name.
- *
+ * May set file attributes for the file name.
+ *
*----------------------------------------------------------------------
*/
int
-TclFileAttrsCmd(interp, objc, objv)
- Tcl_Interp *interp; /* The interpreter for error reporting. */
- int objc; /* Number of command line arguments. */
- Tcl_Obj *CONST objv[]; /* The command line objects. */
+TclFileAttrsCmd(
+ Tcl_Interp *interp, /* The interpreter for error reporting. */
+ int objc, /* Number of command line arguments. */
+ Tcl_Obj *CONST objv[]) /* The command line objects. */
{
int result;
CONST char ** attributeStrings;
Tcl_Obj* objStrings = NULL;
- int numObjStrings = -1;
+ int numObjStrings = -1, didAlloc = 0;
Tcl_Obj *filePtr;
-
+
if (objc < 3) {
Tcl_WrongNumArgs(interp, 2, objv,
"name ?option? ?value? ?option value ...?");
@@ -908,64 +963,95 @@ TclFileAttrsCmd(interp, objc, objv)
if (Tcl_FSConvertToPathType(interp, filePtr) != TCL_OK) {
return TCL_ERROR;
}
-
+
objc -= 3;
objv += 3;
result = TCL_ERROR;
Tcl_SetErrno(0);
+
attributeStrings = Tcl_FSFileAttrStrings(filePtr, &objStrings);
if (attributeStrings == NULL) {
int index;
Tcl_Obj *objPtr;
+
if (objStrings == NULL) {
if (Tcl_GetErrno() != 0) {
- /*
- * There was an error, probably that the filePtr is
- * not accepted by any filesystem
+ /*
+ * There was an error, probably that the filePtr is not
+ * accepted by any filesystem
*/
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "could not read \"", Tcl_GetString(filePtr),
- "\": ", Tcl_PosixError(interp),
- (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "could not read \"",
+ TclGetString(filePtr), "\": ", Tcl_PosixError(interp),
+ NULL);
}
- goto end;
+ return TCL_ERROR;
}
- /* We own the object now */
+
+ /*
+ * We own the object now.
+ */
+
Tcl_IncrRefCount(objStrings);
- /* Use objStrings as a list object */
+
+ /*
+ * Use objStrings as a list object.
+ */
+
if (Tcl_ListObjLength(interp, objStrings, &numObjStrings) != TCL_OK) {
goto end;
}
- attributeStrings = (CONST char **)
- ckalloc ((1+numObjStrings) * sizeof(char*));
+ attributeStrings = (CONST char **) TclStackAlloc(interp,
+ (1+numObjStrings) * sizeof(char*));
+ didAlloc = 1;
for (index = 0; index < numObjStrings; index++) {
Tcl_ListObjIndex(interp, objStrings, index, &objPtr);
- attributeStrings[index] = Tcl_GetString(objPtr);
+ attributeStrings[index] = TclGetString(objPtr);
}
attributeStrings[index] = NULL;
+ } else if (objStrings != NULL) {
+ Tcl_Panic("must not update objPtrRef's variable and return non-NULL");
}
+
if (objc == 0) {
/*
* Get all attributes.
*/
- int index;
+ int index, res = TCL_OK, nbAtts = 0;
Tcl_Obj *listPtr;
-
+
listPtr = Tcl_NewListObj(0, NULL);
for (index = 0; attributeStrings[index] != NULL; index++) {
- Tcl_Obj *objPtr = Tcl_NewStringObj(attributeStrings[index], -1);
- Tcl_ListObjAppendElement(interp, listPtr, objPtr);
- /* We now forget about objPtr, it is in the list */
- objPtr = NULL;
- if (Tcl_FSFileAttrsGet(interp, index, filePtr,
- &objPtr) != TCL_OK) {
- Tcl_DecrRefCount(listPtr);
- goto end;
+ Tcl_Obj *objPtrAttr;
+
+ if (res != TCL_OK) {
+ /*
+ * Clear the error from the last iteration.
+ */
+
+ Tcl_ResetResult(interp);
+ }
+
+ res = Tcl_FSFileAttrsGet(interp, index, filePtr, &objPtrAttr);
+ if (res == TCL_OK) {
+ Tcl_Obj *objPtr =
+ Tcl_NewStringObj(attributeStrings[index], -1);
+
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ Tcl_ListObjAppendElement(interp, listPtr, objPtrAttr);
+ nbAtts++;
}
- Tcl_ListObjAppendElement(interp, listPtr, objPtr);
}
+
+ if (index > 0 && nbAtts == 0) {
+ /*
+ * Error: no valid attributes found.
+ */
+
+ Tcl_DecrRefCount(listPtr);
+ goto end;
+ }
+
Tcl_SetObjResult(interp, listPtr);
} else if (objc == 1) {
/*
@@ -976,9 +1062,9 @@ TclFileAttrsCmd(interp, objc, objv)
Tcl_Obj *objPtr = NULL;
if (numObjStrings == 0) {
- Tcl_AppendResult(interp, "bad option \"",
- Tcl_GetString(objv[0]), "\", there are no file attributes"
- " in this filesystem.", (char *) NULL);
+ Tcl_AppendResult(interp, "bad option \"", TclGetString(objv[0]),
+ "\", there are no file attributes in this filesystem.",
+ NULL);
goto end;
}
@@ -986,9 +1072,8 @@ TclFileAttrsCmd(interp, objc, objv)
"option", 0, &index) != TCL_OK) {
goto end;
}
- if (numObjStrings != -1 && objv[0]->typePtr != NULL
- && objv[0]->typePtr->freeIntRepProc != NULL) {
- objv[0]->typePtr->freeIntRepProc(objv[0]);
+ if (didAlloc) {
+ TclFreeIntRep(objv[0]);
objv[0]->typePtr = NULL;
}
if (Tcl_FSFileAttrsGet(interp, index, filePtr,
@@ -1002,11 +1087,11 @@ TclFileAttrsCmd(interp, objc, objv)
*/
int i, index;
-
+
if (numObjStrings == 0) {
- Tcl_AppendResult(interp, "bad option \"",
- Tcl_GetString(objv[0]), "\", there are no file attributes"
- " in this filesystem.", (char *) NULL);
+ Tcl_AppendResult(interp, "bad option \"", TclGetString(objv[0]),
+ "\", there are no file attributes in this filesystem.",
+ NULL);
goto end;
}
@@ -1015,15 +1100,13 @@ TclFileAttrsCmd(interp, objc, objv)
"option", 0, &index) != TCL_OK) {
goto end;
}
- if (numObjStrings != -1 && objv[i]->typePtr != NULL
- && objv[i]->typePtr->freeIntRepProc != NULL) {
- objv[i]->typePtr->freeIntRepProc(objv[i]);
+ if (didAlloc) {
+ TclFreeIntRep(objv[i]);
objv[i]->typePtr = NULL;
}
if (i + 1 == objc) {
Tcl_AppendResult(interp, "value for \"",
- Tcl_GetString(objv[i]), "\" missing",
- (char *) NULL);
+ TclGetString(objv[i]), "\" missing", NULL);
goto end;
}
if (Tcl_FSFileAttrsSet(interp, index, filePtr,
@@ -1034,17 +1117,29 @@ TclFileAttrsCmd(interp, objc, objv)
}
result = TCL_OK;
- end:
- if (numObjStrings != -1) {
- /* Free up the array we allocated */
- ckfree((char*)attributeStrings);
- /*
- * We don't need this object that was passed to us
- * any more.
+ end:
+ if (didAlloc) {
+ /*
+ * Free up the array we allocated.
*/
- if (objStrings != NULL) {
- Tcl_DecrRefCount(objStrings);
- }
+
+ TclStackFree(interp, (void *)attributeStrings);
+ }
+
+ if (objStrings != NULL) {
+ /*
+ * We don't need this object that was passed to us any more.
+ */
+
+ Tcl_DecrRefCount(objStrings);
}
return result;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclFileName.c b/generic/tclFileName.c
index c8e5887..a8c4f42 100644
--- a/generic/tclFileName.c
+++ b/generic/tclFileName.c
@@ -1,65 +1,23 @@
-/*
+/*
* tclFileName.c --
*
- * This file contains routines for converting file names betwen
- * native and network form.
+ * This file contains routines for converting file names betwen native
+ * and network form.
*
* Copyright (c) 1995-1998 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.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
#include "tclRegexp.h"
-
-/*
- * This define is used to activate Tcl's interpretation of Unix-style
- * paths (containing forward slashes, '.' and '..') on MacOS. A
- * side-effect of this is that some paths become ambiguous.
- */
-#define MAC_UNDERSTANDS_UNIX_PATHS
-
-#ifdef MAC_UNDERSTANDS_UNIX_PATHS
-/*
- * The following regular expression matches the root portion of a Macintosh
- * absolute path. It will match degenerate Unix-style paths, tilde paths,
- * Unix-style paths, and Mac paths. The various subexpressions in this
- * can be summarised as follows: ^(/..|~user/unix|~user:mac|/unix|mac:dir).
- * The subexpression indices which match the root portions, are as follows:
- *
- * degenerate unix-style: 2
- * unix-tilde: 5
- * mac-tilde: 7
- * unix-style: 9 (or 10 to cut off the irrelevant header).
- * mac: 12
- *
- */
-
-#define MAC_ROOT_PATTERN "^((/+([.][.]?/+)*([.][.]?)?)|(~[^:/]*)(/[^:]*)?|(~[^:]*)(:.*)?|/+([.][.]?/+)*([^:/]+)(/[^:]*)?|([^:]+):.*)$"
-
-/*
- * The following variables are used to hold precompiled regular expressions
- * for use in filename matching.
- */
-
-typedef struct ThreadSpecificData {
- int initialized;
- Tcl_Obj *macRootPatternPtr;
-} ThreadSpecificData;
-
-static Tcl_ThreadDataKey dataKey;
-
-static void FileNameCleanup _ANSI_ARGS_((ClientData clientData));
-static void FileNameInit _ANSI_ARGS_((void));
-
-#endif
+#include "tclFileSystem.h" /* For TclGetPathType() */
/*
- * The following variable is set in the TclPlatformInit call to one
- * of: TCL_PLATFORM_UNIX, TCL_PLATFORM_MAC, or TCL_PLATFORM_WINDOWS.
+ * The following variable is set in the TclPlatformInit call to one of:
+ * TCL_PLATFORM_UNIX or TCL_PLATFORM_WINDOWS.
*/
TclPlatformType tclPlatform = TCL_PLATFORM_UNIX;
@@ -68,85 +26,60 @@ TclPlatformType tclPlatform = TCL_PLATFORM_UNIX;
* Prototypes for local procedures defined in this file:
*/
-static CONST char * DoTildeSubst _ANSI_ARGS_((Tcl_Interp *interp,
- CONST char *user, Tcl_DString *resultPtr));
-static CONST char * ExtractWinRoot _ANSI_ARGS_((CONST char *path,
- Tcl_DString *resultPtr, int offset,
- Tcl_PathType *typePtr));
-static int SkipToChar _ANSI_ARGS_((char **stringPtr,
- char *match));
-static Tcl_Obj* SplitMacPath _ANSI_ARGS_((CONST char *path));
-static Tcl_Obj* SplitWinPath _ANSI_ARGS_((CONST char *path));
-static Tcl_Obj* SplitUnixPath _ANSI_ARGS_((CONST char *path));
-#ifdef MAC_UNDERSTANDS_UNIX_PATHS
+static const char * DoTildeSubst(Tcl_Interp *interp,
+ const char *user, Tcl_DString *resultPtr);
+static const char * ExtractWinRoot(const char *path,
+ Tcl_DString *resultPtr, int offset,
+ Tcl_PathType *typePtr);
+static int SkipToChar(char **stringPtr, int match);
+static Tcl_Obj* SplitWinPath(const char *path);
+static Tcl_Obj* SplitUnixPath(const char *path);
+static int DoGlob(Tcl_Interp *interp, Tcl_Obj *resultPtr,
+ const char *separators, Tcl_Obj *pathPtr, int flags,
+ char *pattern, Tcl_GlobTypeData *types);
/*
*----------------------------------------------------------------------
*
- * FileNameInit --
+ * SetResultLength --
*
- * This procedure initializes the patterns used by this module.
+ * Resets the result DString for ExtractWinRoot to accommodate
+ * any NT extended path prefixes.
*
* Results:
* None.
*
* Side effects:
- * Compiles the regular expressions.
- *
+ * May modify the Tcl_DString.
*----------------------------------------------------------------------
*/
static void
-FileNameInit()
+SetResultLength(
+ Tcl_DString *resultPtr,
+ int offset,
+ int extended)
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- if (!tsdPtr->initialized) {
- tsdPtr->initialized = 1;
- tsdPtr->macRootPatternPtr = Tcl_NewStringObj(MAC_ROOT_PATTERN, -1);
- Tcl_CreateThreadExitHandler(FileNameCleanup, NULL);
+ Tcl_DStringSetLength(resultPtr, offset);
+ if (extended == 2) {
+ Tcl_DStringAppend(resultPtr, "//?/UNC/", 8);
+ } else if (extended == 1) {
+ Tcl_DStringAppend(resultPtr, "//?/", 4);
}
}
/*
*----------------------------------------------------------------------
*
- * FileNameCleanup --
- *
- * This procedure is a Tcl_ExitProc used to clean up the static
- * data structures used in this file.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Deallocates storage used by the procedures in this file.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-FileNameCleanup(clientData)
- ClientData clientData; /* Not used. */
-{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- Tcl_DecrRefCount(tsdPtr->macRootPatternPtr);
- tsdPtr->initialized = 0;
-}
-#endif
-
-/*
- *----------------------------------------------------------------------
- *
* ExtractWinRoot --
*
- * Matches the root portion of a Windows path and appends it
- * to the specified Tcl_DString.
- *
+ * Matches the root portion of a Windows path and appends it to the
+ * specified Tcl_DString.
+ *
* Results:
- * Returns the position in the path immediately after the root
- * including any trailing slashes.
- * Appends a cleaned up version of the root to the Tcl_DString
- * at the specified offest.
+ * Returns the position in the path immediately after the root including
+ * any trailing slashes. Appends a cleaned up version of the root to the
+ * Tcl_DString at the specified offest.
*
* Side effects:
* Modifies the specified Tcl_DString.
@@ -154,59 +87,88 @@ FileNameCleanup(clientData)
*----------------------------------------------------------------------
*/
-static CONST char *
-ExtractWinRoot(path, resultPtr, offset, typePtr)
- CONST char *path; /* Path to parse. */
- Tcl_DString *resultPtr; /* Buffer to hold result. */
- int offset; /* Offset in buffer where result should be
+static const char *
+ExtractWinRoot(
+ const char *path, /* Path to parse. */
+ Tcl_DString *resultPtr, /* Buffer to hold result. */
+ int offset, /* Offset in buffer where result should be
* stored. */
- Tcl_PathType *typePtr; /* Where to store pathType result */
+ Tcl_PathType *typePtr) /* Where to store pathType result */
{
+ int extended = 0;
+
+ if ( (path[0] == '/' || path[0] == '\\')
+ && (path[1] == '/' || path[1] == '\\')
+ && (path[2] == '?')
+ && (path[3] == '/' || path[3] == '\\')) {
+ extended = 1;
+ path = path + 4;
+ if (path[0] == 'U' && path[1] == 'N' && path[2] == 'C'
+ && (path[3] == '/' || path[3] == '\\')) {
+ extended = 2;
+ path = path + 4;
+ }
+ }
+
if (path[0] == '/' || path[0] == '\\') {
- /* Might be a UNC or Vol-Relative path */
- CONST char *host, *share, *tail;
+ /*
+ * Might be a UNC or Vol-Relative path.
+ */
+
+ const char *host, *share, *tail;
int hlen, slen;
+
if (path[1] != '/' && path[1] != '\\') {
- Tcl_DStringSetLength(resultPtr, offset);
+ SetResultLength(resultPtr, offset, extended);
*typePtr = TCL_PATH_VOLUME_RELATIVE;
Tcl_DStringAppend(resultPtr, "/", 1);
return &path[1];
}
host = &path[2];
- /* Skip separators */
- while (host[0] == '/' || host[0] == '\\') host++;
+ /*
+ * Skip separators.
+ */
+
+ while (host[0] == '/' || host[0] == '\\') {
+ host++;
+ }
for (hlen = 0; host[hlen];hlen++) {
- if (host[hlen] == '/' || host[hlen] == '\\')
+ if (host[hlen] == '/' || host[hlen] == '\\') {
break;
+ }
}
if (host[hlen] == 0 || host[hlen+1] == 0) {
- /*
- * The path given is simply of the form
- * '/foo', '//foo', '/////foo' or the same
- * with backslashes. If there is exactly
- * one leading '/' the path is volume relative
- * (see filename man page). If there are more
- * than one, we are simply assuming they
- * are superfluous and we trim them away.
- * (An alternative interpretation would
- * be that it is a host name, but we have
+ /*
+ * The path given is simply of the form '/foo', '//foo',
+ * '/////foo' or the same with backslashes. If there is exactly
+ * one leading '/' the path is volume relative (see filename man
+ * page). If there are more than one, we are simply assuming they
+ * are superfluous and we trim them away. (An alternative
+ * interpretation would be that it is a host name, but we have
* been documented that that is not the case).
*/
+
*typePtr = TCL_PATH_VOLUME_RELATIVE;
Tcl_DStringAppend(resultPtr, "/", 1);
return &path[2];
}
- Tcl_DStringSetLength(resultPtr, offset);
+ SetResultLength(resultPtr, offset, extended);
share = &host[hlen];
- /* Skip separators */
- while (share[0] == '/' || share[0] == '\\') share++;
+ /*
+ * Skip separators.
+ */
+
+ while (share[0] == '/' || share[0] == '\\') {
+ share++;
+ }
- for (slen = 0; share[slen];slen++) {
- if (share[slen] == '/' || share[slen] == '\\')
+ for (slen=0; share[slen]; slen++) {
+ if (share[slen] == '/' || share[slen] == '\\') {
break;
+ }
}
Tcl_DStringAppend(resultPtr, "//", 2);
Tcl_DStringAppend(resultPtr, host, hlen);
@@ -215,14 +177,22 @@ ExtractWinRoot(path, resultPtr, offset, typePtr)
tail = &share[slen];
- /* Skip separators */
- while (tail[0] == '/' || tail[0] == '\\') tail++;
+ /*
+ * Skip separators.
+ */
+
+ while (tail[0] == '/' || tail[0] == '\\') {
+ tail++;
+ }
*typePtr = TCL_PATH_ABSOLUTE;
return tail;
} else if (*path && path[1] == ':') {
- /* Might be a drive sep */
- Tcl_DStringSetLength(resultPtr, offset);
+ /*
+ * Might be a drive separator.
+ */
+
+ SetResultLength(resultPtr, offset, extended);
if (path[2] != '/' && path[2] != '\\') {
*typePtr = TCL_PATH_VOLUME_RELATIVE;
@@ -231,8 +201,13 @@ ExtractWinRoot(path, resultPtr, offset, typePtr)
} else {
char *tail = (char*)&path[3];
- /* Skip separators */
- while (*tail && (tail[0] == '/' || tail[0] == '\\')) tail++;
+ /*
+ * Skip separators.
+ */
+
+ while (*tail && (tail[0] == '/' || tail[0] == '\\')) {
+ tail++;
+ }
*typePtr = TCL_PATH_ABSOLUTE;
Tcl_DStringAppend(resultPtr, path, 2);
@@ -242,58 +217,90 @@ ExtractWinRoot(path, resultPtr, offset, typePtr)
}
} else {
int abs = 0;
- if ((path[0] == 'c' || path[0] == 'C')
- && (path[1] == 'o' || path[1] == 'O')) {
+
+ /*
+ * Check for Windows devices.
+ */
+
+ if ((path[0] == 'c' || path[0] == 'C')
+ && (path[1] == 'o' || path[1] == 'O')) {
if ((path[2] == 'm' || path[2] == 'M')
- && path[3] >= '1' && path[3] <= '4') {
- /* May have match for 'com[1-4]:?', which is a serial port */
+ && path[3] >= '1' && path[3] <= '4') {
+ /*
+ * May have match for 'com[1-4]:?', which is a serial port.
+ */
+
if (path[4] == '\0') {
abs = 4;
} else if (path [4] == ':' && path[5] == '\0') {
abs = 5;
}
+
} else if ((path[2] == 'n' || path[2] == 'N') && path[3] == '\0') {
- /* Have match for 'con' */
+ /*
+ * Have match for 'con'.
+ */
+
abs = 3;
}
+
} else if ((path[0] == 'l' || path[0] == 'L')
- && (path[1] == 'p' || path[1] == 'P')
- && (path[2] == 't' || path[2] == 'T')) {
+ && (path[1] == 'p' || path[1] == 'P')
+ && (path[2] == 't' || path[2] == 'T')) {
if (path[3] >= '1' && path[3] <= '3') {
- /* May have match for 'lpt[1-3]:?' */
+ /*
+ * May have match for 'lpt[1-3]:?'
+ */
+
if (path[4] == '\0') {
abs = 4;
} else if (path [4] == ':' && path[5] == '\0') {
abs = 5;
}
}
+
} else if ((path[0] == 'p' || path[0] == 'P')
- && (path[1] == 'r' || path[1] == 'R')
- && (path[2] == 'n' || path[2] == 'N')
- && path[3] == '\0') {
- /* Have match for 'prn' */
+ && (path[1] == 'r' || path[1] == 'R')
+ && (path[2] == 'n' || path[2] == 'N')
+ && path[3] == '\0') {
+ /*
+ * Have match for 'prn'.
+ */
abs = 3;
+
} else if ((path[0] == 'n' || path[0] == 'N')
- && (path[1] == 'u' || path[1] == 'U')
- && (path[2] == 'l' || path[2] == 'L')
- && path[3] == '\0') {
- /* Have match for 'nul' */
+ && (path[1] == 'u' || path[1] == 'U')
+ && (path[2] == 'l' || path[2] == 'L')
+ && path[3] == '\0') {
+ /*
+ * Have match for 'nul'.
+ */
+
abs = 3;
+
} else if ((path[0] == 'a' || path[0] == 'A')
- && (path[1] == 'u' || path[1] == 'U')
- && (path[2] == 'x' || path[2] == 'X')
- && path[3] == '\0') {
- /* Have match for 'aux' */
+ && (path[1] == 'u' || path[1] == 'U')
+ && (path[2] == 'x' || path[2] == 'X')
+ && path[3] == '\0') {
+ /*
+ * Have match for 'aux'.
+ */
+
abs = 3;
}
+
if (abs != 0) {
*typePtr = TCL_PATH_ABSOLUTE;
- Tcl_DStringSetLength(resultPtr, offset);
+ SetResultLength(resultPtr, offset, extended);
Tcl_DStringAppend(resultPtr, path, abs);
return path + abs;
}
}
- /* Anything else is treated as relative */
+
+ /*
+ * Anything else is treated as relative.
+ */
+
*typePtr = TCL_PATH_RELATIVE;
return path;
}
@@ -303,12 +310,12 @@ ExtractWinRoot(path, resultPtr, offset, typePtr)
*
* Tcl_GetPathType --
*
- * Determines whether a given path is relative to the current
- * directory, relative to the current volume, or absolute.
- *
- * The objectified Tcl_FSGetPathType should be used in
- * preference to this function (as you can see below, this
- * is just a wrapper around that other function).
+ * Determines whether a given path is relative to the current directory,
+ * relative to the current volume, or absolute.
+ *
+ * The objectified Tcl_FSGetPathType should be used in preference to this
+ * function (as you can see below, this is just a wrapper around that
+ * other function).
*
* Results:
* Returns one of TCL_PATH_ABSOLUTE, TCL_PATH_RELATIVE, or
@@ -321,11 +328,12 @@ ExtractWinRoot(path, resultPtr, offset, typePtr)
*/
Tcl_PathType
-Tcl_GetPathType(path)
- CONST char *path;
+Tcl_GetPathType(
+ const char *path)
{
Tcl_PathType type;
Tcl_Obj *tempObj = Tcl_NewStringObj(path,-1);
+
Tcl_IncrRefCount(tempObj);
type = Tcl_FSGetPathType(tempObj);
Tcl_DecrRefCount(tempObj);
@@ -337,12 +345,18 @@ Tcl_GetPathType(path)
*
* TclpGetNativePathType --
*
- * Determines whether a given path is relative to the current
- * directory, relative to the current volume, or absolute, but
- * ONLY FOR THE NATIVE FILESYSTEM. This function is called from
- * tclIOUtil.c (but needs to be here due to its dependence on
- * static variables/functions in this file). The exported
- * function Tcl_FSGetPathType should be used by extensions.
+ * Determines whether a given path is relative to the current directory,
+ * relative to the current volume, or absolute, but ONLY FOR THE NATIVE
+ * FILESYSTEM. This function is called from tclIOUtil.c (but needs to be
+ * here due to its dependence on static variables/functions in this
+ * file). The exported function Tcl_FSGetPathType should be used by
+ * extensions.
+ *
+ * Note that '~' paths are always considered TCL_PATH_ABSOLUTE, even
+ * though expanding the '~' could lead to any possible path type. This
+ * function should therefore be considered a low-level, string
+ * manipulation function only -- it doesn't actually do any expansion in
+ * making its determination.
*
* Results:
* Returns one of TCL_PATH_ABSOLUTE, TCL_PATH_RELATIVE, or
@@ -355,20 +369,22 @@ Tcl_GetPathType(path)
*/
Tcl_PathType
-TclpGetNativePathType(pathObjPtr, driveNameLengthPtr, driveNameRef)
- Tcl_Obj *pathObjPtr;
- int *driveNameLengthPtr;
- Tcl_Obj **driveNameRef;
+TclpGetNativePathType(
+ Tcl_Obj *pathPtr, /* Native path of interest */
+ int *driveNameLengthPtr, /* Returns length of drive, if non-NULL and
+ * path was absolute */
+ Tcl_Obj **driveNameRef)
{
Tcl_PathType type = TCL_PATH_ABSOLUTE;
int pathLen;
- char *path = Tcl_GetStringFromObj(pathObjPtr, &pathLen);
-
+ char *path = Tcl_GetStringFromObj(pathPtr, &pathLen);
+
if (path[0] == '~') {
- /*
- * This case is common to all platforms.
- * Paths that begin with ~ are absolute.
+ /*
+ * This case is common to all platforms. Paths that begin with ~ are
+ * absolute.
*/
+
if (driveNameLengthPtr != NULL) {
char *end = path + 1;
while ((*end != '\0') && (*end != '/')) {
@@ -378,137 +394,55 @@ TclpGetNativePathType(pathObjPtr, driveNameLengthPtr, driveNameRef)
}
} else {
switch (tclPlatform) {
- case TCL_PLATFORM_UNIX: {
- char *origPath = path;
-
- /*
- * Paths that begin with / are absolute.
- */
+ case TCL_PLATFORM_UNIX: {
+ char *origPath = path;
+
+ /*
+ * Paths that begin with / are absolute.
+ */
#ifdef __QNX__
- /*
- * Check for QNX //<node id> prefix
- */
- if (*path && (pathLen > 3) && (path[0] == '/')
- && (path[1] == '/') && isdigit(UCHAR(path[2]))) {
- path += 3;
- while (isdigit(UCHAR(*path))) {
- ++path;
- }
- }
-#endif
- if (path[0] == '/') {
- if (driveNameLengthPtr != NULL) {
- /*
- * We need this addition in case the QNX code
- * was used
- */
- *driveNameLengthPtr = (1 + path - origPath);
- }
- } else {
- type = TCL_PATH_RELATIVE;
+ /*
+ * Check for QNX //<node id> prefix
+ */
+ if (*path && (pathLen > 3) && (path[0] == '/')
+ && (path[1] == '/') && isdigit(UCHAR(path[2]))) {
+ path += 3;
+ while (isdigit(UCHAR(*path))) {
+ ++path;
}
- break;
}
- case TCL_PLATFORM_MAC:
- if (path[0] == ':') {
- type = TCL_PATH_RELATIVE;
- } else {
-#ifdef MAC_UNDERSTANDS_UNIX_PATHS
- ThreadSpecificData *tsdPtr;
- Tcl_RegExp re;
-
- tsdPtr = TCL_TSD_INIT(&dataKey);
-
+#endif
+ if (path[0] == '/') {
+ if (driveNameLengthPtr != NULL) {
/*
- * Since we have eliminated the easy cases, use the
- * root pattern to look for the other types.
+ * We need this addition in case the QNX code was used.
*/
- FileNameInit();
- re = Tcl_GetRegExpFromObj(NULL, tsdPtr->macRootPatternPtr,
- REG_ADVANCED);
-
- if (!Tcl_RegExpExec(NULL, re, path, path)) {
- type = TCL_PATH_RELATIVE;
- } else {
- CONST char *root, *end;
- Tcl_RegExpRange(re, 2, &root, &end);
- if (root != NULL) {
- type = TCL_PATH_RELATIVE;
- } else {
- if (driveNameLengthPtr != NULL) {
- Tcl_RegExpRange(re, 0, &root, &end);
- *driveNameLengthPtr = end - root;
- }
- if (driveNameRef != NULL) {
- if (*root == '/') {
- char *c;
- int gotColon = 0;
- *driveNameRef = Tcl_NewStringObj(root + 1,
- end - root -1);
- c = Tcl_GetString(*driveNameRef);
- while (*c != '\0') {
- if (*c == '/') {
- gotColon++;
- *c = ':';
- }
- c++;
- }
- /*
- * If there is no colon, we have just a
- * volume name so we must add a colon so
- * it is an absolute path.
- */
- if (gotColon == 0) {
- Tcl_AppendToObj(*driveNameRef, ":", 1);
- } else if ((gotColon > 1) &&
- (*(c-1) == ':')) {
- /* We have an extra colon */
- Tcl_SetObjLength(*driveNameRef,
- c - Tcl_GetString(*driveNameRef) - 1);
- }
- }
- }
- }
- }
-#else
- if (path[0] == '~') {
- } else if (path[0] == ':') {
- type = TCL_PATH_RELATIVE;
- } else {
- char *colonPos = strchr(path,':');
- if (colonPos == NULL) {
- type = TCL_PATH_RELATIVE;
- } else {
- }
- }
- if (type == TCL_PATH_ABSOLUTE) {
- if (driveNameLengthPtr != NULL) {
- *driveNameLengthPtr = strlen(path);
- }
- }
-#endif
+ *driveNameLengthPtr = (1 + path - origPath);
}
- break;
-
- case TCL_PLATFORM_WINDOWS: {
- Tcl_DString ds;
- CONST char *rootEnd;
-
- Tcl_DStringInit(&ds);
- rootEnd = ExtractWinRoot(path, &ds, 0, &type);
- if ((rootEnd != path) && (driveNameLengthPtr != NULL)) {
- *driveNameLengthPtr = rootEnd - path;
- if (driveNameRef != NULL) {
- *driveNameRef = Tcl_NewStringObj(Tcl_DStringValue(&ds),
- Tcl_DStringLength(&ds));
- Tcl_IncrRefCount(*driveNameRef);
- }
+ } else {
+ type = TCL_PATH_RELATIVE;
+ }
+ break;
+ }
+ case TCL_PLATFORM_WINDOWS: {
+ Tcl_DString ds;
+ const char *rootEnd;
+
+ Tcl_DStringInit(&ds);
+ rootEnd = ExtractWinRoot(path, &ds, 0, &type);
+ if ((rootEnd != path) && (driveNameLengthPtr != NULL)) {
+ *driveNameLengthPtr = rootEnd - path;
+ if (driveNameRef != NULL) {
+ *driveNameRef = Tcl_NewStringObj(Tcl_DStringValue(&ds),
+ Tcl_DStringLength(&ds));
+ Tcl_IncrRefCount(*driveNameRef);
}
- Tcl_DStringFree(&ds);
- break;
}
+ Tcl_DStringFree(&ds);
+ break;
+ }
}
}
return type;
@@ -519,18 +453,17 @@ TclpGetNativePathType(pathObjPtr, driveNameLengthPtr, driveNameRef)
*
* TclpNativeSplitPath --
*
- * This function takes the given Tcl_Obj, which should be a valid
- * path, and returns a Tcl List object containing each segment
- * of that path as an element.
+ * This function takes the given Tcl_Obj, which should be a valid path,
+ * and returns a Tcl List object containing each segment of that path as
+ * an element.
+ *
+ * Note this function currently calls the older Split(Plat)Path
+ * functions, which require more memory allocation than is desirable.
*
- * Note this function currently calls the older Split(Plat)Path
- * functions, which require more memory allocation than is
- * desirable.
- *
* Results:
- * Returns list object with refCount of zero. If the passed in
- * lenPtr is non-NULL, we use it to return the number of elements
- * in the returned list.
+ * Returns list object with refCount of zero. If the passed in lenPtr is
+ * non-NULL, we use it to return the number of elements in the returned
+ * list.
*
* Side effects:
* None.
@@ -538,29 +471,25 @@ TclpGetNativePathType(pathObjPtr, driveNameLengthPtr, driveNameRef)
*---------------------------------------------------------------------------
*/
-Tcl_Obj*
-TclpNativeSplitPath(pathPtr, lenPtr)
- Tcl_Obj *pathPtr; /* Path to split. */
- int *lenPtr; /* int to store number of path elements. */
+Tcl_Obj *
+TclpNativeSplitPath(
+ Tcl_Obj *pathPtr, /* Path to split. */
+ int *lenPtr) /* int to store number of path elements. */
{
- Tcl_Obj *resultPtr = NULL; /* Needed only to prevent gcc warnings. */
+ Tcl_Obj *resultPtr = NULL; /* Needed only to prevent gcc warnings. */
/*
- * Perform platform specific splitting.
+ * Perform platform specific splitting.
*/
switch (tclPlatform) {
- case TCL_PLATFORM_UNIX:
- resultPtr = SplitUnixPath(Tcl_GetString(pathPtr));
- break;
+ case TCL_PLATFORM_UNIX:
+ resultPtr = SplitUnixPath(Tcl_GetString(pathPtr));
+ break;
- case TCL_PLATFORM_WINDOWS:
- resultPtr = SplitWinPath(Tcl_GetString(pathPtr));
- break;
-
- case TCL_PLATFORM_MAC:
- resultPtr = SplitMacPath(Tcl_GetString(pathPtr));
- break;
+ case TCL_PLATFORM_WINDOWS:
+ resultPtr = SplitWinPath(Tcl_GetString(pathPtr));
+ break;
}
/*
@@ -578,20 +507,19 @@ TclpNativeSplitPath(pathPtr, lenPtr)
*
* Tcl_SplitPath --
*
- * Split a path into a list of path components. The first element
- * of the list will have the same path type as the original path.
+ * Split a path into a list of path components. The first element of the
+ * list will have the same path type as the original path.
*
* Results:
- * Returns a standard Tcl result. The interpreter result contains
- * a list of path components.
- * *argvPtr will be filled in with the address of an array
- * whose elements point to the elements of path, in order.
- * *argcPtr will get filled in with the number of valid elements
- * in the array. A single block of memory is dynamically allocated
- * to hold both the argv array and a copy of the path elements.
- * The caller must eventually free this memory by calling ckfree()
- * on *argvPtr. Note: *argvPtr and *argcPtr are only modified
- * if the procedure returns normally.
+ * Returns a standard Tcl result. The interpreter result contains a list
+ * of path components. *argvPtr will be filled in with the address of an
+ * array whose elements point to the elements of path, in order.
+ * *argcPtr will get filled in with the number of valid elements in the
+ * array. A single block of memory is dynamically allocated to hold both
+ * the argv array and a copy of the path elements. The caller must
+ * eventually free this memory by calling ckfree() on *argvPtr. Note:
+ * *argvPtr and *argcPtr are only modified if the procedure returns
+ * normally.
*
* Side effects:
* Allocates memory.
@@ -600,14 +528,14 @@ TclpNativeSplitPath(pathPtr, lenPtr)
*/
void
-Tcl_SplitPath(path, argcPtr, argvPtr)
- CONST char *path; /* Pointer to string containing a path. */
- int *argcPtr; /* Pointer to location to fill in with
- * the number of elements in the path. */
- CONST char ***argvPtr; /* Pointer to place to store pointer to array
+Tcl_SplitPath(
+ const char *path, /* Pointer to string containing a path. */
+ int *argcPtr, /* Pointer to location to fill in with the
+ * number of elements in the path. */
+ const char ***argvPtr) /* Pointer to place to store pointer to array
* of pointers to path elements. */
{
- Tcl_Obj *resultPtr = NULL; /* Needed only to prevent gcc warnings. */
+ Tcl_Obj *resultPtr = NULL; /* Needed only to prevent gcc warnings. */
Tcl_Obj *tmpPtr, *eltPtr;
int i, size, len;
char *p, *str;
@@ -619,38 +547,41 @@ Tcl_SplitPath(path, argcPtr, argvPtr)
tmpPtr = Tcl_NewStringObj(path, -1);
Tcl_IncrRefCount(tmpPtr);
resultPtr = Tcl_FSSplitPath(tmpPtr, argcPtr);
+ Tcl_IncrRefCount(resultPtr);
Tcl_DecrRefCount(tmpPtr);
- /* Calculate space required for the result */
-
+ /*
+ * Calculate space required for the result.
+ */
+
size = 1;
for (i = 0; i < *argcPtr; i++) {
Tcl_ListObjIndex(NULL, resultPtr, i, &eltPtr);
Tcl_GetStringFromObj(eltPtr, &len);
size += len + 1;
}
-
+
/*
- * Allocate a buffer large enough to hold the contents of all of
- * the list plus the argv pointers and the terminating NULL pointer.
+ * Allocate a buffer large enough to hold the contents of all of the list
+ * plus the argv pointers and the terminating NULL pointer.
*/
- *argvPtr = (CONST char **) ckalloc((unsigned)
+ *argvPtr = (const char **) ckalloc((unsigned)
((((*argcPtr) + 1) * sizeof(char *)) + size));
/*
- * Position p after the last argv pointer and copy the contents of
- * the list in, piece by piece.
+ * Position p after the last argv pointer and copy the contents of the
+ * list in, piece by piece.
*/
p = (char *) &(*argvPtr)[(*argcPtr) + 1];
for (i = 0; i < *argcPtr; i++) {
Tcl_ListObjIndex(NULL, resultPtr, i, &eltPtr);
str = Tcl_GetStringFromObj(eltPtr, &len);
- memcpy((VOID *) p, (VOID *) str, (size_t) len+1);
+ memcpy(p, str, (size_t) len+1);
p += len+1;
}
-
+
/*
* Now set up the argv pointers.
*/
@@ -659,7 +590,7 @@ Tcl_SplitPath(path, argcPtr, argvPtr)
for (i = 0; i < *argcPtr; i++) {
(*argvPtr)[i] = p;
- while ((*p++) != '\0') {}
+ for (; *(p++)!='\0'; );
}
(*argvPtr)[i] = NULL;
@@ -675,8 +606,8 @@ Tcl_SplitPath(path, argcPtr, argvPtr)
*
* SplitUnixPath --
*
- * This routine is used by Tcl_(FS)SplitPath to handle splitting
- * Unix paths.
+ * This routine is used by Tcl_(FS)SplitPath to handle splitting Unix
+ * paths.
*
* Results:
* Returns a newly allocated Tcl list object.
@@ -687,12 +618,12 @@ Tcl_SplitPath(path, argcPtr, argvPtr)
*----------------------------------------------------------------------
*/
-static Tcl_Obj*
-SplitUnixPath(path)
- CONST char *path; /* Pointer to string containing a path. */
+static Tcl_Obj *
+SplitUnixPath(
+ const char *path) /* Pointer to string containing a path. */
{
int length;
- CONST char *p, *elementStart;
+ const char *p, *elementStart;
Tcl_Obj *result = Tcl_NewObj();
/*
@@ -720,7 +651,7 @@ SplitUnixPath(path)
}
/*
- * Split on slashes. Embedded elements that start with tilde will be
+ * Split on slashes. Embedded elements that start with tilde will be
* prefixed with "./" so they are not affected by tilde substitution.
*/
@@ -733,7 +664,7 @@ SplitUnixPath(path)
if (length > 0) {
Tcl_Obj *nextElt;
if ((elementStart[0] == '~') && (elementStart != path)) {
- nextElt = Tcl_NewStringObj("./",2);
+ TclNewLiteralStringObj(nextElt, "./");
Tcl_AppendToObj(nextElt, elementStart, length);
} else {
nextElt = Tcl_NewStringObj(elementStart, length);
@@ -746,15 +677,14 @@ SplitUnixPath(path)
}
return result;
}
-
/*
*----------------------------------------------------------------------
*
* SplitWinPath --
*
- * This routine is used by Tcl_(FS)SplitPath to handle splitting
- * Windows paths.
+ * This routine is used by Tcl_(FS)SplitPath to handle splitting Windows
+ * paths.
*
* Results:
* Returns a newly allocated Tcl list object.
@@ -765,17 +695,17 @@ SplitUnixPath(path)
*----------------------------------------------------------------------
*/
-static Tcl_Obj*
-SplitWinPath(path)
- CONST char *path; /* Pointer to string containing a path. */
+static Tcl_Obj *
+SplitWinPath(
+ const char *path) /* Pointer to string containing a path. */
{
int length;
- CONST char *p, *elementStart;
+ const char *p, *elementStart;
Tcl_PathType type = TCL_PATH_ABSOLUTE;
Tcl_DString buf;
Tcl_Obj *result = Tcl_NewObj();
Tcl_DStringInit(&buf);
-
+
p = ExtractWinRoot(path, &buf, 0, &type);
/*
@@ -783,16 +713,15 @@ SplitWinPath(path)
*/
if (p != path) {
- Tcl_ListObjAppendElement(NULL, result,
- Tcl_NewStringObj(Tcl_DStringValue(&buf),
- Tcl_DStringLength(&buf)));
+ Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj(
+ Tcl_DStringValue(&buf), Tcl_DStringLength(&buf)));
}
Tcl_DStringFree(&buf);
-
+
/*
- * Split on slashes. Embedded elements that start with tilde
- * or a drive letter will be prefixed with "./" so they are not
- * affected by tilde substitution.
+ * Split on slashes. Embedded elements that start with tilde or a drive
+ * letter will be prefixed with "./" so they are not affected by tilde
+ * substitution.
*/
do {
@@ -803,11 +732,10 @@ SplitWinPath(path)
length = p - elementStart;
if (length > 0) {
Tcl_Obj *nextElt;
- if ((elementStart != path)
- && ((elementStart[0] == '~')
+ if ((elementStart != path) && ((elementStart[0] == '~')
|| (isalpha(UCHAR(elementStart[0]))
&& elementStart[1] == ':'))) {
- nextElt = Tcl_NewStringObj("./",2);
+ TclNewLiteralStringObj(nextElt, "./");
Tcl_AppendToObj(nextElt, elementStart, length);
} else {
nextElt = Tcl_NewStringObj(elementStart, length);
@@ -820,256 +748,21 @@ SplitWinPath(path)
}
/*
- *----------------------------------------------------------------------
- *
- * SplitMacPath --
- *
- * This routine is used by Tcl_(FS)SplitPath to handle splitting
- * Macintosh paths.
- *
- * Results:
- * Returns a newly allocated Tcl list object.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static Tcl_Obj*
-SplitMacPath(path)
- CONST char *path; /* Pointer to string containing a path. */
-{
- int isMac = 0; /* 1 if is Mac-style, 0 if Unix-style path. */
- int length;
- CONST char *p, *elementStart;
- Tcl_Obj *result;
-#ifdef MAC_UNDERSTANDS_UNIX_PATHS
- Tcl_RegExp re;
- int i;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-#endif
-
- result = Tcl_NewObj();
-
-#ifdef MAC_UNDERSTANDS_UNIX_PATHS
- /*
- * Initialize the path name parser for Macintosh path names.
- */
-
- FileNameInit();
-
- /*
- * Match the root portion of a Mac path name.
- */
-
- i = 0; /* Needed only to prevent gcc warnings. */
-
- re = Tcl_GetRegExpFromObj(NULL, tsdPtr->macRootPatternPtr, REG_ADVANCED);
-
- if (Tcl_RegExpExec(NULL, re, path, path) == 1) {
- CONST char *start, *end;
- Tcl_Obj *nextElt;
-
- /*
- * Treat degenerate absolute paths like / and /../.. as
- * Mac relative file names for lack of anything else to do.
- */
-
- Tcl_RegExpRange(re, 2, &start, &end);
- if (start) {
- Tcl_Obj *elt = Tcl_NewStringObj(":", 1);
- Tcl_RegExpRange(re, 0, &start, &end);
- Tcl_AppendToObj(elt, path, end - start);
- Tcl_ListObjAppendElement(NULL, result, elt);
- return result;
- }
-
- Tcl_RegExpRange(re, 5, &start, &end);
- if (start) {
- /*
- * Unix-style tilde prefixed paths.
- */
-
- isMac = 0;
- i = 5;
- } else {
- Tcl_RegExpRange(re, 7, &start, &end);
- if (start) {
- /*
- * Mac-style tilde prefixed paths.
- */
-
- isMac = 1;
- i = 7;
- } else {
- Tcl_RegExpRange(re, 10, &start, &end);
- if (start) {
- /*
- * Normal Unix style paths.
- */
-
- isMac = 0;
- i = 10;
- } else {
- Tcl_RegExpRange(re, 12, &start, &end);
- if (start) {
- /*
- * Normal Mac style paths.
- */
-
- isMac = 1;
- i = 12;
- }
- }
- }
- }
- Tcl_RegExpRange(re, i, &start, &end);
- length = end - start;
-
- /*
- * Append the element and terminate it with a :
- */
-
- nextElt = Tcl_NewStringObj(start, length);
- Tcl_AppendToObj(nextElt, ":", 1);
- Tcl_ListObjAppendElement(NULL, result, nextElt);
- p = end;
- } else {
- isMac = (strchr(path, ':') != NULL);
- p = path;
- }
-#else
- if ((path[0] != ':') && (path[0] == '~' || (strchr(path,':') != NULL))) {
- CONST char *end;
- Tcl_Obj *nextElt;
-
- isMac = 1;
-
- end = strchr(path,':');
- if (end == NULL) {
- length = strlen(path);
- } else {
- length = end - path;
- }
-
- /*
- * Append the element and terminate it with a :
- */
-
- nextElt = Tcl_NewStringObj(path, length);
- Tcl_AppendToObj(nextElt, ":", 1);
- Tcl_ListObjAppendElement(NULL, result, nextElt);
- p = path + length;
- } else {
- isMac = (strchr(path, ':') != NULL);
- isMac = 1;
- p = path;
- }
-#endif
-
- if (isMac) {
-
- /*
- * p is pointing at the first colon in the path. There
- * will always be one, since this is a Mac-style path.
- * (This is no longer true if MAC_UNDERSTANDS_UNIX_PATHS
- * is false, so we must check whether 'p' points to the
- * end of the string.)
- */
- elementStart = p;
- if (*p == ':') {
- p++;
- }
-
- while ((p = strchr(p, ':')) != NULL) {
- length = p - elementStart;
- if (length == 1) {
- while (*p == ':') {
- Tcl_ListObjAppendElement(NULL, result,
- Tcl_NewStringObj("::", 2));
- elementStart = p++;
- }
- } else {
- /*
- * If this is a simple component, drop the leading colon.
- */
-
- if ((elementStart[1] != '~')
- && (strchr(elementStart+1, '/') == NULL)) {
- elementStart++;
- length--;
- }
- Tcl_ListObjAppendElement(NULL, result,
- Tcl_NewStringObj(elementStart, length));
- elementStart = p++;
- }
- }
- if (elementStart[0] != ':') {
- if (elementStart[0] != '\0') {
- Tcl_ListObjAppendElement(NULL, result,
- Tcl_NewStringObj(elementStart, -1));
- }
- } else {
- if (elementStart[1] != '\0' || elementStart == path) {
- if ((elementStart[1] != '~') && (elementStart[1] != '\0')
- && (strchr(elementStart+1, '/') == NULL)) {
- elementStart++;
- }
- Tcl_ListObjAppendElement(NULL, result,
- Tcl_NewStringObj(elementStart, -1));
- }
- }
- } else {
-
- /*
- * Split on slashes, suppress extra /'s, and convert .. to ::.
- */
-
- for (;;) {
- elementStart = p;
- while ((*p != '\0') && (*p != '/')) {
- p++;
- }
- length = p - elementStart;
- if (length > 0) {
- if ((length == 1) && (elementStart[0] == '.')) {
- Tcl_ListObjAppendElement(NULL, result,
- Tcl_NewStringObj(":", 1));
- } else if ((length == 2) && (elementStart[0] == '.')
- && (elementStart[1] == '.')) {
- Tcl_ListObjAppendElement(NULL, result,
- Tcl_NewStringObj("::", 2));
- } else {
- Tcl_Obj *nextElt;
- if (*elementStart == '~') {
- nextElt = Tcl_NewStringObj(":",1);
- Tcl_AppendToObj(nextElt, elementStart, length);
- } else {
- nextElt = Tcl_NewStringObj(elementStart, length);
- }
- Tcl_ListObjAppendElement(NULL, result, nextElt);
- }
- }
- if (*p++ == '\0') {
- break;
- }
- }
- }
- return result;
-}
-
-/*
*---------------------------------------------------------------------------
*
* Tcl_FSJoinToPath --
*
- * This function takes the given object, which should usually be a
- * valid path or NULL, and joins onto it the array of paths
- * segments given.
+ * This function takes the given object, which should usually be a valid
+ * path or NULL, and joins onto it the array of paths segments given.
+ *
+ * The objects in the array given will temporarily have their refCount
+ * increased by one, and then decreased by one when this function exits
+ * (which means if they had zero refCount when we were called, they will
+ * be freed).
*
* Results:
- * Returns object with refCount of zero
+ * Returns object owned by the caller (which should increment its
+ * refCount) - typically an object with refCount of zero.
*
* Side effects:
* None.
@@ -1077,26 +770,37 @@ SplitMacPath(path)
*---------------------------------------------------------------------------
*/
-Tcl_Obj*
-Tcl_FSJoinToPath(basePtr, objc, objv)
- Tcl_Obj *basePtr;
- int objc;
- Tcl_Obj *CONST objv[];
+Tcl_Obj *
+Tcl_FSJoinToPath(
+ Tcl_Obj *pathPtr, /* Valid path or NULL. */
+ int objc, /* Number of array elements to join */
+ Tcl_Obj *const objv[]) /* Path elements to join. */
{
int i;
Tcl_Obj *lobj, *ret;
- if (basePtr == NULL) {
+ if (pathPtr == NULL) {
lobj = Tcl_NewListObj(0, NULL);
} else {
- lobj = Tcl_NewListObj(1, &basePtr);
+ lobj = Tcl_NewListObj(1, &pathPtr);
}
-
+
for (i = 0; i<objc;i++) {
Tcl_ListObjAppendElement(NULL, lobj, objv[i]);
}
ret = Tcl_FSJoinPath(lobj, -1);
+
+ /*
+ * It is possible that 'ret' is just a member of the list and is therefore
+ * going to be freed here. Therefore we must adjust the refCount manually.
+ * (It would be better if we changed the documentation of this function
+ * and Tcl_FSJoinPath so that the returned object already has a refCount
+ * for the caller, hence avoiding these subtleties (and code ugliness)).
+ */
+
+ Tcl_IncrRefCount(ret);
Tcl_DecrRefCount(lobj);
+ ret->refCount--;
return ret;
}
@@ -1105,10 +809,10 @@ Tcl_FSJoinToPath(basePtr, objc, objv)
*
* TclpNativeJoinPath --
*
- * 'prefix' is absolute, 'joining' is relative to prefix.
+ * 'prefix' is absolute, 'joining' is relative to prefix.
*
* Results:
- * modifies prefix
+ * modifies prefix
*
* Side effects:
* None.
@@ -1117,28 +821,26 @@ Tcl_FSJoinToPath(basePtr, objc, objv)
*/
void
-TclpNativeJoinPath(prefix, joining)
- Tcl_Obj *prefix;
- char* joining;
+TclpNativeJoinPath(
+ Tcl_Obj *prefix,
+ char *joining)
{
int length, needsSep;
char *dest, *p, *start;
-
+
start = Tcl_GetStringFromObj(prefix, &length);
/*
- * Remove the ./ from tilde prefixed elements, and drive-letter
- * prefixed elements on Windows, unless it is the first component.
+ * Remove the ./ from tilde prefixed elements, and drive-letter prefixed
+ * elements on Windows, unless it is the first component.
*/
-
+
p = joining;
-
+
if (length != 0) {
- if ((p[0] == '.') && (p[1] == '/')
- && ((p[2] == '~')
- || ((tclPlatform == TCL_PLATFORM_WINDOWS)
- && isalpha(UCHAR(p[2]))
- && (p[3] == ':')))) {
+ if ((p[0] == '.') && (p[1] == '/') && ((p[2] == '~')
+ || (tclPlatform==TCL_PLATFORM_WINDOWS && isalpha(UCHAR(p[2]))
+ && (p[3] == ':')))) {
p += 2;
}
}
@@ -1147,159 +849,75 @@ TclpNativeJoinPath(prefix, joining)
}
switch (tclPlatform) {
- case TCL_PLATFORM_UNIX:
- /*
- * Append a separator if needed.
- */
+ case TCL_PLATFORM_UNIX:
+ /*
+ * Append a separator if needed.
+ */
- if (length > 0 && (start[length-1] != '/')) {
- Tcl_AppendToObj(prefix, "/", 1);
- length++;
- }
- needsSep = 0;
-
- /*
- * Append the element, eliminating duplicate and trailing
- * slashes.
- */
+ if (length > 0 && (start[length-1] != '/')) {
+ Tcl_AppendToObj(prefix, "/", 1);
+ length++;
+ }
+ needsSep = 0;
- Tcl_SetObjLength(prefix, length + (int) strlen(p));
-
- dest = Tcl_GetString(prefix) + length;
- for (; *p != '\0'; p++) {
- if (*p == '/') {
- while (p[1] == '/') {
- p++;
- }
- if (p[1] != '\0') {
- if (needsSep) {
- *dest++ = '/';
- }
- }
- } else {
- *dest++ = *p;
- needsSep = 1;
+ /*
+ * Append the element, eliminating duplicate and trailing slashes.
+ */
+
+ Tcl_SetObjLength(prefix, length + (int) strlen(p));
+
+ dest = Tcl_GetString(prefix) + length;
+ for (; *p != '\0'; p++) {
+ if (*p == '/') {
+ while (p[1] == '/') {
+ p++;
+ }
+ if (p[1] != '\0' && needsSep) {
+ *dest++ = '/';
}
+ } else {
+ *dest++ = *p;
+ needsSep = 1;
}
- length = dest - Tcl_GetString(prefix);
- Tcl_SetObjLength(prefix, length);
- break;
+ }
+ length = dest - Tcl_GetString(prefix);
+ Tcl_SetObjLength(prefix, length);
+ break;
- case TCL_PLATFORM_WINDOWS:
- /*
- * Check to see if we need to append a separator.
- */
+ case TCL_PLATFORM_WINDOWS:
+ /*
+ * Check to see if we need to append a separator.
+ */
- if ((length > 0) &&
+ if ((length > 0) &&
(start[length-1] != '/') && (start[length-1] != ':')) {
- Tcl_AppendToObj(prefix, "/", 1);
- length++;
- }
- needsSep = 0;
-
- /*
- * Append the element, eliminating duplicate and
- * trailing slashes.
- */
-
- Tcl_SetObjLength(prefix, length + (int) strlen(p));
- dest = Tcl_GetString(prefix) + length;
- for (; *p != '\0'; p++) {
- if ((*p == '/') || (*p == '\\')) {
- while ((p[1] == '/') || (p[1] == '\\')) {
- p++;
- }
- if ((p[1] != '\0') && needsSep) {
- *dest++ = '/';
- }
- } else {
- *dest++ = *p;
- needsSep = 1;
- }
- }
- length = dest - Tcl_GetString(prefix);
- Tcl_SetObjLength(prefix, length);
- break;
+ Tcl_AppendToObj(prefix, "/", 1);
+ length++;
+ }
+ needsSep = 0;
- case TCL_PLATFORM_MAC: {
- int newLength;
-
- /*
- * Sort out separators. We basically add the object we've
- * been given, but we have to make sure that there is
- * exactly one separator inbetween (unless the object we're
- * adding contains multiple contiguous colons, all of which
- * we must add). Also if an object is just ':' we don't
- * bother to add it unless it's the very first element.
- */
+ /*
+ * Append the element, eliminating duplicate and trailing slashes.
+ */
-#ifdef MAC_UNDERSTANDS_UNIX_PATHS
- int adjustedPath = 0;
- if ((strchr(p, ':') == NULL) && (strchr(p, '/') != NULL)) {
- char *start = p;
- adjustedPath = 1;
- while (*start != '\0') {
- if (*start == '/') {
- *start = ':';
- }
- start++;
- }
- }
-#endif
- if (length > 0) {
- if ((p[0] == ':') && (p[1] == '\0')) {
- return;
- }
- if (start[length-1] != ':') {
- if (*p != '\0' && *p != ':') {
- Tcl_AppendToObj(prefix, ":", 1);
- length++;
- }
- } else if (*p == ':') {
+ Tcl_SetObjLength(prefix, length + (int) strlen(p));
+ dest = Tcl_GetString(prefix) + length;
+ for (; *p != '\0'; p++) {
+ if ((*p == '/') || (*p == '\\')) {
+ while ((p[1] == '/') || (p[1] == '\\')) {
p++;
}
- } else {
- if (*p != '\0' && *p != ':') {
- Tcl_AppendToObj(prefix, ":", 1);
- length++;
- }
- }
-
- /*
- * Append the element
- */
-
- newLength = strlen(p);
- /*
- * It may not be good to just do 'Tcl_AppendToObj(prefix,
- * p, newLength)' because the object may contain duplicate
- * colons which we want to get rid of.
- */
- Tcl_AppendToObj(prefix, p, newLength);
-
- /* Remove spurious trailing single ':' */
- dest = Tcl_GetString(prefix) + length + newLength;
- if (*(dest-1) == ':') {
- if (dest-1 > Tcl_GetString(prefix)) {
- if (*(dest-2) != ':') {
- Tcl_SetObjLength(prefix, length + newLength -1);
- }
- }
- }
-#ifdef MAC_UNDERSTANDS_UNIX_PATHS
- /* Revert the path to what it was */
- if (adjustedPath) {
- char *start = joining;
- while (*start != '\0') {
- if (*start == ':') {
- *start = '/';
- }
- start++;
+ if ((p[1] != '\0') && needsSep) {
+ *dest++ = '/';
}
+ } else {
+ *dest++ = *p;
+ needsSep = 1;
}
-#endif
- break;
}
+ length = dest - Tcl_GetString(prefix);
+ Tcl_SetObjLength(prefix, length);
+ break;
}
return;
}
@@ -1309,14 +927,13 @@ TclpNativeJoinPath(prefix, joining)
*
* Tcl_JoinPath --
*
- * Combine a list of paths in a platform specific manner. The
- * function 'Tcl_FSJoinPath' should be used in preference where
- * possible.
+ * Combine a list of paths in a platform specific manner. The function
+ * 'Tcl_FSJoinPath' should be used in preference where possible.
*
* Results:
- * Appends the joined path to the end of the specified
- * Tcl_DString returning a pointer to the resulting string. Note
- * that the Tcl_DString must already be initialized.
+ * Appends the joined path to the end of the specified Tcl_DString
+ * returning a pointer to the resulting string. Note that the
+ * Tcl_DString must already be initialized.
*
* Side effects:
* Modifies the Tcl_DString.
@@ -1325,34 +942,46 @@ TclpNativeJoinPath(prefix, joining)
*/
char *
-Tcl_JoinPath(argc, argv, resultPtr)
- int argc;
- CONST char * CONST *argv;
- Tcl_DString *resultPtr; /* Pointer to previously initialized DString */
+Tcl_JoinPath(
+ int argc,
+ const char *const *argv,
+ Tcl_DString *resultPtr) /* Pointer to previously initialized DString */
{
int i, len;
Tcl_Obj *listObj = Tcl_NewObj();
Tcl_Obj *resultObj;
char *resultStr;
- /* Build the list of paths */
+ /*
+ * Build the list of paths.
+ */
+
for (i = 0; i < argc; i++) {
- Tcl_ListObjAppendElement(NULL, listObj,
+ Tcl_ListObjAppendElement(NULL, listObj,
Tcl_NewStringObj(argv[i], -1));
}
- /* Ask the objectified code to join the paths */
+ /*
+ * Ask the objectified code to join the paths.
+ */
+
Tcl_IncrRefCount(listObj);
resultObj = Tcl_FSJoinPath(listObj, argc);
Tcl_IncrRefCount(resultObj);
Tcl_DecrRefCount(listObj);
- /* Store the result */
+ /*
+ * Store the result.
+ */
+
resultStr = Tcl_GetStringFromObj(resultObj, &len);
Tcl_DStringAppend(resultPtr, resultStr, len);
Tcl_DecrRefCount(resultObj);
- /* Return a pointer to the result */
+ /*
+ * Return a pointer to the result.
+ */
+
return Tcl_DStringValue(resultPtr);
}
@@ -1362,19 +991,19 @@ Tcl_JoinPath(argc, argv, resultPtr)
* Tcl_TranslateFileName --
*
* Converts a file name into a form usable by the native system
- * interfaces. If the name starts with a tilde, it will produce a
- * name where the tilde and following characters have been replaced
- * by the home directory location for the named user.
+ * interfaces. If the name starts with a tilde, it will produce a name
+ * where the tilde and following characters have been replaced by the
+ * home directory location for the named user.
*
* Results:
- * The return value is a pointer to a string containing the name
- * after tilde substitution. If there was no tilde substitution,
- * the return value is a pointer to a copy of the original string.
- * If there was an error in processing the name, then an error
- * message is left in the interp's result (if interp was not NULL)
- * and the return value is NULL. Space for the return value is
- * allocated in bufferPtr; the caller must call Tcl_DStringFree()
- * to free the space if the return value was not NULL.
+ * The return value is a pointer to a string containing the name after
+ * tilde substitution. If there was no tilde substitution, the return
+ * value is a pointer to a copy of the original string. If there was an
+ * error in processing the name, then an error message is left in the
+ * interp's result (if interp was not NULL) and the return value is NULL.
+ * Space for the return value is allocated in bufferPtr; the caller must
+ * call Tcl_DStringFree() to free the space if the return value was not
+ * NULL.
*
* Side effects:
* None.
@@ -1383,15 +1012,15 @@ Tcl_JoinPath(argc, argv, resultPtr)
*/
char *
-Tcl_TranslateFileName(interp, name, bufferPtr)
- Tcl_Interp *interp; /* Interpreter in which to store error
- * message (if necessary). */
- CONST char *name; /* File name, which may begin with "~" (to
+Tcl_TranslateFileName(
+ Tcl_Interp *interp, /* Interpreter in which to store error message
+ * (if necessary). */
+ const char *name, /* File name, which may begin with "~" (to
* indicate current user's home directory) or
* "~<user>" (to indicate any user's home
* directory). */
- Tcl_DString *bufferPtr; /* Uninitialized or free DString filled
- * with name after tilde substitution. */
+ Tcl_DString *bufferPtr) /* Uninitialized or free DString filled with
+ * name after tilde substitution. */
{
Tcl_Obj *path = Tcl_NewStringObj(name, -1);
Tcl_Obj *transPtr;
@@ -1402,15 +1031,15 @@ Tcl_TranslateFileName(interp, name, bufferPtr)
Tcl_DecrRefCount(path);
return NULL;
}
-
+
Tcl_DStringInit(bufferPtr);
Tcl_DStringAppend(bufferPtr, Tcl_GetString(transPtr), -1);
Tcl_DecrRefCount(path);
Tcl_DecrRefCount(transPtr);
-
+
/*
- * Convert forward slashes to backslashes in Windows paths because
- * some system interfaces don't accept forward slashes.
+ * Convert forward slashes to backslashes in Windows paths because some
+ * system interfaces don't accept forward slashes.
*/
if (tclPlatform == TCL_PLATFORM_WINDOWS) {
@@ -1421,6 +1050,7 @@ Tcl_TranslateFileName(interp, name, bufferPtr)
}
}
}
+
return Tcl_DStringValue(bufferPtr);
}
@@ -1429,12 +1059,12 @@ Tcl_TranslateFileName(interp, name, bufferPtr)
*
* TclGetExtension --
*
- * This function returns a pointer to the beginning of the
- * extension part of a file name.
+ * This function returns a pointer to the beginning of the extension part
+ * of a file name.
*
* Results:
* Returns a pointer into name which indicates where the extension
- * starts. If there is no extension, returns NULL.
+ * starts. If there is no extension, returns NULL.
*
* Side effects:
* None.
@@ -1442,11 +1072,11 @@ Tcl_TranslateFileName(interp, name, bufferPtr)
*----------------------------------------------------------------------
*/
-char *
-TclGetExtension(name)
- char *name; /* File name to parse. */
+const char *
+TclGetExtension(
+ const char *name) /* File name to parse. */
{
- char *p, *lastSep;
+ const char *p, *lastSep;
/*
* First find the last directory separator.
@@ -1454,30 +1084,18 @@ TclGetExtension(name)
lastSep = NULL; /* Needed only to prevent gcc warnings. */
switch (tclPlatform) {
- case TCL_PLATFORM_UNIX:
- lastSep = strrchr(name, '/');
- break;
-
- case TCL_PLATFORM_MAC:
-#ifdef MAC_UNDERSTANDS_UNIX_PATHS
- if (strchr(name, ':') == NULL) {
- lastSep = strrchr(name, '/');
- } else {
- lastSep = strrchr(name, ':');
+ case TCL_PLATFORM_UNIX:
+ lastSep = strrchr(name, '/');
+ break;
+
+ case TCL_PLATFORM_WINDOWS:
+ lastSep = NULL;
+ for (p = name; *p != '\0'; p++) {
+ if (strchr("/\\:", *p) != NULL) {
+ lastSep = p;
}
-#else
- lastSep = strrchr(name, ':');
-#endif
- break;
-
- case TCL_PLATFORM_WINDOWS:
- lastSep = NULL;
- for (p = name; *p != '\0'; p++) {
- if (strchr("/\\:", *p) != NULL) {
- lastSep = p;
- }
- }
- break;
+ }
+ break;
}
p = strrchr(name, '.');
if ((p != NULL) && (lastSep != NULL) && (lastSep > p)) {
@@ -1486,7 +1104,7 @@ TclGetExtension(name)
/*
* In earlier versions, we used to back up to the first period in a series
- * so that "foo..o" would be split into "foo" and "..o". This is a
+ * so that "foo..o" would be split into "foo" and "..o". This is a
* confusing and usually incorrect behavior, so now we split at the last
* period in the name.
*/
@@ -1504,11 +1122,10 @@ TclGetExtension(name)
*
* Results:
* The result is a pointer to a static string containing the home
- * directory in native format. If there was an error in processing
- * the substitution, then an error message is left in the interp's
- * result and the return value is NULL. On success, the results
- * are appended to resultPtr, and the contents of resultPtr are
- * returned.
+ * directory in native format. If there was an error in processing the
+ * substitution, then an error message is left in the interp's result and
+ * the return value is NULL. On success, the results are appended to
+ * resultPtr, and the contents of resultPtr are returned.
*
* Side effects:
* Information may be left in resultPtr.
@@ -1516,40 +1133,38 @@ TclGetExtension(name)
*----------------------------------------------------------------------
*/
-static CONST char *
-DoTildeSubst(interp, user, resultPtr)
- Tcl_Interp *interp; /* Interpreter in which to store error
- * message (if necessary). */
- CONST char *user; /* Name of user whose home directory should be
+static const char *
+DoTildeSubst(
+ Tcl_Interp *interp, /* Interpreter in which to store error message
+ * (if necessary). */
+ const char *user, /* Name of user whose home directory should be
* substituted, or "" for current user. */
- Tcl_DString *resultPtr; /* Initialized DString filled with name
- * after tilde substitution. */
+ Tcl_DString *resultPtr) /* Initialized DString filled with name after
+ * tilde substitution. */
{
- CONST char *dir;
+ const char *dir;
if (*user == '\0') {
Tcl_DString dirString;
-
+
dir = TclGetEnv("HOME", &dirString);
if (dir == NULL) {
if (interp) {
Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "couldn't find HOME environment ",
- "variable to expand path", (char *) NULL);
+ Tcl_AppendResult(interp, "couldn't find HOME environment "
+ "variable to expand path", NULL);
}
return NULL;
}
Tcl_JoinPath(1, &dir, resultPtr);
Tcl_DStringFree(&dirString);
- } else {
- if (TclpGetUserHome(user, resultPtr) == NULL) {
- if (interp) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "user \"", user, "\" doesn't exist",
- (char *) NULL);
- }
- return NULL;
+ } else if (TclpGetUserHome(user, resultPtr) == NULL) {
+ if (interp) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "user \"", user, "\" doesn't exist",
+ NULL);
}
+ return NULL;
}
return Tcl_DStringValue(resultPtr);
}
@@ -1559,8 +1174,8 @@ DoTildeSubst(interp, user, resultPtr)
*
* Tcl_GlobObjCmd --
*
- * This procedure is invoked to process the "glob" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "glob" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -1573,23 +1188,24 @@ DoTildeSubst(interp, user, resultPtr)
/* ARGSUSED */
int
-Tcl_GlobObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_GlobObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
int index, i, globFlags, length, join, dir, result;
- char *string, *separators;
+ char *string;
+ const char *separators;
Tcl_Obj *typePtr, *resultPtr, *look;
Tcl_Obj *pathOrDir = NULL;
Tcl_DString prefix;
- static CONST char *options[] = {
- "-directory", "-join", "-nocomplain", "-path", "-tails",
+ static const char *options[] = {
+ "-directory", "-join", "-nocomplain", "-path", "-tails",
"-types", "--", NULL
};
enum options {
- GLOB_DIR, GLOB_JOIN, GLOB_NOCOMPLAIN, GLOB_PATH, GLOB_TAILS,
+ GLOB_DIR, GLOB_JOIN, GLOB_NOCOMPLAIN, GLOB_PATH, GLOB_TAILS,
GLOB_TYPE, GLOB_LAST
};
enum pathDirOptions {PATH_NONE = -1 , PATH_GENERAL = 0, PATH_DIR = 1};
@@ -1600,108 +1216,108 @@ Tcl_GlobObjCmd(dummy, interp, objc, objv)
dir = PATH_NONE;
typePtr = NULL;
for (i = 1; i < objc; i++) {
- if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0, &index)
- != TCL_OK) {
+ if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
+ &index) != TCL_OK) {
string = Tcl_GetStringFromObj(objv[i], &length);
if (string[0] == '-') {
/*
- * It looks like the command contains an option so signal
- * an error
+ * It looks like the command contains an option so signal an
+ * error.
*/
+
return TCL_ERROR;
} else {
/*
- * This clearly isn't an option; assume it's the first
- * glob pattern. We must clear the error
+ * This clearly isn't an option; assume it's the first glob
+ * pattern. We must clear the error.
*/
+
Tcl_ResetResult(interp);
break;
}
}
+
switch (index) {
- case GLOB_NOCOMPLAIN: /* -nocomplain */
- globFlags |= TCL_GLOBMODE_NO_COMPLAIN;
- break;
- case GLOB_DIR: /* -dir */
- if (i == (objc-1)) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "missing argument to \"-directory\"", -1));
- return TCL_ERROR;
- }
- if (dir != PATH_NONE) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "\"-directory\" cannot be used with \"-path\"",
- -1));
- return TCL_ERROR;
- }
- dir = PATH_DIR;
- globFlags |= TCL_GLOBMODE_DIR;
- pathOrDir = objv[i+1];
- i++;
- break;
- case GLOB_JOIN: /* -join */
- join = 1;
- break;
- case GLOB_TAILS: /* -tails */
- globFlags |= TCL_GLOBMODE_TAILS;
- break;
- case GLOB_PATH: /* -path */
- if (i == (objc-1)) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "missing argument to \"-path\"", -1));
- return TCL_ERROR;
- }
- if (dir != PATH_NONE) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "\"-path\" cannot be used with \"-directory\"",
- -1));
- return TCL_ERROR;
- }
- dir = PATH_GENERAL;
- pathOrDir = objv[i+1];
- i++;
- break;
- case GLOB_TYPE: /* -types */
- if (i == (objc-1)) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "missing argument to \"-types\"", -1));
- return TCL_ERROR;
- }
- typePtr = objv[i+1];
- if (Tcl_ListObjLength(interp, typePtr, &length) != TCL_OK) {
- return TCL_ERROR;
- }
- i++;
- break;
- case GLOB_LAST: /* -- */
- i++;
- goto endOfForLoop;
+ case GLOB_NOCOMPLAIN: /* -nocomplain */
+ globFlags |= TCL_GLOBMODE_NO_COMPLAIN;
+ break;
+ case GLOB_DIR: /* -dir */
+ if (i == (objc-1)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "missing argument to \"-directory\"", -1));
+ return TCL_ERROR;
+ }
+ if (dir != PATH_NONE) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\"-directory\" cannot be used with \"-path\"", -1));
+ return TCL_ERROR;
+ }
+ dir = PATH_DIR;
+ globFlags |= TCL_GLOBMODE_DIR;
+ pathOrDir = objv[i+1];
+ i++;
+ break;
+ case GLOB_JOIN: /* -join */
+ join = 1;
+ break;
+ case GLOB_TAILS: /* -tails */
+ globFlags |= TCL_GLOBMODE_TAILS;
+ break;
+ case GLOB_PATH: /* -path */
+ if (i == (objc-1)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "missing argument to \"-path\"", -1));
+ return TCL_ERROR;
+ }
+ if (dir != PATH_NONE) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\"-path\" cannot be used with \"-directory\"", -1));
+ return TCL_ERROR;
+ }
+ dir = PATH_GENERAL;
+ pathOrDir = objv[i+1];
+ i++;
+ break;
+ case GLOB_TYPE: /* -types */
+ if (i == (objc-1)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "missing argument to \"-types\"", -1));
+ return TCL_ERROR;
+ }
+ typePtr = objv[i+1];
+ if (Tcl_ListObjLength(interp, typePtr, &length) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ i++;
+ break;
+ case GLOB_LAST: /* -- */
+ i++;
+ goto endOfForLoop;
}
}
- endOfForLoop:
+
+ endOfForLoop:
if (objc - i < 1) {
- Tcl_WrongNumArgs(interp, 1, objv, "?switches? name ?name ...?");
+ Tcl_WrongNumArgs(interp, 1, objv, "?switches? name ?name ...?");
return TCL_ERROR;
}
if ((globFlags & TCL_GLOBMODE_TAILS) && (pathOrDir == NULL)) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "\"-tails\" must be used with either \"-directory\" or \"-path\"",
- -1));
+ Tcl_AppendResult(interp,
+ "\"-tails\" must be used with either "
+ "\"-directory\" or \"-path\"", NULL);
return TCL_ERROR;
}
-
+
separators = NULL; /* lint. */
switch (tclPlatform) {
- case TCL_PLATFORM_UNIX:
- separators = "/";
- break;
- case TCL_PLATFORM_WINDOWS:
- separators = "/\\:";
- break;
- case TCL_PLATFORM_MAC:
- separators = ":";
- break;
+ case TCL_PLATFORM_UNIX:
+ separators = "/";
+ break;
+ case TCL_PLATFORM_WINDOWS:
+ separators = "/\\:";
+ break;
}
+
if (dir == PATH_GENERAL) {
int pathlength;
char *last;
@@ -1710,49 +1326,70 @@ Tcl_GlobObjCmd(dummy, interp, objc, objv)
/*
* Find the last path separator in the path
*/
+
last = first + pathlength;
for (; last != first; last--) {
if (strchr(separators, *(last-1)) != NULL) {
break;
}
}
+
if (last == first + pathlength) {
- /* It's really a directory */
+ /*
+ * It's really a directory.
+ */
+
dir = PATH_DIR;
+
} else {
Tcl_DString pref;
char *search, *find;
Tcl_DStringInit(&pref);
if (last == first) {
- /* The whole thing is a prefix */
+ /*
+ * The whole thing is a prefix. This means we must remove any
+ * 'tails' flag too, since it is irrelevant now (the same
+ * effect will happen without it), but in particular its use
+ * in TclGlob requires a non-NULL pathOrDir.
+ */
+
Tcl_DStringAppend(&pref, first, -1);
+ globFlags &= ~TCL_GLOBMODE_TAILS;
pathOrDir = NULL;
} else {
- /* Have to split off the end */
+ /*
+ * Have to split off the end.
+ */
+
Tcl_DStringAppend(&pref, last, first+pathlength-last);
pathOrDir = Tcl_NewStringObj(first, last-first-1);
- /*
- * We must ensure that we haven't cut off too much,
- * and turned a valid path like '/' or 'C:/' into
- * an incorrect path like '' or 'C:'. The way we
- * do this is to add a separator if there are none
- * presently in the prefix.
+
+ /*
+ * We must ensure that we haven't cut off too much, and turned
+ * a valid path like '/' or 'C:/' into an incorrect path like
+ * '' or 'C:'. The way we do this is to add a separator if
+ * there are none presently in the prefix.
*/
+
if (strpbrk(Tcl_GetString(pathOrDir), "\\/") == NULL) {
- Tcl_AppendToObj(pathOrDir, last-1, 1);
+ Tcl_AppendToObj(pathOrDir, last-1, 1);
}
}
- /* Need to quote 'prefix' */
+
+ /*
+ * Need to quote 'prefix'.
+ */
+
Tcl_DStringInit(&prefix);
search = Tcl_DStringValue(&pref);
while ((find = (strpbrk(search, "\\[]*?{}"))) != NULL) {
- Tcl_DStringAppend(&prefix, search, find-search);
- Tcl_DStringAppend(&prefix, "\\", 1);
- Tcl_DStringAppend(&prefix, find, 1);
- search = find+1;
- if (*search == '\0') {
- break;
- }
+ Tcl_DStringAppend(&prefix, search, find-search);
+ Tcl_DStringAppend(&prefix, "\\", 1);
+ Tcl_DStringAppend(&prefix, find, 1);
+ search = find+1;
+ if (*search == '\0') {
+ break;
+ }
}
if (*search != '\0') {
Tcl_DStringAppend(&prefix, search, -1);
@@ -1760,29 +1397,33 @@ Tcl_GlobObjCmd(dummy, interp, objc, objv)
Tcl_DStringFree(&pref);
}
}
-
+
if (pathOrDir != NULL) {
Tcl_IncrRefCount(pathOrDir);
}
-
+
if (typePtr != NULL) {
- /*
- * The rest of the possible type arguments (except 'd') are
- * platform specific. We don't complain when they are used
- * on an incompatible platform.
+ /*
+ * The rest of the possible type arguments (except 'd') are platform
+ * specific. We don't complain when they are used on an incompatible
+ * platform.
*/
+
Tcl_ListObjLength(interp, typePtr, &length);
if (length <= 0) {
goto skipTypes;
}
- globTypes = (Tcl_GlobTypeData*) ckalloc(sizeof(Tcl_GlobTypeData));
+ globTypes = (Tcl_GlobTypeData*)
+ TclStackAlloc(interp,sizeof(Tcl_GlobTypeData));
globTypes->type = 0;
globTypes->perm = 0;
globTypes->macType = NULL;
globTypes->macCreator = NULL;
- while(--length >= 0) {
+
+ while (--length >= 0) {
int len;
char *str;
+
Tcl_ListObjIndex(interp, typePtr, length, &look);
str = Tcl_GetStringFromObj(look, &len);
if (strcmp("readonly", str) == 0) {
@@ -1791,48 +1432,54 @@ Tcl_GlobObjCmd(dummy, interp, objc, objv)
globTypes->perm |= TCL_GLOB_PERM_HIDDEN;
} else if (len == 1) {
switch (str[0]) {
- case 'r':
+ case 'r':
globTypes->perm |= TCL_GLOB_PERM_R;
break;
- case 'w':
+ case 'w':
globTypes->perm |= TCL_GLOB_PERM_W;
break;
- case 'x':
+ case 'x':
globTypes->perm |= TCL_GLOB_PERM_X;
break;
- case 'b':
+ case 'b':
globTypes->type |= TCL_GLOB_TYPE_BLOCK;
break;
- case 'c':
+ case 'c':
globTypes->type |= TCL_GLOB_TYPE_CHAR;
break;
- case 'd':
+ case 'd':
globTypes->type |= TCL_GLOB_TYPE_DIR;
break;
- case 'p':
+ case 'p':
globTypes->type |= TCL_GLOB_TYPE_PIPE;
break;
- case 'f':
+ case 'f':
globTypes->type |= TCL_GLOB_TYPE_FILE;
break;
- case 'l':
+ case 'l':
globTypes->type |= TCL_GLOB_TYPE_LINK;
break;
- case 's':
+ case 's':
globTypes->type |= TCL_GLOB_TYPE_SOCK;
break;
- default:
+ default:
goto badTypesArg;
}
+
} else if (len == 4) {
- /* This is assumed to be a MacOS file type */
+ /*
+ * This is assumed to be a MacOS file type.
+ */
+
if (globTypes->macType != NULL) {
goto badMacTypesArg;
}
globTypes->macType = look;
Tcl_IncrRefCount(look);
+
} else {
Tcl_Obj* item;
+
if ((Tcl_ListObjLength(NULL, look, &len) == TCL_OK) &&
(len == 3)) {
Tcl_ListObjIndex(interp, look, 0, &item);
@@ -1857,22 +1504,25 @@ Tcl_GlobObjCmd(dummy, interp, objc, objv)
}
}
}
+
/*
- * Error cases. We reset
- * the 'join' flag to zero, since we haven't yet
- * made use of it.
+ * Error cases. We reset the 'join' flag to zero, since we
+ * haven't yet made use of it.
*/
- badTypesArg:
- resultPtr = Tcl_GetObjResult(interp);
+
+ badTypesArg:
+ TclNewObj(resultPtr);
Tcl_AppendToObj(resultPtr, "bad argument to \"-types\": ", -1);
Tcl_AppendObjToObj(resultPtr, look);
+ Tcl_SetObjResult(interp, resultPtr);
result = TCL_ERROR;
join = 0;
goto endOfGlob;
- badMacTypesArg:
+
+ badMacTypesArg:
Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "only one MacOS type or creator argument"
- " to \"-types\" allowed", -1));
+ "only one MacOS type or creator argument"
+ " to \"-types\" allowed", -1));
result = TCL_ERROR;
join = 0;
goto endOfGlob;
@@ -1881,15 +1531,16 @@ Tcl_GlobObjCmd(dummy, interp, objc, objv)
}
skipTypes:
- /*
- * Now we perform the actual glob below. This may involve joining
- * together the pattern arguments, dealing with particular file types
- * etc. We use a 'goto' to ensure we free any memory allocated along
- * the way.
+ /*
+ * Now we perform the actual glob below. This may involve joining together
+ * the pattern arguments, dealing with particular file types etc. We use a
+ * 'goto' to ensure we free any memory allocated along the way.
*/
+
objc -= i;
objv += i;
result = TCL_OK;
+
if (join) {
if (dir != PATH_GENERAL) {
Tcl_DStringInit(&prefix);
@@ -1901,66 +1552,70 @@ Tcl_GlobObjCmd(dummy, interp, objc, objv)
Tcl_DStringAppend(&prefix, separators, 1);
}
}
- if (TclGlob(interp, Tcl_DStringValue(&prefix), pathOrDir,
- globFlags, globTypes) != TCL_OK) {
+ if (TclGlob(interp, Tcl_DStringValue(&prefix), pathOrDir, globFlags,
+ globTypes) != TCL_OK) {
result = TCL_ERROR;
goto endOfGlob;
}
- } else {
- if (dir == PATH_GENERAL) {
- Tcl_DString str;
- for (i = 0; i < objc; i++) {
- Tcl_DStringInit(&str);
- if (dir == PATH_GENERAL) {
- Tcl_DStringAppend(&str, Tcl_DStringValue(&prefix),
- Tcl_DStringLength(&prefix));
- }
- string = Tcl_GetStringFromObj(objv[i], &length);
- Tcl_DStringAppend(&str, string, length);
- if (TclGlob(interp, Tcl_DStringValue(&str), pathOrDir,
- globFlags, globTypes) != TCL_OK) {
- result = TCL_ERROR;
- Tcl_DStringFree(&str);
- goto endOfGlob;
- }
+ } else if (dir == PATH_GENERAL) {
+ Tcl_DString str;
+
+ for (i = 0; i < objc; i++) {
+ Tcl_DStringInit(&str);
+ if (dir == PATH_GENERAL) {
+ Tcl_DStringAppend(&str, Tcl_DStringValue(&prefix),
+ Tcl_DStringLength(&prefix));
}
- Tcl_DStringFree(&str);
- } else {
- for (i = 0; i < objc; i++) {
- string = Tcl_GetString(objv[i]);
- if (TclGlob(interp, string, pathOrDir,
- globFlags, globTypes) != TCL_OK) {
- result = TCL_ERROR;
- goto endOfGlob;
- }
+ string = Tcl_GetStringFromObj(objv[i], &length);
+ Tcl_DStringAppend(&str, string, length);
+ if (TclGlob(interp, Tcl_DStringValue(&str), pathOrDir, globFlags,
+ globTypes) != TCL_OK) {
+ result = TCL_ERROR;
+ Tcl_DStringFree(&str);
+ goto endOfGlob;
+ }
+ }
+ Tcl_DStringFree(&str);
+ } else {
+ for (i = 0; i < objc; i++) {
+ string = Tcl_GetString(objv[i]);
+ if (TclGlob(interp, string, pathOrDir, globFlags,
+ globTypes) != TCL_OK) {
+ result = TCL_ERROR;
+ goto endOfGlob;
}
}
}
+
if ((globFlags & TCL_GLOBMODE_NO_COMPLAIN) == 0) {
if (Tcl_ListObjLength(interp, Tcl_GetObjResult(interp),
&length) != TCL_OK) {
- /* This should never happen. Maybe we should be more dramatic */
+ /*
+ * This should never happen. Maybe we should be more dramatic.
+ */
+
result = TCL_ERROR;
goto endOfGlob;
}
+
if (length == 0) {
Tcl_AppendResult(interp, "no files matched glob pattern",
- (join || (objc == 1)) ? " \"" : "s \"", (char *) NULL);
+ (join || (objc == 1)) ? " \"" : "s \"", NULL);
if (join) {
- Tcl_AppendResult(interp, Tcl_DStringValue(&prefix),
- (char *) NULL);
+ Tcl_AppendResult(interp, Tcl_DStringValue(&prefix), NULL);
} else {
- char *sep = "";
+ const char *sep = "";
for (i = 0; i < objc; i++) {
string = Tcl_GetString(objv[i]);
- Tcl_AppendResult(interp, sep, string, (char *) NULL);
+ Tcl_AppendResult(interp, sep, string, NULL);
sep = " ";
}
}
- Tcl_AppendResult(interp, "\"", (char *) NULL);
+ Tcl_AppendResult(interp, "\"", NULL);
result = TCL_ERROR;
}
}
+
endOfGlob:
if (join || (dir == PATH_GENERAL)) {
Tcl_DStringFree(&prefix);
@@ -1975,7 +1630,7 @@ Tcl_GlobObjCmd(dummy, interp, objc, objv)
if (globTypes->macCreator != NULL) {
Tcl_DecrRefCount(globTypes->macCreator);
}
- ckfree((char *) globTypes);
+ TclStackFree(interp, globTypes);
}
return result;
}
@@ -1985,24 +1640,24 @@ Tcl_GlobObjCmd(dummy, interp, objc, objv)
*
* TclGlob --
*
- * This procedure prepares arguments for the TclDoGlob call.
- * It sets the separator string based on the platform, performs
- * tilde substitution, and calls TclDoGlob.
- *
- * The interpreter's result, on entry to this function, must
- * be a valid Tcl list (e.g. it could be empty), since we will
- * lappend any new results to that list. If it is not a valid
- * list, this function will fail to do anything very meaningful.
+ * This procedure prepares arguments for the DoGlob call. It sets the
+ * separator string based on the platform, performs * tilde substitution,
+ * and calls DoGlob.
+ *
+ * The interpreter's result, on entry to this function, must be a valid
+ * Tcl list (e.g. it could be empty), since we will lappend any new
+ * results to that list. If it is not a valid list, this function will
+ * fail to do anything very meaningful.
+ *
+ * Note that if globFlags contains 'TCL_GLOBMODE_TAILS' then pathPrefix
+ * cannot be NULL (it is only allowed with -dir or -path).
*
* Results:
- * The return value is a standard Tcl result indicating whether
- * an error occurred in globbing. After a normal return the
- * result in interp (set by TclDoGlob) holds all of the file names
- * given by the pattern and unquotedPrefix arguments. After an
- * error the result in interp will hold an error message, unless
- * the 'TCL_GLOBMODE_NO_COMPLAIN' flag was given, in which case
- * an error results in a TCL_OK return leaving the interpreter's
- * result unmodified.
+ * The return value is a standard Tcl result indicating whether an error
+ * occurred in globbing. After a normal return the result in interp (set
+ * by DoGlob) holds all of the file names given by the pattern and
+ * pathPrefix arguments. After an error the result in interp will hold
+ * an error message.
*
* Side effects:
* The 'pattern' is written to.
@@ -2012,216 +1667,347 @@ Tcl_GlobObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-TclGlob(interp, pattern, unquotedPrefix, globFlags, types)
- Tcl_Interp *interp; /* Interpreter for returning error message
- * or appending list of matching file names. */
- char *pattern; /* Glob pattern to match. Must not refer
- * to a static string. */
- Tcl_Obj *unquotedPrefix; /* Prefix to glob pattern, if non-null, which
- * is considered literally. */
- int globFlags; /* Stores or'ed combination of flags */
- Tcl_GlobTypeData *types; /* Struct containing acceptable types.
- * May be NULL. */
+TclGlob(
+ Tcl_Interp *interp, /* Interpreter for returning error message or
+ * appending list of matching file names. */
+ char *pattern, /* Glob pattern to match. Must not refer to a
+ * static string. */
+ Tcl_Obj *pathPrefix, /* Path prefix to glob pattern, if non-null,
+ * which is considered literally. */
+ int globFlags, /* Stores or'ed combination of flags */
+ Tcl_GlobTypeData *types) /* Struct containing acceptable types. May be
+ * NULL. */
{
- char *separators;
- CONST char *head;
+ const char *separators;
+ const char *head;
char *tail, *start;
- char c;
- int result, prefixLen;
- Tcl_DString buffer;
- Tcl_Obj *oldResult;
+ int result;
+ Tcl_Obj *filenamesObj, *savedResultObj;
separators = NULL; /* lint. */
switch (tclPlatform) {
- case TCL_PLATFORM_UNIX:
- separators = "/";
- break;
- case TCL_PLATFORM_WINDOWS:
- separators = "/\\:";
- break;
- case TCL_PLATFORM_MAC:
-#ifdef MAC_UNDERSTANDS_UNIX_PATHS
- if (unquotedPrefix == NULL) {
- separators = (strchr(pattern, ':') == NULL) ? "/" : ":";
- } else {
- separators = ":";
- }
-#else
- separators = ":";
-#endif
- break;
+ case TCL_PLATFORM_UNIX:
+ separators = "/";
+ break;
+ case TCL_PLATFORM_WINDOWS:
+ separators = "/\\:";
+ break;
}
- Tcl_DStringInit(&buffer);
- if (unquotedPrefix != NULL) {
- start = Tcl_GetString(unquotedPrefix);
- } else {
- start = pattern;
- }
+ if (pathPrefix == NULL) {
+ char c;
+ Tcl_DString buffer;
+ Tcl_DStringInit(&buffer);
- /*
- * Perform tilde substitution, if needed.
- */
+ start = pattern;
- if (start[0] == '~') {
-
/*
- * Find the first path separator after the tilde.
+ * Perform tilde substitution, if needed.
*/
- for (tail = start; *tail != '\0'; tail++) {
- if (*tail == '\\') {
- if (strchr(separators, tail[1]) != NULL) {
+
+ if (start[0] == '~') {
+ /*
+ * Find the first path separator after the tilde.
+ */
+
+ for (tail = start; *tail != '\0'; tail++) {
+ if (*tail == '\\') {
+ if (strchr(separators, tail[1]) != NULL) {
+ break;
+ }
+ } else if (strchr(separators, *tail) != NULL) {
break;
}
- } else if (strchr(separators, *tail) != NULL) {
- break;
}
- }
- /*
- * Determine the home directory for the specified user.
- */
-
- c = *tail;
- *tail = '\0';
- if (globFlags & TCL_GLOBMODE_NO_COMPLAIN) {
- /*
- * We will ignore any error message here, and we
- * don't want to mess up the interpreter's result.
+ /*
+ * Determine the home directory for the specified user.
*/
- head = DoTildeSubst(NULL, start+1, &buffer);
- } else {
+
+ c = *tail;
+ *tail = '\0';
head = DoTildeSubst(interp, start+1, &buffer);
- }
- *tail = c;
- if (head == NULL) {
- if (globFlags & TCL_GLOBMODE_NO_COMPLAIN) {
- return TCL_OK;
- } else {
+ *tail = c;
+ if (head == NULL) {
return TCL_ERROR;
}
- }
- if (head != Tcl_DStringValue(&buffer)) {
- Tcl_DStringAppend(&buffer, head, -1);
- }
- if (unquotedPrefix != NULL) {
- Tcl_DStringAppend(&buffer, tail, -1);
+ if (head != Tcl_DStringValue(&buffer)) {
+ Tcl_DStringAppend(&buffer, head, -1);
+ }
+ pathPrefix = Tcl_NewStringObj(Tcl_DStringValue(&buffer),
+ Tcl_DStringLength(&buffer));
+ Tcl_IncrRefCount(pathPrefix);
+ globFlags |= TCL_GLOBMODE_DIR;
+ if (c != '\0') {
+ tail++;
+ }
+ Tcl_DStringFree(&buffer);
+ } else {
tail = pattern;
}
} else {
+ Tcl_IncrRefCount(pathPrefix);
tail = pattern;
- if (unquotedPrefix != NULL) {
- Tcl_DStringAppend(&buffer,Tcl_GetString(unquotedPrefix),-1);
- }
}
-
- /*
- * We want to remember the length of the current prefix,
- * in case we are using TCL_GLOBMODE_TAILS. Also if we
- * are using TCL_GLOBMODE_DIR, we must make sure the
- * prefix ends in a directory separator.
+
+ /*
+ * Handling empty path prefixes with glob patterns like 'C:' or
+ * 'c:////////' is a pain on Windows if we leave it too late, since these
+ * aren't really patterns at all! We therefore check the head of the
+ * pattern now for such cases, if we don't have an unquoted prefix yet.
+ *
+ * Similarly on Unix with '/' at the head of the pattern -- it just
+ * indicates the root volume, so we treat it as such.
*/
- prefixLen = Tcl_DStringLength(&buffer);
-
- if (prefixLen > 0) {
- c = Tcl_DStringValue(&buffer)[prefixLen-1];
- if (strchr(separators, c) == NULL) {
- /*
- * If the prefix is a directory, make sure it ends in a
- * directory separator.
- */
- if (globFlags & TCL_GLOBMODE_DIR) {
- Tcl_DStringAppend(&buffer,separators,1);
- /* Try to borrow that separator from the tail */
- if (*tail == *separators) {
+
+ if (tclPlatform == TCL_PLATFORM_WINDOWS) {
+ if (pathPrefix == NULL && tail[0] != '\0' && tail[1] == ':') {
+ char *p = tail + 1;
+ pathPrefix = Tcl_NewStringObj(tail, 1);
+ while (*p != '\0') {
+ char c = p[1];
+ if (*p == '\\') {
+ if (strchr(separators, c) != NULL) {
+ if (c == '\\') {
+ c = '/';
+ }
+ Tcl_AppendToObj(pathPrefix, &c, 1);
+ p++;
+ } else {
+ break;
+ }
+ } else if (strchr(separators, *p) != NULL) {
+ Tcl_AppendToObj(pathPrefix, p, 1);
+ } else {
+ break;
+ }
+ p++;
+ }
+ tail = p;
+ Tcl_IncrRefCount(pathPrefix);
+ } else if (pathPrefix == NULL && (tail[0] == '/'
+ || (tail[0] == '\\' && tail[1] == '\\'))) {
+ int driveNameLen;
+ Tcl_Obj *driveName;
+ Tcl_Obj *temp = Tcl_NewStringObj(tail, -1);
+ Tcl_IncrRefCount(temp);
+
+ switch (TclGetPathType(temp, NULL, &driveNameLen, &driveName)) {
+ case TCL_PATH_VOLUME_RELATIVE: {
+ /*
+ * Volume relative path which is equivalent to a path in the
+ * root of the cwd's volume. We will actually return
+ * non-volume-relative paths here. i.e. 'glob /foo*' will
+ * return 'C:/foobar'. This is much the same as globbing for a
+ * path with '\\' will return one with '/' on Windows.
+ */
+
+ Tcl_Obj *cwd = Tcl_FSGetCwd(interp);
+
+ if (cwd == NULL) {
+ Tcl_DecrRefCount(temp);
+ return TCL_ERROR;
+ }
+ pathPrefix = Tcl_NewStringObj(Tcl_GetString(cwd), 3);
+ Tcl_DecrRefCount(cwd);
+ if (tail[0] == '/') {
tail++;
+ } else {
+ tail+=2;
}
+ Tcl_IncrRefCount(pathPrefix);
+ break;
}
- prefixLen++;
+ case TCL_PATH_ABSOLUTE:
+ /*
+ * Absolute, possibly network path //Machine/Share. Use that
+ * as the path prefix (it already has a refCount).
+ */
+
+ pathPrefix = driveName;
+ tail += driveNameLen;
+ break;
+ case TCL_PATH_RELATIVE:
+ /* Do nothing */
+ break;
+ }
+ Tcl_DecrRefCount(temp);
+ }
+
+ /*
+ * ':' no longer needed as a separator. It is only relevant to the
+ * beginning of the path.
+ */
+
+ separators = "/\\";
+
+ } else if (tclPlatform == TCL_PLATFORM_UNIX) {
+ if (pathPrefix == NULL && tail[0] == '/') {
+ pathPrefix = Tcl_NewStringObj(tail, 1);
+ tail++;
+ Tcl_IncrRefCount(pathPrefix);
}
}
- /*
- * We need to get the old result, in case it is over-written
- * below when we still need it.
+ /*
+ * Finally if we still haven't managed to generate a path prefix, check if
+ * the path starts with a current volume.
*/
- oldResult = Tcl_GetObjResult(interp);
- Tcl_IncrRefCount(oldResult);
+
+ if (pathPrefix == NULL) {
+ int driveNameLen;
+ Tcl_Obj *driveName;
+ if (TclFSNonnativePathType(tail, (int) strlen(tail), NULL,
+ &driveNameLen, &driveName) == TCL_PATH_ABSOLUTE) {
+ pathPrefix = driveName;
+ tail += driveNameLen;
+ }
+ }
+
+ /*
+ * To process a [glob] invokation, this function may be called multiple
+ * times. Each time, the previously discovered filenames are in the
+ * interpreter result. We stash that away here so the result is free for
+ * error messsages.
+ */
+
+ savedResultObj = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(savedResultObj);
Tcl_ResetResult(interp);
-
- result = TclDoGlob(interp, separators, &buffer, tail, types);
-
- if (result != TCL_OK) {
- if (globFlags & TCL_GLOBMODE_NO_COMPLAIN) {
- /* Put back the old result and reset the return code */
- Tcl_SetObjResult(interp, oldResult);
+ TclNewObj(filenamesObj);
+ Tcl_IncrRefCount(filenamesObj);
+
+ /*
+ * Now we do the actual globbing, adding filenames as we go to buffer in
+ * filenamesObj
+ */
+
+ if (*tail == '\0' && pathPrefix != NULL) {
+ /*
+ * An empty pattern. This means 'pathPrefix' is actually
+ * a full path of a file/directory we want to simply check
+ * for existence and type.
+ */
+ if (types == NULL) {
+ /*
+ * We just want to check for existence. In this case we
+ * make it easy on Tcl_FSMatchInDirectory and its
+ * sub-implementations by not bothering them (even though
+ * they should support this situation) and we just use the
+ * simple existence check with Tcl_FSAccess.
+ */
+ if (Tcl_FSAccess(pathPrefix, F_OK) == 0) {
+ Tcl_ListObjAppendElement(interp, filenamesObj, pathPrefix);
+ }
result = TCL_OK;
+ } else {
+ /*
+ * We want to check for the correct type. Tcl_FSMatchInDirectory
+ * is documented to do this for us, if we give it a NULL pattern.
+ */
+ result = Tcl_FSMatchInDirectory(interp, filenamesObj, pathPrefix,
+ NULL, types);
}
} else {
- /*
- * Now we must concatenate the 'oldResult' and the current
- * result, and then place that into the interpreter.
- *
- * If we only want the tails, we must strip off the prefix now.
- * It may seem more efficient to pass the tails flag down into
- * TclDoGlob, Tcl_FSMatchInDirectory, but those functions are
- * continually adjusting the prefix as the various pieces of
- * the pattern are assimilated, so that would add a lot of
- * complexity to the code. This way is a little slower (when
- * the -tails flag is given), but much simpler to code.
- */
+ result = DoGlob(interp, filenamesObj, separators, pathPrefix,
+ globFlags & TCL_GLOBMODE_DIR, tail, types);
+ }
+
+ /*
+ * Check for errors...
+ */
+
+ if (result != TCL_OK) {
+ TclDecrRefCount(filenamesObj);
+ TclDecrRefCount(savedResultObj);
+ if (pathPrefix != NULL) {
+ Tcl_DecrRefCount(pathPrefix);
+ }
+ return result;
+ }
+
+ /*
+ * If we only want the tails, we must strip off the prefix now. It may
+ * seem more efficient to pass the tails flag down into DoGlob,
+ * Tcl_FSMatchInDirectory, but those functions are continually adjusting
+ * the prefix as the various pieces of the pattern are assimilated, so
+ * that would add a lot of complexity to the code. This way is a little
+ * slower (when the -tails flag is given), but much simpler to code.
+ *
+ * We do it by rewriting the result list in-place.
+ */
+
+ if (globFlags & TCL_GLOBMODE_TAILS) {
int objc, i;
Tcl_Obj **objv;
+ int prefixLen;
+ const char *pre;
+
+ /*
+ * If this length has never been set, set it here.
+ */
+
+ if (pathPrefix == NULL) {
+ Tcl_Panic("Called TclGlob with TCL_GLOBMODE_TAILS and pathPrefix==NULL");
+ }
+
+ pre = Tcl_GetStringFromObj(pathPrefix, &prefixLen);
+ if (prefixLen > 0
+ && (strchr(separators, pre[prefixLen-1]) == NULL)) {
+ /*
+ * If we're on Windows and the prefix is a volume relative one
+ * like 'C:', then there won't be a path separator in between, so
+ * no need to skip it here.
+ */
- /* Ensure sole ownership */
- if (Tcl_IsShared(oldResult)) {
- Tcl_DecrRefCount(oldResult);
- oldResult = Tcl_DuplicateObj(oldResult);
- Tcl_IncrRefCount(oldResult);
- }
-
- Tcl_ListObjGetElements(NULL, Tcl_GetObjResult(interp),
- &objc, &objv);
-#ifdef MAC_TCL
- /* adjust prefixLen if TclDoGlob prepended a ':' */
- if ((prefixLen > 0) && (objc > 0)
- && (Tcl_DStringValue(&buffer)[0] != ':')) {
- char *str = Tcl_GetStringFromObj(objv[0],NULL);
- if (str[0] == ':') {
- prefixLen++;
+ if ((tclPlatform != TCL_PLATFORM_WINDOWS) || (prefixLen != 2)
+ || (pre[1] != ':')) {
+ prefixLen++;
}
}
-#endif
+
+ Tcl_ListObjGetElements(NULL, filenamesObj, &objc, &objv);
for (i = 0; i< objc; i++) {
- Tcl_Obj* elt;
- if (globFlags & TCL_GLOBMODE_TAILS) {
- int len;
- char *oldStr = Tcl_GetStringFromObj(objv[i],&len);
- if (len == prefixLen) {
- if ((pattern[0] == '\0')
+ int len;
+ char *oldStr = Tcl_GetStringFromObj(objv[i], &len);
+ Tcl_Obj* elems[1];
+
+ if (len == prefixLen) {
+ if ((pattern[0] == '\0')
|| (strchr(separators, pattern[0]) == NULL)) {
- elt = Tcl_NewStringObj(".",1);
- } else {
- elt = Tcl_NewStringObj("/",1);
- }
+ TclNewLiteralStringObj(elems[0], ".");
} else {
- elt = Tcl_NewStringObj(oldStr + prefixLen,
- len - prefixLen);
+ TclNewLiteralStringObj(elems[0], "/");
}
} else {
- elt = objv[i];
+ elems[0] = Tcl_NewStringObj(oldStr+prefixLen, len-prefixLen);
}
- /* Assumption that 'oldResult' is a valid list */
- Tcl_ListObjAppendElement(interp, oldResult, elt);
+ Tcl_ListObjReplace(interp, filenamesObj, i, 1, 1, elems);
}
- Tcl_SetObjResult(interp, oldResult);
}
- /*
- * Release our temporary copy. All code paths above must
- * end here so we free our reference.
+
+ /*
+ * Now we have a list of discovered filenames in filenamesObj and a list
+ * of previously discovered (saved earlier from the interpreter result) in
+ * savedResultObj. Merge them and put them back in the interpreter result.
*/
- Tcl_DecrRefCount(oldResult);
- Tcl_DStringFree(&buffer);
+
+ if (Tcl_IsShared(savedResultObj)) {
+ TclDecrRefCount(savedResultObj);
+ savedResultObj = Tcl_DuplicateObj(savedResultObj);
+ Tcl_IncrRefCount(savedResultObj);
+ }
+ if (Tcl_ListObjAppendList(interp, savedResultObj, filenamesObj) != TCL_OK){
+ result = TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, savedResultObj);
+ }
+ TclDecrRefCount(savedResultObj);
+ TclDecrRefCount(filenamesObj);
+ if (pathPrefix != NULL) {
+ Tcl_DecrRefCount(pathPrefix);
+ }
+
return result;
}
@@ -2230,14 +2016,13 @@ TclGlob(interp, pattern, unquotedPrefix, globFlags, types)
*
* SkipToChar --
*
- * This function traverses a glob pattern looking for the next
- * unquoted occurance of the specified character at the same braces
- * nesting level.
+ * This function traverses a glob pattern looking for the next unquoted
+ * occurance of the specified character at the same braces nesting level.
*
* Results:
- * Updates stringPtr to point to the matching character, or to
- * the end of the string if nothing matched. The return value
- * is 1 if a match was found at the top level, otherwise it is 0.
+ * Updates stringPtr to point to the matching character, or to the end of
+ * the string if nothing matched. The return value is 1 if a match was
+ * found at the top level, otherwise it is 0.
*
* Side effects:
* None.
@@ -2246,9 +2031,9 @@ TclGlob(interp, pattern, unquotedPrefix, globFlags, types)
*/
static int
-SkipToChar(stringPtr, match)
- char **stringPtr; /* Pointer string to check. */
- char *match; /* Pointer to character to find. */
+SkipToChar(
+ char **stringPtr, /* Pointer string to check. */
+ int match) /* Character to find. */
{
int quoted, level;
register char *p;
@@ -2261,7 +2046,7 @@ SkipToChar(stringPtr, match)
quoted = 0;
continue;
}
- if ((level == 0) && (*p == *match)) {
+ if ((level == 0) && (*p == match)) {
*stringPtr = p;
return 1;
}
@@ -2280,23 +2065,23 @@ SkipToChar(stringPtr, match)
/*
*----------------------------------------------------------------------
*
- * TclDoGlob --
+ * DoGlob --
*
- * This recursive procedure forms the heart of the globbing
- * code. It performs a depth-first traversal of the tree
- * given by the path name to be globbed. The directory and
- * remainder are assumed to be native format paths. The prefix
- * contained in 'headPtr' is not used as a glob pattern, simply
- * as a path specifier, so it can contain unquoted glob-sensitive
- * characters (if the directories to which it points contain
- * such strange characters).
+ * This recursive procedure forms the heart of the globbing code. It
+ * performs a depth-first traversal of the tree given by the path name to
+ * be globbed and the pattern. The directory and remainder are assumed to
+ * be native format paths. The prefix contained in 'pathPtr' is either a
+ * directory or path from which to start the search (or NULL). If pathPtr
+ * is NULL, then the pattern must not start with an absolute path
+ * specification (that case should be handled by moving the absolute path
+ * prefix into pathPtr before calling DoGlob).
*
* Results:
- * The return value is a standard Tcl result indicating whether
- * an error occurred in globbing. After a normal return the
- * result in interp will be set to hold all of the file names
- * given by the dir and rem arguments. After an error the
- * result in interp will hold an error message.
+ * The return value is a standard Tcl result indicating whether an error
+ * occurred in globbing. After a normal return the result in interp will
+ * be set to hold all of the file names given by the dir and remaining
+ * arguments. After an error the result in interp will hold an error
+ * message.
*
* Side effects:
* None.
@@ -2304,163 +2089,159 @@ SkipToChar(stringPtr, match)
*----------------------------------------------------------------------
*/
-int
-TclDoGlob(interp, separators, headPtr, tail, types)
- Tcl_Interp *interp; /* Interpreter to use for error reporting
+static int
+DoGlob(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting
* (e.g. unmatched brace). */
- char *separators; /* String containing separator characters
- * that should be used to identify globbing
+ Tcl_Obj *matchesObj, /* Unshared list object in which to place all
+ * resulting filenames. Caller allocates and
+ * deallocates; DoGlob must not touch the
+ * refCount of this object. */
+ const char *separators, /* String containing separator characters that
+ * should be used to identify globbing
* boundaries. */
- Tcl_DString *headPtr; /* Completely expanded prefix. */
- char *tail; /* The unexpanded remainder of the path.
- * Must not be a pointer to a static string. */
- Tcl_GlobTypeData *types; /* List object containing list of acceptable
- * types. May be NULL. */
+ Tcl_Obj *pathPtr, /* Completely expanded prefix. */
+ int flags, /* If non-zero then pathPtr is a directory */
+ char *pattern, /* The pattern to match against. Must not be a
+ * pointer to a static string. */
+ Tcl_GlobTypeData *types) /* List object containing list of acceptable
+ * types. May be NULL. */
{
int baseLength, quoted, count;
int result = TCL_OK;
- char *name, *p, *openBrace, *closeBrace, *firstSpecialChar, savedChar;
- char lastChar = 0;
-
- int length = Tcl_DStringLength(headPtr);
-
- if (length > 0) {
- lastChar = Tcl_DStringValue(headPtr)[length-1];
- }
+ char *name, *p, *openBrace, *closeBrace, *firstSpecialChar;
+ Tcl_Obj *joinedPtr;
/*
- * Consume any leading directory separators, leaving tail pointing
- * just past the last initial separator.
+ * Consume any leading directory separators, leaving pattern pointing just
+ * past the last initial separator.
*/
count = 0;
- name = tail;
- for (; *tail != '\0'; tail++) {
- if (*tail == '\\') {
- /*
+ name = pattern;
+ for (; *pattern != '\0'; pattern++) {
+ if (*pattern == '\\') {
+ /*
* If the first character is escaped, either we have a directory
- * separator, or we have any other character. In the latter case
- * the rest of tail is a pattern, and we must break from the loop.
- * This is particularly important on Windows where '\' is both
- * the escaping character and a directory separator.
+ * separator, or we have any other character. In the latter case
+ * the rest is a pattern, and we must break from the loop. This
+ * is particularly important on Windows where '\' is both the
+ * escaping character and a directory separator.
*/
- if (strchr(separators, tail[1]) != NULL) {
- tail++;
+
+ if (strchr(separators, pattern[1]) != NULL) {
+ pattern++;
} else {
break;
}
- } else if (strchr(separators, *tail) == NULL) {
+ } else if (strchr(separators, *pattern) == NULL) {
break;
}
- if (tclPlatform != TCL_PLATFORM_MAC) {
- if (*tail == '\\') {
- Tcl_DStringAppend(headPtr, separators, 1);
- } else {
- Tcl_DStringAppend(headPtr, tail, 1);
- }
- }
count++;
}
/*
- * Deal with path separators. On the Mac, we have to watch out
- * for multiple separators, since they are special in Mac-style
- * paths.
+ * This block of code is not exercised by the Tcl test suite as of Tcl
+ * 8.5a0. Simplifications to the calling paths suggest it may not be
+ * necessary any more, since path separators are handled elsewhere. It is
+ * left in place in case new bugs are reported.
*/
- switch (tclPlatform) {
- case TCL_PLATFORM_MAC:
-#ifdef MAC_UNDERSTANDS_UNIX_PATHS
- if (*separators == '/') {
- if (((length == 0) && (count == 0))
- || ((length > 0) && (lastChar != ':'))) {
- Tcl_DStringAppend(headPtr, ":", 1);
- }
- } else {
-#endif
- if (count == 0) {
- if ((length > 0) && (lastChar != ':')) {
- Tcl_DStringAppend(headPtr, ":", 1);
- }
- } else {
- if (lastChar == ':') {
- count--;
- }
- while (count-- > 0) {
- Tcl_DStringAppend(headPtr, ":", 1);
- }
- }
-#ifdef MAC_UNDERSTANDS_UNIX_PATHS
- }
-#endif
- break;
+#if 0 /* PROBABLY_OBSOLETE */
+ /*
+ * Deal with path separators.
+ */
+
+ if (pathPtr == NULL) {
+ /*
+ * Length used to be the length of the prefix, and lastChar the
+ * lastChar of the prefix. But, none of this is used any more.
+ */
+
+ int length = 0;
+ char lastChar = 0;
+
+ switch (tclPlatform) {
case TCL_PLATFORM_WINDOWS:
/*
* If this is a drive relative path, add the colon and the
- * trailing slash if needed. Otherwise add the slash if
- * this is the first absolute element, or a later relative
- * element. Add an extra slash if this is a UNC path.
+ * trailing slash if needed. Otherwise add the slash if this is
+ * the first absolute element, or a later relative element. Add an
+ * extra slash if this is a UNC path.
+ */
if (*name == ':') {
- Tcl_DStringAppend(headPtr, ":", 1);
+ Tcl_DStringAppend(&append, ":", 1);
if (count > 1) {
- Tcl_DStringAppend(headPtr, "/", 1);
+ Tcl_DStringAppend(&append, "/", 1);
}
- } else if ((*tail != '\0')
- && (((length > 0)
- && (strchr(separators, lastChar) == NULL))
- || ((length == 0) && (count > 0)))) {
- Tcl_DStringAppend(headPtr, "/", 1);
+ } else if ((*pattern != '\0') && (((length > 0)
+ && (strchr(separators, lastChar) == NULL))
+ || ((length == 0) && (count > 0)))) {
+ Tcl_DStringAppend(&append, "/", 1);
if ((length == 0) && (count > 1)) {
- Tcl_DStringAppend(headPtr, "/", 1);
+ Tcl_DStringAppend(&append, "/", 1);
}
}
- */
-
+
break;
- case TCL_PLATFORM_UNIX: {
+ case TCL_PLATFORM_UNIX:
/*
- * Add a separator if this is the first absolute element, or
- * a later relative element.
-
- if ((*tail != '\0')
- && (((length > 0)
- && (strchr(separators, lastChar) == NULL))
- || ((length == 0) && (count > 0)))) {
- Tcl_DStringAppend(headPtr, "/", 1);
- }
+ * Add a separator if this is the first absolute element, or a
+ * later relative element.
*/
+
+ if ((*pattern != '\0') && (((length > 0)
+ && (strchr(separators, lastChar) == NULL))
+ || ((length == 0) && (count > 0)))) {
+ Tcl_DStringAppend(&append, "/", 1);
+ }
break;
}
}
+#endif /* PROBABLY_OBSOLETE */
/*
- * Look for the first matching pair of braces or the first
- * directory separator that is not inside a pair of braces.
+ * Look for the first matching pair of braces or the first directory
+ * separator that is not inside a pair of braces.
*/
openBrace = closeBrace = NULL;
quoted = 0;
- for (p = tail; *p != '\0'; p++) {
+ for (p = pattern; *p != '\0'; p++) {
if (quoted) {
quoted = 0;
+
} else if (*p == '\\') {
quoted = 1;
if (strchr(separators, p[1]) != NULL) {
- break; /* Quoted directory separator. */
+ /*
+ * Quoted directory separator.
+ */
+ break;
}
+
} else if (strchr(separators, *p) != NULL) {
- break; /* Unquoted directory separator. */
+ /*
+ * Unquoted directory separator.
+ */
+ break;
+
} else if (*p == '{') {
openBrace = p;
p++;
- if (SkipToChar(&p, "}")) {
- closeBrace = p; /* Balanced braces. */
+ if (SkipToChar(&p, '}')) {
+ /*
+ * Balanced braces.
+ */
+
+ closeBrace = p;
break;
}
Tcl_SetResult(interp, "unmatched open-brace in file name",
TCL_STATIC);
return TCL_ERROR;
+
} else if (*p == '}') {
Tcl_SetResult(interp, "unmatched close-brace in file name",
TCL_STATIC);
@@ -2474,29 +2255,28 @@ TclDoGlob(interp, separators, headPtr, tail, types)
if (openBrace != NULL) {
char *element;
+
Tcl_DString newName;
Tcl_DStringInit(&newName);
/*
- * For each element within in the outermost pair of braces,
- * append the element and the remainder to the fixed portion
- * before the first brace and recursively call TclDoGlob.
+ * For each element within in the outermost pair of braces, append the
+ * element and the remainder to the fixed portion before the first
+ * brace and recursively call DoGlob.
*/
- Tcl_DStringAppend(&newName, tail, openBrace-tail);
+ Tcl_DStringAppend(&newName, pattern, openBrace-pattern);
baseLength = Tcl_DStringLength(&newName);
- length = Tcl_DStringLength(headPtr);
*closeBrace = '\0';
for (p = openBrace; p != closeBrace; ) {
p++;
element = p;
- SkipToChar(&p, ",");
- Tcl_DStringSetLength(headPtr, length);
+ SkipToChar(&p, ',');
Tcl_DStringSetLength(&newName, baseLength);
Tcl_DStringAppend(&newName, element, p-element);
Tcl_DStringAppend(&newName, closeBrace+1, -1);
- result = TclDoGlob(interp, separators, headPtr,
- Tcl_DStringValue(&newName), types);
+ result = DoGlob(interp, matchesObj, separators, pathPtr, flags,
+ Tcl_DStringValue(&newName), types);
if (result != TCL_OK) {
break;
}
@@ -2507,276 +2287,273 @@ TclDoGlob(interp, separators, headPtr, tail, types)
}
/*
- * At this point, there are no more brace substitutions to perform on
- * this path component. The variable p is pointing at a quoted or
- * unquoted directory separator or the end of the string. So we need
- * to check for special globbing characters in the current pattern.
- * We avoid modifying tail if p is pointing at the end of the string.
+ * At this point, there are no more brace substitutions to perform on this
+ * path component. The variable p is pointing at a quoted or unquoted
+ * directory separator or the end of the string. So we need to check for
+ * special globbing characters in the current pattern. We avoid modifying
+ * pattern if p is pointing at the end of the string.
+ *
+ * If we find any globbing characters, then we must call
+ * Tcl_FSMatchInDirectory. If we're at the end of the string, then that's
+ * all we need to do. If we're not at the end of the string, then we must
+ * recurse, so we do that below.
+ *
+ * Alternatively, if there are no globbing characters then again there are
+ * two cases. If we're at the end of the string, we just need to check for
+ * the given path's existence and type. If we're not at the end of the
+ * string, we recurse.
*/
if (*p != '\0') {
-
/*
- * Note that we are modifying the string in place. This won't work
- * if the string is a static.
+ * Note that we are modifying the string in place. This won't work if
+ * the string is a static.
*/
- savedChar = *p;
+ char savedChar = *p;
*p = '\0';
- firstSpecialChar = strpbrk(tail, "*[]?\\");
+ firstSpecialChar = strpbrk(pattern, "*[]?\\");
*p = savedChar;
} else {
- firstSpecialChar = strpbrk(tail, "*[]?\\");
+ firstSpecialChar = strpbrk(pattern, "*[]?\\");
}
if (firstSpecialChar != NULL) {
- int ret;
- Tcl_Obj *head = Tcl_NewStringObj(Tcl_DStringValue(headPtr),-1);
- Tcl_IncrRefCount(head);
/*
- * Look for matching files in the given directory. The
- * implementation of this function is platform specific. For
- * each file that matches, it will add the match onto the
- * resultPtr given.
+ * Look for matching files in the given directory. The implementation
+ * of this function is filesystem specific. For each file that
+ * matches, it will add the match onto the resultPtr given.
*/
+
+ static Tcl_GlobTypeData dirOnly = {
+ TCL_GLOB_TYPE_DIR, 0, NULL, NULL
+ };
+ char save = *p;
+ Tcl_Obj* subdirsPtr;
+
if (*p == '\0') {
- ret = Tcl_FSMatchInDirectory(interp, Tcl_GetObjResult(interp),
- head, tail, types);
- } else {
- /*
- * We do the recursion ourselves. This makes implementing
- * Tcl_FSMatchInDirectory for each filesystem much easier.
- */
- Tcl_GlobTypeData dirOnly = { TCL_GLOB_TYPE_DIR, 0, NULL, NULL };
- char save = *p;
- Tcl_Obj *resultPtr;
-
- resultPtr = Tcl_NewListObj(0, NULL);
- Tcl_IncrRefCount(resultPtr);
- *p = '\0';
- ret = Tcl_FSMatchInDirectory(interp, resultPtr,
- head, tail, &dirOnly);
- *p = save;
- if (ret == TCL_OK) {
- int resLength, repair = -1;
- ret = Tcl_ListObjLength(interp, resultPtr, &resLength);
- if (ret == TCL_OK) {
- int i;
- for (i =0; i< resLength; i++) {
- Tcl_Obj *elt;
- Tcl_DString ds;
- Tcl_ListObjIndex(NULL, resultPtr, i, &elt);
- Tcl_DStringInit(&ds);
- if (Tcl_GetString(elt)[0] == '~') {
- Tcl_Obj *paths = Tcl_GetObjResult(interp);
-
- Tcl_ListObjLength(NULL, paths, &repair);
- Tcl_DStringAppend(&ds, "./", 2);
- }
- Tcl_DStringAppend(&ds, Tcl_GetString(elt), -1);
- if(tclPlatform == TCL_PLATFORM_MAC) {
- Tcl_DStringAppend(&ds, ":",1);
- } else {
- Tcl_DStringAppend(&ds, "/",1);
- }
- ret = TclDoGlob(interp, separators, &ds, p+1, types);
- Tcl_DStringFree(&ds);
- if (ret != TCL_OK) {
- break;
- }
- if (repair >= 0) {
- Tcl_Obj *paths = Tcl_GetObjResult(interp);
- int end;
-
- Tcl_ListObjLength(NULL, paths, &end);
- while (repair < end) {
- const char *bytes;
- int numBytes;
- Tcl_Obj *fixme, *newObj;
- Tcl_ListObjIndex(NULL, paths, repair, &fixme);
- bytes = Tcl_GetStringFromObj(fixme, &numBytes);
- newObj = Tcl_NewStringObj(bytes+2, numBytes-2);
- Tcl_ListObjReplace(NULL, paths, repair, 1,
- 1, &newObj);
- repair++;
- }
- repair = -1;
- }
+ return Tcl_FSMatchInDirectory(interp, matchesObj, pathPtr,
+ pattern, types);
+ }
+
+ /*
+ * We do the recursion ourselves. This makes implementing
+ * Tcl_FSMatchInDirectory for each filesystem much easier.
+ */
+
+ *p = '\0';
+ TclNewObj(subdirsPtr);
+ Tcl_IncrRefCount(subdirsPtr);
+ result = Tcl_FSMatchInDirectory(interp, subdirsPtr, pathPtr,
+ pattern, &dirOnly);
+ *p = save;
+ if (result == TCL_OK) {
+ int subdirc, i, repair = -1;
+ Tcl_Obj **subdirv;
+
+ result = Tcl_ListObjGetElements(interp, subdirsPtr,
+ &subdirc, &subdirv);
+ for (i=0; result==TCL_OK && i<subdirc; i++) {
+ Tcl_Obj *copy = NULL;
+
+ if (pathPtr == NULL && Tcl_GetString(subdirv[i])[0] == '~') {
+ Tcl_ListObjLength(NULL, matchesObj, &repair);
+ copy = subdirv[i];
+ subdirv[i] = Tcl_NewStringObj("./", 2);
+ Tcl_AppendObjToObj(subdirv[i], copy);
+ Tcl_IncrRefCount(subdirv[i]);
+ }
+ result = DoGlob(interp, matchesObj, separators, subdirv[i],
+ 1, p+1, types);
+ if (copy) {
+ int end;
+
+ Tcl_DecrRefCount(subdirv[i]);
+ subdirv[i] = copy;
+ Tcl_ListObjLength(NULL, matchesObj, &end);
+ while (repair < end) {
+ const char *bytes;
+ int numBytes;
+ Tcl_Obj *fixme, *newObj;
+ Tcl_ListObjIndex(NULL, matchesObj, repair, &fixme);
+ bytes = Tcl_GetStringFromObj(fixme, &numBytes);
+ newObj = Tcl_NewStringObj(bytes+2, numBytes-2);
+ Tcl_ListObjReplace(NULL, matchesObj, repair, 1,
+ 1, &newObj);
+ repair++;
}
+ repair = -1;
}
}
- Tcl_DecrRefCount(resultPtr);
}
- Tcl_DecrRefCount(head);
- return ret;
+ TclDecrRefCount(subdirsPtr);
+ return result;
}
- Tcl_DStringAppend(headPtr, tail, p-tail);
- if (*p != '\0') {
- return TclDoGlob(interp, separators, headPtr, p, types);
- } else {
+
+ /*
+ * We reach here with no pattern char in current section
+ */
+
+ if (*p == '\0') {
/*
* This is the code path reached by a command like 'glob foo'.
*
- * There are no more wildcards in the pattern and no more
- * unprocessed characters in the tail, so now we can construct
- * the path, and pass it to Tcl_FSMatchInDirectory with an
- * empty pattern to verify the existence of the file and check
- * it is of the correct type (if a 'types' flag it given -- if
- * no such flag was given, we could just use 'Tcl_FSLStat', but
- * for simplicity we keep to a common approach).
+ * There are no more wildcards in the pattern and no more unprocessed
+ * characters in the pattern, so now we can construct the path, and
+ * pass it to Tcl_FSMatchInDirectory with an empty pattern to verify
+ * the existence of the file and check it is of the correct type (if a
+ * 'types' flag it given -- if no such flag was given, we could just
+ * use 'Tcl_FSLStat', but for simplicity we keep to a common
+ * approach).
*/
- Tcl_Obj *nameObj;
+ int length;
+ Tcl_DString append;
+
+ Tcl_DStringInit(&append);
+ Tcl_DStringAppend(&append, pattern, p-pattern);
+
+ if (pathPtr != NULL) {
+ (void) Tcl_GetStringFromObj(pathPtr, &length);
+ } else {
+ length = 0;
+ }
switch (tclPlatform) {
- case TCL_PLATFORM_MAC: {
- if (strchr(Tcl_DStringValue(headPtr), ':') == NULL) {
- Tcl_DStringAppend(headPtr, ":", 1);
+ case TCL_PLATFORM_WINDOWS:
+ if (length == 0 && (Tcl_DStringLength(&append) == 0)) {
+ if (((*name == '\\') && (name[1] == '/' ||
+ name[1] == '\\')) || (*name == '/')) {
+ Tcl_DStringAppend(&append, "/", 1);
+ } else {
+ Tcl_DStringAppend(&append, ".", 1);
}
- break;
}
- case TCL_PLATFORM_WINDOWS: {
- if (Tcl_DStringLength(headPtr) == 0) {
- if (((*name == '\\') && (name[1] == '/' || name[1] == '\\'))
- || (*name == '/')) {
- Tcl_DStringAppend(headPtr, "/", 1);
- } else {
- Tcl_DStringAppend(headPtr, ".", 1);
- }
- }
+
#if defined(__CYGWIN__) && defined(__WIN32__)
- {
- extern int cygwin_conv_to_win32_path
- _ANSI_ARGS_((CONST char *, char *));
+ {
char winbuf[MAX_PATH+1];
- cygwin_conv_to_win32_path(Tcl_DStringValue(headPtr), winbuf);
- Tcl_DStringFree(headPtr);
- Tcl_DStringAppend(headPtr, winbuf, -1);
- }
-#endif /* __CYGWIN__ && __WIN32__ */
- /*
- * Convert to forward slashes. This is required to pass
- * some Tcl tests. We should probably remove the conversions
- * here and in tclWinFile.c, since they aren't needed since
- * the dropping of support for Win32s.
- */
- for (p = Tcl_DStringValue(headPtr); *p != '\0'; p++) {
- if (*p == '\\') {
- *p = '/';
- }
- }
- break;
+ cygwin_conv_to_win32_path(Tcl_DStringValue(&append), winbuf);
+ Tcl_DStringFree(&append);
+ Tcl_DStringAppend(&append, winbuf, -1);
}
- case TCL_PLATFORM_UNIX: {
- if (Tcl_DStringLength(headPtr) == 0) {
- if ((*name == '\\' && name[1] == '/') || (*name == '/')) {
- Tcl_DStringAppend(headPtr, "/", 1);
- } else {
- Tcl_DStringAppend(headPtr, ".", 1);
- }
+#endif /* __CYGWIN__ && __WIN32__ */
+ break;
+
+ case TCL_PLATFORM_UNIX:
+ if (length == 0 && (Tcl_DStringLength(&append) == 0)) {
+ if ((*name == '\\' && name[1] == '/') || (*name == '/')) {
+ Tcl_DStringAppend(&append, "/", 1);
+ } else {
+ Tcl_DStringAppend(&append, ".", 1);
}
- break;
}
+ break;
}
- /* Common for all platforms */
- name = Tcl_DStringValue(headPtr);
- nameObj = Tcl_NewStringObj(name, Tcl_DStringLength(headPtr));
- Tcl_IncrRefCount(nameObj);
- result = Tcl_FSMatchInDirectory(interp, Tcl_GetObjResult(interp),
- nameObj, NULL, types);
- Tcl_DecrRefCount(nameObj);
- return result;
- }
-}
+ /*
+ * Common for all platforms.
+ */
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclFileDirname
- *
- * This procedure calculates the directory above a given
- * path: basically 'file dirname'. It is used both by
- * the 'dirname' subcommand of file and by code in tclIOUtil.c.
- *
- * Results:
- * NULL if an error occurred, otherwise a Tcl_Obj owned by
- * the caller (i.e. most likely with refCount 1).
- *
- * Side effects:
- * None.
- *
- *---------------------------------------------------------------------------
- */
+ if (pathPtr == NULL) {
+ joinedPtr = Tcl_NewStringObj(Tcl_DStringValue(&append),
+ Tcl_DStringLength(&append));
+ } else if (flags) {
+ joinedPtr = TclNewFSPathObj(pathPtr, Tcl_DStringValue(&append),
+ Tcl_DStringLength(&append));
+ } else {
+ joinedPtr = Tcl_DuplicateObj(pathPtr);
+ if (strchr(separators, Tcl_DStringValue(&append)[0]) == NULL) {
+ /*
+ * The current prefix must end in a separator.
+ */
-Tcl_Obj*
-TclFileDirname(interp, pathPtr)
- Tcl_Interp *interp; /* Used for error reporting */
- Tcl_Obj *pathPtr; /* Path to take dirname of */
-{
- int splitElements;
- Tcl_Obj *splitPtr;
- Tcl_Obj *splitResultPtr = NULL;
-
- /*
- * The behaviour we want here is slightly different to
- * the standard Tcl_FSSplitPath in the handling of home
- * directories; Tcl_FSSplitPath preserves the "~" while
- * this code computes the actual full path name, if we
- * had just a single component.
- */
- splitPtr = Tcl_FSSplitPath(pathPtr, &splitElements);
- if ((splitElements == 1) && (Tcl_GetString(pathPtr)[0] == '~')) {
- Tcl_DecrRefCount(splitPtr);
- splitPtr = Tcl_FSGetNormalizedPath(interp, pathPtr);
- if (splitPtr == NULL) {
- return NULL;
+ int len;
+ const char *joined = Tcl_GetStringFromObj(joinedPtr,&len);
+
+ if (strchr(separators, joined[len-1]) == NULL) {
+ Tcl_AppendToObj(joinedPtr, "/", 1);
+ }
+ }
+ Tcl_AppendToObj(joinedPtr, Tcl_DStringValue(&append),
+ Tcl_DStringLength(&append));
}
- splitPtr = Tcl_FSSplitPath(splitPtr, &splitElements);
+ Tcl_IncrRefCount(joinedPtr);
+ Tcl_DStringFree(&append);
+ result = Tcl_FSMatchInDirectory(interp, matchesObj, joinedPtr, NULL,
+ types);
+ Tcl_DecrRefCount(joinedPtr);
+ return result;
}
/*
- * Return all but the last component. If there is only one
- * component, return it if the path was non-relative, otherwise
- * return the current directory.
+ * If it's not the end of the string, we must recurse
*/
- if (splitElements > 1) {
- splitResultPtr = Tcl_FSJoinPath(splitPtr, splitElements - 1);
- } else if (splitElements == 0 ||
- (Tcl_FSGetPathType(pathPtr) == TCL_PATH_RELATIVE)) {
- splitResultPtr = Tcl_NewStringObj(
- ((tclPlatform == TCL_PLATFORM_MAC) ? ":" : "."), 1);
+ if (pathPtr == NULL) {
+ joinedPtr = Tcl_NewStringObj(pattern, p-pattern);
+ } else if (flags) {
+ joinedPtr = TclNewFSPathObj(pathPtr, pattern, p-pattern);
} else {
- Tcl_ListObjIndex(NULL, splitPtr, 0, &splitResultPtr);
+ joinedPtr = Tcl_DuplicateObj(pathPtr);
+ if (strchr(separators, pattern[0]) == NULL) {
+ /*
+ * The current prefix must end in a separator, unless this is a
+ * volume-relative path. In particular globbing in Windows shares,
+ * when not using -dir or -path, e.g. 'glob [file join
+ * //machine/share/subdir *]' requires adding a separator here.
+ * This behaviour is not currently tested for in the test suite.
+ */
+
+ int len;
+ const char *joined = Tcl_GetStringFromObj(joinedPtr,&len);
+
+ if (strchr(separators, joined[len-1]) == NULL) {
+ if (Tcl_FSGetPathType(pathPtr) != TCL_PATH_VOLUME_RELATIVE) {
+ Tcl_AppendToObj(joinedPtr, "/", 1);
+ }
+ }
+ }
+ Tcl_AppendToObj(joinedPtr, pattern, p-pattern);
}
- Tcl_IncrRefCount(splitResultPtr);
- Tcl_DecrRefCount(splitPtr);
- return splitResultPtr;
+
+ Tcl_IncrRefCount(joinedPtr);
+ result = DoGlob(interp, matchesObj, separators, joinedPtr, 1, p, types);
+ Tcl_DecrRefCount(joinedPtr);
+
+ return result;
}
/*
*---------------------------------------------------------------------------
*
- * Tcl_AllocStatBuf
+ * Tcl_AllocStatBuf --
*
- * This procedure allocates a Tcl_StatBuf on the heap. It exists
- * so that extensions may be used unchanged on systems where
- * largefile support is optional.
+ * This procedure allocates a Tcl_StatBuf on the heap. It exists so that
+ * extensions may be used unchanged on systems where largefile support is
+ * optional.
*
* Results:
- * A pointer to a Tcl_StatBuf which may be deallocated by being
- * passed to ckfree().
+ * A pointer to a Tcl_StatBuf which may be deallocated by being passed to
+ * ckfree().
*
* Side effects:
- * None.
+ * None.
*
*---------------------------------------------------------------------------
*/
Tcl_StatBuf *
-Tcl_AllocStatBuf() {
+Tcl_AllocStatBuf(void)
+{
return (Tcl_StatBuf *) ckalloc(sizeof(Tcl_StatBuf));
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclFileSystem.h b/generic/tclFileSystem.h
new file mode 100644
index 0000000..2d6f046
--- /dev/null
+++ b/generic/tclFileSystem.h
@@ -0,0 +1,121 @@
+/*
+ * tclFileSystem.h --
+ *
+ * This file contains the common defintions and prototypes for use by
+ * Tcl's filesystem and path handling layers.
+ *
+ * Copyright (c) 2003 Vince Darley.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TCLFILESYSTEM
+#define _TCLFILESYSTEM
+
+#include "tcl.h"
+
+/*
+ * struct FilesystemRecord --
+ *
+ * A filesystem record is used to keep track of each filesystem currently
+ * registered with the core, in a linked list. Pointers to these structures
+ * are also kept by each "path" Tcl_Obj, and we must retain a refCount on the
+ * number of such references.
+ */
+
+typedef struct FilesystemRecord {
+ ClientData clientData; /* Client specific data for the new filesystem
+ * (can be NULL) */
+ Tcl_Filesystem *fsPtr; /* Pointer to filesystem dispatch table. */
+ int fileRefCount; /* How many Tcl_Obj's use this filesystem. */
+ struct FilesystemRecord *nextPtr;
+ /* The next filesystem registered to Tcl, or
+ * NULL if no more. */
+ struct FilesystemRecord *prevPtr;
+ /* The previous filesystem registered to Tcl,
+ * or NULL if no more. */
+} FilesystemRecord;
+
+/*
+ * This structure holds per-thread private copy of the current directory
+ * maintained by the global cwdPathPtr. This structure holds per-thread
+ * private copies of some global data. This way we avoid most of the
+ * synchronization calls which boosts performance, at cost of having to update
+ * this information each time the corresponding epoch counter changes.
+ */
+
+typedef struct ThreadSpecificData {
+ int initialized;
+ int cwdPathEpoch;
+ int filesystemEpoch;
+ Tcl_Obj *cwdPathPtr;
+ ClientData cwdClientData;
+ FilesystemRecord *filesystemList;
+} ThreadSpecificData;
+
+/*
+ * The internal TclFS API provides routines for handling and manipulating
+ * paths efficiently, taking direct advantage of the "path" Tcl_Obj type.
+ *
+ * These functions are not exported at all at present.
+ */
+
+MODULE_SCOPE int TclFSCwdPointerEquals(Tcl_Obj **pathPtrPtr);
+MODULE_SCOPE int TclFSMakePathFromNormalized(Tcl_Interp *interp,
+ Tcl_Obj *pathPtr, ClientData clientData);
+MODULE_SCOPE int TclFSNormalizeToUniquePath(Tcl_Interp *interp,
+ Tcl_Obj *pathPtr, int startAt,
+ ClientData *clientDataPtr);
+MODULE_SCOPE Tcl_Obj * TclFSMakePathRelative(Tcl_Interp *interp,
+ Tcl_Obj *pathPtr, Tcl_Obj *cwdPtr);
+MODULE_SCOPE Tcl_Obj * TclFSInternalToNormalized(
+ Tcl_Filesystem *fromFilesystem,
+ ClientData clientData,
+ FilesystemRecord **fsRecPtrPtr);
+MODULE_SCOPE int TclFSEnsureEpochOk(Tcl_Obj *pathPtr,
+ Tcl_Filesystem **fsPtrPtr);
+MODULE_SCOPE void TclFSSetPathDetails(Tcl_Obj *pathPtr,
+ FilesystemRecord *fsRecPtr,
+ ClientData clientData);
+MODULE_SCOPE Tcl_Obj * TclFSNormalizeAbsolutePath(Tcl_Interp *interp,
+ Tcl_Obj *pathPtr, ClientData *clientDataPtr);
+
+/*
+ * Private shared variables for use by tclIOUtil.c and tclPathObj.c
+ */
+
+MODULE_SCOPE Tcl_Filesystem tclNativeFilesystem;
+MODULE_SCOPE Tcl_ThreadDataKey tclFsDataKey;
+
+/*
+ * Private shared functions for use by tclIOUtil.c, tclPathObj.c and
+ * tclFileName.c, and any platform-specific filesystem code.
+ */
+
+MODULE_SCOPE Tcl_PathType TclFSGetPathType(Tcl_Obj *pathPtr,
+ Tcl_Filesystem **filesystemPtrPtr,
+ int *driveNameLengthPtr);
+MODULE_SCOPE Tcl_PathType TclFSNonnativePathType(CONST char *pathPtr,
+ int pathLen, Tcl_Filesystem **filesystemPtrPtr,
+ int *driveNameLengthPtr, Tcl_Obj **driveNameRef);
+MODULE_SCOPE Tcl_PathType TclGetPathType(Tcl_Obj *pathPtr,
+ Tcl_Filesystem **filesystemPtrPtr,
+ int *driveNameLengthPtr, Tcl_Obj **driveNameRef);
+MODULE_SCOPE int TclFSEpochOk(int filesystemEpoch);
+MODULE_SCOPE int TclFSCwdIsNative(void);
+MODULE_SCOPE Tcl_Obj * TclWinVolumeRelativeNormalize(Tcl_Interp *interp,
+ CONST char *path, Tcl_Obj **useThisCwdPtr);
+
+MODULE_SCOPE Tcl_FSPathInFilesystemProc TclNativePathInFilesystem;
+MODULE_SCOPE Tcl_FSCreateInternalRepProc TclNativeCreateNativeRep;
+
+#endif /* _TCLFILESYSTEM */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclGet.c b/generic/tclGet.c
index b15f100..54b4370 100644
--- a/generic/tclGet.c
+++ b/generic/tclGet.c
@@ -1,21 +1,18 @@
-/*
+/*
* tclGet.c --
*
- * This file contains procedures to convert strings into
- * other forms, like integers or floating-point numbers or
- * booleans, doing syntax checking along the way.
+ * This file contains functions to convert strings into other forms, like
+ * integers or floating-point numbers or booleans, doing syntax checking
+ * along the way.
*
* Copyright (c) 1990-1993 The Regents of the University of California.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
-#include "tclMath.h"
-
/*
*----------------------------------------------------------------------
@@ -25,10 +22,10 @@
* Given a string, produce the corresponding integer value.
*
* Results:
- * The return value is normally TCL_OK; in this case *intPtr
- * will be set to the integer value equivalent to string. If
- * string is improperly formed then TCL_ERROR is returned and
- * an error message will be left in the interp's result.
+ * The return value is normally TCL_OK; in this case *intPtr will be set
+ * to the integer value equivalent to src. If src is improperly formed
+ * then TCL_ERROR is returned and an error message will be left in the
+ * interp's result.
*
* Side effects:
* None.
@@ -37,80 +34,26 @@
*/
int
-Tcl_GetInt(interp, string, intPtr)
- Tcl_Interp *interp; /* Interpreter to use for error reporting. */
- CONST char *string; /* String containing a (possibly signed)
- * integer in a form acceptable to strtol. */
- int *intPtr; /* Place to store converted result. */
+Tcl_GetInt(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ CONST char *src, /* String containing a (possibly signed)
+ * integer in a form acceptable to
+ * Tcl_GetIntFromObj(). */
+ int *intPtr) /* Place to store converted result. */
{
- char *end;
- CONST char *p = string;
- long i;
-
- /*
- * Note: use strtoul instead of strtol for integer conversions
- * to allow full-size unsigned numbers, but don't depend on strtoul
- * to handle sign characters; it won't in some implementations.
- */
-
- errno = 0;
-#ifdef TCL_STRTOUL_SIGN_CHECK
- /*
- * This special sign check actually causes bad numbers to be allowed
- * when strtoul. I can't find a strtoul that doesn't validly handle
- * signed characters, and the C standard implies that this is all
- * unnecessary. [Bug #634856]
- */
- for ( ; isspace(UCHAR(*p)); p++) { /* INTL: ISO space. */
- /* Empty loop body. */
- }
- if (*p == '-') {
- p++;
- i = -((long)strtoul(p, &end, 0)); /* INTL: Tcl source. */
- } else if (*p == '+') {
- p++;
- i = strtoul(p, &end, 0); /* INTL: Tcl source. */
- } else
-#else
- i = strtoul(p, &end, 0); /* INTL: Tcl source. */
-#endif
- if (end == p) {
- badInteger:
- if (interp != (Tcl_Interp *) NULL) {
- Tcl_AppendResult(interp, "expected integer but got \"", string,
- "\"", (char *) NULL);
- TclCheckBadOctal(interp, string);
- }
- return TCL_ERROR;
- }
+ Tcl_Obj obj;
+ int code;
- /*
- * The second test below is needed on platforms where "long" is
- * larger than "int" to detect values that fit in a long but not in
- * an int.
- */
+ obj.refCount = 1;
+ obj.bytes = (char *) src;
+ obj.length = strlen(src);
+ obj.typePtr = NULL;
- if ((errno == ERANGE)
-#if (LONG_MAX > INT_MAX)
- || (i > UINT_MAX) || (i < -(long)UINT_MAX)
-#endif
- ) {
- if (interp != (Tcl_Interp *) NULL) {
- Tcl_SetResult(interp, "integer value too large to represent",
- TCL_STATIC);
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
- Tcl_GetStringResult(interp), (char *) NULL);
- }
- return TCL_ERROR;
- }
- while ((*end != '\0') && isspace(UCHAR(*end))) { /* INTL: ISO space. */
- end++;
- }
- if (*end != 0) {
- goto badInteger;
+ code = Tcl_GetIntFromObj(interp, &obj, intPtr);
+ if (obj.refCount > 1) {
+ Tcl_Panic("invalid sharing of Tcl_Obj on C stack");
}
- *intPtr = (int) i;
- return TCL_OK;
+ return code;
}
/*
@@ -118,16 +61,15 @@ Tcl_GetInt(interp, string, intPtr)
*
* TclGetLong --
*
- * Given a string, produce the corresponding long integer value.
- * This routine is a version of Tcl_GetInt but returns a "long"
- * instead of an "int".
+ * Given a string, produce the corresponding long integer value. This
+ * routine is a version of Tcl_GetInt but returns a "long" instead of an
+ * "int" (a difference that matters on 64-bit architectures).
*
* Results:
- * The return value is normally TCL_OK; in this case *longPtr
- * will be set to the long integer value equivalent to string. If
- * string is improperly formed then TCL_ERROR is returned and
- * an error message will be left in the interp's result if interp
- * is non-NULL.
+ * The return value is normally TCL_OK; in this case *longPtr will be set
+ * to the long integer value equivalent to src. If src is improperly
+ * formed then TCL_ERROR is returned and an error message will be left in
+ * the interp's result if interp is non-NULL.
*
* Side effects:
* None.
@@ -136,64 +78,27 @@ Tcl_GetInt(interp, string, intPtr)
*/
int
-TclGetLong(interp, string, longPtr)
- Tcl_Interp *interp; /* Interpreter used for error reporting
- * if not NULL. */
- CONST char *string; /* String containing a (possibly signed)
- * long integer in a form acceptable to
- * strtoul. */
- long *longPtr; /* Place to store converted long result. */
+TclGetLong(
+ Tcl_Interp *interp, /* Interpreter used for error reporting if not
+ * NULL. */
+ CONST char *src, /* String containing a (possibly signed) long
+ * integer in a form acceptable to
+ * Tcl_GetLongFromObj(). */
+ long *longPtr) /* Place to store converted long result. */
{
- char *end;
- CONST char *p = string;
- long i;
+ Tcl_Obj obj;
+ int code;
- /*
- * Note: don't depend on strtoul to handle sign characters; it won't
- * in some implementations.
- */
+ obj.refCount = 1;
+ obj.bytes = (char *) src;
+ obj.length = strlen(src);
+ obj.typePtr = NULL;
- errno = 0;
-#ifdef TCL_STRTOUL_SIGN_CHECK
- for ( ; isspace(UCHAR(*p)); p++) { /* INTL: ISO space. */
- /* Empty loop body. */
- }
- if (*p == '-') {
- p++;
- i = -(int)strtoul(p, &end, 0); /* INTL: Tcl source. */
- } else if (*p == '+') {
- p++;
- i = strtoul(p, &end, 0); /* INTL: Tcl source. */
- } else
-#else
- i = strtoul(p, &end, 0); /* INTL: Tcl source. */
-#endif
- if (end == p) {
- badInteger:
- if (interp != (Tcl_Interp *) NULL) {
- Tcl_AppendResult(interp, "expected integer but got \"", string,
- "\"", (char *) NULL);
- TclCheckBadOctal(interp, string);
- }
- return TCL_ERROR;
- }
- if (errno == ERANGE) {
- if (interp != (Tcl_Interp *) NULL) {
- Tcl_SetResult(interp, "integer value too large to represent",
- TCL_STATIC);
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
- Tcl_GetStringResult(interp), (char *) NULL);
- }
- return TCL_ERROR;
+ code = Tcl_GetLongFromObj(interp, &obj, longPtr);
+ if (obj.refCount > 1) {
+ Tcl_Panic("invalid sharing of Tcl_Obj on C stack");
}
- while ((*end != '\0') && isspace(UCHAR(*end))) { /* INTL: ISO space. */
- end++;
- }
- if (*end != 0) {
- goto badInteger;
- }
- *longPtr = i;
- return TCL_OK;
+ return code;
}
/*
@@ -205,10 +110,10 @@ TclGetLong(interp, string, longPtr)
* floating-point value.
*
* Results:
- * The return value is normally TCL_OK; in this case *doublePtr
- * will be set to the double-precision value equivalent to string.
- * If string is improperly formed then TCL_ERROR is returned and
- * an error message will be left in the interp's result.
+ * The return value is normally TCL_OK; in this case *doublePtr will be
+ * set to the double-precision value equivalent to src. If src is
+ * improperly formed then TCL_ERROR is returned and an error message will
+ * be left in the interp's result.
*
* Side effects:
* None.
@@ -217,40 +122,26 @@ TclGetLong(interp, string, longPtr)
*/
int
-Tcl_GetDouble(interp, string, doublePtr)
- Tcl_Interp *interp; /* Interpreter used for error reporting. */
- CONST char *string; /* String containing a floating-point number
- * in a form acceptable to strtod. */
- double *doublePtr; /* Place to store converted result. */
+Tcl_GetDouble(
+ Tcl_Interp *interp, /* Interpreter used for error reporting. */
+ CONST char *src, /* String containing a floating-point number
+ * in a form acceptable to
+ * Tcl_GetDoubleFromObj(). */
+ double *doublePtr) /* Place to store converted result. */
{
- char *end;
- double d;
+ Tcl_Obj obj;
+ int code;
- errno = 0;
- d = strtod(string, &end); /* INTL: Tcl source. */
- if (end == string) {
- badDouble:
- if (interp != (Tcl_Interp *) NULL) {
- Tcl_AppendResult(interp,
- "expected floating-point number but got \"",
- string, "\"", (char *) NULL);
- }
- return TCL_ERROR;
- }
- if (errno != 0 && (d == HUGE_VAL || d == -HUGE_VAL || d == 0)) {
- if (interp != (Tcl_Interp *) NULL) {
- TclExprFloatError(interp, d);
- }
- return TCL_ERROR;
- }
- while ((*end != 0) && isspace(UCHAR(*end))) { /* INTL: ISO space. */
- end++;
- }
- if (*end != 0) {
- goto badDouble;
+ obj.refCount = 1;
+ obj.bytes = (char *) src;
+ obj.length = strlen(src);
+ obj.typePtr = NULL;
+
+ code = Tcl_GetDoubleFromObj(interp, &obj, doublePtr);
+ if (obj.refCount > 1) {
+ Tcl_Panic("invalid sharing of Tcl_Obj on C stack");
}
- *doublePtr = d;
- return TCL_OK;
+ return code;
}
/*
@@ -258,14 +149,14 @@ Tcl_GetDouble(interp, string, doublePtr)
*
* Tcl_GetBoolean --
*
- * Given a string, return a 0/1 boolean value corresponding
- * to the string.
+ * Given a string, return a 0/1 boolean value corresponding to the
+ * string.
*
* Results:
- * The return value is normally TCL_OK; in this case *boolPtr
- * will be set to the 0/1 value equivalent to string. If
- * string is improperly formed then TCL_ERROR is returned and
- * an error message will be left in the interp's result.
+ * The return value is normally TCL_OK; in this case *boolPtr will be set
+ * to the 0/1 value equivalent to src. If src is improperly formed then
+ * TCL_ERROR is returned and an error message will be left in the
+ * interp's result.
*
* Side effects:
* None.
@@ -274,64 +165,35 @@ Tcl_GetDouble(interp, string, doublePtr)
*/
int
-Tcl_GetBoolean(interp, string, boolPtr)
- Tcl_Interp *interp; /* Interpreter used for error reporting. */
- CONST char *string; /* String containing a boolean number
- * specified either as 1/0 or true/false or
- * yes/no. */
- int *boolPtr; /* Place to store converted result, which
- * will be 0 or 1. */
+Tcl_GetBoolean(
+ Tcl_Interp *interp, /* Interpreter used for error reporting. */
+ CONST char *src, /* String containing one of the boolean values
+ * 1, 0, true, false, yes, no, on off. */
+ int *boolPtr) /* Place to store converted result, which will
+ * be 0 or 1. */
{
- int i;
- char lowerCase[10], c;
- size_t length;
+ Tcl_Obj obj;
+ int code;
- /*
- * Convert the input string to all lower-case.
- * INTL: This code will work on UTF strings.
- */
+ obj.refCount = 1;
+ obj.bytes = (char *) src;
+ obj.length = strlen(src);
+ obj.typePtr = NULL;
- for (i = 0; i < 9; i++) {
- c = string[i];
- if (c == 0) {
- break;
- }
- if ((c >= 'A') && (c <= 'Z')) {
- c += (char) ('a' - 'A');
- }
- lowerCase[i] = c;
+ code = Tcl_ConvertToType(interp, &obj, &tclBooleanType);
+ if (obj.refCount > 1) {
+ Tcl_Panic("invalid sharing of Tcl_Obj on C stack");
}
- lowerCase[i] = 0;
-
- length = strlen(lowerCase);
- c = lowerCase[0];
- if ((c == '0') && (lowerCase[1] == '\0')) {
- *boolPtr = 0;
- } else if ((c == '1') && (lowerCase[1] == '\0')) {
- *boolPtr = 1;
- } else if ((c == 'y') && (strncmp(lowerCase, "yes", length) == 0)) {
- *boolPtr = 1;
- } else if ((c == 'n') && (strncmp(lowerCase, "no", length) == 0)) {
- *boolPtr = 0;
- } else if ((c == 't') && (strncmp(lowerCase, "true", length) == 0)) {
- *boolPtr = 1;
- } else if ((c == 'f') && (strncmp(lowerCase, "false", length) == 0)) {
- *boolPtr = 0;
- } else if ((c == 'o') && (length >= 2)) {
- if (strncmp(lowerCase, "on", length) == 0) {
- *boolPtr = 1;
- } else if (strncmp(lowerCase, "off", length) == 0) {
- *boolPtr = 0;
- } else {
- goto badBoolean;
- }
- } else {
- badBoolean:
- if (interp != (Tcl_Interp *) NULL) {
- Tcl_AppendResult(interp, "expected boolean value but got \"",
- string, "\"", (char *) NULL);
- }
- return TCL_ERROR;
+ if (code == TCL_OK) {
+ *boolPtr = obj.internalRep.longValue;
}
- return TCL_OK;
+ return code;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclGetDate.y b/generic/tclGetDate.y
index 7db4a35..e22e40c 100644
--- a/generic/tclGetDate.y
+++ b/generic/tclGetDate.y
@@ -1,337 +1,409 @@
-/*
+/*
* tclGetDate.y --
*
- * Contains yacc grammar for parsing date and time strings.
- * The output of this file should be the file tclDate.c which
- * is used directly in the Tcl sources.
+ * Contains yacc grammar for parsing date and time strings. The output of
+ * this file should be the file tclDate.c which is used directly in the
+ * Tcl sources. Note that this file is largely obsolete in Tcl 8.5; it is
+ * only used when doing free-form date parsing, an ill-defined process
+ * anyway.
*
* Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
+%parse-param {DateInfo* info}
+%lex-param {DateInfo* info}
+%pure-parser
+ /* %error-verbose would be nice, but our token names are meaningless */
+%locations
+
%{
-/*
+/*
* tclDate.c --
*
- * This file is generated from a yacc grammar defined in
- * the file tclGetDate.y. It should not be edited directly.
+ * This file is generated from a yacc grammar defined in the file
+ * tclGetDate.y. It should not be edited directly.
*
* Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCSID
*/
-
#include "tclInt.h"
-#include "tclPort.h"
-
-#if defined(MAC_TCL) && !defined(TCL_MAC_USE_MSL_EPOCH)
-# define EPOCH 1904
-# define START_OF_TIME 1904
-# define END_OF_TIME 2039
-#else
-# define EPOCH 1970
-# define START_OF_TIME 1902
-# define END_OF_TIME 2037
-#endif
+
+/*
+ * Bison generates several labels that happen to be unused. MS Visual C++
+ * doesn't like that, and complains. Tell it to shut up.
+ */
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4102 )
+#endif /* _MSC_VER */
+
+/*
+ * yyparse will accept a 'struct DateInfo' as its parameter; that's where the
+ * parsed fields will be returned.
+ */
+
+typedef struct DateInfo {
+
+ Tcl_Obj* messages; /* Error messages */
+ const char* separatrix; /* String separating messages */
+
+ time_t dateYear;
+ time_t dateMonth;
+ time_t dateDay;
+ int dateHaveDate;
+
+ time_t dateHour;
+ time_t dateMinutes;
+ time_t dateSeconds;
+ int dateMeridian;
+ int dateHaveTime;
+
+ time_t dateTimezone;
+ int dateDSTmode;
+ int dateHaveZone;
+
+ time_t dateRelMonth;
+ time_t dateRelDay;
+ time_t dateRelSeconds;
+ int dateHaveRel;
+
+ time_t dateMonthOrdinal;
+ int dateHaveOrdinalMonth;
+
+ time_t dateDayOrdinal;
+ time_t dateDayNumber;
+ int dateHaveDay;
+
+ const char *dateStart;
+ const char *dateInput;
+ time_t *dateRelPointer;
+
+ int dateDigitCount;
+} DateInfo;
+
+#define YYMALLOC ckalloc
+#define YYFREE(x) (ckfree((void*) (x)))
+
+#define yyDSTmode (info->dateDSTmode)
+#define yyDayOrdinal (info->dateDayOrdinal)
+#define yyDayNumber (info->dateDayNumber)
+#define yyMonthOrdinal (info->dateMonthOrdinal)
+#define yyHaveDate (info->dateHaveDate)
+#define yyHaveDay (info->dateHaveDay)
+#define yyHaveOrdinalMonth (info->dateHaveOrdinalMonth)
+#define yyHaveRel (info->dateHaveRel)
+#define yyHaveTime (info->dateHaveTime)
+#define yyHaveZone (info->dateHaveZone)
+#define yyTimezone (info->dateTimezone)
+#define yyDay (info->dateDay)
+#define yyMonth (info->dateMonth)
+#define yyYear (info->dateYear)
+#define yyHour (info->dateHour)
+#define yyMinutes (info->dateMinutes)
+#define yySeconds (info->dateSeconds)
+#define yyMeridian (info->dateMeridian)
+#define yyRelMonth (info->dateRelMonth)
+#define yyRelDay (info->dateRelDay)
+#define yyRelSeconds (info->dateRelSeconds)
+#define yyRelPointer (info->dateRelPointer)
+#define yyInput (info->dateInput)
+#define yyDigitCount (info->dateDigitCount)
+
+#define EPOCH 1970
+#define START_OF_TIME 1902
+#define END_OF_TIME 2037
/*
* The offset of tm_year of struct tm returned by localtime, gmtime, etc.
- * I don't know how universal this is; K&R II, the NetBSD manpages, and
- * ../compat/strftime.c all agree that tm_year is the year-1900. However,
- * some systems may have a different value. This #define should be the
- * same as in ../compat/strftime.c.
+ * Posix requires 1900.
*/
-#define TM_YEAR_BASE 1900
-#define HOUR(x) ((int) (60 * x))
-#define SECSPERDAY (24L * 60L * 60L)
-#define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0))
+#define TM_YEAR_BASE 1900
+
+#define HOUR(x) ((int) (60 * x))
+#define SECSPERDAY (24L * 60L * 60L)
+#define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0))
/*
- * An entry in the lexical lookup table.
+ * An entry in the lexical lookup table.
*/
+
typedef struct _TABLE {
- char *name;
- int type;
- time_t value;
+ const char *name;
+ int type;
+ time_t value;
} TABLE;
-
/*
- * Daylight-savings mode: on, off, or not yet known.
+ * Daylight-savings mode: on, off, or not yet known.
*/
+
typedef enum _DSTMODE {
DSTon, DSToff, DSTmaybe
} DSTMODE;
/*
- * Meridian: am, pm, or 24-hour style.
+ * Meridian: am, pm, or 24-hour style.
*/
+
typedef enum _MERIDIAN {
MERam, MERpm, MER24
} MERIDIAN;
+%}
-/*
- * Global variables. We could get rid of most of these by using a good
- * union as the yacc stack. (This routine was originally written before
- * yacc had the %union construct.) Maybe someday; right now we only use
- * the %union very rarely.
- */
-static char *yyInput;
-static DSTMODE yyDSTmode;
-static time_t yyDayOrdinal;
-static time_t yyDayNumber;
-static time_t yyMonthOrdinal;
-static int yyHaveDate;
-static int yyHaveDay;
-static int yyHaveOrdinalMonth;
-static int yyHaveRel;
-static int yyHaveTime;
-static int yyHaveZone;
-static time_t yyTimezone;
-static time_t yyDay;
-static time_t yyHour;
-static time_t yyMinutes;
-static time_t yyMonth;
-static time_t yySeconds;
-static time_t yyYear;
-static MERIDIAN yyMeridian;
-static time_t yyRelMonth;
-static time_t yyRelDay;
-static time_t yyRelSeconds;
-static time_t *yyRelPointer;
+%union {
+ time_t Number;
+ enum _MERIDIAN Meridian;
+}
+
+%{
/*
* Prototypes of internal functions.
*/
-static void yyerror _ANSI_ARGS_((char *s));
-static time_t ToSeconds _ANSI_ARGS_((time_t Hours, time_t Minutes,
- time_t Seconds, MERIDIAN Meridian));
-static int Convert _ANSI_ARGS_((time_t Month, time_t Day, time_t Year,
- time_t Hours, time_t Minutes, time_t Seconds,
- MERIDIAN Meridia, DSTMODE DSTmode, time_t *TimePtr));
-static time_t DSTcorrect _ANSI_ARGS_((time_t Start, time_t Future));
-static time_t NamedDay _ANSI_ARGS_((time_t Start, time_t DayOrdinal,
- time_t DayNumber));
-static time_t NamedMonth _ANSI_ARGS_((time_t Start, time_t MonthOrdinal,
- time_t MonthNumber));
-static int RelativeMonth _ANSI_ARGS_((time_t Start, time_t RelMonth,
- time_t *TimePtr));
-static int RelativeDay _ANSI_ARGS_((time_t Start, time_t RelDay,
- time_t *TimePtr));
-static int LookupWord _ANSI_ARGS_((char *buff));
-static int yylex _ANSI_ARGS_((void));
-int
-yyparse _ANSI_ARGS_((void));
+static int LookupWord(YYSTYPE* yylvalPtr, char *buff);
+ static void TclDateerror(YYLTYPE* location,
+ DateInfo* info, const char *s);
+ static int TclDatelex(YYSTYPE* yylvalPtr, YYLTYPE* location,
+ DateInfo* info);
+static time_t ToSeconds(time_t Hours, time_t Minutes,
+ time_t Seconds, MERIDIAN Meridian);
+MODULE_SCOPE int yyparse(DateInfo*);
+
%}
-%union {
- time_t Number;
- enum _MERIDIAN Meridian;
-}
-
-%token tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
-%token tSTARDATE tSEC_UNIT tSNUMBER tUNUMBER tZONE tEPOCH tDST tISOBASE
-%token tDAY_UNIT tNEXT
-
-%type <Number> tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT tDST
-%type <Number> tSEC_UNIT tSNUMBER tUNUMBER tZONE tISOBASE tDAY_UNIT
-%type <Number> unit sign tNEXT tSTARDATE
-%type <Meridian> tMERIDIAN o_merid
+%token tAGO
+%token tDAY
+%token tDAYZONE
+%token tID
+%token tMERIDIAN
+%token tMONTH
+%token tMONTH_UNIT
+%token tSTARDATE
+%token tSEC_UNIT
+%token tSNUMBER
+%token tUNUMBER
+%token tZONE
+%token tEPOCH
+%token tDST
+%token tISOBASE
+%token tDAY_UNIT
+%token tNEXT
+
+%type <Number> tDAY
+%type <Number> tDAYZONE
+%type <Number> tMONTH
+%type <Number> tMONTH_UNIT
+%type <Number> tDST
+%type <Number> tSEC_UNIT
+%type <Number> tSNUMBER
+%type <Number> tUNUMBER
+%type <Number> tZONE
+%type <Number> tISOBASE
+%type <Number> tDAY_UNIT
+%type <Number> unit
+%type <Number> sign
+%type <Number> tNEXT
+%type <Number> tSTARDATE
+%type <Meridian> tMERIDIAN
+%type <Meridian> o_merid
%%
-spec : /* NULL */
- | spec item
- ;
-
-item : time {
- yyHaveTime++;
- }
- | zone {
- yyHaveZone++;
- }
- | date {
- yyHaveDate++;
- }
- | ordMonth {
- yyHaveOrdinalMonth++;
- }
- | day {
- yyHaveDay++;
- }
- | relspec {
- yyHaveRel++;
- }
- | iso {
+spec : /* NULL */
+ | spec item
+ ;
+
+item : time {
+ yyHaveTime++;
+ }
+ | zone {
+ yyHaveZone++;
+ }
+ | date {
+ yyHaveDate++;
+ }
+ | ordMonth {
+ yyHaveOrdinalMonth++;
+ }
+ | day {
+ yyHaveDay++;
+ }
+ | relspec {
+ yyHaveRel++;
+ }
+ | iso {
yyHaveTime++;
yyHaveDate++;
}
- | trek {
+ | trek {
yyHaveTime++;
yyHaveDate++;
yyHaveRel++;
- }
- | number
- ;
-
-time : tUNUMBER tMERIDIAN {
- yyHour = $1;
- yyMinutes = 0;
- yySeconds = 0;
- yyMeridian = $2;
- }
- | tUNUMBER ':' tUNUMBER o_merid {
- yyHour = $1;
- yyMinutes = $3;
- yySeconds = 0;
- yyMeridian = $4;
- }
- | tUNUMBER ':' tUNUMBER '-' tUNUMBER {
- yyHour = $1;
- yyMinutes = $3;
- yyMeridian = MER24;
- yyDSTmode = DSToff;
- yyTimezone = ($5 % 100 + ($5 / 100) * 60);
- }
- | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
- yyHour = $1;
- yyMinutes = $3;
- yySeconds = $5;
- yyMeridian = $6;
- }
- | tUNUMBER ':' tUNUMBER ':' tUNUMBER '-' tUNUMBER {
- yyHour = $1;
- yyMinutes = $3;
- yySeconds = $5;
- yyMeridian = MER24;
- yyDSTmode = DSToff;
- yyTimezone = ($7 % 100 + ($7 / 100) * 60);
- }
- ;
-
-zone : tZONE tDST {
- yyTimezone = $1;
- yyDSTmode = DSTon;
- }
- | tZONE {
- yyTimezone = $1;
- yyDSTmode = DSToff;
- }
- | tDAYZONE {
- yyTimezone = $1;
- yyDSTmode = DSTon;
- }
- ;
-
-day : tDAY {
- yyDayOrdinal = 1;
- yyDayNumber = $1;
- }
- | tDAY ',' {
- yyDayOrdinal = 1;
- yyDayNumber = $1;
- }
- | tUNUMBER tDAY {
- yyDayOrdinal = $1;
- yyDayNumber = $2;
- }
- | sign tUNUMBER tDAY {
- yyDayOrdinal = $1 * $2;
- yyDayNumber = $3;
- }
- | tNEXT tDAY {
- yyDayOrdinal = 2;
- yyDayNumber = $2;
- }
- ;
-
-date : tUNUMBER '/' tUNUMBER {
- yyMonth = $1;
- yyDay = $3;
- }
- | tUNUMBER '/' tUNUMBER '/' tUNUMBER {
- yyMonth = $1;
- yyDay = $3;
- yyYear = $5;
- }
- | tISOBASE {
+ }
+ | number
+ ;
+
+time : tUNUMBER tMERIDIAN {
+ yyHour = $1;
+ yyMinutes = 0;
+ yySeconds = 0;
+ yyMeridian = $2;
+ }
+ | tUNUMBER ':' tUNUMBER o_merid {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = 0;
+ yyMeridian = $4;
+ }
+ | tUNUMBER ':' tUNUMBER '-' tUNUMBER {
+ yyHour = $1;
+ yyMinutes = $3;
+ yyMeridian = MER24;
+ yyDSTmode = DSToff;
+ yyTimezone = ($5 % 100 + ($5 / 100) * 60);
+ ++yyHaveZone;
+ }
+ | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = $5;
+ yyMeridian = $6;
+ }
+ | tUNUMBER ':' tUNUMBER ':' tUNUMBER '-' tUNUMBER {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = $5;
+ yyMeridian = MER24;
+ yyDSTmode = DSToff;
+ yyTimezone = ($7 % 100 + ($7 / 100) * 60);
+ ++yyHaveZone;
+ }
+ ;
+
+zone : tZONE tDST {
+ yyTimezone = $1;
+ yyDSTmode = DSTon;
+ }
+ | tZONE {
+ yyTimezone = $1;
+ yyDSTmode = DSToff;
+ }
+ | tDAYZONE {
+ yyTimezone = $1;
+ yyDSTmode = DSTon;
+ }
+ ;
+
+day : tDAY {
+ yyDayOrdinal = 1;
+ yyDayNumber = $1;
+ }
+ | tDAY ',' {
+ yyDayOrdinal = 1;
+ yyDayNumber = $1;
+ }
+ | tUNUMBER tDAY {
+ yyDayOrdinal = $1;
+ yyDayNumber = $2;
+ }
+ | sign tUNUMBER tDAY {
+ yyDayOrdinal = $1 * $2;
+ yyDayNumber = $3;
+ }
+ | tNEXT tDAY {
+ yyDayOrdinal = 2;
+ yyDayNumber = $2;
+ }
+ ;
+
+date : tUNUMBER '/' tUNUMBER {
+ yyMonth = $1;
+ yyDay = $3;
+ }
+ | tUNUMBER '/' tUNUMBER '/' tUNUMBER {
+ yyMonth = $1;
+ yyDay = $3;
+ yyYear = $5;
+ }
+ | tISOBASE {
yyYear = $1 / 10000;
yyMonth = ($1 % 10000)/100;
yyDay = $1 % 100;
}
- | tUNUMBER '-' tMONTH '-' tUNUMBER {
+ | tUNUMBER '-' tMONTH '-' tUNUMBER {
yyDay = $1;
yyMonth = $3;
yyYear = $5;
}
- | tUNUMBER '-' tUNUMBER '-' tUNUMBER {
- yyMonth = $3;
- yyDay = $5;
- yyYear = $1;
- }
- | tMONTH tUNUMBER {
- yyMonth = $1;
- yyDay = $2;
- }
- | tMONTH tUNUMBER ',' tUNUMBER {
- yyMonth = $1;
- yyDay = $2;
- yyYear = $4;
- }
- | tUNUMBER tMONTH {
- yyMonth = $2;
- yyDay = $1;
- }
- | tEPOCH {
+ | tUNUMBER '-' tUNUMBER '-' tUNUMBER {
+ yyMonth = $3;
+ yyDay = $5;
+ yyYear = $1;
+ }
+ | tMONTH tUNUMBER {
+ yyMonth = $1;
+ yyDay = $2;
+ }
+ | tMONTH tUNUMBER ',' tUNUMBER {
+ yyMonth = $1;
+ yyDay = $2;
+ yyYear = $4;
+ }
+ | tUNUMBER tMONTH {
+ yyMonth = $2;
+ yyDay = $1;
+ }
+ | tEPOCH {
yyMonth = 1;
yyDay = 1;
yyYear = EPOCH;
}
- | tUNUMBER tMONTH tUNUMBER {
- yyMonth = $2;
- yyDay = $1;
- yyYear = $3;
- }
- ;
+ | tUNUMBER tMONTH tUNUMBER {
+ yyMonth = $2;
+ yyDay = $1;
+ yyYear = $3;
+ }
+ ;
ordMonth: tNEXT tMONTH {
yyMonthOrdinal = 1;
yyMonth = $2;
}
- | tNEXT tUNUMBER tMONTH {
+ | tNEXT tUNUMBER tMONTH {
yyMonthOrdinal = $2;
yyMonth = $3;
}
- ;
+ ;
-iso : tISOBASE tZONE tISOBASE {
- if ($2 != HOUR(- 7)) YYABORT;
+iso : tISOBASE tZONE tISOBASE {
+ if ($2 != HOUR( 7)) YYABORT;
yyYear = $1 / 10000;
yyMonth = ($1 % 10000)/100;
yyDay = $1 % 100;
yyHour = $3 / 10000;
yyMinutes = ($3 % 10000)/100;
yySeconds = $3 % 100;
- }
- | tISOBASE tZONE tUNUMBER ':' tUNUMBER ':' tUNUMBER {
- if ($2 != HOUR(- 7)) YYABORT;
+ }
+ | tISOBASE tZONE tUNUMBER ':' tUNUMBER ':' tUNUMBER {
+ if ($2 != HOUR( 7)) YYABORT;
yyYear = $1 / 10000;
yyMonth = ($1 % 10000)/100;
yyDay = $1 % 100;
yyHour = $3;
yyMinutes = $5;
yySeconds = $7;
- }
+ }
| tISOBASE tISOBASE {
yyYear = $1 / 10000;
yyMonth = ($1 % 10000)/100;
@@ -339,21 +411,22 @@ iso : tISOBASE tZONE tISOBASE {
yyHour = $2 / 10000;
yyMinutes = ($2 % 10000)/100;
yySeconds = $2 % 100;
- }
- ;
+ }
+ ;
-trek : tSTARDATE tUNUMBER '.' tUNUMBER {
- /*
- * Offset computed year by -377 so that the returned years will
- * be in a range accessible with a 32 bit clock seconds value
+trek : tSTARDATE tUNUMBER '.' tUNUMBER {
+ /*
+ * Offset computed year by -377 so that the returned years will be
+ * in a range accessible with a 32 bit clock seconds value.
*/
- yyYear = $2/1000 + 2323 - 377;
- yyDay = 1;
+
+ yyYear = $2/1000 + 2323 - 377;
+ yyDay = 1;
yyMonth = 1;
yyRelDay += (($2%1000)*(365 + IsLeapYear(yyYear)))/1000;
yyRelSeconds += $4 * 144 * 60;
- }
- ;
+ }
+ ;
relspec : relunits tAGO {
yyRelSeconds *= -1;
@@ -362,209 +435,241 @@ relspec : relunits tAGO {
}
| relunits
;
-relunits : sign tUNUMBER unit { *yyRelPointer += $1 * $2 * $3; }
- | tUNUMBER unit { *yyRelPointer += $1 * $2; }
- | tNEXT unit { *yyRelPointer += $2; }
- | tNEXT tUNUMBER unit { *yyRelPointer += $2 * $3; }
- | unit { *yyRelPointer += $1; }
- ;
-sign : '-' { $$ = -1; }
- | '+' { $$ = 1; }
- ;
-unit : tSEC_UNIT { $$ = $1; yyRelPointer = &yyRelSeconds; }
- | tDAY_UNIT { $$ = $1; yyRelPointer = &yyRelDay; }
- | tMONTH_UNIT { $$ = $1; yyRelPointer = &yyRelMonth; }
- ;
-
-number : tUNUMBER
- {
- if (yyHaveTime && yyHaveDate && !yyHaveRel) {
- yyYear = $1;
- } else {
- yyHaveTime++;
- if ($1 < 100) {
- yyHour = $1;
- yyMinutes = 0;
+
+relunits : sign tUNUMBER unit {
+ *yyRelPointer += $1 * $2 * $3;
+ }
+ | tUNUMBER unit {
+ *yyRelPointer += $1 * $2;
+ }
+ | tNEXT unit {
+ *yyRelPointer += $2;
+ }
+ | tNEXT tUNUMBER unit {
+ *yyRelPointer += $2 * $3;
+ }
+ | unit {
+ *yyRelPointer += $1;
+ }
+ ;
+
+sign : '-' {
+ $$ = -1;
+ }
+ | '+' {
+ $$ = 1;
+ }
+ ;
+
+unit : tSEC_UNIT {
+ $$ = $1;
+ yyRelPointer = &yyRelSeconds;
+ }
+ | tDAY_UNIT {
+ $$ = $1;
+ yyRelPointer = &yyRelDay;
+ }
+ | tMONTH_UNIT {
+ $$ = $1;
+ yyRelPointer = &yyRelMonth;
+ }
+ ;
+
+number : tUNUMBER {
+ if (yyHaveTime && yyHaveDate && !yyHaveRel) {
+ yyYear = $1;
} else {
- yyHour = $1 / 100;
- yyMinutes = $1 % 100;
+ yyHaveTime++;
+ if (yyDigitCount <= 2) {
+ yyHour = $1;
+ yyMinutes = 0;
+ } else {
+ yyHour = $1 / 100;
+ yyMinutes = $1 % 100;
+ }
+ yySeconds = 0;
+ yyMeridian = MER24;
}
- yySeconds = 0;
- yyMeridian = MER24;
}
- }
-;
+ ;
o_merid : /* NULL */ {
- $$ = MER24;
- }
- | tMERIDIAN {
- $$ = $1;
- }
- ;
+ $$ = MER24;
+ }
+ | tMERIDIAN {
+ $$ = $1;
+ }
+ ;
%%
+MODULE_SCOPE int yychar;
+MODULE_SCOPE YYSTYPE yylval;
+MODULE_SCOPE int yynerrs;
/*
* Month and day table.
*/
-static TABLE MonthDayTable[] = {
- { "january", tMONTH, 1 },
- { "february", tMONTH, 2 },
- { "march", tMONTH, 3 },
- { "april", tMONTH, 4 },
- { "may", tMONTH, 5 },
- { "june", tMONTH, 6 },
- { "july", tMONTH, 7 },
- { "august", tMONTH, 8 },
- { "september", tMONTH, 9 },
- { "sept", tMONTH, 9 },
- { "october", tMONTH, 10 },
- { "november", tMONTH, 11 },
- { "december", tMONTH, 12 },
- { "sunday", tDAY, 0 },
- { "monday", tDAY, 1 },
- { "tuesday", tDAY, 2 },
- { "tues", tDAY, 2 },
- { "wednesday", tDAY, 3 },
- { "wednes", tDAY, 3 },
- { "thursday", tDAY, 4 },
- { "thur", tDAY, 4 },
- { "thurs", tDAY, 4 },
- { "friday", tDAY, 5 },
- { "saturday", tDAY, 6 },
+
+static TABLE MonthDayTable[] = {
+ { "january", tMONTH, 1 },
+ { "february", tMONTH, 2 },
+ { "march", tMONTH, 3 },
+ { "april", tMONTH, 4 },
+ { "may", tMONTH, 5 },
+ { "june", tMONTH, 6 },
+ { "july", tMONTH, 7 },
+ { "august", tMONTH, 8 },
+ { "september", tMONTH, 9 },
+ { "sept", tMONTH, 9 },
+ { "october", tMONTH, 10 },
+ { "november", tMONTH, 11 },
+ { "december", tMONTH, 12 },
+ { "sunday", tDAY, 0 },
+ { "monday", tDAY, 1 },
+ { "tuesday", tDAY, 2 },
+ { "tues", tDAY, 2 },
+ { "wednesday", tDAY, 3 },
+ { "wednes", tDAY, 3 },
+ { "thursday", tDAY, 4 },
+ { "thur", tDAY, 4 },
+ { "thurs", tDAY, 4 },
+ { "friday", tDAY, 5 },
+ { "saturday", tDAY, 6 },
{ NULL }
};
/*
* Time units table.
*/
-static TABLE UnitsTable[] = {
- { "year", tMONTH_UNIT, 12 },
- { "month", tMONTH_UNIT, 1 },
- { "fortnight", tDAY_UNIT, 14 },
- { "week", tDAY_UNIT, 7 },
- { "day", tDAY_UNIT, 1 },
- { "hour", tSEC_UNIT, 60 * 60 },
- { "minute", tSEC_UNIT, 60 },
- { "min", tSEC_UNIT, 60 },
- { "second", tSEC_UNIT, 1 },
- { "sec", tSEC_UNIT, 1 },
+
+static TABLE UnitsTable[] = {
+ { "year", tMONTH_UNIT, 12 },
+ { "month", tMONTH_UNIT, 1 },
+ { "fortnight", tDAY_UNIT, 14 },
+ { "week", tDAY_UNIT, 7 },
+ { "day", tDAY_UNIT, 1 },
+ { "hour", tSEC_UNIT, 60 * 60 },
+ { "minute", tSEC_UNIT, 60 },
+ { "min", tSEC_UNIT, 60 },
+ { "second", tSEC_UNIT, 1 },
+ { "sec", tSEC_UNIT, 1 },
{ NULL }
};
/*
* Assorted relative-time words.
*/
-static TABLE OtherTable[] = {
- { "tomorrow", tDAY_UNIT, 1 },
- { "yesterday", tDAY_UNIT, -1 },
- { "today", tDAY_UNIT, 0 },
- { "now", tSEC_UNIT, 0 },
- { "last", tUNUMBER, -1 },
- { "this", tSEC_UNIT, 0 },
- { "next", tNEXT, 1 },
+
+static TABLE OtherTable[] = {
+ { "tomorrow", tDAY_UNIT, 1 },
+ { "yesterday", tDAY_UNIT, -1 },
+ { "today", tDAY_UNIT, 0 },
+ { "now", tSEC_UNIT, 0 },
+ { "last", tUNUMBER, -1 },
+ { "this", tSEC_UNIT, 0 },
+ { "next", tNEXT, 1 },
#if 0
- { "first", tUNUMBER, 1 },
- { "second", tUNUMBER, 2 },
- { "third", tUNUMBER, 3 },
- { "fourth", tUNUMBER, 4 },
- { "fifth", tUNUMBER, 5 },
- { "sixth", tUNUMBER, 6 },
- { "seventh", tUNUMBER, 7 },
- { "eighth", tUNUMBER, 8 },
- { "ninth", tUNUMBER, 9 },
- { "tenth", tUNUMBER, 10 },
- { "eleventh", tUNUMBER, 11 },
- { "twelfth", tUNUMBER, 12 },
+ { "first", tUNUMBER, 1 },
+ { "second", tUNUMBER, 2 },
+ { "third", tUNUMBER, 3 },
+ { "fourth", tUNUMBER, 4 },
+ { "fifth", tUNUMBER, 5 },
+ { "sixth", tUNUMBER, 6 },
+ { "seventh", tUNUMBER, 7 },
+ { "eighth", tUNUMBER, 8 },
+ { "ninth", tUNUMBER, 9 },
+ { "tenth", tUNUMBER, 10 },
+ { "eleventh", tUNUMBER, 11 },
+ { "twelfth", tUNUMBER, 12 },
#endif
- { "ago", tAGO, 1 },
- { "epoch", tEPOCH, 0 },
- { "stardate", tSTARDATE, 0},
+ { "ago", tAGO, 1 },
+ { "epoch", tEPOCH, 0 },
+ { "stardate", tSTARDATE, 0 },
{ NULL }
};
/*
- * The timezone table. (Note: This table was modified to not use any floating
+ * The timezone table. (Note: This table was modified to not use any floating
* point constants to work around an SGI compiler bug).
*/
-static TABLE TimezoneTable[] = {
- { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
- { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
- { "utc", tZONE, HOUR( 0) },
- { "uct", tZONE, HOUR( 0) }, /* Universal Coordinated Time */
- { "wet", tZONE, HOUR( 0) }, /* Western European */
- { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
- { "wat", tZONE, HOUR( 1) }, /* West Africa */
- { "at", tZONE, HOUR( 2) }, /* Azores */
-#if 0
+
+static TABLE TimezoneTable[] = {
+ { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
+ { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
+ { "utc", tZONE, HOUR( 0) },
+ { "uct", tZONE, HOUR( 0) }, /* Universal Coordinated Time */
+ { "wet", tZONE, HOUR( 0) }, /* Western European */
+ { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
+ { "wat", tZONE, HOUR( 1) }, /* West Africa */
+ { "at", tZONE, HOUR( 2) }, /* Azores */
+#if 0
/* For completeness. BST is also British Summer, and GST is
* also Guam Standard. */
- { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
- { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
+ { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
+ { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
#endif
- { "nft", tZONE, HOUR( 7/2) }, /* Newfoundland */
- { "nst", tZONE, HOUR( 7/2) }, /* Newfoundland Standard */
- { "ndt", tDAYZONE, HOUR( 7/2) }, /* Newfoundland Daylight */
- { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
- { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
- { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
- { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
- { "cst", tZONE, HOUR( 6) }, /* Central Standard */
- { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
- { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
- { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
- { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
- { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
- { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
- { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
- { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
- { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
- { "cat", tZONE, HOUR(10) }, /* Central Alaska */
- { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
- { "nt", tZONE, HOUR(11) }, /* Nome */
- { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
- { "cet", tZONE, -HOUR( 1) }, /* Central European */
- { "cest", tDAYZONE, -HOUR( 1) }, /* Central European Summer */
- { "met", tZONE, -HOUR( 1) }, /* Middle European */
- { "mewt", tZONE, -HOUR( 1) }, /* Middle European Winter */
- { "mest", tDAYZONE, -HOUR( 1) }, /* Middle European Summer */
- { "swt", tZONE, -HOUR( 1) }, /* Swedish Winter */
- { "sst", tDAYZONE, -HOUR( 1) }, /* Swedish Summer */
- { "fwt", tZONE, -HOUR( 1) }, /* French Winter */
- { "fst", tDAYZONE, -HOUR( 1) }, /* French Summer */
- { "eet", tZONE, -HOUR( 2) }, /* Eastern Europe, USSR Zone 1 */
- { "bt", tZONE, -HOUR( 3) }, /* Baghdad, USSR Zone 2 */
- { "it", tZONE, -HOUR( 7/2) }, /* Iran */
- { "zp4", tZONE, -HOUR( 4) }, /* USSR Zone 3 */
- { "zp5", tZONE, -HOUR( 5) }, /* USSR Zone 4 */
- { "ist", tZONE, -HOUR(11/2) }, /* Indian Standard */
- { "zp6", tZONE, -HOUR( 6) }, /* USSR Zone 5 */
-#if 0
+ { "nft", tZONE, HOUR( 7/2) }, /* Newfoundland */
+ { "nst", tZONE, HOUR( 7/2) }, /* Newfoundland Standard */
+ { "ndt", tDAYZONE, HOUR( 7/2) }, /* Newfoundland Daylight */
+ { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
+ { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
+ { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
+ { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
+ { "cst", tZONE, HOUR( 6) }, /* Central Standard */
+ { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
+ { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
+ { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
+ { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
+ { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
+ { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
+ { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
+ { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
+ { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
+ { "cat", tZONE, HOUR(10) }, /* Central Alaska */
+ { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
+ { "nt", tZONE, HOUR(11) }, /* Nome */
+ { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
+ { "cet", tZONE, -HOUR( 1) }, /* Central European */
+ { "cest", tDAYZONE, -HOUR( 1) }, /* Central European Summer */
+ { "met", tZONE, -HOUR( 1) }, /* Middle European */
+ { "mewt", tZONE, -HOUR( 1) }, /* Middle European Winter */
+ { "mest", tDAYZONE, -HOUR( 1) }, /* Middle European Summer */
+ { "swt", tZONE, -HOUR( 1) }, /* Swedish Winter */
+ { "sst", tDAYZONE, -HOUR( 1) }, /* Swedish Summer */
+ { "fwt", tZONE, -HOUR( 1) }, /* French Winter */
+ { "fst", tDAYZONE, -HOUR( 1) }, /* French Summer */
+ { "eet", tZONE, -HOUR( 2) }, /* Eastern Europe, USSR Zone 1 */
+ { "bt", tZONE, -HOUR( 3) }, /* Baghdad, USSR Zone 2 */
+ { "it", tZONE, -HOUR( 7/2) }, /* Iran */
+ { "zp4", tZONE, -HOUR( 4) }, /* USSR Zone 3 */
+ { "zp5", tZONE, -HOUR( 5) }, /* USSR Zone 4 */
+ { "ist", tZONE, -HOUR(11/2) }, /* Indian Standard */
+ { "zp6", tZONE, -HOUR( 6) }, /* USSR Zone 5 */
+#if 0
/* For completeness. NST is also Newfoundland Stanard, nad SST is
* also Swedish Summer. */
- { "nst", tZONE, -HOUR(13/2) }, /* North Sumatra */
- { "sst", tZONE, -HOUR( 7) }, /* South Sumatra, USSR Zone 6 */
-#endif /* 0 */
- { "wast", tZONE, -HOUR( 7) }, /* West Australian Standard */
- { "wadt", tDAYZONE, -HOUR( 7) }, /* West Australian Daylight */
- { "jt", tZONE, -HOUR(15/2) }, /* Java (3pm in Cronusland!) */
- { "cct", tZONE, -HOUR( 8) }, /* China Coast, USSR Zone 7 */
- { "jst", tZONE, -HOUR( 9) }, /* Japan Standard, USSR Zone 8 */
- { "jdt", tDAYZONE, -HOUR( 9) }, /* Japan Daylight */
- { "kst", tZONE, -HOUR( 9) }, /* Korea Standard */
- { "kdt", tDAYZONE, -HOUR( 9) }, /* Korea Daylight */
- { "cast", tZONE, -HOUR(19/2) }, /* Central Australian Standard */
- { "cadt", tDAYZONE, -HOUR(19/2) }, /* Central Australian Daylight */
- { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
- { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
- { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
- { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
- { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
- { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
- { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
+ { "nst", tZONE, -HOUR(13/2) }, /* North Sumatra */
+ { "sst", tZONE, -HOUR( 7) }, /* South Sumatra, USSR Zone 6 */
+#endif /* 0 */
+ { "wast", tZONE, -HOUR( 7) }, /* West Australian Standard */
+ { "wadt", tDAYZONE, -HOUR( 7) }, /* West Australian Daylight */
+ { "jt", tZONE, -HOUR(15/2) }, /* Java (3pm in Cronusland!) */
+ { "cct", tZONE, -HOUR( 8) }, /* China Coast, USSR Zone 7 */
+ { "jst", tZONE, -HOUR( 9) }, /* Japan Standard, USSR Zone 8 */
+ { "jdt", tDAYZONE, -HOUR( 9) }, /* Japan Daylight */
+ { "kst", tZONE, -HOUR( 9) }, /* Korea Standard */
+ { "kdt", tDAYZONE, -HOUR( 9) }, /* Korea Daylight */
+ { "cast", tZONE, -HOUR(19/2) }, /* Central Australian Standard */
+ { "cadt", tDAYZONE, -HOUR(19/2) }, /* Central Australian Daylight */
+ { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
+ { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
+ { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
+ { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
+ { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
+ { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
+ { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
/* ADDED BY Marco Nijdam */
- { "dst", tDST, HOUR( 0) }, /* DST on (hour is ignored) */
+ { "dst", tDST, HOUR( 0) }, /* DST on (hour is ignored) */
/* End ADDED */
{ NULL }
};
@@ -572,311 +677,102 @@ static TABLE TimezoneTable[] = {
/*
* Military timezone table.
*/
-static TABLE MilitaryTable[] = {
- { "a", tZONE, HOUR( 1) },
- { "b", tZONE, HOUR( 2) },
- { "c", tZONE, HOUR( 3) },
- { "d", tZONE, HOUR( 4) },
- { "e", tZONE, HOUR( 5) },
- { "f", tZONE, HOUR( 6) },
- { "g", tZONE, HOUR( 7) },
- { "h", tZONE, HOUR( 8) },
- { "i", tZONE, HOUR( 9) },
- { "k", tZONE, HOUR( 10) },
- { "l", tZONE, HOUR( 11) },
- { "m", tZONE, HOUR( 12) },
- { "n", tZONE, HOUR(- 1) },
- { "o", tZONE, HOUR(- 2) },
- { "p", tZONE, HOUR(- 3) },
- { "q", tZONE, HOUR(- 4) },
- { "r", tZONE, HOUR(- 5) },
- { "s", tZONE, HOUR(- 6) },
- { "t", tZONE, HOUR(- 7) },
- { "u", tZONE, HOUR(- 8) },
- { "v", tZONE, HOUR(- 9) },
- { "w", tZONE, HOUR(-10) },
- { "x", tZONE, HOUR(-11) },
- { "y", tZONE, HOUR(-12) },
- { "z", tZONE, HOUR( 0) },
+
+static TABLE MilitaryTable[] = {
+ { "a", tZONE, -HOUR( 1) },
+ { "b", tZONE, -HOUR( 2) },
+ { "c", tZONE, -HOUR( 3) },
+ { "d", tZONE, -HOUR( 4) },
+ { "e", tZONE, -HOUR( 5) },
+ { "f", tZONE, -HOUR( 6) },
+ { "g", tZONE, -HOUR( 7) },
+ { "h", tZONE, -HOUR( 8) },
+ { "i", tZONE, -HOUR( 9) },
+ { "k", tZONE, -HOUR(10) },
+ { "l", tZONE, -HOUR(11) },
+ { "m", tZONE, -HOUR(12) },
+ { "n", tZONE, HOUR( 1) },
+ { "o", tZONE, HOUR( 2) },
+ { "p", tZONE, HOUR( 3) },
+ { "q", tZONE, HOUR( 4) },
+ { "r", tZONE, HOUR( 5) },
+ { "s", tZONE, HOUR( 6) },
+ { "t", tZONE, HOUR( 7) },
+ { "u", tZONE, HOUR( 8) },
+ { "v", tZONE, HOUR( 9) },
+ { "w", tZONE, HOUR( 10) },
+ { "x", tZONE, HOUR( 11) },
+ { "y", tZONE, HOUR( 12) },
+ { "z", tZONE, HOUR( 0) },
{ NULL }
};
-
/*
* Dump error messages in the bit bucket.
*/
+
static void
-yyerror(s)
- char *s;
+TclDateerror(
+ YYLTYPE* location,
+ DateInfo* infoPtr,
+ const char *s)
{
+ Tcl_Obj* t;
+ Tcl_AppendToObj(infoPtr->messages, infoPtr->separatrix, -1);
+ Tcl_AppendToObj(infoPtr->messages, s, -1);
+ Tcl_AppendToObj(infoPtr->messages, " (characters ", -1);
+ t = Tcl_NewIntObj(location->first_column);
+ Tcl_IncrRefCount(t);
+ Tcl_AppendObjToObj(infoPtr->messages, t);
+ Tcl_DecrRefCount(t);
+ Tcl_AppendToObj(infoPtr->messages, "-", -1);
+ t = Tcl_NewIntObj(location->last_column);
+ Tcl_IncrRefCount(t);
+ Tcl_AppendObjToObj(infoPtr->messages, t);
+ Tcl_DecrRefCount(t);
+ Tcl_AppendToObj(infoPtr->messages, ")", -1);
+ infoPtr->separatrix = "\n";
}
-
static time_t
-ToSeconds(Hours, Minutes, Seconds, Meridian)
- time_t Hours;
- time_t Minutes;
- time_t Seconds;
- MERIDIAN Meridian;
+ToSeconds(
+ time_t Hours,
+ time_t Minutes,
+ time_t Seconds,
+ MERIDIAN Meridian)
{
- if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
- return -1;
+ if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59) {
+ return -1;
+ }
switch (Meridian) {
case MER24:
- if (Hours < 0 || Hours > 23)
- return -1;
- return (Hours * 60L + Minutes) * 60L + Seconds;
+ if (Hours < 0 || Hours > 23) {
+ return -1;
+ }
+ return (Hours * 60L + Minutes) * 60L + Seconds;
case MERam:
- if (Hours < 1 || Hours > 12)
- return -1;
- return ((Hours % 12) * 60L + Minutes) * 60L + Seconds;
+ if (Hours < 1 || Hours > 12) {
+ return -1;
+ }
+ return ((Hours % 12) * 60L + Minutes) * 60L + Seconds;
case MERpm:
- if (Hours < 1 || Hours > 12)
- return -1;
- return (((Hours % 12) + 12) * 60L + Minutes) * 60L + Seconds;
- }
- return -1; /* Should never be reached */
-}
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Convert --
- *
- * Convert a {month, day, year, hours, minutes, seconds, meridian, dst}
- * tuple into a clock seconds value.
- *
- * Results:
- * 0 or -1 indicating success or failure.
- *
- * Side effects:
- * Fills TimePtr with the computed value.
- *
- *-----------------------------------------------------------------------------
- */
-static int
-Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode, TimePtr)
- time_t Month;
- time_t Day;
- time_t Year;
- time_t Hours;
- time_t Minutes;
- time_t Seconds;
- MERIDIAN Meridian;
- DSTMODE DSTmode;
- time_t *TimePtr;
-{
- static int DaysInMonth[12] = {
- 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
- };
- time_t tod;
- time_t Julian;
- int i;
-
- /* Figure out how many days are in February for the given year.
- * Every year divisible by 4 is a leap year.
- * But, every year divisible by 100 is not a leap year.
- * But, every year divisible by 400 is a leap year after all.
- */
- DaysInMonth[1] = IsLeapYear(Year) ? 29 : 28;
-
- /* Check the inputs for validity */
- if (Month < 1 || Month > 12
- || Year < START_OF_TIME || Year > END_OF_TIME
- || Day < 1 || Day > DaysInMonth[(int)--Month])
- return -1;
-
- /* Start computing the value. First determine the number of days
- * represented by the date, then multiply by the number of seconds/day.
- */
- for (Julian = Day - 1, i = 0; i < Month; i++)
- Julian += DaysInMonth[i];
- if (Year >= EPOCH) {
- for (i = EPOCH; i < Year; i++)
- Julian += 365 + IsLeapYear(i);
- } else {
- for (i = Year; i < EPOCH; i++)
- Julian -= 365 + IsLeapYear(i);
- }
- Julian *= SECSPERDAY;
-
- /* Add the timezone offset ?? */
- Julian += yyTimezone * 60L;
-
- /* Add the number of seconds represented by the time component */
- if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
- return -1;
- Julian += tod;
-
- /* Perform a preliminary DST compensation ?? */
- if (DSTmode == DSTon
- || (DSTmode == DSTmaybe && TclpGetDate((TclpTime_t)&Julian, 0)->tm_isdst))
- Julian -= 60 * 60;
- *TimePtr = Julian;
- return 0;
-}
-
-
-static time_t
-DSTcorrect(Start, Future)
- time_t Start;
- time_t Future;
-{
- time_t StartDay;
- time_t FutureDay;
- StartDay = (TclpGetDate((TclpTime_t)&Start, 0)->tm_hour + 1) % 24;
- FutureDay = (TclpGetDate((TclpTime_t)&Future, 0)->tm_hour + 1) % 24;
- return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
-}
-
-
-static time_t
-NamedDay(Start, DayOrdinal, DayNumber)
- time_t Start;
- time_t DayOrdinal;
- time_t DayNumber;
-{
- struct tm *tm;
- time_t now;
-
- now = Start;
- tm = TclpGetDate((TclpTime_t)&now, 0);
- now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
- now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
- return DSTcorrect(Start, now);
-}
-
-static time_t
-NamedMonth(Start, MonthOrdinal, MonthNumber)
- time_t Start;
- time_t MonthOrdinal;
- time_t MonthNumber;
-{
- struct tm *tm;
- time_t now;
- int result;
-
- now = Start;
- tm = TclpGetDate((TclpTime_t)&now, 0);
- /* To compute the next n'th month, we use this alg:
- * add n to year value
- * if currentMonth < requestedMonth decrement year value by 1 (so that
- * doing next february from january gives us february of the current year)
- * set day to 1, time to 0
- */
- tm->tm_year += MonthOrdinal;
- if (tm->tm_mon < MonthNumber - 1) {
- tm->tm_year--;
- }
- result = Convert(MonthNumber, (time_t) 1, tm->tm_year + TM_YEAR_BASE,
- (time_t) 0, (time_t) 0, (time_t) 0, MER24, DSTmaybe, &now);
- if (result < 0) {
- return 0;
- }
- return DSTcorrect(Start, now);
-}
-
-static int
-RelativeMonth(Start, RelMonth, TimePtr)
- time_t Start;
- time_t RelMonth;
- time_t *TimePtr;
-{
- struct tm *tm;
- time_t Month;
- time_t Year;
- time_t Julian;
- int result;
-
- if (RelMonth == 0) {
- *TimePtr = 0;
- return 0;
- }
- tm = TclpGetDate((TclpTime_t)&Start, 0);
- Month = 12 * (tm->tm_year + TM_YEAR_BASE) + tm->tm_mon + RelMonth;
- Year = Month / 12;
- Month = Month % 12 + 1;
- result = Convert(Month, (time_t) tm->tm_mday, Year,
- (time_t) tm->tm_hour, (time_t) tm->tm_min, (time_t) tm->tm_sec,
- MER24, DSTmaybe, &Julian);
-
- /*
- * The Julian time returned above is behind by one day, if "month"
- * or "year" is used to specify relative time and the GMT flag is true.
- * This problem occurs only when the current time is closer to
- * midnight, the difference being not more than its time difference
- * with GMT. For example, in US/Pacific time zone, the problem occurs
- * whenever the current time is between midnight to 8:00am or 7:00amDST.
- * See Bug# 413397 for more details and sample script.
- * To resolve this bug, we simply add the number of seconds corresponding
- * to timezone difference with GMT to Julian time, if GMT flag is true.
- */
-
- if (TclDateTimezone == 0) {
- Julian += TclpGetTimeZone((unsigned long) Start) * 60L;
- }
-
- /*
- * The following iteration takes into account the case were we jump
- * into a "short month". Far example, "one month from Jan 31" will
- * fail because there is no Feb 31. The code below will reduce the
- * day and try converting the date until we succed or the date equals
- * 28 (which always works unless the date is bad in another way).
- */
-
- while ((result != 0) && (tm->tm_mday > 28)) {
- tm->tm_mday--;
- result = Convert(Month, (time_t) tm->tm_mday, Year,
- (time_t) tm->tm_hour, (time_t) tm->tm_min, (time_t) tm->tm_sec,
- MER24, DSTmaybe, &Julian);
- }
- if (result != 0) {
- return -1;
+ if (Hours < 1 || Hours > 12) {
+ return -1;
+ }
+ return (((Hours % 12) + 12) * 60L + Minutes) * 60L + Seconds;
}
- *TimePtr = DSTcorrect(Start, Julian);
- return 0;
+ return -1; /* Should never be reached */
}
-
-/*
- *-----------------------------------------------------------------------------
- *
- * RelativeDay --
- *
- * Given a starting time and a number of days before or after, compute the
- * DST corrected difference between those dates.
- *
- * Results:
- * 1 or -1 indicating success or failure.
- *
- * Side effects:
- * Fills TimePtr with the computed value.
- *
- *-----------------------------------------------------------------------------
- */
-
static int
-RelativeDay(Start, RelDay, TimePtr)
- time_t Start;
- time_t RelDay;
- time_t *TimePtr;
-{
- time_t new;
-
- new = Start + (RelDay * 60 * 60 * 24);
- *TimePtr = DSTcorrect(Start, new);
- return 1;
-}
-
-static int
-LookupWord(buff)
- char *buff;
+LookupWord(
+ YYSTYPE* yylvalPtr,
+ char *buff)
{
register char *p;
register char *q;
register TABLE *tp;
- int i;
- int abbrev;
+ int i, abbrev;
/*
* Make it lowercase.
@@ -885,273 +781,346 @@ LookupWord(buff)
Tcl_UtfToLower(buff);
if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
- yylval.Meridian = MERam;
- return tMERIDIAN;
+ yylvalPtr->Meridian = MERam;
+ return tMERIDIAN;
}
if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
- yylval.Meridian = MERpm;
- return tMERIDIAN;
+ yylvalPtr->Meridian = MERpm;
+ return tMERIDIAN;
}
/*
* See if we have an abbreviation for a month.
*/
+
if (strlen(buff) == 3) {
- abbrev = 1;
+ abbrev = 1;
} else if (strlen(buff) == 4 && buff[3] == '.') {
- abbrev = 1;
- buff[3] = '\0';
+ abbrev = 1;
+ buff[3] = '\0';
} else {
- abbrev = 0;
+ abbrev = 0;
}
for (tp = MonthDayTable; tp->name; tp++) {
- if (abbrev) {
- if (strncmp(buff, tp->name, 3) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
- } else if (strcmp(buff, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
+ if (abbrev) {
+ if (strncmp(buff, tp->name, 3) == 0) {
+ yylvalPtr->Number = tp->value;
+ return tp->type;
+ }
+ } else if (strcmp(buff, tp->name) == 0) {
+ yylvalPtr->Number = tp->value;
+ return tp->type;
+ }
}
for (tp = TimezoneTable; tp->name; tp++) {
- if (strcmp(buff, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
+ if (strcmp(buff, tp->name) == 0) {
+ yylvalPtr->Number = tp->value;
+ return tp->type;
+ }
}
for (tp = UnitsTable; tp->name; tp++) {
- if (strcmp(buff, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
+ if (strcmp(buff, tp->name) == 0) {
+ yylvalPtr->Number = tp->value;
+ return tp->type;
+ }
}
/*
* Strip off any plural and try the units table again.
*/
+
i = strlen(buff) - 1;
- if (buff[i] == 's') {
- buff[i] = '\0';
- for (tp = UnitsTable; tp->name; tp++) {
- if (strcmp(buff, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
+ if (i > 0 && buff[i] == 's') {
+ buff[i] = '\0';
+ for (tp = UnitsTable; tp->name; tp++) {
+ if (strcmp(buff, tp->name) == 0) {
+ yylvalPtr->Number = tp->value;
+ return tp->type;
+ }
}
}
for (tp = OtherTable; tp->name; tp++) {
- if (strcmp(buff, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
+ if (strcmp(buff, tp->name) == 0) {
+ yylvalPtr->Number = tp->value;
+ return tp->type;
+ }
}
/*
* Military timezones.
*/
+
if (buff[1] == '\0' && !(*buff & 0x80)
- && isalpha(UCHAR(*buff))) { /* INTL: ISO only */
- for (tp = MilitaryTable; tp->name; tp++) {
- if (strcmp(buff, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
+ && isalpha(UCHAR(*buff))) { /* INTL: ISO only */
+ for (tp = MilitaryTable; tp->name; tp++) {
+ if (strcmp(buff, tp->name) == 0) {
+ yylvalPtr->Number = tp->value;
+ return tp->type;
+ }
}
}
/*
* Drop out any periods and try the timezone table again.
*/
- for (i = 0, p = q = buff; *q; q++)
- if (*q != '.') {
- *p++ = *q;
- } else {
- i++;
+
+ for (i = 0, p = q = buff; *q; q++) {
+ if (*q != '.') {
+ *p++ = *q;
+ } else {
+ i++;
}
+ }
*p = '\0';
if (i) {
- for (tp = TimezoneTable; tp->name; tp++) {
- if (strcmp(buff, tp->name) == 0) {
- yylval.Number = tp->value;
- return tp->type;
- }
+ for (tp = TimezoneTable; tp->name; tp++) {
+ if (strcmp(buff, tp->name) == 0) {
+ yylvalPtr->Number = tp->value;
+ return tp->type;
+ }
}
}
-
+
return tID;
}
-
static int
-yylex()
+TclDatelex(
+ YYSTYPE* yylvalPtr,
+ YYLTYPE* location,
+ DateInfo *info)
{
- register char c;
- register char *p;
- char buff[20];
- int Count;
+ register char c;
+ register char *p;
+ char buff[20];
+ int Count;
+ location->first_column = yyInput - info->dateStart;
for ( ; ; ) {
- while (isspace(UCHAR(*yyInput))) {
- yyInput++;
+ while (isspace(UCHAR(*yyInput))) {
+ yyInput++;
}
- if (isdigit(UCHAR(c = *yyInput))) { /* INTL: digit */
- /* convert the string into a number; count the number of digits */
+ if (isdigit(UCHAR(c = *yyInput))) { /* INTL: digit */
+ /*
+ * Convert the string into a number; count the number of digits.
+ */
+
Count = 0;
- for (yylval.Number = 0;
- isdigit(UCHAR(c = *yyInput++)); ) { /* INTL: digit */
- yylval.Number = 10 * yylval.Number + c - '0';
+ for (yylvalPtr->Number = 0;
+ isdigit(UCHAR(c = *yyInput++)); ) { /* INTL: digit */
+ yylvalPtr->Number = 10 * yylvalPtr->Number + c - '0';
Count++;
}
- yyInput--;
- /* A number with 6 or more digits is considered an ISO 8601 base */
+ yyInput--;
+ yyDigitCount = Count;
+
+ /*
+ * A number with 6 or more digits is considered an ISO 8601 base.
+ */
+
if (Count >= 6) {
+ location->last_column = yyInput - info->dateStart - 1;
return tISOBASE;
} else {
+ location->last_column = yyInput - info->dateStart - 1;
return tUNUMBER;
}
- }
- if (!(c & 0x80) && isalpha(UCHAR(c))) { /* INTL: ISO only. */
- for (p = buff; isalpha(UCHAR(c = *yyInput++)) /* INTL: ISO only. */
+ }
+ if (!(c & 0x80) && isalpha(UCHAR(c))) { /* INTL: ISO only. */
+ for (p = buff; isalpha(UCHAR(c = *yyInput++)) /* INTL: ISO only. */
|| c == '.'; ) {
- if (p < &buff[sizeof buff - 1]) {
- *p++ = c;
+ if (p < &buff[sizeof buff - 1]) {
+ *p++ = c;
}
}
- *p = '\0';
- yyInput--;
- return LookupWord(buff);
- }
- if (c != '(') {
- return *yyInput++;
- }
- Count = 0;
- do {
- c = *yyInput++;
- if (c == '\0') {
- return c;
+ *p = '\0';
+ yyInput--;
+ location->last_column = yyInput - info->dateStart - 1;
+ return LookupWord(yylvalPtr, buff);
+ }
+ if (c != '(') {
+ location->last_column = yyInput - info->dateStart;
+ return *yyInput++;
+ }
+ Count = 0;
+ do {
+ c = *yyInput++;
+ if (c == '\0') {
+ location->last_column = yyInput - info->dateStart - 1;
+ return c;
} else if (c == '(') {
- Count++;
+ Count++;
} else if (c == ')') {
- Count--;
+ Count--;
}
- } while (Count > 0);
+ } while (Count > 0);
}
}
-/*
- * Specify zone is of -50000 to force GMT. (This allows BST to work).
- */
-
int
-TclGetDate(p, now, zone, timePtr)
- char *p;
- Tcl_WideInt now;
- long zone;
- Tcl_WideInt *timePtr;
+TclClockOldscanObjCmd(
+ ClientData clientData, /* Unused */
+ Tcl_Interp *interp, /* Tcl interpreter */
+ int objc, /* Count of paraneters */
+ Tcl_Obj *CONST *objv) /* Parameters */
{
- struct tm *tm;
- time_t Start;
- time_t Time;
- time_t tod;
- int thisyear;
-
- yyInput = p;
- /* now has to be cast to a time_t for 64bit compliance */
- Start = (time_t) now;
- tm = TclpGetDate((TclpTime_t) &Start, (zone == -50000));
- thisyear = tm->tm_year + TM_YEAR_BASE;
- yyYear = thisyear;
- yyMonth = tm->tm_mon + 1;
- yyDay = tm->tm_mday;
- yyTimezone = zone;
- if (zone == -50000) {
- yyDSTmode = DSToff; /* assume GMT */
- yyTimezone = 0;
- } else {
- yyDSTmode = DSTmaybe;
+ Tcl_Obj *result, *resultElement;
+ int yr, mo, da;
+ DateInfo dateInfo;
+ DateInfo* info = &dateInfo;
+ int status;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "stringToParse baseYear baseMonth baseDay" );
+ return TCL_ERROR;
}
- yyHour = 0;
- yyMinutes = 0;
- yySeconds = 0;
- yyMeridian = MER24;
- yyRelSeconds = 0;
- yyRelMonth = 0;
- yyRelDay = 0;
- yyRelPointer = NULL;
+
+ yyInput = Tcl_GetString( objv[1] );
+ dateInfo.dateStart = yyInput;
yyHaveDate = 0;
- yyHaveDay = 0;
- yyHaveOrdinalMonth = 0;
- yyHaveRel = 0;
+ if (Tcl_GetIntFromObj(interp, objv[2], &yr) != TCL_OK
+ || Tcl_GetIntFromObj(interp, objv[3], &mo) != TCL_OK
+ || Tcl_GetIntFromObj(interp, objv[4], &da) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ yyYear = yr; yyMonth = mo; yyDay = da;
+
yyHaveTime = 0;
+ yyHour = 0; yyMinutes = 0; yySeconds = 0; yyMeridian = MER24;
+
yyHaveZone = 0;
+ yyTimezone = 0; yyDSTmode = DSTmaybe;
+
+ yyHaveOrdinalMonth = 0;
+ yyMonthOrdinal = 0;
+
+ yyHaveDay = 0;
+ yyDayOrdinal = 0; yyDayNumber = 0;
- if (yyparse() || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 ||
- yyHaveDay > 1 || yyHaveOrdinalMonth > 1) {
- return -1;
+ yyHaveRel = 0;
+ yyRelMonth = 0; yyRelDay = 0; yyRelSeconds = 0; yyRelPointer = NULL;
+
+ dateInfo.messages = Tcl_NewObj();
+ dateInfo.separatrix = "";
+ Tcl_IncrRefCount(dateInfo.messages);
+
+ status = yyparse(&dateInfo);
+ if (status == 1) {
+ Tcl_SetObjResult(interp, dateInfo.messages);
+ Tcl_DecrRefCount(dateInfo.messages);
+ return TCL_ERROR;
+ } else if (status == 2) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("memory exhausted", -1));
+ Tcl_DecrRefCount(dateInfo.messages);
+ return TCL_ERROR;
+ } else if (status != 0) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("Unknown status returned "
+ "from date parser. Please "
+ "report this error as a "
+ "bug in Tcl.", -1));
+ Tcl_DecrRefCount(dateInfo.messages);
+ return TCL_ERROR;
}
-
- if (yyHaveDate || yyHaveTime || yyHaveDay) {
- if (TclDateYear < 0) {
- TclDateYear = -TclDateYear;
- }
- /*
- * The following line handles years that are specified using
- * only two digits. The line of code below implements a policy
- * defined by the X/Open workgroup on the millinium rollover.
- * Note: some of those dates may not actually be valid on some
- * platforms. The POSIX standard startes that the dates 70-99
- * shall refer to 1970-1999 and 00-38 shall refer to 2000-2038.
- * This later definition should work on all platforms.
- */
-
- if (TclDateYear < 100) {
- if (TclDateYear >= 69) {
- TclDateYear += 1900;
- } else {
- TclDateYear += 2000;
- }
- }
- if (Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
- yyMeridian, yyDSTmode, &Start) < 0) {
- return -1;
- }
- } else {
- Start = (time_t) now;
- if (!yyHaveRel) {
- Start -= ((tm->tm_hour * 60L * 60L) +
- tm->tm_min * 60L) + tm->tm_sec;
- }
+ Tcl_DecrRefCount(dateInfo.messages);
+
+ if (yyHaveDate > 1) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("more than one date in string", -1));
+ return TCL_ERROR;
+ }
+ if (yyHaveTime > 1) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("more than one time of day in string", -1));
+ return TCL_ERROR;
+ }
+ if (yyHaveZone > 1) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("more than one time zone in string", -1));
+ return TCL_ERROR;
+ }
+ if (yyHaveDay > 1) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("more than one weekday in string", -1));
+ return TCL_ERROR;
+ }
+ if (yyHaveOrdinalMonth > 1) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("more than one ordinal month in string", -1));
+ return TCL_ERROR;
}
- Start += yyRelSeconds;
- if (RelativeMonth(Start, yyRelMonth, &Time) < 0) {
- return -1;
+ result = Tcl_NewObj();
+ resultElement = Tcl_NewObj();
+ if (yyHaveDate) {
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) yyYear));
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) yyMonth));
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) yyDay));
}
- Start += Time;
+ Tcl_ListObjAppendElement(interp, result, resultElement);
- if (RelativeDay(Start, yyRelDay, &Time) < 0) {
- return -1;
+ if (yyHaveTime) {
+ Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj((int)
+ ToSeconds(yyHour, yyMinutes, yySeconds, yyMeridian)));
+ } else {
+ Tcl_ListObjAppendElement(interp, result, Tcl_NewObj());
+ }
+
+ resultElement = Tcl_NewObj();
+ if (yyHaveZone) {
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) -yyTimezone));
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj(1 - yyDSTmode));
+ }
+ Tcl_ListObjAppendElement(interp, result, resultElement);
+
+ resultElement = Tcl_NewObj();
+ if (yyHaveRel) {
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) yyRelMonth));
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) yyRelDay));
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) yyRelSeconds));
}
- Start += Time;
-
+ Tcl_ListObjAppendElement(interp, result, resultElement);
+
+ resultElement = Tcl_NewObj();
if (yyHaveDay && !yyHaveDate) {
- tod = NamedDay(Start, yyDayOrdinal, yyDayNumber);
- Start += tod;
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) yyDayOrdinal));
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) yyDayNumber));
}
+ Tcl_ListObjAppendElement(interp, result, resultElement);
+ resultElement = Tcl_NewObj();
if (yyHaveOrdinalMonth) {
- tod = NamedMonth(Start, yyMonthOrdinal, yyMonth);
- Start += tod;
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) yyMonthOrdinal));
+ Tcl_ListObjAppendElement(interp, resultElement,
+ Tcl_NewIntObj((int) yyMonth));
}
-
- *timePtr = Start;
- return 0;
+ Tcl_ListObjAppendElement(interp, result, resultElement);
+
+ Tcl_SetObjResult(interp, result);
+ return TCL_OK;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclHash.c b/generic/tclHash.c
index e7ee344..00bfdf0 100644
--- a/generic/tclHash.c
+++ b/generic/tclHash.c
@@ -7,8 +7,8 @@
* Copyright (c) 1991-1993 The Regents of the University of California.
* Copyright (c) 1994 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
@@ -17,24 +17,21 @@
* Prevent macros from clashing with function definitions.
*/
-#if TCL_PRESERVE_BINARY_COMPATABILITY
-# undef Tcl_FindHashEntry
-# undef Tcl_CreateHashEntry
-#endif
+#undef Tcl_FindHashEntry
+#undef Tcl_CreateHashEntry
/*
- * When there are this many entries per bucket, on average, rebuild
- * the hash table to make it larger.
+ * When there are this many entries per bucket, on average, rebuild the hash
+ * table to make it larger.
*/
#define REBUILD_MULTIPLIER 3
/*
- * The following macro takes a preliminary integer hash value and
- * produces an index into a hash tables bucket list. The idea is
- * to make it so that preliminary values that are arbitrarily similar
- * will end up in different buckets. The hash function was taken
- * from a random-number generator.
+ * The following macro takes a preliminary integer hash value and produces an
+ * index into a hash tables bucket list. The idea is to make it so that
+ * preliminary values that are arbitrarily similar will end up in different
+ * buckets. The hash function was taken from a random-number generator.
*/
#define RANDOM_INDEX(tablePtr, i) \
@@ -44,60 +41,41 @@
* Prototypes for the array hash key methods.
*/
-static Tcl_HashEntry * AllocArrayEntry _ANSI_ARGS_((
- Tcl_HashTable *tablePtr,
- VOID *keyPtr));
-static int CompareArrayKeys _ANSI_ARGS_((
- VOID *keyPtr, Tcl_HashEntry *hPtr));
-static unsigned int HashArrayKey _ANSI_ARGS_((
- Tcl_HashTable *tablePtr,
- VOID *keyPtr));
+static Tcl_HashEntry * AllocArrayEntry(Tcl_HashTable *tablePtr, VOID *keyPtr);
+static int CompareArrayKeys(VOID *keyPtr, Tcl_HashEntry *hPtr);
+static unsigned int HashArrayKey(Tcl_HashTable *tablePtr, VOID *keyPtr);
/*
* Prototypes for the one word hash key methods.
*/
#if 0
-static Tcl_HashEntry * AllocOneWordEntry _ANSI_ARGS_((
- Tcl_HashTable *tablePtr,
- VOID *keyPtr));
-static int CompareOneWordKeys _ANSI_ARGS_((
- VOID *keyPtr, Tcl_HashEntry *hPtr));
-static unsigned int HashOneWordKey _ANSI_ARGS_((
- Tcl_HashTable *tablePtr,
- VOID *keyPtr));
+static Tcl_HashEntry * AllocOneWordEntry(Tcl_HashTable *tablePtr,
+ VOID *keyPtr);
+static int CompareOneWordKeys(VOID *keyPtr, Tcl_HashEntry *hPtr);
+static unsigned int HashOneWordKey(Tcl_HashTable *tablePtr, VOID *keyPtr);
#endif
/*
* Prototypes for the string hash key methods.
*/
-static Tcl_HashEntry * AllocStringEntry _ANSI_ARGS_((
- Tcl_HashTable *tablePtr,
- VOID *keyPtr));
-static int CompareStringKeys _ANSI_ARGS_((
- VOID *keyPtr, Tcl_HashEntry *hPtr));
-static unsigned int HashStringKey _ANSI_ARGS_((
- Tcl_HashTable *tablePtr,
- VOID *keyPtr));
+static Tcl_HashEntry * AllocStringEntry(Tcl_HashTable *tablePtr,
+ VOID *keyPtr);
+static int CompareStringKeys(VOID *keyPtr, Tcl_HashEntry *hPtr);
+static unsigned int HashStringKey(Tcl_HashTable *tablePtr, VOID *keyPtr);
/*
- * Procedure prototypes for static procedures in this file:
+ * Function prototypes for static functions in this file:
*/
-#if TCL_PRESERVE_BINARY_COMPATABILITY
-static Tcl_HashEntry * BogusFind _ANSI_ARGS_((Tcl_HashTable *tablePtr,
- CONST char *key));
-static Tcl_HashEntry * BogusCreate _ANSI_ARGS_((Tcl_HashTable *tablePtr,
- CONST char *key, int *newPtr));
-static Tcl_HashEntry * FindHashEntry _ANSI_ARGS_((Tcl_HashTable *tablePtr,
- CONST char *key));
-static Tcl_HashEntry * CreateHashEntry _ANSI_ARGS_((Tcl_HashTable *tablePtr,
- CONST char *key, int *newPtr));
-
-#endif
-
-static void RebuildTable _ANSI_ARGS_((Tcl_HashTable *tablePtr));
+static Tcl_HashEntry * BogusFind(Tcl_HashTable *tablePtr, const char *key);
+static Tcl_HashEntry * BogusCreate(Tcl_HashTable *tablePtr, const char *key,
+ int *newPtr);
+static Tcl_HashEntry * CreateHashEntry(Tcl_HashTable *tablePtr, const char *key,
+ int *newPtr);
+static Tcl_HashEntry * FindHashEntry(Tcl_HashTable *tablePtr, const char *key);
+static void RebuildTable(Tcl_HashTable *tablePtr);
Tcl_HashKeyType tclArrayHashKeyType = {
TCL_HASH_KEY_TYPE_VERSION, /* version */
@@ -125,15 +103,14 @@ Tcl_HashKeyType tclStringHashKeyType = {
AllocStringEntry, /* allocEntryProc */
NULL /* freeEntryProc */
};
-
/*
*----------------------------------------------------------------------
*
* Tcl_InitHashTable --
*
- * Given storage for a hash table, set up the fields to prepare
- * the hash table for use.
+ * Given storage for a hash table, set up the fields to prepare the hash
+ * table for use.
*
* Results:
* None.
@@ -147,19 +124,21 @@ Tcl_HashKeyType tclStringHashKeyType = {
#undef Tcl_InitHashTable
void
-Tcl_InitHashTable(tablePtr, keyType)
- register Tcl_HashTable *tablePtr; /* Pointer to table record, which
- * is supplied by the caller. */
- int keyType; /* Type of keys to use in table:
- * TCL_STRING_KEYS, TCL_ONE_WORD_KEYS,
- * or an integer >= 2. */
+Tcl_InitHashTable(
+ register Tcl_HashTable *tablePtr,
+ /* Pointer to table record, which is supplied
+ * by the caller. */
+ int keyType) /* Type of keys to use in table:
+ * TCL_STRING_KEYS, TCL_ONE_WORD_KEYS, or an
+ * integer >= 2. */
{
/*
- * Use a special value to inform the extended version that it must
- * not access any of the new fields in the Tcl_HashTable. If an
- * extension is rebuilt then any calls to this function will be
- * redirected to the extended version by a macro.
+ * Use a special value to inform the extended version that it must not
+ * access any of the new fields in the Tcl_HashTable. If an extension is
+ * rebuilt then any calls to this function will be redirected to the
+ * extended version by a macro.
*/
+
Tcl_InitCustomHashTable(tablePtr, keyType, (Tcl_HashKeyType *) -1);
}
@@ -168,9 +147,9 @@ Tcl_InitHashTable(tablePtr, keyType)
*
* Tcl_InitCustomHashTable --
*
- * Given storage for a hash table, set up the fields to prepare
- * the hash table for use. This is an extended version of
- * Tcl_InitHashTable which supports user defined keys.
+ * Given storage for a hash table, set up the fields to prepare the hash
+ * table for use. This is an extended version of Tcl_InitHashTable which
+ * supports user defined keys.
*
* Results:
* None.
@@ -183,19 +162,19 @@ Tcl_InitHashTable(tablePtr, keyType)
*/
void
-Tcl_InitCustomHashTable(tablePtr, keyType, typePtr)
- register Tcl_HashTable *tablePtr; /* Pointer to table record, which
- * is supplied by the caller. */
- int keyType; /* Type of keys to use in table:
- * TCL_STRING_KEYS, TCL_ONE_WORD_KEYS,
- * TCL_CUSTOM_TYPE_KEYS,
- * TCL_CUSTOM_PTR_KEYS, or an
- * integer >= 2. */
- Tcl_HashKeyType *typePtr; /* Pointer to structure which defines
- * the behaviour of this table. */
+Tcl_InitCustomHashTable(
+ register Tcl_HashTable *tablePtr,
+ /* Pointer to table record, which is supplied
+ * by the caller. */
+ int keyType, /* Type of keys to use in table:
+ * TCL_STRING_KEYS, TCL_ONE_WORD_KEYS,
+ * TCL_CUSTOM_TYPE_KEYS, TCL_CUSTOM_PTR_KEYS,
+ * or an integer >= 2. */
+ Tcl_HashKeyType *typePtr) /* Pointer to structure which defines the
+ * behaviour of this table. */
{
#if (TCL_SMALL_HASH_TABLE != 4)
- panic("Tcl_InitCustomHashTable: TCL_SMALL_HASH_TABLE is %d, not 4\n",
+ Tcl_Panic("Tcl_InitCustomHashTable: TCL_SMALL_HASH_TABLE is %d, not 4",
TCL_SMALL_HASH_TABLE);
#endif
@@ -208,7 +187,6 @@ Tcl_InitCustomHashTable(tablePtr, keyType, typePtr)
tablePtr->downShift = 28;
tablePtr->mask = 3;
tablePtr->keyType = keyType;
-#if TCL_PRESERVE_BINARY_COMPATABILITY
tablePtr->findProc = FindHashEntry;
tablePtr->createProc = CreateHashEntry;
@@ -219,41 +197,16 @@ Tcl_InitCustomHashTable(tablePtr, keyType, typePtr)
*/
} else if (typePtr != (Tcl_HashKeyType *) -1) {
/*
- * The caller is requesting a customized hash table so it must be
- * an extended version.
+ * The caller is requesting a customized hash table so it must be an
+ * extended version.
*/
+
tablePtr->typePtr = typePtr;
} else {
/*
- * The caller has not been rebuilt so the hash table is not
- * extended.
- */
- }
-#else
- if (typePtr == NULL) {
- /*
- * Use the key type to decide which key type is needed.
- */
- if (keyType == TCL_STRING_KEYS) {
- typePtr = &tclStringHashKeyType;
- } else if (keyType == TCL_ONE_WORD_KEYS) {
- typePtr = &tclOneWordHashKeyType;
- } else if (keyType == TCL_CUSTOM_TYPE_KEYS) {
- Tcl_Panic ("No type structure specified for TCL_CUSTOM_TYPE_KEYS");
- } else if (keyType == TCL_CUSTOM_PTR_KEYS) {
- Tcl_Panic ("No type structure specified for TCL_CUSTOM_PTR_KEYS");
- } else {
- typePtr = &tclArrayHashKeyType;
- }
- } else if (typePtr == (Tcl_HashKeyType *) -1) {
- /*
- * If the caller has not been rebuilt then we cannot continue as
- * the hash table is not an extended version.
+ * The caller has not been rebuilt so the hash table is not extended.
*/
- Tcl_Panic ("Hash table is not compatible");
}
- tablePtr->typePtr = typePtr;
-#endif
}
/*
@@ -264,8 +217,8 @@ Tcl_InitCustomHashTable(tablePtr, keyType, typePtr)
* Given a hash table find the entry with a matching key.
*
* Results:
- * The return value is a token for the matching entry in the
- * hash table, or NULL if there was no matching entry.
+ * The return value is a token for the matching entry in the hash table,
+ * or NULL if there was no matching entry.
*
* Side effects:
* None.
@@ -274,104 +227,36 @@ Tcl_InitCustomHashTable(tablePtr, keyType, typePtr)
*/
Tcl_HashEntry *
-Tcl_FindHashEntry(tablePtr, key)
- Tcl_HashTable *tablePtr; /* Table in which to lookup entry. */
- CONST char *key; /* Key to use to find matching entry. */
-#if TCL_PRESERVE_BINARY_COMPATABILITY
+Tcl_FindHashEntry(
+ Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */
+ const char *key) /* Key to use to find matching entry. */
{
- return tablePtr->findProc(tablePtr, key);
+ return (*((tablePtr)->findProc))(tablePtr, key);
}
static Tcl_HashEntry *
-FindHashEntry(tablePtr, key)
- Tcl_HashTable *tablePtr; /* Table in which to lookup entry. */
- CONST char *key; /* Key to use to find matching entry. */
-#endif /* TCL_PRESERVE_BINARY_COMPATABILITY */
+FindHashEntry(
+ Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */
+ const char *key) /* Key to use to find matching entry. */
{
- register Tcl_HashEntry *hPtr;
- Tcl_HashKeyType *typePtr;
- unsigned int hash;
- int index;
-
-#if TCL_PRESERVE_BINARY_COMPATABILITY
- if (tablePtr->keyType == TCL_STRING_KEYS) {
- typePtr = &tclStringHashKeyType;
- } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) {
- typePtr = &tclOneWordHashKeyType;
- } else if (tablePtr->keyType == TCL_CUSTOM_TYPE_KEYS
- || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) {
- typePtr = tablePtr->typePtr;
- } else {
- typePtr = &tclArrayHashKeyType;
- }
-#else
- typePtr = tablePtr->typePtr;
- if (typePtr == NULL) {
- Tcl_Panic("called Tcl_FindHashEntry on deleted table");
- return NULL;
- }
-#endif
-
- if (typePtr->hashKeyProc) {
- hash = typePtr->hashKeyProc (tablePtr, (VOID *) key);
- if (typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) {
- index = RANDOM_INDEX (tablePtr, hash);
- } else {
- index = hash & tablePtr->mask;
- }
- } else {
- hash = (unsigned int) key;
- index = RANDOM_INDEX (tablePtr, hash);
- }
-
- /*
- * Search all of the entries in the appropriate bucket.
- */
-
- if (typePtr->compareKeysProc) {
- Tcl_CompareHashKeysProc *compareKeysProc = typePtr->compareKeysProc;
- for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
- hPtr = hPtr->nextPtr) {
-#if TCL_HASH_KEY_STORE_HASH
- if (hash != (unsigned int) hPtr->hash) {
- continue;
- }
-#endif
- if (compareKeysProc ((VOID *) key, hPtr)) {
- return hPtr;
- }
- }
- } else {
- for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
- hPtr = hPtr->nextPtr) {
-#if TCL_HASH_KEY_STORE_HASH
- if (hash != (unsigned int) hPtr->hash) {
- continue;
- }
-#endif
- if (key == hPtr->key.oneWordValue) {
- return hPtr;
- }
- }
- }
-
- return NULL;
+ return CreateHashEntry(tablePtr, key, NULL);
}
+
/*
*----------------------------------------------------------------------
*
* Tcl_CreateHashEntry --
*
- * Given a hash table with string keys, and a string key, find
- * the entry with a matching key. If there is no matching entry,
- * then create a new entry that does match.
+ * Given a hash table with string keys, and a string key, find the entry
+ * with a matching key. If there is no matching entry, then create a new
+ * entry that does match.
*
* Results:
- * The return value is a pointer to the matching entry. If this
- * is a newly-created entry, then *newPtr will be set to a non-zero
- * value; otherwise *newPtr will be set to 0. If this is a new
- * entry the value stored in the entry will initially be 0.
+ * The return value is a pointer to the matching entry. If this is a
+ * newly-created entry, then *newPtr will be set to a non-zero value;
+ * otherwise *newPtr will be set to 0. If this is a new entry the value
+ * stored in the entry will initially be 0.
*
* Side effects:
* A new entry may be added to the hash table.
@@ -380,59 +265,49 @@ FindHashEntry(tablePtr, key)
*/
Tcl_HashEntry *
-Tcl_CreateHashEntry(tablePtr, key, newPtr)
- Tcl_HashTable *tablePtr; /* Table in which to lookup entry. */
- CONST char *key; /* Key to use to find or create matching
+Tcl_CreateHashEntry(
+ Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */
+ const char *key, /* Key to use to find or create matching
* entry. */
- int *newPtr; /* Store info here telling whether a new
- * entry was created. */
-#if TCL_PRESERVE_BINARY_COMPATABILITY
+ int *newPtr) /* Store info here telling whether a new entry
+ * was created. */
{
- return tablePtr->createProc(tablePtr, key, newPtr);
+ return (*((tablePtr)->createProc))(tablePtr, key, newPtr);
}
static Tcl_HashEntry *
-CreateHashEntry(tablePtr, key, newPtr)
- Tcl_HashTable *tablePtr; /* Table in which to lookup entry. */
- CONST char *key; /* Key to use to find or create matching
+CreateHashEntry(
+ Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */
+ const char *key, /* Key to use to find or create matching
* entry. */
- int *newPtr; /* Store info here telling whether a new
- * entry was created. */
-#endif /* TCL_PRESERVE_BINARY_COMPATABILITY */
+ int *newPtr) /* Store info here telling whether a new entry
+ * was created. */
{
register Tcl_HashEntry *hPtr;
- Tcl_HashKeyType *typePtr;
+ const Tcl_HashKeyType *typePtr;
unsigned int hash;
int index;
-#if TCL_PRESERVE_BINARY_COMPATABILITY
if (tablePtr->keyType == TCL_STRING_KEYS) {
typePtr = &tclStringHashKeyType;
} else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) {
typePtr = &tclOneWordHashKeyType;
} else if (tablePtr->keyType == TCL_CUSTOM_TYPE_KEYS
- || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) {
+ || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) {
typePtr = tablePtr->typePtr;
} else {
typePtr = &tclArrayHashKeyType;
}
-#else
- typePtr = tablePtr->typePtr;
- if (typePtr == NULL) {
- Tcl_Panic("called Tcl_CreateHashEntry on deleted table");
- return NULL;
- }
-#endif
if (typePtr->hashKeyProc) {
- hash = typePtr->hashKeyProc (tablePtr, (VOID *) key);
+ hash = typePtr->hashKeyProc(tablePtr, (VOID *) key);
if (typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) {
index = RANDOM_INDEX (tablePtr, hash);
} else {
index = hash & tablePtr->mask;
}
} else {
- hash = (unsigned int) key;
+ hash = PTR2UINT(key);
index = RANDOM_INDEX (tablePtr, hash);
}
@@ -443,51 +318,56 @@ CreateHashEntry(tablePtr, key, newPtr)
if (typePtr->compareKeysProc) {
Tcl_CompareHashKeysProc *compareKeysProc = typePtr->compareKeysProc;
for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
- hPtr = hPtr->nextPtr) {
+ hPtr = hPtr->nextPtr) {
#if TCL_HASH_KEY_STORE_HASH
- if (hash != (unsigned int) hPtr->hash) {
+ if (hash != PTR2UINT(hPtr->hash)) {
continue;
}
#endif
- if (compareKeysProc ((VOID *) key, hPtr)) {
- *newPtr = 0;
+ if (compareKeysProc((VOID *) key, hPtr)) {
+ if (newPtr) {
+ *newPtr = 0;
+ }
return hPtr;
}
}
} else {
for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
- hPtr = hPtr->nextPtr) {
+ hPtr = hPtr->nextPtr) {
#if TCL_HASH_KEY_STORE_HASH
- if (hash != (unsigned int) hPtr->hash) {
+ if (hash != PTR2UINT(hPtr->hash)) {
continue;
}
#endif
if (key == hPtr->key.oneWordValue) {
- *newPtr = 0;
+ if (newPtr) {
+ *newPtr = 0;
+ }
return hPtr;
}
}
}
+ if (!newPtr) {
+ return NULL;
+ }
+
/*
- * Entry not found. Add a new one to the bucket.
+ * Entry not found. Add a new one to the bucket.
*/
*newPtr = 1;
if (typePtr->allocEntryProc) {
- hPtr = typePtr->allocEntryProc (tablePtr, (VOID *) key);
+ hPtr = typePtr->allocEntryProc(tablePtr, (VOID *) key);
} else {
hPtr = (Tcl_HashEntry *) ckalloc((unsigned) sizeof(Tcl_HashEntry));
hPtr->key.oneWordValue = (char *) key;
+ hPtr->clientData = 0;
}
hPtr->tablePtr = tablePtr;
#if TCL_HASH_KEY_STORE_HASH
-# if TCL_PRESERVE_BINARY_COMPATABILITY
- hPtr->hash = (VOID *) hash;
-# else
- hPtr->hash = hash;
-# endif
+ hPtr->hash = UINT2PTR(hash);
hPtr->nextPtr = tablePtr->buckets[index];
tablePtr->buckets[index] = hPtr;
#else
@@ -495,12 +375,11 @@ CreateHashEntry(tablePtr, key, newPtr)
hPtr->nextPtr = *hPtr->bucketPtr;
*hPtr->bucketPtr = hPtr;
#endif
- hPtr->clientData = 0;
tablePtr->numEntries++;
/*
- * If the table has exceeded a decent size, rebuild it with many
- * more buckets.
+ * If the table has exceeded a decent size, rebuild it with many more
+ * buckets.
*/
if (tablePtr->numEntries >= tablePtr->rebuildSize) {
@@ -520,20 +399,19 @@ CreateHashEntry(tablePtr, key, newPtr)
* None.
*
* Side effects:
- * The entry given by entryPtr is deleted from its table and
- * should never again be used by the caller. It is up to the
- * caller to free the clientData field of the entry, if that
- * is relevant.
+ * The entry given by entryPtr is deleted from its table and should never
+ * again be used by the caller. It is up to the caller to free the
+ * clientData field of the entry, if that is relevant.
*
*----------------------------------------------------------------------
*/
void
-Tcl_DeleteHashEntry(entryPtr)
- Tcl_HashEntry *entryPtr;
+Tcl_DeleteHashEntry(
+ Tcl_HashEntry *entryPtr)
{
register Tcl_HashEntry *prevPtr;
- Tcl_HashKeyType *typePtr;
+ const Tcl_HashKeyType *typePtr;
Tcl_HashTable *tablePtr;
Tcl_HashEntry **bucketPtr;
#if TCL_HASH_KEY_STORE_HASH
@@ -542,27 +420,23 @@ Tcl_DeleteHashEntry(entryPtr)
tablePtr = entryPtr->tablePtr;
-#if TCL_PRESERVE_BINARY_COMPATABILITY
if (tablePtr->keyType == TCL_STRING_KEYS) {
typePtr = &tclStringHashKeyType;
} else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) {
typePtr = &tclOneWordHashKeyType;
} else if (tablePtr->keyType == TCL_CUSTOM_TYPE_KEYS
- || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) {
+ || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) {
typePtr = tablePtr->typePtr;
} else {
typePtr = &tclArrayHashKeyType;
}
-#else
- typePtr = tablePtr->typePtr;
-#endif
#if TCL_HASH_KEY_STORE_HASH
if (typePtr->hashKeyProc == NULL
- || typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) {
+ || typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) {
index = RANDOM_INDEX (tablePtr, entryPtr->hash);
} else {
- index = ((unsigned int) entryPtr->hash) & tablePtr->mask;
+ index = PTR2UINT(entryPtr->hash) & tablePtr->mask;
}
bucketPtr = &(tablePtr->buckets[index]);
@@ -575,7 +449,7 @@ Tcl_DeleteHashEntry(entryPtr)
} else {
for (prevPtr = *bucketPtr; ; prevPtr = prevPtr->nextPtr) {
if (prevPtr == NULL) {
- panic("malformed bucket chain in Tcl_DeleteHashEntry");
+ Tcl_Panic("malformed bucket chain in Tcl_DeleteHashEntry");
}
if (prevPtr->nextPtr == entryPtr) {
prevPtr->nextPtr = entryPtr->nextPtr;
@@ -597,8 +471,8 @@ Tcl_DeleteHashEntry(entryPtr)
*
* Tcl_DeleteHashTable --
*
- * Free up everything associated with a hash table except for
- * the record for the table itself.
+ * Free up everything associated with a hash table except for the record
+ * for the table itself.
*
* Results:
* None.
@@ -610,27 +484,23 @@ Tcl_DeleteHashEntry(entryPtr)
*/
void
-Tcl_DeleteHashTable(tablePtr)
- register Tcl_HashTable *tablePtr; /* Table to delete. */
+Tcl_DeleteHashTable(
+ register Tcl_HashTable *tablePtr) /* Table to delete. */
{
register Tcl_HashEntry *hPtr, *nextPtr;
- Tcl_HashKeyType *typePtr;
+ const Tcl_HashKeyType *typePtr;
int i;
-#if TCL_PRESERVE_BINARY_COMPATABILITY
if (tablePtr->keyType == TCL_STRING_KEYS) {
typePtr = &tclStringHashKeyType;
} else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) {
typePtr = &tclOneWordHashKeyType;
} else if (tablePtr->keyType == TCL_CUSTOM_TYPE_KEYS
- || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) {
+ || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) {
typePtr = tablePtr->typePtr;
} else {
typePtr = &tclArrayHashKeyType;
}
-#else
- typePtr = tablePtr->typePtr;
-#endif
/*
* Free up all the entries in the table.
@@ -654,7 +524,11 @@ Tcl_DeleteHashTable(tablePtr)
*/
if (tablePtr->buckets != tablePtr->staticBuckets) {
- ckfree((char *) tablePtr->buckets);
+ if (typePtr->flags & TCL_HASH_KEY_SYSTEM_HASH) {
+ TclpSysFree((char *) tablePtr->buckets);
+ } else {
+ ckfree((char *) tablePtr->buckets);
+ }
}
/*
@@ -662,12 +536,8 @@ Tcl_DeleteHashTable(tablePtr)
* re-initialization.
*/
-#if TCL_PRESERVE_BINARY_COMPATABILITY
tablePtr->findProc = BogusFind;
tablePtr->createProc = BogusCreate;
-#else
- tablePtr->typePtr = NULL;
-#endif
}
/*
@@ -675,16 +545,14 @@ Tcl_DeleteHashTable(tablePtr)
*
* Tcl_FirstHashEntry --
*
- * Locate the first entry in a hash table and set up a record
- * that can be used to step through all the remaining entries
- * of the table.
+ * Locate the first entry in a hash table and set up a record that can be
+ * used to step through all the remaining entries of the table.
*
* Results:
- * The return value is a pointer to the first entry in tablePtr,
- * or NULL if tablePtr has no entries in it. The memory at
- * *searchPtr is initialized so that subsequent calls to
- * Tcl_NextHashEntry will return all of the entries in the table,
- * one at a time.
+ * The return value is a pointer to the first entry in tablePtr, or NULL
+ * if tablePtr has no entries in it. The memory at *searchPtr is
+ * initialized so that subsequent calls to Tcl_NextHashEntry will return
+ * all of the entries in the table, one at a time.
*
* Side effects:
* None.
@@ -693,10 +561,10 @@ Tcl_DeleteHashTable(tablePtr)
*/
Tcl_HashEntry *
-Tcl_FirstHashEntry(tablePtr, searchPtr)
- Tcl_HashTable *tablePtr; /* Table to search. */
- Tcl_HashSearch *searchPtr; /* Place to store information about
- * progress through the table. */
+Tcl_FirstHashEntry(
+ Tcl_HashTable *tablePtr, /* Table to search. */
+ Tcl_HashSearch *searchPtr) /* Place to store information about progress
+ * through the table. */
{
searchPtr->tablePtr = tablePtr;
searchPtr->nextIndex = 0;
@@ -710,12 +578,12 @@ Tcl_FirstHashEntry(tablePtr, searchPtr)
* Tcl_NextHashEntry --
*
* Once a hash table enumeration has been initiated by calling
- * Tcl_FirstHashEntry, this procedure may be called to return
- * successive elements of the table.
+ * Tcl_FirstHashEntry, this function may be called to return successive
+ * elements of the table.
*
* Results:
- * The return value is the next entry in the hash table being
- * enumerated, or NULL if the end of the table is reached.
+ * The return value is the next entry in the hash table being enumerated,
+ * or NULL if the end of the table is reached.
*
* Side effects:
* None.
@@ -724,11 +592,12 @@ Tcl_FirstHashEntry(tablePtr, searchPtr)
*/
Tcl_HashEntry *
-Tcl_NextHashEntry(searchPtr)
- register Tcl_HashSearch *searchPtr; /* Place to store information about
- * progress through the table. Must
- * have been initialized by calling
- * Tcl_FirstHashEntry. */
+Tcl_NextHashEntry(
+ register Tcl_HashSearch *searchPtr)
+ /* Place to store information about progress
+ * through the table. Must have been
+ * initialized by calling
+ * Tcl_FirstHashEntry. */
{
Tcl_HashEntry *hPtr;
Tcl_HashTable *tablePtr = searchPtr->tablePtr;
@@ -751,13 +620,12 @@ Tcl_NextHashEntry(searchPtr)
*
* Tcl_HashStats --
*
- * Return statistics describing the layout of the hash table
- * in its hash buckets.
+ * Return statistics describing the layout of the hash table in its hash
+ * buckets.
*
* Results:
- * The return value is a malloc-ed string containing information
- * about tablePtr. It is the caller's responsibility to free
- * this string.
+ * The return value is a malloc-ed string containing information about
+ * tablePtr. It is the caller's responsibility to free this string.
*
* Side effects:
* None.
@@ -765,15 +633,27 @@ Tcl_NextHashEntry(searchPtr)
*----------------------------------------------------------------------
*/
-CONST char *
-Tcl_HashStats(tablePtr)
- Tcl_HashTable *tablePtr; /* Table for which to produce stats. */
+char *
+Tcl_HashStats(
+ Tcl_HashTable *tablePtr) /* Table for which to produce stats. */
{
#define NUM_COUNTERS 10
int count[NUM_COUNTERS], overflow, i, j;
double average, tmp;
register Tcl_HashEntry *hPtr;
char *result, *p;
+ const Tcl_HashKeyType *typePtr;
+
+ if (tablePtr->keyType == TCL_STRING_KEYS) {
+ typePtr = &tclStringHashKeyType;
+ } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) {
+ typePtr = &tclOneWordHashKeyType;
+ } else if (tablePtr->keyType == TCL_CUSTOM_TYPE_KEYS
+ || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) {
+ typePtr = tablePtr->typePtr;
+ } else {
+ typePtr = &tclArrayHashKeyType;
+ }
/*
* Compute a histogram of bucket usage.
@@ -795,14 +675,20 @@ Tcl_HashStats(tablePtr)
overflow++;
}
tmp = j;
- average += (tmp+1.0)*(tmp/tablePtr->numEntries)/2.0;
+ if (tablePtr->numEntries != 0) {
+ average += (tmp+1.0)*(tmp/tablePtr->numEntries)/2.0;
+ }
}
/*
* Print out the histogram and a few other pieces of information.
*/
- result = (char *) ckalloc((unsigned) ((NUM_COUNTERS*60) + 300));
+ if (typePtr->flags & TCL_HASH_KEY_SYSTEM_HASH) {
+ result = (char *) TclpSysAlloc((unsigned) (NUM_COUNTERS*60) + 300, 0);
+ } else {
+ result = (char *) ckalloc((unsigned) (NUM_COUNTERS*60) + 300);
+ }
sprintf(result, "%d entries in table, %d buckets\n",
tablePtr->numEntries, tablePtr->numBuckets);
p = result + strlen(result);
@@ -835,9 +721,9 @@ Tcl_HashStats(tablePtr)
*/
static Tcl_HashEntry *
-AllocArrayEntry(tablePtr, keyPtr)
- Tcl_HashTable *tablePtr; /* Hash table. */
- VOID *keyPtr; /* Key to store in the hash table entry. */
+AllocArrayEntry(
+ Tcl_HashTable *tablePtr, /* Hash table. */
+ VOID *keyPtr) /* Key to store in the hash table entry. */
{
int *array = (int *) keyPtr;
register int *iPtr1, *iPtr2;
@@ -848,14 +734,16 @@ AllocArrayEntry(tablePtr, keyPtr)
count = tablePtr->keyType;
size = sizeof(Tcl_HashEntry) + (count*sizeof(int)) - sizeof(hPtr->key);
- if (size < sizeof(Tcl_HashEntry))
+ if (size < sizeof(Tcl_HashEntry)) {
size = sizeof(Tcl_HashEntry);
+ }
hPtr = (Tcl_HashEntry *) ckalloc(size);
for (iPtr1 = array, iPtr2 = hPtr->key.words;
count > 0; count--, iPtr1++, iPtr2++) {
*iPtr2 = *iPtr1;
}
+ hPtr->clientData = 0;
return hPtr;
}
@@ -868,8 +756,8 @@ AllocArrayEntry(tablePtr, keyPtr)
* Compares two array keys.
*
* Results:
- * The return value is 0 if they are different and 1 if they are
- * the same.
+ * The return value is 0 if they are different and 1 if they are the
+ * same.
*
* Side effects:
* None.
@@ -878,12 +766,12 @@ AllocArrayEntry(tablePtr, keyPtr)
*/
static int
-CompareArrayKeys(keyPtr, hPtr)
- VOID *keyPtr; /* New key to compare. */
- Tcl_HashEntry *hPtr; /* Existing key to compare. */
+CompareArrayKeys(
+ VOID *keyPtr, /* New key to compare. */
+ Tcl_HashEntry *hPtr) /* Existing key to compare. */
{
- register CONST int *iPtr1 = (CONST int *) keyPtr;
- register CONST int *iPtr2 = (CONST int *) hPtr->key.words;
+ register const int *iPtr1 = (const int *) keyPtr;
+ register const int *iPtr2 = (const int *) hPtr->key.words;
Tcl_HashTable *tablePtr = hPtr->tablePtr;
int count;
@@ -903,8 +791,8 @@ CompareArrayKeys(keyPtr, hPtr)
*
* HashArrayKey --
*
- * Compute a one-word summary of an array, which can be
- * used to generate a hash index.
+ * Compute a one-word summary of an array, which can be used to generate
+ * a hash index.
*
* Results:
* The return value is a one-word summary of the information in
@@ -917,11 +805,11 @@ CompareArrayKeys(keyPtr, hPtr)
*/
static unsigned int
-HashArrayKey(tablePtr, keyPtr)
- Tcl_HashTable *tablePtr; /* Hash table. */
- VOID *keyPtr; /* Key from which to compute hash value. */
+HashArrayKey(
+ Tcl_HashTable *tablePtr, /* Hash table. */
+ VOID *keyPtr) /* Key from which to compute hash value. */
{
- register CONST int *array = (CONST int *) keyPtr;
+ register const int *array = (const int *) keyPtr;
register unsigned int result;
int count;
@@ -949,11 +837,11 @@ HashArrayKey(tablePtr, keyPtr)
*/
static Tcl_HashEntry *
-AllocStringEntry(tablePtr, keyPtr)
- Tcl_HashTable *tablePtr; /* Hash table. */
- VOID *keyPtr; /* Key to store in the hash table entry. */
+AllocStringEntry(
+ Tcl_HashTable *tablePtr, /* Hash table. */
+ VOID *keyPtr) /* Key to store in the hash table entry. */
{
- CONST char *string = (CONST char *) keyPtr;
+ const char *string = (const char *) keyPtr;
Tcl_HashEntry *hPtr;
unsigned int size, allocsize;
@@ -963,6 +851,7 @@ AllocStringEntry(tablePtr, keyPtr)
}
hPtr = (Tcl_HashEntry *) ckalloc(sizeof(Tcl_HashEntry) + allocsize - sizeof(hPtr->key));
memcpy(hPtr->key.string, string, size);
+ hPtr->clientData = 0;
return hPtr;
}
@@ -974,8 +863,8 @@ AllocStringEntry(tablePtr, keyPtr)
* Compares two string keys.
*
* Results:
- * The return value is 0 if they are different and 1 if they are
- * the same.
+ * The return value is 0 if they are different and 1 if they are the
+ * same.
*
* Side effects:
* None.
@@ -984,22 +873,14 @@ AllocStringEntry(tablePtr, keyPtr)
*/
static int
-CompareStringKeys(keyPtr, hPtr)
- VOID *keyPtr; /* New key to compare. */
- Tcl_HashEntry *hPtr; /* Existing key to compare. */
+CompareStringKeys(
+ VOID *keyPtr, /* New key to compare. */
+ Tcl_HashEntry *hPtr) /* Existing key to compare. */
{
- register CONST char *p1 = (CONST char *) keyPtr;
- register CONST char *p2 = (CONST char *) hPtr->key.string;
+ register const char *p1 = (const char *) keyPtr;
+ register const char *p2 = (const char *) hPtr->key.string;
- for (;; p1++, p2++) {
- if (*p1 != *p2) {
- break;
- }
- if (*p1 == '\0') {
- return 1;
- }
- }
- return 0;
+ return !strcmp(p1, p2);
}
/*
@@ -1007,12 +888,11 @@ CompareStringKeys(keyPtr, hPtr)
*
* HashStringKey --
*
- * Compute a one-word summary of a text string, which can be
- * used to generate a hash index.
+ * Compute a one-word summary of a text string, which can be used to
+ * generate a hash index.
*
* Results:
- * The return value is a one-word summary of the information in
- * string.
+ * The return value is a one-word summary of the information in string.
*
* Side effects:
* None.
@@ -1021,54 +901,49 @@ CompareStringKeys(keyPtr, hPtr)
*/
static unsigned int
-HashStringKey(tablePtr, keyPtr)
- Tcl_HashTable *tablePtr; /* Hash table. */
- VOID *keyPtr; /* Key from which to compute hash value. */
+HashStringKey(
+ Tcl_HashTable *tablePtr, /* Hash table. */
+ VOID *keyPtr) /* Key from which to compute hash value. */
{
- register CONST char *string = (CONST char *) keyPtr;
+ register const char *string = (const char *) keyPtr;
register unsigned int result;
register int c;
/*
- * I tried a zillion different hash functions and asked many other
- * people for advice. Many people had their own favorite functions,
- * all different, but no-one had much idea why they were good ones.
- * I chose the one below (multiply by 9 and add new character)
- * because of the following reasons:
+ * I tried a zillion different hash functions and asked many other people
+ * for advice. Many people had their own favorite functions, all
+ * different, but no-one had much idea why they were good ones. I chose
+ * the one below (multiply by 9 and add new character) because of the
+ * following reasons:
*
- * 1. Multiplying by 10 is perfect for keys that are decimal strings,
- * and multiplying by 9 is just about as good.
- * 2. Times-9 is (shift-left-3) plus (old). This means that each
- * character's bits hang around in the low-order bits of the
- * hash value for ever, plus they spread fairly rapidly up to
- * the high-order bits to fill out the hash value. This seems
- * works well both for decimal and non-decimal strings.
+ * 1. Multiplying by 10 is perfect for keys that are decimal strings, and
+ * multiplying by 9 is just about as good.
+ * 2. Times-9 is (shift-left-3) plus (old). This means that each
+ * character's bits hang around in the low-order bits of the hash value
+ * for ever, plus they spread fairly rapidly up to the high-order bits
+ * to fill out the hash value. This seems works well both for decimal
+ * and non-decimal strings, but isn't strong against maliciously-chosen
+ * keys.
*/
result = 0;
- while (1) {
- c = *string;
- if (c == 0) {
- break;
- }
+
+ for (c=*string++ ; c ; c=*string++) {
result += (result<<3) + c;
- string++;
}
return result;
}
-#if TCL_PRESERVE_BINARY_COMPATABILITY
/*
*----------------------------------------------------------------------
*
* BogusFind --
*
- * This procedure is invoked when an Tcl_FindHashEntry is called
- * on a table that has been deleted.
+ * This function is invoked when an Tcl_FindHashEntry is called on a
+ * table that has been deleted.
*
* Results:
- * If panic returns (which it shouldn't) this procedure returns
- * NULL.
+ * If Tcl_Panic returns (which it shouldn't) this function returns NULL.
*
* Side effects:
* Generates a panic.
@@ -1078,11 +953,11 @@ HashStringKey(tablePtr, keyPtr)
/* ARGSUSED */
static Tcl_HashEntry *
-BogusFind(tablePtr, key)
- Tcl_HashTable *tablePtr; /* Table in which to lookup entry. */
- CONST char *key; /* Key to use to find matching entry. */
+BogusFind(
+ Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */
+ const char *key) /* Key to use to find matching entry. */
{
- panic("called Tcl_FindHashEntry on deleted table");
+ Tcl_Panic("called %s on deleted table", "Tcl_FindHashEntry");
return NULL;
}
@@ -1091,12 +966,11 @@ BogusFind(tablePtr, key)
*
* BogusCreate --
*
- * This procedure is invoked when an Tcl_CreateHashEntry is called
- * on a table that has been deleted.
+ * This function is invoked when an Tcl_CreateHashEntry is called on a
+ * table that has been deleted.
*
* Results:
- * If panic returns (which it shouldn't) this procedure returns
- * NULL.
+ * If panic returns (which it shouldn't) this function returns NULL.
*
* Side effects:
* Generates a panic.
@@ -1106,59 +980,72 @@ BogusFind(tablePtr, key)
/* ARGSUSED */
static Tcl_HashEntry *
-BogusCreate(tablePtr, key, newPtr)
- Tcl_HashTable *tablePtr; /* Table in which to lookup entry. */
- CONST char *key; /* Key to use to find or create matching
+BogusCreate(
+ Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */
+ const char *key, /* Key to use to find or create matching
* entry. */
- int *newPtr; /* Store info here telling whether a new
- * entry was created. */
+ int *newPtr) /* Store info here telling whether a new entry
+ * was created. */
{
- panic("called Tcl_CreateHashEntry on deleted table");
+ Tcl_Panic("called %s on deleted table", "Tcl_CreateHashEntry");
return NULL;
}
-#endif
/*
*----------------------------------------------------------------------
*
* RebuildTable --
*
- * This procedure is invoked when the ratio of entries to hash
- * buckets becomes too large. It creates a new table with a
- * larger bucket array and moves all of the entries into the
- * new table.
+ * This function is invoked when the ratio of entries to hash buckets
+ * becomes too large. It creates a new table with a larger bucket array
+ * and moves all of the entries into the new table.
*
* Results:
* None.
*
* Side effects:
- * Memory gets reallocated and entries get re-hashed to new
- * buckets.
+ * Memory gets reallocated and entries get re-hashed to new buckets.
*
*----------------------------------------------------------------------
*/
static void
-RebuildTable(tablePtr)
- register Tcl_HashTable *tablePtr; /* Table to enlarge. */
+RebuildTable(
+ register Tcl_HashTable *tablePtr) /* Table to enlarge. */
{
int oldSize, count, index;
Tcl_HashEntry **oldBuckets;
register Tcl_HashEntry **oldChainPtr, **newChainPtr;
register Tcl_HashEntry *hPtr;
- Tcl_HashKeyType *typePtr;
+ const Tcl_HashKeyType *typePtr;
+
+ if (tablePtr->keyType == TCL_STRING_KEYS) {
+ typePtr = &tclStringHashKeyType;
+ } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) {
+ typePtr = &tclOneWordHashKeyType;
+ } else if (tablePtr->keyType == TCL_CUSTOM_TYPE_KEYS
+ || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) {
+ typePtr = tablePtr->typePtr;
+ } else {
+ typePtr = &tclArrayHashKeyType;
+ }
oldSize = tablePtr->numBuckets;
oldBuckets = tablePtr->buckets;
/*
- * Allocate and initialize the new bucket array, and set up
- * hashing constants for new array size.
+ * Allocate and initialize the new bucket array, and set up hashing
+ * constants for new array size.
*/
tablePtr->numBuckets *= 4;
- tablePtr->buckets = (Tcl_HashEntry **) ckalloc((unsigned)
- (tablePtr->numBuckets * sizeof(Tcl_HashEntry *)));
+ if (typePtr->flags & TCL_HASH_KEY_SYSTEM_HASH) {
+ tablePtr->buckets = (Tcl_HashEntry **) TclpSysAlloc((unsigned)
+ (tablePtr->numBuckets * sizeof(Tcl_HashEntry *)), 0);
+ } else {
+ tablePtr->buckets = (Tcl_HashEntry **) ckalloc((unsigned)
+ (tablePtr->numBuckets * sizeof(Tcl_HashEntry *)));
+ }
for (count = tablePtr->numBuckets, newChainPtr = tablePtr->buckets;
count > 0; count--, newChainPtr++) {
*newChainPtr = NULL;
@@ -1167,21 +1054,6 @@ RebuildTable(tablePtr)
tablePtr->downShift -= 2;
tablePtr->mask = (tablePtr->mask << 2) + 3;
-#if TCL_PRESERVE_BINARY_COMPATABILITY
- if (tablePtr->keyType == TCL_STRING_KEYS) {
- typePtr = &tclStringHashKeyType;
- } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) {
- typePtr = &tclOneWordHashKeyType;
- } else if (tablePtr->keyType == TCL_CUSTOM_TYPE_KEYS
- || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) {
- typePtr = tablePtr->typePtr;
- } else {
- typePtr = &tclArrayHashKeyType;
- }
-#else
- typePtr = tablePtr->typePtr;
-#endif
-
/*
* Rehash all of the existing entries into the new bucket array.
*/
@@ -1189,21 +1061,22 @@ RebuildTable(tablePtr)
for (oldChainPtr = oldBuckets; oldSize > 0; oldSize--, oldChainPtr++) {
for (hPtr = *oldChainPtr; hPtr != NULL; hPtr = *oldChainPtr) {
*oldChainPtr = hPtr->nextPtr;
-
#if TCL_HASH_KEY_STORE_HASH
if (typePtr->hashKeyProc == NULL
- || typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) {
+ || typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) {
index = RANDOM_INDEX (tablePtr, hPtr->hash);
} else {
- index = ((unsigned int) hPtr->hash) & tablePtr->mask;
+ index = PTR2UINT(hPtr->hash) & tablePtr->mask;
}
hPtr->nextPtr = tablePtr->buckets[index];
tablePtr->buckets[index] = hPtr;
#else
- VOID *key = (VOID *) Tcl_GetHashKey (tablePtr, hPtr);
+ VOID *key = (VOID *) Tcl_GetHashKey(tablePtr, hPtr);
+
if (typePtr->hashKeyProc) {
unsigned int hash;
- hash = typePtr->hashKeyProc (tablePtr, (VOID *) key);
+
+ hash = typePtr->hashKeyProc(tablePtr, key);
if (typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) {
index = RANDOM_INDEX (tablePtr, hash);
} else {
@@ -1225,6 +1098,18 @@ RebuildTable(tablePtr)
*/
if (oldBuckets != tablePtr->staticBuckets) {
- ckfree((char *) oldBuckets);
+ if (typePtr->flags & TCL_HASH_KEY_SYSTEM_HASH) {
+ TclpSysFree((char *) oldBuckets);
+ } else {
+ ckfree((char *) oldBuckets);
+ }
}
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclHistory.c b/generic/tclHistory.c
index 9ff3f49..a23e102 100644
--- a/generic/tclHistory.c
+++ b/generic/tclHistory.c
@@ -1,4 +1,4 @@
-/*
+/*
* tclHistory.c --
*
* This module and the Tcl library file history.tcl together implement
@@ -9,13 +9,11 @@
* Copyright (c) 1990-1993 The Regents of the University of California.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
-
/*
*----------------------------------------------------------------------
@@ -23,8 +21,7 @@
* Tcl_RecordAndEval --
*
* This procedure adds its command argument to the current list of
- * recorded events and then executes the command by calling
- * Tcl_Eval.
+ * recorded events and then executes the command by calling Tcl_Eval.
*
* Results:
* The return value is a standard Tcl return value, the result of
@@ -37,12 +34,12 @@
*/
int
-Tcl_RecordAndEval(interp, cmd, flags)
- Tcl_Interp *interp; /* Token for interpreter in which command
- * will be executed. */
- CONST char *cmd; /* Command to record. */
- int flags; /* Additional flags. TCL_NO_EVAL means
- * only record: don't execute command.
+Tcl_RecordAndEval(
+ Tcl_Interp *interp, /* Token for interpreter in which command will
+ * be executed. */
+ CONST char *cmd, /* Command to record. */
+ int flags) /* Additional flags. TCL_NO_EVAL means only
+ * record: don't execute command.
* TCL_EVAL_GLOBAL means use Tcl_GlobalEval
* instead of Tcl_Eval. */
{
@@ -60,18 +57,17 @@ Tcl_RecordAndEval(interp, cmd, flags)
result = Tcl_RecordAndEvalObj(interp, cmdPtr, flags);
/*
- * Move the interpreter's object result to the string result,
- * then reset the object result.
+ * Move the interpreter's object result to the string result, then
+ * reset the object result.
*/
- Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
- TCL_VOLATILE);
+ (void) Tcl_GetStringResult(interp);
/*
* Discard the Tcl object created to hold the command.
*/
-
- Tcl_DecrRefCount(cmdPtr);
+
+ Tcl_DecrRefCount(cmdPtr);
} else {
/*
* An empty string. Just reset the interpreter's result.
@@ -103,33 +99,56 @@ Tcl_RecordAndEval(interp, cmd, flags)
*/
int
-Tcl_RecordAndEvalObj(interp, cmdPtr, flags)
- Tcl_Interp *interp; /* Token for interpreter in which command
- * will be executed. */
- Tcl_Obj *cmdPtr; /* Points to object holding the command to
+Tcl_RecordAndEvalObj(
+ Tcl_Interp *interp, /* Token for interpreter in which command will
+ * be executed. */
+ Tcl_Obj *cmdPtr, /* Points to object holding the command to
* record and execute. */
- int flags; /* Additional flags. TCL_NO_EVAL means
- * record only: don't execute the command.
- * TCL_EVAL_GLOBAL means evaluate the
- * script in global variable context instead
- * of the current procedure. */
+ int flags) /* Additional flags. TCL_NO_EVAL means record
+ * only: don't execute the command.
+ * TCL_EVAL_GLOBAL means evaluate the script
+ * in global variable context instead of the
+ * current procedure. */
{
- int result;
+ int result, call = 1;
Tcl_Obj *list[3];
register Tcl_Obj *objPtr;
+ Tcl_CmdInfo info;
/*
- * Do recording by eval'ing a tcl history command: history add $cmd.
+ * Do not call [history] if it has been replaced by an empty proc
*/
- list[0] = Tcl_NewStringObj("history", -1);
- list[1] = Tcl_NewStringObj("add", -1);
- list[2] = cmdPtr;
-
- objPtr = Tcl_NewListObj(3, list);
- Tcl_IncrRefCount(objPtr);
- (void) Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL);
- Tcl_DecrRefCount(objPtr);
+ result = Tcl_GetCommandInfo(interp, "history", &info);
+
+ if (result && (info.objProc == TclObjInterpProc)) {
+ Proc *procPtr = (Proc *)(info.objClientData);
+ call = (procPtr->cmdPtr->compileProc != TclCompileNoOp);
+ }
+
+ if (call) {
+
+ /*
+ * Do recording by eval'ing a tcl history command: history add $cmd.
+ */
+
+ TclNewLiteralStringObj(list[0], "history");
+ TclNewLiteralStringObj(list[1], "add");
+ list[2] = cmdPtr;
+
+ objPtr = Tcl_NewListObj(3, list);
+ Tcl_IncrRefCount(objPtr);
+ (void) Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL);
+ Tcl_DecrRefCount(objPtr);
+
+ /*
+ * One possible failure mode above: exceeding a resource limit.
+ */
+
+ if (Tcl_LimitExceeded(interp)) {
+ return TCL_ERROR;
+ }
+ }
/*
* Execute the command.
@@ -141,3 +160,11 @@ Tcl_RecordAndEvalObj(interp, cmdPtr, flags)
}
return result;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclIO.c b/generic/tclIO.c
index 15ac94f..0f01baa 100644
--- a/generic/tclIO.c
+++ b/generic/tclIO.c
@@ -1,4 +1,4 @@
-/*
+/*
* tclIO.c --
*
* This file provides the generic portions (those that are the same on
@@ -7,64 +7,38 @@
* Copyright (c) 1998-2000 Ajuba Solutions
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
#include "tclIO.h"
#include <assert.h>
-#ifndef TCL_INHERIT_STD_CHANNELS
-#define TCL_INHERIT_STD_CHANNELS 1
-#endif
-
-
/*
- * All static variables used in this file are collected into a single
- * instance of the following structure. For multi-threaded implementations,
- * there is one instance of this structure for each thread.
+ * All static variables used in this file are collected into a single instance
+ * of the following structure. For multi-threaded implementations, there is
+ * one instance of this structure for each thread.
*
- * Notice that different structures with the same name appear in other
- * files. The structure defined below is used in this file only.
+ * Notice that different structures with the same name appear in other files.
+ * The structure defined below is used in this file only.
*/
typedef struct ThreadSpecificData {
-
- /*
- * This variable holds the list of nested ChannelHandlerEventProc
- * invocations.
- */
NextChannelHandler *nestedHandlerPtr;
-
- /*
- * List of all channels currently open, indexed by ChannelState,
- * as only one ChannelState exists per set of stacked channels.
- */
- ChannelState *firstCSPtr;
-#ifdef oldcode
- /*
- * Has a channel exit handler been created yet?
- */
- int channelExitHandlerCreated;
-
- /*
- * Has the channel event source been created and registered with the
- * notifier?
- */
- int channelEventSourceCreated;
-#endif
- /*
- * Static variables to hold channels for stdin, stdout and stderr.
- */
- Tcl_Channel stdinChannel;
+ /* This variable holds the list of nested
+ * ChannelHandlerEventProc invocations. */
+ ChannelState *firstCSPtr; /* List of all channels currently open,
+ * indexed by ChannelState, as only one
+ * ChannelState exists per set of stacked
+ * channels. */
+ Tcl_Channel stdinChannel; /* Static variable for the stdin channel. */
int stdinInitialized;
- Tcl_Channel stdoutChannel;
+ Tcl_Channel stdoutChannel; /* Static variable for the stdout channel. */
int stdoutInitialized;
- Tcl_Channel stderrChannel;
+ Tcl_Channel stderrChannel; /* Static variable for the stderr channel. */
int stderrInitialized;
-
+ Tcl_Encoding binaryEncoding;
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
@@ -73,86 +47,181 @@ static Tcl_ThreadDataKey dataKey;
* Static functions in this file:
*/
-static ChannelBuffer * AllocChannelBuffer _ANSI_ARGS_((int length));
-static void ChannelTimerProc _ANSI_ARGS_((
- ClientData clientData));
-static int CheckChannelErrors _ANSI_ARGS_((ChannelState *statePtr,
- int direction));
-static int CheckFlush _ANSI_ARGS_((Channel *chanPtr,
- ChannelBuffer *bufPtr, int newlineFlag));
-static int CheckForDeadChannel _ANSI_ARGS_((Tcl_Interp *interp,
- ChannelState *statePtr));
-static void CheckForStdChannelsBeingClosed _ANSI_ARGS_((
- Tcl_Channel chan));
-static void CleanupChannelHandlers _ANSI_ARGS_((
- Tcl_Interp *interp, Channel *chanPtr));
-static int CloseChannel _ANSI_ARGS_((Tcl_Interp *interp,
- Channel *chanPtr, int errorCode));
-static void CommonGetsCleanup _ANSI_ARGS_((Channel *chanPtr,
- Tcl_Encoding encoding));
-static int CopyAndTranslateBuffer _ANSI_ARGS_((
- ChannelState *statePtr, char *result,
- int space));
-static int CopyBuffer _ANSI_ARGS_((
- Channel *chanPtr, char *result, int space));
-static int CopyData _ANSI_ARGS_((CopyState *csPtr, int mask));
-static void CopyEventProc _ANSI_ARGS_((ClientData clientData,
- int mask));
-static void CreateScriptRecord _ANSI_ARGS_((
- Tcl_Interp *interp, Channel *chanPtr,
- int mask, Tcl_Obj *scriptPtr));
-static void DeleteChannelTable _ANSI_ARGS_((
- ClientData clientData, Tcl_Interp *interp));
-static void DeleteScriptRecord _ANSI_ARGS_((Tcl_Interp *interp,
- Channel *chanPtr, int mask));
-static int DetachChannel _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Channel chan));
-static void DiscardInputQueued _ANSI_ARGS_((ChannelState *statePtr,
- int discardSavedBuffers));
-static void DiscardOutputQueued _ANSI_ARGS_((
- ChannelState *chanPtr));
-static int DoRead _ANSI_ARGS_((Channel *chanPtr, char *srcPtr,
- int slen));
-static int DoWrite _ANSI_ARGS_((Channel *chanPtr, CONST char *src,
- int srcLen));
-static int DoReadChars _ANSI_ARGS_ ((Channel* chan,
- Tcl_Obj* objPtr, int toRead, int appendFlag));
-static int DoWriteChars _ANSI_ARGS_ ((Channel* chan,
- CONST char* src, int len));
-static int FilterInputBytes _ANSI_ARGS_((Channel *chanPtr,
- GetsState *statePtr));
-static int FlushChannel _ANSI_ARGS_((Tcl_Interp *interp,
- Channel *chanPtr, int calledFromAsyncFlush));
-static Tcl_HashTable * GetChannelTable _ANSI_ARGS_((Tcl_Interp *interp));
-static int GetInput _ANSI_ARGS_((Channel *chanPtr));
-static int HaveVersion _ANSI_ARGS_((Tcl_ChannelType *typePtr,
- Tcl_ChannelTypeVersion minimumVersion));
-static void PeekAhead _ANSI_ARGS_((Channel *chanPtr,
- char **dstEndPtr, GetsState *gsPtr));
-static int ReadBytes _ANSI_ARGS_((ChannelState *statePtr,
- Tcl_Obj *objPtr, int charsLeft,
- int *offsetPtr));
-static int ReadChars _ANSI_ARGS_((ChannelState *statePtr,
- Tcl_Obj *objPtr, int charsLeft,
- int *offsetPtr, int *factorPtr));
-static void RecycleBuffer _ANSI_ARGS_((ChannelState *statePtr,
- ChannelBuffer *bufPtr, int mustDiscard));
-static int StackSetBlockMode _ANSI_ARGS_((Channel *chanPtr,
- int mode));
-static int SetBlockMode _ANSI_ARGS_((Tcl_Interp *interp,
- Channel *chanPtr, int mode));
-static void StopCopy _ANSI_ARGS_((CopyState *csPtr));
-static int TranslateInputEOL _ANSI_ARGS_((ChannelState *statePtr,
- char *dst, CONST char *src,
- int *dstLenPtr, int *srcLenPtr));
-static int TranslateOutputEOL _ANSI_ARGS_((ChannelState *statePtr,
- char *dst, CONST char *src,
- int *dstLenPtr, int *srcLenPtr));
-static void UpdateInterest _ANSI_ARGS_((Channel *chanPtr));
-static int WriteBytes _ANSI_ARGS_((Channel *chanPtr,
- CONST char *src, int srcLen));
-static int WriteChars _ANSI_ARGS_((Channel *chanPtr,
- CONST char *src, int srcLen));
+static ChannelBuffer * AllocChannelBuffer(int length);
+static void ChannelTimerProc(ClientData clientData);
+static int CheckChannelErrors(ChannelState *statePtr,
+ int direction);
+static int CheckFlush(Channel *chanPtr, ChannelBuffer *bufPtr,
+ int newlineFlag);
+static int CheckForDeadChannel(Tcl_Interp *interp,
+ ChannelState *statePtr);
+static void CheckForStdChannelsBeingClosed(Tcl_Channel chan);
+static void CleanupChannelHandlers(Tcl_Interp *interp,
+ Channel *chanPtr);
+static int CloseChannel(Tcl_Interp *interp, Channel *chanPtr,
+ int errorCode);
+static void CommonGetsCleanup(Channel *chanPtr);
+static int CopyAndTranslateBuffer(ChannelState *statePtr,
+ char *result, int space);
+static int CopyBuffer(Channel *chanPtr, char *result, int space);
+static int CopyData(CopyState *csPtr, int mask);
+static void CopyEventProc(ClientData clientData, int mask);
+static void CreateScriptRecord(Tcl_Interp *interp,
+ Channel *chanPtr, int mask, Tcl_Obj *scriptPtr);
+static void DeleteChannelTable(ClientData clientData,
+ Tcl_Interp *interp);
+static void DeleteScriptRecord(Tcl_Interp *interp,
+ Channel *chanPtr, int mask);
+static int DetachChannel(Tcl_Interp *interp, Tcl_Channel chan);
+static void DiscardInputQueued(ChannelState *statePtr,
+ int discardSavedBuffers);
+static void DiscardOutputQueued(ChannelState *chanPtr);
+static int DoRead(Channel *chanPtr, char *srcPtr, int slen);
+static int DoWrite(Channel *chanPtr, const char *src, int srcLen);
+static int DoReadChars(Channel *chan, Tcl_Obj *objPtr, int toRead,
+ int appendFlag);
+static int DoWriteChars(Channel *chan, const char *src, int len);
+static int FilterInputBytes(Channel *chanPtr,
+ GetsState *statePtr);
+static int FlushChannel(Tcl_Interp *interp, Channel *chanPtr,
+ int calledFromAsyncFlush);
+static int TclGetsObjBinary(Tcl_Channel chan, Tcl_Obj *objPtr);
+static void FreeBinaryEncoding(ClientData clientData);
+static Tcl_HashTable * GetChannelTable(Tcl_Interp *interp);
+static int GetInput(Channel *chanPtr);
+static int HaveVersion(const Tcl_ChannelType *typePtr,
+ Tcl_ChannelTypeVersion minimumVersion);
+static void PeekAhead(Channel *chanPtr, char **dstEndPtr,
+ GetsState *gsPtr);
+static int ReadBytes(ChannelState *statePtr, Tcl_Obj *objPtr,
+ int charsLeft, int *offsetPtr);
+static int ReadChars(ChannelState *statePtr, Tcl_Obj *objPtr,
+ int charsLeft, int *offsetPtr, int *factorPtr);
+static void RecycleBuffer(ChannelState *statePtr,
+ ChannelBuffer *bufPtr, int mustDiscard);
+static int StackSetBlockMode(Channel *chanPtr, int mode);
+static int SetBlockMode(Tcl_Interp *interp, Channel *chanPtr,
+ int mode);
+static void StopCopy(CopyState *csPtr);
+static int TranslateInputEOL(ChannelState *statePtr, char *dst,
+ const char *src, int *dstLenPtr, int *srcLenPtr);
+static int TranslateOutputEOL(ChannelState *statePtr, char *dst,
+ const char *src, int *dstLenPtr, int *srcLenPtr);
+static void UpdateInterest(Channel *chanPtr);
+static int WriteBytes(Channel *chanPtr, const char *src,
+ int srcLen);
+static int WriteChars(Channel *chanPtr, const char *src,
+ int srcLen);
+static Tcl_Obj * FixLevelCode(Tcl_Obj *msg);
+static void SpliceChannel(Tcl_Channel chan);
+static void CutChannel(Tcl_Channel chan);
+
+/*
+ * Simplifying helper macros. All may use their argument(s) multiple times.
+ * The ANSI C "prototypes" for the macros are listed below, together with a
+ * short description of what the macro does.
+ *
+ * --------------------------------------------------------------------------
+ * int BytesLeft(ChannelBuffer *bufPtr)
+ *
+ * Returns the number of bytes of data remaining in the buffer.
+ *
+ * int SpaceLeft(ChannelBuffer *bufPtr)
+ *
+ * Returns the number of bytes of space remaining at the end of the
+ * buffer.
+ *
+ * int IsBufferReady(ChannelBuffer *bufPtr)
+ *
+ * Returns whether a buffer has bytes available within it.
+ *
+ * int IsBufferEmpty(ChannelBuffer *bufPtr)
+ *
+ * Returns whether a buffer is entirely empty. Note that this is not the
+ * inverse of the above operation; trying to merge the two seems to lead
+ * to occasional crashes...
+ *
+ * int IsBufferFull(ChannelBuffer *bufPtr)
+ *
+ * Returns whether more data can be added to a buffer.
+ *
+ * int IsBufferOverflowing(ChannelBuffer *bufPtr)
+ *
+ * Returns whether a buffer has more data in it than it should.
+ *
+ * char *InsertPoint(ChannelBuffer *bufPtr)
+ *
+ * Returns a pointer to where characters should be added to the buffer.
+ *
+ * char *RemovePoint(ChannelBuffer *bufPtr)
+ *
+ * Returns a pointer to where characters should be removed from the
+ * buffer.
+ * --------------------------------------------------------------------------
+ */
+
+#define BytesLeft(bufPtr) ((bufPtr)->nextAdded - (bufPtr)->nextRemoved)
+
+#define SpaceLeft(bufPtr) ((bufPtr)->bufLength - (bufPtr)->nextAdded)
+
+#define IsBufferReady(bufPtr) ((bufPtr)->nextAdded > (bufPtr)->nextRemoved)
+
+#define IsBufferEmpty(bufPtr) ((bufPtr)->nextAdded == (bufPtr)->nextRemoved)
+
+#define IsBufferFull(bufPtr) ((bufPtr)->nextAdded >= (bufPtr)->bufLength)
+
+#define IsBufferOverflowing(bufPtr) ((bufPtr)->nextAdded > (bufPtr)->bufLength)
+
+#define InsertPoint(bufPtr) ((bufPtr)->buf + (bufPtr)->nextAdded)
+
+#define RemovePoint(bufPtr) ((bufPtr)->buf + (bufPtr)->nextRemoved)
+
+/*
+ * For working with channel state flag bits.
+ */
+
+#define SetFlag(statePtr, flag) ((statePtr)->flags |= (flag))
+#define ResetFlag(statePtr, flag) ((statePtr)->flags &= ~(flag))
+
+/*
+ * Macro for testing whether a string (in optionName, length len) matches a
+ * value (prefix matching rules). Arguments are the minimum length to match
+ * and the value to match against. (Can't use Tcl_GetIndexFromObj as this is
+ * used in a situation where no objects are available.)
+ */
+
+#define HaveOpt(minLength, nameString) \
+ ((len > (minLength)) && (optionName[1] == (nameString)[1]) \
+ && (strncmp(optionName, (nameString), len) == 0))
+
+/*
+ * The ChannelObjType type. We actually store the ChannelState structure
+ * as that lives longest and we want to return the bottomChanPtr when
+ * requested (consistent with Tcl_GetChannel). The setFromAny and
+ * updateString can be NULL as they should not be called.
+ */
+
+static void DupChannelIntRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr);
+static int SetChannelFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
+static void UpdateStringOfChannel(Tcl_Obj *objPtr);
+static void FreeChannelIntRep(Tcl_Obj *objPtr);
+
+static Tcl_ObjType tclChannelType = {
+ "channel", /* name for this type */
+ FreeChannelIntRep, /* freeIntRepProc */
+ DupChannelIntRep, /* dupIntRepProc */
+ NULL, /* updateStringProc UpdateStringOfChannel */
+ NULL /* setFromAnyProc SetChannelFromAny */
+};
+
+#define GET_CHANNELSTATE(objPtr) \
+ ((ChannelState *) (objPtr)->internalRep.otherValuePtr)
+#define SET_CHANNELSTATE(objPtr, storePtr) \
+ ((objPtr)->internalRep.otherValuePtr = (void *) (storePtr))
+#define GET_CHANNELINTERP(objPtr) \
+ ((Interp *) (objPtr)->internalRep.twoPtrValue.ptr2)
+#define SET_CHANNELINTERP(objPtr, storePtr) \
+ ((objPtr)->internalRep.twoPtrValue.ptr2 = (void *) (storePtr))
#define BUSY_STATE(st,fl) \
((((st)->csPtrR) && ((fl) & TCL_READABLE)) || \
@@ -166,7 +235,7 @@ static int WriteChars _ANSI_ARGS_((Channel *chanPtr,
* TclInitIOSubsystem --
*
* Initialize all resources used by this subsystem on a per-process
- * basis.
+ * basis.
*
* Results:
* None.
@@ -178,23 +247,24 @@ static int WriteChars _ANSI_ARGS_((Channel *chanPtr,
*/
void
-TclInitIOSubsystem()
+TclInitIOSubsystem(void)
{
/*
- * By fetching thread local storage we take care of
- * allocating it for each thread.
+ * By fetching thread local storage we take care of allocating it for each
+ * thread.
*/
+
(void) TCL_TSD_INIT(&dataKey);
-}
+}
/*
*-------------------------------------------------------------------------
*
* TclFinalizeIOSubsystem --
*
- * Releases all resources used by this subsystem on a per-thread
- * basis. Closes all extant channels that have not already been
- * closed because they were not owned by any interp.
+ * Releases all resources used by this subsystem on a per-process basis.
+ * Closes all extant channels that have not already been closed because
+ * they were not owned by any interp.
*
* Results:
* None.
@@ -215,23 +285,21 @@ TclFinalizeIOSubsystem(void)
int active = 1; /* Flag == 1 while there's still work to do */
/*
- * Walk all channel state structures known to this thread and
- * close corresponding channels.
+ * Walk all channel state structures known to this thread and close
+ * corresponding channels.
*/
while (active) {
-
/*
- * Iterate through the open channel list, and find the first
- * channel that isn't dead. We start from the head of the list
- * each time, because the close action on one channel can close
- * others.
+ * Iterate through the open channel list, and find the first channel
+ * that isn't dead. We start from the head of the list each time,
+ * because the close action on one channel can close others.
*/
active = 0;
for (statePtr = tsdPtr->firstCSPtr;
- statePtr != NULL;
- statePtr = statePtr->nextCSPtr) {
+ statePtr != NULL;
+ statePtr = statePtr->nextCSPtr) {
chanPtr = statePtr->topChanPtr;
if (!(statePtr->flags & (CHANNEL_INCLOSE|CHANNEL_CLOSED|CHANNEL_DEAD))) {
active = 1;
@@ -240,67 +308,65 @@ TclFinalizeIOSubsystem(void)
}
/*
- * We've found a live channel. Close it.
+ * We've found a live channel. Close it.
*/
if (active) {
-
/*
- * Set the channel back into blocking mode to ensure that we
- * wait for all data to flush out.
+ * Set the channel back into blocking mode to ensure that we wait
+ * for all data to flush out.
*/
-
+
(void) Tcl_SetChannelOption(NULL, (Tcl_Channel) chanPtr,
- "-blocking", "on");
-
+ "-blocking", "on");
+
if ((chanPtr == (Channel *) tsdPtr->stdinChannel) ||
- (chanPtr == (Channel *) tsdPtr->stdoutChannel) ||
- (chanPtr == (Channel *) tsdPtr->stderrChannel)) {
+ (chanPtr == (Channel *) tsdPtr->stdoutChannel) ||
+ (chanPtr == (Channel *) tsdPtr->stderrChannel)) {
/*
- * Decrement the refcount which was earlier artificially
+ * Decrement the refcount which was earlier artificially
* bumped up to keep the channel from being closed.
*/
-
+
statePtr->refCount--;
}
-
+
if (statePtr->refCount <= 0) {
/*
- * Close it only if the refcount indicates that the channel
- * is not referenced from any interpreter. If it is, that
+ * Close it only if the refcount indicates that the channel is
+ * not referenced from any interpreter. If it is, that
* interpreter will close the channel when it gets destroyed.
*/
-
+
(void) Tcl_Close(NULL, (Tcl_Channel) chanPtr);
} else {
/*
* The refcount is greater than zero, so flush the channel.
*/
-
+
Tcl_Flush((Tcl_Channel) chanPtr);
-
+
/*
- * Call the device driver to actually close the underlying
+ * Call the device driver to actually close the underlying
* device for this channel.
*/
-
+
if (chanPtr->typePtr->closeProc != TCL_CLOSE2PROC) {
(chanPtr->typePtr->closeProc)(chanPtr->instanceData, NULL);
} else {
(chanPtr->typePtr->close2Proc)(chanPtr->instanceData,
- NULL, 0);
+ NULL, 0);
}
-
+
/*
- * Finally, we clean up the fields in the channel data
- * structure since all of them have been deleted already.
- * We mark the channel with CHANNEL_DEAD to prevent any
- * further IO operations
- * on it.
+ * Finally, we clean up the fields in the channel data
+ * structure since all of them have been deleted already. We
+ * mark the channel with CHANNEL_DEAD to prevent any further
+ * IO operations on it.
*/
-
+
chanPtr->instanceData = NULL;
- statePtr->flags |= CHANNEL_DEAD;
+ SetFlag(statePtr, CHANNEL_DEAD);
}
}
}
@@ -308,15 +374,14 @@ TclFinalizeIOSubsystem(void)
TclpFinalizeSockets();
TclpFinalizePipes();
}
-
/*
*----------------------------------------------------------------------
*
* Tcl_SetStdChannel --
*
- * This function is used to change the channels that are used
- * for stdin/stdout/stderr in new interpreters.
+ * This function is used to change the channels that are used for
+ * stdin/stdout/stderr in new interpreters.
*
* Results:
* None
@@ -328,24 +393,24 @@ TclFinalizeIOSubsystem(void)
*/
void
-Tcl_SetStdChannel(channel, type)
- Tcl_Channel channel;
- int type; /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR. */
+Tcl_SetStdChannel(
+ Tcl_Channel channel,
+ int type) /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR. */
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
switch (type) {
- case TCL_STDIN:
- tsdPtr->stdinInitialized = 1;
- tsdPtr->stdinChannel = channel;
- break;
- case TCL_STDOUT:
- tsdPtr->stdoutInitialized = 1;
- tsdPtr->stdoutChannel = channel;
- break;
- case TCL_STDERR:
- tsdPtr->stderrInitialized = 1;
- tsdPtr->stderrChannel = channel;
- break;
+ case TCL_STDIN:
+ tsdPtr->stdinInitialized = 1;
+ tsdPtr->stdinChannel = channel;
+ break;
+ case TCL_STDOUT:
+ tsdPtr->stdoutInitialized = 1;
+ tsdPtr->stdoutChannel = channel;
+ break;
+ case TCL_STDERR:
+ tsdPtr->stderrInitialized = 1;
+ tsdPtr->stderrChannel = channel;
+ break;
}
}
@@ -360,71 +425,67 @@ Tcl_SetStdChannel(channel, type)
* Returns the specified standard channel, or NULL.
*
* Side effects:
- * May cause the creation of a standard channel and the underlying
- * file.
+ * May cause the creation of a standard channel and the underlying file.
*
*----------------------------------------------------------------------
*/
+
Tcl_Channel
-Tcl_GetStdChannel(type)
- int type; /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR. */
+Tcl_GetStdChannel(
+ int type) /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR. */
{
Tcl_Channel channel = NULL;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
/*
- * If the channels were not created yet, create them now and
- * store them in the static variables.
+ * If the channels were not created yet, create them now and store them in
+ * the static variables.
*/
switch (type) {
- case TCL_STDIN:
- if (!tsdPtr->stdinInitialized) {
- tsdPtr->stdinChannel = TclpGetDefaultStdChannel(TCL_STDIN);
- tsdPtr->stdinInitialized = 1;
+ case TCL_STDIN:
+ if (!tsdPtr->stdinInitialized) {
+ tsdPtr->stdinChannel = TclpGetDefaultStdChannel(TCL_STDIN);
+ tsdPtr->stdinInitialized = 1;
- /*
- * Artificially bump the refcount to ensure that the channel
- * is only closed on exit.
- *
- * NOTE: Must only do this if stdinChannel is not NULL. It
- * can be NULL in situations where Tcl is unable to connect
- * to the standard input.
- */
-
- if (tsdPtr->stdinChannel != (Tcl_Channel) NULL) {
- (void) Tcl_RegisterChannel((Tcl_Interp *) NULL,
- tsdPtr->stdinChannel);
- }
- }
- channel = tsdPtr->stdinChannel;
- break;
- case TCL_STDOUT:
- if (!tsdPtr->stdoutInitialized) {
- tsdPtr->stdoutChannel = TclpGetDefaultStdChannel(TCL_STDOUT);
- tsdPtr->stdoutInitialized = 1;
- if (tsdPtr->stdoutChannel != (Tcl_Channel) NULL) {
- (void) Tcl_RegisterChannel((Tcl_Interp *) NULL,
- tsdPtr->stdoutChannel);
- }
- }
- channel = tsdPtr->stdoutChannel;
- break;
- case TCL_STDERR:
- if (!tsdPtr->stderrInitialized) {
- tsdPtr->stderrChannel = TclpGetDefaultStdChannel(TCL_STDERR);
- tsdPtr->stderrInitialized = 1;
- if (tsdPtr->stderrChannel != (Tcl_Channel) NULL) {
- (void) Tcl_RegisterChannel((Tcl_Interp *) NULL,
- tsdPtr->stderrChannel);
- }
- }
- channel = tsdPtr->stderrChannel;
- break;
+ /*
+ * Artificially bump the refcount to ensure that the channel is
+ * only closed on exit.
+ *
+ * NOTE: Must only do this if stdinChannel is not NULL. It can be
+ * NULL in situations where Tcl is unable to connect to the
+ * standard input.
+ */
+
+ if (tsdPtr->stdinChannel != NULL) {
+ Tcl_RegisterChannel(NULL, tsdPtr->stdinChannel);
+ }
+ }
+ channel = tsdPtr->stdinChannel;
+ break;
+ case TCL_STDOUT:
+ if (!tsdPtr->stdoutInitialized) {
+ tsdPtr->stdoutChannel = TclpGetDefaultStdChannel(TCL_STDOUT);
+ tsdPtr->stdoutInitialized = 1;
+ if (tsdPtr->stdoutChannel != NULL) {
+ Tcl_RegisterChannel(NULL, tsdPtr->stdoutChannel);
+ }
+ }
+ channel = tsdPtr->stdoutChannel;
+ break;
+ case TCL_STDERR:
+ if (!tsdPtr->stderrInitialized) {
+ tsdPtr->stderrChannel = TclpGetDefaultStdChannel(TCL_STDERR);
+ tsdPtr->stderrInitialized = 1;
+ if (tsdPtr->stderrChannel != NULL) {
+ Tcl_RegisterChannel(NULL, tsdPtr->stderrChannel);
+ }
+ }
+ channel = tsdPtr->stderrChannel;
+ break;
}
return channel;
}
-
/*
*----------------------------------------------------------------------
@@ -438,27 +499,27 @@ Tcl_GetStdChannel(type)
* None.
*
* Side effects:
- * Causes the callback to be called in the future when the channel
- * will be closed.
+ * Causes the callback to be called in the future when the channel will
+ * be closed.
*
*----------------------------------------------------------------------
*/
void
-Tcl_CreateCloseHandler(chan, proc, clientData)
- Tcl_Channel chan; /* The channel for which to create the
- * close callback. */
- Tcl_CloseProc *proc; /* The callback routine to call when the
- * channel will be closed. */
- ClientData clientData; /* Arbitrary data to pass to the
- * close callback. */
+Tcl_CreateCloseHandler(
+ Tcl_Channel chan, /* The channel for which to create the close
+ * callback. */
+ Tcl_CloseProc *proc, /* The callback routine to call when the
+ * channel will be closed. */
+ ClientData clientData) /* Arbitrary data to pass to the close
+ * callback. */
{
ChannelState *statePtr;
CloseCallback *cbPtr;
statePtr = ((Channel *) chan)->state;
- cbPtr = (CloseCallback *) ckalloc((unsigned) sizeof(CloseCallback));
+ cbPtr = (CloseCallback *) ckalloc(sizeof(CloseCallback));
cbPtr->proc = proc;
cbPtr->clientData = clientData;
@@ -471,45 +532,43 @@ Tcl_CreateCloseHandler(chan, proc, clientData)
*
* Tcl_DeleteCloseHandler --
*
- * Removes a callback that would have been called on closing
- * the channel. If there is no matching callback then this
- * function has no effect.
+ * Removes a callback that would have been called on closing the channel.
+ * If there is no matching callback then this function has no effect.
*
* Results:
* None.
*
* Side effects:
- * The callback will not be called in the future when the channel
- * is eventually closed.
+ * The callback will not be called in the future when the channel is
+ * eventually closed.
*
*----------------------------------------------------------------------
*/
void
-Tcl_DeleteCloseHandler(chan, proc, clientData)
- Tcl_Channel chan; /* The channel for which to cancel the
- * close callback. */
- Tcl_CloseProc *proc; /* The procedure for the callback to
- * remove. */
- ClientData clientData; /* The callback data for the callback
- * to remove. */
+Tcl_DeleteCloseHandler(
+ Tcl_Channel chan, /* The channel for which to cancel the close
+ * callback. */
+ Tcl_CloseProc *proc, /* The procedure for the callback to
+ * remove. */
+ ClientData clientData) /* The callback data for the callback to
+ * remove. */
{
ChannelState *statePtr;
CloseCallback *cbPtr, *cbPrevPtr;
statePtr = ((Channel *) chan)->state;
- for (cbPtr = statePtr->closeCbPtr, cbPrevPtr = (CloseCallback *) NULL;
- cbPtr != (CloseCallback *) NULL;
- cbPtr = cbPtr->nextPtr) {
- if ((cbPtr->proc == proc) && (cbPtr->clientData == clientData)) {
- if (cbPrevPtr == (CloseCallback *) NULL) {
- statePtr->closeCbPtr = cbPtr->nextPtr;
- }
- ckfree((char *) cbPtr);
- break;
- } else {
- cbPrevPtr = cbPtr;
- }
+ for (cbPtr = statePtr->closeCbPtr, cbPrevPtr = NULL;
+ cbPtr != NULL; cbPtr = cbPtr->nextPtr) {
+ if ((cbPtr->proc == proc) && (cbPtr->clientData == clientData)) {
+ if (cbPrevPtr == NULL) {
+ statePtr->closeCbPtr = cbPtr->nextPtr;
+ }
+ ckfree((char *) cbPtr);
+ break;
+ } else {
+ cbPrevPtr = cbPtr;
+ }
}
}
@@ -518,58 +577,53 @@ Tcl_DeleteCloseHandler(chan, proc, clientData)
*
* GetChannelTable --
*
- * Gets and potentially initializes the channel table for an
- * interpreter. If it is initializing the table it also inserts
- * channels for stdin, stdout and stderr if the interpreter is
- * trusted.
+ * Gets and potentially initializes the channel table for an interpreter.
+ * If it is initializing the table it also inserts channels for stdin,
+ * stdout and stderr if the interpreter is trusted.
*
* Results:
* A pointer to the hash table created, for use by the caller.
*
* Side effects:
- * Initializes the channel table for an interpreter. May create
- * channels for stdin, stdout and stderr.
+ * Initializes the channel table for an interpreter. May create channels
+ * for stdin, stdout and stderr.
*
*----------------------------------------------------------------------
*/
static Tcl_HashTable *
-GetChannelTable(interp)
- Tcl_Interp *interp;
+GetChannelTable(
+ Tcl_Interp *interp)
{
Tcl_HashTable *hTblPtr; /* Hash table of channels. */
Tcl_Channel stdinChan, stdoutChan, stderrChan;
- hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL);
- if (hTblPtr == (Tcl_HashTable *) NULL) {
- hTblPtr = (Tcl_HashTable *) ckalloc((unsigned) sizeof(Tcl_HashTable));
- Tcl_InitHashTable(hTblPtr, TCL_STRING_KEYS);
-
- (void) Tcl_SetAssocData(interp, "tclIO",
- (Tcl_InterpDeleteProc *) DeleteChannelTable,
- (ClientData) hTblPtr);
-
- /*
- * If the interpreter is trusted (not "safe"), insert channels
- * for stdin, stdout and stderr (possibly creating them in the
- * process).
- */
-
- if (Tcl_IsSafe(interp) == 0) {
- stdinChan = Tcl_GetStdChannel(TCL_STDIN);
- if (stdinChan != NULL) {
- Tcl_RegisterChannel(interp, stdinChan);
- }
- stdoutChan = Tcl_GetStdChannel(TCL_STDOUT);
- if (stdoutChan != NULL) {
- Tcl_RegisterChannel(interp, stdoutChan);
- }
- stderrChan = Tcl_GetStdChannel(TCL_STDERR);
- if (stderrChan != NULL) {
- Tcl_RegisterChannel(interp, stderrChan);
- }
- }
+ hTblPtr = Tcl_GetAssocData(interp, "tclIO", NULL);
+ if (hTblPtr == NULL) {
+ hTblPtr = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
+ Tcl_InitHashTable(hTblPtr, TCL_STRING_KEYS);
+ Tcl_SetAssocData(interp, "tclIO",
+ (Tcl_InterpDeleteProc *) DeleteChannelTable, hTblPtr);
+ /*
+ * If the interpreter is trusted (not "safe"), insert channels for
+ * stdin, stdout and stderr (possibly creating them in the process).
+ */
+
+ if (Tcl_IsSafe(interp) == 0) {
+ stdinChan = Tcl_GetStdChannel(TCL_STDIN);
+ if (stdinChan != NULL) {
+ Tcl_RegisterChannel(interp, stdinChan);
+ }
+ stdoutChan = Tcl_GetStdChannel(TCL_STDOUT);
+ if (stdoutChan != NULL) {
+ Tcl_RegisterChannel(interp, stdoutChan);
+ }
+ stderrChan = Tcl_GetStdChannel(TCL_STDERR);
+ if (stderrChan != NULL) {
+ Tcl_RegisterChannel(interp, stderrChan);
+ }
+ }
}
return hTblPtr;
}
@@ -580,9 +634,8 @@ GetChannelTable(interp)
* DeleteChannelTable --
*
* Deletes the channel table for an interpreter, closing any open
- * channels whose refcount reaches zero. This procedure is invoked
- * when an interpreter is deleted, via the AssocData cleanup
- * mechanism.
+ * channels whose refcount reaches zero. This procedure is invoked when
+ * an interpreter is deleted, via the AssocData cleanup mechanism.
*
* Results:
* None.
@@ -596,9 +649,9 @@ GetChannelTable(interp)
*/
static void
-DeleteChannelTable(clientData, interp)
- ClientData clientData; /* The per-interpreter data structure. */
- Tcl_Interp *interp; /* The interpreter being deleted. */
+DeleteChannelTable(
+ ClientData clientData, /* The per-interpreter data structure. */
+ Tcl_Interp *interp) /* The interpreter being deleted. */
{
Tcl_HashTable *hTblPtr; /* The hash table. */
Tcl_HashSearch hSearch; /* Search variable. */
@@ -606,63 +659,61 @@ DeleteChannelTable(clientData, interp)
Channel *chanPtr; /* Channel being deleted. */
ChannelState *statePtr; /* State of Channel being deleted. */
EventScriptRecord *sPtr, *prevPtr, *nextPtr;
- /* Variables to loop over all channel events
- * registered, to delete the ones that refer
- * to the interpreter being deleted. */
+ /* Variables to loop over all channel events
+ * registered, to delete the ones that refer
+ * to the interpreter being deleted. */
/*
* Delete all the registered channels - this will close channels whose
* refcount reaches zero.
*/
-
- hTblPtr = (Tcl_HashTable *) clientData;
- for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
- hPtr != (Tcl_HashEntry *) NULL;
- hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch)) {
- chanPtr = (Channel *) Tcl_GetHashValue(hPtr);
+ hTblPtr = clientData;
+ for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch); hPtr != NULL;
+ hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch)) {
+ chanPtr = Tcl_GetHashValue(hPtr);
statePtr = chanPtr->state;
- /*
- * Remove any fileevents registered in this interpreter.
- */
-
- for (sPtr = statePtr->scriptRecordPtr,
- prevPtr = (EventScriptRecord *) NULL;
- sPtr != (EventScriptRecord *) NULL;
- sPtr = nextPtr) {
- nextPtr = sPtr->nextPtr;
- if (sPtr->interp == interp) {
- if (prevPtr == (EventScriptRecord *) NULL) {
- statePtr->scriptRecordPtr = nextPtr;
- } else {
- prevPtr->nextPtr = nextPtr;
- }
-
- Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr,
- TclChannelEventScriptInvoker, (ClientData) sPtr);
-
- Tcl_DecrRefCount(sPtr->scriptPtr);
- ckfree((char *) sPtr);
- } else {
- prevPtr = sPtr;
- }
- }
-
- /*
- * Cannot call Tcl_UnregisterChannel because that procedure calls
- * Tcl_GetAssocData to get the channel table, which might already
- * be inaccessible from the interpreter structure. Instead, we
- * emulate the behavior of Tcl_UnregisterChannel directly here.
- */
-
- Tcl_DeleteHashEntry(hPtr);
- statePtr->refCount--;
- if (statePtr->refCount <= 0) {
- if (!(statePtr->flags & BG_FLUSH_SCHEDULED)) {
- (void) Tcl_Close(interp, (Tcl_Channel) chanPtr);
- }
- }
+ /*
+ * Remove any fileevents registered in this interpreter.
+ */
+
+ for (sPtr = statePtr->scriptRecordPtr, prevPtr = NULL;
+ sPtr != NULL; sPtr = nextPtr) {
+ nextPtr = sPtr->nextPtr;
+ if (sPtr->interp == interp) {
+ if (prevPtr == NULL) {
+ statePtr->scriptRecordPtr = nextPtr;
+ } else {
+ prevPtr->nextPtr = nextPtr;
+ }
+
+ Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr,
+ TclChannelEventScriptInvoker, (ClientData) sPtr);
+
+ TclDecrRefCount(sPtr->scriptPtr);
+ ckfree((char *) sPtr);
+ } else {
+ prevPtr = sPtr;
+ }
+ }
+
+ /*
+ * Cannot call Tcl_UnregisterChannel because that procedure calls
+ * Tcl_GetAssocData to get the channel table, which might already be
+ * inaccessible from the interpreter structure. Instead, we emulate
+ * the behavior of Tcl_UnregisterChannel directly here.
+ */
+
+ Tcl_DeleteHashEntry(hPtr);
+ SetFlag(statePtr, CHANNEL_TAINTED);
+ statePtr->refCount--;
+ if (statePtr->refCount <= 0) {
+ if (!(statePtr->flags & BG_FLUSH_SCHEDULED)) {
+ (void) Tcl_Close(interp, (Tcl_Channel) chanPtr);
+ }
+ }
+
}
Tcl_DeleteHashTable(hTblPtr);
ckfree((char *) hTblPtr);
@@ -674,11 +725,11 @@ DeleteChannelTable(clientData, interp)
* CheckForStdChannelsBeingClosed --
*
* Perform special handling for standard channels being closed. When
- * given a standard channel, if the refcount is now 1, it means that
- * the last reference to the standard channel is being explicitly
- * closed. Now bump the refcount artificially down to 0, to ensure the
- * normal handling of channels being closed will occur. Also reset the
- * static pointer to the channel to NULL, to avoid dangling references.
+ * given a standard channel, if the refcount is now 1, it means that the
+ * last reference to the standard channel is being explicitly closed. Now
+ * bump the refcount artificially down to 0, to ensure the normal
+ * handling of channels being closed will occur. Also reset the static
+ * pointer to the channel to NULL, to avoid dangling references.
*
* Results:
* None.
@@ -691,32 +742,32 @@ DeleteChannelTable(clientData, interp)
*/
static void
-CheckForStdChannelsBeingClosed(chan)
- Tcl_Channel chan;
+CheckForStdChannelsBeingClosed(
+ Tcl_Channel chan)
{
ChannelState *statePtr = ((Channel *) chan)->state;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
if ((chan == tsdPtr->stdinChannel) && (tsdPtr->stdinInitialized)) {
- if (statePtr->refCount < 2) {
- statePtr->refCount = 0;
- tsdPtr->stdinChannel = NULL;
- return;
- }
+ if (statePtr->refCount < 2) {
+ statePtr->refCount = 0;
+ tsdPtr->stdinChannel = NULL;
+ return;
+ }
} else if ((chan == tsdPtr->stdoutChannel)
&& (tsdPtr->stdoutInitialized)) {
- if (statePtr->refCount < 2) {
- statePtr->refCount = 0;
- tsdPtr->stdoutChannel = NULL;
- return;
- }
+ if (statePtr->refCount < 2) {
+ statePtr->refCount = 0;
+ tsdPtr->stdoutChannel = NULL;
+ return;
+ }
} else if ((chan == tsdPtr->stderrChannel)
&& (tsdPtr->stderrInitialized)) {
- if (statePtr->refCount < 2) {
- statePtr->refCount = 0;
- tsdPtr->stderrChannel = NULL;
- return;
- }
+ if (statePtr->refCount < 2) {
+ statePtr->refCount = 0;
+ tsdPtr->stderrChannel = NULL;
+ return;
+ }
}
}
@@ -725,27 +776,28 @@ CheckForStdChannelsBeingClosed(chan)
*
* Tcl_IsStandardChannel --
*
- * Test if the given channel is a standard channel. No attempt
- * is made to check if the channel or the standard channels
- * are initialized or otherwise valid.
+ * Test if the given channel is a standard channel. No attempt is made to
+ * check if the channel or the standard channels are initialized or
+ * otherwise valid.
*
* Results:
* Returns 1 if true, 0 if false.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
-int
-Tcl_IsStandardChannel(chan)
- Tcl_Channel chan; /* Channel to check. */
+
+int
+Tcl_IsStandardChannel(
+ Tcl_Channel chan) /* Channel to check. */
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- if ((chan == tsdPtr->stdinChannel)
- || (chan == tsdPtr->stdoutChannel)
- || (chan == tsdPtr->stderrChannel)) {
+ if ((chan == tsdPtr->stdinChannel)
+ || (chan == tsdPtr->stdoutChannel)
+ || (chan == tsdPtr->stderrChannel)) {
return 1;
} else {
return 0;
@@ -758,8 +810,8 @@ Tcl_IsStandardChannel(chan)
* Tcl_RegisterChannel --
*
* Adds an already-open channel to the channel table of an interpreter.
- * If the interpreter passed as argument is NULL, it only increments
- * the channel refCount.
+ * If the interpreter passed as argument is NULL, it only increments the
+ * channel refCount.
*
* Results:
* None.
@@ -771,41 +823,41 @@ Tcl_IsStandardChannel(chan)
*/
void
-Tcl_RegisterChannel(interp, chan)
- Tcl_Interp *interp; /* Interpreter in which to add the channel. */
- Tcl_Channel chan; /* The channel to add to this interpreter
- * channel table. */
+Tcl_RegisterChannel(
+ Tcl_Interp *interp, /* Interpreter in which to add the channel. */
+ Tcl_Channel chan) /* The channel to add to this interpreter
+ * channel table. */
{
Tcl_HashTable *hTblPtr; /* Hash table of channels. */
Tcl_HashEntry *hPtr; /* Search variable. */
- int new; /* Is the hash entry new or does it exist? */
+ int isNew; /* Is the hash entry new or does it exist? */
Channel *chanPtr; /* The actual channel. */
ChannelState *statePtr; /* State of the actual channel. */
/*
- * Always (un)register bottom-most channel in the stack. This makes
+ * Always (un)register bottom-most channel in the stack. This makes
* management of the channel list easier because no manipulation is
* necessary during (un)stack operation.
*/
+
chanPtr = ((Channel *) chan)->state->bottomChanPtr;
statePtr = chanPtr->state;
- if (statePtr->channelName == (CONST char *) NULL) {
- panic("Tcl_RegisterChannel: channel without name");
+ if (statePtr->channelName == NULL) {
+ Tcl_Panic("Tcl_RegisterChannel: channel without name");
}
- if (interp != (Tcl_Interp *) NULL) {
- hTblPtr = GetChannelTable(interp);
- hPtr = Tcl_CreateHashEntry(hTblPtr, statePtr->channelName, &new);
- if (new == 0) {
- if (chan == (Tcl_Channel) Tcl_GetHashValue(hPtr)) {
- return;
- }
+ if (interp != NULL) {
+ hTblPtr = GetChannelTable(interp);
+ hPtr = Tcl_CreateHashEntry(hTblPtr, statePtr->channelName, &isNew);
+ if (!isNew) {
+ if (chan == Tcl_GetHashValue(hPtr)) {
+ return;
+ }
- panic("Tcl_RegisterChannel: duplicate channel names");
- }
- Tcl_SetHashValue(hPtr, (ClientData) chanPtr);
+ Tcl_Panic("Tcl_RegisterChannel: duplicate channel names");
+ }
+ Tcl_SetHashValue(hPtr, chanPtr);
}
-
statePtr->refCount++;
}
@@ -816,19 +868,19 @@ Tcl_RegisterChannel(interp, chan)
*
* Deletes the hash entry for a channel associated with an interpreter.
* If the interpreter given as argument is NULL, it only decrements the
- * reference count. (This all happens in the Tcl_DetachChannel helper
+ * reference count. (This all happens in the Tcl_DetachChannel helper
* function).
- *
- * Finally, if the reference count of the channel drops to zero,
- * it is deleted.
+ *
+ * Finally, if the reference count of the channel drops to zero, it is
+ * deleted.
*
* Results:
* A standard Tcl result.
*
* Side effects:
- * Calls Tcl_DetachChannel which deletes the hash entry for a channel
+ * Calls Tcl_DetachChannel which deletes the hash entry for a channel
* associated with an interpreter.
- *
+ *
* May delete the channel, which can have a variety of consequences,
* especially if we are forced to close the channel.
*
@@ -836,27 +888,26 @@ Tcl_RegisterChannel(interp, chan)
*/
int
-Tcl_UnregisterChannel(interp, chan)
- Tcl_Interp *interp; /* Interpreter in which channel is defined. */
- Tcl_Channel chan; /* Channel to delete. */
+Tcl_UnregisterChannel(
+ Tcl_Interp *interp, /* Interpreter in which channel is defined. */
+ Tcl_Channel chan) /* Channel to delete. */
{
ChannelState *statePtr; /* State of the real channel. */
statePtr = ((Channel *) chan)->state->bottomChanPtr->state;
-
+
if (statePtr->flags & CHANNEL_INCLOSE) {
- if (interp != (Tcl_Interp*) NULL) {
- Tcl_AppendResult(interp,
- "Illegal recursive call to close through close-handler of channel",
- (char *) NULL);
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "Illegal recursive call to close "
+ "through close-handler of channel", NULL);
}
- return TCL_ERROR;
+ return TCL_ERROR;
}
-
+
if (DetachChannel(interp, chan) != TCL_OK) {
- return TCL_OK;
+ return TCL_OK;
}
-
+
statePtr = ((Channel *) chan)->state->bottomChanPtr->state;
/*
@@ -874,29 +925,30 @@ Tcl_UnregisterChannel(interp, chan)
*/
if (statePtr->refCount <= 0) {
+ /*
+ * Ensure that if there is another buffer, it gets flushed whether or
+ * not we are doing a background flush.
+ */
- /*
- * Ensure that if there is another buffer, it gets flushed
- * whether or not we are doing a background flush.
- */
-
- if ((statePtr->curOutPtr != NULL) &&
- (statePtr->curOutPtr->nextAdded >
- statePtr->curOutPtr->nextRemoved)) {
- statePtr->flags |= BUFFER_READY;
- }
+ if ((statePtr->curOutPtr != NULL) &&
+ IsBufferReady(statePtr->curOutPtr)) {
+ SetFlag(statePtr, BUFFER_READY);
+ }
Tcl_Preserve((ClientData)statePtr);
- if (!(statePtr->flags & BG_FLUSH_SCHEDULED)) {
- /* We don't want to re-enter Tcl_Close */
+ if (!(statePtr->flags & BG_FLUSH_SCHEDULED)) {
+ /*
+ * We don't want to re-enter Tcl_Close().
+ */
+
if (!(statePtr->flags & CHANNEL_CLOSED)) {
if (Tcl_Close(interp, chan) != TCL_OK) {
- statePtr->flags |= CHANNEL_CLOSED;
+ SetFlag(statePtr, CHANNEL_CLOSED);
Tcl_Release((ClientData)statePtr);
return TCL_ERROR;
}
}
- }
- statePtr->flags |= CHANNEL_CLOSED;
+ }
+ SetFlag(statePtr, CHANNEL_CLOSED);
Tcl_Release((ClientData)statePtr);
}
return TCL_OK;
@@ -909,45 +961,42 @@ Tcl_UnregisterChannel(interp, chan)
*
* Deletes the hash entry for a channel associated with an interpreter.
* If the interpreter given as argument is NULL, it only decrements the
- * reference count. Even if the ref count drops to zero, the
- * channel is NOT closed or cleaned up. This allows a channel to
- * be detached from an interpreter and left in the same state it
- * was in when it was originally returned by 'Tcl_OpenFileChannel',
- * for example.
- *
- * This function cannot be used on the standard channels, and
- * will return TCL_ERROR if that is attempted.
- *
- * This function should only be necessary for special purposes
- * in which you need to generate a pristine channel from one
- * that has already been used. All ordinary purposes will almost
- * always want to use Tcl_UnregisterChannel instead.
- *
- * Provided the channel is not attached to any other interpreter,
- * it can then be closed with Tcl_Close, rather than with
- * Tcl_UnregisterChannel.
+ * reference count. Even if the ref count drops to zero, the channel is
+ * NOT closed or cleaned up. This allows a channel to be detached from an
+ * interpreter and left in the same state it was in when it was
+ * originally returned by 'Tcl_OpenFileChannel', for example.
+ *
+ * This function cannot be used on the standard channels, and will return
+ * TCL_ERROR if that is attempted.
+ *
+ * This function should only be necessary for special purposes in which
+ * you need to generate a pristine channel from one that has already been
+ * used. All ordinary purposes will almost always want to use
+ * Tcl_UnregisterChannel instead.
+ *
+ * Provided the channel is not attached to any other interpreter, it can
+ * then be closed with Tcl_Close, rather than with Tcl_UnregisterChannel.
*
* Results:
- * A standard Tcl result. If the channel is not currently registered
- * with the given interpreter, TCL_ERROR is returned, otherwise
- * TCL_OK. However no error messages are left in the interp's result.
+ * A standard Tcl result. If the channel is not currently registered with
+ * the given interpreter, TCL_ERROR is returned, otherwise TCL_OK.
+ * However no error messages are left in the interp's result.
*
* Side effects:
- * Deletes the hash entry for a channel associated with an
- * interpreter.
+ * Deletes the hash entry for a channel associated with an interpreter.
*
*----------------------------------------------------------------------
*/
int
-Tcl_DetachChannel(interp, chan)
- Tcl_Interp *interp; /* Interpreter in which channel is defined. */
- Tcl_Channel chan; /* Channel to delete. */
+Tcl_DetachChannel(
+ Tcl_Interp *interp, /* Interpreter in which channel is defined. */
+ Tcl_Channel chan) /* Channel to delete. */
{
if (Tcl_IsStandardChannel(chan)) {
- return TCL_ERROR;
+ return TCL_ERROR;
}
-
+
return DetachChannel(interp, chan);
}
@@ -958,28 +1007,26 @@ Tcl_DetachChannel(interp, chan)
*
* Deletes the hash entry for a channel associated with an interpreter.
* If the interpreter given as argument is NULL, it only decrements the
- * reference count. Even if the ref count drops to zero, the
- * channel is NOT closed or cleaned up. This allows a channel to
- * be detached from an interpreter and left in the same state it
- * was in when it was originally returned by 'Tcl_OpenFileChannel',
- * for example.
+ * reference count. Even if the ref count drops to zero, the channel is
+ * NOT closed or cleaned up. This allows a channel to be detached from an
+ * interpreter and left in the same state it was in when it was
+ * originally returned by 'Tcl_OpenFileChannel', for example.
*
* Results:
- * A standard Tcl result. If the channel is not currently registered
- * with the given interpreter, TCL_ERROR is returned, otherwise
- * TCL_OK. However no error messages are left in the interp's result.
+ * A standard Tcl result. If the channel is not currently registered with
+ * the given interpreter, TCL_ERROR is returned, otherwise TCL_OK.
+ * However no error messages are left in the interp's result.
*
* Side effects:
- * Deletes the hash entry for a channel associated with an
- * interpreter.
+ * Deletes the hash entry for a channel associated with an interpreter.
*
*----------------------------------------------------------------------
*/
static int
-DetachChannel(interp, chan)
- Tcl_Interp *interp; /* Interpreter in which channel is defined. */
- Tcl_Channel chan; /* Channel to delete. */
+DetachChannel(
+ Tcl_Interp *interp, /* Interpreter in which channel is defined. */
+ Tcl_Channel chan) /* Channel to delete. */
{
Tcl_HashTable *hTblPtr; /* Hash table of channels. */
Tcl_HashEntry *hPtr; /* Search variable. */
@@ -987,43 +1034,44 @@ DetachChannel(interp, chan)
ChannelState *statePtr; /* State of the real channel. */
/*
- * Always (un)register bottom-most channel in the stack. This makes
+ * Always (un)register bottom-most channel in the stack. This makes
* management of the channel list easier because no manipulation is
* necessary during (un)stack operation.
*/
+
chanPtr = ((Channel *) chan)->state->bottomChanPtr;
statePtr = chanPtr->state;
- if (interp != (Tcl_Interp *) NULL) {
- hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL);
- if (hTblPtr == (Tcl_HashTable *) NULL) {
+ if (interp != NULL) {
+ hTblPtr = Tcl_GetAssocData(interp, "tclIO", NULL);
+ if (hTblPtr == NULL) {
return TCL_ERROR;
}
hPtr = Tcl_FindHashEntry(hTblPtr, statePtr->channelName);
- if (hPtr == (Tcl_HashEntry *) NULL) {
+ if (hPtr == NULL) {
return TCL_ERROR;
}
if ((Channel *) Tcl_GetHashValue(hPtr) != chanPtr) {
return TCL_ERROR;
}
Tcl_DeleteHashEntry(hPtr);
+ SetFlag(statePtr, CHANNEL_TAINTED);
/*
- * Remove channel handlers that refer to this interpreter, so that they
- * will not be present if the actual close is delayed and more events
- * happen on the channel. This may occur if the channel is shared
- * between several interpreters, or if the channel has async
+ * Remove channel handlers that refer to this interpreter, so that
+ * they will not be present if the actual close is delayed and more
+ * events happen on the channel. This may occur if the channel is
+ * shared between several interpreters, or if the channel has async
* flushing active.
*/
-
+
CleanupChannelHandlers(interp, chanPtr);
}
statePtr->refCount--;
-
+
return TCL_OK;
}
-
/*
*---------------------------------------------------------------------------
@@ -1035,9 +1083,9 @@ DetachChannel(interp, chan)
* channel-type-specific functions.
*
* Results:
- * A Tcl_Channel or NULL on failure. If failed, interp's result
- * object contains an error message. *modePtr is filled with the
- * modes in which the channel was opened.
+ * A Tcl_Channel or NULL on failure. If failed, interp's result object
+ * contains an error message. *modePtr is filled with the modes in which
+ * the channel was opened.
*
* Side effects:
* None.
@@ -1046,26 +1094,26 @@ DetachChannel(interp, chan)
*/
Tcl_Channel
-Tcl_GetChannel(interp, chanName, modePtr)
- Tcl_Interp *interp; /* Interpreter in which to find or create
- * the channel. */
- CONST char *chanName; /* The name of the channel. */
- int *modePtr; /* Where to store the mode in which the
- * channel was opened? Will contain an ORed
- * combination of TCL_READABLE and
- * TCL_WRITABLE, if non-NULL. */
+Tcl_GetChannel(
+ Tcl_Interp *interp, /* Interpreter in which to find or create the
+ * channel. */
+ const char *chanName, /* The name of the channel. */
+ int *modePtr) /* Where to store the mode in which the
+ * channel was opened? Will contain an ORed
+ * combination of TCL_READABLE and
+ * TCL_WRITABLE, if non-NULL. */
{
Channel *chanPtr; /* The actual channel. */
Tcl_HashTable *hTblPtr; /* Hash table of channels. */
Tcl_HashEntry *hPtr; /* Search variable. */
- CONST char *name; /* Translated name. */
+ const char *name; /* Translated name. */
/*
- * Substitute "stdin", etc. Note that even though we immediately
- * find the channel using Tcl_GetStdChannel, we still need to look
- * it up in the specified interpreter to ensure that it is present
- * in the channel table. Otherwise, safe interpreters would always
- * have access to the standard channels.
+ * Substitute "stdin", etc. Note that even though we immediately find the
+ * channel using Tcl_GetStdChannel, we still need to look it up in the
+ * specified interpreter to ensure that it is present in the channel
+ * table. Otherwise, safe interpreters would always have access to the
+ * standard channels.
*/
name = chanName;
@@ -1085,57 +1133,104 @@ Tcl_GetChannel(interp, chanName, modePtr)
hTblPtr = GetChannelTable(interp);
hPtr = Tcl_FindHashEntry(hTblPtr, name);
- if (hPtr == (Tcl_HashEntry *) NULL) {
- Tcl_AppendResult(interp, "can not find channel named \"",
- chanName, "\"", (char *) NULL);
- return NULL;
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "can not find channel named \"", chanName,
+ "\"", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CHANNEL", chanName, NULL);
+ return NULL;
}
/*
- * Always return bottom-most channel in the stack. This one lives
- * the longest - other channels may go away unnoticed.
- * The other APIs compensate where necessary to retrieve the
- * topmost channel again.
+ * Always return bottom-most channel in the stack. This one lives the
+ * longest - other channels may go away unnoticed. The other APIs
+ * compensate where necessary to retrieve the topmost channel again.
*/
- chanPtr = (Channel *) Tcl_GetHashValue(hPtr);
+
+ chanPtr = Tcl_GetHashValue(hPtr);
chanPtr = chanPtr->state->bottomChanPtr;
if (modePtr != NULL) {
- *modePtr = (chanPtr->state->flags & (TCL_READABLE|TCL_WRITABLE));
+ *modePtr = (chanPtr->state->flags & (TCL_READABLE|TCL_WRITABLE));
}
-
+
return (Tcl_Channel) chanPtr;
}
/*
+ *---------------------------------------------------------------------------
+ *
+ * TclGetChannelFromObj --
+ *
+ * Finds an existing Tcl_Channel structure by name in a given
+ * interpreter. This function is public because it is used by
+ * channel-type-specific functions.
+ *
+ * Results:
+ * A Tcl_Channel or NULL on failure. If failed, interp's result object
+ * contains an error message. *modePtr is filled with the modes in which
+ * the channel was opened.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclGetChannelFromObj(
+ Tcl_Interp *interp, /* Interpreter in which to find or create the
+ * channel. */
+ Tcl_Obj *objPtr,
+ Tcl_Channel *channelPtr,
+ int *modePtr, /* Where to store the mode in which the
+ * channel was opened? Will contain an ORed
+ * combination of TCL_READABLE and
+ * TCL_WRITABLE, if non-NULL. */
+ int flags)
+{
+ ChannelState *statePtr;
+
+ if (SetChannelFromAny(interp, objPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ statePtr = GET_CHANNELSTATE(objPtr);
+ *channelPtr = (Tcl_Channel) (statePtr->bottomChanPtr);
+
+ if (modePtr != NULL) {
+ *modePtr = (statePtr->flags & (TCL_READABLE|TCL_WRITABLE));
+ }
+
+ return TCL_OK;
+}
+
+/*
*----------------------------------------------------------------------
*
* Tcl_CreateChannel --
*
- * Creates a new entry in the hash table for a Tcl_Channel
- * record.
+ * Creates a new entry in the hash table for a Tcl_Channel record.
*
* Results:
* Returns the new Tcl_Channel.
*
* Side effects:
- * Creates a new Tcl_Channel instance and inserts it into the
- * hash table.
+ * Creates a new Tcl_Channel instance and inserts it into the hash table.
*
*----------------------------------------------------------------------
*/
Tcl_Channel
-Tcl_CreateChannel(typePtr, chanName, instanceData, mask)
- Tcl_ChannelType *typePtr; /* The channel type record. */
- CONST char *chanName; /* Name of channel to record. */
- ClientData instanceData; /* Instance specific data. */
- int mask; /* TCL_READABLE & TCL_WRITABLE to indicate
- * if the channel is readable, writable. */
+Tcl_CreateChannel(
+ Tcl_ChannelType *typePtr, /* The channel type record. */
+ const char *chanName, /* Name of channel to record. */
+ ClientData instanceData, /* Instance specific data. */
+ int mask) /* TCL_READABLE & TCL_WRITABLE to indicate if
+ * the channel is readable, writable. */
{
Channel *chanPtr; /* The channel structure newly created. */
- ChannelState *statePtr; /* The stack-level independent state info
- * for the channel. */
- CONST char *name;
+ ChannelState *statePtr; /* The stack-level independent state info for
+ * the channel. */
+ const char *name;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
/*
@@ -1143,59 +1238,67 @@ Tcl_CreateChannel(typePtr, chanName, instanceData, mask)
* 8.3.2+, we have to make sure that our assumption that the structure
* remains a binary compatible size is true.
*
- * If this assertion fails on some system, then it can be removed
- * only if the user recompiles code with older channel drivers in
- * the new system as well.
+ * If this assertion fails on some system, then it can be removed only if
+ * the user recompiles code with older channel drivers in the new system
+ * as well.
*/
assert(sizeof(Tcl_ChannelTypeVersion) == sizeof(Tcl_DriverBlockModeProc*));
/*
- * JH: We could subsequently memset these to 0 to avoid the
- * numerous assignments to 0/NULL below.
+ * JH: We could subsequently memset these to 0 to avoid the numerous
+ * assignments to 0/NULL below.
*/
- chanPtr = (Channel *) ckalloc((unsigned) sizeof(Channel));
- statePtr = (ChannelState *) ckalloc((unsigned) sizeof(ChannelState));
+
+ chanPtr = (Channel *) ckalloc(sizeof(Channel));
+ statePtr = (ChannelState *) ckalloc(sizeof(ChannelState));
chanPtr->state = statePtr;
- chanPtr->instanceData = instanceData;
- chanPtr->typePtr = typePtr;
+ chanPtr->instanceData = instanceData;
+ chanPtr->typePtr = typePtr;
/*
* Set all the bits that are part of the stack-independent state
* information for the channel.
*/
- if (chanName != (char *) NULL) {
+ if (chanName != NULL) {
char *tmp = ckalloc((unsigned) (strlen(chanName) + 1));
- statePtr->channelName = tmp;
- strcpy(tmp, chanName);
+
+ statePtr->channelName = tmp;
+ strcpy(tmp, chanName);
} else {
- panic("Tcl_CreateChannel: NULL channel name");
+ Tcl_Panic("Tcl_CreateChannel: NULL channel name");
}
- statePtr->flags = mask;
+ statePtr->flags = mask;
/*
* Set the channel to system default encoding.
+ *
+ * Note the strange bit of protection taking place here. If the system
+ * encoding name is reported back as "binary", something weird is
+ * happening. Tcl provides no "binary" encoding, so someone else has
+ * provided one. We ignore it so as not to interfere with the "magic"
+ * interpretation that Tcl_Channels give to the "-encoding binary" option.
*/
statePtr->encoding = NULL;
name = Tcl_GetEncodingName(NULL);
if (strcmp(name, "binary") != 0) {
- statePtr->encoding = Tcl_GetEncoding(NULL, name);
+ statePtr->encoding = Tcl_GetEncoding(NULL, name);
}
- statePtr->inputEncodingState = NULL;
- statePtr->inputEncodingFlags = TCL_ENCODING_START;
- statePtr->outputEncodingState = NULL;
- statePtr->outputEncodingFlags = TCL_ENCODING_START;
+ statePtr->inputEncodingState = NULL;
+ statePtr->inputEncodingFlags = TCL_ENCODING_START;
+ statePtr->outputEncodingState = NULL;
+ statePtr->outputEncodingFlags = TCL_ENCODING_START;
/*
- * Set the channel up initially in AUTO input translation mode to
- * accept "\n", "\r" and "\r\n". Output translation mode is set to
- * a platform specific default value. The eofChar is set to 0 for both
- * input and output, so that Tcl does not look for an in-file EOF
- * indicator (e.g. ^Z) and does not append an EOF indicator to files.
+ * Set the channel up initially in AUTO input translation mode to accept
+ * "\n", "\r" and "\r\n". Output translation mode is set to a platform
+ * specific default value. The eofChar is set to 0 for both input and
+ * output, so that Tcl does not look for an in-file EOF indicator (e.g.
+ * ^Z) and does not append an EOF indicator to files.
*/
statePtr->inputTranslation = TCL_TRANSLATE_AUTO;
@@ -1205,16 +1308,16 @@ Tcl_CreateChannel(typePtr, chanName, instanceData, mask)
statePtr->unreportedError = 0;
statePtr->refCount = 0;
- statePtr->closeCbPtr = (CloseCallback *) NULL;
- statePtr->curOutPtr = (ChannelBuffer *) NULL;
- statePtr->outQueueHead = (ChannelBuffer *) NULL;
- statePtr->outQueueTail = (ChannelBuffer *) NULL;
- statePtr->saveInBufPtr = (ChannelBuffer *) NULL;
- statePtr->inQueueHead = (ChannelBuffer *) NULL;
- statePtr->inQueueTail = (ChannelBuffer *) NULL;
- statePtr->chPtr = (ChannelHandler *) NULL;
+ statePtr->closeCbPtr = NULL;
+ statePtr->curOutPtr = NULL;
+ statePtr->outQueueHead = NULL;
+ statePtr->outQueueTail = NULL;
+ statePtr->saveInBufPtr = NULL;
+ statePtr->inQueueHead = NULL;
+ statePtr->inQueueTail = NULL;
+ statePtr->chPtr = NULL;
statePtr->interestMask = 0;
- statePtr->scriptRecordPtr = (EventScriptRecord *) NULL;
+ statePtr->scriptRecordPtr = NULL;
statePtr->bufSize = CHANNELBUFFER_DEFAULT_SIZE;
statePtr->timer = NULL;
statePtr->csPtrR = NULL;
@@ -1223,58 +1326,64 @@ Tcl_CreateChannel(typePtr, chanName, instanceData, mask)
statePtr->outputStage = NULL;
if ((statePtr->encoding != NULL) && (statePtr->flags & TCL_WRITABLE)) {
statePtr->outputStage = (char *)
- ckalloc((unsigned) (statePtr->bufSize + 2));
+ ckalloc((unsigned) (statePtr->bufSize + 2));
}
/*
- * As we are creating the channel, it is obviously the top for now
+ * As we are creating the channel, it is obviously the top for now.
*/
+
statePtr->topChanPtr = chanPtr;
statePtr->bottomChanPtr = chanPtr;
- chanPtr->downChanPtr = (Channel *) NULL;
- chanPtr->upChanPtr = (Channel *) NULL;
- chanPtr->inQueueHead = (ChannelBuffer*) NULL;
- chanPtr->inQueueTail = (ChannelBuffer*) NULL;
+ chanPtr->downChanPtr = NULL;
+ chanPtr->upChanPtr = NULL;
+ chanPtr->inQueueHead = NULL;
+ chanPtr->inQueueTail = NULL;
+
+ /*
+ * TIP #219, Tcl Channel Reflection API
+ */
+
+ statePtr->chanMsg = NULL;
+ statePtr->unreportedMsg = NULL;
/*
* Link the channel into the list of all channels; create an on-exit
- * handler if there is not one already, to close off all the channels
- * in the list on exit.
+ * handler if there is not one already, to close off all the channels in
+ * the list on exit.
*
* JH: Could call Tcl_SpliceChannel, but need to avoid NULL check.
*
* TIP #218.
* AK: Just initialize the field to NULL before invoking Tcl_SpliceChannel
- * We need Tcl_SpliceChannel, for the threadAction calls.
- * There is no real reason to duplicate all of this.
+ * We need Tcl_SpliceChannel, for the threadAction calls. There is no
+ * real reason to duplicate all of this.
* NOTE: All drivers using thread actions now have to perform their TSD
- * manipulation only in their thread action proc. Doing it when
- * creating their instance structures will collide with the thread
- * action activity and lead to damaged lists.
+ * manipulation only in their thread action proc. Doing it when
+ * creating their instance structures will collide with the thread
+ * action activity and lead to damaged lists.
*/
- statePtr->nextCSPtr = (ChannelState *) NULL;
- Tcl_SpliceChannel ((Tcl_Channel) chanPtr);
+ statePtr->nextCSPtr = NULL;
+ SpliceChannel((Tcl_Channel) chanPtr);
/*
- * Install this channel in the first empty standard channel slot, if
- * the channel was previously closed explicitly.
+ * Install this channel in the first empty standard channel slot, if the
+ * channel was previously closed explicitly.
*/
-#if TCL_INHERIT_STD_CHANNELS
- if ((tsdPtr->stdinChannel == NULL) &&
- (tsdPtr->stdinInitialized == 1)) {
+
+ if ((tsdPtr->stdinChannel == NULL) && (tsdPtr->stdinInitialized == 1)) {
Tcl_SetStdChannel((Tcl_Channel) chanPtr, TCL_STDIN);
- Tcl_RegisterChannel((Tcl_Interp *) NULL, (Tcl_Channel) chanPtr);
+ Tcl_RegisterChannel(NULL, (Tcl_Channel) chanPtr);
} else if ((tsdPtr->stdoutChannel == NULL) &&
(tsdPtr->stdoutInitialized == 1)) {
Tcl_SetStdChannel((Tcl_Channel) chanPtr, TCL_STDOUT);
- Tcl_RegisterChannel((Tcl_Interp *) NULL, (Tcl_Channel) chanPtr);
+ Tcl_RegisterChannel(NULL, (Tcl_Channel) chanPtr);
} else if ((tsdPtr->stderrChannel == NULL) &&
(tsdPtr->stderrInitialized == 1)) {
Tcl_SetStdChannel((Tcl_Channel) chanPtr, TCL_STDERR);
- Tcl_RegisterChannel((Tcl_Interp *) NULL, (Tcl_Channel) chanPtr);
+ Tcl_RegisterChannel(NULL, (Tcl_Channel) chanPtr);
}
-#endif
return (Tcl_Channel) chanPtr;
}
@@ -1283,53 +1392,52 @@ Tcl_CreateChannel(typePtr, chanName, instanceData, mask)
*
* Tcl_StackChannel --
*
- * Replaces an entry in the hash table for a Tcl_Channel
- * record. The replacement is a new channel with same name,
- * it supercedes the replaced channel. Input and output of
- * the superceded channel is now going through the newly
- * created channel and allows the arbitrary filtering/manipulation
- * of the dataflow.
+ * Replaces an entry in the hash table for a Tcl_Channel record. The
+ * replacement is a new channel with same name, it supercedes the
+ * replaced channel. Input and output of the superceded channel is now
+ * going through the newly created channel and allows the arbitrary
+ * filtering/manipulation of the dataflow.
*
- * Andreas Kupries <a.kupries@westend.com>, 12/13/1998
- * "Trf-Patch for filtering channels"
+ * Andreas Kupries <a.kupries@westend.com>, 12/13/1998 "Trf-Patch for
+ * filtering channels"
*
* Results:
- * Returns the new Tcl_Channel, which actually contains the
- * saved information about prevChan.
+ * Returns the new Tcl_Channel, which actually contains the saved
+ * information about prevChan.
*
* Side effects:
- * A new channel structure is allocated and linked below
- * the existing channel. The channel operations and client
- * data of the existing channel are copied down to the newly
- * created channel, and the current channel has its operations
- * replaced by the new typePtr.
+ * A new channel structure is allocated and linked below the existing
+ * channel. The channel operations and client data of the existing
+ * channel are copied down to the newly created channel, and the current
+ * channel has its operations replaced by the new typePtr.
*
*----------------------------------------------------------------------
*/
Tcl_Channel
-Tcl_StackChannel(interp, typePtr, instanceData, mask, prevChan)
- Tcl_Interp *interp; /* The interpreter we are working in */
- Tcl_ChannelType *typePtr; /* The channel type record for the new
- * channel. */
- ClientData instanceData; /* Instance specific data for the new
- * channel. */
- int mask; /* TCL_READABLE & TCL_WRITABLE to indicate
- * if the channel is readable, writable. */
- Tcl_Channel prevChan; /* The channel structure to replace */
-{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- Channel *chanPtr, *prevChanPtr;
- ChannelState *statePtr;
-
- /*
- * Find the given channel in the list of all channels.
- * If we don't find it, then it was never registered correctly.
+Tcl_StackChannel(
+ Tcl_Interp *interp, /* The interpreter we are working in */
+ Tcl_ChannelType *typePtr, /* The channel type record for the new
+ * channel. */
+ ClientData instanceData, /* Instance specific data for the new
+ * channel. */
+ int mask, /* TCL_READABLE & TCL_WRITABLE to indicate if
+ * the channel is readable, writable. */
+ Tcl_Channel prevChan) /* The channel structure to replace */
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ Channel *chanPtr, *prevChanPtr;
+ ChannelState *statePtr;
+ Tcl_DriverThreadActionProc *threadActionProc;
+
+ /*
+ * Find the given channel (prevChan) in the list of all channels. If we do
+ * not find it, then it was never registered correctly.
*
* This operation should occur at the top of a channel stack.
*/
- statePtr = (ChannelState *) tsdPtr->firstCSPtr;
+ statePtr = (ChannelState *) tsdPtr->firstCSPtr;
prevChanPtr = ((Channel *) prevChan)->state->topChanPtr;
while ((statePtr != NULL) && (statePtr->topChanPtr != prevChanPtr)) {
@@ -1339,21 +1447,21 @@ Tcl_StackChannel(interp, typePtr, instanceData, mask, prevChan)
if (statePtr == NULL) {
if (interp) {
Tcl_AppendResult(interp, "couldn't find state for channel \"",
- Tcl_GetChannelName(prevChan), "\"", (char *) NULL);
+ Tcl_GetChannelName(prevChan), "\"", NULL);
}
- return (Tcl_Channel) NULL;
+ return NULL;
}
/*
- * Here we check if the given "mask" matches the "flags"
- * of the already existing channel.
+ * Here we check if the given "mask" matches the "flags" of the already
+ * existing channel.
*
* | - | R | W | RW |
* --+---+---+---+----+ <=> 0 != (chan->mask & prevChan->mask)
* - | | | | |
- * R | | + | | + | The superceding channel is allowed to
- * W | | | + | + | restrict the capabilities of the
- * RW| | + | + | + | superceded one !
+ * R | | + | | + | The superceding channel is allowed to restrict
+ * W | | | + | + | the capabilities of the superceded one!
+ * RW| | + | + | + |
* --+---+---+---+----+
*/
@@ -1361,16 +1469,16 @@ Tcl_StackChannel(interp, typePtr, instanceData, mask, prevChan)
if (interp) {
Tcl_AppendResult(interp,
"reading and writing both disallowed for channel \"",
- Tcl_GetChannelName(prevChan), "\"", (char *) NULL);
+ Tcl_GetChannelName(prevChan), "\"", NULL);
}
- return (Tcl_Channel) NULL;
+ return NULL;
}
/*
- * Flush the buffers. This ensures that any data still in them
- * at this time is not handled by the new transformation. Restrict
- * this to writable channels. Take care to hide a possible bg-copy
- * in progress from Tcl_Flush and the CheckForChannelErrors inside.
+ * Flush the buffers. This ensures that any data still in them at this
+ * time is not handled by the new transformation. Restrict this to
+ * writable channels. Take care to hide a possible bg-copy in progress
+ * from Tcl_Flush and the CheckForChannelErrors inside.
*/
if ((mask & TCL_WRITABLE) != 0) {
@@ -1378,63 +1486,62 @@ Tcl_StackChannel(interp, typePtr, instanceData, mask, prevChan)
CopyState *csPtrW;
csPtrR = statePtr->csPtrR;
- statePtr->csPtrR = (CopyState*) NULL;
+ statePtr->csPtrR = NULL;
csPtrW = statePtr->csPtrW;
- statePtr->csPtrW = (CopyState*) NULL;
+ statePtr->csPtrW = NULL;
if (Tcl_Flush((Tcl_Channel) prevChanPtr) != TCL_OK) {
- statePtr->csPtrR = csPtrR;
+ statePtr->csPtrR = csPtrR;
statePtr->csPtrW = csPtrW;
if (interp) {
Tcl_AppendResult(interp, "could not flush channel \"",
- Tcl_GetChannelName(prevChan), "\"", (char *) NULL);
+ Tcl_GetChannelName(prevChan), "\"", NULL);
}
- return (Tcl_Channel) NULL;
+ return NULL;
}
- statePtr->csPtrR = csPtrR;
+ statePtr->csPtrR = csPtrR;
statePtr->csPtrW = csPtrW;
}
+
/*
- * Discard any input in the buffers. They are not yet read by the
- * user of the channel, so they have to go through the new
- * transformation before reading. As the buffers contain the
- * untransformed form their contents are not only useless but actually
- * distorts our view of the system.
+ * Discard any input in the buffers. They are not yet read by the user of
+ * the channel, so they have to go through the new transformation before
+ * reading. As the buffers contain the untransformed form their contents
+ * are not only useless but actually distorts our view of the system.
*
- * To preserve the information without having to read them again and
- * to avoid problems with the location in the channel (seeking might
- * be impossible) we move the buffers from the common state structure
- * into the channel itself. We use the buffers in the channel below
- * the new transformation to hold the data. In the future this allows
- * us to write transformations which pre-read data and push the unused
- * part back when they are going away.
+ * To preserve the information without having to read them again and to
+ * avoid problems with the location in the channel (seeking might be
+ * impossible) we move the buffers from the common state structure into
+ * the channel itself. We use the buffers in the channel below the new
+ * transformation to hold the data. In the future this allows us to write
+ * transformations which pre-read data and push the unused part back when
+ * they are going away.
*/
- if (((mask & TCL_READABLE) != 0) &&
- (statePtr->inQueueHead != (ChannelBuffer*) NULL)) {
- /*
- * Remark: It is possible that the channel buffers contain data from
- * some earlier push-backs.
- */
+ if (((mask & TCL_READABLE) != 0) && (statePtr->inQueueHead != NULL)) {
+ /*
+ * Remark: It is possible that the channel buffers contain data from
+ * some earlier push-backs.
+ */
- statePtr->inQueueTail->nextPtr = prevChanPtr->inQueueHead;
- prevChanPtr->inQueueHead = statePtr->inQueueHead;
+ statePtr->inQueueTail->nextPtr = prevChanPtr->inQueueHead;
+ prevChanPtr->inQueueHead = statePtr->inQueueHead;
- if (prevChanPtr->inQueueTail == (ChannelBuffer*) NULL) {
- prevChanPtr->inQueueTail = statePtr->inQueueTail;
- }
+ if (prevChanPtr->inQueueTail == NULL) {
+ prevChanPtr->inQueueTail = statePtr->inQueueTail;
+ }
- statePtr->inQueueHead = (ChannelBuffer*) NULL;
- statePtr->inQueueTail = (ChannelBuffer*) NULL;
+ statePtr->inQueueHead = NULL;
+ statePtr->inQueueTail = NULL;
}
- chanPtr = (Channel *) ckalloc((unsigned) sizeof(Channel));
+ chanPtr = (Channel *) ckalloc(sizeof(Channel));
/*
- * Save some of the current state into the new structure,
- * reinitialize the parts which will stay with the transformation.
+ * Save some of the current state into the new structure, reinitialize the
+ * parts which will stay with the transformation.
*
* Remarks:
*/
@@ -1443,9 +1550,9 @@ Tcl_StackChannel(interp, typePtr, instanceData, mask, prevChan)
chanPtr->instanceData = instanceData;
chanPtr->typePtr = typePtr;
chanPtr->downChanPtr = prevChanPtr;
- chanPtr->upChanPtr = (Channel *) NULL;
- chanPtr->inQueueHead = (ChannelBuffer*) NULL;
- chanPtr->inQueueTail = (ChannelBuffer*) NULL;
+ chanPtr->upChanPtr = NULL;
+ chanPtr->inQueueHead = NULL;
+ chanPtr->inQueueTail = NULL;
/*
* Place new block at the head of a possibly existing list of previously
@@ -1455,6 +1562,22 @@ Tcl_StackChannel(interp, typePtr, instanceData, mask, prevChan)
prevChanPtr->upChanPtr = chanPtr;
statePtr->topChanPtr = chanPtr;
+ /*
+ * TIP #218, Channel Thread Actions.
+ *
+ * We call the thread actions for the new channel directly. We _cannot_
+ * use SpliceChannel, because the (thread-)global list of all channels
+ * always contains the _ChannelState_ for a stack of channels, not the
+ * individual channels. And SpliceChannel would not only call the thread
+ * actions, but also add the shared ChannelState to this list a second
+ * time, mangling it.
+ */
+
+ threadActionProc = Tcl_ChannelThreadActionProc(chanPtr->typePtr);
+ if (threadActionProc != NULL) {
+ (*threadActionProc)(chanPtr->instanceData, TCL_CHANNEL_THREAD_INSERT);
+ }
+
return (Tcl_Channel) chanPtr;
}
@@ -1463,27 +1586,28 @@ Tcl_StackChannel(interp, typePtr, instanceData, mask, prevChan)
*
* Tcl_UnstackChannel --
*
- * Unstacks an entry in the hash table for a Tcl_Channel
- * record. This is the reverse to 'Tcl_StackChannel'.
+ * Unstacks an entry in the hash table for a Tcl_Channel record. This is
+ * the reverse to 'Tcl_StackChannel'.
*
* Results:
* A standard Tcl result.
*
* Side effects:
- * If TCL_ERROR is returned, the posix error code will be set
- * with Tcl_SetErrno.
+ * If TCL_ERROR is returned, the posix error code will be set with
+ * Tcl_SetErrno. May leave a message in interp result as well.
*
*----------------------------------------------------------------------
*/
int
-Tcl_UnstackChannel (interp, chan)
- Tcl_Interp *interp; /* The interpreter we are working in */
- Tcl_Channel chan; /* The channel to unstack */
+Tcl_UnstackChannel(
+ Tcl_Interp *interp, /* The interpreter we are working in */
+ Tcl_Channel chan) /* The channel to unstack */
{
- Channel *chanPtr = (Channel *) chan;
+ Channel *chanPtr = (Channel *) chan;
ChannelState *statePtr = chanPtr->state;
int result = 0;
+ Tcl_DriverThreadActionProc *threadActionProc;
/*
* This operation should occur at the top of a channel stack.
@@ -1491,20 +1615,21 @@ Tcl_UnstackChannel (interp, chan)
chanPtr = statePtr->topChanPtr;
- if (chanPtr->downChanPtr != (Channel *) NULL) {
- /*
+ if (chanPtr->downChanPtr != NULL) {
+ /*
* Instead of manipulating the per-thread / per-interp list/hashtable
* of registered channels we wind down the state of the transformation,
* and then restore the state of underlying channel into the old
* structure.
*/
+
Channel *downChanPtr = chanPtr->downChanPtr;
/*
- * Flush the buffers. This ensures that any data still in them
- * at this time _is_ handled by the transformation we are unstacking
- * right now. Restrict this to writable channels. Take care to hide
- * a possible bg-copy in progress from Tcl_Flush and the
+ * Flush the buffers. This ensures that any data still in them at this
+ * time _is_ handled by the transformation we are unstacking right
+ * now. Restrict this to writable channels. Take care to hide a
+ * possible bg-copy in progress from Tcl_Flush and the
* CheckForChannelErrors inside.
*/
@@ -1513,18 +1638,27 @@ Tcl_UnstackChannel (interp, chan)
CopyState *csPtrW;
csPtrR = statePtr->csPtrR;
- statePtr->csPtrR = (CopyState*) NULL;
+ statePtr->csPtrR = NULL;
csPtrW = statePtr->csPtrW;
- statePtr->csPtrW = (CopyState*) NULL;
+ statePtr->csPtrW = NULL;
if (Tcl_Flush((Tcl_Channel) chanPtr) != TCL_OK) {
- statePtr->csPtrR = csPtrR;
+ statePtr->csPtrR = csPtrR;
statePtr->csPtrW = csPtrW;
- if (interp) {
+
+ /*
+ * TIP #219, Tcl Channel Reflection API.
+ * Move error messages put by the driver into the chan/ip
+ * bypass area into the regular interpreter result. Fall back
+ * to the regular message if nothing was found in the
+ * bypasses.
+ */
+
+ if (!TclChanCaughtErrorBypass(interp, chan) && interp) {
Tcl_AppendResult(interp, "could not flush channel \"",
Tcl_GetChannelName((Tcl_Channel) chanPtr), "\"",
- (char *) NULL);
+ NULL);
}
return TCL_ERROR;
}
@@ -1534,42 +1668,60 @@ Tcl_UnstackChannel (interp, chan)
}
/*
- * Anything in the input queue and the push-back buffers of
- * the transformation going away is transformed data, but not
- * yet read. As unstacking means that the caller does not want
- * to see transformed data any more we have to discard these
- * bytes. To avoid writing an analogue to 'DiscardInputQueued'
- * we move the information in the push back buffers to the
- * input queue and then call 'DiscardInputQueued' on that.
+ * Anything in the input queue and the push-back buffers of the
+ * transformation going away is transformed data, but not yet read. As
+ * unstacking means that the caller does not want to see transformed
+ * data any more we have to discard these bytes. To avoid writing an
+ * analogue to 'DiscardInputQueued' we move the information in the
+ * push back buffers to the input queue and then call
+ * 'DiscardInputQueued' on that.
*/
- if (((statePtr->flags & TCL_READABLE) != 0) &&
- ((statePtr->inQueueHead != (ChannelBuffer*) NULL) ||
- (chanPtr->inQueueHead != (ChannelBuffer*) NULL))) {
+ if ((((statePtr->flags & TCL_READABLE) != 0)) &&
+ ((statePtr->inQueueHead != NULL) ||
+ (chanPtr->inQueueHead != NULL))) {
- if ((statePtr->inQueueHead != (ChannelBuffer*) NULL) &&
- (chanPtr->inQueueHead != (ChannelBuffer*) NULL)) {
- statePtr->inQueueTail->nextPtr = chanPtr->inQueueHead;
+ if ((statePtr->inQueueHead != NULL) &&
+ (chanPtr->inQueueHead != NULL)) {
+ statePtr->inQueueTail->nextPtr = chanPtr->inQueueHead;
statePtr->inQueueTail = chanPtr->inQueueTail;
- statePtr->inQueueHead = statePtr->inQueueTail;
+ statePtr->inQueueHead = statePtr->inQueueTail;
- } else if (chanPtr->inQueueHead != (ChannelBuffer*) NULL) {
- statePtr->inQueueHead = chanPtr->inQueueHead;
+ } else if (chanPtr->inQueueHead != NULL) {
+ statePtr->inQueueHead = chanPtr->inQueueHead;
statePtr->inQueueTail = chanPtr->inQueueTail;
}
- chanPtr->inQueueHead = (ChannelBuffer*) NULL;
- chanPtr->inQueueTail = (ChannelBuffer*) NULL;
+ chanPtr->inQueueHead = NULL;
+ chanPtr->inQueueTail = NULL;
- DiscardInputQueued (statePtr, 0);
+ DiscardInputQueued(statePtr, 0);
}
- statePtr->topChanPtr = downChanPtr;
- downChanPtr->upChanPtr = (Channel *) NULL;
+ /*
+ * TIP #218, Channel Thread Actions.
+ *
+ * We call the thread actions for the new channel directly. We
+ * _cannot_ use CutChannel, because the (thread-)global list of all
+ * channels always contains the _ChannelState_ for a stack of
+ * channels, not the individual channels. And SpliceChannel would not
+ * only call the thread actions, but also remove the shared
+ * ChannelState from this list despite there being more channels for
+ * the state which are still active.
+ */
+
+ threadActionProc = Tcl_ChannelThreadActionProc(chanPtr->typePtr);
+ if (threadActionProc != NULL) {
+ (*threadActionProc)(chanPtr->instanceData,
+ TCL_CHANNEL_THREAD_REMOVE);
+ }
+
+ statePtr->topChanPtr = downChanPtr;
+ downChanPtr->upChanPtr = NULL;
/*
* Leave this link intact for closeproc
- * chanPtr->downChanPtr = (Channel *) NULL;
+ * chanPtr->downChanPtr = NULL;
*/
/*
@@ -1584,28 +1736,51 @@ Tcl_UnstackChannel (interp, chan)
interp, 0);
}
- chanPtr->typePtr = NULL;
+ chanPtr->typePtr = NULL;
+
/*
* AK: Tcl_NotifyChannel may hold a reference to this block of memory
*/
- Tcl_EventuallyFree((ClientData) chanPtr, TCL_DYNAMIC);
+
+ Tcl_EventuallyFree(chanPtr, TCL_DYNAMIC);
UpdateInterest(downChanPtr);
if (result != 0) {
Tcl_SetErrno(result);
+
+ /*
+ * TIP #219, Tcl Channel Reflection API.
+ * Move error messages put by the driver into the chan/ip bypass
+ * area into the regular interpreter result.
+ */
+
+ TclChanCaughtErrorBypass(interp, chan);
return TCL_ERROR;
}
} else {
- /*
- * This channel does not cover another one.
- * Simply do a close, if necessary.
+ /*
+ * This channel does not cover another one. Simply do a close, if
+ * necessary.
*/
- if (statePtr->refCount <= 0) {
- if (Tcl_Close(interp, chan) != TCL_OK) {
- return TCL_ERROR;
- }
+ if (statePtr->refCount <= 0) {
+ if (Tcl_Close(interp, chan) != TCL_OK) {
+ /*
+ * TIP #219, Tcl Channel Reflection API.
+ * "TclChanCaughtErrorBypass" is not required here, it was
+ * done already by "Tcl_Close".
+ */
+
+ return TCL_ERROR;
+ }
}
+
+ /*
+ * TIP #218, Channel Thread Actions.
+ * Not required in this branch, this is done by Tcl_Close. If
+ * Tcl_Close is not called then the ChannelState is still active in
+ * the thread and no action has to be taken either.
+ */
}
return TCL_OK;
@@ -1619,9 +1794,9 @@ Tcl_UnstackChannel (interp, chan)
* Determines whether the specified channel is stacked upon another.
*
* Results:
- * NULL if the channel is not stacked upon another one, or a reference
- * to the channel it is stacked upon. This reference can be used in
- * queries, but modification is not allowed.
+ * NULL if the channel is not stacked upon another one, or a reference to
+ * the channel it is stacked upon. This reference can be used in queries,
+ * but modification is not allowed.
*
* Side effects:
* None.
@@ -1630,10 +1805,11 @@ Tcl_UnstackChannel (interp, chan)
*/
Tcl_Channel
-Tcl_GetStackedChannel(chan)
- Tcl_Channel chan;
+Tcl_GetStackedChannel(
+ Tcl_Channel chan)
{
- Channel *chanPtr = (Channel *) chan; /* The actual channel. */
+ Channel *chanPtr = (Channel *) chan;
+ /* The actual channel. */
return (Tcl_Channel) chanPtr->downChanPtr;
}
@@ -1646,9 +1822,9 @@ Tcl_GetStackedChannel(chan)
* Returns the top channel of a channel stack.
*
* Results:
- * NULL if the channel is not stacked upon another one, or a reference
- * to the channel it is stacked upon. This reference can be used in
- * queries, but modification is not allowed.
+ * NULL if the channel is not stacked upon another one, or a reference to
+ * the channel it is stacked upon. This reference can be used in queries,
+ * but modification is not allowed.
*
* Side effects:
* None.
@@ -1657,10 +1833,11 @@ Tcl_GetStackedChannel(chan)
*/
Tcl_Channel
-Tcl_GetTopChannel(chan)
- Tcl_Channel chan;
+Tcl_GetTopChannel(
+ Tcl_Channel chan)
{
- Channel *chanPtr = (Channel *) chan; /* The actual channel. */
+ Channel *chanPtr = (Channel *) chan;
+ /* The actual channel. */
return (Tcl_Channel) chanPtr->state->topChanPtr;
}
@@ -1682,10 +1859,11 @@ Tcl_GetTopChannel(chan)
*/
ClientData
-Tcl_GetChannelInstanceData(chan)
- Tcl_Channel chan; /* Channel for which to return client data. */
+Tcl_GetChannelInstanceData(
+ Tcl_Channel chan) /* Channel for which to return client data. */
{
- Channel *chanPtr = (Channel *) chan; /* The actual channel. */
+ Channel *chanPtr = (Channel *) chan;
+ /* The actual channel. */
return chanPtr->instanceData;
}
@@ -1695,8 +1873,7 @@ Tcl_GetChannelInstanceData(chan)
*
* Tcl_GetChannelThread --
*
- * Given a channel structure, returns the thread managing it.
- * TIP #10
+ * Given a channel structure, returns the thread managing it. TIP #10
*
* Results:
* Returns the id of the thread managing the channel.
@@ -1708,10 +1885,12 @@ Tcl_GetChannelInstanceData(chan)
*/
Tcl_ThreadId
-Tcl_GetChannelThread(chan)
- Tcl_Channel chan; /* The channel to return managing thread for. */
+Tcl_GetChannelThread(
+ Tcl_Channel chan) /* The channel to return the managing thread
+ * for. */
{
- Channel *chanPtr = (Channel *) chan; /* The actual channel. */
+ Channel *chanPtr = (Channel *) chan;
+ /* The actual channel. */
return chanPtr->state->managingThread;
}
@@ -1733,10 +1912,11 @@ Tcl_GetChannelThread(chan)
*/
Tcl_ChannelType *
-Tcl_GetChannelType(chan)
- Tcl_Channel chan; /* The channel to return type for. */
+Tcl_GetChannelType(
+ Tcl_Channel chan) /* The channel to return type for. */
{
- Channel *chanPtr = (Channel *) chan; /* The actual channel. */
+ Channel *chanPtr = (Channel *) chan;
+ /* The actual channel. */
return chanPtr->typePtr;
}
@@ -1746,8 +1926,8 @@ Tcl_GetChannelType(chan)
*
* Tcl_GetChannelMode --
*
- * Computes a mask indicating whether the channel is open for
- * reading and writing.
+ * Computes a mask indicating whether the channel is open for reading and
+ * writing.
*
* Results:
* An OR-ed combination of TCL_READABLE and TCL_WRITABLE.
@@ -1759,12 +1939,12 @@ Tcl_GetChannelType(chan)
*/
int
-Tcl_GetChannelMode(chan)
- Tcl_Channel chan; /* The channel for which the mode is
- * being computed. */
+Tcl_GetChannelMode(
+ Tcl_Channel chan) /* The channel for which the mode is being
+ * computed. */
{
ChannelState *statePtr = ((Channel *) chan)->state;
- /* State of actual channel. */
+ /* State of actual channel. */
return (statePtr->flags & (TCL_READABLE | TCL_WRITABLE));
}
@@ -1777,9 +1957,8 @@ Tcl_GetChannelMode(chan)
* Returns the string identifying the channel name.
*
* Results:
- * The string containing the channel name. This memory is
- * owned by the generic layer and should not be modified by
- * the caller.
+ * The string containing the channel name. This memory is owned by the
+ * generic layer and should not be modified by the caller.
*
* Side effects:
* None.
@@ -1787,9 +1966,9 @@ Tcl_GetChannelMode(chan)
*----------------------------------------------------------------------
*/
-CONST char *
-Tcl_GetChannelName(chan)
- Tcl_Channel chan; /* The channel for which to return the name. */
+const char *
+Tcl_GetChannelName(
+ Tcl_Channel chan) /* The channel for which to return the name. */
{
ChannelState *statePtr; /* State of actual channel. */
@@ -1815,16 +1994,24 @@ Tcl_GetChannelName(chan)
*/
int
-Tcl_GetChannelHandle(chan, direction, handlePtr)
- Tcl_Channel chan; /* The channel to get file from. */
- int direction; /* TCL_WRITABLE or TCL_READABLE. */
- ClientData *handlePtr; /* Where to store handle */
+Tcl_GetChannelHandle(
+ Tcl_Channel chan, /* The channel to get file from. */
+ int direction, /* TCL_WRITABLE or TCL_READABLE. */
+ ClientData *handlePtr) /* Where to store handle */
{
Channel *chanPtr; /* The actual channel. */
ClientData handle;
int result;
chanPtr = ((Channel *) chan)->state->bottomChanPtr;
+ if (!chanPtr->typePtr->getHandleProc) {
+ Tcl_Obj* err;
+ TclNewLiteralStringObj(err, "channel \"");
+ Tcl_AppendToObj(err, Tcl_GetChannelName(chan), -1);
+ Tcl_AppendToObj(err, "\" does not support OS handles", -1);
+ Tcl_SetChannelError (chan,err);
+ return TCL_ERROR;
+ }
result = (chanPtr->typePtr->getHandleProc)(chanPtr->instanceData,
direction, &handle);
if (handlePtr) {
@@ -1838,16 +2025,15 @@ Tcl_GetChannelHandle(chan, direction, handlePtr)
*
* AllocChannelBuffer --
*
- * A channel buffer has BUFFER_PADDING bytes extra at beginning to
- * hold any bytes of a native-encoding character that got split by
- * the end of the previous buffer and need to be moved to the
- * beginning of the next buffer to make a contiguous string so it
- * can be converted to UTF-8.
+ * A channel buffer has BUFFER_PADDING bytes extra at beginning to hold
+ * any bytes of a native-encoding character that got split by the end of
+ * the previous buffer and need to be moved to the beginning of the next
+ * buffer to make a contiguous string so it can be converted to UTF-8.
*
- * A channel buffer has BUFFER_PADDING bytes extra at the end to
- * hold any bytes of a native-encoding character (generated from a
- * UTF-8 character) that overflow past the end of the buffer and
- * need to be moved to the next buffer.
+ * A channel buffer has BUFFER_PADDING bytes extra at the end to hold any
+ * bytes of a native-encoding character (generated from a UTF-8
+ * character) that overflow past the end of the buffer and need to be
+ * moved to the next buffer.
*
* Results:
* A newly allocated channel buffer.
@@ -1859,8 +2045,8 @@ Tcl_GetChannelHandle(chan, direction, handlePtr)
*/
static ChannelBuffer *
-AllocChannelBuffer(length)
- int length; /* Desired length of channel buffer. */
+AllocChannelBuffer(
+ int length) /* Desired length of channel buffer. */
{
ChannelBuffer *bufPtr;
int n;
@@ -1870,7 +2056,7 @@ AllocChannelBuffer(length)
bufPtr->nextAdded = BUFFER_PADDING;
bufPtr->nextRemoved = BUFFER_PADDING;
bufPtr->bufLength = length + BUFFER_PADDING;
- bufPtr->nextPtr = (ChannelBuffer *) NULL;
+ bufPtr->nextPtr = NULL;
return bufPtr;
}
@@ -1879,11 +2065,10 @@ AllocChannelBuffer(length)
*
* RecycleBuffer --
*
- * Helper function to recycle input and output buffers. Ensures
- * that two input buffers are saved (one in the input queue and
- * another in the saveInBufPtr field) and that curOutPtr is set
- * to a buffer. Only if these conditions are met is the buffer
- * freed to the OS.
+ * Helper function to recycle input and output buffers. Ensures that two
+ * input buffers are saved (one in the input queue and another in the
+ * saveInBufPtr field) and that curOutPtr is set to a buffer. Only if
+ * these conditions are met is the buffer freed to the OS.
*
* Results:
* None.
@@ -1895,46 +2080,46 @@ AllocChannelBuffer(length)
*/
static void
-RecycleBuffer(statePtr, bufPtr, mustDiscard)
- ChannelState *statePtr; /* ChannelState in which to recycle buffers. */
- ChannelBuffer *bufPtr; /* The buffer to recycle. */
- int mustDiscard; /* If nonzero, free the buffer to the
- * OS, always. */
+RecycleBuffer(
+ ChannelState *statePtr, /* ChannelState in which to recycle buffers. */
+ ChannelBuffer *bufPtr, /* The buffer to recycle. */
+ int mustDiscard) /* If nonzero, free the buffer to the OS,
+ * always. */
{
/*
* Do we have to free the buffer to the OS?
*/
if (mustDiscard) {
- ckfree((char *) bufPtr);
- return;
+ ckfree((char *) bufPtr);
+ return;
}
/*
- * Only save buffers which are at least as big as the requested
- * buffersize for the channel. This is to honor dynamic changes
- * of the buffersize made by the user.
+ * Only save buffers which are at least as big as the requested buffersize
+ * for the channel. This is to honor dynamic changes of the buffersize
+ * made by the user.
*/
if ((bufPtr->bufLength - BUFFER_PADDING) < statePtr->bufSize) {
- ckfree((char *) bufPtr);
- return;
+ ckfree((char *) bufPtr);
+ return;
}
/*
* Only save buffers for the input queue if the channel is readable.
*/
-
+
if (statePtr->flags & TCL_READABLE) {
- if (statePtr->inQueueHead == (ChannelBuffer *) NULL) {
- statePtr->inQueueHead = bufPtr;
- statePtr->inQueueTail = bufPtr;
- goto keepit;
- }
- if (statePtr->saveInBufPtr == (ChannelBuffer *) NULL) {
- statePtr->saveInBufPtr = bufPtr;
- goto keepit;
- }
+ if (statePtr->inQueueHead == NULL) {
+ statePtr->inQueueHead = bufPtr;
+ statePtr->inQueueTail = bufPtr;
+ goto keepBuffer;
+ }
+ if (statePtr->saveInBufPtr == NULL) {
+ statePtr->saveInBufPtr = bufPtr;
+ goto keepBuffer;
+ }
}
/*
@@ -1942,10 +2127,10 @@ RecycleBuffer(statePtr, bufPtr, mustDiscard)
*/
if (statePtr->flags & TCL_WRITABLE) {
- if (statePtr->curOutPtr == (ChannelBuffer *) NULL) {
- statePtr->curOutPtr = bufPtr;
- goto keepit;
- }
+ if (statePtr->curOutPtr == NULL) {
+ statePtr->curOutPtr = bufPtr;
+ goto keepBuffer;
+ }
}
/*
@@ -1955,10 +2140,10 @@ RecycleBuffer(statePtr, bufPtr, mustDiscard)
ckfree((char *) bufPtr);
return;
- keepit:
+ keepBuffer:
bufPtr->nextRemoved = BUFFER_PADDING;
bufPtr->nextAdded = BUFFER_PADDING;
- bufPtr->nextPtr = (ChannelBuffer *) NULL;
+ bufPtr->nextPtr = NULL;
}
/*
@@ -1978,18 +2163,18 @@ RecycleBuffer(statePtr, bufPtr, mustDiscard)
*/
static void
-DiscardOutputQueued(statePtr)
- ChannelState *statePtr; /* ChannelState for which to discard output. */
+DiscardOutputQueued(
+ ChannelState *statePtr) /* ChannelState for which to discard output. */
{
ChannelBuffer *bufPtr;
-
- while (statePtr->outQueueHead != (ChannelBuffer *) NULL) {
- bufPtr = statePtr->outQueueHead;
- statePtr->outQueueHead = bufPtr->nextPtr;
- RecycleBuffer(statePtr, bufPtr, 0);
+
+ while (statePtr->outQueueHead != NULL) {
+ bufPtr = statePtr->outQueueHead;
+ statePtr->outQueueHead = bufPtr->nextPtr;
+ RecycleBuffer(statePtr, bufPtr, 0);
}
- statePtr->outQueueHead = (ChannelBuffer *) NULL;
- statePtr->outQueueTail = (ChannelBuffer *) NULL;
+ statePtr->outQueueHead = NULL;
+ statePtr->outQueueTail = NULL;
}
/*
@@ -1997,29 +2182,28 @@ DiscardOutputQueued(statePtr)
*
* CheckForDeadChannel --
*
- * This function checks is a given channel is Dead.
- * (A channel that has been closed but not yet deallocated.)
+ * This function checks is a given channel is Dead (a channel that has
+ * been closed but not yet deallocated.)
*
* Results:
* True (1) if channel is Dead, False (0) if channel is Ok
*
* Side effects:
- * None
+ * None
*
*----------------------------------------------------------------------
*/
static int
-CheckForDeadChannel(interp, statePtr)
- Tcl_Interp *interp; /* For error reporting (can be NULL) */
- ChannelState *statePtr; /* The channel state to check. */
+CheckForDeadChannel(
+ Tcl_Interp *interp, /* For error reporting (can be NULL) */
+ ChannelState *statePtr) /* The channel state to check. */
{
if (statePtr->flags & CHANNEL_DEAD) {
- Tcl_SetErrno(EINVAL);
+ Tcl_SetErrno(EINVAL);
if (interp) {
Tcl_AppendResult(interp,
- "unable to access channel: invalid channel",
- (char *) NULL);
+ "unable to access channel: invalid channel", NULL);
}
return 1;
}
@@ -2036,221 +2220,253 @@ CheckForDeadChannel(interp, statePtr)
* event handler to flush channel output asynchronously.
*
* Results:
- * 0 if successful, else the error code that was returned by the
- * channel type operation.
+ * 0 if successful, else the error code that was returned by the channel
+ * type operation. May leave a message in the interp result.
*
* Side effects:
- * May produce output on a channel. May block indefinitely if the
- * channel is synchronous. May schedule an async flush on the channel.
- * May recycle memory for buffers in the output queue.
+ * May produce output on a channel. May block indefinitely if the channel
+ * is synchronous. May schedule an async flush on the channel. May
+ * recycle memory for buffers in the output queue.
*
*----------------------------------------------------------------------
*/
static int
-FlushChannel(interp, chanPtr, calledFromAsyncFlush)
- Tcl_Interp *interp; /* For error reporting during close. */
- Channel *chanPtr; /* The channel to flush on. */
- int calledFromAsyncFlush; /* If nonzero then we are being
- * called from an asynchronous
- * flush callback. */
+FlushChannel(
+ Tcl_Interp *interp, /* For error reporting during close. */
+ Channel *chanPtr, /* The channel to flush on. */
+ int calledFromAsyncFlush) /* If nonzero then we are being called from an
+ * asynchronous flush callback. */
{
ChannelState *statePtr = chanPtr->state;
- /* State of the channel stack. */
- ChannelBuffer *bufPtr; /* Iterates over buffered output
- * queue. */
- int toWrite; /* Amount of output data in current
- * buffer available to be written. */
- int written; /* Amount of output data actually
- * written in current round. */
- int errorCode = 0; /* Stores POSIX error codes from
- * channel driver operations. */
- int wroteSome = 0; /* Set to one if any data was
- * written to the driver. */
+ /* State of the channel stack. */
+ ChannelBuffer *bufPtr; /* Iterates over buffered output queue. */
+ int toWrite; /* Amount of output data in current buffer
+ * available to be written. */
+ int written; /* Amount of output data actually written in
+ * current round. */
+ int errorCode = 0; /* Stores POSIX error codes from channel
+ * driver operations. */
+ int wroteSome = 0; /* Set to one if any data was written to the
+ * driver. */
/*
- * Prevent writing on a dead channel -- a channel that has been closed
- * but not yet deallocated. This can occur if the exit handler for the
- * channel deallocation runs before all channels are deregistered in
- * all interpreters.
+ * Prevent writing on a dead channel -- a channel that has been closed but
+ * not yet deallocated. This can occur if the exit handler for the channel
+ * deallocation runs before all channels are deregistered in all
+ * interpreters.
*/
-
- if (CheckForDeadChannel(interp, statePtr)) return -1;
-
+
+ if (CheckForDeadChannel(interp, statePtr)) {
+ return -1;
+ }
+
/*
- * Loop over the queued buffers and attempt to flush as
- * much as possible of the queued output to the channel.
+ * Loop over the queued buffers and attempt to flush as much as possible
+ * of the queued output to the channel.
*/
while (1) {
+ /*
+ * If the queue is empty and there is a ready current buffer, OR if
+ * the current buffer is full, then move the current buffer to the
+ * queue.
+ */
+
+ if (((statePtr->curOutPtr != NULL) &&
+ IsBufferFull(statePtr->curOutPtr))
+ || ((statePtr->flags & BUFFER_READY) &&
+ (statePtr->outQueueHead == NULL))) {
+ ResetFlag(statePtr, BUFFER_READY);
+ statePtr->curOutPtr->nextPtr = NULL;
+ if (statePtr->outQueueHead == NULL) {
+ statePtr->outQueueHead = statePtr->curOutPtr;
+ } else {
+ statePtr->outQueueTail->nextPtr = statePtr->curOutPtr;
+ }
+ statePtr->outQueueTail = statePtr->curOutPtr;
+ statePtr->curOutPtr = NULL;
+ }
+ bufPtr = statePtr->outQueueHead;
+
+ /*
+ * If we are not being called from an async flush and an async flush
+ * is active, we just return without producing any output.
+ */
+
+ if ((!calledFromAsyncFlush) &&
+ (statePtr->flags & BG_FLUSH_SCHEDULED)) {
+ return 0;
+ }
+
+ /*
+ * If the output queue is still empty, break out of the while loop.
+ */
+
+ if (bufPtr == NULL) {
+ break; /* Out of the "while (1)". */
+ }
+
+ /*
+ * Produce the output on the channel.
+ */
- /*
- * If the queue is empty and there is a ready current buffer, OR if
- * the current buffer is full, then move the current buffer to the
- * queue.
- */
-
- if (((statePtr->curOutPtr != (ChannelBuffer *) NULL) &&
- (statePtr->curOutPtr->nextAdded == statePtr->curOutPtr->bufLength))
- || ((statePtr->flags & BUFFER_READY) &&
- (statePtr->outQueueHead == (ChannelBuffer *) NULL))) {
- statePtr->flags &= (~(BUFFER_READY));
- statePtr->curOutPtr->nextPtr = (ChannelBuffer *) NULL;
- if (statePtr->outQueueHead == (ChannelBuffer *) NULL) {
- statePtr->outQueueHead = statePtr->curOutPtr;
- } else {
- statePtr->outQueueTail->nextPtr = statePtr->curOutPtr;
- }
- statePtr->outQueueTail = statePtr->curOutPtr;
- statePtr->curOutPtr = (ChannelBuffer *) NULL;
- }
- bufPtr = statePtr->outQueueHead;
-
- /*
- * If we are not being called from an async flush and an async
- * flush is active, we just return without producing any output.
- */
-
- if ((!calledFromAsyncFlush) &&
- (statePtr->flags & BG_FLUSH_SCHEDULED)) {
- return 0;
- }
-
- /*
- * If the output queue is still empty, break out of the while loop.
- */
-
- if (bufPtr == (ChannelBuffer *) NULL) {
- break; /* Out of the "while (1)". */
- }
-
- /*
- * Produce the output on the channel.
- */
-
- toWrite = bufPtr->nextAdded - bufPtr->nextRemoved;
+ toWrite = BytesLeft(bufPtr);
if (toWrite == 0) {
written = 0;
} else {
- written = (chanPtr->typePtr->outputProc) (chanPtr->instanceData,
- bufPtr->buf + bufPtr->nextRemoved, toWrite,
- &errorCode);
+ written = (chanPtr->typePtr->outputProc)(chanPtr->instanceData,
+ RemovePoint(bufPtr), toWrite, &errorCode);
}
/*
- * If the write failed completely attempt to start the asynchronous
- * flush mechanism and break out of this loop - do not attempt to
- * write any more output at this time.
- */
-
- if (written < 0) {
-
- /*
- * If the last attempt to write was interrupted, simply retry.
- */
-
- if (errorCode == EINTR) {
- errorCode = 0;
- continue;
- }
-
- /*
- * If the channel is non-blocking and we would have blocked,
- * start a background flushing handler and break out of the loop.
- */
-
- if ((errorCode == EWOULDBLOCK) || (errorCode == EAGAIN)) {
+ * If the write failed completely attempt to start the asynchronous
+ * flush mechanism and break out of this loop - do not attempt to
+ * write any more output at this time.
+ */
+
+ if (written < 0) {
+ /*
+ * If the last attempt to write was interrupted, simply retry.
+ */
+
+ if (errorCode == EINTR) {
+ errorCode = 0;
+ continue;
+ }
+
+ /*
+ * If the channel is non-blocking and we would have blocked, start
+ * a background flushing handler and break out of the loop.
+ */
+
+ if ((errorCode == EWOULDBLOCK) || (errorCode == EAGAIN)) {
/*
- * This used to check for CHANNEL_NONBLOCKING, and panic
- * if the channel was blocking. However, it appears
- * that setting stdin to -blocking 0 has some effect on
- * the stdout when it's a tty channel (dup'ed underneath)
+ * This used to check for CHANNEL_NONBLOCKING, and panic if
+ * the channel was blocking. However, it appears that setting
+ * stdin to -blocking 0 has some effect on the stdout when
+ * it's a tty channel (dup'ed underneath)
*/
+
if (!(statePtr->flags & BG_FLUSH_SCHEDULED)) {
- statePtr->flags |= BG_FLUSH_SCHEDULED;
+ SetFlag(statePtr, BG_FLUSH_SCHEDULED);
UpdateInterest(chanPtr);
}
errorCode = 0;
break;
- }
+ }
+
+ /*
+ * Decide whether to report the error upwards or defer it.
+ */
+
+ if (calledFromAsyncFlush) {
+ /*
+ * TIP #219, Tcl Channel Reflection API.
+ * When defering the error copy a message from the bypass into
+ * the unreported area. Or discard it if the new error is to be
+ * ignored in favor of an earlier defered error.
+ */
- /*
- * Decide whether to report the error upwards or defer it.
- */
+ Tcl_Obj *msg = statePtr->chanMsg;
- if (calledFromAsyncFlush) {
- if (statePtr->unreportedError == 0) {
- statePtr->unreportedError = errorCode;
- }
- } else {
- Tcl_SetErrno(errorCode);
- if (interp != NULL) {
+ if (statePtr->unreportedError == 0) {
+ statePtr->unreportedError = errorCode;
+ statePtr->unreportedMsg = msg;
+ if (msg != NULL) {
+ Tcl_IncrRefCount(msg);
+ }
+ } else {
+ /*
+ * An old unreported error is kept, and this error thrown
+ * away.
+ */
+
+ statePtr->chanMsg = NULL;
+ if (msg != NULL) {
+ TclDecrRefCount(msg);
+ }
+ }
+ } else {
+ /*
+ * TIP #219, Tcl Channel Reflection API.
+ * Move error messages put by the driver into the chan bypass
+ * area into the regular interpreter result. Fall back to the
+ * regular message if nothing was found in the bypasses.
+ */
+ Tcl_SetErrno(errorCode);
+ if (interp != NULL && !TclChanCaughtErrorBypass(interp,
+ (Tcl_Channel) chanPtr)) {
/*
- * Casting away CONST here is safe because the
- * TCL_VOLATILE flag guarantees CONST treatment
- * of the Posix error string.
+ * Casting away const here is safe because the
+ * TCL_VOLATILE flag guarantees const treatment of the
+ * Posix error string.
*/
- Tcl_SetResult(interp,
- (char *) Tcl_PosixError(interp), TCL_VOLATILE);
+ Tcl_SetResult(interp, (char *) Tcl_PosixError(interp),
+ TCL_VOLATILE);
}
- }
- /*
- * When we get an error we throw away all the output
- * currently queued.
- */
+ /*
+ * An unreportable bypassed message is kept, for the caller of
+ * Tcl_Seek, Tcl_Write, etc.
+ */
+ }
- DiscardOutputQueued(statePtr);
- continue;
- } else {
+ /*
+ * When we get an error we throw away all the output currently
+ * queued.
+ */
+
+ DiscardOutputQueued(statePtr);
+ continue;
+ } else {
wroteSome = 1;
}
- bufPtr->nextRemoved += written;
+ bufPtr->nextRemoved += written;
- /*
- * If this buffer is now empty, recycle it.
- */
+ /*
+ * If this buffer is now empty, recycle it.
+ */
- if (bufPtr->nextRemoved == bufPtr->nextAdded) {
- statePtr->outQueueHead = bufPtr->nextPtr;
- if (statePtr->outQueueHead == (ChannelBuffer *) NULL) {
- statePtr->outQueueTail = (ChannelBuffer *) NULL;
- }
- RecycleBuffer(statePtr, bufPtr, 0);
- }
+ if (IsBufferEmpty(bufPtr)) {
+ statePtr->outQueueHead = bufPtr->nextPtr;
+ if (statePtr->outQueueHead == NULL) {
+ statePtr->outQueueTail = NULL;
+ }
+ RecycleBuffer(statePtr, bufPtr, 0);
+ }
} /* Closes "while (1)". */
/*
* If we wrote some data while flushing in the background, we are done.
- * We can't finish the background flush until we run out of data and
- * the channel becomes writable again. This ensures that all of the
- * pending data has been flushed at the system level.
+ * We can't finish the background flush until we run out of data and the
+ * channel becomes writable again. This ensures that all of the pending
+ * data has been flushed at the system level.
*/
if (statePtr->flags & BG_FLUSH_SCHEDULED) {
if (wroteSome) {
return errorCode;
- } else if (statePtr->outQueueHead == (ChannelBuffer *) NULL) {
- statePtr->flags &= (~(BG_FLUSH_SCHEDULED));
+ } else if (statePtr->outQueueHead == NULL) {
+ ResetFlag(statePtr, BG_FLUSH_SCHEDULED);
(chanPtr->typePtr->watchProc)(chanPtr->instanceData,
statePtr->interestMask);
}
}
/*
- * If the channel is flagged as closed, delete it when the refCount
- * drops to zero, the output queue is empty and there is no output
- * in the current output buffer.
+ * If the channel is flagged as closed, delete it when the refCount drops
+ * to zero, the output queue is empty and there is no output in the
+ * current output buffer.
*/
if ((statePtr->flags & CHANNEL_CLOSED) && (statePtr->refCount <= 0) &&
- (statePtr->outQueueHead == (ChannelBuffer *) NULL) &&
- ((statePtr->curOutPtr == (ChannelBuffer *) NULL) ||
- (statePtr->curOutPtr->nextAdded ==
- statePtr->curOutPtr->nextRemoved))) {
+ (statePtr->outQueueHead == NULL) &&
+ ((statePtr->curOutPtr == NULL) ||
+ IsBufferEmpty(statePtr->curOutPtr))) {
return CloseChannel(interp, chanPtr, errorCode);
}
return errorCode;
@@ -2265,34 +2481,33 @@ FlushChannel(interp, chanPtr, calledFromAsyncFlush)
*
* If the channel was stacked, then the it will copy the necessary
* elements of the NEXT channel into the TOP channel, in essence
- * unstacking the channel. The NEXT channel will then be freed.
+ * unstacking the channel. The NEXT channel will then be freed.
*
- * If the channel was not stacked, then we will free all the bits
- * for the TOP channel, including the data structure itself.
+ * If the channel was not stacked, then we will free all the bits for the
+ * TOP channel, including the data structure itself.
*
* Results:
- * 1 if the channel was stacked, 0 otherwise.
+ * Error code from an unreported error or the driver close operation.
*
* Side effects:
- * May close the actual channel; may free memory.
- * May change the value of errno.
+ * May close the actual channel, may free memory, may change the value of
+ * errno.
*
*----------------------------------------------------------------------
*/
static int
-CloseChannel(interp, chanPtr, errorCode)
- Tcl_Interp *interp; /* For error reporting. */
- Channel *chanPtr; /* The channel to close. */
- int errorCode; /* Status of operation so far. */
-{
- int result = 0; /* Of calling driver close
- * operation. */
- ChannelState *statePtr; /* state of the channel stack. */
+CloseChannel(
+ Tcl_Interp *interp, /* For error reporting. */
+ Channel *chanPtr, /* The channel to close. */
+ int errorCode) /* Status of operation so far. */
+{
+ int result = 0; /* Of calling driver close operation. */
+ ChannelState *statePtr; /* State of the channel stack. */
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
if (chanPtr == NULL) {
- return result;
+ return result;
}
statePtr = chanPtr->state;
@@ -2306,57 +2521,70 @@ CloseChannel(interp, chanPtr, errorCode)
* Discard a leftover buffer in the current output buffer field.
*/
- if (statePtr->curOutPtr != (ChannelBuffer *) NULL) {
- ckfree((char *) statePtr->curOutPtr);
- statePtr->curOutPtr = (ChannelBuffer *) NULL;
+ if (statePtr->curOutPtr != NULL) {
+ ckfree((char *) statePtr->curOutPtr);
+ statePtr->curOutPtr = NULL;
}
-
+
/*
- * The caller guarantees that there are no more buffers
- * queued for output.
+ * The caller guarantees that there are no more buffers queued for output.
*/
- if (statePtr->outQueueHead != (ChannelBuffer *) NULL) {
- panic("TclFlush, closed channel: queued output left");
+ if (statePtr->outQueueHead != NULL) {
+ Tcl_Panic("TclFlush, closed channel: queued output left");
}
/*
- * If the EOF character is set in the channel, append that to the
- * output device.
+ * If the EOF character is set in the channel, append that to the output
+ * device.
*/
if ((statePtr->outEofChar != 0) && (statePtr->flags & TCL_WRITABLE)) {
- int dummy;
- char c;
+ int dummy;
+ char c = (char) statePtr->outEofChar;
- c = (char) statePtr->outEofChar;
- (chanPtr->typePtr->outputProc) (chanPtr->instanceData, &c, 1, &dummy);
+ (chanPtr->typePtr->outputProc)(chanPtr->instanceData, &c, 1, &dummy);
+ }
+
+ /*
+ * TIP #219, Tcl Channel Reflection API.
+ * Move a leftover error message in the channel bypass into the
+ * interpreter bypass. Just clear it if there is no interpreter.
+ */
+
+ if (statePtr->chanMsg != NULL) {
+ if (interp != NULL) {
+ Tcl_SetChannelErrorInterp(interp,statePtr->chanMsg);
+ }
+ TclDecrRefCount(statePtr->chanMsg);
+ statePtr->chanMsg = NULL;
}
/*
* Remove this channel from of the list of all channels.
*/
- Tcl_CutChannel((Tcl_Channel) chanPtr);
+
+ CutChannel((Tcl_Channel) chanPtr);
/*
* Close and free the channel driver state.
+ * This may leave a TIP #219 error message in the interp.
*/
if (chanPtr->typePtr->closeProc != TCL_CLOSE2PROC) {
result = (chanPtr->typePtr->closeProc)(chanPtr->instanceData, interp);
} else {
- result = (chanPtr->typePtr->close2Proc)(chanPtr->instanceData, interp,
- 0);
+ result = (chanPtr->typePtr->close2Proc)(chanPtr->instanceData,
+ interp, 0);
}
/*
- * Some resources can be cleared only if the bottom channel
- * in a stack is closed. All the other channels in the stack
- * are not allowed to remove.
+ * Some resources can be cleared only if the bottom channel in a stack is
+ * closed. All the other channels in the stack are not allowed to remove.
*/
if (chanPtr == statePtr->bottomChanPtr) {
- if (statePtr->channelName != (char *) NULL) {
+ if (statePtr->channelName != NULL) {
ckfree((char *) statePtr->channelName);
statePtr->channelName = NULL;
}
@@ -2364,23 +2592,37 @@ CloseChannel(interp, chanPtr, errorCode)
Tcl_FreeEncoding(statePtr->encoding);
if (statePtr->outputStage != NULL) {
ckfree((char *) statePtr->outputStage);
- statePtr->outputStage = (char *) NULL;
+ statePtr->outputStage = NULL;
}
}
/*
- * If we are being called synchronously, report either
- * any latent error on the channel or the current error.
+ * If we are being called synchronously, report either any latent error on
+ * the channel or the current error.
*/
if (statePtr->unreportedError != 0) {
- errorCode = statePtr->unreportedError;
+ errorCode = statePtr->unreportedError;
+
+ /*
+ * TIP #219, Tcl Channel Reflection API.
+ * Move an error message found in the unreported area into the regular
+ * bypass (interp). This kills any message in the channel bypass area.
+ */
+
+ if (statePtr->chanMsg != NULL) {
+ TclDecrRefCount(statePtr->chanMsg);
+ statePtr->chanMsg = NULL;
+ }
+ if (interp) {
+ Tcl_SetChannelErrorInterp(interp,statePtr->unreportedMsg);
+ }
}
if (errorCode == 0) {
- errorCode = result;
- if (errorCode != 0) {
- Tcl_SetErrno(errorCode);
- }
+ errorCode = result;
+ if (errorCode != 0) {
+ Tcl_SetErrno(errorCode);
+ }
}
/*
@@ -2393,31 +2635,31 @@ CloseChannel(interp, chanPtr, errorCode)
* Mark the channel as deleted by clearing the type structure.
*/
- if (chanPtr->downChanPtr != (Channel *) NULL) {
+ if (chanPtr->downChanPtr != NULL) {
Channel *downChanPtr = chanPtr->downChanPtr;
- statePtr->nextCSPtr = tsdPtr->firstCSPtr;
- tsdPtr->firstCSPtr = statePtr;
+ statePtr->nextCSPtr = tsdPtr->firstCSPtr;
+ tsdPtr->firstCSPtr = statePtr;
- statePtr->topChanPtr = downChanPtr;
- downChanPtr->upChanPtr = (Channel *) NULL;
- chanPtr->typePtr = NULL;
+ statePtr->topChanPtr = downChanPtr;
+ downChanPtr->upChanPtr = NULL;
+ chanPtr->typePtr = NULL;
- Tcl_EventuallyFree((ClientData) chanPtr, TCL_DYNAMIC);
+ Tcl_EventuallyFree(chanPtr, TCL_DYNAMIC);
return Tcl_Close(interp, (Tcl_Channel) downChanPtr);
}
/*
- * There is only the TOP Channel, so we free the remaining
- * pointers we have and then ourselves. Since this is the
- * last of the channels in the stack, make sure to free the
- * ChannelState structure associated with it. We use
- * Tcl_EventuallyFree to allow for any last
+ * There is only the TOP Channel, so we free the remaining pointers we
+ * have and then ourselves. Since this is the last of the channels in the
+ * stack, make sure to free the ChannelState structure associated with it.
+ * We use Tcl_EventuallyFree to allow for any last references.
*/
+
chanPtr->typePtr = NULL;
- Tcl_EventuallyFree((ClientData) statePtr, TCL_DYNAMIC);
- Tcl_EventuallyFree((ClientData) chanPtr, TCL_DYNAMIC);
+ Tcl_EventuallyFree(statePtr, TCL_DYNAMIC);
+ Tcl_EventuallyFree(chanPtr, TCL_DYNAMIC);
return errorCode;
}
@@ -2426,10 +2668,10 @@ CloseChannel(interp, chanPtr, errorCode)
*----------------------------------------------------------------------
*
* Tcl_CutChannel --
+ * CutChannel --
*
- * Removes a channel from the (thread-)global list of all channels
- * (in that thread). This is actually the statePtr for the stack
- * of channel.
+ * Removes a channel from the (thread-)global list of all channels (in
+ * that thread). This is actually the statePtr for the stack of channel.
*
* Results:
* Nothing.
@@ -2438,56 +2680,107 @@ CloseChannel(interp, chanPtr, errorCode)
* Resets the field 'nextCSPtr' of the specified channel state to NULL.
*
* NOTE:
- * The channel to cut out of the list must not be referenced
- * in any interpreter. This is something this procedure cannot
- * check (despite the refcount) because the caller usually wants
- * fiddle with the channel (like transfering it to a different
- * thread) and thus keeps the refcount artifically high to prevent
- * its destruction.
+ * The channel to cut out of the list must not be referenced in any
+ * interpreter. This is something this procedure cannot check (despite
+ * the refcount) because the caller usually wants fiddle with the channel
+ * (like transfering it to a different thread) and thus keeps the
+ * refcount artifically high to prevent its destruction.
*
*----------------------------------------------------------------------
*/
-void
-Tcl_CutChannel(chan)
- Tcl_Channel chan; /* The channel being removed. Must
- * not be referenced in any
- * interpreter. */
-{
- ThreadSpecificData* tsdPtr = TCL_TSD_INIT(&dataKey);
- ChannelState *prevCSPtr; /* Preceding channel state in list of
- * all states - used to splice a
- * channel out of the list on close. */
+static void
+CutChannel(
+ Tcl_Channel chan) /* The channel being removed. Must not be
+ * referenced in any interpreter. */
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ChannelState *prevCSPtr; /* Preceding channel state in list of all
+ * states - used to splice a channel out of
+ * the list on close. */
ChannelState *statePtr = ((Channel *) chan)->state;
- /* state of the channel stack. */
+ /* State of the channel stack. */
Tcl_DriverThreadActionProc *threadActionProc;
/*
- * Remove this channel from of the list of all channels
- * (in the current thread).
+ * Remove this channel from of the list of all channels (in the current
+ * thread).
*/
if (tsdPtr->firstCSPtr && (statePtr == tsdPtr->firstCSPtr)) {
- tsdPtr->firstCSPtr = statePtr->nextCSPtr;
+ tsdPtr->firstCSPtr = statePtr->nextCSPtr;
} else {
- for (prevCSPtr = tsdPtr->firstCSPtr;
- prevCSPtr && (prevCSPtr->nextCSPtr != statePtr);
- prevCSPtr = prevCSPtr->nextCSPtr) {
- /* Empty loop body. */
- }
- if (prevCSPtr == (ChannelState *) NULL) {
- panic("FlushChannel: damaged channel list");
- }
- prevCSPtr->nextCSPtr = statePtr->nextCSPtr;
+ for (prevCSPtr = tsdPtr->firstCSPtr;
+ prevCSPtr && (prevCSPtr->nextCSPtr != statePtr);
+ prevCSPtr = prevCSPtr->nextCSPtr) {
+ /* Empty loop body. */
+ }
+ if (prevCSPtr == NULL) {
+ Tcl_Panic("FlushChannel: damaged channel list");
+ }
+ prevCSPtr->nextCSPtr = statePtr->nextCSPtr;
}
- statePtr->nextCSPtr = (ChannelState *) NULL;
+ statePtr->nextCSPtr = NULL;
- /* TIP #218, Channel Thread Actions */
- threadActionProc = Tcl_ChannelThreadActionProc (Tcl_GetChannelType (chan));
+ /*
+ * TIP #218, Channel Thread Actions
+ */
+
+ threadActionProc = Tcl_ChannelThreadActionProc(Tcl_GetChannelType(chan));
if (threadActionProc != NULL) {
- (*threadActionProc) (Tcl_GetChannelInstanceData(chan),
- TCL_CHANNEL_THREAD_REMOVE);
+ (*threadActionProc)(Tcl_GetChannelInstanceData(chan),
+ TCL_CHANNEL_THREAD_REMOVE);
+ }
+}
+
+void
+Tcl_CutChannel(
+ Tcl_Channel chan) /* The channel being added. Must not be
+ * referenced in any interpreter. */
+{
+ Channel *chanPtr = ((Channel *) chan)->state->bottomChanPtr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ChannelState *prevCSPtr; /* Preceding channel state in list of all
+ * states - used to splice a channel out of
+ * the list on close. */
+ ChannelState *statePtr = chanPtr->state;
+ /* State of the channel stack. */
+ Tcl_DriverThreadActionProc *threadActionProc;
+
+ /*
+ * Remove this channel from of the list of all channels (in the current
+ * thread).
+ */
+
+ if (tsdPtr->firstCSPtr && (statePtr == tsdPtr->firstCSPtr)) {
+ tsdPtr->firstCSPtr = statePtr->nextCSPtr;
+ } else {
+ for (prevCSPtr = tsdPtr->firstCSPtr;
+ prevCSPtr && (prevCSPtr->nextCSPtr != statePtr);
+ prevCSPtr = prevCSPtr->nextCSPtr) {
+ /* Empty loop body. */
+ }
+ if (prevCSPtr == NULL) {
+ Tcl_Panic("FlushChannel: damaged channel list");
+ }
+ prevCSPtr->nextCSPtr = statePtr->nextCSPtr;
+ }
+
+ statePtr->nextCSPtr = NULL;
+
+ /*
+ * TIP #218, Channel Thread Actions
+ * For all transformations and the base channel.
+ */
+
+ while (chanPtr) {
+ threadActionProc = Tcl_ChannelThreadActionProc(chanPtr->typePtr);
+ if (threadActionProc != NULL) {
+ (*threadActionProc)(chanPtr->instanceData,
+ TCL_CHANNEL_THREAD_REMOVE);
+ }
+ chanPtr= chanPtr->upChanPtr;
}
}
@@ -2495,10 +2788,11 @@ Tcl_CutChannel(chan)
*----------------------------------------------------------------------
*
* Tcl_SpliceChannel --
+ * SpliceChannel --
*
- * Adds a channel to the (thread-)global list of all channels
- * (in that thread). Expects that the field 'nextChanPtr' in
- * the channel is set to NULL.
+ * Adds a channel to the (thread-)global list of all channels (in that
+ * thread). Expects that the field 'nextChanPtr' in the channel is set to
+ * NULL.
*
* Results:
* Nothing.
@@ -2508,45 +2802,86 @@ Tcl_CutChannel(chan)
*
* NOTE:
* The channel to splice into the list must not be referenced in any
- * interpreter. This is something this procedure cannot check
- * (despite the refcount) because the caller usually wants figgle
- * with the channel (like transfering it to a different thread)
- * and thus keeps the refcount artifically high to prevent its
- * destruction.
+ * interpreter. This is something this procedure cannot check (despite
+ * the refcount) because the caller usually wants figgle with the channel
+ * (like transfering it to a different thread) and thus keeps the
+ * refcount artifically high to prevent its destruction.
*
*----------------------------------------------------------------------
*/
-void
-Tcl_SpliceChannel(chan)
- Tcl_Channel chan; /* The channel being added. Must
- * not be referenced in any
- * interpreter. */
+static void
+SpliceChannel(
+ Tcl_Channel chan) /* The channel being added. Must not be
+ * referenced in any interpreter. */
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- ChannelState *statePtr = ((Channel *) chan)->state;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ChannelState *statePtr = ((Channel *) chan)->state;
Tcl_DriverThreadActionProc *threadActionProc;
- if (statePtr->nextCSPtr != (ChannelState *) NULL) {
- panic("Tcl_SpliceChannel: trying to add channel used in different list");
+ if (statePtr->nextCSPtr != NULL) {
+ Tcl_Panic("SpliceChannel: trying to add channel used in different list");
}
- statePtr->nextCSPtr = tsdPtr->firstCSPtr;
- tsdPtr->firstCSPtr = statePtr;
+ statePtr->nextCSPtr = tsdPtr->firstCSPtr;
+ tsdPtr->firstCSPtr = statePtr;
/*
- * TIP #10. Mark the current thread as the new one managing this
- * channel. Note: 'Tcl_GetCurrentThread' returns sensible
- * values even for a non-threaded core.
+ * TIP #10. Mark the current thread as the new one managing this channel.
+ * Note: 'Tcl_GetCurrentThread' returns sensible values even for
+ * a non-threaded core.
*/
- statePtr->managingThread = Tcl_GetCurrentThread ();
+ statePtr->managingThread = Tcl_GetCurrentThread();
- /* TIP #218, Channel Thread Actions */
- threadActionProc = Tcl_ChannelThreadActionProc (Tcl_GetChannelType (chan));
+ /*
+ * TIP #218, Channel Thread Actions
+ */
+
+ threadActionProc = Tcl_ChannelThreadActionProc(Tcl_GetChannelType(chan));
if (threadActionProc != NULL) {
- (*threadActionProc) (Tcl_GetChannelInstanceData(chan),
- TCL_CHANNEL_THREAD_INSERT);
+ (*threadActionProc) (Tcl_GetChannelInstanceData(chan),
+ TCL_CHANNEL_THREAD_INSERT);
+ }
+}
+
+void
+Tcl_SpliceChannel(
+ Tcl_Channel chan) /* The channel being added. Must not be
+ * referenced in any interpreter. */
+{
+ Channel *chanPtr = ((Channel *) chan)->state->bottomChanPtr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ChannelState *statePtr = chanPtr->state;
+ Tcl_DriverThreadActionProc *threadActionProc;
+
+ if (statePtr->nextCSPtr != NULL) {
+ Tcl_Panic("SpliceChannel: trying to add channel used in different list");
+ }
+
+ statePtr->nextCSPtr = tsdPtr->firstCSPtr;
+ tsdPtr->firstCSPtr = statePtr;
+
+ /*
+ * TIP #10. Mark the current thread as the new one managing this channel.
+ * Note: 'Tcl_GetCurrentThread' returns sensible values even for
+ * a non-threaded core.
+ */
+
+ statePtr->managingThread = Tcl_GetCurrentThread();
+
+ /*
+ * TIP #218, Channel Thread Actions
+ * For all transformations and the base channel.
+ */
+
+ while (chanPtr) {
+ threadActionProc = Tcl_ChannelThreadActionProc(chanPtr->typePtr);
+ if (threadActionProc != NULL) {
+ (*threadActionProc)(chanPtr->instanceData,
+ TCL_CHANNEL_THREAD_INSERT);
+ }
+ chanPtr= chanPtr->upChanPtr;
}
}
@@ -2565,29 +2900,30 @@ Tcl_SpliceChannel(chan)
*
* NOTE:
* Tcl_Close removes the channel as far as the user is concerned.
- * However, it may continue to exist for a while longer if it has
- * a background flush scheduled. The device itself is eventually
- * closed and the channel record removed, in CloseChannel, above.
+ * However, it may continue to exist for a while longer if it has a
+ * background flush scheduled. The device itself is eventually closed and
+ * the channel record removed, in CloseChannel, above.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
-Tcl_Close(interp, chan)
- Tcl_Interp *interp; /* Interpreter for errors. */
- Tcl_Channel chan; /* The channel being closed. Must
- * not be referenced in any
- * interpreter. */
-{
- CloseCallback *cbPtr; /* Iterate over close callbacks
- * for this channel. */
- Channel *chanPtr; /* The real IO channel. */
- ChannelState *statePtr; /* State of real IO channel. */
- int result; /* Of calling FlushChannel. */
+Tcl_Close(
+ Tcl_Interp *interp, /* Interpreter for errors. */
+ Tcl_Channel chan) /* The channel being closed. Must not be
+ * referenced in any interpreter. */
+{
+ CloseCallback *cbPtr; /* Iterate over close callbacks for this
+ * channel. */
+ Channel *chanPtr; /* The real IO channel. */
+ ChannelState *statePtr; /* State of real IO channel. */
+ int result; /* Of calling FlushChannel. */
+ int flushcode;
+ int stickyError;
- if (chan == (Tcl_Channel) NULL) {
- return TCL_OK;
+ if (chan == NULL) {
+ return TCL_OK;
}
/*
@@ -2604,32 +2940,50 @@ Tcl_Close(interp, chan)
* This operation should occur at the top of a channel stack.
*/
- chanPtr = (Channel *) chan;
- statePtr = chanPtr->state;
- chanPtr = statePtr->topChanPtr;
+ chanPtr = (Channel *) chan;
+ statePtr = chanPtr->state;
+ chanPtr = statePtr->topChanPtr;
if (statePtr->refCount > 0) {
- panic("called Tcl_Close on channel with refCount > 0");
+ Tcl_Panic("called Tcl_Close on channel with refCount > 0");
}
-
+
if (statePtr->flags & CHANNEL_INCLOSE) {
if (interp) {
- Tcl_AppendResult(interp,
- "Illegal recursive call to close through close-handler of channel",
- (char *) NULL);
+ Tcl_AppendResult(interp, "Illegal recursive call to close "
+ "through close-handler of channel", NULL);
}
- return TCL_ERROR;
+ return TCL_ERROR;
}
- statePtr->flags |= CHANNEL_INCLOSE;
+ SetFlag(statePtr, CHANNEL_INCLOSE);
/*
* When the channel has an escape sequence driven encoding such as
* iso2022, the terminated escape sequence must write to the buffer.
*/
+
+ stickyError = 0;
+
if ((statePtr->encoding != NULL) && (statePtr->curOutPtr != NULL)
&& (CheckChannelErrors(statePtr, TCL_WRITABLE) == 0)) {
- statePtr->outputEncodingFlags |= TCL_ENCODING_END;
- WriteChars(chanPtr, "", 0);
+ statePtr->outputEncodingFlags |= TCL_ENCODING_END;
+ if (WriteChars(chanPtr, "", 0) < 0) {
+ stickyError = Tcl_GetErrno();
+ }
+
+ /*
+ * TIP #219, Tcl Channel Reflection API.
+ * Move an error message found in the channel bypass into the
+ * interpreter bypass. Just clear it if there is no interpreter.
+ */
+
+ if (statePtr->chanMsg != NULL) {
+ if (interp != NULL) {
+ Tcl_SetChannelErrorInterp(interp,statePtr->chanMsg);
+ }
+ TclDecrRefCount(statePtr->chanMsg);
+ statePtr->chanMsg = NULL;
+ }
}
Tcl_ClearChannelHandlers(chan);
@@ -2638,27 +2992,26 @@ Tcl_Close(interp, chan)
* Invoke the registered close callbacks and delete their records.
*/
- while (statePtr->closeCbPtr != (CloseCallback *) NULL) {
- cbPtr = statePtr->closeCbPtr;
- statePtr->closeCbPtr = cbPtr->nextPtr;
- (cbPtr->proc) (cbPtr->clientData);
- ckfree((char *) cbPtr);
+ while (statePtr->closeCbPtr != NULL) {
+ cbPtr = statePtr->closeCbPtr;
+ statePtr->closeCbPtr = cbPtr->nextPtr;
+ (cbPtr->proc)(cbPtr->clientData);
+ ckfree((char *) cbPtr);
}
- statePtr->flags &= ~CHANNEL_INCLOSE;
+ ResetFlag(statePtr, CHANNEL_INCLOSE);
/*
* Ensure that the last output buffer will be flushed.
*/
-
- if ((statePtr->curOutPtr != (ChannelBuffer *) NULL) &&
- (statePtr->curOutPtr->nextAdded > statePtr->curOutPtr->nextRemoved)) {
- statePtr->flags |= BUFFER_READY;
+
+ if ((statePtr->curOutPtr != NULL) && IsBufferReady(statePtr->curOutPtr)) {
+ SetFlag(statePtr, BUFFER_READY);
}
/*
- * If this channel supports it, close the read side, since we don't need it
- * anymore and this will help avoid deadlocks on some channel types.
+ * If this channel supports it, close the read side, since we don't need
+ * it anymore and this will help avoid deadlocks on some channel types.
*/
if (chanPtr->typePtr->closeProc == TCL_CLOSE2PROC) {
@@ -2669,14 +3022,42 @@ Tcl_Close(interp, chan)
}
/*
- * The call to FlushChannel will flush any queued output and invoke
- * the close function of the channel driver, or it will set up the
- * channel to be flushed and closed asynchronously.
+ * The call to FlushChannel will flush any queued output and invoke the
+ * close function of the channel driver, or it will set up the channel to
+ * be flushed and closed asynchronously.
*/
- statePtr->flags |= CHANNEL_CLOSED;
- if ((FlushChannel(interp, chanPtr, 0) != 0) || (result != 0)) {
- return TCL_ERROR;
+ SetFlag(statePtr, CHANNEL_CLOSED);
+
+ flushcode = FlushChannel(interp, chanPtr, 0);
+
+ /*
+ * TIP #219.
+ * Capture error messages put by the driver into the bypass area and put
+ * them into the regular interpreter result.
+ *
+ * Notes: Due to the assertion of CHANNEL_CLOSED in the flags
+ * FlushChannel() has called CloseChannel() and thus freed all the channel
+ * structures. We must not try to access "chan" anymore, hence the NULL
+ * argument in the call below. The only place which may still contain a
+ * message is the interpreter itself, and "CloseChannel" made sure to lift
+ * any channel message it generated into it.
+ */
+
+ if (TclChanCaughtErrorBypass(interp, NULL)) {
+ result = EINVAL;
+ }
+
+ if (stickyError != 0) {
+ Tcl_SetErrno(stickyError);
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj(Tcl_PosixError(interp), -1));
+ }
+ flushcode = -1;
+ }
+ if ((flushcode != 0) || (result != 0)) {
+ return TCL_ERROR;
}
return TCL_OK;
}
@@ -2700,8 +3081,8 @@ Tcl_Close(interp, chan)
*/
void
-Tcl_ClearChannelHandlers (channel)
- Tcl_Channel channel;
+Tcl_ClearChannelHandlers(
+ Tcl_Channel channel)
{
ChannelHandler *chPtr, *chNext; /* Iterate over channel handlers. */
EventScriptRecord *ePtr, *eNextPtr; /* Iterate over eventscript records. */
@@ -2714,9 +3095,9 @@ Tcl_ClearChannelHandlers (channel)
* This operation should occur at the top of a channel stack.
*/
- chanPtr = (Channel *) channel;
- statePtr = chanPtr->state;
- chanPtr = statePtr->topChanPtr;
+ chanPtr = (Channel *) channel;
+ statePtr = chanPtr->state;
+ chanPtr = statePtr->topChanPtr;
/*
* Cancel any outstanding timer.
@@ -2725,31 +3106,27 @@ Tcl_ClearChannelHandlers (channel)
Tcl_DeleteTimerHandler(statePtr->timer);
/*
- * Remove any references to channel handlers for this channel that
- * may be about to be invoked.
+ * Remove any references to channel handlers for this channel that may be
+ * about to be invoked.
*/
- for (nhPtr = tsdPtr->nestedHandlerPtr;
- nhPtr != (NextChannelHandler *) NULL;
- nhPtr = nhPtr->nestedHandlerPtr) {
- if (nhPtr->nextHandlerPtr &&
+ for (nhPtr = tsdPtr->nestedHandlerPtr; nhPtr != NULL;
+ nhPtr = nhPtr->nestedHandlerPtr) {
+ if (nhPtr->nextHandlerPtr &&
(nhPtr->nextHandlerPtr->chanPtr == chanPtr)) {
nhPtr->nextHandlerPtr = NULL;
- }
+ }
}
/*
- * Remove all the channel handler records attached to the channel
- * itself.
+ * Remove all the channel handler records attached to the channel itself.
*/
- for (chPtr = statePtr->chPtr;
- chPtr != (ChannelHandler *) NULL;
- chPtr = chNext) {
- chNext = chPtr->nextPtr;
- ckfree((char *) chPtr);
+ for (chPtr = statePtr->chPtr; chPtr != NULL; chPtr = chNext) {
+ chNext = chPtr->nextPtr;
+ ckfree((char *) chPtr);
}
- statePtr->chPtr = (ChannelHandler *) NULL;
+ statePtr->chPtr = NULL;
/*
* Cancel any pending copy operation.
@@ -2771,14 +3148,12 @@ Tcl_ClearChannelHandlers (channel)
* Remove any EventScript records for this channel.
*/
- for (ePtr = statePtr->scriptRecordPtr;
- ePtr != (EventScriptRecord *) NULL;
- ePtr = eNextPtr) {
- eNextPtr = ePtr->nextPtr;
- Tcl_DecrRefCount(ePtr->scriptPtr);
- ckfree((char *) ePtr);
+ for (ePtr = statePtr->scriptRecordPtr; ePtr != NULL; ePtr = eNextPtr) {
+ eNextPtr = ePtr->nextPtr;
+ TclDecrRefCount(ePtr->scriptPtr);
+ ckfree((char *) ePtr);
}
- statePtr->scriptRecordPtr = (EventScriptRecord *) NULL;
+ statePtr->scriptRecordPtr = NULL;
}
/*
@@ -2786,11 +3161,11 @@ Tcl_ClearChannelHandlers (channel)
*
* Tcl_Write --
*
- * Puts a sequence of bytes into an output buffer, may queue the
- * buffer for output if it gets full, and also remembers whether the
- * current buffer is ready e.g. if it contains a newline and we are in
- * line buffering mode. Compensates stacking, i.e. will redirect the
- * data from the specified channel to the topmost channel in a stack.
+ * Puts a sequence of bytes into an output buffer, may queue the buffer
+ * for output if it gets full, and also remembers whether the current
+ * buffer is ready e.g. if it contains a newline and we are in line
+ * buffering mode. Compensates stacking, i.e. will redirect the data from
+ * the specified channel to the topmost channel in a stack.
*
* No encoding conversions are applied to the bytes being read.
*
@@ -2806,27 +3181,28 @@ Tcl_ClearChannelHandlers (channel)
*/
int
-Tcl_Write(chan, src, srcLen)
- Tcl_Channel chan; /* The channel to buffer output for. */
- CONST char *src; /* Data to queue in output buffer. */
- int srcLen; /* Length of data in bytes, or < 0 for
- * strlen(). */
+Tcl_Write(
+ Tcl_Channel chan, /* The channel to buffer output for. */
+ const char *src, /* Data to queue in output buffer. */
+ int srcLen) /* Length of data in bytes, or < 0 for
+ * strlen(). */
{
/*
* Always use the topmost channel of the stack
*/
+
Channel *chanPtr;
- ChannelState *statePtr; /* state info for channel */
+ ChannelState *statePtr; /* State info for channel */
statePtr = ((Channel *) chan)->state;
- chanPtr = statePtr->topChanPtr;
+ chanPtr = statePtr->topChanPtr;
if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) {
return -1;
}
if (srcLen < 0) {
- srcLen = strlen(src);
+ srcLen = strlen(src);
}
return DoWrite(chanPtr, src, srcLen);
}
@@ -2836,11 +3212,11 @@ Tcl_Write(chan, src, srcLen)
*
* Tcl_WriteRaw --
*
- * Puts a sequence of bytes into an output buffer, may queue the
- * buffer for output if it gets full, and also remembers whether the
- * current buffer is ready e.g. if it contains a newline and we are in
- * line buffering mode. Writes directly to the driver of the channel,
- * does not compensate for stacking.
+ * Puts a sequence of bytes into an output buffer, may queue the buffer
+ * for output if it gets full, and also remembers whether the current
+ * buffer is ready e.g. if it contains a newline and we are in line
+ * buffering mode. Writes directly to the driver of the channel, does not
+ * compensate for stacking.
*
* No encoding conversions are applied to the bytes being read.
*
@@ -2856,14 +3232,15 @@ Tcl_Write(chan, src, srcLen)
*/
int
-Tcl_WriteRaw(chan, src, srcLen)
- Tcl_Channel chan; /* The channel to buffer output for. */
- CONST char *src; /* Data to queue in output buffer. */
- int srcLen; /* Length of data in bytes, or < 0 for
- * strlen(). */
+Tcl_WriteRaw(
+ Tcl_Channel chan, /* The channel to buffer output for. */
+ const char *src, /* Data to queue in output buffer. */
+ int srcLen) /* Length of data in bytes, or < 0 for
+ * strlen(). */
{
Channel *chanPtr = ((Channel *) chan);
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
int errorCode, written;
if (CheckChannelErrors(statePtr, TCL_WRITABLE | CHANNEL_RAW_MODE) != 0) {
@@ -2871,7 +3248,7 @@ Tcl_WriteRaw(chan, src, srcLen)
}
if (srcLen < 0) {
- srcLen = strlen(src);
+ srcLen = strlen(src);
}
/*
@@ -2895,11 +3272,11 @@ Tcl_WriteRaw(chan, src, srcLen)
* Tcl_WriteChars --
*
* Takes a sequence of UTF-8 characters and converts them for output
- * using the channel's current encoding, may queue the buffer for
- * output if it gets full, and also remembers whether the current
- * buffer is ready e.g. if it contains a newline and we are in
- * line buffering mode. Compensates stacking, i.e. will redirect the
- * data from the specified channel to the topmost channel in a stack.
+ * using the channel's current encoding, may queue the buffer for output
+ * if it gets full, and also remembers whether the current buffer is
+ * ready e.g. if it contains a newline and we are in line buffering
+ * mode. Compensates stacking, i.e. will redirect the data from the
+ * specified channel to the topmost channel in a stack.
*
* Results:
* The number of bytes written or -1 in case of error. If -1,
@@ -2913,13 +3290,14 @@ Tcl_WriteRaw(chan, src, srcLen)
*/
int
-Tcl_WriteChars(chan, src, len)
- Tcl_Channel chan; /* The channel to buffer output for. */
- CONST char *src; /* UTF-8 characters to queue in output buffer. */
- int len; /* Length of string in bytes, or < 0 for
+Tcl_WriteChars(
+ Tcl_Channel chan, /* The channel to buffer output for. */
+ const char *src, /* UTF-8 characters to queue in output
+ * buffer. */
+ int len) /* Length of string in bytes, or < 0 for
* strlen(). */
{
- ChannelState *statePtr; /* state info for channel */
+ ChannelState *statePtr; /* State info for channel */
statePtr = ((Channel *) chan)->state;
@@ -2927,7 +3305,7 @@ Tcl_WriteChars(chan, src, len)
return -1;
}
- return DoWriteChars ((Channel*) chan, src, len);
+ return DoWriteChars((Channel *) chan, src, len);
}
/*
@@ -2936,11 +3314,11 @@ Tcl_WriteChars(chan, src, len)
* DoWriteChars --
*
* Takes a sequence of UTF-8 characters and converts them for output
- * using the channel's current encoding, may queue the buffer for
- * output if it gets full, and also remembers whether the current
- * buffer is ready e.g. if it contains a newline and we are in
- * line buffering mode. Compensates stacking, i.e. will redirect the
- * data from the specified channel to the topmost channel in a stack.
+ * using the channel's current encoding, may queue the buffer for output
+ * if it gets full, and also remembers whether the current buffer is
+ * ready e.g. if it contains a newline and we are in line buffering mode.
+ * Compensates stacking, i.e. will redirect the data from the specified
+ * channel to the topmost channel in a stack.
*
* Results:
* The number of bytes written or -1 in case of error. If -1,
@@ -2954,36 +3332,43 @@ Tcl_WriteChars(chan, src, len)
*/
static int
-DoWriteChars(chanPtr, src, len)
- Channel* chanPtr; /* The channel to buffer output for. */
- CONST char *src; /* UTF-8 characters to queue in output buffer. */
- int len; /* Length of string in bytes, or < 0 for
+DoWriteChars(
+ Channel *chanPtr, /* The channel to buffer output for. */
+ const char *src, /* UTF-8 characters to queue in output
+ * buffer. */
+ int len) /* Length of string in bytes, or < 0 for
* strlen(). */
{
/*
* Always use the topmost channel of the stack
*/
- ChannelState *statePtr; /* state info for channel */
+
+ ChannelState *statePtr; /* State info for channel */
statePtr = chanPtr->state;
- chanPtr = statePtr->topChanPtr;
+ chanPtr = statePtr->topChanPtr;
if (len < 0) {
- len = strlen(src);
+ len = strlen(src);
}
if (statePtr->encoding == NULL) {
/*
- * Inefficient way to convert UTF-8 to byte-array, but the
- * code parallels the way it is done for objects.
+ * Inefficient way to convert UTF-8 to byte-array, but the code
+ * parallels the way it is done for objects.
+ * Special case for 1-byte (used by eg [puts] for the \n) could
+ * be extended to more efficient translation of the src string.
*/
- Tcl_Obj *objPtr;
- int result;
+ int result;
- objPtr = Tcl_NewStringObj(src, len);
- src = (char *) Tcl_GetByteArrayFromObj(objPtr, &len);
- result = WriteBytes(chanPtr, src, len);
- Tcl_DecrRefCount(objPtr);
+ if ((len == 1) && (UCHAR(*src) < 0xC0)) {
+ result = WriteBytes(chanPtr, src, len);
+ } else {
+ Tcl_Obj *objPtr = Tcl_NewStringObj(src, len);
+ src = (char *) Tcl_GetByteArrayFromObj(objPtr, &len);
+ result = WriteBytes(chanPtr, src, len);
+ TclDecrRefCount(objPtr);
+ }
return result;
}
return WriteChars(chanPtr, src, len);
@@ -2994,17 +3379,17 @@ DoWriteChars(chanPtr, src, len)
*
* Tcl_WriteObj --
*
- * Takes the Tcl object and queues its contents for output. If the
- * encoding of the channel is NULL, takes the byte-array representation
- * of the object and queues those bytes for output. Otherwise, takes
- * the characters in the UTF-8 (string) representation of the object
- * and converts them for output using the channel's current encoding.
- * May flush internal buffers to output if one becomes full or is ready
- * for some other reason, e.g. if it contains a newline and the channel
- * is in line buffering mode.
+ * Takes the Tcl object and queues its contents for output. If the
+ * encoding of the channel is NULL, takes the byte-array representation
+ * of the object and queues those bytes for output. Otherwise, takes the
+ * characters in the UTF-8 (string) representation of the object and
+ * converts them for output using the channel's current encoding. May
+ * flush internal buffers to output if one becomes full or is ready for
+ * some other reason, e.g. if it contains a newline and the channel is in
+ * line buffering mode.
*
* Results:
- * The number of bytes written or -1 in case of error. If -1,
+ * The number of bytes written or -1 in case of error. If -1,
* Tcl_GetErrno() will return the error code.
*
* Side effects:
@@ -3015,20 +3400,21 @@ DoWriteChars(chanPtr, src, len)
*/
int
-Tcl_WriteObj(chan, objPtr)
- Tcl_Channel chan; /* The channel to buffer output for. */
- Tcl_Obj *objPtr; /* The object to write. */
+Tcl_WriteObj(
+ Tcl_Channel chan, /* The channel to buffer output for. */
+ Tcl_Obj *objPtr) /* The object to write. */
{
/*
* Always use the topmost channel of the stack
*/
+
Channel *chanPtr;
- ChannelState *statePtr; /* state info for channel */
+ ChannelState *statePtr; /* State info for channel */
char *src;
int srcLen;
statePtr = ((Channel *) chan)->state;
- chanPtr = statePtr->topChanPtr;
+ chanPtr = statePtr->topChanPtr;
if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) {
return -1;
@@ -3037,7 +3423,7 @@ Tcl_WriteObj(chan, objPtr)
src = (char *) Tcl_GetByteArrayFromObj(objPtr, &srcLen);
return WriteBytes(chanPtr, src, srcLen);
} else {
- src = Tcl_GetStringFromObj(objPtr, &srcLen);
+ src = TclGetStringFromObj(objPtr, &srcLen);
return WriteChars(chanPtr, src, srcLen);
}
}
@@ -3047,10 +3433,10 @@ Tcl_WriteObj(chan, objPtr)
*
* WriteBytes --
*
- * Write a sequence of bytes into an output buffer, may queue the
- * buffer for output if it gets full, and also remembers whether the
- * current buffer is ready e.g. if it contains a newline and we are in
- * line buffering mode.
+ * Write a sequence of bytes into an output buffer, may queue the buffer
+ * for output if it gets full, and also remembers whether the current
+ * buffer is ready e.g. if it contains a newline and we are in line
+ * buffering mode.
*
* Results:
* The number of bytes written or -1 in case of error. If -1,
@@ -3064,33 +3450,36 @@ Tcl_WriteObj(chan, objPtr)
*/
static int
-WriteBytes(chanPtr, src, srcLen)
- Channel *chanPtr; /* The channel to buffer output for. */
- CONST char *src; /* Bytes to write. */
- int srcLen; /* Number of bytes to write. */
+WriteBytes(
+ Channel *chanPtr, /* The channel to buffer output for. */
+ const char *src, /* Bytes to write. */
+ int srcLen) /* Number of bytes to write. */
{
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
ChannelBuffer *bufPtr;
char *dst;
- int dstMax, sawLF, savedLF, total, dstLen, toWrite;
-
+ int dstMax, sawLF, savedLF, total, dstLen, toWrite, translate;
+
total = 0;
sawLF = 0;
savedLF = 0;
+ translate = (statePtr->flags & CHANNEL_LINEBUFFERED)
+ || (statePtr->outputTranslation != TCL_TRANSLATE_LF);
/*
- * Loop over all bytes in src, storing them in output buffer with
- * proper EOL translation.
+ * Loop over all bytes in src, storing them in output buffer with proper
+ * EOL translation.
*/
while (srcLen + savedLF > 0) {
bufPtr = statePtr->curOutPtr;
if (bufPtr == NULL) {
bufPtr = AllocChannelBuffer(statePtr->bufSize);
- statePtr->curOutPtr = bufPtr;
+ statePtr->curOutPtr = bufPtr;
}
- dst = bufPtr->buf + bufPtr->nextAdded;
- dstMax = bufPtr->bufLength - bufPtr->nextAdded;
+ dst = InsertPoint(bufPtr);
+ dstMax = SpaceLeft(bufPtr);
dstLen = dstMax;
toWrite = dstLen;
@@ -3098,25 +3487,32 @@ WriteBytes(chanPtr, src, srcLen)
toWrite = srcLen;
}
- if (savedLF) {
- /*
- * A '\n' was left over from last call to TranslateOutputEOL()
- * and we need to store it in this buffer. If the channel is
- * line-based, we will need to flush it.
- */
+ if (translate) {
+ if (savedLF) {
+ /*
+ * A '\n' was left over from last call to TranslateOutputEOL()
+ * and we need to store it in this buffer. If the channel is
+ * line-based, we will need to flush it.
+ */
- *dst++ = '\n';
- dstLen--;
- sawLF++;
+ *dst++ = '\n';
+ dstLen--;
+ sawLF++;
+ }
+ if (TranslateOutputEOL(statePtr, dst, src, &dstLen, &toWrite)) {
+ sawLF++;
+ }
+ dstLen += savedLF;
+ savedLF = 0;
+ if (dstLen > dstMax) {
+ savedLF = 1;
+ dstLen = dstMax;
+ }
+ } else {
+ memcpy(dst, src, toWrite);
+ dstLen = toWrite;
}
- sawLF += TranslateOutputEOL(statePtr, dst, src, &dstLen, &toWrite);
- dstLen += savedLF;
- savedLF = 0;
- if (dstLen > dstMax) {
- savedLF = 1;
- dstLen = dstMax;
- }
bufPtr->nextAdded += dstLen;
if (CheckFlush(chanPtr, bufPtr, sawLF) != 0) {
return -1;
@@ -3134,11 +3530,10 @@ WriteBytes(chanPtr, src, srcLen)
*
* WriteChars --
*
- * Convert UTF-8 bytes to the channel's external encoding and
- * write the produced bytes into an output buffer, may queue the
- * buffer for output if it gets full, and also remembers whether the
- * current buffer is ready e.g. if it contains a newline and we are in
- * line buffering mode.
+ * Convert UTF-8 bytes to the channel's external encoding and write the
+ * produced bytes into an output buffer, may queue the buffer for output
+ * if it gets full, and also remembers whether the current buffer is
+ * ready e.g. if it contains a newline and we are in line buffering mode.
*
* Results:
* The number of bytes written or -1 in case of error. If -1,
@@ -3152,20 +3547,21 @@ WriteBytes(chanPtr, src, srcLen)
*/
static int
-WriteChars(chanPtr, src, srcLen)
- Channel *chanPtr; /* The channel to buffer output for. */
- CONST char *src; /* UTF-8 string to write. */
- int srcLen; /* Length of UTF-8 string in bytes. */
+WriteChars(
+ Channel *chanPtr, /* The channel to buffer output for. */
+ const char *src, /* UTF-8 string to write. */
+ int srcLen) /* Length of UTF-8 string in bytes. */
{
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
ChannelBuffer *bufPtr;
char *dst, *stage;
int saved, savedLF, sawLF, total, dstLen, stageMax, dstWrote;
int stageLen, toWrite, stageRead, endEncoding, result;
- int consumedSomething;
+ int consumedSomething, translate;
Tcl_Encoding encoding;
char safe[BUFFER_PADDING];
-
+
total = 0;
sawLF = 0;
savedLF = 0;
@@ -3178,6 +3574,9 @@ WriteChars(chanPtr, src, srcLen)
endEncoding = ((statePtr->outputEncodingFlags & TCL_ENCODING_END) != 0);
+ translate = (statePtr->flags & CHANNEL_LINEBUFFERED)
+ || (statePtr->outputTranslation != TCL_TRANSLATE_LF);
+
/*
* Loop over all UTF-8 characters in src, storing them in staging buffer
* with proper EOL translation.
@@ -3185,7 +3584,7 @@ WriteChars(chanPtr, src, srcLen)
consumedSomething = 1;
while (consumedSomething && (srcLen + savedLF + endEncoding > 0)) {
- consumedSomething = 0;
+ consumedSomething = 0;
stage = statePtr->outputStage;
stageMax = statePtr->bufSize;
stageLen = stageMax;
@@ -3195,27 +3594,34 @@ WriteChars(chanPtr, src, srcLen)
toWrite = srcLen;
}
- if (savedLF) {
- /*
- * A '\n' was left over from last call to TranslateOutputEOL()
- * and we need to store it in the staging buffer. If the
- * channel is line-based, we will need to flush the output
- * buffer (after translating the staging buffer).
- */
-
- *stage++ = '\n';
- stageLen--;
- sawLF++;
- }
- sawLF += TranslateOutputEOL(statePtr, stage, src, &stageLen, &toWrite);
+ if (translate) {
+ if (savedLF) {
+ /*
+ * A '\n' was left over from last call to TranslateOutputEOL()
+ * and we need to store it in the staging buffer. If the channel
+ * is line-based, we will need to flush the output buffer (after
+ * translating the staging buffer).
+ */
- stage -= savedLF;
- stageLen += savedLF;
- savedLF = 0;
+ *stage++ = '\n';
+ stageLen--;
+ sawLF++;
+ }
+ if (TranslateOutputEOL(statePtr, stage, src, &stageLen, &toWrite)) {
+ sawLF++;
+ }
- if (stageLen > stageMax) {
- savedLF = 1;
- stageLen = stageMax;
+ stage -= savedLF;
+ stageLen += savedLF;
+ savedLF = 0;
+
+ if (stageLen > stageMax) {
+ savedLF = 1;
+ stageLen = stageMax;
+ }
+ } else {
+ memcpy(stage, src, toWrite);
+ stageLen = toWrite;
}
src += toWrite;
srcLen -= toWrite;
@@ -3231,17 +3637,16 @@ WriteChars(chanPtr, src, srcLen)
bufPtr = AllocChannelBuffer(statePtr->bufSize);
statePtr->curOutPtr = bufPtr;
}
- dst = bufPtr->buf + bufPtr->nextAdded;
- dstLen = bufPtr->bufLength - bufPtr->nextAdded;
+ dst = InsertPoint(bufPtr);
+ dstLen = SpaceLeft(bufPtr);
if (saved != 0) {
/*
- * Here's some translated bytes left over from the last
- * buffer that we need to stick at the beginning of this
- * buffer.
+ * Here's some translated bytes left over from the last buffer
+ * that we need to stick at the beginning of this buffer.
*/
-
- memcpy((VOID *) dst, (VOID *) safe, (size_t) saved);
+
+ memcpy(dst, safe, (size_t) saved);
bufPtr->nextAdded += saved;
dst += saved;
dstLen -= saved;
@@ -3253,7 +3658,8 @@ WriteChars(chanPtr, src, srcLen)
&statePtr->outputEncodingState, dst,
dstLen + BUFFER_PADDING, &stageRead, &dstWrote, NULL);
- /* Fix for SF #506297, reported by Martin Forssen
+ /*
+ * Fix for SF #506297, reported by Martin Forssen
* <ruric@users.sourceforge.net>.
*
* The encoding chosen in the script exposing the bug writes out
@@ -3269,13 +3675,15 @@ WriteChars(chanPtr, src, srcLen)
*/
statePtr->outputEncodingFlags &= ~TCL_ENCODING_START;
+
/*
* The following code must be executed only when result is not 0.
*/
- if (result && ((stageRead + dstWrote) == 0)) {
+
+ if ((result != 0) && (stageRead + dstWrote == 0)) {
/*
* We have an incomplete UTF-8 character at the end of the
- * staging buffer. It will get moved to the beginning of the
+ * staging buffer. It will get moved to the beginning of the
* staging buffer followed by more bytes from src.
*/
@@ -3286,18 +3694,17 @@ WriteChars(chanPtr, src, srcLen)
break;
}
bufPtr->nextAdded += dstWrote;
- if (bufPtr->nextAdded > bufPtr->bufLength) {
+ if (IsBufferOverflowing(bufPtr)) {
/*
* When translating from UTF-8 to external encoding, we
- * allowed the translation to produce a character that
- * crossed the end of the output buffer, so that we would
- * get a completely full buffer before flushing it. The
- * extra bytes will be moved to the beginning of the next
- * buffer.
+ * allowed the translation to produce a character that crossed
+ * the end of the output buffer, so that we would get a
+ * completely full buffer before flushing it. The extra bytes
+ * will be moved to the beginning of the next buffer.
*/
- saved = bufPtr->nextAdded - bufPtr->bufLength;
- memcpy((VOID *) safe, (VOID *) (dst + dstLen), (size_t) saved);
+ saved = -SpaceLeft(bufPtr);
+ memcpy(safe, dst + dstLen, (size_t) saved);
bufPtr->nextAdded = bufPtr->bufLength;
}
if (CheckFlush(chanPtr, bufPtr, sawLF) != 0) {
@@ -3323,13 +3730,14 @@ WriteChars(chanPtr, src, srcLen)
}
}
- /* If nothing was written and it happened because there was no progress
- * in the UTF conversion, we throw an error.
+ /*
+ * If nothing was written and it happened because there was no progress in
+ * the UTF conversion, we throw an error.
*/
if (!consumedSomething && (total == 0)) {
- Tcl_SetErrno (EINVAL);
- return -1;
+ Tcl_SetErrno(EINVAL);
+ return -1;
}
return total;
}
@@ -3339,125 +3747,120 @@ WriteChars(chanPtr, src, srcLen)
*
* TranslateOutputEOL --
*
- * Helper function for WriteBytes() and WriteChars(). Converts the
- * '\n' characters in the source buffer into the appropriate EOL
- * form specified by the output translation mode.
+ * Helper function for WriteBytes() and WriteChars(). Converts the '\n'
+ * characters in the source buffer into the appropriate EOL form
+ * specified by the output translation mode.
*
- * EOL translation stops either when the source buffer is empty
- * or the output buffer is full.
+ * EOL translation stops either when the source buffer is empty or the
+ * output buffer is full.
*
- * When converting to CRLF mode and there is only 1 byte left in
- * the output buffer, this routine stores the '\r' in the last
- * byte and then stores the '\n' in the byte just past the end of the
- * buffer. The caller is responsible for passing in a buffer that
- * is large enough to hold the extra byte.
+ * When converting to CRLF mode and there is only 1 byte left in the
+ * output buffer, this routine stores the '\r' in the last byte and then
+ * stores the '\n' in the byte just past the end of the buffer. The
+ * caller is responsible for passing in a buffer that is large enough to
+ * hold the extra byte.
*
* Results:
- * The return value is 1 if a '\n' was translated from the source
- * buffer, or 0 otherwise -- this can be used by the caller to
- * decide to flush a line-based channel even though the channel
- * buffer is not full.
+ * The return value is 1 if a '\n' was translated from the source buffer,
+ * or 0 otherwise -- this can be used by the caller to decide to flush a
+ * line-based channel even though the channel buffer is not full.
*
- * *dstLenPtr is filled with how many bytes of the output buffer
- * were used. As mentioned above, this can be one more that
- * the output buffer's specified length if a CRLF was stored.
+ * *dstLenPtr is filled with how many bytes of the output buffer were
+ * used. As mentioned above, this can be one more that the output
+ * buffer's specified length if a CRLF was stored.
*
- * *srcLenPtr is filled with how many bytes of the source buffer
- * were consumed.
+ * *srcLenPtr is filled with how many bytes of the source buffer were
+ * consumed.
*
* Side effects:
- * It may be obvious, but bears mentioning that when converting
- * in CRLF mode (which requires two bytes of storage in the output
- * buffer), the number of bytes consumed from the source buffer
- * will be less than the number of bytes stored in the output buffer.
+ * It may be obvious, but bears mentioning that when converting in CRLF
+ * mode (which requires two bytes of storage in the output buffer), the
+ * number of bytes consumed from the source buffer will be less than the
+ * number of bytes stored in the output buffer.
*
*---------------------------------------------------------------------------
*/
static int
-TranslateOutputEOL(statePtr, dst, src, dstLenPtr, srcLenPtr)
- ChannelState *statePtr; /* Channel being read, for translation and
+TranslateOutputEOL(
+ ChannelState *statePtr, /* Channel being read, for translation and
* buffering modes. */
- char *dst; /* Output buffer filled with UTF-8 chars by
+ char *dst, /* Output buffer filled with UTF-8 chars by
* applying appropriate EOL translation to
* source characters. */
- CONST char *src; /* Source UTF-8 characters. */
- int *dstLenPtr; /* On entry, the maximum length of output
- * buffer in bytes. On exit, the number of
+ const char *src, /* Source UTF-8 characters. */
+ int *dstLenPtr, /* On entry, the maximum length of output
+ * buffer in bytes. On exit, the number of
* bytes actually used in output buffer. */
- int *srcLenPtr; /* On entry, the length of source buffer.
- * On exit, the number of bytes read from
- * the source buffer. */
+ int *srcLenPtr) /* On entry, the length of source buffer. On
+ * exit, the number of bytes read from the
+ * source buffer. */
{
char *dstEnd;
int srcLen, newlineFound;
-
+
newlineFound = 0;
srcLen = *srcLenPtr;
switch (statePtr->outputTranslation) {
- case TCL_TRANSLATE_LF: {
- for (dstEnd = dst + srcLen; dst < dstEnd; ) {
- if (*src == '\n') {
- newlineFound = 1;
- }
- *dst++ = *src++;
+ case TCL_TRANSLATE_LF:
+ for (dstEnd = dst + srcLen; dst < dstEnd; ) {
+ if (*src == '\n') {
+ newlineFound = 1;
}
- *dstLenPtr = srcLen;
- break;
- }
- case TCL_TRANSLATE_CR: {
- for (dstEnd = dst + srcLen; dst < dstEnd;) {
- if (*src == '\n') {
- *dst++ = '\r';
- newlineFound = 1;
- src++;
- } else {
- *dst++ = *src++;
- }
+ *dst++ = *src++;
+ }
+ *dstLenPtr = srcLen;
+ break;
+ case TCL_TRANSLATE_CR:
+ for (dstEnd = dst + srcLen; dst < dstEnd;) {
+ if (*src == '\n') {
+ *dst++ = '\r';
+ newlineFound = 1;
+ src++;
+ } else {
+ *dst++ = *src++;
}
- *dstLenPtr = srcLen;
- break;
}
- case TCL_TRANSLATE_CRLF: {
- /*
- * Since this causes the number of bytes to grow, we
- * start off trying to put 'srcLen' bytes into the
- * output buffer, but allow it to store more bytes, as
- * long as there's still source bytes and room in the
- * output buffer.
- */
+ *dstLenPtr = srcLen;
+ break;
+ case TCL_TRANSLATE_CRLF: {
+ /*
+ * Since this causes the number of bytes to grow, we start off trying
+ * to put 'srcLen' bytes into the output buffer, but allow it to store
+ * more bytes, as long as there's still source bytes and room in the
+ * output buffer.
+ */
- char *dstStart, *dstMax;
- CONST char *srcStart;
-
- dstStart = dst;
- dstMax = dst + *dstLenPtr;
+ char *dstStart, *dstMax;
+ const char *srcStart;
- srcStart = src;
-
- if (srcLen < *dstLenPtr) {
- dstEnd = dst + srcLen;
- } else {
- dstEnd = dst + *dstLenPtr;
- }
- while (dst < dstEnd) {
- if (*src == '\n') {
- if (dstEnd < dstMax) {
- dstEnd++;
- }
- *dst++ = '\r';
- newlineFound = 1;
+ dstStart = dst;
+ dstMax = dst + *dstLenPtr;
+
+ srcStart = src;
+
+ if (srcLen < *dstLenPtr) {
+ dstEnd = dst + srcLen;
+ } else {
+ dstEnd = dst + *dstLenPtr;
+ }
+ while (dst < dstEnd) {
+ if (*src == '\n') {
+ if (dstEnd < dstMax) {
+ dstEnd++;
}
- *dst++ = *src++;
+ *dst++ = '\r';
+ newlineFound = 1;
}
- *srcLenPtr = src - srcStart;
- *dstLenPtr = dst - dstStart;
- break;
- }
- default: {
- break;
+ *dst++ = *src++;
}
+ *srcLenPtr = src - srcStart;
+ *dstLenPtr = dst - dstStart;
+ break;
+ }
+ default:
+ break;
}
return newlineFound;
}
@@ -3467,12 +3870,12 @@ TranslateOutputEOL(statePtr, dst, src, dstLenPtr, srcLenPtr)
*
* CheckFlush --
*
- * Helper function for WriteBytes() and WriteChars(). If the
- * channel buffer is ready to be flushed, flush it.
+ * Helper function for WriteBytes() and WriteChars(). If the channel
+ * buffer is ready to be flushed, flush it.
*
* Results:
- * The return value is -1 if there was a problem flushing the
- * channel buffer, or 0 otherwise.
+ * The return value is -1 if there was a problem flushing the channel
+ * buffer, or 0 otherwise.
*
* Side effects:
* The buffer will be recycled if it is flushed.
@@ -3481,13 +3884,15 @@ TranslateOutputEOL(statePtr, dst, src, dstLenPtr, srcLenPtr)
*/
static int
-CheckFlush(chanPtr, bufPtr, newlineFlag)
- Channel *chanPtr; /* Channel being read, for buffering mode. */
- ChannelBuffer *bufPtr; /* Channel buffer to possibly flush. */
- int newlineFlag; /* Non-zero if a the channel buffer
- * contains a newline. */
+CheckFlush(
+ Channel *chanPtr, /* Channel being read, for buffering mode. */
+ ChannelBuffer *bufPtr, /* Channel buffer to possibly flush. */
+ int newlineFlag) /* Non-zero if a the channel buffer contains a
+ * newline. */
{
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
+
/*
* The current buffer is ready for output:
* 1. if it is full.
@@ -3496,14 +3901,14 @@ CheckFlush(chanPtr, bufPtr, newlineFlag)
*/
if ((statePtr->flags & BUFFER_READY) == 0) {
- if (bufPtr->nextAdded == bufPtr->bufLength) {
- statePtr->flags |= BUFFER_READY;
+ if (IsBufferFull(bufPtr)) {
+ SetFlag(statePtr, BUFFER_READY);
} else if (statePtr->flags & CHANNEL_LINEBUFFERED) {
if (newlineFlag != 0) {
- statePtr->flags |= BUFFER_READY;
+ SetFlag(statePtr, BUFFER_READY);
}
} else if (statePtr->flags & CHANNEL_UNBUFFERED) {
- statePtr->flags |= BUFFER_READY;
+ SetFlag(statePtr, BUFFER_READY);
}
}
if (statePtr->flags & BUFFER_READY) {
@@ -3527,17 +3932,17 @@ CheckFlush(chanPtr, bufPtr, newlineFlag)
* error or condition that occurred.
*
* Side effects:
- * May flush output on the channel. May cause input to be consumed
- * from the channel.
+ * May flush output on the channel. May cause input to be consumed from
+ * the channel.
*
*---------------------------------------------------------------------------
*/
int
-Tcl_Gets(chan, lineRead)
- Tcl_Channel chan; /* Channel from which to read. */
- Tcl_DString *lineRead; /* The line read will be appended to this
- * DString as UTF-8 characters. The caller
+Tcl_Gets(
+ Tcl_Channel chan, /* Channel from which to read. */
+ Tcl_DString *lineRead) /* The line read will be appended to this
+ * DString as UTF-8 characters. The caller
* must have initialized it and is responsible
* for managing the storage. */
{
@@ -3545,13 +3950,13 @@ Tcl_Gets(chan, lineRead)
int charsStored, length;
char *string;
- objPtr = Tcl_NewObj();
+ TclNewObj(objPtr);
charsStored = Tcl_GetsObj(chan, objPtr);
if (charsStored > 0) {
- string = Tcl_GetStringFromObj(objPtr, &length);
+ string = TclGetStringFromObj(objPtr, &length);
Tcl_DStringAppend(lineRead, string, length);
}
- Tcl_DecrRefCount(objPtr);
+ TclDecrRefCount(objPtr);
return charsStored;
}
@@ -3561,60 +3966,71 @@ Tcl_Gets(chan, lineRead)
* Tcl_GetsObj --
*
* Accumulate input from the input channel until end-of-line or
- * end-of-file has been seen. Bytes read from the input channel
- * are converted to UTF-8 using the encoding specified by the
- * channel.
+ * end-of-file has been seen. Bytes read from the input channel are
+ * converted to UTF-8 using the encoding specified by the channel.
*
* Results:
* Number of characters accumulated in the object or -1 if error,
- * blocked, or EOF. If -1, use Tcl_GetErrno() to retrieve the
- * POSIX error code for the error or condition that occurred.
+ * blocked, or EOF. If -1, use Tcl_GetErrno() to retrieve the POSIX error
+ * code for the error or condition that occurred.
*
* Side effects:
* Consumes input from the channel.
*
- * On reading EOF, leave channel pointing at EOF char.
- * On reading EOL, leave channel pointing after EOL, but don't
- * return EOL in dst buffer.
+ * On reading EOF, leave channel pointing at EOF char. On reading EOL,
+ * leave channel pointing after EOL, but don't return EOL in dst buffer.
*
*---------------------------------------------------------------------------
*/
int
-Tcl_GetsObj(chan, objPtr)
- Tcl_Channel chan; /* Channel from which to read. */
- Tcl_Obj *objPtr; /* The line read will be appended to this
+Tcl_GetsObj(
+ Tcl_Channel chan, /* Channel from which to read. */
+ Tcl_Obj *objPtr) /* The line read will be appended to this
* object as UTF-8 characters. */
{
GetsState gs;
Channel *chanPtr = (Channel *) chan;
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
ChannelBuffer *bufPtr;
int inEofChar, skip, copiedTotal, oldLength, oldFlags, oldRemoved;
Tcl_Encoding encoding;
char *dst, *dstEnd, *eol, *eof;
Tcl_EncodingState oldState;
+ if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) {
+ copiedTotal = -1;
+ goto done;
+ }
+
+ /*
+ * A binary version of Tcl_GetsObj. This could also handle encodings that
+ * are ascii-7 pure (iso8859, utf-8, ...) with a final encoding conversion
+ * done on objPtr.
+ */
+
+ if ((statePtr->encoding == NULL)
+ && ((statePtr->inputTranslation == TCL_TRANSLATE_LF)
+ || (statePtr->inputTranslation == TCL_TRANSLATE_CR))) {
+ return TclGetsObjBinary(chan, objPtr);
+ }
+
/*
* This operation should occur at the top of a channel stack.
*/
chanPtr = statePtr->topChanPtr;
- if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) {
- copiedTotal = -1;
- goto done;
- }
-
bufPtr = statePtr->inQueueHead;
encoding = statePtr->encoding;
/*
- * Preserved so we can restore the channel's state in case we don't
- * find a newline in the available input.
+ * Preserved so we can restore the channel's state in case we don't find a
+ * newline in the available input.
*/
- Tcl_GetStringFromObj(objPtr, &oldLength);
+ TclGetStringFromObj(objPtr, &oldLength);
oldFlags = statePtr->inputEncodingFlags;
oldState = statePtr->inputEncodingState;
oldRemoved = BUFFER_PADDING;
@@ -3624,17 +4040,25 @@ Tcl_GetsObj(chan, objPtr)
/*
* If there is no encoding, use "iso8859-1" -- Tcl_GetsObj() doesn't
- * produce ByteArray objects. To avoid circularity problems,
- * "iso8859-1" is builtin to Tcl.
+ * produce ByteArray objects.
*/
if (encoding == NULL) {
- encoding = Tcl_GetEncoding(NULL, "iso8859-1");
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ if (tsdPtr->binaryEncoding == NULL) {
+ tsdPtr->binaryEncoding = Tcl_GetEncoding(NULL, "iso8859-1");
+ Tcl_CreateThreadExitHandler(FreeBinaryEncoding, NULL);
+ }
+ encoding = tsdPtr->binaryEncoding;
+ if (encoding == NULL) {
+ Tcl_Panic("attempted gets on binary channel where no iso8859-1 encoding available");
+ }
}
/*
- * Object used by FilterInputBytes to keep track of how much data has
- * been consumed from the channel buffers.
+ * Object used by FilterInputBytes to keep track of how much data has been
+ * consumed from the channel buffers.
*/
gs.objPtr = objPtr;
@@ -3661,10 +4085,10 @@ Tcl_GetsObj(chan, objPtr)
}
dstEnd = dst + gs.bytesWrote;
}
-
+
/*
- * Remember if EOF char is seen, then look for EOL anyhow, because
- * the EOL might be before the EOF char.
+ * Remember if EOF char is seen, then look for EOL anyhow, because the
+ * EOL might be before the EOF char.
*/
if (inEofChar != '\0') {
@@ -3683,31 +4107,37 @@ Tcl_GetsObj(chan, objPtr)
*/
switch (statePtr->inputTranslation) {
- case TCL_TRANSLATE_LF: {
- for (eol = dst; eol < dstEnd; eol++) {
- if (*eol == '\n') {
- skip = 1;
- goto goteol;
- }
+ case TCL_TRANSLATE_LF:
+ for (eol = dst; eol < dstEnd; eol++) {
+ if (*eol == '\n') {
+ skip = 1;
+ goto gotEOL;
}
- break;
}
- case TCL_TRANSLATE_CR: {
- for (eol = dst; eol < dstEnd; eol++) {
- if (*eol == '\r') {
- skip = 1;
- goto goteol;
- }
+ break;
+ case TCL_TRANSLATE_CR:
+ for (eol = dst; eol < dstEnd; eol++) {
+ if (*eol == '\r') {
+ skip = 1;
+ goto gotEOL;
}
- break;
}
- case TCL_TRANSLATE_CRLF: {
- for (eol = dst; eol < dstEnd; eol++) {
- if (*eol == '\r') {
- eol++;
- if (eol >= dstEnd) {
- int offset;
-
+ break;
+ case TCL_TRANSLATE_CRLF:
+ for (eol = dst; eol < dstEnd; eol++) {
+ if (*eol == '\r') {
+ eol++;
+
+ /*
+ * If a CR is at the end of the buffer, then check for a
+ * LF at the begining of the next buffer, unless EOF char
+ * was found already.
+ */
+
+ if (eol >= dstEnd) {
+ int offset;
+
+ if (eol != eof) {
offset = eol - objPtr->bytes;
dst = dstEnd;
if (FilterInputBytes(chanPtr, &gs) != 0) {
@@ -3715,88 +4145,89 @@ Tcl_GetsObj(chan, objPtr)
}
dstEnd = dst + gs.bytesWrote;
eol = objPtr->bytes + offset;
- if (eol >= dstEnd) {
- skip = 0;
- goto goteol;
- }
}
- if (*eol == '\n') {
- eol--;
- skip = 2;
- goto goteol;
+ if (eol >= dstEnd) {
+ skip = 0;
+ goto gotEOL;
}
}
+ if (*eol == '\n') {
+ eol--;
+ skip = 2;
+ goto gotEOL;
+ }
}
- break;
}
- case TCL_TRANSLATE_AUTO: {
- eol = dst;
- skip = 1;
- if (statePtr->flags & INPUT_SAW_CR) {
- statePtr->flags &= ~INPUT_SAW_CR;
- if (*eol == '\n') {
- /*
- * Skip the raw bytes that make up the '\n'.
- */
+ break;
+ case TCL_TRANSLATE_AUTO:
+ eol = dst;
+ skip = 1;
+ if (statePtr->flags & INPUT_SAW_CR) {
+ ResetFlag(statePtr, INPUT_SAW_CR);
+ if ((eol < dstEnd) && (*eol == '\n')) {
+ /*
+ * Skip the raw bytes that make up the '\n'.
+ */
- char tmp[1 + TCL_UTF_MAX];
- int rawRead;
-
- bufPtr = gs.bufPtr;
- Tcl_ExternalToUtf(NULL, gs.encoding,
- bufPtr->buf + bufPtr->nextRemoved,
- gs.rawRead, statePtr->inputEncodingFlags,
- &gs.state, tmp, 1 + TCL_UTF_MAX, &rawRead,
- NULL, NULL);
- bufPtr->nextRemoved += rawRead;
- gs.rawRead -= rawRead;
- gs.bytesWrote--;
- gs.charsWrote--;
- memmove(dst, dst + 1, (size_t) (dstEnd - dst));
- dstEnd--;
- }
+ char tmp[1 + TCL_UTF_MAX];
+ int rawRead;
+
+ bufPtr = gs.bufPtr;
+ Tcl_ExternalToUtf(NULL, gs.encoding, RemovePoint(bufPtr),
+ gs.rawRead, statePtr->inputEncodingFlags,
+ &gs.state, tmp, 1 + TCL_UTF_MAX, &rawRead, NULL,
+ NULL);
+ bufPtr->nextRemoved += rawRead;
+ gs.rawRead -= rawRead;
+ gs.bytesWrote--;
+ gs.charsWrote--;
+ memmove(dst, dst + 1, (size_t) (dstEnd - dst));
+ dstEnd--;
}
- for (eol = dst; eol < dstEnd; eol++) {
- if (*eol == '\r') {
- eol++;
- if (eol == dstEnd) {
- /*
- * If buffer ended on \r, peek ahead to see if a
- * \n is available.
- */
+ }
+ for (eol = dst; eol < dstEnd; eol++) {
+ if (*eol == '\r') {
+ eol++;
+ if (eol == dstEnd) {
+ /*
+ * If buffer ended on \r, peek ahead to see if a \n is
+ * available, unless EOF char was found already.
+ */
+ if (eol != eof) {
int offset;
-
+
offset = eol - objPtr->bytes;
dst = dstEnd;
PeekAhead(chanPtr, &dstEnd, &gs);
eol = objPtr->bytes + offset;
- if (eol >= dstEnd) {
- eol--;
- statePtr->flags |= INPUT_SAW_CR;
- goto goteol;
- }
}
- if (*eol == '\n') {
- skip++;
+
+ if (eol >= dstEnd) {
+ eol--;
+ SetFlag(statePtr, INPUT_SAW_CR);
+ goto gotEOL;
}
- eol--;
- goto goteol;
- } else if (*eol == '\n') {
- goto goteol;
}
+ if (*eol == '\n') {
+ skip++;
+ }
+ eol--;
+ goto gotEOL;
+ } else if (*eol == '\n') {
+ goto gotEOL;
}
}
}
if (eof != NULL) {
/*
- * EOF character was seen. On EOF, leave current file position
+ * EOF character was seen. On EOF, leave current file position
* pointing at the EOF character, but don't store the EOF
* character in the output string.
*/
dstEnd = eof;
- statePtr->flags |= (CHANNEL_EOF | CHANNEL_STICKY_EOF);
+ SetFlag(statePtr, CHANNEL_EOF | CHANNEL_STICKY_EOF);
statePtr->inputEncodingFlags |= TCL_ENCODING_END;
}
if (statePtr->flags & CHANNEL_EOF) {
@@ -3809,29 +4240,31 @@ Tcl_GetsObj(chan, objPtr)
*/
Tcl_SetObjLength(objPtr, oldLength);
- CommonGetsCleanup(chanPtr, encoding);
+ CommonGetsCleanup(chanPtr);
copiedTotal = -1;
goto done;
}
- goto goteol;
+ goto gotEOL;
}
dst = dstEnd;
}
/*
- * Found EOL or EOF, but the output buffer may now contain too many
- * UTF-8 characters. We need to know how many raw bytes correspond to
- * the number of UTF-8 characters we want, plus how many raw bytes
- * correspond to the character(s) making up EOL (if any), so we can
- * remove the correct number of bytes from the channel buffer.
+ * Found EOL or EOF, but the output buffer may now contain too many UTF-8
+ * characters. We need to know how many raw bytes correspond to the number
+ * of UTF-8 characters we want, plus how many raw bytes correspond to the
+ * character(s) making up EOL (if any), so we can remove the correct
+ * number of bytes from the channel buffer.
*/
-
- goteol:
+
+ gotEOL:
bufPtr = gs.bufPtr;
+ if (bufPtr == NULL) {
+ Tcl_Panic("Tcl_GetsObj: gotEOL reached with bufPtr==NULL");
+ }
statePtr->inputEncodingState = gs.state;
- Tcl_ExternalToUtf(NULL, gs.encoding, bufPtr->buf + bufPtr->nextRemoved,
- gs.rawRead, statePtr->inputEncodingFlags,
- &statePtr->inputEncodingState, dst,
+ Tcl_ExternalToUtf(NULL, gs.encoding, RemovePoint(bufPtr), gs.rawRead,
+ statePtr->inputEncodingFlags, &statePtr->inputEncodingState, dst,
eol - dst + skip + TCL_UTF_MAX, &gs.rawRead, NULL,
&gs.charsWrote);
bufPtr->nextRemoved += gs.rawRead;
@@ -3841,25 +4274,28 @@ Tcl_GetsObj(chan, objPtr)
*/
Tcl_SetObjLength(objPtr, eol - objPtr->bytes);
- CommonGetsCleanup(chanPtr, encoding);
- statePtr->flags &= ~CHANNEL_BLOCKED;
+ CommonGetsCleanup(chanPtr);
+ ResetFlag(statePtr, CHANNEL_BLOCKED);
copiedTotal = gs.totalChars + gs.charsWrote - skip;
goto done;
/*
- * Couldn't get a complete line. This only happens if we get a error
- * reading from the channel or we are non-blocking and there wasn't
- * an EOL or EOF in the data available.
+ * Couldn't get a complete line. This only happens if we get a error
+ * reading from the channel or we are non-blocking and there wasn't an EOL
+ * or EOF in the data available.
*/
- restore:
+ restore:
bufPtr = statePtr->inQueueHead;
+ if (bufPtr == NULL) {
+ Tcl_Panic("Tcl_GetsObj: restore reached with bufPtr==NULL");
+ }
bufPtr->nextRemoved = oldRemoved;
for (bufPtr = bufPtr->nextPtr; bufPtr != NULL; bufPtr = bufPtr->nextPtr) {
bufPtr->nextRemoved = BUFFER_PADDING;
}
- CommonGetsCleanup(chanPtr, encoding);
+ CommonGetsCleanup(chanPtr);
statePtr->inputEncodingState = oldState;
statePtr->inputEncodingFlags = oldFlags;
@@ -3867,66 +4303,336 @@ Tcl_GetsObj(chan, objPtr)
/*
* We didn't get a complete line so we need to indicate to UpdateInterest
- * that the gets blocked. It will wait for more data instead of firing
- * a timer, avoiding a busy wait. This is where we are assuming that the
- * next operation is a gets. No more file events will be delivered on
- * this channel until new data arrives or some operation is performed
- * on the channel (e.g. gets, read, fconfigure) that changes the blocking
- * state. Note that this means a file event will not be delivered even
- * though a read would be able to consume the buffered data.
+ * that the gets blocked. It will wait for more data instead of firing a
+ * timer, avoiding a busy wait. This is where we are assuming that the
+ * next operation is a gets. No more file events will be delivered on this
+ * channel until new data arrives or some operation is performed on the
+ * channel (e.g. gets, read, fconfigure) that changes the blocking state.
+ * Note that this means a file event will not be delivered even though a
+ * read would be able to consume the buffered data.
*/
- statePtr->flags |= CHANNEL_NEED_MORE_DATA;
+ SetFlag(statePtr, CHANNEL_NEED_MORE_DATA);
copiedTotal = -1;
- done:
/*
- * Update the notifier state so we don't block while there is still
- * data in the buffers.
+ * Update the notifier state so we don't block while there is still data
+ * in the buffers.
*/
+ done:
UpdateInterest(chanPtr);
return copiedTotal;
}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclGetsObjBinary --
+ *
+ * A variation of Tcl_GetsObj that works directly on the buffers until
+ * end-of-line or end-of-file has been seen. Bytes read from the input
+ * channel return as a ByteArray obj.
+ *
+ * Results:
+ * Number of characters accumulated in the object or -1 if error,
+ * blocked, or EOF. If -1, use Tcl_GetErrno() to retrieve the POSIX error
+ * code for the error or condition that occurred.
+ *
+ * Side effects:
+ * Consumes input from the channel.
+ *
+ * On reading EOF, leave channel pointing at EOF char. On reading EOL,
+ * leave channel pointing after EOL, but don't return EOL in dst buffer.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+TclGetsObjBinary(
+ Tcl_Channel chan, /* Channel from which to read. */
+ Tcl_Obj *objPtr) /* The line read will be appended to this
+ * object as UTF-8 characters. */
+{
+ Channel *chanPtr = (Channel *) chan;
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
+ ChannelBuffer *bufPtr;
+ int inEofChar, skip, copiedTotal, oldLength, oldFlags, oldRemoved;
+ int rawLen, byteLen, eolChar;
+ unsigned char *dst, *dstEnd, *eol, *eof, *byteArray;
+
+ /*
+ * This operation should occur at the top of a channel stack.
+ */
+
+ chanPtr = statePtr->topChanPtr;
+
+ bufPtr = statePtr->inQueueHead;
+
+ /*
+ * Preserved so we can restore the channel's state in case we don't find a
+ * newline in the available input.
+ */
+
+ byteArray = Tcl_GetByteArrayFromObj(objPtr, &byteLen);
+ oldFlags = statePtr->inputEncodingFlags;
+ oldRemoved = BUFFER_PADDING;
+ oldLength = byteLen;
+ if (bufPtr != NULL) {
+ oldRemoved = bufPtr->nextRemoved;
+ }
+
+ rawLen = 0;
+ skip = 0;
+ eof = NULL;
+ inEofChar = statePtr->inEofChar;
+ /* Only handle TCL_TRANSLATE_LF and TCL_TRANSLATE_CR */
+ eolChar = (statePtr->inputTranslation == TCL_TRANSLATE_LF) ? '\n' : '\r';
+
+ while (1) {
+ /*
+ * Subtract the number of bytes that were removed from channel
+ * buffer during last call.
+ */
+
+ if (bufPtr != NULL) {
+ bufPtr->nextRemoved += rawLen;
+ if (!IsBufferReady(bufPtr)) {
+ bufPtr = bufPtr->nextPtr;
+ }
+ }
+
+ if ((bufPtr == NULL) || (bufPtr->nextAdded == BUFFER_PADDING)) {
+ /*
+ * All channel buffers were exhausted and the caller still
+ * hasn't seen EOL. Need to read more bytes from the channel
+ * device. Side effect is to allocate another channel buffer.
+ */
+
+ if (statePtr->flags & CHANNEL_BLOCKED) {
+ if (statePtr->flags & CHANNEL_NONBLOCKING) {
+ goto restore;
+ }
+ ResetFlag(statePtr, CHANNEL_BLOCKED);
+ }
+ if (GetInput(chanPtr) != 0) {
+ goto restore;
+ }
+ bufPtr = statePtr->inQueueTail;
+ }
+
+ dst = (unsigned char *) RemovePoint(bufPtr);
+ dstEnd = dst + BytesLeft(bufPtr);
+
+ /*
+ * Remember if EOF char is seen, then look for EOL anyhow, because the
+ * EOL might be before the EOF char.
+ * XXX - in the binary case, consider coincident search for eol/eof.
+ */
+
+ if (inEofChar != '\0') {
+ for (eol = dst; eol < dstEnd; eol++) {
+ if (*eol == inEofChar) {
+ dstEnd = eol;
+ eof = eol;
+ break;
+ }
+ }
+ }
+
+ /*
+ * On EOL, leave current file position pointing after the EOL, but
+ * don't store the EOL in the output string.
+ */
+
+ for (eol = dst; eol < dstEnd; eol++) {
+ if (*eol == eolChar) {
+ skip = 1;
+ goto gotEOL;
+ }
+ }
+ if (eof != NULL) {
+ /*
+ * EOF character was seen. On EOF, leave current file position
+ * pointing at the EOF character, but don't store the EOF
+ * character in the output string.
+ */
+
+ SetFlag(statePtr, CHANNEL_EOF | CHANNEL_STICKY_EOF);
+ statePtr->inputEncodingFlags |= TCL_ENCODING_END;
+ }
+ if (statePtr->flags & CHANNEL_EOF) {
+ skip = 0;
+ eol = dstEnd;
+ if ((dst == dstEnd) && (byteLen == oldLength)) {
+ /*
+ * If we didn't append any bytes before encountering EOF,
+ * caller needs to see -1.
+ */
+
+ byteArray = Tcl_SetByteArrayLength(objPtr, oldLength);
+ CommonGetsCleanup(chanPtr);
+ copiedTotal = -1;
+ goto done;
+ }
+ goto gotEOL;
+ }
+
+ /*
+ * Copy bytes from the channel buffer to the ByteArray.
+ * This may realloc space, so keep track of result.
+ */
+
+ rawLen = dstEnd - dst;
+ byteArray = Tcl_SetByteArrayLength(objPtr, byteLen + rawLen);
+ memcpy(byteArray + byteLen, dst, (size_t) rawLen);
+ byteLen += rawLen;
+ }
+
+ /*
+ * Found EOL or EOF, but the output buffer may now contain too many bytes.
+ * We need to know how many bytes correspond to the number we want, so we
+ * can remove the correct number of bytes from the channel buffer.
+ */
+
+ gotEOL:
+ if (bufPtr == NULL) {
+ Tcl_Panic("TclGetsObjBinary: gotEOL reached with bufPtr==NULL");
+ }
+
+ rawLen = eol - dst;
+ byteArray = Tcl_SetByteArrayLength(objPtr, byteLen + rawLen);
+ memcpy(byteArray + byteLen, dst, (size_t) rawLen);
+ byteLen += rawLen;
+ bufPtr->nextRemoved += rawLen + skip;
+
+ /*
+ * Convert the buffer if there was an encoding.
+ * XXX - unimplemented.
+ */
+
+ if (statePtr->encoding != NULL) {
+ }
+
+ /*
+ * Recycle all the emptied buffers.
+ */
+
+ CommonGetsCleanup(chanPtr);
+ ResetFlag(statePtr, CHANNEL_BLOCKED);
+ copiedTotal = byteLen;
+ goto done;
+
+ /*
+ * Couldn't get a complete line. This only happens if we get a error
+ * reading from the channel or we are non-blocking and there wasn't an EOL
+ * or EOF in the data available.
+ */
+
+ restore:
+ bufPtr = statePtr->inQueueHead;
+ if (bufPtr == NULL) {
+ Tcl_Panic("TclGetsObjBinary: restore reached with bufPtr==NULL");
+ }
+ bufPtr->nextRemoved = oldRemoved;
+
+ for (bufPtr = bufPtr->nextPtr; bufPtr != NULL; bufPtr = bufPtr->nextPtr) {
+ bufPtr->nextRemoved = BUFFER_PADDING;
+ }
+ CommonGetsCleanup(chanPtr);
+
+ statePtr->inputEncodingFlags = oldFlags;
+ byteArray = Tcl_SetByteArrayLength(objPtr, oldLength);
+
+ /*
+ * We didn't get a complete line so we need to indicate to UpdateInterest
+ * that the gets blocked. It will wait for more data instead of firing a
+ * timer, avoiding a busy wait. This is where we are assuming that the
+ * next operation is a gets. No more file events will be delivered on this
+ * channel until new data arrives or some operation is performed on the
+ * channel (e.g. gets, read, fconfigure) that changes the blocking state.
+ * Note that this means a file event will not be delivered even though a
+ * read would be able to consume the buffered data.
+ */
+
+ SetFlag(statePtr, CHANNEL_NEED_MORE_DATA);
+ copiedTotal = -1;
+
+ /*
+ * Update the notifier state so we don't block while there is still data
+ * in the buffers.
+ */
+
+ done:
+ UpdateInterest(chanPtr);
+ return copiedTotal;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FreeBinaryEncoding --
+ *
+ * Frees any "iso8859-1" Tcl_Encoding created by [gets] on a binary
+ * channel in a thread as part of that thread's finalization.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+FreeBinaryEncoding(
+ ClientData dummy) /* Not used */
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ if (tsdPtr->binaryEncoding != NULL) {
+ Tcl_FreeEncoding(tsdPtr->binaryEncoding);
+ tsdPtr->binaryEncoding = NULL;
+ }
+}
+
/*
*---------------------------------------------------------------------------
*
* FilterInputBytes --
*
- * Helper function for Tcl_GetsObj. Produces UTF-8 characters from
- * raw bytes read from the channel.
+ * Helper function for Tcl_GetsObj. Produces UTF-8 characters from raw
+ * bytes read from the channel.
*
- * Consumes available bytes from channel buffers. When channel
- * buffers are exhausted, reads more bytes from channel device into
- * a new channel buffer. It is the caller's responsibility to
- * free the channel buffers that have been exhausted.
+ * Consumes available bytes from channel buffers. When channel buffers
+ * are exhausted, reads more bytes from channel device into a new channel
+ * buffer. It is the caller's responsibility to free the channel buffers
+ * that have been exhausted.
*
* Results:
- * The return value is -1 if there was an error reading from the
- * channel, 0 otherwise.
+ * The return value is -1 if there was an error reading from the channel,
+ * 0 otherwise.
*
* Side effects:
- * Status object keeps track of how much data from channel buffers
- * has been consumed and where UTF-8 bytes should be stored.
+ * Status object keeps track of how much data from channel buffers has
+ * been consumed and where UTF-8 bytes should be stored.
*
*---------------------------------------------------------------------------
*/
-
+
static int
-FilterInputBytes(chanPtr, gsPtr)
- Channel *chanPtr; /* Channel to read. */
- GetsState *gsPtr; /* Current state of gets operation. */
+FilterInputBytes(
+ Channel *chanPtr, /* Channel to read. */
+ GetsState *gsPtr) /* Current state of gets operation. */
{
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
ChannelBuffer *bufPtr;
- char *raw, *rawStart, *rawEnd;
- char *dst;
- int offset, toRead, dstNeeded, spaceLeft, result, rawLen, length;
+ char *raw, *rawStart, *dst;
+ int offset, toRead, dstNeeded, spaceLeft, result, rawLen;
Tcl_Obj *objPtr;
-#define ENCODING_LINESIZE 20 /* Lower bound on how many bytes to convert
- * at a time. Since we don't know a priori
- * how many bytes of storage this many source
+#define ENCODING_LINESIZE 20 /* Lower bound on how many bytes to convert at
+ * a time. Since we don't know a priori how
+ * many bytes of storage this many source
* bytes will use, we actually need at least
* ENCODING_LINESIZE * TCL_MAX_UTF bytes of
* room. */
@@ -3941,7 +4647,7 @@ FilterInputBytes(chanPtr, gsPtr)
bufPtr = gsPtr->bufPtr;
if (bufPtr != NULL) {
bufPtr->nextRemoved += gsPtr->rawRead;
- if (bufPtr->nextRemoved >= bufPtr->nextAdded) {
+ if (!IsBufferReady(bufPtr)) {
bufPtr = bufPtr->nextPtr;
}
}
@@ -3949,20 +4655,20 @@ FilterInputBytes(chanPtr, gsPtr)
if ((bufPtr == NULL) || (bufPtr->nextAdded == BUFFER_PADDING)) {
/*
- * All channel buffers were exhausted and the caller still hasn't
- * seen EOL. Need to read more bytes from the channel device.
- * Side effect is to allocate another channel buffer.
+ * All channel buffers were exhausted and the caller still hasn't seen
+ * EOL. Need to read more bytes from the channel device. Side effect
+ * is to allocate another channel buffer.
*/
- read:
- if (statePtr->flags & CHANNEL_BLOCKED) {
- if (statePtr->flags & CHANNEL_NONBLOCKING) {
+ read:
+ if (statePtr->flags & CHANNEL_BLOCKED) {
+ if (statePtr->flags & CHANNEL_NONBLOCKING) {
gsPtr->charsWrote = 0;
gsPtr->rawRead = 0;
return -1;
}
- statePtr->flags &= ~CHANNEL_BLOCKED;
- }
+ ResetFlag(statePtr, CHANNEL_BLOCKED);
+ }
if (GetInput(chanPtr) != 0) {
gsPtr->charsWrote = 0;
gsPtr->rawRead = 0;
@@ -3973,15 +4679,14 @@ FilterInputBytes(chanPtr, gsPtr)
}
/*
- * Convert some of the bytes from the channel buffer to UTF-8. Space in
- * objPtr's string rep is used to hold the UTF-8 characters. Grow the
+ * Convert some of the bytes from the channel buffer to UTF-8. Space in
+ * objPtr's string rep is used to hold the UTF-8 characters. Grow the
* string rep if we need more space.
*/
- rawStart = bufPtr->buf + bufPtr->nextRemoved;
+ rawStart = RemovePoint(bufPtr);
raw = rawStart;
- rawEnd = bufPtr->buf + bufPtr->nextAdded;
- rawLen = rawEnd - rawStart;
+ rawLen = BytesLeft(bufPtr);
dst = *gsPtr->dstPtr;
offset = dst - objPtr->bytes;
@@ -3989,15 +4694,19 @@ FilterInputBytes(chanPtr, gsPtr)
if (toRead > rawLen) {
toRead = rawLen;
}
- dstNeeded = toRead * TCL_UTF_MAX + 1;
- spaceLeft = objPtr->length - offset - TCL_UTF_MAX - 1;
+ dstNeeded = toRead * TCL_UTF_MAX;
+ spaceLeft = objPtr->length - offset;
if (dstNeeded > spaceLeft) {
- length = offset * 2;
- if (offset < dstNeeded) {
+ int length = offset + ((offset < dstNeeded) ? dstNeeded : offset);
+
+ if (Tcl_AttemptSetObjLength(objPtr, length) == 0) {
length = offset + dstNeeded;
+ if (Tcl_AttemptSetObjLength(objPtr, length) == 0) {
+ dstNeeded = TCL_UTF_MAX - 1 + toRead;
+ length = offset + dstNeeded;
+ Tcl_SetObjLength(objPtr, length);
+ }
}
- length += TCL_UTF_MAX + 1;
- Tcl_SetObjLength(objPtr, length);
spaceLeft = length - offset;
dst = objPtr->bytes + offset;
*gsPtr->dstPtr = dst;
@@ -4005,44 +4714,45 @@ FilterInputBytes(chanPtr, gsPtr)
gsPtr->state = statePtr->inputEncodingState;
result = Tcl_ExternalToUtf(NULL, gsPtr->encoding, raw, rawLen,
statePtr->inputEncodingFlags, &statePtr->inputEncodingState,
- dst, spaceLeft, &gsPtr->rawRead, &gsPtr->bytesWrote,
+ dst, spaceLeft+1, &gsPtr->rawRead, &gsPtr->bytesWrote,
&gsPtr->charsWrote);
/*
* Make sure that if we go through 'gets', that we reset the
- * TCL_ENCODING_START flag still. [Bug #523988]
+ * TCL_ENCODING_START flag still. [Bug #523988]
*/
+
statePtr->inputEncodingFlags &= ~TCL_ENCODING_START;
if (result == TCL_CONVERT_MULTIBYTE) {
/*
* The last few bytes in this channel buffer were the start of a
- * multibyte sequence. If this buffer was full, then move them to
- * the next buffer so the bytes will be contiguous.
+ * multibyte sequence. If this buffer was full, then move them to the
+ * next buffer so the bytes will be contiguous.
*/
ChannelBuffer *nextPtr;
int extra;
-
+
nextPtr = bufPtr->nextPtr;
- if (bufPtr->nextAdded < bufPtr->bufLength) {
+ if (!IsBufferFull(bufPtr)) {
if (gsPtr->rawRead > 0) {
/*
- * Some raw bytes were converted to UTF-8. Fall through,
+ * Some raw bytes were converted to UTF-8. Fall through,
* returning those UTF-8 characters because a EOL might be
* present in them.
*/
} else if (statePtr->flags & CHANNEL_EOF) {
/*
* There was a partial character followed by EOF on the
- * device. Fall through, returning that nothing was found.
+ * device. Fall through, returning that nothing was found.
*/
bufPtr->nextRemoved = bufPtr->nextAdded;
} else {
/*
- * There are no more cached raw bytes left. See if we can
- * get some more.
+ * There are no more cached raw bytes left. See if we can get
+ * some more.
*/
goto read;
@@ -4054,8 +4764,8 @@ FilterInputBytes(chanPtr, gsPtr)
statePtr->inQueueTail = nextPtr;
}
extra = rawLen - gsPtr->rawRead;
- memcpy((VOID *) (nextPtr->buf + BUFFER_PADDING - extra),
- (VOID *) (raw + gsPtr->rawRead), (size_t) extra);
+ memcpy(nextPtr->buf + BUFFER_PADDING - extra,
+ raw + gsPtr->rawRead, (size_t) extra);
nextPtr->nextRemoved -= extra;
bufPtr->nextAdded -= extra;
}
@@ -4070,9 +4780,9 @@ FilterInputBytes(chanPtr, gsPtr)
*
* PeekAhead --
*
- * Helper function used by Tcl_GetsObj(). Called when we've seen a
- * \r at the end of the UTF-8 string and want to look ahead one
- * character to see if it is a \n.
+ * Helper function used by Tcl_GetsObj(). Called when we've seen a \r at
+ * the end of the UTF-8 string and want to look ahead one character to
+ * see if it is a \n.
*
* Results:
* *gsPtr->dstPtr is filled with a pointer to the start of the range of
@@ -4088,13 +4798,14 @@ FilterInputBytes(chanPtr, gsPtr)
*/
static void
-PeekAhead(chanPtr, dstEndPtr, gsPtr)
- Channel *chanPtr; /* The channel to read. */
- char **dstEndPtr; /* Filled with pointer to end of new range
- * of UTF-8 characters. */
- GetsState *gsPtr; /* Current state of gets operation. */
+PeekAhead(
+ Channel *chanPtr, /* The channel to read. */
+ char **dstEndPtr, /* Filled with pointer to end of new range of
+ * UTF-8 characters. */
+ GetsState *gsPtr) /* Current state of gets operation. */
{
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
ChannelBuffer *bufPtr;
Tcl_DriverBlockModeProc *blockModeProc;
int bytesLeft;
@@ -4103,21 +4814,21 @@ PeekAhead(chanPtr, dstEndPtr, gsPtr)
/*
* If there's any more raw input that's still buffered, we'll peek into
- * that. Otherwise, only get more data from the channel driver if it
- * looks like there might actually be more data. The assumption is that
- * if the channel buffer is filled right up to the end, then there
- * might be more data to read.
+ * that. Otherwise, only get more data from the channel driver if it looks
+ * like there might actually be more data. The assumption is that if the
+ * channel buffer is filled right up to the end, then there might be more
+ * data to read.
*/
blockModeProc = NULL;
if (bufPtr->nextPtr == NULL) {
- bytesLeft = bufPtr->nextAdded - (bufPtr->nextRemoved + gsPtr->rawRead);
+ bytesLeft = BytesLeft(bufPtr) - gsPtr->rawRead;
if (bytesLeft == 0) {
- if (bufPtr->nextAdded < bufPtr->bufLength) {
+ if (!IsBufferFull(bufPtr)) {
/*
* Don't peek ahead if last read was short read.
*/
-
+
goto cleanup;
}
if ((statePtr->flags & CHANNEL_NONBLOCKING) == 0) {
@@ -4141,7 +4852,7 @@ PeekAhead(chanPtr, dstEndPtr, gsPtr)
}
return;
- cleanup:
+ cleanup:
bufPtr->nextRemoved += gsPtr->rawRead;
gsPtr->rawRead = 0;
gsPtr->totalChars += gsPtr->charsWrote;
@@ -4154,8 +4865,8 @@ PeekAhead(chanPtr, dstEndPtr, gsPtr)
*
* CommonGetsCleanup --
*
- * Helper function for Tcl_GetsObj() to restore the channel after
- * a "gets" operation.
+ * Helper function for Tcl_GetsObj() to restore the channel after a
+ * "gets" operation.
*
* Results:
* None.
@@ -4165,19 +4876,19 @@ PeekAhead(chanPtr, dstEndPtr, gsPtr)
*
*---------------------------------------------------------------------------
*/
-
+
static void
-CommonGetsCleanup(chanPtr, encoding)
- Channel *chanPtr;
- Tcl_Encoding encoding;
+CommonGetsCleanup(
+ Channel *chanPtr)
{
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
ChannelBuffer *bufPtr, *nextPtr;
-
+
bufPtr = statePtr->inQueueHead;
for ( ; bufPtr != NULL; bufPtr = nextPtr) {
nextPtr = bufPtr->nextPtr;
- if (bufPtr->nextRemoved < bufPtr->nextAdded) {
+ if (IsBufferReady(bufPtr)) {
break;
}
RecycleBuffer(statePtr, bufPtr, 0);
@@ -4189,20 +4900,20 @@ CommonGetsCleanup(chanPtr, encoding)
/*
* If any multi-byte characters were split across channel buffer
* boundaries, the split-up bytes were moved to the next channel
- * buffer by FilterInputBytes(). Move the bytes back to their
- * original buffer because the caller could change the channel's
- * encoding which could change the interpretation of whether those
- * bytes really made up multi-byte characters after all.
+ * buffer by FilterInputBytes(). Move the bytes back to their original
+ * buffer because the caller could change the channel's encoding which
+ * could change the interpretation of whether those bytes really made
+ * up multi-byte characters after all.
*/
-
+
nextPtr = bufPtr->nextPtr;
for ( ; nextPtr != NULL; nextPtr = bufPtr->nextPtr) {
int extra;
- extra = bufPtr->bufLength - bufPtr->nextAdded;
+ extra = SpaceLeft(bufPtr);
if (extra > 0) {
- memcpy((VOID *) (bufPtr->buf + bufPtr->nextAdded),
- (VOID *) (nextPtr->buf + BUFFER_PADDING - extra),
+ memcpy(InsertPoint(bufPtr),
+ nextPtr->buf + BUFFER_PADDING - extra,
(size_t) extra);
bufPtr->nextAdded += extra;
nextPtr->nextRemoved = BUFFER_PADDING;
@@ -4210,9 +4921,6 @@ CommonGetsCleanup(chanPtr, encoding)
bufPtr = nextPtr;
}
}
- if (statePtr->encoding == NULL) {
- Tcl_FreeEncoding(encoding);
- }
}
/*
@@ -4220,16 +4928,16 @@ CommonGetsCleanup(chanPtr, encoding)
*
* Tcl_Read --
*
- * Reads a given number of bytes from a channel. EOL and EOF
- * translation is done on the bytes being read, so the the number
- * of bytes consumed from the channel may not be equal to the
- * number of bytes stored in the destination buffer.
+ * Reads a given number of bytes from a channel. EOL and EOF translation
+ * is done on the bytes being read, so the number of bytes consumed from
+ * the channel may not be equal to the number of bytes stored in the
+ * destination buffer.
*
* No encoding conversions are applied to the bytes being read.
*
* Results:
- * The number of bytes read, or -1 on error. Use Tcl_GetErrno()
- * to retrieve the error code for the error that occurred.
+ * The number of bytes read, or -1 on error. Use Tcl_GetErrno() to
+ * retrieve the error code for the error that occurred.
*
* Side effects:
* May cause input to be buffered.
@@ -4238,13 +4946,14 @@ CommonGetsCleanup(chanPtr, encoding)
*/
int
-Tcl_Read(chan, dst, bytesToRead)
- Tcl_Channel chan; /* The channel from which to read. */
- char *dst; /* Where to store input read. */
- int bytesToRead; /* Maximum number of bytes to read. */
+Tcl_Read(
+ Tcl_Channel chan, /* The channel from which to read. */
+ char *dst, /* Where to store input read. */
+ int bytesToRead) /* Maximum number of bytes to read. */
{
- Channel *chanPtr = (Channel *) chan;
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+ Channel *chanPtr = (Channel *) chan;
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
/*
* This operation should occur at the top of a channel stack.
@@ -4264,16 +4973,16 @@ Tcl_Read(chan, dst, bytesToRead)
*
* Tcl_ReadRaw --
*
- * Reads a given number of bytes from a channel. EOL and EOF
- * translation is done on the bytes being read, so the the number
- * of bytes consumed from the channel may not be equal to the
- * number of bytes stored in the destination buffer.
+ * Reads a given number of bytes from a channel. EOL and EOF translation
+ * is done on the bytes being read, so the number of bytes consumed from
+ * the channel may not be equal to the number of bytes stored in the
+ * destination buffer.
*
* No encoding conversions are applied to the bytes being read.
*
* Results:
- * The number of bytes read, or -1 on error. Use Tcl_GetErrno()
- * to retrieve the error code for the error that occurred.
+ * The number of bytes read, or -1 on error. Use Tcl_GetErrno() to
+ * retrieve the error code for the error that occurred.
*
* Side effects:
* May cause input to be buffered.
@@ -4282,22 +4991,22 @@ Tcl_Read(chan, dst, bytesToRead)
*/
int
-Tcl_ReadRaw(chan, bufPtr, bytesToRead)
- Tcl_Channel chan; /* The channel from which to read. */
- char *bufPtr; /* Where to store input read. */
- int bytesToRead; /* Maximum number of bytes to read. */
+Tcl_ReadRaw(
+ Tcl_Channel chan, /* The channel from which to read. */
+ char *bufPtr, /* Where to store input read. */
+ int bytesToRead) /* Maximum number of bytes to read. */
{
- Channel *chanPtr = (Channel *) chan;
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
- int nread, result;
- int copied, copiedNow;
+ Channel *chanPtr = (Channel *) chan;
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
+ int nread, result, copied, copiedNow;
/*
* The check below does too much because it will reject a call to this
* function with a channel which is part of an 'fcopy'. But we have to
- * allow this here or else the chaining in the transformation drivers
- * will fail with 'file busy' error instead of retrieving and
- * transforming the data to copy.
+ * allow this here or else the chaining in the transformation drivers will
+ * fail with 'file busy' error instead of retrieving and transforming the
+ * data to copy.
*
* We let the check procedure now believe that there is no fcopy in
* progress. A better solution than this might be an additional flag
@@ -4309,102 +5018,113 @@ Tcl_ReadRaw(chan, bufPtr, bytesToRead)
}
/*
- * Check for information in the push-back buffers. If there is
- * some, use it. Go to the driver only if there is none (anymore)
- * and the caller requests more bytes.
+ * Check for information in the push-back buffers. If there is some, use
+ * it. Go to the driver only if there is none (anymore) and the caller
+ * requests more bytes.
*/
for (copied = 0; copied < bytesToRead; copied += copiedNow) {
- copiedNow = CopyBuffer(chanPtr, bufPtr + copied,
- bytesToRead - copied);
- if (copiedNow == 0) {
- if (statePtr->flags & CHANNEL_EOF) {
+ copiedNow = CopyBuffer(chanPtr, bufPtr + copied,
+ bytesToRead - copied);
+ if (copiedNow == 0) {
+ if (statePtr->flags & CHANNEL_EOF) {
goto done;
- }
- if (statePtr->flags & CHANNEL_BLOCKED) {
- if (statePtr->flags & CHANNEL_NONBLOCKING) {
+ }
+ if (statePtr->flags & CHANNEL_BLOCKED) {
+ if (statePtr->flags & CHANNEL_NONBLOCKING) {
goto done;
- }
- statePtr->flags &= (~(CHANNEL_BLOCKED));
- }
+ }
+ ResetFlag(statePtr, CHANNEL_BLOCKED);
+ }
#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
- /* [SF Tcl Bug 943274]. Better emulation of non-blocking
- * channels for channels without BlockModeProc, by keeping
- * track of true fileevents generated by the OS == Data
- * waiting and reading if and only if we are sure to have
- * data.
+ /*
+ * [Bug 943274]. Better emulation of non-blocking channels for
+ * channels without BlockModeProc, by keeping track of true
+ * fileevents generated by the OS == Data waiting and reading if
+ * and only if we are sure to have data.
*/
if ((statePtr->flags & CHANNEL_NONBLOCKING) &&
- (Tcl_ChannelBlockModeProc(chanPtr->typePtr) == NULL) &&
- !(statePtr->flags & CHANNEL_HAS_MORE_DATA)) {
+ (Tcl_ChannelBlockModeProc(chanPtr->typePtr) == NULL) &&
+ !(statePtr->flags & CHANNEL_HAS_MORE_DATA)) {
+ /*
+ * We bypass the driver; it would block as no data is
+ * available.
+ */
- /* We bypass the driver, it would block, as no data is available */
- nread = -1;
- result = EWOULDBLOCK;
+ nread = -1;
+ result = EWOULDBLOCK;
} else {
#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */
- /*
- * Now go to the driver to get as much as is possible to
- * fill the remaining request. Do all the error handling
- * by ourselves. The code was stolen from 'GetInput' and
- * slightly adapted (different return value here).
- *
- * The case of 'bytesToRead == 0' at this point cannot happen.
- */
-
- nread = (chanPtr->typePtr->inputProc)(chanPtr->instanceData,
- bufPtr + copied, bytesToRead - copied, &result);
+
+ /*
+ * Now go to the driver to get as much as is possible to fill
+ * the remaining request. Do all the error handling by
+ * ourselves. The code was stolen from 'GetInput' and slightly
+ * adapted (different return value here).
+ *
+ * The case of 'bytesToRead == 0' at this point cannot happen.
+ */
+
+ nread = (chanPtr->typePtr->inputProc)(chanPtr->instanceData,
+ bufPtr + copied, bytesToRead - copied, &result);
+
#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
}
#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */
+
if (nread > 0) {
- /*
- * If we get a short read, signal up that we may be
- * BLOCKED. We should avoid calling the driver because
- * on some platforms we will block in the low level
- * reading code even though the channel is set into
- * nonblocking mode.
+ /*
+ * If we get a short read, signal up that we may be BLOCKED.
+ * We should avoid calling the driver because on some
+ * platforms we will block in the low level reading code even
+ * though the channel is set into nonblocking mode.
*/
-
- if (nread < (bytesToRead - copied)) {
- statePtr->flags |= CHANNEL_BLOCKED;
+
+ if (nread < (bytesToRead - copied)) {
+ SetFlag(statePtr, CHANNEL_BLOCKED);
}
#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
- if (nread <= (bytesToRead - copied)) {
- /* [SF Tcl Bug 943274] We have read the available
- * data, clear flag */
- statePtr->flags &= ~CHANNEL_HAS_MORE_DATA;
+ if (nread <= (bytesToRead - copied)) {
+ /*
+ * [Bug 943274] We have read the available data, clear
+ * flag.
+ */
+
+ ResetFlag(statePtr, CHANNEL_HAS_MORE_DATA);
}
#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */
+
} else if (nread == 0) {
- statePtr->flags |= CHANNEL_EOF;
+ SetFlag(statePtr, CHANNEL_EOF);
statePtr->inputEncodingFlags |= TCL_ENCODING_END;
+
} else if (nread < 0) {
- if ((result == EWOULDBLOCK) || (result == EAGAIN)) {
+ if ((result == EWOULDBLOCK) || (result == EAGAIN)) {
if (copied > 0) {
- /*
- * Information that was copied earlier has precedence
- * over EAGAIN/WOULDBLOCK handling.
- */
- return copied;
+ /*
+ * Information that was copied earlier has precedence
+ * over EAGAIN/WOULDBLOCK handling.
+ */
+
+ return copied;
}
- statePtr->flags |= CHANNEL_BLOCKED;
+ SetFlag(statePtr, CHANNEL_BLOCKED);
result = EAGAIN;
}
Tcl_SetErrno(result);
return -1;
- }
+ }
return copied + nread;
- }
+ }
}
-done:
+ done:
return copied;
}
@@ -4413,39 +5133,39 @@ done:
*
* Tcl_ReadChars --
*
- * Reads from the channel until the requested number of characters
- * have been seen, EOF is seen, or the channel would block. EOL
- * and EOF translation is done. If reading binary data, the raw
- * bytes are wrapped in a Tcl byte array object. Otherwise, the raw
- * bytes are converted to UTF-8 using the channel's current encoding
- * and stored in a Tcl string object.
+ * Reads from the channel until the requested number of characters have
+ * been seen, EOF is seen, or the channel would block. EOL and EOF
+ * translation is done. If reading binary data, the raw bytes are wrapped
+ * in a Tcl byte array object. Otherwise, the raw bytes are converted to
+ * UTF-8 using the channel's current encoding and stored in a Tcl string
+ * object.
*
* Results:
- * The number of characters read, or -1 on error. Use Tcl_GetErrno()
- * to retrieve the error code for the error that occurred.
+ * The number of characters read, or -1 on error. Use Tcl_GetErrno() to
+ * retrieve the error code for the error that occurred.
*
* Side effects:
* May cause input to be buffered.
*
*---------------------------------------------------------------------------
*/
-
+
int
-Tcl_ReadChars(chan, objPtr, toRead, appendFlag)
- Tcl_Channel chan; /* The channel to read. */
- Tcl_Obj *objPtr; /* Input data is stored in this object. */
- int toRead; /* Maximum number of characters to store,
- * or -1 to read all available data (up to EOF
- * or when channel blocks). */
- int appendFlag; /* If non-zero, data read from the channel
- * will be appended to the object. Otherwise,
+Tcl_ReadChars(
+ Tcl_Channel chan, /* The channel to read. */
+ Tcl_Obj *objPtr, /* Input data is stored in this object. */
+ int toRead, /* Maximum number of characters to store, or
+ * -1 to read all available data (up to EOF or
+ * when channel blocks). */
+ int appendFlag) /* If non-zero, data read from the channel
+ * will be appended to the object. Otherwise,
* the data will replace the existing contents
* of the object. */
-
{
- Channel* chanPtr = (Channel *) chan;
- ChannelState* statePtr = chanPtr->state; /* state info for channel */
-
+ Channel *chanPtr = (Channel *) chan;
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
+
/*
* This operation should occur at the top of a channel stack.
*/
@@ -4453,52 +5173,53 @@ Tcl_ReadChars(chan, objPtr, toRead, appendFlag)
chanPtr = statePtr->topChanPtr;
if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) {
- /*
+ /*
* Update the notifier state so we don't block while there is still
* data in the buffers.
*/
- UpdateInterest(chanPtr);
+
+ UpdateInterest(chanPtr);
return -1;
}
- return DoReadChars (chanPtr, objPtr, toRead, appendFlag);
+ return DoReadChars(chanPtr, objPtr, toRead, appendFlag);
}
/*
*---------------------------------------------------------------------------
*
* DoReadChars --
*
- * Reads from the channel until the requested number of characters
- * have been seen, EOF is seen, or the channel would block. EOL
- * and EOF translation is done. If reading binary data, the raw
- * bytes are wrapped in a Tcl byte array object. Otherwise, the raw
- * bytes are converted to UTF-8 using the channel's current encoding
- * and stored in a Tcl string object.
+ * Reads from the channel until the requested number of characters have
+ * been seen, EOF is seen, or the channel would block. EOL and EOF
+ * translation is done. If reading binary data, the raw bytes are wrapped
+ * in a Tcl byte array object. Otherwise, the raw bytes are converted to
+ * UTF-8 using the channel's current encoding and stored in a Tcl string
+ * object.
*
* Results:
- * The number of characters read, or -1 on error. Use Tcl_GetErrno()
- * to retrieve the error code for the error that occurred.
+ * The number of characters read, or -1 on error. Use Tcl_GetErrno() to
+ * retrieve the error code for the error that occurred.
*
* Side effects:
* May cause input to be buffered.
*
*---------------------------------------------------------------------------
*/
-
+
static int
-DoReadChars(chanPtr, objPtr, toRead, appendFlag)
- Channel* chanPtr; /* The channel to read. */
- Tcl_Obj *objPtr; /* Input data is stored in this object. */
- int toRead; /* Maximum number of characters to store,
- * or -1 to read all available data (up to EOF
- * or when channel blocks). */
- int appendFlag; /* If non-zero, data read from the channel
- * will be appended to the object. Otherwise,
+DoReadChars(
+ Channel *chanPtr, /* The channel to read. */
+ Tcl_Obj *objPtr, /* Input data is stored in this object. */
+ int toRead, /* Maximum number of characters to store, or
+ * -1 to read all available data (up to EOF or
+ * when channel blocks). */
+ int appendFlag) /* If non-zero, data read from the channel
+ * will be appended to the object. Otherwise,
* the data will replace the existing contents
* of the object. */
-
{
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
ChannelBuffer *bufPtr;
int offset, factor, copied, copiedNow, result;
Tcl_Encoding encoding;
@@ -4508,28 +5229,30 @@ DoReadChars(chanPtr, objPtr, toRead, appendFlag)
* This operation should occur at the top of a channel stack.
*/
- chanPtr = statePtr->topChanPtr;
+ chanPtr = statePtr->topChanPtr;
encoding = statePtr->encoding;
- factor = UTF_EXPANSION_FACTOR;
+ factor = UTF_EXPANSION_FACTOR;
if (appendFlag == 0) {
if (encoding == NULL) {
Tcl_SetByteArrayLength(objPtr, 0);
} else {
Tcl_SetObjLength(objPtr, 0);
- /*
- * We're going to access objPtr->bytes directly, so
- * we must ensure that this is actually a string
- * object (otherwise it might have been pure Unicode).
+
+ /*
+ * We're going to access objPtr->bytes directly, so we must ensure
+ * that this is actually a string object (otherwise it might have
+ * been pure Unicode).
*/
- Tcl_GetString(objPtr);
+
+ TclGetString(objPtr);
}
offset = 0;
} else {
if (encoding == NULL) {
Tcl_GetByteArrayFromObj(objPtr, &offset);
} else {
- Tcl_GetStringFromObj(objPtr, &offset);
+ TclGetStringFromObj(objPtr, &offset);
}
}
@@ -4548,7 +5271,7 @@ DoReadChars(chanPtr, objPtr, toRead, appendFlag)
*/
bufPtr = statePtr->inQueueHead;
- if (bufPtr->nextRemoved == bufPtr->nextAdded) {
+ if (IsBufferEmpty(bufPtr)) {
ChannelBuffer *nextPtr;
nextPtr = bufPtr->nextPtr;
@@ -4559,6 +5282,7 @@ DoReadChars(chanPtr, objPtr, toRead, appendFlag)
}
}
}
+
if (copiedNow < 0) {
if (statePtr->flags & CHANNEL_EOF) {
break;
@@ -4567,7 +5291,7 @@ DoReadChars(chanPtr, objPtr, toRead, appendFlag)
if (statePtr->flags & CHANNEL_NONBLOCKING) {
break;
}
- statePtr->flags &= ~CHANNEL_BLOCKED;
+ ResetFlag(statePtr, CHANNEL_BLOCKED);
}
result = GetInput(chanPtr);
if (result != 0) {
@@ -4582,41 +5306,42 @@ DoReadChars(chanPtr, objPtr, toRead, appendFlag)
toRead -= copiedNow;
}
}
- statePtr->flags &= ~CHANNEL_BLOCKED;
+
+ ResetFlag(statePtr, CHANNEL_BLOCKED);
if (encoding == NULL) {
Tcl_SetByteArrayLength(objPtr, offset);
} else {
Tcl_SetObjLength(objPtr, offset);
}
- done:
/*
- * Update the notifier state so we don't block while there is still
- * data in the buffers.
+ * Update the notifier state so we don't block while there is still data
+ * in the buffers.
*/
+ done:
UpdateInterest(chanPtr);
return copied;
}
+
/*
*---------------------------------------------------------------------------
*
* ReadBytes --
*
- * Reads from the channel until the requested number of bytes have
- * been seen, EOF is seen, or the channel would block. Bytes from
- * the channel are stored in objPtr as a ByteArray object. EOL
- * and EOF translation are done.
+ * Reads from the channel until the requested number of bytes have been
+ * seen, EOF is seen, or the channel would block. Bytes from the channel
+ * are stored in objPtr as a ByteArray object. EOL and EOF translation
+ * are done.
*
- * 'bytesToRead' can safely be a very large number because
- * space is only allocated to hold data read from the channel
- * as needed.
+ * 'bytesToRead' can safely be a very large number because space is only
+ * allocated to hold data read from the channel as needed.
*
* Results:
- * The return value is the number of bytes appended to the object
- * and *offsetPtr is filled with the total number of bytes in the
- * object (greater than the return value if there were already bytes
- * in the object).
+ * The return value is the number of bytes appended to the object and
+ * *offsetPtr is filled with the total number of bytes in the object
+ * (greater than the return value if there were already bytes in the
+ * object).
*
* Side effects:
* None.
@@ -4625,25 +5350,24 @@ DoReadChars(chanPtr, objPtr, toRead, appendFlag)
*/
static int
-ReadBytes(statePtr, objPtr, bytesToRead, offsetPtr)
- ChannelState *statePtr; /* State of the channel to read. */
- Tcl_Obj *objPtr; /* Input data is appended to this ByteArray
- * object. Its length is how much space
- * has been allocated to hold data, not how
- * many bytes of data have been stored in the
+ReadBytes(
+ ChannelState *statePtr, /* State of the channel to read. */
+ Tcl_Obj *objPtr, /* Input data is appended to this ByteArray
+ * object. Its length is how much space has
+ * been allocated to hold data, not how many
+ * bytes of data have been stored in the
* object. */
- int bytesToRead; /* Maximum number of bytes to store,
- * or < 0 to get all available bytes.
- * Bytes are obtained from the first
- * buffer in the queue -- even if this number
- * is larger than the number of bytes
- * available in the first buffer, only the
- * bytes from the first buffer are
+ int bytesToRead, /* Maximum number of bytes to store, or < 0 to
+ * get all available bytes. Bytes are obtained
+ * from the first buffer in the queue - even
+ * if this number is larger than the number of
+ * bytes available in the first buffer, only
+ * the bytes from the first buffer are
* returned. */
- int *offsetPtr; /* On input, contains how many bytes of
- * objPtr have been used to hold data. On
- * output, filled with how many bytes are now
- * being used. */
+ int *offsetPtr) /* On input, contains how many bytes of objPtr
+ * have been used to hold data. On output,
+ * filled with how many bytes are now being
+ * used. */
{
int toRead, srcLen, offset, length, srcRead, dstWrote;
ChannelBuffer *bufPtr;
@@ -4651,9 +5375,9 @@ ReadBytes(statePtr, objPtr, bytesToRead, offsetPtr)
offset = *offsetPtr;
- bufPtr = statePtr->inQueueHead;
- src = bufPtr->buf + bufPtr->nextRemoved;
- srcLen = bufPtr->nextAdded - bufPtr->nextRemoved;
+ bufPtr = statePtr->inQueueHead;
+ src = RemovePoint(bufPtr);
+ srcLen = BytesLeft(bufPtr);
toRead = bytesToRead;
if ((unsigned) toRead > (unsigned) srcLen) {
@@ -4663,9 +5387,9 @@ ReadBytes(statePtr, objPtr, bytesToRead, offsetPtr)
dst = (char *) Tcl_GetByteArrayFromObj(objPtr, &length);
if (toRead > length - offset - 1) {
/*
- * Double the existing size of the object or make enough room to
- * hold all the characters we may get from the source buffer,
- * whichever is larger.
+ * Double the existing size of the object or make enough room to hold
+ * all the characters we may get from the source buffer, whichever is
+ * larger.
*/
length = offset * 2;
@@ -4677,7 +5401,7 @@ ReadBytes(statePtr, objPtr, bytesToRead, offsetPtr)
dst += offset;
if (statePtr->flags & INPUT_NEED_NL) {
- statePtr->flags &= ~INPUT_NEED_NL;
+ ResetFlag(statePtr, INPUT_NEED_NL);
if ((srcLen == 0) || (*src != '\n')) {
*dst = '\r';
*offsetPtr += 1;
@@ -4706,21 +5430,21 @@ ReadBytes(statePtr, objPtr, bytesToRead, offsetPtr)
*
* ReadChars --
*
- * Reads from the channel until the requested number of UTF-8
- * characters have been seen, EOF is seen, or the channel would
- * block. Raw bytes from the channel are converted to UTF-8
- * and stored in objPtr. EOL and EOF translation is done.
+ * Reads from the channel until the requested number of UTF-8 characters
+ * have been seen, EOF is seen, or the channel would block. Raw bytes
+ * from the channel are converted to UTF-8 and stored in objPtr. EOL and
+ * EOF translation is done.
+ *
+ * 'charsToRead' can safely be a very large number because space is only
+ * allocated to hold data read from the channel as needed.
*
- * 'charsToRead' can safely be a very large number because
- * space is only allocated to hold data read from the channel
- * as needed.
+ * 'charsToRead' may *not* be 0.
*
* Results:
- * The return value is the number of characters appended to
- * the object, *offsetPtr is filled with the number of bytes that
- * were appended, and *factorPtr is filled with the expansion
- * factor used to guess how many bytes of UTF-8 to allocate to
- * hold N source bytes.
+ * The return value is the number of characters appended to the object,
+ * *offsetPtr is filled with the number of bytes that were appended, and
+ * *factorPtr is filled with the expansion factor used to guess how many
+ * bytes of UTF-8 to allocate to hold N source bytes.
*
* Side effects:
* None.
@@ -4729,31 +5453,31 @@ ReadBytes(statePtr, objPtr, bytesToRead, offsetPtr)
*/
static int
-ReadChars(statePtr, objPtr, charsToRead, offsetPtr, factorPtr)
- ChannelState *statePtr; /* State of channel to read. */
- Tcl_Obj *objPtr; /* Input data is appended to this object.
+ReadChars(
+ ChannelState *statePtr, /* State of channel to read. */
+ Tcl_Obj *objPtr, /* Input data is appended to this object.
* objPtr->length is how much space has been
* allocated to hold data, not how many bytes
* of data have been stored in the object. */
- int charsToRead; /* Maximum number of characters to store,
- * or -1 to get all available characters.
+ int charsToRead, /* Maximum number of characters to store, or
+ * -1 to get all available characters.
* Characters are obtained from the first
* buffer in the queue -- even if this number
* is larger than the number of characters
* available in the first buffer, only the
* characters from the first buffer are
* returned. */
- int *offsetPtr; /* On input, contains how many bytes of
- * objPtr have been used to hold data. On
- * output, filled with how many bytes are now
- * being used. */
- int *factorPtr; /* On input, contains a guess of how many
+ int *offsetPtr, /* On input, contains how many bytes of objPtr
+ * have been used to hold data. On output,
+ * filled with how many bytes are now being
+ * used. */
+ int *factorPtr) /* On input, contains a guess of how many
* bytes need to be allocated to hold the
* result of converting N source bytes to
- * UTF-8. On output, contains another guess
+ * UTF-8. On output, contains another guess
* based on the data seen so far. */
{
- int toRead, factor, offset, spaceLeft, length, srcLen, dstNeeded;
+ int toRead, factor, offset, spaceLeft, srcLen, dstNeeded;
int srcRead, dstWrote, numChars, dstRead;
ChannelBuffer *bufPtr;
char *src, *dst;
@@ -4763,9 +5487,9 @@ ReadChars(statePtr, objPtr, charsToRead, offsetPtr, factorPtr)
factor = *factorPtr;
offset = *offsetPtr;
- bufPtr = statePtr->inQueueHead;
- src = bufPtr->buf + bufPtr->nextRemoved;
- srcLen = bufPtr->nextAdded - bufPtr->nextRemoved;
+ bufPtr = statePtr->inQueueHead;
+ src = RemovePoint(bufPtr);
+ srcLen = BytesLeft(bufPtr);
toRead = charsToRead;
if ((unsigned)toRead > (unsigned)srcLen) {
@@ -4773,35 +5497,38 @@ ReadChars(statePtr, objPtr, charsToRead, offsetPtr, factorPtr)
}
/*
- * 'factor' is how much we guess that the bytes in the source buffer
- * will expand when converted to UTF-8 chars. This guess comes from
- * analyzing how many characters were produced by the previous
- * pass.
+ * 'factor' is how much we guess that the bytes in the source buffer will
+ * expand when converted to UTF-8 chars. This guess comes from analyzing
+ * how many characters were produced by the previous pass.
*/
- dstNeeded = toRead * factor / UTF_EXPANSION_FACTOR;
- spaceLeft = objPtr->length - offset - TCL_UTF_MAX - 1;
+ dstNeeded = TCL_UTF_MAX - 1 + toRead * factor / UTF_EXPANSION_FACTOR;
+ spaceLeft = objPtr->length - offset;
if (dstNeeded > spaceLeft) {
/*
- * Double the existing size of the object or make enough room to
- * hold all the characters we want from the source buffer,
- * whichever is larger.
+ * Double the existing size of the object or make enough room to hold
+ * all the characters we want from the source buffer, whichever is
+ * larger.
*/
- length = offset * 2;
- if (offset < dstNeeded) {
+ int length = offset + ((offset < dstNeeded) ? dstNeeded : offset);
+
+ if (Tcl_AttemptSetObjLength(objPtr, length) == 0) {
length = offset + dstNeeded;
+ if (Tcl_AttemptSetObjLength(objPtr, length) == 0) {
+ dstNeeded = TCL_UTF_MAX - 1 + toRead;
+ length = offset + dstNeeded;
+ Tcl_SetObjLength(objPtr, length);
+ }
}
spaceLeft = length - offset;
- length += TCL_UTF_MAX + 1;
- Tcl_SetObjLength(objPtr, length);
}
if (toRead == srcLen) {
/*
- * Want to convert the whole buffer in one pass. If we have
- * enough space, convert it using all available space in object
- * rather than using the factor.
+ * Want to convert the whole buffer in one pass. If we have enough
+ * space, convert it using all available space in object rather than
+ * using the factor.
*/
dstNeeded = spaceLeft;
@@ -4809,51 +5536,48 @@ ReadChars(statePtr, objPtr, charsToRead, offsetPtr, factorPtr)
dst = objPtr->bytes + offset;
/*
- * SF Tcl Bug 1462248
- * The cause of the crash reported in the referenced bug is this:
+ * [Bug 1462248]: The cause of the crash reported in this bug is this:
*
* - ReadChars, called with a single buffer, with a incomplete
- * multi-byte character at the end (only the first byte of it).
+ * multi-byte character at the end (only the first byte of it).
* - Encoding translation fails, asks for more data
* - Data is read, and eof is reached, TCL_ENCODING_END (TEE) is set.
- * - ReadChar is called again, converts the first buffer, but due
- * to TEE it does not check for incomplete multi-byte data, and the
- * character just after the end of the first buffer is a valid
- * completion of the multi-byte header in the actual buffer. The
- * conversion reads more characters from the buffer then present.
- * This causes nextRemoved to overshoot nextAdded and the next
- * reads compute a negative srcLen, cause further translations to
- * fail, causing copying of data into the next buffer using bad
- * arguments, causing the mecpy for to eventually fail.
+ * - ReadChar is called again, converts the first buffer, but due to TEE
+ * it does not check for incomplete multi-byte data, and the character
+ * just after the end of the first buffer is a valid completion of the
+ * multi-byte header in the actual buffer. The conversion reads more
+ * characters from the buffer then present. This causes nextRemoved to
+ * overshoot nextAdded and the next reads compute a negative srcLen,
+ * cause further translations to fail, causing copying of data into the
+ * next buffer using bad arguments, causing the mecpy for to eventually
+ * fail.
*
- * In the end it is a memory access bug spiraling out of control
- * if the conditions are _just so_. And ultimate cause is that TEE
- * is given to a conversion where it should not. TEE signals that
- * this is the last buffer. Except in our case it is not.
+ * In the end it is a memory access bug spiraling out of control if the
+ * conditions are _just so_. And ultimate cause is that TEE is given to a
+ * conversion where it should not. TEE signals that this is the last
+ * buffer. Except in our case it is not.
*
- * My solution is to suppress TEE if the first buffer is not the
- * last. We will eventually need it given that EOF has been
- * reached, but not right now. This is what the new flag
- * "endEncSuppressFlag" is for.
+ * My solution is to suppress TEE if the first buffer is not the last. We
+ * will eventually need it given that EOF has been reached, but not right
+ * now. This is what the new flag "endEncSuppressFlag" is for.
*
- * The bug in 'Tcl_Utf2UtfProc' where it read from memory behind
- * the actual buffer has been fixed as well, and fixes the problem
- * with the crash too, but this would still allow the generic
- * layer to accidentially break a multi-byte sequence if the
- * conditions are just right, because again the ExternalToUtf
- * would be successful where it should not.
+ * The bug in 'Tcl_Utf2UtfProc' where it read from memory behind the
+ * actual buffer has been fixed as well, and fixes the problem with the
+ * crash too, but this would still allow the generic layer to
+ * accidentially break a multi-byte sequence if the conditions are just
+ * right, because again the ExternalToUtf would be successful where it
+ * should not.
*/
if ((statePtr->inputEncodingFlags & TCL_ENCODING_END) &&
- (bufPtr->nextPtr != NULL)) {
-
- /* TEE is set for a buffer which is not the last. Squash it
- * for now, and restore it later, before yielding control to
- * our caller.
+ (bufPtr->nextPtr != NULL)) {
+ /*
+ * TEE is set for a buffer which is not the last. Squash it for now,
+ * and restore it later, before yielding control to our caller.
*/
- statePtr->inputEncodingFlags &= ~TCL_ENCODING_END;
- encEndFlagSuppressed = 1;
+ statePtr->inputEncodingFlags &= ~TCL_ENCODING_END;
+ encEndFlagSuppressed = 1;
}
oldState = statePtr->inputEncodingState;
@@ -4862,19 +5586,19 @@ ReadChars(statePtr, objPtr, charsToRead, offsetPtr, factorPtr)
* We want a '\n' because the last character we saw was '\r'.
*/
- statePtr->flags &= ~INPUT_NEED_NL;
+ ResetFlag(statePtr, INPUT_NEED_NL);
Tcl_ExternalToUtf(NULL, statePtr->encoding, src, srcLen,
statePtr->inputEncodingFlags, &statePtr->inputEncodingState,
dst, TCL_UTF_MAX + 1, &srcRead, &dstWrote, &numChars);
if ((dstWrote > 0) && (*dst == '\n')) {
/*
- * The next char was a '\n'. Consume it and produce a '\n'.
+ * The next char was a '\n'. Consume it and produce a '\n'.
*/
bufPtr->nextRemoved += srcRead;
} else {
/*
- * The next char was not a '\n'. Produce a '\r'.
+ * The next char was not a '\n'. Produce a '\r'.
*/
*dst = '\r';
@@ -4885,67 +5609,64 @@ ReadChars(statePtr, objPtr, charsToRead, offsetPtr, factorPtr)
if (encEndFlagSuppressed) {
statePtr->inputEncodingFlags |= TCL_ENCODING_END;
}
- return 1;
+ return 1;
}
Tcl_ExternalToUtf(NULL, statePtr->encoding, src, srcLen,
statePtr->inputEncodingFlags, &statePtr->inputEncodingState, dst,
- dstNeeded + TCL_UTF_MAX, &srcRead, &dstWrote, &numChars);
+ dstNeeded + 1, &srcRead, &dstWrote, &numChars);
if (encEndFlagSuppressed) {
- statePtr->inputEncodingFlags |= TCL_ENCODING_END;
+ statePtr->inputEncodingFlags |= TCL_ENCODING_END;
}
if (srcRead == 0) {
/*
- * Not enough bytes in src buffer to make a complete char. Copy
- * the bytes to the next buffer to make a new contiguous string,
- * then tell the caller to fill the buffer with more bytes.
+ * Not enough bytes in src buffer to make a complete char. Copy the
+ * bytes to the next buffer to make a new contiguous string, then tell
+ * the caller to fill the buffer with more bytes.
*/
ChannelBuffer *nextPtr;
-
+
nextPtr = bufPtr->nextPtr;
if (nextPtr == NULL) {
if (srcLen > 0) {
- /*
+ /*
* There isn't enough data in the buffers to complete the next
* character, so we need to wait for more data before the next
- * file event can be delivered.
- *
- * SF #478856.
+ * file event can be delivered. [Bug 478856]
*
- * The exception to this is if the input buffer was
- * completely empty before we tried to convert its
- * contents. Nothing in, nothing out, and no incomplete
- * character data. The conversion before the current one
- * was complete.
+ * The exception to this is if the input buffer was completely
+ * empty before we tried to convert its contents. Nothing in,
+ * nothing out, and no incomplete character data. The
+ * conversion before the current one was complete.
*/
- statePtr->flags |= CHANNEL_NEED_MORE_DATA;
+ SetFlag(statePtr, CHANNEL_NEED_MORE_DATA);
}
return -1;
}
- /* Space is made at the beginning of the buffer to copy the
- * previous unused bytes there. Check first if the buffer we
- * are using actually has enough space at its beginning for
- * the data we are copying. Because if not we will write over the
- * buffer management information, especially the 'nextPtr'.
+ /*
+ * Space is made at the beginning of the buffer to copy the previous
+ * unused bytes there. Check first if the buffer we are using actually
+ * has enough space at its beginning for the data we are copying.
+ * Because if not we will write over the buffer management
+ * information, especially the 'nextPtr'.
*
- * Note that the BUFFER_PADDING (See AllocChannelBuffer) is
- * used to prevent exactly this situation. I.e. it should
- * never happen. Therefore it is ok to panic should it happen
- * despite the precautions.
+ * Note that the BUFFER_PADDING (See AllocChannelBuffer) is used to
+ * prevent exactly this situation. I.e. it should never happen.
+ * Therefore it is ok to panic should it happen despite the
+ * precautions.
*/
if (nextPtr->nextRemoved - srcLen < 0) {
- Tcl_Panic ("Buffer Underflow, BUFFER_PADDING not enough");
+ Tcl_Panic("Buffer Underflow, BUFFER_PADDING not enough");
}
nextPtr->nextRemoved -= srcLen;
- memcpy((VOID *) (nextPtr->buf + nextPtr->nextRemoved), (VOID *) src,
- (size_t) srcLen);
+ memcpy(RemovePoint(nextPtr), src, (size_t) srcLen);
RecycleBuffer(statePtr, bufPtr, 0);
statePtr->inQueueHead = nextPtr;
return ReadChars(statePtr, objPtr, charsToRead, offsetPtr, factorPtr);
@@ -4954,12 +5675,12 @@ ReadChars(statePtr, objPtr, charsToRead, offsetPtr, factorPtr)
dstRead = dstWrote;
if (TranslateInputEOL(statePtr, dst, dst, &dstWrote, &dstRead) != 0) {
/*
- * Hit EOF char. How many bytes of src correspond to where the
- * EOF was located in dst? Run the conversion again with an
- * output buffer just big enough to hold the data so we can
- * get the correct value for srcRead.
+ * Hit EOF char. How many bytes of src correspond to where the EOF was
+ * located in dst? Run the conversion again with an output buffer just
+ * big enough to hold the data so we can get the correct value for
+ * srcRead.
*/
-
+
if (dstWrote == 0) {
return -1;
}
@@ -4968,12 +5689,12 @@ ReadChars(statePtr, objPtr, charsToRead, offsetPtr, factorPtr)
statePtr->inputEncodingFlags, &statePtr->inputEncodingState,
dst, dstRead + TCL_UTF_MAX, &srcRead, &dstWrote, &numChars);
TranslateInputEOL(statePtr, dst, dst, &dstWrote, &dstRead);
- }
+ }
/*
- * The number of characters that we got may be less than the number
- * that we started with because "\r\n" sequences may have been
- * turned into just '\n' in dst.
+ * The number of characters that we got may be less than the number that
+ * we started with because "\r\n" sequences may have been turned into just
+ * '\n' in dst.
*/
numChars -= (dstRead - dstWrote);
@@ -4983,7 +5704,7 @@ ReadChars(statePtr, objPtr, charsToRead, offsetPtr, factorPtr)
* Got too many chars.
*/
- CONST char *eof;
+ const char *eof;
eof = Tcl_UtfAtIndex(dst, toRead);
statePtr->inputEncodingState = oldState;
@@ -5009,12 +5730,12 @@ ReadChars(statePtr, objPtr, charsToRead, offsetPtr, factorPtr)
*
* TranslateInputEOL --
*
- * Perform input EOL and EOF translation on the source buffer,
- * leaving the translated result in the destination buffer.
+ * Perform input EOL and EOF translation on the source buffer, leaving
+ * the translated result in the destination buffer.
*
* Results:
* The return value is 1 if the EOF character was found when copying
- * bytes to the destination buffer, 0 otherwise.
+ * bytes to the destination buffer, 0 otherwise.
*
* Side effects:
* None.
@@ -5023,23 +5744,23 @@ ReadChars(statePtr, objPtr, charsToRead, offsetPtr, factorPtr)
*/
static int
-TranslateInputEOL(statePtr, dstStart, srcStart, dstLenPtr, srcLenPtr)
- ChannelState *statePtr; /* Channel being read, for EOL translation
- * and EOF character. */
- char *dstStart; /* Output buffer filled with chars by
- * applying appropriate EOL translation to
- * source characters. */
- CONST char *srcStart; /* Source characters. */
- int *dstLenPtr; /* On entry, the maximum length of output
- * buffer in bytes; must be <= *srcLenPtr. On
+TranslateInputEOL(
+ ChannelState *statePtr, /* Channel being read, for EOL translation and
+ * EOF character. */
+ char *dstStart, /* Output buffer filled with chars by applying
+ * appropriate EOL translation to source
+ * characters. */
+ const char *srcStart, /* Source characters. */
+ int *dstLenPtr, /* On entry, the maximum length of output
+ * buffer in bytes; must be <= *srcLenPtr. On
* exit, the number of bytes actually used in
* output buffer. */
- int *srcLenPtr; /* On entry, the length of source buffer.
- * On exit, the number of bytes read from
- * the source buffer. */
+ int *srcLenPtr) /* On entry, the length of source buffer. On
+ * exit, the number of bytes read from the
+ * source buffer. */
{
int dstLen, srcLen, inEofChar;
- CONST char *eof;
+ const char *eof;
dstLen = *dstLenPtr;
@@ -5047,13 +5768,13 @@ TranslateInputEOL(statePtr, dstStart, srcStart, dstLenPtr, srcLenPtr)
inEofChar = statePtr->inEofChar;
if (inEofChar != '\0') {
/*
- * Find EOF in translated buffer then compress out the EOL. The
- * source buffer may be much longer than the destination buffer --
- * we only want to return EOF if the EOF has been copied to the
- * destination buffer.
+ * Find EOF in translated buffer then compress out the EOL. The source
+ * buffer may be much longer than the destination buffer - we only
+ * want to return EOF if the EOF has been copied to the destination
+ * buffer.
*/
- CONST char *src, *srcMax;
+ const char *src, *srcMax;
srcMax = srcStart + *srcLenPtr;
for (src = srcStart; src < srcMax; src++) {
@@ -5069,106 +5790,104 @@ TranslateInputEOL(statePtr, dstStart, srcStart, dstLenPtr, srcLenPtr)
}
}
switch (statePtr->inputTranslation) {
- case TCL_TRANSLATE_LF: {
- if (dstStart != srcStart) {
- memcpy((VOID *) dstStart, (VOID *) srcStart, (size_t) dstLen);
- }
- srcLen = dstLen;
- break;
- }
- case TCL_TRANSLATE_CR: {
- char *dst, *dstEnd;
-
- if (dstStart != srcStart) {
- memcpy((VOID *) dstStart, (VOID *) srcStart, (size_t) dstLen);
- }
- dstEnd = dstStart + dstLen;
- for (dst = dstStart; dst < dstEnd; dst++) {
- if (*dst == '\r') {
- *dst = '\n';
- }
+ case TCL_TRANSLATE_LF:
+ if (dstStart != srcStart) {
+ memcpy(dstStart, srcStart, (size_t) dstLen);
+ }
+ srcLen = dstLen;
+ break;
+ case TCL_TRANSLATE_CR: {
+ char *dst, *dstEnd;
+
+ if (dstStart != srcStart) {
+ memcpy(dstStart, srcStart, (size_t) dstLen);
+ }
+ dstEnd = dstStart + dstLen;
+ for (dst = dstStart; dst < dstEnd; dst++) {
+ if (*dst == '\r') {
+ *dst = '\n';
}
- srcLen = dstLen;
- break;
}
- case TCL_TRANSLATE_CRLF: {
- char *dst;
- CONST char *src, *srcEnd, *srcMax;
-
- dst = dstStart;
- src = srcStart;
- srcEnd = srcStart + dstLen;
- srcMax = srcStart + *srcLenPtr;
-
- for ( ; src < srcEnd; ) {
- if (*src == '\r') {
- src++;
- if (src >= srcMax) {
- statePtr->flags |= INPUT_NEED_NL;
- } else if (*src == '\n') {
- *dst++ = *src++;
- } else {
- *dst++ = '\r';
- }
- } else {
+ srcLen = dstLen;
+ break;
+ }
+ case TCL_TRANSLATE_CRLF: {
+ char *dst;
+ const char *src, *srcEnd, *srcMax;
+
+ dst = dstStart;
+ src = srcStart;
+ srcEnd = srcStart + dstLen;
+ srcMax = srcStart + *srcLenPtr;
+
+ for ( ; src < srcEnd; ) {
+ if (*src == '\r') {
+ src++;
+ if (src >= srcMax) {
+ SetFlag(statePtr, INPUT_NEED_NL);
+ } else if (*src == '\n') {
*dst++ = *src++;
+ } else {
+ *dst++ = '\r';
}
+ } else {
+ *dst++ = *src++;
}
- srcLen = src - srcStart;
- dstLen = dst - dstStart;
- break;
}
- case TCL_TRANSLATE_AUTO: {
- char *dst;
- CONST char *src, *srcEnd, *srcMax;
+ srcLen = src - srcStart;
+ dstLen = dst - dstStart;
+ break;
+ }
+ case TCL_TRANSLATE_AUTO: {
+ char *dst;
+ const char *src, *srcEnd, *srcMax;
- dst = dstStart;
- src = srcStart;
- srcEnd = srcStart + dstLen;
- srcMax = srcStart + *srcLenPtr;
+ dst = dstStart;
+ src = srcStart;
+ srcEnd = srcStart + dstLen;
+ srcMax = srcStart + *srcLenPtr;
- if ((statePtr->flags & INPUT_SAW_CR) && (src < srcMax)) {
- if (*src == '\n') {
- src++;
- }
- statePtr->flags &= ~INPUT_SAW_CR;
+ if ((statePtr->flags & INPUT_SAW_CR) && (src < srcMax)) {
+ if (*src == '\n') {
+ src++;
}
- for ( ; src < srcEnd; ) {
- if (*src == '\r') {
- src++;
- if (src >= srcMax) {
- statePtr->flags |= INPUT_SAW_CR;
- } else if (*src == '\n') {
- if (srcEnd < srcMax) {
- srcEnd++;
- }
- src++;
+ ResetFlag(statePtr, INPUT_SAW_CR);
+ }
+ for ( ; src < srcEnd; ) {
+ if (*src == '\r') {
+ src++;
+ if (src >= srcMax) {
+ SetFlag(statePtr, INPUT_SAW_CR);
+ } else if (*src == '\n') {
+ if (srcEnd < srcMax) {
+ srcEnd++;
}
- *dst++ = '\n';
- } else {
- *dst++ = *src++;
+ src++;
}
+ *dst++ = '\n';
+ } else {
+ *dst++ = *src++;
}
- srcLen = src - srcStart;
- dstLen = dst - dstStart;
- break;
- }
- default: { /* lint. */
- return 0;
}
+ srcLen = src - srcStart;
+ dstLen = dst - dstStart;
+ break;
+ }
+ default:
+ return 0;
}
*dstLenPtr = dstLen;
if ((eof != NULL) && (srcStart + srcLen >= eof)) {
/*
- * EOF character was seen in EOL translated range. Leave current
- * file position pointing at the EOF character, but don't store the
- * EOF character in the output string.
+ * EOF character was seen in EOL translated range. Leave current file
+ * position pointing at the EOF character, but don't store the EOF
+ * character in the output string.
*/
- statePtr->flags |= (CHANNEL_EOF | CHANNEL_STICKY_EOF);
+ SetFlag(statePtr, CHANNEL_EOF | CHANNEL_STICKY_EOF);
statePtr->inputEncodingFlags |= TCL_ENCODING_END;
- statePtr->flags &= ~(INPUT_SAW_CR | INPUT_NEED_NL);
+ ResetFlag(statePtr, INPUT_SAW_CR | INPUT_NEED_NL);
return 1;
}
@@ -5181,8 +5900,8 @@ TranslateInputEOL(statePtr, dstStart, srcStart, dstLenPtr, srcLenPtr)
*
* Tcl_Ungets --
*
- * Causes the supplied string to be added to the input queue of
- * the channel, at either the head or tail of the queue.
+ * Causes the supplied string to be added to the input queue of the
+ * channel, at either the head or tail of the queue.
*
* Results:
* The number of bytes stored in the channel, or -1 on error.
@@ -5194,17 +5913,17 @@ TranslateInputEOL(statePtr, dstStart, srcStart, dstLenPtr, srcLenPtr)
*/
int
-Tcl_Ungets(chan, str, len, atEnd)
- Tcl_Channel chan; /* The channel for which to add the input. */
- CONST char *str; /* The input itself. */
- int len; /* The length of the input. */
- int atEnd; /* If non-zero, add at end of queue; otherwise
- * add at head of queue. */
+Tcl_Ungets(
+ Tcl_Channel chan, /* The channel for which to add the input. */
+ const char *str, /* The input itself. */
+ int len, /* The length of the input. */
+ int atEnd) /* If non-zero, add at end of queue; otherwise
+ * add at head of queue. */
{
Channel *chanPtr; /* The real IO channel. */
ChannelState *statePtr; /* State of actual channel. */
ChannelBuffer *bufPtr; /* Buffer to contain the data. */
- int i, flags;
+ int flags;
chanPtr = (Channel *) chan;
statePtr = chanPtr->state;
@@ -5218,7 +5937,7 @@ Tcl_Ungets(chan, str, len, atEnd)
/*
* CheckChannelErrors clears too many flag bits in this one case.
*/
-
+
flags = statePtr->flags;
if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) {
len = -1;
@@ -5227,42 +5946,40 @@ Tcl_Ungets(chan, str, len, atEnd)
statePtr->flags = flags;
/*
- * If we have encountered a sticky EOF, just punt without storing.
- * (sticky EOF is set if we have seen the input eofChar, to prevent
- * reading beyond the eofChar). Otherwise, clear the EOF flags, and
- * clear the BLOCKED bit. We want to discover these conditions anew
- * in each operation.
+ * If we have encountered a sticky EOF, just punt without storing (sticky
+ * EOF is set if we have seen the input eofChar, to prevent reading beyond
+ * the eofChar). Otherwise, clear the EOF flags, and clear the BLOCKED
+ * bit. We want to discover these conditions anew in each operation.
*/
if (statePtr->flags & CHANNEL_STICKY_EOF) {
goto done;
}
- statePtr->flags &= (~(CHANNEL_BLOCKED | CHANNEL_EOF));
+ ResetFlag(statePtr, CHANNEL_BLOCKED | CHANNEL_EOF);
bufPtr = AllocChannelBuffer(len);
- for (i = 0; i < len; i++) {
- bufPtr->buf[bufPtr->nextAdded++] = str[i];
- }
+ memcpy(InsertPoint(bufPtr), str, (size_t) len);
+ bufPtr->nextAdded += len;
- if (statePtr->inQueueHead == (ChannelBuffer *) NULL) {
- bufPtr->nextPtr = (ChannelBuffer *) NULL;
- statePtr->inQueueHead = bufPtr;
- statePtr->inQueueTail = bufPtr;
+ if (statePtr->inQueueHead == NULL) {
+ bufPtr->nextPtr = NULL;
+ statePtr->inQueueHead = bufPtr;
+ statePtr->inQueueTail = bufPtr;
} else if (atEnd) {
- bufPtr->nextPtr = (ChannelBuffer *) NULL;
- statePtr->inQueueTail->nextPtr = bufPtr;
- statePtr->inQueueTail = bufPtr;
+ bufPtr->nextPtr = NULL;
+ statePtr->inQueueTail->nextPtr = bufPtr;
+ statePtr->inQueueTail = bufPtr;
} else {
- bufPtr->nextPtr = statePtr->inQueueHead;
- statePtr->inQueueHead = bufPtr;
+ bufPtr->nextPtr = statePtr->inQueueHead;
+ statePtr->inQueueHead = bufPtr;
}
- done:
/*
- * Update the notifier state so we don't block while there is still
- * data in the buffers.
+ * Update the notifier state so we don't block while there is still data
+ * in the buffers.
*/
+ done:
UpdateInterest(chanPtr);
return len;
}
@@ -5284,12 +6001,14 @@ Tcl_Ungets(chan, str, len, atEnd)
*/
int
-Tcl_Flush(chan)
- Tcl_Channel chan; /* The Channel to flush. */
+Tcl_Flush(
+ Tcl_Channel chan) /* The Channel to flush. */
{
- int result; /* Of calling FlushChannel. */
- Channel *chanPtr = (Channel *) chan; /* The actual channel. */
- ChannelState *statePtr = chanPtr->state; /* State of actual channel. */
+ int result; /* Of calling FlushChannel. */
+ Channel *chanPtr = (Channel *) chan;
+ /* The actual channel. */
+ ChannelState *statePtr = chanPtr->state;
+ /* State of actual channel. */
/*
* This operation should occur at the top of a channel stack.
@@ -5305,14 +6024,13 @@ Tcl_Flush(chan)
* Force current output buffer to be output also.
*/
- if ((statePtr->curOutPtr != NULL)
- && (statePtr->curOutPtr->nextAdded > 0)) {
- statePtr->flags |= BUFFER_READY;
+ if ((statePtr->curOutPtr != NULL) && IsBufferReady(statePtr->curOutPtr)) {
+ SetFlag(statePtr, BUFFER_READY);
}
-
+
result = FlushChannel(NULL, chanPtr, 0);
if (result != 0) {
- return TCL_ERROR;
+ return TCL_ERROR;
}
return TCL_OK;
@@ -5323,8 +6041,8 @@ Tcl_Flush(chan)
*
* DiscardInputQueued --
*
- * Discards any input read from the channel but not yet consumed
- * by Tcl reading commands.
+ * Discards any input read from the channel but not yet consumed by Tcl
+ * reading commands.
*
* Results:
* None.
@@ -5337,32 +6055,31 @@ Tcl_Flush(chan)
*/
static void
-DiscardInputQueued(statePtr, discardSavedBuffers)
- ChannelState *statePtr; /* Channel on which to discard
- * the queued input. */
- int discardSavedBuffers; /* If non-zero, discard all buffers including
- * last one. */
+DiscardInputQueued(
+ ChannelState *statePtr, /* Channel on which to discard the queued
+ * input. */
+ int discardSavedBuffers) /* If non-zero, discard all buffers including
+ * last one. */
{
- ChannelBuffer *bufPtr, *nxtPtr; /* Loop variables. */
+ ChannelBuffer *bufPtr, *nxtPtr;
+ /* Loop variables. */
bufPtr = statePtr->inQueueHead;
- statePtr->inQueueHead = (ChannelBuffer *) NULL;
- statePtr->inQueueTail = (ChannelBuffer *) NULL;
- for (; bufPtr != (ChannelBuffer *) NULL; bufPtr = nxtPtr) {
- nxtPtr = bufPtr->nextPtr;
- RecycleBuffer(statePtr, bufPtr, discardSavedBuffers);
+ statePtr->inQueueHead = NULL;
+ statePtr->inQueueTail = NULL;
+ for (; bufPtr != NULL; bufPtr = nxtPtr) {
+ nxtPtr = bufPtr->nextPtr;
+ RecycleBuffer(statePtr, bufPtr, discardSavedBuffers);
}
/*
* If discardSavedBuffers is nonzero, must also discard any previously
* saved buffer in the saveInBufPtr field.
*/
-
- if (discardSavedBuffers) {
- if (statePtr->saveInBufPtr != (ChannelBuffer *) NULL) {
- ckfree((char *) statePtr->saveInBufPtr);
- statePtr->saveInBufPtr = (ChannelBuffer *) NULL;
- }
+
+ if (discardSavedBuffers && statePtr->saveInBufPtr != NULL) {
+ ckfree((char *) statePtr->saveInBufPtr);
+ statePtr->saveInBufPtr = NULL;
}
}
@@ -5371,11 +6088,11 @@ DiscardInputQueued(statePtr, discardSavedBuffers)
*
* GetInput --
*
- * Reads input data from a device into a channel buffer.
+ * Reads input data from a device into a channel buffer.
*
* Results:
* The return value is the Posix error code if an error occurred while
- * reading from the file, or 0 otherwise.
+ * reading from the file, or 0 otherwise.
*
* Side effects:
* Reads from the underlying device.
@@ -5384,14 +6101,15 @@ DiscardInputQueued(statePtr, discardSavedBuffers)
*/
static int
-GetInput(chanPtr)
- Channel *chanPtr; /* Channel to read input from. */
+GetInput(
+ Channel *chanPtr) /* Channel to read input from. */
{
int toRead; /* How much to read? */
int result; /* Of calling driver. */
int nread; /* How much was read from channel? */
ChannelBuffer *bufPtr; /* New buffer to add to input queue. */
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
/*
* Prevent reading from a dead channel -- a channel that has been closed
@@ -5399,90 +6117,91 @@ GetInput(chanPtr)
* channel cleanup has run but the channel is still registered in some
* interpreter.
*/
-
+
if (CheckForDeadChannel(NULL, statePtr)) {
return EINVAL;
}
/*
- * First check for more buffers in the pushback area of the
- * topmost channel in the stack and use them. They can be the
- * result of a transformation which went away without reading all
- * the information placed in the area when it was stacked.
+ * First check for more buffers in the pushback area of the topmost
+ * channel in the stack and use them. They can be the result of a
+ * transformation which went away without reading all the information
+ * placed in the area when it was stacked.
*
- * Two possibilities for the state: No buffers in it, or a single
- * empty buffer. In the latter case we can recycle it now.
+ * Two possibilities for the state: No buffers in it, or a single empty
+ * buffer. In the latter case we can recycle it now.
*/
- if (chanPtr->inQueueHead != (ChannelBuffer*) NULL) {
- if (statePtr->inQueueHead != (ChannelBuffer*) NULL) {
+ if (chanPtr->inQueueHead != NULL) {
+ if (statePtr->inQueueHead != NULL) {
RecycleBuffer(statePtr, statePtr->inQueueHead, 0);
- statePtr->inQueueHead = (ChannelBuffer*) NULL;
+ statePtr->inQueueHead = NULL;
}
statePtr->inQueueHead = chanPtr->inQueueHead;
statePtr->inQueueTail = chanPtr->inQueueTail;
- chanPtr->inQueueHead = (ChannelBuffer*) NULL;
- chanPtr->inQueueTail = (ChannelBuffer*) NULL;
+ chanPtr->inQueueHead = NULL;
+ chanPtr->inQueueTail = NULL;
return 0;
}
/*
- * Nothing in the pushback area, fall back to the usual handling
- * (driver, etc.)
+ * Nothing in the pushback area, fall back to the usual handling (driver,
+ * etc.)
*/
/*
- * See if we can fill an existing buffer. If we can, read only
- * as much as will fit in it. Otherwise allocate a new buffer,
- * add it to the input queue and attempt to fill it to the max.
+ * See if we can fill an existing buffer. If we can, read only as much as
+ * will fit in it. Otherwise allocate a new buffer, add it to the input
+ * queue and attempt to fill it to the max.
*/
bufPtr = statePtr->inQueueTail;
- if ((bufPtr != NULL) && (bufPtr->nextAdded < bufPtr->bufLength)) {
- toRead = bufPtr->bufLength - bufPtr->nextAdded;
+ if ((bufPtr != NULL) && !IsBufferFull(bufPtr)) {
+ toRead = SpaceLeft(bufPtr);
} else {
bufPtr = statePtr->saveInBufPtr;
statePtr->saveInBufPtr = NULL;
/*
- * Check the actual buffersize against the requested
- * buffersize. Buffers which are smaller than requested are
- * squashed. This is done to honor dynamic changes of the
- * buffersize made by the user.
+ * Check the actual buffersize against the requested buffersize.
+ * Buffers which are smaller than requested are squashed. This is done
+ * to honor dynamic changes of the buffersize made by the user.
*/
- if ((bufPtr != NULL) && ((bufPtr->bufLength - BUFFER_PADDING) < statePtr->bufSize)) {
- ckfree((char *) bufPtr);
- bufPtr = NULL;
+ if ((bufPtr != NULL)
+ && (bufPtr->bufLength - BUFFER_PADDING < statePtr->bufSize)) {
+ ckfree((char *) bufPtr);
+ bufPtr = NULL;
}
if (bufPtr == NULL) {
bufPtr = AllocChannelBuffer(statePtr->bufSize);
}
- bufPtr->nextPtr = (ChannelBuffer *) NULL;
+ bufPtr->nextPtr = NULL;
- /* SF #427196: Use the actual size of the buffer to determine
- * the number of bytes to read from the channel and not the
- * size for new buffers. They can be different if the
- * buffersize was changed between reads.
+ /*
+ * SF #427196: Use the actual size of the buffer to determine the
+ * number of bytes to read from the channel and not the size for new
+ * buffers. They can be different if the buffersize was changed
+ * between reads.
*
- * Note: This affects performance negatively if the buffersize
- * was extended but this small buffer is reused for all
- * subsequent reads. The system never uses buffers with the
- * requested bigger size in that case. An adjunct patch could
- * try and delete all unused buffers it encounters and which
- * are smaller than the formally requested buffersize.
+ * Note: This affects performance negatively if the buffersize was
+ * extended but this small buffer is reused for all subsequent reads.
+ * The system never uses buffers with the requested bigger size in
+ * that case. An adjunct patch could try and delete all unused buffers
+ * it encounters and which are smaller than the formally requested
+ * buffersize.
*/
- toRead = bufPtr->bufLength - bufPtr->nextAdded;
+ toRead = SpaceLeft(bufPtr);
- if (statePtr->inQueueTail == NULL) {
- statePtr->inQueueHead = bufPtr;
- } else {
- statePtr->inQueueTail->nextPtr = bufPtr;
- }
- statePtr->inQueueTail = bufPtr;
+ if (statePtr->inQueueTail == NULL) {
+ statePtr->inQueueHead = bufPtr;
+ } else {
+ statePtr->inQueueTail->nextPtr = bufPtr;
+ }
+ statePtr->inQueueTail = bufPtr;
}
/*
@@ -5495,24 +6214,27 @@ GetInput(chanPtr)
}
#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
- /* [SF Tcl Bug 943274]. Better emulation of non-blocking channels
- * for channels without BlockModeProc, by keeping track of true
- * fileevents generated by the OS == Data waiting and reading if
- * and only if we are sure to have data.
+ /*
+ * [SF Tcl Bug 943274]. Better emulation of non-blocking channels for
+ * channels without BlockModeProc, by keeping track of true fileevents
+ * generated by the OS == Data waiting and reading if and only if we are
+ * sure to have data.
*/
if ((statePtr->flags & CHANNEL_NONBLOCKING) &&
- (Tcl_ChannelBlockModeProc(chanPtr->typePtr) == NULL) &&
- !(statePtr->flags & CHANNEL_HAS_MORE_DATA)) {
+ (Tcl_ChannelBlockModeProc(chanPtr->typePtr) == NULL) &&
+ !(statePtr->flags & CHANNEL_HAS_MORE_DATA)) {
+ /*
+ * Bypass the driver, it would block, as no data is available
+ */
- /* Bypass the driver, it would block, as no data is available */
- nread = -1;
- result = EWOULDBLOCK;
+ nread = -1;
+ result = EWOULDBLOCK;
} else {
#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */
- nread = (chanPtr->typePtr->inputProc)(chanPtr->instanceData,
- bufPtr->buf + bufPtr->nextAdded, toRead, &result);
+ nread = (chanPtr->typePtr->inputProc)(chanPtr->instanceData,
+ InsertPoint(bufPtr), toRead, &result);
#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
}
@@ -5522,30 +6244,33 @@ GetInput(chanPtr)
bufPtr->nextAdded += nread;
/*
- * If we get a short read, signal up that we may be BLOCKED. We
- * should avoid calling the driver because on some platforms we
- * will block in the low level reading code even though the
- * channel is set into nonblocking mode.
+ * If we get a short read, signal up that we may be BLOCKED. We should
+ * avoid calling the driver because on some platforms we will block in
+ * the low level reading code even though the channel is set into
+ * nonblocking mode.
*/
-
+
if (nread < toRead) {
- statePtr->flags |= CHANNEL_BLOCKED;
+ SetFlag(statePtr, CHANNEL_BLOCKED);
}
#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
if (nread <= toRead) {
- /* [SF Tcl Bug 943274] We have read the available data,
- * clear flag */
- statePtr->flags &= ~CHANNEL_HAS_MORE_DATA;
+ /*
+ * [SF Tcl Bug 943274] We have read the available data, clear
+ * flag.
+ */
+
+ ResetFlag(statePtr, CHANNEL_HAS_MORE_DATA);
}
#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */
} else if (nread == 0) {
- statePtr->flags |= CHANNEL_EOF;
+ SetFlag(statePtr, CHANNEL_EOF);
statePtr->inputEncodingFlags |= TCL_ENCODING_END;
} else if (nread < 0) {
if ((result == EWOULDBLOCK) || (result == EAGAIN)) {
- statePtr->flags |= CHANNEL_BLOCKED;
+ SetFlag(statePtr, CHANNEL_BLOCKED);
result = EAGAIN;
}
Tcl_SetErrno(result);
@@ -5559,12 +6284,12 @@ GetInput(chanPtr)
*
* Tcl_Seek --
*
- * Implements seeking on Tcl Channels. This is a public function
- * so that other C facilities may be implemented on top of it.
+ * Implements seeking on Tcl Channels. This is a public function so that
+ * other C facilities may be implemented on top of it.
*
* Results:
- * The new access point or -1 on error. If error, use Tcl_GetErrno()
- * to retrieve the POSIX error code for the error that occurred.
+ * The new access point or -1 on error. If error, use Tcl_GetErrno() to
+ * retrieve the POSIX error code for the error that occurred.
*
* Side effects:
* May flush output on the channel. May discard queued input.
@@ -5573,30 +6298,32 @@ GetInput(chanPtr)
*/
Tcl_WideInt
-Tcl_Seek(chan, offset, mode)
- Tcl_Channel chan; /* The channel on which to seek. */
- Tcl_WideInt offset; /* Offset to seek to. */
- int mode; /* Relative to which location to seek? */
+Tcl_Seek(
+ Tcl_Channel chan, /* The channel on which to seek. */
+ Tcl_WideInt offset, /* Offset to seek to. */
+ int mode) /* Relative to which location to seek? */
{
- Channel *chanPtr = (Channel *) chan; /* The real IO channel. */
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+ Channel *chanPtr = (Channel *) chan;
+ /* The real IO channel. */
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
int inputBuffered, outputBuffered;
/* # bytes held in buffers. */
int result; /* Of device driver operations. */
Tcl_WideInt curPos; /* Position on the device. */
- int wasAsync; /* Was the channel nonblocking before the
- * seek operation? If so, must restore to
- * nonblocking mode after the seek. */
+ int wasAsync; /* Was the channel nonblocking before the seek
+ * operation? If so, must restore to
+ * non-blocking mode after the seek. */
if (CheckChannelErrors(statePtr, TCL_WRITABLE | TCL_READABLE) != 0) {
return Tcl_LongAsWide(-1);
}
/*
- * Disallow seek on dead channels -- channels that have been closed but
- * not yet been deallocated. Such channels can be found if the exit
- * handler for channel cleanup has run but the channel is still
- * registered in an interpreter.
+ * Disallow seek on dead channels - channels that have been closed but not
+ * yet been deallocated. Such channels can be found if the exit handler
+ * for channel cleanup has run but the channel is still registered in an
+ * interpreter.
*/
if (CheckForDeadChannel(NULL, statePtr)) {
@@ -5614,22 +6341,22 @@ Tcl_Seek(chan, offset, mode)
* defined. This means that the channel does not support seeking.
*/
- if (chanPtr->typePtr->seekProc == (Tcl_DriverSeekProc *) NULL) {
- Tcl_SetErrno(EINVAL);
- return Tcl_LongAsWide(-1);
+ if (chanPtr->typePtr->seekProc == NULL) {
+ Tcl_SetErrno(EINVAL);
+ return Tcl_LongAsWide(-1);
}
/*
- * Compute how much input and output is buffered. If both input and
- * output is buffered, cannot compute the current position.
+ * Compute how much input and output is buffered. If both input and output
+ * is buffered, cannot compute the current position.
*/
inputBuffered = Tcl_InputBuffered(chan);
outputBuffered = Tcl_OutputBuffered(chan);
if ((inputBuffered != 0) && (outputBuffered != 0)) {
- Tcl_SetErrno(EFAULT);
- return Tcl_LongAsWide(-1);
+ Tcl_SetErrno(EFAULT);
+ return Tcl_LongAsWide(-1);
}
/*
@@ -5638,61 +6365,69 @@ Tcl_Seek(chan, offset, mode)
*/
if (mode == SEEK_CUR) {
- offset -= inputBuffered;
+ offset -= inputBuffered;
}
/*
- * Discard any queued input - this input should not be read after
- * the seek.
+ * Discard any queued input - this input should not be read after the
+ * seek.
*/
DiscardInputQueued(statePtr, 0);
/*
- * Reset EOF and BLOCKED flags. We invalidate them by moving the
- * access point. Also clear CR related flags.
+ * Reset EOF and BLOCKED flags. We invalidate them by moving the access
+ * point. Also clear CR related flags.
*/
statePtr->flags &=
- (~(CHANNEL_EOF | CHANNEL_STICKY_EOF | CHANNEL_BLOCKED | INPUT_SAW_CR));
-
+ ~(CHANNEL_EOF | CHANNEL_STICKY_EOF | CHANNEL_BLOCKED | INPUT_SAW_CR);
+
/*
- * If the channel is in asynchronous output mode, switch it back
- * to synchronous mode and cancel any async flush that may be
- * scheduled. After the flush, the channel will be put back into
- * asynchronous output mode.
+ * If the channel is in asynchronous output mode, switch it back to
+ * synchronous mode and cancel any async flush that may be scheduled.
+ * After the flush, the channel will be put back into asynchronous output
+ * mode.
*/
wasAsync = 0;
if (statePtr->flags & CHANNEL_NONBLOCKING) {
- wasAsync = 1;
- result = StackSetBlockMode(chanPtr, TCL_MODE_BLOCKING);
+ wasAsync = 1;
+ result = StackSetBlockMode(chanPtr, TCL_MODE_BLOCKING);
if (result != 0) {
return Tcl_LongAsWide(-1);
}
- statePtr->flags &= (~(CHANNEL_NONBLOCKING));
- if (statePtr->flags & BG_FLUSH_SCHEDULED) {
- statePtr->flags &= (~(BG_FLUSH_SCHEDULED));
- }
+ ResetFlag(statePtr, CHANNEL_NONBLOCKING);
+ if (statePtr->flags & BG_FLUSH_SCHEDULED) {
+ ResetFlag(statePtr, BG_FLUSH_SCHEDULED);
+ }
}
-
+
/*
- * If the flush fails we cannot recover the original position. In
- * that case the seek is not attempted because we do not know where
- * the access position is - instead we return the error. FlushChannel
- * has already called Tcl_SetErrno() to report the error upwards.
- * If the flush succeeds we do the seek also.
+ * If there is data buffered in statePtr->curOutPtr then mark the channel
+ * as ready to flush before invoking FlushChannel.
*/
-
+
+ if ((statePtr->curOutPtr != NULL) && IsBufferReady(statePtr->curOutPtr)) {
+ SetFlag(statePtr, BUFFER_READY);
+ }
+
+ /*
+ * If the flush fails we cannot recover the original position. In that
+ * case the seek is not attempted because we do not know where the access
+ * position is - instead we return the error. FlushChannel has already
+ * called Tcl_SetErrno() to report the error upwards. If the flush
+ * succeeds we do the seek also.
+ */
+
if (FlushChannel(NULL, chanPtr, 0) != 0) {
- curPos = -1;
+ curPos = -1;
} else {
-
- /*
- * Now seek to the new position in the channel as requested by the
- * caller. Note that we prefer the wideSeekProc if that is
- * available and non-NULL...
- */
+ /*
+ * Now seek to the new position in the channel as requested by the
+ * caller. Note that we prefer the wideSeekProc if that is available
+ * and non-NULL...
+ */
if (HaveVersion(chanPtr->typePtr, TCL_CHANNEL_VERSION_3) &&
chanPtr->typePtr->wideSeekProc != NULL) {
@@ -5711,17 +6446,17 @@ Tcl_Seek(chan, offset, mode)
Tcl_SetErrno(result);
}
}
-
+
/*
* Restore to nonblocking mode if that was the previous behavior.
*
- * NOTE: Even if there was an async flush active we do not restore
- * it now because we already flushed all the queued output, above.
+ * NOTE: Even if there was an async flush active we do not restore it now
+ * because we already flushed all the queued output, above.
*/
-
+
if (wasAsync) {
- statePtr->flags |= CHANNEL_NONBLOCKING;
- result = StackSetBlockMode(chanPtr, TCL_MODE_NONBLOCKING);
+ SetFlag(statePtr, CHANNEL_NONBLOCKING);
+ result = StackSetBlockMode(chanPtr, TCL_MODE_NONBLOCKING);
if (result != 0) {
return Tcl_LongAsWide(-1);
}
@@ -5735,13 +6470,13 @@ Tcl_Seek(chan, offset, mode)
*
* Tcl_Tell --
*
- * Returns the position of the next character to be read/written on
- * this channel.
+ * Returns the position of the next character to be read/written on this
+ * channel.
*
* Results:
- * A nonnegative integer on success, -1 on failure. If failed,
- * use Tcl_GetErrno() to retrieve the POSIX error code for the
- * error that occurred.
+ * A nonnegative integer on success, -1 on failure. If failed, use
+ * Tcl_GetErrno() to retrieve the POSIX error code for the error that
+ * occurred.
*
* Side effects:
* None.
@@ -5750,14 +6485,17 @@ Tcl_Seek(chan, offset, mode)
*/
Tcl_WideInt
-Tcl_Tell(chan)
- Tcl_Channel chan; /* The channel to return pos for. */
+Tcl_Tell(
+ Tcl_Channel chan) /* The channel to return pos for. */
{
- Channel *chanPtr = (Channel *) chan; /* The real IO channel. */
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
- int inputBuffered, outputBuffered; /* # bytes held in buffers. */
- int result; /* Of calling device driver. */
- Tcl_WideInt curPos; /* Position on device. */
+ Channel *chanPtr = (Channel *) chan;
+ /* The real IO channel. */
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
+ int inputBuffered, outputBuffered;
+ /* # bytes held in buffers. */
+ int result; /* Of calling device driver. */
+ Tcl_WideInt curPos; /* Position on device. */
if (CheckChannelErrors(statePtr, TCL_WRITABLE | TCL_READABLE) != 0) {
return Tcl_LongAsWide(-1);
@@ -5766,8 +6504,8 @@ Tcl_Tell(chan)
/*
* Disallow tell on dead channels -- channels that have been closed but
* not yet been deallocated. Such channels can be found if the exit
- * handler for channel cleanup has run but the channel is still
- * registered in an interpreter.
+ * handler for channel cleanup has run but the channel is still registered
+ * in an interpreter.
*/
if (CheckForDeadChannel(NULL, statePtr)) {
@@ -5785,28 +6523,28 @@ Tcl_Tell(chan)
* defined. This means that the channel does not support seeking.
*/
- if (chanPtr->typePtr->seekProc == (Tcl_DriverSeekProc *) NULL) {
- Tcl_SetErrno(EINVAL);
- return Tcl_LongAsWide(-1);
+ if (chanPtr->typePtr->seekProc == NULL) {
+ Tcl_SetErrno(EINVAL);
+ return Tcl_LongAsWide(-1);
}
/*
- * Compute how much input and output is buffered. If both input and
- * output is buffered, cannot compute the current position.
+ * Compute how much input and output is buffered. If both input and output
+ * is buffered, cannot compute the current position.
*/
inputBuffered = Tcl_InputBuffered(chan);
outputBuffered = Tcl_OutputBuffered(chan);
if ((inputBuffered != 0) && (outputBuffered != 0)) {
- Tcl_SetErrno(EFAULT);
- return Tcl_LongAsWide(-1);
+ Tcl_SetErrno(EFAULT);
+ return Tcl_LongAsWide(-1);
}
/*
- * Get the current position in the device and compute the position
- * where the next character will be read or written. Note that we
- * prefer the wideSeekProc if that is available and non-NULL...
+ * Get the current position in the device and compute the position where
+ * the next character will be read or written. Note that we prefer the
+ * wideSeekProc if that is available and non-NULL...
*/
if (HaveVersion(chanPtr->typePtr, TCL_CHANNEL_VERSION_3) &&
@@ -5818,11 +6556,11 @@ Tcl_Tell(chan)
chanPtr->instanceData, 0, SEEK_CUR, &result));
}
if (curPos == Tcl_LongAsWide(-1)) {
- Tcl_SetErrno(result);
- return Tcl_LongAsWide(-1);
+ Tcl_SetErrno(result);
+ return Tcl_LongAsWide(-1);
}
if (inputBuffered != 0) {
- return curPos - inputBuffered;
+ return curPos - inputBuffered;
}
return curPos + outputBuffered;
}
@@ -5832,9 +6570,9 @@ Tcl_Tell(chan)
*
* Tcl_SeekOld, Tcl_TellOld --
*
- * Backward-compatability versions of the seek/tell interface that
- * do not support 64-bit offsets. This interface is not documented
- * or expected to be supported indefinitely.
+ * Backward-compatability versions of the seek/tell interface that do not
+ * support 64-bit offsets. This interface is not documented or expected
+ * to be supported indefinitely.
*
* Results:
* As for Tcl_Seek and Tcl_Tell respectively, except truncated to
@@ -5847,10 +6585,10 @@ Tcl_Tell(chan)
*/
int
-Tcl_SeekOld(chan, offset, mode)
- Tcl_Channel chan; /* The channel on which to seek. */
- int offset; /* Offset to seek to. */
- int mode; /* Relative to which location to seek? */
+Tcl_SeekOld(
+ Tcl_Channel chan, /* The channel on which to seek. */
+ int offset, /* Offset to seek to. */
+ int mode) /* Relative to which location to seek? */
{
Tcl_WideInt wOffset, wResult;
@@ -5860,8 +6598,8 @@ Tcl_SeekOld(chan, offset, mode)
}
int
-Tcl_TellOld(chan)
- Tcl_Channel chan; /* The channel to return pos for. */
+Tcl_TellOld(
+ Tcl_Channel chan) /* The channel to return pos for. */
{
Tcl_WideInt wResult;
@@ -5872,28 +6610,98 @@ Tcl_TellOld(chan)
/*
*---------------------------------------------------------------------------
*
+ * Tcl_TruncateChannel --
+ *
+ * Truncate a channel to the given length.
+ *
+ * Results:
+ * TCL_OK on success, TCL_ERROR if the operation failed (e.g. is not
+ * supported by the type of channel, or the underlying OS operation
+ * failed in some way).
+ *
+ * Side effects:
+ * Seeks the channel to the current location. Sets errno on OS error.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+Tcl_TruncateChannel(
+ Tcl_Channel chan, /* Channel to truncate. */
+ Tcl_WideInt length) /* Length to truncate it to. */
+{
+ Channel *chanPtr = (Channel *) chan;
+ Tcl_DriverTruncateProc *truncateProc =
+ Tcl_ChannelTruncateProc(chanPtr->typePtr);
+ int result;
+
+ if (truncateProc == NULL) {
+ /*
+ * Feature not supported and it's not emulatable. Pretend it's
+ * returned an EINVAL, a very generic error!
+ */
+
+ Tcl_SetErrno(EINVAL);
+ return TCL_ERROR;
+ }
+
+ if (!(chanPtr->state->flags & TCL_WRITABLE)) {
+ /*
+ * We require that the file was opened of writing. Do that check now
+ * so that we only flush if we think we're going to succeed.
+ */
+
+ Tcl_SetErrno(EINVAL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Seek first to force a total flush of all pending buffers and ditch any
+ * pre-read input data.
+ */
+
+ if (Tcl_Seek(chan, (Tcl_WideInt)0, SEEK_CUR) == Tcl_LongAsWide(-1)) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * We're all flushed to disk now and we also don't have any unfortunate
+ * input baggage around either; can truncate with impunity.
+ */
+
+ result = truncateProc(chanPtr->instanceData, length);
+ if (result != 0) {
+ Tcl_SetErrno(result);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
* CheckChannelErrors --
*
- * See if the channel is in an ready state and can perform the
- * desired operation.
+ * See if the channel is in an ready state and can perform the desired
+ * operation.
*
* Results:
- * The return value is 0 if the channel is OK, otherwise the
- * return value is -1 and errno is set to indicate the error.
+ * The return value is 0 if the channel is OK, otherwise the return value
+ * is -1 and errno is set to indicate the error.
*
* Side effects:
* May clear the EOF and/or BLOCKED bits if reading from channel.
*
*---------------------------------------------------------------------------
*/
-
+
static int
-CheckChannelErrors(statePtr, flags)
- ChannelState *statePtr; /* Channel to check. */
- int flags; /* Test if channel supports desired operation:
- * TCL_READABLE, TCL_WRITABLE. Also indicates
+CheckChannelErrors(
+ ChannelState *statePtr, /* Channel to check. */
+ int flags) /* Test if channel supports desired operation:
+ * TCL_READABLE, TCL_WRITABLE. Also indicates
* Raw read or write for special close
- * processing*/
+ * processing */
{
int direction = flags & (TCL_READABLE|TCL_WRITABLE);
@@ -5902,20 +6710,31 @@ CheckChannelErrors(statePtr, flags)
*/
if (statePtr->unreportedError != 0) {
- Tcl_SetErrno(statePtr->unreportedError);
- statePtr->unreportedError = 0;
- return -1;
+ Tcl_SetErrno(statePtr->unreportedError);
+ statePtr->unreportedError = 0;
+
+ /*
+ * TIP #219, Tcl Channel Reflection API.
+ * Move a defered error message back into the channel bypass.
+ */
+
+ if (statePtr->chanMsg != NULL) {
+ TclDecrRefCount(statePtr->chanMsg);
+ }
+ statePtr->chanMsg = statePtr->unreportedMsg;
+ statePtr->unreportedMsg = NULL;
+ return -1;
}
/*
- * Only the raw read and write operations are allowed during close
- * in order to drain data from stacked channels.
+ * Only the raw read and write operations are allowed during close in
+ * order to drain data from stacked channels.
*/
if ((statePtr->flags & CHANNEL_CLOSED) &&
((flags & CHANNEL_RAW_MODE) == 0)) {
- Tcl_SetErrno(EACCES);
- return -1;
+ Tcl_SetErrno(EACCES);
+ return -1;
}
/*
@@ -5923,8 +6742,8 @@ CheckChannelErrors(statePtr, flags)
*/
if ((statePtr->flags & direction) == 0) {
- Tcl_SetErrno(EACCES);
- return -1;
+ Tcl_SetErrno(EACCES);
+ return -1;
}
/*
@@ -5942,16 +6761,16 @@ CheckChannelErrors(statePtr, flags)
if (direction == TCL_READABLE) {
/*
- * If we have not encountered a sticky EOF, clear the EOF bit
- * (sticky EOF is set if we have seen the input eofChar, to prevent
- * reading beyond the eofChar). Also, always clear the BLOCKED bit.
- * We want to discover these conditions anew in each operation.
+ * If we have not encountered a sticky EOF, clear the EOF bit (sticky
+ * EOF is set if we have seen the input eofChar, to prevent reading
+ * beyond the eofChar). Also, always clear the BLOCKED bit. We want to
+ * discover these conditions anew in each operation.
*/
if ((statePtr->flags & CHANNEL_STICKY_EOF) == 0) {
- statePtr->flags &= ~CHANNEL_EOF;
+ ResetFlag(statePtr, CHANNEL_EOF);
}
- statePtr->flags &= ~(CHANNEL_BLOCKED | CHANNEL_NEED_MORE_DATA);
+ ResetFlag(statePtr, CHANNEL_BLOCKED | CHANNEL_NEED_MORE_DATA);
}
return 0;
@@ -5974,15 +6793,15 @@ CheckChannelErrors(statePtr, flags)
*/
int
-Tcl_Eof(chan)
- Tcl_Channel chan; /* Does this channel have EOF? */
+Tcl_Eof(
+ Tcl_Channel chan) /* Does this channel have EOF? */
{
ChannelState *statePtr = ((Channel *) chan)->state;
- /* State of real channel structure. */
+ /* State of real channel structure. */
return ((statePtr->flags & CHANNEL_STICKY_EOF) ||
- ((statePtr->flags & CHANNEL_EOF) &&
- (Tcl_InputBuffered(chan) == 0))) ? 1 : 0;
+ ((statePtr->flags & CHANNEL_EOF) &&
+ (Tcl_InputBuffered(chan) == 0))) ? 1 : 0;
}
/*
@@ -6002,11 +6821,11 @@ Tcl_Eof(chan)
*/
int
-Tcl_InputBlocked(chan)
- Tcl_Channel chan; /* Is this channel blocked? */
+Tcl_InputBlocked(
+ Tcl_Channel chan) /* Is this channel blocked? */
{
ChannelState *statePtr = ((Channel *) chan)->state;
- /* State of real channel structure. */
+ /* State of real channel structure. */
return (statePtr->flags & CHANNEL_BLOCKED) ? 1 : 0;
}
@@ -6016,12 +6835,12 @@ Tcl_InputBlocked(chan)
*
* Tcl_InputBuffered --
*
- * Returns the number of bytes of input currently buffered in the
- * common internal buffer of a channel.
+ * Returns the number of bytes of input currently buffered in the common
+ * internal buffer of a channel.
*
* Results:
- * The number of input bytes buffered, or zero if the channel is not
- * open for reading.
+ * The number of input bytes buffered, or zero if the channel is not open
+ * for reading.
*
* Side effects:
* None.
@@ -6030,28 +6849,26 @@ Tcl_InputBlocked(chan)
*/
int
-Tcl_InputBuffered(chan)
- Tcl_Channel chan; /* The channel to query. */
+Tcl_InputBuffered(
+ Tcl_Channel chan) /* The channel to query. */
{
ChannelState *statePtr = ((Channel *) chan)->state;
- /* State of real channel structure. */
+ /* State of real channel structure. */
ChannelBuffer *bufPtr;
int bytesBuffered;
- for (bytesBuffered = 0, bufPtr = statePtr->inQueueHead;
- bufPtr != (ChannelBuffer *) NULL;
- bufPtr = bufPtr->nextPtr) {
- bytesBuffered += (bufPtr->nextAdded - bufPtr->nextRemoved);
+ for (bytesBuffered = 0, bufPtr = statePtr->inQueueHead; bufPtr != NULL;
+ bufPtr = bufPtr->nextPtr) {
+ bytesBuffered += BytesLeft(bufPtr);
}
/*
* Don't forget the bytes in the topmost pushback area.
*/
- for (bufPtr = statePtr->topChanPtr->inQueueHead;
- bufPtr != (ChannelBuffer *) NULL;
- bufPtr = bufPtr->nextPtr) {
- bytesBuffered += (bufPtr->nextAdded - bufPtr->nextRemoved);
+ for (bufPtr = statePtr->topChanPtr->inQueueHead; bufPtr != NULL;
+ bufPtr = bufPtr->nextPtr) {
+ bytesBuffered += BytesLeft(bufPtr);
}
return bytesBuffered;
@@ -6062,12 +6879,12 @@ Tcl_InputBuffered(chan)
*
* Tcl_OutputBuffered --
*
- * Returns the number of bytes of output currently buffered in the
- * common internal buffer of a channel.
+ * Returns the number of bytes of output currently buffered in the common
+ * internal buffer of a channel.
*
* Results:
- * The number of output bytes buffered, or zero if the channel is not
- * open for writing.
+ * The number of output bytes buffered, or zero if the channel is not open
+ * for writing.
*
* Side effects:
* None.
@@ -6076,24 +6893,24 @@ Tcl_InputBuffered(chan)
*/
int
-Tcl_OutputBuffered(chan)
- Tcl_Channel chan; /* The channel to query. */
+Tcl_OutputBuffered(
+ Tcl_Channel chan) /* The channel to query. */
{
ChannelState *statePtr = ((Channel *) chan)->state;
- /* State of real channel structure. */
+ /* State of real channel structure. */
ChannelBuffer *bufPtr;
int bytesBuffered;
- for (bytesBuffered = 0, bufPtr = statePtr->outQueueHead;
- bufPtr != (ChannelBuffer *) NULL;
- bufPtr = bufPtr->nextPtr) {
- bytesBuffered += (bufPtr->nextAdded - bufPtr->nextRemoved);
+ for (bytesBuffered = 0, bufPtr = statePtr->outQueueHead; bufPtr != NULL;
+ bufPtr = bufPtr->nextPtr) {
+ bytesBuffered += BytesLeft(bufPtr);
}
- if ((statePtr->curOutPtr != (ChannelBuffer *) NULL) &&
- (statePtr->curOutPtr->nextAdded > statePtr->curOutPtr->nextRemoved)) {
- statePtr->flags |= BUFFER_READY;
- bytesBuffered +=
- (statePtr->curOutPtr->nextAdded - statePtr->curOutPtr->nextRemoved);
+ if (statePtr->curOutPtr != NULL) {
+ register ChannelBuffer *curOutPtr = statePtr->curOutPtr;
+
+ if (IsBufferReady(curOutPtr)) {
+ bytesBuffered += BytesLeft(curOutPtr);
+ }
}
return bytesBuffered;
@@ -6108,8 +6925,8 @@ Tcl_OutputBuffered(chan)
* internal buffer (push back area) of a channel.
*
* Results:
- * The number of input bytes buffered, or zero if the channel is not
- * open for reading.
+ * The number of input bytes buffered, or zero if the channel is not open
+ * for reading.
*
* Side effects:
* None.
@@ -6118,18 +6935,17 @@ Tcl_OutputBuffered(chan)
*/
int
-Tcl_ChannelBuffered(chan)
- Tcl_Channel chan; /* The channel to query. */
+Tcl_ChannelBuffered(
+ Tcl_Channel chan) /* The channel to query. */
{
Channel *chanPtr = (Channel *) chan;
- /* real channel structure. */
+ /* Real channel structure. */
ChannelBuffer *bufPtr;
- int bytesBuffered;
+ int bytesBuffered = 0;
- for (bytesBuffered = 0, bufPtr = chanPtr->inQueueHead;
- bufPtr != (ChannelBuffer *) NULL;
- bufPtr = bufPtr->nextPtr) {
- bytesBuffered += (bufPtr->nextAdded - bufPtr->nextRemoved);
+ for (bufPtr = chanPtr->inQueueHead; bufPtr != NULL;
+ bufPtr = bufPtr->nextPtr) {
+ bytesBuffered += BytesLeft(bufPtr);
}
return bytesBuffered;
@@ -6140,8 +6956,8 @@ Tcl_ChannelBuffered(chan)
*
* Tcl_SetChannelBufferSize --
*
- * Sets the size of buffers to allocate to store input or output
- * in the channel. The size must be between 1 byte and 1 MByte.
+ * Sets the size of buffers to allocate to store input or output in the
+ * channel. The size must be between 1 byte and 1 MByte.
*
* Results:
* None.
@@ -6153,13 +6969,12 @@ Tcl_ChannelBuffered(chan)
*/
void
-Tcl_SetChannelBufferSize(chan, sz)
- Tcl_Channel chan; /* The channel whose buffer size
- * to set. */
- int sz; /* The size to set. */
+Tcl_SetChannelBufferSize(
+ Tcl_Channel chan, /* The channel whose buffer size to set. */
+ int sz) /* The size to set. */
{
- ChannelState *statePtr; /* State of real channel structure. */
-
+ ChannelState *statePtr; /* State of real channel structure. */
+
/*
* Clip the buffer size to force it into the [1,1M] range
*/
@@ -6179,7 +6994,7 @@ Tcl_SetChannelBufferSize(chan, sz)
}
if ((statePtr->encoding != NULL) && (statePtr->flags & TCL_WRITABLE)) {
statePtr->outputStage = (char *)
- ckalloc((unsigned) (statePtr->bufSize + 2));
+ ckalloc((unsigned) (statePtr->bufSize + 2));
}
}
@@ -6200,12 +7015,12 @@ Tcl_SetChannelBufferSize(chan, sz)
*/
int
-Tcl_GetChannelBufferSize(chan)
- Tcl_Channel chan; /* The channel for which to find the
- * buffer size. */
+Tcl_GetChannelBufferSize(
+ Tcl_Channel chan) /* The channel for which to find the buffer
+ * size. */
{
ChannelState *statePtr = ((Channel *) chan)->state;
- /* State of real channel structure. */
+ /* State of real channel structure. */
return statePtr->bufSize;
}
@@ -6215,44 +7030,43 @@ Tcl_GetChannelBufferSize(chan)
*
* Tcl_BadChannelOption --
*
- * This procedure generates a "bad option" error message in an
- * (optional) interpreter. It is used by channel drivers when
- * a invalid Set/Get option is requested. Its purpose is to concatenate
- * the generic options list to the specific ones and factorize
- * the generic options error message string.
+ * This procedure generates a "bad option" error message in an (optional)
+ * interpreter. It is used by channel drivers when a invalid Set/Get
+ * option is requested. Its purpose is to concatenate the generic options
+ * list to the specific ones and factorize the generic options error
+ * message string.
*
* Results:
* TCL_ERROR.
*
* Side effects:
- * An error message is generated in interp's result object to
- * indicate that a command was invoked with the a bad option
- * The message has the form
- * bad option "blah": should be one of
- * <...generic options...>+<...specific options...>
- * "blah" is the optionName argument and "<specific options>"
- * is a space separated list of specific option words.
- * The function takes good care of inserting minus signs before
- * each option, commas after, and an "or" before the last option.
+
+ * An error message is generated in interp's result object to indicate
+ * that a command was invoked with the a bad option. The message has the
+ * form:
+ * bad option "blah": should be one of
+ * <...generic options...>+<...specific options...>
+ * "blah" is the optionName argument and "<specific options>" is a space
+ * separated list of specific option words. The function takes good care
+ * of inserting minus signs before each option, commas after, and an "or"
+ * before the last option.
*
*----------------------------------------------------------------------
*/
int
-Tcl_BadChannelOption(interp, optionName, optionList)
- Tcl_Interp *interp; /* Current interpreter. (can be NULL)*/
- CONST char *optionName; /* 'bad option' name */
- CONST char *optionList; /* Specific options list to append
- * to the standard generic options.
- * can be NULL for generic options
- * only.
- */
-{
- if (interp) {
- CONST char *genericopt =
- "blocking buffering buffersize encoding eofchar translation";
- CONST char **argv;
- int argc, i;
+Tcl_BadChannelOption(
+ Tcl_Interp *interp, /* Current interpreter (can be NULL).*/
+ const char *optionName, /* 'bad option' name */
+ const char *optionList) /* Specific options list to append to the
+ * standard generic options. Can be NULL for
+ * generic options only. */
+{
+ if (interp != NULL) {
+ const char *genericopt =
+ "blocking buffering buffersize encoding eofchar translation";
+ const char **argv;
+ int argc, i;
Tcl_DString ds;
Tcl_DStringInit(&ds);
@@ -6261,18 +7075,18 @@ Tcl_BadChannelOption(interp, optionName, optionList)
Tcl_DStringAppend(&ds, " ", 1);
Tcl_DStringAppend(&ds, optionList, -1);
}
- if (Tcl_SplitList(interp, Tcl_DStringValue(&ds),
+ if (Tcl_SplitList(interp, Tcl_DStringValue(&ds),
&argc, &argv) != TCL_OK) {
- panic("malformed option list in channel driver");
+ Tcl_Panic("malformed option list in channel driver");
}
Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "bad option \"", optionName,
- "\": should be one of ", (char *) NULL);
+ Tcl_AppendResult(interp, "bad option \"", optionName,
+ "\": should be one of ", NULL);
argc--;
for (i = 0; i < argc; i++) {
- Tcl_AppendResult(interp, "-", argv[i], ", ", (char *) NULL);
+ Tcl_AppendResult(interp, "-", argv[i], ", ", NULL);
}
- Tcl_AppendResult(interp, "or -", argv[i], (char *) NULL);
+ Tcl_AppendResult(interp, "or -", argv[i], NULL);
Tcl_DStringFree(&ds);
ckfree((char *) argv);
}
@@ -6285,39 +7099,40 @@ Tcl_BadChannelOption(interp, optionName, optionList)
*
* Tcl_GetChannelOption --
*
- * Gets a mode associated with an IO channel. If the optionName arg
- * is non NULL, retrieves the value of that option. If the optionName
- * arg is NULL, retrieves a list of alternating option names and
- * values for the given channel.
+ * Gets a mode associated with an IO channel. If the optionName arg is
+ * non NULL, retrieves the value of that option. If the optionName arg is
+ * NULL, retrieves a list of alternating option names and values for the
+ * given channel.
*
* Results:
- * A standard Tcl result. Also sets the supplied DString to the
- * string value of the option(s) returned.
+ * A standard Tcl result. Also sets the supplied DString to the string
+ * value of the option(s) returned.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
int
-Tcl_GetChannelOption(interp, chan, optionName, dsPtr)
- Tcl_Interp *interp; /* For error reporting - can be NULL. */
- Tcl_Channel chan; /* Channel on which to get option. */
- CONST char *optionName; /* Option to get. */
- Tcl_DString *dsPtr; /* Where to store value(s). */
+Tcl_GetChannelOption(
+ Tcl_Interp *interp, /* For error reporting - can be NULL. */
+ Tcl_Channel chan, /* Channel on which to get option. */
+ const char *optionName, /* Option to get. */
+ Tcl_DString *dsPtr) /* Where to store value(s). */
{
size_t len; /* Length of optionName string. */
char optionVal[128]; /* Buffer for sprintf. */
Channel *chanPtr = (Channel *) chan;
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
int flags;
/*
* Disallow options on dead channels -- channels that have been closed but
* not yet been deallocated. Such channels can be found if the exit
- * handler for channel cleanup has run but the channel is still
- * registered in an interpreter.
+ * handler for channel cleanup has run but the channel is still registered
+ * in an interpreter.
*/
if (CheckForDeadChannel(interp, statePtr)) {
@@ -6343,57 +7158,52 @@ Tcl_GetChannelOption(interp, chan, optionName, dsPtr)
}
/*
- * If the optionName is NULL it means that we want a list of all
- * options and values.
+ * If the optionName is NULL it means that we want a list of all options
+ * and values.
*/
-
- if (optionName == (char *) NULL) {
- len = 0;
+
+ if (optionName == NULL) {
+ len = 0;
} else {
- len = strlen(optionName);
- }
-
- if ((len == 0) || ((len > 2) && (optionName[1] == 'b') &&
- (strncmp(optionName, "-blocking", len) == 0))) {
- if (len == 0) {
- Tcl_DStringAppendElement(dsPtr, "-blocking");
- }
- Tcl_DStringAppendElement(dsPtr,
+ len = strlen(optionName);
+ }
+
+ if (len == 0 || HaveOpt(2, "-blocking")) {
+ if (len == 0) {
+ Tcl_DStringAppendElement(dsPtr, "-blocking");
+ }
+ Tcl_DStringAppendElement(dsPtr,
(flags & CHANNEL_NONBLOCKING) ? "0" : "1");
- if (len > 0) {
- return TCL_OK;
- }
- }
- if ((len == 0) || ((len > 7) && (optionName[1] == 'b') &&
- (strncmp(optionName, "-buffering", len) == 0))) {
- if (len == 0) {
- Tcl_DStringAppendElement(dsPtr, "-buffering");
- }
- if (flags & CHANNEL_LINEBUFFERED) {
- Tcl_DStringAppendElement(dsPtr, "line");
- } else if (flags & CHANNEL_UNBUFFERED) {
- Tcl_DStringAppendElement(dsPtr, "none");
- } else {
- Tcl_DStringAppendElement(dsPtr, "full");
- }
- if (len > 0) {
- return TCL_OK;
- }
- }
- if ((len == 0) || ((len > 7) && (optionName[1] == 'b') &&
- (strncmp(optionName, "-buffersize", len) == 0))) {
- if (len == 0) {
- Tcl_DStringAppendElement(dsPtr, "-buffersize");
- }
- TclFormatInt(optionVal, statePtr->bufSize);
- Tcl_DStringAppendElement(dsPtr, optionVal);
- if (len > 0) {
- return TCL_OK;
- }
- }
- if ((len == 0) ||
- ((len > 2) && (optionName[1] == 'e') &&
- (strncmp(optionName, "-encoding", len) == 0))) {
+ if (len > 0) {
+ return TCL_OK;
+ }
+ }
+ if (len == 0 || HaveOpt(7, "-buffering")) {
+ if (len == 0) {
+ Tcl_DStringAppendElement(dsPtr, "-buffering");
+ }
+ if (flags & CHANNEL_LINEBUFFERED) {
+ Tcl_DStringAppendElement(dsPtr, "line");
+ } else if (flags & CHANNEL_UNBUFFERED) {
+ Tcl_DStringAppendElement(dsPtr, "none");
+ } else {
+ Tcl_DStringAppendElement(dsPtr, "full");
+ }
+ if (len > 0) {
+ return TCL_OK;
+ }
+ }
+ if (len == 0 || HaveOpt(7, "-buffersize")) {
+ if (len == 0) {
+ Tcl_DStringAppendElement(dsPtr, "-buffersize");
+ }
+ TclFormatInt(optionVal, statePtr->bufSize);
+ Tcl_DStringAppendElement(dsPtr, optionVal);
+ if (len > 0) {
+ return TCL_OK;
+ }
+ }
+ if (len == 0 || HaveOpt(2, "-encoding")) {
if (len == 0) {
Tcl_DStringAppendElement(dsPtr, "-encoding");
}
@@ -6407,108 +7217,111 @@ Tcl_GetChannelOption(interp, chan, optionName, dsPtr)
return TCL_OK;
}
}
- if ((len == 0) ||
- ((len > 2) && (optionName[1] == 'e') &&
- (strncmp(optionName, "-eofchar", len) == 0))) {
- if (len == 0) {
- Tcl_DStringAppendElement(dsPtr, "-eofchar");
- }
- if (((flags & (TCL_READABLE|TCL_WRITABLE)) ==
- (TCL_READABLE|TCL_WRITABLE)) && (len == 0)) {
- Tcl_DStringStartSublist(dsPtr);
- }
- if (flags & TCL_READABLE) {
- if (statePtr->inEofChar == 0) {
- Tcl_DStringAppendElement(dsPtr, "");
- } else {
- char buf[4];
-
- sprintf(buf, "%c", statePtr->inEofChar);
- Tcl_DStringAppendElement(dsPtr, buf);
- }
- }
- if (flags & TCL_WRITABLE) {
- if (statePtr->outEofChar == 0) {
- Tcl_DStringAppendElement(dsPtr, "");
- } else {
- char buf[4];
-
- sprintf(buf, "%c", statePtr->outEofChar);
- Tcl_DStringAppendElement(dsPtr, buf);
- }
- }
- if ( !(flags & (TCL_READABLE|TCL_WRITABLE))) {
- /* Not readable or writable (server socket) */
- Tcl_DStringAppendElement(dsPtr, "");
- }
- if (((flags & (TCL_READABLE|TCL_WRITABLE)) ==
- (TCL_READABLE|TCL_WRITABLE)) && (len == 0)) {
- Tcl_DStringEndSublist(dsPtr);
- }
- if (len > 0) {
- return TCL_OK;
- }
- }
- if ((len == 0) ||
- ((len > 1) && (optionName[1] == 't') &&
- (strncmp(optionName, "-translation", len) == 0))) {
- if (len == 0) {
- Tcl_DStringAppendElement(dsPtr, "-translation");
- }
- if (((flags & (TCL_READABLE|TCL_WRITABLE)) ==
- (TCL_READABLE|TCL_WRITABLE)) && (len == 0)) {
- Tcl_DStringStartSublist(dsPtr);
- }
- if (flags & TCL_READABLE) {
- if (statePtr->inputTranslation == TCL_TRANSLATE_AUTO) {
- Tcl_DStringAppendElement(dsPtr, "auto");
- } else if (statePtr->inputTranslation == TCL_TRANSLATE_CR) {
- Tcl_DStringAppendElement(dsPtr, "cr");
- } else if (statePtr->inputTranslation == TCL_TRANSLATE_CRLF) {
- Tcl_DStringAppendElement(dsPtr, "crlf");
- } else {
- Tcl_DStringAppendElement(dsPtr, "lf");
- }
- }
- if (flags & TCL_WRITABLE) {
- if (statePtr->outputTranslation == TCL_TRANSLATE_AUTO) {
- Tcl_DStringAppendElement(dsPtr, "auto");
- } else if (statePtr->outputTranslation == TCL_TRANSLATE_CR) {
- Tcl_DStringAppendElement(dsPtr, "cr");
- } else if (statePtr->outputTranslation == TCL_TRANSLATE_CRLF) {
- Tcl_DStringAppendElement(dsPtr, "crlf");
- } else {
- Tcl_DStringAppendElement(dsPtr, "lf");
- }
- }
- if ( !(flags & (TCL_READABLE|TCL_WRITABLE))) {
- /* Not readable or writable (server socket) */
- Tcl_DStringAppendElement(dsPtr, "auto");
- }
- if (((flags & (TCL_READABLE|TCL_WRITABLE)) ==
- (TCL_READABLE|TCL_WRITABLE)) && (len == 0)) {
- Tcl_DStringEndSublist(dsPtr);
- }
- if (len > 0) {
- return TCL_OK;
- }
- }
- if (chanPtr->typePtr->getOptionProc != (Tcl_DriverGetOptionProc *) NULL) {
+ if (len == 0 || HaveOpt(2, "-eofchar")) {
+ if (len == 0) {
+ Tcl_DStringAppendElement(dsPtr, "-eofchar");
+ }
+ if (((flags & (TCL_READABLE|TCL_WRITABLE)) ==
+ (TCL_READABLE|TCL_WRITABLE)) && (len == 0)) {
+ Tcl_DStringStartSublist(dsPtr);
+ }
+ if (flags & TCL_READABLE) {
+ if (statePtr->inEofChar == 0) {
+ Tcl_DStringAppendElement(dsPtr, "");
+ } else {
+ char buf[4];
+
+ sprintf(buf, "%c", statePtr->inEofChar);
+ Tcl_DStringAppendElement(dsPtr, buf);
+ }
+ }
+ if (flags & TCL_WRITABLE) {
+ if (statePtr->outEofChar == 0) {
+ Tcl_DStringAppendElement(dsPtr, "");
+ } else {
+ char buf[4];
+
+ sprintf(buf, "%c", statePtr->outEofChar);
+ Tcl_DStringAppendElement(dsPtr, buf);
+ }
+ }
+ if (!(flags & (TCL_READABLE|TCL_WRITABLE))) {
+ /*
+ * Not readable or writable (e.g. server socket)
+ */
+
+ Tcl_DStringAppendElement(dsPtr, "");
+ }
+ if (((flags & (TCL_READABLE|TCL_WRITABLE)) ==
+ (TCL_READABLE|TCL_WRITABLE)) && (len == 0)) {
+ Tcl_DStringEndSublist(dsPtr);
+ }
+ if (len > 0) {
+ return TCL_OK;
+ }
+ }
+ if (len == 0 || HaveOpt(1, "-translation")) {
+ if (len == 0) {
+ Tcl_DStringAppendElement(dsPtr, "-translation");
+ }
+ if (((flags & (TCL_READABLE|TCL_WRITABLE)) ==
+ (TCL_READABLE|TCL_WRITABLE)) && (len == 0)) {
+ Tcl_DStringStartSublist(dsPtr);
+ }
+ if (flags & TCL_READABLE) {
+ if (statePtr->inputTranslation == TCL_TRANSLATE_AUTO) {
+ Tcl_DStringAppendElement(dsPtr, "auto");
+ } else if (statePtr->inputTranslation == TCL_TRANSLATE_CR) {
+ Tcl_DStringAppendElement(dsPtr, "cr");
+ } else if (statePtr->inputTranslation == TCL_TRANSLATE_CRLF) {
+ Tcl_DStringAppendElement(dsPtr, "crlf");
+ } else {
+ Tcl_DStringAppendElement(dsPtr, "lf");
+ }
+ }
+ if (flags & TCL_WRITABLE) {
+ if (statePtr->outputTranslation == TCL_TRANSLATE_AUTO) {
+ Tcl_DStringAppendElement(dsPtr, "auto");
+ } else if (statePtr->outputTranslation == TCL_TRANSLATE_CR) {
+ Tcl_DStringAppendElement(dsPtr, "cr");
+ } else if (statePtr->outputTranslation == TCL_TRANSLATE_CRLF) {
+ Tcl_DStringAppendElement(dsPtr, "crlf");
+ } else {
+ Tcl_DStringAppendElement(dsPtr, "lf");
+ }
+ }
+ if (!(flags & (TCL_READABLE|TCL_WRITABLE))) {
+ /*
+ * Not readable or writable (e.g. server socket)
+ */
+
+ Tcl_DStringAppendElement(dsPtr, "auto");
+ }
+ if (((flags & (TCL_READABLE|TCL_WRITABLE)) ==
+ (TCL_READABLE|TCL_WRITABLE)) && (len == 0)) {
+ Tcl_DStringEndSublist(dsPtr);
+ }
+ if (len > 0) {
+ return TCL_OK;
+ }
+ }
+
+ if (chanPtr->typePtr->getOptionProc != NULL) {
/*
- * let the driver specific handle additional options
- * and result code and message.
+ * Let the driver specific handle additional options and result code
+ * and message.
*/
- return (chanPtr->typePtr->getOptionProc) (chanPtr->instanceData,
+ return (chanPtr->typePtr->getOptionProc) (chanPtr->instanceData,
interp, optionName, dsPtr);
} else {
/*
- * no driver specific options case.
+ * No driver specific options case.
*/
- if (len == 0) {
- return TCL_OK;
- }
+ if (len == 0) {
+ return TCL_OK;
+ }
return Tcl_BadChannelOption(interp, optionName, NULL);
}
}
@@ -6521,8 +7334,8 @@ Tcl_GetChannelOption(interp, chan, optionName, dsPtr)
* Sets an option on a channel.
*
* Results:
- * A standard Tcl result. On error, sets interp's result object
- * if interp is not NULL.
+ * A standard Tcl result. On error, sets interp's result object if
+ * interp is not NULL.
*
* Side effects:
* May modify an option on a device.
@@ -6531,17 +7344,19 @@ Tcl_GetChannelOption(interp, chan, optionName, dsPtr)
*/
int
-Tcl_SetChannelOption(interp, chan, optionName, newValue)
- Tcl_Interp *interp; /* For error reporting - can be NULL. */
- Tcl_Channel chan; /* Channel on which to set mode. */
- CONST char *optionName; /* Which option to set? */
- CONST char *newValue; /* New value for option. */
-{
- Channel *chanPtr = (Channel *) chan; /* The real IO channel. */
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+Tcl_SetChannelOption(
+ Tcl_Interp *interp, /* For error reporting - can be NULL. */
+ Tcl_Channel chan, /* Channel on which to set mode. */
+ const char *optionName, /* Which option to set? */
+ const char *newValue) /* New value for option. */
+{
+ Channel *chanPtr = (Channel *) chan;
+ /* The real IO channel. */
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
size_t len; /* Length of optionName string. */
int argc;
- CONST char **argv;
+ const char **argv;
/*
* If the channel is in the middle of a background copy, fail.
@@ -6549,18 +7364,17 @@ Tcl_SetChannelOption(interp, chan, optionName, newValue)
if (statePtr->csPtrR || statePtr->csPtrW) {
if (interp) {
- Tcl_AppendResult(interp,
- "unable to set channel options: background copy in progress",
- (char *) NULL);
+ Tcl_AppendResult(interp, "unable to set channel options: "
+ "background copy in progress", NULL);
}
- return TCL_ERROR;
+ return TCL_ERROR;
}
/*
* Disallow options on dead channels -- channels that have been closed but
* not yet been deallocated. Such channels can be found if the exit
- * handler for channel cleanup has run but the channel is still
- * registered in an interpreter.
+ * handler for channel cleanup has run but the channel is still registered
+ * in an interpreter.
*/
if (CheckForDeadChannel(NULL, statePtr)) {
@@ -6575,50 +7389,47 @@ Tcl_SetChannelOption(interp, chan, optionName, newValue)
len = strlen(optionName);
- if ((len > 2) && (optionName[1] == 'b') &&
- (strncmp(optionName, "-blocking", len) == 0)) {
+ if (HaveOpt(2, "-blocking")) {
int newMode;
- if (Tcl_GetBoolean(interp, newValue, &newMode) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (newMode) {
- newMode = TCL_MODE_BLOCKING;
- } else {
- newMode = TCL_MODE_NONBLOCKING;
- }
+
+ if (Tcl_GetBoolean(interp, newValue, &newMode) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ if (newMode) {
+ newMode = TCL_MODE_BLOCKING;
+ } else {
+ newMode = TCL_MODE_NONBLOCKING;
+ }
return SetBlockMode(interp, chanPtr, newMode);
- } else if ((len > 7) && (optionName[1] == 'b') &&
- (strncmp(optionName, "-buffering", len) == 0)) {
- len = strlen(newValue);
- if ((newValue[0] == 'f') && (strncmp(newValue, "full", len) == 0)) {
- statePtr->flags &=
- (~(CHANNEL_UNBUFFERED|CHANNEL_LINEBUFFERED));
- } else if ((newValue[0] == 'l') &&
- (strncmp(newValue, "line", len) == 0)) {
- statePtr->flags &= (~(CHANNEL_UNBUFFERED));
- statePtr->flags |= CHANNEL_LINEBUFFERED;
- } else if ((newValue[0] == 'n') &&
- (strncmp(newValue, "none", len) == 0)) {
- statePtr->flags &= (~(CHANNEL_LINEBUFFERED));
- statePtr->flags |= CHANNEL_UNBUFFERED;
- } else {
- if (interp) {
- Tcl_AppendResult(interp, "bad value for -buffering: ",
- "must be one of full, line, or none",
- (char *) NULL);
- return TCL_ERROR;
- }
- }
+ } else if (HaveOpt(7, "-buffering")) {
+ len = strlen(newValue);
+ if ((newValue[0] == 'f') && (strncmp(newValue, "full", len) == 0)) {
+ statePtr->flags &=
+ ~(CHANNEL_UNBUFFERED|CHANNEL_LINEBUFFERED);
+ } else if ((newValue[0] == 'l') &&
+ (strncmp(newValue, "line", len) == 0)) {
+ ResetFlag(statePtr, CHANNEL_UNBUFFERED);
+ SetFlag(statePtr, CHANNEL_LINEBUFFERED);
+ } else if ((newValue[0] == 'n') &&
+ (strncmp(newValue, "none", len) == 0)) {
+ ResetFlag(statePtr, CHANNEL_LINEBUFFERED);
+ SetFlag(statePtr, CHANNEL_UNBUFFERED);
+ } else {
+ if (interp) {
+ Tcl_AppendResult(interp, "bad value for -buffering: "
+ "must be one of full, line, or none", NULL);
+ return TCL_ERROR;
+ }
+ }
return TCL_OK;
- } else if ((len > 7) && (optionName[1] == 'b') &&
- (strncmp(optionName, "-buffersize", len) == 0)) {
+ } else if (HaveOpt(7, "-buffersize")) {
int newBufferSize;
+
if (Tcl_GetInt(interp, newValue, &newBufferSize) == TCL_ERROR) {
return TCL_ERROR;
}
Tcl_SetChannelBufferSize(chan, newBufferSize);
- } else if ((len > 2) && (optionName[1] == 'e') &&
- (strncmp(optionName, "-encoding", len) == 0)) {
+ } else if (HaveOpt(2, "-encoding")) {
Tcl_Encoding encoding;
if ((newValue[0] == '\0') || (strcmp(newValue, "binary") == 0)) {
@@ -6629,10 +7440,12 @@ Tcl_SetChannelOption(interp, chan, optionName, newValue)
return TCL_ERROR;
}
}
+
/*
* When the channel has an escape sequence driven encoding such as
* iso2022, the terminated escape sequence must write to the buffer.
*/
+
if ((statePtr->encoding != NULL) && (statePtr->curOutPtr != NULL)
&& (CheckChannelErrors(statePtr, TCL_WRITABLE) == 0)) {
statePtr->outputEncodingFlags |= TCL_ENCODING_END;
@@ -6644,74 +7457,77 @@ Tcl_SetChannelOption(interp, chan, optionName, newValue)
statePtr->inputEncodingFlags = TCL_ENCODING_START;
statePtr->outputEncodingState = NULL;
statePtr->outputEncodingFlags = TCL_ENCODING_START;
- statePtr->flags &= ~CHANNEL_NEED_MORE_DATA;
+ ResetFlag(statePtr, CHANNEL_NEED_MORE_DATA);
UpdateInterest(chanPtr);
- } else if ((len > 2) && (optionName[1] == 'e') &&
- (strncmp(optionName, "-eofchar", len) == 0)) {
- if (Tcl_SplitList(interp, newValue, &argc, &argv) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (argc == 0) {
- statePtr->inEofChar = 0;
- statePtr->outEofChar = 0;
- } else if (argc == 1) {
- if (statePtr->flags & TCL_WRITABLE) {
- statePtr->outEofChar = (int) argv[0][0];
- }
- if (statePtr->flags & TCL_READABLE) {
- statePtr->inEofChar = (int) argv[0][0];
- }
- } else if (argc != 2) {
- if (interp) {
- Tcl_AppendResult(interp,
- "bad value for -eofchar: should be a list of zero,",
- " one, or two elements", (char *) NULL);
- }
- ckfree((char *) argv);
- return TCL_ERROR;
- } else {
- if (statePtr->flags & TCL_READABLE) {
- statePtr->inEofChar = (int) argv[0][0];
- }
- if (statePtr->flags & TCL_WRITABLE) {
- statePtr->outEofChar = (int) argv[1][0];
- }
- }
- if (argv != NULL) {
- ckfree((char *) argv);
- }
+ } else if (HaveOpt(2, "-eofchar")) {
+ if (Tcl_SplitList(interp, newValue, &argc, &argv) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ if (argc == 0) {
+ statePtr->inEofChar = 0;
+ statePtr->outEofChar = 0;
+ } else if (argc == 1 || argc == 2) {
+ int outIndex = (argc - 1);
+ int inValue = (int) argv[0][0];
+ int outValue = (int) argv[outIndex][0];
+ if (inValue & 0x80 || outValue & 0x80) {
+ if (interp) {
+ Tcl_AppendResult(interp, "bad value for -eofchar: ",
+ "must be non-NUL ASCII character", NULL);
+ }
+ ckfree((char *) argv);
+ return TCL_ERROR;
+ }
+ if (statePtr->flags & TCL_READABLE) {
+ statePtr->inEofChar = inValue;
+ }
+ if (statePtr->flags & TCL_WRITABLE) {
+ statePtr->outEofChar = outValue;
+ }
+ } else {
+ if (interp) {
+ Tcl_AppendResult(interp,
+ "bad value for -eofchar: should be a list of zero,"
+ " one, or two elements", NULL);
+ }
+ ckfree((char *) argv);
+ return TCL_ERROR;
+ }
+ if (argv != NULL) {
+ ckfree((char *) argv);
+ }
/*
- * [SF Tcl Bug 930851] Reset EOF and BLOCKED flags. Changing
- * the character which signals eof can transform a current eof
- * condition into a 'go ahead'. Ditto for blocked.
+ * [Bug 930851] Reset EOF and BLOCKED flags. Changing the character
+ * which signals eof can transform a current eof condition into a 'go
+ * ahead'. Ditto for blocked.
*/
- statePtr->flags &= (~(CHANNEL_EOF | CHANNEL_STICKY_EOF | CHANNEL_BLOCKED));
+ statePtr->flags &=
+ ~(CHANNEL_EOF | CHANNEL_STICKY_EOF | CHANNEL_BLOCKED);
return TCL_OK;
- } else if ((len > 1) && (optionName[1] == 't') &&
- (strncmp(optionName, "-translation", len) == 0)) {
- CONST char *readMode, *writeMode;
+ } else if (HaveOpt(1, "-translation")) {
+ const char *readMode, *writeMode;
- if (Tcl_SplitList(interp, newValue, &argc, &argv) == TCL_ERROR) {
- return TCL_ERROR;
- }
+ if (Tcl_SplitList(interp, newValue, &argc, &argv) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
- if (argc == 1) {
+ if (argc == 1) {
readMode = (statePtr->flags & TCL_READABLE) ? argv[0] : NULL;
writeMode = (statePtr->flags & TCL_WRITABLE) ? argv[0] : NULL;
} else if (argc == 2) {
readMode = (statePtr->flags & TCL_READABLE) ? argv[0] : NULL;
writeMode = (statePtr->flags & TCL_WRITABLE) ? argv[1] : NULL;
} else {
- if (interp) {
- Tcl_AppendResult(interp,
- "bad value for -translation: must be a one or two",
- " element list", (char *) NULL);
- }
- ckfree((char *) argv);
- return TCL_ERROR;
+ if (interp) {
+ Tcl_AppendResult(interp,
+ "bad value for -translation: must be a one or two"
+ " element list", NULL);
+ }
+ ckfree((char *) argv);
+ return TCL_ERROR;
}
if (readMode) {
@@ -6723,7 +7539,7 @@ Tcl_SetChannelOption(interp, chan, optionName, newValue)
} else if (strcmp(readMode, "binary") == 0) {
translation = TCL_TRANSLATE_LF;
statePtr->inEofChar = 0;
- Tcl_FreeEncoding(statePtr->encoding);
+ Tcl_FreeEncoding(statePtr->encoding);
statePtr->encoding = NULL;
} else if (strcmp(readMode, "lf") == 0) {
translation = TCL_TRANSLATE_LF;
@@ -6736,24 +7552,23 @@ Tcl_SetChannelOption(interp, chan, optionName, newValue)
} else {
if (interp) {
Tcl_AppendResult(interp,
- "bad value for -translation: ",
- "must be one of auto, binary, cr, lf, crlf,",
- " or platform", (char *) NULL);
+ "bad value for -translation: "
+ "must be one of auto, binary, cr, lf, crlf,"
+ " or platform", NULL);
}
ckfree((char *) argv);
return TCL_ERROR;
}
/*
- * Reset the EOL flags since we need to look at any buffered
- * data to see if the new translation mode allows us to
- * complete the line.
+ * Reset the EOL flags since we need to look at any buffered data
+ * to see if the new translation mode allows us to complete the
+ * line.
*/
if (translation != statePtr->inputTranslation) {
statePtr->inputTranslation = translation;
- statePtr->flags &= ~(INPUT_SAW_CR);
- statePtr->flags &= ~(CHANNEL_NEED_MORE_DATA);
+ ResetFlag(statePtr, INPUT_SAW_CR | CHANNEL_NEED_MORE_DATA);
UpdateInterest(chanPtr);
}
}
@@ -6762,10 +7577,9 @@ Tcl_SetChannelOption(interp, chan, optionName, newValue)
/* Do nothing. */
} else if (strcmp(writeMode, "auto") == 0) {
/*
- * This is a hack to get TCP sockets to produce output
- * in CRLF mode if they are being set into AUTO mode.
- * A better solution for achieving this effect will be
- * coded later.
+ * This is a hack to get TCP sockets to produce output in CRLF
+ * mode if they are being set into AUTO mode. A better
+ * solution for achieving this effect will be coded later.
*/
if (strcmp(Tcl_ChannelName(chanPtr->typePtr), "tcp") == 0) {
@@ -6776,7 +7590,7 @@ Tcl_SetChannelOption(interp, chan, optionName, newValue)
} else if (strcmp(writeMode, "binary") == 0) {
statePtr->outEofChar = 0;
statePtr->outputTranslation = TCL_TRANSLATE_LF;
- Tcl_FreeEncoding(statePtr->encoding);
+ Tcl_FreeEncoding(statePtr->encoding);
statePtr->encoding = NULL;
} else if (strcmp(writeMode, "lf") == 0) {
statePtr->outputTranslation = TCL_TRANSLATE_LF;
@@ -6789,21 +7603,21 @@ Tcl_SetChannelOption(interp, chan, optionName, newValue)
} else {
if (interp) {
Tcl_AppendResult(interp,
- "bad value for -translation: ",
- "must be one of auto, binary, cr, lf, crlf,",
- " or platform", (char *) NULL);
+ "bad value for -translation: "
+ "must be one of auto, binary, cr, lf, crlf,"
+ " or platform", NULL);
}
ckfree((char *) argv);
return TCL_ERROR;
}
}
- ckfree((char *) argv);
- return TCL_OK;
+ ckfree((char *) argv);
+ return TCL_OK;
} else if (chanPtr->typePtr->setOptionProc != NULL) {
- return (*chanPtr->typePtr->setOptionProc)(chanPtr->instanceData,
- interp, optionName, newValue);
+ return (*chanPtr->typePtr->setOptionProc)(chanPtr->instanceData,
+ interp, optionName, newValue);
} else {
- return Tcl_BadChannelOption(interp, optionName, (char *) NULL);
+ return Tcl_BadChannelOption(interp, optionName, NULL);
}
/*
@@ -6814,14 +7628,12 @@ Tcl_SetChannelOption(interp, chan, optionName, newValue)
RecycleBuffer(statePtr, statePtr->saveInBufPtr, 1);
statePtr->saveInBufPtr = NULL;
}
- if (statePtr->inQueueHead != NULL) {
- if ((statePtr->inQueueHead->nextPtr == NULL)
- && (statePtr->inQueueHead->nextAdded ==
- statePtr->inQueueHead->nextRemoved)) {
- RecycleBuffer(statePtr, statePtr->inQueueHead, 1);
- statePtr->inQueueHead = NULL;
- statePtr->inQueueTail = NULL;
- }
+ if ((statePtr->inQueueHead != NULL)
+ && (statePtr->inQueueHead->nextPtr == NULL)
+ && IsBufferEmpty(statePtr->inQueueHead)) {
+ RecycleBuffer(statePtr, statePtr->inQueueHead, 1);
+ statePtr->inQueueHead = NULL;
+ statePtr->inQueueTail = NULL;
}
/*
@@ -6829,12 +7641,11 @@ Tcl_SetChannelOption(interp, chan, optionName, newValue)
*/
if (statePtr->outputStage != NULL) {
- ckfree((char *) statePtr->outputStage);
+ ckfree(statePtr->outputStage);
statePtr->outputStage = NULL;
}
if ((statePtr->encoding != NULL) && (statePtr->flags & TCL_WRITABLE)) {
- statePtr->outputStage = (char *)
- ckalloc((unsigned) (statePtr->bufSize + 2));
+ statePtr->outputStage = ckalloc((unsigned) (statePtr->bufSize + 2));
}
return TCL_OK;
}
@@ -6844,11 +7655,10 @@ Tcl_SetChannelOption(interp, chan, optionName, newValue)
*
* CleanupChannelHandlers --
*
- * Removes channel handlers that refer to the supplied interpreter,
- * so that if the actual channel is not closed now, these handlers
- * will not run on subsequent events on the channel. This would be
- * erroneous, because the interpreter no longer has a reference to
- * this channel.
+ * Removes channel handlers that refer to the supplied interpreter, so
+ * that if the actual channel is not closed now, these handlers will not
+ * run on subsequent events on the channel. This would be erroneous,
+ * because the interpreter no longer has a reference to this channel.
*
* Results:
* None.
@@ -6860,38 +7670,37 @@ Tcl_SetChannelOption(interp, chan, optionName, newValue)
*/
static void
-CleanupChannelHandlers(interp, chanPtr)
- Tcl_Interp *interp;
- Channel *chanPtr;
+CleanupChannelHandlers(
+ Tcl_Interp *interp,
+ Channel *chanPtr)
{
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
EventScriptRecord *sPtr, *prevPtr, *nextPtr;
/*
- * Remove fileevent records on this channel that refer to the
- * given interpreter.
+ * Remove fileevent records on this channel that refer to the given
+ * interpreter.
*/
-
- for (sPtr = statePtr->scriptRecordPtr,
- prevPtr = (EventScriptRecord *) NULL;
- sPtr != (EventScriptRecord *) NULL;
- sPtr = nextPtr) {
- nextPtr = sPtr->nextPtr;
- if (sPtr->interp == interp) {
- if (prevPtr == (EventScriptRecord *) NULL) {
- statePtr->scriptRecordPtr = nextPtr;
- } else {
- prevPtr->nextPtr = nextPtr;
- }
- Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr,
- TclChannelEventScriptInvoker, (ClientData) sPtr);
+ for (sPtr = statePtr->scriptRecordPtr, prevPtr = NULL;
+ sPtr != NULL; sPtr = nextPtr) {
+ nextPtr = sPtr->nextPtr;
+ if (sPtr->interp == interp) {
+ if (prevPtr == NULL) {
+ statePtr->scriptRecordPtr = nextPtr;
+ } else {
+ prevPtr->nextPtr = nextPtr;
+ }
- Tcl_DecrRefCount(sPtr->scriptPtr);
- ckfree((char *) sPtr);
- } else {
- prevPtr = sPtr;
- }
+ Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr,
+ TclChannelEventScriptInvoker, sPtr);
+
+ TclDecrRefCount(sPtr->scriptPtr);
+ ckfree((char *) sPtr);
+ } else {
+ prevPtr = sPtr;
+ }
}
}
@@ -6900,10 +7709,9 @@ CleanupChannelHandlers(interp, chanPtr)
*
* Tcl_NotifyChannel --
*
- * This procedure is called by a channel driver when a driver
- * detects an event on a channel. This procedure is responsible
- * for actually handling the event by invoking any channel
- * handler callbacks.
+ * This procedure is called by a channel driver when a driver detects an
+ * event on a channel. This procedure is responsible for actually
+ * handling the event by invoking any channel handler callbacks.
*
* Results:
* None.
@@ -6915,62 +7723,62 @@ CleanupChannelHandlers(interp, chanPtr)
*/
void
-Tcl_NotifyChannel(channel, mask)
- Tcl_Channel channel; /* Channel that detected an event. */
- int mask; /* OR'ed combination of TCL_READABLE,
+Tcl_NotifyChannel(
+ Tcl_Channel channel, /* Channel that detected an event. */
+ int mask) /* OR'ed combination of TCL_READABLE,
* TCL_WRITABLE, or TCL_EXCEPTION: indicates
* which events were detected. */
{
Channel *chanPtr = (Channel *) channel;
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
ChannelHandler *chPtr;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
NextChannelHandler nh;
- Channel* upChanPtr;
- Tcl_ChannelType* upTypePtr;
+ Channel *upChanPtr;
+ const Tcl_ChannelType *upTypePtr;
#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
- /* [SF Tcl Bug 943274]
- * For a non-blocking channel without blockmodeproc we keep track
- * of actual input coming from the OS so that we can do a credible
- * imitation of non-blocking behaviour.
+ /*
+ * [SF Tcl Bug 943274] For a non-blocking channel without blockmodeproc we
+ * keep track of actual input coming from the OS so that we can do a
+ * credible imitation of non-blocking behaviour.
*/
if ((mask & TCL_READABLE) &&
- (statePtr->flags & CHANNEL_NONBLOCKING) &&
- (Tcl_ChannelBlockModeProc(chanPtr->typePtr) == NULL) &&
- !(statePtr->flags & CHANNEL_TIMER_FEV)) {
-
- statePtr->flags |= CHANNEL_HAS_MORE_DATA;
+ (statePtr->flags & CHANNEL_NONBLOCKING) &&
+ (Tcl_ChannelBlockModeProc(chanPtr->typePtr) == NULL) &&
+ !(statePtr->flags & CHANNEL_TIMER_FEV)) {
+ SetFlag(statePtr, CHANNEL_HAS_MORE_DATA);
}
#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */
/*
- * In contrast to the other API functions this procedure walks towards
- * the top of a stack and not down from it.
+ * In contrast to the other API functions this procedure walks towards the
+ * top of a stack and not down from it.
*
* The channel calling this procedure is the one who generated the event,
- * and thus does not take part in handling it. IOW, its HandlerProc is
- * not called, instead we begin with the channel above it.
+ * and thus does not take part in handling it. IOW, its HandlerProc is not
+ * called, instead we begin with the channel above it.
*
- * This behaviour also allows the transformation channels to
- * generate their own events and pass them upward.
+ * This behaviour also allows the transformation channels to generate
+ * their own events and pass them upward.
*/
- while (mask && (chanPtr->upChanPtr != ((Channel*) NULL))) {
- Tcl_DriverHandlerProc* upHandlerProc;
+ while (mask && (chanPtr->upChanPtr != (NULL))) {
+ Tcl_DriverHandlerProc *upHandlerProc;
- upChanPtr = chanPtr->upChanPtr;
+ upChanPtr = chanPtr->upChanPtr;
upTypePtr = upChanPtr->typePtr;
upHandlerProc = Tcl_ChannelHandlerProc(upTypePtr);
if (upHandlerProc != NULL) {
mask = (*upHandlerProc) (upChanPtr->instanceData, mask);
}
- /* ELSE:
- * Ignore transformations which are unable to handle the event
- * coming from below. Assume that they don't change the mask and
- * pass it on.
+ /*
+ * ELSE: Ignore transformations which are unable to handle the event
+ * coming from below. Assume that they don't change the mask and pass
+ * it on.
*/
chanPtr = upChanPtr;
@@ -6979,29 +7787,28 @@ Tcl_NotifyChannel(channel, mask)
channel = (Tcl_Channel) chanPtr;
/*
- * Here we have either reached the top of the stack or the mask is
- * empty. We break out of the procedure if it is the latter.
+ * Here we have either reached the top of the stack or the mask is empty.
+ * We break out of the procedure if it is the latter.
*/
if (!mask) {
- return;
+ return;
}
/*
- * We are now above the topmost channel in a stack and have events
- * left. Now call the channel handlers as usual.
+ * We are now above the topmost channel in a stack and have events left.
+ * Now call the channel handlers as usual.
*
* Preserve the channel struct in case the script closes it.
*/
-
- Tcl_Preserve((ClientData) channel);
- Tcl_Preserve((ClientData) statePtr);
+
+ Tcl_Preserve(channel);
+ Tcl_Preserve(statePtr);
/*
- * If we are flushing in the background, be sure to call FlushChannel
- * for writable events. Note that we have to discard the writable
- * event so we don't call any write handlers before the flush is
- * complete.
+ * If we are flushing in the background, be sure to call FlushChannel for
+ * writable events. Note that we have to discard the writable event so we
+ * don't call any write handlers before the flush is complete.
*/
if ((statePtr->flags & BG_FLUSH_SCHEDULED) && (mask & TCL_WRITABLE)) {
@@ -7013,12 +7820,12 @@ Tcl_NotifyChannel(channel, mask)
* Add this invocation to the list of recursive invocations of
* ChannelHandlerEventProc.
*/
-
- nh.nextHandlerPtr = (ChannelHandler *) NULL;
+
+ nh.nextHandlerPtr = NULL;
nh.nestedHandlerPtr = tsdPtr->nestedHandlerPtr;
tsdPtr->nestedHandlerPtr = &nh;
- for (chPtr = statePtr->chPtr; chPtr != (ChannelHandler *) NULL; ) {
+ for (chPtr = statePtr->chPtr; chPtr != NULL; ) {
/*
* If this channel handler is interested in any of the events that
* have occurred on the channel, invoke its procedure.
@@ -7034,17 +7841,17 @@ Tcl_NotifyChannel(channel, mask)
}
/*
- * Update the notifier interest, since it may have changed after
- * invoking event handlers. Skip that if the channel was deleted
- * in the call to the channel handler.
+ * Update the notifier interest, since it may have changed after invoking
+ * event handlers. Skip that if the channel was deleted in the call to the
+ * channel handler.
*/
if (chanPtr->typePtr != NULL) {
- UpdateInterest(chanPtr);
+ UpdateInterest(chanPtr);
}
- Tcl_Release((ClientData) statePtr);
- Tcl_Release((ClientData) channel);
+ Tcl_Release(statePtr);
+ Tcl_Release(channel);
tsdPtr->nestedHandlerPtr = nh.nestedHandlerPtr;
}
@@ -7054,8 +7861,8 @@ Tcl_NotifyChannel(channel, mask)
*
* UpdateInterest --
*
- * Arrange for the notifier to call us back at appropriate times
- * based on the current state of the channel.
+ * Arrange for the notifier to call us back at appropriate times based on
+ * the current state of the channel.
*
* Results:
* None.
@@ -7067,15 +7874,16 @@ Tcl_NotifyChannel(channel, mask)
*/
static void
-UpdateInterest(chanPtr)
- Channel *chanPtr; /* Channel to update. */
+UpdateInterest(
+ Channel *chanPtr) /* Channel to update. */
{
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
int mask = statePtr->interestMask;
/*
- * If there are flushed buffers waiting to be written, then
- * we need to watch for the channel to become writable.
+ * If there are flushed buffers waiting to be written, then we need to
+ * watch for the channel to become writable.
*/
if (statePtr->flags & BG_FLUSH_SCHEDULED) {
@@ -7085,62 +7893,59 @@ UpdateInterest(chanPtr)
/*
* If there is data in the input queue, and we aren't waiting for more
* data, then we need to schedule a timer so we don't block in the
- * notifier. Also, cancel the read interest so we don't get duplicate
+ * notifier. Also, cancel the read interest so we don't get duplicate
* events.
*/
if (mask & TCL_READABLE) {
if (!(statePtr->flags & CHANNEL_NEED_MORE_DATA)
- && (statePtr->inQueueHead != (ChannelBuffer *) NULL)
- && (statePtr->inQueueHead->nextRemoved <
- statePtr->inQueueHead->nextAdded)) {
+ && (statePtr->inQueueHead != NULL)
+ && IsBufferReady(statePtr->inQueueHead)) {
mask &= ~TCL_READABLE;
/*
* Andreas Kupries, April 11, 2003
*
- * Some operating systems (Solaris 2.6 and higher (but not
- * Solaris 2.5, go figure)) generate READABLE and
- * EXCEPTION events when select()'ing [*] on a plain file,
- * even if EOF was not yet reached. This is a problem in
- * the following situation:
+ * Some operating systems (Solaris 2.6 and higher (but not Solaris
+ * 2.5, go figure)) generate READABLE and EXCEPTION events when
+ * select()'ing [*] on a plain file, even if EOF was not yet
+ * reached. This is a problem in the following situation:
*
- * - An extension asks to get both READABLE and EXCEPTION
- * events.
- * - It reads data into a buffer smaller than the buffer
- * used by Tcl itself.
- * - It does not process all events in the event queue, but
- * only only one, at least in some situations.
+ * - An extension asks to get both READABLE and EXCEPTION events.
+ * - It reads data into a buffer smaller than the buffer used by
+ * Tcl itself.
+ * - It does not process all events in the event queue, but only
+ * one, at least in some situations.
*
* In that case we can get into a situation where
*
* - Tcl drops READABLE here, because it has data in its own
- * buffers waiting to be read by the extension.
+ * buffers waiting to be read by the extension.
* - A READABLE event is syntesized via timer.
* - The OS still reports the EXCEPTION condition on the file.
- * - And the extension gets the EXCPTION event first, and
- * handles this as EOF.
+ * - And the extension gets the EXCPTION event first, and handles
+ * this as EOF.
*
* End result ==> Premature end of reading from a file.
*
- * The concrete example is 'Expect', and its [expect]
- * command (and at the C-level, deep in the bowels of
- * Expect, 'exp_get_next_event'. See marker 'SunOS' for
- * commentary in that function too).
+ * The concrete example is 'Expect', and its [expect] command
+ * (and at the C-level, deep in the bowels of Expect,
+ * 'exp_get_next_event'. See marker 'SunOS' for commentary in
+ * that function too).
*
- * [*] As the Tcl notifier does. See also for marker
- * 'SunOS' in file 'exp_event.c' of Expect.
+ * [*] As the Tcl notifier does. See also for marker 'SunOS' in
+ * file 'exp_event.c' of Expect.
*
- * Our solution here is to drop the interest in the
- * EXCEPTION events too. This compiles on all platforms,
- * and also passes the testsuite on all of them.
+ * Our solution here is to drop the interest in the EXCEPTION
+ * events too. This compiles on all platforms, and also passes the
+ * testsuite on all of them.
*/
mask &= ~TCL_EXCEPTION;
if (!statePtr->timer) {
statePtr->timer = Tcl_CreateTimerHandler(0, ChannelTimerProc,
- (ClientData) chanPtr);
+ chanPtr);
}
}
}
@@ -7152,8 +7957,8 @@ UpdateInterest(chanPtr)
*
* ChannelTimerProc --
*
- * Timer handler scheduled by UpdateInterest to monitor the
- * channel buffers until they are empty.
+ * Timer handler scheduled by UpdateInterest to monitor the channel
+ * buffers until they are empty.
*
* Results:
* None.
@@ -7165,47 +7970,47 @@ UpdateInterest(chanPtr)
*/
static void
-ChannelTimerProc(clientData)
- ClientData clientData;
+ChannelTimerProc(
+ ClientData clientData)
{
- Channel *chanPtr = (Channel *) clientData;
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+ Channel *chanPtr = clientData;
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
if (!(statePtr->flags & CHANNEL_NEED_MORE_DATA)
&& (statePtr->interestMask & TCL_READABLE)
- && (statePtr->inQueueHead != (ChannelBuffer *) NULL)
- && (statePtr->inQueueHead->nextRemoved <
- statePtr->inQueueHead->nextAdded)) {
+ && (statePtr->inQueueHead != NULL)
+ && IsBufferReady(statePtr->inQueueHead)) {
/*
- * Restart the timer in case a channel handler reenters the
- * event loop before UpdateInterest gets called by Tcl_NotifyChannel.
+ * Restart the timer in case a channel handler reenters the event loop
+ * before UpdateInterest gets called by Tcl_NotifyChannel.
*/
- statePtr->timer = Tcl_CreateTimerHandler(0, ChannelTimerProc,
- (ClientData) chanPtr);
+ statePtr->timer = Tcl_CreateTimerHandler(0, ChannelTimerProc,chanPtr);
#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
- /* Set the TIMER flag to notify the higher levels that the
- * driver might have no data for us. We do this only if we are
- * in non-blocking mode and the driver has no BlockModeProc
- * because only then we really don't know if the driver will
- * block or not. A similar test is done in "PeekAhead".
+ /*
+ * Set the TIMER flag to notify the higher levels that the driver
+ * might have no data for us. We do this only if we are in
+ * non-blocking mode and the driver has no BlockModeProc because only
+ * then we really don't know if the driver will block or not. A
+ * similar test is done in "PeekAhead".
*/
if ((statePtr->flags & CHANNEL_NONBLOCKING) &&
(Tcl_ChannelBlockModeProc(chanPtr->typePtr) == NULL)) {
- statePtr->flags |= CHANNEL_TIMER_FEV;
+ SetFlag(statePtr, CHANNEL_TIMER_FEV);
}
#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */
- Tcl_Preserve((ClientData) statePtr);
+ Tcl_Preserve(statePtr);
Tcl_NotifyChannel((Tcl_Channel)chanPtr, TCL_READABLE);
#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
- statePtr->flags &= ~CHANNEL_TIMER_FEV;
+ ResetFlag(statePtr, CHANNEL_TIMER_FEV);
#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */
- Tcl_Release((ClientData) statePtr);
+ Tcl_Release(statePtr);
} else {
statePtr->timer = NULL;
UpdateInterest(chanPtr);
@@ -7217,80 +8022,75 @@ ChannelTimerProc(clientData)
*
* Tcl_CreateChannelHandler --
*
- * Arrange for a given procedure to be invoked whenever the
- * channel indicated by the chanPtr arg becomes readable or
- * writable.
+ * Arrange for a given procedure to be invoked whenever the channel
+ * indicated by the chanPtr arg becomes readable or writable.
*
* Results:
* None.
*
* Side effects:
- * From now on, whenever the I/O channel given by chanPtr becomes
- * ready in the way indicated by mask, proc will be invoked.
- * See the manual entry for details on the calling sequence
- * to proc. If there is already an event handler for chan, proc
- * and clientData, then the mask will be updated.
+ * From now on, whenever the I/O channel given by chanPtr becomes ready
+ * in the way indicated by mask, proc will be invoked. See the manual
+ * entry for details on the calling sequence to proc. If there is already
+ * an event handler for chan, proc and clientData, then the mask will be
+ * updated.
*
*----------------------------------------------------------------------
*/
void
-Tcl_CreateChannelHandler(chan, mask, proc, clientData)
- Tcl_Channel chan; /* The channel to create the handler for. */
- int mask; /* OR'ed combination of TCL_READABLE,
- * TCL_WRITABLE, and TCL_EXCEPTION:
- * indicates conditions under which
- * proc should be called. Use 0 to
- * disable a registered handler. */
- Tcl_ChannelProc *proc; /* Procedure to call for each
- * selected event. */
- ClientData clientData; /* Arbitrary data to pass to proc. */
+Tcl_CreateChannelHandler(
+ Tcl_Channel chan, /* The channel to create the handler for. */
+ int mask, /* OR'ed combination of TCL_READABLE,
+ * TCL_WRITABLE, and TCL_EXCEPTION: indicates
+ * conditions under which proc should be
+ * called. Use 0 to disable a registered
+ * handler. */
+ Tcl_ChannelProc *proc, /* Procedure to call for each selected
+ * event. */
+ ClientData clientData) /* Arbitrary data to pass to proc. */
{
ChannelHandler *chPtr;
Channel *chanPtr = (Channel *) chan;
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
/*
- * Check whether this channel handler is not already registered. If
- * it is not, create a new record, else reuse existing record (smash
- * current values).
+ * Check whether this channel handler is not already registered. If it is
+ * not, create a new record, else reuse existing record (smash current
+ * values).
*/
- for (chPtr = statePtr->chPtr;
- chPtr != (ChannelHandler *) NULL;
- chPtr = chPtr->nextPtr) {
- if ((chPtr->chanPtr == chanPtr) && (chPtr->proc == proc) &&
- (chPtr->clientData == clientData)) {
- break;
- }
+ for (chPtr = statePtr->chPtr; chPtr != NULL; chPtr = chPtr->nextPtr) {
+ if ((chPtr->chanPtr == chanPtr) && (chPtr->proc == proc) &&
+ (chPtr->clientData == clientData)) {
+ break;
+ }
}
- if (chPtr == (ChannelHandler *) NULL) {
- chPtr = (ChannelHandler *) ckalloc((unsigned) sizeof(ChannelHandler));
- chPtr->mask = 0;
- chPtr->proc = proc;
- chPtr->clientData = clientData;
- chPtr->chanPtr = chanPtr;
- chPtr->nextPtr = statePtr->chPtr;
- statePtr->chPtr = chPtr;
+ if (chPtr == NULL) {
+ chPtr = (ChannelHandler *) ckalloc(sizeof(ChannelHandler));
+ chPtr->mask = 0;
+ chPtr->proc = proc;
+ chPtr->clientData = clientData;
+ chPtr->chanPtr = chanPtr;
+ chPtr->nextPtr = statePtr->chPtr;
+ statePtr->chPtr = chPtr;
}
/*
- * The remainder of the initialization below is done regardless of
- * whether or not this is a new record or a modification of an old
- * one.
+ * The remainder of the initialization below is done regardless of whether
+ * or not this is a new record or a modification of an old one.
*/
chPtr->mask = mask;
/*
- * Recompute the interest mask for the channel - this call may actually
- * be disabling an existing handler.
+ * Recompute the interest mask for the channel - this call may actually be
+ * disabling an existing handler.
*/
-
+
statePtr->interestMask = 0;
- for (chPtr = statePtr->chPtr;
- chPtr != (ChannelHandler *) NULL;
- chPtr = chPtr->nextPtr) {
+ for (chPtr = statePtr->chPtr; chPtr != NULL; chPtr = chPtr->nextPtr) {
statePtr->interestMask |= chPtr->mask;
}
@@ -7302,55 +8102,53 @@ Tcl_CreateChannelHandler(chan, mask, proc, clientData)
*
* Tcl_DeleteChannelHandler --
*
- * Cancel a previously arranged callback arrangement for an IO
- * channel.
+ * Cancel a previously arranged callback arrangement for an IO channel.
*
* Results:
* None.
*
* Side effects:
* If a callback was previously registered for this chan, proc and
- * clientData , it is removed and the callback will no longer be called
+ * clientData, it is removed and the callback will no longer be called
* when the channel becomes ready for IO.
*
*----------------------------------------------------------------------
*/
void
-Tcl_DeleteChannelHandler(chan, proc, clientData)
- Tcl_Channel chan; /* The channel for which to remove the
- * callback. */
- Tcl_ChannelProc *proc; /* The procedure in the callback to delete. */
- ClientData clientData; /* The client data in the callback
- * to delete. */
-
+Tcl_DeleteChannelHandler(
+ Tcl_Channel chan, /* The channel for which to remove the
+ * callback. */
+ Tcl_ChannelProc *proc, /* The procedure in the callback to delete. */
+ ClientData clientData) /* The client data in the callback to
+ * delete. */
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
ChannelHandler *chPtr, *prevChPtr;
Channel *chanPtr = (Channel *) chan;
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
NextChannelHandler *nhPtr;
/*
* Find the entry and the previous one in the list.
*/
- for (prevChPtr = (ChannelHandler *) NULL, chPtr = statePtr->chPtr;
- chPtr != (ChannelHandler *) NULL;
- chPtr = chPtr->nextPtr) {
- if ((chPtr->chanPtr == chanPtr) && (chPtr->clientData == clientData)
- && (chPtr->proc == proc)) {
- break;
- }
- prevChPtr = chPtr;
+ for (prevChPtr = NULL, chPtr = statePtr->chPtr; chPtr != NULL;
+ chPtr = chPtr->nextPtr) {
+ if ((chPtr->chanPtr == chanPtr) && (chPtr->clientData == clientData)
+ && (chPtr->proc == proc)) {
+ break;
+ }
+ prevChPtr = chPtr;
}
/*
* If not found, return without doing anything.
*/
- if (chPtr == (ChannelHandler *) NULL) {
- return;
+ if (chPtr == NULL) {
+ return;
}
/*
@@ -7358,36 +8156,32 @@ Tcl_DeleteChannelHandler(chan, proc, clientData)
* process the next one instead - we are going to delete *this* one.
*/
- for (nhPtr = tsdPtr->nestedHandlerPtr;
- nhPtr != (NextChannelHandler *) NULL;
- nhPtr = nhPtr->nestedHandlerPtr) {
- if (nhPtr->nextHandlerPtr == chPtr) {
- nhPtr->nextHandlerPtr = chPtr->nextPtr;
- }
+ for (nhPtr = tsdPtr->nestedHandlerPtr; nhPtr != NULL;
+ nhPtr = nhPtr->nestedHandlerPtr) {
+ if (nhPtr->nextHandlerPtr == chPtr) {
+ nhPtr->nextHandlerPtr = chPtr->nextPtr;
+ }
}
/*
* Splice it out of the list of channel handlers.
*/
-
- if (prevChPtr == (ChannelHandler *) NULL) {
- statePtr->chPtr = chPtr->nextPtr;
+
+ if (prevChPtr == NULL) {
+ statePtr->chPtr = chPtr->nextPtr;
} else {
- prevChPtr->nextPtr = chPtr->nextPtr;
+ prevChPtr->nextPtr = chPtr->nextPtr;
}
ckfree((char *) chPtr);
/*
* Recompute the interest list for the channel, so that infinite loops
- * will not result if Tcl_DeleteChannelHandler is called inside an
- * event.
+ * will not result if Tcl_DeleteChannelHandler is called inside an event.
*/
statePtr->interestMask = 0;
- for (chPtr = statePtr->chPtr;
- chPtr != (ChannelHandler *) NULL;
- chPtr = chPtr->nextPtr) {
- statePtr->interestMask |= chPtr->mask;
+ for (chPtr = statePtr->chPtr; chPtr != NULL; chPtr = chPtr->nextPtr) {
+ statePtr->interestMask |= chPtr->mask;
}
UpdateInterest(statePtr->topChanPtr);
@@ -7398,8 +8192,8 @@ Tcl_DeleteChannelHandler(chan, proc, clientData)
*
* DeleteScriptRecord --
*
- * Delete a script record for this combination of channel, interp
- * and mask.
+ * Delete a script record for this combination of channel, interp and
+ * mask.
*
* Results:
* None.
@@ -7411,36 +8205,35 @@ Tcl_DeleteChannelHandler(chan, proc, clientData)
*/
static void
-DeleteScriptRecord(interp, chanPtr, mask)
- Tcl_Interp *interp; /* Interpreter in which script was to be
- * executed. */
- Channel *chanPtr; /* The channel for which to delete the
- * script record (if any). */
- int mask; /* Events in mask must exactly match mask
- * of script to delete. */
-{
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+DeleteScriptRecord(
+ Tcl_Interp *interp, /* Interpreter in which script was to be
+ * executed. */
+ Channel *chanPtr, /* The channel for which to delete the script
+ * record (if any). */
+ int mask) /* Events in mask must exactly match mask of
+ * script to delete. */
+{
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
EventScriptRecord *esPtr, *prevEsPtr;
- for (esPtr = statePtr->scriptRecordPtr,
- prevEsPtr = (EventScriptRecord *) NULL;
- esPtr != (EventScriptRecord *) NULL;
- prevEsPtr = esPtr, esPtr = esPtr->nextPtr) {
- if ((esPtr->interp == interp) && (esPtr->mask == mask)) {
- if (esPtr == statePtr->scriptRecordPtr) {
- statePtr->scriptRecordPtr = esPtr->nextPtr;
- } else {
- prevEsPtr->nextPtr = esPtr->nextPtr;
- }
+ for (esPtr = statePtr->scriptRecordPtr, prevEsPtr = NULL; esPtr != NULL;
+ prevEsPtr = esPtr, esPtr = esPtr->nextPtr) {
+ if ((esPtr->interp == interp) && (esPtr->mask == mask)) {
+ if (esPtr == statePtr->scriptRecordPtr) {
+ statePtr->scriptRecordPtr = esPtr->nextPtr;
+ } else {
+ prevEsPtr->nextPtr = esPtr->nextPtr;
+ }
+
+ Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr,
+ TclChannelEventScriptInvoker, esPtr);
- Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr,
- TclChannelEventScriptInvoker, (ClientData) esPtr);
-
- Tcl_DecrRefCount(esPtr->scriptPtr);
- ckfree((char *) esPtr);
+ TclDecrRefCount(esPtr->scriptPtr);
+ ckfree((char *) esPtr);
- break;
- }
+ break;
+ }
}
}
@@ -7462,40 +8255,54 @@ DeleteScriptRecord(interp, chanPtr, mask)
*/
static void
-CreateScriptRecord(interp, chanPtr, mask, scriptPtr)
- Tcl_Interp *interp; /* Interpreter in which to execute
- * the stored script. */
- Channel *chanPtr; /* Channel for which script is to
- * be stored. */
- int mask; /* Set of events for which script
- * will be invoked. */
- Tcl_Obj *scriptPtr; /* Pointer to script object. */
-{
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
+CreateScriptRecord(
+ Tcl_Interp *interp, /* Interpreter in which to execute the stored
+ * script. */
+ Channel *chanPtr, /* Channel for which script is to be stored */
+ int mask, /* Set of events for which script will be
+ * invoked. */
+ Tcl_Obj *scriptPtr) /* Pointer to script object. */
+{
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
EventScriptRecord *esPtr;
+ int makeCH;
+
+ for (esPtr=statePtr->scriptRecordPtr; esPtr!=NULL; esPtr=esPtr->nextPtr) {
+ if ((esPtr->interp == interp) && (esPtr->mask == mask)) {
+ TclDecrRefCount(esPtr->scriptPtr);
+ esPtr->scriptPtr = NULL;
+ break;
+ }
+ }
+
+ makeCH = (esPtr == NULL);
- for (esPtr = statePtr->scriptRecordPtr;
- esPtr != (EventScriptRecord *) NULL;
- esPtr = esPtr->nextPtr) {
- if ((esPtr->interp == interp) && (esPtr->mask == mask)) {
- Tcl_DecrRefCount(esPtr->scriptPtr);
- esPtr->scriptPtr = (Tcl_Obj *) NULL;
- break;
- }
- }
- if (esPtr == (EventScriptRecord *) NULL) {
- esPtr = (EventScriptRecord *) ckalloc((unsigned)
- sizeof(EventScriptRecord));
- Tcl_CreateChannelHandler((Tcl_Channel) chanPtr, mask,
- TclChannelEventScriptInvoker, (ClientData) esPtr);
- esPtr->nextPtr = statePtr->scriptRecordPtr;
- statePtr->scriptRecordPtr = esPtr;
+ if (makeCH) {
+ esPtr = (EventScriptRecord *) ckalloc(sizeof(EventScriptRecord));
}
+
+ /*
+ * Initialize the structure before calling Tcl_CreateChannelHandler,
+ * because a reflected channel caling 'chan postevent' aka
+ * 'Tcl_NotifyChannel' in its 'watch'Proc will invoke
+ * 'TclChannelEventScriptInvoker' immediately, and we do not wish it to
+ * see uninitialized memory and crash. See [Bug 2918110].
+ */
+
esPtr->chanPtr = chanPtr;
esPtr->interp = interp;
esPtr->mask = mask;
Tcl_IncrRefCount(scriptPtr);
esPtr->scriptPtr = scriptPtr;
+
+ if (makeCH) {
+ esPtr->nextPtr = statePtr->scriptRecordPtr;
+ statePtr->scriptRecordPtr = esPtr;
+
+ Tcl_CreateChannelHandler((Tcl_Channel) chanPtr, mask,
+ TclChannelEventScriptInvoker, esPtr);
+ }
}
/*
@@ -7503,9 +8310,9 @@ CreateScriptRecord(interp, chanPtr, mask, scriptPtr)
*
* TclChannelEventScriptInvoker --
*
- * Invokes a script scheduled by "fileevent" for when the channel
- * becomes ready for IO. This function is invoked by the channel
- * handler which was created by the Tcl "fileevent" command.
+ * Invokes a script scheduled by "fileevent" for when the channel becomes
+ * ready for IO. This function is invoked by the channel handler which
+ * was created by the Tcl "fileevent" command.
*
* Results:
* None.
@@ -7517,46 +8324,46 @@ CreateScriptRecord(interp, chanPtr, mask, scriptPtr)
*/
void
-TclChannelEventScriptInvoker(clientData, mask)
- ClientData clientData; /* The script+interp record. */
- int mask; /* Not used. */
+TclChannelEventScriptInvoker(
+ ClientData clientData, /* The script+interp record. */
+ int mask) /* Not used. */
{
Tcl_Interp *interp; /* Interpreter in which to eval the script. */
Channel *chanPtr; /* The channel for which this handler is
- * registered. */
+ * registered. */
EventScriptRecord *esPtr; /* The event script + interpreter to eval it
- * in. */
+ * in. */
int result; /* Result of call to eval script. */
- esPtr = (EventScriptRecord *) clientData;
- chanPtr = esPtr->chanPtr;
- mask = esPtr->mask;
- interp = esPtr->interp;
+ esPtr = clientData;
+ chanPtr = esPtr->chanPtr;
+ mask = esPtr->mask;
+ interp = esPtr->interp;
/*
- * We must preserve the interpreter so we can report errors on it
- * later. Note that we do not need to preserve the channel because
- * that is done by Tcl_NotifyChannel before calling channel handlers.
+ * We must preserve the interpreter so we can report errors on it later.
+ * Note that we do not need to preserve the channel because that is done
+ * by Tcl_NotifyChannel before calling channel handlers.
*/
-
- Tcl_Preserve((ClientData) interp);
+
+ Tcl_Preserve(interp);
result = Tcl_EvalObjEx(interp, esPtr->scriptPtr, TCL_EVAL_GLOBAL);
/*
- * On error, cause a background error and remove the channel handler
- * and the script record.
+ * On error, cause a background error and remove the channel handler and
+ * the script record.
*
* NOTE: Must delete channel handler before causing the background error
* because the background error may want to reinstall the handler.
*/
-
+
if (result != TCL_OK) {
if (chanPtr->typePtr != NULL) {
DeleteScriptRecord(interp, chanPtr, mask);
}
- Tcl_BackgroundError(interp);
+ TclBackgroundException(interp, result);
}
- Tcl_Release((ClientData) interp);
+ Tcl_Release(interp);
}
/*
@@ -7564,10 +8371,10 @@ TclChannelEventScriptInvoker(clientData, mask)
*
* Tcl_FileEventObjCmd --
*
- * This procedure implements the "fileevent" Tcl command. See the
- * user documentation for details on what it does. This command is
- * based on the Tk command "fileevent" which in turn is based on work
- * contributed by Mark Diekhans.
+ * This procedure implements the "fileevent" Tcl command. See the user
+ * documentation for details on what it does. This command is based on
+ * the Tk command "fileevent" which in turn is based on work contributed
+ * by Mark Diekhans.
*
* Results:
* A standard Tcl result.
@@ -7580,22 +8387,20 @@ TclChannelEventScriptInvoker(clientData, mask)
/* ARGSUSED */
int
-Tcl_FileEventObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Interpreter in which the channel
- * for which to create the handler
- * is found. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
-{
- Channel *chanPtr; /* The channel to create
- * the handler for. */
- ChannelState *statePtr; /* state info for channel */
- Tcl_Channel chan; /* The opaque type for the channel. */
+Tcl_FileEventObjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter in which the channel for which
+ * to create the handler is found. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Channel *chanPtr; /* The channel to create the handler for. */
+ ChannelState *statePtr; /* State info for channel */
+ Tcl_Channel chan; /* The opaque type for the channel. */
char *chanName;
- int modeIndex; /* Index of mode argument. */
+ int modeIndex; /* Index of mode argument. */
int mask;
- static CONST char *modeOptions[] = {"readable", "writable", NULL};
+ static const char *modeOptions[] = {"readable", "writable", NULL};
static int maskArray[] = {TCL_READABLE, TCL_WRITABLE};
if ((objc != 3) && (objc != 4)) {
@@ -7608,85 +8413,110 @@ Tcl_FileEventObjCmd(clientData, interp, objc, objv)
}
mask = maskArray[modeIndex];
- chanName = Tcl_GetString(objv[1]);
+ chanName = TclGetString(objv[1]);
chan = Tcl_GetChannel(interp, chanName, NULL);
- if (chan == (Tcl_Channel) NULL) {
+ if (chan == NULL) {
return TCL_ERROR;
}
- chanPtr = (Channel *) chan;
+ chanPtr = (Channel *) chan;
statePtr = chanPtr->state;
if ((statePtr->flags & mask) == 0) {
- Tcl_AppendResult(interp, "channel is not ",
- (mask == TCL_READABLE) ? "readable" : "writable",
- (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "channel is not ",
+ (mask == TCL_READABLE) ? "readable" : "writable", NULL);
+ return TCL_ERROR;
}
-
+
/*
* If we are supposed to return the script, do so.
*/
if (objc == 3) {
EventScriptRecord *esPtr;
- for (esPtr = statePtr->scriptRecordPtr;
- esPtr != (EventScriptRecord *) NULL;
- esPtr = esPtr->nextPtr) {
+ for (esPtr = statePtr->scriptRecordPtr; esPtr != NULL;
+ esPtr = esPtr->nextPtr) {
if ((esPtr->interp == interp) && (esPtr->mask == mask)) {
Tcl_SetObjResult(interp, esPtr->scriptPtr);
break;
}
}
- return TCL_OK;
+ return TCL_OK;
}
/*
* If we are supposed to delete a stored script, do so.
*/
- if (*(Tcl_GetString(objv[3])) == '\0') {
- DeleteScriptRecord(interp, chanPtr, mask);
- return TCL_OK;
+ if (*(TclGetString(objv[3])) == '\0') {
+ DeleteScriptRecord(interp, chanPtr, mask);
+ return TCL_OK;
}
/*
- * Make the script record that will link between the event and the
- * script to invoke. This also creates a channel event handler which
- * will evaluate the script in the supplied interpreter.
+ * Make the script record that will link between the event and the script
+ * to invoke. This also creates a channel event handler which will
+ * evaluate the script in the supplied interpreter.
*/
CreateScriptRecord(interp, chanPtr, mask, objv[3]);
-
+
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
+ * ZeroTransferTimerProc --
+ *
+ * Timer handler scheduled by TclCopyChannel so that -command is
+ * called asynchronously even when -size is 0.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Calls CopyData for -command invocation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ZeroTransferTimerProc(
+ ClientData clientData)
+{
+ /* calling CopyData with mask==0 still implies immediate invocation of the
+ * -command callback, and completion of the fcopy.
+ */
+ CopyData(clientData, 0);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TclCopyChannel --
*
* This routine copies data from one channel to another, either
- * synchronously or asynchronously. If a command script is
- * supplied, the operation runs in the background. The script
- * is invoked when the copy completes. Otherwise the function
- * waits until the copy is completed before returning.
+ * synchronously or asynchronously. If a command script is supplied, the
+ * operation runs in the background. The script is invoked when the copy
+ * completes. Otherwise the function waits until the copy is completed
+ * before returning.
*
* Results:
* A standard Tcl result.
*
* Side effects:
- * May schedule a background copy operation that causes both
- * channels to be marked busy.
+ * May schedule a background copy operation that causes both channels to
+ * be marked busy.
*
*----------------------------------------------------------------------
*/
int
-TclCopyChannel(interp, inChan, outChan, toRead, cmdPtr)
- Tcl_Interp *interp; /* Current interpreter. */
- Tcl_Channel inChan; /* Channel to read from. */
- Tcl_Channel outChan; /* Channel to write to. */
- int toRead; /* Amount of data to copy, or -1 for all. */
- Tcl_Obj *cmdPtr; /* Pointer to script to execute or NULL. */
+TclCopyChannel(
+ Tcl_Interp *interp, /* Current interpreter. */
+ Tcl_Channel inChan, /* Channel to read from. */
+ Tcl_Channel outChan, /* Channel to write to. */
+ int toRead, /* Amount of data to copy, or -1 for all. */
+ Tcl_Obj *cmdPtr) /* Pointer to script to execute or NULL. */
{
Channel *inPtr = (Channel *) inChan;
Channel *outPtr = (Channel *) outChan;
@@ -7695,53 +8525,46 @@ TclCopyChannel(interp, inChan, outChan, toRead, cmdPtr)
CopyState *csPtr;
int nonBlocking = (cmdPtr) ? CHANNEL_NONBLOCKING : 0;
- inStatePtr = inPtr->state;
- outStatePtr = outPtr->state;
+ inStatePtr = inPtr->state;
+ outStatePtr = outPtr->state;
if (BUSY_STATE(inStatePtr,TCL_READABLE)) {
if (interp) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "channel \"",
+ Tcl_AppendResult(interp, "channel \"",
Tcl_GetChannelName(inChan), "\" is busy", NULL);
}
return TCL_ERROR;
}
if (BUSY_STATE(outStatePtr,TCL_WRITABLE)) {
if (interp) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "channel \"",
+ Tcl_AppendResult(interp, "channel \"",
Tcl_GetChannelName(outChan), "\" is busy", NULL);
}
return TCL_ERROR;
}
- readFlags = inStatePtr->flags;
- writeFlags = outStatePtr->flags;
+ readFlags = inStatePtr->flags;
+ writeFlags = outStatePtr->flags;
/*
- * Set up the blocking mode appropriately. Background copies need
- * non-blocking channels. Foreground copies need blocking channels.
- * If there is an error, restore the old blocking mode.
+ * Set up the blocking mode appropriately. Background copies need
+ * non-blocking channels. Foreground copies need blocking channels. If
+ * there is an error, restore the old blocking mode.
*/
if (nonBlocking != (readFlags & CHANNEL_NONBLOCKING)) {
- if (SetBlockMode(interp, inPtr,
- nonBlocking ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING)
- != TCL_OK) {
+ if (SetBlockMode(interp, inPtr, nonBlocking ?
+ TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING) != TCL_OK) {
return TCL_ERROR;
}
- }
- if (inPtr != outPtr) {
- if (nonBlocking != (writeFlags & CHANNEL_NONBLOCKING)) {
- if (SetBlockMode(NULL, outPtr,
- nonBlocking ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING)
- != TCL_OK) {
- if (nonBlocking != (readFlags & CHANNEL_NONBLOCKING)) {
- SetBlockMode(NULL, inPtr,
- (readFlags & CHANNEL_NONBLOCKING)
- ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING);
- return TCL_ERROR;
- }
- }
- }
+ }
+ if ((inPtr!=outPtr) && (nonBlocking!=(writeFlags&CHANNEL_NONBLOCKING)) &&
+ (SetBlockMode(NULL, outPtr, nonBlocking ?
+ TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING) != TCL_OK) &&
+ (nonBlocking != (readFlags & CHANNEL_NONBLOCKING))) {
+ SetBlockMode(NULL, inPtr, (readFlags & CHANNEL_NONBLOCKING)
+ ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING);
+ return TCL_ERROR;
}
/*
@@ -7753,19 +8576,19 @@ TclCopyChannel(interp, inChan, outChan, toRead, cmdPtr)
/*
* Allocate a new CopyState to maintain info about the current copy in
- * progress. This structure will be deallocated when the copy is
+ * progress. This structure will be deallocated when the copy is
* completed.
*/
- csPtr = (CopyState*) ckalloc(sizeof(CopyState) + inStatePtr->bufSize);
- csPtr->bufSize = inStatePtr->bufSize;
- csPtr->readPtr = inPtr;
- csPtr->writePtr = outPtr;
- csPtr->readFlags = readFlags;
+ csPtr = (CopyState *) ckalloc(sizeof(CopyState) + inStatePtr->bufSize);
+ csPtr->bufSize = inStatePtr->bufSize;
+ csPtr->readPtr = inPtr;
+ csPtr->writePtr = outPtr;
+ csPtr->readFlags = readFlags;
csPtr->writeFlags = writeFlags;
- csPtr->toRead = toRead;
- csPtr->total = 0;
- csPtr->interp = interp;
+ csPtr->toRead = toRead;
+ csPtr->total = 0;
+ csPtr->interp = interp;
if (cmdPtr) {
Tcl_IncrRefCount(cmdPtr);
}
@@ -7775,6 +8598,16 @@ TclCopyChannel(interp, inChan, outChan, toRead, cmdPtr)
outStatePtr->csPtrW = csPtr;
/*
+ * Special handling of -size 0 async transfers, so that the -command is
+ * still called asynchronously.
+ */
+
+ if ((nonBlocking == CHANNEL_NONBLOCKING) && (toRead == 0)) {
+ Tcl_CreateTimerHandler(0, ZeroTransferTimerProc, csPtr);
+ return 0;
+ }
+
+ /*
* Start copying data between the channels.
*/
@@ -7786,8 +8619,8 @@ TclCopyChannel(interp, inChan, outChan, toRead, cmdPtr)
*
* CopyData --
*
- * This function implements the lowest level of the copying
- * mechanism for TclCopyChannel.
+ * This function implements the lowest level of the copying mechanism for
+ * TclCopyChannel.
*
* Results:
* Returns TCL_OK on success, else TCL_ERROR.
@@ -7799,19 +8632,20 @@ TclCopyChannel(interp, inChan, outChan, toRead, cmdPtr)
*/
static int
-CopyData(csPtr, mask)
- CopyState *csPtr; /* State of copy operation. */
- int mask; /* Current channel event flags. */
+CopyData(
+ CopyState *csPtr, /* State of copy operation. */
+ int mask) /* Current channel event flags. */
{
Tcl_Interp *interp;
- Tcl_Obj *cmdPtr, *errObj = NULL, *bufObj = NULL;
+ Tcl_Obj *cmdPtr, *errObj = NULL, *bufObj = NULL, *msg = NULL;
Tcl_Channel inChan, outChan;
ChannelState *inStatePtr, *outStatePtr;
- int result = TCL_OK, size, total, sizeb;
- char* buffer;
-
- int inBinary, outBinary, sameEncoding; /* Encoding control */
- int underflow; /* input underflow */
+ int result = TCL_OK, size, sizeb;
+ Tcl_WideInt total;
+ char *buffer;
+ int inBinary, outBinary, sameEncoding;
+ /* Encoding control */
+ int underflow; /* Input underflow */
inChan = (Tcl_Channel) csPtr->readPtr;
outChan = (Tcl_Channel) csPtr->writePtr;
@@ -7823,18 +8657,18 @@ CopyData(csPtr, mask)
/*
* Copy the data the slow way, using the translation mechanism.
*
- * Note: We have make sure that we use the topmost channel in a stack
- * for the copying. The caller uses Tcl_GetChannel to access it, and
- * thus gets the bottom of the stack.
+ * Note: We have make sure that we use the topmost channel in a stack for
+ * the copying. The caller uses Tcl_GetChannel to access it, and thus gets
+ * the bottom of the stack.
*/
- inBinary = (inStatePtr->encoding == NULL);
- outBinary = (outStatePtr->encoding == NULL);
- sameEncoding = (inStatePtr->encoding == outStatePtr->encoding);
+ inBinary = (inStatePtr->encoding == NULL);
+ outBinary = (outStatePtr->encoding == NULL);
+ sameEncoding = (inStatePtr->encoding == outStatePtr->encoding);
if (!(inBinary || sameEncoding)) {
- bufObj = Tcl_NewObj ();
- Tcl_IncrRefCount (bufObj);
+ TclNewObj(bufObj);
+ Tcl_IncrRefCount(bufObj);
}
while (csPtr->toRead != 0) {
@@ -7842,17 +8676,19 @@ CopyData(csPtr, mask)
* Check for unreported background errors.
*/
- if (inStatePtr->unreportedError != 0) {
+ Tcl_GetChannelError(inChan, &msg);
+ if ((inStatePtr->unreportedError != 0) || (msg != NULL)) {
Tcl_SetErrno(inStatePtr->unreportedError);
inStatePtr->unreportedError = 0;
goto readError;
}
- if (outStatePtr->unreportedError != 0) {
+ Tcl_GetChannelError(outChan, &msg);
+ if ((outStatePtr->unreportedError != 0) || (msg != NULL)) {
Tcl_SetErrno(outStatePtr->unreportedError);
outStatePtr->unreportedError = 0;
goto writeError;
}
-
+
if (cmdPtr && (mask == 0)) {
/*
* In async mode, we skip reading synchronously and fake an
@@ -7867,51 +8703,60 @@ CopyData(csPtr, mask)
*/
if ((csPtr->toRead == -1) || (csPtr->toRead > csPtr->bufSize)) {
- sizeb = csPtr->bufSize;
+ sizeb = csPtr->bufSize;
} else {
- sizeb = csPtr->toRead;
+ sizeb = csPtr->toRead;
}
if (inBinary || sameEncoding) {
- size = DoRead(inStatePtr->topChanPtr, csPtr->buffer, sizeb);
+ size = DoRead(inStatePtr->topChanPtr, csPtr->buffer, sizeb);
} else {
- size = DoReadChars(inStatePtr->topChanPtr, bufObj, sizeb, 0 /* No append */);
+ size = DoReadChars(inStatePtr->topChanPtr, bufObj, sizeb,
+ 0 /* No append */);
}
- underflow = (size >= 0) && (size < sizeb); /* input underflow */
+ underflow = (size >= 0) && (size < sizeb); /* Input underflow */
}
if (size < 0) {
- readError:
- errObj = Tcl_NewObj();
- Tcl_AppendStringsToObj(errObj, "error reading \"",
- Tcl_GetChannelName(inChan), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ readError:
+ if (interp) {
+ TclNewObj(errObj);
+ Tcl_AppendStringsToObj(errObj, "error reading \"",
+ Tcl_GetChannelName(inChan), "\": ", NULL);
+ if (msg != NULL) {
+ Tcl_AppendObjToObj(errObj, msg);
+ } else {
+ Tcl_AppendStringsToObj(errObj, Tcl_PosixError(interp),
+ NULL);
+ }
+ }
+ if (msg != NULL) {
+ Tcl_DecrRefCount(msg);
+ }
break;
} else if (underflow) {
/*
- * We had an underflow on the read side. If we are at
- * EOF, and not in the synchronous part of an asynchronous
- * fcopy, then the copying is done, otherwise set up a
- * channel handler to detect when the channel becomes
- * readable again.
+ * We had an underflow on the read side. If we are at EOF, and not
+ * in the synchronous part of an asynchronous fcopy, then the
+ * copying is done, otherwise set up a channel handler to detect
+ * when the channel becomes readable again.
*/
-
+
if ((size == 0) && Tcl_Eof(inChan) && !(cmdPtr && (mask == 0))) {
break;
}
if (((!Tcl_Eof(inChan)) || (cmdPtr && (mask == 0))) &&
!(mask & TCL_READABLE)) {
if (mask & TCL_WRITABLE) {
- Tcl_DeleteChannelHandler(outChan, CopyEventProc,
- (ClientData) csPtr);
+ Tcl_DeleteChannelHandler(outChan, CopyEventProc, csPtr);
}
- Tcl_CreateChannelHandler(inChan, TCL_READABLE,
- CopyEventProc, (ClientData) csPtr);
+ Tcl_CreateChannelHandler(inChan, TCL_READABLE, CopyEventProc,
+ csPtr);
}
if (size == 0) {
- if (bufObj != (Tcl_Obj*) NULL) {
- Tcl_DecrRefCount (bufObj);
- bufObj = (Tcl_Obj*) NULL;
+ if (bufObj != NULL) {
+ TclDecrRefCount(bufObj);
+ bufObj = NULL;
}
return TCL_OK;
}
@@ -7925,7 +8770,7 @@ CopyData(csPtr, mask)
buffer = csPtr->buffer;
sizeb = size;
} else {
- buffer = Tcl_GetStringFromObj (bufObj, &sizeb);
+ buffer = TclGetStringFromObj(bufObj, &sizeb);
}
if (outBinary || sameEncoding) {
@@ -7947,19 +8792,29 @@ CopyData(csPtr, mask)
*/
if (sizeb < 0) {
- writeError:
- errObj = Tcl_NewObj();
- Tcl_AppendStringsToObj(errObj, "error writing \"",
- Tcl_GetChannelName(outChan), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ writeError:
+ if (interp) {
+ TclNewObj(errObj);
+ Tcl_AppendStringsToObj(errObj, "error writing \"",
+ Tcl_GetChannelName(outChan), "\": ", NULL);
+ if (msg != NULL) {
+ Tcl_AppendObjToObj(errObj, msg);
+ } else {
+ Tcl_AppendStringsToObj(errObj, Tcl_PosixError(interp),
+ NULL);
+ }
+ }
+ if (msg != NULL) {
+ Tcl_DecrRefCount(msg);
+ }
break;
}
/*
- * Update the current byte count. Do it now so the count is
- * valid before a return or break takes us out of the loop.
- * The invariant at the top of the loop should be that
- * csPtr->toRead holds the number of bytes left to copy.
+ * (UP) Update the current byte count. Do it now so the count is valid
+ * before a return or break takes us out of the loop. The invariant at
+ * the top of the loop should be that csPtr->toRead holds the number
+ * of bytes left to copy.
*/
if (csPtr->toRead != -1) {
@@ -7971,89 +8826,90 @@ CopyData(csPtr, mask)
* Break loop if EOF && (size>0)
*/
- if (Tcl_Eof(inChan)) {
- break;
- }
+ if (Tcl_Eof(inChan)) {
+ break;
+ }
/*
- * Check to see if the write is happening in the background. If so,
+ * Check to see if the write is happening in the background. If so,
* stop copying and wait for the channel to become writable again.
* After input underflow we already installed a readable handler
* therefore we don't need a writable handler.
*/
- if ( ! underflow && (outStatePtr->flags & BG_FLUSH_SCHEDULED) ) {
+ if (!underflow && (outStatePtr->flags & BG_FLUSH_SCHEDULED)) {
if (!(mask & TCL_WRITABLE)) {
if (mask & TCL_READABLE) {
- Tcl_DeleteChannelHandler(inChan, CopyEventProc,
- (ClientData) csPtr);
+ Tcl_DeleteChannelHandler(inChan, CopyEventProc, csPtr);
}
Tcl_CreateChannelHandler(outChan, TCL_WRITABLE,
- CopyEventProc, (ClientData) csPtr);
+ CopyEventProc, csPtr);
}
- if (bufObj != (Tcl_Obj*) NULL) {
- Tcl_DecrRefCount (bufObj);
- bufObj = (Tcl_Obj*) NULL;
+ if (bufObj != NULL) {
+ TclDecrRefCount(bufObj);
+ bufObj = NULL;
}
return TCL_OK;
}
/*
- * For background copies, we only do one buffer per invocation so
- * we don't starve the rest of the system.
+ * For background copies, we only do one buffer per invocation so we
+ * don't starve the rest of the system.
*/
if (cmdPtr && (csPtr->toRead != 0)) {
/*
- * The first time we enter this code, there won't be a
- * channel handler established yet, so do it here.
+ * The first time we enter this code, there won't be a channel
+ * handler established yet, so do it here.
*/
if (mask == 0) {
- Tcl_CreateChannelHandler(outChan, TCL_WRITABLE,
- CopyEventProc, (ClientData) csPtr);
+ Tcl_CreateChannelHandler(outChan, TCL_WRITABLE, CopyEventProc,
+ csPtr);
}
- if (bufObj != (Tcl_Obj*) NULL) {
- Tcl_DecrRefCount (bufObj);
- bufObj = (Tcl_Obj*) NULL;
+ if (bufObj != NULL) {
+ TclDecrRefCount(bufObj);
+ bufObj = NULL;
}
return TCL_OK;
}
} /* while */
- if (bufObj != (Tcl_Obj*) NULL) {
- Tcl_DecrRefCount (bufObj);
- bufObj = (Tcl_Obj*) NULL;
+ if (bufObj != NULL) {
+ TclDecrRefCount(bufObj);
+ bufObj = NULL;
}
/*
- * Make the callback or return the number of bytes transferred.
- * The local total is used because StopCopy frees csPtr.
+ * Make the callback or return the number of bytes transferred. The local
+ * total is used because StopCopy frees csPtr.
*/
total = csPtr->total;
if (cmdPtr && interp) {
+ int code;
/*
- * Get a private copy of the command so we can mutate it
- * by adding arguments. Note that StopCopy frees our saved
- * reference to the original command obj.
+ * Get a private copy of the command so we can mutate it by adding
+ * arguments. Note that StopCopy frees our saved reference to the
+ * original command obj.
*/
cmdPtr = Tcl_DuplicateObj(cmdPtr);
Tcl_IncrRefCount(cmdPtr);
StopCopy(csPtr);
- Tcl_Preserve((ClientData) interp);
+ Tcl_Preserve(interp);
- Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewIntObj(total));
+ Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewWideIntObj(total));
if (errObj) {
Tcl_ListObjAppendElement(interp, cmdPtr, errObj);
}
- if (Tcl_EvalObjEx(interp, cmdPtr, TCL_EVAL_GLOBAL) != TCL_OK) {
- Tcl_BackgroundError(interp);
+ code = Tcl_EvalObjEx(interp, cmdPtr, TCL_EVAL_GLOBAL);
+ if (code != TCL_OK) {
+ TclBackgroundException(interp, code);
result = TCL_ERROR;
}
- Tcl_DecrRefCount(cmdPtr);
- Tcl_Release((ClientData) interp);
+ TclDecrRefCount(cmdPtr);
+ Tcl_Release(interp);
} else {
StopCopy(csPtr);
if (interp) {
@@ -8062,7 +8918,7 @@ CopyData(csPtr, mask)
result = TCL_ERROR;
} else {
Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), total);
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(total));
}
}
}
@@ -8079,8 +8935,8 @@ CopyData(csPtr, mask)
* No encoding conversions are applied to the bytes being read.
*
* Results:
- * The number of characters read, or -1 on error. Use Tcl_GetErrno()
- * to retrieve the error code for the error that occurred.
+ * The number of characters read, or -1 on error. Use Tcl_GetErrno() to
+ * retrieve the error code for the error that occurred.
*
* Side effects:
* May cause input to be buffered.
@@ -8089,60 +8945,61 @@ CopyData(csPtr, mask)
*/
static int
-DoRead(chanPtr, bufPtr, toRead)
- Channel *chanPtr; /* The channel from which to read. */
- char *bufPtr; /* Where to store input read. */
- int toRead; /* Maximum number of bytes to read. */
-{
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
- int copied; /* How many characters were copied into
- * the result string? */
- int copiedNow; /* How many characters were copied from
- * the current input buffer? */
+DoRead(
+ Channel *chanPtr, /* The channel from which to read. */
+ char *bufPtr, /* Where to store input read. */
+ int toRead) /* Maximum number of bytes to read. */
+{
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
+ int copied; /* How many characters were copied into the
+ * result string? */
+ int copiedNow; /* How many characters were copied from the
+ * current input buffer? */
int result; /* Of calling GetInput. */
/*
- * If we have not encountered a sticky EOF, clear the EOF bit. Either
- * way clear the BLOCKED bit. We want to discover these anew during
- * each operation.
+ * If we have not encountered a sticky EOF, clear the EOF bit. Either way
+ * clear the BLOCKED bit. We want to discover these anew during each
+ * operation.
*/
if (!(statePtr->flags & CHANNEL_STICKY_EOF)) {
- statePtr->flags &= ~CHANNEL_EOF;
+ ResetFlag(statePtr, CHANNEL_EOF);
}
- statePtr->flags &= ~(CHANNEL_BLOCKED | CHANNEL_NEED_MORE_DATA);
-
+ ResetFlag(statePtr, CHANNEL_BLOCKED | CHANNEL_NEED_MORE_DATA);
+
for (copied = 0; copied < toRead; copied += copiedNow) {
- copiedNow = CopyAndTranslateBuffer(statePtr, bufPtr + copied,
- toRead - copied);
- if (copiedNow == 0) {
- if (statePtr->flags & CHANNEL_EOF) {
+ copiedNow = CopyAndTranslateBuffer(statePtr, bufPtr + copied,
+ toRead - copied);
+ if (copiedNow == 0) {
+ if (statePtr->flags & CHANNEL_EOF) {
goto done;
- }
- if (statePtr->flags & CHANNEL_BLOCKED) {
- if (statePtr->flags & CHANNEL_NONBLOCKING) {
+ }
+ if (statePtr->flags & CHANNEL_BLOCKED) {
+ if (statePtr->flags & CHANNEL_NONBLOCKING) {
goto done;
- }
- statePtr->flags &= (~(CHANNEL_BLOCKED));
- }
- result = GetInput(chanPtr);
- if (result != 0) {
- if (result != EAGAIN) {
- copied = -1;
- }
+ }
+ ResetFlag(statePtr, CHANNEL_BLOCKED);
+ }
+ result = GetInput(chanPtr);
+ if (result != 0) {
+ if (result != EAGAIN) {
+ copied = -1;
+ }
goto done;
- }
- }
+ }
+ }
}
- statePtr->flags &= (~(CHANNEL_BLOCKED));
+ ResetFlag(statePtr, CHANNEL_BLOCKED);
- done:
/*
- * Update the notifier state so we don't block while there is still
- * data in the buffers.
+ * Update the notifier state so we don't block while there is still data
+ * in the buffers.
*/
+ done:
UpdateInterest(chanPtr);
return copied;
}
@@ -8152,13 +9009,13 @@ DoRead(chanPtr, bufPtr, toRead)
*
* CopyAndTranslateBuffer --
*
- * Copy at most one buffer of input to the result space, doing
- * eol translations according to mode in effect currently.
+ * Copy at most one buffer of input to the result space, doing eol
+ * translations according to mode in effect currently.
*
* Results:
- * Number of bytes stored in the result buffer (as opposed to the
- * number of bytes read from the channel). May return
- * zero if no input is available to be translated.
+ * Number of bytes stored in the result buffer (as opposed to the number
+ * of bytes read from the channel). May return zero if no input is
+ * available to be translated.
*
* Side effects:
* Consumes buffered input. May deallocate one buffer.
@@ -8167,220 +9024,208 @@ DoRead(chanPtr, bufPtr, toRead)
*/
static int
-CopyAndTranslateBuffer(statePtr, result, space)
- ChannelState *statePtr; /* Channel state from which to read input. */
- char *result; /* Where to store the copied input. */
- int space; /* How many bytes are available in result
- * to store the copied input? */
+CopyAndTranslateBuffer(
+ ChannelState *statePtr, /* Channel state from which to read input. */
+ char *result, /* Where to store the copied input. */
+ int space) /* How many bytes are available in result to
+ * store the copied input? */
{
ChannelBuffer *bufPtr; /* The buffer from which to copy bytes. */
- int bytesInBuffer; /* How many bytes are available to be
- * copied in the current input buffer? */
+ int bytesInBuffer; /* How many bytes are available to be copied
+ * in the current input buffer? */
int copied; /* How many characters were already copied
- * into the destination space? */
- int i; /* Iterates over the copied input looking
- * for the input eofChar. */
-
+ * into the destination space? */
+ int i; /* Iterates over the copied input looking for
+ * the input eofChar. */
+
/*
* If there is no input at all, return zero. The invariant is that either
- * there is no buffer in the queue, or if the first buffer is empty, it
- * is also the last buffer (and thus there is no input in the queue).
- * Note also that if the buffer is empty, we leave it in the queue.
+ * there is no buffer in the queue, or if the first buffer is empty, it is
+ * also the last buffer (and thus there is no input in the queue). Note
+ * also that if the buffer is empty, we leave it in the queue.
*/
-
- if (statePtr->inQueueHead == (ChannelBuffer *) NULL) {
- return 0;
+
+ if (statePtr->inQueueHead == NULL) {
+ return 0;
}
bufPtr = statePtr->inQueueHead;
- bytesInBuffer = bufPtr->nextAdded - bufPtr->nextRemoved;
+ bytesInBuffer = BytesLeft(bufPtr);
copied = 0;
switch (statePtr->inputTranslation) {
- case TCL_TRANSLATE_LF: {
- if (bytesInBuffer == 0) {
- return 0;
- }
+ case TCL_TRANSLATE_LF:
+ if (bytesInBuffer == 0) {
+ return 0;
+ }
- /*
- * Copy the current chunk into the result buffer.
- */
-
- if (bytesInBuffer < space) {
- space = bytesInBuffer;
- }
- memcpy((VOID *) result,
- (VOID *) (bufPtr->buf + bufPtr->nextRemoved),
- (size_t) space);
- bufPtr->nextRemoved += space;
- copied = space;
- break;
- }
- case TCL_TRANSLATE_CR: {
- char *end;
-
- if (bytesInBuffer == 0) {
- return 0;
- }
+ /*
+ * Copy the current chunk into the result buffer.
+ */
- /*
- * Copy the current chunk into the result buffer, then
- * replace all \r with \n.
- */
-
- if (bytesInBuffer < space) {
- space = bytesInBuffer;
- }
- memcpy((VOID *) result,
- (VOID *) (bufPtr->buf + bufPtr->nextRemoved),
- (size_t) space);
- bufPtr->nextRemoved += space;
- copied = space;
-
- for (end = result + copied; result < end; result++) {
- if (*result == '\r') {
- *result = '\n';
- }
- }
- break;
- }
- case TCL_TRANSLATE_CRLF: {
- char *src, *end, *dst;
- int curByte;
-
- /*
- * If there is a held-back "\r" at EOF, produce it now.
- */
-
- if (bytesInBuffer == 0) {
- if ((statePtr->flags & (INPUT_SAW_CR | CHANNEL_EOF)) ==
- (INPUT_SAW_CR | CHANNEL_EOF)) {
- result[0] = '\r';
- statePtr->flags &= ~INPUT_SAW_CR;
- return 1;
- }
- return 0;
- }
-
- /*
- * Copy the current chunk and replace "\r\n" with "\n"
- * (but not standalone "\r"!).
- */
-
- if (bytesInBuffer < space) {
- space = bytesInBuffer;
- }
- memcpy((VOID *) result,
- (VOID *) (bufPtr->buf + bufPtr->nextRemoved),
- (size_t) space);
- bufPtr->nextRemoved += space;
- copied = space;
-
- end = result + copied;
- dst = result;
- for (src = result; src < end; src++) {
- curByte = *src;
- if (curByte == '\n') {
- statePtr->flags &= ~INPUT_SAW_CR;
- } else if (statePtr->flags & INPUT_SAW_CR) {
- statePtr->flags &= ~INPUT_SAW_CR;
- *dst = '\r';
- dst++;
- }
- if (curByte == '\r') {
- statePtr->flags |= INPUT_SAW_CR;
- } else {
- *dst = (char) curByte;
- dst++;
- }
+ if (bytesInBuffer < space) {
+ space = bytesInBuffer;
+ }
+ memcpy(result, RemovePoint(bufPtr), (size_t) space);
+ bufPtr->nextRemoved += space;
+ copied = space;
+ break;
+ case TCL_TRANSLATE_CR: {
+ char *end;
+
+ if (bytesInBuffer == 0) {
+ return 0;
+ }
+
+ /*
+ * Copy the current chunk into the result buffer, then replace all \r
+ * with \n.
+ */
+
+ if (bytesInBuffer < space) {
+ space = bytesInBuffer;
+ }
+ memcpy(result, RemovePoint(bufPtr), (size_t) space);
+ bufPtr->nextRemoved += space;
+ copied = space;
+
+ for (end = result + copied; result < end; result++) {
+ if (*result == '\r') {
+ *result = '\n';
}
- copied = dst - result;
- break;
}
- case TCL_TRANSLATE_AUTO: {
- char *src, *end, *dst;
- int curByte;
-
- if (bytesInBuffer == 0) {
- return 0;
- }
-
- /*
- * Loop over the current buffer, converting "\r" and "\r\n"
- * to "\n".
- */
-
- if (bytesInBuffer < space) {
- space = bytesInBuffer;
- }
- memcpy((VOID *) result,
- (VOID *) (bufPtr->buf + bufPtr->nextRemoved),
- (size_t) space);
- bufPtr->nextRemoved += space;
- copied = space;
-
- end = result + copied;
- dst = result;
- for (src = result; src < end; src++) {
- curByte = *src;
- if (curByte == '\r') {
- statePtr->flags |= INPUT_SAW_CR;
- *dst = '\n';
+ break;
+ }
+ case TCL_TRANSLATE_CRLF: {
+ char *src, *end, *dst;
+ int curByte;
+
+ /*
+ * If there is a held-back "\r" at EOF, produce it now.
+ */
+
+ if (bytesInBuffer == 0) {
+ if ((statePtr->flags & (INPUT_SAW_CR | CHANNEL_EOF)) ==
+ (INPUT_SAW_CR | CHANNEL_EOF)) {
+ result[0] = '\r';
+ ResetFlag(statePtr, INPUT_SAW_CR);
+ return 1;
+ }
+ return 0;
+ }
+
+ /*
+ * Copy the current chunk and replace "\r\n" with "\n" (but not
+ * standalone "\r"!).
+ */
+
+ if (bytesInBuffer < space) {
+ space = bytesInBuffer;
+ }
+ memcpy(result, RemovePoint(bufPtr), (size_t) space);
+ bufPtr->nextRemoved += space;
+ copied = space;
+
+ end = result + copied;
+ dst = result;
+ for (src = result; src < end; src++) {
+ curByte = *src;
+ if (curByte == '\n') {
+ ResetFlag(statePtr, INPUT_SAW_CR);
+ } else if (statePtr->flags & INPUT_SAW_CR) {
+ ResetFlag(statePtr, INPUT_SAW_CR);
+ *dst = '\r';
+ dst++;
+ }
+ if (curByte == '\r') {
+ SetFlag(statePtr, INPUT_SAW_CR);
+ } else {
+ *dst = (char) curByte;
+ dst++;
+ }
+ }
+ copied = dst - result;
+ break;
+ }
+ case TCL_TRANSLATE_AUTO: {
+ char *src, *end, *dst;
+ int curByte;
+
+ if (bytesInBuffer == 0) {
+ return 0;
+ }
+
+ /*
+ * Loop over the current buffer, converting "\r" and "\r\n" to "\n".
+ */
+
+ if (bytesInBuffer < space) {
+ space = bytesInBuffer;
+ }
+ memcpy(result, RemovePoint(bufPtr), (size_t) space);
+ bufPtr->nextRemoved += space;
+ copied = space;
+
+ end = result + copied;
+ dst = result;
+ for (src = result; src < end; src++) {
+ curByte = *src;
+ if (curByte == '\r') {
+ SetFlag(statePtr, INPUT_SAW_CR);
+ *dst = '\n';
+ dst++;
+ } else {
+ if ((curByte != '\n') || !(statePtr->flags & INPUT_SAW_CR)) {
+ *dst = (char) curByte;
dst++;
- } else {
- if ((curByte != '\n') ||
- !(statePtr->flags & INPUT_SAW_CR)) {
- *dst = (char) curByte;
- dst++;
- }
- statePtr->flags &= ~INPUT_SAW_CR;
}
+ ResetFlag(statePtr, INPUT_SAW_CR);
}
- copied = dst - result;
- break;
- }
- default: {
- panic("unknown eol translation mode");
}
+ copied = dst - result;
+ break;
+ }
+ default:
+ Tcl_Panic("unknown eol translation mode");
}
/*
- * If an in-stream EOF character is set for this channel, check that
- * the input we copied so far does not contain the EOF char. If it does,
- * copy only up to and excluding that character.
+ * If an in-stream EOF character is set for this channel, check that the
+ * input we copied so far does not contain the EOF char. If it does, copy
+ * only up to and excluding that character.
*/
-
+
if (statePtr->inEofChar != 0) {
- for (i = 0; i < copied; i++) {
- if (result[i] == (char) statePtr->inEofChar) {
+ for (i = 0; i < copied; i++) {
+ if (result[i] == (char) statePtr->inEofChar) {
/*
- * Set sticky EOF so that no further input is presented
- * to the caller.
+ * Set sticky EOF so that no further input is presented to the
+ * caller.
*/
-
- statePtr->flags |= (CHANNEL_EOF | CHANNEL_STICKY_EOF);
+
+ SetFlag(statePtr, CHANNEL_EOF | CHANNEL_STICKY_EOF);
statePtr->inputEncodingFlags |= TCL_ENCODING_END;
copied = i;
- break;
- }
- }
+ break;
+ }
+ }
}
/*
* If the current buffer is empty recycle it.
*/
- if (bufPtr->nextRemoved == bufPtr->nextAdded) {
- statePtr->inQueueHead = bufPtr->nextPtr;
- if (statePtr->inQueueHead == (ChannelBuffer *) NULL) {
- statePtr->inQueueTail = (ChannelBuffer *) NULL;
- }
- RecycleBuffer(statePtr, bufPtr, 0);
+ if (IsBufferEmpty(bufPtr)) {
+ statePtr->inQueueHead = bufPtr->nextPtr;
+ if (statePtr->inQueueHead == NULL) {
+ statePtr->inQueueTail = NULL;
+ }
+ RecycleBuffer(statePtr, bufPtr, 0);
}
/*
- * Return the number of characters copied into the result buffer.
- * This may be different from the number of bytes consumed, because
- * of EOL translations.
+ * Return the number of characters copied into the result buffer. This may
+ * be different from the number of bytes consumed, because of EOL
+ * translations.
*/
return copied;
@@ -8394,8 +9239,8 @@ CopyAndTranslateBuffer(statePtr, result, space)
* Copy at most one buffer of input to the result space.
*
* Results:
- * Number of bytes stored in the result buffer. May return
- * zero if no input is available.
+ * Number of bytes stored in the result buffer. May return zero if no
+ * input is available.
*
* Side effects:
* Consumes buffered input. May deallocate one buffer.
@@ -8404,39 +9249,39 @@ CopyAndTranslateBuffer(statePtr, result, space)
*/
static int
-CopyBuffer(chanPtr, result, space)
- Channel *chanPtr; /* Channel from which to read input. */
- char *result; /* Where to store the copied input. */
- int space; /* How many bytes are available in result
- * to store the copied input? */
+CopyBuffer(
+ Channel *chanPtr, /* Channel from which to read input. */
+ char *result, /* Where to store the copied input. */
+ int space) /* How many bytes are available in result to
+ * store the copied input? */
{
ChannelBuffer *bufPtr; /* The buffer from which to copy bytes. */
- int bytesInBuffer; /* How many bytes are available to be
- * copied in the current input buffer? */
+ int bytesInBuffer; /* How many bytes are available to be copied
+ * in the current input buffer? */
int copied; /* How many characters were already copied
- * into the destination space? */
-
+ * into the destination space? */
+
/*
- * If there is no input at all, return zero. The invariant is that
- * either there is no buffer in the queue, or if the first buffer
- * is empty, it is also the last buffer (and thus there is no
- * input in the queue). Note also that if the buffer is empty, we
- * don't leave it in the queue, but recycle it.
+ * If there is no input at all, return zero. The invariant is that either
+ * there is no buffer in the queue, or if the first buffer is empty, it is
+ * also the last buffer (and thus there is no input in the queue). Note
+ * also that if the buffer is empty, we don't leave it in the queue, but
+ * recycle it.
*/
-
- if (chanPtr->inQueueHead == (ChannelBuffer *) NULL) {
- return 0;
+
+ if (chanPtr->inQueueHead == NULL) {
+ return 0;
}
bufPtr = chanPtr->inQueueHead;
- bytesInBuffer = bufPtr->nextAdded - bufPtr->nextRemoved;
+ bytesInBuffer = BytesLeft(bufPtr);
copied = 0;
if (bytesInBuffer == 0) {
- RecycleBuffer(chanPtr->state, bufPtr, 0);
- chanPtr->inQueueHead = (ChannelBuffer*) NULL;
- chanPtr->inQueueTail = (ChannelBuffer*) NULL;
- return 0;
+ RecycleBuffer(chanPtr->state, bufPtr, 0);
+ chanPtr->inQueueHead = NULL;
+ chanPtr->inQueueTail = NULL;
+ return 0;
}
/*
@@ -8444,31 +9289,29 @@ CopyBuffer(chanPtr, result, space)
*/
if (bytesInBuffer < space) {
- space = bytesInBuffer;
+ space = bytesInBuffer;
}
- memcpy((VOID *) result,
- (VOID *) (bufPtr->buf + bufPtr->nextRemoved),
- (size_t) space);
+ memcpy(result, RemovePoint(bufPtr), (size_t) space);
bufPtr->nextRemoved += space;
copied = space;
/*
- * We don't care about in-stream EOF characters here as the data
- * read here may still flow through one or more transformations,
- * i.e. is not in its final state yet.
+ * We don't care about in-stream EOF characters here as the data read here
+ * may still flow through one or more transformations, i.e. is not in its
+ * final state yet.
*/
/*
* If the current buffer is empty recycle it.
*/
- if (bufPtr->nextRemoved == bufPtr->nextAdded) {
- chanPtr->inQueueHead = bufPtr->nextPtr;
- if (chanPtr->inQueueHead == (ChannelBuffer *) NULL) {
- chanPtr->inQueueTail = (ChannelBuffer *) NULL;
- }
- RecycleBuffer(chanPtr->state, bufPtr, 0);
+ if (IsBufferEmpty(bufPtr)) {
+ chanPtr->inQueueHead = bufPtr->nextPtr;
+ if (chanPtr->inQueueHead == NULL) {
+ chanPtr->inQueueTail = NULL;
+ }
+ RecycleBuffer(chanPtr->state, bufPtr, 0);
}
/*
@@ -8500,29 +9343,28 @@ CopyBuffer(chanPtr, result, space)
*/
static int
-DoWrite(chanPtr, src, srcLen)
- Channel *chanPtr; /* The channel to buffer output for. */
- CONST char *src; /* Data to write. */
- int srcLen; /* Number of bytes to write. */
-{
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
- ChannelBuffer *outBufPtr; /* Current output buffer. */
- int foundNewline; /* Did we find a newline in output? */
+DoWrite(
+ Channel *chanPtr, /* The channel to buffer output for. */
+ const char *src, /* Data to write. */
+ int srcLen) /* Number of bytes to write. */
+{
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
+ ChannelBuffer *outBufPtr; /* Current output buffer. */
+ int foundNewline; /* Did we find a newline in output? */
char *dPtr;
- CONST char *sPtr; /* Search variables for newline. */
- int crsent; /* In CRLF eol translation mode,
- * remember the fact that a CR was
- * output to the channel without
- * its following NL. */
- int i; /* Loop index for newline search. */
- int destCopied; /* How many bytes were used in this
- * destination buffer to hold the
- * output? */
- int totalDestCopied; /* How many bytes total were
- * copied to the channel buffer? */
- int srcCopied; /* How many bytes were copied from
- * the source string? */
- char *destPtr; /* Where in line to copy to? */
+ const char *sPtr; /* Search variables for newline. */
+ int crsent; /* In CRLF eol translation mode, remember the
+ * fact that a CR was output to the channel
+ * without its following NL. */
+ int i; /* Loop index for newline search. */
+ int destCopied; /* How many bytes were used in this
+ * destination buffer to hold the output? */
+ int totalDestCopied; /* How many bytes total were copied to the
+ * channel buffer? */
+ int srcCopied; /* How many bytes were copied from the source
+ * string? */
+ char *destPtr; /* Where in line to copy to? */
/*
* If we are in network (or windows) translation mode, record the fact
@@ -8530,7 +9372,7 @@ DoWrite(chanPtr, src, srcLen)
*/
crsent = 0;
-
+
/*
* Loop filling buffers and flushing them until all output has been
* consumed.
@@ -8540,97 +9382,96 @@ DoWrite(chanPtr, src, srcLen)
totalDestCopied = 0;
while (srcLen > 0) {
-
- /*
- * Make sure there is a current output buffer to accept output.
- */
-
- if (statePtr->curOutPtr == (ChannelBuffer *) NULL) {
- statePtr->curOutPtr = AllocChannelBuffer(statePtr->bufSize);
- }
-
- outBufPtr = statePtr->curOutPtr;
-
- destCopied = outBufPtr->bufLength - outBufPtr->nextAdded;
- if (destCopied > srcLen) {
- destCopied = srcLen;
- }
-
- destPtr = outBufPtr->buf + outBufPtr->nextAdded;
- switch (statePtr->outputTranslation) {
- case TCL_TRANSLATE_LF:
- srcCopied = destCopied;
- memcpy((VOID *) destPtr, (VOID *) src, (size_t) destCopied);
- break;
- case TCL_TRANSLATE_CR:
- srcCopied = destCopied;
- memcpy((VOID *) destPtr, (VOID *) src, (size_t) destCopied);
- for (dPtr = destPtr; dPtr < destPtr + destCopied; dPtr++) {
- if (*dPtr == '\n') {
- *dPtr = '\r';
- }
- }
- break;
- case TCL_TRANSLATE_CRLF:
- for (srcCopied = 0, dPtr = destPtr, sPtr = src;
- dPtr < destPtr + destCopied;
- dPtr++, sPtr++, srcCopied++) {
- if (*sPtr == '\n') {
- if (crsent) {
- *dPtr = '\n';
- crsent = 0;
- } else {
- *dPtr = '\r';
- crsent = 1;
- sPtr--, srcCopied--;
- }
- } else {
- *dPtr = *sPtr;
- }
- }
- break;
- case TCL_TRANSLATE_AUTO:
- panic("Tcl_Write: AUTO output translation mode not supported");
- default:
- panic("Tcl_Write: unknown output translation mode");
- }
-
- /*
- * The current buffer is ready for output if it is full, or if it
- * contains a newline and this channel is line-buffered, or if it
- * contains any output and this channel is unbuffered.
- */
-
- outBufPtr->nextAdded += destCopied;
- if (!(statePtr->flags & BUFFER_READY)) {
- if (outBufPtr->nextAdded == outBufPtr->bufLength) {
- statePtr->flags |= BUFFER_READY;
- } else if (statePtr->flags & CHANNEL_LINEBUFFERED) {
- for (sPtr = src, i = 0, foundNewline = 0;
- (i < srcCopied) && (!foundNewline);
- i++, sPtr++) {
- if (*sPtr == '\n') {
- foundNewline = 1;
- break;
- }
- }
- if (foundNewline) {
- statePtr->flags |= BUFFER_READY;
- }
- } else if (statePtr->flags & CHANNEL_UNBUFFERED) {
- statePtr->flags |= BUFFER_READY;
- }
- }
-
- totalDestCopied += srcCopied;
- src += srcCopied;
- srcLen -= srcCopied;
-
- if (statePtr->flags & BUFFER_READY) {
- if (FlushChannel(NULL, chanPtr, 0) != 0) {
- return -1;
- }
- }
+ /*
+ * Make sure there is a current output buffer to accept output.
+ */
+
+ if (statePtr->curOutPtr == NULL) {
+ statePtr->curOutPtr = AllocChannelBuffer(statePtr->bufSize);
+ }
+
+ outBufPtr = statePtr->curOutPtr;
+
+ destCopied = SpaceLeft(outBufPtr);
+ if (destCopied > srcLen) {
+ destCopied = srcLen;
+ }
+
+ destPtr = InsertPoint(outBufPtr);
+ switch (statePtr->outputTranslation) {
+ case TCL_TRANSLATE_LF:
+ srcCopied = destCopied;
+ memcpy(destPtr, src, (size_t) destCopied);
+ break;
+ case TCL_TRANSLATE_CR:
+ srcCopied = destCopied;
+ memcpy(destPtr, src, (size_t) destCopied);
+ for (dPtr = destPtr; dPtr < destPtr + destCopied; dPtr++) {
+ if (*dPtr == '\n') {
+ *dPtr = '\r';
+ }
+ }
+ break;
+ case TCL_TRANSLATE_CRLF:
+ for (srcCopied = 0, dPtr = destPtr, sPtr = src;
+ dPtr < destPtr + destCopied;
+ dPtr++, sPtr++, srcCopied++) {
+ if (*sPtr == '\n') {
+ if (crsent) {
+ *dPtr = '\n';
+ crsent = 0;
+ } else {
+ *dPtr = '\r';
+ crsent = 1;
+ sPtr--, srcCopied--;
+ }
+ } else {
+ *dPtr = *sPtr;
+ }
+ }
+ break;
+ case TCL_TRANSLATE_AUTO:
+ Tcl_Panic("Tcl_Write: AUTO output translation mode not supported");
+ default:
+ Tcl_Panic("Tcl_Write: unknown output translation mode");
+ }
+
+ /*
+ * The current buffer is ready for output if it is full, or if it
+ * contains a newline and this channel is line-buffered, or if it
+ * contains any output and this channel is unbuffered.
+ */
+
+ outBufPtr->nextAdded += destCopied;
+ if (!(statePtr->flags & BUFFER_READY)) {
+ if (IsBufferFull(outBufPtr)) {
+ SetFlag(statePtr, BUFFER_READY);
+ } else if (statePtr->flags & CHANNEL_LINEBUFFERED) {
+ for (sPtr = src, i = 0, foundNewline = 0;
+ (i < srcCopied) && (!foundNewline);
+ i++, sPtr++) {
+ if (*sPtr == '\n') {
+ foundNewline = 1;
+ break;
+ }
+ }
+ if (foundNewline) {
+ SetFlag(statePtr, BUFFER_READY);
+ }
+ } else if (statePtr->flags & CHANNEL_UNBUFFERED) {
+ SetFlag(statePtr, BUFFER_READY);
+ }
+ }
+
+ totalDestCopied += srcCopied;
+ src += srcCopied;
+ srcLen -= srcCopied;
+
+ if (statePtr->flags & BUFFER_READY) {
+ if (FlushChannel(NULL, chanPtr, 0) != 0) {
+ return -1;
+ }
+ }
} /* Closes "while" */
return totalDestCopied;
@@ -8641,9 +9482,9 @@ DoWrite(chanPtr, src, srcLen)
*
* CopyEventProc --
*
- * This routine is invoked as a channel event handler for
- * the background copy operation. It is just a trivial wrapper
- * around the CopyData routine.
+ * This routine is invoked as a channel event handler for the background
+ * copy operation. It is just a trivial wrapper around the CopyData
+ * routine.
*
* Results:
* None.
@@ -8655,11 +9496,11 @@ DoWrite(chanPtr, src, srcLen)
*/
static void
-CopyEventProc(clientData, mask)
- ClientData clientData;
- int mask;
+CopyEventProc(
+ ClientData clientData,
+ int mask)
{
- (void) CopyData((CopyState *)clientData, mask);
+ (void) CopyData((CopyState *) clientData, mask);
}
/*
@@ -8673,15 +9514,15 @@ CopyEventProc(clientData, mask)
* None.
*
* Side effects:
- * Removes any pending channel handlers and restores the blocking
- * and buffering modes of the channels. The CopyState is freed.
+ * Removes any pending channel handlers and restores the blocking and
+ * buffering modes of the channels. The CopyState is freed.
*
*----------------------------------------------------------------------
*/
static void
-StopCopy(csPtr)
- CopyState *csPtr; /* State for bg copy to stop . */
+StopCopy(
+ CopyState *csPtr) /* State for bg copy to stop . */
{
ChannelState *inStatePtr, *outStatePtr;
int nonBlocking;
@@ -8690,8 +9531,8 @@ StopCopy(csPtr)
return;
}
- inStatePtr = csPtr->readPtr->state;
- outStatePtr = csPtr->writePtr->state;
+ inStatePtr = csPtr->readPtr->state;
+ outStatePtr = csPtr->writePtr->state;
/*
* Restore the old blocking mode and output buffering mode.
@@ -8711,20 +9552,20 @@ StopCopy(csPtr)
}
outStatePtr->flags &= ~(CHANNEL_LINEBUFFERED | CHANNEL_UNBUFFERED);
outStatePtr->flags |=
- csPtr->writeFlags & (CHANNEL_LINEBUFFERED | CHANNEL_UNBUFFERED);
+ csPtr->writeFlags & (CHANNEL_LINEBUFFERED | CHANNEL_UNBUFFERED);
if (csPtr->cmdPtr) {
- Tcl_DeleteChannelHandler((Tcl_Channel)csPtr->readPtr, CopyEventProc,
- (ClientData)csPtr);
+ Tcl_DeleteChannelHandler((Tcl_Channel) csPtr->readPtr, CopyEventProc,
+ csPtr);
if (csPtr->readPtr != csPtr->writePtr) {
- Tcl_DeleteChannelHandler((Tcl_Channel)csPtr->writePtr,
- CopyEventProc, (ClientData)csPtr);
+ Tcl_DeleteChannelHandler((Tcl_Channel) csPtr->writePtr,
+ CopyEventProc, csPtr);
}
- Tcl_DecrRefCount(csPtr->cmdPtr);
+ TclDecrRefCount(csPtr->cmdPtr);
}
- inStatePtr->csPtrR = NULL;
+ inStatePtr->csPtrR = NULL;
outStatePtr->csPtrW = NULL;
- ckfree((char*) csPtr);
+ ckfree((char *) csPtr);
}
/*
@@ -8732,23 +9573,23 @@ StopCopy(csPtr)
*
* StackSetBlockMode --
*
- * This function sets the blocking mode for a channel, iterating
- * through each channel in a stack and updates the state flags.
+ * This function sets the blocking mode for a channel, iterating through
+ * each channel in a stack and updates the state flags.
*
* Results:
* 0 if OK, result code from failed blockModeProc otherwise.
*
* Side effects:
- * Modifies the blocking mode of the channel and possibly generates
- * an error.
+ * Modifies the blocking mode of the channel and possibly generates an
+ * error.
*
*----------------------------------------------------------------------
*/
static int
-StackSetBlockMode(chanPtr, mode)
- Channel *chanPtr; /* Channel to modify. */
- int mode; /* One of TCL_MODE_BLOCKING or
+StackSetBlockMode(
+ Channel *chanPtr, /* Channel to modify. */
+ int mode) /* One of TCL_MODE_BLOCKING or
* TCL_MODE_NONBLOCKING. */
{
int result = 0;
@@ -8759,7 +9600,7 @@ StackSetBlockMode(chanPtr, mode)
*/
chanPtr = chanPtr->state->topChanPtr;
- while (chanPtr != (Channel *) NULL) {
+ while (chanPtr != NULL) {
blockModeProc = Tcl_ChannelBlockModeProc(chanPtr->typePtr);
if (blockModeProc != NULL) {
result = (*blockModeProc) (chanPtr->instanceData, mode);
@@ -8778,41 +9619,64 @@ StackSetBlockMode(chanPtr, mode)
*
* SetBlockMode --
*
- * This function sets the blocking mode for a channel and updates
- * the state flags.
+ * This function sets the blocking mode for a channel and updates the
+ * state flags.
*
* Results:
* A standard Tcl result.
*
* Side effects:
- * Modifies the blocking mode of the channel and possibly generates
- * an error.
+ * Modifies the blocking mode of the channel and possibly generates an
+ * error.
*
*----------------------------------------------------------------------
*/
static int
-SetBlockMode(interp, chanPtr, mode)
- Tcl_Interp *interp; /* Interp for error reporting. */
- Channel *chanPtr; /* Channel to modify. */
- int mode; /* One of TCL_MODE_BLOCKING or
+SetBlockMode(
+ Tcl_Interp *interp, /* Interp for error reporting. */
+ Channel *chanPtr, /* Channel to modify. */
+ int mode) /* One of TCL_MODE_BLOCKING or
* TCL_MODE_NONBLOCKING. */
{
- ChannelState *statePtr = chanPtr->state; /* state info for channel */
int result = 0;
+ ChannelState *statePtr = chanPtr->state;
+ /* State info for channel */
result = StackSetBlockMode(chanPtr, mode);
if (result != 0) {
- if (interp != (Tcl_Interp *) NULL) {
- Tcl_AppendResult(interp, "error setting blocking mode: ",
- Tcl_PosixError(interp), (char *) NULL);
+ if (interp != NULL) {
+ /*
+ * TIP #219.
+ * Move error messages put by the driver into the bypass area and
+ * put them into the regular interpreter result. Fall back to the
+ * regular message if nothing was found in the bypass.
+ *
+ * Note that we cannot have a message in the interpreter bypass
+ * area, StackSetBlockMode is restricted to the channel bypass.
+ * We still need the interp as the destination of the move.
+ */
+
+ if (!TclChanCaughtErrorBypass(interp, (Tcl_Channel) chanPtr)) {
+ Tcl_AppendResult(interp, "error setting blocking mode: ",
+ Tcl_PosixError(interp), NULL);
+ }
+ } else {
+ /*
+ * TIP #219.
+ * If we have no interpreter to put a bypass message into we have
+ * to clear it, to prevent its propagation and use in other places
+ * unrelated to the actual occurence of the problem.
+ */
+
+ Tcl_SetChannelError((Tcl_Channel) chanPtr, NULL);
}
return TCL_ERROR;
}
if (mode == TCL_MODE_BLOCKING) {
- statePtr->flags &= (~(CHANNEL_NONBLOCKING | BG_FLUSH_SCHEDULED));
+ ResetFlag(statePtr, CHANNEL_NONBLOCKING | BG_FLUSH_SCHEDULED);
} else {
- statePtr->flags |= CHANNEL_NONBLOCKING;
+ SetFlag(statePtr, CHANNEL_NONBLOCKING);
}
return TCL_OK;
}
@@ -8834,10 +9698,10 @@ SetBlockMode(interp, chanPtr, mode)
*/
int
-Tcl_GetChannelNames(interp)
- Tcl_Interp *interp; /* Interp for error reporting. */
+Tcl_GetChannelNames(
+ Tcl_Interp *interp) /* Interp for error reporting. */
{
- return Tcl_GetChannelNamesEx(interp, (char *) NULL);
+ return Tcl_GetChannelNamesEx(interp, NULL);
}
/*
@@ -8845,9 +9709,9 @@ Tcl_GetChannelNames(interp)
*
* Tcl_GetChannelNamesEx --
*
- * Return the names of open channels in the interp filtered
- * filtered through a pattern. If pattern is NULL, it returns
- * all the open channels.
+ * Return the names of open channels in the interp filtered filtered
+ * through a pattern. If pattern is NULL, it returns all the open
+ * channels.
*
* Results:
* TCL_OK or TCL_ERROR.
@@ -8859,35 +9723,44 @@ Tcl_GetChannelNames(interp)
*/
int
-Tcl_GetChannelNamesEx(interp, pattern)
- Tcl_Interp *interp; /* Interp for error reporting. */
- CONST char *pattern; /* pattern to filter on. */
+Tcl_GetChannelNamesEx(
+ Tcl_Interp *interp, /* Interp for error reporting. */
+ const char *pattern) /* Pattern to filter on. */
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
ChannelState *statePtr;
- CONST char *name; /* name for channel */
- Tcl_Obj *resultPtr; /* pointer to result object */
+ const char *name; /* Name for channel */
+ Tcl_Obj *resultPtr; /* Pointer to result object */
Tcl_HashTable *hTblPtr; /* Hash table of channels. */
Tcl_HashEntry *hPtr; /* Search variable. */
Tcl_HashSearch hSearch; /* Search variable. */
- if (interp == (Tcl_Interp *) NULL) {
+ if (interp == NULL) {
return TCL_OK;
}
/*
- * Get the channel table that stores the channels registered
- * for this interpreter.
+ * Get the channel table that stores the channels registered for this
+ * interpreter.
*/
- hTblPtr = GetChannelTable(interp);
- resultPtr = Tcl_GetObjResult(interp);
- for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
- hPtr != (Tcl_HashEntry *) NULL;
- hPtr = Tcl_NextHashEntry(&hSearch)) {
+ hTblPtr = GetChannelTable(interp);
+ TclNewObj(resultPtr);
+ if ((pattern != NULL) && TclMatchIsTrivial(pattern)
+ && !((pattern[0] == 's') && (pattern[1] == 't')
+ && (pattern[2] == 'd'))) {
+ if ((Tcl_FindHashEntry(hTblPtr, pattern) != NULL)
+ && (Tcl_ListObjAppendElement(interp, resultPtr,
+ Tcl_NewStringObj(pattern, -1)) != TCL_OK)) {
+ goto error;
+ }
+ goto done;
+ }
+ for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch); hPtr != NULL;
+ hPtr = Tcl_NextHashEntry(&hSearch)) {
statePtr = ((Channel *) Tcl_GetHashValue(hPtr))->state;
- if (statePtr->topChanPtr == (Channel *) tsdPtr->stdinChannel) {
+ if (statePtr->topChanPtr == (Channel *) tsdPtr->stdinChannel) {
name = "stdin";
} else if (statePtr->topChanPtr == (Channel *) tsdPtr->stdoutChannel) {
name = "stdout";
@@ -8895,18 +9768,24 @@ Tcl_GetChannelNamesEx(interp, pattern)
name = "stderr";
} else {
/*
- * This is also stored in Tcl_GetHashKey(hTblPtr, hPtr),
- * but it's simpler to just grab the name from the statePtr.
+ * This is also stored in Tcl_GetHashKey(hTblPtr, hPtr), but it's
+ * simpler to just grab the name from the statePtr.
*/
+
name = statePtr->channelName;
}
if (((pattern == NULL) || Tcl_StringMatch(name, pattern)) &&
(Tcl_ListObjAppendElement(interp, resultPtr,
Tcl_NewStringObj(name, -1)) != TCL_OK)) {
+ error:
+ TclDecrRefCount(resultPtr);
return TCL_ERROR;
}
}
+
+ done:
+ Tcl_SetObjResult(interp, resultPtr);
return TCL_OK;
}
@@ -8915,8 +9794,8 @@ Tcl_GetChannelNamesEx(interp, pattern)
*
* Tcl_IsChannelRegistered --
*
- * Checks whether the channel is associated with the interp.
- * See also Tcl_RegisterChannel and Tcl_UnregisterChannel.
+ * Checks whether the channel is associated with the interp. See also
+ * Tcl_RegisterChannel and Tcl_UnregisterChannel.
*
* Results:
* 0 if the channel is not registered in the interpreter, 1 else.
@@ -8928,32 +9807,33 @@ Tcl_GetChannelNamesEx(interp, pattern)
*/
int
-Tcl_IsChannelRegistered (interp, chan)
- Tcl_Interp* interp; /* The interp to query of the channel */
- Tcl_Channel chan; /* The channel to check */
+Tcl_IsChannelRegistered(
+ Tcl_Interp *interp, /* The interp to query of the channel */
+ Tcl_Channel chan) /* The channel to check */
{
- Tcl_HashTable *hTblPtr; /* Hash table of channels. */
- Tcl_HashEntry *hPtr; /* Search variable. */
- Channel *chanPtr; /* The real IO channel. */
- ChannelState *statePtr; /* State of the real channel. */
+ Tcl_HashTable *hTblPtr; /* Hash table of channels. */
+ Tcl_HashEntry *hPtr; /* Search variable. */
+ Channel *chanPtr; /* The real IO channel. */
+ ChannelState *statePtr; /* State of the real channel. */
/*
- * Always check bottom-most channel in the stack. This is the one
- * that gets registered.
+ * Always check bottom-most channel in the stack. This is the one that
+ * gets registered.
*/
+
chanPtr = ((Channel *) chan)->state->bottomChanPtr;
statePtr = chanPtr->state;
- hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL);
- if (hTblPtr == (Tcl_HashTable *) NULL) {
- return 0;
+ hTblPtr = Tcl_GetAssocData(interp, "tclIO", NULL);
+ if (hTblPtr == NULL) {
+ return 0;
}
hPtr = Tcl_FindHashEntry(hTblPtr, statePtr->channelName);
- if (hPtr == (Tcl_HashEntry *) NULL) {
- return 0;
+ if (hPtr == NULL) {
+ return 0;
}
if ((Channel *) Tcl_GetHashValue(hPtr) != chanPtr) {
- return 0;
+ return 0;
}
return 1;
@@ -8976,11 +9856,11 @@ Tcl_IsChannelRegistered (interp, chan)
*/
int
-Tcl_IsChannelShared (chan)
- Tcl_Channel chan; /* The channel to query */
+Tcl_IsChannelShared(
+ Tcl_Channel chan) /* The channel to query */
{
ChannelState *statePtr = ((Channel *) chan)->state;
- /* State of real channel structure. */
+ /* State of real channel structure. */
return ((statePtr->refCount > 1) ? 1 : 0);
}
@@ -8991,8 +9871,8 @@ Tcl_IsChannelShared (chan)
* Tcl_IsChannelExisting --
*
* Checks whether a channel of the given name exists in the
- * (thread)-global list of all channels.
- * See Tcl_GetChannelNamesEx for function exposed at the Tcl level.
+ * (thread)-global list of all channels. See Tcl_GetChannelNamesEx for
+ * function exposed at the Tcl level.
*
* Results:
* A boolean value (0 = Does not exist, 1 = Does exist).
@@ -9004,19 +9884,18 @@ Tcl_IsChannelShared (chan)
*/
int
-Tcl_IsChannelExisting(chanName)
- CONST char* chanName; /* The name of the channel to look for. */
+Tcl_IsChannelExisting(
+ const char *chanName) /* The name of the channel to look for. */
{
ChannelState *statePtr;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- CONST char *name;
+ const char *name;
int chanNameLen;
chanNameLen = strlen(chanName);
- for (statePtr = tsdPtr->firstCSPtr;
- statePtr != NULL;
- statePtr = statePtr->nextCSPtr) {
- if (statePtr->topChanPtr == (Channel *) tsdPtr->stdinChannel) {
+ for (statePtr = tsdPtr->firstCSPtr; statePtr != NULL;
+ statePtr = statePtr->nextCSPtr) {
+ if (statePtr->topChanPtr == (Channel *) tsdPtr->stdinChannel) {
name = "stdin";
} else if (statePtr->topChanPtr == (Channel *) tsdPtr->stdoutChannel) {
name = "stdout";
@@ -9026,7 +9905,8 @@ Tcl_IsChannelExisting(chanName)
name = statePtr->channelName;
}
- /* Bug 2333466. Include \0 in the compare to prevent partial matching on prefixes.
+ /* Bug 2333466. Include \0 in the compare to prevent partial matching
+ * on prefixes.
*/
if ((*chanName == *name) &&
(memcmp(name, chanName, (size_t) chanNameLen+1) == 0)) {
@@ -9053,9 +9933,9 @@ Tcl_IsChannelExisting(chanName)
*----------------------------------------------------------------------
*/
-CONST char *
-Tcl_ChannelName(chanTypePtr)
- Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */
+const char *
+Tcl_ChannelName(
+ const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */
{
return chanTypePtr->typeName;
}
@@ -9077,8 +9957,9 @@ Tcl_ChannelName(chanTypePtr)
*/
Tcl_ChannelTypeVersion
-Tcl_ChannelVersion(chanTypePtr)
- Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */
+Tcl_ChannelVersion(
+ const Tcl_ChannelType *chanTypePtr)
+ /* Pointer to channel type. */
{
if (chanTypePtr->version == TCL_CHANNEL_VERSION_2) {
return TCL_CHANNEL_VERSION_2;
@@ -9086,11 +9967,14 @@ Tcl_ChannelVersion(chanTypePtr)
return TCL_CHANNEL_VERSION_3;
} else if (chanTypePtr->version == TCL_CHANNEL_VERSION_4) {
return TCL_CHANNEL_VERSION_4;
+ } else if (chanTypePtr->version == TCL_CHANNEL_VERSION_5) {
+ return TCL_CHANNEL_VERSION_5;
} else {
/*
- * In <v2 channel versions, the version field is occupied
- * by the Tcl_DriverBlockModeProc
+ * In <v2 channel versions, the version field is occupied by the
+ * Tcl_DriverBlockModeProc
*/
+
return TCL_CHANNEL_VERSION_1;
}
}
@@ -9113,13 +9997,13 @@ Tcl_ChannelVersion(chanTypePtr)
*/
static int
-HaveVersion(chanTypePtr, minimumVersion)
- Tcl_ChannelType *chanTypePtr;
- Tcl_ChannelTypeVersion minimumVersion;
+HaveVersion(
+ const Tcl_ChannelType *chanTypePtr,
+ Tcl_ChannelTypeVersion minimumVersion)
{
Tcl_ChannelTypeVersion actualVersion = Tcl_ChannelVersion(chanTypePtr);
- return ((int)actualVersion) >= ((int)minimumVersion);
+ return (PTR2INT(actualVersion)) >= (PTR2INT(minimumVersion));
}
/*
@@ -9138,8 +10022,9 @@ HaveVersion(chanTypePtr, minimumVersion)
*---------------------------------------------------------------------- */
Tcl_DriverBlockModeProc *
-Tcl_ChannelBlockModeProc(chanTypePtr)
- Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */
+Tcl_ChannelBlockModeProc(
+ const Tcl_ChannelType *chanTypePtr)
+ /* Pointer to channel type. */
{
if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_2)) {
return chanTypePtr->blockModeProc;
@@ -9147,6 +10032,7 @@ Tcl_ChannelBlockModeProc(chanTypePtr)
/*
* The v1 structure had the blockModeProc in a different place.
*/
+
return (Tcl_DriverBlockModeProc *) (chanTypePtr->version);
}
}
@@ -9168,8 +10054,9 @@ Tcl_ChannelBlockModeProc(chanTypePtr)
*/
Tcl_DriverCloseProc *
-Tcl_ChannelCloseProc(chanTypePtr)
- Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */
+Tcl_ChannelCloseProc(
+ const Tcl_ChannelType *chanTypePtr)
+ /* Pointer to channel type. */
{
return chanTypePtr->closeProc;
}
@@ -9191,8 +10078,9 @@ Tcl_ChannelCloseProc(chanTypePtr)
*/
Tcl_DriverClose2Proc *
-Tcl_ChannelClose2Proc(chanTypePtr)
- Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */
+Tcl_ChannelClose2Proc(
+ const Tcl_ChannelType *chanTypePtr)
+ /* Pointer to channel type. */
{
return chanTypePtr->close2Proc;
}
@@ -9214,8 +10102,9 @@ Tcl_ChannelClose2Proc(chanTypePtr)
*/
Tcl_DriverInputProc *
-Tcl_ChannelInputProc(chanTypePtr)
- Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */
+Tcl_ChannelInputProc(
+ const Tcl_ChannelType *chanTypePtr)
+ /* Pointer to channel type. */
{
return chanTypePtr->inputProc;
}
@@ -9237,8 +10126,9 @@ Tcl_ChannelInputProc(chanTypePtr)
*/
Tcl_DriverOutputProc *
-Tcl_ChannelOutputProc(chanTypePtr)
- Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */
+Tcl_ChannelOutputProc(
+ const Tcl_ChannelType *chanTypePtr)
+ /* Pointer to channel type. */
{
return chanTypePtr->outputProc;
}
@@ -9260,8 +10150,9 @@ Tcl_ChannelOutputProc(chanTypePtr)
*/
Tcl_DriverSeekProc *
-Tcl_ChannelSeekProc(chanTypePtr)
- Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */
+Tcl_ChannelSeekProc(
+ const Tcl_ChannelType *chanTypePtr)
+ /* Pointer to channel type. */
{
return chanTypePtr->seekProc;
}
@@ -9283,8 +10174,9 @@ Tcl_ChannelSeekProc(chanTypePtr)
*/
Tcl_DriverSetOptionProc *
-Tcl_ChannelSetOptionProc(chanTypePtr)
- Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */
+Tcl_ChannelSetOptionProc(
+ const Tcl_ChannelType *chanTypePtr)
+ /* Pointer to channel type. */
{
return chanTypePtr->setOptionProc;
}
@@ -9306,8 +10198,9 @@ Tcl_ChannelSetOptionProc(chanTypePtr)
*/
Tcl_DriverGetOptionProc *
-Tcl_ChannelGetOptionProc(chanTypePtr)
- Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */
+Tcl_ChannelGetOptionProc(
+ const Tcl_ChannelType *chanTypePtr)
+ /* Pointer to channel type. */
{
return chanTypePtr->getOptionProc;
}
@@ -9329,8 +10222,9 @@ Tcl_ChannelGetOptionProc(chanTypePtr)
*/
Tcl_DriverWatchProc *
-Tcl_ChannelWatchProc(chanTypePtr)
- Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */
+Tcl_ChannelWatchProc(
+ const Tcl_ChannelType *chanTypePtr)
+ /* Pointer to channel type. */
{
return chanTypePtr->watchProc;
}
@@ -9352,8 +10246,9 @@ Tcl_ChannelWatchProc(chanTypePtr)
*/
Tcl_DriverGetHandleProc *
-Tcl_ChannelGetHandleProc(chanTypePtr)
- Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */
+Tcl_ChannelGetHandleProc(
+ const Tcl_ChannelType *chanTypePtr)
+ /* Pointer to channel type. */
{
return chanTypePtr->getHandleProc;
}
@@ -9375,8 +10270,9 @@ Tcl_ChannelGetHandleProc(chanTypePtr)
*/
Tcl_DriverFlushProc *
-Tcl_ChannelFlushProc(chanTypePtr)
- Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */
+Tcl_ChannelFlushProc(
+ const Tcl_ChannelType *chanTypePtr)
+ /* Pointer to channel type. */
{
if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_2)) {
return chanTypePtr->flushProc;
@@ -9402,8 +10298,9 @@ Tcl_ChannelFlushProc(chanTypePtr)
*/
Tcl_DriverHandlerProc *
-Tcl_ChannelHandlerProc(chanTypePtr)
- Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */
+Tcl_ChannelHandlerProc(
+ const Tcl_ChannelType *chanTypePtr)
+ /* Pointer to channel type. */
{
if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_2)) {
return chanTypePtr->handlerProc;
@@ -9429,8 +10326,9 @@ Tcl_ChannelHandlerProc(chanTypePtr)
*/
Tcl_DriverWideSeekProc *
-Tcl_ChannelWideSeekProc(chanTypePtr)
- Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */
+Tcl_ChannelWideSeekProc(
+ const Tcl_ChannelType *chanTypePtr)
+ /* Pointer to channel type. */
{
if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_3)) {
return chanTypePtr->wideSeekProc;
@@ -9444,7 +10342,8 @@ Tcl_ChannelWideSeekProc(chanTypePtr)
*
* Tcl_ChannelThreadActionProc --
*
- * Return the Tcl_DriverThreadActionProc of the channel type.
+ * TIP #218, Channel Thread Actions. Return the
+ * Tcl_DriverThreadActionProc of the channel type.
*
* Results:
* A pointer to the proc.
@@ -9456,8 +10355,9 @@ Tcl_ChannelWideSeekProc(chanTypePtr)
*/
Tcl_DriverThreadActionProc *
-Tcl_ChannelThreadActionProc(chanTypePtr)
- Tcl_ChannelType *chanTypePtr; /* Pointer to channel type. */
+Tcl_ChannelThreadActionProc(
+ const Tcl_ChannelType *chanTypePtr)
+ /* Pointer to channel type. */
{
if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_4)) {
return chanTypePtr->threadActionProc;
@@ -9465,43 +10365,537 @@ Tcl_ChannelThreadActionProc(chanTypePtr)
return NULL;
}
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetChannelErrorInterp --
+ *
+ * TIP #219, Tcl Channel Reflection API.
+ * Store an error message for the I/O system.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Discards a previously stored message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetChannelErrorInterp(
+ Tcl_Interp *interp, /* Interp to store the data into. */
+ Tcl_Obj *msg) /* Error message to store. */
+{
+ Interp *iPtr = (Interp *) interp;
+
+ if (iPtr->chanMsg != NULL) {
+ TclDecrRefCount(iPtr->chanMsg);
+ iPtr->chanMsg = NULL;
+ }
+
+ if (msg != NULL) {
+ iPtr->chanMsg = FixLevelCode(msg);
+ Tcl_IncrRefCount(iPtr->chanMsg);
+ }
+ return;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetChannelError --
+ *
+ * TIP #219, Tcl Channel Reflection API.
+ * Store an error message for the I/O system.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Discards a previously stored message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetChannelError(
+ Tcl_Channel chan, /* Channel to store the data into. */
+ Tcl_Obj *msg) /* Error message to store. */
+{
+ ChannelState *statePtr = ((Channel *) chan)->state;
+
+ if (statePtr->chanMsg != NULL) {
+ TclDecrRefCount(statePtr->chanMsg);
+ statePtr->chanMsg = NULL;
+ }
+
+ if (msg != NULL) {
+ statePtr->chanMsg = FixLevelCode(msg);
+ Tcl_IncrRefCount(statePtr->chanMsg);
+ }
+ return;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FixLevelCode --
+ *
+ * TIP #219, Tcl Channel Reflection API.
+ * Scans an error message for bad -code / -level directives. Returns a
+ * modified copy with such directives corrected, and the input if it had
+ * no problems.
+ *
+ * Results:
+ * A Tcl_Obj*
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+FixLevelCode(
+ Tcl_Obj *msg)
+{
+ int explicitResult, numOptions, lc, lcn;
+ Tcl_Obj **lv, **lvn;
+ int res, i, j, val, lignore, cignore;
+ int newlevel = -1, newcode = -1;
+ /* ASSERT msg != NULL */
+
+ /*
+ * Process the caught message.
+ *
+ * Syntax = (option value)... ?message?
+ *
+ * Bad message syntax causes a panic, because the other side uses
+ * Tcl_GetReturnOptions and list construction functions to marshall the
+ * information. Hence an error means that we've got serious breakage.
+ */
+
+ res = Tcl_ListObjGetElements(NULL, msg, &lc, &lv);
+ if (res != TCL_OK) {
+ Tcl_Panic("Tcl_SetChannelError(Interp): Bad syntax of message");
+ }
+
+ explicitResult = (1 == (lc % 2));
+ numOptions = lc - explicitResult;
+
+ /*
+ * No options, nothing to do.
+ */
+
+ if (numOptions == 0) {
+ return msg;
+ }
+
+ /*
+ * Check for -code x, x != 1|error, and -level x, x != 0
+ */
+
+ for (i = 0; i < numOptions; i += 2) {
+ if (0 == strcmp(TclGetString(lv[i]), "-code")) {
+ /*
+ * !"error", !integer, integer != 1 (numeric code for error)
+ */
+
+ res = TclGetIntFromObj(NULL, lv[i+1], &val);
+ if (((res == TCL_OK) && (val != 1)) || ((res != TCL_OK) &&
+ (0 != strcmp(TclGetString(lv[i+1]), "error")))) {
+ newcode = 1;
+ }
+ } else if (0 == strcmp(TclGetString(lv[i]), "-level")) {
+ /*
+ * !integer, integer != 0
+ */
+
+ res = TclGetIntFromObj(NULL, lv [i+1], &val);
+ if ((res != TCL_OK) || (val != 0)) {
+ newlevel = 0;
+ }
+ }
+ }
+
+ /*
+ * -code, -level are either not present or ok. Nothing to do.
+ */
+
+ if ((newlevel < 0) && (newcode < 0)) {
+ return msg;
+ }
+
+ lcn = numOptions;
+ if (explicitResult) {
+ lcn ++;
+ }
+ if (newlevel >= 0) {
+ lcn += 2;
+ }
+ if (newcode >= 0) {
+ lcn += 2;
+ }
+
+ lvn = (Tcl_Obj **) ckalloc(lcn * sizeof(Tcl_Obj *));
+
+ /*
+ * New level/code information is spliced into the first occurence of
+ * -level, -code, further occurences are ignored. The options cannot be
+ * not present, we would not come here. Options which are ok are simply
+ * copied over.
+ */
+
+ lignore = cignore = 0;
+ for (i=0, j=0; i<numOptions; i+=2) {
+ if (0 == strcmp(TclGetString(lv[i]), "-level")) {
+ if (newlevel >= 0) {
+ lvn[j++] = lv[i];
+ lvn[j++] = Tcl_NewIntObj(newlevel);
+ newlevel = -1;
+ lignore = 1;
+ continue;
+ } else if (lignore) {
+ continue;
+ }
+ } else if (0 == strcmp(TclGetString(lv[i]), "-code")) {
+ if (newcode >= 0) {
+ lvn[j++] = lv[i];
+ lvn[j++] = Tcl_NewIntObj(newcode);
+ newcode = -1;
+ cignore = 1;
+ continue;
+ } else if (cignore) {
+ continue;
+ }
+ }
+
+ /*
+ * Keep everything else, possibly copied down.
+ */
+
+ lvn[j++] = lv[i];
+ lvn[j++] = lv[i+1];
+ }
+ if (newlevel >= 0) {
+ Tcl_Panic("Defined newlevel not used in rewrite");
+ }
+ if (newcode >= 0) {
+ Tcl_Panic("Defined newcode not used in rewrite");
+ }
+
+ if (explicitResult) {
+ lvn[j++] = lv[i];
+ }
+
+ msg = Tcl_NewListObj(j, lvn);
+
+ ckfree((char *) lvn);
+ return msg;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetChannelErrorInterp --
+ *
+ * TIP #219, Tcl Channel Reflection API.
+ * Return the message stored by the channel driver.
+ *
+ * Results:
+ * Tcl error message object.
+ *
+ * Side effects:
+ * Resets the stored data to NULL.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_GetChannelErrorInterp(
+ Tcl_Interp *interp, /* Interp to query. */
+ Tcl_Obj **msg) /* Place for error message. */
+{
+ Interp *iPtr = (Interp *) interp;
+
+ *msg = iPtr->chanMsg;
+ iPtr->chanMsg = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetChannelError --
+ *
+ * TIP #219, Tcl Channel Reflection API.
+ * Return the message stored by the channel driver.
+ *
+ * Results:
+ * Tcl error message object.
+ *
+ * Side effects:
+ * Resets the stored data to NULL.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_GetChannelError(
+ Tcl_Channel chan, /* Channel to query. */
+ Tcl_Obj **msg) /* Place for error message. */
+{
+ ChannelState *statePtr = ((Channel *) chan)->state;
+
+ *msg = statePtr->chanMsg;
+ statePtr->chanMsg = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ChannelTruncateProc --
+ *
+ * TIP #208 (subsection relating to truncation, based on TIP #206).
+ * Return the Tcl_DriverTruncateProc of the channel type.
+ *
+ * Results:
+ * A pointer to the proc.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_DriverTruncateProc *
+Tcl_ChannelTruncateProc(
+ const Tcl_ChannelType *chanTypePtr)
+ /* Pointer to channel type. */
+{
+ if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_5)) {
+ return chanTypePtr->truncateProc;
+ } else {
+ return NULL;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupChannelIntRep --
+ *
+ * Initialize the internal representation of a new Tcl_Obj to a copy of
+ * the internal representation of an existing string object.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * copyPtr's internal rep is set to a copy of srcPtr's internal
+ * representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DupChannelIntRep(
+ register Tcl_Obj *srcPtr, /* Object with internal rep to copy. Must have
+ * an internal rep of type "Channel". */
+ register Tcl_Obj *copyPtr) /* Object with internal rep to set. Must not
+ * currently have an internal rep.*/
+{
+ ChannelState *statePtr = GET_CHANNELSTATE(srcPtr);
+ Interp *interpPtr = GET_CHANNELINTERP(srcPtr);
+
+ SET_CHANNELSTATE(copyPtr, statePtr);
+ SET_CHANNELINTERP(copyPtr, interpPtr);
+ Tcl_Preserve((ClientData) statePtr);
+ copyPtr->typePtr = &tclChannelType;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetChannelFromAny --
+ *
+ * Create an internal representation of type "Channel" for an object.
+ *
+ * Results:
+ * This operation always succeeds and returns TCL_OK.
+ *
+ * Side effects:
+ * Any old internal reputation for objPtr is freed and the internal
+ * representation is set to "Channel".
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetChannelFromAny(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ register Tcl_Obj *objPtr) /* The object to convert. */
+{
+ ChannelState *statePtr;
+ Interp *interpPtr;
+
+ if (interp == NULL) {
+ return TCL_ERROR;
+ }
+ if (objPtr->typePtr == &tclChannelType) {
+ /*
+ * The channel is valid until any call to DetachChannel occurs.
+ * Ensure consistency checks are done.
+ */
+ statePtr = GET_CHANNELSTATE(objPtr);
+ interpPtr = GET_CHANNELINTERP(objPtr);
+ if (statePtr->flags & (CHANNEL_TAINTED|CHANNEL_CLOSED)) {
+ ResetFlag(statePtr, CHANNEL_TAINTED);
+ Tcl_Release((ClientData) statePtr);
+ UpdateStringOfChannel(objPtr);
+ objPtr->typePtr = NULL;
+ } else if (interpPtr != (Interp*) interp) {
+ Tcl_Release((ClientData) statePtr);
+ UpdateStringOfChannel(objPtr);
+ objPtr->typePtr = NULL;
+ }
+ }
+ if (objPtr->typePtr != &tclChannelType) {
+ Tcl_Channel chan;
+
+ /*
+ * We need a valid string with which to check for a valid channel, but
+ * make sure not to free internal rep until validated. [Bug 1847044]
+ */
+ if ((objPtr->typePtr != NULL) && (objPtr->bytes == NULL)) {
+ objPtr->typePtr->updateStringProc(objPtr);
+ }
+
+ chan = Tcl_GetChannel(interp, objPtr->bytes, NULL);
+ if (chan == NULL) {
+ return TCL_ERROR;
+ }
+
+ TclFreeIntRep(objPtr);
+ statePtr = ((Channel *)chan)->state;
+ Tcl_Preserve((ClientData) statePtr);
+ SET_CHANNELSTATE(objPtr, statePtr);
+ SET_CHANNELINTERP(objPtr, interp);
+ objPtr->typePtr = &tclChannelType;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateStringOfChannel --
+ *
+ * Update the string representation for an object whose internal
+ * representation is "Channel".
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The object's string may be set by converting its Unicode represention
+ * to UTF format.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateStringOfChannel(
+ Tcl_Obj *objPtr) /* Object with string rep to update. */
+{
+ if (objPtr->bytes == NULL) {
+ ChannelState *statePtr = GET_CHANNELSTATE(objPtr);
+ const char *name = statePtr->channelName;
+ if (name) {
+ size_t len = strlen(name);
+ objPtr->bytes = (char *) ckalloc(len + 1);
+ objPtr->length = len;
+ memcpy(objPtr->bytes, name, len);
+ } else {
+ objPtr->bytes = tclEmptyStringRep;
+ objPtr->length = 0;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeChannelIntRep --
+ *
+ * Release statePtr storage.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May cause state to be freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeChannelIntRep(
+ Tcl_Obj *objPtr) /* Object with internal rep to free. */
+{
+ Tcl_Release((ClientData) GET_CHANNELSTATE(objPtr));
+}
+
#if 0
-/* For future debugging work, a simple function to print the flags of
- * a channel in semi-readable form.
+/*
+ * For future debugging work, a simple function to print the flags of a
+ * channel in semi-readable form.
*/
static int
-DumpFlags (str, flags)
- char* str;
- int flags;
-{
- char buf [20];
- int i = 0;
-
- if (flags & TCL_READABLE) {buf[i] = 'r';} else {buf [i]='_';}; i++;
- if (flags & TCL_WRITABLE) {buf[i] = 'w';} else {buf [i]='_';}; i++;
- if (flags & CHANNEL_NONBLOCKING) {buf[i] = 'n';} else {buf [i]='_';}; i++;
- if (flags & CHANNEL_LINEBUFFERED) {buf[i] = 'l';} else {buf [i]='_';}; i++;
- if (flags & CHANNEL_UNBUFFERED) {buf[i] = 'u';} else {buf [i]='_';}; i++;
- if (flags & BUFFER_READY) {buf[i] = 'R';} else {buf [i]='_';}; i++;
- if (flags & BG_FLUSH_SCHEDULED) {buf[i] = 'F';} else {buf [i]='_';}; i++;
- if (flags & CHANNEL_CLOSED) {buf[i] = 'c';} else {buf [i]='_';}; i++;
- if (flags & CHANNEL_EOF) {buf[i] = 'E';} else {buf [i]='_';}; i++;
- if (flags & CHANNEL_STICKY_EOF) {buf[i] = 'S';} else {buf [i]='_';}; i++;
- if (flags & CHANNEL_BLOCKED) {buf[i] = 'B';} else {buf [i]='_';}; i++;
- if (flags & INPUT_SAW_CR) {buf[i] = '/';} else {buf [i]='_';}; i++;
- if (flags & INPUT_NEED_NL) {buf[i] = '*';} else {buf [i]='_';}; i++;
- if (flags & CHANNEL_DEAD) {buf[i] = 'D';} else {buf [i]='_';}; i++;
- if (flags & CHANNEL_RAW_MODE) {buf[i] = 'R';} else {buf [i]='_';}; i++;
+DumpFlags(
+ char *str,
+ int flags)
+{
+ char buf[20];
+ int i = 0;
+
+#define ChanFlag(chr,bit) (buf[i++] = ((flags & (bit)) ? (chr) : '_'))
+
+ ChanFlag('r', TCL_READABLE);
+ ChanFlag('w', TCL_WRITABLE);
+ ChanFlag('n', CHANNEL_NONBLOCKING);
+ ChanFlag('l', CHANNEL_LINEBUFFERED);
+ ChanFlag('u', CHANNEL_UNBUFFERED);
+ ChanFlag('R', BUFFER_READY);
+ ChanFlag('F', BG_FLUSH_SCHEDULED);
+ ChanFlag('c', CHANNEL_CLOSED);
+ ChanFlag('E', CHANNEL_EOF);
+ ChanFlag('S', CHANNEL_STICKY_EOF);
+ ChanFlag('B', CHANNEL_BLOCKED);
+ ChanFlag('/', INPUT_SAW_CR);
+ ChanFlag('*', INPUT_NEED_NL);
+ ChanFlag('D', CHANNEL_DEAD);
+ ChanFlag('R', CHANNEL_RAW_MODE);
#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
- if (flags & CHANNEL_TIMER_FEV) {buf[i] = 'T';} else {buf [i]='_';}; i++;
- if (flags & CHANNEL_HAS_MORE_DATA) {buf[i] = 'H';} else {buf [i]='_';}; i++;
+ ChanFlag('T', CHANNEL_TIMER_FEV);
+ ChanFlag('H', CHANNEL_HAS_MORE_DATA);
#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */
- if (flags & CHANNEL_INCLOSE) {buf[i] = 'x';} else {buf [i]='_';}; i++;
- buf [i] ='\0';
+ ChanFlag('x', CHANNEL_INCLOSE);
+
+ buf[i] ='\0';
- fprintf (stderr,"%s: %s\n", str, buf); fflush(stderr);
- return 0;
+ fprintf(stderr, "%s: %s\n", str, buf);
+ return 0;
}
#endif
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclIO.h b/generic/tclIO.h
index e9f6151..8746a09 100644
--- a/generic/tclIO.h
+++ b/generic/tclIO.h
@@ -1,4 +1,4 @@
-/*
+/*
* tclIO.h --
*
* This file provides the generic portions (those that are the same on
@@ -7,16 +7,16 @@
* Copyright (c) 1998-2000 Ajuba Solutions
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
/*
* Make sure that both EAGAIN and EWOULDBLOCK are defined. This does not
- * compile on systems where neither is defined. We want both defined so
- * that we can test safely for both. In the code we still have to test for
- * both because there may be systems on which both are defined and have
- * different values.
+ * compile on systems where neither is defined. We want both defined so that
+ * we can test safely for both. In the code we still have to test for both
+ * because there may be systems on which both are defined and have different
+ * values.
*/
#if ((!defined(EWOULDBLOCK)) && (defined(EAGAIN)))
@@ -26,12 +26,12 @@
# define EAGAIN EWOULDBLOCK
#endif
#if ((!defined(EAGAIN)) && (!defined(EWOULDBLOCK)))
-error one of EWOULDBLOCK or EAGAIN must be defined
+#error one of EWOULDBLOCK or EAGAIN must be defined
#endif
/*
* The following structure encapsulates the state for a background channel
- * copy. Note that the data buffer for the copy will be appended to this
+ * copy. Note that the data buffer for the copy will be appended to this
* structure.
*/
@@ -41,7 +41,7 @@ typedef struct CopyState {
int readFlags; /* Original read channel flags. */
int writeFlags; /* Original write channel flags. */
int toRead; /* Number of bytes to copy, or -1. */
- int total; /* Total bytes transferred (written). */
+ Tcl_WideInt total; /* Total bytes transferred (written). */
Tcl_Interp *interp; /* Interp that started the copy. */
Tcl_Obj *cmdPtr; /* Command to be invoked at completion. */
int bufSize; /* Size of appended buffer. */
@@ -57,28 +57,28 @@ typedef struct CopyState {
typedef struct ChannelBuffer {
int nextAdded; /* The next position into which a character
- * will be put in the buffer. */
- int nextRemoved; /* Position of next byte to be removed
- * from the buffer. */
+ * will be put in the buffer. */
+ int nextRemoved; /* Position of next byte to be removed from
+ * the buffer. */
int bufLength; /* How big is the buffer? */
struct ChannelBuffer *nextPtr;
/* Next buffer in chain. */
char buf[4]; /* Placeholder for real buffer. The real
- * buffer occuppies this space + bufSize-4
- * bytes. This must be the last field in
- * the structure. */
+ * buffer occuppies this space + bufSize-4
+ * bytes. This must be the last field in the
+ * structure. */
} ChannelBuffer;
#define CHANNELBUFFER_HEADER_SIZE (sizeof(ChannelBuffer) - 4)
/*
* How much extra space to allocate in buffer to hold bytes from previous
- * buffer (when converting to UTF-8) or to hold bytes that will go to
- * next buffer (when converting from UTF-8).
+ * buffer (when converting to UTF-8) or to hold bytes that will go to next
+ * buffer (when converting from UTF-8).
*/
-
-#define BUFFER_PADDING 16
-
+
+#define BUFFER_PADDING 16
+
/*
* The following defines the *default* buffer size for channels.
*/
@@ -86,28 +86,29 @@ typedef struct ChannelBuffer {
#define CHANNELBUFFER_DEFAULT_SIZE (1024 * 4)
/*
- * Structure to record a close callback. One such record exists for
- * each close callback registered for a channel.
+ * Structure to record a close callback. One such record exists for each close
+ * callback registered for a channel.
*/
typedef struct CloseCallback {
- Tcl_CloseProc *proc; /* The procedure to call. */
- ClientData clientData; /* Arbitrary one-word data to pass
- * to the callback. */
- struct CloseCallback *nextPtr; /* For chaining close callbacks. */
+ Tcl_CloseProc *proc; /* The procedure to call. */
+ ClientData clientData; /* Arbitrary one-word data to pass to the
+ * callback. */
+ struct CloseCallback *nextPtr;
+ /* For chaining close callbacks. */
} CloseCallback;
/*
* The following structure describes the information saved from a call to
- * "fileevent". This is used later when the event being waited for to
- * invoke the saved script in the interpreter designed in this record.
+ * "fileevent". This is used later when the event being waited for to invoke
+ * the saved script in the interpreter designed in this record.
*/
typedef struct EventScriptRecord {
struct Channel *chanPtr; /* The channel for which this script is
- * registered. This is used only when an
- * error occurs during evaluation of the
- * script, to delete the handler. */
+ * registered. This is used only when an error
+ * occurs during evaluation of the script, to
+ * delete the handler. */
Tcl_Obj *scriptPtr; /* Script to invoke. */
Tcl_Interp *interp; /* In what interpreter to invoke script? */
int mask; /* Events must overlap current mask for the
@@ -119,29 +120,28 @@ typedef struct EventScriptRecord {
/*
* struct Channel:
*
- * One of these structures is allocated for each open channel. It contains data
- * specific to the channel but which belongs to the generic part of the Tcl
- * channel mechanism, and it points at an instance specific (and type
- * specific) * instance data, and at a channel type structure.
+ * One of these structures is allocated for each open channel. It contains
+ * data specific to the channel but which belongs to the generic part of the
+ * Tcl channel mechanism, and it points at an instance specific (and type
+ * specific) instance data, and at a channel type structure.
*/
typedef struct Channel {
struct ChannelState *state; /* Split out state information */
-
- ClientData instanceData; /* Instance-specific data provided by
- * creator of channel. */
+ ClientData instanceData; /* Instance-specific data provided by creator
+ * of channel. */
Tcl_ChannelType *typePtr; /* Pointer to channel type structure. */
-
struct Channel *downChanPtr;/* Refers to channel this one was stacked
- * upon. This reference is NULL for normal
- * channels. See Tcl_StackChannel. */
+ * upon. This reference is NULL for normal
+ * channels. See Tcl_StackChannel. */
struct Channel *upChanPtr; /* Refers to the channel above stacked this
* one. NULL for the top most channel. */
/*
- * Intermediate buffers to hold pre-read data for consumption by a
- * newly stacked transformation. See 'Tcl_StackChannel'.
+ * Intermediate buffers to hold pre-read data for consumption by a newly
+ * stacked transformation. See 'Tcl_StackChannel'.
*/
+
ChannelBuffer *inQueueHead; /* Points at first buffer in input queue. */
ChannelBuffer *inQueueTail; /* Points at last buffer in input queue. */
} Channel;
@@ -149,54 +149,52 @@ typedef struct Channel {
/*
* struct ChannelState:
*
- * One of these structures is allocated for each open channel. It contains data
- * specific to the channel but which belongs to the generic part of the Tcl
- * channel mechanism, and it points at an instance specific (and type
- * specific) * instance data, and at a channel type structure.
+ * One of these structures is allocated for each open channel. It contains
+ * data specific to the channel but which belongs to the generic part of the
+ * Tcl channel mechanism, and it points at an instance specific (and type
+ * specific) instance data, and at a channel type structure.
*/
typedef struct ChannelState {
CONST char *channelName; /* The name of the channel instance in Tcl
- * commands. Storage is owned by the generic IO
- * code, is dynamically allocated. */
+ * commands. Storage is owned by the generic
+ * IO code, is dynamically allocated. */
int flags; /* ORed combination of the flags defined
* below. */
Tcl_Encoding encoding; /* Encoding to apply when reading or writing
- * data on this channel. NULL means no
+ * data on this channel. NULL means no
* encoding is applied to data. */
Tcl_EncodingState inputEncodingState;
- /* Current encoding state, used when converting
- * input data bytes to UTF-8. */
+ /* Current encoding state, used when
+ * converting input data bytes to UTF-8. */
int inputEncodingFlags; /* Encoding flags to pass to conversion
* routine when converting input data bytes to
- * UTF-8. May be TCL_ENCODING_START before
+ * UTF-8. May be TCL_ENCODING_START before
* converting first byte and TCL_ENCODING_END
* when EOF is seen. */
Tcl_EncodingState outputEncodingState;
- /* Current encoding state, used when converting
- * UTF-8 to output data bytes. */
+ /* Current encoding state, used when
+ * converting UTF-8 to output data bytes. */
int outputEncodingFlags; /* Encoding flags to pass to conversion
* routine when converting UTF-8 to output
- * data bytes. May be TCL_ENCODING_START
+ * data bytes. May be TCL_ENCODING_START
* before converting first byte and
* TCL_ENCODING_END when EOF is seen. */
TclEolTranslation inputTranslation;
/* What translation to apply for end of line
- * sequences on input? */
+ * sequences on input? */
TclEolTranslation outputTranslation;
- /* What translation to use for generating
- * end of line sequences in output? */
- int inEofChar; /* If nonzero, use this as a signal of EOF
- * on input. */
- int outEofChar; /* If nonzero, append this to the channel
- * when it is closed if it is open for
- * writing. */
+ /* What translation to use for generating end
+ * of line sequences in output? */
+ int inEofChar; /* If nonzero, use this as a signal of EOF on
+ * input. */
+ int outEofChar; /* If nonzero, append this to the channel when
+ * it is closed if it is open for writing. */
int unreportedError; /* Non-zero if an error report was deferred
* because it happened in the background. The
* value is the POSIX error code. */
int refCount; /* How many interpreters hold references to
* this IO channel? */
-
CloseCallback *closeCbPtr; /* Callbacks registered to be called when the
* channel is closed. */
char *outputStage; /* Temporary staging buffer used when
@@ -205,37 +203,46 @@ typedef struct ChannelState {
ChannelBuffer *curOutPtr; /* Current output buffer being filled. */
ChannelBuffer *outQueueHead;/* Points at first buffer in output queue. */
ChannelBuffer *outQueueTail;/* Points at last buffer in output queue. */
-
ChannelBuffer *saveInBufPtr;/* Buffer saved for input queue - eliminates
* need to allocate a new buffer for "gets"
* that crosses buffer boundaries. */
ChannelBuffer *inQueueHead; /* Points at first buffer in input queue. */
ChannelBuffer *inQueueTail; /* Points at last buffer in input queue. */
-
- struct ChannelHandler *chPtr;/* List of channel handlers registered
- * for this channel. */
+ struct ChannelHandler *chPtr;/* List of channel handlers registered for
+ * this channel. */
int interestMask; /* Mask of all events this channel has
* handlers for. */
EventScriptRecord *scriptRecordPtr;
- /* Chain of all scripts registered for
- * event handlers ("fileevent") on this
- * channel. */
-
+ /* Chain of all scripts registered for event
+ * handlers ("fileevent") on this channel. */
int bufSize; /* What size buffers to allocate? */
Tcl_TimerToken timer; /* Handle to wakeup timer for this channel. */
CopyState *csPtrR; /* State of background copy for which channel is input, or NULL. */
CopyState *csPtrW; /* State of background copy for which channel is output, or NULL. */
- Channel *topChanPtr; /* Refers to topmost channel in a stack.
- * Never NULL. */
+ Channel *topChanPtr; /* Refers to topmost channel in a stack. Never
+ * NULL. */
Channel *bottomChanPtr; /* Refers to bottommost channel in a stack.
* This channel can be relied on to live as
* long as the channel state. Never NULL. */
struct ChannelState *nextCSPtr;
/* Next in list of channels currently open. */
- Tcl_ThreadId managingThread; /* TIP #10: Id of the thread managing
- * this stack of channels. */
+ Tcl_ThreadId managingThread;/* TIP #10: Id of the thread managing this
+ * stack of channels. */
+
+ /*
+ * TIP #219 ... Info for the I/O system ...
+ * Error message set by channel drivers, for the propagation of arbitrary
+ * Tcl errors. This information, if present (chanMsg not NULL), takes
+ * precedence over a posix error code returned by a channel operation.
+ */
+
+ Tcl_Obj* chanMsg;
+ Tcl_Obj* unreportedMsg; /* Non-NULL if an error report was deferred
+ * because it happened in the background. The
+ * value is the chanMg, if any. #219's
+ * companion to 'unreportedError'. */
} ChannelState;
-
+
/*
* Values for the flags field in Channel. Any ORed combination of the
* following flags can be stored in the field. These flags record various
@@ -243,107 +250,106 @@ typedef struct ChannelState {
* the channel can also have TCL_READABLE (1<<1) and TCL_WRITABLE (1<<2) set.
*/
-#define CHANNEL_NONBLOCKING (1<<3) /* Channel is currently in
- * nonblocking mode. */
+#define CHANNEL_NONBLOCKING (1<<3) /* Channel is currently in nonblocking
+ * mode. */
#define CHANNEL_LINEBUFFERED (1<<4) /* Output to the channel must be
* flushed after every newline. */
#define CHANNEL_UNBUFFERED (1<<5) /* Output to the channel must always
* be flushed immediately. */
#define BUFFER_READY (1<<6) /* Current output buffer (the
- * curOutPtr field in the
- * channel structure) should be
- * output as soon as possible even
- * though it may not be full. */
-#define BG_FLUSH_SCHEDULED (1<<7) /* A background flush of the
- * queued output buffers has been
- * scheduled. */
-#define CHANNEL_CLOSED (1<<8) /* Channel has been closed. No
- * further Tcl-level IO on the
- * channel is allowed. */
-#define CHANNEL_EOF (1<<9) /* EOF occurred on this channel.
- * This bit is cleared before every
- * input operation. */
-#define CHANNEL_STICKY_EOF (1<<10) /* EOF occurred on this channel because
- * we saw the input eofChar. This bit
- * prevents clearing of the EOF bit
- * before every input operation. */
-#define CHANNEL_BLOCKED (1<<11) /* EWOULDBLOCK or EAGAIN occurred
- * on this channel. This bit is
- * cleared before every input or
- * output operation. */
+ * curOutPtr field in the channel
+ * structure) should be output as soon
+ * as possible even though it may not
+ * be full. */
+#define BG_FLUSH_SCHEDULED (1<<7) /* A background flush of the queued
+ * output buffers has been
+ * scheduled. */
+#define CHANNEL_CLOSED (1<<8) /* Channel has been closed. No further
+ * Tcl-level IO on the channel is
+ * allowed. */
+#define CHANNEL_EOF (1<<9) /* EOF occurred on this channel. This
+ * bit is cleared before every input
+ * operation. */
+#define CHANNEL_STICKY_EOF (1<<10) /* EOF occurred on this channel
+ * because we saw the input
+ * eofChar. This bit prevents clearing
+ * of the EOF bit before every input
+ * operation. */
+#define CHANNEL_BLOCKED (1<<11) /* EWOULDBLOCK or EAGAIN occurred on
+ * this channel. This bit is cleared
+ * before every input or output
+ * operation. */
#define INPUT_SAW_CR (1<<12) /* Channel is in CRLF eol input
- * translation mode and the last
- * byte seen was a "\r". */
+ * translation mode and the last byte
+ * seen was a "\r". */
#define INPUT_NEED_NL (1<<15) /* Saw a '\r' at end of last buffer,
* and there should be a '\n' at
* beginning of next buffer. */
-#define CHANNEL_DEAD (1<<13) /* The channel has been closed by
- * the exit handler (on exit) but
- * not deallocated. When any IO
- * operation sees this flag on a
- * channel, it does not call driver
- * level functions to avoid referring
- * to deallocated data. */
+#define CHANNEL_DEAD (1<<13) /* The channel has been closed by the
+ * exit handler (on exit) but not
+ * deallocated. When any IO operation
+ * sees this flag on a channel, it
+ * does not call driver level
+ * functions to avoid referring to
+ * deallocated data. */
#define CHANNEL_NEED_MORE_DATA (1<<14) /* The last input operation failed
* because there was not enough data
- * to complete the operation. This
- * flag is set when gets fails to
- * get a complete line or when read
- * fails to get a complete character.
- * When set, file events will not be
+ * to complete the operation. This
+ * flag is set when gets fails to get
+ * a complete line or when read fails
+ * to get a complete character. When
+ * set, file events will not be
* delivered for buffered data until
- * the state of the channel changes. */
+ * the state of the channel
+ * changes. */
#define CHANNEL_RAW_MODE (1<<16) /* When set, notes that the Raw API is
* being used. */
#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
-#define CHANNEL_TIMER_FEV (1<<17) /* When set the event we are
- * notified by is a fileevent
- * generated by a timer. We
- * don't know if the driver
- * has more data and should
- * not try to read from it. If
- * the system needs more than
- * is in the buffers out read
- * routines will simulate a
- * short read (0 characters
- * read) */
-#define CHANNEL_HAS_MORE_DATA (1<<18) /* Set by NotifyChannel for a
- * channel if and only if the
- * channel is configured
- * non-blocking, the driver
+#define CHANNEL_TIMER_FEV (1<<17) /* When set the event we are notified
+ * by is a fileevent generated by a
+ * timer. We don't know if the driver
+ * has more data and should not try to
+ * read from it. If the system needs
+ * more than is in the buffers out
+ * read routines will simulate a short
+ * read (0 characters read) */
+#define CHANNEL_HAS_MORE_DATA (1<<18) /* Set by NotifyChannel for a channel
+ * if and only if the channel is
+ * configured non-blocking, the driver
* for said channel has no
- * blockmodeproc, and data has
- * arrived for reading at the
- * OS level). A GetInput will
- * pass reading from the
+ * blockmodeproc, and data has arrived
+ * for reading at the OS level). A
+ * GetInput will pass reading from the
* driver if the channel is
- * non-blocking, without
- * blockmode proc and the flag
- * has not been set. A read
- * will be performed if the
- * flag is set. This will
- * reset the flag as well. */
+ * non-blocking, without blockmode
+ * proc and the flag has not been set.
+ * A read will be performed if the
+ * flag is set. This will reset the
+ * flag as well. */
#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */
-#define CHANNEL_INCLOSE (1<<19) /* Channel is currently being
- * closed. Its structures are
- * still live and usable, but
- * it may not be closed again
- * from within the close handler.
- */
+#define CHANNEL_INCLOSE (1<<19) /* Channel is currently being closed.
+ * Its structures are still live and
+ * usable, but it may not be closed
+ * again from within the close
+ * handler. */
+#define CHANNEL_TAINTED (1<<20) /* Channel stack structure has changed.
+ * Used by Channel Tcl_Obj type to
+ * determine if we have to revalidate
+ * the channel. */
/*
* For each channel handler registered in a call to Tcl_CreateChannelHandler,
* there is one record of the following type. All of records for a specific
- * channel are chained together in a singly linked list which is stored in
- * the channel structure.
+ * channel are chained together in a singly linked list which is stored in the
+ * channel structure.
*/
typedef struct ChannelHandler {
Channel *chanPtr; /* The channel structure for this channel. */
int mask; /* Mask of desired events. */
Tcl_ChannelProc *proc; /* Procedure to call in the type of
- * Tcl_CreateChannelHandler. */
+ * Tcl_CreateChannelHandler. */
ClientData clientData; /* Argument to pass to procedure. */
struct ChannelHandler *nextPtr;
/* Next one in list of registered handlers. */
@@ -366,17 +372,17 @@ typedef struct ChannelHandler {
*/
typedef struct NextChannelHandler {
- ChannelHandler *nextHandlerPtr; /* The next handler to be invoked in
- * this invocation. */
+ ChannelHandler *nextHandlerPtr;
+ /* The next handler to be invoked in this
+ * invocation. */
struct NextChannelHandler *nestedHandlerPtr;
- /* Next nested invocation of
- * ChannelHandlerEventProc. */
+ /* Next nested invocation of
+ * ChannelHandlerEventProc. */
} NextChannelHandler;
-
/*
- * The following structure describes the event that is added to the Tcl
- * event queue by the channel handler check procedure.
+ * The following structure describes the event that is added to the Tcl event
+ * queue by the channel handler check procedure.
*/
typedef struct ChannelHandlerEvent {
@@ -386,26 +392,26 @@ typedef struct ChannelHandlerEvent {
} ChannelHandlerEvent;
/*
- * The following structure is used by Tcl_GetsObj() to encapsulates the
- * state for a "gets" operation.
+ * The following structure is used by Tcl_GetsObj() to encapsulates the state
+ * for a "gets" operation.
*/
-
+
typedef struct GetsState {
- Tcl_Obj *objPtr; /* The object to which UTF-8 characters
- * will be appended. */
- char **dstPtr; /* Pointer into objPtr's string rep where
- * next character should be stored. */
- Tcl_Encoding encoding; /* The encoding to use to convert raw bytes
- * to UTF-8. */
+ Tcl_Obj *objPtr; /* The object to which UTF-8 characters will
+ * be appended. */
+ char **dstPtr; /* Pointer into objPtr's string rep where next
+ * character should be stored. */
+ Tcl_Encoding encoding; /* The encoding to use to convert raw bytes to
+ * UTF-8. */
ChannelBuffer *bufPtr; /* The current buffer of raw bytes being
* emptied. */
Tcl_EncodingState state; /* The encoding state just before the last
* external to UTF-8 conversion in
* FilterInputBytes(). */
- int rawRead; /* The number of bytes removed from bufPtr
- * in the last call to FilterInputBytes(). */
- int bytesWrote; /* The number of bytes of UTF-8 data
- * appended to objPtr during the last call to
+ int rawRead; /* The number of bytes removed from bufPtr in
+ * the last call to FilterInputBytes(). */
+ int bytesWrote; /* The number of bytes of UTF-8 data appended
+ * to objPtr during the last call to
* FilterInputBytes(). */
int charsWrote; /* The corresponding number of UTF-8
* characters appended to objPtr during the
@@ -414,3 +420,11 @@ typedef struct GetsState {
* appended to objPtr so far, just before the
* last call to FilterInputBytes(). */
} GetsState;
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclIOCmd.c b/generic/tclIOCmd.c
index 44c2738..0c05cbf 100644
--- a/generic/tclIOCmd.c
+++ b/generic/tclIOCmd.c
@@ -1,16 +1,15 @@
-/*
+/*
* tclIOCmd.c --
*
* Contains the definitions of most of the Tcl commands relating to IO.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
/*
* Callback structure for accept callback in a TCP server.
@@ -22,26 +21,75 @@ typedef struct AcceptCallback {
} AcceptCallback;
/*
+ * Thread local storage used to maintain a per-thread stdout channel obj.
+ * It must be per-thread because of std channel limitations.
+ */
+
+typedef struct ThreadSpecificData {
+ int initialized; /* Set to 1 when the module is initialized. */
+ Tcl_Obj *stdoutObjPtr; /* Cached stdout channel Tcl_Obj */
+} ThreadSpecificData;
+
+static Tcl_ThreadDataKey dataKey;
+
+/*
* Static functions for this file:
*/
-static void AcceptCallbackProc _ANSI_ARGS_((ClientData callbackData,
- Tcl_Channel chan, char *address, int port));
-static void RegisterTcpServerInterpCleanup _ANSI_ARGS_((Tcl_Interp *interp,
- AcceptCallback *acceptCallbackPtr));
-static void TcpAcceptCallbacksDeleteProc _ANSI_ARGS_((
- ClientData clientData, Tcl_Interp *interp));
-static void TcpServerCloseProc _ANSI_ARGS_((ClientData callbackData));
-static void UnregisterTcpServerInterpCleanupProc _ANSI_ARGS_((
- Tcl_Interp *interp, AcceptCallback *acceptCallbackPtr));
+static void FinalizeIOCmdTSD(ClientData clientData);
+static void AcceptCallbackProc(ClientData callbackData,
+ Tcl_Channel chan, char *address, int port);
+static int ChanPendingObjCmd(ClientData unused,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int ChanTruncateObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static void RegisterTcpServerInterpCleanup(Tcl_Interp *interp,
+ AcceptCallback *acceptCallbackPtr);
+static void TcpAcceptCallbacksDeleteProc(ClientData clientData,
+ Tcl_Interp *interp);
+static void TcpServerCloseProc(ClientData callbackData);
+static void UnregisterTcpServerInterpCleanupProc(
+ Tcl_Interp *interp,
+ AcceptCallback *acceptCallbackPtr);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FinalizeIOCmdTSD --
+ *
+ * Release the storage associated with the per-thread cache.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FinalizeIOCmdTSD(
+ ClientData clientData) /* Not used. */
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ if (tsdPtr->stdoutObjPtr != NULL) {
+ Tcl_DecrRefCount(tsdPtr->stdoutObjPtr);
+ tsdPtr->stdoutObjPtr = NULL;
+ }
+ tsdPtr->initialized = 0;
+}
/*
*----------------------------------------------------------------------
*
* Tcl_PutsObjCmd --
*
- * This procedure is invoked to process the "puts" Tcl command.
- * See the user documentation for details on what it does.
+ * This function is invoked to process the "puts" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -54,94 +102,106 @@ static void UnregisterTcpServerInterpCleanupProc _ANSI_ARGS_((
/* ARGSUSED */
int
-Tcl_PutsObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_PutsObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- Tcl_Channel chan; /* The channel to puts on. */
- Tcl_Obj *string; /* String to write. */
- int newline; /* Add a newline at end? */
- char *channelId; /* Name of channel for puts. */
- int result; /* Result of puts operation. */
- int mode; /* Mode in which channel is opened. */
+ Tcl_Channel chan; /* The channel to puts on. */
+ Tcl_Obj *string; /* String to write. */
+ Tcl_Obj *chanObjPtr = NULL; /* channel object. */
+ int newline; /* Add a newline at end? */
+ int result; /* Result of puts operation. */
+ int mode; /* Mode in which channel is opened. */
+ ThreadSpecificData *tsdPtr;
switch (objc) {
- case 2: /* puts $x */
+ case 2: /* [puts $x] */
string = objv[1];
newline = 1;
- channelId = "stdout";
break;
- case 3: /* puts -nonewline $x or puts $chan $x */
- if (strcmp(Tcl_GetString(objv[1]), "-nonewline") == 0) {
+ case 3: /* [puts -nonewline $x] or [puts $chan $x] */
+ if (strcmp(TclGetString(objv[1]), "-nonewline") == 0) {
newline = 0;
- channelId = "stdout";
} else {
newline = 1;
- channelId = Tcl_GetString(objv[1]);
+ chanObjPtr = objv[1];
}
string = objv[2];
break;
- case 4: /* puts -nonewline $chan $x or puts $chan $x nonewline */
- if (strcmp(Tcl_GetString(objv[1]), "-nonewline") == 0) {
- channelId = Tcl_GetString(objv[2]);
+ case 4: /* [puts -nonewline $chan $x] or [puts $chan $x nonewline] */
+ newline = 0;
+ if (strcmp(TclGetString(objv[1]), "-nonewline") == 0) {
+ chanObjPtr = objv[2];
string = objv[3];
- } else {
+ break;
+ } else if (strcmp(TclGetString(objv[3]), "nonewline") == 0) {
/*
- * The code below provides backwards compatibility with an
- * old form of the command that is no longer recommended
- * or documented.
+ * The code below provides backwards compatibility with an old
+ * form of the command that is no longer recommended or
+ * documented. See also [Bug #3151675]. Will be removed in Tcl 9,
+ * maybe even earlier.
*/
- char *arg;
- int length;
-
- arg = Tcl_GetStringFromObj(objv[3], &length);
- if ((length != 9) || (strncmp(arg, "nonewline", (size_t) length) != 0)) {
- Tcl_AppendResult(interp, "bad argument \"", arg,
- "\": should be \"nonewline\"",
- (char *) NULL);
- return TCL_ERROR;
- }
- channelId = Tcl_GetString(objv[1]);
+ chanObjPtr = objv[1];
string = objv[2];
+ break;
}
- newline = 0;
- break;
-
- default: /* puts or puts some bad number of arguments... */
+ /* Fall through */
+ default:
+ /* [puts] or [puts some bad number of arguments...] */
Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? ?channelId? string");
return TCL_ERROR;
}
- chan = Tcl_GetChannel(interp, channelId, &mode);
- if (chan == (Tcl_Channel) NULL) {
- return TCL_ERROR;
+ if (chanObjPtr == NULL) {
+ tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ if (!tsdPtr->initialized) {
+ tsdPtr->initialized = 1;
+ TclNewLiteralStringObj(tsdPtr->stdoutObjPtr, "stdout");
+ Tcl_IncrRefCount(tsdPtr->stdoutObjPtr);
+ Tcl_CreateThreadExitHandler(FinalizeIOCmdTSD, NULL);
+ }
+ chanObjPtr = tsdPtr->stdoutObjPtr;
+ }
+ if (TclGetChannelFromObj(interp, chanObjPtr, &chan, &mode, 0) != TCL_OK) {
+ return TCL_ERROR;
}
if ((mode & TCL_WRITABLE) == 0) {
- Tcl_AppendResult(interp, "channel \"", channelId,
- "\" wasn't opened for writing", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "channel \"", TclGetString(chanObjPtr),
+ "\" wasn't opened for writing", NULL);
+ return TCL_ERROR;
}
result = Tcl_WriteObj(chan, string);
if (result < 0) {
- goto error;
+ goto error;
}
if (newline != 0) {
- result = Tcl_WriteChars(chan, "\n", 1);
- if (result < 0) {
- goto error;
- }
+ result = Tcl_WriteChars(chan, "\n", 1);
+ if (result < 0) {
+ goto error;
+ }
}
return TCL_OK;
- error:
- Tcl_AppendResult(interp, "error writing \"", channelId, "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ /*
+ * TIP #219.
+ * Capture error messages put by the driver into the bypass area and put
+ * them into the regular interpreter result. Fall back to the regular
+ * message if nothing was found in the bypass.
+ */
+
+ error:
+ if (!TclChanCaughtErrorBypass(interp, chan)) {
+ Tcl_AppendResult(interp, "error writing \"",
+ TclGetString(chanObjPtr), "\": ",
+ Tcl_PosixError(interp), NULL);
+ }
return TCL_ERROR;
}
@@ -150,8 +210,8 @@ Tcl_PutsObjCmd(dummy, interp, objc, objv)
*
* Tcl_FlushObjCmd --
*
- * This procedure is called to process the Tcl "flush" command.
- * See the user documentation for details on what it does.
+ * This function is called to process the Tcl "flush" command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -164,34 +224,43 @@ Tcl_PutsObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_FlushObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_FlushObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- Tcl_Channel chan; /* The channel to flush on. */
- char *channelId;
+ Tcl_Obj *chanObjPtr;
+ Tcl_Channel chan; /* The channel to flush on. */
int mode;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "channelId");
return TCL_ERROR;
}
- channelId = Tcl_GetString(objv[1]);
- chan = Tcl_GetChannel(interp, channelId, &mode);
- if (chan == (Tcl_Channel) NULL) {
+ chanObjPtr = objv[1];
+ if (TclGetChannelFromObj(interp, chanObjPtr, &chan, &mode, 0) != TCL_OK) {
return TCL_ERROR;
}
if ((mode & TCL_WRITABLE) == 0) {
- Tcl_AppendResult(interp, "channel \"", channelId,
- "\" wasn't opened for writing", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "channel \"", TclGetString(chanObjPtr),
+ "\" wasn't opened for writing", NULL);
+ return TCL_ERROR;
}
-
+
if (Tcl_Flush(chan) != TCL_OK) {
- Tcl_AppendResult(interp, "error flushing \"", channelId, "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ /*
+ * TIP #219.
+ * Capture error messages put by the driver into the bypass area and
+ * put them into the regular interpreter result. Fall back to the
+ * regular message if nothing was found in the bypass.
+ */
+
+ if (!TclChanCaughtErrorBypass(interp, chan)) {
+ Tcl_AppendResult(interp, "error flushing \"",
+ TclGetString(chanObjPtr), "\": ",
+ Tcl_PosixError(interp), NULL);
+ }
return TCL_ERROR;
}
return TCL_OK;
@@ -202,8 +271,8 @@ Tcl_FlushObjCmd(dummy, interp, objc, objv)
*
* Tcl_GetsObjCmd --
*
- * This procedure is called to process the Tcl "gets" command.
- * See the user documentation for details on what it does.
+ * This function is called to process the Tcl "gets" command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -216,54 +285,61 @@ Tcl_FlushObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_GetsObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_GetsObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- Tcl_Channel chan; /* The channel to read from. */
- int lineLen; /* Length of line just read. */
- int mode; /* Mode in which channel is opened. */
- char *name;
- Tcl_Obj *linePtr;
+ Tcl_Channel chan; /* The channel to read from. */
+ int lineLen; /* Length of line just read. */
+ int mode; /* Mode in which channel is opened. */
+ Tcl_Obj *linePtr, *chanObjPtr;
if ((objc != 2) && (objc != 3)) {
Tcl_WrongNumArgs(interp, 1, objv, "channelId ?varName?");
return TCL_ERROR;
}
- name = Tcl_GetString(objv[1]);
- chan = Tcl_GetChannel(interp, name, &mode);
- if (chan == (Tcl_Channel) NULL) {
+ chanObjPtr = objv[1];
+ if (TclGetChannelFromObj(interp, chanObjPtr, &chan, &mode, 0) != TCL_OK) {
return TCL_ERROR;
}
if ((mode & TCL_READABLE) == 0) {
- Tcl_AppendResult(interp, "channel \"", name,
- "\" wasn't opened for reading", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "channel \"", TclGetString(chanObjPtr),
+ "\" wasn't opened for reading", NULL);
+ return TCL_ERROR;
}
linePtr = Tcl_NewObj();
-
lineLen = Tcl_GetsObj(chan, linePtr);
if (lineLen < 0) {
- if (!Tcl_Eof(chan) && !Tcl_InputBlocked(chan)) {
+ if (!Tcl_Eof(chan) && !Tcl_InputBlocked(chan)) {
Tcl_DecrRefCount(linePtr);
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "error reading \"", name, "\": ",
- Tcl_PosixError(interp), (char *) NULL);
- return TCL_ERROR;
- }
- lineLen = -1;
+
+ /*
+ * TIP #219. Capture error messages put by the driver into the
+ * bypass area and put them into the regular interpreter result.
+ * Fall back to the regular message if nothing was found in the
+ * bypass.
+ */
+
+ if (!TclChanCaughtErrorBypass(interp, chan)) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "error reading \"",
+ TclGetString(chanObjPtr), "\": ",
+ Tcl_PosixError(interp), NULL);
+ }
+ return TCL_ERROR;
+ }
+ lineLen = -1;
}
if (objc == 3) {
if (Tcl_ObjSetVar2(interp, objv[2], NULL, linePtr,
TCL_LEAVE_ERR_MSG) == NULL) {
- Tcl_DecrRefCount(linePtr);
- return TCL_ERROR;
- }
+ return TCL_ERROR;
+ }
Tcl_SetObjResult(interp, Tcl_NewIntObj(lineLen));
- return TCL_OK;
+ return TCL_OK;
} else {
Tcl_SetObjResult(interp, linePtr);
}
@@ -275,8 +351,8 @@ Tcl_GetsObjCmd(dummy, interp, objc, objv)
*
* Tcl_ReadObjCmd --
*
- * This procedure is invoked to process the Tcl "read" command.
- * See the user documentation for details on what it does.
+ * This function is invoked to process the Tcl "read" command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -289,94 +365,116 @@ Tcl_GetsObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_ReadObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_ReadObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan; /* The channel to read from. */
int newline, i; /* Discard newline at end? */
int toRead; /* How many bytes to read? */
int charactersRead; /* How many characters were read? */
int mode; /* Mode in which channel is opened. */
- char *name;
- Tcl_Obj *resultPtr;
+ Tcl_Obj *resultPtr, *chanObjPtr;
if ((objc != 2) && (objc != 3)) {
- argerror:
+ Interp *iPtr;
+
+ argerror:
+ iPtr = (Interp *) interp;
Tcl_WrongNumArgs(interp, 1, objv, "channelId ?numChars?");
- Tcl_AppendResult(interp, " or \"", Tcl_GetString(objv[0]),
- " ?-nonewline? channelId\"", (char *) NULL);
+
+ /*
+ * Do not append directly; that makes ensembles using this command as
+ * a subcommand produce the wrong message.
+ */
+
+ iPtr->flags |= INTERP_ALTERNATE_WRONG_ARGS;
+ Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? channelId");
+ iPtr->flags &= ~INTERP_ALTERNATE_WRONG_ARGS;
return TCL_ERROR;
}
i = 1;
newline = 0;
- if (strcmp(Tcl_GetString(objv[1]), "-nonewline") == 0) {
+ if (strcmp(TclGetString(objv[1]), "-nonewline") == 0) {
newline = 1;
i++;
}
if (i == objc) {
- goto argerror;
+ goto argerror;
}
- name = Tcl_GetString(objv[i]);
- chan = Tcl_GetChannel(interp, name, &mode);
- if (chan == (Tcl_Channel) NULL) {
+ chanObjPtr = objv[i];
+ if (TclGetChannelFromObj(interp, chanObjPtr, &chan, &mode, 0) != TCL_OK) {
return TCL_ERROR;
}
if ((mode & TCL_READABLE) == 0) {
- Tcl_AppendResult(interp, "channel \"", name,
- "\" wasn't opened for reading", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "channel \"", TclGetString(chanObjPtr),
+ "\" wasn't opened for reading", NULL);
+ return TCL_ERROR;
}
i++; /* Consumed channel name. */
/*
- * Compute how many bytes to read, and see whether the final
- * newline should be dropped.
+ * Compute how many bytes to read.
*/
toRead = -1;
if (i < objc) {
- char *arg;
-
- arg = Tcl_GetString(objv[i]);
- if (isdigit(UCHAR(arg[0]))) { /* INTL: digit */
- if (Tcl_GetIntFromObj(interp, objv[i], &toRead) != TCL_OK) {
- return TCL_ERROR;
+ if (TclGetIntFromObj(interp, objv[i], &toRead) != TCL_OK) {
+ /*
+ * The code below provides backwards compatibility with an old
+ * form of the command that is no longer recommended or
+ * documented. See also [Bug #3151675]. Will be removed in Tcl 9,
+ * maybe even earlier.
+ */
+
+ if (strcmp(TclGetString(objv[i]), "nonewline") != 0) {
+ return TCL_ERROR;
}
- } else if (strcmp(arg, "nonewline") == 0) {
newline = 1;
- } else {
- Tcl_AppendResult(interp, "bad argument \"", arg,
- "\": should be \"nonewline\"", (char *) NULL);
+ } else if (toRead < 0) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "expected non-negative integer but got \"",
+ TclGetString(objv[i]), "\"", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "VALUE", "NUMBER", NULL);
return TCL_ERROR;
- }
+ }
}
resultPtr = Tcl_NewObj();
Tcl_IncrRefCount(resultPtr);
charactersRead = Tcl_ReadChars(chan, resultPtr, toRead, 0);
if (charactersRead < 0) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "error reading \"", name, "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ /*
+ * TIP #219.
+ * Capture error messages put by the driver into the bypass area and
+ * put them into the regular interpreter result. Fall back to the
+ * regular message if nothing was found in the bypass.
+ */
+
+ if (!TclChanCaughtErrorBypass(interp, chan)) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "error reading \"",
+ TclGetString(chanObjPtr), "\": ",
+ Tcl_PosixError(interp), NULL);
+ }
Tcl_DecrRefCount(resultPtr);
return TCL_ERROR;
}
-
+
/*
* If requested, remove the last newline in the channel if at EOF.
*/
-
+
if ((charactersRead > 0) && (newline != 0)) {
char *result;
int length;
- result = Tcl_GetStringFromObj(resultPtr, &length);
+ result = TclGetStringFromObj(resultPtr, &length);
if (result[length - 1] == '\n') {
Tcl_SetObjLength(resultPtr, length - 1);
}
@@ -391,35 +489,34 @@ Tcl_ReadObjCmd(dummy, interp, objc, objv)
*
* Tcl_SeekObjCmd --
*
- * This procedure is invoked to process the Tcl "seek" command. See
- * the user documentation for details on what it does.
+ * This function is invoked to process the Tcl "seek" command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
- * Moves the position of the access point on the specified channel.
- * May flush queued output.
+ * Moves the position of the access point on the specified channel. May
+ * flush queued output.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
-Tcl_SeekObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_SeekObjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- Tcl_Channel chan; /* The channel to tell on. */
- Tcl_WideInt offset; /* Where to seek? */
- int mode; /* How to seek? */
- Tcl_WideInt result; /* Of calling Tcl_Seek. */
- char *chanName;
+ Tcl_Channel chan; /* The channel to tell on. */
+ Tcl_WideInt offset; /* Where to seek? */
+ int mode; /* How to seek? */
+ Tcl_WideInt result; /* Of calling Tcl_Seek. */
int optionIndex;
- static CONST char *originOptions[] = {
- "start", "current", "end", (char *) NULL
+ static const char *originOptions[] = {
+ "start", "current", "end", NULL
};
static int modeArray[] = {SEEK_SET, SEEK_CUR, SEEK_END};
@@ -427,9 +524,7 @@ Tcl_SeekObjCmd(clientData, interp, objc, objv)
Tcl_WrongNumArgs(interp, 1, objv, "channelId offset ?origin?");
return TCL_ERROR;
}
- chanName = Tcl_GetString(objv[1]);
- chan = Tcl_GetChannel(interp, chanName, NULL);
- if (chan == (Tcl_Channel) NULL) {
+ if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
return TCL_ERROR;
}
if (Tcl_GetWideIntFromObj(interp, objv[2], &offset) != TCL_OK) {
@@ -446,9 +541,18 @@ Tcl_SeekObjCmd(clientData, interp, objc, objv)
result = Tcl_Seek(chan, offset, mode);
if (result == Tcl_LongAsWide(-1)) {
- Tcl_AppendResult(interp, "error during seek on \"",
- chanName, "\": ", Tcl_PosixError(interp), (char *) NULL);
- return TCL_ERROR;
+ /*
+ * TIP #219.
+ * Capture error messages put by the driver into the bypass area and
+ * put them into the regular interpreter result. Fall back to the
+ * regular message if nothing was found in the bypass.
+ */
+ if (!TclChanCaughtErrorBypass(interp, chan)) {
+ Tcl_AppendResult(interp, "error during seek on \"",
+ TclGetString(objv[1]), "\": ",
+ Tcl_PosixError(interp), NULL);
+ }
+ return TCL_ERROR;
}
return TCL_OK;
}
@@ -458,8 +562,8 @@ Tcl_SeekObjCmd(clientData, interp, objc, objv)
*
* Tcl_TellObjCmd --
*
- * This procedure is invoked to process the Tcl "tell" command.
- * See the user documentation for details on what it does.
+ * This function is invoked to process the Tcl "tell" command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -472,30 +576,42 @@ Tcl_SeekObjCmd(clientData, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_TellObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_TellObjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- Tcl_Channel chan; /* The channel to tell on. */
- char *chanName;
+ Tcl_Channel chan; /* The channel to tell on. */
+ Tcl_WideInt newLoc;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "channelId");
return TCL_ERROR;
}
+
+ /*
+ * Try to find a channel with the right name and permissions in the IO
+ * channel table of this interpreter.
+ */
+
+ if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ newLoc = Tcl_Tell(chan);
+
/*
- * Try to find a channel with the right name and permissions in
- * the IO channel table of this interpreter.
+ * TIP #219.
+ * Capture error messages put by the driver into the bypass area and put
+ * them into the regular interpreter result.
*/
-
- chanName = Tcl_GetString(objv[1]);
- chan = Tcl_GetChannel(interp, chanName, NULL);
- if (chan == (Tcl_Channel) NULL) {
+
+ if (TclChanCaughtErrorBypass(interp, chan)) {
return TCL_ERROR;
}
- Tcl_SetWideIntObj(Tcl_GetObjResult(interp), Tcl_Tell(chan));
+
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(newLoc));
return TCL_OK;
}
@@ -504,8 +620,8 @@ Tcl_TellObjCmd(clientData, interp, objc, objv)
*
* Tcl_CloseObjCmd --
*
- * This procedure is invoked to process the Tcl "close" command.
- * See the user documentation for details on what it does.
+ * This function is invoked to process the Tcl "close" command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -518,48 +634,48 @@ Tcl_TellObjCmd(clientData, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_CloseObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_CloseObjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- Tcl_Channel chan; /* The channel to close. */
- char *arg;
+ Tcl_Channel chan; /* The channel to close. */
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "channelId");
return TCL_ERROR;
}
- arg = Tcl_GetString(objv[1]);
- chan = Tcl_GetChannel(interp, arg, NULL);
- if (chan == (Tcl_Channel) NULL) {
+ if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
return TCL_ERROR;
}
if (Tcl_UnregisterChannel(interp, chan) != TCL_OK) {
- /*
- * If there is an error message and it ends with a newline, remove
- * the newline. This is done for command pipeline channels where the
- * error output from the subprocesses is stored in interp's result.
- *
- * NOTE: This is likely to not have any effect on regular error
- * messages produced by drivers during the closing of a channel,
- * because the Tcl convention is that such error messages do not
- * have a terminating newline.
- */
-
- Tcl_Obj *resultPtr;
+ /*
+ * If there is an error message and it ends with a newline, remove the
+ * newline. This is done for command pipeline channels where the error
+ * output from the subprocesses is stored in interp's result.
+ *
+ * NOTE: This is likely to not have any effect on regular error
+ * messages produced by drivers during the closing of a channel,
+ * because the Tcl convention is that such error messages do not have
+ * a terminating newline.
+ */
+
+ Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);
char *string;
int len;
-
- resultPtr = Tcl_GetObjResult(interp);
- string = Tcl_GetStringFromObj(resultPtr, &len);
- if ((len > 0) && (string[len - 1] == '\n')) {
+
+ if (Tcl_IsShared(resultPtr)) {
+ resultPtr = Tcl_DuplicateObj(resultPtr);
+ Tcl_SetObjResult(interp, resultPtr);
+ }
+ string = TclGetStringFromObj(resultPtr, &len);
+ if ((len > 0) && (string[len - 1] == '\n')) {
Tcl_SetObjLength(resultPtr, len - 1);
- }
- return TCL_ERROR;
+ }
+ return TCL_ERROR;
}
return TCL_OK;
@@ -570,8 +686,8 @@ Tcl_CloseObjCmd(clientData, interp, objc, objv)
*
* Tcl_FconfigureObjCmd --
*
- * This procedure is invoked to process the Tcl "fconfigure" command.
- * See the user documentation for details on what it does.
+ * This function is invoked to process the Tcl "fconfigure" command. See
+ * the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -584,55 +700,60 @@ Tcl_CloseObjCmd(clientData, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_FconfigureObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_FconfigureObjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- char *chanName, *optionName, *valueName;
- Tcl_Channel chan; /* The channel to set a mode on. */
- int i; /* Iterate over arg-value pairs. */
- Tcl_DString ds; /* DString to hold result of
- * calling Tcl_GetChannelOption. */
+ char *optionName, *valueName;
+ Tcl_Channel chan; /* The channel to set a mode on. */
+ int i; /* Iterate over arg-value pairs. */
if ((objc < 2) || (((objc % 2) == 1) && (objc != 3))) {
Tcl_WrongNumArgs(interp, 1, objv,
"channelId ?optionName? ?value? ?optionName value?...");
- return TCL_ERROR;
+ return TCL_ERROR;
}
- chanName = Tcl_GetString(objv[1]);
- chan = Tcl_GetChannel(interp, chanName, NULL);
- if (chan == (Tcl_Channel) NULL) {
- return TCL_ERROR;
+
+ if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
+ return TCL_ERROR;
}
+
if (objc == 2) {
- Tcl_DStringInit(&ds);
- if (Tcl_GetChannelOption(interp, chan, (char *) NULL, &ds) != TCL_OK) {
+ Tcl_DString ds; /* DString to hold result of calling
+ * Tcl_GetChannelOption. */
+
+ Tcl_DStringInit(&ds);
+ if (Tcl_GetChannelOption(interp, chan, NULL, &ds) != TCL_OK) {
Tcl_DStringFree(&ds);
return TCL_ERROR;
- }
- Tcl_DStringResult(interp, &ds);
- return TCL_OK;
- }
- if (objc == 3) {
- Tcl_DStringInit(&ds);
- optionName = Tcl_GetString(objv[2]);
- if (Tcl_GetChannelOption(interp, chan, optionName, &ds) != TCL_OK) {
- Tcl_DStringFree(&ds);
- return TCL_ERROR;
- }
- Tcl_DStringResult(interp, &ds);
- return TCL_OK;
+ }
+ Tcl_DStringResult(interp, &ds);
+ return TCL_OK;
+ } else if (objc == 3) {
+ Tcl_DString ds; /* DString to hold result of calling
+ * Tcl_GetChannelOption. */
+
+ Tcl_DStringInit(&ds);
+ optionName = TclGetString(objv[2]);
+ if (Tcl_GetChannelOption(interp, chan, optionName, &ds) != TCL_OK) {
+ Tcl_DStringFree(&ds);
+ return TCL_ERROR;
+ }
+ Tcl_DStringResult(interp, &ds);
+ return TCL_OK;
}
+
for (i = 3; i < objc; i += 2) {
- optionName = Tcl_GetString(objv[i-1]);
- valueName = Tcl_GetString(objv[i]);
- if (Tcl_SetChannelOption(interp, chan, optionName, valueName)
+ optionName = TclGetString(objv[i-1]);
+ valueName = TclGetString(objv[i]);
+ if (Tcl_SetChannelOption(interp, chan, optionName, valueName)
!= TCL_OK) {
- return TCL_ERROR;
- }
+ return TCL_ERROR;
+ }
}
+
return TCL_OK;
}
@@ -641,43 +762,39 @@ Tcl_FconfigureObjCmd(clientData, interp, objc, objv)
*
* Tcl_EofObjCmd --
*
- * This procedure is invoked to process the Tcl "eof" command.
- * See the user documentation for details on what it does.
+ * This function is invoked to process the Tcl "eof" command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
- * Sets interp's result to boolean true or false depending on whether
- * the specified channel has an EOF condition.
+ * Sets interp's result to boolean true or false depending on whether the
+ * specified channel has an EOF condition.
*
*---------------------------------------------------------------------------
*/
/* ARGSUSED */
int
-Tcl_EofObjCmd(unused, interp, objc, objv)
- ClientData unused; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_EofObjCmd(
+ ClientData unused, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan;
- int dummy;
- char *arg;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "channelId");
- return TCL_ERROR;
+ return TCL_ERROR;
}
- arg = Tcl_GetString(objv[1]);
- chan = Tcl_GetChannel(interp, arg, &dummy);
- if (chan == NULL) {
+ if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
return TCL_ERROR;
}
- Tcl_SetBooleanObj(Tcl_GetObjResult(interp), Tcl_Eof(chan));
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(Tcl_Eof(chan)));
return TCL_OK;
}
@@ -686,8 +803,8 @@ Tcl_EofObjCmd(unused, interp, objc, objv)
*
* Tcl_ExecObjCmd --
*
- * This procedure is invoked to process the "exec" Tcl command.
- * See the user documentation for details on what it does.
+ * This function is invoked to process the "exec" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -700,47 +817,39 @@ Tcl_EofObjCmd(unused, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_ExecObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_ExecObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
-#ifdef MAC_TCL
-
- Tcl_AppendResult(interp, "exec not implemented under Mac OS",
- (char *)NULL);
- return TCL_ERROR;
-
-#else /* !MAC_TCL */
-
/*
- * This procedure generates an argv array for the string arguments. It
+ * This function generates an argv array for the string arguments. It
* starts out with stack-allocated space but uses dynamically-allocated
* storage if needed.
*/
-#define NUM_ARGS 20
Tcl_Obj *resultPtr;
- CONST char **argv;
+ const char **argv;
char *string;
Tcl_Channel chan;
- CONST char *argStorage[NUM_ARGS];
int argc, background, i, index, keepNewline, result, skip, length;
- static CONST char *options[] = {
- "-keepnewline", "--", NULL
+ int ignoreStderr;
+ static const char *options[] = {
+ "-ignorestderr", "-keepnewline", "--", NULL
};
enum options {
- EXEC_KEEPNEWLINE, EXEC_LAST
+ EXEC_IGNORESTDERR, EXEC_KEEPNEWLINE, EXEC_LAST
};
/*
- * Check for a leading "-keepnewline" argument.
+ * Check for any leading option arguments.
*/
keepNewline = 0;
+ ignoreStderr = 0;
for (skip = 1; skip < objc; skip++) {
- string = Tcl_GetString(objv[skip]);
+ string = TclGetString(objv[skip]);
if (string[0] != '-') {
break;
}
@@ -750,6 +859,8 @@ Tcl_ExecObjCmd(dummy, interp, objc, objv)
}
if (index == EXEC_KEEPNEWLINE) {
keepNewline = 1;
+ } else if (index == EXEC_IGNORESTDERR) {
+ ignoreStderr = 1;
} else {
skip++;
break;
@@ -765,23 +876,20 @@ Tcl_ExecObjCmd(dummy, interp, objc, objv)
*/
background = 0;
- string = Tcl_GetString(objv[objc - 1]);
+ string = TclGetString(objv[objc - 1]);
if ((string[0] == '&') && (string[1] == '\0')) {
objc--;
- background = 1;
+ background = 1;
}
/*
- * Create the string argument array "argv". Make sure argv is large
- * enough to hold the argc arguments plus 1 extra for the zero
- * end-of-argv word.
+ * Create the string argument array "argv". Make sure argv is large enough
+ * to hold the argc arguments plus 1 extra for the zero end-of-argv word.
*/
- argv = argStorage;
argc = objc - skip;
- if ((argc + 1) > sizeof(argv) / sizeof(argv[0])) {
- argv = (CONST char **) ckalloc((unsigned)(argc + 1) * sizeof(char *));
- }
+ argv = (const char **)
+ TclStackAlloc(interp, (unsigned)(argc + 1) * sizeof(char *));
/*
* Copy the string conversions of each (post option) object into the
@@ -789,64 +897,71 @@ Tcl_ExecObjCmd(dummy, interp, objc, objv)
*/
for (i = 0; i < argc; i++) {
- argv[i] = Tcl_GetString(objv[i + skip]);
+ argv[i] = TclGetString(objv[i + skip]);
}
argv[argc] = NULL;
- chan = Tcl_OpenCommandChannel(interp, argc, argv,
- (background ? 0 : TCL_STDOUT | TCL_STDERR));
+ chan = Tcl_OpenCommandChannel(interp, argc, argv, (background ? 0 :
+ (ignoreStderr ? TCL_STDOUT : TCL_STDOUT|TCL_STDERR)));
/*
- * Free the argv array if malloc'ed storage was used.
+ * Free the argv array.
*/
- if (argv != argStorage) {
- ckfree((char *)argv);
- }
+ TclStackFree(interp, (void *)argv);
- if (chan == (Tcl_Channel) NULL) {
+ if (chan == NULL) {
return TCL_ERROR;
}
if (background) {
- /*
+ /*
* Store the list of PIDs from the pipeline in interp's result and
* detach the PIDs (instead of waiting for them).
*/
- TclGetAndDetachPids(interp, chan);
- if (Tcl_Close(interp, chan) != TCL_OK) {
+ TclGetAndDetachPids(interp, chan);
+ if (Tcl_Close(interp, chan) != TCL_OK) {
return TCL_ERROR;
- }
+ }
return TCL_OK;
}
resultPtr = Tcl_NewObj();
if (Tcl_GetChannelHandle(chan, TCL_READABLE, NULL) == TCL_OK) {
if (Tcl_ReadChars(chan, resultPtr, -1, 0) < 0) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "error reading output from command: ",
- Tcl_PosixError(interp), (char *) NULL);
- Tcl_DecrRefCount(resultPtr);
+ /*
+ * TIP #219.
+ * Capture error messages put by the driver into the bypass area
+ * and put them into the regular interpreter result. Fall back to
+ * the regular message if nothing was found in the bypass.
+ */
+
+ if (!TclChanCaughtErrorBypass(interp, chan)) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "error reading output from command: ",
+ Tcl_PosixError(interp), NULL);
+ Tcl_DecrRefCount(resultPtr);
+ }
return TCL_ERROR;
}
}
+
/*
- * If the process produced anything on stderr, it will have been
- * returned in the interpreter result. It needs to be appended to
- * the result string.
+ * If the process produced anything on stderr, it will have been returned
+ * in the interpreter result. It needs to be appended to the result
+ * string.
*/
result = Tcl_Close(interp, chan);
- string = Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &length);
- Tcl_AppendToObj(resultPtr, string, length);
+ Tcl_AppendObjToObj(resultPtr, Tcl_GetObjResult(interp));
/*
- * If the last character of the result is a newline, then remove
- * the newline character.
+ * If the last character of the result is a newline, then remove the
+ * newline character.
*/
-
+
if (keepNewline == 0) {
- string = Tcl_GetStringFromObj(resultPtr, &length);
+ string = TclGetStringFromObj(resultPtr, &length);
if ((length > 0) && (string[length - 1] == '\n')) {
Tcl_SetObjLength(resultPtr, length - 1);
}
@@ -854,7 +969,6 @@ Tcl_ExecObjCmd(dummy, interp, objc, objv)
Tcl_SetObjResult(interp, resultPtr);
return result;
-#endif /* !MAC_TCL */
}
/*
@@ -862,48 +976,45 @@ Tcl_ExecObjCmd(dummy, interp, objc, objv)
*
* Tcl_FblockedObjCmd --
*
- * This procedure is invoked to process the Tcl "fblocked" command.
- * See the user documentation for details on what it does.
+ * This function is invoked to process the Tcl "fblocked" command. See
+ * the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
- * Sets interp's result to boolean true or false depending on whether
- * the preceeding input operation on the channel would have blocked.
+ * Sets interp's result to boolean true or false depending on whether the
+ * preceeding input operation on the channel would have blocked.
*
*---------------------------------------------------------------------------
*/
/* ARGSUSED */
int
-Tcl_FblockedObjCmd(unused, interp, objc, objv)
- ClientData unused; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_FblockedObjCmd(
+ ClientData unused, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan;
int mode;
- char *arg;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "channelId");
- return TCL_ERROR;
+ return TCL_ERROR;
}
- arg = Tcl_GetString(objv[1]);
- chan = Tcl_GetChannel(interp, arg, &mode);
- if (chan == NULL) {
- return TCL_ERROR;
+ if (TclGetChannelFromObj(interp, objv[1], &chan, &mode, 0) != TCL_OK) {
+ return TCL_ERROR;
}
if ((mode & TCL_READABLE) == 0) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "channel \"",
- arg, "\" wasn't opened for reading", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "channel \"", TclGetString(objv[1]),
+ "\" wasn't opened for reading", NULL);
+ return TCL_ERROR;
}
-
- Tcl_SetBooleanObj(Tcl_GetObjResult(interp), Tcl_InputBlocked(chan));
+
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(Tcl_InputBlocked(chan)));
return TCL_OK;
}
@@ -912,8 +1023,8 @@ Tcl_FblockedObjCmd(unused, interp, objc, objv)
*
* Tcl_OpenObjCmd --
*
- * This procedure is invoked to process the "open" Tcl command.
- * See the user documentation for details on what it does.
+ * This function is invoked to process the "open" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -926,14 +1037,14 @@ Tcl_FblockedObjCmd(unused, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_OpenObjCmd(notUsed, interp, objc, objv)
- ClientData notUsed; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_OpenObjCmd(
+ ClientData notUsed, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
int pipeline, prot;
- char *modeString, *what;
+ const char *modeString, *what;
Tcl_Channel chan;
if ((objc < 2) || (objc > 4)) {
@@ -944,16 +1055,34 @@ Tcl_OpenObjCmd(notUsed, interp, objc, objv)
if (objc == 2) {
modeString = "r";
} else {
- modeString = Tcl_GetString(objv[2]);
+ modeString = TclGetString(objv[2]);
if (objc == 4) {
- if (Tcl_GetIntFromObj(interp, objv[3], &prot) != TCL_OK) {
+ char *permString = TclGetString(objv[3]);
+ int code = TCL_ERROR;
+ int scanned = TclParseAllWhiteSpace(permString, -1);
+
+ /* Support legacy octal numbers */
+ if ((permString[scanned] == '0')
+ && (permString[scanned+1] >= '0')
+ && (permString[scanned+1] <= '7')) {
+
+ Tcl_Obj *permObj;
+
+ TclNewLiteralStringObj(permObj, "0o");
+ Tcl_AppendToObj(permObj, permString+scanned+1, -1);
+ code = TclGetIntFromObj(NULL, permObj, &prot);
+ Tcl_DecrRefCount(permObj);
+ }
+
+ if ((code == TCL_ERROR)
+ && TclGetIntFromObj(interp, objv[3], &prot) != TCL_OK) {
return TCL_ERROR;
}
}
}
pipeline = 0;
- what = Tcl_GetString(objv[1]);
+ what = TclGetString(objv[1]);
if (what[0] == '|') {
pipeline = 1;
}
@@ -963,50 +1092,47 @@ Tcl_OpenObjCmd(notUsed, interp, objc, objv)
*/
if (!pipeline) {
- chan = Tcl_FSOpenFileChannel(interp, objv[1], modeString, prot);
+ chan = Tcl_FSOpenFileChannel(interp, objv[1], modeString, prot);
} else {
-#ifdef MAC_TCL
- Tcl_AppendResult(interp,
- "command pipelines not supported on Macintosh OS",
- (char *)NULL);
- return TCL_ERROR;
-#else
- int mode, seekFlag, cmdObjc;
- CONST char **cmdArgv;
+ int mode, seekFlag, cmdObjc, binary;
+ const char **cmdArgv;
- if (Tcl_SplitList(interp, what+1, &cmdObjc, &cmdArgv) != TCL_OK) {
- return TCL_ERROR;
- }
+ if (Tcl_SplitList(interp, what+1, &cmdObjc, &cmdArgv) != TCL_OK) {
+ return TCL_ERROR;
+ }
- mode = TclGetOpenMode(interp, modeString, &seekFlag);
- if (mode == -1) {
+ mode = TclGetOpenModeEx(interp, modeString, &seekFlag, &binary);
+ if (mode == -1) {
chan = NULL;
- } else {
+ } else {
int flags = TCL_STDERR | TCL_ENFORCE_MODE;
+
switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) {
- case O_RDONLY:
- flags |= TCL_STDOUT;
- break;
- case O_WRONLY:
- flags |= TCL_STDIN;
- break;
- case O_RDWR:
- flags |= (TCL_STDIN | TCL_STDOUT);
- break;
- default:
- panic("Tcl_OpenCmd: invalid mode value");
- break;
+ case O_RDONLY:
+ flags |= TCL_STDOUT;
+ break;
+ case O_WRONLY:
+ flags |= TCL_STDIN;
+ break;
+ case O_RDWR:
+ flags |= (TCL_STDIN | TCL_STDOUT);
+ break;
+ default:
+ Tcl_Panic("Tcl_OpenCmd: invalid mode value");
+ break;
}
chan = Tcl_OpenCommandChannel(interp, cmdObjc, cmdArgv, flags);
+ if (binary && chan) {
+ Tcl_SetChannelOption(interp, chan, "-translation", "binary");
+ }
}
- ckfree((char *) cmdArgv);
-#endif
+ ckfree((char *) cmdArgv);
}
- if (chan == (Tcl_Channel) NULL) {
- return TCL_ERROR;
+ if (chan == NULL) {
+ return TCL_ERROR;
}
Tcl_RegisterChannel(interp, chan);
- Tcl_AppendResult(interp, Tcl_GetChannelName(chan), (char *) NULL);
+ Tcl_AppendResult(interp, Tcl_GetChannelName(chan), NULL);
return TCL_OK;
}
@@ -1015,40 +1141,38 @@ Tcl_OpenObjCmd(notUsed, interp, objc, objv)
*
* TcpAcceptCallbacksDeleteProc --
*
- * Assocdata cleanup routine called when an interpreter is being
- * deleted to set the interp field of all the accept callback records
- * registered with the interpreter to NULL. This will prevent the
- * interpreter from being used in the future to eval accept scripts.
+ * Assocdata cleanup routine called when an interpreter is being deleted
+ * to set the interp field of all the accept callback records registered
+ * with the interpreter to NULL. This will prevent the interpreter from
+ * being used in the future to eval accept scripts.
*
* Results:
* None.
*
* Side effects:
* Deallocates memory and sets the interp field of all the accept
- * callback records to NULL to prevent this interpreter from being
- * used subsequently to eval accept scripts.
+ * callback records to NULL to prevent this interpreter from being used
+ * subsequently to eval accept scripts.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
static void
-TcpAcceptCallbacksDeleteProc(clientData, interp)
- ClientData clientData; /* Data which was passed when the assocdata
- * was registered. */
- Tcl_Interp *interp; /* Interpreter being deleted - not used. */
+TcpAcceptCallbacksDeleteProc(
+ ClientData clientData, /* Data which was passed when the assocdata
+ * was registered. */
+ Tcl_Interp *interp) /* Interpreter being deleted - not used. */
{
- Tcl_HashTable *hTblPtr;
+ Tcl_HashTable *hTblPtr = clientData;
Tcl_HashEntry *hPtr;
Tcl_HashSearch hSearch;
- AcceptCallback *acceptCallbackPtr;
- hTblPtr = (Tcl_HashTable *) clientData;
for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
- hPtr != (Tcl_HashEntry *) NULL;
- hPtr = Tcl_NextHashEntry(&hSearch)) {
- acceptCallbackPtr = (AcceptCallback *) Tcl_GetHashValue(hPtr);
- acceptCallbackPtr->interp = (Tcl_Interp *) NULL;
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) {
+ AcceptCallback *acceptCallbackPtr = Tcl_GetHashValue(hPtr);
+
+ acceptCallbackPtr->interp = NULL;
}
Tcl_DeleteHashTable(hTblPtr);
ckfree((char *) hTblPtr);
@@ -1059,50 +1183,50 @@ TcpAcceptCallbacksDeleteProc(clientData, interp)
*
* RegisterTcpServerInterpCleanup --
*
- * Registers an accept callback record to have its interp
- * field set to NULL when the interpreter is deleted.
+ * Registers an accept callback record to have its interp field set to
+ * NULL when the interpreter is deleted.
*
* Results:
* None.
*
* Side effects:
- * When, in the future, the interpreter is deleted, the interp
- * field of the accept callback data structure will be set to
- * NULL. This will prevent attempts to eval the accept script
- * in a deleted interpreter.
+ * When, in the future, the interpreter is deleted, the interp field of
+ * the accept callback data structure will be set to NULL. This will
+ * prevent attempts to eval the accept script in a deleted interpreter.
*
*----------------------------------------------------------------------
*/
static void
-RegisterTcpServerInterpCleanup(interp, acceptCallbackPtr)
- Tcl_Interp *interp; /* Interpreter for which we want to be
- * informed of deletion. */
- AcceptCallback *acceptCallbackPtr;
- /* The accept callback record whose
- * interp field we want set to NULL when
- * the interpreter is deleted. */
+RegisterTcpServerInterpCleanup(
+ Tcl_Interp *interp, /* Interpreter for which we want to be
+ * informed of deletion. */
+ AcceptCallback *acceptCallbackPtr)
+ /* The accept callback record whose interp
+ * field we want set to NULL when the
+ * interpreter is deleted. */
{
- Tcl_HashTable *hTblPtr; /* Hash table for accept callback
- * records to smash when the interpreter
- * will be deleted. */
+ Tcl_HashTable *hTblPtr; /* Hash table for accept callback records to
+ * smash when the interpreter will be
+ * deleted. */
Tcl_HashEntry *hPtr; /* Entry for this record. */
- int new; /* Is the entry new? */
+ int isNew; /* Is the entry new? */
- hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp,
- "tclTCPAcceptCallbacks",
- NULL);
- if (hTblPtr == (Tcl_HashTable *) NULL) {
- hTblPtr = (Tcl_HashTable *) ckalloc((unsigned) sizeof(Tcl_HashTable));
- Tcl_InitHashTable(hTblPtr, TCL_ONE_WORD_KEYS);
- (void) Tcl_SetAssocData(interp, "tclTCPAcceptCallbacks",
- TcpAcceptCallbacksDeleteProc, (ClientData) hTblPtr);
- }
- hPtr = Tcl_CreateHashEntry(hTblPtr, (char *) acceptCallbackPtr, &new);
- if (!new) {
- panic("RegisterTcpServerCleanup: damaged accept record table");
- }
- Tcl_SetHashValue(hPtr, (ClientData) acceptCallbackPtr);
+ hTblPtr = (Tcl_HashTable *)
+ Tcl_GetAssocData(interp, "tclTCPAcceptCallbacks", NULL);
+
+ if (hTblPtr == NULL) {
+ hTblPtr = (Tcl_HashTable *) ckalloc((unsigned) sizeof(Tcl_HashTable));
+ Tcl_InitHashTable(hTblPtr, TCL_ONE_WORD_KEYS);
+ (void) Tcl_SetAssocData(interp, "tclTCPAcceptCallbacks",
+ TcpAcceptCallbacksDeleteProc, hTblPtr);
+ }
+
+ hPtr = Tcl_CreateHashEntry(hTblPtr, (char *) acceptCallbackPtr, &isNew);
+ if (!isNew) {
+ Tcl_Panic("RegisterTcpServerCleanup: damaged accept record table");
+ }
+ Tcl_SetHashValue(hPtr, acceptCallbackPtr);
}
/*
@@ -1110,41 +1234,41 @@ RegisterTcpServerInterpCleanup(interp, acceptCallbackPtr)
*
* UnregisterTcpServerInterpCleanupProc --
*
- * Unregister a previously registered accept callback record. The
- * interp field of this record will no longer be set to NULL in
- * the future when the interpreter is deleted.
+ * Unregister a previously registered accept callback record. The interp
+ * field of this record will no longer be set to NULL in the future when
+ * the interpreter is deleted.
*
* Results:
* None.
*
* Side effects:
- * Prevents the interp field of the accept callback record from
- * being set to NULL in the future when the interpreter is deleted.
+ * Prevents the interp field of the accept callback record from being set
+ * to NULL in the future when the interpreter is deleted.
*
*----------------------------------------------------------------------
*/
static void
-UnregisterTcpServerInterpCleanupProc(interp, acceptCallbackPtr)
- Tcl_Interp *interp; /* Interpreter in which the accept callback
- * record was registered. */
- AcceptCallback *acceptCallbackPtr;
- /* The record for which to delete the
- * registration. */
+UnregisterTcpServerInterpCleanupProc(
+ Tcl_Interp *interp, /* Interpreter in which the accept callback
+ * record was registered. */
+ AcceptCallback *acceptCallbackPtr)
+ /* The record for which to delete the
+ * registration. */
{
Tcl_HashTable *hTblPtr;
Tcl_HashEntry *hPtr;
hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp,
- "tclTCPAcceptCallbacks", NULL);
- if (hTblPtr == (Tcl_HashTable *) NULL) {
- return;
+ "tclTCPAcceptCallbacks", NULL);
+ if (hTblPtr == NULL) {
+ return;
}
+
hPtr = Tcl_FindHashEntry(hTblPtr, (char *) acceptCallbackPtr);
- if (hPtr == (Tcl_HashEntry *) NULL) {
- return;
+ if (hPtr != NULL) {
+ Tcl_DeleteHashEntry(hPtr);
}
- Tcl_DeleteHashEntry(hPtr);
}
/*
@@ -1152,8 +1276,8 @@ UnregisterTcpServerInterpCleanupProc(interp, acceptCallbackPtr)
*
* AcceptCallbackProc --
*
- * This callback is invoked by the TCP channel driver when it
- * accepts a new connection from a client on a server socket.
+ * This callback is invoked by the TCP channel driver when it accepts a
+ * new connection from a client on a server socket.
*
* Results:
* None.
@@ -1165,72 +1289,65 @@ UnregisterTcpServerInterpCleanupProc(interp, acceptCallbackPtr)
*/
static void
-AcceptCallbackProc(callbackData, chan, address, port)
- ClientData callbackData; /* The data stored when the callback
- * was created in the call to
- * Tcl_OpenTcpServer. */
- Tcl_Channel chan; /* Channel for the newly accepted
- * connection. */
- char *address; /* Address of client that was
- * accepted. */
- int port; /* Port of client that was accepted. */
+AcceptCallbackProc(
+ ClientData callbackData, /* The data stored when the callback was
+ * created in the call to
+ * Tcl_OpenTcpServer. */
+ Tcl_Channel chan, /* Channel for the newly accepted
+ * connection. */
+ char *address, /* Address of client that was accepted. */
+ int port) /* Port of client that was accepted. */
{
- AcceptCallback *acceptCallbackPtr;
- Tcl_Interp *interp;
- char *script;
- char portBuf[TCL_INTEGER_SPACE];
- int result;
-
- acceptCallbackPtr = (AcceptCallback *) callbackData;
+ AcceptCallback *acceptCallbackPtr = (AcceptCallback *) callbackData;
/*
* Check if the callback is still valid; the interpreter may have gone
* away, this is signalled by setting the interp field of the callback
* data to NULL.
*/
-
- if (acceptCallbackPtr->interp != (Tcl_Interp *) NULL) {
- script = acceptCallbackPtr->script;
- interp = acceptCallbackPtr->interp;
-
- Tcl_Preserve((ClientData) script);
- Tcl_Preserve((ClientData) interp);
+ if (acceptCallbackPtr->interp != NULL) {
+ char portBuf[TCL_INTEGER_SPACE];
+ char *script = acceptCallbackPtr->script;
+ Tcl_Interp *interp = acceptCallbackPtr->interp;
+ int result;
+
+ Tcl_Preserve(script);
+ Tcl_Preserve(interp);
TclFormatInt(portBuf, port);
- Tcl_RegisterChannel(interp, chan);
-
- /*
- * Artificially bump the refcount to protect the channel from
- * being deleted while the script is being evaluated.
- */
-
- Tcl_RegisterChannel((Tcl_Interp *) NULL, chan);
-
- result = Tcl_VarEval(interp, script, " ", Tcl_GetChannelName(chan),
- " ", address, " ", portBuf, (char *) NULL);
- if (result != TCL_OK) {
- Tcl_BackgroundError(interp);
+ Tcl_RegisterChannel(interp, chan);
+
+ /*
+ * Artificially bump the refcount to protect the channel from being
+ * deleted while the script is being evaluated.
+ */
+
+ Tcl_RegisterChannel(NULL, chan);
+
+ result = Tcl_VarEval(interp, script, " ", Tcl_GetChannelName(chan),
+ " ", address, " ", portBuf, NULL);
+ if (result != TCL_OK) {
+ TclBackgroundException(interp, result);
Tcl_UnregisterChannel(interp, chan);
- }
+ }
- /*
- * Decrement the artificially bumped refcount. After this it is
- * not safe anymore to use "chan", because it may now be deleted.
- */
+ /*
+ * Decrement the artificially bumped refcount. After this it is not
+ * safe anymore to use "chan", because it may now be deleted.
+ */
- Tcl_UnregisterChannel((Tcl_Interp *) NULL, chan);
-
- Tcl_Release((ClientData) interp);
- Tcl_Release((ClientData) script);
- } else {
+ Tcl_UnregisterChannel(NULL, chan);
- /*
- * The interpreter has been deleted, so there is no useful
- * way to utilize the client socket - just close it.
- */
+ Tcl_Release(interp);
+ Tcl_Release(script);
+ } else {
+ /*
+ * The interpreter has been deleted, so there is no useful way to
+ * utilize the client socket - just close it.
+ */
- Tcl_Close((Tcl_Interp *) NULL, chan);
+ Tcl_Close(NULL, chan);
}
}
@@ -1239,36 +1356,35 @@ AcceptCallbackProc(callbackData, chan, address, port)
*
* TcpServerCloseProc --
*
- * This callback is called when the TCP server channel for which it
- * was registered is being closed. It informs the interpreter in
- * which the accept script is evaluated (if that interpreter still
- * exists) that this channel no longer needs to be informed if the
- * interpreter is deleted.
+ * This callback is called when the TCP server channel for which it was
+ * registered is being closed. It informs the interpreter in which the
+ * accept script is evaluated (if that interpreter still exists) that
+ * this channel no longer needs to be informed if the interpreter is
+ * deleted.
*
* Results:
* None.
*
* Side effects:
- * In the future, if the interpreter is deleted this channel will
- * no longer be informed.
+ * In the future, if the interpreter is deleted this channel will no
+ * longer be informed.
*
*----------------------------------------------------------------------
*/
static void
-TcpServerCloseProc(callbackData)
- ClientData callbackData; /* The data passed in the call to
- * Tcl_CreateCloseHandler. */
+TcpServerCloseProc(
+ ClientData callbackData) /* The data passed in the call to
+ * Tcl_CreateCloseHandler. */
{
- AcceptCallback *acceptCallbackPtr;
- /* The actual data. */
+ AcceptCallback *acceptCallbackPtr = (AcceptCallback *) callbackData;
+ /* The actual data. */
- acceptCallbackPtr = (AcceptCallback *) callbackData;
- if (acceptCallbackPtr->interp != (Tcl_Interp *) NULL) {
- UnregisterTcpServerInterpCleanupProc(acceptCallbackPtr->interp,
- acceptCallbackPtr);
+ if (acceptCallbackPtr->interp != NULL) {
+ UnregisterTcpServerInterpCleanupProc(acceptCallbackPtr->interp,
+ acceptCallbackPtr);
}
- Tcl_EventuallyFree((ClientData) acceptCallbackPtr->script, TCL_DYNAMIC);
+ Tcl_EventuallyFree(acceptCallbackPtr->script, TCL_DYNAMIC);
ckfree((char *) acceptCallbackPtr);
}
@@ -1277,8 +1393,8 @@ TcpServerCloseProc(callbackData)
*
* Tcl_SocketObjCmd --
*
- * This procedure is invoked to process the "socket" Tcl command.
- * See the user documentation for details on what it does.
+ * This function is invoked to process the "socket" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -1290,127 +1406,115 @@ TcpServerCloseProc(callbackData)
*/
int
-Tcl_SocketObjCmd(notUsed, interp, objc, objv)
- ClientData notUsed; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_SocketObjCmd(
+ ClientData notUsed, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- static CONST char *socketOptions[] = {
- "-async", "-myaddr", "-myport","-server", (char *) NULL
+ static const char *socketOptions[] = {
+ "-async", "-myaddr", "-myport","-server", NULL
};
enum socketOptions {
- SKT_ASYNC, SKT_MYADDR, SKT_MYPORT, SKT_SERVER
+ SKT_ASYNC, SKT_MYADDR, SKT_MYPORT, SKT_SERVER
};
- int optionIndex, a, server, port;
- char *arg, *copyScript, *host, *script;
- char *myaddr = NULL;
- int myport = 0;
- int async = 0;
+ int optionIndex, a, server = 0, port, myport = 0, async = 0;
+ char *host, *script = NULL, *myaddr = NULL;
Tcl_Channel chan;
- AcceptCallback *acceptCallbackPtr;
-
- server = 0;
- script = NULL;
if (TclpHasSockets(interp) != TCL_OK) {
return TCL_ERROR;
}
for (a = 1; a < objc; a++) {
- arg = Tcl_GetString(objv[a]);
+ const char *arg = Tcl_GetString(objv[a]);
+
if (arg[0] != '-') {
break;
}
- if (Tcl_GetIndexFromObj(interp, objv[a], socketOptions,
- "option", TCL_EXACT, &optionIndex) != TCL_OK) {
+ if (Tcl_GetIndexFromObj(interp, objv[a], socketOptions, "option",
+ TCL_EXACT, &optionIndex) != TCL_OK) {
return TCL_ERROR;
}
switch ((enum socketOptions) optionIndex) {
- case SKT_ASYNC: {
- if (server == 1) {
- Tcl_AppendResult(interp,
- "cannot set -async option for server sockets",
- (char *) NULL);
- return TCL_ERROR;
- }
- async = 1;
- break;
+ case SKT_ASYNC:
+ if (server == 1) {
+ Tcl_AppendResult(interp,
+ "cannot set -async option for server sockets", NULL);
+ return TCL_ERROR;
}
- case SKT_MYADDR: {
- a++;
- if (a >= objc) {
- Tcl_AppendResult(interp,
- "no argument given for -myaddr option",
- (char *) NULL);
- return TCL_ERROR;
- }
- myaddr = Tcl_GetString(objv[a]);
- break;
+ async = 1;
+ break;
+ case SKT_MYADDR:
+ a++;
+ if (a >= objc) {
+ Tcl_AppendResult(interp,
+ "no argument given for -myaddr option", NULL);
+ return TCL_ERROR;
}
- case SKT_MYPORT: {
- char *myPortName;
- a++;
- if (a >= objc) {
- Tcl_AppendResult(interp,
- "no argument given for -myport option",
- (char *) NULL);
- return TCL_ERROR;
- }
- myPortName = Tcl_GetString(objv[a]);
- if (TclSockGetPort(interp, myPortName, "tcp", &myport)
- != TCL_OK) {
- return TCL_ERROR;
- }
- break;
+ myaddr = TclGetString(objv[a]);
+ break;
+ case SKT_MYPORT: {
+ char *myPortName;
+
+ a++;
+ if (a >= objc) {
+ Tcl_AppendResult(interp,
+ "no argument given for -myport option", NULL);
+ return TCL_ERROR;
}
- case SKT_SERVER: {
- if (async == 1) {
- Tcl_AppendResult(interp,
- "cannot set -async option for server sockets",
- (char *) NULL);
- return TCL_ERROR;
- }
- server = 1;
- a++;
- if (a >= objc) {
- Tcl_AppendResult(interp,
- "no argument given for -server option",
- (char *) NULL);
- return TCL_ERROR;
- }
- script = Tcl_GetString(objv[a]);
- break;
+ myPortName = TclGetString(objv[a]);
+ if (TclSockGetPort(interp, myPortName, "tcp", &myport) != TCL_OK) {
+ return TCL_ERROR;
}
- default: {
- panic("Tcl_SocketObjCmd: bad option index to SocketOptions");
+ break;
+ }
+ case SKT_SERVER:
+ if (async == 1) {
+ Tcl_AppendResult(interp,
+ "cannot set -async option for server sockets", NULL);
+ return TCL_ERROR;
}
+ server = 1;
+ a++;
+ if (a >= objc) {
+ Tcl_AppendResult(interp,
+ "no argument given for -server option", NULL);
+ return TCL_ERROR;
+ }
+ script = TclGetString(objv[a]);
+ break;
+ default:
+ Tcl_Panic("Tcl_SocketObjCmd: bad option index to SocketOptions");
}
}
if (server) {
- host = myaddr; /* NULL implies INADDR_ANY */
+ host = myaddr; /* NULL implies INADDR_ANY */
if (myport != 0) {
- Tcl_AppendResult(interp, "Option -myport is not valid for servers",
+ Tcl_AppendResult(interp, "option -myport is not valid for servers",
NULL);
return TCL_ERROR;
}
} else if (a < objc) {
- host = Tcl_GetString(objv[a]);
+ host = TclGetString(objv[a]);
a++;
} else {
-wrongNumArgs:
- Tcl_AppendResult(interp, "wrong # args: should be either:\n",
- Tcl_GetString(objv[0]),
- " ?-myaddr addr? ?-myport myport? ?-async? host port\n",
- Tcl_GetString(objv[0]),
- " -server command ?-myaddr addr? port",
- (char *) NULL);
- return TCL_ERROR;
+ Interp *iPtr;
+
+ wrongNumArgs:
+ iPtr = (Interp *) interp;
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "?-myaddr addr? ?-myport myport? ?-async? host port");
+ iPtr->flags |= INTERP_ALTERNATE_WRONG_ARGS;
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "-server command ?-myaddr addr? port");
+ iPtr->flags &= ~INTERP_ALTERNATE_WRONG_ARGS;
+ return TCL_ERROR;
}
if (a == objc-1) {
- if (TclSockGetPort(interp, Tcl_GetString(objv[a]),
- "tcp", &port) != TCL_OK) {
+ if (TclSockGetPort(interp, TclGetString(objv[a]), "tcp",
+ &port) != TCL_OK) {
return TCL_ERROR;
}
} else {
@@ -1418,46 +1522,47 @@ wrongNumArgs:
}
if (server) {
- acceptCallbackPtr = (AcceptCallback *) ckalloc((unsigned)
- sizeof(AcceptCallback));
- copyScript = ckalloc((unsigned) strlen(script) + 1);
- strcpy(copyScript, script);
- acceptCallbackPtr->script = copyScript;
- acceptCallbackPtr->interp = interp;
- chan = Tcl_OpenTcpServer(interp, port, host, AcceptCallbackProc,
- (ClientData) acceptCallbackPtr);
- if (chan == (Tcl_Channel) NULL) {
- ckfree(copyScript);
- ckfree((char *) acceptCallbackPtr);
- return TCL_ERROR;
- }
-
- /*
- * Register with the interpreter to let us know when the
- * interpreter is deleted (by having the callback set the
- * acceptCallbackPtr->interp field to NULL). This is to
- * avoid trying to eval the script in a deleted interpreter.
- */
-
- RegisterTcpServerInterpCleanup(interp, acceptCallbackPtr);
-
- /*
- * Register a close callback. This callback will inform the
- * interpreter (if it still exists) that this channel does not
- * need to be informed when the interpreter is deleted.
- */
-
- Tcl_CreateCloseHandler(chan, TcpServerCloseProc,
- (ClientData) acceptCallbackPtr);
+ AcceptCallback *acceptCallbackPtr = (AcceptCallback *)
+ ckalloc((unsigned) sizeof(AcceptCallback));
+ unsigned len = strlen(script) + 1;
+ char *copyScript = ckalloc(len);
+
+ memcpy(copyScript, script, len);
+ acceptCallbackPtr->script = copyScript;
+ acceptCallbackPtr->interp = interp;
+ chan = Tcl_OpenTcpServer(interp, port, host, AcceptCallbackProc,
+ acceptCallbackPtr);
+ if (chan == NULL) {
+ ckfree(copyScript);
+ ckfree((char *) acceptCallbackPtr);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Register with the interpreter to let us know when the interpreter
+ * is deleted (by having the callback set the interp field of the
+ * acceptCallbackPtr's structure to NULL). This is to avoid trying to
+ * eval the script in a deleted interpreter.
+ */
+
+ RegisterTcpServerInterpCleanup(interp, acceptCallbackPtr);
+
+ /*
+ * Register a close callback. This callback will inform the
+ * interpreter (if it still exists) that this channel does not need to
+ * be informed when the interpreter is deleted.
+ */
+
+ Tcl_CreateCloseHandler(chan, TcpServerCloseProc, acceptCallbackPtr);
} else {
- chan = Tcl_OpenTcpClient(interp, port, host, myaddr, myport, async);
- if (chan == (Tcl_Channel) NULL) {
- return TCL_ERROR;
- }
- }
- Tcl_RegisterChannel(interp, chan);
- Tcl_AppendResult(interp, Tcl_GetChannelName(chan), (char *) NULL);
-
+ chan = Tcl_OpenTcpClient(interp, port, host, myaddr, myport, async);
+ if (chan == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ Tcl_RegisterChannel(interp, chan);
+ Tcl_AppendResult(interp, Tcl_GetChannelName(chan), NULL);
+
return TCL_OK;
}
@@ -1466,32 +1571,30 @@ wrongNumArgs:
*
* Tcl_FcopyObjCmd --
*
- * This procedure is invoked to process the "fcopy" Tcl command.
- * See the user documentation for details on what it does.
+ * This function is invoked to process the "fcopy" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
- * Moves data between two channels and possibly sets up a
- * background copy handler.
+ * Moves data between two channels and possibly sets up a background copy
+ * handler.
*
*----------------------------------------------------------------------
*/
int
-Tcl_FcopyObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_FcopyObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel inChan, outChan;
- char *arg;
- int mode, i;
- int toRead, index;
+ int mode, i, toRead, index;
Tcl_Obj *cmdPtr;
- static CONST char* switches[] = { "-size", "-command", NULL };
+ static const char* switches[] = { "-size", "-command", NULL };
enum { FcopySize, FcopyCommand };
if ((objc < 3) || (objc > 7) || (objc == 4) || (objc == 6)) {
@@ -1501,60 +1604,269 @@ Tcl_FcopyObjCmd(dummy, interp, objc, objv)
}
/*
- * Parse the channel arguments and verify that they are readable
- * or writable, as appropriate.
+ * Parse the channel arguments and verify that they are readable or
+ * writable, as appropriate.
*/
- arg = Tcl_GetString(objv[1]);
- inChan = Tcl_GetChannel(interp, arg, &mode);
- if (inChan == (Tcl_Channel) NULL) {
+ if (TclGetChannelFromObj(interp, objv[1], &inChan, &mode, 0) != TCL_OK) {
return TCL_ERROR;
}
if ((mode & TCL_READABLE) == 0) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "channel \"",
- arg,
- "\" wasn't opened for reading", (char *) NULL);
- return TCL_ERROR;
- }
- arg = Tcl_GetString(objv[2]);
- outChan = Tcl_GetChannel(interp, arg, &mode);
- if (outChan == (Tcl_Channel) NULL) {
+ Tcl_AppendResult(interp, "channel \"", TclGetString(objv[1]),
+ "\" wasn't opened for reading", NULL);
+ return TCL_ERROR;
+ }
+ if (TclGetChannelFromObj(interp, objv[2], &outChan, &mode, 0) != TCL_OK) {
return TCL_ERROR;
}
if ((mode & TCL_WRITABLE) == 0) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "channel \"",
- arg,
- "\" wasn't opened for writing", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "channel \"", TclGetString(objv[2]),
+ "\" wasn't opened for writing", NULL);
+ return TCL_ERROR;
}
toRead = -1;
cmdPtr = NULL;
for (i = 3; i < objc; i += 2) {
if (Tcl_GetIndexFromObj(interp, objv[i], switches, "switch", 0,
- (int *) &index) != TCL_OK) {
+ &index) != TCL_OK) {
return TCL_ERROR;
}
switch (index) {
- case FcopySize:
- if (Tcl_GetIntFromObj(interp, objv[i+1], &toRead) != TCL_OK) {
- return TCL_ERROR;
- }
- if (toRead<0) {
- /*
- * Handle all negative sizes like -1, meaning 'copy all'.
- * By resetting toRead we avoid changes in the
- * core copying functions (which explicitly check
- * for -1 and crash on any other negative value).
- */
- toRead = -1;
- }
- break;
- case FcopyCommand:
- cmdPtr = objv[i+1];
- break;
+ case FcopySize:
+ if (TclGetIntFromObj(interp, objv[i+1], &toRead) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (toRead<0) {
+ /*
+ * Handle all negative sizes like -1, meaning 'copy all'. By
+ * resetting toRead we avoid changes in the core copying
+ * functions (which explicitly check for -1 and crash on any
+ * other negative value).
+ */
+ toRead = -1;
+ }
+ break;
+ case FcopyCommand:
+ cmdPtr = objv[i+1];
+ break;
}
}
return TclCopyChannel(interp, inChan, outChan, toRead, cmdPtr);
}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ChanPendingObjCmd --
+ *
+ * This function is invoked to process the Tcl "chan pending" command
+ * (TIP #287). See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Sets interp's result to the number of bytes of buffered input or
+ * output (depending on whether the first argument is "input" or
+ * "output"), or -1 if the channel wasn't opened for that mode.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+ChanPendingObjCmd(
+ ClientData unused, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tcl_Channel chan;
+ int index, mode;
+ static const char *options[] = {"input", "output", NULL};
+ enum options {PENDING_INPUT, PENDING_OUTPUT};
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "mode channelId");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objv[1], options, "mode", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (TclGetChannelFromObj(interp, objv[2], &chan, &mode, 0) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum options) index) {
+ case PENDING_INPUT:
+ if ((mode & TCL_READABLE) == 0) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(Tcl_InputBuffered(chan)));
+ }
+ break;
+ case PENDING_OUTPUT:
+ if ((mode & TCL_WRITABLE) == 0) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(Tcl_OutputBuffered(chan)));
+ }
+ break;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ChanTruncateObjCmd --
+ *
+ * This function is invoked to process the "chan truncate" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Truncates a channel (or rather a file underlying a channel).
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ChanTruncateObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tcl_Channel chan;
+ Tcl_WideInt length;
+
+ if ((objc < 2) || (objc > 3)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "channelId ?length?");
+ return TCL_ERROR;
+ }
+ if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (objc == 3) {
+ /*
+ * User is supplying an explicit length.
+ */
+
+ if (Tcl_GetWideIntFromObj(interp, objv[2], &length) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (length < 0) {
+ Tcl_AppendResult(interp,
+ "cannot truncate to negative length of file", NULL);
+ return TCL_ERROR;
+ }
+ } else {
+ /*
+ * User wants to truncate to the current file position.
+ */
+
+ length = Tcl_Tell(chan);
+ if (length == Tcl_WideAsLong(-1)) {
+ Tcl_AppendResult(interp,
+ "could not determine current location in \"",
+ TclGetString(objv[1]), "\": ",
+ Tcl_PosixError(interp), NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ if (Tcl_TruncateChannel(chan, length) != TCL_OK) {
+ Tcl_AppendResult(interp, "error during truncate on \"",
+ TclGetString(objv[1]), "\": ",
+ Tcl_PosixError(interp), NULL);
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclInitChanCmd --
+ *
+ * This function is invoked to create the "chan" Tcl command. See the
+ * user documentation for details on what it does.
+ *
+ * Results:
+ * A Tcl command handle.
+ *
+ * Side effects:
+ * None (since nothing is byte-compiled).
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Command
+TclInitChanCmd(
+ Tcl_Interp *interp)
+{
+ /*
+ * Most commands are plugged directly together, but some are done via
+ * alias-like rewriting; [chan configure] is this way for security reasons
+ * (want overwriting of [fconfigure] to control that nicely), and [chan
+ * names] because the functionality isn't available as a separate command
+ * function at the moment.
+ */
+ static const EnsembleImplMap initMap[] = {
+ {"blocked", Tcl_FblockedObjCmd},
+ {"close", Tcl_CloseObjCmd},
+ {"copy", Tcl_FcopyObjCmd},
+ {"create", TclChanCreateObjCmd}, /* TIP #219 */
+ {"eof", Tcl_EofObjCmd},
+ {"event", Tcl_FileEventObjCmd},
+ {"flush", Tcl_FlushObjCmd},
+ {"gets", Tcl_GetsObjCmd},
+ {"pending", ChanPendingObjCmd}, /* TIP #287 */
+ {"postevent", TclChanPostEventObjCmd}, /* TIP #219 */
+ {"puts", Tcl_PutsObjCmd},
+ {"read", Tcl_ReadObjCmd},
+ {"seek", Tcl_SeekObjCmd},
+ {"tell", Tcl_TellObjCmd},
+ {"truncate", ChanTruncateObjCmd}, /* TIP #208 */
+ {NULL}
+ };
+ static const char *extras[] = {
+ "configure", "::fconfigure",
+ "names", "::file channels",
+ NULL
+ };
+ Tcl_Command ensemble;
+ Tcl_Obj *mapObj;
+ int i;
+
+ ensemble = TclMakeEnsemble(interp, "chan", initMap);
+ Tcl_GetEnsembleMappingDict(NULL, ensemble, &mapObj);
+ for (i=0 ; extras[i] ; i+=2) {
+ /*
+ * Can assume that reference counts are all incremented.
+ */
+
+ Tcl_DictObjPut(NULL, mapObj, Tcl_NewStringObj(extras[i], -1),
+ Tcl_NewStringObj(extras[i+1], -1));
+ }
+ Tcl_SetEnsembleMappingDict(interp, ensemble, mapObj);
+ return ensemble;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclIOGT.c b/generic/tclIOGT.c
index 0cd9c67..5dae459 100644
--- a/generic/tclIOGT.c
+++ b/generic/tclIOGT.c
@@ -1,112 +1,101 @@
/*
* tclIOGT.c --
*
- * Implements a generic transformation exposing the underlying API
- * at the script level. Contributed by Andreas Kupries.
+ * Implements a generic transformation exposing the underlying API at the
+ * script level. Contributed by Andreas Kupries.
*
* Copyright (c) 2000 Ajuba Solutions
* Copyright (c) 1999-2000 Andreas Kupries (a.kupries@westend.com)
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
#include "tclIO.h"
-
/*
- * Forward declarations of internal procedures.
- * First the driver procedures of the transformation.
+ * Forward declarations of internal procedures. First the driver procedures of
+ * the transformation.
*/
-static int TransformBlockModeProc _ANSI_ARGS_ ((
- ClientData instanceData, int mode));
-static int TransformCloseProc _ANSI_ARGS_ ((
- ClientData instanceData, Tcl_Interp* interp));
-static int TransformInputProc _ANSI_ARGS_ ((
- ClientData instanceData,
- char* buf, int toRead, int* errorCodePtr));
-static int TransformOutputProc _ANSI_ARGS_ ((
- ClientData instanceData, CONST char *buf,
- int toWrite, int* errorCodePtr));
-static int TransformSeekProc _ANSI_ARGS_ ((
- ClientData instanceData, long offset,
- int mode, int* errorCodePtr));
-static int TransformSetOptionProc _ANSI_ARGS_((
- ClientData instanceData, Tcl_Interp *interp,
- CONST char *optionName, CONST char *value));
-static int TransformGetOptionProc _ANSI_ARGS_((
- ClientData instanceData, Tcl_Interp *interp,
- CONST char *optionName, Tcl_DString *dsPtr));
-static void TransformWatchProc _ANSI_ARGS_ ((
- ClientData instanceData, int mask));
-static int TransformGetFileHandleProc _ANSI_ARGS_ ((
- ClientData instanceData, int direction,
- ClientData* handlePtr));
-static int TransformNotifyProc _ANSI_ARGS_ ((
- ClientData instanceData, int mask));
-static Tcl_WideInt TransformWideSeekProc _ANSI_ARGS_ ((
- ClientData instanceData, Tcl_WideInt offset,
- int mode, int* errorCodePtr));
+static int TransformBlockModeProc(ClientData instanceData,
+ int mode);
+static int TransformCloseProc(ClientData instanceData,
+ Tcl_Interp *interp);
+static int TransformInputProc(ClientData instanceData, char *buf,
+ int toRead, int *errorCodePtr);
+static int TransformOutputProc(ClientData instanceData,
+ const char *buf, int toWrite, int *errorCodePtr);
+static int TransformSeekProc(ClientData instanceData, long offset,
+ int mode, int *errorCodePtr);
+static int TransformSetOptionProc(ClientData instanceData,
+ Tcl_Interp *interp, const char *optionName,
+ const char *value);
+static int TransformGetOptionProc(ClientData instanceData,
+ Tcl_Interp *interp, const char *optionName,
+ Tcl_DString *dsPtr);
+static void TransformWatchProc(ClientData instanceData, int mask);
+static int TransformGetFileHandleProc(ClientData instanceData,
+ int direction, ClientData *handlePtr);
+static int TransformNotifyProc(ClientData instanceData, int mask);
+static Tcl_WideInt TransformWideSeekProc(ClientData instanceData,
+ Tcl_WideInt offset, int mode, int *errorCodePtr);
/*
- * Forward declarations of internal procedures.
- * Secondly the procedures for handling and generating fileeevents.
+ * Forward declarations of internal procedures. Secondly the procedures for
+ * handling and generating fileeevents.
*/
-static void TransformChannelHandlerTimer _ANSI_ARGS_ ((
- ClientData clientData));
+static void TransformChannelHandlerTimer(ClientData clientData);
/*
- * Forward declarations of internal procedures.
- * Third, helper procedures encapsulating essential tasks.
+ * Forward declarations of internal procedures. Third, helper procedures
+ * encapsulating essential tasks.
*/
typedef struct TransformChannelData TransformChannelData;
-static int ExecuteCallback _ANSI_ARGS_ ((
- TransformChannelData* ctrl, Tcl_Interp* interp,
- unsigned char* op, unsigned char* buf,
- int bufLen, int transmit, int preserve));
+static int ExecuteCallback(TransformChannelData *ctrl,
+ Tcl_Interp *interp, unsigned char *op,
+ unsigned char *buf, int bufLen, int transmit,
+ int preserve);
/*
- * Action codes to give to 'ExecuteCallback' (argument 'transmit')
- * confering to the procedure what to do with the result of the script
- * it calls.
+ * Action codes to give to 'ExecuteCallback' (argument 'transmit'), telling
+ * the procedure what to do with the result of the script it calls.
*/
-#define TRANSMIT_DONT (0) /* No transfer to do */
-#define TRANSMIT_DOWN (1) /* Transfer to the underlying channel */
-#define TRANSMIT_SELF (2) /* Transfer into our channel. */
-#define TRANSMIT_IBUF (3) /* Transfer to internal input buffer */
-#define TRANSMIT_NUM (4) /* Transfer number to 'maxRead' */
+#define TRANSMIT_DONT 0 /* No transfer to do. */
+#define TRANSMIT_DOWN 1 /* Transfer to the underlying channel. */
+#define TRANSMIT_SELF 2 /* Transfer into our channel. */
+#define TRANSMIT_IBUF 3 /* Transfer to internal input buffer. */
+#define TRANSMIT_NUM 4 /* Transfer number to 'maxRead'. */
/*
- * Codes for 'preserve' of 'ExecuteCallback'
+ * Codes for 'preserve' of 'ExecuteCallback'.
*/
-#define P_PRESERVE (1)
-#define P_NO_PRESERVE (0)
+#define P_PRESERVE 1
+#define P_NO_PRESERVE 0
/*
- * Strings for the action codes delivered to the script implementing
- * a transformation. Argument 'op' of 'ExecuteCallback'.
+ * Strings for the action codes delivered to the script implementing a
+ * transformation. Argument 'op' of 'ExecuteCallback'.
*/
-#define A_CREATE_WRITE (UCHARP ("create/write"))
-#define A_DELETE_WRITE (UCHARP ("delete/write"))
-#define A_FLUSH_WRITE (UCHARP ("flush/write"))
-#define A_WRITE (UCHARP ("write"))
+#define A_CREATE_WRITE (UCHARP("create/write"))
+#define A_DELETE_WRITE (UCHARP("delete/write"))
+#define A_FLUSH_WRITE (UCHARP("flush/write"))
+#define A_WRITE (UCHARP("write"))
-#define A_CREATE_READ (UCHARP ("create/read"))
-#define A_DELETE_READ (UCHARP ("delete/read"))
-#define A_FLUSH_READ (UCHARP ("flush/read"))
-#define A_READ (UCHARP ("read"))
+#define A_CREATE_READ (UCHARP("create/read"))
+#define A_DELETE_READ (UCHARP("delete/read"))
+#define A_FLUSH_READ (UCHARP("flush/read"))
+#define A_READ (UCHARP("read"))
-#define A_QUERY_MAXREAD (UCHARP ("query/maxRead"))
-#define A_CLEAR_READ (UCHARP ("clear/read"))
+#define A_QUERY_MAXREAD (UCHARP("query/maxRead"))
+#define A_CLEAR_READ (UCHARP("clear/read"))
/*
* Management of a simple buffer.
@@ -114,73 +103,75 @@ static int ExecuteCallback _ANSI_ARGS_ ((
typedef struct ResultBuffer ResultBuffer;
-static void ResultClear _ANSI_ARGS_ ((ResultBuffer* r));
-static void ResultInit _ANSI_ARGS_ ((ResultBuffer* r));
-static int ResultLength _ANSI_ARGS_ ((ResultBuffer* r));
-static int ResultCopy _ANSI_ARGS_ ((ResultBuffer* r,
- unsigned char* buf, int toRead));
-static void ResultAdd _ANSI_ARGS_ ((ResultBuffer* r,
- unsigned char* buf, int toWrite));
+static inline void ResultClear(ResultBuffer *r);
+static inline void ResultInit(ResultBuffer *r);
+static inline int ResultEmpty(ResultBuffer *r);
+static inline int ResultCopy(ResultBuffer *r, unsigned char *buf,
+ size_t toRead);
+static inline void ResultAdd(ResultBuffer *r, unsigned char *buf,
+ size_t toWrite);
/*
- * This structure describes the channel type structure for tcl based
+ * This structure describes the channel type structure for Tcl-based
* transformations.
*/
static Tcl_ChannelType transformChannelType = {
- "transform", /* Type name. */
- TCL_CHANNEL_VERSION_3,
- TransformCloseProc, /* Close proc. */
- TransformInputProc, /* Input proc. */
- TransformOutputProc, /* Output proc. */
- TransformSeekProc, /* Seek proc. */
- TransformSetOptionProc, /* Set option proc. */
- TransformGetOptionProc, /* Get option proc. */
- TransformWatchProc, /* Initialize notifier. */
- TransformGetFileHandleProc, /* Get OS handles out of channel. */
- NULL, /* close2proc */
- TransformBlockModeProc, /* Set blocking/nonblocking mode.*/
- NULL, /* Flush proc. */
- TransformNotifyProc, /* Handling of events bubbling up */
- TransformWideSeekProc, /* Wide seek proc */
+ "transform", /* Type name. */
+ TCL_CHANNEL_VERSION_5, /* v5 channel */
+ TransformCloseProc, /* Close proc. */
+ TransformInputProc, /* Input proc. */
+ TransformOutputProc, /* Output proc. */
+ TransformSeekProc, /* Seek proc. */
+ TransformSetOptionProc, /* Set option proc. */
+ TransformGetOptionProc, /* Get option proc. */
+ TransformWatchProc, /* Initialize notifier. */
+ TransformGetFileHandleProc, /* Get OS handles out of channel. */
+ NULL, /* close2proc */
+ TransformBlockModeProc, /* Set blocking/nonblocking mode.*/
+ NULL, /* Flush proc. */
+ TransformNotifyProc, /* Handling of events bubbling up. */
+ TransformWideSeekProc, /* Wide seek proc. */
+ NULL, /* Thread action. */
+ NULL, /* Truncate. */
};
/*
* Possible values for 'flags' field in control structure, see below.
*/
-#define CHANNEL_ASYNC (1<<0) /* non-blocking mode */
+#define CHANNEL_ASYNC (1<<0) /* Non-blocking mode. */
/*
- * Definition of the structure containing the information about the
- * internal input buffer.
+ * Definition of the structure containing the information about the internal
+ * input buffer.
*/
struct ResultBuffer {
- unsigned char* buf; /* Reference to the buffer area */
- int allocated; /* Allocated size of the buffer area */
- int used; /* Number of bytes in the buffer, <= allocated */
+ unsigned char *buf; /* Reference to the buffer area. */
+ size_t allocated; /* Allocated size of the buffer area. */
+ size_t used; /* Number of bytes in the buffer, no more than
+ * number allocated. */
};
/*
- * Additional bytes to allocate during buffer expansion
+ * Additional bytes to allocate during buffer expansion.
*/
-#define INCREMENT (512)
+#define INCREMENT 512
/*
- * Number of milliseconds to wait before firing an event to flush
- * out information waiting in buffers (fileevent support).
+ * Number of milliseconds to wait before firing an event to flush out
+ * information waiting in buffers (fileevent support).
*/
-#define FLUSH_DELAY (5)
+#define FLUSH_DELAY 5
/*
* Convenience macro to make some casts easier to use.
*/
-#define UCHARP(x) ((unsigned char*) (x))
-#define NO_INTERP ((Tcl_Interp*) NULL)
+#define UCHARP(x) ((unsigned char *) (x))
/*
* Definition of a structure used by all transformations generated here to
@@ -188,48 +179,47 @@ struct ResultBuffer {
*/
struct TransformChannelData {
-
/*
* General section. Data to integrate the transformation into the channel
* system.
*/
- Tcl_Channel self; /* Our own Channel handle */
- int readIsFlushed; /* Flag to note wether in.flushProc was called or not
- */
- int flags; /* Currently CHANNEL_ASYNC or zero */
- int watchMask; /* Current watch/event/interest mask */
- int mode; /* mode of parent channel, OR'ed combination of
- * TCL_READABLE, TCL_WRITABLE */
- Tcl_TimerToken timer; /* Timer for automatic flushing of information
- * sitting in an internal buffer. Required for full
- * fileevent support */
+ Tcl_Channel self; /* Our own Channel handle. */
+ int readIsFlushed; /* Flag to note whether in.flushProc was
+ * called or not. */
+ int flags; /* Currently CHANNEL_ASYNC or zero. */
+ int watchMask; /* Current watch/event/interest mask. */
+ int mode; /* Mode of parent channel, OR'ed combination
+ * of TCL_READABLE, TCL_WRITABLE. */
+ Tcl_TimerToken timer; /* Timer for automatic flushing of information
+ * sitting in an internal buffer. Required for
+ * full fileevent support. */
+
/*
* Transformation specific data.
*/
- int maxRead; /* Maximum allowed number of bytes to read, as
- * given to us by the tcl script implementing the
- * transformation. */
- Tcl_Interp* interp; /* Reference to the interpreter which created the
- * transformation. Used to execute the code
- * below. */
- Tcl_Obj* command; /* Tcl code to execute for a buffer */
- ResultBuffer result; /* Internal buffer used to store the result of a
- * transformation of incoming data. Additionally
- * serves as buffer of all data not yet consumed by
- * the reader. */
+ int maxRead; /* Maximum allowed number of bytes to read, as
+ * given to us by the Tcl script implementing
+ * the transformation. */
+ Tcl_Interp *interp; /* Reference to the interpreter which created
+ * the transformation. Used to execute the
+ * code below. */
+ Tcl_Obj *command; /* Tcl code to execute for a buffer */
+ ResultBuffer result; /* Internal buffer used to store the result of
+ * a transformation of incoming data. Also
+ * serves as buffer of all data not yet
+ * consumed by the reader. */
};
-
/*
*----------------------------------------------------------------------
*
* TclChannelTransform --
*
- * Implements the Tcl "testchannel transform" debugging command.
- * This is part of the testing environment. This sets up a tcl
- * script (cmdObjPtr) to be used as a transform on the channel.
+ * Implements the Tcl "testchannel transform" debugging command. This is
+ * part of the testing environment. This sets up a tcl script (cmdObjPtr)
+ * to be used as a transform on the channel.
*
* Results:
* A standard Tcl result.
@@ -242,69 +232,63 @@ struct TransformChannelData {
/* ARGSUSED */
int
-TclChannelTransform(interp, chan, cmdObjPtr)
- Tcl_Interp *interp; /* Interpreter for result. */
- Tcl_Channel chan; /* Channel to transform. */
- Tcl_Obj *cmdObjPtr; /* Script to use for transform. */
+TclChannelTransform(
+ Tcl_Interp *interp, /* Interpreter for result. */
+ Tcl_Channel chan, /* Channel to transform. */
+ Tcl_Obj *cmdObjPtr) /* Script to use for transform. */
{
- Channel *chanPtr; /* The actual channel. */
- ChannelState *statePtr; /* state info for channel */
- int mode; /* rw mode of the channel */
- TransformChannelData *dataPtr;
- int res;
- Tcl_DString ds;
-
- if (chan == (Tcl_Channel) NULL) {
+ Channel *chanPtr; /* The actual channel. */
+ ChannelState *statePtr; /* State info for channel. */
+ int mode; /* Read/write mode of the channel. */
+ TransformChannelData *dataPtr;
+ Tcl_DString ds;
+
+ if (chan == NULL) {
return TCL_ERROR;
}
- chanPtr = (Channel *) chan;
- statePtr = chanPtr->state;
- chanPtr = statePtr->topChanPtr;
- chan = (Tcl_Channel) chanPtr;
- mode = (statePtr->flags & (TCL_READABLE|TCL_WRITABLE));
+
+ chanPtr = (Channel *) chan;
+ statePtr = chanPtr->state;
+ chanPtr = statePtr->topChanPtr;
+ chan = (Tcl_Channel) chanPtr;
+ mode = (statePtr->flags & (TCL_READABLE|TCL_WRITABLE));
/*
- * Now initialize the transformation state and stack it upon the
- * specified channel. One of the necessary things to do is to
- * retrieve the blocking regime of the underlying channel and to
- * use the same for us too.
+ * Now initialize the transformation state and stack it upon the specified
+ * channel. One of the necessary things to do is to retrieve the blocking
+ * regime of the underlying channel and to use the same for us too.
*/
- dataPtr = (TransformChannelData*) ckalloc(sizeof(TransformChannelData));
+ dataPtr = (TransformChannelData *) ckalloc(sizeof(TransformChannelData));
- Tcl_DStringInit (&ds);
+ Tcl_DStringInit(&ds);
Tcl_GetChannelOption(interp, chan, "-blocking", &ds);
-
dataPtr->readIsFlushed = 0;
- dataPtr->flags = 0;
-
+ dataPtr->flags = 0;
if (ds.string[0] == '0') {
dataPtr->flags |= CHANNEL_ASYNC;
}
-
- Tcl_DStringFree (&ds);
-
- dataPtr->self = chan;
- dataPtr->watchMask = 0;
- dataPtr->mode = mode;
- dataPtr->timer = (Tcl_TimerToken) NULL;
- dataPtr->maxRead = 4096; /* Initial value not relevant */
- dataPtr->interp = interp;
- dataPtr->command = cmdObjPtr;
-
+ Tcl_DStringFree(&ds);
+
+ dataPtr->self = chan;
+ dataPtr->watchMask = 0;
+ dataPtr->mode = mode;
+ dataPtr->timer = NULL;
+ dataPtr->maxRead = 4096; /* Initial value not relevant. */
+ dataPtr->interp = interp;
+ dataPtr->command = cmdObjPtr;
Tcl_IncrRefCount(dataPtr->command);
ResultInit(&dataPtr->result);
- dataPtr->self = Tcl_StackChannel(interp, &transformChannelType,
- (ClientData) dataPtr, mode, chan);
- if (dataPtr->self == (Tcl_Channel) NULL) {
+ dataPtr->self = Tcl_StackChannel(interp, &transformChannelType, dataPtr,
+ mode, chan);
+ if (dataPtr->self == NULL) {
Tcl_AppendResult(interp, "\nfailed to stack channel \"",
- Tcl_GetChannelName(chan), "\"", (char *) NULL);
-
+ Tcl_GetChannelName(chan), "\"", NULL);
Tcl_DecrRefCount(dataPtr->command);
ResultClear(&dataPtr->result);
- ckfree((VOID *) dataPtr);
+ ckfree((char *) dataPtr);
return TCL_ERROR;
}
@@ -312,65 +296,62 @@ TclChannelTransform(interp, chan, cmdObjPtr)
* At last initialize the transformation at the script level.
*/
- if (dataPtr->mode & TCL_WRITABLE) {
- res = ExecuteCallback (dataPtr, NO_INTERP, A_CREATE_WRITE,
- NULL, 0, TRANSMIT_DONT, P_NO_PRESERVE);
-
- if (res != TCL_OK) {
- Tcl_UnstackChannel(interp, chan);
- return TCL_ERROR;
- }
+ if ((dataPtr->mode & TCL_WRITABLE) && ExecuteCallback(dataPtr, NULL,
+ A_CREATE_WRITE, NULL, 0, TRANSMIT_DONT, P_NO_PRESERVE) != TCL_OK){
+ Tcl_UnstackChannel(interp, chan);
+ return TCL_ERROR;
}
- if (dataPtr->mode & TCL_READABLE) {
- res = ExecuteCallback (dataPtr, NO_INTERP, A_CREATE_READ,
- NULL, 0, TRANSMIT_DONT, P_NO_PRESERVE);
-
- if (res != TCL_OK) {
- ExecuteCallback (dataPtr, NO_INTERP, A_DELETE_WRITE,
- NULL, 0, TRANSMIT_DONT, P_NO_PRESERVE);
-
- Tcl_UnstackChannel(interp, chan);
- return TCL_ERROR;
- }
+ if ((dataPtr->mode & TCL_READABLE) && ExecuteCallback(dataPtr, NULL,
+ A_CREATE_READ, NULL, 0, TRANSMIT_DONT, P_NO_PRESERVE) != TCL_OK) {
+ ExecuteCallback(dataPtr, NULL, A_DELETE_WRITE, NULL, 0, TRANSMIT_DONT,
+ P_NO_PRESERVE);
+ Tcl_UnstackChannel(interp, chan);
+ return TCL_ERROR;
}
return TCL_OK;
}
/*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*
- * ExecuteCallback --
+ * ExecuteCallback --
*
- * Executes the defined callback for buffer and
- * operation.
+ * Executes the defined callback for buffer and operation.
*
- * Sideeffects:
- * As of the executed tcl script.
+ * Side effects:
+ * As of the executed tcl script.
*
- * Result:
- * A standard TCL error code. In case of an
- * error a message is left in the result area
- * of the specified interpreter.
+ * Result:
+ * A standard TCL error code. In case of an error a message is left in
+ * the result area of the specified interpreter.
*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*/
static int
-ExecuteCallback (dataPtr, interp, op, buf, bufLen, transmit, preserve)
- TransformChannelData* dataPtr; /* Transformation with the callback */
- Tcl_Interp* interp; /* Current interpreter, possibly NULL */
- unsigned char* op; /* Operation invoking the callback */
- unsigned char* buf; /* Buffer to give to the script. */
- int bufLen; /* Ands its length */
- int transmit; /* Flag, determines whether the result
- * of the callback is sent to the
- * underlying channel or not. */
- int preserve; /* Flag. If true the procedure will
- * preserver the result state of all
- * accessed interpreters. */
+ExecuteCallback(
+ TransformChannelData *dataPtr,
+ /* Transformation with the callback. */
+ Tcl_Interp *interp, /* Current interpreter, possibly NULL. */
+ unsigned char *op, /* Operation invoking the callback. */
+ unsigned char *buf, /* Buffer to give to the script. */
+ int bufLen, /* And its length. */
+ int transmit, /* Flag, determines whether the result of the
+ * callback is sent to the underlying channel
+ * or not. */
+ int preserve) /* Flag. If true the procedure will preserve
+ * the result state of all accessed
+ * interpreters. */
{
+ Tcl_Obj *resObj; /* See below, switch (transmit). */
+ int resLen;
+ unsigned char *resBuf;
+ Tcl_InterpState state = NULL;
+ int res = TCL_OK;
+ Tcl_Obj *command = Tcl_DuplicateObj(dataPtr->command);
+
/*
* Step 1, create the complete command to execute. Do this by appending
* operation and buffer to operate upon to a copy of the callback
@@ -379,72 +360,43 @@ ExecuteCallback (dataPtr, interp, op, buf, bufLen, transmit, preserve)
* arguments. Feather's curried commands would come in handy here.
*/
- Tcl_Obj* resObj; /* See below, switch (transmit) */
- int resLen;
- unsigned char* resBuf;
- Tcl_SavedResult ciSave;
- int res = TCL_OK;
- Tcl_Obj* command = Tcl_DuplicateObj (dataPtr->command);
- Tcl_Obj* temp;
-
- if (preserve) {
- Tcl_SaveResult (dataPtr->interp, &ciSave);
- }
-
- if (command == (Tcl_Obj*) NULL) {
- /* Memory allocation problem */
- res = TCL_ERROR;
- goto cleanup;
+ if (preserve == P_PRESERVE) {
+ state = Tcl_SaveInterpState(dataPtr->interp, res);
}
Tcl_IncrRefCount(command);
-
- temp = Tcl_NewStringObj((char*) op, -1);
-
- if (temp == (Tcl_Obj*) NULL) {
- /* Memory allocation problem */
- res = TCL_ERROR;
- goto cleanup;
- }
-
- res = Tcl_ListObjAppendElement(dataPtr->interp, command, temp);
-
- if (res != TCL_OK)
+ res = Tcl_ListObjAppendElement(dataPtr->interp, command,
+ Tcl_NewStringObj((char *) op, -1));
+ if (res != TCL_OK) {
goto cleanup;
+ }
/*
- * Use a byte-array to prevent the misinterpretation of binary data
- * coming through as UTF while at the tcl level.
+ * Use a byte-array to prevent the misinterpretation of binary data coming
+ * through as UTF while at the tcl level.
*/
- temp = Tcl_NewByteArrayObj(buf, bufLen);
-
- if (temp == (Tcl_Obj*) NULL) {
- /* Memory allocation problem */
- res = TCL_ERROR;
- goto cleanup;
+ res = Tcl_ListObjAppendElement(dataPtr->interp, command,
+ Tcl_NewByteArrayObj(buf, bufLen));
+ if (res != TCL_OK) {
+ goto cleanup;
}
- res = Tcl_ListObjAppendElement (dataPtr->interp, command, temp);
-
- if (res != TCL_OK)
- goto cleanup;
-
/*
- * Step 2, execute the command at the global level of the interpreter
- * used to create the transformation. Destroy the command afterward.
- * If an error occured and the current interpreter is defined and not
- * equal to the interpreter for the callback, then copy the error
- * message into current interpreter. Don't copy if in preservation mode.
+ * Step 2, execute the command at the global level of the interpreter used
+ * to create the transformation. Destroy the command afterward. If an
+ * error occured and the current interpreter is defined and not equal to
+ * the interpreter for the callback, then copy the error message into
+ * current interpreter. Don't copy if in preservation mode.
*/
res = Tcl_EvalObjEx(dataPtr->interp, command, TCL_EVAL_GLOBAL);
- Tcl_DecrRefCount (command);
- command = (Tcl_Obj*) NULL;
+ Tcl_DecrRefCount(command);
+ command = NULL;
- if ((res != TCL_OK) && (interp != NO_INTERP) &&
- (dataPtr->interp != interp) && !preserve) {
- Tcl_SetObjResult(interp, Tcl_GetObjResult(dataPtr->interp));
+ if ((res != TCL_OK) && (interp != NULL) && (dataPtr->interp != interp)
+ && (preserve == P_NO_PRESERVE)) {
+ Tcl_SetObjResult(interp, Tcl_GetObjResult(dataPtr->interp));
return res;
}
@@ -454,121 +406,115 @@ ExecuteCallback (dataPtr, interp, op, buf, bufLen, transmit, preserve)
*/
switch (transmit) {
- case TRANSMIT_DONT:
- /* nothing to do */
- break;
-
- case TRANSMIT_DOWN:
- resObj = Tcl_GetObjResult(dataPtr->interp);
- resBuf = (unsigned char*) Tcl_GetByteArrayFromObj(resObj, &resLen);
- Tcl_WriteRaw(Tcl_GetStackedChannel(dataPtr->self),
- (char*) resBuf, resLen);
- break;
-
- case TRANSMIT_SELF:
- resObj = Tcl_GetObjResult (dataPtr->interp);
- resBuf = (unsigned char*) Tcl_GetByteArrayFromObj(resObj, &resLen);
- Tcl_WriteRaw(dataPtr->self, (char*) resBuf, resLen);
- break;
-
- case TRANSMIT_IBUF:
- resObj = Tcl_GetObjResult (dataPtr->interp);
- resBuf = (unsigned char*) Tcl_GetByteArrayFromObj(resObj, &resLen);
- ResultAdd(&dataPtr->result, resBuf, resLen);
- break;
-
- case TRANSMIT_NUM:
- /* Interpret result as integer number */
- resObj = Tcl_GetObjResult (dataPtr->interp);
- Tcl_GetIntFromObj(dataPtr->interp, resObj, &dataPtr->maxRead);
- break;
+ case TRANSMIT_DONT:
+ /* nothing to do */
+ break;
+
+ case TRANSMIT_DOWN:
+ resObj = Tcl_GetObjResult(dataPtr->interp);
+ resBuf = Tcl_GetByteArrayFromObj(resObj, &resLen);
+ Tcl_WriteRaw(Tcl_GetStackedChannel(dataPtr->self), (char *) resBuf,
+ resLen);
+ break;
+
+ case TRANSMIT_SELF:
+ resObj = Tcl_GetObjResult(dataPtr->interp);
+ resBuf = Tcl_GetByteArrayFromObj(resObj, &resLen);
+ Tcl_WriteRaw(dataPtr->self, (char *) resBuf, resLen);
+ break;
+
+ case TRANSMIT_IBUF:
+ resObj = Tcl_GetObjResult(dataPtr->interp);
+ resBuf = Tcl_GetByteArrayFromObj(resObj, &resLen);
+ ResultAdd(&dataPtr->result, resBuf, resLen);
+ break;
+
+ case TRANSMIT_NUM:
+ /*
+ * Interpret result as integer number.
+ */
+
+ resObj = Tcl_GetObjResult(dataPtr->interp);
+ TclGetIntFromObj(dataPtr->interp, resObj, &dataPtr->maxRead);
+ break;
}
Tcl_ResetResult(dataPtr->interp);
-
- if (preserve) {
- Tcl_RestoreResult(dataPtr->interp, &ciSave);
+ if (preserve == P_PRESERVE) {
+ (void) Tcl_RestoreInterpState(dataPtr->interp, state);
}
-
return res;
- cleanup:
- if (preserve) {
- Tcl_RestoreResult(dataPtr->interp, &ciSave);
+ cleanup:
+ if (preserve == P_PRESERVE) {
+ (void) Tcl_RestoreInterpState(dataPtr->interp, state);
}
-
- if (command != (Tcl_Obj*) NULL) {
- Tcl_DecrRefCount(command);
+ if (command != NULL) {
+ Tcl_DecrRefCount(command);
}
-
return res;
}
/*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*
- * TransformBlockModeProc --
+ * TransformBlockModeProc --
*
- * Trap handler. Called by the generic IO system
- * during option processing to change the blocking
- * mode of the channel.
+ * Trap handler. Called by the generic IO system during option processing
+ * to change the blocking mode of the channel.
*
- * Sideeffects:
- * Forwards the request to the underlying
- * channel.
+ * Side effects:
+ * Forwards the request to the underlying channel.
*
- * Result:
- * 0 if successful, errno when failed.
+ * Result:
+ * 0 if successful, errno when failed.
*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*/
static int
-TransformBlockModeProc (instanceData, mode)
- ClientData instanceData; /* State of transformation */
- int mode; /* New blocking mode */
+TransformBlockModeProc(
+ ClientData instanceData, /* State of transformation. */
+ int mode) /* New blocking mode. */
{
- TransformChannelData* dataPtr = (TransformChannelData*) instanceData;
+ TransformChannelData *dataPtr = instanceData;
if (mode == TCL_MODE_NONBLOCKING) {
- dataPtr->flags |= CHANNEL_ASYNC;
+ dataPtr->flags |= CHANNEL_ASYNC;
} else {
- dataPtr->flags &= ~(CHANNEL_ASYNC);
+ dataPtr->flags &= ~CHANNEL_ASYNC;
}
return 0;
}
/*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*
- * TransformCloseProc --
+ * TransformCloseProc --
*
- * Trap handler. Called by the generic IO system
- * during destruction of the transformation channel.
+ * Trap handler. Called by the generic IO system during destruction of
+ * the transformation channel.
*
- * Sideeffects:
- * Releases the memory allocated in
- * 'Tcl_TransformObjCmd'.
+ * Side effects:
+ * Releases the memory allocated in 'Tcl_TransformObjCmd'.
*
- * Result:
- * None.
+ * Result:
+ * None.
*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*/
static int
-TransformCloseProc (instanceData, interp)
- ClientData instanceData;
- Tcl_Interp* interp;
+TransformCloseProc(
+ ClientData instanceData,
+ Tcl_Interp *interp)
{
- TransformChannelData* dataPtr = (TransformChannelData*) instanceData;
-
- /*
- * Important: In this procedure 'dataPtr->self' already points to
- * the underlying channel.
- */
+ TransformChannelData *dataPtr = instanceData;
/*
+ * Important: In this procedure 'dataPtr->self' already points to the
+ * underlying channel.
+ *
* There is no need to cancel an existing channel handler, this is already
* done. Either by 'Tcl_UnstackChannel' or by the general cleanup in
* 'Tcl_Close'.
@@ -577,81 +523,82 @@ TransformCloseProc (instanceData, interp)
* removed channel.
*/
- if (dataPtr->timer != (Tcl_TimerToken) NULL) {
- Tcl_DeleteTimerHandler (dataPtr->timer);
- dataPtr->timer = (Tcl_TimerToken) NULL;
+ if (dataPtr->timer != NULL) {
+ Tcl_DeleteTimerHandler(dataPtr->timer);
+ dataPtr->timer = NULL;
}
/*
* Now flush data waiting in internal buffers to output and input. The
- * input must be done despite the fact that there is no real receiver
- * for it anymore. But the scripts might have sideeffects other parts
- * of the system rely on (f.e. signaling the close to interested parties).
+ * input must be done despite the fact that there is no real receiver for
+ * it anymore. But the scripts might have sideeffects other parts of the
+ * system rely on (f.e. signaling the close to interested parties).
*/
if (dataPtr->mode & TCL_WRITABLE) {
- ExecuteCallback (dataPtr, interp, A_FLUSH_WRITE,
- NULL, 0, TRANSMIT_DOWN, 1);
+ ExecuteCallback(dataPtr, interp, A_FLUSH_WRITE, NULL, 0,
+ TRANSMIT_DOWN, P_PRESERVE);
}
if ((dataPtr->mode & TCL_READABLE) && !dataPtr->readIsFlushed) {
dataPtr->readIsFlushed = 1;
- ExecuteCallback (dataPtr, interp, A_FLUSH_READ,
- NULL, 0, TRANSMIT_IBUF, 1);
+ ExecuteCallback(dataPtr, interp, A_FLUSH_READ, NULL, 0, TRANSMIT_IBUF,
+ P_PRESERVE);
}
if (dataPtr->mode & TCL_WRITABLE) {
- ExecuteCallback (dataPtr, interp, A_DELETE_WRITE,
- NULL, 0, TRANSMIT_DONT, 1);
+ ExecuteCallback(dataPtr, interp, A_DELETE_WRITE, NULL, 0,
+ TRANSMIT_DONT, P_PRESERVE);
}
-
if (dataPtr->mode & TCL_READABLE) {
- ExecuteCallback (dataPtr, interp, A_DELETE_READ,
- NULL, 0, TRANSMIT_DONT, 1);
+ ExecuteCallback(dataPtr, interp, A_DELETE_READ, NULL, 0,
+ TRANSMIT_DONT, P_PRESERVE);
}
/*
- * General cleanup
+ * General cleanup.
*/
ResultClear(&dataPtr->result);
Tcl_DecrRefCount(dataPtr->command);
- ckfree((VOID*) dataPtr);
-
+ ckfree((char *) dataPtr);
return TCL_OK;
}
/*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*
- * TransformInputProc --
+ * TransformInputProc --
*
* Called by the generic IO system to convert read data.
*
- * Sideeffects:
- * As defined by the conversion.
+ * Side effects:
+ * As defined by the conversion.
*
- * Result:
- * A transformed buffer.
+ * Result:
+ * A transformed buffer.
*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*/
static int
-TransformInputProc (instanceData, buf, toRead, errorCodePtr)
- ClientData instanceData;
- char* buf;
- int toRead;
- int* errorCodePtr;
+TransformInputProc(
+ ClientData instanceData,
+ char *buf,
+ int toRead,
+ int *errorCodePtr)
{
- TransformChannelData* dataPtr = (TransformChannelData*) instanceData;
- int gotBytes, read, res, copied;
+ TransformChannelData *dataPtr = instanceData;
+ int gotBytes, read, copied;
Tcl_Channel downChan;
- /* should assert (dataPtr->mode & TCL_READABLE) */
+ /*
+ * Should assert(dataPtr->mode & TCL_READABLE);
+ */
if (toRead == 0) {
- /* Catch a no-op.
+ /*
+ * Catch a no-op.
*/
return 0;
}
@@ -660,113 +607,116 @@ TransformInputProc (instanceData, buf, toRead, errorCodePtr)
downChan = Tcl_GetStackedChannel(dataPtr->self);
while (toRead > 0) {
- /*
+ /*
* Loop until the request is satisfied (or no data is available from
* below, possibly EOF).
*/
- copied = ResultCopy (&dataPtr->result, UCHARP (buf), toRead);
-
- toRead -= copied;
- buf += copied;
+ copied = ResultCopy(&dataPtr->result, UCHARP(buf), toRead);
+ toRead -= copied;
+ buf += copied;
gotBytes += copied;
if (toRead == 0) {
- /* The request was completely satisfied from our buffers.
- * We can break out of the loop and return to the caller.
+ /*
+ * The request was completely satisfied from our buffers. We can
+ * break out of the loop and return to the caller.
*/
+
return gotBytes;
}
/*
- * Length (dataPtr->result) == 0, toRead > 0 here . Use the incoming
- * 'buf'! as target to store the intermediary information read
- * from the underlying channel.
+ * Length (dataPtr->result) == 0, toRead > 0 here. Use the incoming
+ * 'buf'! as target to store the intermediary information read from
+ * the underlying channel.
*
- * Ask the tcl level how much data it allows us to read from
- * the underlying channel. This feature allows the transform to
- * signal EOF upstream although there is none downstream. Useful
- * to control an unbounded 'fcopy', either through counting bytes,
- * or by pattern matching.
+ * Ask the tcl level how much data it allows us to read from the
+ * underlying channel. This feature allows the transform to signal EOF
+ * upstream although there is none downstream. Useful to control an
+ * unbounded 'fcopy', either through counting bytes, or by pattern
+ * matching.
*/
- ExecuteCallback (dataPtr, NO_INTERP, A_QUERY_MAXREAD,
- NULL, 0, TRANSMIT_NUM /* -> maxRead */, 1);
+ ExecuteCallback(dataPtr, NULL, A_QUERY_MAXREAD, NULL, 0,
+ TRANSMIT_NUM /* -> maxRead */, P_PRESERVE);
if (dataPtr->maxRead >= 0) {
if (dataPtr->maxRead < toRead) {
- toRead = dataPtr->maxRead;
+ toRead = dataPtr->maxRead;
}
- } /* else: 'maxRead < 0' == Accept the current value of toRead */
-
+ } /* else: 'maxRead < 0' == Accept the current value of toRead. */
if (toRead <= 0) {
return gotBytes;
}
- read = Tcl_ReadRaw(downChan, buf, toRead);
+ /*
+ * Get bytes from the underlying channel.
+ */
+ read = Tcl_ReadRaw(downChan, buf, toRead);
if (read < 0) {
- /* Report errors to caller. EAGAIN is a special situation.
- * If we had some data before we report that instead of the
- * request to re-try.
+ /*
+ * Report errors to caller. EAGAIN is a special situation. If we
+ * had some data before we report that instead of the request to
+ * re-try.
*/
if ((Tcl_GetErrno() == EAGAIN) && (gotBytes > 0)) {
- return gotBytes;
+ return gotBytes;
}
*errorCodePtr = Tcl_GetErrno();
- return -1;
- }
-
- if (read == 0) {
+ return -1;
+ } else if (read == 0) {
/*
- * Check wether we hit on EOF in the underlying channel or
- * not. If not differentiate between blocking and
- * non-blocking modes. In non-blocking mode we ran
- * temporarily out of data. Signal this to the caller via
- * EWOULDBLOCK and error return (-1). In the other cases
- * we simply return what we got and let the caller wait
- * for more. On the other hand, if we got an EOF we have
- * to convert and flush all waiting partial data.
+ * Check wether we hit on EOF in the underlying channel or not. If
+ * not differentiate between blocking and non-blocking modes. In
+ * non-blocking mode we ran temporarily out of data. Signal this
+ * to the caller via EWOULDBLOCK and error return (-1). In the
+ * other cases we simply return what we got and let the caller
+ * wait for more. On the other hand, if we got an EOF we have to
+ * convert and flush all waiting partial data.
*/
- if (! Tcl_Eof (downChan)) {
- if ((gotBytes == 0) && (dataPtr->flags & CHANNEL_ASYNC)) {
+ if (!Tcl_Eof(downChan)) {
+ if ((gotBytes == 0) && (dataPtr->flags & CHANNEL_ASYNC)) {
*errorCodePtr = EWOULDBLOCK;
return -1;
- } else {
- return gotBytes;
- }
- } else {
- if (dataPtr->readIsFlushed) {
- /* Already flushed, nothing to do anymore
- */
- return gotBytes;
}
+ return gotBytes;
+ }
+
+ if (dataPtr->readIsFlushed) {
+ /*
+ * Already flushed, nothing to do anymore.
+ */
- dataPtr->readIsFlushed = 1;
+ return gotBytes;
+ }
- ExecuteCallback (dataPtr, NO_INTERP, A_FLUSH_READ,
- NULL, 0, TRANSMIT_IBUF, P_PRESERVE);
+ dataPtr->readIsFlushed = 1;
+ ExecuteCallback(dataPtr, NULL, A_FLUSH_READ, NULL, 0,
+ TRANSMIT_IBUF, P_PRESERVE);
- if (ResultLength (&dataPtr->result) == 0) {
- /* we had nothing to flush */
- return gotBytes;
- }
+ if (ResultEmpty(&dataPtr->result)) {
+ /*
+ * We had nothing to flush.
+ */
- continue; /* at: while (toRead > 0) */
+ return gotBytes;
}
+
+ continue; /* at: while (toRead > 0) */
} /* read == 0 */
- /* Transform the read chunk and add the result to our
- * read buffer (dataPtr->result)
+ /*
+ * Transform the read chunk and add the result to our read buffer
+ * (dataPtr->result).
*/
- res = ExecuteCallback (dataPtr, NO_INTERP, A_READ,
- UCHARP (buf), read, TRANSMIT_IBUF, P_PRESERVE);
-
- if (res != TCL_OK) {
+ if (ExecuteCallback(dataPtr, NULL, A_READ, UCHARP(buf), read,
+ TRANSMIT_IBUF, P_PRESERVE) != TCL_OK) {
*errorCodePtr = EINVAL;
return -1;
}
@@ -776,46 +726,45 @@ TransformInputProc (instanceData, buf, toRead, errorCodePtr)
}
/*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*
- * TransformOutputProc --
+ * TransformOutputProc --
*
- * Called by the generic IO system to convert data
- * waiting to be written.
+ * Called by the generic IO system to convert data waiting to be written.
*
- * Sideeffects:
- * As defined by the transformation.
+ * Side effects:
+ * As defined by the transformation.
*
- * Result:
- * A transformed buffer.
+ * Result:
+ * A transformed buffer.
*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*/
static int
-TransformOutputProc (instanceData, buf, toWrite, errorCodePtr)
- ClientData instanceData;
- CONST char* buf;
- int toWrite;
- int* errorCodePtr;
+TransformOutputProc(
+ ClientData instanceData,
+ const char *buf,
+ int toWrite,
+ int *errorCodePtr)
{
- TransformChannelData* dataPtr = (TransformChannelData*) instanceData;
- int res;
+ TransformChannelData *dataPtr = instanceData;
- /* should assert (dataPtr->mode & TCL_WRITABLE) */
+ /*
+ * Should assert(dataPtr->mode & TCL_WRITABLE);
+ */
if (toWrite == 0) {
- /* Catch a no-op.
+ /*
+ * Catch a no-op.
*/
+
return 0;
}
- res = ExecuteCallback (dataPtr, NO_INTERP, A_WRITE,
- UCHARP (buf), toWrite,
- TRANSMIT_DOWN, P_NO_PRESERVE);
-
- if (res != TCL_OK) {
- *errorCodePtr = EINVAL;
+ if (ExecuteCallback(dataPtr, NULL, A_WRITE, UCHARP(buf), toWrite,
+ TRANSMIT_DOWN, P_NO_PRESERVE) != TCL_OK) {
+ *errorCodePtr = EINVAL;
return -1;
}
@@ -823,69 +772,67 @@ TransformOutputProc (instanceData, buf, toWrite, errorCodePtr)
}
/*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*
- * TransformSeekProc --
+ * TransformSeekProc --
*
- * This procedure is called by the generic IO level
- * to move the access point in a channel.
+ * This procedure is called by the generic IO level to move the access
+ * point in a channel.
*
- * Sideeffects:
- * Moves the location at which the channel
- * will be accessed in future operations.
- * Flushes all transformation buffers, then
- * forwards it to the underlying channel.
+ * Side effects:
+ * Moves the location at which the channel will be accessed in future
+ * operations. Flushes all transformation buffers, then forwards it to
+ * the underlying channel.
*
- * Result:
- * -1 if failed, the new position if
- * successful. An output argument contains
- * the POSIX error code if an error
- * occurred, or zero.
+ * Result:
+ * -1 if failed, the new position if successful. An output argument
+ * contains the POSIX error code if an error occurred, or zero.
*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*/
static int
-TransformSeekProc (instanceData, offset, mode, errorCodePtr)
- ClientData instanceData; /* The channel to manipulate */
- long offset; /* Size of movement. */
- int mode; /* How to move */
- int* errorCodePtr; /* Location of error flag. */
+TransformSeekProc(
+ ClientData instanceData, /* The channel to manipulate. */
+ long offset, /* Size of movement. */
+ int mode, /* How to move. */
+ int *errorCodePtr) /* Location of error flag. */
{
- TransformChannelData* dataPtr = (TransformChannelData*) instanceData;
- Tcl_Channel parent = Tcl_GetStackedChannel(dataPtr->self);
- Tcl_ChannelType* parentType = Tcl_GetChannelType(parent);
- Tcl_DriverSeekProc* parentSeekProc = Tcl_ChannelSeekProc(parentType);
+ TransformChannelData *dataPtr = instanceData;
+ Tcl_Channel parent = Tcl_GetStackedChannel(dataPtr->self);
+ Tcl_ChannelType *parentType = Tcl_GetChannelType(parent);
+ Tcl_DriverSeekProc *parentSeekProc = Tcl_ChannelSeekProc(parentType);
if ((offset == 0) && (mode == SEEK_CUR)) {
- /* This is no seek but a request to tell the caller the current
+ /*
+ * This is no seek but a request to tell the caller the current
* location. Simply pass the request down.
*/
- return (*parentSeekProc) (Tcl_GetChannelInstanceData(parent),
- offset, mode, errorCodePtr);
+ return parentSeekProc(Tcl_GetChannelInstanceData(parent), offset,
+ mode, errorCodePtr);
}
/*
- * It is a real request to change the position. Flush all data waiting
- * for output and discard everything in the input buffers. Then pass
- * the request down, unchanged.
+ * It is a real request to change the position. Flush all data waiting for
+ * output and discard everything in the input buffers. Then pass the
+ * request down, unchanged.
*/
if (dataPtr->mode & TCL_WRITABLE) {
- ExecuteCallback (dataPtr, NO_INTERP, A_FLUSH_WRITE,
- NULL, 0, TRANSMIT_DOWN, P_NO_PRESERVE);
+ ExecuteCallback(dataPtr, NULL, A_FLUSH_WRITE, NULL, 0, TRANSMIT_DOWN,
+ P_NO_PRESERVE);
}
if (dataPtr->mode & TCL_READABLE) {
- ExecuteCallback (dataPtr, NO_INTERP, A_CLEAR_READ,
- NULL, 0, TRANSMIT_DONT, P_NO_PRESERVE);
+ ExecuteCallback(dataPtr, NULL, A_CLEAR_READ, NULL, 0, TRANSMIT_DONT,
+ P_NO_PRESERVE);
ResultClear(&dataPtr->result);
dataPtr->readIsFlushed = 0;
}
- return (*parentSeekProc) (Tcl_GetChannelInstanceData(parent),
- offset, mode, errorCodePtr);
+ return parentSeekProc(Tcl_GetChannelInstanceData(parent), offset, mode,
+ errorCodePtr);
}
/*
@@ -893,71 +840,64 @@ TransformSeekProc (instanceData, offset, mode, errorCodePtr)
*
* TransformWideSeekProc --
*
- * This procedure is called by the generic IO level to move the
- * access point in a channel, with a (potentially) 64-bit offset.
+ * This procedure is called by the generic IO level to move the access
+ * point in a channel, with a (potentially) 64-bit offset.
*
* Side effects:
- * Moves the location at which the channel will be accessed in
- * future operations. Flushes all transformation buffers, then
- * forwards it to the underlying channel.
+ * Moves the location at which the channel will be accessed in future
+ * operations. Flushes all transformation buffers, then forwards it to
+ * the underlying channel.
*
* Result:
- * -1 if failed, the new position if successful. An output
- * argument contains the POSIX error code if an error occurred,
- * or zero.
+ * -1 if failed, the new position if successful. An output argument
+ * contains the POSIX error code if an error occurred, or zero.
*
*----------------------------------------------------------------------
*/
static Tcl_WideInt
-TransformWideSeekProc (instanceData, offset, mode, errorCodePtr)
- ClientData instanceData; /* The channel to manipulate */
- Tcl_WideInt offset; /* Size of movement. */
- int mode; /* How to move */
- int* errorCodePtr; /* Location of error flag. */
+TransformWideSeekProc(
+ ClientData instanceData, /* The channel to manipulate. */
+ Tcl_WideInt offset, /* Size of movement. */
+ int mode, /* How to move. */
+ int *errorCodePtr) /* Location of error flag. */
{
- TransformChannelData* dataPtr =
- (TransformChannelData*) instanceData;
- Tcl_Channel parent =
- Tcl_GetStackedChannel(dataPtr->self);
- Tcl_ChannelType* parentType =
- Tcl_GetChannelType(parent);
- Tcl_DriverSeekProc* parentSeekProc =
- Tcl_ChannelSeekProc(parentType);
- Tcl_DriverWideSeekProc* parentWideSeekProc =
- Tcl_ChannelWideSeekProc(parentType);
- ClientData parentData =
- Tcl_GetChannelInstanceData(parent);
+ TransformChannelData *dataPtr = instanceData;
+ Tcl_Channel parent = Tcl_GetStackedChannel(dataPtr->self);
+ Tcl_ChannelType *parentType = Tcl_GetChannelType(parent);
+ Tcl_DriverSeekProc *parentSeekProc = Tcl_ChannelSeekProc(parentType);
+ Tcl_DriverWideSeekProc *parentWideSeekProc =
+ Tcl_ChannelWideSeekProc(parentType);
+ ClientData parentData = Tcl_GetChannelInstanceData(parent);
if ((offset == Tcl_LongAsWide(0)) && (mode == SEEK_CUR)) {
- /*
+ /*
* This is no seek but a request to tell the caller the current
* location. Simply pass the request down.
*/
if (parentWideSeekProc != NULL) {
- return (*parentWideSeekProc) (parentData, offset, mode,
- errorCodePtr);
+ return parentWideSeekProc(parentData, offset, mode, errorCodePtr);
}
- return Tcl_LongAsWide((*parentSeekProc) (parentData, 0, mode,
+ return Tcl_LongAsWide(parentSeekProc(parentData, 0, mode,
errorCodePtr));
}
/*
- * It is a real request to change the position. Flush all data waiting
- * for output and discard everything in the input buffers. Then pass
- * the request down, unchanged.
+ * It is a real request to change the position. Flush all data waiting for
+ * output and discard everything in the input buffers. Then pass the
+ * request down, unchanged.
*/
if (dataPtr->mode & TCL_WRITABLE) {
- ExecuteCallback (dataPtr, NO_INTERP, A_FLUSH_WRITE,
- NULL, 0, TRANSMIT_DOWN, P_NO_PRESERVE);
+ ExecuteCallback(dataPtr, NULL, A_FLUSH_WRITE, NULL, 0, TRANSMIT_DOWN,
+ P_NO_PRESERVE);
}
if (dataPtr->mode & TCL_READABLE) {
- ExecuteCallback (dataPtr, NO_INTERP, A_CLEAR_READ,
- NULL, 0, TRANSMIT_DONT, P_NO_PRESERVE);
+ ExecuteCallback(dataPtr, NULL, A_CLEAR_READ, NULL, 0, TRANSMIT_DONT,
+ P_NO_PRESERVE);
ResultClear(&dataPtr->result);
dataPtr->readIsFlushed = 0;
}
@@ -965,487 +905,491 @@ TransformWideSeekProc (instanceData, offset, mode, errorCodePtr)
/*
* If we have a wide seek capability, we should stick with that.
*/
+
if (parentWideSeekProc != NULL) {
- return (*parentWideSeekProc) (parentData, offset, mode, errorCodePtr);
+ return parentWideSeekProc(parentData, offset, mode, errorCodePtr);
}
/*
- * We're transferring to narrow seeks at this point; this is a bit
- * complex because we have to check whether the seek is possible
- * first (i.e. whether we are losing information in truncating the
- * bits of the offset.) Luckily, there's a defined error for what
- * happens when trying to go out of the representable range.
+ * We're transferring to narrow seeks at this point; this is a bit complex
+ * because we have to check whether the seek is possible first (i.e.
+ * whether we are losing information in truncating the bits of the
+ * offset). Luckily, there's a defined error for what happens when trying
+ * to go out of the representable range.
*/
+
if (offset<Tcl_LongAsWide(LONG_MIN) || offset>Tcl_LongAsWide(LONG_MAX)) {
*errorCodePtr = EOVERFLOW;
return Tcl_LongAsWide(-1);
}
- return Tcl_LongAsWide((*parentSeekProc) (parentData,
- Tcl_WideAsLong(offset), mode, errorCodePtr));
+
+ return Tcl_LongAsWide(parentSeekProc(parentData, Tcl_WideAsLong(offset),
+ mode, errorCodePtr));
}
/*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*
- * TransformSetOptionProc --
+ * TransformSetOptionProc --
*
- * Called by generic layer to handle the reconfi-
- * guration of channel specific options. As this
- * channel type does not have such, it simply passes
- * all requests downstream.
+ * Called by generic layer to handle the reconfiguration of channel
+ * specific options. As this channel type does not have such, it simply
+ * passes all requests downstream.
*
- * Sideeffects:
- * As defined by the channel downstream.
+ * Side effects:
+ * As defined by the channel downstream.
*
- * Result:
- * A standard TCL error code.
+ * Result:
+ * A standard TCL error code.
*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*/
static int
-TransformSetOptionProc (instanceData, interp, optionName, value)
- ClientData instanceData;
- Tcl_Interp *interp;
- CONST char *optionName;
- CONST char *value;
+TransformSetOptionProc(
+ ClientData instanceData,
+ Tcl_Interp *interp,
+ const char *optionName,
+ const char *value)
{
- TransformChannelData* dataPtr = (TransformChannelData*) instanceData;
+ TransformChannelData *dataPtr = instanceData;
Tcl_Channel downChan = Tcl_GetStackedChannel(dataPtr->self);
Tcl_DriverSetOptionProc *setOptionProc;
setOptionProc = Tcl_ChannelSetOptionProc(Tcl_GetChannelType(downChan));
- if (setOptionProc != NULL) {
- return (*setOptionProc)(Tcl_GetChannelInstanceData(downChan),
- interp, optionName, value);
+ if (setOptionProc == NULL) {
+ return TCL_ERROR;
}
- return TCL_ERROR;
+
+ return setOptionProc(Tcl_GetChannelInstanceData(downChan), interp,
+ optionName, value);
}
/*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*
- * TransformGetOptionProc --
+ * TransformGetOptionProc --
*
- * Called by generic layer to handle requests for
- * the values of channel specific options. As this
- * channel type does not have such, it simply passes
- * all requests downstream.
+ * Called by generic layer to handle requests for the values of channel
+ * specific options. As this channel type does not have such, it simply
+ * passes all requests downstream.
*
- * Sideeffects:
- * As defined by the channel downstream.
+ * Side effects:
+ * As defined by the channel downstream.
*
- * Result:
- * A standard TCL error code.
+ * Result:
+ * A standard TCL error code.
*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*/
static int
-TransformGetOptionProc (instanceData, interp, optionName, dsPtr)
- ClientData instanceData;
- Tcl_Interp* interp;
- CONST char* optionName;
- Tcl_DString* dsPtr;
+TransformGetOptionProc(
+ ClientData instanceData,
+ Tcl_Interp *interp,
+ const char *optionName,
+ Tcl_DString *dsPtr)
{
- TransformChannelData* dataPtr = (TransformChannelData*) instanceData;
+ TransformChannelData *dataPtr = instanceData;
Tcl_Channel downChan = Tcl_GetStackedChannel(dataPtr->self);
Tcl_DriverGetOptionProc *getOptionProc;
getOptionProc = Tcl_ChannelGetOptionProc(Tcl_GetChannelType(downChan));
if (getOptionProc != NULL) {
- return (*getOptionProc)(Tcl_GetChannelInstanceData(downChan),
- interp, optionName, dsPtr);
- } else if (optionName == (CONST char*) NULL) {
+ return getOptionProc(Tcl_GetChannelInstanceData(downChan), interp,
+ optionName, dsPtr);
+ } else if (optionName == NULL) {
/*
* Request is query for all options, this is ok.
*/
+
return TCL_OK;
}
+
/*
- * Request for a specific option has to fail, we don't have any.
+ * Request for a specific option has to fail, since we don't have any.
*/
+
return TCL_ERROR;
}
/*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*
- * TransformWatchProc --
+ * TransformWatchProc --
*
- * Initialize the notifier to watch for events from
- * this channel.
+ * Initialize the notifier to watch for events from this channel.
*
- * Sideeffects:
- * Sets up the notifier so that a future
- * event on the channel will be seen by Tcl.
+ * Side effects:
+ * Sets up the notifier so that a future event on the channel will be
+ * seen by Tcl.
*
- * Result:
- * None.
+ * Result:
+ * None.
*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*/
+
/* ARGSUSED */
static void
-TransformWatchProc (instanceData, mask)
- ClientData instanceData; /* Channel to watch */
- int mask; /* Events of interest */
+TransformWatchProc(
+ ClientData instanceData, /* Channel to watch. */
+ int mask) /* Events of interest. */
{
- /* The caller expressed interest in events occuring for this
- * channel. We are forwarding the call to the underlying
- * channel now.
- */
+ TransformChannelData *dataPtr = instanceData;
+ Tcl_Channel downChan;
- TransformChannelData* dataPtr = (TransformChannelData*) instanceData;
- Tcl_Channel downChan;
+ /*
+ * The caller expressed interest in events occuring for this channel. We
+ * are forwarding the call to the underlying channel now.
+ */
dataPtr->watchMask = mask;
- /* No channel handlers any more. We will be notified automatically
- * about events on the channel below via a call to our
- * 'TransformNotifyProc'. But we have to pass the interest down now.
- * We are allowed to add additional 'interest' to the mask if we want
- * to. But this transformation has no such interest. It just passes
- * the request down, unchanged.
+ /*
+ * No channel handlers any more. We will be notified automatically about
+ * events on the channel below via a call to our 'TransformNotifyProc'.
+ * But we have to pass the interest down now. We are allowed to add
+ * additional 'interest' to the mask if we want to. But this
+ * transformation has no such interest. It just passes the request down,
+ * unchanged.
*/
downChan = Tcl_GetStackedChannel(dataPtr->self);
- (Tcl_GetChannelType(downChan))
- ->watchProc(Tcl_GetChannelInstanceData(downChan), mask);
+ Tcl_GetChannelType(downChan)->watchProc(
+ Tcl_GetChannelInstanceData(downChan), mask);
/*
* Management of the internal timer.
*/
- if ((dataPtr->timer != (Tcl_TimerToken) NULL) &&
- (!(mask & TCL_READABLE) || (ResultLength(&dataPtr->result) == 0))) {
-
- /* A pending timer exists, but either is there no (more)
- * interest in the events it generates or nothing is availablee
- * for reading, so remove it.
+ if ((dataPtr->timer != NULL) &&
+ (!(mask & TCL_READABLE) || ResultEmpty(&dataPtr->result))) {
+ /*
+ * A pending timer exists, but either is there no (more) interest in
+ * the events it generates or nothing is available for reading, so
+ * remove it.
*/
- Tcl_DeleteTimerHandler (dataPtr->timer);
- dataPtr->timer = (Tcl_TimerToken) NULL;
+ Tcl_DeleteTimerHandler(dataPtr->timer);
+ dataPtr->timer = NULL;
}
- if ((dataPtr->timer == (Tcl_TimerToken) NULL) &&
- (mask & TCL_READABLE) && (ResultLength (&dataPtr->result) > 0)) {
-
- /* There is no pending timer, but there is interest in readable
- * events and we actually have data waiting, so generate a timer
- * to flush that.
+ if ((dataPtr->timer == NULL) && (mask & TCL_READABLE)
+ && !ResultEmpty(&dataPtr->result)) {
+ /*
+ * There is no pending timer, but there is interest in readable events
+ * and we actually have data waiting, so generate a timer to flush
+ * that.
*/
- dataPtr->timer = Tcl_CreateTimerHandler (FLUSH_DELAY,
- TransformChannelHandlerTimer, (ClientData) dataPtr);
+ dataPtr->timer = Tcl_CreateTimerHandler(FLUSH_DELAY,
+ TransformChannelHandlerTimer, dataPtr);
}
}
/*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*
- * TransformGetFileHandleProc --
+ * TransformGetFileHandleProc --
*
- * Called from Tcl_GetChannelHandle to retrieve
- * OS specific file handle from inside this channel.
+ * Called from Tcl_GetChannelHandle to retrieve OS specific file handle
+ * from inside this channel.
*
- * Sideeffects:
- * None.
+ * Side effects:
+ * None.
*
- * Result:
- * The appropriate Tcl_File or NULL if not
- * present.
+ * Result:
+ * The appropriate Tcl_File or NULL if not present.
*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*/
+
static int
-TransformGetFileHandleProc (instanceData, direction, handlePtr)
- ClientData instanceData; /* Channel to query */
- int direction; /* Direction of interest */
- ClientData* handlePtr; /* Place to store the handle into */
+TransformGetFileHandleProc(
+ ClientData instanceData, /* Channel to query. */
+ int direction, /* Direction of interest. */
+ ClientData *handlePtr) /* Place to store the handle into. */
{
+ TransformChannelData *dataPtr = instanceData;
+
/*
- * Return the handle belonging to parent channel.
- * IOW, pass the request down and the result up.
+ * Return the handle belonging to parent channel. IOW, pass the request
+ * down and the result up.
*/
- TransformChannelData* dataPtr = (TransformChannelData*) instanceData;
-
return Tcl_GetChannelHandle(Tcl_GetStackedChannel(dataPtr->self),
direction, handlePtr);
}
/*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*
- * TransformNotifyProc --
+ * TransformNotifyProc --
*
- * ------------------------------------------------*
- * Handler called by Tcl to inform us of activity
- * on the underlying channel.
- * ------------------------------------------------*
+ * Handler called by Tcl to inform us of activity on the underlying
+ * channel.
*
- * Sideeffects:
- * May process the incoming event by itself.
+ * Side effects:
+ * May process the incoming event by itself.
*
- * Result:
- * None.
+ * Result:
+ * None.
*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*/
static int
-TransformNotifyProc (clientData, mask)
- ClientData clientData; /* The state of the notified transformation */
- int mask; /* The mask of occuring events */
+TransformNotifyProc(
+ ClientData clientData, /* The state of the notified
+ * transformation. */
+ int mask) /* The mask of occuring events. */
{
- TransformChannelData* dataPtr = (TransformChannelData*) clientData;
+ TransformChannelData *dataPtr = clientData;
/*
- * An event occured in the underlying channel. This
- * transformation doesn't process such events thus returns the
- * incoming mask unchanged.
+ * An event occured in the underlying channel. This transformation doesn't
+ * process such events thus returns the incoming mask unchanged.
*/
- if (dataPtr->timer != (Tcl_TimerToken) NULL) {
+ if (dataPtr->timer != NULL) {
/*
- * Delete an existing timer. It was not fired, yet we are
- * here, so the channel below generated such an event and we
- * don't have to. The renewal of the interest after the
- * execution of channel handlers will eventually cause us to
- * recreate the timer (in TransformWatchProc).
+ * Delete an existing timer. It was not fired, yet we are here, so the
+ * channel below generated such an event and we don't have to. The
+ * renewal of the interest after the execution of channel handlers
+ * will eventually cause us to recreate the timer (in
+ * TransformWatchProc).
*/
- Tcl_DeleteTimerHandler (dataPtr->timer);
- dataPtr->timer = (Tcl_TimerToken) NULL;
+ Tcl_DeleteTimerHandler(dataPtr->timer);
+ dataPtr->timer = NULL;
}
-
return mask;
}
/*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*
- * TransformChannelHandlerTimer --
+ * TransformChannelHandlerTimer --
*
- * Called by the notifier (-> timer) to flush out
- * information waiting in the input buffer.
+ * Called by the notifier (-> timer) to flush out information waiting in
+ * the input buffer.
*
- * Sideeffects:
- * As of 'Tcl_NotifyChannel'.
+ * Side effects:
+ * As of 'Tcl_NotifyChannel'.
*
- * Result:
- * None.
+ * Result:
+ * None.
*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*/
static void
-TransformChannelHandlerTimer (clientData)
- ClientData clientData; /* Transformation to query */
+TransformChannelHandlerTimer(
+ ClientData clientData) /* Transformation to query. */
{
- TransformChannelData* dataPtr = (TransformChannelData*) clientData;
+ TransformChannelData *dataPtr = clientData;
- dataPtr->timer = (Tcl_TimerToken) NULL;
-
- if (!(dataPtr->watchMask & TCL_READABLE) ||
- (ResultLength (&dataPtr->result) == 0)) {
- /* The timer fired, but either is there no (more)
- * interest in the events it generates or nothing is available
- * for reading, so ignore it and don't recreate it.
+ dataPtr->timer = NULL;
+ if (!(dataPtr->watchMask&TCL_READABLE) || ResultEmpty(&dataPtr->result)) {
+ /*
+ * The timer fired, but either is there no (more) interest in the
+ * events it generates or nothing is available for reading, so ignore
+ * it and don't recreate it.
*/
return;
}
-
Tcl_NotifyChannel(dataPtr->self, TCL_READABLE);
}
/*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*
- * ResultClear --
+ * ResultClear --
*
* Deallocates any memory allocated by 'ResultAdd'.
*
- * Sideeffects:
- * See above.
+ * Side effects:
+ * See above.
*
- * Result:
- * None.
+ * Result:
+ * None.
*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*/
-static void
-ResultClear (r)
- ResultBuffer* r; /* Reference to the buffer to clear out */
+static inline void
+ResultClear(
+ ResultBuffer *r) /* Reference to the buffer to clear out. */
{
r->used = 0;
if (r->allocated) {
- ckfree((char*) r->buf);
- r->buf = UCHARP (NULL);
+ ckfree((char *) r->buf);
+ r->buf = NULL;
r->allocated = 0;
}
}
/*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*
- * ResultInit --
+ * ResultInit --
*
- * Initializes the specified buffer structure. The
- * structure will contain valid information for an
- * emtpy buffer.
+ * Initializes the specified buffer structure. The structure will contain
+ * valid information for an emtpy buffer.
*
- * Sideeffects:
- * See above.
+ * Side effects:
+ * See above.
*
- * Result:
- * None.
+ * Result:
+ * None.
*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*/
-static void
-ResultInit (r)
- ResultBuffer* r; /* Reference to the structure to initialize */
+static inline void
+ResultInit(
+ ResultBuffer *r) /* Reference to the structure to
+ * initialize. */
{
- r->used = 0;
+ r->used = 0;
r->allocated = 0;
- r->buf = UCHARP (NULL);
+ r->buf = NULL;
}
/*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*
- * ResultLength --
+ * ResultEmpty --
*
- * Returns the number of bytes stored in the buffer.
+ * Returns whether the number of bytes stored in the buffer is zero.
*
- * Sideeffects:
- * None.
+ * Side effects:
+ * None.
*
- * Result:
- * An integer, see above too.
+ * Result:
+ * A boolean.
*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*/
-static int
-ResultLength (r)
- ResultBuffer* r; /* The structure to query */
+static inline int
+ResultEmpty(
+ ResultBuffer *r) /* The structure to query. */
{
- return r->used;
+ return r->used == 0;
}
/*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*
- * ResultCopy --
+ * ResultCopy --
*
- * Copies the requested number of bytes from the
- * buffer into the specified array and removes them
- * from the buffer afterward. Copies less if there
- * is not enough data in the buffer.
+ * Copies the requested number of bytes from the buffer into the
+ * specified array and removes them from the buffer afterward. Copies
+ * less if there is not enough data in the buffer.
*
- * Sideeffects:
- * See above.
+ * Side effects:
+ * See above.
*
- * Result:
- * The number of actually copied bytes,
- * possibly less than 'toRead'.
+ * Result:
+ * The number of actually copied bytes, possibly less than 'toRead'.
*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*/
-static int
-ResultCopy (r, buf, toRead)
- ResultBuffer* r; /* The buffer to read from */
- unsigned char* buf; /* The buffer to copy into */
- int toRead; /* Number of requested bytes */
+static inline int
+ResultCopy(
+ ResultBuffer *r, /* The buffer to read from. */
+ unsigned char *buf, /* The buffer to copy into. */
+ size_t toRead) /* Number of requested bytes. */
{
if (r->used == 0) {
- /* Nothing to copy in the case of an empty buffer.
+ /*
+ * Nothing to copy in the case of an empty buffer.
*/
- return 0;
- }
-
- if (r->used == toRead) {
- /* We have just enough. Copy everything to the caller.
+ return 0;
+ } else if (r->used == toRead) {
+ /*
+ * We have just enough. Copy everything to the caller.
*/
- memcpy ((VOID*) buf, (VOID*) r->buf, (size_t) toRead);
+ memcpy(buf, r->buf, toRead);
r->used = 0;
- return toRead;
- }
-
- if (r->used > toRead) {
- /* The internal buffer contains more than requested.
- * Copy the requested subset to the caller, and shift
- * the remaining bytes down.
+ } else if (r->used > toRead) {
+ /*
+ * The internal buffer contains more than requested. Copy the
+ * requested subset to the caller, and shift the remaining bytes down.
*/
- memcpy ((VOID*) buf, (VOID*) r->buf, (size_t) toRead);
- memmove ((VOID*) r->buf, (VOID*) (r->buf + toRead),
- (size_t) r->used - toRead);
-
+ memcpy(buf, r->buf, toRead);
+ memmove(r->buf, r->buf + toRead, r->used - toRead);
r->used -= toRead;
- return toRead;
- }
-
- /* There is not enough in the buffer to satisfy the caller, so
- * take everything.
- */
+ } else {
+ /*
+ * There is not enough in the buffer to satisfy the caller, so take
+ * everything.
+ */
- memcpy((VOID*) buf, (VOID*) r->buf, (size_t) r->used);
- toRead = r->used;
- r->used = 0;
+ memcpy(buf, r->buf, r->used);
+ toRead = r->used;
+ r->used = 0;
+ }
return toRead;
}
/*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*
- * ResultAdd --
+ * ResultAdd --
*
- * Adds the bytes in the specified array to the
- * buffer, by appending it.
+ * Adds the bytes in the specified array to the buffer, by appending it.
*
- * Sideeffects:
- * See above.
+ * Side effects:
+ * See above.
*
- * Result:
- * None.
+ * Result:
+ * None.
*
- *------------------------------------------------------*
+ *----------------------------------------------------------------------
*/
-static void
-ResultAdd (r, buf, toWrite)
- ResultBuffer* r; /* The buffer to extend */
- unsigned char* buf; /* The buffer to read from */
- int toWrite; /* The number of bytes in 'buf' */
+static inline void
+ResultAdd(
+ ResultBuffer *r, /* The buffer to extend. */
+ unsigned char *buf, /* The buffer to read from. */
+ size_t toWrite) /* The number of bytes in 'buf'. */
{
- if ((r->used + toWrite) > r->allocated) {
- /* Extension of the internal buffer is required.
+ if (r->used + toWrite > r->allocated) {
+ /*
+ * Extension of the internal buffer is required.
*/
- if (r->allocated == 0) {
+ if (r->allocated == 0) {
r->allocated = toWrite + INCREMENT;
- r->buf = UCHARP (ckalloc((unsigned) r->allocated));
+ r->buf = UCHARP(ckalloc(r->allocated));
} else {
r->allocated += toWrite + INCREMENT;
- r->buf = UCHARP (ckrealloc((char*) r->buf,
- (unsigned) r->allocated));
+ r->buf = UCHARP(ckrealloc((char *) r->buf, r->allocated));
}
}
- /* now copy data */
- memcpy(r->buf + r->used, buf, (size_t) toWrite);
+ /*
+ * Now we may copy the data.
+ */
+
+ memcpy(r->buf + r->used, buf, toWrite);
r->used += toWrite;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclIORChan.c b/generic/tclIORChan.c
new file mode 100644
index 0000000..d3bd8c4
--- /dev/null
+++ b/generic/tclIORChan.c
@@ -0,0 +1,3189 @@
+/*
+ * tclIORChan.c --
+ *
+ * This file contains the implementation of Tcl's generic channel
+ * reflection code, which allows the implementation of Tcl channels in
+ * Tcl code.
+ *
+ * Parts of this file are based on code contributed by Jean-Claude
+ * Wippler.
+ *
+ * See TIP #219 for the specification of this functionality.
+ *
+ * Copyright (c) 2004-2005 ActiveState, a divison of Sophos
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include <tclInt.h>
+#include <tclIO.h>
+#include <assert.h>
+
+#ifndef EINVAL
+#define EINVAL 9
+#endif
+#ifndef EOK
+#define EOK 0
+#endif
+
+/*
+ * Signatures of all functions used in the C layer of the reflection.
+ */
+
+static int ReflectClose(ClientData clientData,
+ Tcl_Interp *interp);
+static int ReflectInput(ClientData clientData, char *buf,
+ int toRead, int *errorCodePtr);
+static int ReflectOutput(ClientData clientData, const char *buf,
+ int toWrite, int *errorCodePtr);
+static void ReflectWatch(ClientData clientData, int mask);
+static int ReflectBlock(ClientData clientData, int mode);
+static Tcl_WideInt ReflectSeekWide(ClientData clientData,
+ Tcl_WideInt offset, int mode, int *errorCodePtr);
+static int ReflectSeek(ClientData clientData, long offset,
+ int mode, int *errorCodePtr);
+static int ReflectGetOption(ClientData clientData,
+ Tcl_Interp *interp, const char *optionName,
+ Tcl_DString *dsPtr);
+static int ReflectSetOption(ClientData clientData,
+ Tcl_Interp *interp, const char *optionName,
+ const char *newValue);
+
+/*
+ * The C layer channel type/driver definition used by the reflection. This is
+ * a version 3 structure.
+ */
+
+static Tcl_ChannelType tclRChannelType = {
+ "tclrchannel", /* Type name. */
+ TCL_CHANNEL_VERSION_5, /* v5 channel */
+ ReflectClose, /* Close channel, clean instance data */
+ ReflectInput, /* Handle read request */
+ ReflectOutput, /* Handle write request */
+ ReflectSeek, /* Move location of access point. NULL'able */
+ ReflectSetOption, /* Set options. NULL'able */
+ ReflectGetOption, /* Get options. NULL'able */
+ ReflectWatch, /* Initialize notifier */
+ NULL, /* Get OS handle from the channel. NULL'able */
+ NULL, /* No close2 support. NULL'able */
+ ReflectBlock, /* Set blocking/nonblocking. NULL'able */
+ NULL, /* Flush channel. Not used by core. NULL'able */
+ NULL, /* Handle events. NULL'able */
+ ReflectSeekWide, /* Move access point (64 bit). NULL'able */
+ NULL, /* thread action */
+ NULL, /* truncate */
+};
+
+/*
+ * Instance data for a reflected channel. ===========================
+ */
+
+typedef struct {
+ Tcl_Channel chan; /* Back reference to generic channel
+ * structure. */
+ Tcl_Interp *interp; /* Reference to the interpreter containing the
+ * Tcl level part of the channel. NULL here
+ * signals the channel is dead because the
+ * interpreter/thread containing its Tcl
+ * command is gone.
+ */
+#ifdef TCL_THREADS
+ Tcl_ThreadId thread; /* Thread the 'interp' belongs to. */
+#endif
+
+ /* See [==] as well.
+ * Storage for the command prefix and the additional words required for
+ * the invocation of methods in the command handler.
+ *
+ * argv [0] ... [.] | [argc-2] [argc-1] | [argc] [argc+2]
+ * cmd ... pfx | method chan | detail1 detail2
+ * ~~~~ CT ~~~ ~~ CT ~~
+ *
+ * CT = Belongs to the 'Command handler Thread'.
+ */
+
+ int argc; /* Number of preallocated words - 2 */
+ Tcl_Obj **argv; /* Preallocated array for calling the handler.
+ * args[0] is placeholder for cmd word.
+ * Followed by the arguments in the prefix,
+ * plus 4 placeholders for method, channel,
+ * and at most two varying (method specific)
+ * words. */
+ int methods; /* Bitmask of supported methods */
+
+ /*
+ * NOTE (9): Should we have predefined shared literals for the method
+ * names?
+ */
+
+ int mode; /* Mask of R/W mode */
+ int interest; /* Mask of events the channel is interested
+ * in. */
+
+ /*
+ * Note regarding the usage of timers.
+ *
+ * Most channel implementations need a timer in the C level to ensure that
+ * data in buffers is flushed out through the generation of fake file
+ * events.
+ *
+ * See 'rechan', 'memchan', etc.
+ *
+ * Here this is _not_ required. Interest in events is posted to the Tcl
+ * level via 'watch'. And posting of events is possible from the Tcl level
+ * as well, via 'chan postevent'. This means that the generation of all
+ * events, fake or not, timer based or not, is completely in the hands of
+ * the Tcl level. Therefore no timer here.
+ */
+} ReflectedChannel;
+
+/*
+ * Structure of the table maping from channel handles to reflected
+ * channels. Each interpreter which has the handler command for one or more
+ * reflected channels records them in such a table, so that 'chan postevent'
+ * is able to find them even if the actual channel was moved to a different
+ * interpreter and/or thread.
+ *
+ * The table is reachable via the standard interpreter AssocData, the key is
+ * defined below.
+ */
+
+typedef struct {
+ Tcl_HashTable map;
+} ReflectedChannelMap;
+
+#define RCMKEY "ReflectedChannelMap"
+
+/*
+ * Event literals. ==================================================
+ */
+
+static const char *eventOptions[] = {
+ "read", "write", NULL
+};
+typedef enum {
+ EVENT_READ, EVENT_WRITE
+} EventOption;
+
+/*
+ * Method literals. ==================================================
+ */
+
+static const char *methodNames[] = {
+ "blocking", /* OPT */
+ "cget", /* OPT \/ Together or none */
+ "cgetall", /* OPT /\ of these two */
+ "configure", /* OPT */
+ "finalize", /* */
+ "initialize", /* */
+ "read", /* OPT */
+ "seek", /* OPT */
+ "watch", /* */
+ "write", /* OPT */
+ NULL
+};
+typedef enum {
+ METH_BLOCKING,
+ METH_CGET,
+ METH_CGETALL,
+ METH_CONFIGURE,
+ METH_FINAL,
+ METH_INIT,
+ METH_READ,
+ METH_SEEK,
+ METH_WATCH,
+ METH_WRITE
+} MethodName;
+
+#define FLAG(m) (1 << (m))
+#define REQUIRED_METHODS \
+ (FLAG(METH_INIT) | FLAG(METH_FINAL) | FLAG(METH_WATCH))
+#define NULLABLE_METHODS \
+ (FLAG(METH_BLOCKING) | FLAG(METH_SEEK) | \
+ FLAG(METH_CONFIGURE) | FLAG(METH_CGET) | FLAG(METH_CGETALL))
+
+#define RANDW \
+ (TCL_READABLE | TCL_WRITABLE)
+
+#define IMPLIES(a,b) ((!(a)) || (b))
+#define NEGIMPL(a,b)
+#define HAS(x,f) (x & FLAG(f))
+
+#ifdef TCL_THREADS
+/*
+ * Thread specific types and structures.
+ *
+ * We are here essentially creating a very specific implementation of 'thread
+ * send'.
+ */
+
+/*
+ * Enumeration of all operations which can be forwarded.
+ */
+
+typedef enum {
+ ForwardedClose,
+ ForwardedInput,
+ ForwardedOutput,
+ ForwardedSeek,
+ ForwardedWatch,
+ ForwardedBlock,
+ ForwardedSetOpt,
+ ForwardedGetOpt,
+ ForwardedGetOptAll
+} ForwardedOperation;
+
+/*
+ * Event used to forward driver invocations to the thread actually managing
+ * the channel. We cannot construct the command to execute and forward that.
+ * Because then it will contain a mixture of Tcl_Obj's belonging to both the
+ * command handler thread (CT), and the thread managing the channel (MT),
+ * executed in CT. Tcl_Obj's are not allowed to cross thread boundaries. So we
+ * forward an operation code, the argument details, and reference to results.
+ * The command is assembled in the CT and belongs fully to that thread. No
+ * sharing problems.
+ */
+
+typedef struct ForwardParamBase {
+ int code; /* O: Ok/Fail of the cmd handler */
+ char *msgStr; /* O: Error message for handler failure */
+ int mustFree; /* O: True if msgStr is allocated, false if
+ * otherwise (static). */
+} ForwardParamBase;
+
+/*
+ * Operation specific parameter/result structures. (These are "subtypes" of
+ * ForwardParamBase. Where an operation does not need any special types, it
+ * has no "subtype" and just uses ForwardParamBase, as listed above.)
+ */
+
+struct ForwardParamInput {
+ ForwardParamBase base; /* "Supertype". MUST COME FIRST. */
+ char *buf; /* O: Where to store the read bytes */
+ int toRead; /* I: #bytes to read,
+ * O: #bytes actually read */
+};
+struct ForwardParamOutput {
+ ForwardParamBase base; /* "Supertype". MUST COME FIRST. */
+ const char *buf; /* I: Where the bytes to write come from */
+ int toWrite; /* I: #bytes to write,
+ * O: #bytes actually written */
+};
+struct ForwardParamSeek {
+ ForwardParamBase base; /* "Supertype". MUST COME FIRST. */
+ int seekMode; /* I: How to seek */
+ Tcl_WideInt offset; /* I: Where to seek,
+ * O: New location */
+};
+struct ForwardParamWatch {
+ ForwardParamBase base; /* "Supertype". MUST COME FIRST. */
+ int mask; /* I: What events to watch for */
+};
+struct ForwardParamBlock {
+ ForwardParamBase base; /* "Supertype". MUST COME FIRST. */
+ int nonblocking; /* I: What mode to activate */
+};
+struct ForwardParamSetOpt {
+ ForwardParamBase base; /* "Supertype". MUST COME FIRST. */
+ const char *name; /* Name of option to set */
+ const char *value; /* Value to set */
+};
+struct ForwardParamGetOpt {
+ ForwardParamBase base; /* "Supertype". MUST COME FIRST. */
+ const char *name; /* Name of option to get, maybe NULL */
+ Tcl_DString *value; /* Result */
+};
+
+/*
+ * Now join all these together in a single union for convenience.
+ */
+
+typedef union ForwardParam {
+ ForwardParamBase base;
+ struct ForwardParamInput input;
+ struct ForwardParamOutput output;
+ struct ForwardParamSeek seek;
+ struct ForwardParamWatch watch;
+ struct ForwardParamBlock block;
+ struct ForwardParamSetOpt setOpt;
+ struct ForwardParamGetOpt getOpt;
+} ForwardParam;
+
+/*
+ * Forward declaration.
+ */
+
+typedef struct ForwardingResult ForwardingResult;
+
+/*
+ * General event structure, with reference to operation specific data.
+ */
+
+typedef struct ForwardingEvent {
+ Tcl_Event event; /* Basic event data, has to be first item */
+ ForwardingResult *resultPtr;
+ ForwardedOperation op; /* Forwarded driver operation */
+ ReflectedChannel *rcPtr; /* Channel instance */
+ ForwardParam *param; /* Packaged arguments and return values, a
+ * ForwardParam pointer. */
+} ForwardingEvent;
+
+/*
+ * Structure to manage the result of the forwarding. This is not the result of
+ * the operation itself, but about the success of the forward event itself.
+ * The event can be successful, even if the operation which was forwarded
+ * failed. It is also there to manage the synchronization between the involved
+ * threads.
+ */
+
+struct ForwardingResult {
+ Tcl_ThreadId src; /* Originating thread. */
+ Tcl_ThreadId dst; /* Thread the op was forwarded to. */
+ Tcl_Interp* dsti; /* Interpreter in the thread the op was forwarded to. */
+ /*
+ * Note regarding 'dsti' above: Its information is also available via the
+ * chain evPtr->rcPtr->interp, however, as can be seen, two more
+ * indirections are needed to retrieve it. And the evPtr may be gone,
+ * breaking the chain.
+ */
+ Tcl_Condition done; /* Condition variable the forwarder blocks
+ * on. */
+ int result; /* TCL_OK or TCL_ERROR */
+ ForwardingEvent *evPtr; /* Event the result belongs to. */
+ ForwardingResult *prevPtr, *nextPtr;
+ /* Links into the list of pending forwarded
+ * results. */
+};
+
+typedef struct ThreadSpecificData {
+ /*
+ * Table of all reflected channels owned by this thread. This is the
+ * per-thread version of the per-interpreter map.
+ */
+
+ ReflectedChannelMap* rcmPtr;
+} ThreadSpecificData;
+
+static Tcl_ThreadDataKey dataKey;
+
+/*
+ * List of forwarded operations which have not completed yet, plus the mutex
+ * to protect the access to this process global list.
+ */
+
+static ForwardingResult *forwardList = NULL;
+TCL_DECLARE_MUTEX(rcForwardMutex)
+
+/*
+ * Function containing the generic code executing a forward, and wrapper
+ * macros for the actual operations we wish to forward. Uses ForwardProc as
+ * the event function executed by the thread receiving a forwarding event
+ * (which executes the appropriate function and collects the result, if any).
+ *
+ * The ExitProc ensures that things do not deadlock when the sending thread
+ * involved in the forwarding exits. It also clean things up so that we don't
+ * leak resources when threads go away.
+ */
+
+static void ForwardOpToOwnerThread(ReflectedChannel *rcPtr,
+ ForwardedOperation op, const VOID *param);
+static int ForwardProc(Tcl_Event *evPtr, int mask);
+static void SrcExitProc(ClientData clientData);
+
+#define FreeReceivedError(p) \
+ if ((p)->base.mustFree) { \
+ ckfree((p)->base.msgStr); \
+ }
+#define PassReceivedErrorInterp(i,p) \
+ if ((i) != NULL) { \
+ Tcl_SetChannelErrorInterp((i), \
+ Tcl_NewStringObj((p)->base.msgStr, -1)); \
+ } \
+ FreeReceivedError(p)
+#define PassReceivedError(c,p) \
+ Tcl_SetChannelError((c), Tcl_NewStringObj((p)->base.msgStr, -1)); \
+ FreeReceivedError(p)
+#define ForwardSetStaticError(p,emsg) \
+ (p)->base.code = TCL_ERROR; \
+ (p)->base.mustFree = 0; \
+ (p)->base.msgStr = (char *) (emsg)
+#define ForwardSetDynamicError(p,emsg) \
+ (p)->base.code = TCL_ERROR; \
+ (p)->base.mustFree = 1; \
+ (p)->base.msgStr = (char *) (emsg)
+
+static void ForwardSetObjError(ForwardParam *p, Tcl_Obj *objPtr);
+
+static ReflectedChannelMap * GetThreadReflectedChannelMap(void);
+static void DeleteThreadReflectedChannelMap(ClientData clientData);
+
+#endif /* TCL_THREADS */
+
+#define SetChannelErrorStr(c,msgStr) \
+ Tcl_SetChannelError((c), Tcl_NewStringObj((msgStr), -1))
+
+static Tcl_Obj * MarshallError(Tcl_Interp *interp);
+static void UnmarshallErrorResult(Tcl_Interp *interp,
+ Tcl_Obj *msgObj);
+
+/*
+ * Static functions for this file:
+ */
+
+static int EncodeEventMask(Tcl_Interp *interp,
+ const char *objName, Tcl_Obj *obj, int *mask);
+static Tcl_Obj * DecodeEventMask(int mask);
+static ReflectedChannel * NewReflectedChannel(Tcl_Interp *interp,
+ Tcl_Obj *cmdpfxObj, int mode, Tcl_Obj *handleObj);
+static Tcl_Obj * NextHandle(void);
+static void FreeReflectedChannel(ReflectedChannel *rcPtr);
+static int InvokeTclMethod(ReflectedChannel *rcPtr,
+ const char *method, Tcl_Obj *argOneObj,
+ Tcl_Obj *argTwoObj, Tcl_Obj **resultObjPtr);
+
+static ReflectedChannelMap * GetReflectedChannelMap(Tcl_Interp *interp);
+static void DeleteReflectedChannelMap(ClientData clientData,
+ Tcl_Interp *interp);
+static int ErrnoReturn(ReflectedChannel *rcPtr, Tcl_Obj* resObj);
+
+/*
+ * Global constant strings (messages). ==================
+ * These string are used directly as bypass errors, thus they have to be valid
+ * Tcl lists where the last element is the message itself. Hence the
+ * list-quoting to keep the words of the message together. See also [x].
+ */
+
+static const char *msg_read_unsup = "{read not supported by Tcl driver}";
+static const char *msg_read_toomuch = "{read delivered more than requested}";
+static const char *msg_write_unsup = "{write not supported by Tcl driver}";
+static const char *msg_write_toomuch = "{write wrote more than requested}";
+static const char *msg_write_nothing = "{write wrote nothing}";
+static const char *msg_seek_beforestart = "{Tried to seek before origin}";
+#ifdef TCL_THREADS
+static const char *msg_send_originlost = "{Channel thread lost}";
+static const char *msg_send_dstlost = "{Owner lost}";
+#endif /* TCL_THREADS */
+static const char *msg_dstlost = "-code 1 -level 0 -errorcode NONE -errorinfo {} -errorline 1 {Owner lost}";
+
+/*
+ * Main methods to plug into the 'chan' ensemble'. ==================
+ */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclChanCreateObjCmd --
+ *
+ * This function is invoked to process the "chan create" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result. The handle of the new channel is placed in the
+ * interp result.
+ *
+ * Side effects:
+ * Creates a new channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclChanCreateObjCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ ReflectedChannel *rcPtr; /* Instance data of the new channel */
+ Tcl_Obj *rcId; /* Handle of the new channel */
+ int mode; /* R/W mode of new channel. Has to match
+ * abilities of handler commands */
+ Tcl_Obj *cmdObj; /* Command prefix, list of words */
+ Tcl_Obj *cmdNameObj; /* Command name */
+ Tcl_Channel chan; /* Token for the new channel */
+ Tcl_Obj *modeObj; /* mode in obj form for method call */
+ int listc; /* Result of 'initialize', and of */
+ Tcl_Obj **listv; /* its sublist in the 2nd element */
+ int methIndex; /* Encoded method name */
+ int result; /* Result code for 'initialize' */
+ Tcl_Obj *resObj; /* Result data for 'initialize' */
+ int methods; /* Bitmask for supported methods. */
+ Channel *chanPtr; /* 'chan' resolved to internal struct. */
+ Tcl_Obj *err; /* Error message */
+ ReflectedChannelMap* rcmPtr; /* Map of reflected channels with handlers in this interp */
+ Tcl_HashEntry* hPtr; /* Entry in the above map */
+ int isNew; /* Placeholder. */
+
+ /*
+ * Syntax: chan create MODE CMDPREFIX
+ * [0] [1] [2] [3]
+ *
+ * Actually: rCreate MODE CMDPREFIX
+ * [0] [1] [2]
+ */
+
+#define MODE (1)
+#define CMD (2)
+
+ /*
+ * Number of arguments...
+ */
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "mode cmdprefix");
+ return TCL_ERROR;
+ }
+
+ /*
+ * First argument is a list of modes. Allowed entries are "read", "write".
+ * Expect at least one list element. Abbreviations are ok.
+ */
+
+ modeObj = objv[MODE];
+ if (EncodeEventMask(interp, "mode", objv[MODE], &mode) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Second argument is command prefix, i.e. list of words, first word is
+ * name of handler command, other words are fixed arguments. Run the
+ * 'initialize' method to get the list of supported methods. Validate
+ * this.
+ */
+
+ cmdObj = objv[CMD];
+
+ /*
+ * Basic check that the command prefix truly is a list.
+ */
+
+ if (Tcl_ListObjIndex(interp, cmdObj, 0, &cmdNameObj) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Now create the channel.
+ */
+
+ rcId = NextHandle();
+ rcPtr = NewReflectedChannel(interp, cmdObj, mode, rcId);
+ chan = Tcl_CreateChannel(&tclRChannelType, TclGetString(rcId), rcPtr,
+ mode);
+ rcPtr->chan = chan;
+ chanPtr = (Channel *) chan;
+
+ /*
+ * Invoke 'initialize' and validate that the handler is present and ok.
+ * Squash the channel if not.
+ *
+ * Note: The conversion of 'mode' back into a Tcl_Obj ensures that
+ * 'initialize' is invoked with canonical mode names, and no
+ * abbreviations. Using modeObj directly could feed abbreviations into the
+ * handler, and the handler is not specified to handle such.
+ */
+
+ modeObj = DecodeEventMask(mode);
+ /* assert modeObj.refCount == 1 */
+ result = InvokeTclMethod(rcPtr, "initialize", modeObj, NULL, &resObj);
+ Tcl_DecrRefCount(modeObj);
+ if (result != TCL_OK) {
+ UnmarshallErrorResult(interp, resObj);
+ Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
+ goto error;
+ }
+
+ /*
+ * Verify the result.
+ * - List, of method names. Convert to mask.
+ * Check for non-optionals through the mask.
+ * Compare open mode against optional r/w.
+ */
+
+ if (Tcl_ListObjGetElements(NULL, resObj, &listc, &listv) != TCL_OK) {
+ TclNewLiteralStringObj(err, "chan handler \"");
+ Tcl_AppendObjToObj(err, cmdObj);
+ Tcl_AppendToObj(err, " initialize\" returned non-list: ", -1);
+ Tcl_AppendObjToObj(err, resObj);
+ Tcl_SetObjResult(interp, err);
+ Tcl_DecrRefCount(resObj);
+ goto error;
+ }
+
+ methods = 0;
+ while (listc > 0) {
+ if (Tcl_GetIndexFromObj(interp, listv[listc-1], methodNames,
+ "method", TCL_EXACT, &methIndex) != TCL_OK) {
+ TclNewLiteralStringObj(err, "chan handler \"");
+ Tcl_AppendObjToObj(err, cmdObj);
+ Tcl_AppendToObj(err, " initialize\" returned ", -1);
+ Tcl_AppendObjToObj(err, Tcl_GetObjResult(interp));
+ Tcl_SetObjResult(interp, err);
+ Tcl_DecrRefCount(resObj);
+ goto error;
+ }
+
+ methods |= FLAG(methIndex);
+ listc--;
+ }
+ Tcl_DecrRefCount(resObj);
+
+ if ((REQUIRED_METHODS & methods) != REQUIRED_METHODS) {
+ TclNewLiteralStringObj(err, "chan handler \"");
+ Tcl_AppendObjToObj(err, cmdObj);
+ Tcl_AppendToObj(err, "\" does not support all required methods", -1);
+ Tcl_SetObjResult(interp, err);
+ goto error;
+ }
+
+ if ((mode & TCL_READABLE) && !HAS(methods, METH_READ)) {
+ TclNewLiteralStringObj(err, "chan handler \"");
+ Tcl_AppendObjToObj(err, cmdObj);
+ Tcl_AppendToObj(err, "\" lacks a \"read\" method", -1);
+ Tcl_SetObjResult(interp, err);
+ goto error;
+ }
+
+ if ((mode & TCL_WRITABLE) && !HAS(methods, METH_WRITE)) {
+ TclNewLiteralStringObj(err, "chan handler \"");
+ Tcl_AppendObjToObj(err, cmdObj);
+ Tcl_AppendToObj(err, "\" lacks a \"write\" method", -1);
+ Tcl_SetObjResult(interp, err);
+ goto error;
+ }
+
+ if (!IMPLIES(HAS(methods, METH_CGET), HAS(methods, METH_CGETALL))) {
+ TclNewLiteralStringObj(err, "chan handler \"");
+ Tcl_AppendObjToObj(err, cmdObj);
+ Tcl_AppendToObj(err, "\" supports \"cget\" but not \"cgetall\"", -1);
+ Tcl_SetObjResult(interp, err);
+ goto error;
+ }
+
+ if (!IMPLIES(HAS(methods, METH_CGETALL), HAS(methods, METH_CGET))) {
+ TclNewLiteralStringObj(err, "chan handler \"");
+ Tcl_AppendObjToObj(err, cmdObj);
+ Tcl_AppendToObj(err, "\" supports \"cgetall\" but not \"cget\"", -1);
+ Tcl_SetObjResult(interp, err);
+ goto error;
+ }
+
+ Tcl_ResetResult(interp);
+
+ /*
+ * Everything is fine now.
+ */
+
+ rcPtr->methods = methods;
+
+ if ((methods & NULLABLE_METHODS) != NULLABLE_METHODS) {
+ /*
+ * Some of the nullable methods are not supported. We clone the
+ * channel type, null the associated C functions, and use the result
+ * as the actual channel type.
+ */
+
+ Tcl_ChannelType *clonePtr = (Tcl_ChannelType *)
+ ckalloc(sizeof(Tcl_ChannelType));
+
+ memcpy(clonePtr, &tclRChannelType, sizeof(Tcl_ChannelType));
+
+ if (!(methods & FLAG(METH_CONFIGURE))) {
+ clonePtr->setOptionProc = NULL;
+ }
+
+ if (!(methods & FLAG(METH_CGET)) && !(methods & FLAG(METH_CGETALL))) {
+ clonePtr->getOptionProc = NULL;
+ }
+ if (!(methods & FLAG(METH_BLOCKING))) {
+ clonePtr->blockModeProc = NULL;
+ }
+ if (!(methods & FLAG(METH_SEEK))) {
+ clonePtr->seekProc = NULL;
+ clonePtr->wideSeekProc = NULL;
+ }
+
+ chanPtr->typePtr = clonePtr;
+ }
+
+ /*
+ * Register the channel in the I/O system, and in our our map for 'chan
+ * postevent'.
+ */
+
+ Tcl_RegisterChannel(interp, chan);
+
+ rcmPtr = GetReflectedChannelMap (interp);
+ hPtr = Tcl_CreateHashEntry(&rcmPtr->map,
+ chanPtr->state->channelName, &isNew);
+ if (!isNew) {
+ if (chanPtr != Tcl_GetHashValue(hPtr)) {
+ Tcl_Panic("TclChanCreateObjCmd: duplicate channel names");
+ }
+ }
+ Tcl_SetHashValue(hPtr, chan);
+#ifdef TCL_THREADS
+ rcmPtr = GetThreadReflectedChannelMap();
+ hPtr = Tcl_CreateHashEntry(&rcmPtr->map,
+ chanPtr->state->channelName, &isNew);
+ Tcl_SetHashValue(hPtr, chan);
+#endif
+
+ /*
+ * Return handle as result of command.
+ */
+
+ Tcl_SetObjResult(interp, rcId);
+ return TCL_OK;
+
+ error:
+ /*
+ * Signal to ReflectClose to not call 'finalize'.
+ */
+
+ rcPtr->methods = 0;
+ Tcl_Close(interp, chan);
+ return TCL_ERROR;
+
+#undef MODE
+#undef CMD
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclChanPostEventObjCmd --
+ *
+ * This function is invoked to process the "chan postevent" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Posts events to a reflected channel, invokes event handlers. The
+ * latter implies that arbitrary side effects are possible.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclChanPostEventObjCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ /*
+ * Syntax: chan postevent CHANNEL EVENTSPEC
+ * [0] [1] [2] [3]
+ *
+ * Actually: rPostevent CHANNEL EVENTSPEC
+ * [0] [1] [2]
+ *
+ * where EVENTSPEC = {read write ...} (Abbreviations allowed as well).
+ */
+
+#define CHAN (1)
+#define EVENT (2)
+
+ const char *chanId; /* Tcl level channel handle */
+ Tcl_Channel chan; /* Channel associated to the handle */
+ const Tcl_ChannelType *chanTypePtr;
+ /* Its associated driver structure */
+ ReflectedChannel *rcPtr; /* Associated instance data */
+ int events; /* Mask of events to post */
+ ReflectedChannelMap* rcmPtr; /* Map of reflected channels with handlers in this interp */
+ Tcl_HashEntry* hPtr; /* Entry in the above map */
+
+ /*
+ * Number of arguments...
+ */
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "channel eventspec");
+ return TCL_ERROR;
+ }
+
+ /*
+ * First argument is a channel, a reflected channel, and the call of this
+ * command is done from the interp defining the channel handler cmd.
+ */
+
+ chanId = TclGetString(objv[CHAN]);
+
+ rcmPtr = GetReflectedChannelMap (interp);
+ hPtr = Tcl_FindHashEntry (&rcmPtr->map, chanId);
+
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "can not find reflected channel named \"", chanId,
+ "\"", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CHANNEL", chanId, NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Note that the search above subsumes several of the older checks, namely:
+ *
+ * (1) Does the channel handle refer to a reflected channel ?
+ * (2) Is the post event issued from the interpreter holding the handler
+ * of the reflected channel ?
+ *
+ * A successful search answers yes to both. Because the map holds only
+ * handles of reflected channels, and only of such whose handler is
+ * defined in this interpreter.
+ *
+ * We keep the old checks for both, for paranioa, but abort now instead of
+ * throwing errors, as failure now means that our internal datastructures
+ * have gone seriously haywire.
+ */
+
+ chan = Tcl_GetHashValue(hPtr);
+ chanTypePtr = Tcl_GetChannelType(chan);
+
+ /*
+ * We use a function referenced by the channel type as our cookie to
+ * detect calls to non-reflecting channels. The channel type itself is not
+ * suitable, as it might not be the static definition in this file, but a
+ * clone thereof. And while we have reserved the name of the type nothing
+ * in the core checks against violation, so someone else might have
+ * created a channel type using our name, clashing with ourselves.
+ */
+
+ if (chanTypePtr->watchProc != &ReflectWatch) {
+ Tcl_Panic ("TclChanPostEventObjCmd: channel is not a reflected channel");
+ }
+
+ rcPtr = (ReflectedChannel *) Tcl_GetChannelInstanceData(chan);
+
+ if (rcPtr->interp != interp) {
+ Tcl_Panic ("TclChanPostEventObjCmd: postevent accepted for call from outside interpreter");
+ }
+
+ /*
+ * Second argument is a list of events. Allowed entries are "read",
+ * "write". Expect at least one list element. Abbreviations are ok.
+ */
+
+ if (EncodeEventMask(interp, "event", objv[EVENT], &events) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Check that the channel is actually interested in the provided events.
+ */
+
+ if (events & ~rcPtr->interest) {
+ Tcl_AppendResult(interp, "tried to post events channel \"", chanId,
+ "\" is not interested in", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * We have the channel and the events to post.
+ */
+
+ Tcl_NotifyChannel(chan, events);
+
+ /*
+ * Squash interp results left by the event script.
+ */
+
+ Tcl_ResetResult(interp);
+ return TCL_OK;
+
+#undef CHAN
+#undef EVENT
+}
+
+/*
+ * Channel error message marshalling utilities.
+ */
+
+static Tcl_Obj*
+MarshallError(
+ Tcl_Interp *interp)
+{
+ /*
+ * Capture the result status of the interpreter into a string. => List of
+ * options and values, followed by the error message. The result has
+ * refCount 0.
+ */
+
+ Tcl_Obj *returnOpt = Tcl_GetReturnOptions(interp, TCL_ERROR);
+
+ /*
+ * => returnOpt.refCount == 0. We can append directly.
+ */
+
+ Tcl_ListObjAppendElement(NULL, returnOpt, Tcl_GetObjResult(interp));
+ return returnOpt;
+}
+
+static void
+UnmarshallErrorResult(
+ Tcl_Interp *interp,
+ Tcl_Obj *msgObj)
+{
+ int lc;
+ Tcl_Obj **lv;
+ int explicitResult;
+ int numOptions;
+
+ /*
+ * Process the caught message.
+ *
+ * Syntax = (option value)... ?message?
+ *
+ * Bad syntax causes a panic. This is OK because the other side uses
+ * Tcl_GetReturnOptions and list construction functions to marshall the
+ * information; if we panic here, something has gone badly wrong already.
+ */
+
+ if (Tcl_ListObjGetElements(interp, msgObj, &lc, &lv) != TCL_OK) {
+ Tcl_Panic("TclChanCaughtErrorBypass: Bad syntax of caught result");
+ }
+ if (interp == NULL) {
+ return;
+ }
+
+ explicitResult = lc & 1; /* Odd number of values? */
+ numOptions = lc - explicitResult;
+
+ if (explicitResult) {
+ Tcl_SetObjResult(interp, lv[lc-1]);
+ }
+
+ (void) Tcl_SetReturnOptions(interp, Tcl_NewListObj(numOptions, lv));
+ ((Interp *)interp)->flags &= ~ERR_ALREADY_LOGGED;
+}
+
+int
+TclChanCaughtErrorBypass(
+ Tcl_Interp *interp,
+ Tcl_Channel chan)
+{
+ Tcl_Obj *chanMsgObj = NULL;
+ Tcl_Obj *interpMsgObj = NULL;
+ Tcl_Obj *msgObj = NULL;
+
+ /*
+ * Get a bypassed error message from channel and/or interpreter, save the
+ * reference, then kill the returned objects, if there were any. If there
+ * are messages in both the channel has preference.
+ */
+
+ if ((chan == NULL) && (interp == NULL)) {
+ return 0;
+ }
+
+ if (chan != NULL) {
+ Tcl_GetChannelError(chan, &chanMsgObj);
+ }
+ if (interp != NULL) {
+ Tcl_GetChannelErrorInterp(interp, &interpMsgObj);
+ }
+
+ if (chanMsgObj != NULL) {
+ msgObj = chanMsgObj;
+ } else if (interpMsgObj != NULL) {
+ msgObj = interpMsgObj;
+ }
+ if (msgObj != NULL) {
+ Tcl_IncrRefCount(msgObj);
+ }
+
+ if (chanMsgObj != NULL) {
+ Tcl_DecrRefCount(chanMsgObj);
+ }
+ if (interpMsgObj != NULL) {
+ Tcl_DecrRefCount(interpMsgObj);
+ }
+
+ /*
+ * No message returned, nothing caught.
+ */
+
+ if (msgObj == NULL) {
+ return 0;
+ }
+
+ UnmarshallErrorResult(interp, msgObj);
+
+ Tcl_DecrRefCount(msgObj);
+ return 1;
+}
+
+/*
+ * Driver functions. ================================================
+ */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReflectClose --
+ *
+ * This function is invoked when the channel is closed, to delete the
+ * driver specific instance data.
+ *
+ * Results:
+ * A posix error.
+ *
+ * Side effects:
+ * Releases memory. Arbitrary, as it calls upon a script.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReflectClose(
+ ClientData clientData,
+ Tcl_Interp *interp)
+{
+ ReflectedChannel *rcPtr = (ReflectedChannel *) clientData;
+ int result; /* Result code for 'close' */
+ Tcl_Obj *resObj; /* Result data for 'close' */
+ ReflectedChannelMap* rcmPtr; /* Map of reflected channels with handlers in this interp */
+ Tcl_HashEntry* hPtr; /* Entry in the above map */
+
+ if (TclInThreadExit()) {
+ /*
+ * This call comes from TclFinalizeIOSystem. There are no
+ * interpreters, and therefore we cannot call upon the handler command
+ * anymore. Threading is irrelevant as well. We simply clean up all
+ * our C level data structures and leave the Tcl level to the other
+ * finalization functions.
+ */
+
+ /*
+ * THREADED => Forward this to the origin thread
+ *
+ * Note: DeleteThreadReflectedChannelMap() is the thread exit handler for the origin
+ * thread. Use this to clean up the structure? Except if lost?
+ */
+
+#ifdef TCL_THREADS
+ if (rcPtr->thread != Tcl_GetCurrentThread()) {
+ ForwardParam p;
+
+ ForwardOpToOwnerThread(rcPtr, ForwardedClose, &p);
+ result = p.base.code;
+
+ /*
+ * FreeReflectedChannel is done in the forwarded operation!, in
+ * the other thread. rcPtr here is gone!
+ */
+
+ if (result != TCL_OK) {
+ FreeReceivedError(&p);
+ }
+ return EOK;
+ }
+#endif
+
+ Tcl_EventuallyFree (rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
+ return EOK;
+ }
+
+ /*
+ * -- No -- ASSERT rcPtr->methods & FLAG(METH_FINAL)
+ *
+ * A cleaned method mask here implies that the channel creation was
+ * aborted, and "finalize" must not be called.
+ */
+
+ if (rcPtr->methods == 0) {
+ Tcl_EventuallyFree (rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
+ return EOK;
+ }
+
+ /*
+ * Are we in the correct thread?
+ */
+
+#ifdef TCL_THREADS
+ if (rcPtr->thread != Tcl_GetCurrentThread()) {
+ ForwardParam p;
+
+ ForwardOpToOwnerThread(rcPtr, ForwardedClose, &p);
+ result = p.base.code;
+
+ /*
+ * FreeReflectedChannel is done in the forwarded operation!, in the
+ * other thread. rcPtr here is gone!
+ */
+
+ if (result != TCL_OK) {
+ PassReceivedErrorInterp(interp, &p);
+ }
+ } else {
+#endif
+ result = InvokeTclMethod(rcPtr, "finalize", NULL, NULL, &resObj);
+ if ((result != TCL_OK) && (interp != NULL)) {
+ Tcl_SetChannelErrorInterp(interp, resObj);
+ }
+
+ Tcl_DecrRefCount(resObj); /* Remove reference we held from the
+ * invoke */
+
+ /*
+ * Remove the channel from the map before releasing the memory, to
+ * prevent future accesses (like by 'postevent') from finding and
+ * dereferencing a dangling pointer.
+ *
+ * NOTE: The channel may not be in the map. This is ok, that happens
+ * when the channel was created in a different interpreter and/or
+ * thread and then was moved here.
+ *
+ * NOTE: The channel may have been removed from the map already via
+ * the per-interp DeleteReflectedChannelMap exit-handler.
+ */
+
+ if (rcPtr->interp) {
+ rcmPtr = GetReflectedChannelMap (rcPtr->interp);
+ hPtr = Tcl_FindHashEntry (&rcmPtr->map,
+ Tcl_GetChannelName (rcPtr->chan));
+ if (hPtr) {
+ Tcl_DeleteHashEntry (hPtr);
+ }
+ }
+#ifdef TCL_THREADS
+ rcmPtr = GetThreadReflectedChannelMap();
+ hPtr = Tcl_FindHashEntry (&rcmPtr->map,
+ Tcl_GetChannelName (rcPtr->chan));
+ if (hPtr) {
+ Tcl_DeleteHashEntry (hPtr);
+ }
+#endif
+
+ Tcl_EventuallyFree (rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
+#ifdef TCL_THREADS
+ }
+#endif
+ return (result == TCL_OK) ? EOK : EINVAL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReflectInput --
+ *
+ * This function is invoked when more data is requested from the channel.
+ *
+ * Results:
+ * The number of bytes read.
+ *
+ * Side effects:
+ * Allocates memory. Arbitrary, as it calls upon a script.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReflectInput(
+ ClientData clientData,
+ char *buf,
+ int toRead,
+ int *errorCodePtr)
+{
+ ReflectedChannel *rcPtr = (ReflectedChannel *) clientData;
+ Tcl_Obj *toReadObj;
+ int bytec; /* Number of returned bytes */
+ unsigned char *bytev; /* Array of returned bytes */
+ Tcl_Obj *resObj; /* Result data for 'read' */
+
+ /*
+ * The following check can be done before thread redirection, because we
+ * are reading from an item which is readonly, i.e. will never change
+ * during the lifetime of the channel.
+ */
+
+ if (!(rcPtr->methods & FLAG(METH_READ))) {
+ SetChannelErrorStr(rcPtr->chan, msg_read_unsup);
+ *errorCodePtr = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Are we in the correct thread?
+ */
+
+#ifdef TCL_THREADS
+ if (rcPtr->thread != Tcl_GetCurrentThread()) {
+ ForwardParam p;
+
+ p.input.buf = buf;
+ p.input.toRead = toRead;
+
+ ForwardOpToOwnerThread(rcPtr, ForwardedInput, &p);
+
+ if (p.base.code != TCL_OK) {
+ if (p.base.code < 0) {
+ /* No error message, this is an errno signal. */
+ *errorCodePtr = -p.base.code;
+ } else {
+ PassReceivedError(rcPtr->chan, &p);
+ *errorCodePtr = EINVAL;
+ }
+ p.input.toRead = -1;
+ } else {
+ *errorCodePtr = EOK;
+ }
+
+ return p.input.toRead;
+ }
+#endif
+
+ /* ASSERT: rcPtr->method & FLAG(METH_READ) */
+ /* ASSERT: rcPtr->mode & TCL_READABLE */
+
+ Tcl_Preserve(rcPtr);
+
+ toReadObj = Tcl_NewIntObj(toRead);
+ Tcl_IncrRefCount(toReadObj);
+
+ if (InvokeTclMethod(rcPtr, "read", toReadObj, NULL, &resObj)!=TCL_OK) {
+ int code = ErrnoReturn (rcPtr, resObj);
+
+ if (code < 0) {
+ *errorCodePtr = -code;
+ goto error;
+ }
+
+ Tcl_SetChannelError(rcPtr->chan, resObj);
+ goto invalid;
+ }
+
+ bytev = Tcl_GetByteArrayFromObj(resObj, &bytec);
+
+ if (toRead < bytec) {
+ SetChannelErrorStr(rcPtr->chan, msg_read_toomuch);
+ goto invalid;
+ }
+
+ *errorCodePtr = EOK;
+
+ if (bytec > 0) {
+ memcpy(buf, bytev, (size_t)bytec);
+ }
+
+ stop:
+ Tcl_DecrRefCount(toReadObj);
+ Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
+ Tcl_Release(rcPtr);
+ return bytec;
+ invalid:
+ *errorCodePtr = EINVAL;
+ error:
+ bytec = -1;
+ goto stop;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReflectOutput --
+ *
+ * This function is invoked when data is writen to the channel.
+ *
+ * Results:
+ * The number of bytes actually written.
+ *
+ * Side effects:
+ * Allocates memory. Arbitrary, as it calls upon a script.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReflectOutput(
+ ClientData clientData,
+ const char *buf,
+ int toWrite,
+ int *errorCodePtr)
+{
+ ReflectedChannel *rcPtr = (ReflectedChannel *) clientData;
+ Tcl_Obj *bufObj;
+ Tcl_Obj *resObj; /* Result data for 'write' */
+ int written;
+
+ /*
+ * The following check can be done before thread redirection, because we
+ * are reading from an item which is readonly, i.e. will never change
+ * during the lifetime of the channel.
+ */
+
+ if (!(rcPtr->methods & FLAG(METH_WRITE))) {
+ SetChannelErrorStr(rcPtr->chan, msg_write_unsup);
+ *errorCodePtr = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Are we in the correct thread?
+ */
+
+#ifdef TCL_THREADS
+ if (rcPtr->thread != Tcl_GetCurrentThread()) {
+ ForwardParam p;
+
+ p.output.buf = buf;
+ p.output.toWrite = toWrite;
+
+ ForwardOpToOwnerThread(rcPtr, ForwardedOutput, &p);
+
+ if (p.base.code != TCL_OK) {
+ if (p.base.code < 0) {
+ /* No error message, this is an errno signal. */
+ *errorCodePtr = -p.base.code;
+ } else {
+ PassReceivedError(rcPtr->chan, &p);
+ *errorCodePtr = EINVAL;
+ }
+ p.output.toWrite = -1;
+ } else {
+ *errorCodePtr = EOK;
+ }
+
+ return p.output.toWrite;
+ }
+#endif
+
+ /* ASSERT: rcPtr->method & FLAG(METH_WRITE) */
+ /* ASSERT: rcPtr->mode & TCL_WRITABLE */
+
+ Tcl_Preserve(rcPtr);
+
+ bufObj = Tcl_NewByteArrayObj((unsigned char *) buf, toWrite);
+ Tcl_IncrRefCount(bufObj);
+
+ if (InvokeTclMethod(rcPtr, "write", bufObj, NULL, &resObj) != TCL_OK) {
+ int code = ErrnoReturn(rcPtr, resObj);
+
+ if (code < 0) {
+ *errorCodePtr = -code;
+ goto error;
+ }
+
+ Tcl_SetChannelError(rcPtr->chan, resObj);
+ goto invalid;
+ }
+
+ if (Tcl_GetIntFromObj(rcPtr->interp, resObj, &written) != TCL_OK) {
+ Tcl_SetChannelError(rcPtr->chan, MarshallError(rcPtr->interp));
+ goto invalid;
+ }
+
+ if ((written == 0) && (toWrite > 0)) {
+ /*
+ * The handler claims to have written nothing of what it was
+ * given. That is bad.
+ */
+
+ SetChannelErrorStr(rcPtr->chan, msg_write_nothing);
+ goto invalid;
+ }
+ if (toWrite < written) {
+ /*
+ * The handler claims to have written more than it was given. That is
+ * bad. Note that the I/O core would crash if we were to return this
+ * information, trying to write -nnn bytes in the next iteration.
+ */
+
+ SetChannelErrorStr(rcPtr->chan, msg_write_toomuch);
+ goto invalid;
+ }
+
+ *errorCodePtr = EOK;
+ stop:
+ Tcl_DecrRefCount(bufObj);
+ Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
+ Tcl_Release(rcPtr);
+ return written;
+ invalid:
+ *errorCodePtr = EINVAL;
+ error:
+ written = -1;
+ goto stop;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReflectSeekWide / ReflectSeek --
+ *
+ * This function is invoked when the user wishes to seek on the channel.
+ *
+ * Results:
+ * The new location of the access point.
+ *
+ * Side effects:
+ * Allocates memory. Arbitrary, as it calls upon a script.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_WideInt
+ReflectSeekWide(
+ ClientData clientData,
+ Tcl_WideInt offset,
+ int seekMode,
+ int *errorCodePtr)
+{
+ ReflectedChannel *rcPtr = (ReflectedChannel *) clientData;
+ Tcl_Obj *offObj, *baseObj;
+ Tcl_Obj *resObj; /* Result for 'seek' */
+ Tcl_WideInt newLoc;
+
+ /*
+ * Are we in the correct thread?
+ */
+
+#ifdef TCL_THREADS
+ if (rcPtr->thread != Tcl_GetCurrentThread()) {
+ ForwardParam p;
+
+ p.seek.seekMode = seekMode;
+ p.seek.offset = offset;
+
+ ForwardOpToOwnerThread(rcPtr, ForwardedSeek, &p);
+
+ if (p.base.code != TCL_OK) {
+ PassReceivedError(rcPtr->chan, &p);
+ *errorCodePtr = EINVAL;
+ p.seek.offset = -1;
+ } else {
+ *errorCodePtr = EOK;
+ }
+
+ return p.seek.offset;
+ }
+#endif
+
+ /* ASSERT: rcPtr->method & FLAG(METH_SEEK) */
+
+ Tcl_Preserve(rcPtr);
+
+ offObj = Tcl_NewWideIntObj(offset);
+ baseObj = Tcl_NewStringObj((seekMode == SEEK_SET) ? "start" :
+ ((seekMode == SEEK_CUR) ? "current" : "end"), -1);
+ Tcl_IncrRefCount(offObj);
+ Tcl_IncrRefCount(baseObj);
+
+ if (InvokeTclMethod(rcPtr, "seek", offObj, baseObj, &resObj)!=TCL_OK) {
+ Tcl_SetChannelError(rcPtr->chan, resObj);
+ goto invalid;
+ }
+
+ if (Tcl_GetWideIntFromObj(rcPtr->interp, resObj, &newLoc) != TCL_OK) {
+ Tcl_SetChannelError(rcPtr->chan, MarshallError(rcPtr->interp));
+ goto invalid;
+ }
+
+ if (newLoc < Tcl_LongAsWide(0)) {
+ SetChannelErrorStr(rcPtr->chan, msg_seek_beforestart);
+ goto invalid;
+ }
+
+ *errorCodePtr = EOK;
+ stop:
+ Tcl_DecrRefCount(offObj);
+ Tcl_DecrRefCount(baseObj);
+ Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
+ Tcl_Release(rcPtr);
+ return newLoc;
+ invalid:
+ *errorCodePtr = EINVAL;
+ newLoc = -1;
+ goto stop;
+}
+
+static int
+ReflectSeek(
+ ClientData clientData,
+ long offset,
+ int seekMode,
+ int *errorCodePtr)
+{
+ /*
+ * This function can be invoked from a transformation which is based on
+ * standard seeking, i.e. non-wide. Because of this we have to implement
+ * it, a dummy is not enough. We simply delegate the call to the wide
+ * routine.
+ */
+
+ return (int) ReflectSeekWide(clientData, Tcl_LongAsWide(offset), seekMode,
+ errorCodePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReflectWatch --
+ *
+ * This function is invoked to tell the channel what events the I/O
+ * system is interested in.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Allocates memory. Arbitrary, as it calls upon a script.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ReflectWatch(
+ ClientData clientData,
+ int mask)
+{
+ ReflectedChannel *rcPtr = (ReflectedChannel *) clientData;
+ Tcl_Obj *maskObj;
+
+ /* ASSERT rcPtr->methods & FLAG(METH_WATCH) */
+
+ /*
+ * We restrict the interest to what the channel can support. IOW there
+ * will never be write events for a channel which is not writable.
+ * Analoguously for read events and non-readable channels.
+ */
+
+ mask &= rcPtr->mode;
+
+ if (mask == rcPtr->interest) {
+ /*
+ * Same old, same old, why should we do something?
+ */
+
+ return;
+ }
+
+ rcPtr->interest = mask;
+
+ /*
+ * Are we in the correct thread?
+ */
+
+#ifdef TCL_THREADS
+ if (rcPtr->thread != Tcl_GetCurrentThread()) {
+ ForwardParam p;
+
+ p.watch.mask = mask;
+ ForwardOpToOwnerThread(rcPtr, ForwardedWatch, &p);
+
+ /*
+ * Any failure from the forward is ignored. We have no place to put
+ * this.
+ */
+
+ return;
+ }
+#endif
+
+ Tcl_Preserve(rcPtr);
+
+ maskObj = DecodeEventMask(mask);
+ /* assert maskObj.refCount == 1 */
+ (void) InvokeTclMethod(rcPtr, "watch", maskObj, NULL, NULL);
+ Tcl_DecrRefCount(maskObj);
+
+ Tcl_Release(rcPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReflectBlock --
+ *
+ * This function is invoked to tell the channel which blocking behaviour
+ * is required of it.
+ *
+ * Results:
+ * A posix error number.
+ *
+ * Side effects:
+ * Allocates memory. Arbitrary, as it calls upon a script.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReflectBlock(
+ ClientData clientData,
+ int nonblocking)
+{
+ ReflectedChannel *rcPtr = (ReflectedChannel *) clientData;
+ Tcl_Obj *blockObj;
+ int errorNum; /* EINVAL or EOK (success). */
+ Tcl_Obj *resObj; /* Result data for 'blocking' */
+
+ /*
+ * Are we in the correct thread?
+ */
+
+#ifdef TCL_THREADS
+ if (rcPtr->thread != Tcl_GetCurrentThread()) {
+ ForwardParam p;
+
+ p.block.nonblocking = nonblocking;
+
+ ForwardOpToOwnerThread(rcPtr, ForwardedBlock, &p);
+
+ if (p.base.code != TCL_OK) {
+ PassReceivedError(rcPtr->chan, &p);
+ return EINVAL;
+ }
+
+ return EOK;
+ }
+#endif
+
+ blockObj = Tcl_NewBooleanObj(!nonblocking);
+ Tcl_IncrRefCount(blockObj);
+
+ Tcl_Preserve(rcPtr);
+
+ if (InvokeTclMethod(rcPtr, "blocking", blockObj, NULL, &resObj) != TCL_OK) {
+ Tcl_SetChannelError(rcPtr->chan, resObj);
+ errorNum = EINVAL;
+ } else {
+ errorNum = EOK;
+ }
+
+ Tcl_DecrRefCount(blockObj);
+ Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
+
+ Tcl_Release(rcPtr);
+ return errorNum;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReflectSetOption --
+ *
+ * This function is invoked to configure a channel option.
+ *
+ * Results:
+ * A standard Tcl result code.
+ *
+ * Side effects:
+ * Arbitrary, as it calls upon a Tcl script.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReflectSetOption(
+ ClientData clientData, /* Channel to query */
+ Tcl_Interp *interp, /* Interpreter to leave error messages in */
+ const char *optionName, /* Name of requested option */
+ const char *newValue) /* The new value */
+{
+ ReflectedChannel *rcPtr = (ReflectedChannel *) clientData;
+ Tcl_Obj *optionObj, *valueObj;
+ int result; /* Result code for 'configure' */
+ Tcl_Obj *resObj; /* Result data for 'configure' */
+
+ /*
+ * Are we in the correct thread?
+ */
+
+#ifdef TCL_THREADS
+ if (rcPtr->thread != Tcl_GetCurrentThread()) {
+ ForwardParam p;
+
+ p.setOpt.name = optionName;
+ p.setOpt.value = newValue;
+
+ ForwardOpToOwnerThread(rcPtr, ForwardedSetOpt, &p);
+
+ if (p.base.code != TCL_OK) {
+ Tcl_Obj *err = Tcl_NewStringObj(p.base.msgStr, -1);
+
+ UnmarshallErrorResult(interp, err);
+ Tcl_DecrRefCount(err);
+ FreeReceivedError(&p);
+ }
+
+ return p.base.code;
+ }
+#endif
+ Tcl_Preserve(rcPtr);
+
+ optionObj = Tcl_NewStringObj(optionName, -1);
+ valueObj = Tcl_NewStringObj(newValue, -1);
+
+ Tcl_IncrRefCount(optionObj);
+ Tcl_IncrRefCount(valueObj);
+
+ result = InvokeTclMethod(rcPtr, "configure",optionObj,valueObj, &resObj);
+ if (result != TCL_OK) {
+ UnmarshallErrorResult(interp, resObj);
+ }
+
+ Tcl_DecrRefCount(optionObj);
+ Tcl_DecrRefCount(valueObj);
+ Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
+ Tcl_Release(rcPtr);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReflectGetOption --
+ *
+ * This function is invoked to retrieve all or a channel option.
+ *
+ * Results:
+ * A standard Tcl result code.
+ *
+ * Side effects:
+ * Arbitrary, as it calls upon a Tcl script.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ReflectGetOption(
+ ClientData clientData, /* Channel to query */
+ Tcl_Interp *interp, /* Interpreter to leave error messages in */
+ const char *optionName, /* Name of reuqested option */
+ Tcl_DString *dsPtr) /* String to place the result into */
+{
+ /*
+ * This code is special. It has regular passing of Tcl result, and errors.
+ * The bypass functions are not required.
+ */
+
+ ReflectedChannel *rcPtr = (ReflectedChannel*) clientData;
+ Tcl_Obj *optionObj;
+ Tcl_Obj *resObj; /* Result data for 'configure' */
+ int listc, result = TCL_OK;
+ Tcl_Obj **listv;
+ const char *method;
+
+ /*
+ * Are we in the correct thread?
+ */
+
+#ifdef TCL_THREADS
+ if (rcPtr->thread != Tcl_GetCurrentThread()) {
+ int opcode;
+ ForwardParam p;
+
+ p.getOpt.name = optionName;
+ p.getOpt.value = dsPtr;
+
+ if (optionName == NULL) {
+ opcode = ForwardedGetOptAll;
+ } else {
+ opcode = ForwardedGetOpt;
+ }
+
+ ForwardOpToOwnerThread(rcPtr, opcode, &p);
+
+ if (p.base.code != TCL_OK) {
+ Tcl_Obj *err = Tcl_NewStringObj(p.base.msgStr, -1);
+
+ UnmarshallErrorResult(interp, err);
+ Tcl_DecrRefCount(err);
+ FreeReceivedError(&p);
+ }
+
+ return p.base.code;
+ }
+#endif
+
+ if (optionName == NULL) {
+ /*
+ * Retrieve all options.
+ */
+
+ method = "cgetall";
+ optionObj = NULL;
+ } else {
+ /*
+ * Retrieve the value of one option.
+ */
+
+ method = "cget";
+ optionObj = Tcl_NewStringObj(optionName, -1);
+ Tcl_IncrRefCount(optionObj);
+ }
+
+ Tcl_Preserve(rcPtr);
+
+ if (InvokeTclMethod(rcPtr, method, optionObj, NULL, &resObj)!=TCL_OK) {
+ UnmarshallErrorResult(interp, resObj);
+ goto error;
+ }
+
+ /*
+ * The result has to go into the 'dsPtr' for propagation to the caller of
+ * the driver.
+ */
+
+ if (optionObj != NULL) {
+ Tcl_DStringAppend(dsPtr, TclGetString(resObj), -1);
+ goto ok;
+ }
+
+ /*
+ * Extract the list and append each item as element.
+ */
+
+ /*
+ * NOTE (4): If we extract the string rep we can assume a properly quoted
+ * string. Together with a separating space this way of simply appending
+ * the whole string rep might be faster. It also doesn't check if the
+ * result is a valid list. Nor that the list has an even number elements.
+ */
+
+ if (Tcl_ListObjGetElements(interp, resObj, &listc, &listv) != TCL_OK) {
+ goto error;
+ }
+
+ if ((listc % 2) == 1) {
+ /*
+ * Odd number of elements is wrong.
+ */
+
+ Tcl_ResetResult(interp);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Expected list with even number of "
+ "elements, got %d element%s instead", listc,
+ (listc == 1 ? "" : "s")));
+ goto error;
+ } else {
+ int len;
+ char *str = Tcl_GetStringFromObj(resObj, &len);
+
+ if (len) {
+ Tcl_DStringAppend(dsPtr, " ", 1);
+ Tcl_DStringAppend(dsPtr, str, len);
+ }
+ goto ok;
+ }
+
+ ok:
+ result = TCL_OK;
+ stop:
+ if (optionObj) {
+ Tcl_DecrRefCount(optionObj);
+ }
+ Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */
+ Tcl_Release(rcPtr);
+ return result;
+ error:
+ result = TCL_ERROR;
+ goto stop;
+}
+
+/*
+ * Helpers. =========================================================
+ */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EncodeEventMask --
+ *
+ * This function takes a list of event items and constructs the
+ * equivalent internal bitmask. The list must contain at least one
+ * element. Elements are "read", "write", or any unique abbreviation of
+ * them. Note that the bitmask is not changed if problems are
+ * encountered.
+ *
+ * Results:
+ * A standard Tcl error code. A bitmask where TCL_READABLE and/or
+ * TCL_WRITABLE can be set.
+ *
+ * Side effects:
+ * May shimmer 'obj' to a list representation. May place an error message
+ * into the interp result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+EncodeEventMask(
+ Tcl_Interp *interp,
+ const char *objName,
+ Tcl_Obj *obj,
+ int *mask)
+{
+ int events; /* Mask of events to post */
+ int listc; /* #elements in eventspec list */
+ Tcl_Obj **listv; /* Elements of eventspec list */
+ int evIndex; /* Id of event for an element of the eventspec
+ * list. */
+
+ if (Tcl_ListObjGetElements(interp, obj, &listc, &listv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (listc < 1) {
+ Tcl_AppendResult(interp, "bad ", objName, " list: is empty", NULL);
+ return TCL_ERROR;
+ }
+
+ events = 0;
+ while (listc > 0) {
+ if (Tcl_GetIndexFromObj(interp, listv[listc-1], eventOptions,
+ objName, 0, &evIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch (evIndex) {
+ case EVENT_READ:
+ events |= TCL_READABLE;
+ break;
+ case EVENT_WRITE:
+ events |= TCL_WRITABLE;
+ break;
+ }
+ listc --;
+ }
+
+ *mask = events;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DecodeEventMask --
+ *
+ * This function takes an internal bitmask of events and constructs the
+ * equivalent list of event items.
+ *
+ * Results:
+ * A Tcl_Obj reference. The object will have a refCount of one. The user
+ * has to decrement it to release the object.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+DecodeEventMask(
+ int mask)
+{
+ register const char *eventStr;
+ Tcl_Obj *evObj;
+
+ switch (mask & RANDW) {
+ case RANDW:
+ eventStr = "read write";
+ break;
+ case TCL_READABLE:
+ eventStr = "read";
+ break;
+ case TCL_WRITABLE:
+ eventStr = "write";
+ break;
+ default:
+ eventStr = "";
+ break;
+ }
+
+ evObj = Tcl_NewStringObj(eventStr, -1);
+ Tcl_IncrRefCount(evObj);
+ return evObj;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NewReflectedChannel --
+ *
+ * This function is invoked to allocate and initialize the instance data
+ * of a new reflected channel.
+ *
+ * Results:
+ * A heap-allocated channel instance.
+ *
+ * Side effects:
+ * Allocates memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static ReflectedChannel *
+NewReflectedChannel(
+ Tcl_Interp *interp,
+ Tcl_Obj *cmdpfxObj,
+ int mode,
+ Tcl_Obj *handleObj)
+{
+ ReflectedChannel *rcPtr;
+ int i, listc;
+ Tcl_Obj **listv;
+
+ rcPtr = (ReflectedChannel *) ckalloc(sizeof(ReflectedChannel));
+
+ /* rcPtr->chan: Assigned by caller. Dummy data here. */
+ /* rcPtr->methods: Assigned by caller. Dummy data here. */
+
+ rcPtr->chan = NULL;
+ rcPtr->methods = 0;
+ rcPtr->interp = interp;
+#ifdef TCL_THREADS
+ rcPtr->thread = Tcl_GetCurrentThread();
+#endif
+ rcPtr->mode = mode;
+ rcPtr->interest = 0; /* Initially no interest registered */
+
+ /*
+ * Method placeholder.
+ */
+
+ /* ASSERT: cmdpfxObj is a Tcl List */
+
+ Tcl_ListObjGetElements(interp, cmdpfxObj, &listc, &listv);
+
+ /*
+ * See [==] as well.
+ * Storage for the command prefix and the additional words required for
+ * the invocation of methods in the command handler.
+ *
+ * listv [0] [listc-1] | [listc] [listc+1] |
+ * argv [0] ... [.] | [argc-2] [argc-1] | [argc] [argc+2]
+ * cmd ... pfx | method chan | detail1 detail2
+ */
+
+ rcPtr->argc = listc + 2;
+ rcPtr->argv = (Tcl_Obj **) ckalloc(sizeof(Tcl_Obj *) * (listc+4));
+
+ /*
+ * Duplicate object references.
+ */
+
+ for (i=0; i<listc ; i++) {
+ Tcl_Obj *word = rcPtr->argv[i] = listv[i];
+
+ Tcl_IncrRefCount(word);
+ }
+
+ i++; /* Skip placeholder for method */
+
+ /*
+ * [Bug 1667990]: See [x] in FreeReflectedChannel for release
+ */
+
+ rcPtr->argv[i] = handleObj;
+ Tcl_IncrRefCount(handleObj);
+
+ /*
+ * The next two objects are kept empty, varying arguments.
+ */
+
+ /*
+ * Initialization complete.
+ */
+
+ return rcPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NextHandle --
+ *
+ * This function is invoked to generate a channel handle for a new
+ * reflected channel.
+ *
+ * Results:
+ * A Tcl_Obj containing the string of the new channel handle. The
+ * refcount of the returned object is -- zero --.
+ *
+ * Side effects:
+ * May allocate memory. Mutex protected critical section locks out other
+ * threads for a short time.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+NextHandle(void)
+{
+ /*
+ * Count number of generated reflected channels. Used for id generation.
+ * Ids are never reclaimed and there is no dealing with wrap around. On
+ * the other hand, "unsigned long" should be big enough except for
+ * absolute longrunners (generate a 100 ids per second => overflow will
+ * occur in 1 1/3 years).
+ */
+
+ TCL_DECLARE_MUTEX(rcCounterMutex)
+ static unsigned long rcCounter = 0;
+ Tcl_Obj *resObj;
+
+ Tcl_MutexLock(&rcCounterMutex);
+ resObj = Tcl_ObjPrintf("rc%lu", rcCounter);
+ rcCounter++;
+ Tcl_MutexUnlock(&rcCounterMutex);
+
+ return resObj;
+}
+
+static void
+FreeReflectedChannel(
+ ReflectedChannel *rcPtr)
+{
+ Channel *chanPtr = (Channel *) rcPtr->chan;
+ int i, n;
+
+ if (chanPtr->typePtr != &tclRChannelType) {
+ /*
+ * Delete a cloned ChannelType structure.
+ */
+
+ ckfree((char*) chanPtr->typePtr);
+ }
+
+ n = rcPtr->argc - 2;
+ for (i=0; i<n; i++) {
+ Tcl_DecrRefCount(rcPtr->argv[i]);
+ }
+
+ /*
+ * [Bug 1667990]: See [x] in NewReflectedChannel for lock. n+1 = argc-1.
+ */
+
+ Tcl_DecrRefCount(rcPtr->argv[n+1]);
+
+ ckfree((char*) rcPtr->argv);
+ ckfree((char*) rcPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InvokeTclMethod --
+ *
+ * This function is used to invoke the Tcl level of a reflected channel.
+ * It handles all the command assembly, invokation, and generic state and
+ * result mgmt. It does *not* handle thread redirection; that is the
+ * responsibility of clients of this function.
+ *
+ * Results:
+ * Result code and data as returned by the method.
+ *
+ * Side effects:
+ * Arbitrary, as it calls upon a Tcl script.
+ *
+ * Contract:
+ * argOneObj.refCount >= 1 on entry and exit, if argOneObj != NULL
+ * argTwoObj.refCount >= 1 on entry and exit, if argTwoObj != NULL
+ * resObj.refCount in {0, 1, ...}
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+InvokeTclMethod(
+ ReflectedChannel *rcPtr,
+ const char *method,
+ Tcl_Obj *argOneObj, /* NULL'able */
+ Tcl_Obj *argTwoObj, /* NULL'able */
+ Tcl_Obj **resultObjPtr) /* NULL'able */
+{
+ int cmdc; /* #words in constructed command */
+ Tcl_Obj *methObj = NULL; /* Method name in object form */
+ Tcl_InterpState sr; /* State of handler interp */
+ int result; /* Result code of method invokation */
+ Tcl_Obj *resObj = NULL; /* Result of method invokation. */
+
+ if (!rcPtr->interp) {
+ /*
+ * The channel is marked as dead. Bail out immediately, with an
+ * appropriate error.
+ */
+
+ if (resultObjPtr != NULL) {
+ resObj = Tcl_NewStringObj(msg_dstlost,-1);
+ *resultObjPtr = resObj;
+ Tcl_IncrRefCount(resObj);
+ }
+
+ /*
+ * Not touching argOneObj, argTwoObj, they have not been used.
+ * See the contract as well.
+ */
+
+ return TCL_ERROR;
+ }
+
+ /*
+ * NOTE (5): Decide impl. issue: Cache objects with method names? Needs
+ * TSD data as reflections can be created in many different threads.
+ * NO: Caching of command resolutions means storage per channel.
+ */
+
+ /*
+ * Insert method into the pre-allocated area, after the command prefix,
+ * before the channel id.
+ */
+
+ methObj = Tcl_NewStringObj(method, -1);
+ Tcl_IncrRefCount(methObj);
+ rcPtr->argv[rcPtr->argc - 2] = methObj;
+
+ /*
+ * Append the additional argument containing method specific details
+ * behind the channel id. If specified.
+ */
+
+ cmdc = rcPtr->argc;
+ if (argOneObj) {
+ rcPtr->argv[cmdc] = argOneObj;
+ cmdc++;
+ if (argTwoObj) {
+ rcPtr->argv[cmdc] = argTwoObj;
+ cmdc++;
+ }
+ }
+
+ /*
+ * And run the handler... This is done in auch a manner which leaves any
+ * existing state intact.
+ */
+
+ sr = Tcl_SaveInterpState(rcPtr->interp, 0 /* Dummy */);
+ Tcl_Preserve(rcPtr->interp);
+ result = Tcl_EvalObjv(rcPtr->interp, cmdc, rcPtr->argv, TCL_EVAL_GLOBAL);
+
+ /*
+ * We do not try to extract the result information if the caller has no
+ * interest in it. I.e. there is no need to put effort into creating
+ * something which is discarded immediately after.
+ */
+
+ if (resultObjPtr) {
+ if (result == TCL_OK) {
+ /*
+ * Ok result taken as is, also if the caller requests that there
+ * is no capture.
+ */
+
+ resObj = Tcl_GetObjResult(rcPtr->interp);
+ } else {
+ /*
+ * Non-ok result is always treated as an error. We have to capture
+ * the full state of the result, including additional options.
+ *
+ * This is complex and ugly, and would be completely unnecessary
+ * if we only added support for a TCL_FORBID_EXCEPTIONS flag.
+ */
+
+ if (result != TCL_ERROR) {
+ Tcl_Obj *cmd = Tcl_NewListObj(cmdc, rcPtr->argv);
+ int cmdLen;
+ const char *cmdString = Tcl_GetStringFromObj(cmd, &cmdLen);
+
+ Tcl_IncrRefCount(cmd);
+ Tcl_ResetResult(rcPtr->interp);
+ Tcl_SetObjResult(rcPtr->interp, Tcl_ObjPrintf(
+ "chan handler returned bad code: %d", result));
+ Tcl_LogCommandInfo(rcPtr->interp, cmdString, cmdString,
+ cmdLen);
+ Tcl_DecrRefCount(cmd);
+ result = TCL_ERROR;
+ }
+ Tcl_AppendObjToErrorInfo(rcPtr->interp, Tcl_ObjPrintf(
+ "\n (chan handler subcommand \"%s\")", method));
+ resObj = MarshallError(rcPtr->interp);
+ }
+ Tcl_IncrRefCount(resObj);
+ }
+ Tcl_RestoreInterpState(rcPtr->interp, sr);
+ Tcl_Release(rcPtr->interp);
+
+ /*
+ * Cleanup of the dynamic parts of the command.
+ *
+ * The detail objects survived the Tcl_EvalObjv without change because of
+ * the contract. Therefore there is no need to decrement the refcounts. Only
+ * the internal method object has to be disposed of.
+ */
+
+ Tcl_DecrRefCount(methObj);
+
+ /*
+ * The resObj has a ref count of 1 at this location. This means that the
+ * caller of InvokeTclMethod has to dispose of it (but only if it was
+ * returned to it).
+ */
+
+ if (resultObjPtr != NULL) {
+ *resultObjPtr = resObj;
+ }
+
+ /*
+ * There no need to handle the case where nothing is returned, because for
+ * that case resObj was not set anyway.
+ */
+
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ErrnoReturn --
+ *
+ * Checks a method error result if it returned an 'errno'.
+ *
+ * Results:
+ * The negative errno found in the error result, or 0.
+ *
+ * Side effects:
+ * None.
+ *
+ * Users:
+ * ReflectInput/Output(), to enable the signaling of EAGAIN
+ * on 0-sized short reads/writes.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ErrnoReturn(ReflectedChannel *rcPtr, Tcl_Obj* resObj)
+{
+ int code;
+ Tcl_InterpState sr; /* State of handler interp */
+
+ if (!rcPtr->interp) {
+ return 0;
+ }
+
+ sr = Tcl_SaveInterpState(rcPtr->interp, 0 /* Dummy */);
+ UnmarshallErrorResult(rcPtr->interp, resObj);
+
+ resObj = Tcl_GetObjResult(rcPtr->interp);
+
+ if (((Tcl_GetIntFromObj(rcPtr->interp, resObj, &code) != TCL_OK) || (code >= 0))) {
+ if (strcmp ("EAGAIN",Tcl_GetString(resObj)) == 0) {
+ code = - EAGAIN;
+ } else {
+ code = 0;
+ }
+ }
+
+ Tcl_RestoreInterpState(rcPtr->interp, sr);
+ return code;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetReflectedChannelMap --
+ *
+ * Gets and potentially initializes the reflected channel map for an
+ * interpreter.
+ *
+ * Results:
+ * A pointer to the map created, for use by the caller.
+ *
+ * Side effects:
+ * Initializes the reflected channel map for an interpreter.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static ReflectedChannelMap *
+GetReflectedChannelMap(
+ Tcl_Interp *interp)
+{
+ ReflectedChannelMap* rcmPtr = Tcl_GetAssocData(interp, RCMKEY, NULL);
+
+ if (rcmPtr == NULL) {
+ rcmPtr = (ReflectedChannelMap *) ckalloc(sizeof(ReflectedChannelMap));
+ Tcl_InitHashTable(&rcmPtr->map, TCL_STRING_KEYS);
+ Tcl_SetAssocData(interp, RCMKEY,
+ (Tcl_InterpDeleteProc *) DeleteReflectedChannelMap, rcmPtr);
+ }
+ return rcmPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteReflectedChannelMap --
+ *
+ * Deletes the channel table for an interpreter, closing any open
+ * channels whose refcount reaches zero. This procedure is invoked when
+ * an interpreter is deleted, via the AssocData cleanup mechanism.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Deletes the hash table of channels. May close channels. May flush
+ * output on closed channels. Removes any channeEvent handlers that were
+ * registered in this interpreter.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DeleteReflectedChannelMap(
+ ClientData clientData, /* The per-interpreter data structure. */
+ Tcl_Interp *interp) /* The interpreter being deleted. */
+{
+ ReflectedChannelMap* rcmPtr; /* The map */
+ Tcl_HashSearch hSearch; /* Search variable. */
+ Tcl_HashEntry *hPtr; /* Search variable. */
+ ReflectedChannel* rcPtr;
+ Tcl_Channel chan;
+
+#ifdef TCL_THREADS
+ ForwardingResult *resultPtr;
+ ForwardingEvent *evPtr;
+ ForwardParam *paramPtr;
+#endif
+
+ /*
+ * Delete all entries. The channels may have been closed already, or will
+ * be closed later, by the standard IO finalization of an interpreter
+ * under destruction. Except for the channels which were moved to a
+ * different interpreter and/or thread. They do not exist from the IO
+ * systems point of view and will not get closed. Therefore mark all as
+ * dead so that any future access will cause a proper error. For channels
+ * in a different thread we actually do the same as
+ * DeleteThreadReflectedChannelMap(), just restricted to the channels of
+ * this interp.
+ */
+
+ rcmPtr = clientData;
+ for (hPtr = Tcl_FirstHashEntry(&rcmPtr->map, &hSearch);
+ hPtr != NULL;
+ hPtr = Tcl_FirstHashEntry(&rcmPtr->map, &hSearch)) {
+
+ chan = (Tcl_Channel) Tcl_GetHashValue (hPtr);
+ rcPtr = (ReflectedChannel *) Tcl_GetChannelInstanceData(chan);
+
+ rcPtr->interp = NULL;
+
+ Tcl_DeleteHashEntry(hPtr);
+ }
+ Tcl_DeleteHashTable(&rcmPtr->map);
+ ckfree((char *) &rcmPtr->map);
+
+#ifdef TCL_THREADS
+ /*
+ * The origin interpreter for one or more reflected channels is gone.
+ */
+
+ /*
+ * Go through the list of pending results and cancel all whose events were
+ * destined for this interpreter. While this is in progress we block any
+ * other access to the list of pending results.
+ */
+
+ Tcl_MutexLock(&rcForwardMutex);
+
+ for (resultPtr = forwardList;
+ resultPtr != NULL;
+ resultPtr = resultPtr->nextPtr) {
+ if (resultPtr->dsti != interp) {
+ /* Ignore results/events for other interpreters. */
+ continue;
+ }
+
+ /*
+ * The receiver for the event exited, before processing the event. We
+ * detach the result now, wake the originator up and signal failure.
+ */
+
+ evPtr = resultPtr->evPtr;
+ paramPtr = evPtr->param;
+
+ evPtr->resultPtr = NULL;
+ resultPtr->evPtr = NULL;
+ resultPtr->result = TCL_ERROR;
+
+ ForwardSetStaticError(paramPtr, msg_send_dstlost);
+
+ Tcl_ConditionNotify(&resultPtr->done);
+ }
+
+ /*
+ * Get the map of all channels handled by the current thread. This is a
+ * ReflectedChannelMap, but on a per-thread basis, not per-interp. Go
+ * through the channels and remove all which were handled by this
+ * interpreter. They have already been marked as dead.
+ */
+
+ rcmPtr = GetThreadReflectedChannelMap();
+ for (hPtr = Tcl_FirstHashEntry(&rcmPtr->map, &hSearch);
+ hPtr != NULL;
+ hPtr = Tcl_NextHashEntry(&hSearch)) {
+
+ chan = (Tcl_Channel) Tcl_GetHashValue (hPtr);
+ rcPtr = (ReflectedChannel *) Tcl_GetChannelInstanceData(chan);
+
+ if (rcPtr->interp != interp) {
+ /* Ignore entries for other interpreters */
+ continue;
+ }
+
+ Tcl_DeleteHashEntry(hPtr);
+ }
+
+ Tcl_MutexUnlock(&rcForwardMutex);
+#endif
+}
+
+#ifdef TCL_THREADS
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetThreadReflectedChannelMap --
+ *
+ * Gets and potentially initializes the reflected channel map for a
+ * thread.
+ *
+ * Results:
+ * A pointer to the map created, for use by the caller.
+ *
+ * Side effects:
+ * Initializes the reflected channel map for a thread.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static ReflectedChannelMap *
+GetThreadReflectedChannelMap()
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ if (!tsdPtr->rcmPtr) {
+ tsdPtr->rcmPtr = (ReflectedChannelMap *) ckalloc(sizeof(ReflectedChannelMap));
+ Tcl_InitHashTable(&tsdPtr->rcmPtr->map, TCL_STRING_KEYS);
+ Tcl_CreateThreadExitHandler(DeleteThreadReflectedChannelMap, NULL);
+ }
+
+ return tsdPtr->rcmPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteThreadReflectedChannelMap --
+ *
+ * Deletes the channel table for a thread. This procedure is invoked when
+ * a thread is deleted. The channels have already been marked as dead, in
+ * DeleteReflectedChannelMap().
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Deletes the hash table of channels.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DeleteThreadReflectedChannelMap(
+ ClientData clientData) /* The per-thread data structure. */
+{
+ Tcl_HashSearch hSearch; /* Search variable. */
+ Tcl_HashEntry *hPtr; /* Search variable. */
+ Tcl_ThreadId self = Tcl_GetCurrentThread();
+
+ ReflectedChannelMap* rcmPtr; /* The map */
+ Tcl_Channel chan;
+ ReflectedChannel* rcPtr;
+ ForwardingResult *resultPtr;
+ ForwardingEvent *evPtr;
+ ForwardParam *paramPtr;
+
+ /*
+ * The origin thread for one or more reflected channels is gone.
+ * NOTE: If this function is called due to a thread getting killed the
+ * per-interp DeleteReflectedChannelMap is apparently not called.
+ */
+
+ /*
+ * Go through the list of pending results and cancel all whose events were
+ * destined for this thread. While this is in progress we block any
+ * other access to the list of pending results.
+ */
+
+ Tcl_MutexLock(&rcForwardMutex);
+
+ for (resultPtr = forwardList;
+ resultPtr != NULL;
+ resultPtr = resultPtr->nextPtr) {
+ if (resultPtr->dst != self) {
+ /* Ignore results/events for other threads. */
+ continue;
+ }
+
+ /*
+ * The receiver for the event exited, before processing the event. We
+ * detach the result now, wake the originator up and signal failure.
+ */
+
+ evPtr = resultPtr->evPtr;
+ paramPtr = evPtr->param;
+
+ evPtr->resultPtr = NULL;
+ resultPtr->evPtr = NULL;
+ resultPtr->result = TCL_ERROR;
+
+ ForwardSetStaticError(paramPtr, msg_send_dstlost);
+
+ Tcl_ConditionNotify(&resultPtr->done);
+ }
+
+ /*
+ * Get the map of all channels handled by the current thread. This is a
+ * ReflectedChannelMap, but on a per-thread basis, not per-interp. Go
+ * through the channels, remove all, mark them as dead.
+ */
+
+ rcmPtr = GetThreadReflectedChannelMap();
+ for (hPtr = Tcl_FirstHashEntry(&rcmPtr->map, &hSearch);
+ hPtr != NULL;
+ hPtr = Tcl_FirstHashEntry(&rcmPtr->map, &hSearch)) {
+
+ chan = (Tcl_Channel) Tcl_GetHashValue (hPtr);
+ rcPtr = (ReflectedChannel *) Tcl_GetChannelInstanceData(chan);
+
+ rcPtr->interp = NULL;
+
+ Tcl_DeleteHashEntry(hPtr);
+ }
+
+ Tcl_MutexUnlock(&rcForwardMutex);
+}
+
+static void
+ForwardOpToOwnerThread(
+ ReflectedChannel *rcPtr, /* Channel instance */
+ ForwardedOperation op, /* Forwarded driver operation */
+ const VOID *param) /* Arguments */
+{
+ Tcl_ThreadId dst = rcPtr->thread;
+ ForwardingEvent *evPtr;
+ ForwardingResult *resultPtr;
+ int result;
+
+ /*
+ * We gather the lock early. This allows us to check the liveness of the
+ * channel without interference from DeleteThreadReflectedChannelMap().
+ */
+
+ Tcl_MutexLock(&rcForwardMutex);
+
+ if (rcPtr->interp == NULL) {
+ /*
+ * The channel is marked as dead. Bail out immediately, with an
+ * appropriate error. Do not forget to unlock the mutex on this path.
+ */
+
+ ForwardSetStaticError((ForwardParam *)param, msg_send_dstlost);
+ Tcl_MutexUnlock(&rcForwardMutex);
+ return;
+ }
+
+ /*
+ * Create and initialize the event and data structures.
+ */
+
+ evPtr = (ForwardingEvent *) ckalloc(sizeof(ForwardingEvent));
+ resultPtr = (ForwardingResult *) ckalloc(sizeof(ForwardingResult));
+
+ evPtr->event.proc = ForwardProc;
+ evPtr->resultPtr = resultPtr;
+ evPtr->op = op;
+ evPtr->rcPtr = rcPtr;
+ evPtr->param = (ForwardParam *) param;
+
+ resultPtr->src = Tcl_GetCurrentThread();
+ resultPtr->dst = dst;
+ resultPtr->dsti = rcPtr->interp;
+ resultPtr->done = NULL;
+ resultPtr->result = -1;
+ resultPtr->evPtr = evPtr;
+
+ /*
+ * Now execute the forward.
+ */
+
+ TclSpliceIn(resultPtr, forwardList);
+ /* Do not unlock here. That is done by the ConditionWait */
+
+ /*
+ * Ensure cleanup of the event if the origin thread exits while this event
+ * is pending or in progress. Exitus of the destination thread is handled
+ * by DeleteThreadReflectionChannelMap(), this is set up by
+ * GetThreadReflectedChannelMap(). This is what we use the 'forwardList'
+ * (see above) for.
+ */
+
+ Tcl_CreateThreadExitHandler(SrcExitProc, (ClientData) evPtr);
+
+ /*
+ * Queue the event and poke the other thread's notifier.
+ */
+
+ Tcl_ThreadQueueEvent(dst, (Tcl_Event *)evPtr, TCL_QUEUE_TAIL);
+ Tcl_ThreadAlert(dst);
+
+ /*
+ * (*) Block until the other thread has either processed the transfer or
+ * rejected it.
+ */
+
+ while (resultPtr->result < 0) {
+ /*
+ * NOTE (1): Is it possible that the current thread goes away while
+ * waiting here? IOW Is it possible that "SrcExitProc" is called while
+ * we are here? See complementary note (2) in "SrcExitProc"
+ *
+ * The ConditionWait unlocks the mutex during the wait and relocks it
+ * immediately after.
+ */
+
+ Tcl_ConditionWait(&resultPtr->done, &rcForwardMutex, NULL);
+ }
+
+ /*
+ * Unlink result from the forwarder list.
+ * No need to lock. Either still locked, or locked by the ConditionWait
+ */
+
+ TclSpliceOut(resultPtr, forwardList);
+
+ resultPtr->nextPtr = NULL;
+ resultPtr->prevPtr = NULL;
+
+ Tcl_MutexUnlock(&rcForwardMutex);
+ Tcl_ConditionFinalize(&resultPtr->done);
+
+ /*
+ * Kill the cleanup handler now, and the result structure as well, before
+ * returning the success code.
+ *
+ * Note: The event structure has already been deleted.
+ */
+
+ Tcl_DeleteThreadExitHandler(SrcExitProc, (ClientData) evPtr);
+
+ result = resultPtr->result;
+ ckfree((char*) resultPtr);
+}
+
+static int
+ForwardProc(
+ Tcl_Event *evGPtr,
+ int mask)
+{
+ /*
+ * Notes regarding access to the referenced data.
+ *
+ * In principle the data belongs to the originating thread (see
+ * evPtr->src), however this thread is currently blocked at (*), i.e.
+ * quiescent. Because of this we can treat the data as belonging to us,
+ * without fear of race conditions. I.e. we can read and write as we like.
+ *
+ * The only thing we cannot be sure of is the resultPtr. This can be be
+ * NULLed if the originating thread went away while the event is handled
+ * here now.
+ */
+
+ ForwardingEvent *evPtr = (ForwardingEvent *) evGPtr;
+ ForwardingResult *resultPtr = evPtr->resultPtr;
+ ReflectedChannel *rcPtr = evPtr->rcPtr;
+ Tcl_Interp *interp = rcPtr->interp;
+ ForwardParam *paramPtr = evPtr->param;
+ Tcl_Obj *resObj = NULL; /* Interp result of InvokeTclMethod */
+ ReflectedChannelMap* rcmPtr; /* Map of reflected channels with handlers in this interp */
+ Tcl_HashEntry* hPtr; /* Entry in the above map */
+
+ /*
+ * Ignore the event if no one is waiting for its result anymore.
+ */
+
+ if (!resultPtr) {
+ return 1;
+ }
+
+ paramPtr->base.code = TCL_OK;
+ paramPtr->base.msgStr = NULL;
+ paramPtr->base.mustFree = 0;
+
+ switch (evPtr->op) {
+ /*
+ * The destination thread for the following operations is
+ * rcPtr->thread, which contains rcPtr->interp, the interp we have to
+ * call upon for the driver.
+ */
+
+ case ForwardedClose:
+ /*
+ * No parameters/results.
+ */
+
+ if (InvokeTclMethod(rcPtr, "finalize", NULL, NULL, &resObj)!=TCL_OK) {
+ ForwardSetObjError(paramPtr, resObj);
+ }
+
+ /*
+ * Freeing is done here, in the origin thread, because the argv[]
+ * objects belong to this thread. Deallocating them in a different
+ * thread is not allowed
+ *
+ * We remove the channel from both interpreter and thread maps before
+ * releasing the memory, to prevent future accesses (like by
+ * 'postevent') from finding and dereferencing a dangling pointer.
+ */
+
+ rcmPtr = GetReflectedChannelMap (interp);
+ hPtr = Tcl_FindHashEntry (&rcmPtr->map,
+ Tcl_GetChannelName (rcPtr->chan));
+ Tcl_DeleteHashEntry (hPtr);
+
+ rcmPtr = GetThreadReflectedChannelMap();
+ hPtr = Tcl_FindHashEntry (&rcmPtr->map,
+ Tcl_GetChannelName (rcPtr->chan));
+ Tcl_DeleteHashEntry (hPtr);
+
+ Tcl_EventuallyFree (rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
+ break;
+
+ case ForwardedInput: {
+ Tcl_Obj *toReadObj = Tcl_NewIntObj(paramPtr->input.toRead);
+ Tcl_IncrRefCount(toReadObj);
+
+ Tcl_Preserve(rcPtr);
+ if (InvokeTclMethod(rcPtr, "read", toReadObj, NULL, &resObj)!=TCL_OK){
+ int code = ErrnoReturn (rcPtr, resObj);
+
+ if (code < 0) {
+ paramPtr->base.code = code;
+ } else {
+ ForwardSetObjError(paramPtr, resObj);
+ }
+ paramPtr->input.toRead = -1;
+ } else {
+ /*
+ * Process a regular result.
+ */
+
+ int bytec; /* Number of returned bytes */
+ unsigned char *bytev; /* Array of returned bytes */
+
+ bytev = Tcl_GetByteArrayFromObj(resObj, &bytec);
+
+ if (paramPtr->input.toRead < bytec) {
+ ForwardSetStaticError(paramPtr, msg_read_toomuch);
+ paramPtr->input.toRead = -1;
+ } else {
+ if (bytec > 0) {
+ memcpy(paramPtr->input.buf, bytev, (size_t)bytec);
+ }
+ paramPtr->input.toRead = bytec;
+ }
+ }
+ Tcl_Release(rcPtr);
+ Tcl_DecrRefCount(toReadObj);
+ break;
+ }
+
+ case ForwardedOutput: {
+ Tcl_Obj *bufObj = Tcl_NewByteArrayObj((unsigned char *)
+ paramPtr->output.buf, paramPtr->output.toWrite);
+ Tcl_IncrRefCount(bufObj);
+
+ Tcl_Preserve(rcPtr);
+ if (InvokeTclMethod(rcPtr, "write", bufObj, NULL, &resObj) != TCL_OK) {
+ int code = ErrnoReturn(rcPtr, resObj);
+
+ if (code < 0) {
+ paramPtr->base.code = code;
+ } else {
+ ForwardSetObjError(paramPtr, resObj);
+ }
+ paramPtr->output.toWrite = -1;
+ } else {
+ /*
+ * Process a regular result.
+ */
+
+ int written;
+
+ if (Tcl_GetIntFromObj(interp, resObj, &written) != TCL_OK) {
+ ForwardSetObjError(paramPtr, MarshallError(interp));
+ paramPtr->output.toWrite = -1;
+ } else if (written==0 || paramPtr->output.toWrite<written) {
+ ForwardSetStaticError(paramPtr, msg_write_toomuch);
+ paramPtr->output.toWrite = -1;
+ } else {
+ paramPtr->output.toWrite = written;
+ }
+ }
+ Tcl_Release(rcPtr);
+ Tcl_DecrRefCount(bufObj);
+ break;
+ }
+
+ case ForwardedSeek: {
+ Tcl_Obj *offObj = Tcl_NewWideIntObj(paramPtr->seek.offset);
+ Tcl_Obj *baseObj = Tcl_NewStringObj(
+ (paramPtr->seek.seekMode==SEEK_SET) ? "start" :
+ (paramPtr->seek.seekMode==SEEK_CUR) ? "current" : "end", -1);
+
+ Tcl_IncrRefCount(offObj);
+ Tcl_IncrRefCount(baseObj);
+
+ Tcl_Preserve(rcPtr);
+ if (InvokeTclMethod(rcPtr, "seek", offObj, baseObj, &resObj)!=TCL_OK){
+ ForwardSetObjError(paramPtr, resObj);
+ paramPtr->seek.offset = -1;
+ } else {
+ /*
+ * Process a regular result. If the type is wrong this may change
+ * into an error.
+ */
+
+ Tcl_WideInt newLoc;
+
+ if (Tcl_GetWideIntFromObj(interp, resObj, &newLoc) == TCL_OK) {
+ if (newLoc < Tcl_LongAsWide(0)) {
+ ForwardSetStaticError(paramPtr, msg_seek_beforestart);
+ paramPtr->seek.offset = -1;
+ } else {
+ paramPtr->seek.offset = newLoc;
+ }
+ } else {
+ ForwardSetObjError(paramPtr, MarshallError(interp));
+ paramPtr->seek.offset = -1;
+ }
+ }
+ Tcl_Release(rcPtr);
+ Tcl_DecrRefCount(offObj);
+ Tcl_DecrRefCount(baseObj);
+ break;
+ }
+
+ case ForwardedWatch: {
+ Tcl_Obj *maskObj = DecodeEventMask(paramPtr->watch.mask);
+ /* assert maskObj.refCount == 1 */
+
+ Tcl_Preserve(rcPtr);
+ (void) InvokeTclMethod(rcPtr, "watch", maskObj, NULL, NULL);
+ Tcl_DecrRefCount(maskObj);
+ Tcl_Release(rcPtr);
+ break;
+ }
+
+ case ForwardedBlock: {
+ Tcl_Obj *blockObj = Tcl_NewBooleanObj(!paramPtr->block.nonblocking);
+ Tcl_IncrRefCount(blockObj);
+
+ Tcl_Preserve(rcPtr);
+ if (InvokeTclMethod(rcPtr, "blocking", blockObj, NULL,
+ &resObj) != TCL_OK) {
+ ForwardSetObjError(paramPtr, resObj);
+ }
+ Tcl_Release(rcPtr);
+ Tcl_DecrRefCount(blockObj);
+ break;
+ }
+
+ case ForwardedSetOpt: {
+ Tcl_Obj *optionObj = Tcl_NewStringObj(paramPtr->setOpt.name, -1);
+ Tcl_Obj *valueObj = Tcl_NewStringObj(paramPtr->setOpt.value, -1);
+
+ Tcl_IncrRefCount(optionObj);
+ Tcl_IncrRefCount(valueObj);
+ Tcl_Preserve(rcPtr);
+ if (InvokeTclMethod(rcPtr, "configure", optionObj, valueObj,
+ &resObj) != TCL_OK) {
+ ForwardSetObjError(paramPtr, resObj);
+ }
+ Tcl_Release(rcPtr);
+ Tcl_DecrRefCount(optionObj);
+ Tcl_DecrRefCount(valueObj);
+ break;
+ }
+
+ case ForwardedGetOpt: {
+ /*
+ * Retrieve the value of one option.
+ */
+
+ Tcl_Obj *optionObj = Tcl_NewStringObj(paramPtr->getOpt.name, -1);
+ Tcl_IncrRefCount(optionObj);
+
+ Tcl_Preserve(rcPtr);
+ if (InvokeTclMethod(rcPtr, "cget", optionObj, NULL, &resObj)!=TCL_OK){
+ ForwardSetObjError(paramPtr, resObj);
+ } else {
+ Tcl_DStringAppend(paramPtr->getOpt.value,
+ TclGetString(resObj), -1);
+ }
+ Tcl_Release(rcPtr);
+ Tcl_DecrRefCount(optionObj);
+ break;
+ }
+
+ case ForwardedGetOptAll:
+ /*
+ * Retrieve all options.
+ */
+
+ Tcl_Preserve(rcPtr);
+ if (InvokeTclMethod(rcPtr, "cgetall", NULL, NULL, &resObj) != TCL_OK){
+ ForwardSetObjError(paramPtr, resObj);
+ } else {
+ /*
+ * Extract list, validate that it is a list, and #elements. See
+ * NOTE (4) as well.
+ */
+
+ int listc;
+ Tcl_Obj **listv;
+
+ if (Tcl_ListObjGetElements(interp, resObj, &listc,
+ &listv) != TCL_OK) {
+ ForwardSetObjError(paramPtr, MarshallError(interp));
+ } else if ((listc % 2) == 1) {
+ /*
+ * Odd number of elements is wrong. [x].
+ */
+
+ char *buf = ckalloc(200);
+ sprintf(buf,
+ "{Expected list with even number of elements, got %d %s instead}",
+ listc, (listc == 1 ? "element" : "elements"));
+
+ ForwardSetDynamicError(paramPtr, buf);
+ } else {
+ int len;
+ const char *str = Tcl_GetStringFromObj(resObj, &len);
+
+ if (len) {
+ Tcl_DStringAppend(paramPtr->getOpt.value, " ", 1);
+ Tcl_DStringAppend(paramPtr->getOpt.value, str, len);
+ }
+ }
+ }
+ Tcl_Release(rcPtr);
+ break;
+
+ default:
+ /*
+ * Bad operation code.
+ */
+
+ Tcl_Panic("Bad operation code in ForwardProc");
+ break;
+ }
+
+ /*
+ * Remove the reference we held on the result of the invoke, if we had
+ * such.
+ */
+
+ if (resObj != NULL) {
+ Tcl_DecrRefCount(resObj);
+ }
+
+ if (resultPtr) {
+ /*
+ * Report the forwarding result synchronously to the waiting caller.
+ * This unblocks (*) as well. This is wrapped into a conditional
+ * because the caller may have exited in the mean time.
+ */
+
+ Tcl_MutexLock(&rcForwardMutex);
+ resultPtr->result = TCL_OK;
+ Tcl_ConditionNotify(&resultPtr->done);
+ Tcl_MutexUnlock(&rcForwardMutex);
+ }
+
+ return 1;
+}
+
+static void
+SrcExitProc(
+ ClientData clientData)
+{
+ ForwardingEvent *evPtr = (ForwardingEvent *) clientData;
+ ForwardingResult *resultPtr;
+ ForwardParam *paramPtr;
+
+ /*
+ * NOTE (2): Can this handler be called with the originator blocked?
+ */
+
+ /*
+ * The originator for the event exited. It is not sure if this can happen,
+ * as the originator should be blocked at (*) while the event is in
+ * transit/pending.
+ *
+ * We make sure that the event cannot refer to the result anymore, remove
+ * it from the list of pending results and free the structure. Locking the
+ * access ensures that we cannot get in conflict with "ForwardProc",
+ * should it already execute the event.
+ */
+
+ Tcl_MutexLock(&rcForwardMutex);
+
+ resultPtr = evPtr->resultPtr;
+ paramPtr = evPtr->param;
+
+ evPtr->resultPtr = NULL;
+ resultPtr->evPtr = NULL;
+ resultPtr->result = TCL_ERROR;
+
+ ForwardSetStaticError(paramPtr, msg_send_originlost);
+
+ /*
+ * See below: TclSpliceOut(resultPtr, forwardList);
+ */
+
+ Tcl_MutexUnlock(&rcForwardMutex);
+
+ /*
+ * This unlocks (*). The structure will be spliced out and freed by
+ * "ForwardProc". Maybe.
+ */
+
+ Tcl_ConditionNotify(&resultPtr->done);
+}
+
+static void
+ForwardSetObjError(
+ ForwardParam *paramPtr,
+ Tcl_Obj *obj)
+{
+ int len;
+ const char *msgStr = Tcl_GetStringFromObj(obj, &len);
+
+ len++;
+ ForwardSetDynamicError(paramPtr, ckalloc((unsigned) len));
+ memcpy(paramPtr->base.msgStr, msgStr, (unsigned) len);
+}
+#endif
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/generic/tclIOSock.c b/generic/tclIOSock.c
index f311912..ec4a9d9 100644
--- a/generic/tclIOSock.c
+++ b/generic/tclIOSock.c
@@ -1,30 +1,28 @@
-/*
+/*
* tclIOSock.c --
*
* Common routines used by all socket based channel types.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
/*
*---------------------------------------------------------------------------
*
* TclSockGetPort --
*
- * Maps from a string, which could be a service name, to a port.
- * Used by socket creation code to get port numbers and resolve
- * registered service names to port numbers.
+ * Maps from a string, which could be a service name, to a port. Used by
+ * socket creation code to get port numbers and resolve registered
+ * service names to port numbers.
*
* Results:
- * A standard Tcl result. On success, the port number is returned
- * in portPtr. On failure, an error message is left in the interp's
- * result.
+ * A standard Tcl result. On success, the port number is returned in
+ * portPtr. On failure, an error message is left in the interp's result.
*
* Side effects:
* None.
@@ -33,21 +31,21 @@
*/
int
-TclSockGetPort(interp, string, proto, portPtr)
- Tcl_Interp *interp;
- char *string; /* Integer or service name */
- char *proto; /* "tcp" or "udp", typically */
- int *portPtr; /* Return port number */
+TclSockGetPort(
+ Tcl_Interp *interp,
+ const char *string, /* Integer or service name */
+ const char *proto, /* "tcp" or "udp", typically */
+ int *portPtr) /* Return port number */
{
struct servent *sp; /* Protocol info for named services */
Tcl_DString ds;
- CONST char *native;
+ const char *native;
if (Tcl_GetInt(NULL, string, portPtr) != TCL_OK) {
/*
* Don't bother translating 'proto' to native.
*/
-
+
native = Tcl_UtfToExternalDString(NULL, string, -1, &ds);
sp = getservbyname(native, proto); /* INTL: Native. */
Tcl_DStringFree(&ds);
@@ -60,8 +58,8 @@ TclSockGetPort(interp, string, proto, portPtr)
return TCL_ERROR;
}
if (*portPtr > 0xFFFF) {
- Tcl_AppendResult(interp, "couldn't open socket: port number too high",
- (char *) NULL);
+ Tcl_AppendResult(interp, "couldn't open socket: port number too high",
+ NULL);
return TCL_ERROR;
}
return TCL_OK;
@@ -84,9 +82,9 @@ TclSockGetPort(interp, string, proto, portPtr)
*/
int
-TclSockMinimumBuffers(sock, size)
- int sock; /* Socket file descriptor */
- int size; /* Minimum buffer size */
+TclSockMinimumBuffers(
+ int sock, /* Socket file descriptor */
+ int size) /* Minimum buffer size */
{
int current;
socklen_t len;
@@ -105,3 +103,11 @@ TclSockMinimumBuffers(sock, size)
}
return TCL_OK;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c
index 32658a8..fb8b74f 100644
--- a/generic/tclIOUtil.c
+++ b/generic/tclIOUtil.c
@@ -1,180 +1,106 @@
-/*
+/*
* tclIOUtil.c --
*
- * This file contains the implementation of Tcl's generic
- * filesystem code, which supports a pluggable filesystem
- * architecture allowing both platform specific filesystems and
- * 'virtual filesystems'. All filesystem access should go through
- * the functions defined in this file. Most of this code was
- * contributed by Vince Darley.
+ * This file contains the implementation of Tcl's generic filesystem
+ * code, which supports a pluggable filesystem architecture allowing both
+ * platform specific filesystems and 'virtual filesystems'. All
+ * filesystem access should go through the functions defined in this
+ * file. Most of this code was contributed by Vince Darley.
*
- * Parts of this file are based on code contributed by Karl
- * Lehenbauer, Mark Diekhans and Peter da Silva.
+ * Parts of this file are based on code contributed by Karl Lehenbauer,
+ * Mark Diekhans and Peter da Silva.
*
* Copyright (c) 1991-1994 The Regents of the University of California.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 2001-2004 Vincent Darley.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
-#ifdef MAC_TCL
-#include "tclMacInt.h"
-#endif
#ifdef __WIN32__
-/* for tclWinProcs->useWide */
-#include "tclWinInt.h"
+# include "tclWinInt.h"
#endif
+#include "tclFileSystem.h"
-/*
- * struct FilesystemRecord --
- *
- * A filesystem record is used to keep track of each
- * filesystem currently registered with the core,
- * in a linked list. Pointers to these structures
- * are also kept by each "path" Tcl_Obj, and we must
- * retain a refCount on the number of such references.
- */
-typedef struct FilesystemRecord {
- ClientData clientData; /* Client specific data for the new
- * filesystem (can be NULL) */
- Tcl_Filesystem *fsPtr; /* Pointer to filesystem dispatch
- * table. */
- int fileRefCount; /* How many Tcl_Obj's use this
- * filesystem. */
- struct FilesystemRecord *nextPtr;
- /* The next filesystem registered
- * to Tcl, or NULL if no more. */
- struct FilesystemRecord *prevPtr;
- /* The previous filesystem registered
- * to Tcl, or NULL if no more. */
-} FilesystemRecord;
-
-/*
- * The internal TclFS API provides routines for handling and
- * manipulating paths efficiently, taking direct advantage of
- * the "path" Tcl_Obj type.
- *
- * These functions are not exported at all at present.
- */
-
-int TclFSCwdPointerEquals _ANSI_ARGS_((Tcl_Obj* objPtr));
-int TclFSMakePathFromNormalized _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr, ClientData clientData));
-int TclFSNormalizeToUniquePath _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *pathPtr, int startAt, ClientData *clientDataPtr));
-Tcl_Obj* TclFSMakePathRelative _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr, Tcl_Obj *cwdPtr));
-Tcl_Obj* TclFSInternalToNormalized _ANSI_ARGS_((
- Tcl_Filesystem *fromFilesystem, ClientData clientData,
- FilesystemRecord **fsRecPtrPtr));
-int TclFSEnsureEpochOk _ANSI_ARGS_((Tcl_Obj* pathObjPtr,
- Tcl_Filesystem **fsPtrPtr));
-void TclFSSetPathDetails _ANSI_ARGS_((Tcl_Obj *pathObjPtr,
- FilesystemRecord *fsRecPtr, ClientData clientData));
-
-/*
- * Private variables for use in this file
- */
-extern Tcl_Filesystem tclNativeFilesystem;
-extern int theFilesystemEpoch;
-
-/*
- * Private functions for use in this file
- */
-static Tcl_PathType FSGetPathType _ANSI_ARGS_((Tcl_Obj *pathObjPtr,
- Tcl_Filesystem **filesystemPtrPtr,
- int *driveNameLengthPtr));
-static Tcl_PathType GetPathType _ANSI_ARGS_((Tcl_Obj *pathObjPtr,
- Tcl_Filesystem **filesystemPtrPtr,
- int *driveNameLengthPtr, Tcl_Obj **driveNameRef));
-static Tcl_FSPathInFilesystemProc NativePathInFilesystem;
-static Tcl_Obj* TclFSNormalizeAbsolutePath
- _ANSI_ARGS_((Tcl_Interp* interp, Tcl_Obj *pathPtr,
- ClientData *clientDataPtr));
/*
- * Prototypes for procedures defined later in this file.
+ * Prototypes for functions defined later in this file.
*/
-static FilesystemRecord* FsGetFirstFilesystem(void);
-static void FsThrExitProc(ClientData cd);
-static Tcl_Obj* FsListMounts _ANSI_ARGS_((Tcl_Obj *pathPtr,
- CONST char *pattern));
-static Tcl_Obj* FsAddMountsToGlobResult _ANSI_ARGS_((Tcl_Obj *result,
- Tcl_Obj *pathPtr, CONST char *pattern, Tcl_GlobTypeData *types));
+static FilesystemRecord*FsGetFirstFilesystem(void);
+static void FsThrExitProc(ClientData cd);
+static Tcl_Obj * FsListMounts(Tcl_Obj *pathPtr, const char *pattern);
+static void FsAddMountsToGlobResult(Tcl_Obj *resultPtr,
+ Tcl_Obj *pathPtr, const char *pattern,
+ Tcl_GlobTypeData *types);
+static void FsUpdateCwd(Tcl_Obj *cwdObj, ClientData clientData);
#ifdef TCL_THREADS
-static void FsRecacheFilesystemList(void);
+static void FsRecacheFilesystemList(void);
#endif
-/*
- * These form part of the native filesystem support. They are needed
- * here because we have a few native filesystem functions (which are
- * the same for mac/win/unix) in this file. There is no need to place
- * them in tclInt.h, because they are not (and should not be) used
- * anywhere else.
+/*
+ * These form part of the native filesystem support. They are needed here
+ * because we have a few native filesystem functions (which are the same for
+ * win/unix) in this file. There is no need to place them in tclInt.h, because
+ * they are not (and should not be) used anywhere else.
*/
-extern CONST char * tclpFileAttrStrings[];
-extern CONST TclFileAttrProcs tclpFileAttrProcs[];
-/*
- * The following functions are obsolete string based APIs, and should
- * be removed in a future release (Tcl 9 would be a good time).
+MODULE_SCOPE const char * tclpFileAttrStrings[];
+MODULE_SCOPE const TclFileAttrProcs tclpFileAttrProcs[];
+
+/*
+ * The following functions are obsolete string based APIs, and should be
+ * removed in a future release (Tcl 9 would be a good time).
*/
+
/* Obsolete */
int
-Tcl_Stat(path, oldStyleBuf)
- CONST char *path; /* Path of file to stat (in current CP). */
- struct stat *oldStyleBuf; /* Filled with results of stat call. */
+Tcl_Stat(
+ const char *path, /* Path of file to stat (in current CP). */
+ struct stat *oldStyleBuf) /* Filled with results of stat call. */
{
int ret;
Tcl_StatBuf buf;
- Tcl_Obj *pathPtr = Tcl_NewStringObj(path,-1);
+ Tcl_Obj *pathPtr = Tcl_NewStringObj(path, -1);
Tcl_IncrRefCount(pathPtr);
ret = Tcl_FSStat(pathPtr, &buf);
Tcl_DecrRefCount(pathPtr);
if (ret != -1) {
#ifndef TCL_WIDE_INT_IS_LONG
-# define OUT_OF_RANGE(x) \
+ Tcl_WideInt tmp1, tmp2, tmp3 = 0;
+# define OUT_OF_RANGE(x) \
(((Tcl_WideInt)(x)) < Tcl_LongAsWide(LONG_MIN) || \
((Tcl_WideInt)(x)) > Tcl_LongAsWide(LONG_MAX))
-#if defined(__GNUC__) && __GNUC__ >= 2
-/*
- * Workaround gcc warning of "comparison is always false due to limited range of
- * data type" in this macro by checking max type size, and when necessary ANDing
- * with the complement of ULONG_MAX instead of the comparison:
- */
-# define OUT_OF_URANGE(x) \
- ((((Tcl_WideUInt)(~ (__typeof__(x)) 0)) > (Tcl_WideUInt)ULONG_MAX) && \
- (((Tcl_WideUInt)(x)) & ~(Tcl_WideUInt)ULONG_MAX))
-#else
-# define OUT_OF_URANGE(x) \
- (((Tcl_WideUInt)(x)) > (Tcl_WideUInt)ULONG_MAX)
-#endif
+# define OUT_OF_URANGE(x) \
+ (((Tcl_WideUInt)(x)) > ((Tcl_WideUInt)ULONG_MAX))
/*
* Perform the result-buffer overflow check manually.
*
* Note that ino_t/ino64_t is unsigned...
+ *
+ * Workaround gcc warning of "comparison is always false due to
+ * limited range of data type" by assigning to tmp var of type
+ * Tcl_WideInt.
*/
- if (OUT_OF_URANGE(buf.st_ino) || OUT_OF_RANGE(buf.st_size)
-#ifdef HAVE_ST_BLOCKS
- || OUT_OF_RANGE(buf.st_blocks)
+ tmp1 = (Tcl_WideInt) buf.st_ino;
+ tmp2 = (Tcl_WideInt) buf.st_size;
+#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
+ tmp3 = (Tcl_WideInt) buf.st_blocks;
#endif
- ) {
-#ifdef EFBIG
+
+ if (OUT_OF_URANGE(tmp1) || OUT_OF_RANGE(tmp2) || OUT_OF_RANGE(tmp3)) {
+#if defined(EFBIG)
errno = EFBIG;
-#else
-# ifdef EOVERFLOW
+#elif defined(EOVERFLOW)
errno = EOVERFLOW;
-# else
-# error "What status should be returned for file size out of range?"
-# endif
+#else
+#error "What status should be returned for file size out of range?"
#endif
return -1;
}
@@ -184,27 +110,33 @@ Tcl_Stat(path, oldStyleBuf)
#endif /* !TCL_WIDE_INT_IS_LONG */
/*
- * Copy across all supported fields, with possible type
- * coercions on those fields that change between the normal
- * and lf64 versions of the stat structure (on Solaris at
- * least.) This is slow when the structure sizes coincide,
- * but that's what you get for using an obsolete interface.
+ * Copy across all supported fields, with possible type coercions on
+ * those fields that change between the normal and lf64 versions of
+ * the stat structure (on Solaris at least). This is slow when the
+ * structure sizes coincide, but that's what you get for using an
+ * obsolete interface.
*/
- oldStyleBuf->st_mode = buf.st_mode;
- oldStyleBuf->st_ino = (ino_t) buf.st_ino;
- oldStyleBuf->st_dev = buf.st_dev;
- oldStyleBuf->st_rdev = buf.st_rdev;
- oldStyleBuf->st_nlink = buf.st_nlink;
- oldStyleBuf->st_uid = buf.st_uid;
- oldStyleBuf->st_gid = buf.st_gid;
- oldStyleBuf->st_size = (off_t) buf.st_size;
- oldStyleBuf->st_atime = buf.st_atime;
- oldStyleBuf->st_mtime = buf.st_mtime;
- oldStyleBuf->st_ctime = buf.st_ctime;
-#ifdef HAVE_ST_BLOCKS
- oldStyleBuf->st_blksize = buf.st_blksize;
- oldStyleBuf->st_blocks = (blkcnt_t) buf.st_blocks;
+ oldStyleBuf->st_mode = buf.st_mode;
+ oldStyleBuf->st_ino = (ino_t) buf.st_ino;
+ oldStyleBuf->st_dev = buf.st_dev;
+ oldStyleBuf->st_rdev = buf.st_rdev;
+ oldStyleBuf->st_nlink = buf.st_nlink;
+ oldStyleBuf->st_uid = buf.st_uid;
+ oldStyleBuf->st_gid = buf.st_gid;
+ oldStyleBuf->st_size = (off_t) buf.st_size;
+ oldStyleBuf->st_atime = buf.st_atime;
+ oldStyleBuf->st_mtime = buf.st_mtime;
+ oldStyleBuf->st_ctime = buf.st_ctime;
+#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
+ oldStyleBuf->st_blksize = buf.st_blksize;
+#endif
+#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
+#ifdef HAVE_BLKCNT_T
+ oldStyleBuf->st_blocks = (blkcnt_t) buf.st_blocks;
+#else
+ oldStyleBuf->st_blocks = (unsigned long) buf.st_blocks;
+#endif
#endif
}
return ret;
@@ -212,43 +144,45 @@ Tcl_Stat(path, oldStyleBuf)
/* Obsolete */
int
-Tcl_Access(path, mode)
- CONST char *path; /* Path of file to access (in current CP). */
- int mode; /* Permission setting. */
+Tcl_Access(
+ const char *path, /* Path of file to access (in current CP). */
+ int mode) /* Permission setting. */
{
int ret;
Tcl_Obj *pathPtr = Tcl_NewStringObj(path,-1);
+
Tcl_IncrRefCount(pathPtr);
ret = Tcl_FSAccess(pathPtr,mode);
Tcl_DecrRefCount(pathPtr);
+
return ret;
}
/* Obsolete */
Tcl_Channel
-Tcl_OpenFileChannel(interp, path, modeString, permissions)
- Tcl_Interp *interp; /* Interpreter for error reporting;
- * can be NULL. */
- CONST char *path; /* Name of file to open. */
- CONST char *modeString; /* A list of POSIX open modes or
- * a string such as "rw". */
- int permissions; /* If the open involves creating a
- * file, with what modes to create
- * it? */
+Tcl_OpenFileChannel(
+ Tcl_Interp *interp, /* Interpreter for error reporting; can be
+ * NULL. */
+ const char *path, /* Name of file to open. */
+ const char *modeString, /* A list of POSIX open modes or a string such
+ * as "rw". */
+ int permissions) /* If the open involves creating a file, with
+ * what modes to create it? */
{
Tcl_Channel ret;
Tcl_Obj *pathPtr = Tcl_NewStringObj(path,-1);
+
Tcl_IncrRefCount(pathPtr);
ret = Tcl_FSOpenFileChannel(interp, pathPtr, modeString, permissions);
Tcl_DecrRefCount(pathPtr);
- return ret;
+ return ret;
}
/* Obsolete */
int
-Tcl_Chdir(dirName)
- CONST char *dirName;
+Tcl_Chdir(
+ const char *dirName)
{
int ret;
Tcl_Obj *pathPtr = Tcl_NewStringObj(dirName,-1);
@@ -260,9 +194,9 @@ Tcl_Chdir(dirName)
/* Obsolete */
char *
-Tcl_GetCwd(interp, cwdPtr)
- Tcl_Interp *interp;
- Tcl_DString *cwdPtr;
+Tcl_GetCwd(
+ Tcl_Interp *interp,
+ Tcl_DString *cwdPtr)
{
Tcl_Obj *cwd;
cwd = Tcl_FSGetCwd(interp);
@@ -278,9 +212,9 @@ Tcl_GetCwd(interp, cwdPtr)
/* Obsolete */
int
-Tcl_EvalFile(interp, fileName)
- Tcl_Interp *interp; /* Interpreter in which to process file. */
- CONST char *fileName; /* Name of file to process. Tilde-substitution
+Tcl_EvalFile(
+ Tcl_Interp *interp, /* Interpreter in which to process file. */
+ const char *fileName) /* Name of file to process. Tilde-substitution
* will be performed on this name. */
{
int ret;
@@ -291,59 +225,58 @@ Tcl_EvalFile(interp, fileName)
return ret;
}
-
-/*
- * The 3 hooks for Stat, Access and OpenFileChannel are obsolete. The
- * complete, general hooked filesystem APIs should be used instead.
- * This define decides whether to include the obsolete hooks and
- * related code. If these are removed, we'll also want to remove them
- * from stubs/tclInt. The only known users of these APIs are prowrap
- * and mktclapp. New code/extensions should not use them, since they
- * do not provide as full support as the full filesystem API.
- *
- * As soon as prowrap and mktclapp are updated to use the full
- * filesystem support, I suggest all these hooks are removed.
+/*
+ * The 3 hooks for Stat, Access and OpenFileChannel are obsolete. The
+ * complete, general hooked filesystem APIs should be used instead. This
+ * define decides whether to include the obsolete hooks and related code. If
+ * these are removed, we'll also want to remove them from stubs/tclInt. The
+ * only known users of these APIs are prowrap and mktclapp. New
+ * code/extensions should not use them, since they do not provide as full
+ * support as the full filesystem API.
+ *
+ * As soon as prowrap and mktclapp are updated to use the full filesystem
+ * support, I suggest all these hooks are removed.
*/
-#define USE_OBSOLETE_FS_HOOKS
+#undef USE_OBSOLETE_FS_HOOKS
#ifdef USE_OBSOLETE_FS_HOOKS
+
/*
- * The following typedef declarations allow for hooking into the chain
- * of functions maintained for 'Tcl_Stat(...)', 'Tcl_Access(...)' &
- * 'Tcl_OpenFileChannel(...)'. Basically for each hookable function
- * a linked list is defined.
+ * The following typedef declarations allow for hooking into the chain of
+ * functions maintained for 'Tcl_Stat(...)', 'Tcl_Access(...)' &
+ * 'Tcl_OpenFileChannel(...)'. Basically for each hookable function a linked
+ * list is defined.
*/
typedef struct StatProc {
- TclStatProc_ *proc; /* Function to process a 'stat()' call */
- struct StatProc *nextPtr; /* The next 'stat()' function to call */
+ TclStatProc_ *proc; /* Function to process a 'stat()' call */
+ struct StatProc *nextPtr; /* The next 'stat()' function to call */
} StatProc;
typedef struct AccessProc {
- TclAccessProc_ *proc; /* Function to process a 'access()' call */
- struct AccessProc *nextPtr; /* The next 'access()' function to call */
+ TclAccessProc_ *proc; /* Function to process a 'access()' call */
+ struct AccessProc *nextPtr; /* The next 'access()' function to call */
} AccessProc;
typedef struct OpenFileChannelProc {
- TclOpenFileChannelProc_ *proc; /* Function to process a
- * 'Tcl_OpenFileChannel()' call */
+ TclOpenFileChannelProc_ *proc;
+ /* Function to process a
+ * 'Tcl_OpenFileChannel()' call */
struct OpenFileChannelProc *nextPtr;
- /* The next 'Tcl_OpenFileChannel()'
- * function to call */
+ /* The next 'Tcl_OpenFileChannel()' function
+ * to call */
} OpenFileChannelProc;
/*
- * For each type of (obsolete) hookable function, a static node is
- * declared to hold the function pointer for the "built-in" routine
- * (e.g. 'TclpStat(...)') and the respective list is initialized as a
- * pointer to that node.
- *
- * The "delete" functions (e.g. 'TclStatDeleteProc(...)') ensure that
- * these statically declared list entry cannot be inadvertently removed.
+ * For each type of (obsolete) hookable function, a static node is declared to
+ * hold the function pointer for the "built-in" routine (e.g. 'TclpStat(...)')
+ * and the respective list is initialized as a pointer to that node.
+ *
+ * The "delete" functions (e.g. 'TclStatDeleteProc(...)') ensure that these
+ * statically declared list entry cannot be inadvertently removed.
*
- * This method avoids the need to call any sort of "initialization"
- * function.
+ * This method avoids the need to call any sort of "initialization" function.
*
* All three lists are protected by a global obsoleteFsHookMutex.
*/
@@ -356,71 +289,69 @@ TCL_DECLARE_MUTEX(obsoleteFsHookMutex)
#endif /* USE_OBSOLETE_FS_HOOKS */
-/*
- * Declare the native filesystem support. These functions should
- * be considered private to Tcl, and should really not be called
- * directly by any code other than this file (i.e. neither by
- * Tcl's core nor by extensions). Similarly, the old string-based
- * Tclp... native filesystem functions should not be called.
- *
- * The correct API to use now is the Tcl_FS... set of functions,
- * which ensure correct and complete virtual filesystem support.
- *
- * We cannot make all of these static, since some of them
- * are implemented in the platform-specific directories.
+/*
+ * Declare the native filesystem support. These functions should be considered
+ * private to Tcl, and should really not be called directly by any code other
+ * than this file (i.e. neither by Tcl's core nor by extensions). Similarly,
+ * the old string-based Tclp... native filesystem functions should not be
+ * called.
+ *
+ * The correct API to use now is the Tcl_FS... set of functions, which ensure
+ * correct and complete virtual filesystem support.
+ *
+ * We cannot make all of these static, since some of them are implemented in
+ * the platform-specific directories.
*/
+
static Tcl_FSFilesystemSeparatorProc NativeFilesystemSeparator;
static Tcl_FSFreeInternalRepProc NativeFreeInternalRep;
-static Tcl_FSCreateInternalRepProc NativeCreateNativeRep;
static Tcl_FSFileAttrStringsProc NativeFileAttrStrings;
-static Tcl_FSFileAttrsGetProc NativeFileAttrsGet;
-static Tcl_FSFileAttrsSetProc NativeFileAttrsSet;
-
-/*
- * The only reason these functions are not static is that they
- * are either called by code in the native (win/unix/mac) directories
- * or they are actually implemented in those directories. They
- * should simply not be called by code outside Tcl's native
- * filesystem core. i.e. they should be considered 'static' to
- * Tcl's filesystem code (if we ever built the native filesystem
- * support into a separate code library, this could actually be
- * enforced).
+static Tcl_FSFileAttrsGetProc NativeFileAttrsGet;
+static Tcl_FSFileAttrsSetProc NativeFileAttrsSet;
+
+/*
+ * The only reason these functions are not static is that they are either
+ * called by code in the native (win/unix) directories or they are actually
+ * implemented in those directories. They should simply not be called by code
+ * outside Tcl's native filesystem core i.e. they should be considered
+ * 'static' to Tcl's filesystem code (if we ever built the native filesystem
+ * support into a separate code library, this could actually be enforced).
*/
-Tcl_FSFilesystemPathTypeProc TclpFilesystemPathType;
-Tcl_FSInternalToNormalizedProc TclpNativeToNormalized;
-Tcl_FSStatProc TclpObjStat;
-Tcl_FSAccessProc TclpObjAccess;
-Tcl_FSMatchInDirectoryProc TclpMatchInDirectory;
-Tcl_FSGetCwdProc TclpObjGetCwd;
-Tcl_FSChdirProc TclpObjChdir;
-Tcl_FSLstatProc TclpObjLstat;
-Tcl_FSCopyFileProc TclpObjCopyFile;
-Tcl_FSDeleteFileProc TclpObjDeleteFile;
-Tcl_FSRenameFileProc TclpObjRenameFile;
-Tcl_FSCreateDirectoryProc TclpObjCreateDirectory;
-Tcl_FSCopyDirectoryProc TclpObjCopyDirectory;
-Tcl_FSRemoveDirectoryProc TclpObjRemoveDirectory;
-Tcl_FSUnloadFileProc TclpUnloadFile;
-Tcl_FSLinkProc TclpObjLink;
-Tcl_FSListVolumesProc TclpObjListVolumes;
-
-/*
- * Define the native filesystem dispatch table. If necessary, it
- * is ok to make this non-static, but it should only be accessed
- * by the functions actually listed within it (or perhaps other
- * helper functions of them). Anything which is not part of this
- * 'native filesystem implementation' should not be delving inside
- * here!
+
+Tcl_FSFilesystemPathTypeProc TclpFilesystemPathType;
+Tcl_FSInternalToNormalizedProc TclpNativeToNormalized;
+Tcl_FSStatProc TclpObjStat;
+Tcl_FSAccessProc TclpObjAccess;
+Tcl_FSMatchInDirectoryProc TclpMatchInDirectory;
+Tcl_FSChdirProc TclpObjChdir;
+Tcl_FSLstatProc TclpObjLstat;
+Tcl_FSCopyFileProc TclpObjCopyFile;
+Tcl_FSDeleteFileProc TclpObjDeleteFile;
+Tcl_FSRenameFileProc TclpObjRenameFile;
+Tcl_FSCreateDirectoryProc TclpObjCreateDirectory;
+Tcl_FSCopyDirectoryProc TclpObjCopyDirectory;
+Tcl_FSRemoveDirectoryProc TclpObjRemoveDirectory;
+Tcl_FSUnloadFileProc TclpUnloadFile;
+Tcl_FSLinkProc TclpObjLink;
+Tcl_FSListVolumesProc TclpObjListVolumes;
+
+/*
+ * Define the native filesystem dispatch table. If necessary, it is ok to make
+ * this non-static, but it should only be accessed by the functions actually
+ * listed within it (or perhaps other helper functions of them). Anything
+ * which is not part of this 'native filesystem implementation' should not be
+ * delving inside here!
*/
+
Tcl_Filesystem tclNativeFilesystem = {
"native",
sizeof(Tcl_Filesystem),
- TCL_FILESYSTEM_VERSION_1,
- &NativePathInFilesystem,
+ TCL_FILESYSTEM_VERSION_2,
+ &TclNativePathInFilesystem,
&TclNativeDupInternalRep,
&NativeFreeInternalRep,
&TclpNativeToNormalized,
- &NativeCreateNativeRep,
+ &TclNativeCreateNativeRep,
&TclpObjNormalizePath,
&TclpFilesystemPathType,
&NativeFilesystemSeparator,
@@ -439,26 +370,28 @@ Tcl_Filesystem tclNativeFilesystem = {
&NativeFileAttrsGet,
&NativeFileAttrsSet,
&TclpObjCreateDirectory,
- &TclpObjRemoveDirectory,
+ &TclpObjRemoveDirectory,
&TclpObjDeleteFile,
&TclpObjCopyFile,
&TclpObjRenameFile,
- &TclpObjCopyDirectory,
+ &TclpObjCopyDirectory,
&TclpObjLstat,
&TclpDlopen,
- &TclpObjGetCwd,
+ /* Needs a cast since we're using version_2 */
+ (Tcl_FSGetCwdProc *) &TclpGetNativeCwd,
&TclpObjChdir
};
-/*
- * Define the tail of the linked list. Note that for unconventional
- * uses of Tcl without a native filesystem, we may in the future wish
- * to modify the current approach of hard-coding the native filesystem
- * in the lookup list 'filesystemList' below.
- *
- * We initialize the record so that it thinks one file uses it. This
- * means it will never be freed.
+/*
+ * Define the tail of the linked list. Note that for unconventional uses of
+ * Tcl without a native filesystem, we may in the future wish to modify the
+ * current approach of hard-coding the native filesystem in the lookup list
+ * 'filesystemList' below.
+ *
+ * We initialize the record so that it thinks one file uses it. This means it
+ * will never be freed.
*/
+
static FilesystemRecord nativeFilesystemRecord = {
NULL,
&tclNativeFilesystem,
@@ -466,86 +399,79 @@ static FilesystemRecord nativeFilesystemRecord = {
NULL
};
-/*
- * This is incremented each time we modify the linked list of
- * filesystems. Any time it changes, all cached filesystem
- * representations are suspect and must be freed.
- * For multithreading builds, change of the filesystem epoch
- * will trigger cache cleanup in all threads.
+/*
+ * This is incremented each time we modify the linked list of filesystems. Any
+ * time it changes, all cached filesystem representations are suspect and must
+ * be freed. For multithreading builds, change of the filesystem epoch will
+ * trigger cache cleanup in all threads.
*/
-int theFilesystemEpoch = 0;
+
+static int theFilesystemEpoch = 0;
/*
- * Stores the linked list of filesystems. A 1:1 copy of this
- * list is also maintained in the TSD for each thread. This
- * is to avoid synchronization issues.
+ * Stores the linked list of filesystems. A 1:1 copy of this list is also
+ * maintained in the TSD for each thread. This is to avoid synchronization
+ * issues.
*/
-static FilesystemRecord *filesystemList = &nativeFilesystemRecord;
+static FilesystemRecord *filesystemList = &nativeFilesystemRecord;
TCL_DECLARE_MUTEX(filesystemMutex)
-/*
+/*
* Used to implement Tcl_FSGetCwd in a file-system independent way.
*/
+
static Tcl_Obj* cwdPathPtr = NULL;
static int cwdPathEpoch = 0;
+static ClientData cwdClientData = NULL;
TCL_DECLARE_MUTEX(cwdMutex)
-/*
- * This structure holds per-thread private copies of
- * some global data. This way we avoid most of the
- * synchronization calls which boosts performance, at
- * cost of having to update this information each
- * time the corresponding epoch counter changes.
- *
- */
-typedef struct ThreadSpecificData {
- int initialized;
- int cwdPathEpoch;
- int filesystemEpoch;
- Tcl_Obj *cwdPathPtr;
- FilesystemRecord *filesystemList;
-} ThreadSpecificData;
-
-static Tcl_ThreadDataKey dataKey;
-
-/*
- * Declare fallback support function and
- * information for Tcl_FSLoadFile
- */
-static Tcl_FSUnloadFileProc FSUnloadTempFile;
+Tcl_ThreadDataKey tclFsDataKey;
/*
- * One of these structures is used each time we successfully load a
- * file from a file system by way of making a temporary copy of the
- * file on the native filesystem. We need to store both the actual
- * unloadProc/clientData combination which was used, and the original
- * and modified filenames, so that we can correctly undo the entire
- * operation when we want to unload the code.
+ * One of these structures is used each time we successfully load a file from
+ * a file system by way of making a temporary copy of the file on the native
+ * filesystem. We need to store both the actual unloadProc/clientData
+ * combination which was used, and the original and modified filenames, so
+ * that we can correctly undo the entire operation when we want to unload the
+ * code.
*/
+
typedef struct FsDivertLoad {
Tcl_LoadHandle loadHandle;
- Tcl_FSUnloadFileProc *unloadProcPtr;
+ Tcl_FSUnloadFileProc *unloadProcPtr;
Tcl_Obj *divertedFile;
- Tcl_Filesystem *divertedFilesystem;
+ const Tcl_Filesystem *divertedFilesystem;
ClientData divertedFileNativeRep;
} FsDivertLoad;
-
-/* Now move on to the basic filesystem implementation */
+
+/*
+ * Now move on to the basic filesystem implementation
+ */
static void
-FsThrExitProc(cd)
- ClientData cd;
+FsThrExitProc(
+ ClientData cd)
{
- ThreadSpecificData *tsdPtr = (ThreadSpecificData*)cd;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *) cd;
FilesystemRecord *fsRecPtr = NULL, *tmpFsRecPtr = NULL;
- /* Trash the cwd copy */
+ /*
+ * Trash the cwd copy.
+ */
+
if (tsdPtr->cwdPathPtr != NULL) {
Tcl_DecrRefCount(tsdPtr->cwdPathPtr);
tsdPtr->cwdPathPtr = NULL;
}
- /* Trash the filesystems cache */
+ if (tsdPtr->cwdClientData != NULL) {
+ NativeFreeInternalRep(tsdPtr->cwdClientData);
+ }
+
+ /*
+ * Trash the filesystems cache.
+ */
+
fsRecPtr = tsdPtr->filesystemList;
while (fsRecPtr != NULL) {
tmpFsRecPtr = fsRecPtr->nextPtr;
@@ -557,47 +483,113 @@ FsThrExitProc(cd)
tsdPtr->initialized = 0;
}
-int
-TclFSCwdPointerEquals(objPtr)
- Tcl_Obj* objPtr;
+int
+TclFSCwdIsNative(void)
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
+
+ if (tsdPtr->cwdClientData != NULL) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclFSCwdPointerEquals --
+ *
+ * Check whether the current working directory is equal to the path
+ * given.
+ *
+ * Results:
+ * 1 (equal) or 0 (un-equal) as appropriate.
+ *
+ * Side effects:
+ * If the paths are equal, but are not the same object, this method will
+ * modify the given pathPtrPtr to refer to the same object. In this case
+ * the object pointed to by pathPtrPtr will have its refCount
+ * decremented, and it will be adjusted to point to the cwd (with a new
+ * refCount).
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclFSCwdPointerEquals(
+ Tcl_Obj** pathPtrPtr)
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
Tcl_MutexLock(&cwdMutex);
- if (tsdPtr->cwdPathPtr == NULL) {
+ if (tsdPtr->cwdPathPtr == NULL
+ || tsdPtr->cwdPathEpoch != cwdPathEpoch) {
+ if (tsdPtr->cwdPathPtr != NULL) {
+ Tcl_DecrRefCount(tsdPtr->cwdPathPtr);
+ }
+ if (tsdPtr->cwdClientData != NULL) {
+ NativeFreeInternalRep(tsdPtr->cwdClientData);
+ }
if (cwdPathPtr == NULL) {
tsdPtr->cwdPathPtr = NULL;
} else {
tsdPtr->cwdPathPtr = Tcl_DuplicateObj(cwdPathPtr);
Tcl_IncrRefCount(tsdPtr->cwdPathPtr);
}
- tsdPtr->cwdPathEpoch = cwdPathEpoch;
- } else if (tsdPtr->cwdPathEpoch != cwdPathEpoch) {
- Tcl_DecrRefCount(tsdPtr->cwdPathPtr);
- if (cwdPathPtr == NULL) {
- tsdPtr->cwdPathPtr = NULL;
+ if (cwdClientData == NULL) {
+ tsdPtr->cwdClientData = NULL;
} else {
- tsdPtr->cwdPathPtr = Tcl_DuplicateObj(cwdPathPtr);
- Tcl_IncrRefCount(tsdPtr->cwdPathPtr);
+ tsdPtr->cwdClientData = TclNativeDupInternalRep(cwdClientData);
}
+ tsdPtr->cwdPathEpoch = cwdPathEpoch;
}
Tcl_MutexUnlock(&cwdMutex);
if (tsdPtr->initialized == 0) {
- Tcl_CreateThreadExitHandler(FsThrExitProc, (ClientData)tsdPtr);
+ Tcl_CreateThreadExitHandler(FsThrExitProc, (ClientData) tsdPtr);
tsdPtr->initialized = 1;
}
- return (tsdPtr->cwdPathPtr == objPtr);
+
+ if (pathPtrPtr == NULL) {
+ return (tsdPtr->cwdPathPtr == NULL);
+ }
+
+ if (tsdPtr->cwdPathPtr == *pathPtrPtr) {
+ return 1;
+ } else {
+ int len1, len2;
+ const char *str1, *str2;
+
+ str1 = Tcl_GetStringFromObj(tsdPtr->cwdPathPtr, &len1);
+ str2 = Tcl_GetStringFromObj(*pathPtrPtr, &len2);
+ if (len1 == len2 && !strcmp(str1,str2)) {
+ /*
+ * They are equal, but different objects. Update so they will be
+ * the same object in the future.
+ */
+
+ Tcl_DecrRefCount(*pathPtrPtr);
+ *pathPtrPtr = tsdPtr->cwdPathPtr;
+ Tcl_IncrRefCount(*pathPtrPtr);
+ return 1;
+ } else {
+ return 0;
+ }
+ }
}
-#ifdef TCL_THREADS
+#ifdef TCL_THREADS
static void
FsRecacheFilesystemList(void)
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
FilesystemRecord *fsRecPtr, *tmpFsRecPtr = NULL;
- /* Trash the current cache */
+ /*
+ * Trash the current cache.
+ */
+
fsRecPtr = tsdPtr->filesystemList;
while (fsRecPtr != NULL) {
tmpFsRecPtr = fsRecPtr->nextPtr;
@@ -609,22 +601,25 @@ FsRecacheFilesystemList(void)
tsdPtr->filesystemList = NULL;
/*
- * Code below operates on shared data. We
- * are already called under mutex lock so
- * we can safely proceed.
+ * Code below operates on shared data. We are already called under mutex
+ * lock so we can safely proceed.
+ *
+ * Locate tail of the global filesystem list.
*/
- /* Locate tail of the global filesystem list */
fsRecPtr = filesystemList;
while (fsRecPtr != NULL) {
tmpFsRecPtr = fsRecPtr;
fsRecPtr = fsRecPtr->nextPtr;
}
-
- /* Refill the cache honouring the order */
+
+ /*
+ * Refill the cache honouring the order.
+ */
+
fsRecPtr = tmpFsRecPtr;
while (fsRecPtr != NULL) {
- tmpFsRecPtr = (FilesystemRecord *)ckalloc(sizeof(FilesystemRecord));
+ tmpFsRecPtr = (FilesystemRecord *) ckalloc(sizeof(FilesystemRecord));
*tmpFsRecPtr = *fsRecPtr;
tmpFsRecPtr->nextPtr = tsdPtr->filesystemList;
tmpFsRecPtr->prevPtr = NULL;
@@ -632,20 +627,24 @@ FsRecacheFilesystemList(void)
tsdPtr->filesystemList->prevPtr = tmpFsRecPtr;
}
tsdPtr->filesystemList = tmpFsRecPtr;
- fsRecPtr = fsRecPtr->prevPtr;
+ fsRecPtr = fsRecPtr->prevPtr;
}
- /* Make sure the above gets released on thread exit */
+ /*
+ * Make sure the above gets released on thread exit.
+ */
+
if (tsdPtr->initialized == 0) {
- Tcl_CreateThreadExitHandler(FsThrExitProc, (ClientData)tsdPtr);
+ Tcl_CreateThreadExitHandler(FsThrExitProc, (ClientData) tsdPtr);
tsdPtr->initialized = 1;
}
}
-#endif
+#endif /* TCL_THREADS */
static FilesystemRecord *
-FsGetFirstFilesystem(void) {
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+FsGetFirstFilesystem(void)
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
FilesystemRecord *fsRecPtr;
#ifndef TCL_THREADS
tsdPtr->filesystemEpoch = theFilesystemEpoch;
@@ -654,7 +653,7 @@ FsGetFirstFilesystem(void) {
Tcl_MutexLock(&filesystemMutex);
if (tsdPtr->filesystemList == NULL
|| (tsdPtr->filesystemEpoch != theFilesystemEpoch)) {
- FsRecacheFilesystemList();
+ FsRecacheFilesystemList();
tsdPtr->filesystemEpoch = theFilesystemEpoch;
}
Tcl_MutexUnlock(&filesystemMutex);
@@ -663,13 +662,32 @@ FsGetFirstFilesystem(void) {
return fsRecPtr;
}
+/*
+ * The epoch can be changed both by filesystems being added or removed and by
+ * env(HOME) changing.
+ */
+
+int
+TclFSEpochOk(
+ int filesystemEpoch)
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
+ (void) FsGetFirstFilesystem();
+ return (filesystemEpoch == tsdPtr->filesystemEpoch);
+}
+
+/*
+ * If non-NULL, clientData is owned by us and must be freed later.
+ */
+
static void
-FsUpdateCwd(cwdObj)
- Tcl_Obj *cwdObj;
+FsUpdateCwd(
+ Tcl_Obj *cwdObj,
+ ClientData clientData)
{
int len;
char *str = NULL;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
if (cwdObj != NULL) {
str = Tcl_GetStringFromObj(cwdObj, &len);
@@ -677,26 +695,42 @@ FsUpdateCwd(cwdObj)
Tcl_MutexLock(&cwdMutex);
if (cwdPathPtr != NULL) {
- Tcl_DecrRefCount(cwdPathPtr);
+ Tcl_DecrRefCount(cwdPathPtr);
+ }
+ if (cwdClientData != NULL) {
+ NativeFreeInternalRep(cwdClientData);
}
+
if (cwdObj == NULL) {
cwdPathPtr = NULL;
+ cwdClientData = NULL;
} else {
- /* This MUST be stored as string object! */
- cwdPathPtr = Tcl_NewStringObj(str, len);
+ /*
+ * This must be stored as string obj!
+ */
+
+ cwdPathPtr = Tcl_NewStringObj(str, len);
Tcl_IncrRefCount(cwdPathPtr);
+ cwdClientData = TclNativeDupInternalRep(clientData);
}
+
cwdPathEpoch++;
tsdPtr->cwdPathEpoch = cwdPathEpoch;
Tcl_MutexUnlock(&cwdMutex);
if (tsdPtr->cwdPathPtr) {
- Tcl_DecrRefCount(tsdPtr->cwdPathPtr);
+ Tcl_DecrRefCount(tsdPtr->cwdPathPtr);
+ }
+ if (tsdPtr->cwdClientData) {
+ NativeFreeInternalRep(tsdPtr->cwdClientData);
}
+
if (cwdObj == NULL) {
tsdPtr->cwdPathPtr = NULL;
+ tsdPtr->cwdClientData = NULL;
} else {
- tsdPtr->cwdPathPtr = Tcl_NewStringObj(str, len);
+ tsdPtr->cwdPathPtr = Tcl_NewStringObj(str, len);
+ tsdPtr->cwdClientData = clientData;
Tcl_IncrRefCount(tsdPtr->cwdPathPtr);
}
}
@@ -706,12 +740,12 @@ FsUpdateCwd(cwdObj)
*
* TclFinalizeFilesystem --
*
- * Clean up the filesystem. After this, calls to all Tcl_FS...
- * functions will fail.
- *
- * We will later call TclResetFilesystem to restore the FS
- * to a pristine state.
- *
+ * Clean up the filesystem. After this, calls to all Tcl_FS... functions
+ * will fail.
+ *
+ * We will later call TclResetFilesystem to restore the FS to a pristine
+ * state.
+ *
* Results:
* None.
*
@@ -722,31 +756,38 @@ FsUpdateCwd(cwdObj)
*/
void
-TclFinalizeFilesystem()
+TclFinalizeFilesystem(void)
{
FilesystemRecord *fsRecPtr;
- /*
- * Assumption that only one thread is active now. Otherwise
- * we would need to put various mutexes around this code.
+ /*
+ * Assumption that only one thread is active now. Otherwise we would need
+ * to put various mutexes around this code.
*/
-
+
if (cwdPathPtr != NULL) {
Tcl_DecrRefCount(cwdPathPtr);
cwdPathPtr = NULL;
- cwdPathEpoch = 0;
+ cwdPathEpoch = 0;
+ }
+ if (cwdClientData != NULL) {
+ NativeFreeInternalRep(cwdClientData);
+ cwdClientData = NULL;
}
- /*
- * Remove all filesystems, freeing any allocated memory
- * that is no longer needed
+ /*
+ * Remove all filesystems, freeing any allocated memory that is no longer
+ * needed
*/
fsRecPtr = filesystemList;
while (fsRecPtr != NULL) {
FilesystemRecord *tmpFsRecPtr = fsRecPtr->nextPtr;
if (fsRecPtr->fileRefCount <= 0) {
- /* The native filesystem is static, so we don't free it */
+ /*
+ * The native filesystem is static, so we don't free it.
+ */
+
if (fsRecPtr->fsPtr != &tclNativeFilesystem) {
ckfree((char *)fsRecPtr);
}
@@ -756,13 +797,15 @@ TclFinalizeFilesystem()
filesystemList = NULL;
/*
- * Now filesystemList is NULL. This means that any attempt
- * to use the filesystem is likely to fail.
+ * Now filesystemList is NULL. This means that any attempt to use the
+ * filesystem is likely to fail.
*/
+#ifdef USE_OBSOLETE_FS_HOOKS
statProcList = NULL;
accessProcList = NULL;
openFileChannelProcList = NULL;
+#endif
#ifdef __WIN32__
TclWinEncodingsCleanup();
#endif
@@ -774,7 +817,7 @@ TclFinalizeFilesystem()
* TclResetFilesystem --
*
* Restore the filesystem to a pristine state.
- *
+ *
* Results:
* None.
*
@@ -785,22 +828,21 @@ TclFinalizeFilesystem()
*/
void
-TclResetFilesystem()
+TclResetFilesystem(void)
{
filesystemList = &nativeFilesystemRecord;
- /*
- * Note, at this point, I believe nativeFilesystemRecord ->
- * fileRefCount should equal 1 and if not, we should try to track
- * down the cause.
+ /*
+ * Note, at this point, I believe nativeFilesystemRecord -> fileRefCount
+ * should equal 1 and if not, we should try to track down the cause.
*/
-
+
#ifdef __WIN32__
- /*
- * Cleans up the win32 API filesystem proc lookup table. This must
- * happen very late in finalization so that deleting of copied
- * dlls can occur.
+ /*
+ * Cleans up the win32 API filesystem proc lookup table. This must happen
+ * very late in finalization so that deleting of copied dlls can occur.
*/
+
TclWinResetInterfaces();
#endif
}
@@ -810,36 +852,35 @@ TclResetFilesystem()
*
* Tcl_FSRegister --
*
- * Insert the filesystem function table at the head of the list of
- * functions which are used during calls to all file-system
- * operations. The filesystem will be added even if it is
- * already in the list. (You can use Tcl_FSData to
- * check if it is in the list, provided the ClientData used was
- * not NULL).
- *
- * Note that the filesystem handling is head-to-tail of the list.
- * Each filesystem is asked in turn whether it can handle a
- * particular request, _until_ one of them says 'yes'. At that
- * point no further filesystems are asked.
- *
- * In particular this means if you want to add a diagnostic
- * filesystem (which simply reports all fs activity), it must be
- * at the head of the list: i.e. it must be the last registered.
+ * Insert the filesystem function table at the head of the list of
+ * functions which are used during calls to all file-system operations.
+ * The filesystem will be added even if it is already in the list. (You
+ * can use Tcl_FSData to check if it is in the list, provided the
+ * ClientData used was not NULL).
+ *
+ * Note that the filesystem handling is head-to-tail of the list. Each
+ * filesystem is asked in turn whether it can handle a particular
+ * request, until one of them says 'yes'. At that point no further
+ * filesystems are asked.
+ *
+ * In particular this means if you want to add a diagnostic filesystem
+ * (which simply reports all fs activity), it must be at the head of the
+ * list: i.e. it must be the last registered.
*
* Results:
- * Normally TCL_OK; TCL_ERROR if memory for a new node in the list
- * could not be allocated.
+ * Normally TCL_OK; TCL_ERROR if memory for a new node in the list could
+ * not be allocated.
*
* Side effects:
- * Memory allocated and modifies the link list for filesystems.
+ * Memory allocated and modifies the link list for filesystems.
*
*----------------------------------------------------------------------
*/
int
-Tcl_FSRegister(clientData, fsPtr)
- ClientData clientData; /* Client specific data for this fs */
- Tcl_Filesystem *fsPtr; /* The filesystem record for the new fs. */
+Tcl_FSRegister(
+ ClientData clientData, /* Client specific data for this fs */
+ Tcl_Filesystem *fsPtr) /* The filesystem record for the new fs. */
{
FilesystemRecord *newFilesystemPtr;
@@ -851,25 +892,27 @@ Tcl_FSRegister(clientData, fsPtr)
newFilesystemPtr->clientData = clientData;
newFilesystemPtr->fsPtr = fsPtr;
- /*
- * We start with a refCount of 1. If this drops to zero, then
- * anyone is welcome to ckfree us.
+
+ /*
+ * We start with a refCount of 1. If this drops to zero, then anyone is
+ * welcome to ckfree us.
*/
+
newFilesystemPtr->fileRefCount = 1;
- /*
- * Is this lock and wait strictly speaking necessary? Since any
- * iterators out there will have grabbed a copy of the head of
- * the list and be iterating away from that, if we add a new
- * element to the head of the list, it can't possibly have any
- * effect on any of their loops. In fact it could be better not
- * to wait, since we are adjusting the filesystem epoch, any
- * cached representations calculated by existing iterators are
+ /*
+ * Is this lock and wait strictly speaking necessary? Since any iterators
+ * out there will have grabbed a copy of the head of the list and be
+ * iterating away from that, if we add a new element to the head of the
+ * list, it can't possibly have any effect on any of their loops. In fact
+ * it could be better not to wait, since we are adjusting the filesystem
+ * epoch, any cached representations calculated by existing iterators are
* going to have to be thrown away anyway.
- *
- * However, since registering and unregistering filesystems is
- * a very rare action, this is not a very important point.
+ *
+ * However, since registering and unregistering filesystems is a very rare
+ * action, this is not a very important point.
*/
+
Tcl_MutexLock(&filesystemMutex);
newFilesystemPtr->nextPtr = filesystemList;
@@ -879,10 +922,11 @@ Tcl_FSRegister(clientData, fsPtr)
}
filesystemList = newFilesystemPtr;
- /*
- * Increment the filesystem epoch counter, since existing paths
- * might conceivably now belong to different filesystems.
+ /*
+ * Increment the filesystem epoch counter, since existing paths might
+ * conceivably now belong to different filesystems.
*/
+
theFilesystemEpoch++;
Tcl_MutexUnlock(&filesystemMutex);
@@ -894,29 +938,28 @@ Tcl_FSRegister(clientData, fsPtr)
*
* Tcl_FSUnregister --
*
- * Remove the passed filesystem from the list of filesystem
- * function tables. It also ensures that the built-in
- * (native) filesystem is not removable, although we may wish
- * to change that decision in the future to allow a smaller
- * Tcl core, in which the native filesystem is not used at
- * all (we could, say, initialise Tcl completely over a network
- * connection).
+ * Remove the passed filesystem from the list of filesystem function
+ * tables. It also ensures that the built-in (native) filesystem is not
+ * removable, although we may wish to change that decision in the future
+ * to allow a smaller Tcl core, in which the native filesystem is not
+ * used at all (we could, say, initialise Tcl completely over a network
+ * connection).
*
* Results:
- * TCL_OK if the procedure pointer was successfully removed,
- * TCL_ERROR otherwise.
+ * TCL_OK if the function pointer was successfully removed, TCL_ERROR
+ * otherwise.
*
* Side effects:
- * Memory may be deallocated (or will be later, once no "path"
- * objects refer to this filesystem), but the list of registered
- * filesystems is updated immediately.
+ * Memory may be deallocated (or will be later, once no "path" objects
+ * refer to this filesystem), but the list of registered filesystems is
+ * updated immediately.
*
*----------------------------------------------------------------------
*/
int
-Tcl_FSUnregister(fsPtr)
- Tcl_Filesystem *fsPtr; /* The filesystem record to remove. */
+Tcl_FSUnregister(
+ Tcl_Filesystem *fsPtr) /* The filesystem record to remove. */
{
int retVal = TCL_ERROR;
FilesystemRecord *fsRecPtr;
@@ -924,9 +967,9 @@ Tcl_FSUnregister(fsPtr)
Tcl_MutexLock(&filesystemMutex);
/*
- * Traverse the 'filesystemList' looking for the particular node
- * whose 'fsPtr' member matches 'fsPtr' and remove that one from
- * the list. Ensure that the "default" node cannot be removed.
+ * Traverse the 'filesystemList' looking for the particular node whose
+ * 'fsPtr' member matches 'fsPtr' and remove that one from the list.
+ * Ensure that the "default" node cannot be removed.
*/
fsRecPtr = filesystemList;
@@ -940,19 +983,20 @@ Tcl_FSUnregister(fsPtr)
if (fsRecPtr->nextPtr) {
fsRecPtr->nextPtr->prevPtr = fsRecPtr->prevPtr;
}
- /*
- * Increment the filesystem epoch counter, since existing
- * paths might conceivably now belong to different
- * filesystems. This should also ensure that paths which
- * have cached the filesystem which is about to be deleted
- * do not reference that filesystem (which would of course
- * lead to memory exceptions).
+
+ /*
+ * Increment the filesystem epoch counter, since existing paths
+ * might conceivably now belong to different filesystems. This
+ * should also ensure that paths which have cached the filesystem
+ * which is about to be deleted do not reference that filesystem
+ * (which would of course lead to memory exceptions).
*/
+
theFilesystemEpoch++;
-
+
fsRecPtr->fileRefCount--;
if (fsRecPtr->fileRefCount <= 0) {
- ckfree((char *)fsRecPtr);
+ ckfree((char *)fsRecPtr);
}
retVal = TCL_OK;
@@ -962,7 +1006,7 @@ Tcl_FSUnregister(fsPtr)
}
Tcl_MutexUnlock(&filesystemMutex);
- return (retVal);
+ return retVal;
}
/*
@@ -970,132 +1014,145 @@ Tcl_FSUnregister(fsPtr)
*
* Tcl_FSMatchInDirectory --
*
- * This routine is used by the globbing code to search a directory
- * for all files which match a given pattern. The appropriate
- * function for the filesystem to which pathPtr belongs will be
- * called. If pathPtr does not belong to any filesystem and if it
- * is NULL or the empty string, then we assume the pattern is to be
- * matched in the current working directory. To avoid each
- * filesystem's Tcl_FSMatchInDirectoryProc having to deal with this
- * issue, we create a pathPtr on the fly (equal to the cwd), and
- * then remove it from the results returned. This makes filesystems
- * easy to write, since they can assume the pathPtr passed to them
- * is an ordinary path. In fact this means we could remove such
- * special case handling from Tcl's native filesystems.
- *
- * If 'pattern' is NULL, then pathPtr is assumed to be a fully
- * specified path of a single file/directory which must be
- * checked for existence and correct type.
- *
- * Results:
- *
- * The return value is a standard Tcl result indicating whether an
- * error occurred in globbing. Error messages are placed in
- * interp, but good results are placed in the resultPtr given.
- *
+ * This routine is used by the globbing code to search a directory for
+ * all files which match a given pattern. The appropriate function for
+ * the filesystem to which pathPtr belongs will be called. If pathPtr
+ * does not belong to any filesystem and if it is NULL or the empty
+ * string, then we assume the pattern is to be matched in the current
+ * working directory. To avoid have the Tcl_FSMatchInDirectoryProc for
+ * each filesystem from having to deal with this issue, we create a
+ * pathPtr on the fly (equal to the cwd), and then remove it from the
+ * results returned. This makes filesystems easy to write, since they can
+ * assume the pathPtr passed to them is an ordinary path. In fact this
+ * means we could remove such special case handling from Tcl's native
+ * filesystems.
+ *
+ * If 'pattern' is NULL, then pathPtr is assumed to be a fully specified
+ * path of a single file/directory which must be checked for existence
+ * and correct type.
+ *
+ * Results:
+ *
+ * The return value is a standard Tcl result indicating whether an error
+ * occurred in globbing. Error messages are placed in interp, but good
+ * results are placed in the resultPtr given.
+ *
* Recursive searches, e.g.
- *
- * glob -dir $dir -join * pkgIndex.tcl
- *
- * which must recurse through each directory matching '*' are
- * handled internally by Tcl, by passing specific flags in a
- * modified 'types' parameter. This means the actual filesystem
- * only ever sees patterns which match in a single directory.
+ * glob -dir $dir -join * pkgIndex.tcl
+ * which must recurse through each directory matching '*' are handled
+ * internally by Tcl, by passing specific flags in a modified 'types'
+ * parameter. This means the actual filesystem only ever sees patterns
+ * which match in a single directory.
*
* Side effects:
* The interpreter may have an error message inserted into it.
*
- *----------------------------------------------------------------------
+ *----------------------------------------------------------------------
*/
int
-Tcl_FSMatchInDirectory(interp, result, pathPtr, pattern, types)
- Tcl_Interp *interp; /* Interpreter to receive error messages. */
- Tcl_Obj *result; /* List object to receive results. */
- Tcl_Obj *pathPtr; /* Contains path to directory to search. */
- CONST char *pattern; /* Pattern to match against. */
- Tcl_GlobTypeData *types; /* Object containing list of acceptable types.
+Tcl_FSMatchInDirectory(
+ Tcl_Interp *interp, /* Interpreter to receive error messages, but
+ * may be NULL. */
+ Tcl_Obj *resultPtr, /* List object to receive results. */
+ Tcl_Obj *pathPtr, /* Contains path to directory to search. */
+ const char *pattern, /* Pattern to match against. */
+ Tcl_GlobTypeData *types) /* Object containing list of acceptable types.
* May be NULL. In particular the directory
* flag is very important. */
{
- Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
+ const Tcl_Filesystem *fsPtr;
+ Tcl_Obj *cwd, *tmpResultPtr, **elemsPtr;
+ int resLength, i, ret = -1;
+
+ if (types != NULL && types->type & TCL_GLOB_TYPE_MOUNT) {
+ /*
+ * We don't currently allow querying of mounts by external code (a
+ * valuable future step), so since we're the only function that
+ * actually knows about mounts, this means we're being called
+ * recursively by ourself. Return no matches.
+ */
+
+ return TCL_OK;
+ }
+
+ if (pathPtr != NULL) {
+ fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
+ } else {
+ fsPtr = NULL;
+ }
+
+ /*
+ * Check if we've successfully mapped the path to a filesystem within
+ * which to search.
+ */
+
if (fsPtr != NULL) {
- Tcl_FSMatchInDirectoryProc *proc = fsPtr->matchInDirectoryProc;
- if (proc != NULL) {
- int ret = (*proc)(interp, result, pathPtr, pattern, types);
- if (ret == TCL_OK && pattern != NULL) {
- result = FsAddMountsToGlobResult(result, pathPtr,
- pattern, types);
- }
- return ret;
+ if (fsPtr->matchInDirectoryProc == NULL) {
+ Tcl_SetErrno(ENOENT);
+ return -1;
}
- } else {
- Tcl_Obj* cwd;
- int ret = -1;
- if (pathPtr != NULL) {
- int len;
- Tcl_GetStringFromObj(pathPtr,&len);
- if (len != 0) {
- /*
- * We have no idea how to match files in a directory
- * which belongs to no known filesystem
- */
- Tcl_SetErrno(ENOENT);
- return -1;
- }
+ ret = (*fsPtr->matchInDirectoryProc)(interp, resultPtr, pathPtr,
+ pattern, types);
+ if (ret == TCL_OK && pattern != NULL) {
+ FsAddMountsToGlobResult(resultPtr, pathPtr, pattern, types);
}
- /*
- * We have an empty or NULL path. This is defined to mean we
- * must search for files within the current 'cwd'. We
- * therefore use that, but then since the proc we call will
- * return results which include the cwd we must then trim it
- * off the front of each path in the result. We choose to deal
- * with this here (in the generic code), since if we don't,
- * every single filesystem's implementation of
- * Tcl_FSMatchInDirectory will have to deal with it for us.
- */
- cwd = Tcl_FSGetCwd(NULL);
- if (cwd == NULL) {
- if (interp != NULL) {
- Tcl_SetResult(interp, "glob couldn't determine "
- "the current working directory", TCL_STATIC);
- }
- return TCL_ERROR;
+ return ret;
+ }
+
+ /*
+ * If the path isn't empty, we have no idea how to match files in a
+ * directory which belongs to no known filesystem
+ */
+
+ if (pathPtr != NULL && TclGetString(pathPtr)[0] != '\0') {
+ Tcl_SetErrno(ENOENT);
+ return -1;
+ }
+
+ /*
+ * We have an empty or NULL path. This is defined to mean we must search
+ * for files within the current 'cwd'. We therefore use that, but then
+ * since the proc we call will return results which include the cwd we
+ * must then trim it off the front of each path in the result. We choose
+ * to deal with this here (in the generic code), since if we don't, every
+ * single filesystem's implementation of Tcl_FSMatchInDirectory will have
+ * to deal with it for us.
+ */
+
+ cwd = Tcl_FSGetCwd(NULL);
+ if (cwd == NULL) {
+ if (interp != NULL) {
+ Tcl_SetResult(interp, "glob couldn't determine "
+ "the current working directory", TCL_STATIC);
}
- fsPtr = Tcl_FSGetFileSystemForPath(cwd);
- if (fsPtr != NULL) {
- Tcl_FSMatchInDirectoryProc *proc = fsPtr->matchInDirectoryProc;
- if (proc != NULL) {
- Tcl_Obj* tmpResultPtr = Tcl_NewListObj(0, NULL);
- Tcl_IncrRefCount(tmpResultPtr);
- ret = (*proc)(interp, tmpResultPtr, cwd, pattern, types);
- if (ret == TCL_OK) {
- int resLength;
-
- tmpResultPtr = FsAddMountsToGlobResult(tmpResultPtr, cwd,
- pattern, types);
-
- ret = Tcl_ListObjLength(interp, tmpResultPtr, &resLength);
- if (ret == TCL_OK) {
- int i;
-
- for (i = 0; i < resLength; i++) {
- Tcl_Obj *elt;
-
- Tcl_ListObjIndex(interp, tmpResultPtr, i, &elt);
- Tcl_ListObjAppendElement(interp, result,
- TclFSMakePathRelative(interp, elt, cwd));
- }
- }
- }
- Tcl_DecrRefCount(tmpResultPtr);
+ return TCL_ERROR;
+ }
+
+ fsPtr = Tcl_FSGetFileSystemForPath(cwd);
+ if (fsPtr != NULL && fsPtr->matchInDirectoryProc != NULL) {
+ TclNewObj(tmpResultPtr);
+ Tcl_IncrRefCount(tmpResultPtr);
+ ret = (*fsPtr->matchInDirectoryProc)(interp, tmpResultPtr, cwd,
+ pattern, types);
+ if (ret == TCL_OK) {
+ FsAddMountsToGlobResult(tmpResultPtr, cwd, pattern, types);
+
+ /*
+ * Note that we know resultPtr and tmpResultPtr are distinct.
+ */
+
+ ret = Tcl_ListObjGetElements(interp, tmpResultPtr,
+ &resLength, &elemsPtr);
+ for (i=0 ; ret==TCL_OK && i<resLength ; i++) {
+ ret = Tcl_ListObjAppendElement(interp, resultPtr,
+ TclFSMakePathRelative(interp, elemsPtr[i], cwd));
}
}
- Tcl_DecrRefCount(cwd);
- return ret;
+ TclDecrRefCount(tmpResultPtr);
}
- Tcl_SetErrno(ENOENT);
- return -1;
+ Tcl_DecrRefCount(cwd);
+ return ret;
}
/*
@@ -1103,85 +1160,104 @@ Tcl_FSMatchInDirectory(interp, result, pathPtr, pattern, types)
*
* FsAddMountsToGlobResult --
*
- * This routine is used by the globbing code to take the results
- * of a directory listing and add any mounted paths to that
- * listing. This is required so that simple things like
- * 'glob *' merge mounts and listings correctly.
- *
- * Results:
- *
- * The passed in 'result' may be modified (in place, if
- * necessary), and the correct list is returned.
+ * This routine is used by the globbing code to take the results of a
+ * directory listing and add any mounted paths to that listing. This is
+ * required so that simple things like 'glob *' merge mounts and listings
+ * correctly.
*
- * Side effects:
+ * Results:
* None.
*
- *----------------------------------------------------------------------
+ * Side effects:
+ * Modifies the resultPtr.
+ *
+ *----------------------------------------------------------------------
*/
-static Tcl_Obj*
-FsAddMountsToGlobResult(result, pathPtr, pattern, types)
- Tcl_Obj *result; /* The current list of matching paths */
- Tcl_Obj *pathPtr; /* The directory in question */
- CONST char *pattern;
- Tcl_GlobTypeData *types;
+
+static void
+FsAddMountsToGlobResult(
+ Tcl_Obj *resultPtr, /* The current list of matching paths; must
+ * not be shared! */
+ Tcl_Obj *pathPtr, /* The directory in question */
+ const char *pattern, /* Pattern to match against. */
+ Tcl_GlobTypeData *types) /* Object containing list of acceptable types.
+ * May be NULL. In particular the directory
+ * flag is very important. */
{
int mLength, gLength, i;
int dir = (types == NULL || (types->type & TCL_GLOB_TYPE_DIR));
Tcl_Obj *mounts = FsListMounts(pathPtr, pattern);
- if (mounts == NULL) return result;
+ if (mounts == NULL) {
+ return;
+ }
if (Tcl_ListObjLength(NULL, mounts, &mLength) != TCL_OK || mLength == 0) {
goto endOfMounts;
}
- if (Tcl_ListObjLength(NULL, result, &gLength) != TCL_OK) {
+ if (Tcl_ListObjLength(NULL, resultPtr, &gLength) != TCL_OK) {
goto endOfMounts;
}
- for (i = 0; i < mLength; i++) {
+ for (i=0 ; i<mLength ; i++) {
Tcl_Obj *mElt;
int j;
int found = 0;
-
+
Tcl_ListObjIndex(NULL, mounts, i, &mElt);
- for (j = 0; j < gLength; j++) {
+ for (j=0 ; j<gLength ; j++) {
Tcl_Obj *gElt;
- Tcl_ListObjIndex(NULL, result, j, &gElt);
+
+ Tcl_ListObjIndex(NULL, resultPtr, j, &gElt);
if (Tcl_FSEqualPaths(mElt, gElt)) {
found = 1;
if (!dir) {
- /* We don't want to list this */
- if (Tcl_IsShared(result)) {
- Tcl_Obj *newList;
- newList = Tcl_DuplicateObj(result);
- Tcl_DecrRefCount(result);
- result = newList;
- }
- Tcl_ListObjReplace(NULL, result, j, 1, 0, NULL);
+ /*
+ * We don't want to list this.
+ */
+
+ Tcl_ListObjReplace(NULL, resultPtr, j, 1, 0, NULL);
gLength--;
}
- /* Break out of for loop */
- break;
+ break; /* Break out of for loop */
}
}
if (!found && dir) {
- if (Tcl_IsShared(result)) {
- Tcl_Obj *newList;
- newList = Tcl_DuplicateObj(result);
- Tcl_DecrRefCount(result);
- result = newList;
+ Tcl_Obj *norm;
+ int len, mlen;
+
+ /*
+ * We know mElt is absolute normalized and lies inside pathPtr, so
+ * now we must add to the result the right representation of mElt,
+ * i.e. the representation which is relative to pathPtr.
+ */
+
+ norm = Tcl_FSGetNormalizedPath(NULL, pathPtr);
+ if (norm != NULL) {
+ const char *path, *mount;
+
+ mount = Tcl_GetStringFromObj(mElt, &mlen);
+ path = Tcl_GetStringFromObj(norm, &len);
+ if (path[len-1] == '/') {
+ /*
+ * Deal with the root of the volume.
+ */
+
+ len--;
+ }
+ len++; /* account for '/' in the mElt [Bug 1602539] */
+ mElt = TclNewFSPathObj(pathPtr, mount + len, mlen - len);
+ Tcl_ListObjAppendElement(NULL, resultPtr, mElt);
}
- Tcl_ListObjAppendElement(NULL, result, mElt);
- /*
- * No need to increment gLength, since we
- * don't want to compare mounts against
- * mounts.
+ /*
+ * No need to increment gLength, since we don't want to compare
+ * mounts against mounts.
*/
}
}
+
endOfMounts:
Tcl_DecrRefCount(mounts);
- return result;
}
/*
@@ -1189,65 +1265,65 @@ FsAddMountsToGlobResult(result, pathPtr, pattern, types)
*
* Tcl_FSMountsChanged --
*
- * Notify the filesystem that the available mounted filesystems
- * (or within any one filesystem type, the number or location of
- * mount points) have changed.
+ * Notify the filesystem that the available mounted filesystems (or
+ * within any one filesystem type, the number or location of mount
+ * points) have changed.
*
* Results:
- * None.
+ * None.
*
* Side effects:
- * The global filesystem variable 'theFilesystemEpoch' is
- * incremented. The effect of this is to make all cached
- * path representations invalid. Clearly it should only therefore
- * be called when it is really required! There are a few
- * circumstances when it should be called:
- *
- * (1) when a new filesystem is registered or unregistered.
- * Strictly speaking this is only necessary if the new filesystem
- * accepts file paths as is (normally the filesystem itself is
- * really a shell which hasn't yet had any mount points established
- * and so its 'pathInFilesystem' proc will always fail). However,
- * for safety, Tcl always calls this for you in these circumstances.
- *
- * (2) when additional mount points are established inside any
- * existing filesystem (except the native fs)
- *
- * (3) when any filesystem (except the native fs) changes the list
- * of available volumes.
- *
- * (4) when the mapping from a string representation of a file to
- * a full, normalized path changes. For example, if 'env(HOME)'
- * is modified, then any path containing '~' will map to a different
- * filesystem location. Therefore all such paths need to have
- * their internal representation invalidated.
- *
- * Tcl has no control over (2) and (3), so any registered filesystem
- * must make sure it calls this function when those situations
- * occur.
- *
- * (Note: the reason for the exception in 2,3 for the native
- * filesystem is that the native filesystem by default claims all
- * unknown files even if it really doesn't understand them or if
- * they don't exist).
+ * The global filesystem variable 'theFilesystemEpoch' is incremented.
+ * The effect of this is to make all cached path representations invalid.
+ * Clearly it should only therefore be called when it is really required!
+ * There are a few circumstances when it should be called:
+ *
+ * (1) when a new filesystem is registered or unregistered. Strictly
+ * speaking this is only necessary if the new filesystem accepts file
+ * paths as is (normally the filesystem itself is really a shell which
+ * hasn't yet had any mount points established and so its
+ * 'pathInFilesystem' proc will always fail). However, for safety, Tcl
+ * always calls this for you in these circumstances.
+ *
+ * (2) when additional mount points are established inside any existing
+ * filesystem (except the native fs)
+ *
+ * (3) when any filesystem (except the native fs) changes the list of
+ * available volumes.
+ *
+ * (4) when the mapping from a string representation of a file to a full,
+ * normalized path changes. For example, if 'env(HOME)' is modified, then
+ * any path containing '~' will map to a different filesystem location.
+ * Therefore all such paths need to have their internal representation
+ * invalidated.
+ *
+ * Tcl has no control over (2) and (3), so any registered filesystem must
+ * make sure it calls this function when those situations occur.
+ *
+ * (Note: the reason for the exception in 2,3 for the native filesystem
+ * is that the native filesystem by default claims all unknown files even
+ * if it really doesn't understand them or if they don't exist).
*
*----------------------------------------------------------------------
*/
void
-Tcl_FSMountsChanged(fsPtr)
- Tcl_Filesystem *fsPtr;
+Tcl_FSMountsChanged(
+ Tcl_Filesystem *fsPtr)
{
- /*
- * We currently don't do anything with this parameter. We
- * could in the future only invalidate files for this filesystem
- * or otherwise take more advanced action.
+ /*
+ * We currently don't do anything with this parameter. We could in the
+ * future only invalidate files for this filesystem or otherwise take more
+ * advanced action.
*/
+
(void)fsPtr;
- /*
- * Increment the filesystem epoch counter, since existing paths
- * might now belong to different filesystems.
+
+ /*
+ * Increment the filesystem epoch counter, since existing paths might now
+ * belong to different filesystems.
*/
+
Tcl_MutexLock(&filesystemMutex);
theFilesystemEpoch++;
Tcl_MutexUnlock(&filesystemMutex);
@@ -1258,31 +1334,31 @@ Tcl_FSMountsChanged(fsPtr)
*
* Tcl_FSData --
*
- * Retrieve the clientData field for the filesystem given,
- * or NULL if that filesystem is not registered.
+ * Retrieve the clientData field for the filesystem given, or NULL if
+ * that filesystem is not registered.
*
* Results:
- * A clientData value, or NULL. Note that if the filesystem
- * was registered with a NULL clientData field, this function
- * will return that NULL value.
+ * A clientData value, or NULL. Note that if the filesystem was
+ * registered with a NULL clientData field, this function will return
+ * that NULL value.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
ClientData
-Tcl_FSData(fsPtr)
- Tcl_Filesystem *fsPtr; /* The filesystem record to query. */
+Tcl_FSData(
+ Tcl_Filesystem *fsPtr) /* The filesystem record to query. */
{
ClientData retVal = NULL;
FilesystemRecord *fsRecPtr = FsGetFirstFilesystem();
/*
- * Traverse the 'filesystemList' looking for the particular node
- * whose 'fsPtr' member matches 'fsPtr' and remove that one from
- * the list. Ensure that the "default" node cannot be removed.
+ * Traverse the list of filesystems look for a particular one. If found,
+ * return that filesystem's clientData (originally provided when calling
+ * Tcl_FSRegister).
*/
while ((retVal == NULL) && (fsRecPtr != NULL)) {
@@ -1298,201 +1374,82 @@ Tcl_FSData(fsPtr)
/*
*---------------------------------------------------------------------------
*
- * TclFSNormalizeAbsolutePath --
- *
- * Description:
- * Takes an absolute path specification and computes a 'normalized'
- * path from it.
- *
- * A normalized path is one which has all '../', './' removed.
- * Also it is one which is in the 'standard' format for the native
- * platform. On MacOS, Unix, this means the path must be free of
- * symbolic links/aliases, and on Windows it means we want the
- * long form, with that long form's case-dependence (which gives
- * us a unique, case-dependent path).
- *
- * The behaviour of this function if passed a non-absolute path
- * is NOT defined.
- *
- * Results:
- * The result is returned in a Tcl_Obj with a refCount of 1,
- * which is therefore owned by the caller. It must be
- * freed (with Tcl_DecrRefCount) by the caller when no longer needed.
- *
- * Side effects:
- * None (beyond the memory allocation for the result).
- *
- * Special note:
- * This code is based on code from Matt Newman and Jean-Claude
- * Wippler, with additions from Vince Darley and is copyright
- * those respective authors.
- *
- *---------------------------------------------------------------------------
- */
-static Tcl_Obj *
-TclFSNormalizeAbsolutePath(interp, pathPtr, clientDataPtr)
- Tcl_Interp* interp; /* Interpreter to use */
- Tcl_Obj *pathPtr; /* Absolute path to normalize */
- ClientData *clientDataPtr;
-{
- int splen = 0, nplen, eltLen, i;
- char *eltName;
- Tcl_Obj *retVal;
- Tcl_Obj *split;
- Tcl_Obj *elt;
-
- /* Split has refCount zero */
- split = Tcl_FSSplitPath(pathPtr, &splen);
-
- /*
- * Modify the list of entries in place, by removing '.', and
- * removing '..' and the entry before -- unless that entry before
- * is the top-level entry, i.e. the name of a volume.
- */
- nplen = 0;
- for (i = 0; i < splen; i++) {
- Tcl_ListObjIndex(NULL, split, nplen, &elt);
- eltName = Tcl_GetStringFromObj(elt, &eltLen);
-
- if ((eltLen == 1) && (eltName[0] == '.')) {
- Tcl_ListObjReplace(NULL, split, nplen, 1, 0, NULL);
- } else if ((eltLen == 2)
- && (eltName[0] == '.') && (eltName[1] == '.')) {
- if (nplen > 1) {
- nplen--;
- Tcl_ListObjReplace(NULL, split, nplen, 2, 0, NULL);
- } else {
- Tcl_ListObjReplace(NULL, split, nplen, 1, 0, NULL);
- }
- } else {
- nplen++;
- }
- }
- if (nplen > 0) {
- ClientData clientData = NULL;
-
- retVal = Tcl_FSJoinPath(split, nplen);
- /*
- * Now we have an absolute path, with no '..', '.' sequences,
- * but it still may not be in 'unique' form, depending on the
- * platform. For instance, Unix is case-sensitive, so the
- * path is ok. Windows is case-insensitive, and also has the
- * weird 'longname/shortname' thing (e.g. C:/Program Files/ and
- * C:/Progra~1/ are equivalent). MacOS is case-insensitive.
- *
- * Virtual file systems which may be registered may have
- * other criteria for normalizing a path.
- */
- Tcl_IncrRefCount(retVal);
- TclFSNormalizeToUniquePath(interp, retVal, 0, &clientData);
- /*
- * Since we know it is a normalized path, we can
- * actually convert this object into an "path" object for
- * greater efficiency
- */
- TclFSMakePathFromNormalized(interp, retVal, clientData);
- if (clientDataPtr != NULL) {
- *clientDataPtr = clientData;
- }
- } else {
- /* Init to an empty string */
- retVal = Tcl_NewStringObj("",0);
- Tcl_IncrRefCount(retVal);
- }
- /*
- * We increment and then decrement the refCount of split to free
- * it. We do this right at the end, in case there are
- * optimisations in Tcl_FSJoinPath(split, nplen) above which would
- * let it make use of split more effectively if it has a refCount
- * of zero. Also we can't just decrement the ref count, in case
- * 'split' was actually returned by the join call above, in a
- * single-element optimisation when nplen == 1.
- */
- Tcl_IncrRefCount(split);
- Tcl_DecrRefCount(split);
-
- /* This has a refCount of 1 for the caller */
- return retVal;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
* TclFSNormalizeToUniquePath --
*
- * Description:
- * Takes a path specification containing no ../, ./ sequences,
- * and converts it into a unique path for the given platform.
- * On MacOS, Unix, this means the path must be free of
- * symbolic links/aliases, and on Windows it means we want the
- * long form, with that long form's case-dependence (which gives
- * us a unique, case-dependent path).
+ * Takes a path specification containing no ../, ./ sequences, and
+ * converts it into a unique path for the given platform. On Unix, this
+ * means the path must be free of symbolic links/aliases, and on Windows
+ * it means we want the long form, with that long form's case-dependence
+ * (which gives us a unique, case-dependent path).
*
* Results:
- * The pathPtr is modified in place. The return value is
- * the last byte offset which was recognised in the path
- * string.
+ * The pathPtr is modified in place. The return value is the last byte
+ * offset which was recognised in the path string.
*
* Side effects:
* None (beyond the memory allocation for the result).
*
* Special notes:
- * If the filesystem-specific normalizePathProcs can re-introduce
- * ../, ./ sequences into the path, then this function will
- * not return the correct result. This may be possible with
- * symbolic links on unix/macos.
- *
- * Important assumption: if startAt is non-zero, it must point
- * to a directory separator that we know exists and is already
- * normalized (so it is important not to point to the char just
- * after the separator).
+ * If the filesystem-specific normalizePathProcs can re-introduce ../, ./
+ * sequences into the path, then this function will not return the
+ * correct result. This may be possible with symbolic links on unix.
+ *
+ * Important assumption: if startAt is non-zero, it must point to a
+ * directory separator that we know exists and is already normalized (so
+ * it is important not to point to the char just after the separator).
+ *
*---------------------------------------------------------------------------
*/
+
int
-TclFSNormalizeToUniquePath(interp, pathPtr, startAt, clientDataPtr)
- Tcl_Interp *interp;
- Tcl_Obj *pathPtr;
- int startAt;
- ClientData *clientDataPtr;
+TclFSNormalizeToUniquePath(
+ Tcl_Interp *interp, /* Used for error messages. */
+ Tcl_Obj *pathPtr, /* The path to normalize in place */
+ int startAt, /* Start at this char-offset */
+ ClientData *clientDataPtr) /* If we generated a complete normalized path
+ * for a given filesystem, we can optionally
+ * return an fs-specific clientdata here. */
{
FilesystemRecord *fsRecPtr, *firstFsRecPtr;
/* Ignore this variable */
- (void)clientDataPtr;
-
+ (void) clientDataPtr;
+
/*
- * Call each of the "normalise path" functions in succession. This is
- * a special case, in which if we have a native filesystem handler,
- * we call it first. This is because the root of Tcl's filesystem
- * is always a native filesystem (i.e. '/' on unix is native).
+ * Call each of the "normalise path" functions in succession. This is a
+ * special case, in which if we have a native filesystem handler, we call
+ * it first. This is because the root of Tcl's filesystem is always a
+ * native filesystem (i.e. '/' on unix is native).
*/
firstFsRecPtr = FsGetFirstFilesystem();
fsRecPtr = firstFsRecPtr;
while (fsRecPtr != NULL) {
- if (fsRecPtr->fsPtr == &tclNativeFilesystem) {
+ if (fsRecPtr->fsPtr == &tclNativeFilesystem) {
Tcl_FSNormalizePathProc *proc = fsRecPtr->fsPtr->normalizePathProc;
if (proc != NULL) {
startAt = (*proc)(interp, pathPtr, startAt);
}
break;
- }
+ }
fsRecPtr = fsRecPtr->nextPtr;
}
-
- fsRecPtr = firstFsRecPtr;
+
+ fsRecPtr = firstFsRecPtr;
while (fsRecPtr != NULL) {
- /* Skip the native system next time through */
+ /*
+ * Skip the native system next time through.
+ */
+
if (fsRecPtr->fsPtr != &tclNativeFilesystem) {
Tcl_FSNormalizePathProc *proc = fsRecPtr->fsPtr->normalizePathProc;
if (proc != NULL) {
startAt = (*proc)(interp, pathPtr, startAt);
}
- /*
+
+ /*
* We could add an efficiency check like this:
- *
- * if (retVal == length-of(pathPtr)) {break;}
- *
+ * if (retVal == length-of(pathPtr)) {break;}
* but there's not much benefit.
*/
}
@@ -1507,10 +1464,40 @@ TclFSNormalizeToUniquePath(interp, pathPtr, startAt, clientDataPtr)
*
* TclGetOpenMode --
*
- * Description:
+ * This routine is an obsolete, limited version of TclGetOpenModeEx()
+ * below. It exists only to satisfy any extensions imprudently using it
+ * via Tcl's internal stubs table.
+ *
+ * Results:
+ * Same as TclGetOpenModeEx().
+ *
+ * Side effects:
+ * Same as TclGetOpenModeEx().
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclGetOpenMode(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting -
+ * may be NULL. */
+ const char *modeString, /* Mode string, e.g. "r+" or "RDONLY CREAT" */
+ int *seekFlagPtr) /* Set this to 1 if the caller should seek to
+ * EOF during the opening of the file. */
+{
+ int binary = 0;
+ return TclGetOpenModeEx(interp, modeString, seekFlagPtr, &binary);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclGetOpenModeEx --
+ *
* Computes a POSIX mode mask for opening a file, from a given string,
- * and also sets a flag to indicate whether the caller should seek to
- * EOF after opening the file.
+ * and also sets flags to indicate whether the caller should seek to EOF
+ * after opening the file, and whether the caller should configure the
+ * channel for binary data.
*
* Results:
* On success, returns mode to pass to "open". If an error occurs, the
@@ -1518,37 +1505,41 @@ TclFSNormalizeToUniquePath(interp, pathPtr, startAt, clientDataPtr)
* object to an error message.
*
* Side effects:
- * Sets the integer referenced by seekFlagPtr to 1 to tell the caller
- * to seek to EOF after opening the file.
+ * Sets the integer referenced by seekFlagPtr to 1 to tell the caller to
+ * seek to EOF after opening the file, or to 0 otherwise. Sets the
+ * integer referenced by binaryPtr to 1 to tell the caller to seek to
+ * configure the channel for binary data, or to 0 otherwise.
*
* Special note:
- * This code is based on a prototype implementation contributed
- * by Mark Diekhans.
+ * This code is based on a prototype implementation contributed by Mark
+ * Diekhans.
*
*---------------------------------------------------------------------------
*/
int
-TclGetOpenMode(interp, string, seekFlagPtr)
- Tcl_Interp *interp; /* Interpreter to use for error
- * reporting - may be NULL. */
- CONST char *string; /* Mode string, e.g. "r+" or
- * "RDONLY CREAT". */
- int *seekFlagPtr; /* Set this to 1 if the caller
- * should seek to EOF during the
- * opening of the file. */
+TclGetOpenModeEx(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting -
+ * may be NULL. */
+ const char *modeString, /* Mode string, e.g. "r+" or "RDONLY CREAT" */
+ int *seekFlagPtr, /* Set this to 1 if the caller should seek to
+ * EOF during the opening of the file. */
+ int *binaryPtr) /* Set this to 1 if the caller should
+ * configure the opened channel for binary
+ * operations */
{
int mode, modeArgc, c, i, gotRW;
- CONST char **modeArgv, *flag;
+ const char **modeArgv, *flag;
#define RW_MODES (O_RDONLY|O_WRONLY|O_RDWR)
/*
- * Check for the simpler fopen-like access modes (e.g. "r"). They
- * are distinguished from the POSIX access modes by the presence
- * of a lower-case first letter.
+ * Check for the simpler fopen-like access modes (e.g. "r"). They are
+ * distinguished from the POSIX access modes by the presence of a
+ * lower-case first letter.
*/
*seekFlagPtr = 0;
+ *binaryPtr = 0;
mode = 0;
/*
@@ -1556,66 +1547,82 @@ TclGetOpenMode(interp, string, seekFlagPtr)
* routines.
*/
- if (!(string[0] & 0x80)
- && islower(UCHAR(string[0]))) { /* INTL: ISO only. */
- switch (string[0]) {
- case 'r':
- mode = O_RDONLY;
- break;
- case 'w':
- mode = O_WRONLY|O_CREAT|O_TRUNC;
- break;
- case 'a':
- /* [Bug 680143].
- * Added O_APPEND for proper automatic
- * seek-to-end-on-write by the OS.
+ if (!(modeString[0] & 0x80)
+ && islower(UCHAR(modeString[0]))) { /* INTL: ISO only. */
+ switch (modeString[0]) {
+ case 'r':
+ mode = O_RDONLY;
+ break;
+ case 'w':
+ mode = O_WRONLY|O_CREAT|O_TRUNC;
+ break;
+ case 'a':
+ /*
+ * Added O_APPEND for proper automatic seek-to-end-on-write by the
+ * OS. [Bug 680143]
+ */
+
+ mode = O_WRONLY|O_CREAT|O_APPEND;
+ *seekFlagPtr = 1;
+ break;
+ default:
+ goto error;
+ }
+ i=1;
+ while (i<3 && modeString[i]) {
+ if (modeString[i] == modeString[i-1]) {
+ goto error;
+ }
+ switch (modeString[i++]) {
+ case '+':
+ /*
+ * Must remove the O_APPEND flag so that the seek command
+ * works. [Bug 1773127]
*/
- mode = O_WRONLY|O_CREAT|O_APPEND;
- *seekFlagPtr = 1;
+
+ mode &= ~(O_RDONLY|O_WRONLY|O_APPEND);
+ mode |= O_RDWR;
+ break;
+ case 'b':
+ *binaryPtr = 1;
break;
default:
- error:
- if (interp != (Tcl_Interp *) NULL) {
- Tcl_AppendResult(interp,
- "illegal access mode \"", string, "\"",
- (char *) NULL);
- }
- return -1;
- }
- if (string[1] == '+') {
- /*
- * Must remove the O_APPEND flag so that the seek command
- * works. [Bug 1773127]
- */
- mode &= ~(O_RDONLY|O_WRONLY|O_APPEND);
- mode |= O_RDWR;
- if (string[2] != 0) {
goto error;
}
- } else if (string[1] != 0) {
+ }
+ if (modeString[i] != 0) {
goto error;
}
- return mode;
+ return mode;
+
+ error:
+ *seekFlagPtr = 0;
+ *binaryPtr = 0;
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "illegal access mode \"", modeString,
+ "\"", NULL);
+ }
+ return -1;
}
/*
- * The access modes are specified using a list of POSIX modes
- * such as O_CREAT.
+ * The access modes are specified using a list of POSIX modes such as
+ * O_CREAT.
*
- * IMPORTANT NOTE: We rely on Tcl_SplitList working correctly when
- * a NULL interpreter is passed in.
+ * IMPORTANT NOTE: We rely on Tcl_SplitList working correctly when a NULL
+ * interpreter is passed in.
*/
- if (Tcl_SplitList(interp, string, &modeArgc, &modeArgv) != TCL_OK) {
- if (interp != (Tcl_Interp *) NULL) {
- Tcl_AddErrorInfo(interp,
- "\n while processing open access modes \"");
- Tcl_AddErrorInfo(interp, string);
- Tcl_AddErrorInfo(interp, "\"");
- }
- return -1;
+ if (Tcl_SplitList(interp, modeString, &modeArgc, &modeArgv) != TCL_OK) {
+ if (interp != NULL) {
+ Tcl_AddErrorInfo(interp,
+ "\n while processing open access modes \"");
+ Tcl_AddErrorInfo(interp, modeString);
+ Tcl_AddErrorInfo(interp, "\"");
+ }
+ return -1;
}
-
+
gotRW = 0;
for (i = 0; i < modeArgc; i++) {
flag = modeArgv[i];
@@ -1631,88 +1638,106 @@ TclGetOpenMode(interp, string, seekFlagPtr)
gotRW = 1;
} else if ((c == 'A') && (strcmp(flag, "APPEND") == 0)) {
mode |= O_APPEND;
- *seekFlagPtr = 1;
+ *seekFlagPtr = 1;
} else if ((c == 'C') && (strcmp(flag, "CREAT") == 0)) {
mode |= O_CREAT;
} else if ((c == 'E') && (strcmp(flag, "EXCL") == 0)) {
mode |= O_EXCL;
+
} else if ((c == 'N') && (strcmp(flag, "NOCTTY") == 0)) {
#ifdef O_NOCTTY
mode |= O_NOCTTY;
#else
- if (interp != (Tcl_Interp *) NULL) {
- Tcl_AppendResult(interp, "access mode \"", flag,
- "\" not supported by this system", (char *) NULL);
- }
- ckfree((char *) modeArgv);
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "access mode \"", flag,
+ "\" not supported by this system", NULL);
+ }
+ ckfree((char *) modeArgv);
return -1;
#endif
+
} else if ((c == 'N') && (strcmp(flag, "NONBLOCK") == 0)) {
-#if defined(O_NDELAY) || defined(O_NONBLOCK)
-# ifdef O_NONBLOCK
+#ifdef O_NONBLOCK
mode |= O_NONBLOCK;
-# else
- mode |= O_NDELAY;
-# endif
#else
- if (interp != (Tcl_Interp *) NULL) {
- Tcl_AppendResult(interp, "access mode \"", flag,
- "\" not supported by this system", (char *) NULL);
- }
- ckfree((char *) modeArgv);
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "access mode \"", flag,
+ "\" not supported by this system", NULL);
+ }
+ ckfree((char *) modeArgv);
return -1;
#endif
+
} else if ((c == 'T') && (strcmp(flag, "TRUNC") == 0)) {
mode |= O_TRUNC;
+ } else if ((c == 'B') && (strcmp(flag, "BINARY") == 0)) {
+ *binaryPtr = 1;
} else {
- if (interp != (Tcl_Interp *) NULL) {
- Tcl_AppendResult(interp, "invalid access mode \"", flag,
- "\": must be RDONLY, WRONLY, RDWR, APPEND, CREAT",
- " EXCL, NOCTTY, NONBLOCK, or TRUNC", (char *) NULL);
- }
+
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "invalid access mode \"", flag,
+ "\": must be RDONLY, WRONLY, RDWR, APPEND, BINARY, "
+ "CREAT, EXCL, NOCTTY, NONBLOCK, or TRUNC", NULL);
+ }
ckfree((char *) modeArgv);
return -1;
}
}
+
ckfree((char *) modeArgv);
+
if (!gotRW) {
- if (interp != (Tcl_Interp *) NULL) {
- Tcl_AppendResult(interp, "access mode must include either",
- " RDONLY, WRONLY, or RDWR", (char *) NULL);
- }
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "access mode must include either"
+ " RDONLY, WRONLY, or RDWR", NULL);
+ }
return -1;
}
return mode;
}
/*
+ * Tcl_FSEvalFile is Tcl_FSEvalFileEx without encoding argument.
+ */
+
+int
+Tcl_FSEvalFile(
+ Tcl_Interp *interp, /* Interpreter in which to process file. */
+ Tcl_Obj *pathPtr) /* Path of file to process. Tilde-substitution
+ * will be performed on this name. */
+{
+ return Tcl_FSEvalFileEx(interp, pathPtr, NULL);
+}
+
+/*
*----------------------------------------------------------------------
*
- * Tcl_FSEvalFile --
+ * Tcl_FSEvalFileEx --
*
- * Read in a file and process the entire file as one gigantic
- * Tcl command.
+ * Read in a file and process the entire file as one gigantic Tcl
+ * command.
*
* Results:
- * A standard Tcl result, which is either the result of executing
- * the file or an error indicating why the file couldn't be read.
+ * A standard Tcl result, which is either the result of executing the
+ * file or an error indicating why the file couldn't be read.
*
* Side effects:
- * Depends on the commands in the file. During the evaluation
- * of the contents of the file, iPtr->scriptFile is made to
- * point to pathPtr (the old value is cached and replaced when
- * this function returns).
+ * Depends on the commands in the file. During the evaluation of the
+ * contents of the file, iPtr->scriptFile is made to point to pathPtr
+ * (the old value is cached and replaced when this function returns).
*
*----------------------------------------------------------------------
*/
int
-Tcl_FSEvalFile(interp, pathPtr)
- Tcl_Interp *interp; /* Interpreter in which to process file. */
- Tcl_Obj *pathPtr; /* Path of file to process. Tilde-substitution
+Tcl_FSEvalFileEx(
+ Tcl_Interp *interp, /* Interpreter in which to process file. */
+ Tcl_Obj *pathPtr, /* Path of file to process. Tilde-substitution
* will be performed on this name. */
+ const char *encodingName) /* If non-NULL, then use this encoding for the
+ * file. NULL means use the system encoding. */
{
- int result, length;
+ int length, result = TCL_ERROR;
Tcl_StatBuf statBuf;
Tcl_Obj *oldScriptFile;
Interp *iPtr;
@@ -1721,43 +1746,54 @@ Tcl_FSEvalFile(interp, pathPtr)
Tcl_Obj *objPtr;
if (Tcl_FSGetNormalizedPath(interp, pathPtr) == NULL) {
- return TCL_ERROR;
+ return result;
}
- result = TCL_ERROR;
- objPtr = Tcl_NewObj();
- Tcl_IncrRefCount(objPtr);
-
if (Tcl_FSStat(pathPtr, &statBuf) == -1) {
- Tcl_SetErrno(errno);
- Tcl_AppendResult(interp, "couldn't read file \"",
- Tcl_GetString(pathPtr),
- "\": ", Tcl_PosixError(interp), (char *) NULL);
- goto end;
+ Tcl_SetErrno(errno);
+ Tcl_AppendResult(interp, "couldn't read file \"",
+ Tcl_GetString(pathPtr), "\": ", Tcl_PosixError(interp), NULL);
+ return result;
}
chan = Tcl_FSOpenFileChannel(interp, pathPtr, "r", 0644);
if (chan == (Tcl_Channel) NULL) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "couldn't read file \"",
- Tcl_GetString(pathPtr),
- "\": ", Tcl_PosixError(interp), (char *) NULL);
- goto end;
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "couldn't read file \"",
+ Tcl_GetString(pathPtr), "\": ", Tcl_PosixError(interp), NULL);
+ return result;
}
+
/*
- * The eofchar is \32 (^Z). This is the usual on Windows, but we
- * effect this cross-platform to allow for scripted documents.
- * [Bug: 2040]
+ * The eofchar is \32 (^Z). This is the usual on Windows, but we effect
+ * this cross-platform to allow for scripted documents. [Bug: 2040]
*/
+
Tcl_SetChannelOption(interp, chan, "-eofchar", "\32");
+
+ /*
+ * If the encoding is specified, set it for the channel. Else don't touch
+ * it (and use the system encoding) Report error on unknown encoding.
+ */
+
+ if (encodingName != NULL) {
+ if (Tcl_SetChannelOption(interp, chan, "-encoding", encodingName)
+ != TCL_OK) {
+ Tcl_Close(interp,chan);
+ return result;
+ }
+ }
+
+ objPtr = Tcl_NewObj();
+ Tcl_IncrRefCount(objPtr);
if (Tcl_ReadChars(chan, objPtr, -1, 0) < 0) {
- Tcl_Close(interp, chan);
- Tcl_AppendResult(interp, "couldn't read file \"",
- Tcl_GetString(pathPtr),
- "\": ", Tcl_PosixError(interp), (char *) NULL);
+ Tcl_Close(interp, chan);
+ Tcl_AppendResult(interp, "couldn't read file \"",
+ Tcl_GetString(pathPtr), "\": ", Tcl_PosixError(interp), NULL);
goto end;
}
+
if (Tcl_Close(interp, chan) != TCL_OK) {
- goto end;
+ goto end;
}
iPtr = (Interp *) interp;
@@ -1765,18 +1801,17 @@ Tcl_FSEvalFile(interp, pathPtr)
iPtr->scriptFile = pathPtr;
Tcl_IncrRefCount(iPtr->scriptFile);
string = Tcl_GetStringFromObj(objPtr, &length);
-
-#ifdef TCL_TIP280
/* TIP #280 Force the evaluator to open a frame for a sourced
* file. */
iPtr->evalFlags |= TCL_EVAL_FILE;
-#endif
result = Tcl_EvalEx(interp, string, length, 0);
- /*
+
+ /*
* Now we have to be careful; the script may have changed the
- * iPtr->scriptFile value, so we must reset it without
- * assuming it still points to 'pathPtr'.
+ * iPtr->scriptFile value, so we must reset it without assuming it still
+ * points to 'pathPtr'.
*/
+
if (iPtr->scriptFile != NULL) {
Tcl_DecrRefCount(iPtr->scriptFile);
}
@@ -1785,18 +1820,21 @@ Tcl_FSEvalFile(interp, pathPtr)
if (result == TCL_RETURN) {
result = TclUpdateReturnInfo(iPtr);
} else if (result == TCL_ERROR) {
- char msg[200 + TCL_INTEGER_SPACE];
-
/*
* Record information telling where the error occurred.
*/
- sprintf(msg, "\n (file \"%.150s\" line %d)", Tcl_GetString(pathPtr),
- interp->errorLine);
- Tcl_AddErrorInfo(interp, msg);
+ const char *pathString = Tcl_GetStringFromObj(pathPtr, &length);
+ int limit = 150;
+ int overflow = (length > limit);
+
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (file \"%.*s%s\" line %d)",
+ (overflow ? limit : length), pathString,
+ (overflow ? "..." : ""), interp->errorLine));
}
- end:
+ end:
Tcl_DecrRefCount(objPtr);
return result;
}
@@ -1807,21 +1845,21 @@ Tcl_FSEvalFile(interp, pathPtr)
* Tcl_GetErrno --
*
* Gets the current value of the Tcl error code variable. This is
- * currently the global variable "errno" but could in the future
- * change to something else.
+ * currently the global variable "errno" but could in the future change
+ * to something else.
*
* Results:
* The value of the Tcl error code variable.
*
* Side effects:
- * None. Note that the value of the Tcl error code variable is
- * UNDEFINED if a call to Tcl_SetErrno did not precede this call.
+ * None. Note that the value of the Tcl error code variable is UNDEFINED
+ * if a call to Tcl_SetErrno did not precede this call.
*
*----------------------------------------------------------------------
*/
int
-Tcl_GetErrno()
+Tcl_GetErrno(void)
{
return errno;
}
@@ -1843,8 +1881,8 @@ Tcl_GetErrno()
*/
void
-Tcl_SetErrno(err)
- int err; /* The new value. */
+Tcl_SetErrno(
+ int err) /* The new value. */
{
errno = err;
}
@@ -1854,32 +1892,31 @@ Tcl_SetErrno(err)
*
* Tcl_PosixError --
*
- * This procedure is typically called after UNIX kernel calls
- * return errors. It stores machine-readable information about
- * the error in $errorCode returns an information string for
- * the caller's use.
+ * This function is typically called after UNIX kernel calls return
+ * errors. It stores machine-readable information about the error in
+ * errorCode field of interp and returns an information string for the
+ * caller's use.
*
* Results:
- * The return value is a human-readable string describing the
- * error.
+ * The return value is a human-readable string describing the error.
*
* Side effects:
- * The global variable $errorCode is reset.
+ * The errorCode field of the interp is set.
*
*----------------------------------------------------------------------
*/
-CONST char *
-Tcl_PosixError(interp)
- Tcl_Interp *interp; /* Interpreter whose $errorCode variable
- * is to be changed. */
+const char *
+Tcl_PosixError(
+ Tcl_Interp *interp) /* Interpreter whose errorCode field is to be
+ * set. */
{
- CONST char *id, *msg;
+ const char *id, *msg;
msg = Tcl_ErrnoMsg(errno);
id = Tcl_ErrnoId();
if (interp) {
- Tcl_SetErrorCode(interp, "POSIX", id, msg, (char *) NULL);
+ Tcl_SetErrorCode(interp, "POSIX", id, msg, NULL);
}
return msg;
}
@@ -1889,37 +1926,37 @@ Tcl_PosixError(interp)
*
* Tcl_FSStat --
*
- * This procedure replaces the library version of stat and lsat.
- *
- * The appropriate function for the filesystem to which pathPtr
- * belongs will be called.
+ * This function replaces the library version of stat and lsat.
+ *
+ * The appropriate function for the filesystem to which pathPtr belongs
+ * will be called.
*
* Results:
- * See stat documentation.
+ * See stat documentation.
*
* Side effects:
- * See stat documentation.
+ * See stat documentation.
*
*----------------------------------------------------------------------
*/
int
-Tcl_FSStat(pathPtr, buf)
- Tcl_Obj *pathPtr; /* Path of file to stat (in current CP). */
- Tcl_StatBuf *buf; /* Filled with results of stat call. */
+Tcl_FSStat(
+ Tcl_Obj *pathPtr, /* Path of file to stat (in current CP). */
+ Tcl_StatBuf *buf) /* Filled with results of stat call. */
{
- Tcl_Filesystem *fsPtr;
+ const Tcl_Filesystem *fsPtr;
#ifdef USE_OBSOLETE_FS_HOOKS
- Tcl_StatBuf oldStyleStatBuffer;
+ struct stat oldStyleStatBuffer;
int retVal = -1;
/*
- * Call each of the "stat" function in succession. A non-return
- * value of -1 indicates the particular function has succeeded.
+ * Call each of the "stat" function in succession. A non-return value of
+ * -1 indicates the particular function has succeeded.
*/
Tcl_MutexLock(&obsoleteFsHookMutex);
-
+
if (statProcList != NULL) {
StatProc *statProcPtr;
char *path;
@@ -1939,13 +1976,14 @@ Tcl_FSStat(pathPtr, buf)
Tcl_DecrRefCount(transPtr);
}
}
-
+
Tcl_MutexUnlock(&obsoleteFsHookMutex);
if (retVal != -1) {
/*
- * Note that EOVERFLOW is not a problem here, and these
- * assignments should all be widening (if not identity.)
+ * Note that EOVERFLOW is not a problem here, and these assignments
+ * should all be widening (if not identity.)
*/
+
buf->st_mode = oldStyleStatBuffer.st_mode;
buf->st_ino = oldStyleStatBuffer.st_ino;
buf->st_dev = oldStyleStatBuffer.st_dev;
@@ -1957,13 +1995,16 @@ Tcl_FSStat(pathPtr, buf)
buf->st_atime = oldStyleStatBuffer.st_atime;
buf->st_mtime = oldStyleStatBuffer.st_mtime;
buf->st_ctime = oldStyleStatBuffer.st_ctime;
-#ifdef HAVE_ST_BLOCKS
+#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
buf->st_blksize = oldStyleStatBuffer.st_blksize;
+#endif
+#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
buf->st_blocks = Tcl_LongAsWide(oldStyleStatBuffer.st_blocks);
#endif
- return retVal;
+ return retVal;
}
#endif /* USE_OBSOLETE_FS_HOOKS */
+
fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
if (fsPtr != NULL) {
Tcl_FSStatProc *proc = fsPtr->statProc;
@@ -1980,27 +2021,26 @@ Tcl_FSStat(pathPtr, buf)
*
* Tcl_FSLstat --
*
- * This procedure replaces the library version of lstat.
- * The appropriate function for the filesystem to which pathPtr
- * belongs will be called. If no 'lstat' function is listed,
- * but a 'stat' function is, then Tcl will fall back on the
- * stat function.
+ * This function replaces the library version of lstat. The appropriate
+ * function for the filesystem to which pathPtr belongs will be called.
+ * If no 'lstat' function is listed, but a 'stat' function is, then Tcl
+ * will fall back on the stat function.
*
* Results:
- * See lstat documentation.
+ * See lstat documentation.
*
* Side effects:
- * See lstat documentation.
+ * See lstat documentation.
*
*----------------------------------------------------------------------
*/
int
-Tcl_FSLstat(pathPtr, buf)
- Tcl_Obj *pathPtr; /* Path of file to stat (in current CP). */
- Tcl_StatBuf *buf; /* Filled with results of stat call. */
+Tcl_FSLstat(
+ Tcl_Obj *pathPtr, /* Path of file to stat (in current CP). */
+ Tcl_StatBuf *buf) /* Filled with results of stat call. */
{
- Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
+ const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
if (fsPtr != NULL) {
Tcl_FSLstatProc *proc = fsPtr->lstatProc;
if (proc != NULL) {
@@ -2021,31 +2061,30 @@ Tcl_FSLstat(pathPtr, buf)
*
* Tcl_FSAccess --
*
- * This procedure replaces the library version of access.
- * The appropriate function for the filesystem to which pathPtr
- * belongs will be called.
+ * This function replaces the library version of access. The appropriate
+ * function for the filesystem to which pathPtr belongs will be called.
*
* Results:
- * See access documentation.
+ * See access documentation.
*
* Side effects:
- * See access documentation.
+ * See access documentation.
*
*----------------------------------------------------------------------
*/
int
-Tcl_FSAccess(pathPtr, mode)
- Tcl_Obj *pathPtr; /* Path of file to access (in current CP). */
- int mode; /* Permission setting. */
+Tcl_FSAccess(
+ Tcl_Obj *pathPtr, /* Path of file to access (in current CP). */
+ int mode) /* Permission setting. */
{
- Tcl_Filesystem *fsPtr;
+ const Tcl_Filesystem *fsPtr;
#ifdef USE_OBSOLETE_FS_HOOKS
int retVal = -1;
/*
- * Call each of the "access" function in succession. A non-return
- * value of -1 indicates the particular function has succeeded.
+ * Call each of the "access" function in succession. A non-return value of
+ * -1 indicates the particular function has succeeded.
*/
Tcl_MutexLock(&obsoleteFsHookMutex);
@@ -2069,12 +2108,13 @@ Tcl_FSAccess(pathPtr, mode)
Tcl_DecrRefCount(transPtr);
}
}
-
+
Tcl_MutexUnlock(&obsoleteFsHookMutex);
if (retVal != -1) {
return retVal;
}
#endif /* USE_OBSOLETE_FS_HOOKS */
+
fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
if (fsPtr != NULL) {
Tcl_FSAccessProc *proc = fsPtr->accessProc;
@@ -2092,38 +2132,36 @@ Tcl_FSAccess(pathPtr, mode)
*
* Tcl_FSOpenFileChannel --
*
- * The appropriate function for the filesystem to which pathPtr
- * belongs will be called.
+ * The appropriate function for the filesystem to which pathPtr belongs
+ * will be called.
*
* Results:
* The new channel or NULL, if the named file could not be opened.
*
* Side effects:
- * May open the channel and may cause creation of a file on the
- * file system.
+ * May open the channel and may cause creation of a file on the file
+ * system.
*
*----------------------------------------------------------------------
*/
-
+
Tcl_Channel
-Tcl_FSOpenFileChannel(interp, pathPtr, modeString, permissions)
- Tcl_Interp *interp; /* Interpreter for error reporting;
- * can be NULL. */
- Tcl_Obj *pathPtr; /* Name of file to open. */
- CONST char *modeString; /* A list of POSIX open modes or
- * a string such as "rw". */
- int permissions; /* If the open involves creating a
- * file, with what modes to create
- * it? */
+Tcl_FSOpenFileChannel(
+ Tcl_Interp *interp, /* Interpreter for error reporting; can be
+ * NULL. */
+ Tcl_Obj *pathPtr, /* Name of file to open. */
+ const char *modeString, /* A list of POSIX open modes or a string such
+ * as "rw". */
+ int permissions) /* If the open involves creating a file, with
+ * what modes to create it? */
{
- Tcl_Filesystem *fsPtr;
-#ifdef USE_OBSOLETE_FS_HOOKS
+ const Tcl_Filesystem *fsPtr;
Tcl_Channel retVal = NULL;
+#ifdef USE_OBSOLETE_FS_HOOKS
/*
- * Call each of the "Tcl_OpenFileChannel" functions in succession.
- * A non-NULL return value indicates the particular function has
- * succeeded.
+ * Call each of the "Tcl_OpenFileChannel" functions in succession. A
+ * non-NULL return value indicates the particular function has succeeded.
*/
Tcl_MutexLock(&obsoleteFsHookMutex);
@@ -2131,7 +2169,7 @@ Tcl_FSOpenFileChannel(interp, pathPtr, modeString, permissions)
OpenFileChannelProc *openFileChannelProcPtr;
char *path;
Tcl_Obj *transPtr = Tcl_FSGetTranslatedPath(interp, pathPtr);
-
+
if (transPtr == NULL) {
path = NULL;
} else {
@@ -2139,10 +2177,10 @@ Tcl_FSOpenFileChannel(interp, pathPtr, modeString, permissions)
}
openFileChannelProcPtr = openFileChannelProcList;
-
+
while ((retVal == NULL) && (openFileChannelProcPtr != NULL)) {
retVal = (*openFileChannelProcPtr->proc)(interp, path,
- modeString, permissions);
+ modeString, permissions);
openFileChannelProcPtr = openFileChannelProcPtr->nextPtr;
}
if (transPtr != NULL) {
@@ -2154,49 +2192,70 @@ Tcl_FSOpenFileChannel(interp, pathPtr, modeString, permissions)
return retVal;
}
#endif /* USE_OBSOLETE_FS_HOOKS */
-
- /*
- * We need this just to ensure we return the correct error messages
- * under some circumstances.
+
+ /*
+ * We need this just to ensure we return the correct error messages under
+ * some circumstances.
*/
+
if (Tcl_FSGetNormalizedPath(interp, pathPtr) == NULL) {
- return NULL;
+ return NULL;
}
-
+
fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
if (fsPtr != NULL) {
Tcl_FSOpenFileChannelProc *proc = fsPtr->openFileChannelProc;
if (proc != NULL) {
- int mode, seekFlag;
- mode = TclGetOpenMode(interp, modeString, &seekFlag);
+ int mode, seekFlag, binary;
+
+ /*
+ * Parse the mode, picking up whether we want to seek to start
+ * with and/or set the channel automatically into binary mode.
+ */
+
+ mode = TclGetOpenModeEx(interp, modeString, &seekFlag, &binary);
if (mode == -1) {
- return NULL;
+ return NULL;
}
+
+ /*
+ * Do the actual open() call.
+ */
+
retVal = (*proc)(interp, pathPtr, mode, permissions);
- if (retVal != NULL) {
- if (seekFlag) {
- if (Tcl_Seek(retVal, (Tcl_WideInt)0,
- SEEK_END) < (Tcl_WideInt)0) {
- if (interp != (Tcl_Interp *) NULL) {
- Tcl_AppendResult(interp,
- "could not seek to end of file while opening \"",
- Tcl_GetString(pathPtr), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
- }
- Tcl_Close(NULL, retVal);
- return NULL;
- }
+ if (retVal == NULL) {
+ return NULL;
+ }
+
+ /*
+ * Apply appropriate flags parsed out above.
+ */
+
+ if (seekFlag && Tcl_Seek(retVal, (Tcl_WideInt)0,
+ SEEK_END) < (Tcl_WideInt)0) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "could not seek to end "
+ "of file while opening \"", Tcl_GetString(pathPtr),
+ "\": ", Tcl_PosixError(interp), NULL);
}
+ Tcl_Close(NULL, retVal);
+ return NULL;
+ }
+ if (binary) {
+ Tcl_SetChannelOption(interp, retVal, "-translation", "binary");
}
return retVal;
}
}
- /* File doesn't belong to any filesystem that can open it */
+
+ /*
+ * File doesn't belong to any filesystem that can open it.
+ */
+
Tcl_SetErrno(ENOENT);
if (interp != NULL) {
- Tcl_AppendResult(interp, "couldn't open \"",
- Tcl_GetString(pathPtr), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ Tcl_AppendResult(interp, "couldn't open \"", Tcl_GetString(pathPtr),
+ "\": ", Tcl_PosixError(interp), NULL);
}
return NULL;
}
@@ -2206,26 +2265,25 @@ Tcl_FSOpenFileChannel(interp, pathPtr, modeString, permissions)
*
* Tcl_FSUtime --
*
- * This procedure replaces the library version of utime.
- * The appropriate function for the filesystem to which pathPtr
- * belongs will be called.
+ * This function replaces the library version of utime. The appropriate
+ * function for the filesystem to which pathPtr belongs will be called.
*
* Results:
- * See utime documentation.
+ * See utime documentation.
*
* Side effects:
- * See utime documentation.
+ * See utime documentation.
*
*----------------------------------------------------------------------
*/
-int
-Tcl_FSUtime (pathPtr, tval)
- Tcl_Obj *pathPtr; /* File to change access/modification times */
- struct utimbuf *tval; /* Structure containing access/modification
- * times to use. Should not be modified. */
+int
+Tcl_FSUtime(
+ Tcl_Obj *pathPtr, /* File to change access/modification times */
+ struct utimbuf *tval) /* Structure containing access/modification
+ * times to use. Should not be modified. */
{
- Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
+ const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
if (fsPtr != NULL) {
Tcl_FSUtimeProc *proc = fsPtr->utimeProc;
if (proc != NULL) {
@@ -2240,25 +2298,25 @@ Tcl_FSUtime (pathPtr, tval)
*
* NativeFileAttrStrings --
*
- * This procedure implements the platform dependent 'file
- * attributes' subcommand, for the native filesystem, for listing
- * the set of possible attribute strings. This function is part
- * of Tcl's native filesystem support, and is placed here because
- * it is shared by Unix, MacOS and Windows code.
+ * This function implements the platform dependent 'file attributes'
+ * subcommand, for the native filesystem, for listing the set of possible
+ * attribute strings. This function is part of Tcl's native filesystem
+ * support, and is placed here because it is shared by Unix and Windows
+ * code.
*
* Results:
- * An array of strings
+ * An array of strings
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
-static CONST char**
-NativeFileAttrStrings(pathPtr, objPtrRef)
- Tcl_Obj *pathPtr;
- Tcl_Obj** objPtrRef;
+static const char **
+NativeFileAttrStrings(
+ Tcl_Obj *pathPtr,
+ Tcl_Obj **objPtrRef)
{
return tclpFileAttrStrings;
}
@@ -2268,34 +2326,32 @@ NativeFileAttrStrings(pathPtr, objPtrRef)
*
* NativeFileAttrsGet --
*
- * This procedure implements the platform dependent
- * 'file attributes' subcommand, for the native
- * filesystem, for 'get' operations. This function is part
- * of Tcl's native filesystem support, and is placed here
- * because it is shared by Unix, MacOS and Windows code.
+ * This function implements the platform dependent 'file attributes'
+ * subcommand, for the native filesystem, for 'get' operations. This
+ * function is part of Tcl's native filesystem support, and is placed
+ * here because it is shared by Unix and Windows code.
*
* Results:
- * Standard Tcl return code. The object placed in objPtrRef
- * (if TCL_OK was returned) is likely to have a refCount of zero.
- * Either way we must either store it somewhere (e.g. the Tcl
- * result), or Incr/Decr its refCount to ensure it is properly
- * freed.
+ * Standard Tcl return code. The object placed in objPtrRef (if TCL_OK
+ * was returned) is likely to have a refCount of zero. Either way we must
+ * either store it somewhere (e.g. the Tcl result), or Incr/Decr its
+ * refCount to ensure it is properly freed.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
static int
-NativeFileAttrsGet(interp, index, pathPtr, objPtrRef)
- Tcl_Interp *interp; /* The interpreter for error reporting. */
- int index; /* index of the attribute command. */
- Tcl_Obj *pathPtr; /* path of file we are operating on. */
- Tcl_Obj **objPtrRef; /* for output. */
+NativeFileAttrsGet(
+ Tcl_Interp *interp, /* The interpreter for error reporting. */
+ int index, /* index of the attribute command. */
+ Tcl_Obj *pathPtr, /* path of file we are operating on. */
+ Tcl_Obj **objPtrRef) /* for output. */
{
- return (*tclpFileAttrProcs[index].getProc)(interp, index,
- pathPtr, objPtrRef);
+ return (*tclpFileAttrProcs[index].getProc)(interp, index, pathPtr,
+ objPtrRef);
}
/*
@@ -2303,30 +2359,28 @@ NativeFileAttrsGet(interp, index, pathPtr, objPtrRef)
*
* NativeFileAttrsSet --
*
- * This procedure implements the platform dependent
- * 'file attributes' subcommand, for the native
- * filesystem, for 'set' operations. This function is part
- * of Tcl's native filesystem support, and is placed here
- * because it is shared by Unix, MacOS and Windows code.
+ * This function implements the platform dependent 'file attributes'
+ * subcommand, for the native filesystem, for 'set' operations. This
+ * function is part of Tcl's native filesystem support, and is placed
+ * here because it is shared by Unix and Windows code.
*
* Results:
- * Standard Tcl return code.
+ * Standard Tcl return code.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
static int
-NativeFileAttrsSet(interp, index, pathPtr, objPtr)
- Tcl_Interp *interp; /* The interpreter for error reporting. */
- int index; /* index of the attribute command. */
- Tcl_Obj *pathPtr; /* path of file we are operating on. */
- Tcl_Obj *objPtr; /* set to this value. */
+NativeFileAttrsSet(
+ Tcl_Interp *interp, /* The interpreter for error reporting. */
+ int index, /* index of the attribute command. */
+ Tcl_Obj *pathPtr, /* path of file we are operating on. */
+ Tcl_Obj *objPtr) /* set to this value. */
{
- return (*tclpFileAttrProcs[index].setProc)(interp, index,
- pathPtr, objPtr);
+ return (*tclpFileAttrProcs[index].setProc)(interp, index, pathPtr, objPtr);
}
/*
@@ -2334,32 +2388,32 @@ NativeFileAttrsSet(interp, index, pathPtr, objPtr)
*
* Tcl_FSFileAttrStrings --
*
- * This procedure implements part of the hookable 'file
- * attributes' subcommand. The appropriate function for the
- * filesystem to which pathPtr belongs will be called.
+ * This function implements part of the hookable 'file attributes'
+ * subcommand. The appropriate function for the filesystem to which
+ * pathPtr belongs will be called.
*
* Results:
- * The called procedure may either return an array of strings,
- * or may instead return NULL and place a Tcl list into the
- * given objPtrRef. Tcl will take that list and first increment
- * its refCount before using it. On completion of that use, Tcl
- * will decrement its refCount. Hence if the list should be
- * disposed of by Tcl when done, it should have a refCount of zero,
- * and if the list should not be disposed of, the filesystem
- * should ensure it retains a refCount on the object.
+ * The called function may either return an array of strings, or may
+ * instead return NULL and place a Tcl list into the given objPtrRef.
+ * Tcl will take that list and first increment its refCount before using
+ * it. On completion of that use, Tcl will decrement its refCount. Hence
+ * if the list should be disposed of by Tcl when done, it should have a
+ * refCount of zero, and if the list should not be disposed of, the
+ * filesystem should ensure it retains a refCount on the object.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
-CONST char **
-Tcl_FSFileAttrStrings(pathPtr, objPtrRef)
- Tcl_Obj* pathPtr;
- Tcl_Obj** objPtrRef;
+const char **
+Tcl_FSFileAttrStrings(
+ Tcl_Obj *pathPtr,
+ Tcl_Obj **objPtrRef)
{
- Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
+ const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
+
if (fsPtr != NULL) {
Tcl_FSFileAttrStringsProc *proc = fsPtr->fileAttrStringsProc;
if (proc != NULL) {
@@ -2373,34 +2427,110 @@ Tcl_FSFileAttrStrings(pathPtr, objPtrRef)
/*
*----------------------------------------------------------------------
*
- * Tcl_FSFileAttrsGet --
+ * TclFSFileAttrIndex --
*
- * This procedure implements read access for the hookable 'file
- * attributes' subcommand. The appropriate function for the
- * filesystem to which pathPtr belongs will be called.
+ * Helper function for converting an attribute name to an index into the
+ * attribute table.
*
* Results:
- * Standard Tcl return code. The object placed in objPtrRef
- * (if TCL_OK was returned) is likely to have a refCount of zero.
- * Either way we must either store it somewhere (e.g. the Tcl
- * result), or Incr/Decr its refCount to ensure it is properly
- * freed.
+ * Tcl result code, index written to *indexPtr on result==TCL_OK
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclFSFileAttrIndex(
+ Tcl_Obj *pathPtr, /* File whose attributes are to be indexed
+ * into. */
+ const char *attributeName, /* The attribute being looked for. */
+ int *indexPtr) /* Where to write the found index. */
+{
+ Tcl_Obj *listObj = NULL;
+ const char **attrTable;
+
+ /*
+ * Get the attribute table for the file.
+ */
+
+ attrTable = Tcl_FSFileAttrStrings(pathPtr, &listObj);
+ if (listObj != NULL) {
+ Tcl_IncrRefCount(listObj);
+ }
+
+ if (attrTable != NULL) {
+ /*
+ * It's a constant attribute table, so use T_GIFO.
+ */
+
+ Tcl_Obj *tmpObj = Tcl_NewStringObj(attributeName, -1);
+ int result;
+ result = Tcl_GetIndexFromObj(NULL, tmpObj, attrTable, NULL, TCL_EXACT,
+ indexPtr);
+ TclDecrRefCount(tmpObj);
+ if (listObj != NULL) {
+ TclDecrRefCount(listObj);
+ }
+ return result;
+ } else if (listObj != NULL) {
+ /*
+ * It's a non-constant attribute list, so do a literal search.
+ */
+
+ int i, objc;
+ Tcl_Obj **objv;
+
+ if (Tcl_ListObjGetElements(NULL, listObj, &objc, &objv) != TCL_OK) {
+ TclDecrRefCount(listObj);
+ return TCL_ERROR;
+ }
+ for (i=0 ; i<objc ; i++) {
+ if (!strcmp(attributeName, TclGetString(objv[i]))) {
+ TclDecrRefCount(listObj);
+ *indexPtr = i;
+ return TCL_OK;
+ }
+ }
+ TclDecrRefCount(listObj);
+ return TCL_ERROR;
+ } else {
+ return TCL_ERROR;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_FSFileAttrsGet --
+ *
+ * This function implements read access for the hookable 'file
+ * attributes' subcommand. The appropriate function for the filesystem to
+ * which pathPtr belongs will be called.
+ *
+ * Results:
+ * Standard Tcl return code. The object placed in objPtrRef (if TCL_OK
+ * was returned) is likely to have a refCount of zero. Either way we must
+ * either store it somewhere (e.g. the Tcl result), or Incr/Decr its
+ * refCount to ensure it is properly freed.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
int
-Tcl_FSFileAttrsGet(interp, index, pathPtr, objPtrRef)
- Tcl_Interp *interp; /* The interpreter for error reporting. */
- int index; /* index of the attribute command. */
- Tcl_Obj *pathPtr; /* filename we are operating on. */
- Tcl_Obj **objPtrRef; /* for output. */
+Tcl_FSFileAttrsGet(
+ Tcl_Interp *interp, /* The interpreter for error reporting. */
+ int index, /* index of the attribute command. */
+ Tcl_Obj *pathPtr, /* filename we are operating on. */
+ Tcl_Obj **objPtrRef) /* for output. */
{
- Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
+ const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
+
if (fsPtr != NULL) {
Tcl_FSFileAttrsGetProc *proc = fsPtr->fileAttrsGetProc;
if (proc != NULL) {
@@ -2416,27 +2546,28 @@ Tcl_FSFileAttrsGet(interp, index, pathPtr, objPtrRef)
*
* Tcl_FSFileAttrsSet --
*
- * This procedure implements write access for the hookable 'file
- * attributes' subcommand. The appropriate function for the
- * filesystem to which pathPtr belongs will be called.
+ * This function implements write access for the hookable 'file
+ * attributes' subcommand. The appropriate function for the filesystem to
+ * which pathPtr belongs will be called.
*
* Results:
- * Standard Tcl return code.
+ * Standard Tcl return code.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
int
-Tcl_FSFileAttrsSet(interp, index, pathPtr, objPtr)
- Tcl_Interp *interp; /* The interpreter for error reporting. */
- int index; /* index of the attribute command. */
- Tcl_Obj *pathPtr; /* filename we are operating on. */
- Tcl_Obj *objPtr; /* Input value. */
+Tcl_FSFileAttrsSet(
+ Tcl_Interp *interp, /* The interpreter for error reporting. */
+ int index, /* index of the attribute command. */
+ Tcl_Obj *pathPtr, /* filename we are operating on. */
+ Tcl_Obj *objPtr) /* Input value. */
{
- Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
+ const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
+
if (fsPtr != NULL) {
Tcl_FSFileAttrsSetProc *proc = fsPtr->fileAttrsSetProc;
if (proc != NULL) {
@@ -2453,34 +2584,32 @@ Tcl_FSFileAttrsSet(interp, index, pathPtr, objPtr)
* Tcl_FSGetCwd --
*
* This function replaces the library version of getcwd().
- *
- * Most VFS's will *not* implement a 'cwdProc'. Tcl now maintains
- * its own record (in a Tcl_Obj) of the cwd, and an attempt
- * is made to synchronise this with the cwd's containing filesystem,
- * if that filesystem provides a cwdProc (e.g. the native filesystem).
- *
- * Note that if Tcl's cwd is not in the native filesystem, then of
- * course Tcl's cwd and the native cwd are different: extensions
- * should therefore ensure they only access the cwd through this
- * function to avoid confusion.
- *
+ *
+ * Most VFS's will *not* implement a 'cwdProc'. Tcl now maintains its own
+ * record (in a Tcl_Obj) of the cwd, and an attempt is made to synch this
+ * with the cwd's containing filesystem, if that filesystem provides a
+ * cwdProc (e.g. the native filesystem).
+ *
+ * Note that if Tcl's cwd is not in the native filesystem, then of course
+ * Tcl's cwd and the native cwd are different: extensions should
+ * therefore ensure they only access the cwd through this function to
+ * avoid confusion.
+ *
* If a global cwdPathPtr already exists, it is cached in the thread's
* private data structures and reference to the cached copy is returned,
* subject to a synchronisation attempt in that cwdPathPtr's fs.
- *
- * Otherwise, the chain of functions that have been "inserted"
- * into the filesystem will be called in succession until either a
- * value other than NULL is returned, or the entire list is
- * visited.
+ *
+ * Otherwise, the chain of functions that have been "inserted" into the
+ * filesystem will be called in succession until either a value other
+ * than NULL is returned, or the entire list is visited.
*
* Results:
- * The result is a pointer to a Tcl_Obj specifying the current
- * directory, or NULL if the current directory could not be
- * determined. If NULL is returned, an error message is left in the
- * interp's result.
- *
- * The result already has its refCount incremented for the caller.
- * When it is no longer needed, that refCount should be decremented.
+ * The result is a pointer to a Tcl_Obj specifying the current directory,
+ * or NULL if the current directory could not be determined. If NULL is
+ * returned, an error message is left in the interp's result.
+ *
+ * The result already has its refCount incremented for the caller. When
+ * it is no longer needed, that refCount should be decremented.
*
* Side effects:
* Various objects may be freed and allocated.
@@ -2488,117 +2617,218 @@ Tcl_FSFileAttrsSet(interp, index, pathPtr, objPtr)
*----------------------------------------------------------------------
*/
-Tcl_Obj*
-Tcl_FSGetCwd(interp)
- Tcl_Interp *interp;
+Tcl_Obj *
+Tcl_FSGetCwd(
+ Tcl_Interp *interp)
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
+
if (TclFSCwdPointerEquals(NULL)) {
FilesystemRecord *fsRecPtr;
Tcl_Obj *retVal = NULL;
- /*
- * We've never been called before, try to find a cwd. Call
- * each of the "Tcl_GetCwd" function in succession. A non-NULL
- * return value indicates the particular function has
- * succeeded.
+ /*
+ * We've never been called before, try to find a cwd. Call each of the
+ * "Tcl_GetCwd" function in succession. A non-NULL return value
+ * indicates the particular function has succeeded.
*/
fsRecPtr = FsGetFirstFilesystem();
while ((retVal == NULL) && (fsRecPtr != NULL)) {
Tcl_FSGetCwdProc *proc = fsRecPtr->fsPtr->getCwdProc;
if (proc != NULL) {
- retVal = (*proc)(interp);
+ if (fsRecPtr->fsPtr->version != TCL_FILESYSTEM_VERSION_1) {
+ ClientData retCd;
+ TclFSGetCwdProc2 *proc2 = (TclFSGetCwdProc2*)proc;
+
+ retCd = (*proc2)(NULL);
+ if (retCd != NULL) {
+ Tcl_Obj *norm;
+ /* Looks like a new current directory */
+ retVal = (*fsRecPtr->fsPtr->internalToNormalizedProc)(
+ retCd);
+ Tcl_IncrRefCount(retVal);
+ norm = TclFSNormalizeAbsolutePath(interp,retVal,NULL);
+ if (norm != NULL) {
+ /*
+ * We found a cwd, which is now in our global
+ * storage. We must make a copy. Norm already has
+ * a refCount of 1.
+ *
+ * Threading issue: note that multiple threads at
+ * system startup could in principle call this
+ * function simultaneously. They will therefore
+ * each set the cwdPathPtr independently. That
+ * behaviour is a bit peculiar, but should be
+ * fine. Once we have a cwd, we'll always be in
+ * the 'else' branch below which is simpler.
+ */
+
+ FsUpdateCwd(norm, retCd);
+ Tcl_DecrRefCount(norm);
+ } else {
+ (*fsRecPtr->fsPtr->freeInternalRepProc)(retCd);
+ }
+ Tcl_DecrRefCount(retVal);
+ retVal = NULL;
+ goto cdDidNotChange;
+ } else if (interp != NULL) {
+ Tcl_AppendResult(interp,
+ "error getting working directory name: ",
+ Tcl_PosixError(interp), NULL);
+ }
+ } else {
+ retVal = (*proc)(interp);
+ }
}
fsRecPtr = fsRecPtr->nextPtr;
}
- /*
- * Now the 'cwd' may NOT be normalized, at least on some
- * platforms. For the sake of efficiency, we want a completely
- * normalized cwd at all times.
- *
- * Finally, if retVal is NULL, we do not have a cwd, which
- * could be problematic.
+
+ /*
+ * Now the 'cwd' may NOT be normalized, at least on some platforms.
+ * For the sake of efficiency, we want a completely normalized cwd at
+ * all times.
+ *
+ * Finally, if retVal is NULL, we do not have a cwd, which could be
+ * problematic.
*/
+
if (retVal != NULL) {
Tcl_Obj *norm = TclFSNormalizeAbsolutePath(interp, retVal, NULL);
if (norm != NULL) {
- /*
- * We found a cwd, which is now in our global storage.
- * We must make a copy. Norm already has a refCount of 1.
- *
+ /*
+ * We found a cwd, which is now in our global storage. We must
+ * make a copy. Norm already has a refCount of 1.
+ *
* Threading issue: note that multiple threads at system
- * startup could in principle call this procedure
- * simultaneously. They will therefore each set the
- * cwdPathPtr independently. That behaviour is a bit
- * peculiar, but should be fine. Once we have a cwd,
- * we'll always be in the 'else' branch below which
- * is simpler.
+ * startup could in principle call this function
+ * simultaneously. They will therefore each set the cwdPathPtr
+ * independently. That behaviour is a bit peculiar, but should
+ * be fine. Once we have a cwd, we'll always be in the 'else'
+ * branch below which is simpler.
*/
- FsUpdateCwd(norm);
+
+ ClientData cd = (ClientData) Tcl_FSGetNativePath(norm);
+ FsUpdateCwd(norm, TclNativeDupInternalRep(cd));
Tcl_DecrRefCount(norm);
}
Tcl_DecrRefCount(retVal);
}
} else {
- /*
- * We already have a cwd cached, but we want to give the
- * filesystem it is in a chance to check whether that cwd
- * has changed, or is perhaps no longer accessible. This
- * allows an error to be thrown if, say, the permissions on
- * that directory have changed.
+ /*
+ * We already have a cwd cached, but we want to give the filesystem it
+ * is in a chance to check whether that cwd has changed, or is perhaps
+ * no longer accessible. This allows an error to be thrown if, say,
+ * the permissions on that directory have changed.
*/
- Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(tsdPtr->cwdPathPtr);
- /*
- * If the filesystem couldn't be found, or if no cwd function
- * exists for this filesystem, then we simply assume the cached
- * cwd is ok. If we do call a cwd, we must watch for errors
- * (if the cwd returns NULL). This ensures that, say, on Unix
- * if the permissions of the cwd change, 'pwd' does actually
- * throw the correct error in Tcl. (This is tested for in the
- * test suite on unix).
+
+ const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(tsdPtr->cwdPathPtr);
+
+ /*
+ * If the filesystem couldn't be found, or if no cwd function exists
+ * for this filesystem, then we simply assume the cached cwd is ok.
+ * If we do call a cwd, we must watch for errors (if the cwd returns
+ * NULL). This ensures that, say, on Unix if the permissions of the
+ * cwd change, 'pwd' does actually throw the correct error in Tcl.
+ * (This is tested for in the test suite on unix).
*/
+
if (fsPtr != NULL) {
Tcl_FSGetCwdProc *proc = fsPtr->getCwdProc;
+ ClientData retCd = NULL;
if (proc != NULL) {
- Tcl_Obj *retVal = (*proc)(interp);
+ Tcl_Obj *retVal;
+ if (fsPtr->version != TCL_FILESYSTEM_VERSION_1) {
+ TclFSGetCwdProc2 *proc2 = (TclFSGetCwdProc2*)proc;
+
+ retCd = (*proc2)(tsdPtr->cwdClientData);
+ if (retCd == NULL && interp != NULL) {
+ Tcl_AppendResult(interp,
+ "error getting working directory name: ",
+ Tcl_PosixError(interp), NULL);
+ }
+
+ if (retCd == tsdPtr->cwdClientData) {
+ goto cdDidNotChange;
+ }
+
+ /*
+ * Looks like a new current directory.
+ */
+
+ retVal = (*fsPtr->internalToNormalizedProc)(retCd);
+ Tcl_IncrRefCount(retVal);
+ } else {
+ retVal = (*proc)(interp);
+ }
if (retVal != NULL) {
- Tcl_Obj *norm = TclFSNormalizeAbsolutePath(interp, retVal, NULL);
- /*
- * Check whether cwd has changed from the value
- * previously stored in cwdPathPtr. Really 'norm'
- * shouldn't be null, but we are careful.
+ Tcl_Obj *norm = TclFSNormalizeAbsolutePath(interp,
+ retVal, NULL);
+
+ /*
+ * Check whether cwd has changed from the value previously
+ * stored in cwdPathPtr. Really 'norm' shouldn't be NULL,
+ * but we are careful.
*/
+
if (norm == NULL) {
/* Do nothing */
- } else if (Tcl_FSEqualPaths(tsdPtr->cwdPathPtr, norm)) {
- /*
- * If the paths were equal, we can be more
- * efficient and retain the old path object
- * which will probably already be shared. In
- * this case we can simply free the normalized
- * path we just calculated.
- */
- Tcl_DecrRefCount(norm);
+ if (retCd != NULL) {
+ (*fsPtr->freeInternalRepProc)(retCd);
+ }
+ } else if (norm == tsdPtr->cwdPathPtr) {
+ goto cdEqual;
} else {
- FsUpdateCwd(norm);
- Tcl_DecrRefCount(norm);
+ /*
+ * Note that both 'norm' and 'tsdPtr->cwdPathPtr' are
+ * normalized paths. Therefore we can be more
+ * efficient than calling 'Tcl_FSEqualPaths', and in
+ * addition avoid a nasty infinite loop bug when
+ * trying to normalize tsdPtr->cwdPathPtr.
+ */
+
+ int len1, len2;
+ char *str1, *str2;
+
+ str1 = Tcl_GetStringFromObj(tsdPtr->cwdPathPtr, &len1);
+ str2 = Tcl_GetStringFromObj(norm, &len2);
+ if ((len1 == len2) && (strcmp(str1, str2) == 0)) {
+ /*
+ * If the paths were equal, we can be more
+ * efficient and retain the old path object which
+ * will probably already be shared. In this case
+ * we can simply free the normalized path we just
+ * calculated.
+ */
+
+ cdEqual:
+ Tcl_DecrRefCount(norm);
+ if (retCd != NULL) {
+ (*fsPtr->freeInternalRepProc)(retCd);
+ }
+ } else {
+ FsUpdateCwd(norm, retCd);
+ Tcl_DecrRefCount(norm);
+ }
}
Tcl_DecrRefCount(retVal);
} else {
- /* The 'cwd' function returned an error; reset the cwd */
- FsUpdateCwd(NULL);
+ /*
+ * The 'cwd' function returned an error; reset the cwd.
+ */
+
+ FsUpdateCwd(NULL, NULL);
}
}
}
}
-
+
+ cdDidNotChange:
if (tsdPtr->cwdPathPtr != NULL) {
Tcl_IncrRefCount(tsdPtr->cwdPathPtr);
}
-
- return tsdPtr->cwdPathPtr;
+
+ return tsdPtr->cwdPathPtr;
}
/*
@@ -2607,131 +2837,148 @@ Tcl_FSGetCwd(interp)
* Tcl_FSChdir --
*
* This function replaces the library version of chdir().
- *
- * The path is normalized and then passed to the filesystem
- * which claims it.
+ *
+ * The path is normalized and then passed to the filesystem which claims
+ * it.
*
* Results:
- * See chdir() documentation. If successful, we keep a
- * record of the successful path in cwdPathPtr for subsequent
- * calls to getcwd.
+ * See chdir() documentation. If successful, we keep a record of the
+ * successful path in cwdPathPtr for subsequent calls to getcwd.
*
* Side effects:
- * See chdir() documentation. The global cwdPathPtr may
- * change value.
+ * See chdir() documentation. The global cwdPathPtr may change value.
*
*----------------------------------------------------------------------
*/
+
int
-Tcl_FSChdir(pathPtr)
- Tcl_Obj *pathPtr;
+Tcl_FSChdir(
+ Tcl_Obj *pathPtr)
{
- Tcl_Filesystem *fsPtr;
+ const Tcl_Filesystem *fsPtr;
int retVal = -1;
-
-#ifdef WIN32
- /*
- * This complete hack addresses the bug tested in winFCmd-16.12,
- * where having your HOME as "C:" (IOW, a seemingly path relative
- * dir) would cause a crash when you cd'd to it and requested 'pwd'.
- * The work-around is to force such a dir into an absolute path by
- * tacking on '/'.
- *
- * We check for '~' specifically because that's what Tcl_CdObjCmd
- * passes in that triggers the bug. A direct 'cd C:' call will not
- * because that gets the volumerelative pwd.
- *
- * This is not an issue for 8.5 as that has a more elaborate change
- * that requires the use of TCL_FILESYSTEM_VERSION_2.
- */
- Tcl_Obj *objPtr = NULL;
- if (pathPtr->bytes && pathPtr->length == 1 && pathPtr->bytes[0] == '~') {
- int len;
- char *str;
- objPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
- if (objPtr == NULL) {
- Tcl_SetErrno(ENOENT);
- return -1;
- }
- Tcl_IncrRefCount(objPtr);
- str = Tcl_GetStringFromObj(objPtr, &len);
- if (len == 2 && str[1] == ':') {
- pathPtr = Tcl_NewStringObj(str, len);
- Tcl_AppendToObj(pathPtr, "/", 1);
- Tcl_IncrRefCount(pathPtr);
- Tcl_DecrRefCount(objPtr);
- objPtr = pathPtr;
- } else {
- Tcl_DecrRefCount(objPtr);
- objPtr = NULL;
- }
- }
-#endif
if (Tcl_FSGetNormalizedPath(NULL, pathPtr) == NULL) {
-#ifdef WIN32
- if (objPtr) { Tcl_DecrRefCount(objPtr); }
-#endif
Tcl_SetErrno(ENOENT);
- return -1;
+ return retVal;
}
-
+
fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
if (fsPtr != NULL) {
Tcl_FSChdirProc *proc = fsPtr->chdirProc;
if (proc != NULL) {
+ /*
+ * If this fails, an appropriate errno will have been stored using
+ * 'Tcl_SetErrno()'.
+ */
+
retVal = (*proc)(pathPtr);
} else {
- /* Fallback on stat-based implementation */
+ /*
+ * Fallback on stat-based implementation.
+ */
+
Tcl_StatBuf buf;
- /* If the file can be stat'ed and is a directory and
- * is readable, then we can chdir. */
- if ((Tcl_FSStat(pathPtr, &buf) == 0)
- && (S_ISDIR(buf.st_mode))
- && (Tcl_FSAccess(pathPtr, R_OK) == 0)) {
- /* We allow the chdir */
+
+ /*
+ * If the file can be stat'ed and is a directory and is readable,
+ * then we can chdir. If any of these actions fail, then
+ * 'Tcl_SetErrno()' should automatically have been called to set
+ * an appropriate error code
+ */
+
+ if ((Tcl_FSStat(pathPtr, &buf) == 0) && (S_ISDIR(buf.st_mode))
+ && (Tcl_FSAccess(pathPtr, R_OK) == 0)) {
+ /*
+ * We allow the chdir.
+ */
+
retVal = 0;
}
}
+ } else {
+ Tcl_SetErrno(ENOENT);
}
- if (retVal != -1) {
- /*
- * The cwd changed, or an error was thrown. If an error was
- * thrown, we can just continue (and that will report the error
- * to the user). If there was no error we must assume that the
- * cwd was actually changed to the normalized value we
- * calculated above, and we must therefore cache that
- * information.
+ /*
+ * The cwd changed, or an error was thrown. If an error was thrown, we can
+ * just continue (and that will report the error to the user). If there
+ * was no error we must assume that the cwd was actually changed to the
+ * normalized value we calculated above, and we must therefore cache that
+ * information.
+ */
+
+ /*
+ * If the filesystem in question has a getCwdProc, then the correct logic
+ * which performs the part below is already part of the Tcl_FSGetCwd()
+ * call, so no need to replicate it again. This will have a side effect
+ * though. The private authoritative representation of the current working
+ * directory stored in cwdPathPtr in static memory will be out-of-sync
+ * with the real OS-maintained value. The first call to Tcl_FSGetCwd will
+ * however recalculate the private copy to match the OS-value so
+ * everything will work right.
+ *
+ * However, if there is no getCwdProc, then we _must_ update our private
+ * storage of the cwd, since this is the only opportunity to do that!
+ *
+ * Note: We currently call this block of code irrespective of whether
+ * there was a getCwdProc or not, but the code should all in principle
+ * work if we only call this block if fsPtr->getCwdProc == NULL.
+ */
+
+ if (retVal == 0) {
+ /*
+ * Note that this normalized path may be different to what we found
+ * above (or at least a different object), if the filesystem epoch
+ * changed recently. This can actually happen with scripted documents
+ * very easily. Therefore we ask for the normalized path again (the
+ * correct value will have been cached as a result of the
+ * Tcl_FSGetFileSystemForPath call above anyway).
*/
- if (retVal == 0) {
- /*
- * Note that this normalized path may be different to what
- * we found above (or at least a different object), if the
- * filesystem epoch changed recently. This can actually
- * happen with scripted documents very easily. Therefore
- * we ask for the normalized path again (the correct value
- * will have been cached as a result of the
- * Tcl_FSGetFileSystemForPath call above anyway).
+
+ Tcl_Obj *normDirName = Tcl_FSGetNormalizedPath(NULL, pathPtr);
+
+ if (normDirName == NULL) {
+ /* Not really true, but what else to do? */
+ Tcl_SetErrno(ENOENT);
+ return -1;
+ }
+
+ if (fsPtr == &tclNativeFilesystem) {
+ /*
+ * For the native filesystem, we keep a cache of the native
+ * representation of the cwd. But, we want to do that for the
+ * exact format that is returned by 'getcwd' (so that we can later
+ * compare the two representations for equality), which might not
+ * be exactly the same char-string as the native representation of
+ * the fully normalized path (e.g. on Windows there's a
+ * forward-slash vs backslash difference). Hence we ask for this
+ * again here. On Unix it might actually be true that we always
+ * have the correct form in the native rep in which case we could
+ * simply use:
+ * cd = Tcl_FSGetNativePath(pathPtr);
+ * instead. This should be examined by someone on Unix.
*/
- Tcl_Obj *normDirName = Tcl_FSGetNormalizedPath(NULL, pathPtr);
- if (normDirName == NULL) {
-#ifdef WIN32
- if (objPtr) { Tcl_DecrRefCount(objPtr); }
-#endif
- Tcl_SetErrno(ENOENT);
- return -1;
+
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
+ ClientData cd;
+ ClientData oldcd = tsdPtr->cwdClientData;
+
+ /*
+ * Assumption we are using a filesystem version 2.
+ */
+
+ TclFSGetCwdProc2 *proc2 = (TclFSGetCwdProc2*)fsPtr->getCwdProc;
+ cd = (*proc2)(oldcd);
+ if (cd != oldcd) {
+ FsUpdateCwd(normDirName, cd);
}
- FsUpdateCwd(normDirName);
+ } else {
+ FsUpdateCwd(normDirName, NULL);
}
- } else {
- Tcl_SetErrno(ENOENT);
}
-
-#ifdef WIN32
- if (objPtr) { Tcl_DecrRefCount(objPtr); }
-#endif
- return (retVal);
+
+ return retVal;
}
/*
@@ -2739,306 +2986,446 @@ Tcl_FSChdir(pathPtr)
*
* Tcl_FSLoadFile --
*
- * Dynamically loads a binary code file into memory and returns
- * the addresses of two procedures within that file, if they are
- * defined. The appropriate function for the filesystem to which
- * pathPtr belongs will be called.
- *
- * Note that the native filesystem doesn't actually assume
- * 'pathPtr' is a path. Rather it assumes filename is either
- * a path or just the name of a file which can be found somewhere
- * in the environment's loadable path. This behaviour is not
- * very compatible with virtual filesystems (and has other problems
- * documented in the load man-page), so it is advised that full
- * paths are always used.
+ * Dynamically loads a binary code file into memory and returns the
+ * addresses of two functions within that file, if they are defined. The
+ * appropriate function for the filesystem to which pathPtr belongs will
+ * be called.
+ *
+ * Note that the native filesystem doesn't actually assume 'pathPtr' is a
+ * path. Rather it assumes pathPtr is either a path or just the name
+ * (tail) of a file which can be found somewhere in the environment's
+ * loadable path. This behaviour is not very compatible with virtual
+ * filesystems (and has other problems documented in the load man-page),
+ * so it is advised that full paths are always used.
*
* Results:
- * A standard Tcl completion code. If an error occurs, an error
- * message is left in the interp's result.
+ * A standard Tcl completion code. If an error occurs, an error message
+ * is left in the interp's result.
*
* Side effects:
- * New code suddenly appears in memory. This may later be
- * unloaded by passing the clientData to the unloadProc.
+ * New code suddenly appears in memory. This may later be unloaded by
+ * passing the clientData to the unloadProc.
*
*----------------------------------------------------------------------
*/
int
-Tcl_FSLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr,
- handlePtr, unloadProcPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Obj *pathPtr; /* Name of the file containing the desired
+Tcl_FSLoadFile(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *pathPtr, /* Name of the file containing the desired
* code. */
- CONST char *sym1, *sym2; /* Names of two procedures to look up in
- * the file's symbol table. */
- Tcl_PackageInitProc **proc1Ptr, **proc2Ptr;
+ const char *sym1, const char *sym2,
+ /* Names of two functions to look up in the
+ * file's symbol table. */
+ Tcl_PackageInitProc **proc1Ptr, Tcl_PackageInitProc **proc2Ptr,
/* Where to return the addresses corresponding
* to sym1 and sym2. */
- Tcl_LoadHandle *handlePtr; /* Filled with token for dynamically loaded
- * file which will be passed back to
+ Tcl_LoadHandle *handlePtr, /* Filled with token for dynamically loaded
+ * file which will be passed back to
* (*unloadProcPtr)() to unload the file. */
- Tcl_FSUnloadFileProc **unloadProcPtr;
- /* Filled with address of Tcl_FSUnloadFileProc
- * function which should be used for
- * this file. */
+ Tcl_FSUnloadFileProc **unloadProcPtr)
+ /* Filled with address of Tcl_FSUnloadFileProc
+ * function which should be used for this
+ * file. */
{
- Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
- if (fsPtr != NULL) {
- Tcl_FSLoadFileProc *proc = fsPtr->loadFileProc;
- if (proc != NULL) {
- int retVal = (*proc)(interp, pathPtr, handlePtr, unloadProcPtr);
- if (retVal != TCL_OK) {
- return retVal;
- }
+ const char *symbols[2];
+ Tcl_PackageInitProc **procPtrs[2];
+ ClientData clientData;
+ int res;
+
+ /*
+ * Initialize the arrays.
+ */
+
+ symbols[0] = sym1;
+ symbols[1] = sym2;
+ procPtrs[0] = proc1Ptr;
+ procPtrs[1] = proc2Ptr;
+
+ /*
+ * Perform the load.
+ */
+
+ res = TclLoadFile(interp, pathPtr, 2, symbols, procPtrs, handlePtr,
+ &clientData, unloadProcPtr);
+
+ /*
+ * Due to an unfortunate mis-design in Tcl 8.4 fs, when loading a shared
+ * library, we don't keep the loadHandle (for TclpFindSymbol) and the
+ * clientData (for the unloadProc) separately. In fact we effectively
+ * throw away the loadHandle and only use the clientData. It just so
+ * happens, for the native filesystem only, that these two are identical.
+ *
+ * This also means that the signatures Tcl_FSUnloadFileProc and
+ * Tcl_FSLoadFileProc are both misleading.
+ */
+
+ *handlePtr = (Tcl_LoadHandle) clientData;
+ return res;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclLoadFile --
+ *
+ * Dynamically loads a binary code file into memory and returns the
+ * addresses of a number of given functions within that file, if they are
+ * defined. The appropriate function for the filesystem to which pathPtr
+ * belongs will be called.
+ *
+ * Note that the native filesystem doesn't actually assume 'pathPtr' is a
+ * path. Rather it assumes pathPtr is either a path or just the name
+ * (tail) of a file which can be found somewhere in the environment's
+ * loadable path. This behaviour is not very compatible with virtual
+ * filesystems (and has other problems documented in the load man-page),
+ * so it is advised that full paths are always used.
+ *
+ * This function is currently private to Tcl. It may be exported in the
+ * future and its interface fixed (but we should clean up the
+ * loadHandle/clientData confusion at that time -- see the above comments
+ * in Tcl_FSLoadFile for details). For a public function, see
+ * Tcl_FSLoadFile.
+ *
+ * Results:
+ * A standard Tcl completion code. If an error occurs, an error message
+ * is left in the interp's result.
+ *
+ * Side effects:
+ * New code suddenly appears in memory. This may later be unloaded by
+ * passing the clientData to the unloadProc.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclLoadFile(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *pathPtr, /* Name of the file containing the desired
+ * code. */
+ int symc, /* Number of symbols/procPtrs in the next two
+ * arrays. */
+ const char *symbols[], /* Names of functions to look up in the file's
+ * symbol table. */
+ Tcl_PackageInitProc **procPtrs[],
+ /* Where to return the addresses corresponding
+ * to symbols[]. */
+ Tcl_LoadHandle *handlePtr, /* Filled with token for shared library
+ * information which can be used in
+ * TclpFindSymbol. */
+ ClientData *clientDataPtr, /* Filled with token for dynamically loaded
+ * file which will be passed back to
+ * (*unloadProcPtr)() to unload the file. */
+ Tcl_FSUnloadFileProc **unloadProcPtr)
+ /* Filled with address of Tcl_FSUnloadFileProc
+ * function which should be used for this
+ * file. */
+{
+ const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
+ Tcl_FSLoadFileProc *proc;
+ Tcl_Filesystem *copyFsPtr;
+ Tcl_Obj *copyToPtr;
+ Tcl_LoadHandle newLoadHandle = NULL;
+ ClientData newClientData = NULL;
+ Tcl_FSUnloadFileProc *newUnloadProcPtr = NULL;
+ FsDivertLoad *tvdlPtr;
+ int retVal;
+
+ if (fsPtr == NULL) {
+ Tcl_SetErrno(ENOENT);
+ return TCL_ERROR;
+ }
+
+ proc = fsPtr->loadFileProc;
+ if (proc != NULL) {
+ int retVal = (*proc)(interp, pathPtr, handlePtr, unloadProcPtr);
+ if (retVal == TCL_OK) {
if (*handlePtr == NULL) {
return TCL_ERROR;
}
- if (sym1 != NULL) {
- *proc1Ptr = TclpFindSymbol(interp, *handlePtr, sym1);
- }
- if (sym2 != NULL) {
- *proc2Ptr = TclpFindSymbol(interp, *handlePtr, sym2);
- }
+
+ /*
+ * Copy this across, since both are equal for the native fs.
+ */
+
+ *clientDataPtr = (ClientData)*handlePtr;
+ Tcl_ResetResult(interp);
+ goto resolveSymbols;
+ }
+ if (Tcl_GetErrno() != EXDEV) {
return retVal;
- } else {
- Tcl_Filesystem *copyFsPtr;
- Tcl_Obj *copyToPtr;
-
- /* First check if it is readable -- and exists! */
- if (Tcl_FSAccess(pathPtr, R_OK) != 0) {
- Tcl_AppendResult(interp, "couldn't load library \"",
- Tcl_GetString(pathPtr), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
- return TCL_ERROR;
- }
-
+ }
+ }
+
+ /*
+ * The filesystem doesn't support 'load', so we fall back on the following
+ * technique:
+ *
+ * First check if it is readable -- and exists!
+ */
+
+ if (Tcl_FSAccess(pathPtr, R_OK) != 0) {
+ Tcl_AppendResult(interp, "couldn't load library \"",
+ Tcl_GetString(pathPtr), "\": ", Tcl_PosixError(interp), NULL);
+ return TCL_ERROR;
+ }
+
#ifdef TCL_LOAD_FROM_MEMORY
- /*
- * The platform supports loading code from memory, so ask for a
- * buffer of the appropriate size, read the file into it and
- * load the code from the buffer:
+ /*
+ * The platform supports loading code from memory, so ask for a buffer of
+ * the appropriate size, read the file into it and load the code from the
+ * buffer:
+ */
+
+ {
+ int ret, size;
+ void *buffer;
+ Tcl_StatBuf statBuf;
+ Tcl_Channel data;
+
+ ret = Tcl_FSStat(pathPtr, &statBuf);
+ if (ret < 0) {
+ goto mustCopyToTempAnyway;
+ }
+ size = (int) statBuf.st_size;
+
+ /*
+ * Tcl_Read takes an int: check that file size isn't wide.
*/
- do {
- int ret, size;
- void *buffer;
- Tcl_StatBuf statBuf;
- Tcl_Channel data;
-
- ret = Tcl_FSStat(pathPtr, &statBuf);
- if (ret < 0) {
- break;
- }
- size = (int) statBuf.st_size;
- /* Tcl_Read takes an int: check that file size isn't wide */
- if (size != (Tcl_WideInt)statBuf.st_size) {
- break;
- }
- data = Tcl_FSOpenFileChannel(interp, pathPtr, "r", 0666);
- if (!data) {
- break;
- }
- buffer = TclpLoadMemoryGetBuffer(interp, size);
- if (!buffer) {
- Tcl_Close(interp, data);
- break;
- }
- Tcl_SetChannelOption(interp, data, "-translation", "binary");
- ret = Tcl_Read(data, buffer, size);
- Tcl_Close(interp, data);
- ret = TclpLoadMemory(interp, buffer, size, ret, handlePtr, unloadProcPtr);
- if (ret == TCL_OK) {
- if (*handlePtr == NULL) {
- break;
- }
- if (sym1 != NULL) {
- *proc1Ptr = TclpFindSymbol(interp, *handlePtr, sym1);
- }
- if (sym2 != NULL) {
- *proc2Ptr = TclpFindSymbol(interp, *handlePtr, sym2);
- }
- return TCL_OK;
- }
- } while (0);
- Tcl_ResetResult(interp);
+
+ if (size != (Tcl_WideInt) statBuf.st_size) {
+ goto mustCopyToTempAnyway;
+ }
+ data = Tcl_FSOpenFileChannel(interp, pathPtr, "rb", 0666);
+ if (!data) {
+ goto mustCopyToTempAnyway;
+ }
+ buffer = TclpLoadMemoryGetBuffer(interp, size);
+ if (!buffer) {
+ Tcl_Close(interp, data);
+ goto mustCopyToTempAnyway;
+ }
+ ret = Tcl_Read(data, buffer, size);
+ Tcl_Close(interp, data);
+ ret = TclpLoadMemory(interp, buffer, size, ret, handlePtr,
+ unloadProcPtr);
+ if (ret == TCL_OK && *handlePtr != NULL) {
+ *clientDataPtr = (ClientData) *handlePtr;
+ goto resolveSymbols;
+ }
+ }
+
+ mustCopyToTempAnyway:
+ Tcl_ResetResult(interp);
#endif
- /*
- * Get a temporary filename to use, first to
- * copy the file into, and then to load.
- */
- copyToPtr = TclpTempFileName();
- if (copyToPtr == NULL) {
- return -1;
- }
- Tcl_IncrRefCount(copyToPtr);
-
- copyFsPtr = Tcl_FSGetFileSystemForPath(copyToPtr);
- if ((copyFsPtr == NULL) || (copyFsPtr == fsPtr)) {
- /*
- * We already know we can't use Tcl_FSLoadFile from
- * this filesystem, and we must avoid a possible
- * infinite loop. Try to delete the file we
- * probably created, and then exit.
- */
- Tcl_FSDeleteFile(copyToPtr);
- Tcl_DecrRefCount(copyToPtr);
- return -1;
- }
-
- if (TclCrossFilesystemCopy(interp, pathPtr,
- copyToPtr) == TCL_OK) {
- Tcl_LoadHandle newLoadHandle = NULL;
- Tcl_FSUnloadFileProc *newUnloadProcPtr = NULL;
- FsDivertLoad *tvdlPtr;
- int retVal;
-
-#if !defined(__WIN32__) && !defined(MAC_TCL)
- /*
- * Do we need to set appropriate permissions
- * on the file? This may be required on some
- * systems. On Unix we could loop over
- * the file attributes, and set any that are
- * called "-permissions" to 0700. However,
- * we just do this directly, like this:
- */
-
- Tcl_Obj* perm = Tcl_NewStringObj("0700",-1);
- Tcl_IncrRefCount(perm);
- Tcl_FSFileAttrsSet(NULL, 2, copyToPtr, perm);
- Tcl_DecrRefCount(perm);
+ /*
+ * Get a temporary filename to use, first to copy the file into, and then
+ * to load.
+ */
+
+ copyToPtr = TclpTempFileName();
+ if (copyToPtr == NULL) {
+ Tcl_AppendResult(interp, "couldn't create temporary file: ",
+ Tcl_PosixError(interp), NULL);
+ return TCL_ERROR;
+ }
+ Tcl_IncrRefCount(copyToPtr);
+
+ copyFsPtr = Tcl_FSGetFileSystemForPath(copyToPtr);
+ if ((copyFsPtr == NULL) || (copyFsPtr == fsPtr)) {
+ /*
+ * We already know we can't use Tcl_FSLoadFile from this filesystem,
+ * and we must avoid a possible infinite loop. Try to delete the file
+ * we probably created, and then exit.
+ */
+
+ Tcl_FSDeleteFile(copyToPtr);
+ Tcl_DecrRefCount(copyToPtr);
+ Tcl_AppendResult(interp, "couldn't load from current filesystem",NULL);
+ return TCL_ERROR;
+ }
+
+ if (TclCrossFilesystemCopy(interp, pathPtr, copyToPtr) != TCL_OK) {
+ /*
+ * Cross-platform copy failed.
+ */
+
+ Tcl_FSDeleteFile(copyToPtr);
+ Tcl_DecrRefCount(copyToPtr);
+ return TCL_ERROR;
+ }
+
+#if !defined(__WIN32__)
+ /*
+ * Do we need to set appropriate permissions on the file? This may be
+ * required on some systems. On Unix we could loop over the file
+ * attributes, and set any that are called "-permissions" to 0700. However
+ * we just do this directly, like this:
+ */
+
+ {
+ int index;
+ Tcl_Obj *perm;
+
+ TclNewLiteralStringObj(perm, "0700");
+ Tcl_IncrRefCount(perm);
+ if (TclFSFileAttrIndex(copyToPtr, "-permissions", &index) == TCL_OK) {
+ Tcl_FSFileAttrsSet(NULL, index, copyToPtr, perm);
+ }
+ Tcl_DecrRefCount(perm);
+ }
#endif
-
- /*
- * We need to reset the result now, because the cross-
- * filesystem copy may have stored the number of bytes
- * in the result
- */
- Tcl_ResetResult(interp);
-
- retVal = Tcl_FSLoadFile(interp, copyToPtr, sym1, sym2,
- proc1Ptr, proc2Ptr,
- &newLoadHandle,
- &newUnloadProcPtr);
- if (retVal != TCL_OK) {
- /* The file didn't load successfully */
- Tcl_FSDeleteFile(copyToPtr);
- Tcl_DecrRefCount(copyToPtr);
- return retVal;
- }
- /*
- * Try to delete the file immediately -- this is
- * possible in some OSes, and avoids any worries
- * about leaving the copy laying around on exit.
- */
- if (Tcl_FSDeleteFile(copyToPtr) == TCL_OK) {
- Tcl_DecrRefCount(copyToPtr);
- /*
- * We tell our caller about the real shared
- * library which was loaded. Note that this
- * does mean that the package list maintained
- * by 'load' will store the original (vfs)
- * path alongside the temporary load handle
- * and unload proc ptr.
- */
- (*handlePtr) = newLoadHandle;
- (*unloadProcPtr) = newUnloadProcPtr;
- return TCL_OK;
- }
- /*
- * When we unload this file, we need to divert the
- * unloading so we can unload and cleanup the
- * temporary file correctly.
- */
- tvdlPtr = (FsDivertLoad*) ckalloc(sizeof(FsDivertLoad));
- /*
- * Remember three pieces of information. This allows
- * us to cleanup the diverted load completely, on
- * platforms which allow proper unloading of code.
- */
- tvdlPtr->loadHandle = newLoadHandle;
- tvdlPtr->unloadProcPtr = newUnloadProcPtr;
-
- if (copyFsPtr != &tclNativeFilesystem) {
- /* copyToPtr is already incremented for this reference */
- tvdlPtr->divertedFile = copyToPtr;
-
- /*
- * This is the filesystem we loaded it into. Since
- * we have a reference to 'copyToPtr', we already
- * have a refCount on this filesystem, so we don't
- * need to worry about it disappearing on us.
- */
- tvdlPtr->divertedFilesystem = copyFsPtr;
- tvdlPtr->divertedFileNativeRep = NULL;
- } else {
- /* We need the native rep */
- tvdlPtr->divertedFileNativeRep =
- TclNativeDupInternalRep(Tcl_FSGetInternalRep(copyToPtr,
- copyFsPtr));
- /*
- * We don't need or want references to the copied
- * Tcl_Obj or the filesystem if it is the native
- * one.
- */
- tvdlPtr->divertedFile = NULL;
- tvdlPtr->divertedFilesystem = NULL;
- Tcl_DecrRefCount(copyToPtr);
- }
+ /*
+ * We need to reset the result now, because the cross-filesystem copy may
+ * have stored the number of bytes in the result.
+ */
- copyToPtr = NULL;
- (*handlePtr) = (Tcl_LoadHandle) tvdlPtr;
- (*unloadProcPtr) = &FSUnloadTempFile;
- return retVal;
- } else {
- /* Cross-platform copy failed */
- Tcl_FSDeleteFile(copyToPtr);
- Tcl_DecrRefCount(copyToPtr);
- return TCL_ERROR;
+ Tcl_ResetResult(interp);
+
+ retVal = TclLoadFile(interp, copyToPtr, symc, symbols, procPtrs,
+ &newLoadHandle, &newClientData, &newUnloadProcPtr);
+ if (retVal != TCL_OK) {
+ /*
+ * The file didn't load successfully.
+ */
+
+ Tcl_FSDeleteFile(copyToPtr);
+ Tcl_DecrRefCount(copyToPtr);
+ return retVal;
+ }
+
+ /*
+ * Try to delete the file immediately - this is possible in some OSes, and
+ * avoids any worries about leaving the copy laying around on exit.
+ */
+
+ if (Tcl_FSDeleteFile(copyToPtr) == TCL_OK) {
+ Tcl_DecrRefCount(copyToPtr);
+
+ /*
+ * We tell our caller about the real shared library which was loaded.
+ * Note that this does mean that the package list maintained by 'load'
+ * will store the original (vfs) path alongside the temporary load
+ * handle and unload proc ptr.
+ */
+
+ (*handlePtr) = newLoadHandle;
+ (*clientDataPtr) = newClientData;
+ (*unloadProcPtr) = newUnloadProcPtr;
+ Tcl_ResetResult(interp);
+ return TCL_OK;
+ }
+
+ /*
+ * When we unload this file, we need to divert the unloading so we can
+ * unload and cleanup the temporary file correctly.
+ */
+
+ tvdlPtr = (FsDivertLoad *) ckalloc(sizeof(FsDivertLoad));
+
+ /*
+ * Remember three pieces of information. This allows us to cleanup the
+ * diverted load completely, on platforms which allow proper unloading of
+ * code.
+ */
+
+ tvdlPtr->loadHandle = newLoadHandle;
+ tvdlPtr->unloadProcPtr = newUnloadProcPtr;
+
+ if (copyFsPtr != &tclNativeFilesystem) {
+ /*
+ * copyToPtr is already incremented for this reference.
+ */
+
+ tvdlPtr->divertedFile = copyToPtr;
+
+ /*
+ * This is the filesystem we loaded it into. Since we have a reference
+ * to 'copyToPtr', we already have a refCount on this filesystem, so
+ * we don't need to worry about it disappearing on us.
+ */
+
+ tvdlPtr->divertedFilesystem = copyFsPtr;
+ tvdlPtr->divertedFileNativeRep = NULL;
+ } else {
+ /*
+ * We need the native rep.
+ */
+
+ tvdlPtr->divertedFileNativeRep = TclNativeDupInternalRep(
+ Tcl_FSGetInternalRep(copyToPtr, copyFsPtr));
+
+ /*
+ * We don't need or want references to the copied Tcl_Obj or the
+ * filesystem if it is the native one.
+ */
+
+ tvdlPtr->divertedFile = NULL;
+ tvdlPtr->divertedFilesystem = NULL;
+ Tcl_DecrRefCount(copyToPtr);
+ }
+
+ copyToPtr = NULL;
+ (*handlePtr) = newLoadHandle;
+ (*clientDataPtr) = (ClientData) tvdlPtr;
+ (*unloadProcPtr) = TclFSUnloadTempFile;
+
+ Tcl_ResetResult(interp);
+ return retVal;
+
+ resolveSymbols:
+ {
+ int i;
+
+ for (i=0 ; i<symc ; i++) {
+ if (symbols[i] != NULL) {
+ *procPtrs[i] = TclpFindSymbol(interp, *handlePtr, symbols[i]);
}
}
}
- Tcl_SetErrno(ENOENT);
- return -1;
+ return TCL_OK;
}
-/*
- * This function used to be in the platform specific directories, but it
- * has now been made to work cross-platform
+/*
+ * This function used to be in the platform specific directories, but it has
+ * now been made to work cross-platform
*/
+
int
-TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr,
- clientDataPtr, unloadProcPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Obj *pathPtr; /* Name of the file containing the desired
+TclpLoadFile(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *pathPtr, /* Name of the file containing the desired
* code (UTF-8). */
- CONST char *sym1, *sym2; /* Names of two procedures to look up in
- * the file's symbol table. */
- Tcl_PackageInitProc **proc1Ptr, **proc2Ptr;
+ const char *sym1, CONST char *sym2,
+ /* Names of two functions to look up in the
+ * file's symbol table. */
+ Tcl_PackageInitProc **proc1Ptr, Tcl_PackageInitProc **proc2Ptr,
/* Where to return the addresses corresponding
* to sym1 and sym2. */
- ClientData *clientDataPtr; /* Filled with token for dynamically loaded
- * file which will be passed back to
+ ClientData *clientDataPtr, /* Filled with token for dynamically loaded
+ * file which will be passed back to
* (*unloadProcPtr)() to unload the file. */
- Tcl_FSUnloadFileProc **unloadProcPtr;
+ Tcl_FSUnloadFileProc **unloadProcPtr)
/* Filled with address of Tcl_FSUnloadFileProc
- * function which should be used for
- * this file. */
+ * function which should be used for this
+ * file. */
{
Tcl_LoadHandle handle = NULL;
int res;
-
+
res = TclpDlopen(interp, pathPtr, &handle, unloadProcPtr);
-
+
if (res != TCL_OK) {
- return res;
+ return res;
}
if (handle == NULL) {
return TCL_ERROR;
}
-
- *clientDataPtr = (ClientData)handle;
-
+
+ *clientDataPtr = (ClientData) handle;
+
*proc1Ptr = TclpFindSymbol(interp, handle, sym1);
*proc2Ptr = TclpFindSymbol(interp, handle, sym2);
return TCL_OK;
@@ -3047,85 +3434,91 @@ TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr,
/*
*---------------------------------------------------------------------------
*
- * FSUnloadTempFile --
+ * TclFSUnloadTempFile --
*
- * This function is called when we loaded a library of code via
- * an intermediate temporary file. This function ensures
- * the library is correctly unloaded and the temporary file
- * is correctly deleted.
+ * This function is called when we loaded a library of code via an
+ * intermediate temporary file. This function ensures the library is
+ * correctly unloaded and the temporary file is correctly deleted.
*
* Results:
* None.
*
* Side effects:
- * The effects of the 'unload' function called, and of course
- * the temporary file will be deleted.
+ * The effects of the 'unload' function called, and of course the
+ * temporary file will be deleted.
*
*---------------------------------------------------------------------------
*/
-static void
-FSUnloadTempFile(loadHandle)
- Tcl_LoadHandle loadHandle; /* loadHandle returned by a previous call
- * to Tcl_FSLoadFile(). The loadHandle is
- * a token that represents the loaded
- * file. */
+
+void
+TclFSUnloadTempFile(
+ Tcl_LoadHandle loadHandle) /* loadHandle returned by a previous call to
+ * Tcl_FSLoadFile(). The loadHandle is a token
+ * that represents the loaded file. */
{
- FsDivertLoad *tvdlPtr = (FsDivertLoad*)loadHandle;
- /*
- * This test should never trigger, since we give
- * the client data in the function above.
+ FsDivertLoad *tvdlPtr = (FsDivertLoad *) loadHandle;
+
+ /*
+ * This test should never trigger, since we give the client data in the
+ * function above.
*/
- if (tvdlPtr == NULL) { return; }
-
- /*
- * Call the real 'unloadfile' proc we actually used. It is very
- * important that we call this first, so that the shared library
- * is actually unloaded by the OS. Otherwise, the following
- * 'delete' may well fail because the shared library is still in
- * use.
+
+ if (tvdlPtr == NULL) {
+ return;
+ }
+
+ /*
+ * Call the real 'unloadfile' proc we actually used. It is very important
+ * that we call this first, so that the shared library is actually
+ * unloaded by the OS. Otherwise, the following 'delete' may well fail
+ * because the shared library is still in use.
*/
+
if (tvdlPtr->unloadProcPtr != NULL) {
(*tvdlPtr->unloadProcPtr)(tvdlPtr->loadHandle);
}
-
+
if (tvdlPtr->divertedFilesystem == NULL) {
- /*
- * It was the native filesystem, and we have a special
- * function available just for this purpose, which we
- * know works even at this late stage.
+ /*
+ * It was the native filesystem, and we have a special function
+ * available just for this purpose, which we know works even at this
+ * late stage.
*/
+
TclpDeleteFile(tvdlPtr->divertedFileNativeRep);
NativeFreeInternalRep(tvdlPtr->divertedFileNativeRep);
+
} else {
- /*
- * Remove the temporary file we created. Note, we may crash
- * here because encodings have been taken down already.
+ /*
+ * Remove the temporary file we created. Note, we may crash here
+ * because encodings have been taken down already.
*/
+
if (tvdlPtr->divertedFilesystem->deleteFileProc(tvdlPtr->divertedFile)
- != TCL_OK) {
- /*
+ != TCL_OK) {
+ /*
* The above may have failed because the filesystem, or something
* it depends upon (e.g. encodings) have been taken down because
* Tcl is exiting.
- *
- * We may need to work out how to delete this file more
- * robustly (or give the filesystem the information it needs
- * to delete the file more robustly).
- *
- * In particular, one problem might be that the filesystem
- * cannot extract the information it needs from the above
- * path object because Tcl's entire filesystem apparatus
- * (the code in this file) has been finalized, and it
- * refuses to pass the internal representation to the
- * filesystem.
+ *
+ * We may need to work out how to delete this file more robustly
+ * (or give the filesystem the information it needs to delete the
+ * file more robustly).
+ *
+ * In particular, one problem might be that the filesystem cannot
+ * extract the information it needs from the above path object
+ * because Tcl's entire filesystem apparatus (the code in this
+ * file) has been finalized, and it refuses to pass the internal
+ * representation to the filesystem.
*/
}
-
- /*
- * And free up the allocations. This will also of course remove
- * a refCount from the Tcl_Filesystem to which this file belongs,
- * which could then free up the filesystem if we are exiting.
+
+ /*
+ * And free up the allocations. This will also of course remove a
+ * refCount from the Tcl_Filesystem to which this file belongs, which
+ * could then free up the filesystem if we are exiting.
*/
+
Tcl_DecrRefCount(tvdlPtr->divertedFile);
}
@@ -3137,57 +3530,58 @@ FSUnloadTempFile(loadHandle)
*
* Tcl_FSLink --
*
- * This function replaces the library version of readlink() and
- * can also be used to make links. The appropriate function for
- * the filesystem to which pathPtr belongs will be called.
+ * This function replaces the library version of readlink() and can also
+ * be used to make links. The appropriate function for the filesystem to
+ * which pathPtr belongs will be called.
*
* Results:
- * If toPtr is NULL, then the result is a Tcl_Obj specifying the
- * contents of the symbolic link given by 'pathPtr', or NULL if
- * the symbolic link could not be read. The result is owned by
- * the caller, which should call Tcl_DecrRefCount when the result
- * is no longer needed.
- *
- * If toPtr is non-NULL, then the result is toPtr if the link action
- * was successful, or NULL if not. In this case the result has no
- * additional reference count, and need not be freed. The actual
- * action to perform is given by the 'linkAction' flags, which is
- * an or'd combination of:
- *
- * TCL_CREATE_SYMBOLIC_LINK
- * TCL_CREATE_HARD_LINK
- *
- * Note that most filesystems will not support linking across
- * to different filesystems, so this function will usually
- * fail unless toPtr is in the same FS as pathPtr.
- *
+ * If toPtr is NULL, then the result is a Tcl_Obj specifying the contents
+ * of the symbolic link given by 'pathPtr', or NULL if the symbolic link
+ * could not be read. The result is owned by the caller, which should
+ * call Tcl_DecrRefCount when the result is no longer needed.
+ *
+ * If toPtr is non-NULL, then the result is toPtr if the link action was
+ * successful, or NULL if not. In this case the result has no additional
+ * reference count, and need not be freed. The actual action to perform
+ * is given by the 'linkAction' flags, which is an or'd combination of:
+ *
+ * TCL_CREATE_SYMBOLIC_LINK
+ * TCL_CREATE_HARD_LINK
+ *
+ * Note that most filesystems will not support linking across to
+ * different filesystems, so this function will usually fail unless toPtr
+ * is in the same FS as pathPtr.
+ *
* Side effects:
- * See readlink() documentation. A new filesystem link
- * object may appear
+ * See readlink() documentation. A new filesystem link object may appear.
*
*---------------------------------------------------------------------------
*/
Tcl_Obj *
-Tcl_FSLink(pathPtr, toPtr, linkAction)
- Tcl_Obj *pathPtr; /* Path of file to readlink or link */
- Tcl_Obj *toPtr; /* NULL or path to be linked to */
- int linkAction; /* Action to perform */
+Tcl_FSLink(
+ Tcl_Obj *pathPtr, /* Path of file to readlink or link */
+ Tcl_Obj *toPtr, /* NULL or path to be linked to */
+ int linkAction) /* Action to perform */
{
- Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
+ const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
+
if (fsPtr != NULL) {
Tcl_FSLinkProc *proc = fsPtr->linkProc;
+
if (proc != NULL) {
return (*proc)(pathPtr, toPtr, linkAction);
}
}
+
/*
- * If S_IFLNK isn't defined it means that the machine doesn't
- * support symbolic links, so the file can't possibly be a
- * symbolic link. Generate an EINVAL error, which is what
- * happens on machines that do support symbolic links when
- * you invoke readlink on a file that isn't a symbolic link.
+ * If S_IFLNK isn't defined it means that the machine doesn't support
+ * symbolic links, so the file can't possibly be a symbolic link. Generate
+ * an EINVAL error, which is what happens on machines that do support
+ * symbolic links when you invoke readlink on a file that isn't a symbolic
+ * link.
*/
+
#ifndef S_IFLNK
errno = EINVAL;
#else
@@ -3201,17 +3595,16 @@ Tcl_FSLink(pathPtr, toPtr, linkAction)
*
* Tcl_FSListVolumes --
*
- * Lists the currently mounted volumes. The chain of functions
- * that have been "inserted" into the filesystem will be called in
- * succession; each may return a list of volumes, all of which are
- * added to the result until all mounted file systems are listed.
- *
- * Notice that we assume the lists returned by each filesystem
- * (if non NULL) have been given a refCount for us already.
- * However, we are NOT allowed to hang on to the list itself
- * (it belongs to the filesystem we called). Therefore we
- * quite naturally add its contents to the result we are
- * building, and then decrement the refCount.
+ * Lists the currently mounted volumes. The chain of functions that have
+ * been "inserted" into the filesystem will be called in succession; each
+ * may return a list of volumes, all of which are added to the result
+ * until all mounted file systems are listed.
+ *
+ * Notice that we assume the lists returned by each filesystem (if non
+ * NULL) have been given a refCount for us already. However, we are NOT
+ * allowed to hang on to the list itself (it belongs to the filesystem we
+ * called). Therefore we quite naturally add its contents to the result
+ * we are building, and then decrement the refCount.
*
* Results:
* The list of volumes, in an object which has refCount 0.
@@ -3227,12 +3620,12 @@ Tcl_FSListVolumes(void)
{
FilesystemRecord *fsRecPtr;
Tcl_Obj *resultPtr = Tcl_NewObj();
-
+
/*
- * Call each of the "listVolumes" function in succession.
- * A non-NULL return value indicates the particular function has
- * succeeded. We call all the functions registered, since we want
- * a list of all drives from all filesystems.
+ * Call each of the "listVolumes" function in succession. A non-NULL
+ * return value indicates the particular function has succeeded. We call
+ * all the functions registered, since we want a list of all drives from
+ * all filesystems.
*/
fsRecPtr = FsGetFirstFilesystem();
@@ -3247,7 +3640,7 @@ Tcl_FSListVolumes(void)
}
fsRecPtr = fsRecPtr->nextPtr;
}
-
+
return resultPtr;
}
@@ -3256,13 +3649,12 @@ Tcl_FSListVolumes(void)
*
* FsListMounts --
*
- * List all mounts within the given directory, which match the
- * given pattern.
+ * List all mounts within the given directory, which match the given
+ * pattern.
*
* Results:
- * The list of mounts, in a list object which has refCount 0, or
- * NULL if we didn't even find any filesystems to try to list
- * mounts.
+ * The list of mounts, in a list object which has refCount 0, or NULL if
+ * we didn't even find any filesystems to try to list mounts.
*
* Side effects:
* None
@@ -3270,27 +3662,27 @@ Tcl_FSListVolumes(void)
*---------------------------------------------------------------------------
*/
-static Tcl_Obj*
-FsListMounts(pathPtr, pattern)
- Tcl_Obj *pathPtr; /* Contains path to directory to search. */
- CONST char *pattern; /* Pattern to match against. */
+static Tcl_Obj *
+FsListMounts(
+ Tcl_Obj *pathPtr, /* Contains path to directory to search. */
+ const char *pattern) /* Pattern to match against. */
{
FilesystemRecord *fsRecPtr;
Tcl_GlobTypeData mountsOnly = { TCL_GLOB_TYPE_MOUNT, 0, NULL, NULL };
Tcl_Obj *resultPtr = NULL;
-
+
/*
- * Call each of the "listMounts" functions in succession.
- * A non-NULL return value indicates the particular function has
- * succeeded. We call all the functions registered, since we want
- * a list from each filesystems.
+ * Call each of the "matchInDirectory" functions in succession, with the
+ * specific type information 'mountsOnly'. A non-NULL return value
+ * indicates the particular function has succeeded. We call all the
+ * functions registered, since we want a list from each filesystems.
*/
fsRecPtr = FsGetFirstFilesystem();
while (fsRecPtr != NULL) {
if (fsRecPtr->fsPtr != &tclNativeFilesystem) {
- Tcl_FSMatchInDirectoryProc *proc =
- fsRecPtr->fsPtr->matchInDirectoryProc;
+ Tcl_FSMatchInDirectoryProc *proc =
+ fsRecPtr->fsPtr->matchInDirectoryProc;
if (proc != NULL) {
if (resultPtr == NULL) {
resultPtr = Tcl_NewObj();
@@ -3300,7 +3692,7 @@ FsListMounts(pathPtr, pattern)
}
fsRecPtr = fsRecPtr->nextPtr;
}
-
+
return resultPtr;
}
@@ -3309,14 +3701,14 @@ FsListMounts(pathPtr, pattern)
*
* Tcl_FSSplitPath --
*
- * This function takes the given Tcl_Obj, which should be a valid
- * path, and returns a Tcl List object containing each segment of
- * that path as an element.
+ * This function takes the given Tcl_Obj, which should be a valid path,
+ * and returns a Tcl List object containing each segment of that path as
+ * an element.
*
* Results:
- * Returns list object with refCount of zero. If the passed in
- * lenPtr is non-NULL, we use it to return the number of elements
- * in the returned list.
+ * Returns list object with refCount of zero. If the passed in lenPtr is
+ * non-NULL, we use it to return the number of elements in the returned
+ * list.
*
* Side effects:
* None.
@@ -3324,23 +3716,23 @@ FsListMounts(pathPtr, pattern)
*---------------------------------------------------------------------------
*/
-Tcl_Obj*
-Tcl_FSSplitPath(pathPtr, lenPtr)
- Tcl_Obj *pathPtr; /* Path to split. */
- int *lenPtr; /* int to store number of path elements. */
+Tcl_Obj *
+Tcl_FSSplitPath(
+ Tcl_Obj *pathPtr, /* Path to split. */
+ int *lenPtr) /* int to store number of path elements. */
{
- Tcl_Obj *result = NULL; /* Needed only to prevent gcc warnings. */
+ Tcl_Obj *result = NULL; /* Needed only to prevent gcc warnings. */
Tcl_Filesystem *fsPtr;
char separator = '/';
int driveNameLength;
char *p;
-
+
/*
- * Perform platform specific splitting.
+ * Perform platform specific splitting.
*/
- if (FSGetPathType(pathPtr, &fsPtr, &driveNameLength)
- == TCL_PATH_ABSOLUTE) {
+ if (TclFSGetPathType(pathPtr, &fsPtr,
+ &driveNameLength) == TCL_PATH_ABSOLUTE) {
if (fsPtr == &tclNativeFilesystem) {
return TclpNativeSplitPath(pathPtr, lenPtr);
}
@@ -3348,27 +3740,35 @@ Tcl_FSSplitPath(pathPtr, lenPtr)
return TclpNativeSplitPath(pathPtr, lenPtr);
}
- /* We assume separators are single characters */
+ /*
+ * We assume separators are single characters.
+ */
+
if (fsPtr->filesystemSeparatorProc != NULL) {
Tcl_Obj *sep = (*fsPtr->filesystemSeparatorProc)(pathPtr);
if (sep != NULL) {
+ Tcl_IncrRefCount(sep);
separator = Tcl_GetString(sep)[0];
+ Tcl_DecrRefCount(sep);
}
}
-
- /*
- * Place the drive name as first element of the
- * result list. The drive name may contain strange
- * characters, like colons and multiple forward slashes
- * (for example 'ftp://' is a valid vfs drive name)
+
+ /*
+ * Place the drive name as first element of the result list. The drive
+ * name may contain strange characters, like colons and multiple forward
+ * slashes (for example 'ftp://' is a valid vfs drive name)
*/
+
result = Tcl_NewObj();
p = Tcl_GetString(pathPtr);
- Tcl_ListObjAppendElement(NULL, result,
- Tcl_NewStringObj(p, driveNameLength));
- p+= driveNameLength;
-
- /* Add the remaining path elements to the list */
+ Tcl_ListObjAppendElement(NULL, result,
+ Tcl_NewStringObj(p, driveNameLength));
+ p += driveNameLength;
+
+ /*
+ * Add the remaining path elements to the list.
+ */
+
for (;;) {
char *elementStart = p;
int length;
@@ -3379,7 +3779,7 @@ Tcl_FSSplitPath(pathPtr, lenPtr)
if (length > 0) {
Tcl_Obj *nextElt;
if (elementStart[0] == '~') {
- nextElt = Tcl_NewStringObj("./",2);
+ TclNewLiteralStringObj(nextElt, "./");
Tcl_AppendToObj(nextElt, elementStart, length);
} else {
nextElt = Tcl_NewStringObj(elementStart, length);
@@ -3390,23 +3790,23 @@ Tcl_FSSplitPath(pathPtr, lenPtr)
break;
}
}
-
+
/*
* Compute the number of elements in the result.
*/
if (lenPtr != NULL) {
- Tcl_ListObjLength(NULL, result, lenPtr);
+ TclListObjLength(NULL, result, lenPtr);
}
return result;
}
/* Simple helper function */
-Tcl_Obj*
-TclFSInternalToNormalized(fromFilesystem, clientData, fsRecPtrPtr)
- Tcl_Filesystem *fromFilesystem;
- ClientData clientData;
- FilesystemRecord **fsRecPtrPtr;
+Tcl_Obj *
+TclFSInternalToNormalized(
+ Tcl_Filesystem *fromFilesystem,
+ ClientData clientData,
+ FilesystemRecord **fsRecPtrPtr)
{
FilesystemRecord *fsRecPtr = FsGetFirstFilesystem();
@@ -3417,9 +3817,9 @@ TclFSInternalToNormalized(fromFilesystem, clientData, fsRecPtrPtr)
}
fsRecPtr = fsRecPtr->nextPtr;
}
-
- if ((fsRecPtr != NULL)
- && (fromFilesystem->internalToNormalizedProc != NULL)) {
+
+ if ((fsRecPtr != NULL)
+ && (fromFilesystem->internalToNormalizedProc != NULL)) {
return (*fromFilesystem->internalToNormalizedProc)(clientData);
} else {
return NULL;
@@ -3429,15 +3829,15 @@ TclFSInternalToNormalized(fromFilesystem, clientData, fsRecPtrPtr)
/*
*----------------------------------------------------------------------
*
- * GetPathType --
+ * TclGetPathType --
*
* Helper function used by FSGetPathType.
*
* Results:
* Returns one of TCL_PATH_ABSOLUTE, TCL_PATH_RELATIVE, or
- * TCL_PATH_VOLUME_RELATIVE. The filesystem reference will
- * be set if and only if it is non-NULL and the function's
- * return value is TCL_PATH_ABSOLUTE.
+ * TCL_PATH_VOLUME_RELATIVE. The filesystem reference will be set if and
+ * only if it is non-NULL and the function's return value is
+ * TCL_PATH_ABSOLUTE.
*
* Side effects:
* None.
@@ -3445,64 +3845,129 @@ TclFSInternalToNormalized(fromFilesystem, clientData, fsRecPtrPtr)
*----------------------------------------------------------------------
*/
-static Tcl_PathType
-GetPathType(pathObjPtr, filesystemPtrPtr, driveNameLengthPtr, driveNameRef)
- Tcl_Obj *pathObjPtr;
- Tcl_Filesystem **filesystemPtrPtr;
- int *driveNameLengthPtr;
- Tcl_Obj **driveNameRef;
+Tcl_PathType
+TclGetPathType(
+ Tcl_Obj *pathPtr, /* Path to determine type for */
+ Tcl_Filesystem **filesystemPtrPtr,
+ /* If absolute path and this is not NULL, then
+ * set to the filesystem which claims this
+ * path. */
+ int *driveNameLengthPtr, /* If the path is absolute, and this is
+ * non-NULL, then set to the length of the
+ * driveName. */
+ Tcl_Obj **driveNameRef) /* If the path is absolute, and this is
+ * non-NULL, then set to the name of the
+ * drive, network-volume which contains the
+ * path, already with a refCount for the
+ * caller. */
{
- FilesystemRecord *fsRecPtr;
int pathLen;
char *path;
+ Tcl_PathType type;
+
+ path = Tcl_GetStringFromObj(pathPtr, &pathLen);
+
+ type = TclFSNonnativePathType(path, pathLen, filesystemPtrPtr,
+ driveNameLengthPtr, driveNameRef);
+
+ if (type != TCL_PATH_ABSOLUTE) {
+ type = TclpGetNativePathType(pathPtr, driveNameLengthPtr,
+ driveNameRef);
+ if ((type == TCL_PATH_ABSOLUTE) && (filesystemPtrPtr != NULL)) {
+ *filesystemPtrPtr = &tclNativeFilesystem;
+ }
+ }
+ return type;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclFSNonnativePathType --
+ *
+ * Helper function used by TclGetPathType. Its purpose is to check
+ * whether the given path starts with a string which corresponds to a
+ * file volume in any registered filesystem except the native one. For
+ * speed and historical reasons the native filesystem has special
+ * hard-coded checks dotted here and there in the filesystem code.
+ *
+ * Results:
+ * Returns one of TCL_PATH_ABSOLUTE or TCL_PATH_RELATIVE. The filesystem
+ * reference will be set if and only if it is non-NULL and the function's
+ * return value is TCL_PATH_ABSOLUTE.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_PathType
+TclFSNonnativePathType(
+ const char *path, /* Path to determine type for */
+ int pathLen, /* Length of the path */
+ Tcl_Filesystem **filesystemPtrPtr,
+ /* If absolute path and this is not NULL, then
+ * set to the filesystem which claims this
+ * path. */
+ int *driveNameLengthPtr, /* If the path is absolute, and this is
+ * non-NULL, then set to the length of the
+ * driveName. */
+ Tcl_Obj **driveNameRef) /* If the path is absolute, and this is
+ * non-NULL, then set to the name of the
+ * drive, network-volume which contains the
+ * path, already with a refCount for the
+ * caller. */
+{
+ FilesystemRecord *fsRecPtr;
Tcl_PathType type = TCL_PATH_RELATIVE;
-
- path = Tcl_GetStringFromObj(pathObjPtr, &pathLen);
/*
- * Call each of the "listVolumes" function in succession, checking
- * whether the given path is an absolute path on any of the volumes
- * returned (this is done by checking whether the path's prefix
- * matches).
+ * Call each of the "listVolumes" function in succession, checking whether
+ * the given path is an absolute path on any of the volumes returned (this
+ * is done by checking whether the path's prefix matches).
*/
fsRecPtr = FsGetFirstFilesystem();
while (fsRecPtr != NULL) {
Tcl_FSListVolumesProc *proc = fsRecPtr->fsPtr->listVolumesProc;
- /*
+
+ /*
* We want to skip the native filesystem in this loop because
- * otherwise we won't necessarily pass all the Tcl testsuite --
- * this is because some of the tests artificially change the
- * current platform (between mac, win, unix) but the list
- * of volumes we get by calling (*proc) will reflect the current
- * (real) platform only and this may cause some tests to fail.
- * In particular, on unix '/' will match the beginning of
- * certain absolute Windows paths starting '//' and those tests
- * will go wrong.
- *
- * Besides these test-suite issues, there is one other reason
- * to skip the native filesystem --- since the tclFilename.c
- * code has nice fast 'absolute path' checkers, we don't want
- * to waste time repeating that effort here, and this
- * function is actually called quite often, so if we can
- * save the overhead of the native filesystem returning us
- * a list of volumes all the time, it is better.
+ * otherwise we won't necessarily pass all the Tcl testsuite -- this
+ * is because some of the tests artificially change the current
+ * platform (between win, unix) but the list of volumes we get by
+ * calling (*proc) will reflect the current (real) platform only and
+ * this may cause some tests to fail. In particular, on unix '/' will
+ * match the beginning of certain absolute Windows paths starting '//'
+ * and those tests will go wrong.
+ *
+ * Besides these test-suite issues, there is one other reason to skip
+ * the native filesystem --- since the tclFilename.c code has nice
+ * fast 'absolute path' checkers, we don't want to waste time
+ * repeating that effort here, and this function is actually called
+ * quite often, so if we can save the overhead of the native
+ * filesystem returning us a list of volumes all the time, it is
+ * better.
*/
+
if ((fsRecPtr->fsPtr != &tclNativeFilesystem) && (proc != NULL)) {
int numVolumes;
Tcl_Obj *thisFsVolumes = (*proc)();
+
if (thisFsVolumes != NULL) {
- if (Tcl_ListObjLength(NULL, thisFsVolumes,
- &numVolumes) != TCL_OK) {
- /*
- * This is VERY bad; the Tcl_FSListVolumesProc
- * didn't return a valid list. Set numVolumes to
- * -1 so that we skip the while loop below and just
- * return with the current value of 'type'.
- *
- * It would be better if we could signal an error
- * here (but panic seems a bit excessive).
+ if (Tcl_ListObjLength(NULL, thisFsVolumes, &numVolumes)
+ != TCL_OK) {
+ /*
+ * This is VERY bad; the Tcl_FSListVolumesProc didn't
+ * return a valid list. Set numVolumes to -1 so that we
+ * skip the while loop below and just return with the
+ * current value of 'type'.
+ *
+ * It would be better if we could signal an error here
+ * (but Tcl_Panic seems a bit excessive).
*/
+
numVolumes = -1;
}
while (numVolumes > 0) {
@@ -3533,21 +3998,15 @@ GetPathType(pathObjPtr, filesystemPtrPtr, driveNameLengthPtr, driveNameRef)
}
Tcl_DecrRefCount(thisFsVolumes);
if (type == TCL_PATH_ABSOLUTE) {
- /* We don't need to examine any more filesystems */
+ /*
+ * We don't need to examine any more filesystems.
+ */
break;
}
}
}
fsRecPtr = fsRecPtr->nextPtr;
}
-
- if (type != TCL_PATH_ABSOLUTE) {
- type = TclpGetNativePathType(pathObjPtr, driveNameLengthPtr,
- driveNameRef);
- if ((type == TCL_PATH_ABSOLUTE) && (filesystemPtrPtr != NULL)) {
- *filesystemPtrPtr = &tclNativeFilesystem;
- }
- }
return type;
}
@@ -3556,12 +4015,12 @@ GetPathType(pathObjPtr, filesystemPtrPtr, driveNameLengthPtr, driveNameRef)
*
* Tcl_FSRenameFile --
*
- * If the two paths given belong to the same filesystem, we call
- * that filesystems rename function. Otherwise we simply
- * return the posix error 'EXDEV', and -1.
+ * If the two paths given belong to the same filesystem, we call that
+ * filesystems rename function. Otherwise we simply return the POSIX
+ * error 'EXDEV', and -1.
*
* Results:
- * Standard Tcl error code if a function was called.
+ * Standard Tcl error code if a function was called.
*
* Side effects:
* A file may be renamed.
@@ -3570,21 +4029,21 @@ GetPathType(pathObjPtr, filesystemPtrPtr, driveNameLengthPtr, driveNameRef)
*/
int
-Tcl_FSRenameFile(srcPathPtr, destPathPtr)
- Tcl_Obj* srcPathPtr; /* Pathname of file or dir to be renamed
+Tcl_FSRenameFile(
+ Tcl_Obj* srcPathPtr, /* Pathname of file or dir to be renamed
* (UTF-8). */
- Tcl_Obj *destPathPtr; /* New pathname of file or directory
+ Tcl_Obj *destPathPtr) /* New pathname of file or directory
* (UTF-8). */
{
int retVal = -1;
- Tcl_Filesystem *fsPtr, *fsPtr2;
+ const Tcl_Filesystem *fsPtr, *fsPtr2;
fsPtr = Tcl_FSGetFileSystemForPath(srcPathPtr);
fsPtr2 = Tcl_FSGetFileSystemForPath(destPathPtr);
- if (fsPtr == fsPtr2 && fsPtr != NULL) {
+ if ((fsPtr == fsPtr2) && (fsPtr != NULL)) {
Tcl_FSRenameFileProc *proc = fsPtr->renameFileProc;
if (proc != NULL) {
- retVal = (*proc)(srcPathPtr, destPathPtr);
+ retVal = (*proc)(srcPathPtr, destPathPtr);
}
}
if (retVal == -1) {
@@ -3598,16 +4057,16 @@ Tcl_FSRenameFile(srcPathPtr, destPathPtr)
*
* Tcl_FSCopyFile --
*
- * If the two paths given belong to the same filesystem, we call
- * that filesystem's copy function. Otherwise we simply
- * return the posix error 'EXDEV', and -1.
- *
- * Note that in the native filesystems, 'copyFileProc' is defined
- * to copy soft links (i.e. it copies the links themselves, not
- * the things they point to).
+ * If the two paths given belong to the same filesystem, we call that
+ * filesystem's copy function. Otherwise we simply return the POSIX error
+ * 'EXDEV', and -1.
+ *
+ * Note that in the native filesystems, 'copyFileProc' is defined to copy
+ * soft links (i.e. it copies the links themselves, not the things they
+ * point to).
*
* Results:
- * Standard Tcl error code if a function was called.
+ * Standard Tcl error code if a function was called.
*
* Side effects:
* A file may be copied.
@@ -3615,13 +4074,13 @@ Tcl_FSRenameFile(srcPathPtr, destPathPtr)
*---------------------------------------------------------------------------
*/
-int
-Tcl_FSCopyFile(srcPathPtr, destPathPtr)
- Tcl_Obj* srcPathPtr; /* Pathname of file to be copied (UTF-8). */
- Tcl_Obj *destPathPtr; /* Pathname of file to copy to (UTF-8). */
+int
+Tcl_FSCopyFile(
+ Tcl_Obj *srcPathPtr, /* Pathname of file to be copied (UTF-8). */
+ Tcl_Obj *destPathPtr) /* Pathname of file to copy to (UTF-8). */
{
int retVal = -1;
- Tcl_Filesystem *fsPtr, *fsPtr2;
+ const Tcl_Filesystem *fsPtr, *fsPtr2;
fsPtr = Tcl_FSGetFileSystemForPath(srcPathPtr);
fsPtr2 = Tcl_FSGetFileSystemForPath(destPathPtr);
@@ -3642,64 +4101,75 @@ Tcl_FSCopyFile(srcPathPtr, destPathPtr)
*
* TclCrossFilesystemCopy --
*
- * Helper for above function, and for Tcl_FSLoadFile, to copy
- * files from one filesystem to another. This function will
- * overwrite the target file if it already exists.
+ * Helper for above function, and for Tcl_FSLoadFile, to copy files from
+ * one filesystem to another. This function will overwrite the target
+ * file if it already exists.
*
* Results:
- * Standard Tcl error code.
+ * Standard Tcl error code.
*
* Side effects:
* A file may be created.
*
*---------------------------------------------------------------------------
*/
-int
-TclCrossFilesystemCopy(interp, source, target)
- Tcl_Interp *interp; /* For error messages */
- Tcl_Obj *source; /* Pathname of file to be copied (UTF-8). */
- Tcl_Obj *target; /* Pathname of file to copy to (UTF-8). */
+int
+TclCrossFilesystemCopy(
+ Tcl_Interp *interp, /* For error messages */
+ Tcl_Obj *source, /* Pathname of file to be copied (UTF-8). */
+ Tcl_Obj *target) /* Pathname of file to copy to (UTF-8). */
{
int result = TCL_ERROR;
int prot = 0666;
-
- Tcl_Channel out = Tcl_FSOpenFileChannel(interp, target, "w", prot);
- if (out != NULL) {
- /* It looks like we can copy it over */
- Tcl_Channel in = Tcl_FSOpenFileChannel(interp, source,
- "r", prot);
- if (in == NULL) {
- /* This is very strange, we checked this above */
- Tcl_Close(interp, out);
- } else {
- Tcl_StatBuf sourceStatBuf;
- struct utimbuf tval;
- /*
- * Copy it synchronously. We might wish to add an
- * asynchronous option to support vfs's which are
- * slow (e.g. network sockets).
- */
- Tcl_SetChannelOption(interp, in, "-translation", "binary");
- Tcl_SetChannelOption(interp, out, "-translation", "binary");
-
- if (TclCopyChannel(interp, in, out, -1, NULL) == TCL_OK) {
- result = TCL_OK;
- }
- /*
- * If the copy failed, assume that copy channel left
- * a good error message.
- */
- Tcl_Close(interp, in);
- Tcl_Close(interp, out);
-
- /* Set modification date of copied file */
- if (Tcl_FSLstat(source, &sourceStatBuf) == 0) {
- tval.actime = sourceStatBuf.st_atime;
- tval.modtime = sourceStatBuf.st_mtime;
- Tcl_FSUtime(target, &tval);
- }
- }
+ Tcl_Channel in, out;
+ Tcl_StatBuf sourceStatBuf;
+ struct utimbuf tval;
+
+ out = Tcl_FSOpenFileChannel(interp, target, "wb", prot);
+ if (out == NULL) {
+ /*
+ * It looks like we cannot copy it over. Bail out...
+ */
+ goto done;
+ }
+
+ in = Tcl_FSOpenFileChannel(interp, source, "rb", prot);
+ if (in == NULL) {
+ /*
+ * This is very strange, caller should have checked this...
+ */
+
+ Tcl_Close(interp, out);
+ goto done;
+ }
+
+ /*
+ * Copy it synchronously. We might wish to add an asynchronous option to
+ * support vfs's which are slow (e.g. network sockets).
+ */
+
+ if (TclCopyChannel(interp, in, out, -1, NULL) == TCL_OK) {
+ result = TCL_OK;
+ }
+
+ /*
+ * If the copy failed, assume that copy channel left a good error message.
+ */
+
+ Tcl_Close(interp, in);
+ Tcl_Close(interp, out);
+
+ /*
+ * Set modification date of copied file.
+ */
+
+ if (Tcl_FSLstat(source, &sourceStatBuf) == 0) {
+ tval.actime = sourceStatBuf.st_atime;
+ tval.modtime = sourceStatBuf.st_mtime;
+ Tcl_FSUtime(target, &tval);
}
+
+ done:
return result;
}
@@ -3708,11 +4178,11 @@ TclCrossFilesystemCopy(interp, source, target)
*
* Tcl_FSDeleteFile --
*
- * The appropriate function for the filesystem to which pathPtr
- * belongs will be called.
+ * The appropriate function for the filesystem to which pathPtr belongs
+ * will be called.
*
* Results:
- * Standard Tcl error code.
+ * Standard Tcl error code.
*
* Side effects:
* A file may be deleted.
@@ -3721,10 +4191,10 @@ TclCrossFilesystemCopy(interp, source, target)
*/
int
-Tcl_FSDeleteFile(pathPtr)
- Tcl_Obj *pathPtr; /* Pathname of file to be removed (UTF-8). */
+Tcl_FSDeleteFile(
+ Tcl_Obj *pathPtr) /* Pathname of file to be removed (UTF-8). */
{
- Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
+ const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
if (fsPtr != NULL) {
Tcl_FSDeleteFileProc *proc = fsPtr->deleteFileProc;
if (proc != NULL) {
@@ -3740,11 +4210,11 @@ Tcl_FSDeleteFile(pathPtr)
*
* Tcl_FSCreateDirectory --
*
- * The appropriate function for the filesystem to which pathPtr
- * belongs will be called.
+ * The appropriate function for the filesystem to which pathPtr belongs
+ * will be called.
*
* Results:
- * Standard Tcl error code.
+ * Standard Tcl error code.
*
* Side effects:
* A directory may be created.
@@ -3753,10 +4223,10 @@ Tcl_FSDeleteFile(pathPtr)
*/
int
-Tcl_FSCreateDirectory(pathPtr)
- Tcl_Obj *pathPtr; /* Pathname of directory to create (UTF-8). */
+Tcl_FSCreateDirectory(
+ Tcl_Obj *pathPtr) /* Pathname of directory to create (UTF-8). */
{
- Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
+ const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
if (fsPtr != NULL) {
Tcl_FSCreateDirectoryProc *proc = fsPtr->createDirectoryProc;
if (proc != NULL) {
@@ -3772,12 +4242,12 @@ Tcl_FSCreateDirectory(pathPtr)
*
* Tcl_FSCopyDirectory --
*
- * If the two paths given belong to the same filesystem, we call
- * that filesystems copy-directory function. Otherwise we simply
- * return the posix error 'EXDEV', and -1.
+ * If the two paths given belong to the same filesystem, we call that
+ * filesystems copy-directory function. Otherwise we simply return the
+ * POSIX error 'EXDEV', and -1.
*
* Results:
- * Standard Tcl error code if a function was called.
+ * Standard Tcl error code if a function was called.
*
* Side effects:
* A directory may be copied.
@@ -3786,16 +4256,16 @@ Tcl_FSCreateDirectory(pathPtr)
*/
int
-Tcl_FSCopyDirectory(srcPathPtr, destPathPtr, errorPtr)
- Tcl_Obj* srcPathPtr; /* Pathname of directory to be copied
+Tcl_FSCopyDirectory(
+ Tcl_Obj* srcPathPtr, /* Pathname of directory to be copied
* (UTF-8). */
- Tcl_Obj *destPathPtr; /* Pathname of target directory (UTF-8). */
- Tcl_Obj **errorPtr; /* If non-NULL, then will be set to a
- * new object containing name of file
- * causing error, with refCount 1. */
+ Tcl_Obj *destPathPtr, /* Pathname of target directory (UTF-8). */
+ Tcl_Obj **errorPtr) /* If non-NULL, then will be set to a new
+ * object containing name of file causing
+ * error, with refCount 1. */
{
int retVal = -1;
- Tcl_Filesystem *fsPtr, *fsPtr2;
+ const Tcl_Filesystem *fsPtr, *fsPtr2;
fsPtr = Tcl_FSGetFileSystemForPath(srcPathPtr);
fsPtr2 = Tcl_FSGetFileSystemForPath(destPathPtr);
@@ -3816,11 +4286,11 @@ Tcl_FSCopyDirectory(srcPathPtr, destPathPtr, errorPtr)
*
* Tcl_FSRemoveDirectory --
*
- * The appropriate function for the filesystem to which pathPtr
- * belongs will be called.
+ * The appropriate function for the filesystem to which pathPtr belongs
+ * will be called.
*
* Results:
- * Standard Tcl error code.
+ * Standard Tcl error code.
*
* Side effects:
* A directory may be deleted.
@@ -3829,49 +4299,53 @@ Tcl_FSCopyDirectory(srcPathPtr, destPathPtr, errorPtr)
*/
int
-Tcl_FSRemoveDirectory(pathPtr, recursive, errorPtr)
- Tcl_Obj *pathPtr; /* Pathname of directory to be removed
+Tcl_FSRemoveDirectory(
+ Tcl_Obj *pathPtr, /* Pathname of directory to be removed
* (UTF-8). */
- int recursive; /* If non-zero, removes directories that
- * are nonempty. Otherwise, will only remove
- * empty directories. */
- Tcl_Obj **errorPtr; /* If non-NULL, then will be set to a
- * new object containing name of file
- * causing error, with refCount 1. */
+ int recursive, /* If non-zero, removes directories that are
+ * nonempty. Otherwise, will only remove empty
+ * directories. */
+ Tcl_Obj **errorPtr) /* If non-NULL, then will be set to a new
+ * object containing name of file causing
+ * error, with refCount 1. */
{
- Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
- if (fsPtr != NULL) {
+ const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
+ if (fsPtr != NULL && fsPtr->removeDirectoryProc != NULL) {
Tcl_FSRemoveDirectoryProc *proc = fsPtr->removeDirectoryProc;
- if (proc != NULL) {
- if (recursive) {
- /*
- * We check whether the cwd lies inside this directory
- * and move it if it does.
- */
- Tcl_Obj *cwdPtr = Tcl_FSGetCwd(NULL);
- if (cwdPtr != NULL) {
- char *cwdStr, *normPathStr;
- int cwdLen, normLen;
- Tcl_Obj *normPath = Tcl_FSGetNormalizedPath(NULL, pathPtr);
- if (normPath != NULL) {
- normPathStr = Tcl_GetStringFromObj(normPath, &normLen);
- cwdStr = Tcl_GetStringFromObj(cwdPtr, &cwdLen);
- if ((cwdLen >= normLen) && (strncmp(normPathStr,
- cwdStr, (size_t) normLen) == 0)) {
- /*
- * the cwd is inside the directory, so we
- * perform a 'cd [file dirname $path]'
- */
- Tcl_Obj *dirPtr = TclFileDirname(NULL, pathPtr);
- Tcl_FSChdir(dirPtr);
- Tcl_DecrRefCount(dirPtr);
- }
+ if (recursive) {
+ /*
+ * We check whether the cwd lies inside this directory and move it
+ * if it does.
+ */
+
+ Tcl_Obj *cwdPtr = Tcl_FSGetCwd(NULL);
+
+ if (cwdPtr != NULL) {
+ char *cwdStr, *normPathStr;
+ int cwdLen, normLen;
+ Tcl_Obj *normPath = Tcl_FSGetNormalizedPath(NULL, pathPtr);
+
+ if (normPath != NULL) {
+ normPathStr = Tcl_GetStringFromObj(normPath, &normLen);
+ cwdStr = Tcl_GetStringFromObj(cwdPtr, &cwdLen);
+ if ((cwdLen >= normLen) && (strncmp(normPathStr, cwdStr,
+ (size_t) normLen) == 0)) {
+ /*
+ * The cwd is inside the directory, so we perform a
+ * 'cd [file dirname $path]'.
+ */
+
+ Tcl_Obj *dirPtr = TclPathPart(NULL, pathPtr,
+ TCL_PATH_DIRNAME);
+
+ Tcl_FSChdir(dirPtr);
+ Tcl_DecrRefCount(dirPtr);
}
- Tcl_DecrRefCount(cwdPtr);
}
+ Tcl_DecrRefCount(cwdPtr);
}
- return (*proc)(pathPtr, recursive, errorPtr);
}
+ return (*proc)(pathPtr, recursive, errorPtr);
}
Tcl_SetErrno(ENOENT);
return -1;
@@ -3882,13 +4356,13 @@ Tcl_FSRemoveDirectory(pathPtr, recursive, errorPtr)
*
* Tcl_FSGetFileSystemForPath --
*
- * This function determines which filesystem to use for a
- * particular path object, and returns the filesystem which
- * accepts this file. If no filesystem will accept this object
- * as a valid file path, then NULL is returned.
+ * This function determines which filesystem to use for a particular path
+ * object, and returns the filesystem which accepts this file. If no
+ * filesystem will accept this object as a valid file path, then NULL is
+ * returned.
*
* Results:
-.* NULL or a filesystem which will accept this path.
+ * NULL or a filesystem which will accept this path.
*
* Side effects:
* The object may be converted to a path type.
@@ -3896,56 +4370,60 @@ Tcl_FSRemoveDirectory(pathPtr, recursive, errorPtr)
*---------------------------------------------------------------------------
*/
-Tcl_Filesystem*
-Tcl_FSGetFileSystemForPath(pathObjPtr)
- Tcl_Obj* pathObjPtr;
+Tcl_Filesystem *
+Tcl_FSGetFileSystemForPath(
+ Tcl_Obj* pathPtr)
{
FilesystemRecord *fsRecPtr;
Tcl_Filesystem* retVal = NULL;
-
- /*
- * If the object has a refCount of zero, we reject it. This
- * is to avoid possible segfaults or nondeterministic memory
- * leaks (i.e. the user doesn't know if they should decrement
- * the ref count on return or not).
+
+ if (pathPtr == NULL) {
+ Tcl_Panic("Tcl_FSGetFileSystemForPath called with NULL object");
+ return NULL;
+ }
+
+ /*
+ * If the object has a refCount of zero, we reject it. This is to avoid
+ * possible segfaults or nondeterministic memory leaks (i.e. the user
+ * doesn't know if they should decrement the ref count on return or not).
*/
-
- if (pathObjPtr->refCount == 0) {
- panic("Tcl_FSGetFileSystemForPath called with object with refCount == 0");
+
+ if (pathPtr->refCount == 0) {
+ Tcl_Panic("Tcl_FSGetFileSystemForPath called with object with refCount == 0");
return NULL;
}
-
- /*
- * Check if the filesystem has changed in some way since
- * this object's internal representation was calculated.
- * Before doing that, assure we have the most up-to-date
- * copy of the master filesystem. This is accomplished
- * by the FsGetFirstFilesystem() call.
+
+ /*
+ * Check if the filesystem has changed in some way since this object's
+ * internal representation was calculated. Before doing that, assure we
+ * have the most up-to-date copy of the master filesystem. This is
+ * accomplished by the FsGetFirstFilesystem() call.
*/
fsRecPtr = FsGetFirstFilesystem();
- if (TclFSEnsureEpochOk(pathObjPtr, &retVal) != TCL_OK) {
+ if (TclFSEnsureEpochOk(pathPtr, &retVal) != TCL_OK) {
return NULL;
}
/*
- * Call each of the "pathInFilesystem" functions in succession. A
- * non-return value of -1 indicates the particular function has
- * succeeded.
+ * Call each of the "pathInFilesystem" functions in succession. A
+ * non-return value of -1 indicates the particular function has succeeded.
*/
while ((retVal == NULL) && (fsRecPtr != NULL)) {
- Tcl_FSPathInFilesystemProc *proc = fsRecPtr->fsPtr->pathInFilesystemProc;
+ Tcl_FSPathInFilesystemProc *proc =
+ fsRecPtr->fsPtr->pathInFilesystemProc;
+
if (proc != NULL) {
ClientData clientData = NULL;
- int ret = (*proc)(pathObjPtr, &clientData);
- if (ret != -1) {
- /*
- * We assume the type of pathObjPtr hasn't been changed
- * by the above call to the pathInFilesystemProc.
+ if ((*proc)(pathPtr, &clientData) != -1) {
+ /*
+ * We assume the type of pathPtr hasn't been changed by the
+ * above call to the pathInFilesystemProc.
*/
- TclFSSetPathDetails(pathObjPtr, fsRecPtr, clientData);
+
+ TclFSSetPathDetails(pathPtr, fsRecPtr, clientData);
retVal = fsRecPtr->fsPtr;
}
}
@@ -3960,26 +4438,23 @@ Tcl_FSGetFileSystemForPath(pathObjPtr)
*
* Tcl_FSGetNativePath --
*
- * This function is for use by the Win/Unix/MacOS native filesystems,
- * so that they can easily retrieve the native (char* or TCHAR*)
- * representation of a path. Other filesystems will probably
- * want to implement similar functions. They basically act as a
- * safety net around Tcl_FSGetInternalRep. Normally your file-
- * system procedures will always be called with path objects
- * already converted to the correct filesystem, but if for
- * some reason they are called directly (i.e. by procedures
- * not in this file), then one cannot necessarily guarantee that
- * the path object pointer is from the correct filesystem.
- *
- * Note: in the future it might be desireable to have separate
- * versions of this function with different signatures, for
- * example Tcl_FSGetNativeMacPath, Tcl_FSGetNativeUnixPath etc.
- * Right now, since native paths are all string based, we use just
- * one function. On MacOS we could possibly use an FSSpec or
- * FSRef as the native representation.
+ * This function is for use by the Win/Unix native filesystems, so that
+ * they can easily retrieve the native (char* or TCHAR*) representation
+ * of a path. Other filesystems will probably want to implement similar
+ * functions. They basically act as a safety net around
+ * Tcl_FSGetInternalRep. Normally your file-system functions will always
+ * be called with path objects already converted to the correct
+ * filesystem, but if for some reason they are called directly (i.e. by
+ * functions not in this file), then one cannot necessarily guarantee
+ * that the path object pointer is from the correct filesystem.
+ *
+ * Note: in the future it might be desireable to have separate versions
+ * of this function with different signatures, for example
+ * Tcl_FSGetNativeWinPath, Tcl_FSGetNativeUnixPath etc. Right now, since
+ * native paths are all string based, we use just one function.
*
* Results:
- * NULL or a valid native path.
+ * NULL or a valid native path.
*
* Side effects:
* See Tcl_FSGetInternalRep.
@@ -3987,164 +4462,11 @@ Tcl_FSGetFileSystemForPath(pathObjPtr)
*---------------------------------------------------------------------------
*/
-CONST char *
-Tcl_FSGetNativePath(pathObjPtr)
- Tcl_Obj *pathObjPtr;
+const char *
+Tcl_FSGetNativePath(
+ Tcl_Obj *pathPtr)
{
- return (CONST char *)Tcl_FSGetInternalRep(pathObjPtr, &tclNativeFilesystem);
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * NativeCreateNativeRep --
- *
- * Create a native representation for the given path.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *---------------------------------------------------------------------------
- */
-static ClientData
-NativeCreateNativeRep(pathObjPtr)
- Tcl_Obj* pathObjPtr;
-{
- char *nativePathPtr;
- Tcl_DString ds;
- Tcl_Obj* validPathObjPtr;
- int len;
- char *str;
-
- /* Make sure the normalized path is set */
- validPathObjPtr = Tcl_FSGetNormalizedPath(NULL, pathObjPtr);
- if (validPathObjPtr == NULL) {
- return NULL;
- }
-
- str = Tcl_GetStringFromObj(validPathObjPtr, &len);
-#ifdef __WIN32__
- Tcl_WinUtfToTChar(str, len, &ds);
- if (tclWinProcs->useWide) {
- len = Tcl_DStringLength(&ds) + sizeof(WCHAR);
- } else {
- len = Tcl_DStringLength(&ds) + sizeof(char);
- }
-#else
- Tcl_UtfToExternalDString(NULL, str, len, &ds);
- len = Tcl_DStringLength(&ds) + sizeof(char);
-#endif
- nativePathPtr = ckalloc((unsigned) len);
- memcpy((VOID*)nativePathPtr, (VOID*)Tcl_DStringValue(&ds), (size_t) len);
-
- Tcl_DStringFree(&ds);
- return (ClientData)nativePathPtr;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclpNativeToNormalized --
- *
- * Convert native format to a normalized path object, with refCount
- * of zero.
- *
- * Results:
- * A valid normalized path.
- *
- * Side effects:
- * None.
- *
- *---------------------------------------------------------------------------
- */
-Tcl_Obj*
-TclpNativeToNormalized(clientData)
- ClientData clientData;
-{
- Tcl_DString ds;
- Tcl_Obj *objPtr;
- CONST char *copy;
- int len;
-
-#ifdef __WIN32__
- Tcl_WinTCharToUtf((CONST char*)clientData, -1, &ds);
-#else
- Tcl_ExternalToUtfDString(NULL, (CONST char*)clientData, -1, &ds);
-#endif
-
- copy = Tcl_DStringValue(&ds);
- len = Tcl_DStringLength(&ds);
-
-#ifdef __WIN32__
- /*
- * Certain native path representations on Windows have this special
- * prefix to indicate that they are to be treated specially. For
- * example extremely long paths, or symlinks
- */
- if (*copy == '\\') {
- if (0 == strncmp(copy,"\\??\\",4)) {
- copy += 4;
- len -= 4;
- } else if (0 == strncmp(copy,"\\\\?\\",4)) {
- copy += 4;
- len -= 4;
- }
- }
-#endif
-
- objPtr = Tcl_NewStringObj(copy,len);
- Tcl_DStringFree(&ds);
-
- return objPtr;
-}
-
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclNativeDupInternalRep --
- *
- * Duplicate the native representation.
- *
- * Results:
- * The copied native representation, or NULL if it is not possible
- * to copy the representation.
- *
- * Side effects:
- * None.
- *
- *---------------------------------------------------------------------------
- */
-ClientData
-TclNativeDupInternalRep(clientData)
- ClientData clientData;
-{
- ClientData copy;
- size_t len;
-
- if (clientData == NULL) {
- return NULL;
- }
-
-#ifdef __WIN32__
- if (tclWinProcs->useWide) {
- /* unicode representation when running on NT/2K/XP */
- len = sizeof(WCHAR) + (wcslen((CONST WCHAR*)clientData) * sizeof(WCHAR));
- } else {
- /* ansi representation when running on 95/98/ME */
- len = sizeof(char) + (strlen((CONST char*)clientData) * sizeof(char));
- }
-#else
- /* ansi representation when running on Unix/MacOS */
- len = sizeof(char) + (strlen((CONST char*)clientData) * sizeof(char));
-#endif
-
- copy = (ClientData) ckalloc(len);
- memcpy((VOID*)copy, (VOID*)clientData, len);
- return copy;
+ return (const char *) Tcl_FSGetInternalRep(pathPtr, &tclNativeFilesystem);
}
/*
@@ -4152,21 +4474,22 @@ TclNativeDupInternalRep(clientData)
*
* NativeFreeInternalRep --
*
- * Free a native internal representation, which will be non-NULL.
+ * Free a native internal representation, which will be non-NULL.
*
* Results:
- * None.
+ * None.
*
* Side effects:
* Memory is released.
*
*---------------------------------------------------------------------------
*/
-static void
-NativeFreeInternalRep(clientData)
- ClientData clientData;
+
+static void
+NativeFreeInternalRep(
+ ClientData clientData)
{
- ckfree((char*)clientData);
+ ckfree((char *) clientData);
}
/*
@@ -4174,44 +4497,42 @@ NativeFreeInternalRep(clientData)
*
* Tcl_FSFileSystemInfo --
*
- * This function returns a list of two elements. The first
- * element is the name of the filesystem (e.g. "native" or "vfs"),
- * and the second is the particular type of the given path within
- * that filesystem.
+ * This function returns a list of two elements. The first element is the
+ * name of the filesystem (e.g. "native" or "vfs"), and the second is the
+ * particular type of the given path within that filesystem.
*
* Results:
- * A list of two elements.
+ * A list of two elements.
*
* Side effects:
* The object may be converted to a path type.
*
*---------------------------------------------------------------------------
*/
-Tcl_Obj*
-Tcl_FSFileSystemInfo(pathObjPtr)
- Tcl_Obj* pathObjPtr;
+
+Tcl_Obj *
+Tcl_FSFileSystemInfo(
+ Tcl_Obj *pathPtr)
{
Tcl_Obj *resPtr;
Tcl_FSFilesystemPathTypeProc *proc;
- Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathObjPtr);
-
+ const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
+
if (fsPtr == NULL) {
return NULL;
}
-
- resPtr = Tcl_NewListObj(0,NULL);
-
- Tcl_ListObjAppendElement(NULL, resPtr,
- Tcl_NewStringObj(fsPtr->typeName,-1));
+
+ resPtr = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(NULL,resPtr,Tcl_NewStringObj(fsPtr->typeName,-1));
proc = fsPtr->filesystemPathTypeProc;
if (proc != NULL) {
- Tcl_Obj *typePtr = (*proc)(pathObjPtr);
+ Tcl_Obj *typePtr = (*proc)(pathPtr);
if (typePtr != NULL) {
Tcl_ListObjAppendElement(NULL, resPtr, typePtr);
}
}
-
+
return resPtr;
}
@@ -4220,33 +4541,42 @@ Tcl_FSFileSystemInfo(pathObjPtr)
*
* Tcl_FSPathSeparator --
*
- * This function returns the separator to be used for a given
- * path. The object returned should have a refCount of zero
+ * This function returns the separator to be used for a given path. The
+ * object returned should have a refCount of zero
*
* Results:
- * A Tcl object, with a refCount of zero. If the caller
- * needs to retain a reference to the object, it should
- * call Tcl_IncrRefCount.
+ * A Tcl object, with a refCount of zero. If the caller needs to retain a
+ * reference to the object, it should call Tcl_IncrRefCount, and should
+ * otherwise free the object.
*
* Side effects:
* The path object may be converted to a path type.
*
*---------------------------------------------------------------------------
*/
-Tcl_Obj*
-Tcl_FSPathSeparator(pathObjPtr)
- Tcl_Obj* pathObjPtr;
+
+Tcl_Obj *
+Tcl_FSPathSeparator(
+ Tcl_Obj *pathPtr)
{
- Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathObjPtr);
-
+ const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
+
if (fsPtr == NULL) {
return NULL;
}
if (fsPtr->filesystemSeparatorProc != NULL) {
- return (*fsPtr->filesystemSeparatorProc)(pathObjPtr);
+ return (*fsPtr->filesystemSeparatorProc)(pathPtr);
+ } else {
+ Tcl_Obj *resultObj;
+
+ /*
+ * Allow filesystems not to provide a filesystemSeparatorProc if they
+ * wish to use the standard forward slash.
+ */
+
+ TclNewLiteralStringObj(resultObj, "/");
+ return resultObj;
}
-
- return NULL;
}
/*
@@ -4254,32 +4584,30 @@ Tcl_FSPathSeparator(pathObjPtr)
*
* NativeFilesystemSeparator --
*
- * This function is part of the native filesystem support, and
- * returns the separator for the given path.
+ * This function is part of the native filesystem support, and returns
+ * the separator for the given path.
*
* Results:
- * String object containing the separator character.
+ * String object containing the separator character.
*
* Side effects:
* None.
*
*---------------------------------------------------------------------------
*/
-static Tcl_Obj*
-NativeFilesystemSeparator(pathObjPtr)
- Tcl_Obj* pathObjPtr;
+
+static Tcl_Obj *
+NativeFilesystemSeparator(
+ Tcl_Obj *pathPtr)
{
- char *separator = NULL; /* lint */
+ const char *separator = NULL; /* lint */
switch (tclPlatform) {
- case TCL_PLATFORM_UNIX:
- separator = "/";
- break;
- case TCL_PLATFORM_WINDOWS:
- separator = "\\";
- break;
- case TCL_PLATFORM_MAC:
- separator = ":";
- break;
+ case TCL_PLATFORM_UNIX:
+ separator = "/";
+ break;
+ case TCL_PLATFORM_WINDOWS:
+ separator = "\\";
+ break;
}
return Tcl_NewStringObj(separator,1);
}
@@ -4292,26 +4620,25 @@ NativeFilesystemSeparator(pathObjPtr)
*
* TclStatInsertProc --
*
- * Insert the passed procedure pointer at the head of the list of
- * functions which are used during a call to 'TclStat(...)'. The
- * passed function should behave exactly like 'TclStat' when called
- * during that time (see 'TclStat(...)' for more information).
- * The function will be added even if it already in the list.
+ * Insert the passed function pointer at the head of the list of
+ * functions which are used during a call to 'TclStat(...)'. The passed
+ * function should behave exactly like 'TclStat' when called during that
+ * time (see 'TclStat(...)' for more information). The function will be
+ * added even if it already in the list.
*
* Results:
- * Normally TCL_OK; TCL_ERROR if memory for a new node in the list
- * could not be allocated.
+ * Normally TCL_OK; TCL_ERROR if memory for a new node in the list could
+ * not be allocated.
*
* Side effects:
- * Memory allocated and modifies the link list for 'TclStat'
- * functions.
+ * Memory allocated and modifies the link list for 'TclStat' functions.
*
*----------------------------------------------------------------------
*/
int
-TclStatInsertProc (proc)
- TclStatProc_ *proc;
+TclStatInsertProc(
+ TclStatProc_ *proc)
{
int retVal = TCL_ERROR;
@@ -4340,22 +4667,21 @@ TclStatInsertProc (proc)
* TclStatDeleteProc --
*
* Removed the passed function pointer from the list of 'TclStat'
- * functions. Ensures that the built-in stat function is not
- * removvable.
+ * functions. Ensures that the built-in stat function is not removable.
*
* Results:
- * TCL_OK if the procedure pointer was successfully removed,
- * TCL_ERROR otherwise.
+ * TCL_OK if the function pointer was successfully removed, TCL_ERROR
+ * otherwise.
*
* Side effects:
- * Memory is deallocated and the respective list updated.
+ * Memory is deallocated and the respective list updated.
*
*----------------------------------------------------------------------
*/
int
-TclStatDeleteProc (proc)
- TclStatProc_ *proc;
+TclStatDeleteProc(
+ TclStatProc_ *proc)
{
int retVal = TCL_ERROR;
StatProc *tmpStatProcPtr;
@@ -4363,10 +4689,11 @@ TclStatDeleteProc (proc)
Tcl_MutexLock(&obsoleteFsHookMutex);
tmpStatProcPtr = statProcList;
+
/*
- * Traverse the 'statProcList' looking for the particular node
- * whose 'proc' member matches 'proc' and remove that one from
- * the list. Ensure that the "default" node cannot be removed.
+ * Traverse the 'statProcList' looking for the particular node whose
+ * 'proc' member matches 'proc' and remove that one from the list. Ensure
+ * that the "default" node cannot be removed.
*/
while ((retVal == TCL_ERROR) && (tmpStatProcPtr != NULL)) {
@@ -4396,27 +4723,25 @@ TclStatDeleteProc (proc)
*
* TclAccessInsertProc --
*
- * Insert the passed procedure pointer at the head of the list of
- * functions which are used during a call to 'TclAccess(...)'.
- * The passed function should behave exactly like 'TclAccess' when
- * called during that time (see 'TclAccess(...)' for more
- * information). The function will be added even if it already in
- * the list.
+ * Insert the passed function pointer at the head of the list of
+ * functions which are used during a call to 'TclAccess(...)'. The passed
+ * function should behave exactly like 'TclAccess' when called during
+ * that time (see 'TclAccess(...)' for more information). The function
+ * will be added even if it already in the list.
*
* Results:
- * Normally TCL_OK; TCL_ERROR if memory for a new node in the list
- * could not be allocated.
+ * Normally TCL_OK; TCL_ERROR if memory for a new node in the list could
+ * not be allocated.
*
* Side effects:
- * Memory allocated and modifies the link list for 'TclAccess'
- * functions.
+ * Memory allocated and modifies the link list for 'TclAccess' functions.
*
*----------------------------------------------------------------------
*/
int
-TclAccessInsertProc(proc)
- TclAccessProc_ *proc;
+TclAccessInsertProc(
+ TclAccessProc_ *proc)
{
int retVal = TCL_ERROR;
@@ -4445,31 +4770,30 @@ TclAccessInsertProc(proc)
* TclAccessDeleteProc --
*
* Removed the passed function pointer from the list of 'TclAccess'
- * functions. Ensures that the built-in access function is not
- * removvable.
+ * functions. Ensures that the built-in access function is not removable.
*
* Results:
- * TCL_OK if the procedure pointer was successfully removed,
- * TCL_ERROR otherwise.
+ * TCL_OK if the function pointer was successfully removed, TCL_ERROR
+ * otherwise.
*
* Side effects:
- * Memory is deallocated and the respective list updated.
+ * Memory is deallocated and the respective list updated.
*
*----------------------------------------------------------------------
*/
int
-TclAccessDeleteProc(proc)
- TclAccessProc_ *proc;
+TclAccessDeleteProc(
+ TclAccessProc_ *proc)
{
int retVal = TCL_ERROR;
AccessProc *tmpAccessProcPtr;
AccessProc *prevAccessProcPtr = NULL;
/*
- * Traverse the 'accessProcList' looking for the particular node
- * whose 'proc' member matches 'proc' and remove that one from
- * the list. Ensure that the "default" node cannot be removed.
+ * Traverse the 'accessProcList' looking for the particular node whose
+ * 'proc' member matches 'proc' and remove that one from the list. Ensure
+ * that the "default" node cannot be removed.
*/
Tcl_MutexLock(&obsoleteFsHookMutex);
@@ -4500,45 +4824,43 @@ TclAccessDeleteProc(proc)
*
* TclOpenFileChannelInsertProc --
*
- * Insert the passed procedure pointer at the head of the list of
- * functions which are used during a call to
- * 'Tcl_OpenFileChannel(...)'. The passed function should behave
- * exactly like 'Tcl_OpenFileChannel' when called during that time
- * (see 'Tcl_OpenFileChannel(...)' for more information). The
- * function will be added even if it already in the list.
+ * Insert the passed function pointer at the head of the list of
+ * functions which are used during a call to 'Tcl_OpenFileChannel(...)'.
+ * The passed function should behave exactly like 'Tcl_OpenFileChannel'
+ * when called during that time (see 'Tcl_OpenFileChannel(...)' for more
+ * information). The function will be added even if it already in the
+ * list.
*
* Results:
- * Normally TCL_OK; TCL_ERROR if memory for a new node in the list
- * could not be allocated.
+ * Normally TCL_OK; TCL_ERROR if memory for a new node in the list could
+ * not be allocated.
*
* Side effects:
- * Memory allocated and modifies the link list for
- * 'Tcl_OpenFileChannel' functions.
+ * Memory allocated and modifies the link list for 'Tcl_OpenFileChannel'
+ * functions.
*
*----------------------------------------------------------------------
*/
int
-TclOpenFileChannelInsertProc(proc)
- TclOpenFileChannelProc_ *proc;
+TclOpenFileChannelInsertProc(
+ TclOpenFileChannelProc_ *proc)
{
int retVal = TCL_ERROR;
if (proc != NULL) {
OpenFileChannelProc *newOpenFileChannelProcPtr;
- newOpenFileChannelProcPtr =
- (OpenFileChannelProc *)ckalloc(sizeof(OpenFileChannelProc));
+ newOpenFileChannelProcPtr = (OpenFileChannelProc *)
+ ckalloc(sizeof(OpenFileChannelProc));
- if (newOpenFileChannelProcPtr != NULL) {
- newOpenFileChannelProcPtr->proc = proc;
- Tcl_MutexLock(&obsoleteFsHookMutex);
- newOpenFileChannelProcPtr->nextPtr = openFileChannelProcList;
- openFileChannelProcList = newOpenFileChannelProcPtr;
- Tcl_MutexUnlock(&obsoleteFsHookMutex);
+ newOpenFileChannelProcPtr->proc = proc;
+ Tcl_MutexLock(&obsoleteFsHookMutex);
+ newOpenFileChannelProcPtr->nextPtr = openFileChannelProcList;
+ openFileChannelProcList = newOpenFileChannelProcPtr;
+ Tcl_MutexUnlock(&obsoleteFsHookMutex);
- retVal = TCL_OK;
- }
+ retVal = TCL_OK;
}
return retVal;
@@ -4550,31 +4872,30 @@ TclOpenFileChannelInsertProc(proc)
* TclOpenFileChannelDeleteProc --
*
* Removed the passed function pointer from the list of
- * 'Tcl_OpenFileChannel' functions. Ensures that the built-in
- * open file channel function is not removable.
+ * 'Tcl_OpenFileChannel' functions. Ensures that the built-in open file
+ * channel function is not removable.
*
* Results:
- * TCL_OK if the procedure pointer was successfully removed,
- * TCL_ERROR otherwise.
+ * TCL_OK if the function pointer was successfully removed, TCL_ERROR
+ * otherwise.
*
* Side effects:
- * Memory is deallocated and the respective list updated.
+ * Memory is deallocated and the respective list updated.
*
*----------------------------------------------------------------------
*/
int
-TclOpenFileChannelDeleteProc(proc)
- TclOpenFileChannelProc_ *proc;
+TclOpenFileChannelDeleteProc(
+ TclOpenFileChannelProc_ *proc)
{
int retVal = TCL_ERROR;
OpenFileChannelProc *tmpOpenFileChannelProcPtr = openFileChannelProcList;
OpenFileChannelProc *prevOpenFileChannelProcPtr = NULL;
/*
- * Traverse the 'openFileChannelProcList' looking for the particular
- * node whose 'proc' member matches 'proc' and remove that one from
- * the list.
+ * Traverse the 'openFileChannelProcList' looking for the particular node
+ * whose 'proc' member matches 'proc' and remove that one from the list.
*/
Tcl_MutexLock(&obsoleteFsHookMutex);
@@ -4589,7 +4910,7 @@ TclOpenFileChannelDeleteProc(proc)
tmpOpenFileChannelProcPtr->nextPtr;
}
- ckfree((char *)tmpOpenFileChannelProcPtr);
+ ckfree((char *) tmpOpenFileChannelProcPtr);
retVal = TCL_OK;
} else {
@@ -4602,1956 +4923,11 @@ TclOpenFileChannelDeleteProc(proc)
return retVal;
}
#endif /* USE_OBSOLETE_FS_HOOKS */
-
-
-/*
- * Prototypes for procedures defined later in this file.
- */
-
-static void DupFsPathInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
- Tcl_Obj *copyPtr));
-static void FreeFsPathInternalRep _ANSI_ARGS_((Tcl_Obj *listPtr));
-static void UpdateStringOfFsPath _ANSI_ARGS_((Tcl_Obj *objPtr));
-static int SetFsPathFromAny _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
-static int FindSplitPos _ANSI_ARGS_((char *path, char *separator));
-
-
-
-/*
- * Define the 'path' object type, which Tcl uses to represent
- * file paths internally.
- */
-static Tcl_ObjType tclFsPathType = {
- "path", /* name */
- FreeFsPathInternalRep, /* freeIntRepProc */
- DupFsPathInternalRep, /* dupIntRepProc */
- UpdateStringOfFsPath, /* updateStringProc */
- SetFsPathFromAny /* setFromAnyProc */
-};
-
-/*
- * struct FsPath --
- *
- * Internal representation of a Tcl_Obj of "path" type. This
- * can be used to represent relative or absolute paths, and has
- * certain optimisations when used to represent paths which are
- * already normalized and absolute.
- *
- * Note that 'normPathPtr' can be a circular reference to the
- * container Tcl_Obj of this FsPath.
- */
-typedef struct FsPath {
- Tcl_Obj *translatedPathPtr; /* Name without any ~user sequences.
- * If this is NULL, then this is a
- * pure normalized, absolute path
- * object, in which the parent Tcl_Obj's
- * string rep is already both translated
- * and normalized. */
- Tcl_Obj *normPathPtr; /* Normalized absolute path, without
- * ., .. or ~user sequences. If the
- * Tcl_Obj containing
- * this FsPath is already normalized,
- * this may be a circular reference back
- * to the container. If that is NOT the
- * case, we have a refCount on the object. */
- Tcl_Obj *cwdPtr; /* If null, path is absolute, else
- * this points to the cwd object used
- * for this path. We have a refCount
- * on the object. */
- int flags; /* Flags to describe interpretation */
- ClientData nativePathPtr; /* Native representation of this path,
- * which is filesystem dependent. */
- int filesystemEpoch; /* Used to ensure the path representation
- * was generated during the correct
- * filesystem epoch. The epoch changes
- * when filesystem-mounts are changed. */
- struct FilesystemRecord *fsRecPtr;
- /* Pointer to the filesystem record
- * entry to use for this path. */
-} FsPath;
-
-/*
- * Define some macros to give us convenient access to path-object
- * specific fields.
- */
-#define PATHOBJ(objPtr) (objPtr->internalRep.otherValuePtr)
-#define PATHFLAGS(objPtr) \
- (((FsPath*)(objPtr->internalRep.otherValuePtr))->flags)
-
-#define TCLPATH_APPENDED 1
-#define TCLPATH_RELATIVE 2
-#define TCLPATH_NEEDNORM 4
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_FSGetPathType --
- *
- * Determines whether a given path is relative to the current
- * directory, relative to the current volume, or absolute.
- *
- * Results:
- * Returns one of TCL_PATH_ABSOLUTE, TCL_PATH_RELATIVE, or
- * TCL_PATH_VOLUME_RELATIVE.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_PathType
-Tcl_FSGetPathType(pathObjPtr)
- Tcl_Obj *pathObjPtr;
-{
- return FSGetPathType(pathObjPtr, NULL, NULL);
-}
/*
- *----------------------------------------------------------------------
- *
- * FSGetPathType --
- *
- * Determines whether a given path is relative to the current
- * directory, relative to the current volume, or absolute. If the
- * caller wishes to know which filesystem claimed the path (in the
- * case for which the path is absolute), then a reference to a
- * filesystem pointer can be passed in (but passing NULL is
- * acceptable).
- *
- * Results:
- * Returns one of TCL_PATH_ABSOLUTE, TCL_PATH_RELATIVE, or
- * TCL_PATH_VOLUME_RELATIVE. The filesystem reference will
- * be set if and only if it is non-NULL and the function's
- * return value is TCL_PATH_ABSOLUTE.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static Tcl_PathType
-FSGetPathType(pathObjPtr, filesystemPtrPtr, driveNameLengthPtr)
- Tcl_Obj *pathObjPtr;
- Tcl_Filesystem **filesystemPtrPtr;
- int *driveNameLengthPtr;
-{
- if (Tcl_FSConvertToPathType(NULL, pathObjPtr) != TCL_OK) {
- return GetPathType(pathObjPtr, filesystemPtrPtr,
- driveNameLengthPtr, NULL);
- } else {
- FsPath *fsPathPtr = (FsPath*) PATHOBJ(pathObjPtr);
- if (fsPathPtr->cwdPtr != NULL) {
- if (PATHFLAGS(pathObjPtr) == 0) {
- /* The path is not absolute... */
-#ifdef __WIN32__
- /* ... on Windows we must make another call to determine
- * whether it's relative or volumerelative [Bug 2571597]. */
- return GetPathType(pathObjPtr, filesystemPtrPtr,
- driveNameLengthPtr, NULL);
-#else
- /* On other systems, quickly deduce !absolute -> relative */
- return TCL_PATH_RELATIVE;
-#endif
- }
- return FSGetPathType(fsPathPtr->cwdPtr, filesystemPtrPtr,
- driveNameLengthPtr);
- } else {
- return GetPathType(pathObjPtr, filesystemPtrPtr,
- driveNameLengthPtr, NULL);
- }
- }
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * Tcl_FSJoinPath --
- *
- * This function takes the given Tcl_Obj, which should be a valid
- * list, and returns the path object given by considering the
- * first 'elements' elements as valid path segments. If elements < 0,
- * we use the entire list.
- *
- * Results:
- * Returns object with refCount of zero, (or if non-zero, it has
- * references elsewhere in Tcl). Either way, the caller must
- * increment its refCount before use.
- *
- * Side effects:
- * None.
- *
- *---------------------------------------------------------------------------
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
*/
-Tcl_Obj*
-Tcl_FSJoinPath(listObj, elements)
- Tcl_Obj *listObj;
- int elements;
-{
- Tcl_Obj *res;
- int i;
- Tcl_Filesystem *fsPtr = NULL;
-
- if (elements < 0) {
- if (Tcl_ListObjLength(NULL, listObj, &elements) != TCL_OK) {
- return NULL;
- }
- } else {
- /* Just make sure it is a valid list */
- int listTest;
- if (Tcl_ListObjLength(NULL, listObj, &listTest) != TCL_OK) {
- return NULL;
- }
- /*
- * Correct this if it is too large, otherwise we will
- * waste our time joining null elements to the path
- */
- if (elements > listTest) {
- elements = listTest;
- }
- }
-
- res = Tcl_NewObj();
-
- for (i = 0; i < elements; i++) {
- Tcl_Obj *elt;
- int driveNameLength;
- Tcl_PathType type;
- char *strElt;
- int strEltLen;
- int length;
- char *ptr;
- Tcl_Obj *driveName = NULL;
-
- Tcl_ListObjIndex(NULL, listObj, i, &elt);
-
- /*
- * This is a special case where we can be much more
- * efficient, where we are joining a single relative path
- * onto an object that is already of path type. The
- * 'TclNewFSPathObj' call below creates an object which
- * can be normalized more efficiently. Currently we only
- * use the special case when we have exactly two elements,
- * but we could expand that in the future.
- */
- if ((i == (elements-2)) && (i == 0) && (elt->typePtr == &tclFsPathType)
- && !(elt->bytes != NULL && (elt->bytes[0] == '\0'))) {
- Tcl_Obj *tail;
- Tcl_PathType type;
- Tcl_ListObjIndex(NULL, listObj, i+1, &tail);
- type = GetPathType(tail, NULL, NULL, NULL);
- if (type == TCL_PATH_RELATIVE) {
- CONST char *str;
- int len;
- str = Tcl_GetStringFromObj(tail,&len);
- if (len == 0) {
- /*
- * This happens if we try to handle the root volume
- * '/'. There's no need to return a special path
- * object, when the base itself is just fine!
- */
- Tcl_DecrRefCount(res);
- return elt;
- }
- /*
- * If it doesn't begin with '.' and is a mac or unix
- * path or it a windows path without backslashes, then we
- * can be very efficient here. (In fact even a windows
- * path with backslashes can be joined efficiently, but
- * the path object would not have forward slashes only,
- * and this would therefore contradict our 'file join'
- * documentation).
- */
- if (str[0] != '.' && ((tclPlatform != TCL_PLATFORM_WINDOWS)
- || (strchr(str, '\\') == NULL))) {
- /*
- * Finally, on Windows, 'file join' is defined to
- * convert all backslashes to forward slashes,
- * so the base part cannot have backslashes either.
- */
- if ((tclPlatform != TCL_PLATFORM_WINDOWS)
- || (strchr(Tcl_GetString(elt), '\\') == NULL)) {
- if (res != NULL) {
- TclDecrRefCount(res);
- }
- return TclNewFSPathObj(elt, str, len);
- }
- }
- /*
- * Otherwise we don't have an easy join, and
- * we must let the more general code below handle
- * things
- */
- } else {
- if (tclPlatform == TCL_PLATFORM_UNIX) {
- Tcl_DecrRefCount(res);
- return tail;
- } else {
- CONST char *str;
- int len;
- str = Tcl_GetStringFromObj(tail,&len);
- if (tclPlatform == TCL_PLATFORM_WINDOWS) {
- if (strchr(str, '\\') == NULL) {
- Tcl_DecrRefCount(res);
- return tail;
- }
- } else if (tclPlatform == TCL_PLATFORM_MAC) {
- if (strchr(str, '/') == NULL) {
- Tcl_DecrRefCount(res);
- return tail;
- }
- }
- }
- }
- }
- strElt = Tcl_GetStringFromObj(elt, &strEltLen);
- type = GetPathType(elt, &fsPtr, &driveNameLength, &driveName);
- if (type != TCL_PATH_RELATIVE) {
- /* Zero out the current result */
- Tcl_DecrRefCount(res);
- if (driveName != NULL) {
- res = Tcl_DuplicateObj(driveName);
- Tcl_DecrRefCount(driveName);
- } else {
- res = Tcl_NewStringObj(strElt, driveNameLength);
- }
- strElt += driveNameLength;
- }
-
- ptr = Tcl_GetStringFromObj(res, &length);
-
- /*
- * Strip off any './' before a tilde, unless this is the
- * beginning of the path.
- */
- if (length > 0 && strEltLen > 0) {
- if ((strElt[0] == '.') && (strElt[1] == '/')
- && (strElt[2] == '~')) {
- strElt += 2;
- }
- }
-
- /*
- * A NULL value for fsPtr at this stage basically means
- * we're trying to join a relative path onto something
- * which is also relative (or empty). There's nothing
- * particularly wrong with that.
- */
- if (*strElt == '\0') continue;
-
- if (fsPtr == &tclNativeFilesystem || fsPtr == NULL) {
- TclpNativeJoinPath(res, strElt);
- } else {
- char separator = '/';
- int needsSep = 0;
-
- if (fsPtr->filesystemSeparatorProc != NULL) {
- Tcl_Obj *sep = (*fsPtr->filesystemSeparatorProc)(res);
- if (sep != NULL) {
- separator = Tcl_GetString(sep)[0];
- }
- }
-
- if (length > 0 && ptr[length -1] != '/') {
- Tcl_AppendToObj(res, &separator, 1);
- length++;
- }
- Tcl_SetObjLength(res, length + (int) strlen(strElt));
-
- ptr = Tcl_GetString(res) + length;
- for (; *strElt != '\0'; strElt++) {
- if (*strElt == separator) {
- while (strElt[1] == separator) {
- strElt++;
- }
- if (strElt[1] != '\0') {
- if (needsSep) {
- *ptr++ = separator;
- }
- }
- } else {
- *ptr++ = *strElt;
- needsSep = 1;
- }
- }
- length = ptr - Tcl_GetString(res);
- Tcl_SetObjLength(res, length);
- }
- }
- return res;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * Tcl_FSConvertToPathType --
- *
- * This function tries to convert the given Tcl_Obj to a valid
- * Tcl path type, taking account of the fact that the cwd may
- * have changed even if this object is already supposedly of
- * the correct type.
- *
- * The filename may begin with "~" (to indicate current user's
- * home directory) or "~<user>" (to indicate any user's home
- * directory).
- *
- * Results:
- * Standard Tcl error code.
- *
- * Side effects:
- * The old representation may be freed, and new memory allocated.
- *
- *---------------------------------------------------------------------------
- */
-int
-Tcl_FSConvertToPathType(interp, objPtr)
- Tcl_Interp *interp; /* Interpreter in which to store error
- * message (if necessary). */
- Tcl_Obj *objPtr; /* Object to convert to a valid, current
- * path type. */
-{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
- /*
- * While it is bad practice to examine an object's type directly,
- * this is actually the best thing to do here. The reason is that
- * if we are converting this object to FsPath type for the first
- * time, we don't need to worry whether the 'cwd' has changed.
- * On the other hand, if this object is already of FsPath type,
- * and is a relative path, we do have to worry about the cwd.
- * If the cwd has changed, we must recompute the path.
- */
- if (objPtr->typePtr == &tclFsPathType) {
- FsPath *fsPathPtr = (FsPath*) PATHOBJ(objPtr);
- if (fsPathPtr->filesystemEpoch != tsdPtr->filesystemEpoch) {
- if (objPtr->bytes == NULL) {
- UpdateStringOfFsPath(objPtr);
- }
- FreeFsPathInternalRep(objPtr);
- objPtr->typePtr = NULL;
- return Tcl_ConvertToType(interp, objPtr, &tclFsPathType);
- }
- return TCL_OK;
- } else {
- return Tcl_ConvertToType(interp, objPtr, &tclFsPathType);
- }
-}
-
-/*
- * Helper function for SetFsPathFromAny. Returns position of first
- * directory delimiter in the path.
- */
-static int
-FindSplitPos(path, separator)
- char *path;
- char *separator;
-{
- int count = 0;
- switch (tclPlatform) {
- case TCL_PLATFORM_UNIX:
- case TCL_PLATFORM_MAC:
- while (path[count] != 0) {
- if (path[count] == *separator) {
- return count;
- }
- count++;
- }
- break;
-
- case TCL_PLATFORM_WINDOWS:
- while (path[count] != 0) {
- if (path[count] == *separator || path[count] == '\\') {
- return count;
- }
- count++;
- }
- break;
- }
- return count;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclNewFSPathObj --
- *
- * Creates a path object whose string representation is
- * '[file join dirPtr addStrRep]', but does so in a way that
- * allows for more efficient caching of normalized paths.
- *
- * Assumptions:
- * 'dirPtr' must be an absolute path.
- * 'len' may not be zero.
- *
- * Results:
- * The new Tcl object, with refCount zero.
- *
- * Side effects:
- * Memory is allocated. 'dirPtr' gets an additional refCount.
- *
- *---------------------------------------------------------------------------
- */
-
-Tcl_Obj*
-TclNewFSPathObj(Tcl_Obj *dirPtr, CONST char *addStrRep, int len)
-{
- FsPath *fsPathPtr;
- Tcl_Obj *objPtr;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- CONST char *p;
- int state = 0, count = 0;
-
- objPtr = Tcl_NewObj();
- fsPathPtr = (FsPath*)ckalloc((unsigned)sizeof(FsPath));
-
- if (tclPlatform == TCL_PLATFORM_MAC) {
- /*
- * Mac relative paths may begin with a directory separator ':'.
- * If present, we need to skip this ':' because we assume that
- * we can join dirPtr and addStrRep by concatenating them as
- * strings (and we ensure that dirPtr is terminated by a ':').
- */
- if (addStrRep[0] == ':') {
- addStrRep++;
- len--;
- }
- }
- /* Setup the path */
- fsPathPtr->translatedPathPtr = NULL;
- fsPathPtr->normPathPtr = Tcl_NewStringObj(addStrRep, len);
- Tcl_IncrRefCount(fsPathPtr->normPathPtr);
- fsPathPtr->cwdPtr = dirPtr;
- Tcl_IncrRefCount(dirPtr);
- fsPathPtr->nativePathPtr = NULL;
- fsPathPtr->fsRecPtr = NULL;
- fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
-
- PATHOBJ(objPtr) = (VOID *) fsPathPtr;
- PATHFLAGS(objPtr) = TCLPATH_RELATIVE | TCLPATH_APPENDED;
- objPtr->typePtr = &tclFsPathType;
- objPtr->bytes = NULL;
- objPtr->length = 0;
-
- /*
- * Look for path components made up of only "."
- * This is overly conservative analysis to keep simple. It may
- * mark some things as needing more aggressive normalization
- * that don't actually need it. No harm done.
- */
- for (p = addStrRep; len > 0; p++, len--) {
- switch (state) {
- case 0: /* So far only "." since last dirsep or start */
- switch (*p) {
- case '.':
- count++;
- break;
- case '/':
- case '\\':
- case ':':
- if (count) {
- PATHFLAGS(objPtr) |= TCLPATH_NEEDNORM;
- len = 0;
- }
- break;
- default:
- count = 0;
- state = 1;
- }
- case 1: /* Scanning for next dirsep */
- switch (*p) {
- case '/':
- case '\\':
- case ':':
- state = 0;
- break;
- }
- }
- }
- if (len == 0 && count) {
- PATHFLAGS(objPtr) |= TCLPATH_NEEDNORM;
- }
-
- return objPtr;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclFSMakePathRelative --
- *
- * Only for internal use.
- *
- * Takes a path and a directory, where we _assume_ both path and
- * directory are absolute, normalized and that the path lies
- * inside the directory. Returns a Tcl_Obj representing filename
- * of the path relative to the directory.
- *
- * In the case where the resulting path would start with a '~', we
- * take special care to return an ordinary string. This means to
- * use that path (and not have it interpreted as a user name),
- * one must prepend './'. This may seem strange, but that is how
- * 'glob' is currently defined.
- *
- * Results:
- * NULL on error, otherwise a valid object, typically with
- * refCount of zero, which it is assumed the caller will
- * increment.
- *
- * Side effects:
- * The old representation may be freed, and new memory allocated.
- *
- *---------------------------------------------------------------------------
- */
-
-Tcl_Obj*
-TclFSMakePathRelative(interp, objPtr, cwdPtr)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- Tcl_Obj *objPtr; /* The object we have. */
- Tcl_Obj *cwdPtr; /* Make it relative to this. */
-{
- int cwdLen, len;
- CONST char *tempStr;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
- if (objPtr->typePtr == &tclFsPathType) {
- FsPath *fsPathPtr = (FsPath*) PATHOBJ(objPtr);
- if (PATHFLAGS(objPtr) != 0
- && fsPathPtr->cwdPtr == cwdPtr) {
- objPtr = fsPathPtr->normPathPtr;
- /* Free old representation */
- if (objPtr->typePtr != NULL) {
- if (objPtr->bytes == NULL) {
- if (objPtr->typePtr->updateStringProc == NULL) {
- if (interp != NULL) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "can't find object",
- "string representation", (char *) NULL);
- }
- return NULL;
- }
- objPtr->typePtr->updateStringProc(objPtr);
- }
- if ((objPtr->typePtr->freeIntRepProc) != NULL) {
- (*objPtr->typePtr->freeIntRepProc)(objPtr);
- }
- }
- /* Now objPtr is a string object */
-
- if (Tcl_GetString(objPtr)[0] == '~') {
- /*
- * If the first character of the path is a tilde,
- * we must just return the path as is, to agree
- * with the defined behaviour of 'glob'.
- */
- return objPtr;
- }
-
- fsPathPtr = (FsPath*)ckalloc((unsigned)sizeof(FsPath));
-
- /* Circular reference, by design */
- fsPathPtr->translatedPathPtr = objPtr;
- fsPathPtr->normPathPtr = NULL;
- fsPathPtr->cwdPtr = cwdPtr;
- Tcl_IncrRefCount(cwdPtr);
- fsPathPtr->nativePathPtr = NULL;
- fsPathPtr->fsRecPtr = NULL;
- fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
-
- PATHOBJ(objPtr) = (VOID *) fsPathPtr;
- PATHFLAGS(objPtr) = 0;
- objPtr->typePtr = &tclFsPathType;
-
- return objPtr;
- }
- }
- /*
- * We know the cwd is a normalised object which does
- * not end in a directory delimiter, unless the cwd
- * is the name of a volume, in which case it will
- * end in a delimiter! We handle this situation here.
- * A better test than the '!= sep' might be to simply
- * check if 'cwd' is a root volume.
- *
- * Note that if we get this wrong, we will strip off
- * either too much or too little below, leading to
- * wrong answers returned by glob.
- */
- tempStr = Tcl_GetStringFromObj(cwdPtr, &cwdLen);
- /*
- * Should we perhaps use 'Tcl_FSPathSeparator'?
- * But then what about the Windows special case?
- * Perhaps we should just check if cwd is a root
- * volume.
- */
- switch (tclPlatform) {
- case TCL_PLATFORM_UNIX:
- if (tempStr[cwdLen-1] != '/') {
- cwdLen++;
- }
- break;
- case TCL_PLATFORM_WINDOWS:
- if (tempStr[cwdLen-1] != '/'
- && tempStr[cwdLen-1] != '\\') {
- cwdLen++;
- }
- break;
- case TCL_PLATFORM_MAC:
- if (tempStr[cwdLen-1] != ':') {
- cwdLen++;
- }
- break;
- }
- tempStr = Tcl_GetStringFromObj(objPtr, &len);
-
- return Tcl_NewStringObj(tempStr + cwdLen, len - cwdLen);
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclFSMakePathFromNormalized --
- *
- * Like SetFsPathFromAny, but assumes the given object is an
- * absolute normalized path. Only for internal use.
- *
- * Results:
- * Standard Tcl error code.
- *
- * Side effects:
- * The old representation may be freed, and new memory allocated.
- *
- *---------------------------------------------------------------------------
- */
-
-int
-TclFSMakePathFromNormalized(interp, objPtr, nativeRep)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- Tcl_Obj *objPtr; /* The object to convert. */
- ClientData nativeRep; /* The native rep for the object, if known
- * else NULL. */
-{
- FsPath *fsPathPtr;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
- if (objPtr->typePtr == &tclFsPathType) {
- return TCL_OK;
- }
-
- /* Free old representation */
- if (objPtr->typePtr != NULL) {
- if (objPtr->bytes == NULL) {
- if (objPtr->typePtr->updateStringProc == NULL) {
- if (interp != NULL) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "can't find object",
- "string representation", (char *) NULL);
- }
- return TCL_ERROR;
- }
- objPtr->typePtr->updateStringProc(objPtr);
- }
- if ((objPtr->typePtr->freeIntRepProc) != NULL) {
- (*objPtr->typePtr->freeIntRepProc)(objPtr);
- }
- }
-
- fsPathPtr = (FsPath*)ckalloc((unsigned)sizeof(FsPath));
- /* It's a pure normalized absolute path */
- fsPathPtr->translatedPathPtr = NULL;
- fsPathPtr->normPathPtr = objPtr;
- fsPathPtr->cwdPtr = NULL;
- fsPathPtr->nativePathPtr = nativeRep;
- fsPathPtr->fsRecPtr = NULL;
- fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
-
- PATHOBJ(objPtr) = (VOID *) fsPathPtr;
- PATHFLAGS(objPtr) = 0;
- objPtr->typePtr = &tclFsPathType;
-
- return TCL_OK;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * Tcl_FSNewNativePath --
- *
- * This function performs the something like that reverse of the
- * usual obj->path->nativerep conversions. If some code retrieves
- * a path in native form (from, e.g. readlink or a native dialog),
- * and that path is to be used at the Tcl level, then calling
- * this function is an efficient way of creating the appropriate
- * path object type.
- *
- * Any memory which is allocated for 'clientData' should be retained
- * until clientData is passed to the filesystem's freeInternalRepProc
- * when it can be freed. The built in platform-specific filesystems
- * use 'ckalloc' to allocate clientData, and ckfree to free it.
- *
- * Results:
- * NULL or a valid path object pointer, with refCount zero.
- *
- * Side effects:
- * New memory may be allocated.
- *
- *---------------------------------------------------------------------------
- */
-
-Tcl_Obj *
-Tcl_FSNewNativePath(fromFilesystem, clientData)
- Tcl_Filesystem* fromFilesystem;
- ClientData clientData;
-{
- Tcl_Obj *objPtr;
- FsPath *fsPathPtr;
-
- FilesystemRecord *fsFromPtr;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
- objPtr = TclFSInternalToNormalized(fromFilesystem, clientData, &fsFromPtr);
- if (objPtr == NULL) {
- return NULL;
- }
-
- /*
- * Free old representation; shouldn't normally be any,
- * but best to be safe.
- */
- if (objPtr->typePtr != NULL) {
- if (objPtr->bytes == NULL) {
- if (objPtr->typePtr->updateStringProc == NULL) {
- return NULL;
- }
- objPtr->typePtr->updateStringProc(objPtr);
- }
- if ((objPtr->typePtr->freeIntRepProc) != NULL) {
- (*objPtr->typePtr->freeIntRepProc)(objPtr);
- }
- }
-
- fsPathPtr = (FsPath*)ckalloc((unsigned)sizeof(FsPath));
-
- fsPathPtr->translatedPathPtr = NULL;
- /* Circular reference, by design */
- fsPathPtr->normPathPtr = objPtr;
- fsPathPtr->cwdPtr = NULL;
- fsPathPtr->nativePathPtr = clientData;
- fsPathPtr->fsRecPtr = fsFromPtr;
- fsPathPtr->fsRecPtr->fileRefCount++;
- fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
-
- PATHOBJ(objPtr) = (VOID *) fsPathPtr;
- PATHFLAGS(objPtr) = 0;
- objPtr->typePtr = &tclFsPathType;
-
- return objPtr;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * Tcl_FSGetTranslatedPath --
- *
- * This function attempts to extract the translated path
- * from the given Tcl_Obj. If the translation succeeds (i.e. the
- * object is a valid path), then it is returned. Otherwise NULL
- * will be returned, and an error message may be left in the
- * interpreter (if it is non-NULL)
- *
- * Results:
- * NULL or a valid Tcl_Obj pointer.
- *
- * Side effects:
- * Only those of 'Tcl_FSConvertToPathType'
- *
- *---------------------------------------------------------------------------
- */
-
-Tcl_Obj*
-Tcl_FSGetTranslatedPath(interp, pathPtr)
- Tcl_Interp *interp;
- Tcl_Obj* pathPtr;
-{
- Tcl_Obj *retObj = NULL;
- FsPath *srcFsPathPtr;
-
- if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) {
- return NULL;
- }
- srcFsPathPtr = (FsPath*) PATHOBJ(pathPtr);
- if (srcFsPathPtr->translatedPathPtr == NULL) {
- if (PATHFLAGS(pathPtr) != 0) {
- /*
- * We lack a translated path result, but we have a directory
- * (cwdPtr) and a tail (normPathPtr), and if we join the
- * translated version of cwdPtr to normPathPtr, we'll get the
- * translated result we need, and can store it for future use.
- */
-
- Tcl_Obj *translatedCwdPtr = Tcl_FSGetTranslatedPath(interp,
- srcFsPathPtr->cwdPtr);
-
- retObj = Tcl_FSJoinToPath(translatedCwdPtr, 1,
- &(srcFsPathPtr->normPathPtr));
- srcFsPathPtr->translatedPathPtr = retObj;
- Tcl_IncrRefCount(retObj);
- Tcl_DecrRefCount(translatedCwdPtr);
- } else {
- /*
- * It is a pure absolute, normalized path object.
- * This is something like being a 'pure list'. The
- * object's string, translatedPath and normalizedPath
- * are all identical.
- */
- retObj = srcFsPathPtr->normPathPtr;
- }
- } else {
- /* It is an ordinary path object */
- retObj = srcFsPathPtr->translatedPathPtr;
- }
-
- if (retObj) {
- Tcl_IncrRefCount(retObj);
- }
- return retObj;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * Tcl_FSGetTranslatedStringPath --
- *
- * This function attempts to extract the translated path
- * from the given Tcl_Obj. If the translation succeeds (i.e. the
- * object is a valid path), then the path is returned. Otherwise NULL
- * will be returned, and an error message may be left in the
- * interpreter (if it is non-NULL)
- *
- * Results:
- * NULL or a valid string.
- *
- * Side effects:
- * Only those of 'Tcl_FSConvertToPathType'
- *
- *---------------------------------------------------------------------------
- */
-CONST char*
-Tcl_FSGetTranslatedStringPath(interp, pathPtr)
- Tcl_Interp *interp;
- Tcl_Obj* pathPtr;
-{
- Tcl_Obj *transPtr = Tcl_FSGetTranslatedPath(interp, pathPtr);
-
- if (transPtr != NULL) {
- int len;
- CONST char *result, *orig;
- orig = Tcl_GetStringFromObj(transPtr, &len);
- result = (char*) ckalloc((unsigned)(len+1));
- memcpy((VOID*) result, (VOID*) orig, (size_t) (len+1));
- Tcl_DecrRefCount(transPtr);
- return result;
- }
-
- return NULL;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * Tcl_FSGetNormalizedPath --
- *
- * This important function attempts to extract from the given Tcl_Obj
- * a unique normalised path representation, whose string value can
- * be used as a unique identifier for the file.
- *
- * Results:
- * NULL or a valid path object pointer.
- *
- * Side effects:
- * New memory may be allocated. The Tcl 'errno' may be modified
- * in the process of trying to examine various path possibilities.
- *
- *---------------------------------------------------------------------------
- */
-
-Tcl_Obj*
-Tcl_FSGetNormalizedPath(interp, pathObjPtr)
- Tcl_Interp *interp;
- Tcl_Obj* pathObjPtr;
-{
- FsPath *fsPathPtr;
-
- if (Tcl_FSConvertToPathType(interp, pathObjPtr) != TCL_OK) {
- return NULL;
- }
- fsPathPtr = (FsPath*) PATHOBJ(pathObjPtr);
-
- if (PATHFLAGS(pathObjPtr) != 0) {
- /*
- * This is a special path object which is the result of
- * something like 'file join'
- */
- Tcl_Obj *dir, *copy;
- int cwdLen;
- int pathType;
- CONST char *cwdStr;
- ClientData clientData = NULL;
-
- pathType = Tcl_FSGetPathType(fsPathPtr->cwdPtr);
- dir = Tcl_FSGetNormalizedPath(interp, fsPathPtr->cwdPtr);
- if (dir == NULL) {
- return NULL;
- }
- if (pathObjPtr->bytes == NULL) {
- UpdateStringOfFsPath(pathObjPtr);
- }
- copy = Tcl_DuplicateObj(dir);
- Tcl_IncrRefCount(copy);
- Tcl_IncrRefCount(dir);
- /* We now own a reference on both 'dir' and 'copy' */
-
- cwdStr = Tcl_GetStringFromObj(copy, &cwdLen);
- /*
- * Should we perhaps use 'Tcl_FSPathSeparator'?
- * But then what about the Windows special case?
- * Perhaps we should just check if cwd is a root volume.
- * We should never get cwdLen == 0 in this code path.
- */
- switch (tclPlatform) {
- case TCL_PLATFORM_UNIX:
- if (cwdStr[cwdLen-1] != '/') {
- Tcl_AppendToObj(copy, "/", 1);
- cwdLen++;
- }
- break;
- case TCL_PLATFORM_WINDOWS:
- if (cwdStr[cwdLen-1] != '/'
- && cwdStr[cwdLen-1] != '\\') {
- Tcl_AppendToObj(copy, "/", 1);
- cwdLen++;
- }
- break;
- case TCL_PLATFORM_MAC:
- if (cwdStr[cwdLen-1] != ':') {
- Tcl_AppendToObj(copy, ":", 1);
- cwdLen++;
- }
- break;
- }
- Tcl_AppendObjToObj(copy, fsPathPtr->normPathPtr);
-
- /* Normalize the combined string. */
-
- if (PATHFLAGS(pathObjPtr) & TCLPATH_NEEDNORM) {
- /*
- * If the "tail" part has components (like /../) that cause
- * the combined path to need more complete normalizing,
- * call on the more powerful routine to accomplish that so
- * we avoid [Bug 2385549] ...
- */
-
- Tcl_Obj *newCopy = TclFSNormalizeAbsolutePath(interp, copy, NULL);
- Tcl_DecrRefCount(copy);
- copy = newCopy;
- } else {
- /*
- * ... but in most cases where we join a trouble free tail
- * to a normalized head, we can more efficiently normalize the
- * combined path by passing over only the unnormalized tail
- * portion. When this is sufficient, prior developers claim
- * this should be much faster. We use 'cwdLen-1' so that we are
- * already pointing at the dir-separator that we know about.
- * The normalization code will actually start off directly
- * after that separator.
- */
-
- TclFSNormalizeToUniquePath(interp, copy, cwdLen-1,
- (fsPathPtr->nativePathPtr == NULL ? &clientData : NULL));
- }
-
- /* Now we need to construct the new path object */
-
- if (pathType == TCL_PATH_RELATIVE) {
- FsPath* origDirFsPathPtr;
- Tcl_Obj *origDir = fsPathPtr->cwdPtr;
- origDirFsPathPtr = (FsPath*) PATHOBJ(origDir);
-
- fsPathPtr->cwdPtr = origDirFsPathPtr->cwdPtr;
- Tcl_IncrRefCount(fsPathPtr->cwdPtr);
-
- Tcl_DecrRefCount(fsPathPtr->normPathPtr);
- fsPathPtr->normPathPtr = copy;
- /* That's our reference to copy used */
- Tcl_DecrRefCount(dir);
- Tcl_DecrRefCount(origDir);
- } else {
- Tcl_DecrRefCount(fsPathPtr->cwdPtr);
- fsPathPtr->cwdPtr = NULL;
- Tcl_DecrRefCount(fsPathPtr->normPathPtr);
- fsPathPtr->normPathPtr = copy;
- /* That's our reference to copy used */
- Tcl_DecrRefCount(dir);
- }
- if (clientData != NULL) {
- /*
- * This may be unnecessary. It appears that the
- * TclFSNormalizeToUniquePath call above should have already
- * set this up. Not changing out of fear of the unknown.
- */
- fsPathPtr->nativePathPtr = clientData;
- }
- PATHFLAGS(pathObjPtr) = 0;
- }
- /* Ensure cwd hasn't changed */
- if (fsPathPtr->cwdPtr != NULL) {
- if (!TclFSCwdPointerEquals(fsPathPtr->cwdPtr)) {
- if (pathObjPtr->bytes == NULL) {
- UpdateStringOfFsPath(pathObjPtr);
- }
- FreeFsPathInternalRep(pathObjPtr);
- pathObjPtr->typePtr = NULL;
- if (Tcl_ConvertToType(interp, pathObjPtr,
- &tclFsPathType) != TCL_OK) {
- return NULL;
- }
- fsPathPtr = (FsPath*) PATHOBJ(pathObjPtr);
- } else if (fsPathPtr->normPathPtr == NULL) {
- int cwdLen;
- Tcl_Obj *copy;
- CONST char *cwdStr;
- ClientData clientData = NULL;
-
- copy = Tcl_DuplicateObj(fsPathPtr->cwdPtr);
- Tcl_IncrRefCount(copy);
- cwdStr = Tcl_GetStringFromObj(copy, &cwdLen);
- /*
- * Should we perhaps use 'Tcl_FSPathSeparator'?
- * But then what about the Windows special case?
- * Perhaps we should just check if cwd is a root volume.
- * We should never get cwdLen == 0 in this code path.
- */
- switch (tclPlatform) {
- case TCL_PLATFORM_UNIX:
- if (cwdStr[cwdLen-1] != '/') {
- Tcl_AppendToObj(copy, "/", 1);
- cwdLen++;
- }
- break;
- case TCL_PLATFORM_WINDOWS:
- if (cwdStr[cwdLen-1] != '/'
- && cwdStr[cwdLen-1] != '\\') {
- Tcl_AppendToObj(copy, "/", 1);
- cwdLen++;
- }
- break;
- case TCL_PLATFORM_MAC:
- if (cwdStr[cwdLen-1] != ':') {
- Tcl_AppendToObj(copy, ":", 1);
- cwdLen++;
- }
- break;
- }
- Tcl_AppendObjToObj(copy, pathObjPtr);
- /*
- * Normalize the combined string, but only starting after
- * the end of the previously normalized 'dir'. This should
- * be much faster!
- */
- TclFSNormalizeToUniquePath(interp, copy, cwdLen-1,
- (fsPathPtr->nativePathPtr == NULL ? &clientData : NULL));
- fsPathPtr->normPathPtr = copy;
- if (clientData != NULL) {
- fsPathPtr->nativePathPtr = clientData;
- }
- }
- }
- if (fsPathPtr->normPathPtr == NULL) {
- ClientData clientData = NULL;
- Tcl_Obj *useThisCwd = NULL;
- /*
- * Since normPathPtr is NULL, but this is a valid path
- * object, we know that the translatedPathPtr cannot be NULL.
- */
- Tcl_Obj *absolutePath = fsPathPtr->translatedPathPtr;
- char *path = Tcl_GetString(absolutePath);
-
- /*
- * We have to be a little bit careful here to avoid infinite loops
- * we're asking Tcl_FSGetPathType to return the path's type, but
- * that call can actually result in a lot of other filesystem
- * action, which might loop back through here.
- */
- if (path[0] != '\0') {
- Tcl_PathType type = Tcl_FSGetPathType(pathObjPtr);
- if (type == TCL_PATH_RELATIVE) {
- useThisCwd = Tcl_FSGetCwd(interp);
-
- if (useThisCwd == NULL) return NULL;
-
- absolutePath = Tcl_FSJoinToPath(useThisCwd, 1, &absolutePath);
- Tcl_IncrRefCount(absolutePath);
- /* We have a refCount on the cwd */
-#ifdef __WIN32__
- } else if (type == TCL_PATH_VOLUME_RELATIVE) {
- /*
- * Only Windows has volume-relative paths. These
- * paths are rather rare, but is is nice if Tcl can
- * handle them. It is much better if we can
- * handle them here, rather than in the native fs code,
- * because we really need to have a real absolute path
- * just below.
- *
- * We do not let this block compile on non-Windows
- * platforms because the test suite's manual forcing
- * of tclPlatform can otherwise cause this code path
- * to be executed, causing various errors because
- * volume-relative paths really do not exist.
- */
- useThisCwd = Tcl_FSGetCwd(interp);
- if (useThisCwd == NULL) return NULL;
-
- if (path[0] == '/') {
- /*
- * Path of form /foo/bar which is a path in the
- * root directory of the current volume.
- */
- CONST char *drive = Tcl_GetString(useThisCwd);
- absolutePath = Tcl_NewStringObj(drive,2);
- Tcl_AppendToObj(absolutePath, path, -1);
- Tcl_IncrRefCount(absolutePath);
- /* We have a refCount on the cwd */
- } else {
- /*
- * Path of form C:foo/bar, but this only makes
- * sense if the cwd is also on drive C.
- */
- CONST char *drive = Tcl_GetString(useThisCwd);
- char drive_c = path[0];
- if (drive_c >= 'a') {
- drive_c -= ('a' - 'A');
- }
- if (drive[0] == drive_c) {
- absolutePath = Tcl_DuplicateObj(useThisCwd);
- /* We have a refCount on the cwd */
- } else {
- Tcl_DecrRefCount(useThisCwd);
- useThisCwd = NULL;
- /*
- * The path is not in the current drive, but
- * is volume-relative. The way Tcl 8.3 handles
- * this is that it treats such a path as
- * relative to the root of the drive. We
- * therefore behave the same here.
- */
- absolutePath = Tcl_NewStringObj(path, 2);
- }
- Tcl_IncrRefCount(absolutePath);
- Tcl_AppendToObj(absolutePath, "/", 1);
- Tcl_AppendToObj(absolutePath, path+2, -1);
- }
-#endif /* __WIN32__ */
- }
- }
- /* Already has refCount incremented */
- fsPathPtr->normPathPtr = TclFSNormalizeAbsolutePath(interp, absolutePath,
- (fsPathPtr->nativePathPtr == NULL ? &clientData : NULL));
- if (0 && (clientData != NULL)) {
- fsPathPtr->nativePathPtr =
- (*fsPathPtr->fsRecPtr->fsPtr->dupInternalRepProc)(clientData);
- }
- if (!strcmp(Tcl_GetString(fsPathPtr->normPathPtr),
- Tcl_GetString(pathObjPtr))) {
- /*
- * The path was already normalized.
- * Get rid of the duplicate.
- */
- Tcl_DecrRefCount(fsPathPtr->normPathPtr);
- /*
- * We do *not* increment the refCount for
- * this circular reference
- */
- fsPathPtr->normPathPtr = pathObjPtr;
- }
- if (useThisCwd != NULL) {
- /* This was returned by Tcl_FSJoinToPath above */
- Tcl_DecrRefCount(absolutePath);
- fsPathPtr->cwdPtr = useThisCwd;
- }
- }
-
- return fsPathPtr->normPathPtr;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * Tcl_FSGetInternalRep --
- *
- * Extract the internal representation of a given path object,
- * in the given filesystem. If the path object belongs to a
- * different filesystem, we return NULL.
- *
- * If the internal representation is currently NULL, we attempt
- * to generate it, by calling the filesystem's
- * 'Tcl_FSCreateInternalRepProc'.
- *
- * Results:
- * NULL or a valid internal representation.
- *
- * Side effects:
- * An attempt may be made to convert the object.
- *
- *---------------------------------------------------------------------------
- */
-
-ClientData
-Tcl_FSGetInternalRep(pathObjPtr, fsPtr)
- Tcl_Obj* pathObjPtr;
- Tcl_Filesystem *fsPtr;
-{
- FsPath *srcFsPathPtr;
-
- if (Tcl_FSConvertToPathType(NULL, pathObjPtr) != TCL_OK) {
- return NULL;
- }
- srcFsPathPtr = (FsPath*) PATHOBJ(pathObjPtr);
-
- /*
- * We will only return the native representation for the caller's
- * filesystem. Otherwise we will simply return NULL. This means
- * that there must be a unique bi-directional mapping between paths
- * and filesystems, and that this mapping will not allow 'remapped'
- * files -- files which are in one filesystem but mapped into
- * another. Another way of putting this is that 'stacked'
- * filesystems are not allowed. We recognise that this is a
- * potentially useful feature for the future.
- *
- * Even something simple like a 'pass through' filesystem which
- * logs all activity and passes the calls onto the native system
- * would be nice, but not easily achievable with the current
- * implementation.
- */
- if (srcFsPathPtr->fsRecPtr == NULL) {
- /*
- * This only usually happens in wrappers like TclpStat which
- * create a string object and pass it to TclpObjStat. Code
- * which calls the Tcl_FS.. functions should always have a
- * filesystem already set. Whether this code path is legal or
- * not depends on whether we decide to allow external code to
- * call the native filesystem directly. It is at least safer
- * to allow this sub-optimal routing.
- */
- Tcl_FSGetFileSystemForPath(pathObjPtr);
-
- /*
- * If we fail through here, then the path is probably not a
- * valid path in the filesystsem, and is most likely to be a
- * use of the empty path "" via a direct call to one of the
- * objectified interfaces (e.g. from the Tcl testsuite).
- */
- srcFsPathPtr = (FsPath*) PATHOBJ(pathObjPtr);
- if (srcFsPathPtr->fsRecPtr == NULL) {
- return NULL;
- }
- }
-
- if (fsPtr != srcFsPathPtr->fsRecPtr->fsPtr) {
- /*
- * There is still one possibility we should consider; if the
- * file belongs to a different filesystem, perhaps it is
- * actually linked through to a file in our own filesystem
- * which we do care about. The way we can check for this
- * is we ask what filesystem this path belongs to.
- */
- Tcl_Filesystem *actualFs = Tcl_FSGetFileSystemForPath(pathObjPtr);
- if (actualFs == fsPtr) {
- return Tcl_FSGetInternalRep(pathObjPtr, fsPtr);
- }
- return NULL;
- }
-
- if (srcFsPathPtr->nativePathPtr == NULL) {
- Tcl_FSCreateInternalRepProc *proc;
- char *nativePathPtr;
-
- proc = srcFsPathPtr->fsRecPtr->fsPtr->createInternalRepProc;
- if (proc == NULL) {
- return NULL;
- }
-
- nativePathPtr = (*proc)(pathObjPtr);
- srcFsPathPtr = (FsPath*) PATHOBJ(pathObjPtr);
- srcFsPathPtr->nativePathPtr = nativePathPtr;
- }
-
- return srcFsPathPtr->nativePathPtr;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclFSEnsureEpochOk --
- *
- * This will ensure the pathObjPtr is up to date and can be
- * converted into a "path" type, and that we are able to generate a
- * complete normalized path which is used to determine the
- * filesystem match.
- *
- * Results:
- * Standard Tcl return code.
- *
- * Side effects:
- * An attempt may be made to convert the object.
- *
- *---------------------------------------------------------------------------
- */
-
-int
-TclFSEnsureEpochOk(pathObjPtr, fsPtrPtr)
- Tcl_Obj* pathObjPtr;
- Tcl_Filesystem **fsPtrPtr;
-{
- FsPath *srcFsPathPtr;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
- /*
- * SHOULD BE ABLE TO IMPROVE EFFICIENCY HERE.
- */
-
- if (Tcl_FSGetNormalizedPath(NULL, pathObjPtr) == NULL) {
- return TCL_ERROR;
- }
-
- srcFsPathPtr = (FsPath*) PATHOBJ(pathObjPtr);
-
- /*
- * Check if the filesystem has changed in some way since
- * this object's internal representation was calculated.
- */
- if (srcFsPathPtr->filesystemEpoch != tsdPtr->filesystemEpoch) {
- /*
- * We have to discard the stale representation and
- * recalculate it
- */
- if (pathObjPtr->bytes == NULL) {
- UpdateStringOfFsPath(pathObjPtr);
- }
- FreeFsPathInternalRep(pathObjPtr);
- pathObjPtr->typePtr = NULL;
- if (SetFsPathFromAny(NULL, pathObjPtr) != TCL_OK) {
- return TCL_ERROR;
- }
- srcFsPathPtr = (FsPath*) PATHOBJ(pathObjPtr);
- }
- /* Check whether the object is already assigned to a fs */
- if (srcFsPathPtr->fsRecPtr != NULL) {
- *fsPtrPtr = srcFsPathPtr->fsRecPtr->fsPtr;
- }
-
- return TCL_OK;
-}
-
-void
-TclFSSetPathDetails(pathObjPtr, fsRecPtr, clientData)
- Tcl_Obj *pathObjPtr;
- FilesystemRecord *fsRecPtr;
- ClientData clientData;
-{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- /* We assume pathObjPtr is already of the correct type */
- FsPath *srcFsPathPtr;
-
- srcFsPathPtr = (FsPath*) PATHOBJ(pathObjPtr);
- srcFsPathPtr->fsRecPtr = fsRecPtr;
- srcFsPathPtr->nativePathPtr = clientData;
- srcFsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
- fsRecPtr->fileRefCount++;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * Tcl_FSEqualPaths --
- *
- * This function tests whether the two paths given are equal path
- * objects. If either or both is NULL, 0 is always returned.
- *
- * Results:
- * 1 or 0.
- *
- * Side effects:
- * None.
- *
- *---------------------------------------------------------------------------
- */
-
-int
-Tcl_FSEqualPaths(firstPtr, secondPtr)
- Tcl_Obj* firstPtr;
- Tcl_Obj* secondPtr;
-{
- if (firstPtr == secondPtr) {
- return 1;
- } else {
- char *firstStr, *secondStr;
- int firstLen, secondLen, tempErrno;
-
- if (firstPtr == NULL || secondPtr == NULL) {
- return 0;
- }
- firstStr = Tcl_GetStringFromObj(firstPtr, &firstLen);
- secondStr = Tcl_GetStringFromObj(secondPtr, &secondLen);
- if ((firstLen == secondLen) && (strcmp(firstStr, secondStr) == 0)) {
- return 1;
- }
- /*
- * Try the most thorough, correct method of comparing fully
- * normalized paths
- */
-
- tempErrno = Tcl_GetErrno();
- firstPtr = Tcl_FSGetNormalizedPath(NULL, firstPtr);
- secondPtr = Tcl_FSGetNormalizedPath(NULL, secondPtr);
- Tcl_SetErrno(tempErrno);
-
- if (firstPtr == NULL || secondPtr == NULL) {
- return 0;
- }
- firstStr = Tcl_GetStringFromObj(firstPtr, &firstLen);
- secondStr = Tcl_GetStringFromObj(secondPtr, &secondLen);
- if ((firstLen == secondLen) && (strcmp(firstStr, secondStr) == 0)) {
- return 1;
- }
- }
-
- return 0;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * SetFsPathFromAny --
- *
- * This function tries to convert the given Tcl_Obj to a valid
- * Tcl path type.
- *
- * The filename may begin with "~" (to indicate current user's
- * home directory) or "~<user>" (to indicate any user's home
- * directory).
- *
- * Results:
- * Standard Tcl error code.
- *
- * Side effects:
- * The old representation may be freed, and new memory allocated.
- *
- *---------------------------------------------------------------------------
- */
-
-static int
-SetFsPathFromAny(interp, objPtr)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- Tcl_Obj *objPtr; /* The object to convert. */
-{
- int len;
- FsPath *fsPathPtr;
- Tcl_Obj *transPtr;
- char *name;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
- if (objPtr->typePtr == &tclFsPathType) {
- return TCL_OK;
- }
-
- /*
- * First step is to translate the filename. This is similar to
- * Tcl_TranslateFilename, but shouldn't convert everything to
- * windows backslashes on that platform. The current
- * implementation of this piece is a slightly optimised version
- * of the various Tilde/Split/Join stuff to avoid multiple
- * split/join operations.
- *
- * We remove any trailing directory separator.
- *
- * However, the split/join routines are quite complex, and
- * one has to make sure not to break anything on Unix, Win
- * or MacOS (fCmd.test, fileName.test and cmdAH.test exercise
- * most of the code).
- */
- name = Tcl_GetStringFromObj(objPtr,&len);
-
- /*
- * Handle tilde substitutions, if needed.
- */
- if (name[0] == '~') {
- char *expandedUser;
- Tcl_DString temp;
- int split;
- char separator='/';
-
- if (tclPlatform==TCL_PLATFORM_MAC) {
- if (strchr(name, ':') != NULL) separator = ':';
- }
-
- split = FindSplitPos(name, &separator);
- if (split != len) {
- /* We have multiple pieces '~user/foo/bar...' */
- name[split] = '\0';
- }
- /* Do some tilde substitution */
- if (name[1] == '\0') {
- /* We have just '~' */
- CONST char *dir;
- Tcl_DString dirString;
- if (split != len) { name[split] = separator; }
-
- dir = TclGetEnv("HOME", &dirString);
- if (dir == NULL) {
- if (interp) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "couldn't find HOME environment ",
- "variable to expand path", (char *) NULL);
- }
- return TCL_ERROR;
- }
- Tcl_DStringInit(&temp);
- Tcl_JoinPath(1, &dir, &temp);
- Tcl_DStringFree(&dirString);
- } else {
- /* We have a user name '~user' */
- Tcl_DStringInit(&temp);
- if (TclpGetUserHome(name+1, &temp) == NULL) {
- if (interp != NULL) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "user \"", (name+1),
- "\" doesn't exist", (char *) NULL);
- }
- Tcl_DStringFree(&temp);
- if (split != len) { name[split] = separator; }
- return TCL_ERROR;
- }
- if (split != len) { name[split] = separator; }
- }
-
- expandedUser = Tcl_DStringValue(&temp);
- transPtr = Tcl_NewStringObj(expandedUser, Tcl_DStringLength(&temp));
-
- if (split != len) {
- /* Join up the tilde substitution with the rest */
- if (name[split+1] == separator) {
-
- /*
- * Somewhat tricky case like ~//foo/bar.
- * Make use of Split/Join machinery to get it right.
- * Assumes all paths beginning with ~ are part of the
- * native filesystem.
- */
-
- int objc;
- Tcl_Obj **objv;
- Tcl_Obj *parts = TclpNativeSplitPath(objPtr, NULL);
- Tcl_ListObjGetElements(NULL, parts, &objc, &objv);
- /* Skip '~'. It's replaced by its expansion */
- objc--; objv++;
- while (objc--) {
- TclpNativeJoinPath(transPtr, Tcl_GetString(*objv++));
- }
- Tcl_DecrRefCount(parts);
- } else {
- /* Simple case. "rest" is relative path. Just join it. */
- Tcl_Obj *rest = Tcl_NewStringObj(name+split+1,-1);
- transPtr = Tcl_FSJoinToPath(transPtr, 1, &rest);
- }
- }
- Tcl_DStringFree(&temp);
- } else {
- transPtr = Tcl_FSJoinToPath(objPtr,0,NULL);
- }
-
-#if defined(__CYGWIN__) && defined(__WIN32__)
- {
- extern int cygwin_conv_to_win32_path
- _ANSI_ARGS_((CONST char *, char *));
- char winbuf[MAX_PATH+1];
-
- /*
- * In the Cygwin world, call conv_to_win32_path in order to use the
- * mount table to translate the file name into something Windows will
- * understand. Take care when converting empty strings!
- */
- name = Tcl_GetStringFromObj(transPtr, &len);
- if (len > 0) {
- cygwin_conv_to_win32_path(name, winbuf);
- TclWinNoBackslash(winbuf);
- Tcl_SetStringObj(transPtr, winbuf, -1);
- }
- }
-#endif /* __CYGWIN__ && __WIN32__ */
-
- /*
- * Now we have a translated filename in 'transPtr'. This will have
- * forward slashes on Windows, and will not contain any ~user
- * sequences.
- */
-
- fsPathPtr = (FsPath*)ckalloc((unsigned)sizeof(FsPath));
-
- fsPathPtr->translatedPathPtr = transPtr;
- Tcl_IncrRefCount(fsPathPtr->translatedPathPtr);
- fsPathPtr->normPathPtr = NULL;
- fsPathPtr->cwdPtr = NULL;
- fsPathPtr->nativePathPtr = NULL;
- fsPathPtr->fsRecPtr = NULL;
- fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
-
- /*
- * Free old representation before installing our new one.
- */
- if (objPtr->typePtr != NULL && objPtr->typePtr->freeIntRepProc != NULL) {
- (objPtr->typePtr->freeIntRepProc)(objPtr);
- }
- PATHOBJ(objPtr) = (VOID *) fsPathPtr;
- PATHFLAGS(objPtr) = 0;
- objPtr->typePtr = &tclFsPathType;
-
- return TCL_OK;
-}
-
-static void
-FreeFsPathInternalRep(pathObjPtr)
- Tcl_Obj *pathObjPtr; /* Path object with internal rep to free. */
-{
- FsPath *fsPathPtr = (FsPath*) PATHOBJ(pathObjPtr);
-
- if (fsPathPtr->translatedPathPtr != NULL) {
- if (fsPathPtr->translatedPathPtr != pathObjPtr) {
- Tcl_DecrRefCount(fsPathPtr->translatedPathPtr);
- }
- }
- if (fsPathPtr->normPathPtr != NULL) {
- if (fsPathPtr->normPathPtr != pathObjPtr) {
- Tcl_DecrRefCount(fsPathPtr->normPathPtr);
- }
- fsPathPtr->normPathPtr = NULL;
- }
- if (fsPathPtr->cwdPtr != NULL) {
- Tcl_DecrRefCount(fsPathPtr->cwdPtr);
- }
- if (fsPathPtr->nativePathPtr != NULL) {
- if (fsPathPtr->fsRecPtr != NULL) {
- if (fsPathPtr->fsRecPtr->fsPtr->freeInternalRepProc != NULL) {
- (*fsPathPtr->fsRecPtr->fsPtr
- ->freeInternalRepProc)(fsPathPtr->nativePathPtr);
- fsPathPtr->nativePathPtr = NULL;
- }
- }
- }
- if (fsPathPtr->fsRecPtr != NULL) {
- fsPathPtr->fsRecPtr->fileRefCount--;
- if (fsPathPtr->fsRecPtr->fileRefCount <= 0) {
- /* It has been unregistered already, so simply free it */
- ckfree((char *)fsPathPtr->fsRecPtr);
- }
- }
-
- ckfree((char*) fsPathPtr);
-}
-
-
-static void
-DupFsPathInternalRep(srcPtr, copyPtr)
- Tcl_Obj *srcPtr; /* Path obj with internal rep to copy. */
- Tcl_Obj *copyPtr; /* Path obj with internal rep to set. */
-{
- FsPath *srcFsPathPtr = (FsPath*) PATHOBJ(srcPtr);
- FsPath *copyFsPathPtr = (FsPath*) ckalloc((unsigned)sizeof(FsPath));
-
- Tcl_FSDupInternalRepProc *dupProc;
-
- PATHOBJ(copyPtr) = (VOID *) copyFsPathPtr;
-
- if (srcFsPathPtr->translatedPathPtr != NULL) {
- copyFsPathPtr->translatedPathPtr = srcFsPathPtr->translatedPathPtr;
- if (copyFsPathPtr->translatedPathPtr != copyPtr) {
- Tcl_IncrRefCount(copyFsPathPtr->translatedPathPtr);
- }
- } else {
- copyFsPathPtr->translatedPathPtr = NULL;
- }
-
- if (srcFsPathPtr->normPathPtr != NULL) {
- copyFsPathPtr->normPathPtr = srcFsPathPtr->normPathPtr;
- if (copyFsPathPtr->normPathPtr != copyPtr) {
- Tcl_IncrRefCount(copyFsPathPtr->normPathPtr);
- }
- } else {
- copyFsPathPtr->normPathPtr = NULL;
- }
-
- if (srcFsPathPtr->cwdPtr != NULL) {
- copyFsPathPtr->cwdPtr = srcFsPathPtr->cwdPtr;
- Tcl_IncrRefCount(copyFsPathPtr->cwdPtr);
- } else {
- copyFsPathPtr->cwdPtr = NULL;
- }
-
- copyFsPathPtr->flags = srcFsPathPtr->flags;
-
- if (srcFsPathPtr->fsRecPtr != NULL
- && srcFsPathPtr->nativePathPtr != NULL) {
- dupProc = srcFsPathPtr->fsRecPtr->fsPtr->dupInternalRepProc;
- if (dupProc != NULL) {
- copyFsPathPtr->nativePathPtr =
- (*dupProc)(srcFsPathPtr->nativePathPtr);
- } else {
- copyFsPathPtr->nativePathPtr = NULL;
- }
- } else {
- copyFsPathPtr->nativePathPtr = NULL;
- }
- copyFsPathPtr->fsRecPtr = srcFsPathPtr->fsRecPtr;
- copyFsPathPtr->filesystemEpoch = srcFsPathPtr->filesystemEpoch;
- if (copyFsPathPtr->fsRecPtr != NULL) {
- copyFsPathPtr->fsRecPtr->fileRefCount++;
- }
-
- copyPtr->typePtr = &tclFsPathType;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * UpdateStringOfFsPath --
- *
- * Gives an object a valid string rep.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Memory may be allocated.
- *
- *---------------------------------------------------------------------------
- */
-
-static void
-UpdateStringOfFsPath(objPtr)
- register Tcl_Obj *objPtr; /* path obj with string rep to update. */
-{
- FsPath *fsPathPtr = (FsPath*) PATHOBJ(objPtr);
- CONST char *cwdStr;
- int cwdLen;
- Tcl_Obj *copy;
-
- if (PATHFLAGS(objPtr) == 0 || fsPathPtr->cwdPtr == NULL) {
- panic("Called UpdateStringOfFsPath with invalid object");
- }
-
- copy = Tcl_DuplicateObj(fsPathPtr->cwdPtr);
- Tcl_IncrRefCount(copy);
-
- cwdStr = Tcl_GetStringFromObj(copy, &cwdLen);
- /*
- * Should we perhaps use 'Tcl_FSPathSeparator'?
- * But then what about the Windows special case?
- * Perhaps we should just check if cwd is a root volume.
- * We should never get cwdLen == 0 in this code path.
- */
- switch (tclPlatform) {
- case TCL_PLATFORM_UNIX:
- if (cwdStr[cwdLen-1] != '/') {
- Tcl_AppendToObj(copy, "/", 1);
- cwdLen++;
- }
- break;
- case TCL_PLATFORM_WINDOWS:
- /*
- * We need the extra 'cwdLen != 2', and ':' checks because
- * a volume relative path doesn't get a '/'. For example
- * 'glob C:*cat*.exe' will return 'C:cat32.exe'
- */
- if (cwdStr[cwdLen-1] != '/'
- && cwdStr[cwdLen-1] != '\\') {
- if (cwdLen != 2 || cwdStr[1] != ':') {
- Tcl_AppendToObj(copy, "/", 1);
- cwdLen++;
- }
- }
- break;
- case TCL_PLATFORM_MAC:
- if (cwdStr[cwdLen-1] != ':') {
- Tcl_AppendToObj(copy, ":", 1);
- cwdLen++;
- }
- break;
- }
- Tcl_AppendObjToObj(copy, fsPathPtr->normPathPtr);
- objPtr->bytes = Tcl_GetStringFromObj(copy, &cwdLen);
- objPtr->length = cwdLen;
- copy->bytes = tclEmptyStringRep;
- copy->length = 0;
- Tcl_DecrRefCount(copy);
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * NativePathInFilesystem --
- *
- * Any path object is acceptable to the native filesystem, by
- * default (we will throw errors when illegal paths are actually
- * tried to be used).
- *
- * However, this behavior means the native filesystem must be
- * the last filesystem in the lookup list (otherwise it will
- * claim all files belong to it, and other filesystems will
- * never get a look in).
- *
- * Results:
- * TCL_OK, to indicate 'yes', -1 to indicate no.
- *
- * Side effects:
- * None.
- *
- *---------------------------------------------------------------------------
- */
-static int
-NativePathInFilesystem(pathPtr, clientDataPtr)
- Tcl_Obj *pathPtr;
- ClientData *clientDataPtr;
-{
- /*
- * A special case is required to handle the empty path "".
- * This is a valid path (i.e. the user should be able
- * to do 'file exists ""' without throwing an error), but
- * equally the path doesn't exist. Those are the semantics
- * of Tcl (at present anyway), so we have to abide by them
- * here.
- */
- if (pathPtr->typePtr == &tclFsPathType) {
- if (pathPtr->bytes != NULL && pathPtr->bytes[0] == '\0') {
- /* We reject the empty path "" */
- return -1;
- }
- /* Otherwise there is no way this path can be empty */
- } else {
- /*
- * It is somewhat unusual to reach this code path without
- * the object being of tclFsPathType. However, we do
- * our best to deal with the situation.
- */
- int len;
- Tcl_GetStringFromObj(pathPtr,&len);
- if (len == 0) {
- /* We reject the empty path "" */
- return -1;
- }
- }
- /*
- * Path is of correct type, or is of non-zero length,
- * so we accept it.
- */
- return TCL_OK;
-}
diff --git a/generic/tclIndexObj.c b/generic/tclIndexObj.c
index 79fc262..7991533 100644
--- a/generic/tclIndexObj.c
+++ b/generic/tclIndexObj.c
@@ -1,36 +1,33 @@
-/*
+/*
* tclIndexObj.c --
*
- * This file implements objects of type "index". This object type
- * is used to lookup a keyword in a table of valid values and cache
- * the index of the matching entry.
+ * This file implements objects of type "index". This object type is used
+ * to lookup a keyword in a table of valid values and cache the index of
+ * the matching entry.
*
* Copyright (c) 1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
/*
- * Prototypes for procedures defined later in this file:
+ * Prototypes for functions defined later in this file:
*/
-static int SetIndexFromAny _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
-static void UpdateStringOfIndex _ANSI_ARGS_((Tcl_Obj *objPtr));
-static void DupIndex _ANSI_ARGS_((Tcl_Obj *srcPtr,
- Tcl_Obj *dupPtr));
-static void FreeIndex _ANSI_ARGS_((Tcl_Obj *objPtr));
+static int SetIndexFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
+static void UpdateStringOfIndex(Tcl_Obj *objPtr);
+static void DupIndex(Tcl_Obj *srcPtr, Tcl_Obj *dupPtr);
+static void FreeIndex(Tcl_Obj *objPtr);
/*
- * The structure below defines the index Tcl object type by means of
- * procedures that can be invoked by generic object code.
+ * The structure below defines the index Tcl object type by means of functions
+ * that can be invoked by generic object code.
*/
-Tcl_ObjType tclIndexType = {
+static Tcl_ObjType indexType = {
"index", /* name */
FreeIndex, /* freeIntRepProc */
DupIndex, /* dupIntRepProc */
@@ -39,15 +36,15 @@ Tcl_ObjType tclIndexType = {
};
/*
- * The definition of the internal representation of the "index"
- * object; The internalRep.otherValuePtr field of an object of "index"
- * type will be a pointer to one of these structures.
+ * The definition of the internal representation of the "index" object; The
+ * internalRep.otherValuePtr field of an object of "index" type will be a
+ * pointer to one of these structures.
*
* Keep this structure declaration in sync with tclTestObj.c
*/
typedef struct {
- VOID *tablePtr; /* Pointer to the table of strings */
+ void *tablePtr; /* Pointer to the table of strings */
int offset; /* Offset between table entries */
int index; /* Selected index into table. */
} IndexRep;
@@ -55,68 +52,68 @@ typedef struct {
/*
* The following macros greatly simplify moving through a table...
*/
+
#define STRING_AT(table, offset, index) \
- (*((CONST char * CONST *)(((char *)(table)) + ((offset) * (index)))))
+ (*((const char *const *)(((char *)(table)) + ((offset) * (index)))))
#define NEXT_ENTRY(table, offset) \
(&(STRING_AT(table, offset, 1)))
#define EXPAND_OF(indexRep) \
STRING_AT((indexRep)->tablePtr, (indexRep)->offset, (indexRep)->index)
-
/*
*----------------------------------------------------------------------
*
* Tcl_GetIndexFromObj --
*
- * This procedure looks up an object's value in a table of strings
- * and returns the index of the matching string, if any.
+ * This function looks up an object's value in a table of strings and
+ * returns the index of the matching string, if any.
*
* Results:
- *
- * If the value of objPtr is identical to or a unique abbreviation
- * for one of the entries in objPtr, then the return value is
- * TCL_OK and the index of the matching entry is stored at
- * *indexPtr. If there isn't a proper match, then TCL_ERROR is
- * returned and an error message is left in interp's result (unless
- * interp is NULL). The msg argument is used in the error
- * message; for example, if msg has the value "option" then the
- * error message will say something flag 'bad option "foo": must be
+ * If the value of objPtr is identical to or a unique abbreviation for
+ * one of the entries in objPtr, then the return value is TCL_OK and the
+ * index of the matching entry is stored at *indexPtr. If there isn't a
+ * proper match, then TCL_ERROR is returned and an error message is left
+ * in interp's result (unless interp is NULL). The msg argument is used
+ * in the error message; for example, if msg has the value "option" then
+ * the error message will say something flag 'bad option "foo": must be
* ...'
*
* Side effects:
- * The result of the lookup is cached as the internal rep of
- * objPtr, so that repeated lookups can be done quickly.
+ * The result of the lookup is cached as the internal rep of objPtr, so
+ * that repeated lookups can be done quickly.
*
*----------------------------------------------------------------------
*/
int
-Tcl_GetIndexFromObj(interp, objPtr, tablePtr, msg, flags, indexPtr)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- Tcl_Obj *objPtr; /* Object containing the string to lookup. */
- CONST char **tablePtr; /* Array of strings to compare against the
+Tcl_GetIndexFromObj(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tcl_Obj *objPtr, /* Object containing the string to lookup. */
+ const char **tablePtr, /* Array of strings to compare against the
* value of objPtr; last entry must be NULL
* and there must not be duplicate entries. */
- CONST char *msg; /* Identifying word to use in error messages. */
- int flags; /* 0 or TCL_EXACT */
- int *indexPtr; /* Place to store resulting integer index. */
+ const char *msg, /* Identifying word to use in error
+ * messages. */
+ int flags, /* 0 or TCL_EXACT */
+ int *indexPtr) /* Place to store resulting integer index. */
{
/*
- * See if there is a valid cached result from a previous lookup
- * (doing the check here saves the overhead of calling
- * Tcl_GetIndexFromObjStruct in the common case where the result
- * is cached).
+ * See if there is a valid cached result from a previous lookup (doing the
+ * check here saves the overhead of calling Tcl_GetIndexFromObjStruct in
+ * the common case where the result is cached).
*/
- if (objPtr->typePtr == &tclIndexType) {
- IndexRep *indexRep = (IndexRep *) objPtr->internalRep.otherValuePtr;
+ if (objPtr->typePtr == &indexType) {
+ IndexRep *indexRep = objPtr->internalRep.otherValuePtr;
+
/*
- * Here's hoping we don't get hit by unfortunate packing
- * constraints on odd platforms like a Cray PVP...
+ * Here's hoping we don't get hit by unfortunate packing constraints
+ * on odd platforms like a Cray PVP...
*/
- if (indexRep->tablePtr == (VOID *)tablePtr &&
- indexRep->offset == sizeof(char *)) {
+
+ if (indexRep->tablePtr == (void *) tablePtr
+ && indexRep->offset == sizeof(char *)) {
*indexPtr = indexRep->index;
return TCL_OK;
}
@@ -130,49 +127,46 @@ Tcl_GetIndexFromObj(interp, objPtr, tablePtr, msg, flags, indexPtr)
*
* Tcl_GetIndexFromObjStruct --
*
- * This procedure looks up an object's value given a starting
- * string and an offset for the amount of space between strings.
- * This is useful when the strings are embedded in some other
- * kind of array.
+ * This function looks up an object's value given a starting string and
+ * an offset for the amount of space between strings. This is useful when
+ * the strings are embedded in some other kind of array.
*
* Results:
- *
- * If the value of objPtr is identical to or a unique abbreviation
- * for one of the entries in objPtr, then the return value is
- * TCL_OK and the index of the matching entry is stored at
- * *indexPtr. If there isn't a proper match, then TCL_ERROR is
- * returned and an error message is left in interp's result (unless
- * interp is NULL). The msg argument is used in the error
- * message; for example, if msg has the value "option" then the
- * error message will say something flag 'bad option "foo": must be
+ * If the value of objPtr is identical to or a unique abbreviation for
+ * one of the entries in objPtr, then the return value is TCL_OK and the
+ * index of the matching entry is stored at *indexPtr. If there isn't a
+ * proper match, then TCL_ERROR is returned and an error message is left
+ * in interp's result (unless interp is NULL). The msg argument is used
+ * in the error message; for example, if msg has the value "option" then
+ * the error message will say something flag 'bad option "foo": must be
* ...'
*
* Side effects:
- * The result of the lookup is cached as the internal rep of
- * objPtr, so that repeated lookups can be done quickly.
+ * The result of the lookup is cached as the internal rep of objPtr, so
+ * that repeated lookups can be done quickly.
*
*----------------------------------------------------------------------
*/
int
-Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags,
- indexPtr)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- Tcl_Obj *objPtr; /* Object containing the string to lookup. */
- CONST VOID *tablePtr; /* The first string in the table. The second
+Tcl_GetIndexFromObjStruct(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tcl_Obj *objPtr, /* Object containing the string to lookup. */
+ const void *tablePtr, /* The first string in the table. The second
* string will be at this address plus the
* offset, the third plus the offset again,
- * etc. The last entry must be NULL
- * and there must not be duplicate entries. */
- int offset; /* The number of bytes between entries */
- CONST char *msg; /* Identifying word to use in error messages. */
- int flags; /* 0 or TCL_EXACT */
- int *indexPtr; /* Place to store resulting integer index. */
+ * etc. The last entry must be NULL and there
+ * must not be duplicate entries. */
+ int offset, /* The number of bytes between entries */
+ const char *msg, /* Identifying word to use in error
+ * messages. */
+ int flags, /* 0 or TCL_EXACT */
+ int *indexPtr) /* Place to store resulting integer index. */
{
- int index, i, numAbbrev;
+ int index, idx, numAbbrev;
char *key, *p1;
- CONST char *p2;
- CONST char * CONST *entryPtr;
+ const char *p2;
+ const char *const *entryPtr;
Tcl_Obj *resultPtr;
IndexRep *indexRep;
@@ -180,8 +174,8 @@ Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags,
* See if there is a valid cached result from a previous lookup.
*/
- if (objPtr->typePtr == &tclIndexType) {
- indexRep = (IndexRep *) objPtr->internalRep.otherValuePtr;
+ if (objPtr->typePtr == &indexType) {
+ indexRep = objPtr->internalRep.otherValuePtr;
if (indexRep->tablePtr==tablePtr && indexRep->offset==offset) {
*indexPtr = indexRep->index;
return TCL_OK;
@@ -189,7 +183,7 @@ Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags,
}
/*
- * Lookup the value of the object in the table. Accept unique
+ * Lookup the value of the object in the table. Accept unique
* abbreviations unless TCL_EXACT is set in flags.
*/
@@ -203,82 +197,83 @@ Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags,
* - A single abbreviation (allowed depending on flags)
* - Several abbreviations (never allowed, but overridden by exact match)
*/
- for (entryPtr = tablePtr, i = 0; *entryPtr != NULL;
- entryPtr = NEXT_ENTRY(entryPtr, offset), i++) {
+
+ for (entryPtr = tablePtr, idx = 0; *entryPtr != NULL;
+ entryPtr = NEXT_ENTRY(entryPtr, offset), idx++) {
for (p1 = key, p2 = *entryPtr; *p1 == *p2; p1++, p2++) {
if (*p1 == '\0') {
- index = i;
+ index = idx;
goto done;
}
}
if (*p1 == '\0') {
/*
- * The value is an abbreviation for this entry. Continue
- * checking other entries to make sure it's unique. If we
- * get more than one unique abbreviation, keep searching to
- * see if there is an exact match, but remember the number
- * of unique abbreviations and don't allow either.
+ * The value is an abbreviation for this entry. Continue checking
+ * other entries to make sure it's unique. If we get more than one
+ * unique abbreviation, keep searching to see if there is an exact
+ * match, but remember the number of unique abbreviations and
+ * don't allow either.
*/
numAbbrev++;
- index = i;
+ index = idx;
}
}
+
/*
- * Check if we were instructed to disallow abbreviations.
+ * Check if we were instructed to disallow abbreviations.
*/
+
if ((flags & TCL_EXACT) || (key[0] == '\0') || (numAbbrev != 1)) {
goto error;
}
- done:
+ done:
/*
- * Cache the found representation. Note that we want to avoid
- * allocating a new internal-rep if at all possible since that is
- * potentially a slow operation.
+ * Cache the found representation. Note that we want to avoid allocating a
+ * new internal-rep if at all possible since that is potentially a slow
+ * operation.
*/
- if (objPtr->typePtr == &tclIndexType) {
- indexRep = (IndexRep *) objPtr->internalRep.otherValuePtr;
+
+ if (objPtr->typePtr == &indexType) {
+ indexRep = objPtr->internalRep.otherValuePtr;
} else {
- if ((objPtr->typePtr != NULL)
- && (objPtr->typePtr->freeIntRepProc != NULL)) {
- objPtr->typePtr->freeIntRepProc(objPtr);
- }
+ TclFreeIntRep(objPtr);
indexRep = (IndexRep *) ckalloc(sizeof(IndexRep));
- objPtr->internalRep.otherValuePtr = (VOID *) indexRep;
- objPtr->typePtr = &tclIndexType;
+ objPtr->internalRep.otherValuePtr = indexRep;
+ objPtr->typePtr = &indexType;
}
- indexRep->tablePtr = (VOID*) tablePtr;
+ indexRep->tablePtr = (void *) tablePtr;
indexRep->offset = offset;
indexRep->index = index;
*indexPtr = index;
return TCL_OK;
- error:
+ error:
if (interp != NULL) {
/*
* Produce a fancy error message.
*/
+
int count;
TclNewObj(resultPtr);
Tcl_SetObjResult(interp, resultPtr);
Tcl_AppendStringsToObj(resultPtr, (numAbbrev > 1) &&
- !(flags & TCL_EXACT) ? "ambiguous " : "bad ", msg, " \"",
- key, "\": must be ", STRING_AT(tablePtr,offset,0), (char*)NULL);
+ !(flags & TCL_EXACT) ? "ambiguous " : "bad ", msg, " \"", key,
+ "\": must be ", STRING_AT(tablePtr, offset, 0), NULL);
for (entryPtr = NEXT_ENTRY(tablePtr, offset), count = 0;
*entryPtr != NULL;
entryPtr = NEXT_ENTRY(entryPtr, offset), count++) {
if (*NEXT_ENTRY(entryPtr, offset) == NULL) {
- Tcl_AppendStringsToObj(resultPtr,
- (count > 0) ? ", or " : " or ", *entryPtr,
- (char *) NULL);
+ Tcl_AppendStringsToObj(resultPtr, ((count > 0) ? "," : ""),
+ " or ", *entryPtr, NULL);
} else {
- Tcl_AppendStringsToObj(resultPtr, ", ", *entryPtr,
- (char *) NULL);
+ Tcl_AppendStringsToObj(resultPtr, ", ", *entryPtr, NULL);
}
}
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", msg, key, NULL);
}
return TCL_ERROR;
}
@@ -288,14 +283,14 @@ Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags,
*
* SetIndexFromAny --
*
- * This procedure is called to convert a Tcl object to index
- * internal form. However, this doesn't make sense (need to have a
- * table of keywords in order to do the conversion) so the
- * procedure always generates an error.
+ * This function is called to convert a Tcl object to index internal
+ * form. However, this doesn't make sense (need to have a table of
+ * keywords in order to do the conversion) so the function always
+ * generates an error.
*
* Results:
- * The return value is always TCL_ERROR, and an error message is
- * left in interp's result if interp isn't NULL.
+ * The return value is always TCL_ERROR, and an error message is left in
+ * interp's result if interp isn't NULL.
*
* Side effects:
* None.
@@ -304,14 +299,14 @@ Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags,
*/
static int
-SetIndexFromAny(interp, objPtr)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- register Tcl_Obj *objPtr; /* The object to convert. */
+SetIndexFromAny(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ register Tcl_Obj *objPtr) /* The object to convert. */
{
if (interp) {
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
"can't convert value to index except via Tcl_GetIndexFromObj API",
- -1);
+ -1));
}
return TCL_ERROR;
}
@@ -321,9 +316,8 @@ SetIndexFromAny(interp, objPtr)
*
* UpdateStringOfIndex --
*
- * This procedure is called to convert a Tcl object from index
- * internal form to its string form. No abbreviation is ever
- * generated.
+ * This function is called to convert a Tcl object from index internal
+ * form to its string form. No abbreviation is ever generated.
*
* Results:
* None.
@@ -335,13 +329,13 @@ SetIndexFromAny(interp, objPtr)
*/
static void
-UpdateStringOfIndex(objPtr)
- Tcl_Obj *objPtr;
+UpdateStringOfIndex(
+ Tcl_Obj *objPtr)
{
- IndexRep *indexRep = (IndexRep *) objPtr->internalRep.otherValuePtr;
+ IndexRep *indexRep = objPtr->internalRep.otherValuePtr;
register char *buf;
register unsigned len;
- register CONST char *indexStr = EXPAND_OF(indexRep);
+ register const char *indexStr = EXPAND_OF(indexRep);
len = strlen(indexStr);
buf = (char *) ckalloc(len + 1);
@@ -355,29 +349,30 @@ UpdateStringOfIndex(objPtr)
*
* DupIndex --
*
- * This procedure is called to copy the internal rep of an index
- * Tcl object from to another object.
+ * This function is called to copy the internal rep of an index Tcl
+ * object from to another object.
*
* Results:
* None.
*
* Side effects:
- * The internal representation of the target object is updated
- * and the type is set.
+ * The internal representation of the target object is updated and the
+ * type is set.
*
*----------------------------------------------------------------------
*/
static void
-DupIndex(srcPtr, dupPtr)
- Tcl_Obj *srcPtr, *dupPtr;
+DupIndex(
+ Tcl_Obj *srcPtr,
+ Tcl_Obj *dupPtr)
{
- IndexRep *srcIndexRep = (IndexRep *) srcPtr->internalRep.otherValuePtr;
+ IndexRep *srcIndexRep = srcPtr->internalRep.otherValuePtr;
IndexRep *dupIndexRep = (IndexRep *) ckalloc(sizeof(IndexRep));
memcpy(dupIndexRep, srcIndexRep, sizeof(IndexRep));
- dupPtr->internalRep.otherValuePtr = (VOID *) dupIndexRep;
- dupPtr->typePtr = &tclIndexType;
+ dupPtr->internalRep.otherValuePtr = dupIndexRep;
+ dupPtr->typePtr = &indexType;
}
/*
@@ -385,8 +380,8 @@ DupIndex(srcPtr, dupPtr)
*
* FreeIndex --
*
- * This procedure is called to delete the internal rep of an index
- * Tcl object.
+ * This function is called to delete the internal rep of an index Tcl
+ * object.
*
* Results:
* None.
@@ -398,10 +393,11 @@ DupIndex(srcPtr, dupPtr)
*/
static void
-FreeIndex(objPtr)
- Tcl_Obj *objPtr;
+FreeIndex(
+ Tcl_Obj *objPtr)
{
ckfree((char *) objPtr->internalRep.otherValuePtr);
+ objPtr->typePtr = NULL;
}
/*
@@ -409,70 +405,241 @@ FreeIndex(objPtr)
*
* Tcl_WrongNumArgs --
*
- * This procedure generates a "wrong # args" error message in an
- * interpreter. It is used as a utility function by many command
- * procedures.
+ * This function generates a "wrong # args" error message in an
+ * interpreter. It is used as a utility function by many command
+ * functions, including the function that implements procedures.
*
* Results:
* None.
*
* Side effects:
- * An error message is generated in interp's result object to
- * indicate that a command was invoked with the wrong number of
- * arguments. The message has the form
+ * An error message is generated in interp's result object to indicate
+ * that a command was invoked with the wrong number of arguments. The
+ * message has the form
* wrong # args: should be "foo bar additional stuff"
- * where "foo" and "bar" are the initial objects in objv (objc
- * determines how many of these are printed) and "additional stuff"
- * is the contents of the message argument.
+ * where "foo" and "bar" are the initial objects in objv (objc determines
+ * how many of these are printed) and "additional stuff" is the contents
+ * of the message argument.
+ *
+ * The message printed is modified somewhat if the command is wrapped
+ * inside an ensemble. In that case, the error message generated is
+ * rewritten in such a way that it appears to be generated from the
+ * user-visible command and not how that command is actually implemented,
+ * giving a better overall user experience.
+ *
+ * Internally, the Tcl core may set the flag INTERP_ALTERNATE_WRONG_ARGS
+ * in the interpreter to generate complex multi-part messages by calling
+ * this function repeatedly. This allows the code that knows how to
+ * handle ensemble-related error messages to be kept here while still
+ * generating suitable error messages for commands like [read] and
+ * [socket]. Ideally, this would be done through an extra flags argument,
+ * but that wouldn't be source-compatible with the existing API and it's
+ * a fairly rare requirement anyway.
*
*----------------------------------------------------------------------
*/
void
-Tcl_WrongNumArgs(interp, objc, objv, message)
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments to print
- * from objv. */
- Tcl_Obj *CONST objv[]; /* Initial argument objects, which
- * should be included in the error
- * message. */
- CONST char *message; /* Error message to print after the
- * leading objects in objv. The
- * message may be NULL. */
+Tcl_WrongNumArgs(
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments to print from objv. */
+ Tcl_Obj *const objv[], /* Initial argument objects, which should be
+ * included in the error message. */
+ const char *message) /* Error message to print after the leading
+ * objects in objv. The message may be
+ * NULL. */
{
Tcl_Obj *objPtr;
- int i;
- register IndexRep *indexRep;
+ int i, len, elemLen, flags;
+ Interp *iPtr = (Interp *) interp;
+ const char *elementStr;
+
+ /*
+ * [incr Tcl] does something fairly horrific when generating error
+ * messages for its ensembles; it passes the whole set of ensemble
+ * arguments as a list in the first argument. This means that this code
+ * causes a problem in iTcl if it attempts to correctly quote all
+ * arguments, which would be the correct thing to do. We work around this
+ * nasty behaviour for now, and hope that we can remove it all in the
+ * future...
+ */
+
+#ifndef AVOID_HACKS_FOR_ITCL
+ int isFirst = 1; /* Special flag used to inhibit the treating
+ * of the first word as a list element so the
+ * hacky way Itcl generates error messages for
+ * its ensembles will still work. [Bug
+ * 1066837] */
+# define MAY_QUOTE_WORD (!isFirst)
+# define AFTER_FIRST_WORD (isFirst = 0)
+#else /* !AVOID_HACKS_FOR_ITCL */
+# define MAY_QUOTE_WORD 1
+# define AFTER_FIRST_WORD (void) 0
+#endif /* AVOID_HACKS_FOR_ITCL */
TclNewObj(objPtr);
- Tcl_SetObjResult(interp, objPtr);
- Tcl_AppendToObj(objPtr, "wrong # args: should be \"", -1);
+ if (iPtr->flags & INTERP_ALTERNATE_WRONG_ARGS) {
+ Tcl_AppendObjToObj(objPtr, Tcl_GetObjResult(interp));
+ Tcl_AppendToObj(objPtr, " or \"", -1);
+ } else {
+ Tcl_AppendToObj(objPtr, "wrong # args: should be \"", -1);
+ }
+
+ /*
+ * Check to see if we are processing an ensemble implementation, and if so
+ * rewrite the results in terms of how the ensemble was invoked.
+ */
+
+ if (iPtr->ensembleRewrite.sourceObjs != NULL) {
+ int toSkip = iPtr->ensembleRewrite.numInsertedObjs;
+ int toPrint = iPtr->ensembleRewrite.numRemovedObjs;
+ Tcl_Obj *const *origObjv = iPtr->ensembleRewrite.sourceObjs;
+
+ /*
+ * We only know how to do rewriting if all the replaced objects are
+ * actually arguments (in objv) to this function. Otherwise it just
+ * gets too complicated and we'd be better off just giving a slightly
+ * confusing error message...
+ */
+
+ if (objc < toSkip) {
+ goto addNormalArgumentsToMessage;
+ }
+
+ /*
+ * Strip out the actual arguments that the ensemble inserted.
+ */
+
+ objv += toSkip;
+ objc -= toSkip;
+
+ /*
+ * We assume no object is of index type.
+ */
+
+ for (i=0 ; i<toPrint ; i++) {
+ /*
+ * Add the element, quoting it if necessary.
+ */
+
+ if (origObjv[i]->typePtr == &indexType) {
+ register IndexRep *indexRep =
+ origObjv[i]->internalRep.otherValuePtr;
+
+ elementStr = EXPAND_OF(indexRep);
+ elemLen = strlen(elementStr);
+ } else if (origObjv[i]->typePtr == &tclEnsembleCmdType) {
+ register EnsembleCmdRep *ecrPtr =
+ origObjv[i]->internalRep.otherValuePtr;
+
+ elementStr = ecrPtr->fullSubcmdName;
+ elemLen = strlen(elementStr);
+ } else {
+ elementStr = TclGetStringFromObj(origObjv[i], &elemLen);
+ }
+ flags = 0;
+ len = TclScanElement(elementStr, elemLen, &flags);
+
+ if (MAY_QUOTE_WORD && len != elemLen) {
+ char *quotedElementStr = TclStackAlloc(interp,
+ (unsigned)len + 1);
+
+ len = TclConvertElement(elementStr, elemLen,
+ quotedElementStr, flags);
+ Tcl_AppendToObj(objPtr, quotedElementStr, len);
+ TclStackFree(interp, quotedElementStr);
+ } else {
+ Tcl_AppendToObj(objPtr, elementStr, elemLen);
+ }
+
+ AFTER_FIRST_WORD;
+
+ /*
+ * Add a space if the word is not the last one (which has a
+ * moderately complex condition here).
+ */
+
+ if (i<toPrint-1 || objc!=0 || message!=NULL) {
+ Tcl_AppendStringsToObj(objPtr, " ", NULL);
+ }
+ }
+ }
+
+ /*
+ * Now add the arguments (other than those rewritten) that the caller took
+ * from its calling context.
+ */
+
+ addNormalArgumentsToMessage:
for (i = 0; i < objc; i++) {
/*
- * If the object is an index type use the index table which allows
- * for the correct error message even if the subcommand was
- * abbreviated. Otherwise, just use the string rep.
+ * If the object is an index type use the index table which allows for
+ * the correct error message even if the subcommand was abbreviated.
+ * Otherwise, just use the string rep.
*/
-
- if (objv[i]->typePtr == &tclIndexType) {
- indexRep = (IndexRep *) objv[i]->internalRep.otherValuePtr;
- Tcl_AppendStringsToObj(objPtr, EXPAND_OF(indexRep), (char *) NULL);
+
+ if (objv[i]->typePtr == &indexType) {
+ register IndexRep *indexRep = objv[i]->internalRep.otherValuePtr;
+
+ Tcl_AppendStringsToObj(objPtr, EXPAND_OF(indexRep), NULL);
+ } else if (objv[i]->typePtr == &tclEnsembleCmdType) {
+ register EnsembleCmdRep *ecrPtr =
+ objv[i]->internalRep.otherValuePtr;
+
+ Tcl_AppendStringsToObj(objPtr, ecrPtr->fullSubcmdName, NULL);
} else {
- Tcl_AppendStringsToObj(objPtr, Tcl_GetString(objv[i]),
- (char *) NULL);
+ /*
+ * Quote the argument if it contains spaces (Bug 942757).
+ */
+
+ elementStr = TclGetStringFromObj(objv[i], &elemLen);
+ flags = 0;
+ len = TclScanElement(elementStr, elemLen, &flags);
+
+ if (MAY_QUOTE_WORD && len != elemLen) {
+ char *quotedElementStr = TclStackAlloc(interp,
+ (unsigned) len + 1);
+
+ len = TclConvertElement(elementStr, elemLen,
+ quotedElementStr, flags);
+ Tcl_AppendToObj(objPtr, quotedElementStr, len);
+ TclStackFree(interp, quotedElementStr);
+ } else {
+ Tcl_AppendToObj(objPtr, elementStr, elemLen);
+ }
}
+ AFTER_FIRST_WORD;
+
/*
* Append a space character (" ") if there is more text to follow
* (either another element from objv, or the message string).
*/
- if ((i < (objc - 1)) || message) {
- Tcl_AppendStringsToObj(objPtr, " ", (char *) NULL);
+
+ if (i<objc-1 || message!=NULL) {
+ Tcl_AppendStringsToObj(objPtr, " ", NULL);
}
}
- if (message) {
- Tcl_AppendStringsToObj(objPtr, message, (char *) NULL);
+ /*
+ * Add any trailing message bits and set the resulting string as the
+ * interpreter result. Caller is responsible for reporting this as an
+ * actual error.
+ */
+
+ if (message != NULL) {
+ Tcl_AppendStringsToObj(objPtr, message, NULL);
}
- Tcl_AppendStringsToObj(objPtr, "\"", (char *) NULL);
+ Tcl_AppendStringsToObj(objPtr, "\"", NULL);
+ Tcl_SetObjResult(interp, objPtr);
+#undef MAY_QUOTE_WORD
+#undef AFTER_FIRST_WORD
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclInitScript.h b/generic/tclInitScript.h
deleted file mode 100644
index a3a1d6a..0000000
--- a/generic/tclInitScript.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * tclInitScript.h --
- *
- * This file contains Unix & Windows common init script
- * It is not used on the Mac. (the mac init script is in tclMacInit.c)
- *
- * Copyright (c) 1998 Sun Microsystems, Inc.
- * Copyright (c) 1999 by Scriptics Corporation.
- * All rights reserved.
- */
-
-/*
- * In order to find init.tcl during initialization, the following script
- * is invoked by Tcl_Init(). It looks in several different directories:
- *
- * $tcl_library - can specify a primary location, if set
- * no other locations will be checked
- *
- * $env(TCL_LIBRARY) - highest priority so user can always override
- * the search path unless the application has
- * specified an exact directory above
- *
- * $tclDefaultLibrary - this value is initialized by TclPlatformInit
- * from a static C variable that was set at
- * compile time
- *
- * $tcl_libPath - this value is initialized by a call to
- * TclGetLibraryPath called from Tcl_Init.
- *
- * The first directory on this path that contains a valid init.tcl script
- * will be set as the value of tcl_library.
- *
- * Note that this entire search mechanism can be bypassed by defining an
- * alternate tclInit procedure before calling Tcl_Init().
- */
-
-static char initScript[] = "if {[info proc tclInit]==\"\"} {\n\
- proc tclInit {} {\n\
- global tcl_libPath tcl_library errorInfo\n\
- global env tclDefaultLibrary\n\
- rename tclInit {}\n\
- set errors {}\n\
- set dirs {}\n\
- if {[info exists tcl_library]} {\n\
- lappend dirs $tcl_library\n\
- } else {\n\
- if {[info exists env(TCL_LIBRARY)]} {\n\
- lappend dirs $env(TCL_LIBRARY)\n\
- }\n\
- catch {\n\
- lappend dirs $tclDefaultLibrary\n\
- unset tclDefaultLibrary\n\
- }\n\
- set dirs [concat $dirs $tcl_libPath]\n\
- }\n\
- foreach i $dirs {\n\
- set tcl_library $i\n\
- set tclfile [file join $i init.tcl]\n\
- if {[file exists $tclfile]} {\n\
- if {![catch {uplevel #0 [list source $tclfile]} msg]} {\n\
- return\n\
- } else {\n\
- append errors \"$tclfile: $msg\n$errorInfo\n\"\n\
- }\n\
- }\n\
- }\n\
- set msg \"Can't find a usable init.tcl in the following directories: \n\"\n\
- append msg \" $dirs\n\n\"\n\
- append msg \"$errors\n\n\"\n\
- append msg \"This probably means that Tcl wasn't installed properly.\n\"\n\
- error $msg\n\
- }\n\
-}\n\
-tclInit";
-
-
-/*
- * A pointer to a string that holds an initialization script that if non-NULL
- * is evaluated in Tcl_Init() prior to the the built-in initialization script
- * above. This variable can be modified by the procedure below.
- */
-
-static char * tclPreInitScript = NULL;
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TclSetPreInitScript --
- *
- * This routine is used to change the value of the internal
- * variable, tclPreInitScript.
- *
- * Results:
- * Returns the current value of tclPreInitScript.
- *
- * Side effects:
- * Changes the way Tcl_Init() routine behaves.
- *
- *----------------------------------------------------------------------
- */
-
-char *
-TclSetPreInitScript (string)
- char *string; /* Pointer to a script. */
-{
- char *prevString = tclPreInitScript;
- tclPreInitScript = string;
- return(prevString);
-}
diff --git a/generic/tclInt.decls b/generic/tclInt.decls
index 4fb88c6..e30379e 100644
--- a/generic/tclInt.decls
+++ b/generic/tclInt.decls
@@ -8,12 +8,13 @@
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
+# Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
library tcl
-
+
# Define the unsupported generic interfaces.
interface tclInt
@@ -27,20 +28,20 @@ interface tclInt
#declare 0 generic {
# int TclAccess(CONST char *path, int mode)
#}
-declare 1 generic {
- int TclAccessDeleteProc(TclAccessProc_ *proc)
-}
-declare 2 generic {
- int TclAccessInsertProc(TclAccessProc_ *proc)
-}
+#declare 1 generic {
+# int TclAccessDeleteProc(TclAccessProc_ *proc)
+#}
+#declare 2 generic {
+# int TclAccessInsertProc(TclAccessProc_ *proc)
+#}
declare 3 generic {
void TclAllocateFreeObjects(void)
}
# Replaced by TclpChdir in 8.1:
-# declare 4 generic {
+# declare 4 generic {
# int TclChdir(Tcl_Interp *interp, char *dirName)
# }
-declare 5 {unix win} {
+declare 5 generic {
int TclCleanupChildren(Tcl_Interp *interp, int numPids, Tcl_Pid *pidPtr,
Tcl_Channel errorChan)
}
@@ -57,13 +58,13 @@ declare 8 generic {
# TclCreatePipeline unofficially exported for use by BLT.
-declare 9 {unix win} {
+declare 9 generic {
int TclCreatePipeline(Tcl_Interp *interp, int argc, CONST char **argv,
Tcl_Pid **pidArrayPtr, TclFile *inPipePtr, TclFile *outPipePtr,
TclFile *errFilePtr)
}
declare 10 generic {
- int TclCreateProc(Tcl_Interp *interp, Namespace *nsPtr,
+ int TclCreateProc(Tcl_Interp *interp, Namespace *nsPtr,
CONST char *procName,
Tcl_Obj *argsPtr, Tcl_Obj *bodyPtr, Proc **procPtrPtr)
}
@@ -71,14 +72,15 @@ declare 11 generic {
void TclDeleteCompiledLocalVars(Interp *iPtr, CallFrame *framePtr)
}
declare 12 generic {
- void TclDeleteVars(Interp *iPtr, Tcl_HashTable *tablePtr)
-}
-declare 13 generic {
- int TclDoGlob(Tcl_Interp *interp, char *separators,
- Tcl_DString *headPtr, char *tail, Tcl_GlobTypeData *types)
+ void TclDeleteVars(Interp *iPtr, TclVarHashTable *tablePtr)
}
+# Removed in 8.5
+#declare 13 generic {
+# int TclDoGlob(Tcl_Interp *interp, char *separators,
+# Tcl_DString *headPtr, char *tail, Tcl_GlobTypeData *types)
+#}
declare 14 generic {
- void TclDumpMemoryInfo(FILE *outFile)
+ int TclDumpMemoryInfo(ClientData clientData, int flags)
}
# Removed in 8.1:
# declare 15 generic {
@@ -109,8 +111,9 @@ declare 22 generic {
int *sizePtr, int *bracePtr)
}
declare 23 generic {
- Proc * TclFindProc(Interp *iPtr, CONST char *procName)
+ Proc *TclFindProc(Interp *iPtr, CONST char *procName)
}
+# Replaced with macro (see tclInt.h) in Tcl 8.5.0, restored in 8.5.10
declare 24 generic {
int TclFormatInt(char *buffer, long n)
}
@@ -118,42 +121,44 @@ declare 25 generic {
void TclFreePackageInfo(Interp *iPtr)
}
# Removed in 8.1:
-# declare 26 generic {
-# char * TclGetCwd(Tcl_Interp *interp)
+# declare 26 generic {
+# char *TclGetCwd(Tcl_Interp *interp)
# }
-declare 27 generic {
- int TclGetDate(char *p, Tcl_WideInt now, long zone,
- Tcl_WideInt *timePtr)
-}
+# Removed in 8.5
+#declare 27 generic {
+# int TclGetDate(char *p, unsigned long now, long zone,
+# unsigned long *timePtr)
+#}
declare 28 generic {
Tcl_Channel TclpGetDefaultStdChannel(int type)
}
# Removed in 8.4b2:
#declare 29 generic {
-# Tcl_Obj * TclGetElementOfIndexedArray(Tcl_Interp *interp,
+# Tcl_Obj *TclGetElementOfIndexedArray(Tcl_Interp *interp,
# int localIndex, Tcl_Obj *elemPtr, int flags)
#}
-# Replaced by char * TclGetEnv(CONST char *name, Tcl_DString *valuePtr) in 8.1:
+# Replaced by char *TclGetEnv(CONST char *name, Tcl_DString *valuePtr) in 8.1:
# declare 30 generic {
-# char * TclGetEnv(CONST char *name)
+# char *TclGetEnv(CONST char *name)
# }
declare 31 generic {
- char * TclGetExtension(char *name)
+ CONST char *TclGetExtension(CONST char *name)
}
declare 32 generic {
int TclGetFrame(Tcl_Interp *interp, CONST char *str,
CallFrame **framePtrPtr)
}
-declare 33 generic {
- TclCmdProcType TclGetInterpProc(void)
-}
+# Removed in Tcl 8.5
+#declare 33 generic {
+# TclCmdProcType TclGetInterpProc(void)
+#}
declare 34 generic {
int TclGetIntForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr,
int endValue, int *indexPtr)
}
# Removed in 8.4b2:
#declare 35 generic {
-# Tcl_Obj * TclGetIndexedScalar(Tcl_Interp *interp, int localIndex,
+# Tcl_Obj *TclGetIndexedScalar(Tcl_Interp *interp, int localIndex,
# int flags)
#}
declare 36 generic {
@@ -178,11 +183,13 @@ declare 41 generic {
Tcl_Command TclGetOriginalCommand(Tcl_Command command)
}
declare 42 generic {
- char * TclpGetUserHome(CONST char *name, Tcl_DString *bufferPtr)
-}
-declare 43 generic {
- int TclGlobalInvoke(Tcl_Interp *interp, int argc, CONST84 char **argv, int flags)
+ char *TclpGetUserHome(CONST char *name, Tcl_DString *bufferPtr)
}
+# Removed in Tcl 8.5a2
+#declare 43 generic {
+# int TclGlobalInvoke(Tcl_Interp *interp, int argc, CONST84 char **argv,
+# int flags)
+#}
declare 44 generic {
int TclGuessPackageName(CONST char *fileName, Tcl_DString *bufPtr)
}
@@ -194,18 +201,18 @@ declare 46 generic {
}
# Removed in 8.4b2:
#declare 47 generic {
-# Tcl_Obj * TclIncrElementOfIndexedArray(Tcl_Interp *interp,
+# Tcl_Obj *TclIncrElementOfIndexedArray(Tcl_Interp *interp,
# int localIndex, Tcl_Obj *elemPtr, long incrAmount)
#}
# Removed in 8.4b2:
#declare 48 generic {
-# Tcl_Obj * TclIncrIndexedScalar(Tcl_Interp *interp, int localIndex,
+# Tcl_Obj *TclIncrIndexedScalar(Tcl_Interp *interp, int localIndex,
# long incrAmount)
#}
-declare 49 generic {
- Tcl_Obj * TclIncrVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
- Tcl_Obj *part2Ptr, long incrAmount, int part1NotParsed)
-}
+#declare 49 generic {
+# Tcl_Obj *TclIncrVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
+# Tcl_Obj *part2Ptr, long incrAmount, int part1NotParsed)
+#}
declare 50 generic {
void TclInitCompiledLocals(Tcl_Interp *interp, CallFrame *framePtr,
Namespace *nsPtr)
@@ -213,9 +220,11 @@ declare 50 generic {
declare 51 generic {
int TclInterpInit(Tcl_Interp *interp)
}
-declare 52 generic {
- int TclInvoke(Tcl_Interp *interp, int argc, CONST84 char **argv, int flags)
-}
+# Removed in Tcl 8.5a2
+#declare 52 generic {
+# int TclInvoke(Tcl_Interp *interp, int argc, CONST84 char **argv,
+# int flags)
+#}
declare 53 generic {
int TclInvokeObjectCommand(ClientData clientData, Tcl_Interp *interp,
int argc, CONST84 char **argv)
@@ -225,7 +234,7 @@ declare 54 generic {
int objc, Tcl_Obj *CONST objv[])
}
declare 55 generic {
- Proc * TclIsProc(Command *cmdPtr)
+ Proc *TclIsProc(Command *cmdPtr)
}
# Replaced with TclpLoadFile in 8.1:
# declare 56 generic {
@@ -238,7 +247,7 @@ declare 55 generic {
# int TclLooksLikeInt(char *p)
# }
declare 58 generic {
- Var * TclLookupVar(Tcl_Interp *interp, CONST char *part1, CONST char *part2,
+ Var *TclLookupVar(Tcl_Interp *interp, CONST char *part1, CONST char *part2,
int flags, CONST char *msg, int createPart1, int createPart2,
Var **arrayPtrPtr)
}
@@ -251,7 +260,7 @@ declare 60 generic {
int TclNeedSpace(CONST char *start, CONST char *end)
}
declare 61 generic {
- Tcl_Obj * TclNewProcBodyObj(Proc *procPtr)
+ Tcl_Obj *TclNewProcBodyObj(Proc *procPtr)
}
declare 62 generic {
int TclObjCommandComplete(Tcl_Obj *cmdPtr)
@@ -264,22 +273,23 @@ declare 64 generic {
int TclObjInvoke(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[],
int flags)
}
-declare 65 generic {
- int TclObjInvokeGlobal(Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[], int flags)
-}
-declare 66 generic {
- int TclOpenFileChannelDeleteProc(TclOpenFileChannelProc_ *proc)
-}
-declare 67 generic {
- int TclOpenFileChannelInsertProc(TclOpenFileChannelProc_ *proc)
-}
+# Removed in Tcl 8.5a2
+#declare 65 generic {
+# int TclObjInvokeGlobal(Tcl_Interp *interp, int objc,
+# Tcl_Obj *CONST objv[], int flags)
+#}
+#declare 66 generic {
+# int TclOpenFileChannelDeleteProc(TclOpenFileChannelProc_ *proc)
+#}
+#declare 67 generic {
+# int TclOpenFileChannelInsertProc(TclOpenFileChannelProc_ *proc)
+#}
# Replaced by Tcl_FSAccess in 8.4:
#declare 68 generic {
# int TclpAccess(CONST char *path, int mode)
#}
declare 69 generic {
- char * TclpAlloc(unsigned int size)
+ char *TclpAlloc(unsigned int size)
}
#declare 70 generic {
# int TclpCopyFile(CONST char *source, CONST char *dest)
@@ -308,9 +318,8 @@ declare 76 generic {
declare 77 generic {
void TclpGetTime(Tcl_Time *time)
}
-
declare 78 generic {
- int TclpGetTimeZone(Tcl_WideInt time)
+ int TclpGetTimeZone(unsigned long time)
}
# Replaced by Tcl_FSListVolumes in 8.4:
#declare 79 generic {
@@ -322,7 +331,7 @@ declare 78 generic {
# char *modeString, int permissions)
#}
declare 81 generic {
- char * TclpRealloc(char *ptr, unsigned int size)
+ char *TclpRealloc(char *ptr, unsigned int size)
}
#declare 82 generic {
# int TclpRemoveDirectory(CONST char *path, int recursive,
@@ -348,7 +357,7 @@ declare 81 generic {
# void TclPlatformInit(Tcl_Interp *interp)
# }
declare 88 generic {
- char * TclPrecTraceProc(ClientData clientData, Tcl_Interp *interp,
+ char *TclPrecTraceProc(ClientData clientData, Tcl_Interp *interp,
CONST char *name1, CONST char *name2, int flags)
}
declare 89 generic {
@@ -370,16 +379,18 @@ declare 92 generic {
declare 93 generic {
void TclProcDeleteProc(ClientData clientData)
}
-declare 94 generic {
- int TclProcInterpProc(ClientData clientData, Tcl_Interp *interp,
- int argc, CONST84 char **argv)
-}
+# Removed in Tcl 8.5:
+#declare 94 generic {
+# int TclProcInterpProc(ClientData clientData, Tcl_Interp *interp,
+# int argc, CONST84 char **argv)
+#}
# Replaced by Tcl_FSStat in 8.4:
#declare 95 generic {
# int TclpStat(CONST char *path, Tcl_StatBuf *buf)
#}
declare 96 generic {
- int TclRenameCommand(Tcl_Interp *interp, char *oldName, char *newName)
+ int TclRenameCommand(Tcl_Interp *interp, CONST char *oldName,
+ CONST char *newName)
}
declare 97 generic {
void TclResetShadowedCmdRefs(Tcl_Interp *interp, Command *newCmdPtr)
@@ -389,37 +400,37 @@ declare 98 generic {
}
# Removed in 8.4b2:
#declare 99 generic {
-# Tcl_Obj * TclSetElementOfIndexedArray(Tcl_Interp *interp, int localIndex,
+# Tcl_Obj *TclSetElementOfIndexedArray(Tcl_Interp *interp, int localIndex,
# Tcl_Obj *elemPtr, Tcl_Obj *objPtr, int flags)
#}
# Removed in 8.4b2:
#declare 100 generic {
-# Tcl_Obj * TclSetIndexedScalar(Tcl_Interp *interp, int localIndex,
+# Tcl_Obj *TclSetIndexedScalar(Tcl_Interp *interp, int localIndex,
# Tcl_Obj *objPtr, int flags)
#}
declare 101 generic {
- char * TclSetPreInitScript(char *string)
+ char *TclSetPreInitScript(char *string)
}
declare 102 generic {
void TclSetupEnv(Tcl_Interp *interp)
}
declare 103 generic {
- int TclSockGetPort(Tcl_Interp *interp, char *str, char *proto,
+ int TclSockGetPort(Tcl_Interp *interp, CONST char *str, CONST char *proto,
int *portPtr)
}
-declare 104 {unix win} {
+declare 104 generic {
int TclSockMinimumBuffers(int sock, int size)
}
# Replaced by Tcl_FSStat in 8.4:
#declare 105 generic {
# int TclStat(CONST char *path, Tcl_StatBuf *buf)
#}
-declare 106 generic {
- int TclStatDeleteProc(TclStatProc_ *proc)
-}
-declare 107 generic {
- int TclStatInsertProc(TclStatProc_ *proc)
-}
+#declare 106 generic {
+# int TclStatDeleteProc(TclStatProc_ *proc)
+#}
+#declare 107 generic {
+# int TclStatInsertProc(TclStatProc_ *proc)
+#}
declare 108 generic {
void TclTeardownNamespace(Namespace *nsPtr)
}
@@ -428,7 +439,7 @@ declare 109 generic {
}
# Removed in 8.1:
# declare 110 generic {
-# char * TclWordEnd(char *start, char *lastChar, int nested, int *semiPtr)
+# char *TclWordEnd(char *start, char *lastChar, int nested, int *semiPtr)
# }
# Procedures used in conjunction with Tcl namespaces. They are
@@ -444,7 +455,7 @@ declare 112 generic {
Tcl_Obj *objPtr)
}
declare 113 generic {
- Tcl_Namespace * Tcl_CreateNamespace(Tcl_Interp *interp, CONST char *name,
+ Tcl_Namespace *Tcl_CreateNamespace(Tcl_Interp *interp, CONST char *name,
ClientData clientData, Tcl_NamespaceDeleteProc *deleteProc)
}
declare 114 generic {
@@ -459,7 +470,7 @@ declare 116 generic {
Tcl_Namespace *contextNsPtr, int flags)
}
declare 117 generic {
- Tcl_Namespace * Tcl_FindNamespace(Tcl_Interp *interp, CONST char *name,
+ Tcl_Namespace *Tcl_FindNamespace(Tcl_Interp *interp, CONST char *name,
Tcl_Namespace *contextNsPtr, int flags)
}
declare 118 generic {
@@ -486,10 +497,10 @@ declare 123 generic {
Tcl_Obj *objPtr)
}
declare 124 generic {
- Tcl_Namespace * Tcl_GetCurrentNamespace(Tcl_Interp *interp)
+ Tcl_Namespace *Tcl_GetCurrentNamespace(Tcl_Interp *interp)
}
declare 125 generic {
- Tcl_Namespace * Tcl_GetGlobalNamespace(Tcl_Interp *interp)
+ Tcl_Namespace *Tcl_GetGlobalNamespace(Tcl_Interp *interp)
}
declare 126 generic {
void Tcl_GetVariableFullName(Tcl_Interp *interp, Tcl_Var variable,
@@ -500,12 +511,12 @@ declare 127 generic {
CONST char *pattern, int allowOverwrite)
}
declare 128 generic {
- void Tcl_PopCallFrame(Tcl_Interp* interp)
+ void Tcl_PopCallFrame(Tcl_Interp *interp)
}
declare 129 generic {
- int Tcl_PushCallFrame(Tcl_Interp* interp, Tcl_CallFrame *framePtr,
+ int Tcl_PushCallFrame(Tcl_Interp *interp, Tcl_CallFrame *framePtr,
Tcl_Namespace *nsPtr, int isProcCallFrame)
-}
+}
declare 130 generic {
int Tcl_RemoveInterpResolvers(Tcl_Interp *interp, CONST char *name)
}
@@ -518,15 +529,16 @@ declare 132 generic {
int TclpHasSockets(Tcl_Interp *interp)
}
declare 133 generic {
- struct tm * TclpGetDate(TclpTime_t time, int useGMT)
-}
-declare 134 generic {
- size_t TclpStrftime(char *s, size_t maxsize, CONST char *format,
- CONST struct tm *t, int useGMT)
-}
-declare 135 generic {
- int TclpCheckStackSpace(void)
+ struct tm *TclpGetDate(CONST time_t *time, int useGMT)
}
+# Removed in 8.5
+#declare 134 generic {
+# size_t TclpStrftime(char *s, size_t maxsize, CONST char *format,
+# CONST struct tm *t, int useGMT)
+#}
+#declare 135 generic {
+# int TclpCheckStackSpace(void)
+#}
# Added in 8.1:
@@ -534,16 +546,16 @@ declare 135 generic {
# int TclpChdir(CONST char *dirName)
#}
declare 138 generic {
- CONST84_RETURN char * TclGetEnv(CONST char *name, Tcl_DString *valuePtr)
+ CONST84_RETURN char *TclGetEnv(CONST char *name, Tcl_DString *valuePtr)
}
#declare 139 generic {
# int TclpLoadFile(Tcl_Interp *interp, char *fileName, char *sym1,
# char *sym2, Tcl_PackageInitProc **proc1Ptr,
# Tcl_PackageInitProc **proc2Ptr, ClientData *clientDataPtr)
#}
-declare 140 generic {
- int TclLooksLikeInt(CONST char *bytes, int length)
-}
+#declare 140 generic {
+# int TclLooksLikeInt(CONST char *bytes, int length)
+#}
# This is used by TclX, but should otherwise be considered private
declare 141 generic {
CONST84_RETURN char *TclpGetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr)
@@ -563,19 +575,15 @@ declare 144 generic {
declare 145 generic {
struct AuxDataType *TclGetAuxDataType(char *typeName)
}
-
declare 146 generic {
- TclHandle TclHandleCreate(VOID *ptr)
+ TclHandle TclHandleCreate(void *ptr)
}
-
declare 147 generic {
void TclHandleFree(TclHandle handle)
}
-
declare 148 generic {
TclHandle TclHandlePreserve(TclHandle handle)
}
-
declare 149 generic {
void TclHandleRelease(TclHandle handle)
}
@@ -589,7 +597,6 @@ declare 151 generic {
void TclRegExpRangeUniChar(Tcl_RegExp re, int index, int *startPtr,
int *endPtr)
}
-
declare 152 generic {
void TclSetLibraryPath(Tcl_Obj *pathPtr)
}
@@ -608,11 +615,11 @@ declare 153 generic {
#}
declare 156 generic {
- void TclRegError (Tcl_Interp *interp, CONST char *msg,
+ void TclRegError(Tcl_Interp *interp, CONST char *msg,
int status)
}
declare 157 generic {
- Var * TclVarTraceExists (Tcl_Interp *interp, CONST char *varName)
+ Var *TclVarTraceExists(Tcl_Interp *interp, CONST char *varName)
}
declare 158 generic {
void TclSetStartupScriptFileName(CONST char *filename)
@@ -622,7 +629,8 @@ declare 159 generic {
}
#declare 160 generic {
# int TclpMatchFilesTypes(Tcl_Interp *interp, char *separators,
-# Tcl_DString *dirPtr, char *pattern, char *tail, GlobTypeData *types)
+# Tcl_DString *dirPtr, char *pattern, char *tail,
+# GlobTypeData *types)
#}
# new in 8.3.2/8.4a2
@@ -634,13 +642,13 @@ declare 162 generic {
void TclChannelEventScriptInvoker(ClientData clientData, int flags)
}
-# ALERT: The result of 'TclGetInstructionTable' is actually an
+# ALERT: The result of 'TclGetInstructionTable' is actually a
# "InstructionDesc*" but we do not want to describe this structure in
# "tclInt.h". It is described in "tclCompile.h". Use a cast to the
# correct type when calling this procedure.
declare 163 generic {
- VOID *TclGetInstructionTable(void)
+ void *TclGetInstructionTable(void)
}
# ALERT: The argument of 'TclExpandCodeArray' is actually a
@@ -648,7 +656,7 @@ declare 163 generic {
# "tclInt.h". It is described in "tclCompile.h".
declare 164 generic {
- void TclExpandCodeArray(VOID *envPtr)
+ void TclExpandCodeArray(void *envPtr)
}
# These functions are vfs aware, but are generally only useful internally.
@@ -658,7 +666,7 @@ declare 165 generic {
# New function due to TIP #33
declare 166 generic {
- int TclListObjSetElement(Tcl_Interp *interp, Tcl_Obj *listPtr,
+ int TclListObjSetElement(Tcl_Interp *interp, Tcl_Obj *listPtr,
int index, Tcl_Obj *valuePtr)
}
@@ -674,16 +682,15 @@ declare 169 generic {
int TclpUtfNcmp2(CONST char *s1, CONST char *s2, unsigned long n)
}
declare 170 generic {
- int TclCheckInterpTraces (Tcl_Interp *interp, CONST char *command, int numChars, \
- Command *cmdPtr, int result, int traceFlags, int objc, \
- Tcl_Obj *CONST objv[])
+ int TclCheckInterpTraces(Tcl_Interp *interp, CONST char *command,
+ int numChars, Command *cmdPtr, int result, int traceFlags,
+ int objc, Tcl_Obj *CONST objv[])
}
declare 171 generic {
- int TclCheckExecutionTraces (Tcl_Interp *interp, CONST char *command, int numChars, \
- Command *cmdPtr, int result, int traceFlags, int objc, \
- Tcl_Obj *CONST objv[])
+ int TclCheckExecutionTraces(Tcl_Interp *interp, CONST char *command,
+ int numChars, Command *cmdPtr, int result, int traceFlags,
+ int objc, Tcl_Obj *CONST objv[])
}
-
declare 172 generic {
int TclInThreadExit(void)
}
@@ -691,157 +698,275 @@ declare 172 generic {
# added for 8.4.2
declare 173 generic {
- int TclUniCharMatch (CONST Tcl_UniChar *string, int strLen, \
- CONST Tcl_UniChar *pattern, int ptnLen, int nocase)
+ int TclUniCharMatch(CONST Tcl_UniChar *string, int strLen,
+ CONST Tcl_UniChar *pattern, int ptnLen, int flags)
}
-# TclpGmtime and TclpLocaltime promoted to the generic interface from unix
+# added for 8.4.3
-declare 182 generic {
- struct tm *TclpLocaltime(TclpTime_t_CONST clock)
+#declare 174 generic {
+# Tcl_Obj *TclIncrWideVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
+# Tcl_Obj *part2Ptr, Tcl_WideInt wideIncrAmount, int part1NotParsed)
+#}
+
+# Factoring out of trace code
+
+declare 175 generic {
+ int TclCallVarTraces(Interp *iPtr, Var *arrayPtr, Var *varPtr,
+ CONST char *part1, CONST char *part2, int flags, int leaveErrMsg)
}
-declare 183 generic {
- struct tm *TclpGmtime(TclpTime_t_CONST clock)
+declare 176 generic {
+ void TclCleanupVar(Var *varPtr, Var *arrayPtr)
}
-
-declare 199 generic {
- int TclMatchIsTrivial(CONST char *pattern)
+declare 177 generic {
+ void TclVarErrMsg(Tcl_Interp *interp, CONST char *part1, CONST char *part2,
+ CONST char *operation, CONST char *reason)
+}
+declare 178 generic {
+ void Tcl_SetStartupScript(Tcl_Obj *pathPtr, CONST char* encodingName)
+}
+declare 179 generic {
+ Tcl_Obj *Tcl_GetStartupScript(CONST char **encodingNamePtr)
}
-##############################################################################
+# REMOVED
+# Allocate lists without copying arrays
+# declare 180 generic {
+# Tcl_Obj *TclNewListObjDirect(int objc, Tcl_Obj **objv)
+# }
+#declare 181 generic {
+# Tcl_Obj *TclDbNewListObjDirect(int objc, Tcl_Obj **objv,
+# CONST char *file, int line)
+#}
-# Define the platform specific internal Tcl interface. These functions are
-# only available on the designated platform.
+# TclpGmtime and TclpLocaltime promoted to the generic interface from unix
-interface tclIntPlat
+declare 182 generic {
+ struct tm *TclpLocaltime(CONST time_t *clock)
+}
+declare 183 generic {
+ struct tm *TclpGmtime(CONST time_t *clock)
+}
+
+# For the new "Thread Storage" subsystem.
+
+### REMOVED on grounds it should never have been exposed. All these
+### functions are now either static in tclThreadStorage.c or
+### MODULE_SCOPE.
+# declare 184 generic {
+# void TclThreadStorageLockInit(void)
+# }
+# declare 185 generic {
+# void TclThreadStorageLock(void)
+# }
+# declare 186 generic {
+# void TclThreadStorageUnlock(void)
+# }
+# declare 187 generic {
+# void TclThreadStoragePrint(FILE *outFile, int flags)
+# }
+# declare 188 generic {
+# Tcl_HashTable *TclThreadStorageGetHashTable(Tcl_ThreadId id)
+# }
+# declare 189 generic {
+# Tcl_HashTable *TclThreadStorageInit(Tcl_ThreadId id, void *reserved)
+# }
+# declare 190 generic {
+# void TclThreadStorageDataKeyInit(Tcl_ThreadDataKey *keyPtr)
+# }
+# declare 191 generic {
+# void *TclThreadStorageDataKeyGet(Tcl_ThreadDataKey *keyPtr)
+# }
+# declare 192 generic {
+# void TclThreadStorageDataKeySet(Tcl_ThreadDataKey *keyPtr, void *data)
+# }
+# declare 193 generic {
+# void TclFinalizeThreadStorageThread(Tcl_ThreadId id)
+# }
+# declare 194 generic {
+# void TclFinalizeThreadStorage(void)
+# }
+# declare 195 generic {
+# void TclFinalizeThreadStorageData(Tcl_ThreadDataKey *keyPtr)
+# }
+# declare 196 generic {
+# void TclFinalizeThreadStorageDataKey(Tcl_ThreadDataKey *keyPtr)
+# }
-########################
-# Mac specific internals
+#
+# Added in tcl8.5a5 for compiler/executor experimentation.
+# Disabled in Tcl 8.5.1; experiments terminated. :/
+#
+#declare 197 generic {
+# int TclCompEvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+# CONST CmdFrame *invoker, int word)
+#}
+declare 198 generic {
+ int TclObjGetFrame(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ CallFrame **framePtrPtr)
+}
-declare 0 mac {
- VOID * TclpSysAlloc(long size, int isBin)
+#declare 199 generic {
+# int TclMatchIsTrivial(CONST char *pattern)
+#}
+
+# 200-208 exported for use by the test suite [Bug 1054748]
+declare 200 generic {
+ int TclpObjRemoveDirectory(Tcl_Obj *pathPtr, int recursive,
+ Tcl_Obj **errorPtr)
}
-declare 1 mac {
- void TclpSysFree(VOID *ptr)
+declare 201 generic {
+ int TclpObjCopyDirectory(Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr,
+ Tcl_Obj **errorPtr)
}
-declare 2 mac {
- VOID * TclpSysRealloc(VOID *cp, unsigned int size)
+declare 202 generic {
+ int TclpObjCreateDirectory(Tcl_Obj *pathPtr)
}
-declare 3 mac {
- void TclpExit(int status)
+declare 203 generic {
+ int TclpObjDeleteFile(Tcl_Obj *pathPtr)
}
-
-# Prototypes for functions found in the tclMacUtil.c compatability library.
-
-declare 4 mac {
- int FSpGetDefaultDir(FSSpecPtr theSpec)
+declare 204 generic {
+ int TclpObjCopyFile(Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr)
}
-declare 5 mac {
- int FSpSetDefaultDir(FSSpecPtr theSpec)
+declare 205 generic {
+ int TclpObjRenameFile(Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr)
}
-declare 6 mac {
- OSErr FSpFindFolder(short vRefNum, OSType folderType,
- Boolean createFolder, FSSpec *spec)
+declare 206 generic {
+ int TclpObjStat(Tcl_Obj *pathPtr, Tcl_StatBuf *buf)
}
-declare 7 mac {
- void GetGlobalMouseTcl(Point *mouse)
+declare 207 generic {
+ int TclpObjAccess(Tcl_Obj *pathPtr, int mode)
}
-
-# The following routines are utility functions in Tcl. They are exported
-# here because they are needed in Tk. They are not officially supported,
-# however. The first set are from the MoreFiles package.
-
-declare 8 mac {
- pascal OSErr FSpGetDirectoryIDTcl(CONST FSSpec *spec, long *theDirID,
- Boolean *isDirectory)
+declare 208 generic {
+ Tcl_Channel TclpOpenFileChannel(Tcl_Interp *interp,
+ Tcl_Obj *pathPtr, int mode, int permissions)
+}
+# Made public by TIP 258
+#declare 209 generic {
+# Tcl_Obj *TclGetEncodingSearchPath(void)
+#}
+#declare 210 generic {
+# int TclSetEncodingSearchPath(Tcl_Obj *searchPath)
+#}
+#declare 211 generic {
+# CONST char *TclpGetEncodingNameFromEnvironment(Tcl_DString *bufPtr)
+#}
+declare 212 generic {
+ void TclpFindExecutable(CONST char *argv0)
}
-declare 9 mac {
- pascal short FSpOpenResFileCompatTcl(CONST FSSpec *spec,
- SignedByte permission)
+declare 213 generic {
+ Tcl_Obj *TclGetObjNameOfExecutable(void)
}
-declare 10 mac {
- pascal void FSpCreateResFileCompatTcl(CONST FSSpec *spec, OSType creator,
- OSType fileType, ScriptCode scriptTag)
+declare 214 generic {
+ void TclSetObjNameOfExecutable(Tcl_Obj *name, Tcl_Encoding encoding)
}
-
-# Like the MoreFiles routines these fix problems in the standard
-# Mac calls. These routines are from tclMacUtils.h.
-
-declare 11 mac {
- int FSpLocationFromPath(int length, CONST char *path, FSSpecPtr theSpec)
+declare 215 generic {
+ void *TclStackAlloc(Tcl_Interp *interp, int numBytes)
}
-declare 12 mac {
- OSErr FSpPathFromLocation(FSSpecPtr theSpec, int *length,
- Handle *fullPath)
+declare 216 generic {
+ void TclStackFree(Tcl_Interp *interp, void *freePtr)
+}
+declare 217 generic {
+ int TclPushStackFrame(Tcl_Interp *interp, Tcl_CallFrame **framePtrPtr,
+ Tcl_Namespace *namespacePtr, int isProcCallFrame)
+}
+declare 218 generic {
+ void TclPopStackFrame(Tcl_Interp *interp)
}
-# Prototypes of Mac only internal functions.
+# for use in tclTest.c
+declare 224 generic {
+ TclPlatformType *TclGetPlatform(void)
+}
-declare 13 mac {
- void TclMacExitHandler(void)
+#
+declare 225 generic {
+ Tcl_Obj *TclTraceDictPath(Tcl_Interp *interp, Tcl_Obj *rootPtr,
+ int keyc, Tcl_Obj *CONST keyv[], int flags)
}
-declare 14 mac {
- void TclMacInitExitToShell(int usePatch)
+declare 226 generic {
+ int TclObjBeingDeleted(Tcl_Obj *objPtr)
}
-declare 15 mac {
- OSErr TclMacInstallExitToShellPatch(ExitToShellProcPtr newProc)
+declare 227 generic {
+ void TclSetNsPath(Namespace *nsPtr, int pathLength,
+ Tcl_Namespace *pathAry[])
}
-declare 16 mac {
- int TclMacOSErrorToPosixError(int error)
+declare 228 generic {
+ int TclObjInterpProcCore(register Tcl_Interp *interp, Tcl_Obj *procNameObj,
+ int skip, ProcErrorProc errorProc)
}
-declare 17 mac {
- void TclMacRemoveTimer(VOID *timerToken)
+declare 229 generic {
+ int TclPtrMakeUpvar(Tcl_Interp *interp, Var *otherP1Ptr,
+ CONST char *myName, int myFlags, int index)
}
-declare 18 mac {
- VOID *TclMacStartTimer(long ms)
+declare 230 generic {
+ Var *TclObjLookupVar(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
+ CONST char *part2, int flags, CONST char *msg,
+ CONST int createPart1, CONST int createPart2, Var **arrayPtrPtr)
}
-declare 19 mac {
- int TclMacTimerExpired(VOID *timerToken)
+declare 231 generic {
+ int TclGetNamespaceFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ Tcl_Namespace **nsPtrPtr)
}
-declare 20 mac {
- int TclMacRegisterResourceFork(short fileRef, Tcl_Obj *tokenPtr,
- int insert)
-}
-declare 21 mac {
- short TclMacUnRegisterResourceFork(char *tokenPtr, Tcl_Obj *resultPtr)
-}
-declare 22 mac {
- int TclMacCreateEnv(void)
+
+# Bits and pieces of TIP#280's guts
+declare 232 generic {
+ int TclEvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags,
+ CONST CmdFrame *invoker, int word)
}
-declare 23 mac {
- FILE * TclMacFOpenHack(CONST char *path, CONST char *mode)
+declare 233 generic {
+ void TclGetSrcInfoForPc(CmdFrame *contextPtr)
}
-# Replaced in 8.1 by TclpReadLink:
-# declare 24 mac {
-# int TclMacReadlink(char *path, char *buf, int size)
-# }
-declare 24 mac {
- char * TclpGetTZName(int isdst)
+
+# Exports for VarReform compat: Itcl, XOTcl like to peek into our varTables :(
+declare 234 generic {
+ Var *TclVarHashCreateVar(TclVarHashTable *tablePtr, CONST char *key,
+ int *newPtr)
}
-declare 25 mac {
- int TclMacChmod(CONST char *path, int mode)
+declare 235 generic {
+ void TclInitVarHashTable(TclVarHashTable *tablePtr, Namespace *nsPtr)
}
-# version of FSpLocationFromPath that doesn't resolve the last path component
-declare 26 mac {
- int FSpLLocationFromPath(int length, CONST char *path, FSSpecPtr theSpec)
+
+
+# TIP 337 made this one public
+declare 236 generic {
+ void TclBackgroundException(Tcl_Interp *interp, int code)
+}
+
+# Tcl_Obj leak detection support.
+declare 243 generic {
+ void TclDbDumpActiveObjects(FILE *outFile)
}
-############################
-# Windows specific internals
+declare 249 {
+ char* TclDoubleDigits(double dv, int ndigits, int flags,
+ int* decpt, int* signum, char** endPtr)
+}
+
+
+##############################################################################
+
+# Define the platform specific internal Tcl interface. These functions are
+# only available on the designated platform.
+
+interface tclIntPlat
+
+################################
+# Windows specific functions
declare 0 win {
- void TclWinConvertError(DWORD errCode)
+ void TclWinConvertError(unsigned long errCode)
}
declare 1 win {
- void TclWinConvertWSAError(DWORD errCode)
+ void TclWinConvertWSAError(unsigned long errCode)
}
declare 2 win {
- struct servent * TclWinGetServByName(CONST char *nm,
+ struct servent *TclWinGetServByName(CONST char *nm,
CONST char *proto)
}
declare 3 win {
- int TclWinGetSockOpt(SOCKET s, int level, int optname,
- char FAR * optval, int FAR *optlen)
+ int TclWinGetSockOpt(int s, int level, int optname,
+ char FAR *optval, int FAR *optlen)
}
declare 4 win {
HINSTANCE TclWinGetTclInstance(void)
@@ -854,8 +979,8 @@ declare 6 win {
u_short TclWinNToHS(u_short ns)
}
declare 7 win {
- int TclWinSetSockOpt(SOCKET s, int level, int optname,
- CONST char FAR * optval, int optlen)
+ int TclWinSetSockOpt(int s, int level, int optname,
+ CONST char FAR *optval, int optlen)
}
declare 8 win {
unsigned long TclpGetPid(Tcl_Pid pid)
@@ -893,7 +1018,7 @@ declare 15 win {
# TclFile TclpCreateTempFile(char *contents, Tcl_DString *namePtr)
# }
# declare 17 win {
-# char * TclpGetTZName(void)
+# char *TclpGetTZName(void)
# }
declare 18 win {
TclFile TclpMakeFile(Tcl_Channel channel, int direction)
@@ -902,7 +1027,7 @@ declare 19 win {
TclFile TclpOpenFile(CONST char *fname, int mode)
}
declare 20 win {
- void TclWinAddProcess(HANDLE hProcess, DWORD id)
+ void TclWinAddProcess(void *hProcess, unsigned long id)
}
# removed permanently for 8.4
@@ -915,14 +1040,15 @@ declare 22 win {
TclFile TclpCreateTempFile(CONST char *contents)
}
declare 23 win {
- char * TclpGetTZName(int isdst)
+ char *TclpGetTZName(int isdst)
}
declare 24 win {
- char * TclWinNoBackslash(char *path)
-}
-declare 25 win {
- TclPlatformType *TclWinGetPlatform(void)
+ char *TclWinNoBackslash(char *path)
}
+# replaced by generic TclGetPlatform
+#declare 25 win {
+# TclPlatformType *TclWinGetPlatform(void)
+#}
declare 26 win {
void TclWinSetInterfaces(int wide)
}
@@ -930,7 +1056,7 @@ declare 26 win {
# Added in Tcl 8.3.3 / 8.4
declare 27 win {
- void TclWinFlushDirtyChannels (void)
+ void TclWinFlushDirtyChannels(void)
}
# Added in 8.4.2
@@ -938,13 +1064,12 @@ declare 27 win {
declare 28 win {
void TclWinResetInterfaces(void)
}
-
declare 29 win {
- int TclWinCPUID( unsigned int index, unsigned int *regs )
+ int TclWinCPUID(unsigned int index, unsigned int *regs)
}
-#########################
-# Unix specific internals
+################################
+# Unix specific functions
# Pipe channel functions
@@ -989,21 +1114,52 @@ declare 9 unix {
# Added in 8.4:
declare 10 unix {
- Tcl_DirEntry * TclpReaddir(DIR * dir)
+ Tcl_DirEntry *TclpReaddir(DIR *dir)
}
-
# Slots 11 and 12 are forwarders for functions that were promoted to
# generic Stubs
-
declare 11 unix {
- struct tm * TclpLocaltime_unix(TclpTime_t_CONST clock)
+ struct tm *TclpLocaltime_unix(CONST time_t *clock)
}
-
declare 12 unix {
- struct tm * TclpGmtime_unix(TclpTime_t_CONST clock)
+ struct tm *TclpGmtime_unix(CONST time_t *clock)
}
-
declare 13 unix {
- char * TclpInetNtoa(struct in_addr addr)
+ char *TclpInetNtoa(struct in_addr addr)
+}
+
+# Added in 8.5:
+
+declare 14 unix {
+ int TclUnixCopyFile(CONST char *src, CONST char *dst,
+ CONST Tcl_StatBuf *statBufPtr, int dontCopyAtts)
+}
+
+################################
+# Mac OS X specific functions
+
+declare 15 macosx {
+ int TclMacOSXGetFileAttribute(Tcl_Interp *interp, int objIndex,
+ Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr)
+}
+declare 16 macosx {
+ int TclMacOSXSetFileAttribute(Tcl_Interp *interp, int objIndex,
+ Tcl_Obj *fileName, Tcl_Obj *attributePtr)
+}
+declare 17 macosx {
+ int TclMacOSXCopyFileAttributes(CONST char *src, CONST char *dst,
+ CONST Tcl_StatBuf *statBufPtr)
+}
+declare 18 macosx {
+ int TclMacOSXMatchType(Tcl_Interp *interp, CONST char *pathName,
+ CONST char *fileName, Tcl_StatBuf *statBufPtr,
+ Tcl_GlobTypeData *types)
+}
+declare 19 macosx {
+ void TclMacOSXNotifierAddRunLoopMode(CONST void *runLoopMode)
}
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/generic/tclInt.h b/generic/tclInt.h
index 20c1155..854404f 100644
--- a/generic/tclInt.h
+++ b/generic/tclInt.h
@@ -10,35 +10,34 @@
* Copyright (c) 2001, 2002 by Kevin B. Kenny. All rights reserved.
* Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#ifndef _TCLINT
#define _TCLINT
/*
- * Common include files needed by most of the Tcl source files are
- * included here, so that system-dependent personalizations for the
- * include files only have to be made in once place. This results
- * in a few extra includes, but greater modularity. The order of
- * the three groups of #includes is important. For example, stdio.h
- * is needed by tcl.h, and the _ANSI_ARGS_ declaration in tcl.h is
- * needed by stdlib.h in some configurations.
+ * Some numerics configuration options.
*/
-#ifndef _TCL
-#include "tcl.h"
-#endif
+#undef NO_WIDE_TYPE
+#undef ACCEPT_NAN
+
+/*
+ * Common include files needed by most of the Tcl source files are included
+ * here, so that system-dependent personalizations for the include files only
+ * have to be made in once place. This results in a few extra includes, but
+ * greater modularity. The order of the three groups of #includes is
+ * important. For example, stdio.h is needed by tcl.h, and the _ANSI_ARGS_
+ * declaration in tcl.h is needed by stdlib.h in some configurations.
+ */
+
+#include "tclPort.h"
#include <stdio.h>
#include <ctype.h>
-#ifdef NO_LIMITS_H
-# include "../compat/limits.h"
-#else
-# include <limits.h>
-#endif
#ifdef NO_STDLIB_H
# include "../compat/stdlib.h"
#else
@@ -49,9 +48,14 @@
#else
#include <string.h>
#endif
+#ifdef STDC_HEADERS
+#include <stddef.h>
+#else
+typedef int ptrdiff_t;
+#endif
/*
- * Ensure WORDS_BIGENDIAN is defined correcly:
+ * Ensure WORDS_BIGENDIAN is defined correctly:
* Needs to happen here in addition to configure to work with fat compiles on
* Darwin (where configure runs only once for multiple architectures).
*/
@@ -64,15 +68,15 @@
#endif
#ifdef BYTE_ORDER
# ifdef BIG_ENDIAN
-# if BYTE_ORDER == BIG_ENDIAN
-# undef WORDS_BIGENDIAN
-# define WORDS_BIGENDIAN 1
-# endif
+# if BYTE_ORDER == BIG_ENDIAN
+# undef WORDS_BIGENDIAN
+# define WORDS_BIGENDIAN 1
+# endif
# endif
# ifdef LITTLE_ENDIAN
-# if BYTE_ORDER == LITTLE_ENDIAN
-# undef WORDS_BIGENDIAN
-# endif
+# if BYTE_ORDER == LITTLE_ENDIAN
+# undef WORDS_BIGENDIAN
+# endif
# endif
#endif
@@ -89,66 +93,83 @@
# endif
#endif
-#undef TCL_STORAGE_CLASS
-#ifdef BUILD_tcl
-# define TCL_STORAGE_CLASS DLLEXPORT
-#else
-# ifdef USE_TCL_STUBS
-# define TCL_STORAGE_CLASS
-# else
-# define TCL_STORAGE_CLASS DLLIMPORT
-# endif
+/*
+ * When Tcl_WideInt and long are the same type, there's no value in
+ * having a tclWideIntType separate from the tclIntType.
+ */
+#ifdef TCL_WIDE_INT_IS_LONG
+#define NO_WIDE_TYPE
#endif
/*
- * The following procedures allow namespaces to be customized to
- * support special name resolution rules for commands/variables.
- *
+ * Macros used to cast between pointers and integers (e.g. when storing an int
+ * in ClientData), on 64-bit architectures they avoid gcc warning about "cast
+ * to/from pointer from/to integer of different size".
+ */
+
+#if !defined(INT2PTR) && !defined(PTR2INT)
+# if defined(HAVE_INTPTR_T) || defined(intptr_t)
+# define INT2PTR(p) ((void *)(intptr_t)(p))
+# define PTR2INT(p) ((int)(intptr_t)(p))
+# else
+# define INT2PTR(p) ((void *)(p))
+# define PTR2INT(p) ((int)(p))
+# endif
+#endif
+#if !defined(UINT2PTR) && !defined(PTR2UINT)
+# if defined(HAVE_UINTPTR_T) || defined(uintptr_t)
+# define UINT2PTR(p) ((void *)(uintptr_t)(p))
+# define PTR2UINT(p) ((unsigned int)(uintptr_t)(p))
+# else
+# define UINT2PTR(p) ((void *)(p))
+# define PTR2UINT(p) ((unsigned int)(p))
+# endif
+#endif
+
+/*
+ * The following procedures allow namespaces to be customized to support
+ * special name resolution rules for commands/variables.
*/
struct Tcl_ResolvedVarInfo;
-typedef Tcl_Var (Tcl_ResolveRuntimeVarProc) _ANSI_ARGS_((
- Tcl_Interp* interp, struct Tcl_ResolvedVarInfo *vinfoPtr));
+typedef Tcl_Var (Tcl_ResolveRuntimeVarProc)(Tcl_Interp *interp,
+ struct Tcl_ResolvedVarInfo *vinfoPtr);
-typedef void (Tcl_ResolveVarDeleteProc) _ANSI_ARGS_((
- struct Tcl_ResolvedVarInfo *vinfoPtr));
+typedef void (Tcl_ResolveVarDeleteProc)(struct Tcl_ResolvedVarInfo *vinfoPtr);
/*
* The following structure encapsulates the routines needed to resolve a
- * variable reference at runtime. Any variable specific state will typically
+ * variable reference at runtime. Any variable specific state will typically
* be appended to this structure.
*/
-
typedef struct Tcl_ResolvedVarInfo {
Tcl_ResolveRuntimeVarProc *fetchProc;
Tcl_ResolveVarDeleteProc *deleteProc;
} Tcl_ResolvedVarInfo;
+typedef int (Tcl_ResolveCompiledVarProc)(Tcl_Interp *interp,
+ CONST84 char *name, int length, Tcl_Namespace *context,
+ Tcl_ResolvedVarInfo **rPtr);
+typedef int (Tcl_ResolveVarProc)(Tcl_Interp *interp, CONST84 char *name,
+ Tcl_Namespace *context, int flags, Tcl_Var *rPtr);
-typedef int (Tcl_ResolveCompiledVarProc) _ANSI_ARGS_((
- Tcl_Interp* interp, CONST84 char* name, int length,
- Tcl_Namespace *context, Tcl_ResolvedVarInfo **rPtr));
+typedef int (Tcl_ResolveCmdProc)(Tcl_Interp *interp, CONST84 char *name,
+ Tcl_Namespace *context, int flags, Tcl_Command *rPtr);
-typedef int (Tcl_ResolveVarProc) _ANSI_ARGS_((
- Tcl_Interp* interp, CONST84 char* name, Tcl_Namespace *context,
- int flags, Tcl_Var *rPtr));
-
-typedef int (Tcl_ResolveCmdProc) _ANSI_ARGS_((Tcl_Interp* interp,
- CONST84 char* name, Tcl_Namespace *context, int flags,
- Tcl_Command *rPtr));
-
typedef struct Tcl_ResolverInfo {
- Tcl_ResolveCmdProc *cmdResProc; /* Procedure handling command name
- * resolution. */
- Tcl_ResolveVarProc *varResProc; /* Procedure handling variable name
- * resolution for variables that
- * can only be handled at runtime. */
+ Tcl_ResolveCmdProc *cmdResProc;
+ /* Procedure handling command name
+ * resolution. */
+ Tcl_ResolveVarProc *varResProc;
+ /* Procedure handling variable name resolution
+ * for variables that can only be handled at
+ * runtime. */
Tcl_ResolveCompiledVarProc *compiledVarResProc;
- /* Procedure handling variable name
- * resolution at compile time. */
+ /* Procedure handling variable name resolution
+ * at compile time. */
} Tcl_ResolverInfo;
/*
@@ -157,427 +178,546 @@ typedef struct Tcl_ResolverInfo {
*----------------------------------------------------------------
*/
+typedef struct Tcl_Ensemble Tcl_Ensemble;
+typedef struct NamespacePathEntry NamespacePathEntry;
+
+/*
+ * Special hashtable for variables: this is just a Tcl_HashTable with an nsPtr
+ * field added at the end: in this way variables can find their namespace
+ * without having to copy a pointer in their struct: they can access it via
+ * their hPtr->tablePtr.
+ */
+
+typedef struct TclVarHashTable {
+ Tcl_HashTable table;
+ struct Namespace *nsPtr;
+} TclVarHashTable;
+
+/*
+ * This is for itcl - it likes to search our varTables directly :(
+ */
+
+#define TclVarHashFindVar(tablePtr, key) \
+ TclVarHashCreateVar((tablePtr), (key), NULL)
+
+
/*
* The structure below defines a namespace.
* Note: the first five fields must match exactly the fields in a
- * Tcl_Namespace structure (see tcl.h). If you change one, be sure to
- * change the other.
+ * Tcl_Namespace structure (see tcl.h). If you change one, be sure to change
+ * the other.
*/
typedef struct Namespace {
- char *name; /* The namespace's simple (unqualified)
- * name. This contains no ::'s. The name of
- * the global namespace is "" although "::"
- * is an synonym. */
- char *fullName; /* The namespace's fully qualified name.
- * This starts with ::. */
- ClientData clientData; /* An arbitrary value associated with this
- * namespace. */
+ char *name; /* The namespace's simple (unqualified) name.
+ * This contains no ::'s. The name of the
+ * global namespace is "" although "::" is an
+ * synonym. */
+ char *fullName; /* The namespace's fully qualified name. This
+ * starts with ::. */
+ ClientData clientData; /* An arbitrary value associated with this
+ * namespace. */
Tcl_NamespaceDeleteProc *deleteProc;
- /* Procedure invoked when deleting the
- * namespace to, e.g., free clientData. */
- struct Namespace *parentPtr; /* Points to the namespace that contains
- * this one. NULL if this is the global
- * namespace. */
- Tcl_HashTable childTable; /* Contains any child namespaces. Indexed
- * by strings; values have type
- * (Namespace *). */
- long nsId; /* Unique id for the namespace. */
- Tcl_Interp *interp; /* The interpreter containing this
- * namespace. */
- int flags; /* OR-ed combination of the namespace
- * status flags NS_DYING and NS_DEAD
- * listed below. */
- int activationCount; /* Number of "activations" or active call
- * frames for this namespace that are on
- * the Tcl call stack. The namespace won't
- * be freed until activationCount becomes
- * zero. */
- int refCount; /* Count of references by namespaceName *
- * objects. The namespace can't be freed
- * until refCount becomes zero. */
- Tcl_HashTable cmdTable; /* Contains all the commands currently
- * registered in the namespace. Indexed by
- * strings; values have type (Command *).
- * Commands imported by Tcl_Import have
- * Command structures that point (via an
- * ImportedCmdRef structure) to the
- * Command structure in the source
- * namespace's command table. */
- Tcl_HashTable varTable; /* Contains all the (global) variables
- * currently in this namespace. Indexed
- * by strings; values have type (Var *). */
- char **exportArrayPtr; /* Points to an array of string patterns
- * specifying which commands are exported.
- * A pattern may include "string match"
- * style wildcard characters to specify
- * multiple commands; however, no namespace
- * qualifiers are allowed. NULL if no
- * export patterns are registered. */
- int numExportPatterns; /* Number of export patterns currently
- * registered using "namespace export". */
- int maxExportPatterns; /* Mumber of export patterns for which
- * space is currently allocated. */
- int cmdRefEpoch; /* Incremented if a newly added command
- * shadows a command for which this
- * namespace has already cached a Command *
- * pointer; this causes all its cached
- * Command* pointers to be invalidated. */
- int resolverEpoch; /* Incremented whenever (a) the name resolution
- * rules change for this namespace or (b) a
- * newly added command shadows a command that
- * is compiled to bytecodes.
- * This invalidates all byte codes compiled
- * in the namespace, causing the code to be
- * recompiled under the new rules.*/
+ /* Procedure invoked when deleting the
+ * namespace to, e.g., free clientData. */
+ struct Namespace *parentPtr;/* Points to the namespace that contains this
+ * one. NULL if this is the global
+ * namespace. */
+ Tcl_HashTable childTable; /* Contains any child namespaces. Indexed by
+ * strings; values have type (Namespace *). */
+ long nsId; /* Unique id for the namespace. */
+ Tcl_Interp *interp; /* The interpreter containing this
+ * namespace. */
+ int flags; /* OR-ed combination of the namespace status
+ * flags NS_DYING and NS_DEAD listed below. */
+ int activationCount; /* Number of "activations" or active call
+ * frames for this namespace that are on the
+ * Tcl call stack. The namespace won't be
+ * freed until activationCount becomes zero. */
+ int refCount; /* Count of references by namespaceName
+ * objects. The namespace can't be freed until
+ * refCount becomes zero. */
+ Tcl_HashTable cmdTable; /* Contains all the commands currently
+ * registered in the namespace. Indexed by
+ * strings; values have type (Command *).
+ * Commands imported by Tcl_Import have
+ * Command structures that point (via an
+ * ImportedCmdRef structure) to the Command
+ * structure in the source namespace's command
+ * table. */
+ TclVarHashTable varTable; /* Contains all the (global) variables
+ * currently in this namespace. Indexed by
+ * strings; values have type (Var *). */
+ char **exportArrayPtr; /* Points to an array of string patterns
+ * specifying which commands are exported. A
+ * pattern may include "string match" style
+ * wildcard characters to specify multiple
+ * commands; however, no namespace qualifiers
+ * are allowed. NULL if no export patterns are
+ * registered. */
+ int numExportPatterns; /* Number of export patterns currently
+ * registered using "namespace export". */
+ int maxExportPatterns; /* Mumber of export patterns for which space
+ * is currently allocated. */
+ int cmdRefEpoch; /* Incremented if a newly added command
+ * shadows a command for which this namespace
+ * has already cached a Command* pointer; this
+ * causes all its cached Command* pointers to
+ * be invalidated. */
+ int resolverEpoch; /* Incremented whenever (a) the name
+ * resolution rules change for this namespace
+ * or (b) a newly added command shadows a
+ * command that is compiled to bytecodes. This
+ * invalidates all byte codes compiled in the
+ * namespace, causing the code to be
+ * recompiled under the new rules.*/
Tcl_ResolveCmdProc *cmdResProc;
- /* If non-null, this procedure overrides
- * the usual command resolution mechanism
- * in Tcl. This procedure is invoked
- * within Tcl_FindCommand to resolve all
- * command references within the namespace. */
+ /* If non-null, this procedure overrides the
+ * usual command resolution mechanism in Tcl.
+ * This procedure is invoked within
+ * Tcl_FindCommand to resolve all command
+ * references within the namespace. */
Tcl_ResolveVarProc *varResProc;
- /* If non-null, this procedure overrides
- * the usual variable resolution mechanism
- * in Tcl. This procedure is invoked
- * within Tcl_FindNamespaceVar to resolve all
- * variable references within the namespace
- * at runtime. */
+ /* If non-null, this procedure overrides the
+ * usual variable resolution mechanism in Tcl.
+ * This procedure is invoked within
+ * Tcl_FindNamespaceVar to resolve all
+ * variable references within the namespace at
+ * runtime. */
Tcl_ResolveCompiledVarProc *compiledVarResProc;
- /* If non-null, this procedure overrides
- * the usual variable resolution mechanism
- * in Tcl. This procedure is invoked
- * within LookupCompiledLocal to resolve
- * variable references within the namespace
- * at compile time. */
+ /* If non-null, this procedure overrides the
+ * usual variable resolution mechanism in Tcl.
+ * This procedure is invoked within
+ * LookupCompiledLocal to resolve variable
+ * references within the namespace at compile
+ * time. */
+ int exportLookupEpoch; /* Incremented whenever a command is added to
+ * a namespace, removed from a namespace or
+ * the exports of a namespace are changed.
+ * Allows TIP#112-driven command lists to be
+ * validated efficiently. */
+ Tcl_Ensemble *ensembles; /* List of structures that contain the details
+ * of the ensembles that are implemented on
+ * top of this namespace. */
+ Tcl_Obj *unknownHandlerPtr; /* A script fragment to be used when command
+ * resolution in this namespace fails. TIP
+ * 181. */
+ int commandPathLength; /* The length of the explicit path. */
+ NamespacePathEntry *commandPathArray;
+ /* The explicit path of the namespace as an
+ * array. */
+ NamespacePathEntry *commandPathSourceList;
+ /* Linked list of path entries that point to
+ * this namespace. */
} Namespace;
/*
+ * An entry on a namespace's command resolution path.
+ */
+
+struct NamespacePathEntry {
+ Namespace *nsPtr; /* What does this path entry point to? If it
+ * is NULL, this path entry points is
+ * redundant and should be skipped. */
+ Namespace *creatorNsPtr; /* Where does this path entry point from? This
+ * allows for efficient invalidation of
+ * references when the path entry's target
+ * updates its current list of defined
+ * commands. */
+ NamespacePathEntry *prevPtr, *nextPtr;
+ /* Linked list pointers or NULL at either end
+ * of the list that hangs off Namespace's
+ * commandPathSourceList field. */
+};
+
+/*
* Flags used to represent the status of a namespace:
*
* NS_DYING - 1 means Tcl_DeleteNamespace has been called to delete the
* namespace but there are still active call frames on the Tcl
* stack that refer to the namespace. When the last call frame
* referring to it has been popped, it's variables and command
- * will be destroyed and it will be marked "dead" (NS_DEAD).
- * The namespace can no longer be looked up by name.
+ * will be destroyed and it will be marked "dead" (NS_DEAD). The
+ * namespace can no longer be looked up by name.
* NS_DEAD - 1 means Tcl_DeleteNamespace has been called to delete the
- * namespace and no call frames still refer to it. Its
- * variables and command have already been destroyed. This bit
- * allows the namespace resolution code to recognize that the
- * namespace is "deleted". When the last namespaceName object
- * in any byte code code unit that refers to the namespace has
- * been freed (i.e., when the namespace's refCount is 0), the
- * namespace's storage will be freed.
+ * namespace and no call frames still refer to it. Its variables
+ * and command have already been destroyed. This bit allows the
+ * namespace resolution code to recognize that the namespace is
+ * "deleted". When the last namespaceName object in any byte code
+ * unit that refers to the namespace has been freed (i.e., when
+ * the namespace's refCount is 0), the namespace's storage will
+ * be freed.
* NS_KILLED 1 means that TclTeardownNamespace has already been called on
* this namespace and it should not be called again [Bug 1355942]
*/
#define NS_DYING 0x01
#define NS_DEAD 0x02
-#define NS_KILLED 0x04
+#define NS_KILLED 0x04
+
+/*
+ * Flags passed to TclGetNamespaceForQualName:
+ *
+ * TCL_GLOBAL_ONLY - (see tcl.h) Look only in the global ns.
+ * TCL_NAMESPACE_ONLY - (see tcl.h) Look only in the context ns.
+ * TCL_CREATE_NS_IF_UNKNOWN - Create unknown namespaces.
+ * TCL_FIND_ONLY_NS - The name sought is a namespace name.
+ */
+
+#define TCL_CREATE_NS_IF_UNKNOWN 0x800
+#define TCL_FIND_ONLY_NS 0x1000
+
+/*
+ * The data cached in an ensemble subcommand's Tcl_Obj rep (reference in
+ * otherValuePtr field). This structure is not shared between Tcl_Objs
+ * referring to the same subcommand, even where one is a duplicate of another.
+ */
+
+typedef struct {
+ Namespace *nsPtr; /* The namespace backing the ensemble which
+ * this is a subcommand of. */
+ int epoch; /* Used to confirm when the data in this
+ * really structure matches up with the
+ * ensemble. */
+ Tcl_Command token; /* Reference to the comamnd for which this
+ * structure is a cache of the resolution. */
+ char *fullSubcmdName; /* The full (local) name of the subcommand,
+ * allocated with ckalloc(). */
+ Tcl_Obj *realPrefixObj; /* Object containing the prefix words of the
+ * command that implements this ensemble
+ * subcommand. */
+} EnsembleCmdRep;
/*
- * Flag passed to TclGetNamespaceForQualName to have it create all namespace
- * components of a namespace-qualified name that cannot be found. The new
- * namespaces are created within their specified parent. Note that this
- * flag's value must not conflict with the values of the flags
- * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, and FIND_ONLY_NS (defined in
- * tclNamesp.c).
+ * Flag to enable bytecode compilation of an ensemble.
*/
-#define CREATE_NS_IF_UNKNOWN 0x800
+#define ENSEMBLE_COMPILE 0x4
/*
*----------------------------------------------------------------
- * Data structures related to variables. These are used primarily
- * in tclVar.c
+ * Data structures related to variables. These are used primarily in tclVar.c
*----------------------------------------------------------------
*/
/*
- * The following structure defines a variable trace, which is used to
- * invoke a specific C procedure whenever certain operations are performed
- * on a variable.
+ * The following structure defines a variable trace, which is used to invoke a
+ * specific C procedure whenever certain operations are performed on a
+ * variable.
*/
typedef struct VarTrace {
- Tcl_VarTraceProc *traceProc;/* Procedure to call when operations given
- * by flags are performed on variable. */
+ Tcl_VarTraceProc *traceProc;/* Procedure to call when operations given by
+ * flags are performed on variable. */
ClientData clientData; /* Argument to pass to proc. */
int flags; /* What events the trace procedure is
- * interested in: OR-ed combination of
+ * interested in: OR-ed combination of
* TCL_TRACE_READS, TCL_TRACE_WRITES,
* TCL_TRACE_UNSETS and TCL_TRACE_ARRAY. */
- struct VarTrace *nextPtr; /* Next in list of traces associated with
- * a particular variable. */
+ struct VarTrace *nextPtr; /* Next in list of traces associated with a
+ * particular variable. */
} VarTrace;
/*
- * The following structure defines a command trace, which is used to
- * invoke a specific C procedure whenever certain operations are performed
- * on a command.
+ * The following structure defines a command trace, which is used to invoke a
+ * specific C procedure whenever certain operations are performed on a
+ * command.
*/
typedef struct CommandTrace {
- Tcl_CommandTraceProc *traceProc;/* Procedure to call when operations given
- * by flags are performed on command. */
- ClientData clientData; /* Argument to pass to proc. */
- int flags; /* What events the trace procedure is
- * interested in: OR-ed combination of
- * TCL_TRACE_RENAME, TCL_TRACE_DELETE. */
- struct CommandTrace *nextPtr; /* Next in list of traces associated with
- * a particular command. */
- int refCount; /* Used to ensure this structure is
- * not deleted too early. Keeps track
- * of how many pieces of code have
- * a pointer to this structure. */
+ Tcl_CommandTraceProc *traceProc;
+ /* Procedure to call when operations given by
+ * flags are performed on command. */
+ ClientData clientData; /* Argument to pass to proc. */
+ int flags; /* What events the trace procedure is
+ * interested in: OR-ed combination of
+ * TCL_TRACE_RENAME, TCL_TRACE_DELETE. */
+ struct CommandTrace *nextPtr;
+ /* Next in list of traces associated with a
+ * particular command. */
+ int refCount; /* Used to ensure this structure is not
+ * deleted too early. Keeps track of how many
+ * pieces of code have a pointer to this
+ * structure. */
} CommandTrace;
/*
- * When a command trace is active (i.e. its associated procedure is
- * executing), one of the following structures is linked into a list
- * associated with the command's interpreter. The information in
- * the structure is needed in order for Tcl to behave reasonably
- * if traces are deleted while traces are active.
+ * When a command trace is active (i.e. its associated procedure is executing)
+ * one of the following structures is linked into a list associated with the
+ * command's interpreter. The information in the structure is needed in order
+ * for Tcl to behave reasonably if traces are deleted while traces are active.
*/
typedef struct ActiveCommandTrace {
struct Command *cmdPtr; /* Command that's being traced. */
struct ActiveCommandTrace *nextPtr;
- /* Next in list of all active command
- * traces for the interpreter, or NULL
- * if no more. */
- CommandTrace *nextTracePtr; /* Next trace to check after current
- * trace procedure returns; if this
- * trace gets deleted, must update pointer
- * to avoid using free'd memory. */
- int reverseScan; /* Boolean set true when the traces
- * are scanning in reverse order. */
+ /* Next in list of all active command traces
+ * for the interpreter, or NULL if no more. */
+ CommandTrace *nextTracePtr; /* Next trace to check after current trace
+ * procedure returns; if this trace gets
+ * deleted, must update pointer to avoid using
+ * free'd memory. */
+ int reverseScan; /* Boolean set true when traces are scanning
+ * in reverse order. */
} ActiveCommandTrace;
/*
* When a variable trace is active (i.e. its associated procedure is
- * executing), one of the following structures is linked into a list
- * associated with the variable's interpreter. The information in
- * the structure is needed in order for Tcl to behave reasonably
- * if traces are deleted while traces are active.
+ * executing) one of the following structures is linked into a list associated
+ * with the variable's interpreter. The information in the structure is needed
+ * in order for Tcl to behave reasonably if traces are deleted while traces
+ * are active.
*/
typedef struct ActiveVarTrace {
struct Var *varPtr; /* Variable that's being traced. */
struct ActiveVarTrace *nextPtr;
- /* Next in list of all active variable
- * traces for the interpreter, or NULL
- * if no more. */
- VarTrace *nextTracePtr; /* Next trace to check after current
- * trace procedure returns; if this
- * trace gets deleted, must update pointer
- * to avoid using free'd memory. */
+ /* Next in list of all active variable traces
+ * for the interpreter, or NULL if no more. */
+ VarTrace *nextTracePtr; /* Next trace to check after current trace
+ * procedure returns; if this trace gets
+ * deleted, must update pointer to avoid using
+ * free'd memory. */
} ActiveVarTrace;
/*
- * The following structure describes an enumerative search in progress on
- * an array variable; this are invoked with options to the "array"
- * command.
+ * The following structure describes an enumerative search in progress on an
+ * array variable; this are invoked with options to the "array" command.
*/
typedef struct ArraySearch {
int id; /* Integer id used to distinguish among
- * multiple concurrent searches for the
- * same array. */
+ * multiple concurrent searches for the same
+ * array. */
struct Var *varPtr; /* Pointer to array variable that's being
* searched. */
- Tcl_HashSearch search; /* Info kept by the hash module about
- * progress through the array. */
- Tcl_HashEntry *nextEntry; /* Non-null means this is the next element
- * to be enumerated (it's leftover from
- * the Tcl_FirstHashEntry call or from
- * an "array anymore" command). NULL
- * means must call Tcl_NextHashEntry
- * to get value to return. */
- struct ArraySearch *nextPtr;/* Next in list of all active searches
- * for this variable, or NULL if this is
- * the last one. */
+ Tcl_HashSearch search; /* Info kept by the hash module about progress
+ * through the array. */
+ Tcl_HashEntry *nextEntry; /* Non-null means this is the next element to
+ * be enumerated (it's leftover from the
+ * Tcl_FirstHashEntry call or from an "array
+ * anymore" command). NULL means must call
+ * Tcl_NextHashEntry to get value to
+ * return. */
+ struct ArraySearch *nextPtr;/* Next in list of all active searches for
+ * this variable, or NULL if this is the last
+ * one. */
} ArraySearch;
/*
- * The structure below defines a variable, which associates a string name
- * with a Tcl_Obj value. These structures are kept in procedure call frames
- * (for local variables recognized by the compiler) or in the heap (for
- * global variables and any variable not known to the compiler). For each
- * Var structure in the heap, a hash table entry holds the variable name and
- * a pointer to the Var structure.
+ * The structure below defines a variable, which associates a string name with
+ * a Tcl_Obj value. These structures are kept in procedure call frames (for
+ * local variables recognized by the compiler) or in the heap (for global
+ * variables and any variable not known to the compiler). For each Var
+ * structure in the heap, a hash table entry holds the variable name and a
+ * pointer to the Var structure.
*/
typedef struct Var {
+ int flags; /* Miscellaneous bits of information about
+ * variable. See below for definitions. */
union {
- Tcl_Obj *objPtr; /* The variable's object value. Used for
+ Tcl_Obj *objPtr; /* The variable's object value. Used for
* scalar variables and array elements. */
- Tcl_HashTable *tablePtr;/* For array variables, this points to
- * information about the hash table used
- * to implement the associative array.
- * Points to malloc-ed data. */
- struct Var *linkPtr; /* If this is a global variable being
- * referred to in a procedure, or a variable
- * created by "upvar", this field points to
- * the referenced variable's Var struct. */
+ TclVarHashTable *tablePtr;/* For array variables, this points to
+ * information about the hash table used to
+ * implement the associative array. Points to
+ * ckalloc-ed data. */
+ struct Var *linkPtr; /* If this is a global variable being referred
+ * to in a procedure, or a variable created by
+ * "upvar", this field points to the
+ * referenced variable's Var struct. */
} value;
- char *name; /* NULL if the variable is in a hashtable,
- * otherwise points to the variable's
- * name. It is used, e.g., by TclLookupVar
- * and "info locals". The storage for the
- * characters of the name is not owned by
- * the Var and must not be freed when
- * freeing the Var. */
- Namespace *nsPtr; /* Points to the namespace that contains
- * this variable or NULL if the variable is
- * a local variable in a Tcl procedure. */
- Tcl_HashEntry *hPtr; /* If variable is in a hashtable, either the
- * hash table entry that refers to this
- * variable or NULL if the variable has been
- * detached from its hash table (e.g. an
- * array is deleted, but some of its
- * elements are still referred to in
- * upvars). NULL if the variable is not in a
- * hashtable. This is used to delete an
- * variable from its hashtable if it is no
- * longer needed. */
- int refCount; /* Counts number of active uses of this
- * variable, not including its entry in the
- * call frame or the hash table: 1 for each
- * additional variable whose linkPtr points
- * here, 1 for each nested trace active on
- * variable, and 1 if the variable is a
- * namespace variable. This record can't be
- * deleted until refCount becomes 0. */
- VarTrace *tracePtr; /* First in list of all traces set for this
- * variable. */
- ArraySearch *searchPtr; /* First in list of all searches active
- * for this variable, or NULL if none. */
- int flags; /* Miscellaneous bits of information about
- * variable. See below for definitions. */
} Var;
-/*
- * Flag bits for variables. The first three (VAR_SCALAR, VAR_ARRAY, and
- * VAR_LINK) are mutually exclusive and give the "type" of the variable.
- * VAR_UNDEFINED is independent of the variable's type.
+typedef struct VarInHash {
+ Var var;
+ int refCount; /* Counts number of active uses of this
+ * variable: 1 for the entry in the hash
+ * table, 1 for each additional variable whose
+ * linkPtr points here, 1 for each nested
+ * trace active on variable, and 1 if the
+ * variable is a namespace variable. This
+ * record can't be deleted until refCount
+ * becomes 0. */
+ Tcl_HashEntry entry; /* The hash table entry that refers to this
+ * variable. This is used to find the name of
+ * the variable and to delete it from its
+ * hashtable if it is no longer needed. It
+ * also holds the variable's name. */
+} VarInHash;
+
+/*
+ * Flag bits for variables. The first two (VAR_ARRAY and VAR_LINK) are
+ * mutually exclusive and give the "type" of the variable. If none is set,
+ * this is a scalar variable.
+ *
+ * VAR_ARRAY - 1 means this is an array variable rather than
+ * a scalar variable or link. The "tablePtr"
+ * field points to the array's hashtable for its
+ * elements.
+ * VAR_LINK - 1 means this Var structure contains a pointer
+ * to another Var structure that either has the
+ * real value or is itself another VAR_LINK
+ * pointer. Variables like this come about
+ * through "upvar" and "global" commands, or
+ * through references to variables in enclosing
+ * namespaces.
+ *
+ * Flags that indicate the type and status of storage; none is set for
+ * compiled local variables (Var structs).
*
- * VAR_SCALAR - 1 means this is a scalar variable and not
- * an array or link. The "objPtr" field points
- * to the variable's value, a Tcl object.
- * VAR_ARRAY - 1 means this is an array variable rather
- * than a scalar variable or link. The
- * "tablePtr" field points to the array's
- * hashtable for its elements.
- * VAR_LINK - 1 means this Var structure contains a
- * pointer to another Var structure that
- * either has the real value or is itself
- * another VAR_LINK pointer. Variables like
- * this come about through "upvar" and "global"
- * commands, or through references to variables
- * in enclosing namespaces.
- * VAR_UNDEFINED - 1 means that the variable is in the process
- * of being deleted. An undefined variable
- * logically does not exist and survives only
- * while it has a trace, or if it is a global
- * variable currently being used by some
- * procedure.
* VAR_IN_HASHTABLE - 1 means this variable is in a hashtable and
- * the Var structure is malloced. 0 if it is
- * a local variable that was assigned a slot
- * in a procedure frame by the compiler so the
- * Var storage is part of the call frame.
- * VAR_TRACE_ACTIVE - 1 means that trace processing is currently
- * underway for a read or write access, so
- * new read or write accesses should not cause
- * trace procedures to be called and the
- * variable can't be deleted.
+ * the Var structure is malloced. 0 if it is a
+ * local variable that was assigned a slot in a
+ * procedure frame by the compiler so the Var
+ * storage is part of the call frame.
+ * VAR_DEAD_HASH 1 means that this var's entry in the hashtable
+ * has already been deleted.
* VAR_ARRAY_ELEMENT - 1 means that this variable is an array
- * element, so it is not legal for it to be
- * an array itself (the VAR_ARRAY flag had
- * better not be set).
- * VAR_NAMESPACE_VAR - 1 means that this variable was declared
- * as a namespace variable. This flag ensures
- * it persists until its namespace is
- * destroyed or until the variable is unset;
- * it will persist even if it has not been
- * initialized and is marked undefined.
- * The variable's refCount is incremented to
- * reflect the "reference" from its namespace.
+ * element, so it is not legal for it to be an
+ * array itself (the VAR_ARRAY flag had better
+ * not be set).
+ * VAR_NAMESPACE_VAR - 1 means that this variable was declared as a
+ * namespace variable. This flag ensures it
+ * persists until its namespace is destroyed or
+ * until the variable is unset; it will persist
+ * even if it has not been initialized and is
+ * marked undefined. The variable's refCount is
+ * incremented to reflect the "reference" from
+ * its namespace.
*
- * The following additional flags are used with the CompiledLocal type
- * defined below:
+ * Flag values relating to the variable's trace and search status.
+ *
+ * VAR_TRACED_READ
+ * VAR_TRACED_WRITE
+ * VAR_TRACED_UNSET
+ * VAR_TRACED_ARRAY
+ * VAR_TRACE_ACTIVE - 1 means that trace processing is currently
+ * underway for a read or write access, so new
+ * read or write accesses should not cause trace
+ * procedures to be called and the variable can't
+ * be deleted.
+ * VAR_SEARCH_ACTIVE
+ *
+ * The following additional flags are used with the CompiledLocal type defined
+ * below:
*
* VAR_ARGUMENT - 1 means that this variable holds a procedure
- * argument.
+ * argument.
* VAR_TEMPORARY - 1 if the local variable is an anonymous
* temporary variable. Temporaries have a NULL
* name.
* VAR_RESOLVED - 1 if name resolution has been done for this
* variable.
+ * VAR_IS_ARGS 1 if this variable is the last argument and is
+ * named "args".
+ */
+
+/*
+ * FLAGS RENUMBERED: everything breaks already, make things simpler.
+ *
+ * IMPORTANT: skip the values 0x10, 0x20, 0x40, 0x800 corresponding to
+ * TCL_TRACE_(READS/WRITES/UNSETS/ARRAY): makes code simpler in tclTrace.c
+ *
+ * Keep the flag values for VAR_ARGUMENT and VAR_TEMPORARY so that old values
+ * in precompiled scripts keep working.
*/
-#define VAR_SCALAR 0x1
-#define VAR_ARRAY 0x2
-#define VAR_LINK 0x4
-#define VAR_UNDEFINED 0x8
-#define VAR_IN_HASHTABLE 0x10
-#define VAR_TRACE_ACTIVE 0x20
-#define VAR_ARRAY_ELEMENT 0x40
-#define VAR_NAMESPACE_VAR 0x80
+/* Type of value (0 is scalar) */
+#define VAR_ARRAY 0x1
+#define VAR_LINK 0x2
-#define VAR_ARGUMENT 0x100
-#define VAR_TEMPORARY 0x200
-#define VAR_RESOLVED 0x400
+/* Type of storage (0 is compiled local) */
+#define VAR_IN_HASHTABLE 0x4
+#define VAR_DEAD_HASH 0x8
+#define VAR_ARRAY_ELEMENT 0x1000
+#define VAR_NAMESPACE_VAR 0x80 /* KEEP OLD VALUE for Itcl */
+
+#define VAR_ALL_HASH \
+ (VAR_IN_HASHTABLE|VAR_DEAD_HASH|VAR_NAMESPACE_VAR|VAR_ARRAY_ELEMENT)
+
+/* Trace and search state. */
+
+#define VAR_TRACED_READ 0x10 /* TCL_TRACE_READS */
+#define VAR_TRACED_WRITE 0x20 /* TCL_TRACE_WRITES */
+#define VAR_TRACED_UNSET 0x40 /* TCL_TRACE_UNSETS */
+#define VAR_TRACED_ARRAY 0x800 /* TCL_TRACE_ARRAY */
+#define VAR_TRACE_ACTIVE 0x2000
+#define VAR_SEARCH_ACTIVE 0x4000
+#define VAR_ALL_TRACES \
+ (VAR_TRACED_READ|VAR_TRACED_WRITE|VAR_TRACED_ARRAY|VAR_TRACED_UNSET)
+
+/* Special handling on initialisation (only CompiledLocal). */
+#define VAR_ARGUMENT 0x100 /* KEEP OLD VALUE! See tclProc.c */
+#define VAR_TEMPORARY 0x200 /* KEEP OLD VALUE! See tclProc.c */
+#define VAR_IS_ARGS 0x400
+#define VAR_RESOLVED 0x8000
/*
* Macros to ensure that various flag bits are set properly for variables.
* The ANSI C "prototypes" for these macros are:
*
- * EXTERN void TclSetVarScalar _ANSI_ARGS_((Var *varPtr));
- * EXTERN void TclSetVarArray _ANSI_ARGS_((Var *varPtr));
- * EXTERN void TclSetVarLink _ANSI_ARGS_((Var *varPtr));
- * EXTERN void TclSetVarArrayElement _ANSI_ARGS_((Var *varPtr));
- * EXTERN void TclSetVarUndefined _ANSI_ARGS_((Var *varPtr));
- * EXTERN void TclClearVarUndefined _ANSI_ARGS_((Var *varPtr));
+ * MODULE_SCOPE void TclSetVarScalar(Var *varPtr);
+ * MODULE_SCOPE void TclSetVarArray(Var *varPtr);
+ * MODULE_SCOPE void TclSetVarLink(Var *varPtr);
+ * MODULE_SCOPE void TclSetVarArrayElement(Var *varPtr);
+ * MODULE_SCOPE void TclSetVarUndefined(Var *varPtr);
+ * MODULE_SCOPE void TclClearVarUndefined(Var *varPtr);
*/
#define TclSetVarScalar(varPtr) \
- (varPtr)->flags = ((varPtr)->flags & ~(VAR_ARRAY|VAR_LINK)) | VAR_SCALAR
+ (varPtr)->flags &= ~(VAR_ARRAY|VAR_LINK)
#define TclSetVarArray(varPtr) \
- (varPtr)->flags = ((varPtr)->flags & ~(VAR_SCALAR|VAR_LINK)) | VAR_ARRAY
+ (varPtr)->flags = ((varPtr)->flags & ~VAR_LINK) | VAR_ARRAY
#define TclSetVarLink(varPtr) \
- (varPtr)->flags = ((varPtr)->flags & ~(VAR_SCALAR|VAR_ARRAY)) | VAR_LINK
+ (varPtr)->flags = ((varPtr)->flags & ~VAR_ARRAY) | VAR_LINK
#define TclSetVarArrayElement(varPtr) \
(varPtr)->flags = ((varPtr)->flags & ~VAR_ARRAY) | VAR_ARRAY_ELEMENT
#define TclSetVarUndefined(varPtr) \
- (varPtr)->flags |= VAR_UNDEFINED
+ (varPtr)->flags &= ~(VAR_ARRAY|VAR_LINK);\
+ (varPtr)->value.objPtr = NULL
-#define TclClearVarUndefined(varPtr) \
- (varPtr)->flags &= ~VAR_UNDEFINED
+#define TclClearVarUndefined(varPtr)
+
+#define TclSetVarTraceActive(varPtr) \
+ (varPtr)->flags |= VAR_TRACE_ACTIVE
+
+#define TclClearVarTraceActive(varPtr) \
+ (varPtr)->flags &= ~VAR_TRACE_ACTIVE
+
+#define TclSetVarNamespaceVar(varPtr) \
+ if (!TclIsVarNamespaceVar(varPtr)) {\
+ (varPtr)->flags |= VAR_NAMESPACE_VAR;\
+ ((VarInHash *)(varPtr))->refCount++;\
+ }
+
+#define TclClearVarNamespaceVar(varPtr) \
+ if (TclIsVarNamespaceVar(varPtr)) {\
+ (varPtr)->flags &= ~VAR_NAMESPACE_VAR;\
+ ((VarInHash *)(varPtr))->refCount--;\
+ }
/*
* Macros to read various flag bits of variables.
* The ANSI C "prototypes" for these macros are:
*
- * EXTERN int TclIsVarScalar _ANSI_ARGS_((Var *varPtr));
- * EXTERN int TclIsVarLink _ANSI_ARGS_((Var *varPtr));
- * EXTERN int TclIsVarArray _ANSI_ARGS_((Var *varPtr));
- * EXTERN int TclIsVarUndefined _ANSI_ARGS_((Var *varPtr));
- * EXTERN int TclIsVarArrayElement _ANSI_ARGS_((Var *varPtr));
- * EXTERN int TclIsVarTemporary _ANSI_ARGS_((Var *varPtr));
- * EXTERN int TclIsVarArgument _ANSI_ARGS_((Var *varPtr));
- * EXTERN int TclIsVarResolved _ANSI_ARGS_((Var *varPtr));
- */
-
+ * MODULE_SCOPE int TclIsVarScalar(Var *varPtr);
+ * MODULE_SCOPE int TclIsVarLink(Var *varPtr);
+ * MODULE_SCOPE int TclIsVarArray(Var *varPtr);
+ * MODULE_SCOPE int TclIsVarUndefined(Var *varPtr);
+ * MODULE_SCOPE int TclIsVarArrayElement(Var *varPtr);
+ * MODULE_SCOPE int TclIsVarTemporary(Var *varPtr);
+ * MODULE_SCOPE int TclIsVarArgument(Var *varPtr);
+ * MODULE_SCOPE int TclIsVarResolved(Var *varPtr);
+ */
+
#define TclIsVarScalar(varPtr) \
- ((varPtr)->flags & VAR_SCALAR)
+ !((varPtr)->flags & (VAR_ARRAY|VAR_LINK))
#define TclIsVarLink(varPtr) \
((varPtr)->flags & VAR_LINK)
@@ -586,24 +726,74 @@ typedef struct Var {
((varPtr)->flags & VAR_ARRAY)
#define TclIsVarUndefined(varPtr) \
- ((varPtr)->flags & VAR_UNDEFINED)
+ ((varPtr)->value.objPtr == NULL)
#define TclIsVarArrayElement(varPtr) \
((varPtr)->flags & VAR_ARRAY_ELEMENT)
+#define TclIsVarNamespaceVar(varPtr) \
+ ((varPtr)->flags & VAR_NAMESPACE_VAR)
+
#define TclIsVarTemporary(varPtr) \
((varPtr)->flags & VAR_TEMPORARY)
-
+
#define TclIsVarArgument(varPtr) \
((varPtr)->flags & VAR_ARGUMENT)
-
+
#define TclIsVarResolved(varPtr) \
((varPtr)->flags & VAR_RESOLVED)
+#define TclIsVarTraceActive(varPtr) \
+ ((varPtr)->flags & VAR_TRACE_ACTIVE)
+
+#define TclIsVarTraced(varPtr) \
+ ((varPtr)->flags & VAR_ALL_TRACES)
+
+#define TclIsVarInHash(varPtr) \
+ ((varPtr)->flags & VAR_IN_HASHTABLE)
+
+#define TclIsVarDeadHash(varPtr) \
+ ((varPtr)->flags & VAR_DEAD_HASH)
+
+#define TclGetVarNsPtr(varPtr) \
+ (TclIsVarInHash(varPtr) \
+ ? ((TclVarHashTable *) ((((VarInHash *) (varPtr))->entry.tablePtr)))->nsPtr \
+ : NULL)
+
+#define VarHashRefCount(varPtr) \
+ ((VarInHash *) (varPtr))->refCount
+
+/*
+ * Macros for direct variable access by TEBC.
+ */
+
+#define TclIsVarDirectReadable(varPtr) \
+ ( !((varPtr)->flags & (VAR_ARRAY|VAR_LINK|VAR_TRACED_READ)) \
+ && (varPtr)->value.objPtr)
+
+#define TclIsVarDirectWritable(varPtr) \
+ !((varPtr)->flags & (VAR_ARRAY|VAR_LINK|VAR_TRACED_WRITE|VAR_DEAD_HASH))
+
+#define TclIsVarDirectModifyable(varPtr) \
+ ( !((varPtr)->flags & (VAR_ARRAY|VAR_LINK|VAR_TRACED_READ|VAR_TRACED_WRITE)) \
+ && (varPtr)->value.objPtr)
+
+#define TclIsVarDirectReadable2(varPtr, arrayPtr) \
+ (TclIsVarDirectReadable(varPtr) &&\
+ (!(arrayPtr) || !((arrayPtr)->flags & VAR_TRACED_READ)))
+
+#define TclIsVarDirectWritable2(varPtr, arrayPtr) \
+ (TclIsVarDirectWritable(varPtr) &&\
+ (!(arrayPtr) || !((arrayPtr)->flags & VAR_TRACED_WRITE)))
+
+#define TclIsVarDirectModifyable2(varPtr, arrayPtr) \
+ (TclIsVarDirectModifyable(varPtr) &&\
+ (!(arrayPtr) || !((arrayPtr)->flags & (VAR_TRACED_READ|VAR_TRACED_WRITE))))
+
/*
*----------------------------------------------------------------
- * Data structures related to procedures. These are used primarily
- * in tclProc.c, tclCompile.c, and tclExecute.c.
+ * Data structures related to procedures. These are used primarily in
+ * tclProc.c, tclCompile.c, and tclExecute.c.
*----------------------------------------------------------------
*/
@@ -616,32 +806,31 @@ struct Command;
/*
* The variable-length structure below describes a local variable of a
- * procedure that was recognized by the compiler. These variables have a
- * name, an element in the array of compiler-assigned local variables in the
+ * procedure that was recognized by the compiler. These variables have a name,
+ * an element in the array of compiler-assigned local variables in the
* procedure's call frame, and various other items of information. If the
- * local variable is a formal argument, it may also have a default value.
- * The compiler can't recognize local variables whose names are
- * expressions (these names are only known at runtime when the expressions
- * are evaluated) or local variables that are created as a result of an
- * "upvar" or "uplevel" command. These other local variables are kept
- * separately in a hash table in the call frame.
+ * local variable is a formal argument, it may also have a default value. The
+ * compiler can't recognize local variables whose names are expressions (these
+ * names are only known at runtime when the expressions are evaluated) or
+ * local variables that are created as a result of an "upvar" or "uplevel"
+ * command. These other local variables are kept separately in a hash table in
+ * the call frame.
*/
typedef struct CompiledLocal {
struct CompiledLocal *nextPtr;
- /* Next compiler-recognized local variable
- * for this procedure, or NULL if this is
- * the last local. */
+ /* Next compiler-recognized local variable for
+ * this procedure, or NULL if this is the last
+ * local. */
int nameLength; /* The number of characters in local
- * variable's name. Used to speed up
- * variable lookups. */
+ * variable's name. Used to speed up variable
+ * lookups. */
int frameIndex; /* Index in the array of compiler-assigned
* variables in the procedure call frame. */
int flags; /* Flag bits for the local variable. Same as
* the flags for the Var structure above,
- * although only VAR_SCALAR, VAR_ARRAY,
- * VAR_LINK, VAR_ARGUMENT, VAR_TEMPORARY, and
- * VAR_RESOLVED make sense. */
+ * although only VAR_ARGUMENT, VAR_TEMPORARY,
+ * and VAR_RESOLVED make sense. */
Tcl_Obj *defValuePtr; /* Pointer to the default value of an
* argument, if any. NULL if not an argument
* or, if an argument, no default value. */
@@ -649,277 +838,306 @@ typedef struct CompiledLocal {
/* Customized variable resolution info
* supplied by the Tcl_ResolveCompiledVarProc
* associated with a namespace. Each variable
- * is marked by a unique ClientData tag
- * during compilation, and that same tag
- * is used to find the variable at runtime. */
- char name[4]; /* Name of the local variable starts here.
- * If the name is NULL, this will just be
- * '\0'. The actual size of this field will
- * be large enough to hold the name. MUST
- * BE THE LAST FIELD IN THE STRUCTURE! */
+ * is marked by a unique ClientData tag during
+ * compilation, and that same tag is used to
+ * find the variable at runtime. */
+ char name[4]; /* Name of the local variable starts here. If
+ * the name is NULL, this will just be '\0'.
+ * The actual size of this field will be large
+ * enough to hold the name. MUST BE THE LAST
+ * FIELD IN THE STRUCTURE! */
} CompiledLocal;
/*
* The structure below defines a command procedure, which consists of a
- * collection of Tcl commands plus information about arguments and other
- * local variables recognized at compile time.
+ * collection of Tcl commands plus information about arguments and other local
+ * variables recognized at compile time.
*/
typedef struct Proc {
- struct Interp *iPtr; /* Interpreter for which this command
- * is defined. */
- int refCount; /* Reference count: 1 if still present
- * in command table plus 1 for each call
- * to the procedure that is currently
- * active. This structure can be freed
- * when refCount becomes zero. */
- struct Command *cmdPtr; /* Points to the Command structure for
- * this procedure. This is used to get
- * the namespace in which to execute
- * the procedure. */
- Tcl_Obj *bodyPtr; /* Points to the ByteCode object for
- * procedure's body command. */
- int numArgs; /* Number of formal parameters. */
- int numCompiledLocals; /* Count of local variables recognized by
- * the compiler including arguments and
- * temporaries. */
- CompiledLocal *firstLocalPtr; /* Pointer to first of the procedure's
- * compiler-allocated local variables, or
- * NULL if none. The first numArgs entries
- * in this list describe the procedure's
- * formal arguments. */
- CompiledLocal *lastLocalPtr; /* Pointer to the last allocated local
- * variable or NULL if none. This has
- * frame index (numCompiledLocals-1). */
+ struct Interp *iPtr; /* Interpreter for which this command is
+ * defined. */
+ int refCount; /* Reference count: 1 if still present in
+ * command table plus 1 for each call to the
+ * procedure that is currently active. This
+ * structure can be freed when refCount
+ * becomes zero. */
+ struct Command *cmdPtr; /* Points to the Command structure for this
+ * procedure. This is used to get the
+ * namespace in which to execute the
+ * procedure. */
+ Tcl_Obj *bodyPtr; /* Points to the ByteCode object for
+ * procedure's body command. */
+ int numArgs; /* Number of formal parameters. */
+ int numCompiledLocals; /* Count of local variables recognized by the
+ * compiler including arguments and
+ * temporaries. */
+ CompiledLocal *firstLocalPtr;
+ /* Pointer to first of the procedure's
+ * compiler-allocated local variables, or NULL
+ * if none. The first numArgs entries in this
+ * list describe the procedure's formal
+ * arguments. */
+ CompiledLocal *lastLocalPtr;/* Pointer to the last allocated local
+ * variable or NULL if none. This has frame
+ * index (numCompiledLocals-1). */
} Proc;
/*
- * The structure below defines a command trace. This is used to allow Tcl
+ * The type of functions called to process errors found during the execution
+ * of a procedure (or lambda term or ...).
+ */
+
+typedef void (*ProcErrorProc)(Tcl_Interp *interp, Tcl_Obj *procNameObj);
+
+/*
+ * The structure below defines a command trace. This is used to allow Tcl
* clients to find out whenever a command is about to be executed.
*/
typedef struct Trace {
- int level; /* Only trace commands at nesting level
- * less than or equal to this. */
+ int level; /* Only trace commands at nesting level less
+ * than or equal to this. */
Tcl_CmdObjTraceProc *proc; /* Procedure to call to trace command. */
ClientData clientData; /* Arbitrary value to pass to proc. */
struct Trace *nextPtr; /* Next in list of traces for this interp. */
int flags; /* Flags governing the trace - see
- * Tcl_CreateObjTrace for details */
- Tcl_CmdObjTraceDeleteProc* delProc;
- /* Procedure to call when trace is deleted */
+ * Tcl_CreateObjTrace for details. */
+ Tcl_CmdObjTraceDeleteProc *delProc;
+ /* Procedure to call when trace is deleted. */
} Trace;
/*
- * When an interpreter trace is active (i.e. its associated procedure
- * is executing), one of the following structures is linked into a list
- * associated with the interpreter. The information in the structure
- * is needed in order for Tcl to behave reasonably if traces are
- * deleted while traces are active.
+ * When an interpreter trace is active (i.e. its associated procedure is
+ * executing), one of the following structures is linked into a list
+ * associated with the interpreter. The information in the structure is needed
+ * in order for Tcl to behave reasonably if traces are deleted while traces
+ * are active.
*/
typedef struct ActiveInterpTrace {
struct ActiveInterpTrace *nextPtr;
- /* Next in list of all active command
- * traces for the interpreter, or NULL
- * if no more. */
- Trace *nextTracePtr; /* Next trace to check after current
- * trace procedure returns; if this
- * trace gets deleted, must update pointer
- * to avoid using free'd memory. */
- int reverseScan; /* Boolean set true when the traces
- * are scanning in reverse order. */
+ /* Next in list of all active command traces
+ * for the interpreter, or NULL if no more. */
+ Trace *nextTracePtr; /* Next trace to check after current trace
+ * procedure returns; if this trace gets
+ * deleted, must update pointer to avoid using
+ * free'd memory. */
+ int reverseScan; /* Boolean set true when traces are scanning
+ * in reverse order. */
} ActiveInterpTrace;
/*
- * The structure below defines an entry in the assocData hash table which
- * is associated with an interpreter. The entry contains a pointer to a
- * function to call when the interpreter is deleted, and a pointer to
- * a user-defined piece of data.
+ * Flag values designating types of execution traces. See tclTrace.c for
+ * related flag values.
+ *
+ * TCL_TRACE_ENTER_EXEC - triggers enter/enterstep traces.
+ * - passed to Tcl_CreateObjTrace to set up
+ * "enterstep" traces.
+ * TCL_TRACE_LEAVE_EXEC - triggers leave/leavestep traces.
+ * - passed to Tcl_CreateObjTrace to set up
+ * "leavestep" traces.
+ */
+
+#define TCL_TRACE_ENTER_EXEC 1
+#define TCL_TRACE_LEAVE_EXEC 2
+
+/*
+ * The structure below defines an entry in the assocData hash table which is
+ * associated with an interpreter. The entry contains a pointer to a function
+ * to call when the interpreter is deleted, and a pointer to a user-defined
+ * piece of data.
*/
typedef struct AssocData {
Tcl_InterpDeleteProc *proc; /* Proc to call when deleting. */
ClientData clientData; /* Value to pass to proc. */
-} AssocData;
+} AssocData;
/*
* The structure below defines a call frame. A call frame defines a naming
- * context for a procedure call: its local naming scope (for local
- * variables) and its global naming scope (a namespace, perhaps the global
- * :: namespace). A call frame can also define the naming context for a
- * namespace eval or namespace inscope command: the namespace in which the
- * command's code should execute. The Tcl_CallFrame structures exist only
- * while procedures or namespace eval/inscope's are being executed, and
- * provide a kind of Tcl call stack.
- *
+ * context for a procedure call: its local naming scope (for local variables)
+ * and its global naming scope (a namespace, perhaps the global :: namespace).
+ * A call frame can also define the naming context for a namespace eval or
+ * namespace inscope command: the namespace in which the command's code should
+ * execute. The Tcl_CallFrame structures exist only while procedures or
+ * namespace eval/inscope's are being executed, and provide a kind of Tcl call
+ * stack.
+ *
* WARNING!! The structure definition must be kept consistent with the
* Tcl_CallFrame structure in tcl.h. If you change one, change the other.
*/
+/*
+ * Will be grown to contain: pointers to the varnames (allocated at the end),
+ * plus the init values for each variable (suitable to be memcopied on init)
+ */
+
+typedef struct LocalCache {
+ int refCount;
+ int numVars;
+ Tcl_Obj *varName0;
+} LocalCache;
+
+#define localName(framePtr, i) \
+ ((&((framePtr)->localCachePtr->varName0))[(i)])
+
+MODULE_SCOPE void TclFreeLocalCache(Tcl_Interp *interp,
+ LocalCache *localCachePtr);
+
typedef struct CallFrame {
Namespace *nsPtr; /* Points to the namespace used to resolve
* commands and global variables. */
- int isProcCallFrame; /* If nonzero, the frame was pushed to
- * execute a Tcl procedure and may have
- * local vars. If 0, the frame was pushed
- * to execute a namespace command and var
- * references are treated as references to
- * namespace vars; varTablePtr and
- * compiledLocals are ignored. */
- int objc; /* This and objv below describe the
- * arguments for this procedure call. */
- Tcl_Obj *CONST *objv; /* Array of argument objects. */
+ int isProcCallFrame; /* If 0, the frame was pushed to execute a
+ * namespace command and var references are
+ * treated as references to namespace vars;
+ * varTablePtr and compiledLocals are ignored.
+ * If FRAME_IS_PROC is set, the frame was
+ * pushed to execute a Tcl procedure and may
+ * have local vars. */
+ int objc; /* This and objv below describe the arguments
+ * for this procedure call. */
+ Tcl_Obj *const *objv; /* Array of argument objects. */
struct CallFrame *callerPtr;
/* Value of interp->framePtr when this
- * procedure was invoked (i.e. next higher
- * in stack of all active procedures). */
+ * procedure was invoked (i.e. next higher in
+ * stack of all active procedures). */
struct CallFrame *callerVarPtr;
/* Value of interp->varFramePtr when this
* procedure was invoked (i.e. determines
- * variable scoping within caller). Same
- * as callerPtr unless an "uplevel" command
- * or something equivalent was active in
- * the caller). */
+ * variable scoping within caller). Same as
+ * callerPtr unless an "uplevel" command or
+ * something equivalent was active in the
+ * caller). */
int level; /* Level of this procedure, for "uplevel"
* purposes (i.e. corresponds to nesting of
* callerVarPtr's, not callerPtr's). 1 for
* outermost procedure, 0 for top-level. */
- Proc *procPtr; /* Points to the structure defining the
- * called procedure. Used to get information
- * such as the number of compiled local
- * variables (local variables assigned
- * entries ["slots"] in the compiledLocals
- * array below). */
- Tcl_HashTable *varTablePtr; /* Hash table containing local variables not
+ Proc *procPtr; /* Points to the structure defining the called
+ * procedure. Used to get information such as
+ * the number of compiled local variables
+ * (local variables assigned entries ["slots"]
+ * in the compiledLocals array below). */
+ TclVarHashTable *varTablePtr;
+ /* Hash table containing local variables not
* recognized by the compiler, or created at
* execution time through, e.g., upvar.
* Initially NULL and created if needed. */
- int numCompiledLocals; /* Count of local variables recognized by
- * the compiler including arguments. */
- Var* compiledLocals; /* Points to the array of local variables
+ int numCompiledLocals; /* Count of local variables recognized by the
+ * compiler including arguments. */
+ Var *compiledLocals; /* Points to the array of local variables
* recognized by the compiler. The compiler
* emits code that refers to these variables
* using an index into this array. */
+ ClientData clientData; /* Pointer to some context that is used by
+ * object systems. The meaning of the contents
+ * of this field is defined by the code that
+ * sets it, and it should only ever be set by
+ * the code that is pushing the frame. In that
+ * case, the code that sets it should also
+ * have some means of discovering what the
+ * meaning of the value is, which we do not
+ * specify. */
+ LocalCache *localCachePtr;
} CallFrame;
-#ifdef TCL_TIP280
+#define FRAME_IS_PROC 0x1
+#define FRAME_IS_LAMBDA 0x2
+
/*
* TIP #280
- * The structure below defines a command frame. A command frame
- * provides location information for all commands executing a tcl
- * script (source, eval, uplevel, procedure bodies, ...). The runtime
- * structure essentially contains the stack trace as it would be if
- * the currently executing command were to throw an error.
+ * The structure below defines a command frame. A command frame provides
+ * location information for all commands executing a tcl script (source, eval,
+ * uplevel, procedure bodies, ...). The runtime structure essentially contains
+ * the stack trace as it would be if the currently executing command were to
+ * throw an error.
*
- * For commands where it makes sense it refers to the associated
- * CallFrame as well.
+ * For commands where it makes sense it refers to the associated CallFrame as
+ * well.
*
- * The structures are chained in a single list, with the top of the
- * stack anchored in the Interp structure.
+ * The structures are chained in a single list, with the top of the stack
+ * anchored in the Interp structure.
*
- * Instances can be allocated on the C stack, or the heap, the former
- * making cleanup a bit simpler.
+ * Instances can be allocated on the C stack, or the heap, the former making
+ * cleanup a bit simpler.
*/
typedef struct CmdFrame {
- /* General data. Always available. */
-
- int type; /* Values see below */
- int level; /* #Frames in stack, prevent O(n) scan of list */
- int* line; /* Lines the words of the command start on */
- int nline;
-
- CallFrame* framePtr; /* Procedure activation record, may be NULL */
- struct CmdFrame* nextPtr; /* Link to calling frame */
-
- /* Data needed for Eval vs TEBC
- *
- * EXECUTION CONTEXTS and usage of CmdFrame
- *
- * Field TEBC EvalEx EvalObjEx
- * ======= ==== ====== =========
- * level yes yes yes
- * type BC/PREBC SRC/EVAL EVAL_LIST
- * line0 yes yes yes
- * framePtr yes yes yes
- * ======= ==== ====== =========
- *
- * ======= ==== ====== ========= union data
- * line1 - yes -
- * line3 - yes -
- * path - yes -
- * ------- ---- ------ ---------
- * codePtr yes - -
- * pc yes - -
- * ======= ==== ====== =========
- *
- * ======= ==== ====== ========= | union cmd
- * listPtr - - yes |
- * ------- ---- ------ --------- |
- * cmd yes yes - |
- * cmdlen yes yes - |
- * ------- ---- ------ --------- |
- */
-
- union {
- struct {
- Tcl_Obj* path; /* Path of the sourced file the command
- * is in. */
- } eval;
- struct {
- CONST void* codePtr; /* Byte code currently executed */
- CONST char* pc; /* and instruction pointer. */
- } tebc;
- } data;
+ /*
+ * General data. Always available.
+ */
- union {
- struct {
- CONST char* cmd; /* The executed command, if possible */
- int len; /* And its length */
- } str;
- Tcl_Obj* listPtr; /* Tcl_EvalObjEx, cmd list */
- } cmd;
+ int type; /* Values see below. */
+ int level; /* Number of frames in stack, prevent O(n)
+ * scan of list. */
+ int *line; /* Lines the words of the command start on. */
+ int nline;
+ CallFrame *framePtr; /* Procedure activation record, may be
+ * NULL. */
+ struct CmdFrame *nextPtr; /* Link to calling frame. */
+ /*
+ * Data needed for Eval vs TEBC
+ *
+ * EXECUTION CONTEXTS and usage of CmdFrame
+ *
+ * Field TEBC EvalEx EvalObjEx
+ * ======= ==== ====== =========
+ * level yes yes yes
+ * type BC/PREBC SRC/EVAL EVAL_LIST
+ * line0 yes yes yes
+ * framePtr yes yes yes
+ * ======= ==== ====== =========
+ *
+ * ======= ==== ====== ========= union data
+ * line1 - yes -
+ * line3 - yes -
+ * path - yes -
+ * ------- ---- ------ ---------
+ * codePtr yes - -
+ * pc yes - -
+ * ======= ==== ====== =========
+ *
+ * ======= ==== ====== ========= | union cmd
+ * listPtr - - yes |
+ * ------- ---- ------ --------- |
+ * cmd yes yes - |
+ * cmdlen yes yes - |
+ * ------- ---- ------ --------- |
+ */
+ union {
+ struct {
+ Tcl_Obj *path; /* Path of the sourced file the command is
+ * in. */
+ } eval;
+ struct {
+ const void *codePtr;/* Byte code currently executed... */
+ const char *pc; /* ... and instruction pointer. */
+ } tebc;
+ } data;
+ union {
+ struct {
+ const char *cmd; /* The executed command, if possible... */
+ int len; /* ... and its length. */
+ } str;
+ Tcl_Obj *listPtr; /* Tcl_EvalObjEx, cmd list. */
+ } cmd;
} CmdFrame;
-/* The following macros define the allowed values for the type field
- * of the CmdFrame structure above. Some of the values occur only in
- * the extended location data referenced via the 'baseLocPtr'.
- *
- * TCL_LOCATION_EVAL : Frame is for a script evaluated by EvalEx.
- * TCL_LOCATION_EVAL_LIST : Frame is for a script evaluated by the list
- * optimization path of EvalObjEx.
- * TCL_LOCATION_BC : Frame is for bytecode.
- * TCL_LOCATION_PREBC : Frame is for precompiled bytecode.
- * TCL_LOCATION_SOURCE : Frame is for a script evaluated by EvalEx,
- * from a sourced file.
- * TCL_LOCATION_PROC : Frame is for bytecode of a procedure.
- *
- * A TCL_LOCATION_BC type in a frame can be overridden by _SOURCE and
- * _PROC types, per the context of the byte code in execution.
- */
-
-#define TCL_LOCATION_EVAL (0) /* Location in a dynamic eval script */
-#define TCL_LOCATION_EVAL_LIST (1) /* Location in a dynamic eval script, list-path */
-#define TCL_LOCATION_BC (2) /* Location in byte code */
-#define TCL_LOCATION_PREBC (3) /* Location in precompiled byte code, no location */
-#define TCL_LOCATION_SOURCE (4) /* Location in a file */
-#define TCL_LOCATION_PROC (5) /* Location in a dynamic proc */
-
-#define TCL_LOCATION_LAST (6) /* Number of values in the enum */
-
typedef struct CFWord {
- CmdFrame* framePtr; /* CmdFrame to acess */
- int word; /* Index of the word in the command */
- int refCount; /* #times the word is on the stack */
+ CmdFrame *framePtr; /* CmdFrame to access. */
+ int word; /* Index of the word in the command. */
+ int refCount; /* Number of times the word is on the
+ * stack. */
} CFWord;
typedef struct CFWordBC {
- CmdFrame* framePtr; /* CmdFrame to acess */
- int pc; /* Instruction pointer of a command in ExtCmdLoc.loc[.] */
- int word; /* Index of word in ExtCmdLoc.loc[cmd]->{line,literal}[.] */
- struct CFWordBC* prevPtr;
+ CmdFrame *framePtr; /* CmdFrame to access. */
+ int pc; /* Instruction pointer of a command in
+ * ExtCmdLoc.loc[.] */
+ int word; /* Index of word in
+ * ExtCmdLoc.loc[cmd]->line[.] */
+ struct CFWordBC *prevPtr; /* Previous entry in stack for same Tcl_Obj. */
} CFWordBC;
/*
@@ -932,96 +1150,125 @@ typedef struct CFWordBC {
* tracking.
*
* These structures are allocated and filled by both the function
- * EvalTokensStandard() in the file "tclBasic.c" and its caller EvalEx(), and
- * stored in the thread-global hashtable "lineCLPtr" in file "tclObj.c". They
- * are used by the functions TclSetByteCodeFromAny() and TclCompileScript(),
- * both found in the file "tclCompile.c". Their memory is released by the
- * function TclFreeObj(), in the file "tclObj.c", and also by the function
- * TclThreadFinalizeObjects(), in the same file.
+ * TclSubstTokens() in the file "tclParse.c" and its caller TclEvalEx() in the
+ * file "tclBasic.c", and stored in the thread-global hashtable "lineCLPtr" in
+ * file "tclObj.c". They are used by the functions TclSetByteCodeFromAny() and
+ * TclCompileScript(), both found in the file "tclCompile.c". Their memory is
+ * released by the function TclFreeObj(), in the file "tclObj.c", and also by
+ * the function TclThreadFinalizeObjects(), in the same file.
*/
-#define CLL_END (-1)
+#define CLL_END (-1)
typedef struct ContLineLoc {
- int num; /* Number of entries in loc, not counting the final -1
- * marker entry */
- int loc[1]; /* Table of locations, as character offsets. The table is
- * allocated as part of the structure, i.e. the loc array
- * extends behind the nominal end of the structure. An entry
- * containing the value CLL_END is put after the last
- * location, as end-marker/sentinel. */
+ int num; /* Number of entries in loc, not counting the
+ * final -1 marker entry. */
+ int loc[1]; /* Table of locations, as character offsets.
+ * The table is allocated as part of the
+ * structure, extending behind the nominal end
+ * of the structure. An entry containing the
+ * value -1 is put after the last location, as
+ * end-marker/sentinel. */
} ContLineLoc;
-#endif /* TCL_TIP280 */
+/*
+ * The following macros define the allowed values for the type field of the
+ * CmdFrame structure above. Some of the values occur only in the extended
+ * location data referenced via the 'baseLocPtr'.
+ *
+ * TCL_LOCATION_EVAL : Frame is for a script evaluated by EvalEx.
+ * TCL_LOCATION_EVAL_LIST : Frame is for a script evaluated by the list
+ * optimization path of EvalObjEx.
+ * TCL_LOCATION_BC : Frame is for bytecode.
+ * TCL_LOCATION_PREBC : Frame is for precompiled bytecode.
+ * TCL_LOCATION_SOURCE : Frame is for a script evaluated by EvalEx, from a
+ * sourced file.
+ * TCL_LOCATION_PROC : Frame is for bytecode of a procedure.
+ *
+ * A TCL_LOCATION_BC type in a frame can be overridden by _SOURCE and _PROC
+ * types, per the context of the byte code in execution.
+ */
+
+#define TCL_LOCATION_EVAL (0) /* Location in a dynamic eval script. */
+#define TCL_LOCATION_EVAL_LIST (1) /* Location in a dynamic eval script,
+ * list-path. */
+#define TCL_LOCATION_BC (2) /* Location in byte code. */
+#define TCL_LOCATION_PREBC (3) /* Location in precompiled byte code, no
+ * location. */
+#define TCL_LOCATION_SOURCE (4) /* Location in a file. */
+#define TCL_LOCATION_PROC (5) /* Location in a dynamic proc. */
+#define TCL_LOCATION_LAST (6) /* Number of values in the enum. */
+
+/*
+ * Structure passed to describe procedure-like "procedures" that are not
+ * procedures (e.g. a lambda) so that their details can be reported correctly
+ * by [info frame]. Contains a sub-structure for each extra field.
+ */
+
+typedef Tcl_Obj *(*GetFrameInfoValueProc)(ClientData clientData);
+typedef struct {
+ const char *name; /* Name of this field. */
+ GetFrameInfoValueProc proc; /* Function to generate a Tcl_Obj* from the
+ * clientData, or just use the clientData
+ * directly (after casting) if NULL. */
+ ClientData clientData; /* Context for above function, or Tcl_Obj* if
+ * proc field is NULL. */
+} ExtraFrameInfoField;
+typedef struct {
+ int length; /* Length of array. */
+ ExtraFrameInfoField fields[2];
+ /* Really as long as necessary, but this is
+ * long enough for nearly anything. */
+} ExtraFrameInfo;
/*
*----------------------------------------------------------------
- * Data structures and procedures related to TclHandles, which
- * are a very lightweight method of preserving enough information
- * to determine if an arbitrary malloc'd block has been deleted.
+ * Data structures and procedures related to TclHandles, which are a very
+ * lightweight method of preserving enough information to determine if an
+ * arbitrary malloc'd block has been deleted.
*----------------------------------------------------------------
*/
-typedef VOID **TclHandle;
+typedef void **TclHandle;
/*
*----------------------------------------------------------------
- * Data structures related to expressions. These are used only in
- * tclExpr.c.
+ * Experimental flag value passed to Tcl_GetRegExpFromObj. Intended for use
+ * only by Expect. It will probably go away in a later release.
*----------------------------------------------------------------
*/
-/*
- * The data structure below defines a math function (e.g. sin or hypot)
- * for use in Tcl expressions.
- */
-
-#define MAX_MATH_ARGS 5
-typedef struct MathFunc {
- int builtinFuncIndex; /* If this is a builtin math function, its
- * index in the array of builtin functions.
- * (tclCompilation.h lists these indices.)
- * The value is -1 if this is a new function
- * defined by Tcl_CreateMathFunc. The value
- * is also -1 if a builtin function is
- * replaced by a Tcl_CreateMathFunc call. */
- int numArgs; /* Number of arguments for function. */
- Tcl_ValueType argTypes[MAX_MATH_ARGS];
- /* Acceptable types for each argument. */
- Tcl_MathProc *proc; /* Procedure that implements this function.
- * NULL if isBuiltinFunc is 1. */
- ClientData clientData; /* Additional argument to pass to the
- * function when invoking it. NULL if
- * isBuiltinFunc is 1. */
-} MathFunc;
+#define TCL_REG_BOSONLY 002000 /* Prepend \A to pattern so it only matches at
+ * the beginning of the string. */
/*
* These are a thin layer over TclpThreadKeyDataGet and TclpThreadKeyDataSet
- * when threads are used, or an emulation if there are no threads. These
- * are really internal and Tcl clients should use Tcl_GetThreadData.
+ * when threads are used, or an emulation if there are no threads. These are
+ * really internal and Tcl clients should use Tcl_GetThreadData.
*/
-EXTERN VOID *TclThreadDataKeyGet _ANSI_ARGS_((Tcl_ThreadDataKey *keyPtr));
-EXTERN void TclThreadDataKeySet _ANSI_ARGS_((Tcl_ThreadDataKey *keyPtr, VOID *data));
+MODULE_SCOPE void * TclThreadDataKeyGet(Tcl_ThreadDataKey *keyPtr);
+MODULE_SCOPE void TclThreadDataKeySet(Tcl_ThreadDataKey *keyPtr,
+ void *data);
/*
* This is a convenience macro used to initialize a thread local storage ptr.
*/
-#define TCL_TSD_INIT(keyPtr) (ThreadSpecificData *)Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData))
+#define TCL_TSD_INIT(keyPtr) \
+ (ThreadSpecificData *)Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData))
/*
*----------------------------------------------------------------
- * Data structures related to bytecode compilation and execution.
- * These are used primarily in tclCompile.c, tclExecute.c, and
- * tclBasic.c.
+ * Data structures related to bytecode compilation and execution. These are
+ * used primarily in tclCompile.c, tclExecute.c, and tclBasic.c.
*----------------------------------------------------------------
*/
/*
* Forward declaration to prevent errors when the forward references to
- * Tcl_Parse and CompileEnv are encountered in the procedure type
- * CompileProc declared below.
+ * Tcl_Parse and CompileEnv are encountered in the procedure type CompileProc
+ * declared below.
*/
struct CompileEnv;
@@ -1029,62 +1276,72 @@ struct CompileEnv;
/*
* The type of procedures called by the Tcl bytecode compiler to compile
* commands. Pointers to these procedures are kept in the Command structure
- * describing each command. When a CompileProc returns, the interpreter's
- * result is set to error information, if any. In addition, the CompileProc
- * returns an integer value, which is one of the following:
+ * describing each command. The integer value returned by a CompileProc must
+ * be one of the following:
*
* TCL_OK Compilation completed normally.
- * TCL_ERROR Compilation failed because of an error;
- * the interpreter's result describes what went wrong.
- * TCL_OUT_LINE_COMPILE Compilation failed because, e.g., the command is
- * too complex for effective inline compilation. The
- * CompileProc believes the command is legal but
- * should be compiled "out of line" by emitting code
- * to invoke its command procedure at runtime.
+ * TCL_ERROR Compilation could not be completed. This can be just a
+ * judgment by the CompileProc that the command is too
+ * complex to compile effectively, or it can indicate
+ * that in the current state of the interp, the command
+ * would raise an error. The bytecode compiler will not
+ * do any error reporting at compiler time. Error
+ * reporting is deferred until the actual runtime,
+ * because by then changes in the interp state may allow
+ * the command to be successfully evaluated.
+ * TCL_OUT_LINE_COMPILE A source-compatible alias for TCL_ERROR, kept for the
+ * sake of old code only.
*/
-#define TCL_OUT_LINE_COMPILE (TCL_CONTINUE + 1)
+#define TCL_OUT_LINE_COMPILE TCL_ERROR
-typedef int (CompileProc) _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Parse *parsePtr, struct CompileEnv *compEnvPtr));
+typedef int (CompileProc)(Tcl_Interp *interp, Tcl_Parse *parsePtr,
+ struct Command *cmdPtr, struct CompileEnv *compEnvPtr);
/*
* The type of procedure called from the compilation hook point in
* SetByteCodeFromAny.
*/
-typedef int (CompileHookProc) _ANSI_ARGS_((Tcl_Interp *interp,
- struct CompileEnv *compEnvPtr, ClientData clientData));
+typedef int (CompileHookProc)(Tcl_Interp *interp,
+ struct CompileEnv *compEnvPtr, ClientData clientData);
+
+/*
+ * The data structure for a (linked list of) execution stacks.
+ */
+
+typedef struct ExecStack {
+ struct ExecStack *prevPtr;
+ struct ExecStack *nextPtr;
+ Tcl_Obj **markerPtr;
+ Tcl_Obj **endPtr;
+ Tcl_Obj **tosPtr;
+ Tcl_Obj *stackWords[1];
+} ExecStack;
/*
* The data structure defining the execution environment for ByteCode's.
- * There is one ExecEnv structure per Tcl interpreter. It holds the
- * evaluation stack that holds command operands and results. The stack grows
- * towards increasing addresses. The "stackTop" member is cached by
- * TclExecuteByteCode in a local variable: it must be set before calling
- * TclExecuteByteCode and will be restored by TclExecuteByteCode before it
- * returns.
+ * There is one ExecEnv structure per Tcl interpreter. It holds the evaluation
+ * stack that holds command operands and results. The stack grows towards
+ * increasing addresses. The member stackPtr points to the stackItems of the
+ * currently active execution stack.
*/
typedef struct ExecEnv {
- Tcl_Obj **stackPtr; /* Points to the first item in the
- * evaluation stack on the heap. */
- int stackTop; /* Index of current top of stack; -1 when
- * the stack is empty. */
- int stackEnd; /* Index of last usable item in stack. */
- Tcl_Obj *errorInfo;
- Tcl_Obj *errorCode;
+ ExecStack *execStackPtr; /* Points to the first item in the evaluation
+ * stack on the heap. */
+ Tcl_Obj *constants[2]; /* Pointers to constant "0" and "1" objs. */
} ExecEnv;
/*
* The definitions for the LiteralTable and LiteralEntry structures. Each
* interpreter contains a LiteralTable. It is used to reduce the storage
* needed for all the Tcl objects that hold the literals of scripts compiled
- * by the interpreter. A literal's object is shared by all the ByteCodes
- * that refer to the literal. Each distinct literal has one LiteralEntry
- * entry in the LiteralTable. A literal table is a specialized hash table
- * that is indexed by the literal's string representation, which may contain
- * null characters.
+ * by the interpreter. A literal's object is shared by all the ByteCodes that
+ * refer to the literal. Each distinct literal has one LiteralEntry entry in
+ * the LiteralTable. A literal table is a specialized hash table that is
+ * indexed by the literal's string representation, which may contain null
+ * characters.
*
* Note that we reduce the space needed for literals by sharing literal
* objects both within a ByteCode (each ByteCode contains a local
@@ -1093,37 +1350,36 @@ typedef struct ExecEnv {
*/
typedef struct LiteralEntry {
- struct LiteralEntry *nextPtr; /* Points to next entry in this
- * hash bucket or NULL if end of
- * chain. */
- Tcl_Obj *objPtr; /* Points to Tcl object that
- * holds the literal's bytes and
- * length. */
- int refCount; /* If in an interpreter's global
- * literal table, the number of
- * ByteCode structures that share
- * the literal object; the literal
- * entry can be freed when refCount
- * drops to 0. If in a local literal
- * table, -1. */
+ struct LiteralEntry *nextPtr;
+ /* Points to next entry in this hash bucket or
+ * NULL if end of chain. */
+ Tcl_Obj *objPtr; /* Points to Tcl object that holds the
+ * literal's bytes and length. */
+ int refCount; /* If in an interpreter's global literal
+ * table, the number of ByteCode structures
+ * that share the literal object; the literal
+ * entry can be freed when refCount drops to
+ * 0. If in a local literal table, -1. */
+ Namespace *nsPtr; /* Namespace in which this literal is used. We
+ * try to avoid sharing literal non-FQ command
+ * names among different namespaces to reduce
+ * shimmering. */
} LiteralEntry;
typedef struct LiteralTable {
- LiteralEntry **buckets; /* Pointer to bucket array. Each
- * element points to first entry in
- * bucket's hash chain, or NULL. */
+ LiteralEntry **buckets; /* Pointer to bucket array. Each element
+ * points to first entry in bucket's hash
+ * chain, or NULL. */
LiteralEntry *staticBuckets[TCL_SMALL_HASH_TABLE];
- /* Bucket array used for small
- * tables to avoid mallocs and
- * frees. */
- int numBuckets; /* Total number of buckets allocated
- * at **buckets. */
- int numEntries; /* Total number of entries present
- * in table. */
- int rebuildSize; /* Enlarge table when numEntries
- * gets to be this large. */
- int mask; /* Mask value used in hashing
- * function. */
+ /* Bucket array used for small tables to avoid
+ * mallocs and frees. */
+ int numBuckets; /* Total number of buckets allocated at
+ * **buckets. */
+ int numEntries; /* Total number of entries present in
+ * table. */
+ int rebuildSize; /* Enlarge table when numEntries gets to be
+ * this large. */
+ int mask; /* Mask value used in hashing function. */
} LiteralTable;
/*
@@ -1134,36 +1390,49 @@ typedef struct LiteralTable {
#ifdef TCL_COMPILE_STATS
typedef struct ByteCodeStats {
- long numExecutions; /* Number of ByteCodes executed. */
- long numCompilations; /* Number of ByteCodes created. */
- long numByteCodesFreed; /* Number of ByteCodes destroyed. */
- long instructionCount[256]; /* Number of times each instruction was
- * executed. */
-
- double totalSrcBytes; /* Total source bytes ever compiled. */
- double totalByteCodeBytes; /* Total bytes for all ByteCodes. */
- double currentSrcBytes; /* Src bytes for all current ByteCodes. */
- double currentByteCodeBytes; /* Code bytes in all current ByteCodes. */
-
- long srcCount[32]; /* Source size distribution: # of srcs of
- * size [2**(n-1)..2**n), n in [0..32). */
- long byteCodeCount[32]; /* ByteCode size distribution. */
- long lifetimeCount[32]; /* ByteCode lifetime distribution (ms). */
-
- double currentInstBytes; /* Instruction bytes-current ByteCodes. */
- double currentLitBytes; /* Current literal bytes. */
- double currentExceptBytes; /* Current exception table bytes. */
- double currentAuxBytes; /* Current auxiliary information bytes. */
- double currentCmdMapBytes; /* Current src<->code map bytes. */
-
- long numLiteralsCreated; /* Total literal objects ever compiled. */
- double totalLitStringBytes; /* Total string bytes in all literals. */
- double currentLitStringBytes; /* String bytes in current literals. */
- long literalCount[32]; /* Distribution of literal string sizes. */
+ long numExecutions; /* Number of ByteCodes executed. */
+ long numCompilations; /* Number of ByteCodes created. */
+ long numByteCodesFreed; /* Number of ByteCodes destroyed. */
+ long instructionCount[256]; /* Number of times each instruction was
+ * executed. */
+
+ double totalSrcBytes; /* Total source bytes ever compiled. */
+ double totalByteCodeBytes; /* Total bytes for all ByteCodes. */
+ double currentSrcBytes; /* Src bytes for all current ByteCodes. */
+ double currentByteCodeBytes;/* Code bytes in all current ByteCodes. */
+
+ long srcCount[32]; /* Source size distribution: # of srcs of
+ * size [2**(n-1)..2**n), n in [0..32). */
+ long byteCodeCount[32]; /* ByteCode size distribution. */
+ long lifetimeCount[32]; /* ByteCode lifetime distribution (ms). */
+
+ double currentInstBytes; /* Instruction bytes-current ByteCodes. */
+ double currentLitBytes; /* Current literal bytes. */
+ double currentExceptBytes; /* Current exception table bytes. */
+ double currentAuxBytes; /* Current auxiliary information bytes. */
+ double currentCmdMapBytes; /* Current src<->code map bytes. */
+
+ long numLiteralsCreated; /* Total literal objects ever compiled. */
+ double totalLitStringBytes; /* Total string bytes in all literals. */
+ double currentLitStringBytes;
+ /* String bytes in current literals. */
+ long literalCount[32]; /* Distribution of literal string sizes. */
} ByteCodeStats;
#endif /* TCL_COMPILE_STATS */
/*
+ * Structure used in implementation of those core ensembles which are
+ * partially compiled. Used as an array of these, with a terminating field
+ * whose 'name' is NULL.
+ */
+
+typedef struct {
+ const char *name; /* The name of the subcommand. */
+ Tcl_ObjCmdProc *proc; /* The implementation of the subcommand. */
+ CompileProc *compileProc; /* The compiler for the subcommand. */
+} EnsembleImplMap;
+
+/*
*----------------------------------------------------------------
* Data structures related to commands.
*----------------------------------------------------------------
@@ -1171,11 +1440,12 @@ typedef struct ByteCodeStats {
/*
* An imported command is created in an namespace when it imports a "real"
- * command from another namespace. An imported command has a Command
- * structure that points (via its ClientData value) to the "real" Command
- * structure in the source namespace's command table. The real command
- * records all the imported commands that refer to it in a list of ImportRef
- * structures so that they can be deleted when the real command is deleted. */
+ * command from another namespace. An imported command has a Command structure
+ * that points (via its ClientData value) to the "real" Command structure in
+ * the source namespace's command table. The real command records all the
+ * imported commands that refer to it in a list of ImportRef structures so
+ * that they can be deleted when the real command is deleted.
+ */
typedef struct ImportRef {
struct Command *importedCmdPtr;
@@ -1183,11 +1453,11 @@ typedef struct ImportRef {
* an importing namespace; this command
* redirects its invocations to the "real"
* command. */
- struct ImportRef *nextPtr; /* Next element on the linked list of
- * imported commands that refer to the
- * "real" command. The real command deletes
- * these imported commands on this list when
- * it is deleted. */
+ struct ImportRef *nextPtr; /* Next element on the linked list of imported
+ * commands that refer to the "real" command.
+ * The real command deletes these imported
+ * commands on this list when it is
+ * deleted. */
} ImportRef;
/*
@@ -1200,35 +1470,34 @@ typedef struct ImportedCmdData {
struct Command *realCmdPtr; /* "Real" command that this imported command
* refers to. */
struct Command *selfPtr; /* Pointer to this imported command. Needed
- * only when deleting it in order to remove
- * it from the real command's linked list of
+ * only when deleting it in order to remove it
+ * from the real command's linked list of
* imported commands that refer to it. */
} ImportedCmdData;
/*
- * A Command structure exists for each command in a namespace. The
- * Tcl_Command opaque type actually refers to these structures.
+ * A Command structure exists for each command in a namespace. The Tcl_Command
+ * opaque type actually refers to these structures.
*/
typedef struct Command {
- Tcl_HashEntry *hPtr; /* Pointer to the hash table entry that
- * refers to this command. The hash table is
- * either a namespace's command table or an
+ Tcl_HashEntry *hPtr; /* Pointer to the hash table entry that refers
+ * to this command. The hash table is either a
+ * namespace's command table or an
* interpreter's hidden command table. This
* pointer is used to get a command's name
* from its Tcl_Command handle. NULL means
- * that the hash table entry has been
- * removed already (this can happen if
- * deleteProc causes the command to be
- * deleted or recreated). */
+ * that the hash table entry has been removed
+ * already (this can happen if deleteProc
+ * causes the command to be deleted or
+ * recreated). */
Namespace *nsPtr; /* Points to the namespace containing this
* command. */
int refCount; /* 1 if in command hashtable plus 1 for each
* reference from a CmdName Tcl object
- * representing a command's name in a
- * ByteCode instruction sequence. This
- * structure can be freed when refCount
- * becomes zero. */
+ * representing a command's name in a ByteCode
+ * instruction sequence. This structure can be
+ * freed when refCount becomes zero. */
int cmdEpoch; /* Incremented to invalidate any references
* that point to this command when it is
* renamed, deleted, hidden, or exposed. */
@@ -1239,45 +1508,46 @@ typedef struct Command {
Tcl_CmdProc *proc; /* String-based command procedure. */
ClientData clientData; /* Arbitrary value passed to string proc. */
Tcl_CmdDeleteProc *deleteProc;
- /* Procedure invoked when deleting command
- * to, e.g., free all client data. */
+ /* Procedure invoked when deleting command to,
+ * e.g., free all client data. */
ClientData deleteData; /* Arbitrary value passed to deleteProc. */
int flags; /* Miscellaneous bits of information about
* command. See below for definitions. */
ImportRef *importRefPtr; /* List of each imported Command created in
* another namespace when this command is
- * imported. These imported commands
- * redirect invocations back to this
- * command. The list is used to remove all
- * those imported commands when deleting
- * this "real" command. */
+ * imported. These imported commands redirect
+ * invocations back to this command. The list
+ * is used to remove all those imported
+ * commands when deleting this "real"
+ * command. */
CommandTrace *tracePtr; /* First in list of all traces set for this
* command. */
} Command;
/*
- * Flag bits for commands.
+ * Flag bits for commands.
*
- * CMD_IS_DELETED - Means that the command is in the process
- * of being deleted (its deleteProc is
- * currently executing). Other attempts to
- * delete the command should be ignored.
+ * CMD_IS_DELETED - Means that the command is in the process of
+ * being deleted (its deleteProc is currently
+ * executing). Other attempts to delete the
+ * command should be ignored.
* CMD_TRACE_ACTIVE - 1 means that trace processing is currently
- * underway for a rename/delete change.
- * See the two flags below for which is
- * currently being processed.
- * CMD_HAS_EXEC_TRACES - 1 means that this command has at least
- * one execution trace (as opposed to simple
- * delete/rename traces) in its tracePtr list.
- * TCL_TRACE_RENAME - A rename trace is in progress. Further
- * recursive renames will not be traced.
- * TCL_TRACE_DELETE - A delete trace is in progress. Further
- * recursive deletes will not be traced.
+ * underway for a rename/delete change. See the
+ * two flags below for which is currently being
+ * processed.
+ * CMD_HAS_EXEC_TRACES - 1 means that this command has at least one
+ * execution trace (as opposed to simple
+ * delete/rename traces) in its tracePtr list.
+ * TCL_TRACE_RENAME - A rename trace is in progress. Further
+ * recursive renames will not be traced.
+ * TCL_TRACE_DELETE - A delete trace is in progress. Further
+ * recursive deletes will not be traced.
* (these last two flags are defined in tcl.h)
*/
-#define CMD_IS_DELETED 0x1
-#define CMD_TRACE_ACTIVE 0x2
-#define CMD_HAS_EXEC_TRACES 0x4
+
+#define CMD_IS_DELETED 0x1
+#define CMD_TRACE_ACTIVE 0x2
+#define CMD_HAS_EXEC_TRACES 0x4
/*
*----------------------------------------------------------------
@@ -1286,12 +1556,11 @@ typedef struct Command {
*/
/*
- * The interpreter keeps a linked list of name resolution schemes.
- * The scheme for a namespace is consulted first, followed by the
- * list of schemes in an interpreter, followed by the default
- * name resolution in Tcl. Schemes are added/removed from the
- * interpreter's list by calling Tcl_AddInterpResolver and
- * Tcl_RemoveInterpResolver.
+ * The interpreter keeps a linked list of name resolution schemes. The scheme
+ * for a namespace is consulted first, followed by the list of schemes in an
+ * interpreter, followed by the default name resolution in Tcl. Schemes are
+ * added/removed from the interpreter's list by calling Tcl_AddInterpResolver
+ * and Tcl_RemoveInterpResolver.
*/
typedef struct ResolverScheme {
@@ -1300,18 +1569,23 @@ typedef struct ResolverScheme {
/* Procedure handling command name
* resolution. */
Tcl_ResolveVarProc *varResProc;
- /* Procedure handling variable name
- * resolution for variables that
- * can only be handled at runtime. */
+ /* Procedure handling variable name resolution
+ * for variables that can only be handled at
+ * runtime. */
Tcl_ResolveCompiledVarProc *compiledVarResProc;
- /* Procedure handling variable name
- * resolution at compile time. */
+ /* Procedure handling variable name resolution
+ * at compile time. */
struct ResolverScheme *nextPtr;
/* Pointer to next record in linked list. */
} ResolverScheme;
-#ifdef TCL_TIP268
+/*
+ * Forward declaration of the TIP#143 limit handler structure.
+ */
+
+typedef struct LimitHandler LimitHandler;
+
/*
* TIP #268.
* Values for the selection mode, i.e the package require preferences.
@@ -1320,24 +1594,21 @@ typedef struct ResolverScheme {
enum PkgPreferOptions {
PKG_PREFER_LATEST, PKG_PREFER_STABLE
};
-#endif
/*
*----------------------------------------------------------------
- * This structure defines an interpreter, which is a collection of
- * commands plus other state information related to interpreting
- * commands, such as variable storage. Primary responsibility for
- * this data structure is in tclBasic.c, but almost every Tcl
- * source file uses something in here.
+ * This structure defines an interpreter, which is a collection of commands
+ * plus other state information related to interpreting commands, such as
+ * variable storage. Primary responsibility for this data structure is in
+ * tclBasic.c, but almost every Tcl source file uses something in here.
*----------------------------------------------------------------
*/
typedef struct Interp {
-
/*
- * Note: the first three fields must match exactly the fields in
- * a Tcl_Interp struct (see tcl.h). If you change one, be sure to
- * change the other.
+ * Note: the first three fields must match exactly the fields in a
+ * Tcl_Interp struct (see tcl.h). If you change one, be sure to change the
+ * other.
*
* The interpreter's result is held in both the string and the
* objResultPtr fields. These fields hold, respectively, the result's
@@ -1346,106 +1617,97 @@ typedef struct Interp {
* The two fields are kept consistent unless some C code sets
* interp->result directly. Programs should not access result and
* objResultPtr directly; instead, they should always get and set the
- * result using procedures such as Tcl_SetObjResult, Tcl_GetObjResult,
- * and Tcl_GetStringResult. See the SetResult man page for details.
+ * result using procedures such as Tcl_SetObjResult, Tcl_GetObjResult, and
+ * Tcl_GetStringResult. See the SetResult man page for details.
*/
char *result; /* If the last command returned a string
* result, this points to it. Should not be
* accessed directly; see comment above. */
Tcl_FreeProc *freeProc; /* Zero means a string result is statically
- * allocated. TCL_DYNAMIC means string
- * result was allocated with ckalloc and
- * should be freed with ckfree. Other values
- * give address of procedure to invoke to
- * free the string result. Tcl_Eval must
- * free it before executing next command. */
- int errorLine; /* When TCL_ERROR is returned, this gives
- * the line number in the command where the
- * error occurred (1 means first line). */
+ * allocated. TCL_DYNAMIC means string result
+ * was allocated with ckalloc and should be
+ * freed with ckfree. Other values give
+ * address of procedure to invoke to free the
+ * string result. Tcl_Eval must free it before
+ * executing next command. */
+ int errorLine; /* When TCL_ERROR is returned, this gives the
+ * line number in the command where the error
+ * occurred (1 means first line). */
struct TclStubs *stubTable;
- /* Pointer to the exported Tcl stub table.
- * On previous versions of Tcl this is a
- * pointer to the objResultPtr or a pointer
- * to a buckets array in a hash table. We
- * therefore have to do some careful checking
- * before we can use this. */
+ /* Pointer to the exported Tcl stub table. On
+ * previous versions of Tcl this is a pointer
+ * to the objResultPtr or a pointer to a
+ * buckets array in a hash table. We therefore
+ * have to do some careful checking before we
+ * can use this. */
TclHandle handle; /* Handle used to keep track of when this
* interp is deleted. */
Namespace *globalNsPtr; /* The interpreter's global namespace. */
Tcl_HashTable *hiddenCmdTablePtr;
- /* Hash table used by tclBasic.c to keep
- * track of hidden commands on a per-interp
+ /* Hash table used by tclBasic.c to keep track
+ * of hidden commands on a per-interp
* basis. */
ClientData interpInfo; /* Information used by tclInterp.c to keep
- * track of master/slave interps on
- * a per-interp basis. */
- Tcl_HashTable mathFuncTable;/* Contains all the math functions currently
- * defined for the interpreter. Indexed by
- * strings (function names); values have
- * type (MathFunc *). */
-
-
+ * track of master/slave interps on a
+ * per-interp basis. */
+ Tcl_HashTable unused2; /* No longer used (was mathFuncTable) */
/*
- * Information related to procedures and variables. See tclProc.c
- * and tclVar.c for usage.
+ * Information related to procedures and variables. See tclProc.c and
+ * tclVar.c for usage.
*/
int numLevels; /* Keeps track of how many nested calls to
* Tcl_Eval are in progress for this
- * interpreter. It's used to delay deletion
- * of the table until all Tcl_Eval
- * invocations are completed. */
+ * interpreter. It's used to delay deletion of
+ * the table until all Tcl_Eval invocations
+ * are completed. */
int maxNestingDepth; /* If numLevels exceeds this value then Tcl
* assumes that infinite recursion has
* occurred and it generates an error. */
CallFrame *framePtr; /* Points to top-most in stack of all nested
- * procedure invocations. NULL means there
- * are no active procedures. */
+ * procedure invocations. */
CallFrame *varFramePtr; /* Points to the call frame whose variables
* are currently in use (same as framePtr
* unless an "uplevel" command is
- * executing). NULL means no procedure is
- * active or "uplevel 0" is executing. */
+ * executing). */
ActiveVarTrace *activeVarTracePtr;
- /* First in list of active traces for
- * interp, or NULL if no active traces. */
- int returnCode; /* Completion code to return if current
- * procedure exits with TCL_RETURN code. */
- char *errorInfo; /* Value to store in errorInfo if returnCode
- * is TCL_ERROR. Malloc'ed, may be NULL */
- char *errorCode; /* Value to store in errorCode if returnCode
- * is TCL_ERROR. Malloc'ed, may be NULL */
+ /* First in list of active traces for interp,
+ * or NULL if no active traces. */
+ int returnCode; /* [return -code] parameter. */
+ CallFrame *rootFramePtr; /* Global frame pointer for this
+ * interpreter. */
+ Namespace *lookupNsPtr; /* Namespace to use ONLY on the next
+ * TCL_EVAL_INVOKE call to Tcl_EvalObjv. */
/*
- * Information used by Tcl_AppendResult to keep track of partial
- * results. See Tcl_AppendResult code for details.
+ * Information used by Tcl_AppendResult to keep track of partial results.
+ * See Tcl_AppendResult code for details.
*/
- char *appendResult; /* Storage space for results generated
- * by Tcl_AppendResult. Malloc-ed. NULL
- * means not yet allocated. */
+ char *appendResult; /* Storage space for results generated by
+ * Tcl_AppendResult. Ckalloc-ed. NULL means
+ * not yet allocated. */
int appendAvl; /* Total amount of space available at
* partialResult. */
- int appendUsed; /* Number of non-null bytes currently
- * stored at partialResult. */
+ int appendUsed; /* Number of non-null bytes currently stored
+ * at partialResult. */
/*
- * Information about packages. Used only in tclPkg.c.
+ * Information about packages. Used only in tclPkg.c.
*/
- Tcl_HashTable packageTable; /* Describes all of the packages loaded
- * in or available to this interpreter.
- * Keys are package names, values are
- * (Package *) pointers. */
- char *packageUnknown; /* Command to invoke during "package
- * require" commands for packages that
- * aren't described in packageTable.
- * Malloc'ed, may be NULL. */
-
+ Tcl_HashTable packageTable; /* Describes all of the packages loaded in or
+ * available to this interpreter. Keys are
+ * package names, values are (Package *)
+ * pointers. */
+ char *packageUnknown; /* Command to invoke during "package require"
+ * commands for packages that aren't described
+ * in packageTable. Ckalloc'ed, may be
+ * NULL. */
/*
* Miscellaneous information:
*/
@@ -1454,44 +1716,42 @@ typedef struct Interp {
* has been called for this interpreter. */
int evalFlags; /* Flags to control next call to Tcl_Eval.
* Normally zero, but may be set before
- * calling Tcl_Eval. See below for valid
+ * calling Tcl_Eval. See below for valid
* values. */
- int termOffset; /* Offset of character just after last one
- * compiled or executed by Tcl_EvalObj. */
- LiteralTable literalTable; /* Contains LiteralEntry's describing all
- * Tcl objects holding literals of scripts
- * compiled by the interpreter. Indexed by
- * the string representations of literals.
- * Used to avoid creating duplicate
- * objects. */
- int compileEpoch; /* Holds the current "compilation epoch"
- * for this interpreter. This is
- * incremented to invalidate existing
- * ByteCodes when, e.g., a command with a
- * compile procedure is redefined. */
- Proc *compiledProcPtr; /* If a procedure is being compiled, a
- * pointer to its Proc structure; otherwise,
- * this is NULL. Set by ObjInterpProc in
- * tclProc.c and used by tclCompile.c to
- * process local variables appropriately. */
+ int unused1; /* No longer used (was termOffset) */
+ LiteralTable literalTable; /* Contains LiteralEntry's describing all Tcl
+ * objects holding literals of scripts
+ * compiled by the interpreter. Indexed by the
+ * string representations of literals. Used to
+ * avoid creating duplicate objects. */
+ int compileEpoch; /* Holds the current "compilation epoch" for
+ * this interpreter. This is incremented to
+ * invalidate existing ByteCodes when, e.g., a
+ * command with a compile procedure is
+ * redefined. */
+ Proc *compiledProcPtr; /* If a procedure is being compiled, a pointer
+ * to its Proc structure; otherwise, this is
+ * NULL. Set by ObjInterpProc in tclProc.c and
+ * used by tclCompile.c to process local
+ * variables appropriately. */
ResolverScheme *resolverPtr;
/* Linked list of name resolution schemes
- * added to this interpreter. Schemes
- * are added/removed by calling
+ * added to this interpreter. Schemes are
+ * added and removed by calling
* Tcl_AddInterpResolvers and
- * Tcl_RemoveInterpResolver. */
+ * Tcl_RemoveInterpResolver respectively. */
Tcl_Obj *scriptFile; /* NULL means there is no nested source
- * command active; otherwise this points to
+ * command active; otherwise this points to
* pathPtr of the file being sourced. */
- int flags; /* Various flag bits. See below. */
+ int flags; /* Various flag bits. See below. */
long randSeed; /* Seed used for rand() function. */
Trace *tracePtr; /* List of traces for this interpreter. */
- Tcl_HashTable *assocData; /* Hash table for associating data with
- * this interpreter. Cleaned up when
- * this interpreter is deleted. */
+ Tcl_HashTable *assocData; /* Hash table for associating data with this
+ * interpreter. Cleaned up when this
+ * interpreter is deleted. */
struct ExecEnv *execEnvPtr; /* Execution environment for Tcl bytecode
- * execution. Contains a pointer to the
- * Tcl evaluation stack. */
+ * execution. Contains a pointer to the Tcl
+ * evaluation stack. */
Tcl_Obj *emptyObjPtr; /* Points to an object holding an empty
* string. Returned by Tcl_ObjSetVar2 when
* variable traces change a variable in a
@@ -1501,67 +1761,137 @@ typedef struct Interp {
Tcl_Obj *objResultPtr; /* If the last command returned an object
* result, this points to it. Should not be
* accessed directly; see comment above. */
- Tcl_ThreadId threadId; /* ID of thread that owns the interpreter */
+ Tcl_ThreadId threadId; /* ID of thread that owns the interpreter. */
ActiveCommandTrace *activeCmdTracePtr;
/* First in list of active command traces for
* interp, or NULL if no active traces. */
ActiveInterpTrace *activeInterpTracePtr;
- /* First in list of active traces for
- * interp, or NULL if no active traces. */
+ /* First in list of active traces for interp,
+ * or NULL if no active traces. */
- int tracesForbiddingInline; /* Count of traces (in the list headed by
+ int tracesForbiddingInline; /* Count of traces (in the list headed by
* tracePtr) that forbid inline bytecode
- * compilation */
-#ifdef TCL_TIP280
- /* TIP #280 */
- CmdFrame* cmdFramePtr; /* Points to the command frame containing
- * the location information for the current
+ * compilation. */
+
+ /*
+ * Fields used to manage extensible return options (TIP 90).
+ */
+
+ Tcl_Obj *returnOpts; /* A dictionary holding the options to the
+ * last [return] command. */
+
+ Tcl_Obj *errorInfo; /* errorInfo value (now as a Tcl_Obj). */
+ Tcl_Obj *eiVar; /* cached ref to ::errorInfo variable. */
+ Tcl_Obj *errorCode; /* errorCode value (now as a Tcl_Obj). */
+ Tcl_Obj *ecVar; /* cached ref to ::errorInfo variable. */
+ int returnLevel; /* [return -level] parameter. */
+
+ /*
+ * Resource limiting framework support (TIP#143).
+ */
+
+ struct {
+ int active; /* Flag values defining which limits have been
+ * set. */
+ int granularityTicker; /* Counter used to determine how often to
+ * check the limits. */
+ int exceeded; /* Which limits have been exceeded, described
+ * as flag values the same as the 'active'
+ * field. */
+
+ int cmdCount; /* Limit for how many commands to execute in
+ * the interpreter. */
+ LimitHandler *cmdHandlers;
+ /* Handlers to execute when the limit is
+ * reached. */
+ int cmdGranularity; /* Mod factor used to determine how often to
+ * evaluate the limit check. */
+
+ Tcl_Time time; /* Time limit for execution within the
+ * interpreter. */
+ LimitHandler *timeHandlers;
+ /* Handlers to execute when the limit is
+ * reached. */
+ int timeGranularity; /* Mod factor used to determine how often to
+ * evaluate the limit check. */
+ Tcl_TimerToken timeEvent;
+ /* Handle for a timer callback that will occur
+ * when the time-limit is exceeded. */
+
+ Tcl_HashTable callbacks;/* Mapping from (interp,type) pair to data
+ * used to install a limit handler callback to
+ * run in _this_ interp when the limit is
+ * exceeded. */
+ } limit;
+
+ /*
+ * Information for improved default error generation from ensembles
+ * (TIP#112).
+ */
+
+ struct {
+ Tcl_Obj *const *sourceObjs;
+ /* What arguments were actually input into the
+ * *root* ensemble command? (Nested ensembles
+ * don't rewrite this.) NULL if we're not
+ * processing an ensemble. */
+ int numRemovedObjs; /* How many arguments have been stripped off
+ * because of ensemble processing. */
+ int numInsertedObjs; /* How many of the current arguments were
+ * inserted by an ensemble. */
+ } ensembleRewrite;
+
+ /*
+ * TIP #219: Global info for the I/O system.
+ */
+
+ Tcl_Obj *chanMsg; /* Error message set by channel drivers, for
+ * the propagation of arbitrary Tcl errors.
+ * This information, if present (chanMsg not
+ * NULL), takes precedence over a POSIX error
+ * code returned by a channel operation. */
+
+ /*
+ * Source code origin information (TIP #280).
+ */
+
+ CmdFrame *cmdFramePtr; /* Points to the command frame containing the
+ * location information for the current
* command. */
- CONST CmdFrame* invokeCmdFramePtr; /* Points to the command frame which is the
- * invoking context of the bytecode compiler.
- * NULL when the byte code compiler is not
- * active */
- int invokeWord; /* Index of the word in the command which
+ const CmdFrame *invokeCmdFramePtr;
+ /* Points to the command frame which is the
+ * invoking context of the bytecode compiler.
+ * NULL when the byte code compiler is not
+ * active. */
+ int invokeWord; /* Index of the word in the command which
* is getting compiled. */
- Tcl_HashTable* linePBodyPtr;
- /* This table remembers for each
- * statically defined procedure the
- * location information for its
- * body. It is keyed by the address of
- * the Proc structure for a procedure.
- * The values are "struct CmdFrame*".
- */
- Tcl_HashTable* lineBCPtr;
- /* This table remembers for each
- * ByteCode object the location
- * information for its body. It is
- * keyed by the address of the Proc
- * structure for a procedure. The
- * values are "struct ExtCmdLoc*" (See
- * tclCompile.h).
- */
- Tcl_HashTable* lineLABCPtr;
- Tcl_HashTable* lineLAPtr;
- /* This table remembers for each
- * argument of a command on the
- * execution stack the index of the
- * argument in the command, and the
- * location data of the command. It is
- * keyed by the address of the Tcl_Obj
- * containing the argument. The values
- * are "struct CFWord*" (See
- * tclBasic.c). This allows commands
- * like uplevel, eval, etc. to find
- * location information for their
- * arguments, if they are a proper
- * literal argument to an invoking
- * command. Alt view: An index to the
- * CmdFrame stack keyed by command
- * argument holders.
- */
- ContLineLoc* scriptCLLocPtr;
- /* This table points to the location data for
+ Tcl_HashTable *linePBodyPtr;/* This table remembers for each statically
+ * defined procedure the location information
+ * for its body. It is keyed by the address of
+ * the Proc structure for a procedure. The
+ * values are "struct CmdFrame*". */
+ Tcl_HashTable *lineBCPtr; /* This table remembers for each ByteCode
+ * object the location information for its
+ * body. It is keyed by the address of the
+ * Proc structure for a procedure. The values
+ * are "struct ExtCmdLoc*". (See
+ * tclCompile.h) */
+ Tcl_HashTable *lineLABCPtr;
+ Tcl_HashTable *lineLAPtr; /* This table remembers for each argument of a
+ * command on the execution stack the index of
+ * the argument in the command, and the
+ * location data of the command. It is keyed
+ * by the address of the Tcl_Obj containing
+ * the argument. The values are "struct
+ * CFWord*" (See tclBasic.c). This allows
+ * commands like uplevel, eval, etc. to find
+ * location information for their arguments,
+ * if they are a proper literal argument to an
+ * invoking command. Alt view: An index to the
+ * CmdFrame stack keyed by command argument
+ * holders. */
+ ContLineLoc *scriptCLLocPtr;/* This table points to the location data for
* invisible continuation lines in the script,
* if any. This pointer is set by the function
* TclEvalObjEx() in file "tclBasic.c", and
@@ -1570,43 +1900,114 @@ typedef struct Interp {
* execution what CompileEnv.clLoc does for
* the bytecode compiler.
*/
-#endif
-#ifdef TCL_TIP268
/*
- * TIP #268.
- * The currently active selection mode,
- * i.e the package require preferences.
+ * TIP #268. The currently active selection mode, i.e. the package require
+ * preferences.
*/
- int packagePrefer; /* Current package selection mode. */
-#endif
+ int packagePrefer; /* Current package selection mode. */
+
+ /*
+ * Hashtables for variable traces and searches.
+ */
+
+ Tcl_HashTable varTraces; /* Hashtable holding the start of a variable's
+ * active trace list; varPtr is the key. */
+ Tcl_HashTable varSearches; /* Hashtable holding the start of a variable's
+ * active searches list; varPtr is the key. */
+ /*
+ * The thread-specific data ekeko: cache pointers or values that
+ * (a) do not change during the thread's lifetime
+ * (b) require access to TSD to determine at runtime
+ * (c) are accessed very often (e.g., at each command call)
+ *
+ * Note that these are the same for all interps in the same thread. They
+ * just have to be initialised for the thread's master interp, slaves
+ * inherit the value.
+ *
+ * They are used by the macros defined below.
+ */
+
+ void *allocCache;
+ void *pendingObjDataPtr; /* Pointer to the Cache and PendingObjData
+ * structs for this interp's thread; see
+ * tclObj.c and tclThreadAlloc.c */
+ int *asyncReadyPtr; /* Pointer to the asyncReady indicator for
+ * this interp's thread; see tclAsync.c */
+ int *stackBound; /* Pointer to the limit stack address
+ * allowable for invoking a new command
+ * without "risking" a C-stack overflow; see
+ * TclpCheckStackSpace in the platform's
+ * directory. */
+
+
+#ifdef TCL_COMPILE_STATS
/*
* Statistical information about the bytecode compiler and interpreter's
* operation.
*/
-#ifdef TCL_COMPILE_STATS
- ByteCodeStats stats; /* Holds compilation and execution
- * statistics for this interpreter. */
-#endif /* TCL_COMPILE_STATS */
+ ByteCodeStats stats; /* Holds compilation and execution statistics
+ * for this interpreter. */
+#endif /* TCL_COMPILE_STATS */
} Interp;
/*
+ * Macros that use the TSD-ekeko.
+ */
+
+#define TclAsyncReady(iPtr) \
+ *((iPtr)->asyncReadyPtr)
+
+/*
+ * General list of interpreters. Doubly linked for easier removal of items
+ * deep in the list.
+ */
+
+typedef struct InterpList {
+ Interp *interpPtr;
+ struct InterpList *prevPtr;
+ struct InterpList *nextPtr;
+} InterpList;
+
+/*
+ * Macros for splicing into and out of doubly linked lists. They assume
+ * existence of struct items 'prevPtr' and 'nextPtr'.
+ *
+ * a = element to add or remove.
+ * b = list head.
+ *
+ * TclSpliceIn adds to the head of the list.
+ */
+
+#define TclSpliceIn(a,b) \
+ (a)->nextPtr = (b); \
+ if ((b) != NULL) { \
+ (b)->prevPtr = (a); \
+ } \
+ (a)->prevPtr = NULL, (b) = (a);
+
+#define TclSpliceOut(a,b) \
+ if ((a)->prevPtr != NULL) { \
+ (a)->prevPtr->nextPtr = (a)->nextPtr; \
+ } else { \
+ (b) = (a)->nextPtr; \
+ } \
+ if ((a)->nextPtr != NULL) { \
+ (a)->nextPtr->prevPtr = (a)->prevPtr; \
+ }
+
+/*
* EvalFlag bits for Interp structures:
*
- * TCL_BRACKET_TERM 1 means that the current script is terminated by
- * a close bracket rather than the end of the string.
- * TCL_ALLOW_EXCEPTIONS 1 means it's OK for the script to terminate with
- * a code other than TCL_OK or TCL_ERROR; 0 means
- * codes other than these should be turned into errors.
- */
-
-#define TCL_BRACKET_TERM 1
-#define TCL_ALLOW_EXCEPTIONS 4
-#ifdef TCL_TIP280
-#define TCL_EVAL_FILE 2
-#define TCL_EVAL_CTX 8
-#endif
+ * TCL_ALLOW_EXCEPTIONS 1 means it's OK for the script to terminate with a
+ * code other than TCL_OK or TCL_ERROR; 0 means codes
+ * other than these should be turned into errors.
+ */
+
+#define TCL_ALLOW_EXCEPTIONS 4
+#define TCL_EVAL_FILE 2
+#define TCL_EVAL_CTX 8
/*
* Flag bits for Interp structures:
@@ -1615,116 +2016,155 @@ typedef struct Interp {
* don't process any more commands for it, and destroy
* the structure as soon as all nested invocations of
* Tcl_Eval are done.
- * ERR_IN_PROGRESS: Non-zero means an error unwind is already in
- * progress. Zero means a command proc has been
- * invoked since last error occured.
- * ERR_ALREADY_LOGGED: Non-zero means information has already been logged
- * in $errorInfo for the current Tcl_Eval instance,
- * so Tcl_Eval needn't log it (used to implement the
- * "error message log" command).
- * ERROR_CODE_SET: Non-zero means that Tcl_SetErrorCode has been
- * called to record information for the current
- * error. Zero means Tcl_Eval must clear the
- * errorCode variable if an error is returned.
- * EXPR_INITIALIZED: Non-zero means initialization specific to
- * expressions has been carried out.
- * DONT_COMPILE_CMDS_INLINE: Non-zero means that the bytecode compiler
- * should not compile any commands into an inline
- * sequence of instructions. This is set 1, for
- * example, when command traces are requested.
- * RAND_SEED_INITIALIZED: Non-zero means that the randSeed value of the
- * interp has not be initialized. This is set 1
- * when we first use the rand() or srand() functions.
- * SAFE_INTERP: Non zero means that the current interp is a
- * safe interp (ie it has only the safe commands
- * installed, less priviledge than a regular interp).
- * USE_EVAL_DIRECT: Non-zero means don't use the compiler or byte-code
- * interpreter; instead, have Tcl_EvalObj call
- * Tcl_EvalEx. Used primarily for testing the
- * new parser.
+ * ERR_ALREADY_LOGGED: Non-zero means information has already been logged in
+ * iPtr->errorInfo for the current Tcl_Eval instance, so
+ * Tcl_Eval needn't log it (used to implement the "error
+ * message log" command).
+ * DONT_COMPILE_CMDS_INLINE: Non-zero means that the bytecode compiler should
+ * not compile any commands into an inline sequence of
+ * instructions. This is set 1, for example, when command
+ * traces are requested.
+ * RAND_SEED_INITIALIZED: Non-zero means that the randSeed value of the interp
+ * has not be initialized. This is set 1 when we first
+ * use the rand() or srand() functions.
+ * SAFE_INTERP: Non zero means that the current interp is a safe
+ * interp (i.e. it has only the safe commands installed,
+ * less priviledge than a regular interp).
+ * INTERP_DEBUG_FRAME: Used for switching on various extra interpreter
+ * debug/info mechanisms (e.g. info frame eval/uplevel
+ * tracing) which are performance intensive.
* INTERP_TRACE_IN_PROGRESS: Non-zero means that an interp trace is currently
* active; so no further trace callbacks should be
* invoked.
+ * INTERP_ALTERNATE_WRONG_ARGS: Used for listing second and subsequent forms
+ * of the wrong-num-args string in Tcl_WrongNumArgs.
+ * Makes it append instead of replacing and uses
+ * different intermediate text.
+ *
+ * WARNING: For the sake of some extensions that have made use of former
+ * internal values, do not re-use the flag values 2 (formerly ERR_IN_PROGRESS)
+ * or 8 (formerly ERROR_CODE_SET).
*/
-#define DELETED 1
-#define ERR_IN_PROGRESS 2
-#define ERR_ALREADY_LOGGED 4
-#define ERROR_CODE_SET 8
-#define EXPR_INITIALIZED 0x10
-#define DONT_COMPILE_CMDS_INLINE 0x20
-#define RAND_SEED_INITIALIZED 0x40
-#define SAFE_INTERP 0x80
-#define USE_EVAL_DIRECT 0x100
-#define INTERP_TRACE_IN_PROGRESS 0x200
+#define DELETED 1
+#define ERR_ALREADY_LOGGED 4
+#define INTERP_DEBUG_FRAME 0x10
+#define DONT_COMPILE_CMDS_INLINE 0x20
+#define RAND_SEED_INITIALIZED 0x40
+#define SAFE_INTERP 0x80
+#define INTERP_TRACE_IN_PROGRESS 0x200
+#define INTERP_ALTERNATE_WRONG_ARGS 0x400
+#define ERR_LEGACY_COPY 0x800
/*
- * Maximum number of levels of nesting permitted in Tcl commands (used
- * to catch infinite recursion).
+ * Maximum number of levels of nesting permitted in Tcl commands (used to
+ * catch infinite recursion).
*/
#define MAX_NESTING_DEPTH 1000
/*
- * The macro below is used to modify a "char" value (e.g. by casting
- * it to an unsigned character) so that it can be used safely with
- * macros such as isspace.
+ * TIP#143 limit handler internal representation.
+ */
+
+struct LimitHandler {
+ int flags; /* The state of this particular handler. */
+ Tcl_LimitHandlerProc *handlerProc;
+ /* The handler callback. */
+ ClientData clientData; /* Opaque argument to the handler callback. */
+ Tcl_LimitHandlerDeleteProc *deleteProc;
+ /* How to delete the clientData. */
+ LimitHandler *prevPtr; /* Previous item in linked list of
+ * handlers. */
+ LimitHandler *nextPtr; /* Next item in linked list of handlers. */
+};
+
+/*
+ * Values for the LimitHandler flags field.
+ * LIMIT_HANDLER_ACTIVE - Whether the handler is currently being
+ * processed; handlers are never to be entered reentrantly.
+ * LIMIT_HANDLER_DELETED - Whether the handler has been deleted. This
+ * should not normally be observed because when a handler is
+ * deleted it is also spliced out of the list of handlers, but
+ * even so we will be careful.
+ */
+
+#define LIMIT_HANDLER_ACTIVE 0x01
+#define LIMIT_HANDLER_DELETED 0x02
+
+/*
+ * The macro below is used to modify a "char" value (e.g. by casting it to an
+ * unsigned character) so that it can be used safely with macros such as
+ * isspace.
*/
#define UCHAR(c) ((unsigned char) (c))
/*
+ * This macro is used to properly align the memory allocated by Tcl, giving
+ * the same alignment as the native malloc.
+ */
+
+#if defined(__APPLE__)
+#define TCL_ALLOCALIGN 16
+#else
+#define TCL_ALLOCALIGN (2*sizeof(void *))
+#endif
+
+/*
* This macro is used to determine the offset needed to safely allocate any
* data structure in memory. Given a starting offset or size, it "rounds up"
* or "aligns" the offset to the next 8-byte boundary so that any data
* structure can be placed at the resulting offset without fear of an
* alignment error.
*
- * WARNING!! DO NOT USE THIS MACRO TO ALIGN POINTERS: it will produce
- * the wrong result on platforms that allocate addresses that are divisible
- * by 4 or 2. Only use it for offsets or sizes.
+ * WARNING!! DO NOT USE THIS MACRO TO ALIGN POINTERS: it will produce the
+ * wrong result on platforms that allocate addresses that are divisible by 4
+ * or 2. Only use it for offsets or sizes.
+ *
+ * This macro is only used by tclCompile.c in the core (Bug 926445). It
+ * however not be made file static, as extensions that touch bytecodes
+ * (notably tbcload) require it.
*/
#define TCL_ALIGN(x) (((int)(x) + 7) & ~7)
/*
- * The following enum values are used to specify the runtime platform
- * setting of the tclPlatform variable.
+ * The following enum values are used to specify the runtime platform setting
+ * of the tclPlatform variable.
*/
typedef enum {
- TCL_PLATFORM_UNIX, /* Any Unix-like OS. */
- TCL_PLATFORM_MAC, /* MacOS. */
- TCL_PLATFORM_WINDOWS /* Any Microsoft Windows OS. */
+ TCL_PLATFORM_UNIX = 0, /* Any Unix-like OS. */
+ TCL_PLATFORM_WINDOWS = 2 /* Any Microsoft Windows OS. */
} TclPlatformType;
/*
- * The following enum values are used to indicate the translation
- * of a Tcl channel. Declared here so that each platform can define
- * TCL_PLATFORM_TRANSLATION to the native translation on that platform
+ * The following enum values are used to indicate the translation of a Tcl
+ * channel. Declared here so that each platform can define
+ * TCL_PLATFORM_TRANSLATION to the native translation on that platform.
*/
typedef enum TclEolTranslation {
- TCL_TRANSLATE_AUTO, /* Eol == \r, \n and \r\n. */
- TCL_TRANSLATE_CR, /* Eol == \r. */
- TCL_TRANSLATE_LF, /* Eol == \n. */
- TCL_TRANSLATE_CRLF /* Eol == \r\n. */
+ TCL_TRANSLATE_AUTO, /* Eol == \r, \n and \r\n. */
+ TCL_TRANSLATE_CR, /* Eol == \r. */
+ TCL_TRANSLATE_LF, /* Eol == \n. */
+ TCL_TRANSLATE_CRLF /* Eol == \r\n. */
} TclEolTranslation;
/*
* Flags for TclInvoke:
*
- * TCL_INVOKE_HIDDEN Invoke a hidden command; if not set,
- * invokes an exposed command.
- * TCL_INVOKE_NO_UNKNOWN If set, "unknown" is not invoked if
- * the command to be invoked is not found.
- * Only has an effect if invoking an exposed
- * command, i.e. if TCL_INVOKE_HIDDEN is not
- * also set.
- * TCL_INVOKE_NO_TRACEBACK Does not record traceback information if
- * the invoked command returns an error. Used
- * if the caller plans on recording its own
- * traceback information.
+ * TCL_INVOKE_HIDDEN Invoke a hidden command; if not set, invokes
+ * an exposed command.
+ * TCL_INVOKE_NO_UNKNOWN If set, "unknown" is not invoked if the
+ * command to be invoked is not found. Only has
+ * an effect if invoking an exposed command,
+ * i.e. if TCL_INVOKE_HIDDEN is not also set.
+ * TCL_INVOKE_NO_TRACEBACK Does not record traceback information if the
+ * invoked command returns an error. Used if the
+ * caller plans on recording its own traceback
+ * information.
*/
#define TCL_INVOKE_HIDDEN (1<<0)
@@ -1732,62 +2172,176 @@ typedef enum TclEolTranslation {
#define TCL_INVOKE_NO_TRACEBACK (1<<2)
/*
- * The structure used as the internal representation of Tcl list
- * objects. This is an array of pointers to the element objects. This array
- * is grown (reallocated and copied) as necessary to hold all the list's
- * element pointers. The array might contain more slots than currently used
- * to hold all element pointers. This is done to make append operations
+ * The structure used as the internal representation of Tcl list objects. This
+ * struct is grown (reallocated and copied) as necessary to hold all the
+ * list's element pointers. The struct might contain more slots than currently
+ * used to hold all element pointers. This is done to make append operations
* faster.
*/
typedef struct List {
+ int refCount;
int maxElemCount; /* Total number of element array slots. */
int elemCount; /* Current number of list elements. */
- Tcl_Obj **elements; /* Array of pointers to element objects. */
+ int canonicalFlag; /* Set if the string representation was
+ * derived from the list representation. May
+ * be ignored if there is no string rep at
+ * all.*/
+ Tcl_Obj *elements; /* First list element; the struct is grown to
+ * accomodate all elements. */
} List;
+#define LIST_MAX \
+ (1 + (int)(((size_t)UINT_MAX - sizeof(List))/sizeof(Tcl_Obj *)))
/*
- * The following types are used for getting and storing platform-specific
- * file attributes in tclFCmd.c and the various platform-versions of
- * that file. This is done to have as much common code as possible
- * in the file attributes code. For more information about the callbacks,
- * see TclFileAttrsCmd in tclFCmd.c.
+ * Macro used to get the elements of a list object.
*/
-typedef int (TclGetFileAttrProc) _ANSI_ARGS_((Tcl_Interp *interp,
- int objIndex, Tcl_Obj *fileName, Tcl_Obj **attrObjPtrPtr));
-typedef int (TclSetFileAttrProc) _ANSI_ARGS_((Tcl_Interp *interp,
- int objIndex, Tcl_Obj *fileName, Tcl_Obj *attrObjPtr));
+#define ListRepPtr(listPtr) \
+ ((List *) (listPtr)->internalRep.twoPtrValue.ptr1)
+
+#define ListSetIntRep(objPtr, listRepPtr) \
+ (objPtr)->internalRep.twoPtrValue.ptr1 = (void *)(listRepPtr), \
+ (objPtr)->internalRep.twoPtrValue.ptr2 = NULL, \
+ (listRepPtr)->refCount++, \
+ (objPtr)->typePtr = &tclListType
+
+#define ListObjGetElements(listPtr, objc, objv) \
+ ((objv) = &(ListRepPtr(listPtr)->elements), \
+ (objc) = ListRepPtr(listPtr)->elemCount)
+
+#define ListObjLength(listPtr, len) \
+ ((len) = ListRepPtr(listPtr)->elemCount)
+
+#define ListObjIsCanonical(listPtr) \
+ (((listPtr)->bytes == NULL) || ListRepPtr(listPtr)->canonicalFlag)
+
+#define TclListObjGetElements(interp, listPtr, objcPtr, objvPtr) \
+ (((listPtr)->typePtr == &tclListType) \
+ ? ((ListObjGetElements((listPtr), *(objcPtr), *(objvPtr))), TCL_OK)\
+ : Tcl_ListObjGetElements((interp), (listPtr), (objcPtr), (objvPtr)))
+
+#define TclListObjLength(interp, listPtr, lenPtr) \
+ (((listPtr)->typePtr == &tclListType) \
+ ? ((ListObjLength((listPtr), *(lenPtr))), TCL_OK)\
+ : Tcl_ListObjLength((interp), (listPtr), (lenPtr)))
+
+#define TclListObjIsCanonical(listPtr) \
+ (((listPtr)->typePtr == &tclListType) ? ListObjIsCanonical((listPtr)) : 0)
+
+/*
+ * Macros providing a faster path to integers: Tcl_GetLongFromObj everywhere,
+ * Tcl_GetIntFromObj and TclGetIntForIndex on platforms where longs are ints.
+ *
+ * WARNING: these macros eval their args more than once.
+ */
+
+#define TclGetLongFromObj(interp, objPtr, longPtr) \
+ (((objPtr)->typePtr == &tclIntType) \
+ ? ((*(longPtr) = (objPtr)->internalRep.longValue), TCL_OK) \
+ : Tcl_GetLongFromObj((interp), (objPtr), (longPtr)))
+
+#if (LONG_MAX == INT_MAX)
+#define TclGetIntFromObj(interp, objPtr, intPtr) \
+ (((objPtr)->typePtr == &tclIntType) \
+ ? ((*(intPtr) = (objPtr)->internalRep.longValue), TCL_OK) \
+ : Tcl_GetIntFromObj((interp), (objPtr), (intPtr)))
+#define TclGetIntForIndexM(interp, objPtr, endValue, idxPtr) \
+ (((objPtr)->typePtr == &tclIntType) \
+ ? ((*(idxPtr) = (objPtr)->internalRep.longValue), TCL_OK) \
+ : TclGetIntForIndex((interp), (objPtr), (endValue), (idxPtr)))
+#else
+#define TclGetIntFromObj(interp, objPtr, intPtr) \
+ Tcl_GetIntFromObj((interp), (objPtr), (intPtr))
+#define TclGetIntForIndexM(interp, objPtr, ignore, idxPtr) \
+ TclGetIntForIndex(interp, objPtr, ignore, idxPtr)
+#endif
+
+/*
+ * Flag values for TclTraceDictPath().
+ *
+ * DICT_PATH_READ indicates that all entries on the path must exist but no
+ * updates will be needed.
+ *
+ * DICT_PATH_UPDATE indicates that we are going to be doing an update at the
+ * tip of the path, so duplication of shared objects should be done along the
+ * way.
+ *
+ * DICT_PATH_EXISTS indicates that we are performing an existance test and a
+ * lookup failure should therefore not be an error. If (and only if) this flag
+ * is set, TclTraceDictPath() will return the special value
+ * DICT_PATH_NON_EXISTENT if the path is not traceable.
+ *
+ * DICT_PATH_CREATE (which also requires the DICT_PATH_UPDATE bit to be set)
+ * indicates that we are to create non-existant dictionaries on the path.
+ */
+
+#define DICT_PATH_READ 0
+#define DICT_PATH_UPDATE 1
+#define DICT_PATH_EXISTS 2
+#define DICT_PATH_CREATE 5
+
+#define DICT_PATH_NON_EXISTENT ((Tcl_Obj *) (void *) 1)
+
+/*
+ *----------------------------------------------------------------
+ * Data structures related to the filesystem internals
+ *----------------------------------------------------------------
+ */
+
+/*
+ * The version_2 filesystem is private to Tcl. As and when these changes have
+ * been thoroughly tested and investigated a new public filesystem interface
+ * will be released. The aim is more versatile virtual filesystem interfaces,
+ * more efficiency in 'path' manipulation and usage, and cleaner filesystem
+ * code internally.
+ */
+
+#define TCL_FILESYSTEM_VERSION_2 ((Tcl_FSVersion) 0x2)
+typedef ClientData (TclFSGetCwdProc2)(ClientData clientData);
+
+/*
+ * The following types are used for getting and storing platform-specific file
+ * attributes in tclFCmd.c and the various platform-versions of that file.
+ * This is done to have as much common code as possible in the file attributes
+ * code. For more information about the callbacks, see TclFileAttrsCmd in
+ * tclFCmd.c.
+ */
+
+typedef int (TclGetFileAttrProc)(Tcl_Interp *interp, int objIndex,
+ Tcl_Obj *fileName, Tcl_Obj **attrObjPtrPtr);
+typedef int (TclSetFileAttrProc)(Tcl_Interp *interp, int objIndex,
+ Tcl_Obj *fileName, Tcl_Obj *attrObjPtr);
typedef struct TclFileAttrProcs {
- TclGetFileAttrProc *getProc; /* The procedure for getting attrs. */
- TclSetFileAttrProc *setProc; /* The procedure for setting attrs. */
+ TclGetFileAttrProc *getProc;/* The procedure for getting attrs. */
+ TclSetFileAttrProc *setProc;/* The procedure for setting attrs. */
} TclFileAttrProcs;
/*
* Opaque handle used in pipeline routines to encapsulate platform-dependent
- * state.
+ * state.
*/
typedef struct TclFile_ *TclFile;
-
-/*
- * Opaque names for platform specific types.
- */
-
-typedef struct TclpTime_t_ *TclpTime_t;
-typedef struct TclpTime_t_ *CONST TclpTime_t_CONST;
/*
- * The "globParameters" argument of the function TclGlob is an
- * or'ed combination of the following values:
+ * The "globParameters" argument of the function TclGlob is an or'ed
+ * combination of the following values:
*/
-#define TCL_GLOBMODE_NO_COMPLAIN 1
-#define TCL_GLOBMODE_JOIN 2
-#define TCL_GLOBMODE_DIR 4
-#define TCL_GLOBMODE_TAILS 8
+#define TCL_GLOBMODE_NO_COMPLAIN 1
+#define TCL_GLOBMODE_JOIN 2
+#define TCL_GLOBMODE_DIR 4
+#define TCL_GLOBMODE_TAILS 8
+
+typedef enum Tcl_PathPart {
+ TCL_PATH_DIRNAME,
+ TCL_PATH_TAIL,
+ TCL_PATH_EXTENSION,
+ TCL_PATH_ROOT
+} Tcl_PathPart;
/*
*----------------------------------------------------------------
@@ -1795,12 +2349,10 @@ typedef struct TclpTime_t_ *CONST TclpTime_t_CONST;
*----------------------------------------------------------------
*/
-typedef int (TclStatProc_) _ANSI_ARGS_((CONST char *path, Tcl_StatBuf *buf));
-typedef int (TclAccessProc_) _ANSI_ARGS_((CONST char *path, int mode));
-typedef Tcl_Channel (TclOpenFileChannelProc_) _ANSI_ARGS_((Tcl_Interp *interp,
- CONST char *fileName, CONST char *modeString,
- int permissions));
-
+typedef int (TclStatProc_)(CONST char *path, struct stat *buf);
+typedef int (TclAccessProc_)(CONST char *path, int mode);
+typedef Tcl_Channel (TclOpenFileChannelProc_)(Tcl_Interp *interp,
+ CONST char *fileName, CONST char *modeString, int permissions);
/*
*----------------------------------------------------------------
@@ -1813,324 +2365,469 @@ typedef Tcl_ObjCmdProc *TclObjCmdProcType;
/*
*----------------------------------------------------------------
+ * Data structures for process-global values.
+ *----------------------------------------------------------------
+ */
+
+typedef void (TclInitProcessGlobalValueProc)(char **valuePtr, int *lengthPtr,
+ Tcl_Encoding *encodingPtr);
+
+/*
+ * A ProcessGlobalValue struct exists for each internal value in Tcl that is
+ * to be shared among several threads. Each thread sees a (Tcl_Obj) copy of
+ * the value, and the master is kept as a counted string, with epoch and mutex
+ * control. Each ProcessGlobalValue struct should be a static variable in some
+ * file.
+ */
+
+typedef struct ProcessGlobalValue {
+ int epoch; /* Epoch counter to detect changes in the
+ * master value. */
+ int numBytes; /* Length of the master string. */
+ char *value; /* The master string value. */
+ Tcl_Encoding encoding; /* system encoding when master string was
+ * initialized. */
+ TclInitProcessGlobalValueProc *proc;
+ /* A procedure to initialize the master string
+ * copy when a "get" request comes in before
+ * any "set" request has been received. */
+ Tcl_Mutex mutex; /* Enforce orderly access from multiple
+ * threads. */
+ Tcl_ThreadDataKey key; /* Key for per-thread data holding the
+ * (Tcl_Obj) copy for each thread. */
+} ProcessGlobalValue;
+
+/*
+ *----------------------------------------------------------------------
+ * Flags for TclParseNumber
+ *----------------------------------------------------------------------
+ */
+
+#define TCL_PARSE_DECIMAL_ONLY 1
+ /* Leading zero doesn't denote octal or
+ * hex. */
+#define TCL_PARSE_OCTAL_ONLY 2
+ /* Parse octal even without prefix. */
+#define TCL_PARSE_HEXADECIMAL_ONLY 4
+ /* Parse hexadecimal even without prefix. */
+#define TCL_PARSE_INTEGER_ONLY 8
+ /* Disable floating point parsing. */
+#define TCL_PARSE_SCAN_PREFIXES 16
+ /* Use [scan] rules dealing with 0?
+ * prefixes. */
+#define TCL_PARSE_NO_WHITESPACE 32
+ /* Reject leading/trailing whitespace. */
+
+/*
+ *----------------------------------------------------------------------
+ * Type values TclGetNumberFromObj
+ *----------------------------------------------------------------------
+ */
+
+#define TCL_NUMBER_LONG 1
+#define TCL_NUMBER_WIDE 2
+#define TCL_NUMBER_BIG 3
+#define TCL_NUMBER_DOUBLE 4
+#define TCL_NUMBER_NAN 5
+
+/*
+ *----------------------------------------------------------------
* Variables shared among Tcl modules but not used by the outside world.
*----------------------------------------------------------------
*/
-extern Tcl_Time tclBlockTime;
-extern int tclBlockTimeSet;
-extern char * tclExecutableName;
-extern char * tclNativeExecutableName;
-extern char * tclDefaultEncodingDir;
-extern Tcl_ChannelType tclFileChannelType;
-extern char * tclMemDumpFileName;
-extern TclPlatformType tclPlatform;
-extern Tcl_NotifierProcs tclOriginalNotifier;
+MODULE_SCOPE char *tclNativeExecutableName;
+MODULE_SCOPE int tclFindExecutableSearchDone;
+MODULE_SCOPE char *tclMemDumpFileName;
+MODULE_SCOPE TclPlatformType tclPlatform;
+MODULE_SCOPE Tcl_NotifierProcs tclOriginalNotifier;
+
+/*
+ * TIP #233 (Virtualized Time)
+ * Data for the time hooks, if any.
+ */
+
+MODULE_SCOPE Tcl_GetTimeProc *tclGetTimeProcPtr;
+MODULE_SCOPE Tcl_ScaleTimeProc *tclScaleTimeProcPtr;
+MODULE_SCOPE ClientData tclTimeClientData;
/*
* Variables denoting the Tcl object types defined in the core.
*/
-extern Tcl_ObjType tclBooleanType;
-extern Tcl_ObjType tclByteArrayType;
-extern Tcl_ObjType tclByteCodeType;
-extern Tcl_ObjType tclDoubleType;
-extern Tcl_ObjType tclEndOffsetType;
-extern Tcl_ObjType tclIntType;
-extern Tcl_ObjType tclListType;
-extern Tcl_ObjType tclProcBodyType;
-extern Tcl_ObjType tclStringType;
-extern Tcl_ObjType tclArraySearchType;
-extern Tcl_ObjType tclIndexType;
-extern Tcl_ObjType tclNsNameType;
-extern Tcl_ObjType tclWideIntType;
+MODULE_SCOPE Tcl_ObjType tclBignumType;
+MODULE_SCOPE Tcl_ObjType tclBooleanType;
+MODULE_SCOPE Tcl_ObjType tclByteArrayType;
+MODULE_SCOPE Tcl_ObjType tclByteCodeType;
+MODULE_SCOPE Tcl_ObjType tclDoubleType;
+MODULE_SCOPE Tcl_ObjType tclEndOffsetType;
+MODULE_SCOPE Tcl_ObjType tclIntType;
+MODULE_SCOPE Tcl_ObjType tclListType;
+MODULE_SCOPE Tcl_ObjType tclDictType;
+MODULE_SCOPE Tcl_ObjType tclProcBodyType;
+MODULE_SCOPE Tcl_ObjType tclStringType;
+MODULE_SCOPE Tcl_ObjType tclArraySearchType;
+MODULE_SCOPE Tcl_ObjType tclEnsembleCmdType;
+#ifndef NO_WIDE_TYPE
+MODULE_SCOPE Tcl_ObjType tclWideIntType;
+#endif
+MODULE_SCOPE Tcl_ObjType tclRegexpType;
/*
* Variables denoting the hash key types defined in the core.
*/
-extern Tcl_HashKeyType tclArrayHashKeyType;
-extern Tcl_HashKeyType tclOneWordHashKeyType;
-extern Tcl_HashKeyType tclStringHashKeyType;
-extern Tcl_HashKeyType tclObjHashKeyType;
+MODULE_SCOPE Tcl_HashKeyType tclArrayHashKeyType;
+MODULE_SCOPE Tcl_HashKeyType tclOneWordHashKeyType;
+MODULE_SCOPE Tcl_HashKeyType tclStringHashKeyType;
+MODULE_SCOPE Tcl_HashKeyType tclObjHashKeyType;
/*
* The head of the list of free Tcl objects, and the total number of Tcl
* objects ever allocated and freed.
*/
-extern Tcl_Obj * tclFreeObjList;
+MODULE_SCOPE Tcl_Obj * tclFreeObjList;
#ifdef TCL_COMPILE_STATS
-extern long tclObjsAlloced;
-extern long tclObjsFreed;
+MODULE_SCOPE long tclObjsAlloced;
+MODULE_SCOPE long tclObjsFreed;
#define TCL_MAX_SHARED_OBJ_STATS 5
-extern long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS];
+MODULE_SCOPE long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS];
#endif /* TCL_COMPILE_STATS */
/*
- * Pointer to a heap-allocated string of length zero that the Tcl core uses
- * as the value of an empty string representation for an object. This value
- * is shared by all new objects allocated by Tcl_NewObj.
+ * Pointer to a heap-allocated string of length zero that the Tcl core uses as
+ * the value of an empty string representation for an object. This value is
+ * shared by all new objects allocated by Tcl_NewObj.
*/
-extern char * tclEmptyStringRep;
-extern char tclEmptyString;
+MODULE_SCOPE char * tclEmptyStringRep;
+MODULE_SCOPE char tclEmptyString;
+
+/* Flags for conversion of doubles to digit strings */
+
+#define TCL_DD_SHORTEST 0x4
+ /* Use the shortest possible string */
+#define TCL_DD_STEELE 0x5
+ /* Use the original Steele&White algorithm */
+#define TCL_DD_E_FORMAT 0x2
+ /* Use a fixed-length string of digits,
+ * suitable for E format*/
+#define TCL_DD_F_FORMAT 0x3
+ /* Use a fixed number of digits after the
+ * decimal point, suitable for F format */
+
+#define TCL_DD_SHORTEN_FLAG 0x4
+ /* Allow return of a shorter digit string
+ * if it converts losslessly */
+#define TCL_DD_NO_QUICK 0x8
+ /* Debug flag: forbid quick FP conversion */
+
+#define TCL_DD_CONVERSION_TYPE_MASK 0x3
+ /* Mask to isolate the conversion type */
+#define TCL_DD_STEELE0 0x1
+ /* 'Steele&White' after masking */
+#define TCL_DD_SHORTEST0 0x0
+ /* 'Shortest possible' after masking */
/*
*----------------------------------------------------------------
- * Procedures shared among Tcl modules but not used by the outside
- * world:
+ * Procedures shared among Tcl modules but not used by the outside world:
*----------------------------------------------------------------
*/
-#ifdef TCL_TIP280
-EXTERN void TclAdvanceLines _ANSI_ARGS_((int* line, CONST char* start,
- CONST char* end));
-EXTERN void TclAdvanceContinuations _ANSI_ARGS_((int* line, int** next,
- int loc));
-EXTERN ContLineLoc* TclContinuationsEnter _ANSI_ARGS_((Tcl_Obj* objPtr, int num,
- int* loc));
-EXTERN void TclContinuationsEnterDerived _ANSI_ARGS_((Tcl_Obj* objPtr,
- int start, int* clNext));
-EXTERN ContLineLoc* TclContinuationsGet _ANSI_ARGS_((Tcl_Obj* objPtr));
-
-EXTERN void TclContinuationsCopy _ANSI_ARGS_((Tcl_Obj* objPtr, Tcl_Obj* originObjPtr));
-
+MODULE_SCOPE void TclAdvanceContinuations(int* line, int** next, int loc);
+MODULE_SCOPE void TclAdvanceLines(int *line, const char *start,
+ const char *end);
+MODULE_SCOPE void TclArgumentEnter(Tcl_Interp* interp,
+ Tcl_Obj* objv[], int objc, CmdFrame* cf);
+MODULE_SCOPE void TclArgumentRelease(Tcl_Interp* interp,
+ Tcl_Obj* objv[], int objc);
+MODULE_SCOPE void TclArgumentGet(Tcl_Interp* interp, Tcl_Obj* obj,
+ CmdFrame **cfPtrPtr, int *wordPtr);
+MODULE_SCOPE void TclArgumentBCEnter(Tcl_Interp *interp,
+ Tcl_Obj* objv[], int objc,
+ void *codePtr, CmdFrame *cfPtr, int pc);
+MODULE_SCOPE void TclArgumentBCRelease(Tcl_Interp *interp,
+ Tcl_Obj *objv[], int objc,
+ void *codePtr, int pc);
+MODULE_SCOPE int TclArraySet(Tcl_Interp *interp,
+ Tcl_Obj *arrayNameObj, Tcl_Obj *arrayElemObj);
+MODULE_SCOPE double TclBignumToDouble(mp_int *bignum);
+MODULE_SCOPE int TclByteArrayMatch(const unsigned char *string,
+ int strLen, const unsigned char *pattern,
+ int ptnLen, int flags);
+MODULE_SCOPE double TclCeil(mp_int *a);
+MODULE_SCOPE int TclCheckBadOctal(Tcl_Interp *interp, const char *value);
+MODULE_SCOPE int TclChanCaughtErrorBypass(Tcl_Interp *interp,
+ Tcl_Channel chan);
+MODULE_SCOPE ContLineLoc* TclContinuationsEnter(Tcl_Obj *objPtr, int num,
+ int *loc);
+MODULE_SCOPE void TclContinuationsEnterDerived(Tcl_Obj *objPtr,
+ int start, int *clNext);
+MODULE_SCOPE ContLineLoc* TclContinuationsGet(Tcl_Obj *objPtr);
+MODULE_SCOPE void TclContinuationsCopy(Tcl_Obj *objPtr,
+ Tcl_Obj *originObjPtr);
+MODULE_SCOPE int TclConvertElement(CONST char *src, int length,
+ char *dst, int flags);
+MODULE_SCOPE void TclDeleteNamespaceVars(Namespace *nsPtr);
+/* TIP #280 - Modified token based evulation, with line information. */
+MODULE_SCOPE int TclEvalEx(Tcl_Interp *interp, const char *script,
+ int numBytes, int flags, int line,
+ int *clNextOuter, CONST char *outerScript);
+MODULE_SCOPE int TclFileAttrsCmd(Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclFileCopyCmd(Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclFileDeleteCmd(Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclFileMakeDirsCmd(Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclFileRenameCmd(Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE void TclCreateLateExitHandler(Tcl_ExitProc *proc,
+ ClientData clientData);
+MODULE_SCOPE void TclDeleteLateExitHandler(Tcl_ExitProc *proc,
+ ClientData clientData);
+MODULE_SCOPE void TclFinalizeAllocSubsystem(void);
+MODULE_SCOPE void TclFinalizeAsync(void);
+MODULE_SCOPE void TclFinalizeDoubleConversion(void);
+MODULE_SCOPE void TclFinalizeEncodingSubsystem(void);
+MODULE_SCOPE void TclFinalizeEnvironment(void);
+MODULE_SCOPE void TclFinalizeExecution(void);
+MODULE_SCOPE void TclFinalizeIOSubsystem(void);
+MODULE_SCOPE void TclFinalizeFilesystem(void);
+MODULE_SCOPE void TclResetFilesystem(void);
+MODULE_SCOPE void TclFinalizeLoad(void);
+MODULE_SCOPE void TclFinalizeLock(void);
+MODULE_SCOPE void TclFinalizeMemorySubsystem(void);
+MODULE_SCOPE void TclFinalizeNotifier(void);
+MODULE_SCOPE void TclFinalizeObjects(void);
+MODULE_SCOPE void TclFinalizePreserve(void);
+MODULE_SCOPE void TclFinalizeSynchronization(void);
+MODULE_SCOPE void TclFinalizeThreadAlloc(void);
+MODULE_SCOPE void TclFinalizeThreadData(void);
+MODULE_SCOPE void TclFinalizeThreadObjects(void);
+MODULE_SCOPE double TclFloor(mp_int *a);
+MODULE_SCOPE void TclFormatNaN(double value, char *buffer);
+MODULE_SCOPE int TclFSFileAttrIndex(Tcl_Obj *pathPtr,
+ const char *attributeName, int *indexPtr);
+MODULE_SCOPE void TclFSUnloadTempFile(Tcl_LoadHandle loadHandle);
+MODULE_SCOPE int * TclGetAsyncReadyPtr(void);
+MODULE_SCOPE Tcl_Obj * TclGetBgErrorHandler(Tcl_Interp *interp);
+MODULE_SCOPE int TclGetChannelFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, Tcl_Channel *chanPtr,
+ int *modePtr, int flags);
+MODULE_SCOPE int TclGetNumberFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, ClientData *clientDataPtr,
+ int *typePtr);
+MODULE_SCOPE int TclGetOpenModeEx(Tcl_Interp *interp,
+ const char *modeString, int *seekFlagPtr,
+ int *binaryPtr);
+MODULE_SCOPE Tcl_Obj * TclGetProcessGlobalValue(ProcessGlobalValue *pgvPtr);
+MODULE_SCOPE const char *TclGetSrcInfoForCmd(Interp *iPtr, int *lenPtr);
+MODULE_SCOPE int TclGlob(Tcl_Interp *interp, char *pattern,
+ Tcl_Obj *unquotedPrefix, int globFlags,
+ Tcl_GlobTypeData *types);
+MODULE_SCOPE int TclIncrObj(Tcl_Interp *interp, Tcl_Obj *valuePtr,
+ Tcl_Obj *incrPtr);
+MODULE_SCOPE Tcl_Obj * TclIncrObjVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
+ Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr, int flags);
+MODULE_SCOPE int TclInfoExistsCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE Tcl_Obj * TclInfoFrame(Tcl_Interp *interp, CmdFrame *framePtr);
+MODULE_SCOPE int TclInfoGlobalsCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclInfoLocalsCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclInfoVarsCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE void TclInitAlloc(void);
+MODULE_SCOPE void TclInitDbCkalloc(void);
+MODULE_SCOPE void TclInitDoubleConversion(void);
+MODULE_SCOPE void TclInitEmbeddedConfigurationInformation(
+ Tcl_Interp *interp);
+MODULE_SCOPE void TclInitEncodingSubsystem(void);
+MODULE_SCOPE void TclInitIOSubsystem(void);
+MODULE_SCOPE void TclInitLimitSupport(Tcl_Interp *interp);
+MODULE_SCOPE void TclInitNamespaceSubsystem(void);
+MODULE_SCOPE void TclInitNotifier(void);
+MODULE_SCOPE void TclInitObjSubsystem(void);
+MODULE_SCOPE void TclInitSubsystems(void);
+MODULE_SCOPE int TclInterpReady(Tcl_Interp *interp);
+MODULE_SCOPE int TclIsLocalScalar(const char *src, int len);
+MODULE_SCOPE int TclIsSpaceProc(char byte);
+MODULE_SCOPE int TclJoinThread(Tcl_ThreadId id, int *result);
+MODULE_SCOPE void TclLimitRemoveAllHandlers(Tcl_Interp *interp);
+MODULE_SCOPE Tcl_Obj * TclLindexList(Tcl_Interp *interp,
+ Tcl_Obj *listPtr, Tcl_Obj *argPtr);
+MODULE_SCOPE Tcl_Obj * TclLindexFlat(Tcl_Interp *interp, Tcl_Obj *listPtr,
+ int indexCount, Tcl_Obj *const indexArray[]);
+/* TIP #280 */
+MODULE_SCOPE void TclListLines(Tcl_Obj *listObj, int line, int n,
+ int *lines, Tcl_Obj *const *elems);
+MODULE_SCOPE Tcl_Obj * TclListObjCopy(Tcl_Interp *interp, Tcl_Obj *listPtr);
+MODULE_SCOPE int TclLoadFile(Tcl_Interp *interp, Tcl_Obj *pathPtr,
+ int symc, const char *symbols[],
+ Tcl_PackageInitProc **procPtrs[],
+ Tcl_LoadHandle *handlePtr,
+ ClientData *clientDataPtr,
+ Tcl_FSUnloadFileProc **unloadProcPtr);
+MODULE_SCOPE Tcl_Obj * TclLsetList(Tcl_Interp *interp, Tcl_Obj *listPtr,
+ Tcl_Obj *indexPtr, Tcl_Obj *valuePtr);
+MODULE_SCOPE Tcl_Obj * TclLsetFlat(Tcl_Interp *interp, Tcl_Obj *listPtr,
+ int indexCount, Tcl_Obj *const indexArray[],
+ Tcl_Obj *valuePtr);
+MODULE_SCOPE Tcl_Command TclMakeEnsemble(Tcl_Interp *interp, const char *name,
+ const EnsembleImplMap map[]);
+MODULE_SCOPE int TclMaxListLength(CONST char *bytes, int numBytes,
+ CONST char **endPtr);
+MODULE_SCOPE int TclMergeReturnOptions(Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[], Tcl_Obj **optionsPtrPtr,
+ int *codePtr, int *levelPtr);
+MODULE_SCOPE int TclNokia770Doubles();
+MODULE_SCOPE void TclObjVarErrMsg(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
+ Tcl_Obj *part2Ptr, const char *operation,
+ const char *reason, int index);
+MODULE_SCOPE int TclObjInvokeNamespace(Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[],
+ Tcl_Namespace *nsPtr, int flags);
+MODULE_SCOPE int TclObjUnsetVar2(Tcl_Interp *interp,
+ Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags);
+MODULE_SCOPE int TclParseBackslash(const char *src,
+ int numBytes, int *readPtr, char *dst);
+MODULE_SCOPE int TclParseHex(const char *src, int numBytes,
+ Tcl_UniChar *resultPtr);
+MODULE_SCOPE int TclParseNumber(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ const char *expected, const char *bytes,
+ int numBytes, const char **endPtrPtr, int flags);
+MODULE_SCOPE void TclParseInit(Tcl_Interp *interp, const char *string,
+ int numBytes, Tcl_Parse *parsePtr);
+MODULE_SCOPE int TclParseAllWhiteSpace(const char *src, int numBytes);
+MODULE_SCOPE int TclProcessReturn(Tcl_Interp *interp,
+ int code, int level, Tcl_Obj *returnOpts);
+#ifndef TCL_NO_STACK_CHECK
+MODULE_SCOPE int TclpGetCStackParams(int **stackBoundPtr);
#endif
-EXTERN int TclArraySet _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *arrayNameObj, Tcl_Obj *arrayElemObj));
-EXTERN int TclCheckBadOctal _ANSI_ARGS_((Tcl_Interp *interp,
- CONST char *value));
-EXTERN void TclDeleteNamespaceVars _ANSI_ARGS_((Namespace *nsPtr));
-
-#ifdef TCL_TIP280
-EXTERN int TclEvalObjEx _ANSI_ARGS_((Tcl_Interp *interp,
- register Tcl_Obj *objPtr,
- int flags,
- CONST CmdFrame* invoker,
- int word));
-
-EXTERN void TclArgumentEnter _ANSI_ARGS_((Tcl_Interp* interp,
- Tcl_Obj* objv[], int objc, CmdFrame* cf));
-EXTERN void TclArgumentRelease _ANSI_ARGS_((Tcl_Interp* interp,
- Tcl_Obj* objv[], int objc));
-EXTERN void TclArgumentBCEnter _ANSI_ARGS_((Tcl_Interp* interp,
- Tcl_Obj* objv[], int objc,
- void* codePtr, CmdFrame* cfPtr, int pc));
-EXTERN void TclArgumentBCRelease _ANSI_ARGS_((Tcl_Interp* interp,
- Tcl_Obj* objv[], int objc,
- void* codePtr, int pc));
-
-EXTERN void TclArgumentGet _ANSI_ARGS_((Tcl_Interp* interp, Tcl_Obj* obj,
- CmdFrame** cfPtrPtr, int* wordPtr));
+MODULE_SCOPE int TclpObjLstat(Tcl_Obj *pathPtr, Tcl_StatBuf *buf);
+MODULE_SCOPE Tcl_Obj * TclpTempFileName(void);
+MODULE_SCOPE Tcl_Obj * TclNewFSPathObj(Tcl_Obj *dirPtr, const char *addStrRep,
+ int len);
+MODULE_SCOPE int TclpDeleteFile(const char *path);
+MODULE_SCOPE void TclpFinalizeCondition(Tcl_Condition *condPtr);
+MODULE_SCOPE void TclpFinalizeMutex(Tcl_Mutex *mutexPtr);
+MODULE_SCOPE void TclpFinalizePipes(void);
+MODULE_SCOPE void TclpFinalizeSockets(void);
+MODULE_SCOPE int TclpThreadCreate(Tcl_ThreadId *idPtr,
+ Tcl_ThreadCreateProc proc, ClientData clientData,
+ int stackSize, int flags);
+MODULE_SCOPE int TclpFindVariable(const char *name, int *lengthPtr);
+MODULE_SCOPE void TclpInitLibraryPath(char **valuePtr,
+ int *lengthPtr, Tcl_Encoding *encodingPtr);
+MODULE_SCOPE void TclpInitLock(void);
+MODULE_SCOPE void TclpInitPlatform(void);
+MODULE_SCOPE void TclpInitUnlock(void);
+MODULE_SCOPE int TclpLoadFile(Tcl_Interp *interp, Tcl_Obj *pathPtr,
+ const char *sym1, const char *sym2,
+ Tcl_PackageInitProc **proc1Ptr,
+ Tcl_PackageInitProc **proc2Ptr,
+ ClientData *clientDataPtr,
+ Tcl_FSUnloadFileProc **unloadProcPtr);
+MODULE_SCOPE Tcl_Obj * TclpObjListVolumes(void);
+MODULE_SCOPE void TclpMasterLock(void);
+MODULE_SCOPE void TclpMasterUnlock(void);
+MODULE_SCOPE int TclpMatchFiles(Tcl_Interp *interp, char *separators,
+ Tcl_DString *dirPtr, char *pattern, char *tail);
+MODULE_SCOPE int TclpObjNormalizePath(Tcl_Interp *interp,
+ Tcl_Obj *pathPtr, int nextCheckpoint);
+MODULE_SCOPE void TclpNativeJoinPath(Tcl_Obj *prefix, char *joining);
+MODULE_SCOPE Tcl_Obj * TclpNativeSplitPath(Tcl_Obj *pathPtr, int *lenPtr);
+MODULE_SCOPE Tcl_PathType TclpGetNativePathType(Tcl_Obj *pathPtr,
+ int *driveNameLengthPtr, Tcl_Obj **driveNameRef);
+MODULE_SCOPE int TclCrossFilesystemCopy(Tcl_Interp *interp,
+ Tcl_Obj *source, Tcl_Obj *target);
+MODULE_SCOPE int TclpMatchInDirectory(Tcl_Interp *interp,
+ Tcl_Obj *resultPtr, Tcl_Obj *pathPtr,
+ const char *pattern, Tcl_GlobTypeData *types);
+MODULE_SCOPE ClientData TclpGetNativeCwd(ClientData clientData);
+MODULE_SCOPE Tcl_FSDupInternalRepProc TclNativeDupInternalRep;
+MODULE_SCOPE Tcl_Obj * TclpObjLink(Tcl_Obj *pathPtr, Tcl_Obj *toPtr,
+ int linkType);
+MODULE_SCOPE int TclpObjChdir(Tcl_Obj *pathPtr);
+MODULE_SCOPE Tcl_Obj * TclPathPart(Tcl_Interp *interp, Tcl_Obj *pathPtr,
+ Tcl_PathPart portion);
+#ifndef TclpPanic
+MODULE_SCOPE void TclpPanic(const char *format, ...);
#endif
-
-EXTERN void TclExpandTokenArray _ANSI_ARGS_((
- Tcl_Parse *parsePtr));
-EXTERN int TclFileAttrsCmd _ANSI_ARGS_((Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-EXTERN int TclFileCopyCmd _ANSI_ARGS_((Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[])) ;
-EXTERN int TclFileDeleteCmd _ANSI_ARGS_((Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-EXTERN int TclFileMakeDirsCmd _ANSI_ARGS_((Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[])) ;
-EXTERN int TclFileRenameCmd _ANSI_ARGS_((Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[])) ;
-EXTERN void TclCreateLateExitHandler (Tcl_ExitProc * proc,
- ClientData clientData);
-EXTERN void TclDeleteLateExitHandler (Tcl_ExitProc * proc,
- ClientData clientData);
-EXTERN void TclFinalizeAllocSubsystem _ANSI_ARGS_((void));
-EXTERN void TclFinalizeAsync _ANSI_ARGS_((void));
-EXTERN void TclFinalizeCompilation _ANSI_ARGS_((void));
-EXTERN void TclFinalizeEncodingSubsystem _ANSI_ARGS_((void));
-EXTERN void TclFinalizeEnvironment _ANSI_ARGS_((void));
-EXTERN void TclFinalizeExecution _ANSI_ARGS_((void));
-EXTERN void TclFinalizeIOSubsystem _ANSI_ARGS_((void));
-EXTERN void TclFinalizeFilesystem _ANSI_ARGS_((void));
-EXTERN void TclResetFilesystem _ANSI_ARGS_((void));
-EXTERN void TclFinalizeLoad _ANSI_ARGS_((void));
-EXTERN void TclFinalizeLock _ANSI_ARGS_((void));
-EXTERN void TclFinalizeMemorySubsystem _ANSI_ARGS_((void));
-EXTERN void TclFinalizeNotifier _ANSI_ARGS_((void));
-EXTERN void TclFinalizeObjects _ANSI_ARGS_((void));
-EXTERN void TclFinalizePreserve _ANSI_ARGS_((void));
-EXTERN void TclFinalizeSynchronization _ANSI_ARGS_((void));
-EXTERN void TclFinalizeThreadAlloc _ANSI_ARGS_((void));
-EXTERN void TclFinalizeThreadData _ANSI_ARGS_((void));
-EXTERN int TclGetEncodingFromObj _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr, Tcl_Encoding *encodingPtr));
-#ifdef TCL_TIP280
-EXTERN void TclGetSrcInfoForPc _ANSI_ARGS_((CmdFrame* cfPtr));
-#endif
-EXTERN int TclGlob _ANSI_ARGS_((Tcl_Interp *interp,
- char *pattern, Tcl_Obj *unquotedPrefix,
- int globFlags, Tcl_GlobTypeData* types));
-EXTERN void TclInitAlloc _ANSI_ARGS_((void));
-EXTERN void TclInitDbCkalloc _ANSI_ARGS_((void));
-EXTERN void TclInitEncodingSubsystem _ANSI_ARGS_((void));
-EXTERN void TclInitIOSubsystem _ANSI_ARGS_((void));
-EXTERN void TclInitNamespaceSubsystem _ANSI_ARGS_((void));
-EXTERN void TclInitNotifier _ANSI_ARGS_((void));
-EXTERN void TclInitObjSubsystem _ANSI_ARGS_((void));
-EXTERN void TclInitSubsystems _ANSI_ARGS_((CONST char *argv0));
-EXTERN int TclIsLocalScalar _ANSI_ARGS_((CONST char *src,
- int len));
-EXTERN int TclJoinThread _ANSI_ARGS_((Tcl_ThreadId id,
- int* result));
-EXTERN Tcl_Obj * TclLindexList _ANSI_ARGS_((Tcl_Interp* interp,
- Tcl_Obj* listPtr,
- Tcl_Obj* argPtr ));
-EXTERN Tcl_Obj * TclLindexFlat _ANSI_ARGS_((Tcl_Interp* interp,
- Tcl_Obj* listPtr,
- int indexCount,
- Tcl_Obj *CONST indexArray[]
- ));
-EXTERN Tcl_Obj * TclLsetList _ANSI_ARGS_((Tcl_Interp* interp,
- Tcl_Obj* listPtr,
- Tcl_Obj* indexPtr,
- Tcl_Obj* valuePtr
- ));
-EXTERN Tcl_Obj * TclLsetFlat _ANSI_ARGS_((Tcl_Interp* interp,
- Tcl_Obj* listPtr,
- int indexCount,
- Tcl_Obj *CONST indexArray[],
- Tcl_Obj* valuePtr
- ));
-EXTERN int TclParseBackslash _ANSI_ARGS_((CONST char *src,
- int numBytes, int *readPtr, char *dst));
-EXTERN int TclParseHex _ANSI_ARGS_((CONST char *src, int numBytes,
- Tcl_UniChar *resultPtr));
-EXTERN int TclParseInteger _ANSI_ARGS_((CONST char *string,
- int numBytes));
-EXTERN int TclParseWhiteSpace _ANSI_ARGS_((CONST char *src,
- int numBytes, Tcl_Parse *parsePtr, char *typePtr));
-#ifdef TCL_TIP280
-EXTERN int TclWordKnownAtCompileTime _ANSI_ARGS_((Tcl_Token* token));
+MODULE_SCOPE char * TclpReadlink(const char *fileName,
+ Tcl_DString *linkPtr);
+#ifndef TclpReleaseFile
+MODULE_SCOPE void TclpReleaseFile(TclFile file);
#endif
-EXTERN int TclpObjAccess _ANSI_ARGS_((Tcl_Obj *filename,
- int mode));
-EXTERN int TclpObjLstat _ANSI_ARGS_((Tcl_Obj *pathPtr,
- Tcl_StatBuf *buf));
-EXTERN int TclpCheckStackSpace _ANSI_ARGS_((void));
-EXTERN Tcl_Obj* TclpTempFileName _ANSI_ARGS_((void));
-EXTERN Tcl_Obj* TclNewFSPathObj _ANSI_ARGS_((Tcl_Obj *dirPtr,
- CONST char *addStrRep, int len));
-EXTERN int TclpDeleteFile _ANSI_ARGS_((CONST char *path));
-EXTERN void TclpFinalizeCondition _ANSI_ARGS_((
- Tcl_Condition *condPtr));
-EXTERN void TclpFinalizeMutex _ANSI_ARGS_((Tcl_Mutex *mutexPtr));
-EXTERN void TclpFinalizePipes _ANSI_ARGS_((void));
-EXTERN void TclpFinalizeSockets _ANSI_ARGS_((void));
-EXTERN void TclpFinalizeThreadData _ANSI_ARGS_((
- Tcl_ThreadDataKey *keyPtr));
-EXTERN void TclpFinalizeThreadDataKey _ANSI_ARGS_((
- Tcl_ThreadDataKey *keyPtr));
-EXTERN char * TclpFindExecutable _ANSI_ARGS_((
- CONST char *argv0));
-EXTERN int TclpFindVariable _ANSI_ARGS_((CONST char *name,
- int *lengthPtr));
-EXTERN int TclpInitLibraryPath _ANSI_ARGS_((CONST char *argv0));
-EXTERN void TclpInitLock _ANSI_ARGS_((void));
-EXTERN void TclpInitPlatform _ANSI_ARGS_((void));
-EXTERN void TclpInitUnlock _ANSI_ARGS_((void));
-EXTERN int TclpLoadFile _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *pathPtr,
- CONST char *sym1, CONST char *sym2,
- Tcl_PackageInitProc **proc1Ptr,
- Tcl_PackageInitProc **proc2Ptr,
- ClientData *clientDataPtr,
- Tcl_FSUnloadFileProc **unloadProcPtr));
-EXTERN Tcl_Obj* TclpObjListVolumes _ANSI_ARGS_((void));
-EXTERN void TclpMasterLock _ANSI_ARGS_((void));
-EXTERN void TclpMasterUnlock _ANSI_ARGS_((void));
-EXTERN int TclpMatchFiles _ANSI_ARGS_((Tcl_Interp *interp,
- char *separators, Tcl_DString *dirPtr,
- char *pattern, char *tail));
-EXTERN int TclpObjNormalizePath _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *pathPtr, int nextCheckpoint));
-EXTERN int TclpObjCreateDirectory _ANSI_ARGS_((Tcl_Obj *pathPtr));
-EXTERN void TclpNativeJoinPath _ANSI_ARGS_((Tcl_Obj *prefix,
- char *joining));
-EXTERN Tcl_Obj* TclpNativeSplitPath _ANSI_ARGS_((Tcl_Obj *pathPtr,
- int *lenPtr));
-EXTERN Tcl_PathType TclpGetNativePathType _ANSI_ARGS_((Tcl_Obj *pathObjPtr,
- int *driveNameLengthPtr, Tcl_Obj **driveNameRef));
-EXTERN int TclCrossFilesystemCopy _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *source, Tcl_Obj *target));
-EXTERN int TclpObjDeleteFile _ANSI_ARGS_((Tcl_Obj *pathPtr));
-EXTERN int TclpObjCopyDirectory _ANSI_ARGS_((Tcl_Obj *srcPathPtr,
- Tcl_Obj *destPathPtr, Tcl_Obj **errorPtr));
-EXTERN int TclpObjCopyFile _ANSI_ARGS_((Tcl_Obj *srcPathPtr,
- Tcl_Obj *destPathPtr));
-EXTERN int TclpObjRemoveDirectory _ANSI_ARGS_((Tcl_Obj *pathPtr,
- int recursive, Tcl_Obj **errorPtr));
-EXTERN int TclpObjRenameFile _ANSI_ARGS_((Tcl_Obj *srcPathPtr,
- Tcl_Obj *destPathPtr));
-EXTERN int TclpMatchInDirectory _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *resultPtr, Tcl_Obj *pathPtr,
- CONST char *pattern, Tcl_GlobTypeData *types));
-EXTERN Tcl_Obj* TclpObjGetCwd _ANSI_ARGS_((Tcl_Interp *interp));
-EXTERN Tcl_FSDupInternalRepProc TclNativeDupInternalRep;
-EXTERN Tcl_Obj* TclpObjLink _ANSI_ARGS_((Tcl_Obj *pathPtr,
- Tcl_Obj *toPtr, int linkType));
-EXTERN int TclpObjChdir _ANSI_ARGS_((Tcl_Obj *pathPtr));
-EXTERN Tcl_Obj* TclFileDirname _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj*pathPtr));
-EXTERN int TclpObjStat _ANSI_ARGS_((Tcl_Obj *pathPtr, Tcl_StatBuf *buf));
-EXTERN Tcl_Channel TclpOpenFileChannel _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *pathPtr, int mode,
- int permissions));
-EXTERN void TclpPanic _ANSI_ARGS_(TCL_VARARGS(CONST char *,
- format));
-EXTERN char * TclpReadlink _ANSI_ARGS_((CONST char *fileName,
- Tcl_DString *linkPtr));
-EXTERN void TclpReleaseFile _ANSI_ARGS_((TclFile file));
-EXTERN void TclpSetVariables _ANSI_ARGS_((Tcl_Interp *interp));
-EXTERN void TclpUnloadFile _ANSI_ARGS_((Tcl_LoadHandle loadHandle));
-EXTERN VOID * TclpThreadDataKeyGet _ANSI_ARGS_((
- Tcl_ThreadDataKey *keyPtr));
-EXTERN void TclpThreadDataKeyInit _ANSI_ARGS_((
- Tcl_ThreadDataKey *keyPtr));
-EXTERN void TclpThreadDataKeySet _ANSI_ARGS_((
- Tcl_ThreadDataKey *keyPtr, VOID *data));
-EXTERN int TclpThreadCreate _ANSI_ARGS_((
- Tcl_ThreadId *idPtr,
- Tcl_ThreadCreateProc proc,
- ClientData clientData,
- int stackSize, int flags));
-EXTERN void TclpThreadExit _ANSI_ARGS_((int status));
-EXTERN void TclRememberCondition _ANSI_ARGS_((Tcl_Condition *mutex));
-EXTERN void TclRememberDataKey _ANSI_ARGS_((Tcl_ThreadDataKey *mutex));
-EXTERN VOID TclRememberJoinableThread _ANSI_ARGS_((Tcl_ThreadId id));
-EXTERN void TclRememberMutex _ANSI_ARGS_((Tcl_Mutex *mutex));
-EXTERN VOID TclSignalExitThread _ANSI_ARGS_((Tcl_ThreadId id,
- int result));
-EXTERN void TclTransferResult _ANSI_ARGS_((Tcl_Interp *sourceInterp,
- int result, Tcl_Interp *targetInterp));
-EXTERN Tcl_Obj* TclpNativeToNormalized
- _ANSI_ARGS_((ClientData clientData));
-EXTERN Tcl_Obj* TclpFilesystemPathType
- _ANSI_ARGS_((Tcl_Obj* pathObjPtr));
-EXTERN Tcl_PackageInitProc* TclpFindSymbol _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_LoadHandle loadHandle, CONST char *symbol));
-EXTERN int TclpDlopen _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *pathPtr,
- Tcl_LoadHandle *loadHandle,
- Tcl_FSUnloadFileProc **unloadProcPtr));
-EXTERN int TclpUtime _ANSI_ARGS_((Tcl_Obj *pathPtr,
- struct utimbuf *tval));
-
+MODULE_SCOPE void TclpSetInterfaces(void);
+MODULE_SCOPE void TclpSetVariables(Tcl_Interp *interp);
+MODULE_SCOPE void TclpUnloadFile(Tcl_LoadHandle loadHandle);
+MODULE_SCOPE void * TclpThreadDataKeyGet(Tcl_ThreadDataKey *keyPtr);
+MODULE_SCOPE void TclpThreadDataKeySet(Tcl_ThreadDataKey *keyPtr,
+ void *data);
+MODULE_SCOPE void TclpThreadExit(int status);
+MODULE_SCOPE size_t TclpThreadGetStackSize(void);
+MODULE_SCOPE void TclRememberCondition(Tcl_Condition *mutex);
+MODULE_SCOPE void TclRememberJoinableThread(Tcl_ThreadId id);
+MODULE_SCOPE void TclRememberMutex(Tcl_Mutex *mutex);
+MODULE_SCOPE void TclRemoveScriptLimitCallbacks(Tcl_Interp *interp);
+MODULE_SCOPE int TclReToGlob(Tcl_Interp *interp, const char *reStr,
+ int reStrLen, Tcl_DString *dsPtr, int *flagsPtr);
+MODULE_SCOPE int TclScanElement(CONST char *string, int length,
+ int *flagPtr);
+MODULE_SCOPE void TclSetBgErrorHandler(Tcl_Interp *interp,
+ Tcl_Obj *cmdPrefix);
+MODULE_SCOPE void TclSetBignumIntRep(Tcl_Obj *objPtr,
+ mp_int *bignumValue);
+MODULE_SCOPE void TclSetCmdNameObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ Command *cmdPtr);
+MODULE_SCOPE void TclSetProcessGlobalValue(ProcessGlobalValue *pgvPtr,
+ Tcl_Obj *newValue, Tcl_Encoding encoding);
+MODULE_SCOPE void TclSignalExitThread(Tcl_ThreadId id, int result);
+MODULE_SCOPE void * TclStackRealloc(Tcl_Interp *interp, void *ptr,
+ int numBytes);
+MODULE_SCOPE int TclStringMatch(const char *str, int strLen,
+ const char *pattern, int ptnLen, int flags);
+MODULE_SCOPE int TclStringMatchObj(Tcl_Obj *stringObj,
+ Tcl_Obj *patternObj, int flags);
+MODULE_SCOPE Tcl_Obj * TclStringObjReverse(Tcl_Obj *objPtr);
+MODULE_SCOPE int TclSubstTokens(Tcl_Interp *interp, Tcl_Token *tokenPtr,
+ int count, int *tokensLeftPtr, int line,
+ int *clNextOuter, CONST char *outerScript);
+MODULE_SCOPE void TclTransferResult(Tcl_Interp *sourceInterp, int result,
+ Tcl_Interp *targetInterp);
+MODULE_SCOPE int TclTrimLeft(const char *bytes, int numBytes,
+ const char *trim, int numTrim);
+MODULE_SCOPE int TclTrimRight(const char *bytes, int numBytes,
+ const char *trim, int numTrim);
+MODULE_SCOPE Tcl_Obj * TclpNativeToNormalized(ClientData clientData);
+MODULE_SCOPE Tcl_Obj * TclpFilesystemPathType(Tcl_Obj *pathPtr);
+MODULE_SCOPE Tcl_PackageInitProc *TclpFindSymbol(Tcl_Interp *interp,
+ Tcl_LoadHandle loadHandle, const char *symbol);
+MODULE_SCOPE int TclpDlopen(Tcl_Interp *interp, Tcl_Obj *pathPtr,
+ Tcl_LoadHandle *loadHandle,
+ Tcl_FSUnloadFileProc **unloadProcPtr);
+MODULE_SCOPE int TclpUtime(Tcl_Obj *pathPtr, struct utimbuf *tval);
#ifdef TCL_LOAD_FROM_MEMORY
-EXTERN void* TclpLoadMemoryGetBuffer _ANSI_ARGS_((
- Tcl_Interp *interp, int size));
-EXTERN int TclpLoadMemory _ANSI_ARGS_((Tcl_Interp *interp,
- void *buffer, int size, int codeSize,
- Tcl_LoadHandle *loadHandle,
- Tcl_FSUnloadFileProc **unloadProcPtr));
+MODULE_SCOPE void * TclpLoadMemoryGetBuffer(Tcl_Interp *interp, int size);
+MODULE_SCOPE int TclpLoadMemory(Tcl_Interp *interp, void *buffer,
+ int size, int codeSize, Tcl_LoadHandle *loadHandle,
+ Tcl_FSUnloadFileProc **unloadProcPtr);
+#endif
+MODULE_SCOPE void TclInitThreadStorage(void);
+MODULE_SCOPE void TclpFinalizeThreadDataThread(void);
+MODULE_SCOPE void TclFinalizeThreadStorage(void);
+#ifdef TCL_WIDE_CLICKS
+MODULE_SCOPE Tcl_WideInt TclpGetWideClicks(void);
+MODULE_SCOPE double TclpWideClicksToNanoseconds(Tcl_WideInt clicks);
#endif
+MODULE_SCOPE Tcl_Obj * TclDisassembleByteCodeObj(Tcl_Obj *objPtr);
/*
*----------------------------------------------------------------
@@ -2138,179 +2835,266 @@ EXTERN int TclpLoadMemory _ANSI_ARGS_((Tcl_Interp *interp,
*----------------------------------------------------------------
*/
-EXTERN int Tcl_AfterObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_AppendObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_ArrayObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_BinaryObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_BreakObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_CaseObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_CatchObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_CdObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_ClockObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_CloseObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_ConcatObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_ContinueObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_EncodingObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_EofObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_ErrorObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_EvalObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_ExecObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_ExitObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_ExprObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_FblockedObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_FconfigureObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_FcopyObjCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_FileObjCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_FileEventObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_FlushObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_ForObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_ForeachObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_FormatObjCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_GetsObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_GlobalObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_GlobObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_IfObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_IncrObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_InfoObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_InterpObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_JoinObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_LappendObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_LindexObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_LinsertObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_LlengthObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_ListObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_LoadObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_LrangeObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_LreplaceObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_LsearchObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_LsetObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp* interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_LsortObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_NamespaceObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_OpenObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_PackageObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_PidObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_PutsObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_PwdObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_ReadObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_RegexpObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_RegsubObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_RenameObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_ReturnObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_ScanObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_SeekObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_SetObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_SplitObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_SocketObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_SourceObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_StringObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_SubstObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_SwitchObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_TellObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_TimeObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_TraceObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_UnsetObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_UpdateObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_UplevelObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_UpvarObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_VariableObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_VwaitObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_WhileObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-
-/*
- *----------------------------------------------------------------
- * Command procedures found only in the Mac version of the core:
- *----------------------------------------------------------------
- */
-
-#ifdef MAC_TCL
-EXTERN int Tcl_EchoCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, CONST84 char **argv));
-EXTERN int Tcl_LsObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_BeepObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_MacSourceObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int Tcl_ResourceObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-#endif
+MODULE_SCOPE int Tcl_AfterObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_AppendObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_ApplyObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_ArrayObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_BinaryObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_BreakObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_CaseObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_CatchObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_CdObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE Tcl_Command TclInitChanCmd(Tcl_Interp *interp);
+MODULE_SCOPE int TclChanCreateObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclChanPostEventObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE void TclClockInit(Tcl_Interp *interp);
+MODULE_SCOPE int TclClockOldscanObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_CloseObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_ConcatObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_ContinueObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE Tcl_TimerToken TclCreateAbsoluteTimerHandler(
+ Tcl_Time *timePtr, Tcl_TimerProc *proc,
+ ClientData clientData);
+MODULE_SCOPE int TclDefaultBgErrorHandlerObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE Tcl_Command TclInitDictCmd(Tcl_Interp *interp);
+MODULE_SCOPE int Tcl_DisassembleObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_EncodingObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_EofObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_ErrorObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_EvalObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_ExecObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_ExitObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_ExprObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_FblockedObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_FconfigureObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_FcopyObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_FileObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_FileEventObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_FlushObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_ForObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_ForeachObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_FormatObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_GetsObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_GlobalObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_GlobObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_IfObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_IncrObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE Tcl_Command TclInitInfoCmd(Tcl_Interp *interp);
+MODULE_SCOPE int Tcl_InterpObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int argc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_JoinObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_LappendObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_LassignObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_LindexObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_LinsertObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_LlengthObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_ListObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_LoadObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_LrangeObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_LrepeatObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_LreplaceObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_LreverseObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_LsearchObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_LsetObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_LsortObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_NamespaceObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_OpenObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_PackageObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_PidObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_PutsObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_PwdObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_ReadObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_RegexpObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_RegsubObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_RenameObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_ReturnObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_ScanObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_SeekObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_SetObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_SplitObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_SocketObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_SourceObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE Tcl_Command TclInitStringCmd(Tcl_Interp *interp);
+MODULE_SCOPE int Tcl_SubstObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_SwitchObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_TellObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_TimeObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_TraceObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_UnloadObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_UnsetObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_UpdateObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_UplevelObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_UpvarObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_VariableObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_VwaitObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int Tcl_WhileObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
/*
*----------------------------------------------------------------
@@ -2318,88 +3102,327 @@ EXTERN int Tcl_ResourceObjCmd _ANSI_ARGS_((ClientData clientData,
*----------------------------------------------------------------
*/
-EXTERN int TclCompileAppendCmd _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
-EXTERN int TclCompileBreakCmd _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
-EXTERN int TclCompileCatchCmd _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
-EXTERN int TclCompileContinueCmd _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
-EXTERN int TclCompileExprCmd _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
-EXTERN int TclCompileForCmd _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
-EXTERN int TclCompileForeachCmd _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
-EXTERN int TclCompileIfCmd _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
-EXTERN int TclCompileIncrCmd _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
-EXTERN int TclCompileLappendCmd _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
-EXTERN int TclCompileLindexCmd _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
-EXTERN int TclCompileListCmd _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
-EXTERN int TclCompileLlengthCmd _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
-EXTERN int TclCompileLsetCmd _ANSI_ARGS_((Tcl_Interp* interp,
- Tcl_Parse* parsePtr, struct CompileEnv* envPtr));
-EXTERN int TclCompileRegexpCmd _ANSI_ARGS_((Tcl_Interp* interp,
- Tcl_Parse* parsePtr, struct CompileEnv* envPtr));
-EXTERN int TclCompileReturnCmd _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
-EXTERN int TclCompileSetCmd _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
-EXTERN int TclCompileStringCmd _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
-EXTERN int TclCompileWhileCmd _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
-
-/*
- * Functions defined in generic/tclVar.c and currenttly exported only
- * for use by the bytecode compiler and engine. Some of these could later
- * be placed in the public interface.
- */
-
-EXTERN Var * TclLookupArrayElement _ANSI_ARGS_((Tcl_Interp *interp,
- CONST char *arrayName, CONST char *elName, CONST int flags,
- CONST char *msg, CONST int createPart1,
- CONST int createPart2, Var *arrayPtr));
-EXTERN Var * TclObjLookupVar _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *part1Ptr, CONST char *part2, int flags,
- CONST char *msg, CONST int createPart1,
- CONST int createPart2, Var **arrayPtrPtr));
-EXTERN Tcl_Obj *TclPtrGetVar _ANSI_ARGS_((Tcl_Interp *interp, Var *varPtr,
- Var *arrayPtr, CONST char *part1, CONST char *part2,
- CONST int flags));
-EXTERN Tcl_Obj *TclPtrSetVar _ANSI_ARGS_((Tcl_Interp *interp, Var *varPtr,
- Var *arrayPtr, CONST char *part1, CONST char *part2,
- Tcl_Obj *newValuePtr, CONST int flags));
-EXTERN Tcl_Obj *TclPtrIncrVar _ANSI_ARGS_((Tcl_Interp *interp, Var *varPtr,
- Var *arrayPtr, CONST char *part1, CONST char *part2,
- CONST long i, CONST int flags));
+MODULE_SCOPE int TclCompileAppendCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileBreakCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileCatchCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileContinueCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileDictAppendCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileDictForCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileDictGetCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileDictIncrCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileDictLappendCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileDictSetCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileDictUpdateCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileEnsemble(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileExprCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileForCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileForeachCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileGlobalCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileIfCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileInfoExistsCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileIncrCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileLappendCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileLassignCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileLindexCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileListCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileLlengthCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileLsetCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileNamespaceCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileNoOp(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileRegexpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileReturnCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileSetCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileStringCmpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileStringEqualCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileStringIndexCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileStringLenCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileStringMatchCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileSwitchCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileUpvarCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileVariableCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclCompileWhileCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+
+MODULE_SCOPE int TclInvertOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileInvertOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclNotOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileNotOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclAddOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileAddOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclMulOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileMulOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclAndOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileAndOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclOrOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileOrOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclXorOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileXorOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclPowOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompilePowOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclLshiftOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileLshiftOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclRshiftOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileRshiftOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclModOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileModOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclNeqOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileNeqOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclStrneqOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileStrneqOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclInOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileInOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclNiOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileNiOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclMinusOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileMinusOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclDivOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileDivOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclLessOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileLessOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclLeqOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileLeqOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclGreaterOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileGreaterOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclGeqOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileGeqOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclEqOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileEqOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+MODULE_SCOPE int TclStreqOpCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+MODULE_SCOPE int TclCompileStreqOpCmd(Tcl_Interp *interp,
+ Tcl_Parse *parsePtr, Command *cmdPtr,
+ struct CompileEnv *envPtr);
+
+/*
+ * Functions defined in generic/tclVar.c and currenttly exported only for use
+ * by the bytecode compiler and engine. Some of these could later be placed in
+ * the public interface.
+ */
+
+MODULE_SCOPE Var * TclObjLookupVarEx(Tcl_Interp * interp,
+ Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags,
+ const char *msg, const int createPart1,
+ const int createPart2, Var **arrayPtrPtr);
+MODULE_SCOPE Var * TclLookupArrayElement(Tcl_Interp *interp,
+ Tcl_Obj *arrayNamePtr, Tcl_Obj *elNamePtr,
+ const int flags, const char *msg,
+ const int createPart1, const int createPart2,
+ Var *arrayPtr, int index);
+MODULE_SCOPE Tcl_Obj * TclPtrGetVar(Tcl_Interp *interp,
+ Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr,
+ Tcl_Obj *part2Ptr, const int flags, int index);
+MODULE_SCOPE Tcl_Obj * TclPtrSetVar(Tcl_Interp *interp,
+ Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr,
+ Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr,
+ const int flags, int index);
+MODULE_SCOPE Tcl_Obj * TclPtrIncrObjVar(Tcl_Interp *interp,
+ Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr,
+ Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr,
+ const int flags, int index);
+MODULE_SCOPE int TclPtrObjMakeUpvar(Tcl_Interp *interp, Var *otherPtr,
+ Tcl_Obj *myNamePtr, int myFlags, int index);
+MODULE_SCOPE void TclInvalidateNsPath(Namespace *nsPtr);
+
+/*
+ * The new extended interface to the variable traces.
+ */
+
+MODULE_SCOPE int TclObjCallVarTraces(Interp *iPtr, Var *arrayPtr,
+ Var *varPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr,
+ int flags, int leaveErrMsg, int index);
+
+/*
+ * So tclObj.c and tclDictObj.c can share these implementations.
+ */
+
+MODULE_SCOPE int TclCompareObjKeys(void *keyPtr, Tcl_HashEntry *hPtr);
+MODULE_SCOPE void TclFreeObjEntry(Tcl_HashEntry *hPtr);
+MODULE_SCOPE unsigned TclHashObjKey(Tcl_HashTable *tablePtr, void *keyPtr);
/*
*----------------------------------------------------------------
* Macros used by the Tcl core to create and release Tcl objects.
* TclNewObj(objPtr) creates a new object denoting an empty string.
- * TclDecrRefCount(objPtr) decrements the object's reference count,
- * and frees the object if its reference count is zero.
- * These macros are inline versions of Tcl_NewObj() and
- * Tcl_DecrRefCount(). Notice that the names differ in not having
- * a "_" after the "Tcl". Notice also that these macros reference
- * their argument more than once, so you should avoid calling them
- * with an expression that is expensive to compute or has
- * side effects. The ANSI C "prototypes" for these macros are:
+ * TclDecrRefCount(objPtr) decrements the object's reference count, and frees
+ * the object if its reference count is zero. These macros are inline versions
+ * of Tcl_NewObj() and Tcl_DecrRefCount(). Notice that the names differ in not
+ * having a "_" after the "Tcl". Notice also that these macros reference their
+ * argument more than once, so you should avoid calling them with an
+ * expression that is expensive to compute or has side effects. The ANSI C
+ * "prototypes" for these macros are:
*
- * EXTERN void TclNewObj _ANSI_ARGS_((Tcl_Obj *objPtr));
- * EXTERN void TclDecrRefCount _ANSI_ARGS_((Tcl_Obj *objPtr));
+ * MODULE_SCOPE void TclNewObj(Tcl_Obj *objPtr);
+ * MODULE_SCOPE void TclDecrRefCount(Tcl_Obj *objPtr);
*
- * These macros are defined in terms of two macros that depend on
- * memory allocator in use: TclAllocObjStorage, TclFreeObjStorage.
- * They are defined below.
+ * These macros are defined in terms of two macros that depend on memory
+ * allocator in use: TclAllocObjStorage, TclFreeObjStorage. They are defined
+ * below.
*----------------------------------------------------------------
*/
@@ -2426,94 +3449,78 @@ EXTERN Tcl_Obj *TclPtrIncrVar _ANSI_ARGS_((Tcl_Interp *interp, Var *varPtr,
# define TclIncrObjsFreed()
#endif /* TCL_COMPILE_STATS */
-#define TclNewObj(objPtr) \
- TclAllocObjStorage(objPtr); \
+#ifndef TCL_MEM_DEBUG
+# define TclNewObj(objPtr) \
TclIncrObjsAllocated(); \
+ TclAllocObjStorage(objPtr); \
(objPtr)->refCount = 0; \
(objPtr)->bytes = tclEmptyStringRep; \
(objPtr)->length = 0; \
(objPtr)->typePtr = NULL; \
TCL_DTRACE_OBJ_CREATE(objPtr)
-
-#ifdef TCL_MEM_DEBUG
-# define TclDecrRefCount(objPtr) \
- Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__)
-#else
-# define TclDecrRefCount(objPtr) \
- if (--(objPtr)->refCount <= 0) { \
- TCL_DTRACE_OBJ_FREE(objPtr); \
- if (((objPtr)->typePtr != NULL) \
- && ((objPtr)->typePtr->freeIntRepProc != NULL)) { \
- (objPtr)->typePtr->freeIntRepProc(objPtr); \
- } \
- if (((objPtr)->bytes != NULL) \
- && ((objPtr)->bytes != tclEmptyStringRep)) { \
- ckfree((char *) (objPtr)->bytes); \
+/*
+ * Invalidate the string rep first so we can use the bytes value for our
+ * pointer chain, and signal an obj deletion (as opposed to shimmering) with
+ * 'length == -1'.
+ * Use empty 'if ; else' to handle use in unbraced outer if/else conditions.
+ */
+
+# define TclDecrRefCount(objPtr) \
+ if (--(objPtr)->refCount > 0) ; else { \
+ if (!(objPtr)->typePtr || !(objPtr)->typePtr->freeIntRepProc) { \
+ TCL_DTRACE_OBJ_FREE(objPtr); \
+ if ((objPtr)->bytes \
+ && ((objPtr)->bytes != tclEmptyStringRep)) { \
+ ckfree((char *) (objPtr)->bytes); \
+ } \
+ (objPtr)->length = -1; \
+ TclFreeObjStorage(objPtr); \
+ TclIncrObjsFreed(); \
+ } else { \
+ TclFreeObj(objPtr); \
} \
- TclFreeObjStorage(objPtr); \
- TclIncrObjsFreed(); \
}
-#endif
-
-#ifdef TCL_MEM_DEBUG
-# define TclAllocObjStorage(objPtr) \
- (objPtr) = (Tcl_Obj *) \
- Tcl_DbCkalloc(sizeof(Tcl_Obj), __FILE__, __LINE__)
-# define TclFreeObjStorage(objPtr) \
- if ((objPtr)->refCount < -1) { \
- panic("Reference count for %lx was negative: %s line %d", \
- (objPtr), __FILE__, __LINE__); \
- } \
- ckfree((char *) (objPtr))
-
-# define TclDbNewObj(objPtr, file, line) \
- (objPtr) = (Tcl_Obj *) Tcl_DbCkalloc(sizeof(Tcl_Obj), (file), (line)); \
- (objPtr)->refCount = 0; \
- (objPtr)->bytes = tclEmptyStringRep; \
- (objPtr)->length = 0; \
- (objPtr)->typePtr = NULL; \
- TclIncrObjsAllocated(); \
- TCL_DTRACE_OBJ_CREATE(objPtr)
-
-
-#elif defined(PURIFY)
+#if defined(PURIFY)
/*
* The PURIFY mode is like the regular mode, but instead of doing block
* Tcl_Obj allocation and keeping a freed list for efficiency, it always
- * allocates and frees a single Tcl_Obj so that tools like Purify can
- * better track memory leaks
+ * allocates and frees a single Tcl_Obj so that tools like Purify can better
+ * track memory leaks.
*/
# define TclAllocObjStorage(objPtr) \
- (objPtr) = (Tcl_Obj *) Tcl_Ckalloc(sizeof(Tcl_Obj))
+ (objPtr) = (Tcl_Obj *) Tcl_Alloc(sizeof(Tcl_Obj))
# define TclFreeObjStorage(objPtr) \
- ckfree((char *) (objPtr))
+ ckfree((char *) (objPtr))
+#undef USE_THREAD_ALLOC
#elif defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
/*
- * The TCL_THREADS mode is like the regular mode but allocates Tcl_Obj's
- * from per-thread caches.
+ * The TCL_THREADS mode is like the regular mode but allocates Tcl_Obj's from
+ * per-thread caches.
*/
-EXTERN Tcl_Obj *TclThreadAllocObj _ANSI_ARGS_((void));
-EXTERN void TclThreadFreeObj _ANSI_ARGS_((Tcl_Obj *));
-EXTERN void TclFreeAllocCache _ANSI_ARGS_((void *));
-EXTERN void TclpFreeAllocMutex _ANSI_ARGS_((Tcl_Mutex* mutex));
-EXTERN void TclpFreeAllocCache _ANSI_ARGS_((void *));
-
+MODULE_SCOPE Tcl_Obj * TclThreadAllocObj(void);
+MODULE_SCOPE void TclThreadFreeObj(Tcl_Obj *);
+MODULE_SCOPE Tcl_Mutex *TclpNewAllocMutex(void);
+MODULE_SCOPE void TclFreeAllocCache(void *);
+MODULE_SCOPE void * TclpGetAllocCache(void);
+MODULE_SCOPE void TclpSetAllocCache(void *);
+MODULE_SCOPE void TclpFreeAllocMutex(Tcl_Mutex *mutex);
+MODULE_SCOPE void TclpFreeAllocCache(void *);
# define TclAllocObjStorage(objPtr) \
- (objPtr) = TclThreadAllocObj()
+ (objPtr) = TclThreadAllocObj()
# define TclFreeObjStorage(objPtr) \
- TclThreadFreeObj((objPtr))
+ TclThreadFreeObj((objPtr))
-#else /* not TCL_MEM_DEBUG */
+#else /* not PURIFY or USE_THREAD_ALLOC */
#if defined(USE_TCLALLOC) && USE_TCLALLOC
MODULE_SCOPE void TclFinalizeAllocSubsystem();
@@ -2524,38 +3531,60 @@ EXTERN void TclpFreeAllocCache _ANSI_ARGS_((void *));
#ifdef TCL_THREADS
/* declared in tclObj.c */
-extern Tcl_Mutex tclObjMutex;
+MODULE_SCOPE Tcl_Mutex tclObjMutex;
#endif
# define TclAllocObjStorage(objPtr) \
- Tcl_MutexLock(&tclObjMutex); \
- if (tclFreeObjList == NULL) { \
- TclAllocateFreeObjects(); \
- } \
- (objPtr) = tclFreeObjList; \
- tclFreeObjList = (Tcl_Obj *) \
- tclFreeObjList->internalRep.otherValuePtr; \
- Tcl_MutexUnlock(&tclObjMutex)
+ Tcl_MutexLock(&tclObjMutex); \
+ if (tclFreeObjList == NULL) { \
+ TclAllocateFreeObjects(); \
+ } \
+ (objPtr) = tclFreeObjList; \
+ tclFreeObjList = (Tcl_Obj *) \
+ tclFreeObjList->internalRep.otherValuePtr; \
+ Tcl_MutexUnlock(&tclObjMutex)
# define TclFreeObjStorage(objPtr) \
- Tcl_MutexLock(&tclObjMutex); \
- (objPtr)->internalRep.otherValuePtr = (VOID *) tclFreeObjList; \
- tclFreeObjList = (objPtr); \
- Tcl_MutexUnlock(&tclObjMutex)
+ Tcl_MutexLock(&tclObjMutex); \
+ (objPtr)->internalRep.otherValuePtr = (void *) tclFreeObjList; \
+ tclFreeObjList = (objPtr); \
+ Tcl_MutexUnlock(&tclObjMutex)
+#endif
+
+#else /* TCL_MEM_DEBUG */
+MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, CONST char *file,
+ int line);
+
+# define TclDbNewObj(objPtr, file, line) \
+ TclIncrObjsAllocated(); \
+ (objPtr) = (Tcl_Obj *) Tcl_DbCkalloc(sizeof(Tcl_Obj), (file), (line)); \
+ TclDbInitNewObj((objPtr), (file), (line)); \
+ TCL_DTRACE_OBJ_CREATE(objPtr)
+
+# define TclNewObj(objPtr) \
+ TclDbNewObj(objPtr, __FILE__, __LINE__);
+
+# define TclDecrRefCount(objPtr) \
+ Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__)
+# define TclNewListObjDirect(objc, objv) \
+ TclDbNewListObjDirect(objc, objv, __FILE__, __LINE__)
+
+#undef USE_THREAD_ALLOC
#endif /* TCL_MEM_DEBUG */
/*
*----------------------------------------------------------------
- * Macro used by the Tcl core to set a Tcl_Obj's string representation
- * to a copy of the "len" bytes starting at "bytePtr". This code
- * works even if the byte array contains NULLs as long as the length
- * is correct. Because "len" is referenced multiple times, it should
- * be as simple an expression as possible. The ANSI C "prototype" for
- * this macro is:
+ * Macro used by the Tcl core to set a Tcl_Obj's string representation to a
+ * copy of the "len" bytes starting at "bytePtr". This code works even if the
+ * byte array contains NULLs as long as the length is correct. Because "len"
+ * is referenced multiple times, it should be as simple an expression as
+ * possible. The ANSI C "prototype" for this macro is:
*
- * EXTERN void TclInitStringRep _ANSI_ARGS_((Tcl_Obj *objPtr,
- * char *bytePtr, int len));
+ * MODULE_SCOPE void TclInitStringRep(Tcl_Obj *objPtr, char *bytePtr, int len);
+ *
+ * This macro should only be called on an unshared objPtr where
+ * objPtr->typePtr->freeIntRepProc == NULL
*----------------------------------------------------------------
*/
@@ -2565,7 +3594,7 @@ extern Tcl_Mutex tclObjMutex;
(objPtr)->length = 0; \
} else { \
(objPtr)->bytes = (char *) ckalloc((unsigned) ((len) + 1)); \
- memcpy((VOID *) (objPtr)->bytes, (VOID *) (bytePtr), \
+ memcpy((void *) (objPtr)->bytes, (void *) (bytePtr), \
(unsigned) (len)); \
(objPtr)->bytes[len] = '\0'; \
(objPtr)->length = (len); \
@@ -2573,80 +3602,400 @@ extern Tcl_Mutex tclObjMutex;
/*
*----------------------------------------------------------------
- * Macro used by the Tcl core to get the string representation's
- * byte array pointer from a Tcl_Obj. This is an inline version
- * of Tcl_GetString(). The macro's expression result is the string
- * rep's byte pointer which might be NULL. The bytes referenced by
- * this pointer must not be modified by the caller.
- * The ANSI C "prototype" for this macro is:
+ * Macro used by the Tcl core to get the string representation's byte array
+ * pointer from a Tcl_Obj. This is an inline version of Tcl_GetString(). The
+ * macro's expression result is the string rep's byte pointer which might be
+ * NULL. The bytes referenced by this pointer must not be modified by the
+ * caller. The ANSI C "prototype" for this macro is:
*
- * EXTERN char * TclGetString _ANSI_ARGS_((Tcl_Obj *objPtr));
+ * MODULE_SCOPE char * TclGetString(Tcl_Obj *objPtr);
*----------------------------------------------------------------
*/
#define TclGetString(objPtr) \
((objPtr)->bytes? (objPtr)->bytes : Tcl_GetString((objPtr)))
+#define TclGetStringFromObj(objPtr, lenPtr) \
+ ((objPtr)->bytes \
+ ? (*(lenPtr) = (objPtr)->length, (objPtr)->bytes) \
+ : Tcl_GetStringFromObj((objPtr), (lenPtr)))
+
/*
*----------------------------------------------------------------
- * Macro used by the Tcl core to get a Tcl_WideInt value out of
- * a Tcl_Obj of the "wideInt" type. Different implementation on
- * different platforms depending whether TCL_WIDE_INT_IS_LONG.
+ * Macro used by the Tcl core to clean out an object's internal
+ * representation. Does not actually reset the rep's bytes. The ANSI C
+ * "prototype" for this macro is:
+ *
+ * MODULE_SCOPE void TclFreeIntRep(Tcl_Obj *objPtr);
*----------------------------------------------------------------
*/
-#ifdef TCL_WIDE_INT_IS_LONG
-# define TclGetWide(resultVar, objPtr) \
- (resultVar) = (objPtr)->internalRep.longValue
-# define TclGetLongFromWide(resultVar, objPtr) \
- (resultVar) = (objPtr)->internalRep.longValue
-#else
-# define TclGetWide(resultVar, objPtr) \
- (resultVar) = (objPtr)->internalRep.wideValue
-# define TclGetLongFromWide(resultVar, objPtr) \
- (resultVar) = Tcl_WideAsLong((objPtr)->internalRep.wideValue)
-#endif
+#define TclFreeIntRep(objPtr) \
+ if ((objPtr)->typePtr != NULL && \
+ (objPtr)->typePtr->freeIntRepProc != NULL) { \
+ (objPtr)->typePtr->freeIntRepProc(objPtr); \
+ }
/*
*----------------------------------------------------------------
- * Macro used by the Tcl core get a unicode char from a utf string.
- * It checks to see if we have a one-byte utf char before calling
- * the real Tcl_UtfToUniChar, as this will save a lot of time for
- * primarily ascii string handling. The macro's expression result
- * is 1 for the 1-byte case or the result of Tcl_UtfToUniChar.
+ * Macro used by the Tcl core to clean out an object's string representation.
* The ANSI C "prototype" for this macro is:
*
- * EXTERN int TclUtfToUniChar _ANSI_ARGS_((CONST char *string,
- * Tcl_UniChar *ch));
+ * MODULE_SCOPE void TclInvalidateStringRep(Tcl_Obj *objPtr);
+ *----------------------------------------------------------------
+ */
+
+#define TclInvalidateStringRep(objPtr) \
+ if (objPtr->bytes != NULL) { \
+ if (objPtr->bytes != tclEmptyStringRep) { \
+ ckfree((char *) objPtr->bytes); \
+ } \
+ objPtr->bytes = NULL; \
+ }
+
+/*
+ *----------------------------------------------------------------
+ * Macros used by the Tcl core to grow Tcl_Token arrays. They use the same
+ * growth algorithm as used in tclStringObj.c for growing strings. The ANSI C
+ * "prototype" for this macro is:
+ *
+ * MODULE_SCOPE void TclGrowTokenArray(Tcl_Token *tokenPtr, int used,
+ * int available, int append,
+ * Tcl_Token *staticPtr);
+ * MODULE_SCOPE void TclGrowParseTokenArray(Tcl_Parse *parsePtr,
+ * int append);
+ *----------------------------------------------------------------
+ */
+
+#define TCL_MAX_TOKENS (int)(UINT_MAX / sizeof(Tcl_Token))
+#define TCL_MIN_TOKEN_GROWTH 50
+#define TclGrowTokenArray(tokenPtr, used, available, append, staticPtr) \
+{ \
+ int needed = (used) + (append); \
+ if (needed > TCL_MAX_TOKENS) { \
+ Tcl_Panic("max # of tokens for a Tcl parse (%d) exceeded", \
+ TCL_MAX_TOKENS); \
+ } \
+ if (needed > (available)) { \
+ int allocated = 2 * needed; \
+ Tcl_Token *oldPtr = (tokenPtr); \
+ Tcl_Token *newPtr; \
+ if (oldPtr == (staticPtr)) { \
+ oldPtr = NULL; \
+ } \
+ if (allocated > TCL_MAX_TOKENS) { \
+ allocated = TCL_MAX_TOKENS; \
+ } \
+ newPtr = (Tcl_Token *) attemptckrealloc((char *) oldPtr, \
+ (unsigned int) (allocated * sizeof(Tcl_Token))); \
+ if (newPtr == NULL) { \
+ allocated = needed + (append) + TCL_MIN_TOKEN_GROWTH; \
+ if (allocated > TCL_MAX_TOKENS) { \
+ allocated = TCL_MAX_TOKENS; \
+ } \
+ newPtr = (Tcl_Token *) ckrealloc((char *) oldPtr, \
+ (unsigned int) (allocated * sizeof(Tcl_Token))); \
+ } \
+ (available) = allocated; \
+ if (oldPtr == NULL) { \
+ memcpy((VOID *) newPtr, (VOID *) staticPtr, \
+ (size_t) ((used) * sizeof(Tcl_Token))); \
+ } \
+ (tokenPtr) = newPtr; \
+ } \
+}
+
+#define TclGrowParseTokenArray(parsePtr, append) \
+ TclGrowTokenArray((parsePtr)->tokenPtr, (parsePtr)->numTokens, \
+ (parsePtr)->tokensAvailable, (append), \
+ (parsePtr)->staticTokens)
+
+/*
+ *----------------------------------------------------------------
+ * Macro used by the Tcl core get a unicode char from a utf string. It checks
+ * to see if we have a one-byte utf char before calling the real
+ * Tcl_UtfToUniChar, as this will save a lot of time for primarily ASCII
+ * string handling. The macro's expression result is 1 for the 1-byte case or
+ * the result of Tcl_UtfToUniChar. The ANSI C "prototype" for this macro is:
+ *
+ * MODULE_SCOPE int TclUtfToUniChar(const char *string, Tcl_UniChar *ch);
*----------------------------------------------------------------
*/
#define TclUtfToUniChar(str, chPtr) \
- ((((unsigned char) *(str)) < 0xC0) ? \
- ((*(chPtr) = (Tcl_UniChar) *(str)), 1) \
+ ((((unsigned char) *(str)) < 0xC0) ? \
+ ((*(chPtr) = (Tcl_UniChar) *(str)), 1) \
: Tcl_UtfToUniChar(str, chPtr))
/*
*----------------------------------------------------------------
- * Macro used by the Tcl core to compare Unicode strings. On
- * big-endian systems we can use the more efficient memcmp, but
- * this would not be lexically correct on little-endian systems.
- * The ANSI C "prototype" for this macro is:
+ * Macro used by the Tcl core to compare Unicode strings. On big-endian
+ * systems we can use the more efficient memcmp, but this would not be
+ * lexically correct on little-endian systems. The ANSI C "prototype" for
+ * this macro is:
*
- * EXTERN int TclUniCharNcmp _ANSI_ARGS_((CONST Tcl_UniChar *cs,
- * CONST Tcl_UniChar *ct, unsigned long n));
+ * MODULE_SCOPE int TclUniCharNcmp(const Tcl_UniChar *cs,
+ * const Tcl_UniChar *ct, unsigned long n);
*----------------------------------------------------------------
*/
+
#ifdef WORDS_BIGENDIAN
# define TclUniCharNcmp(cs,ct,n) memcmp((cs),(ct),(n)*sizeof(Tcl_UniChar))
#else /* !WORDS_BIGENDIAN */
# define TclUniCharNcmp Tcl_UniCharNcmp
#endif /* WORDS_BIGENDIAN */
-#include "tclIntDecls.h"
+/*
+ *----------------------------------------------------------------
+ * Macro used by the Tcl core to increment a namespace's export export epoch
+ * counter. The ANSI C "prototype" for this macro is:
+ *
+ * MODULE_SCOPE void TclInvalidateNsCmdLookup(Namespace *nsPtr);
+ *----------------------------------------------------------------
+ */
-# undef TCL_STORAGE_CLASS
-# define TCL_STORAGE_CLASS DLLIMPORT
+#define TclInvalidateNsCmdLookup(nsPtr) \
+ if ((nsPtr)->numExportPatterns) { \
+ (nsPtr)->exportLookupEpoch++; \
+ } \
+ if ((nsPtr)->commandPathLength) { \
+ (nsPtr)->cmdRefEpoch++; \
+ }
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Core procedures added to libtommath for bignum manipulation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE int TclTommath_Init(Tcl_Interp *interp);
+MODULE_SCOPE void TclBNInitBignumFromLong(mp_int *bignum, long initVal);
+MODULE_SCOPE void TclBNInitBignumFromWideInt(mp_int *bignum,
+ Tcl_WideInt initVal);
+MODULE_SCOPE void TclBNInitBignumFromWideUInt(mp_int *bignum,
+ Tcl_WideUInt initVal);
+
+/*
+ *----------------------------------------------------------------
+ * Macro used by the Tcl core to check whether a pattern has any characters
+ * special to [string match]. The ANSI C "prototype" for this macro is:
+ *
+ * MODULE_SCOPE int TclMatchIsTrivial(const char *pattern);
+ *----------------------------------------------------------------
+ */
+
+#define TclMatchIsTrivial(pattern) strpbrk((pattern), "*[?\\") == NULL
+
+/*
+ *----------------------------------------------------------------
+ * Macros used by the Tcl core to set a Tcl_Obj's numeric representation
+ * avoiding the corresponding function calls in time critical parts of the
+ * core. They should only be called on unshared objects. The ANSI C
+ * "prototypes" for these macros are:
+ *
+ * MODULE_SCOPE void TclSetIntObj(Tcl_Obj *objPtr, int intValue);
+ * MODULE_SCOPE void TclSetLongObj(Tcl_Obj *objPtr, long longValue);
+ * MODULE_SCOPE void TclSetBooleanObj(Tcl_Obj *objPtr, long boolValue);
+ * MODULE_SCOPE void TclSetWideIntObj(Tcl_Obj *objPtr, Tcl_WideInt w);
+ * MODULE_SCOPE void TclSetDoubleObj(Tcl_Obj *objPtr, double d);
+ *----------------------------------------------------------------
+ */
+
+#define TclSetIntObj(objPtr, i) \
+ TclInvalidateStringRep(objPtr);\
+ TclFreeIntRep(objPtr); \
+ (objPtr)->internalRep.longValue = (long)(i); \
+ (objPtr)->typePtr = &tclIntType
+
+#define TclSetLongObj(objPtr, l) \
+ TclSetIntObj((objPtr), (l))
+
+/*
+ * NOTE: There is to be no such thing as a "pure" boolean. Boolean values set
+ * programmatically go straight to being "int" Tcl_Obj's, with value 0 or 1.
+ * The only "boolean" Tcl_Obj's shall be those holding the cached boolean
+ * value of strings like: "yes", "no", "true", "false", "on", "off".
+ */
+
+#define TclSetBooleanObj(objPtr, b) \
+ TclSetIntObj((objPtr), ((b)? 1 : 0));
+
+#ifndef NO_WIDE_TYPE
+#define TclSetWideIntObj(objPtr, w) \
+ TclInvalidateStringRep(objPtr);\
+ TclFreeIntRep(objPtr); \
+ (objPtr)->internalRep.wideValue = (Tcl_WideInt)(w); \
+ (objPtr)->typePtr = &tclWideIntType
+#endif
+
+#define TclSetDoubleObj(objPtr, d) \
+ TclInvalidateStringRep(objPtr);\
+ TclFreeIntRep(objPtr); \
+ (objPtr)->internalRep.doubleValue = (double)(d); \
+ (objPtr)->typePtr = &tclDoubleType
+
+/*
+ *----------------------------------------------------------------
+ * Macros used by the Tcl core to create and initialise objects of standard
+ * types, avoiding the corresponding function calls in time critical parts of
+ * the core. The ANSI C "prototypes" for these macros are:
+ *
+ * MODULE_SCOPE void TclNewIntObj(Tcl_Obj *objPtr, int i);
+ * MODULE_SCOPE void TclNewLongObj(Tcl_Obj *objPtr, long l);
+ * MODULE_SCOPE void TclNewBooleanObj(Tcl_Obj *objPtr, int b);
+ * MODULE_SCOPE void TclNewWideObj(Tcl_Obj *objPtr, Tcl_WideInt w);
+ * MODULE_SCOPE void TclNewDoubleObj(Tcl_Obj *objPtr, double d);
+ * MODULE_SCOPE void TclNewStringObj(Tcl_Obj *objPtr, char *s, int len);
+ * MODULE_SCOPE void TclNewLiteralStringObj(Tcl_Obj*objPtr, char*sLiteral);
+ *
+ *----------------------------------------------------------------
+ */
+
+#ifndef TCL_MEM_DEBUG
+#define TclNewIntObj(objPtr, i) \
+ TclIncrObjsAllocated(); \
+ TclAllocObjStorage(objPtr); \
+ (objPtr)->refCount = 0; \
+ (objPtr)->bytes = NULL; \
+ (objPtr)->internalRep.longValue = (long)(i); \
+ (objPtr)->typePtr = &tclIntType; \
+ TCL_DTRACE_OBJ_CREATE(objPtr)
+
+#define TclNewLongObj(objPtr, l) \
+ TclNewIntObj((objPtr), (l))
+
+/*
+ * NOTE: There is to be no such thing as a "pure" boolean.
+ * See comment above TclSetBooleanObj macro above.
+ */
+#define TclNewBooleanObj(objPtr, b) \
+ TclNewIntObj((objPtr), ((b)? 1 : 0))
+
+#define TclNewDoubleObj(objPtr, d) \
+ TclIncrObjsAllocated(); \
+ TclAllocObjStorage(objPtr); \
+ (objPtr)->refCount = 0; \
+ (objPtr)->bytes = NULL; \
+ (objPtr)->internalRep.doubleValue = (double)(d); \
+ (objPtr)->typePtr = &tclDoubleType; \
+ TCL_DTRACE_OBJ_CREATE(objPtr)
+
+#define TclNewStringObj(objPtr, s, len) \
+ TclIncrObjsAllocated(); \
+ TclAllocObjStorage(objPtr); \
+ (objPtr)->refCount = 0; \
+ TclInitStringRep((objPtr), (s), (len));\
+ (objPtr)->typePtr = NULL; \
+ TCL_DTRACE_OBJ_CREATE(objPtr)
+
+#else /* TCL_MEM_DEBUG */
+#define TclNewIntObj(objPtr, i) \
+ (objPtr) = Tcl_NewIntObj(i)
+
+#define TclNewLongObj(objPtr, l) \
+ (objPtr) = Tcl_NewLongObj(l)
+
+#define TclNewBooleanObj(objPtr, b) \
+ (objPtr) = Tcl_NewBooleanObj(b)
+
+#define TclNewDoubleObj(objPtr, d) \
+ (objPtr) = Tcl_NewDoubleObj(d)
+
+#define TclNewStringObj(objPtr, s, len) \
+ (objPtr) = Tcl_NewStringObj((s), (len))
+#endif /* TCL_MEM_DEBUG */
+
+/*
+ * The sLiteral argument *must* be a string literal; the incantation with
+ * sizeof(sLiteral "") will fail to compile otherwise.
+ */
+#define TclNewLiteralStringObj(objPtr, sLiteral) \
+ TclNewStringObj((objPtr), (sLiteral), (int) (sizeof(sLiteral "") - 1))
+
+/*
+ *----------------------------------------------------------------
+ * Macros used by the Tcl core to test for some special double values.
+ * The ANSI C "prototypes" for these macros are:
+ *
+ * MODULE_SCOPE int TclIsInfinite(double d);
+ * MODULE_SCOPE int TclIsNaN(double d);
+ */
+
+#ifdef _MSC_VER
+# define TclIsInfinite(d) (!(_finite((d))))
+# define TclIsNaN(d) (_isnan((d)))
+#else
+# define TclIsInfinite(d) ((d) > DBL_MAX || (d) < -DBL_MAX)
+# ifdef NO_ISNAN
+# define TclIsNaN(d) ((d) != (d))
+# else
+# define TclIsNaN(d) (isnan(d))
+# endif
+#endif
+
+/*
+ * ----------------------------------------------------------------------
+ * Macro to use to find the offset of a field in a structure. Computes number
+ * of bytes from beginning of structure to a given field.
+ */
+
+#ifdef offsetof
+#define TclOffset(type, field) ((int) offsetof(type, field))
+#else
+#define TclOffset(type, field) ((int) ((char *) &((type *) 0)->field))
+#endif
+
+/*
+ *----------------------------------------------------------------
+ * Inline version of Tcl_GetCurrentNamespace and Tcl_GetGlobalNamespace.
+ */
+
+#define TclGetCurrentNamespace(interp) \
+ (Tcl_Namespace *) ((Interp *)(interp))->varFramePtr->nsPtr
+
+#define TclGetGlobalNamespace(interp) \
+ (Tcl_Namespace *) ((Interp *)(interp))->globalNsPtr
+
+/*
+ *----------------------------------------------------------------
+ * Inline version of TclCleanupCommand; still need the function as it is in
+ * the internal stubs, but the core can use the macro instead.
+ */
+
+#define TclCleanupCommandMacro(cmdPtr) \
+ if (--(cmdPtr)->refCount <= 0) { \
+ ckfree((char *) (cmdPtr));\
+ }
+
+/*
+ *----------------------------------------------------------------
+ * Inline versions of Tcl_LimitReady() and Tcl_LimitExceeded to limit number
+ * of calls out of the critical path. Note that this code isn't particularly
+ * readable; the non-inline version (in tclInterp.c) is much easier to
+ * understand. Note also that these macros takes different args (iPtr->limit)
+ * to the non-inline version.
+ */
+
+#define TclLimitExceeded(limit) ((limit).exceeded != 0)
+
+#define TclLimitReady(limit) \
+ (((limit).active == 0) ? 0 : \
+ (++(limit).granularityTicker, \
+ ((((limit).active & TCL_LIMIT_COMMANDS) && \
+ (((limit).cmdGranularity == 1) || \
+ ((limit).granularityTicker % (limit).cmdGranularity == 0))) \
+ ? 1 : \
+ (((limit).active & TCL_LIMIT_TIME) && \
+ (((limit).timeGranularity == 1) || \
+ ((limit).granularityTicker % (limit).timeGranularity == 0)))\
+ ? 1 : 0)))
+
+
+#include "tclIntDecls.h"
+#include "tclIntPlatDecls.h"
+#include "tclTomMathDecls.h"
#endif /* _TCLINT */
diff --git a/generic/tclIntDecls.h b/generic/tclIntDecls.h
index 1d831ed..fb63ec0 100644
--- a/generic/tclIntDecls.h
+++ b/generic/tclIntDecls.h
@@ -15,6 +15,34 @@
#ifndef _TCLINTDECLS
#define _TCLINTDECLS
+#include "tclPort.h"
+
+#undef TCL_STORAGE_CLASS
+#ifdef BUILD_tcl
+# define TCL_STORAGE_CLASS DLLEXPORT
+#else
+# ifdef USE_TCL_STUBS
+# define TCL_STORAGE_CLASS
+# else
+# define TCL_STORAGE_CLASS DLLIMPORT
+# endif
+#endif
+
+/* [Bug #803489] Tcl_FindNamespace problem in the Stubs table */
+#undef Tcl_AppendExportList
+#undef Tcl_CreateNamespace
+#undef Tcl_DeleteNamespace
+#undef Tcl_Export
+#undef Tcl_FindCommand
+#undef Tcl_FindNamespace
+#undef Tcl_FindNamespaceVar
+#undef Tcl_ForgetImport
+#undef Tcl_GetCommandFromObj
+#undef Tcl_GetCommandFullName
+#undef Tcl_GetCurrentNamespace
+#undef Tcl_GetGlobalNamespace
+#undef Tcl_Import
+
/*
* WARNING: This file is automatically generated by the tools/genStubs.tcl
* script. Any modifications to the function declarations below should be made
@@ -28,491 +56,780 @@
*/
/* Slot 0 is reserved */
-/* 1 */
-EXTERN int TclAccessDeleteProc _ANSI_ARGS_((
- TclAccessProc_ * proc));
-/* 2 */
-EXTERN int TclAccessInsertProc _ANSI_ARGS_((
- TclAccessProc_ * proc));
+/* Slot 1 is reserved */
+/* Slot 2 is reserved */
+#ifndef TclAllocateFreeObjects_TCL_DECLARED
+#define TclAllocateFreeObjects_TCL_DECLARED
/* 3 */
-EXTERN void TclAllocateFreeObjects _ANSI_ARGS_((void));
+EXTERN void TclAllocateFreeObjects(void);
+#endif
/* Slot 4 is reserved */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+#ifndef TclCleanupChildren_TCL_DECLARED
+#define TclCleanupChildren_TCL_DECLARED
/* 5 */
-EXTERN int TclCleanupChildren _ANSI_ARGS_((Tcl_Interp * interp,
- int numPids, Tcl_Pid * pidPtr,
- Tcl_Channel errorChan));
-#endif /* UNIX */
-#ifdef __WIN32__
-/* 5 */
-EXTERN int TclCleanupChildren _ANSI_ARGS_((Tcl_Interp * interp,
- int numPids, Tcl_Pid * pidPtr,
- Tcl_Channel errorChan));
-#endif /* __WIN32__ */
+EXTERN int TclCleanupChildren(Tcl_Interp *interp, int numPids,
+ Tcl_Pid *pidPtr, Tcl_Channel errorChan);
+#endif
+#ifndef TclCleanupCommand_TCL_DECLARED
+#define TclCleanupCommand_TCL_DECLARED
/* 6 */
-EXTERN void TclCleanupCommand _ANSI_ARGS_((Command * cmdPtr));
+EXTERN void TclCleanupCommand(Command *cmdPtr);
+#endif
+#ifndef TclCopyAndCollapse_TCL_DECLARED
+#define TclCopyAndCollapse_TCL_DECLARED
/* 7 */
-EXTERN int TclCopyAndCollapse _ANSI_ARGS_((int count,
- CONST char * src, char * dst));
+EXTERN int TclCopyAndCollapse(int count, CONST char *src,
+ char *dst);
+#endif
+#ifndef TclCopyChannel_TCL_DECLARED
+#define TclCopyChannel_TCL_DECLARED
/* 8 */
-EXTERN int TclCopyChannel _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Channel inChan, Tcl_Channel outChan,
- int toRead, Tcl_Obj * cmdPtr));
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
-/* 9 */
-EXTERN int TclCreatePipeline _ANSI_ARGS_((Tcl_Interp * interp,
- int argc, CONST char ** argv,
- Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr,
- TclFile * outPipePtr, TclFile * errFilePtr));
-#endif /* UNIX */
-#ifdef __WIN32__
+EXTERN int TclCopyChannel(Tcl_Interp *interp,
+ Tcl_Channel inChan, Tcl_Channel outChan,
+ int toRead, Tcl_Obj *cmdPtr);
+#endif
+#ifndef TclCreatePipeline_TCL_DECLARED
+#define TclCreatePipeline_TCL_DECLARED
/* 9 */
-EXTERN int TclCreatePipeline _ANSI_ARGS_((Tcl_Interp * interp,
- int argc, CONST char ** argv,
- Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr,
- TclFile * outPipePtr, TclFile * errFilePtr));
-#endif /* __WIN32__ */
+EXTERN int TclCreatePipeline(Tcl_Interp *interp, int argc,
+ CONST char **argv, Tcl_Pid **pidArrayPtr,
+ TclFile *inPipePtr, TclFile *outPipePtr,
+ TclFile *errFilePtr);
+#endif
+#ifndef TclCreateProc_TCL_DECLARED
+#define TclCreateProc_TCL_DECLARED
/* 10 */
-EXTERN int TclCreateProc _ANSI_ARGS_((Tcl_Interp * interp,
- Namespace * nsPtr, CONST char * procName,
- Tcl_Obj * argsPtr, Tcl_Obj * bodyPtr,
- Proc ** procPtrPtr));
+EXTERN int TclCreateProc(Tcl_Interp *interp, Namespace *nsPtr,
+ CONST char *procName, Tcl_Obj *argsPtr,
+ Tcl_Obj *bodyPtr, Proc **procPtrPtr);
+#endif
+#ifndef TclDeleteCompiledLocalVars_TCL_DECLARED
+#define TclDeleteCompiledLocalVars_TCL_DECLARED
/* 11 */
-EXTERN void TclDeleteCompiledLocalVars _ANSI_ARGS_((
- Interp * iPtr, CallFrame * framePtr));
+EXTERN void TclDeleteCompiledLocalVars(Interp *iPtr,
+ CallFrame *framePtr);
+#endif
+#ifndef TclDeleteVars_TCL_DECLARED
+#define TclDeleteVars_TCL_DECLARED
/* 12 */
-EXTERN void TclDeleteVars _ANSI_ARGS_((Interp * iPtr,
- Tcl_HashTable * tablePtr));
-/* 13 */
-EXTERN int TclDoGlob _ANSI_ARGS_((Tcl_Interp * interp,
- char * separators, Tcl_DString * headPtr,
- char * tail, Tcl_GlobTypeData * types));
+EXTERN void TclDeleteVars(Interp *iPtr,
+ TclVarHashTable *tablePtr);
+#endif
+/* Slot 13 is reserved */
+#ifndef TclDumpMemoryInfo_TCL_DECLARED
+#define TclDumpMemoryInfo_TCL_DECLARED
/* 14 */
-EXTERN void TclDumpMemoryInfo _ANSI_ARGS_((FILE * outFile));
+EXTERN int TclDumpMemoryInfo(ClientData clientData, int flags);
+#endif
/* Slot 15 is reserved */
+#ifndef TclExprFloatError_TCL_DECLARED
+#define TclExprFloatError_TCL_DECLARED
/* 16 */
-EXTERN void TclExprFloatError _ANSI_ARGS_((Tcl_Interp * interp,
- double value));
+EXTERN void TclExprFloatError(Tcl_Interp *interp, double value);
+#endif
/* Slot 17 is reserved */
/* Slot 18 is reserved */
/* Slot 19 is reserved */
/* Slot 20 is reserved */
/* Slot 21 is reserved */
+#ifndef TclFindElement_TCL_DECLARED
+#define TclFindElement_TCL_DECLARED
/* 22 */
-EXTERN int TclFindElement _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * listStr, int listLength,
- CONST char ** elementPtr,
- CONST char ** nextPtr, int * sizePtr,
- int * bracePtr));
+EXTERN int TclFindElement(Tcl_Interp *interp,
+ CONST char *listStr, int listLength,
+ CONST char **elementPtr,
+ CONST char **nextPtr, int *sizePtr,
+ int *bracePtr);
+#endif
+#ifndef TclFindProc_TCL_DECLARED
+#define TclFindProc_TCL_DECLARED
/* 23 */
-EXTERN Proc * TclFindProc _ANSI_ARGS_((Interp * iPtr,
- CONST char * procName));
+EXTERN Proc * TclFindProc(Interp *iPtr, CONST char *procName);
+#endif
+#ifndef TclFormatInt_TCL_DECLARED
+#define TclFormatInt_TCL_DECLARED
/* 24 */
-EXTERN int TclFormatInt _ANSI_ARGS_((char * buffer, long n));
+EXTERN int TclFormatInt(char *buffer, long n);
+#endif
+#ifndef TclFreePackageInfo_TCL_DECLARED
+#define TclFreePackageInfo_TCL_DECLARED
/* 25 */
-EXTERN void TclFreePackageInfo _ANSI_ARGS_((Interp * iPtr));
+EXTERN void TclFreePackageInfo(Interp *iPtr);
+#endif
/* Slot 26 is reserved */
-/* 27 */
-EXTERN int TclGetDate _ANSI_ARGS_((char * p, Tcl_WideInt now,
- long zone, Tcl_WideInt * timePtr));
+/* Slot 27 is reserved */
+#ifndef TclpGetDefaultStdChannel_TCL_DECLARED
+#define TclpGetDefaultStdChannel_TCL_DECLARED
/* 28 */
-EXTERN Tcl_Channel TclpGetDefaultStdChannel _ANSI_ARGS_((int type));
+EXTERN Tcl_Channel TclpGetDefaultStdChannel(int type);
+#endif
/* Slot 29 is reserved */
/* Slot 30 is reserved */
+#ifndef TclGetExtension_TCL_DECLARED
+#define TclGetExtension_TCL_DECLARED
/* 31 */
-EXTERN char * TclGetExtension _ANSI_ARGS_((char * name));
+EXTERN CONST char * TclGetExtension(CONST char *name);
+#endif
+#ifndef TclGetFrame_TCL_DECLARED
+#define TclGetFrame_TCL_DECLARED
/* 32 */
-EXTERN int TclGetFrame _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * str, CallFrame ** framePtrPtr));
-/* 33 */
-EXTERN TclCmdProcType TclGetInterpProc _ANSI_ARGS_((void));
+EXTERN int TclGetFrame(Tcl_Interp *interp, CONST char *str,
+ CallFrame **framePtrPtr);
+#endif
+/* Slot 33 is reserved */
+#ifndef TclGetIntForIndex_TCL_DECLARED
+#define TclGetIntForIndex_TCL_DECLARED
/* 34 */
-EXTERN int TclGetIntForIndex _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * objPtr, int endValue,
- int * indexPtr));
+EXTERN int TclGetIntForIndex(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, int endValue, int *indexPtr);
+#endif
/* Slot 35 is reserved */
+#ifndef TclGetLong_TCL_DECLARED
+#define TclGetLong_TCL_DECLARED
/* 36 */
-EXTERN int TclGetLong _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * str, long * longPtr));
+EXTERN int TclGetLong(Tcl_Interp *interp, CONST char *str,
+ long *longPtr);
+#endif
+#ifndef TclGetLoadedPackages_TCL_DECLARED
+#define TclGetLoadedPackages_TCL_DECLARED
/* 37 */
-EXTERN int TclGetLoadedPackages _ANSI_ARGS_((
- Tcl_Interp * interp, char * targetName));
+EXTERN int TclGetLoadedPackages(Tcl_Interp *interp,
+ char *targetName);
+#endif
+#ifndef TclGetNamespaceForQualName_TCL_DECLARED
+#define TclGetNamespaceForQualName_TCL_DECLARED
/* 38 */
-EXTERN int TclGetNamespaceForQualName _ANSI_ARGS_((
- Tcl_Interp * interp, CONST char * qualName,
- Namespace * cxtNsPtr, int flags,
- Namespace ** nsPtrPtr,
- Namespace ** altNsPtrPtr,
- Namespace ** actualCxtPtrPtr,
- CONST char ** simpleNamePtr));
+EXTERN int TclGetNamespaceForQualName(Tcl_Interp *interp,
+ CONST char *qualName, Namespace *cxtNsPtr,
+ int flags, Namespace **nsPtrPtr,
+ Namespace **altNsPtrPtr,
+ Namespace **actualCxtPtrPtr,
+ CONST char **simpleNamePtr);
+#endif
+#ifndef TclGetObjInterpProc_TCL_DECLARED
+#define TclGetObjInterpProc_TCL_DECLARED
/* 39 */
-EXTERN TclObjCmdProcType TclGetObjInterpProc _ANSI_ARGS_((void));
+EXTERN TclObjCmdProcType TclGetObjInterpProc(void);
+#endif
+#ifndef TclGetOpenMode_TCL_DECLARED
+#define TclGetOpenMode_TCL_DECLARED
/* 40 */
-EXTERN int TclGetOpenMode _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * str, int * seekFlagPtr));
+EXTERN int TclGetOpenMode(Tcl_Interp *interp, CONST char *str,
+ int *seekFlagPtr);
+#endif
+#ifndef TclGetOriginalCommand_TCL_DECLARED
+#define TclGetOriginalCommand_TCL_DECLARED
/* 41 */
-EXTERN Tcl_Command TclGetOriginalCommand _ANSI_ARGS_((
- Tcl_Command command));
+EXTERN Tcl_Command TclGetOriginalCommand(Tcl_Command command);
+#endif
+#ifndef TclpGetUserHome_TCL_DECLARED
+#define TclpGetUserHome_TCL_DECLARED
/* 42 */
-EXTERN char * TclpGetUserHome _ANSI_ARGS_((CONST char * name,
- Tcl_DString * bufferPtr));
-/* 43 */
-EXTERN int TclGlobalInvoke _ANSI_ARGS_((Tcl_Interp * interp,
- int argc, CONST84 char ** argv, int flags));
+EXTERN char * TclpGetUserHome(CONST char *name,
+ Tcl_DString *bufferPtr);
+#endif
+/* Slot 43 is reserved */
+#ifndef TclGuessPackageName_TCL_DECLARED
+#define TclGuessPackageName_TCL_DECLARED
/* 44 */
-EXTERN int TclGuessPackageName _ANSI_ARGS_((
- CONST char * fileName, Tcl_DString * bufPtr));
+EXTERN int TclGuessPackageName(CONST char *fileName,
+ Tcl_DString *bufPtr);
+#endif
+#ifndef TclHideUnsafeCommands_TCL_DECLARED
+#define TclHideUnsafeCommands_TCL_DECLARED
/* 45 */
-EXTERN int TclHideUnsafeCommands _ANSI_ARGS_((
- Tcl_Interp * interp));
+EXTERN int TclHideUnsafeCommands(Tcl_Interp *interp);
+#endif
+#ifndef TclInExit_TCL_DECLARED
+#define TclInExit_TCL_DECLARED
/* 46 */
-EXTERN int TclInExit _ANSI_ARGS_((void));
+EXTERN int TclInExit(void);
+#endif
/* Slot 47 is reserved */
/* Slot 48 is reserved */
-/* 49 */
-EXTERN Tcl_Obj * TclIncrVar2 _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr,
- long incrAmount, int part1NotParsed));
+/* Slot 49 is reserved */
+#ifndef TclInitCompiledLocals_TCL_DECLARED
+#define TclInitCompiledLocals_TCL_DECLARED
/* 50 */
-EXTERN void TclInitCompiledLocals _ANSI_ARGS_((
- Tcl_Interp * interp, CallFrame * framePtr,
- Namespace * nsPtr));
+EXTERN void TclInitCompiledLocals(Tcl_Interp *interp,
+ CallFrame *framePtr, Namespace *nsPtr);
+#endif
+#ifndef TclInterpInit_TCL_DECLARED
+#define TclInterpInit_TCL_DECLARED
/* 51 */
-EXTERN int TclInterpInit _ANSI_ARGS_((Tcl_Interp * interp));
-/* 52 */
-EXTERN int TclInvoke _ANSI_ARGS_((Tcl_Interp * interp, int argc,
- CONST84 char ** argv, int flags));
+EXTERN int TclInterpInit(Tcl_Interp *interp);
+#endif
+/* Slot 52 is reserved */
+#ifndef TclInvokeObjectCommand_TCL_DECLARED
+#define TclInvokeObjectCommand_TCL_DECLARED
/* 53 */
-EXTERN int TclInvokeObjectCommand _ANSI_ARGS_((
- ClientData clientData, Tcl_Interp * interp,
- int argc, CONST84 char ** argv));
+EXTERN int TclInvokeObjectCommand(ClientData clientData,
+ Tcl_Interp *interp, int argc,
+ CONST84 char **argv);
+#endif
+#ifndef TclInvokeStringCommand_TCL_DECLARED
+#define TclInvokeStringCommand_TCL_DECLARED
/* 54 */
-EXTERN int TclInvokeStringCommand _ANSI_ARGS_((
- ClientData clientData, Tcl_Interp * interp,
- int objc, Tcl_Obj *CONST objv[]));
+EXTERN int TclInvokeStringCommand(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]);
+#endif
+#ifndef TclIsProc_TCL_DECLARED
+#define TclIsProc_TCL_DECLARED
/* 55 */
-EXTERN Proc * TclIsProc _ANSI_ARGS_((Command * cmdPtr));
+EXTERN Proc * TclIsProc(Command *cmdPtr);
+#endif
/* Slot 56 is reserved */
/* Slot 57 is reserved */
+#ifndef TclLookupVar_TCL_DECLARED
+#define TclLookupVar_TCL_DECLARED
/* 58 */
-EXTERN Var * TclLookupVar _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * part1, CONST char * part2,
- int flags, CONST char * msg, int createPart1,
- int createPart2, Var ** arrayPtrPtr));
+EXTERN Var * TclLookupVar(Tcl_Interp *interp, CONST char *part1,
+ CONST char *part2, int flags,
+ CONST char *msg, int createPart1,
+ int createPart2, Var **arrayPtrPtr);
+#endif
/* Slot 59 is reserved */
+#ifndef TclNeedSpace_TCL_DECLARED
+#define TclNeedSpace_TCL_DECLARED
/* 60 */
-EXTERN int TclNeedSpace _ANSI_ARGS_((CONST char * start,
- CONST char * end));
+EXTERN int TclNeedSpace(CONST char *start, CONST char *end);
+#endif
+#ifndef TclNewProcBodyObj_TCL_DECLARED
+#define TclNewProcBodyObj_TCL_DECLARED
/* 61 */
-EXTERN Tcl_Obj * TclNewProcBodyObj _ANSI_ARGS_((Proc * procPtr));
+EXTERN Tcl_Obj * TclNewProcBodyObj(Proc *procPtr);
+#endif
+#ifndef TclObjCommandComplete_TCL_DECLARED
+#define TclObjCommandComplete_TCL_DECLARED
/* 62 */
-EXTERN int TclObjCommandComplete _ANSI_ARGS_((Tcl_Obj * cmdPtr));
+EXTERN int TclObjCommandComplete(Tcl_Obj *cmdPtr);
+#endif
+#ifndef TclObjInterpProc_TCL_DECLARED
+#define TclObjInterpProc_TCL_DECLARED
/* 63 */
-EXTERN int TclObjInterpProc _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp * interp, int objc,
- Tcl_Obj *CONST objv[]));
+EXTERN int TclObjInterpProc(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]);
+#endif
+#ifndef TclObjInvoke_TCL_DECLARED
+#define TclObjInvoke_TCL_DECLARED
/* 64 */
-EXTERN int TclObjInvoke _ANSI_ARGS_((Tcl_Interp * interp,
- int objc, Tcl_Obj *CONST objv[], int flags));
-/* 65 */
-EXTERN int TclObjInvokeGlobal _ANSI_ARGS_((Tcl_Interp * interp,
- int objc, Tcl_Obj *CONST objv[], int flags));
-/* 66 */
-EXTERN int TclOpenFileChannelDeleteProc _ANSI_ARGS_((
- TclOpenFileChannelProc_ * proc));
-/* 67 */
-EXTERN int TclOpenFileChannelInsertProc _ANSI_ARGS_((
- TclOpenFileChannelProc_ * proc));
+EXTERN int TclObjInvoke(Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[], int flags);
+#endif
+/* Slot 65 is reserved */
+/* Slot 66 is reserved */
+/* Slot 67 is reserved */
/* Slot 68 is reserved */
+#ifndef TclpAlloc_TCL_DECLARED
+#define TclpAlloc_TCL_DECLARED
/* 69 */
-EXTERN char * TclpAlloc _ANSI_ARGS_((unsigned int size));
+EXTERN char * TclpAlloc(unsigned int size);
+#endif
/* Slot 70 is reserved */
/* Slot 71 is reserved */
/* Slot 72 is reserved */
/* Slot 73 is reserved */
+#ifndef TclpFree_TCL_DECLARED
+#define TclpFree_TCL_DECLARED
/* 74 */
-EXTERN void TclpFree _ANSI_ARGS_((char * ptr));
+EXTERN void TclpFree(char *ptr);
+#endif
+#ifndef TclpGetClicks_TCL_DECLARED
+#define TclpGetClicks_TCL_DECLARED
/* 75 */
-EXTERN unsigned long TclpGetClicks _ANSI_ARGS_((void));
+EXTERN unsigned long TclpGetClicks(void);
+#endif
+#ifndef TclpGetSeconds_TCL_DECLARED
+#define TclpGetSeconds_TCL_DECLARED
/* 76 */
-EXTERN unsigned long TclpGetSeconds _ANSI_ARGS_((void));
+EXTERN unsigned long TclpGetSeconds(void);
+#endif
+#ifndef TclpGetTime_TCL_DECLARED
+#define TclpGetTime_TCL_DECLARED
/* 77 */
-EXTERN void TclpGetTime _ANSI_ARGS_((Tcl_Time * time));
+EXTERN void TclpGetTime(Tcl_Time *time);
+#endif
+#ifndef TclpGetTimeZone_TCL_DECLARED
+#define TclpGetTimeZone_TCL_DECLARED
/* 78 */
-EXTERN int TclpGetTimeZone _ANSI_ARGS_((Tcl_WideInt time));
+EXTERN int TclpGetTimeZone(unsigned long time);
+#endif
/* Slot 79 is reserved */
/* Slot 80 is reserved */
+#ifndef TclpRealloc_TCL_DECLARED
+#define TclpRealloc_TCL_DECLARED
/* 81 */
-EXTERN char * TclpRealloc _ANSI_ARGS_((char * ptr,
- unsigned int size));
+EXTERN char * TclpRealloc(char *ptr, unsigned int size);
+#endif
/* Slot 82 is reserved */
/* Slot 83 is reserved */
/* Slot 84 is reserved */
/* Slot 85 is reserved */
/* Slot 86 is reserved */
/* Slot 87 is reserved */
+#ifndef TclPrecTraceProc_TCL_DECLARED
+#define TclPrecTraceProc_TCL_DECLARED
/* 88 */
-EXTERN char * TclPrecTraceProc _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp * interp, CONST char * name1,
- CONST char * name2, int flags));
+EXTERN char * TclPrecTraceProc(ClientData clientData,
+ Tcl_Interp *interp, CONST char *name1,
+ CONST char *name2, int flags);
+#endif
+#ifndef TclPreventAliasLoop_TCL_DECLARED
+#define TclPreventAliasLoop_TCL_DECLARED
/* 89 */
-EXTERN int TclPreventAliasLoop _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Interp * cmdInterp, Tcl_Command cmd));
+EXTERN int TclPreventAliasLoop(Tcl_Interp *interp,
+ Tcl_Interp *cmdInterp, Tcl_Command cmd);
+#endif
/* Slot 90 is reserved */
+#ifndef TclProcCleanupProc_TCL_DECLARED
+#define TclProcCleanupProc_TCL_DECLARED
/* 91 */
-EXTERN void TclProcCleanupProc _ANSI_ARGS_((Proc * procPtr));
+EXTERN void TclProcCleanupProc(Proc *procPtr);
+#endif
+#ifndef TclProcCompileProc_TCL_DECLARED
+#define TclProcCompileProc_TCL_DECLARED
/* 92 */
-EXTERN int TclProcCompileProc _ANSI_ARGS_((Tcl_Interp * interp,
- Proc * procPtr, Tcl_Obj * bodyPtr,
- Namespace * nsPtr, CONST char * description,
- CONST char * procName));
+EXTERN int TclProcCompileProc(Tcl_Interp *interp, Proc *procPtr,
+ Tcl_Obj *bodyPtr, Namespace *nsPtr,
+ CONST char *description,
+ CONST char *procName);
+#endif
+#ifndef TclProcDeleteProc_TCL_DECLARED
+#define TclProcDeleteProc_TCL_DECLARED
/* 93 */
-EXTERN void TclProcDeleteProc _ANSI_ARGS_((ClientData clientData));
-/* 94 */
-EXTERN int TclProcInterpProc _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp * interp, int argc,
- CONST84 char ** argv));
+EXTERN void TclProcDeleteProc(ClientData clientData);
+#endif
+/* Slot 94 is reserved */
/* Slot 95 is reserved */
+#ifndef TclRenameCommand_TCL_DECLARED
+#define TclRenameCommand_TCL_DECLARED
/* 96 */
-EXTERN int TclRenameCommand _ANSI_ARGS_((Tcl_Interp * interp,
- char * oldName, char * newName));
+EXTERN int TclRenameCommand(Tcl_Interp *interp,
+ CONST char *oldName, CONST char *newName);
+#endif
+#ifndef TclResetShadowedCmdRefs_TCL_DECLARED
+#define TclResetShadowedCmdRefs_TCL_DECLARED
/* 97 */
-EXTERN void TclResetShadowedCmdRefs _ANSI_ARGS_((
- Tcl_Interp * interp, Command * newCmdPtr));
+EXTERN void TclResetShadowedCmdRefs(Tcl_Interp *interp,
+ Command *newCmdPtr);
+#endif
+#ifndef TclServiceIdle_TCL_DECLARED
+#define TclServiceIdle_TCL_DECLARED
/* 98 */
-EXTERN int TclServiceIdle _ANSI_ARGS_((void));
+EXTERN int TclServiceIdle(void);
+#endif
/* Slot 99 is reserved */
/* Slot 100 is reserved */
+#ifndef TclSetPreInitScript_TCL_DECLARED
+#define TclSetPreInitScript_TCL_DECLARED
/* 101 */
-EXTERN char * TclSetPreInitScript _ANSI_ARGS_((char * string));
+EXTERN char * TclSetPreInitScript(char *string);
+#endif
+#ifndef TclSetupEnv_TCL_DECLARED
+#define TclSetupEnv_TCL_DECLARED
/* 102 */
-EXTERN void TclSetupEnv _ANSI_ARGS_((Tcl_Interp * interp));
+EXTERN void TclSetupEnv(Tcl_Interp *interp);
+#endif
+#ifndef TclSockGetPort_TCL_DECLARED
+#define TclSockGetPort_TCL_DECLARED
/* 103 */
-EXTERN int TclSockGetPort _ANSI_ARGS_((Tcl_Interp * interp,
- char * str, char * proto, int * portPtr));
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
-/* 104 */
-EXTERN int TclSockMinimumBuffers _ANSI_ARGS_((int sock,
- int size));
-#endif /* UNIX */
-#ifdef __WIN32__
+EXTERN int TclSockGetPort(Tcl_Interp *interp, CONST char *str,
+ CONST char *proto, int *portPtr);
+#endif
+#ifndef TclSockMinimumBuffers_TCL_DECLARED
+#define TclSockMinimumBuffers_TCL_DECLARED
/* 104 */
-EXTERN int TclSockMinimumBuffers _ANSI_ARGS_((int sock,
- int size));
-#endif /* __WIN32__ */
+EXTERN int TclSockMinimumBuffers(int sock, int size);
+#endif
/* Slot 105 is reserved */
-/* 106 */
-EXTERN int TclStatDeleteProc _ANSI_ARGS_((TclStatProc_ * proc));
-/* 107 */
-EXTERN int TclStatInsertProc _ANSI_ARGS_((TclStatProc_ * proc));
+/* Slot 106 is reserved */
+/* Slot 107 is reserved */
+#ifndef TclTeardownNamespace_TCL_DECLARED
+#define TclTeardownNamespace_TCL_DECLARED
/* 108 */
-EXTERN void TclTeardownNamespace _ANSI_ARGS_((Namespace * nsPtr));
+EXTERN void TclTeardownNamespace(Namespace *nsPtr);
+#endif
+#ifndef TclUpdateReturnInfo_TCL_DECLARED
+#define TclUpdateReturnInfo_TCL_DECLARED
/* 109 */
-EXTERN int TclUpdateReturnInfo _ANSI_ARGS_((Interp * iPtr));
+EXTERN int TclUpdateReturnInfo(Interp *iPtr);
+#endif
/* Slot 110 is reserved */
+#ifndef Tcl_AddInterpResolvers_TCL_DECLARED
+#define Tcl_AddInterpResolvers_TCL_DECLARED
/* 111 */
-EXTERN void Tcl_AddInterpResolvers _ANSI_ARGS_((
- Tcl_Interp * interp, CONST char * name,
- Tcl_ResolveCmdProc * cmdProc,
- Tcl_ResolveVarProc * varProc,
- Tcl_ResolveCompiledVarProc * compiledVarProc));
+EXTERN void Tcl_AddInterpResolvers(Tcl_Interp *interp,
+ CONST char *name,
+ Tcl_ResolveCmdProc *cmdProc,
+ Tcl_ResolveVarProc *varProc,
+ Tcl_ResolveCompiledVarProc *compiledVarProc);
+#endif
+#ifndef Tcl_AppendExportList_TCL_DECLARED
+#define Tcl_AppendExportList_TCL_DECLARED
/* 112 */
-EXTERN int Tcl_AppendExportList _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Namespace * nsPtr,
- Tcl_Obj * objPtr));
+EXTERN int Tcl_AppendExportList(Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr, Tcl_Obj *objPtr);
+#endif
+#ifndef Tcl_CreateNamespace_TCL_DECLARED
+#define Tcl_CreateNamespace_TCL_DECLARED
/* 113 */
-EXTERN Tcl_Namespace * Tcl_CreateNamespace _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * name, ClientData clientData,
- Tcl_NamespaceDeleteProc * deleteProc));
+EXTERN Tcl_Namespace * Tcl_CreateNamespace(Tcl_Interp *interp,
+ CONST char *name, ClientData clientData,
+ Tcl_NamespaceDeleteProc *deleteProc);
+#endif
+#ifndef Tcl_DeleteNamespace_TCL_DECLARED
+#define Tcl_DeleteNamespace_TCL_DECLARED
/* 114 */
-EXTERN void Tcl_DeleteNamespace _ANSI_ARGS_((
- Tcl_Namespace * nsPtr));
+EXTERN void Tcl_DeleteNamespace(Tcl_Namespace *nsPtr);
+#endif
+#ifndef Tcl_Export_TCL_DECLARED
+#define Tcl_Export_TCL_DECLARED
/* 115 */
-EXTERN int Tcl_Export _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Namespace * nsPtr, CONST char * pattern,
- int resetListFirst));
+EXTERN int Tcl_Export(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
+ CONST char *pattern, int resetListFirst);
+#endif
+#ifndef Tcl_FindCommand_TCL_DECLARED
+#define Tcl_FindCommand_TCL_DECLARED
/* 116 */
-EXTERN Tcl_Command Tcl_FindCommand _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * name,
- Tcl_Namespace * contextNsPtr, int flags));
+EXTERN Tcl_Command Tcl_FindCommand(Tcl_Interp *interp, CONST char *name,
+ Tcl_Namespace *contextNsPtr, int flags);
+#endif
+#ifndef Tcl_FindNamespace_TCL_DECLARED
+#define Tcl_FindNamespace_TCL_DECLARED
/* 117 */
-EXTERN Tcl_Namespace * Tcl_FindNamespace _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * name,
- Tcl_Namespace * contextNsPtr, int flags));
+EXTERN Tcl_Namespace * Tcl_FindNamespace(Tcl_Interp *interp,
+ CONST char *name,
+ Tcl_Namespace *contextNsPtr, int flags);
+#endif
+#ifndef Tcl_GetInterpResolvers_TCL_DECLARED
+#define Tcl_GetInterpResolvers_TCL_DECLARED
/* 118 */
-EXTERN int Tcl_GetInterpResolvers _ANSI_ARGS_((
- Tcl_Interp * interp, CONST char * name,
- Tcl_ResolverInfo * resInfo));
+EXTERN int Tcl_GetInterpResolvers(Tcl_Interp *interp,
+ CONST char *name, Tcl_ResolverInfo *resInfo);
+#endif
+#ifndef Tcl_GetNamespaceResolvers_TCL_DECLARED
+#define Tcl_GetNamespaceResolvers_TCL_DECLARED
/* 119 */
-EXTERN int Tcl_GetNamespaceResolvers _ANSI_ARGS_((
- Tcl_Namespace * namespacePtr,
- Tcl_ResolverInfo * resInfo));
+EXTERN int Tcl_GetNamespaceResolvers(
+ Tcl_Namespace *namespacePtr,
+ Tcl_ResolverInfo *resInfo);
+#endif
+#ifndef Tcl_FindNamespaceVar_TCL_DECLARED
+#define Tcl_FindNamespaceVar_TCL_DECLARED
/* 120 */
-EXTERN Tcl_Var Tcl_FindNamespaceVar _ANSI_ARGS_((
- Tcl_Interp * interp, CONST char * name,
- Tcl_Namespace * contextNsPtr, int flags));
+EXTERN Tcl_Var Tcl_FindNamespaceVar(Tcl_Interp *interp,
+ CONST char *name,
+ Tcl_Namespace *contextNsPtr, int flags);
+#endif
+#ifndef Tcl_ForgetImport_TCL_DECLARED
+#define Tcl_ForgetImport_TCL_DECLARED
/* 121 */
-EXTERN int Tcl_ForgetImport _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Namespace * nsPtr, CONST char * pattern));
+EXTERN int Tcl_ForgetImport(Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr, CONST char *pattern);
+#endif
+#ifndef Tcl_GetCommandFromObj_TCL_DECLARED
+#define Tcl_GetCommandFromObj_TCL_DECLARED
/* 122 */
-EXTERN Tcl_Command Tcl_GetCommandFromObj _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Obj * objPtr));
+EXTERN Tcl_Command Tcl_GetCommandFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr);
+#endif
+#ifndef Tcl_GetCommandFullName_TCL_DECLARED
+#define Tcl_GetCommandFullName_TCL_DECLARED
/* 123 */
-EXTERN void Tcl_GetCommandFullName _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Command command,
- Tcl_Obj * objPtr));
+EXTERN void Tcl_GetCommandFullName(Tcl_Interp *interp,
+ Tcl_Command command, Tcl_Obj *objPtr);
+#endif
+#ifndef Tcl_GetCurrentNamespace_TCL_DECLARED
+#define Tcl_GetCurrentNamespace_TCL_DECLARED
/* 124 */
-EXTERN Tcl_Namespace * Tcl_GetCurrentNamespace _ANSI_ARGS_((
- Tcl_Interp * interp));
+EXTERN Tcl_Namespace * Tcl_GetCurrentNamespace(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_GetGlobalNamespace_TCL_DECLARED
+#define Tcl_GetGlobalNamespace_TCL_DECLARED
/* 125 */
-EXTERN Tcl_Namespace * Tcl_GetGlobalNamespace _ANSI_ARGS_((
- Tcl_Interp * interp));
+EXTERN Tcl_Namespace * Tcl_GetGlobalNamespace(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_GetVariableFullName_TCL_DECLARED
+#define Tcl_GetVariableFullName_TCL_DECLARED
/* 126 */
-EXTERN void Tcl_GetVariableFullName _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Var variable,
- Tcl_Obj * objPtr));
+EXTERN void Tcl_GetVariableFullName(Tcl_Interp *interp,
+ Tcl_Var variable, Tcl_Obj *objPtr);
+#endif
+#ifndef Tcl_Import_TCL_DECLARED
+#define Tcl_Import_TCL_DECLARED
/* 127 */
-EXTERN int Tcl_Import _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Namespace * nsPtr, CONST char * pattern,
- int allowOverwrite));
+EXTERN int Tcl_Import(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
+ CONST char *pattern, int allowOverwrite);
+#endif
+#ifndef Tcl_PopCallFrame_TCL_DECLARED
+#define Tcl_PopCallFrame_TCL_DECLARED
/* 128 */
-EXTERN void Tcl_PopCallFrame _ANSI_ARGS_((Tcl_Interp* interp));
+EXTERN void Tcl_PopCallFrame(Tcl_Interp *interp);
+#endif
+#ifndef Tcl_PushCallFrame_TCL_DECLARED
+#define Tcl_PushCallFrame_TCL_DECLARED
/* 129 */
-EXTERN int Tcl_PushCallFrame _ANSI_ARGS_((Tcl_Interp* interp,
- Tcl_CallFrame * framePtr,
- Tcl_Namespace * nsPtr, int isProcCallFrame));
+EXTERN int Tcl_PushCallFrame(Tcl_Interp *interp,
+ Tcl_CallFrame *framePtr,
+ Tcl_Namespace *nsPtr, int isProcCallFrame);
+#endif
+#ifndef Tcl_RemoveInterpResolvers_TCL_DECLARED
+#define Tcl_RemoveInterpResolvers_TCL_DECLARED
/* 130 */
-EXTERN int Tcl_RemoveInterpResolvers _ANSI_ARGS_((
- Tcl_Interp * interp, CONST char * name));
+EXTERN int Tcl_RemoveInterpResolvers(Tcl_Interp *interp,
+ CONST char *name);
+#endif
+#ifndef Tcl_SetNamespaceResolvers_TCL_DECLARED
+#define Tcl_SetNamespaceResolvers_TCL_DECLARED
/* 131 */
-EXTERN void Tcl_SetNamespaceResolvers _ANSI_ARGS_((
- Tcl_Namespace * namespacePtr,
- Tcl_ResolveCmdProc * cmdProc,
- Tcl_ResolveVarProc * varProc,
- Tcl_ResolveCompiledVarProc * compiledVarProc));
+EXTERN void Tcl_SetNamespaceResolvers(
+ Tcl_Namespace *namespacePtr,
+ Tcl_ResolveCmdProc *cmdProc,
+ Tcl_ResolveVarProc *varProc,
+ Tcl_ResolveCompiledVarProc *compiledVarProc);
+#endif
+#ifndef TclpHasSockets_TCL_DECLARED
+#define TclpHasSockets_TCL_DECLARED
/* 132 */
-EXTERN int TclpHasSockets _ANSI_ARGS_((Tcl_Interp * interp));
+EXTERN int TclpHasSockets(Tcl_Interp *interp);
+#endif
+#ifndef TclpGetDate_TCL_DECLARED
+#define TclpGetDate_TCL_DECLARED
/* 133 */
-EXTERN struct tm * TclpGetDate _ANSI_ARGS_((TclpTime_t time, int useGMT));
-/* 134 */
-EXTERN size_t TclpStrftime _ANSI_ARGS_((char * s, size_t maxsize,
- CONST char * format, CONST struct tm * t,
- int useGMT));
-/* 135 */
-EXTERN int TclpCheckStackSpace _ANSI_ARGS_((void));
+EXTERN struct tm * TclpGetDate(CONST time_t *time, int useGMT);
+#endif
+/* Slot 134 is reserved */
+/* Slot 135 is reserved */
/* Slot 136 is reserved */
/* Slot 137 is reserved */
+#ifndef TclGetEnv_TCL_DECLARED
+#define TclGetEnv_TCL_DECLARED
/* 138 */
-EXTERN CONST84_RETURN char * TclGetEnv _ANSI_ARGS_((CONST char * name,
- Tcl_DString * valuePtr));
+EXTERN CONST84_RETURN char * TclGetEnv(CONST char *name,
+ Tcl_DString *valuePtr);
+#endif
/* Slot 139 is reserved */
-/* 140 */
-EXTERN int TclLooksLikeInt _ANSI_ARGS_((CONST char * bytes,
- int length));
+/* Slot 140 is reserved */
+#ifndef TclpGetCwd_TCL_DECLARED
+#define TclpGetCwd_TCL_DECLARED
/* 141 */
-EXTERN CONST84_RETURN char * TclpGetCwd _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_DString * cwdPtr));
+EXTERN CONST84_RETURN char * TclpGetCwd(Tcl_Interp *interp,
+ Tcl_DString *cwdPtr);
+#endif
+#ifndef TclSetByteCodeFromAny_TCL_DECLARED
+#define TclSetByteCodeFromAny_TCL_DECLARED
/* 142 */
-EXTERN int TclSetByteCodeFromAny _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Obj * objPtr,
- CompileHookProc * hookProc,
- ClientData clientData));
+EXTERN int TclSetByteCodeFromAny(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, CompileHookProc *hookProc,
+ ClientData clientData);
+#endif
+#ifndef TclAddLiteralObj_TCL_DECLARED
+#define TclAddLiteralObj_TCL_DECLARED
/* 143 */
-EXTERN int TclAddLiteralObj _ANSI_ARGS_((
- struct CompileEnv * envPtr, Tcl_Obj * objPtr,
- LiteralEntry ** litPtrPtr));
+EXTERN int TclAddLiteralObj(struct CompileEnv *envPtr,
+ Tcl_Obj *objPtr, LiteralEntry **litPtrPtr);
+#endif
+#ifndef TclHideLiteral_TCL_DECLARED
+#define TclHideLiteral_TCL_DECLARED
/* 144 */
-EXTERN void TclHideLiteral _ANSI_ARGS_((Tcl_Interp * interp,
- struct CompileEnv * envPtr, int index));
+EXTERN void TclHideLiteral(Tcl_Interp *interp,
+ struct CompileEnv *envPtr, int index);
+#endif
+#ifndef TclGetAuxDataType_TCL_DECLARED
+#define TclGetAuxDataType_TCL_DECLARED
/* 145 */
-EXTERN struct AuxDataType * TclGetAuxDataType _ANSI_ARGS_((char * typeName));
+EXTERN struct AuxDataType * TclGetAuxDataType(char *typeName);
+#endif
+#ifndef TclHandleCreate_TCL_DECLARED
+#define TclHandleCreate_TCL_DECLARED
/* 146 */
-EXTERN TclHandle TclHandleCreate _ANSI_ARGS_((VOID * ptr));
+EXTERN TclHandle TclHandleCreate(VOID *ptr);
+#endif
+#ifndef TclHandleFree_TCL_DECLARED
+#define TclHandleFree_TCL_DECLARED
/* 147 */
-EXTERN void TclHandleFree _ANSI_ARGS_((TclHandle handle));
+EXTERN void TclHandleFree(TclHandle handle);
+#endif
+#ifndef TclHandlePreserve_TCL_DECLARED
+#define TclHandlePreserve_TCL_DECLARED
/* 148 */
-EXTERN TclHandle TclHandlePreserve _ANSI_ARGS_((TclHandle handle));
+EXTERN TclHandle TclHandlePreserve(TclHandle handle);
+#endif
+#ifndef TclHandleRelease_TCL_DECLARED
+#define TclHandleRelease_TCL_DECLARED
/* 149 */
-EXTERN void TclHandleRelease _ANSI_ARGS_((TclHandle handle));
+EXTERN void TclHandleRelease(TclHandle handle);
+#endif
+#ifndef TclRegAbout_TCL_DECLARED
+#define TclRegAbout_TCL_DECLARED
/* 150 */
-EXTERN int TclRegAbout _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_RegExp re));
+EXTERN int TclRegAbout(Tcl_Interp *interp, Tcl_RegExp re);
+#endif
+#ifndef TclRegExpRangeUniChar_TCL_DECLARED
+#define TclRegExpRangeUniChar_TCL_DECLARED
/* 151 */
-EXTERN void TclRegExpRangeUniChar _ANSI_ARGS_((Tcl_RegExp re,
- int index, int * startPtr, int * endPtr));
+EXTERN void TclRegExpRangeUniChar(Tcl_RegExp re, int index,
+ int *startPtr, int *endPtr);
+#endif
+#ifndef TclSetLibraryPath_TCL_DECLARED
+#define TclSetLibraryPath_TCL_DECLARED
/* 152 */
-EXTERN void TclSetLibraryPath _ANSI_ARGS_((Tcl_Obj * pathPtr));
+EXTERN void TclSetLibraryPath(Tcl_Obj *pathPtr);
+#endif
+#ifndef TclGetLibraryPath_TCL_DECLARED
+#define TclGetLibraryPath_TCL_DECLARED
/* 153 */
-EXTERN Tcl_Obj * TclGetLibraryPath _ANSI_ARGS_((void));
+EXTERN Tcl_Obj * TclGetLibraryPath(void);
+#endif
/* Slot 154 is reserved */
/* Slot 155 is reserved */
+#ifndef TclRegError_TCL_DECLARED
+#define TclRegError_TCL_DECLARED
/* 156 */
-EXTERN void TclRegError _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * msg, int status));
+EXTERN void TclRegError(Tcl_Interp *interp, CONST char *msg,
+ int status);
+#endif
+#ifndef TclVarTraceExists_TCL_DECLARED
+#define TclVarTraceExists_TCL_DECLARED
/* 157 */
-EXTERN Var * TclVarTraceExists _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * varName));
+EXTERN Var * TclVarTraceExists(Tcl_Interp *interp,
+ CONST char *varName);
+#endif
+#ifndef TclSetStartupScriptFileName_TCL_DECLARED
+#define TclSetStartupScriptFileName_TCL_DECLARED
/* 158 */
-EXTERN void TclSetStartupScriptFileName _ANSI_ARGS_((
- CONST char * filename));
+EXTERN void TclSetStartupScriptFileName(CONST char *filename);
+#endif
+#ifndef TclGetStartupScriptFileName_TCL_DECLARED
+#define TclGetStartupScriptFileName_TCL_DECLARED
/* 159 */
-EXTERN CONST84_RETURN char * TclGetStartupScriptFileName _ANSI_ARGS_((void));
+EXTERN CONST84_RETURN char * TclGetStartupScriptFileName(void);
+#endif
/* Slot 160 is reserved */
+#ifndef TclChannelTransform_TCL_DECLARED
+#define TclChannelTransform_TCL_DECLARED
/* 161 */
-EXTERN int TclChannelTransform _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Channel chan, Tcl_Obj * cmdObjPtr));
+EXTERN int TclChannelTransform(Tcl_Interp *interp,
+ Tcl_Channel chan, Tcl_Obj *cmdObjPtr);
+#endif
+#ifndef TclChannelEventScriptInvoker_TCL_DECLARED
+#define TclChannelEventScriptInvoker_TCL_DECLARED
/* 162 */
-EXTERN void TclChannelEventScriptInvoker _ANSI_ARGS_((
- ClientData clientData, int flags));
+EXTERN void TclChannelEventScriptInvoker(ClientData clientData,
+ int flags);
+#endif
+#ifndef TclGetInstructionTable_TCL_DECLARED
+#define TclGetInstructionTable_TCL_DECLARED
/* 163 */
-EXTERN VOID * TclGetInstructionTable _ANSI_ARGS_((void));
+EXTERN VOID * TclGetInstructionTable(void);
+#endif
+#ifndef TclExpandCodeArray_TCL_DECLARED
+#define TclExpandCodeArray_TCL_DECLARED
/* 164 */
-EXTERN void TclExpandCodeArray _ANSI_ARGS_((VOID * envPtr));
+EXTERN void TclExpandCodeArray(VOID *envPtr);
+#endif
+#ifndef TclpSetInitialEncodings_TCL_DECLARED
+#define TclpSetInitialEncodings_TCL_DECLARED
/* 165 */
-EXTERN void TclpSetInitialEncodings _ANSI_ARGS_((void));
+EXTERN void TclpSetInitialEncodings(void);
+#endif
+#ifndef TclListObjSetElement_TCL_DECLARED
+#define TclListObjSetElement_TCL_DECLARED
/* 166 */
-EXTERN int TclListObjSetElement _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Obj * listPtr,
- int index, Tcl_Obj * valuePtr));
+EXTERN int TclListObjSetElement(Tcl_Interp *interp,
+ Tcl_Obj *listPtr, int index,
+ Tcl_Obj *valuePtr);
+#endif
+#ifndef TclSetStartupScriptPath_TCL_DECLARED
+#define TclSetStartupScriptPath_TCL_DECLARED
/* 167 */
-EXTERN void TclSetStartupScriptPath _ANSI_ARGS_((
- Tcl_Obj * pathPtr));
+EXTERN void TclSetStartupScriptPath(Tcl_Obj *pathPtr);
+#endif
+#ifndef TclGetStartupScriptPath_TCL_DECLARED
+#define TclGetStartupScriptPath_TCL_DECLARED
/* 168 */
-EXTERN Tcl_Obj * TclGetStartupScriptPath _ANSI_ARGS_((void));
+EXTERN Tcl_Obj * TclGetStartupScriptPath(void);
+#endif
+#ifndef TclpUtfNcmp2_TCL_DECLARED
+#define TclpUtfNcmp2_TCL_DECLARED
/* 169 */
-EXTERN int TclpUtfNcmp2 _ANSI_ARGS_((CONST char * s1,
- CONST char * s2, unsigned long n));
+EXTERN int TclpUtfNcmp2(CONST char *s1, CONST char *s2,
+ unsigned long n);
+#endif
+#ifndef TclCheckInterpTraces_TCL_DECLARED
+#define TclCheckInterpTraces_TCL_DECLARED
/* 170 */
-EXTERN int TclCheckInterpTraces _ANSI_ARGS_((
- Tcl_Interp * interp, CONST char * command,
- int numChars, Command * cmdPtr, int result,
- int traceFlags, int objc,
- Tcl_Obj *CONST objv[]));
+EXTERN int TclCheckInterpTraces(Tcl_Interp *interp,
+ CONST char *command, int numChars,
+ Command *cmdPtr, int result, int traceFlags,
+ int objc, Tcl_Obj *CONST objv[]);
+#endif
+#ifndef TclCheckExecutionTraces_TCL_DECLARED
+#define TclCheckExecutionTraces_TCL_DECLARED
/* 171 */
-EXTERN int TclCheckExecutionTraces _ANSI_ARGS_((
- Tcl_Interp * interp, CONST char * command,
- int numChars, Command * cmdPtr, int result,
- int traceFlags, int objc,
- Tcl_Obj *CONST objv[]));
+EXTERN int TclCheckExecutionTraces(Tcl_Interp *interp,
+ CONST char *command, int numChars,
+ Command *cmdPtr, int result, int traceFlags,
+ int objc, Tcl_Obj *CONST objv[]);
+#endif
+#ifndef TclInThreadExit_TCL_DECLARED
+#define TclInThreadExit_TCL_DECLARED
/* 172 */
-EXTERN int TclInThreadExit _ANSI_ARGS_((void));
+EXTERN int TclInThreadExit(void);
+#endif
+#ifndef TclUniCharMatch_TCL_DECLARED
+#define TclUniCharMatch_TCL_DECLARED
/* 173 */
-EXTERN int TclUniCharMatch _ANSI_ARGS_((
- CONST Tcl_UniChar * string, int strLen,
- CONST Tcl_UniChar * pattern, int ptnLen,
- int nocase));
+EXTERN int TclUniCharMatch(CONST Tcl_UniChar *string,
+ int strLen, CONST Tcl_UniChar *pattern,
+ int ptnLen, int flags);
+#endif
/* Slot 174 is reserved */
-/* Slot 175 is reserved */
-/* Slot 176 is reserved */
-/* Slot 177 is reserved */
-/* Slot 178 is reserved */
-/* Slot 179 is reserved */
+#ifndef TclCallVarTraces_TCL_DECLARED
+#define TclCallVarTraces_TCL_DECLARED
+/* 175 */
+EXTERN int TclCallVarTraces(Interp *iPtr, Var *arrayPtr,
+ Var *varPtr, CONST char *part1,
+ CONST char *part2, int flags,
+ int leaveErrMsg);
+#endif
+#ifndef TclCleanupVar_TCL_DECLARED
+#define TclCleanupVar_TCL_DECLARED
+/* 176 */
+EXTERN void TclCleanupVar(Var *varPtr, Var *arrayPtr);
+#endif
+#ifndef TclVarErrMsg_TCL_DECLARED
+#define TclVarErrMsg_TCL_DECLARED
+/* 177 */
+EXTERN void TclVarErrMsg(Tcl_Interp *interp, CONST char *part1,
+ CONST char *part2, CONST char *operation,
+ CONST char *reason);
+#endif
+#ifndef Tcl_SetStartupScript_TCL_DECLARED
+#define Tcl_SetStartupScript_TCL_DECLARED
+/* 178 */
+EXTERN void Tcl_SetStartupScript(Tcl_Obj *pathPtr,
+ CONST char*encodingName);
+#endif
+#ifndef Tcl_GetStartupScript_TCL_DECLARED
+#define Tcl_GetStartupScript_TCL_DECLARED
+/* 179 */
+EXTERN Tcl_Obj * Tcl_GetStartupScript(CONST char **encodingNamePtr);
+#endif
/* Slot 180 is reserved */
/* Slot 181 is reserved */
+#ifndef TclpLocaltime_TCL_DECLARED
+#define TclpLocaltime_TCL_DECLARED
/* 182 */
-EXTERN struct tm * TclpLocaltime _ANSI_ARGS_((TclpTime_t_CONST clock));
+EXTERN struct tm * TclpLocaltime(CONST time_t *clock);
+#endif
+#ifndef TclpGmtime_TCL_DECLARED
+#define TclpGmtime_TCL_DECLARED
/* 183 */
-EXTERN struct tm * TclpGmtime _ANSI_ARGS_((TclpTime_t_CONST clock));
+EXTERN struct tm * TclpGmtime(CONST time_t *clock);
+#endif
/* Slot 184 is reserved */
/* Slot 185 is reserved */
/* Slot 186 is reserved */
@@ -527,238 +844,466 @@ EXTERN struct tm * TclpGmtime _ANSI_ARGS_((TclpTime_t_CONST clock));
/* Slot 195 is reserved */
/* Slot 196 is reserved */
/* Slot 197 is reserved */
-/* Slot 198 is reserved */
-/* 199 */
-EXTERN int TclMatchIsTrivial _ANSI_ARGS_((CONST char * pattern));
+#ifndef TclObjGetFrame_TCL_DECLARED
+#define TclObjGetFrame_TCL_DECLARED
+/* 198 */
+EXTERN int TclObjGetFrame(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ CallFrame **framePtrPtr);
+#endif
+/* Slot 199 is reserved */
+#ifndef TclpObjRemoveDirectory_TCL_DECLARED
+#define TclpObjRemoveDirectory_TCL_DECLARED
+/* 200 */
+EXTERN int TclpObjRemoveDirectory(Tcl_Obj *pathPtr,
+ int recursive, Tcl_Obj **errorPtr);
+#endif
+#ifndef TclpObjCopyDirectory_TCL_DECLARED
+#define TclpObjCopyDirectory_TCL_DECLARED
+/* 201 */
+EXTERN int TclpObjCopyDirectory(Tcl_Obj *srcPathPtr,
+ Tcl_Obj *destPathPtr, Tcl_Obj **errorPtr);
+#endif
+#ifndef TclpObjCreateDirectory_TCL_DECLARED
+#define TclpObjCreateDirectory_TCL_DECLARED
+/* 202 */
+EXTERN int TclpObjCreateDirectory(Tcl_Obj *pathPtr);
+#endif
+#ifndef TclpObjDeleteFile_TCL_DECLARED
+#define TclpObjDeleteFile_TCL_DECLARED
+/* 203 */
+EXTERN int TclpObjDeleteFile(Tcl_Obj *pathPtr);
+#endif
+#ifndef TclpObjCopyFile_TCL_DECLARED
+#define TclpObjCopyFile_TCL_DECLARED
+/* 204 */
+EXTERN int TclpObjCopyFile(Tcl_Obj *srcPathPtr,
+ Tcl_Obj *destPathPtr);
+#endif
+#ifndef TclpObjRenameFile_TCL_DECLARED
+#define TclpObjRenameFile_TCL_DECLARED
+/* 205 */
+EXTERN int TclpObjRenameFile(Tcl_Obj *srcPathPtr,
+ Tcl_Obj *destPathPtr);
+#endif
+#ifndef TclpObjStat_TCL_DECLARED
+#define TclpObjStat_TCL_DECLARED
+/* 206 */
+EXTERN int TclpObjStat(Tcl_Obj *pathPtr, Tcl_StatBuf *buf);
+#endif
+#ifndef TclpObjAccess_TCL_DECLARED
+#define TclpObjAccess_TCL_DECLARED
+/* 207 */
+EXTERN int TclpObjAccess(Tcl_Obj *pathPtr, int mode);
+#endif
+#ifndef TclpOpenFileChannel_TCL_DECLARED
+#define TclpOpenFileChannel_TCL_DECLARED
+/* 208 */
+EXTERN Tcl_Channel TclpOpenFileChannel(Tcl_Interp *interp,
+ Tcl_Obj *pathPtr, int mode, int permissions);
+#endif
+/* Slot 209 is reserved */
+/* Slot 210 is reserved */
+/* Slot 211 is reserved */
+#ifndef TclpFindExecutable_TCL_DECLARED
+#define TclpFindExecutable_TCL_DECLARED
+/* 212 */
+EXTERN void TclpFindExecutable(CONST char *argv0);
+#endif
+#ifndef TclGetObjNameOfExecutable_TCL_DECLARED
+#define TclGetObjNameOfExecutable_TCL_DECLARED
+/* 213 */
+EXTERN Tcl_Obj * TclGetObjNameOfExecutable(void);
+#endif
+#ifndef TclSetObjNameOfExecutable_TCL_DECLARED
+#define TclSetObjNameOfExecutable_TCL_DECLARED
+/* 214 */
+EXTERN void TclSetObjNameOfExecutable(Tcl_Obj *name,
+ Tcl_Encoding encoding);
+#endif
+#ifndef TclStackAlloc_TCL_DECLARED
+#define TclStackAlloc_TCL_DECLARED
+/* 215 */
+EXTERN VOID * TclStackAlloc(Tcl_Interp *interp, int numBytes);
+#endif
+#ifndef TclStackFree_TCL_DECLARED
+#define TclStackFree_TCL_DECLARED
+/* 216 */
+EXTERN void TclStackFree(Tcl_Interp *interp, VOID *freePtr);
+#endif
+#ifndef TclPushStackFrame_TCL_DECLARED
+#define TclPushStackFrame_TCL_DECLARED
+/* 217 */
+EXTERN int TclPushStackFrame(Tcl_Interp *interp,
+ Tcl_CallFrame **framePtrPtr,
+ Tcl_Namespace *namespacePtr,
+ int isProcCallFrame);
+#endif
+#ifndef TclPopStackFrame_TCL_DECLARED
+#define TclPopStackFrame_TCL_DECLARED
+/* 218 */
+EXTERN void TclPopStackFrame(Tcl_Interp *interp);
+#endif
+/* Slot 219 is reserved */
+/* Slot 220 is reserved */
+/* Slot 221 is reserved */
+/* Slot 222 is reserved */
+/* Slot 223 is reserved */
+#ifndef TclGetPlatform_TCL_DECLARED
+#define TclGetPlatform_TCL_DECLARED
+/* 224 */
+EXTERN TclPlatformType * TclGetPlatform(void);
+#endif
+#ifndef TclTraceDictPath_TCL_DECLARED
+#define TclTraceDictPath_TCL_DECLARED
+/* 225 */
+EXTERN Tcl_Obj * TclTraceDictPath(Tcl_Interp *interp,
+ Tcl_Obj *rootPtr, int keyc,
+ Tcl_Obj *CONST keyv[], int flags);
+#endif
+#ifndef TclObjBeingDeleted_TCL_DECLARED
+#define TclObjBeingDeleted_TCL_DECLARED
+/* 226 */
+EXTERN int TclObjBeingDeleted(Tcl_Obj *objPtr);
+#endif
+#ifndef TclSetNsPath_TCL_DECLARED
+#define TclSetNsPath_TCL_DECLARED
+/* 227 */
+EXTERN void TclSetNsPath(Namespace *nsPtr, int pathLength,
+ Tcl_Namespace *pathAry[]);
+#endif
+#ifndef TclObjInterpProcCore_TCL_DECLARED
+#define TclObjInterpProcCore_TCL_DECLARED
+/* 228 */
+EXTERN int TclObjInterpProcCore(register Tcl_Interp *interp,
+ Tcl_Obj *procNameObj, int skip,
+ ProcErrorProc errorProc);
+#endif
+#ifndef TclPtrMakeUpvar_TCL_DECLARED
+#define TclPtrMakeUpvar_TCL_DECLARED
+/* 229 */
+EXTERN int TclPtrMakeUpvar(Tcl_Interp *interp, Var *otherP1Ptr,
+ CONST char *myName, int myFlags, int index);
+#endif
+#ifndef TclObjLookupVar_TCL_DECLARED
+#define TclObjLookupVar_TCL_DECLARED
+/* 230 */
+EXTERN Var * TclObjLookupVar(Tcl_Interp *interp,
+ Tcl_Obj *part1Ptr, CONST char *part2,
+ int flags, CONST char *msg,
+ CONST int createPart1, CONST int createPart2,
+ Var **arrayPtrPtr);
+#endif
+#ifndef TclGetNamespaceFromObj_TCL_DECLARED
+#define TclGetNamespaceFromObj_TCL_DECLARED
+/* 231 */
+EXTERN int TclGetNamespaceFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, Tcl_Namespace **nsPtrPtr);
+#endif
+#ifndef TclEvalObjEx_TCL_DECLARED
+#define TclEvalObjEx_TCL_DECLARED
+/* 232 */
+EXTERN int TclEvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ int flags, CONST CmdFrame *invoker, int word);
+#endif
+#ifndef TclGetSrcInfoForPc_TCL_DECLARED
+#define TclGetSrcInfoForPc_TCL_DECLARED
+/* 233 */
+EXTERN void TclGetSrcInfoForPc(CmdFrame *contextPtr);
+#endif
+#ifndef TclVarHashCreateVar_TCL_DECLARED
+#define TclVarHashCreateVar_TCL_DECLARED
+/* 234 */
+EXTERN Var * TclVarHashCreateVar(TclVarHashTable *tablePtr,
+ CONST char *key, int *newPtr);
+#endif
+#ifndef TclInitVarHashTable_TCL_DECLARED
+#define TclInitVarHashTable_TCL_DECLARED
+/* 235 */
+EXTERN void TclInitVarHashTable(TclVarHashTable *tablePtr,
+ Namespace *nsPtr);
+#endif
+#ifndef TclBackgroundException_TCL_DECLARED
+#define TclBackgroundException_TCL_DECLARED
+/* 236 */
+EXTERN void TclBackgroundException(Tcl_Interp *interp, int code);
+#endif
+/* Slot 237 is reserved */
+/* Slot 238 is reserved */
+/* Slot 239 is reserved */
+/* Slot 240 is reserved */
+/* Slot 241 is reserved */
+/* Slot 242 is reserved */
+#ifndef TclDbDumpActiveObjects_TCL_DECLARED
+#define TclDbDumpActiveObjects_TCL_DECLARED
+/* 243 */
+EXTERN void TclDbDumpActiveObjects(FILE *outFile);
+#endif
+/* Slot 244 is reserved */
+/* Slot 245 is reserved */
+/* Slot 246 is reserved */
+/* Slot 247 is reserved */
+/* Slot 248 is reserved */
+#ifndef TclDoubleDigits_TCL_DECLARED
+#define TclDoubleDigits_TCL_DECLARED
+/* 249 */
+EXTERN char* TclDoubleDigits(double dv, int ndigits, int flags,
+ int*decpt, int*signum, char**endPtr);
+#endif
typedef struct TclIntStubs {
int magic;
struct TclIntStubHooks *hooks;
- void *reserved0;
- int (*tclAccessDeleteProc) _ANSI_ARGS_((TclAccessProc_ * proc)); /* 1 */
- int (*tclAccessInsertProc) _ANSI_ARGS_((TclAccessProc_ * proc)); /* 2 */
- void (*tclAllocateFreeObjects) _ANSI_ARGS_((void)); /* 3 */
- void *reserved4;
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
- int (*tclCleanupChildren) _ANSI_ARGS_((Tcl_Interp * interp, int numPids, Tcl_Pid * pidPtr, Tcl_Channel errorChan)); /* 5 */
-#endif /* UNIX */
-#ifdef __WIN32__
- int (*tclCleanupChildren) _ANSI_ARGS_((Tcl_Interp * interp, int numPids, Tcl_Pid * pidPtr, Tcl_Channel errorChan)); /* 5 */
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
- void *reserved5;
-#endif /* MAC_TCL */
- void (*tclCleanupCommand) _ANSI_ARGS_((Command * cmdPtr)); /* 6 */
- int (*tclCopyAndCollapse) _ANSI_ARGS_((int count, CONST char * src, char * dst)); /* 7 */
- int (*tclCopyChannel) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel inChan, Tcl_Channel outChan, int toRead, Tcl_Obj * cmdPtr)); /* 8 */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
- int (*tclCreatePipeline) _ANSI_ARGS_((Tcl_Interp * interp, int argc, CONST char ** argv, Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr, TclFile * outPipePtr, TclFile * errFilePtr)); /* 9 */
-#endif /* UNIX */
-#ifdef __WIN32__
- int (*tclCreatePipeline) _ANSI_ARGS_((Tcl_Interp * interp, int argc, CONST char ** argv, Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr, TclFile * outPipePtr, TclFile * errFilePtr)); /* 9 */
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
- void *reserved9;
-#endif /* MAC_TCL */
- int (*tclCreateProc) _ANSI_ARGS_((Tcl_Interp * interp, Namespace * nsPtr, CONST char * procName, Tcl_Obj * argsPtr, Tcl_Obj * bodyPtr, Proc ** procPtrPtr)); /* 10 */
- void (*tclDeleteCompiledLocalVars) _ANSI_ARGS_((Interp * iPtr, CallFrame * framePtr)); /* 11 */
- void (*tclDeleteVars) _ANSI_ARGS_((Interp * iPtr, Tcl_HashTable * tablePtr)); /* 12 */
- int (*tclDoGlob) _ANSI_ARGS_((Tcl_Interp * interp, char * separators, Tcl_DString * headPtr, char * tail, Tcl_GlobTypeData * types)); /* 13 */
- void (*tclDumpMemoryInfo) _ANSI_ARGS_((FILE * outFile)); /* 14 */
- void *reserved15;
- void (*tclExprFloatError) _ANSI_ARGS_((Tcl_Interp * interp, double value)); /* 16 */
- void *reserved17;
- void *reserved18;
- void *reserved19;
- void *reserved20;
- void *reserved21;
- int (*tclFindElement) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * listStr, int listLength, CONST char ** elementPtr, CONST char ** nextPtr, int * sizePtr, int * bracePtr)); /* 22 */
- Proc * (*tclFindProc) _ANSI_ARGS_((Interp * iPtr, CONST char * procName)); /* 23 */
- int (*tclFormatInt) _ANSI_ARGS_((char * buffer, long n)); /* 24 */
- void (*tclFreePackageInfo) _ANSI_ARGS_((Interp * iPtr)); /* 25 */
- void *reserved26;
- int (*tclGetDate) _ANSI_ARGS_((char * p, Tcl_WideInt now, long zone, Tcl_WideInt * timePtr)); /* 27 */
- Tcl_Channel (*tclpGetDefaultStdChannel) _ANSI_ARGS_((int type)); /* 28 */
- void *reserved29;
- void *reserved30;
- char * (*tclGetExtension) _ANSI_ARGS_((char * name)); /* 31 */
- int (*tclGetFrame) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, CallFrame ** framePtrPtr)); /* 32 */
- TclCmdProcType (*tclGetInterpProc) _ANSI_ARGS_((void)); /* 33 */
- int (*tclGetIntForIndex) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, int endValue, int * indexPtr)); /* 34 */
- void *reserved35;
- int (*tclGetLong) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, long * longPtr)); /* 36 */
- int (*tclGetLoadedPackages) _ANSI_ARGS_((Tcl_Interp * interp, char * targetName)); /* 37 */
- int (*tclGetNamespaceForQualName) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * qualName, Namespace * cxtNsPtr, int flags, Namespace ** nsPtrPtr, Namespace ** altNsPtrPtr, Namespace ** actualCxtPtrPtr, CONST char ** simpleNamePtr)); /* 38 */
- TclObjCmdProcType (*tclGetObjInterpProc) _ANSI_ARGS_((void)); /* 39 */
- int (*tclGetOpenMode) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, int * seekFlagPtr)); /* 40 */
- Tcl_Command (*tclGetOriginalCommand) _ANSI_ARGS_((Tcl_Command command)); /* 41 */
- char * (*tclpGetUserHome) _ANSI_ARGS_((CONST char * name, Tcl_DString * bufferPtr)); /* 42 */
- int (*tclGlobalInvoke) _ANSI_ARGS_((Tcl_Interp * interp, int argc, CONST84 char ** argv, int flags)); /* 43 */
- int (*tclGuessPackageName) _ANSI_ARGS_((CONST char * fileName, Tcl_DString * bufPtr)); /* 44 */
- int (*tclHideUnsafeCommands) _ANSI_ARGS_((Tcl_Interp * interp)); /* 45 */
- int (*tclInExit) _ANSI_ARGS_((void)); /* 46 */
- void *reserved47;
- void *reserved48;
- Tcl_Obj * (*tclIncrVar2) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr, long incrAmount, int part1NotParsed)); /* 49 */
- void (*tclInitCompiledLocals) _ANSI_ARGS_((Tcl_Interp * interp, CallFrame * framePtr, Namespace * nsPtr)); /* 50 */
- int (*tclInterpInit) _ANSI_ARGS_((Tcl_Interp * interp)); /* 51 */
- int (*tclInvoke) _ANSI_ARGS_((Tcl_Interp * interp, int argc, CONST84 char ** argv, int flags)); /* 52 */
- int (*tclInvokeObjectCommand) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int argc, CONST84 char ** argv)); /* 53 */
- int (*tclInvokeStringCommand) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[])); /* 54 */
- Proc * (*tclIsProc) _ANSI_ARGS_((Command * cmdPtr)); /* 55 */
- void *reserved56;
- void *reserved57;
- Var * (*tclLookupVar) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * part1, CONST char * part2, int flags, CONST char * msg, int createPart1, int createPart2, Var ** arrayPtrPtr)); /* 58 */
- void *reserved59;
- int (*tclNeedSpace) _ANSI_ARGS_((CONST char * start, CONST char * end)); /* 60 */
- Tcl_Obj * (*tclNewProcBodyObj) _ANSI_ARGS_((Proc * procPtr)); /* 61 */
- int (*tclObjCommandComplete) _ANSI_ARGS_((Tcl_Obj * cmdPtr)); /* 62 */
- int (*tclObjInterpProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[])); /* 63 */
- int (*tclObjInvoke) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[], int flags)); /* 64 */
- int (*tclObjInvokeGlobal) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[], int flags)); /* 65 */
- int (*tclOpenFileChannelDeleteProc) _ANSI_ARGS_((TclOpenFileChannelProc_ * proc)); /* 66 */
- int (*tclOpenFileChannelInsertProc) _ANSI_ARGS_((TclOpenFileChannelProc_ * proc)); /* 67 */
- void *reserved68;
- char * (*tclpAlloc) _ANSI_ARGS_((unsigned int size)); /* 69 */
- void *reserved70;
- void *reserved71;
- void *reserved72;
- void *reserved73;
- void (*tclpFree) _ANSI_ARGS_((char * ptr)); /* 74 */
- unsigned long (*tclpGetClicks) _ANSI_ARGS_((void)); /* 75 */
- unsigned long (*tclpGetSeconds) _ANSI_ARGS_((void)); /* 76 */
- void (*tclpGetTime) _ANSI_ARGS_((Tcl_Time * time)); /* 77 */
- int (*tclpGetTimeZone) _ANSI_ARGS_((Tcl_WideInt time)); /* 78 */
- void *reserved79;
- void *reserved80;
- char * (*tclpRealloc) _ANSI_ARGS_((char * ptr, unsigned int size)); /* 81 */
- void *reserved82;
- void *reserved83;
- void *reserved84;
- void *reserved85;
- void *reserved86;
- void *reserved87;
- char * (*tclPrecTraceProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, CONST char * name1, CONST char * name2, int flags)); /* 88 */
- int (*tclPreventAliasLoop) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Interp * cmdInterp, Tcl_Command cmd)); /* 89 */
- void *reserved90;
- void (*tclProcCleanupProc) _ANSI_ARGS_((Proc * procPtr)); /* 91 */
- int (*tclProcCompileProc) _ANSI_ARGS_((Tcl_Interp * interp, Proc * procPtr, Tcl_Obj * bodyPtr, Namespace * nsPtr, CONST char * description, CONST char * procName)); /* 92 */
- void (*tclProcDeleteProc) _ANSI_ARGS_((ClientData clientData)); /* 93 */
- int (*tclProcInterpProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int argc, CONST84 char ** argv)); /* 94 */
- void *reserved95;
- int (*tclRenameCommand) _ANSI_ARGS_((Tcl_Interp * interp, char * oldName, char * newName)); /* 96 */
- void (*tclResetShadowedCmdRefs) _ANSI_ARGS_((Tcl_Interp * interp, Command * newCmdPtr)); /* 97 */
- int (*tclServiceIdle) _ANSI_ARGS_((void)); /* 98 */
- void *reserved99;
- void *reserved100;
- char * (*tclSetPreInitScript) _ANSI_ARGS_((char * string)); /* 101 */
- void (*tclSetupEnv) _ANSI_ARGS_((Tcl_Interp * interp)); /* 102 */
- int (*tclSockGetPort) _ANSI_ARGS_((Tcl_Interp * interp, char * str, char * proto, int * portPtr)); /* 103 */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
- int (*tclSockMinimumBuffers) _ANSI_ARGS_((int sock, int size)); /* 104 */
-#endif /* UNIX */
-#ifdef __WIN32__
- int (*tclSockMinimumBuffers) _ANSI_ARGS_((int sock, int size)); /* 104 */
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
- void *reserved104;
-#endif /* MAC_TCL */
- void *reserved105;
- int (*tclStatDeleteProc) _ANSI_ARGS_((TclStatProc_ * proc)); /* 106 */
- int (*tclStatInsertProc) _ANSI_ARGS_((TclStatProc_ * proc)); /* 107 */
- void (*tclTeardownNamespace) _ANSI_ARGS_((Namespace * nsPtr)); /* 108 */
- int (*tclUpdateReturnInfo) _ANSI_ARGS_((Interp * iPtr)); /* 109 */
- void *reserved110;
- void (*tcl_AddInterpResolvers) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, Tcl_ResolveCmdProc * cmdProc, Tcl_ResolveVarProc * varProc, Tcl_ResolveCompiledVarProc * compiledVarProc)); /* 111 */
- int (*tcl_AppendExportList) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Namespace * nsPtr, Tcl_Obj * objPtr)); /* 112 */
- Tcl_Namespace * (*tcl_CreateNamespace) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, ClientData clientData, Tcl_NamespaceDeleteProc * deleteProc)); /* 113 */
- void (*tcl_DeleteNamespace) _ANSI_ARGS_((Tcl_Namespace * nsPtr)); /* 114 */
- int (*tcl_Export) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Namespace * nsPtr, CONST char * pattern, int resetListFirst)); /* 115 */
- Tcl_Command (*tcl_FindCommand) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, Tcl_Namespace * contextNsPtr, int flags)); /* 116 */
- Tcl_Namespace * (*tcl_FindNamespace) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, Tcl_Namespace * contextNsPtr, int flags)); /* 117 */
- int (*tcl_GetInterpResolvers) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, Tcl_ResolverInfo * resInfo)); /* 118 */
- int (*tcl_GetNamespaceResolvers) _ANSI_ARGS_((Tcl_Namespace * namespacePtr, Tcl_ResolverInfo * resInfo)); /* 119 */
- Tcl_Var (*tcl_FindNamespaceVar) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, Tcl_Namespace * contextNsPtr, int flags)); /* 120 */
- int (*tcl_ForgetImport) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Namespace * nsPtr, CONST char * pattern)); /* 121 */
- Tcl_Command (*tcl_GetCommandFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr)); /* 122 */
- void (*tcl_GetCommandFullName) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Command command, Tcl_Obj * objPtr)); /* 123 */
- Tcl_Namespace * (*tcl_GetCurrentNamespace) _ANSI_ARGS_((Tcl_Interp * interp)); /* 124 */
- Tcl_Namespace * (*tcl_GetGlobalNamespace) _ANSI_ARGS_((Tcl_Interp * interp)); /* 125 */
- void (*tcl_GetVariableFullName) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Var variable, Tcl_Obj * objPtr)); /* 126 */
- int (*tcl_Import) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Namespace * nsPtr, CONST char * pattern, int allowOverwrite)); /* 127 */
- void (*tcl_PopCallFrame) _ANSI_ARGS_((Tcl_Interp* interp)); /* 128 */
- int (*tcl_PushCallFrame) _ANSI_ARGS_((Tcl_Interp* interp, Tcl_CallFrame * framePtr, Tcl_Namespace * nsPtr, int isProcCallFrame)); /* 129 */
- int (*tcl_RemoveInterpResolvers) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name)); /* 130 */
- void (*tcl_SetNamespaceResolvers) _ANSI_ARGS_((Tcl_Namespace * namespacePtr, Tcl_ResolveCmdProc * cmdProc, Tcl_ResolveVarProc * varProc, Tcl_ResolveCompiledVarProc * compiledVarProc)); /* 131 */
- int (*tclpHasSockets) _ANSI_ARGS_((Tcl_Interp * interp)); /* 132 */
- struct tm * (*tclpGetDate) _ANSI_ARGS_((TclpTime_t time, int useGMT)); /* 133 */
- size_t (*tclpStrftime) _ANSI_ARGS_((char * s, size_t maxsize, CONST char * format, CONST struct tm * t, int useGMT)); /* 134 */
- int (*tclpCheckStackSpace) _ANSI_ARGS_((void)); /* 135 */
- void *reserved136;
- void *reserved137;
- CONST84_RETURN char * (*tclGetEnv) _ANSI_ARGS_((CONST char * name, Tcl_DString * valuePtr)); /* 138 */
- void *reserved139;
- int (*tclLooksLikeInt) _ANSI_ARGS_((CONST char * bytes, int length)); /* 140 */
- CONST84_RETURN char * (*tclpGetCwd) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_DString * cwdPtr)); /* 141 */
- int (*tclSetByteCodeFromAny) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, CompileHookProc * hookProc, ClientData clientData)); /* 142 */
- int (*tclAddLiteralObj) _ANSI_ARGS_((struct CompileEnv * envPtr, Tcl_Obj * objPtr, LiteralEntry ** litPtrPtr)); /* 143 */
- void (*tclHideLiteral) _ANSI_ARGS_((Tcl_Interp * interp, struct CompileEnv * envPtr, int index)); /* 144 */
- struct AuxDataType * (*tclGetAuxDataType) _ANSI_ARGS_((char * typeName)); /* 145 */
- TclHandle (*tclHandleCreate) _ANSI_ARGS_((VOID * ptr)); /* 146 */
- void (*tclHandleFree) _ANSI_ARGS_((TclHandle handle)); /* 147 */
- TclHandle (*tclHandlePreserve) _ANSI_ARGS_((TclHandle handle)); /* 148 */
- void (*tclHandleRelease) _ANSI_ARGS_((TclHandle handle)); /* 149 */
- int (*tclRegAbout) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_RegExp re)); /* 150 */
- void (*tclRegExpRangeUniChar) _ANSI_ARGS_((Tcl_RegExp re, int index, int * startPtr, int * endPtr)); /* 151 */
- void (*tclSetLibraryPath) _ANSI_ARGS_((Tcl_Obj * pathPtr)); /* 152 */
- Tcl_Obj * (*tclGetLibraryPath) _ANSI_ARGS_((void)); /* 153 */
- void *reserved154;
- void *reserved155;
- void (*tclRegError) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * msg, int status)); /* 156 */
- Var * (*tclVarTraceExists) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * varName)); /* 157 */
- void (*tclSetStartupScriptFileName) _ANSI_ARGS_((CONST char * filename)); /* 158 */
- CONST84_RETURN char * (*tclGetStartupScriptFileName) _ANSI_ARGS_((void)); /* 159 */
- void *reserved160;
- int (*tclChannelTransform) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan, Tcl_Obj * cmdObjPtr)); /* 161 */
- void (*tclChannelEventScriptInvoker) _ANSI_ARGS_((ClientData clientData, int flags)); /* 162 */
- VOID * (*tclGetInstructionTable) _ANSI_ARGS_((void)); /* 163 */
- void (*tclExpandCodeArray) _ANSI_ARGS_((VOID * envPtr)); /* 164 */
- void (*tclpSetInitialEncodings) _ANSI_ARGS_((void)); /* 165 */
- int (*tclListObjSetElement) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * listPtr, int index, Tcl_Obj * valuePtr)); /* 166 */
- void (*tclSetStartupScriptPath) _ANSI_ARGS_((Tcl_Obj * pathPtr)); /* 167 */
- Tcl_Obj * (*tclGetStartupScriptPath) _ANSI_ARGS_((void)); /* 168 */
- int (*tclpUtfNcmp2) _ANSI_ARGS_((CONST char * s1, CONST char * s2, unsigned long n)); /* 169 */
- int (*tclCheckInterpTraces) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * command, int numChars, Command * cmdPtr, int result, int traceFlags, int objc, Tcl_Obj *CONST objv[])); /* 170 */
- int (*tclCheckExecutionTraces) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * command, int numChars, Command * cmdPtr, int result, int traceFlags, int objc, Tcl_Obj *CONST objv[])); /* 171 */
- int (*tclInThreadExit) _ANSI_ARGS_((void)); /* 172 */
- int (*tclUniCharMatch) _ANSI_ARGS_((CONST Tcl_UniChar * string, int strLen, CONST Tcl_UniChar * pattern, int ptnLen, int nocase)); /* 173 */
- void *reserved174;
- void *reserved175;
- void *reserved176;
- void *reserved177;
- void *reserved178;
- void *reserved179;
- void *reserved180;
- void *reserved181;
- struct tm * (*tclpLocaltime) _ANSI_ARGS_((TclpTime_t_CONST clock)); /* 182 */
- struct tm * (*tclpGmtime) _ANSI_ARGS_((TclpTime_t_CONST clock)); /* 183 */
- void *reserved184;
- void *reserved185;
- void *reserved186;
- void *reserved187;
- void *reserved188;
- void *reserved189;
- void *reserved190;
- void *reserved191;
- void *reserved192;
- void *reserved193;
- void *reserved194;
- void *reserved195;
- void *reserved196;
- void *reserved197;
- void *reserved198;
- int (*tclMatchIsTrivial) _ANSI_ARGS_((CONST char * pattern)); /* 199 */
+ VOID *reserved0;
+ VOID *reserved1;
+ VOID *reserved2;
+ void (*tclAllocateFreeObjects) (void); /* 3 */
+ VOID *reserved4;
+ int (*tclCleanupChildren) (Tcl_Interp *interp, int numPids, Tcl_Pid *pidPtr, Tcl_Channel errorChan); /* 5 */
+ void (*tclCleanupCommand) (Command *cmdPtr); /* 6 */
+ int (*tclCopyAndCollapse) (int count, CONST char *src, char *dst); /* 7 */
+ int (*tclCopyChannel) (Tcl_Interp *interp, Tcl_Channel inChan, Tcl_Channel outChan, int toRead, Tcl_Obj *cmdPtr); /* 8 */
+ int (*tclCreatePipeline) (Tcl_Interp *interp, int argc, CONST char **argv, Tcl_Pid **pidArrayPtr, TclFile *inPipePtr, TclFile *outPipePtr, TclFile *errFilePtr); /* 9 */
+ int (*tclCreateProc) (Tcl_Interp *interp, Namespace *nsPtr, CONST char *procName, Tcl_Obj *argsPtr, Tcl_Obj *bodyPtr, Proc **procPtrPtr); /* 10 */
+ void (*tclDeleteCompiledLocalVars) (Interp *iPtr, CallFrame *framePtr); /* 11 */
+ void (*tclDeleteVars) (Interp *iPtr, TclVarHashTable *tablePtr); /* 12 */
+ VOID *reserved13;
+ int (*tclDumpMemoryInfo) (ClientData clientData, int flags); /* 14 */
+ VOID *reserved15;
+ void (*tclExprFloatError) (Tcl_Interp *interp, double value); /* 16 */
+ VOID *reserved17;
+ VOID *reserved18;
+ VOID *reserved19;
+ VOID *reserved20;
+ VOID *reserved21;
+ int (*tclFindElement) (Tcl_Interp *interp, CONST char *listStr, int listLength, CONST char **elementPtr, CONST char **nextPtr, int *sizePtr, int *bracePtr); /* 22 */
+ Proc * (*tclFindProc) (Interp *iPtr, CONST char *procName); /* 23 */
+ int (*tclFormatInt) (char *buffer, long n); /* 24 */
+ void (*tclFreePackageInfo) (Interp *iPtr); /* 25 */
+ VOID *reserved26;
+ VOID *reserved27;
+ Tcl_Channel (*tclpGetDefaultStdChannel) (int type); /* 28 */
+ VOID *reserved29;
+ VOID *reserved30;
+ CONST char * (*tclGetExtension) (CONST char *name); /* 31 */
+ int (*tclGetFrame) (Tcl_Interp *interp, CONST char *str, CallFrame **framePtrPtr); /* 32 */
+ VOID *reserved33;
+ int (*tclGetIntForIndex) (Tcl_Interp *interp, Tcl_Obj *objPtr, int endValue, int *indexPtr); /* 34 */
+ VOID *reserved35;
+ int (*tclGetLong) (Tcl_Interp *interp, CONST char *str, long *longPtr); /* 36 */
+ int (*tclGetLoadedPackages) (Tcl_Interp *interp, char *targetName); /* 37 */
+ int (*tclGetNamespaceForQualName) (Tcl_Interp *interp, CONST char *qualName, Namespace *cxtNsPtr, int flags, Namespace **nsPtrPtr, Namespace **altNsPtrPtr, Namespace **actualCxtPtrPtr, CONST char **simpleNamePtr); /* 38 */
+ TclObjCmdProcType (*tclGetObjInterpProc) (void); /* 39 */
+ int (*tclGetOpenMode) (Tcl_Interp *interp, CONST char *str, int *seekFlagPtr); /* 40 */
+ Tcl_Command (*tclGetOriginalCommand) (Tcl_Command command); /* 41 */
+ char * (*tclpGetUserHome) (CONST char *name, Tcl_DString *bufferPtr); /* 42 */
+ VOID *reserved43;
+ int (*tclGuessPackageName) (CONST char *fileName, Tcl_DString *bufPtr); /* 44 */
+ int (*tclHideUnsafeCommands) (Tcl_Interp *interp); /* 45 */
+ int (*tclInExit) (void); /* 46 */
+ VOID *reserved47;
+ VOID *reserved48;
+ VOID *reserved49;
+ void (*tclInitCompiledLocals) (Tcl_Interp *interp, CallFrame *framePtr, Namespace *nsPtr); /* 50 */
+ int (*tclInterpInit) (Tcl_Interp *interp); /* 51 */
+ VOID *reserved52;
+ int (*tclInvokeObjectCommand) (ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char **argv); /* 53 */
+ int (*tclInvokeStringCommand) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); /* 54 */
+ Proc * (*tclIsProc) (Command *cmdPtr); /* 55 */
+ VOID *reserved56;
+ VOID *reserved57;
+ Var * (*tclLookupVar) (Tcl_Interp *interp, CONST char *part1, CONST char *part2, int flags, CONST char *msg, int createPart1, int createPart2, Var **arrayPtrPtr); /* 58 */
+ VOID *reserved59;
+ int (*tclNeedSpace) (CONST char *start, CONST char *end); /* 60 */
+ Tcl_Obj * (*tclNewProcBodyObj) (Proc *procPtr); /* 61 */
+ int (*tclObjCommandComplete) (Tcl_Obj *cmdPtr); /* 62 */
+ int (*tclObjInterpProc) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); /* 63 */
+ int (*tclObjInvoke) (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int flags); /* 64 */
+ VOID *reserved65;
+ VOID *reserved66;
+ VOID *reserved67;
+ VOID *reserved68;
+ char * (*tclpAlloc) (unsigned int size); /* 69 */
+ VOID *reserved70;
+ VOID *reserved71;
+ VOID *reserved72;
+ VOID *reserved73;
+ void (*tclpFree) (char *ptr); /* 74 */
+ unsigned long (*tclpGetClicks) (void); /* 75 */
+ unsigned long (*tclpGetSeconds) (void); /* 76 */
+ void (*tclpGetTime) (Tcl_Time *time); /* 77 */
+ int (*tclpGetTimeZone) (unsigned long time); /* 78 */
+ VOID *reserved79;
+ VOID *reserved80;
+ char * (*tclpRealloc) (char *ptr, unsigned int size); /* 81 */
+ VOID *reserved82;
+ VOID *reserved83;
+ VOID *reserved84;
+ VOID *reserved85;
+ VOID *reserved86;
+ VOID *reserved87;
+ char * (*tclPrecTraceProc) (ClientData clientData, Tcl_Interp *interp, CONST char *name1, CONST char *name2, int flags); /* 88 */
+ int (*tclPreventAliasLoop) (Tcl_Interp *interp, Tcl_Interp *cmdInterp, Tcl_Command cmd); /* 89 */
+ VOID *reserved90;
+ void (*tclProcCleanupProc) (Proc *procPtr); /* 91 */
+ int (*tclProcCompileProc) (Tcl_Interp *interp, Proc *procPtr, Tcl_Obj *bodyPtr, Namespace *nsPtr, CONST char *description, CONST char *procName); /* 92 */
+ void (*tclProcDeleteProc) (ClientData clientData); /* 93 */
+ VOID *reserved94;
+ VOID *reserved95;
+ int (*tclRenameCommand) (Tcl_Interp *interp, CONST char *oldName, CONST char *newName); /* 96 */
+ void (*tclResetShadowedCmdRefs) (Tcl_Interp *interp, Command *newCmdPtr); /* 97 */
+ int (*tclServiceIdle) (void); /* 98 */
+ VOID *reserved99;
+ VOID *reserved100;
+ char * (*tclSetPreInitScript) (char *string); /* 101 */
+ void (*tclSetupEnv) (Tcl_Interp *interp); /* 102 */
+ int (*tclSockGetPort) (Tcl_Interp *interp, CONST char *str, CONST char *proto, int *portPtr); /* 103 */
+ int (*tclSockMinimumBuffers) (int sock, int size); /* 104 */
+ VOID *reserved105;
+ VOID *reserved106;
+ VOID *reserved107;
+ void (*tclTeardownNamespace) (Namespace *nsPtr); /* 108 */
+ int (*tclUpdateReturnInfo) (Interp *iPtr); /* 109 */
+ VOID *reserved110;
+ void (*tcl_AddInterpResolvers) (Tcl_Interp *interp, CONST char *name, Tcl_ResolveCmdProc *cmdProc, Tcl_ResolveVarProc *varProc, Tcl_ResolveCompiledVarProc *compiledVarProc); /* 111 */
+ int (*tcl_AppendExportList) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, Tcl_Obj *objPtr); /* 112 */
+ Tcl_Namespace * (*tcl_CreateNamespace) (Tcl_Interp *interp, CONST char *name, ClientData clientData, Tcl_NamespaceDeleteProc *deleteProc); /* 113 */
+ void (*tcl_DeleteNamespace) (Tcl_Namespace *nsPtr); /* 114 */
+ int (*tcl_Export) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, CONST char *pattern, int resetListFirst); /* 115 */
+ Tcl_Command (*tcl_FindCommand) (Tcl_Interp *interp, CONST char *name, Tcl_Namespace *contextNsPtr, int flags); /* 116 */
+ Tcl_Namespace * (*tcl_FindNamespace) (Tcl_Interp *interp, CONST char *name, Tcl_Namespace *contextNsPtr, int flags); /* 117 */
+ int (*tcl_GetInterpResolvers) (Tcl_Interp *interp, CONST char *name, Tcl_ResolverInfo *resInfo); /* 118 */
+ int (*tcl_GetNamespaceResolvers) (Tcl_Namespace *namespacePtr, Tcl_ResolverInfo *resInfo); /* 119 */
+ Tcl_Var (*tcl_FindNamespaceVar) (Tcl_Interp *interp, CONST char *name, Tcl_Namespace *contextNsPtr, int flags); /* 120 */
+ int (*tcl_ForgetImport) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, CONST char *pattern); /* 121 */
+ Tcl_Command (*tcl_GetCommandFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 122 */
+ void (*tcl_GetCommandFullName) (Tcl_Interp *interp, Tcl_Command command, Tcl_Obj *objPtr); /* 123 */
+ Tcl_Namespace * (*tcl_GetCurrentNamespace) (Tcl_Interp *interp); /* 124 */
+ Tcl_Namespace * (*tcl_GetGlobalNamespace) (Tcl_Interp *interp); /* 125 */
+ void (*tcl_GetVariableFullName) (Tcl_Interp *interp, Tcl_Var variable, Tcl_Obj *objPtr); /* 126 */
+ int (*tcl_Import) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, CONST char *pattern, int allowOverwrite); /* 127 */
+ void (*tcl_PopCallFrame) (Tcl_Interp *interp); /* 128 */
+ int (*tcl_PushCallFrame) (Tcl_Interp *interp, Tcl_CallFrame *framePtr, Tcl_Namespace *nsPtr, int isProcCallFrame); /* 129 */
+ int (*tcl_RemoveInterpResolvers) (Tcl_Interp *interp, CONST char *name); /* 130 */
+ void (*tcl_SetNamespaceResolvers) (Tcl_Namespace *namespacePtr, Tcl_ResolveCmdProc *cmdProc, Tcl_ResolveVarProc *varProc, Tcl_ResolveCompiledVarProc *compiledVarProc); /* 131 */
+ int (*tclpHasSockets) (Tcl_Interp *interp); /* 132 */
+ struct tm * (*tclpGetDate) (CONST time_t *time, int useGMT); /* 133 */
+ VOID *reserved134;
+ VOID *reserved135;
+ VOID *reserved136;
+ VOID *reserved137;
+ CONST84_RETURN char * (*tclGetEnv) (CONST char *name, Tcl_DString *valuePtr); /* 138 */
+ VOID *reserved139;
+ VOID *reserved140;
+ CONST84_RETURN char * (*tclpGetCwd) (Tcl_Interp *interp, Tcl_DString *cwdPtr); /* 141 */
+ int (*tclSetByteCodeFromAny) (Tcl_Interp *interp, Tcl_Obj *objPtr, CompileHookProc *hookProc, ClientData clientData); /* 142 */
+ int (*tclAddLiteralObj) (struct CompileEnv *envPtr, Tcl_Obj *objPtr, LiteralEntry **litPtrPtr); /* 143 */
+ void (*tclHideLiteral) (Tcl_Interp *interp, struct CompileEnv *envPtr, int index); /* 144 */
+ struct AuxDataType * (*tclGetAuxDataType) (char *typeName); /* 145 */
+ TclHandle (*tclHandleCreate) (VOID *ptr); /* 146 */
+ void (*tclHandleFree) (TclHandle handle); /* 147 */
+ TclHandle (*tclHandlePreserve) (TclHandle handle); /* 148 */
+ void (*tclHandleRelease) (TclHandle handle); /* 149 */
+ int (*tclRegAbout) (Tcl_Interp *interp, Tcl_RegExp re); /* 150 */
+ void (*tclRegExpRangeUniChar) (Tcl_RegExp re, int index, int *startPtr, int *endPtr); /* 151 */
+ void (*tclSetLibraryPath) (Tcl_Obj *pathPtr); /* 152 */
+ Tcl_Obj * (*tclGetLibraryPath) (void); /* 153 */
+ VOID *reserved154;
+ VOID *reserved155;
+ void (*tclRegError) (Tcl_Interp *interp, CONST char *msg, int status); /* 156 */
+ Var * (*tclVarTraceExists) (Tcl_Interp *interp, CONST char *varName); /* 157 */
+ void (*tclSetStartupScriptFileName) (CONST char *filename); /* 158 */
+ CONST84_RETURN char * (*tclGetStartupScriptFileName) (void); /* 159 */
+ VOID *reserved160;
+ int (*tclChannelTransform) (Tcl_Interp *interp, Tcl_Channel chan, Tcl_Obj *cmdObjPtr); /* 161 */
+ void (*tclChannelEventScriptInvoker) (ClientData clientData, int flags); /* 162 */
+ VOID * (*tclGetInstructionTable) (void); /* 163 */
+ void (*tclExpandCodeArray) (VOID *envPtr); /* 164 */
+ void (*tclpSetInitialEncodings) (void); /* 165 */
+ int (*tclListObjSetElement) (Tcl_Interp *interp, Tcl_Obj *listPtr, int index, Tcl_Obj *valuePtr); /* 166 */
+ void (*tclSetStartupScriptPath) (Tcl_Obj *pathPtr); /* 167 */
+ Tcl_Obj * (*tclGetStartupScriptPath) (void); /* 168 */
+ int (*tclpUtfNcmp2) (CONST char *s1, CONST char *s2, unsigned long n); /* 169 */
+ int (*tclCheckInterpTraces) (Tcl_Interp *interp, CONST char *command, int numChars, Command *cmdPtr, int result, int traceFlags, int objc, Tcl_Obj *CONST objv[]); /* 170 */
+ int (*tclCheckExecutionTraces) (Tcl_Interp *interp, CONST char *command, int numChars, Command *cmdPtr, int result, int traceFlags, int objc, Tcl_Obj *CONST objv[]); /* 171 */
+ int (*tclInThreadExit) (void); /* 172 */
+ int (*tclUniCharMatch) (CONST Tcl_UniChar *string, int strLen, CONST Tcl_UniChar *pattern, int ptnLen, int flags); /* 173 */
+ VOID *reserved174;
+ int (*tclCallVarTraces) (Interp *iPtr, Var *arrayPtr, Var *varPtr, CONST char *part1, CONST char *part2, int flags, int leaveErrMsg); /* 175 */
+ void (*tclCleanupVar) (Var *varPtr, Var *arrayPtr); /* 176 */
+ void (*tclVarErrMsg) (Tcl_Interp *interp, CONST char *part1, CONST char *part2, CONST char *operation, CONST char *reason); /* 177 */
+ void (*tcl_SetStartupScript) (Tcl_Obj *pathPtr, CONST char*encodingName); /* 178 */
+ Tcl_Obj * (*tcl_GetStartupScript) (CONST char **encodingNamePtr); /* 179 */
+ VOID *reserved180;
+ VOID *reserved181;
+ struct tm * (*tclpLocaltime) (CONST time_t *clock); /* 182 */
+ struct tm * (*tclpGmtime) (CONST time_t *clock); /* 183 */
+ VOID *reserved184;
+ VOID *reserved185;
+ VOID *reserved186;
+ VOID *reserved187;
+ VOID *reserved188;
+ VOID *reserved189;
+ VOID *reserved190;
+ VOID *reserved191;
+ VOID *reserved192;
+ VOID *reserved193;
+ VOID *reserved194;
+ VOID *reserved195;
+ VOID *reserved196;
+ VOID *reserved197;
+ int (*tclObjGetFrame) (Tcl_Interp *interp, Tcl_Obj *objPtr, CallFrame **framePtrPtr); /* 198 */
+ VOID *reserved199;
+ int (*tclpObjRemoveDirectory) (Tcl_Obj *pathPtr, int recursive, Tcl_Obj **errorPtr); /* 200 */
+ int (*tclpObjCopyDirectory) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr, Tcl_Obj **errorPtr); /* 201 */
+ int (*tclpObjCreateDirectory) (Tcl_Obj *pathPtr); /* 202 */
+ int (*tclpObjDeleteFile) (Tcl_Obj *pathPtr); /* 203 */
+ int (*tclpObjCopyFile) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr); /* 204 */
+ int (*tclpObjRenameFile) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr); /* 205 */
+ int (*tclpObjStat) (Tcl_Obj *pathPtr, Tcl_StatBuf *buf); /* 206 */
+ int (*tclpObjAccess) (Tcl_Obj *pathPtr, int mode); /* 207 */
+ Tcl_Channel (*tclpOpenFileChannel) (Tcl_Interp *interp, Tcl_Obj *pathPtr, int mode, int permissions); /* 208 */
+ VOID *reserved209;
+ VOID *reserved210;
+ VOID *reserved211;
+ void (*tclpFindExecutable) (CONST char *argv0); /* 212 */
+ Tcl_Obj * (*tclGetObjNameOfExecutable) (void); /* 213 */
+ void (*tclSetObjNameOfExecutable) (Tcl_Obj *name, Tcl_Encoding encoding); /* 214 */
+ VOID * (*tclStackAlloc) (Tcl_Interp *interp, int numBytes); /* 215 */
+ void (*tclStackFree) (Tcl_Interp *interp, VOID *freePtr); /* 216 */
+ int (*tclPushStackFrame) (Tcl_Interp *interp, Tcl_CallFrame **framePtrPtr, Tcl_Namespace *namespacePtr, int isProcCallFrame); /* 217 */
+ void (*tclPopStackFrame) (Tcl_Interp *interp); /* 218 */
+ VOID *reserved219;
+ VOID *reserved220;
+ VOID *reserved221;
+ VOID *reserved222;
+ VOID *reserved223;
+ TclPlatformType * (*tclGetPlatform) (void); /* 224 */
+ Tcl_Obj * (*tclTraceDictPath) (Tcl_Interp *interp, Tcl_Obj *rootPtr, int keyc, Tcl_Obj *CONST keyv[], int flags); /* 225 */
+ int (*tclObjBeingDeleted) (Tcl_Obj *objPtr); /* 226 */
+ void (*tclSetNsPath) (Namespace *nsPtr, int pathLength, Tcl_Namespace *pathAry[]); /* 227 */
+ int (*tclObjInterpProcCore) (register Tcl_Interp *interp, Tcl_Obj *procNameObj, int skip, ProcErrorProc errorProc); /* 228 */
+ int (*tclPtrMakeUpvar) (Tcl_Interp *interp, Var *otherP1Ptr, CONST char *myName, int myFlags, int index); /* 229 */
+ Var * (*tclObjLookupVar) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, CONST char *part2, int flags, CONST char *msg, CONST int createPart1, CONST int createPart2, Var **arrayPtrPtr); /* 230 */
+ int (*tclGetNamespaceFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Namespace **nsPtrPtr); /* 231 */
+ int (*tclEvalObjEx) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags, CONST CmdFrame *invoker, int word); /* 232 */
+ void (*tclGetSrcInfoForPc) (CmdFrame *contextPtr); /* 233 */
+ Var * (*tclVarHashCreateVar) (TclVarHashTable *tablePtr, CONST char *key, int *newPtr); /* 234 */
+ void (*tclInitVarHashTable) (TclVarHashTable *tablePtr, Namespace *nsPtr); /* 235 */
+ void (*tclBackgroundException) (Tcl_Interp *interp, int code); /* 236 */
+ VOID *reserved237;
+ VOID *reserved238;
+ VOID *reserved239;
+ VOID *reserved240;
+ VOID *reserved241;
+ VOID *reserved242;
+ void (*tclDbDumpActiveObjects) (FILE *outFile); /* 243 */
+ VOID *reserved244;
+ VOID *reserved245;
+ VOID *reserved246;
+ VOID *reserved247;
+ VOID *reserved248;
+ char* (*tclDoubleDigits) (double dv, int ndigits, int flags, int*decpt, int*signum, char**endPtr); /* 249 */
} TclIntStubs;
#ifdef __cplusplus
@@ -776,31 +1321,17 @@ extern TclIntStubs *tclIntStubsPtr;
*/
/* Slot 0 is reserved */
-#ifndef TclAccessDeleteProc
-#define TclAccessDeleteProc \
- (tclIntStubsPtr->tclAccessDeleteProc) /* 1 */
-#endif
-#ifndef TclAccessInsertProc
-#define TclAccessInsertProc \
- (tclIntStubsPtr->tclAccessInsertProc) /* 2 */
-#endif
+/* Slot 1 is reserved */
+/* Slot 2 is reserved */
#ifndef TclAllocateFreeObjects
#define TclAllocateFreeObjects \
(tclIntStubsPtr->tclAllocateFreeObjects) /* 3 */
#endif
/* Slot 4 is reserved */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
-#ifndef TclCleanupChildren
-#define TclCleanupChildren \
- (tclIntStubsPtr->tclCleanupChildren) /* 5 */
-#endif
-#endif /* UNIX */
-#ifdef __WIN32__
#ifndef TclCleanupChildren
#define TclCleanupChildren \
(tclIntStubsPtr->tclCleanupChildren) /* 5 */
#endif
-#endif /* __WIN32__ */
#ifndef TclCleanupCommand
#define TclCleanupCommand \
(tclIntStubsPtr->tclCleanupCommand) /* 6 */
@@ -813,18 +1344,10 @@ extern TclIntStubs *tclIntStubsPtr;
#define TclCopyChannel \
(tclIntStubsPtr->tclCopyChannel) /* 8 */
#endif
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
#ifndef TclCreatePipeline
#define TclCreatePipeline \
(tclIntStubsPtr->tclCreatePipeline) /* 9 */
#endif
-#endif /* UNIX */
-#ifdef __WIN32__
-#ifndef TclCreatePipeline
-#define TclCreatePipeline \
- (tclIntStubsPtr->tclCreatePipeline) /* 9 */
-#endif
-#endif /* __WIN32__ */
#ifndef TclCreateProc
#define TclCreateProc \
(tclIntStubsPtr->tclCreateProc) /* 10 */
@@ -837,10 +1360,7 @@ extern TclIntStubs *tclIntStubsPtr;
#define TclDeleteVars \
(tclIntStubsPtr->tclDeleteVars) /* 12 */
#endif
-#ifndef TclDoGlob
-#define TclDoGlob \
- (tclIntStubsPtr->tclDoGlob) /* 13 */
-#endif
+/* Slot 13 is reserved */
#ifndef TclDumpMemoryInfo
#define TclDumpMemoryInfo \
(tclIntStubsPtr->tclDumpMemoryInfo) /* 14 */
@@ -872,10 +1392,7 @@ extern TclIntStubs *tclIntStubsPtr;
(tclIntStubsPtr->tclFreePackageInfo) /* 25 */
#endif
/* Slot 26 is reserved */
-#ifndef TclGetDate
-#define TclGetDate \
- (tclIntStubsPtr->tclGetDate) /* 27 */
-#endif
+/* Slot 27 is reserved */
#ifndef TclpGetDefaultStdChannel
#define TclpGetDefaultStdChannel \
(tclIntStubsPtr->tclpGetDefaultStdChannel) /* 28 */
@@ -890,10 +1407,7 @@ extern TclIntStubs *tclIntStubsPtr;
#define TclGetFrame \
(tclIntStubsPtr->tclGetFrame) /* 32 */
#endif
-#ifndef TclGetInterpProc
-#define TclGetInterpProc \
- (tclIntStubsPtr->tclGetInterpProc) /* 33 */
-#endif
+/* Slot 33 is reserved */
#ifndef TclGetIntForIndex
#define TclGetIntForIndex \
(tclIntStubsPtr->tclGetIntForIndex) /* 34 */
@@ -927,10 +1441,7 @@ extern TclIntStubs *tclIntStubsPtr;
#define TclpGetUserHome \
(tclIntStubsPtr->tclpGetUserHome) /* 42 */
#endif
-#ifndef TclGlobalInvoke
-#define TclGlobalInvoke \
- (tclIntStubsPtr->tclGlobalInvoke) /* 43 */
-#endif
+/* Slot 43 is reserved */
#ifndef TclGuessPackageName
#define TclGuessPackageName \
(tclIntStubsPtr->tclGuessPackageName) /* 44 */
@@ -945,10 +1456,7 @@ extern TclIntStubs *tclIntStubsPtr;
#endif
/* Slot 47 is reserved */
/* Slot 48 is reserved */
-#ifndef TclIncrVar2
-#define TclIncrVar2 \
- (tclIntStubsPtr->tclIncrVar2) /* 49 */
-#endif
+/* Slot 49 is reserved */
#ifndef TclInitCompiledLocals
#define TclInitCompiledLocals \
(tclIntStubsPtr->tclInitCompiledLocals) /* 50 */
@@ -957,10 +1465,7 @@ extern TclIntStubs *tclIntStubsPtr;
#define TclInterpInit \
(tclIntStubsPtr->tclInterpInit) /* 51 */
#endif
-#ifndef TclInvoke
-#define TclInvoke \
- (tclIntStubsPtr->tclInvoke) /* 52 */
-#endif
+/* Slot 52 is reserved */
#ifndef TclInvokeObjectCommand
#define TclInvokeObjectCommand \
(tclIntStubsPtr->tclInvokeObjectCommand) /* 53 */
@@ -1000,18 +1505,9 @@ extern TclIntStubs *tclIntStubsPtr;
#define TclObjInvoke \
(tclIntStubsPtr->tclObjInvoke) /* 64 */
#endif
-#ifndef TclObjInvokeGlobal
-#define TclObjInvokeGlobal \
- (tclIntStubsPtr->tclObjInvokeGlobal) /* 65 */
-#endif
-#ifndef TclOpenFileChannelDeleteProc
-#define TclOpenFileChannelDeleteProc \
- (tclIntStubsPtr->tclOpenFileChannelDeleteProc) /* 66 */
-#endif
-#ifndef TclOpenFileChannelInsertProc
-#define TclOpenFileChannelInsertProc \
- (tclIntStubsPtr->tclOpenFileChannelInsertProc) /* 67 */
-#endif
+/* Slot 65 is reserved */
+/* Slot 66 is reserved */
+/* Slot 67 is reserved */
/* Slot 68 is reserved */
#ifndef TclpAlloc
#define TclpAlloc \
@@ -1074,10 +1570,7 @@ extern TclIntStubs *tclIntStubsPtr;
#define TclProcDeleteProc \
(tclIntStubsPtr->tclProcDeleteProc) /* 93 */
#endif
-#ifndef TclProcInterpProc
-#define TclProcInterpProc \
- (tclIntStubsPtr->tclProcInterpProc) /* 94 */
-#endif
+/* Slot 94 is reserved */
/* Slot 95 is reserved */
#ifndef TclRenameCommand
#define TclRenameCommand \
@@ -1105,27 +1598,13 @@ extern TclIntStubs *tclIntStubsPtr;
#define TclSockGetPort \
(tclIntStubsPtr->tclSockGetPort) /* 103 */
#endif
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
-#ifndef TclSockMinimumBuffers
-#define TclSockMinimumBuffers \
- (tclIntStubsPtr->tclSockMinimumBuffers) /* 104 */
-#endif
-#endif /* UNIX */
-#ifdef __WIN32__
#ifndef TclSockMinimumBuffers
#define TclSockMinimumBuffers \
(tclIntStubsPtr->tclSockMinimumBuffers) /* 104 */
#endif
-#endif /* __WIN32__ */
/* Slot 105 is reserved */
-#ifndef TclStatDeleteProc
-#define TclStatDeleteProc \
- (tclIntStubsPtr->tclStatDeleteProc) /* 106 */
-#endif
-#ifndef TclStatInsertProc
-#define TclStatInsertProc \
- (tclIntStubsPtr->tclStatInsertProc) /* 107 */
-#endif
+/* Slot 106 is reserved */
+/* Slot 107 is reserved */
#ifndef TclTeardownNamespace
#define TclTeardownNamespace \
(tclIntStubsPtr->tclTeardownNamespace) /* 108 */
@@ -1227,14 +1706,8 @@ extern TclIntStubs *tclIntStubsPtr;
#define TclpGetDate \
(tclIntStubsPtr->tclpGetDate) /* 133 */
#endif
-#ifndef TclpStrftime
-#define TclpStrftime \
- (tclIntStubsPtr->tclpStrftime) /* 134 */
-#endif
-#ifndef TclpCheckStackSpace
-#define TclpCheckStackSpace \
- (tclIntStubsPtr->tclpCheckStackSpace) /* 135 */
-#endif
+/* Slot 134 is reserved */
+/* Slot 135 is reserved */
/* Slot 136 is reserved */
/* Slot 137 is reserved */
#ifndef TclGetEnv
@@ -1242,10 +1715,7 @@ extern TclIntStubs *tclIntStubsPtr;
(tclIntStubsPtr->tclGetEnv) /* 138 */
#endif
/* Slot 139 is reserved */
-#ifndef TclLooksLikeInt
-#define TclLooksLikeInt \
- (tclIntStubsPtr->tclLooksLikeInt) /* 140 */
-#endif
+/* Slot 140 is reserved */
#ifndef TclpGetCwd
#define TclpGetCwd \
(tclIntStubsPtr->tclpGetCwd) /* 141 */
@@ -1370,11 +1840,26 @@ extern TclIntStubs *tclIntStubsPtr;
(tclIntStubsPtr->tclUniCharMatch) /* 173 */
#endif
/* Slot 174 is reserved */
-/* Slot 175 is reserved */
-/* Slot 176 is reserved */
-/* Slot 177 is reserved */
-/* Slot 178 is reserved */
-/* Slot 179 is reserved */
+#ifndef TclCallVarTraces
+#define TclCallVarTraces \
+ (tclIntStubsPtr->tclCallVarTraces) /* 175 */
+#endif
+#ifndef TclCleanupVar
+#define TclCleanupVar \
+ (tclIntStubsPtr->tclCleanupVar) /* 176 */
+#endif
+#ifndef TclVarErrMsg
+#define TclVarErrMsg \
+ (tclIntStubsPtr->tclVarErrMsg) /* 177 */
+#endif
+#ifndef Tcl_SetStartupScript
+#define Tcl_SetStartupScript \
+ (tclIntStubsPtr->tcl_SetStartupScript) /* 178 */
+#endif
+#ifndef Tcl_GetStartupScript
+#define Tcl_GetStartupScript \
+ (tclIntStubsPtr->tcl_GetStartupScript) /* 179 */
+#endif
/* Slot 180 is reserved */
/* Slot 181 is reserved */
#ifndef TclpLocaltime
@@ -1399,14 +1884,160 @@ extern TclIntStubs *tclIntStubsPtr;
/* Slot 195 is reserved */
/* Slot 196 is reserved */
/* Slot 197 is reserved */
-/* Slot 198 is reserved */
-#ifndef TclMatchIsTrivial
-#define TclMatchIsTrivial \
- (tclIntStubsPtr->tclMatchIsTrivial) /* 199 */
+#ifndef TclObjGetFrame
+#define TclObjGetFrame \
+ (tclIntStubsPtr->tclObjGetFrame) /* 198 */
+#endif
+/* Slot 199 is reserved */
+#ifndef TclpObjRemoveDirectory
+#define TclpObjRemoveDirectory \
+ (tclIntStubsPtr->tclpObjRemoveDirectory) /* 200 */
+#endif
+#ifndef TclpObjCopyDirectory
+#define TclpObjCopyDirectory \
+ (tclIntStubsPtr->tclpObjCopyDirectory) /* 201 */
+#endif
+#ifndef TclpObjCreateDirectory
+#define TclpObjCreateDirectory \
+ (tclIntStubsPtr->tclpObjCreateDirectory) /* 202 */
+#endif
+#ifndef TclpObjDeleteFile
+#define TclpObjDeleteFile \
+ (tclIntStubsPtr->tclpObjDeleteFile) /* 203 */
+#endif
+#ifndef TclpObjCopyFile
+#define TclpObjCopyFile \
+ (tclIntStubsPtr->tclpObjCopyFile) /* 204 */
+#endif
+#ifndef TclpObjRenameFile
+#define TclpObjRenameFile \
+ (tclIntStubsPtr->tclpObjRenameFile) /* 205 */
+#endif
+#ifndef TclpObjStat
+#define TclpObjStat \
+ (tclIntStubsPtr->tclpObjStat) /* 206 */
+#endif
+#ifndef TclpObjAccess
+#define TclpObjAccess \
+ (tclIntStubsPtr->tclpObjAccess) /* 207 */
+#endif
+#ifndef TclpOpenFileChannel
+#define TclpOpenFileChannel \
+ (tclIntStubsPtr->tclpOpenFileChannel) /* 208 */
+#endif
+/* Slot 209 is reserved */
+/* Slot 210 is reserved */
+/* Slot 211 is reserved */
+#ifndef TclpFindExecutable
+#define TclpFindExecutable \
+ (tclIntStubsPtr->tclpFindExecutable) /* 212 */
+#endif
+#ifndef TclGetObjNameOfExecutable
+#define TclGetObjNameOfExecutable \
+ (tclIntStubsPtr->tclGetObjNameOfExecutable) /* 213 */
+#endif
+#ifndef TclSetObjNameOfExecutable
+#define TclSetObjNameOfExecutable \
+ (tclIntStubsPtr->tclSetObjNameOfExecutable) /* 214 */
+#endif
+#ifndef TclStackAlloc
+#define TclStackAlloc \
+ (tclIntStubsPtr->tclStackAlloc) /* 215 */
+#endif
+#ifndef TclStackFree
+#define TclStackFree \
+ (tclIntStubsPtr->tclStackFree) /* 216 */
+#endif
+#ifndef TclPushStackFrame
+#define TclPushStackFrame \
+ (tclIntStubsPtr->tclPushStackFrame) /* 217 */
+#endif
+#ifndef TclPopStackFrame
+#define TclPopStackFrame \
+ (tclIntStubsPtr->tclPopStackFrame) /* 218 */
+#endif
+/* Slot 219 is reserved */
+/* Slot 220 is reserved */
+/* Slot 221 is reserved */
+/* Slot 222 is reserved */
+/* Slot 223 is reserved */
+#ifndef TclGetPlatform
+#define TclGetPlatform \
+ (tclIntStubsPtr->tclGetPlatform) /* 224 */
+#endif
+#ifndef TclTraceDictPath
+#define TclTraceDictPath \
+ (tclIntStubsPtr->tclTraceDictPath) /* 225 */
+#endif
+#ifndef TclObjBeingDeleted
+#define TclObjBeingDeleted \
+ (tclIntStubsPtr->tclObjBeingDeleted) /* 226 */
+#endif
+#ifndef TclSetNsPath
+#define TclSetNsPath \
+ (tclIntStubsPtr->tclSetNsPath) /* 227 */
+#endif
+#ifndef TclObjInterpProcCore
+#define TclObjInterpProcCore \
+ (tclIntStubsPtr->tclObjInterpProcCore) /* 228 */
+#endif
+#ifndef TclPtrMakeUpvar
+#define TclPtrMakeUpvar \
+ (tclIntStubsPtr->tclPtrMakeUpvar) /* 229 */
+#endif
+#ifndef TclObjLookupVar
+#define TclObjLookupVar \
+ (tclIntStubsPtr->tclObjLookupVar) /* 230 */
+#endif
+#ifndef TclGetNamespaceFromObj
+#define TclGetNamespaceFromObj \
+ (tclIntStubsPtr->tclGetNamespaceFromObj) /* 231 */
+#endif
+#ifndef TclEvalObjEx
+#define TclEvalObjEx \
+ (tclIntStubsPtr->tclEvalObjEx) /* 232 */
+#endif
+#ifndef TclGetSrcInfoForPc
+#define TclGetSrcInfoForPc \
+ (tclIntStubsPtr->tclGetSrcInfoForPc) /* 233 */
+#endif
+#ifndef TclVarHashCreateVar
+#define TclVarHashCreateVar \
+ (tclIntStubsPtr->tclVarHashCreateVar) /* 234 */
+#endif
+#ifndef TclInitVarHashTable
+#define TclInitVarHashTable \
+ (tclIntStubsPtr->tclInitVarHashTable) /* 235 */
+#endif
+#ifndef TclBackgroundException
+#define TclBackgroundException \
+ (tclIntStubsPtr->tclBackgroundException) /* 236 */
+#endif
+/* Slot 237 is reserved */
+/* Slot 238 is reserved */
+/* Slot 239 is reserved */
+/* Slot 240 is reserved */
+/* Slot 241 is reserved */
+/* Slot 242 is reserved */
+#ifndef TclDbDumpActiveObjects
+#define TclDbDumpActiveObjects \
+ (tclIntStubsPtr->tclDbDumpActiveObjects) /* 243 */
+#endif
+/* Slot 244 is reserved */
+/* Slot 245 is reserved */
+/* Slot 246 is reserved */
+/* Slot 247 is reserved */
+/* Slot 248 is reserved */
+#ifndef TclDoubleDigits
+#define TclDoubleDigits \
+ (tclIntStubsPtr->tclDoubleDigits) /* 249 */
#endif
#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */
/* !END!: Do not edit above this line. */
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLIMPORT
+
#endif /* _TCLINTDECLS */
diff --git a/generic/tclIntPlatDecls.h b/generic/tclIntPlatDecls.h
index 35bacf1..3c03015 100644
--- a/generic/tclIntPlatDecls.h
+++ b/generic/tclIntPlatDecls.h
@@ -13,6 +13,17 @@
#ifndef _TCLINTPLATDECLS
#define _TCLINTPLATDECLS
+#undef TCL_STORAGE_CLASS
+#ifdef BUILD_tcl
+# define TCL_STORAGE_CLASS DLLEXPORT
+#else
+# ifdef USE_TCL_STUBS
+# define TCL_STORAGE_CLASS
+# else
+# define TCL_STORAGE_CLASS DLLIMPORT
+# endif
+#endif
+
/*
* WARNING: This file is automatically generated by the tools/genStubs.tcl
* script. Any modifications to the function declarations below should be made
@@ -25,277 +36,416 @@
* Exported function declarations:
*/
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
+#ifndef TclGetAndDetachPids_TCL_DECLARED
+#define TclGetAndDetachPids_TCL_DECLARED
/* 0 */
-EXTERN void TclGetAndDetachPids _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Channel chan));
+EXTERN void TclGetAndDetachPids(Tcl_Interp *interp,
+ Tcl_Channel chan);
+#endif
+#ifndef TclpCloseFile_TCL_DECLARED
+#define TclpCloseFile_TCL_DECLARED
/* 1 */
-EXTERN int TclpCloseFile _ANSI_ARGS_((TclFile file));
+EXTERN int TclpCloseFile(TclFile file);
+#endif
+#ifndef TclpCreateCommandChannel_TCL_DECLARED
+#define TclpCreateCommandChannel_TCL_DECLARED
/* 2 */
-EXTERN Tcl_Channel TclpCreateCommandChannel _ANSI_ARGS_((
- TclFile readFile, TclFile writeFile,
- TclFile errorFile, int numPids,
- Tcl_Pid * pidPtr));
+EXTERN Tcl_Channel TclpCreateCommandChannel(TclFile readFile,
+ TclFile writeFile, TclFile errorFile,
+ int numPids, Tcl_Pid *pidPtr);
+#endif
+#ifndef TclpCreatePipe_TCL_DECLARED
+#define TclpCreatePipe_TCL_DECLARED
/* 3 */
-EXTERN int TclpCreatePipe _ANSI_ARGS_((TclFile * readPipe,
- TclFile * writePipe));
+EXTERN int TclpCreatePipe(TclFile *readPipe, TclFile *writePipe);
+#endif
+#ifndef TclpCreateProcess_TCL_DECLARED
+#define TclpCreateProcess_TCL_DECLARED
/* 4 */
-EXTERN int TclpCreateProcess _ANSI_ARGS_((Tcl_Interp * interp,
- int argc, CONST char ** argv,
- TclFile inputFile, TclFile outputFile,
- TclFile errorFile, Tcl_Pid * pidPtr));
+EXTERN int TclpCreateProcess(Tcl_Interp *interp, int argc,
+ CONST char **argv, TclFile inputFile,
+ TclFile outputFile, TclFile errorFile,
+ Tcl_Pid *pidPtr);
+#endif
/* Slot 5 is reserved */
+#ifndef TclpMakeFile_TCL_DECLARED
+#define TclpMakeFile_TCL_DECLARED
/* 6 */
-EXTERN TclFile TclpMakeFile _ANSI_ARGS_((Tcl_Channel channel,
- int direction));
+EXTERN TclFile TclpMakeFile(Tcl_Channel channel, int direction);
+#endif
+#ifndef TclpOpenFile_TCL_DECLARED
+#define TclpOpenFile_TCL_DECLARED
/* 7 */
-EXTERN TclFile TclpOpenFile _ANSI_ARGS_((CONST char * fname,
- int mode));
+EXTERN TclFile TclpOpenFile(CONST char *fname, int mode);
+#endif
+#ifndef TclUnixWaitForFile_TCL_DECLARED
+#define TclUnixWaitForFile_TCL_DECLARED
/* 8 */
-EXTERN int TclUnixWaitForFile _ANSI_ARGS_((int fd, int mask,
- int timeout));
+EXTERN int TclUnixWaitForFile(int fd, int mask, int timeout);
+#endif
+#ifndef TclpCreateTempFile_TCL_DECLARED
+#define TclpCreateTempFile_TCL_DECLARED
/* 9 */
-EXTERN TclFile TclpCreateTempFile _ANSI_ARGS_((
- CONST char * contents));
+EXTERN TclFile TclpCreateTempFile(CONST char *contents);
+#endif
+#ifndef TclpReaddir_TCL_DECLARED
+#define TclpReaddir_TCL_DECLARED
/* 10 */
-EXTERN Tcl_DirEntry * TclpReaddir _ANSI_ARGS_((DIR * dir));
+EXTERN Tcl_DirEntry * TclpReaddir(DIR *dir);
+#endif
+#ifndef TclpLocaltime_unix_TCL_DECLARED
+#define TclpLocaltime_unix_TCL_DECLARED
/* 11 */
-EXTERN struct tm * TclpLocaltime_unix _ANSI_ARGS_((
- TclpTime_t_CONST clock));
+EXTERN struct tm * TclpLocaltime_unix(CONST time_t *clock);
+#endif
+#ifndef TclpGmtime_unix_TCL_DECLARED
+#define TclpGmtime_unix_TCL_DECLARED
/* 12 */
-EXTERN struct tm * TclpGmtime_unix _ANSI_ARGS_((TclpTime_t_CONST clock));
+EXTERN struct tm * TclpGmtime_unix(CONST time_t *clock);
+#endif
+#ifndef TclpInetNtoa_TCL_DECLARED
+#define TclpInetNtoa_TCL_DECLARED
/* 13 */
-EXTERN char * TclpInetNtoa _ANSI_ARGS_((struct in_addr addr));
+EXTERN char * TclpInetNtoa(struct in_addr addr);
+#endif
+#ifndef TclUnixCopyFile_TCL_DECLARED
+#define TclUnixCopyFile_TCL_DECLARED
+/* 14 */
+EXTERN int TclUnixCopyFile(CONST char *src, CONST char *dst,
+ CONST Tcl_StatBuf *statBufPtr,
+ int dontCopyAtts);
+#endif
#endif /* UNIX */
-#ifdef __WIN32__
+#ifdef __WIN32__ /* WIN */
+#ifndef TclWinConvertError_TCL_DECLARED
+#define TclWinConvertError_TCL_DECLARED
/* 0 */
-EXTERN void TclWinConvertError _ANSI_ARGS_((DWORD errCode));
+EXTERN void TclWinConvertError(unsigned long errCode);
+#endif
+#ifndef TclWinConvertWSAError_TCL_DECLARED
+#define TclWinConvertWSAError_TCL_DECLARED
/* 1 */
-EXTERN void TclWinConvertWSAError _ANSI_ARGS_((DWORD errCode));
+EXTERN void TclWinConvertWSAError(unsigned long errCode);
+#endif
+#ifndef TclWinGetServByName_TCL_DECLARED
+#define TclWinGetServByName_TCL_DECLARED
/* 2 */
-EXTERN struct servent * TclWinGetServByName _ANSI_ARGS_((CONST char * nm,
- CONST char * proto));
+EXTERN struct servent * TclWinGetServByName(CONST char *nm,
+ CONST char *proto);
+#endif
+#ifndef TclWinGetSockOpt_TCL_DECLARED
+#define TclWinGetSockOpt_TCL_DECLARED
/* 3 */
-EXTERN int TclWinGetSockOpt _ANSI_ARGS_((SOCKET s, int level,
- int optname, char FAR * optval,
- int FAR * optlen));
+EXTERN int TclWinGetSockOpt(int s, int level, int optname,
+ char FAR *optval, int FAR *optlen);
+#endif
+#ifndef TclWinGetTclInstance_TCL_DECLARED
+#define TclWinGetTclInstance_TCL_DECLARED
/* 4 */
-EXTERN HINSTANCE TclWinGetTclInstance _ANSI_ARGS_((void));
+EXTERN HINSTANCE TclWinGetTclInstance(void);
+#endif
/* Slot 5 is reserved */
+#ifndef TclWinNToHS_TCL_DECLARED
+#define TclWinNToHS_TCL_DECLARED
/* 6 */
-EXTERN u_short TclWinNToHS _ANSI_ARGS_((u_short ns));
+EXTERN u_short TclWinNToHS(u_short ns);
+#endif
+#ifndef TclWinSetSockOpt_TCL_DECLARED
+#define TclWinSetSockOpt_TCL_DECLARED
/* 7 */
-EXTERN int TclWinSetSockOpt _ANSI_ARGS_((SOCKET s, int level,
- int optname, CONST char FAR * optval,
- int optlen));
+EXTERN int TclWinSetSockOpt(int s, int level, int optname,
+ CONST char FAR *optval, int optlen);
+#endif
+#ifndef TclpGetPid_TCL_DECLARED
+#define TclpGetPid_TCL_DECLARED
/* 8 */
-EXTERN unsigned long TclpGetPid _ANSI_ARGS_((Tcl_Pid pid));
+EXTERN unsigned long TclpGetPid(Tcl_Pid pid);
+#endif
+#ifndef TclWinGetPlatformId_TCL_DECLARED
+#define TclWinGetPlatformId_TCL_DECLARED
/* 9 */
-EXTERN int TclWinGetPlatformId _ANSI_ARGS_((void));
+EXTERN int TclWinGetPlatformId(void);
+#endif
/* Slot 10 is reserved */
+#ifndef TclGetAndDetachPids_TCL_DECLARED
+#define TclGetAndDetachPids_TCL_DECLARED
/* 11 */
-EXTERN void TclGetAndDetachPids _ANSI_ARGS_((Tcl_Interp * interp,
- Tcl_Channel chan));
+EXTERN void TclGetAndDetachPids(Tcl_Interp *interp,
+ Tcl_Channel chan);
+#endif
+#ifndef TclpCloseFile_TCL_DECLARED
+#define TclpCloseFile_TCL_DECLARED
/* 12 */
-EXTERN int TclpCloseFile _ANSI_ARGS_((TclFile file));
+EXTERN int TclpCloseFile(TclFile file);
+#endif
+#ifndef TclpCreateCommandChannel_TCL_DECLARED
+#define TclpCreateCommandChannel_TCL_DECLARED
/* 13 */
-EXTERN Tcl_Channel TclpCreateCommandChannel _ANSI_ARGS_((
- TclFile readFile, TclFile writeFile,
- TclFile errorFile, int numPids,
- Tcl_Pid * pidPtr));
+EXTERN Tcl_Channel TclpCreateCommandChannel(TclFile readFile,
+ TclFile writeFile, TclFile errorFile,
+ int numPids, Tcl_Pid *pidPtr);
+#endif
+#ifndef TclpCreatePipe_TCL_DECLARED
+#define TclpCreatePipe_TCL_DECLARED
/* 14 */
-EXTERN int TclpCreatePipe _ANSI_ARGS_((TclFile * readPipe,
- TclFile * writePipe));
+EXTERN int TclpCreatePipe(TclFile *readPipe, TclFile *writePipe);
+#endif
+#ifndef TclpCreateProcess_TCL_DECLARED
+#define TclpCreateProcess_TCL_DECLARED
/* 15 */
-EXTERN int TclpCreateProcess _ANSI_ARGS_((Tcl_Interp * interp,
- int argc, CONST char ** argv,
- TclFile inputFile, TclFile outputFile,
- TclFile errorFile, Tcl_Pid * pidPtr));
+EXTERN int TclpCreateProcess(Tcl_Interp *interp, int argc,
+ CONST char **argv, TclFile inputFile,
+ TclFile outputFile, TclFile errorFile,
+ Tcl_Pid *pidPtr);
+#endif
/* Slot 16 is reserved */
/* Slot 17 is reserved */
+#ifndef TclpMakeFile_TCL_DECLARED
+#define TclpMakeFile_TCL_DECLARED
/* 18 */
-EXTERN TclFile TclpMakeFile _ANSI_ARGS_((Tcl_Channel channel,
- int direction));
+EXTERN TclFile TclpMakeFile(Tcl_Channel channel, int direction);
+#endif
+#ifndef TclpOpenFile_TCL_DECLARED
+#define TclpOpenFile_TCL_DECLARED
/* 19 */
-EXTERN TclFile TclpOpenFile _ANSI_ARGS_((CONST char * fname,
- int mode));
+EXTERN TclFile TclpOpenFile(CONST char *fname, int mode);
+#endif
+#ifndef TclWinAddProcess_TCL_DECLARED
+#define TclWinAddProcess_TCL_DECLARED
/* 20 */
-EXTERN void TclWinAddProcess _ANSI_ARGS_((HANDLE hProcess,
- DWORD id));
+EXTERN void TclWinAddProcess(VOID *hProcess, unsigned long id);
+#endif
/* Slot 21 is reserved */
+#ifndef TclpCreateTempFile_TCL_DECLARED
+#define TclpCreateTempFile_TCL_DECLARED
/* 22 */
-EXTERN TclFile TclpCreateTempFile _ANSI_ARGS_((
- CONST char * contents));
+EXTERN TclFile TclpCreateTempFile(CONST char *contents);
+#endif
+#ifndef TclpGetTZName_TCL_DECLARED
+#define TclpGetTZName_TCL_DECLARED
/* 23 */
-EXTERN char * TclpGetTZName _ANSI_ARGS_((int isdst));
+EXTERN char * TclpGetTZName(int isdst);
+#endif
+#ifndef TclWinNoBackslash_TCL_DECLARED
+#define TclWinNoBackslash_TCL_DECLARED
/* 24 */
-EXTERN char * TclWinNoBackslash _ANSI_ARGS_((char * path));
-/* 25 */
-EXTERN TclPlatformType * TclWinGetPlatform _ANSI_ARGS_((void));
+EXTERN char * TclWinNoBackslash(char *path);
+#endif
+/* Slot 25 is reserved */
+#ifndef TclWinSetInterfaces_TCL_DECLARED
+#define TclWinSetInterfaces_TCL_DECLARED
/* 26 */
-EXTERN void TclWinSetInterfaces _ANSI_ARGS_((int wide));
+EXTERN void TclWinSetInterfaces(int wide);
+#endif
+#ifndef TclWinFlushDirtyChannels_TCL_DECLARED
+#define TclWinFlushDirtyChannels_TCL_DECLARED
/* 27 */
-EXTERN void TclWinFlushDirtyChannels _ANSI_ARGS_((void));
+EXTERN void TclWinFlushDirtyChannels(void);
+#endif
+#ifndef TclWinResetInterfaces_TCL_DECLARED
+#define TclWinResetInterfaces_TCL_DECLARED
/* 28 */
-EXTERN void TclWinResetInterfaces _ANSI_ARGS_((void));
+EXTERN void TclWinResetInterfaces(void);
+#endif
+#ifndef TclWinCPUID_TCL_DECLARED
+#define TclWinCPUID_TCL_DECLARED
/* 29 */
-EXTERN int TclWinCPUID _ANSI_ARGS_((unsigned int index,
- unsigned int * regs));
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
+EXTERN int TclWinCPUID(unsigned int index, unsigned int *regs);
+#endif
+#endif /* WIN */
+#ifdef MAC_OSX_TCL /* MACOSX */
+#ifndef TclGetAndDetachPids_TCL_DECLARED
+#define TclGetAndDetachPids_TCL_DECLARED
/* 0 */
-EXTERN VOID * TclpSysAlloc _ANSI_ARGS_((long size, int isBin));
+EXTERN void TclGetAndDetachPids(Tcl_Interp *interp,
+ Tcl_Channel chan);
+#endif
+#ifndef TclpCloseFile_TCL_DECLARED
+#define TclpCloseFile_TCL_DECLARED
/* 1 */
-EXTERN void TclpSysFree _ANSI_ARGS_((VOID * ptr));
+EXTERN int TclpCloseFile(TclFile file);
+#endif
+#ifndef TclpCreateCommandChannel_TCL_DECLARED
+#define TclpCreateCommandChannel_TCL_DECLARED
/* 2 */
-EXTERN VOID * TclpSysRealloc _ANSI_ARGS_((VOID * cp,
- unsigned int size));
+EXTERN Tcl_Channel TclpCreateCommandChannel(TclFile readFile,
+ TclFile writeFile, TclFile errorFile,
+ int numPids, Tcl_Pid *pidPtr);
+#endif
+#ifndef TclpCreatePipe_TCL_DECLARED
+#define TclpCreatePipe_TCL_DECLARED
/* 3 */
-EXTERN void TclpExit _ANSI_ARGS_((int status));
+EXTERN int TclpCreatePipe(TclFile *readPipe, TclFile *writePipe);
+#endif
+#ifndef TclpCreateProcess_TCL_DECLARED
+#define TclpCreateProcess_TCL_DECLARED
/* 4 */
-EXTERN int FSpGetDefaultDir _ANSI_ARGS_((FSSpecPtr theSpec));
-/* 5 */
-EXTERN int FSpSetDefaultDir _ANSI_ARGS_((FSSpecPtr theSpec));
+EXTERN int TclpCreateProcess(Tcl_Interp *interp, int argc,
+ CONST char **argv, TclFile inputFile,
+ TclFile outputFile, TclFile errorFile,
+ Tcl_Pid *pidPtr);
+#endif
+/* Slot 5 is reserved */
+#ifndef TclpMakeFile_TCL_DECLARED
+#define TclpMakeFile_TCL_DECLARED
/* 6 */
-EXTERN OSErr FSpFindFolder _ANSI_ARGS_((short vRefNum,
- OSType folderType, Boolean createFolder,
- FSSpec * spec));
+EXTERN TclFile TclpMakeFile(Tcl_Channel channel, int direction);
+#endif
+#ifndef TclpOpenFile_TCL_DECLARED
+#define TclpOpenFile_TCL_DECLARED
/* 7 */
-EXTERN void GetGlobalMouseTcl _ANSI_ARGS_((Point * mouse));
+EXTERN TclFile TclpOpenFile(CONST char *fname, int mode);
+#endif
+#ifndef TclUnixWaitForFile_TCL_DECLARED
+#define TclUnixWaitForFile_TCL_DECLARED
/* 8 */
-EXTERN pascal OSErr FSpGetDirectoryIDTcl _ANSI_ARGS_((
- CONST FSSpec * spec, long * theDirID,
- Boolean * isDirectory));
+EXTERN int TclUnixWaitForFile(int fd, int mask, int timeout);
+#endif
+#ifndef TclpCreateTempFile_TCL_DECLARED
+#define TclpCreateTempFile_TCL_DECLARED
/* 9 */
-EXTERN pascal short FSpOpenResFileCompatTcl _ANSI_ARGS_((
- CONST FSSpec * spec, SignedByte permission));
+EXTERN TclFile TclpCreateTempFile(CONST char *contents);
+#endif
+#ifndef TclpReaddir_TCL_DECLARED
+#define TclpReaddir_TCL_DECLARED
/* 10 */
-EXTERN pascal void FSpCreateResFileCompatTcl _ANSI_ARGS_((
- CONST FSSpec * spec, OSType creator,
- OSType fileType, ScriptCode scriptTag));
+EXTERN Tcl_DirEntry * TclpReaddir(DIR *dir);
+#endif
+#ifndef TclpLocaltime_unix_TCL_DECLARED
+#define TclpLocaltime_unix_TCL_DECLARED
/* 11 */
-EXTERN int FSpLocationFromPath _ANSI_ARGS_((int length,
- CONST char * path, FSSpecPtr theSpec));
+EXTERN struct tm * TclpLocaltime_unix(CONST time_t *clock);
+#endif
+#ifndef TclpGmtime_unix_TCL_DECLARED
+#define TclpGmtime_unix_TCL_DECLARED
/* 12 */
-EXTERN OSErr FSpPathFromLocation _ANSI_ARGS_((FSSpecPtr theSpec,
- int * length, Handle * fullPath));
+EXTERN struct tm * TclpGmtime_unix(CONST time_t *clock);
+#endif
+#ifndef TclpInetNtoa_TCL_DECLARED
+#define TclpInetNtoa_TCL_DECLARED
/* 13 */
-EXTERN void TclMacExitHandler _ANSI_ARGS_((void));
+EXTERN char * TclpInetNtoa(struct in_addr addr);
+#endif
+#ifndef TclUnixCopyFile_TCL_DECLARED
+#define TclUnixCopyFile_TCL_DECLARED
/* 14 */
-EXTERN void TclMacInitExitToShell _ANSI_ARGS_((int usePatch));
+EXTERN int TclUnixCopyFile(CONST char *src, CONST char *dst,
+ CONST Tcl_StatBuf *statBufPtr,
+ int dontCopyAtts);
+#endif
+#ifndef TclMacOSXGetFileAttribute_TCL_DECLARED
+#define TclMacOSXGetFileAttribute_TCL_DECLARED
/* 15 */
-EXTERN OSErr TclMacInstallExitToShellPatch _ANSI_ARGS_((
- ExitToShellProcPtr newProc));
+EXTERN int TclMacOSXGetFileAttribute(Tcl_Interp *interp,
+ int objIndex, Tcl_Obj *fileName,
+ Tcl_Obj **attributePtrPtr);
+#endif
+#ifndef TclMacOSXSetFileAttribute_TCL_DECLARED
+#define TclMacOSXSetFileAttribute_TCL_DECLARED
/* 16 */
-EXTERN int TclMacOSErrorToPosixError _ANSI_ARGS_((int error));
+EXTERN int TclMacOSXSetFileAttribute(Tcl_Interp *interp,
+ int objIndex, Tcl_Obj *fileName,
+ Tcl_Obj *attributePtr);
+#endif
+#ifndef TclMacOSXCopyFileAttributes_TCL_DECLARED
+#define TclMacOSXCopyFileAttributes_TCL_DECLARED
/* 17 */
-EXTERN void TclMacRemoveTimer _ANSI_ARGS_((VOID * timerToken));
+EXTERN int TclMacOSXCopyFileAttributes(CONST char *src,
+ CONST char *dst,
+ CONST Tcl_StatBuf *statBufPtr);
+#endif
+#ifndef TclMacOSXMatchType_TCL_DECLARED
+#define TclMacOSXMatchType_TCL_DECLARED
/* 18 */
-EXTERN VOID * TclMacStartTimer _ANSI_ARGS_((long ms));
+EXTERN int TclMacOSXMatchType(Tcl_Interp *interp,
+ CONST char *pathName, CONST char *fileName,
+ Tcl_StatBuf *statBufPtr,
+ Tcl_GlobTypeData *types);
+#endif
+#ifndef TclMacOSXNotifierAddRunLoopMode_TCL_DECLARED
+#define TclMacOSXNotifierAddRunLoopMode_TCL_DECLARED
/* 19 */
-EXTERN int TclMacTimerExpired _ANSI_ARGS_((VOID * timerToken));
-/* 20 */
-EXTERN int TclMacRegisterResourceFork _ANSI_ARGS_((
- short fileRef, Tcl_Obj * tokenPtr,
- int insert));
-/* 21 */
-EXTERN short TclMacUnRegisterResourceFork _ANSI_ARGS_((
- char * tokenPtr, Tcl_Obj * resultPtr));
-/* 22 */
-EXTERN int TclMacCreateEnv _ANSI_ARGS_((void));
-/* 23 */
-EXTERN FILE * TclMacFOpenHack _ANSI_ARGS_((CONST char * path,
- CONST char * mode));
-/* 24 */
-EXTERN char * TclpGetTZName _ANSI_ARGS_((int isdst));
-/* 25 */
-EXTERN int TclMacChmod _ANSI_ARGS_((CONST char * path, int mode));
-/* 26 */
-EXTERN int FSpLLocationFromPath _ANSI_ARGS_((int length,
- CONST char * path, FSSpecPtr theSpec));
-#endif /* MAC_TCL */
+EXTERN void TclMacOSXNotifierAddRunLoopMode(
+ CONST VOID *runLoopMode);
+#endif
+#endif /* MACOSX */
typedef struct TclIntPlatStubs {
int magic;
struct TclIntPlatStubHooks *hooks;
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
- void (*tclGetAndDetachPids) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan)); /* 0 */
- int (*tclpCloseFile) _ANSI_ARGS_((TclFile file)); /* 1 */
- Tcl_Channel (*tclpCreateCommandChannel) _ANSI_ARGS_((TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid * pidPtr)); /* 2 */
- int (*tclpCreatePipe) _ANSI_ARGS_((TclFile * readPipe, TclFile * writePipe)); /* 3 */
- int (*tclpCreateProcess) _ANSI_ARGS_((Tcl_Interp * interp, int argc, CONST char ** argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid * pidPtr)); /* 4 */
- void *reserved5;
- TclFile (*tclpMakeFile) _ANSI_ARGS_((Tcl_Channel channel, int direction)); /* 6 */
- TclFile (*tclpOpenFile) _ANSI_ARGS_((CONST char * fname, int mode)); /* 7 */
- int (*tclUnixWaitForFile) _ANSI_ARGS_((int fd, int mask, int timeout)); /* 8 */
- TclFile (*tclpCreateTempFile) _ANSI_ARGS_((CONST char * contents)); /* 9 */
- Tcl_DirEntry * (*tclpReaddir) _ANSI_ARGS_((DIR * dir)); /* 10 */
- struct tm * (*tclpLocaltime_unix) _ANSI_ARGS_((TclpTime_t_CONST clock)); /* 11 */
- struct tm * (*tclpGmtime_unix) _ANSI_ARGS_((TclpTime_t_CONST clock)); /* 12 */
- char * (*tclpInetNtoa) _ANSI_ARGS_((struct in_addr addr)); /* 13 */
+#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
+ void (*tclGetAndDetachPids) (Tcl_Interp *interp, Tcl_Channel chan); /* 0 */
+ int (*tclpCloseFile) (TclFile file); /* 1 */
+ Tcl_Channel (*tclpCreateCommandChannel) (TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr); /* 2 */
+ int (*tclpCreatePipe) (TclFile *readPipe, TclFile *writePipe); /* 3 */
+ int (*tclpCreateProcess) (Tcl_Interp *interp, int argc, CONST char **argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid *pidPtr); /* 4 */
+ VOID *reserved5;
+ TclFile (*tclpMakeFile) (Tcl_Channel channel, int direction); /* 6 */
+ TclFile (*tclpOpenFile) (CONST char *fname, int mode); /* 7 */
+ int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 8 */
+ TclFile (*tclpCreateTempFile) (CONST char *contents); /* 9 */
+ Tcl_DirEntry * (*tclpReaddir) (DIR *dir); /* 10 */
+ struct tm * (*tclpLocaltime_unix) (CONST time_t *clock); /* 11 */
+ struct tm * (*tclpGmtime_unix) (CONST time_t *clock); /* 12 */
+ char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */
+ int (*tclUnixCopyFile) (CONST char *src, CONST char *dst, CONST Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 14 */
#endif /* UNIX */
-#ifdef __WIN32__
- void (*tclWinConvertError) _ANSI_ARGS_((DWORD errCode)); /* 0 */
- void (*tclWinConvertWSAError) _ANSI_ARGS_((DWORD errCode)); /* 1 */
- struct servent * (*tclWinGetServByName) _ANSI_ARGS_((CONST char * nm, CONST char * proto)); /* 2 */
- int (*tclWinGetSockOpt) _ANSI_ARGS_((SOCKET s, int level, int optname, char FAR * optval, int FAR * optlen)); /* 3 */
- HINSTANCE (*tclWinGetTclInstance) _ANSI_ARGS_((void)); /* 4 */
- void *reserved5;
- u_short (*tclWinNToHS) _ANSI_ARGS_((u_short ns)); /* 6 */
- int (*tclWinSetSockOpt) _ANSI_ARGS_((SOCKET s, int level, int optname, CONST char FAR * optval, int optlen)); /* 7 */
- unsigned long (*tclpGetPid) _ANSI_ARGS_((Tcl_Pid pid)); /* 8 */
- int (*tclWinGetPlatformId) _ANSI_ARGS_((void)); /* 9 */
- void *reserved10;
- void (*tclGetAndDetachPids) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan)); /* 11 */
- int (*tclpCloseFile) _ANSI_ARGS_((TclFile file)); /* 12 */
- Tcl_Channel (*tclpCreateCommandChannel) _ANSI_ARGS_((TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid * pidPtr)); /* 13 */
- int (*tclpCreatePipe) _ANSI_ARGS_((TclFile * readPipe, TclFile * writePipe)); /* 14 */
- int (*tclpCreateProcess) _ANSI_ARGS_((Tcl_Interp * interp, int argc, CONST char ** argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid * pidPtr)); /* 15 */
- void *reserved16;
- void *reserved17;
- TclFile (*tclpMakeFile) _ANSI_ARGS_((Tcl_Channel channel, int direction)); /* 18 */
- TclFile (*tclpOpenFile) _ANSI_ARGS_((CONST char * fname, int mode)); /* 19 */
- void (*tclWinAddProcess) _ANSI_ARGS_((HANDLE hProcess, DWORD id)); /* 20 */
- void *reserved21;
- TclFile (*tclpCreateTempFile) _ANSI_ARGS_((CONST char * contents)); /* 22 */
- char * (*tclpGetTZName) _ANSI_ARGS_((int isdst)); /* 23 */
- char * (*tclWinNoBackslash) _ANSI_ARGS_((char * path)); /* 24 */
- TclPlatformType * (*tclWinGetPlatform) _ANSI_ARGS_((void)); /* 25 */
- void (*tclWinSetInterfaces) _ANSI_ARGS_((int wide)); /* 26 */
- void (*tclWinFlushDirtyChannels) _ANSI_ARGS_((void)); /* 27 */
- void (*tclWinResetInterfaces) _ANSI_ARGS_((void)); /* 28 */
- int (*tclWinCPUID) _ANSI_ARGS_((unsigned int index, unsigned int * regs)); /* 29 */
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
- VOID * (*tclpSysAlloc) _ANSI_ARGS_((long size, int isBin)); /* 0 */
- void (*tclpSysFree) _ANSI_ARGS_((VOID * ptr)); /* 1 */
- VOID * (*tclpSysRealloc) _ANSI_ARGS_((VOID * cp, unsigned int size)); /* 2 */
- void (*tclpExit) _ANSI_ARGS_((int status)); /* 3 */
- int (*fSpGetDefaultDir) _ANSI_ARGS_((FSSpecPtr theSpec)); /* 4 */
- int (*fSpSetDefaultDir) _ANSI_ARGS_((FSSpecPtr theSpec)); /* 5 */
- OSErr (*fSpFindFolder) _ANSI_ARGS_((short vRefNum, OSType folderType, Boolean createFolder, FSSpec * spec)); /* 6 */
- void (*getGlobalMouseTcl) _ANSI_ARGS_((Point * mouse)); /* 7 */
- pascal OSErr (*fSpGetDirectoryIDTcl) _ANSI_ARGS_((CONST FSSpec * spec, long * theDirID, Boolean * isDirectory)); /* 8 */
- pascal short (*fSpOpenResFileCompatTcl) _ANSI_ARGS_((CONST FSSpec * spec, SignedByte permission)); /* 9 */
- pascal void (*fSpCreateResFileCompatTcl) _ANSI_ARGS_((CONST FSSpec * spec, OSType creator, OSType fileType, ScriptCode scriptTag)); /* 10 */
- int (*fSpLocationFromPath) _ANSI_ARGS_((int length, CONST char * path, FSSpecPtr theSpec)); /* 11 */
- OSErr (*fSpPathFromLocation) _ANSI_ARGS_((FSSpecPtr theSpec, int * length, Handle * fullPath)); /* 12 */
- void (*tclMacExitHandler) _ANSI_ARGS_((void)); /* 13 */
- void (*tclMacInitExitToShell) _ANSI_ARGS_((int usePatch)); /* 14 */
- OSErr (*tclMacInstallExitToShellPatch) _ANSI_ARGS_((ExitToShellProcPtr newProc)); /* 15 */
- int (*tclMacOSErrorToPosixError) _ANSI_ARGS_((int error)); /* 16 */
- void (*tclMacRemoveTimer) _ANSI_ARGS_((VOID * timerToken)); /* 17 */
- VOID * (*tclMacStartTimer) _ANSI_ARGS_((long ms)); /* 18 */
- int (*tclMacTimerExpired) _ANSI_ARGS_((VOID * timerToken)); /* 19 */
- int (*tclMacRegisterResourceFork) _ANSI_ARGS_((short fileRef, Tcl_Obj * tokenPtr, int insert)); /* 20 */
- short (*tclMacUnRegisterResourceFork) _ANSI_ARGS_((char * tokenPtr, Tcl_Obj * resultPtr)); /* 21 */
- int (*tclMacCreateEnv) _ANSI_ARGS_((void)); /* 22 */
- FILE * (*tclMacFOpenHack) _ANSI_ARGS_((CONST char * path, CONST char * mode)); /* 23 */
- char * (*tclpGetTZName) _ANSI_ARGS_((int isdst)); /* 24 */
- int (*tclMacChmod) _ANSI_ARGS_((CONST char * path, int mode)); /* 25 */
- int (*fSpLLocationFromPath) _ANSI_ARGS_((int length, CONST char * path, FSSpecPtr theSpec)); /* 26 */
-#endif /* MAC_TCL */
+#ifdef __WIN32__ /* WIN */
+ void (*tclWinConvertError) (unsigned long errCode); /* 0 */
+ void (*tclWinConvertWSAError) (unsigned long errCode); /* 1 */
+ struct servent * (*tclWinGetServByName) (CONST char *nm, CONST char *proto); /* 2 */
+ int (*tclWinGetSockOpt) (int s, int level, int optname, char FAR *optval, int FAR *optlen); /* 3 */
+ HINSTANCE (*tclWinGetTclInstance) (void); /* 4 */
+ VOID *reserved5;
+ u_short (*tclWinNToHS) (u_short ns); /* 6 */
+ int (*tclWinSetSockOpt) (int s, int level, int optname, CONST char FAR *optval, int optlen); /* 7 */
+ unsigned long (*tclpGetPid) (Tcl_Pid pid); /* 8 */
+ int (*tclWinGetPlatformId) (void); /* 9 */
+ VOID *reserved10;
+ void (*tclGetAndDetachPids) (Tcl_Interp *interp, Tcl_Channel chan); /* 11 */
+ int (*tclpCloseFile) (TclFile file); /* 12 */
+ Tcl_Channel (*tclpCreateCommandChannel) (TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr); /* 13 */
+ int (*tclpCreatePipe) (TclFile *readPipe, TclFile *writePipe); /* 14 */
+ int (*tclpCreateProcess) (Tcl_Interp *interp, int argc, CONST char **argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid *pidPtr); /* 15 */
+ VOID *reserved16;
+ VOID *reserved17;
+ TclFile (*tclpMakeFile) (Tcl_Channel channel, int direction); /* 18 */
+ TclFile (*tclpOpenFile) (CONST char *fname, int mode); /* 19 */
+ void (*tclWinAddProcess) (VOID *hProcess, unsigned long id); /* 20 */
+ VOID *reserved21;
+ TclFile (*tclpCreateTempFile) (CONST char *contents); /* 22 */
+ char * (*tclpGetTZName) (int isdst); /* 23 */
+ char * (*tclWinNoBackslash) (char *path); /* 24 */
+ VOID *reserved25;
+ void (*tclWinSetInterfaces) (int wide); /* 26 */
+ void (*tclWinFlushDirtyChannels) (void); /* 27 */
+ void (*tclWinResetInterfaces) (void); /* 28 */
+ int (*tclWinCPUID) (unsigned int index, unsigned int *regs); /* 29 */
+#endif /* WIN */
+#ifdef MAC_OSX_TCL /* MACOSX */
+ void (*tclGetAndDetachPids) (Tcl_Interp *interp, Tcl_Channel chan); /* 0 */
+ int (*tclpCloseFile) (TclFile file); /* 1 */
+ Tcl_Channel (*tclpCreateCommandChannel) (TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr); /* 2 */
+ int (*tclpCreatePipe) (TclFile *readPipe, TclFile *writePipe); /* 3 */
+ int (*tclpCreateProcess) (Tcl_Interp *interp, int argc, CONST char **argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid *pidPtr); /* 4 */
+ VOID *reserved5;
+ TclFile (*tclpMakeFile) (Tcl_Channel channel, int direction); /* 6 */
+ TclFile (*tclpOpenFile) (CONST char *fname, int mode); /* 7 */
+ int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 8 */
+ TclFile (*tclpCreateTempFile) (CONST char *contents); /* 9 */
+ Tcl_DirEntry * (*tclpReaddir) (DIR *dir); /* 10 */
+ struct tm * (*tclpLocaltime_unix) (CONST time_t *clock); /* 11 */
+ struct tm * (*tclpGmtime_unix) (CONST time_t *clock); /* 12 */
+ char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */
+ int (*tclUnixCopyFile) (CONST char *src, CONST char *dst, CONST Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 14 */
+ int (*tclMacOSXGetFileAttribute) (Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr); /* 15 */
+ int (*tclMacOSXSetFileAttribute) (Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj *attributePtr); /* 16 */
+ int (*tclMacOSXCopyFileAttributes) (CONST char *src, CONST char *dst, CONST Tcl_StatBuf *statBufPtr); /* 17 */
+ int (*tclMacOSXMatchType) (Tcl_Interp *interp, CONST char *pathName, CONST char *fileName, Tcl_StatBuf *statBufPtr, Tcl_GlobTypeData *types); /* 18 */
+ void (*tclMacOSXNotifierAddRunLoopMode) (CONST VOID *runLoopMode); /* 19 */
+#endif /* MACOSX */
} TclIntPlatStubs;
#ifdef __cplusplus
@@ -312,7 +462,7 @@ extern TclIntPlatStubs *tclIntPlatStubsPtr;
* Inline function declarations:
*/
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
#ifndef TclGetAndDetachPids
#define TclGetAndDetachPids \
(tclIntPlatStubsPtr->tclGetAndDetachPids) /* 0 */
@@ -366,8 +516,12 @@ extern TclIntPlatStubs *tclIntPlatStubsPtr;
#define TclpInetNtoa \
(tclIntPlatStubsPtr->tclpInetNtoa) /* 13 */
#endif
+#ifndef TclUnixCopyFile
+#define TclUnixCopyFile \
+ (tclIntPlatStubsPtr->tclUnixCopyFile) /* 14 */
+#endif
#endif /* UNIX */
-#ifdef __WIN32__
+#ifdef __WIN32__ /* WIN */
#ifndef TclWinConvertError
#define TclWinConvertError \
(tclIntPlatStubsPtr->tclWinConvertError) /* 0 */
@@ -453,10 +607,7 @@ extern TclIntPlatStubs *tclIntPlatStubsPtr;
#define TclWinNoBackslash \
(tclIntPlatStubsPtr->tclWinNoBackslash) /* 24 */
#endif
-#ifndef TclWinGetPlatform
-#define TclWinGetPlatform \
- (tclIntPlatStubsPtr->tclWinGetPlatform) /* 25 */
-#endif
+/* Slot 25 is reserved */
#ifndef TclWinSetInterfaces
#define TclWinSetInterfaces \
(tclIntPlatStubsPtr->tclWinSetInterfaces) /* 26 */
@@ -473,122 +624,93 @@ extern TclIntPlatStubs *tclIntPlatStubsPtr;
#define TclWinCPUID \
(tclIntPlatStubsPtr->tclWinCPUID) /* 29 */
#endif
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
-#ifndef TclpSysAlloc
-#define TclpSysAlloc \
- (tclIntPlatStubsPtr->tclpSysAlloc) /* 0 */
-#endif
-#ifndef TclpSysFree
-#define TclpSysFree \
- (tclIntPlatStubsPtr->tclpSysFree) /* 1 */
-#endif
-#ifndef TclpSysRealloc
-#define TclpSysRealloc \
- (tclIntPlatStubsPtr->tclpSysRealloc) /* 2 */
-#endif
-#ifndef TclpExit
-#define TclpExit \
- (tclIntPlatStubsPtr->tclpExit) /* 3 */
-#endif
-#ifndef FSpGetDefaultDir
-#define FSpGetDefaultDir \
- (tclIntPlatStubsPtr->fSpGetDefaultDir) /* 4 */
-#endif
-#ifndef FSpSetDefaultDir
-#define FSpSetDefaultDir \
- (tclIntPlatStubsPtr->fSpSetDefaultDir) /* 5 */
-#endif
-#ifndef FSpFindFolder
-#define FSpFindFolder \
- (tclIntPlatStubsPtr->fSpFindFolder) /* 6 */
-#endif
-#ifndef GetGlobalMouseTcl
-#define GetGlobalMouseTcl \
- (tclIntPlatStubsPtr->getGlobalMouseTcl) /* 7 */
-#endif
-#ifndef FSpGetDirectoryIDTcl
-#define FSpGetDirectoryIDTcl \
- (tclIntPlatStubsPtr->fSpGetDirectoryIDTcl) /* 8 */
+#endif /* WIN */
+#ifdef MAC_OSX_TCL /* MACOSX */
+#ifndef TclGetAndDetachPids
+#define TclGetAndDetachPids \
+ (tclIntPlatStubsPtr->tclGetAndDetachPids) /* 0 */
#endif
-#ifndef FSpOpenResFileCompatTcl
-#define FSpOpenResFileCompatTcl \
- (tclIntPlatStubsPtr->fSpOpenResFileCompatTcl) /* 9 */
+#ifndef TclpCloseFile
+#define TclpCloseFile \
+ (tclIntPlatStubsPtr->tclpCloseFile) /* 1 */
#endif
-#ifndef FSpCreateResFileCompatTcl
-#define FSpCreateResFileCompatTcl \
- (tclIntPlatStubsPtr->fSpCreateResFileCompatTcl) /* 10 */
+#ifndef TclpCreateCommandChannel
+#define TclpCreateCommandChannel \
+ (tclIntPlatStubsPtr->tclpCreateCommandChannel) /* 2 */
#endif
-#ifndef FSpLocationFromPath
-#define FSpLocationFromPath \
- (tclIntPlatStubsPtr->fSpLocationFromPath) /* 11 */
+#ifndef TclpCreatePipe
+#define TclpCreatePipe \
+ (tclIntPlatStubsPtr->tclpCreatePipe) /* 3 */
#endif
-#ifndef FSpPathFromLocation
-#define FSpPathFromLocation \
- (tclIntPlatStubsPtr->fSpPathFromLocation) /* 12 */
+#ifndef TclpCreateProcess
+#define TclpCreateProcess \
+ (tclIntPlatStubsPtr->tclpCreateProcess) /* 4 */
#endif
-#ifndef TclMacExitHandler
-#define TclMacExitHandler \
- (tclIntPlatStubsPtr->tclMacExitHandler) /* 13 */
+/* Slot 5 is reserved */
+#ifndef TclpMakeFile
+#define TclpMakeFile \
+ (tclIntPlatStubsPtr->tclpMakeFile) /* 6 */
#endif
-#ifndef TclMacInitExitToShell
-#define TclMacInitExitToShell \
- (tclIntPlatStubsPtr->tclMacInitExitToShell) /* 14 */
+#ifndef TclpOpenFile
+#define TclpOpenFile \
+ (tclIntPlatStubsPtr->tclpOpenFile) /* 7 */
#endif
-#ifndef TclMacInstallExitToShellPatch
-#define TclMacInstallExitToShellPatch \
- (tclIntPlatStubsPtr->tclMacInstallExitToShellPatch) /* 15 */
+#ifndef TclUnixWaitForFile
+#define TclUnixWaitForFile \
+ (tclIntPlatStubsPtr->tclUnixWaitForFile) /* 8 */
#endif
-#ifndef TclMacOSErrorToPosixError
-#define TclMacOSErrorToPosixError \
- (tclIntPlatStubsPtr->tclMacOSErrorToPosixError) /* 16 */
+#ifndef TclpCreateTempFile
+#define TclpCreateTempFile \
+ (tclIntPlatStubsPtr->tclpCreateTempFile) /* 9 */
#endif
-#ifndef TclMacRemoveTimer
-#define TclMacRemoveTimer \
- (tclIntPlatStubsPtr->tclMacRemoveTimer) /* 17 */
+#ifndef TclpReaddir
+#define TclpReaddir \
+ (tclIntPlatStubsPtr->tclpReaddir) /* 10 */
#endif
-#ifndef TclMacStartTimer
-#define TclMacStartTimer \
- (tclIntPlatStubsPtr->tclMacStartTimer) /* 18 */
+#ifndef TclpLocaltime_unix
+#define TclpLocaltime_unix \
+ (tclIntPlatStubsPtr->tclpLocaltime_unix) /* 11 */
#endif
-#ifndef TclMacTimerExpired
-#define TclMacTimerExpired \
- (tclIntPlatStubsPtr->tclMacTimerExpired) /* 19 */
+#ifndef TclpGmtime_unix
+#define TclpGmtime_unix \
+ (tclIntPlatStubsPtr->tclpGmtime_unix) /* 12 */
#endif
-#ifndef TclMacRegisterResourceFork
-#define TclMacRegisterResourceFork \
- (tclIntPlatStubsPtr->tclMacRegisterResourceFork) /* 20 */
+#ifndef TclpInetNtoa
+#define TclpInetNtoa \
+ (tclIntPlatStubsPtr->tclpInetNtoa) /* 13 */
#endif
-#ifndef TclMacUnRegisterResourceFork
-#define TclMacUnRegisterResourceFork \
- (tclIntPlatStubsPtr->tclMacUnRegisterResourceFork) /* 21 */
+#ifndef TclUnixCopyFile
+#define TclUnixCopyFile \
+ (tclIntPlatStubsPtr->tclUnixCopyFile) /* 14 */
#endif
-#ifndef TclMacCreateEnv
-#define TclMacCreateEnv \
- (tclIntPlatStubsPtr->tclMacCreateEnv) /* 22 */
+#ifndef TclMacOSXGetFileAttribute
+#define TclMacOSXGetFileAttribute \
+ (tclIntPlatStubsPtr->tclMacOSXGetFileAttribute) /* 15 */
#endif
-#ifndef TclMacFOpenHack
-#define TclMacFOpenHack \
- (tclIntPlatStubsPtr->tclMacFOpenHack) /* 23 */
+#ifndef TclMacOSXSetFileAttribute
+#define TclMacOSXSetFileAttribute \
+ (tclIntPlatStubsPtr->tclMacOSXSetFileAttribute) /* 16 */
#endif
-#ifndef TclpGetTZName
-#define TclpGetTZName \
- (tclIntPlatStubsPtr->tclpGetTZName) /* 24 */
+#ifndef TclMacOSXCopyFileAttributes
+#define TclMacOSXCopyFileAttributes \
+ (tclIntPlatStubsPtr->tclMacOSXCopyFileAttributes) /* 17 */
#endif
-#ifndef TclMacChmod
-#define TclMacChmod \
- (tclIntPlatStubsPtr->tclMacChmod) /* 25 */
+#ifndef TclMacOSXMatchType
+#define TclMacOSXMatchType \
+ (tclIntPlatStubsPtr->tclMacOSXMatchType) /* 18 */
#endif
-#ifndef FSpLLocationFromPath
-#define FSpLLocationFromPath \
- (tclIntPlatStubsPtr->fSpLLocationFromPath) /* 26 */
+#ifndef TclMacOSXNotifierAddRunLoopMode
+#define TclMacOSXNotifierAddRunLoopMode \
+ (tclIntPlatStubsPtr->tclMacOSXNotifierAddRunLoopMode) /* 19 */
#endif
-#endif /* MAC_TCL */
+#endif /* MACOSX */
#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */
/* !END!: Do not edit above this line. */
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLIMPORT
#undef TclpLocaltime_unix
#undef TclpGmtime_unix
diff --git a/generic/tclInterp.c b/generic/tclInterp.c
index 53686bd..0b05913 100644
--- a/generic/tclInterp.c
+++ b/generic/tclInterp.c
@@ -1,63 +1,67 @@
-/*
+/*
* tclInterp.c --
*
- * This file implements the "interp" command which allows creation
- * and manipulation of Tcl interpreters from within Tcl scripts.
+ * This file implements the "interp" command which allows creation and
+ * manipulation of Tcl interpreters from within Tcl scripts.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright (c) 2004 Donal K. Fellows
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
-#include <stdio.h>
-
+
/*
- * Counter for how many aliases were created (global)
+ * A pointer to a string that holds an initialization script that if non-NULL
+ * is evaluated in Tcl_Init() prior to the built-in initialization script
+ * above. This variable can be modified by the function below.
*/
-static int aliasCounter = 0;
-TCL_DECLARE_MUTEX(cntMutex)
+static char *tclPreInitScript = NULL;
+
+/* Forward declaration */
+struct Target;
/*
* struct Alias:
*
- * Stores information about an alias. Is stored in the slave interpreter
- * and used by the source command to find the target command in the master
- * when the source command is invoked.
+ * Stores information about an alias. Is stored in the slave interpreter and
+ * used by the source command to find the target command in the master when
+ * the source command is invoked.
*/
typedef struct Alias {
- Tcl_Obj *namePtr; /* Name of alias command in slave interp. */
+ Tcl_Obj *token; /* Token for the alias command in the slave
+ * interp. This used to be the command name in
+ * the slave when the alias was first
+ * created. */
Tcl_Interp *targetInterp; /* Interp in which target command will be
* invoked. */
- Tcl_Command slaveCmd; /* Source command in slave interpreter,
- * bound to command that invokes the target
- * command in the target interpreter. */
+ Tcl_Command slaveCmd; /* Source command in slave interpreter, bound
+ * to command that invokes the target command
+ * in the target interpreter. */
Tcl_HashEntry *aliasEntryPtr;
/* Entry for the alias hash table in slave.
- * This is used by alias deletion to remove
- * the alias from the slave interpreter
- * alias table. */
- Tcl_HashEntry *targetEntryPtr;
- /* Entry for target command in master.
- * This is used in the master interpreter to
- * map back from the target command to aliases
- * redirecting to it. Random access to this
- * hash table is never required - we are using
- * a hash table only for convenience. */
- int objc; /* Count of Tcl_Obj in the prefix of the
- * target command to be invoked in the
- * target interpreter. Additional arguments
- * specified when calling the alias in the
- * slave interp will be appended to the prefix
- * before the command is invoked. */
- Tcl_Obj *objPtr; /* The first actual prefix object - the target
- * command name; this has to be at the end of the
- * structure, which will be extended to accomodate
- * the remaining objects in the prefix. */
+ * This is used by alias deletion to remove
+ * the alias from the slave interpreter alias
+ * table. */
+ struct Target *targetPtr; /* Entry for target command in master. This is
+ * used in the master interpreter to map back
+ * from the target command to aliases
+ * redirecting to it. */
+ int objc; /* Count of Tcl_Obj in the prefix of the
+ * target command to be invoked in the target
+ * interpreter. Additional arguments specified
+ * when calling the alias in the slave interp
+ * will be appended to the prefix before the
+ * command is invoked. */
+ Tcl_Obj *objPtr; /* The first actual prefix object - the target
+ * command name; this has to be at the end of
+ * the structure, which will be extended to
+ * accomodate the remaining objects in the
+ * prefix. */
} Alias;
/*
@@ -65,23 +69,23 @@ typedef struct Alias {
* struct Slave:
*
* Used by the "interp" command to record and find information about slave
- * interpreters. Maps from a command name in the master to information about
- * a slave interpreter, e.g. what aliases are defined in it.
+ * interpreters. Maps from a command name in the master to information about a
+ * slave interpreter, e.g. what aliases are defined in it.
*/
typedef struct Slave {
Tcl_Interp *masterInterp; /* Master interpreter for this slave. */
Tcl_HashEntry *slaveEntryPtr;
- /* Hash entry in masters slave table for
- * this slave interpreter. Used to find
- * this record, and used when deleting the
- * slave interpreter to delete it from the
- * master's table. */
+ /* Hash entry in masters slave table for this
+ * slave interpreter. Used to find this
+ * record, and used when deleting the slave
+ * interpreter to delete it from the master's
+ * table. */
Tcl_Interp *slaveInterp; /* The slave interpreter. */
Tcl_Command interpCmd; /* Interpreter object command. */
- Tcl_HashTable aliasTable; /* Table which maps from names of commands
- * in slave interpreter to struct Alias
- * defined below. */
+ Tcl_HashTable aliasTable; /* Table which maps from names of commands in
+ * slave interpreter to struct Alias defined
+ * below. */
} Slave;
/*
@@ -92,43 +96,47 @@ typedef struct Slave {
* interpreters and must be deleted when the target interpreter is deleted. In
* case they would not be deleted the source interpreter would be left with a
* "dangling pointer". One such record is stored in the Master record of the
- * master interpreter (in the targetTable hashtable, see below) with the
- * master for each alias which directs to a command in the master. These
- * records are used to remove the source command for an from a slave if/when
- * the master is deleted.
+ * master interpreter with the master for each alias which directs to a
+ * command in the master. These records are used to remove the source command
+ * for an from a slave if/when the master is deleted. They are organized in a
+ * doubly-linked list attached to the master interpreter.
*/
typedef struct Target {
Tcl_Command slaveCmd; /* Command for alias in slave interp. */
Tcl_Interp *slaveInterp; /* Slave Interpreter. */
+ struct Target *nextPtr; /* Next in list of target records, or NULL if
+ * at the end of the list of targets. */
+ struct Target *prevPtr; /* Previous in list of target records, or NULL
+ * if at the start of the list of targets. */
} Target;
/*
* struct Master:
*
- * This record is used for two purposes: First, slaveTable (a hashtable)
- * maps from names of commands to slave interpreters. This hashtable is
- * used to store information about slave interpreters of this interpreter,
- * to map over all slaves, etc. The second purpose is to store information
- * about all aliases in slaves (or siblings) which direct to target commands
- * in this interpreter (using the targetTable hashtable).
- *
- * NB: the flags field in the interp structure, used with SAFE_INTERP
- * mask denotes whether the interpreter is safe or not. Safe
- * interpreters have restricted functionality, can only create safe slave
- * interpreters and can only load safe extensions.
+ * This record is used for two purposes: First, slaveTable (a hashtable) maps
+ * from names of commands to slave interpreters. This hashtable is used to
+ * store information about slave interpreters of this interpreter, to map over
+ * all slaves, etc. The second purpose is to store information about all
+ * aliases in slaves (or siblings) which direct to target commands in this
+ * interpreter (using the targetsPtr doubly-linked list).
+ *
+ * NB: the flags field in the interp structure, used with SAFE_INTERP mask
+ * denotes whether the interpreter is safe or not. Safe interpreters have
+ * restricted functionality, can only create safe slave interpreters and can
+ * only load safe extensions.
*/
typedef struct Master {
- Tcl_HashTable slaveTable; /* Hash table for slave interpreters.
- * Maps from command names to Slave records. */
- Tcl_HashTable targetTable; /* Hash table for Target Records. Contains
- * all Target records which denote aliases
- * from slaves or sibling interpreters that
- * direct to commands in this interpreter. This
- * table is used to remove dangling pointers
- * from the slave (or sibling) interpreters
- * when this interpreter is deleted. */
+ Tcl_HashTable slaveTable; /* Hash table for slave interpreters. Maps
+ * from command names to Slave records. */
+ Target *targetsPtr; /* The head of a doubly-linked list of all the
+ * target records which denote aliases from
+ * slaves or sibling interpreters that direct
+ * to commands in this interpreter. This list
+ * is used to remove dangling pointers from
+ * the slave (or sibling) interpreters when
+ * this interpreter is deleted. */
} Master;
/*
@@ -144,67 +152,268 @@ typedef struct InterpInfo {
} InterpInfo;
/*
- * Prototypes for local static procedures:
+ * Limit callbacks handled by scripts are modelled as structures which are
+ * stored in hashes indexed by a two-word key. Note that the type of the
+ * 'type' field in the key is not int; this is to make sure that things are
+ * likely to work properly on 64-bit architectures.
+ */
+
+typedef struct ScriptLimitCallback {
+ Tcl_Interp *interp; /* The interpreter in which to execute the
+ * callback. */
+ Tcl_Obj *scriptObj; /* The script to execute to perform the
+ * user-defined part of the callback. */
+ int type; /* What kind of callback is this. */
+ Tcl_HashEntry *entryPtr; /* The entry in the hash table maintained by
+ * the target interpreter that refers to this
+ * callback record, or NULL if the entry has
+ * already been deleted from that hash
+ * table. */
+} ScriptLimitCallback;
+
+typedef struct ScriptLimitCallbackKey {
+ Tcl_Interp *interp; /* The interpreter that the limit callback was
+ * attached to. This is not the interpreter
+ * that the callback runs in! */
+ long type; /* The type of callback that this is. */
+} ScriptLimitCallbackKey;
+
+/*
+ * Prototypes for local static functions:
*/
-static int AliasCreate _ANSI_ARGS_((Tcl_Interp *interp,
+static int AliasCreate(Tcl_Interp *interp,
Tcl_Interp *slaveInterp, Tcl_Interp *masterInterp,
Tcl_Obj *namePtr, Tcl_Obj *targetPtr, int objc,
- Tcl_Obj *CONST objv[]));
-static int AliasDelete _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Interp *slaveInterp, Tcl_Obj *namePtr));
-static int AliasDescribe _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Interp *slaveInterp, Tcl_Obj *objPtr));
-static int AliasList _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Interp *slaveInterp));
-static int AliasObjCmd _ANSI_ARGS_((ClientData dummy,
+ Tcl_Obj *const objv[]);
+static int AliasDelete(Tcl_Interp *interp,
+ Tcl_Interp *slaveInterp, Tcl_Obj *namePtr);
+static int AliasDescribe(Tcl_Interp *interp,
+ Tcl_Interp *slaveInterp, Tcl_Obj *objPtr);
+static int AliasList(Tcl_Interp *interp, Tcl_Interp *slaveInterp);
+static int AliasObjCmd(ClientData dummy,
Tcl_Interp *currentInterp, int objc,
- Tcl_Obj *CONST objv[]));
-static void AliasObjCmdDeleteProc _ANSI_ARGS_((
- ClientData clientData));
-
-static Tcl_Interp * GetInterp _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *pathPtr));
-static Tcl_Interp * GetInterp2 _ANSI_ARGS_((Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static void InterpInfoDeleteProc _ANSI_ARGS_((
- ClientData clientData, Tcl_Interp *interp));
-static Tcl_Interp * SlaveCreate _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *pathPtr, int safe));
-static int SlaveEval _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *const objv[]);
+static void AliasObjCmdDeleteProc(ClientData clientData);
+static Tcl_Interp * GetInterp(Tcl_Interp *interp, Tcl_Obj *pathPtr);
+static Tcl_Interp * GetInterp2(Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static void InterpInfoDeleteProc(ClientData clientData,
+ Tcl_Interp *interp);
+static int SlaveBgerror(Tcl_Interp *interp,
Tcl_Interp *slaveInterp, int objc,
- Tcl_Obj *CONST objv[]));
-static int SlaveExpose _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *const objv[]);
+static Tcl_Interp * SlaveCreate(Tcl_Interp *interp, Tcl_Obj *pathPtr,
+ int safe);
+static int SlaveDebugCmd(Tcl_Interp *interp,
+ Tcl_Interp *slaveInterp,
+ int objc, Tcl_Obj *const objv[]);
+static int SlaveEval(Tcl_Interp *interp, Tcl_Interp *slaveInterp,
+ int objc, Tcl_Obj *const objv[]);
+static int SlaveExpose(Tcl_Interp *interp,
Tcl_Interp *slaveInterp, int objc,
- Tcl_Obj *CONST objv[]));
-static int SlaveHide _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *const objv[]);
+static int SlaveHide(Tcl_Interp *interp, Tcl_Interp *slaveInterp,
+ int objc, Tcl_Obj *const objv[]);
+static int SlaveHidden(Tcl_Interp *interp,
+ Tcl_Interp *slaveInterp);
+static int SlaveInvokeHidden(Tcl_Interp *interp,
+ Tcl_Interp *slaveInterp,
+ const char *namespaceName,
+ int objc, Tcl_Obj *const objv[]);
+static int SlaveMarkTrusted(Tcl_Interp *interp,
+ Tcl_Interp *slaveInterp);
+static int SlaveObjCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static void SlaveObjCmdDeleteProc(ClientData clientData);
+static int SlaveRecursionLimit(Tcl_Interp *interp,
Tcl_Interp *slaveInterp, int objc,
- Tcl_Obj *CONST objv[]));
-static int SlaveHidden _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Interp *slaveInterp));
-static int SlaveInvokeHidden _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Interp *slaveInterp, int global, int objc,
- Tcl_Obj *CONST objv[]));
-static int SlaveMarkTrusted _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Interp *slaveInterp));
-static int SlaveObjCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static void SlaveObjCmdDeleteProc _ANSI_ARGS_((
- ClientData clientData));
-static int SlaveRecursionLimit _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Interp *slaveInterp, int objc,
- Tcl_Obj *CONST objv[]));
+ Tcl_Obj *const objv[]);
+static int SlaveCommandLimitCmd(Tcl_Interp *interp,
+ Tcl_Interp *slaveInterp, int consumedObjc,
+ int objc, Tcl_Obj *const objv[]);
+static int SlaveTimeLimitCmd(Tcl_Interp *interp,
+ Tcl_Interp *slaveInterp, int consumedObjc,
+ int objc, Tcl_Obj *const objv[]);
+static void InheritLimitsFromMaster(Tcl_Interp *slaveInterp,
+ Tcl_Interp *masterInterp);
+static void SetScriptLimitCallback(Tcl_Interp *interp, int type,
+ Tcl_Interp *targetInterp, Tcl_Obj *scriptObj);
+static void CallScriptLimitCallback(ClientData clientData,
+ Tcl_Interp *interp);
+static void DeleteScriptLimitCallback(ClientData clientData);
+static void RunLimitHandlers(LimitHandler *handlerPtr,
+ Tcl_Interp *interp);
+static void TimeLimitCallback(ClientData clientData);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclSetPreInitScript --
+ *
+ * This routine is used to change the value of the internal variable,
+ * tclPreInitScript.
+ *
+ * Results:
+ * Returns the current value of tclPreInitScript.
+ *
+ * Side effects:
+ * Changes the way Tcl_Init() routine behaves.
+ *
+ *----------------------------------------------------------------------
+ */
+char *
+TclSetPreInitScript(
+ char *string) /* Pointer to a script. */
+{
+ char *prevString = tclPreInitScript;
+ tclPreInitScript = string;
+ return(prevString);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_Init --
+ *
+ * This function is typically invoked by Tcl_AppInit functions to find
+ * and source the "init.tcl" script, which should exist somewhere on the
+ * Tcl library path.
+ *
+ * Results:
+ * Returns a standard Tcl completion code and sets the interp's result if
+ * there is an error.
+ *
+ * Side effects:
+ * Depends on what's in the init.tcl script.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_Init(
+ Tcl_Interp *interp) /* Interpreter to initialize. */
+{
+ if (tclPreInitScript != NULL) {
+ if (Tcl_Eval(interp, tclPreInitScript) == TCL_ERROR) {
+ return (TCL_ERROR);
+ };
+ }
+
+ /*
+ * In order to find init.tcl during initialization, the following script
+ * is invoked by Tcl_Init(). It looks in several different directories:
+ *
+ * $tcl_library - can specify a primary location, if set, no
+ * other locations will be checked. This is the
+ * recommended way for a program that embeds
+ * Tcl to specifically tell Tcl where to find
+ * an init.tcl file.
+ *
+ * $env(TCL_LIBRARY) - highest priority so user can always override
+ * the search path unless the application has
+ * specified an exact directory above
+ *
+ * $tclDefaultLibrary - INTERNAL: This variable is set by Tcl on
+ * those platforms where it can determine at
+ * runtime the directory where it expects the
+ * init.tcl file to be. After [tclInit] reads
+ * and uses this value, it [unset]s it.
+ * External users of Tcl should not make use of
+ * the variable to customize [tclInit].
+ *
+ * $tcl_libPath - OBSOLETE: This variable is no longer set by
+ * Tcl itself, but [tclInit] examines it in
+ * case some program that embeds Tcl is
+ * customizing [tclInit] by setting this
+ * variable to a list of directories in which
+ * to search.
+ *
+ * [tcl::pkgconfig get scriptdir,runtime]
+ * - the directory determined by configure to be
+ * the place where Tcl's script library is to
+ * be installed.
+ *
+ * The first directory on this path that contains a valid init.tcl script
+ * will be set as the value of tcl_library.
+ *
+ * Note that this entire search mechanism can be bypassed by defining an
+ * alternate tclInit command before calling Tcl_Init().
+ */
+
+ return Tcl_Eval(interp,
+"if {[namespace which -command tclInit] eq \"\"} {\n"
+" proc tclInit {} {\n"
+" global tcl_libPath tcl_library env tclDefaultLibrary\n"
+" rename tclInit {}\n"
+" if {[info exists tcl_library]} {\n"
+" set scripts {{set tcl_library}}\n"
+" } else {\n"
+" set scripts {}\n"
+" if {[info exists env(TCL_LIBRARY)] && ($env(TCL_LIBRARY) ne {})} {\n"
+" lappend scripts {set env(TCL_LIBRARY)}\n"
+" lappend scripts {\n"
+"if {[regexp ^tcl(.*)$ [file tail $env(TCL_LIBRARY)] -> tail] == 0} continue\n"
+"if {$tail eq [info tclversion]} continue\n"
+"file join [file dirname $env(TCL_LIBRARY)] tcl[info tclversion]}\n"
+" }\n"
+" if {[info exists tclDefaultLibrary]} {\n"
+" lappend scripts {set tclDefaultLibrary}\n"
+" } else {\n"
+" lappend scripts {::tcl::pkgconfig get scriptdir,runtime}\n"
+" }\n"
+" lappend scripts {\n"
+"set parentDir [file dirname [file dirname [info nameofexecutable]]]\n"
+"set grandParentDir [file dirname $parentDir]\n"
+"file join $parentDir lib tcl[info tclversion]} \\\n"
+" {file join $grandParentDir lib tcl[info tclversion]} \\\n"
+" {file join $parentDir library} \\\n"
+" {file join $grandParentDir library} \\\n"
+" {file join $grandParentDir tcl[info patchlevel] library} \\\n"
+" {\n"
+"file join [file dirname $grandParentDir] tcl[info patchlevel] library}\n"
+" if {[info exists tcl_libPath]\n"
+" && [catch {llength $tcl_libPath} len] == 0} {\n"
+" for {set i 0} {$i < $len} {incr i} {\n"
+" lappend scripts [list lindex \\$tcl_libPath $i]\n"
+" }\n"
+" }\n"
+" }\n"
+" set dirs {}\n"
+" set errors {}\n"
+" foreach script $scripts {\n"
+" lappend dirs [eval $script]\n"
+" set tcl_library [lindex $dirs end]\n"
+" set tclfile [file join $tcl_library init.tcl]\n"
+" if {[file exists $tclfile]} {\n"
+" if {[catch {uplevel #0 [list source $tclfile]} msg opts]} {\n"
+" append errors \"$tclfile: $msg\n\"\n"
+" append errors \"[dict get $opts -errorinfo]\n\"\n"
+" continue\n"
+" }\n"
+" unset -nocomplain tclDefaultLibrary\n"
+" return\n"
+" }\n"
+" }\n"
+" unset -nocomplain tclDefaultLibrary\n"
+" set msg \"Can't find a usable init.tcl in the following directories: \n\"\n"
+" append msg \" $dirs\n\n\"\n"
+" append msg \"$errors\n\n\"\n"
+" append msg \"This probably means that Tcl wasn't installed properly.\n\"\n"
+" error $msg\n"
+" }\n"
+"}\n"
+"tclInit");
+}
/*
*---------------------------------------------------------------------------
*
* TclInterpInit --
*
- * Initializes the invoking interpreter for using the master, slave
- * and safe interp facilities. This is called from inside
- * Tcl_CreateInterp().
+ * Initializes the invoking interpreter for using the master, slave and
+ * safe interp facilities. This is called from inside Tcl_CreateInterp().
*
* Results:
* Always returns TCL_OK for backwards compatibility.
@@ -217,19 +426,19 @@ static int SlaveRecursionLimit _ANSI_ARGS_((Tcl_Interp *interp,
*/
int
-TclInterpInit(interp)
- Tcl_Interp *interp; /* Interpreter to initialize. */
+TclInterpInit(
+ Tcl_Interp *interp) /* Interpreter to initialize. */
{
InterpInfo *interpInfoPtr;
Master *masterPtr;
- Slave *slavePtr;
+ Slave *slavePtr;
interpInfoPtr = (InterpInfo *) ckalloc(sizeof(InterpInfo));
- ((Interp *) interp)->interpInfo = (ClientData) interpInfoPtr;
+ ((Interp *) interp)->interpInfo = interpInfoPtr;
masterPtr = &interpInfoPtr->master;
Tcl_InitHashTable(&masterPtr->slaveTable, TCL_STRING_KEYS);
- Tcl_InitHashTable(&masterPtr->targetTable, TCL_ONE_WORD_KEYS);
+ masterPtr->targetsPtr = NULL;
slavePtr = &interpInfoPtr->slave;
slavePtr->masterInterp = NULL;
@@ -249,30 +458,27 @@ TclInterpInit(interp)
*
* InterpInfoDeleteProc --
*
- * Invoked when an interpreter is being deleted. It releases all
- * storage used by the master/slave/safe interpreter facilities.
+ * Invoked when an interpreter is being deleted. It releases all storage
+ * used by the master/slave/safe interpreter facilities.
*
* Results:
* None.
*
* Side effects:
- * Cleans up storage. Sets the interpInfoPtr field of the interp
- * to NULL.
+ * Cleans up storage. Sets the interpInfoPtr field of the interp to NULL.
*
*---------------------------------------------------------------------------
*/
static void
-InterpInfoDeleteProc(clientData, interp)
- ClientData clientData; /* Ignored. */
- Tcl_Interp *interp; /* Interp being deleted. All commands for
+InterpInfoDeleteProc(
+ ClientData clientData, /* Ignored. */
+ Tcl_Interp *interp) /* Interp being deleted. All commands for
* slave interps should already be deleted. */
{
InterpInfo *interpInfoPtr;
Slave *slavePtr;
Master *masterPtr;
- Tcl_HashSearch hSearch;
- Tcl_HashEntry *hPtr;
Target *targetPtr;
interpInfoPtr = (InterpInfo *) ((Interp *) interp)->interpInfo;
@@ -283,36 +489,34 @@ InterpInfoDeleteProc(clientData, interp)
masterPtr = &interpInfoPtr->master;
if (masterPtr->slaveTable.numEntries != 0) {
- panic("InterpInfoDeleteProc: still exist commands");
+ Tcl_Panic("InterpInfoDeleteProc: still exist commands");
}
Tcl_DeleteHashTable(&masterPtr->slaveTable);
/*
* Tell any interps that have aliases to this interp that they should
- * delete those aliases. If the other interp was already dead, it
- * would have removed the target record already.
+ * delete those aliases. If the other interp was already dead, it would
+ * have removed the target record already.
*/
- hPtr = Tcl_FirstHashEntry(&masterPtr->targetTable, &hSearch);
- while (hPtr != NULL) {
- targetPtr = (Target *) Tcl_GetHashValue(hPtr);
+ for (targetPtr = masterPtr->targetsPtr; targetPtr != NULL; ) {
+ Target *tmpPtr = targetPtr->nextPtr;
Tcl_DeleteCommandFromToken(targetPtr->slaveInterp,
targetPtr->slaveCmd);
- hPtr = Tcl_NextHashEntry(&hSearch);
+ targetPtr = tmpPtr;
}
- Tcl_DeleteHashTable(&masterPtr->targetTable);
slavePtr = &interpInfoPtr->slave;
if (slavePtr->interpCmd != NULL) {
/*
- * Tcl_DeleteInterp() was called on this interpreter, rather
- * "interp delete" or the equivalent deletion of the command in the
- * master. First ensure that the cleanup callback doesn't try to
- * delete the interp again.
+ * Tcl_DeleteInterp() was called on this interpreter, rather "interp
+ * delete" or the equivalent deletion of the command in the master.
+ * First ensure that the cleanup callback doesn't try to delete the
+ * interp again.
*/
slavePtr->slaveInterp = NULL;
- Tcl_DeleteCommandFromToken(slavePtr->masterInterp,
+ Tcl_DeleteCommandFromToken(slavePtr->masterInterp,
slavePtr->interpCmd);
}
@@ -321,11 +525,11 @@ InterpInfoDeleteProc(clientData, interp)
*/
if (slavePtr->aliasTable.numEntries != 0) {
- panic("InterpInfoDeleteProc: still exist aliases");
+ Tcl_Panic("InterpInfoDeleteProc: still exist aliases");
}
Tcl_DeleteHashTable(&slavePtr->aliasTable);
- ckfree((char *) interpInfoPtr);
+ ckfree((char *) interpInfoPtr);
}
/*
@@ -333,8 +537,8 @@ InterpInfoDeleteProc(clientData, interp)
*
* Tcl_InterpObjCmd --
*
- * This procedure is invoked to process the "interp" Tcl command.
- * See the user documentation for details on what it does.
+ * This function is invoked to process the "interp" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -346,430 +550,472 @@ InterpInfoDeleteProc(clientData, interp)
*/
/* ARGSUSED */
int
-Tcl_InterpObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Unused. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_InterpObjCmd(
+ ClientData clientData, /* Unused. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
int index;
- static CONST char *options[] = {
- "alias", "aliases", "create", "delete",
- "eval", "exists", "expose", "hide",
- "hidden", "issafe", "invokehidden", "marktrusted",
- "recursionlimit", "slaves", "share",
- "target", "transfer",
- NULL
+ static const char *options[] = {
+ "alias", "aliases", "bgerror", "create",
+ "debug", "delete", "eval", "exists", "expose",
+ "hide", "hidden", "issafe", "invokehidden",
+ "limit", "marktrusted", "recursionlimit","slaves",
+ "share", "target", "transfer",
+ NULL
};
enum option {
- OPT_ALIAS, OPT_ALIASES, OPT_CREATE, OPT_DELETE,
- OPT_EVAL, OPT_EXISTS, OPT_EXPOSE, OPT_HIDE,
- OPT_HIDDEN, OPT_ISSAFE, OPT_INVOKEHID, OPT_MARKTRUSTED,
- OPT_RECLIMIT, OPT_SLAVES, OPT_SHARE,
- OPT_TARGET, OPT_TRANSFER
+ OPT_ALIAS, OPT_ALIASES, OPT_BGERROR, OPT_CREATE,
+ OPT_DEBUG, OPT_DELETE, OPT_EVAL, OPT_EXISTS, OPT_EXPOSE,
+ OPT_HIDE, OPT_HIDDEN, OPT_ISSAFE, OPT_INVOKEHID,
+ OPT_LIMIT, OPT_MARKTRUSTED,OPT_RECLIMIT, OPT_SLAVES,
+ OPT_SHARE, OPT_TARGET, OPT_TRANSFER
};
-
if (objc < 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "cmd ?arg ...?");
- return TCL_ERROR;
+ Tcl_WrongNumArgs(interp, 1, objv, "cmd ?arg ...?");
+ return TCL_ERROR;
}
- if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0,
+ if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0,
&index) != TCL_OK) {
return TCL_ERROR;
}
switch ((enum option) index) {
- case OPT_ALIAS: {
- Tcl_Interp *slaveInterp, *masterInterp;
+ case OPT_ALIAS: {
+ Tcl_Interp *slaveInterp, *masterInterp;
- if (objc < 4) {
- aliasArgs:
- Tcl_WrongNumArgs(interp, 2, objv,
- "slavePath slaveCmd ?masterPath masterCmd? ?args ..?");
- return TCL_ERROR;
- }
- slaveInterp = GetInterp(interp, objv[2]);
- if (slaveInterp == (Tcl_Interp *) NULL) {
+ if (objc < 4) {
+ aliasArgs:
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "slavePath slaveCmd ?masterPath masterCmd? ?args ..?");
+ return TCL_ERROR;
+ }
+ slaveInterp = GetInterp(interp, objv[2]);
+ if (slaveInterp == NULL) {
+ return TCL_ERROR;
+ }
+ if (objc == 4) {
+ return AliasDescribe(interp, slaveInterp, objv[3]);
+ }
+ if ((objc == 5) && (TclGetString(objv[4])[0] == '\0')) {
+ return AliasDelete(interp, slaveInterp, objv[3]);
+ }
+ if (objc > 5) {
+ masterInterp = GetInterp(interp, objv[4]);
+ if (masterInterp == NULL) {
return TCL_ERROR;
}
- if (objc == 4) {
- return AliasDescribe(interp, slaveInterp, objv[3]);
- }
- if ((objc == 5) && (Tcl_GetString(objv[4])[0] == '\0')) {
- return AliasDelete(interp, slaveInterp, objv[3]);
- }
- if (objc > 5) {
- masterInterp = GetInterp(interp, objv[4]);
- if (masterInterp == (Tcl_Interp *) NULL) {
- return TCL_ERROR;
- }
- if (Tcl_GetString(objv[5])[0] == '\0') {
- if (objc == 6) {
- return AliasDelete(interp, slaveInterp, objv[3]);
- }
- } else {
- return AliasCreate(interp, slaveInterp, masterInterp,
- objv[3], objv[5], objc - 6, objv + 6);
+ if (TclGetString(objv[5])[0] == '\0') {
+ if (objc == 6) {
+ return AliasDelete(interp, slaveInterp, objv[3]);
}
+ } else {
+ return AliasCreate(interp, slaveInterp, masterInterp, objv[3],
+ objv[5], objc - 6, objv + 6);
}
- goto aliasArgs;
}
- case OPT_ALIASES: {
- Tcl_Interp *slaveInterp;
+ goto aliasArgs;
+ }
+ case OPT_ALIASES: {
+ Tcl_Interp *slaveInterp;
- slaveInterp = GetInterp2(interp, objc, objv);
- if (slaveInterp == NULL) {
- return TCL_ERROR;
- }
- return AliasList(interp, slaveInterp);
- }
- case OPT_CREATE: {
- int i, last, safe;
- Tcl_Obj *slavePtr;
- char buf[16 + TCL_INTEGER_SPACE];
- static CONST char *options[] = {
- "-safe", "--", NULL
- };
- enum option {
- OPT_SAFE, OPT_LAST
- };
-
- safe = Tcl_IsSafe(interp);
-
- /*
- * Weird historical rules: "-safe" is accepted at the end, too.
- */
+ slaveInterp = GetInterp2(interp, objc, objv);
+ if (slaveInterp == NULL) {
+ return TCL_ERROR;
+ }
+ return AliasList(interp, slaveInterp);
+ }
+ case OPT_BGERROR: {
+ Tcl_Interp *slaveInterp;
- slavePtr = NULL;
- last = 0;
- for (i = 2; i < objc; i++) {
- if ((last == 0) && (Tcl_GetString(objv[i])[0] == '-')) {
- if (Tcl_GetIndexFromObj(interp, objv[i], options, "option",
- 0, &index) != TCL_OK) {
- return TCL_ERROR;
- }
- if (index == OPT_SAFE) {
- safe = 1;
- continue;
- }
- i++;
- last = 1;
- }
- if (slavePtr != NULL) {
- Tcl_WrongNumArgs(interp, 2, objv, "?-safe? ?--? ?path?");
+ if (objc != 3 && objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "path ?cmdPrefix?");
+ return TCL_ERROR;
+ }
+ slaveInterp = GetInterp(interp, objv[2]);
+ if (slaveInterp == NULL) {
+ return TCL_ERROR;
+ }
+ return SlaveBgerror(interp, slaveInterp, objc - 3, objv + 3);
+ }
+ case OPT_CREATE: {
+ int i, last, safe;
+ Tcl_Obj *slavePtr;
+ char buf[16 + TCL_INTEGER_SPACE];
+ static const char *options[] = {
+ "-safe", "--", NULL
+ };
+ enum option {
+ OPT_SAFE, OPT_LAST
+ };
+
+ safe = Tcl_IsSafe(interp);
+
+ /*
+ * Weird historical rules: "-safe" is accepted at the end, too.
+ */
+
+ slavePtr = NULL;
+ last = 0;
+ for (i = 2; i < objc; i++) {
+ if ((last == 0) && (Tcl_GetString(objv[i])[0] == '-')) {
+ if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
+ &index) != TCL_OK) {
return TCL_ERROR;
}
- if (i < objc) {
- slavePtr = objv[i];
- }
- }
- buf[0] = '\0';
- if (slavePtr == NULL) {
- /*
- * Create an anonymous interpreter -- we choose its name and
- * the name of the command. We check that the command name
- * that we use for the interpreter does not collide with an
- * existing command in the master interpreter.
- */
-
- for (i = 0; ; i++) {
- Tcl_CmdInfo cmdInfo;
-
- sprintf(buf, "interp%d", i);
- if (Tcl_GetCommandInfo(interp, buf, &cmdInfo) == 0) {
- break;
- }
+ if (index == OPT_SAFE) {
+ safe = 1;
+ continue;
}
- slavePtr = Tcl_NewStringObj(buf, -1);
+ i++;
+ last = 1;
}
- if (SlaveCreate(interp, slavePtr, safe) == NULL) {
- if (buf[0] != '\0') {
- Tcl_DecrRefCount(slavePtr);
- }
+ if (slavePtr != NULL) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-safe? ?--? ?path?");
return TCL_ERROR;
}
- Tcl_SetObjResult(interp, slavePtr);
- return TCL_OK;
- }
- case OPT_DELETE: {
- int i;
- InterpInfo *iiPtr;
- Tcl_Interp *slaveInterp;
-
- for (i = 2; i < objc; i++) {
- slaveInterp = GetInterp(interp, objv[i]);
- if (slaveInterp == NULL) {
- return TCL_ERROR;
- } else if (slaveInterp == interp) {
- Tcl_ResetResult(interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "cannot delete the current interpreter",
- (char *) NULL);
- return TCL_ERROR;
- }
- iiPtr = (InterpInfo *) ((Interp *) slaveInterp)->interpInfo;
- Tcl_DeleteCommandFromToken(iiPtr->slave.masterInterp,
- iiPtr->slave.interpCmd);
+ if (i < objc) {
+ slavePtr = objv[i];
}
- return TCL_OK;
}
- case OPT_EVAL: {
- Tcl_Interp *slaveInterp;
+ buf[0] = '\0';
+ if (slavePtr == NULL) {
+ /*
+ * Create an anonymous interpreter -- we choose its name and the
+ * name of the command. We check that the command name that we use
+ * for the interpreter does not collide with an existing command
+ * in the master interpreter.
+ */
- if (objc < 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "path arg ?arg ...?");
- return TCL_ERROR;
+ for (i = 0; ; i++) {
+ Tcl_CmdInfo cmdInfo;
+
+ sprintf(buf, "interp%d", i);
+ if (Tcl_GetCommandInfo(interp, buf, &cmdInfo) == 0) {
+ break;
+ }
}
- slaveInterp = GetInterp(interp, objv[2]);
- if (slaveInterp == NULL) {
- return TCL_ERROR;
+ slavePtr = Tcl_NewStringObj(buf, -1);
+ }
+ if (SlaveCreate(interp, slavePtr, safe) == NULL) {
+ if (buf[0] != '\0') {
+ Tcl_DecrRefCount(slavePtr);
}
- return SlaveEval(interp, slaveInterp, objc - 3, objv + 3);
+ return TCL_ERROR;
}
- case OPT_EXISTS: {
- int exists;
- Tcl_Interp *slaveInterp;
+ Tcl_SetObjResult(interp, slavePtr);
+ return TCL_OK;
+ }
+ case OPT_DEBUG: {
+ /* TIP #378 */
+ Tcl_Interp *slaveInterp;
- exists = 1;
- slaveInterp = GetInterp2(interp, objc, objv);
- if (slaveInterp == NULL) {
- if (objc > 3) {
- return TCL_ERROR;
- }
- Tcl_ResetResult(interp);
- exists = 0;
- }
- Tcl_SetIntObj(Tcl_GetObjResult(interp), exists);
- return TCL_OK;
+ /*
+ * Currently only -frame supported, otherwise ?-option ?value??
+ */
+ if (objc < 3 || objc > 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "path ?-frame ?bool??");
+ return TCL_ERROR;
}
- case OPT_EXPOSE: {
- Tcl_Interp *slaveInterp;
+ slaveInterp = GetInterp(interp, objv[2]);
+ if (slaveInterp == NULL) {
+ return TCL_ERROR;
+ }
+ return SlaveDebugCmd(interp, slaveInterp, objc - 3, objv + 3);
+ }
+ case OPT_DELETE: {
+ int i;
+ InterpInfo *iiPtr;
+ Tcl_Interp *slaveInterp;
- if ((objc < 4) || (objc > 5)) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "path hiddenCmdName ?cmdName?");
- return TCL_ERROR;
- }
- slaveInterp = GetInterp(interp, objv[2]);
+ for (i = 2; i < objc; i++) {
+ slaveInterp = GetInterp(interp, objv[i]);
if (slaveInterp == NULL) {
return TCL_ERROR;
+ } else if (slaveInterp == interp) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "cannot delete the current interpreter", -1));
+ return TCL_ERROR;
}
- return SlaveExpose(interp, slaveInterp, objc - 3, objv + 3);
+ iiPtr = (InterpInfo *) ((Interp *) slaveInterp)->interpInfo;
+ Tcl_DeleteCommandFromToken(iiPtr->slave.masterInterp,
+ iiPtr->slave.interpCmd);
}
- case OPT_HIDE: {
- Tcl_Interp *slaveInterp; /* A slave. */
+ return TCL_OK;
+ }
+ case OPT_EVAL: {
+ Tcl_Interp *slaveInterp;
- if ((objc < 4) || (objc > 5)) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "path cmdName ?hiddenCmdName?");
- return TCL_ERROR;
- }
- slaveInterp = GetInterp(interp, objv[2]);
- if (slaveInterp == (Tcl_Interp *) NULL) {
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "path arg ?arg ...?");
+ return TCL_ERROR;
+ }
+ slaveInterp = GetInterp(interp, objv[2]);
+ if (slaveInterp == NULL) {
+ return TCL_ERROR;
+ }
+ return SlaveEval(interp, slaveInterp, objc - 3, objv + 3);
+ }
+ case OPT_EXISTS: {
+ int exists;
+ Tcl_Interp *slaveInterp;
+
+ exists = 1;
+ slaveInterp = GetInterp2(interp, objc, objv);
+ if (slaveInterp == NULL) {
+ if (objc > 3) {
return TCL_ERROR;
}
- return SlaveHide(interp, slaveInterp, objc - 3, objv + 3);
+ Tcl_ResetResult(interp);
+ exists = 0;
}
- case OPT_HIDDEN: {
- Tcl_Interp *slaveInterp; /* A slave. */
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(exists));
+ return TCL_OK;
+ }
+ case OPT_EXPOSE: {
+ Tcl_Interp *slaveInterp;
- slaveInterp = GetInterp2(interp, objc, objv);
- if (slaveInterp == NULL) {
- return TCL_ERROR;
- }
- return SlaveHidden(interp, slaveInterp);
+ if ((objc < 4) || (objc > 5)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "path hiddenCmdName ?cmdName?");
+ return TCL_ERROR;
+ }
+ slaveInterp = GetInterp(interp, objv[2]);
+ if (slaveInterp == NULL) {
+ return TCL_ERROR;
}
- case OPT_ISSAFE: {
- Tcl_Interp *slaveInterp;
+ return SlaveExpose(interp, slaveInterp, objc - 3, objv + 3);
+ }
+ case OPT_HIDE: {
+ Tcl_Interp *slaveInterp; /* A slave. */
- slaveInterp = GetInterp2(interp, objc, objv);
- if (slaveInterp == NULL) {
+ if ((objc < 4) || (objc > 5)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "path cmdName ?hiddenCmdName?");
+ return TCL_ERROR;
+ }
+ slaveInterp = GetInterp(interp, objv[2]);
+ if (slaveInterp == NULL) {
+ return TCL_ERROR;
+ }
+ return SlaveHide(interp, slaveInterp, objc - 3, objv + 3);
+ }
+ case OPT_HIDDEN: {
+ Tcl_Interp *slaveInterp; /* A slave. */
+
+ slaveInterp = GetInterp2(interp, objc, objv);
+ if (slaveInterp == NULL) {
+ return TCL_ERROR;
+ }
+ return SlaveHidden(interp, slaveInterp);
+ }
+ case OPT_ISSAFE: {
+ Tcl_Interp *slaveInterp;
+
+ slaveInterp = GetInterp2(interp, objc, objv);
+ if (slaveInterp == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(Tcl_IsSafe(slaveInterp)));
+ return TCL_OK;
+ }
+ case OPT_INVOKEHID: {
+ int i, index;
+ const char *namespaceName;
+ Tcl_Interp *slaveInterp;
+ static const char *hiddenOptions[] = {
+ "-global", "-namespace", "--", NULL
+ };
+ enum hiddenOption {
+ OPT_GLOBAL, OPT_NAMESPACE, OPT_LAST
+ };
+
+ namespaceName = NULL;
+ for (i = 3; i < objc; i++) {
+ if (TclGetString(objv[i])[0] != '-') {
+ break;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[i], hiddenOptions, "option",
+ 0, &index) != TCL_OK) {
return TCL_ERROR;
}
- Tcl_SetIntObj(Tcl_GetObjResult(interp), Tcl_IsSafe(slaveInterp));
- return TCL_OK;
- }
- case OPT_INVOKEHID: {
- int i, index, global;
- Tcl_Interp *slaveInterp;
- static CONST char *hiddenOptions[] = {
- "-global", "--", NULL
- };
- enum hiddenOption {
- OPT_GLOBAL, OPT_LAST
- };
-
- global = 0;
- for (i = 3; i < objc; i++) {
- if (Tcl_GetString(objv[i])[0] != '-') {
+ if (index == OPT_GLOBAL) {
+ namespaceName = "::";
+ } else if (index == OPT_NAMESPACE) {
+ if (++i == objc) { /* There must be more arguments. */
break;
- }
- if (Tcl_GetIndexFromObj(interp, objv[i], hiddenOptions,
- "option", 0, &index) != TCL_OK) {
- return TCL_ERROR;
- }
- if (index == OPT_GLOBAL) {
- global = 1;
} else {
- i++;
- break;
+ namespaceName = TclGetString(objv[i]);
}
+ } else {
+ i++;
+ break;
}
- if (objc - i < 1) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "path ?-global? ?--? cmd ?arg ..?");
- return TCL_ERROR;
- }
- slaveInterp = GetInterp(interp, objv[2]);
- if (slaveInterp == (Tcl_Interp *) NULL) {
- return TCL_ERROR;
- }
- return SlaveInvokeHidden(interp, slaveInterp, global, objc - i,
- objv + i);
}
- case OPT_MARKTRUSTED: {
- Tcl_Interp *slaveInterp;
+ if (objc - i < 1) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "path ?-namespace ns? ?-global? ?--? cmd ?arg ..?");
+ return TCL_ERROR;
+ }
+ slaveInterp = GetInterp(interp, objv[2]);
+ if (slaveInterp == NULL) {
+ return TCL_ERROR;
+ }
+ return SlaveInvokeHidden(interp, slaveInterp, namespaceName, objc - i,
+ objv + i);
+ }
+ case OPT_LIMIT: {
+ Tcl_Interp *slaveInterp;
+ static const char *limitTypes[] = {
+ "commands", "time", NULL
+ };
+ enum LimitTypes {
+ LIMIT_TYPE_COMMANDS, LIMIT_TYPE_TIME
+ };
+ int limitType;
+
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "path limitType ?options?");
+ return TCL_ERROR;
+ }
+ slaveInterp = GetInterp(interp, objv[2]);
+ if (slaveInterp == NULL) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[3], limitTypes, "limit type", 0,
+ &limitType) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum LimitTypes) limitType) {
+ case LIMIT_TYPE_COMMANDS:
+ return SlaveCommandLimitCmd(interp, slaveInterp, 4, objc,objv);
+ case LIMIT_TYPE_TIME:
+ return SlaveTimeLimitCmd(interp, slaveInterp, 4, objc, objv);
+ }
+ }
+ case OPT_MARKTRUSTED: {
+ Tcl_Interp *slaveInterp;
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "path");
- return TCL_ERROR;
- }
- slaveInterp = GetInterp(interp, objv[2]);
- if (slaveInterp == NULL) {
- return TCL_ERROR;
- }
- return SlaveMarkTrusted(interp, slaveInterp);
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "path");
+ return TCL_ERROR;
}
- case OPT_RECLIMIT: {
- Tcl_Interp *slaveInterp;
+ slaveInterp = GetInterp(interp, objv[2]);
+ if (slaveInterp == NULL) {
+ return TCL_ERROR;
+ }
+ return SlaveMarkTrusted(interp, slaveInterp);
+ }
+ case OPT_RECLIMIT: {
+ Tcl_Interp *slaveInterp;
- if (objc != 3 && objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "path ?newlimit?");
- return TCL_ERROR;
- }
- slaveInterp = GetInterp(interp, objv[2]);
- if (slaveInterp == NULL) {
- return TCL_ERROR;
- }
- return SlaveRecursionLimit(interp, slaveInterp, objc - 3, objv + 3);
- }
- case OPT_SLAVES: {
- Tcl_Interp *slaveInterp;
- InterpInfo *iiPtr;
- Tcl_Obj *resultPtr;
- Tcl_HashEntry *hPtr;
- Tcl_HashSearch hashSearch;
- char *string;
-
- slaveInterp = GetInterp2(interp, objc, objv);
- if (slaveInterp == NULL) {
- return TCL_ERROR;
- }
- iiPtr = (InterpInfo *) ((Interp *) slaveInterp)->interpInfo;
- resultPtr = Tcl_GetObjResult(interp);
- hPtr = Tcl_FirstHashEntry(&iiPtr->master.slaveTable, &hashSearch);
- for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&hashSearch)) {
- string = Tcl_GetHashKey(&iiPtr->master.slaveTable, hPtr);
- Tcl_ListObjAppendElement(NULL, resultPtr,
- Tcl_NewStringObj(string, -1));
- }
- return TCL_OK;
+ if (objc != 3 && objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "path ?newlimit?");
+ return TCL_ERROR;
+ }
+ slaveInterp = GetInterp(interp, objv[2]);
+ if (slaveInterp == NULL) {
+ return TCL_ERROR;
}
- case OPT_SHARE: {
- Tcl_Interp *slaveInterp; /* A slave. */
- Tcl_Interp *masterInterp; /* Its master. */
- Tcl_Channel chan;
+ return SlaveRecursionLimit(interp, slaveInterp, objc - 3, objv + 3);
+ }
+ case OPT_SLAVES: {
+ Tcl_Interp *slaveInterp;
+ InterpInfo *iiPtr;
+ Tcl_Obj *resultPtr;
+ Tcl_HashEntry *hPtr;
+ Tcl_HashSearch hashSearch;
+ char *string;
- if (objc != 5) {
- Tcl_WrongNumArgs(interp, 2, objv, "srcPath channelId destPath");
- return TCL_ERROR;
- }
- masterInterp = GetInterp(interp, objv[2]);
- if (masterInterp == NULL) {
- return TCL_ERROR;
- }
- chan = Tcl_GetChannel(masterInterp, Tcl_GetString(objv[3]),
- NULL);
- if (chan == NULL) {
- TclTransferResult(masterInterp, TCL_OK, interp);
- return TCL_ERROR;
- }
- slaveInterp = GetInterp(interp, objv[4]);
- if (slaveInterp == NULL) {
- return TCL_ERROR;
- }
- Tcl_RegisterChannel(slaveInterp, chan);
- return TCL_OK;
+ slaveInterp = GetInterp2(interp, objc, objv);
+ if (slaveInterp == NULL) {
+ return TCL_ERROR;
+ }
+ iiPtr = (InterpInfo *) ((Interp *) slaveInterp)->interpInfo;
+ resultPtr = Tcl_NewObj();
+ hPtr = Tcl_FirstHashEntry(&iiPtr->master.slaveTable, &hashSearch);
+ for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&hashSearch)) {
+ string = Tcl_GetHashKey(&iiPtr->master.slaveTable, hPtr);
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewStringObj(string, -1));
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ return TCL_OK;
+ }
+ case OPT_TRANSFER:
+ case OPT_SHARE: {
+ Tcl_Interp *slaveInterp; /* A slave. */
+ Tcl_Interp *masterInterp; /* Its master. */
+ Tcl_Channel chan;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "srcPath channelId destPath");
+ return TCL_ERROR;
+ }
+ masterInterp = GetInterp(interp, objv[2]);
+ if (masterInterp == NULL) {
+ return TCL_ERROR;
+ }
+ chan = Tcl_GetChannel(masterInterp, TclGetString(objv[3]), NULL);
+ if (chan == NULL) {
+ TclTransferResult(masterInterp, TCL_OK, interp);
+ return TCL_ERROR;
}
- case OPT_TARGET: {
- Tcl_Interp *slaveInterp;
- InterpInfo *iiPtr;
- Tcl_HashEntry *hPtr;
- Alias *aliasPtr;
- char *aliasName;
+ slaveInterp = GetInterp(interp, objv[4]);
+ if (slaveInterp == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_RegisterChannel(slaveInterp, chan);
+ if (index == OPT_TRANSFER) {
+ /*
+ * When transferring, as opposed to sharing, we must unhitch the
+ * channel from the interpreter where it started.
+ */
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "path alias");
+ if (Tcl_UnregisterChannel(masterInterp, chan) != TCL_OK) {
+ TclTransferResult(masterInterp, TCL_OK, interp);
return TCL_ERROR;
}
+ }
+ return TCL_OK;
+ }
+ case OPT_TARGET: {
+ Tcl_Interp *slaveInterp;
+ InterpInfo *iiPtr;
+ Tcl_HashEntry *hPtr;
+ Alias *aliasPtr;
+ char *aliasName;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "path alias");
+ return TCL_ERROR;
+ }
- slaveInterp = GetInterp(interp, objv[2]);
- if (slaveInterp == NULL) {
- return TCL_ERROR;
- }
+ slaveInterp = GetInterp(interp, objv[2]);
+ if (slaveInterp == NULL) {
+ return TCL_ERROR;
+ }
- aliasName = Tcl_GetString(objv[3]);
+ aliasName = TclGetString(objv[3]);
- iiPtr = (InterpInfo *) ((Interp *) slaveInterp)->interpInfo;
- hPtr = Tcl_FindHashEntry(&iiPtr->slave.aliasTable, aliasName);
- if (hPtr == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "alias \"", aliasName, "\" in path \"",
- Tcl_GetString(objv[2]), "\" not found",
- (char *) NULL);
- return TCL_ERROR;
- }
- aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
- if (Tcl_GetInterpPath(interp, aliasPtr->targetInterp) != TCL_OK) {
- Tcl_ResetResult(interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "target interpreter for alias \"", aliasName,
- "\" in path \"", Tcl_GetString(objv[2]),
- "\" is not my descendant", (char *) NULL);
- return TCL_ERROR;
- }
- return TCL_OK;
+ iiPtr = (InterpInfo *) ((Interp *) slaveInterp)->interpInfo;
+ hPtr = Tcl_FindHashEntry(&iiPtr->slave.aliasTable, aliasName);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "alias \"", aliasName, "\" in path \"",
+ Tcl_GetString(objv[2]), "\" not found", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS", aliasName,
+ NULL);
+ return TCL_ERROR;
}
- case OPT_TRANSFER: {
- Tcl_Interp *slaveInterp; /* A slave. */
- Tcl_Interp *masterInterp; /* Its master. */
- Tcl_Channel chan;
-
- if (objc != 5) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "srcPath channelId destPath");
- return TCL_ERROR;
- }
- masterInterp = GetInterp(interp, objv[2]);
- if (masterInterp == NULL) {
- return TCL_ERROR;
- }
- chan = Tcl_GetChannel(masterInterp, Tcl_GetString(objv[3]), NULL);
- if (chan == NULL) {
- TclTransferResult(masterInterp, TCL_OK, interp);
- return TCL_ERROR;
- }
- slaveInterp = GetInterp(interp, objv[4]);
- if (slaveInterp == NULL) {
- return TCL_ERROR;
- }
- Tcl_RegisterChannel(slaveInterp, chan);
- if (Tcl_UnregisterChannel(masterInterp, chan) != TCL_OK) {
- TclTransferResult(masterInterp, TCL_OK, interp);
- return TCL_ERROR;
- }
- return TCL_OK;
+ aliasPtr = Tcl_GetHashValue(hPtr);
+ if (Tcl_GetInterpPath(interp, aliasPtr->targetInterp) != TCL_OK) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "target interpreter for alias \"",
+ aliasName, "\" in path \"", Tcl_GetString(objv[2]),
+ "\" is not my descendant", NULL);
+ return TCL_ERROR;
}
+ return TCL_OK;
+ }
}
return TCL_OK;
}
@@ -783,24 +1029,24 @@ Tcl_InterpObjCmd(clientData, interp, objc, objv)
* potentially specified on the command line to an Tcl_Interp.
*
* Results:
- * The return value is the interp specified on the command line,
- * or the interp argument itself if no interp was specified on the
- * command line. If the interp could not be found or the wrong
- * number of arguments was specified on the command line, the return
- * value is NULL and an error message is left in the interp's result.
+ * The return value is the interp specified on the command line, or the
+ * interp argument itself if no interp was specified on the command line.
+ * If the interp could not be found or the wrong number of arguments was
+ * specified on the command line, the return value is NULL and an error
+ * message is left in the interp's result.
*
* Side effects:
* None.
*
*---------------------------------------------------------------------------
*/
-
+
static Tcl_Interp *
-GetInterp2(interp, objc, objv)
- Tcl_Interp *interp; /* Default interp if no interp was specified
+GetInterp2(
+ Tcl_Interp *interp, /* Default interp if no interp was specified
* on the command line. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
if (objc == 2) {
return interp;
@@ -829,25 +1075,26 @@ GetInterp2(interp, objc, objv)
*/
int
-Tcl_CreateAlias(slaveInterp, slaveCmd, targetInterp, targetCmd, argc, argv)
- Tcl_Interp *slaveInterp; /* Interpreter for source command. */
- CONST char *slaveCmd; /* Command to install in slave. */
- Tcl_Interp *targetInterp; /* Interpreter for target command. */
- CONST char *targetCmd; /* Name of target command. */
- int argc; /* How many additional arguments? */
- CONST char * CONST *argv; /* These are the additional args. */
+Tcl_CreateAlias(
+ Tcl_Interp *slaveInterp, /* Interpreter for source command. */
+ const char *slaveCmd, /* Command to install in slave. */
+ Tcl_Interp *targetInterp, /* Interpreter for target command. */
+ const char *targetCmd, /* Name of target command. */
+ int argc, /* How many additional arguments? */
+ const char *const *argv) /* These are the additional args. */
{
Tcl_Obj *slaveObjPtr, *targetObjPtr;
Tcl_Obj **objv;
int i;
int result;
-
- objv = (Tcl_Obj **) ckalloc((unsigned) sizeof(Tcl_Obj *) * argc);
+
+ objv = (Tcl_Obj **)
+ TclStackAlloc(slaveInterp, (unsigned) sizeof(Tcl_Obj *) * argc);
for (i = 0; i < argc; i++) {
- objv[i] = Tcl_NewStringObj(argv[i], -1);
- Tcl_IncrRefCount(objv[i]);
+ objv[i] = Tcl_NewStringObj(argv[i], -1);
+ Tcl_IncrRefCount(objv[i]);
}
-
+
slaveObjPtr = Tcl_NewStringObj(slaveCmd, -1);
Tcl_IncrRefCount(slaveObjPtr);
@@ -860,7 +1107,7 @@ Tcl_CreateAlias(slaveInterp, slaveCmd, targetInterp, targetCmd, argc, argv)
for (i = 0; i < argc; i++) {
Tcl_DecrRefCount(objv[i]);
}
- ckfree((char *) objv);
+ TclStackFree(slaveInterp, objv);
Tcl_DecrRefCount(targetObjPtr);
Tcl_DecrRefCount(slaveObjPtr);
@@ -884,13 +1131,13 @@ Tcl_CreateAlias(slaveInterp, slaveCmd, targetInterp, targetCmd, argc, argv)
*/
int
-Tcl_CreateAliasObj(slaveInterp, slaveCmd, targetInterp, targetCmd, objc, objv)
- Tcl_Interp *slaveInterp; /* Interpreter for source command. */
- CONST char *slaveCmd; /* Command to install in slave. */
- Tcl_Interp *targetInterp; /* Interpreter for target command. */
- CONST char *targetCmd; /* Name of target command. */
- int objc; /* How many additional arguments? */
- Tcl_Obj *CONST objv[]; /* Argument vector. */
+Tcl_CreateAliasObj(
+ Tcl_Interp *slaveInterp, /* Interpreter for source command. */
+ const char *slaveCmd, /* Command to install in slave. */
+ Tcl_Interp *targetInterp, /* Interpreter for target command. */
+ const char *targetCmd, /* Name of target command. */
+ int objc, /* How many additional arguments? */
+ Tcl_Obj *const objv[]) /* Argument vector. */
{
Tcl_Obj *slaveObjPtr, *targetObjPtr;
int result;
@@ -917,7 +1164,7 @@ Tcl_CreateAliasObj(slaveInterp, slaveCmd, targetInterp, targetCmd, objc, objv)
* Gets information about an alias.
*
* Results:
- * A standard Tcl result.
+ * A standard Tcl result.
*
* Side effects:
* None.
@@ -926,29 +1173,28 @@ Tcl_CreateAliasObj(slaveInterp, slaveCmd, targetInterp, targetCmd, objc, objv)
*/
int
-Tcl_GetAlias(interp, aliasName, targetInterpPtr, targetNamePtr, argcPtr,
- argvPtr)
- Tcl_Interp *interp; /* Interp to start search from. */
- CONST char *aliasName; /* Name of alias to find. */
- Tcl_Interp **targetInterpPtr; /* (Return) target interpreter. */
- CONST char **targetNamePtr; /* (Return) name of target command. */
- int *argcPtr; /* (Return) count of addnl args. */
- CONST char ***argvPtr; /* (Return) additional arguments. */
+Tcl_GetAlias(
+ Tcl_Interp *interp, /* Interp to start search from. */
+ const char *aliasName, /* Name of alias to find. */
+ Tcl_Interp **targetInterpPtr,
+ /* (Return) target interpreter. */
+ const char **targetNamePtr, /* (Return) name of target command. */
+ int *argcPtr, /* (Return) count of addnl args. */
+ const char ***argvPtr) /* (Return) additional arguments. */
{
- InterpInfo *iiPtr;
+ InterpInfo *iiPtr = (InterpInfo *) ((Interp *) interp)->interpInfo;
Tcl_HashEntry *hPtr;
Alias *aliasPtr;
int i, objc;
Tcl_Obj **objv;
-
- iiPtr = (InterpInfo *) ((Interp *) interp)->interpInfo;
+
hPtr = Tcl_FindHashEntry(&iiPtr->slave.aliasTable, aliasName);
if (hPtr == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "alias \"", aliasName, "\" not found", (char *) NULL);
+ Tcl_AppendResult(interp, "alias \"", aliasName, "\" not found", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS", aliasName, NULL);
return TCL_ERROR;
}
- aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
+ aliasPtr = Tcl_GetHashValue(hPtr);
objc = aliasPtr->objc;
objv = &aliasPtr->objPtr;
@@ -956,17 +1202,17 @@ Tcl_GetAlias(interp, aliasName, targetInterpPtr, targetNamePtr, argcPtr,
*targetInterpPtr = aliasPtr->targetInterp;
}
if (targetNamePtr != NULL) {
- *targetNamePtr = Tcl_GetString(objv[0]);
+ *targetNamePtr = TclGetString(objv[0]);
}
if (argcPtr != NULL) {
*argcPtr = objc - 1;
}
if (argvPtr != NULL) {
- *argvPtr = (CONST char **)
- ckalloc((unsigned) sizeof(CONST char *) * (objc - 1));
- for (i = 1; i < objc; i++) {
- (*argvPtr)[i - 1] = Tcl_GetString(objv[i]);
- }
+ *argvPtr = (const char **)
+ ckalloc((unsigned) sizeof(const char *) * (objc - 1));
+ for (i = 1; i < objc; i++) {
+ (*argvPtr)[i - 1] = TclGetString(objv[i]);
+ }
}
return TCL_OK;
}
@@ -988,43 +1234,42 @@ Tcl_GetAlias(interp, aliasName, targetInterpPtr, targetNamePtr, argcPtr,
*/
int
-Tcl_GetAliasObj(interp, aliasName, targetInterpPtr, targetNamePtr, objcPtr,
- objvPtr)
- Tcl_Interp *interp; /* Interp to start search from. */
- CONST char *aliasName; /* Name of alias to find. */
- Tcl_Interp **targetInterpPtr; /* (Return) target interpreter. */
- CONST char **targetNamePtr; /* (Return) name of target command. */
- int *objcPtr; /* (Return) count of addnl args. */
- Tcl_Obj ***objvPtr; /* (Return) additional args. */
+Tcl_GetAliasObj(
+ Tcl_Interp *interp, /* Interp to start search from. */
+ const char *aliasName, /* Name of alias to find. */
+ Tcl_Interp **targetInterpPtr,
+ /* (Return) target interpreter. */
+ const char **targetNamePtr, /* (Return) name of target command. */
+ int *objcPtr, /* (Return) count of addnl args. */
+ Tcl_Obj ***objvPtr) /* (Return) additional args. */
{
- InterpInfo *iiPtr;
+ InterpInfo *iiPtr = (InterpInfo *) ((Interp *) interp)->interpInfo;
Tcl_HashEntry *hPtr;
- Alias *aliasPtr;
+ Alias *aliasPtr;
int objc;
Tcl_Obj **objv;
- iiPtr = (InterpInfo *) ((Interp *) interp)->interpInfo;
hPtr = Tcl_FindHashEntry(&iiPtr->slave.aliasTable, aliasName);
- if (hPtr == (Tcl_HashEntry *) NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "alias \"", aliasName, "\" not found", (char *) NULL);
- return TCL_ERROR;
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "alias \"", aliasName, "\" not found", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS", aliasName, NULL);
+ return TCL_ERROR;
}
- aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
+ aliasPtr = Tcl_GetHashValue(hPtr);
objc = aliasPtr->objc;
objv = &aliasPtr->objPtr;
- if (targetInterpPtr != (Tcl_Interp **) NULL) {
- *targetInterpPtr = aliasPtr->targetInterp;
+ if (targetInterpPtr != NULL) {
+ *targetInterpPtr = aliasPtr->targetInterp;
}
- if (targetNamePtr != (CONST char **) NULL) {
- *targetNamePtr = Tcl_GetString(objv[0]);
+ if (targetNamePtr != NULL) {
+ *targetNamePtr = TclGetString(objv[0]);
}
- if (objcPtr != (int *) NULL) {
- *objcPtr = objc - 1;
+ if (objcPtr != NULL) {
+ *objcPtr = objc - 1;
}
- if (objvPtr != (Tcl_Obj ***) NULL) {
- *objvPtr = objv + 1;
+ if (objvPtr != NULL) {
+ *objvPtr = objv + 1;
}
return TCL_OK;
}
@@ -1034,30 +1279,29 @@ Tcl_GetAliasObj(interp, aliasName, targetInterpPtr, targetNamePtr, objcPtr,
*
* TclPreventAliasLoop --
*
- * When defining an alias or renaming a command, prevent an alias
- * loop from being formed.
+ * When defining an alias or renaming a command, prevent an alias loop
+ * from being formed.
*
* Results:
* A standard Tcl object result.
*
* Side effects:
- * If TCL_ERROR is returned, the function also stores an error message
- * in the interpreter's result object.
+ * If TCL_ERROR is returned, the function also stores an error message in
+ * the interpreter's result object.
*
* NOTE:
- * This function is public internal (instead of being static to
- * this file) because it is also used from TclRenameCommand.
+ * This function is public internal (instead of being static to this
+ * file) because it is also used from TclRenameCommand.
*
*----------------------------------------------------------------------
*/
int
-TclPreventAliasLoop(interp, cmdInterp, cmd)
- Tcl_Interp *interp; /* Interp in which to report errors. */
- Tcl_Interp *cmdInterp; /* Interp in which the command is
- * being defined. */
- Tcl_Command cmd; /* Tcl command we are attempting
- * to define. */
+TclPreventAliasLoop(
+ Tcl_Interp *interp, /* Interp in which to report errors. */
+ Tcl_Interp *cmdInterp, /* Interp in which the command is being
+ * defined. */
+ Tcl_Command cmd) /* Tcl command we are attempting to define. */
{
Command *cmdPtr = (Command *) cmd;
Alias *aliasPtr, *nextAliasPtr;
@@ -1065,18 +1309,18 @@ TclPreventAliasLoop(interp, cmdInterp, cmd)
Command *aliasCmdPtr;
/*
- * If we are not creating or renaming an alias, then it is
- * always OK to create or rename the command.
+ * If we are not creating or renaming an alias, then it is always OK to
+ * create or rename the command.
*/
-
+
if (cmdPtr->objProc != AliasObjCmd) {
- return TCL_OK;
+ return TCL_OK;
}
/*
- * OK, we are dealing with an alias, so traverse the chain of aliases.
- * If we encounter the alias we are defining (or renaming to) any in
- * the chain then we have a loop.
+ * OK, we are dealing with an alias, so traverse the chain of aliases. If
+ * we encounter the alias we are defining (or renaming to) any in the
+ * chain then we have a loop.
*/
aliasPtr = (Alias *) cmdPtr->objClientData;
@@ -1084,9 +1328,9 @@ TclPreventAliasLoop(interp, cmdInterp, cmd)
while (1) {
Tcl_Obj *cmdNamePtr;
- /*
- * If the target of the next alias in the chain is the same as
- * the source alias, we have a loop.
+ /*
+ * If the target of the next alias in the chain is the same as the
+ * source alias, we have a loop.
*/
if (Tcl_InterpDeleted(nextAliasPtr->targetInterp)) {
@@ -1095,39 +1339,37 @@ TclPreventAliasLoop(interp, cmdInterp, cmd)
* [Bug #641195]
*/
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "cannot define or rename alias \"",
- Tcl_GetString(aliasPtr->namePtr),
- "\": interpreter deleted", (char *) NULL);
+ Tcl_AppendResult(interp, "cannot define or rename alias \"",
+ Tcl_GetCommandName(cmdInterp, cmd),
+ "\": interpreter deleted", NULL);
return TCL_ERROR;
}
cmdNamePtr = nextAliasPtr->objPtr;
aliasCmd = Tcl_FindCommand(nextAliasPtr->targetInterp,
- Tcl_GetString(cmdNamePtr),
+ TclGetString(cmdNamePtr),
Tcl_GetGlobalNamespace(nextAliasPtr->targetInterp),
/*flags*/ 0);
- if (aliasCmd == (Tcl_Command) NULL) {
- return TCL_OK;
- }
+ if (aliasCmd == NULL) {
+ return TCL_OK;
+ }
aliasCmdPtr = (Command *) aliasCmd;
- if (aliasCmdPtr == cmdPtr) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "cannot define or rename alias \"",
- Tcl_GetString(aliasPtr->namePtr),
- "\": would create a loop", (char *) NULL);
- return TCL_ERROR;
- }
-
- /*
+ if (aliasCmdPtr == cmdPtr) {
+ Tcl_AppendResult(interp, "cannot define or rename alias \"",
+ Tcl_GetCommandName(cmdInterp, cmd),
+ "\": would create a loop", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
* Otherwise, follow the chain one step further. See if the target
- * command is an alias - if so, follow the loop to its target
- * command. Otherwise we do not have a loop.
+ * command is an alias - if so, follow the loop to its target command.
+ * Otherwise we do not have a loop.
*/
- if (aliasCmdPtr->objProc != AliasObjCmd) {
- return TCL_OK;
- }
- nextAliasPtr = (Alias *) aliasCmdPtr->objClientData;
+ if (aliasCmdPtr->objProc != AliasObjCmd) {
+ return TCL_OK;
+ }
+ nextAliasPtr = (Alias *) aliasCmdPtr->objClientData;
}
/* NOTREACHED */
@@ -1144,24 +1386,23 @@ TclPreventAliasLoop(interp, cmdInterp, cmd)
* A standard Tcl result.
*
* Side effects:
- * An alias command is created and entered into the alias table
- * for the slave interpreter.
+ * An alias command is created and entered into the alias table for the
+ * slave interpreter.
*
*----------------------------------------------------------------------
*/
static int
-AliasCreate(interp, slaveInterp, masterInterp, namePtr, targetNamePtr,
- objc, objv)
- Tcl_Interp *interp; /* Interp for error reporting. */
- Tcl_Interp *slaveInterp; /* Interp where alias cmd will live or from
+AliasCreate(
+ Tcl_Interp *interp, /* Interp for error reporting. */
+ Tcl_Interp *slaveInterp, /* Interp where alias cmd will live or from
* which alias will be deleted. */
- Tcl_Interp *masterInterp; /* Interp in which target command will be
+ Tcl_Interp *masterInterp, /* Interp in which target command will be
* invoked. */
- Tcl_Obj *namePtr; /* Name of alias cmd. */
- Tcl_Obj *targetNamePtr; /* Name of target cmd. */
- int objc; /* Additional arguments to store */
- Tcl_Obj *CONST objv[]; /* with alias. */
+ Tcl_Obj *namePtr, /* Name of alias cmd. */
+ Tcl_Obj *targetNamePtr, /* Name of target cmd. */
+ int objc, /* Additional arguments to store */
+ Tcl_Obj *const objv[]) /* with alias. */
{
Alias *aliasPtr;
Tcl_HashEntry *hPtr;
@@ -1169,13 +1410,13 @@ AliasCreate(interp, slaveInterp, masterInterp, namePtr, targetNamePtr,
Slave *slavePtr;
Master *masterPtr;
Tcl_Obj **prefv;
- int new, i;
+ int isNew, i;
- aliasPtr = (Alias *) ckalloc((unsigned) (sizeof(Alias)
- + objc * sizeof(Tcl_Obj *)));
- aliasPtr->namePtr = namePtr;
- Tcl_IncrRefCount(aliasPtr->namePtr);
- aliasPtr->targetInterp = masterInterp;
+ aliasPtr = (Alias *) ckalloc((unsigned) (sizeof(Alias)
+ + objc * sizeof(Tcl_Obj *)));
+ aliasPtr->token = namePtr;
+ Tcl_IncrRefCount(aliasPtr->token);
+ aliasPtr->targetInterp = masterInterp;
aliasPtr->objc = objc + 1;
prefv = &aliasPtr->objPtr;
@@ -1191,26 +1432,26 @@ AliasCreate(interp, slaveInterp, masterInterp, namePtr, targetNamePtr,
Tcl_Preserve(masterInterp);
aliasPtr->slaveCmd = Tcl_CreateObjCommand(slaveInterp,
- Tcl_GetString(namePtr), AliasObjCmd, (ClientData) aliasPtr,
+ TclGetString(namePtr), AliasObjCmd, aliasPtr,
AliasObjCmdDeleteProc);
if (TclPreventAliasLoop(interp, slaveInterp,
aliasPtr->slaveCmd) != TCL_OK) {
/*
- * Found an alias loop! The last call to Tcl_CreateObjCommand made
- * the alias point to itself. Delete the command and its alias
- * record. Be careful to wipe out its client data first, so the
- * command doesn't try to delete itself.
+ * Found an alias loop! The last call to Tcl_CreateObjCommand made the
+ * alias point to itself. Delete the command and its alias record. Be
+ * careful to wipe out its client data first, so the command doesn't
+ * try to delete itself.
*/
Command *cmdPtr;
-
- Tcl_DecrRefCount(aliasPtr->namePtr);
+
+ Tcl_DecrRefCount(aliasPtr->token);
Tcl_DecrRefCount(targetNamePtr);
for (i = 0; i < objc; i++) {
Tcl_DecrRefCount(objv[i]);
}
-
+
cmdPtr = (Command *) aliasPtr->slaveCmd;
cmdPtr->clientData = NULL;
cmdPtr->deleteProc = NULL;
@@ -1229,28 +1470,42 @@ AliasCreate(interp, slaveInterp, masterInterp, namePtr, targetNamePtr,
}
/*
- * Make an entry in the alias table. If it already exists delete
- * the alias command. Then retry.
+ * Make an entry in the alias table. If it already exists, retry.
*/
slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave;
while (1) {
- Alias *oldAliasPtr;
+ Tcl_Obj *newToken;
char *string;
-
- string = Tcl_GetString(namePtr);
- hPtr = Tcl_CreateHashEntry(&slavePtr->aliasTable, string, &new);
- if (new != 0) {
+
+ string = TclGetString(aliasPtr->token);
+ hPtr = Tcl_CreateHashEntry(&slavePtr->aliasTable, string, &isNew);
+ if (isNew != 0) {
break;
}
- oldAliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
- Tcl_DeleteCommandFromToken(slaveInterp, oldAliasPtr->slaveCmd);
+ /*
+ * The alias name cannot be used as unique token, it is already taken.
+ * We can produce a unique token by prepending "::" repeatedly. This
+ * algorithm is a stop-gap to try to maintain the command name as
+ * token for most use cases, fearful of possible backwards compat
+ * problems. A better algorithm would produce unique tokens that need
+ * not be related to the command name.
+ *
+ * ATTENTION: the tests in interp.test and possibly safe.test depend
+ * on the precise definition of these tokens.
+ */
+
+ TclNewLiteralStringObj(newToken, "::");
+ Tcl_AppendObjToObj(newToken, aliasPtr->token);
+ Tcl_DecrRefCount(aliasPtr->token);
+ aliasPtr->token = newToken;
+ Tcl_IncrRefCount(aliasPtr->token);
}
aliasPtr->aliasEntryPtr = hPtr;
- Tcl_SetHashValue(hPtr, (ClientData) aliasPtr);
-
+ Tcl_SetHashValue(hPtr, aliasPtr);
+
/*
* Create the new command. We must do it after deleting any old command,
* because the alias may be pointing at a renamed alias, as in:
@@ -1264,19 +1519,16 @@ AliasCreate(interp, slaveInterp, masterInterp, namePtr, targetNamePtr,
targetPtr->slaveCmd = aliasPtr->slaveCmd;
targetPtr->slaveInterp = slaveInterp;
- Tcl_MutexLock(&cntMutex);
- masterPtr = &((InterpInfo *) ((Interp *) masterInterp)->interpInfo)->master;
- do {
- hPtr = Tcl_CreateHashEntry(&masterPtr->targetTable,
- (char *) aliasCounter, &new);
- aliasCounter++;
- } while (new == 0);
- Tcl_MutexUnlock(&cntMutex);
-
- Tcl_SetHashValue(hPtr, (ClientData) targetPtr);
- aliasPtr->targetEntryPtr = hPtr;
+ masterPtr = &((InterpInfo *) ((Interp*) masterInterp)->interpInfo)->master;
+ targetPtr->nextPtr = masterPtr->targetsPtr;
+ targetPtr->prevPtr = NULL;
+ if (masterPtr->targetsPtr != NULL) {
+ masterPtr->targetsPtr->prevPtr = targetPtr;
+ }
+ masterPtr->targetsPtr = targetPtr;
+ aliasPtr->targetPtr = targetPtr;
- Tcl_SetObjResult(interp, namePtr);
+ Tcl_SetObjResult(interp, aliasPtr->token);
Tcl_Release(slaveInterp);
Tcl_Release(masterInterp);
@@ -1300,10 +1552,10 @@ AliasCreate(interp, slaveInterp, masterInterp, namePtr, targetNamePtr,
*/
static int
-AliasDelete(interp, slaveInterp, namePtr)
- Tcl_Interp *interp; /* Interpreter for result & errors. */
- Tcl_Interp *slaveInterp; /* Interpreter containing alias. */
- Tcl_Obj *namePtr; /* Name of alias to delete. */
+AliasDelete(
+ Tcl_Interp *interp, /* Interpreter for result & errors. */
+ Tcl_Interp *slaveInterp, /* Interpreter containing alias. */
+ Tcl_Obj *namePtr) /* Name of alias to delete. */
{
Slave *slavePtr;
Alias *aliasPtr;
@@ -1316,13 +1568,15 @@ AliasDelete(interp, slaveInterp, namePtr)
*/
slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave;
- hPtr = Tcl_FindHashEntry(&slavePtr->aliasTable, Tcl_GetString(namePtr));
+ hPtr = Tcl_FindHashEntry(&slavePtr->aliasTable, TclGetString(namePtr));
if (hPtr == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "alias \"",
- Tcl_GetString(namePtr), "\" not found", NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "alias \"", TclGetString(namePtr),
+ "\" not found", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS",
+ TclGetString(namePtr), NULL);
+ return TCL_ERROR;
}
- aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
+ aliasPtr = Tcl_GetHashValue(hPtr);
Tcl_DeleteCommandFromToken(slaveInterp, aliasPtr->slaveCmd);
return TCL_OK;
}
@@ -1332,10 +1586,9 @@ AliasDelete(interp, slaveInterp, namePtr)
*
* AliasDescribe --
*
- * Sets the interpreter's result object to a Tcl list describing
- * the given alias in the given interpreter: its target command
- * and the additional arguments to prepend to any invocation
- * of the alias.
+ * Sets the interpreter's result object to a Tcl list describing the
+ * given alias in the given interpreter: its target command and the
+ * additional arguments to prepend to any invocation of the alias.
*
* Results:
* A standard Tcl result.
@@ -1347,14 +1600,14 @@ AliasDelete(interp, slaveInterp, namePtr)
*/
static int
-AliasDescribe(interp, slaveInterp, namePtr)
- Tcl_Interp *interp; /* Interpreter for result & errors. */
- Tcl_Interp *slaveInterp; /* Interpreter containing alias. */
- Tcl_Obj *namePtr; /* Name of alias to describe. */
+AliasDescribe(
+ Tcl_Interp *interp, /* Interpreter for result & errors. */
+ Tcl_Interp *slaveInterp, /* Interpreter containing alias. */
+ Tcl_Obj *namePtr) /* Name of alias to describe. */
{
Slave *slavePtr;
Tcl_HashEntry *hPtr;
- Alias *aliasPtr;
+ Alias *aliasPtr;
Tcl_Obj *prefixPtr;
/*
@@ -1366,9 +1619,9 @@ AliasDescribe(interp, slaveInterp, namePtr)
slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave;
hPtr = Tcl_FindHashEntry(&slavePtr->aliasTable, Tcl_GetString(namePtr));
if (hPtr == NULL) {
- return TCL_OK;
+ return TCL_OK;
}
- aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);
+ aliasPtr = Tcl_GetHashValue(hPtr);
prefixPtr = Tcl_NewListObj(aliasPtr->objc, &aliasPtr->objPtr);
Tcl_SetObjResult(interp, prefixPtr);
return TCL_OK;
@@ -1391,24 +1644,24 @@ AliasDescribe(interp, slaveInterp, namePtr)
*/
static int
-AliasList(interp, slaveInterp)
- Tcl_Interp *interp; /* Interp for data return. */
- Tcl_Interp *slaveInterp; /* Interp whose aliases to compute. */
+AliasList(
+ Tcl_Interp *interp, /* Interp for data return. */
+ Tcl_Interp *slaveInterp) /* Interp whose aliases to compute. */
{
Tcl_HashEntry *entryPtr;
Tcl_HashSearch hashSearch;
- Tcl_Obj *resultPtr;
+ Tcl_Obj *resultPtr = Tcl_NewObj();
Alias *aliasPtr;
Slave *slavePtr;
slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave;
- resultPtr = Tcl_GetObjResult(interp);
entryPtr = Tcl_FirstHashEntry(&slavePtr->aliasTable, &hashSearch);
for ( ; entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&hashSearch)) {
- aliasPtr = (Alias *) Tcl_GetHashValue(entryPtr);
- Tcl_ListObjAppendElement(NULL, resultPtr, aliasPtr->namePtr);
+ aliasPtr = Tcl_GetHashValue(entryPtr);
+ Tcl_ListObjAppendElement(NULL, resultPtr, aliasPtr->token);
}
+ Tcl_SetObjResult(interp, resultPtr);
return TCL_OK;
}
@@ -1417,80 +1670,120 @@ AliasList(interp, slaveInterp)
*
* AliasObjCmd --
*
- * This is the procedure that services invocations of aliases in a
- * slave interpreter. One such command exists for each alias. When
- * invoked, this procedure redirects the invocation to the target
- * command in the master interpreter as designated by the Alias
- * record associated with this command.
+ * This is the function that services invocations of aliases in a slave
+ * interpreter. One such command exists for each alias. When invoked,
+ * this function redirects the invocation to the target command in the
+ * master interpreter as designated by the Alias record associated with
+ * this command.
*
* Results:
* A standard Tcl result.
*
* Side effects:
- * Causes forwarding of the invocation; all possible side effects
- * may occur as a result of invoking the command to which the
- * invocation is forwarded.
+ * Causes forwarding of the invocation; all possible side effects may
+ * occur as a result of invoking the command to which the invocation is
+ * forwarded.
*
*----------------------------------------------------------------------
*/
static int
-AliasObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Alias record. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument vector. */
+AliasObjCmd(
+ ClientData clientData, /* Alias record. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument vector. */
{
#define ALIAS_CMDV_PREALLOC 10
- Tcl_Interp *targetInterp;
- Alias *aliasPtr;
+ Alias *aliasPtr = clientData;
+ Tcl_Interp *targetInterp = aliasPtr->targetInterp;
int result, prefc, cmdc, i;
Tcl_Obj **prefv, **cmdv;
Tcl_Obj *cmdArr[ALIAS_CMDV_PREALLOC];
- aliasPtr = (Alias *) clientData;
- targetInterp = aliasPtr->targetInterp;
+ Interp *tPtr = (Interp *) targetInterp;
+ int isRootEnsemble = (tPtr->ensembleRewrite.sourceObjs == NULL);
/*
- * Append the arguments to the command prefix and invoke the command
- * in the target interp's global namespace.
+ * Append the arguments to the command prefix and invoke the command in
+ * the target interp's global namespace.
*/
-
+
prefc = aliasPtr->objc;
prefv = &aliasPtr->objPtr;
cmdc = prefc + objc - 1;
if (cmdc <= ALIAS_CMDV_PREALLOC) {
cmdv = cmdArr;
} else {
- cmdv = (Tcl_Obj **) ckalloc((unsigned) (cmdc * sizeof(Tcl_Obj *)));
+ cmdv = (Tcl_Obj **) TclStackAlloc(interp, cmdc*(int)sizeof(Tcl_Obj*));
}
prefv = &aliasPtr->objPtr;
- memcpy((VOID *) cmdv, (VOID *) prefv,
- (size_t) (prefc * sizeof(Tcl_Obj *)));
- memcpy((VOID *) (cmdv+prefc), (VOID *) (objv+1),
- (size_t) ((objc-1) * sizeof(Tcl_Obj *)));
+ memcpy(cmdv, prefv, (size_t) (prefc * sizeof(Tcl_Obj *)));
+ memcpy(cmdv+prefc, objv+1, (size_t) ((objc-1) * sizeof(Tcl_Obj *)));
Tcl_ResetResult(targetInterp);
for (i=0; i<cmdc; i++) {
Tcl_IncrRefCount(cmdv[i]);
}
- if (targetInterp != interp) {
- Tcl_Preserve((ClientData) targetInterp);
- result = Tcl_EvalObjv(targetInterp, cmdc, cmdv, TCL_EVAL_INVOKE);
- TclTransferResult(targetInterp, result, interp);
- Tcl_Release((ClientData) targetInterp);
+
+ /*
+ * Use the ensemble rewriting machinery to ensure correct error messages:
+ * only the source command should show, not the full target prefix.
+ */
+
+ if (isRootEnsemble) {
+ tPtr->ensembleRewrite.sourceObjs = objv;
+ tPtr->ensembleRewrite.numRemovedObjs = 1;
+ tPtr->ensembleRewrite.numInsertedObjs = prefc;
} else {
- result = Tcl_EvalObjv(targetInterp, cmdc, cmdv, TCL_EVAL_INVOKE);
+ tPtr->ensembleRewrite.numInsertedObjs += prefc - 1;
+ }
+
+ /*
+ * Protect the target interpreter if it isn't the same as the source
+ * interpreter so that we can continue to work with it after the target
+ * command completes.
+ */
+
+ if (targetInterp != interp) {
+ Tcl_Preserve(targetInterp);
}
+
+ /*
+ * Execute the target command in the target interpreter.
+ */
+
+ result = Tcl_EvalObjv(targetInterp, cmdc, cmdv, TCL_EVAL_INVOKE);
+
+ /*
+ * Clean up the ensemble rewrite info if we set it in the first place.
+ */
+
+ if (isRootEnsemble) {
+ tPtr->ensembleRewrite.sourceObjs = NULL;
+ tPtr->ensembleRewrite.numRemovedObjs = 0;
+ tPtr->ensembleRewrite.numInsertedObjs = 0;
+ }
+
+ /*
+ * If it was a cross-interpreter alias, we need to transfer the result
+ * back to the source interpreter and release the lock we previously set
+ * on the target interpreter.
+ */
+
+ if (targetInterp != interp) {
+ TclTransferResult(targetInterp, result, interp);
+ Tcl_Release(targetInterp);
+ }
+
for (i=0; i<cmdc; i++) {
Tcl_DecrRefCount(cmdv[i]);
}
-
if (cmdv != cmdArr) {
- ckfree((char *) cmdv);
+ TclStackFree(interp, cmdv);
}
- return result;
+ return result;
#undef ALIAS_CMDV_PREALLOC
}
@@ -1499,41 +1792,53 @@ AliasObjCmd(clientData, interp, objc, objv)
*
* AliasObjCmdDeleteProc --
*
- * Is invoked when an alias command is deleted in a slave. Cleans up
- * all storage associated with this alias.
+ * Is invoked when an alias command is deleted in a slave. Cleans up all
+ * storage associated with this alias.
*
* Results:
* None.
*
* Side effects:
- * Deletes the alias record and its entry in the alias table for
- * the interpreter.
+ * Deletes the alias record and its entry in the alias table for the
+ * interpreter.
*
*----------------------------------------------------------------------
*/
static void
-AliasObjCmdDeleteProc(clientData)
- ClientData clientData; /* The alias record for this alias. */
+AliasObjCmdDeleteProc(
+ ClientData clientData) /* The alias record for this alias. */
{
- Alias *aliasPtr;
- Target *targetPtr;
+ Alias *aliasPtr = clientData;
+ Target *targetPtr;
int i;
Tcl_Obj **objv;
- aliasPtr = (Alias *) clientData;
-
- Tcl_DecrRefCount(aliasPtr->namePtr);
+ Tcl_DecrRefCount(aliasPtr->token);
objv = &aliasPtr->objPtr;
for (i = 0; i < aliasPtr->objc; i++) {
Tcl_DecrRefCount(objv[i]);
}
Tcl_DeleteHashEntry(aliasPtr->aliasEntryPtr);
- targetPtr = (Target *) Tcl_GetHashValue(aliasPtr->targetEntryPtr);
- ckfree((char *) targetPtr);
- Tcl_DeleteHashEntry(aliasPtr->targetEntryPtr);
+ /*
+ * Splice the target record out of the target interpreter's master list.
+ */
+
+ targetPtr = aliasPtr->targetPtr;
+ if (targetPtr->prevPtr != NULL) {
+ targetPtr->prevPtr->nextPtr = targetPtr->nextPtr;
+ } else {
+ Master *masterPtr = &((InterpInfo *) ((Interp *)
+ aliasPtr->targetInterp)->interpInfo)->master;
+ masterPtr->targetsPtr = targetPtr->nextPtr;
+ }
+ if (targetPtr->nextPtr != NULL) {
+ targetPtr->nextPtr->prevPtr = targetPtr->prevPtr;
+ }
+
+ ckfree((char *) targetPtr);
ckfree((char *) aliasPtr);
}
@@ -1542,29 +1847,29 @@ AliasObjCmdDeleteProc(clientData)
*
* Tcl_CreateSlave --
*
- * Creates a slave interpreter. The slavePath argument denotes the
- * name of the new slave relative to the current interpreter; the
- * slave is a direct descendant of the one-before-last component of
- * the path, e.g. it is a descendant of the current interpreter if
- * the slavePath argument contains only one component. Optionally makes
- * the slave interpreter safe.
+ * Creates a slave interpreter. The slavePath argument denotes the name
+ * of the new slave relative to the current interpreter; the slave is a
+ * direct descendant of the one-before-last component of the path,
+ * e.g. it is a descendant of the current interpreter if the slavePath
+ * argument contains only one component. Optionally makes the slave
+ * interpreter safe.
*
* Results:
* Returns the interpreter structure created, or NULL if an error
* occurred.
*
* Side effects:
- * Creates a new interpreter and a new interpreter object command in
- * the interpreter indicated by the slavePath argument.
+ * Creates a new interpreter and a new interpreter object command in the
+ * interpreter indicated by the slavePath argument.
*
*----------------------------------------------------------------------
*/
Tcl_Interp *
-Tcl_CreateSlave(interp, slavePath, isSafe)
- Tcl_Interp *interp; /* Interpreter to start search at. */
- CONST char *slavePath; /* Name of slave to create. */
- int isSafe; /* Should new slave be "safe" ? */
+Tcl_CreateSlave(
+ Tcl_Interp *interp, /* Interpreter to start search at. */
+ const char *slavePath, /* Name of slave to create. */
+ int isSafe) /* Should new slave be "safe" ? */
{
Tcl_Obj *pathPtr;
Tcl_Interp *slaveInterp;
@@ -1584,8 +1889,7 @@ Tcl_CreateSlave(interp, slavePath, isSafe)
* Finds a slave interpreter by its path name.
*
* Results:
- * Returns a Tcl_Interp * for the named interpreter or NULL if not
- * found.
+ * Returns a Tcl_Interp * for the named interpreter or NULL if not found.
*
* Side effects:
* None.
@@ -1594,9 +1898,9 @@ Tcl_CreateSlave(interp, slavePath, isSafe)
*/
Tcl_Interp *
-Tcl_GetSlave(interp, slavePath)
- Tcl_Interp *interp; /* Interpreter to start search from. */
- CONST char *slavePath; /* Path of slave to find. */
+Tcl_GetSlave(
+ Tcl_Interp *interp, /* Interpreter to start search from. */
+ const char *slavePath) /* Path of slave to find. */
{
Tcl_Obj *pathPtr;
Tcl_Interp *slaveInterp;
@@ -1625,13 +1929,13 @@ Tcl_GetSlave(interp, slavePath)
*/
Tcl_Interp *
-Tcl_GetMaster(interp)
- Tcl_Interp *interp; /* Get the master of this interpreter. */
+Tcl_GetMaster(
+ Tcl_Interp *interp) /* Get the master of this interpreter. */
{
Slave *slavePtr; /* Slave record of this interpreter. */
- if (interp == (Tcl_Interp *) NULL) {
- return NULL;
+ if (interp == NULL) {
+ return NULL;
}
slavePtr = &((InterpInfo *) ((Interp *) interp)->interpInfo)->slave;
return slavePtr->masterInterp;
@@ -1643,19 +1947,17 @@ Tcl_GetMaster(interp)
* Tcl_GetInterpPath --
*
* Sets the result of the asking interpreter to a proper Tcl list
- * containing the names of interpreters between the asking and
- * target interpreters. The target interpreter must be either the
- * same as the asking interpreter or one of its slaves (including
- * recursively).
+ * containing the names of interpreters between the asking and target
+ * interpreters. The target interpreter must be either the same as the
+ * asking interpreter or one of its slaves (including recursively).
*
* Results:
- * TCL_OK if the target interpreter is the same as, or a descendant
- * of, the asking interpreter; TCL_ERROR else. This way one can
- * distinguish between the case where the asking and target interps
- * are the same (an empty list is the result, and TCL_OK is returned)
- * and when the target is not a descendant of the asking interpreter
- * (in which case the Tcl result is an error message and the function
- * returns TCL_ERROR).
+ * TCL_OK if the target interpreter is the same as, or a descendant of,
+ * the asking interpreter; TCL_ERROR else. This way one can distinguish
+ * between the case where the asking and target interps are the same (an
+ * empty list is the result, and TCL_OK is returned) and when the target
+ * is not a descendant of the asking interpreter (in which case the Tcl
+ * result is an error message and the function returns TCL_ERROR).
*
* Side effects:
* None.
@@ -1664,25 +1966,24 @@ Tcl_GetMaster(interp)
*/
int
-Tcl_GetInterpPath(askingInterp, targetInterp)
- Tcl_Interp *askingInterp; /* Interpreter to start search from. */
- Tcl_Interp *targetInterp; /* Interpreter to find. */
+Tcl_GetInterpPath(
+ Tcl_Interp *askingInterp, /* Interpreter to start search from. */
+ Tcl_Interp *targetInterp) /* Interpreter to find. */
{
InterpInfo *iiPtr;
-
+
if (targetInterp == askingInterp) {
- return TCL_OK;
+ return TCL_OK;
}
if (targetInterp == NULL) {
return TCL_ERROR;
}
iiPtr = (InterpInfo *) ((Interp *) targetInterp)->interpInfo;
if (Tcl_GetInterpPath(askingInterp, iiPtr->slave.masterInterp) != TCL_OK) {
- return TCL_ERROR;
+ return TCL_ERROR;
}
- Tcl_AppendElement(askingInterp,
- Tcl_GetHashKey(&iiPtr->master.slaveTable,
- iiPtr->slave.slaveEntryPtr));
+ Tcl_AppendElement(askingInterp, Tcl_GetHashKey(&iiPtr->master.slaveTable,
+ iiPtr->slave.slaveEntryPtr));
return TCL_OK;
}
@@ -1695,7 +1996,7 @@ Tcl_GetInterpPath(askingInterp, targetInterp)
*
* Results:
* Returns the slave interpreter known by that name in the calling
- * interpreter, or NULL if no interpreter known by that name exists.
+ * interpreter, or NULL if no interpreter known by that name exists.
*
* Side effects:
* Assigns to the pointer variable passed in, if not NULL.
@@ -1704,41 +2005,42 @@ Tcl_GetInterpPath(askingInterp, targetInterp)
*/
static Tcl_Interp *
-GetInterp(interp, pathPtr)
- Tcl_Interp *interp; /* Interp. to start search from. */
- Tcl_Obj *pathPtr; /* List object containing name of interp. to
+GetInterp(
+ Tcl_Interp *interp, /* Interp. to start search from. */
+ Tcl_Obj *pathPtr) /* List object containing name of interp. to
* be found. */
{
Tcl_HashEntry *hPtr; /* Search element. */
Slave *slavePtr; /* Interim slave record. */
Tcl_Obj **objv;
- int objc, i;
+ int objc, i;
Tcl_Interp *searchInterp; /* Interim storage for interp. to find. */
InterpInfo *masterInfoPtr;
- if (Tcl_ListObjGetElements(interp, pathPtr, &objc, &objv) != TCL_OK) {
+ if (TclListObjGetElements(interp, pathPtr, &objc, &objv) != TCL_OK) {
return NULL;
}
searchInterp = interp;
for (i = 0; i < objc; i++) {
masterInfoPtr = (InterpInfo *) ((Interp *) searchInterp)->interpInfo;
- hPtr = Tcl_FindHashEntry(&masterInfoPtr->master.slaveTable,
- Tcl_GetString(objv[i]));
- if (hPtr == NULL) {
+ hPtr = Tcl_FindHashEntry(&masterInfoPtr->master.slaveTable,
+ TclGetString(objv[i]));
+ if (hPtr == NULL) {
searchInterp = NULL;
break;
}
- slavePtr = (Slave *) Tcl_GetHashValue(hPtr);
- searchInterp = slavePtr->slaveInterp;
- if (searchInterp == NULL) {
+ slavePtr = Tcl_GetHashValue(hPtr);
+ searchInterp = slavePtr->slaveInterp;
+ if (searchInterp == NULL) {
break;
}
}
if (searchInterp == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "could not find interpreter \"",
- Tcl_GetString(pathPtr), "\"", (char *) NULL);
+ Tcl_AppendResult(interp, "could not find interpreter \"",
+ TclGetString(pathPtr), "\"", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INTERP",
+ TclGetString(pathPtr), NULL);
}
return searchInterp;
}
@@ -1746,11 +2048,51 @@ GetInterp(interp, pathPtr)
/*
*----------------------------------------------------------------------
*
+ * SlaveBgerror --
+ *
+ * Helper function to set/query the background error handling command
+ * prefix of an interp
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * When (objc == 1), slaveInterp will be set to a new background handler
+ * of objv[0].
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SlaveBgerror(
+ Tcl_Interp *interp, /* Interp for error return. */
+ Tcl_Interp *slaveInterp, /* Interp in which limit is set/queried. */
+ int objc, /* Set or Query. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ if (objc) {
+ int length;
+
+ if (TCL_ERROR == TclListObjLength(NULL, objv[0], &length)
+ || (length < 1)) {
+ Tcl_AppendResult(interp, "cmdPrefix must be list of length >= 1",
+ NULL);
+ return TCL_ERROR;
+ }
+ TclSetBgErrorHandler(slaveInterp, objv[0]);
+ }
+ Tcl_SetObjResult(interp, TclGetBgErrorHandler(slaveInterp));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* SlaveCreate --
*
- * Helper function to do the actual work of creating a slave interp
- * and new object command. Also optionally makes the new slave
- * interpreter "safe".
+ * Helper function to do the actual work of creating a slave interp and
+ * new object command. Also optionally makes the new slave interpreter
+ * "safe".
*
* Results:
* Returns the new Tcl_Interp * if successful or NULL if not. If failed,
@@ -1763,17 +2105,17 @@ GetInterp(interp, pathPtr)
*/
static Tcl_Interp *
-SlaveCreate(interp, pathPtr, safe)
- Tcl_Interp *interp; /* Interp. to start search from. */
- Tcl_Obj *pathPtr; /* Path (name) of slave to create. */
- int safe; /* Should we make it "safe"? */
+SlaveCreate(
+ Tcl_Interp *interp, /* Interp. to start search from. */
+ Tcl_Obj *pathPtr, /* Path (name) of slave to create. */
+ int safe) /* Should we make it "safe"? */
{
Tcl_Interp *masterInterp, *slaveInterp;
Slave *slavePtr;
InterpInfo *masterInfoPtr;
Tcl_HashEntry *hPtr;
char *path;
- int new, objc;
+ int isNew, objc;
Tcl_Obj **objv;
if (Tcl_ListObjGetElements(interp, pathPtr, &objc, &objv) != TCL_OK) {
@@ -1781,29 +2123,29 @@ SlaveCreate(interp, pathPtr, safe)
}
if (objc < 2) {
masterInterp = interp;
- path = Tcl_GetString(pathPtr);
+ path = TclGetString(pathPtr);
} else {
Tcl_Obj *objPtr;
-
+
objPtr = Tcl_NewListObj(objc - 1, objv);
masterInterp = GetInterp(interp, objPtr);
Tcl_DecrRefCount(objPtr);
if (masterInterp == NULL) {
return NULL;
}
- path = Tcl_GetString(objv[objc - 1]);
+ path = TclGetString(objv[objc - 1]);
}
if (safe == 0) {
safe = Tcl_IsSafe(masterInterp);
}
masterInfoPtr = (InterpInfo *) ((Interp *) masterInterp)->interpInfo;
- hPtr = Tcl_CreateHashEntry(&masterInfoPtr->master.slaveTable, path, &new);
- if (new == 0) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "interpreter named \"", path,
- "\" already exists, cannot create", (char *) NULL);
- return NULL;
+ hPtr = Tcl_CreateHashEntry(&masterInfoPtr->master.slaveTable, path,
+ &isNew);
+ if (isNew == 0) {
+ Tcl_AppendResult(interp, "interpreter named \"", path,
+ "\" already exists, cannot create", NULL);
+ return NULL;
}
slaveInterp = Tcl_CreateInterp();
@@ -1812,35 +2154,66 @@ SlaveCreate(interp, pathPtr, safe)
slavePtr->slaveEntryPtr = hPtr;
slavePtr->slaveInterp = slaveInterp;
slavePtr->interpCmd = Tcl_CreateObjCommand(masterInterp, path,
- SlaveObjCmd, (ClientData) slaveInterp, SlaveObjCmdDeleteProc);
+ SlaveObjCmd, slaveInterp, SlaveObjCmdDeleteProc);
Tcl_InitHashTable(&slavePtr->aliasTable, TCL_STRING_KEYS);
- Tcl_SetHashValue(hPtr, (ClientData) slavePtr);
+ Tcl_SetHashValue(hPtr, slavePtr);
Tcl_SetVar(slaveInterp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
-
+
/*
* Inherit the recursion limit.
*/
+
((Interp *) slaveInterp)->maxNestingDepth =
- ((Interp *) masterInterp)->maxNestingDepth ;
+ ((Interp *) masterInterp)->maxNestingDepth;
if (safe) {
- if (Tcl_MakeSafe(slaveInterp) == TCL_ERROR) {
- goto error;
- }
+ if (Tcl_MakeSafe(slaveInterp) == TCL_ERROR) {
+ goto error;
+ }
} else {
- if (Tcl_Init(slaveInterp) == TCL_ERROR) {
- goto error;
- }
+ if (Tcl_Init(slaveInterp) == TCL_ERROR) {
+ goto error;
+ }
+
/*
- * This will create the "memory" command in slave interpreters
- * if we compiled with TCL_MEM_DEBUG, otherwise it does nothing.
+ * This will create the "memory" command in slave interpreters if we
+ * compiled with TCL_MEM_DEBUG, otherwise it does nothing.
*/
+
Tcl_InitMemory(slaveInterp);
}
+
+ /*
+ * Inherit the TIP#143 limits.
+ */
+
+ InheritLimitsFromMaster(slaveInterp, masterInterp);
+
+ /*
+ * The [clock] command presents a safe API, but uses unsafe features in
+ * its implementation. This means it has to be implemented in safe interps
+ * as an alias to a version in the (trusted) master.
+ */
+
+ if (safe) {
+ Tcl_Obj *clockObj;
+ int status;
+
+ TclNewLiteralStringObj(clockObj, "clock");
+ Tcl_IncrRefCount(clockObj);
+ status = AliasCreate(interp, slaveInterp, masterInterp, clockObj,
+ clockObj, 0, NULL);
+ Tcl_DecrRefCount(clockObj);
+ if (status != TCL_OK) {
+ goto error2;
+ }
+ }
+
return slaveInterp;
- error:
+ error:
TclTransferResult(slaveInterp, TCL_ERROR, interp);
+ error2:
Tcl_DeleteInterp(slaveInterp);
return NULL;
@@ -1851,8 +2224,8 @@ SlaveCreate(interp, pathPtr, safe)
*
* SlaveObjCmd --
*
- * Command to manipulate an interpreter, e.g. to send commands to it
- * to be evaluated. One such command exists for each slave interpreter.
+ * Command to manipulate an interpreter, e.g. to send commands to it to
+ * be evaluated. One such command exists for each slave interpreter.
*
* Results:
* A standard Tcl result.
@@ -1864,33 +2237,32 @@ SlaveCreate(interp, pathPtr, safe)
*/
static int
-SlaveObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Slave interpreter. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+SlaveObjCmd(
+ ClientData clientData, /* Slave interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- Tcl_Interp *slaveInterp;
+ Tcl_Interp *slaveInterp = clientData;
int index;
- static CONST char *options[] = {
- "alias", "aliases", "eval", "expose",
- "hide", "hidden", "issafe", "invokehidden",
- "marktrusted", "recursionlimit", NULL
+ static const char *options[] = {
+ "alias", "aliases", "bgerror", "debug", "eval",
+ "expose", "hide", "hidden", "issafe",
+ "invokehidden", "limit", "marktrusted", "recursionlimit", NULL
};
enum options {
- OPT_ALIAS, OPT_ALIASES, OPT_EVAL, OPT_EXPOSE,
- OPT_HIDE, OPT_HIDDEN, OPT_ISSAFE, OPT_INVOKEHIDDEN,
- OPT_MARKTRUSTED, OPT_RECLIMIT
+ OPT_ALIAS, OPT_ALIASES, OPT_BGERROR, OPT_DEBUG, OPT_EVAL,
+ OPT_EXPOSE, OPT_HIDE, OPT_HIDDEN, OPT_ISSAFE,
+ OPT_INVOKEHIDDEN, OPT_LIMIT, OPT_MARKTRUSTED, OPT_RECLIMIT
};
-
- slaveInterp = (Tcl_Interp *) clientData;
+
if (slaveInterp == NULL) {
- panic("SlaveObjCmd: interpreter has been deleted");
+ Tcl_Panic("SlaveObjCmd: interpreter has been deleted");
}
if (objc < 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "cmd ?arg ...?");
- return TCL_ERROR;
+ Tcl_WrongNumArgs(interp, 1, objv, "cmd ?arg ...?");
+ return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0,
&index) != TCL_OK) {
@@ -1898,114 +2270,152 @@ SlaveObjCmd(clientData, interp, objc, objv)
}
switch ((enum options) index) {
- case OPT_ALIAS: {
- if (objc > 2) {
- if (objc == 3) {
- return AliasDescribe(interp, slaveInterp, objv[2]);
- }
- if (Tcl_GetString(objv[3])[0] == '\0') {
- if (objc == 4) {
- return AliasDelete(interp, slaveInterp, objv[2]);
- }
- } else {
- return AliasCreate(interp, slaveInterp, interp, objv[2],
- objv[3], objc - 4, objv + 4);
+ case OPT_ALIAS:
+ if (objc > 2) {
+ if (objc == 3) {
+ return AliasDescribe(interp, slaveInterp, objv[2]);
+ }
+ if (TclGetString(objv[3])[0] == '\0') {
+ if (objc == 4) {
+ return AliasDelete(interp, slaveInterp, objv[2]);
}
+ } else {
+ return AliasCreate(interp, slaveInterp, interp, objv[2],
+ objv[3], objc - 4, objv + 4);
}
- Tcl_WrongNumArgs(interp, 2, objv,
- "aliasName ?targetName? ?args..?");
- return TCL_ERROR;
}
- case OPT_ALIASES: {
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL);
- return TCL_ERROR;
- }
- return AliasList(interp, slaveInterp);
+ Tcl_WrongNumArgs(interp, 2, objv, "aliasName ?targetName? ?args..?");
+ return TCL_ERROR;
+ case OPT_ALIASES:
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return TCL_ERROR;
}
- case OPT_EVAL: {
- if (objc < 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "arg ?arg ...?");
- return TCL_ERROR;
- }
- return SlaveEval(interp, slaveInterp, objc - 2, objv + 2);
+ return AliasList(interp, slaveInterp);
+ case OPT_BGERROR:
+ if (objc != 2 && objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?cmdPrefix?");
+ return TCL_ERROR;
}
- case OPT_EXPOSE: {
- if ((objc < 3) || (objc > 4)) {
- Tcl_WrongNumArgs(interp, 2, objv, "hiddenCmdName ?cmdName?");
- return TCL_ERROR;
- }
- return SlaveExpose(interp, slaveInterp, objc - 2, objv + 2);
+ return SlaveBgerror(interp, slaveInterp, objc - 2, objv + 2);
+ case OPT_DEBUG:
+ /*
+ * TIP #378 *
+ * Currently only -frame supported, otherwise ?-option ?value? ...?
+ */
+ if (objc > 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-frame ?bool??");
+ return TCL_ERROR;
}
- case OPT_HIDE: {
- if ((objc < 3) || (objc > 4)) {
- Tcl_WrongNumArgs(interp, 2, objv, "cmdName ?hiddenCmdName?");
- return TCL_ERROR;
- }
- return SlaveHide(interp, slaveInterp, objc - 2, objv + 2);
+ return SlaveDebugCmd(interp, slaveInterp, objc - 2, objv + 2);
+ case OPT_EVAL:
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "arg ?arg ...?");
+ return TCL_ERROR;
}
- case OPT_HIDDEN: {
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- return TCL_ERROR;
- }
- return SlaveHidden(interp, slaveInterp);
+ return SlaveEval(interp, slaveInterp, objc - 2, objv + 2);
+ case OPT_EXPOSE:
+ if ((objc < 3) || (objc > 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "hiddenCmdName ?cmdName?");
+ return TCL_ERROR;
}
- case OPT_ISSAFE: {
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL);
+ return SlaveExpose(interp, slaveInterp, objc - 2, objv + 2);
+ case OPT_HIDE:
+ if ((objc < 3) || (objc > 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "cmdName ?hiddenCmdName?");
+ return TCL_ERROR;
+ }
+ return SlaveHide(interp, slaveInterp, objc - 2, objv + 2);
+ case OPT_HIDDEN:
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return TCL_ERROR;
+ }
+ return SlaveHidden(interp, slaveInterp);
+ case OPT_ISSAFE:
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(Tcl_IsSafe(slaveInterp)));
+ return TCL_OK;
+ case OPT_INVOKEHIDDEN: {
+ int i, index;
+ const char *namespaceName;
+ static const char *hiddenOptions[] = {
+ "-global", "-namespace", "--", NULL
+ };
+ enum hiddenOption {
+ OPT_GLOBAL, OPT_NAMESPACE, OPT_LAST
+ };
+
+ namespaceName = NULL;
+ for (i = 2; i < objc; i++) {
+ if (TclGetString(objv[i])[0] != '-') {
+ break;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[i], hiddenOptions, "option",
+ 0, &index) != TCL_OK) {
return TCL_ERROR;
}
- Tcl_SetIntObj(Tcl_GetObjResult(interp), Tcl_IsSafe(slaveInterp));
- return TCL_OK;
- }
- case OPT_INVOKEHIDDEN: {
- int global, i, index;
- static CONST char *hiddenOptions[] = {
- "-global", "--", NULL
- };
- enum hiddenOption {
- OPT_GLOBAL, OPT_LAST
- };
- global = 0;
- for (i = 2; i < objc; i++) {
- if (Tcl_GetString(objv[i])[0] != '-') {
+ if (index == OPT_GLOBAL) {
+ namespaceName = "::";
+ } else if (index == OPT_NAMESPACE) {
+ if (++i == objc) { /* There must be more arguments. */
break;
- }
- if (Tcl_GetIndexFromObj(interp, objv[i], hiddenOptions,
- "option", 0, &index) != TCL_OK) {
- return TCL_ERROR;
- }
- if (index == OPT_GLOBAL) {
- global = 1;
} else {
- i++;
- break;
+ namespaceName = TclGetString(objv[i]);
}
+ } else {
+ i++;
+ break;
}
- if (objc - i < 1) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-global? ?--? cmd ?arg ..?");
- return TCL_ERROR;
- }
- return SlaveInvokeHidden(interp, slaveInterp, global, objc - i,
- objv + i);
}
- case OPT_MARKTRUSTED: {
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- return TCL_ERROR;
- }
- return SlaveMarkTrusted(interp, slaveInterp);
+ if (objc - i < 1) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-namespace ns? ?-global? ?--? cmd ?arg ..?");
+ return TCL_ERROR;
}
- case OPT_RECLIMIT: {
- if (objc != 2 && objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "?newlimit?");
- return TCL_ERROR;
- }
- return SlaveRecursionLimit(interp, slaveInterp, objc - 2, objv + 2);
+ return SlaveInvokeHidden(interp, slaveInterp, namespaceName,
+ objc - i, objv + i);
+ }
+ case OPT_LIMIT: {
+ static const char *limitTypes[] = {
+ "commands", "time", NULL
+ };
+ enum LimitTypes {
+ LIMIT_TYPE_COMMANDS, LIMIT_TYPE_TIME
+ };
+ int limitType;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "limitType ?options?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[2], limitTypes, "limit type", 0,
+ &limitType) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum LimitTypes) limitType) {
+ case LIMIT_TYPE_COMMANDS:
+ return SlaveCommandLimitCmd(interp, slaveInterp, 3, objc,objv);
+ case LIMIT_TYPE_TIME:
+ return SlaveTimeLimitCmd(interp, slaveInterp, 3, objc, objv);
}
}
+ case OPT_MARKTRUSTED:
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return TCL_ERROR;
+ }
+ return SlaveMarkTrusted(interp, slaveInterp);
+ case OPT_RECLIMIT:
+ if (objc != 2 && objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?newlimit?");
+ return TCL_ERROR;
+ }
+ return SlaveRecursionLimit(interp, slaveInterp, objc - 2, objv + 2);
+ }
return TCL_ERROR;
}
@@ -2023,20 +2433,20 @@ SlaveObjCmd(clientData, interp, objc, objv)
* None.
*
* Side effects:
- * Cleans up all state associated with the slave interpreter and
- * destroys the slave interpreter.
+ * Cleans up all state associated with the slave interpreter and destroys
+ * the slave interpreter.
*
*----------------------------------------------------------------------
*/
static void
-SlaveObjCmdDeleteProc(clientData)
- ClientData clientData; /* The SlaveRecord for the command. */
+SlaveObjCmdDeleteProc(
+ ClientData clientData) /* The SlaveRecord for the command. */
{
- Slave *slavePtr; /* Interim storage for Slave record. */
- Tcl_Interp *slaveInterp; /* And for a slave interp. */
+ Slave *slavePtr; /* Interim storage for Slave record. */
+ Tcl_Interp *slaveInterp = clientData;
+ /* And for a slave interp. */
- slaveInterp = (Tcl_Interp *) clientData;
slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave;
/*
@@ -2046,9 +2456,9 @@ SlaveObjCmdDeleteProc(clientData)
Tcl_DeleteHashEntry(slavePtr->slaveEntryPtr);
/*
- * Set to NULL so that when the InterpInfo is cleaned up in the slave
- * it does not try to delete the command causing all sorts of grief.
- * See SlaveRecordDeleteProc().
+ * Set to NULL so that when the InterpInfo is cleaned up in the slave it
+ * does not try to delete the command causing all sorts of grief. See
+ * SlaveRecordDeleteProc().
*/
slavePtr->interpCmd = NULL;
@@ -2061,6 +2471,75 @@ SlaveObjCmdDeleteProc(clientData)
/*
*----------------------------------------------------------------------
*
+ * SlaveDebugCmd -- TIP #378
+ *
+ * Helper function to handle 'debug' command in a slave interpreter.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * May modify INTERP_DEBUG flag in the slave.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SlaveDebugCmd(
+ Tcl_Interp *interp, /* Interp for error return. */
+ Tcl_Interp *slaveInterp, /* The slave interpreter in which command
+ * will be evaluated. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ static const char *debugTypes[] = {
+ "-frame", NULL
+ };
+ enum DebugTypes {
+ DEBUG_TYPE_FRAME
+ };
+ int debugType;
+ Interp *iPtr;
+ Tcl_Obj *resultPtr;
+
+ iPtr = (Interp *) slaveInterp;
+ if (objc == 0) {
+ resultPtr = Tcl_NewObj();
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewStringObj("-frame", -1));
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewBooleanObj(iPtr->flags & INTERP_DEBUG_FRAME));
+ Tcl_SetObjResult(interp, resultPtr);
+ } else {
+ if (Tcl_GetIndexFromObj(interp, objv[0], debugTypes,
+ "debug option", 0, &debugType) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (debugType == DEBUG_TYPE_FRAME) {
+ if (objc == 2) { /* set */
+ if (Tcl_GetBooleanFromObj(interp, objv[1], &debugType)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ /*
+ * Quietly ignore attempts to disable interp debugging.
+ * This is a one-way switch as frame debug info is maintained
+ * in a stack that must be consistent once turned on.
+ */
+ if (debugType) {
+ iPtr->flags |= INTERP_DEBUG_FRAME;
+ }
+ }
+ Tcl_SetObjResult(interp,
+ Tcl_NewBooleanObj(iPtr->flags & INTERP_DEBUG_FRAME));
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* SlaveEval --
*
* Helper function to evaluate a command in a slave interpreter.
@@ -2075,30 +2554,30 @@ SlaveObjCmdDeleteProc(clientData)
*/
static int
-SlaveEval(interp, slaveInterp, objc, objv)
- Tcl_Interp *interp; /* Interp for error return. */
- Tcl_Interp *slaveInterp; /* The slave interpreter in which command
+SlaveEval(
+ Tcl_Interp *interp, /* Interp for error return. */
+ Tcl_Interp *slaveInterp, /* The slave interpreter in which command
* will be evaluated. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
int result;
Tcl_Obj *objPtr;
-
- Tcl_Preserve((ClientData) slaveInterp);
+
+ Tcl_Preserve(slaveInterp);
Tcl_AllowExceptions(slaveInterp);
if (objc == 1) {
-#ifndef TCL_TIP280
- result = Tcl_EvalObjEx(slaveInterp, objv[0], 0);
-#else
- /* TIP #280 : Make actual argument location available to eval'd script */
- Interp* iPtr = (Interp*) interp;
+ /*
+ * TIP #280: Make actual argument location available to eval'd script.
+ */
+
+ Interp *iPtr = (Interp *) interp;
CmdFrame* invoker = iPtr->cmdFramePtr;
int word = 0;
+
TclArgumentGet (interp, objv[0], &invoker, &word);
result = TclEvalObjEx(slaveInterp, objv[0], 0, invoker, word);
-#endif
} else {
objPtr = Tcl_ConcatObj(objc, objv);
Tcl_IncrRefCount(objPtr);
@@ -2107,7 +2586,7 @@ SlaveEval(interp, slaveInterp, objc, objv)
}
TclTransferResult(slaveInterp, result, interp);
- Tcl_Release((ClientData) slaveInterp);
+ Tcl_Release(slaveInterp);
return result;
}
@@ -2122,30 +2601,30 @@ SlaveEval(interp, slaveInterp, objc, objv)
* A standard Tcl result.
*
* Side effects:
- * After this call scripts in the slave will be able to invoke
- * the newly exposed command.
+ * After this call scripts in the slave will be able to invoke the newly
+ * exposed command.
*
*----------------------------------------------------------------------
*/
static int
-SlaveExpose(interp, slaveInterp, objc, objv)
- Tcl_Interp *interp; /* Interp for error return. */
- Tcl_Interp *slaveInterp; /* Interp in which command will be exposed. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument strings. */
+SlaveExpose(
+ Tcl_Interp *interp, /* Interp for error return. */
+ Tcl_Interp *slaveInterp, /* Interp in which command will be exposed. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
{
char *name;
-
+
if (Tcl_IsSafe(interp)) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
"permission denied: safe interpreter cannot expose commands",
- (char *) NULL);
+ -1));
return TCL_ERROR;
}
- name = Tcl_GetString(objv[(objc == 1) ? 0 : 1]);
- if (Tcl_ExposeCommand(slaveInterp, Tcl_GetString(objv[0]),
+ name = TclGetString(objv[(objc == 1) ? 0 : 1]);
+ if (Tcl_ExposeCommand(slaveInterp, TclGetString(objv[0]),
name) != TCL_OK) {
TclTransferResult(slaveInterp, TCL_ERROR, interp);
return TCL_ERROR;
@@ -2164,31 +2643,29 @@ SlaveExpose(interp, slaveInterp, objc, objv)
* A standard Tcl result.
*
* Side effects:
- * When (objc == 1), slaveInterp will be set to a new recursion
- * limit of objv[0].
+ * When (objc == 1), slaveInterp will be set to a new recursion limit of
+ * objv[0].
*
*----------------------------------------------------------------------
*/
static int
-SlaveRecursionLimit(interp, slaveInterp, objc, objv)
- Tcl_Interp *interp; /* Interp for error return. */
- Tcl_Interp *slaveInterp; /* Interp in which limit is set/queried. */
- int objc; /* Set or Query. */
- Tcl_Obj *CONST objv[]; /* Argument strings. */
+SlaveRecursionLimit(
+ Tcl_Interp *interp, /* Interp for error return. */
+ Tcl_Interp *slaveInterp, /* Interp in which limit is set/queried. */
+ int objc, /* Set or Query. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
{
Interp *iPtr;
int limit;
if (objc) {
if (Tcl_IsSafe(interp)) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "permission denied: ",
- "safe interpreters cannot change recursion limit",
- (char *) NULL);
+ Tcl_AppendResult(interp, "permission denied: "
+ "safe interpreters cannot change recursion limit", NULL);
return TCL_ERROR;
}
- if (Tcl_GetIntFromObj(interp, objv[0], &limit) == TCL_ERROR) {
+ if (TclGetIntFromObj(interp, objv[0], &limit) == TCL_ERROR) {
return TCL_ERROR;
}
if (limit <= 0) {
@@ -2204,11 +2681,11 @@ SlaveRecursionLimit(interp, slaveInterp, objc, objv)
return TCL_ERROR;
}
Tcl_SetObjResult(interp, objv[0]);
- return TCL_OK;
+ return TCL_OK;
} else {
limit = Tcl_SetRecursionLimit(slaveInterp, 0);
Tcl_SetObjResult(interp, Tcl_NewIntObj(limit));
- return TCL_OK;
+ return TCL_OK;
}
}
@@ -2223,31 +2700,30 @@ SlaveRecursionLimit(interp, slaveInterp, objc, objv)
* A standard Tcl result.
*
* Side effects:
- * After this call scripts in the slave will no longer be able
- * to invoke the named command.
+ * After this call scripts in the slave will no longer be able to invoke
+ * the named command.
*
*----------------------------------------------------------------------
*/
static int
-SlaveHide(interp, slaveInterp, objc, objv)
- Tcl_Interp *interp; /* Interp for error return. */
- Tcl_Interp *slaveInterp; /* Interp in which command will be exposed. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument strings. */
+SlaveHide(
+ Tcl_Interp *interp, /* Interp for error return. */
+ Tcl_Interp *slaveInterp, /* Interp in which command will be exposed. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
{
char *name;
-
+
if (Tcl_IsSafe(interp)) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
"permission denied: safe interpreter cannot hide commands",
- (char *) NULL);
+ -1));
return TCL_ERROR;
}
- name = Tcl_GetString(objv[(objc == 1) ? 0 : 1]);
- if (Tcl_HideCommand(slaveInterp, Tcl_GetString(objv[0]),
- name) != TCL_OK) {
+ name = TclGetString(objv[(objc == 1) ? 0 : 1]);
+ if (Tcl_HideCommand(slaveInterp, TclGetString(objv[0]), name) != TCL_OK) {
TclTransferResult(slaveInterp, TCL_ERROR, interp);
return TCL_ERROR;
}
@@ -2272,26 +2748,25 @@ SlaveHide(interp, slaveInterp, objc, objv)
*/
static int
-SlaveHidden(interp, slaveInterp)
- Tcl_Interp *interp; /* Interp for data return. */
- Tcl_Interp *slaveInterp; /* Interp whose hidden commands to query. */
+SlaveHidden(
+ Tcl_Interp *interp, /* Interp for data return. */
+ Tcl_Interp *slaveInterp) /* Interp whose hidden commands to query. */
{
- Tcl_Obj *listObjPtr; /* Local object pointer. */
+ Tcl_Obj *listObjPtr = Tcl_NewObj(); /* Local object pointer. */
Tcl_HashTable *hTblPtr; /* For local searches. */
Tcl_HashEntry *hPtr; /* For local searches. */
Tcl_HashSearch hSearch; /* For local searches. */
-
- listObjPtr = Tcl_GetObjResult(interp);
+
hTblPtr = ((Interp *) slaveInterp)->hiddenCmdTablePtr;
- if (hTblPtr != (Tcl_HashTable *) NULL) {
+ if (hTblPtr != NULL) {
for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
- hPtr != (Tcl_HashEntry *) NULL;
- hPtr = Tcl_NextHashEntry(&hSearch)) {
-
+ hPtr != NULL;
+ hPtr = Tcl_NextHashEntry(&hSearch)) {
Tcl_ListObjAppendElement(NULL, listObjPtr,
Tcl_NewStringObj(Tcl_GetHashKey(hTblPtr, hPtr), -1));
}
}
+ Tcl_SetObjResult(interp, listObjPtr);
return TCL_OK;
}
@@ -2312,37 +2787,45 @@ SlaveHidden(interp, slaveInterp)
*/
static int
-SlaveInvokeHidden(interp, slaveInterp, global, objc, objv)
- Tcl_Interp *interp; /* Interp for error return. */
- Tcl_Interp *slaveInterp; /* The slave interpreter in which command
- * will be invoked. */
- int global; /* Non-zero to invoke in global namespace. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+SlaveInvokeHidden(
+ Tcl_Interp *interp, /* Interp for error return. */
+ Tcl_Interp *slaveInterp, /* The slave interpreter in which command will
+ * be invoked. */
+ const char *namespaceName, /* The namespace to use, if any. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
int result;
-
+
if (Tcl_IsSafe(interp)) {
- Tcl_SetStringObj(Tcl_GetObjResult(interp),
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
"not allowed to invoke hidden commands from safe interpreter",
- -1);
+ -1));
return TCL_ERROR;
}
- Tcl_Preserve((ClientData) slaveInterp);
+ Tcl_Preserve(slaveInterp);
Tcl_AllowExceptions(slaveInterp);
-
- if (global) {
- result = TclObjInvokeGlobal(slaveInterp, objc, objv,
- TCL_INVOKE_HIDDEN);
+
+ if (namespaceName == NULL) {
+ result = TclObjInvoke(slaveInterp, objc, objv, TCL_INVOKE_HIDDEN);
} else {
- result = TclObjInvoke(slaveInterp, objc, objv, TCL_INVOKE_HIDDEN);
+ Namespace *nsPtr, *dummy1, *dummy2;
+ const char *tail;
+
+ result = TclGetNamespaceForQualName(slaveInterp, namespaceName, NULL,
+ TCL_FIND_ONLY_NS | TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG
+ | TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
+ if (result == TCL_OK) {
+ result = TclObjInvokeNamespace(slaveInterp, objc, objv,
+ (Tcl_Namespace *)nsPtr, TCL_INVOKE_HIDDEN);
+ }
}
TclTransferResult(slaveInterp, result, interp);
- Tcl_Release((ClientData) slaveInterp);
- return result;
+ Tcl_Release(slaveInterp);
+ return result;
}
/*
@@ -2356,22 +2839,22 @@ SlaveInvokeHidden(interp, slaveInterp, global, objc, objv)
* A standard Tcl result.
*
* Side effects:
- * After this call the hard-wired security checks in the core no
- * longer prevent the slave from performing certain operations.
+ * After this call the hard-wired security checks in the core no longer
+ * prevent the slave from performing certain operations.
*
*----------------------------------------------------------------------
*/
static int
-SlaveMarkTrusted(interp, slaveInterp)
- Tcl_Interp *interp; /* Interp for error return. */
- Tcl_Interp *slaveInterp; /* The slave interpreter which will be
- * marked trusted. */
+SlaveMarkTrusted(
+ Tcl_Interp *interp, /* Interp for error return. */
+ Tcl_Interp *slaveInterp) /* The slave interpreter which will be marked
+ * trusted. */
{
if (Tcl_IsSafe(interp)) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
"permission denied: safe interpreter cannot mark trusted",
- (char *) NULL);
+ -1));
return TCL_ERROR;
}
((Interp *) slaveInterp)->flags &= ~SAFE_INTERP;
@@ -2395,17 +2878,15 @@ SlaveMarkTrusted(interp, slaveInterp)
*/
int
-Tcl_IsSafe(interp)
- Tcl_Interp *interp; /* Is this interpreter "safe" ? */
+Tcl_IsSafe(
+ Tcl_Interp *interp) /* Is this interpreter "safe" ? */
{
- Interp *iPtr;
+ Interp *iPtr = (Interp *) interp;
- if (interp == (Tcl_Interp *) NULL) {
- return 0;
+ if (iPtr == NULL) {
+ return 0;
}
- iPtr = (Interp *) interp;
-
- return ( (iPtr->flags) & SAFE_INTERP ) ? 1 : 0 ;
+ return (iPtr->flags & SAFE_INTERP) ? 1 : 0;
}
/*
@@ -2414,34 +2895,50 @@ Tcl_IsSafe(interp)
* Tcl_MakeSafe --
*
* Makes its argument interpreter contain only functionality that is
- * defined to be part of Safe Tcl. Unsafe commands are hidden, the
- * env array is unset, and the standard channels are removed.
+ * defined to be part of Safe Tcl. Unsafe commands are hidden, the env
+ * array is unset, and the standard channels are removed.
*
* Results:
* None.
*
* Side effects:
- * Hides commands in its argument interpreter, and removes settings
- * and channels.
+ * Hides commands in its argument interpreter, and removes settings and
+ * channels.
*
*----------------------------------------------------------------------
*/
int
-Tcl_MakeSafe(interp)
- Tcl_Interp *interp; /* Interpreter to be made safe. */
+Tcl_MakeSafe(
+ Tcl_Interp *interp) /* Interpreter to be made safe. */
{
- Tcl_Channel chan; /* Channel to remove from
- * safe interpreter. */
+ Tcl_Channel chan; /* Channel to remove from safe interpreter. */
Interp *iPtr = (Interp *) interp;
+ Tcl_Interp *master = ((InterpInfo*) iPtr->interpInfo)->slave.masterInterp;
TclHideUnsafeCommands(interp);
-
+
+ if (master != NULL) {
+ /*
+ * Alias these function implementations in the slave to those in the
+ * master; the overall implementations are safe, but they're normally
+ * defined by init.tcl which is not sourced by safe interpreters.
+ * Assume these functions all work. [Bug 2895741]
+ */
+
+ (void) Tcl_Eval(interp,
+ "namespace eval ::tcl {namespace eval mathfunc {}}");
+ (void) Tcl_CreateAlias(interp, "::tcl::mathfunc::min", master,
+ "::tcl::mathfunc::min", 0, NULL);
+ (void) Tcl_CreateAlias(interp, "::tcl::mathfunc::max", master,
+ "::tcl::mathfunc::max", 0, NULL);
+ }
+
iPtr->flags |= SAFE_INTERP;
/*
- * Unsetting variables : (which should not have been set
- * in the first place, but...)
+ * Unsetting variables : (which should not have been set in the first
+ * place, but...)
*/
/*
@@ -2450,7 +2947,7 @@ Tcl_MakeSafe(interp)
Tcl_UnsetVar(interp, "env", TCL_GLOBAL_ONLY);
- /*
+ /*
* Remove unsafe parts of tcl_platform
*/
@@ -2460,37 +2957,1556 @@ Tcl_MakeSafe(interp)
Tcl_UnsetVar2(interp, "tcl_platform", "user", TCL_GLOBAL_ONLY);
/*
- * Unset path informations variables
- * (the only one remaining is [info nameofexecutable])
+ * Unset path informations variables (the only one remaining is [info
+ * nameofexecutable])
*/
Tcl_UnsetVar(interp, "tclDefaultLibrary", TCL_GLOBAL_ONLY);
Tcl_UnsetVar(interp, "tcl_library", TCL_GLOBAL_ONLY);
Tcl_UnsetVar(interp, "tcl_pkgPath", TCL_GLOBAL_ONLY);
-
+
/*
- * Remove the standard channels from the interpreter; safe interpreters
- * do not ordinarily have access to stdin, stdout and stderr.
+ * Remove the standard channels from the interpreter; safe interpreters do
+ * not ordinarily have access to stdin, stdout and stderr.
*
* NOTE: These channels are not added to the interpreter by the
* Tcl_CreateInterp call, but may be added later, by another I/O
- * operation. We want to ensure that the interpreter does not have
- * these channels even if it is being made safe after being used for
- * some time..
+ * operation. We want to ensure that the interpreter does not have these
+ * channels even if it is being made safe after being used for some time..
*/
chan = Tcl_GetStdChannel(TCL_STDIN);
- if (chan != (Tcl_Channel) NULL) {
- Tcl_UnregisterChannel(interp, chan);
+ if (chan != NULL) {
+ Tcl_UnregisterChannel(interp, chan);
}
chan = Tcl_GetStdChannel(TCL_STDOUT);
- if (chan != (Tcl_Channel) NULL) {
- Tcl_UnregisterChannel(interp, chan);
+ if (chan != NULL) {
+ Tcl_UnregisterChannel(interp, chan);
}
chan = Tcl_GetStdChannel(TCL_STDERR);
- if (chan != (Tcl_Channel) NULL) {
- Tcl_UnregisterChannel(interp, chan);
+ if (chan != NULL) {
+ Tcl_UnregisterChannel(interp, chan);
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LimitExceeded --
+ *
+ * Tests whether any limit has been exceeded in the given interpreter
+ * (i.e. whether the interpreter is currently unable to process further
+ * scripts).
+ *
+ * Results:
+ * A boolean value.
+ *
+ * Side effects:
+ * None.
+ *
+ * Notes:
+ * If you change this function, you MUST also update TclLimitExceeded() in
+ * tclInt.h.
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_LimitExceeded(
+ Tcl_Interp *interp)
+{
+ register Interp *iPtr = (Interp *) interp;
+
+ return iPtr->limit.exceeded != 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LimitReady --
+ *
+ * Find out whether any limit has been set on the interpreter, and if so
+ * check whether the granularity of that limit is such that the full
+ * limit check should be carried out.
+ *
+ * Results:
+ * A boolean value that indicates whether to call Tcl_LimitCheck.
+ *
+ * Side effects:
+ * Increments the limit granularity counter.
+ *
+ * Notes:
+ * If you change this function, you MUST also update TclLimitReady() in
+ * tclInt.h.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_LimitReady(
+ Tcl_Interp *interp)
+{
+ register Interp *iPtr = (Interp *) interp;
+
+ if (iPtr->limit.active != 0) {
+ register int ticker = ++iPtr->limit.granularityTicker;
+
+ if ((iPtr->limit.active & TCL_LIMIT_COMMANDS) &&
+ ((iPtr->limit.cmdGranularity == 1) ||
+ (ticker % iPtr->limit.cmdGranularity == 0))) {
+ return 1;
+ }
+ if ((iPtr->limit.active & TCL_LIMIT_TIME) &&
+ ((iPtr->limit.timeGranularity == 1) ||
+ (ticker % iPtr->limit.timeGranularity == 0))) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LimitCheck --
+ *
+ * Check all currently set limits in the interpreter (where permitted by
+ * granularity). If a limit is exceeded, call its callbacks and, if the
+ * limit is still exceeded after the callbacks have run, make the
+ * interpreter generate an error that cannot be caught within the limited
+ * interpreter.
+ *
+ * Results:
+ * A Tcl result value (TCL_OK if no limit is exceeded, and TCL_ERROR if a
+ * limit has been exceeded).
+ *
+ * Side effects:
+ * May invoke system calls. May invoke other interpreters. May be
+ * reentrant. May put the interpreter into a state where it can no longer
+ * execute commands without outside intervention.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_LimitCheck(
+ Tcl_Interp *interp)
+{
+ Interp *iPtr = (Interp *) interp;
+ register int ticker = iPtr->limit.granularityTicker;
+
+ if (Tcl_InterpDeleted(interp)) {
+ return TCL_OK;
+ }
+
+ if ((iPtr->limit.active & TCL_LIMIT_COMMANDS) &&
+ ((iPtr->limit.cmdGranularity == 1) ||
+ (ticker % iPtr->limit.cmdGranularity == 0)) &&
+ (iPtr->limit.cmdCount < iPtr->cmdCount)) {
+ iPtr->limit.exceeded |= TCL_LIMIT_COMMANDS;
+ Tcl_Preserve(interp);
+ RunLimitHandlers(iPtr->limit.cmdHandlers, interp);
+ if (iPtr->limit.cmdCount >= iPtr->cmdCount) {
+ iPtr->limit.exceeded &= ~TCL_LIMIT_COMMANDS;
+ } else if (iPtr->limit.exceeded & TCL_LIMIT_COMMANDS) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "command count limit exceeded", NULL);
+ Tcl_Release(interp);
+ return TCL_ERROR;
+ }
+ Tcl_Release(interp);
+ }
+
+ if ((iPtr->limit.active & TCL_LIMIT_TIME) &&
+ ((iPtr->limit.timeGranularity == 1) ||
+ (ticker % iPtr->limit.timeGranularity == 0))) {
+ Tcl_Time now;
+
+ Tcl_GetTime(&now);
+ if (iPtr->limit.time.sec < now.sec ||
+ (iPtr->limit.time.sec == now.sec &&
+ iPtr->limit.time.usec < now.usec)) {
+ iPtr->limit.exceeded |= TCL_LIMIT_TIME;
+ Tcl_Preserve(interp);
+ RunLimitHandlers(iPtr->limit.timeHandlers, interp);
+ if (iPtr->limit.time.sec > now.sec ||
+ (iPtr->limit.time.sec == now.sec &&
+ iPtr->limit.time.usec >= now.usec)) {
+ iPtr->limit.exceeded &= ~TCL_LIMIT_TIME;
+ } else if (iPtr->limit.exceeded & TCL_LIMIT_TIME) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "time limit exceeded", NULL);
+ Tcl_Release(interp);
+ return TCL_ERROR;
+ }
+ Tcl_Release(interp);
+ }
}
return TCL_OK;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RunLimitHandlers --
+ *
+ * Invoke all the limit handlers in a list (for a particular limit).
+ * Note that no particular limit handler callback will be invoked
+ * reentrantly.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depends on the limit handlers.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RunLimitHandlers(
+ LimitHandler *handlerPtr,
+ Tcl_Interp *interp)
+{
+ LimitHandler *nextPtr;
+ for (; handlerPtr!=NULL ; handlerPtr=nextPtr) {
+ if (handlerPtr->flags & (LIMIT_HANDLER_DELETED|LIMIT_HANDLER_ACTIVE)) {
+ /*
+ * Reentrant call or something seriously strange in the delete
+ * code.
+ */
+
+ nextPtr = handlerPtr->nextPtr;
+ continue;
+ }
+
+ /*
+ * Set the ACTIVE flag while running the limit handler itself so we
+ * cannot reentrantly call this handler and know to use the alternate
+ * method of deletion if necessary.
+ */
+
+ handlerPtr->flags |= LIMIT_HANDLER_ACTIVE;
+ (handlerPtr->handlerProc)(handlerPtr->clientData, interp);
+ handlerPtr->flags &= ~LIMIT_HANDLER_ACTIVE;
+
+ /*
+ * Rediscover this value; it might have changed during the processing
+ * of a limit handler. We have to record it here because we might
+ * delete the structure below, and reading a value out of a deleted
+ * structure is unsafe (even if actually legal with some
+ * malloc()/free() implementations.)
+ */
+
+ nextPtr = handlerPtr->nextPtr;
+
+ /*
+ * If we deleted the current handler while we were executing it, we
+ * will have spliced it out of the list and set the
+ * LIMIT_HANDLER_DELETED flag.
+ */
+
+ if (handlerPtr->flags & LIMIT_HANDLER_DELETED) {
+ if (handlerPtr->deleteProc != NULL) {
+ (handlerPtr->deleteProc)(handlerPtr->clientData);
+ }
+ ckfree((char *) handlerPtr);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LimitAddHandler --
+ *
+ * Add a callback handler for a particular resource limit.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Extends the internal linked list of handlers for a limit.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_LimitAddHandler(
+ Tcl_Interp *interp,
+ int type,
+ Tcl_LimitHandlerProc *handlerProc,
+ ClientData clientData,
+ Tcl_LimitHandlerDeleteProc *deleteProc)
+{
+ Interp *iPtr = (Interp *) interp;
+ LimitHandler *handlerPtr;
+
+ /*
+ * Convert everything into a real deletion callback.
+ */
+
+ if (deleteProc == (Tcl_LimitHandlerDeleteProc *) TCL_DYNAMIC) {
+ deleteProc = (Tcl_LimitHandlerDeleteProc *) Tcl_Free;
+ }
+ if (deleteProc == (Tcl_LimitHandlerDeleteProc *) TCL_STATIC) {
+ deleteProc = NULL;
+ }
+
+ /*
+ * Allocate a handler record.
+ */
+
+ handlerPtr = (LimitHandler *) ckalloc(sizeof(LimitHandler));
+ handlerPtr->flags = 0;
+ handlerPtr->handlerProc = handlerProc;
+ handlerPtr->clientData = clientData;
+ handlerPtr->deleteProc = deleteProc;
+ handlerPtr->prevPtr = NULL;
+
+ /*
+ * Prepend onto the front of the correct linked list.
+ */
+
+ switch (type) {
+ case TCL_LIMIT_COMMANDS:
+ handlerPtr->nextPtr = iPtr->limit.cmdHandlers;
+ if (handlerPtr->nextPtr != NULL) {
+ handlerPtr->nextPtr->prevPtr = handlerPtr;
+ }
+ iPtr->limit.cmdHandlers = handlerPtr;
+ return;
+
+ case TCL_LIMIT_TIME:
+ handlerPtr->nextPtr = iPtr->limit.timeHandlers;
+ if (handlerPtr->nextPtr != NULL) {
+ handlerPtr->nextPtr->prevPtr = handlerPtr;
+ }
+ iPtr->limit.timeHandlers = handlerPtr;
+ return;
+ }
+
+ Tcl_Panic("unknown type of resource limit");
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LimitRemoveHandler --
+ *
+ * Remove a callback handler for a particular resource limit.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The handler is spliced out of the internal linked list for the limit,
+ * and if not currently being invoked, deleted. Otherwise it is just
+ * marked for deletion and removed when the limit handler has finished
+ * executing.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_LimitRemoveHandler(
+ Tcl_Interp *interp,
+ int type,
+ Tcl_LimitHandlerProc *handlerProc,
+ ClientData clientData)
+{
+ Interp *iPtr = (Interp *) interp;
+ LimitHandler *handlerPtr;
+
+ switch (type) {
+ case TCL_LIMIT_COMMANDS:
+ handlerPtr = iPtr->limit.cmdHandlers;
+ break;
+ case TCL_LIMIT_TIME:
+ handlerPtr = iPtr->limit.timeHandlers;
+ break;
+ default:
+ Tcl_Panic("unknown type of resource limit");
+ return;
+ }
+
+ for (; handlerPtr!=NULL ; handlerPtr=handlerPtr->nextPtr) {
+ if ((handlerPtr->handlerProc != handlerProc) ||
+ (handlerPtr->clientData != clientData)) {
+ continue;
+ }
+
+ /*
+ * We've found the handler to delete; mark it as doomed if not already
+ * so marked (which shouldn't actually happen).
+ */
+
+ if (handlerPtr->flags & LIMIT_HANDLER_DELETED) {
+ return;
+ }
+ handlerPtr->flags |= LIMIT_HANDLER_DELETED;
+
+ /*
+ * Splice the handler out of the doubly-linked list.
+ */
+
+ if (handlerPtr->prevPtr == NULL) {
+ switch (type) {
+ case TCL_LIMIT_COMMANDS:
+ iPtr->limit.cmdHandlers = handlerPtr->nextPtr;
+ break;
+ case TCL_LIMIT_TIME:
+ iPtr->limit.timeHandlers = handlerPtr->nextPtr;
+ break;
+ }
+ } else {
+ handlerPtr->prevPtr->nextPtr = handlerPtr->nextPtr;
+ }
+ if (handlerPtr->nextPtr != NULL) {
+ handlerPtr->nextPtr->prevPtr = handlerPtr->prevPtr;
+ }
+
+ /*
+ * If nothing is currently executing the handler, delete its client
+ * data and the overall handler structure now. Otherwise it will all
+ * go away when the handler returns.
+ */
+
+ if (!(handlerPtr->flags & LIMIT_HANDLER_ACTIVE)) {
+ if (handlerPtr->deleteProc != NULL) {
+ (handlerPtr->deleteProc)(handlerPtr->clientData);
+ }
+ ckfree((char *) handlerPtr);
+ }
+ return;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclLimitRemoveAllHandlers --
+ *
+ * Remove all limit callback handlers for an interpreter. This is invoked
+ * as part of deleting the interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Limit handlers are deleted or marked for deletion (as with
+ * Tcl_LimitRemoveHandler).
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclLimitRemoveAllHandlers(
+ Tcl_Interp *interp)
+{
+ Interp *iPtr = (Interp *) interp;
+ LimitHandler *handlerPtr, *nextHandlerPtr;
+
+ /*
+ * Delete all command-limit handlers.
+ */
+
+ for (handlerPtr=iPtr->limit.cmdHandlers, iPtr->limit.cmdHandlers=NULL;
+ handlerPtr!=NULL; handlerPtr=nextHandlerPtr) {
+ nextHandlerPtr = handlerPtr->nextPtr;
+
+ /*
+ * Do not delete here if it has already been marked for deletion.
+ */
+
+ if (handlerPtr->flags & LIMIT_HANDLER_DELETED) {
+ continue;
+ }
+ handlerPtr->flags |= LIMIT_HANDLER_DELETED;
+ handlerPtr->prevPtr = NULL;
+ handlerPtr->nextPtr = NULL;
+
+ /*
+ * If nothing is currently executing the handler, delete its client
+ * data and the overall handler structure now. Otherwise it will all
+ * go away when the handler returns.
+ */
+
+ if (!(handlerPtr->flags & LIMIT_HANDLER_ACTIVE)) {
+ if (handlerPtr->deleteProc != NULL) {
+ (handlerPtr->deleteProc)(handlerPtr->clientData);
+ }
+ ckfree((char *) handlerPtr);
+ }
+ }
+
+ /*
+ * Delete all time-limit handlers.
+ */
+
+ for (handlerPtr=iPtr->limit.timeHandlers, iPtr->limit.timeHandlers=NULL;
+ handlerPtr!=NULL; handlerPtr=nextHandlerPtr) {
+ nextHandlerPtr = handlerPtr->nextPtr;
+
+ /*
+ * Do not delete here if it has already been marked for deletion.
+ */
+
+ if (handlerPtr->flags & LIMIT_HANDLER_DELETED) {
+ continue;
+ }
+ handlerPtr->flags |= LIMIT_HANDLER_DELETED;
+ handlerPtr->prevPtr = NULL;
+ handlerPtr->nextPtr = NULL;
+
+ /*
+ * If nothing is currently executing the handler, delete its client
+ * data and the overall handler structure now. Otherwise it will all
+ * go away when the handler returns.
+ */
+
+ if (!(handlerPtr->flags & LIMIT_HANDLER_ACTIVE)) {
+ if (handlerPtr->deleteProc != NULL) {
+ (handlerPtr->deleteProc)(handlerPtr->clientData);
+ }
+ ckfree((char *) handlerPtr);
+ }
+ }
+
+ /*
+ * Delete the timer callback that is used to trap limits that occur in
+ * [vwait]s...
+ */
+
+ if (iPtr->limit.timeEvent != NULL) {
+ Tcl_DeleteTimerHandler(iPtr->limit.timeEvent);
+ iPtr->limit.timeEvent = NULL;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LimitTypeEnabled --
+ *
+ * Check whether a particular limit has been enabled for an interpreter.
+ *
+ * Results:
+ * A boolean value.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_LimitTypeEnabled(
+ Tcl_Interp *interp,
+ int type)
+{
+ Interp *iPtr = (Interp *) interp;
+
+ return (iPtr->limit.active & type) != 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LimitTypeExceeded --
+ *
+ * Check whether a particular limit has been exceeded for an interpreter.
+ *
+ * Results:
+ * A boolean value (note that Tcl_LimitExceeded will always return
+ * non-zero when this function returns non-zero).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_LimitTypeExceeded(
+ Tcl_Interp *interp,
+ int type)
+{
+ Interp *iPtr = (Interp *) interp;
+
+ return (iPtr->limit.exceeded & type) != 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LimitTypeSet --
+ *
+ * Enable a particular limit for an interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The limit is turned on and will be checked in future at an interval
+ * determined by the frequency of calling of Tcl_LimitReady and the
+ * granularity of the limit in question.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_LimitTypeSet(
+ Tcl_Interp *interp,
+ int type)
+{
+ Interp *iPtr = (Interp *) interp;
+
+ iPtr->limit.active |= type;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LimitTypeReset --
+ *
+ * Disable a particular limit for an interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The limit is disabled. If the limit was exceeded when this function
+ * was called, the limit will no longer be exceeded afterwards and the
+ * interpreter will be free to execute further scripts (assuming it isn't
+ * also deleted, of course).
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_LimitTypeReset(
+ Tcl_Interp *interp,
+ int type)
+{
+ Interp *iPtr = (Interp *) interp;
+
+ iPtr->limit.active &= ~type;
+ iPtr->limit.exceeded &= ~type;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LimitSetCommands --
+ *
+ * Set the command limit for an interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Also resets whether the command limit was exceeded. This might permit
+ * a small amount of further execution in the interpreter even if the
+ * limit itself is theoretically exceeded.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_LimitSetCommands(
+ Tcl_Interp *interp,
+ int commandLimit)
+{
+ Interp *iPtr = (Interp *) interp;
+
+ iPtr->limit.cmdCount = commandLimit;
+ iPtr->limit.exceeded &= ~TCL_LIMIT_COMMANDS;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LimitGetCommands --
+ *
+ * Get the number of commands that may be executed in the interpreter
+ * before the command-limit is reached.
+ *
+ * Results:
+ * An upper bound on the number of commands.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_LimitGetCommands(
+ Tcl_Interp *interp)
+{
+ Interp *iPtr = (Interp *) interp;
+
+ return iPtr->limit.cmdCount;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LimitSetTime --
+ *
+ * Set the time limit for an interpreter by copying it from the value
+ * pointed to by the timeLimitPtr argument.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Also resets whether the time limit was exceeded. This might permit a
+ * small amount of further execution in the interpreter even if the limit
+ * itself is theoretically exceeded.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_LimitSetTime(
+ Tcl_Interp *interp,
+ Tcl_Time *timeLimitPtr)
+{
+ Interp *iPtr = (Interp *) interp;
+ Tcl_Time nextMoment;
+
+ memcpy(&iPtr->limit.time, timeLimitPtr, sizeof(Tcl_Time));
+ if (iPtr->limit.timeEvent != NULL) {
+ Tcl_DeleteTimerHandler(iPtr->limit.timeEvent);
+ }
+ nextMoment.sec = timeLimitPtr->sec;
+ nextMoment.usec = timeLimitPtr->usec+10;
+ if (nextMoment.usec >= 1000000) {
+ nextMoment.sec++;
+ nextMoment.usec -= 1000000;
+ }
+ iPtr->limit.timeEvent = TclCreateAbsoluteTimerHandler(&nextMoment,
+ TimeLimitCallback, interp);
+ iPtr->limit.exceeded &= ~TCL_LIMIT_TIME;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TimeLimitCallback --
+ *
+ * Callback that allows time limits to be enforced even when doing a
+ * blocking wait for events.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May put the interpreter into a state where it can no longer execute
+ * commands. May make callbacks into other interpreters.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TimeLimitCallback(
+ ClientData clientData)
+{
+ Tcl_Interp *interp = clientData;
+ Interp *iPtr = clientData;
+ int code;
+
+ Tcl_Preserve(interp);
+ iPtr->limit.timeEvent = NULL;
+
+ /*
+ * Must reset the granularity ticker here to force an immediate full
+ * check. This is OK because we're swallowing the cost in the overall cost
+ * of the event loop. [Bug 2891362]
+ */
+
+ iPtr->limit.granularityTicker = 0;
+
+ code = Tcl_LimitCheck(interp);
+ if (code != TCL_OK) {
+ Tcl_AddErrorInfo(interp, "\n (while waiting for event)");
+ TclBackgroundException(interp, code);
+ }
+ Tcl_Release(interp);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LimitGetTime --
+ *
+ * Get the current time limit.
+ *
+ * Results:
+ * The time limit (by it being copied into the variable pointed to by the
+ * timeLimitPtr).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_LimitGetTime(
+ Tcl_Interp *interp,
+ Tcl_Time *timeLimitPtr)
+{
+ Interp *iPtr = (Interp *) interp;
+
+ memcpy(timeLimitPtr, &iPtr->limit.time, sizeof(Tcl_Time));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LimitSetGranularity --
+ *
+ * Set the granularity divisor (which must be positive) for a particular
+ * limit.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The granularity is updated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_LimitSetGranularity(
+ Tcl_Interp *interp,
+ int type,
+ int granularity)
+{
+ Interp *iPtr = (Interp *) interp;
+ if (granularity < 1) {
+ Tcl_Panic("limit granularity must be positive");
+ }
+
+ switch (type) {
+ case TCL_LIMIT_COMMANDS:
+ iPtr->limit.cmdGranularity = granularity;
+ return;
+ case TCL_LIMIT_TIME:
+ iPtr->limit.timeGranularity = granularity;
+ return;
+ }
+ Tcl_Panic("unknown type of resource limit");
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LimitGetGranularity --
+ *
+ * Get the granularity divisor for a particular limit.
+ *
+ * Results:
+ * The granularity divisor for the given limit.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_LimitGetGranularity(
+ Tcl_Interp *interp,
+ int type)
+{
+ Interp *iPtr = (Interp *) interp;
+
+ switch (type) {
+ case TCL_LIMIT_COMMANDS:
+ return iPtr->limit.cmdGranularity;
+ case TCL_LIMIT_TIME:
+ return iPtr->limit.timeGranularity;
+ }
+ Tcl_Panic("unknown type of resource limit");
+ return -1; /* NOT REACHED */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteScriptLimitCallback --
+ *
+ * Callback for when a script limit (a limit callback implemented as a
+ * Tcl script in a master interpreter, as set up from Tcl) is deleted.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The reference to the script callback from the controlling interpreter
+ * is removed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DeleteScriptLimitCallback(
+ ClientData clientData)
+{
+ ScriptLimitCallback *limitCBPtr = clientData;
+
+ Tcl_DecrRefCount(limitCBPtr->scriptObj);
+ if (limitCBPtr->entryPtr != NULL) {
+ Tcl_DeleteHashEntry(limitCBPtr->entryPtr);
+ }
+ ckfree((char *) limitCBPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CallScriptLimitCallback --
+ *
+ * Invoke a script limit callback. Used to implement limit callbacks set
+ * at the Tcl level on child interpreters.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depends on the callback script. Errors are reported as background
+ * errors.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CallScriptLimitCallback(
+ ClientData clientData,
+ Tcl_Interp *interp) /* Interpreter which failed the limit */
+{
+ ScriptLimitCallback *limitCBPtr = clientData;
+ int code;
+
+ if (Tcl_InterpDeleted(limitCBPtr->interp)) {
+ return;
+ }
+ Tcl_Preserve(limitCBPtr->interp);
+ code = Tcl_EvalObjEx(limitCBPtr->interp, limitCBPtr->scriptObj,
+ TCL_EVAL_GLOBAL);
+ if (code != TCL_OK && !Tcl_InterpDeleted(limitCBPtr->interp)) {
+ TclBackgroundException(limitCBPtr->interp, code);
+ }
+ Tcl_Release(limitCBPtr->interp);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetScriptLimitCallback --
+ *
+ * Install (or remove, if scriptObj is NULL) a limit callback script that
+ * is called when the target interpreter exceeds the type of limit
+ * specified. Each interpreter may only have one callback set on another
+ * interpreter through this mechanism (though as many interpreters may be
+ * limited as the programmer chooses overall).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A limit callback implemented as an invokation of a Tcl script in
+ * another interpreter is either installed or removed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SetScriptLimitCallback(
+ Tcl_Interp *interp,
+ int type,
+ Tcl_Interp *targetInterp,
+ Tcl_Obj *scriptObj)
+{
+ ScriptLimitCallback *limitCBPtr;
+ Tcl_HashEntry *hashPtr;
+ int isNew;
+ ScriptLimitCallbackKey key;
+ Interp *iPtr = (Interp *) interp;
+
+ if (interp == targetInterp) {
+ Tcl_Panic("installing limit callback to the limited interpreter");
+ }
+
+ key.interp = targetInterp;
+ key.type = type;
+
+ if (scriptObj == NULL) {
+ hashPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key);
+ if (hashPtr != NULL) {
+ Tcl_LimitRemoveHandler(targetInterp, type, CallScriptLimitCallback,
+ Tcl_GetHashValue(hashPtr));
+ }
+ return;
+ }
+
+ hashPtr = Tcl_CreateHashEntry(&iPtr->limit.callbacks, (char *) &key,
+ &isNew);
+ if (!isNew) {
+ limitCBPtr = Tcl_GetHashValue(hashPtr);
+ limitCBPtr->entryPtr = NULL;
+ Tcl_LimitRemoveHandler(targetInterp, type, CallScriptLimitCallback,
+ limitCBPtr);
+ }
+
+ limitCBPtr = (ScriptLimitCallback *) ckalloc(sizeof(ScriptLimitCallback));
+ limitCBPtr->interp = interp;
+ limitCBPtr->scriptObj = scriptObj;
+ limitCBPtr->entryPtr = hashPtr;
+ limitCBPtr->type = type;
+ Tcl_IncrRefCount(scriptObj);
+
+ Tcl_LimitAddHandler(targetInterp, type, CallScriptLimitCallback,
+ limitCBPtr, DeleteScriptLimitCallback);
+ Tcl_SetHashValue(hashPtr, limitCBPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclRemoveScriptLimitCallbacks --
+ *
+ * Remove all script-implemented limit callbacks that make calls back
+ * into the given interpreter. This invoked as part of deleting an
+ * interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The script limit callbacks are removed or marked for later removal.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclRemoveScriptLimitCallbacks(
+ Tcl_Interp *interp)
+{
+ Interp *iPtr = (Interp *) interp;
+ Tcl_HashEntry *hashPtr;
+ Tcl_HashSearch search;
+ ScriptLimitCallbackKey *keyPtr;
+
+ hashPtr = Tcl_FirstHashEntry(&iPtr->limit.callbacks, &search);
+ while (hashPtr != NULL) {
+ keyPtr = (ScriptLimitCallbackKey *)
+ Tcl_GetHashKey(&iPtr->limit.callbacks, hashPtr);
+ Tcl_LimitRemoveHandler(keyPtr->interp, keyPtr->type,
+ CallScriptLimitCallback, Tcl_GetHashValue(hashPtr));
+ hashPtr = Tcl_NextHashEntry(&search);
+ }
+ Tcl_DeleteHashTable(&iPtr->limit.callbacks);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclInitLimitSupport --
+ *
+ * Initialise all the parts of the interpreter relating to resource limit
+ * management. This allows an interpreter to both have limits set upon
+ * itself and set limits upon other interpreters.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The resource limit subsystem is initialised for the interpreter.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclInitLimitSupport(
+ Tcl_Interp *interp)
+{
+ Interp *iPtr = (Interp *) interp;
+
+ iPtr->limit.active = 0;
+ iPtr->limit.granularityTicker = 0;
+ iPtr->limit.exceeded = 0;
+ iPtr->limit.cmdCount = 0;
+ iPtr->limit.cmdHandlers = NULL;
+ iPtr->limit.cmdGranularity = 1;
+ memset(&iPtr->limit.time, 0, sizeof(Tcl_Time));
+ iPtr->limit.timeHandlers = NULL;
+ iPtr->limit.timeEvent = NULL;
+ iPtr->limit.timeGranularity = 10;
+ Tcl_InitHashTable(&iPtr->limit.callbacks,
+ sizeof(ScriptLimitCallbackKey)/sizeof(int));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InheritLimitsFromMaster --
+ *
+ * Derive the interpreter limit configuration for a slave interpreter
+ * from the limit config for the master.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The slave interpreter limits are set so that if the master has a
+ * limit, it may not exceed it by handing off work to slave interpreters.
+ * Note that this does not transfer limit callbacks from the master to
+ * the slave.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InheritLimitsFromMaster(
+ Tcl_Interp *slaveInterp,
+ Tcl_Interp *masterInterp)
+{
+ Interp *slavePtr = (Interp *) slaveInterp;
+ Interp *masterPtr = (Interp *) masterInterp;
+
+ if (masterPtr->limit.active & TCL_LIMIT_COMMANDS) {
+ slavePtr->limit.active |= TCL_LIMIT_COMMANDS;
+ slavePtr->limit.cmdCount = 0;
+ slavePtr->limit.cmdGranularity = masterPtr->limit.cmdGranularity;
+ }
+ if (masterPtr->limit.active & TCL_LIMIT_TIME) {
+ slavePtr->limit.active |= TCL_LIMIT_TIME;
+ memcpy(&slavePtr->limit.time, &masterPtr->limit.time,
+ sizeof(Tcl_Time));
+ slavePtr->limit.timeGranularity = masterPtr->limit.timeGranularity;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SlaveCommandLimitCmd --
+ *
+ * Implementation of the [interp limit $i commands] and [$i limit
+ * commands] subcommands. See the interp manual page for a full
+ * description.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Depends on the arguments.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SlaveCommandLimitCmd(
+ Tcl_Interp *interp, /* Current interpreter. */
+ Tcl_Interp *slaveInterp, /* Interpreter being adjusted. */
+ int consumedObjc, /* Number of args already parsed. */
+ int objc, /* Total number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ static const char *options[] = {
+ "-command", "-granularity", "-value", NULL
+ };
+ enum Options {
+ OPT_CMD, OPT_GRAN, OPT_VAL
+ };
+ Interp *iPtr = (Interp *) interp;
+ int index;
+ ScriptLimitCallbackKey key;
+ ScriptLimitCallback *limitCBPtr;
+ Tcl_HashEntry *hPtr;
+
+ if (objc == consumedObjc) {
+ Tcl_Obj *dictPtr;
+
+ TclNewObj(dictPtr);
+ key.interp = slaveInterp;
+ key.type = TCL_LIMIT_COMMANDS;
+ hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key);
+ if (hPtr != NULL) {
+ limitCBPtr = Tcl_GetHashValue(hPtr);
+ if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) {
+ Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[0], -1),
+ limitCBPtr->scriptObj);
+ } else {
+ goto putEmptyCommandInDict;
+ }
+ } else {
+ Tcl_Obj *empty;
+
+ putEmptyCommandInDict:
+ TclNewObj(empty);
+ Tcl_DictObjPut(NULL, dictPtr,
+ Tcl_NewStringObj(options[0], -1), empty);
+ }
+ Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[1], -1),
+ Tcl_NewIntObj(Tcl_LimitGetGranularity(slaveInterp,
+ TCL_LIMIT_COMMANDS)));
+
+ if (Tcl_LimitTypeEnabled(slaveInterp, TCL_LIMIT_COMMANDS)) {
+ Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[2], -1),
+ Tcl_NewIntObj(Tcl_LimitGetCommands(slaveInterp)));
+ } else {
+ Tcl_Obj *empty;
+
+ TclNewObj(empty);
+ Tcl_DictObjPut(NULL, dictPtr,
+ Tcl_NewStringObj(options[2], -1), empty);
+ }
+ Tcl_SetObjResult(interp, dictPtr);
+ return TCL_OK;
+ } else if (objc == consumedObjc+1) {
+ if (Tcl_GetIndexFromObj(interp, objv[consumedObjc], options, "option",
+ 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum Options) index) {
+ case OPT_CMD:
+ key.interp = slaveInterp;
+ key.type = TCL_LIMIT_COMMANDS;
+ hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key);
+ if (hPtr != NULL) {
+ limitCBPtr = Tcl_GetHashValue(hPtr);
+ if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) {
+ Tcl_SetObjResult(interp, limitCBPtr->scriptObj);
+ }
+ }
+ break;
+ case OPT_GRAN:
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(
+ Tcl_LimitGetGranularity(slaveInterp, TCL_LIMIT_COMMANDS)));
+ break;
+ case OPT_VAL:
+ if (Tcl_LimitTypeEnabled(slaveInterp, TCL_LIMIT_COMMANDS)) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewIntObj(Tcl_LimitGetCommands(slaveInterp)));
+ }
+ break;
+ }
+ return TCL_OK;
+ } else if ((objc-consumedObjc) & 1 /* isOdd(objc-consumedObjc) */) {
+ Tcl_WrongNumArgs(interp, consumedObjc, objv,
+ "?-option? ?value? ?-option value ...?");
+ return TCL_ERROR;
+ } else {
+ int i, scriptLen = 0, limitLen = 0;
+ Tcl_Obj *scriptObj = NULL, *granObj = NULL, *limitObj = NULL;
+ int gran = 0, limit = 0;
+
+ for (i=consumedObjc ; i<objc ; i+=2) {
+ if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum Options) index) {
+ case OPT_CMD:
+ scriptObj = objv[i+1];
+ (void) Tcl_GetStringFromObj(objv[i+1], &scriptLen);
+ break;
+ case OPT_GRAN:
+ granObj = objv[i+1];
+ if (TclGetIntFromObj(interp, objv[i+1], &gran) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (gran < 1) {
+ Tcl_AppendResult(interp, "granularity must be at "
+ "least 1", NULL);
+ return TCL_ERROR;
+ }
+ break;
+ case OPT_VAL:
+ limitObj = objv[i+1];
+ (void) Tcl_GetStringFromObj(objv[i+1], &limitLen);
+ if (limitLen == 0) {
+ break;
+ }
+ if (TclGetIntFromObj(interp, objv[i+1], &limit) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (limit < 0) {
+ Tcl_AppendResult(interp, "command limit value must be at "
+ "least 0", NULL);
+ return TCL_ERROR;
+ }
+ break;
+ }
+ }
+ if (scriptObj != NULL) {
+ SetScriptLimitCallback(interp, TCL_LIMIT_COMMANDS, slaveInterp,
+ (scriptLen > 0 ? scriptObj : NULL));
+ }
+ if (granObj != NULL) {
+ Tcl_LimitSetGranularity(slaveInterp, TCL_LIMIT_COMMANDS, gran);
+ }
+ if (limitObj != NULL) {
+ if (limitLen > 0) {
+ Tcl_LimitSetCommands(slaveInterp, limit);
+ Tcl_LimitTypeSet(slaveInterp, TCL_LIMIT_COMMANDS);
+ } else {
+ Tcl_LimitTypeReset(slaveInterp, TCL_LIMIT_COMMANDS);
+ }
+ }
+ return TCL_OK;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SlaveTimeLimitCmd --
+ *
+ * Implementation of the [interp limit $i time] and [$i limit time]
+ * subcommands. See the interp manual page for a full description.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Depends on the arguments.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SlaveTimeLimitCmd(
+ Tcl_Interp *interp, /* Current interpreter. */
+ Tcl_Interp *slaveInterp, /* Interpreter being adjusted. */
+ int consumedObjc, /* Number of args already parsed. */
+ int objc, /* Total number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ static const char *options[] = {
+ "-command", "-granularity", "-milliseconds", "-seconds", NULL
+ };
+ enum Options {
+ OPT_CMD, OPT_GRAN, OPT_MILLI, OPT_SEC
+ };
+ Interp *iPtr = (Interp *) interp;
+ int index;
+ ScriptLimitCallbackKey key;
+ ScriptLimitCallback *limitCBPtr;
+ Tcl_HashEntry *hPtr;
+
+ if (objc == consumedObjc) {
+ Tcl_Obj *dictPtr;
+
+ TclNewObj(dictPtr);
+ key.interp = slaveInterp;
+ key.type = TCL_LIMIT_TIME;
+ hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key);
+ if (hPtr != NULL) {
+ limitCBPtr = Tcl_GetHashValue(hPtr);
+ if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) {
+ Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[0], -1),
+ limitCBPtr->scriptObj);
+ } else {
+ goto putEmptyCommandInDict;
+ }
+ } else {
+ Tcl_Obj *empty;
+ putEmptyCommandInDict:
+ TclNewObj(empty);
+ Tcl_DictObjPut(NULL, dictPtr,
+ Tcl_NewStringObj(options[0], -1), empty);
+ }
+ Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[1], -1),
+ Tcl_NewIntObj(Tcl_LimitGetGranularity(slaveInterp,
+ TCL_LIMIT_TIME)));
+
+ if (Tcl_LimitTypeEnabled(slaveInterp, TCL_LIMIT_TIME)) {
+ Tcl_Time limitMoment;
+
+ Tcl_LimitGetTime(slaveInterp, &limitMoment);
+ Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[2], -1),
+ Tcl_NewLongObj(limitMoment.usec/1000));
+ Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[3], -1),
+ Tcl_NewLongObj(limitMoment.sec));
+ } else {
+ Tcl_Obj *empty;
+
+ TclNewObj(empty);
+ Tcl_DictObjPut(NULL, dictPtr,
+ Tcl_NewStringObj(options[2], -1), empty);
+ Tcl_DictObjPut(NULL, dictPtr,
+ Tcl_NewStringObj(options[3], -1), empty);
+ }
+ Tcl_SetObjResult(interp, dictPtr);
+ return TCL_OK;
+ } else if (objc == consumedObjc+1) {
+ if (Tcl_GetIndexFromObj(interp, objv[consumedObjc], options, "option",
+ 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum Options) index) {
+ case OPT_CMD:
+ key.interp = slaveInterp;
+ key.type = TCL_LIMIT_TIME;
+ hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key);
+ if (hPtr != NULL) {
+ limitCBPtr = Tcl_GetHashValue(hPtr);
+ if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) {
+ Tcl_SetObjResult(interp, limitCBPtr->scriptObj);
+ }
+ }
+ break;
+ case OPT_GRAN:
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(
+ Tcl_LimitGetGranularity(slaveInterp, TCL_LIMIT_TIME)));
+ break;
+ case OPT_MILLI:
+ if (Tcl_LimitTypeEnabled(slaveInterp, TCL_LIMIT_TIME)) {
+ Tcl_Time limitMoment;
+
+ Tcl_LimitGetTime(slaveInterp, &limitMoment);
+ Tcl_SetObjResult(interp,
+ Tcl_NewLongObj(limitMoment.usec/1000));
+ }
+ break;
+ case OPT_SEC:
+ if (Tcl_LimitTypeEnabled(slaveInterp, TCL_LIMIT_TIME)) {
+ Tcl_Time limitMoment;
+
+ Tcl_LimitGetTime(slaveInterp, &limitMoment);
+ Tcl_SetObjResult(interp, Tcl_NewLongObj(limitMoment.sec));
+ }
+ break;
+ }
+ return TCL_OK;
+ } else if ((objc-consumedObjc) & 1 /* isOdd(objc-consumedObjc) */) {
+ Tcl_WrongNumArgs(interp, consumedObjc, objv,
+ "?-option? ?value? ?-option value ...?");
+ return TCL_ERROR;
+ } else {
+ int i, scriptLen = 0, milliLen = 0, secLen = 0;
+ Tcl_Obj *scriptObj = NULL, *granObj = NULL;
+ Tcl_Obj *milliObj = NULL, *secObj = NULL;
+ int gran = 0;
+ Tcl_Time limitMoment;
+ int tmp;
+
+ Tcl_LimitGetTime(slaveInterp, &limitMoment);
+ for (i=consumedObjc ; i<objc ; i+=2) {
+ if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum Options) index) {
+ case OPT_CMD:
+ scriptObj = objv[i+1];
+ (void) Tcl_GetStringFromObj(objv[i+1], &scriptLen);
+ break;
+ case OPT_GRAN:
+ granObj = objv[i+1];
+ if (TclGetIntFromObj(interp, objv[i+1], &gran) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (gran < 1) {
+ Tcl_AppendResult(interp, "granularity must be at "
+ "least 1", NULL);
+ return TCL_ERROR;
+ }
+ break;
+ case OPT_MILLI:
+ milliObj = objv[i+1];
+ (void) Tcl_GetStringFromObj(objv[i+1], &milliLen);
+ if (milliLen == 0) {
+ break;
+ }
+ if (TclGetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (tmp < 0) {
+ Tcl_AppendResult(interp, "milliseconds must be at least 0",
+ NULL);
+ return TCL_ERROR;
+ }
+ limitMoment.usec = ((long)tmp)*1000;
+ break;
+ case OPT_SEC:
+ secObj = objv[i+1];
+ (void) Tcl_GetStringFromObj(objv[i+1], &secLen);
+ if (secLen == 0) {
+ break;
+ }
+ if (TclGetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (tmp < 0) {
+ Tcl_AppendResult(interp, "seconds must be at least 0",
+ NULL);
+ return TCL_ERROR;
+ }
+ limitMoment.sec = tmp;
+ break;
+ }
+ }
+ if (milliObj != NULL || secObj != NULL) {
+ if (milliObj != NULL) {
+ /*
+ * Setting -milliseconds but clearing -seconds, or resetting
+ * -milliseconds but not resetting -seconds? Bad voodoo!
+ */
+
+ if (secObj != NULL && secLen == 0 && milliLen > 0) {
+ Tcl_AppendResult(interp, "may only set -milliseconds "
+ "if -seconds is not also being reset", NULL);
+ return TCL_ERROR;
+ }
+ if (milliLen == 0 && (secObj == NULL || secLen > 0)) {
+ Tcl_AppendResult(interp, "may only reset -milliseconds "
+ "if -seconds is also being reset", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ if (milliLen > 0 || secLen > 0) {
+ /*
+ * Force usec to be in range [0..1000000), possibly
+ * incrementing sec in the process. This makes it much easier
+ * for people to write scripts that do small time increments.
+ */
+
+ limitMoment.sec += limitMoment.usec / 1000000;
+ limitMoment.usec %= 1000000;
+
+ Tcl_LimitSetTime(slaveInterp, &limitMoment);
+ Tcl_LimitTypeSet(slaveInterp, TCL_LIMIT_TIME);
+ } else {
+ Tcl_LimitTypeReset(slaveInterp, TCL_LIMIT_TIME);
+ }
+ }
+ if (scriptObj != NULL) {
+ SetScriptLimitCallback(interp, TCL_LIMIT_TIME, slaveInterp,
+ (scriptLen > 0 ? scriptObj : NULL));
+ }
+ if (granObj != NULL) {
+ Tcl_LimitSetGranularity(slaveInterp, TCL_LIMIT_TIME, gran);
+ }
+ return TCL_OK;
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclLink.c b/generic/tclLink.c
index 28b1786..f7911a4 100644
--- a/generic/tclLink.c
+++ b/generic/tclLink.c
@@ -1,102 +1,125 @@
-/*
+/*
* tclLink.c --
*
- * This file implements linked variables (a C variable that is
- * tied to a Tcl variable). The idea of linked variables was
- * first suggested by Andreas Stolcke and this implementation is
- * based heavily on a prototype implementation provided by
- * him.
+ * This file implements linked variables (a C variable that is tied to a
+ * Tcl variable). The idea of linked variables was first suggested by
+ * Andreas Stolcke and this implementation is based heavily on a
+ * prototype implementation provided by him.
*
* Copyright (c) 1993 The Regents of the University of California.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
/*
- * For each linked variable there is a data structure of the following
- * type, which describes the link and is the clientData for the trace
- * set on the Tcl variable.
+ * For each linked variable there is a data structure of the following type,
+ * which describes the link and is the clientData for the trace set on the Tcl
+ * variable.
*/
typedef struct Link {
Tcl_Interp *interp; /* Interpreter containing Tcl variable. */
- Tcl_Obj *varName; /* Name of variable (must be global). This
- * is needed during trace callbacks, since
- * the actual variable may be aliased at
- * that time via upvar. */
+ Tcl_Obj *varName; /* Name of variable (must be global). This is
+ * needed during trace callbacks, since the
+ * actual variable may be aliased at that time
+ * via upvar. */
char *addr; /* Location of C variable. */
int type; /* Type of link (TCL_LINK_INT, etc.). */
union {
+ char c;
+ unsigned char uc;
int i;
- double d;
+ unsigned int ui;
+ short s;
+ unsigned short us;
+ long l;
+ unsigned long ul;
Tcl_WideInt w;
- } lastValue; /* Last known value of C variable; used to
+ Tcl_WideUInt uw;
+ float f;
+ double d;
+ } lastValue; /* Last known value of C variable; used to
* avoid string conversions. */
- int flags; /* Miscellaneous one-bit values; see below
- * for definitions. */
+ int flags; /* Miscellaneous one-bit values; see below for
+ * definitions. */
} Link;
/*
* Definitions for flag bits:
* LINK_READ_ONLY - 1 means errors should be generated if Tcl
* script attempts to write variable.
- * LINK_BEING_UPDATED - 1 means that a call to Tcl_UpdateLinkedVar
- * is in progress for this variable, so
- * trace callbacks on the variable should
- * be ignored.
+ * LINK_BEING_UPDATED - 1 means that a call to Tcl_UpdateLinkedVar is
+ * in progress for this variable, so trace
+ * callbacks on the variable should be ignored.
*/
#define LINK_READ_ONLY 1
#define LINK_BEING_UPDATED 2
/*
- * Forward references to procedures defined later in this file:
+ * Forward references to functions defined later in this file:
+ */
+
+static char * LinkTraceProc(ClientData clientData,Tcl_Interp *interp,
+ CONST char *name1, CONST char *name2, int flags);
+static Tcl_Obj * ObjValue(Link *linkPtr);
+
+/*
+ * Convenience macro for accessing the value of the C variable pointed to by a
+ * link. Note that this macro produces something that may be regarded as an
+ * lvalue or rvalue; it may be assigned to as well as read. Also note that
+ * this macro assumes the name of the variable being accessed (linkPtr); this
+ * is not strictly a good thing, but it keeps the code much shorter and
+ * cleaner.
*/
-static char * LinkTraceProc _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, CONST char *name1,
- CONST char *name2, int flags));
-static Tcl_Obj * ObjValue _ANSI_ARGS_((Link *linkPtr));
+#define LinkedVar(type) (*(type *) linkPtr->addr)
/*
*----------------------------------------------------------------------
*
* Tcl_LinkVar --
*
- * Link a C variable to a Tcl variable so that changes to either
- * one causes the other to change.
+ * Link a C variable to a Tcl variable so that changes to either one
+ * causes the other to change.
*
* Results:
- * The return value is TCL_OK if everything went well or TCL_ERROR
- * if an error occurred (the interp's result is also set after
- * errors).
+ * The return value is TCL_OK if everything went well or TCL_ERROR if an
+ * error occurred (the interp's result is also set after errors).
*
* Side effects:
- * The value at *addr is linked to the Tcl variable "varName",
- * using "type" to convert between string values for Tcl and
- * binary values for *addr.
+ * The value at *addr is linked to the Tcl variable "varName", using
+ * "type" to convert between string values for Tcl and binary values for
+ * *addr.
*
*----------------------------------------------------------------------
*/
int
-Tcl_LinkVar(interp, varName, addr, type)
- Tcl_Interp *interp; /* Interpreter in which varName exists. */
- CONST char *varName; /* Name of a global variable in interp. */
- char *addr; /* Address of a C variable to be linked
- * to varName. */
- int type; /* Type of C variable: TCL_LINK_INT, etc.
- * Also may have TCL_LINK_READ_ONLY
- * OR'ed in. */
+Tcl_LinkVar(
+ Tcl_Interp *interp, /* Interpreter in which varName exists. */
+ CONST char *varName, /* Name of a global variable in interp. */
+ char *addr, /* Address of a C variable to be linked to
+ * varName. */
+ int type) /* Type of C variable: TCL_LINK_INT, etc. Also
+ * may have TCL_LINK_READ_ONLY OR'ed in. */
{
- Tcl_Obj *objPtr, *resPtr;
+ Tcl_Obj *objPtr;
Link *linkPtr;
int code;
+ linkPtr = (Link *) Tcl_VarTraceInfo(interp, varName, TCL_GLOBAL_ONLY,
+ LinkTraceProc, (ClientData) NULL);
+ if (linkPtr != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "variable '%s' is already linked", varName));
+ return TCL_ERROR;
+ }
+
linkPtr = (Link *) ckalloc(sizeof(Link));
linkPtr->interp = interp;
linkPtr->varName = Tcl_NewStringObj(varName, -1);
@@ -109,11 +132,8 @@ Tcl_LinkVar(interp, varName, addr, type)
linkPtr->flags = 0;
}
objPtr = ObjValue(linkPtr);
- Tcl_IncrRefCount(objPtr);
- resPtr = Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, objPtr,
- TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG);
- Tcl_DecrRefCount(objPtr);
- if (resPtr == NULL) {
+ if (Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, objPtr,
+ TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
Tcl_DecrRefCount(linkPtr->varName);
ckfree((char *) linkPtr);
return TCL_ERROR;
@@ -139,17 +159,17 @@ Tcl_LinkVar(interp, varName, addr, type)
* None.
*
* Side effects:
- * If "varName" was previously linked to a C variable, the link
- * is broken to make the variable independent. If there was no
- * previous link for "varName" then nothing happens.
+ * If "varName" was previously linked to a C variable, the link is broken
+ * to make the variable independent. If there was no previous link for
+ * "varName" then nothing happens.
*
*----------------------------------------------------------------------
*/
void
-Tcl_UnlinkVar(interp, varName)
- Tcl_Interp *interp; /* Interpreter containing variable to unlink. */
- CONST char *varName; /* Global variable in interp to unlink. */
+Tcl_UnlinkVar(
+ Tcl_Interp *interp, /* Interpreter containing variable to unlink */
+ CONST char *varName) /* Global variable in interp to unlink. */
{
Link *linkPtr;
@@ -170,28 +190,27 @@ Tcl_UnlinkVar(interp, varName)
*
* Tcl_UpdateLinkedVar --
*
- * This procedure is invoked after a linked variable has been
- * changed by C code. It updates the Tcl variable so that
- * traces on the variable will trigger.
+ * This function is invoked after a linked variable has been changed by C
+ * code. It updates the Tcl variable so that traces on the variable will
+ * trigger.
*
* Results:
* None.
*
* Side effects:
- * The Tcl variable "varName" is updated from its C value,
- * causing traces on the variable to trigger.
+ * The Tcl variable "varName" is updated from its C value, causing traces
+ * on the variable to trigger.
*
*----------------------------------------------------------------------
*/
void
-Tcl_UpdateLinkedVar(interp, varName)
- Tcl_Interp *interp; /* Interpreter containing variable. */
- CONST char *varName; /* Name of global variable that is linked. */
+Tcl_UpdateLinkedVar(
+ Tcl_Interp *interp, /* Interpreter containing variable. */
+ CONST char *varName) /* Name of global variable that is linked. */
{
Link *linkPtr;
int savedFlag;
- Tcl_Obj *objPtr;
linkPtr = (Link *) Tcl_VarTraceInfo(interp, varName, TCL_GLOBAL_ONLY,
LinkTraceProc, (ClientData) NULL);
@@ -200,10 +219,8 @@ Tcl_UpdateLinkedVar(interp, varName)
}
savedFlag = linkPtr->flags & LINK_BEING_UPDATED;
linkPtr->flags |= LINK_BEING_UPDATED;
- objPtr = ObjValue(linkPtr);
- Tcl_IncrRefCount(objPtr);
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, objPtr, TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(objPtr);
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
/*
* Callback may have unlinked the variable. [Bug 1740631]
*/
@@ -219,39 +236,42 @@ Tcl_UpdateLinkedVar(interp, varName)
*
* LinkTraceProc --
*
- * This procedure is invoked when a linked Tcl variable is read,
- * written, or unset from Tcl. It's responsible for keeping the
- * C variable in sync with the Tcl variable.
+ * This function is invoked when a linked Tcl variable is read, written,
+ * or unset from Tcl. It's responsible for keeping the C variable in sync
+ * with the Tcl variable.
*
* Results:
- * If all goes well, NULL is returned; otherwise an error message
- * is returned.
+ * If all goes well, NULL is returned; otherwise an error message is
+ * returned.
*
* Side effects:
- * The C variable may be updated to make it consistent with the
- * Tcl variable, or the Tcl variable may be overwritten to reject
- * a modification.
+ * The C variable may be updated to make it consistent with the Tcl
+ * variable, or the Tcl variable may be overwritten to reject a
+ * modification.
*
*----------------------------------------------------------------------
*/
static char *
-LinkTraceProc(clientData, interp, name1, name2, flags)
- ClientData clientData; /* Contains information about the link. */
- Tcl_Interp *interp; /* Interpreter containing Tcl variable. */
- CONST char *name1; /* First part of variable name. */
- CONST char *name2; /* Second part of variable name. */
- int flags; /* Miscellaneous additional information. */
+LinkTraceProc(
+ ClientData clientData, /* Contains information about the link. */
+ Tcl_Interp *interp, /* Interpreter containing Tcl variable. */
+ CONST char *name1, /* First part of variable name. */
+ CONST char *name2, /* Second part of variable name. */
+ int flags) /* Miscellaneous additional information. */
{
Link *linkPtr = (Link *) clientData;
int changed, valueLength;
CONST char *value;
- char **pp, *result;
- Tcl_Obj *objPtr, *valueObj, *tmpPtr;
+ char **pp;
+ Tcl_Obj *valueObj;
+ int valueInt;
+ Tcl_WideInt valueWide;
+ double valueDouble;
/*
- * If the variable is being unset, then just re-create it (with a
- * trace) unless the whole interpreter is going away.
+ * If the variable is being unset, then just re-create it (with a trace)
+ * unless the whole interpreter is going away.
*/
if (flags & TCL_TRACE_UNSETS) {
@@ -259,11 +279,8 @@ LinkTraceProc(clientData, interp, name1, name2, flags)
Tcl_DecrRefCount(linkPtr->varName);
ckfree((char *) linkPtr);
} else if (flags & TCL_TRACE_DESTROYED) {
- tmpPtr = ObjValue(linkPtr);
- Tcl_IncrRefCount(tmpPtr);
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, tmpPtr,
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(tmpPtr);
Tcl_TraceVar(interp, Tcl_GetString(linkPtr->varName),
TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES
|TCL_TRACE_UNSETS, LinkTraceProc, (ClientData) linkPtr);
@@ -272,10 +289,9 @@ LinkTraceProc(clientData, interp, name1, name2, flags)
}
/*
- * If we were invoked because of a call to Tcl_UpdateLinkedVar, then
- * don't do anything at all. In particular, we don't want to get
- * upset that the variable is being modified, even if it is
- * supposed to be read-only.
+ * If we were invoked because of a call to Tcl_UpdateLinkedVar, then don't
+ * do anything at all. In particular, we don't want to get upset that the
+ * variable is being modified, even if it is supposed to be read-only.
*/
if (linkPtr->flags & LINK_BEING_UPDATED) {
@@ -283,21 +299,48 @@ LinkTraceProc(clientData, interp, name1, name2, flags)
}
/*
- * For read accesses, update the Tcl variable if the C variable
- * has changed since the last time we updated the Tcl variable.
+ * For read accesses, update the Tcl variable if the C variable has
+ * changed since the last time we updated the Tcl variable.
*/
if (flags & TCL_TRACE_READS) {
switch (linkPtr->type) {
case TCL_LINK_INT:
case TCL_LINK_BOOLEAN:
- changed = *(int *)(linkPtr->addr) != linkPtr->lastValue.i;
+ changed = (LinkedVar(int) != linkPtr->lastValue.i);
break;
case TCL_LINK_DOUBLE:
- changed = *(double *)(linkPtr->addr) != linkPtr->lastValue.d;
+ changed = (LinkedVar(double) != linkPtr->lastValue.d);
break;
case TCL_LINK_WIDE_INT:
- changed = *(Tcl_WideInt *)(linkPtr->addr) != linkPtr->lastValue.w;
+ changed = (LinkedVar(Tcl_WideInt) != linkPtr->lastValue.w);
+ break;
+ case TCL_LINK_WIDE_UINT:
+ changed = (LinkedVar(Tcl_WideUInt) != linkPtr->lastValue.uw);
+ break;
+ case TCL_LINK_CHAR:
+ changed = (LinkedVar(char) != linkPtr->lastValue.c);
+ break;
+ case TCL_LINK_UCHAR:
+ changed = (LinkedVar(unsigned char) != linkPtr->lastValue.uc);
+ break;
+ case TCL_LINK_SHORT:
+ changed = (LinkedVar(short) != linkPtr->lastValue.s);
+ break;
+ case TCL_LINK_USHORT:
+ changed = (LinkedVar(unsigned short) != linkPtr->lastValue.us);
+ break;
+ case TCL_LINK_UINT:
+ changed = (LinkedVar(unsigned int) != linkPtr->lastValue.ui);
+ break;
+ case TCL_LINK_LONG:
+ changed = (LinkedVar(long) != linkPtr->lastValue.l);
+ break;
+ case TCL_LINK_ULONG:
+ changed = (LinkedVar(unsigned long) != linkPtr->lastValue.ul);
+ break;
+ case TCL_LINK_FLOAT:
+ changed = (LinkedVar(float) != linkPtr->lastValue.f);
break;
case TCL_LINK_STRING:
changed = 1;
@@ -306,30 +349,24 @@ LinkTraceProc(clientData, interp, name1, name2, flags)
return "internal error: bad linked variable type";
}
if (changed) {
- tmpPtr = ObjValue(linkPtr);
- Tcl_IncrRefCount(tmpPtr);
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, tmpPtr,
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(tmpPtr);
}
return NULL;
}
/*
- * For writes, first make sure that the variable is writable. Then
- * convert the Tcl value to C if possible. If the variable isn't
- * writable or can't be converted, then restore the varaible's old
- * value and return an error. Another tricky thing: we have to save
- * and restore the interpreter's result, since the variable access
- * could occur when the result has been partially set.
+ * For writes, first make sure that the variable is writable. Then convert
+ * the Tcl value to C if possible. If the variable isn't writable or can't
+ * be converted, then restore the varaible's old value and return an
+ * error. Another tricky thing: we have to save and restore the interp's
+ * result, since the variable access could occur when the result has been
+ * partially set.
*/
if (linkPtr->flags & LINK_READ_ONLY) {
- tmpPtr = ObjValue(linkPtr);
- Tcl_IncrRefCount(tmpPtr);
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, tmpPtr,
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(tmpPtr);
return "linked variable is read-only";
}
valueObj = Tcl_ObjGetVar2(interp, linkPtr->varName,NULL, TCL_GLOBAL_ONLY);
@@ -337,92 +374,172 @@ LinkTraceProc(clientData, interp, name1, name2, flags)
/*
* This shouldn't ever happen.
*/
+
return "internal error: linked variable couldn't be read";
}
- objPtr = Tcl_GetObjResult(interp);
- Tcl_IncrRefCount(objPtr);
- Tcl_ResetResult(interp);
- result = NULL;
-
switch (linkPtr->type) {
case TCL_LINK_INT:
- if (Tcl_GetIntFromObj(interp, valueObj, &linkPtr->lastValue.i)
+ if (Tcl_GetIntFromObj(NULL, valueObj, &linkPtr->lastValue.i)
!= TCL_OK) {
- Tcl_SetObjResult(interp, objPtr);
- tmpPtr = ObjValue(linkPtr);
- Tcl_IncrRefCount(tmpPtr);
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, tmpPtr,
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(tmpPtr);
- result = "variable must have integer value";
- goto end;
+ return "variable must have integer value";
}
- *(int *)(linkPtr->addr) = linkPtr->lastValue.i;
+ LinkedVar(int) = linkPtr->lastValue.i;
break;
case TCL_LINK_WIDE_INT:
- if (Tcl_GetWideIntFromObj(interp, valueObj, &linkPtr->lastValue.w)
+ if (Tcl_GetWideIntFromObj(NULL, valueObj, &linkPtr->lastValue.w)
!= TCL_OK) {
- Tcl_SetObjResult(interp, objPtr);
- tmpPtr = ObjValue(linkPtr);
- Tcl_IncrRefCount(tmpPtr);
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, tmpPtr,
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(tmpPtr);
- result = "variable must have integer value";
- goto end;
+ return "variable must have integer value";
}
- *(Tcl_WideInt *)(linkPtr->addr) = linkPtr->lastValue.w;
+ LinkedVar(Tcl_WideInt) = linkPtr->lastValue.w;
break;
case TCL_LINK_DOUBLE:
- if (Tcl_GetDoubleFromObj(interp, valueObj, &linkPtr->lastValue.d)
+ if (Tcl_GetDoubleFromObj(NULL, valueObj, &linkPtr->lastValue.d)
!= TCL_OK) {
- Tcl_SetObjResult(interp, objPtr);
- tmpPtr = ObjValue(linkPtr);
- Tcl_IncrRefCount(tmpPtr);
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, tmpPtr,
- TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(tmpPtr);
- result = "variable must have real value";
- goto end;
+#ifdef ACCEPT_NAN
+ if (valueObj->typePtr != &tclDoubleType) {
+#endif
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
+ ObjValue(linkPtr), TCL_GLOBAL_ONLY);
+ return "variable must have real value";
+#ifdef ACCEPT_NAN
+ }
+ linkPtr->lastValue.d = valueObj->internalRep.doubleValue;
+#endif
}
- *(double *)(linkPtr->addr) = linkPtr->lastValue.d;
+ LinkedVar(double) = linkPtr->lastValue.d;
break;
case TCL_LINK_BOOLEAN:
- if (Tcl_GetBooleanFromObj(interp, valueObj, &linkPtr->lastValue.i)
- != TCL_OK) {
- Tcl_SetObjResult(interp, objPtr);
- tmpPtr = ObjValue(linkPtr);
- Tcl_IncrRefCount(tmpPtr);
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, tmpPtr,
+ if (Tcl_GetBooleanFromObj(NULL, valueObj, &linkPtr->lastValue.i)
+ != TCL_OK) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have boolean value";
+ }
+ LinkedVar(int) = linkPtr->lastValue.i;
+ break;
+
+ case TCL_LINK_CHAR:
+ if (Tcl_GetIntFromObj(interp, valueObj, &valueInt) != TCL_OK
+ || valueInt < SCHAR_MIN || valueInt > SCHAR_MAX) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have char value";
+ }
+ linkPtr->lastValue.c = (char)valueInt;
+ LinkedVar(char) = linkPtr->lastValue.c;
+ break;
+
+ case TCL_LINK_UCHAR:
+ if (Tcl_GetIntFromObj(interp, valueObj, &valueInt) != TCL_OK
+ || valueInt < 0 || valueInt > UCHAR_MAX) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(tmpPtr);
- result = "variable must have boolean value";
- goto end;
+ return "variable must have unsigned char value";
}
- *(int *)(linkPtr->addr) = linkPtr->lastValue.i;
+ linkPtr->lastValue.uc = (unsigned char) valueInt;
+ LinkedVar(unsigned char) = linkPtr->lastValue.uc;
+ break;
+
+ case TCL_LINK_SHORT:
+ if (Tcl_GetIntFromObj(interp, valueObj, &valueInt) != TCL_OK
+ || valueInt < SHRT_MIN || valueInt > SHRT_MAX) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have short value";
+ }
+ linkPtr->lastValue.s = (short)valueInt;
+ LinkedVar(short) = linkPtr->lastValue.s;
+ break;
+
+ case TCL_LINK_USHORT:
+ if (Tcl_GetIntFromObj(interp, valueObj, &valueInt) != TCL_OK
+ || valueInt < 0 || valueInt > USHRT_MAX) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have unsigned short value";
+ }
+ linkPtr->lastValue.us = (unsigned short)valueInt;
+ LinkedVar(unsigned short) = linkPtr->lastValue.us;
+ break;
+
+ case TCL_LINK_UINT:
+ if (Tcl_GetWideIntFromObj(interp, valueObj, &valueWide) != TCL_OK
+ || valueWide < 0 || valueWide > UINT_MAX) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have unsigned int value";
+ }
+ linkPtr->lastValue.ui = (unsigned int)valueWide;
+ LinkedVar(unsigned int) = linkPtr->lastValue.ui;
+ break;
+
+ case TCL_LINK_LONG:
+ if (Tcl_GetWideIntFromObj(interp, valueObj, &valueWide) != TCL_OK
+ || valueWide < LONG_MIN || valueWide > LONG_MAX) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have long value";
+ }
+ linkPtr->lastValue.l = (long)valueWide;
+ LinkedVar(long) = linkPtr->lastValue.l;
+ break;
+
+ case TCL_LINK_ULONG:
+ if (Tcl_GetWideIntFromObj(interp, valueObj, &valueWide) != TCL_OK
+ || valueWide < 0 || (Tcl_WideUInt) valueWide > ULONG_MAX) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have unsigned long value";
+ }
+ linkPtr->lastValue.ul = (unsigned long)valueWide;
+ LinkedVar(unsigned long) = linkPtr->lastValue.ul;
+ break;
+
+ case TCL_LINK_WIDE_UINT:
+ /*
+ * FIXME: represent as a bignum.
+ */
+ if (Tcl_GetWideIntFromObj(interp, valueObj, &valueWide) != TCL_OK) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have unsigned wide int value";
+ }
+ linkPtr->lastValue.uw = (Tcl_WideUInt)valueWide;
+ LinkedVar(Tcl_WideUInt) = linkPtr->lastValue.uw;
+ break;
+
+ case TCL_LINK_FLOAT:
+ if (Tcl_GetDoubleFromObj(interp, valueObj, &valueDouble) != TCL_OK
+ || valueDouble < -FLT_MAX || valueDouble > FLT_MAX) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have float value";
+ }
+ linkPtr->lastValue.f = (float)valueDouble;
+ LinkedVar(float) = linkPtr->lastValue.f;
break;
case TCL_LINK_STRING:
value = Tcl_GetStringFromObj(valueObj, &valueLength);
valueLength++;
- pp = (char **)(linkPtr->addr);
- if (*pp != NULL) {
- ckfree(*pp);
- }
- *pp = (char *) ckalloc((unsigned) valueLength);
+ pp = (char **) linkPtr->addr;
+
+ *pp = ckrealloc(*pp, valueLength);
memcpy(*pp, value, (unsigned) valueLength);
break;
default:
return "internal error: bad linked variable type";
}
- end:
- Tcl_DecrRefCount(objPtr);
- return result;
+ return NULL;
}
/*
@@ -430,12 +547,12 @@ LinkTraceProc(clientData, interp, name1, name2, flags)
*
* ObjValue --
*
- * Converts the value of a C variable to a Tcl_Obj* for use in a
- * Tcl variable to which it is linked.
+ * Converts the value of a C variable to a Tcl_Obj* for use in a Tcl
+ * variable to which it is linked.
*
* Results:
- * The return value is a pointer to a Tcl_Obj that represents
- * the value of the C variable given by linkPtr.
+ * The return value is a pointer to a Tcl_Obj that represents the value
+ * of the C variable given by linkPtr.
*
* Side effects:
* None.
@@ -444,36 +561,78 @@ LinkTraceProc(clientData, interp, name1, name2, flags)
*/
static Tcl_Obj *
-ObjValue(linkPtr)
- Link *linkPtr; /* Structure describing linked variable. */
+ObjValue(
+ Link *linkPtr) /* Structure describing linked variable. */
{
char *p;
+ Tcl_Obj *resultObj;
switch (linkPtr->type) {
case TCL_LINK_INT:
- linkPtr->lastValue.i = *(int *)(linkPtr->addr);
+ linkPtr->lastValue.i = LinkedVar(int);
return Tcl_NewIntObj(linkPtr->lastValue.i);
case TCL_LINK_WIDE_INT:
- linkPtr->lastValue.w = *(Tcl_WideInt *)(linkPtr->addr);
+ linkPtr->lastValue.w = LinkedVar(Tcl_WideInt);
return Tcl_NewWideIntObj(linkPtr->lastValue.w);
case TCL_LINK_DOUBLE:
- linkPtr->lastValue.d = *(double *)(linkPtr->addr);
+ linkPtr->lastValue.d = LinkedVar(double);
return Tcl_NewDoubleObj(linkPtr->lastValue.d);
case TCL_LINK_BOOLEAN:
- linkPtr->lastValue.i = *(int *)(linkPtr->addr);
+ linkPtr->lastValue.i = LinkedVar(int);
return Tcl_NewBooleanObj(linkPtr->lastValue.i != 0);
+ case TCL_LINK_CHAR:
+ linkPtr->lastValue.c = LinkedVar(char);
+ return Tcl_NewIntObj(linkPtr->lastValue.c);
+ case TCL_LINK_UCHAR:
+ linkPtr->lastValue.uc = LinkedVar(unsigned char);
+ return Tcl_NewIntObj(linkPtr->lastValue.uc);
+ case TCL_LINK_SHORT:
+ linkPtr->lastValue.s = LinkedVar(short);
+ return Tcl_NewIntObj(linkPtr->lastValue.s);
+ case TCL_LINK_USHORT:
+ linkPtr->lastValue.us = LinkedVar(unsigned short);
+ return Tcl_NewIntObj(linkPtr->lastValue.us);
+ case TCL_LINK_UINT:
+ linkPtr->lastValue.ui = LinkedVar(unsigned int);
+ return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.ui);
+ case TCL_LINK_LONG:
+ linkPtr->lastValue.l = LinkedVar(long);
+ return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.l);
+ case TCL_LINK_ULONG:
+ linkPtr->lastValue.ul = LinkedVar(unsigned long);
+ return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.ul);
+ case TCL_LINK_FLOAT:
+ linkPtr->lastValue.f = LinkedVar(float);
+ return Tcl_NewDoubleObj(linkPtr->lastValue.f);
+ case TCL_LINK_WIDE_UINT:
+ linkPtr->lastValue.uw = LinkedVar(Tcl_WideUInt);
+ /*
+ * FIXME: represent as a bignum.
+ */
+ return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.uw);
case TCL_LINK_STRING:
- p = *(char **)(linkPtr->addr);
+ p = LinkedVar(char *);
if (p == NULL) {
- return Tcl_NewStringObj("NULL", 4);
+ TclNewLiteralStringObj(resultObj, "NULL");
+ return resultObj;
}
return Tcl_NewStringObj(p, -1);
/*
- * This code only gets executed if the link type is unknown
- * (shouldn't ever happen).
+ * This code only gets executed if the link type is unknown (shouldn't
+ * ever happen).
*/
+
default:
- return Tcl_NewStringObj("??", 2);
+ TclNewLiteralStringObj(resultObj, "??");
+ return resultObj;
}
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclListObj.c b/generic/tclListObj.c
index fffe6a2..17aa256 100644
--- a/generic/tclListObj.c
+++ b/generic/tclListObj.c
@@ -1,70 +1,193 @@
-/*
+/*
* tclListObj.c --
*
- * This file contains procedures that implement the Tcl list object
- * type.
+ * This file contains functions that implement the Tcl list object type.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright (c) 1998 by Scriptics Corporation.
* Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
/*
- * Prototypes for procedures defined later in this file:
+ * Prototypes for functions defined later in this file:
*/
-static void DupListInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
- Tcl_Obj *copyPtr));
-static void FreeListInternalRep _ANSI_ARGS_((Tcl_Obj *listPtr));
-static int SetListFromAny _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
-static void UpdateStringOfList _ANSI_ARGS_((Tcl_Obj *listPtr));
+static List * AttemptNewList(Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]);
+static List * NewListIntRep(int objc, Tcl_Obj *CONST objv[], int p);
+static void DupListInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
+static void FreeListInternalRep(Tcl_Obj *listPtr);
+static int SetListFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
+static void UpdateStringOfList(Tcl_Obj *listPtr);
/*
- * The structure below defines the list Tcl object type by means of
- * procedures that can be invoked by generic object code.
+ * The structure below defines the list Tcl object type by means of functions
+ * that can be invoked by generic object code.
*
* The internal representation of a list object is a two-pointer
- * representation. The first pointer designates a List structure that
- * contains an array of pointers to the element objects, together with
- * integers that represent the current element count and the allocated
- * size of the array. The second pointer is normally NULL; during
- * execution of functions in this file that operate on nested sublists,
- * it is occasionally used as working storage to avoid an auxiliary
- * stack.
+ * representation. The first pointer designates a List structure that contains
+ * an array of pointers to the element objects, together with integers that
+ * represent the current element count and the allocated size of the array.
+ * The second pointer is normally NULL; during execution of functions in this
+ * file that operate on nested sublists, it is occasionally used as working
+ * storage to avoid an auxiliary stack.
*/
Tcl_ObjType tclListType = {
- "list", /* name */
- FreeListInternalRep, /* freeIntRepProc */
- DupListInternalRep, /* dupIntRepProc */
- UpdateStringOfList, /* updateStringProc */
- SetListFromAny /* setFromAnyProc */
+ "list", /* name */
+ FreeListInternalRep, /* freeIntRepProc */
+ DupListInternalRep, /* dupIntRepProc */
+ UpdateStringOfList, /* updateStringProc */
+ SetListFromAny /* setFromAnyProc */
};
/*
*----------------------------------------------------------------------
*
+ * NewListIntRep --
+ *
+ * Creates a list internal rep with space for objc elements. objc
+ * must be > 0. If objv!=NULL, initializes with the first objc values
+ * in that array. If objv==NULL, initalize list internal rep to have
+ * 0 elements, with space to add objc more. Flag value "p" indicates
+ * how to behave on failure.
+ *
+ * Results:
+ * A new List struct with refCount 0 is returned. If some failure
+ * prevents this then if p=0, NULL is returned and otherwise the
+ * routine panics.
+ *
+ * Side effects:
+ * The ref counts of the elements in objv are incremented since the
+ * resulting list now refers to them.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static List *
+NewListIntRep(
+ int objc,
+ Tcl_Obj *CONST objv[],
+ int p)
+{
+ List *listRepPtr;
+
+ if (objc <= 0) {
+ Tcl_Panic("NewListIntRep: expects postive element count");
+ }
+
+ /*
+ * First check to see if we'd overflow and try to allocate an object
+ * larger than our memory allocator allows. Note that this is actually a
+ * fairly small value when you're on a serious 64-bit machine, but that
+ * requires API changes to fix. See [Bug 219196] for a discussion.
+ */
+
+ if ((size_t)objc > LIST_MAX) {
+ if (p) {
+ Tcl_Panic("max length of a Tcl list (%d elements) exceeded",
+ LIST_MAX);
+ }
+ return NULL;
+ }
+
+ listRepPtr = (List *)
+ attemptckalloc(sizeof(List) + ((objc-1) * sizeof(Tcl_Obj *)));
+ if (listRepPtr == NULL) {
+ if (p) {
+ Tcl_Panic("list creation failed: unable to alloc %u bytes",
+ (unsigned)(sizeof(List) + ((objc-1) * sizeof(Tcl_Obj *))));
+ }
+ return NULL;
+ }
+
+ listRepPtr->canonicalFlag = 0;
+ listRepPtr->refCount = 0;
+ listRepPtr->maxElemCount = objc;
+
+ if (objv) {
+ Tcl_Obj **elemPtrs;
+ int i;
+
+ listRepPtr->elemCount = objc;
+ elemPtrs = &listRepPtr->elements;
+ for (i = 0; i < objc; i++) {
+ elemPtrs[i] = objv[i];
+ Tcl_IncrRefCount(elemPtrs[i]);
+ }
+ } else {
+ listRepPtr->elemCount = 0;
+ }
+ return listRepPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AttemptNewList --
+ *
+ * Creates a list internal rep with space for objc elements. objc
+ * must be > 0. If objv!=NULL, initializes with the first objc values
+ * in that array. If objv==NULL, initalize list internal rep to have
+ * 0 elements, with space to add objc more.
+ *
+ * Results:
+ * A new List struct with refCount 0 is returned. If some failure
+ * prevents this then NULL is returned, and an error message is left
+ * in the interp result, unless interp is NULL.
+ *
+ * Side effects:
+ * The ref counts of the elements in objv are incremented since the
+ * resulting list now refers to them.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static List *
+AttemptNewList(
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[])
+{
+ List *listRepPtr = NewListIntRep(objc, objv, 0);
+
+ if (interp != NULL && listRepPtr == NULL) {
+ if (objc > LIST_MAX) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "max length of a Tcl list (%d elements) exceeded",
+ LIST_MAX));
+ } else {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "list creation failed: unable to alloc %u bytes",
+ (unsigned)(sizeof(List) + ((objc-1) * sizeof(Tcl_Obj *)))));
+ }
+ }
+ return listRepPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tcl_NewListObj --
*
- * This procedure is normally called when not debugging: i.e., when
+ * This function is normally called when not debugging: i.e., when
* TCL_MEM_DEBUG is not defined. It creates a new list object from an
* (objc,objv) array: that is, each of the objc elements of the array
* referenced by objv is inserted as an element into a new Tcl object.
*
- * When TCL_MEM_DEBUG is defined, this procedure just returns the
- * result of calling the debugging version Tcl_DbNewListObj.
+ * When TCL_MEM_DEBUG is defined, this function just returns the result
+ * of calling the debugging version Tcl_DbNewListObj.
*
* Results:
* A new list object is returned that is initialized from the object
* pointers in objv. If objc is less than or equal to zero, an empty
- * object is returned. The new object's string representation
- * is left NULL. The resulting new list object has ref count 0.
+ * object is returned. The new object's string representation is left
+ * NULL. The resulting new list object has ref count 0.
*
* Side effects:
* The ref counts of the elements in objv are incremented since the
@@ -77,9 +200,9 @@ Tcl_ObjType tclListType = {
#undef Tcl_NewListObj
Tcl_Obj *
-Tcl_NewListObj(objc, objv)
- int objc; /* Count of objects referenced by objv. */
- Tcl_Obj *CONST objv[]; /* An array of pointers to Tcl objects. */
+Tcl_NewListObj(
+ int objc, /* Count of objects referenced by objv. */
+ Tcl_Obj *CONST objv[]) /* An array of pointers to Tcl objects. */
{
return Tcl_DbNewListObj(objc, objv, "unknown", 0);
}
@@ -87,36 +210,31 @@ Tcl_NewListObj(objc, objv)
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
-Tcl_NewListObj(objc, objv)
- int objc; /* Count of objects referenced by objv. */
- Tcl_Obj *CONST objv[]; /* An array of pointers to Tcl objects. */
+Tcl_NewListObj(
+ int objc, /* Count of objects referenced by objv. */
+ Tcl_Obj *CONST objv[]) /* An array of pointers to Tcl objects. */
{
- register Tcl_Obj *listPtr;
- register Tcl_Obj **elemPtrs;
- register List *listRepPtr;
- int i;
-
+ List *listRepPtr;
+ Tcl_Obj *listPtr;
+
TclNewObj(listPtr);
-
- if (objc > 0) {
- Tcl_InvalidateStringRep(listPtr);
-
- elemPtrs = (Tcl_Obj **)
- ckalloc((unsigned) (objc * sizeof(Tcl_Obj *)));
- for (i = 0; i < objc; i++) {
- elemPtrs[i] = objv[i];
- Tcl_IncrRefCount(elemPtrs[i]);
- }
-
- listRepPtr = (List *) ckalloc(sizeof(List));
- listRepPtr->maxElemCount = objc;
- listRepPtr->elemCount = objc;
- listRepPtr->elements = elemPtrs;
-
- listPtr->internalRep.twoPtrValue.ptr1 = (VOID *) listRepPtr;
- listPtr->internalRep.twoPtrValue.ptr2 = NULL;
- listPtr->typePtr = &tclListType;
+
+ if (objc <= 0) {
+ return listPtr;
}
+
+ /*
+ * Create the internal rep.
+ */
+
+ listRepPtr = NewListIntRep(objc, objv, 1);
+
+ /*
+ * Now create the object.
+ */
+
+ Tcl_InvalidateStringRep(listPtr);
+ ListSetIntRep(listPtr, listRepPtr);
return listPtr;
}
#endif /* if TCL_MEM_DEBUG */
@@ -126,22 +244,22 @@ Tcl_NewListObj(objc, objv)
*
* Tcl_DbNewListObj --
*
- * This procedure is normally called when debugging: i.e., when
- * TCL_MEM_DEBUG is defined. It creates new list objects. It is the
- * same as the Tcl_NewListObj procedure above except that it calls
+ * This function is normally called when debugging: i.e., when
+ * TCL_MEM_DEBUG is defined. It creates new list objects. It is the same
+ * as the Tcl_NewListObj function above except that it calls
* Tcl_DbCkalloc directly with the file name and line number from its
* caller. This simplifies debugging since then the [memory active]
- * command will report the correct file name and line number when
+ * command will report the correct file name and line number when
* reporting objects that haven't been freed.
*
- * When TCL_MEM_DEBUG is not defined, this procedure just returns the
+ * When TCL_MEM_DEBUG is not defined, this function just returns the
* result of calling Tcl_NewListObj.
*
* Results:
* A new list object is returned that is initialized from the object
* pointers in objv. If objc is less than or equal to zero, an empty
- * object is returned. The new object's string representation
- * is left NULL. The new list object has ref count 0.
+ * object is returned. The new object's string representation is left
+ * NULL. The new list object has ref count 0.
*
* Side effects:
* The ref counts of the elements in objv are incremented since the
@@ -153,53 +271,49 @@ Tcl_NewListObj(objc, objv)
#ifdef TCL_MEM_DEBUG
Tcl_Obj *
-Tcl_DbNewListObj(objc, objv, file, line)
- int objc; /* Count of objects referenced by objv. */
- Tcl_Obj *CONST objv[]; /* An array of pointers to Tcl objects. */
- CONST char *file; /* The name of the source file calling this
- * procedure; used for debugging. */
- int line; /* Line number in the source file; used
- * for debugging. */
+Tcl_DbNewListObj(
+ int objc, /* Count of objects referenced by objv. */
+ Tcl_Obj *CONST objv[], /* An array of pointers to Tcl objects. */
+ CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
- register Tcl_Obj *listPtr;
- register Tcl_Obj **elemPtrs;
- register List *listRepPtr;
- int i;
-
+ Tcl_Obj *listPtr;
+ List *listRepPtr;
+
TclDbNewObj(listPtr, file, line);
-
- if (objc > 0) {
- Tcl_InvalidateStringRep(listPtr);
-
- elemPtrs = (Tcl_Obj **)
- ckalloc((unsigned) (objc * sizeof(Tcl_Obj *)));
- for (i = 0; i < objc; i++) {
- elemPtrs[i] = objv[i];
- Tcl_IncrRefCount(elemPtrs[i]);
- }
-
- listRepPtr = (List *) ckalloc(sizeof(List));
- listRepPtr->maxElemCount = objc;
- listRepPtr->elemCount = objc;
- listRepPtr->elements = elemPtrs;
-
- listPtr->internalRep.twoPtrValue.ptr1 = (VOID *) listRepPtr;
- listPtr->internalRep.twoPtrValue.ptr2 = NULL;
- listPtr->typePtr = &tclListType;
+
+ if (objc <= 0) {
+ return listPtr;
}
+
+ /*
+ * Create the internal rep.
+ */
+
+ listRepPtr = NewListIntRep(objc, objv, 1);
+
+ /*
+ * Now create the object.
+ */
+
+ Tcl_InvalidateStringRep(listPtr);
+ ListSetIntRep(listPtr, listRepPtr);
+
return listPtr;
}
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
-Tcl_DbNewListObj(objc, objv, file, line)
- int objc; /* Count of objects referenced by objv. */
- Tcl_Obj *CONST objv[]; /* An array of pointers to Tcl objects. */
- CONST char *file; /* The name of the source file calling this
- * procedure; used for debugging. */
- int line; /* Line number in the source file; used
- * for debugging. */
+Tcl_DbNewListObj(
+ int objc, /* Count of objects referenced by objv. */
+ Tcl_Obj *CONST objv[], /* An array of pointers to Tcl objects. */
+ CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
return Tcl_NewListObj(objc, objv);
}
@@ -210,8 +324,8 @@ Tcl_DbNewListObj(objc, objv, file, line)
*
* Tcl_SetListObj --
*
- * Modify an object to be a list containing each of the objc elements
- * of the object array referenced by objv.
+ * Modify an object to be a list containing each of the objc elements of
+ * the object array referenced by objv.
*
* Results:
* None.
@@ -219,61 +333,43 @@ Tcl_DbNewListObj(objc, objv, file, line)
* Side effects:
* The object is made a list object and is initialized from the object
* pointers in objv. If objc is less than or equal to zero, an empty
- * object is returned. The new object's string representation
- * is left NULL. The ref counts of the elements in objv are incremented
- * since the list now refers to them. The object's old string and
- * internal representations are freed and its type is set NULL.
+ * object is returned. The new object's string representation is left
+ * NULL. The ref counts of the elements in objv are incremented since the
+ * list now refers to them. The object's old string and internal
+ * representations are freed and its type is set NULL.
*
*----------------------------------------------------------------------
*/
void
-Tcl_SetListObj(objPtr, objc, objv)
- Tcl_Obj *objPtr; /* Object whose internal rep to init. */
- int objc; /* Count of objects referenced by objv. */
- Tcl_Obj *CONST objv[]; /* An array of pointers to Tcl objects. */
+Tcl_SetListObj(
+ Tcl_Obj *objPtr, /* Object whose internal rep to init. */
+ int objc, /* Count of objects referenced by objv. */
+ Tcl_Obj *CONST objv[]) /* An array of pointers to Tcl objects. */
{
- register Tcl_Obj **elemPtrs;
- register List *listRepPtr;
- Tcl_ObjType *oldTypePtr = objPtr->typePtr;
- int i;
+ List *listRepPtr;
if (Tcl_IsShared(objPtr)) {
- panic("Tcl_SetListObj called with shared object");
+ Tcl_Panic("%s called with shared object", "Tcl_SetListObj");
}
-
+
/*
* Free any old string rep and any internal rep for the old type.
*/
- if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
- oldTypePtr->freeIntRepProc(objPtr);
- }
+ TclFreeIntRep(objPtr);
objPtr->typePtr = NULL;
Tcl_InvalidateStringRep(objPtr);
-
+
/*
* Set the object's type to "list" and initialize the internal rep.
- * However, if there are no elements to put in the list, just give
- * the object an empty string rep and a NULL type.
+ * However, if there are no elements to put in the list, just give the
+ * object an empty string rep and a NULL type.
*/
if (objc > 0) {
- elemPtrs = (Tcl_Obj **)
- ckalloc((unsigned) (objc * sizeof(Tcl_Obj *)));
- for (i = 0; i < objc; i++) {
- elemPtrs[i] = objv[i];
- Tcl_IncrRefCount(elemPtrs[i]);
- }
-
- listRepPtr = (List *) ckalloc(sizeof(List));
- listRepPtr->maxElemCount = objc;
- listRepPtr->elemCount = objc;
- listRepPtr->elements = elemPtrs;
-
- objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) listRepPtr;
- objPtr->internalRep.twoPtrValue.ptr2 = NULL;
- objPtr->typePtr = &tclListType;
+ listRepPtr = NewListIntRep(objc, objv, 1);
+ ListSetIntRep(objPtr, listRepPtr);
} else {
objPtr->bytes = tclEmptyStringRep;
objPtr->length = 0;
@@ -283,25 +379,66 @@ Tcl_SetListObj(objPtr, objc, objv)
/*
*----------------------------------------------------------------------
*
+ * TclListObjCopy --
+ *
+ * Makes a "pure list" copy of a list value. This provides for the C
+ * level a counterpart of the [lrange $list 0 end] command, while using
+ * internals details to be as efficient as possible.
+ *
+ * Results:
+ * Normally returns a pointer to a new Tcl_Obj, that contains the same
+ * list value as *listPtr does. The returned Tcl_Obj has a refCount of
+ * zero. If *listPtr does not hold a list, NULL is returned, and if
+ * interp is non-NULL, an error message is recorded there.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclListObjCopy(
+ Tcl_Interp *interp, /* Used to report errors if not NULL. */
+ Tcl_Obj *listPtr) /* List object for which an element array is
+ * to be returned. */
+{
+ Tcl_Obj *copyPtr;
+
+ if (listPtr->typePtr != &tclListType) {
+ if (SetListFromAny(interp, listPtr) != TCL_OK) {
+ return NULL;
+ }
+ }
+
+ TclNewObj(copyPtr);
+ TclInvalidateStringRep(copyPtr);
+ DupListInternalRep(listPtr, copyPtr);
+ return copyPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tcl_ListObjGetElements --
*
- * This procedure returns an (objc,objv) array of the elements in a
- * list object.
+ * This function returns an (objc,objv) array of the elements in a list
+ * object.
*
* Results:
* The return value is normally TCL_OK; in this case *objcPtr is set to
* the count of list elements and *objvPtr is set to a pointer to an
- * array of (*objcPtr) pointers to each list element. If listPtr does
- * not refer to a list object and the object can not be converted to
- * one, TCL_ERROR is returned and an error message will be left in
- * the interpreter's result if interp is not NULL.
+ * array of (*objcPtr) pointers to each list element. If listPtr does not
+ * refer to a list object and the object can not be converted to one,
+ * TCL_ERROR is returned and an error message will be left in the
+ * interpreter's result if interp is not NULL.
*
* The objects referenced by the returned array should be treated as
* readonly and their ref counts are _not_ incremented; the caller must
- * do that if it holds on to a reference. Furthermore, the pointer
- * and length returned by this procedure may change as soon as any
- * procedure is called on the list object; be careful about retaining
- * the pointer in a local data structure.
+ * do that if it holds on to a reference. Furthermore, the pointer and
+ * length returned by this function may change as soon as any function is
+ * called on the list object; be careful about retaining the pointer in a
+ * local data structure.
*
* Side effects:
* The possible conversion of the object referenced by listPtr
@@ -311,26 +448,33 @@ Tcl_SetListObj(objPtr, objc, objv)
*/
int
-Tcl_ListObjGetElements(interp, listPtr, objcPtr, objvPtr)
- Tcl_Interp *interp; /* Used to report errors if not NULL. */
- register Tcl_Obj *listPtr; /* List object for which an element array
- * is to be returned. */
- int *objcPtr; /* Where to store the count of objects
+Tcl_ListObjGetElements(
+ Tcl_Interp *interp, /* Used to report errors if not NULL. */
+ register Tcl_Obj *listPtr, /* List object for which an element array is
+ * to be returned. */
+ int *objcPtr, /* Where to store the count of objects
* referenced by objv. */
- Tcl_Obj ***objvPtr; /* Where to store the pointer to an array
- * of pointers to the list's objects. */
+ Tcl_Obj ***objvPtr) /* Where to store the pointer to an array of
+ * pointers to the list's objects. */
{
register List *listRepPtr;
if (listPtr->typePtr != &tclListType) {
- int result = SetListFromAny(interp, listPtr);
+ int result;
+
+ if (listPtr->bytes == tclEmptyStringRep) {
+ *objcPtr = 0;
+ *objvPtr = NULL;
+ return TCL_OK;
+ }
+ result = SetListFromAny(interp, listPtr);
if (result != TCL_OK) {
return result;
}
}
- listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
+ listRepPtr = ListRepPtr(listPtr);
*objcPtr = listRepPtr->elemCount;
- *objvPtr = listRepPtr->elements;
+ *objvPtr = &listRepPtr->elements;
return TCL_OK;
}
@@ -339,50 +483,46 @@ Tcl_ListObjGetElements(interp, listPtr, objcPtr, objvPtr)
*
* Tcl_ListObjAppendList --
*
- * This procedure appends the objects in the list referenced by
+ * This function appends the objects in the list referenced by
* elemListPtr to the list object referenced by listPtr. If listPtr is
* not already a list object, an attempt will be made to convert it to
* one.
*
* Results:
- * The return value is normally TCL_OK. If listPtr or elemListPtr do
- * not refer to list objects and they can not be converted to one,
- * TCL_ERROR is returned and an error message is left in
- * the interpreter's result if interp is not NULL.
+ * The return value is normally TCL_OK. If listPtr or elemListPtr do not
+ * refer to list objects and they can not be converted to one, TCL_ERROR
+ * is returned and an error message is left in the interpreter's result
+ * if interp is not NULL.
*
* Side effects:
* The reference counts of the elements in elemListPtr are incremented
* since the list now refers to them. listPtr and elemListPtr are
- * converted, if necessary, to list objects. Also, appending the
- * new elements may cause listObj's array of element pointers to grow.
+ * converted, if necessary, to list objects. Also, appending the new
+ * elements may cause listObj's array of element pointers to grow.
* listPtr's old string representation, if any, is invalidated.
*
*----------------------------------------------------------------------
*/
int
-Tcl_ListObjAppendList(interp, listPtr, elemListPtr)
- Tcl_Interp *interp; /* Used to report errors if not NULL. */
- register Tcl_Obj *listPtr; /* List object to append elements to. */
- Tcl_Obj *elemListPtr; /* List obj with elements to append. */
+Tcl_ListObjAppendList(
+ Tcl_Interp *interp, /* Used to report errors if not NULL. */
+ register Tcl_Obj *listPtr, /* List object to append elements to. */
+ Tcl_Obj *elemListPtr) /* List obj with elements to append. */
{
- register List *listRepPtr;
int listLen, objc, result;
Tcl_Obj **objv;
if (Tcl_IsShared(listPtr)) {
- panic("Tcl_ListObjAppendList called with shared object");
+ Tcl_Panic("%s called with shared object", "Tcl_ListObjAppendList");
}
- if (listPtr->typePtr != &tclListType) {
- result = SetListFromAny(interp, listPtr);
- if (result != TCL_OK) {
- return result;
- }
+
+ result = TclListObjLength(interp, listPtr, &listLen);
+ if (result != TCL_OK) {
+ return result;
}
- listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
- listLen = listRepPtr->elemCount;
- result = Tcl_ListObjGetElements(interp, elemListPtr, &objc, &objv);
+ result = TclListObjGetElements(interp, elemListPtr, &objc, &objv);
if (result != TCL_OK) {
return result;
}
@@ -391,7 +531,7 @@ Tcl_ListObjAppendList(interp, listPtr, elemListPtr)
* Insert objc new elements starting after the lists's last element.
* Delete zero existing elements.
*/
-
+
return Tcl_ListObjReplace(interp, listPtr, listLen, 0, objc, objv);
}
@@ -400,77 +540,102 @@ Tcl_ListObjAppendList(interp, listPtr, elemListPtr)
*
* Tcl_ListObjAppendElement --
*
- * This procedure is a special purpose version of
- * Tcl_ListObjAppendList: it appends a single object referenced by
- * objPtr to the list object referenced by listPtr. If listPtr is not
- * already a list object, an attempt will be made to convert it to one.
+ * This function is a special purpose version of Tcl_ListObjAppendList:
+ * it appends a single object referenced by objPtr to the list object
+ * referenced by listPtr. If listPtr is not already a list object, an
+ * attempt will be made to convert it to one.
*
* Results:
- * The return value is normally TCL_OK; in this case objPtr is added
- * to the end of listPtr's list. If listPtr does not refer to a list
- * object and the object can not be converted to one, TCL_ERROR is
- * returned and an error message will be left in the interpreter's
- * result if interp is not NULL.
+ * The return value is normally TCL_OK; in this case objPtr is added to
+ * the end of listPtr's list. If listPtr does not refer to a list object
+ * and the object can not be converted to one, TCL_ERROR is returned and
+ * an error message will be left in the interpreter's result if interp is
+ * not NULL.
*
* Side effects:
- * The ref count of objPtr is incremented since the list now refers
- * to it. listPtr will be converted, if necessary, to a list object.
- * Also, appending the new element may cause listObj's array of element
- * pointers to grow. listPtr's old string representation, if any,
- * is invalidated.
+ * The ref count of objPtr is incremented since the list now refers to
+ * it. listPtr will be converted, if necessary, to a list object. Also,
+ * appending the new element may cause listObj's array of element
+ * pointers to grow. listPtr's old string representation, if any, is
+ * invalidated.
*
*----------------------------------------------------------------------
*/
int
-Tcl_ListObjAppendElement(interp, listPtr, objPtr)
- Tcl_Interp *interp; /* Used to report errors if not NULL. */
- Tcl_Obj *listPtr; /* List object to append objPtr to. */
- Tcl_Obj *objPtr; /* Object to append to listPtr's list. */
+Tcl_ListObjAppendElement(
+ Tcl_Interp *interp, /* Used to report errors if not NULL. */
+ Tcl_Obj *listPtr, /* List object to append objPtr to. */
+ Tcl_Obj *objPtr) /* Object to append to listPtr's list. */
{
register List *listRepPtr;
register Tcl_Obj **elemPtrs;
- int numElems, numRequired;
-
+ int numElems, numRequired, newMax, newSize, i;
+
if (Tcl_IsShared(listPtr)) {
- panic("Tcl_ListObjAppendElement called with shared object");
+ Tcl_Panic("%s called with shared object", "Tcl_ListObjAppendElement");
}
if (listPtr->typePtr != &tclListType) {
- int result = SetListFromAny(interp, listPtr);
+ int result;
+
+ if (listPtr->bytes == tclEmptyStringRep) {
+ Tcl_SetListObj(listPtr, 1, &objPtr);
+ return TCL_OK;
+ }
+ result = SetListFromAny(interp, listPtr);
if (result != TCL_OK) {
return result;
}
}
- listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
- elemPtrs = listRepPtr->elements;
+ listRepPtr = ListRepPtr(listPtr);
numElems = listRepPtr->elemCount;
numRequired = numElems + 1 ;
-
+
/*
- * If there is no room in the current array of element pointers,
- * allocate a new, larger array and copy the pointers to it.
+ * If there is no room in the current array of element pointers, allocate
+ * a new, larger array and copy the pointers to it. If the List struct is
+ * shared, allocate a new one.
*/
- if (numRequired > listRepPtr->maxElemCount) {
- int newMax = (2 * numRequired);
- Tcl_Obj **newElemPtrs = (Tcl_Obj **)
- ckalloc((unsigned) (newMax * sizeof(Tcl_Obj *)));
-
- memcpy((VOID *) newElemPtrs, (VOID *) elemPtrs,
- (size_t) (numElems * sizeof(Tcl_Obj *)));
+ if (numRequired > listRepPtr->maxElemCount){
+ newMax = 2 * numRequired;
+ newSize = sizeof(List) + ((newMax-1) * sizeof(Tcl_Obj *));
+ } else {
+ newMax = listRepPtr->maxElemCount;
+ newSize = 0;
+ }
+
+ if (listRepPtr->refCount > 1) {
+ List *oldListRepPtr = listRepPtr;
+ Tcl_Obj **oldElems;
+ listRepPtr = AttemptNewList(interp, newMax, NULL);
+ if (listRepPtr == NULL) {
+ return TCL_ERROR;
+ }
+ oldElems = &oldListRepPtr->elements;
+ elemPtrs = &listRepPtr->elements;
+ for (i=0; i<numElems; i++) {
+ elemPtrs[i] = oldElems[i];
+ Tcl_IncrRefCount(elemPtrs[i]);
+ }
+ listRepPtr->elemCount = numElems;
+ listRepPtr->refCount++;
+ oldListRepPtr->refCount--;
+ listPtr->internalRep.twoPtrValue.ptr1 = (void *) listRepPtr;
+ } else if (newSize) {
+ listRepPtr = (List *) ckrealloc((char *)listRepPtr, (size_t)newSize);
listRepPtr->maxElemCount = newMax;
- listRepPtr->elements = newElemPtrs;
- ckfree((char *) elemPtrs);
- elemPtrs = newElemPtrs;
+ listPtr->internalRep.twoPtrValue.ptr1 = (void *) listRepPtr;
}
/*
- * Add objPtr to the end of listPtr's array of element
- * pointers. Increment the ref count for the (now shared) objPtr.
+ * Add objPtr to the end of listPtr's array of element pointers. Increment
+ * the ref count for the (now shared) objPtr.
*/
+ elemPtrs = &listRepPtr->elements;
elemPtrs[numElems] = objPtr;
Tcl_IncrRefCount(objPtr);
listRepPtr->elemCount++;
@@ -489,20 +654,20 @@ Tcl_ListObjAppendElement(interp, listPtr, objPtr)
*
* Tcl_ListObjIndex --
*
- * This procedure returns a pointer to the index'th object from the
- * list referenced by listPtr. The first element has index 0. If index
- * is negative or greater than or equal to the number of elements in
- * the list, a NULL is returned. If listPtr is not a list object, an
- * attempt will be made to convert it to a list.
+ * This function returns a pointer to the index'th object from the list
+ * referenced by listPtr. The first element has index 0. If index is
+ * negative or greater than or equal to the number of elements in the
+ * list, a NULL is returned. If listPtr is not a list object, an attempt
+ * will be made to convert it to a list.
*
* Results:
- * The return value is normally TCL_OK; in this case objPtrPtr is set
- * to the Tcl_Obj pointer for the index'th list element or NULL if
- * index is out of range. This object should be treated as readonly and
- * its ref count is _not_ incremented; the caller must do that if it
- * holds on to the reference. If listPtr does not refer to a list and
- * can't be converted to one, TCL_ERROR is returned and an error
- * message is left in the interpreter's result if interp is not NULL.
+ * The return value is normally TCL_OK; in this case objPtrPtr is set to
+ * the Tcl_Obj pointer for the index'th list element or NULL if index is
+ * out of range. This object should be treated as readonly and its ref
+ * count is _not_ incremented; the caller must do that if it holds on to
+ * the reference. If listPtr does not refer to a list and can't be
+ * converted to one, TCL_ERROR is returned and an error message is left
+ * in the interpreter's result if interp is not NULL.
*
* Side effects:
* listPtr will be converted, if necessary, to a list object.
@@ -511,28 +676,34 @@ Tcl_ListObjAppendElement(interp, listPtr, objPtr)
*/
int
-Tcl_ListObjIndex(interp, listPtr, index, objPtrPtr)
- Tcl_Interp *interp; /* Used to report errors if not NULL. */
- register Tcl_Obj *listPtr; /* List object to index into. */
- register int index; /* Index of element to return. */
- Tcl_Obj **objPtrPtr; /* The resulting Tcl_Obj* is stored here. */
+Tcl_ListObjIndex(
+ Tcl_Interp *interp, /* Used to report errors if not NULL. */
+ register Tcl_Obj *listPtr, /* List object to index into. */
+ register int index, /* Index of element to return. */
+ Tcl_Obj **objPtrPtr) /* The resulting Tcl_Obj* is stored here. */
{
register List *listRepPtr;
-
+
if (listPtr->typePtr != &tclListType) {
- int result = SetListFromAny(interp, listPtr);
+ int result;
+
+ if (listPtr->bytes == tclEmptyStringRep) {
+ *objPtrPtr = NULL;
+ return TCL_OK;
+ }
+ result = SetListFromAny(interp, listPtr);
if (result != TCL_OK) {
return result;
}
}
- listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
+ listRepPtr = ListRepPtr(listPtr);
if ((index < 0) || (index >= listRepPtr->elemCount)) {
*objPtrPtr = NULL;
} else {
- *objPtrPtr = listRepPtr->elements[index];
+ *objPtrPtr = (&listRepPtr->elements)[index];
}
-
+
return TCL_OK;
}
@@ -541,16 +712,16 @@ Tcl_ListObjIndex(interp, listPtr, index, objPtrPtr)
*
* Tcl_ListObjLength --
*
- * This procedure returns the number of elements in a list object. If
- * the object is not already a list object, an attempt will be made to
+ * This function returns the number of elements in a list object. If the
+ * object is not already a list object, an attempt will be made to
* convert it to one.
*
* Results:
- * The return value is normally TCL_OK; in this case *intPtr will be
- * set to the integer count of list elements. If listPtr does not refer
- * to a list object and the object can not be converted to one,
- * TCL_ERROR is returned and an error message will be left in
- * the interpreter's result if interp is not NULL.
+ * The return value is normally TCL_OK; in this case *intPtr will be set
+ * to the integer count of list elements. If listPtr does not refer to a
+ * list object and the object can not be converted to one, TCL_ERROR is
+ * returned and an error message will be left in the interpreter's result
+ * if interp is not NULL.
*
* Side effects:
* The possible conversion of the argument object to a list object.
@@ -559,21 +730,27 @@ Tcl_ListObjIndex(interp, listPtr, index, objPtrPtr)
*/
int
-Tcl_ListObjLength(interp, listPtr, intPtr)
- Tcl_Interp *interp; /* Used to report errors if not NULL. */
- register Tcl_Obj *listPtr; /* List object whose #elements to return. */
- register int *intPtr; /* The resulting int is stored here. */
+Tcl_ListObjLength(
+ Tcl_Interp *interp, /* Used to report errors if not NULL. */
+ register Tcl_Obj *listPtr, /* List object whose #elements to return. */
+ register int *intPtr) /* The resulting int is stored here. */
{
register List *listRepPtr;
-
+
if (listPtr->typePtr != &tclListType) {
- int result = SetListFromAny(interp, listPtr);
+ int result;
+
+ if (listPtr->bytes == tclEmptyStringRep) {
+ *intPtr = 0;
+ return TCL_OK;
+ }
+ result = SetListFromAny(interp, listPtr);
if (result != TCL_OK) {
return result;
}
}
- listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
+ listRepPtr = ListRepPtr(listPtr);
*intPtr = listRepPtr->elemCount;
return TCL_OK;
}
@@ -582,178 +759,227 @@ Tcl_ListObjLength(interp, listPtr, intPtr)
*----------------------------------------------------------------------
*
* Tcl_ListObjReplace --
- *
- * This procedure replaces zero or more elements of the list referenced
- * by listPtr with the objects from an (objc,objv) array.
- * The objc elements of the array referenced by objv replace the
- * count elements in listPtr starting at first.
+ *
+ * This function replaces zero or more elements of the list referenced by
+ * listPtr with the objects from an (objc,objv) array. The objc elements
+ * of the array referenced by objv replace the count elements in listPtr
+ * starting at first.
*
* If the argument first is zero or negative, it refers to the first
* element. If first is greater than or equal to the number of elements
* in the list, then no elements are deleted; the new elements are
- * appended to the list. Count gives the number of elements to
- * replace. If count is zero or negative then no elements are deleted;
- * the new elements are simply inserted before first.
+ * appended to the list. Count gives the number of elements to replace.
+ * If count is zero or negative then no elements are deleted; the new
+ * elements are simply inserted before first.
*
* The argument objv refers to an array of objc pointers to the new
- * elements to be added to listPtr in place of those that were
- * deleted. If objv is NULL, no new elements are added. If listPtr is
- * not a list object, an attempt will be made to convert it to one.
+ * elements to be added to listPtr in place of those that were deleted.
+ * If objv is NULL, no new elements are added. If listPtr is not a list
+ * object, an attempt will be made to convert it to one.
*
* Results:
- * The return value is normally TCL_OK. If listPtr does
- * not refer to a list object and can not be converted to one,
- * TCL_ERROR is returned and an error message will be left in
- * the interpreter's result if interp is not NULL.
+ * The return value is normally TCL_OK. If listPtr does not refer to a
+ * list object and can not be converted to one, TCL_ERROR is returned and
+ * an error message will be left in the interpreter's result if interp is
+ * not NULL.
*
* Side effects:
- * The ref counts of the objc elements in objv are incremented since
- * the resulting list now refers to them. Similarly, the ref counts for
- * replaced objects are decremented. listPtr is converted, if
- * necessary, to a list object. listPtr's old string representation, if
- * any, is freed.
+ * The ref counts of the objc elements in objv are incremented since the
+ * resulting list now refers to them. Similarly, the ref counts for
+ * replaced objects are decremented. listPtr is converted, if necessary,
+ * to a list object. listPtr's old string representation, if any, is
+ * freed.
*
*----------------------------------------------------------------------
*/
int
-Tcl_ListObjReplace(interp, listPtr, first, count, objc, objv)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- Tcl_Obj *listPtr; /* List object whose elements to replace. */
- int first; /* Index of first element to replace. */
- int count; /* Number of elements to replace. */
- int objc; /* Number of objects to insert. */
- Tcl_Obj *CONST objv[]; /* An array of objc pointers to Tcl objects
- * to insert. */
+Tcl_ListObjReplace(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tcl_Obj *listPtr, /* List object whose elements to replace. */
+ int first, /* Index of first element to replace. */
+ int count, /* Number of elements to replace. */
+ int objc, /* Number of objects to insert. */
+ Tcl_Obj *CONST objv[]) /* An array of objc pointers to Tcl objects to
+ * insert. */
{
List *listRepPtr;
- register Tcl_Obj **elemPtrs, **newPtrs;
- Tcl_Obj *victimPtr;
- int numElems, numRequired, numAfterLast;
- int start, shift, newMax, i, j, result;
-
+ register Tcl_Obj **elemPtrs;
+ int numElems, numRequired, numAfterLast, start, i, j, isShared;
+
if (Tcl_IsShared(listPtr)) {
- panic("Tcl_ListObjReplace called with shared object");
+ Tcl_Panic("%s called with shared object", "Tcl_ListObjReplace");
}
if (listPtr->typePtr != &tclListType) {
- result = SetListFromAny(interp, listPtr);
- if (result != TCL_OK) {
- return result;
+ if (listPtr->bytes == tclEmptyStringRep) {
+ if (objc) {
+ Tcl_SetListObj(listPtr, objc, NULL);
+ } else {
+ return TCL_OK;
+ }
+ } else {
+ int result = SetListFromAny(interp, listPtr);
+
+ if (result != TCL_OK) {
+ return result;
+ }
}
}
- listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
- elemPtrs = listRepPtr->elements;
+
+ /*
+ * Note that when count == 0 and objc == 0, this routine is logically a
+ * no-op, removing and adding no elements to the list. However, by flowing
+ * through this routine anyway, we get the important side effect that the
+ * resulting listPtr is a list in canoncial form. This is important.
+ * Resist any temptation to optimize this case.
+ */
+
+ listRepPtr = ListRepPtr(listPtr);
+ elemPtrs = &listRepPtr->elements;
numElems = listRepPtr->elemCount;
- if (first < 0) {
- first = 0;
+ if (first < 0) {
+ first = 0;
}
if (first >= numElems) {
- first = numElems; /* so we'll insert after last element */
+ first = numElems; /* So we'll insert after last element. */
}
if (count < 0) {
count = 0;
- }
-
- numRequired = (numElems - count + objc);
- if (numRequired <= listRepPtr->maxElemCount) {
+ } else if (numElems < first+count || first+count < 0) {
/*
- * Enough room in the current array. First "delete" count
- * elements starting at first.
+ * The 'first+count < 0' condition here guards agains integer
+ * overflow in determining 'first+count'
*/
+ count = numElems - first;
+ }
- for (i = 0, j = first; i < count; i++, j++) {
- victimPtr = elemPtrs[j];
- TclDecrRefCount(victimPtr);
- }
+ isShared = (listRepPtr->refCount > 1);
+ numRequired = numElems - count + objc;
+
+ if ((numRequired <= listRepPtr->maxElemCount) && !isShared) {
+ int shift;
/*
- * Shift the elements after the last one removed to their
- * new locations.
+ * Can use the current List struct. First "delete" count elements
+ * starting at first.
*/
- start = (first + count);
- numAfterLast = (numElems - start);
- shift = (objc - count); /* numNewElems - numDeleted */
- if ((numAfterLast > 0) && (shift != 0)) {
- Tcl_Obj **src, **dst;
+ for (j = first; j < first + count; j++) {
+ Tcl_Obj *victimPtr = elemPtrs[j];
- src = elemPtrs + start; dst = src + shift;
- memmove((VOID*) dst, (VOID*) src,
- (size_t) (numAfterLast * sizeof(Tcl_Obj*)));
+ TclDecrRefCount(victimPtr);
}
/*
- * Insert the new elements into elemPtrs before "first".
+ * Shift the elements after the last one removed to their new
+ * locations.
*/
- for (i = 0, j = first; i < objc; i++, j++) {
- elemPtrs[j] = objv[i];
- Tcl_IncrRefCount(objv[i]);
- }
-
- /*
- * Update the count of elements.
- */
+ start = first + count;
+ numAfterLast = numElems - start;
+ shift = objc - count; /* numNewElems - numDeleted */
+ if ((numAfterLast > 0) && (shift != 0)) {
+ Tcl_Obj **src = elemPtrs + start;
- listRepPtr->elemCount = numRequired;
+ memmove(src+shift, src, (size_t) numAfterLast * sizeof(Tcl_Obj*));
+ }
} else {
/*
- * Not enough room in the current array. Allocate a larger array and
- * insert elements into it.
+ * Cannot use the current List struct; it is shared, too small, or
+ * both. Allocate a new struct and insert elements into it.
*/
- newMax = (2 * numRequired);
- newPtrs = (Tcl_Obj **)
- ckalloc((unsigned) (newMax * sizeof(Tcl_Obj *)));
+ List *oldListRepPtr = listRepPtr;
+ Tcl_Obj **oldPtrs = elemPtrs;
+ int newMax;
- /*
- * Copy over the elements before "first".
- */
+ if (numRequired > listRepPtr->maxElemCount){
+ newMax = 2 * numRequired;
+ } else {
+ newMax = listRepPtr->maxElemCount;
+ }
- if (first > 0) {
- memcpy((VOID *) newPtrs, (VOID *) elemPtrs,
- (size_t) (first * sizeof(Tcl_Obj *)));
+ listRepPtr = AttemptNewList(interp, newMax, NULL);
+ if (listRepPtr == NULL) {
+ return TCL_ERROR;
}
- /*
- * "Delete" count elements starting at first.
- */
+ listPtr->internalRep.twoPtrValue.ptr1 = (void *) listRepPtr;
+ listRepPtr->refCount++;
- for (i = 0, j = first; i < count; i++, j++) {
- victimPtr = elemPtrs[j];
- TclDecrRefCount(victimPtr);
- }
+ elemPtrs = &listRepPtr->elements;
- /*
- * Copy the elements after the last one removed, shifted to
- * their new locations.
- */
+ if (isShared) {
+ /*
+ * The old struct will remain in place; need new refCounts for the
+ * new List struct references. Copy over only the surviving
+ * elements.
+ */
- start = (first + count);
- numAfterLast = (numElems - start);
- if (numAfterLast > 0) {
- memcpy((VOID *) &(newPtrs[first + objc]),
- (VOID *) &(elemPtrs[start]),
- (size_t) (numAfterLast * sizeof(Tcl_Obj *)));
- }
-
- /*
- * Insert the new elements before "first" and update the
- * count of elements.
- */
+ for (i=0; i < first; i++) {
+ elemPtrs[i] = oldPtrs[i];
+ Tcl_IncrRefCount(elemPtrs[i]);
+ }
+ for (i = first + count, j = first + objc;
+ j < numRequired; i++, j++) {
+ elemPtrs[j] = oldPtrs[i];
+ Tcl_IncrRefCount(elemPtrs[j]);
+ }
+
+ oldListRepPtr->refCount--;
+ } else {
+ /*
+ * The old struct will be removed; use its inherited refCounts.
+ */
+
+ if (first > 0) {
+ memcpy(elemPtrs, oldPtrs, (size_t) first * sizeof(Tcl_Obj *));
+ }
- for (i = 0, j = first; i < objc; i++, j++) {
- newPtrs[j] = objv[i];
- Tcl_IncrRefCount(objv[i]);
+ /*
+ * "Delete" count elements starting at first.
+ */
+
+ for (j = first; j < first + count; j++) {
+ Tcl_Obj *victimPtr = oldPtrs[j];
+
+ TclDecrRefCount(victimPtr);
+ }
+
+ /*
+ * Copy the elements after the last one removed, shifted to their
+ * new locations.
+ */
+
+ start = first + count;
+ numAfterLast = numElems - start;
+ if (numAfterLast > 0) {
+ memcpy(elemPtrs + first + objc, oldPtrs + start,
+ (size_t) numAfterLast * sizeof(Tcl_Obj *));
+ }
+
+ ckfree((char *) oldListRepPtr);
}
+ }
- listRepPtr->elemCount = numRequired;
- listRepPtr->maxElemCount = newMax;
- listRepPtr->elements = newPtrs;
- ckfree((char *) elemPtrs);
+ /*
+ * Insert the new elements into elemPtrs before "first". We don't do a
+ * memcpy here because we must increment the reference counts for the
+ * added elements, so we must explicitly loop anyway.
+ */
+
+ for (i=0,j=first ; i<objc ; i++,j++) {
+ elemPtrs[j] = objv[i];
+ Tcl_IncrRefCount(objv[i]);
}
-
+
+ /*
+ * Update the count of elements.
+ */
+
+ listRepPtr->elemCount = numRequired;
+
/*
* Invalidate and free any old string representation since it no longer
* reflects the list's internal representation.
@@ -766,270 +992,249 @@ Tcl_ListObjReplace(interp, listPtr, first, count, objc, objv)
/*
*----------------------------------------------------------------------
*
- * TclLsetList --
- *
- * Core of the 'lset' command when objc == 4. Objv[2] may be
- * either a scalar index or a list of indices.
+ * TclLindexList --
+ *
+ * This procedure handles the 'lindex' command when objc==3.
*
* Results:
- * Returns the new value of the list variable, or NULL if an
- * error occurs.
+ * Returns a pointer to the object extracted, or NULL if an error
+ * occurred. The returned object already includes one reference count for
+ * the pointer returned.
*
* Side effects:
- * Surgery is performed on the list value to produce the
- * result.
- *
- * On entry, the reference count of the variable value does not reflect
- * any references held on the stack. The first action of this function
- * is to determine whether the object is shared, and to duplicate it if
- * it is. The reference count of the duplicate is incremented.
- * At this point, the reference count will be 1 for either case, so that
- * the object will appear to be unshared.
- *
- * If an error occurs, and the object has been duplicated, the reference
- * count on the duplicate is decremented so that it is now 0: this dismisses
- * any memory that was allocated by this procedure.
- *
- * If no error occurs, the reference count of the original object is
- * incremented if the object has not been duplicated, and nothing is
- * done to a reference count of the duplicate. Now the reference count
- * of an unduplicated object is 2 (the returned pointer, plus the one
- * stored in the variable). The reference count of a duplicate object
- * is 1, reflecting that the returned pointer is the only active
- * reference. The caller is expected to store the returned value back
- * in the variable and decrement its reference count. (INST_STORE_*
- * does exactly this.)
- *
- * Tcl_LsetFlat and related functions maintain a linked list of
- * Tcl_Obj's whose string representations must be spoilt by threading
- * via 'ptr2' of the two-pointer internal representation. On entry
- * to Tcl_LsetList, the values of 'ptr2' are immaterial; on exit,
- * the 'ptr2' field of any Tcl_Obj that has been modified is set to
- * NULL.
+ * None.
+ *
+ * Notes:
+ * This procedure is implemented entirely as a wrapper around
+ * TclLindexFlat. All it does is reconfigure the argument format into the
+ * form required by TclLindexFlat, while taking care to manage shimmering
+ * in such a way that we tend to keep the most useful intreps and/or
+ * avoid the most expensive conversions.
*
*----------------------------------------------------------------------
*/
-Tcl_Obj*
-TclLsetList( interp, listPtr, indexArgPtr, valuePtr )
- Tcl_Interp* interp; /* Tcl interpreter */
- Tcl_Obj* listPtr; /* Pointer to the list being modified */
- Tcl_Obj* indexArgPtr; /* Index or index-list arg to 'lset' */
- Tcl_Obj* valuePtr; /* Value arg to 'lset' */
+Tcl_Obj *
+TclLindexList(
+ Tcl_Interp *interp, /* Tcl interpreter. */
+ Tcl_Obj *listPtr, /* List being unpacked. */
+ Tcl_Obj *argPtr) /* Index or index list. */
{
- int indexCount; /* Number of indices in the index list */
- Tcl_Obj** indices; /* Vector of indices in the index list*/
-
- int duplicated; /* Flag == 1 if the obj has been
- * duplicated, 0 otherwise */
- Tcl_Obj* retValuePtr; /* Pointer to the list to be returned */
- int index; /* Current index in the list - discarded */
- int result; /* Status return from library calls */
- Tcl_Obj* subListPtr; /* Pointer to the current sublist */
- int elemCount; /* Count of elements in the current sublist */
- Tcl_Obj** elemPtrs; /* Pointers to elements of current sublist */
- Tcl_Obj* chainPtr; /* Pointer to the enclosing sublist
- * of the current sublist */
- int i;
+ int index; /* Index into the list. */
+ Tcl_Obj **indices; /* Array of list indices. */
+ int indexCount; /* Size of the array of list indices. */
+ Tcl_Obj *indexListCopy;
/*
- * Determine whether the index arg designates a list or a single
- * index. We have to be careful about the order of the checks to
- * avoid repeated shimmering; see TIP #22 and #23 for details.
+ * Determine whether argPtr designates a list or a single index. We have
+ * to be careful about the order of the checks to avoid repeated
+ * shimmering; see TIP#22 and TIP#33 for the details.
*/
- if ( indexArgPtr->typePtr != &tclListType
- && TclGetIntForIndex( NULL, indexArgPtr, 0, &index ) == TCL_OK ) {
-
- /*
- * indexArgPtr designates a single index.
- */
-
- return TclLsetFlat( interp, listPtr, 1, &indexArgPtr, valuePtr );
-
- } else if ( Tcl_ListObjGetElements( NULL, indexArgPtr,
- &indexCount, &indices ) != TCL_OK ) {
-
+ if (argPtr->typePtr != &tclListType
+ && TclGetIntForIndexM(NULL , argPtr, 0, &index) == TCL_OK) {
/*
- * indexArgPtr designates something that is neither an index nor a
- * well formed list. Report the error via TclLsetFlat.
+ * argPtr designates a single index.
*/
- return TclLsetFlat( interp, listPtr, 1, &indexArgPtr, valuePtr );
-
+ return TclLindexFlat(interp, listPtr, 1, &argPtr);
}
/*
- * At this point, we know that argPtr designates a well formed list,
- * and the 'else if' above has parsed it into indexCount and indices.
- * If there are no indices, simply return 'valuePtr', counting the
- * returned pointer as a reference.
+ * Here we make a private copy of the index list argument to avoid any
+ * shimmering issues that might invalidate the indices array below while
+ * we are still using it. This is probably unnecessary. It does not appear
+ * that any damaging shimmering is possible, and no test has been devised
+ * to show any error when this private copy is not made. But it's cheap,
+ * and it offers some future-proofing insurance in case the TclLindexFlat
+ * implementation changes in some unexpected way, or some new form of
+ * trace or callback permits things to happen that the current
+ * implementation does not.
*/
- if ( indexCount == 0 ) {
- Tcl_IncrRefCount( valuePtr );
- return valuePtr;
- }
-
- /*
- * Duplicate the list arg if necessary.
- */
+ indexListCopy = TclListObjCopy(NULL, argPtr);
+ if (indexListCopy == NULL) {
+ /*
+ * argPtr designates something that is neither an index nor a
+ * well-formed list. Report the error via TclLindexFlat.
+ */
- if ( Tcl_IsShared( listPtr ) ) {
- duplicated = 1;
- listPtr = Tcl_DuplicateObj( listPtr );
- Tcl_IncrRefCount( listPtr );
- } else {
- duplicated = 0;
+ return TclLindexFlat(interp, listPtr, 1, &argPtr);
}
- /*
- * It would be tempting simply to go off to TclLsetFlat to finish the
- * processing. Alas, it is also incorrect! The problem is that
- * 'indexArgPtr' may designate a sublist of 'listPtr' whose value
- * is to be manipulated. The fact that 'listPtr' is itself unshared
- * does not guarantee that no sublist is. Therefore, it's necessary
- * to replicate all the work here, expanding the index list on each
- * trip through the loop.
- */
-
- /*
- * Anchor the linked list of Tcl_Obj's whose string reps must be
- * invalidated if the operation succeeds.
- */
+ TclListObjGetElements(NULL, indexListCopy, &indexCount, &indices);
+ listPtr = TclLindexFlat(interp, listPtr, indexCount, indices);
+ Tcl_DecrRefCount(indexListCopy);
+ return listPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclLindexFlat --
+ *
+ * This procedure is the core of the 'lindex' command, with all index
+ * arguments presented as a flat list.
+ *
+ * Results:
+ * Returns a pointer to the object extracted, or NULL if an error
+ * occurred. The returned object already includes one reference count for
+ * the pointer returned.
+ *
+ * Side effects:
+ * None.
+ *
+ * Notes:
+ * The reference count of the returned object includes one reference
+ * corresponding to the pointer returned. Thus, the calling code will
+ * usually do something like:
+ * Tcl_SetObjResult(interp, result);
+ * Tcl_DecrRefCount(result);
+ *
+ *----------------------------------------------------------------------
+ */
- retValuePtr = listPtr;
- chainPtr = NULL;
+Tcl_Obj *
+TclLindexFlat(
+ Tcl_Interp *interp, /* Tcl interpreter. */
+ Tcl_Obj *listPtr, /* Tcl object representing the list. */
+ int indexCount, /* Count of indices. */
+ Tcl_Obj *const indexArray[])/* Array of pointers to Tcl objects that
+ * represent the indices in the list. */
+{
+ int i;
- /*
- * Handle each index arg by diving into the appropriate sublist
- */
+ Tcl_IncrRefCount(listPtr);
- for ( i = 0; ; ++i ) {
+ for (i=0 ; i<indexCount && listPtr ; i++) {
+ int index, listLen;
+ Tcl_Obj **elemPtrs, *sublistCopy;
/*
- * Take the sublist apart.
+ * Here we make a private copy of the current sublist, so we avoid any
+ * shimmering issues that might invalidate the elemPtr array below
+ * while we are still using it. See test lindex-8.4.
*/
- result = Tcl_ListObjGetElements( interp, listPtr,
- &elemCount, &elemPtrs );
- if ( result != TCL_OK ) {
- break;
- }
- listPtr->internalRep.twoPtrValue.ptr2 = (VOID *) chainPtr;
-
- /*
- * Reconstitute the index array
- */
+ sublistCopy = TclListObjCopy(interp, listPtr);
+ Tcl_DecrRefCount(listPtr);
+ listPtr = NULL;
- result = Tcl_ListObjGetElements( interp, indexArgPtr,
- &indexCount, &indices );
- if ( result != TCL_OK ) {
- /*
- * Shouldn't be able to get here, because we already
- * parsed the thing successfully once.
+ if (sublistCopy == NULL) {
+ /*
+ * The sublist is not a list at all => error.
*/
- break;
- }
- /*
- * Determine the index of the requested element.
- */
-
- result = TclGetIntForIndex( interp, indices[ i ],
- (elemCount - 1), &index );
- if ( result != TCL_OK ) {
break;
}
-
- /*
- * Check that the index is in range.
- */
-
- if ( ( index < 0 ) || ( index >= elemCount ) ) {
- Tcl_SetObjResult( interp,
- Tcl_NewStringObj( "list index out of range",
- -1 ) );
- result = TCL_ERROR;
- break;
- }
-
- /*
- * Break the loop after extracting the innermost sublist
- */
-
- if ( i >= indexCount-1 ) {
- result = TCL_OK;
- break;
- }
-
- /*
- * Extract the appropriate sublist, and make sure that it is unshared.
- */
+ TclListObjGetElements(NULL, sublistCopy, &listLen, &elemPtrs);
+
+ if (TclGetIntForIndexM(interp, indexArray[i], /*endValue*/ listLen-1,
+ &index) == TCL_OK) {
+ if (index<0 || index>=listLen) {
+ /*
+ * Index is out of range. Break out of loop with empty result.
+ * First check remaining indices for validity
+ */
- subListPtr = elemPtrs[ index ];
- if ( Tcl_IsShared( subListPtr ) ) {
- subListPtr = Tcl_DuplicateObj( subListPtr );
- result = TclListObjSetElement( interp, listPtr, index,
- subListPtr );
- if ( result != TCL_OK ) {
- /*
- * We actually shouldn't be able to get here, because
- * we've already checked everything that TclListObjSetElement
- * checks. If we were to get here, it would result in leaking
- * subListPtr.
+ while (++i < indexCount) {
+ if (TclGetIntForIndexM(interp, indexArray[i], -1, &index)
+ != TCL_OK) {
+ Tcl_DecrRefCount(sublistCopy);
+ return NULL;
+ }
+ }
+ listPtr = Tcl_NewObj();
+ } else {
+ /*
+ * Extract the pointer to the appropriate element.
*/
- break;
+
+ listPtr = elemPtrs[index];
}
+ Tcl_IncrRefCount(listPtr);
}
+ Tcl_DecrRefCount(sublistCopy);
+ }
- /*
- * Chain the current sublist onto the linked list of Tcl_Obj's
- * whose string reps must be spoilt.
- */
-
- chainPtr = listPtr;
- listPtr = subListPtr;
+ return listPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclLsetList --
+ *
+ * Core of the 'lset' command when objc == 4. Objv[2] may be either a
+ * scalar index or a list of indices.
+ *
+ * Results:
+ * Returns the new value of the list variable, or NULL if there was an
+ * error. The returned object includes one reference count for the
+ * pointer returned.
+ *
+ * Side effects:
+ * None.
+ *
+ * Notes:
+ * This procedure is implemented entirely as a wrapper around
+ * TclLsetFlat. All it does is reconfigure the argument format into the
+ * form required by TclLsetFlat, while taking care to manage shimmering
+ * in such a way that we tend to keep the most useful intreps and/or
+ * avoid the most expensive conversions.
+ *
+ *----------------------------------------------------------------------
+ */
- }
+Tcl_Obj *
+TclLsetList(
+ Tcl_Interp *interp, /* Tcl interpreter. */
+ Tcl_Obj *listPtr, /* Pointer to the list being modified. */
+ Tcl_Obj *indexArgPtr, /* Index or index-list arg to 'lset'. */
+ Tcl_Obj *valuePtr) /* Value arg to 'lset'. */
+{
+ int indexCount; /* Number of indices in the index list. */
+ Tcl_Obj **indices; /* Vector of indices in the index list. */
+ Tcl_Obj *retValuePtr; /* Pointer to the list to be returned. */
+ int index; /* Current index in the list - discarded. */
+ Tcl_Obj *indexListCopy;
/*
- * Store the new element into the correct slot in the innermost sublist.
+ * Determine whether the index arg designates a list or a single index.
+ * We have to be careful about the order of the checks to avoid repeated
+ * shimmering; see TIP #22 and #23 for details.
*/
- if ( result == TCL_OK ) {
- result = TclListObjSetElement( interp, listPtr, index, valuePtr );
- }
+ if (indexArgPtr->typePtr != &tclListType
+ && TclGetIntForIndexM(NULL, indexArgPtr, 0, &index) == TCL_OK) {
+ /*
+ * indexArgPtr designates a single index.
+ */
- if ( result == TCL_OK ) {
+ return TclLsetFlat(interp, listPtr, 1, &indexArgPtr, valuePtr);
- listPtr->internalRep.twoPtrValue.ptr2 = (VOID *) chainPtr;
+ }
- /* Spoil all the string reps */
-
- while ( listPtr != NULL ) {
- subListPtr = (Tcl_Obj *) listPtr->internalRep.twoPtrValue.ptr2;
- Tcl_InvalidateStringRep( listPtr );
- listPtr->internalRep.twoPtrValue.ptr2 = NULL;
- listPtr = subListPtr;
- }
+ indexListCopy = TclListObjCopy(NULL, indexArgPtr);
+ if (indexListCopy == NULL) {
+ /*
+ * indexArgPtr designates something that is neither an index nor a
+ * well formed list. Report the error via TclLsetFlat.
+ */
- /* Return the new list if everything worked. */
-
- if ( !duplicated ) {
- Tcl_IncrRefCount( retValuePtr );
- }
- return retValuePtr;
+ return TclLsetFlat(interp, listPtr, 1, &indexArgPtr, valuePtr);
}
+ TclListObjGetElements(NULL, indexArgPtr, &indexCount, &indices);
- /* Clean up the one dangling reference otherwise */
+ /*
+ * Let TclLsetFlat handle the actual lset'ting.
+ */
- if ( duplicated ) {
- Tcl_DecrRefCount( retValuePtr );
- }
- return NULL;
+ retValuePtr = TclLsetFlat(interp, listPtr, indexCount, indices, valuePtr);
+ Tcl_DecrRefCount(indexListCopy);
+ return retValuePtr;
}
/*
@@ -1037,220 +1242,216 @@ TclLsetList( interp, listPtr, indexArgPtr, valuePtr )
*
* TclLsetFlat --
*
- * Core of the 'lset' command when objc>=5. Objv[2], ... ,
- * objv[objc-2] contain scalar indices.
+ * Core engine of the 'lset' command.
*
* Results:
- * Returns the new value of the list variable, or NULL if an
- * error occurs.
+ * Returns the new value of the list variable, or NULL if an error
+ * occurred. The returned object includes one reference count for
+ * the pointer returned.
*
* Side effects:
- * Surgery is performed on the list value to produce the
- * result.
- *
- * On entry, the reference count of the variable value does not reflect
- * any references held on the stack. The first action of this function
- * is to determine whether the object is shared, and to duplicate it if
- * it is. The reference count of the duplicate is incremented.
- * At this point, the reference count will be 1 for either case, so that
- * the object will appear to be unshared.
- *
- * If an error occurs, and the object has been duplicated, the reference
- * count on the duplicate is decremented so that it is now 0: this dismisses
- * any memory that was allocated by this procedure.
- *
- * If no error occurs, the reference count of the original object is
- * incremented if the object has not been duplicated, and nothing is
- * done to a reference count of the duplicate. Now the reference count
- * of an unduplicated object is 2 (the returned pointer, plus the one
- * stored in the variable). The reference count of a duplicate object
- * is 1, reflecting that the returned pointer is the only active
- * reference. The caller is expected to store the returned value back
- * in the variable and decrement its reference count. (INST_STORE_*
- * does exactly this.)
- *
- * Tcl_LsetList and related functions maintain a linked list of
- * Tcl_Obj's whose string representations must be spoilt by threading
- * via 'ptr2' of the two-pointer internal representation. On entry
- * to Tcl_LsetList, the values of 'ptr2' are immaterial; on exit,
- * the 'ptr2' field of any Tcl_Obj that has been modified is set to
- * NULL.
+ * On entry, the reference count of the variable value does not reflect
+ * any references held on the stack. The first action of this function is
+ * to determine whether the object is shared, and to duplicate it if it
+ * is. The reference count of the duplicate is incremented. At this
+ * point, the reference count will be 1 for either case, so that the
+ * object will appear to be unshared.
+ *
+ * If an error occurs, and the object has been duplicated, the reference
+ * count on the duplicate is decremented so that it is now 0: this
+ * dismisses any memory that was allocated by this function.
+ *
+ * If no error occurs, the reference count of the original object is
+ * incremented if the object has not been duplicated, and nothing is done
+ * to a reference count of the duplicate. Now the reference count of an
+ * unduplicated object is 2 (the returned pointer, plus the one stored in
+ * the variable). The reference count of a duplicate object is 1,
+ * reflecting that the returned pointer is the only active reference. The
+ * caller is expected to store the returned value back in the variable
+ * and decrement its reference count. (INST_STORE_* does exactly this.)
+ *
+ * Surgery is performed on the unshared list value to produce the result.
+ * TclLsetFlat maintains a linked list of Tcl_Obj's whose string
+ * representations must be spoilt by threading via 'ptr2' of the
+ * two-pointer internal representation. On entry to TclLsetFlat, the
+ * values of 'ptr2' are immaterial; on exit, the 'ptr2' field of any
+ * Tcl_Obj that has been modified is set to NULL.
*
*----------------------------------------------------------------------
*/
-Tcl_Obj*
-TclLsetFlat( interp, listPtr, indexCount, indexArray, valuePtr )
- Tcl_Interp* interp; /* Tcl interpreter */
- Tcl_Obj* listPtr; /* Pointer to the list being modified */
- int indexCount; /* Number of index args */
- Tcl_Obj *CONST indexArray[];
- /* Index args */
- Tcl_Obj* valuePtr; /* Value arg to 'lset' */
+Tcl_Obj *
+TclLsetFlat(
+ Tcl_Interp *interp, /* Tcl interpreter. */
+ Tcl_Obj *listPtr, /* Pointer to the list being modified. */
+ int indexCount, /* Number of index args. */
+ Tcl_Obj *const indexArray[],
+ /* Index args. */
+ Tcl_Obj *valuePtr) /* Value arg to 'lset'. */
{
-
- int duplicated; /* Flag == 1 if the obj has been
- * duplicated, 0 otherwise */
- Tcl_Obj* retValuePtr; /* Pointer to the list to be returned */
-
- int elemCount; /* Length of one sublist being changed */
- Tcl_Obj** elemPtrs; /* Pointers to the elements of a sublist */
-
- Tcl_Obj* subListPtr; /* Pointer to the current sublist */
-
- int index; /* Index of the element to replace in the
- * current sublist */
- Tcl_Obj* chainPtr; /* Pointer to the enclosing list of
- * the current sublist. */
-
- int result; /* Status return from library calls */
-
-
-
- int i;
+ int index, result;
+ Tcl_Obj *subListPtr, *retValuePtr, *chainPtr;
/*
- * If there are no indices, then simply return the new value,
- * counting the returned pointer as a reference
+ * If there are no indices, simply return the new value.
+ * (Without indices, [lset] is a synonym for [set].
*/
- if ( indexCount == 0 ) {
- Tcl_IncrRefCount( valuePtr );
+ if (indexCount == 0) {
+ Tcl_IncrRefCount(valuePtr);
return valuePtr;
}
/*
- * If the list is shared, make a private copy.
+ * If the list is shared, make a copy we can modify (copy-on-write).
+ * We use Tcl_DuplicateObj() instead of TclListObjCopy() for a few
+ * reasons: 1) we have not yet confirmed listPtr is actually a list;
+ * 2) We make a verbatim copy of any existing string rep, and when
+ * we combine that with the delayed invalidation of string reps of
+ * modified Tcl_Obj's implemented below, the outcome is that any
+ * error condition that causes this routine to return NULL, will
+ * leave the string rep of listPtr and all elements to be unchanged.
*/
- if ( Tcl_IsShared( listPtr ) ) {
- duplicated = 1;
- listPtr = Tcl_DuplicateObj( listPtr );
- Tcl_IncrRefCount( listPtr );
- } else {
- duplicated = 0;
- }
+ subListPtr = Tcl_IsShared(listPtr) ? Tcl_DuplicateObj(listPtr) : listPtr;
/*
* Anchor the linked list of Tcl_Obj's whose string reps must be
* invalidated if the operation succeeds.
*/
- retValuePtr = listPtr;
+ retValuePtr = subListPtr;
chainPtr = NULL;
/*
- * Handle each index arg by diving into the appropriate sublist
+ * Loop through all the index arguments, and for each one dive
+ * into the appropriate sublist.
*/
- for ( i = 0; ; ++i ) {
-
- /*
- * Take the sublist apart.
- */
+ do {
+ int elemCount;
+ Tcl_Obj *parentList, **elemPtrs;
- result = Tcl_ListObjGetElements( interp, listPtr,
- &elemCount, &elemPtrs );
- if ( result != TCL_OK ) {
+ /* Check for the possible error conditions... */
+ result = TCL_ERROR;
+ if (TclListObjGetElements(interp, subListPtr, &elemCount, &elemPtrs)
+ != TCL_OK) {
+ /* ...the sublist we're indexing into isn't a list at all. */
break;
}
- listPtr->internalRep.twoPtrValue.ptr2 = (VOID *) chainPtr;
/*
- * Determine the index of the requested element.
+ * WARNING: the macro TclGetIntForIndexM is not safe for
+ * post-increments, avoid '*indexArray++' here.
*/
-
- result = TclGetIntForIndex( interp, indexArray[ i ],
- (elemCount - 1), &index );
- if ( result != TCL_OK ) {
- break;
- }
- /*
- * Check that the index is in range.
- */
-
- if ( ( index < 0 ) || ( index >= elemCount ) ) {
- Tcl_SetObjResult( interp,
- Tcl_NewStringObj( "list index out of range",
- -1 ) );
- result = TCL_ERROR;
+ if (TclGetIntForIndexM(interp, *indexArray, elemCount - 1, &index)
+ != TCL_OK) {
+ /* ...the index we're trying to use isn't an index at all. */
+ indexArray++;
break;
}
+ indexArray++;
- /*
- * Break the loop after extracting the innermost sublist
- */
-
- if ( i >= indexCount-1 ) {
- result = TCL_OK;
+ if (index < 0 || index >= elemCount) {
+ /* ...the index points outside the sublist. */
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("list index out of range", -1));
+ }
break;
}
-
+
/*
- * Extract the appropriate sublist, and make sure that it is unshared.
+ * No error conditions. As long as we're not yet on the last
+ * index, determine the next sublist for the next pass through
+ * the loop, and take steps to make sure it is an unshared copy,
+ * as we intend to modify it.
*/
- subListPtr = elemPtrs[ index ];
- if ( Tcl_IsShared( subListPtr ) ) {
- subListPtr = Tcl_DuplicateObj( subListPtr );
- result = TclListObjSetElement( interp, listPtr, index,
- subListPtr );
- if ( result != TCL_OK ) {
- /*
- * We actually shouldn't be able to get here.
- * If we do, it would result in leaking subListPtr,
- * but everything's been validated already; the error
- * exit from TclListObjSetElement should never happen.
- */
- break;
+ result = TCL_OK;
+ if (--indexCount) {
+ parentList = subListPtr;
+ subListPtr = elemPtrs[index];
+ if (Tcl_IsShared(subListPtr)) {
+ subListPtr = Tcl_DuplicateObj(subListPtr);
}
- }
- /*
- * Chain the current sublist onto the linked list of Tcl_Obj's
- * whose string reps must be spoilt.
- */
+ /*
+ * Replace the original elemPtr[index] in parentList with a copy
+ * we know to be unshared. This call will also deal with the
+ * situation where parentList shares its intrep with other
+ * Tcl_Obj's. Dealing with the shared intrep case can cause
+ * subListPtr to become shared again, so detect that case and
+ * make and store another copy.
+ */
- chainPtr = listPtr;
- listPtr = subListPtr;
+ TclListObjSetElement(NULL, parentList, index, subListPtr);
+ if (Tcl_IsShared(subListPtr)) {
+ subListPtr = Tcl_DuplicateObj(subListPtr);
+ TclListObjSetElement(NULL, parentList, index, subListPtr);
+ }
- }
+ /*
+ * The TclListObjSetElement() calls do not spoil the string
+ * rep of parentList, and that's fine for now, since all we've
+ * done so far is replace a list element with an unshared copy.
+ * The list value remains the same, so the string rep. is still
+ * valid, and unchanged, which is good because if this whole
+ * routine returns NULL, we'd like to leave no change to the
+ * value of the lset variable. Later on, when we set valuePtr
+ * in its proper place, then all containing lists will have
+ * their values changed, and will need their string reps spoiled.
+ * We maintain a list of all those Tcl_Obj's (via a little intrep
+ * surgery) so we can spoil them at that time.
+ */
- /* Store the result in the list element */
+ parentList->internalRep.twoPtrValue.ptr2 = (void *) chainPtr;
+ chainPtr = parentList;
+ }
+ } while (indexCount > 0);
- if ( result == TCL_OK ) {
- result = TclListObjSetElement( interp, listPtr, index, valuePtr );
- }
+ /*
+ * Either we've detected and error condition, and exited the loop
+ * with result == TCL_ERROR, or we've successfully reached the last
+ * index, and we're ready to store valuePtr. In either case, we
+ * need to clean up our string spoiling list of Tcl_Obj's.
+ */
- if ( result == TCL_OK ) {
+ while (chainPtr) {
+ Tcl_Obj *objPtr = chainPtr;
- listPtr->internalRep.twoPtrValue.ptr2 = (VOID *) chainPtr;
+ if (result == TCL_OK) {
- /* Spoil all the string reps */
-
- while ( listPtr != NULL ) {
- subListPtr = (Tcl_Obj *) listPtr->internalRep.twoPtrValue.ptr2;
- Tcl_InvalidateStringRep( listPtr );
- listPtr->internalRep.twoPtrValue.ptr2 = NULL;
- listPtr = subListPtr;
- }
+ /*
+ * We're going to store valuePtr, so spoil string reps
+ * of all containing lists.
+ */
- /* Return the new list if everything worked. */
-
- if ( !duplicated ) {
- Tcl_IncrRefCount( retValuePtr );
+ Tcl_InvalidateStringRep(objPtr);
}
- return retValuePtr;
- }
- /* Clean up the one dangling reference otherwise */
+ /* Clear away our intrep surgery mess */
+ chainPtr = (Tcl_Obj *) objPtr->internalRep.twoPtrValue.ptr2;
+ objPtr->internalRep.twoPtrValue.ptr2 = NULL;
+ }
- if ( duplicated ) {
- Tcl_DecrRefCount( retValuePtr );
+ if (result != TCL_OK) {
+ /*
+ * Error return; message is already in interp. Clean up
+ * any excess memory.
+ */
+ if (retValuePtr != listPtr) {
+ Tcl_DecrRefCount(retValuePtr);
+ }
+ return NULL;
}
- return NULL;
+ /* Store valuePtr in proper sublist and return */
+ TclListObjSetElement(NULL, subListPtr, index, valuePtr);
+ Tcl_InvalidateStringRep(subListPtr);
+ Tcl_IncrRefCount(retValuePtr);
+ return retValuePtr;
}
/*
@@ -1261,86 +1462,125 @@ TclLsetFlat( interp, listPtr, indexCount, indexArray, valuePtr )
* Set a single element of a list to a specified value
*
* Results:
- *
- * The return value is normally TCL_OK. If listPtr does not
- * refer to a list object and cannot be converted to one, TCL_ERROR
- * is returned and an error message will be left in the interpreter
- * result if interp is not NULL. Similarly, if index designates
- * an element outside the range [0..listLength-1], where
- * listLength is the count of elements in the list object designated
- * by listPtr, TCL_ERROR is returned and an error message is left
- * in the interpreter result.
+ * The return value is normally TCL_OK. If listPtr does not refer to a
+ * list object and cannot be converted to one, TCL_ERROR is returned and
+ * an error message will be left in the interpreter result if interp is
+ * not NULL. Similarly, if index designates an element outside the range
+ * [0..listLength-1], where listLength is the count of elements in the
+ * list object designated by listPtr, TCL_ERROR is returned and an error
+ * message is left in the interpreter result.
*
* Side effects:
+ * Tcl_Panic if listPtr designates a shared object. Otherwise, attempts
+ * to convert it to a list with a non-shared internal rep. Decrements the
+ * ref count of the object at the specified index within the list,
+ * replaces with the object designated by valuePtr, and increments the
+ * ref count of the replacement object.
*
- * Panics if listPtr designates a shared object. Otherwise, attempts
- * to convert it to a list. Decrements the ref count of the object
- * at the specified index within the list, replaces with the
- * object designated by valuePtr, and increments the ref count
- * of the replacement object.
- *
- * It is the caller's responsibility to invalidate the string
- * representation of the object.
+ * It is the caller's responsibility to invalidate the string
+ * representation of the object.
*
*----------------------------------------------------------------------
*/
int
-TclListObjSetElement( interp, listPtr, index, valuePtr )
- Tcl_Interp* interp; /* Tcl interpreter; used for error reporting
- * if not NULL */
- Tcl_Obj* listPtr; /* List object in which element should be
- * stored */
- int index; /* Index of element to store */
- Tcl_Obj* valuePtr; /* Tcl object to store in the designated
- * list element */
+TclListObjSetElement(
+ Tcl_Interp *interp, /* Tcl interpreter; used for error reporting
+ * if not NULL. */
+ Tcl_Obj *listPtr, /* List object in which element should be
+ * stored. */
+ int index, /* Index of element to store. */
+ Tcl_Obj *valuePtr) /* Tcl object to store in the designated list
+ * element. */
{
- int result; /* Return value from this function */
- List* listRepPtr; /* Internal representation of the list
- * being modified */
- Tcl_Obj** elemPtrs; /* Pointers to elements of the list */
- int elemCount; /* Number of elements in the list */
+ List *listRepPtr; /* Internal representation of the list being
+ * modified. */
+ Tcl_Obj **elemPtrs; /* Pointers to elements of the list. */
+ int elemCount; /* Number of elements in the list. */
- /* Ensure that the listPtr parameter designates an unshared list */
+ /*
+ * Ensure that the listPtr parameter designates an unshared list.
+ */
- if ( Tcl_IsShared( listPtr ) ) {
- panic( "Tcl_ListObjSetElement called with shared object" );
+ if (Tcl_IsShared(listPtr)) {
+ Tcl_Panic("%s called with shared object", "TclListObjSetElement");
}
- if ( listPtr->typePtr != &tclListType ) {
- result = SetListFromAny( interp, listPtr );
- if ( result != TCL_OK ) {
+ if (listPtr->typePtr != &tclListType) {
+ int result;
+
+ if (listPtr->bytes == tclEmptyStringRep) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("list index out of range", -1));
+ }
+ return TCL_ERROR;
+ }
+ result = SetListFromAny(interp, listPtr);
+ if (result != TCL_OK) {
return result;
}
}
- listRepPtr = (List*) listPtr->internalRep.twoPtrValue.ptr1;
- elemPtrs = listRepPtr->elements;
+
+ listRepPtr = ListRepPtr(listPtr);
elemCount = listRepPtr->elemCount;
+ elemPtrs = &listRepPtr->elements;
+
+ /*
+ * Ensure that the index is in bounds.
+ */
+
+ if (index<0 || index>=elemCount) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("list index out of range", -1));
+ }
+ return TCL_ERROR;
+ }
+
+ /*
+ * If the internal rep is shared, replace it with an unshared copy.
+ */
- /* Ensure that the index is in bounds */
+ if (listRepPtr->refCount > 1) {
+ List *oldListRepPtr = listRepPtr;
+ Tcl_Obj **oldElemPtrs = elemPtrs;
+ int i;
- if ( index < 0 || index >= elemCount ) {
- if ( interp != NULL ) {
- Tcl_SetObjResult( interp,
- Tcl_NewStringObj( "list index out of range",
- -1 ) );
+ listRepPtr = AttemptNewList(interp, listRepPtr->maxElemCount, NULL);
+ if (listRepPtr == NULL) {
return TCL_ERROR;
}
+ listRepPtr->canonicalFlag = oldListRepPtr->canonicalFlag;
+ elemPtrs = &listRepPtr->elements;
+ for (i=0; i < elemCount; i++) {
+ elemPtrs[i] = oldElemPtrs[i];
+ Tcl_IncrRefCount(elemPtrs[i]);
+ }
+ listRepPtr->refCount++;
+ listRepPtr->elemCount = elemCount;
+ listPtr->internalRep.twoPtrValue.ptr1 = (void *) listRepPtr;
+ oldListRepPtr->refCount--;
}
- /* Add a reference to the new list element */
+ /*
+ * Add a reference to the new list element.
+ */
- Tcl_IncrRefCount( valuePtr );
+ Tcl_IncrRefCount(valuePtr);
- /* Remove a reference from the old list element */
+ /*
+ * Remove a reference from the old list element.
+ */
- Tcl_DecrRefCount( elemPtrs[ index ] );
+ Tcl_DecrRefCount(elemPtrs[index]);
- /* Stash the new object in the list */
+ /*
+ * Stash the new object in the list.
+ */
- elemPtrs[ index ] = valuePtr;
+ elemPtrs[index] = valuePtr;
return TCL_OK;
-
}
/*
@@ -1356,31 +1596,31 @@ TclListObjSetElement( interp, listPtr, index, valuePtr )
*
* Side effects:
* Frees listPtr's List* internal representation and sets listPtr's
- * internalRep.twoPtrValue.ptr1 to NULL. Decrements the ref counts
- * of all element objects, which may free them.
+ * internalRep.twoPtrValue.ptr1 to NULL. Decrements the ref counts of all
+ * element objects, which may free them.
*
*----------------------------------------------------------------------
*/
static void
-FreeListInternalRep(listPtr)
- Tcl_Obj *listPtr; /* List object with internal rep to free. */
+FreeListInternalRep(
+ Tcl_Obj *listPtr) /* List object with internal rep to free. */
{
- register List *listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
- register Tcl_Obj **elemPtrs = listRepPtr->elements;
- register Tcl_Obj *objPtr;
- int numElems = listRepPtr->elemCount;
- int i;
-
- for (i = 0; i < numElems; i++) {
- objPtr = elemPtrs[i];
- Tcl_DecrRefCount(objPtr);
+ List *listRepPtr = ListRepPtr(listPtr);
+
+ if (--listRepPtr->refCount <= 0) {
+ Tcl_Obj **elemPtrs = &listRepPtr->elements;
+ int i, numElems = listRepPtr->elemCount;
+
+ for (i = 0; i < numElems; i++) {
+ Tcl_DecrRefCount(elemPtrs[i]);
+ }
+ ckfree((char *) listRepPtr);
}
- ckfree((char *) elemPtrs);
- ckfree((char *) listRepPtr);
listPtr->internalRep.twoPtrValue.ptr1 = NULL;
listPtr->internalRep.twoPtrValue.ptr2 = NULL;
+ listPtr->typePtr = NULL;
}
/*
@@ -1388,57 +1628,26 @@ FreeListInternalRep(listPtr)
*
* DupListInternalRep --
*
- * Initialize the internal representation of a list Tcl_Obj to a
- * copy of the internal representation of an existing list object.
+ * Initialize the internal representation of a list Tcl_Obj to share the
+ * internal representation of an existing list object.
*
* Results:
* None.
*
* Side effects:
- * "srcPtr"s list internal rep pointer should not be NULL and we assume
- * it is not NULL. We set "copyPtr"s internal rep to a pointer to a
- * newly allocated List structure that, in turn, points to "srcPtr"s
- * element objects. Those element objects are not actually copied but
- * are shared between "srcPtr" and "copyPtr". The ref count of each
- * element object is incremented.
+ * The reference count of the List internal rep is incremented.
*
*----------------------------------------------------------------------
*/
static void
-DupListInternalRep(srcPtr, copyPtr)
- Tcl_Obj *srcPtr; /* Object with internal rep to copy. */
- Tcl_Obj *copyPtr; /* Object with internal rep to set. */
+DupListInternalRep(
+ Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
+ Tcl_Obj *copyPtr) /* Object with internal rep to set. */
{
- List *srcListRepPtr = (List *) srcPtr->internalRep.twoPtrValue.ptr1;
- int numElems = srcListRepPtr->elemCount;
- int maxElems = srcListRepPtr->maxElemCount;
- register Tcl_Obj **srcElemPtrs = srcListRepPtr->elements;
- register Tcl_Obj **copyElemPtrs;
- register List *copyListRepPtr;
- int i;
+ List *listRepPtr = ListRepPtr(srcPtr);
- /*
- * Allocate a new List structure that points to "srcPtr"s element
- * objects. Increment the ref counts for those (now shared) element
- * objects.
- */
-
- copyElemPtrs = (Tcl_Obj **)
- ckalloc((unsigned) maxElems * sizeof(Tcl_Obj *));
- for (i = 0; i < numElems; i++) {
- copyElemPtrs[i] = srcElemPtrs[i];
- Tcl_IncrRefCount(copyElemPtrs[i]);
- }
-
- copyListRepPtr = (List *) ckalloc(sizeof(List));
- copyListRepPtr->maxElemCount = maxElems;
- copyListRepPtr->elemCount = numElems;
- copyListRepPtr->elements = copyElemPtrs;
-
- copyPtr->internalRep.twoPtrValue.ptr1 = (VOID *) copyListRepPtr;
- copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
- copyPtr->typePtr = &tclListType;
+ ListSetIntRep(copyPtr, listRepPtr);
}
/*
@@ -1446,8 +1655,7 @@ DupListInternalRep(srcPtr, copyPtr)
*
* SetListFromAny --
*
- * Attempt to generate a list internal form for the Tcl object
- * "objPtr".
+ * Attempt to generate a list internal form for the Tcl object "objPtr".
*
* Results:
* The return value is TCL_OK or TCL_ERROR. If an error occurs during
@@ -1462,110 +1670,113 @@ DupListInternalRep(srcPtr, copyPtr)
*/
static int
-SetListFromAny(interp, objPtr)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- Tcl_Obj *objPtr; /* The object to convert. */
+SetListFromAny(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tcl_Obj *objPtr) /* The object to convert. */
{
- Tcl_ObjType *oldTypePtr = objPtr->typePtr;
- char *string, *s;
- CONST char *elemStart, *nextElem;
- int lenRemain, length, estCount, elemSize, hasBrace, i, j, result;
- char *limit; /* Points just after string's last byte. */
- register CONST char *p;
- register Tcl_Obj **elemPtrs;
- register Tcl_Obj *elemPtr;
List *listRepPtr;
+ Tcl_Obj **elemPtrs;
/*
- * Get the string representation. Make it up-to-date if necessary.
+ * Dictionaries are a special case; they have a string representation such
+ * that *all* valid dictionaries are valid lists. Hence we can convert
+ * more directly. Only do this when there's no existing string rep; if
+ * there is, it is the string rep that's authoritative (because it could
+ * describe duplicate keys).
*/
- string = Tcl_GetStringFromObj(objPtr, &length);
+ if (objPtr->typePtr == &tclDictType && !objPtr->bytes) {
+ Tcl_Obj *keyPtr, *valuePtr;
+ Tcl_DictSearch search;
+ int done, size;
- /*
- * Parse the string into separate string objects, and create a List
- * structure that points to the element string objects. We use a
- * modified version of Tcl_SplitList's implementation to avoid one
- * malloc and a string copy for each list element. First, estimate the
- * number of elements by counting the number of space characters in the
- * list.
- */
+ /*
+ * Create the new list representation. Note that we do not need to do
+ * anything with the string representation as the transformation (and
+ * the reverse back to a dictionary) are both order-preserving. Also
+ * note that since we know we've got a valid dictionary (by
+ * representation) we also know that fetching the size of the
+ * dictionary or iterating over it will not fail.
+ */
- limit = (string + length);
- estCount = 1;
- for (p = string; p < limit; p++) {
- if (isspace(UCHAR(*p))) { /* INTL: ISO space. */
- estCount++;
+ Tcl_DictObjSize(NULL, objPtr, &size);
+ listRepPtr = AttemptNewList(interp, size > 0 ? 2*size : 1, NULL);
+ if (!listRepPtr) {
+ return TCL_ERROR;
}
- }
+ listRepPtr->elemCount = 2 * size;
- /*
- * Allocate a new List structure with enough room for "estCount"
- * elements. Each element is a pointer to a Tcl_Obj with the appropriate
- * string rep. The initial "estCount" elements are set using the
- * corresponding "argv" strings.
- */
+ /*
+ * Populate the list representation.
+ */
- elemPtrs = (Tcl_Obj **)
- ckalloc((unsigned) (estCount * sizeof(Tcl_Obj *)));
- for (p = string, lenRemain = length, i = 0;
- lenRemain > 0;
- p = nextElem, lenRemain = (limit - nextElem), i++) {
- result = TclFindElement(interp, p, lenRemain, &elemStart, &nextElem,
- &elemSize, &hasBrace);
- if (result != TCL_OK) {
- for (j = 0; j < i; j++) {
- elemPtr = elemPtrs[j];
- Tcl_DecrRefCount(elemPtr);
- }
- ckfree((char *) elemPtrs);
- return result;
- }
- if (elemStart >= limit) {
- break;
- }
- if (i > estCount) {
- panic("SetListFromAny: bad size estimate for list");
+ elemPtrs = &listRepPtr->elements;
+ Tcl_DictObjFirst(NULL, objPtr, &search, &keyPtr, &valuePtr, &done);
+ while (!done) {
+ *elemPtrs++ = keyPtr;
+ *elemPtrs++ = valuePtr;
+ Tcl_IncrRefCount(keyPtr);
+ Tcl_IncrRefCount(valuePtr);
+ Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done);
}
+ } else {
+ int estCount, length;
+ const char *limit, *nextElem = TclGetStringFromObj(objPtr, &length);
/*
- * Allocate a Tcl object for the element and initialize it from the
- * "elemSize" bytes starting at "elemStart".
+ * Allocate enough space to hold a (Tcl_Obj *) for each
+ * (possible) list element.
*/
- s = ckalloc((unsigned) elemSize + 1);
- if (hasBrace) {
- memcpy((VOID *) s, (VOID *) elemStart, (size_t) elemSize);
- s[elemSize] = 0;
- } else {
- elemSize = TclCopyAndCollapse(elemSize, elemStart, s);
+ estCount = TclMaxListLength(nextElem, length, &limit);
+ estCount += (estCount == 0); /* Smallest List struct holds 1 element. */
+ listRepPtr = AttemptNewList(interp, estCount, NULL);
+ if (listRepPtr == NULL) {
+ return TCL_ERROR;
+ }
+ elemPtrs = &listRepPtr->elements;
+
+ /* Each iteration, parse and store a list element */
+ while (nextElem < limit) {
+ const char *elemStart;
+ int elemSize, literal;
+
+ if (TCL_OK != TclFindElement(interp, nextElem, (limit - nextElem),
+ &elemStart, &nextElem, &elemSize, &literal)) {
+ while (--elemPtrs >= &listRepPtr->elements) {
+ Tcl_DecrRefCount(*elemPtrs);
+ }
+ ckfree((char *) listRepPtr);
+ return TCL_ERROR;
+ }
+ if (elemStart == limit) {
+ break;
+ }
+
+ /* TODO: replace panic with error on alloc failure? */
+ if (literal) {
+ TclNewStringObj(*elemPtrs, elemStart, elemSize);
+ } else {
+ TclNewObj(*elemPtrs);
+ (*elemPtrs)->bytes = ckalloc((unsigned) elemSize + 1);
+ (*elemPtrs)->length = TclCopyAndCollapse(elemSize, elemStart,
+ (*elemPtrs)->bytes);
+ }
+
+ Tcl_IncrRefCount(*elemPtrs++);/* Since list now holds ref to it. */
}
-
- TclNewObj(elemPtr);
- elemPtr->bytes = s;
- elemPtr->length = elemSize;
- elemPtrs[i] = elemPtr;
- Tcl_IncrRefCount(elemPtr); /* since list now holds ref to it */
- }
- listRepPtr = (List *) ckalloc(sizeof(List));
- listRepPtr->maxElemCount = estCount;
- listRepPtr->elemCount = i;
- listRepPtr->elements = elemPtrs;
+ listRepPtr->elemCount = elemPtrs - &listRepPtr->elements;
+ }
/*
- * Free the old internalRep before setting the new one. We do this as
- * late as possible to allow the conversion code, in particular
+ * Free the old internalRep before setting the new one. We do this as late
+ * as possible to allow the conversion code, in particular
* Tcl_GetStringFromObj, to use that old internalRep.
*/
- if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
- oldTypePtr->freeIntRepProc(objPtr);
- }
-
- objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) listRepPtr;
- objPtr->internalRep.twoPtrValue.ptr2 = NULL;
- objPtr->typePtr = &tclListType;
+ TclFreeIntRep(objPtr);
+ ListSetIntRep(objPtr, listRepPtr);
return TCL_OK;
}
@@ -1574,39 +1785,50 @@ SetListFromAny(interp, objPtr)
*
* UpdateStringOfList --
*
- * Update the string representation for a list object.
- * Note: This procedure does not invalidate an existing old string rep
- * so storage will be lost if this has not already been done.
+ * Update the string representation for a list object. Note: This
+ * function does not invalidate an existing old string rep so storage
+ * will be lost if this has not already been done.
*
* Results:
* None.
*
* Side effects:
- * The object's string is set to a valid string that results from
- * the list-to-string conversion. This string will be empty if the
- * list has no elements. The list internal representation
- * should not be NULL and we assume it is not NULL.
+ * The object's string is set to a valid string that results from the
+ * list-to-string conversion. This string will be empty if the list has
+ * no elements. The list internal representation should not be NULL and
+ * we assume it is not NULL.
*
*----------------------------------------------------------------------
*/
static void
-UpdateStringOfList(listPtr)
- Tcl_Obj *listPtr; /* List object with string rep to update. */
+UpdateStringOfList(
+ Tcl_Obj *listPtr) /* List object with string rep to update. */
{
# define LOCAL_SIZE 20
- int localFlags[LOCAL_SIZE], *flagPtr;
- List *listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
+ int localFlags[LOCAL_SIZE], *flagPtr = NULL;
+ List *listRepPtr = ListRepPtr(listPtr);
int numElems = listRepPtr->elemCount;
- register int i;
+ int i, length, bytesNeeded = 0;
char *elem, *dst;
- int length;
+ Tcl_Obj **elemPtrs;
/*
- * Convert each element of the list to string form and then convert it
- * to proper list element form, adding it to the result buffer.
+ * Mark the list as being canonical; although it will now have a string
+ * rep, it is one we derived through proper "canonical" quoting and so
+ * it's known to be free from nasties relating to [concat] and [eval].
*/
+ listRepPtr->canonicalFlag = 1;
+
+ /* Handle empty list case first, so rest of the routine is simpler */
+
+ if (numElems == 0) {
+ listPtr->bytes = tclEmptyStringRep;
+ listPtr->length = 0;
+ return;
+ }
+
/*
* Pass 1: estimate space, gather flags.
*/
@@ -1614,41 +1836,47 @@ UpdateStringOfList(listPtr)
if (numElems <= LOCAL_SIZE) {
flagPtr = localFlags;
} else {
- flagPtr = (int *) ckalloc((unsigned) numElems*sizeof(int));
+ /* We know numElems <= LIST_MAX, so this is safe. */
+ flagPtr = (int *) ckalloc((unsigned) numElems * sizeof(int));
}
- listPtr->length = 1;
+ elemPtrs = &listRepPtr->elements;
for (i = 0; i < numElems; i++) {
- elem = Tcl_GetStringFromObj(listRepPtr->elements[i], &length);
- listPtr->length += Tcl_ScanCountedElement(elem, length,
- &flagPtr[i]) + 1;
- /*
- * Check for continued sanity. [Bug 1267380]
- */
- if (listPtr->length < 1) {
- Tcl_Panic("string representation size exceeds sane bounds");
+ flagPtr[i] = ( i ? TCL_DONT_QUOTE_HASH : 0 );
+ elem = TclGetStringFromObj(elemPtrs[i], &length);
+ bytesNeeded += TclScanElement(elem, length, flagPtr+i);
+ if (bytesNeeded < 0) {
+ Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
}
}
+ if (bytesNeeded > INT_MAX - numElems + 1) {
+ Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
+ }
+ bytesNeeded += numElems;
/*
* Pass 2: copy into string rep buffer.
*/
- listPtr->bytes = ckalloc((unsigned) listPtr->length);
+ listPtr->length = bytesNeeded - 1;
+ listPtr->bytes = ckalloc((unsigned) bytesNeeded);
dst = listPtr->bytes;
for (i = 0; i < numElems; i++) {
- elem = Tcl_GetStringFromObj(listRepPtr->elements[i], &length);
- dst += Tcl_ConvertCountedElement(elem, length, dst, flagPtr[i]);
- *dst = ' ';
- dst++;
+ flagPtr[i] |= ( i ? TCL_DONT_QUOTE_HASH : 0 );
+ elem = TclGetStringFromObj(elemPtrs[i], &length);
+ dst += TclConvertElement(elem, length, dst, flagPtr[i]);
+ *dst++ = ' ';
}
+ listPtr->bytes[listPtr->length] = '\0';
+
if (flagPtr != localFlags) {
ckfree((char *) flagPtr);
}
- if (dst == listPtr->bytes) {
- *dst = 0;
- } else {
- dst--;
- *dst = 0;
- }
- listPtr->length = dst - listPtr->bytes;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclLiteral.c b/generic/tclLiteral.c
index 0c88303..2c91b82 100644
--- a/generic/tclLiteral.c
+++ b/generic/tclLiteral.c
@@ -1,76 +1,74 @@
-/*
+/*
* tclLiteral.c --
*
- * Implementation of the global and ByteCode-local literal tables
- * used to manage the Tcl objects created for literal values during
- * compilation of Tcl scripts. This implementation borrows heavily
- * from the more general hashtable implementation of Tcl hash tables
- * that appears in tclHash.c.
+ * Implementation of the global and ByteCode-local literal tables used to
+ * manage the Tcl objects created for literal values during compilation
+ * of Tcl scripts. This implementation borrows heavily from the more
+ * general hashtable implementation of Tcl hash tables that appears in
+ * tclHash.c.
*
* Copyright (c) 1997-1998 Sun Microsystems, Inc.
+ * Copyright (c) 2004 by Kevin B. Kenny. All rights reserved.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
#include "tclCompile.h"
-#include "tclPort.h"
+
/*
- * When there are this many entries per bucket, on average, rebuild
- * a literal's hash table to make it larger.
+ * When there are this many entries per bucket, on average, rebuild a
+ * literal's hash table to make it larger.
*/
#define REBUILD_MULTIPLIER 3
/*
- * Procedure prototypes for static procedures in this file:
+ * Function prototypes for static functions in this file:
*/
-static int AddLocalLiteralEntry _ANSI_ARGS_((
- CompileEnv *envPtr, LiteralEntry *globalPtr,
- int localHash));
-static void ExpandLocalLiteralArray _ANSI_ARGS_((
- CompileEnv *envPtr));
-static unsigned int HashString _ANSI_ARGS_((CONST char *bytes,
- int length));
-static void RebuildLiteralTable _ANSI_ARGS_((
- LiteralTable *tablePtr));
+static int AddLocalLiteralEntry(CompileEnv *envPtr,
+ Tcl_Obj *objPtr, int localHash);
+static void ExpandLocalLiteralArray(CompileEnv *envPtr);
+static unsigned int HashString(const char *bytes, int length);
+static void RebuildLiteralTable(LiteralTable *tablePtr);
/*
*----------------------------------------------------------------------
*
* TclInitLiteralTable --
*
- * This procedure is called to initialize the fields of a literal table
+ * This function is called to initialize the fields of a literal table
* structure for either an interpreter or a compilation's CompileEnv
* structure.
*
* Results:
* None.
*
- * Side effects:
+ * Side effects:
* The literal table is made ready for use.
*
*----------------------------------------------------------------------
*/
void
-TclInitLiteralTable(tablePtr)
- register LiteralTable *tablePtr; /* Pointer to table structure, which
- * is supplied by the caller. */
+TclInitLiteralTable(
+ register LiteralTable *tablePtr)
+ /* Pointer to table structure, which is
+ * supplied by the caller. */
{
-#if (TCL_SMALL_HASH_TABLE != 4)
- panic("TclInitLiteralTable: TCL_SMALL_HASH_TABLE is %d, not 4\n",
+#if (TCL_SMALL_HASH_TABLE != 4)
+ Tcl_Panic("TclInitLiteralTable: TCL_SMALL_HASH_TABLE is %d, not 4",
TCL_SMALL_HASH_TABLE);
#endif
-
+
tablePtr->buckets = tablePtr->staticBuckets;
tablePtr->staticBuckets[0] = tablePtr->staticBuckets[1] = 0;
tablePtr->staticBuckets[2] = tablePtr->staticBuckets[3] = 0;
tablePtr->numBuckets = TCL_SMALL_HASH_TABLE;
tablePtr->numEntries = 0;
- tablePtr->rebuildSize = TCL_SMALL_HASH_TABLE*REBUILD_MULTIPLIER;
+ tablePtr->rebuildSize = TCL_SMALL_HASH_TABLE * REBUILD_MULTIPLIER;
tablePtr->mask = 3;
}
@@ -79,49 +77,58 @@ TclInitLiteralTable(tablePtr)
*
* TclDeleteLiteralTable --
*
- * This procedure frees up everything associated with a literal table
- * except for the table's structure itself.
+ * This function frees up everything associated with a literal table
+ * except for the table's structure itself. It is called when the
+ * interpreter is deleted.
*
* Results:
* None.
*
* Side effects:
- * Each literal in the table is released: i.e., its reference count
- * in the global literal table is decremented and, if it becomes zero,
- * the literal is freed. In addition, the table's bucket array is
- * freed.
+ * Each literal in the table is released: i.e., its reference count in
+ * the global literal table is decremented and, if it becomes zero, the
+ * literal is freed. In addition, the table's bucket array is freed.
*
*----------------------------------------------------------------------
*/
void
-TclDeleteLiteralTable(interp, tablePtr)
- Tcl_Interp *interp; /* Interpreter containing shared literals
+TclDeleteLiteralTable(
+ Tcl_Interp *interp, /* Interpreter containing shared literals
* referenced by the table to delete. */
- LiteralTable *tablePtr; /* Points to the literal table to delete. */
+ LiteralTable *tablePtr) /* Points to the literal table to delete. */
{
- LiteralEntry *entryPtr;
- int i, start;
+ LiteralEntry *entryPtr, *nextPtr;
+ Tcl_Obj *objPtr;
+ int i;
/*
- * Release remaining literals in the table. Note that releasing a
- * literal might release other literals, modifying the table, so we
- * restart the search from the bucket chain we last found an entry.
+ * Release remaining literals in the table. Note that releasing a literal
+ * might release other literals, modifying the table, so we restart the
+ * search from the bucket chain we last found an entry.
*/
#ifdef TCL_COMPILE_DEBUG
TclVerifyGlobalLiteralTable((Interp *) interp);
#endif /*TCL_COMPILE_DEBUG*/
- start = 0;
- while (tablePtr->numEntries > 0) {
- for (i = start; i < tablePtr->numBuckets; i++) {
- entryPtr = tablePtr->buckets[i];
- if (entryPtr != NULL) {
- TclReleaseLiteral(interp, entryPtr->objPtr);
- start = i;
- break;
- }
+ /*
+ * We used to call TclReleaseLiteral for each literal in the table, which
+ * is rather inefficient as it causes one lookup-by-hash for each
+ * reference to the literal. We now rely at interp-deletion on each
+ * bytecode object to release its references to the literal Tcl_Obj
+ * without requiring that it updates the global table itself, and deal
+ * here only with the table.
+ */
+
+ for (i=0 ; i<tablePtr->numBuckets ; i++) {
+ entryPtr = tablePtr->buckets[i];
+ while (entryPtr != NULL) {
+ objPtr = entryPtr->objPtr;
+ TclDecrRefCount(objPtr);
+ nextPtr = entryPtr->nextPtr;
+ ckfree((char *) entryPtr);
+ entryPtr = nextPtr;
}
}
@@ -137,199 +144,266 @@ TclDeleteLiteralTable(interp, tablePtr)
/*
*----------------------------------------------------------------------
*
- * TclRegisterLiteral --
+ * TclCreateLiteral --
*
- * Find, or if necessary create, an object in a CompileEnv literal
- * array that has a string representation matching the argument string.
+ * Find, or if necessary create, an object in the interpreter's literal
+ * table that has a string representation matching the argument
+ * string. If nsPtr!=NULL then only literals stored for the namespace are
+ * considered.
*
* Results:
- * The index in the CompileEnv's literal array that references a
- * shared literal matching the string. The object is created if
- * necessary.
+ * The literal object. If it was created in this call *newPtr is set to
+ * 1, else 0. NULL is returned if newPtr==NULL and no literal is found.
*
* Side effects:
- * To maximize sharing, we look up the string in the interpreter's
- * global literal table. If not found, we create a new shared literal
- * in the global table. We then add a reference to the shared
- * literal in the CompileEnv's literal array.
- *
- * If onHeap is 1, this procedure is given ownership of the string: if
- * an object is created then its string representation is set directly
- * from string, otherwise the string is freed. Typically, a caller sets
- * onHeap 1 if "string" is an already heap-allocated buffer holding the
- * result of backslash substitutions.
+ * Increments the ref count of the global LiteralEntry since the caller
+ * now holds a reference.
+ * If LITERAL_ON_HEAP is set in flags, this function is given ownership
+ * of the string: if an object is created then its string representation
+ * is set directly from string, otherwise the string is freed. Typically,
+ * a caller sets LITERAL_ON_HEAP if "string" is an already heap-allocated
+ * buffer holding the result of backslash substitutions.
*
*----------------------------------------------------------------------
*/
-int
-TclRegisterLiteral(envPtr, bytes, length, onHeap)
- CompileEnv *envPtr; /* Points to the CompileEnv in whose object
- * array an object is found or created. */
- register char *bytes; /* Points to string for which to find or
- * create an object in CompileEnv's object
- * array. */
- int length; /* Number of bytes in the string. If < 0,
- * the string consists of all bytes up to
- * the first null character. */
- int onHeap; /* If 1 then the caller already malloc'd
- * bytes and ownership is passed to this
- * procedure. */
+Tcl_Obj *
+TclCreateLiteral(
+ Interp *iPtr,
+ char *bytes,
+ int length,
+ unsigned int hash, /* The string's hash. If -1, it will be computed here */
+ int *newPtr,
+ Namespace *nsPtr,
+ int flags,
+ LiteralEntry **globalPtrPtr)
{
- Interp *iPtr = envPtr->iPtr;
LiteralTable *globalTablePtr = &(iPtr->literalTable);
- LiteralTable *localTablePtr = &(envPtr->localLitTable);
- register LiteralEntry *globalPtr, *localPtr;
- register Tcl_Obj *objPtr;
- unsigned int hash;
- int localHash, globalHash, objIndex;
- long n;
- char buf[TCL_INTEGER_SPACE];
-
- if (length < 0) {
- length = (bytes? strlen(bytes) : 0);
- }
- hash = HashString(bytes, length);
-
+ LiteralEntry *globalPtr;
+ int globalHash;
+ Tcl_Obj *objPtr;
+
/*
- * Is the literal already in the CompileEnv's local literal array?
- * If so, just return its index.
+ * Is it in the interpreter's global literal table?
*/
- localHash = (hash & localTablePtr->mask);
- for (localPtr = localTablePtr->buckets[localHash];
- localPtr != NULL; localPtr = localPtr->nextPtr) {
- objPtr = localPtr->objPtr;
- if ((objPtr->length == length) && ((length == 0)
- || ((objPtr->bytes[0] == bytes[0])
- && (memcmp(objPtr->bytes, bytes, (unsigned) length)
- == 0)))) {
- if (onHeap) {
- ckfree(bytes);
- }
- objIndex = (localPtr - envPtr->literalArrayPtr);
-#ifdef TCL_COMPILE_DEBUG
- TclVerifyLocalLiteralTable(envPtr);
-#endif /*TCL_COMPILE_DEBUG*/
-
- return objIndex;
- }
+ if (hash == (unsigned int) -1) {
+ hash = HashString(bytes, length);
}
-
- /*
- * The literal is new to this CompileEnv. Is it in the interpreter's
- * global literal table?
- */
-
globalHash = (hash & globalTablePtr->mask);
- for (globalPtr = globalTablePtr->buckets[globalHash];
- globalPtr != NULL; globalPtr = globalPtr->nextPtr) {
+ for (globalPtr=globalTablePtr->buckets[globalHash] ; globalPtr!=NULL;
+ globalPtr = globalPtr->nextPtr) {
objPtr = globalPtr->objPtr;
- if ((objPtr->length == length) && ((length == 0)
+ if ((globalPtr->nsPtr == nsPtr)
+ && (objPtr->length == length) && ((length == 0)
|| ((objPtr->bytes[0] == bytes[0])
- && (memcmp(objPtr->bytes, bytes, (unsigned) length)
- == 0)))) {
+ && (memcmp(objPtr->bytes, bytes, (unsigned) length) == 0)))) {
/*
- * A global literal was found. Add an entry to the CompileEnv's
- * local literal array.
+ * A literal was found: return it
*/
-
- if (onHeap) {
- ckfree(bytes);
+
+ if (newPtr) {
+ *newPtr = 0;
}
- objIndex = AddLocalLiteralEntry(envPtr, globalPtr, localHash);
-#ifdef TCL_COMPILE_DEBUG
- if (globalPtr->refCount < 1) {
- panic("TclRegisterLiteral: global literal \"%.*s\" had bad refCount %d",
- (length>60? 60 : length), bytes,
- globalPtr->refCount);
+ if (globalPtrPtr) {
+ *globalPtrPtr = globalPtr;
}
- TclVerifyLocalLiteralTable(envPtr);
-#endif /*TCL_COMPILE_DEBUG*/
- return objIndex;
+ if (flags & LITERAL_ON_HEAP) {
+ ckfree(bytes);
+ }
+ globalPtr->refCount++;
+ return objPtr;
+ }
+ }
+ if (!newPtr) {
+ if (flags & LITERAL_ON_HEAP) {
+ ckfree(bytes);
}
+ return NULL;
}
/*
* The literal is new to the interpreter. Add it to the global literal
- * table then add an entry to the CompileEnv's local literal array.
- * Convert the object to an integer object if possible.
+ * table.
*/
TclNewObj(objPtr);
Tcl_IncrRefCount(objPtr);
- if (onHeap) {
+ if (flags & LITERAL_ON_HEAP) {
objPtr->bytes = bytes;
objPtr->length = length;
} else {
TclInitStringRep(objPtr, bytes, length);
}
- if (TclLooksLikeInt(bytes, length)) {
- /*
- * From here we use the objPtr, because it is NULL terminated
- */
- if (TclGetLong((Tcl_Interp *) NULL, objPtr->bytes, &n) == TCL_OK) {
- TclFormatInt(buf, n);
- if (strcmp(objPtr->bytes, buf) == 0) {
- objPtr->internalRep.longValue = n;
- objPtr->typePtr = &tclIntType;
- }
- }
- }
-
#ifdef TCL_COMPILE_DEBUG
if (TclLookupLiteralEntry((Tcl_Interp *) iPtr, objPtr) != NULL) {
- panic("TclRegisterLiteral: literal \"%.*s\" found globally but shouldn't be",
- (length>60? 60 : length), bytes);
+ Tcl_Panic("TclRegisterLiteral: literal \"%.*s\" found globally but shouldn't be",
+ (length>60? 60 : length), bytes);
}
#endif
globalPtr = (LiteralEntry *) ckalloc((unsigned) sizeof(LiteralEntry));
globalPtr->objPtr = objPtr;
- globalPtr->refCount = 0;
+ globalPtr->refCount = 1;
+ globalPtr->nsPtr = nsPtr;
globalPtr->nextPtr = globalTablePtr->buckets[globalHash];
globalTablePtr->buckets[globalHash] = globalPtr;
globalTablePtr->numEntries++;
/*
- * If the global literal table has exceeded a decent size, rebuild it
- * with more buckets.
+ * If the global literal table has exceeded a decent size, rebuild it with
+ * more buckets.
*/
if (globalTablePtr->numEntries >= globalTablePtr->rebuildSize) {
RebuildLiteralTable(globalTablePtr);
}
- objIndex = AddLocalLiteralEntry(envPtr, globalPtr, localHash);
#ifdef TCL_COMPILE_DEBUG
TclVerifyGlobalLiteralTable(iPtr);
- TclVerifyLocalLiteralTable(envPtr);
{
LiteralEntry *entryPtr;
int found, i;
+
found = 0;
- for (i = 0; i < globalTablePtr->numBuckets; i++) {
- for (entryPtr = globalTablePtr->buckets[i];
- entryPtr != NULL; entryPtr = entryPtr->nextPtr) {
- if ((entryPtr == globalPtr)
- && (entryPtr->objPtr == objPtr)) {
+ for (i=0 ; i<globalTablePtr->numBuckets ; i++) {
+ for (entryPtr=globalTablePtr->buckets[i]; entryPtr!=NULL ;
+ entryPtr=entryPtr->nextPtr) {
+ if ((entryPtr == globalPtr) && (entryPtr->objPtr == objPtr)) {
found = 1;
}
}
}
if (!found) {
- panic("TclRegisterLiteral: literal \"%.*s\" wasn't global",
- (length>60? 60 : length), bytes);
+ Tcl_Panic("TclRegisterLiteral: literal \"%.*s\" wasn't global",
+ (length>60? 60 : length), bytes);
}
}
#endif /*TCL_COMPILE_DEBUG*/
-#ifdef TCL_COMPILE_STATS
+
+#ifdef TCL_COMPILE_STATS
iPtr->stats.numLiteralsCreated++;
- iPtr->stats.totalLitStringBytes += (double) (length + 1);
+ iPtr->stats.totalLitStringBytes += (double) (length + 1);
iPtr->stats.currentLitStringBytes += (double) (length + 1);
iPtr->stats.literalCount[TclLog2(length)]++;
#endif /*TCL_COMPILE_STATS*/
+
+ if (globalPtrPtr) {
+ *globalPtrPtr = globalPtr;
+ }
+ *newPtr = 1;
+ return objPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclRegisterLiteral --
+ *
+ * Find, or if necessary create, an object in a CompileEnv literal array
+ * that has a string representation matching the argument string.
+ *
+ * Results:
+ * The index in the CompileEnv's literal array that references a shared
+ * literal matching the string. The object is created if necessary.
+ *
+ * Side effects:
+ * To maximize sharing, we look up the string in the interpreter's global
+ * literal table. If not found, we create a new shared literal in the
+ * global table. We then add a reference to the shared literal in the
+ * CompileEnv's literal array.
+ *
+ * If LITERAL_ON_HEAP is set in flags, this function is given ownership
+ * of the string: if an object is created then its string representation
+ * is set directly from string, otherwise the string is freed. Typically,
+ * a caller sets LITERAL_ON_HEAP if "string" is an already heap-allocated
+ * buffer holding the result of backslash substitutions.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclRegisterLiteral(
+ CompileEnv *envPtr, /* Points to the CompileEnv in whose object
+ * array an object is found or created. */
+ register char *bytes, /* Points to string for which to find or
+ * create an object in CompileEnv's object
+ * array. */
+ int length, /* Number of bytes in the string. If < 0, the
+ * string consists of all bytes up to the
+ * first null character. */
+ int flags) /* If LITERAL_ON_HEAP then the caller already
+ * malloc'd bytes and ownership is passed to
+ * this function. If LITERAL_NS_SCOPE then
+ * the literal shouldnot be shared accross
+ * namespaces. */
+{
+ Interp *iPtr = envPtr->iPtr;
+ LiteralTable *localTablePtr = &(envPtr->localLitTable);
+ LiteralEntry *globalPtr, *localPtr;
+ Tcl_Obj *objPtr;
+ unsigned int hash;
+ int localHash, objIndex, new;
+ Namespace *nsPtr;
+
+ if (length < 0) {
+ length = (bytes ? strlen(bytes) : 0);
+ }
+ hash = HashString(bytes, length);
+
+ /*
+ * Is the literal already in the CompileEnv's local literal array? If so,
+ * just return its index.
+ */
+
+ localHash = (hash & localTablePtr->mask);
+ for (localPtr=localTablePtr->buckets[localHash] ; localPtr!=NULL;
+ localPtr = localPtr->nextPtr) {
+ objPtr = localPtr->objPtr;
+ if ((objPtr->length == length) && ((length == 0)
+ || ((objPtr->bytes[0] == bytes[0])
+ && (memcmp(objPtr->bytes, bytes, (unsigned) length) == 0)))) {
+ if (flags & LITERAL_ON_HEAP) {
+ ckfree(bytes);
+ }
+ objIndex = (localPtr - envPtr->literalArrayPtr);
+#ifdef TCL_COMPILE_DEBUG
+ TclVerifyLocalLiteralTable(envPtr);
+#endif /*TCL_COMPILE_DEBUG*/
+
+ return objIndex;
+ }
+ }
+
+ /*
+ * The literal is new to this CompileEnv. Should it be shared accross
+ * namespaces? If it is a fully qualified name, the namespace
+ * specification is not needed to avoid sharing.
+ */
+
+ if ((flags & LITERAL_NS_SCOPE) && iPtr->varFramePtr
+ && ((length <2) || (bytes[0] != ':') || (bytes[1] != ':'))) {
+ nsPtr = iPtr->varFramePtr->nsPtr;
+ } else {
+ nsPtr = NULL;
+ }
+
+ /*
+ * Is it in the interpreter's global literal table? If not, create it.
+ */
+
+ objPtr = TclCreateLiteral(iPtr, bytes, length, hash, &new, nsPtr,
+ flags, &globalPtr);
+ objIndex = AddLocalLiteralEntry(envPtr, objPtr, localHash);
+
+#ifdef TCL_COMPILE_DEBUG
+ if (globalPtr->refCount < 1) {
+ Tcl_Panic("TclRegisterLiteral: global literal \"%.*s\" had bad refCount %d",
+ (length>60? 60 : length), bytes, globalPtr->refCount);
+ }
+ TclVerifyLocalLiteralTable(envPtr);
+#endif /*TCL_COMPILE_DEBUG*/
return objIndex;
}
@@ -339,24 +413,24 @@ TclRegisterLiteral(envPtr, bytes, length, onHeap)
* TclLookupLiteralEntry --
*
* Finds the LiteralEntry that corresponds to a literal Tcl object
- * holding a literal.
+ * holding a literal.
*
* Results:
- * Returns the matching LiteralEntry if found, otherwise NULL.
+ * Returns the matching LiteralEntry if found, otherwise NULL.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
LiteralEntry *
-TclLookupLiteralEntry(interp, objPtr)
- Tcl_Interp *interp; /* Interpreter for which objPtr was created
- * to hold a literal. */
- register Tcl_Obj *objPtr; /* Points to a Tcl object holding a
- * literal that was previously created by a
- * call to TclRegisterLiteral. */
+TclLookupLiteralEntry(
+ Tcl_Interp *interp, /* Interpreter for which objPtr was created to
+ * hold a literal. */
+ register Tcl_Obj *objPtr) /* Points to a Tcl object holding a literal
+ * that was previously created by a call to
+ * TclRegisterLiteral. */
{
Interp *iPtr = (Interp *) interp;
LiteralTable *globalTablePtr = &(iPtr->literalTable);
@@ -364,13 +438,13 @@ TclLookupLiteralEntry(interp, objPtr)
char *bytes;
int length, globalHash;
- bytes = Tcl_GetStringFromObj(objPtr, &length);
+ bytes = TclGetStringFromObj(objPtr, &length);
globalHash = (HashString(bytes, length) & globalTablePtr->mask);
- for (entryPtr = globalTablePtr->buckets[globalHash];
- entryPtr != NULL; entryPtr = entryPtr->nextPtr) {
- if (entryPtr->objPtr == objPtr) {
- return entryPtr;
- }
+ for (entryPtr=globalTablePtr->buckets[globalHash] ; entryPtr!=NULL;
+ entryPtr=entryPtr->nextPtr) {
+ if (entryPtr->objPtr == objPtr) {
+ return entryPtr;
+ }
}
return NULL;
}
@@ -380,10 +454,10 @@ TclLookupLiteralEntry(interp, objPtr)
*
* TclHideLiteral --
*
- * Remove a literal entry from the literal hash tables, leaving it in
- * the literal array so existing references continue to function.
- * This makes it possible to turn a shared literal into a private
- * literal that cannot be shared.
+ * Remove a literal entry from the literal hash tables, leaving it in the
+ * literal array so existing references continue to function. This makes
+ * it possible to turn a shared literal into a private literal that
+ * cannot be shared.
*
* Results:
* None.
@@ -396,13 +470,13 @@ TclLookupLiteralEntry(interp, objPtr)
*/
void
-TclHideLiteral(interp, envPtr, index)
- Tcl_Interp *interp; /* Interpreter for which objPtr was created
- * to hold a literal. */
- register CompileEnv *envPtr; /* Points to CompileEnv whose literal array
- * contains the entry being hidden. */
- int index; /* The index of the entry in the literal
- * array. */
+TclHideLiteral(
+ Tcl_Interp *interp, /* Interpreter for which objPtr was created to
+ * hold a literal. */
+ register CompileEnv *envPtr,/* Points to CompileEnv whose literal array
+ * contains the entry being hidden. */
+ int index) /* The index of the entry in the literal
+ * array. */
{
LiteralEntry **nextPtrPtr, *entryPtr, *lPtr;
LiteralTable *localTablePtr = &(envPtr->localLitTable);
@@ -414,9 +488,9 @@ TclHideLiteral(interp, envPtr, index)
/*
* To avoid unwanted sharing we need to copy the object and remove it from
- * the local and global literal tables. It still has a slot in the literal
- * array so it can be referred to by byte codes, but it will not be matched
- * by literal searches.
+ * the local and global literal tables. It still has a slot in the literal
+ * array so it can be referred to by byte codes, but it will not be
+ * matched by literal searches.
*/
newObjPtr = Tcl_DuplicateObj(lPtr->objPtr);
@@ -424,11 +498,11 @@ TclHideLiteral(interp, envPtr, index)
TclReleaseLiteral(interp, lPtr->objPtr);
lPtr->objPtr = newObjPtr;
- bytes = Tcl_GetStringFromObj(newObjPtr, &length);
+ bytes = TclGetStringFromObj(newObjPtr, &length);
localHash = (HashString(bytes, length) & localTablePtr->mask);
nextPtrPtr = &localTablePtr->buckets[localHash];
- for (entryPtr = *nextPtrPtr; entryPtr != NULL; entryPtr = *nextPtrPtr) {
+ for (entryPtr=*nextPtrPtr ; entryPtr!=NULL ; entryPtr=*nextPtrPtr) {
if (entryPtr == lPtr) {
*nextPtrPtr = lPtr->nextPtr;
lPtr->nextPtr = NULL;
@@ -444,31 +518,30 @@ TclHideLiteral(interp, envPtr, index)
*
* TclAddLiteralObj --
*
- * Add a single literal object to the literal array. This
- * function does not add the literal to the local or global
- * literal tables. The caller is expected to add the entry
- * to whatever tables are appropriate.
+ * Add a single literal object to the literal array. This function does
+ * not add the literal to the local or global literal tables. The caller
+ * is expected to add the entry to whatever tables are appropriate.
*
* Results:
* The index in the CompileEnv's literal array that references the
- * literal. Stores the pointer to the new literal entry in the
- * location referenced by the localPtrPtr argument.
+ * literal. Stores the pointer to the new literal entry in the location
+ * referenced by the localPtrPtr argument.
*
* Side effects:
- * Expands the literal array if necessary. Increments the refcount
- * on the literal object.
+ * Expands the literal array if necessary. Increments the refcount on the
+ * literal object.
*
*----------------------------------------------------------------------
*/
int
-TclAddLiteralObj(envPtr, objPtr, litPtrPtr)
- register CompileEnv *envPtr; /* Points to CompileEnv in whose literal
- * array the object is to be inserted. */
- Tcl_Obj *objPtr; /* The object to insert into the array. */
- LiteralEntry **litPtrPtr; /* The location where the pointer to the
- * new literal entry should be stored.
- * May be NULL. */
+TclAddLiteralObj(
+ register CompileEnv *envPtr,/* Points to CompileEnv in whose literal array
+ * the object is to be inserted. */
+ Tcl_Obj *objPtr, /* The object to insert into the array. */
+ LiteralEntry **litPtrPtr) /* The location where the pointer to the new
+ * literal entry should be stored. May be
+ * NULL. */
{
register LiteralEntry *lPtr;
int objIndex;
@@ -504,27 +577,24 @@ TclAddLiteralObj(envPtr, objPtr, litPtrPtr)
* literal.
*
* Side effects:
- * Increments the ref count of the global LiteralEntry since the
- * CompileEnv now refers to the literal. Expands the literal array
- * if necessary. May rebuild the hash bucket array of the CompileEnv's
- * literal array if it becomes too large.
+ * Expands the literal array if necessary. May rebuild the hash bucket
+ * array of the CompileEnv's literal array if it becomes too large.
*
*----------------------------------------------------------------------
*/
static int
-AddLocalLiteralEntry(envPtr, globalPtr, localHash)
- register CompileEnv *envPtr; /* Points to CompileEnv in whose literal
- * array the object is to be inserted. */
- LiteralEntry *globalPtr; /* Points to the global LiteralEntry for
- * the literal to add to the CompileEnv. */
- int localHash; /* Hash value for the literal's string. */
+AddLocalLiteralEntry(
+ register CompileEnv *envPtr,/* Points to CompileEnv in whose literal array
+ * the object is to be inserted. */
+ Tcl_Obj *objPtr, /* The literal to add to the CompileEnv. */
+ int localHash) /* Hash value for the literal's string. */
{
register LiteralTable *localTablePtr = &(envPtr->localLitTable);
LiteralEntry *localPtr;
int objIndex;
-
- objIndex = TclAddLiteralObj(envPtr, globalPtr->objPtr, &localPtr);
+
+ objIndex = TclAddLiteralObj(envPtr, objPtr, &localPtr);
/*
* Add the literal to the local table.
@@ -534,8 +604,6 @@ AddLocalLiteralEntry(envPtr, globalPtr, localHash)
localTablePtr->buckets[localHash] = localPtr;
localTablePtr->numEntries++;
- globalPtr->refCount++;
-
/*
* If the CompileEnv's local literal table has exceeded a decent size,
* rebuild it with more buckets.
@@ -550,22 +618,25 @@ AddLocalLiteralEntry(envPtr, globalPtr, localHash)
{
char *bytes;
int length, found, i;
+
found = 0;
- for (i = 0; i < localTablePtr->numBuckets; i++) {
- for (localPtr = localTablePtr->buckets[i];
- localPtr != NULL; localPtr = localPtr->nextPtr) {
- if (localPtr->objPtr == globalPtr->objPtr) {
+ for (i=0 ; i<localTablePtr->numBuckets ; i++) {
+ for (localPtr=localTablePtr->buckets[i] ; localPtr!=NULL ;
+ localPtr=localPtr->nextPtr) {
+ if (localPtr->objPtr == objPtr) {
found = 1;
}
}
}
+
if (!found) {
- bytes = Tcl_GetStringFromObj(globalPtr->objPtr, &length);
- panic("AddLocalLiteralEntry: literal \"%.*s\" wasn't found locally",
- (length>60? 60 : length), bytes);
+ bytes = Tcl_GetStringFromObj(objPtr, &length);
+ Tcl_Panic("AddLocalLiteralEntry: literal \"%.*s\" wasn't found locally",
+ (length>60? 60 : length), bytes);
}
}
#endif /*TCL_COMPILE_DEBUG*/
+
return objIndex;
}
@@ -574,72 +645,72 @@ AddLocalLiteralEntry(envPtr, globalPtr, localHash)
*
* ExpandLocalLiteralArray --
*
- * Procedure that uses malloc to allocate more storage for a
- * CompileEnv's local literal array.
+ * Function that uses malloc to allocate more storage for a CompileEnv's
+ * local literal array.
*
* Results:
* None.
*
* Side effects:
- * The literal array in *envPtr is reallocated to a new array of
- * double the size, and if envPtr->mallocedLiteralArray is non-zero
- * the old array is freed. Entries are copied from the old array
- * to the new one. The local literal table is updated to refer to
- * the new entries.
+ * The literal array in *envPtr is reallocated to a new array of double
+ * the size, and if envPtr->mallocedLiteralArray is non-zero the old
+ * array is freed. Entries are copied from the old array to the new one.
+ * The local literal table is updated to refer to the new entries.
*
*----------------------------------------------------------------------
*/
static void
-ExpandLocalLiteralArray(envPtr)
- register CompileEnv *envPtr; /* Points to the CompileEnv whose object
- * array must be enlarged. */
+ExpandLocalLiteralArray(
+ register CompileEnv *envPtr)/* Points to the CompileEnv whose object array
+ * must be enlarged. */
{
/*
- * The current allocated local literal entries are stored between
- * elements 0 and (envPtr->literalArrayNext - 1) [inclusive].
+ * The current allocated local literal entries are stored between elements
+ * 0 and (envPtr->literalArrayNext - 1) [inclusive].
*/
LiteralTable *localTablePtr = &(envPtr->localLitTable);
int currElems = envPtr->literalArrayNext;
size_t currBytes = (currElems * sizeof(LiteralEntry));
- register LiteralEntry *currArrayPtr = envPtr->literalArrayPtr;
- register LiteralEntry *newArrayPtr =
- (LiteralEntry *) ckalloc((unsigned) (2 * currBytes));
+ LiteralEntry *currArrayPtr = envPtr->literalArrayPtr;
+ LiteralEntry *newArrayPtr;
int i;
-
+
+ if (envPtr->mallocedLiteralArray) {
+ newArrayPtr = (LiteralEntry *) ckrealloc(
+ (char *)currArrayPtr, 2 * currBytes);
+ } else {
+ /*
+ * envPtr->literalArrayPtr isn't a ckalloc'd pointer, so we must
+ * code a ckrealloc equivalent for ourselves
+ */
+ newArrayPtr = (LiteralEntry *) ckalloc(2 * currBytes);
+ memcpy(newArrayPtr, currArrayPtr, currBytes);
+ envPtr->mallocedLiteralArray = 1;
+ }
+
/*
- * Copy from the old literal array to the new, then update the local
- * literal table's bucket array.
+ * Update the local literal table's bucket array.
*/
- memcpy((VOID *) newArrayPtr, (VOID *) currArrayPtr, currBytes);
- for (i = 0; i < currElems; i++) {
- if (currArrayPtr[i].nextPtr == NULL) {
- newArrayPtr[i].nextPtr = NULL;
- } else {
- newArrayPtr[i].nextPtr = newArrayPtr
- + (currArrayPtr[i].nextPtr - currArrayPtr);
+ if (currArrayPtr != newArrayPtr) {
+ for (i=0 ; i<currElems ; i++) {
+ if (newArrayPtr[i].nextPtr != NULL) {
+ newArrayPtr[i].nextPtr = newArrayPtr
+ + (newArrayPtr[i].nextPtr - currArrayPtr);
+ }
}
- }
- for (i = 0; i < localTablePtr->numBuckets; i++) {
- if (localTablePtr->buckets[i] != NULL) {
- localTablePtr->buckets[i] = newArrayPtr
- + (localTablePtr->buckets[i] - currArrayPtr);
+ for (i=0 ; i<localTablePtr->numBuckets ; i++) {
+ if (localTablePtr->buckets[i] != NULL) {
+ localTablePtr->buckets[i] = newArrayPtr
+ + (localTablePtr->buckets[i] - currArrayPtr);
+ }
}
}
- /*
- * Free the old literal array if needed, and mark the new literal
- * array as malloced.
- */
-
- if (envPtr->mallocedLiteralArray) {
- ckfree((char *) currArrayPtr);
- }
envPtr->literalArrayPtr = newArrayPtr;
envPtr->literalArrayEnd = (2 * currElems);
- envPtr->mallocedLiteralArray = 1;
}
/*
@@ -647,59 +718,56 @@ ExpandLocalLiteralArray(envPtr)
*
* TclReleaseLiteral --
*
- * This procedure releases a reference to one of the shared Tcl objects
- * that hold literals. It is called to release the literals referenced
- * by a ByteCode that is being destroyed, and it is also called by
+ * This function releases a reference to one of the shared Tcl objects
+ * that hold literals. It is called to release the literals referenced by
+ * a ByteCode that is being destroyed, and it is also called by
* TclDeleteLiteralTable.
*
* Results:
* None.
*
* Side effects:
- * The reference count for the global LiteralTable entry that
- * corresponds to the literal is decremented. If no other reference
- * to a global literal object remains, it is freed.
+ * The reference count for the global LiteralTable entry that corresponds
+ * to the literal is decremented. If no other reference to a global
+ * literal object remains, it is freed.
*
*----------------------------------------------------------------------
*/
void
-TclReleaseLiteral(interp, objPtr)
- Tcl_Interp *interp; /* Interpreter for which objPtr was created
- * to hold a literal. */
- register Tcl_Obj *objPtr; /* Points to a literal object that was
+TclReleaseLiteral(
+ Tcl_Interp *interp, /* Interpreter for which objPtr was created to
+ * hold a literal. */
+ register Tcl_Obj *objPtr) /* Points to a literal object that was
* previously created by a call to
* TclRegisterLiteral. */
{
Interp *iPtr = (Interp *) interp;
LiteralTable *globalTablePtr = &(iPtr->literalTable);
register LiteralEntry *entryPtr, *prevPtr;
- ByteCode* codePtr;
char *bytes;
int length, index;
- bytes = Tcl_GetStringFromObj(objPtr, &length);
+ bytes = TclGetStringFromObj(objPtr, &length);
index = (HashString(bytes, length) & globalTablePtr->mask);
/*
- * Check to see if the object is in the global literal table and
- * remove this reference. The object may not be in the table if
- * it is a hidden local literal.
+ * Check to see if the object is in the global literal table and remove
+ * this reference. The object may not be in the table if it is a hidden
+ * local literal.
*/
- for (prevPtr = NULL, entryPtr = globalTablePtr->buckets[index];
- entryPtr != NULL;
- prevPtr = entryPtr, entryPtr = entryPtr->nextPtr) {
+ for (prevPtr=NULL, entryPtr=globalTablePtr->buckets[index];
+ entryPtr!=NULL ; prevPtr=entryPtr, entryPtr=entryPtr->nextPtr) {
if (entryPtr->objPtr == objPtr) {
entryPtr->refCount--;
/*
- * If the literal is no longer being used by any ByteCode,
- * delete the entry then remove the reference corresponding
- * to the global literal table entry (decrement the ref count
- * of the object).
+ * If the literal is no longer being used by any ByteCode, delete
+ * the entry then remove the reference corresponding to the global
+ * literal table entry (decrement the ref count of the object).
*/
-
+
if (entryPtr->refCount == 0) {
if (prevPtr == NULL) {
globalTablePtr->buckets[index] = entryPtr->nextPtr;
@@ -711,22 +779,6 @@ TclReleaseLiteral(interp, objPtr)
TclDecrRefCount(objPtr);
- /*
- * Check if the LiteralEntry is only being kept alive by
- * a circular reference from a ByteCode stored as its
- * internal rep. In that case, set the ByteCode object array
- * entry NULL to signal to TclCleanupByteCode to not try to
- * release this about to be freed literal again.
- */
-
- if (objPtr->typePtr == &tclByteCodeType) {
- codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
- if ((codePtr->numLitObjects == 1)
- && (codePtr->objArrayPtr[0] == objPtr)) {
- codePtr->objArrayPtr[0] = NULL;
- }
- }
-
#ifdef TCL_COMPILE_STATS
iPtr->stats.currentLitStringBytes -= (double) (length + 1);
#endif /*TCL_COMPILE_STATS*/
@@ -734,10 +786,9 @@ TclReleaseLiteral(interp, objPtr)
break;
}
}
-
+
/*
- * Remove the reference corresponding to the local literal table
- * entry.
+ * Remove the reference corresponding to the local literal table entry.
*/
Tcl_DecrRefCount(objPtr);
@@ -748,12 +799,11 @@ TclReleaseLiteral(interp, objPtr)
*
* HashString --
*
- * Compute a one-word summary of a text string, which can be
- * used to generate a hash index.
+ * Compute a one-word summary of a text string, which can be used to
+ * generate a hash index.
*
* Results:
- * The return value is a one-word summary of the information in
- * string.
+ * The return value is a one-word summary of the information in string.
*
* Side effects:
* None.
@@ -762,33 +812,32 @@ TclReleaseLiteral(interp, objPtr)
*/
static unsigned int
-HashString(bytes, length)
- register CONST char *bytes; /* String for which to compute hash
- * value. */
- int length; /* Number of bytes in the string. */
+HashString(
+ register const char *bytes, /* String for which to compute hash value. */
+ int length) /* Number of bytes in the string. */
{
register unsigned int result;
register int i;
/*
- * I tried a zillion different hash functions and asked many other
- * people for advice. Many people had their own favorite functions,
- * all different, but no-one had much idea why they were good ones.
- * I chose the one below (multiply by 9 and add new character)
- * because of the following reasons:
+ * I tried a zillion different hash functions and asked many other people
+ * for advice. Many people had their own favorite functions, all
+ * different, but no-one had much idea why they were good ones. I chose
+ * the one below (multiply by 9 and add new character) because of the
+ * following reasons:
*
- * 1. Multiplying by 10 is perfect for keys that are decimal strings,
- * and multiplying by 9 is just about as good.
- * 2. Times-9 is (shift-left-3) plus (old). This means that each
- * character's bits hang around in the low-order bits of the
- * hash value for ever, plus they spread fairly rapidly up to
- * the high-order bits to fill out the hash value. This seems
- * works well both for decimal and non-decimal strings.
+ * 1. Multiplying by 10 is perfect for keys that are decimal strings, and
+ * multiplying by 9 is just about as good.
+ * 2. Times-9 is (shift-left-3) plus (old). This means that each
+ * character's bits hang around in the low-order bits of the hash value
+ * for ever, plus they spread fairly rapidly up to the high-order bits
+ * to fill out the hash value. This seems works well both for decimal
+ * and non-decimal strings.
*/
result = 0;
- for (i = 0; i < length; i++) {
- result += (result<<3) + *bytes++;
+ for (i=0 ; i<length ; i++) {
+ result += (result<<3) + bytes[i];
}
return result;
}
@@ -798,9 +847,9 @@ HashString(bytes, length)
*
* RebuildLiteralTable --
*
- * This procedure is invoked when the ratio of entries to hash buckets
- * becomes too large in a local or global literal table. It allocates
- * a larger bucket array and moves the entries into the new buckets.
+ * This function is invoked when the ratio of entries to hash buckets
+ * becomes too large in a local or global literal table. It allocates a
+ * larger bucket array and moves the entries into the new buckets.
*
* Results:
* None.
@@ -812,8 +861,9 @@ HashString(bytes, length)
*/
static void
-RebuildLiteralTable(tablePtr)
- register LiteralTable *tablePtr; /* Local or global table to enlarge. */
+RebuildLiteralTable(
+ register LiteralTable *tablePtr)
+ /* Local or global table to enlarge. */
{
LiteralEntry **oldBuckets;
register LiteralEntry **oldChainPtr, **newChainPtr;
@@ -826,16 +876,15 @@ RebuildLiteralTable(tablePtr)
oldBuckets = tablePtr->buckets;
/*
- * Allocate and initialize the new bucket array, and set up
- * hashing constants for new array size.
+ * Allocate and initialize the new bucket array, and set up hashing
+ * constants for new array size.
*/
tablePtr->numBuckets *= 4;
tablePtr->buckets = (LiteralEntry **) ckalloc((unsigned)
(tablePtr->numBuckets * sizeof(LiteralEntry *)));
- for (count = tablePtr->numBuckets, newChainPtr = tablePtr->buckets;
- count > 0;
- count--, newChainPtr++) {
+ for (count=tablePtr->numBuckets, newChainPtr=tablePtr->buckets;
+ count>0 ; count--, newChainPtr++) {
*newChainPtr = NULL;
}
tablePtr->rebuildSize *= 4;
@@ -845,14 +894,11 @@ RebuildLiteralTable(tablePtr)
* Rehash all of the existing entries into the new bucket array.
*/
- for (oldChainPtr = oldBuckets;
- oldSize > 0;
- oldSize--, oldChainPtr++) {
- for (entryPtr = *oldChainPtr; entryPtr != NULL;
- entryPtr = *oldChainPtr) {
- bytes = Tcl_GetStringFromObj(entryPtr->objPtr, &length);
+ for (oldChainPtr=oldBuckets ; oldSize>0 ; oldSize--,oldChainPtr++) {
+ for (entryPtr=*oldChainPtr ; entryPtr!=NULL ; entryPtr=*oldChainPtr) {
+ bytes = TclGetStringFromObj(entryPtr->objPtr, &length);
index = (HashString(bytes, length) & tablePtr->mask);
-
+
*oldChainPtr = entryPtr->nextPtr;
bucketPtr = &(tablePtr->buckets[index]);
entryPtr->nextPtr = *bucketPtr;
@@ -875,13 +921,12 @@ RebuildLiteralTable(tablePtr)
*
* TclLiteralStats --
*
- * Return statistics describing the layout of the hash table
- * in its hash buckets.
+ * Return statistics describing the layout of the hash table in its hash
+ * buckets.
*
* Results:
- * The return value is a malloc-ed string containing information
- * about tablePtr. It is the caller's responsibility to free
- * this string.
+ * The return value is a malloc-ed string containing information about
+ * tablePtr. It is the caller's responsibility to free this string.
*
* Side effects:
* None.
@@ -890,8 +935,8 @@ RebuildLiteralTable(tablePtr)
*/
char *
-TclLiteralStats(tablePtr)
- LiteralTable *tablePtr; /* Table for which to produce stats. */
+TclLiteralStats(
+ LiteralTable *tablePtr) /* Table for which to produce stats. */
{
#define NUM_COUNTERS 10
int count[NUM_COUNTERS], overflow, i, j;
@@ -900,19 +945,19 @@ TclLiteralStats(tablePtr)
char *result, *p;
/*
- * Compute a histogram of bucket usage. For each bucket chain i,
- * j is the number of entries in the chain.
+ * Compute a histogram of bucket usage. For each bucket chain i, j is the
+ * number of entries in the chain.
*/
- for (i = 0; i < NUM_COUNTERS; i++) {
+ for (i=0 ; i<NUM_COUNTERS ; i++) {
count[i] = 0;
}
overflow = 0;
average = 0.0;
- for (i = 0; i < tablePtr->numBuckets; i++) {
+ for (i=0 ; i<tablePtr->numBuckets ; i++) {
j = 0;
- for (entryPtr = tablePtr->buckets[i]; entryPtr != NULL;
- entryPtr = entryPtr->nextPtr) {
+ for (entryPtr=tablePtr->buckets[i] ; entryPtr!=NULL;
+ entryPtr=entryPtr->nextPtr) {
j++;
}
if (j < NUM_COUNTERS) {
@@ -932,7 +977,7 @@ TclLiteralStats(tablePtr)
sprintf(result, "%d entries in table, %d buckets\n",
tablePtr->numEntries, tablePtr->numBuckets);
p = result + strlen(result);
- for (i = 0; i < NUM_COUNTERS; i++) {
+ for (i=0 ; i<NUM_COUNTERS ; i++) {
sprintf(p, "number of buckets with %d entries: %d\n",
i, count[i]);
p += strlen(p);
@@ -957,15 +1002,15 @@ TclLiteralStats(tablePtr)
* None.
*
* Side effects:
- * Panics if problems are found.
+ * Tcl_Panic if problems are found.
*
*----------------------------------------------------------------------
*/
void
-TclVerifyLocalLiteralTable(envPtr)
- CompileEnv *envPtr; /* Points to CompileEnv whose literal
- * table is to be validated. */
+TclVerifyLocalLiteralTable(
+ CompileEnv *envPtr) /* Points to CompileEnv whose literal table is
+ * to be validated. */
{
register LiteralTable *localTablePtr = &(envPtr->localLitTable);
register LiteralEntry *localPtr;
@@ -974,30 +1019,29 @@ TclVerifyLocalLiteralTable(envPtr)
int length, count;
count = 0;
- for (i = 0; i < localTablePtr->numBuckets; i++) {
- for (localPtr = localTablePtr->buckets[i];
- localPtr != NULL; localPtr = localPtr->nextPtr) {
+ for (i=0 ; i<localTablePtr->numBuckets ; i++) {
+ for (localPtr=localTablePtr->buckets[i] ; localPtr!=NULL;
+ localPtr=localPtr->nextPtr) {
count++;
if (localPtr->refCount != -1) {
bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length);
- panic("TclVerifyLocalLiteralTable: local literal \"%.*s\" had bad refCount %d",
- (length>60? 60 : length), bytes,
- localPtr->refCount);
+ Tcl_Panic("TclVerifyLocalLiteralTable: local literal \"%.*s\" had bad refCount %d",
+ (length>60? 60 : length), bytes, localPtr->refCount);
}
if (TclLookupLiteralEntry((Tcl_Interp *) envPtr->iPtr,
localPtr->objPtr) == NULL) {
bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length);
- panic("TclVerifyLocalLiteralTable: local literal \"%.*s\" is not global",
- (length>60? 60 : length), bytes);
+ Tcl_Panic("TclVerifyLocalLiteralTable: local literal \"%.*s\" is not global",
+ (length>60? 60 : length), bytes);
}
if (localPtr->objPtr->bytes == NULL) {
- panic("TclVerifyLocalLiteralTable: literal has NULL string rep");
+ Tcl_Panic("TclVerifyLocalLiteralTable: literal has NULL string rep");
}
}
}
if (count != localTablePtr->numEntries) {
- panic("TclVerifyLocalLiteralTable: local literal table had %d entries, should be %d",
- count, localTablePtr->numEntries);
+ Tcl_Panic("TclVerifyLocalLiteralTable: local literal table had %d entries, should be %d",
+ count, localTablePtr->numEntries);
}
}
@@ -1012,15 +1056,15 @@ TclVerifyLocalLiteralTable(envPtr)
* None.
*
* Side effects:
- * Panics if problems are found.
+ * Tcl_Panic if problems are found.
*
*----------------------------------------------------------------------
*/
void
-TclVerifyGlobalLiteralTable(iPtr)
- Interp *iPtr; /* Points to interpreter whose global
- * literal table is to be validated. */
+TclVerifyGlobalLiteralTable(
+ Interp *iPtr) /* Points to interpreter whose global literal
+ * table is to be validated. */
{
register LiteralTable *globalTablePtr = &(iPtr->literalTable);
register LiteralEntry *globalPtr;
@@ -1029,24 +1073,31 @@ TclVerifyGlobalLiteralTable(iPtr)
int length, count;
count = 0;
- for (i = 0; i < globalTablePtr->numBuckets; i++) {
- for (globalPtr = globalTablePtr->buckets[i];
- globalPtr != NULL; globalPtr = globalPtr->nextPtr) {
+ for (i=0 ; i<globalTablePtr->numBuckets ; i++) {
+ for (globalPtr=globalTablePtr->buckets[i] ; globalPtr!=NULL;
+ globalPtr=globalPtr->nextPtr) {
count++;
if (globalPtr->refCount < 1) {
bytes = Tcl_GetStringFromObj(globalPtr->objPtr, &length);
- panic("TclVerifyGlobalLiteralTable: global literal \"%.*s\" had bad refCount %d",
- (length>60? 60 : length), bytes,
- globalPtr->refCount);
+ Tcl_Panic("TclVerifyGlobalLiteralTable: global literal \"%.*s\" had bad refCount %d",
+ (length>60? 60 : length), bytes, globalPtr->refCount);
}
if (globalPtr->objPtr->bytes == NULL) {
- panic("TclVerifyGlobalLiteralTable: literal has NULL string rep");
+ Tcl_Panic("TclVerifyGlobalLiteralTable: literal has NULL string rep");
}
}
}
if (count != globalTablePtr->numEntries) {
- panic("TclVerifyGlobalLiteralTable: global literal table had %d entries, should be %d",
- count, globalTablePtr->numEntries);
+ Tcl_Panic("TclVerifyGlobalLiteralTable: global literal table had %d entries, should be %d",
+ count, globalTablePtr->numEntries);
}
}
#endif /*TCL_COMPILE_DEBUG*/
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclLoad.c b/generic/tclLoad.c
index b576daf..e64d0e0 100644
--- a/generic/tclLoad.c
+++ b/generic/tclLoad.c
@@ -1,59 +1,69 @@
-/*
+/*
* tclLoad.c --
*
- * This file provides the generic portion (those that are the same
- * on all platforms) of Tcl's dynamic loading facilities.
+ * This file provides the generic portion (those that are the same on all
+ * platforms) of Tcl's dynamic loading facilities.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
/*
- * The following structure describes a package that has been loaded
- * either dynamically (with the "load" command) or statically (as
- * indicated by a call to TclGetLoadedPackages). All such packages
- * are linked together into a single list for the process. Packages
- * are never unloaded, until the application exits, when
- * TclFinalizeLoad is called, and these structures are freed.
+ * The following structure describes a package that has been loaded either
+ * dynamically (with the "load" command) or statically (as indicated by a call
+ * to TclGetLoadedPackages). All such packages are linked together into a
+ * single list for the process. Packages are never unloaded, until the
+ * application exits, when TclFinalizeLoad is called, and these structures are
+ * freed.
*/
typedef struct LoadedPackage {
- char *fileName; /* Name of the file from which the
- * package was loaded. An empty string
- * means the package is loaded statically.
- * Malloc-ed. */
+ char *fileName; /* Name of the file from which the package was
+ * loaded. An empty string means the package
+ * is loaded statically. Malloc-ed. */
char *packageName; /* Name of package prefix for the package,
* properly capitalized (first letter UC,
- * others LC), no "_", as in "Net".
+ * others LC), no "_", as in "Net".
* Malloc-ed. */
Tcl_LoadHandle loadHandle; /* Token for the loaded file which should be
* passed to (*unLoadProcPtr)() when the file
- * is no longer needed. If fileName is NULL,
+ * is no longer needed. If fileName is NULL,
* then this field is irrelevant. */
Tcl_PackageInitProc *initProc;
- /* Initialization procedure to call to
+ /* Initialization function to call to
* incorporate this package into a trusted
* interpreter. */
Tcl_PackageInitProc *safeInitProc;
- /* Initialization procedure to call to
+ /* Initialization function to call to
* incorporate this package into a safe
* interpreter (one that will execute
- * untrusted scripts). NULL means the
- * package can't be used in unsafe
- * interpreters. */
+ * untrusted scripts). NULL means the package
+ * can't be used in unsafe interpreters. */
+ Tcl_PackageUnloadProc *unloadProc;
+ /* Finalisation function to unload a package
+ * from a trusted interpreter. NULL means that
+ * the package cannot be unloaded. */
+ Tcl_PackageUnloadProc *safeUnloadProc;
+ /* Finalisation function to unload a package
+ * from a safe interpreter. NULL means that
+ * the package cannot be unloaded. */
+ int interpRefCount; /* How many times the package has been loaded
+ * in trusted interpreters. */
+ int safeInterpRefCount; /* How many times the package has been loaded
+ * in safe interpreters. */
Tcl_FSUnloadFileProc *unLoadProcPtr;
- /* Procedure to use to unload this package.
- * If NULL, then we do not attempt to unload
- * the package. If fileName is NULL, then
- * this field is irrelevant. */
+ /* Function to use to unload this package. If
+ * NULL, then we do not attempt to unload the
+ * package. If fileName is NULL, then this
+ * field is irrelevant. */
struct LoadedPackage *nextPtr;
/* Next in list of all packages loaded into
- * this application process. NULL means
- * end of list. */
+ * this application process. NULL means end of
+ * list. */
} LoadedPackage;
/*
@@ -69,35 +79,35 @@ static LoadedPackage *firstPackagePtr = NULL;
TCL_DECLARE_MUTEX(packageMutex)
/*
- * The following structure represents a particular package that has
- * been incorporated into a particular interpreter (by calling its
- * initialization procedure). There is a list of these structures for
- * each interpreter, with an AssocData value (key "load") for the
- * interpreter that points to the first package (if any).
+ * The following structure represents a particular package that has been
+ * incorporated into a particular interpreter (by calling its initialization
+ * function). There is a list of these structures for each interpreter, with
+ * an AssocData value (key "load") for the interpreter that points to the
+ * first package (if any).
*/
typedef struct InterpPackage {
LoadedPackage *pkgPtr; /* Points to detailed information about
* package. */
struct InterpPackage *nextPtr;
- /* Next package in this interpreter, or
- * NULL for end of list. */
+ /* Next package in this interpreter, or NULL
+ * for end of list. */
} InterpPackage;
/*
- * Prototypes for procedures that are private to this file:
+ * Prototypes for functions that are private to this file:
*/
-static void LoadCleanupProc _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp));
+static void LoadCleanupProc(ClientData clientData,
+ Tcl_Interp *interp);
/*
*----------------------------------------------------------------------
*
* Tcl_LoadObjCmd --
*
- * This procedure is invoked to process the "load" Tcl command.
- * See the user documentation for details on what it does.
+ * This function is invoked to process the "load" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -109,36 +119,41 @@ static void LoadCleanupProc _ANSI_ARGS_((ClientData clientData,
*/
int
-Tcl_LoadObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_LoadObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Interp *target;
LoadedPackage *pkgPtr, *defaultPtr;
Tcl_DString pkgName, tmp, initName, safeInitName;
- Tcl_PackageInitProc *initProc, *safeInitProc;
+ Tcl_DString unloadName, safeUnloadName;
+ Tcl_PackageInitProc *initProc, *safeInitProc, *unloadProc, *safeUnloadProc;
InterpPackage *ipFirstPtr, *ipPtr;
- int code, namesMatch, filesMatch;
+ int code, namesMatch, filesMatch, offset;
+ const char *symbols[4];
+ Tcl_PackageInitProc **procPtrs[4];
+ ClientData clientData;
char *p, *fullFileName, *packageName;
Tcl_LoadHandle loadHandle;
Tcl_FSUnloadFileProc *unLoadProcPtr = NULL;
Tcl_UniChar ch;
- int offset;
if ((objc < 2) || (objc > 4)) {
- Tcl_WrongNumArgs(interp, 1, objv, "fileName ?packageName? ?interp?");
+ Tcl_WrongNumArgs(interp, 1, objv, "fileName ?packageName? ?interp?");
return TCL_ERROR;
}
if (Tcl_FSConvertToPathType(interp, objv[1]) != TCL_OK) {
return TCL_ERROR;
}
fullFileName = Tcl_GetString(objv[1]);
-
+
Tcl_DStringInit(&pkgName);
Tcl_DStringInit(&initName);
Tcl_DStringInit(&safeInitName);
+ Tcl_DStringInit(&unloadName);
+ Tcl_DStringInit(&safeUnloadName);
Tcl_DStringInit(&tmp);
packageName = NULL;
@@ -162,23 +177,25 @@ Tcl_LoadObjCmd(dummy, interp, objc, objv)
target = interp;
if (objc == 4) {
- char *slaveIntName;
- slaveIntName = Tcl_GetString(objv[3]);
+ char *slaveIntName = Tcl_GetString(objv[3]);
+
target = Tcl_GetSlave(interp, slaveIntName);
if (target == NULL) {
- return TCL_ERROR;
+ code = TCL_ERROR;
+ goto done;
}
}
/*
* Scan through the packages that are currently loaded to see if the
- * package we want is already loaded. We'll use a loaded package if
- * it meets any of the following conditions:
+ * package we want is already loaded. We'll use a loaded package if it
+ * meets any of the following conditions:
* - Its name and file match the once we're looking for.
* - Its file matches, and we weren't given a name.
- * - Its name matches, the file name was specified as empty, and there
- * is only no statically loaded package with the same name.
+ * - Its name matches, the file name was specified as empty, and there is
+ * only no statically loaded package with the same name.
*/
+
Tcl_MutexLock(&packageMutex);
defaultPtr = NULL;
@@ -210,13 +227,12 @@ Tcl_LoadObjCmd(dummy, interp, objc, objv)
}
if (filesMatch && !namesMatch && (fullFileName[0] != 0)) {
/*
- * Can't have two different packages loaded from the same
- * file.
+ * Can't have two different packages loaded from the same file.
*/
Tcl_AppendResult(interp, "file \"", fullFileName,
"\" is already loaded for package \"",
- pkgPtr->packageName, "\"", (char *) NULL);
+ pkgPtr->packageName, "\"", NULL);
code = TCL_ERROR;
Tcl_MutexUnlock(&packageMutex);
goto done;
@@ -229,13 +245,13 @@ Tcl_LoadObjCmd(dummy, interp, objc, objv)
/*
* Scan through the list of packages already loaded in the target
- * interpreter. If the package we want is already loaded there,
- * then there's nothing for us to to.
+ * interpreter. If the package we want is already loaded there, then
+ * there's nothing for us to do.
*/
if (pkgPtr != NULL) {
- ipFirstPtr = (InterpPackage *) Tcl_GetAssocData(target, "tclLoad",
- (Tcl_InterpDeleteProc **) NULL);
+ ipFirstPtr = (InterpPackage *) Tcl_GetAssocData(target,
+ "tclLoad", NULL);
for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
if (ipPtr->pkgPtr == pkgPtr) {
code = TCL_OK;
@@ -246,13 +262,13 @@ Tcl_LoadObjCmd(dummy, interp, objc, objv)
if (pkgPtr == NULL) {
/*
- * The desired file isn't currently loaded, so load it. It's an
- * error if the desired package is a static one.
+ * The desired file isn't currently loaded, so load it. It's an error
+ * if the desired package is a static one.
*/
if (fullFileName[0] == 0) {
Tcl_AppendResult(interp, "package \"", packageName,
- "\" isn't loaded statically", (char *) NULL);
+ "\" isn't loaded statically", NULL);
code = TCL_ERROR;
goto done;
}
@@ -265,9 +281,11 @@ Tcl_LoadObjCmd(dummy, interp, objc, objv)
Tcl_DStringAppend(&pkgName, packageName, -1);
} else {
int retc;
+
/*
* Threading note - this call used to be protected by a mutex.
*/
+
retc = TclGuessPackageName(fullFileName, &pkgName);
if (!retc) {
Tcl_Obj *splitPtr;
@@ -276,11 +294,11 @@ Tcl_LoadObjCmd(dummy, interp, objc, objv)
char *pkgGuess;
/*
- * The platform-specific code couldn't figure out the
- * module name. Make a guess by taking the last element
- * of the file name, stripping off any leading "lib",
- * and then using all of the alphabetic and underline
- * characters that follow that.
+ * The platform-specific code couldn't figure out the module
+ * name. Make a guess by taking the last element of the file
+ * name, stripping off any leading "lib", and then using all
+ * of the alphabetic and underline characters that follow
+ * that.
*/
splitPtr = Tcl_FSSplitPath(objv[1], &pElements);
@@ -302,7 +320,7 @@ Tcl_LoadObjCmd(dummy, interp, objc, objv)
Tcl_DecrRefCount(splitPtr);
Tcl_AppendResult(interp,
"couldn't figure out package name for ",
- fullFileName, (char *) NULL);
+ fullFileName, NULL);
code = TCL_ERROR;
goto done;
}
@@ -316,36 +334,50 @@ Tcl_LoadObjCmd(dummy, interp, objc, objv)
* character is in caps (or title case) but the others are all
* lower-case.
*/
-
+
Tcl_DStringSetLength(&pkgName,
Tcl_UtfToTitle(Tcl_DStringValue(&pkgName)));
/*
- * Compute the names of the two initialization procedures,
- * based on the package name.
+ * Compute the names of the two initialization functions, based on the
+ * package name.
*/
-
+
Tcl_DStringAppend(&initName, Tcl_DStringValue(&pkgName), -1);
Tcl_DStringAppend(&initName, "_Init", 5);
Tcl_DStringAppend(&safeInitName, Tcl_DStringValue(&pkgName), -1);
Tcl_DStringAppend(&safeInitName, "_SafeInit", 9);
+ Tcl_DStringAppend(&unloadName, Tcl_DStringValue(&pkgName), -1);
+ Tcl_DStringAppend(&unloadName, "_Unload", 7);
+ Tcl_DStringAppend(&safeUnloadName, Tcl_DStringValue(&pkgName), -1);
+ Tcl_DStringAppend(&safeUnloadName, "_SafeUnload", 11);
/*
- * Call platform-specific code to load the package and find the
- * two initialization procedures.
+ * Call platform-specific code to load the package and find the two
+ * initialization functions.
*/
+ symbols[0] = Tcl_DStringValue(&initName);
+ symbols[1] = Tcl_DStringValue(&safeInitName);
+ symbols[2] = Tcl_DStringValue(&unloadName);
+ symbols[3] = Tcl_DStringValue(&safeUnloadName);
+ procPtrs[0] = &initProc;
+ procPtrs[1] = &safeInitProc;
+ procPtrs[2] = &unloadProc;
+ procPtrs[3] = &safeUnloadProc;
+
Tcl_MutexLock(&packageMutex);
- code = Tcl_FSLoadFile(interp, objv[1], Tcl_DStringValue(&initName),
- Tcl_DStringValue(&safeInitName), &initProc, &safeInitProc,
- &loadHandle,&unLoadProcPtr);
+ code = TclLoadFile(interp, objv[1], 4, symbols, procPtrs,
+ &loadHandle, &clientData, &unLoadProcPtr);
Tcl_MutexUnlock(&packageMutex);
+ loadHandle = (Tcl_LoadHandle) clientData;
if (code != TCL_OK) {
goto done;
}
- if (initProc == NULL) {
+
+ if (*procPtrs[0] /* initProc */ == NULL) {
Tcl_AppendResult(interp, "couldn't find procedure ",
- Tcl_DStringValue(&initName), (char *) NULL);
+ Tcl_DStringValue(&initName), NULL);
if (unLoadProcPtr != NULL) {
(*unLoadProcPtr)(loadHandle);
}
@@ -358,26 +390,30 @@ Tcl_LoadObjCmd(dummy, interp, objc, objv)
*/
pkgPtr = (LoadedPackage *) ckalloc(sizeof(LoadedPackage));
- pkgPtr->fileName = (char *) ckalloc((unsigned)
+ pkgPtr->fileName = (char *) ckalloc((unsigned)
(strlen(fullFileName) + 1));
strcpy(pkgPtr->fileName, fullFileName);
- pkgPtr->packageName = (char *) ckalloc((unsigned)
+ pkgPtr->packageName = (char *) ckalloc((unsigned)
(Tcl_DStringLength(&pkgName) + 1));
strcpy(pkgPtr->packageName, Tcl_DStringValue(&pkgName));
- pkgPtr->loadHandle = loadHandle;
- pkgPtr->unLoadProcPtr = unLoadProcPtr;
- pkgPtr->initProc = initProc;
- pkgPtr->safeInitProc = safeInitProc;
+ pkgPtr->loadHandle = loadHandle;
+ pkgPtr->unLoadProcPtr = unLoadProcPtr;
+ pkgPtr->initProc = *procPtrs[0];
+ pkgPtr->safeInitProc = *procPtrs[1];
+ pkgPtr->unloadProc = (Tcl_PackageUnloadProc*) *procPtrs[2];
+ pkgPtr->safeUnloadProc = (Tcl_PackageUnloadProc*) *procPtrs[3];
+ pkgPtr->interpRefCount = 0;
+ pkgPtr->safeInterpRefCount = 0;
+
Tcl_MutexLock(&packageMutex);
- pkgPtr->nextPtr = firstPackagePtr;
- firstPackagePtr = pkgPtr;
+ pkgPtr->nextPtr = firstPackagePtr;
+ firstPackagePtr = pkgPtr;
Tcl_MutexUnlock(&packageMutex);
}
/*
- * Invoke the package's initialization procedure (either the
- * normal one or the safe one, depending on whether or not the
- * interpreter is safe).
+ * Invoke the package's initialization function (either the normal one or
+ * the safe one, depending on whether or not the interpreter is safe).
*/
if (Tcl_IsSafe(target)) {
@@ -385,9 +421,8 @@ Tcl_LoadObjCmd(dummy, interp, objc, objv)
code = (*pkgPtr->safeInitProc)(target);
} else {
Tcl_AppendResult(interp,
- "can't use package in a safe interpreter: ",
- "no ", pkgPtr->packageName, "_SafeInit procedure",
- (char *) NULL);
+ "can't use package in a safe interpreter: no ",
+ pkgPtr->packageName, "_SafeInit procedure", NULL);
code = TCL_ERROR;
goto done;
}
@@ -396,18 +431,30 @@ Tcl_LoadObjCmd(dummy, interp, objc, objv)
}
/*
- * Record the fact that the package has been loaded in the
- * target interpreter.
+ * Record the fact that the package has been loaded in the target
+ * interpreter.
*/
if (code == TCL_OK) {
/*
+ * Update the proper reference count.
+ */
+
+ Tcl_MutexLock(&packageMutex);
+ if (Tcl_IsSafe(target)) {
+ ++pkgPtr->safeInterpRefCount;
+ } else {
+ ++pkgPtr->interpRefCount;
+ }
+ Tcl_MutexUnlock(&packageMutex);
+
+ /*
* Refetch ipFirstPtr: loading the package may have introduced
* additional static packages at the head of the linked list!
*/
- ipFirstPtr = (InterpPackage *) Tcl_GetAssocData(target, "tclLoad",
- (Tcl_InterpDeleteProc **) NULL);
+ ipFirstPtr = (InterpPackage *) Tcl_GetAssocData(target,
+ "tclLoad", NULL);
ipPtr = (InterpPackage *) ckalloc(sizeof(InterpPackage));
ipPtr->pkgPtr = pkgPtr;
ipPtr->nextPtr = ipFirstPtr;
@@ -417,11 +464,434 @@ Tcl_LoadObjCmd(dummy, interp, objc, objv)
TclTransferResult(target, code, interp);
}
- done:
+ done:
Tcl_DStringFree(&pkgName);
Tcl_DStringFree(&initName);
Tcl_DStringFree(&safeInitName);
+ Tcl_DStringFree(&unloadName);
+ Tcl_DStringFree(&safeUnloadName);
+ Tcl_DStringFree(&tmp);
+ return code;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_UnloadObjCmd --
+ *
+ * This function is invoked to process the "unload" Tcl command. See the
+ * user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_UnloadObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tcl_Interp *target; /* Which interpreter to unload from. */
+ LoadedPackage *pkgPtr, *defaultPtr;
+ Tcl_DString pkgName, tmp;
+ Tcl_PackageUnloadProc *unloadProc;
+ InterpPackage *ipFirstPtr, *ipPtr;
+ int i, index, code, complain = 1, keepLibrary = 0;
+ int trustedRefCount = -1, safeRefCount = -1;
+ const char *fullFileName = "";
+ char *packageName;
+ static const char *options[] = {
+ "-nocomplain", "-keeplibrary", "--", NULL
+ };
+ enum options {
+ UNLOAD_NOCOMPLAIN, UNLOAD_KEEPLIB, UNLOAD_LAST
+ };
+
+ for (i = 1; i < objc; i++) {
+ if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
+ &index) != TCL_OK) {
+ fullFileName = Tcl_GetString(objv[i]);
+ if (fullFileName[0] == '-') {
+ /*
+ * It looks like the command contains an option so signal an
+ * error
+ */
+
+ return TCL_ERROR;
+ } else {
+ /*
+ * This clearly isn't an option; assume it's the filename. We
+ * must clear the error.
+ */
+
+ Tcl_ResetResult(interp);
+ break;
+ }
+ }
+ switch (index) {
+ case UNLOAD_NOCOMPLAIN: /* -nocomplain */
+ complain = 0;
+ break;
+ case UNLOAD_KEEPLIB: /* -keeplibrary */
+ keepLibrary = 1;
+ break;
+ case UNLOAD_LAST: /* -- */
+ i++;
+ goto endOfForLoop;
+ }
+ }
+ endOfForLoop:
+ if ((objc-i < 1) || (objc-i > 3)) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "?switches? fileName ?packageName? ?interp?");
+ return TCL_ERROR;
+ }
+ if (Tcl_FSConvertToPathType(interp, objv[i]) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ fullFileName = Tcl_GetString(objv[i]);
+ Tcl_DStringInit(&pkgName);
+ Tcl_DStringInit(&tmp);
+
+ packageName = NULL;
+ if (objc - i >= 2) {
+ packageName = Tcl_GetString(objv[i+1]);
+ if (packageName[0] == '\0') {
+ packageName = NULL;
+ }
+ }
+ if ((fullFileName[0] == 0) && (packageName == NULL)) {
+ Tcl_SetResult(interp,
+ "must specify either file name or package name",
+ TCL_STATIC);
+ code = TCL_ERROR;
+ goto done;
+ }
+
+ /*
+ * Figure out which interpreter we're going to load the package into.
+ */
+
+ target = interp;
+ if (objc - i == 3) {
+ char *slaveIntName;
+ slaveIntName = Tcl_GetString(objv[i+2]);
+ target = Tcl_GetSlave(interp, slaveIntName);
+ if (target == NULL) {
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Scan through the packages that are currently loaded to see if the
+ * package we want is already loaded. We'll use a loaded package if it
+ * meets any of the following conditions:
+ * - Its name and file match the once we're looking for.
+ * - Its file matches, and we weren't given a name.
+ * - Its name matches, the file name was specified as empty, and there is
+ * only no statically loaded package with the same name.
+ */
+
+ Tcl_MutexLock(&packageMutex);
+
+ defaultPtr = NULL;
+ for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) {
+ int namesMatch, filesMatch;
+
+ if (packageName == NULL) {
+ namesMatch = 0;
+ } else {
+ Tcl_DStringSetLength(&pkgName, 0);
+ Tcl_DStringAppend(&pkgName, packageName, -1);
+ Tcl_DStringSetLength(&tmp, 0);
+ Tcl_DStringAppend(&tmp, pkgPtr->packageName, -1);
+ Tcl_UtfToLower(Tcl_DStringValue(&pkgName));
+ Tcl_UtfToLower(Tcl_DStringValue(&tmp));
+ if (strcmp(Tcl_DStringValue(&tmp),
+ Tcl_DStringValue(&pkgName)) == 0) {
+ namesMatch = 1;
+ } else {
+ namesMatch = 0;
+ }
+ }
+ Tcl_DStringSetLength(&pkgName, 0);
+
+ filesMatch = (strcmp(pkgPtr->fileName, fullFileName) == 0);
+ if (filesMatch && (namesMatch || (packageName == NULL))) {
+ break;
+ }
+ if (namesMatch && (fullFileName[0] == 0)) {
+ defaultPtr = pkgPtr;
+ }
+ if (filesMatch && !namesMatch && (fullFileName[0] != 0)) {
+ break;
+ }
+ }
+ Tcl_MutexUnlock(&packageMutex);
+ if (fullFileName[0] == 0) {
+ /*
+ * It's an error to try unload a static package.
+ */
+
+ Tcl_AppendResult(interp, "package \"", packageName,
+ "\" is loaded statically and cannot be unloaded", NULL);
+ code = TCL_ERROR;
+ goto done;
+ }
+ if (pkgPtr == NULL) {
+ /*
+ * The DLL pointed by the provided filename has never been loaded.
+ */
+
+ Tcl_AppendResult(interp, "file \"", fullFileName,
+ "\" has never been loaded", NULL);
+ code = TCL_ERROR;
+ goto done;
+ }
+
+ /*
+ * Scan through the list of packages already loaded in the target
+ * interpreter. If the package we want is already loaded there, then we
+ * should proceed with unloading.
+ */
+
+ code = TCL_ERROR;
+ if (pkgPtr != NULL) {
+ ipFirstPtr = (InterpPackage *) Tcl_GetAssocData(target,
+ "tclLoad", NULL);
+ for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
+ if (ipPtr->pkgPtr == pkgPtr) {
+ code = TCL_OK;
+ break;
+ }
+ }
+ }
+ if (code != TCL_OK) {
+ /*
+ * The package has not been loaded in this interpreter.
+ */
+
+ Tcl_AppendResult(interp, "file \"", fullFileName,
+ "\" has never been loaded in this interpreter", NULL);
+ code = TCL_ERROR;
+ goto done;
+ }
+
+ /*
+ * Ensure that the DLL can be unloaded. If it is a trusted interpreter,
+ * pkgPtr->unloadProc must not be NULL for the DLL to be unloadable. If
+ * the interpreter is a safe one, pkgPtr->safeUnloadProc must be non-NULL.
+ */
+
+ if (Tcl_IsSafe(target)) {
+ if (pkgPtr->safeUnloadProc == NULL) {
+ Tcl_AppendResult(interp, "file \"", fullFileName,
+ "\" cannot be unloaded under a safe interpreter", NULL);
+ code = TCL_ERROR;
+ goto done;
+ }
+ unloadProc = pkgPtr->safeUnloadProc;
+ } else {
+ if (pkgPtr->unloadProc == NULL) {
+ Tcl_AppendResult(interp, "file \"", fullFileName,
+ "\" cannot be unloaded under a trusted interpreter", NULL);
+ code = TCL_ERROR;
+ goto done;
+ }
+ unloadProc = pkgPtr->unloadProc;
+ }
+
+ /*
+ * We are ready to unload the package. First, evaluate the unload
+ * function. If this fails, we cannot proceed with unload. Also, we must
+ * specify the proper flag to pass to the unload callback.
+ * TCL_UNLOAD_DETACH_FROM_INTERPRETER is defined when the callback should
+ * only remove itself from the interpreter; the library will be unloaded
+ * in a future call of unload. In case the library will be unloaded just
+ * after the callback returns, TCL_UNLOAD_DETACH_FROM_PROCESS is passed.
+ */
+
+ code = TCL_UNLOAD_DETACH_FROM_INTERPRETER;
+ if (!keepLibrary) {
+ Tcl_MutexLock(&packageMutex);
+ trustedRefCount = pkgPtr->interpRefCount;
+ safeRefCount = pkgPtr->safeInterpRefCount;
+ Tcl_MutexUnlock(&packageMutex);
+
+ if (Tcl_IsSafe(target)) {
+ --safeRefCount;
+ } else {
+ --trustedRefCount;
+ }
+
+ if (safeRefCount <= 0 && trustedRefCount <= 0) {
+ code = TCL_UNLOAD_DETACH_FROM_PROCESS;
+ }
+ }
+ code = (*unloadProc)(target, code);
+ if (code != TCL_OK) {
+ TclTransferResult(target, code, interp);
+ goto done;
+ }
+
+ /*
+ * The unload function executed fine. Examine the reference count to see
+ * if we unload the DLL.
+ */
+
+ Tcl_MutexLock(&packageMutex);
+ if (Tcl_IsSafe(target)) {
+ --pkgPtr->safeInterpRefCount;
+
+ /*
+ * Do not let counter get negative.
+ */
+
+ if (pkgPtr->safeInterpRefCount < 0) {
+ pkgPtr->safeInterpRefCount = 0;
+ }
+ } else {
+ --pkgPtr->interpRefCount;
+
+ /*
+ * Do not let counter get negative.
+ */
+
+ if (pkgPtr->interpRefCount < 0) {
+ pkgPtr->interpRefCount = 0;
+ }
+ }
+ trustedRefCount = pkgPtr->interpRefCount;
+ safeRefCount = pkgPtr->safeInterpRefCount;
+ Tcl_MutexUnlock(&packageMutex);
+
+ code = TCL_OK;
+ if (pkgPtr->safeInterpRefCount <= 0 && pkgPtr->interpRefCount <= 0
+ && !keepLibrary) {
+ /*
+ * Unload the shared library from the application memory...
+ */
+
+#if defined(TCL_UNLOAD_DLLS) || defined(__WIN32__)
+ /*
+ * Some Unix dlls are poorly behaved - registering things like atexit
+ * calls that can't be unregistered. If you unload such dlls, you get
+ * a core on exit because it wants to call a function in the dll after
+ * it's been unloaded.
+ */
+
+ if (pkgPtr->fileName[0] != '\0') {
+ Tcl_FSUnloadFileProc *unLoadProcPtr = pkgPtr->unLoadProcPtr;
+
+ if (unLoadProcPtr != NULL) {
+ Tcl_MutexLock(&packageMutex);
+ if ((pkgPtr->unloadProc != NULL) || (unLoadProcPtr == TclFSUnloadTempFile)) {
+ (*unLoadProcPtr)(pkgPtr->loadHandle);
+ }
+
+ /*
+ * Remove this library from the loaded library cache.
+ */
+
+ defaultPtr = pkgPtr;
+ if (defaultPtr == firstPackagePtr) {
+ firstPackagePtr = pkgPtr->nextPtr;
+ } else {
+ for (pkgPtr = firstPackagePtr; pkgPtr != NULL;
+ pkgPtr = pkgPtr->nextPtr) {
+ if (pkgPtr->nextPtr == defaultPtr) {
+ pkgPtr->nextPtr = defaultPtr->nextPtr;
+ break;
+ }
+ }
+ }
+
+ /*
+ * Remove this library from the interpreter's library cache.
+ */
+
+ ipFirstPtr = (InterpPackage *) Tcl_GetAssocData(target,
+ "tclLoad", NULL);
+ ipPtr = ipFirstPtr;
+ if (ipPtr->pkgPtr == defaultPtr) {
+ ipFirstPtr = ipFirstPtr->nextPtr;
+ } else {
+ InterpPackage *ipPrevPtr;
+
+ for (ipPrevPtr = ipPtr; ipPtr != NULL;
+ ipPrevPtr = ipPtr, ipPtr = ipPtr->nextPtr) {
+ if (ipPtr->pkgPtr == pkgPtr) {
+ ipPrevPtr->nextPtr = ipPtr->nextPtr;
+ break;
+ }
+ }
+ }
+ Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc,
+ (ClientData) ipFirstPtr);
+ ckfree(defaultPtr->fileName);
+ ckfree(defaultPtr->packageName);
+ ckfree((char *) defaultPtr);
+ ckfree((char *) ipPtr);
+ Tcl_MutexUnlock(&packageMutex);
+ } else {
+ Tcl_AppendResult(interp, "file \"", fullFileName,
+ "\" cannot be unloaded: filesystem does not support unloading",
+ NULL);
+ code = TCL_ERROR;
+ }
+ }
+#else
+ Tcl_AppendResult(interp, "file \"", fullFileName,
+ "\" cannot be unloaded: unloading disabled", NULL);
+ code = TCL_ERROR;
+#endif
+ }
+
+ done:
+ Tcl_DStringFree(&pkgName);
Tcl_DStringFree(&tmp);
+ if (!complain && code!=TCL_OK) {
+ code = TCL_OK;
+ Tcl_ResetResult(interp);
+ }
+ if (code == TCL_OK) {
+#if 0
+ /*
+ * Result of [unload] was not documented in TIP#100, so force to be
+ * the empty string by commenting this out. DKF.
+ */
+
+ Tcl_Obj *resultObjPtr, *objPtr[2];
+
+ /*
+ * Our result is the two reference counts.
+ */
+
+ objPtr[0] = Tcl_NewIntObj(trustedRefCount);
+ objPtr[1] = Tcl_NewIntObj(safeRefCount);
+ if (objPtr[0] == NULL || objPtr[1] == NULL) {
+ if (objPtr[0]) {
+ Tcl_DecrRefCount(objPtr[0]);
+ }
+ if (objPtr[1]) {
+ Tcl_DecrRefCount(objPtr[1]);
+ }
+ } else {
+ resultObjPtr = Tcl_NewListObj(2, objPtr);
+ if (resultObjPtr != NULL) {
+ Tcl_SetObjResult(interp, resultObjPtr);
+ }
+ }
+#endif
+ }
return code;
}
@@ -430,37 +900,37 @@ Tcl_LoadObjCmd(dummy, interp, objc, objv)
*
* Tcl_StaticPackage --
*
- * This procedure is invoked to indicate that a particular
- * package has been linked statically with an application.
+ * This function is invoked to indicate that a particular package has
+ * been linked statically with an application.
*
* Results:
* None.
*
* Side effects:
- * Once this procedure completes, the package becomes loadable
- * via the "load" command with an empty file name.
+ * Once this function completes, the package becomes loadable via the
+ * "load" command with an empty file name.
*
*----------------------------------------------------------------------
*/
void
-Tcl_StaticPackage(interp, pkgName, initProc, safeInitProc)
- Tcl_Interp *interp; /* If not NULL, it means that the
- * package has already been loaded
- * into the given interpreter by
- * calling the appropriate init proc. */
- CONST char *pkgName; /* Name of package (must be properly
- * capitalized: first letter upper
- * case, others lower case). */
- Tcl_PackageInitProc *initProc; /* Procedure to call to incorporate
- * this package into a trusted
- * interpreter. */
- Tcl_PackageInitProc *safeInitProc; /* Procedure to call to incorporate
- * this package into a safe interpreter
- * (one that will execute untrusted
- * scripts). NULL means the package
- * can't be used in safe
- * interpreters. */
+Tcl_StaticPackage(
+ Tcl_Interp *interp, /* If not NULL, it means that the package has
+ * already been loaded into the given
+ * interpreter by calling the appropriate init
+ * proc. */
+ const char *pkgName, /* Name of package (must be properly
+ * capitalized: first letter upper case,
+ * others lower case). */
+ Tcl_PackageInitProc *initProc,
+ /* Function to call to incorporate this
+ * package into a trusted interpreter. */
+ Tcl_PackageInitProc *safeInitProc)
+ /* Function to call to incorporate this
+ * package into a safe interpreter (one that
+ * will execute untrusted scripts). NULL means
+ * the package can't be used in safe
+ * interpreters. */
{
LoadedPackage *pkgPtr;
InterpPackage *ipPtr, *ipFirstPtr;
@@ -481,16 +951,16 @@ Tcl_StaticPackage(interp, pkgName, initProc, safeInitProc)
Tcl_MutexUnlock(&packageMutex);
/*
- * If the package is not yet recorded as being loaded statically,
- * add it to the list now.
+ * If the package is not yet recorded as being loaded statically, add it
+ * to the list now.
*/
if ( pkgPtr == NULL ) {
pkgPtr = (LoadedPackage *) ckalloc(sizeof(LoadedPackage));
pkgPtr->fileName = (char *) ckalloc((unsigned) 1);
pkgPtr->fileName[0] = 0;
- pkgPtr->packageName = (char *) ckalloc((unsigned)
- (strlen(pkgName) + 1));
+ pkgPtr->packageName = (char *)
+ ckalloc((unsigned) (strlen(pkgName) + 1));
strcpy(pkgPtr->packageName, pkgName);
pkgPtr->loadHandle = NULL;
pkgPtr->initProc = initProc;
@@ -504,12 +974,12 @@ Tcl_StaticPackage(interp, pkgName, initProc, safeInitProc)
if (interp != NULL) {
/*
- * If we're loading the package into an interpreter,
- * determine whether it's already loaded.
+ * If we're loading the package into an interpreter, determine whether
+ * it's already loaded.
*/
- ipFirstPtr = (InterpPackage *) Tcl_GetAssocData(interp, "tclLoad",
- (Tcl_InterpDeleteProc **) NULL);
+ ipFirstPtr = (InterpPackage *) Tcl_GetAssocData(interp,
+ "tclLoad", NULL);
for ( ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr ) {
if ( ipPtr->pkgPtr == pkgPtr ) {
return;
@@ -517,8 +987,8 @@ Tcl_StaticPackage(interp, pkgName, initProc, safeInitProc)
}
/*
- * Package isn't loade in the current interp yet. Mark it as
- * now being loaded.
+ * Package isn't loade in the current interp yet. Mark it as now being
+ * loaded.
*/
ipPtr = (InterpPackage *) ckalloc(sizeof(InterpPackage));
@@ -534,17 +1004,15 @@ Tcl_StaticPackage(interp, pkgName, initProc, safeInitProc)
*
* TclGetLoadedPackages --
*
- * This procedure returns information about all of the files
- * that are loaded (either in a particular intepreter, or
- * for all interpreters).
+ * This function returns information about all of the files that are
+ * loaded (either in a particular intepreter, or for all interpreters).
*
* Results:
- * The return value is a standard Tcl completion code. If
- * successful, a list of lists is placed in the interp's result.
- * Each sublist corresponds to one loaded file; its first
- * element is the name of the file (or an empty string for
- * something that's statically loaded) and the second element
- * is the name of the package in that file.
+ * The return value is a standard Tcl completion code. If successful, a
+ * list of lists is placed in the interp's result. Each sublist
+ * corresponds to one loaded file; its first element is the name of the
+ * file (or an empty string for something that's statically loaded) and
+ * the second element is the name of the package in that file.
*
* Side effects:
* None.
@@ -553,21 +1021,21 @@ Tcl_StaticPackage(interp, pkgName, initProc, safeInitProc)
*/
int
-TclGetLoadedPackages(interp, targetName)
- Tcl_Interp *interp; /* Interpreter in which to return
- * information or error message. */
- char *targetName; /* Name of target interpreter or NULL.
- * If NULL, return info about all interps;
+TclGetLoadedPackages(
+ Tcl_Interp *interp, /* Interpreter in which to return information
+ * or error message. */
+ char *targetName) /* Name of target interpreter or NULL. If
+ * NULL, return info about all interps;
* otherwise, just return info about this
* interpreter. */
{
Tcl_Interp *target;
LoadedPackage *pkgPtr;
InterpPackage *ipPtr;
- char *prefix;
+ const char *prefix;
if (targetName == NULL) {
- /*
+ /*
* Return information about all of the available packages.
*/
@@ -575,10 +1043,10 @@ TclGetLoadedPackages(interp, targetName)
Tcl_MutexLock(&packageMutex);
for (pkgPtr = firstPackagePtr; pkgPtr != NULL;
pkgPtr = pkgPtr->nextPtr) {
- Tcl_AppendResult(interp, prefix, (char *) NULL);
+ Tcl_AppendResult(interp, prefix, NULL);
Tcl_AppendElement(interp, pkgPtr->fileName);
Tcl_AppendElement(interp, pkgPtr->packageName);
- Tcl_AppendResult(interp, "}", (char *) NULL);
+ Tcl_AppendResult(interp, "}", NULL);
prefix = " {";
}
Tcl_MutexUnlock(&packageMutex);
@@ -586,23 +1054,22 @@ TclGetLoadedPackages(interp, targetName)
}
/*
- * Return information about only the packages that are loaded in
- * a given interpreter.
+ * Return information about only the packages that are loaded in a given
+ * interpreter.
*/
target = Tcl_GetSlave(interp, targetName);
if (target == NULL) {
return TCL_ERROR;
}
- ipPtr = (InterpPackage *) Tcl_GetAssocData(target, "tclLoad",
- (Tcl_InterpDeleteProc **) NULL);
+ ipPtr = (InterpPackage *) Tcl_GetAssocData(target, "tclLoad", NULL);
prefix = "{";
for ( ; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
pkgPtr = ipPtr->pkgPtr;
- Tcl_AppendResult(interp, prefix, (char *) NULL);
+ Tcl_AppendResult(interp, prefix, NULL);
Tcl_AppendElement(interp, pkgPtr->fileName);
Tcl_AppendElement(interp, pkgPtr->packageName);
- Tcl_AppendResult(interp, "}", (char *) NULL);
+ Tcl_AppendResult(interp, "}", NULL);
prefix = " {";
}
return TCL_OK;
@@ -613,25 +1080,24 @@ TclGetLoadedPackages(interp, targetName)
*
* LoadCleanupProc --
*
- * This procedure is called to delete all of the InterpPackage
- * structures for an interpreter when the interpreter is deleted.
- * It gets invoked via the Tcl AssocData mechanism.
+ * This function is called to delete all of the InterpPackage structures
+ * for an interpreter when the interpreter is deleted. It gets invoked
+ * via the Tcl AssocData mechanism.
*
* Results:
* None.
*
* Side effects:
- * Storage for all of the InterpPackage procedures for interp
- * get deleted.
+ * Storage for all of the InterpPackage functions for interp get deleted.
*
*----------------------------------------------------------------------
*/
static void
-LoadCleanupProc(clientData, interp)
- ClientData clientData; /* Pointer to first InterpPackage structure
+LoadCleanupProc(
+ ClientData clientData, /* Pointer to first InterpPackage structure
* for interp. */
- Tcl_Interp *interp; /* Interpreter that is being deleted. */
+ Tcl_Interp *interp) /* Interpreter that is being deleted. */
{
InterpPackage *ipPtr, *nextPtr;
@@ -648,8 +1114,8 @@ LoadCleanupProc(clientData, interp)
*
* TclFinalizeLoad --
*
- * This procedure is invoked just before the application exits.
- * It frees all of the LoadedPackage structures.
+ * This function is invoked just before the application exits. It frees
+ * all of the LoadedPackage structures.
*
* Results:
* None.
@@ -661,38 +1127,49 @@ LoadCleanupProc(clientData, interp)
*/
void
-TclFinalizeLoad()
+TclFinalizeLoad(void)
{
LoadedPackage *pkgPtr;
/*
- * No synchronization here because there should just be
- * one thread alive at this point. Logically,
- * packageMutex should be grabbed at this point, but
- * the Mutexes get finalized before the call to this routine.
- * The only subsystem left alive at this point is the
- * memory allocator.
+ * No synchronization here because there should just be one thread alive
+ * at this point. Logically, packageMutex should be grabbed at this point,
+ * but the Mutexes get finalized before the call to this routine. The
+ * only subsystem left alive at this point is the memory allocator.
*/
while (firstPackagePtr != NULL) {
pkgPtr = firstPackagePtr;
firstPackagePtr = pkgPtr->nextPtr;
+
#if defined(TCL_UNLOAD_DLLS) || defined(__WIN32__)
/*
- * Some Unix dlls are poorly behaved - registering things like
- * atexit calls that can't be unregistered. If you unload
- * such dlls, you get a core on exit because it wants to
- * call a function in the dll after it's been unloaded.
+ * Some Unix dlls are poorly behaved - registering things like atexit
+ * calls that can't be unregistered. If you unload such dlls, you get
+ * a core on exit because it wants to call a function in the dll after
+ * it has been unloaded.
*/
+
if (pkgPtr->fileName[0] != '\0') {
Tcl_FSUnloadFileProc *unLoadProcPtr = pkgPtr->unLoadProcPtr;
- if (unLoadProcPtr != NULL) {
- (*unLoadProcPtr)(pkgPtr->loadHandle);
+ if ((unLoadProcPtr != NULL)
+ && ((pkgPtr->unloadProc != NULL)
+ || (unLoadProcPtr == TclFSUnloadTempFile))) {
+ (*unLoadProcPtr)(pkgPtr->loadHandle);
}
}
#endif
+
ckfree(pkgPtr->fileName);
ckfree(pkgPtr->packageName);
ckfree((char *) pkgPtr);
}
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclLoadNone.c b/generic/tclLoadNone.c
index 4f795aa..d328a41 100644
--- a/generic/tclLoadNone.c
+++ b/generic/tclLoadNone.c
@@ -1,14 +1,13 @@
-/*
+/*
* tclLoadNone.c --
*
- * This procedure provides a version of the TclLoadFile for use
- * in systems that don't support dynamic loading; it just returns
- * an error.
+ * This procedure provides a version of the TclLoadFile for use in
+ * systems that don't support dynamic loading; it just returns an error.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
@@ -18,13 +17,13 @@
*
* TclpDlopen --
*
- * This procedure is called to carry out dynamic loading of binary
- * code; it is intended for use only on systems that don't support
- * dynamic loading (it returns an error).
+ * This procedure is called to carry out dynamic loading of binary code;
+ * it is intended for use only on systems that don't support dynamic
+ * loading (it returns an error).
*
* Results:
- * The result is TCL_ERROR, and an error message is left in
- * the interp's result.
+ * The result is TCL_ERROR, and an error message is left in the interp's
+ * result.
*
* Side effects:
* None.
@@ -33,17 +32,17 @@
*/
int
-TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Obj *pathPtr; /* Name of the file containing the desired
+TclpDlopen(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *pathPtr, /* Name of the file containing the desired
* code (UTF-8). */
- Tcl_LoadHandle *loadHandle; /* Filled with token for dynamically loaded
- * file which will be passed back to
+ Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
+ * file which will be passed back to
* (*unloadProcPtr)() to unload the file. */
- Tcl_FSUnloadFileProc **unloadProcPtr;
+ Tcl_FSUnloadFileProc **unloadProcPtr)
/* Filled with address of Tcl_FSUnloadFileProc
- * function which should be used for
- * this file. */
+ * function which should be used for this
+ * file. */
{
Tcl_SetResult(interp,
"dynamic loading is not currently available on this system",
@@ -56,21 +55,24 @@ TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr)
*
* TclpFindSymbol --
*
- * Looks up a symbol, by name, through a handle associated with
- * a previously loaded piece of code (shared library).
+ * Looks up a symbol, by name, through a handle associated with a
+ * previously loaded piece of code (shared library). This version of this
+ * routine should never be called because the associated TclpDlopen()
+ * function always returns an error.
*
* Results:
- * Returns a pointer to the function associated with 'symbol' if
- * it is found. Otherwise returns NULL and may leave an error
- * message in the interp's result.
+ * Returns a pointer to the function associated with 'symbol' if it is
+ * found. Otherwise returns NULL and may leave an error message in the
+ * interp's result.
*
*----------------------------------------------------------------------
*/
-Tcl_PackageInitProc*
-TclpFindSymbol(interp, loadHandle, symbol)
- Tcl_Interp *interp;
- Tcl_LoadHandle loadHandle;
- CONST char *symbol;
+
+Tcl_PackageInitProc *
+TclpFindSymbol(
+ Tcl_Interp *interp,
+ Tcl_LoadHandle loadHandle,
+ CONST char *symbol)
{
return NULL;
}
@@ -80,14 +82,14 @@ TclpFindSymbol(interp, loadHandle, symbol)
*
* TclGuessPackageName --
*
- * If the "load" command is invoked without providing a package
- * name, this procedure is invoked to try to figure it out.
+ * If the "load" command is invoked without providing a package name,
+ * this procedure is invoked to try to figure it out.
*
* Results:
- * Always returns 0 to indicate that we couldn't figure out a
- * package name; generic code will then try to guess the package
- * from the file name. A return value of 1 would have meant that
- * we figured out the package name and put it in bufPtr.
+ * Always returns 0 to indicate that we couldn't figure out a package
+ * name; generic code will then try to guess the package from the file
+ * name. A return value of 1 would have meant that we figured out the
+ * package name and put it in bufPtr.
*
* Side effects:
* None.
@@ -96,11 +98,11 @@ TclpFindSymbol(interp, loadHandle, symbol)
*/
int
-TclGuessPackageName(fileName, bufPtr)
- CONST char *fileName; /* Name of file containing package (already
+TclGuessPackageName(
+ CONST char *fileName, /* Name of file containing package (already
* translated to local form if needed). */
- Tcl_DString *bufPtr; /* Initialized empty dstring. Append
- * package name to this if possible. */
+ Tcl_DString *bufPtr) /* Initialized empty dstring. Append package
+ * name to this if possible. */
{
return 0;
}
@@ -110,9 +112,9 @@ TclGuessPackageName(fileName, bufPtr)
*
* TclpUnloadFile --
*
- * This procedure is called to carry out dynamic unloading of binary
- * code; it is intended for use only on systems that don't support
- * dynamic loading (it does nothing).
+ * This procedure is called to carry out dynamic unloading of binary code;
+ * it is intended for use only on systems that don't support dynamic
+ * loading (it does nothing).
*
* Results:
* None.
@@ -124,10 +126,17 @@ TclGuessPackageName(fileName, bufPtr)
*/
void
-TclpUnloadFile(loadHandle)
- Tcl_LoadHandle loadHandle; /* loadHandle returned by a previous call
- * to TclpDlopen(). The loadHandle is
- * a token that represents the loaded
- * file. */
+TclpUnloadFile(
+ Tcl_LoadHandle loadHandle) /* loadHandle returned by a previous call to
+ * TclpDlopen(). The loadHandle is a token
+ * that represents the loaded file. */
{
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclMain.c b/generic/tclMain.c
index 8252170..7a19a38 100644
--- a/generic/tclMain.c
+++ b/generic/tclMain.c
@@ -1,4 +1,4 @@
-/*
+/*
* tclMain.c --
*
* Main program for Tcl shells and other Tcl-based applications.
@@ -7,104 +7,177 @@
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
* Copyright (c) 2000 Ajuba Solutions.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
-#include "tcl.h"
#include "tclInt.h"
-# undef TCL_STORAGE_CLASS
-# define TCL_STORAGE_CLASS DLLEXPORT
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLEXPORT
/*
- * Declarations for various library procedures and variables (don't want
- * to include tclPort.h here, because people might copy this file out of
- * the Tcl source directory to make their own modified versions).
+ * The default prompt used when the user has not overridden it.
*/
-#if !defined(MAC_TCL)
-extern int isatty _ANSI_ARGS_((int fd));
-#else
-#include <unistd.h>
-#endif
+#define DEFAULT_PRIMARY_PROMPT "% "
-static Tcl_Obj *tclStartupScriptPath = NULL;
+/*
+ * Declarations for various library functions and variables (don't want to
+ * include tclPort.h here, because people might copy this file out of the Tcl
+ * source directory to make their own modified versions).
+ */
+extern CRTIMPORT int isatty(int fd);
+
+static Tcl_Obj *tclStartupScriptPath = NULL;
+static Tcl_Obj *tclStartupScriptEncoding = NULL;
static Tcl_MainLoopProc *mainLoopProc = NULL;
-/*
- * Structure definition for information used to keep the state of
- * an interactive command processor that reads lines from standard
- * input and writes prompts and results to standard output.
+/*
+ * Structure definition for information used to keep the state of an
+ * interactive command processor that reads lines from standard input and
+ * writes prompts and results to standard output.
*/
typedef enum {
- PROMPT_NONE, /* Print no prompt */
- PROMPT_START, /* Print prompt for command start */
- PROMPT_CONTINUE /* Print prompt for command continuation */
+ PROMPT_NONE, /* Print no prompt */
+ PROMPT_START, /* Print prompt for command start */
+ PROMPT_CONTINUE /* Print prompt for command continuation */
} PromptType;
typedef struct InteractiveState {
- Tcl_Channel input; /* The standard input channel from which
- * lines are read. */
- int tty; /* Non-zero means standard input is a
- * terminal-like device. Zero means it's
- * a file. */
- Tcl_Obj *commandPtr; /* Used to assemble lines of input into
- * Tcl commands. */
+ Tcl_Channel input; /* The standard input channel from which lines
+ * are read. */
+ int tty; /* Non-zero means standard input is a
+ * terminal-like device. Zero means it's a
+ * file. */
+ Tcl_Obj *commandPtr; /* Used to assemble lines of input into Tcl
+ * commands. */
PromptType prompt; /* Next prompt to print */
Tcl_Interp *interp; /* Interpreter that evaluates interactive
* commands. */
} InteractiveState;
/*
- * Forward declarations for procedures defined later in this file.
+ * Forward declarations for functions defined later in this file.
*/
-static void Prompt _ANSI_ARGS_((Tcl_Interp *interp,
- PromptType *promptPtr));
-static void StdinProc _ANSI_ARGS_((ClientData clientData,
- int mask));
-
+static void Prompt(Tcl_Interp *interp, PromptType *promptPtr);
+static void StdinProc(ClientData clientData, int mask);
/*
*----------------------------------------------------------------------
*
- * TclSetStartupScriptPath --
+ * Tcl_SetStartupScript --
*
- * Primes the startup script VFS path, used to override the
- * command line processing.
+ * Sets the path and encoding of the startup script to be evaluated by
+ * Tcl_Main, used to override the command line processing.
*
* Results:
- * None.
+ * None.
*
* Side effects:
- * This procedure initializes the VFS path of the Tcl script to
- * run at startup.
*
*----------------------------------------------------------------------
*/
-void TclSetStartupScriptPath(pathPtr)
- Tcl_Obj *pathPtr;
+
+void
+Tcl_SetStartupScript(
+ Tcl_Obj *path, /* Filesystem path of startup script file */
+ CONST char *encoding) /* Encoding of the data in that file */
{
+ Tcl_Obj *newEncoding = NULL;
+ if (encoding != NULL) {
+ newEncoding = Tcl_NewStringObj(encoding, -1);
+ }
+
if (tclStartupScriptPath != NULL) {
Tcl_DecrRefCount(tclStartupScriptPath);
}
- tclStartupScriptPath = pathPtr;
+ tclStartupScriptPath = path;
if (tclStartupScriptPath != NULL) {
Tcl_IncrRefCount(tclStartupScriptPath);
}
+
+ if (tclStartupScriptEncoding != NULL) {
+ Tcl_DecrRefCount(tclStartupScriptEncoding);
+ }
+ tclStartupScriptEncoding = newEncoding;
+ if (tclStartupScriptEncoding != NULL) {
+ Tcl_IncrRefCount(tclStartupScriptEncoding);
+ }
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetStartupScript --
+ *
+ * Gets the path and encoding of the startup script to be evaluated by
+ * Tcl_Main.
+ *
+ * Results:
+ * The path of the startup script; NULL if none has been set.
+ *
+ * Side effects:
+ * If encodingPtr is not NULL, stores a (CONST char *) in it pointing to
+ * the encoding name registered for the startup script. Tcl retains
+ * ownership of the string, and may free it. Caller should make a copy
+ * for long-term use.
+ *
+ *----------------------------------------------------------------------
+ */
+Tcl_Obj *
+Tcl_GetStartupScript(
+ CONST char **encodingPtr) /* When not NULL, points to storage for the
+ * (CONST char *) that points to the
+ * registered encoding name for the startup
+ * script */
+{
+ if (encodingPtr != NULL) {
+ if (tclStartupScriptEncoding == NULL) {
+ *encodingPtr = NULL;
+ } else {
+ *encodingPtr = Tcl_GetString(tclStartupScriptEncoding);
+ }
+ }
+ return tclStartupScriptPath;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclSetStartupScriptPath --
+ *
+ * Primes the startup script VFS path, used to override the command line
+ * processing.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * This function initializes the VFS path of the Tcl script to run at
+ * startup.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+TclSetStartupScriptPath(
+ Tcl_Obj *path)
+{
+ Tcl_SetStartupScript(path, NULL);
+}
+
/*
*----------------------------------------------------------------------
*
* TclGetStartupScriptPath --
*
- * Gets the startup script VFS path, used to override the
- * command line processing.
+ * Gets the startup script VFS path, used to override the command line
+ * processing.
*
* Results:
* The startup script VFS path, NULL if none has been set.
@@ -114,44 +187,46 @@ void TclSetStartupScriptPath(pathPtr)
*
*----------------------------------------------------------------------
*/
-Tcl_Obj *TclGetStartupScriptPath()
+
+Tcl_Obj *
+TclGetStartupScriptPath(void)
{
- return tclStartupScriptPath;
+ return Tcl_GetStartupScript(NULL);
}
-
-
+
/*
*----------------------------------------------------------------------
*
* TclSetStartupScriptFileName --
*
- * Primes the startup script file name, used to override the
- * command line processing.
+ * Primes the startup script file name, used to override the command line
+ * processing.
*
* Results:
- * None.
+ * None.
*
* Side effects:
- * This procedure initializes the file name of the Tcl script to
- * run at startup.
+ * This function initializes the file name of the Tcl script to run at
+ * startup.
*
*----------------------------------------------------------------------
*/
-void TclSetStartupScriptFileName(fileName)
- CONST char *fileName;
+
+void
+TclSetStartupScriptFileName(
+ CONST char *fileName)
{
- Tcl_Obj *pathPtr = Tcl_NewStringObj(fileName,-1);
- TclSetStartupScriptPath(pathPtr);
+ Tcl_Obj *path = Tcl_NewStringObj(fileName,-1);
+ Tcl_SetStartupScript(path, NULL);
}
-
/*
*----------------------------------------------------------------------
*
* TclGetStartupScriptFileName --
*
- * Gets the startup script file name, used to override the
- * command line processing.
+ * Gets the startup script file name, used to override the command line
+ * processing.
*
* Results:
* The startup script file name, NULL if none has been set.
@@ -161,54 +236,111 @@ void TclSetStartupScriptFileName(fileName)
*
*----------------------------------------------------------------------
*/
-CONST char *TclGetStartupScriptFileName()
+
+CONST char *
+TclGetStartupScriptFileName(void)
{
- Tcl_Obj *pathPtr = TclGetStartupScriptPath();
+ Tcl_Obj *path = Tcl_GetStartupScript(NULL);
- if (pathPtr == NULL) {
+ if (path == NULL) {
return NULL;
}
- return Tcl_GetString(pathPtr);
+ return Tcl_GetString(path);
}
+
+/*----------------------------------------------------------------------
+ *
+ * Tcl_SourceRCFile --
+ *
+ * This function is typically invoked by Tcl_Main of Tk_Main function to
+ * source an application specific rc file into the interpreter at startup
+ * time.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depends on what's in the rc script.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SourceRCFile(
+ Tcl_Interp *interp) /* Interpreter to source rc file into. */
+{
+ Tcl_DString temp;
+ CONST char *fileName;
+ Tcl_Channel errChannel;
+ fileName = Tcl_GetVar(interp, "tcl_rcFileName", TCL_GLOBAL_ONLY);
+ if (fileName != NULL) {
+ Tcl_Channel c;
+ CONST char *fullName;
+ Tcl_DStringInit(&temp);
+ fullName = Tcl_TranslateFileName(interp, fileName, &temp);
+ if (fullName == NULL) {
+ /*
+ * Couldn't translate the file name (e.g. it referred to a bogus
+ * user or there was no HOME environment variable). Just do
+ * nothing.
+ */
+ } else {
+ /*
+ * Test for the existence of the rc file before trying to read it.
+ */
+
+ c = Tcl_OpenFileChannel(NULL, fullName, "r", 0);
+ if (c != (Tcl_Channel) NULL) {
+ Tcl_Close(NULL, c);
+ if (Tcl_EvalFile(interp, fullName) != TCL_OK) {
+ errChannel = Tcl_GetStdChannel(TCL_STDERR);
+ if (errChannel) {
+ Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
+ Tcl_WriteChars(errChannel, "\n", 1);
+ }
+ }
+ }
+ }
+ Tcl_DStringFree(&temp);
+ }
+}
-/*
- *----------------------------------------------------------------------
+/*----------------------------------------------------------------------
*
* Tcl_Main --
*
* Main program for tclsh and most other Tcl-based applications.
*
* Results:
- * None. This procedure never returns (it exits the process when
- * it's done).
+ * None. This function never returns (it exits the process when it's
+ * done).
*
* Side effects:
- * This procedure initializes the Tcl world and then starts
- * interpreting commands; almost anything could happen, depending
- * on the script being interpreted.
+ * This function initializes the Tcl world and then starts interpreting
+ * commands; almost anything could happen, depending on the script being
+ * interpreted.
*
*----------------------------------------------------------------------
*/
void
-Tcl_Main(argc, argv, appInitProc)
- int argc; /* Number of arguments. */
- char **argv; /* Array of argument strings. */
- Tcl_AppInitProc *appInitProc;
+Tcl_Main(
+ int argc, /* Number of arguments. */
+ char **argv, /* Array of argument strings. */
+ Tcl_AppInitProc *appInitProc)
/* Application-specific initialization
- * procedure to call after most
- * initialization but before starting to
- * execute commands. */
+ * function to call after most initialization
+ * but before starting to execute commands. */
{
- Tcl_Obj *resultPtr, *argvPtr, *commandPtr = NULL;
+ Tcl_Obj *path, *resultPtr, *argvPtr, *commandPtr = NULL;
+ CONST char *encodingName = NULL;
PromptType prompt = PROMPT_START;
int code, length, tty, exitCode = 0;
Tcl_Channel inChannel, outChannel, errChannel;
Tcl_Interp *interp;
Tcl_DString appName;
- Tcl_Obj *objPtr;
Tcl_FindExecutable(argv[0]);
@@ -216,35 +348,48 @@ Tcl_Main(argc, argv, appInitProc)
Tcl_InitMemory(interp);
/*
- * Make command-line arguments available in the Tcl variables "argc"
- * and "argv". If the first argument doesn't start with a "-" then
- * strip it off and use it as the name of a script file to process.
+ * If the application has not already set a startup script, parse the
+ * first few command line arguments to determine the script path and
+ * encoding.
*/
- if (TclGetStartupScriptPath() == NULL) {
- if ((argc > 1) && (argv[1][0] != '-')) {
- TclSetStartupScriptFileName(argv[1]);
+ if (NULL == Tcl_GetStartupScript(NULL)) {
+
+ /*
+ * Check whether first 3 args (argv[1] - argv[3]) look like
+ * -encoding ENCODING FILENAME
+ * or like
+ * FILENAME
+ */
+
+ if ((argc > 3) && (0 == strcmp("-encoding", argv[1]))
+ && ('-' != argv[3][0])) {
+ Tcl_SetStartupScript(Tcl_NewStringObj(argv[3], -1), argv[2]);
+ argc -= 3;
+ argv += 3;
+ } else if ((argc > 1) && ('-' != argv[1][0])) {
+ Tcl_SetStartupScript(Tcl_NewStringObj(argv[1], -1), NULL);
argc--;
argv++;
}
}
- if (TclGetStartupScriptPath() == NULL) {
+ path = Tcl_GetStartupScript(&encodingName);
+ if (path == NULL) {
Tcl_ExternalToUtfDString(NULL, argv[0], -1, &appName);
} else {
- TclSetStartupScriptFileName(Tcl_ExternalToUtfDString(NULL,
- TclGetStartupScriptFileName(), -1, &appName));
+ CONST char *pathName = Tcl_GetStringFromObj(path, &length);
+ Tcl_ExternalToUtfDString(NULL, pathName, length, &appName);
+ path = Tcl_NewStringObj(Tcl_DStringValue(&appName), -1);
+ Tcl_SetStartupScript(path, encodingName);
}
Tcl_SetVar(interp, "argv0", Tcl_DStringValue(&appName), TCL_GLOBAL_ONLY);
Tcl_DStringFree(&appName);
argc--;
argv++;
- objPtr = Tcl_NewIntObj(argc);
- Tcl_IncrRefCount(objPtr);
- Tcl_SetVar2Ex(interp, "argc", NULL, objPtr, TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(objPtr);
-
+ Tcl_SetVar2Ex(interp, "argc", NULL, Tcl_NewIntObj(argc), TCL_GLOBAL_ONLY);
+
argvPtr = Tcl_NewListObj(0, NULL);
while (argc--) {
Tcl_DString ds;
@@ -253,19 +398,16 @@ Tcl_Main(argc, argv, appInitProc)
Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)));
Tcl_DStringFree(&ds);
}
- Tcl_IncrRefCount(argvPtr);
Tcl_SetVar2Ex(interp, "argv", NULL, argvPtr, TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(argvPtr);
/*
* Set the "tcl_interactive" variable.
*/
tty = isatty(0);
- Tcl_SetVar(interp, "tcl_interactive",
- ((TclGetStartupScriptPath() == NULL) && tty) ? "1" : "0",
+ Tcl_SetVar(interp, "tcl_interactive", ((path == NULL) && tty) ? "1" : "0",
TCL_GLOBAL_ONLY);
-
+
/*
* Invoke application-specific initialization.
*/
@@ -283,27 +425,34 @@ Tcl_Main(argc, argv, appInitProc)
if (Tcl_InterpDeleted(interp)) {
goto done;
}
+ if (Tcl_LimitExceeded(interp)) {
+ goto done;
+ }
/*
- * If a script file was specified then just source that file
- * and quit.
+ * If a script file was specified then just source that file and quit.
+ * Must fetch it again, as the appInitProc might have reset it.
*/
- if (TclGetStartupScriptPath() != NULL) {
- code = Tcl_FSEvalFile(interp, TclGetStartupScriptPath());
+ path = Tcl_GetStartupScript(&encodingName);
+ if (path != NULL) {
+ code = Tcl_FSEvalFileEx(interp, path, encodingName);
if (code != TCL_OK) {
errChannel = Tcl_GetStdChannel(TCL_STDERR);
if (errChannel) {
+ Tcl_Obj *options = Tcl_GetReturnOptions(interp, code);
+ Tcl_Obj *keyPtr, *valuePtr;
- /*
- * The following statement guarantees that the errorInfo
- * variable is set properly.
- */
+ TclNewLiteralStringObj(keyPtr, "-errorinfo");
+ Tcl_IncrRefCount(keyPtr);
+ Tcl_DictObjGet(NULL, options, keyPtr, &valuePtr);
+ Tcl_DecrRefCount(keyPtr);
- Tcl_AddErrorInfo(interp, "");
- Tcl_WriteObj(errChannel, Tcl_GetVar2Ex(interp, "errorInfo",
- NULL, TCL_GLOBAL_ONLY));
+ if (valuePtr) {
+ Tcl_WriteObj(errChannel, valuePtr);
+ }
Tcl_WriteChars(errChannel, "\n", 1);
+ Tcl_DecrRefCount(options);
}
exitCode = 1;
}
@@ -311,16 +460,19 @@ Tcl_Main(argc, argv, appInitProc)
}
/*
- * We're running interactively. Source a user-specific startup
- * file if the application specified one and if the file exists.
+ * We're running interactively. Source a user-specific startup file if the
+ * application specified one and if the file exists.
*/
Tcl_SourceRCFile(interp);
+ if (Tcl_LimitExceeded(interp)) {
+ goto done;
+ }
/*
- * Process commands from stdin until there's an end-of-file. Note
- * that we need to fetch the standard channels again after every
- * eval, since they may have been changed.
+ * Process commands from stdin until there's an end-of-file. Note that we
+ * need to fetch the standard channels again after every eval, since they
+ * may have been changed.
*/
commandPtr = Tcl_NewObj();
@@ -329,6 +481,7 @@ Tcl_Main(argc, argv, appInitProc)
/*
* Get a new value for tty if anyone writes to ::tcl_interactive
*/
+
Tcl_LinkVar(interp, "tcl_interactive", (char *) &tty, TCL_LINK_BOOLEAN);
inChannel = Tcl_GetStdChannel(TCL_STDIN);
outChannel = Tcl_GetStdChannel(TCL_STDOUT);
@@ -339,9 +492,12 @@ Tcl_Main(argc, argv, appInitProc)
if (Tcl_InterpDeleted(interp)) {
break;
}
+ if (Tcl_LimitExceeded(interp)) {
+ break;
+ }
inChannel = Tcl_GetStdChannel(TCL_STDIN);
if (inChannel == (Tcl_Channel) NULL) {
- break;
+ break;
}
}
if (Tcl_IsShared(commandPtr)) {
@@ -349,32 +505,32 @@ Tcl_Main(argc, argv, appInitProc)
commandPtr = Tcl_DuplicateObj(commandPtr);
Tcl_IncrRefCount(commandPtr);
}
- length = Tcl_GetsObj(inChannel, commandPtr);
+ length = Tcl_GetsObj(inChannel, commandPtr);
if (length < 0) {
if (Tcl_InputBlocked(inChannel)) {
-
/*
* This can only happen if stdin has been set to
- * non-blocking. In that case cycle back and try
- * again. This sets up a tight polling loop (since
- * we have no event loop running). If this causes
- * bad CPU hogging, we might try toggling the blocking
- * on stdin instead.
+ * non-blocking. In that case cycle back and try again.
+ * This sets up a tight polling loop (since we have no
+ * event loop running). If this causes bad CPU hogging,
+ * we might try toggling the blocking on stdin instead.
*/
continue;
}
- /*
+ /*
* Either EOF, or an error on stdin; we're done
*/
break;
}
- /*
- * Add the newline removed by Tcl_GetsObj back to the string.
- */
+ /*
+ * Add the newline removed by Tcl_GetsObj back to the string.
+ * Have to add it back before testing completeness, because
+ * it can make a difference. [Bug 1775878].
+ */
if (Tcl_IsShared(commandPtr)) {
Tcl_DecrRefCount(commandPtr);
@@ -388,6 +544,12 @@ Tcl_Main(argc, argv, appInitProc)
}
prompt = PROMPT_START;
+ /*
+ * The final newline is syntactically redundant, and causes
+ * some error messages troubles deeper in, so lop it back off.
+ */
+ Tcl_GetStringFromObj(commandPtr, &length);
+ Tcl_SetObjLength(commandPtr, --length);
code = Tcl_RecordAndEvalObj(interp, commandPtr, TCL_EVAL_GLOBAL);
inChannel = Tcl_GetStdChannel(TCL_STDIN);
outChannel = Tcl_GetStdChannel(TCL_STDOUT);
@@ -400,7 +562,7 @@ Tcl_Main(argc, argv, appInitProc)
Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
Tcl_WriteChars(errChannel, "\n", 1);
}
- } else if (tty) {
+ } else if (tty) {
resultPtr = Tcl_GetObjResult(interp);
Tcl_IncrRefCount(resultPtr);
Tcl_GetStringFromObj(resultPtr, &length);
@@ -412,18 +574,18 @@ Tcl_Main(argc, argv, appInitProc)
}
} else { /* (mainLoopProc != NULL) */
/*
- * If a main loop has been defined while running interactively,
- * we want to start a fileevent based prompt by establishing a
+ * If a main loop has been defined while running interactively, we
+ * want to start a fileevent based prompt by establishing a
* channel handler for stdin.
*/
InteractiveState *isPtr = NULL;
if (inChannel) {
- if (tty) {
+ if (tty) {
Prompt(interp, &prompt);
- }
- isPtr = (InteractiveState *)
+ }
+ isPtr = (InteractiveState *)
ckalloc((int) sizeof(InteractiveState));
isPtr->input = inChannel;
isPtr->tty = tty;
@@ -462,8 +624,8 @@ Tcl_Main(argc, argv, appInitProc)
#ifdef TCL_MEM_DEBUG
/*
- * This code here only for the (unsupported and deprecated)
- * [checkmem] command.
+ * This code here only for the (unsupported and deprecated) [checkmem]
+ * command.
*/
if (tclMemDumpFileName != NULL) {
@@ -473,13 +635,13 @@ Tcl_Main(argc, argv, appInitProc)
#endif
}
- done:
- if ((exitCode == 0) && (mainLoopProc != NULL)) {
-
+ done:
+ if ((exitCode == 0) && (mainLoopProc != NULL)
+ && !Tcl_LimitExceeded(interp)) {
/*
- * If everything has gone OK so far, call the main loop proc,
- * if it exists. Packages (like Tk) can set it to start processing
- * events at this point.
+ * If everything has gone OK so far, call the main loop proc, if it
+ * exists. Packages (like Tk) can set it to start processing events at
+ * this point.
*/
(*mainLoopProc)();
@@ -490,32 +652,35 @@ Tcl_Main(argc, argv, appInitProc)
}
/*
- * Rather than calling exit, invoke the "exit" command so that
- * users can replace "exit" with some other command to do additional
- * cleanup on exit. The Tcl_Eval call should never return.
+ * Rather than calling exit, invoke the "exit" command so that users can
+ * replace "exit" with some other command to do additional cleanup on
+ * exit. The Tcl_EvalObjEx call should never return.
*/
if (!Tcl_InterpDeleted(interp)) {
- char buffer[TCL_INTEGER_SPACE + 5];
- sprintf(buffer, "exit %d", exitCode);
- Tcl_Eval(interp, buffer);
-
- /*
- * If Tcl_Eval returns, trying to eval [exit], something
- * unusual is happening. Maybe interp has been deleted;
- * maybe [exit] was redefined. We still want to cleanup
- * and exit.
- */
-
- if (!Tcl_InterpDeleted(interp)) {
- Tcl_DeleteInterp(interp);
- }
+ if (!Tcl_LimitExceeded(interp)) {
+ Tcl_Obj *cmd = Tcl_ObjPrintf("exit %d", exitCode);
+ Tcl_IncrRefCount(cmd);
+ Tcl_EvalObjEx(interp, cmd, TCL_EVAL_GLOBAL);
+ Tcl_DecrRefCount(cmd);
+ }
+
+ /*
+ * If Tcl_EvalObjEx returns, trying to eval [exit], something unusual
+ * is happening. Maybe interp has been deleted; maybe [exit] was
+ * redefined, maybe we've blown up because of an exceeded limit. We
+ * still want to cleanup and exit.
+ */
+
+ if (!Tcl_InterpDeleted(interp)) {
+ Tcl_DeleteInterp(interp);
+ }
}
- TclSetStartupScriptPath(NULL);
+ Tcl_SetStartupScript(NULL, NULL);
/*
- * If we get here, the master interp has been deleted. Allow
- * its destruction with the last matching Tcl_Release.
+ * If we get here, the master interp has been deleted. Allow its
+ * destruction with the last matching Tcl_Release.
*/
Tcl_Release((ClientData) interp);
@@ -527,21 +692,21 @@ Tcl_Main(argc, argv, appInitProc)
*
* Tcl_SetMainLoop --
*
- * Sets an alternative main loop procedure.
+ * Sets an alternative main loop function.
*
* Results:
- * Returns the previously defined main loop procedure.
+ * Returns the previously defined main loop function.
*
* Side effects:
- * This procedure will be called before Tcl exits, allowing for
- * the creation of an event loop.
+ * This function will be called before Tcl exits, allowing for the
+ * creation of an event loop.
*
*---------------------------------------------------------------
*/
void
-Tcl_SetMainLoop(proc)
- Tcl_MainLoopProc *proc;
+Tcl_SetMainLoop(
+ Tcl_MainLoopProc *proc)
{
mainLoopProc = proc;
}
@@ -551,26 +716,25 @@ Tcl_SetMainLoop(proc)
*
* StdinProc --
*
- * This procedure is invoked by the event dispatcher whenever
- * standard input becomes readable. It grabs the next line of
- * input characters, adds them to a command being assembled, and
- * executes the command if it's complete.
+ * This function is invoked by the event dispatcher whenever standard
+ * input becomes readable. It grabs the next line of input characters,
+ * adds them to a command being assembled, and executes the command if
+ * it's complete.
*
* Results:
* None.
*
* Side effects:
- * Could be almost arbitrary, depending on the command that's
- * typed.
+ * Could be almost arbitrary, depending on the command that's typed.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
static void
-StdinProc(clientData, mask)
- ClientData clientData; /* The state of interactive cmd line */
- int mask; /* Not used. */
+StdinProc(
+ ClientData clientData, /* The state of interactive cmd line */
+ int mask) /* Not used. */
{
InteractiveState *isPtr = (InteractiveState *) clientData;
Tcl_Channel chan = isPtr->input;
@@ -590,10 +754,11 @@ StdinProc(clientData, mask)
}
if (isPtr->tty) {
/*
- * Would be better to find a way to exit the mainLoop?
- * Or perhaps evaluate [exit]? Leaving as is for now due
- * to compatibility concerns.
+ * Would be better to find a way to exit the mainLoop? Or perhaps
+ * evaluate [exit]? Leaving as is for now due to compatibility
+ * concerns.
*/
+
Tcl_Exit(0);
}
Tcl_DeleteChannelHandler(chan, StdinProc, (ClientData) isPtr);
@@ -607,17 +772,18 @@ StdinProc(clientData, mask)
}
Tcl_AppendToObj(commandPtr, "\n", 1);
if (!TclObjCommandComplete(commandPtr)) {
- isPtr->prompt = PROMPT_CONTINUE;
- goto prompt;
+ isPtr->prompt = PROMPT_CONTINUE;
+ goto prompt;
}
isPtr->prompt = PROMPT_START;
+ Tcl_GetStringFromObj(commandPtr, &length);
+ Tcl_SetObjLength(commandPtr, --length);
/*
* Disable the stdin channel handler while evaluating the command;
- * otherwise if the command re-enters the event loop we might
- * process commands from stdin before the current command is
- * finished. Among other things, this will trash the text of the
- * command being evaluated.
+ * otherwise if the command re-enters the event loop we might process
+ * commands from stdin before the current command is finished. Among other
+ * things, this will trash the text of the command being evaluated.
*/
Tcl_CreateChannelHandler(chan, 0, StdinProc, (ClientData) isPtr);
@@ -652,7 +818,7 @@ StdinProc(clientData, mask)
* If a tty stdin is still around, output a prompt.
*/
- prompt:
+ prompt:
if (isPtr->tty && (isPtr->input != (Tcl_Channel) NULL)) {
Prompt(interp, &(isPtr->prompt));
isPtr->input = Tcl_GetStdChannel(TCL_STDIN);
@@ -664,25 +830,24 @@ StdinProc(clientData, mask)
*
* Prompt --
*
- * Issue a prompt on standard output, or invoke a script
- * to issue the prompt.
+ * Issue a prompt on standard output, or invoke a script to issue the
+ * prompt.
*
* Results:
* None.
*
* Side effects:
- * A prompt gets output, and a Tcl script may be evaluated
- * in interp.
+ * A prompt gets output, and a Tcl script may be evaluated in interp.
*
*----------------------------------------------------------------------
*/
static void
-Prompt(interp, promptPtr)
- Tcl_Interp *interp; /* Interpreter to use for prompting. */
- PromptType *promptPtr; /* Points to type of prompt to print.
- * Filled with PROMPT_NONE after a
- * prompt is printed. */
+Prompt(
+ Tcl_Interp *interp, /* Interpreter to use for prompting. */
+ PromptType *promptPtr) /* Points to type of prompt to print. Filled
+ * with PROMPT_NONE after a prompt is
+ * printed. */
{
Tcl_Obj *promptCmdPtr;
int code;
@@ -695,15 +860,17 @@ Prompt(interp, promptPtr)
promptCmdPtr = Tcl_GetVar2Ex(interp,
((*promptPtr == PROMPT_CONTINUE) ? "tcl_prompt2" : "tcl_prompt1"),
NULL, TCL_GLOBAL_ONLY);
+
if (Tcl_InterpDeleted(interp)) {
return;
}
if (promptCmdPtr == NULL) {
- defaultPrompt:
+ defaultPrompt:
outChannel = Tcl_GetStdChannel(TCL_STDOUT);
if ((*promptPtr == PROMPT_START)
&& (outChannel != (Tcl_Channel) NULL)) {
- Tcl_WriteChars(outChannel, "% ", 2);
+ Tcl_WriteChars(outChannel, DEFAULT_PRIMARY_PROMPT,
+ strlen(DEFAULT_PRIMARY_PROMPT));
}
} else {
code = Tcl_EvalObjEx(interp, promptCmdPtr, TCL_EVAL_GLOBAL);
@@ -711,16 +878,25 @@ Prompt(interp, promptPtr)
Tcl_AddErrorInfo(interp,
"\n (script that generates prompt)");
errChannel = Tcl_GetStdChannel(TCL_STDERR);
- if (errChannel != (Tcl_Channel) NULL) {
- Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
- Tcl_WriteChars(errChannel, "\n", 1);
- }
+ if (errChannel != (Tcl_Channel) NULL) {
+ Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
+ Tcl_WriteChars(errChannel, "\n", 1);
+ }
goto defaultPrompt;
}
}
+
outChannel = Tcl_GetStdChannel(TCL_STDOUT);
if (outChannel != (Tcl_Channel) NULL) {
Tcl_Flush(outChannel);
}
*promptPtr = PROMPT_NONE;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclMath.h b/generic/tclMath.h
deleted file mode 100644
index 7492af0..0000000
--- a/generic/tclMath.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * tclMath.h --
- *
- * This file is necessary because of Metrowerks CodeWarrior Pro 1
- * on the Macintosh. With 8-byte doubles turned on, the definitions of
- * sin, cos, acos, etc., are screwed up. They are fine as long as
- * they are used as function calls, but if the function pointers
- * are passed around and used, they will crash hard on the 68K.
- *
- * Copyright (c) 1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#ifndef _TCLMATH
-#define _TCLMATH
-
-#if defined(MAC_TCL)
-# include "tclMacMath.h"
-#else
-# include <math.h>
-#endif
-
-#endif /* _TCLMATH */
diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c
index 77352a1..5dbffc6 100644
--- a/generic/tclNamesp.c
+++ b/generic/tclNamesp.c
@@ -1,164 +1,264 @@
/*
* tclNamesp.c --
*
- * Contains support for namespaces, which provide a separate context of
- * commands and global variables. The global :: namespace is the
- * traditional Tcl "global" scope. Other namespaces are created as
- * children of the global namespace. These other namespaces contain
- * special-purpose commands and variables for packages.
+ * Contains support for namespaces, which provide a separate context of
+ * commands and global variables. The global :: namespace is the
+ * traditional Tcl "global" scope. Other namespaces are created as
+ * children of the global namespace. These other namespaces contain
+ * special-purpose commands and variables for packages. Also includes the
+ * TIP#112 ensemble machinery.
*
* Copyright (c) 1993-1997 Lucent Technologies.
* Copyright (c) 1997 Sun Microsystems, Inc.
* Copyright (c) 1998-1999 by Scriptics Corporation.
+ * Copyright (c) 2002-2005 Donal K. Fellows.
+ * Copyright (c) 2006 Neil Madden.
+ * Contributions from Don Porter, NIST, 2007. (not subject to US copyright)
*
* Originally implemented by
* Michael J. McLennan
* Bell Labs Innovations for Lucent Technologies
* mmclennan@lucent.com
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
/*
- * Flag passed to TclGetNamespaceForQualName to indicate that it should
- * search for a namespace rather than a command or variable inside a
- * namespace. Note that this flag's value must not conflict with the values
- * of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, or CREATE_NS_IF_UNKNOWN.
+ * Thread-local storage used to avoid having a global lock on data that is not
+ * limited to a single interpreter.
*/
-#define FIND_ONLY_NS 0x1000
+typedef struct ThreadSpecificData {
+ long numNsCreated; /* Count of the number of namespaces created
+ * within the thread. This value is used as a
+ * unique id for each namespace. Cannot be
+ * per-interp because the nsId is used to
+ * distinguish objects which can be passed
+ * around between interps in the same thread,
+ * but does not need to be global because
+ * object internal reps are always per-thread
+ * anyway. */
+} ThreadSpecificData;
+
+static Tcl_ThreadDataKey dataKey;
/*
- * Initial size of stack allocated space for tail list - used when resetting
- * shadowed command references in the functin: TclResetShadowedCmdRefs.
+ * This structure contains a cached pointer to a namespace that is the result
+ * of resolving the namespace's name in some other namespace. It is the
+ * internal representation for a nsName object. It contains the pointer along
+ * with some information that is used to check the cached pointer's validity.
*/
-#define NUM_TRAIL_ELEMS 5
+typedef struct ResolvedNsName {
+ Namespace *nsPtr; /* A cached pointer to the Namespace that the
+ * name resolved to. */
+ Namespace *refNsPtr; /* Points to the namespace context in which the
+ * name was resolved. NULL if the name is fully
+ * qualified and thus the resolution does not
+ * depend on the context. */
+ int refCount; /* Reference count: 1 for each nsName object
+ * that has a pointer to this ResolvedNsName
+ * structure as its internal rep. This
+ * structure can be freed when refCount
+ * becomes zero. */
+} ResolvedNsName;
/*
- * Count of the number of namespaces created. This value is used as a
- * unique id for each namespace.
+ * The client data for an ensemble command. This consists of the table of
+ * commands that are actually exported by the namespace, and an epoch counter
+ * that, combined with the exportLookupEpoch field of the namespace structure,
+ * defines whether the table contains valid data or will need to be recomputed
+ * next time the ensemble command is called.
*/
-static long numNsCreated = 0;
-TCL_DECLARE_MUTEX(nsMutex)
+typedef struct EnsembleConfig {
+ Namespace *nsPtr; /* The namspace backing this ensemble up. */
+ Tcl_Command token; /* The token for the command that provides
+ * ensemble support for the namespace, or NULL
+ * if the command has been deleted (or never
+ * existed; the global namespace never has an
+ * ensemble command.) */
+ int epoch; /* The epoch at which this ensemble's table of
+ * exported commands is valid. */
+ char **subcommandArrayPtr; /* Array of ensemble subcommand names. At all
+ * consistent points, this will have the same
+ * number of entries as there are entries in
+ * the subcommandTable hash. */
+ Tcl_HashTable subcommandTable;
+ /* Hash table of ensemble subcommand names,
+ * which are its keys so this also provides
+ * the storage management for those subcommand
+ * names. The contents of the entry values are
+ * object version the prefix lists to use when
+ * substituting for the command/subcommand to
+ * build the ensemble implementation command.
+ * Has to be stored here as well as in
+ * subcommandDict because that field is NULL
+ * when we are deriving the ensemble from the
+ * namespace exports list. FUTURE WORK: use
+ * object hash table here. */
+ struct EnsembleConfig *next;/* The next ensemble in the linked list of
+ * ensembles associated with a namespace. If
+ * this field points to this ensemble, the
+ * structure has already been unlinked from
+ * all lists, and cannot be found by scanning
+ * the list from the namespace's ensemble
+ * field. */
+ int flags; /* ORed combo of TCL_ENSEMBLE_PREFIX, ENS_DEAD
+ * and ENSEMBLE_COMPILE. */
+
+ /* OBJECT FIELDS FOR ENSEMBLE CONFIGURATION */
+
+ Tcl_Obj *subcommandDict; /* Dictionary providing mapping from
+ * subcommands to their implementing command
+ * prefixes, or NULL if we are to build the
+ * map automatically from the namespace
+ * exports. */
+ Tcl_Obj *subcmdList; /* List of commands that this ensemble
+ * actually provides, and whose implementation
+ * will be built using the subcommandDict (if
+ * present and defined) and by simple mapping
+ * to the namespace otherwise. If NULL,
+ * indicates that we are using the (dynamic)
+ * list of currently exported commands. */
+ Tcl_Obj *unknownHandler; /* Script prefix used to handle the case when
+ * no match is found (according to the rule
+ * defined by flag bit TCL_ENSEMBLE_PREFIX) or
+ * NULL to use the default error-generating
+ * behaviour. The script execution gets all
+ * the arguments to the ensemble command
+ * (including objv[0]) and will have the
+ * results passed directly back to the caller
+ * (including the error code) unless the code
+ * is TCL_CONTINUE in which case the
+ * subcommand will be reparsed by the ensemble
+ * core, presumably because the ensemble
+ * itself has been updated. */
+} EnsembleConfig;
+
+#define ENS_DEAD 0x1 /* Flag value to say that the ensemble is dead
+ * and on its way out. */
/*
- * This structure contains a cached pointer to a namespace that is the
- * result of resolving the namespace's name in some other namespace. It is
- * the internal representation for a nsName object. It contains the
- * pointer along with some information that is used to check the cached
- * pointer's validity.
+ * Declarations for functions local to this file:
*/
-typedef struct ResolvedNsName {
- Namespace *nsPtr; /* A cached namespace pointer. */
- long nsId; /* nsPtr's unique namespace id. Used to
- * verify that nsPtr is still valid
- * (e.g., it's possible that the namespace
- * was deleted and a new one created at
- * the same address). */
- Namespace *refNsPtr; /* Points to the namespace containing the
- * reference (not the namespace that
- * contains the referenced namespace). */
- int refCount; /* Reference count: 1 for each nsName
- * object that has a pointer to this
- * ResolvedNsName structure as its internal
- * rep. This structure can be freed when
- * refCount becomes zero. */
-} ResolvedNsName;
+static void DeleteImportedCmd(ClientData clientData);
+static int DoImport(Tcl_Interp *interp,
+ Namespace *nsPtr, Tcl_HashEntry *hPtr,
+ const char *cmdName, const char *pattern,
+ Namespace *importNsPtr, int allowOverwrite);
+static void DupNsNameInternalRep(Tcl_Obj *objPtr,Tcl_Obj *copyPtr);
+static char * ErrorCodeRead(ClientData clientData,Tcl_Interp *interp,
+ const char *name1, const char *name2, int flags);
+static char * ErrorInfoRead(ClientData clientData,Tcl_Interp *interp,
+ const char *name1, const char *name2, int flags);
+static char * EstablishErrorCodeTraces(ClientData clientData,
+ Tcl_Interp *interp, const char *name1,
+ const char *name2, int flags);
+static char * EstablishErrorInfoTraces(ClientData clientData,
+ Tcl_Interp *interp, const char *name1,
+ const char *name2, int flags);
+static void FreeNsNameInternalRep(Tcl_Obj *objPtr);
+static int GetNamespaceFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, Tcl_Namespace **nsPtrPtr);
+static int InvokeImportedCmd(ClientData clientData,
+ Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]);
+static int NamespaceChildrenCmd(ClientData dummy,
+ Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]);
+static int NamespaceCodeCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int NamespaceCurrentCmd(ClientData dummy,
+ Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]);
+static int NamespaceDeleteCmd(ClientData dummy,Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int NamespaceEnsembleCmd(ClientData dummy,
+ Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]);
+static int NamespaceEvalCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int NamespaceExistsCmd(ClientData dummy,Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int NamespaceExportCmd(ClientData dummy,Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int NamespaceForgetCmd(ClientData dummy,Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static void NamespaceFree(Namespace *nsPtr);
+static int NamespaceImportCmd(ClientData dummy,Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int NamespaceInscopeCmd(ClientData dummy,
+ Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]);
+static int NamespaceOriginCmd(ClientData dummy,Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int NamespaceParentCmd(ClientData dummy,Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int NamespacePathCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int NamespaceQualifiersCmd(ClientData dummy,
+ Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]);
+static int NamespaceTailCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int NamespaceUpvarCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int NamespaceUnknownCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int NamespaceWhichCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int SetNsNameFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
+static int NsEnsembleImplementationCmd(ClientData clientData,
+ Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]);
+static void BuildEnsembleConfig(EnsembleConfig *ensemblePtr);
+static int NsEnsembleStringOrder(const void *strPtr1,
+ const void *strPtr2);
+static void DeleteEnsembleConfig(ClientData clientData);
+static void MakeCachedEnsembleCommand(Tcl_Obj *objPtr,
+ EnsembleConfig *ensemblePtr,
+ const char *subcmdName, Tcl_Obj *prefixObjPtr);
+static void FreeEnsembleCmdRep(Tcl_Obj *objPtr);
+static void DupEnsembleCmdRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr);
+static void StringOfEnsembleCmdRep(Tcl_Obj *objPtr);
+static void UnlinkNsPath(Namespace *nsPtr);
/*
- * Declarations for procedures local to this file:
- */
-
-static void DeleteImportedCmd _ANSI_ARGS_((
- ClientData clientData));
-static void DupNsNameInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr,
- Tcl_Obj *copyPtr));
-static void FreeNsNameInternalRep _ANSI_ARGS_((
- Tcl_Obj *objPtr));
-static int GetNamespaceFromObj _ANSI_ARGS_((
- Tcl_Interp *interp, Tcl_Obj *objPtr,
- Tcl_Namespace **nsPtrPtr));
-static int InvokeImportedCmd _ANSI_ARGS_((
- ClientData clientData, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-static int NamespaceChildrenCmd _ANSI_ARGS_((
- ClientData dummy, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-static int NamespaceCodeCmd _ANSI_ARGS_((
- ClientData dummy, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-static int NamespaceCurrentCmd _ANSI_ARGS_((
- ClientData dummy, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-static int NamespaceDeleteCmd _ANSI_ARGS_((
- ClientData dummy, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-static int NamespaceEvalCmd _ANSI_ARGS_((
- ClientData dummy, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-static int NamespaceExistsCmd _ANSI_ARGS_((
- ClientData dummy, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-static int NamespaceExportCmd _ANSI_ARGS_((
- ClientData dummy, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-static int NamespaceForgetCmd _ANSI_ARGS_((
- ClientData dummy, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-static void NamespaceFree _ANSI_ARGS_((Namespace *nsPtr));
-static int NamespaceImportCmd _ANSI_ARGS_((
- ClientData dummy, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-static int NamespaceInscopeCmd _ANSI_ARGS_((
- ClientData dummy, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-static int NamespaceOriginCmd _ANSI_ARGS_((
- ClientData dummy, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-static int NamespaceParentCmd _ANSI_ARGS_((
- ClientData dummy, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-static int NamespaceQualifiersCmd _ANSI_ARGS_((
- ClientData dummy, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-static int NamespaceTailCmd _ANSI_ARGS_((
- ClientData dummy, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-static int NamespaceWhichCmd _ANSI_ARGS_((
- ClientData dummy, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-static int SetNsNameFromAny _ANSI_ARGS_((
- Tcl_Interp *interp, Tcl_Obj *objPtr));
-static void UpdateStringOfNsName _ANSI_ARGS_((Tcl_Obj *objPtr));
-
-/*
- * This structure defines a Tcl object type that contains a
- * namespace reference. It is used in commands that take the
- * name of a namespace as an argument. The namespace reference
- * is resolved, and the result in cached in the object.
- */
-
-Tcl_ObjType tclNsNameType = {
+ * This structure defines a Tcl object type that contains a namespace
+ * reference. It is used in commands that take the name of a namespace as an
+ * argument. The namespace reference is resolved, and the result in cached in
+ * the object.
+ */
+
+static Tcl_ObjType nsNameType = {
"nsName", /* the type's name */
FreeNsNameInternalRep, /* freeIntRepProc */
DupNsNameInternalRep, /* dupIntRepProc */
- UpdateStringOfNsName, /* updateStringProc */
+ NULL, /* updateStringProc */
SetNsNameFromAny /* setFromAnyProc */
};
+
+/*
+ * This structure defines a Tcl object type that contains a reference to an
+ * ensemble subcommand (e.g. the "length" in [string length ab]). It is used
+ * to cache the mapping between the subcommand itself and the real command
+ * that implements it.
+ */
+
+Tcl_ObjType tclEnsembleCmdType = {
+ "ensembleCommand", /* the type's name */
+ FreeEnsembleCmdRep, /* freeIntRepProc */
+ DupEnsembleCmdRep, /* dupIntRepProc */
+ StringOfEnsembleCmdRep, /* updateStringProc */
+ NULL /* setFromAnyProc */
+};
/*
*----------------------------------------------------------------------
*
* TclInitNamespaceSubsystem --
*
- * This procedure is called to initialize all the structures that
- * are used by namespaces on a per-process basis.
+ * This function is called to initialize all the structures that are used
+ * by namespaces on a per-process basis.
*
* Results:
* None.
@@ -170,7 +270,7 @@ Tcl_ObjType tclNsNameType = {
*/
void
-TclInitNamespaceSubsystem()
+TclInitNamespaceSubsystem(void)
{
/*
* Does nothing for now.
@@ -194,19 +294,11 @@ TclInitNamespaceSubsystem()
*/
Tcl_Namespace *
-Tcl_GetCurrentNamespace(interp)
- register Tcl_Interp *interp; /* Interpreter whose current namespace is
- * being queried. */
+Tcl_GetCurrentNamespace(
+ register Tcl_Interp *interp)/* Interpreter whose current namespace is
+ * being queried. */
{
- register Interp *iPtr = (Interp *) interp;
- register Namespace *nsPtr;
-
- if (iPtr->varFramePtr != NULL) {
- nsPtr = iPtr->varFramePtr->nsPtr;
- } else {
- nsPtr = iPtr->globalNsPtr;
- }
- return (Tcl_Namespace *) nsPtr;
+ return TclGetCurrentNamespace(interp);
}
/*
@@ -226,13 +318,11 @@ Tcl_GetCurrentNamespace(interp)
*/
Tcl_Namespace *
-Tcl_GetGlobalNamespace(interp)
- register Tcl_Interp *interp; /* Interpreter whose global namespace
- * should be returned. */
+Tcl_GetGlobalNamespace(
+ register Tcl_Interp *interp)/* Interpreter whose global namespace should
+ * be returned. */
{
- register Interp *iPtr = (Interp *) interp;
-
- return (Tcl_Namespace *) iPtr->globalNsPtr;
+ return TclGetGlobalNamespace(interp);
}
/*
@@ -240,9 +330,9 @@ Tcl_GetGlobalNamespace(interp)
*
* Tcl_PushCallFrame --
*
- * Pushes a new call frame onto the interpreter's Tcl call stack.
- * Called when executing a Tcl procedure or a "namespace eval" or
- * "namespace inscope" command.
+ * Pushes a new call frame onto the interpreter's Tcl call stack. Called
+ * when executing a Tcl procedure or a "namespace eval" or "namespace
+ * inscope" command.
*
* Results:
* Returns TCL_OK if successful, or TCL_ERROR (along with an error
@@ -255,45 +345,53 @@ Tcl_GetGlobalNamespace(interp)
*/
int
-Tcl_PushCallFrame(interp, callFramePtr, namespacePtr, isProcCallFrame)
- Tcl_Interp *interp; /* Interpreter in which the new call frame
- * is to be pushed. */
- Tcl_CallFrame *callFramePtr; /* Points to a call frame structure to
- * push. Storage for this has already been
- * allocated by the caller; typically this
- * is the address of a CallFrame structure
- * allocated on the caller's C stack. The
- * call frame will be initialized by this
- * procedure. The caller can pop the frame
- * later with Tcl_PopCallFrame, and it is
- * responsible for freeing the frame's
- * storage. */
- Tcl_Namespace *namespacePtr; /* Points to the namespace in which the
- * frame will execute. If NULL, the
- * interpreter's current namespace will
- * be used. */
- int isProcCallFrame; /* If nonzero, the frame represents a
- * called Tcl procedure and may have local
- * vars. Vars will ordinarily be looked up
- * in the frame. If new variables are
- * created, they will be created in the
- * frame. If 0, the frame is for a
- * "namespace eval" or "namespace inscope"
- * command and var references are treated
- * as references to namespace variables. */
+Tcl_PushCallFrame(
+ Tcl_Interp *interp, /* Interpreter in which the new call frame is
+ * to be pushed. */
+ Tcl_CallFrame *callFramePtr,/* Points to a call frame structure to push.
+ * Storage for this has already been allocated
+ * by the caller; typically this is the
+ * address of a CallFrame structure allocated
+ * on the caller's C stack. The call frame
+ * will be initialized by this function. The
+ * caller can pop the frame later with
+ * Tcl_PopCallFrame, and it is responsible for
+ * freeing the frame's storage. */
+ Tcl_Namespace *namespacePtr,/* Points to the namespace in which the frame
+ * will execute. If NULL, the interpreter's
+ * current namespace will be used. */
+ int isProcCallFrame) /* If nonzero, the frame represents a called
+ * Tcl procedure and may have local vars. Vars
+ * will ordinarily be looked up in the frame.
+ * If new variables are created, they will be
+ * created in the frame. If 0, the frame is
+ * for a "namespace eval" or "namespace
+ * inscope" command and var references are
+ * treated as references to namespace
+ * variables. */
{
Interp *iPtr = (Interp *) interp;
register CallFrame *framePtr = (CallFrame *) callFramePtr;
register Namespace *nsPtr;
if (namespacePtr == NULL) {
- nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+ nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
} else {
- nsPtr = (Namespace *) namespacePtr;
- if (nsPtr->flags & NS_DEAD) {
- panic("Trying to push call frame for dead namespace");
+ nsPtr = (Namespace *) namespacePtr;
+
+ /*
+ * TODO: Examine whether it would be better to guard based on NS_DYING
+ * or NS_KILLED. It appears that these are not tested because they can
+ * be set in a global interp that has been [namespace delete]d, but
+ * which never really completely goes away because of lingering global
+ * things like ::errorInfo and [::unknown] and hidden commands.
+ * Review of those designs might permit stricter checking here.
+ */
+
+ if (nsPtr->flags & NS_DEAD) {
+ Tcl_Panic("Trying to push call frame for dead namespace");
/*NOTREACHED*/
- }
+ }
}
nsPtr->activationCount++;
@@ -304,18 +402,20 @@ Tcl_PushCallFrame(interp, callFramePtr, namespacePtr, isProcCallFrame)
framePtr->callerPtr = iPtr->framePtr;
framePtr->callerVarPtr = iPtr->varFramePtr;
if (iPtr->varFramePtr != NULL) {
- framePtr->level = (iPtr->varFramePtr->level + 1);
+ framePtr->level = (iPtr->varFramePtr->level + 1);
} else {
- framePtr->level = 1;
+ framePtr->level = 0;
}
- framePtr->procPtr = NULL; /* no called procedure */
- framePtr->varTablePtr = NULL; /* and no local variables */
+ framePtr->procPtr = NULL; /* no called procedure */
+ framePtr->varTablePtr = NULL; /* and no local variables */
framePtr->numCompiledLocals = 0;
framePtr->compiledLocals = NULL;
+ framePtr->clientData = NULL;
+ framePtr->localCachePtr = NULL;
/*
- * Push the new call frame onto the interpreter's stack of procedure
- * call frames making it the current frame.
+ * Push the new call frame onto the interpreter's stack of procedure call
+ * frames making it the current frame.
*/
iPtr->framePtr = framePtr;
@@ -336,51 +436,57 @@ Tcl_PushCallFrame(interp, callFramePtr, namespacePtr, isProcCallFrame)
*
* Side effects:
* Modifies the call stack of the interpreter. Resets various fields of
- * the popped call frame. If a namespace has been deleted and
- * has no more activations on the call stack, the namespace is
- * destroyed.
+ * the popped call frame. If a namespace has been deleted and has no more
+ * activations on the call stack, the namespace is destroyed.
*
*----------------------------------------------------------------------
*/
void
-Tcl_PopCallFrame(interp)
- Tcl_Interp* interp; /* Interpreter with call frame to pop. */
+Tcl_PopCallFrame(
+ Tcl_Interp *interp) /* Interpreter with call frame to pop. */
{
register Interp *iPtr = (Interp *) interp;
register CallFrame *framePtr = iPtr->framePtr;
Namespace *nsPtr;
/*
- * It's important to remove the call frame from the interpreter's stack
- * of call frames before deleting local variables, so that traces
- * invoked by the variable deletion don't see the partially-deleted
- * frame.
+ * It's important to remove the call frame from the interpreter's stack of
+ * call frames before deleting local variables, so that traces invoked by
+ * the variable deletion don't see the partially-deleted frame.
*/
- iPtr->framePtr = framePtr->callerPtr;
- iPtr->varFramePtr = framePtr->callerVarPtr;
+ if (framePtr->callerPtr) {
+ iPtr->framePtr = framePtr->callerPtr;
+ iPtr->varFramePtr = framePtr->callerVarPtr;
+ } else {
+ /* Tcl_PopCallFrame: trying to pop rootCallFrame! */
+ }
if (framePtr->varTablePtr != NULL) {
- TclDeleteVars(iPtr, framePtr->varTablePtr);
- ckfree((char *) framePtr->varTablePtr);
- framePtr->varTablePtr = NULL;
+ TclDeleteVars(iPtr, framePtr->varTablePtr);
+ ckfree((char *) framePtr->varTablePtr);
+ framePtr->varTablePtr = NULL;
}
if (framePtr->numCompiledLocals > 0) {
- TclDeleteCompiledLocalVars(iPtr, framePtr);
+ TclDeleteCompiledLocalVars(iPtr, framePtr);
+ if (--framePtr->localCachePtr->refCount == 0) {
+ TclFreeLocalCache(interp, framePtr->localCachePtr);
+ }
+ framePtr->localCachePtr = NULL;
}
/*
- * Decrement the namespace's count of active call frames. If the
- * namespace is "dying" and there are no more active call frames,
- * call Tcl_DeleteNamespace to destroy it.
+ * Decrement the namespace's count of active call frames. If the namespace
+ * is "dying" and there are no more active call frames, call
+ * Tcl_DeleteNamespace to destroy it.
*/
nsPtr = framePtr->nsPtr;
nsPtr->activationCount--;
if ((nsPtr->flags & NS_DYING)
- && (nsPtr->activationCount == 0)) {
- Tcl_DeleteNamespace((Tcl_Namespace *) nsPtr);
+ && (nsPtr->activationCount - (nsPtr == iPtr->globalNsPtr) == 0)) {
+ Tcl_DeleteNamespace((Tcl_Namespace *) nsPtr);
}
framePtr->nsPtr = NULL;
}
@@ -388,137 +494,346 @@ Tcl_PopCallFrame(interp)
/*
*----------------------------------------------------------------------
*
+ * TclPushStackFrame --
+ *
+ * Allocates a new call frame in the interpreter's execution stack, then
+ * pushes it onto the interpreter's Tcl call stack. Called when executing
+ * a Tcl procedure or a "namespace eval" or "namespace inscope" command.
+ *
+ * Results:
+ * Returns TCL_OK if successful, or TCL_ERROR (along with an error
+ * message in the interpreter's result object) if something goes wrong.
+ *
+ * Side effects:
+ * Modifies the interpreter's Tcl call stack.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclPushStackFrame(
+ Tcl_Interp *interp, /* Interpreter in which the new call frame is
+ * to be pushed. */
+ Tcl_CallFrame **framePtrPtr,/* Place to store a pointer to the stack
+ * allocated call frame. */
+ Tcl_Namespace *namespacePtr,/* Points to the namespace in which the frame
+ * will execute. If NULL, the interpreter's
+ * current namespace will be used. */
+ int isProcCallFrame) /* If nonzero, the frame represents a called
+ * Tcl procedure and may have local vars. Vars
+ * will ordinarily be looked up in the frame.
+ * If new variables are created, they will be
+ * created in the frame. If 0, the frame is
+ * for a "namespace eval" or "namespace
+ * inscope" command and var references are
+ * treated as references to namespace
+ * variables. */
+{
+ *framePtrPtr = (Tcl_CallFrame *) TclStackAlloc(interp, sizeof(CallFrame));
+ return Tcl_PushCallFrame(interp, *framePtrPtr, namespacePtr,
+ isProcCallFrame);
+}
+
+void
+TclPopStackFrame(
+ Tcl_Interp *interp) /* Interpreter with call frame to pop. */
+{
+ CallFrame *freePtr = ((Interp *)interp)->framePtr;
+
+ Tcl_PopCallFrame(interp);
+ TclStackFree(interp, freePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EstablishErrorCodeTraces --
+ *
+ * Creates traces on the ::errorCode variable to keep its value
+ * consistent with the expectations of legacy code.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Read and unset traces are established on ::errorCode.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+EstablishErrorCodeTraces(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ const char *name1,
+ const char *name2,
+ int flags)
+{
+ Tcl_TraceVar(interp, "errorCode", TCL_GLOBAL_ONLY | TCL_TRACE_READS,
+ ErrorCodeRead, NULL);
+ Tcl_TraceVar(interp, "errorCode", TCL_GLOBAL_ONLY | TCL_TRACE_UNSETS,
+ EstablishErrorCodeTraces, NULL);
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ErrorCodeRead --
+ *
+ * Called when the ::errorCode variable is read. Copies the current value
+ * of the interp's errorCode field into ::errorCode.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+ErrorCodeRead(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ const char *name1,
+ const char *name2,
+ int flags)
+{
+ Interp *iPtr = (Interp *)interp;
+
+ if (Tcl_InterpDeleted(interp) || !(iPtr->flags & ERR_LEGACY_COPY)) {
+ return NULL;
+ }
+ if (iPtr->errorCode) {
+ Tcl_ObjSetVar2(interp, iPtr->ecVar, NULL,
+ iPtr->errorCode, TCL_GLOBAL_ONLY);
+ return NULL;
+ }
+ if (NULL == Tcl_ObjGetVar2(interp, iPtr->ecVar, NULL, TCL_GLOBAL_ONLY)) {
+ Tcl_ObjSetVar2(interp, iPtr->ecVar, NULL,
+ Tcl_NewObj(), TCL_GLOBAL_ONLY);
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EstablishErrorInfoTraces --
+ *
+ * Creates traces on the ::errorInfo variable to keep its value
+ * consistent with the expectations of legacy code.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Read and unset traces are established on ::errorInfo.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+EstablishErrorInfoTraces(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ const char *name1,
+ const char *name2,
+ int flags)
+{
+ Tcl_TraceVar(interp, "errorInfo", TCL_GLOBAL_ONLY | TCL_TRACE_READS,
+ ErrorInfoRead, NULL);
+ Tcl_TraceVar(interp, "errorInfo", TCL_GLOBAL_ONLY | TCL_TRACE_UNSETS,
+ EstablishErrorInfoTraces, NULL);
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ErrorInfoRead --
+ *
+ * Called when the ::errorInfo variable is read. Copies the current value
+ * of the interp's errorInfo field into ::errorInfo.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+ErrorInfoRead(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ const char *name1,
+ const char *name2,
+ int flags)
+{
+ Interp *iPtr = (Interp *) interp;
+
+ if (Tcl_InterpDeleted(interp) || !(iPtr->flags & ERR_LEGACY_COPY)) {
+ return NULL;
+ }
+ if (iPtr->errorInfo) {
+ Tcl_ObjSetVar2(interp, iPtr->eiVar, NULL,
+ iPtr->errorInfo, TCL_GLOBAL_ONLY);
+ return NULL;
+ }
+ if (NULL == Tcl_ObjGetVar2(interp, iPtr->eiVar, NULL, TCL_GLOBAL_ONLY)) {
+ Tcl_ObjSetVar2(interp, iPtr->eiVar, NULL,
+ Tcl_NewObj(), TCL_GLOBAL_ONLY);
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tcl_CreateNamespace --
*
- * Creates a new namespace with the given name. If there is no
- * active namespace (i.e., the interpreter is being initialized),
- * the global :: namespace is created and returned.
+ * Creates a new namespace with the given name. If there is no active
+ * namespace (i.e., the interpreter is being initialized), the global ::
+ * namespace is created and returned.
*
* Results:
- * Returns a pointer to the new namespace if successful. If the
- * namespace already exists or if another error occurs, this routine
- * returns NULL, along with an error message in the interpreter's
- * result object.
+ * Returns a pointer to the new namespace if successful. If the namespace
+ * already exists or if another error occurs, this routine returns NULL,
+ * along with an error message in the interpreter's result object.
*
* Side effects:
- * If the name contains "::" qualifiers and a parent namespace does
- * not already exist, it is automatically created.
+ * If the name contains "::" qualifiers and a parent namespace does not
+ * already exist, it is automatically created.
*
*----------------------------------------------------------------------
*/
Tcl_Namespace *
-Tcl_CreateNamespace(interp, name, clientData, deleteProc)
- Tcl_Interp *interp; /* Interpreter in which a new namespace
- * is being created. Also used for
- * error reporting. */
- CONST char *name; /* Name for the new namespace. May be a
- * qualified name with names of ancestor
- * namespaces separated by "::"s. */
- ClientData clientData; /* One-word value to store with
- * namespace. */
- Tcl_NamespaceDeleteProc *deleteProc;
- /* Procedure called to delete client
- * data when the namespace is deleted.
- * NULL if no procedure should be
- * called. */
+Tcl_CreateNamespace(
+ Tcl_Interp *interp, /* Interpreter in which a new namespace is
+ * being created. Also used for error
+ * reporting. */
+ const char *name, /* Name for the new namespace. May be a
+ * qualified name with names of ancestor
+ * namespaces separated by "::"s. */
+ ClientData clientData, /* One-word value to store with namespace. */
+ Tcl_NamespaceDeleteProc *deleteProc)
+ /* Function called to delete client data when
+ * the namespace is deleted. NULL if no
+ * function should be called. */
{
Interp *iPtr = (Interp *) interp;
register Namespace *nsPtr, *ancestorPtr;
Namespace *parentPtr, *dummy1Ptr, *dummy2Ptr;
Namespace *globalNsPtr = iPtr->globalNsPtr;
- CONST char *simpleName;
+ const char *simpleName;
Tcl_HashEntry *entryPtr;
Tcl_DString buffer1, buffer2;
- int newEntry;
+ Tcl_DString *namePtr, *buffPtr;
+ int newEntry, nameLen;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
/*
- * If there is no active namespace, the interpreter is being
- * initialized.
+ * If there is no active namespace, the interpreter is being initialized.
*/
if ((globalNsPtr == NULL) && (iPtr->varFramePtr == NULL)) {
/*
- * Treat this namespace as the global namespace, and avoid
- * looking for a parent.
+ * Treat this namespace as the global namespace, and avoid looking for
+ * a parent.
*/
-
- parentPtr = NULL;
- simpleName = "";
+
+ parentPtr = NULL;
+ simpleName = "";
} else if (*name == '\0') {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "can't create namespace \"\": only global namespace can have empty name", (char *) NULL);
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "can't create namespace \"\": "
+ "only global namespace can have empty name", NULL);
return NULL;
} else {
/*
* Find the parent for the new namespace.
*/
- TclGetNamespaceForQualName(interp, name, (Namespace *) NULL,
- /*flags*/ (CREATE_NS_IF_UNKNOWN | TCL_LEAVE_ERR_MSG),
+ TclGetNamespaceForQualName(interp, name, NULL,
+ /*flags*/ (TCL_CREATE_NS_IF_UNKNOWN | TCL_LEAVE_ERR_MSG),
&parentPtr, &dummy1Ptr, &dummy2Ptr, &simpleName);
/*
* If the unqualified name at the end is empty, there were trailing
- * "::"s after the namespace's name which we ignore. The new
- * namespace was already (recursively) created and is pointed to
- * by parentPtr.
+ * "::"s after the namespace's name which we ignore. The new namespace
+ * was already (recursively) created and is pointed to by parentPtr.
*/
if (*simpleName == '\0') {
return (Tcl_Namespace *) parentPtr;
}
- /*
- * Check for a bad namespace name and make sure that the name
- * does not already exist in the parent namespace.
+ /*
+ * Check for a bad namespace name and make sure that the name does not
+ * already exist in the parent namespace.
*/
- if (Tcl_FindHashEntry(&parentPtr->childTable, simpleName) != NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "can't create namespace \"", name,
- "\": already exists", (char *) NULL);
- return NULL;
- }
+ if (Tcl_FindHashEntry(&parentPtr->childTable, simpleName) != NULL) {
+ Tcl_AppendResult(interp, "can't create namespace \"", name,
+ "\": already exists", NULL);
+ return NULL;
+ }
}
/*
- * Create the new namespace and root it in its parent. Increment the
- * count of namespaces created.
+ * Create the new namespace and root it in its parent. Increment the count
+ * of namespaces created.
*/
-
nsPtr = (Namespace *) ckalloc(sizeof(Namespace));
- nsPtr->name = (char *) ckalloc((unsigned) (strlen(simpleName)+1));
+ nsPtr->name = ckalloc((unsigned) (strlen(simpleName)+1));
strcpy(nsPtr->name, simpleName);
- nsPtr->fullName = NULL; /* set below */
- nsPtr->clientData = clientData;
- nsPtr->deleteProc = deleteProc;
- nsPtr->parentPtr = parentPtr;
+ nsPtr->fullName = NULL; /* Set below. */
+ nsPtr->clientData = clientData;
+ nsPtr->deleteProc = deleteProc;
+ nsPtr->parentPtr = parentPtr;
Tcl_InitHashTable(&nsPtr->childTable, TCL_STRING_KEYS);
- Tcl_MutexLock(&nsMutex);
- numNsCreated++;
- nsPtr->nsId = numNsCreated;
- Tcl_MutexUnlock(&nsMutex);
- nsPtr->interp = interp;
- nsPtr->flags = 0;
+ nsPtr->nsId = ++(tsdPtr->numNsCreated);
+ nsPtr->interp = interp;
+ nsPtr->flags = 0;
nsPtr->activationCount = 0;
- nsPtr->refCount = 0;
+ nsPtr->refCount = 0;
Tcl_InitHashTable(&nsPtr->cmdTable, TCL_STRING_KEYS);
- Tcl_InitHashTable(&nsPtr->varTable, TCL_STRING_KEYS);
- nsPtr->exportArrayPtr = NULL;
+ TclInitVarHashTable(&nsPtr->varTable, nsPtr);
+ nsPtr->exportArrayPtr = NULL;
nsPtr->numExportPatterns = 0;
nsPtr->maxExportPatterns = 0;
- nsPtr->cmdRefEpoch = 0;
- nsPtr->resolverEpoch = 0;
- nsPtr->cmdResProc = NULL;
- nsPtr->varResProc = NULL;
+ nsPtr->cmdRefEpoch = 0;
+ nsPtr->resolverEpoch = 0;
+ nsPtr->cmdResProc = NULL;
+ nsPtr->varResProc = NULL;
nsPtr->compiledVarResProc = NULL;
+ nsPtr->exportLookupEpoch = 0;
+ nsPtr->ensembles = NULL;
+ nsPtr->unknownHandlerPtr = NULL;
+ nsPtr->commandPathLength = 0;
+ nsPtr->commandPathArray = NULL;
+ nsPtr->commandPathSourceList = NULL;
if (parentPtr != NULL) {
- entryPtr = Tcl_CreateHashEntry(&parentPtr->childTable, simpleName,
- &newEntry);
- Tcl_SetHashValue(entryPtr, (ClientData) nsPtr);
+ entryPtr = Tcl_CreateHashEntry(&parentPtr->childTable, simpleName,
+ &newEntry);
+ Tcl_SetHashValue(entryPtr, nsPtr);
+ } else {
+ /*
+ * In the global namespace create traces to maintain the ::errorInfo
+ * and ::errorCode variables.
+ */
+
+ iPtr->globalNsPtr = nsPtr;
+ EstablishErrorInfoTraces(NULL, interp, NULL, NULL, 0);
+ EstablishErrorCodeTraces(NULL, interp, NULL, NULL, 0);
}
/*
@@ -527,22 +842,41 @@ Tcl_CreateNamespace(interp, name, clientData, deleteProc)
Tcl_DStringInit(&buffer1);
Tcl_DStringInit(&buffer2);
- for (ancestorPtr = nsPtr; ancestorPtr != NULL;
+ namePtr = &buffer1;
+ buffPtr = &buffer2;
+ for (ancestorPtr = nsPtr; ancestorPtr != NULL;
ancestorPtr = ancestorPtr->parentPtr) {
- if (ancestorPtr != globalNsPtr) {
- Tcl_DStringAppend(&buffer1, "::", 2);
- Tcl_DStringAppend(&buffer1, ancestorPtr->name, -1);
- }
- Tcl_DStringAppend(&buffer1, Tcl_DStringValue(&buffer2), -1);
+ if (ancestorPtr != globalNsPtr) {
+ register Tcl_DString *tempPtr = namePtr;
+
+ Tcl_DStringAppend(buffPtr, "::", 2);
+ Tcl_DStringAppend(buffPtr, ancestorPtr->name, -1);
+ Tcl_DStringAppend(buffPtr, Tcl_DStringValue(namePtr),
+ Tcl_DStringLength(namePtr));
+
+ /*
+ * Clear the unwanted buffer or we end up appending to previous
+ * results, making the namespace fullNames of nested namespaces
+ * very wrong (and strange).
+ */
- Tcl_DStringSetLength(&buffer2, 0);
- Tcl_DStringAppend(&buffer2, Tcl_DStringValue(&buffer1), -1);
- Tcl_DStringSetLength(&buffer1, 0);
+ Tcl_DStringSetLength(namePtr, 0);
+
+ /*
+ * Now swap the buffer pointers so that we build in the other
+ * buffer. This is faster than repeated copying back and forth
+ * between buffers.
+ */
+
+ namePtr = buffPtr;
+ buffPtr = tempPtr;
+ }
}
-
- name = Tcl_DStringValue(&buffer2);
- nsPtr->fullName = (char *) ckalloc((unsigned) (strlen(name)+1));
- strcpy(nsPtr->fullName, name);
+
+ name = Tcl_DStringValue(namePtr);
+ nameLen = Tcl_DStringLength(namePtr);
+ nsPtr->fullName = ckalloc((unsigned) (nameLen+1));
+ memcpy(nsPtr->fullName, name, (unsigned) nameLen + 1);
Tcl_DStringFree(&buffer1);
Tcl_DStringFree(&buffer2);
@@ -566,50 +900,79 @@ Tcl_CreateNamespace(interp, name, clientData, deleteProc)
* None.
*
* Side effects:
- * When a namespace is deleted, it is automatically removed as a
- * child of its parent namespace. Also, all its commands, variables
- * and child namespaces are deleted.
+ * When a namespace is deleted, it is automatically removed as a child of
+ * its parent namespace. Also, all its commands, variables and child
+ * namespaces are deleted.
*
*----------------------------------------------------------------------
*/
void
-Tcl_DeleteNamespace(namespacePtr)
- Tcl_Namespace *namespacePtr; /* Points to the namespace to delete. */
+Tcl_DeleteNamespace(
+ Tcl_Namespace *namespacePtr)/* Points to the namespace to delete. */
{
register Namespace *nsPtr = (Namespace *) namespacePtr;
Interp *iPtr = (Interp *) nsPtr->interp;
- Namespace *globalNsPtr =
- (Namespace *) Tcl_GetGlobalNamespace((Tcl_Interp *) iPtr);
+ Namespace *globalNsPtr = (Namespace *)
+ TclGetGlobalNamespace((Tcl_Interp *) iPtr);
Tcl_HashEntry *entryPtr;
/*
+ * If the namespace has associated ensemble commands, delete them first.
+ * This leaves the actual contents of the namespace alone (unless they are
+ * linked ensemble commands, of course). Note that this code is actually
+ * reentrant so command delete traces won't purturb things badly.
+ */
+
+ while (nsPtr->ensembles != NULL) {
+ EnsembleConfig *ensemblePtr = (EnsembleConfig *) nsPtr->ensembles;
+
+ /*
+ * Splice out and link to indicate that we've already been killed.
+ */
+
+ nsPtr->ensembles = (Tcl_Ensemble *) ensemblePtr->next;
+ ensemblePtr->next = ensemblePtr;
+ Tcl_DeleteCommandFromToken(nsPtr->interp, ensemblePtr->token);
+ }
+
+ /*
+ * If the namespace has a registered unknown handler (TIP 181), then free
+ * it here.
+ */
+
+ if (nsPtr->unknownHandlerPtr != NULL) {
+ Tcl_DecrRefCount(nsPtr->unknownHandlerPtr);
+ nsPtr->unknownHandlerPtr = NULL;
+ }
+
+ /*
* If the namespace is on the call frame stack, it is marked as "dying"
- * (NS_DYING is OR'd into its flags): the namespace can't be looked up
- * by name but its commands and variables are still usable by those
- * active call frames. When all active call frames referring to the
- * namespace have been popped from the Tcl stack, Tcl_PopCallFrame will
- * call this procedure again to delete everything in the namespace.
- * If no nsName objects refer to the namespace (i.e., if its refCount
- * is zero), its commands and variables are deleted and the storage for
- * its namespace structure is freed. Otherwise, if its refCount is
- * nonzero, the namespace's commands and variables are deleted but the
- * structure isn't freed. Instead, NS_DEAD is OR'd into the structure's
- * flags to allow the namespace resolution code to recognize that the
- * namespace is "deleted". The structure's storage is freed by
- * FreeNsNameInternalRep when its refCount reaches 0.
- */
-
- if (nsPtr->activationCount > 0) {
- nsPtr->flags |= NS_DYING;
- if (nsPtr->parentPtr != NULL) {
- entryPtr = Tcl_FindHashEntry(&nsPtr->parentPtr->childTable,
+ * (NS_DYING is OR'd into its flags): the namespace can't be looked up by
+ * name but its commands and variables are still usable by those active
+ * call frames. When all active call frames referring to the namespace
+ * have been popped from the Tcl stack, Tcl_PopCallFrame will call this
+ * function again to delete everything in the namespace. If no nsName
+ * objects refer to the namespace (i.e., if its refCount is zero), its
+ * commands and variables are deleted and the storage for its namespace
+ * structure is freed. Otherwise, if its refCount is nonzero, the
+ * namespace's commands and variables are deleted but the structure isn't
+ * freed. Instead, NS_DEAD is OR'd into the structure's flags to allow the
+ * namespace resolution code to recognize that the namespace is "deleted".
+ * The structure's storage is freed by FreeNsNameInternalRep when its
+ * refCount reaches 0.
+ */
+
+ if (nsPtr->activationCount - (nsPtr == globalNsPtr) > 0) {
+ nsPtr->flags |= NS_DYING;
+ if (nsPtr->parentPtr != NULL) {
+ entryPtr = Tcl_FindHashEntry(&nsPtr->parentPtr->childTable,
nsPtr->name);
- if (entryPtr != NULL) {
- Tcl_DeleteHashEntry(entryPtr);
- }
- }
- nsPtr->parentPtr = NULL;
+ if (entryPtr != NULL) {
+ Tcl_DeleteHashEntry(entryPtr);
+ }
+ }
+ nsPtr->parentPtr = NULL;
} else if (!(nsPtr->flags & NS_KILLED)) {
/*
* Delete the namespace and everything in it. If this is the global
@@ -620,38 +983,46 @@ Tcl_DeleteNamespace(namespacePtr)
*/
nsPtr->flags |= (NS_DYING|NS_KILLED);
-
- TclTeardownNamespace(nsPtr);
- if ((nsPtr != globalNsPtr) || (iPtr->flags & DELETED)) {
- /*
+ TclTeardownNamespace(nsPtr);
+
+ if ((nsPtr != globalNsPtr) || (iPtr->flags & DELETED)) {
+ /*
* If this is the global namespace, then it may have residual
- * "errorInfo" and "errorCode" variables for errors that
- * occurred while it was being torn down. Try to clear the
- * variable list one last time.
+ * "errorInfo" and "errorCode" variables for errors that occurred
+ * while it was being torn down. Try to clear the variable list
+ * one last time.
+ */
+
+ TclDeleteNamespaceVars(nsPtr);
+
+ Tcl_DeleteHashTable(&nsPtr->childTable);
+ Tcl_DeleteHashTable(&nsPtr->cmdTable);
+
+ /*
+ * If the reference count is 0, then discard the namespace.
+ * Otherwise, mark it as "dead" so that it can't be used.
+ */
+
+ if (nsPtr->refCount == 0) {
+ NamespaceFree(nsPtr);
+ } else {
+ nsPtr->flags |= NS_DEAD;
+ }
+ } else {
+ /*
+ * Restore the ::errorInfo and ::errorCode traces.
*/
- TclDeleteNamespaceVars(nsPtr);
-
- Tcl_DeleteHashTable(&nsPtr->childTable);
- Tcl_DeleteHashTable(&nsPtr->cmdTable);
-
- /*
- * If the reference count is 0, then discard the namespace.
- * Otherwise, mark it as "dead" so that it can't be used.
- */
-
- if (nsPtr->refCount == 0) {
- NamespaceFree(nsPtr);
- } else {
- nsPtr->flags |= NS_DEAD;
- }
- } else {
+ EstablishErrorInfoTraces(NULL, nsPtr->interp, NULL, NULL, 0);
+ EstablishErrorCodeTraces(NULL, nsPtr->interp, NULL, NULL, 0);
+
/*
- * We didn't really kill it, so remove the KILLED marks, so
- * it can get killed later, avoiding mem leaks
+ * We didn't really kill it, so remove the KILLED marks, so it can
+ * get killed later, avoiding mem leaks.
*/
- nsPtr->flags &= ~(NS_DYING|NS_KILLED);
+
+ nsPtr->flags &= ~(NS_DYING|NS_KILLED);
}
}
}
@@ -666,9 +1037,7 @@ Tcl_DeleteNamespace(namespacePtr)
* commands, variables, and child namespaces.
*
* This is kept separate from Tcl_DeleteNamespace so that the global
- * namespace can be handled specially. Global variables like
- * "errorInfo" and "errorCode" need to remain intact while other
- * namespaces and commands are torn down, in case any errors occur.
+ * namespace can be handled specially.
*
* Results:
* None.
@@ -676,15 +1045,13 @@ Tcl_DeleteNamespace(namespacePtr)
* Side effects:
* Removes this namespace from its parent's child namespace hashtable.
* Deletes all commands, variables and namespaces in this namespace.
- * If this is the global namespace, the "errorInfo" and "errorCode"
- * variables are left alone and deleted later.
*
*----------------------------------------------------------------------
*/
void
-TclTeardownNamespace(nsPtr)
- register Namespace *nsPtr; /* Points to the namespace to be dismantled
+TclTeardownNamespace(
+ register Namespace *nsPtr) /* Points to the namespace to be dismantled
* and unlinked from its parent. */
{
Interp *iPtr = (Interp *) nsPtr->interp;
@@ -692,69 +1059,30 @@ TclTeardownNamespace(nsPtr)
Tcl_HashSearch search;
Tcl_Namespace *childNsPtr;
Tcl_Command cmd;
- Namespace *globalNsPtr =
- (Namespace *) Tcl_GetGlobalNamespace((Tcl_Interp *) iPtr);
int i;
/*
- * Start by destroying the namespace's variable table,
- * since variables might trigger traces.
+ * Start by destroying the namespace's variable table, since variables
+ * might trigger traces. Variable table should be cleared but not freed!
+ * TclDeleteNamespaceVars frees it, so we reinitialize it afterwards.
*/
- if (nsPtr == globalNsPtr) {
- /*
- * This is the global namespace. Tearing it down will destroy the
- * ::errorInfo and ::errorCode variables. We save and restore them
- * in case there are any errors in progress, so the error details
- * they contain will not be lost. See test namespace-8.5
- */
-
- Tcl_Obj *errorInfo = Tcl_GetVar2Ex(nsPtr->interp, "errorInfo",
- NULL, TCL_GLOBAL_ONLY);
- Tcl_Obj *errorCode = Tcl_GetVar2Ex(nsPtr->interp, "errorCode",
- NULL, TCL_GLOBAL_ONLY);
-
- if (errorInfo) {
- Tcl_IncrRefCount(errorInfo);
- }
- if (errorCode) {
- Tcl_IncrRefCount(errorCode);
- }
-
- TclDeleteNamespaceVars(nsPtr);
- Tcl_InitHashTable(&nsPtr->varTable, TCL_STRING_KEYS);
-
- if (errorInfo) {
- Tcl_SetVar2Ex(nsPtr->interp, "errorInfo", NULL,
- errorInfo, TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(errorInfo);
- }
- if (errorCode) {
- Tcl_SetVar2Ex(nsPtr->interp, "errorCode", NULL,
- errorCode, TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(errorCode);
- }
- } else {
- /*
- * Variable table should be cleared but not freed! TclDeleteVars
- * frees it, so we reinitialize it afterwards.
- */
-
- TclDeleteNamespaceVars(nsPtr);
- Tcl_InitHashTable(&nsPtr->varTable, TCL_STRING_KEYS);
- }
+ TclDeleteNamespaceVars(nsPtr);
+ TclInitVarHashTable(&nsPtr->varTable, nsPtr);
/*
* Delete all commands in this namespace. Be careful when traversing the
* hash table: when each command is deleted, it removes itself from the
* command table.
+ *
+ * Don't optimize to Tcl_NextHashEntry() because of traces.
*/
for (entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
- entryPtr != NULL;
- entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search)) {
- cmd = (Tcl_Command) Tcl_GetHashValue(entryPtr);
- Tcl_DeleteCommandFromToken((Tcl_Interp *) iPtr, cmd);
+ entryPtr != NULL;
+ entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search)) {
+ cmd = Tcl_GetHashValue(entryPtr);
+ Tcl_DeleteCommandFromToken((Tcl_Interp *) iPtr, cmd);
}
Tcl_DeleteHashTable(&nsPtr->cmdTable);
Tcl_InitHashTable(&nsPtr->cmdTable, TCL_STRING_KEYS);
@@ -764,28 +1092,49 @@ TclTeardownNamespace(nsPtr)
*/
if (nsPtr->parentPtr != NULL) {
- entryPtr = Tcl_FindHashEntry(&nsPtr->parentPtr->childTable,
- nsPtr->name);
- if (entryPtr != NULL) {
- Tcl_DeleteHashEntry(entryPtr);
- }
+ entryPtr = Tcl_FindHashEntry(&nsPtr->parentPtr->childTable,
+ nsPtr->name);
+ if (entryPtr != NULL) {
+ Tcl_DeleteHashEntry(entryPtr);
+ }
}
nsPtr->parentPtr = NULL;
/*
+ * Delete the namespace path if one is installed.
+ */
+
+ if (nsPtr->commandPathLength != 0) {
+ UnlinkNsPath(nsPtr);
+ nsPtr->commandPathLength = 0;
+ }
+ if (nsPtr->commandPathSourceList != NULL) {
+ NamespacePathEntry *nsPathPtr = nsPtr->commandPathSourceList;
+ do {
+ if (nsPathPtr->nsPtr != NULL && nsPathPtr->creatorNsPtr != NULL) {
+ nsPathPtr->creatorNsPtr->cmdRefEpoch++;
+ }
+ nsPathPtr->nsPtr = NULL;
+ nsPathPtr = nsPathPtr->nextPtr;
+ } while (nsPathPtr != NULL);
+ nsPtr->commandPathSourceList = NULL;
+ }
+
+ /*
* Delete all the child namespaces.
*
- * BE CAREFUL: When each child is deleted, it will divorce
- * itself from its parent. You can't traverse a hash table
- * properly if its elements are being deleted. We use only
- * the Tcl_FirstHashEntry function to be safe.
+ * BE CAREFUL: When each child is deleted, it will divorce itself from its
+ * parent. You can't traverse a hash table properly if its elements are
+ * being deleted. We use only the Tcl_FirstHashEntry function to be safe.
+ *
+ * Don't optimize to Tcl_NextHashEntry() because of traces.
*/
for (entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search);
- entryPtr != NULL;
- entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search)) {
- childNsPtr = (Tcl_Namespace *) Tcl_GetHashValue(entryPtr);
- Tcl_DeleteNamespace(childNsPtr);
+ entryPtr != NULL;
+ entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search)) {
+ childNsPtr = Tcl_GetHashValue(entryPtr);
+ Tcl_DeleteNamespace(childNsPtr);
}
/*
@@ -796,7 +1145,7 @@ TclTeardownNamespace(nsPtr)
for (i = 0; i < nsPtr->numExportPatterns; i++) {
ckfree(nsPtr->exportArrayPtr[i]);
}
- ckfree((char *) nsPtr->exportArrayPtr);
+ ckfree((char *) nsPtr->exportArrayPtr);
nsPtr->exportArrayPtr = NULL;
nsPtr->numExportPatterns = 0;
nsPtr->maxExportPatterns = 0;
@@ -807,15 +1156,15 @@ TclTeardownNamespace(nsPtr)
*/
if (nsPtr->deleteProc != NULL) {
- (*nsPtr->deleteProc)(nsPtr->clientData);
+ (*nsPtr->deleteProc)(nsPtr->clientData);
}
nsPtr->deleteProc = NULL;
nsPtr->clientData = NULL;
/*
- * Reset the namespace's id field to ensure that this namespace won't
- * be interpreted as valid by, e.g., the cache validation code for
- * cached command references in Tcl_GetCommandFromObj.
+ * Reset the namespace's id field to ensure that this namespace won't be
+ * interpreted as valid by, e.g., the cache validation code for cached
+ * command references in Tcl_GetCommandFromObj.
*/
nsPtr->nsId = 0;
@@ -826,9 +1175,8 @@ TclTeardownNamespace(nsPtr)
*
* NamespaceFree --
*
- * Called after a namespace has been deleted, when its
- * reference count reaches 0. Frees the data structure
- * representing the namespace.
+ * Called after a namespace has been deleted, when its reference count
+ * reaches 0. Frees the data structure representing the namespace.
*
* Results:
* None.
@@ -840,8 +1188,8 @@ TclTeardownNamespace(nsPtr)
*/
static void
-NamespaceFree(nsPtr)
- register Namespace *nsPtr; /* Points to the namespace to free. */
+NamespaceFree(
+ register Namespace *nsPtr) /* Points to the namespace to free. */
{
/*
* Most of the namespace's contents are freed when the namespace is
@@ -854,7 +1202,6 @@ NamespaceFree(nsPtr)
ckfree((char *) nsPtr);
}
-
/*
*----------------------------------------------------------------------
@@ -862,10 +1209,10 @@ NamespaceFree(nsPtr)
* Tcl_Export --
*
* Makes all the commands matching a pattern available to later be
- * imported from the namespace specified by namespacePtr (or the
- * current namespace if namespacePtr is NULL). The specified pattern is
- * appended onto the namespace's export pattern list, which is
- * optionally cleared beforehand.
+ * imported from the namespace specified by namespacePtr (or the current
+ * namespace if namespacePtr is NULL). The specified pattern is appended
+ * onto the namespace's export pattern list, which is optionally cleared
+ * beforehand.
*
* Results:
* Returns TCL_OK if successful, or TCL_ERROR (along with an error
@@ -879,23 +1226,22 @@ NamespaceFree(nsPtr)
*/
int
-Tcl_Export(interp, namespacePtr, pattern, resetListFirst)
- Tcl_Interp *interp; /* Current interpreter. */
- Tcl_Namespace *namespacePtr; /* Points to the namespace from which
- * commands are to be exported. NULL for
- * the current namespace. */
- CONST char *pattern; /* String pattern indicating which commands
- * to export. This pattern may not include
- * any namespace qualifiers; only commands
- * in the specified namespace may be
- * exported. */
- int resetListFirst; /* If nonzero, resets the namespace's
- * export list before appending. */
-{
-#define INIT_EXPORT_PATTERNS 5
+Tcl_Export(
+ Tcl_Interp *interp, /* Current interpreter. */
+ Tcl_Namespace *namespacePtr,/* Points to the namespace from which commands
+ * are to be exported. NULL for the current
+ * namespace. */
+ const char *pattern, /* String pattern indicating which commands to
+ * export. This pattern may not include any
+ * namespace qualifiers; only commands in the
+ * specified namespace may be exported. */
+ int resetListFirst) /* If nonzero, resets the namespace's export
+ * list before appending. */
+{
+#define INIT_EXPORT_PATTERNS 5
Namespace *nsPtr, *exportNsPtr, *dummyPtr;
- Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
- CONST char *simplePattern;
+ Namespace *currNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
+ const char *simplePattern;
char *patternCpy;
int neededElems, len, i;
@@ -904,9 +1250,9 @@ Tcl_Export(interp, namespacePtr, pattern, resetListFirst)
*/
if (namespacePtr == NULL) {
- nsPtr = (Namespace *) currNsPtr;
+ nsPtr = (Namespace *) currNsPtr;
} else {
- nsPtr = (Namespace *) namespacePtr;
+ nsPtr = (Namespace *) namespacePtr;
}
/*
@@ -921,6 +1267,7 @@ Tcl_Export(interp, namespacePtr, pattern, resetListFirst)
}
ckfree((char *) nsPtr->exportArrayPtr);
nsPtr->exportArrayPtr = NULL;
+ TclInvalidateNsCmdLookup(nsPtr);
nsPtr->numExportPatterns = 0;
nsPtr->maxExportPatterns = 0;
}
@@ -935,49 +1282,39 @@ Tcl_Export(interp, namespacePtr, pattern, resetListFirst)
&exportNsPtr, &dummyPtr, &dummyPtr, &simplePattern);
if ((exportNsPtr != nsPtr) || (strcmp(pattern, simplePattern) != 0)) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "invalid export pattern \"", pattern,
- "\": pattern can't specify a namespace",
- (char *) NULL);
+ Tcl_AppendResult(interp, "invalid export pattern \"", pattern,
+ "\": pattern can't specify a namespace", NULL);
return TCL_ERROR;
}
/*
* Make sure that we don't already have the pattern in the array
*/
+
if (nsPtr->exportArrayPtr != NULL) {
for (i = 0; i < nsPtr->numExportPatterns; i++) {
if (strcmp(pattern, nsPtr->exportArrayPtr[i]) == 0) {
/*
- * The pattern already exists in the list
+ * The pattern already exists in the list.
*/
+
return TCL_OK;
}
}
}
/*
- * Make sure there is room in the namespace's pattern array for the
- * new pattern.
+ * Make sure there is room in the namespace's pattern array for the new
+ * pattern.
*/
neededElems = nsPtr->numExportPatterns + 1;
- if (nsPtr->exportArrayPtr == NULL) {
+ if (neededElems > nsPtr->maxExportPatterns) {
+ nsPtr->maxExportPatterns = nsPtr->maxExportPatterns ?
+ 2 * nsPtr->maxExportPatterns : INIT_EXPORT_PATTERNS;
nsPtr->exportArrayPtr = (char **)
- ckalloc((unsigned) (INIT_EXPORT_PATTERNS * sizeof(char *)));
- nsPtr->numExportPatterns = 0;
- nsPtr->maxExportPatterns = INIT_EXPORT_PATTERNS;
- } else if (neededElems > nsPtr->maxExportPatterns) {
- int numNewElems = 2 * nsPtr->maxExportPatterns;
- size_t currBytes = nsPtr->numExportPatterns * sizeof(char *);
- size_t newBytes = numNewElems * sizeof(char *);
- char **newPtr = (char **) ckalloc((unsigned) newBytes);
-
- memcpy((VOID *) newPtr, (VOID *) nsPtr->exportArrayPtr,
- currBytes);
- ckfree((char *) nsPtr->exportArrayPtr);
- nsPtr->exportArrayPtr = (char **) newPtr;
- nsPtr->maxExportPatterns = numNewElems;
+ ckrealloc((char *) nsPtr->exportArrayPtr,
+ sizeof(char *) * nsPtr->maxExportPatterns);
}
/*
@@ -985,11 +1322,20 @@ Tcl_Export(interp, namespacePtr, pattern, resetListFirst)
*/
len = strlen(pattern);
- patternCpy = (char *) ckalloc((unsigned) (len + 1));
- strcpy(patternCpy, pattern);
-
+ patternCpy = ckalloc((unsigned) (len + 1));
+ memcpy(patternCpy, pattern, (unsigned) len + 1);
+
nsPtr->exportArrayPtr[nsPtr->numExportPatterns] = patternCpy;
nsPtr->numExportPatterns++;
+
+ /*
+ * The list of commands actually exported from the namespace might have
+ * changed (probably will have!) However, we do not need to recompute this
+ * just yet; next time we need the info will be soon enough.
+ */
+
+ TclInvalidateNsCmdLookup(nsPtr);
+
return TCL_OK;
#undef INIT_EXPORT_PATTERNS
}
@@ -1005,24 +1351,24 @@ Tcl_Export(interp, namespacePtr, pattern, resetListFirst)
* Results:
* The return value is normally TCL_OK; in this case the object
* referenced by objPtr has each export pattern appended to it. If an
- * error occurs, TCL_ERROR is returned and the interpreter's result
- * holds an error message.
+ * error occurs, TCL_ERROR is returned and the interpreter's result holds
+ * an error message.
*
* Side effects:
- * If necessary, the object referenced by objPtr is converted into
- * a list object.
+ * If necessary, the object referenced by objPtr is converted into a list
+ * object.
*
*----------------------------------------------------------------------
*/
int
-Tcl_AppendExportList(interp, namespacePtr, objPtr)
- Tcl_Interp *interp; /* Interpreter used for error reporting. */
- Tcl_Namespace *namespacePtr; /* Points to the namespace whose export
- * pattern list is appended onto objPtr.
- * NULL for the current namespace. */
- Tcl_Obj *objPtr; /* Points to the Tcl object onto which the
- * export pattern list is appended. */
+Tcl_AppendExportList(
+ Tcl_Interp *interp, /* Interpreter used for error reporting. */
+ Tcl_Namespace *namespacePtr,/* Points to the namespace whose export
+ * pattern list is appended onto objPtr. NULL
+ * for the current namespace. */
+ Tcl_Obj *objPtr) /* Points to the Tcl object onto which the
+ * export pattern list is appended. */
{
Namespace *nsPtr;
int i, result;
@@ -1032,9 +1378,9 @@ Tcl_AppendExportList(interp, namespacePtr, objPtr)
*/
if (namespacePtr == NULL) {
- nsPtr = (Namespace *) (Namespace *) Tcl_GetCurrentNamespace(interp);
+ nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
} else {
- nsPtr = (Namespace *) namespacePtr;
+ nsPtr = (Namespace *) namespacePtr;
}
/*
@@ -1057,90 +1403,79 @@ Tcl_AppendExportList(interp, namespacePtr, objPtr)
* Tcl_Import --
*
* Imports all of the commands matching a pattern into the namespace
- * specified by namespacePtr (or the current namespace if contextNsPtr
- * is NULL). This is done by creating a new command (the "imported
- * command") that points to the real command in its original namespace.
+ * specified by namespacePtr (or the current namespace if contextNsPtr is
+ * NULL). This is done by creating a new command (the "imported command")
+ * that points to the real command in its original namespace.
*
- * If matching commands are on the autoload path but haven't been
- * loaded yet, this command forces them to be loaded, then creates
- * the links to them.
+ * If matching commands are on the autoload path but haven't been loaded
+ * yet, this command forces them to be loaded, then creates the links to
+ * them.
*
* Results:
* Returns TCL_OK if successful, or TCL_ERROR (along with an error
* message in the interpreter's result) if something goes wrong.
*
* Side effects:
- * Creates new commands in the importing namespace. These indirect
- * calls back to the real command and are deleted if the real commands
- * are deleted.
+ * Creates new commands in the importing namespace. These indirect calls
+ * back to the real command and are deleted if the real commands are
+ * deleted.
*
*----------------------------------------------------------------------
*/
int
-Tcl_Import(interp, namespacePtr, pattern, allowOverwrite)
- Tcl_Interp *interp; /* Current interpreter. */
- Tcl_Namespace *namespacePtr; /* Points to the namespace into which the
- * commands are to be imported. NULL for
- * the current namespace. */
- CONST char *pattern; /* String pattern indicating which commands
- * to import. This pattern should be
- * qualified by the name of the namespace
- * from which to import the command(s). */
- int allowOverwrite; /* If nonzero, allow existing commands to
- * be overwritten by imported commands.
- * If 0, return an error if an imported
- * cmd conflicts with an existing one. */
+Tcl_Import(
+ Tcl_Interp *interp, /* Current interpreter. */
+ Tcl_Namespace *namespacePtr,/* Points to the namespace into which the
+ * commands are to be imported. NULL for the
+ * current namespace. */
+ const char *pattern, /* String pattern indicating which commands to
+ * import. This pattern should be qualified by
+ * the name of the namespace from which to
+ * import the command(s). */
+ int allowOverwrite) /* If nonzero, allow existing commands to be
+ * overwritten by imported commands. If 0,
+ * return an error if an imported cmd
+ * conflicts with an existing one. */
{
- Interp *iPtr = (Interp *) interp;
Namespace *nsPtr, *importNsPtr, *dummyPtr;
- Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
- CONST char *simplePattern;
- char *cmdName;
+ const char *simplePattern;
register Tcl_HashEntry *hPtr;
Tcl_HashSearch search;
- Command *cmdPtr;
- ImportRef *refPtr;
- Tcl_Command autoCmd, importedCmd;
- ImportedCmdData *dataPtr;
- int wasExported, i, result;
/*
* If the specified namespace is NULL, use the current namespace.
*/
if (namespacePtr == NULL) {
- nsPtr = (Namespace *) currNsPtr;
+ nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
} else {
- nsPtr = (Namespace *) namespacePtr;
+ nsPtr = (Namespace *) namespacePtr;
}
-
+
/*
- * First, invoke the "auto_import" command with the pattern
- * being imported. This command is part of the Tcl library.
- * It looks for imported commands in autoloaded libraries and
- * loads them in. That way, they will be found when we try
- * to create links below.
+ * First, invoke the "auto_import" command with the pattern being
+ * imported. This command is part of the Tcl library. It looks for
+ * imported commands in autoloaded libraries and loads them in. That way,
+ * they will be found when we try to create links below.
+ *
+ * Note that we don't just call Tcl_EvalObjv() directly because we do not
+ * want absence of the command to be a failure case.
*/
-
- autoCmd = Tcl_FindCommand(interp, "auto_import",
- (Tcl_Namespace *) NULL, /*flags*/ TCL_GLOBAL_ONLY);
-
- if (autoCmd != NULL) {
+
+ if (Tcl_FindCommand(interp,"auto_import",NULL,TCL_GLOBAL_ONLY) != NULL) {
Tcl_Obj *objv[2];
-
- objv[0] = Tcl_NewStringObj("auto_import", -1);
- Tcl_IncrRefCount(objv[0]);
+ int result;
+
+ TclNewLiteralStringObj(objv[0], "auto_import");
objv[1] = Tcl_NewStringObj(pattern, -1);
+
+ Tcl_IncrRefCount(objv[0]);
Tcl_IncrRefCount(objv[1]);
-
- cmdPtr = (Command *) autoCmd;
- result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp,
- 2, objv);
-
+ result = Tcl_EvalObjv(interp, 2, objv, TCL_GLOBAL_ONLY);
Tcl_DecrRefCount(objv[0]);
Tcl_DecrRefCount(objv[1]);
-
+
if (result != TCL_OK) {
return TCL_ERROR;
}
@@ -1148,38 +1483,35 @@ Tcl_Import(interp, namespacePtr, pattern, allowOverwrite)
}
/*
- * From the pattern, find the namespace from which we are importing
- * and get the simple pattern (no namespace qualifiers or ::'s) at
- * the end.
+ * From the pattern, find the namespace from which we are importing and
+ * get the simple pattern (no namespace qualifiers or ::'s) at the end.
*/
if (strlen(pattern) == 0) {
- Tcl_SetStringObj(Tcl_GetObjResult(interp),
- "empty import pattern", -1);
- return TCL_ERROR;
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("empty import pattern", -1));
+ return TCL_ERROR;
}
TclGetNamespaceForQualName(interp, pattern, nsPtr,
/*flags*/ (TCL_LEAVE_ERR_MSG | TCL_NAMESPACE_ONLY),
&importNsPtr, &dummyPtr, &dummyPtr, &simplePattern);
if (importNsPtr == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "unknown namespace in import pattern \"",
- pattern, "\"", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "unknown namespace in import pattern \"",
+ pattern, "\"", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", pattern, NULL);
+ return TCL_ERROR;
}
if (importNsPtr == nsPtr) {
if (pattern == simplePattern) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ Tcl_AppendResult(interp,
"no namespace specified in import pattern \"", pattern,
- "\"", (char *) NULL);
+ "\"", NULL);
} else {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "import pattern \"", pattern,
+ Tcl_AppendResult(interp, "import pattern \"", pattern,
"\" tries to import from namespace \"",
- importNsPtr->name, "\" into itself", (char *) NULL);
+ importNsPtr->name, "\" into itself", NULL);
}
- return TCL_ERROR;
+ return TCL_ERROR;
}
/*
@@ -1189,118 +1521,154 @@ Tcl_Import(interp, namespacePtr, pattern, allowOverwrite)
* commands redirect their invocations to the "real" command.
*/
+ if ((simplePattern != NULL) && TclMatchIsTrivial(simplePattern)) {
+ hPtr = Tcl_FindHashEntry(&importNsPtr->cmdTable, simplePattern);
+ if (hPtr == NULL) {
+ return TCL_OK;
+ }
+ return DoImport(interp, nsPtr, hPtr, simplePattern, pattern,
+ importNsPtr, allowOverwrite);
+ }
for (hPtr = Tcl_FirstHashEntry(&importNsPtr->cmdTable, &search);
- (hPtr != NULL);
- hPtr = Tcl_NextHashEntry(&search)) {
- cmdName = Tcl_GetHashKey(&importNsPtr->cmdTable, hPtr);
- if (Tcl_StringMatch(cmdName, simplePattern)) {
- /*
- * The command cmdName in the source namespace matches the
- * pattern. Check whether it was exported. If it wasn't,
- * we ignore it.
- */
- Tcl_HashEntry *found;
+ (hPtr != NULL); hPtr = Tcl_NextHashEntry(&search)) {
+ char *cmdName = Tcl_GetHashKey(&importNsPtr->cmdTable, hPtr);
+ if (Tcl_StringMatch(cmdName, simplePattern) &&
+ DoImport(interp, nsPtr, hPtr, cmdName, pattern, importNsPtr,
+ allowOverwrite) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DoImport --
+ *
+ * Import a particular command from one namespace into another. Helper
+ * for Tcl_Import().
+ *
+ * Results:
+ * Standard Tcl result code. If TCL_ERROR, appends an error message to
+ * the interpreter result.
+ *
+ * Side effects:
+ * A new command is created in the target namespace unless this is a
+ * reimport of exactly the same command as before.
+ *
+ *----------------------------------------------------------------------
+ */
- wasExported = 0;
- for (i = 0; i < importNsPtr->numExportPatterns; i++) {
- if (Tcl_StringMatch(cmdName,
- importNsPtr->exportArrayPtr[i])) {
- wasExported = 1;
- break;
- }
- }
- if (!wasExported) {
- continue;
- }
+static int
+DoImport(
+ Tcl_Interp *interp,
+ Namespace *nsPtr,
+ Tcl_HashEntry *hPtr,
+ const char *cmdName,
+ const char *pattern,
+ Namespace *importNsPtr,
+ int allowOverwrite)
+{
+ int i = 0, exported = 0;
+ Tcl_HashEntry *found;
- /*
- * Unless there is a name clash, create an imported command
- * in the current namespace that refers to cmdPtr.
- */
+ /*
+ * The command cmdName in the source namespace matches the pattern. Check
+ * whether it was exported. If it wasn't, we ignore it.
+ */
- found = Tcl_FindHashEntry(&nsPtr->cmdTable, cmdName);
- if ((found == NULL) || allowOverwrite) {
- /*
- * Create the imported command and its client data.
- * To create the new command in the current namespace,
- * generate a fully qualified name for it.
- */
+ while (!exported && (i < importNsPtr->numExportPatterns)) {
+ exported |= Tcl_StringMatch(cmdName, importNsPtr->exportArrayPtr[i++]);
+ }
+ if (!exported) {
+ return TCL_OK;
+ }
- Tcl_DString ds;
+ /*
+ * Unless there is a name clash, create an imported command in the current
+ * namespace that refers to cmdPtr.
+ */
- Tcl_DStringInit(&ds);
- Tcl_DStringAppend(&ds, nsPtr->fullName, -1);
- if (nsPtr != iPtr->globalNsPtr) {
- Tcl_DStringAppend(&ds, "::", 2);
- }
- Tcl_DStringAppend(&ds, cmdName, -1);
+ found = Tcl_FindHashEntry(&nsPtr->cmdTable, cmdName);
+ if ((found == NULL) || allowOverwrite) {
+ /*
+ * Create the imported command and its client data. To create the new
+ * command in the current namespace, generate a fully qualified name
+ * for it.
+ */
- /*
- * Check whether creating the new imported command in the
- * current namespace would create a cycle of imported
- * command references.
- */
+ Tcl_DString ds;
+ Tcl_Command importedCmd;
+ ImportedCmdData *dataPtr;
+ Command *cmdPtr;
+ ImportRef *refPtr;
- cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
- if ((found != NULL)
- && cmdPtr->deleteProc == DeleteImportedCmd) {
-
- Command *overwrite = (Command *) Tcl_GetHashValue(found);
- Command *link = cmdPtr;
- while (link->deleteProc == DeleteImportedCmd) {
- ImportedCmdData *dataPtr;
-
- dataPtr = (ImportedCmdData *) link->objClientData;
- link = dataPtr->realCmdPtr;
- if (overwrite == link) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "import pattern \"", pattern,
- "\" would create a loop containing ",
- "command \"", Tcl_DStringValue(&ds),
- "\"", (char *) NULL);
- Tcl_DStringFree(&ds);
- return TCL_ERROR;
- }
- }
+ Tcl_DStringInit(&ds);
+ Tcl_DStringAppend(&ds, nsPtr->fullName, -1);
+ if (nsPtr != ((Interp *) interp)->globalNsPtr) {
+ Tcl_DStringAppend(&ds, "::", 2);
+ }
+ Tcl_DStringAppend(&ds, cmdName, -1);
+
+ /*
+ * Check whether creating the new imported command in the current
+ * namespace would create a cycle of imported command references.
+ */
+
+ cmdPtr = Tcl_GetHashValue(hPtr);
+ if (found != NULL && cmdPtr->deleteProc == DeleteImportedCmd) {
+ Command *overwrite = Tcl_GetHashValue(found);
+ Command *link = cmdPtr;
+
+ while (link->deleteProc == DeleteImportedCmd) {
+ ImportedCmdData *dataPtr = link->objClientData;
+
+ link = dataPtr->realCmdPtr;
+ if (overwrite == link) {
+ Tcl_AppendResult(interp, "import pattern \"", pattern,
+ "\" would create a loop containing command \"",
+ Tcl_DStringValue(&ds), "\"", NULL);
+ Tcl_DStringFree(&ds);
+ return TCL_ERROR;
}
+ }
+ }
+
+ dataPtr = (ImportedCmdData *) ckalloc(sizeof(ImportedCmdData));
+ importedCmd = Tcl_CreateObjCommand(interp, Tcl_DStringValue(&ds),
+ InvokeImportedCmd, dataPtr, DeleteImportedCmd);
+ dataPtr->realCmdPtr = cmdPtr;
+ dataPtr->selfPtr = (Command *) importedCmd;
+ dataPtr->selfPtr->compileProc = cmdPtr->compileProc;
+ Tcl_DStringFree(&ds);
+
+ /*
+ * Create an ImportRef structure describing this new import command
+ * and add it to the import ref list in the "real" command.
+ */
+
+ refPtr = (ImportRef *) ckalloc(sizeof(ImportRef));
+ refPtr->importedCmdPtr = (Command *) importedCmd;
+ refPtr->nextPtr = cmdPtr->importRefPtr;
+ cmdPtr->importRefPtr = refPtr;
+ } else {
+ Command *overwrite = Tcl_GetHashValue(found);
- dataPtr = (ImportedCmdData *)
- ckalloc(sizeof(ImportedCmdData));
- importedCmd = Tcl_CreateObjCommand(interp,
- Tcl_DStringValue(&ds), InvokeImportedCmd,
- (ClientData) dataPtr, DeleteImportedCmd);
- dataPtr->realCmdPtr = cmdPtr;
- dataPtr->selfPtr = (Command *) importedCmd;
- dataPtr->selfPtr->compileProc = cmdPtr->compileProc;
- Tcl_DStringFree(&ds);
+ if (overwrite->deleteProc == DeleteImportedCmd) {
+ ImportedCmdData *dataPtr = overwrite->objClientData;
+ if (dataPtr->realCmdPtr == Tcl_GetHashValue(hPtr)) {
/*
- * Create an ImportRef structure describing this new import
- * command and add it to the import ref list in the "real"
- * command.
+ * Repeated import of same command is acceptable.
*/
- refPtr = (ImportRef *) ckalloc(sizeof(ImportRef));
- refPtr->importedCmdPtr = (Command *) importedCmd;
- refPtr->nextPtr = cmdPtr->importRefPtr;
- cmdPtr->importRefPtr = refPtr;
- } else {
- Command *overwrite = (Command *) Tcl_GetHashValue(found);
- if (overwrite->deleteProc == DeleteImportedCmd) {
- ImportedCmdData *dataPtr =
- (ImportedCmdData *) overwrite->objClientData;
- if (dataPtr->realCmdPtr
- == (Command *) Tcl_GetHashValue(hPtr)) {
- /* Repeated import of same command -- acceptable */
- return TCL_OK;
- }
- }
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "can't import command \"", cmdName,
- "\": already exists", (char *) NULL);
- return TCL_ERROR;
- }
- }
+ return TCL_OK;
+ }
+ }
+ Tcl_AppendResult(interp, "can't import command \"", cmdName,
+ "\": already exists", NULL);
+ return TCL_ERROR;
}
return TCL_OK;
}
@@ -1310,40 +1678,39 @@ Tcl_Import(interp, namespacePtr, pattern, allowOverwrite)
*
* Tcl_ForgetImport --
*
- * Deletes commands previously imported into the namespace indicated. The
- * by namespacePtr, or the current namespace of interp, when
- * namespacePtr is NULL. The pattern controls which imported commands
- * are deleted. A simple pattern, one without namespace separators,
- * matches the current command names of imported commands in the
- * namespace. Matching imported commands are deleted. A qualified
- * pattern is interpreted as deletion selection on the basis of where
- * the command is imported from. The original command and "first link"
- * command for each imported command are determined, and they are matched
- * against the pattern. A match leads to deletion of the imported
- * command.
+ * Deletes commands previously imported into the namespace indicated.
+ * The by namespacePtr, or the current namespace of interp, when
+ * namespacePtr is NULL. The pattern controls which imported commands are
+ * deleted. A simple pattern, one without namespace separators, matches
+ * the current command names of imported commands in the namespace.
+ * Matching imported commands are deleted. A qualified pattern is
+ * interpreted as deletion selection on the basis of where the command is
+ * imported from. The original command and "first link" command for each
+ * imported command are determined, and they are matched against the
+ * pattern. A match leads to deletion of the imported command.
*
* Results:
- * Returns TCL_ERROR and records an error message in the interp
- * result if a namespace qualified pattern refers to a namespace
- * that does not exist. Otherwise, returns TCL_OK.
+ * Returns TCL_ERROR and records an error message in the interp result if
+ * a namespace qualified pattern refers to a namespace that does not
+ * exist. Otherwise, returns TCL_OK.
*
* Side effects:
- * May delete commands.
+ * May delete commands.
*
*----------------------------------------------------------------------
*/
int
-Tcl_ForgetImport(interp, namespacePtr, pattern)
- Tcl_Interp *interp; /* Current interpreter. */
- Tcl_Namespace *namespacePtr; /* Points to the namespace from which
- * previously imported commands should be
- * removed. NULL for current namespace. */
- CONST char *pattern; /* String pattern indicating which imported
- * commands to remove. */
+Tcl_ForgetImport(
+ Tcl_Interp *interp, /* Current interpreter. */
+ Tcl_Namespace *namespacePtr,/* Points to the namespace from which
+ * previously imported commands should be
+ * removed. NULL for current namespace. */
+ const char *pattern) /* String pattern indicating which imported
+ * commands to remove. */
{
Namespace *nsPtr, *sourceNsPtr, *dummyPtr;
- CONST char *simplePattern;
+ const char *simplePattern;
char *cmdName;
register Tcl_HashEntry *hPtr;
Tcl_HashSearch search;
@@ -1353,14 +1720,14 @@ Tcl_ForgetImport(interp, namespacePtr, pattern)
*/
if (namespacePtr == NULL) {
- nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+ nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
} else {
- nsPtr = (Namespace *) namespacePtr;
+ nsPtr = (Namespace *) namespacePtr;
}
/*
- * Parse the pattern into its namespace-qualification (if any)
- * and the simple pattern.
+ * Parse the pattern into its namespace-qualification (if any) and the
+ * simple pattern.
*/
TclGetNamespaceForQualName(interp, pattern, nsPtr,
@@ -1368,22 +1735,33 @@ Tcl_ForgetImport(interp, namespacePtr, pattern)
&sourceNsPtr, &dummyPtr, &dummyPtr, &simplePattern);
if (sourceNsPtr == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ Tcl_AppendResult(interp,
"unknown namespace in namespace forget pattern \"",
- pattern, "\"", (char *) NULL);
- return TCL_ERROR;
+ pattern, "\"", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", pattern, NULL);
+ return TCL_ERROR;
}
if (strcmp(pattern, simplePattern) == 0) {
/*
- * The pattern is simple.
- * Delete any imported commands that match it.
+ * The pattern is simple. Delete any imported commands that match it.
*/
+ if (TclMatchIsTrivial(simplePattern)) {
+ Command *cmdPtr;
+
+ hPtr = Tcl_FindHashEntry(&nsPtr->cmdTable, simplePattern);
+ if ((hPtr != NULL)
+ && (cmdPtr = Tcl_GetHashValue(hPtr))
+ && (cmdPtr->deleteProc == DeleteImportedCmd)) {
+ Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
+ }
+ return TCL_OK;
+ }
for (hPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
- (hPtr != NULL);
- hPtr = Tcl_NextHashEntry(&search)) {
- Command *cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
+ (hPtr != NULL); hPtr = Tcl_NextHashEntry(&search)) {
+ Command *cmdPtr = Tcl_GetHashValue(hPtr);
+
if (cmdPtr->deleteProc != DeleteImportedCmd) {
continue;
}
@@ -1395,26 +1773,29 @@ Tcl_ForgetImport(interp, namespacePtr, pattern)
return TCL_OK;
}
- /* The pattern was namespace-qualified */
+ /*
+ * The pattern was namespace-qualified.
+ */
for (hPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search); (hPtr != NULL);
hPtr = Tcl_NextHashEntry(&search)) {
Tcl_CmdInfo info;
- Tcl_Command token = (Tcl_Command) Tcl_GetHashValue(hPtr);
+ Tcl_Command token = Tcl_GetHashValue(hPtr);
Tcl_Command origin = TclGetOriginalCommand(token);
if (Tcl_GetCommandInfoFromToken(origin, &info) == 0) {
- continue; /* Not an imported command */
+ continue; /* Not an imported command. */
}
if (info.namespacePtr != (Tcl_Namespace *) sourceNsPtr) {
/*
- * Original not in namespace we're matching.
- * Check the first link in the import chain.
+ * Original not in namespace we're matching. Check the first link
+ * in the import chain.
*/
+
Command *cmdPtr = (Command *) token;
- ImportedCmdData *dataPtr =
- (ImportedCmdData *) cmdPtr->objClientData;
+ ImportedCmdData *dataPtr = cmdPtr->objClientData;
Tcl_Command firstToken = (Tcl_Command) dataPtr->realCmdPtr;
+
if (firstToken == origin) {
continue;
}
@@ -1438,15 +1819,15 @@ Tcl_ForgetImport(interp, namespacePtr, pattern)
*
* An imported command is created in an namespace when a "real" command
* is imported from another namespace. If the specified command is an
- * imported command, this procedure returns the original command it
- * refers to.
+ * imported command, this function returns the original command it refers
+ * to.
*
* Results:
* If the command was imported into a sequence of namespaces a, b,...,n
* where each successive namespace just imports the command from the
- * previous namespace, this procedure returns the Tcl_Command token in
- * the first namespace, a. Otherwise, if the specified command is not
- * an imported command, the procedure returns NULL.
+ * previous namespace, this function returns the Tcl_Command token in the
+ * first namespace, a. Otherwise, if the specified command is not an
+ * imported command, the function returns NULL.
*
* Side effects:
* None.
@@ -1455,19 +1836,19 @@ Tcl_ForgetImport(interp, namespacePtr, pattern)
*/
Tcl_Command
-TclGetOriginalCommand(command)
- Tcl_Command command; /* The imported command for which the
- * original command should be returned. */
+TclGetOriginalCommand(
+ Tcl_Command command) /* The imported command for which the original
+ * command should be returned. */
{
register Command *cmdPtr = (Command *) command;
ImportedCmdData *dataPtr;
if (cmdPtr->deleteProc != DeleteImportedCmd) {
- return (Tcl_Command) NULL;
+ return NULL;
}
-
+
while (cmdPtr->deleteProc == DeleteImportedCmd) {
- dataPtr = (ImportedCmdData *) cmdPtr->objClientData;
+ dataPtr = cmdPtr->objClientData;
cmdPtr = dataPtr->realCmdPtr;
}
return (Tcl_Command) cmdPtr;
@@ -1478,33 +1859,33 @@ TclGetOriginalCommand(command)
*
* InvokeImportedCmd --
*
- * Invoked by Tcl whenever the user calls an imported command that
- * was created by Tcl_Import. Finds the "real" command (in another
+ * Invoked by Tcl whenever the user calls an imported command that was
+ * created by Tcl_Import. Finds the "real" command (in another
* namespace), and passes control to it.
*
* Results:
- * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
+ * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
*
* Side effects:
- * Returns a result in the interpreter's result object. If anything
- * goes wrong, the result object is set to an error message.
+ * Returns a result in the interpreter's result object. If anything goes
+ * wrong, the result object is set to an error message.
*
*----------------------------------------------------------------------
*/
static int
-InvokeImportedCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Points to the imported command's
+InvokeImportedCmd(
+ ClientData clientData, /* Points to the imported command's
* ImportedCmdData structure. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* The argument objects. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* The argument objects. */
{
- register ImportedCmdData *dataPtr = (ImportedCmdData *) clientData;
+ register ImportedCmdData *dataPtr = clientData;
register Command *realCmdPtr = dataPtr->realCmdPtr;
return (*realCmdPtr->objProc)(realCmdPtr->objClientData, interp,
- objc, objv);
+ objc, objv);
}
/*
@@ -1513,11 +1894,11 @@ InvokeImportedCmd(clientData, interp, objc, objv)
* DeleteImportedCmd --
*
* Invoked by Tcl whenever an imported command is deleted. The "real"
- * command keeps a list of all the imported commands that refer to it,
- * so those imported commands can be deleted when the real command is
- * deleted. This procedure removes the imported command reference from
- * the real command's list, and frees up the memory associated with
- * the imported command.
+ * command keeps a list of all the imported commands that refer to it, so
+ * those imported commands can be deleted when the real command is
+ * deleted. This function removes the imported command reference from the
+ * real command's list, and frees up the memory associated with the
+ * imported command.
*
* Results:
* None.
@@ -1529,25 +1910,25 @@ InvokeImportedCmd(clientData, interp, objc, objv)
*/
static void
-DeleteImportedCmd(clientData)
- ClientData clientData; /* Points to the imported command's
+DeleteImportedCmd(
+ ClientData clientData) /* Points to the imported command's
* ImportedCmdData structure. */
{
- ImportedCmdData *dataPtr = (ImportedCmdData *) clientData;
+ ImportedCmdData *dataPtr = clientData;
Command *realCmdPtr = dataPtr->realCmdPtr;
Command *selfPtr = dataPtr->selfPtr;
register ImportRef *refPtr, *prevPtr;
prevPtr = NULL;
- for (refPtr = realCmdPtr->importRefPtr; refPtr != NULL;
- refPtr = refPtr->nextPtr) {
+ for (refPtr = realCmdPtr->importRefPtr; refPtr != NULL;
+ refPtr = refPtr->nextPtr) {
if (refPtr->importedCmdPtr == selfPtr) {
/*
* Remove *refPtr from real command's list of imported commands
* that refer to it.
*/
-
- if (prevPtr == NULL) { /* refPtr is first in list */
+
+ if (prevPtr == NULL) { /* refPtr is first in list. */
realCmdPtr->importRefPtr = refPtr->nextPtr;
} else {
prevPtr->nextPtr = refPtr->nextPtr;
@@ -1558,8 +1939,8 @@ DeleteImportedCmd(clientData)
}
prevPtr = refPtr;
}
-
- panic("DeleteImportedCmd: did not find cmd in real cmd's list of import references");
+
+ Tcl_Panic("DeleteImportedCmd: did not find cmd in real cmd's list of import references");
}
/*
@@ -1568,162 +1949,157 @@ DeleteImportedCmd(clientData)
* TclGetNamespaceForQualName --
*
* Given a qualified name specifying a command, variable, or namespace,
- * and a namespace in which to resolve the name, this procedure returns
- * a pointer to the namespace that contains the item. A qualified name
- * consists of the "simple" name of an item qualified by the names of
- * an arbitrary number of containing namespace separated by "::"s. If
- * the qualified name starts with "::", it is interpreted absolutely
- * from the global namespace. Otherwise, it is interpreted relative to
- * the namespace specified by cxtNsPtr if it is non-NULL. If cxtNsPtr
- * is NULL, the name is interpreted relative to the current namespace.
- *
- * A relative name like "foo::bar::x" can be found starting in either
- * the current namespace or in the global namespace. So each search
- * usually follows two tracks, and two possible namespaces are
- * returned. If the procedure sets either *nsPtrPtr or *altNsPtrPtr to
- * NULL, then that path failed.
+ * and a namespace in which to resolve the name, this function returns a
+ * pointer to the namespace that contains the item. A qualified name
+ * consists of the "simple" name of an item qualified by the names of an
+ * arbitrary number of containing namespace separated by "::"s. If the
+ * qualified name starts with "::", it is interpreted absolutely from the
+ * global namespace. Otherwise, it is interpreted relative to the
+ * namespace specified by cxtNsPtr if it is non-NULL. If cxtNsPtr is
+ * NULL, the name is interpreted relative to the current namespace.
+ *
+ * A relative name like "foo::bar::x" can be found starting in either the
+ * current namespace or in the global namespace. So each search usually
+ * follows two tracks, and two possible namespaces are returned. If the
+ * function sets either *nsPtrPtr or *altNsPtrPtr to NULL, then that path
+ * failed.
*
* If "flags" contains TCL_GLOBAL_ONLY, the relative qualified name is
- * sought only in the global :: namespace. The alternate search
- * (also) starting from the global namespace is ignored and
- * *altNsPtrPtr is set NULL.
- *
- * If "flags" contains TCL_NAMESPACE_ONLY, the relative qualified
- * name is sought only in the namespace specified by cxtNsPtr. The
- * alternate search starting from the global namespace is ignored and
- * *altNsPtrPtr is set NULL. If both TCL_GLOBAL_ONLY and
- * TCL_NAMESPACE_ONLY are specified, TCL_GLOBAL_ONLY is ignored and
- * the search starts from the namespace specified by cxtNsPtr.
- *
- * If "flags" contains CREATE_NS_IF_UNKNOWN, all namespace
- * components of the qualified name that cannot be found are
- * automatically created within their specified parent. This makes sure
- * that functions like Tcl_CreateCommand always succeed. There is no
- * alternate search path, so *altNsPtrPtr is set NULL.
- *
- * If "flags" contains FIND_ONLY_NS, the qualified name is treated as a
- * reference to a namespace, and the entire qualified name is
- * followed. If the name is relative, the namespace is looked up only
- * in the current namespace. A pointer to the namespace is stored in
- * *nsPtrPtr and NULL is stored in *simpleNamePtr. Otherwise, if
- * FIND_ONLY_NS is not specified, only the leading components are
- * treated as namespace names, and a pointer to the simple name of the
- * final component is stored in *simpleNamePtr.
+ * sought only in the global :: namespace. The alternate search (also)
+ * starting from the global namespace is ignored and *altNsPtrPtr is set
+ * NULL.
+ *
+ * If "flags" contains TCL_NAMESPACE_ONLY, the relative qualified name is
+ * sought only in the namespace specified by cxtNsPtr. The alternate
+ * search starting from the global namespace is ignored and *altNsPtrPtr
+ * is set NULL. If both TCL_GLOBAL_ONLY and TCL_NAMESPACE_ONLY are
+ * specified, TCL_GLOBAL_ONLY is ignored and the search starts from the
+ * namespace specified by cxtNsPtr.
+ *
+ * If "flags" contains TCL_CREATE_NS_IF_UNKNOWN, all namespace components
+ * of the qualified name that cannot be found are automatically created
+ * within their specified parent. This makes sure that functions like
+ * Tcl_CreateCommand always succeed. There is no alternate search path,
+ * so *altNsPtrPtr is set NULL.
+ *
+ * If "flags" contains TCL_FIND_ONLY_NS, the qualified name is treated as
+ * a reference to a namespace, and the entire qualified name is followed.
+ * If the name is relative, the namespace is looked up only in the
+ * current namespace. A pointer to the namespace is stored in *nsPtrPtr
+ * and NULL is stored in *simpleNamePtr. Otherwise, if TCL_FIND_ONLY_NS
+ * is not specified, only the leading components are treated as namespace
+ * names, and a pointer to the simple name of the final component is
+ * stored in *simpleNamePtr.
*
* Results:
* It sets *nsPtrPtr and *altNsPtrPtr to point to the two possible
* namespaces which represent the last (containing) namespace in the
- * qualified name. If the procedure sets either *nsPtrPtr or *altNsPtrPtr
- * to NULL, then the search along that path failed. The procedure also
+ * qualified name. If the function sets either *nsPtrPtr or *altNsPtrPtr
+ * to NULL, then the search along that path failed. The function also
* stores a pointer to the simple name of the final component in
* *simpleNamePtr. If the qualified name is "::" or was treated as a
- * namespace reference (FIND_ONLY_NS), the procedure stores a pointer
+ * namespace reference (TCL_FIND_ONLY_NS), the function stores a pointer
* to the namespace in *nsPtrPtr, NULL in *altNsPtrPtr, and sets
* *simpleNamePtr to point to an empty string.
*
- * If there is an error, this procedure returns TCL_ERROR. If "flags"
+ * If there is an error, this function returns TCL_ERROR. If "flags"
* contains TCL_LEAVE_ERR_MSG, an error message is returned in the
* interpreter's result object. Otherwise, the interpreter's result
* object is left unchanged.
*
- * *actualCxtPtrPtr is set to the actual context namespace. It is
- * set to the input context namespace pointer in cxtNsPtr. If cxtNsPtr
- * is NULL, it is set to the current namespace context.
+ * *actualCxtPtrPtr is set to the actual context namespace. It is set to
+ * the input context namespace pointer in cxtNsPtr. If cxtNsPtr is NULL,
+ * it is set to the current namespace context.
*
- * For backwards compatibility with the TclPro byte code loader,
- * this function always returns TCL_OK.
+ * For backwards compatibility with the TclPro byte code loader, this
+ * function always returns TCL_OK.
*
* Side effects:
- * If "flags" contains CREATE_NS_IF_UNKNOWN, new namespaces may be
+ * If "flags" contains TCL_CREATE_NS_IF_UNKNOWN, new namespaces may be
* created.
*
*----------------------------------------------------------------------
*/
int
-TclGetNamespaceForQualName(interp, qualName, cxtNsPtr, flags,
- nsPtrPtr, altNsPtrPtr, actualCxtPtrPtr, simpleNamePtr)
- Tcl_Interp *interp; /* Interpreter in which to find the
- * namespace containing qualName. */
- CONST char *qualName; /* A namespace-qualified name of an
- * command, variable, or namespace. */
- Namespace *cxtNsPtr; /* The namespace in which to start the
- * search for qualName's namespace. If NULL
- * start from the current namespace.
- * Ignored if TCL_GLOBAL_ONLY is set. */
- int flags; /* Flags controlling the search: an OR'd
- * combination of TCL_GLOBAL_ONLY,
- * TCL_NAMESPACE_ONLY,
- * CREATE_NS_IF_UNKNOWN, and
- * FIND_ONLY_NS. */
- Namespace **nsPtrPtr; /* Address where procedure stores a pointer
- * to containing namespace if qualName is
- * found starting from *cxtNsPtr or, if
- * TCL_GLOBAL_ONLY is set, if qualName is
- * found in the global :: namespace. NULL
- * is stored otherwise. */
- Namespace **altNsPtrPtr; /* Address where procedure stores a pointer
- * to containing namespace if qualName is
- * found starting from the global ::
- * namespace. NULL is stored if qualName
- * isn't found starting from :: or if the
- * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
- * CREATE_NS_IF_UNKNOWN, FIND_ONLY_NS flag
- * is set. */
- Namespace **actualCxtPtrPtr; /* Address where procedure stores a pointer
- * to the actual namespace from which the
- * search started. This is either cxtNsPtr,
- * the :: namespace if TCL_GLOBAL_ONLY was
- * specified, or the current namespace if
- * cxtNsPtr was NULL. */
- CONST char **simpleNamePtr; /* Address where procedure stores the
- * simple name at end of the qualName, or
- * NULL if qualName is "::" or the flag
- * FIND_ONLY_NS was specified. */
+TclGetNamespaceForQualName(
+ Tcl_Interp *interp, /* Interpreter in which to find the namespace
+ * containing qualName. */
+ const char *qualName, /* A namespace-qualified name of an command,
+ * variable, or namespace. */
+ Namespace *cxtNsPtr, /* The namespace in which to start the search
+ * for qualName's namespace. If NULL start
+ * from the current namespace. Ignored if
+ * TCL_GLOBAL_ONLY is set. */
+ int flags, /* Flags controlling the search: an OR'd
+ * combination of TCL_GLOBAL_ONLY,
+ * TCL_NAMESPACE_ONLY, TCL_FIND_ONLY_NS, and
+ * TCL_CREATE_NS_IF_UNKNOWN. */
+ Namespace **nsPtrPtr, /* Address where function stores a pointer to
+ * containing namespace if qualName is found
+ * starting from *cxtNsPtr or, if
+ * TCL_GLOBAL_ONLY is set, if qualName is
+ * found in the global :: namespace. NULL is
+ * stored otherwise. */
+ Namespace **altNsPtrPtr, /* Address where function stores a pointer to
+ * containing namespace if qualName is found
+ * starting from the global :: namespace.
+ * NULL is stored if qualName isn't found
+ * starting from :: or if the TCL_GLOBAL_ONLY,
+ * TCL_NAMESPACE_ONLY, TCL_FIND_ONLY_NS,
+ * TCL_CREATE_NS_IF_UNKNOWN flag is set. */
+ Namespace **actualCxtPtrPtr,/* Address where function stores a pointer to
+ * the actual namespace from which the search
+ * started. This is either cxtNsPtr, the ::
+ * namespace if TCL_GLOBAL_ONLY was specified,
+ * or the current namespace if cxtNsPtr was
+ * NULL. */
+ const char **simpleNamePtr) /* Address where function stores the simple
+ * name at end of the qualName, or NULL if
+ * qualName is "::" or the flag
+ * TCL_FIND_ONLY_NS was specified. */
{
Interp *iPtr = (Interp *) interp;
Namespace *nsPtr = cxtNsPtr;
Namespace *altNsPtr;
Namespace *globalNsPtr = iPtr->globalNsPtr;
- CONST char *start, *end;
- CONST char *nsName;
+ const char *start, *end;
+ const char *nsName;
Tcl_HashEntry *entryPtr;
Tcl_DString buffer;
int len;
/*
* Determine the context namespace nsPtr in which to start the primary
- * search. If the qualName name starts with a "::" or TCL_GLOBAL_ONLY
- * was specified, search from the global namespace. Otherwise, use the
+ * search. If the qualName name starts with a "::" or TCL_GLOBAL_ONLY was
+ * specified, search from the global namespace. Otherwise, use the
* namespace given in cxtNsPtr, or if that is NULL, use the current
- * namespace context. Note that we always treat two or more
- * adjacent ":"s as a namespace separator.
+ * namespace context. Note that we always treat two or more adjacent ":"s
+ * as a namespace separator.
*/
if (flags & TCL_GLOBAL_ONLY) {
nsPtr = globalNsPtr;
} else if (nsPtr == NULL) {
- if (iPtr->varFramePtr != NULL) {
- nsPtr = iPtr->varFramePtr->nsPtr;
- } else {
- nsPtr = iPtr->globalNsPtr;
- }
+ nsPtr = iPtr->varFramePtr->nsPtr;
}
- start = qualName; /* pts to start of qualifying namespace */
+ start = qualName; /* Points to start of qualifying
+ * namespace. */
if ((*qualName == ':') && (*(qualName+1) == ':')) {
- start = qualName+2; /* skip over the initial :: */
+ start = qualName+2; /* Skip over the initial :: */
while (*start == ':') {
- start++; /* skip over a subsequent : */
+ start++; /* Skip over a subsequent : */
}
- nsPtr = globalNsPtr;
- if (*start == '\0') { /* qualName is just two or more ":"s */
- *nsPtrPtr = globalNsPtr;
- *altNsPtrPtr = NULL;
+ nsPtr = globalNsPtr;
+ if (*start == '\0') { /* qualName is just two or more
+ * ":"s. */
+ *nsPtrPtr = globalNsPtr;
+ *altNsPtrPtr = NULL;
*actualCxtPtrPtr = globalNsPtr;
- *simpleNamePtr = start; /* points to empty string */
- return TCL_OK;
- }
+ *simpleNamePtr = start; /* Points to empty string. */
+ return TCL_OK;
+ }
}
*actualCxtPtrPtr = nsPtr;
@@ -1736,8 +2112,8 @@ TclGetNamespaceForQualName(interp, qualName, cxtNsPtr, flags,
altNsPtr = globalNsPtr;
if ((nsPtr == globalNsPtr)
- || (flags & (TCL_NAMESPACE_ONLY | FIND_ONLY_NS))) {
- altNsPtr = NULL;
+ || (flags & (TCL_NAMESPACE_ONLY | TCL_FIND_ONLY_NS))) {
+ altNsPtr = NULL;
}
/*
@@ -1747,38 +2123,37 @@ TclGetNamespaceForQualName(interp, qualName, cxtNsPtr, flags,
Tcl_DStringInit(&buffer);
end = start;
while (*start != '\0') {
- /*
- * Find the next namespace qualifier (i.e., a name ending in "::")
- * or the end of the qualified name (i.e., a name ending in "\0").
- * Set len to the number of characters, starting from start,
- * in the name; set end to point after the "::"s or at the "\0".
- */
+ /*
+ * Find the next namespace qualifier (i.e., a name ending in "::") or
+ * the end of the qualified name (i.e., a name ending in "\0"). Set
+ * len to the number of characters, starting from start, in the name;
+ * set end to point after the "::"s or at the "\0".
+ */
len = 0;
- for (end = start; *end != '\0'; end++) {
+ for (end = start; *end != '\0'; end++) {
if ((*end == ':') && (*(end+1) == ':')) {
- end += 2; /* skip over the initial :: */
+ end += 2; /* Skip over the initial :: */
while (*end == ':') {
- end++; /* skip over the subsequent : */
+ end++; /* Skip over the subsequent : */
}
- break; /* exit for loop; end is after ::'s */
+ break; /* Exit for loop; end is after ::'s */
}
- len++;
+ len++;
}
- if ((*end == '\0')
- && !((end-start >= 2) && (*(end-1) == ':') && (*(end-2) == ':'))) {
+ if (*end=='\0' && !(end-start>=2 && *(end-1)==':' && *(end-2)==':')) {
/*
- * qualName ended with a simple name at start. If FIND_ONLY_NS
- * was specified, look this up as a namespace. Otherwise,
- * start is the name of a cmd or var and we are done.
+ * qualName ended with a simple name at start. If TCL_FIND_ONLY_NS
+ * was specified, look this up as a namespace. Otherwise, start is
+ * the name of a cmd or var and we are done.
*/
-
- if (flags & FIND_ONLY_NS) {
+
+ if (flags & TCL_FIND_ONLY_NS) {
nsName = start;
} else {
- *nsPtrPtr = nsPtr;
- *altNsPtrPtr = altNsPtr;
+ *nsPtrPtr = nsPtr;
+ *altNsPtrPtr = altNsPtr;
*simpleNamePtr = start;
Tcl_DStringFree(&buffer);
return TCL_OK;
@@ -1787,69 +2162,70 @@ TclGetNamespaceForQualName(interp, qualName, cxtNsPtr, flags,
/*
* start points to the beginning of a namespace qualifier ending
* in "::". end points to the start of a name in that namespace
- * that might be empty. Copy the namespace qualifier to a
- * buffer so it can be null terminated. We can't modify the
- * incoming qualName since it may be a string constant.
+ * that might be empty. Copy the namespace qualifier to a buffer
+ * so it can be null terminated. We can't modify the incoming
+ * qualName since it may be a string constant.
*/
Tcl_DStringSetLength(&buffer, 0);
- Tcl_DStringAppend(&buffer, start, len);
- nsName = Tcl_DStringValue(&buffer);
- }
+ Tcl_DStringAppend(&buffer, start, len);
+ nsName = Tcl_DStringValue(&buffer);
+ }
- /*
+ /*
* Look up the namespace qualifier nsName in the current namespace
- * context. If it isn't found but CREATE_NS_IF_UNKNOWN is set,
- * create that qualifying namespace. This is needed for procedures
- * like Tcl_CreateCommand that cannot fail.
+ * context. If it isn't found but TCL_CREATE_NS_IF_UNKNOWN is set,
+ * create that qualifying namespace. This is needed for functions like
+ * Tcl_CreateCommand that cannot fail.
+ */
+
+ if (nsPtr != NULL) {
+ entryPtr = Tcl_FindHashEntry(&nsPtr->childTable, nsName);
+ if (entryPtr != NULL) {
+ nsPtr = Tcl_GetHashValue(entryPtr);
+ } else if (flags & TCL_CREATE_NS_IF_UNKNOWN) {
+ Tcl_CallFrame *framePtr;
+
+ (void) TclPushStackFrame(interp, &framePtr,
+ (Tcl_Namespace *) nsPtr, /*isProcCallFrame*/ 0);
+
+ nsPtr = (Namespace *) Tcl_CreateNamespace(interp, nsName,
+ NULL, NULL);
+ TclPopStackFrame(interp);
+
+ if (nsPtr == NULL) {
+ Tcl_Panic("Could not create namespace '%s'", nsName);
+ }
+ } else { /* Namespace not found and was not
+ * created. */
+ nsPtr = NULL;
+ }
+ }
+
+ /*
+ * Look up the namespace qualifier in the alternate search path too.
*/
- if (nsPtr != NULL) {
- entryPtr = Tcl_FindHashEntry(&nsPtr->childTable, nsName);
- if (entryPtr != NULL) {
- nsPtr = (Namespace *) Tcl_GetHashValue(entryPtr);
- } else if (flags & CREATE_NS_IF_UNKNOWN) {
- Tcl_CallFrame frame;
-
- (void) Tcl_PushCallFrame(interp, &frame,
- (Tcl_Namespace *) nsPtr, /*isProcCallFrame*/ 0);
-
- nsPtr = (Namespace *) Tcl_CreateNamespace(interp, nsName,
- (ClientData) NULL, (Tcl_NamespaceDeleteProc *) NULL);
- Tcl_PopCallFrame(interp);
-
- if (nsPtr == NULL) {
- panic("Could not create namespace '%s'", nsName);
- }
- } else { /* namespace not found and wasn't created */
- nsPtr = NULL;
- }
- }
-
- /*
- * Look up the namespace qualifier in the alternate search path too.
- */
-
- if (altNsPtr != NULL) {
- entryPtr = Tcl_FindHashEntry(&altNsPtr->childTable, nsName);
- if (entryPtr != NULL) {
- altNsPtr = (Namespace *) Tcl_GetHashValue(entryPtr);
- } else {
- altNsPtr = NULL;
- }
- }
-
- /*
- * If both search paths have failed, return NULL results.
- */
-
- if ((nsPtr == NULL) && (altNsPtr == NULL)) {
- *nsPtrPtr = NULL;
- *altNsPtrPtr = NULL;
- *simpleNamePtr = NULL;
- Tcl_DStringFree(&buffer);
- return TCL_OK;
- }
+ if (altNsPtr != NULL) {
+ entryPtr = Tcl_FindHashEntry(&altNsPtr->childTable, nsName);
+ if (entryPtr != NULL) {
+ altNsPtr = Tcl_GetHashValue(entryPtr);
+ } else {
+ altNsPtr = NULL;
+ }
+ }
+
+ /*
+ * If both search paths have failed, return NULL results.
+ */
+
+ if ((nsPtr == NULL) && (altNsPtr == NULL)) {
+ *nsPtrPtr = NULL;
+ *altNsPtrPtr = NULL;
+ *simpleNamePtr = NULL;
+ Tcl_DStringFree(&buffer);
+ return TCL_OK;
+ }
start = end;
}
@@ -1859,26 +2235,26 @@ TclGetNamespaceForQualName(interp, qualName, cxtNsPtr, flags,
* variable name, trailing "::"s refer to the cmd or var named {}.
*/
- if ((flags & FIND_ONLY_NS)
- || ((end > start ) && (*(end-1) != ':'))) {
- *simpleNamePtr = NULL; /* found namespace name */
+ if ((flags & TCL_FIND_ONLY_NS) || (end>start && *(end-1)!=':')) {
+ *simpleNamePtr = NULL; /* Found namespace name. */
} else {
- *simpleNamePtr = end; /* found cmd/var: points to empty string */
+ *simpleNamePtr = end; /* Found cmd/var: points to empty
+ * string. */
}
/*
- * As a special case, if we are looking for a namespace and qualName
- * is "" and the current active namespace (nsPtr) is not the global
- * namespace, return NULL (no namespace was found). This is because
- * namespaces can not have empty names except for the global namespace.
+ * As a special case, if we are looking for a namespace and qualName is ""
+ * and the current active namespace (nsPtr) is not the global namespace,
+ * return NULL (no namespace was found). This is because namespaces can
+ * not have empty names except for the global namespace.
*/
- if ((flags & FIND_ONLY_NS) && (*qualName == '\0')
+ if ((flags & TCL_FIND_ONLY_NS) && (*qualName == '\0')
&& (nsPtr != globalNsPtr)) {
nsPtr = NULL;
}
- *nsPtrPtr = nsPtr;
+ *nsPtrPtr = nsPtr;
*altNsPtrPtr = altNsPtr;
Tcl_DStringFree(&buffer);
return TCL_OK;
@@ -1892,9 +2268,9 @@ TclGetNamespaceForQualName(interp, qualName, cxtNsPtr, flags,
* Searches for a namespace.
*
* Results:
- * Returns a pointer to the namespace if it is found. Otherwise,
- * returns NULL and leaves an error message in the interpreter's
- * result object if "flags" contains TCL_LEAVE_ERR_MSG.
+ * Returns a pointer to the namespace if it is found. Otherwise, returns
+ * NULL and leaves an error message in the interpreter's result object if
+ * "flags" contains TCL_LEAVE_ERR_MSG.
*
* Side effects:
* None.
@@ -1903,41 +2279,41 @@ TclGetNamespaceForQualName(interp, qualName, cxtNsPtr, flags,
*/
Tcl_Namespace *
-Tcl_FindNamespace(interp, name, contextNsPtr, flags)
- Tcl_Interp *interp; /* The interpreter in which to find the
- * namespace. */
- CONST char *name; /* Namespace name. If it starts with "::",
- * will be looked up in global namespace.
- * Else, looked up first in contextNsPtr
- * (current namespace if contextNsPtr is
- * NULL), then in global namespace. */
- Tcl_Namespace *contextNsPtr; /* Ignored if TCL_GLOBAL_ONLY flag is set
- * or if the name starts with "::".
- * Otherwise, points to namespace in which
- * to resolve name; if NULL, look up name
- * in the current namespace. */
- register int flags; /* Flags controlling namespace lookup: an
- * OR'd combination of TCL_GLOBAL_ONLY and
- * TCL_LEAVE_ERR_MSG flags. */
+Tcl_FindNamespace(
+ Tcl_Interp *interp, /* The interpreter in which to find the
+ * namespace. */
+ const char *name, /* Namespace name. If it starts with "::",
+ * will be looked up in global namespace.
+ * Else, looked up first in contextNsPtr
+ * (current namespace if contextNsPtr is
+ * NULL), then in global namespace. */
+ Tcl_Namespace *contextNsPtr,/* Ignored if TCL_GLOBAL_ONLY flag is set or
+ * if the name starts with "::". Otherwise,
+ * points to namespace in which to resolve
+ * name; if NULL, look up name in the current
+ * namespace. */
+ register int flags) /* Flags controlling namespace lookup: an OR'd
+ * combination of TCL_GLOBAL_ONLY and
+ * TCL_LEAVE_ERR_MSG flags. */
{
Namespace *nsPtr, *dummy1Ptr, *dummy2Ptr;
- CONST char *dummy;
+ const char *dummy;
/*
- * Find the namespace(s) that contain the specified namespace name.
- * Add the FIND_ONLY_NS flag to resolve the name all the way down
- * to its last component, a namespace.
+ * Find the namespace(s) that contain the specified namespace name. Add
+ * the TCL_FIND_ONLY_NS flag to resolve the name all the way down to its
+ * last component, a namespace.
*/
TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr,
- (flags | FIND_ONLY_NS), &nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy);
-
+ flags|TCL_FIND_ONLY_NS, &nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy);
+
if (nsPtr != NULL) {
- return (Tcl_Namespace *) nsPtr;
+ return (Tcl_Namespace *) nsPtr;
} else if (flags & TCL_LEAVE_ERR_MSG) {
Tcl_ResetResult(interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "unknown namespace \"", name, "\"", (char *) NULL);
+ Tcl_AppendResult(interp, "unknown namespace \"", name, "\"", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", name, NULL);
}
return NULL;
}
@@ -1950,10 +2326,10 @@ Tcl_FindNamespace(interp, name, contextNsPtr, flags)
* Searches for a command.
*
* Results:
- * Returns a token for the command if it is found. Otherwise, if it
- * can't be found or there is an error, returns NULL and leaves an
- * error message in the interpreter's result object if "flags"
- * contains TCL_LEAVE_ERR_MSG.
+ * Returns a token for the command if it is found. Otherwise, if it can't
+ * be found or there is an error, returns NULL and leaves an error
+ * message in the interpreter's result object if "flags" contains
+ * TCL_LEAVE_ERR_MSG.
*
* Side effects:
* None.
@@ -1962,244 +2338,171 @@ Tcl_FindNamespace(interp, name, contextNsPtr, flags)
*/
Tcl_Command
-Tcl_FindCommand(interp, name, contextNsPtr, flags)
- Tcl_Interp *interp; /* The interpreter in which to find the
- * command and to report errors. */
- CONST char *name; /* Command's name. If it starts with "::",
- * will be looked up in global namespace.
- * Else, looked up first in contextNsPtr
- * (current namespace if contextNsPtr is
- * NULL), then in global namespace. */
- Tcl_Namespace *contextNsPtr; /* Ignored if TCL_GLOBAL_ONLY flag set.
- * Otherwise, points to namespace in which
- * to resolve name. If NULL, look up name
- * in the current namespace. */
- int flags; /* An OR'd combination of flags:
- * TCL_GLOBAL_ONLY (look up name only in
- * global namespace), TCL_NAMESPACE_ONLY
- * (look up only in contextNsPtr, or the
- * current namespace if contextNsPtr is
- * NULL), and TCL_LEAVE_ERR_MSG. If both
- * TCL_GLOBAL_ONLY and TCL_NAMESPACE_ONLY
- * are given, TCL_GLOBAL_ONLY is
- * ignored. */
-{
- Interp *iPtr = (Interp*)interp;
-
- ResolverScheme *resPtr;
- Namespace *nsPtr[2], *cxtNsPtr;
- CONST char *simpleName;
+Tcl_FindCommand(
+ Tcl_Interp *interp, /* The interpreter in which to find the
+ * command and to report errors. */
+ const char *name, /* Command's name. If it starts with "::",
+ * will be looked up in global namespace.
+ * Else, looked up first in contextNsPtr
+ * (current namespace if contextNsPtr is
+ * NULL), then in global namespace. */
+ Tcl_Namespace *contextNsPtr,/* Ignored if TCL_GLOBAL_ONLY flag set.
+ * Otherwise, points to namespace in which to
+ * resolve name. If NULL, look up name in the
+ * current namespace. */
+ int flags) /* An OR'd combination of flags:
+ * TCL_GLOBAL_ONLY (look up name only in
+ * global namespace), TCL_NAMESPACE_ONLY (look
+ * up only in contextNsPtr, or the current
+ * namespace if contextNsPtr is NULL), and
+ * TCL_LEAVE_ERR_MSG. If both TCL_GLOBAL_ONLY
+ * and TCL_NAMESPACE_ONLY are given,
+ * TCL_GLOBAL_ONLY is ignored. */
+{
+ Interp *iPtr = (Interp *) interp;
+ Namespace *cxtNsPtr;
register Tcl_HashEntry *entryPtr;
register Command *cmdPtr;
- register int search;
+ const char *simpleName;
int result;
- Tcl_Command cmd;
/*
- * If this namespace has a command resolver, then give it first
- * crack at the command resolution. If the interpreter has any
- * command resolvers, consult them next. The command resolver
- * procedures may return a Tcl_Command value, they may signal
- * to continue onward, or they may signal an error.
+ * If this namespace has a command resolver, then give it first crack at
+ * the command resolution. If the interpreter has any command resolvers,
+ * consult them next. The command resolver functions may return a
+ * Tcl_Command value, they may signal to continue onward, or they may
+ * signal an error.
*/
- if ((flags & TCL_GLOBAL_ONLY) != 0) {
- cxtNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
- }
- else if (contextNsPtr != NULL) {
- cxtNsPtr = (Namespace *) contextNsPtr;
- }
- else {
- cxtNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+
+ if ((flags & TCL_GLOBAL_ONLY) || !strncmp(name, "::", 2)) {
+ cxtNsPtr = (Namespace *) TclGetGlobalNamespace(interp);
+ } else if (contextNsPtr != NULL) {
+ cxtNsPtr = (Namespace *) contextNsPtr;
+ } else {
+ cxtNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
}
if (cxtNsPtr->cmdResProc != NULL || iPtr->resolverPtr != NULL) {
- resPtr = iPtr->resolverPtr;
+ ResolverScheme *resPtr = iPtr->resolverPtr;
+ Tcl_Command cmd;
- if (cxtNsPtr->cmdResProc) {
- result = (*cxtNsPtr->cmdResProc)(interp, name,
- (Tcl_Namespace *) cxtNsPtr, flags, &cmd);
- } else {
- result = TCL_CONTINUE;
- }
+ if (cxtNsPtr->cmdResProc) {
+ result = (*cxtNsPtr->cmdResProc)(interp, name,
+ (Tcl_Namespace *) cxtNsPtr, flags, &cmd);
+ } else {
+ result = TCL_CONTINUE;
+ }
- while (result == TCL_CONTINUE && resPtr) {
- if (resPtr->cmdResProc) {
- result = (*resPtr->cmdResProc)(interp, name,
- (Tcl_Namespace *) cxtNsPtr, flags, &cmd);
- }
- resPtr = resPtr->nextPtr;
- }
+ while (result == TCL_CONTINUE && resPtr) {
+ if (resPtr->cmdResProc) {
+ result = (*resPtr->cmdResProc)(interp, name,
+ (Tcl_Namespace *) cxtNsPtr, flags, &cmd);
+ }
+ resPtr = resPtr->nextPtr;
+ }
- if (result == TCL_OK) {
- return cmd;
- }
- else if (result != TCL_CONTINUE) {
- return (Tcl_Command) NULL;
- }
+ if (result == TCL_OK) {
+ return cmd;
+ } else if (result != TCL_CONTINUE) {
+ return NULL;
+ }
}
/*
* Find the namespace(s) that contain the command.
*/
- TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr,
- flags, &nsPtr[0], &nsPtr[1], &cxtNsPtr, &simpleName);
-
- /*
- * Look for the command in the command table of its namespace.
- * Be sure to check both possible search paths: from the specified
- * namespace context and from the global namespace.
- */
-
cmdPtr = NULL;
- for (search = 0; (search < 2) && (cmdPtr == NULL); search++) {
- if ((nsPtr[search] != NULL) && (simpleName != NULL)) {
- entryPtr = Tcl_FindHashEntry(&nsPtr[search]->cmdTable,
- simpleName);
- if (entryPtr != NULL) {
- cmdPtr = (Command *) Tcl_GetHashValue(entryPtr);
+ if (cxtNsPtr->commandPathLength!=0 && strncmp(name, "::", 2)
+ && !(flags & TCL_NAMESPACE_ONLY)) {
+ int i;
+ Namespace *pathNsPtr, *realNsPtr, *dummyNsPtr;
+
+ (void) TclGetNamespaceForQualName(interp, name, cxtNsPtr,
+ TCL_NAMESPACE_ONLY, &realNsPtr, &dummyNsPtr, &dummyNsPtr,
+ &simpleName);
+ if ((realNsPtr != NULL) && (simpleName != NULL)) {
+ if ((cxtNsPtr == realNsPtr)
+ || !(realNsPtr->flags & NS_DYING)) {
+ entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
+ if (entryPtr != NULL) {
+ cmdPtr = Tcl_GetHashValue(entryPtr);
+ }
}
}
- }
-
- if (cmdPtr != NULL) {
- return (Tcl_Command) cmdPtr;
- } else if (flags & TCL_LEAVE_ERR_MSG) {
- Tcl_ResetResult(interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "unknown command \"", name, "\"", (char *) NULL);
- }
- return (Tcl_Command) NULL;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_FindNamespaceVar --
- *
- * Searches for a namespace variable, a variable not local to a
- * procedure. The variable can be either a scalar or an array, but
- * may not be an element of an array.
- *
- * Results:
- * Returns a token for the variable if it is found. Otherwise, if it
- * can't be found or there is an error, returns NULL and leaves an
- * error message in the interpreter's result object if "flags"
- * contains TCL_LEAVE_ERR_MSG.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
+ /*
+ * Next, check along the path.
+ */
-Tcl_Var
-Tcl_FindNamespaceVar(interp, name, contextNsPtr, flags)
- Tcl_Interp *interp; /* The interpreter in which to find the
- * variable. */
- CONST char *name; /* Variable's name. If it starts with "::",
- * will be looked up in global namespace.
- * Else, looked up first in contextNsPtr
- * (current namespace if contextNsPtr is
- * NULL), then in global namespace. */
- Tcl_Namespace *contextNsPtr; /* Ignored if TCL_GLOBAL_ONLY flag set.
- * Otherwise, points to namespace in which
- * to resolve name. If NULL, look up name
- * in the current namespace. */
- int flags; /* An OR'd combination of flags:
- * TCL_GLOBAL_ONLY (look up name only in
- * global namespace), TCL_NAMESPACE_ONLY
- * (look up only in contextNsPtr, or the
- * current namespace if contextNsPtr is
- * NULL), and TCL_LEAVE_ERR_MSG. If both
- * TCL_GLOBAL_ONLY and TCL_NAMESPACE_ONLY
- * are given, TCL_GLOBAL_ONLY is
- * ignored. */
-{
- Interp *iPtr = (Interp*)interp;
- ResolverScheme *resPtr;
- Namespace *nsPtr[2], *cxtNsPtr;
- CONST char *simpleName;
- Tcl_HashEntry *entryPtr;
- Var *varPtr;
- register int search;
- int result;
- Tcl_Var var;
+ for (i=0 ; i<cxtNsPtr->commandPathLength && cmdPtr==NULL ; i++) {
+ pathNsPtr = cxtNsPtr->commandPathArray[i].nsPtr;
+ if (pathNsPtr == NULL) {
+ continue;
+ }
+ (void) TclGetNamespaceForQualName(interp, name, pathNsPtr,
+ TCL_NAMESPACE_ONLY, &realNsPtr, &dummyNsPtr, &dummyNsPtr,
+ &simpleName);
+ if ((realNsPtr != NULL) && (simpleName != NULL)
+ && !(realNsPtr->flags & NS_DYING)) {
+ entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
+ if (entryPtr != NULL) {
+ cmdPtr = Tcl_GetHashValue(entryPtr);
+ }
+ }
+ }
- /*
- * If this namespace has a variable resolver, then give it first
- * crack at the variable resolution. It may return a Tcl_Var
- * value, it may signal to continue onward, or it may signal
- * an error.
- */
- if ((flags & TCL_GLOBAL_ONLY) != 0) {
- cxtNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
- }
- else if (contextNsPtr != NULL) {
- cxtNsPtr = (Namespace *) contextNsPtr;
- }
- else {
- cxtNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
- }
+ /*
+ * If we've still not found the command, look in the global namespace
+ * as a last resort.
+ */
- if (cxtNsPtr->varResProc != NULL || iPtr->resolverPtr != NULL) {
- resPtr = iPtr->resolverPtr;
+ if (cmdPtr == NULL) {
+ (void) TclGetNamespaceForQualName(interp, name, NULL,
+ TCL_GLOBAL_ONLY, &realNsPtr, &dummyNsPtr, &dummyNsPtr,
+ &simpleName);
+ if ((realNsPtr != NULL) && (simpleName != NULL)
+ && !(realNsPtr->flags & NS_DYING)) {
+ entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
+ if (entryPtr != NULL) {
+ cmdPtr = Tcl_GetHashValue(entryPtr);
+ }
+ }
+ }
+ } else {
+ Namespace *nsPtr[2];
+ register int search;
- if (cxtNsPtr->varResProc) {
- result = (*cxtNsPtr->varResProc)(interp, name,
- (Tcl_Namespace *) cxtNsPtr, flags, &var);
- } else {
- result = TCL_CONTINUE;
- }
+ TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr,
+ flags, &nsPtr[0], &nsPtr[1], &cxtNsPtr, &simpleName);
- while (result == TCL_CONTINUE && resPtr) {
- if (resPtr->varResProc) {
- result = (*resPtr->varResProc)(interp, name,
- (Tcl_Namespace *) cxtNsPtr, flags, &var);
- }
- resPtr = resPtr->nextPtr;
- }
+ /*
+ * Look for the command in the command table of its namespace. Be sure
+ * to check both possible search paths: from the specified namespace
+ * context and from the global namespace.
+ */
- if (result == TCL_OK) {
- return var;
- }
- else if (result != TCL_CONTINUE) {
- return (Tcl_Var) NULL;
- }
+ for (search = 0; (search < 2) && (cmdPtr == NULL); search++) {
+ if ((nsPtr[search] != NULL) && (simpleName != NULL)) {
+ entryPtr = Tcl_FindHashEntry(&nsPtr[search]->cmdTable,
+ simpleName);
+ if (entryPtr != NULL) {
+ cmdPtr = Tcl_GetHashValue(entryPtr);
+ }
+ }
+ }
}
- /*
- * Find the namespace(s) that contain the variable.
- */
-
- TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr,
- flags, &nsPtr[0], &nsPtr[1], &cxtNsPtr, &simpleName);
-
- /*
- * Look for the variable in the variable table of its namespace.
- * Be sure to check both possible search paths: from the specified
- * namespace context and from the global namespace.
- */
-
- varPtr = NULL;
- for (search = 0; (search < 2) && (varPtr == NULL); search++) {
- if ((nsPtr[search] != NULL) && (simpleName != NULL)) {
- entryPtr = Tcl_FindHashEntry(&nsPtr[search]->varTable,
- simpleName);
- if (entryPtr != NULL) {
- varPtr = (Var *) Tcl_GetHashValue(entryPtr);
- }
- }
+ if (cmdPtr != NULL) {
+ return (Tcl_Command) cmdPtr;
}
- if (varPtr != NULL) {
- return (Tcl_Var) varPtr;
- } else if (flags & TCL_LEAVE_ERR_MSG) {
+
+ if (flags & TCL_LEAVE_ERR_MSG) {
Tcl_ResetResult(interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "unknown variable \"", name, "\"", (char *) NULL);
+ Tcl_AppendResult(interp, "unknown command \"", name, "\"", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", name, NULL);
}
- return (Tcl_Var) NULL;
+ return NULL;
}
/*
@@ -2211,56 +2514,49 @@ Tcl_FindNamespaceVar(interp, name, contextNsPtr, flags)
* command references that the new command may invalidate. Consider the
* following cases that could happen when you add a command "foo" to a
* namespace "b":
- * 1. It could shadow a command named "foo" at the global scope.
- * If it does, all command references in the namespace "b" are
+ * 1. It could shadow a command named "foo" at the global scope. If
+ * it does, all command references in the namespace "b" are
* suspect.
- * 2. Suppose the namespace "b" resides in a namespace "a".
- * Then to "a" the new command "b::foo" could shadow another
- * command "b::foo" in the global namespace. If so, then all
- * command references in "a" are suspect.
- * The same checks are applied to all parent namespaces, until we
- * reach the global :: namespace.
+ * 2. Suppose the namespace "b" resides in a namespace "a". Then to
+ * "a" the new command "b::foo" could shadow another command
+ * "b::foo" in the global namespace. If so, then all command
+ * references in "a" * are suspect.
+ * The same checks are applied to all parent namespaces, until we reach
+ * the global :: namespace.
*
* Results:
* None.
*
* Side effects:
* If the new command shadows an existing command, the cmdRefEpoch
- * counter is incremented in each namespace that sees the shadow.
- * This invalidates all command references that were previously cached
- * in that namespace. The next time the commands are used, they are
- * resolved from scratch.
+ * counter is incremented in each namespace that sees the shadow. This
+ * invalidates all command references that were previously cached in that
+ * namespace. The next time the commands are used, they are resolved from
+ * scratch.
*
*----------------------------------------------------------------------
*/
void
-TclResetShadowedCmdRefs(interp, newCmdPtr)
- Tcl_Interp *interp; /* Interpreter containing the new command. */
- Command *newCmdPtr; /* Points to the new command. */
+TclResetShadowedCmdRefs(
+ Tcl_Interp *interp, /* Interpreter containing the new command. */
+ Command *newCmdPtr) /* Points to the new command. */
{
char *cmdName;
Tcl_HashEntry *hPtr;
register Namespace *nsPtr;
Namespace *trailNsPtr, *shadowNsPtr;
- Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
+ Namespace *globalNsPtr = (Namespace *) TclGetGlobalNamespace(interp);
int found, i;
-
- /*
- * This procedure generates an array used to hold the trail list. This
- * starts out with stack-allocated space but uses dynamically-allocated
- * storage if needed.
- */
-
- Namespace *(trailStorage[NUM_TRAIL_ELEMS]);
- Namespace **trailPtr = trailStorage;
int trailFront = -1;
- int trailSize = NUM_TRAIL_ELEMS;
+ int trailSize = 5; /* Formerly NUM_TRAIL_ELEMS. */
+ Namespace **trailPtr = (Namespace **)
+ TclStackAlloc(interp, trailSize * sizeof(Namespace *));
/*
- * Start at the namespace containing the new command, and work up
- * through the list of parents. Stop just before the global namespace,
- * since the global namespace can't "shadow" its own entries.
+ * Start at the namespace containing the new command, and work up through
+ * the list of parents. Stop just before the global namespace, since the
+ * global namespace can't "shadow" its own entries.
*
* The namespace "trail" list we build consists of the names of each
* namespace that encloses the new command, in order from outermost to
@@ -2268,200 +2564,164 @@ TclResetShadowedCmdRefs(interp, newCmdPtr)
* eventually extends the trail upwards by one namespace, nsPtr. We use
* this trail list to see if nsPtr (e.g. "a" in 2. above) could have
* now-invalid cached command references. This will happen if nsPtr
- * (e.g. "a") contains a sequence of child namespaces (e.g. "b")
- * such that there is a identically-named sequence of child namespaces
- * starting from :: (e.g. "::b") whose tail namespace contains a command
- * also named cmdName.
+ * (e.g. "a") contains a sequence of child namespaces (e.g. "b") such that
+ * there is a identically-named sequence of child namespaces starting from
+ * :: (e.g. "::b") whose tail namespace contains a command also named
+ * cmdName.
*/
cmdName = Tcl_GetHashKey(newCmdPtr->hPtr->tablePtr, newCmdPtr->hPtr);
- for (nsPtr = newCmdPtr->nsPtr;
- (nsPtr != NULL) && (nsPtr != globalNsPtr);
- nsPtr = nsPtr->parentPtr) {
- /*
+ for (nsPtr=newCmdPtr->nsPtr ; (nsPtr!=NULL) && (nsPtr!=globalNsPtr) ;
+ nsPtr=nsPtr->parentPtr) {
+ /*
* Find the maximal sequence of child namespaces contained in nsPtr
- * such that there is a identically-named sequence of child
- * namespaces starting from ::. shadowNsPtr will be the tail of this
- * sequence, or the deepest namespace under :: that might contain a
- * command now shadowed by cmdName. We check below if shadowNsPtr
- * actually contains a command cmdName.
+ * such that there is a identically-named sequence of child namespaces
+ * starting from ::. shadowNsPtr will be the tail of this sequence, or
+ * the deepest namespace under :: that might contain a command now
+ * shadowed by cmdName. We check below if shadowNsPtr actually
+ * contains a command cmdName.
*/
- found = 1;
- shadowNsPtr = globalNsPtr;
+ found = 1;
+ shadowNsPtr = globalNsPtr;
- for (i = trailFront; i >= 0; i--) {
- trailNsPtr = trailPtr[i];
- hPtr = Tcl_FindHashEntry(&shadowNsPtr->childTable,
+ for (i = trailFront; i >= 0; i--) {
+ trailNsPtr = trailPtr[i];
+ hPtr = Tcl_FindHashEntry(&shadowNsPtr->childTable,
trailNsPtr->name);
- if (hPtr != NULL) {
- shadowNsPtr = (Namespace *) Tcl_GetHashValue(hPtr);
- } else {
- found = 0;
- break;
- }
- }
-
- /*
- * If shadowNsPtr contains a command named cmdName, we invalidate
- * all of the command refs cached in nsPtr. As a boundary case,
+ if (hPtr != NULL) {
+ shadowNsPtr = Tcl_GetHashValue(hPtr);
+ } else {
+ found = 0;
+ break;
+ }
+ }
+
+ /*
+ * If shadowNsPtr contains a command named cmdName, we invalidate all
+ * of the command refs cached in nsPtr. As a boundary case,
* shadowNsPtr is initially :: and we check for case 1. above.
*/
- if (found) {
- hPtr = Tcl_FindHashEntry(&shadowNsPtr->cmdTable, cmdName);
- if (hPtr != NULL) {
- nsPtr->cmdRefEpoch++;
+ if (found) {
+ hPtr = Tcl_FindHashEntry(&shadowNsPtr->cmdTable, cmdName);
+ if (hPtr != NULL) {
+ nsPtr->cmdRefEpoch++;
+ TclInvalidateNsPath(nsPtr);
- /*
+ /*
* If the shadowed command was compiled to bytecodes, we
* invalidate all the bytecodes in nsPtr, to force a new
* compilation. We use the resolverEpoch to signal the need
* for a fresh compilation of every bytecode.
*/
- if ((((Command *) Tcl_GetHashValue(hPtr))->compileProc) != NULL) {
+ if (((Command *)Tcl_GetHashValue(hPtr))->compileProc != NULL) {
nsPtr->resolverEpoch++;
}
- }
- }
+ }
+ }
- /*
- * Insert nsPtr at the front of the trail list: i.e., at the end
- * of the trailPtr array.
+ /*
+ * Insert nsPtr at the front of the trail list: i.e., at the end of
+ * the trailPtr array.
*/
trailFront++;
if (trailFront == trailSize) {
- size_t currBytes = trailSize * sizeof(Namespace *);
- int newSize = 2*trailSize;
- size_t newBytes = newSize * sizeof(Namespace *);
- Namespace **newPtr =
- (Namespace **) ckalloc((unsigned) newBytes);
-
- memcpy((VOID *) newPtr, (VOID *) trailPtr, currBytes);
- if (trailPtr != trailStorage) {
- ckfree((char *) trailPtr);
- }
- trailPtr = newPtr;
+ int newSize = 2 * trailSize;
+ trailPtr = (Namespace **) TclStackRealloc(interp,
+ trailPtr, newSize * sizeof(Namespace *));
trailSize = newSize;
}
trailPtr[trailFront] = nsPtr;
}
-
- /*
- * Free any allocated storage.
- */
-
- if (trailPtr != trailStorage) {
- ckfree((char *) trailPtr);
- }
+ TclStackFree(interp, trailPtr);
}
/*
*----------------------------------------------------------------------
*
- * GetNamespaceFromObj --
+ * TclGetNamespaceFromObj, GetNamespaceFromObj --
*
* Gets the namespace specified by the name in a Tcl_Obj.
*
* Results:
- * Returns TCL_OK if the namespace was resolved successfully, and
- * stores a pointer to the namespace in the location specified by
- * nsPtrPtr. If the namespace can't be found, the procedure stores
- * NULL in *nsPtrPtr and returns TCL_OK. If anything else goes wrong,
- * this procedure returns TCL_ERROR.
+ * Returns TCL_OK if the namespace was resolved successfully, and stores
+ * a pointer to the namespace in the location specified by nsPtrPtr. If
+ * the namespace can't be found, or anything else goes wrong, this
+ * function returns TCL_ERROR and writes an error message to interp,
+ * if non-NULL.
*
* Side effects:
* May update the internal representation for the object, caching the
- * namespace reference. The next time this procedure is called, the
+ * namespace reference. The next time this function is called, the
* namespace value can be found quickly.
*
- * If anything goes wrong, an error message is left in the
- * interpreter's result object.
- *
*----------------------------------------------------------------------
*/
-static int
-GetNamespaceFromObj(interp, objPtr, nsPtrPtr)
- Tcl_Interp *interp; /* The current interpreter. */
- Tcl_Obj *objPtr; /* The object to be resolved as the name
- * of a namespace. */
- Tcl_Namespace **nsPtrPtr; /* Result namespace pointer goes here. */
+int
+TclGetNamespaceFromObj(
+ Tcl_Interp *interp, /* The current interpreter. */
+ Tcl_Obj *objPtr, /* The object to be resolved as the name of a
+ * namespace. */
+ Tcl_Namespace **nsPtrPtr) /* Result namespace pointer goes here. */
{
- Interp *iPtr = (Interp *) interp;
- register ResolvedNsName *resNamePtr;
- register Namespace *nsPtr;
- Namespace *currNsPtr;
- CallFrame *savedFramePtr;
- int result = TCL_OK;
- char *name;
+ if (GetNamespaceFromObj(interp, objPtr, nsPtrPtr) == TCL_ERROR) {
+ const char *name = TclGetString(objPtr);
- /*
- * If the namespace name is fully qualified, do as if the lookup were
- * done from the global namespace; this helps avoid repeated lookups
- * of fully qualified names.
- */
+ if ((name[0] == ':') && (name[1] == ':')) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "namespace \"%s\" not found", name));
+ } else {
+ /*
+ * Get the current namespace name.
+ */
- savedFramePtr = iPtr->varFramePtr;
- name = Tcl_GetString(objPtr);
- if ((*name++ == ':') && (*name == ':')) {
- iPtr->varFramePtr = NULL;
+ NamespaceCurrentCmd(NULL, interp, 2, NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "namespace \"%s\" not found in \"%s\"", name,
+ Tcl_GetStringResult(interp)));
+ }
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", name, NULL);
+ return TCL_ERROR;
}
+ return TCL_OK;
+}
- currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
-
- /*
- * Get the internal representation, converting to a namespace type if
- * needed. The internal representation is a ResolvedNsName that points
- * to the actual namespace.
- */
-
- if (objPtr->typePtr != &tclNsNameType) {
- result = tclNsNameType.setFromAnyProc(interp, objPtr);
- if (result != TCL_OK) {
- goto done;
- }
- }
- resNamePtr = (ResolvedNsName *) objPtr->internalRep.otherValuePtr;
+static int
+GetNamespaceFromObj(
+ Tcl_Interp *interp, /* The current interpreter. */
+ Tcl_Obj *objPtr, /* The object to be resolved as the name of a
+ * namespace. */
+ Tcl_Namespace **nsPtrPtr) /* Result namespace pointer goes here. */
+{
+ ResolvedNsName *resNamePtr;
+ Namespace *nsPtr, *refNsPtr;
- /*
- * Check the context namespace of the resolved symbol to make sure that
- * it is fresh. If not, then force another conversion to the namespace
- * type, to discard the old rep and create a new one. Note that we
- * verify that the namespace id of the cached namespace is the same as
- * the id when we cached it; this insures that the namespace wasn't
- * deleted and a new one created at the same address.
- */
+ if (objPtr->typePtr == &nsNameType) {
+ /*
+ * Check that the ResolvedNsName is still valid; avoid letting the ref
+ * cross interps.
+ */
- nsPtr = NULL;
- if ((resNamePtr != NULL)
- && (resNamePtr->refNsPtr == currNsPtr)
- && (resNamePtr->nsId == resNamePtr->nsPtr->nsId)) {
- nsPtr = resNamePtr->nsPtr;
- if (nsPtr->flags & NS_DEAD) {
- nsPtr = NULL;
- }
- }
- if (nsPtr == NULL) { /* try again */
- result = tclNsNameType.setFromAnyProc(interp, objPtr);
- if (result != TCL_OK) {
- goto done;
- }
- resNamePtr = (ResolvedNsName *) objPtr->internalRep.otherValuePtr;
- if (resNamePtr != NULL) {
- nsPtr = resNamePtr->nsPtr;
- if (nsPtr->flags & NS_DEAD) {
- nsPtr = NULL;
- }
- }
- }
- *nsPtrPtr = (Tcl_Namespace *) nsPtr;
-
- done:
- iPtr->varFramePtr = savedFramePtr;
- return result;
+ resNamePtr = (ResolvedNsName *) objPtr->internalRep.twoPtrValue.ptr1;
+ nsPtr = resNamePtr->nsPtr;
+ refNsPtr = resNamePtr->refNsPtr;
+ if (!(nsPtr->flags & NS_DYING) && (interp == nsPtr->interp) &&
+ (!refNsPtr || ((interp == refNsPtr->interp) &&
+ (refNsPtr== (Namespace *) Tcl_GetCurrentNamespace(interp))))) {
+ *nsPtrPtr = (Tcl_Namespace *) nsPtr;
+ return TCL_OK;
+ }
+ }
+ if (SetNsNameFromAny(interp, objPtr) == TCL_OK) {
+ resNamePtr = (ResolvedNsName *) objPtr->internalRep.twoPtrValue.ptr1;
+ *nsPtrPtr = (Tcl_Namespace *) resNamePtr->nsPtr;
+ return TCL_OK;
+ }
+ return TCL_ERROR;
}
/*
@@ -2469,13 +2729,14 @@ GetNamespaceFromObj(interp, objPtr, nsPtrPtr)
*
* Tcl_NamespaceObjCmd --
*
- * Invoked to implement the "namespace" command that creates, deletes,
- * or manipulates Tcl namespaces. Handles the following syntax:
+ * Invoked to implement the "namespace" command that creates, deletes, or
+ * manipulates Tcl namespaces. Handles the following syntax:
*
* namespace children ?name? ?pattern?
* namespace code arg
* namespace current
* namespace delete ?name name...?
+ * namespace ensemble subcommand ?arg...?
* namespace eval name arg ?arg...?
* namespace exists name
* namespace export ?-clear? ?pattern pattern...?
@@ -2493,41 +2754,40 @@ GetNamespaceFromObj(interp, objPtr, nsPtrPtr)
* anything goes wrong.
*
* Side effects:
- * Based on the subcommand name (e.g., "import"), this procedure
- * dispatches to a corresponding procedure NamespaceXXXCmd defined
- * statically in this file. This procedure's side effects depend on
- * whatever that subcommand procedure does. If there is an error, this
- * procedure returns an error message in the interpreter's result
- * object. Otherwise it may return a result in the interpreter's result
- * object.
+ * Based on the subcommand name (e.g., "import"), this function
+ * dispatches to a corresponding function NamespaceXXXCmd defined
+ * statically in this file. This function's side effects depend on
+ * whatever that subcommand function does. If there is an error, this
+ * function returns an error message in the interpreter's result object.
+ * Otherwise it may return a result in the interpreter's result object.
*
*----------------------------------------------------------------------
*/
int
-Tcl_NamespaceObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Arbitrary value passed to cmd. */
- Tcl_Interp *interp; /* Current interpreter. */
- register int objc; /* Number of arguments. */
- register Tcl_Obj *CONST objv[]; /* Argument objects. */
-{
- static CONST char *subCmds[] = {
- "children", "code", "current", "delete",
+Tcl_NamespaceObjCmd(
+ ClientData clientData, /* Arbitrary value passed to cmd. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ static const char *subCmds[] = {
+ "children", "code", "current", "delete", "ensemble",
"eval", "exists", "export", "forget", "import",
- "inscope", "origin", "parent", "qualifiers",
- "tail", "which", (char *) NULL
+ "inscope", "origin", "parent", "path", "qualifiers",
+ "tail", "unknown", "upvar", "which", NULL
};
enum NSSubCmdIdx {
- NSChildrenIdx, NSCodeIdx, NSCurrentIdx, NSDeleteIdx,
+ NSChildrenIdx, NSCodeIdx, NSCurrentIdx, NSDeleteIdx, NSEnsembleIdx,
NSEvalIdx, NSExistsIdx, NSExportIdx, NSForgetIdx, NSImportIdx,
- NSInscopeIdx, NSOriginIdx, NSParentIdx, NSQualifiersIdx,
- NSTailIdx, NSWhichIdx
+ NSInscopeIdx, NSOriginIdx, NSParentIdx, NSPathIdx, NSQualifiersIdx,
+ NSTailIdx, NSUnknownIdx, NSUpvarIdx, NSWhichIdx
};
int index, result;
if (objc < 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?arg ...?");
- return TCL_ERROR;
+ Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?arg ...?");
+ return TCL_ERROR;
}
/*
@@ -2539,53 +2799,65 @@ Tcl_NamespaceObjCmd(clientData, interp, objc, objv)
if (result != TCL_OK) {
return result;
}
-
+
switch (index) {
- case NSChildrenIdx:
- result = NamespaceChildrenCmd(clientData, interp, objc, objv);
- break;
- case NSCodeIdx:
- result = NamespaceCodeCmd(clientData, interp, objc, objv);
- break;
- case NSCurrentIdx:
- result = NamespaceCurrentCmd(clientData, interp, objc, objv);
- break;
- case NSDeleteIdx:
- result = NamespaceDeleteCmd(clientData, interp, objc, objv);
- break;
- case NSEvalIdx:
- result = NamespaceEvalCmd(clientData, interp, objc, objv);
- break;
- case NSExistsIdx:
- result = NamespaceExistsCmd(clientData, interp, objc, objv);
- break;
- case NSExportIdx:
- result = NamespaceExportCmd(clientData, interp, objc, objv);
- break;
- case NSForgetIdx:
- result = NamespaceForgetCmd(clientData, interp, objc, objv);
- break;
- case NSImportIdx:
- result = NamespaceImportCmd(clientData, interp, objc, objv);
- break;
- case NSInscopeIdx:
- result = NamespaceInscopeCmd(clientData, interp, objc, objv);
- break;
- case NSOriginIdx:
- result = NamespaceOriginCmd(clientData, interp, objc, objv);
- break;
- case NSParentIdx:
- result = NamespaceParentCmd(clientData, interp, objc, objv);
- break;
- case NSQualifiersIdx:
- result = NamespaceQualifiersCmd(clientData, interp, objc, objv);
- break;
- case NSTailIdx:
- result = NamespaceTailCmd(clientData, interp, objc, objv);
- break;
- case NSWhichIdx:
- result = NamespaceWhichCmd(clientData, interp, objc, objv);
- break;
+ case NSChildrenIdx:
+ result = NamespaceChildrenCmd(clientData, interp, objc, objv);
+ break;
+ case NSCodeIdx:
+ result = NamespaceCodeCmd(clientData, interp, objc, objv);
+ break;
+ case NSCurrentIdx:
+ result = NamespaceCurrentCmd(clientData, interp, objc, objv);
+ break;
+ case NSDeleteIdx:
+ result = NamespaceDeleteCmd(clientData, interp, objc, objv);
+ break;
+ case NSEnsembleIdx:
+ result = NamespaceEnsembleCmd(clientData, interp, objc, objv);
+ break;
+ case NSEvalIdx:
+ result = NamespaceEvalCmd(clientData, interp, objc, objv);
+ break;
+ case NSExistsIdx:
+ result = NamespaceExistsCmd(clientData, interp, objc, objv);
+ break;
+ case NSExportIdx:
+ result = NamespaceExportCmd(clientData, interp, objc, objv);
+ break;
+ case NSForgetIdx:
+ result = NamespaceForgetCmd(clientData, interp, objc, objv);
+ break;
+ case NSImportIdx:
+ result = NamespaceImportCmd(clientData, interp, objc, objv);
+ break;
+ case NSInscopeIdx:
+ result = NamespaceInscopeCmd(clientData, interp, objc, objv);
+ break;
+ case NSOriginIdx:
+ result = NamespaceOriginCmd(clientData, interp, objc, objv);
+ break;
+ case NSParentIdx:
+ result = NamespaceParentCmd(clientData, interp, objc, objv);
+ break;
+ case NSPathIdx:
+ result = NamespacePathCmd(clientData, interp, objc, objv);
+ break;
+ case NSQualifiersIdx:
+ result = NamespaceQualifiersCmd(clientData, interp, objc, objv);
+ break;
+ case NSTailIdx:
+ result = NamespaceTailCmd(clientData, interp, objc, objv);
+ break;
+ case NSUpvarIdx:
+ result = NamespaceUpvarCmd(clientData, interp, objc, objv);
+ break;
+ case NSUnknownIdx:
+ result = NamespaceUnknownCmd(clientData, interp, objc, objv);
+ break;
+ case NSWhichIdx:
+ result = NamespaceWhichCmd(clientData, interp, objc, objv);
+ break;
}
return result;
}
@@ -2596,8 +2868,8 @@ Tcl_NamespaceObjCmd(clientData, interp, objc, objv)
* NamespaceChildrenCmd --
*
* Invoked to implement the "namespace children" command that returns a
- * list containing the fully-qualified names of the child namespaces of
- * a given namespace. Handles the following syntax:
+ * list containing the fully-qualified names of the child namespaces of a
+ * given namespace. Handles the following syntax:
*
* namespace children ?name? ?pattern?
*
@@ -2605,22 +2877,22 @@ Tcl_NamespaceObjCmd(clientData, interp, objc, objv)
* Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
*
* Side effects:
- * Returns a result in the interpreter's result object. If anything
- * goes wrong, the result is an error message.
+ * Returns a result in the interpreter's result object. If anything goes
+ * wrong, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-NamespaceChildrenCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+NamespaceChildrenCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Namespace *namespacePtr;
Namespace *nsPtr, *childNsPtr;
- Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
+ Namespace *globalNsPtr = (Namespace *) TclGetGlobalNamespace(interp);
char *pattern = NULL;
Tcl_DString buffer;
register Tcl_HashEntry *entryPtr;
@@ -2632,21 +2904,15 @@ NamespaceChildrenCmd(dummy, interp, objc, objv)
*/
if (objc == 2) {
- nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+ nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
} else if ((objc == 3) || (objc == 4)) {
- if (GetNamespaceFromObj(interp, objv[2], &namespacePtr) != TCL_OK) {
- return TCL_ERROR;
- }
- if (namespacePtr == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "unknown namespace \"", Tcl_GetString(objv[2]),
- "\" in namespace children command", (char *) NULL);
- return TCL_ERROR;
- }
- nsPtr = (Namespace *) namespacePtr;
+ if (TclGetNamespaceFromObj(interp, objv[2], &namespacePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ nsPtr = (Namespace *) namespacePtr;
} else {
Tcl_WrongNumArgs(interp, 2, objv, "?name? ?pattern?");
- return TCL_ERROR;
+ return TCL_ERROR;
}
/*
@@ -2655,37 +2921,50 @@ NamespaceChildrenCmd(dummy, interp, objc, objv)
Tcl_DStringInit(&buffer);
if (objc == 4) {
- char *name = Tcl_GetString(objv[3]);
-
- if ((*name == ':') && (*(name+1) == ':')) {
- pattern = name;
- } else {
- Tcl_DStringAppend(&buffer, nsPtr->fullName, -1);
- if (nsPtr != globalNsPtr) {
- Tcl_DStringAppend(&buffer, "::", 2);
- }
- Tcl_DStringAppend(&buffer, name, -1);
- pattern = Tcl_DStringValue(&buffer);
- }
+ char *name = TclGetString(objv[3]);
+
+ if ((*name == ':') && (*(name+1) == ':')) {
+ pattern = name;
+ } else {
+ Tcl_DStringAppend(&buffer, nsPtr->fullName, -1);
+ if (nsPtr != globalNsPtr) {
+ Tcl_DStringAppend(&buffer, "::", 2);
+ }
+ Tcl_DStringAppend(&buffer, name, -1);
+ pattern = Tcl_DStringValue(&buffer);
+ }
}
/*
- * Create a list containing the full names of all child namespaces
- * whose names match the specified pattern, if any.
+ * Create a list containing the full names of all child namespaces whose
+ * names match the specified pattern, if any.
*/
- listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+ listPtr = Tcl_NewListObj(0, NULL);
+ if ((pattern != NULL) && TclMatchIsTrivial(pattern)) {
+ unsigned int length = strlen(nsPtr->fullName);
+
+ if (strncmp(pattern, nsPtr->fullName, length) != 0) {
+ goto searchDone;
+ }
+ if (Tcl_FindHashEntry(&nsPtr->childTable, pattern+length) != NULL) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(pattern, -1));
+ }
+ goto searchDone;
+ }
entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search);
while (entryPtr != NULL) {
- childNsPtr = (Namespace *) Tcl_GetHashValue(entryPtr);
- if ((pattern == NULL)
- || Tcl_StringMatch(childNsPtr->fullName, pattern)) {
- elemPtr = Tcl_NewStringObj(childNsPtr->fullName, -1);
- Tcl_ListObjAppendElement(interp, listPtr, elemPtr);
- }
- entryPtr = Tcl_NextHashEntry(&search);
+ childNsPtr = Tcl_GetHashValue(entryPtr);
+ if ((pattern == NULL)
+ || Tcl_StringMatch(childNsPtr->fullName, pattern)) {
+ elemPtr = Tcl_NewStringObj(childNsPtr->fullName, -1);
+ Tcl_ListObjAppendElement(interp, listPtr, elemPtr);
+ }
+ entryPtr = Tcl_NextHashEntry(&search);
}
+ searchDone:
Tcl_SetObjResult(interp, listPtr);
Tcl_DStringFree(&buffer);
return TCL_OK;
@@ -2706,79 +2985,73 @@ NamespaceChildrenCmd(dummy, interp, objc, objv)
*
* list ::namespace inscope [namespace current] $arg
*
- * However, if "arg" is itself a scoped value starting with
- * "::namespace inscope", then the result is just "arg".
+ * However, if "arg" is itself a scoped value starting with "::namespace
+ * inscope", then the result is just "arg".
*
* Results:
* Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
*
* Side effects:
- * If anything goes wrong, this procedure returns an error
- * message as the result in the interpreter's result object.
+ * If anything goes wrong, this function returns an error message as the
+ * result in the interpreter's result object.
*
*----------------------------------------------------------------------
*/
static int
-NamespaceCodeCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+NamespaceCodeCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Namespace *currNsPtr;
Tcl_Obj *listPtr, *objPtr;
- register char *arg, *p;
+ register char *arg;
int length;
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "arg");
- return TCL_ERROR;
+ return TCL_ERROR;
}
/*
* If "arg" is already a scoped value, then return it directly.
+ * Take care to only check for scoping in precisely the style that
+ * [::namespace code] generates it. Anything more forgiving can have
+ * the effect of failing in namespaces that contain their own custom
+ " "namespace" command. [Bug 3202171].
*/
- arg = Tcl_GetStringFromObj(objv[2], &length);
- while (*arg == ':') {
- arg++;
- length--;
- }
- if ((*arg == 'n') && (length > 17)
- && (strncmp(arg, "namespace", 9) == 0)) {
- for (p = (arg + 9); (*p == ' '); p++) {
- /* empty body: skip over spaces */
- }
- if ((*p == 'i') && ((p + 7) <= (arg + length))
- && (strncmp(p, "inscope", 7) == 0)) {
- Tcl_SetObjResult(interp, objv[2]);
- return TCL_OK;
- }
+ arg = TclGetStringFromObj(objv[2], &length);
+ if (*arg==':' && length > 20
+ && strncmp(arg, "::namespace inscope ", 20) == 0) {
+ Tcl_SetObjResult(interp, objv[2]);
+ return TCL_OK;
}
/*
* Otherwise, construct a scoped command by building a list with
- * "namespace inscope", the full name of the current namespace, and
- * the argument "arg". By constructing a list, we ensure that scoped
- * commands are interpreted properly when they are executed later,
- * by the "namespace inscope" command.
+ * "namespace inscope", the full name of the current namespace, and the
+ * argument "arg". By constructing a list, we ensure that scoped commands
+ * are interpreted properly when they are executed later, by the
+ * "namespace inscope" command.
*/
- listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
- Tcl_ListObjAppendElement(interp, listPtr,
- Tcl_NewStringObj("::namespace", -1));
- Tcl_ListObjAppendElement(interp, listPtr,
- Tcl_NewStringObj("inscope", -1));
+ TclNewObj(listPtr);
+ TclNewLiteralStringObj(objPtr, "::namespace");
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ TclNewLiteralStringObj(objPtr, "inscope");
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
- currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
- if (currNsPtr == (Namespace *) Tcl_GetGlobalNamespace(interp)) {
- objPtr = Tcl_NewStringObj("::", -1);
+ currNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
+ if (currNsPtr == (Namespace *) TclGetGlobalNamespace(interp)) {
+ TclNewLiteralStringObj(objPtr, "::");
} else {
objPtr = Tcl_NewStringObj(currNsPtr->fullName, -1);
}
Tcl_ListObjAppendElement(interp, listPtr, objPtr);
-
+
Tcl_ListObjAppendElement(interp, listPtr, objv[2]);
Tcl_SetObjResult(interp, listPtr);
@@ -2790,9 +3063,9 @@ NamespaceCodeCmd(dummy, interp, objc, objv)
*
* NamespaceCurrentCmd --
*
- * Invoked to implement the "namespace current" command which returns
- * the fully-qualified name of the current namespace. Handles the
- * following syntax:
+ * Invoked to implement the "namespace current" command which returns the
+ * fully-qualified name of the current namespace. Handles the following
+ * syntax:
*
* namespace current
*
@@ -2800,40 +3073,40 @@ NamespaceCodeCmd(dummy, interp, objc, objv)
* Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
*
* Side effects:
- * Returns a result in the interpreter's result object. If anything
- * goes wrong, the result is an error message.
+ * Returns a result in the interpreter's result object. If anything goes
+ * wrong, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-NamespaceCurrentCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+NamespaceCurrentCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
register Namespace *currNsPtr;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 2, objv, NULL);
- return TCL_ERROR;
+ return TCL_ERROR;
}
/*
- * The "real" name of the global namespace ("::") is the null string,
- * but we return "::" for it as a convenience to programmers. Note that
- * "" and "::" are treated as synonyms by the namespace code so that it
- * is still easy to do things like:
+ * The "real" name of the global namespace ("::") is the null string, but
+ * we return "::" for it as a convenience to programmers. Note that "" and
+ * "::" are treated as synonyms by the namespace code so that it is still
+ * easy to do things like:
*
* namespace [namespace current]::bar { ... }
*/
- currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
- if (currNsPtr == (Namespace *) Tcl_GetGlobalNamespace(interp)) {
- Tcl_AppendToObj(Tcl_GetObjResult(interp), "::", -1);
+ currNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
+ if (currNsPtr == (Namespace *) TclGetGlobalNamespace(interp)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("::", 2));
} else {
- Tcl_AppendToObj(Tcl_GetObjResult(interp), currNsPtr->fullName, -1);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(currNsPtr->fullName, -1));
}
return TCL_OK;
}
@@ -2851,57 +3124,58 @@ NamespaceCurrentCmd(dummy, interp, objc, objv)
* Each name identifies a namespace. It may include a sequence of
* namespace qualifiers separated by "::"s. If a namespace is found, it
* is deleted: all variables and procedures contained in that namespace
- * are deleted. If that namespace is being used on the call stack, it
- * is kept alive (but logically deleted) until it is removed from the
- * call stack: that is, it can no longer be referenced by name but any
+ * are deleted. If that namespace is being used on the call stack, it is
+ * kept alive (but logically deleted) until it is removed from the call
+ * stack: that is, it can no longer be referenced by name but any
* currently executing procedure that refers to it is allowed to do so
* until the procedure returns. If the namespace can't be found, this
- * procedure returns an error. If no namespaces are specified, this
+ * function returns an error. If no namespaces are specified, this
* command does nothing.
*
* Results:
- * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
+ * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
*
* Side effects:
* Deletes the specified namespaces. If anything goes wrong, this
- * procedure returns an error message in the interpreter's
- * result object.
+ * function returns an error message in the interpreter's result object.
*
*----------------------------------------------------------------------
*/
static int
-NamespaceDeleteCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+NamespaceDeleteCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Namespace *namespacePtr;
char *name;
register int i;
if (objc < 2) {
- Tcl_WrongNumArgs(interp, 2, objv, "?name name...?");
- return TCL_ERROR;
+ Tcl_WrongNumArgs(interp, 2, objv, "?name name...?");
+ return TCL_ERROR;
}
/*
- * Destroying one namespace may cause another to be destroyed. Break
- * this into two passes: first check to make sure that all namespaces on
- * the command line are valid, and report any errors.
+ * Destroying one namespace may cause another to be destroyed. Break this
+ * into two passes: first check to make sure that all namespaces on the
+ * command line are valid, and report any errors.
*/
for (i = 2; i < objc; i++) {
- name = Tcl_GetString(objv[i]);
- namespacePtr = Tcl_FindNamespace(interp, name,
- (Tcl_Namespace *) NULL, /*flags*/ 0);
- if (namespacePtr == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "unknown namespace \"", Tcl_GetString(objv[i]),
- "\" in namespace delete command", (char *) NULL);
- return TCL_ERROR;
- }
+ name = TclGetString(objv[i]);
+ namespacePtr = Tcl_FindNamespace(interp, name, NULL, /*flags*/ 0);
+ if ((namespacePtr == NULL)
+ || (((Namespace *)namespacePtr)->flags & NS_KILLED)) {
+ Tcl_AppendResult(interp, "unknown namespace \"",
+ TclGetString(objv[i]),
+ "\" in namespace delete command", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE",
+ TclGetString(objv[i]), NULL);
+ return TCL_ERROR;
+ }
}
/*
@@ -2909,12 +3183,11 @@ NamespaceDeleteCmd(dummy, interp, objc, objv)
*/
for (i = 2; i < objc; i++) {
- name = Tcl_GetString(objv[i]);
- namespacePtr = Tcl_FindNamespace(interp, name,
- (Tcl_Namespace *) NULL, /* flags */ 0);
+ name = TclGetString(objv[i]);
+ namespacePtr = Tcl_FindNamespace(interp, name, NULL, /* flags */ 0);
if (namespacePtr) {
- Tcl_DeleteNamespace(namespacePtr);
- }
+ Tcl_DeleteNamespace(namespacePtr);
+ }
}
return TCL_OK;
}
@@ -2924,44 +3197,43 @@ NamespaceDeleteCmd(dummy, interp, objc, objv)
*
* NamespaceEvalCmd --
*
- * Invoked to implement the "namespace eval" command. Executes
- * commands in a namespace. If the namespace does not already exist,
- * it is created. Handles the following syntax:
+ * Invoked to implement the "namespace eval" command. Executes commands
+ * in a namespace. If the namespace does not already exist, it is
+ * created. Handles the following syntax:
*
* namespace eval name arg ?arg...?
*
* If more than one arg argument is specified, the command that is
- * executed is the result of concatenating the arguments together with
- * a space between each argument.
+ * executed is the result of concatenating the arguments together with a
+ * space between each argument.
*
* Results:
- * Returns TCL_OK if the namespace is found and the commands are
- * executed successfully. Returns TCL_ERROR if anything goes wrong.
+ * Returns TCL_OK if the namespace is found and the commands are executed
+ * successfully. Returns TCL_ERROR if anything goes wrong.
*
* Side effects:
- * Returns the result of the command in the interpreter's result
- * object. If anything goes wrong, this procedure returns an error
- * message as the result.
+ * Returns the result of the command in the interpreter's result object.
+ * If anything goes wrong, this function returns an error message as the
+ * result.
*
*----------------------------------------------------------------------
*/
static int
-NamespaceEvalCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+NamespaceEvalCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Namespace *namespacePtr;
- CallFrame frame;
+ CallFrame *framePtr, **framePtrPtr;
Tcl_Obj *objPtr;
- char *name;
- int length, result;
+ int result;
if (objc < 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "name arg ?arg...?");
- return TCL_ERROR;
+ Tcl_WrongNumArgs(interp, 2, objv, "name arg ?arg...?");
+ return TCL_ERROR;
}
/*
@@ -2970,74 +3242,79 @@ NamespaceEvalCmd(dummy, interp, objc, objv)
*/
result = GetNamespaceFromObj(interp, objv[2], &namespacePtr);
- if (result != TCL_OK) {
- return result;
- }
/*
* If the namespace wasn't found, try to create it.
*/
-
- if (namespacePtr == NULL) {
- name = Tcl_GetStringFromObj(objv[2], &length);
- namespacePtr = Tcl_CreateNamespace(interp, name, (ClientData) NULL,
- (Tcl_NamespaceDeleteProc *) NULL);
+
+ if (result == TCL_ERROR) {
+ char *name = TclGetString(objv[2]);
+
+ namespacePtr = Tcl_CreateNamespace(interp, name, NULL, NULL);
if (namespacePtr == NULL) {
return TCL_ERROR;
}
}
/*
- * Make the specified namespace the current namespace and evaluate
- * the command(s).
+ * Make the specified namespace the current namespace and evaluate the
+ * command(s).
*/
- result = Tcl_PushCallFrame(interp, (Tcl_CallFrame *) &frame,
- namespacePtr, /*isProcCallFrame*/ 0);
+ /* This is needed to satisfy GCC 3.3's strict aliasing rules */
+ framePtrPtr = &framePtr;
+ result = TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr,
+ namespacePtr, /*isProcCallFrame*/ 0);
if (result != TCL_OK) {
- return TCL_ERROR;
+ return TCL_ERROR;
}
- frame.objc = objc;
- frame.objv = objv; /* ref counts do not need to be incremented here */
+
+ framePtr->objc = objc;
+ framePtr->objv = objv;
if (objc == 4) {
-#ifndef TCL_TIP280
- result = Tcl_EvalObjEx(interp, objv[3], 0);
-#else
- /* TIP #280 : Make actual argument location available to eval'd script */
- Interp* iPtr = (Interp*) interp;
+ /*
+ * TIP #280: Make actual argument location available to eval'd script.
+ */
+
+ Interp *iPtr = (Interp *) interp;
CmdFrame* invoker = iPtr->cmdFramePtr;
int word = 3;
+
TclArgumentGet (interp, objv[3], &invoker, &word);
- result = TclEvalObjEx(interp, objv[3], 0, invoker, word);
-#endif
+ result = TclEvalObjEx(interp, objv[3], 0, invoker, word);
} else {
/*
* More than one argument: concatenate them together with spaces
- * between, then evaluate the result. Tcl_EvalObjEx will delete
- * the object when it decrements its refcount after eval'ing it.
+ * between, then evaluate the result. Tcl_EvalObjEx will delete the
+ * object when it decrements its refcount after eval'ing it.
*/
- objPtr = Tcl_ConcatObj(objc-3, objv+3);
-#ifndef TCL_TIP280
- result = Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_DIRECT);
-#else
- /* TIP #280. Make invoking context available to eval'd script */
+
+ objPtr = Tcl_ConcatObj(objc-3, objv+3);
+
+ /*
+ * TIP #280: Make invoking context available to eval'd script.
+ */
+
result = TclEvalObjEx(interp, objPtr, TCL_EVAL_DIRECT, NULL, 0);
-#endif
}
+
if (result == TCL_ERROR) {
- char msg[256 + TCL_INTEGER_SPACE];
-
- sprintf(msg, "\n (in namespace eval \"%.200s\" script line %d)",
- namespacePtr->fullName, interp->errorLine);
- Tcl_AddObjErrorInfo(interp, msg, -1);
+ int length = strlen(namespacePtr->fullName);
+ int limit = 200;
+ int overflow = (length > limit);
+
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (in namespace eval \"%.*s%s\" script line %d)",
+ (overflow ? limit : length), namespacePtr->fullName,
+ (overflow ? "..." : ""), interp->errorLine));
}
/*
* Restore the previous "current" namespace.
*/
-
- Tcl_PopCallFrame(interp);
+
+ TclPopStackFrame(interp);
return result;
}
@@ -3046,9 +3323,9 @@ NamespaceEvalCmd(dummy, interp, objc, objv)
*
* NamespaceExistsCmd --
*
- * Invoked to implement the "namespace exists" command that returns
- * true if the given namespace currently exists, and false otherwise.
- * Handles the following syntax:
+ * Invoked to implement the "namespace exists" command that returns true
+ * if the given namespace currently exists, and false otherwise. Handles
+ * the following syntax:
*
* namespace exists name
*
@@ -3056,35 +3333,28 @@ NamespaceEvalCmd(dummy, interp, objc, objv)
* Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
*
* Side effects:
- * Returns a result in the interpreter's result object. If anything
- * goes wrong, the result is an error message.
+ * Returns a result in the interpreter's result object. If anything goes
+ * wrong, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-NamespaceExistsCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+NamespaceExistsCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Namespace *namespacePtr;
if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "name");
- return TCL_ERROR;
- }
-
- /*
- * Check whether the given namespace exists
- */
-
- if (GetNamespaceFromObj(interp, objv[2], &namespacePtr) != TCL_OK) {
- return TCL_ERROR;
+ Tcl_WrongNumArgs(interp, 2, objv, "name");
+ return TCL_ERROR;
}
- Tcl_SetBooleanObj(Tcl_GetObjResult(interp), (namespacePtr != NULL));
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
+ GetNamespaceFromObj(interp, objv[2], &namespacePtr) == TCL_OK));
return TCL_OK;
}
@@ -3095,18 +3365,18 @@ NamespaceExistsCmd(dummy, interp, objc, objv)
*
* Invoked to implement the "namespace export" command that specifies
* which commands are exported from a namespace. The exported commands
- * are those that can be imported into another namespace using
- * "namespace import". Both commands defined in a namespace and
- * commands the namespace has imported can be exported by a
- * namespace. This command has the following syntax:
+ * are those that can be imported into another namespace using "namespace
+ * import". Both commands defined in a namespace and commands the
+ * namespace has imported can be exported by a namespace. This command
+ * has the following syntax:
*
* namespace export ?-clear? ?pattern pattern...?
*
- * Each pattern may contain "string match"-style pattern matching
- * special characters, but the pattern may not include any namespace
- * qualifiers: that is, the pattern must specify commands in the
- * current (exporting) namespace. The specified patterns are appended
- * onto the namespace's list of export patterns.
+ * Each pattern may contain "string match"-style pattern matching special
+ * characters, but the pattern may not include any namespace qualifiers:
+ * that is, the pattern must specify commands in the current (exporting)
+ * namespace. The specified patterns are appended onto the namespace's
+ * list of export patterns.
*
* To reset the namespace's export pattern list, specify the "-clear"
* flag.
@@ -3118,28 +3388,27 @@ NamespaceExistsCmd(dummy, interp, objc, objv)
* Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
*
* Side effects:
- * Returns a result in the interpreter's result object. If anything
- * goes wrong, the result is an error message.
+ * Returns a result in the interpreter's result object. If anything goes
+ * wrong, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-NamespaceExportCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+NamespaceExportCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- Namespace *currNsPtr = (Namespace*) Tcl_GetCurrentNamespace(interp);
+ Namespace *currNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
char *pattern, *string;
int resetListFirst = 0;
int firstArg, patternCt, i, result;
if (objc < 2) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-clear? ?pattern pattern...?");
- return TCL_ERROR;
+ Tcl_WrongNumArgs(interp, 2, objv, "?-clear? ?pattern pattern...?");
+ return TCL_ERROR;
}
/*
@@ -3148,7 +3417,7 @@ NamespaceExportCmd(dummy, interp, objc, objv)
firstArg = 2;
if (firstArg < objc) {
- string = Tcl_GetString(objv[firstArg]);
+ string = TclGetString(objv[firstArg]);
if (strcmp(string, "-clear") == 0) {
resetListFirst = 1;
firstArg++;
@@ -3156,18 +3425,22 @@ NamespaceExportCmd(dummy, interp, objc, objv)
}
/*
- * If no pattern arguments are given, and "-clear" isn't specified,
- * return the namespace's current export pattern list.
+ * If no pattern arguments are given, and "-clear" isn't specified, return
+ * the namespace's current export pattern list.
*/
patternCt = (objc - firstArg);
if (patternCt == 0) {
if (firstArg > 2) {
return TCL_OK;
- } else { /* create list with export patterns */
- Tcl_Obj *listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
- result = Tcl_AppendExportList(interp,
- (Tcl_Namespace *) currNsPtr, listPtr);
+ } else {
+ /*
+ * Create list with export patterns.
+ */
+
+ Tcl_Obj *listPtr = Tcl_NewListObj(0, NULL);
+ result = Tcl_AppendExportList(interp, (Tcl_Namespace *) currNsPtr,
+ listPtr);
if (result != TCL_OK) {
return result;
}
@@ -3179,14 +3452,14 @@ NamespaceExportCmd(dummy, interp, objc, objv)
/*
* Add each pattern to the namespace's export pattern list.
*/
-
+
for (i = firstArg; i < objc; i++) {
- pattern = Tcl_GetString(objv[i]);
+ pattern = TclGetString(objv[i]);
result = Tcl_Export(interp, (Tcl_Namespace *) currNsPtr, pattern,
((i == firstArg)? resetListFirst : 0));
- if (result != TCL_OK) {
- return result;
- }
+ if (result != TCL_OK) {
+ return result;
+ }
}
return TCL_OK;
}
@@ -3196,52 +3469,52 @@ NamespaceExportCmd(dummy, interp, objc, objv)
*
* NamespaceForgetCmd --
*
- * Invoked to implement the "namespace forget" command to remove
- * imported commands from a namespace. Handles the following syntax:
+ * Invoked to implement the "namespace forget" command to remove imported
+ * commands from a namespace. Handles the following syntax:
*
* namespace forget ?pattern pattern...?
*
* Each pattern is a name like "foo::*" or "a::b::x*". That is, the
- * pattern may include the special pattern matching characters
- * recognized by the "string match" command, but only in the command
- * name at the end of the qualified name; the special pattern
- * characters may not appear in a namespace name. All of the commands
- * that match that pattern are checked to see if they have an imported
- * command in the current namespace that refers to the matched
- * command. If there is an alias, it is removed.
- *
+ * pattern may include the special pattern matching characters recognized
+ * by the "string match" command, but only in the command name at the end
+ * of the qualified name; the special pattern characters may not appear
+ * in a namespace name. All of the commands that match that pattern are
+ * checked to see if they have an imported command in the current
+ * namespace that refers to the matched command. If there is an alias, it
+ * is removed.
+ *
* Results:
* Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
*
* Side effects:
- * Imported commands are removed from the current namespace. If
- * anything goes wrong, this procedure returns an error message in the
+ * Imported commands are removed from the current namespace. If anything
+ * goes wrong, this function returns an error message in the
* interpreter's result object.
*
*----------------------------------------------------------------------
*/
static int
-NamespaceForgetCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+NamespaceForgetCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
char *pattern;
register int i, result;
if (objc < 2) {
- Tcl_WrongNumArgs(interp, 2, objv, "?pattern pattern...?");
- return TCL_ERROR;
+ Tcl_WrongNumArgs(interp, 2, objv, "?pattern pattern...?");
+ return TCL_ERROR;
}
for (i = 2; i < objc; i++) {
- pattern = Tcl_GetString(objv[i]);
- result = Tcl_ForgetImport(interp, (Tcl_Namespace *) NULL, pattern);
- if (result != TCL_OK) {
- return result;
- }
+ pattern = TclGetString(objv[i]);
+ result = Tcl_ForgetImport(interp, NULL, pattern);
+ if (result != TCL_OK) {
+ return result;
+ }
}
return TCL_OK;
}
@@ -3256,39 +3529,42 @@ NamespaceForgetCmd(dummy, interp, objc, objv)
*
* namespace import ?-force? ?pattern pattern...?
*
- * Each pattern is a namespace-qualified name like "foo::*",
- * "a::b::x*", or "bar::p". That is, the pattern may include the
- * special pattern matching characters recognized by the "string match"
- * command, but only in the command name at the end of the qualified
- * name; the special pattern characters may not appear in a namespace
- * name. All of the commands that match the pattern and which are
- * exported from their namespace are made accessible from the current
- * namespace context. This is done by creating a new "imported command"
- * in the current namespace that points to the real command in its
- * original namespace; when the imported command is called, it invokes
- * the real command.
+ * Each pattern is a namespace-qualified name like "foo::*", "a::b::x*",
+ * or "bar::p". That is, the pattern may include the special pattern
+ * matching characters recognized by the "string match" command, but only
+ * in the command name at the end of the qualified name; the special
+ * pattern characters may not appear in a namespace name. All of the
+ * commands that match the pattern and which are exported from their
+ * namespace are made accessible from the current namespace context. This
+ * is done by creating a new "imported command" in the current namespace
+ * that points to the real command in its original namespace; when the
+ * imported command is called, it invokes the real command.
*
* If an imported command conflicts with an existing command, it is
* treated as an error. But if the "-force" option is included, then
* existing commands are overwritten by the imported commands.
- *
+ *
+ * If there are no pattern arguments and the "-force" flag isn't given,
+ * this command returns the list of commands currently imported in
+ * the current namespace.
+ *
* Results:
* Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
*
* Side effects:
* Adds imported commands to the current namespace. If anything goes
- * wrong, this procedure returns an error message in the interpreter's
+ * wrong, this function returns an error message in the interpreter's
* result object.
*
*----------------------------------------------------------------------
*/
static int
-NamespaceImportCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+NamespaceImportCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
int allowOverwrite = 0;
char *string, *pattern;
@@ -3296,9 +3572,8 @@ NamespaceImportCmd(dummy, interp, objc, objv)
int firstArg;
if (objc < 2) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-force? ?pattern pattern...?");
- return TCL_ERROR;
+ Tcl_WrongNumArgs(interp, 2, objv, "?-force? ?pattern pattern...?");
+ return TCL_ERROR;
}
/*
@@ -3307,11 +3582,34 @@ NamespaceImportCmd(dummy, interp, objc, objv)
firstArg = 2;
if (firstArg < objc) {
- string = Tcl_GetString(objv[firstArg]);
+ string = TclGetString(objv[firstArg]);
if ((*string == '-') && (strcmp(string, "-force") == 0)) {
allowOverwrite = 1;
firstArg++;
}
+ } else {
+ /*
+ * When objc == 2, command is just [namespace import]. Introspection
+ * form to return list of imported commands.
+ */
+
+ Tcl_HashEntry *hPtr;
+ Tcl_HashSearch search;
+ Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
+ Tcl_Obj *listPtr;
+
+ TclNewObj(listPtr);
+ for (hPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ Command *cmdPtr = Tcl_GetHashValue(hPtr);
+
+ if (cmdPtr->deleteProc == DeleteImportedCmd) {
+ Tcl_ListObjAppendElement(NULL, listPtr, Tcl_NewStringObj(
+ Tcl_GetHashKey(&nsPtr->cmdTable, hPtr) ,-1));
+ }
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
}
/*
@@ -3319,12 +3617,11 @@ NamespaceImportCmd(dummy, interp, objc, objv)
*/
for (i = firstArg; i < objc; i++) {
- pattern = Tcl_GetString(objv[i]);
- result = Tcl_Import(interp, (Tcl_Namespace *) NULL, pattern,
- allowOverwrite);
- if (result != TCL_OK) {
- return result;
- }
+ pattern = TclGetString(objv[i]);
+ result = Tcl_Import(interp, NULL, pattern, allowOverwrite);
+ if (result != TCL_OK) {
+ return result;
+ }
}
return TCL_OK;
}
@@ -3336,30 +3633,29 @@ NamespaceImportCmd(dummy, interp, objc, objv)
*
* Invoked to implement the "namespace inscope" command that executes a
* script in the context of a particular namespace. This command is not
- * expected to be used directly by programmers; calls to it are
- * generated implicitly when programs use "namespace code" commands
- * to register callback scripts. Handles the following syntax:
+ * expected to be used directly by programmers; calls to it are generated
+ * implicitly when programs use "namespace code" commands to register
+ * callback scripts. Handles the following syntax:
*
* namespace inscope name arg ?arg...?
*
* The "namespace inscope" command is much like the "namespace eval"
* command except that it has lappend semantics and the namespace must
- * already exist. It treats the first argument as a list, and appends
- * any arguments after the first onto the end as proper list elements.
- * For example,
+ * already exist. It treats the first argument as a list, and appends any
+ * arguments after the first onto the end as proper list elements. For
+ * example,
*
- * namespace inscope ::foo a b c d
+ * namespace inscope ::foo {a b} c d e
*
* is equivalent to
*
- * namespace eval ::foo [concat a [list b c d]]
+ * namespace eval ::foo [concat {a b} [list c d e]]
*
- * This lappend semantics is important because many callback scripts
- * are actually prefixes.
+ * This lappend semantics is important because many callback scripts are
+ * actually prefixes.
*
* Results:
- * Returns TCL_OK to indicate success, or TCL_ERROR to indicate
- * failure.
+ * Returns TCL_OK to indicate success, or TCL_ERROR to indicate failure.
*
* Side effects:
* Returns a result in the Tcl interpreter's result object.
@@ -3368,88 +3664,88 @@ NamespaceImportCmd(dummy, interp, objc, objv)
*/
static int
-NamespaceInscopeCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+NamespaceInscopeCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Namespace *namespacePtr;
- Tcl_CallFrame frame;
+ CallFrame *framePtr, **framePtrPtr;
int i, result;
if (objc < 4) {
Tcl_WrongNumArgs(interp, 2, objv, "name arg ?arg...?");
- return TCL_ERROR;
+ return TCL_ERROR;
}
/*
* Resolve the namespace reference.
*/
- result = GetNamespaceFromObj(interp, objv[2], &namespacePtr);
- if (result != TCL_OK) {
- return result;
- }
- if (namespacePtr == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "unknown namespace \"", Tcl_GetString(objv[2]),
- "\" in inscope namespace command", (char *) NULL);
- return TCL_ERROR;
+ if (TclGetNamespaceFromObj(interp, objv[2], &namespacePtr) != TCL_OK) {
+ return TCL_ERROR;
}
/*
* Make the specified namespace the current namespace.
*/
- result = Tcl_PushCallFrame(interp, &frame, namespacePtr,
- /*isProcCallFrame*/ 0);
+ framePtrPtr = &framePtr; /* This is needed to satisfy GCC's
+ * strict aliasing rules. */
+ result = TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr,
+ namespacePtr, /*isProcCallFrame*/ 0);
if (result != TCL_OK) {
- return result;
+ return result;
}
+ framePtr->objc = objc;
+ framePtr->objv = objv;
+
/*
- * Execute the command. If there is just one argument, just treat it as
- * a script and evaluate it. Otherwise, create a list from the arguments
+ * Execute the command. If there is just one argument, just treat it as a
+ * script and evaluate it. Otherwise, create a list from the arguments
* after the first one, then concatenate the first argument and the list
* of extra arguments to form the command to evaluate.
*/
if (objc == 4) {
- result = Tcl_EvalObjEx(interp, objv[3], 0);
+ result = Tcl_EvalObjEx(interp, objv[3], 0);
} else {
Tcl_Obj *concatObjv[2];
register Tcl_Obj *listPtr, *cmdObjPtr;
-
- listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
- for (i = 4; i < objc; i++) {
- result = Tcl_ListObjAppendElement(interp, listPtr, objv[i]);
- if (result != TCL_OK) {
- Tcl_DecrRefCount(listPtr); /* free unneeded obj */
- return result;
- }
- }
+
+ listPtr = Tcl_NewListObj(0, NULL);
+ for (i = 4; i < objc; i++) {
+ if (Tcl_ListObjAppendElement(interp, listPtr, objv[i]) != TCL_OK) {
+ Tcl_DecrRefCount(listPtr); /* Free unneeded obj. */
+ return TCL_ERROR;
+ }
+ }
concatObjv[0] = objv[3];
concatObjv[1] = listPtr;
cmdObjPtr = Tcl_ConcatObj(2, concatObjv);
- result = Tcl_EvalObjEx(interp, cmdObjPtr, TCL_EVAL_DIRECT);
- Tcl_DecrRefCount(listPtr); /* we're done with the list object */
+ result = Tcl_EvalObjEx(interp, cmdObjPtr, TCL_EVAL_DIRECT);
+ Tcl_DecrRefCount(listPtr); /* We're done with the list object. */
}
+
if (result == TCL_ERROR) {
- char msg[256 + TCL_INTEGER_SPACE];
-
- sprintf(msg,
- "\n (in namespace inscope \"%.200s\" script line %d)",
- namespacePtr->fullName, interp->errorLine);
- Tcl_AddObjErrorInfo(interp, msg, -1);
+ int length = strlen(namespacePtr->fullName);
+ int limit = 200;
+ int overflow = (length > limit);
+
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (in namespace inscope \"%.*s%s\" script line %d)",
+ (overflow ? limit : length), namespacePtr->fullName,
+ (overflow ? "..." : ""), interp->errorLine));
}
/*
* Restore the previous "current" namespace.
*/
- Tcl_PopCallFrame(interp);
+ TclPopStackFrame(interp);
return result;
}
@@ -3472,49 +3768,53 @@ NamespaceInscopeCmd(dummy, interp, objc, objv)
* command returns the fully-qualified name of the original command in
* the first namespace, a. If "name" does not refer to an alias, its
* fully-qualified name is returned. The returned name is stored in the
- * interpreter's result object. This procedure returns TCL_OK if
+ * interpreter's result object. This function returns TCL_OK if
* successful, and TCL_ERROR if anything goes wrong.
*
* Side effects:
- * If anything goes wrong, this procedure returns an error message in
- * the interpreter's result object.
+ * If anything goes wrong, this function returns an error message in the
+ * interpreter's result object.
*
*----------------------------------------------------------------------
*/
static int
-NamespaceOriginCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+NamespaceOriginCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Command command, origCommand;
+ Tcl_Obj *resultPtr;
if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "name");
- return TCL_ERROR;
+ Tcl_WrongNumArgs(interp, 2, objv, "name");
+ return TCL_ERROR;
}
command = Tcl_GetCommandFromObj(interp, objv[2]);
- if (command == (Tcl_Command) NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "invalid command name \"", Tcl_GetString(objv[2]),
- "\"", (char *) NULL);
+ if (command == NULL) {
+ Tcl_AppendResult(interp, "invalid command name \"",
+ TclGetString(objv[2]), "\"", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND",
+ TclGetString(objv[2]), NULL);
return TCL_ERROR;
}
origCommand = TclGetOriginalCommand(command);
- if (origCommand == (Tcl_Command) NULL) {
+ TclNewObj(resultPtr);
+ if (origCommand == NULL) {
/*
* The specified command isn't an imported command. Return the
- * command's name qualified by the full name of the namespace it
- * was defined in.
+ * command's name qualified by the full name of the namespace it was
+ * defined in.
*/
-
- Tcl_GetCommandFullName(interp, command, Tcl_GetObjResult(interp));
+
+ Tcl_GetCommandFullName(interp, command, resultPtr);
} else {
- Tcl_GetCommandFullName(interp, origCommand, Tcl_GetObjResult(interp));
+ Tcl_GetCommandFullName(interp, origCommand, resultPtr);
}
+ Tcl_SetObjResult(interp, resultPtr);
return TCL_OK;
}
@@ -3533,38 +3833,30 @@ NamespaceOriginCmd(dummy, interp, objc, objv)
* Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
*
* Side effects:
- * Returns a result in the interpreter's result object. If anything
- * goes wrong, the result is an error message.
+ * Returns a result in the interpreter's result object. If anything goes
+ * wrong, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-NamespaceParentCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+NamespaceParentCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Namespace *nsPtr;
- int result;
if (objc == 2) {
- nsPtr = Tcl_GetCurrentNamespace(interp);
+ nsPtr = TclGetCurrentNamespace(interp);
} else if (objc == 3) {
- result = GetNamespaceFromObj(interp, objv[2], &nsPtr);
- if (result != TCL_OK) {
- return result;
- }
- if (nsPtr == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "unknown namespace \"", Tcl_GetString(objv[2]),
- "\" in namespace parent command", (char *) NULL);
- return TCL_ERROR;
- }
+ if (TclGetNamespaceFromObj(interp, objv[2], &nsPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
} else {
- Tcl_WrongNumArgs(interp, 2, objv, "?name?");
- return TCL_ERROR;
+ Tcl_WrongNumArgs(interp, 2, objv, "?name?");
+ return TCL_ERROR;
}
/*
@@ -3572,8 +3864,8 @@ NamespaceParentCmd(dummy, interp, objc, objv)
*/
if (nsPtr->parentPtr != NULL) {
- Tcl_SetStringObj(Tcl_GetObjResult(interp),
- nsPtr->parentPtr->fullName, -1);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ nsPtr->parentPtr->fullName, -1));
}
return TCL_OK;
}
@@ -3581,66 +3873,479 @@ NamespaceParentCmd(dummy, interp, objc, objv)
/*
*----------------------------------------------------------------------
*
+ * NamespacePathCmd --
+ *
+ * Invoked to implement the "namespace path" command that reads and
+ * writes the current namespace's command resolution path. Has one
+ * optional argument: if present, it is a list of named namespaces to set
+ * the path to, and if absent, the current path should be returned.
+ * Handles the following syntax:
+ *
+ * namespace path ?nsList?
+ *
+ * Results:
+ * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong
+ * (most notably if the namespace list contains the name of something
+ * other than a namespace). In the successful-exit case, may set the
+ * interpreter result to the list of names of the namespaces on the
+ * current namespace's path.
+ *
+ * Side effects:
+ * May update the namespace path (triggering a recomputing of all command
+ * names that depend on the namespace for resolution).
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NamespacePathCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
+ int i, nsObjc, result = TCL_ERROR;
+ Tcl_Obj **nsObjv;
+ Tcl_Namespace **namespaceList = NULL;
+
+ if (objc > 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?pathList?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * If no path is given, return the current path.
+ */
+
+ if (objc == 2) {
+ /*
+ * Not a very fast way to compute this, but easy to get right.
+ */
+
+ for (i=0 ; i<nsPtr->commandPathLength ; i++) {
+ if (nsPtr->commandPathArray[i].nsPtr != NULL) {
+ Tcl_AppendElement(interp,
+ nsPtr->commandPathArray[i].nsPtr->fullName);
+ }
+ }
+ return TCL_OK;
+ }
+
+ /*
+ * There is a path given, so parse it into an array of namespace pointers.
+ */
+
+ if (TclListObjGetElements(interp, objv[2], &nsObjc, &nsObjv) != TCL_OK) {
+ goto badNamespace;
+ }
+ if (nsObjc != 0) {
+ namespaceList = (Tcl_Namespace **)
+ TclStackAlloc(interp, sizeof(Tcl_Namespace *) * nsObjc);
+
+ for (i=0 ; i<nsObjc ; i++) {
+ if (TclGetNamespaceFromObj(interp, nsObjv[i],
+ &namespaceList[i]) != TCL_OK) {
+ goto badNamespace;
+ }
+ }
+ }
+
+ /*
+ * Now we have the list of valid namespaces, install it as the path.
+ */
+
+ TclSetNsPath(nsPtr, nsObjc, namespaceList);
+
+ result = TCL_OK;
+ badNamespace:
+ if (namespaceList != NULL) {
+ TclStackFree(interp, namespaceList);
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclSetNsPath --
+ *
+ * Sets the namespace command name resolution path to the given list of
+ * namespaces. If the list is empty (of zero length) the path is set to
+ * empty and the default old-style behaviour of command name resolution
+ * is used.
+ *
+ * Results:
+ * nothing
+ *
+ * Side effects:
+ * Invalidates the command name resolution caches for any command
+ * resolved in the given namespace.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclSetNsPath(
+ Namespace *nsPtr, /* Namespace whose path is to be set. */
+ int pathLength, /* Length of pathAry. */
+ Tcl_Namespace *pathAry[]) /* Array of namespaces that are the path. */
+{
+ if (pathLength != 0) {
+ NamespacePathEntry *tmpPathArray = (NamespacePathEntry *)
+ ckalloc(sizeof(NamespacePathEntry) * pathLength);
+ int i;
+
+ for (i=0 ; i<pathLength ; i++) {
+ tmpPathArray[i].nsPtr = (Namespace *) pathAry[i];
+ tmpPathArray[i].creatorNsPtr = nsPtr;
+ tmpPathArray[i].prevPtr = NULL;
+ tmpPathArray[i].nextPtr =
+ tmpPathArray[i].nsPtr->commandPathSourceList;
+ if (tmpPathArray[i].nextPtr != NULL) {
+ tmpPathArray[i].nextPtr->prevPtr = &tmpPathArray[i];
+ }
+ tmpPathArray[i].nsPtr->commandPathSourceList = &tmpPathArray[i];
+ }
+ if (nsPtr->commandPathLength != 0) {
+ UnlinkNsPath(nsPtr);
+ }
+ nsPtr->commandPathArray = tmpPathArray;
+ } else {
+ if (nsPtr->commandPathLength != 0) {
+ UnlinkNsPath(nsPtr);
+ }
+ }
+
+ nsPtr->commandPathLength = pathLength;
+ nsPtr->cmdRefEpoch++;
+ nsPtr->resolverEpoch++;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UnlinkNsPath --
+ *
+ * Delete the given namespace's command name resolution path. Only call
+ * if the path is non-empty. Caller must reset the counter containing the
+ * path size.
+ *
+ * Results:
+ * nothing
+ *
+ * Side effects:
+ * Deletes the array of path entries and unlinks those path entries from
+ * the target namespace's list of interested namespaces.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UnlinkNsPath(
+ Namespace *nsPtr)
+{
+ int i;
+ for (i=0 ; i<nsPtr->commandPathLength ; i++) {
+ NamespacePathEntry *nsPathPtr = &nsPtr->commandPathArray[i];
+ if (nsPathPtr->prevPtr != NULL) {
+ nsPathPtr->prevPtr->nextPtr = nsPathPtr->nextPtr;
+ }
+ if (nsPathPtr->nextPtr != NULL) {
+ nsPathPtr->nextPtr->prevPtr = nsPathPtr->prevPtr;
+ }
+ if (nsPathPtr->nsPtr != NULL) {
+ if (nsPathPtr->nsPtr->commandPathSourceList == nsPathPtr) {
+ nsPathPtr->nsPtr->commandPathSourceList = nsPathPtr->nextPtr;
+ }
+ }
+ }
+ ckfree((char *) nsPtr->commandPathArray);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclInvalidateNsPath --
+ *
+ * Invalidate the name resolution caches for all names looked up in
+ * namespaces whose name path includes the given namespace.
+ *
+ * Results:
+ * nothing
+ *
+ * Side effects:
+ * Increments the command reference epoch in each namespace whose path
+ * includes the given namespace. This causes any cached resolved names
+ * whose root cacheing context starts at that namespace to be recomputed
+ * the next time they are used.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclInvalidateNsPath(
+ Namespace *nsPtr)
+{
+ NamespacePathEntry *nsPathPtr = nsPtr->commandPathSourceList;
+ while (nsPathPtr != NULL) {
+ if (nsPathPtr->nsPtr != NULL) {
+ nsPathPtr->creatorNsPtr->cmdRefEpoch++;
+ }
+ nsPathPtr = nsPathPtr->nextPtr;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* NamespaceQualifiersCmd --
*
* Invoked to implement the "namespace qualifiers" command that returns
* any leading namespace qualifiers in a string. These qualifiers are
* namespace names separated by "::"s. For example, for "::foo::p" this
- * command returns "::foo", and for "::" it returns "". This command
- * is the complement of the "namespace tail" command. Note that this
- * command does not check whether the "namespace" names are, in fact,
- * the names of currently defined namespaces. Handles the following
- * syntax:
+ * command returns "::foo", and for "::" it returns "". This command is
+ * the complement of the "namespace tail" command. Note that this command
+ * does not check whether the "namespace" names are, in fact, the names
+ * of currently defined namespaces. Handles the following syntax:
*
* namespace qualifiers string
*
* Results:
- * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
+ * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
*
* Side effects:
- * Returns a result in the interpreter's result object. If anything
- * goes wrong, the result is an error message.
+ * Returns a result in the interpreter's result object. If anything goes
+ * wrong, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-NamespaceQualifiersCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+NamespaceQualifiersCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
register char *name, *p;
int length;
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "string");
- return TCL_ERROR;
+ return TCL_ERROR;
}
/*
- * Find the end of the string, then work backward and find
- * the start of the last "::" qualifier.
+ * Find the end of the string, then work backward and find the start of
+ * the last "::" qualifier.
*/
- name = Tcl_GetString(objv[2]);
+ name = TclGetString(objv[2]);
for (p = name; *p != '\0'; p++) {
/* empty body */
}
while (--p >= name) {
- if ((*p == ':') && (p > name) && (*(p-1) == ':')) {
- p -= 2; /* back up over the :: */
+ if ((*p == ':') && (p > name) && (*(p-1) == ':')) {
+ p -= 2; /* Back up over the :: */
while ((p >= name) && (*p == ':')) {
- p--; /* back up over the preceeding : */
+ p--; /* Back up over the preceeding : */
}
break;
- }
+ }
}
if (p >= name) {
- length = p-name+1;
- Tcl_AppendToObj(Tcl_GetObjResult(interp), name, length);
+ length = p-name+1;
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(name, length));
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NamespaceUnknownCmd --
+ *
+ * Invoked to implement the "namespace unknown" command (TIP 181) that
+ * sets or queries a per-namespace unknown command handler. This handler
+ * is called when command lookup fails (current and global ns). The
+ * default handler for the global namespace is ::unknown. The default
+ * handler for other namespaces is to call the global namespace unknown
+ * handler. Passing an empty list results in resetting the handler to its
+ * default.
+ *
+ * namespace unknown ?handler?
+ *
+ * Results:
+ * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ * If no handler is specified, returns a result in the interpreter's
+ * result object, otherwise it sets the unknown handler pointer in the
+ * current namespace to the script fragment provided. If anything goes
+ * wrong, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NamespaceUnknownCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tcl_Namespace *currNsPtr;
+ Tcl_Obj *resultPtr;
+ int rc;
+
+ if (objc > 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?script?");
+ return TCL_ERROR;
+ }
+
+ currNsPtr = TclGetCurrentNamespace(interp);
+
+ if (objc == 2) {
+ /*
+ * Introspection - return the current namespace handler.
+ */
+
+ resultPtr = Tcl_GetNamespaceUnknownHandler(interp, currNsPtr);
+ if (resultPtr == NULL) {
+ TclNewObj(resultPtr);
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ } else {
+ rc = Tcl_SetNamespaceUnknownHandler(interp, currNsPtr, objv[2]);
+ if (rc == TCL_OK) {
+ Tcl_SetObjResult(interp, objv[2]);
+ }
+ return rc;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetNamespaceUnknownHandler --
+ *
+ * Returns the unknown command handler registered for the given
+ * namespace.
+ *
+ * Results:
+ * Returns the current unknown command handler, or NULL if none exists
+ * for the namespace.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tcl_GetNamespaceUnknownHandler(
+ Tcl_Interp *interp, /* The interpreter in which the namespace
+ * exists. */
+ Tcl_Namespace *nsPtr) /* The namespace. */
+{
+ Namespace *currNsPtr = (Namespace *)nsPtr;
+
+ if (currNsPtr->unknownHandlerPtr == NULL &&
+ currNsPtr == ((Interp *)interp)->globalNsPtr) {
+ /*
+ * Default handler for global namespace is "::unknown". For all other
+ * namespaces, it is NULL (which falls back on the global unknown
+ * handler).
+ */
+
+ TclNewLiteralStringObj(currNsPtr->unknownHandlerPtr, "::unknown");
+ Tcl_IncrRefCount(currNsPtr->unknownHandlerPtr);
+ }
+ return currNsPtr->unknownHandlerPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetNamespaceUnknownHandler --
+ *
+ * Sets the unknown command handler for the given namespace to the
+ * command prefix passed.
+ *
+ * Results:
+ * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ * Sets the namespace unknown command handler. If the passed in handler
+ * is NULL or an empty list, then the handler is reset to its default. If
+ * an error occurs, then an error message is left in the interpreter
+ * result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_SetNamespaceUnknownHandler(
+ Tcl_Interp *interp, /* Interpreter in which the namespace
+ * exists. */
+ Tcl_Namespace *nsPtr, /* Namespace which is being updated. */
+ Tcl_Obj *handlerPtr) /* The new handler, or NULL to reset. */
+{
+ int lstlen = 0;
+ Namespace *currNsPtr = (Namespace *)nsPtr;
+
+ /*
+ * Ensure that we check for errors *first* before we change anything.
+ */
+
+ if (handlerPtr != NULL) {
+ if (TclListObjLength(interp, handlerPtr, &lstlen) != TCL_OK) {
+ /*
+ * Not a list.
+ */
+
+ return TCL_ERROR;
+ }
+ if (lstlen > 0) {
+ /*
+ * We are going to be saving this handler. Increment the reference
+ * count before decrementing the refcount on the previous handler,
+ * so that nothing strange can happen if we are told to set the
+ * handler to the previous value.
+ */
+
+ Tcl_IncrRefCount(handlerPtr);
+ }
+ }
+
+ /*
+ * Remove old handler next.
+ */
+
+ if (currNsPtr->unknownHandlerPtr != NULL) {
+ Tcl_DecrRefCount(currNsPtr->unknownHandlerPtr);
+ }
+
+ /*
+ * Install the new handler.
+ */
+
+ if (lstlen > 0) {
+ /*
+ * Just store the handler. It already has the correct reference count.
+ */
+
+ currNsPtr->unknownHandlerPtr = handlerPtr;
+ } else {
+ /*
+ * If NULL or an empty list is passed, this resets to the default
+ * handler.
+ */
+
+ currNsPtr->unknownHandlerPtr = NULL;
}
return TCL_OK;
}
@@ -3651,13 +4356,13 @@ NamespaceQualifiersCmd(dummy, interp, objc, objv)
* NamespaceTailCmd --
*
* Invoked to implement the "namespace tail" command that returns the
- * trailing name at the end of a string with "::" namespace
- * qualifiers. These qualifiers are namespace names separated by
- * "::"s. For example, for "::foo::p" this command returns "p", and for
- * "::" it returns "". This command is the complement of the "namespace
- * qualifiers" command. Note that this command does not check whether
- * the "namespace" names are, in fact, the names of currently defined
- * namespaces. Handles the following syntax:
+ * trailing name at the end of a string with "::" namespace qualifiers.
+ * These qualifiers are namespace names separated by "::"s. For example,
+ * for "::foo::p" this command returns "p", and for "::" it returns "".
+ * This command is the complement of the "namespace qualifiers" command.
+ * Note that this command does not check whether the "namespace" names
+ * are, in fact, the names of currently defined namespaces. Handles the
+ * following syntax:
*
* namespace tail string
*
@@ -3665,44 +4370,44 @@ NamespaceQualifiersCmd(dummy, interp, objc, objv)
* Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
*
* Side effects:
- * Returns a result in the interpreter's result object. If anything
- * goes wrong, the result is an error message.
+ * Returns a result in the interpreter's result object. If anything goes
+ * wrong, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-NamespaceTailCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+NamespaceTailCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
register char *name, *p;
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "string");
- return TCL_ERROR;
+ return TCL_ERROR;
}
/*
- * Find the end of the string, then work backward and find the
- * last "::" qualifier.
+ * Find the end of the string, then work backward and find the last "::"
+ * qualifier.
*/
- name = Tcl_GetString(objv[2]);
+ name = TclGetString(objv[2]);
for (p = name; *p != '\0'; p++) {
/* empty body */
}
while (--p > name) {
- if ((*p == ':') && (*(p-1) == ':')) {
- p++; /* just after the last "::" */
- break;
- }
+ if ((*p == ':') && (*(p-1) == ':')) {
+ p++; /* Just after the last "::" */
+ break;
+ }
}
-
+
if (p >= name) {
- Tcl_AppendToObj(Tcl_GetObjResult(interp), p, -1);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(p, -1));
}
return TCL_OK;
}
@@ -3710,6 +4415,81 @@ NamespaceTailCmd(dummy, interp, objc, objv)
/*
*----------------------------------------------------------------------
*
+ * NamespaceUpvarCmd --
+ *
+ * Invoked to implement the "namespace upvar" command, that creates
+ * variables in the current scope linked to variables in another
+ * namespace. Handles the following syntax:
+ *
+ * namespace upvar ns otherVar myVar ?otherVar myVar ...?
+ *
+ * Results:
+ * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ * Creates new variables in the current scope, linked to the
+ * corresponding variables in the stipulated nmamespace. If anything goes
+ * wrong, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NamespaceUpvarCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Interp *iPtr = (Interp *) interp;
+ Tcl_Namespace *nsPtr, *savedNsPtr;
+ Var *otherPtr, *arrayPtr;
+ char *myName;
+
+ if (objc < 5 || !(objc & 1)) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "ns otherVar myVar ?otherVar myVar ...?");
+ return TCL_ERROR;
+ }
+
+ if (TclGetNamespaceFromObj(interp, objv[2], &nsPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ objc -= 3;
+ objv += 3;
+
+ for (; objc>0 ; objc-=2, objv+=2) {
+ /*
+ * Locate the other variable
+ */
+
+ savedNsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr;
+ iPtr->varFramePtr->nsPtr = (Namespace *) nsPtr;
+ otherPtr = TclObjLookupVarEx(interp, objv[0], NULL,
+ (TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG), "access",
+ /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
+ iPtr->varFramePtr->nsPtr = (Namespace *) savedNsPtr;
+ if (otherPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create the new variable and link it to otherPtr.
+ */
+
+ myName = TclGetString(objv[1]);
+ if (TclPtrMakeUpvar(interp, otherPtr, myName, 0, -1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* NamespaceWhichCmd --
*
* Invoked to implement the "namespace which" command that returns the
@@ -3723,70 +4503,66 @@ NamespaceTailCmd(dummy, interp, objc, objv)
* Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
*
* Side effects:
- * Returns a result in the interpreter's result object. If anything
- * goes wrong, the result is an error message.
+ * Returns a result in the interpreter's result object. If anything goes
+ * wrong, the result is an error message.
*
*----------------------------------------------------------------------
*/
static int
-NamespaceWhichCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+NamespaceWhichCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- register char *arg;
- Tcl_Command cmd;
- Tcl_Var variable;
- int argIndex, lookup;
+ static const char *opts[] = {
+ "-command", "-variable", NULL
+ };
+ int lookupType = 0;
+ Tcl_Obj *resultPtr;
- if (objc < 3) {
- badArgs:
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-command? ?-variable? name");
- return TCL_ERROR;
- }
+ if (objc < 3 || objc > 4) {
+ badArgs:
+ Tcl_WrongNumArgs(interp, 2, objv, "?-command? ?-variable? name");
+ return TCL_ERROR;
+ } else if (objc == 4) {
+ /*
+ * Look for a flag controlling the lookup.
+ */
- /*
- * Look for a flag controlling the lookup.
- */
+ if (Tcl_GetIndexFromObj(interp, objv[2], opts, "option", 0,
+ &lookupType) != TCL_OK) {
+ /*
+ * Preserve old style of error message!
+ */
- argIndex = 2;
- lookup = 0; /* assume command lookup by default */
- arg = Tcl_GetString(objv[2]);
- if (*arg == '-') {
- if (strncmp(arg, "-command", 8) == 0) {
- lookup = 0;
- } else if (strncmp(arg, "-variable", 9) == 0) {
- lookup = 1;
- } else {
+ Tcl_ResetResult(interp);
goto badArgs;
}
- argIndex = 3;
- }
- if (objc != (argIndex + 1)) {
- goto badArgs;
}
- switch (lookup) {
- case 0: /* -command */
- cmd = Tcl_GetCommandFromObj(interp, objv[argIndex]);
- if (cmd == (Tcl_Command) NULL) {
- return TCL_OK; /* cmd not found, just return (no error) */
- }
- Tcl_GetCommandFullName(interp, cmd, Tcl_GetObjResult(interp));
- break;
+ TclNewObj(resultPtr);
+ switch (lookupType) {
+ case 0: { /* -command */
+ Tcl_Command cmd = Tcl_GetCommandFromObj(interp, objv[objc-1]);
- case 1: /* -variable */
- arg = Tcl_GetString(objv[argIndex]);
- variable = Tcl_FindNamespaceVar(interp, arg, (Tcl_Namespace *) NULL,
- /*flags*/ 0);
- if (variable != (Tcl_Var) NULL) {
- Tcl_GetVariableFullName(interp, variable, Tcl_GetObjResult(interp));
- }
- break;
+ if (cmd != NULL) {
+ Tcl_GetCommandFullName(interp, cmd, resultPtr);
+ }
+ break;
+ }
+ case 1: { /* -variable */
+ Tcl_Var var = Tcl_FindNamespaceVar(interp,
+ TclGetString(objv[objc-1]), NULL, /*flags*/ 0);
+
+ if (var != NULL) {
+ Tcl_GetVariableFullName(interp, var, resultPtr);
+ }
+ break;
+ }
}
+ Tcl_SetObjResult(interp, resultPtr);
return TCL_OK;
}
@@ -3802,45 +4578,44 @@ NamespaceWhichCmd(dummy, interp, objc, objv)
* None.
*
* Side effects:
- * Decrements the ref count of any Namespace structure pointed
- * to by the nsName's internal representation. If there are no more
- * references to the namespace, it's structure will be freed.
+ * Decrements the ref count of any Namespace structure pointed to by the
+ * nsName's internal representation. If there are no more references to
+ * the namespace, it's structure will be freed.
*
*----------------------------------------------------------------------
*/
static void
-FreeNsNameInternalRep(objPtr)
- register Tcl_Obj *objPtr; /* nsName object with internal
- * representation to free */
+FreeNsNameInternalRep(
+ register Tcl_Obj *objPtr) /* nsName object with internal representation
+ * to free. */
{
- register ResolvedNsName *resNamePtr =
- (ResolvedNsName *) objPtr->internalRep.otherValuePtr;
+ register ResolvedNsName *resNamePtr = (ResolvedNsName *)
+ objPtr->internalRep.twoPtrValue.ptr1;
Namespace *nsPtr;
/*
- * Decrement the reference count of the namespace. If there are no
- * more references, free it up.
+ * Decrement the reference count of the namespace. If there are no more
+ * references, free it up.
*/
- if (resNamePtr != NULL) {
- resNamePtr->refCount--;
- if (resNamePtr->refCount == 0) {
+ resNamePtr->refCount--;
+ if (resNamePtr->refCount == 0) {
- /*
- * Decrement the reference count for the cached namespace. If
- * the namespace is dead, and there are no more references to
- * it, free it.
- */
+ /*
+ * Decrement the reference count for the cached namespace. If the
+ * namespace is dead, and there are no more references to it, free
+ * it.
+ */
- nsPtr = resNamePtr->nsPtr;
- nsPtr->refCount--;
- if ((nsPtr->refCount == 0) && (nsPtr->flags & NS_DEAD)) {
- NamespaceFree(nsPtr);
- }
- ckfree((char *) resNamePtr);
- }
+ nsPtr = resNamePtr->nsPtr;
+ nsPtr->refCount--;
+ if ((nsPtr->refCount == 0) && (nsPtr->flags & NS_DEAD)) {
+ NamespaceFree(nsPtr);
+ }
+ ckfree((char *) resNamePtr);
}
+ objPtr->typePtr = NULL;
}
/*
@@ -3856,25 +4631,23 @@ FreeNsNameInternalRep(objPtr)
*
* Side effects:
* copyPtr's internal rep is set to refer to the same namespace
- * referenced by srcPtr's internal rep. Increments the ref count of
- * the ResolvedNsName structure used to hold the namespace reference.
+ * referenced by srcPtr's internal rep. Increments the ref count of the
+ * ResolvedNsName structure used to hold the namespace reference.
*
*----------------------------------------------------------------------
*/
static void
-DupNsNameInternalRep(srcPtr, copyPtr)
- Tcl_Obj *srcPtr; /* Object with internal rep to copy. */
- register Tcl_Obj *copyPtr; /* Object with internal rep to set. */
+DupNsNameInternalRep(
+ Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
+ register Tcl_Obj *copyPtr) /* Object with internal rep to set. */
{
- register ResolvedNsName *resNamePtr =
- (ResolvedNsName *) srcPtr->internalRep.otherValuePtr;
+ register ResolvedNsName *resNamePtr = (ResolvedNsName *)
+ srcPtr->internalRep.twoPtrValue.ptr1;
- copyPtr->internalRep.otherValuePtr = (VOID *) resNamePtr;
- if (resNamePtr != NULL) {
- resNamePtr->refCount++;
- }
- copyPtr->typePtr = &tclNsNameType;
+ copyPtr->internalRep.twoPtrValue.ptr1 = resNamePtr;
+ resNamePtr->refCount++;
+ copyPtr->typePtr = &nsNameType;
}
/*
@@ -3882,146 +4655,2349 @@ DupNsNameInternalRep(srcPtr, copyPtr)
*
* SetNsNameFromAny --
*
- * Attempt to generate a nsName internal representation for a
- * Tcl object.
+ * Attempt to generate a nsName internal representation for a Tcl object.
*
* Results:
- * Returns TCL_OK if the value could be converted to a proper
- * namespace reference. Otherwise, it returns TCL_ERROR, along
- * with an error message in the interpreter's result object.
+ * Returns TCL_OK if the value could be converted to a proper namespace
+ * reference. Otherwise, it returns TCL_ERROR, along with an error
+ * message in the interpreter's result object.
*
* Side effects:
- * If successful, the object is made a nsName object. Its internal rep
- * is set to point to a ResolvedNsName, which contains a cached pointer
- * to the Namespace. Reference counts are kept on both the
- * ResolvedNsName and the Namespace, so we can keep track of their
- * usage and free them when appropriate.
+ * If successful, the object is made a nsName object. Its internal rep is
+ * set to point to a ResolvedNsName, which contains a cached pointer to
+ * the Namespace. Reference counts are kept on both the ResolvedNsName
+ * and the Namespace, so we can keep track of their usage and free them
+ * when appropriate.
*
*----------------------------------------------------------------------
*/
static int
-SetNsNameFromAny(interp, objPtr)
- Tcl_Interp *interp; /* Points to the namespace in which to
- * resolve name. Also used for error
- * reporting if not NULL. */
- register Tcl_Obj *objPtr; /* The object to convert. */
+SetNsNameFromAny(
+ Tcl_Interp *interp, /* Points to the namespace in which to resolve
+ * name. Also used for error reporting if not
+ * NULL. */
+ register Tcl_Obj *objPtr) /* The object to convert. */
{
- register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
- char *name;
- CONST char *dummy;
+ const char *dummy;
Namespace *nsPtr, *dummy1Ptr, *dummy2Ptr;
register ResolvedNsName *resNamePtr;
+ const char *name;
if (interp == NULL) {
return TCL_ERROR;
}
+ name = TclGetString(objPtr);
+ TclGetNamespaceForQualName(interp, name, NULL, TCL_FIND_ONLY_NS,
+ &nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy);
+
/*
- * Get the string representation. Make it up-to-date if necessary.
+ * If we found a namespace, then create a new ResolvedNsName structure
+ * that holds a reference to it.
*/
- name = objPtr->bytes;
- if (name == NULL) {
- name = Tcl_GetString(objPtr);
+ if ((nsPtr == NULL) || (nsPtr->flags & NS_DYING)) {
+ /*
+ * Our failed lookup proves any previously cached nsName intrep is no
+ * longer valid. Get rid of it so we no longer waste memory storing
+ * it, nor time determining its invalidity again and again.
+ */
+
+ if (objPtr->typePtr == &nsNameType) {
+ TclFreeIntRep(objPtr);
+ objPtr->typePtr = NULL;
+ }
+ return TCL_ERROR;
+ }
+
+ nsPtr->refCount++;
+ resNamePtr = (ResolvedNsName *) ckalloc(sizeof(ResolvedNsName));
+ resNamePtr->nsPtr = nsPtr;
+ if ((name[0] == ':') && (name[1] == ':')) {
+ resNamePtr->refNsPtr = NULL;
+ } else {
+ resNamePtr->refNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+ }
+ resNamePtr->refCount = 1;
+ TclFreeIntRep(objPtr);
+ objPtr->internalRep.twoPtrValue.ptr1 = resNamePtr;
+ objPtr->typePtr = &nsNameType;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NamespaceEnsembleCmd --
+ *
+ * Invoked to implement the "namespace ensemble" command that creates and
+ * manipulates ensembles built on top of namespaces. Handles the
+ * following syntax:
+ *
+ * namespace ensemble name ?dictionary?
+ *
+ * Results:
+ * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ * Creates the ensemble for the namespace if one did not previously
+ * exist. Alternatively, alters the way that the ensemble's subcommand =>
+ * implementation prefix is configured.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NamespaceEnsembleCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ Namespace *nsPtr;
+ Tcl_Command token;
+ static const char *subcommands[] = {
+ "configure", "create", "exists", NULL
+ };
+ enum EnsSubcmds {
+ ENS_CONFIG, ENS_CREATE, ENS_EXISTS
+ };
+ static const char *createOptions[] = {
+ "-command", "-map", "-prefixes", "-subcommands", "-unknown", NULL
+ };
+ enum EnsCreateOpts {
+ CRT_CMD, CRT_MAP, CRT_PREFIX, CRT_SUBCMDS, CRT_UNKNOWN
+ };
+ static const char *configOptions[] = {
+ "-map", "-namespace", "-prefixes", "-subcommands", "-unknown", NULL
+ };
+ enum EnsConfigOpts {
+ CONF_MAP, CONF_NAMESPACE, CONF_PREFIX, CONF_SUBCMDS, CONF_UNKNOWN
+ };
+ int index;
+
+ nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
+ if (nsPtr == NULL || nsPtr->flags & NS_DYING) {
+ if (!Tcl_InterpDeleted(interp)) {
+ Tcl_AppendResult(interp,
+ "tried to manipulate ensemble of deleted namespace", NULL);
+ }
+ return TCL_ERROR;
+ }
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "subcommand ?arg ...?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[2], subcommands, "subcommand", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum EnsSubcmds) index) {
+ case ENS_CREATE: {
+ char *name;
+ Tcl_DictSearch search;
+ Tcl_Obj *listObj;
+ int done, len, allocatedMapFlag = 0;
+ /*
+ * Defaults
+ */
+ Tcl_Obj *subcmdObj = NULL;
+ Tcl_Obj *mapObj = NULL;
+ int permitPrefix = 1;
+ Tcl_Obj *unknownObj = NULL;
+
+ objv += 3;
+ objc -= 3;
+
+ /*
+ * Work out what name to use for the command to create. If supplied,
+ * it is either fully specified or relative to the current namespace.
+ * If not supplied, it is exactly the name of the current namespace.
+ */
+
+ name = nsPtr->fullName;
+
+ /*
+ * Parse the option list, applying type checks as we go. Note that we
+ * are not incrementing any reference counts in the objects at this
+ * stage, so the presence of an option multiple times won't cause any
+ * memory leaks.
+ */
+
+ for (; objc>1 ; objc-=2,objv+=2 ) {
+ if (Tcl_GetIndexFromObj(interp, objv[0], createOptions, "option",
+ 0, &index) != TCL_OK) {
+ if (allocatedMapFlag) {
+ Tcl_DecrRefCount(mapObj);
+ }
+ return TCL_ERROR;
+ }
+ switch ((enum EnsCreateOpts) index) {
+ case CRT_CMD:
+ name = TclGetString(objv[1]);
+ continue;
+ case CRT_SUBCMDS:
+ if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
+ if (allocatedMapFlag) {
+ Tcl_DecrRefCount(mapObj);
+ }
+ return TCL_ERROR;
+ }
+ subcmdObj = (len > 0 ? objv[1] : NULL);
+ continue;
+ case CRT_MAP: {
+ Tcl_Obj *patchedDict = NULL, *subcmdObj;
+
+ /*
+ * Verify that the map is sensible.
+ */
+
+ if (Tcl_DictObjFirst(interp, objv[1], &search,
+ &subcmdObj, &listObj, &done) != TCL_OK) {
+ if (allocatedMapFlag) {
+ Tcl_DecrRefCount(mapObj);
+ }
+ return TCL_ERROR;
+ }
+ if (done) {
+ mapObj = NULL;
+ continue;
+ }
+ do {
+ Tcl_Obj **listv;
+ char *cmd;
+
+ if (TclListObjGetElements(interp, listObj, &len,
+ &listv) != TCL_OK) {
+ Tcl_DictObjDone(&search);
+ if (patchedDict) {
+ Tcl_DecrRefCount(patchedDict);
+ }
+ if (allocatedMapFlag) {
+ Tcl_DecrRefCount(mapObj);
+ }
+ return TCL_ERROR;
+ }
+ if (len < 1) {
+ Tcl_SetResult(interp,
+ "ensemble subcommand implementations "
+ "must be non-empty lists", TCL_STATIC);
+ Tcl_DictObjDone(&search);
+ if (patchedDict) {
+ Tcl_DecrRefCount(patchedDict);
+ }
+ if (allocatedMapFlag) {
+ Tcl_DecrRefCount(mapObj);
+ }
+ return TCL_ERROR;
+ }
+ cmd = TclGetString(listv[0]);
+ if (!(cmd[0] == ':' && cmd[1] == ':')) {
+ Tcl_Obj *newList = Tcl_NewListObj(len, listv);
+ Tcl_Obj *newCmd = Tcl_NewStringObj(nsPtr->fullName,-1);
+
+ if (nsPtr->parentPtr) {
+ Tcl_AppendStringsToObj(newCmd, "::", NULL);
+ }
+ Tcl_AppendObjToObj(newCmd, listv[0]);
+ Tcl_ListObjReplace(NULL, newList, 0, 1, 1, &newCmd);
+ if (patchedDict == NULL) {
+ patchedDict = Tcl_DuplicateObj(objv[1]);
+ }
+ Tcl_DictObjPut(NULL, patchedDict, subcmdObj, newList);
+ }
+ Tcl_DictObjNext(&search, &subcmdObj, &listObj, &done);
+ } while (!done);
+
+ if (allocatedMapFlag) {
+ Tcl_DecrRefCount(mapObj);
+ }
+ mapObj = (patchedDict ? patchedDict : objv[1]);
+ if (patchedDict) {
+ allocatedMapFlag = 1;
+ }
+ continue;
+ }
+ case CRT_PREFIX:
+ if (Tcl_GetBooleanFromObj(interp, objv[1],
+ &permitPrefix) != TCL_OK) {
+ if (allocatedMapFlag) {
+ Tcl_DecrRefCount(mapObj);
+ }
+ return TCL_ERROR;
+ }
+ continue;
+ case CRT_UNKNOWN:
+ if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
+ if (allocatedMapFlag) {
+ Tcl_DecrRefCount(mapObj);
+ }
+ return TCL_ERROR;
+ }
+ unknownObj = (len > 0 ? objv[1] : NULL);
+ continue;
+ }
+ }
+
+ /*
+ * Create the ensemble. Note that this might delete another ensemble
+ * linked to the same namespace, so we must be careful. However, we
+ * should be OK because we only link the namespace into the list once
+ * we've created it (and after any deletions have occurred.)
+ */
+
+ token = Tcl_CreateEnsemble(interp, name, NULL,
+ (permitPrefix ? TCL_ENSEMBLE_PREFIX : 0));
+ Tcl_SetEnsembleSubcommandList(interp, token, subcmdObj);
+ Tcl_SetEnsembleMappingDict(interp, token, mapObj);
+ Tcl_SetEnsembleUnknownHandler(interp, token, unknownObj);
+
+ /*
+ * Tricky! Must ensure that the result is not shared (command delete
+ * traces could have corrupted the pristine object that we started
+ * with). [Snit test rename-1.5]
+ */
+
+ Tcl_ResetResult(interp);
+ Tcl_GetCommandFullName(interp, token, Tcl_GetObjResult(interp));
+ return TCL_OK;
+ }
+
+ case ENS_EXISTS:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "cmdname");
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
+ Tcl_FindEnsemble(interp, objv[3], 0) != NULL));
+ return TCL_OK;
+
+ case ENS_CONFIG:
+ if (objc < 4 || (objc != 5 && objc & 1)) {
+ Tcl_WrongNumArgs(interp, 3, objv, "cmdname ?opt? ?value? ...");
+ return TCL_ERROR;
+ }
+ token = Tcl_FindEnsemble(interp, objv[3], TCL_LEAVE_ERR_MSG);
+ if (token == NULL) {
+ return TCL_ERROR;
+ }
+
+ if (objc == 5) {
+ Tcl_Obj *resultObj = NULL; /* silence gcc 4 warning */
+
+ if (Tcl_GetIndexFromObj(interp, objv[4], configOptions, "option",
+ 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum EnsConfigOpts) index) {
+ case CONF_SUBCMDS:
+ Tcl_GetEnsembleSubcommandList(NULL, token, &resultObj);
+ if (resultObj != NULL) {
+ Tcl_SetObjResult(interp, resultObj);
+ }
+ break;
+ case CONF_MAP:
+ Tcl_GetEnsembleMappingDict(NULL, token, &resultObj);
+ if (resultObj != NULL) {
+ Tcl_SetObjResult(interp, resultObj);
+ }
+ break;
+ case CONF_NAMESPACE: {
+ Tcl_Namespace *namespacePtr = NULL; /* silence gcc 4 warning */
+
+ Tcl_GetEnsembleNamespace(NULL, token, &namespacePtr);
+ Tcl_SetResult(interp, ((Namespace *)namespacePtr)->fullName,
+ TCL_VOLATILE);
+ break;
+ }
+ case CONF_PREFIX: {
+ int flags = 0; /* silence gcc 4 warning */
+
+ Tcl_GetEnsembleFlags(NULL, token, &flags);
+ Tcl_SetObjResult(interp,
+ Tcl_NewBooleanObj(flags & TCL_ENSEMBLE_PREFIX));
+ break;
+ }
+ case CONF_UNKNOWN:
+ Tcl_GetEnsembleUnknownHandler(NULL, token, &resultObj);
+ if (resultObj != NULL) {
+ Tcl_SetObjResult(interp, resultObj);
+ }
+ break;
+ }
+ return TCL_OK;
+
+ } else if (objc == 4) {
+ /*
+ * Produce list of all information.
+ */
+
+ Tcl_Obj *resultObj, *tmpObj = NULL; /* silence gcc 4 warning */
+ Tcl_Namespace *namespacePtr = NULL; /* silence gcc 4 warning */
+ int flags = 0; /* silence gcc 4 warning */
+
+ TclNewObj(resultObj);
+
+ /* -map option */
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ Tcl_NewStringObj(configOptions[CONF_MAP], -1));
+ Tcl_GetEnsembleMappingDict(NULL, token, &tmpObj);
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ (tmpObj != NULL) ? tmpObj : Tcl_NewObj());
+
+ /* -namespace option */
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ Tcl_NewStringObj(configOptions[CONF_NAMESPACE], -1));
+ Tcl_GetEnsembleNamespace(NULL, token, &namespacePtr);
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ Tcl_NewStringObj(((Namespace *)namespacePtr)->fullName,
+ -1));
+
+ /* -prefix option */
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ Tcl_NewStringObj(configOptions[CONF_PREFIX], -1));
+ Tcl_GetEnsembleFlags(NULL, token, &flags);
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ Tcl_NewBooleanObj(flags & TCL_ENSEMBLE_PREFIX));
+
+ /* -subcommands option */
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ Tcl_NewStringObj(configOptions[CONF_SUBCMDS], -1));
+ Tcl_GetEnsembleSubcommandList(NULL, token, &tmpObj);
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ (tmpObj != NULL) ? tmpObj : Tcl_NewObj());
+
+ /* -unknown option */
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ Tcl_NewStringObj(configOptions[CONF_UNKNOWN], -1));
+ Tcl_GetEnsembleUnknownHandler(NULL, token, &tmpObj);
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ (tmpObj != NULL) ? tmpObj : Tcl_NewObj());
+
+ Tcl_SetObjResult(interp, resultObj);
+ return TCL_OK;
+ } else {
+ Tcl_DictSearch search;
+ Tcl_Obj *listObj;
+ int done, len, allocatedMapFlag = 0;
+ Tcl_Obj *subcmdObj = NULL, *mapObj = NULL,
+ *unknownObj = NULL; /* Defaults, silence gcc 4 warnings */
+ int permitPrefix, flags = 0; /* silence gcc 4 warning */
+
+ Tcl_GetEnsembleSubcommandList(NULL, token, &subcmdObj);
+ Tcl_GetEnsembleMappingDict(NULL, token, &mapObj);
+ Tcl_GetEnsembleUnknownHandler(NULL, token, &unknownObj);
+ Tcl_GetEnsembleFlags(NULL, token, &flags);
+ permitPrefix = (flags & TCL_ENSEMBLE_PREFIX) != 0;
+
+ objv += 4;
+ objc -= 4;
+
+ /*
+ * Parse the option list, applying type checks as we go. Note that
+ * we are not incrementing any reference counts in the objects at
+ * this stage, so the presence of an option multiple times won't
+ * cause any memory leaks.
+ */
+
+ for (; objc>0 ; objc-=2,objv+=2 ) {
+ if (Tcl_GetIndexFromObj(interp, objv[0], configOptions,
+ "option", 0, &index) != TCL_OK) {
+ if (allocatedMapFlag) {
+ Tcl_DecrRefCount(mapObj);
+ }
+ return TCL_ERROR;
+ }
+ switch ((enum EnsConfigOpts) index) {
+ case CONF_SUBCMDS:
+ if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
+ if (allocatedMapFlag) {
+ Tcl_DecrRefCount(mapObj);
+ }
+ return TCL_ERROR;
+ }
+ subcmdObj = (len > 0 ? objv[1] : NULL);
+ continue;
+ case CONF_MAP: {
+ Tcl_Obj *patchedDict = NULL, *subcmdObj;
+
+ /*
+ * Verify that the map is sensible.
+ */
+
+ if (Tcl_DictObjFirst(interp, objv[1], &search,
+ &subcmdObj, &listObj, &done) != TCL_OK) {
+ if (allocatedMapFlag) {
+ Tcl_DecrRefCount(mapObj);
+ }
+ return TCL_ERROR;
+ }
+ if (done) {
+ mapObj = NULL;
+ continue;
+ }
+ do {
+ Tcl_Obj **listv;
+ char *cmd;
+
+ if (TclListObjGetElements(interp, listObj, &len,
+ &listv) != TCL_OK) {
+ Tcl_DictObjDone(&search);
+ if (patchedDict) {
+ Tcl_DecrRefCount(patchedDict);
+ }
+ if (allocatedMapFlag) {
+ Tcl_DecrRefCount(mapObj);
+ }
+ return TCL_ERROR;
+ }
+ if (len < 1) {
+ Tcl_SetResult(interp,
+ "ensemble subcommand implementations "
+ "must be non-empty lists", TCL_STATIC);
+ Tcl_DictObjDone(&search);
+ if (patchedDict) {
+ Tcl_DecrRefCount(patchedDict);
+ }
+ if (allocatedMapFlag) {
+ Tcl_DecrRefCount(mapObj);
+ }
+ return TCL_ERROR;
+ }
+ cmd = TclGetString(listv[0]);
+ if (!(cmd[0] == ':' && cmd[1] == ':')) {
+ Tcl_Obj *newList = Tcl_NewListObj(len, listv);
+ Tcl_Obj *newCmd =
+ Tcl_NewStringObj(nsPtr->fullName, -1);
+ if (nsPtr->parentPtr) {
+ Tcl_AppendStringsToObj(newCmd, "::", NULL);
+ }
+ Tcl_AppendObjToObj(newCmd, listv[0]);
+ Tcl_ListObjReplace(NULL, newList, 0,1, 1,&newCmd);
+ if (patchedDict == NULL) {
+ patchedDict = Tcl_DuplicateObj(objv[1]);
+ }
+ Tcl_DictObjPut(NULL, patchedDict, subcmdObj,
+ newList);
+ }
+ Tcl_DictObjNext(&search, &subcmdObj, &listObj, &done);
+ } while (!done);
+ if (allocatedMapFlag) {
+ Tcl_DecrRefCount(mapObj);
+ }
+ mapObj = (patchedDict ? patchedDict : objv[1]);
+ if (patchedDict) {
+ allocatedMapFlag = 1;
+ }
+ continue;
+ }
+ case CONF_NAMESPACE:
+ if (allocatedMapFlag) {
+ Tcl_DecrRefCount(mapObj);
+ }
+ Tcl_AppendResult(interp, "option -namespace is read-only",
+ NULL);
+ return TCL_ERROR;
+ case CONF_PREFIX:
+ if (Tcl_GetBooleanFromObj(interp, objv[1],
+ &permitPrefix) != TCL_OK) {
+ if (allocatedMapFlag) {
+ Tcl_DecrRefCount(mapObj);
+ }
+ return TCL_ERROR;
+ }
+ continue;
+ case CONF_UNKNOWN:
+ if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
+ if (allocatedMapFlag) {
+ Tcl_DecrRefCount(mapObj);
+ }
+ return TCL_ERROR;
+ }
+ unknownObj = (len > 0 ? objv[1] : NULL);
+ continue;
+ }
+ }
+
+ /*
+ * Update the namespace now that we've finished the parsing stage.
+ */
+
+ flags = (permitPrefix ? flags|TCL_ENSEMBLE_PREFIX
+ : flags&~TCL_ENSEMBLE_PREFIX);
+ Tcl_SetEnsembleSubcommandList(interp, token, subcmdObj);
+ Tcl_SetEnsembleMappingDict(interp, token, mapObj);
+ Tcl_SetEnsembleUnknownHandler(interp, token, unknownObj);
+ Tcl_SetEnsembleFlags(interp, token, flags);
+ return TCL_OK;
+ }
+
+ default:
+ Tcl_Panic("unexpected ensemble command");
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_CreateEnsemble --
+ *
+ * Create a simple ensemble attached to the given namespace.
+ *
+ * Results:
+ * The token for the command created.
+ *
+ * Side effects:
+ * The ensemble is created and marked for compilation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Command
+Tcl_CreateEnsemble(
+ Tcl_Interp *interp,
+ const char *name,
+ Tcl_Namespace *namespacePtr,
+ int flags)
+{
+ Namespace *nsPtr = (Namespace *) namespacePtr;
+ EnsembleConfig *ensemblePtr = (EnsembleConfig *)
+ ckalloc(sizeof(EnsembleConfig));
+ Tcl_Obj *nameObj = NULL;
+
+ if (nsPtr == NULL) {
+ nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
}
/*
- * Look for the namespace "name" in the current namespace. If there is
- * an error parsing the (possibly qualified) name, return an error.
- * If the namespace isn't found, we convert the object to an nsName
- * object with a NULL ResolvedNsName* internal rep.
+ * Make the name of the ensemble into a fully qualified name. This might
+ * allocate a temporary object.
*/
- TclGetNamespaceForQualName(interp, name, (Namespace *) NULL,
- FIND_ONLY_NS, &nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy);
+ if (!(name[0] == ':' && name[1] == ':')) {
+ nameObj = Tcl_NewStringObj(nsPtr->fullName, -1);
+ if (nsPtr->parentPtr == NULL) {
+ Tcl_AppendStringsToObj(nameObj, name, NULL);
+ } else {
+ Tcl_AppendStringsToObj(nameObj, "::", name, NULL);
+ }
+ Tcl_IncrRefCount(nameObj);
+ name = TclGetString(nameObj);
+ }
+
+ ensemblePtr->nsPtr = nsPtr;
+ ensemblePtr->epoch = 0;
+ Tcl_InitHashTable(&ensemblePtr->subcommandTable, TCL_STRING_KEYS);
+ ensemblePtr->subcommandArrayPtr = NULL;
+ ensemblePtr->subcmdList = NULL;
+ ensemblePtr->subcommandDict = NULL;
+ ensemblePtr->flags = flags;
+ ensemblePtr->unknownHandler = NULL;
+ ensemblePtr->token = Tcl_CreateObjCommand(interp, name,
+ NsEnsembleImplementationCmd, ensemblePtr, DeleteEnsembleConfig);
+ ensemblePtr->next = (EnsembleConfig *) nsPtr->ensembles;
+ nsPtr->ensembles = (Tcl_Ensemble *) ensemblePtr;
/*
- * If we found a namespace, then create a new ResolvedNsName structure
- * that holds a reference to it.
+ * Trigger an eventual recomputation of the ensemble command set. Note
+ * that this is slightly tricky, as it means that we are not actually
+ * counting the number of namespace export actions, but it is the simplest
+ * way to go!
*/
- if (nsPtr != NULL) {
- Namespace *currNsPtr =
- (Namespace *) Tcl_GetCurrentNamespace(interp);
-
- nsPtr->refCount++;
- resNamePtr = (ResolvedNsName *) ckalloc(sizeof(ResolvedNsName));
- resNamePtr->nsPtr = nsPtr;
- resNamePtr->nsId = nsPtr->nsId;
- resNamePtr->refNsPtr = currNsPtr;
- resNamePtr->refCount = 1;
- } else {
- resNamePtr = NULL;
+ nsPtr->exportLookupEpoch++;
+
+ if (flags & ENSEMBLE_COMPILE) {
+ ((Command *) ensemblePtr->token)->compileProc = TclCompileEnsemble;
+ }
+
+ if (nameObj != NULL) {
+ TclDecrRefCount(nameObj);
+ }
+ return ensemblePtr->token;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetEnsembleSubcommandList --
+ *
+ * Set the subcommand list for a particular ensemble.
+ *
+ * Results:
+ * Tcl result code (error if command token does not indicate an ensemble
+ * or the subcommand list - if non-NULL - is not a list).
+ *
+ * Side effects:
+ * The ensemble is updated and marked for recompilation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_SetEnsembleSubcommandList(
+ Tcl_Interp *interp,
+ Tcl_Command token,
+ Tcl_Obj *subcmdList)
+{
+ Command *cmdPtr = (Command *) token;
+ EnsembleConfig *ensemblePtr;
+ Tcl_Obj *oldList;
+
+ if (cmdPtr->objProc != NsEnsembleImplementationCmd) {
+ Tcl_AppendResult(interp, "command is not an ensemble", NULL);
+ return TCL_ERROR;
+ }
+ if (subcmdList != NULL) {
+ int length;
+
+ if (TclListObjLength(interp, subcmdList, &length) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (length < 1) {
+ subcmdList = NULL;
+ }
}
+ ensemblePtr = cmdPtr->objClientData;
+ oldList = ensemblePtr->subcmdList;
+ ensemblePtr->subcmdList = subcmdList;
+ if (subcmdList != NULL) {
+ Tcl_IncrRefCount(subcmdList);
+ }
+ if (oldList != NULL) {
+ TclDecrRefCount(oldList);
+ }
+
+ /*
+ * Trigger an eventual recomputation of the ensemble command set. Note
+ * that this is slightly tricky, as it means that we are not actually
+ * counting the number of namespace export actions, but it is the simplest
+ * way to go!
+ */
+
+ ensemblePtr->nsPtr->exportLookupEpoch++;
+
/*
- * Free the old internalRep before setting the new one.
- * We do this as late as possible to allow the conversion code
- * (in particular, Tcl_GetStringFromObj) to use that old internalRep.
+ * Special hack to make compiling of [info exists] work when the
+ * dictionary is modified.
*/
- if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
- oldTypePtr->freeIntRepProc(objPtr);
+ if (cmdPtr->compileProc != NULL) {
+ ((Interp *)interp)->compileEpoch++;
}
- objPtr->internalRep.otherValuePtr = (VOID *) resNamePtr;
- objPtr->typePtr = &tclNsNameType;
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * UpdateStringOfNsName --
+ * Tcl_SetEnsembleMappingDict --
*
- * Updates the string representation for a nsName object.
- * Note: This procedure does not free an existing old string rep
- * so storage will be lost if this has not already been done.
+ * Set the mapping dictionary for a particular ensemble.
*
* Results:
- * None.
+ * Tcl result code (error if command token does not indicate an ensemble
+ * or the mapping - if non-NULL - is not a dict).
*
* Side effects:
- * The object's string is set to a copy of the fully qualified
- * namespace name.
+ * The ensemble is updated and marked for recompilation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_SetEnsembleMappingDict(
+ Tcl_Interp *interp,
+ Tcl_Command token,
+ Tcl_Obj *mapDict)
+{
+ Command *cmdPtr = (Command *) token;
+ EnsembleConfig *ensemblePtr;
+ Tcl_Obj *oldDict;
+
+ if (cmdPtr->objProc != NsEnsembleImplementationCmd) {
+ Tcl_AppendResult(interp, "command is not an ensemble", NULL);
+ return TCL_ERROR;
+ }
+ if (mapDict != NULL) {
+ int size, done;
+ Tcl_DictSearch search;
+ Tcl_Obj *valuePtr;
+
+ if (Tcl_DictObjSize(interp, mapDict, &size) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ for (Tcl_DictObjFirst(NULL, mapDict, &search, NULL, &valuePtr, &done);
+ !done; Tcl_DictObjNext(&search, NULL, &valuePtr, &done)) {
+ Tcl_Obj *cmdPtr;
+ const char *bytes;
+
+ if (Tcl_ListObjIndex(interp, valuePtr, 0, &cmdPtr) != TCL_OK) {
+ Tcl_DictObjDone(&search);
+ return TCL_ERROR;
+ }
+ bytes = TclGetString(cmdPtr);
+ if (bytes[0] != ':' || bytes[1] != ':') {
+ Tcl_AppendResult(interp,
+ "ensemble target is not a fully-qualified command",
+ NULL);
+ Tcl_DictObjDone(&search);
+ return TCL_ERROR;
+ }
+ }
+
+ if (size < 1) {
+ mapDict = NULL;
+ }
+ }
+
+ ensemblePtr = cmdPtr->objClientData;
+ oldDict = ensemblePtr->subcommandDict;
+ ensemblePtr->subcommandDict = mapDict;
+ if (mapDict != NULL) {
+ Tcl_IncrRefCount(mapDict);
+ }
+ if (oldDict != NULL) {
+ TclDecrRefCount(oldDict);
+ }
+
+ /*
+ * Trigger an eventual recomputation of the ensemble command set. Note
+ * that this is slightly tricky, as it means that we are not actually
+ * counting the number of namespace export actions, but it is the simplest
+ * way to go!
+ */
+
+ ensemblePtr->nsPtr->exportLookupEpoch++;
+
+ /*
+ * Special hack to make compiling of [info exists] work when the
+ * dictionary is modified.
+ */
+
+ if (cmdPtr->compileProc != NULL) {
+ ((Interp *)interp)->compileEpoch++;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetEnsembleUnknownHandler --
+ *
+ * Set the unknown handler for a particular ensemble.
+ *
+ * Results:
+ * Tcl result code (error if command token does not indicate an ensemble
+ * or the unknown handler - if non-NULL - is not a list).
+ *
+ * Side effects:
+ * The ensemble is updated and marked for recompilation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_SetEnsembleUnknownHandler(
+ Tcl_Interp *interp,
+ Tcl_Command token,
+ Tcl_Obj *unknownList)
+{
+ Command *cmdPtr = (Command *) token;
+ EnsembleConfig *ensemblePtr;
+ Tcl_Obj *oldList;
+
+ if (cmdPtr->objProc != NsEnsembleImplementationCmd) {
+ Tcl_AppendResult(interp, "command is not an ensemble", NULL);
+ return TCL_ERROR;
+ }
+ if (unknownList != NULL) {
+ int length;
+
+ if (TclListObjLength(interp, unknownList, &length) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (length < 1) {
+ unknownList = NULL;
+ }
+ }
+
+ ensemblePtr = cmdPtr->objClientData;
+ oldList = ensemblePtr->unknownHandler;
+ ensemblePtr->unknownHandler = unknownList;
+ if (unknownList != NULL) {
+ Tcl_IncrRefCount(unknownList);
+ }
+ if (oldList != NULL) {
+ TclDecrRefCount(oldList);
+ }
+
+ /*
+ * Trigger an eventual recomputation of the ensemble command set. Note
+ * that this is slightly tricky, as it means that we are not actually
+ * counting the number of namespace export actions, but it is the simplest
+ * way to go!
+ */
+
+ ensemblePtr->nsPtr->exportLookupEpoch++;
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetEnsembleFlags --
+ *
+ * Set the flags for a particular ensemble.
+ *
+ * Results:
+ * Tcl result code (error if command token does not indicate an
+ * ensemble).
+ *
+ * Side effects:
+ * The ensemble is updated and marked for recompilation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_SetEnsembleFlags(
+ Tcl_Interp *interp,
+ Tcl_Command token,
+ int flags)
+{
+ Command *cmdPtr = (Command *) token;
+ EnsembleConfig *ensemblePtr;
+ int wasCompiled;
+
+ if (cmdPtr->objProc != NsEnsembleImplementationCmd) {
+ Tcl_AppendResult(interp, "command is not an ensemble", NULL);
+ return TCL_ERROR;
+ }
+
+ ensemblePtr = cmdPtr->objClientData;
+ wasCompiled = ensemblePtr->flags & ENSEMBLE_COMPILE;
+
+ /*
+ * This API refuses to set the ENS_DEAD flag...
+ */
+
+ ensemblePtr->flags &= ENS_DEAD;
+ ensemblePtr->flags |= flags & ~ENS_DEAD;
+
+ /*
+ * Trigger an eventual recomputation of the ensemble command set. Note
+ * that this is slightly tricky, as it means that we are not actually
+ * counting the number of namespace export actions, but it is the simplest
+ * way to go!
+ */
+
+ ensemblePtr->nsPtr->exportLookupEpoch++;
+
+ /*
+ * If the ENSEMBLE_COMPILE flag status was changed, install or remove the
+ * compiler function and bump the interpreter's compilation epoch so that
+ * bytecode gets regenerated.
+ */
+
+ if (flags & ENSEMBLE_COMPILE) {
+ if (!wasCompiled) {
+ ((Command*) ensemblePtr->token)->compileProc = TclCompileEnsemble;
+ ((Interp *) interp)->compileEpoch++;
+ }
+ } else {
+ if (wasCompiled) {
+ ((Command*) ensemblePtr->token)->compileProc = NULL;
+ ((Interp *) interp)->compileEpoch++;
+ }
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetEnsembleSubcommandList --
+ *
+ * Get the list of subcommands associated with a particular ensemble.
+ *
+ * Results:
+ * Tcl result code (error if command token does not indicate an
+ * ensemble). The list of subcommands is returned by updating the
+ * variable pointed to by the last parameter (NULL if this is to be
+ * derived from the mapping dictionary or the associated namespace's
+ * exported commands).
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GetEnsembleSubcommandList(
+ Tcl_Interp *interp,
+ Tcl_Command token,
+ Tcl_Obj **subcmdListPtr)
+{
+ Command *cmdPtr = (Command *) token;
+ EnsembleConfig *ensemblePtr;
+
+ if (cmdPtr->objProc != NsEnsembleImplementationCmd) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "command is not an ensemble", NULL);
+ }
+ return TCL_ERROR;
+ }
+
+ ensemblePtr = cmdPtr->objClientData;
+ *subcmdListPtr = ensemblePtr->subcmdList;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetEnsembleMappingDict --
+ *
+ * Get the command mapping dictionary associated with a particular
+ * ensemble.
+ *
+ * Results:
+ * Tcl result code (error if command token does not indicate an
+ * ensemble). The mapping dict is returned by updating the variable
+ * pointed to by the last parameter (NULL if none is installed).
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GetEnsembleMappingDict(
+ Tcl_Interp *interp,
+ Tcl_Command token,
+ Tcl_Obj **mapDictPtr)
+{
+ Command *cmdPtr = (Command *) token;
+ EnsembleConfig *ensemblePtr;
+
+ if (cmdPtr->objProc != NsEnsembleImplementationCmd) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "command is not an ensemble", NULL);
+ }
+ return TCL_ERROR;
+ }
+
+ ensemblePtr = cmdPtr->objClientData;
+ *mapDictPtr = ensemblePtr->subcommandDict;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetEnsembleUnknownHandler --
+ *
+ * Get the unknown handler associated with a particular ensemble.
+ *
+ * Results:
+ * Tcl result code (error if command token does not indicate an
+ * ensemble). The unknown handler is returned by updating the variable
+ * pointed to by the last parameter (NULL if no handler is installed).
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GetEnsembleUnknownHandler(
+ Tcl_Interp *interp,
+ Tcl_Command token,
+ Tcl_Obj **unknownListPtr)
+{
+ Command *cmdPtr = (Command *) token;
+ EnsembleConfig *ensemblePtr;
+
+ if (cmdPtr->objProc != NsEnsembleImplementationCmd) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "command is not an ensemble", NULL);
+ }
+ return TCL_ERROR;
+ }
+
+ ensemblePtr = cmdPtr->objClientData;
+ *unknownListPtr = ensemblePtr->unknownHandler;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetEnsembleFlags --
+ *
+ * Get the flags for a particular ensemble.
+ *
+ * Results:
+ * Tcl result code (error if command token does not indicate an
+ * ensemble). The flags are returned by updating the variable pointed to
+ * by the last parameter.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GetEnsembleFlags(
+ Tcl_Interp *interp,
+ Tcl_Command token,
+ int *flagsPtr)
+{
+ Command *cmdPtr = (Command *) token;
+ EnsembleConfig *ensemblePtr;
+
+ if (cmdPtr->objProc != NsEnsembleImplementationCmd) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "command is not an ensemble", NULL);
+ }
+ return TCL_ERROR;
+ }
+
+ ensemblePtr = cmdPtr->objClientData;
+ *flagsPtr = ensemblePtr->flags;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetEnsembleNamespace --
+ *
+ * Get the namespace associated with a particular ensemble.
+ *
+ * Results:
+ * Tcl result code (error if command token does not indicate an
+ * ensemble). Namespace is returned by updating the variable pointed to
+ * by the last parameter.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GetEnsembleNamespace(
+ Tcl_Interp *interp,
+ Tcl_Command token,
+ Tcl_Namespace **namespacePtrPtr)
+{
+ Command *cmdPtr = (Command *) token;
+ EnsembleConfig *ensemblePtr;
+
+ if (cmdPtr->objProc != NsEnsembleImplementationCmd) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "command is not an ensemble", NULL);
+ }
+ return TCL_ERROR;
+ }
+
+ ensemblePtr = cmdPtr->objClientData;
+ *namespacePtrPtr = (Tcl_Namespace *) ensemblePtr->nsPtr;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_FindEnsemble --
+ *
+ * Given a command name, get the ensemble token for it, allowing for
+ * [namespace import]s. [Bug 1017022]
+ *
+ * Results:
+ * The token for the ensemble command with the given name, or NULL if the
+ * command either does not exist or is not an ensemble (when an error
+ * message will be written into the interp if thats non-NULL).
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Command
+Tcl_FindEnsemble(
+ Tcl_Interp *interp, /* Where to do the lookup, and where to write
+ * the errors if TCL_LEAVE_ERR_MSG is set in
+ * the flags. */
+ Tcl_Obj *cmdNameObj, /* Name of command to look up. */
+ int flags) /* Either 0 or TCL_LEAVE_ERR_MSG; other flags
+ * are probably not useful. */
+{
+ Command *cmdPtr;
+
+ cmdPtr = (Command *)
+ Tcl_FindCommand(interp, TclGetString(cmdNameObj), NULL, flags);
+ if (cmdPtr == NULL) {
+ return NULL;
+ }
+
+ if (cmdPtr->objProc != NsEnsembleImplementationCmd) {
+ /*
+ * Reuse existing infrastructure for following import link chains
+ * rather than duplicating it.
+ */
+
+ cmdPtr = (Command *) TclGetOriginalCommand((Tcl_Command) cmdPtr);
+
+ if (cmdPtr == NULL || cmdPtr->objProc != NsEnsembleImplementationCmd) {
+ if (flags & TCL_LEAVE_ERR_MSG) {
+ Tcl_AppendResult(interp, "\"", TclGetString(cmdNameObj),
+ "\" is not an ensemble command", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENSEMBLE",
+ TclGetString(cmdNameObj), NULL);
+ }
+ return NULL;
+ }
+ }
+
+ return (Tcl_Command) cmdPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_IsEnsemble --
+ *
+ * Simple test for ensemble-hood that takes into account imported
+ * ensemble commands as well.
+ *
+ * Results:
+ * Boolean value
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_IsEnsemble(
+ Tcl_Command token)
+{
+ Command *cmdPtr = (Command *) token;
+ if (cmdPtr->objProc == NsEnsembleImplementationCmd) {
+ return 1;
+ }
+ cmdPtr = (Command *) TclGetOriginalCommand((Tcl_Command) cmdPtr);
+ if (cmdPtr == NULL || cmdPtr->objProc != NsEnsembleImplementationCmd) {
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMakeEnsemble --
+ *
+ * Create an ensemble from a table of implementation commands. The
+ * ensemble will be subject to (limited) compilation if any of the
+ * implementation commands are compilable.
+ *
+ * Results:
+ * Handle for the ensemble, or NULL if creation of it fails.
+ *
+ * Side effects:
+ * May advance bytecode compilation epoch.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Command
+TclMakeEnsemble(
+ Tcl_Interp *interp,
+ const char *name,
+ const EnsembleImplMap map[])
+{
+ Tcl_Command ensemble; /* The overall ensemble. */
+ Tcl_Namespace *tclNsPtr; /* Reference to the "::tcl" namespace. */
+ Tcl_DString buf;
+
+ tclNsPtr = Tcl_FindNamespace(interp, "::tcl", NULL,
+ TCL_CREATE_NS_IF_UNKNOWN);
+ if (tclNsPtr == NULL) {
+ Tcl_Panic("unable to find or create ::tcl namespace!");
+ }
+ Tcl_DStringInit(&buf);
+ Tcl_DStringAppend(&buf, "::tcl::", -1);
+ Tcl_DStringAppend(&buf, name, -1);
+ tclNsPtr = Tcl_FindNamespace(interp, Tcl_DStringValue(&buf), NULL,
+ TCL_CREATE_NS_IF_UNKNOWN);
+ if (tclNsPtr == NULL) {
+ Tcl_Panic("unable to find or create %s namespace!",
+ Tcl_DStringValue(&buf));
+ }
+ ensemble = Tcl_CreateEnsemble(interp, Tcl_DStringValue(&buf)+5, tclNsPtr,
+ TCL_ENSEMBLE_PREFIX);
+ Tcl_DStringAppend(&buf, "::", -1);
+ if (ensemble != NULL) {
+ Tcl_Obj *mapDict;
+ int i, compile = 0;
+
+ TclNewObj(mapDict);
+ for (i=0 ; map[i].name != NULL ; i++) {
+ Tcl_Obj *fromObj, *toObj;
+ Command *cmdPtr;
+
+ fromObj = Tcl_NewStringObj(map[i].name, -1);
+ TclNewStringObj(toObj, Tcl_DStringValue(&buf),
+ Tcl_DStringLength(&buf));
+ Tcl_AppendToObj(toObj, map[i].name, -1);
+ Tcl_DictObjPut(NULL, mapDict, fromObj, toObj);
+ cmdPtr = (Command *) Tcl_CreateObjCommand(interp,
+ TclGetString(toObj), map[i].proc, NULL, NULL);
+ cmdPtr->compileProc = map[i].compileProc;
+ compile |= (map[i].compileProc != NULL);
+ }
+ Tcl_SetEnsembleMappingDict(interp, ensemble, mapDict);
+ if (compile) {
+ Tcl_SetEnsembleFlags(interp, ensemble,
+ TCL_ENSEMBLE_PREFIX | ENSEMBLE_COMPILE);
+ }
+ }
+ Tcl_DStringFree(&buf);
+
+ return ensemble;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NsEnsembleImplementationCmd --
+ *
+ * Implements an ensemble of commands (being those exported by a
+ * namespace other than the global namespace) as a command with the same
+ * (short) name as the namespace in the parent namespace.
+ *
+ * Results:
+ * A standard Tcl result code. Will be TCL_ERROR if the command is not an
+ * unambiguous prefix of any command exported by the ensemble's
+ * namespace.
+ *
+ * Side effects:
+ * Depends on the command within the namespace that gets executed. If the
+ * ensemble itself returns TCL_ERROR, a descriptive error message will be
+ * placed in the interpreter's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NsEnsembleImplementationCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ EnsembleConfig *ensemblePtr = clientData;
+ /* The ensemble itself. */
+ Tcl_Obj **tempObjv; /* Space used to construct the list of
+ * arguments to pass to the command that
+ * implements the ensemble subcommand. */
+ int result; /* The result of the subcommand execution. */
+ Tcl_Obj *prefixObj; /* An object containing the prefix words of
+ * the command that implements the
+ * subcommand. */
+ Tcl_HashEntry *hPtr; /* Used for efficient lookup of fully
+ * specified but not yet cached command
+ * names. */
+ Tcl_Obj **prefixObjv; /* The list of objects to substitute in as the
+ * target command prefix. */
+ int prefixObjc; /* Size of prefixObjv of course! */
+ int reparseCount = 0; /* Number of reparses. */
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?argument ...?");
+ return TCL_ERROR;
+ }
+
+ restartEnsembleParse:
+ if (ensemblePtr->nsPtr->flags & NS_DYING) {
+ /*
+ * Don't know how we got here, but make things give up quickly.
+ */
+
+ if (!Tcl_InterpDeleted(interp)) {
+ Tcl_AppendResult(interp,
+ "ensemble activated for deleted namespace", NULL);
+ }
+ return TCL_ERROR;
+ }
+
+ /*
+ * Determine if the table of subcommands is right. If so, we can just look
+ * up in there and go straight to dispatch.
+ */
+
+ if (ensemblePtr->epoch == ensemblePtr->nsPtr->exportLookupEpoch) {
+ /*
+ * Table of subcommands is still valid; therefore there might be a
+ * valid cache of discovered information which we can reuse. Do the
+ * check here, and if we're still valid, we can jump straight to the
+ * part where we do the invocation of the subcommand.
+ */
+
+ if (objv[1]->typePtr == &tclEnsembleCmdType) {
+ EnsembleCmdRep *ensembleCmd = objv[1]->internalRep.otherValuePtr;
+
+ if (ensembleCmd->nsPtr == ensemblePtr->nsPtr &&
+ ensembleCmd->epoch == ensemblePtr->epoch &&
+ ensembleCmd->token == ensemblePtr->token) {
+ prefixObj = ensembleCmd->realPrefixObj;
+ Tcl_IncrRefCount(prefixObj);
+ goto runResultingSubcommand;
+ }
+ }
+ } else {
+ BuildEnsembleConfig(ensemblePtr);
+ ensemblePtr->epoch = ensemblePtr->nsPtr->exportLookupEpoch;
+ }
+
+ /*
+ * Look in the hashtable for the subcommand name; this is the fastest way
+ * of all.
+ */
+
+ hPtr = Tcl_FindHashEntry(&ensemblePtr->subcommandTable,
+ TclGetString(objv[1]));
+ if (hPtr != NULL) {
+ char *fullName = Tcl_GetHashKey(&ensemblePtr->subcommandTable, hPtr);
+
+ prefixObj = Tcl_GetHashValue(hPtr);
+
+ /*
+ * Cache for later in the subcommand object.
+ */
+
+ MakeCachedEnsembleCommand(objv[1], ensemblePtr, fullName, prefixObj);
+ } else if (!(ensemblePtr->flags & TCL_ENSEMBLE_PREFIX)) {
+ /*
+ * Could not map, no prefixing, go to unknown/error handling.
+ */
+
+ goto unknownOrAmbiguousSubcommand;
+ } else {
+ /*
+ * If we've not already confirmed the command with the hash as part of
+ * building our export table, we need to scan the sorted array for
+ * matches.
+ */
+
+ char *subcmdName; /* Name of the subcommand, or unique prefix of
+ * it (will be an error for a non-unique
+ * prefix). */
+ char *fullName = NULL; /* Full name of the subcommand. */
+ int stringLength, i;
+ int tableLength = ensemblePtr->subcommandTable.numEntries;
+
+ subcmdName = TclGetString(objv[1]);
+ stringLength = objv[1]->length;
+ for (i=0 ; i<tableLength ; i++) {
+ register int cmp = strncmp(subcmdName,
+ ensemblePtr->subcommandArrayPtr[i],
+ (unsigned) stringLength);
+
+ if (cmp == 0) {
+ if (fullName != NULL) {
+ /*
+ * Since there's never the exact-match case to worry about
+ * (hash search filters this), getting here indicates that
+ * our subcommand is an ambiguous prefix of (at least) two
+ * exported subcommands, which is an error case.
+ */
+
+ goto unknownOrAmbiguousSubcommand;
+ }
+ fullName = ensemblePtr->subcommandArrayPtr[i];
+ } else if (cmp < 0) {
+ /*
+ * Because we are searching a sorted table, we can now stop
+ * searching because we have gone past anything that could
+ * possibly match.
+ */
+
+ break;
+ }
+ }
+ if (fullName == NULL) {
+ /*
+ * The subcommand is not a prefix of anything, so bail out!
+ */
+
+ goto unknownOrAmbiguousSubcommand;
+ }
+ hPtr = Tcl_FindHashEntry(&ensemblePtr->subcommandTable, fullName);
+ if (hPtr == NULL) {
+ Tcl_Panic("full name %s not found in supposedly synchronized hash",
+ fullName);
+ }
+ prefixObj = Tcl_GetHashValue(hPtr);
+
+ /*
+ * Cache for later in the subcommand object.
+ */
+
+ MakeCachedEnsembleCommand(objv[1], ensemblePtr, fullName, prefixObj);
+ }
+
+ Tcl_IncrRefCount(prefixObj);
+ runResultingSubcommand:
+
+ /*
+ * Do the real work of execution of the subcommand by building an array of
+ * objects (note that this is potentially not the same length as the
+ * number of arguments to this ensemble command), populating it and then
+ * feeding it back through the main command-lookup engine. In theory, we
+ * could look up the command in the namespace ourselves, as we already
+ * have the namespace in which it is guaranteed to exist, but we don't do
+ * that (the cacheing of the command object used should help with that.)
+ */
+
+ {
+ Interp *iPtr = (Interp *) interp;
+ int isRootEnsemble;
+ Tcl_Obj *copyObj;
+
+ /*
+ * Get the prefix that we're rewriting to. To do this we need to
+ * ensure that the internal representation of the list does not change
+ * so that we can safely keep the internal representations of the
+ * elements in the list.
+ */
+
+ copyObj = TclListObjCopy(NULL, prefixObj);
+ TclListObjGetElements(NULL, copyObj, &prefixObjc, &prefixObjv);
+
+ /*
+ * Record what arguments the script sent in so that things like
+ * Tcl_WrongNumArgs can give the correct error message.
+ */
+
+ isRootEnsemble = (iPtr->ensembleRewrite.sourceObjs == NULL);
+ if (isRootEnsemble) {
+ iPtr->ensembleRewrite.sourceObjs = objv;
+ iPtr->ensembleRewrite.numRemovedObjs = 2;
+ iPtr->ensembleRewrite.numInsertedObjs = prefixObjc;
+ } else {
+ int ni = iPtr->ensembleRewrite.numInsertedObjs;
+
+ if (ni < 2) {
+ iPtr->ensembleRewrite.numRemovedObjs += 2 - ni;
+ iPtr->ensembleRewrite.numInsertedObjs += prefixObjc-1;
+ } else {
+ iPtr->ensembleRewrite.numInsertedObjs += prefixObjc-2;
+ }
+ }
+
+ /*
+ * Allocate a workspace and build the list of arguments to pass to the
+ * target command in it.
+ */
+
+ tempObjv = (Tcl_Obj **) TclStackAlloc(interp,
+ (int) sizeof(Tcl_Obj *) * (objc - 2 + prefixObjc));
+ memcpy(tempObjv, prefixObjv, sizeof(Tcl_Obj *) * prefixObjc);
+ memcpy(tempObjv+prefixObjc, objv+2, sizeof(Tcl_Obj *) * (objc-2));
+
+ /*
+ * Hand off to the target command.
+ */
+
+ result = Tcl_EvalObjv(interp, objc-2+prefixObjc, tempObjv,
+ TCL_EVAL_INVOKE);
+
+ /*
+ * Clean up.
+ */
+
+ TclStackFree(interp, tempObjv);
+ Tcl_DecrRefCount(copyObj);
+ if (isRootEnsemble) {
+ iPtr->ensembleRewrite.sourceObjs = NULL;
+ iPtr->ensembleRewrite.numRemovedObjs = 0;
+ iPtr->ensembleRewrite.numInsertedObjs = 0;
+ }
+ }
+ Tcl_DecrRefCount(prefixObj);
+ return result;
+
+ unknownOrAmbiguousSubcommand:
+ /*
+ * Have not been able to match the subcommand asked for with a real
+ * subcommand that we export. See whether a handler has been registered
+ * for dealing with this situation. Will only call (at most) once for any
+ * particular ensemble invocation.
+ */
+
+ if (ensemblePtr->unknownHandler != NULL && reparseCount++ < 1) {
+ int paramc, i;
+ Tcl_Obj **paramv, *unknownCmd, *ensObj;
+
+ unknownCmd = Tcl_DuplicateObj(ensemblePtr->unknownHandler);
+ TclNewObj(ensObj);
+ Tcl_GetCommandFullName(interp, ensemblePtr->token, ensObj);
+ Tcl_ListObjAppendElement(NULL, unknownCmd, ensObj);
+ for (i=1 ; i<objc ; i++) {
+ Tcl_ListObjAppendElement(NULL, unknownCmd, objv[i]);
+ }
+ TclListObjGetElements(NULL, unknownCmd, &paramc, &paramv);
+ Tcl_Preserve(ensemblePtr);
+ Tcl_IncrRefCount(unknownCmd);
+ result = Tcl_EvalObjv(interp, paramc, paramv, 0);
+ if (result == TCL_OK) {
+ prefixObj = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(prefixObj);
+ Tcl_DecrRefCount(unknownCmd);
+ Tcl_Release(ensemblePtr);
+ Tcl_ResetResult(interp);
+ if (ensemblePtr->flags & ENS_DEAD) {
+ Tcl_DecrRefCount(prefixObj);
+ Tcl_SetResult(interp,
+ "unknown subcommand handler deleted its ensemble",
+ TCL_STATIC);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Namespace is still there. Check if the result is a valid list.
+ * If it is, and it is non-empty, that list is what we are using
+ * as our replacement.
+ */
+
+ if (TclListObjLength(interp, prefixObj, &prefixObjc) != TCL_OK) {
+ Tcl_DecrRefCount(prefixObj);
+ Tcl_AddErrorInfo(interp, "\n while parsing result of "
+ "ensemble unknown subcommand handler");
+ return TCL_ERROR;
+ }
+ if (prefixObjc > 0) {
+ goto runResultingSubcommand;
+ }
+
+ /*
+ * Namespace alive & empty result => reparse.
+ */
+
+ Tcl_DecrRefCount(prefixObj);
+ goto restartEnsembleParse;
+ }
+ if (!Tcl_InterpDeleted(interp)) {
+ if (result != TCL_ERROR) {
+ char buf[TCL_INTEGER_SPACE];
+
+ Tcl_ResetResult(interp);
+ Tcl_SetResult(interp,
+ "unknown subcommand handler returned bad code: ",
+ TCL_STATIC);
+ switch (result) {
+ case TCL_RETURN:
+ Tcl_AppendResult(interp, "return", NULL);
+ break;
+ case TCL_BREAK:
+ Tcl_AppendResult(interp, "break", NULL);
+ break;
+ case TCL_CONTINUE:
+ Tcl_AppendResult(interp, "continue", NULL);
+ break;
+ default:
+ sprintf(buf, "%d", result);
+ Tcl_AppendResult(interp, buf, NULL);
+ }
+ Tcl_AddErrorInfo(interp, "\n result of "
+ "ensemble unknown subcommand handler: ");
+ Tcl_AddErrorInfo(interp, TclGetString(unknownCmd));
+ } else {
+ Tcl_AddErrorInfo(interp,
+ "\n (ensemble unknown subcommand handler)");
+ }
+ }
+ Tcl_DecrRefCount(unknownCmd);
+ Tcl_Release(ensemblePtr);
+ return TCL_ERROR;
+ }
+
+ /*
+ * We cannot determine what subcommand to hand off to, so generate a
+ * (standard) failure message. Note the one odd case compared with
+ * standard ensemble-like command, which is where a namespace has no
+ * exported commands at all...
+ */
+
+ Tcl_ResetResult(interp);
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENSEMBLE",
+ TclGetString(objv[1]), NULL);
+ if (ensemblePtr->subcommandTable.numEntries == 0) {
+ Tcl_AppendResult(interp, "unknown subcommand \"",TclGetString(objv[1]),
+ "\": namespace ", ensemblePtr->nsPtr->fullName,
+ " does not export any commands", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "SUBCOMMAND",
+ TclGetString(objv[1]), NULL);
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult(interp, "unknown ",
+ (ensemblePtr->flags & TCL_ENSEMBLE_PREFIX ? "or ambiguous " : ""),
+ "subcommand \"", TclGetString(objv[1]), "\": must be ", NULL);
+ if (ensemblePtr->subcommandTable.numEntries == 1) {
+ Tcl_AppendResult(interp, ensemblePtr->subcommandArrayPtr[0], NULL);
+ } else {
+ int i;
+
+ for (i=0 ; i<ensemblePtr->subcommandTable.numEntries-1 ; i++) {
+ Tcl_AppendResult(interp,
+ ensemblePtr->subcommandArrayPtr[i], ", ", NULL);
+ }
+ Tcl_AppendResult(interp, "or ",
+ ensemblePtr->subcommandArrayPtr[i], NULL);
+ }
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "SUBCOMMAND",
+ TclGetString(objv[1]), NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MakeCachedEnsembleCommand --
+ *
+ * Cache what we've computed so far; it's not nice to repeatedly copy
+ * strings about. Note that to do this, we start by deleting any old
+ * representation that there was (though if it was an out of date
+ * ensemble rep, we can skip some of the deallocation process.)
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Alters the internal representation of the first object parameter.
*
*----------------------------------------------------------------------
*/
static void
-UpdateStringOfNsName(objPtr)
- register Tcl_Obj *objPtr; /* nsName object with string rep to update. */
+MakeCachedEnsembleCommand(
+ Tcl_Obj *objPtr,
+ EnsembleConfig *ensemblePtr,
+ const char *subcommandName,
+ Tcl_Obj *prefixObjPtr)
{
- ResolvedNsName *resNamePtr =
- (ResolvedNsName *) objPtr->internalRep.otherValuePtr;
- register Namespace *nsPtr;
- char *name = "";
+ register EnsembleCmdRep *ensembleCmd;
int length;
- if ((resNamePtr != NULL)
- && (resNamePtr->nsId == resNamePtr->nsPtr->nsId)) {
- nsPtr = resNamePtr->nsPtr;
- if (nsPtr->flags & NS_DEAD) {
- nsPtr = NULL;
- }
- if (nsPtr != NULL) {
- name = nsPtr->fullName;
- }
+ if (objPtr->typePtr == &tclEnsembleCmdType) {
+ ensembleCmd = objPtr->internalRep.otherValuePtr;
+ Tcl_DecrRefCount(ensembleCmd->realPrefixObj);
+ ensembleCmd->nsPtr->refCount--;
+ if ((ensembleCmd->nsPtr->refCount == 0)
+ && (ensembleCmd->nsPtr->flags & NS_DEAD)) {
+ NamespaceFree(ensembleCmd->nsPtr);
+ }
+ ckfree(ensembleCmd->fullSubcmdName);
+ } else {
+ /*
+ * Kill the old internal rep, and replace it with a brand new one of
+ * our own.
+ */
+
+ TclFreeIntRep(objPtr);
+ ensembleCmd = (EnsembleCmdRep *) ckalloc(sizeof(EnsembleCmdRep));
+ objPtr->internalRep.otherValuePtr = ensembleCmd;
+ objPtr->typePtr = &tclEnsembleCmdType;
+ }
+
+ /*
+ * Populate the internal rep.
+ */
+
+ ensembleCmd->nsPtr = ensemblePtr->nsPtr;
+ ensembleCmd->epoch = ensemblePtr->epoch;
+ ensembleCmd->token = ensemblePtr->token;
+ ensemblePtr->nsPtr->refCount++;
+ ensembleCmd->realPrefixObj = prefixObjPtr;
+ length = strlen(subcommandName)+1;
+ ensembleCmd->fullSubcmdName = ckalloc((unsigned) length);
+ memcpy(ensembleCmd->fullSubcmdName, subcommandName, (unsigned) length);
+ Tcl_IncrRefCount(ensembleCmd->realPrefixObj);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteEnsembleConfig --
+ *
+ * Destroys the data structure used to represent an ensemble. This is
+ * called when the ensemble's command is deleted (which happens
+ * automatically if the ensemble's namespace is deleted.) Maintainers
+ * should note that ensembles should be deleted by deleting their
+ * commands.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is (eventually) deallocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DeleteEnsembleConfig(
+ ClientData clientData)
+{
+ EnsembleConfig *ensemblePtr = clientData;
+ Namespace *nsPtr = ensemblePtr->nsPtr;
+ Tcl_HashSearch search;
+ Tcl_HashEntry *hEnt;
+
+ /*
+ * Unlink from the ensemble chain if it has not been marked as having been
+ * done already.
+ */
+
+ if (ensemblePtr->next != ensemblePtr) {
+ EnsembleConfig *ensPtr = (EnsembleConfig *) nsPtr->ensembles;
+ if (ensPtr == ensemblePtr) {
+ nsPtr->ensembles = (Tcl_Ensemble *) ensemblePtr->next;
+ } else {
+ while (ensPtr != NULL) {
+ if (ensPtr->next == ensemblePtr) {
+ ensPtr->next = ensemblePtr->next;
+ break;
+ }
+ ensPtr = ensPtr->next;
+ }
+ }
}
/*
- * The following sets the string rep to an empty string on the heap
- * if the internal rep is NULL.
+ * Mark the namespace as dead so code that uses Tcl_Preserve() can tell
+ * whether disaster happened anyway.
*/
- length = strlen(name);
- if (length == 0) {
- objPtr->bytes = tclEmptyStringRep;
+ ensemblePtr->flags |= ENS_DEAD;
+
+ /*
+ * Kill the pointer-containing fields.
+ */
+
+ if (ensemblePtr->subcommandTable.numEntries != 0) {
+ ckfree((char *) ensemblePtr->subcommandArrayPtr);
+ }
+ hEnt = Tcl_FirstHashEntry(&ensemblePtr->subcommandTable, &search);
+ while (hEnt != NULL) {
+ Tcl_Obj *prefixObj = Tcl_GetHashValue(hEnt);
+
+ Tcl_DecrRefCount(prefixObj);
+ hEnt = Tcl_NextHashEntry(&search);
+ }
+ Tcl_DeleteHashTable(&ensemblePtr->subcommandTable);
+ if (ensemblePtr->subcmdList != NULL) {
+ Tcl_DecrRefCount(ensemblePtr->subcmdList);
+ }
+ if (ensemblePtr->subcommandDict != NULL) {
+ Tcl_DecrRefCount(ensemblePtr->subcommandDict);
+ }
+ if (ensemblePtr->unknownHandler != NULL) {
+ Tcl_DecrRefCount(ensemblePtr->unknownHandler);
+ }
+
+ /*
+ * Arrange for the structure to be reclaimed. Note that this is complex
+ * because we have to make sure that we can react sensibly when an
+ * ensemble is deleted during the process of initialising the ensemble
+ * (especially the unknown callback.)
+ */
+
+ Tcl_EventuallyFree(ensemblePtr, TCL_DYNAMIC);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BuildEnsembleConfig --
+ *
+ * Create the internal data structures that describe how an ensemble
+ * looks, being a hash mapping from the full command name to the Tcl list
+ * that describes the implementation prefix words, and a sorted array of
+ * all the full command names to allow for reasonably efficient
+ * unambiguous prefix handling.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Reallocates and rebuilds the hash table and array stored at the
+ * ensemblePtr argument. For large ensembles or large namespaces, this is
+ * a potentially expensive operation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+BuildEnsembleConfig(
+ EnsembleConfig *ensemblePtr)
+{
+ Tcl_HashSearch search; /* Used for scanning the set of commands in
+ * the namespace that backs up this
+ * ensemble. */
+ int i, j, isNew;
+ Tcl_HashTable *hash = &ensemblePtr->subcommandTable;
+ Tcl_HashEntry *hPtr;
+
+ if (hash->numEntries != 0) {
+ /*
+ * Remove pre-existing table.
+ */
+
+ Tcl_HashSearch search;
+
+ ckfree((char *) ensemblePtr->subcommandArrayPtr);
+ hPtr = Tcl_FirstHashEntry(hash, &search);
+ while (hPtr != NULL) {
+ Tcl_Obj *prefixObj = Tcl_GetHashValue(hPtr);
+ Tcl_DecrRefCount(prefixObj);
+ hPtr = Tcl_NextHashEntry(&search);
+ }
+ Tcl_DeleteHashTable(hash);
+ Tcl_InitHashTable(hash, TCL_STRING_KEYS);
+ }
+
+ /*
+ * See if we've got an export list. If so, we will only export exactly
+ * those commands, which may be either implemented by the prefix in the
+ * subcommandDict or mapped directly onto the namespace's commands.
+ */
+
+ if (ensemblePtr->subcmdList != NULL) {
+ Tcl_Obj **subcmdv, *target, *cmdObj, *cmdPrefixObj;
+ int subcmdc;
+
+ TclListObjGetElements(NULL, ensemblePtr->subcmdList, &subcmdc,
+ &subcmdv);
+ for (i=0 ; i<subcmdc ; i++) {
+ char *name = TclGetString(subcmdv[i]);
+
+ hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
+
+ /*
+ * Skip non-unique cases.
+ */
+
+ if (!isNew) {
+ continue;
+ }
+
+ /*
+ * Look in our dictionary (if present) for the command.
+ */
+
+ if (ensemblePtr->subcommandDict != NULL) {
+ Tcl_DictObjGet(NULL, ensemblePtr->subcommandDict, subcmdv[i],
+ &target);
+ if (target != NULL) {
+ Tcl_SetHashValue(hPtr, target);
+ Tcl_IncrRefCount(target);
+ continue;
+ }
+ }
+
+ /*
+ * Not there, so map onto the namespace. Note in this case that we
+ * do not guarantee that the command is actually there; that is
+ * the programmer's responsibility (or [::unknown] of course).
+ */
+
+ cmdObj = Tcl_NewStringObj(ensemblePtr->nsPtr->fullName, -1);
+ if (ensemblePtr->nsPtr->parentPtr != NULL) {
+ Tcl_AppendStringsToObj(cmdObj, "::", name, NULL);
+ } else {
+ Tcl_AppendStringsToObj(cmdObj, name, NULL);
+ }
+ cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
+ Tcl_SetHashValue(hPtr, cmdPrefixObj);
+ Tcl_IncrRefCount(cmdPrefixObj);
+ }
+ } else if (ensemblePtr->subcommandDict != NULL) {
+ /*
+ * No subcmd list, but we do have a mapping dictionary so we should
+ * use the keys of that. Convert the dictionary's contents into the
+ * form required for the ensemble's internal hashtable.
+ */
+
+ Tcl_DictSearch dictSearch;
+ Tcl_Obj *keyObj, *valueObj;
+ int done;
+
+ Tcl_DictObjFirst(NULL, ensemblePtr->subcommandDict, &dictSearch,
+ &keyObj, &valueObj, &done);
+ while (!done) {
+ char *name = TclGetString(keyObj);
+
+ hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
+ Tcl_SetHashValue(hPtr, valueObj);
+ Tcl_IncrRefCount(valueObj);
+ Tcl_DictObjNext(&dictSearch, &keyObj, &valueObj, &done);
+ }
} else {
- objPtr->bytes = (char *) ckalloc((unsigned) (length + 1));
- memcpy((VOID *) objPtr->bytes, (VOID *) name, (unsigned) length);
- objPtr->bytes[length] = '\0';
+ /*
+ * Discover what commands are actually exported by the namespace.
+ * What we have is an array of patterns and a hash table whose keys
+ * are the command names exported by the namespace (the contents do
+ * not matter here.) We must find out what commands are actually
+ * exported by filtering each command in the namespace against each of
+ * the patterns in the export list. Note that we use an intermediate
+ * hash table to make memory management easier, and because that makes
+ * exact matching far easier too.
+ *
+ * Suggestion for future enhancement: compute the unique prefixes and
+ * place them in the hash too, which should make for even faster
+ * matching.
+ */
+
+ hPtr = Tcl_FirstHashEntry(&ensemblePtr->nsPtr->cmdTable, &search);
+ for (; hPtr!= NULL ; hPtr=Tcl_NextHashEntry(&search)) {
+ char *nsCmdName = /* Name of command in namespace. */
+ Tcl_GetHashKey(&ensemblePtr->nsPtr->cmdTable, hPtr);
+
+ for (i=0 ; i<ensemblePtr->nsPtr->numExportPatterns ; i++) {
+ if (Tcl_StringMatch(nsCmdName,
+ ensemblePtr->nsPtr->exportArrayPtr[i])) {
+ hPtr = Tcl_CreateHashEntry(hash, nsCmdName, &isNew);
+
+ /*
+ * Remember, hash entries have a full reference to the
+ * substituted part of the command (as a list) as their
+ * content!
+ */
+
+ if (isNew) {
+ Tcl_Obj *cmdObj, *cmdPrefixObj;
+
+ TclNewObj(cmdObj);
+ Tcl_AppendStringsToObj(cmdObj,
+ ensemblePtr->nsPtr->fullName,
+ (ensemblePtr->nsPtr->parentPtr ? "::" : ""),
+ nsCmdName, NULL);
+ cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
+ Tcl_SetHashValue(hPtr, cmdPrefixObj);
+ Tcl_IncrRefCount(cmdPrefixObj);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ if (hash->numEntries == 0) {
+ ensemblePtr->subcommandArrayPtr = NULL;
+ return;
+ }
+
+ /*
+ * Create a sorted array of all subcommands in the ensemble; hash tables
+ * are all very well for a quick look for an exact match, but they can't
+ * determine things like whether a string is a prefix of another (not
+ * without lots of preparation anyway) and they're no good for when we're
+ * generating the error message either.
+ *
+ * We do this by filling an array with the names (we use the hash keys
+ * directly to save a copy, since any time we change the array we change
+ * the hash too, and vice versa) and running quicksort over the array.
+ */
+
+ ensemblePtr->subcommandArrayPtr = (char **)
+ ckalloc(sizeof(char *) * hash->numEntries);
+
+ /*
+ * Fill array from both ends as this makes us less likely to end up with
+ * performance problems in qsort(), which is good. Note that doing this
+ * makes this code much more opaque, but the naive alternatve:
+ *
+ * for (hPtr=Tcl_FirstHashEntry(hash,&search),i=0 ;
+ * hPtr!=NULL ; hPtr=Tcl_NextHashEntry(&search),i++) {
+ * ensemblePtr->subcommandArrayPtr[i] = Tcl_GetHashKey(hash, &hPtr);
+ * }
+ *
+ * can produce long runs of precisely ordered table entries when the
+ * commands in the namespace are declared in a sorted fashion (an ordering
+ * some people like) and the hashing functions (or the command names
+ * themselves) are fairly unfortunate. By filling from both ends, it
+ * requires active malice (and probably a debugger) to get qsort() to have
+ * awful runtime behaviour.
+ */
+
+ i = 0;
+ j = hash->numEntries;
+ hPtr = Tcl_FirstHashEntry(hash, &search);
+ while (hPtr != NULL) {
+ ensemblePtr->subcommandArrayPtr[i++] = Tcl_GetHashKey(hash, hPtr);
+ hPtr = Tcl_NextHashEntry(&search);
+ if (hPtr == NULL) {
+ break;
+ }
+ ensemblePtr->subcommandArrayPtr[--j] = Tcl_GetHashKey(hash, hPtr);
+ hPtr = Tcl_NextHashEntry(&search);
+ }
+ if (hash->numEntries > 1) {
+ qsort(ensemblePtr->subcommandArrayPtr, (unsigned)hash->numEntries,
+ sizeof(char *), NsEnsembleStringOrder);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NsEnsembleStringOrder --
+ *
+ * Helper function to compare two pointers to two strings for use with
+ * qsort().
+ *
+ * Results:
+ * -1 if the first string is smaller, 1 if the second string is smaller,
+ * and 0 if they are equal.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NsEnsembleStringOrder(
+ const void *strPtr1,
+ const void *strPtr2)
+{
+ return strcmp(*(const char **)strPtr1, *(const char **)strPtr2);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeEnsembleCmdRep --
+ *
+ * Destroys the internal representation of a Tcl_Obj that has been
+ * holding information about a command in an ensemble.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is deallocated. If this held the last reference to a
+ * namespace's main structure, that main structure will also be
+ * destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeEnsembleCmdRep(
+ Tcl_Obj *objPtr)
+{
+ EnsembleCmdRep *ensembleCmd = objPtr->internalRep.otherValuePtr;
+
+ Tcl_DecrRefCount(ensembleCmd->realPrefixObj);
+ ckfree(ensembleCmd->fullSubcmdName);
+ ensembleCmd->nsPtr->refCount--;
+ if ((ensembleCmd->nsPtr->refCount == 0)
+ && (ensembleCmd->nsPtr->flags & NS_DEAD)) {
+ NamespaceFree(ensembleCmd->nsPtr);
}
+ ckfree((char *) ensembleCmd);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupEnsembleCmdRep --
+ *
+ * Makes one Tcl_Obj into a copy of another that is a subcommand of an
+ * ensemble.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is allocated, and the namespace that the ensemble is built on
+ * top of gains another reference.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DupEnsembleCmdRep(
+ Tcl_Obj *objPtr,
+ Tcl_Obj *copyPtr)
+{
+ EnsembleCmdRep *ensembleCmd = objPtr->internalRep.otherValuePtr;
+ EnsembleCmdRep *ensembleCopy = (EnsembleCmdRep *)
+ ckalloc(sizeof(EnsembleCmdRep));
+ int length = strlen(ensembleCmd->fullSubcmdName);
+
+ copyPtr->typePtr = &tclEnsembleCmdType;
+ copyPtr->internalRep.otherValuePtr = ensembleCopy;
+ ensembleCopy->nsPtr = ensembleCmd->nsPtr;
+ ensembleCopy->epoch = ensembleCmd->epoch;
+ ensembleCopy->token = ensembleCmd->token;
+ ensembleCopy->nsPtr->refCount++;
+ ensembleCopy->realPrefixObj = ensembleCmd->realPrefixObj;
+ Tcl_IncrRefCount(ensembleCopy->realPrefixObj);
+ ensembleCopy->fullSubcmdName = ckalloc((unsigned) length+1);
+ memcpy(ensembleCopy->fullSubcmdName, ensembleCmd->fullSubcmdName,
+ (unsigned) length+1);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringOfEnsembleCmdRep --
+ *
+ * Creates a string representation of a Tcl_Obj that holds a subcommand
+ * of an ensemble.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The object gains a string (UTF-8) representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+StringOfEnsembleCmdRep(
+ Tcl_Obj *objPtr)
+{
+ EnsembleCmdRep *ensembleCmd = objPtr->internalRep.otherValuePtr;
+ int length = strlen(ensembleCmd->fullSubcmdName);
+
objPtr->length = length;
+ objPtr->bytes = ckalloc((unsigned) length+1);
+ memcpy(objPtr->bytes, ensembleCmd->fullSubcmdName, (unsigned) length+1);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LogCommandInfo --
+ *
+ * This function is invoked after an error occurs in an interpreter. It
+ * adds information to iPtr->errorInfo field to describe the command that
+ * was being executed when the error occurred.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information about the command is added to errorInfo and the line
+ * number stored internally in the interpreter is set.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_LogCommandInfo(
+ Tcl_Interp *interp, /* Interpreter in which to log information. */
+ const char *script, /* First character in script containing
+ * command (must be <= command). */
+ const char *command, /* First character in command that generated
+ * the error. */
+ int length) /* Number of bytes in command (-1 means use
+ * all bytes up to first null byte). */
+{
+ register const char *p;
+ Interp *iPtr = (Interp *) interp;
+ int overflow, limit = 150;
+ Var *varPtr, *arrayPtr;
+
+ if (iPtr->flags & ERR_ALREADY_LOGGED) {
+ /*
+ * Someone else has already logged error information for this command;
+ * we shouldn't add anything more.
+ */
+
+ return;
+ }
+
+ /*
+ * Compute the line number where the error occurred.
+ */
+
+ iPtr->errorLine = 1;
+ for (p = script; p != command; p++) {
+ if (*p == '\n') {
+ iPtr->errorLine++;
+ }
+ }
+
+ if (length < 0) {
+ length = strlen(command);
+ }
+ overflow = (length > limit);
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n %s\n\"%.*s%s\"", ((iPtr->errorInfo == NULL)
+ ? "while executing" : "invoked from within"),
+ (overflow ? limit : length), command, (overflow ? "..." : "")));
+
+ varPtr = TclObjLookupVarEx(interp, iPtr->eiVar, NULL, TCL_GLOBAL_ONLY,
+ NULL, 0, 0, &arrayPtr);
+ if ((varPtr == NULL) || !TclIsVarTraced(varPtr)) {
+ /*
+ * Should not happen.
+ */
+
+ return;
+ } else {
+ Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&iPtr->varTraces,
+ (char *) varPtr);
+ VarTrace *tracePtr = Tcl_GetHashValue(hPtr);
+
+ if (tracePtr->traceProc != EstablishErrorInfoTraces) {
+ /*
+ * The most recent trace set on ::errorInfo is not the one the
+ * core itself puts on last. This means some other code is tracing
+ * the variable, and the additional trace(s) might be write traces
+ * that expect the timing of writes to ::errorInfo that existed
+ * Tcl releases before 8.5. To satisfy that compatibility need, we
+ * write the current -errorinfo value to the ::errorInfo variable.
+ */
+
+ Tcl_ObjSetVar2(interp, iPtr->eiVar, NULL, iPtr->errorInfo,
+ TCL_GLOBAL_ONLY);
+ }
+ }
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclNotify.c b/generic/tclNotify.c
index bf82f1c..f85fb7a 100644
--- a/generic/tclNotify.c
+++ b/generic/tclNotify.c
@@ -1,28 +1,27 @@
-/*
+/*
* tclNotify.c --
*
- * This file implements the generic portion of the Tcl notifier.
- * The notifier is lowest-level part of the event system. It
- * manages an event queue that holds Tcl_Event structures. The
- * platform specific portion of the notifier is defined in the
- * tcl*Notify.c files in each platform directory.
+ * This file implements the generic portion of the Tcl notifier. The
+ * notifier is lowest-level part of the event system. It manages an event
+ * queue that holds Tcl_Event structures. The platform specific portion
+ * of the notifier is defined in the tcl*Notify.c files in each platform
+ * directory.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright (c) 1998 by Scriptics Corporation.
* Copyright (c) 2003 by Kevin B. Kenny. All rights reserved.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
extern TclStubs tclStubs;
/*
- * For each event source (created with Tcl_CreateEventSource) there
- * is a structure of the following type:
+ * For each event source (created with Tcl_CreateEventSource) there is a
+ * structure of the following type:
*/
typedef struct EventSource {
@@ -35,34 +34,34 @@ typedef struct EventSource {
/*
* The following structure keeps track of the state of the notifier on a
* per-thread basis. The first three elements keep track of the event queue.
- * In addition to the first (next to be serviced) and last events in the queue,
- * we keep track of a "marker" event. This provides a simple priority
+ * In addition to the first (next to be serviced) and last events in the
+ * queue, we keep track of a "marker" event. This provides a simple priority
* mechanism whereby events can be inserted at the front of the queue but
- * behind all other high-priority events already in the queue (this is used for
- * things like a sequence of Enter and Leave events generated during a grab in
- * Tk). These elements are protected by the queueMutex so that any thread
- * can queue an event on any notifier. Note that all of the values in this
- * structure will be initialized to 0.
+ * behind all other high-priority events already in the queue (this is used
+ * for things like a sequence of Enter and Leave events generated during a
+ * grab in Tk). These elements are protected by the queueMutex so that any
+ * thread can queue an event on any notifier. Note that all of the values in
+ * this structure will be initialized to 0.
*/
typedef struct ThreadSpecificData {
Tcl_Event *firstEventPtr; /* First pending event, or NULL if none. */
Tcl_Event *lastEventPtr; /* Last pending event, or NULL if none. */
- Tcl_Event *markerEventPtr; /* Last high-priority event in queue, or
- * NULL if none. */
+ Tcl_Event *markerEventPtr; /* Last high-priority event in queue, or NULL
+ * if none. */
Tcl_Mutex queueMutex; /* Mutex to protect access to the previous
* three fields. */
int serviceMode; /* One of TCL_SERVICE_NONE or
* TCL_SERVICE_ALL. */
- int blockTimeSet; /* 0 means there is no maximum block
- * time: block forever. */
- Tcl_Time blockTime; /* If blockTimeSet is 1, gives the
- * maximum elapsed time for the next block. */
- int inTraversal; /* 1 if Tcl_SetMaxBlockTime is being
- * called during an event source traversal. */
+ int blockTimeSet; /* 0 means there is no maximum block time:
+ * block forever. */
+ Tcl_Time blockTime; /* If blockTimeSet is 1, gives the maximum
+ * elapsed time for the next block. */
+ int inTraversal; /* 1 if Tcl_SetMaxBlockTime is being called
+ * during an event source traversal. */
EventSource *firstEventSourcePtr;
- /* Pointer to first event source in
- * list of event sources for this thread. */
+ /* Pointer to first event source in list of
+ * event sources for this thread. */
Tcl_ThreadId threadId; /* Thread that owns this notifier instance. */
ClientData clientData; /* Opaque handle for platform specific
* notifier. */
@@ -76,20 +75,20 @@ typedef struct ThreadSpecificData {
static Tcl_ThreadDataKey dataKey;
/*
- * Global list of notifiers. Access to this list is controlled by the
- * listLock mutex. If this becomes a performance bottleneck, this could
- * be replaced with a hashtable.
+ * Global list of notifiers. Access to this list is controlled by the listLock
+ * mutex. If this becomes a performance bottleneck, this could be replaced
+ * with a hashtable.
*/
-static ThreadSpecificData *firstNotifierPtr;
+static ThreadSpecificData *firstNotifierPtr = NULL;
TCL_DECLARE_MUTEX(listLock)
/*
* Declarations for routines used only in this file.
*/
-static void QueueEvent _ANSI_ARGS_((ThreadSpecificData *tsdPtr,
- Tcl_Event* evPtr, Tcl_QueuePosition position));
+static void QueueEvent(ThreadSpecificData *tsdPtr,
+ Tcl_Event* evPtr, Tcl_QueuePosition position);
/*
*----------------------------------------------------------------------
@@ -109,18 +108,29 @@ static void QueueEvent _ANSI_ARGS_((ThreadSpecificData *tsdPtr,
*/
void
-TclInitNotifier()
+TclInitNotifier(void)
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ThreadSpecificData *tsdPtr;
+ Tcl_ThreadId threadId = Tcl_GetCurrentThread();
Tcl_MutexLock(&listLock);
+ for (tsdPtr = firstNotifierPtr; tsdPtr && tsdPtr->threadId != threadId;
+ tsdPtr = tsdPtr->nextPtr) {
+ /* Empty loop body. */
+ }
- tsdPtr->threadId = Tcl_GetCurrentThread();
- tsdPtr->clientData = tclStubs.tcl_InitNotifier();
- tsdPtr->initialized = 1;
- tsdPtr->nextPtr = firstNotifierPtr;
- firstNotifierPtr = tsdPtr;
+ if (NULL == tsdPtr) {
+ /*
+ * Notifier not yet initialized in this thread.
+ */
+ tsdPtr = TCL_TSD_INIT(&dataKey);
+ tsdPtr->threadId = threadId;
+ tsdPtr->clientData = tclStubs.tcl_InitNotifier();
+ tsdPtr->initialized = 1;
+ tsdPtr->nextPtr = firstNotifierPtr;
+ firstNotifierPtr = tsdPtr;
+ }
Tcl_MutexUnlock(&listLock);
}
@@ -129,40 +139,39 @@ TclInitNotifier()
*
* TclFinalizeNotifier --
*
- * Finalize the thread local data structures for the notifier
- * subsystem.
+ * Finalize the thread local data structures for the notifier subsystem.
*
* Results:
- * None.
+ * None.
*
* Side effects:
- * Removes the notifier associated with the current thread from
- * the global notifier list. This is done only if the notifier
- * was initialized for this thread by call to TclInitNotifier().
- * This is always true for threads which have been seeded with
- * an Tcl interpreter, since the call to Tcl_CreateInterp will,
- * among other things, call TclInitializeSubsystems() and this
- * one will, in turn, call the TclInitNotifier() for the thread.
- * For threads created without the Tcl interpreter, though,
- * nobody is explicitly nor implicitly calling the TclInitNotifier
- * hence, TclFinalizeNotifier should not be performed at all.
+ * Removes the notifier associated with the current thread from the
+ * global notifier list. This is done only if the notifier was
+ * initialized for this thread by call to TclInitNotifier(). This is
+ * always true for threads which have been seeded with an Tcl
+ * interpreter, since the call to Tcl_CreateInterp will, among other
+ * things, call TclInitializeSubsystems() and this one will, in turn,
+ * call the TclInitNotifier() for the thread. For threads created without
+ * the Tcl interpreter, though, nobody is explicitly nor implicitly
+ * calling the TclInitNotifier hence, TclFinalizeNotifier should not be
+ * performed at all.
*
*----------------------------------------------------------------------
*/
void
-TclFinalizeNotifier()
+TclFinalizeNotifier(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
ThreadSpecificData **prevPtrPtr;
Tcl_Event *evPtr, *hold;
if (!tsdPtr->initialized) {
- return; /* Notifier not initialized for the current thread */
+ return; /* Notifier not initialized for the current thread */
}
Tcl_MutexLock(&(tsdPtr->queueMutex));
- for (evPtr = tsdPtr->firstEventPtr; evPtr != (Tcl_Event *) NULL; ) {
+ for (evPtr = tsdPtr->firstEventPtr; evPtr != NULL; ) {
hold = evPtr;
evPtr = evPtr->nextPtr;
ckfree((char *) hold);
@@ -178,7 +187,7 @@ TclFinalizeNotifier()
}
Tcl_MutexFinalize(&(tsdPtr->queueMutex));
for (prevPtrPtr = &firstNotifierPtr; *prevPtrPtr != NULL;
- prevPtrPtr = &((*prevPtrPtr)->nextPtr)) {
+ prevPtrPtr = &((*prevPtrPtr)->nextPtr)) {
if (*prevPtrPtr == tsdPtr) {
*prevPtrPtr = tsdPtr->nextPtr;
break;
@@ -194,26 +203,26 @@ TclFinalizeNotifier()
*
* Tcl_SetNotifier --
*
- * Install a set of alternate functions for use with the notifier.
- # In particular, this can be used to install the Xt-based
- * notifier for use with the Browser plugin.
+ * Install a set of alternate functions for use with the notifier. In
+ * particular, this can be used to install the Xt-based notifier for use
+ * with the Browser plugin.
*
* Results:
* None.
*
* Side effects:
- * Overstomps part of the stub vector. This relies on hooks
- * added to the default procedures in case those are called
- * directly (i.e., not through the stub table.)
+ * Overstomps part of the stub vector. This relies on hooks added to the
+ * default functions in case those are called directly (i.e., not through
+ * the stub table.)
*
*----------------------------------------------------------------------
*/
void
-Tcl_SetNotifier(notifierProcPtr)
- Tcl_NotifierProcs *notifierProcPtr;
+Tcl_SetNotifier(
+ Tcl_NotifierProcs *notifierProcPtr)
{
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+#if !defined(__WIN32__) /* UNIX */
tclStubs.tcl_CreateFileHandler = notifierProcPtr->createFileHandlerProc;
tclStubs.tcl_DeleteFileHandler = notifierProcPtr->deleteFileHandlerProc;
#endif
@@ -230,10 +239,9 @@ Tcl_SetNotifier(notifierProcPtr)
*
* Tcl_CreateEventSource --
*
- * This procedure is invoked to create a new source of events.
- * The source is identified by a procedure that gets invoked
- * during Tcl_DoOneEvent to check for events on that source
- * and queue them.
+ * This function is invoked to create a new source of events. The source
+ * is identified by a function that gets invoked during Tcl_DoOneEvent to
+ * check for events on that source and queue them.
*
*
* Results:
@@ -241,34 +249,36 @@ Tcl_SetNotifier(notifierProcPtr)
*
* Side effects:
* SetupProc and checkProc will be invoked each time that Tcl_DoOneEvent
- * runs out of things to do. SetupProc will be invoked before
- * Tcl_DoOneEvent calls select or whatever else it uses to wait
- * for events. SetupProc typically calls functions like
- * Tcl_SetMaxBlockTime to indicate what to wait for.
+ * runs out of things to do. SetupProc will be invoked before
+ * Tcl_DoOneEvent calls select or whatever else it uses to wait for
+ * events. SetupProc typically calls functions like Tcl_SetMaxBlockTime
+ * to indicate what to wait for.
*
* CheckProc is called after select or whatever operation was actually
- * used to wait. It figures out whether anything interesting actually
+ * used to wait. It figures out whether anything interesting actually
* happened (e.g. by calling Tcl_AsyncReady), and then calls
* Tcl_QueueEvent to queue any events that are ready.
*
- * Each of these procedures is passed two arguments, e.g.
+ * Each of these functions is passed two arguments, e.g.
* (*checkProc)(ClientData clientData, int flags));
- * ClientData is the same as the clientData argument here, and flags
- * is a combination of things like TCL_FILE_EVENTS that indicates
- * what events are of interest: setupProc and checkProc use flags
- * to figure out whether their events are relevant or not.
+ * ClientData is the same as the clientData argument here, and flags is a
+ * combination of things like TCL_FILE_EVENTS that indicates what events
+ * are of interest: setupProc and checkProc use flags to figure out
+ * whether their events are relevant or not.
*
*----------------------------------------------------------------------
*/
void
-Tcl_CreateEventSource(setupProc, checkProc, clientData)
- Tcl_EventSetupProc *setupProc; /* Procedure to invoke to figure out
- * what to wait for. */
- Tcl_EventCheckProc *checkProc; /* Procedure to call after waiting
- * to see what happened. */
- ClientData clientData; /* One-word argument to pass to
- * setupProc and checkProc. */
+Tcl_CreateEventSource(
+ Tcl_EventSetupProc *setupProc,
+ /* Function to invoke to figure out what to
+ * wait for. */
+ Tcl_EventCheckProc *checkProc,
+ /* Function to call after waiting to see what
+ * happened. */
+ ClientData clientData) /* One-word argument to pass to setupProc and
+ * checkProc. */
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
EventSource *sourcePtr = (EventSource *) ckalloc(sizeof(EventSource));
@@ -285,28 +295,29 @@ Tcl_CreateEventSource(setupProc, checkProc, clientData)
*
* Tcl_DeleteEventSource --
*
- * This procedure is invoked to delete the source of events
- * given by proc and clientData.
+ * This function is invoked to delete the source of events given by proc
+ * and clientData.
*
* Results:
* None.
*
* Side effects:
- * The given event source is cancelled, so its procedure will
- * never again be called. If no such source exists, nothing
- * happens.
+ * The given event source is cancelled, so its function will never again
+ * be called. If no such source exists, nothing happens.
*
*----------------------------------------------------------------------
*/
void
-Tcl_DeleteEventSource(setupProc, checkProc, clientData)
- Tcl_EventSetupProc *setupProc; /* Procedure to invoke to figure out
- * what to wait for. */
- Tcl_EventCheckProc *checkProc; /* Procedure to call after waiting
- * to see what happened. */
- ClientData clientData; /* One-word argument to pass to
- * setupProc and checkProc. */
+Tcl_DeleteEventSource(
+ Tcl_EventSetupProc *setupProc,
+ /* Function to invoke to figure out what to
+ * wait for. */
+ Tcl_EventCheckProc *checkProc,
+ /* Function to call after waiting to see what
+ * happened. */
+ ClientData clientData) /* One-word argument to pass to setupProc and
+ * checkProc. */
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
EventSource *sourcePtr, *prevPtr;
@@ -334,8 +345,7 @@ Tcl_DeleteEventSource(setupProc, checkProc, clientData)
*
* Tcl_QueueEvent --
*
- * Queue an event on the event queue associated with the
- * current thread.
+ * Queue an event on the event queue associated with the current thread.
*
* Results:
* None.
@@ -347,14 +357,13 @@ Tcl_DeleteEventSource(setupProc, checkProc, clientData)
*/
void
-Tcl_QueueEvent(evPtr, position)
- Tcl_Event* evPtr; /* Event to add to queue. The storage
- * space must have been allocated the caller
- * with malloc (ckalloc), and it becomes
- * the property of the event queue. It
- * will be freed after the event has been
- * handled. */
- Tcl_QueuePosition position; /* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD,
+Tcl_QueueEvent(
+ Tcl_Event* evPtr, /* Event to add to queue. The storage space
+ * must have been allocated the caller with
+ * malloc (ckalloc), and it becomes the
+ * property of the event queue. It will be
+ * freed after the event has been handled. */
+ Tcl_QueuePosition position) /* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD,
* TCL_QUEUE_MARK. */
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -378,15 +387,14 @@ Tcl_QueueEvent(evPtr, position)
*/
void
-Tcl_ThreadQueueEvent(threadId, evPtr, position)
- Tcl_ThreadId threadId; /* Identifier for thread to use. */
- Tcl_Event* evPtr; /* Event to add to queue. The storage
- * space must have been allocated the caller
- * with malloc (ckalloc), and it becomes
- * the property of the event queue. It
- * will be freed after the event has been
- * handled. */
- Tcl_QueuePosition position; /* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD,
+Tcl_ThreadQueueEvent(
+ Tcl_ThreadId threadId, /* Identifier for thread to use. */
+ Tcl_Event *evPtr, /* Event to add to queue. The storage space
+ * must have been allocated the caller with
+ * malloc (ckalloc), and it becomes the
+ * property of the event queue. It will be
+ * freed after the event has been handled. */
+ Tcl_QueuePosition position) /* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD,
* TCL_QUEUE_MARK. */
{
ThreadSpecificData *tsdPtr;
@@ -397,7 +405,7 @@ Tcl_ThreadQueueEvent(threadId, evPtr, position)
Tcl_MutexLock(&listLock);
for (tsdPtr = firstNotifierPtr; tsdPtr && tsdPtr->threadId != threadId;
- tsdPtr = tsdPtr->nextPtr) {
+ tsdPtr = tsdPtr->nextPtr) {
/* Empty loop body. */
}
@@ -418,12 +426,12 @@ Tcl_ThreadQueueEvent(threadId, evPtr, position)
*
* QueueEvent --
*
- * Insert an event into the specified thread's event queue at one
- * of three positions: the head, the tail, or before a floating
- * marker. Events inserted before the marker will be processed in
- * first-in-first-out order, but before any events inserted at
- * the tail of the queue. Events inserted at the head of the
- * queue will be processed in last-in-first-out order.
+ * Insert an event into the specified thread's event queue at one of
+ * three positions: the head, the tail, or before a floating marker.
+ * Events inserted before the marker will be processed in first-in-
+ * first-out order, but before any events inserted at the tail of the
+ * queue. Events inserted at the head of the queue will be processed in
+ * last-in-first-out order.
*
* Results:
* None.
@@ -435,16 +443,15 @@ Tcl_ThreadQueueEvent(threadId, evPtr, position)
*/
static void
-QueueEvent(tsdPtr, evPtr, position)
- ThreadSpecificData *tsdPtr; /* Handle to thread local data that indicates
+QueueEvent(
+ ThreadSpecificData *tsdPtr, /* Handle to thread local data that indicates
* which event queue to use. */
- Tcl_Event* evPtr; /* Event to add to queue. The storage
- * space must have been allocated the caller
- * with malloc (ckalloc), and it becomes
- * the property of the event queue. It
- * will be freed after the event has been
- * handled. */
- Tcl_QueuePosition position; /* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD,
+ Tcl_Event *evPtr, /* Event to add to queue. The storage space
+ * must have been allocated the caller with
+ * malloc (ckalloc), and it becomes the
+ * property of the event queue. It will be
+ * freed after the event has been handled. */
+ Tcl_QueuePosition position) /* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD,
* TCL_QUEUE_MARK. */
{
Tcl_MutexLock(&(tsdPtr->queueMutex));
@@ -468,12 +475,12 @@ QueueEvent(tsdPtr, evPtr, position)
evPtr->nextPtr = tsdPtr->firstEventPtr;
if (tsdPtr->firstEventPtr == NULL) {
tsdPtr->lastEventPtr = evPtr;
- }
+ }
tsdPtr->firstEventPtr = evPtr;
} else if (position == TCL_QUEUE_MARK) {
/*
- * Insert the event after the current marker event and advance
- * the marker to the new event.
+ * Insert the event after the current marker event and advance the
+ * marker to the new event.
*/
if (tsdPtr->markerEventPtr == NULL) {
@@ -496,10 +503,10 @@ QueueEvent(tsdPtr, evPtr, position)
*
* Tcl_DeleteEvents --
*
- * Calls a procedure for each event in the queue and deletes those
- * for which the procedure returns 1. Events for which the
- * procedure returns 0 are left in the queue. Operates on the
- * queue associated with the current thread.
+ * Calls a function for each event in the queue and deletes those for
+ * which the function returns 1. Events for which the function returns 0
+ * are left in the queue. Operates on the queue associated with the
+ * current thread.
*
* Results:
* None.
@@ -511,36 +518,65 @@ QueueEvent(tsdPtr, evPtr, position)
*/
void
-Tcl_DeleteEvents(proc, clientData)
- Tcl_EventDeleteProc *proc; /* The procedure to call. */
- ClientData clientData; /* type-specific data. */
+Tcl_DeleteEvents(
+ Tcl_EventDeleteProc *proc, /* The function to call. */
+ ClientData clientData) /* The type-specific data. */
{
- Tcl_Event *evPtr, *prevPtr, *hold;
+ Tcl_Event *evPtr; /* Pointer to the event being examined */
+ Tcl_Event *prevPtr; /* Pointer to evPtr's predecessor, or NULL if
+ * evPtr designates the first event in the
+ * queue for the thread. */
+ Tcl_Event* hold;
+
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
Tcl_MutexLock(&(tsdPtr->queueMutex));
- for (prevPtr = (Tcl_Event *) NULL, evPtr = tsdPtr->firstEventPtr;
- evPtr != (Tcl_Event *) NULL;
- ) {
- if ((*proc) (evPtr, clientData) == 1) {
- if (tsdPtr->firstEventPtr == evPtr) {
- tsdPtr->firstEventPtr = evPtr->nextPtr;
- } else {
- prevPtr->nextPtr = evPtr->nextPtr;
- }
- if (evPtr->nextPtr == (Tcl_Event *) NULL) {
- tsdPtr->lastEventPtr = prevPtr;
- }
- if (tsdPtr->markerEventPtr == evPtr) {
- tsdPtr->markerEventPtr = prevPtr;
- }
- hold = evPtr;
- evPtr = evPtr->nextPtr;
- ckfree((char *) hold);
- } else {
- prevPtr = evPtr;
- evPtr = evPtr->nextPtr;
- }
+
+ /*
+ * Walk the queue of events for the thread, applying 'proc' to each to
+ * decide whether to eliminate the event.
+ */
+
+ prevPtr = NULL;
+ evPtr = tsdPtr->firstEventPtr;
+ while (evPtr != NULL) {
+ if ((*proc)(evPtr, clientData) == 1) {
+ /*
+ * This event should be deleted. Unlink it.
+ */
+
+ if (prevPtr == NULL) {
+ tsdPtr->firstEventPtr = evPtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = evPtr->nextPtr;
+ }
+
+ /*
+ * Update 'last' and 'marker' events if either has been deleted.
+ */
+
+ if (evPtr->nextPtr == NULL) {
+ tsdPtr->lastEventPtr = prevPtr;
+ }
+ if (tsdPtr->markerEventPtr == evPtr) {
+ tsdPtr->markerEventPtr = prevPtr;
+ }
+
+ /*
+ * Delete the event data structure.
+ */
+
+ hold = evPtr;
+ evPtr = evPtr->nextPtr;
+ ckfree((char *) hold);
+ } else {
+ /*
+ * Event is to be retained.
+ */
+
+ prevPtr = evPtr;
+ evPtr = evPtr->nextPtr;
+ }
}
Tcl_MutexUnlock(&(tsdPtr->queueMutex));
}
@@ -550,30 +586,29 @@ Tcl_DeleteEvents(proc, clientData)
*
* Tcl_ServiceEvent --
*
- * Process one event from the event queue, or invoke an
- * asynchronous event handler. Operates on event queue for
- * current thread.
+ * Process one event from the event queue, or invoke an asynchronous
+ * event handler. Operates on event queue for current thread.
*
* Results:
- * The return value is 1 if the procedure actually found an event
- * to process. If no processing occurred, then 0 is returned.
+ * The return value is 1 if the function actually found an event to
+ * process. If no processing occurred, then 0 is returned.
*
* Side effects:
- * Invokes all of the event handlers for the highest priority
- * event in the event queue. May collapse some events into a
- * single event or discard stale events.
+ * Invokes all of the event handlers for the highest priority event in
+ * the event queue. May collapse some events into a single event or
+ * discard stale events.
*
*----------------------------------------------------------------------
*/
int
-Tcl_ServiceEvent(flags)
- int flags; /* Indicates what events should be processed.
+Tcl_ServiceEvent(
+ int flags) /* Indicates what events should be processed.
* May be any combination of TCL_WINDOW_EVENTS
* TCL_FILE_EVENTS, TCL_TIMER_EVENTS, or other
- * flags defined elsewhere. Events not
- * matching this will be skipped for processing
- * later. */
+ * flags defined elsewhere. Events not
+ * matching this will be skipped for
+ * processing later. */
{
Tcl_Event *evPtr, *prevPtr;
Tcl_EventProc *proc;
@@ -581,46 +616,46 @@ Tcl_ServiceEvent(flags)
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
/*
- * Asynchronous event handlers are considered to be the highest
- * priority events, and so must be invoked before we process events
- * on the event queue.
+ * Asynchronous event handlers are considered to be the highest priority
+ * events, and so must be invoked before we process events on the event
+ * queue.
*/
-
+
if (Tcl_AsyncReady()) {
- (void) Tcl_AsyncInvoke((Tcl_Interp *) NULL, 0);
+ (void) Tcl_AsyncInvoke(NULL, 0);
return 1;
}
/*
* No event flags is equivalent to TCL_ALL_EVENTS.
*/
-
+
if ((flags & TCL_ALL_EVENTS) == 0) {
flags |= TCL_ALL_EVENTS;
}
/*
- * Loop through all the events in the queue until we find one
- * that can actually be handled.
+ * Loop through all the events in the queue until we find one that can
+ * actually be handled.
*/
Tcl_MutexLock(&(tsdPtr->queueMutex));
for (evPtr = tsdPtr->firstEventPtr; evPtr != NULL;
- evPtr = evPtr->nextPtr) {
+ evPtr = evPtr->nextPtr) {
/*
- * Call the handler for the event. If it actually handles the
- * event then free the storage for the event. There are two
- * tricky things here, both stemming from the fact that the event
- * code may be re-entered while servicing the event:
+ * Call the handler for the event. If it actually handles the event
+ * then free the storage for the event. There are two tricky things
+ * here, both stemming from the fact that the event code may be
+ * re-entered while servicing the event:
*
* 1. Set the "proc" field to NULL. This is a signal to ourselves
- * that we shouldn't reexecute the handler if the event loop
- * is re-entered.
+ * that we shouldn't reexecute the handler if the event loop is
+ * re-entered.
* 2. When freeing the event, must search the queue again from the
- * front to find it. This is because the event queue could
- * change almost arbitrarily while handling the event, so we
- * can't depend on pointers found now still being valid when
- * the handler returns.
+ * front to find it. This is because the event queue could change
+ * almost arbitrarily while handling the event, so we can't depend
+ * on pointers found now still being valid when the handler
+ * returns.
*/
proc = evPtr->proc;
@@ -630,10 +665,10 @@ Tcl_ServiceEvent(flags)
evPtr->proc = NULL;
/*
- * Release the lock before calling the event procedure. This
- * allows other threads to post events if we enter a recursive
- * event loop in this thread. Note that we are making the assumption
- * that if the proc returns 0, the event is still in the list.
+ * Release the lock before calling the event function. This allows
+ * other threads to post events if we enter a recursive event loop in
+ * this thread. Note that we are making the assumption that if the
+ * proc returns 0, the event is still in the list.
*/
Tcl_MutexUnlock(&(tsdPtr->queueMutex));
@@ -655,8 +690,8 @@ Tcl_ServiceEvent(flags)
}
} else {
for (prevPtr = tsdPtr->firstEventPtr;
- prevPtr && prevPtr->nextPtr != evPtr;
- prevPtr = prevPtr->nextPtr) {
+ prevPtr && prevPtr->nextPtr != evPtr;
+ prevPtr = prevPtr->nextPtr) {
/* Empty loop body. */
}
if (prevPtr) {
@@ -678,8 +713,8 @@ Tcl_ServiceEvent(flags)
return 1;
} else {
/*
- * The event wasn't actually handled, so we have to restore
- * the proc field to allow the event to be attempted again.
+ * The event wasn't actually handled, so we have to restore the
+ * proc field to allow the event to be attempted again.
*/
evPtr->proc = proc;
@@ -706,7 +741,7 @@ Tcl_ServiceEvent(flags)
*/
int
-Tcl_GetServiceMode()
+Tcl_GetServiceMode(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -724,14 +759,14 @@ Tcl_GetServiceMode()
* Returns the previous service mode.
*
* Side effects:
- * Invokes the notifier service mode hook procedure.
+ * Invokes the notifier service mode hook function.
*
*----------------------------------------------------------------------
*/
int
-Tcl_SetServiceMode(mode)
- int mode; /* New service mode: TCL_SERVICE_ALL or
+Tcl_SetServiceMode(
+ int mode) /* New service mode: TCL_SERVICE_ALL or
* TCL_SERVICE_NONE */
{
int oldMode;
@@ -750,10 +785,10 @@ Tcl_SetServiceMode(mode)
*
* Tcl_SetMaxBlockTime --
*
- * This procedure is invoked by event sources to tell the notifier
- * how long it may block the next time it blocks. The timePtr
- * argument gives a maximum time; the actual time may be less if
- * some other event source requested a smaller time.
+ * This function is invoked by event sources to tell the notifier how
+ * long it may block the next time it blocks. The timePtr argument gives
+ * a maximum time; the actual time may be less if some other event source
+ * requested a smaller time.
*
* Results:
* None.
@@ -765,10 +800,10 @@ Tcl_SetServiceMode(mode)
*/
void
-Tcl_SetMaxBlockTime(timePtr)
- Tcl_Time *timePtr; /* Specifies a maximum elapsed time for
- * the next blocking operation in the
- * event tsdPtr-> */
+Tcl_SetMaxBlockTime(
+ Tcl_Time *timePtr) /* Specifies a maximum elapsed time for the
+ * next blocking operation in the event
+ * tsdPtr-> */
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -780,8 +815,8 @@ Tcl_SetMaxBlockTime(timePtr)
}
/*
- * If we are called outside an event source traversal, set the
- * timeout immediately.
+ * If we are called outside an event source traversal, set the timeout
+ * immediately.
*/
if (!tsdPtr->inTraversal) {
@@ -798,27 +833,27 @@ Tcl_SetMaxBlockTime(timePtr)
*
* Tcl_DoOneEvent --
*
- * Process a single event of some sort. If there's no work to
- * do, wait for an event to occur, then process it.
+ * Process a single event of some sort. If there's no work to do, wait
+ * for an event to occur, then process it.
*
* Results:
- * The return value is 1 if the procedure actually found an event
- * to process. If no processing occurred, then 0 is returned (this
- * can happen if the TCL_DONT_WAIT flag is set or if there are no
- * event handlers to wait for in the set specified by flags).
+ * The return value is 1 if the function actually found an event to
+ * process. If no processing occurred, then 0 is returned (this can
+ * happen if the TCL_DONT_WAIT flag is set or if there are no event
+ * handlers to wait for in the set specified by flags).
*
* Side effects:
- * May delay execution of process while waiting for an event,
- * unless TCL_DONT_WAIT is set in the flags argument. Event
- * sources are invoked to check for and queue events. Event
- * handlers may produce arbitrary side effects.
+ * May delay execution of process while waiting for an event, unless
+ * TCL_DONT_WAIT is set in the flags argument. Event sources are invoked
+ * to check for and queue events. Event handlers may produce arbitrary
+ * side effects.
*
*----------------------------------------------------------------------
*/
int
-Tcl_DoOneEvent(flags)
- int flags; /* Miscellaneous flag values: may be any
+Tcl_DoOneEvent(
+ int flags) /* Miscellaneous flag values: may be any
* combination of TCL_DONT_WAIT,
* TCL_WINDOW_EVENTS, TCL_FILE_EVENTS,
* TCL_TIMER_EVENTS, TCL_IDLE_EVENTS, or
@@ -830,47 +865,45 @@ Tcl_DoOneEvent(flags)
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
/*
- * The first thing we do is to service any asynchronous event
- * handlers.
+ * The first thing we do is to service any asynchronous event handlers.
*/
-
+
if (Tcl_AsyncReady()) {
- (void) Tcl_AsyncInvoke((Tcl_Interp *) NULL, 0);
+ (void) Tcl_AsyncInvoke(NULL, 0);
return 1;
}
/*
* No event flags is equivalent to TCL_ALL_EVENTS.
*/
-
+
if ((flags & TCL_ALL_EVENTS) == 0) {
flags |= TCL_ALL_EVENTS;
}
/*
- * Set the service mode to none so notifier event routines won't
- * try to service events recursively.
+ * Set the service mode to none so notifier event routines won't try to
+ * service events recursively.
*/
oldMode = tsdPtr->serviceMode;
tsdPtr->serviceMode = TCL_SERVICE_NONE;
/*
- * The core of this procedure is an infinite loop, even though
- * we only service one event. The reason for this is that we
- * may be processing events that don't do anything inside of Tcl.
+ * The core of this function is an infinite loop, even though we only
+ * service one event. The reason for this is that we may be processing
+ * events that don't do anything inside of Tcl.
*/
while (1) {
-
/*
- * If idle events are the only things to service, skip the
- * main part of the loop and go directly to handle idle
- * events (i.e. don't wait even if TCL_DONT_WAIT isn't set).
+ * If idle events are the only things to service, skip the main part
+ * of the loop and go directly to handle idle events (i.e. don't wait
+ * even if TCL_DONT_WAIT isn't set).
*/
if ((flags & TCL_ALL_EVENTS) == TCL_IDLE_EVENTS) {
- flags = TCL_IDLE_EVENTS|TCL_DONT_WAIT;
+ flags = TCL_IDLE_EVENTS | TCL_DONT_WAIT;
goto idleEvents;
}
@@ -884,8 +917,8 @@ Tcl_DoOneEvent(flags)
}
/*
- * If TCL_DONT_WAIT is set, be sure to poll rather than
- * blocking, otherwise reset the block time to infinity.
+ * If TCL_DONT_WAIT is set, be sure to poll rather than blocking,
+ * otherwise reset the block time to infinity.
*/
if (flags & TCL_DONT_WAIT) {
@@ -897,13 +930,13 @@ Tcl_DoOneEvent(flags)
}
/*
- * Set up all the event sources for new events. This will
- * cause the block time to be updated if necessary.
+ * Set up all the event sources for new events. This will cause the
+ * block time to be updated if necessary.
*/
tsdPtr->inTraversal = 1;
for (sourcePtr = tsdPtr->firstEventSourcePtr; sourcePtr != NULL;
- sourcePtr = sourcePtr->nextPtr) {
+ sourcePtr = sourcePtr->nextPtr) {
if (sourcePtr->setupProc) {
(sourcePtr->setupProc)(sourcePtr->clientData, flags);
}
@@ -917,8 +950,8 @@ Tcl_DoOneEvent(flags)
}
/*
- * Wait for a new event or a timeout. If Tcl_WaitForEvent
- * returns -1, we should abort Tcl_DoOneEvent.
+ * Wait for a new event or a timeout. If Tcl_WaitForEvent returns -1,
+ * we should abort Tcl_DoOneEvent.
*/
result = Tcl_WaitForEvent(timePtr);
@@ -932,7 +965,7 @@ Tcl_DoOneEvent(flags)
*/
for (sourcePtr = tsdPtr->firstEventSourcePtr; sourcePtr != NULL;
- sourcePtr = sourcePtr->nextPtr) {
+ sourcePtr = sourcePtr->nextPtr) {
if (sourcePtr->checkProc) {
(sourcePtr->checkProc)(sourcePtr->clientData, flags);
}
@@ -948,12 +981,12 @@ Tcl_DoOneEvent(flags)
}
/*
- * We've tried everything at this point, but nobody we know
- * about had anything to do. Check for idle events. If none,
- * either quit or go back to the top and try again.
+ * We've tried everything at this point, but nobody we know about had
+ * anything to do. Check for idle events. If none, either quit or go
+ * back to the top and try again.
*/
- idleEvents:
+ idleEvents:
if (flags & TCL_IDLE_EVENTS) {
if (TclServiceIdle()) {
result = 1;
@@ -965,23 +998,21 @@ Tcl_DoOneEvent(flags)
}
/*
- * If Tcl_WaitForEvent has returned 1,
- * indicating that one system event has been dispatched
- * (and thus that some Tcl code might have been indirectly executed),
- * we break out of the loop.
- * We do this to give VwaitCmd for instance a chance to check
- * if that system event had the side effect of changing the
- * variable (so the vwait can return and unwind properly).
+ * If Tcl_WaitForEvent has returned 1, indicating that one system
+ * event has been dispatched (and thus that some Tcl code might have
+ * been indirectly executed), we break out of the loop. We do this to
+ * give VwaitCmd for instance a chance to check if that system event
+ * had the side effect of changing the variable (so the vwait can
+ * return and unwind properly).
*
- * NB: We will process idle events if any first, because
- * otherwise we might never do the idle events if the notifier
- * always gets system events.
+ * NB: We will process idle events if any first, because otherwise we
+ * might never do the idle events if the notifier always gets
+ * system events.
*/
if (result) {
break;
}
-
}
tsdPtr->serviceMode = oldMode;
@@ -993,12 +1024,11 @@ Tcl_DoOneEvent(flags)
*
* Tcl_ServiceAll --
*
- * This routine checks all of the event sources, processes
- * events that are on the Tcl event queue, and then calls the
- * any idle handlers. Platform specific notifier callbacks that
- * generate events should call this routine before returning to
- * the system in order to ensure that Tcl gets a chance to
- * process the new events.
+ * This routine checks all of the event sources, processes events that
+ * are on the Tcl event queue, and then calls the any idle handlers.
+ * Platform specific notifier callbacks that generate events should call
+ * this routine before returning to the system in order to ensure that
+ * Tcl gets a chance to process the new events.
*
* Results:
* Returns 1 if an event or idle handler was invoked, else 0.
@@ -1010,7 +1040,7 @@ Tcl_DoOneEvent(flags)
*/
int
-Tcl_ServiceAll()
+Tcl_ServiceAll(void)
{
int result = 0;
EventSource *sourcePtr;
@@ -1021,10 +1051,10 @@ Tcl_ServiceAll()
}
/*
- * We need to turn off event servicing like we to in Tcl_DoOneEvent,
- * to avoid recursive calls.
+ * We need to turn off event servicing like we to in Tcl_DoOneEvent, to
+ * avoid recursive calls.
*/
-
+
tsdPtr->serviceMode = TCL_SERVICE_NONE;
/*
@@ -1032,26 +1062,26 @@ Tcl_ServiceAll()
*/
if (Tcl_AsyncReady()) {
- (void) Tcl_AsyncInvoke((Tcl_Interp *) NULL, 0);
+ (void) Tcl_AsyncInvoke(NULL, 0);
}
/*
- * Make a single pass through all event sources, queued events,
- * and idle handlers. Note that we wait to update the notifier
- * timer until the end so we can avoid multiple changes.
+ * Make a single pass through all event sources, queued events, and idle
+ * handlers. Note that we wait to update the notifier timer until the end
+ * so we can avoid multiple changes.
*/
tsdPtr->inTraversal = 1;
tsdPtr->blockTimeSet = 0;
for (sourcePtr = tsdPtr->firstEventSourcePtr; sourcePtr != NULL;
- sourcePtr = sourcePtr->nextPtr) {
+ sourcePtr = sourcePtr->nextPtr) {
if (sourcePtr->setupProc) {
(sourcePtr->setupProc)(sourcePtr->clientData, TCL_ALL_EVENTS);
}
}
for (sourcePtr = tsdPtr->firstEventSourcePtr; sourcePtr != NULL;
- sourcePtr = sourcePtr->nextPtr) {
+ sourcePtr = sourcePtr->nextPtr) {
if (sourcePtr->checkProc) {
(sourcePtr->checkProc)(sourcePtr->clientData, TCL_ALL_EVENTS);
}
@@ -1079,8 +1109,8 @@ Tcl_ServiceAll()
*
* Tcl_ThreadAlert --
*
- * This function wakes up the notifier associated with the
- * specified thread (if there is one).
+ * This function wakes up the notifier associated with the specified
+ * thread (if there is one).
*
* Results:
* None.
@@ -1092,16 +1122,15 @@ Tcl_ServiceAll()
*/
void
-Tcl_ThreadAlert(threadId)
- Tcl_ThreadId threadId; /* Identifier for thread to use. */
+Tcl_ThreadAlert(
+ Tcl_ThreadId threadId) /* Identifier for thread to use. */
{
ThreadSpecificData *tsdPtr;
/*
- * Find the notifier associated with the specified thread.
- * Note that we need to hold the listLock while calling
- * Tcl_AlertNotifier to avoid a race condition where
- * the specified thread might destroy its notifier.
+ * Find the notifier associated with the specified thread. Note that we
+ * need to hold the listLock while calling Tcl_AlertNotifier to avoid a
+ * race condition where the specified thread might destroy its notifier.
*/
Tcl_MutexLock(&listLock);
@@ -1115,3 +1144,11 @@ Tcl_ThreadAlert(threadId)
}
Tcl_MutexUnlock(&listLock);
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclObj.c b/generic/tclObj.c
index 7b9bb61..5c17df2 100644
--- a/generic/tclObj.c
+++ b/generic/tclObj.c
@@ -1,28 +1,30 @@
-/*
+/*
* tclObj.c --
*
- * This file contains Tcl object-related procedures that are used by
- * many Tcl commands.
+ * This file contains Tcl object-related functions that are used by many
+ * Tcl commands.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright (c) 1999 by Scriptics Corporation.
* Copyright (c) 2001 by ActiveState Corporation.
+ * Copyright (c) 2005 by Kevin B. Kenny. All rights reserved.
* Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclCompile.h"
-#include "tclPort.h"
+#include "tommath.h"
+#include <float.h>
+#include <math.h>
/*
* Table of all object types.
*/
static Tcl_HashTable typeTable;
-static int typeTableInitialized = 0; /* 0 means not yet initialized. */
+static int typeTableInitialized = 0; /* 0 means not yet initialized. */
TCL_DECLARE_MUTEX(tableMutex)
/*
@@ -32,259 +34,379 @@ TCL_DECLARE_MUTEX(tableMutex)
Tcl_Obj *tclFreeObjList = NULL;
/*
- * The object allocator is single threaded. This mutex is referenced
- * by the TclNewObj macro, however, so must be visible.
+ * The object allocator is single threaded. This mutex is referenced by the
+ * TclNewObj macro, however, so must be visible.
*/
#ifdef TCL_THREADS
+MODULE_SCOPE Tcl_Mutex tclObjMutex;
Tcl_Mutex tclObjMutex;
#endif
/*
- * Pointer to a heap-allocated string of length zero that the Tcl core uses
- * as the value of an empty string representation for an object. This value
- * is shared by all new objects allocated by Tcl_NewObj.
+ * Pointer to a heap-allocated string of length zero that the Tcl core uses as
+ * the value of an empty string representation for an object. This value is
+ * shared by all new objects allocated by Tcl_NewObj.
*/
char tclEmptyString = '\0';
char *tclEmptyStringRep = &tclEmptyString;
+
+#if defined(TCL_MEM_DEBUG) && defined(TCL_THREADS)
+/*
+ * Structure for tracking the source file and line number where a given Tcl_Obj
+ * was allocated. We also track the pointer to the Tcl_Obj itself, for sanity
+ * checking purposes.
+ */
+typedef struct ObjData {
+ Tcl_Obj *objPtr; /* The pointer to the allocated Tcl_Obj. */
+ CONST char *file; /* The name of the source file calling this
+ * function; used for debugging. */
+ int line; /* Line number in the source file; used for
+ * debugging. */
+} ObjData;
+#endif /* TCL_MEM_DEBUG && TCL_THREADS */
-#ifdef TCL_TIP280
/*
- * All static variables used in this file are collected into a single
- * instance of the following structure. For multi-threaded implementations,
- * there is one instance of this structure for each thread.
+ * All static variables used in this file are collected into a single instance
+ * of the following structure. For multi-threaded implementations, there is
+ * one instance of this structure for each thread.
*
- * Notice that different structures with the same name appear in other
- * files. The structure defined below is used in this file only.
+ * Notice that different structures with the same name appear in other files.
+ * The structure defined below is used in this file only.
*/
typedef struct ThreadSpecificData {
- Tcl_HashTable* lineCLPtr; /* This table remembers for each Tcl_Obj generated
- * by a call to the function EvalTokensStandard()
- * from a literal text where bs+nl sequences
- * occured in it, if any. I.e. this table keeps
- * track of invisible/stripped continuation
- * lines. Its keys are Tcl_Obj pointers, the
- * values are ContLineLoc pointers. See the file
- * tclCompile.h for the definition of this
- * structure, and for references to all related
- * places in the core.
- */
+ Tcl_HashTable* lineCLPtr; /* This table remembers for each Tcl_Obj
+ * generated by a call to the function
+ * TclSubstTokens() from a literal text
+ * where bs+nl sequences occured in it, if
+ * any. I.e. this table keeps track of
+ * invisible/stripped continuation lines. Its
+ * keys are Tcl_Obj pointers, the values are
+ * ContLineLoc pointers. See the file
+ * tclCompile.h for the definition of this
+ * structure, and for references to all related
+ * places in the core.
+ */
+#if defined(TCL_MEM_DEBUG) && defined(TCL_THREADS)
+ /*
+ * Thread local table that is used to check that a Tcl_Obj was not
+ * allocated by some other thread.
+ */
+
+ Tcl_HashTable *objThreadMap;
+#endif /* TCL_MEM_DEBUG && TCL_THREADS */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
-static void ContLineLocFree _ANSI_ARGS_((char* clientData));
-static void TclThreadFinalizeObjects _ANSI_ARGS_((ClientData clientData));
-static ThreadSpecificData* TclGetContinuationTable _ANSI_ARGS_(());
+static void ContLineLocFree (char* clientData);
+static void TclThreadFinalizeContLines (ClientData clientData);
+static ThreadSpecificData* TclGetContLineTable (void);
+
+/*
+ * Nested Tcl_Obj deletion management support
+ *
+ * All context references used in the object freeing code are pointers to this
+ * structure; every thread will have its own structure instance. The purpose
+ * of this structure is to allow deeply nested collections of Tcl_Objs to be
+ * freed without taking a vast depth of C stack (which could cause all sorts
+ * of breakage.)
+ */
+
+typedef struct PendingObjData {
+ int deletionCount; /* Count of the number of invokations of
+ * TclFreeObj() are on the stack (at least
+ * conceptually; many are actually expanded
+ * macros). */
+ Tcl_Obj *deletionStack; /* Stack of objects that have had TclFreeObj()
+ * invoked upon them but which can't be
+ * deleted yet because they are in a nested
+ * invokation of TclFreeObj(). By postponing
+ * this way, we limit the maximum overall C
+ * stack depth when deleting a complex object.
+ * The down-side is that we alter the overall
+ * behaviour by altering the order in which
+ * objects are deleted, and we change the
+ * order in which the string rep and the
+ * internal rep of an object are deleted. Note
+ * that code which assumes the previous
+ * behaviour in either of these respects is
+ * unsafe anyway; it was never documented as
+ * to exactly what would happen in these
+ * cases, and the overall contract of a
+ * user-level Tcl_DecrRefCount() is still
+ * preserved (assuming that a particular T_DRC
+ * would delete an object is not very
+ * safe). */
+} PendingObjData;
+
+/*
+ * These are separated out so that some semantic content is attached
+ * to them.
+ */
+#define ObjDeletionLock(contextPtr) ((contextPtr)->deletionCount++)
+#define ObjDeletionUnlock(contextPtr) ((contextPtr)->deletionCount--)
+#define ObjDeletePending(contextPtr) ((contextPtr)->deletionCount > 0)
+#define ObjOnStack(contextPtr) ((contextPtr)->deletionStack != NULL)
+#define PushObjToDelete(contextPtr,objPtr) \
+ /* The string rep is already invalidated so we can use the bytes value \
+ * for our pointer chain: push onto the head of the stack. */ \
+ (objPtr)->bytes = (char *) ((contextPtr)->deletionStack); \
+ (contextPtr)->deletionStack = (objPtr)
+#define PopObjToDelete(contextPtr,objPtrVar) \
+ (objPtrVar) = (contextPtr)->deletionStack; \
+ (contextPtr)->deletionStack = (Tcl_Obj *) (objPtrVar)->bytes
+
+/*
+ * Macro to set up the local reference to the deletion context.
+ */
+#ifndef TCL_THREADS
+static PendingObjData pendingObjData;
+#define ObjInitDeletionContext(contextPtr) \
+ PendingObjData *CONST contextPtr = &pendingObjData
+#else
+static Tcl_ThreadDataKey pendingObjDataKey;
+#define ObjInitDeletionContext(contextPtr) \
+ PendingObjData *CONST contextPtr = (PendingObjData *) \
+ Tcl_GetThreadData(&pendingObjDataKey, sizeof(PendingObjData))
#endif
/*
- * Prototypes for procedures defined later in this file:
+ * Macros to pack/unpack a bignum's fields in a Tcl_Obj internal rep
*/
-static int SetBooleanFromAny _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
-static int SetDoubleFromAny _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
-static int SetIntFromAny _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
-static int SetIntOrWideFromAny _ANSI_ARGS_((Tcl_Interp* interp,
- Tcl_Obj *objPtr));
-static void UpdateStringOfBoolean _ANSI_ARGS_((Tcl_Obj *objPtr));
-static void UpdateStringOfDouble _ANSI_ARGS_((Tcl_Obj *objPtr));
-static void UpdateStringOfInt _ANSI_ARGS_((Tcl_Obj *objPtr));
-static int SetWideIntFromAny _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
+#define PACK_BIGNUM(bignum, objPtr) \
+ if ((bignum).used > 0x7fff) { \
+ mp_int *temp = (void *) ckalloc((unsigned) sizeof(mp_int)); \
+ *temp = bignum; \
+ (objPtr)->internalRep.ptrAndLongRep.ptr = (void*) temp; \
+ (objPtr)->internalRep.ptrAndLongRep.value = (unsigned long)(-1); \
+ } else { \
+ if ((bignum).alloc > 0x7fff) { \
+ mp_shrink(&(bignum)); \
+ } \
+ (objPtr)->internalRep.ptrAndLongRep.ptr = (void*) (bignum).dp; \
+ (objPtr)->internalRep.ptrAndLongRep.value = ( ((bignum).sign << 30) \
+ | ((bignum).alloc << 15) | ((bignum).used)); \
+ }
+
+#define UNPACK_BIGNUM(objPtr, bignum) \
+ if ((objPtr)->internalRep.ptrAndLongRep.value == (unsigned long)(-1)) { \
+ (bignum) = *((mp_int *) ((objPtr)->internalRep.ptrAndLongRep.ptr)); \
+ } else { \
+ (bignum).dp = (mp_digit*) (objPtr)->internalRep.ptrAndLongRep.ptr; \
+ (bignum).sign = (objPtr)->internalRep.ptrAndLongRep.value >> 30; \
+ (bignum).alloc = \
+ ((objPtr)->internalRep.ptrAndLongRep.value >> 15) & 0x7fff; \
+ (bignum).used = (objPtr)->internalRep.ptrAndLongRep.value & 0x7fff; \
+ }
-#ifndef TCL_WIDE_INT_IS_LONG
-static void UpdateStringOfWideInt _ANSI_ARGS_((Tcl_Obj *objPtr));
+/*
+ * Prototypes for functions defined later in this file:
+ */
+
+static int ParseBoolean(Tcl_Obj *objPtr);
+static int SetBooleanFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
+static int SetDoubleFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
+static int SetIntFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
+static void UpdateStringOfDouble(Tcl_Obj *objPtr);
+static void UpdateStringOfInt(Tcl_Obj *objPtr);
+#ifndef NO_WIDE_TYPE
+static void UpdateStringOfWideInt(Tcl_Obj *objPtr);
+static int SetWideIntFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
#endif
+static void FreeBignum(Tcl_Obj *objPtr);
+static void DupBignum(Tcl_Obj *objPtr, Tcl_Obj *copyPtr);
+static void UpdateStringOfBignum(Tcl_Obj *objPtr);
+static int GetBignumFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ int copy, mp_int *bignumValue);
/*
* Prototypes for the array hash key methods.
*/
-static Tcl_HashEntry * AllocObjEntry _ANSI_ARGS_((
- Tcl_HashTable *tablePtr, VOID *keyPtr));
-static int CompareObjKeys _ANSI_ARGS_((
- VOID *keyPtr, Tcl_HashEntry *hPtr));
-static void FreeObjEntry _ANSI_ARGS_((
- Tcl_HashEntry *hPtr));
-static unsigned int HashObjKey _ANSI_ARGS_((
- Tcl_HashTable *tablePtr,
- VOID *keyPtr));
+static Tcl_HashEntry * AllocObjEntry(Tcl_HashTable *tablePtr, void *keyPtr);
/*
* Prototypes for the CommandName object type.
*/
-static void DupCmdNameInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr,
- Tcl_Obj *copyPtr));
-static void FreeCmdNameInternalRep _ANSI_ARGS_((
- Tcl_Obj *objPtr));
-static int SetCmdNameFromAny _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
-
+static void DupCmdNameInternalRep(Tcl_Obj *objPtr,
+ Tcl_Obj *copyPtr);
+static void FreeCmdNameInternalRep(Tcl_Obj *objPtr);
+static int SetCmdNameFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
/*
* The structures below defines the Tcl object types defined in this file by
- * means of procedures that can be invoked by generic object code. See also
+ * means of functions that can be invoked by generic object code. See also
* tclStringObj.c, tclListObj.c, tclByteCode.c for other type manager
* implementations.
*/
-Tcl_ObjType tclBooleanType = {
+static Tcl_ObjType oldBooleanType = {
"boolean", /* name */
- (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
- (Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */
- UpdateStringOfBoolean, /* updateStringProc */
+ NULL, /* freeIntRepProc */
+ NULL, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ SetBooleanFromAny /* setFromAnyProc */
+};
+Tcl_ObjType tclBooleanType = {
+ "booleanString", /* name */
+ NULL, /* freeIntRepProc */
+ NULL, /* dupIntRepProc */
+ NULL, /* updateStringProc */
SetBooleanFromAny /* setFromAnyProc */
};
-
Tcl_ObjType tclDoubleType = {
"double", /* name */
- (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
- (Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */
+ NULL, /* freeIntRepProc */
+ NULL, /* dupIntRepProc */
UpdateStringOfDouble, /* updateStringProc */
SetDoubleFromAny /* setFromAnyProc */
};
-
Tcl_ObjType tclIntType = {
"int", /* name */
- (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
- (Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */
+ NULL, /* freeIntRepProc */
+ NULL, /* dupIntRepProc */
UpdateStringOfInt, /* updateStringProc */
SetIntFromAny /* setFromAnyProc */
};
-
+#ifndef NO_WIDE_TYPE
Tcl_ObjType tclWideIntType = {
"wideInt", /* name */
- (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
- (Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */
-#ifdef TCL_WIDE_INT_IS_LONG
- UpdateStringOfInt, /* updateStringProc */
-#else /* !TCL_WIDE_INT_IS_LONG */
+ NULL, /* freeIntRepProc */
+ NULL, /* dupIntRepProc */
UpdateStringOfWideInt, /* updateStringProc */
-#endif
SetWideIntFromAny /* setFromAnyProc */
};
+#endif
+Tcl_ObjType tclBignumType = {
+ "bignum", /* name */
+ FreeBignum, /* freeIntRepProc */
+ DupBignum, /* dupIntRepProc */
+ UpdateStringOfBignum, /* updateStringProc */
+ NULL /* setFromAnyProc */
+};
/*
* The structure below defines the Tcl obj hash key type.
*/
+
Tcl_HashKeyType tclObjHashKeyType = {
- TCL_HASH_KEY_TYPE_VERSION, /* version */
- 0, /* flags */
- HashObjKey, /* hashKeyProc */
- CompareObjKeys, /* compareKeysProc */
- AllocObjEntry, /* allocEntryProc */
- FreeObjEntry /* freeEntryProc */
+ TCL_HASH_KEY_TYPE_VERSION, /* version */
+ 0, /* flags */
+ TclHashObjKey, /* hashKeyProc */
+ TclCompareObjKeys, /* compareKeysProc */
+ AllocObjEntry, /* allocEntryProc */
+ TclFreeObjEntry /* freeEntryProc */
};
/*
* The structure below defines the command name Tcl object type by means of
- * procedures that can be invoked by generic object code. Objects of this
- * type cache the Command pointer that results from looking up command names
- * in the command hashtable. Such objects appear as the zeroth ("command
- * name") argument in a Tcl command.
+ * functions that can be invoked by generic object code. Objects of this type
+ * cache the Command pointer that results from looking up command names in the
+ * command hashtable. Such objects appear as the zeroth ("command name")
+ * argument in a Tcl command.
*
* NOTE: the ResolvedCmdName that gets cached is stored in the
- * twoPtrValue.ptr1 field, and the twoPtrValue.ptr2 field is unused.
- * You might think you could use the simpler otherValuePtr field to
- * store the single ResolvedCmdName pointer, but DO NOT DO THIS. It
- * seems that some extensions use the second internal pointer field
- * of the twoPtrValue field for their own purposes.
+ * twoPtrValue.ptr1 field, and the twoPtrValue.ptr2 field is unused. You might
+ * think you could use the simpler otherValuePtr field to store the single
+ * ResolvedCmdName pointer, but DO NOT DO THIS. It seems that some extensions
+ * use the second internal pointer field of the twoPtrValue field for their
+ * own purposes.
*/
static Tcl_ObjType tclCmdNameType = {
"cmdName", /* name */
FreeCmdNameInternalRep, /* freeIntRepProc */
DupCmdNameInternalRep, /* dupIntRepProc */
- (Tcl_UpdateStringProc *) NULL, /* updateStringProc */
+ NULL, /* updateStringProc */
SetCmdNameFromAny /* setFromAnyProc */
};
-
/*
- * Structure containing a cached pointer to a command that is the result
- * of resolving the command's name in some namespace. It is the internal
- * representation for a cmdName object. It contains the pointer along
- * with some information that is used to check the pointer's validity.
+ * Structure containing a cached pointer to a command that is the result of
+ * resolving the command's name in some namespace. It is the internal
+ * representation for a cmdName object. It contains the pointer along with
+ * some information that is used to check the pointer's validity.
*/
typedef struct ResolvedCmdName {
Command *cmdPtr; /* A cached Command pointer. */
Namespace *refNsPtr; /* Points to the namespace containing the
- * reference (not the namespace that
- * contains the referenced command). */
+ * reference (not the namespace that contains
+ * the referenced command). NULL if the name
+ * is fully qualified.*/
long refNsId; /* refNsPtr's unique namespace id. Used to
- * verify that refNsPtr is still valid
- * (e.g., it's possible that the cmd's
- * containing namespace was deleted and a
- * new one created at the same address). */
+ * verify that refNsPtr is still valid (e.g.,
+ * it's possible that the cmd's containing
+ * namespace was deleted and a new one created
+ * at the same address). */
int refNsCmdEpoch; /* Value of the referencing namespace's
* cmdRefEpoch when the pointer was cached.
* Before using the cached pointer, we check
* if the namespace's epoch was incremented;
* if so, this cached pointer is invalid. */
int cmdEpoch; /* Value of the command's cmdEpoch when this
- * pointer was cached. Before using the
- * cached pointer, we check if the cmd's
- * epoch was incremented; if so, the cmd was
- * renamed, deleted, hidden, or exposed, and
- * so the pointer is invalid. */
- int refCount; /* Reference count: 1 for each cmdName
- * object that has a pointer to this
- * ResolvedCmdName structure as its internal
- * rep. This structure can be freed when
- * refCount becomes zero. */
+ * pointer was cached. Before using the cached
+ * pointer, we check if the cmd's epoch was
+ * incremented; if so, the cmd was renamed,
+ * deleted, hidden, or exposed, and so the
+ * pointer is invalid. */
+ int refCount; /* Reference count: 1 for each cmdName object
+ * that has a pointer to this ResolvedCmdName
+ * structure as its internal rep. This
+ * structure can be freed when refCount
+ * becomes zero. */
} ResolvedCmdName;
-
/*
*-------------------------------------------------------------------------
*
* TclInitObjectSubsystem --
*
- * This procedure is invoked to perform once-only initialization of
- * the type table. It also registers the object types defined in
- * this file.
+ * This function is invoked to perform once-only initialization of the
+ * type table. It also registers the object types defined in this file.
*
* Results:
* None.
*
* Side effects:
- * Initializes the table of defined object types "typeTable" with
- * builtin object types defined in this file.
+ * Initializes the table of defined object types "typeTable" with builtin
+ * object types defined in this file.
*
*-------------------------------------------------------------------------
*/
void
-TclInitObjSubsystem()
+TclInitObjSubsystem(void)
{
Tcl_MutexLock(&tableMutex);
typeTableInitialized = 1;
Tcl_InitHashTable(&typeTable, TCL_STRING_KEYS);
Tcl_MutexUnlock(&tableMutex);
- Tcl_RegisterObjType(&tclBooleanType);
Tcl_RegisterObjType(&tclByteArrayType);
Tcl_RegisterObjType(&tclDoubleType);
Tcl_RegisterObjType(&tclEndOffsetType);
Tcl_RegisterObjType(&tclIntType);
- Tcl_RegisterObjType(&tclWideIntType);
Tcl_RegisterObjType(&tclStringType);
Tcl_RegisterObjType(&tclListType);
+ Tcl_RegisterObjType(&tclDictType);
Tcl_RegisterObjType(&tclByteCodeType);
- Tcl_RegisterObjType(&tclProcBodyType);
Tcl_RegisterObjType(&tclArraySearchType);
- Tcl_RegisterObjType(&tclIndexType);
- Tcl_RegisterObjType(&tclNsNameType);
Tcl_RegisterObjType(&tclCmdNameType);
+ Tcl_RegisterObjType(&tclRegexpType);
+ Tcl_RegisterObjType(&tclProcBodyType);
+
+ /* For backward compatibility only ... */
+ Tcl_RegisterObjType(&oldBooleanType);
+#ifndef NO_WIDE_TYPE
+ Tcl_RegisterObjType(&tclWideIntType);
+#endif
#ifdef TCL_COMPILE_STATS
Tcl_MutexLock(&tclObjMutex);
@@ -292,7 +414,7 @@ TclInitObjSubsystem()
tclObjsFreed = 0;
{
int i;
- for (i = 0; i < TCL_MAX_SHARED_OBJ_STATS; i++) {
+ for (i=0 ; i<TCL_MAX_SHARED_OBJ_STATS ; i++) {
tclObjsShared[i] = 0;
}
}
@@ -303,10 +425,53 @@ TclInitObjSubsystem()
/*
*----------------------------------------------------------------------
*
+ * TclFinalizeThreadObjects --
+ *
+ * This function is called by Tcl_FinalizeThread to clean up thread
+ * specific Tcl_Obj information.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclFinalizeThreadObjects(void)
+{
+#if defined(TCL_MEM_DEBUG) && defined(TCL_THREADS)
+ Tcl_HashEntry *hPtr;
+ Tcl_HashSearch hSearch;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ Tcl_HashTable *tablePtr = tsdPtr->objThreadMap;
+
+ if (tablePtr != NULL) {
+ for (hPtr = Tcl_FirstHashEntry(tablePtr, &hSearch);
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) {
+ ObjData *objData = Tcl_GetHashValue(hPtr);
+
+ if (objData != NULL) {
+ ckfree((char *) objData);
+ }
+ }
+
+ Tcl_DeleteHashTable(tablePtr);
+ ckfree((char *) tablePtr);
+ tsdPtr->objThreadMap = NULL;
+ }
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TclFinalizeObjects --
*
- * This procedure is called by Tcl_Finalize to clean up all
- * registered Tcl_ObjType's and to reset the tclFreeObjList.
+ * This function is called by Tcl_Finalize to clean up all registered
+ * Tcl_ObjType's and to reset the tclFreeObjList.
*
* Results:
* None.
@@ -318,37 +483,36 @@ TclInitObjSubsystem()
*/
void
-TclFinalizeObjects()
+TclFinalizeObjects(void)
{
Tcl_MutexLock(&tableMutex);
if (typeTableInitialized) {
- Tcl_DeleteHashTable(&typeTable);
- typeTableInitialized = 0;
+ Tcl_DeleteHashTable(&typeTable);
+ typeTableInitialized = 0;
}
Tcl_MutexUnlock(&tableMutex);
- /*
- * All we do here is reset the head pointer of the linked list of
- * free Tcl_Obj's to NULL; the memory finalization will take care
- * of releasing memory for us.
+ /*
+ * All we do here is reset the head pointer of the linked list of free
+ * Tcl_Obj's to NULL; the memory finalization will take care of releasing
+ * memory for us.
*/
Tcl_MutexLock(&tclObjMutex);
tclFreeObjList = NULL;
Tcl_MutexUnlock(&tclObjMutex);
}
-#ifdef TCL_TIP280
/*
*----------------------------------------------------------------------
*
- * TclGetContinuationTable --
+ * TclGetContLineTable --
*
* This procedure is a helper which returns the thread-specific
* hash-table used to track continuation line information associated with
- * Tcl_Obj*.
+ * Tcl_Obj*, and the objThreadMap, etc.
*
* Results:
- * A reference to the continuation line thread-data.
+ * A reference to the thread-data.
*
* Side effects:
* May allocate memory for the thread-data.
@@ -358,7 +522,7 @@ TclFinalizeObjects()
*/
static ThreadSpecificData*
-TclGetContinuationTable()
+TclGetContLineTable()
{
/*
* Initialize the hashtable tracking invisible continuation lines. For
@@ -372,7 +536,7 @@ TclGetContinuationTable()
if (!tsdPtr->lineCLPtr) {
tsdPtr->lineCLPtr = (Tcl_HashTable*) ckalloc (sizeof (Tcl_HashTable));
Tcl_InitHashTable(tsdPtr->lineCLPtr, TCL_ONE_WORD_KEYS);
- Tcl_CreateThreadExitHandler (TclThreadFinalizeObjects,NULL);
+ Tcl_CreateThreadExitHandler (TclThreadFinalizeContLines,NULL);
}
return tsdPtr;
}
@@ -396,36 +560,49 @@ TclGetContinuationTable()
*/
ContLineLoc*
-TclContinuationsEnter(objPtr,num,loc)
- Tcl_Obj* objPtr;
- int num;
- int* loc;
+TclContinuationsEnter(Tcl_Obj* objPtr,
+ int num,
+ int* loc)
{
- int newEntry;
- ThreadSpecificData *tsdPtr = TclGetContinuationTable();
- Tcl_HashEntry* hPtr =
- Tcl_CreateHashEntry (tsdPtr->lineCLPtr, (char*) objPtr, &newEntry);
+ int newEntry;
+ ThreadSpecificData *tsdPtr = TclGetContLineTable();
+ Tcl_HashEntry* hPtr =
+ Tcl_CreateHashEntry (tsdPtr->lineCLPtr, (char*) objPtr, &newEntry);
- ContLineLoc* clLocPtr =
- (ContLineLoc*) ckalloc (sizeof(ContLineLoc) + num*sizeof(int));
+ ContLineLoc* clLocPtr =
+ (ContLineLoc*) ckalloc (sizeof(ContLineLoc) + num*sizeof(int));
if (!newEntry) {
/*
- * Somehow we're entering ContLineLoc data for the same value (objPtr)
- * more than one time. Not sure whether that's expected, or a sign of
- * trouble, but at a minimum, we should take care not to leak the old
- * entry.
+ * We're entering ContLineLoc data for the same value more than one
+ * time. Taking care not to leak the old entry.
+ *
+ * This can happen when literals in a proc body are shared. See for
+ * example test info-30.19 where the action (code) for all branches of
+ * the switch command is identical, mapping them all to the same
+ * literal. An interesting result of this is that the number and
+ * locations (offset) of invisible continuation lines in the literal
+ * are the same for all occurences.
+ *
+ * Note that while reusing the existing entry is possible it requires
+ * the same actions as for a new entry because we have to copy the
+ * incoming num/loc data even so. Because we are called from
+ * TclContinuationsEnterDerived for this case, which modified the
+ * stored locations (Rebased to the proper relative offset). Just
+ * returning the stored entry and data would rebase them a second
+ * time, or more, hosing the data. It is easier to simply replace, as
+ * we are doing.
*/
ckfree((char *) Tcl_GetHashValue(hPtr));
}
- clLocPtr->num = num;
- memcpy (&clLocPtr->loc, loc, num*sizeof(int));
- clLocPtr->loc[num] = CLL_END; /* Sentinel */
- Tcl_SetHashValue (hPtr, clLocPtr);
+ clLocPtr->num = num;
+ memcpy (&clLocPtr->loc, loc, num*sizeof(int));
+ clLocPtr->loc[num] = CLL_END; /* Sentinel */
+ Tcl_SetHashValue (hPtr, clLocPtr);
- return clLocPtr;
+ return clLocPtr;
}
/*
@@ -448,19 +625,16 @@ TclContinuationsEnter(objPtr,num,loc)
*/
void
-TclContinuationsEnterDerived(objPtr, start, clNext)
- Tcl_Obj* objPtr;
- int start;
- int* clNext;
+TclContinuationsEnterDerived(Tcl_Obj* objPtr, int start, int* clNext)
{
/*
* We have to handle invisible continuations lines here as well, despite
- * the code we have in EvalTokensStandard (ETS) for that. Why ?
- * Nesting. If our script is the sole argument to an 'eval' command, for
- * example, the scriptCLLocPtr we are using here was generated by a
- * previous call to ETS, and while the words we have here may contain
- * continuation lines they are invisible already, and the call to ETS
- * above had no bs+nl sequences to trigger its code.
+ * the code we have in TclSubstTokens (TST) for that. Why ? Nesting. If
+ * our script is the sole argument to an 'eval' command, for example, the
+ * scriptCLLocPtr we are using was generated by a previous call to TST,
+ * and while the words we have here may contain continuation lines they
+ * are invisible already, and the inner call to TST had no bs+nl sequences
+ * to trigger its code.
*
* Luckily for us, the table we have to create here for the current word
* has to be a slice of the table currently in use, with the locations
@@ -501,7 +675,7 @@ TclContinuationsEnterDerived(objPtr, start, clNext)
num = wordCLLast - clNext;
if (num) {
int i;
- ContLineLoc* clLocPtr =
+ ContLineLoc* clLocPtr =
TclContinuationsEnter(objPtr, num, clNext);
/*
@@ -547,7 +721,7 @@ TclContinuationsEnterDerived(objPtr, start, clNext)
void
TclContinuationsCopy(Tcl_Obj* objPtr, Tcl_Obj* originObjPtr)
{
- ThreadSpecificData *tsdPtr = TclGetContinuationTable();
+ ThreadSpecificData *tsdPtr = TclGetContLineTable();
Tcl_HashEntry* hPtr = Tcl_FindHashEntry (tsdPtr->lineCLPtr, (char*) originObjPtr);
if (hPtr) {
@@ -577,10 +751,9 @@ TclContinuationsCopy(Tcl_Obj* objPtr, Tcl_Obj* originObjPtr)
*/
ContLineLoc*
-TclContinuationsGet(objPtr)
- Tcl_Obj* objPtr;
+TclContinuationsGet(Tcl_Obj* objPtr)
{
- ThreadSpecificData *tsdPtr = TclGetContinuationTable();
+ ThreadSpecificData *tsdPtr = TclGetContLineTable();
Tcl_HashEntry* hPtr = Tcl_FindHashEntry (tsdPtr->lineCLPtr, (char*) objPtr);
if (hPtr) {
@@ -593,7 +766,7 @@ TclContinuationsGet(objPtr)
/*
*----------------------------------------------------------------------
*
- * TclThreadFinalizeObjects --
+ * TclThreadFinalizeContLines --
*
* This procedure is a helper which releases all continuation line
* information currently known. It is run as a thread exit handler.
@@ -609,31 +782,30 @@ TclContinuationsGet(objPtr)
*/
static void
-TclThreadFinalizeObjects (clientData)
- ClientData clientData;
+TclThreadFinalizeContLines (ClientData clientData)
{
/*
* Release the hashtable tracking invisible continuation lines.
*/
+ ThreadSpecificData *tsdPtr = TclGetContLineTable();
Tcl_HashEntry *hPtr;
Tcl_HashSearch hSearch;
- ThreadSpecificData *tsdPtr = TclGetContinuationTable();
for (hPtr = Tcl_FirstHashEntry(tsdPtr->lineCLPtr, &hSearch);
hPtr != NULL;
hPtr = Tcl_NextHashEntry(&hSearch)) {
/*
- * We are not using Tcl_EventuallyFree (as in
- * TclFreeObj()) because here we can be sure that the
- * compiler will not hold references to the data in the
- * hashtable, and using TEF might bork the finalization
- * sequence.
+ * We are not using Tcl_EventuallyFree (as in TclFreeObj()) because
+ * here we can be sure that the compiler will not hold references to
+ * the data in the hashtable, and using TEF might bork the
+ * finalization sequence.
*/
ContLineLocFree (Tcl_GetHashValue (hPtr));
Tcl_DeleteHashEntry (hPtr);
}
Tcl_DeleteHashTable (tsdPtr->lineCLPtr);
+ ckfree((char *) tsdPtr->lineCLPtr);
tsdPtr->lineCLPtr = NULL;
}
@@ -655,41 +827,41 @@ TclThreadFinalizeObjects (clientData)
*/
static void
-ContLineLocFree (clientData)
- char* clientData;
+ContLineLocFree (char* clientData)
{
- ckfree (clientData);
+ ckfree (clientData);
}
-#endif
+
/*
*--------------------------------------------------------------
*
* Tcl_RegisterObjType --
*
- * This procedure is called to register a new Tcl object type
- * in the table of all object types supported by Tcl.
+ * This function is called to register a new Tcl object type in the table
+ * of all object types supported by Tcl.
*
* Results:
* None.
*
* Side effects:
- * The type is registered in the Tcl type table. If there was already
- * a type with the same name as in typePtr, it is replaced with the
- * new type.
+ * The type is registered in the Tcl type table. If there was already a
+ * type with the same name as in typePtr, it is replaced with the new
+ * type.
*
*--------------------------------------------------------------
*/
void
-Tcl_RegisterObjType(typePtr)
- Tcl_ObjType *typePtr; /* Information about object type;
- * storage must be statically
- * allocated (must live forever). */
+Tcl_RegisterObjType(
+ Tcl_ObjType *typePtr) /* Information about object type; storage must
+ * be statically allocated (must live
+ * forever). */
{
- int new;
+ int isNew;
+
Tcl_MutexLock(&tableMutex);
Tcl_SetHashValue(
- Tcl_CreateHashEntry(&typeTable, typePtr->name, &new), typePtr);
+ Tcl_CreateHashEntry(&typeTable, typePtr->name, &isNew), typePtr);
Tcl_MutexUnlock(&tableMutex);
}
@@ -698,56 +870,54 @@ Tcl_RegisterObjType(typePtr)
*
* Tcl_AppendAllObjTypes --
*
- * This procedure appends onto the argument object the name of each
- * object type as a list element. This includes the builtin object
- * types (e.g. int, list) as well as those added using
- * Tcl_NewObj. These names can be used, for example, with
- * Tcl_GetObjType to get pointers to the corresponding Tcl_ObjType
- * structures.
+ * This function appends onto the argument object the name of each object
+ * type as a list element. This includes the builtin object types (e.g.
+ * int, list) as well as those added using Tcl_NewObj. These names can be
+ * used, for example, with Tcl_GetObjType to get pointers to the
+ * corresponding Tcl_ObjType structures.
*
* Results:
* The return value is normally TCL_OK; in this case the object
- * referenced by objPtr has each type name appended to it. If an
- * error occurs, TCL_ERROR is returned and the interpreter's result
- * holds an error message.
+ * referenced by objPtr has each type name appended to it. If an error
+ * occurs, TCL_ERROR is returned and the interpreter's result holds an
+ * error message.
*
* Side effects:
- * If necessary, the object referenced by objPtr is converted into
- * a list object.
+ * If necessary, the object referenced by objPtr is converted into a list
+ * object.
*
*----------------------------------------------------------------------
*/
int
-Tcl_AppendAllObjTypes(interp, objPtr)
- Tcl_Interp *interp; /* Interpreter used for error reporting. */
- Tcl_Obj *objPtr; /* Points to the Tcl object onto which the
- * name of each registered type is appended
- * as a list element. */
+Tcl_AppendAllObjTypes(
+ Tcl_Interp *interp, /* Interpreter used for error reporting. */
+ Tcl_Obj *objPtr) /* Points to the Tcl object onto which the
+ * name of each registered type is appended as
+ * a list element. */
{
register Tcl_HashEntry *hPtr;
Tcl_HashSearch search;
- int objc;
- Tcl_Obj **objv;
+ int numElems;
/*
* Get the test for a valid list out of the way first.
*/
- if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ if (TclListObjLength(interp, objPtr, &numElems) != TCL_OK) {
return TCL_ERROR;
}
/*
- * Type names are NUL-terminated, not counted strings.
- * This code relies on that.
+ * Type names are NUL-terminated, not counted strings. This code relies on
+ * that.
*/
Tcl_MutexLock(&tableMutex);
for (hPtr = Tcl_FirstHashEntry(&typeTable, &search);
- hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
Tcl_ListObjAppendElement(NULL, objPtr,
- Tcl_NewStringObj(Tcl_GetHashKey(&typeTable, hPtr), -1));
+ Tcl_NewStringObj(Tcl_GetHashKey(&typeTable, hPtr), -1));
}
Tcl_MutexUnlock(&tableMutex);
return TCL_OK;
@@ -758,12 +928,11 @@ Tcl_AppendAllObjTypes(interp, objPtr)
*
* Tcl_GetObjType --
*
- * This procedure looks up an object type by name.
+ * This function looks up an object type by name.
*
* Results:
- * If an object type with name matching "typeName" is found, a pointer
- * to its Tcl_ObjType structure is returned; otherwise, NULL is
- * returned.
+ * If an object type with name matching "typeName" is found, a pointer to
+ * its Tcl_ObjType structure is returned; otherwise, NULL is returned.
*
* Side effects:
* None.
@@ -772,16 +941,16 @@ Tcl_AppendAllObjTypes(interp, objPtr)
*/
Tcl_ObjType *
-Tcl_GetObjType(typeName)
- CONST char *typeName; /* Name of Tcl object type to look up. */
+Tcl_GetObjType(
+ CONST char *typeName) /* Name of Tcl object type to look up. */
{
register Tcl_HashEntry *hPtr;
Tcl_ObjType *typePtr = NULL;
Tcl_MutexLock(&tableMutex);
hPtr = Tcl_FindHashEntry(&typeTable, typeName);
- if (hPtr != (Tcl_HashEntry *) NULL) {
- typePtr = (Tcl_ObjType *) Tcl_GetHashValue(hPtr);
+ if (hPtr != NULL) {
+ typePtr = (Tcl_ObjType *) Tcl_GetHashValue(hPtr);
}
Tcl_MutexUnlock(&tableMutex);
return typePtr;
@@ -796,10 +965,10 @@ Tcl_GetObjType(typeName)
*
* Results:
* The return value is TCL_OK on success and TCL_ERROR on failure. If
- * TCL_ERROR is returned, then the interpreter's result contains an
- * error message unless "interp" is NULL. Passing a NULL "interp"
- * allows this procedure to be used as a test whether the conversion
- * could be done (and in fact was done).
+ * TCL_ERROR is returned, then the interpreter's result contains an error
+ * message unless "interp" is NULL. Passing a NULL "interp" allows this
+ * function to be used as a test whether the conversion could be done
+ * (and in fact was done).
*
* Side effects:
* Any internal representation for the old type is freed.
@@ -808,46 +977,169 @@ Tcl_GetObjType(typeName)
*/
int
-Tcl_ConvertToType(interp, objPtr, typePtr)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- Tcl_Obj *objPtr; /* The object to convert. */
- Tcl_ObjType *typePtr; /* The target type. */
+Tcl_ConvertToType(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tcl_Obj *objPtr, /* The object to convert. */
+ Tcl_ObjType *typePtr) /* The target type. */
{
if (objPtr->typePtr == typePtr) {
return TCL_OK;
}
/*
- * Use the target type's Tcl_SetFromAnyProc to set "objPtr"s internal
- * form as appropriate for the target type. This frees the old internal
+ * Use the target type's Tcl_SetFromAnyProc to set "objPtr"s internal form
+ * as appropriate for the target type. This frees the old internal
* representation.
*/
+ if (typePtr->setFromAnyProc == NULL) {
+ Tcl_Panic("may not convert object to type %s", typePtr->name);
+ }
+
return typePtr->setFromAnyProc(interp, objPtr);
}
/*
+ *--------------------------------------------------------------
+ *
+ * TclDbDumpActiveObjects --
+ *
+ * This function is called to dump all of the active Tcl_Obj structs this
+ * allocator knows about.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TclDbDumpActiveObjects(
+ FILE *outFile)
+{
+#if defined(TCL_MEM_DEBUG) && defined(TCL_THREADS)
+ Tcl_HashSearch hSearch;
+ Tcl_HashEntry *hPtr;
+ Tcl_HashTable *tablePtr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ tablePtr = tsdPtr->objThreadMap;
+
+ if (tablePtr != NULL) {
+ fprintf(outFile, "total objects: %d\n", tablePtr->numEntries);
+ for (hPtr = Tcl_FirstHashEntry(tablePtr, &hSearch); hPtr != NULL;
+ hPtr = Tcl_NextHashEntry(&hSearch)) {
+ ObjData *objData = Tcl_GetHashValue(hPtr);
+
+ if (objData != NULL) {
+ fprintf(outFile,
+ "key = 0x%p, objPtr = 0x%p, file = %s, line = %d\n",
+ Tcl_GetHashKey(tablePtr, hPtr), objData->objPtr,
+ objData->file, objData->line);
+ } else {
+ fprintf(outFile, "key = 0x%p\n",
+ Tcl_GetHashKey(tablePtr, hPtr));
+ }
+ }
+ }
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclDbInitNewObj --
+ *
+ * Called via the TclNewObj or TclDbNewObj macros when TCL_MEM_DEBUG is
+ * enabled. This function will initialize the members of a Tcl_Obj
+ * struct. Initilization would be done inline via the TclNewObj macro
+ * when compiling without TCL_MEM_DEBUG.
+ *
+ * Results:
+ * The Tcl_Obj struct members are initialized.
+ *
+ * Side effects:
+ * None.
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TCL_MEM_DEBUG
+void
+TclDbInitNewObj(
+ register Tcl_Obj *objPtr,
+ register CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ register int line) /* Line number in the source file; used for
+ * debugging. */
+{
+ objPtr->refCount = 0;
+ objPtr->bytes = tclEmptyStringRep;
+ objPtr->length = 0;
+ objPtr->typePtr = NULL;
+
+#ifdef TCL_THREADS
+ /*
+ * Add entry to a thread local map used to check if a Tcl_Obj was
+ * allocated by the currently executing thread.
+ */
+
+ if (!TclInExit()) {
+ Tcl_HashEntry *hPtr;
+ Tcl_HashTable *tablePtr;
+ int isNew;
+ ObjData *objData;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ if (tsdPtr->objThreadMap == NULL) {
+ tsdPtr->objThreadMap = (Tcl_HashTable *)
+ ckalloc(sizeof(Tcl_HashTable));
+ Tcl_InitHashTable(tsdPtr->objThreadMap, TCL_ONE_WORD_KEYS);
+ }
+ tablePtr = tsdPtr->objThreadMap;
+ hPtr = Tcl_CreateHashEntry(tablePtr, (char *) objPtr, &isNew);
+ if (!isNew) {
+ Tcl_Panic("expected to create new entry for object map");
+ }
+
+ /*
+ * Record the debugging information.
+ */
+
+ objData = (ObjData *) ckalloc(sizeof(ObjData));
+ objData->objPtr = objPtr;
+ objData->file = file;
+ objData->line = line;
+ Tcl_SetHashValue(hPtr, objData);
+ }
+#endif /* TCL_THREADS */
+}
+#endif /* TCL_MEM_DEBUG */
+
+/*
*----------------------------------------------------------------------
*
* Tcl_NewObj --
*
- * This procedure is normally called when not debugging: i.e., when
+ * This function is normally called when not debugging: i.e., when
* TCL_MEM_DEBUG is not defined. It creates new Tcl objects that denote
* the empty string. These objects have a NULL object type and NULL
- * string representation byte pointer. Type managers call this routine
- * to allocate new objects that they further initialize.
+ * string representation byte pointer. Type managers call this routine to
+ * allocate new objects that they further initialize.
*
- * When TCL_MEM_DEBUG is defined, this procedure just returns the
- * result of calling the debugging version Tcl_DbNewObj.
+ * When TCL_MEM_DEBUG is defined, this function just returns the result
+ * of calling the debugging version Tcl_DbNewObj.
*
* Results:
* The result is a newly allocated object that represents the empty
- * string. The new object's typePtr is set NULL and its ref count
- * is set to 0.
+ * string. The new object's typePtr is set NULL and its ref count is set
+ * to 0.
*
* Side effects:
- * If compiling with TCL_COMPILE_STATS, this procedure increments
- * the global count of allocated objects (tclObjsAlloced).
+ * If compiling with TCL_COMPILE_STATS, this function increments the
+ * global count of allocated objects (tclObjsAlloced).
*
*----------------------------------------------------------------------
*/
@@ -856,7 +1148,7 @@ Tcl_ConvertToType(interp, objPtr, typePtr)
#undef Tcl_NewObj
Tcl_Obj *
-Tcl_NewObj()
+Tcl_NewObj(void)
{
return Tcl_DbNewObj("unknown", 0);
}
@@ -864,13 +1156,12 @@ Tcl_NewObj()
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
-Tcl_NewObj()
+Tcl_NewObj(void)
{
register Tcl_Obj *objPtr;
/*
- * Use the macro defined in tclInt.h - it will use the
- * correct allocator.
+ * Use the macro defined in tclInt.h - it will use the correct allocator.
*/
TclNewObj(objPtr);
@@ -883,24 +1174,24 @@ Tcl_NewObj()
*
* Tcl_DbNewObj --
*
- * This procedure is normally called when debugging: i.e., when
+ * This function is normally called when debugging: i.e., when
* TCL_MEM_DEBUG is defined. It creates new Tcl objects that denote the
- * empty string. It is the same as the Tcl_NewObj procedure above
- * except that it calls Tcl_DbCkalloc directly with the file name and
- * line number from its caller. This simplifies debugging since then
- * the [memory active] command will report the correct file name and line
+ * empty string. It is the same as the Tcl_NewObj function above except
+ * that it calls Tcl_DbCkalloc directly with the file name and line
+ * number from its caller. This simplifies debugging since then the
+ * [memory active] command will report the correct file name and line
* number when reporting objects that haven't been freed.
*
- * When TCL_MEM_DEBUG is not defined, this procedure just returns the
+ * When TCL_MEM_DEBUG is not defined, this function just returns the
* result of calling Tcl_NewObj.
*
* Results:
- * The result is a newly allocated that represents the empty string.
- * The new object's typePtr is set NULL and its ref count is set to 0.
+ * The result is a newly allocated that represents the empty string. The
+ * new object's typePtr is set NULL and its ref count is set to 0.
*
* Side effects:
- * If compiling with TCL_COMPILE_STATS, this procedure increments
- * the global count of allocated objects (tclObjsAlloced).
+ * If compiling with TCL_COMPILE_STATS, this function increments the
+ * global count of allocated objects (tclObjsAlloced).
*
*----------------------------------------------------------------------
*/
@@ -908,17 +1199,16 @@ Tcl_NewObj()
#ifdef TCL_MEM_DEBUG
Tcl_Obj *
-Tcl_DbNewObj(file, line)
- register CONST char *file; /* The name of the source file calling this
- * procedure; used for debugging. */
- register int line; /* Line number in the source file; used
- * for debugging. */
+Tcl_DbNewObj(
+ register CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ register int line) /* Line number in the source file; used for
+ * debugging. */
{
register Tcl_Obj *objPtr;
/*
- * Use the macro defined in tclInt.h - it will use the
- * correct allocator.
+ * Use the macro defined in tclInt.h - it will use the correct allocator.
*/
TclDbNewObj(objPtr, file, line);
@@ -927,11 +1217,11 @@ Tcl_DbNewObj(file, line)
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
-Tcl_DbNewObj(file, line)
- CONST char *file; /* The name of the source file calling this
- * procedure; used for debugging. */
- int line; /* Line number in the source file; used
- * for debugging. */
+Tcl_DbNewObj(
+ CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
return Tcl_NewObj();
}
@@ -942,8 +1232,8 @@ Tcl_DbNewObj(file, line)
*
* TclAllocateFreeObjects --
*
- * Procedure to allocate a number of free Tcl_Objs. This is done using
- * a single ckalloc to reduce the overhead for Tcl_Obj allocation.
+ * Function to allocate a number of free Tcl_Objs. This is done using a
+ * single ckalloc to reduce the overhead for Tcl_Obj allocation.
*
* Assumes mutex is held.
*
@@ -961,7 +1251,7 @@ Tcl_DbNewObj(file, line)
#define OBJS_TO_ALLOC_EACH_TIME 100
void
-TclAllocateFreeObjects()
+TclAllocateFreeObjects(void)
{
size_t bytesToAlloc = (OBJS_TO_ALLOC_EACH_TIME * sizeof(Tcl_Obj));
char *basePtr;
@@ -969,22 +1259,20 @@ TclAllocateFreeObjects()
register int i;
/*
- * This has been noted by Purify to be a potential leak. The problem is
+ * This has been noted by Purify to be a potential leak. The problem is
* that Tcl, when not TCL_MEM_DEBUG compiled, keeps around all allocated
- * Tcl_Obj's, pointed to by tclFreeObjList, when freed instead of
- * actually freeing the memory. TclFinalizeObjects() does not ckfree()
- * this memory, but leaves it to Tcl's memory subsystem finalziation to
- * release it. Purify apparently can't figure that out, and fires a
- * false alarm.
+ * Tcl_Obj's, pointed to by tclFreeObjList, when freed instead of actually
+ * freeing the memory. TclFinalizeObjects() does not ckfree() this memory,
+ * but leaves it to Tcl's memory subsystem finalization to release it.
+ * Purify apparently can't figure that out, and fires a false alarm.
*/
basePtr = (char *) ckalloc(bytesToAlloc);
- memset(basePtr, 0, bytesToAlloc);
prevPtr = NULL;
objPtr = (Tcl_Obj *) basePtr;
for (i = 0; i < OBJS_TO_ALLOC_EACH_TIME; i++) {
- objPtr->internalRep.otherValuePtr = (VOID *) prevPtr;
+ objPtr->internalRep.otherValuePtr = (void *) prevPtr;
prevPtr = objPtr;
objPtr++;
}
@@ -997,64 +1285,166 @@ TclAllocateFreeObjects()
*
* TclFreeObj --
*
- * This procedure frees the memory associated with the argument
- * object. It is called by the tcl.h macro Tcl_DecrRefCount when an
- * object's ref count is zero. It is only "public" since it must
- * be callable by that macro wherever the macro is used. It should not
- * be directly called by clients.
+ * This function frees the memory associated with the argument object.
+ * It is called by the tcl.h macro Tcl_DecrRefCount when an object's ref
+ * count is zero. It is only "public" since it must be callable by that
+ * macro wherever the macro is used. It should not be directly called by
+ * clients.
*
* Results:
* None.
*
* Side effects:
- * Deallocates the storage for the object's Tcl_Obj structure
- * after deallocating the string representation and calling the
- * type-specific Tcl_FreeInternalRepProc to deallocate the object's
- * internal representation. If compiling with TCL_COMPILE_STATS,
- * this procedure increments the global count of freed objects
- * (tclObjsFreed).
+ * Deallocates the storage for the object's Tcl_Obj structure after
+ * deallocating the string representation and calling the type-specific
+ * Tcl_FreeInternalRepProc to deallocate the object's internal
+ * representation. If compiling with TCL_COMPILE_STATS, this function
+ * increments the global count of freed objects (tclObjsFreed).
*
*----------------------------------------------------------------------
*/
+#ifdef TCL_MEM_DEBUG
void
-TclFreeObj(objPtr)
- register Tcl_Obj *objPtr; /* The object to be freed. */
+TclFreeObj(
+ register Tcl_Obj *objPtr) /* The object to be freed. */
{
register Tcl_ObjType *typePtr = objPtr->typePtr;
-
-#ifdef TCL_MEM_DEBUG
- if ((objPtr)->refCount < -1) {
- panic("Reference count for %lx was negative", objPtr);
+
+ /*
+ * This macro declares a variable, so must come here...
+ */
+
+ ObjInitDeletionContext(context);
+
+ if (objPtr->refCount < -1) {
+ Tcl_Panic("Reference count for %lx was negative", objPtr);
}
-#endif /* TCL_MEM_DEBUG */
- TCL_DTRACE_OBJ_FREE(objPtr);
- if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
- typePtr->freeIntRepProc(objPtr);
+ /* Invalidate the string rep first so we can use the bytes value
+ * for our pointer chain, and signal an obj deletion (as opposed
+ * to shimmering) with 'length == -1' */
+
+ TclInvalidateStringRep(objPtr);
+ objPtr->length = -1;
+
+ if (ObjDeletePending(context)) {
+ PushObjToDelete(context, objPtr);
+ } else {
+ TCL_DTRACE_OBJ_FREE(objPtr);
+ if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+ ObjDeletionLock(context);
+ typePtr->freeIntRepProc(objPtr);
+ ObjDeletionUnlock(context);
+ }
+
+ Tcl_MutexLock(&tclObjMutex);
+ ckfree((char *) objPtr);
+ Tcl_MutexUnlock(&tclObjMutex);
+ TclIncrObjsFreed();
+ ObjDeletionLock(context);
+ while (ObjOnStack(context)) {
+ Tcl_Obj *objToFree;
+
+ PopObjToDelete(context,objToFree);
+ TCL_DTRACE_OBJ_FREE(objToFree);
+ TclFreeIntRep(objToFree);
+
+ Tcl_MutexLock(&tclObjMutex);
+ ckfree((char *) objToFree);
+ Tcl_MutexUnlock(&tclObjMutex);
+ TclIncrObjsFreed();
+ }
+ ObjDeletionUnlock(context);
}
- Tcl_InvalidateStringRep(objPtr);
/*
- * If debugging Tcl's memory usage, deallocate the object using ckfree.
- * Otherwise, deallocate it by adding it onto the list of free
- * Tcl_Obj structs we maintain.
+ * We cannot use TclGetContinuationTable() here, because that may
+ * re-initialize the thread-data for calls coming after the
+ * finalization. We have to access it using the low-level call and then
+ * check for validity. This function can be called after
+ * TclFinalizeThreadData() has already killed the thread-global data
+ * structures. Performing TCL_TSD_INIT will leave us with an
+ * un-initialized memory block upon which we crash (if we where to access
+ * the uninitialized hashtable).
*/
-#if defined(TCL_MEM_DEBUG) || defined(PURIFY)
- Tcl_MutexLock(&tclObjMutex);
- ckfree((char *) objPtr);
- Tcl_MutexUnlock(&tclObjMutex);
-#elif defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
- TclThreadFreeObj(objPtr);
-#else
- Tcl_MutexLock(&tclObjMutex);
- objPtr->internalRep.otherValuePtr = (VOID *) tclFreeObjList;
- tclFreeObjList = objPtr;
- Tcl_MutexUnlock(&tclObjMutex);
-#endif /* TCL_MEM_DEBUG */
+ {
+ ThreadSpecificData* tsdPtr = TCL_TSD_INIT(&dataKey);
+ if (tsdPtr->lineCLPtr) {
+ Tcl_HashEntry* hPtr = Tcl_FindHashEntry (tsdPtr->lineCLPtr, (char *) objPtr);
+ if (hPtr) {
+ Tcl_EventuallyFree (Tcl_GetHashValue (hPtr), ContLineLocFree);
+ Tcl_DeleteHashEntry (hPtr);
+ }
+ }
+ }
+}
+#else /* TCL_MEM_DEBUG */
+
+void
+TclFreeObj(
+ register Tcl_Obj *objPtr) /* The object to be freed. */
+{
+ /* Invalidate the string rep first so we can use the bytes value
+ * for our pointer chain, and signal an obj deletion (as opposed
+ * to shimmering) with 'length == -1' */
+
+ TclInvalidateStringRep(objPtr);
+ objPtr->length = -1;
+
+ if (!objPtr->typePtr || !objPtr->typePtr->freeIntRepProc) {
+ /*
+ * objPtr can be freed safely, as it will not attempt to free any
+ * other objects: it will not cause recursive calls to this function.
+ */
+
+ TCL_DTRACE_OBJ_FREE(objPtr);
+ TclFreeObjStorage(objPtr);
+ TclIncrObjsFreed();
+ } else {
+ /*
+ * This macro declares a variable, so must come here...
+ */
+
+ ObjInitDeletionContext(context);
+
+ if (ObjDeletePending(context)) {
+ PushObjToDelete(context, objPtr);
+ } else {
+ /*
+ * Note that the contents of the while loop assume that the string
+ * rep has already been freed and we don't want to do anything
+ * fancy with adding to the queue inside ourselves. Must take care
+ * to unstack the object first since freeing the internal rep can
+ * add further objects to the stack. The code assumes that it is
+ * the first thing in a block; all current usages in the core
+ * satisfy this.
+ */
+
+ TCL_DTRACE_OBJ_FREE(objPtr);
+ ObjDeletionLock(context);
+ objPtr->typePtr->freeIntRepProc(objPtr);
+ ObjDeletionUnlock(context);
+
+ TclFreeObjStorage(objPtr);
+ TclIncrObjsFreed();
+ ObjDeletionLock(context);
+ while (ObjOnStack(context)) {
+ Tcl_Obj *objToFree;
+ PopObjToDelete(context,objToFree);
+ TCL_DTRACE_OBJ_FREE(objToFree);
+ if ((objToFree->typePtr != NULL)
+ && (objToFree->typePtr->freeIntRepProc != NULL)) {
+ objToFree->typePtr->freeIntRepProc(objToFree);
+ }
+ TclFreeObjStorage(objToFree);
+ TclIncrObjsFreed();
+ }
+ ObjDeletionUnlock(context);
+ }
+ }
-#ifdef TCL_TIP280
/*
* We cannot use TclGetContinuationTable() here, because that may
* re-initialize the thread-data for calls coming after the
@@ -1076,9 +1466,34 @@ TclFreeObj(objPtr)
}
}
}
+}
#endif
- TclIncrObjsFreed();
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclObjBeingDeleted --
+ *
+ * This function returns 1 when the Tcl_Obj is being deleted. It is
+ * provided for the rare cases where the reason for the loss of an
+ * internal rep might be relevant. [FR 1512138]
+ *
+ * Results:
+ * 1 if being deleted, 0 otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclObjBeingDeleted(
+ Tcl_Obj *objPtr)
+{
+ return (objPtr->length == -1);
}
+
/*
*----------------------------------------------------------------------
@@ -1089,29 +1504,29 @@ TclFreeObj(objPtr)
* object.
*
* Results:
- * The return value is a pointer to a newly created Tcl_Obj. This
- * object has reference count 0 and the same type, if any, as the
- * source object objPtr. Also:
+ * The return value is a pointer to a newly created Tcl_Obj. This object
+ * has reference count 0 and the same type, if any, as the source object
+ * objPtr. Also:
* 1) If the source object has a valid string rep, we copy it;
- * otherwise, the duplicate's string rep is set NULL to mark
- * it invalid.
+ * otherwise, the duplicate's string rep is set NULL to mark it
+ * invalid.
* 2) If the source object has an internal representation (i.e. its
- * typePtr is non-NULL), the new object's internal rep is set to
- * a copy; otherwise the new internal rep is marked invalid.
+ * typePtr is non-NULL), the new object's internal rep is set to a
+ * copy; otherwise the new internal rep is marked invalid.
*
* Side effects:
- * What constitutes "copying" the internal representation depends on
- * the type. For example, if the argument object is a list,
- * the element objects it points to will not actually be copied but
- * will be shared with the duplicate list. That is, the ref counts of
- * the element objects will be incremented.
+ * What constitutes "copying" the internal representation depends on the
+ * type. For example, if the argument object is a list, the element
+ * objects it points to will not actually be copied but will be shared
+ * with the duplicate list. That is, the ref counts of the element
+ * objects will be incremented.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
-Tcl_DuplicateObj(objPtr)
- register Tcl_Obj *objPtr; /* The object to duplicate. */
+Tcl_DuplicateObj(
+ register Tcl_Obj *objPtr) /* The object to duplicate. */
{
register Tcl_ObjType *typePtr = objPtr->typePtr;
register Tcl_Obj *dupPtr;
@@ -1123,7 +1538,7 @@ Tcl_DuplicateObj(objPtr)
} else if (objPtr->bytes != tclEmptyStringRep) {
TclInitStringRep(dupPtr, objPtr->bytes, objPtr->length);
}
-
+
if (typePtr != NULL) {
if (typePtr->dupIntRepProc == NULL) {
dupPtr->internalRep = objPtr->internalRep;
@@ -1157,16 +1572,16 @@ Tcl_DuplicateObj(objPtr)
*/
char *
-Tcl_GetString(objPtr)
- register Tcl_Obj *objPtr; /* Object whose string rep byte pointer
- * should be returned. */
+Tcl_GetString(
+ register Tcl_Obj *objPtr) /* Object whose string rep byte pointer should
+ * be returned. */
{
if (objPtr->bytes != NULL) {
return objPtr->bytes;
}
if (objPtr->typePtr->updateStringProc == NULL) {
- panic("UpdateStringProc should not be invoked for type %s",
+ Tcl_Panic("UpdateStringProc should not be invoked for type %s",
objPtr->typePtr->name);
}
(*objPtr->typePtr->updateStringProc)(objPtr);
@@ -1178,16 +1593,16 @@ Tcl_GetString(objPtr)
*
* Tcl_GetStringFromObj --
*
- * Returns the string representation's byte array pointer and length
- * for an object.
+ * Returns the string representation's byte array pointer and length for
+ * an object.
*
* Results:
- * Returns a pointer to the string representation of objPtr. If
- * lengthPtr isn't NULL, the length of the string representation is
- * stored at *lengthPtr. The byte array referenced by the returned
- * pointer must not be modified by the caller. Furthermore, the
- * caller must copy the bytes if they need to retain them since the
- * object's string rep can change as a result of other operations.
+ * Returns a pointer to the string representation of objPtr. If lengthPtr
+ * isn't NULL, the length of the string representation is stored at
+ * *lengthPtr. The byte array referenced by the returned pointer must not
+ * be modified by the caller. Furthermore, the caller must copy the bytes
+ * if they need to retain them since the object's string rep can change
+ * as a result of other operations.
*
* Side effects:
* May call the object's updateStringProc to update the string
@@ -1197,16 +1612,16 @@ Tcl_GetString(objPtr)
*/
char *
-Tcl_GetStringFromObj(objPtr, lengthPtr)
- register Tcl_Obj *objPtr; /* Object whose string rep byte pointer should
+Tcl_GetStringFromObj(
+ register Tcl_Obj *objPtr, /* Object whose string rep byte pointer should
* be returned. */
- register int *lengthPtr; /* If non-NULL, the location where the string
+ register int *lengthPtr) /* If non-NULL, the location where the string
* rep's byte array length should * be stored.
* If NULL, no length is stored. */
{
if (objPtr->bytes == NULL) {
if (objPtr->typePtr->updateStringProc == NULL) {
- panic("UpdateStringProc should not be invoked for type %s",
+ Tcl_Panic("UpdateStringProc should not be invoked for type %s",
objPtr->typePtr->name);
}
(*objPtr->typePtr->updateStringProc)(objPtr);
@@ -1223,48 +1638,44 @@ Tcl_GetStringFromObj(objPtr, lengthPtr)
*
* Tcl_InvalidateStringRep --
*
- * This procedure is called to invalidate an object's string
- * representation.
+ * This function is called to invalidate an object's string
+ * representation.
*
* Results:
* None.
*
* Side effects:
- * Deallocates the storage for any old string representation, then
- * sets the string representation NULL to mark it invalid.
+ * Deallocates the storage for any old string representation, then sets
+ * the string representation NULL to mark it invalid.
*
*----------------------------------------------------------------------
*/
void
-Tcl_InvalidateStringRep(objPtr)
- register Tcl_Obj *objPtr; /* Object whose string rep byte pointer
- * should be freed. */
+Tcl_InvalidateStringRep(
+ register Tcl_Obj *objPtr) /* Object whose string rep byte pointer should
+ * be freed. */
{
- if (objPtr->bytes != NULL) {
- if (objPtr->bytes != tclEmptyStringRep) {
- ckfree((char *) objPtr->bytes);
- }
- objPtr->bytes = NULL;
- }
+ TclInvalidateStringRep(objPtr);
}
+
/*
*----------------------------------------------------------------------
*
* Tcl_NewBooleanObj --
*
- * This procedure is normally called when not debugging: i.e., when
+ * This function is normally called when not debugging: i.e., when
* TCL_MEM_DEBUG is not defined. It creates a new Tcl_Obj and
- * initializes it from the argument boolean value. A nonzero
- * "boolValue" is coerced to 1.
+ * initializes it from the argument boolean value. A nonzero "boolValue"
+ * is coerced to 1.
*
- * When TCL_MEM_DEBUG is defined, this procedure just returns the
- * result of calling the debugging version Tcl_DbNewBooleanObj.
+ * When TCL_MEM_DEBUG is defined, this function just returns the result
+ * of calling the debugging version Tcl_DbNewBooleanObj.
*
* Results:
- * The newly created object is returned. This object will have an
- * invalid string representation. The returned object has ref count 0.
+ * The newly created object is returned. This object will have an invalid
+ * string representation. The returned object has ref count 0.
*
* Side effects:
* None.
@@ -1276,8 +1687,8 @@ Tcl_InvalidateStringRep(objPtr)
#undef Tcl_NewBooleanObj
Tcl_Obj *
-Tcl_NewBooleanObj(boolValue)
- register int boolValue; /* Boolean used to initialize new object. */
+Tcl_NewBooleanObj(
+ register int boolValue) /* Boolean used to initialize new object. */
{
return Tcl_DbNewBooleanObj(boolValue, "unknown", 0);
}
@@ -1285,16 +1696,12 @@ Tcl_NewBooleanObj(boolValue)
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
-Tcl_NewBooleanObj(boolValue)
- register int boolValue; /* Boolean used to initialize new object. */
+Tcl_NewBooleanObj(
+ register int boolValue) /* Boolean used to initialize new object. */
{
register Tcl_Obj *objPtr;
- TclNewObj(objPtr);
- objPtr->bytes = NULL;
-
- objPtr->internalRep.longValue = (boolValue? 1 : 0);
- objPtr->typePtr = &tclBooleanType;
+ TclNewBooleanObj(objPtr, boolValue);
return objPtr;
}
#endif /* TCL_MEM_DEBUG */
@@ -1304,20 +1711,20 @@ Tcl_NewBooleanObj(boolValue)
*
* Tcl_DbNewBooleanObj --
*
- * This procedure is normally called when debugging: i.e., when
+ * This function is normally called when debugging: i.e., when
* TCL_MEM_DEBUG is defined. It creates new boolean objects. It is the
- * same as the Tcl_NewBooleanObj procedure above except that it calls
+ * same as the Tcl_NewBooleanObj function above except that it calls
* Tcl_DbCkalloc directly with the file name and line number from its
* caller. This simplifies debugging since then the [memory active]
- * command will report the correct file name and line number when
+ * command will report the correct file name and line number when
* reporting objects that haven't been freed.
*
- * When TCL_MEM_DEBUG is not defined, this procedure just returns the
+ * When TCL_MEM_DEBUG is not defined, this function just returns the
* result of calling Tcl_NewBooleanObj.
*
* Results:
- * The newly created object is returned. This object will have an
- * invalid string representation. The returned object has ref count 0.
+ * The newly created object is returned. This object will have an invalid
+ * string representation. The returned object has ref count 0.
*
* Side effects:
* None.
@@ -1328,32 +1735,32 @@ Tcl_NewBooleanObj(boolValue)
#ifdef TCL_MEM_DEBUG
Tcl_Obj *
-Tcl_DbNewBooleanObj(boolValue, file, line)
- register int boolValue; /* Boolean used to initialize new object. */
- CONST char *file; /* The name of the source file calling this
- * procedure; used for debugging. */
- int line; /* Line number in the source file; used
- * for debugging. */
+Tcl_DbNewBooleanObj(
+ register int boolValue, /* Boolean used to initialize new object. */
+ CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
register Tcl_Obj *objPtr;
TclDbNewObj(objPtr, file, line);
objPtr->bytes = NULL;
-
+
objPtr->internalRep.longValue = (boolValue? 1 : 0);
- objPtr->typePtr = &tclBooleanType;
+ objPtr->typePtr = &tclIntType;
return objPtr;
}
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
-Tcl_DbNewBooleanObj(boolValue, file, line)
- register int boolValue; /* Boolean used to initialize new object. */
- CONST char *file; /* The name of the source file calling this
- * procedure; used for debugging. */
- int line; /* Line number in the source file; used
- * for debugging. */
+Tcl_DbNewBooleanObj(
+ register int boolValue, /* Boolean used to initialize new object. */
+ CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
return Tcl_NewBooleanObj(boolValue);
}
@@ -1371,30 +1778,22 @@ Tcl_DbNewBooleanObj(boolValue, file, line)
* None.
*
* Side effects:
- * The object's old string rep, if any, is freed. Also, any old
- * internal rep is freed.
+ * The object's old string rep, if any, is freed. Also, any old internal
+ * rep is freed.
*
*----------------------------------------------------------------------
*/
void
-Tcl_SetBooleanObj(objPtr, boolValue)
- register Tcl_Obj *objPtr; /* Object whose internal rep to init. */
- register int boolValue; /* Boolean used to set object's value. */
+Tcl_SetBooleanObj(
+ register Tcl_Obj *objPtr, /* Object whose internal rep to init. */
+ register int boolValue) /* Boolean used to set object's value. */
{
- register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
-
if (Tcl_IsShared(objPtr)) {
- panic("Tcl_SetBooleanObj called with shared object");
+ Tcl_Panic("%s called with shared object", "Tcl_SetBooleanObj");
}
-
- if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
- oldTypePtr->freeIntRepProc(objPtr);
- }
-
- objPtr->internalRep.longValue = (boolValue? 1 : 0);
- objPtr->typePtr = &tclBooleanType;
- Tcl_InvalidateStringRep(objPtr);
+
+ TclSetBooleanObj(objPtr, boolValue);
}
/*
@@ -1402,9 +1801,8 @@ Tcl_SetBooleanObj(objPtr, boolValue)
*
* Tcl_GetBooleanFromObj --
*
- * Attempt to return a boolean from the Tcl object "objPtr". If the
- * object is not already a boolean, an attempt will be made to convert
- * it to one.
+ * Attempt to return a boolean from the Tcl object "objPtr". This
+ * includes conversion from any of Tcl's numeric types.
*
* Results:
* The return value is a standard Tcl object result. If an error occurs
@@ -1412,30 +1810,56 @@ Tcl_SetBooleanObj(objPtr, boolValue)
* result unless "interp" is NULL.
*
* Side effects:
- * If the object is not already a boolean, the conversion will free
- * any old internal representation.
+ * The intrep of *objPtr may be changed.
*
*----------------------------------------------------------------------
*/
int
-Tcl_GetBooleanFromObj(interp, objPtr, boolPtr)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- register Tcl_Obj *objPtr; /* The object from which to get boolean. */
- register int *boolPtr; /* Place to store resulting boolean. */
+Tcl_GetBooleanFromObj(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ register Tcl_Obj *objPtr, /* The object from which to get boolean. */
+ register int *boolPtr) /* Place to store resulting boolean. */
{
- register int result;
+ do {
+ if (objPtr->typePtr == &tclIntType) {
+ *boolPtr = (objPtr->internalRep.longValue != 0);
+ return TCL_OK;
+ }
+ if (objPtr->typePtr == &tclBooleanType) {
+ *boolPtr = (int) objPtr->internalRep.longValue;
+ return TCL_OK;
+ }
+ if (objPtr->typePtr == &tclDoubleType) {
+ /*
+ * Caution: Don't be tempted to check directly for the "double"
+ * Tcl_ObjType and then compare the intrep to 0.0. This isn't
+ * reliable because a "double" Tcl_ObjType can hold the NaN value.
+ * Use the API Tcl_GetDoubleFromObj, which does the checking and
+ * sets the proper error message for us.
+ */
- if (objPtr->typePtr == &tclBooleanType) {
- result = TCL_OK;
- } else {
- result = SetBooleanFromAny(interp, objPtr);
- }
+ double d;
- if (result == TCL_OK) {
- *boolPtr = (int) objPtr->internalRep.longValue;
- }
- return result;
+ if (Tcl_GetDoubleFromObj(interp, objPtr, &d) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *boolPtr = (d != 0.0);
+ return TCL_OK;
+ }
+ if (objPtr->typePtr == &tclBignumType) {
+ *boolPtr = 1;
+ return TCL_OK;
+ }
+#ifndef NO_WIDE_TYPE
+ if (objPtr->typePtr == &tclWideIntType) {
+ *boolPtr = (objPtr->internalRep.wideValue != 0);
+ return TCL_OK;
+ }
+#endif
+ } while ((ParseBoolean(objPtr) == TCL_OK) || (TCL_OK ==
+ TclParseNumber(interp, objPtr, "boolean value", NULL,-1,NULL,0)));
+ return TCL_ERROR;
}
/*
@@ -1452,218 +1876,174 @@ Tcl_GetBooleanFromObj(interp, objPtr, boolPtr)
* unless "interp" is NULL.
*
* Side effects:
- * If no error occurs, an integer 1 or 0 is stored as "objPtr"s
- * internal representation and the type of "objPtr" is set to boolean.
+ * If no error occurs, an integer 1 or 0 is stored as "objPtr"s internal
+ * representation and the type of "objPtr" is set to boolean.
*
*----------------------------------------------------------------------
*/
static int
-SetBooleanFromAny(interp, objPtr)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- register Tcl_Obj *objPtr; /* The object to convert. */
-{
- Tcl_ObjType *oldTypePtr = objPtr->typePtr;
- char *string, *end;
- register char c;
- char lowerCase[10];
- int newBool, length;
- register int i;
-
+SetBooleanFromAny(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ register Tcl_Obj *objPtr) /* The object to convert. */
+{
/*
- * Get the string representation. Make it up-to-date if necessary.
+ * For some "pure" numeric Tcl_ObjTypes (no string rep), we can determine
+ * whether a boolean conversion is possible without generating the string
+ * rep.
*/
-
- string = Tcl_GetStringFromObj(objPtr, &length);
+
+ if (objPtr->bytes == NULL) {
+ if (objPtr->typePtr == &tclIntType) {
+ switch (objPtr->internalRep.longValue) {
+ case 0L: case 1L:
+ return TCL_OK;
+ }
+ goto badBoolean;
+ }
+
+ if (objPtr->typePtr == &tclBignumType) {
+ goto badBoolean;
+ }
+
+#ifndef NO_WIDE_TYPE
+ if (objPtr->typePtr == &tclWideIntType) {
+ goto badBoolean;
+ }
+#endif
+
+ if (objPtr->typePtr == &tclDoubleType) {
+ goto badBoolean;
+ }
+ }
+
+ if (ParseBoolean(objPtr) == TCL_OK) {
+ return TCL_OK;
+ }
+
+ badBoolean:
+ if (interp != NULL) {
+ int length;
+ char *str = Tcl_GetStringFromObj(objPtr, &length);
+ Tcl_Obj *msg;
+
+ TclNewLiteralStringObj(msg, "expected boolean value but got \"");
+ Tcl_AppendLimitedToObj(msg, str, length, 50, "");
+ Tcl_AppendToObj(msg, "\"", -1);
+ Tcl_SetObjResult(interp, msg);
+ }
+ return TCL_ERROR;
+}
+
+static int
+ParseBoolean(
+ register Tcl_Obj *objPtr) /* The object to parse/convert. */
+{
+ int i, length, newBool;
+ char lowerCase[6], *str = TclGetStringFromObj(objPtr, &length);
+
+ if ((length == 0) || (length > 5)) {
+ /* longest valid boolean string rep. is "false" */
+ return TCL_ERROR;
+ }
+
+ switch (str[0]) {
+ case '0':
+ if (length == 1) {
+ newBool = 0;
+ goto numericBoolean;
+ }
+ return TCL_ERROR;
+ case '1':
+ if (length == 1) {
+ newBool = 1;
+ goto numericBoolean;
+ }
+ return TCL_ERROR;
+ }
/*
- * Use the obvious shortcuts for numerical values; if objPtr is not
- * of numerical type, parse its string rep.
+ * Force to lower case for case-insensitive detection. Filter out known
+ * invalid characters at the same time.
*/
-
- if (objPtr->typePtr == &tclIntType) {
- newBool = (objPtr->internalRep.longValue != 0);
- } else if (objPtr->typePtr == &tclDoubleType) {
- newBool = (objPtr->internalRep.doubleValue != 0.0);
- } else if (objPtr->typePtr == &tclWideIntType) {
- newBool = (objPtr->internalRep.wideValue != 0);
- } else {
- /*
- * Copy the string converting its characters to lower case.
- */
-
- for (i = 0; (i < 9) && (i < length); i++) {
- c = string[i];
- /*
- * Weed out international characters so we can safely operate
- * on single bytes.
- */
-
- if (c & 0x80) {
- goto badBoolean;
- }
- if (Tcl_UniCharIsUpper(UCHAR(c))) {
- c = (char) Tcl_UniCharToLower(UCHAR(c));
- }
+
+ for (i=0; i < length; i++) {
+ char c = str[i];
+ switch (c) {
+ case 'A': case 'E': case 'F': case 'L': case 'N':
+ case 'O': case 'R': case 'S': case 'T': case 'U': case 'Y':
+ lowerCase[i] = c + (char) ('a' - 'A');
+ break;
+ case 'a': case 'e': case 'f': case 'l': case 'n':
+ case 'o': case 'r': case 's': case 't': case 'u': case 'y':
lowerCase[i] = c;
+ break;
+ default:
+ return TCL_ERROR;
}
- lowerCase[i] = 0;
-
+ }
+ lowerCase[length] = 0;
+ switch (lowerCase[0]) {
+ case 'y':
/*
- * Parse the string as a boolean. We use an implementation here that
- * doesn't report errors in interp if interp is NULL.
+ * Checking the 'y' is redundant, but makes the code clearer.
*/
-
- c = lowerCase[0];
- if ((c == '0') && (lowerCase[1] == '\0')) {
- newBool = 0;
- } else if ((c == '1') && (lowerCase[1] == '\0')) {
+ if (strncmp(lowerCase, "yes", (size_t) length) == 0) {
newBool = 1;
- } else if ((c == 'y') && (strncmp(lowerCase, "yes", (size_t) length) == 0)) {
+ goto goodBoolean;
+ }
+ return TCL_ERROR;
+ case 'n':
+ if (strncmp(lowerCase, "no", (size_t) length) == 0) {
+ newBool = 0;
+ goto goodBoolean;
+ }
+ return TCL_ERROR;
+ case 't':
+ if (strncmp(lowerCase, "true", (size_t) length) == 0) {
newBool = 1;
- } else if ((c == 'n') && (strncmp(lowerCase, "no", (size_t) length) == 0)) {
+ goto goodBoolean;
+ }
+ return TCL_ERROR;
+ case 'f':
+ if (strncmp(lowerCase, "false", (size_t) length) == 0) {
newBool = 0;
- } else if ((c == 't') && (strncmp(lowerCase, "true", (size_t) length) == 0)) {
+ goto goodBoolean;
+ }
+ return TCL_ERROR;
+ case 'o':
+ if (length < 2) {
+ return TCL_ERROR;
+ }
+ if (strncmp(lowerCase, "on", (size_t) length) == 0) {
newBool = 1;
- } else if ((c == 'f') && (strncmp(lowerCase, "false", (size_t) length) == 0)) {
+ goto goodBoolean;
+ } else if (strncmp(lowerCase, "off", (size_t) length) == 0) {
newBool = 0;
- } else if ((c == 'o') && (length >= 2)) {
- if (strncmp(lowerCase, "on", (size_t) length) == 0) {
- newBool = 1;
- } else if (strncmp(lowerCase, "off", (size_t) length) == 0) {
- newBool = 0;
- } else {
- goto badBoolean;
- }
- } else {
- double dbl;
- /*
- * Boolean values can be extracted from ints or doubles. Note
- * that we don't use strtoul or strtoull here because we don't
- * care about what the value is, just whether it is equal to
- * zero or not.
- */
-#ifdef TCL_WIDE_INT_IS_LONG
- newBool = strtol(string, &end, 0);
- if (end != string) {
- /*
- * Make sure the string has no garbage after the end of
- * the int.
- */
- while ((end < (string+length))
- && isspace(UCHAR(*end))) { /* INTL: ISO only */
- end++;
- }
- if (end == (string+length)) {
- newBool = (newBool != 0);
- goto goodBoolean;
- }
- }
-#else /* !TCL_WIDE_INT_IS_LONG */
- Tcl_WideInt wide = strtoll(string, &end, 0);
- if (end != string) {
- /*
- * Make sure the string has no garbage after the end of
- * the wide int.
- */
- while ((end < (string+length))
- && isspace(UCHAR(*end))) { /* INTL: ISO only */
- end++;
- }
- if (end == (string+length)) {
- newBool = (wide != Tcl_LongAsWide(0));
- goto goodBoolean;
- }
- }
-#endif /* TCL_WIDE_INT_IS_LONG */
- /*
- * Still might be a string containing the characters representing an
- * int or double that wasn't handled above. This would be a string
- * like "27" or "1.0" that is non-zero and not "1". Such a string
- * would result in the boolean value true. We try converting to
- * double. If that succeeds and the resulting double is non-zero, we
- * have a "true". Note that numbers can't have embedded NULLs.
- */
-
- dbl = strtod(string, &end);
- if (end == string) {
- goto badBoolean;
- }
-
- /*
- * Make sure the string has no garbage after the end of the double.
- */
-
- while ((end < (string+length))
- && isspace(UCHAR(*end))) { /* INTL: ISO only */
- end++;
- }
- if (end != (string+length)) {
- goto badBoolean;
- }
- newBool = (dbl != 0.0);
+ goto goodBoolean;
}
+ return TCL_ERROR;
+ default:
+ return TCL_ERROR;
}
/*
- * Free the old internalRep before setting the new one. We do this as
- * late as possible to allow the conversion code, in particular
+ * Free the old internalRep before setting the new one. We do this as late
+ * as possible to allow the conversion code, in particular
* Tcl_GetStringFromObj, to use that old internalRep.
*/
- goodBoolean:
- if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
- oldTypePtr->freeIntRepProc(objPtr);
- }
-
+ goodBoolean:
+ TclFreeIntRep(objPtr);
objPtr->internalRep.longValue = newBool;
objPtr->typePtr = &tclBooleanType;
return TCL_OK;
- badBoolean:
- if (interp != NULL) {
- /*
- * Must copy string before resetting the result in case a caller
- * is trying to convert the interpreter's result to a boolean.
- */
-
- char buf[100];
- sprintf(buf, "expected boolean value but got \"%.50s\"", string);
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
- }
- return TCL_ERROR;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * UpdateStringOfBoolean --
- *
- * Update the string representation for a boolean object.
- * Note: This procedure does not free an existing old string rep
- * so storage will be lost if this has not already been done.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The object's string is set to a valid string that results from
- * the boolean-to-string conversion.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-UpdateStringOfBoolean(objPtr)
- register Tcl_Obj *objPtr; /* Int object whose string rep to update. */
-{
- char *s = ckalloc((unsigned) 2);
-
- s[0] = (char) (objPtr->internalRep.longValue? '1' : '0');
- s[1] = '\0';
- objPtr->bytes = s;
- objPtr->length = 1;
+ numericBoolean:
+ TclFreeIntRep(objPtr);
+ objPtr->internalRep.longValue = newBool;
+ objPtr->typePtr = &tclIntType;
+ return TCL_OK;
}
/*
@@ -1671,12 +2051,12 @@ UpdateStringOfBoolean(objPtr)
*
* Tcl_NewDoubleObj --
*
- * This procedure is normally called when not debugging: i.e., when
+ * This function is normally called when not debugging: i.e., when
* TCL_MEM_DEBUG is not defined. It creates a new double object and
* initializes it from the argument double value.
*
- * When TCL_MEM_DEBUG is defined, this procedure just returns the
- * result of calling the debugging version Tcl_DbNewDoubleObj.
+ * When TCL_MEM_DEBUG is defined, this function just returns the result
+ * of calling the debugging version Tcl_DbNewDoubleObj.
*
* Results:
* The newly created object is returned. This object will have an
@@ -1692,8 +2072,8 @@ UpdateStringOfBoolean(objPtr)
#undef Tcl_NewDoubleObj
Tcl_Obj *
-Tcl_NewDoubleObj(dblValue)
- register double dblValue; /* Double used to initialize the object. */
+Tcl_NewDoubleObj(
+ register double dblValue) /* Double used to initialize the object. */
{
return Tcl_DbNewDoubleObj(dblValue, "unknown", 0);
}
@@ -1701,16 +2081,12 @@ Tcl_NewDoubleObj(dblValue)
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
-Tcl_NewDoubleObj(dblValue)
- register double dblValue; /* Double used to initialize the object. */
+Tcl_NewDoubleObj(
+ register double dblValue) /* Double used to initialize the object. */
{
register Tcl_Obj *objPtr;
- TclNewObj(objPtr);
- objPtr->bytes = NULL;
-
- objPtr->internalRep.doubleValue = dblValue;
- objPtr->typePtr = &tclDoubleType;
+ TclNewDoubleObj(objPtr, dblValue);
return objPtr;
}
#endif /* if TCL_MEM_DEBUG */
@@ -1720,20 +2096,20 @@ Tcl_NewDoubleObj(dblValue)
*
* Tcl_DbNewDoubleObj --
*
- * This procedure is normally called when debugging: i.e., when
+ * This function is normally called when debugging: i.e., when
* TCL_MEM_DEBUG is defined. It creates new double objects. It is the
- * same as the Tcl_NewDoubleObj procedure above except that it calls
+ * same as the Tcl_NewDoubleObj function above except that it calls
* Tcl_DbCkalloc directly with the file name and line number from its
* caller. This simplifies debugging since then the [memory active]
- * command will report the correct file name and line number when
+ * command will report the correct file name and line number when
* reporting objects that haven't been freed.
*
- * When TCL_MEM_DEBUG is not defined, this procedure just returns the
+ * When TCL_MEM_DEBUG is not defined, this function just returns the
* result of calling Tcl_NewDoubleObj.
*
* Results:
- * The newly created object is returned. This object will have an
- * invalid string representation. The returned object has ref count 0.
+ * The newly created object is returned. This object will have an invalid
+ * string representation. The returned object has ref count 0.
*
* Side effects:
* None.
@@ -1744,18 +2120,18 @@ Tcl_NewDoubleObj(dblValue)
#ifdef TCL_MEM_DEBUG
Tcl_Obj *
-Tcl_DbNewDoubleObj(dblValue, file, line)
- register double dblValue; /* Double used to initialize the object. */
- CONST char *file; /* The name of the source file calling this
- * procedure; used for debugging. */
- int line; /* Line number in the source file; used
- * for debugging. */
+Tcl_DbNewDoubleObj(
+ register double dblValue, /* Double used to initialize the object. */
+ CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
register Tcl_Obj *objPtr;
TclDbNewObj(objPtr, file, line);
objPtr->bytes = NULL;
-
+
objPtr->internalRep.doubleValue = dblValue;
objPtr->typePtr = &tclDoubleType;
return objPtr;
@@ -1764,12 +2140,12 @@ Tcl_DbNewDoubleObj(dblValue, file, line)
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
-Tcl_DbNewDoubleObj(dblValue, file, line)
- register double dblValue; /* Double used to initialize the object. */
- CONST char *file; /* The name of the source file calling this
- * procedure; used for debugging. */
- int line; /* Line number in the source file; used
- * for debugging. */
+Tcl_DbNewDoubleObj(
+ register double dblValue, /* Double used to initialize the object. */
+ CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
return Tcl_NewDoubleObj(dblValue);
}
@@ -1787,30 +2163,22 @@ Tcl_DbNewDoubleObj(dblValue, file, line)
* None.
*
* Side effects:
- * The object's old string rep, if any, is freed. Also, any old
- * internal rep is freed.
+ * The object's old string rep, if any, is freed. Also, any old internal
+ * rep is freed.
*
*----------------------------------------------------------------------
*/
void
-Tcl_SetDoubleObj(objPtr, dblValue)
- register Tcl_Obj *objPtr; /* Object whose internal rep to init. */
- register double dblValue; /* Double used to set the object's value. */
+Tcl_SetDoubleObj(
+ register Tcl_Obj *objPtr, /* Object whose internal rep to init. */
+ register double dblValue) /* Double used to set the object's value. */
{
- register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
-
if (Tcl_IsShared(objPtr)) {
- panic("Tcl_SetDoubleObj called with shared object");
+ Tcl_Panic("%s called with shared object", "Tcl_SetDoubleObj");
}
- if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
- oldTypePtr->freeIntRepProc(objPtr);
- }
-
- objPtr->internalRep.doubleValue = dblValue;
- objPtr->typePtr = &tclDoubleType;
- Tcl_InvalidateStringRep(objPtr);
+ TclSetDoubleObj(objPtr, dblValue);
}
/*
@@ -1818,9 +2186,8 @@ Tcl_SetDoubleObj(objPtr, dblValue)
*
* Tcl_GetDoubleFromObj --
*
- * Attempt to return a double from the Tcl object "objPtr". If the
- * object is not already a double, an attempt will be made to convert
- * it to one.
+ * Attempt to return a double from the Tcl object "objPtr". If the object
+ * is not already a double, an attempt will be made to convert it to one.
*
* Results:
* The return value is a standard Tcl object result. If an error occurs
@@ -1828,30 +2195,48 @@ Tcl_SetDoubleObj(objPtr, dblValue)
* result unless "interp" is NULL.
*
* Side effects:
- * If the object is not already a double, the conversion will free
- * any old internal representation.
+ * If the object is not already a double, the conversion will free any
+ * old internal representation.
*
*----------------------------------------------------------------------
*/
int
-Tcl_GetDoubleFromObj(interp, objPtr, dblPtr)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- register Tcl_Obj *objPtr; /* The object from which to get a double. */
- register double *dblPtr; /* Place to store resulting double. */
+Tcl_GetDoubleFromObj(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ register Tcl_Obj *objPtr, /* The object from which to get a double. */
+ register double *dblPtr) /* Place to store resulting double. */
{
- register int result;
-
- if (objPtr->typePtr == &tclDoubleType) {
- *dblPtr = objPtr->internalRep.doubleValue;
- return TCL_OK;
- }
-
- result = SetDoubleFromAny(interp, objPtr);
- if (result == TCL_OK) {
- *dblPtr = objPtr->internalRep.doubleValue;
- }
- return result;
+ do {
+ if (objPtr->typePtr == &tclDoubleType) {
+ if (TclIsNaN(objPtr->internalRep.doubleValue)) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "floating point value is Not a Number", -1));
+ }
+ return TCL_ERROR;
+ }
+ *dblPtr = (double) objPtr->internalRep.doubleValue;
+ return TCL_OK;
+ }
+ if (objPtr->typePtr == &tclIntType) {
+ *dblPtr = objPtr->internalRep.longValue;
+ return TCL_OK;
+ }
+ if (objPtr->typePtr == &tclBignumType) {
+ mp_int big;
+ UNPACK_BIGNUM( objPtr, big );
+ *dblPtr = TclBignumToDouble( &big );
+ return TCL_OK;
+ }
+#ifndef NO_WIDE_TYPE
+ if (objPtr->typePtr == &tclWideIntType) {
+ *dblPtr = (double) objPtr->internalRep.wideValue;
+ return TCL_OK;
+ }
+#endif
+ } while (SetDoubleFromAny(interp, objPtr) == TCL_OK);
+ return TCL_ERROR;
}
/*
@@ -1875,78 +2260,12 @@ Tcl_GetDoubleFromObj(interp, objPtr, dblPtr)
*/
static int
-SetDoubleFromAny(interp, objPtr)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- register Tcl_Obj *objPtr; /* The object to convert. */
+SetDoubleFromAny(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ register Tcl_Obj *objPtr) /* The object to convert. */
{
- Tcl_ObjType *oldTypePtr = objPtr->typePtr;
- char *string, *end;
- double newDouble;
- int length;
-
- /*
- * Get the string representation. Make it up-to-date if necessary.
- */
-
- string = Tcl_GetStringFromObj(objPtr, &length);
-
- /*
- * Now parse "objPtr"s string as an double. Numbers can't have embedded
- * NULLs. We use an implementation here that doesn't report errors in
- * interp if interp is NULL.
- */
-
- errno = 0;
- newDouble = strtod(string, &end);
- if (end == string) {
- badDouble:
- if (interp != NULL) {
- /*
- * Must copy string before resetting the result in case a caller
- * is trying to convert the interpreter's result to an int.
- */
-
- char buf[100];
- sprintf(buf, "expected floating-point number but got \"%.50s\"",
- string);
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
- }
- return TCL_ERROR;
- }
- if (errno != 0) {
- if (interp != NULL) {
- TclExprFloatError(interp, newDouble);
- }
- return TCL_ERROR;
- }
-
- /*
- * Make sure that the string has no garbage after the end of the double.
- */
-
- while ((end < (string+length))
- && isspace(UCHAR(*end))) { /* INTL: ISO space. */
- end++;
- }
- if (end != (string+length)) {
- goto badDouble;
- }
-
- /*
- * The conversion to double succeeded. Free the old internalRep before
- * setting the new one. We do this as late as possible to allow the
- * conversion code, in particular Tcl_GetStringFromObj, to use that old
- * internalRep.
- */
-
- if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
- oldTypePtr->freeIntRepProc(objPtr);
- }
-
- objPtr->internalRep.doubleValue = newDouble;
- objPtr->typePtr = &tclDoubleType;
- return TCL_OK;
+ return TclParseNumber(interp, objPtr, "floating-point number", NULL, -1,
+ NULL, 0);
}
/*
@@ -1954,9 +2273,9 @@ SetDoubleFromAny(interp, objPtr)
*
* UpdateStringOfDouble --
*
- * Update the string representation for a double-precision floating
- * point object. This must obey the current tcl_precision value for
- * double-to-string conversions. Note: This procedure does not free an
+ * Update the string representation for a double-precision floating point
+ * object. This must obey the current tcl_precision value for
+ * double-to-string conversions. Note: This function does not free an
* existing old string rep so storage will be lost if this has not
* already been done.
*
@@ -1964,23 +2283,22 @@ SetDoubleFromAny(interp, objPtr)
* None.
*
* Side effects:
- * The object's string is set to a valid string that results from
- * the double-to-string conversion.
+ * The object's string is set to a valid string that results from the
+ * double-to-string conversion.
*
*----------------------------------------------------------------------
*/
static void
-UpdateStringOfDouble(objPtr)
- register Tcl_Obj *objPtr; /* Double obj with string rep to update. */
+UpdateStringOfDouble(
+ register Tcl_Obj *objPtr) /* Double obj with string rep to update. */
{
char buffer[TCL_DOUBLE_SPACE];
register int len;
-
- Tcl_PrintDouble((Tcl_Interp *) NULL, objPtr->internalRep.doubleValue,
- buffer);
+
+ Tcl_PrintDouble(NULL, objPtr->internalRep.doubleValue, buffer);
len = strlen(buffer);
-
+
objPtr->bytes = (char *) ckalloc((unsigned) len + 1);
strcpy(objPtr->bytes, buffer);
objPtr->length = len;
@@ -1993,22 +2311,22 @@ UpdateStringOfDouble(objPtr)
*
* If a client is compiled with TCL_MEM_DEBUG defined, calls to
* Tcl_NewIntObj to create a new integer object end up calling the
- * debugging procedure Tcl_DbNewLongObj instead.
+ * debugging function Tcl_DbNewLongObj instead.
*
* Otherwise, if the client is compiled without TCL_MEM_DEBUG defined,
* calls to Tcl_NewIntObj result in a call to one of the two
- * Tcl_NewIntObj implementations below. We provide two implementations
- * so that the Tcl core can be compiled to do memory debugging of the
- * core even if a client does not request it for itself.
+ * Tcl_NewIntObj implementations below. We provide two implementations so
+ * that the Tcl core can be compiled to do memory debugging of the core
+ * even if a client does not request it for itself.
*
* Integer and long integer objects share the same "integer" type
* implementation. We store all integers as longs and Tcl_GetIntFromObj
- * checks whether the current value of the long can be represented by
- * an int.
+ * checks whether the current value of the long can be represented by an
+ * int.
*
* Results:
- * The newly created object is returned. This object will have an
- * invalid string representation. The returned object has ref count 0.
+ * The newly created object is returned. This object will have an invalid
+ * string representation. The returned object has ref count 0.
*
* Side effects:
* None.
@@ -2020,8 +2338,8 @@ UpdateStringOfDouble(objPtr)
#undef Tcl_NewIntObj
Tcl_Obj *
-Tcl_NewIntObj(intValue)
- register int intValue; /* Int used to initialize the new object. */
+Tcl_NewIntObj(
+ register int intValue) /* Int used to initialize the new object. */
{
return Tcl_DbNewLongObj((long)intValue, "unknown", 0);
}
@@ -2029,16 +2347,12 @@ Tcl_NewIntObj(intValue)
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
-Tcl_NewIntObj(intValue)
- register int intValue; /* Int used to initialize the new object. */
+Tcl_NewIntObj(
+ register int intValue) /* Int used to initialize the new object. */
{
register Tcl_Obj *objPtr;
- TclNewObj(objPtr);
- objPtr->bytes = NULL;
-
- objPtr->internalRep.longValue = (long)intValue;
- objPtr->typePtr = &tclIntType;
+ TclNewIntObj(objPtr, intValue);
return objPtr;
}
#endif /* if TCL_MEM_DEBUG */
@@ -2055,30 +2369,22 @@ Tcl_NewIntObj(intValue)
* None.
*
* Side effects:
- * The object's old string rep, if any, is freed. Also, any old
- * internal rep is freed.
+ * The object's old string rep, if any, is freed. Also, any old internal
+ * rep is freed.
*
*----------------------------------------------------------------------
*/
void
-Tcl_SetIntObj(objPtr, intValue)
- register Tcl_Obj *objPtr; /* Object whose internal rep to init. */
- register int intValue; /* Integer used to set object's value. */
+Tcl_SetIntObj(
+ register Tcl_Obj *objPtr, /* Object whose internal rep to init. */
+ register int intValue) /* Integer used to set object's value. */
{
- register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
-
if (Tcl_IsShared(objPtr)) {
- panic("Tcl_SetIntObj called with shared object");
+ Tcl_Panic("%s called with shared object", "Tcl_SetIntObj");
}
-
- if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
- oldTypePtr->freeIntRepProc(objPtr);
- }
-
- objPtr->internalRep.longValue = (long) intValue;
- objPtr->typePtr = &tclIntType;
- Tcl_InvalidateStringRep(objPtr);
+
+ TclSetIntObj(objPtr, intValue);
}
/*
@@ -2091,67 +2397,48 @@ Tcl_SetIntObj(objPtr, intValue)
*
* Integer and long integer objects share the same "integer" type
* implementation. We store all integers as longs and Tcl_GetIntFromObj
- * checks whether the current value of the long can be represented by
- * an int.
+ * checks whether the current value of the long can be represented by an
+ * int.
*
* Results:
* The return value is a standard Tcl object result. If an error occurs
- * during conversion or if the long integer held by the object
- * can not be represented by an int, an error message is left in
- * the interpreter's result unless "interp" is NULL.
+ * during conversion or if the long integer held by the object can not be
+ * represented by an int, an error message is left in the interpreter's
+ * result unless "interp" is NULL.
*
* Side effects:
- * If the object is not already an int, the conversion will free
- * any old internal representation.
+ * If the object is not already an int, the conversion will free any old
+ * internal representation.
*
*----------------------------------------------------------------------
*/
int
-Tcl_GetIntFromObj(interp, objPtr, intPtr)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- register Tcl_Obj *objPtr; /* The object from which to get a int. */
- register int *intPtr; /* Place to store resulting int. */
+Tcl_GetIntFromObj(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ register Tcl_Obj *objPtr, /* The object from which to get a int. */
+ register int *intPtr) /* Place to store resulting int. */
{
- int result;
- Tcl_WideInt w = 0;
-
- /*
- * If the object isn't already an integer of any width, try to
- * convert it to one.
- */
-
- if (objPtr->typePtr != &tclIntType && objPtr->typePtr != &tclWideIntType) {
- result = SetIntOrWideFromAny(interp, objPtr);
- if (result != TCL_OK) {
- return result;
- }
- }
-
- /*
- * Object should now be either int or wide. Get its value.
- */
+#if (LONG_MAX == INT_MAX)
+ return TclGetLongFromObj(interp, objPtr, (long *) intPtr);
+#else
+ long l;
-#ifndef TCL_WIDE_INT_IS_LONG
- if (objPtr->typePtr == &tclWideIntType) {
- w = objPtr->internalRep.wideValue;
- } else
-#endif
- {
- w = Tcl_LongAsWide(objPtr->internalRep.longValue);
+ if (TclGetLongFromObj(interp, objPtr, &l) != TCL_OK) {
+ return TCL_ERROR;
}
-
- if ((LLONG_MAX > UINT_MAX)
- && ((w > UINT_MAX) || (w < -(Tcl_WideInt)UINT_MAX))) {
+ if ((ULONG_MAX > UINT_MAX) && ((l > UINT_MAX) || (l < -(long)UINT_MAX))) {
if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "integer value too large to represent as non-long integer",
- -1));
+ CONST char *s =
+ "integer value too large to represent as non-long integer";
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
+ Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL);
}
return TCL_ERROR;
}
- *intPtr = (int)w;
+ *intPtr = (int) l;
return TCL_OK;
+#endif
}
/*
@@ -2159,173 +2446,24 @@ Tcl_GetIntFromObj(interp, objPtr, intPtr)
*
* SetIntFromAny --
*
- * Attempts to force the internal representation for a Tcl object
- * to tclIntType, specifically.
- *
- * Results:
- * The return value is a standard object Tcl result. If an
- * error occurs during conversion, an error message is left in
- * the interpreter's result unless "interp" is NULL.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-SetIntFromAny( Tcl_Interp* interp,
- /* Tcl interpreter */
- Tcl_Obj* objPtr )
- /* Pointer to the object to convert */
-{
- int result;
-
- result = SetIntOrWideFromAny( interp, objPtr );
- if ( result != TCL_OK ) {
- return result;
- }
- if ( objPtr->typePtr != &tclIntType ) {
- if ( interp != NULL ) {
- char *s = "integer value too large to represent";
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1);
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (char *) NULL);
- }
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * SetIntOrWideFromAny --
- *
- * Attempt to generate an integer internal form for the Tcl object
- * "objPtr".
+ * Attempts to force the internal representation for a Tcl object to
+ * tclIntType, specifically.
*
* Results:
* The return value is a standard object Tcl result. If an error occurs
* during conversion, an error message is left in the interpreter's
* result unless "interp" is NULL.
*
- * Side effects:
- * If no error occurs, an int is stored as "objPtr"s internal
- * representation.
- *
*----------------------------------------------------------------------
*/
static int
-SetIntOrWideFromAny(interp, objPtr)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- register Tcl_Obj *objPtr; /* The object to convert. */
-{
- Tcl_ObjType *oldTypePtr = objPtr->typePtr;
- char *string, *end;
- int length;
- register char *p;
- unsigned long newLong;
- int isNegative = 0;
- int isWide = 0;
-
- /*
- * Get the string representation. Make it up-to-date if necessary.
- */
-
- p = string = Tcl_GetStringFromObj(objPtr, &length);
-
- /*
- * Now parse "objPtr"s string as an int. We use an implementation here
- * that doesn't report errors in interp if interp is NULL. Note: use
- * strtoul instead of strtol for integer conversions to allow full-size
- * unsigned numbers, but don't depend on strtoul to handle sign
- * characters; it won't in some implementations.
- */
-
- errno = 0;
- for ( ; isspace(UCHAR(*p)); p++) { /* INTL: ISO space. */
- /* Empty loop body. */
- }
- if (*p == '-') {
- p++;
- isNegative = 1;
- } else if (*p == '+') {
- p++;
- }
- if (!isdigit(UCHAR(*p))) {
- badInteger:
- if (interp != NULL) {
- /*
- * Must copy string before resetting the result in case a caller
- * is trying to convert the interpreter's result to an int.
- */
-
- char buf[100];
- sprintf(buf, "expected integer but got \"%.50s\"", string);
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
- TclCheckBadOctal(interp, string);
- }
- return TCL_ERROR;
- }
- newLong = strtoul(p, &end, 0);
- if (end == p) {
- goto badInteger;
- }
- if (errno == ERANGE) {
- if (interp != NULL) {
- char *s = "integer value too large to represent";
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1);
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (char *) NULL);
- }
- return TCL_ERROR;
- }
-
- /*
- * Make sure that the string has no garbage after the end of the int.
- */
-
- while ((end < (string+length))
- && isspace(UCHAR(*end))) { /* INTL: ISO space. */
- end++;
- }
- if (end != (string+length)) {
- goto badInteger;
- }
-
- /*
- * If the resulting integer will exceed the range of a long,
- * put it into a wide instead. (Tcl Bug #868489)
- */
-
-#ifndef TCL_WIDE_INT_IS_LONG
- if ((isNegative && newLong > (unsigned long) (LONG_MAX) + 1)
- || (!isNegative && newLong > LONG_MAX)) {
- isWide = 1;
- }
-#endif
-
- /*
- * The conversion to int succeeded. Free the old internalRep before
- * setting the new one. We do this as late as possible to allow the
- * conversion code, in particular Tcl_GetStringFromObj, to use that old
- * internalRep.
- */
-
- if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
- oldTypePtr->freeIntRepProc(objPtr);
- }
-
- if (isWide) {
- objPtr->internalRep.wideValue =
- (isNegative ? -(Tcl_WideInt)newLong : (Tcl_WideInt)newLong);
- objPtr->typePtr = &tclWideIntType;
- } else {
- objPtr->internalRep.longValue =
- (isNegative ? -(long)newLong : (long)newLong);
- objPtr->typePtr = &tclIntType;
- }
- return TCL_OK;
+SetIntFromAny(
+ Tcl_Interp *interp, /* Tcl interpreter */
+ Tcl_Obj *objPtr) /* Pointer to the object to convert */
+{
+ long l;
+ return TclGetLongFromObj(interp, objPtr, &l);
}
/*
@@ -2333,29 +2471,29 @@ SetIntOrWideFromAny(interp, objPtr)
*
* UpdateStringOfInt --
*
- * Update the string representation for an integer object.
- * Note: This procedure does not free an existing old string rep
- * so storage will be lost if this has not already been done.
+ * Update the string representation for an integer object. Note: This
+ * function does not free an existing old string rep so storage will be
+ * lost if this has not already been done.
*
* Results:
* None.
*
* Side effects:
- * The object's string is set to a valid string that results from
- * the int-to-string conversion.
+ * The object's string is set to a valid string that results from the
+ * int-to-string conversion.
*
*----------------------------------------------------------------------
*/
static void
-UpdateStringOfInt(objPtr)
- register Tcl_Obj *objPtr; /* Int object whose string rep to update. */
+UpdateStringOfInt(
+ register Tcl_Obj *objPtr) /* Int object whose string rep to update. */
{
char buffer[TCL_INTEGER_SPACE];
register int len;
-
+
len = TclFormatInt(buffer, objPtr->internalRep.longValue);
-
+
objPtr->bytes = ckalloc((unsigned) len + 1);
strcpy(objPtr->bytes, buffer);
objPtr->length = len;
@@ -2367,23 +2505,23 @@ UpdateStringOfInt(objPtr)
* Tcl_NewLongObj --
*
* If a client is compiled with TCL_MEM_DEBUG defined, calls to
- * Tcl_NewLongObj to create a new long integer object end up calling
- * the debugging procedure Tcl_DbNewLongObj instead.
+ * Tcl_NewLongObj to create a new long integer object end up calling the
+ * debugging function Tcl_DbNewLongObj instead.
*
* Otherwise, if the client is compiled without TCL_MEM_DEBUG defined,
* calls to Tcl_NewLongObj result in a call to one of the two
* Tcl_NewLongObj implementations below. We provide two implementations
- * so that the Tcl core can be compiled to do memory debugging of the
+ * so that the Tcl core can be compiled to do memory debugging of the
* core even if a client does not request it for itself.
*
* Integer and long integer objects share the same "integer" type
* implementation. We store all integers as longs and Tcl_GetIntFromObj
- * checks whether the current value of the long can be represented by
- * an int.
+ * checks whether the current value of the long can be represented by an
+ * int.
*
* Results:
- * The newly created object is returned. This object will have an
- * invalid string representation. The returned object has ref count 0.
+ * The newly created object is returned. This object will have an invalid
+ * string representation. The returned object has ref count 0.
*
* Side effects:
* None.
@@ -2395,8 +2533,8 @@ UpdateStringOfInt(objPtr)
#undef Tcl_NewLongObj
Tcl_Obj *
-Tcl_NewLongObj(longValue)
- register long longValue; /* Long integer used to initialize the
+Tcl_NewLongObj(
+ register long longValue) /* Long integer used to initialize the
* new object. */
{
return Tcl_DbNewLongObj(longValue, "unknown", 0);
@@ -2405,17 +2543,13 @@ Tcl_NewLongObj(longValue)
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
-Tcl_NewLongObj(longValue)
- register long longValue; /* Long integer used to initialize the
+Tcl_NewLongObj(
+ register long longValue) /* Long integer used to initialize the
* new object. */
{
register Tcl_Obj *objPtr;
- TclNewObj(objPtr);
- objPtr->bytes = NULL;
-
- objPtr->internalRep.longValue = longValue;
- objPtr->typePtr = &tclIntType;
+ TclNewLongObj(objPtr, longValue);
return objPtr;
}
#endif /* if TCL_MEM_DEBUG */
@@ -2426,26 +2560,25 @@ Tcl_NewLongObj(longValue)
* Tcl_DbNewLongObj --
*
* If a client is compiled with TCL_MEM_DEBUG defined, calls to
- * Tcl_NewIntObj and Tcl_NewLongObj to create new integer or
- * long integer objects end up calling the debugging procedure
- * Tcl_DbNewLongObj instead. We provide two implementations of
- * Tcl_DbNewLongObj so that whether the Tcl core is compiled to do
- * memory debugging of the core is independent of whether a client
- * requests debugging for itself.
- *
- * When the core is compiled with TCL_MEM_DEBUG defined,
- * Tcl_DbNewLongObj calls Tcl_DbCkalloc directly with the file name and
- * line number from its caller. This simplifies debugging since then
- * the [memory active] command will report the caller's file name and
- * line number when reporting objects that haven't been freed.
+ * Tcl_NewIntObj and Tcl_NewLongObj to create new integer or long integer
+ * objects end up calling the debugging function Tcl_DbNewLongObj
+ * instead. We provide two implementations of Tcl_DbNewLongObj so that
+ * whether the Tcl core is compiled to do memory debugging of the core is
+ * independent of whether a client requests debugging for itself.
+ *
+ * When the core is compiled with TCL_MEM_DEBUG defined, Tcl_DbNewLongObj
+ * calls Tcl_DbCkalloc directly with the file name and line number from
+ * its caller. This simplifies debugging since then the [memory active]
+ * command will report the caller's file name and line number when
+ * reporting objects that haven't been freed.
*
* Otherwise, when the core is compiled without TCL_MEM_DEBUG defined,
- * this procedure just returns the result of calling Tcl_NewLongObj.
+ * this function just returns the result of calling Tcl_NewLongObj.
*
* Results:
- * The newly created long integer object is returned. This object
- * will have an invalid string representation. The returned object has
- * ref count 0.
+ * The newly created long integer object is returned. This object will
+ * have an invalid string representation. The returned object has ref
+ * count 0.
*
* Side effects:
* Allocates memory.
@@ -2456,19 +2589,19 @@ Tcl_NewLongObj(longValue)
#ifdef TCL_MEM_DEBUG
Tcl_Obj *
-Tcl_DbNewLongObj(longValue, file, line)
- register long longValue; /* Long integer used to initialize the
- * new object. */
- CONST char *file; /* The name of the source file calling this
- * procedure; used for debugging. */
- int line; /* Line number in the source file; used
- * for debugging. */
+Tcl_DbNewLongObj(
+ register long longValue, /* Long integer used to initialize the new
+ * object. */
+ CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
register Tcl_Obj *objPtr;
TclDbNewObj(objPtr, file, line);
objPtr->bytes = NULL;
-
+
objPtr->internalRep.longValue = longValue;
objPtr->typePtr = &tclIntType;
return objPtr;
@@ -2477,13 +2610,13 @@ Tcl_DbNewLongObj(longValue, file, line)
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
-Tcl_DbNewLongObj(longValue, file, line)
- register long longValue; /* Long integer used to initialize the
- * new object. */
- CONST char *file; /* The name of the source file calling this
- * procedure; used for debugging. */
- int line; /* Line number in the source file; used
- * for debugging. */
+Tcl_DbNewLongObj(
+ register long longValue, /* Long integer used to initialize the new
+ * object. */
+ CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
return Tcl_NewLongObj(longValue);
}
@@ -2501,31 +2634,23 @@ Tcl_DbNewLongObj(longValue, file, line)
* None.
*
* Side effects:
- * The object's old string rep, if any, is freed. Also, any old
- * internal rep is freed.
+ * The object's old string rep, if any, is freed. Also, any old internal
+ * rep is freed.
*
*----------------------------------------------------------------------
*/
void
-Tcl_SetLongObj(objPtr, longValue)
- register Tcl_Obj *objPtr; /* Object whose internal rep to init. */
- register long longValue; /* Long integer used to initialize the
+Tcl_SetLongObj(
+ register Tcl_Obj *objPtr, /* Object whose internal rep to init. */
+ register long longValue) /* Long integer used to initialize the
* object's value. */
{
- register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
-
if (Tcl_IsShared(objPtr)) {
- panic("Tcl_SetLongObj called with shared object");
+ Tcl_Panic("%s called with shared object", "Tcl_SetLongObj");
}
- if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
- oldTypePtr->freeIntRepProc(objPtr);
- }
-
- objPtr->internalRep.longValue = longValue;
- objPtr->typePtr = &tclIntType;
- Tcl_InvalidateStringRep(objPtr);
+ TclSetLongObj(objPtr, longValue);
}
/*
@@ -2533,8 +2658,8 @@ Tcl_SetLongObj(objPtr, longValue)
*
* Tcl_GetLongFromObj --
*
- * Attempt to return an long integer from the Tcl object "objPtr". If
- * the object is not already an int object, an attempt will be made to
+ * Attempt to return an long integer from the Tcl object "objPtr". If the
+ * object is not already an int object, an attempt will be made to
* convert it to one.
*
* Results:
@@ -2550,211 +2675,133 @@ Tcl_SetLongObj(objPtr, longValue)
*/
int
-Tcl_GetLongFromObj(interp, objPtr, longPtr)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- register Tcl_Obj *objPtr; /* The object from which to get a long. */
- register long *longPtr; /* Place to store resulting long. */
+Tcl_GetLongFromObj(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ register Tcl_Obj *objPtr, /* The object from which to get a long. */
+ register long *longPtr) /* Place to store resulting long. */
{
- register int result;
-
- if (objPtr->typePtr != &tclIntType && objPtr->typePtr != &tclWideIntType) {
- result = SetIntOrWideFromAny(interp, objPtr);
- if (result != TCL_OK) {
- return result;
+ do {
+ if (objPtr->typePtr == &tclIntType) {
+ *longPtr = objPtr->internalRep.longValue;
+ return TCL_OK;
}
- }
-
-#ifndef TCL_WIDE_INT_IS_LONG
- if (objPtr->typePtr == &tclWideIntType) {
- /*
- * If the object is already a wide integer, don't convert it.
- * This code allows for any integer in the range -ULONG_MAX to
- * ULONG_MAX to be converted to a long, ignoring overflow.
- * The rule preserves existing semantics for conversion of
- * integers on input, but avoids inadvertent demotion of
- * wide integers to 32-bit ones in the internal rep.
- */
+#ifndef NO_WIDE_TYPE
+ if (objPtr->typePtr == &tclWideIntType) {
+ /*
+ * We return any integer in the range -ULONG_MAX to ULONG_MAX
+ * converted to a long, ignoring overflow. The rule preserves
+ * existing semantics for conversion of integers on input, but
+ * avoids inadvertent demotion of wide integers to 32-bit ones in
+ * the internal rep.
+ */
- Tcl_WideInt w = objPtr->internalRep.wideValue;
- if (w >= -(Tcl_WideInt)(ULONG_MAX) && w <= (Tcl_WideInt)(ULONG_MAX)) {
- *longPtr = Tcl_WideAsLong(w);
- return TCL_OK;
- } else {
- if (interp != NULL) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "integer value too large to represent", -1);
+ Tcl_WideInt w = objPtr->internalRep.wideValue;
+ if (w >= -(Tcl_WideInt)(ULONG_MAX)
+ && w <= (Tcl_WideInt)(ULONG_MAX)) {
+ *longPtr = Tcl_WideAsLong(w);
+ return TCL_OK;
}
- return TCL_ERROR;
+ goto tooLarge;
}
- }
-#endif
-
- *longPtr = objPtr->internalRep.longValue;
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * SetWideIntFromAny --
- *
- * Attempt to generate an integer internal form for the Tcl object
- * "objPtr".
- *
- * Results:
- * The return value is a standard object Tcl result. If an error occurs
- * during conversion, an error message is left in the interpreter's
- * result unless "interp" is NULL.
- *
- * Side effects:
- * If no error occurs, an int is stored as "objPtr"s internal
- * representation.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-SetWideIntFromAny(interp, objPtr)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- register Tcl_Obj *objPtr; /* The object to convert. */
-{
-#ifndef TCL_WIDE_INT_IS_LONG
- Tcl_ObjType *oldTypePtr = objPtr->typePtr;
- char *string, *end;
- int length;
- register char *p;
- Tcl_WideInt newWide;
-
- /*
- * Get the string representation. Make it up-to-date if necessary.
- */
-
- p = string = Tcl_GetStringFromObj(objPtr, &length);
-
- /*
- * Now parse "objPtr"s string as an int. We use an implementation here
- * that doesn't report errors in interp if interp is NULL. Note: use
- * strtoull instead of strtoll for integer conversions to allow full-size
- * unsigned numbers, but don't depend on strtoull to handle sign
- * characters; it won't in some implementations.
- */
-
- errno = 0;
-#ifdef TCL_STRTOUL_SIGN_CHECK
- for ( ; isspace(UCHAR(*p)); p++) { /* INTL: ISO space. */
- /* Empty loop body. */
- }
- if (*p == '-') {
- p++;
- newWide = -((Tcl_WideInt)strtoull(p, &end, 0));
- } else if (*p == '+') {
- p++;
- newWide = strtoull(p, &end, 0);
- } else
-#else
- newWide = strtoull(p, &end, 0);
#endif
- if (end == p) {
- badInteger:
- if (interp != NULL) {
+ if (objPtr->typePtr == &tclDoubleType) {
+ if (interp != NULL) {
+ Tcl_Obj *msg;
+
+ TclNewLiteralStringObj(msg, "expected integer but got \"");
+ Tcl_AppendObjToObj(msg, objPtr);
+ Tcl_AppendToObj(msg, "\"", -1);
+ Tcl_SetObjResult(interp, msg);
+ }
+ return TCL_ERROR;
+ }
+ if (objPtr->typePtr == &tclBignumType) {
/*
- * Must copy string before resetting the result in case a caller
- * is trying to convert the interpreter's result to an int.
+ * Must check for those bignum values that can fit in a long, even
+ * when auto-narrowing is enabled. Only those values in the signed
+ * long range get auto-narrowed to tclIntType, while all the
+ * values in the unsigned long range will fit in a long.
*/
-
- char buf[100];
- sprintf(buf, "expected integer but got \"%.50s\"", string);
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
- TclCheckBadOctal(interp, string);
- }
- return TCL_ERROR;
- }
- if (errno == ERANGE) {
- if (interp != NULL) {
- char *s = "integer value too large to represent";
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1);
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (char *) NULL);
- }
- return TCL_ERROR;
- }
- /*
- * Make sure that the string has no garbage after the end of the int.
- */
-
- while ((end < (string+length))
- && isspace(UCHAR(*end))) { /* INTL: ISO space. */
- end++;
- }
- if (end != (string+length)) {
- goto badInteger;
- }
-
- /*
- * The conversion to int succeeded. Free the old internalRep before
- * setting the new one. We do this as late as possible to allow the
- * conversion code, in particular Tcl_GetStringFromObj, to use that old
- * internalRep.
- */
-
- if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
- oldTypePtr->freeIntRepProc(objPtr);
- }
-
- objPtr->internalRep.wideValue = newWide;
-#else
- if (TCL_ERROR == SetIntFromAny(interp, objPtr)) {
- return TCL_ERROR;
- }
+ mp_int big;
+
+ UNPACK_BIGNUM(objPtr, big);
+ if ((size_t)(big.used) <= (CHAR_BIT * sizeof(long) + DIGIT_BIT - 1)
+ / DIGIT_BIT) {
+ unsigned long value = 0, numBytes = sizeof(long);
+ long scratch;
+ unsigned char *bytes = (unsigned char *)&scratch;
+ if (mp_to_unsigned_bin_n(&big, bytes, &numBytes) == MP_OKAY) {
+ while (numBytes-- > 0) {
+ value = (value << CHAR_BIT) | *bytes++;
+ }
+ if (big.sign) {
+ *longPtr = - (long) value;
+ } else {
+ *longPtr = (long) value;
+ }
+ return TCL_OK;
+ }
+ }
+#ifndef NO_WIDE_TYPE
+ tooLarge:
#endif
- objPtr->typePtr = &tclWideIntType;
- return TCL_OK;
+ if (interp != NULL) {
+ char *s = "integer value too large to represent";
+ Tcl_Obj *msg = Tcl_NewStringObj(s, -1);
+
+ Tcl_SetObjResult(interp, msg);
+ Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL);
+ }
+ return TCL_ERROR;
+ }
+ } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL,
+ TCL_PARSE_INTEGER_ONLY)==TCL_OK);
+ return TCL_ERROR;
}
+#ifndef NO_WIDE_TYPE
/*
*----------------------------------------------------------------------
*
* UpdateStringOfWideInt --
*
- * Update the string representation for a wide integer object.
- * Note: This procedure does not free an existing old string rep
- * so storage will be lost if this has not already been done.
+ * Update the string representation for a wide integer object. Note: this
+ * function does not free an existing old string rep so storage will be
+ * lost if this has not already been done.
*
* Results:
* None.
*
* Side effects:
- * The object's string is set to a valid string that results from
- * the wideInt-to-string conversion.
+ * The object's string is set to a valid string that results from the
+ * wideInt-to-string conversion.
*
*----------------------------------------------------------------------
*/
-#ifndef TCL_WIDE_INT_IS_LONG
static void
-UpdateStringOfWideInt(objPtr)
- register Tcl_Obj *objPtr; /* Int object whose string rep to update. */
+UpdateStringOfWideInt(
+ register Tcl_Obj *objPtr) /* Int object whose string rep to update. */
{
char buffer[TCL_INTEGER_SPACE+2];
register unsigned len;
register Tcl_WideInt wideVal = objPtr->internalRep.wideValue;
/*
- * Note that sprintf will generate a compiler warning under
- * Mingw claiming %I64 is an unknown format specifier.
- * Just ignore this warning. We can't use %L as the format
- * specifier since that gets printed as a 32 bit value.
+ * Note that sprintf will generate a compiler warning under Mingw claiming
+ * %I64 is an unknown format specifier. Just ignore this warning. We can't
+ * use %L as the format specifier since that gets printed as a 32 bit
+ * value.
*/
+
sprintf(buffer, "%" TCL_LL_MODIFIER "d", wideVal);
len = strlen(buffer);
objPtr->bytes = ckalloc((unsigned) len + 1);
memcpy(objPtr->bytes, buffer, len + 1);
objPtr->length = len;
}
-#endif /* TCL_WIDE_INT_IS_LONG */
+#endif /* !NO_WIDE_TYPE */
/*
*----------------------------------------------------------------------
@@ -2763,17 +2810,17 @@ UpdateStringOfWideInt(objPtr)
*
* If a client is compiled with TCL_MEM_DEBUG defined, calls to
* Tcl_NewWideIntObj to create a new 64-bit integer object end up calling
- * the debugging procedure Tcl_DbNewWideIntObj instead.
+ * the debugging function Tcl_DbNewWideIntObj instead.
*
* Otherwise, if the client is compiled without TCL_MEM_DEBUG defined,
* calls to Tcl_NewWideIntObj result in a call to one of the two
- * Tcl_NewWideIntObj implementations below. We provide two implementations
- * so that the Tcl core can be compiled to do memory debugging of the
- * core even if a client does not request it for itself.
+ * Tcl_NewWideIntObj implementations below. We provide two
+ * implementations so that the Tcl core can be compiled to do memory
+ * debugging of the core even if a client does not request it for itself.
*
* Results:
- * The newly created object is returned. This object will have an
- * invalid string representation. The returned object has ref count 0.
+ * The newly created object is returned. This object will have an invalid
+ * string representation. The returned object has ref count 0.
*
* Side effects:
* None.
@@ -2785,9 +2832,10 @@ UpdateStringOfWideInt(objPtr)
#undef Tcl_NewWideIntObj
Tcl_Obj *
-Tcl_NewWideIntObj(wideValue)
- register Tcl_WideInt wideValue; /* Wide integer used to initialize
- * the new object. */
+Tcl_NewWideIntObj(
+ register Tcl_WideInt wideValue)
+ /* Wide integer used to initialize the new
+ * object. */
{
return Tcl_DbNewWideIntObj(wideValue, "unknown", 0);
}
@@ -2795,17 +2843,15 @@ Tcl_NewWideIntObj(wideValue)
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
-Tcl_NewWideIntObj(wideValue)
- register Tcl_WideInt wideValue; /* Wide integer used to initialize
- * the new object. */
+Tcl_NewWideIntObj(
+ register Tcl_WideInt wideValue)
+ /* Wide integer used to initialize the new
+ * object. */
{
register Tcl_Obj *objPtr;
TclNewObj(objPtr);
- objPtr->bytes = NULL;
-
- objPtr->internalRep.wideValue = wideValue;
- objPtr->typePtr = &tclWideIntType;
+ Tcl_SetWideIntObj(objPtr, wideValue);
return objPtr;
}
#endif /* if TCL_MEM_DEBUG */
@@ -2816,27 +2862,25 @@ Tcl_NewWideIntObj(wideValue)
* Tcl_DbNewWideIntObj --
*
* If a client is compiled with TCL_MEM_DEBUG defined, calls to
- * Tcl_NewWideIntObj to create new wide integer end up calling
- * the debugging procedure Tcl_DbNewWideIntObj instead. We
- * provide two implementations of Tcl_DbNewWideIntObj so that
- * whether the Tcl core is compiled to do memory debugging of the
- * core is independent of whether a client requests debugging for
- * itself.
+ * Tcl_NewWideIntObj to create new wide integer end up calling the
+ * debugging function Tcl_DbNewWideIntObj instead. We provide two
+ * implementations of Tcl_DbNewWideIntObj so that whether the Tcl core is
+ * compiled to do memory debugging of the core is independent of whether
+ * a client requests debugging for itself.
*
* When the core is compiled with TCL_MEM_DEBUG defined,
- * Tcl_DbNewWideIntObj calls Tcl_DbCkalloc directly with the file
- * name and line number from its caller. This simplifies
- * debugging since then the checkmem command will report the
- * caller's file name and line number when reporting objects that
- * haven't been freed.
+ * Tcl_DbNewWideIntObj calls Tcl_DbCkalloc directly with the file name
+ * and line number from its caller. This simplifies debugging since then
+ * the checkmem command will report the caller's file name and line
+ * number when reporting objects that haven't been freed.
*
* Otherwise, when the core is compiled without TCL_MEM_DEBUG defined,
- * this procedure just returns the result of calling Tcl_NewWideIntObj.
+ * this function just returns the result of calling Tcl_NewWideIntObj.
*
* Results:
- * The newly created wide integer object is returned. This object
- * will have an invalid string representation. The returned object has
- * ref count 0.
+ * The newly created wide integer object is returned. This object will
+ * have an invalid string representation. The returned object has ref
+ * count 0.
*
* Side effects:
* Allocates memory.
@@ -2847,36 +2891,33 @@ Tcl_NewWideIntObj(wideValue)
#ifdef TCL_MEM_DEBUG
Tcl_Obj *
-Tcl_DbNewWideIntObj(wideValue, file, line)
- register Tcl_WideInt wideValue; /* Wide integer used to initialize
- * the new object. */
- CONST char *file; /* The name of the source file
- * calling this procedure; used for
- * debugging. */
- int line; /* Line number in the source file;
- * used for debugging. */
+Tcl_DbNewWideIntObj(
+ register Tcl_WideInt wideValue,
+ /* Wide integer used to initialize the new
+ * object. */
+ CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
register Tcl_Obj *objPtr;
TclDbNewObj(objPtr, file, line);
- objPtr->bytes = NULL;
-
- objPtr->internalRep.wideValue = wideValue;
- objPtr->typePtr = &tclWideIntType;
+ Tcl_SetWideIntObj(objPtr, wideValue);
return objPtr;
}
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
-Tcl_DbNewWideIntObj(wideValue, file, line)
- register Tcl_WideInt wideValue; /* Long integer used to initialize
- * the new object. */
- CONST char *file; /* The name of the source file
- * calling this procedure; used for
- * debugging. */
- int line; /* Line number in the source file;
- * used for debugging. */
+Tcl_DbNewWideIntObj(
+ register Tcl_WideInt wideValue,
+ /* Long integer used to initialize the new
+ * object. */
+ CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
return Tcl_NewWideIntObj(wideValue);
}
@@ -2887,38 +2928,43 @@ Tcl_DbNewWideIntObj(wideValue, file, line)
*
* Tcl_SetWideIntObj --
*
- * Modify an object to be a wide integer object and to have the
- * specified wide integer value.
+ * Modify an object to be a wide integer object and to have the specified
+ * wide integer value.
*
* Results:
* None.
*
* Side effects:
- * The object's old string rep, if any, is freed. Also, any old
- * internal rep is freed.
+ * The object's old string rep, if any, is freed. Also, any old internal
+ * rep is freed.
*
*----------------------------------------------------------------------
*/
void
-Tcl_SetWideIntObj(objPtr, wideValue)
- register Tcl_Obj *objPtr; /* Object w. internal rep to init. */
- register Tcl_WideInt wideValue; /* Wide integer used to initialize
- * the object's value. */
+Tcl_SetWideIntObj(
+ register Tcl_Obj *objPtr, /* Object w. internal rep to init. */
+ register Tcl_WideInt wideValue)
+ /* Wide integer used to initialize the
+ * object's value. */
{
- register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
-
if (Tcl_IsShared(objPtr)) {
- panic("Tcl_SetWideIntObj called with shared object");
+ Tcl_Panic("%s called with shared object", "Tcl_SetWideIntObj");
}
- if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
- oldTypePtr->freeIntRepProc(objPtr);
+ if ((wideValue >= (Tcl_WideInt) LONG_MIN)
+ && (wideValue <= (Tcl_WideInt) LONG_MAX)) {
+ TclSetLongObj(objPtr, (long) wideValue);
+ } else {
+#ifndef NO_WIDE_TYPE
+ TclSetWideIntObj(objPtr, wideValue);
+#else
+ mp_int big;
+
+ TclBNInitBignumFromWideInt(&big, wideValue);
+ Tcl_SetBignumObj(objPtr, &big);
+#endif
}
-
- objPtr->internalRep.wideValue = wideValue;
- objPtr->typePtr = &tclWideIntType;
- Tcl_InvalidateStringRep(objPtr);
}
/*
@@ -2926,9 +2972,9 @@ Tcl_SetWideIntObj(objPtr, wideValue)
*
* Tcl_GetWideIntFromObj --
*
- * Attempt to return a wide integer from the Tcl object "objPtr". If
- * the object is not already a wide int object, an attempt will be made
- * to convert it to one.
+ * Attempt to return a wide integer from the Tcl object "objPtr". If the
+ * object is not already a wide int object, an attempt will be made to
+ * convert it to one.
*
* Results:
* The return value is a standard Tcl object result. If an error occurs
@@ -2943,33 +2989,589 @@ Tcl_SetWideIntObj(objPtr, wideValue)
*/
int
-Tcl_GetWideIntFromObj(interp, objPtr, wideIntPtr)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- register Tcl_Obj *objPtr; /* Object from which to get a wide int. */
- register Tcl_WideInt *wideIntPtr; /* Place to store resulting long. */
+Tcl_GetWideIntFromObj(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ register Tcl_Obj *objPtr, /* Object from which to get a wide int. */
+ register Tcl_WideInt *wideIntPtr)
+ /* Place to store resulting long. */
{
- register int result;
+ do {
+#ifndef NO_WIDE_TYPE
+ if (objPtr->typePtr == &tclWideIntType) {
+ *wideIntPtr = objPtr->internalRep.wideValue;
+ return TCL_OK;
+ }
+#endif
+ if (objPtr->typePtr == &tclIntType) {
+ *wideIntPtr = (Tcl_WideInt) objPtr->internalRep.longValue;
+ return TCL_OK;
+ }
+ if (objPtr->typePtr == &tclDoubleType) {
+ if (interp != NULL) {
+ Tcl_Obj *msg;
+
+ TclNewLiteralStringObj(msg, "expected integer but got \"");
+ Tcl_AppendObjToObj(msg, objPtr);
+ Tcl_AppendToObj(msg, "\"", -1);
+ Tcl_SetObjResult(interp, msg);
+ }
+ return TCL_ERROR;
+ }
+ if (objPtr->typePtr == &tclBignumType) {
+ /*
+ * Must check for those bignum values that can fit in a
+ * Tcl_WideInt, even when auto-narrowing is enabled.
+ */
- if (objPtr->typePtr == &tclWideIntType) {
- gotWide:
- *wideIntPtr = objPtr->internalRep.wideValue;
- return TCL_OK;
+ mp_int big;
+
+ UNPACK_BIGNUM(objPtr, big);
+ if ((size_t)(big.used) <= (CHAR_BIT * sizeof(Tcl_WideInt)
+ + DIGIT_BIT - 1) / DIGIT_BIT) {
+ Tcl_WideUInt value = 0;
+ unsigned long numBytes = sizeof(Tcl_WideInt);
+ Tcl_WideInt scratch;
+ unsigned char *bytes = (unsigned char *) &scratch;
+
+ if (mp_to_unsigned_bin_n(&big, bytes, &numBytes) == MP_OKAY) {
+ while (numBytes-- > 0) {
+ value = (value << CHAR_BIT) | *bytes++;
+ }
+ if (big.sign) {
+ *wideIntPtr = - (Tcl_WideInt) value;
+ } else {
+ *wideIntPtr = (Tcl_WideInt) value;
+ }
+ return TCL_OK;
+ }
+ }
+ if (interp != NULL) {
+ char *s = "integer value too large to represent";
+ Tcl_Obj* msg = Tcl_NewStringObj(s, -1);
+
+ Tcl_SetObjResult(interp, msg);
+ Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL);
+ }
+ return TCL_ERROR;
+ }
+ } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL,
+ TCL_PARSE_INTEGER_ONLY)==TCL_OK);
+ return TCL_ERROR;
+}
+#ifndef NO_WIDE_TYPE
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetWideIntFromAny --
+ *
+ * Attempts to force the internal representation for a Tcl object to
+ * tclWideIntType, specifically.
+ *
+ * Results:
+ * The return value is a standard object Tcl result. If an error occurs
+ * during conversion, an error message is left in the interpreter's
+ * result unless "interp" is NULL.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetWideIntFromAny(
+ Tcl_Interp *interp, /* Tcl interpreter */
+ Tcl_Obj *objPtr) /* Pointer to the object to convert */
+{
+ Tcl_WideInt w;
+ return Tcl_GetWideIntFromObj(interp, objPtr, &w);
+}
+#endif /* !NO_WIDE_TYPE */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeBignum --
+ *
+ * This function frees the internal rep of a bignum.
+ *
+ * Results:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeBignum(
+ Tcl_Obj *objPtr)
+{
+ mp_int toFree; /* Bignum to free */
+
+ UNPACK_BIGNUM(objPtr, toFree);
+ mp_clear(&toFree);
+ if ((long)(objPtr->internalRep.ptrAndLongRep.value) < 0) {
+ ckfree((char *)objPtr->internalRep.ptrAndLongRep.ptr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupBignum --
+ *
+ * This function duplicates the internal rep of a bignum.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The destination object receies a copy of the source object
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DupBignum(
+ Tcl_Obj *srcPtr,
+ Tcl_Obj *copyPtr)
+{
+ mp_int bignumVal;
+ mp_int bignumCopy;
+
+ copyPtr->typePtr = &tclBignumType;
+ UNPACK_BIGNUM(srcPtr, bignumVal);
+ if (mp_init_copy(&bignumCopy, &bignumVal) != MP_OKAY) {
+ Tcl_Panic("initialization failure in DupBignum");
}
- if (objPtr->typePtr == &tclIntType) {
+ PACK_BIGNUM(bignumCopy, copyPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateStringOfBignum --
+ *
+ * This function updates the string representation of a bignum object.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The object's string is set to whatever results from the bignum-
+ * to-string conversion.
+ *
+ * The object's existing string representation is NOT freed; memory will leak
+ * if the string rep is still valid at the time this function is called.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateStringOfBignum(
+ Tcl_Obj *objPtr)
+{
+ mp_int bignumVal;
+ int size;
+ int status;
+ char* stringVal;
+
+ UNPACK_BIGNUM(objPtr, bignumVal);
+ status = mp_radix_size(&bignumVal, 10, &size);
+ if (status != MP_OKAY) {
+ Tcl_Panic("radix size failure in UpdateStringOfBignum");
+ }
+ if (size == 3) {
/*
- * This cast is safe; all valid ints/longs are wides.
+ * mp_radix_size() returns 3 when more than INT_MAX bytes would be
+ * needed to hold the string rep (because mp_radix_size ignores
+ * integer overflow issues). When we know the string rep will be more
+ * than 3, we can conclude the string rep would overflow our string
+ * length limits.
+ *
+ * Note that so long as we enforce our bignums to the size that fits
+ * in a packed bignum, this branch will never be taken.
*/
- objPtr->internalRep.wideValue =
- Tcl_LongAsWide(objPtr->internalRep.longValue);
- objPtr->typePtr = &tclWideIntType;
- goto gotWide;
+ Tcl_Panic("UpdateStringOfBignum: string length limit exceeded");
}
- result = SetWideIntFromAny(interp, objPtr);
- if (result == TCL_OK) {
- *wideIntPtr = objPtr->internalRep.wideValue;
+ stringVal = ckalloc((size_t) size);
+ status = mp_toradix_n(&bignumVal, stringVal, 10, size);
+ if (status != MP_OKAY) {
+ Tcl_Panic("conversion failure in UpdateStringOfBignum");
}
- return result;
+ objPtr->bytes = stringVal;
+ objPtr->length = size - 1; /* size includes a trailing null byte */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_NewBignumObj --
+ *
+ * Creates an initializes a bignum object.
+ *
+ * Results:
+ * Returns the newly created object.
+ *
+ * Side effects:
+ * The bignum value is cleared, since ownership has transferred to Tcl.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TCL_MEM_DEBUG
+#undef Tcl_NewBignumObj
+
+Tcl_Obj *
+Tcl_NewBignumObj(
+ mp_int *bignumValue)
+{
+ return Tcl_DbNewBignumObj(bignumValue, "unknown", 0);
+}
+#else
+Tcl_Obj *
+Tcl_NewBignumObj(
+ mp_int *bignumValue)
+{
+ Tcl_Obj* objPtr;
+
+ TclNewObj(objPtr);
+ Tcl_SetBignumObj(objPtr, bignumValue);
+ return objPtr;
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DbNewBignumObj --
+ *
+ * This function is normally called when debugging: that is, when
+ * TCL_MEM_DEBUG is defined. It constructs a bignum object, recording the
+ * creation point so that [memory active] can report it.
+ *
+ * Results:
+ * Returns the newly created object.
+ *
+ * Side effects:
+ * The bignum value is cleared, since ownership has transferred to Tcl.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TCL_MEM_DEBUG
+Tcl_Obj *
+Tcl_DbNewBignumObj(
+ mp_int *bignumValue,
+ CONST char *file,
+ int line)
+{
+ Tcl_Obj *objPtr;
+
+ TclDbNewObj(objPtr, file, line);
+ Tcl_SetBignumObj(objPtr, bignumValue);
+ return objPtr;
+}
+#else
+Tcl_Obj *
+Tcl_DbNewBignumObj(
+ mp_int *bignumValue,
+ CONST char *file,
+ int line)
+{
+ return Tcl_NewBignumObj(bignumValue);
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetBignumFromObj --
+ *
+ * This function retrieves a 'bignum' value from a Tcl object, converting
+ * the object if necessary. Either copies or transfers the mp_int value
+ * depending on the copy flag value passed in.
+ *
+ * Results:
+ * Returns TCL_OK if the conversion is successful, TCL_ERROR otherwise.
+ *
+ * Side effects:
+ * A copy of bignum is stored in *bignumValue, which is expected to be
+ * uninitialized or cleared. If conversion fails, and the 'interp'
+ * argument is not NULL, an error message is stored in the interpreter
+ * result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetBignumFromObj(
+ Tcl_Interp *interp, /* Tcl interpreter for error reporting */
+ Tcl_Obj *objPtr, /* Object to read */
+ int copy, /* Whether to copy the returned bignum value */
+ mp_int *bignumValue) /* Returned bignum value. */
+{
+ do {
+ if (objPtr->typePtr == &tclBignumType) {
+ if (copy || Tcl_IsShared(objPtr)) {
+ mp_int temp;
+ UNPACK_BIGNUM(objPtr, temp);
+ mp_init_copy(bignumValue, &temp);
+ } else {
+ UNPACK_BIGNUM(objPtr, *bignumValue);
+ objPtr->internalRep.ptrAndLongRep.ptr = NULL;
+ objPtr->internalRep.ptrAndLongRep.value = 0;
+ objPtr->typePtr = NULL;
+ if (objPtr->bytes == NULL) {
+ TclInitStringRep(objPtr, tclEmptyStringRep, 0);
+ }
+ }
+ return TCL_OK;
+ }
+ if (objPtr->typePtr == &tclIntType) {
+ TclBNInitBignumFromLong(bignumValue, objPtr->internalRep.longValue);
+ return TCL_OK;
+ }
+#ifndef NO_WIDE_TYPE
+ if (objPtr->typePtr == &tclWideIntType) {
+ TclBNInitBignumFromWideInt(bignumValue,
+ objPtr->internalRep.wideValue);
+ return TCL_OK;
+ }
+#endif
+ if (objPtr->typePtr == &tclDoubleType) {
+ if (interp != NULL) {
+ Tcl_Obj *msg;
+
+ TclNewLiteralStringObj(msg, "expected integer but got \"");
+ Tcl_AppendObjToObj(msg, objPtr);
+ Tcl_AppendToObj(msg, "\"", -1);
+ Tcl_SetObjResult(interp, msg);
+ }
+ return TCL_ERROR;
+ }
+ } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL,
+ TCL_PARSE_INTEGER_ONLY)==TCL_OK);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetBignumFromObj --
+ *
+ * This function retrieves a 'bignum' value from a Tcl object, converting
+ * the object if necessary.
+ *
+ * Results:
+ * Returns TCL_OK if the conversion is successful, TCL_ERROR otherwise.
+ *
+ * Side effects:
+ * A copy of bignum is stored in *bignumValue, which is expected to be
+ * uninitialized or cleared. If conversion fails, an the 'interp'
+ * argument is not NULL, an error message is stored in the interpreter
+ * result.
+ *
+ * It is expected that the caller will NOT have invoked mp_init on the
+ * bignum value before passing it in. Tcl will initialize the mp_int as
+ * it sets the value. The value is a copy of the value in objPtr, so it
+ * becomes the responsibility of the caller to call mp_clear on it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GetBignumFromObj(
+ Tcl_Interp *interp, /* Tcl interpreter for error reporting */
+ Tcl_Obj *objPtr, /* Object to read */
+ mp_int *bignumValue) /* Returned bignum value. */
+{
+ return GetBignumFromObj(interp, objPtr, 1, bignumValue);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_TakeBignumFromObj --
+ *
+ * This function retrieves a 'bignum' value from a Tcl object, converting
+ * the object if necessary.
+ *
+ * Results:
+ * Returns TCL_OK if the conversion is successful, TCL_ERROR otherwise.
+ *
+ * Side effects:
+ * A copy of bignum is stored in *bignumValue, which is expected to be
+ * uninitialized or cleared. If conversion fails, an the 'interp'
+ * argument is not NULL, an error message is stored in the interpreter
+ * result.
+ *
+ * It is expected that the caller will NOT have invoked mp_init on the
+ * bignum value before passing it in. Tcl will initialize the mp_int as
+ * it sets the value. The value is transferred from the internals of
+ * objPtr to the caller, passing responsibility of the caller to call
+ * mp_clear on it. The objPtr is cleared to hold an empty value.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_TakeBignumFromObj(
+ Tcl_Interp *interp, /* Tcl interpreter for error reporting */
+ Tcl_Obj *objPtr, /* Object to read */
+ mp_int *bignumValue) /* Returned bignum value. */
+{
+ return GetBignumFromObj(interp, objPtr, 0, bignumValue);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetBignumObj --
+ *
+ * This function sets the value of a Tcl_Obj to a large integer.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Object value is stored. The bignum value is cleared, since ownership
+ * has transferred to Tcl.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetBignumObj(
+ Tcl_Obj *objPtr, /* Object to set */
+ mp_int *bignumValue) /* Value to store */
+{
+ if (Tcl_IsShared(objPtr)) {
+ Tcl_Panic("%s called with shared object", "Tcl_SetBignumObj");
+ }
+ if ((size_t)(bignumValue->used)
+ <= (CHAR_BIT * sizeof(long) + DIGIT_BIT - 1) / DIGIT_BIT) {
+ unsigned long value = 0, numBytes = sizeof(long);
+ long scratch;
+ unsigned char *bytes = (unsigned char *)&scratch;
+ if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) {
+ goto tooLargeForLong;
+ }
+ while (numBytes-- > 0) {
+ value = (value << CHAR_BIT) | *bytes++;
+ }
+ if (value > (((~(unsigned long)0) >> 1) + bignumValue->sign)) {
+ goto tooLargeForLong;
+ }
+ if (bignumValue->sign) {
+ TclSetLongObj(objPtr, -(long)value);
+ } else {
+ TclSetLongObj(objPtr, (long)value);
+ }
+ mp_clear(bignumValue);
+ return;
+ }
+ tooLargeForLong:
+#ifndef NO_WIDE_TYPE
+ if ((size_t)(bignumValue->used)
+ <= (CHAR_BIT * sizeof(Tcl_WideInt) + DIGIT_BIT - 1) / DIGIT_BIT) {
+ Tcl_WideUInt value = 0;
+ unsigned long numBytes = sizeof(Tcl_WideInt);
+ Tcl_WideInt scratch;
+ unsigned char *bytes = (unsigned char *)&scratch;
+ if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) {
+ goto tooLargeForWide;
+ }
+ while (numBytes-- > 0) {
+ value = (value << CHAR_BIT) | *bytes++;
+ }
+ if (value > (((~(Tcl_WideUInt)0) >> 1) + bignumValue->sign)) {
+ goto tooLargeForWide;
+ }
+ if (bignumValue->sign) {
+ TclSetWideIntObj(objPtr, -(Tcl_WideInt)value);
+ } else {
+ TclSetWideIntObj(objPtr, (Tcl_WideInt)value);
+ }
+ mp_clear(bignumValue);
+ return;
+ }
+ tooLargeForWide:
+#endif
+ TclInvalidateStringRep(objPtr);
+ TclFreeIntRep(objPtr);
+ TclSetBignumIntRep(objPtr, bignumValue);
+}
+
+void
+TclSetBignumIntRep(
+ Tcl_Obj *objPtr,
+ mp_int *bignumValue)
+{
+ objPtr->typePtr = &tclBignumType;
+ PACK_BIGNUM(*bignumValue, objPtr);
+
+ /*
+ * Clear the mp_int value.
+ * Don't call mp_clear() because it would free the digit array
+ * we just packed into the Tcl_Obj.
+ */
+
+ bignumValue->dp = NULL;
+ bignumValue->alloc = bignumValue->used = 0;
+ bignumValue->sign = MP_NEG;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetNumberFromObj --
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *----------------------------------------------------------------------
+ */
+
+int TclGetNumberFromObj(
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr,
+ ClientData *clientDataPtr,
+ int *typePtr)
+{
+ do {
+ if (objPtr->typePtr == &tclDoubleType) {
+ if (TclIsNaN(objPtr->internalRep.doubleValue)) {
+ *typePtr = TCL_NUMBER_NAN;
+ } else {
+ *typePtr = TCL_NUMBER_DOUBLE;
+ }
+ *clientDataPtr = &(objPtr->internalRep.doubleValue);
+ return TCL_OK;
+ }
+ if (objPtr->typePtr == &tclIntType) {
+ *typePtr = TCL_NUMBER_LONG;
+ *clientDataPtr = &(objPtr->internalRep.longValue);
+ return TCL_OK;
+ }
+#ifndef NO_WIDE_TYPE
+ if (objPtr->typePtr == &tclWideIntType) {
+ *typePtr = TCL_NUMBER_WIDE;
+ *clientDataPtr = &(objPtr->internalRep.wideValue);
+ return TCL_OK;
+ }
+#endif
+ if (objPtr->typePtr == &tclBignumType) {
+ static Tcl_ThreadDataKey bignumKey;
+ mp_int *bigPtr = Tcl_GetThreadData(&bignumKey,
+ (int) sizeof(mp_int));
+ UNPACK_BIGNUM( objPtr, *bigPtr );
+ *typePtr = TCL_NUMBER_BIG;
+ *clientDataPtr = bigPtr;
+ return TCL_OK;
+ }
+ } while (TCL_OK ==
+ TclParseNumber(interp, objPtr, "number", NULL, -1, NULL, 0));
+ return TCL_ERROR;
}
/*
@@ -2977,12 +3579,12 @@ Tcl_GetWideIntFromObj(interp, objPtr, wideIntPtr)
*
* Tcl_DbIncrRefCount --
*
- * This procedure is normally called when debugging: i.e., when
- * TCL_MEM_DEBUG is defined. This checks to see whether or not
- * the memory has been freed before incrementing the ref count.
+ * This function is normally called when debugging: i.e., when
+ * TCL_MEM_DEBUG is defined. This checks to see whether or not the memory
+ * has been freed before incrementing the ref count.
*
- * When TCL_MEM_DEBUG is not defined, this procedure just increments
- * the reference count of the object.
+ * When TCL_MEM_DEBUG is not defined, this function just increments the
+ * reference count of the object.
*
* Results:
* None.
@@ -2994,20 +3596,45 @@ Tcl_GetWideIntFromObj(interp, objPtr, wideIntPtr)
*/
void
-Tcl_DbIncrRefCount(objPtr, file, line)
- register Tcl_Obj *objPtr; /* The object we are registering a
- * reference to. */
- CONST char *file; /* The name of the source file calling this
- * procedure; used for debugging. */
- int line; /* Line number in the source file; used
- * for debugging. */
+Tcl_DbIncrRefCount(
+ register Tcl_Obj *objPtr, /* The object we are registering a reference
+ * to. */
+ CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
#ifdef TCL_MEM_DEBUG
if (objPtr->refCount == 0x61616161) {
fprintf(stderr, "file = %s, line = %d\n", file, line);
fflush(stderr);
- panic("Trying to increment refCount of previously disposed object.");
+ Tcl_Panic("incrementing refCount of previously disposed object");
}
+
+# ifdef TCL_THREADS
+ /*
+ * Check to make sure that the Tcl_Obj was allocated by the current
+ * thread. Don't do this check when shutting down since thread local
+ * storage can be finalized before the last Tcl_Obj is freed.
+ */
+
+ if (!TclInExit()) {
+ Tcl_HashTable *tablePtr;
+ Tcl_HashEntry *hPtr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ tablePtr = tsdPtr->objThreadMap;
+ if (!tablePtr) {
+ Tcl_Panic("object table not initialized");
+ }
+ hPtr = Tcl_FindHashEntry(tablePtr, (char *) objPtr);
+ if (!hPtr) {
+ Tcl_Panic("%s%s",
+ "Trying to incr ref count of "
+ "Tcl_Obj allocated in another thread");
+ }
+ }
+# endif
#endif
++(objPtr)->refCount;
}
@@ -3017,12 +3644,12 @@ Tcl_DbIncrRefCount(objPtr, file, line)
*
* Tcl_DbDecrRefCount --
*
- * This procedure is normally called when debugging: i.e., when
- * TCL_MEM_DEBUG is defined. This checks to see whether or not
- * the memory has been freed before decrementing the ref count.
+ * This function is normally called when debugging: i.e., when
+ * TCL_MEM_DEBUG is defined. This checks to see whether or not the memory
+ * has been freed before decrementing the ref count.
*
- * When TCL_MEM_DEBUG is not defined, this procedure just decrements
- * the reference count of the object.
+ * When TCL_MEM_DEBUG is not defined, this function just decrements the
+ * reference count of the object.
*
* Results:
* None.
@@ -3034,20 +3661,59 @@ Tcl_DbIncrRefCount(objPtr, file, line)
*/
void
-Tcl_DbDecrRefCount(objPtr, file, line)
- register Tcl_Obj *objPtr; /* The object we are releasing a reference
+Tcl_DbDecrRefCount(
+ register Tcl_Obj *objPtr, /* The object we are releasing a reference
* to. */
- CONST char *file; /* The name of the source file calling this
- * procedure; used for debugging. */
- int line; /* Line number in the source file; used
- * for debugging. */
+ CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
#ifdef TCL_MEM_DEBUG
if (objPtr->refCount == 0x61616161) {
fprintf(stderr, "file = %s, line = %d\n", file, line);
fflush(stderr);
- panic("Trying to decrement refCount of previously disposed object.");
+ Tcl_Panic("decrementing refCount of previously disposed object");
}
+
+# ifdef TCL_THREADS
+ /*
+ * Check to make sure that the Tcl_Obj was allocated by the current
+ * thread. Don't do this check when shutting down since thread local
+ * storage can be finalized before the last Tcl_Obj is freed.
+ */
+
+ if (!TclInExit()) {
+ Tcl_HashTable *tablePtr;
+ Tcl_HashEntry *hPtr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ tablePtr = tsdPtr->objThreadMap;
+ if (!tablePtr) {
+ Tcl_Panic("object table not initialized");
+ }
+ hPtr = Tcl_FindHashEntry(tablePtr, (char *) objPtr);
+ if (!hPtr) {
+ Tcl_Panic("%s%s",
+ "Trying to decr ref count of "
+ "Tcl_Obj allocated in another thread");
+ }
+
+ /*
+ * If the Tcl_Obj is going to be deleted, remove the entry.
+ */
+
+ if ((objPtr->refCount - 1) <= 0) {
+ ObjData *objData = Tcl_GetHashValue(hPtr);
+
+ if (objData != NULL) {
+ ckfree((char *) objData);
+ }
+
+ Tcl_DeleteHashEntry(hPtr);
+ }
+ }
+# endif
#endif
if (--(objPtr)->refCount <= 0) {
TclFreeObj(objPtr);
@@ -3059,12 +3725,12 @@ Tcl_DbDecrRefCount(objPtr, file, line)
*
* Tcl_DbIsShared --
*
- * This procedure is normally called when debugging: i.e., when
- * TCL_MEM_DEBUG is defined. It tests whether the object has a ref
- * count greater than one.
+ * This function is normally called when debugging: i.e., when
+ * TCL_MEM_DEBUG is defined. It tests whether the object has a ref count
+ * greater than one.
*
- * When TCL_MEM_DEBUG is not defined, this procedure just tests
- * if the object has a ref count greater than one.
+ * When TCL_MEM_DEBUG is not defined, this function just tests if the
+ * object has a ref count greater than one.
*
* Results:
* None.
@@ -3076,20 +3742,45 @@ Tcl_DbDecrRefCount(objPtr, file, line)
*/
int
-Tcl_DbIsShared(objPtr, file, line)
- register Tcl_Obj *objPtr; /* The object to test for being shared. */
- CONST char *file; /* The name of the source file calling this
- * procedure; used for debugging. */
- int line; /* Line number in the source file; used
- * for debugging. */
+Tcl_DbIsShared(
+ register Tcl_Obj *objPtr, /* The object to test for being shared. */
+ CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
#ifdef TCL_MEM_DEBUG
if (objPtr->refCount == 0x61616161) {
fprintf(stderr, "file = %s, line = %d\n", file, line);
fflush(stderr);
- panic("Trying to check whether previously disposed object is shared.");
+ Tcl_Panic("checking whether previously disposed object is shared");
+ }
+
+# ifdef TCL_THREADS
+ /*
+ * Check to make sure that the Tcl_Obj was allocated by the current
+ * thread. Don't do this check when shutting down since thread local
+ * storage can be finalized before the last Tcl_Obj is freed.
+ */
+
+ if (!TclInExit()) {
+ Tcl_HashTable *tablePtr;
+ Tcl_HashEntry *hPtr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ tablePtr = tsdPtr->objThreadMap;
+ if (!tablePtr) {
+ Tcl_Panic("object table not initialized");
+ }
+ hPtr = Tcl_FindHashEntry(tablePtr, (char *) objPtr);
+ if (!hPtr) {
+ Tcl_Panic("%s%s",
+ "Trying to check shared status of"
+ "Tcl_Obj allocated in another thread");
+ }
}
+# endif
#endif
+
#ifdef TCL_COMPILE_STATS
Tcl_MutexLock(&tclObjMutex);
if ((objPtr)->refCount <= 1) {
@@ -3101,6 +3792,7 @@ Tcl_DbIsShared(objPtr, file, line)
}
Tcl_MutexUnlock(&tclObjMutex);
#endif
+
return ((objPtr)->refCount > 1);
}
@@ -3109,8 +3801,8 @@ Tcl_DbIsShared(objPtr, file, line)
*
* Tcl_InitObjHashTable --
*
- * Given storage for a hash table, set up the fields to prepare
- * the hash table for use, the keys are Tcl_Obj *.
+ * Given storage for a hash table, set up the fields to prepare the hash
+ * table for use, the keys are Tcl_Obj *.
*
* Results:
* None.
@@ -3123,9 +3815,10 @@ Tcl_DbIsShared(objPtr, file, line)
*/
void
-Tcl_InitObjHashTable(tablePtr)
- register Tcl_HashTable *tablePtr; /* Pointer to table record, which
- * is supplied by the caller. */
+Tcl_InitObjHashTable(
+ register Tcl_HashTable *tablePtr)
+ /* Pointer to table record, which is supplied
+ * by the caller. */
{
Tcl_InitCustomHashTable(tablePtr, TCL_CUSTOM_PTR_KEYS,
&tclObjHashKeyType);
@@ -3148,16 +3841,17 @@ Tcl_InitObjHashTable(tablePtr)
*/
static Tcl_HashEntry *
-AllocObjEntry(tablePtr, keyPtr)
- Tcl_HashTable *tablePtr; /* Hash table. */
- VOID *keyPtr; /* Key to store in the hash table entry. */
+AllocObjEntry(
+ Tcl_HashTable *tablePtr, /* Hash table. */
+ void *keyPtr) /* Key to store in the hash table entry. */
{
Tcl_Obj *objPtr = (Tcl_Obj *) keyPtr;
Tcl_HashEntry *hPtr;
hPtr = (Tcl_HashEntry *) ckalloc((unsigned) (sizeof(Tcl_HashEntry)));
hPtr->key.oneWordValue = (char *) objPtr;
- Tcl_IncrRefCount (objPtr);
+ Tcl_IncrRefCount(objPtr);
+ hPtr->clientData = NULL;
return hPtr;
}
@@ -3165,13 +3859,13 @@ AllocObjEntry(tablePtr, keyPtr)
/*
*----------------------------------------------------------------------
*
- * CompareObjKeys --
+ * TclCompareObjKeys --
*
* Compares two Tcl_Obj * keys.
*
* Results:
- * The return value is 0 if they are different and 1 if they are
- * the same.
+ * The return value is 0 if they are different and 1 if they are the
+ * same.
*
* Side effects:
* None.
@@ -3179,10 +3873,10 @@ AllocObjEntry(tablePtr, keyPtr)
*----------------------------------------------------------------------
*/
-static int
-CompareObjKeys(keyPtr, hPtr)
- VOID *keyPtr; /* New key to compare. */
- Tcl_HashEntry *hPtr; /* Existing key to compare. */
+int
+TclCompareObjKeys(
+ void *keyPtr, /* New key to compare. */
+ Tcl_HashEntry *hPtr) /* Existing key to compare. */
{
Tcl_Obj *objPtr1 = (Tcl_Obj *) keyPtr;
Tcl_Obj *objPtr2 = (Tcl_Obj *) hPtr->key.oneWordValue;
@@ -3192,6 +3886,7 @@ CompareObjKeys(keyPtr, hPtr)
/*
* If the object pointers are the same then they match.
*/
+
if (objPtr1 == objPtr2) {
return 1;
}
@@ -3200,14 +3895,16 @@ CompareObjKeys(keyPtr, hPtr)
* Don't use Tcl_GetStringFromObj as it would prevent l1 and l2 being
* in a register.
*/
+
p1 = TclGetString(objPtr1);
l1 = objPtr1->length;
p2 = TclGetString(objPtr2);
l2 = objPtr2->length;
-
+
/*
* Only compare if the string representations are of the same length.
*/
+
if (l1 == l2) {
for (;; p1++, p2++, l1--) {
if (*p1 != *p2) {
@@ -3225,7 +3922,7 @@ CompareObjKeys(keyPtr, hPtr)
/*
*----------------------------------------------------------------------
*
- * FreeObjEntry --
+ * TclFreeObjEntry --
*
* Frees space for a Tcl_HashEntry containing the Tcl_Obj * key.
*
@@ -3238,27 +3935,27 @@ CompareObjKeys(keyPtr, hPtr)
*----------------------------------------------------------------------
*/
-static void
-FreeObjEntry(hPtr)
- Tcl_HashEntry *hPtr; /* Hash entry to free. */
+void
+TclFreeObjEntry(
+ Tcl_HashEntry *hPtr) /* Hash entry to free. */
{
Tcl_Obj *objPtr = (Tcl_Obj *) hPtr->key.oneWordValue;
- Tcl_DecrRefCount (objPtr);
- ckfree ((char *) hPtr);
+ Tcl_DecrRefCount(objPtr);
+ ckfree((char *) hPtr);
}
/*
*----------------------------------------------------------------------
*
- * HashObjKey --
+ * TclHashObjKey --
*
* Compute a one-word summary of the string representation of the
* Tcl_Obj, which can be used to generate a hash index.
*
* Results:
- * The return value is a one-word summary of the information in
- * the string representation of the Tcl_Obj.
+ * The return value is a one-word summary of the information in the
+ * string representation of the Tcl_Obj.
*
* Side effects:
* None.
@@ -3266,36 +3963,35 @@ FreeObjEntry(hPtr)
*----------------------------------------------------------------------
*/
-static unsigned int
-HashObjKey(tablePtr, keyPtr)
- Tcl_HashTable *tablePtr; /* Hash table. */
- VOID *keyPtr; /* Key from which to compute hash value. */
+unsigned int
+TclHashObjKey(
+ Tcl_HashTable *tablePtr, /* Hash table. */
+ void *keyPtr) /* Key from which to compute hash value. */
{
Tcl_Obj *objPtr = (Tcl_Obj *) keyPtr;
CONST char *string = TclGetString(objPtr);
int length = objPtr->length;
- unsigned int result;
+ unsigned int result = 0;
int i;
/*
- * I tried a zillion different hash functions and asked many other
- * people for advice. Many people had their own favorite functions,
- * all different, but no-one had much idea why they were good ones.
- * I chose the one below (multiply by 9 and add new character)
- * because of the following reasons:
+ * I tried a zillion different hash functions and asked many other people
+ * for advice. Many people had their own favorite functions, all
+ * different, but no-one had much idea why they were good ones. I chose
+ * the one below (multiply by 9 and add new character) because of the
+ * following reasons:
*
- * 1. Multiplying by 10 is perfect for keys that are decimal strings,
- * and multiplying by 9 is just about as good.
- * 2. Times-9 is (shift-left-3) plus (old). This means that each
- * character's bits hang around in the low-order bits of the
- * hash value for ever, plus they spread fairly rapidly up to
- * the high-order bits to fill out the hash value. This seems
- * works well both for decimal and non-decimal strings.
+ * 1. Multiplying by 10 is perfect for keys that are decimal strings, and
+ * multiplying by 9 is just about as good.
+ * 2. Times-9 is (shift-left-3) plus (old). This means that each
+ * character's bits hang around in the low-order bits of the hash value
+ * for ever, plus they spread fairly rapidly up to the high-order bits
+ * to fill out the hash value. This seems works well both for decimal
+ * and *non-decimal strings.
*/
- result = 0;
for (i=0 ; i<length ; i++) {
- result += (result<<3) + string[i];
+ result += (result << 3) + string[i];
}
return result;
}
@@ -3305,111 +4001,78 @@ HashObjKey(tablePtr, keyPtr)
*
* Tcl_GetCommandFromObj --
*
- * Returns the command specified by the name in a Tcl_Obj.
+ * Returns the command specified by the name in a Tcl_Obj.
*
* Results:
- * Returns a token for the command if it is found. Otherwise, if it
- * can't be found or there is an error, returns NULL.
+ * Returns a token for the command if it is found. Otherwise, if it can't
+ * be found or there is an error, returns NULL.
*
* Side effects:
- * May update the internal representation for the object, caching
- * the command reference so that the next time this procedure is
- * called with the same object, the command can be found quickly.
+ * May update the internal representation for the object, caching the
+ * command reference so that the next time this function is called with
+ * the same object, the command can be found quickly.
*
*----------------------------------------------------------------------
*/
Tcl_Command
-Tcl_GetCommandFromObj(interp, objPtr)
- Tcl_Interp *interp; /* The interpreter in which to resolve the
+Tcl_GetCommandFromObj(
+ Tcl_Interp *interp, /* The interpreter in which to resolve the
* command and to report errors. */
- register Tcl_Obj *objPtr; /* The object containing the command's
- * name. If the name starts with "::", will
- * be looked up in global namespace. Else,
- * looked up first in the current namespace,
- * then in global namespace. */
+ register Tcl_Obj *objPtr) /* The object containing the command's name.
+ * If the name starts with "::", will be
+ * looked up in global namespace. Else, looked
+ * up first in the current namespace, then in
+ * global namespace. */
{
- Interp *iPtr = (Interp *) interp;
register ResolvedCmdName *resPtr;
register Command *cmdPtr;
- Namespace *currNsPtr;
+ Namespace *refNsPtr;
int result;
- CallFrame *savedFramePtr;
- char *name;
-
- /*
- * If the variable name is fully qualified, do as if the lookup were
- * done from the global namespace; this helps avoid repeated lookups
- * of fully qualified names. It costs close to nothing, and may be very
- * helpful for OO applications which pass along a command name ("this"),
- * [Patch 456668]
- */
-
- savedFramePtr = iPtr->varFramePtr;
- name = Tcl_GetString(objPtr);
- if ((*name++ == ':') && (*name == ':')) {
- iPtr->varFramePtr = NULL;
- }
/*
* Get the internal representation, converting to a command type if
- * needed. The internal representation is a ResolvedCmdName that points
- * to the actual command.
+ * needed. The internal representation is a ResolvedCmdName that points to
+ * the actual command.
+ *
+ * Check the context namespace and the namespace epoch of the resolved
+ * symbol to make sure that it is fresh. Note that we verify that the
+ * namespace id of the context namespace is the same as the one we cached;
+ * this insures that the namespace wasn't deleted and a new one created at
+ * the same address with the same command epoch. Note that fully qualified
+ * names have a NULL refNsPtr, these checks needn't be made.
+ *
+ * Check also that the command's epoch is up to date, and that the command
+ * is not deleted.
+ *
+ * If any check fails, then force another conversion to the command type,
+ * to discard the old rep and create a new one.
*/
-
- if (objPtr->typePtr != &tclCmdNameType) {
- result = tclCmdNameType.setFromAnyProc(interp, objPtr);
- if (result != TCL_OK) {
- iPtr->varFramePtr = savedFramePtr;
- return (Tcl_Command) NULL;
- }
- }
- resPtr = (ResolvedCmdName *) objPtr->internalRep.twoPtrValue.ptr1;
- /*
- * Get the current namespace.
- */
-
- if (iPtr->varFramePtr != NULL) {
- currNsPtr = iPtr->varFramePtr->nsPtr;
- } else {
- currNsPtr = iPtr->globalNsPtr;
+ resPtr = (ResolvedCmdName *) objPtr->internalRep.twoPtrValue.ptr1;
+ if ((objPtr->typePtr != &tclCmdNameType)
+ || (resPtr == NULL)
+ || (cmdPtr = resPtr->cmdPtr, cmdPtr->cmdEpoch != resPtr->cmdEpoch)
+ || (cmdPtr->flags & CMD_IS_DELETED)
+ || (interp != cmdPtr->nsPtr->interp)
+ || (cmdPtr->nsPtr->flags & NS_DYING)
+ || ((resPtr->refNsPtr != NULL) &&
+ (((refNsPtr = (Namespace *) TclGetCurrentNamespace(interp))
+ != resPtr->refNsPtr)
+ || (resPtr->refNsId != refNsPtr->nsId)
+ || (resPtr->refNsCmdEpoch != refNsPtr->cmdRefEpoch)))
+ ) {
+
+ result = tclCmdNameType.setFromAnyProc(interp, objPtr);
+
+ resPtr = (ResolvedCmdName *) objPtr->internalRep.twoPtrValue.ptr1;
+ if ((result == TCL_OK) && resPtr) {
+ cmdPtr = resPtr->cmdPtr;
+ } else {
+ cmdPtr = NULL;
+ }
}
-
- /*
- * Check the context namespace and the namespace epoch of the resolved
- * symbol to make sure that it is fresh. If not, then force another
- * conversion to the command type, to discard the old rep and create a
- * new one. Note that we verify that the namespace id of the context
- * namespace is the same as the one we cached; this insures that the
- * namespace wasn't deleted and a new one created at the same address
- * with the same command epoch.
- */
- cmdPtr = NULL;
- if ((resPtr != NULL)
- && (resPtr->refNsPtr == currNsPtr)
- && (resPtr->refNsId == currNsPtr->nsId)
- && (resPtr->refNsCmdEpoch == currNsPtr->cmdRefEpoch)) {
- cmdPtr = resPtr->cmdPtr;
- if (cmdPtr->cmdEpoch != resPtr->cmdEpoch
- || (cmdPtr->flags & CMD_IS_DELETED)) {
- cmdPtr = NULL;
- }
- }
-
- if (cmdPtr == NULL) {
- result = tclCmdNameType.setFromAnyProc(interp, objPtr);
- if (result != TCL_OK) {
- iPtr->varFramePtr = savedFramePtr;
- return (Tcl_Command) NULL;
- }
- resPtr = (ResolvedCmdName *) objPtr->internalRep.twoPtrValue.ptr1;
- if (resPtr != NULL) {
- cmdPtr = resPtr->cmdPtr;
- }
- }
- iPtr->varFramePtr = savedFramePtr;
return (Tcl_Command) cmdPtr;
}
@@ -3426,54 +4089,59 @@ Tcl_GetCommandFromObj(interp, objPtr)
*
* Side effects:
* The object's old internal rep is freed. It's string rep is not
- * changed. The refcount in the Command structure is incremented to
- * keep it from being freed if the command is later deleted until
+ * changed. The refcount in the Command structure is incremented to keep
+ * it from being freed if the command is later deleted until
* TclExecuteByteCode has a chance to recognize that it was deleted.
*
*----------------------------------------------------------------------
*/
void
-TclSetCmdNameObj(interp, objPtr, cmdPtr)
- Tcl_Interp *interp; /* Points to interpreter containing command
+TclSetCmdNameObj(
+ Tcl_Interp *interp, /* Points to interpreter containing command
* that should be cached in objPtr. */
- register Tcl_Obj *objPtr; /* Points to Tcl object to be changed to
- * a CmdName object. */
- Command *cmdPtr; /* Points to Command structure that the
+ register Tcl_Obj *objPtr, /* Points to Tcl object to be changed to a
+ * CmdName object. */
+ Command *cmdPtr) /* Points to Command structure that the
* CmdName object should refer to. */
{
Interp *iPtr = (Interp *) interp;
register ResolvedCmdName *resPtr;
- Tcl_ObjType *oldTypePtr = objPtr->typePtr;
register Namespace *currNsPtr;
+ char *name;
- if (oldTypePtr == &tclCmdNameType) {
+ if (objPtr->typePtr == &tclCmdNameType) {
return;
}
-
- /*
- * Get the current namespace.
- */
-
- if (iPtr->varFramePtr != NULL) {
- currNsPtr = iPtr->varFramePtr->nsPtr;
- } else {
- currNsPtr = iPtr->globalNsPtr;
- }
-
+
cmdPtr->refCount++;
resPtr = (ResolvedCmdName *) ckalloc(sizeof(ResolvedCmdName));
resPtr->cmdPtr = cmdPtr;
- resPtr->refNsPtr = currNsPtr;
- resPtr->refNsId = currNsPtr->nsId;
- resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch;
resPtr->cmdEpoch = cmdPtr->cmdEpoch;
resPtr->refCount = 1;
-
- if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
- oldTypePtr->freeIntRepProc(objPtr);
+
+ name = TclGetString(objPtr);
+ if ((*name++ == ':') && (*name == ':')) {
+ /*
+ * The name is fully qualified: set the referring namespace to
+ * NULL.
+ */
+
+ resPtr->refNsPtr = NULL;
+ } else {
+ /*
+ * Get the current namespace.
+ */
+
+ currNsPtr = iPtr->varFramePtr->nsPtr;
+
+ resPtr->refNsPtr = currNsPtr;
+ resPtr->refNsId = currNsPtr->nsId;
+ resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch;
}
- objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) resPtr;
+
+ TclFreeIntRep(objPtr);
+ objPtr->internalRep.twoPtrValue.ptr1 = (void *) resPtr;
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
objPtr->typePtr = &tclCmdNameType;
}
@@ -3491,17 +4159,17 @@ TclSetCmdNameObj(interp, objPtr, cmdPtr)
*
* Side effects:
* Decrements the ref count of any cached ResolvedCmdName structure
- * pointed to by the cmdName's internal representation. If this is
- * the last use of the ResolvedCmdName, it is freed. This in turn
- * decrements the ref count of the Command structure pointed to by
- * the ResolvedSymbol, which may free the Command structure.
+ * pointed to by the cmdName's internal representation. If this is the
+ * last use of the ResolvedCmdName, it is freed. This in turn decrements
+ * the ref count of the Command structure pointed to by the
+ * ResolvedSymbol, which may free the Command structure.
*
*----------------------------------------------------------------------
*/
static void
-FreeCmdNameInternalRep(objPtr)
- register Tcl_Obj *objPtr; /* CmdName object with internal
+FreeCmdNameInternalRep(
+ register Tcl_Obj *objPtr) /* CmdName object with internal
* representation to free. */
{
register ResolvedCmdName *resPtr =
@@ -3509,23 +4177,24 @@ FreeCmdNameInternalRep(objPtr)
if (resPtr != NULL) {
/*
- * Decrement the reference count of the ResolvedCmdName structure.
- * If there are no more uses, free the ResolvedCmdName structure.
+ * Decrement the reference count of the ResolvedCmdName structure. If
+ * there are no more uses, free the ResolvedCmdName structure.
*/
-
- resPtr->refCount--;
- if (resPtr->refCount == 0) {
- /*
- * Now free the cached command, unless it is still in its
- * hash table or if there are other references to it
- * from other cmdName objects.
+
+ resPtr->refCount--;
+ if (resPtr->refCount == 0) {
+ /*
+ * Now free the cached command, unless it is still in its hash
+ * table or if there are other references to it from other cmdName
+ * objects.
*/
-
- Command *cmdPtr = resPtr->cmdPtr;
- TclCleanupCommand(cmdPtr);
- ckfree((char *) resPtr);
- }
+
+ Command *cmdPtr = resPtr->cmdPtr;
+ TclCleanupCommandMacro(cmdPtr);
+ ckfree((char *) resPtr);
+ }
}
+ objPtr->typePtr = NULL;
}
/*
@@ -3533,33 +4202,33 @@ FreeCmdNameInternalRep(objPtr)
*
* DupCmdNameInternalRep --
*
- * Initialize the internal representation of an cmdName Tcl_Obj to a
- * copy of the internal representation of an existing cmdName object.
+ * Initialize the internal representation of an cmdName Tcl_Obj to a copy
+ * of the internal representation of an existing cmdName object.
*
* Results:
* None.
*
* Side effects:
* "copyPtr"s internal rep is set to point to the ResolvedCmdName
- * structure corresponding to "srcPtr"s internal rep. Increments the
- * ref count of the ResolvedCmdName structure pointed to by the
- * cmdName's internal representation.
+ * structure corresponding to "srcPtr"s internal rep. Increments the ref
+ * count of the ResolvedCmdName structure pointed to by the cmdName's
+ * internal representation.
*
*----------------------------------------------------------------------
*/
static void
-DupCmdNameInternalRep(srcPtr, copyPtr)
- Tcl_Obj *srcPtr; /* Object with internal rep to copy. */
- register Tcl_Obj *copyPtr; /* Object with internal rep to set. */
+DupCmdNameInternalRep(
+ Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
+ register Tcl_Obj *copyPtr) /* Object with internal rep to set. */
{
- register ResolvedCmdName *resPtr =
- (ResolvedCmdName *) srcPtr->internalRep.twoPtrValue.ptr1;
+ register ResolvedCmdName *resPtr = (ResolvedCmdName *)
+ srcPtr->internalRep.twoPtrValue.ptr1;
- copyPtr->internalRep.twoPtrValue.ptr1 = (VOID *) resPtr;
+ copyPtr->internalRep.twoPtrValue.ptr1 = (void *) resPtr;
copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
if (resPtr != NULL) {
- resPtr->refCount++;
+ resPtr->refCount++;
}
copyPtr->typePtr = &tclCmdNameType;
}
@@ -3577,22 +4246,21 @@ DupCmdNameInternalRep(srcPtr, copyPtr)
*
* Side effects:
* A pointer to a ResolvedCmdName structure that holds a cached pointer
- * to the command with a name that matches objPtr's string rep is
- * stored as objPtr's internal representation. This ResolvedCmdName
- * pointer will be NULL if no matching command was found. The ref count
- * of the cached Command's structure (if any) is also incremented.
+ * to the command with a name that matches objPtr's string rep is stored
+ * as objPtr's internal representation. This ResolvedCmdName pointer will
+ * be NULL if no matching command was found. The ref count of the cached
+ * Command's structure (if any) is also incremented.
*
*----------------------------------------------------------------------
*/
static int
-SetCmdNameFromAny(interp, objPtr)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- register Tcl_Obj *objPtr; /* The object to convert. */
+SetCmdNameFromAny(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ register Tcl_Obj *objPtr) /* The object to convert. */
{
Interp *iPtr = (Interp *) interp;
char *name;
- Tcl_Command cmd;
register Command *cmdPtr;
Namespace *currNsPtr;
register ResolvedCmdName *resPtr;
@@ -3602,15 +4270,6 @@ SetCmdNameFromAny(interp, objPtr)
}
/*
- * Get "objPtr"s string representation. Make it up-to-date if necessary.
- */
-
- name = objPtr->bytes;
- if (name == NULL) {
- name = Tcl_GetString(objPtr);
- }
-
- /*
* Find the Command structure, if any, that describes the command called
* "name". Build a ResolvedCmdName that holds a cached pointer to this
* Command, and bump the reference count in the referenced Command
@@ -3618,47 +4277,62 @@ SetCmdNameFromAny(interp, objPtr)
* referenced from a CmdName object.
*/
- cmd = Tcl_FindCommand(interp, name, (Tcl_Namespace *) NULL,
- /*flags*/ 0);
- cmdPtr = (Command *) cmd;
- if (cmdPtr != NULL) {
- /*
- * Get the current namespace.
- */
-
- if (iPtr->varFramePtr != NULL) {
- currNsPtr = iPtr->varFramePtr->nsPtr;
- } else {
- currNsPtr = iPtr->globalNsPtr;
- }
-
- cmdPtr->refCount++;
- resPtr = (ResolvedCmdName *) ckalloc(sizeof(ResolvedCmdName));
- resPtr->cmdPtr = cmdPtr;
- resPtr->refNsPtr = currNsPtr;
- resPtr->refNsId = currNsPtr->nsId;
- resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch;
- resPtr->cmdEpoch = cmdPtr->cmdEpoch;
- resPtr->refCount = 1;
- } else {
- resPtr = NULL; /* no command named "name" was found */
- }
+ name = TclGetString(objPtr);
+ cmdPtr = (Command *) Tcl_FindCommand(interp, name, /*ns*/ NULL, /*flags*/ 0);
/*
- * Free the old internalRep before setting the new one. We do this as
- * late as possible to allow the conversion code, in particular
- * GetStringFromObj, to use that old internalRep. If no Command
- * structure was found, leave NULL as the cached value.
+ * Free the old internalRep before setting the new one. Do this after
+ * getting the string rep to allow the conversion code (in particular,
+ * Tcl_GetStringFromObj) to use that old internalRep.
*/
- if ((objPtr->typePtr != NULL)
- && (objPtr->typePtr->freeIntRepProc != NULL)) {
- objPtr->typePtr->freeIntRepProc(objPtr);
+ if (cmdPtr) {
+ cmdPtr->refCount++;
+ resPtr = (ResolvedCmdName *) objPtr->internalRep.otherValuePtr;
+ if ((objPtr->typePtr == &tclCmdNameType)
+ && resPtr && (resPtr->refCount == 1)) {
+ /*
+ * Reuse the old ResolvedCmdName struct instead of freeing it
+ */
+
+ Command *oldCmdPtr = resPtr->cmdPtr;
+ if (--oldCmdPtr->refCount == 0) {
+ TclCleanupCommandMacro(oldCmdPtr);
+ }
+ } else {
+ TclFreeIntRep(objPtr);
+ resPtr = (ResolvedCmdName *) ckalloc(sizeof(ResolvedCmdName));
+ resPtr->refCount = 1;
+ objPtr->internalRep.twoPtrValue.ptr1 = (void *) resPtr;
+ objPtr->internalRep.twoPtrValue.ptr2 = NULL;
+ objPtr->typePtr = &tclCmdNameType;
+ }
+ resPtr->cmdPtr = cmdPtr;
+ resPtr->cmdEpoch = cmdPtr->cmdEpoch;
+ if ((*name++ == ':') && (*name == ':')) {
+ /*
+ * The name is fully qualified: set the referring namespace to
+ * NULL.
+ */
+
+ resPtr->refNsPtr = NULL;
+ } else {
+ /*
+ * Get the current namespace.
+ */
+
+ currNsPtr = iPtr->varFramePtr->nsPtr;
+
+ resPtr->refNsPtr = currNsPtr;
+ resPtr->refNsId = currNsPtr->nsId;
+ resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch;
+ }
+ } else {
+ TclFreeIntRep(objPtr);
+ objPtr->internalRep.twoPtrValue.ptr1 = NULL;
+ objPtr->internalRep.twoPtrValue.ptr2 = NULL;
+ objPtr->typePtr = &tclCmdNameType;
}
-
- objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) resPtr;
- objPtr->internalRep.twoPtrValue.ptr2 = NULL;
- objPtr->typePtr = &tclCmdNameType;
return TCL_OK;
}
@@ -3669,4 +4343,3 @@ SetCmdNameFromAny(interp, objPtr)
* fill-column: 78
* End:
*/
-
diff --git a/generic/tclPanic.c b/generic/tclPanic.c
index 4614edc..600307e 100644
--- a/generic/tclPanic.c
+++ b/generic/tclPanic.c
@@ -1,43 +1,40 @@
-/*
+/*
* tclPanic.c --
*
- * Source code for the "Tcl_Panic" library procedure for Tcl;
- * individual applications will probably call Tcl_SetPanicProc()
- * to set an application-specific panic procedure.
+ * Source code for the "Tcl_Panic" library procedure for Tcl; individual
+ * applications will probably call Tcl_SetPanicProc() to set an
+ * application-specific panic procedure.
*
* Copyright (c) 1988-1993 The Regents of the University of California.
* Copyright (c) 1994 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.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
/*
- * The panicProc variable contains a pointer to an application
- * specific panic procedure.
+ * The panicProc variable contains a pointer to an application specific panic
+ * procedure.
*/
static Tcl_PanicProc *panicProc = NULL;
/*
- * The platformPanicProc variable contains a pointer to a platform
- * specific panic procedure, if any. ( TclpPanic may be NULL via
- * a macro. )
+ * The platformPanicProc variable contains a pointer to a platform specific
+ * panic procedure, if any. (TclpPanic may be NULL via a macro.)
*/
-static Tcl_PanicProc * CONST platformPanicProc = TclpPanic;
-
+static Tcl_PanicProc *CONST platformPanicProc = TclpPanic;
/*
*----------------------------------------------------------------------
*
* Tcl_SetPanicProc --
*
- * Replace the default panic behavior with the specified functiion.
+ * Replace the default panic behavior with the specified function.
*
* Results:
* None.
@@ -49,8 +46,8 @@ static Tcl_PanicProc * CONST platformPanicProc = TclpPanic;
*/
void
-Tcl_SetPanicProc(proc)
- Tcl_PanicProc *proc;
+Tcl_SetPanicProc(
+ Tcl_PanicProc *proc)
{
panicProc = proc;
}
@@ -72,10 +69,10 @@ Tcl_SetPanicProc(proc)
*/
void
-Tcl_PanicVA (format, argList)
- CONST char *format; /* Format string, suitable for passing to
+Tcl_PanicVA(
+ CONST char *format, /* Format string, suitable for passing to
* fprintf. */
- va_list argList; /* Variable argument list. */
+ va_list argList) /* Variable argument list. */
{
char *arg1, *arg2, *arg3, *arg4; /* Additional arguments (variable in
* number) to pass to fprintf. */
@@ -89,7 +86,7 @@ Tcl_PanicVA (format, argList)
arg6 = va_arg(argList, char *);
arg7 = va_arg(argList, char *);
arg8 = va_arg(argList, char *);
-
+
if (panicProc != NULL) {
(void) (*panicProc)(format, arg1, arg2, arg3, arg4,
arg5, arg6, arg7, arg8);
@@ -121,14 +118,23 @@ Tcl_PanicVA (format, argList)
*----------------------------------------------------------------------
*/
- /* VARARGS ARGSUSED */
+ /* ARGSUSED */
void
-Tcl_Panic TCL_VARARGS_DEF(CONST char *,arg1)
+Tcl_Panic(
+ CONST char *format,
+ ...)
{
va_list argList;
- CONST char *format;
- format = TCL_VARARGS_START(CONST char *,arg1,argList);
+ va_start(argList, format);
Tcl_PanicVA(format, argList);
va_end (argList);
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclParse.c b/generic/tclParse.c
index a3f8433..96c2a10 100644
--- a/generic/tclParse.c
+++ b/generic/tclParse.c
@@ -1,61 +1,58 @@
-/*
+/*
* tclParse.c --
*
- * This file contains procedures that parse Tcl scripts. They
- * do so in a general-purpose fashion that can be used for many
- * different purposes, including compilation, direct execution,
- * code analysis, etc.
+ * This file contains functions that parse Tcl scripts. They do so in a
+ * general-purpose fashion that can be used for many different purposes,
+ * including compilation, direct execution, code analysis, etc.
*
* Copyright (c) 1997 Sun Microsystems, Inc.
* Copyright (c) 1998-2000 Ajuba Solutions.
* Contributions from Don Porter, NIST, 2002. (not subject to US copyright)
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
/*
- * The following table provides parsing information about each possible
- * 8-bit character. The table is designed to be referenced with either
- * signed or unsigned characters, so it has 384 entries. The first 128
- * entries correspond to negative character values, the next 256 correspond
- * to positive character values. The last 128 entries are identical to the
- * first 128. The table is always indexed with a 128-byte offset (the 128th
- * entry corresponds to a character value of 0).
- *
- * The macro CHAR_TYPE is used to index into the table and return
- * information about its character argument. The following return
- * values are defined.
- *
- * TYPE_NORMAL - All characters that don't have special significance
- * to the Tcl parser.
- * TYPE_SPACE - The character is a whitespace character other
- * than newline.
- * TYPE_COMMAND_END - Character is newline or semicolon.
- * TYPE_SUBS - Character begins a substitution or has other
- * special meaning in ParseTokens: backslash, dollar
- * sign, or open bracket.
- * TYPE_QUOTE - Character is a double quote.
- * TYPE_CLOSE_PAREN - Character is a right parenthesis.
- * TYPE_CLOSE_BRACK - Character is a right square bracket.
- * TYPE_BRACE - Character is a curly brace (either left or right).
+ * The following table provides parsing information about each possible 8-bit
+ * character. The table is designed to be referenced with either signed or
+ * unsigned characters, so it has 384 entries. The first 128 entries
+ * correspond to negative character values, the next 256 correspond to
+ * positive character values. The last 128 entries are identical to the first
+ * 128. The table is always indexed with a 128-byte offset (the 128th entry
+ * corresponds to a character value of 0).
+ *
+ * The macro CHAR_TYPE is used to index into the table and return information
+ * about its character argument. The following return values are defined.
+ *
+ * TYPE_NORMAL - All characters that don't have special significance to
+ * the Tcl parser.
+ * TYPE_SPACE - The character is a whitespace character other than
+ * newline.
+ * TYPE_COMMAND_END - Character is newline or semicolon.
+ * TYPE_SUBS - Character begins a substitution or has other special
+ * meaning in ParseTokens: backslash, dollar sign, or
+ * open bracket.
+ * TYPE_QUOTE - Character is a double quote.
+ * TYPE_CLOSE_PAREN - Character is a right parenthesis.
+ * TYPE_CLOSE_BRACK - Character is a right square bracket.
+ * TYPE_BRACE - Character is a curly brace (either left or right).
*/
-#define TYPE_NORMAL 0
-#define TYPE_SPACE 0x1
-#define TYPE_COMMAND_END 0x2
-#define TYPE_SUBS 0x4
-#define TYPE_QUOTE 0x8
-#define TYPE_CLOSE_PAREN 0x10
-#define TYPE_CLOSE_BRACK 0x20
-#define TYPE_BRACE 0x40
+#define TYPE_NORMAL 0
+#define TYPE_SPACE 0x1
+#define TYPE_COMMAND_END 0x2
+#define TYPE_SUBS 0x4
+#define TYPE_QUOTE 0x8
+#define TYPE_CLOSE_PAREN 0x10
+#define TYPE_CLOSE_BRACK 0x20
+#define TYPE_BRACE 0x40
#define CHAR_TYPE(c) (charTypeTable+128)[(int)(c)]
-static CONST char charTypeTable[] = {
+static const char charTypeTable[] = {
/*
* Negative character values, from -128 to -1:
*/
@@ -169,96 +166,120 @@ static CONST char charTypeTable[] = {
};
/*
- * Prototypes for local procedures defined in this file:
+ * Prototypes for local functions defined in this file:
*/
-static int CommandComplete _ANSI_ARGS_((CONST char *script,
- int numBytes));
-static int ParseComment _ANSI_ARGS_((CONST char *src, int numBytes,
- Tcl_Parse *parsePtr));
-static int ParseTokens _ANSI_ARGS_((CONST char *src, int numBytes,
- int mask, Tcl_Parse *parsePtr));
+static inline int CommandComplete(const char *script, int numBytes);
+static int ParseComment(const char *src, int numBytes,
+ Tcl_Parse *parsePtr);
+static int ParseTokens(const char *src, int numBytes, int mask,
+ int flags, Tcl_Parse *parsePtr);
+static int ParseWhiteSpace(const char *src, int numBytes,
+ int *incompletePtr, char *typePtr);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclParseInit --
+ *
+ * Initialize the fields of a Tcl_Parse struct.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The Tcl_Parse struct pointed to by parsePtr gets initialized.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+TclParseInit(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting */
+ const char *start, /* Start of string to be parsed. */
+ int numBytes, /* Total number of bytes in string. If < 0,
+ * the script consists of all bytes up to the
+ * first null character. */
+ Tcl_Parse *parsePtr) /* Points to struct to initialize */
+{
+ parsePtr->numWords = 0;
+ parsePtr->tokenPtr = parsePtr->staticTokens;
+ parsePtr->numTokens = 0;
+ parsePtr->tokensAvailable = NUM_STATIC_TOKENS;
+ parsePtr->string = start;
+ parsePtr->end = start + numBytes;
+ parsePtr->term = parsePtr->end;
+ parsePtr->interp = interp;
+ parsePtr->incomplete = 0;
+ parsePtr->errorType = TCL_PARSE_SUCCESS;
+}
+
/*
*----------------------------------------------------------------------
*
* Tcl_ParseCommand --
*
- * Given a string, this procedure parses the first Tcl command
- * in the string and returns information about the structure of
- * the command.
+ * Given a string, this function parses the first Tcl command in the
+ * string and returns information about the structure of the command.
*
* Results:
- * The return value is TCL_OK if the command was parsed
- * successfully and TCL_ERROR otherwise. If an error occurs
- * and interp isn't NULL then an error message is left in
- * its result. On a successful return, parsePtr is filled in
- * with information about the command that was parsed.
+ * The return value is TCL_OK if the command was parsed successfully and
+ * TCL_ERROR otherwise. If an error occurs and interp isn't NULL then an
+ * error message is left in its result. On a successful return, parsePtr
+ * is filled in with information about the command that was parsed.
*
* Side effects:
- * If there is insufficient space in parsePtr to hold all the
- * information about the command, then additional space is
- * malloc-ed. If the procedure returns TCL_OK then the caller must
- * eventually invoke Tcl_FreeParse to release any additional space
- * that was allocated.
+ * If there is insufficient space in parsePtr to hold all the information
+ * about the command, then additional space is malloc-ed. If the function
+ * returns TCL_OK then the caller must eventually invoke Tcl_FreeParse to
+ * release any additional space that was allocated.
*
*----------------------------------------------------------------------
*/
int
-Tcl_ParseCommand(interp, string, numBytes, nested, parsePtr)
- Tcl_Interp *interp; /* Interpreter to use for error reporting;
- * if NULL, then no error message is
- * provided. */
- CONST char *string; /* First character of string containing
- * one or more Tcl commands. */
- register int numBytes; /* Total number of bytes in string. If < 0,
- * the script consists of all bytes up to
- * the first null character. */
- int nested; /* Non-zero means this is a nested command:
- * close bracket should be considered
- * a command terminator. If zero, then close
+Tcl_ParseCommand(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting; if
+ * NULL, then no error message is provided. */
+ const char *start, /* First character of string containing one or
+ * more Tcl commands. */
+ register int numBytes, /* Total number of bytes in string. If < 0,
+ * the script consists of all bytes up to the
+ * first null character. */
+ int nested, /* Non-zero means this is a nested command:
+ * close bracket should be considered a
+ * command terminator. If zero, then close
* bracket has no special meaning. */
- register Tcl_Parse *parsePtr;
- /* Structure to fill in with information
- * about the parsed command; any previous
- * information in the structure is
- * ignored. */
+ register Tcl_Parse *parsePtr)
+ /* Structure to fill in with information about
+ * the parsed command; any previous
+ * information in the structure is ignored. */
{
- register CONST char *src; /* Points to current character
- * in the command. */
+ register const char *src; /* Points to current character in the
+ * command. */
char type; /* Result returned by CHAR_TYPE(*src). */
Tcl_Token *tokenPtr; /* Pointer to token being filled in. */
int wordIndex; /* Index of word token for current word. */
- int terminators; /* CHAR_TYPE bits that indicate the end
- * of a command. */
- CONST char *termPtr; /* Set by Tcl_ParseBraces/QuotedString to
+ int terminators; /* CHAR_TYPE bits that indicate the end of a
+ * command. */
+ const char *termPtr; /* Set by Tcl_ParseBraces/QuotedString to
* point to char after terminating one. */
int scanned;
-
- if ((string == NULL) && (numBytes!=0)) {
+
+ if ((start == NULL) && (numBytes != 0)) {
if (interp != NULL) {
Tcl_SetResult(interp, "can't parse a NULL pointer", TCL_STATIC);
}
return TCL_ERROR;
}
if (numBytes < 0) {
- numBytes = strlen(string);
+ numBytes = strlen(start);
}
+ TclParseInit(interp, start, numBytes, parsePtr);
parsePtr->commentStart = NULL;
parsePtr->commentSize = 0;
parsePtr->commandStart = NULL;
parsePtr->commandSize = 0;
- parsePtr->numWords = 0;
- parsePtr->tokenPtr = parsePtr->staticTokens;
- parsePtr->numTokens = 0;
- parsePtr->tokensAvailable = NUM_STATIC_TOKENS;
- parsePtr->string = string;
- parsePtr->end = string + numBytes;
- parsePtr->term = parsePtr->end;
- parsePtr->interp = interp;
- parsePtr->incomplete = 0;
- parsePtr->errorType = TCL_PARSE_SUCCESS;
if (nested != 0) {
terminators = TYPE_COMMAND_END | TYPE_CLOSE_BRACK;
} else {
@@ -270,8 +291,9 @@ Tcl_ParseCommand(interp, string, numBytes, nested, parsePtr)
* command.
*/
- scanned = ParseComment(string, numBytes, parsePtr);
- src = (string + scanned); numBytes -= scanned;
+ scanned = ParseComment(start, numBytes, parsePtr);
+ src = (start + scanned);
+ numBytes -= scanned;
if (numBytes == 0) {
if (nested) {
parsePtr->incomplete = nested;
@@ -279,19 +301,19 @@ Tcl_ParseCommand(interp, string, numBytes, nested, parsePtr)
}
/*
- * The following loop parses the words of the command, one word
- * in each iteration through the loop.
+ * The following loop parses the words of the command, one word in each
+ * iteration through the loop.
*/
parsePtr->commandStart = src;
while (1) {
+ int expandWord = 0;
+
/*
* Create the token for the word.
*/
- if (parsePtr->numTokens == parsePtr->tokensAvailable) {
- TclExpandTokenArray(parsePtr);
- }
+ TclGrowParseTokenArray(parsePtr, 1);
wordIndex = parsePtr->numTokens;
tokenPtr = &parsePtr->tokenPtr[wordIndex];
tokenPtr->type = TCL_TOKEN_WORD;
@@ -301,8 +323,9 @@ Tcl_ParseCommand(interp, string, numBytes, nested, parsePtr)
* sequence: it should be treated just like white space.
*/
- scanned = TclParseWhiteSpace(src, numBytes, parsePtr, &type);
- src += scanned; numBytes -= scanned;
+ scanned = ParseWhiteSpace(src,numBytes, &parsePtr->incomplete, &type);
+ src += scanned;
+ numBytes -= scanned;
if (numBytes == 0) {
parsePtr->term = src;
break;
@@ -317,60 +340,229 @@ Tcl_ParseCommand(interp, string, numBytes, nested, parsePtr)
parsePtr->numWords++;
/*
- * At this point the word can have one of three forms: something
- * enclosed in quotes, something enclosed in braces, or an
- * unquoted word (anything else).
+ * At this point the word can have one of four forms: something
+ * enclosed in quotes, something enclosed in braces, and expanding
+ * word, or an unquoted word (anything else).
*/
+ parseWord:
if (*src == '"') {
- if (Tcl_ParseQuotedString(interp, src, numBytes,
- parsePtr, 1, &termPtr) != TCL_OK) {
+ if (Tcl_ParseQuotedString(interp, src, numBytes, parsePtr, 1,
+ &termPtr) != TCL_OK) {
goto error;
}
- src = termPtr; numBytes = parsePtr->end - src;
+ src = termPtr;
+ numBytes = parsePtr->end - src;
} else if (*src == '{') {
- if (Tcl_ParseBraces(interp, src, numBytes,
- parsePtr, 1, &termPtr) != TCL_OK) {
+ int expIdx = wordIndex + 1;
+ Tcl_Token *expPtr;
+
+ if (Tcl_ParseBraces(interp, src, numBytes, parsePtr, 1,
+ &termPtr) != TCL_OK) {
goto error;
}
- src = termPtr; numBytes = parsePtr->end - src;
+ src = termPtr;
+ numBytes = parsePtr->end - src;
+
+ /*
+ * Check whether the braces contained the word expansion prefix
+ * {*}
+ */
+
+ expPtr = &parsePtr->tokenPtr[expIdx];
+ if ((0 == expandWord)
+ /* Haven't seen prefix already */
+ && (1 == parsePtr->numTokens - expIdx)
+ /* Only one token */
+ && (((1 == (size_t) expPtr->size)
+ /* Same length as prefix */
+ && (expPtr->start[0] == '*')))
+ /* Is the prefix */
+ && (numBytes > 0) && (0 == ParseWhiteSpace(termPtr,
+ numBytes, &parsePtr->incomplete, &type))
+ && (type != TYPE_COMMAND_END)
+ /* Non-whitespace follows */) {
+ expandWord = 1;
+ parsePtr->numTokens--;
+ goto parseWord;
+ }
} else {
/*
- * This is an unquoted word. Call ParseTokens and let it do
- * all of the work.
+ * This is an unquoted word. Call ParseTokens and let it do all of
+ * the work.
*/
if (ParseTokens(src, numBytes, TYPE_SPACE|terminators,
- parsePtr) != TCL_OK) {
+ TCL_SUBST_ALL, parsePtr) != TCL_OK) {
goto error;
}
- src = parsePtr->term; numBytes = parsePtr->end - src;
+ src = parsePtr->term;
+ numBytes = parsePtr->end - src;
}
/*
- * Finish filling in the token for the word and check for the
- * special case of a word consisting of a single range of
- * literal text.
+ * Finish filling in the token for the word and check for the special
+ * case of a word consisting of a single range of literal text.
*/
tokenPtr = &parsePtr->tokenPtr[wordIndex];
tokenPtr->size = src - tokenPtr->start;
tokenPtr->numComponents = parsePtr->numTokens - (wordIndex + 1);
- if ((tokenPtr->numComponents == 1)
+ if (expandWord) {
+ int i, isLiteral = 1;
+
+ /*
+ * When a command includes a word that is an expanded literal; for
+ * example, {*}{1 2 3}, the parser performs that expansion
+ * immediately, generating several TCL_TOKEN_SIMPLE_WORDs instead
+ * of a single TCL_TOKEN_EXPAND_WORD that the Tcl_ParseCommand()
+ * caller might have to expand. This notably makes it simpler for
+ * those callers that wish to track line endings, such as those
+ * that implement key parts of TIP 280.
+ *
+ * First check whether the thing to be expanded is a literal,
+ * in the sense of being composed entirely of TCL_TOKEN_TEXT
+ * tokens.
+ */
+
+ for (i = 1; i <= tokenPtr->numComponents; i++) {
+ if (tokenPtr[i].type != TCL_TOKEN_TEXT) {
+ isLiteral = 0;
+ break;
+ }
+ }
+
+ if (isLiteral) {
+ int elemCount = 0, code = TCL_OK, literal = 1;
+ const char *nextElem, *listEnd, *elemStart;
+
+ /*
+ * The word to be expanded is a literal, so determine the
+ * boundaries of the literal string to be treated as a list
+ * and expanded. That literal string starts at
+ * tokenPtr[1].start, and includes all bytes up to, but not
+ * including (tokenPtr[tokenPtr->numComponents].start +
+ * tokenPtr[tokenPtr->numComponents].size)
+ */
+
+ listEnd = (tokenPtr[tokenPtr->numComponents].start +
+ tokenPtr[tokenPtr->numComponents].size);
+ nextElem = tokenPtr[1].start;
+
+ /*
+ * Step through the literal string, parsing and counting list
+ * elements.
+ */
+
+ while (nextElem < listEnd) {
+ int size;
+
+ code = TclFindElement(NULL, nextElem, listEnd - nextElem,
+ &elemStart, &nextElem, &size, &literal);
+ if ((code != TCL_OK) || !literal) {
+ break;
+ }
+ if (elemStart < listEnd) {
+ elemCount++;
+ }
+ }
+
+ if ((code != TCL_OK) || !literal) {
+ /*
+ * Some list element could not be parsed, or is not
+ * present as a literal substring of the script. The
+ * compiler cannot handle list elements that get generated
+ * by a call to TclCopyAndCollapse(). Defer the
+ * handling of this to compile/eval time, where code is
+ * already in place to report the "attempt to expand a
+ * non-list" error or expand lists that require
+ * substitution.
+ */
+
+ tokenPtr->type = TCL_TOKEN_EXPAND_WORD;
+ } else if (elemCount == 0) {
+ /*
+ * We are expanding a literal empty list. This means that
+ * the expanding word completely disappears, leaving no
+ * word generated this pass through the loop. Adjust
+ * accounting appropriately.
+ */
+
+ parsePtr->numWords--;
+ parsePtr->numTokens = wordIndex;
+ } else {
+ /*
+ * Recalculate the number of Tcl_Tokens needed to store
+ * tokens representing the expanded list.
+ */
+
+ CONST char *listStart;
+ int growthNeeded = wordIndex + 2*elemCount
+ - parsePtr->numTokens;
+ parsePtr->numWords += elemCount - 1;
+ if (growthNeeded > 0) {
+ TclGrowParseTokenArray(parsePtr, growthNeeded);
+ tokenPtr = &parsePtr->tokenPtr[wordIndex];
+ }
+ parsePtr->numTokens = wordIndex + 2*elemCount;
+
+ /*
+ * Generate a TCL_TOKEN_SIMPLE_WORD token sequence for
+ * each element of the literal list we are expanding in
+ * place. Take care with the start and size fields of each
+ * token so they point to the right literal characters in
+ * the original script to represent the right expanded
+ * word value.
+ */
+
+ listStart = nextElem = tokenPtr[1].start;
+ while (nextElem < listEnd) {
+ int quoted;
+
+ tokenPtr->type = TCL_TOKEN_SIMPLE_WORD;
+ tokenPtr->numComponents = 1;
+
+ tokenPtr++;
+ tokenPtr->type = TCL_TOKEN_TEXT;
+ tokenPtr->numComponents = 0;
+ TclFindElement(NULL, nextElem, listEnd - nextElem,
+ &(tokenPtr->start), &nextElem,
+ &(tokenPtr->size), NULL);
+
+ quoted = (tokenPtr->start[-1] == '{'
+ || tokenPtr->start[-1] == '"')
+ && tokenPtr->start > listStart;
+ tokenPtr[-1].start = tokenPtr->start - quoted;
+ tokenPtr[-1].size = tokenPtr->start + tokenPtr->size
+ - tokenPtr[-1].start + quoted;
+
+ tokenPtr++;
+ }
+ }
+ } else {
+ /*
+ * The word to be expanded is not a literal, so defer
+ * expansion to compile/eval time by marking with a
+ * TCL_TOKEN_EXPAND_WORD token.
+ */
+
+ tokenPtr->type = TCL_TOKEN_EXPAND_WORD;
+ }
+ } else if ((tokenPtr->numComponents == 1)
&& (tokenPtr[1].type == TCL_TOKEN_TEXT)) {
tokenPtr->type = TCL_TOKEN_SIMPLE_WORD;
}
/*
- * Do two additional checks: (a) make sure we're really at the
- * end of a word (there might have been garbage left after a
- * quoted or braced word), and (b) check for the end of the
- * command.
+ * Do two additional checks: (a) make sure we're really at the end of
+ * a word (there might have been garbage left after a quoted or braced
+ * word), and (b) check for the end of the command.
*/
- scanned = TclParseWhiteSpace(src, numBytes, parsePtr, &type);
+ scanned = ParseWhiteSpace(src,numBytes, &parsePtr->incomplete, &type);
if (scanned) {
- src += scanned; numBytes -= scanned;
+ src += scanned;
+ numBytes -= scanned;
continue;
}
@@ -380,10 +572,10 @@ Tcl_ParseCommand(interp, string, numBytes, nested, parsePtr)
}
if ((type & terminators) != 0) {
parsePtr->term = src;
- src++;
+ src++;
break;
}
- if (src[-1] == '"') {
+ if (src[-1] == '"') {
if (interp != NULL) {
Tcl_SetResult(interp, "extra characters after close-quote",
TCL_STATIC);
@@ -403,51 +595,72 @@ Tcl_ParseCommand(interp, string, numBytes, nested, parsePtr)
parsePtr->commandSize = src - parsePtr->commandStart;
return TCL_OK;
- error:
+ error:
Tcl_FreeParse(parsePtr);
- if (parsePtr->commandStart == NULL) {
- parsePtr->commandStart = string;
- }
parsePtr->commandSize = parsePtr->end - parsePtr->commandStart;
return TCL_ERROR;
}
-
+
/*
*----------------------------------------------------------------------
*
- * TclParseWhiteSpace --
+ * TclIsSpaceProc --
*
- * Scans up to numBytes bytes starting at src, consuming white
- * space as defined by Tcl's parsing rules.
+ * Report whether byte is in the set of whitespace characters used by
+ * Tcl to separate words in scripts or elements in lists.
*
* Results:
- * Returns the number of bytes recognized as white space. Records
- * at parsePtr, information about the parse. Records at typePtr
- * the character type of the non-whitespace character that terminated
- * the scan.
+ * Returns 1, if byte is in the set, 0 otherwise.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
+
int
-TclParseWhiteSpace(src, numBytes, parsePtr, typePtr)
- CONST char *src; /* First character to parse. */
- register int numBytes; /* Max number of bytes to scan. */
- Tcl_Parse *parsePtr; /* Information about parse in progress.
- * Updated if parsing indicates
- * an incomplete command. */
- char *typePtr; /* Points to location to store character
- * type of character that ends run
- * of whitespace */
+TclIsSpaceProc(
+ char byte)
+{
+ return CHAR_TYPE(byte) & (TYPE_SPACE) || byte == '\n';
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ParseWhiteSpace --
+ *
+ * Scans up to numBytes bytes starting at src, consuming white space
+ * between words as defined by Tcl's parsing rules.
+ *
+ * Results:
+ * Returns the number of bytes recognized as white space. Records at
+ * parsePtr, information about the parse. Records at typePtr the
+ * character type of the non-whitespace character that terminated the
+ * scan.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ParseWhiteSpace(
+ const char *src, /* First character to parse. */
+ register int numBytes, /* Max number of bytes to scan. */
+ int *incompletePtr, /* Set this boolean memory to true if parsing
+ * indicates an incomplete command. */
+ char *typePtr) /* Points to location to store character type
+ * of character that ends run of whitespace */
{
register char type = TYPE_NORMAL;
- register CONST char *p = src;
+ register const char *p = src;
while (1) {
while (numBytes && ((type = CHAR_TYPE(*p)) & TYPE_SPACE)) {
- numBytes--; p++;
+ numBytes--;
+ p++;
}
if (numBytes && (type & TYPE_SUBS)) {
if (*p != '\\') {
@@ -461,7 +674,7 @@ TclParseWhiteSpace(src, numBytes, parsePtr, typePtr)
}
p+=2;
if (--numBytes == 0) {
- parsePtr->incomplete = 1;
+ *incompletePtr = 1;
break;
}
continue;
@@ -475,42 +688,74 @@ TclParseWhiteSpace(src, numBytes, parsePtr, typePtr)
/*
*----------------------------------------------------------------------
*
+ * TclParseAllWhiteSpace --
+ *
+ * Scans up to numBytes bytes starting at src, consuming all white space
+ * including the command-terminating newline characters.
+ *
+ * Results:
+ * Returns the number of bytes recognized as white space.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclParseAllWhiteSpace(
+ const char *src, /* First character to parse. */
+ int numBytes) /* Max number of byes to scan */
+{
+ int dummy;
+ char type;
+ const char *p = src;
+
+ do {
+ int scanned = ParseWhiteSpace(p, numBytes, &dummy, &type);
+
+ p += scanned;
+ numBytes -= scanned;
+ } while (numBytes && (*p == '\n') && (p++, --numBytes));
+ return (p-src);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TclParseHex --
*
- * Scans a hexadecimal number as a Tcl_UniChar value.
- * (e.g., for parsing \x and \u escape sequences).
- * At most numBytes bytes are scanned.
+ * Scans a hexadecimal number as a Tcl_UniChar value (e.g., for parsing
+ * \x and \u escape sequences). At most numBytes bytes are scanned.
*
* Results:
- * The numeric value is stored in *resultPtr.
- * Returns the number of bytes consumed.
+ * The numeric value is stored in *resultPtr. Returns the number of bytes
+ * consumed.
*
* Notes:
- * Relies on the following properties of the ASCII
- * character set, with which UTF-8 is compatible:
+ * Relies on the following properties of the ASCII character set, with
+ * which UTF-8 is compatible:
*
- * The digits '0' .. '9' and the letters 'A' .. 'Z' and 'a' .. 'z'
- * occupy consecutive code points, and '0' < 'A' < 'a'.
+ * The digits '0' .. '9' and the letters 'A' .. 'Z' and 'a' .. 'z' occupy
+ * consecutive code points, and '0' < 'A' < 'a'.
*
*----------------------------------------------------------------------
*/
+
int
-TclParseHex(src, numBytes, resultPtr)
- CONST char *src; /* First character to parse. */
- int numBytes; /* Max number of byes to scan */
- Tcl_UniChar *resultPtr; /* Points to storage provided by
- * caller where the Tcl_UniChar
- * resulting from the conversion is
- * to be written. */
+TclParseHex(
+ const char *src, /* First character to parse. */
+ int numBytes, /* Max number of byes to scan */
+ Tcl_UniChar *resultPtr) /* Points to storage provided by caller where
+ * the Tcl_UniChar resulting from the
+ * conversion is to be written. */
{
Tcl_UniChar result = 0;
- register CONST char *p = src;
+ register const char *p = src;
while (numBytes--) {
unsigned char digit = UCHAR(*p);
- if (!isxdigit(digit))
+ if (!isxdigit(digit)) {
break;
+ }
++p;
result <<= 4;
@@ -533,35 +778,35 @@ TclParseHex(src, numBytes, resultPtr)
*
* TclParseBackslash --
*
- * Scans up to numBytes bytes starting at src, consuming a
- * backslash sequence as defined by Tcl's parsing rules.
+ * Scans up to numBytes bytes starting at src, consuming a backslash
+ * sequence as defined by Tcl's parsing rules.
*
* Results:
* Records at readPtr the number of bytes making up the backslash
- * sequence. Records at dst the UTF-8 encoded equivalent of
- * that backslash sequence. Returns the number of bytes written
- * to dst, at most TCL_UTF_MAX. Either readPtr or dst may be
- * NULL, if the results are not needed, but the return value is
- * the same either way.
+ * sequence. Records at dst the UTF-8 encoded equivalent of that
+ * backslash sequence. Returns the number of bytes written to dst, at
+ * most TCL_UTF_MAX. Either readPtr or dst may be NULL, if the results
+ * are not needed, but the return value is the same either way.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
+
int
-TclParseBackslash(src, numBytes, readPtr, dst)
- CONST char * src; /* Points to the backslash character of a
- * a backslash sequence */
- int numBytes; /* Max number of bytes to scan */
- int *readPtr; /* NULL, or points to storage where the
- * number of bytes scanned should be written. */
- char *dst; /* NULL, or points to buffer where the UTF-8
- * encoding of the backslash sequence is to be
- * written. At most TCL_UTF_MAX bytes will be
- * written there. */
+TclParseBackslash(
+ const char *src, /* Points to the backslash character of a a
+ * backslash sequence. */
+ int numBytes, /* Max number of bytes to scan. */
+ int *readPtr, /* NULL, or points to storage where the number
+ * of bytes scanned should be written. */
+ char *dst) /* NULL, or points to buffer where the UTF-8
+ * encoding of the backslash sequence is to be
+ * written. At most TCL_UTF_MAX bytes will be
+ * written there. */
{
- register CONST char *p = src+1;
+ register const char *p = src+1;
Tcl_UniChar result;
int count;
char buf[TCL_UTF_MAX];
@@ -574,11 +819,14 @@ TclParseBackslash(src, numBytes, readPtr, dst)
}
if (dst == NULL) {
- dst = buf;
+ dst = buf;
}
if (numBytes == 1) {
- /* Can only scan the backslash. Return it. */
+ /*
+ * Can only scan the backslash, so return it.
+ */
+
result = '\\';
count = 1;
goto done;
@@ -586,105 +834,117 @@ TclParseBackslash(src, numBytes, readPtr, dst)
count = 2;
switch (*p) {
- /*
- * Note: in the conversions below, use absolute values (e.g.,
- * 0xa) rather than symbolic values (e.g. \n) that get converted
- * by the compiler. It's possible that compilers on some
- * platforms will do the symbolic conversions differently, which
- * could result in non-portable Tcl scripts.
- */
-
- case 'a':
- result = 0x7;
- break;
- case 'b':
- result = 0x8;
- break;
- case 'f':
- result = 0xc;
- break;
- case 'n':
- result = 0xa;
- break;
- case 'r':
- result = 0xd;
- break;
- case 't':
- result = 0x9;
- break;
- case 'v':
- result = 0xb;
- break;
- case 'x':
- count += TclParseHex(p+1, numBytes-2, &result);
- if (count == 2) {
- /* No hexadigits -> This is just "x". */
- result = 'x';
- } else {
- /* Keep only the last byte (2 hex digits) */
- result = (unsigned char) result;
- }
- break;
- case 'u':
- count += TclParseHex(p+1, (numBytes > 5) ? 4 : numBytes-2, &result);
- if (count == 2) {
- /* No hexadigits -> This is just "u". */
- result = 'u';
+ /*
+ * Note: in the conversions below, use absolute values (e.g., 0xa)
+ * rather than symbolic values (e.g. \n) that get converted by the
+ * compiler. It's possible that compilers on some platforms will do
+ * the symbolic conversions differently, which could result in
+ * non-portable Tcl scripts.
+ */
+
+ case 'a':
+ result = 0x7;
+ break;
+ case 'b':
+ result = 0x8;
+ break;
+ case 'f':
+ result = 0xc;
+ break;
+ case 'n':
+ result = 0xa;
+ break;
+ case 'r':
+ result = 0xd;
+ break;
+ case 't':
+ result = 0x9;
+ break;
+ case 'v':
+ result = 0xb;
+ break;
+ case 'x':
+ count += TclParseHex(p+1, numBytes-2, &result);
+ if (count == 2) {
+ /*
+ * No hexadigits -> This is just "x".
+ */
+
+ result = 'x';
+ } else {
+ /*
+ * Keep only the last byte (2 hex digits).
+ */
+ result = (unsigned char) result;
+ }
+ break;
+ case 'u':
+ count += TclParseHex(p+1, (numBytes > 5) ? 4 : numBytes-2, &result);
+ if (count == 2) {
+ /*
+ * No hexadigits -> This is just "u".
+ */
+ result = 'u';
+ }
+ break;
+ case '\n':
+ count--;
+ do {
+ p++;
+ count++;
+ } while ((count < numBytes) && ((*p == ' ') || (*p == '\t')));
+ result = ' ';
+ break;
+ case 0:
+ result = '\\';
+ count = 1;
+ break;
+ default:
+ /*
+ * Check for an octal number \oo?o?
+ */
+
+ if (isdigit(UCHAR(*p)) && (UCHAR(*p) < '8')) { /* INTL: digit */
+ result = (unsigned char)(*p - '0');
+ p++;
+ if ((numBytes == 2) || !isdigit(UCHAR(*p)) /* INTL: digit */
+ || (UCHAR(*p) >= '8')) {
+ break;
}
- break;
- case '\n':
- count--;
- do {
- p++; count++;
- } while ((count < numBytes) && ((*p == ' ') || (*p == '\t')));
- result = ' ';
- break;
- case 0:
- result = '\\';
- count = 1;
- break;
- default:
- /*
- * Check for an octal number \oo?o?
- */
- if (isdigit(UCHAR(*p)) && (UCHAR(*p) < '8')) { /* INTL: digit */
- result = (unsigned char)(*p - '0');
- p++;
- if ((numBytes == 2) || !isdigit(UCHAR(*p)) /* INTL: digit */
- || (UCHAR(*p) >= '8')) {
- break;
- }
- count = 3;
- result = (unsigned char)((result << 3) + (*p - '0'));
- p++;
- if ((numBytes == 3) || !isdigit(UCHAR(*p)) /* INTL: digit */
- || (UCHAR(*p) >= '8')) {
- break;
- }
- count = 4;
- result = (unsigned char)((result << 3) + (*p - '0'));
- break;
- }
- /*
- * We have to convert here in case the user has put a
- * backslash in front of a multi-byte utf-8 character.
- * While this means nothing special, we shouldn't break up
- * a correct utf-8 character. [Bug #217987] test subst-3.2
- */
- if (Tcl_UtfCharComplete(p, numBytes - 1)) {
- count = Tcl_UtfToUniChar(p, &result) + 1; /* +1 for '\' */
- } else {
- char utfBytes[TCL_UTF_MAX];
- memcpy(utfBytes, p, (size_t) (numBytes - 1));
- utfBytes[numBytes - 1] = '\0';
- count = Tcl_UtfToUniChar(utfBytes, &result) + 1;
+ count = 3;
+ result = (unsigned char)((result << 3) + (*p - '0'));
+ p++;
+ if ((numBytes == 3) || !isdigit(UCHAR(*p)) /* INTL: digit */
+ || (UCHAR(*p) >= '8')) {
+ break;
}
- break;
+ count = 4;
+ result = (unsigned char)((result << 3) + (*p - '0'));
+ break;
+ }
+
+ /*
+ * We have to convert here in case the user has put a backslash in
+ * front of a multi-byte utf-8 character. While this means nothing
+ * special, we shouldn't break up a correct utf-8 character. [Bug
+ * #217987] test subst-3.2
+ */
+
+ if (Tcl_UtfCharComplete(p, numBytes - 1)) {
+ count = Tcl_UtfToUniChar(p, &result) + 1; /* +1 for '\' */
+ } else {
+ char utfBytes[TCL_UTF_MAX];
+
+ memcpy(utfBytes, p, (size_t) (numBytes - 1));
+ utfBytes[numBytes - 1] = '\0';
+ count = Tcl_UtfToUniChar(utfBytes, &result) + 1;
+ }
+ break;
}
- done:
+ done:
if (readPtr != NULL) {
- *readPtr = count;
+ *readPtr = count;
}
return Tcl_UniCharToUtf((int) result, dst);
}
@@ -694,57 +954,69 @@ TclParseBackslash(src, numBytes, readPtr, dst)
*
* ParseComment --
*
- * Scans up to numBytes bytes starting at src, consuming a
- * Tcl comment as defined by Tcl's parsing rules.
+ * Scans up to numBytes bytes starting at src, consuming a Tcl comment as
+ * defined by Tcl's parsing rules.
*
* Results:
- * Records in parsePtr information about the parse. Returns the
- * number of bytes consumed.
+ * Records in parsePtr information about the parse. Returns the number of
+ * bytes consumed.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
+
static int
-ParseComment(src, numBytes, parsePtr)
- CONST char *src; /* First character to parse. */
- register int numBytes; /* Max number of bytes to scan. */
- Tcl_Parse *parsePtr; /* Information about parse in progress.
- * Updated if parsing indicates
- * an incomplete command. */
+ParseComment(
+ const char *src, /* First character to parse. */
+ register int numBytes, /* Max number of bytes to scan. */
+ Tcl_Parse *parsePtr) /* Information about parse in progress.
+ * Updated if parsing indicates an incomplete
+ * command. */
{
- register CONST char *p = src;
+ register const char *p = src;
+
while (numBytes) {
char type;
int scanned;
+
do {
- scanned = TclParseWhiteSpace(p, numBytes, parsePtr, &type);
- p += scanned; numBytes -= scanned;
+ scanned = ParseWhiteSpace(p, numBytes,
+ &parsePtr->incomplete, &type);
+ p += scanned;
+ numBytes -= scanned;
} while (numBytes && (*p == '\n') && (p++,numBytes--));
+
if ((numBytes == 0) || (*p != '#')) {
break;
}
if (parsePtr->commentStart == NULL) {
parsePtr->commentStart = p;
}
+
while (numBytes) {
if (*p == '\\') {
- scanned = TclParseWhiteSpace(p, numBytes, parsePtr, &type);
+ scanned = ParseWhiteSpace(p, numBytes, &parsePtr->incomplete,
+ &type);
if (scanned) {
- p += scanned; numBytes -= scanned;
+ p += scanned;
+ numBytes -= scanned;
} else {
/*
- * General backslash substitution in comments isn't
- * part of the formal spec, but test parse-15.47
- * and history indicate that it has been the de facto
- * rule. Don't change it now.
+ * General backslash substitution in comments isn't part
+ * of the formal spec, but test parse-15.47 and history
+ * indicate that it has been the de facto rule. Don't
+ * change it now.
*/
+
TclParseBackslash(p, numBytes, &scanned, NULL);
- p += scanned; numBytes -= scanned;
+ p += scanned;
+ numBytes -= scanned;
}
} else {
- p++; numBytes--;
+ p++;
+ numBytes--;
if (p[-1] == '\n') {
break;
}
@@ -754,27 +1026,25 @@ ParseComment(src, numBytes, parsePtr)
}
return (p - src);
}
-
+
/*
*----------------------------------------------------------------------
*
* ParseTokens --
*
- * This procedure forms the heart of the Tcl parser. It parses one
- * or more tokens from a string, up to a termination point
- * specified by the caller. This procedure is used to parse
- * unquoted command words (those not in quotes or braces), words in
- * quotes, and array indices for variables. No more than numBytes
- * bytes will be scanned.
+ * This function forms the heart of the Tcl parser. It parses one or more
+ * tokens from a string, up to a termination point specified by the
+ * caller. This function is used to parse unquoted command words (those
+ * not in quotes or braces), words in quotes, and array indices for
+ * variables. No more than numBytes bytes will be scanned.
*
* Results:
- * Tokens are added to parsePtr and parsePtr->term is filled in
- * with the address of the character that terminated the parse (the
- * first one whose CHAR_TYPE matched mask or the character at
- * parsePtr->end). The return value is TCL_OK if the parse
- * completed successfully and TCL_ERROR otherwise. If a parse
- * error occurs and parsePtr->interp isn't NULL, then an error
- * message is left in the interpreter's result.
+ * Tokens are added to parsePtr and parsePtr->term is filled in with the
+ * address of the character that terminated the parse (the first one
+ * whose CHAR_TYPE matched mask or the character at parsePtr->end). The
+ * return value is TCL_OK if the parse completed successfully and
+ * TCL_ERROR otherwise. If a parse error occurs and parsePtr->interp is
+ * not NULL, then an error message is left in the interpreter's result.
*
* Side effects:
* None.
@@ -783,45 +1053,49 @@ ParseComment(src, numBytes, parsePtr)
*/
static int
-ParseTokens(src, numBytes, mask, parsePtr)
- register CONST char *src; /* First character to parse. */
- register int numBytes; /* Max number of bytes to scan. */
- int mask; /* Specifies when to stop parsing. The
- * parse stops at the first unquoted
- * character whose CHAR_TYPE contains
- * any of the bits in mask. */
- Tcl_Parse *parsePtr; /* Information about parse in progress.
+ParseTokens(
+ register const char *src, /* First character to parse. */
+ register int numBytes, /* Max number of bytes to scan. */
+ int mask, /* Specifies when to stop parsing. The parse
+ * stops at the first unquoted character whose
+ * CHAR_TYPE contains any of the bits in
+ * mask. */
+ int flags, /* OR-ed bits indicating what substitutions to
+ * perform: TCL_SUBST_COMMANDS,
+ * TCL_SUBST_VARIABLES, and
+ * TCL_SUBST_BACKSLASHES */
+ Tcl_Parse *parsePtr) /* Information about parse in progress.
* Updated with additional tokens and
* termination information. */
{
- char type;
- int originalTokens, varToken;
+ char type;
+ int originalTokens;
+ int noSubstCmds = !(flags & TCL_SUBST_COMMANDS);
+ int noSubstVars = !(flags & TCL_SUBST_VARIABLES);
+ int noSubstBS = !(flags & TCL_SUBST_BACKSLASHES);
Tcl_Token *tokenPtr;
- Tcl_Parse nested;
/*
- * Each iteration through the following loop adds one token of
- * type TCL_TOKEN_TEXT, TCL_TOKEN_BS, TCL_TOKEN_COMMAND, or
- * TCL_TOKEN_VARIABLE to parsePtr. For TCL_TOKEN_VARIABLE tokens,
- * additional tokens are added for the parsed variable name.
+ * Each iteration through the following loop adds one token of type
+ * TCL_TOKEN_TEXT, TCL_TOKEN_BS, TCL_TOKEN_COMMAND, or TCL_TOKEN_VARIABLE
+ * to parsePtr. For TCL_TOKEN_VARIABLE tokens, additional tokens are added
+ * for the parsed variable name.
*/
originalTokens = parsePtr->numTokens;
while (numBytes && !((type = CHAR_TYPE(*src)) & mask)) {
- if (parsePtr->numTokens == parsePtr->tokensAvailable) {
- TclExpandTokenArray(parsePtr);
- }
+ TclGrowParseTokenArray(parsePtr, 1);
tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
tokenPtr->start = src;
tokenPtr->numComponents = 0;
if ((type & TYPE_SUBS) == 0) {
/*
- * This is a simple range of characters. Scan to find the end
- * of the range.
+ * This is a simple range of characters. Scan to find the end of
+ * the range.
*/
- while ((++src, --numBytes)
+ while ((++src, --numBytes)
&& !(CHAR_TYPE(*src) & (mask | TYPE_SUBS))) {
/* empty loop */
}
@@ -829,81 +1103,116 @@ ParseTokens(src, numBytes, mask, parsePtr)
tokenPtr->size = src - tokenPtr->start;
parsePtr->numTokens++;
} else if (*src == '$') {
+ int varToken;
+
+ if (noSubstVars) {
+ tokenPtr->type = TCL_TOKEN_TEXT;
+ tokenPtr->size = 1;
+ parsePtr->numTokens++;
+ src++;
+ numBytes--;
+ continue;
+ }
+
/*
- * This is a variable reference. Call Tcl_ParseVarName to do
- * all the dirty work of parsing the name.
+ * This is a variable reference. Call Tcl_ParseVarName to do all
+ * the dirty work of parsing the name.
*/
varToken = parsePtr->numTokens;
- if (Tcl_ParseVarName(parsePtr->interp, src, numBytes,
- parsePtr, 1) != TCL_OK) {
+ if (Tcl_ParseVarName(parsePtr->interp, src, numBytes, parsePtr,
+ 1) != TCL_OK) {
return TCL_ERROR;
}
src += parsePtr->tokenPtr[varToken].size;
numBytes -= parsePtr->tokenPtr[varToken].size;
} else if (*src == '[') {
+ Tcl_Parse *nestedPtr;
+
+ if (noSubstCmds) {
+ tokenPtr->type = TCL_TOKEN_TEXT;
+ tokenPtr->size = 1;
+ parsePtr->numTokens++;
+ src++;
+ numBytes--;
+ continue;
+ }
+
/*
- * Command substitution. Call Tcl_ParseCommand recursively
- * (and repeatedly) to parse the nested command(s), then
- * throw away the parse information.
+ * Command substitution. Call Tcl_ParseCommand recursively (and
+ * repeatedly) to parse the nested command(s), then throw away the
+ * parse information.
*/
- src++; numBytes--;
+ src++;
+ numBytes--;
+ nestedPtr = (Tcl_Parse *)
+ TclStackAlloc(parsePtr->interp, sizeof(Tcl_Parse));
while (1) {
- if (Tcl_ParseCommand(parsePtr->interp, src,
- numBytes, 1, &nested) != TCL_OK) {
- parsePtr->errorType = nested.errorType;
- parsePtr->term = nested.term;
- parsePtr->incomplete = nested.incomplete;
+ if (Tcl_ParseCommand(parsePtr->interp, src, numBytes, 1,
+ nestedPtr) != TCL_OK) {
+ parsePtr->errorType = nestedPtr->errorType;
+ parsePtr->term = nestedPtr->term;
+ parsePtr->incomplete = nestedPtr->incomplete;
+ TclStackFree(parsePtr->interp, nestedPtr);
return TCL_ERROR;
}
- src = nested.commandStart + nested.commandSize;
+ src = nestedPtr->commandStart + nestedPtr->commandSize;
numBytes = parsePtr->end - src;
-
- /*
- * This is equivalent to Tcl_FreeParse(&nested), but
- * presumably inlined here for sake of runtime optimization
- */
-
- if (nested.tokenPtr != nested.staticTokens) {
- ckfree((char *) nested.tokenPtr);
- }
+ Tcl_FreeParse(nestedPtr);
/*
* Check for the closing ']' that ends the command
- * substitution. It must have been the last character of
- * the parsed command.
+ * substitution. It must have been the last character of the
+ * parsed command.
*/
- if ((nested.term < parsePtr->end) && (*nested.term == ']')
- && !nested.incomplete) {
+ if ((nestedPtr->term < parsePtr->end)
+ && (*(nestedPtr->term) == ']')
+ && !(nestedPtr->incomplete)) {
break;
}
if (numBytes == 0) {
if (parsePtr->interp != NULL) {
Tcl_SetResult(parsePtr->interp,
- "missing close-bracket", TCL_STATIC);
+ "missing close-bracket", TCL_STATIC);
}
parsePtr->errorType = TCL_PARSE_MISSING_BRACKET;
parsePtr->term = tokenPtr->start;
parsePtr->incomplete = 1;
+ TclStackFree(parsePtr->interp, nestedPtr);
return TCL_ERROR;
}
}
+ TclStackFree(parsePtr->interp, nestedPtr);
tokenPtr->type = TCL_TOKEN_COMMAND;
tokenPtr->size = src - tokenPtr->start;
parsePtr->numTokens++;
} else if (*src == '\\') {
+ if (noSubstBS) {
+ tokenPtr->type = TCL_TOKEN_TEXT;
+ tokenPtr->size = 1;
+ parsePtr->numTokens++;
+ src++;
+ numBytes--;
+ continue;
+ }
+
/*
* Backslash substitution.
*/
+
TclParseBackslash(src, numBytes, &tokenPtr->size, NULL);
if (tokenPtr->size == 1) {
- /* Just a backslash, due to end of string */
+ /*
+ * Just a backslash, due to end of string.
+ */
+
tokenPtr->type = TCL_TOKEN_TEXT;
parsePtr->numTokens++;
- src++; numBytes--;
+ src++;
+ numBytes--;
continue;
}
@@ -913,9 +1222,9 @@ ParseTokens(src, numBytes, mask, parsePtr)
}
/*
- * Note: backslash-newline is special in that it is
- * treated the same as a space character would be. This
- * means that it could terminate the token.
+ * Note: backslash-newline is special in that it is treated
+ * the same as a space character would be. This means that it
+ * could terminate the token.
*/
if (mask & TYPE_SPACE) {
@@ -934,25 +1243,24 @@ ParseTokens(src, numBytes, mask, parsePtr)
tokenPtr->type = TCL_TOKEN_TEXT;
tokenPtr->size = 1;
parsePtr->numTokens++;
- src++; numBytes--;
+ src++;
+ numBytes--;
} else {
- panic("ParseTokens encountered unknown character");
+ Tcl_Panic("ParseTokens encountered unknown character");
}
}
if (parsePtr->numTokens == originalTokens) {
/*
- * There was nothing in this range of text. Add an empty token
- * for the empty range, so that there is always at least one
- * token added.
+ * There was nothing in this range of text. Add an empty token for the
+ * empty range, so that there is always at least one token added.
*/
- if (parsePtr->numTokens == parsePtr->tokensAvailable) {
- TclExpandTokenArray(parsePtr);
- }
+
+ TclGrowParseTokenArray(parsePtr, 1);
tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
tokenPtr->start = src;
tokenPtr->numComponents = 0;
- finishToken:
+ finishToken:
tokenPtr->type = TCL_TOKEN_TEXT;
tokenPtr->size = 0;
parsePtr->numTokens++;
@@ -960,171 +1268,112 @@ ParseTokens(src, numBytes, mask, parsePtr)
parsePtr->term = src;
return TCL_OK;
}
-
+
/*
*----------------------------------------------------------------------
*
* Tcl_FreeParse --
*
- * This procedure is invoked to free any dynamic storage that may
- * have been allocated by a previous call to Tcl_ParseCommand.
+ * This function is invoked to free any dynamic storage that may have
+ * been allocated by a previous call to Tcl_ParseCommand.
*
* Results:
* None.
*
* Side effects:
- * If there is any dynamically allocated memory in *parsePtr,
- * it is freed.
+ * If there is any dynamically allocated memory in *parsePtr, it is
+ * freed.
*
*----------------------------------------------------------------------
*/
void
-Tcl_FreeParse(parsePtr)
- Tcl_Parse *parsePtr; /* Structure that was filled in by a
- * previous call to Tcl_ParseCommand. */
+Tcl_FreeParse(
+ Tcl_Parse *parsePtr) /* Structure that was filled in by a previous
+ * call to Tcl_ParseCommand. */
{
if (parsePtr->tokenPtr != parsePtr->staticTokens) {
ckfree((char *) parsePtr->tokenPtr);
parsePtr->tokenPtr = parsePtr->staticTokens;
}
}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclExpandTokenArray --
- *
- * This procedure is invoked when the current space for tokens in
- * a Tcl_Parse structure fills up; it allocates memory to grow the
- * token array
- *
- * Results:
- * None.
- *
- * Side effects:
- * Memory is allocated for a new larger token array; the memory
- * for the old array is freed, if it had been dynamically allocated.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclExpandTokenArray(parsePtr)
- Tcl_Parse *parsePtr; /* Parse structure whose token space
- * has overflowed. */
-{
- int newCount;
- Tcl_Token *newPtr;
-
-#define MAX_TOKENS (int)(UINT_MAX / sizeof(Tcl_Token))
-
- if (parsePtr->tokensAvailable == MAX_TOKENS) {
- Tcl_Panic("max # of tokens for a Tcl parse (%d) exceeded", MAX_TOKENS);
- }
- newCount = parsePtr->tokensAvailable*2;
- if (newCount > MAX_TOKENS) {
- newCount = MAX_TOKENS;
- }
- newPtr = (Tcl_Token *) ckalloc((unsigned) (newCount * sizeof(Tcl_Token)));
- memcpy((VOID *) newPtr, (VOID *) parsePtr->tokenPtr,
- (size_t) (parsePtr->tokensAvailable * sizeof(Tcl_Token)));
- if (parsePtr->tokenPtr != parsePtr->staticTokens) {
- ckfree((char *) parsePtr->tokenPtr);
- }
- parsePtr->tokenPtr = newPtr;
- parsePtr->tokensAvailable = newCount;
-}
-
+
/*
*----------------------------------------------------------------------
*
* Tcl_ParseVarName --
*
- * Given a string starting with a $ sign, parse off a variable
- * name and return information about the parse. No more than
- * numBytes bytes will be scanned.
+ * Given a string starting with a $ sign, parse off a variable name and
+ * return information about the parse. No more than numBytes bytes will
+ * be scanned.
*
* Results:
- * The return value is TCL_OK if the command was parsed
- * successfully and TCL_ERROR otherwise. If an error occurs and
- * interp isn't NULL then an error message is left in its result.
- * On a successful return, tokenPtr and numTokens fields of
- * parsePtr are filled in with information about the variable name
- * that was parsed. The "size" field of the first new token gives
- * the total number of bytes in the variable name. Other fields in
- * parsePtr are undefined.
+ * The return value is TCL_OK if the command was parsed successfully and
+ * TCL_ERROR otherwise. If an error occurs and interp isn't NULL then an
+ * error message is left in its result. On a successful return, tokenPtr
+ * and numTokens fields of parsePtr are filled in with information about
+ * the variable name that was parsed. The "size" field of the first new
+ * token gives the total number of bytes in the variable name. Other
+ * fields in parsePtr are undefined.
*
* Side effects:
- * If there is insufficient space in parsePtr to hold all the
- * information about the command, then additional space is
- * malloc-ed. If the procedure returns TCL_OK then the caller must
- * eventually invoke Tcl_FreeParse to release any additional space
- * that was allocated.
+ * If there is insufficient space in parsePtr to hold all the information
+ * about the command, then additional space is malloc-ed. If the function
+ * returns TCL_OK then the caller must eventually invoke Tcl_FreeParse to
+ * release any additional space that was allocated.
*
*----------------------------------------------------------------------
*/
int
-Tcl_ParseVarName(interp, string, numBytes, parsePtr, append)
- Tcl_Interp *interp; /* Interpreter to use for error reporting;
- * if NULL, then no error message is
- * provided. */
- CONST char *string; /* String containing variable name. First
- * character must be "$". */
- register int numBytes; /* Total number of bytes in string. If < 0,
+Tcl_ParseVarName(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting; if
+ * NULL, then no error message is provided. */
+ const char *start, /* Start of variable substitution string.
+ * First character must be "$". */
+ register int numBytes, /* Total number of bytes in string. If < 0,
* the string consists of all bytes up to the
* first null character. */
- Tcl_Parse *parsePtr; /* Structure to fill in with information
- * about the variable name. */
- int append; /* Non-zero means append tokens to existing
+ Tcl_Parse *parsePtr, /* Structure to fill in with information about
+ * the variable name. */
+ int append) /* Non-zero means append tokens to existing
* information in parsePtr; zero means ignore
- * existing tokens in parsePtr and reinitialize
- * it. */
+ * existing tokens in parsePtr and
+ * reinitialize it. */
{
Tcl_Token *tokenPtr;
- register CONST char *src;
+ register const char *src;
unsigned char c;
int varIndex, offset;
Tcl_UniChar ch;
unsigned array;
- if ((numBytes == 0) || (string == NULL)) {
+ if ((numBytes == 0) || (start == NULL)) {
return TCL_ERROR;
}
if (numBytes < 0) {
- numBytes = strlen(string);
+ numBytes = strlen(start);
}
if (!append) {
- parsePtr->numWords = 0;
- parsePtr->tokenPtr = parsePtr->staticTokens;
- parsePtr->numTokens = 0;
- parsePtr->tokensAvailable = NUM_STATIC_TOKENS;
- parsePtr->string = string;
- parsePtr->end = (string + numBytes);
- parsePtr->interp = interp;
- parsePtr->errorType = TCL_PARSE_SUCCESS;
- parsePtr->incomplete = 0;
+ TclParseInit(interp, start, numBytes, parsePtr);
}
/*
- * Generate one token for the variable, an additional token for the
- * name, plus any number of additional tokens for the index, if
- * there is one.
+ * Generate one token for the variable, an additional token for the name,
+ * plus any number of additional tokens for the index, if there is one.
*/
- src = string;
- if ((parsePtr->numTokens + 2) > parsePtr->tokensAvailable) {
- TclExpandTokenArray(parsePtr);
- }
+ src = start;
+ TclGrowParseTokenArray(parsePtr, 2);
tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
tokenPtr->type = TCL_TOKEN_VARIABLE;
tokenPtr->start = src;
varIndex = parsePtr->numTokens;
parsePtr->numTokens++;
tokenPtr++;
- src++; numBytes--;
+ src++;
+ numBytes--;
if (numBytes == 0) {
goto justADollarSign;
}
@@ -1134,29 +1383,30 @@ Tcl_ParseVarName(interp, string, numBytes, parsePtr, append)
/*
* The name of the variable can have three forms:
- * 1. The $ sign is followed by an open curly brace. Then
- * the variable name is everything up to the next close
- * curly brace, and the variable is a scalar variable.
- * 2. The $ sign is not followed by an open curly brace. Then
- * the variable name is everything up to the next
- * character that isn't a letter, digit, or underscore.
- * :: sequences are also considered part of the variable
- * name, in order to support namespaces. If the following
- * character is an open parenthesis, then the information
- * between parentheses is the array element name.
- * 3. The $ sign is followed by something that isn't a letter,
- * digit, or underscore: in this case, there is no variable
- * name and the token is just "$".
+ * 1. The $ sign is followed by an open curly brace. Then the variable
+ * name is everything up to the next close curly brace, and the
+ * variable is a scalar variable.
+ * 2. The $ sign is not followed by an open curly brace. Then the variable
+ * name is everything up to the next character that isn't a letter,
+ * digit, or underscore. :: sequences are also considered part of the
+ * variable name, in order to support namespaces. If the following
+ * character is an open parenthesis, then the information between
+ * parentheses is the array element name.
+ * 3. The $ sign is followed by something that isn't a letter, digit, or
+ * underscore: in this case, there is no variable name and the token is
+ * just "$".
*/
if (*src == '{') {
- src++; numBytes--;
+ src++;
+ numBytes--;
tokenPtr->type = TCL_TOKEN_TEXT;
tokenPtr->start = src;
tokenPtr->numComponents = 0;
while (numBytes && (*src != '}')) {
- numBytes--; src++;
+ numBytes--;
+ src++;
}
if (numBytes == 0) {
if (parsePtr->interp != NULL) {
@@ -1176,24 +1426,29 @@ Tcl_ParseVarName(interp, string, numBytes, parsePtr, append)
tokenPtr->type = TCL_TOKEN_TEXT;
tokenPtr->start = src;
tokenPtr->numComponents = 0;
+
while (numBytes) {
if (Tcl_UtfCharComplete(src, numBytes)) {
- offset = Tcl_UtfToUniChar(src, &ch);
+ offset = Tcl_UtfToUniChar(src, &ch);
} else {
char utfBytes[TCL_UTF_MAX];
+
memcpy(utfBytes, src, (size_t) numBytes);
utfBytes[numBytes] = '\0';
- offset = Tcl_UtfToUniChar(utfBytes, &ch);
+ offset = Tcl_UtfToUniChar(utfBytes, &ch);
}
c = UCHAR(ch);
- if (isalnum(c) || (c == '_')) { /* INTL: ISO only, UCHAR. */
- src += offset; numBytes -= offset;
+ if (isalnum(c) || (c == '_')) { /* INTL: ISO only, UCHAR. */
+ src += offset;
+ numBytes -= offset;
continue;
}
if ((c == ':') && (numBytes != 1) && (src[1] == ':')) {
- src += 2; numBytes -= 2;
+ src += 2;
+ numBytes -= 2;
while (numBytes && (*src == ':')) {
- src++; numBytes--;
+ src++;
+ numBytes--;
}
continue;
}
@@ -1203,6 +1458,7 @@ Tcl_ParseVarName(interp, string, numBytes, parsePtr, append)
/*
* Support for empty array names here.
*/
+
array = (numBytes && (*src == '('));
tokenPtr->size = src - tokenPtr->start;
if ((tokenPtr->size == 0) && !array) {
@@ -1211,17 +1467,16 @@ Tcl_ParseVarName(interp, string, numBytes, parsePtr, append)
parsePtr->numTokens++;
if (array) {
/*
- * This is a reference to an array element. Call
- * ParseTokens recursively to parse the element name,
- * since it could contain any number of substitutions.
+ * This is a reference to an array element. Call ParseTokens
+ * recursively to parse the element name, since it could contain
+ * any number of substitutions.
*/
- if (ParseTokens(src+1, numBytes-1, TYPE_CLOSE_PAREN, parsePtr)
- != TCL_OK) {
+ if (TCL_OK != ParseTokens(src+1, numBytes-1, TYPE_CLOSE_PAREN,
+ TCL_SUBST_ALL, parsePtr)) {
goto error;
}
- if ((parsePtr->term == (src + numBytes))
- || (*parsePtr->term != ')')) {
+ if ((parsePtr->term == src+numBytes) || (*parsePtr->term != ')')){
if (parsePtr->interp != NULL) {
Tcl_SetResult(parsePtr->interp, "missing )",
TCL_STATIC);
@@ -1240,38 +1495,37 @@ Tcl_ParseVarName(interp, string, numBytes, parsePtr, append)
return TCL_OK;
/*
- * The dollar sign isn't followed by a variable name.
- * replace the TCL_TOKEN_VARIABLE token with a
- * TCL_TOKEN_TEXT token for the dollar sign.
+ * The dollar sign isn't followed by a variable name. Replace the
+ * TCL_TOKEN_VARIABLE token with a TCL_TOKEN_TEXT token for the dollar
+ * sign.
*/
- justADollarSign:
+ justADollarSign:
tokenPtr = &parsePtr->tokenPtr[varIndex];
tokenPtr->type = TCL_TOKEN_TEXT;
tokenPtr->size = 1;
tokenPtr->numComponents = 0;
return TCL_OK;
- error:
+ error:
Tcl_FreeParse(parsePtr);
return TCL_ERROR;
}
-
+
/*
*----------------------------------------------------------------------
*
* Tcl_ParseVar --
*
- * Given a string starting with a $ sign, parse off a variable
- * name and return its value.
+ * Given a string starting with a $ sign, parse off a variable name and
+ * return its value.
*
* Results:
- * The return value is the contents of the variable given by
- * the leading characters of string. If termPtr isn't NULL,
- * *termPtr gets filled in with the address of the character
- * just after the last one in the variable specifier. If the
- * variable doesn't exist, then the return value is NULL and
- * an error message will be left in interp's result.
+ * The return value is the contents of the variable given by the leading
+ * characters of string. If termPtr isn't NULL, *termPtr gets filled in
+ * with the address of the character just after the last one in the
+ * variable specifier. If the variable doesn't exist, then the return
+ * value is NULL and an error message will be left in interp's result.
*
* Side effects:
* None.
@@ -1279,50 +1533,54 @@ Tcl_ParseVarName(interp, string, numBytes, parsePtr, append)
*----------------------------------------------------------------------
*/
-CONST char *
-Tcl_ParseVar(interp, string, termPtr)
- Tcl_Interp *interp; /* Context for looking up variable. */
- register CONST char *string; /* String containing variable name.
- * First character must be "$". */
- CONST char **termPtr; /* If non-NULL, points to word to fill
- * in with character just after last
- * one in the variable specifier. */
-
+const char *
+Tcl_ParseVar(
+ Tcl_Interp *interp, /* Context for looking up variable. */
+ register const char *start, /* Start of variable substitution. First
+ * character must be "$". */
+ const char **termPtr) /* If non-NULL, points to word to fill in with
+ * character just after last one in the
+ * variable specifier. */
{
- Tcl_Parse parse;
register Tcl_Obj *objPtr;
int code;
+ Tcl_Parse *parsePtr = (Tcl_Parse *)
+ TclStackAlloc(interp, sizeof(Tcl_Parse));
- if (Tcl_ParseVarName(interp, string, -1, &parse, 0) != TCL_OK) {
+ if (Tcl_ParseVarName(interp, start, -1, parsePtr, 0) != TCL_OK) {
+ TclStackFree(interp, parsePtr);
return NULL;
}
if (termPtr != NULL) {
- *termPtr = string + parse.tokenPtr->size;
+ *termPtr = start + parsePtr->tokenPtr->size;
}
- if (parse.numTokens == 1) {
+ if (parsePtr->numTokens == 1) {
/*
* There isn't a variable name after all: the $ is just a $.
*/
+ TclStackFree(interp, parsePtr);
return "$";
}
- code = Tcl_EvalTokensStandard(interp, parse.tokenPtr, parse.numTokens);
+ code = TclSubstTokens(interp, parsePtr->tokenPtr, parsePtr->numTokens,
+ NULL, 1, NULL, NULL);
+ TclStackFree(interp, parsePtr);
if (code != TCL_OK) {
return NULL;
}
objPtr = Tcl_GetObjResult(interp);
/*
- * At this point we should have an object containing the value of
- * a variable. Just return the string from that object.
+ * At this point we should have an object containing the value of a
+ * variable. Just return the string from that object.
*
* This should have returned the object for the user to manage, but
- * instead we have some weak reference to the string value in the
- * object, which is why we make sure the object exists after resetting
- * the result. This isn't ideal, but it's the best we can do with the
- * current documented interface. -- hobbs
+ * instead we have some weak reference to the string value in the object,
+ * which is why we make sure the object exists after resetting the result.
+ * This isn't ideal, but it's the best we can do with the current
+ * documented interface. -- hobbs
*/
if (!Tcl_IsShared(objPtr)) {
@@ -1331,87 +1589,75 @@ Tcl_ParseVar(interp, string, termPtr)
Tcl_ResetResult(interp);
return TclGetString(objPtr);
}
-
+
/*
*----------------------------------------------------------------------
*
* Tcl_ParseBraces --
*
* Given a string in braces such as a Tcl command argument or a string
- * value in a Tcl expression, this procedure parses the string and
- * returns information about the parse. No more than numBytes bytes
- * will be scanned.
+ * value in a Tcl expression, this function parses the string and returns
+ * information about the parse. No more than numBytes bytes will be
+ * scanned.
*
* Results:
* The return value is TCL_OK if the string was parsed successfully and
- * TCL_ERROR otherwise. If an error occurs and interp isn't NULL then
- * an error message is left in its result. On a successful return,
- * tokenPtr and numTokens fields of parsePtr are filled in with
- * information about the string that was parsed. Other fields in
- * parsePtr are undefined. termPtr is set to point to the character
- * just after the last one in the braced string.
+ * TCL_ERROR otherwise. If an error occurs and interp isn't NULL then an
+ * error message is left in its result. On a successful return, tokenPtr
+ * and numTokens fields of parsePtr are filled in with information about
+ * the string that was parsed. Other fields in parsePtr are undefined.
+ * termPtr is set to point to the character just after the last one in
+ * the braced string.
*
* Side effects:
- * If there is insufficient space in parsePtr to hold all the
- * information about the command, then additional space is
- * malloc-ed. If the procedure returns TCL_OK then the caller must
- * eventually invoke Tcl_FreeParse to release any additional space
- * that was allocated.
+ * If there is insufficient space in parsePtr to hold all the information
+ * about the command, then additional space is malloc-ed. If the function
+ * returns TCL_OK then the caller must eventually invoke Tcl_FreeParse to
+ * release any additional space that was allocated.
*
*----------------------------------------------------------------------
*/
int
-Tcl_ParseBraces(interp, string, numBytes, parsePtr, append, termPtr)
- Tcl_Interp *interp; /* Interpreter to use for error reporting;
- * if NULL, then no error message is
- * provided. */
- CONST char *string; /* String containing the string in braces.
- * The first character must be '{'. */
- register int numBytes; /* Total number of bytes in string. If < 0,
- * the string consists of all bytes up to
- * the first null character. */
- register Tcl_Parse *parsePtr;
- /* Structure to fill in with information
- * about the string. */
- int append; /* Non-zero means append tokens to existing
- * information in parsePtr; zero means
- * ignore existing tokens in parsePtr and
+Tcl_ParseBraces(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting; if
+ * NULL, then no error message is provided. */
+ const char *start, /* Start of string enclosed in braces. The
+ * first character must be {'. */
+ register int numBytes, /* Total number of bytes in string. If < 0,
+ * the string consists of all bytes up to the
+ * first null character. */
+ register Tcl_Parse *parsePtr,
+ /* Structure to fill in with information about
+ * the string. */
+ int append, /* Non-zero means append tokens to existing
+ * information in parsePtr; zero means ignore
+ * existing tokens in parsePtr and
* reinitialize it. */
- CONST char **termPtr; /* If non-NULL, points to word in which to
- * store a pointer to the character just
- * after the terminating '}' if the parse
- * was successful. */
-
+ const char **termPtr) /* If non-NULL, points to word in which to
+ * store a pointer to the character just after
+ * the terminating '}' if the parse was
+ * successful. */
{
Tcl_Token *tokenPtr;
- register CONST char *src;
+ register const char *src;
int startIndex, level, length;
- if ((numBytes == 0) || (string == NULL)) {
+ if ((numBytes == 0) || (start == NULL)) {
return TCL_ERROR;
}
if (numBytes < 0) {
- numBytes = strlen(string);
+ numBytes = strlen(start);
}
if (!append) {
- parsePtr->numWords = 0;
- parsePtr->tokenPtr = parsePtr->staticTokens;
- parsePtr->numTokens = 0;
- parsePtr->tokensAvailable = NUM_STATIC_TOKENS;
- parsePtr->string = string;
- parsePtr->end = (string + numBytes);
- parsePtr->interp = interp;
- parsePtr->errorType = TCL_PARSE_SUCCESS;
+ TclParseInit(interp, start, numBytes, parsePtr);
}
- src = string;
+ src = start;
startIndex = parsePtr->numTokens;
- if (parsePtr->numTokens == parsePtr->tokensAvailable) {
- TclExpandTokenArray(parsePtr);
- }
+ TclGrowParseTokenArray(parsePtr, 1);
tokenPtr = &parsePtr->tokenPtr[startIndex];
tokenPtr->type = TCL_TOKEN_TEXT;
tokenPtr->start = src+1;
@@ -1424,195 +1670,189 @@ Tcl_ParseBraces(interp, string, numBytes, parsePtr, append, termPtr)
}
}
if (numBytes == 0) {
- register int openBrace = 0;
+ goto missingBraceError;
+ }
- parsePtr->errorType = TCL_PARSE_MISSING_BRACE;
- parsePtr->term = string;
- parsePtr->incomplete = 1;
- if (parsePtr->interp == NULL) {
+ switch (*src) {
+ case '{':
+ level++;
+ break;
+ case '}':
+ if (--level == 0) {
/*
- * Skip straight to the exit code since we have no
- * interpreter to put error message in.
+ * Decide if we need to finish emitting a partially-finished
+ * token. There are 3 cases:
+ * {abc \newline xyz} or {xyz}
+ * - finish emitting "xyz" token
+ * {abc \newline}
+ * - don't emit token after \newline
+ * {} - finish emitting zero-sized token
+ *
+ * The last case ensures that there is a token (even if empty)
+ * that describes the braced string.
*/
- goto error;
- }
-
- Tcl_SetResult(parsePtr->interp, "missing close-brace", TCL_STATIC);
-
- /*
- * Guess if the problem is due to comments by searching
- * the source string for a possible open brace within the
- * context of a comment. Since we aren't performing a
- * full Tcl parse, just look for an open brace preceded
- * by a '<whitespace>#' on the same line.
- */
- while (--src > string) {
- switch (*src) {
- case '{':
- openBrace = 1;
- break;
- case '\n':
- openBrace = 0;
- break;
- case '#' :
- if (openBrace && (isspace(UCHAR(src[-1])))) {
- Tcl_AppendResult(parsePtr->interp,
- ": possible unbalanced brace in comment",
- (char *) NULL);
- goto error;
- }
- break;
+ if ((src != tokenPtr->start)
+ || (parsePtr->numTokens == startIndex)) {
+ tokenPtr->size = (src - tokenPtr->start);
+ parsePtr->numTokens++;
}
+ if (termPtr != NULL) {
+ *termPtr = src+1;
+ }
+ return TCL_OK;
}
+ break;
+ case '\\':
+ TclParseBackslash(src, numBytes, &length, NULL);
+ if ((length > 1) && (src[1] == '\n')) {
+ /*
+ * A backslash-newline sequence must be collapsed, even inside
+ * braces, so we have to split the word into multiple tokens
+ * so that the backslash-newline can be represented
+ * explicitly.
+ */
- error:
- Tcl_FreeParse(parsePtr);
- return TCL_ERROR;
+ if (numBytes == 2) {
+ parsePtr->incomplete = 1;
+ }
+ tokenPtr->size = (src - tokenPtr->start);
+ if (tokenPtr->size != 0) {
+ parsePtr->numTokens++;
+ }
+ TclGrowParseTokenArray(parsePtr, 2);
+ tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
+ tokenPtr->type = TCL_TOKEN_BS;
+ tokenPtr->start = src;
+ tokenPtr->size = length;
+ tokenPtr->numComponents = 0;
+ parsePtr->numTokens++;
+
+ src += length - 1;
+ numBytes -= length - 1;
+ tokenPtr++;
+ tokenPtr->type = TCL_TOKEN_TEXT;
+ tokenPtr->start = src + 1;
+ tokenPtr->numComponents = 0;
+ } else {
+ src += length - 1;
+ numBytes -= length - 1;
+ }
+ break;
}
- switch (*src) {
+ }
+
+ missingBraceError:
+ parsePtr->errorType = TCL_PARSE_MISSING_BRACE;
+ parsePtr->term = start;
+ parsePtr->incomplete = 1;
+ if (parsePtr->interp == NULL) {
+ /*
+ * Skip straight to the exit code since we have no interpreter to put
+ * error message in.
+ */
+
+ goto error;
+ }
+
+ Tcl_SetResult(parsePtr->interp, "missing close-brace", TCL_STATIC);
+
+ /*
+ * Guess if the problem is due to comments by searching the source string
+ * for a possible open brace within the context of a comment. Since we
+ * aren't performing a full Tcl parse, just look for an open brace
+ * preceded by a '<whitespace>#' on the same line.
+ */
+
+ {
+ register int openBrace = 0;
+
+ while (--src > start) {
+ switch (*src) {
case '{':
- level++;
+ openBrace = 1;
break;
- case '}':
- if (--level == 0) {
-
- /*
- * Decide if we need to finish emitting a
- * partially-finished token. There are 3 cases:
- * {abc \newline xyz} or {xyz}
- * - finish emitting "xyz" token
- * {abc \newline}
- * - don't emit token after \newline
- * {} - finish emitting zero-sized token
- *
- * The last case ensures that there is a token
- * (even if empty) that describes the braced string.
- */
-
- if ((src != tokenPtr->start)
- || (parsePtr->numTokens == startIndex)) {
- tokenPtr->size = (src - tokenPtr->start);
- parsePtr->numTokens++;
- }
- if (termPtr != NULL) {
- *termPtr = src+1;
- }
- return TCL_OK;
- }
+ case '\n':
+ openBrace = 0;
break;
- case '\\':
- TclParseBackslash(src, numBytes, &length, NULL);
- if ((length > 1) && (src[1] == '\n')) {
- /*
- * A backslash-newline sequence must be collapsed, even
- * inside braces, so we have to split the word into
- * multiple tokens so that the backslash-newline can be
- * represented explicitly.
- */
-
- if (numBytes == 2) {
- parsePtr->incomplete = 1;
- }
- tokenPtr->size = (src - tokenPtr->start);
- if (tokenPtr->size != 0) {
- parsePtr->numTokens++;
- }
- if ((parsePtr->numTokens+1) >= parsePtr->tokensAvailable) {
- TclExpandTokenArray(parsePtr);
- }
- tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
- tokenPtr->type = TCL_TOKEN_BS;
- tokenPtr->start = src;
- tokenPtr->size = length;
- tokenPtr->numComponents = 0;
- parsePtr->numTokens++;
-
- src += length - 1;
- numBytes -= length - 1;
- tokenPtr++;
- tokenPtr->type = TCL_TOKEN_TEXT;
- tokenPtr->start = src + 1;
- tokenPtr->numComponents = 0;
- } else {
- src += length - 1;
- numBytes -= length - 1;
+ case '#' :
+ if (openBrace && TclIsSpaceProc(src[-1])) {
+ Tcl_AppendResult(parsePtr->interp,
+ ": possible unbalanced brace in comment", NULL);
+ goto error;
}
break;
+ }
}
}
-}
+ error:
+ Tcl_FreeParse(parsePtr);
+ return TCL_ERROR;
+}
+
/*
*----------------------------------------------------------------------
*
* Tcl_ParseQuotedString --
*
- * Given a double-quoted string such as a quoted Tcl command argument
- * or a quoted value in a Tcl expression, this procedure parses the
- * string and returns information about the parse. No more than
- * numBytes bytes will be scanned.
+ * Given a double-quoted string such as a quoted Tcl command argument or
+ * a quoted value in a Tcl expression, this function parses the string
+ * and returns information about the parse. No more than numBytes bytes
+ * will be scanned.
*
* Results:
* The return value is TCL_OK if the string was parsed successfully and
- * TCL_ERROR otherwise. If an error occurs and interp isn't NULL then
- * an error message is left in its result. On a successful return,
- * tokenPtr and numTokens fields of parsePtr are filled in with
- * information about the string that was parsed. Other fields in
- * parsePtr are undefined. termPtr is set to point to the character
- * just after the quoted string's terminating close-quote.
+ * TCL_ERROR otherwise. If an error occurs and interp isn't NULL then an
+ * error message is left in its result. On a successful return, tokenPtr
+ * and numTokens fields of parsePtr are filled in with information about
+ * the string that was parsed. Other fields in parsePtr are undefined.
+ * termPtr is set to point to the character just after the quoted
+ * string's terminating close-quote.
*
* Side effects:
- * If there is insufficient space in parsePtr to hold all the
- * information about the command, then additional space is
- * malloc-ed. If the procedure returns TCL_OK then the caller must
- * eventually invoke Tcl_FreeParse to release any additional space
- * that was allocated.
+ * If there is insufficient space in parsePtr to hold all the information
+ * about the command, then additional space is malloc-ed. If the function
+ * returns TCL_OK then the caller must eventually invoke Tcl_FreeParse to
+ * release any additional space that was allocated.
*
*----------------------------------------------------------------------
*/
int
-Tcl_ParseQuotedString(interp, string, numBytes, parsePtr, append, termPtr)
- Tcl_Interp *interp; /* Interpreter to use for error reporting;
- * if NULL, then no error message is
- * provided. */
- CONST char *string; /* String containing the quoted string.
- * The first character must be '"'. */
- register int numBytes; /* Total number of bytes in string. If < 0,
- * the string consists of all bytes up to
- * the first null character. */
- register Tcl_Parse *parsePtr;
- /* Structure to fill in with information
- * about the string. */
- int append; /* Non-zero means append tokens to existing
- * information in parsePtr; zero means
- * ignore existing tokens in parsePtr and
+Tcl_ParseQuotedString(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting; if
+ * NULL, then no error message is provided. */
+ const char *start, /* Start of the quoted string. The first
+ * character must be '"'. */
+ register int numBytes, /* Total number of bytes in string. If < 0,
+ * the string consists of all bytes up to the
+ * first null character. */
+ register Tcl_Parse *parsePtr,
+ /* Structure to fill in with information about
+ * the string. */
+ int append, /* Non-zero means append tokens to existing
+ * information in parsePtr; zero means ignore
+ * existing tokens in parsePtr and
* reinitialize it. */
- CONST char **termPtr; /* If non-NULL, points to word in which to
- * store a pointer to the character just
- * after the quoted string's terminating
- * close-quote if the parse succeeds. */
+ const char **termPtr) /* If non-NULL, points to word in which to
+ * store a pointer to the character just after
+ * the quoted string's terminating close-quote
+ * if the parse succeeds. */
{
- if ((numBytes == 0) || (string == NULL)) {
+ if ((numBytes == 0) || (start == NULL)) {
return TCL_ERROR;
}
if (numBytes < 0) {
- numBytes = strlen(string);
+ numBytes = strlen(start);
}
if (!append) {
- parsePtr->numWords = 0;
- parsePtr->tokenPtr = parsePtr->staticTokens;
- parsePtr->numTokens = 0;
- parsePtr->tokensAvailable = NUM_STATIC_TOKENS;
- parsePtr->string = string;
- parsePtr->end = (string + numBytes);
- parsePtr->interp = interp;
- parsePtr->errorType = TCL_PARSE_SUCCESS;
+ TclParseInit(interp, start, numBytes, parsePtr);
}
-
- if (ParseTokens(string+1, numBytes-1, TYPE_QUOTE, parsePtr) != TCL_OK) {
+
+ if (TCL_OK != ParseTokens(start+1, numBytes-1, TYPE_QUOTE, TCL_SUBST_ALL,
+ parsePtr)) {
goto error;
}
if (*parsePtr->term != '"') {
@@ -1620,7 +1860,7 @@ Tcl_ParseQuotedString(interp, string, numBytes, parsePtr, append, termPtr)
Tcl_SetResult(parsePtr->interp, "missing \"", TCL_STATIC);
}
parsePtr->errorType = TCL_PARSE_MISSING_QUOTE;
- parsePtr->term = string;
+ parsePtr->term = start;
parsePtr->incomplete = 1;
goto error;
}
@@ -1629,24 +1869,579 @@ Tcl_ParseQuotedString(interp, string, numBytes, parsePtr, append, termPtr)
}
return TCL_OK;
- error:
+ error:
Tcl_FreeParse(parsePtr);
return TCL_ERROR;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SubstObj --
+ *
+ * This function performs the substitutions specified on the given string
+ * as described in the user documentation for the "subst" Tcl command.
+ *
+ * Results:
+ * A Tcl_Obj* containing the substituted string, or NULL to indicate that
+ * an error occurred.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tcl_SubstObj(
+ Tcl_Interp *interp, /* Interpreter in which substitution occurs */
+ Tcl_Obj *objPtr, /* The value to be substituted. */
+ int flags) /* What substitutions to do. */
+{
+ int length, tokensLeft, code;
+ Tcl_Token *endTokenPtr;
+ Tcl_Obj *result, *errMsg = NULL;
+ const char *p = TclGetStringFromObj(objPtr, &length);
+ Tcl_Parse *parsePtr = (Tcl_Parse *)
+ TclStackAlloc(interp, sizeof(Tcl_Parse));
+
+ TclParseInit(interp, p, length, parsePtr);
+
+ /*
+ * First parse the string rep of objPtr, as if it were enclosed as a
+ * "-quoted word in a normal Tcl command. Honor flags that selectively
+ * inhibit types of substitution.
+ */
+
+ if (TCL_OK != ParseTokens(p, length, /* mask */ 0, flags, parsePtr)) {
+ /*
+ * There was a parse error. Save the error message for possible
+ * reporting later.
+ */
+
+ errMsg = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(errMsg);
+
+ /*
+ * We need to re-parse to get the portion of the string we can [subst]
+ * before the parse error. Sadly, all the Tcl_Token's created by the
+ * first parse attempt are gone, freed according to the public spec
+ * for the Tcl_Parse* routines. The only clue we have is parse.term,
+ * which points to either the unmatched opener, or to characters that
+ * follow a close brace or close quote.
+ *
+ * Call ParseTokens again, working on the string up to parse.term.
+ * Keep repeating until we get a good parse on a prefix.
+ */
+
+ do {
+ parsePtr->numTokens = 0;
+ parsePtr->tokensAvailable = NUM_STATIC_TOKENS;
+ parsePtr->end = parsePtr->term;
+ parsePtr->incomplete = 0;
+ parsePtr->errorType = TCL_PARSE_SUCCESS;
+ } while (TCL_OK !=
+ ParseTokens(p, parsePtr->end - p, 0, flags, parsePtr));
+
+ /*
+ * The good parse will have to be followed by {, (, or [.
+ */
+
+ switch (*(parsePtr->term)) {
+ case '{':
+ /*
+ * Parse error was a missing } in a ${varname} variable
+ * substitution at the toplevel. We will subst everything up to
+ * that broken variable substitution before reporting the parse
+ * error. Substituting the leftover '$' will have no side-effects,
+ * so the current token stream is fine.
+ */
+ break;
+
+ case '(':
+ /*
+ * Parse error was during the parsing of the index part of an
+ * array variable substitution at the toplevel.
+ */
+
+ if (*(parsePtr->term - 1) == '$') {
+ /*
+ * Special case where removing the array index left us with
+ * just a dollar sign (array variable with name the empty
+ * string as its name), instead of with a scalar variable
+ * reference.
+ *
+ * As in the previous case, existing token stream is OK.
+ */
+ } else {
+ /*
+ * The current parse includes a successful parse of a scalar
+ * variable substitution where there should have been an array
+ * variable substitution. We remove that mistaken part of the
+ * parse before moving on. A scalar variable substitution is
+ * two tokens.
+ */
+
+ Tcl_Token *varTokenPtr =
+ parsePtr->tokenPtr + parsePtr->numTokens - 2;
+
+ if (varTokenPtr->type != TCL_TOKEN_VARIABLE) {
+ Tcl_Panic("Tcl_SubstObj: programming error");
+ }
+ if (varTokenPtr[1].type != TCL_TOKEN_TEXT) {
+ Tcl_Panic("Tcl_SubstObj: programming error");
+ }
+ parsePtr->numTokens -= 2;
+ }
+ break;
+ case '[':
+ /*
+ * Parse error occurred during parsing of a toplevel command
+ * substitution.
+ */
+
+ parsePtr->end = p + length;
+ p = parsePtr->term + 1;
+ length = parsePtr->end - p;
+ if (length == 0) {
+ /*
+ * No commands, just an unmatched [. As in previous cases,
+ * existing token stream is OK.
+ */
+ } else {
+ /*
+ * We want to add the parsing of as many commands as we can
+ * within that substitution until we reach the actual parse
+ * error. We'll do additional parsing to determine what length
+ * to claim for the final TCL_TOKEN_COMMAND token.
+ */
+
+ Tcl_Token *tokenPtr;
+ const char *lastTerm = parsePtr->term;
+ Tcl_Parse *nestedPtr = (Tcl_Parse *)
+ TclStackAlloc(interp, sizeof(Tcl_Parse));
+
+ while (TCL_OK ==
+ Tcl_ParseCommand(NULL, p, length, 0, nestedPtr)) {
+ Tcl_FreeParse(nestedPtr);
+ p = nestedPtr->term + (nestedPtr->term < nestedPtr->end);
+ length = nestedPtr->end - p;
+ if ((length == 0) && (nestedPtr->term == nestedPtr->end)) {
+ /*
+ * If we run out of string, blame the missing close
+ * bracket on the last command, and do not evaluate it
+ * during substitution.
+ */
+
+ break;
+ }
+ lastTerm = nestedPtr->term;
+ }
+ TclStackFree(interp, nestedPtr);
+
+ if (lastTerm == parsePtr->term) {
+ /*
+ * Parse error in first command. No commands to subst, add
+ * no more tokens.
+ */
+ break;
+ }
+
+ /*
+ * Create a command substitution token for whatever commands
+ * got parsed.
+ */
+
+ TclGrowParseTokenArray(parsePtr, 1);
+ tokenPtr = &(parsePtr->tokenPtr[parsePtr->numTokens]);
+ tokenPtr->start = parsePtr->term;
+ tokenPtr->numComponents = 0;
+ tokenPtr->type = TCL_TOKEN_COMMAND;
+ tokenPtr->size = lastTerm - tokenPtr->start + 1;
+ parsePtr->numTokens++;
+ }
+ break;
+
+ default:
+ Tcl_Panic("bad parse in Tcl_SubstObj: %c", p[length]);
+ }
+ }
+ /*
+ * Next, substitute the parsed tokens just as in normal Tcl evaluation.
+ */
+
+ endTokenPtr = parsePtr->tokenPtr + parsePtr->numTokens;
+ tokensLeft = parsePtr->numTokens;
+ code = TclSubstTokens(interp, endTokenPtr - tokensLeft, tokensLeft,
+ &tokensLeft, 1, NULL, NULL);
+ if (code == TCL_OK) {
+ Tcl_FreeParse(parsePtr);
+ TclStackFree(interp, parsePtr);
+ if (errMsg != NULL) {
+ Tcl_SetObjResult(interp, errMsg);
+ Tcl_DecrRefCount(errMsg);
+ return NULL;
+ }
+ return Tcl_GetObjResult(interp);
+ }
+
+ result = Tcl_NewObj();
+ while (1) {
+ switch (code) {
+ case TCL_ERROR:
+ Tcl_FreeParse(parsePtr);
+ TclStackFree(interp, parsePtr);
+ Tcl_DecrRefCount(result);
+ if (errMsg != NULL) {
+ Tcl_DecrRefCount(errMsg);
+ }
+ return NULL;
+ case TCL_BREAK:
+ tokensLeft = 0; /* Halt substitution */
+ default:
+ Tcl_AppendObjToObj(result, Tcl_GetObjResult(interp));
+ }
+
+ if (tokensLeft == 0) {
+ Tcl_FreeParse(parsePtr);
+ TclStackFree(interp, parsePtr);
+ if (errMsg != NULL) {
+ if (code != TCL_BREAK) {
+ Tcl_DecrRefCount(result);
+ Tcl_SetObjResult(interp, errMsg);
+ Tcl_DecrRefCount(errMsg);
+ return NULL;
+ }
+ Tcl_DecrRefCount(errMsg);
+ }
+ return result;
+ }
+
+ code = TclSubstTokens(interp, endTokenPtr - tokensLeft, tokensLeft,
+ &tokensLeft, 1, NULL, NULL);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclSubstTokens --
+ *
+ * Accepts an array of count Tcl_Token's, and creates a result value in
+ * the interp from concatenating the results of performing Tcl
+ * substitution on each Tcl_Token. Substitution is interrupted if any
+ * non-TCL_OK completion code arises.
+ *
+ * Results:
+ * The return value is a standard Tcl completion code. The result in
+ * interp is the substituted value, or an error message if TCL_ERROR is
+ * returned. If tokensLeftPtr is not NULL, then it points to an int where
+ * the number of tokens remaining to be processed is written.
+ *
+ * Side effects:
+ * Can be anything, depending on the types of substitution done.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclSubstTokens(
+ Tcl_Interp *interp, /* Interpreter in which to lookup variables,
+ * execute nested commands, and report
+ * errors. */
+ Tcl_Token *tokenPtr, /* Pointer to first in an array of tokens to
+ * evaluate and concatenate. */
+ int count, /* Number of tokens to consider at tokenPtr.
+ * Must be at least 1. */
+ int *tokensLeftPtr, /* If not NULL, points to memory where an
+ * integer representing the number of tokens
+ * left to be substituted will be written */
+ int line, /* The line the script starts on. */
+ int* clNextOuter, /* Information about an outer context for */
+ CONST char* outerScript) /* continuation line data. This is set by
+ * EvalEx() to properly handle [...]-nested
+ * commands. The 'outerScript' refers to the
+ * most-outer script containing the embedded
+ * command, which is refered to by 'script'. The
+ * 'clNextOuter' refers to the current entry in
+ * the table of continuation lines in this
+ * "master script", and the character offsets are
+ * relative to the 'outerScript' as well.
+ *
+ * If outerScript == script, then this call is for
+ * words in the outer-most script/command. See
+ * Tcl_EvalEx() and TclEvalObjEx() for the places
+ * generating arguments for which this is true.
+ */
+{
+ Tcl_Obj *result;
+ int code = TCL_OK;
+#define NUM_STATIC_POS 20
+ int isLiteral, maxNumCL, numCL, i, adjust;
+ int* clPosition = NULL;
+ Interp* iPtr = (Interp*) interp;
+ int inFile = iPtr->evalFlags & TCL_EVAL_FILE;
+
+ /*
+ * Each pass through this loop will substitute one token, and its
+ * components, if any. The only thing tricky here is that we go to some
+ * effort to pass Tcl_Obj's through untouched, to avoid string copying and
+ * Tcl_Obj creation if possible, to aid performance and limit shimmering.
+ *
+ * Further optimization opportunities might be to check for the equivalent
+ * of Tcl_SetObjResult(interp, Tcl_GetObjResult(interp)) and omit them.
+ */
+
+ /*
+ * For the handling of continuation lines in literals we first check if
+ * this is actually a literal. For if not we can forego the additional
+ * processing. Otherwise we pre-allocate a small table to store the
+ * locations of all continuation lines we find in this literal, if
+ * any. The table is extended if needed.
+ */
+
+ numCL = 0;
+ maxNumCL = 0;
+ isLiteral = 1;
+ for (i=0 ; i < count; i++) {
+ if ((tokenPtr[i].type != TCL_TOKEN_TEXT) &&
+ (tokenPtr[i].type != TCL_TOKEN_BS)) {
+ isLiteral = 0;
+ break;
+ }
+ }
+
+ if (isLiteral) {
+ maxNumCL = NUM_STATIC_POS;
+ clPosition = (int*) ckalloc (maxNumCL*sizeof(int));
+ }
+
+ adjust = 0;
+ result = NULL;
+ for (; count>0 && code==TCL_OK ; count--, tokenPtr++) {
+ Tcl_Obj *appendObj = NULL;
+ const char *append = NULL;
+ int appendByteLength = 0;
+ char utfCharBytes[TCL_UTF_MAX];
+
+ switch (tokenPtr->type) {
+ case TCL_TOKEN_TEXT:
+ append = tokenPtr->start;
+ appendByteLength = tokenPtr->size;
+ break;
+
+ case TCL_TOKEN_BS:
+ appendByteLength = TclParseBackslash(tokenPtr->start,
+ tokenPtr->size, NULL, utfCharBytes);
+ append = utfCharBytes;
+ /*
+ * If the backslash sequence we found is in a literal, and
+ * represented a continuation line, we compute and store its
+ * location (as char offset to the beginning of the _result_
+ * script). We may have to extend the table of locations.
+ *
+ * Note that the continuation line information is relevant even if
+ * the word we are processing is not a literal, as it can affect
+ * nested commands. See the branch for TCL_TOKEN_COMMAND below,
+ * where the adjustment we are tracking here is taken into
+ * account. The good thing is that we do not need a table of
+ * everything, just the number of lines we have to add as
+ * correction.
+ */
+
+ if ((appendByteLength == 1) && (utfCharBytes[0] == ' ') &&
+ (tokenPtr->start[1] == '\n')) {
+ if (isLiteral) {
+ int clPos;
+ if (result == 0) {
+ clPos = 0;
+ } else {
+ Tcl_GetStringFromObj(result, &clPos);
+ }
+
+ if (numCL >= maxNumCL) {
+ maxNumCL *= 2;
+ clPosition = (int*) ckrealloc ((char*)clPosition,
+ maxNumCL*sizeof(int));
+ }
+ clPosition[numCL] = clPos;
+ numCL ++;
+ }
+ adjust ++;
+ }
+ break;
+
+ case TCL_TOKEN_COMMAND: {
+ Interp *iPtr = (Interp *) interp;
+
+ iPtr->numLevels++;
+ code = TclInterpReady(interp);
+ if (code == TCL_OK) {
+ /*
+ * Test cases: info-30.{6,8,9}
+ */
+
+ int theline;
+ TclAdvanceContinuations (&line, &clNextOuter,
+ tokenPtr->start - outerScript);
+ theline = line + adjust;
+ /* TIP #280: Transfer line information to nested command */
+ code = TclEvalEx(interp, tokenPtr->start+1, tokenPtr->size-2,
+ 0, theline, clNextOuter, outerScript);
+ /*
+ * Restore flag reset by nested eval for future bracketed
+ * commands and their cmdframe setup
+ */
+ if (inFile) {
+ iPtr->evalFlags |= TCL_EVAL_FILE;
+ }
+ }
+ iPtr->numLevels--;
+ appendObj = Tcl_GetObjResult(interp);
+ break;
+ }
+
+ case TCL_TOKEN_VARIABLE: {
+ Tcl_Obj *arrayIndex = NULL;
+ Tcl_Obj *varName = NULL;
+
+ if (tokenPtr->numComponents > 1) {
+ /*
+ * Subst the index part of an array variable reference.
+ */
+
+ code = TclSubstTokens(interp, tokenPtr+2,
+ tokenPtr->numComponents - 1, NULL, line, NULL, NULL);
+ arrayIndex = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(arrayIndex);
+ }
+
+ if (code == TCL_OK) {
+ varName = Tcl_NewStringObj(tokenPtr[1].start,
+ tokenPtr[1].size);
+ appendObj = Tcl_ObjGetVar2(interp, varName, arrayIndex,
+ TCL_LEAVE_ERR_MSG);
+ Tcl_DecrRefCount(varName);
+ if (appendObj == NULL) {
+ code = TCL_ERROR;
+ }
+ }
+
+ switch (code) {
+ case TCL_OK: /* Got value */
+ case TCL_ERROR: /* Already have error message */
+ case TCL_BREAK: /* Will not substitute anyway */
+ case TCL_CONTINUE: /* Will not substitute anyway */
+ break;
+ default:
+ /*
+ * All other return codes, we will subst the result from the
+ * code-throwing evaluation.
+ */
+
+ appendObj = Tcl_GetObjResult(interp);
+ }
+
+ if (arrayIndex != NULL) {
+ Tcl_DecrRefCount(arrayIndex);
+ }
+ count -= tokenPtr->numComponents;
+ tokenPtr += tokenPtr->numComponents;
+ break;
+ }
+
+ default:
+ Tcl_Panic("unexpected token type in TclSubstTokens: %d",
+ tokenPtr->type);
+ }
+
+ if ((code == TCL_BREAK) || (code == TCL_CONTINUE)) {
+ /*
+ * Inhibit substitution.
+ */
+ continue;
+ }
+
+ if (result == NULL) {
+ /*
+ * First pass through. If we have a Tcl_Obj, just use it. If not,
+ * create one from our string.
+ */
+
+ if (appendObj != NULL) {
+ result = appendObj;
+ } else {
+ result = Tcl_NewStringObj(append, appendByteLength);
+ }
+ Tcl_IncrRefCount(result);
+ } else {
+ /*
+ * Subsequent passes. Append to result.
+ */
+
+ if (Tcl_IsShared(result)) {
+ Tcl_DecrRefCount(result);
+ result = Tcl_DuplicateObj(result);
+ Tcl_IncrRefCount(result);
+ }
+ if (appendObj != NULL) {
+ Tcl_AppendObjToObj(result, appendObj);
+ } else {
+ Tcl_AppendToObj(result, append, appendByteLength);
+ }
+ }
+ }
+
+ if (code != TCL_ERROR) { /* Keep error message in result! */
+ if (result != NULL) {
+ Tcl_SetObjResult(interp, result);
+ /*
+ * If the code found continuation lines (which implies that this
+ * word is a literal), then we store the accumulated table of
+ * locations in the thread-global data structure for the bytecode
+ * compiler to find later, assuming that the literal is a script
+ * which will be compiled.
+ */
+
+ if (numCL) {
+ TclContinuationsEnter(result, numCL, clPosition);
+ }
+
+ /*
+ * Release the temp table we used to collect the locations of
+ * continuation lines, if any.
+ */
+
+ if (maxNumCL) {
+ ckfree ((char*) clPosition);
+ }
+ } else {
+ Tcl_ResetResult(interp);
+ }
+ }
+ if (tokensLeftPtr != NULL) {
+ *tokensLeftPtr = count;
+ }
+ if (result != NULL) {
+ Tcl_DecrRefCount(result);
+ }
+ return code;
+}
+
/*
*----------------------------------------------------------------------
*
* CommandComplete --
*
- * This procedure is shared by TclCommandComplete and
- * Tcl_ObjCommandcoComplete; it does all the real work of seeing
- * whether a script is complete
+ * This function is shared by TclCommandComplete and
+ * Tcl_ObjCommandComplete; it does all the real work of seeing whether a
+ * script is complete
*
* Results:
* 1 is returned if the script is complete, 0 if there are open
- * delimiters such as " or (. 1 is also returned if there is a
- * parse error in the script other than unmatched delimiters.
+ * delimiters such as " or (. 1 is also returned if there is a parse
+ * error in the script other than unmatched delimiters.
*
* Side effects:
* None.
@@ -1654,19 +2449,18 @@ Tcl_ParseQuotedString(interp, string, numBytes, parsePtr, append, termPtr)
*----------------------------------------------------------------------
*/
-static int
-CommandComplete(script, numBytes)
- CONST char *script; /* Script to check. */
- int numBytes; /* Number of bytes in script. */
+static inline int
+CommandComplete(
+ const char *script, /* Script to check. */
+ int numBytes) /* Number of bytes in script. */
{
Tcl_Parse parse;
- CONST char *p, *end;
+ const char *p, *end;
int result;
p = script;
end = p + numBytes;
- while (Tcl_ParseCommand((Tcl_Interp *) NULL, p, end - p, 0, &parse)
- == TCL_OK) {
+ while (Tcl_ParseCommand(NULL, p, end - p, 0, &parse) == TCL_OK) {
p = parse.commandStart + parse.commandSize;
if (p >= end) {
break;
@@ -1681,20 +2475,20 @@ CommandComplete(script, numBytes)
Tcl_FreeParse(&parse);
return result;
}
-
+
/*
*----------------------------------------------------------------------
*
* Tcl_CommandComplete --
*
- * Given a partial or complete Tcl script, this procedure
- * determines whether the script is complete in the sense
- * of having matched braces and quotes and brackets.
+ * Given a partial or complete Tcl script, this function determines
+ * whether the script is complete in the sense of having matched braces
+ * and quotes and brackets.
*
* Results:
- * 1 is returned if the script is complete, 0 otherwise.
- * 1 is also returned if there is a parse error in the script
- * other than unmatched delimiters.
+ * 1 is returned if the script is complete, 0 otherwise. 1 is also
+ * returned if there is a parse error in the script other than unmatched
+ * delimiters.
*
* Side effects:
* None.
@@ -1703,20 +2497,20 @@ CommandComplete(script, numBytes)
*/
int
-Tcl_CommandComplete(script)
- CONST char *script; /* Script to check. */
+Tcl_CommandComplete(
+ const char *script) /* Script to check. */
{
return CommandComplete(script, (int) strlen(script));
}
-
+
/*
*----------------------------------------------------------------------
*
* TclObjCommandComplete --
*
- * Given a partial or complete Tcl command in a Tcl object, this
- * procedure determines whether the command is complete in the sense of
- * having matched braces and quotes and brackets.
+ * Given a partial or complete Tcl command in a Tcl object, this function
+ * determines whether the command is complete in the sense of having
+ * matched braces and quotes and brackets.
*
* Results:
* 1 is returned if the command is complete, 0 otherwise.
@@ -1728,24 +2522,23 @@ Tcl_CommandComplete(script)
*/
int
-TclObjCommandComplete(objPtr)
- Tcl_Obj *objPtr; /* Points to object holding script
- * to check. */
+TclObjCommandComplete(
+ Tcl_Obj *objPtr) /* Points to object holding script to
+ * check. */
{
- CONST char *script;
int length;
+ const char *script = Tcl_GetStringFromObj(objPtr, &length);
- script = Tcl_GetStringFromObj(objPtr, &length);
return CommandComplete(script, length);
}
-
+
/*
*----------------------------------------------------------------------
*
* TclIsLocalScalar --
*
- * Check to see if a given string is a legal scalar variable
- * name with no namespace qualifiers or substitutions.
+ * Check to see if a given string is a legal scalar variable name with no
+ * namespace qualifiers or substitutions.
*
* Results:
* Returns 1 if the variable is a local scalar.
@@ -1757,34 +2550,42 @@ TclObjCommandComplete(objPtr)
*/
int
-TclIsLocalScalar(src, len)
- CONST char *src;
- int len;
+TclIsLocalScalar(
+ const char *src,
+ int len)
{
- CONST char *p;
- CONST char *lastChar = src + (len - 1);
+ const char *p;
+ const char *lastChar = src + (len - 1);
- for (p = src; p <= lastChar; p++) {
+ for (p=src ; p<=lastChar ; p++) {
if ((CHAR_TYPE(*p) != TYPE_NORMAL) &&
(CHAR_TYPE(*p) != TYPE_COMMAND_END)) {
/*
- * TCL_COMMAND_END is returned for the last character
- * of the string. By this point we know it isn't
- * an array or namespace reference.
+ * TCL_COMMAND_END is returned for the last character of the
+ * string. By this point we know it isn't an array or namespace
+ * reference.
*/
return 0;
}
- if (*p == '(') {
- if (*lastChar == ')') { /* we have an array element */
+ if (*p == '(') {
+ if (*lastChar == ')') { /* We have an array element */
return 0;
}
} else if (*p == ':') {
- if ((p != lastChar) && *(p+1) == ':') { /* qualified name */
+ if ((p != lastChar) && *(p+1) == ':') { /* qualified name */
return 0;
}
}
}
-
+
return 1;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclParseExpr.c b/generic/tclParseExpr.c
deleted file mode 100644
index 9fdf8e5..0000000
--- a/generic/tclParseExpr.c
+++ /dev/null
@@ -1,2083 +0,0 @@
-/*
- * tclParseExpr.c --
- *
- * This file contains procedures that parse Tcl expressions. They
- * do so in a general-purpose fashion that can be used for many
- * different purposes, including compilation, direct execution,
- * code analysis, etc.
- *
- * Copyright (c) 1997 Sun Microsystems, Inc.
- * Copyright (c) 1998-2000 by Scriptics Corporation.
- * Contributions from Don Porter, NIST, 2002. (not subject to US copyright)
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include "tclInt.h"
-
-/*
- * The stuff below is a bit of a hack so that this file can be used in
- * environments that include no UNIX, i.e. no errno: just arrange to use
- * the errno from tclExecute.c here.
- */
-
-#ifndef TCL_GENERIC_ONLY
-#include "tclPort.h"
-#else
-#define NO_ERRNO_H
-#endif
-
-#ifdef NO_ERRNO_H
-extern int errno; /* Use errno from tclExecute.c. */
-#define ERANGE 34
-#endif
-
-/*
- * Boolean variable that controls whether expression parse tracing
- * is enabled.
- */
-
-#ifdef TCL_COMPILE_DEBUG
-static int traceParseExpr = 0;
-#endif /* TCL_COMPILE_DEBUG */
-
-/*
- * The ParseInfo structure holds state while parsing an expression.
- * A pointer to an ParseInfo record is passed among the routines in
- * this module.
- */
-
-typedef struct ParseInfo {
- Tcl_Parse *parsePtr; /* Points to structure to fill in with
- * information about the expression. */
- int lexeme; /* Type of last lexeme scanned in expr.
- * See below for definitions. Corresponds to
- * size characters beginning at start. */
- CONST char *start; /* First character in lexeme. */
- int size; /* Number of bytes in lexeme. */
- CONST char *next; /* Position of the next character to be
- * scanned in the expression string. */
- CONST char *prevEnd; /* Points to the character just after the
- * last one in the previous lexeme. Used to
- * compute size of subexpression tokens. */
- CONST char *originalExpr; /* Points to the start of the expression
- * originally passed to Tcl_ParseExpr. */
- CONST char *lastChar; /* Points just after last byte of expr. */
-} ParseInfo;
-
-/*
- * Definitions of the different lexemes that appear in expressions. The
- * order of these must match the corresponding entries in the
- * operatorStrings array below.
- *
- * Basic lexemes:
- */
-
-#define LITERAL 0
-#define FUNC_NAME 1
-#define OPEN_BRACKET 2
-#define OPEN_BRACE 3
-#define OPEN_PAREN 4
-#define CLOSE_PAREN 5
-#define DOLLAR 6
-#define QUOTE 7
-#define COMMA 8
-#define END 9
-#define UNKNOWN 10
-#define UNKNOWN_CHAR 11
-
-/*
- * Binary numeric operators:
- */
-
-#define MULT 12
-#define DIVIDE 13
-#define MOD 14
-#define PLUS 15
-#define MINUS 16
-#define LEFT_SHIFT 17
-#define RIGHT_SHIFT 18
-#define LESS 19
-#define GREATER 20
-#define LEQ 21
-#define GEQ 22
-#define EQUAL 23
-#define NEQ 24
-#define BIT_AND 25
-#define BIT_XOR 26
-#define BIT_OR 27
-#define AND 28
-#define OR 29
-#define QUESTY 30
-#define COLON 31
-
-/*
- * Unary operators. Unary minus and plus are represented by the (binary)
- * lexemes MINUS and PLUS.
- */
-
-#define NOT 32
-#define BIT_NOT 33
-
-/*
- * Binary string operators:
- */
-
-#define STREQ 34
-#define STRNEQ 35
-
-/*
- * Mapping from lexemes to strings; used for debugging messages. These
- * entries must match the order and number of the lexeme definitions above.
- */
-
-static char *lexemeStrings[] = {
- "LITERAL", "FUNCNAME",
- "[", "{", "(", ")", "$", "\"", ",", "END", "UNKNOWN", "UNKNOWN_CHAR",
- "*", "/", "%", "+", "-",
- "<<", ">>", "<", ">", "<=", ">=", "==", "!=",
- "&", "^", "|", "&&", "||", "?", ":",
- "!", "~", "eq", "ne",
-};
-
-/*
- * Declarations for local procedures to this file:
- */
-
-static int GetLexeme _ANSI_ARGS_((ParseInfo *infoPtr));
-static void LogSyntaxError _ANSI_ARGS_((ParseInfo *infoPtr,
- CONST char *extraInfo));
-static int ParseAddExpr _ANSI_ARGS_((ParseInfo *infoPtr));
-static int ParseBitAndExpr _ANSI_ARGS_((ParseInfo *infoPtr));
-static int ParseBitOrExpr _ANSI_ARGS_((ParseInfo *infoPtr));
-static int ParseBitXorExpr _ANSI_ARGS_((ParseInfo *infoPtr));
-static int ParseCondExpr _ANSI_ARGS_((ParseInfo *infoPtr));
-static int ParseEqualityExpr _ANSI_ARGS_((ParseInfo *infoPtr));
-static int ParseLandExpr _ANSI_ARGS_((ParseInfo *infoPtr));
-static int ParseLorExpr _ANSI_ARGS_((ParseInfo *infoPtr));
-static int ParseMaxDoubleLength _ANSI_ARGS_((CONST char *string,
- CONST char *end));
-static int ParseMultiplyExpr _ANSI_ARGS_((ParseInfo *infoPtr));
-static int ParsePrimaryExpr _ANSI_ARGS_((ParseInfo *infoPtr));
-static int ParseRelationalExpr _ANSI_ARGS_((ParseInfo *infoPtr));
-static int ParseShiftExpr _ANSI_ARGS_((ParseInfo *infoPtr));
-static int ParseUnaryExpr _ANSI_ARGS_((ParseInfo *infoPtr));
-static void PrependSubExprTokens _ANSI_ARGS_((CONST char *op,
- int opBytes, CONST char *src, int srcBytes,
- int firstIndex, ParseInfo *infoPtr));
-
-/*
- * Macro used to debug the execution of the recursive descent parser used
- * to parse expressions.
- */
-
-#ifdef TCL_COMPILE_DEBUG
-#define HERE(production, level) \
- if (traceParseExpr) { \
- fprintf(stderr, "%*s%s: lexeme=%s, next=\"%.20s\"\n", \
- (level), " ", (production), \
- lexemeStrings[infoPtr->lexeme], infoPtr->next); \
- }
-#else
-#define HERE(production, level)
-#endif /* TCL_COMPILE_DEBUG */
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_ParseExpr --
- *
- * Given a string, this procedure parses the first Tcl expression
- * in the string and returns information about the structure of
- * the expression. This procedure is the top-level interface to the
- * the expression parsing module. No more that numBytes bytes will
- * be scanned.
- *
- * Results:
- * The return value is TCL_OK if the command was parsed successfully
- * and TCL_ERROR otherwise. If an error occurs and interp isn't NULL
- * then an error message is left in its result. On a successful return,
- * parsePtr is filled in with information about the expression that
- * was parsed.
- *
- * Side effects:
- * If there is insufficient space in parsePtr to hold all the
- * information about the expression, then additional space is
- * malloc-ed. If the procedure returns TCL_OK then the caller must
- * eventually invoke Tcl_FreeParse to release any additional space
- * that was allocated.
- *
- *----------------------------------------------------------------------
- */
-
-int
-Tcl_ParseExpr(interp, string, numBytes, parsePtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- CONST char *string; /* The source string to parse. */
- int numBytes; /* Number of bytes in string. If < 0, the
- * string consists of all bytes up to the
- * first null character. */
- Tcl_Parse *parsePtr; /* Structure to fill with information about
- * the parsed expression; any previous
- * information in the structure is
- * ignored. */
-{
- ParseInfo info;
- int code;
-
- if (numBytes < 0) {
- numBytes = (string? strlen(string) : 0);
- }
-#ifdef TCL_COMPILE_DEBUG
- if (traceParseExpr) {
- fprintf(stderr, "Tcl_ParseExpr: string=\"%.*s\"\n",
- numBytes, string);
- }
-#endif /* TCL_COMPILE_DEBUG */
-
- parsePtr->commentStart = NULL;
- parsePtr->commentSize = 0;
- parsePtr->commandStart = NULL;
- parsePtr->commandSize = 0;
- parsePtr->numWords = 0;
- parsePtr->tokenPtr = parsePtr->staticTokens;
- parsePtr->numTokens = 0;
- parsePtr->tokensAvailable = NUM_STATIC_TOKENS;
- parsePtr->string = string;
- parsePtr->end = (string + numBytes);
- parsePtr->interp = interp;
- parsePtr->term = string;
- parsePtr->incomplete = 0;
-
- /*
- * Initialize the ParseInfo structure that holds state while parsing
- * the expression.
- */
-
- info.parsePtr = parsePtr;
- info.lexeme = UNKNOWN;
- info.start = NULL;
- info.size = 0;
- info.next = string;
- info.prevEnd = string;
- info.originalExpr = string;
- info.lastChar = (string + numBytes); /* just after last char of expr */
-
- /*
- * Get the first lexeme then parse the expression.
- */
-
- code = GetLexeme(&info);
- if (code != TCL_OK) {
- goto error;
- }
- code = ParseCondExpr(&info);
- if (code != TCL_OK) {
- goto error;
- }
- if (info.lexeme != END) {
- LogSyntaxError(&info, "extra tokens at end of expression");
- goto error;
- }
- return TCL_OK;
-
- error:
- if (parsePtr->tokenPtr != parsePtr->staticTokens) {
- ckfree((char *) parsePtr->tokenPtr);
- }
- return TCL_ERROR;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ParseCondExpr --
- *
- * This procedure parses a Tcl conditional expression:
- * condExpr ::= lorExpr ['?' condExpr ':' condExpr]
- *
- * Note that this is the topmost recursive-descent parsing routine used
- * by Tcl_ParseExpr to parse expressions. This avoids an extra procedure
- * call since such a procedure would only return the result of calling
- * ParseCondExpr. Other recursive-descent procedures that need to parse
- * complete expressions also call ParseCondExpr.
- *
- * Results:
- * The return value is TCL_OK on a successful parse and TCL_ERROR
- * on failure. If TCL_ERROR is returned, then the interpreter's result
- * contains an error message.
- *
- * Side effects:
- * If there is insufficient space in parsePtr to hold all the
- * information about the subexpression, then additional space is
- * malloc-ed.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ParseCondExpr(infoPtr)
- ParseInfo *infoPtr; /* Holds the parse state for the
- * expression being parsed. */
-{
- Tcl_Parse *parsePtr = infoPtr->parsePtr;
- Tcl_Token *tokenPtr, *firstTokenPtr, *condTokenPtr;
- int firstIndex, numToMove, code;
- CONST char *srcStart;
-
- HERE("condExpr", 1);
- srcStart = infoPtr->start;
- firstIndex = parsePtr->numTokens;
-
- code = ParseLorExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- if (infoPtr->lexeme == QUESTY) {
- /*
- * Emit two tokens: one TCL_TOKEN_SUB_EXPR token for the entire
- * conditional expression, and a TCL_TOKEN_OPERATOR token for
- * the "?" operator. Note that these two tokens must be inserted
- * before the LOR operand tokens generated above.
- */
-
- if ((parsePtr->numTokens + 1) >= parsePtr->tokensAvailable) {
- TclExpandTokenArray(parsePtr);
- }
- firstTokenPtr = &parsePtr->tokenPtr[firstIndex];
- tokenPtr = (firstTokenPtr + 2);
- numToMove = (parsePtr->numTokens - firstIndex);
- memmove((VOID *) tokenPtr, (VOID *) firstTokenPtr,
- (size_t) (numToMove * sizeof(Tcl_Token)));
- parsePtr->numTokens += 2;
-
- tokenPtr = firstTokenPtr;
- tokenPtr->type = TCL_TOKEN_SUB_EXPR;
- tokenPtr->start = srcStart;
-
- tokenPtr++;
- tokenPtr->type = TCL_TOKEN_OPERATOR;
- tokenPtr->start = infoPtr->start;
- tokenPtr->size = 1;
- tokenPtr->numComponents = 0;
-
- /*
- * Skip over the '?'.
- */
-
- code = GetLexeme(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- /*
- * Parse the "then" expression.
- */
-
- code = ParseCondExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
- if (infoPtr->lexeme != COLON) {
- LogSyntaxError(infoPtr, "missing colon from ternary conditional");
- return TCL_ERROR;
- }
- code = GetLexeme(infoPtr); /* skip over the ':' */
- if (code != TCL_OK) {
- return code;
- }
-
- /*
- * Parse the "else" expression.
- */
-
- code = ParseCondExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- /*
- * Now set the size-related fields in the '?' subexpression token.
- */
-
- condTokenPtr = &parsePtr->tokenPtr[firstIndex];
- condTokenPtr->size = (infoPtr->prevEnd - srcStart);
- condTokenPtr->numComponents = parsePtr->numTokens - (firstIndex+1);
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ParseLorExpr --
- *
- * This procedure parses a Tcl logical or expression:
- * lorExpr ::= landExpr {'||' landExpr}
- *
- * Results:
- * The return value is TCL_OK on a successful parse and TCL_ERROR
- * on failure. If TCL_ERROR is returned, then the interpreter's result
- * contains an error message.
- *
- * Side effects:
- * If there is insufficient space in parsePtr to hold all the
- * information about the subexpression, then additional space is
- * malloc-ed.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ParseLorExpr(infoPtr)
- ParseInfo *infoPtr; /* Holds the parse state for the
- * expression being parsed. */
-{
- Tcl_Parse *parsePtr = infoPtr->parsePtr;
- int firstIndex, code;
- CONST char *srcStart, *operator;
-
- HERE("lorExpr", 2);
- srcStart = infoPtr->start;
- firstIndex = parsePtr->numTokens;
-
- code = ParseLandExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- while (infoPtr->lexeme == OR) {
- operator = infoPtr->start;
- code = GetLexeme(infoPtr); /* skip over the '||' */
- if (code != TCL_OK) {
- return code;
- }
- code = ParseLandExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- /*
- * Generate tokens for the LOR subexpression and the '||' operator.
- */
-
- PrependSubExprTokens(operator, 2, srcStart,
- (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ParseLandExpr --
- *
- * This procedure parses a Tcl logical and expression:
- * landExpr ::= bitOrExpr {'&&' bitOrExpr}
- *
- * Results:
- * The return value is TCL_OK on a successful parse and TCL_ERROR
- * on failure. If TCL_ERROR is returned, then the interpreter's result
- * contains an error message.
- *
- * Side effects:
- * If there is insufficient space in parsePtr to hold all the
- * information about the subexpression, then additional space is
- * malloc-ed.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ParseLandExpr(infoPtr)
- ParseInfo *infoPtr; /* Holds the parse state for the
- * expression being parsed. */
-{
- Tcl_Parse *parsePtr = infoPtr->parsePtr;
- int firstIndex, code;
- CONST char *srcStart, *operator;
-
- HERE("landExpr", 3);
- srcStart = infoPtr->start;
- firstIndex = parsePtr->numTokens;
-
- code = ParseBitOrExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- while (infoPtr->lexeme == AND) {
- operator = infoPtr->start;
- code = GetLexeme(infoPtr); /* skip over the '&&' */
- if (code != TCL_OK) {
- return code;
- }
- code = ParseBitOrExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- /*
- * Generate tokens for the LAND subexpression and the '&&' operator.
- */
-
- PrependSubExprTokens(operator, 2, srcStart,
- (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ParseBitOrExpr --
- *
- * This procedure parses a Tcl bitwise or expression:
- * bitOrExpr ::= bitXorExpr {'|' bitXorExpr}
- *
- * Results:
- * The return value is TCL_OK on a successful parse and TCL_ERROR
- * on failure. If TCL_ERROR is returned, then the interpreter's result
- * contains an error message.
- *
- * Side effects:
- * If there is insufficient space in parsePtr to hold all the
- * information about the subexpression, then additional space is
- * malloc-ed.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ParseBitOrExpr(infoPtr)
- ParseInfo *infoPtr; /* Holds the parse state for the
- * expression being parsed. */
-{
- Tcl_Parse *parsePtr = infoPtr->parsePtr;
- int firstIndex, code;
- CONST char *srcStart, *operator;
-
- HERE("bitOrExpr", 4);
- srcStart = infoPtr->start;
- firstIndex = parsePtr->numTokens;
-
- code = ParseBitXorExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- while (infoPtr->lexeme == BIT_OR) {
- operator = infoPtr->start;
- code = GetLexeme(infoPtr); /* skip over the '|' */
- if (code != TCL_OK) {
- return code;
- }
-
- code = ParseBitXorExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- /*
- * Generate tokens for the BITOR subexpression and the '|' operator.
- */
-
- PrependSubExprTokens(operator, 1, srcStart,
- (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ParseBitXorExpr --
- *
- * This procedure parses a Tcl bitwise exclusive or expression:
- * bitXorExpr ::= bitAndExpr {'^' bitAndExpr}
- *
- * Results:
- * The return value is TCL_OK on a successful parse and TCL_ERROR
- * on failure. If TCL_ERROR is returned, then the interpreter's result
- * contains an error message.
- *
- * Side effects:
- * If there is insufficient space in parsePtr to hold all the
- * information about the subexpression, then additional space is
- * malloc-ed.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ParseBitXorExpr(infoPtr)
- ParseInfo *infoPtr; /* Holds the parse state for the
- * expression being parsed. */
-{
- Tcl_Parse *parsePtr = infoPtr->parsePtr;
- int firstIndex, code;
- CONST char *srcStart, *operator;
-
- HERE("bitXorExpr", 5);
- srcStart = infoPtr->start;
- firstIndex = parsePtr->numTokens;
-
- code = ParseBitAndExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- while (infoPtr->lexeme == BIT_XOR) {
- operator = infoPtr->start;
- code = GetLexeme(infoPtr); /* skip over the '^' */
- if (code != TCL_OK) {
- return code;
- }
-
- code = ParseBitAndExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- /*
- * Generate tokens for the XOR subexpression and the '^' operator.
- */
-
- PrependSubExprTokens(operator, 1, srcStart,
- (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ParseBitAndExpr --
- *
- * This procedure parses a Tcl bitwise and expression:
- * bitAndExpr ::= equalityExpr {'&' equalityExpr}
- *
- * Results:
- * The return value is TCL_OK on a successful parse and TCL_ERROR
- * on failure. If TCL_ERROR is returned, then the interpreter's result
- * contains an error message.
- *
- * Side effects:
- * If there is insufficient space in parsePtr to hold all the
- * information about the subexpression, then additional space is
- * malloc-ed.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ParseBitAndExpr(infoPtr)
- ParseInfo *infoPtr; /* Holds the parse state for the
- * expression being parsed. */
-{
- Tcl_Parse *parsePtr = infoPtr->parsePtr;
- int firstIndex, code;
- CONST char *srcStart, *operator;
-
- HERE("bitAndExpr", 6);
- srcStart = infoPtr->start;
- firstIndex = parsePtr->numTokens;
-
- code = ParseEqualityExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- while (infoPtr->lexeme == BIT_AND) {
- operator = infoPtr->start;
- code = GetLexeme(infoPtr); /* skip over the '&' */
- if (code != TCL_OK) {
- return code;
- }
- code = ParseEqualityExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- /*
- * Generate tokens for the BITAND subexpression and '&' operator.
- */
-
- PrependSubExprTokens(operator, 1, srcStart,
- (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ParseEqualityExpr --
- *
- * This procedure parses a Tcl equality (inequality) expression:
- * equalityExpr ::= relationalExpr
- * {('==' | '!=' | 'ne' | 'eq') relationalExpr}
- *
- * Results:
- * The return value is TCL_OK on a successful parse and TCL_ERROR
- * on failure. If TCL_ERROR is returned, then the interpreter's result
- * contains an error message.
- *
- * Side effects:
- * If there is insufficient space in parsePtr to hold all the
- * information about the subexpression, then additional space is
- * malloc-ed.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ParseEqualityExpr(infoPtr)
- ParseInfo *infoPtr; /* Holds the parse state for the
- * expression being parsed. */
-{
- Tcl_Parse *parsePtr = infoPtr->parsePtr;
- int firstIndex, lexeme, code;
- CONST char *srcStart, *operator;
-
- HERE("equalityExpr", 7);
- srcStart = infoPtr->start;
- firstIndex = parsePtr->numTokens;
-
- code = ParseRelationalExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- lexeme = infoPtr->lexeme;
- while ((lexeme == EQUAL) || (lexeme == NEQ)
- || (lexeme == STREQ) || (lexeme == STRNEQ)) {
- operator = infoPtr->start;
- code = GetLexeme(infoPtr); /* skip over ==, !=, 'eq' or 'ne' */
- if (code != TCL_OK) {
- return code;
- }
- code = ParseRelationalExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- /*
- * Generate tokens for the subexpression and '==', '!=', 'eq' or 'ne'
- * operator.
- */
-
- PrependSubExprTokens(operator, 2, srcStart,
- (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
- lexeme = infoPtr->lexeme;
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ParseRelationalExpr --
- *
- * This procedure parses a Tcl relational expression:
- * relationalExpr ::= shiftExpr {('<' | '>' | '<=' | '>=') shiftExpr}
- *
- * Results:
- * The return value is TCL_OK on a successful parse and TCL_ERROR
- * on failure. If TCL_ERROR is returned, then the interpreter's result
- * contains an error message.
- *
- * Side effects:
- * If there is insufficient space in parsePtr to hold all the
- * information about the subexpression, then additional space is
- * malloc-ed.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ParseRelationalExpr(infoPtr)
- ParseInfo *infoPtr; /* Holds the parse state for the
- * expression being parsed. */
-{
- Tcl_Parse *parsePtr = infoPtr->parsePtr;
- int firstIndex, lexeme, operatorSize, code;
- CONST char *srcStart, *operator;
-
- HERE("relationalExpr", 8);
- srcStart = infoPtr->start;
- firstIndex = parsePtr->numTokens;
-
- code = ParseShiftExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- lexeme = infoPtr->lexeme;
- while ((lexeme == LESS) || (lexeme == GREATER) || (lexeme == LEQ)
- || (lexeme == GEQ)) {
- operator = infoPtr->start;
- if ((lexeme == LEQ) || (lexeme == GEQ)) {
- operatorSize = 2;
- } else {
- operatorSize = 1;
- }
- code = GetLexeme(infoPtr); /* skip over the operator */
- if (code != TCL_OK) {
- return code;
- }
- code = ParseShiftExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- /*
- * Generate tokens for the subexpression and the operator.
- */
-
- PrependSubExprTokens(operator, operatorSize, srcStart,
- (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
- lexeme = infoPtr->lexeme;
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ParseShiftExpr --
- *
- * This procedure parses a Tcl shift expression:
- * shiftExpr ::= addExpr {('<<' | '>>') addExpr}
- *
- * Results:
- * The return value is TCL_OK on a successful parse and TCL_ERROR
- * on failure. If TCL_ERROR is returned, then the interpreter's result
- * contains an error message.
- *
- * Side effects:
- * If there is insufficient space in parsePtr to hold all the
- * information about the subexpression, then additional space is
- * malloc-ed.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ParseShiftExpr(infoPtr)
- ParseInfo *infoPtr; /* Holds the parse state for the
- * expression being parsed. */
-{
- Tcl_Parse *parsePtr = infoPtr->parsePtr;
- int firstIndex, lexeme, code;
- CONST char *srcStart, *operator;
-
- HERE("shiftExpr", 9);
- srcStart = infoPtr->start;
- firstIndex = parsePtr->numTokens;
-
- code = ParseAddExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- lexeme = infoPtr->lexeme;
- while ((lexeme == LEFT_SHIFT) || (lexeme == RIGHT_SHIFT)) {
- operator = infoPtr->start;
- code = GetLexeme(infoPtr); /* skip over << or >> */
- if (code != TCL_OK) {
- return code;
- }
- code = ParseAddExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- /*
- * Generate tokens for the subexpression and '<<' or '>>' operator.
- */
-
- PrependSubExprTokens(operator, 2, srcStart,
- (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
- lexeme = infoPtr->lexeme;
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ParseAddExpr --
- *
- * This procedure parses a Tcl addition expression:
- * addExpr ::= multiplyExpr {('+' | '-') multiplyExpr}
- *
- * Results:
- * The return value is TCL_OK on a successful parse and TCL_ERROR
- * on failure. If TCL_ERROR is returned, then the interpreter's result
- * contains an error message.
- *
- * Side effects:
- * If there is insufficient space in parsePtr to hold all the
- * information about the subexpression, then additional space is
- * malloc-ed.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ParseAddExpr(infoPtr)
- ParseInfo *infoPtr; /* Holds the parse state for the
- * expression being parsed. */
-{
- Tcl_Parse *parsePtr = infoPtr->parsePtr;
- int firstIndex, lexeme, code;
- CONST char *srcStart, *operator;
-
- HERE("addExpr", 10);
- srcStart = infoPtr->start;
- firstIndex = parsePtr->numTokens;
-
- code = ParseMultiplyExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- lexeme = infoPtr->lexeme;
- while ((lexeme == PLUS) || (lexeme == MINUS)) {
- operator = infoPtr->start;
- code = GetLexeme(infoPtr); /* skip over + or - */
- if (code != TCL_OK) {
- return code;
- }
- code = ParseMultiplyExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- /*
- * Generate tokens for the subexpression and '+' or '-' operator.
- */
-
- PrependSubExprTokens(operator, 1, srcStart,
- (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
- lexeme = infoPtr->lexeme;
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ParseMultiplyExpr --
- *
- * This procedure parses a Tcl multiply expression:
- * multiplyExpr ::= unaryExpr {('*' | '/' | '%') unaryExpr}
- *
- * Results:
- * The return value is TCL_OK on a successful parse and TCL_ERROR
- * on failure. If TCL_ERROR is returned, then the interpreter's result
- * contains an error message.
- *
- * Side effects:
- * If there is insufficient space in parsePtr to hold all the
- * information about the subexpression, then additional space is
- * malloc-ed.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ParseMultiplyExpr(infoPtr)
- ParseInfo *infoPtr; /* Holds the parse state for the
- * expression being parsed. */
-{
- Tcl_Parse *parsePtr = infoPtr->parsePtr;
- int firstIndex, lexeme, code;
- CONST char *srcStart, *operator;
-
- HERE("multiplyExpr", 11);
- srcStart = infoPtr->start;
- firstIndex = parsePtr->numTokens;
-
- code = ParseUnaryExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- lexeme = infoPtr->lexeme;
- while ((lexeme == MULT) || (lexeme == DIVIDE) || (lexeme == MOD)) {
- operator = infoPtr->start;
- code = GetLexeme(infoPtr); /* skip over * or / or % */
- if (code != TCL_OK) {
- return code;
- }
- code = ParseUnaryExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- /*
- * Generate tokens for the subexpression and * or / or % operator.
- */
-
- PrependSubExprTokens(operator, 1, srcStart,
- (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
- lexeme = infoPtr->lexeme;
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ParseUnaryExpr --
- *
- * This procedure parses a Tcl unary expression:
- * unaryExpr ::= ('+' | '-' | '~' | '!') unaryExpr | primaryExpr
- *
- * Results:
- * The return value is TCL_OK on a successful parse and TCL_ERROR
- * on failure. If TCL_ERROR is returned, then the interpreter's result
- * contains an error message.
- *
- * Side effects:
- * If there is insufficient space in parsePtr to hold all the
- * information about the subexpression, then additional space is
- * malloc-ed.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ParseUnaryExpr(infoPtr)
- ParseInfo *infoPtr; /* Holds the parse state for the
- * expression being parsed. */
-{
- Tcl_Parse *parsePtr = infoPtr->parsePtr;
- int firstIndex, lexeme, code;
- CONST char *srcStart, *operator;
-
- HERE("unaryExpr", 12);
- srcStart = infoPtr->start;
- firstIndex = parsePtr->numTokens;
-
- lexeme = infoPtr->lexeme;
- if ((lexeme == PLUS) || (lexeme == MINUS) || (lexeme == BIT_NOT)
- || (lexeme == NOT)) {
- operator = infoPtr->start;
- code = GetLexeme(infoPtr); /* skip over the unary operator */
- if (code != TCL_OK) {
- return code;
- }
- code = ParseUnaryExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- /*
- * Generate tokens for the subexpression and the operator.
- */
-
- PrependSubExprTokens(operator, 1, srcStart,
- (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
- } else { /* must be a primaryExpr */
- code = ParsePrimaryExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ParsePrimaryExpr --
- *
- * This procedure parses a Tcl primary expression:
- * primaryExpr ::= literal | varReference | quotedString |
- * '[' command ']' | mathFuncCall | '(' condExpr ')'
- *
- * Results:
- * The return value is TCL_OK on a successful parse and TCL_ERROR
- * on failure. If TCL_ERROR is returned, then the interpreter's result
- * contains an error message.
- *
- * Side effects:
- * If there is insufficient space in parsePtr to hold all the
- * information about the subexpression, then additional space is
- * malloc-ed.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ParsePrimaryExpr(infoPtr)
- ParseInfo *infoPtr; /* Holds the parse state for the
- * expression being parsed. */
-{
- Tcl_Parse *parsePtr = infoPtr->parsePtr;
- Tcl_Interp *interp = parsePtr->interp;
- Tcl_Token *tokenPtr, *exprTokenPtr;
- Tcl_Parse nested;
- CONST char *dollarPtr, *stringStart, *termPtr, *src;
- int lexeme, exprIndex, firstIndex, numToMove, code;
-
- /*
- * We simply recurse on parenthesized subexpressions.
- */
-
- HERE("primaryExpr", 13);
- lexeme = infoPtr->lexeme;
- if (lexeme == OPEN_PAREN) {
- code = GetLexeme(infoPtr); /* skip over the '(' */
- if (code != TCL_OK) {
- return code;
- }
- code = ParseCondExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
- if (infoPtr->lexeme != CLOSE_PAREN) {
- LogSyntaxError(infoPtr, "looking for close parenthesis");
- return TCL_ERROR;
- }
- code = GetLexeme(infoPtr); /* skip over the ')' */
- if (code != TCL_OK) {
- return code;
- }
- return TCL_OK;
- }
-
- /*
- * Start a TCL_TOKEN_SUB_EXPR token for the primary.
- */
-
- if (parsePtr->numTokens == parsePtr->tokensAvailable) {
- TclExpandTokenArray(parsePtr);
- }
- exprIndex = parsePtr->numTokens;
- exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
- exprTokenPtr->type = TCL_TOKEN_SUB_EXPR;
- exprTokenPtr->start = infoPtr->start;
- parsePtr->numTokens++;
-
- /*
- * Process the primary then finish setting the fields of the
- * TCL_TOKEN_SUB_EXPR token. Note that we can't use the pointer now
- * stored in "exprTokenPtr" in the code below since the token array
- * might be reallocated.
- */
-
- firstIndex = parsePtr->numTokens;
- switch (lexeme) {
- case LITERAL:
- /*
- * Int or double number.
- */
-
- tokenizeLiteral:
- if (parsePtr->numTokens == parsePtr->tokensAvailable) {
- TclExpandTokenArray(parsePtr);
- }
- tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
- tokenPtr->type = TCL_TOKEN_TEXT;
- tokenPtr->start = infoPtr->start;
- tokenPtr->size = infoPtr->size;
- tokenPtr->numComponents = 0;
- parsePtr->numTokens++;
-
- exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
- exprTokenPtr->size = infoPtr->size;
- exprTokenPtr->numComponents = 1;
- break;
-
- case DOLLAR:
- /*
- * $var variable reference.
- */
-
- dollarPtr = (infoPtr->next - 1);
- code = Tcl_ParseVarName(interp, dollarPtr,
- (infoPtr->lastChar - dollarPtr), parsePtr, 1);
- if (code != TCL_OK) {
- return code;
- }
- infoPtr->next = dollarPtr + parsePtr->tokenPtr[firstIndex].size;
-
- exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
- exprTokenPtr->size = parsePtr->tokenPtr[firstIndex].size;
- exprTokenPtr->numComponents =
- (parsePtr->tokenPtr[firstIndex].numComponents + 1);
- break;
-
- case QUOTE:
- /*
- * '"' string '"'
- */
-
- stringStart = infoPtr->next;
- code = Tcl_ParseQuotedString(interp, infoPtr->start,
- (infoPtr->lastChar - stringStart), parsePtr, 1, &termPtr);
- if (code != TCL_OK) {
- return code;
- }
- infoPtr->next = termPtr;
-
- exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
- exprTokenPtr->size = (termPtr - exprTokenPtr->start);
- exprTokenPtr->numComponents = parsePtr->numTokens - firstIndex;
-
- /*
- * If parsing the quoted string resulted in more than one token,
- * insert a TCL_TOKEN_WORD token before them. This indicates that
- * the quoted string represents a concatenation of multiple tokens.
- */
-
- if (exprTokenPtr->numComponents > 1) {
- if (parsePtr->numTokens >= parsePtr->tokensAvailable) {
- TclExpandTokenArray(parsePtr);
- }
- tokenPtr = &parsePtr->tokenPtr[firstIndex];
- numToMove = (parsePtr->numTokens - firstIndex);
- memmove((VOID *) (tokenPtr + 1), (VOID *) tokenPtr,
- (size_t) (numToMove * sizeof(Tcl_Token)));
- parsePtr->numTokens++;
-
- exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
- exprTokenPtr->numComponents++;
-
- tokenPtr->type = TCL_TOKEN_WORD;
- tokenPtr->start = exprTokenPtr->start;
- tokenPtr->size = exprTokenPtr->size;
- tokenPtr->numComponents = (exprTokenPtr->numComponents - 1);
- }
- break;
-
- case OPEN_BRACKET:
- /*
- * '[' command {command} ']'
- */
-
- if (parsePtr->numTokens == parsePtr->tokensAvailable) {
- TclExpandTokenArray(parsePtr);
- }
- tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
- tokenPtr->type = TCL_TOKEN_COMMAND;
- tokenPtr->start = infoPtr->start;
- tokenPtr->numComponents = 0;
- parsePtr->numTokens++;
-
- /*
- * Call Tcl_ParseCommand repeatedly to parse the nested command(s)
- * to find their end, then throw away that parse information.
- */
-
- src = infoPtr->next;
- while (1) {
- if (Tcl_ParseCommand(interp, src, (parsePtr->end - src), 1,
- &nested) != TCL_OK) {
- parsePtr->term = nested.term;
- parsePtr->errorType = nested.errorType;
- parsePtr->incomplete = nested.incomplete;
- return TCL_ERROR;
- }
- src = (nested.commandStart + nested.commandSize);
-
- /*
- * This is equivalent to Tcl_FreeParse(&nested), but
- * presumably inlined here for sake of runtime optimization
- */
-
- if (nested.tokenPtr != nested.staticTokens) {
- ckfree((char *) nested.tokenPtr);
- }
-
- /*
- * Check for the closing ']' that ends the command substitution.
- * It must have been the last character of the parsed command.
- */
-
- if ((nested.term < parsePtr->end) && (*nested.term == ']')
- && !nested.incomplete) {
- break;
- }
- if (src == parsePtr->end) {
- if (parsePtr->interp != NULL) {
- Tcl_SetResult(interp, "missing close-bracket",
- TCL_STATIC);
- }
- parsePtr->term = tokenPtr->start;
- parsePtr->errorType = TCL_PARSE_MISSING_BRACKET;
- parsePtr->incomplete = 1;
- return TCL_ERROR;
- }
- }
- tokenPtr->size = (src - tokenPtr->start);
- infoPtr->next = src;
-
- exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
- exprTokenPtr->size = (src - tokenPtr->start);
- exprTokenPtr->numComponents = 1;
- break;
-
- case OPEN_BRACE:
- /*
- * '{' string '}'
- */
-
- code = Tcl_ParseBraces(interp, infoPtr->start,
- (infoPtr->lastChar - infoPtr->start), parsePtr, 1,
- &termPtr);
- if (code != TCL_OK) {
- return code;
- }
- infoPtr->next = termPtr;
-
- exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
- exprTokenPtr->size = (termPtr - infoPtr->start);
- exprTokenPtr->numComponents = parsePtr->numTokens - firstIndex;
-
- /*
- * If parsing the braced string resulted in more than one token,
- * insert a TCL_TOKEN_WORD token before them. This indicates that
- * the braced string represents a concatenation of multiple tokens.
- */
-
- if (exprTokenPtr->numComponents > 1) {
- if (parsePtr->numTokens >= parsePtr->tokensAvailable) {
- TclExpandTokenArray(parsePtr);
- }
- tokenPtr = &parsePtr->tokenPtr[firstIndex];
- numToMove = (parsePtr->numTokens - firstIndex);
- memmove((VOID *) (tokenPtr + 1), (VOID *) tokenPtr,
- (size_t) (numToMove * sizeof(Tcl_Token)));
- parsePtr->numTokens++;
-
- exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
- exprTokenPtr->numComponents++;
-
- tokenPtr->type = TCL_TOKEN_WORD;
- tokenPtr->start = exprTokenPtr->start;
- tokenPtr->size = exprTokenPtr->size;
- tokenPtr->numComponents = exprTokenPtr->numComponents-1;
- }
- break;
-
-/*
- * Disable attempt to support functions named "eq" or "ne". This
- * is unworkable in the Tcl 8.4.* releases. See Tcl Bugs 1971879
- * and 1201589.
- *
- case STREQ:
- case STRNEQ:
-*/
- case FUNC_NAME: {
- /*
- * math_func '(' expr {',' expr} ')'
- */
-
- ParseInfo savedInfo = *infoPtr;
-
- code = GetLexeme(infoPtr); /* skip over function name */
- if (code != TCL_OK) {
- return code;
- }
- if (infoPtr->lexeme != OPEN_PAREN) {
- int code;
- Tcl_DString functionName;
- Tcl_HashEntry *hPtr;
- Interp *iPtr = (Interp *) infoPtr->parsePtr->interp;
- Tcl_Obj *objPtr = Tcl_NewStringObj(savedInfo.start, savedInfo.size);
-
- /* Check for boolean literals (true, false, yes, no, on, off) */
- Tcl_IncrRefCount(objPtr);
- code = Tcl_ConvertToType(NULL, objPtr, &tclBooleanType);
- Tcl_DecrRefCount(objPtr);
- if (code == TCL_OK) {
- *infoPtr = savedInfo;
- goto tokenizeLiteral;
- }
-
- /*
- * Guess what kind of error we have by trying to tell
- * whether we have a function or variable name here.
- * Alas, this makes the parser more tightly bound with the
- * rest of the interpreter, but that is the only way to
- * give a sensible message here. Still, it is not too
- * serious as this is only done when generating an error.
- */
-
- /*
- * Look up the name as a function name. We need a writable
- * copy (DString) so we can terminate it with a NULL for
- * the benefit of Tcl_FindHashEntry which operates on
- * NULL-terminated string keys.
- */
- Tcl_DStringInit(&functionName);
- hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable,
- Tcl_DStringAppend(&functionName,
- savedInfo.start, savedInfo.size));
- Tcl_DStringFree(&functionName);
-
- /*
- * Assume that we have an attempted variable reference
- * unless we've got a function name, as the set of
- * potential function names is typically much smaller.
- */
- if (hPtr != NULL) {
- LogSyntaxError(infoPtr,
- "expected parenthesis enclosing function arguments");
- } else {
- LogSyntaxError(infoPtr,
- "variable references require preceding $");
- }
- return TCL_ERROR;
- }
-
- if (parsePtr->numTokens == parsePtr->tokensAvailable) {
- TclExpandTokenArray(parsePtr);
- }
- tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
- tokenPtr->type = TCL_TOKEN_OPERATOR;
- tokenPtr->start = savedInfo.start;
- tokenPtr->size = savedInfo.size;
- tokenPtr->numComponents = 0;
- parsePtr->numTokens++;
-
- code = GetLexeme(infoPtr); /* skip over '(' */
- if (code != TCL_OK) {
- return code;
- }
-
- while (infoPtr->lexeme != CLOSE_PAREN) {
- code = ParseCondExpr(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
-
- if (infoPtr->lexeme == COMMA) {
- code = GetLexeme(infoPtr); /* skip over , */
- if (code != TCL_OK) {
- return code;
- }
- } else if (infoPtr->lexeme != CLOSE_PAREN) {
- LogSyntaxError(infoPtr,
- "missing close parenthesis at end of function call");
- return TCL_ERROR;
- }
- }
-
- exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
- exprTokenPtr->size = (infoPtr->next - exprTokenPtr->start);
- exprTokenPtr->numComponents = parsePtr->numTokens - firstIndex;
- break;
- }
-
- case COMMA:
- LogSyntaxError(infoPtr,
- "commas can only separate function arguments");
- return TCL_ERROR;
- case END:
- LogSyntaxError(infoPtr, "premature end of expression");
- return TCL_ERROR;
- case UNKNOWN:
- LogSyntaxError(infoPtr, "single equality character not legal in expressions");
- return TCL_ERROR;
- case UNKNOWN_CHAR:
- LogSyntaxError(infoPtr, "character not legal in expressions");
- return TCL_ERROR;
- case QUESTY:
- LogSyntaxError(infoPtr, "unexpected ternary 'then' separator");
- return TCL_ERROR;
- case COLON:
- LogSyntaxError(infoPtr, "unexpected ternary 'else' separator");
- return TCL_ERROR;
- case CLOSE_PAREN:
- LogSyntaxError(infoPtr, "unexpected close parenthesis");
- return TCL_ERROR;
-
- default: {
- char buf[64];
-
- sprintf(buf, "unexpected operator %s", lexemeStrings[lexeme]);
- LogSyntaxError(infoPtr, buf);
- return TCL_ERROR;
- }
- }
-
- /*
- * Advance to the next lexeme before returning.
- */
-
- code = GetLexeme(infoPtr);
- if (code != TCL_OK) {
- return code;
- }
- parsePtr->term = infoPtr->next;
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * GetLexeme --
- *
- * Lexical scanner for Tcl expressions: scans a single operator or
- * other syntactic element from an expression string.
- *
- * Results:
- * TCL_OK is returned unless an error occurred. In that case a standard
- * Tcl error code is returned and, if infoPtr->parsePtr->interp is
- * non-NULL, the interpreter's result is set to hold an error
- * message. TCL_ERROR is returned if an integer overflow, or a
- * floating-point overflow or underflow occurred while reading in a
- * number. If the lexical analysis is successful, infoPtr->lexeme
- * refers to the next symbol in the expression string, and
- * infoPtr->next is advanced past the lexeme. Also, if the lexeme is a
- * LITERAL or FUNC_NAME, then infoPtr->start is set to the first
- * character of the lexeme; otherwise it is set NULL.
- *
- * Side effects:
- * If there is insufficient space in parsePtr to hold all the
- * information about the subexpression, then additional space is
- * malloc-ed..
- *
- *----------------------------------------------------------------------
- */
-
-static int
-GetLexeme(infoPtr)
- ParseInfo *infoPtr; /* Holds state needed to parse the expr,
- * including the resulting lexeme. */
-{
- register CONST char *src; /* Points to current source char. */
- char c;
- int offset, length, numBytes;
- Tcl_Parse *parsePtr = infoPtr->parsePtr;
- Tcl_Interp *interp = parsePtr->interp;
- Tcl_UniChar ch;
-
- /*
- * Record where the previous lexeme ended. Since we always read one
- * lexeme ahead during parsing, this helps us know the source length of
- * subexpression tokens.
- */
-
- infoPtr->prevEnd = infoPtr->next;
-
- /*
- * Scan over leading white space at the start of a lexeme.
- */
-
- src = infoPtr->next;
- numBytes = parsePtr->end - src;
- do {
- char type;
- int scanned = TclParseWhiteSpace(src, numBytes, parsePtr, &type);
- src += scanned; numBytes -= scanned;
- } while (numBytes && (*src == '\n') && (src++,numBytes--));
- parsePtr->term = src;
- if (numBytes == 0) {
- infoPtr->lexeme = END;
- infoPtr->next = src;
- return TCL_OK;
- }
-
- /*
- * Try to parse the lexeme first as an integer or floating-point
- * number. Don't check for a number if the first character c is
- * "+" or "-". If we did, we might treat a binary operator as unary
- * by mistake, which would eventually cause a syntax error.
- */
-
- c = *src;
- if ((c != '+') && (c != '-')) {
- CONST char *end = infoPtr->lastChar;
- if ((length = TclParseInteger(src, (end - src)))) {
- /*
- * First length bytes look like an integer. Verify by
- * attempting the conversion to the largest integer we have.
- */
- int code;
- Tcl_WideInt wide;
- Tcl_Obj *value = Tcl_NewStringObj(src, length);
-
- Tcl_IncrRefCount(value);
- code = Tcl_GetWideIntFromObj(interp, value, &wide);
- Tcl_DecrRefCount(value);
- if (code == TCL_ERROR) {
- parsePtr->errorType = TCL_PARSE_BAD_NUMBER;
- return TCL_ERROR;
- }
- infoPtr->lexeme = LITERAL;
- infoPtr->start = src;
- infoPtr->size = length;
- infoPtr->next = (src + length);
- parsePtr->term = infoPtr->next;
- return TCL_OK;
- } else if ((length = ParseMaxDoubleLength(src, end))) {
- /*
- * There are length characters that could be a double.
- * Let strtod() tells us for sure. Need a writable copy
- * so we can set an terminating NULL to keep strtod from
- * scanning too far.
- */
- char *startPtr, *termPtr;
- double doubleValue;
- Tcl_DString toParse;
-
- errno = 0;
- Tcl_DStringInit(&toParse);
- startPtr = Tcl_DStringAppend(&toParse, src, length);
- doubleValue = strtod(startPtr, &termPtr);
- Tcl_DStringFree(&toParse);
- if (termPtr != startPtr) {
- if (errno != 0) {
- if (interp != NULL) {
- TclExprFloatError(interp, doubleValue);
- }
- parsePtr->errorType = TCL_PARSE_BAD_NUMBER;
- return TCL_ERROR;
- }
-
- /*
- * startPtr was the start of a valid double, copied
- * from src.
- */
-
- infoPtr->lexeme = LITERAL;
- infoPtr->start = src;
- if ((termPtr - startPtr) > length) {
- infoPtr->size = length;
- } else {
- infoPtr->size = (termPtr - startPtr);
- }
- infoPtr->next = src + infoPtr->size;
- parsePtr->term = infoPtr->next;
- return TCL_OK;
- }
- }
- }
-
- /*
- * Not an integer or double literal. Initialize the lexeme's fields
- * assuming the common case of a single character lexeme.
- */
-
- infoPtr->start = src;
- infoPtr->size = 1;
- infoPtr->next = src+1;
- parsePtr->term = infoPtr->next;
-
- switch (*src) {
- case '[':
- infoPtr->lexeme = OPEN_BRACKET;
- return TCL_OK;
-
- case '{':
- infoPtr->lexeme = OPEN_BRACE;
- return TCL_OK;
-
- case '(':
- infoPtr->lexeme = OPEN_PAREN;
- return TCL_OK;
-
- case ')':
- infoPtr->lexeme = CLOSE_PAREN;
- return TCL_OK;
-
- case '$':
- infoPtr->lexeme = DOLLAR;
- return TCL_OK;
-
- case '\"':
- infoPtr->lexeme = QUOTE;
- return TCL_OK;
-
- case ',':
- infoPtr->lexeme = COMMA;
- return TCL_OK;
-
- case '*':
- infoPtr->lexeme = MULT;
- return TCL_OK;
-
- case '/':
- infoPtr->lexeme = DIVIDE;
- return TCL_OK;
-
- case '%':
- infoPtr->lexeme = MOD;
- return TCL_OK;
-
- case '+':
- infoPtr->lexeme = PLUS;
- return TCL_OK;
-
- case '-':
- infoPtr->lexeme = MINUS;
- return TCL_OK;
-
- case '?':
- infoPtr->lexeme = QUESTY;
- return TCL_OK;
-
- case ':':
- infoPtr->lexeme = COLON;
- return TCL_OK;
-
- case '<':
- infoPtr->lexeme = LESS;
- if ((infoPtr->lastChar - src) > 1) {
- switch (src[1]) {
- case '<':
- infoPtr->lexeme = LEFT_SHIFT;
- infoPtr->size = 2;
- infoPtr->next = src+2;
- break;
- case '=':
- infoPtr->lexeme = LEQ;
- infoPtr->size = 2;
- infoPtr->next = src+2;
- break;
- }
- }
- parsePtr->term = infoPtr->next;
- return TCL_OK;
-
- case '>':
- infoPtr->lexeme = GREATER;
- if ((infoPtr->lastChar - src) > 1) {
- switch (src[1]) {
- case '>':
- infoPtr->lexeme = RIGHT_SHIFT;
- infoPtr->size = 2;
- infoPtr->next = src+2;
- break;
- case '=':
- infoPtr->lexeme = GEQ;
- infoPtr->size = 2;
- infoPtr->next = src+2;
- break;
- }
- }
- parsePtr->term = infoPtr->next;
- return TCL_OK;
-
- case '=':
- infoPtr->lexeme = UNKNOWN;
- if ((src[1] == '=') && ((infoPtr->lastChar - src) > 1)) {
- infoPtr->lexeme = EQUAL;
- infoPtr->size = 2;
- infoPtr->next = src+2;
- }
- parsePtr->term = infoPtr->next;
- return TCL_OK;
-
- case '!':
- infoPtr->lexeme = NOT;
- if ((src[1] == '=') && ((infoPtr->lastChar - src) > 1)) {
- infoPtr->lexeme = NEQ;
- infoPtr->size = 2;
- infoPtr->next = src+2;
- }
- parsePtr->term = infoPtr->next;
- return TCL_OK;
-
- case '&':
- infoPtr->lexeme = BIT_AND;
- if ((src[1] == '&') && ((infoPtr->lastChar - src) > 1)) {
- infoPtr->lexeme = AND;
- infoPtr->size = 2;
- infoPtr->next = src+2;
- }
- parsePtr->term = infoPtr->next;
- return TCL_OK;
-
- case '^':
- infoPtr->lexeme = BIT_XOR;
- return TCL_OK;
-
- case '|':
- infoPtr->lexeme = BIT_OR;
- if ((src[1] == '|') && ((infoPtr->lastChar - src) > 1)) {
- infoPtr->lexeme = OR;
- infoPtr->size = 2;
- infoPtr->next = src+2;
- }
- parsePtr->term = infoPtr->next;
- return TCL_OK;
-
- case '~':
- infoPtr->lexeme = BIT_NOT;
- return TCL_OK;
-
- case 'e':
- if ((src[1] == 'q') && ((infoPtr->lastChar - src) > 1)) {
- infoPtr->lexeme = STREQ;
- infoPtr->size = 2;
- infoPtr->next = src+2;
- parsePtr->term = infoPtr->next;
- return TCL_OK;
- } else {
- goto checkFuncName;
- }
-
- case 'n':
- if ((src[1] == 'e') && ((infoPtr->lastChar - src) > 1)) {
- infoPtr->lexeme = STRNEQ;
- infoPtr->size = 2;
- infoPtr->next = src+2;
- parsePtr->term = infoPtr->next;
- return TCL_OK;
- } else {
- goto checkFuncName;
- }
-
- default:
- checkFuncName:
- length = (infoPtr->lastChar - src);
- if (Tcl_UtfCharComplete(src, length)) {
- offset = Tcl_UtfToUniChar(src, &ch);
- } else {
- char utfBytes[TCL_UTF_MAX];
- memcpy(utfBytes, src, (size_t) length);
- utfBytes[length] = '\0';
- offset = Tcl_UtfToUniChar(utfBytes, &ch);
- }
- c = UCHAR(ch);
- if (isalpha(UCHAR(c))) { /* INTL: ISO only. */
- infoPtr->lexeme = FUNC_NAME;
- while (isalnum(UCHAR(c)) || (c == '_')) { /* INTL: ISO only. */
- src += offset; length -= offset;
- if (Tcl_UtfCharComplete(src, length)) {
- offset = Tcl_UtfToUniChar(src, &ch);
- } else {
- char utfBytes[TCL_UTF_MAX];
- memcpy(utfBytes, src, (size_t) length);
- utfBytes[length] = '\0';
- offset = Tcl_UtfToUniChar(utfBytes, &ch);
- }
- c = UCHAR(ch);
- }
- infoPtr->size = (src - infoPtr->start);
- infoPtr->next = src;
- parsePtr->term = infoPtr->next;
- return TCL_OK;
- }
- infoPtr->lexeme = UNKNOWN_CHAR;
- return TCL_OK;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclParseInteger --
- *
- * Scans up to numBytes bytes starting at src, and checks whether
- * the leading bytes look like an integer's string representation.
- *
- * Results:
- * Returns 0 if the leading bytes do not look like an integer.
- * Otherwise, returns the number of bytes examined that look
- * like an integer. This may be less than numBytes if the integer
- * is only the leading part of the string.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclParseInteger(string, numBytes)
- register CONST char *string;/* The string to examine. */
- register int numBytes; /* Max number of bytes to scan. */
-{
- register CONST char *p = string;
-
- /* Take care of introductory "0x" */
- if ((numBytes > 1) && (p[0] == '0') && ((p[1] == 'x') || (p[1] == 'X'))) {
- int scanned;
- Tcl_UniChar ch;
- p+=2; numBytes -= 2;
- scanned = TclParseHex(p, numBytes, &ch);
- if (scanned) {
- return scanned + 2;
- }
-
- /* Recognize the 0 as valid integer, but x is left behind */
- return 1;
- }
- while (numBytes && isdigit(UCHAR(*p))) { /* INTL: digit */
- numBytes--; p++;
- }
- if (numBytes == 0) {
- return (p - string);
- }
- if ((*p != '.') && (*p != 'e') && (*p != 'E')) {
- return (p - string);
- }
- return 0;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ParseMaxDoubleLength --
- *
- * Scans a sequence of bytes checking that the characters could
- * be in a string rep of a double.
- *
- * Results:
- * Returns the number of bytes starting with string, runing to, but
- * not including end, all of which could be part of a string rep.
- * of a double. Only character identity is used, no actual
- * parsing is done.
- *
- * The legal bytes are '0' - '9', 'A' - 'F', 'a' - 'f',
- * '.', '+', '-', 'i', 'I', 'n', 'N', 'p', 'P', 'x', and 'X'.
- * This covers the values "Inf" and "Nan" as well as the
- * decimal and hexadecimal representations recognized by a
- * C99-compliant strtod().
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ParseMaxDoubleLength(string, end)
- register CONST char *string;/* The string to examine. */
- CONST char *end; /* Point to the first character past the end
- * of the string we are examining. */
-{
- CONST char *p = string;
- while (p < end) {
- switch (*p) {
- case '0': case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9': case 'A': case 'B':
- case 'C': case 'D': case 'E': case 'F': case 'I': case 'N':
- case 'P': case 'X': case 'a': case 'b': case 'c': case 'd':
- case 'e': case 'f': case 'i': case 'n': case 'p': case 'x':
- case '.': case '+': case '-':
- p++;
- break;
- default:
- goto done;
- }
- }
- done:
- return (p - string);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * PrependSubExprTokens --
- *
- * This procedure is called after the operands of an subexpression have
- * been parsed. It generates two tokens: a TCL_TOKEN_SUB_EXPR token for
- * the subexpression, and a TCL_TOKEN_OPERATOR token for its operator.
- * These two tokens are inserted before the operand tokens.
- *
- * Results:
- * None.
- *
- * Side effects:
- * If there is insufficient space in parsePtr to hold the new tokens,
- * additional space is malloc-ed.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-PrependSubExprTokens(op, opBytes, src, srcBytes, firstIndex, infoPtr)
- CONST char *op; /* Points to first byte of the operator
- * in the source script. */
- int opBytes; /* Number of bytes in the operator. */
- CONST char *src; /* Points to first byte of the subexpression
- * in the source script. */
- int srcBytes; /* Number of bytes in subexpression's
- * source. */
- int firstIndex; /* Index of first token already emitted for
- * operator's first (or only) operand. */
- ParseInfo *infoPtr; /* Holds the parse state for the
- * expression being parsed. */
-{
- Tcl_Parse *parsePtr = infoPtr->parsePtr;
- Tcl_Token *tokenPtr, *firstTokenPtr;
- int numToMove;
-
- if ((parsePtr->numTokens + 1) >= parsePtr->tokensAvailable) {
- TclExpandTokenArray(parsePtr);
- }
- firstTokenPtr = &parsePtr->tokenPtr[firstIndex];
- tokenPtr = (firstTokenPtr + 2);
- numToMove = (parsePtr->numTokens - firstIndex);
- memmove((VOID *) tokenPtr, (VOID *) firstTokenPtr,
- (size_t) (numToMove * sizeof(Tcl_Token)));
- parsePtr->numTokens += 2;
-
- tokenPtr = firstTokenPtr;
- tokenPtr->type = TCL_TOKEN_SUB_EXPR;
- tokenPtr->start = src;
- tokenPtr->size = srcBytes;
- tokenPtr->numComponents = parsePtr->numTokens - (firstIndex + 1);
-
- tokenPtr++;
- tokenPtr->type = TCL_TOKEN_OPERATOR;
- tokenPtr->start = op;
- tokenPtr->size = opBytes;
- tokenPtr->numComponents = 0;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * LogSyntaxError --
- *
- * This procedure is invoked after an error occurs when parsing an
- * expression. It sets the interpreter result to an error message
- * describing the error.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Sets the interpreter result to an error message describing the
- * expression that was being parsed when the error occurred, and why
- * the parser considers that to be a syntax error at all.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-LogSyntaxError(infoPtr, extraInfo)
- ParseInfo *infoPtr; /* Holds the parse state for the
- * expression being parsed. */
- CONST char *extraInfo; /* String to provide extra information
- * about the syntax error. */
-{
- int numBytes = (infoPtr->lastChar - infoPtr->originalExpr);
- char buffer[100];
-
- if (numBytes > 60) {
- sprintf(buffer, "syntax error in expression \"%.60s...\"",
- infoPtr->originalExpr);
- } else {
- sprintf(buffer, "syntax error in expression \"%.*s\"",
- numBytes, infoPtr->originalExpr);
- }
- Tcl_ResetResult(infoPtr->parsePtr->interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(infoPtr->parsePtr->interp),
- buffer, ": ", extraInfo, (char *) NULL);
- infoPtr->parsePtr->errorType = TCL_PARSE_SYNTAX;
- infoPtr->parsePtr->term = infoPtr->start;
-}
diff --git a/generic/tclPathObj.c b/generic/tclPathObj.c
new file mode 100644
index 0000000..8840e4a
--- /dev/null
+++ b/generic/tclPathObj.c
@@ -0,0 +1,2836 @@
+/*
+ * tclPathObj.c --
+ *
+ * This file contains the implementation of Tcl's "path" object type used
+ * to represent and manipulate a general (virtual) filesystem entity in
+ * an efficient manner.
+ *
+ * Copyright (c) 2003 Vince Darley.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tclInt.h"
+#include "tclFileSystem.h"
+
+/*
+ * Prototypes for functions defined later in this file.
+ */
+
+static Tcl_Obj * AppendPath(Tcl_Obj *head, Tcl_Obj *tail);
+static void DupFsPathInternalRep(Tcl_Obj *srcPtr,
+ Tcl_Obj *copyPtr);
+static void FreeFsPathInternalRep(Tcl_Obj *pathPtr);
+static void UpdateStringOfFsPath(Tcl_Obj *pathPtr);
+static int SetFsPathFromAny(Tcl_Interp *interp, Tcl_Obj *pathPtr);
+static int FindSplitPos(const char *path, int separator);
+static int IsSeparatorOrNull(int ch);
+static Tcl_Obj * GetExtension(Tcl_Obj *pathPtr);
+
+/*
+ * Define the 'path' object type, which Tcl uses to represent file paths
+ * internally.
+ */
+
+static Tcl_ObjType tclFsPathType = {
+ "path", /* name */
+ FreeFsPathInternalRep, /* freeIntRepProc */
+ DupFsPathInternalRep, /* dupIntRepProc */
+ UpdateStringOfFsPath, /* updateStringProc */
+ SetFsPathFromAny /* setFromAnyProc */
+};
+
+/*
+ * struct FsPath --
+ *
+ * Internal representation of a Tcl_Obj of "path" type. This can be used to
+ * represent relative or absolute paths, and has certain optimisations when
+ * used to represent paths which are already normalized and absolute.
+ *
+ * Note that both 'translatedPathPtr' and 'normPathPtr' can be a circular
+ * reference to the container Tcl_Obj of this FsPath.
+ *
+ * There are two cases, with the first being the most common:
+ *
+ * (i) flags == 0, => Ordinary path.
+ *
+ * translatedPathPtr contains the translated path (which may be a circular
+ * reference to the object itself). If it is NULL then the path is pure
+ * normalized (and the normPathPtr will be a circular reference). cwdPtr is
+ * null for an absolute path, and non-null for a relative path (unless the cwd
+ * has never been set, in which case the cwdPtr may also be null for a
+ * relative path).
+ *
+ * (ii) flags != 0, => Special path, see TclNewFSPathObj
+ *
+ * Now, this is a path like 'file join $dir $tail' where, cwdPtr is the $dir
+ * and normPathPtr is the $tail.
+ *
+ */
+
+typedef struct FsPath {
+ Tcl_Obj *translatedPathPtr; /* Name without any ~user sequences. If this
+ * is NULL, then this is a pure normalized,
+ * absolute path object, in which the parent
+ * Tcl_Obj's string rep is already both
+ * translated and normalized. */
+ Tcl_Obj *normPathPtr; /* Normalized absolute path, without ., .. or
+ * ~user sequences. If the Tcl_Obj containing
+ * this FsPath is already normalized, this may
+ * be a circular reference back to the
+ * container. If that is NOT the case, we have
+ * a refCount on the object. */
+ Tcl_Obj *cwdPtr; /* If null, path is absolute, else this points
+ * to the cwd object used for this path. We
+ * have a refCount on the object. */
+ int flags; /* Flags to describe interpretation - see
+ * below. */
+ ClientData nativePathPtr; /* Native representation of this path, which
+ * is filesystem dependent. */
+ int filesystemEpoch; /* Used to ensure the path representation was
+ * generated during the correct filesystem
+ * epoch. The epoch changes when
+ * filesystem-mounts are changed. */
+ struct FilesystemRecord *fsRecPtr;
+ /* Pointer to the filesystem record entry to
+ * use for this path. */
+} FsPath;
+
+/*
+ * Flag values for FsPath->flags.
+ */
+
+#define TCLPATH_APPENDED 1
+#define TCLPATH_NEEDNORM 4
+
+/*
+ * Define some macros to give us convenient access to path-object specific
+ * fields.
+ */
+
+#define PATHOBJ(pathPtr) ((FsPath *) (pathPtr)->internalRep.otherValuePtr)
+#define SETPATHOBJ(pathPtr,fsPathPtr) \
+ ((pathPtr)->internalRep.otherValuePtr = (void *) (fsPathPtr))
+#define PATHFLAGS(pathPtr) (PATHOBJ(pathPtr)->flags)
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclFSNormalizeAbsolutePath --
+ *
+ * Takes an absolute path specification and computes a 'normalized' path
+ * from it.
+ *
+ * A normalized path is one which has all '../', './' removed. Also it is
+ * one which is in the 'standard' format for the native platform. On
+ * Unix, this means the path must be free of symbolic links/aliases, and
+ * on Windows it means we want the long form, with that long form's
+ * case-dependence (which gives us a unique, case-dependent path).
+ *
+ * The behaviour of this function if passed a non-absolute path is NOT
+ * defined.
+ *
+ * pathPtr may have a refCount of zero, or may be a shared object.
+ *
+ * Results:
+ * The result is returned in a Tcl_Obj with a refCount of 1, which is
+ * therefore owned by the caller. It must be freed (with
+ * Tcl_DecrRefCount) by the caller when no longer needed.
+ *
+ * Side effects:
+ * None (beyond the memory allocation for the result).
+ *
+ * Special note:
+ * This code was originally based on code from Matt Newman and
+ * Jean-Claude Wippler, but has since been totally rewritten by Vince
+ * Darley to deal with symbolic links.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclFSNormalizeAbsolutePath(
+ Tcl_Interp *interp, /* Interpreter to use */
+ Tcl_Obj *pathPtr, /* Absolute path to normalize */
+ ClientData *clientDataPtr) /* If non-NULL, then may be set to the
+ * fs-specific clientData for this path. This
+ * will happen when that extra information can
+ * be calculated efficiently as a side-effect
+ * of normalization. */
+{
+ ClientData clientData = NULL;
+ const char *dirSep, *oldDirSep;
+ int first = 1; /* Set to zero once we've passed the first
+ * directory separator - we can't use '..' to
+ * remove the volume in a path. */
+ Tcl_Obj *retVal = NULL;
+ dirSep = TclGetString(pathPtr);
+
+ if (tclPlatform == TCL_PLATFORM_WINDOWS) {
+ if ( (dirSep[0] == '/' || dirSep[0] == '\\')
+ && (dirSep[1] == '/' || dirSep[1] == '\\')
+ && (dirSep[2] == '?')
+ && (dirSep[3] == '/' || dirSep[3] == '\\')) {
+ /* NT extended path */
+ dirSep += 4;
+
+ if ( (dirSep[0] == 'U' || dirSep[0] == 'u')
+ && (dirSep[1] == 'N' || dirSep[1] == 'n')
+ && (dirSep[2] == 'C' || dirSep[2] == 'c')
+ && (dirSep[3] == '/' || dirSep[3] == '\\')) {
+ /* NT extended UNC path */
+ dirSep += 4;
+ }
+ }
+ if (dirSep[0] != 0 && dirSep[1] == ':' &&
+ (dirSep[2] == '/' || dirSep[2] == '\\')) {
+ /* Do nothing */
+ } else if ((dirSep[0] == '/' || dirSep[0] == '\\')
+ && (dirSep[1] == '/' || dirSep[1] == '\\')) {
+ /*
+ * UNC style path, where we must skip over the first separator,
+ * since the first two segments are actually inseparable.
+ */
+
+ dirSep += 2;
+ dirSep += FindSplitPos(dirSep, '/');
+ if (*dirSep != 0) {
+ dirSep++;
+ }
+ }
+ }
+
+ /*
+ * Scan forward from one directory separator to the next, checking for
+ * '..' and '.' sequences which must be handled specially. In particular
+ * handling of '..' can be complicated if the directory before is a link,
+ * since we will have to expand the link to be able to back up one level.
+ */
+
+ while (*dirSep != 0) {
+ oldDirSep = dirSep;
+ if (!first) {
+ dirSep++;
+ }
+ dirSep += FindSplitPos(dirSep, '/');
+ if (dirSep[0] == 0 || dirSep[1] == 0) {
+ if (retVal != NULL) {
+ Tcl_AppendToObj(retVal, oldDirSep, dirSep - oldDirSep);
+ }
+ break;
+ }
+ if (dirSep[1] == '.') {
+ if (retVal != NULL) {
+ Tcl_AppendToObj(retVal, oldDirSep, dirSep - oldDirSep);
+ oldDirSep = dirSep;
+ }
+ again:
+ if (IsSeparatorOrNull(dirSep[2])) {
+ /*
+ * Need to skip '.' in the path.
+ */
+ int curLen;
+
+ if (retVal == NULL) {
+ const char *path = TclGetString(pathPtr);
+ retVal = Tcl_NewStringObj(path, dirSep - path);
+ Tcl_IncrRefCount(retVal);
+ }
+ (void) Tcl_GetStringFromObj(retVal, &curLen);
+ if (curLen == 0) {
+ Tcl_AppendToObj(retVal, dirSep, 1);
+ }
+ dirSep += 2;
+ oldDirSep = dirSep;
+ if (dirSep[0] != 0 && dirSep[1] == '.') {
+ goto again;
+ }
+ continue;
+ }
+ if (dirSep[2] == '.' && IsSeparatorOrNull(dirSep[3])) {
+ Tcl_Obj *link;
+ int curLen;
+ char *linkStr;
+
+ /*
+ * Have '..' so need to skip previous directory.
+ */
+
+ if (retVal == NULL) {
+ const char *path = TclGetString(pathPtr);
+
+ retVal = Tcl_NewStringObj(path, dirSep - path);
+ Tcl_IncrRefCount(retVal);
+ }
+ (void) Tcl_GetStringFromObj(retVal, &curLen);
+ if (curLen == 0) {
+ Tcl_AppendToObj(retVal, dirSep, 1);
+ }
+ if (!first || (tclPlatform == TCL_PLATFORM_UNIX)) {
+ link = Tcl_FSLink(retVal, NULL, 0);
+ if (link != NULL) {
+ /*
+ * Got a link. Need to check if the link is relative
+ * or absolute, for those platforms where relative
+ * links exist.
+ */
+
+ if (tclPlatform != TCL_PLATFORM_WINDOWS &&
+ Tcl_FSGetPathType(link) == TCL_PATH_RELATIVE) {
+ /*
+ * We need to follow this link which is relative
+ * to retVal's directory. This means concatenating
+ * the link onto the directory of the path so far.
+ */
+
+ const char *path =
+ Tcl_GetStringFromObj(retVal, &curLen);
+
+ while (--curLen >= 0) {
+ if (IsSeparatorOrNull(path[curLen])) {
+ break;
+ }
+ }
+ if (Tcl_IsShared(retVal)) {
+ TclDecrRefCount(retVal);
+ retVal = Tcl_DuplicateObj(retVal);
+ Tcl_IncrRefCount(retVal);
+ }
+
+ /*
+ * We want the trailing slash.
+ */
+
+ Tcl_SetObjLength(retVal, curLen+1);
+ Tcl_AppendObjToObj(retVal, link);
+ TclDecrRefCount(link);
+ linkStr = Tcl_GetStringFromObj(retVal, &curLen);
+ } else {
+ /*
+ * Absolute link.
+ */
+
+ TclDecrRefCount(retVal);
+ retVal = link;
+ linkStr = Tcl_GetStringFromObj(retVal, &curLen);
+
+ /*
+ * Convert to forward-slashes on windows.
+ */
+
+ if (tclPlatform == TCL_PLATFORM_WINDOWS) {
+ int i;
+
+ for (i = 0; i < curLen; i++) {
+ if (linkStr[i] == '\\') {
+ linkStr[i] = '/';
+ }
+ }
+ }
+ }
+ } else {
+ linkStr = Tcl_GetStringFromObj(retVal, &curLen);
+ }
+
+ /*
+ * Either way, we now remove the last path element.
+ * (but not the first character of the path)
+ */
+
+ while (--curLen >= 0) {
+ if (IsSeparatorOrNull(linkStr[curLen])) {
+ if (curLen) {
+ Tcl_SetObjLength(retVal, curLen);
+ } else {
+ Tcl_SetObjLength(retVal, 1);
+ }
+ break;
+ }
+ }
+ }
+ dirSep += 3;
+ oldDirSep = dirSep;
+
+ if ((curLen == 0) && (dirSep[0] != 0)) {
+ Tcl_SetObjLength(retVal, 0);
+ }
+
+ if (dirSep[0] != 0 && dirSep[1] == '.') {
+ goto again;
+ }
+ continue;
+ }
+ }
+ first = 0;
+ if (retVal != NULL) {
+ Tcl_AppendToObj(retVal, oldDirSep, dirSep - oldDirSep);
+ }
+ }
+
+ /*
+ * If we didn't make any changes, just use the input path.
+ */
+
+ if (retVal == NULL) {
+ retVal = pathPtr;
+ Tcl_IncrRefCount(retVal);
+
+ if (Tcl_IsShared(retVal)) {
+ /*
+ * Unfortunately, the platform-specific normalization code which
+ * will be called below has no way of dealing with the case where
+ * an object is shared. It is expecting to modify an object in
+ * place. So, we must duplicate this here to ensure an object with
+ * a single ref-count.
+ *
+ * If that changes in the future (e.g. the normalize proc is given
+ * one object and is able to return a different one), then we
+ * could remove this code.
+ */
+
+ TclDecrRefCount(retVal);
+ retVal = Tcl_DuplicateObj(pathPtr);
+ Tcl_IncrRefCount(retVal);
+ }
+ }
+
+ /*
+ * Ensure a windows drive like C:/ has a trailing separator
+ */
+
+ if (tclPlatform == TCL_PLATFORM_WINDOWS) {
+ int len;
+ const char *path = Tcl_GetStringFromObj(retVal, &len);
+
+ if (len == 2 && path[0] != 0 && path[1] == ':') {
+ if (Tcl_IsShared(retVal)) {
+ TclDecrRefCount(retVal);
+ retVal = Tcl_DuplicateObj(retVal);
+ Tcl_IncrRefCount(retVal);
+ }
+ Tcl_AppendToObj(retVal, "/", 1);
+ }
+ }
+
+ /*
+ * Now we have an absolute path, with no '..', '.' sequences, but it still
+ * may not be in 'unique' form, depending on the platform. For instance,
+ * Unix is case-sensitive, so the path is ok. Windows is case-insensitive,
+ * and also has the weird 'longname/shortname' thing (e.g. C:/Program
+ * Files/ and C:/Progra~1/ are equivalent).
+ *
+ * Virtual file systems which may be registered may have other criteria
+ * for normalizing a path.
+ */
+
+ TclFSNormalizeToUniquePath(interp, retVal, 0, &clientData);
+
+ /*
+ * Since we know it is a normalized path, we can actually convert this
+ * object into an FsPath for greater efficiency
+ */
+
+ TclFSMakePathFromNormalized(interp, retVal, clientData);
+ if (clientDataPtr != NULL) {
+ *clientDataPtr = clientData;
+ }
+
+ /*
+ * This has a refCount of 1 for the caller, unlike many Tcl_Obj APIs.
+ */
+
+ return retVal;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_FSGetPathType --
+ *
+ * Determines whether a given path is relative to the current directory,
+ * relative to the current volume, or absolute.
+ *
+ * Results:
+ * Returns one of TCL_PATH_ABSOLUTE, TCL_PATH_RELATIVE, or
+ * TCL_PATH_VOLUME_RELATIVE.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_PathType
+Tcl_FSGetPathType(
+ Tcl_Obj *pathPtr)
+{
+ return TclFSGetPathType(pathPtr, NULL, NULL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclFSGetPathType --
+ *
+ * Determines whether a given path is relative to the current directory,
+ * relative to the current volume, or absolute. If the caller wishes to
+ * know which filesystem claimed the path (in the case for which the path
+ * is absolute), then a reference to a filesystem pointer can be passed
+ * in (but passing NULL is acceptable).
+ *
+ * Results:
+ * Returns one of TCL_PATH_ABSOLUTE, TCL_PATH_RELATIVE, or
+ * TCL_PATH_VOLUME_RELATIVE. The filesystem reference will be set if and
+ * only if it is non-NULL and the function's return value is
+ * TCL_PATH_ABSOLUTE.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_PathType
+TclFSGetPathType(
+ Tcl_Obj *pathPtr,
+ Tcl_Filesystem **filesystemPtrPtr,
+ int *driveNameLengthPtr)
+{
+ FsPath *fsPathPtr;
+
+ if (Tcl_FSConvertToPathType(NULL, pathPtr) != TCL_OK) {
+ return TclGetPathType(pathPtr, filesystemPtrPtr, driveNameLengthPtr,
+ NULL);
+ }
+
+ fsPathPtr = PATHOBJ(pathPtr);
+ if (fsPathPtr->cwdPtr == NULL) {
+ return TclGetPathType(pathPtr, filesystemPtrPtr, driveNameLengthPtr,
+ NULL);
+ }
+
+ if (PATHFLAGS(pathPtr) == 0) {
+ /* The path is not absolute... */
+#ifdef __WIN32__
+ /* ... on Windows we must make another call to determine whether
+ * it's relative or volumerelative [Bug 2571597]. */
+ return TclGetPathType(pathPtr, filesystemPtrPtr, driveNameLengthPtr,
+ NULL);
+#else
+ /* On other systems, quickly deduce !absolute -> relative */
+ return TCL_PATH_RELATIVE;
+#endif
+ }
+ return TclFSGetPathType(fsPathPtr->cwdPtr, filesystemPtrPtr,
+ driveNameLengthPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclPathPart
+ *
+ * This function calculates the requested part of the given path, which
+ * can be:
+ *
+ * - the directory above ('file dirname')
+ * - the tail ('file tail')
+ * - the extension ('file extension')
+ * - the root ('file root')
+ *
+ * The 'portion' parameter dictates which of these to calculate. There
+ * are a number of special cases both to be more efficient, and because
+ * the behaviour when given a path with only a single element is defined
+ * to require the expansion of that single element, where possible.
+ *
+ * Should look into integrating 'FileBasename' in tclFCmd.c into this
+ * function.
+ *
+ * Results:
+ * NULL if an error occurred, otherwise a Tcl_Obj owned by the caller
+ * (i.e. most likely with refCount 1).
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclPathPart(
+ Tcl_Interp *interp, /* Used for error reporting */
+ Tcl_Obj *pathPtr, /* Path to take dirname of */
+ Tcl_PathPart portion) /* Requested portion of name */
+{
+ if (pathPtr->typePtr == &tclFsPathType) {
+ FsPath *fsPathPtr = PATHOBJ(pathPtr);
+
+ if (TclFSEpochOk(fsPathPtr->filesystemEpoch)
+ && (PATHFLAGS(pathPtr) != 0)) {
+ switch (portion) {
+ case TCL_PATH_DIRNAME: {
+ /*
+ * Check if the joined-on bit has any directory delimiters in
+ * it. If so, the 'dirname' would be a joining of the main
+ * part with the dirname of the joined-on bit. We could handle
+ * that special case here, but we don't, and instead just use
+ * the standardPath code.
+ */
+
+ int numBytes;
+ const char *rest =
+ Tcl_GetStringFromObj(fsPathPtr->normPathPtr, &numBytes);
+
+ if (strchr(rest, '/') != NULL) {
+ goto standardPath;
+ }
+ /*
+ * If the joined-on bit is empty, then [file dirname] is
+ * documented to return all but the last non-empty element
+ * of the path, so we need to split apart the main part to
+ * get the right answer. We could do that here, but it's
+ * simpler to fall back to the standardPath code.
+ * [Bug 2710920]
+ */
+ if (numBytes == 0) {
+ goto standardPath;
+ }
+ if (tclPlatform == TCL_PLATFORM_WINDOWS
+ && strchr(rest, '\\') != NULL) {
+ goto standardPath;
+ }
+
+ /*
+ * The joined-on path is simple, so we can just return here.
+ */
+
+ Tcl_IncrRefCount(fsPathPtr->cwdPtr);
+ return fsPathPtr->cwdPtr;
+ }
+ case TCL_PATH_TAIL: {
+ /*
+ * Check if the joined-on bit has any directory delimiters in
+ * it. If so, the 'tail' would be only the part following the
+ * last delimiter. We could handle that special case here, but
+ * we don't, and instead just use the standardPath code.
+ */
+
+ int numBytes;
+ const char *rest =
+ Tcl_GetStringFromObj(fsPathPtr->normPathPtr, &numBytes);
+
+ if (strchr(rest, '/') != NULL) {
+ goto standardPath;
+ }
+ /*
+ * If the joined-on bit is empty, then [file tail] is
+ * documented to return the last non-empty element
+ * of the path, so we need to split off the last element
+ * of the main part to get the right answer. We could do
+ * that here, but it's simpler to fall back to the
+ * standardPath code. [Bug 2710920]
+ */
+ if (numBytes == 0) {
+ goto standardPath;
+ }
+ if (tclPlatform == TCL_PLATFORM_WINDOWS
+ && strchr(rest, '\\') != NULL) {
+ goto standardPath;
+ }
+ Tcl_IncrRefCount(fsPathPtr->normPathPtr);
+ return fsPathPtr->normPathPtr;
+ }
+ case TCL_PATH_EXTENSION:
+ return GetExtension(fsPathPtr->normPathPtr);
+ case TCL_PATH_ROOT: {
+ const char *fileName, *extension;
+ int length;
+
+ fileName = Tcl_GetStringFromObj(fsPathPtr->normPathPtr,
+ &length);
+ extension = TclGetExtension(fileName);
+ if (extension == NULL) {
+ /*
+ * There is no extension so the root is the same as the
+ * path we were given.
+ */
+
+ Tcl_IncrRefCount(pathPtr);
+ return pathPtr;
+ } else {
+ /*
+ * Need to return the whole path with the extension
+ * suffix removed. Do that by joining our "head" to
+ * our "tail" with the extension suffix removed from
+ * the tail.
+ */
+
+ Tcl_Obj *resultPtr =
+ TclNewFSPathObj(fsPathPtr->cwdPtr, fileName,
+ (int)(length - strlen(extension)));
+
+ Tcl_IncrRefCount(resultPtr);
+ return resultPtr;
+ }
+ }
+ default:
+ /* We should never get here */
+ Tcl_Panic("Bad portion to TclPathPart");
+ /* For less clever compilers */
+ return NULL;
+ }
+ } else if (fsPathPtr->cwdPtr != NULL) {
+ /* Relative path */
+ goto standardPath;
+ } else {
+ /* Absolute path */
+ goto standardPath;
+ }
+ } else {
+ int splitElements;
+ Tcl_Obj *splitPtr, *resultPtr;
+
+ standardPath:
+ resultPtr = NULL;
+ if (portion == TCL_PATH_EXTENSION) {
+ return GetExtension(pathPtr);
+ } else if (portion == TCL_PATH_ROOT) {
+ int length;
+ const char *fileName, *extension;
+
+ fileName = Tcl_GetStringFromObj(pathPtr, &length);
+ extension = TclGetExtension(fileName);
+ if (extension == NULL) {
+ Tcl_IncrRefCount(pathPtr);
+ return pathPtr;
+ } else {
+ Tcl_Obj *root = Tcl_NewStringObj(fileName,
+ (int) (length - strlen(extension)));
+
+ Tcl_IncrRefCount(root);
+ return root;
+ }
+ }
+
+ /*
+ * The behaviour we want here is slightly different to the standard
+ * Tcl_FSSplitPath in the handling of home directories;
+ * Tcl_FSSplitPath preserves the "~" while this code computes the
+ * actual full path name, if we had just a single component.
+ */
+
+ splitPtr = Tcl_FSSplitPath(pathPtr, &splitElements);
+ Tcl_IncrRefCount(splitPtr);
+ if (splitElements == 1 && TclGetString(pathPtr)[0] == '~') {
+ Tcl_Obj *norm;
+
+ TclDecrRefCount(splitPtr);
+ norm = Tcl_FSGetNormalizedPath(interp, pathPtr);
+ if (norm == NULL) {
+ return NULL;
+ }
+ splitPtr = Tcl_FSSplitPath(norm, &splitElements);
+ Tcl_IncrRefCount(splitPtr);
+ }
+ if (portion == TCL_PATH_TAIL) {
+ /*
+ * Return the last component, unless it is the only component, and
+ * it is the root of an absolute path.
+ */
+
+ if ((splitElements > 0) && ((splitElements > 1) ||
+ (Tcl_FSGetPathType(pathPtr) == TCL_PATH_RELATIVE))) {
+ Tcl_ListObjIndex(NULL, splitPtr, splitElements-1, &resultPtr);
+ } else {
+ resultPtr = Tcl_NewObj();
+ }
+ } else {
+ /*
+ * Return all but the last component. If there is only one
+ * component, return it if the path was non-relative, otherwise
+ * return the current directory.
+ */
+
+ if (splitElements > 1) {
+ resultPtr = Tcl_FSJoinPath(splitPtr, splitElements - 1);
+ } else if (splitElements == 0 ||
+ (Tcl_FSGetPathType(pathPtr) == TCL_PATH_RELATIVE)) {
+ TclNewLiteralStringObj(resultPtr, ".");
+ } else {
+ Tcl_ListObjIndex(NULL, splitPtr, 0, &resultPtr);
+ }
+ }
+ Tcl_IncrRefCount(resultPtr);
+ TclDecrRefCount(splitPtr);
+ return resultPtr;
+ }
+}
+
+/*
+ * Simple helper function
+ */
+
+static Tcl_Obj *
+GetExtension(
+ Tcl_Obj *pathPtr)
+{
+ const char *tail, *extension;
+ Tcl_Obj *ret;
+
+ tail = TclGetString(pathPtr);
+ extension = TclGetExtension(tail);
+ if (extension == NULL) {
+ ret = Tcl_NewObj();
+ } else {
+ ret = Tcl_NewStringObj(extension, -1);
+ }
+ Tcl_IncrRefCount(ret);
+ return ret;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tcl_FSJoinPath --
+ *
+ * This function takes the given Tcl_Obj, which should be a valid list,
+ * and returns the path object given by considering the first 'elements'
+ * elements as valid path segments (each path segment may be a complete
+ * path, a partial path or just a single possible directory or file
+ * name). If any path segment is actually an absolute path, then all
+ * prior path segments are discarded.
+ *
+ * If elements < 0, we use the entire list that was given.
+ *
+ * It is possible that the returned object is actually an element of the
+ * given list, so the caller should be careful to store a refCount to it
+ * before freeing the list.
+ *
+ * Results:
+ * Returns object with refCount of zero, (or if non-zero, it has
+ * references elsewhere in Tcl). Either way, the caller must increment
+ * its refCount before use. Note that in the case where the caller has
+ * asked to join zero elements of the list, the return value will be an
+ * empty-string Tcl_Obj.
+ *
+ * If the given listObj was invalid, then the calling routine has a bug,
+ * and this function will just return NULL.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tcl_FSJoinPath(
+ Tcl_Obj *listObj, /* Path elements to join, may have a zero
+ * reference count. */
+ int elements) /* Number of elements to use (-1 = all) */
+{
+ Tcl_Obj *res;
+ int i;
+ Tcl_Filesystem *fsPtr = NULL;
+
+ if (elements < 0) {
+ if (Tcl_ListObjLength(NULL, listObj, &elements) != TCL_OK) {
+ return NULL;
+ }
+ } else {
+ /*
+ * Just make sure it is a valid list.
+ */
+
+ int listTest;
+
+ if (Tcl_ListObjLength(NULL, listObj, &listTest) != TCL_OK) {
+ return NULL;
+ }
+
+ /*
+ * Correct this if it is too large, otherwise we will waste our time
+ * joining null elements to the path.
+ */
+
+ if (elements > listTest) {
+ elements = listTest;
+ }
+ }
+
+ res = NULL;
+
+ for (i = 0; i < elements; i++) {
+ Tcl_Obj *elt, *driveName = NULL;
+ int driveNameLength, strEltLen, length;
+ Tcl_PathType type;
+ char *strElt, *ptr;
+
+ Tcl_ListObjIndex(NULL, listObj, i, &elt);
+
+ /*
+ * This is a special case where we can be much more efficient, where
+ * we are joining a single relative path onto an object that is
+ * already of path type. The 'TclNewFSPathObj' call below creates an
+ * object which can be normalized more efficiently. Currently we only
+ * use the special case when we have exactly two elements, but we
+ * could expand that in the future.
+ */
+
+ if ((i == (elements-2)) && (i == 0) && (elt->typePtr == &tclFsPathType)
+ && !(elt->bytes != NULL && (elt->bytes[0] == '\0'))) {
+ Tcl_Obj *tail;
+
+ Tcl_ListObjIndex(NULL, listObj, i+1, &tail);
+ type = TclGetPathType(tail, NULL, NULL, NULL);
+ if (type == TCL_PATH_RELATIVE) {
+ const char *str;
+ int len;
+
+ str = Tcl_GetStringFromObj(tail, &len);
+ if (len == 0) {
+ /*
+ * This happens if we try to handle the root volume '/'.
+ * There's no need to return a special path object, when
+ * the base itself is just fine!
+ */
+
+ if (res != NULL) {
+ TclDecrRefCount(res);
+ }
+ return elt;
+ }
+
+ /*
+ * If it doesn't begin with '.' and is a unix path or it a
+ * windows path without backslashes, then we can be very
+ * efficient here. (In fact even a windows path with
+ * backslashes can be joined efficiently, but the path object
+ * would not have forward slashes only, and this would
+ * therefore contradict our 'file join' documentation).
+ */
+
+ if (str[0] != '.' && ((tclPlatform != TCL_PLATFORM_WINDOWS)
+ || (strchr(str, '\\') == NULL))) {
+ /*
+ * Finally, on Windows, 'file join' is defined to convert
+ * all backslashes to forward slashes, so the base part
+ * cannot have backslashes either.
+ */
+
+ if ((tclPlatform != TCL_PLATFORM_WINDOWS)
+ || (strchr(Tcl_GetString(elt), '\\') == NULL)) {
+ if (res != NULL) {
+ TclDecrRefCount(res);
+ }
+ return TclNewFSPathObj(elt, str, len);
+ }
+ }
+
+ /*
+ * Otherwise we don't have an easy join, and we must let the
+ * more general code below handle things.
+ */
+ } else if (tclPlatform == TCL_PLATFORM_UNIX) {
+ if (res != NULL) {
+ TclDecrRefCount(res);
+ }
+ return tail;
+ } else {
+ const char *str = TclGetString(tail);
+
+ if (tclPlatform == TCL_PLATFORM_WINDOWS) {
+ if (strchr(str, '\\') == NULL) {
+ if (res != NULL) {
+ TclDecrRefCount(res);
+ }
+ return tail;
+ }
+ }
+ }
+ }
+ strElt = Tcl_GetStringFromObj(elt, &strEltLen);
+ type = TclGetPathType(elt, &fsPtr, &driveNameLength, &driveName);
+ if (type != TCL_PATH_RELATIVE) {
+ /*
+ * Zero out the current result.
+ */
+
+ if (res != NULL) {
+ TclDecrRefCount(res);
+ }
+
+ if (driveName != NULL) {
+ /*
+ * We've been given a separate drive-name object, because the
+ * prefix in 'elt' is not in a suitable format for us (e.g. it
+ * may contain irrelevant multiple separators, like
+ * C://///foo).
+ */
+
+ res = Tcl_DuplicateObj(driveName);
+ TclDecrRefCount(driveName);
+
+ /*
+ * Do not set driveName to NULL, because we will check its
+ * value below (but we won't access the contents, since those
+ * have been cleaned-up).
+ */
+ } else {
+ res = Tcl_NewStringObj(strElt, driveNameLength);
+ }
+ strElt += driveNameLength;
+ } else if (driveName != NULL) {
+ Tcl_DecrRefCount(driveName);
+ }
+
+ /*
+ * Optimisation block: if this is the last element to be examined, and
+ * it is absolute or the only element, and the drive-prefix was ok (if
+ * there is one), it might be that the path is already in a suitable
+ * form to be returned. Then we can short-cut the rest of this
+ * function.
+ */
+
+ if ((driveName == NULL) && (i == (elements - 1))
+ && (type != TCL_PATH_RELATIVE || res == NULL)) {
+ /*
+ * It's the last path segment. Perform a quick check if the path
+ * is already in a suitable form.
+ */
+
+ if (tclPlatform == TCL_PLATFORM_WINDOWS) {
+ if (strchr(strElt, '\\') != NULL) {
+ goto noQuickReturn;
+ }
+ }
+ ptr = strElt;
+ while (*ptr != '\0') {
+ if (*ptr == '/' && (ptr[1] == '/' || ptr[1] == '\0')) {
+ /*
+ * We have a repeated file separator, which means the path
+ * is not in normalized form
+ */
+
+ goto noQuickReturn;
+ }
+ ptr++;
+ }
+ if (res != NULL) {
+ TclDecrRefCount(res);
+ }
+
+ /*
+ * This element is just what we want to return already - no
+ * further manipulation is requred.
+ */
+
+ return elt;
+ }
+
+ /*
+ * The path element was not of a suitable form to be returned as is.
+ * We need to perform a more complex operation here.
+ */
+
+ noQuickReturn:
+ if (res == NULL) {
+ res = Tcl_NewObj();
+ ptr = Tcl_GetStringFromObj(res, &length);
+ } else {
+ ptr = Tcl_GetStringFromObj(res, &length);
+ }
+
+ /*
+ * Strip off any './' before a tilde, unless this is the beginning of
+ * the path.
+ */
+
+ if (length > 0 && strEltLen > 0 && (strElt[0] == '.') &&
+ (strElt[1] == '/') && (strElt[2] == '~')) {
+ strElt += 2;
+ }
+
+ /*
+ * A NULL value for fsPtr at this stage basically means we're trying
+ * to join a relative path onto something which is also relative (or
+ * empty). There's nothing particularly wrong with that.
+ */
+
+ if (*strElt == '\0') {
+ continue;
+ }
+
+ if (fsPtr == &tclNativeFilesystem || fsPtr == NULL) {
+ TclpNativeJoinPath(res, strElt);
+ } else {
+ char separator = '/';
+ int needsSep = 0;
+
+ if (fsPtr->filesystemSeparatorProc != NULL) {
+ Tcl_Obj *sep = (*fsPtr->filesystemSeparatorProc)(res);
+
+ if (sep != NULL) {
+ separator = TclGetString(sep)[0];
+ }
+ }
+
+ if (length > 0 && ptr[length -1] != '/') {
+ Tcl_AppendToObj(res, &separator, 1);
+ length++;
+ }
+ Tcl_SetObjLength(res, length + (int) strlen(strElt));
+
+ ptr = TclGetString(res) + length;
+ for (; *strElt != '\0'; strElt++) {
+ if (*strElt == separator) {
+ while (strElt[1] == separator) {
+ strElt++;
+ }
+ if (strElt[1] != '\0') {
+ if (needsSep) {
+ *ptr++ = separator;
+ }
+ }
+ } else {
+ *ptr++ = *strElt;
+ needsSep = 1;
+ }
+ }
+ length = ptr - TclGetString(res);
+ Tcl_SetObjLength(res, length);
+ }
+ }
+ if (res == NULL) {
+ res = Tcl_NewObj();
+ }
+ return res;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tcl_FSConvertToPathType --
+ *
+ * This function tries to convert the given Tcl_Obj to a valid Tcl path
+ * type, taking account of the fact that the cwd may have changed even if
+ * this object is already supposedly of the correct type.
+ *
+ * The filename may begin with "~" (to indicate current user's home
+ * directory) or "~<user>" (to indicate any user's home directory).
+ *
+ * Results:
+ * Standard Tcl error code.
+ *
+ * Side effects:
+ * The old representation may be freed, and new memory allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+Tcl_FSConvertToPathType(
+ Tcl_Interp *interp, /* Interpreter in which to store error message
+ * (if necessary). */
+ Tcl_Obj *pathPtr) /* Object to convert to a valid, current path
+ * type. */
+{
+ /*
+ * While it is bad practice to examine an object's type directly, this is
+ * actually the best thing to do here. The reason is that if we are
+ * converting this object to FsPath type for the first time, we don't need
+ * to worry whether the 'cwd' has changed. On the other hand, if this
+ * object is already of FsPath type, and is a relative path, we do have to
+ * worry about the cwd. If the cwd has changed, we must recompute the
+ * path.
+ */
+
+ if (pathPtr->typePtr == &tclFsPathType) {
+ if (TclFSEpochOk(PATHOBJ(pathPtr)->filesystemEpoch)) {
+ return TCL_OK;
+ }
+
+ if (pathPtr->bytes == NULL) {
+ UpdateStringOfFsPath(pathPtr);
+ }
+ FreeFsPathInternalRep(pathPtr);
+ }
+
+ return Tcl_ConvertToType(interp, pathPtr, &tclFsPathType);
+
+ /*
+ * We used to have more complex code here:
+ *
+ * FsPath *fsPathPtr = PATHOBJ(pathPtr);
+ * if (fsPathPtr->cwdPtr == NULL || PATHFLAGS(pathPtr) != 0) {
+ * return TCL_OK;
+ * } else {
+ * if (TclFSCwdPointerEquals(&fsPathPtr->cwdPtr)) {
+ * return TCL_OK;
+ * } else {
+ * if (pathPtr->bytes == NULL) {
+ * UpdateStringOfFsPath(pathPtr);
+ * }
+ * FreeFsPathInternalRep(pathPtr);
+ * return Tcl_ConvertToType(interp, pathPtr, &tclFsPathType);
+ * }
+ * }
+ *
+ * But we no longer believe this is necessary.
+ */
+}
+
+/*
+ * Helper function for normalization.
+ */
+
+static int
+IsSeparatorOrNull(
+ int ch)
+{
+ if (ch == 0) {
+ return 1;
+ }
+ switch (tclPlatform) {
+ case TCL_PLATFORM_UNIX:
+ return (ch == '/' ? 1 : 0);
+ case TCL_PLATFORM_WINDOWS:
+ return ((ch == '/' || ch == '\\') ? 1 : 0);
+ }
+ return 0;
+}
+
+/*
+ * Helper function for SetFsPathFromAny. Returns position of first directory
+ * delimiter in the path. If no separator is found, then returns the position
+ * of the end of the string.
+ */
+
+static int
+FindSplitPos(
+ const char *path,
+ int separator)
+{
+ int count = 0;
+ switch (tclPlatform) {
+ case TCL_PLATFORM_UNIX:
+ while (path[count] != 0) {
+ if (path[count] == separator) {
+ return count;
+ }
+ count++;
+ }
+ break;
+
+ case TCL_PLATFORM_WINDOWS:
+ while (path[count] != 0) {
+ if (path[count] == separator || path[count] == '\\') {
+ return count;
+ }
+ count++;
+ }
+ break;
+ }
+ return count;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclNewFSPathObj --
+ *
+ * Creates a path object whose string representation is '[file join
+ * dirPtr addStrRep]', but does so in a way that allows for more
+ * efficient creation and caching of normalized paths, and more efficient
+ * 'file dirname', 'file tail', etc.
+ *
+ * Assumptions:
+ * 'dirPtr' must be an absolute path. 'len' may not be zero.
+ *
+ * Results:
+ * The new Tcl object, with refCount zero.
+ *
+ * Side effects:
+ * Memory is allocated. 'dirPtr' gets an additional refCount.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclNewFSPathObj(
+ Tcl_Obj *dirPtr,
+ const char *addStrRep,
+ int len)
+{
+ FsPath *fsPathPtr;
+ Tcl_Obj *pathPtr;
+ ThreadSpecificData *tsdPtr;
+ const char *p;
+ int state = 0, count = 0;
+
+ /* [Bug 2806250] - this is only a partial solution of the problem.
+ * The PATHFLAGS != 0 representation assumes in many places that
+ * the "tail" part stored in the normPathPtr field is itself a
+ * relative path. Strings that begin with "~" are not relative paths,
+ * so we must prevent their storage in the normPathPtr field.
+ *
+ * More generally we ought to be testing "addStrRep" for any value
+ * that is not a relative path, but in an unconstrained VFS world
+ * that could be just about anything, and testing could be expensive.
+ * Since this routine plays a big role in [glob], anything that slows
+ * it down would be unwelcome. For now, continue the risk of further
+ * bugs when some Tcl_Filesystem uses otherwise relative path strings
+ * as absolute path strings. Sensible Tcl_Filesystems will avoid
+ * that by mounting on path prefixes like foo:// which cannot be the
+ * name of a file or directory read from a native [glob] operation.
+ */
+ if (addStrRep[0] == '~') {
+ Tcl_Obj *tail = Tcl_NewStringObj(addStrRep, len);
+
+ pathPtr = AppendPath(dirPtr, tail);
+ Tcl_DecrRefCount(tail);
+ return pathPtr;
+ }
+
+ tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
+
+ pathPtr = Tcl_NewObj();
+ fsPathPtr = (FsPath *) ckalloc(sizeof(FsPath));
+
+ /*
+ * Set up the path.
+ */
+
+ fsPathPtr->translatedPathPtr = NULL;
+ fsPathPtr->normPathPtr = Tcl_NewStringObj(addStrRep, len);
+ Tcl_IncrRefCount(fsPathPtr->normPathPtr);
+ fsPathPtr->cwdPtr = dirPtr;
+ Tcl_IncrRefCount(dirPtr);
+ fsPathPtr->nativePathPtr = NULL;
+ fsPathPtr->fsRecPtr = NULL;
+ fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
+
+ SETPATHOBJ(pathPtr, fsPathPtr);
+ PATHFLAGS(pathPtr) = TCLPATH_APPENDED;
+ pathPtr->typePtr = &tclFsPathType;
+ pathPtr->bytes = NULL;
+ pathPtr->length = 0;
+
+ /*
+ * Look for path components made up of only "."
+ * This is overly conservative analysis to keep simple. It may
+ * mark some things as needing more aggressive normalization
+ * that don't actually need it. No harm done.
+ */
+ for (p = addStrRep; len > 0; p++, len--) {
+ switch (state) {
+ case 0: /* So far only "." since last dirsep or start */
+ switch (*p) {
+ case '.':
+ count++;
+ break;
+ case '/':
+ case '\\':
+ case ':':
+ if (count) {
+ PATHFLAGS(pathPtr) |= TCLPATH_NEEDNORM;
+ len = 0;
+ }
+ break;
+ default:
+ count = 0;
+ state = 1;
+ }
+ case 1: /* Scanning for next dirsep */
+ switch (*p) {
+ case '/':
+ case '\\':
+ case ':':
+ state = 0;
+ break;
+ }
+ }
+ }
+ if (len == 0 && count) {
+ PATHFLAGS(pathPtr) |= TCLPATH_NEEDNORM;
+ }
+
+ return pathPtr;
+}
+
+static Tcl_Obj *
+AppendPath(
+ Tcl_Obj *head,
+ Tcl_Obj *tail)
+{
+ int numBytes;
+ const char *bytes;
+ Tcl_Obj *copy = Tcl_DuplicateObj(head);
+
+ bytes = Tcl_GetStringFromObj(copy, &numBytes);
+
+ /*
+ * Should we perhaps use 'Tcl_FSPathSeparator'? But then what about the
+ * Windows special case? Perhaps we should just check if cwd is a root
+ * volume. We should never get numBytes == 0 in this code path.
+ */
+
+ switch (tclPlatform) {
+ case TCL_PLATFORM_UNIX:
+ if (bytes[numBytes-1] != '/') {
+ Tcl_AppendToObj(copy, "/", 1);
+ }
+ break;
+
+ case TCL_PLATFORM_WINDOWS:
+ /*
+ * We need the extra 'numBytes != 2', and ':' checks because a volume
+ * relative path doesn't get a '/'. For example 'glob C:*cat*.exe'
+ * will return 'C:cat32.exe'
+ */
+
+ if (bytes[numBytes-1] != '/' && bytes[numBytes-1] != '\\') {
+ if (numBytes!= 2 || bytes[1] != ':') {
+ Tcl_AppendToObj(copy, "/", 1);
+ }
+ }
+ break;
+ }
+
+ Tcl_AppendObjToObj(copy, tail);
+ return copy;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclFSMakePathRelative --
+ *
+ * Only for internal use.
+ *
+ * Takes a path and a directory, where we _assume_ both path and
+ * directory are absolute, normalized and that the path lies inside the
+ * directory. Returns a Tcl_Obj representing filename of the path
+ * relative to the directory.
+ *
+ * Results:
+ * NULL on error, otherwise a valid object, typically with refCount of
+ * zero, which it is assumed the caller will increment.
+ *
+ * Side effects:
+ * The old representation may be freed, and new memory allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclFSMakePathRelative(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tcl_Obj *pathPtr, /* The path we have. */
+ Tcl_Obj *cwdPtr) /* Make it relative to this. */
+{
+ int cwdLen, len;
+ const char *tempStr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
+
+ if (pathPtr->typePtr == &tclFsPathType) {
+ FsPath *fsPathPtr = PATHOBJ(pathPtr);
+
+ if (PATHFLAGS(pathPtr) != 0
+ && fsPathPtr->cwdPtr == cwdPtr) {
+ pathPtr = fsPathPtr->normPathPtr;
+
+ /* TODO: Determine how much, if any, of this forcing
+ * the relative path tail into the "path" Tcl_ObjType
+ * with a recorded cwdPtr context has any actual value.
+ *
+ * Nothing is getting cached. Not normPathPtr, not nativePathPtr,
+ * nor fsRecPtr, so storing the cwdPtr context against which such
+ * cached values might later be validated appears to be of no
+ * value. Take that away, and all this code is just a mildly
+ * optimized equivalent of a call to SetFsPathFromAny(). That
+ * optimization may have some value, *if* these value in fact
+ * get used as "path" values before used as something else.
+ * If not, though, whatever cost we pay below to convert to
+ * one of the "path" intreps is just a waste, it seems. The
+ * usual convention in the core is to delay ObjType conversion
+ * until it is needed and demanded, and I don't see why this
+ * section of code should be an exception to that. Leaving it
+ * in place for the rest of the 8.5.* releases just for sake
+ * of stability.
+ */
+
+ /*
+ * Free old representation.
+ */
+
+ if (pathPtr->typePtr != NULL) {
+ if (pathPtr->bytes == NULL) {
+ if (pathPtr->typePtr->updateStringProc == NULL) {
+ if (interp != NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "can't find object"
+ "string representation", NULL);
+ }
+ return NULL;
+ }
+ pathPtr->typePtr->updateStringProc(pathPtr);
+ }
+ TclFreeIntRep(pathPtr);
+ }
+
+ /*
+ * Now pathPtr is a string object.
+ */
+
+ fsPathPtr = (FsPath *) ckalloc(sizeof(FsPath));
+
+ /*
+ * Circular reference, by design.
+ */
+
+ fsPathPtr->translatedPathPtr = pathPtr;
+ fsPathPtr->normPathPtr = NULL;
+ fsPathPtr->cwdPtr = cwdPtr;
+ Tcl_IncrRefCount(cwdPtr);
+ fsPathPtr->nativePathPtr = NULL;
+ fsPathPtr->fsRecPtr = NULL;
+ fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
+
+ SETPATHOBJ(pathPtr, fsPathPtr);
+ PATHFLAGS(pathPtr) = 0;
+ pathPtr->typePtr = &tclFsPathType;
+
+ return pathPtr;
+ }
+ }
+
+ /*
+ * We know the cwd is a normalised object which does not end in a
+ * directory delimiter, unless the cwd is the name of a volume, in which
+ * case it will end in a delimiter! We handle this situation here. A
+ * better test than the '!= sep' might be to simply check if 'cwd' is a
+ * root volume.
+ *
+ * Note that if we get this wrong, we will strip off either too much or
+ * too little below, leading to wrong answers returned by glob.
+ */
+
+ tempStr = Tcl_GetStringFromObj(cwdPtr, &cwdLen);
+
+ /*
+ * Should we perhaps use 'Tcl_FSPathSeparator'? But then what about the
+ * Windows special case? Perhaps we should just check if cwd is a root
+ * volume.
+ */
+
+ switch (tclPlatform) {
+ case TCL_PLATFORM_UNIX:
+ if (tempStr[cwdLen-1] != '/') {
+ cwdLen++;
+ }
+ break;
+ case TCL_PLATFORM_WINDOWS:
+ if (tempStr[cwdLen-1] != '/' && tempStr[cwdLen-1] != '\\') {
+ cwdLen++;
+ }
+ break;
+ }
+ tempStr = Tcl_GetStringFromObj(pathPtr, &len);
+
+ return Tcl_NewStringObj(tempStr + cwdLen, len - cwdLen);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclFSMakePathFromNormalized --
+ *
+ * Like SetFsPathFromAny, but assumes the given object is an absolute
+ * normalized path. Only for internal use.
+ *
+ * Results:
+ * Standard Tcl error code.
+ *
+ * Side effects:
+ * The old representation may be freed, and new memory allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclFSMakePathFromNormalized(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tcl_Obj *pathPtr, /* The object to convert. */
+ ClientData nativeRep) /* The native rep for the object, if known
+ * else NULL. */
+{
+ FsPath *fsPathPtr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
+
+ if (pathPtr->typePtr == &tclFsPathType) {
+ return TCL_OK;
+ }
+
+ /*
+ * Free old representation
+ */
+
+ if (pathPtr->typePtr != NULL) {
+ if (pathPtr->bytes == NULL) {
+ if (pathPtr->typePtr->updateStringProc == NULL) {
+ if (interp != NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "can't find object"
+ "string representation", NULL);
+ }
+ return TCL_ERROR;
+ }
+ pathPtr->typePtr->updateStringProc(pathPtr);
+ }
+ TclFreeIntRep(pathPtr);
+ }
+
+ fsPathPtr = (FsPath *) ckalloc(sizeof(FsPath));
+
+ /*
+ * It's a pure normalized absolute path.
+ */
+
+ fsPathPtr->translatedPathPtr = NULL;
+
+ /*
+ * Circular reference by design.
+ */
+
+ fsPathPtr->normPathPtr = pathPtr;
+ fsPathPtr->cwdPtr = NULL;
+ fsPathPtr->nativePathPtr = nativeRep;
+ fsPathPtr->fsRecPtr = NULL;
+ fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
+
+ SETPATHOBJ(pathPtr, fsPathPtr);
+ PATHFLAGS(pathPtr) = 0;
+ pathPtr->typePtr = &tclFsPathType;
+
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tcl_FSNewNativePath --
+ *
+ * This function performs the something like the reverse of the usual
+ * obj->path->nativerep conversions. If some code retrieves a path in
+ * native form (from, e.g. readlink or a native dialog), and that path is
+ * to be used at the Tcl level, then calling this function is an
+ * efficient way of creating the appropriate path object type.
+ *
+ * Any memory which is allocated for 'clientData' should be retained
+ * until clientData is passed to the filesystem's freeInternalRepProc
+ * when it can be freed. The built in platform-specific filesystems use
+ * 'ckalloc' to allocate clientData, and ckfree to free it.
+ *
+ * Results:
+ * NULL or a valid path object pointer, with refCount zero.
+ *
+ * Side effects:
+ * New memory may be allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tcl_FSNewNativePath(
+ Tcl_Filesystem *fromFilesystem,
+ ClientData clientData)
+{
+ Tcl_Obj *pathPtr;
+ FsPath *fsPathPtr;
+
+ FilesystemRecord *fsFromPtr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
+
+ pathPtr = TclFSInternalToNormalized(fromFilesystem, clientData,
+ &fsFromPtr);
+ if (pathPtr == NULL) {
+ return NULL;
+ }
+
+ /*
+ * Free old representation; shouldn't normally be any, but best to be
+ * safe.
+ */
+
+ if (pathPtr->typePtr != NULL) {
+ if (pathPtr->bytes == NULL) {
+ if (pathPtr->typePtr->updateStringProc == NULL) {
+ return NULL;
+ }
+ pathPtr->typePtr->updateStringProc(pathPtr);
+ }
+ TclFreeIntRep(pathPtr);
+ }
+
+ fsPathPtr = (FsPath *) ckalloc(sizeof(FsPath));
+
+ fsPathPtr->translatedPathPtr = NULL;
+
+ /*
+ * Circular reference, by design.
+ */
+
+ fsPathPtr->normPathPtr = pathPtr;
+ fsPathPtr->cwdPtr = NULL;
+ fsPathPtr->nativePathPtr = clientData;
+ fsPathPtr->fsRecPtr = fsFromPtr;
+ fsPathPtr->fsRecPtr->fileRefCount++;
+ fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
+
+ SETPATHOBJ(pathPtr, fsPathPtr);
+ PATHFLAGS(pathPtr) = 0;
+ pathPtr->typePtr = &tclFsPathType;
+
+ return pathPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tcl_FSGetTranslatedPath --
+ *
+ * This function attempts to extract the translated path from the given
+ * Tcl_Obj. If the translation succeeds (i.e. the object is a valid
+ * path), then it is returned. Otherwise NULL will be returned, and an
+ * error message may be left in the interpreter (if it is non-NULL)
+ *
+ * Results:
+ * NULL or a valid Tcl_Obj pointer.
+ *
+ * Side effects:
+ * Only those of 'Tcl_FSConvertToPathType'
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tcl_FSGetTranslatedPath(
+ Tcl_Interp *interp,
+ Tcl_Obj *pathPtr)
+{
+ Tcl_Obj *retObj = NULL;
+ FsPath *srcFsPathPtr;
+
+ if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) {
+ return NULL;
+ }
+ srcFsPathPtr = PATHOBJ(pathPtr);
+ if (srcFsPathPtr->translatedPathPtr == NULL) {
+ if (PATHFLAGS(pathPtr) != 0) {
+ /*
+ * We lack a translated path result, but we have a directory
+ * (cwdPtr) and a tail (normPathPtr), and if we join the
+ * translated version of cwdPtr to normPathPtr, we'll get the
+ * translated result we need, and can store it for future use.
+ */
+
+ Tcl_Obj *translatedCwdPtr = Tcl_FSGetTranslatedPath(interp,
+ srcFsPathPtr->cwdPtr);
+ if (translatedCwdPtr == NULL) {
+ return NULL;
+ }
+
+ retObj = Tcl_FSJoinToPath(translatedCwdPtr, 1,
+ &(srcFsPathPtr->normPathPtr));
+ srcFsPathPtr->translatedPathPtr = retObj;
+ Tcl_IncrRefCount(retObj);
+ Tcl_DecrRefCount(translatedCwdPtr);
+ } else {
+ /*
+ * It is a pure absolute, normalized path object. This is
+ * something like being a 'pure list'. The object's string,
+ * translatedPath and normalizedPath are all identical.
+ */
+
+ retObj = srcFsPathPtr->normPathPtr;
+ }
+ } else {
+ /*
+ * It is an ordinary path object.
+ */
+
+ retObj = srcFsPathPtr->translatedPathPtr;
+ }
+
+ if (retObj != NULL) {
+ Tcl_IncrRefCount(retObj);
+ }
+ return retObj;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tcl_FSGetTranslatedStringPath --
+ *
+ * This function attempts to extract the translated path from the given
+ * Tcl_Obj. If the translation succeeds (i.e. the object is a valid
+ * path), then the path is returned. Otherwise NULL will be returned, and
+ * an error message may be left in the interpreter (if it is non-NULL)
+ *
+ * Results:
+ * NULL or a valid string.
+ *
+ * Side effects:
+ * Only those of 'Tcl_FSConvertToPathType'
+ *
+ *---------------------------------------------------------------------------
+ */
+
+const char *
+Tcl_FSGetTranslatedStringPath(
+ Tcl_Interp *interp,
+ Tcl_Obj *pathPtr)
+{
+ Tcl_Obj *transPtr = Tcl_FSGetTranslatedPath(interp, pathPtr);
+
+ if (transPtr != NULL) {
+ int len;
+ const char *orig = Tcl_GetStringFromObj(transPtr, &len);
+ char *result = (char *) ckalloc((unsigned) len+1);
+
+ memcpy(result, orig, (size_t) len+1);
+ TclDecrRefCount(transPtr);
+ return result;
+ }
+
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tcl_FSGetNormalizedPath --
+ *
+ * This important function attempts to extract from the given Tcl_Obj a
+ * unique normalised path representation, whose string value can be used
+ * as a unique identifier for the file.
+ *
+ * Results:
+ * NULL or a valid path object pointer.
+ *
+ * Side effects:
+ * New memory may be allocated. The Tcl 'errno' may be modified in the
+ * process of trying to examine various path possibilities.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tcl_FSGetNormalizedPath(
+ Tcl_Interp *interp,
+ Tcl_Obj *pathPtr)
+{
+ FsPath *fsPathPtr;
+
+ if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) {
+ return NULL;
+ }
+ fsPathPtr = PATHOBJ(pathPtr);
+
+ if (PATHFLAGS(pathPtr) != 0) {
+ /*
+ * This is a special path object which is the result of something like
+ * 'file join'
+ */
+
+ Tcl_Obj *dir, *copy;
+ int cwdLen, pathType;
+ ClientData clientData = NULL;
+
+ pathType = Tcl_FSGetPathType(fsPathPtr->cwdPtr);
+ dir = Tcl_FSGetNormalizedPath(interp, fsPathPtr->cwdPtr);
+ if (dir == NULL) {
+ return NULL;
+ }
+ /* TODO: Figure out why this is needed. */
+ if (pathPtr->bytes == NULL) {
+ UpdateStringOfFsPath(pathPtr);
+ }
+
+ copy = AppendPath(dir, fsPathPtr->normPathPtr);
+ Tcl_IncrRefCount(dir);
+ Tcl_IncrRefCount(copy);
+
+ /*
+ * We now own a reference on both 'dir' and 'copy'
+ */
+
+ (void) Tcl_GetStringFromObj(dir, &cwdLen);
+ cwdLen += (Tcl_GetString(copy)[cwdLen] == '/');
+
+ /* Normalize the combined string. */
+
+ if (PATHFLAGS(pathPtr) & TCLPATH_NEEDNORM) {
+ /*
+ * If the "tail" part has components (like /../) that cause
+ * the combined path to need more complete normalizing,
+ * call on the more powerful routine to accomplish that so
+ * we avoid [Bug 2385549] ...
+ */
+
+ Tcl_Obj *newCopy = TclFSNormalizeAbsolutePath(interp, copy, NULL);
+ Tcl_DecrRefCount(copy);
+ copy = newCopy;
+ } else {
+ /*
+ * ... but in most cases where we join a trouble free tail
+ * to a normalized head, we can more efficiently normalize the
+ * combined path by passing over only the unnormalized tail
+ * portion. When this is sufficient, prior developers claim
+ * this should be much faster. We use 'cwdLen-1' so that we are
+ * already pointing at the dir-separator that we know about.
+ * The normalization code will actually start off directly
+ * after that separator.
+ */
+
+ TclFSNormalizeToUniquePath(interp, copy, cwdLen-1,
+ (fsPathPtr->nativePathPtr == NULL ? &clientData : NULL));
+ }
+
+ /* Now we need to construct the new path object. */
+
+ if (pathType == TCL_PATH_RELATIVE) {
+ Tcl_Obj *origDir = fsPathPtr->cwdPtr;
+
+ /*
+ * NOTE: here we are (dangerously?) assuming that origDir points
+ * to a Tcl_Obj with Tcl_ObjType == &tclFsPathType . The
+ * pathType = Tcl_FSGetPathType(fsPathPtr->cwdPtr);
+ * above that set the pathType value should have established
+ * that, but it's far less clear on what basis we know there's
+ * been no shimmering since then.
+ */
+
+ FsPath *origDirFsPathPtr = PATHOBJ(origDir);
+
+ fsPathPtr->cwdPtr = origDirFsPathPtr->cwdPtr;
+ Tcl_IncrRefCount(fsPathPtr->cwdPtr);
+
+ TclDecrRefCount(fsPathPtr->normPathPtr);
+ fsPathPtr->normPathPtr = copy;
+
+ /*
+ * That's our reference to copy used.
+ */
+
+ TclDecrRefCount(dir);
+ TclDecrRefCount(origDir);
+ } else {
+ TclDecrRefCount(fsPathPtr->cwdPtr);
+ fsPathPtr->cwdPtr = NULL;
+ TclDecrRefCount(fsPathPtr->normPathPtr);
+ fsPathPtr->normPathPtr = copy;
+
+ /*
+ * That's our reference to copy used.
+ */
+
+ TclDecrRefCount(dir);
+ }
+ if (clientData != NULL) {
+ /*
+ * This may be unnecessary. It appears that the
+ * TclFSNormalizeToUniquePath call above should have already
+ * set this up. Not changing out of fear of the unknown.
+ */
+
+ fsPathPtr->nativePathPtr = clientData;
+ }
+ PATHFLAGS(pathPtr) = 0;
+ }
+
+ /*
+ * Ensure cwd hasn't changed.
+ */
+
+ if (fsPathPtr->cwdPtr != NULL) {
+ if (!TclFSCwdPointerEquals(&fsPathPtr->cwdPtr)) {
+ if (pathPtr->bytes == NULL) {
+ UpdateStringOfFsPath(pathPtr);
+ }
+ FreeFsPathInternalRep(pathPtr);
+ if (Tcl_ConvertToType(interp, pathPtr, &tclFsPathType) != TCL_OK) {
+ return NULL;
+ }
+ fsPathPtr = PATHOBJ(pathPtr);
+ } else if (fsPathPtr->normPathPtr == NULL) {
+ int cwdLen;
+ Tcl_Obj *copy;
+ ClientData clientData = NULL;
+
+ copy = AppendPath(fsPathPtr->cwdPtr, pathPtr);
+
+ (void) Tcl_GetStringFromObj(fsPathPtr->cwdPtr, &cwdLen);
+ cwdLen += (Tcl_GetString(copy)[cwdLen] == '/');
+
+ /*
+ * Normalize the combined string, but only starting after the end
+ * of the previously normalized 'dir'. This should be much faster!
+ */
+
+ TclFSNormalizeToUniquePath(interp, copy, cwdLen-1,
+ (fsPathPtr->nativePathPtr == NULL ? &clientData : NULL));
+ fsPathPtr->normPathPtr = copy;
+ Tcl_IncrRefCount(fsPathPtr->normPathPtr);
+ if (clientData != NULL) {
+ fsPathPtr->nativePathPtr = clientData;
+ }
+ }
+ }
+ if (fsPathPtr->normPathPtr == NULL) {
+ ClientData clientData = NULL;
+ Tcl_Obj *useThisCwd = NULL;
+ int pureNormalized = 1;
+
+ /*
+ * Since normPathPtr is NULL, but this is a valid path object, we know
+ * that the translatedPathPtr cannot be NULL.
+ */
+
+ Tcl_Obj *absolutePath = fsPathPtr->translatedPathPtr;
+ const char *path = TclGetString(absolutePath);
+
+ Tcl_IncrRefCount(absolutePath);
+
+ /*
+ * We have to be a little bit careful here to avoid infinite loops
+ * we're asking Tcl_FSGetPathType to return the path's type, but that
+ * call can actually result in a lot of other filesystem action, which
+ * might loop back through here.
+ */
+
+ if (path[0] == '\0') {
+ /*
+ * Special handling for the empty string value. This one is
+ * very weird with [file normalize {}] => {}. (The reasoning
+ * supporting this is unknown to DGP, but he fears changing it.)
+ * Attempt here to keep the expectations of other parts of
+ * Tcl_Filesystem code about state of the FsPath fields satisfied.
+ *
+ * In particular, capture the cwd value and save so it can be
+ * stored in the cwdPtr field below.
+ */
+
+ useThisCwd = Tcl_FSGetCwd(interp);
+ } else {
+ /*
+ * We don't ask for the type of 'pathPtr' here, because that is
+ * not correct for our purposes when we have a path like '~'. Tcl
+ * has a bit of a contradiction in that '~' paths are defined as
+ * 'absolute', but in reality can be just about anything,
+ * depending on how env(HOME) is set.
+ */
+
+ Tcl_PathType type = Tcl_FSGetPathType(absolutePath);
+
+ if (type == TCL_PATH_RELATIVE) {
+ useThisCwd = Tcl_FSGetCwd(interp);
+
+ if (useThisCwd == NULL) {
+ return NULL;
+ }
+
+ pureNormalized = 0;
+ Tcl_DecrRefCount(absolutePath);
+ absolutePath = Tcl_FSJoinToPath(useThisCwd, 1, &absolutePath);
+ Tcl_IncrRefCount(absolutePath);
+
+ /*
+ * We have a refCount on the cwd.
+ */
+#ifdef __WIN32__
+ } else if (type == TCL_PATH_VOLUME_RELATIVE) {
+ /*
+ * Only Windows has volume-relative paths.
+ */
+
+ Tcl_DecrRefCount(absolutePath);
+ absolutePath = TclWinVolumeRelativeNormalize(interp,
+ path, &useThisCwd);
+ if (absolutePath == NULL) {
+ return NULL;
+ }
+ pureNormalized = 0;
+#endif /* __WIN32__ */
+ }
+ }
+
+ /*
+ * Already has refCount incremented.
+ */
+
+ fsPathPtr->normPathPtr = TclFSNormalizeAbsolutePath(interp,
+ absolutePath,
+ (fsPathPtr->nativePathPtr == NULL ? &clientData : NULL));
+ if (0 && (clientData != NULL)) {
+ fsPathPtr->nativePathPtr =
+ (*fsPathPtr->fsRecPtr->fsPtr->dupInternalRepProc)(clientData);
+ }
+
+ /*
+ * Check if path is pure normalized (this can only be the case if it
+ * is an absolute path).
+ */
+
+ if (pureNormalized) {
+ if (!strcmp(TclGetString(fsPathPtr->normPathPtr),
+ TclGetString(pathPtr))) {
+ /*
+ * The path was already normalized. Get rid of the duplicate.
+ */
+
+ TclDecrRefCount(fsPathPtr->normPathPtr);
+
+ /*
+ * We do *not* increment the refCount for this circular
+ * reference.
+ */
+
+ fsPathPtr->normPathPtr = pathPtr;
+ }
+ }
+ if (useThisCwd != NULL) {
+ /*
+ * We just need to free an object we allocated above for relative
+ * paths (this was returned by Tcl_FSJoinToPath above), and then
+ * of course store the cwd.
+ */
+
+ fsPathPtr->cwdPtr = useThisCwd;
+ }
+ TclDecrRefCount(absolutePath);
+ }
+
+ return fsPathPtr->normPathPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tcl_FSGetInternalRep --
+ *
+ * Extract the internal representation of a given path object, in the
+ * given filesystem. If the path object belongs to a different
+ * filesystem, we return NULL.
+ *
+ * If the internal representation is currently NULL, we attempt to
+ * generate it, by calling the filesystem's
+ * 'Tcl_FSCreateInternalRepProc'.
+ *
+ * Results:
+ * NULL or a valid internal representation.
+ *
+ * Side effects:
+ * An attempt may be made to convert the object.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+ClientData
+Tcl_FSGetInternalRep(
+ Tcl_Obj *pathPtr,
+ Tcl_Filesystem *fsPtr)
+{
+ FsPath *srcFsPathPtr;
+
+ if (Tcl_FSConvertToPathType(NULL, pathPtr) != TCL_OK) {
+ return NULL;
+ }
+ srcFsPathPtr = PATHOBJ(pathPtr);
+
+ /*
+ * We will only return the native representation for the caller's
+ * filesystem. Otherwise we will simply return NULL. This means that there
+ * must be a unique bi-directional mapping between paths and filesystems,
+ * and that this mapping will not allow 'remapped' files -- files which
+ * are in one filesystem but mapped into another. Another way of putting
+ * this is that 'stacked' filesystems are not allowed. We recognise that
+ * this is a potentially useful feature for the future.
+ *
+ * Even something simple like a 'pass through' filesystem which logs all
+ * activity and passes the calls onto the native system would be nice, but
+ * not easily achievable with the current implementation.
+ */
+
+ if (srcFsPathPtr->fsRecPtr == NULL) {
+ /*
+ * This only usually happens in wrappers like TclpStat which create a
+ * string object and pass it to TclpObjStat. Code which calls the
+ * Tcl_FS.. functions should always have a filesystem already set.
+ * Whether this code path is legal or not depends on whether we decide
+ * to allow external code to call the native filesystem directly. It
+ * is at least safer to allow this sub-optimal routing.
+ */
+
+ Tcl_FSGetFileSystemForPath(pathPtr);
+
+ /*
+ * If we fail through here, then the path is probably not a valid path
+ * in the filesystsem, and is most likely to be a use of the empty
+ * path "" via a direct call to one of the objectified interfaces
+ * (e.g. from the Tcl testsuite).
+ */
+
+ srcFsPathPtr = PATHOBJ(pathPtr);
+ if (srcFsPathPtr->fsRecPtr == NULL) {
+ return NULL;
+ }
+ }
+
+ /*
+ * There is still one possibility we should consider; if the file belongs
+ * to a different filesystem, perhaps it is actually linked through to a
+ * file in our own filesystem which we do care about. The way we can check
+ * for this is we ask what filesystem this path belongs to.
+ */
+
+ if (fsPtr != srcFsPathPtr->fsRecPtr->fsPtr) {
+ const Tcl_Filesystem *actualFs = Tcl_FSGetFileSystemForPath(pathPtr);
+
+ if (actualFs == fsPtr) {
+ return Tcl_FSGetInternalRep(pathPtr, fsPtr);
+ }
+ return NULL;
+ }
+
+ if (srcFsPathPtr->nativePathPtr == NULL) {
+ Tcl_FSCreateInternalRepProc *proc;
+ char *nativePathPtr;
+
+ proc = srcFsPathPtr->fsRecPtr->fsPtr->createInternalRepProc;
+ if (proc == NULL) {
+ return NULL;
+ }
+
+ nativePathPtr = (*proc)(pathPtr);
+ srcFsPathPtr = PATHOBJ(pathPtr);
+ srcFsPathPtr->nativePathPtr = nativePathPtr;
+ }
+
+ return srcFsPathPtr->nativePathPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclFSEnsureEpochOk --
+ *
+ * This will ensure the pathPtr is up to date and can be converted into a
+ * "path" type, and that we are able to generate a complete normalized
+ * path which is used to determine the filesystem match.
+ *
+ * Results:
+ * Standard Tcl return code.
+ *
+ * Side effects:
+ * An attempt may be made to convert the object.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclFSEnsureEpochOk(
+ Tcl_Obj *pathPtr,
+ Tcl_Filesystem **fsPtrPtr)
+{
+ FsPath *srcFsPathPtr;
+
+ if (pathPtr->typePtr != &tclFsPathType) {
+ return TCL_OK;
+ }
+
+ srcFsPathPtr = PATHOBJ(pathPtr);
+
+ /*
+ * Check if the filesystem has changed in some way since this object's
+ * internal representation was calculated.
+ */
+
+ if (!TclFSEpochOk(srcFsPathPtr->filesystemEpoch)) {
+ /*
+ * We have to discard the stale representation and recalculate it.
+ */
+
+ if (pathPtr->bytes == NULL) {
+ UpdateStringOfFsPath(pathPtr);
+ }
+ FreeFsPathInternalRep(pathPtr);
+ if (SetFsPathFromAny(NULL, pathPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ srcFsPathPtr = PATHOBJ(pathPtr);
+ }
+
+ /*
+ * Check whether the object is already assigned to a fs.
+ */
+
+ if (srcFsPathPtr->fsRecPtr != NULL) {
+ *fsPtrPtr = srcFsPathPtr->fsRecPtr->fsPtr;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclFSSetPathDetails --
+ *
+ * ???
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * ???
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+TclFSSetPathDetails(
+ Tcl_Obj *pathPtr,
+ FilesystemRecord *fsRecPtr,
+ ClientData clientData)
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
+ FsPath *srcFsPathPtr;
+
+ /*
+ * Make sure pathPtr is of the correct type.
+ */
+
+ if (pathPtr->typePtr != &tclFsPathType) {
+ if (SetFsPathFromAny(NULL, pathPtr) != TCL_OK) {
+ return;
+ }
+ }
+
+ srcFsPathPtr = PATHOBJ(pathPtr);
+ srcFsPathPtr->fsRecPtr = fsRecPtr;
+ srcFsPathPtr->nativePathPtr = clientData;
+ srcFsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
+ fsRecPtr->fileRefCount++;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tcl_FSEqualPaths --
+ *
+ * This function tests whether the two paths given are equal path
+ * objects. If either or both is NULL, 0 is always returned.
+ *
+ * Results:
+ * 1 or 0.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+Tcl_FSEqualPaths(
+ Tcl_Obj *firstPtr,
+ Tcl_Obj *secondPtr)
+{
+ char *firstStr, *secondStr;
+ int firstLen, secondLen, tempErrno;
+
+ if (firstPtr == secondPtr) {
+ return 1;
+ }
+
+ if (firstPtr == NULL || secondPtr == NULL) {
+ return 0;
+ }
+ firstStr = Tcl_GetStringFromObj(firstPtr, &firstLen);
+ secondStr = Tcl_GetStringFromObj(secondPtr, &secondLen);
+ if ((firstLen == secondLen) && (strcmp(firstStr, secondStr) == 0)) {
+ return 1;
+ }
+
+ /*
+ * Try the most thorough, correct method of comparing fully normalized
+ * paths.
+ */
+
+ tempErrno = Tcl_GetErrno();
+ firstPtr = Tcl_FSGetNormalizedPath(NULL, firstPtr);
+ secondPtr = Tcl_FSGetNormalizedPath(NULL, secondPtr);
+ Tcl_SetErrno(tempErrno);
+
+ if (firstPtr == NULL || secondPtr == NULL) {
+ return 0;
+ }
+
+ firstStr = Tcl_GetStringFromObj(firstPtr, &firstLen);
+ secondStr = Tcl_GetStringFromObj(secondPtr, &secondLen);
+ return (firstLen == secondLen) && (strcmp(firstStr, secondStr) == 0);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SetFsPathFromAny --
+ *
+ * This function tries to convert the given Tcl_Obj to a valid Tcl path
+ * type.
+ *
+ * The filename may begin with "~" (to indicate current user's home
+ * directory) or "~<user>" (to indicate any user's home directory).
+ *
+ * Results:
+ * Standard Tcl error code.
+ *
+ * Side effects:
+ * The old representation may be freed, and new memory allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+SetFsPathFromAny(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tcl_Obj *pathPtr) /* The object to convert. */
+{
+ int len;
+ FsPath *fsPathPtr;
+ Tcl_Obj *transPtr;
+ char *name;
+#if defined(__CYGWIN__) && defined(__WIN32__)
+ int copied = 0;
+#endif
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
+
+ if (pathPtr->typePtr == &tclFsPathType) {
+ return TCL_OK;
+ }
+
+ /*
+ * First step is to translate the filename. This is similar to
+ * Tcl_TranslateFilename, but shouldn't convert everything to windows
+ * backslashes on that platform. The current implementation of this piece
+ * is a slightly optimised version of the various Tilde/Split/Join stuff
+ * to avoid multiple split/join operations.
+ *
+ * We remove any trailing directory separator.
+ *
+ * However, the split/join routines are quite complex, and one has to make
+ * sure not to break anything on Unix or Win (fCmd.test, fileName.test and
+ * cmdAH.test exercise most of the code).
+ */
+
+ name = Tcl_GetStringFromObj(pathPtr, &len);
+
+ /*
+ * Handle tilde substitutions, if needed.
+ */
+
+ if (name[0] == '~') {
+ char *expandedUser;
+ Tcl_DString temp;
+ int split;
+ char separator = '/';
+
+ split = FindSplitPos(name, separator);
+ if (split != len) {
+ /*
+ * We have multiple pieces '~user/foo/bar...'
+ */
+
+ name[split] = '\0';
+ }
+
+ /*
+ * Do some tilde substitution.
+ */
+
+ if (name[1] == '\0') {
+ /*
+ * We have just '~'
+ */
+
+ const char *dir;
+ Tcl_DString dirString;
+
+ if (split != len) {
+ name[split] = separator;
+ }
+
+ dir = TclGetEnv("HOME", &dirString);
+ if (dir == NULL) {
+ if (interp) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "couldn't find HOME environment "
+ "variable to expand path", NULL);
+ }
+ return TCL_ERROR;
+ }
+ Tcl_DStringInit(&temp);
+ Tcl_JoinPath(1, &dir, &temp);
+ Tcl_DStringFree(&dirString);
+ } else {
+ /*
+ * We have a user name '~user'
+ */
+
+ Tcl_DStringInit(&temp);
+ if (TclpGetUserHome(name+1, &temp) == NULL) {
+ if (interp != NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "user \"", name+1,
+ "\" doesn't exist", NULL);
+ }
+ Tcl_DStringFree(&temp);
+ if (split != len) {
+ name[split] = separator;
+ }
+ return TCL_ERROR;
+ }
+ if (split != len) {
+ name[split] = separator;
+ }
+ }
+
+ expandedUser = Tcl_DStringValue(&temp);
+ transPtr = Tcl_NewStringObj(expandedUser, Tcl_DStringLength(&temp));
+
+ if (split != len) {
+ /*
+ * Join up the tilde substitution with the rest.
+ */
+
+ if (name[split+1] == separator) {
+ /*
+ * Somewhat tricky case like ~//foo/bar. Make use of
+ * Split/Join machinery to get it right. Assumes all paths
+ * beginning with ~ are part of the native filesystem.
+ */
+
+ int objc;
+ Tcl_Obj **objv;
+ Tcl_Obj *parts = TclpNativeSplitPath(pathPtr, NULL);
+
+ Tcl_ListObjGetElements(NULL, parts, &objc, &objv);
+
+ /*
+ * Skip '~'. It's replaced by its expansion.
+ */
+
+ objc--; objv++;
+ while (objc--) {
+ TclpNativeJoinPath(transPtr, Tcl_GetString(*objv++));
+ }
+ TclDecrRefCount(parts);
+ } else {
+ /*
+ * Simple case. "rest" is relative path. Just join it. The
+ * "rest" object will be freed when Tcl_FSJoinToPath returns
+ * (unless something else claims a refCount on it).
+ */
+
+ Tcl_Obj *joined;
+ Tcl_Obj *rest = Tcl_NewStringObj(name+split+1, -1);
+
+ Tcl_IncrRefCount(transPtr);
+ joined = Tcl_FSJoinToPath(transPtr, 1, &rest);
+ TclDecrRefCount(transPtr);
+ transPtr = joined;
+ }
+ }
+ Tcl_DStringFree(&temp);
+ } else {
+ transPtr = Tcl_FSJoinToPath(pathPtr, 0, NULL);
+ }
+
+#if defined(__CYGWIN__) && defined(__WIN32__)
+ {
+ char winbuf[MAX_PATH+1];
+
+ /*
+ * In the Cygwin world, call conv_to_win32_path in order to use the
+ * mount table to translate the file name into something Windows will
+ * understand. Take care when converting empty strings!
+ */
+
+ name = Tcl_GetStringFromObj(transPtr, &len);
+ if (len > 0) {
+ cygwin_conv_to_win32_path(name, winbuf);
+ TclWinNoBackslash(winbuf);
+ if (Tcl_IsShared(transPtr)) {
+ copied = 1;
+ transPtr = Tcl_DuplicateObj(transPtr);
+ Tcl_IncrRefCount(transPtr);
+ }
+ Tcl_SetStringObj(transPtr, winbuf, -1);
+ }
+ }
+#endif /* __CYGWIN__ && __WIN32__ */
+
+ /*
+ * Now we have a translated filename in 'transPtr'. This will have forward
+ * slashes on Windows, and will not contain any ~user sequences.
+ */
+
+ fsPathPtr = (FsPath *) ckalloc(sizeof(FsPath));
+
+ fsPathPtr->translatedPathPtr = transPtr;
+ if (transPtr != pathPtr) {
+ Tcl_IncrRefCount(fsPathPtr->translatedPathPtr);
+ }
+ fsPathPtr->normPathPtr = NULL;
+ fsPathPtr->cwdPtr = NULL;
+ fsPathPtr->nativePathPtr = NULL;
+ fsPathPtr->fsRecPtr = NULL;
+ fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
+
+ /*
+ * Free old representation before installing our new one.
+ */
+
+ TclFreeIntRep(pathPtr);
+ SETPATHOBJ(pathPtr, fsPathPtr);
+ PATHFLAGS(pathPtr) = 0;
+ pathPtr->typePtr = &tclFsPathType;
+#if defined(__CYGWIN__) && defined(__WIN32__)
+ if (copied) {
+ Tcl_DecrRefCount(transPtr);
+ }
+#endif
+
+ return TCL_OK;
+}
+
+static void
+FreeFsPathInternalRep(
+ Tcl_Obj *pathPtr) /* Path object with internal rep to free. */
+{
+ FsPath *fsPathPtr = PATHOBJ(pathPtr);
+
+ if (fsPathPtr->translatedPathPtr != NULL) {
+ if (fsPathPtr->translatedPathPtr != pathPtr) {
+ TclDecrRefCount(fsPathPtr->translatedPathPtr);
+ }
+ }
+ if (fsPathPtr->normPathPtr != NULL) {
+ if (fsPathPtr->normPathPtr != pathPtr) {
+ TclDecrRefCount(fsPathPtr->normPathPtr);
+ }
+ fsPathPtr->normPathPtr = NULL;
+ }
+ if (fsPathPtr->cwdPtr != NULL) {
+ TclDecrRefCount(fsPathPtr->cwdPtr);
+ }
+ if (fsPathPtr->nativePathPtr != NULL && fsPathPtr->fsRecPtr != NULL) {
+ Tcl_FSFreeInternalRepProc *freeProc =
+ fsPathPtr->fsRecPtr->fsPtr->freeInternalRepProc;
+
+ if (freeProc != NULL) {
+ (*freeProc)(fsPathPtr->nativePathPtr);
+ fsPathPtr->nativePathPtr = NULL;
+ }
+ }
+ if (fsPathPtr->fsRecPtr != NULL) {
+ fsPathPtr->fsRecPtr->fileRefCount--;
+ if (fsPathPtr->fsRecPtr->fileRefCount <= 0) {
+ /*
+ * It has been unregistered already.
+ */
+
+ ckfree((char *) fsPathPtr->fsRecPtr);
+ }
+ }
+
+ ckfree((char *) fsPathPtr);
+ pathPtr->typePtr = NULL;
+}
+
+static void
+DupFsPathInternalRep(
+ Tcl_Obj *srcPtr, /* Path obj with internal rep to copy. */
+ Tcl_Obj *copyPtr) /* Path obj with internal rep to set. */
+{
+ FsPath *srcFsPathPtr = PATHOBJ(srcPtr);
+ FsPath *copyFsPathPtr = (FsPath *) ckalloc(sizeof(FsPath));
+
+ SETPATHOBJ(copyPtr, copyFsPathPtr);
+
+ if (srcFsPathPtr->translatedPathPtr == srcPtr) {
+ /* Cycle in src -> make cycle in copy. */
+ copyFsPathPtr->translatedPathPtr = copyPtr;
+ } else {
+ copyFsPathPtr->translatedPathPtr = srcFsPathPtr->translatedPathPtr;
+ if (copyFsPathPtr->translatedPathPtr != NULL) {
+ Tcl_IncrRefCount(copyFsPathPtr->translatedPathPtr);
+ }
+ }
+
+ if (srcFsPathPtr->normPathPtr == srcPtr) {
+ /* Cycle in src -> make cycle in copy. */
+ copyFsPathPtr->normPathPtr = copyPtr;
+ } else {
+ copyFsPathPtr->normPathPtr = srcFsPathPtr->normPathPtr;
+ if (copyFsPathPtr->normPathPtr != NULL) {
+ Tcl_IncrRefCount(copyFsPathPtr->normPathPtr);
+ }
+ }
+
+ copyFsPathPtr->cwdPtr = srcFsPathPtr->cwdPtr;
+ if (copyFsPathPtr->cwdPtr != NULL) {
+ Tcl_IncrRefCount(copyFsPathPtr->cwdPtr);
+ }
+
+ copyFsPathPtr->flags = srcFsPathPtr->flags;
+
+ if (srcFsPathPtr->fsRecPtr != NULL
+ && srcFsPathPtr->nativePathPtr != NULL) {
+ Tcl_FSDupInternalRepProc *dupProc =
+ srcFsPathPtr->fsRecPtr->fsPtr->dupInternalRepProc;
+
+ if (dupProc != NULL) {
+ copyFsPathPtr->nativePathPtr =
+ (*dupProc)(srcFsPathPtr->nativePathPtr);
+ } else {
+ copyFsPathPtr->nativePathPtr = NULL;
+ }
+ } else {
+ copyFsPathPtr->nativePathPtr = NULL;
+ }
+ copyFsPathPtr->fsRecPtr = srcFsPathPtr->fsRecPtr;
+ copyFsPathPtr->filesystemEpoch = srcFsPathPtr->filesystemEpoch;
+ if (copyFsPathPtr->fsRecPtr != NULL) {
+ copyFsPathPtr->fsRecPtr->fileRefCount++;
+ }
+
+ copyPtr->typePtr = &tclFsPathType;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * UpdateStringOfFsPath --
+ *
+ * Gives an object a valid string rep.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory may be allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+UpdateStringOfFsPath(
+ register Tcl_Obj *pathPtr) /* path obj with string rep to update. */
+{
+ FsPath *fsPathPtr = PATHOBJ(pathPtr);
+ int cwdLen;
+ Tcl_Obj *copy;
+
+ if (PATHFLAGS(pathPtr) == 0 || fsPathPtr->cwdPtr == NULL) {
+ Tcl_Panic("Called UpdateStringOfFsPath with invalid object");
+ }
+
+ copy = AppendPath(fsPathPtr->cwdPtr, fsPathPtr->normPathPtr);
+
+ pathPtr->bytes = Tcl_GetStringFromObj(copy, &cwdLen);
+ pathPtr->length = cwdLen;
+ copy->bytes = tclEmptyStringRep;
+ copy->length = 0;
+ TclDecrRefCount(copy);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclNativePathInFilesystem --
+ *
+ * Any path object is acceptable to the native filesystem, by default (we
+ * will throw errors when illegal paths are actually tried to be used).
+ *
+ * However, this behavior means the native filesystem must be the last
+ * filesystem in the lookup list (otherwise it will claim all files
+ * belong to it, and other filesystems will never get a look in).
+ *
+ * Results:
+ * TCL_OK, to indicate 'yes', -1 to indicate no.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclNativePathInFilesystem(
+ Tcl_Obj *pathPtr,
+ ClientData *clientDataPtr)
+{
+ /*
+ * A special case is required to handle the empty path "". This is a valid
+ * path (i.e. the user should be able to do 'file exists ""' without
+ * throwing an error), but equally the path doesn't exist. Those are the
+ * semantics of Tcl (at present anyway), so we have to abide by them here.
+ */
+
+ if (pathPtr->typePtr == &tclFsPathType) {
+ if (pathPtr->bytes != NULL && pathPtr->bytes[0] == '\0') {
+ /*
+ * We reject the empty path "".
+ */
+
+ return -1;
+ }
+
+ /*
+ * Otherwise there is no way this path can be empty.
+ */
+ } else {
+ /*
+ * It is somewhat unusual to reach this code path without the object
+ * being of tclFsPathType. However, we do our best to deal with the
+ * situation.
+ */
+
+ int len;
+
+ (void) Tcl_GetStringFromObj(pathPtr, &len);
+ if (len == 0) {
+ /*
+ * We reject the empty path "".
+ */
+
+ return -1;
+ }
+ }
+
+ /*
+ * Path is of correct type, or is of non-zero length, so we accept it.
+ */
+
+ return TCL_OK;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclPipe.c b/generic/tclPipe.c
index 1042e09..dd70e5e 100644
--- a/generic/tclPipe.c
+++ b/generic/tclPipe.c
@@ -1,60 +1,56 @@
-/*
+/*
* tclPipe.c --
*
- * This file contains the generic portion of the command channel
- * driver as well as various utility routines used in managing
- * subprocesses.
+ * This file contains the generic portion of the command channel driver
+ * as well as various utility routines used in managing subprocesses.
*
* Copyright (c) 1997 by Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
/*
- * A linked list of the following structures is used to keep track
- * of child processes that have been detached but haven't exited
- * yet, so we can make sure that they're properly "reaped" (officially
- * waited for) and don't lie around as zombies cluttering the
- * system.
+ * A linked list of the following structures is used to keep track of child
+ * processes that have been detached but haven't exited yet, so we can make
+ * sure that they're properly "reaped" (officially waited for) and don't lie
+ * around as zombies cluttering the system.
*/
typedef struct Detached {
- Tcl_Pid pid; /* Id of process that's been detached
- * but isn't known to have exited. */
- struct Detached *nextPtr; /* Next in list of all detached
- * processes. */
+ Tcl_Pid pid; /* Id of process that's been detached but
+ * isn't known to have exited. */
+ struct Detached *nextPtr; /* Next in list of all detached processes. */
} Detached;
-static Detached *detList = NULL; /* List of all detached proceses. */
-TCL_DECLARE_MUTEX(pipeMutex) /* Guard access to detList. */
+static Detached *detList = NULL;/* List of all detached proceses. */
+TCL_DECLARE_MUTEX(pipeMutex) /* Guard access to detList. */
/*
- * Declarations for local procedures defined in this file:
+ * Declarations for local functions defined in this file:
*/
-static TclFile FileForRedirect _ANSI_ARGS_((Tcl_Interp *interp,
- CONST char *spec, int atOk, CONST char *arg,
- CONST char *nextArg, int flags, int *skipPtr,
- int *closePtr, int *releasePtr));
+static TclFile FileForRedirect(Tcl_Interp *interp, CONST char *spec,
+ int atOk, CONST char *arg, CONST char *nextArg,
+ int flags, int *skipPtr, int *closePtr,
+ int *releasePtr);
/*
*----------------------------------------------------------------------
*
* FileForRedirect --
*
- * This procedure does much of the work of parsing redirection
- * operators. It handles "@" if specified and allowed, and a file
- * name, and opens the file if necessary.
+ * This function does much of the work of parsing redirection operators.
+ * It handles "@" if specified and allowed, and a file name, and opens
+ * the file if necessary.
*
* Results:
- * The return value is the descriptor number for the file. If an
- * error occurs then NULL is returned and an error message is left
- * in the interp's result. Several arguments are side-effected; see
- * the argument list below for details.
+ * The return value is the descriptor number for the file. If an error
+ * occurs then NULL is returned and an error message is left in the
+ * interp's result. Several arguments are side-effected; see the argument
+ * list below for details.
*
* Side effects:
* None.
@@ -63,34 +59,33 @@ static TclFile FileForRedirect _ANSI_ARGS_((Tcl_Interp *interp,
*/
static TclFile
-FileForRedirect(interp, spec, atOK, arg, nextArg, flags, skipPtr, closePtr,
- releasePtr)
- Tcl_Interp *interp; /* Intepreter to use for error reporting. */
- CONST char *spec; /* Points to character just after
- * redirection character. */
- int atOK; /* Non-zero means that '@' notation can be
+FileForRedirect(
+ Tcl_Interp *interp, /* Intepreter to use for error reporting. */
+ CONST char *spec, /* Points to character just after redirection
+ * character. */
+ int atOK, /* Non-zero means that '@' notation can be
* used to specify a channel, zero means that
* it isn't. */
- CONST char *arg; /* Pointer to entire argument containing
- * spec: used for error reporting. */
- CONST char *nextArg; /* Next argument in argc/argv array, if needed
- * for file name or channel name. May be
+ CONST char *arg, /* Pointer to entire argument containing spec:
+ * used for error reporting. */
+ CONST char *nextArg, /* Next argument in argc/argv array, if needed
+ * for file name or channel name. May be
* NULL. */
- int flags; /* Flags to use for opening file or to
- * specify mode for channel. */
- int *skipPtr; /* Filled with 1 if redirection target was
- * in spec, 2 if it was in nextArg. */
- int *closePtr; /* Filled with one if the caller should
- * close the file when done with it, zero
+ int flags, /* Flags to use for opening file or to specify
+ * mode for channel. */
+ int *skipPtr, /* Filled with 1 if redirection target was in
+ * spec, 2 if it was in nextArg. */
+ int *closePtr, /* Filled with one if the caller should close
+ * the file when done with it, zero
* otherwise. */
- int *releasePtr;
+ int *releasePtr)
{
int writing = (flags & O_WRONLY);
Tcl_Channel chan;
TclFile file;
*skipPtr = 1;
- if ((atOK != 0) && (*spec == '@')) {
+ if ((atOK != 0) && (*spec == '@')) {
spec++;
if (*spec == '\0') {
spec = nextArg;
@@ -105,18 +100,22 @@ FileForRedirect(interp, spec, atOK, arg, nextArg, flags, skipPtr, closePtr,
}
file = TclpMakeFile(chan, writing ? TCL_WRITABLE : TCL_READABLE);
if (file == NULL) {
- Tcl_AppendResult(interp, "channel \"", Tcl_GetChannelName(chan),
- "\" wasn't opened for ",
- ((writing) ? "writing" : "reading"), (char *) NULL);
+ Tcl_Obj* msg;
+ Tcl_GetChannelError(chan, &msg);
+ if (msg) {
+ Tcl_SetObjResult (interp, msg);
+ } else {
+ Tcl_AppendResult(interp, "channel \"", Tcl_GetChannelName(chan),
+ "\" wasn't opened for ",
+ ((writing) ? "writing" : "reading"), NULL);
+ }
return NULL;
}
*releasePtr = 1;
if (writing) {
-
/*
- * Be sure to flush output to the file, so that anything
- * written by the child appears after stuff we've already
- * written.
+ * Be sure to flush output to the file, so that anything written
+ * by the child appears after stuff we've already written.
*/
Tcl_Flush(chan);
@@ -141,16 +140,16 @@ FileForRedirect(interp, spec, atOK, arg, nextArg, flags, skipPtr, closePtr,
if (file == NULL) {
Tcl_AppendResult(interp, "couldn't ",
((writing) ? "write" : "read"), " file \"", spec, "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ Tcl_PosixError(interp), NULL);
return NULL;
}
*closePtr = 1;
}
return file;
- badLastArg:
+ badLastArg:
Tcl_AppendResult(interp, "can't specify \"", arg,
- "\" as last word in command", (char *) NULL);
+ "\" as last word in command", NULL);
return NULL;
}
@@ -159,10 +158,9 @@ FileForRedirect(interp, spec, atOK, arg, nextArg, flags, skipPtr, closePtr,
*
* Tcl_DetachPids --
*
- * This procedure is called to indicate that one or more child
- * processes have been placed in background and will never be
- * waited for; they should eventually be reaped by
- * Tcl_ReapDetachedProcs.
+ * This function is called to indicate that one or more child processes
+ * have been placed in background and will never be waited for; they
+ * should eventually be reaped by Tcl_ReapDetachedProcs.
*
* Results:
* None.
@@ -174,10 +172,10 @@ FileForRedirect(interp, spec, atOK, arg, nextArg, flags, skipPtr, closePtr,
*/
void
-Tcl_DetachPids(numPids, pidPtr)
- int numPids; /* Number of pids to detach: gives size
- * of array pointed to by pidPtr. */
- Tcl_Pid *pidPtr; /* Array of pids to detach. */
+Tcl_DetachPids(
+ int numPids, /* Number of pids to detach: gives size of
+ * array pointed to by pidPtr. */
+ Tcl_Pid *pidPtr) /* Array of pids to detach. */
{
register Detached *detPtr;
int i;
@@ -198,23 +196,22 @@ Tcl_DetachPids(numPids, pidPtr)
*
* Tcl_ReapDetachedProcs --
*
- * This procedure checks to see if any detached processes have
- * exited and, if so, it "reaps" them by officially waiting on
- * them. It should be called "occasionally" to make sure that
- * all detached processes are eventually reaped.
+ * This function checks to see if any detached processes have exited and,
+ * if so, it "reaps" them by officially waiting on them. It should be
+ * called "occasionally" to make sure that all detached processes are
+ * eventually reaped.
*
* Results:
* None.
*
* Side effects:
- * Processes are waited on, so that they can be reaped by the
- * system.
+ * Processes are waited on, so that they can be reaped by the system.
*
*----------------------------------------------------------------------
*/
void
-Tcl_ReapDetachedProcs()
+Tcl_ReapDetachedProcs(void)
{
register Detached *detPtr;
Detached *nextPtr, *prevPtr;
@@ -246,30 +243,30 @@ Tcl_ReapDetachedProcs()
*
* TclCleanupChildren --
*
- * This is a utility procedure used to wait for child processes
- * to exit, record information about abnormal exits, and then
- * collect any stderr output generated by them.
+ * This is a utility function used to wait for child processes to exit,
+ * record information about abnormal exits, and then collect any stderr
+ * output generated by them.
*
* Results:
- * The return value is a standard Tcl result. If anything at
- * weird happened with the child processes, TCL_ERROR is returned
- * and a message is left in the interp's result.
+ * The return value is a standard Tcl result. If anything at weird
+ * happened with the child processes, TCL_ERROR is returned and a message
+ * is left in the interp's result.
*
* Side effects:
- * If the last character of the interp's result is a newline, then it
- * is removed unless keepNewline is non-zero. File errorId gets
- * closed, and pidPtr is freed back to the storage allocator.
+ * If the last character of the interp's result is a newline, then it is
+ * removed unless keepNewline is non-zero. File errorId gets closed, and
+ * pidPtr is freed back to the storage allocator.
*
*----------------------------------------------------------------------
*/
int
-TclCleanupChildren(interp, numPids, pidPtr, errorChan)
- Tcl_Interp *interp; /* Used for error messages. */
- int numPids; /* Number of entries in pidPtr array. */
- Tcl_Pid *pidPtr; /* Array of process ids of children. */
- Tcl_Channel errorChan; /* Channel for file containing stderr output
- * from pipeline. NULL means there isn't any
+TclCleanupChildren(
+ Tcl_Interp *interp, /* Used for error messages. */
+ int numPids, /* Number of entries in pidPtr array. */
+ Tcl_Pid *pidPtr, /* Array of process ids of children. */
+ Tcl_Channel errorChan) /* Channel for file containing stderr output
+ * from pipeline. NULL means there isn't any
* stderr output. */
{
int result = TCL_OK;
@@ -282,93 +279,83 @@ TclCleanupChildren(interp, numPids, pidPtr, errorChan)
abnormalExit = 0;
for (i = 0; i < numPids; i++) {
/*
- * We need to get the resolved pid before we wait on it as
- * the windows implimentation of Tcl_WaitPid deletes the
- * information such that any following calls to TclpGetPid
- * fail.
+ * We need to get the resolved pid before we wait on it as the windows
+ * implimentation of Tcl_WaitPid deletes the information such that any
+ * following calls to TclpGetPid fail.
*/
+
resolvedPid = TclpGetPid(pidPtr[i]);
pid = Tcl_WaitPid(pidPtr[i], (int *) &waitStatus, 0);
if (pid == (Tcl_Pid) -1) {
result = TCL_ERROR;
- if (interp != (Tcl_Interp *) NULL) {
+ if (interp != NULL) {
msg = Tcl_PosixError(interp);
if (errno == ECHILD) {
/*
- * This changeup in message suggested by Mark Diekhans
- * to remind people that ECHILD errors can occur on
- * some systems if SIGCHLD isn't in its default state.
+ * This changeup in message suggested by Mark Diekhans to
+ * remind people that ECHILD errors can occur on some
+ * systems if SIGCHLD isn't in its default state.
*/
msg =
"child process lost (is SIGCHLD ignored or trapped?)";
}
Tcl_AppendResult(interp, "error waiting for process to exit: ",
- msg, (char *) NULL);
+ msg, NULL);
}
continue;
}
/*
- * Create error messages for unusual process exits. An
- * extra newline gets appended to each error message, but
- * it gets removed below (in the same fashion that an
- * extra newline in the command's output is removed).
+ * Create error messages for unusual process exits. An extra newline
+ * gets appended to each error message, but it gets removed below (in
+ * the same fashion that an extra newline in the command's output is
+ * removed).
*/
if (!WIFEXITED(waitStatus) || (WEXITSTATUS(waitStatus) != 0)) {
char msg1[TCL_INTEGER_SPACE], msg2[TCL_INTEGER_SPACE];
result = TCL_ERROR;
- TclFormatInt(msg1, (long) resolvedPid);
+ sprintf(msg1, "%lu", resolvedPid);
if (WIFEXITED(waitStatus)) {
if (interp != (Tcl_Interp *) NULL) {
- TclFormatInt(msg2, WEXITSTATUS(waitStatus));
- Tcl_SetErrorCode(interp, "CHILDSTATUS", msg1, msg2,
- (char *) NULL);
+ sprintf(msg2, "%lu",
+ (unsigned long) WEXITSTATUS(waitStatus));
+ Tcl_SetErrorCode(interp, "CHILDSTATUS", msg1, msg2, NULL);
}
abnormalExit = 1;
- } else if (WIFSIGNALED(waitStatus)) {
- if (interp != (Tcl_Interp *) NULL) {
- CONST char *p;
-
+ } else if (interp != NULL) {
+ CONST char *p;
+
+ if (WIFSIGNALED(waitStatus)) {
p = Tcl_SignalMsg((int) (WTERMSIG(waitStatus)));
Tcl_SetErrorCode(interp, "CHILDKILLED", msg1,
Tcl_SignalId((int) (WTERMSIG(waitStatus))), p,
- (char *) NULL);
- Tcl_AppendResult(interp, "child killed: ", p, "\n",
- (char *) NULL);
- }
- } else if (WIFSTOPPED(waitStatus)) {
- if (interp != (Tcl_Interp *) NULL) {
- CONST char *p;
-
+ NULL);
+ Tcl_AppendResult(interp, "child killed: ", p, "\n", NULL);
+ } else if (WIFSTOPPED(waitStatus)) {
p = Tcl_SignalMsg((int) (WSTOPSIG(waitStatus)));
Tcl_SetErrorCode(interp, "CHILDSUSP", msg1,
- Tcl_SignalId((int) (WSTOPSIG(waitStatus))),
- p, (char *) NULL);
+ Tcl_SignalId((int) (WSTOPSIG(waitStatus))), p,
+ NULL);
Tcl_AppendResult(interp, "child suspended: ", p, "\n",
- (char *) NULL);
- }
- } else {
- if (interp != (Tcl_Interp *) NULL) {
+ NULL);
+ } else {
Tcl_AppendResult(interp,
- "child wait status didn't make sense\n",
- (char *) NULL);
+ "child wait status didn't make sense\n", NULL);
}
}
}
}
/*
- * Read the standard error file. If there's anything there,
- * then return an error and add the file's contents to the result
- * string.
+ * Read the standard error file. If there's anything there, then return an
+ * error and add the file's contents to the result string.
*/
anyErrorInfo = 0;
if (errorChan != NULL) {
-
/*
* Make sure we start at the beginning of the file.
*/
@@ -376,7 +363,7 @@ TclCleanupChildren(interp, numPids, pidPtr, errorChan)
if (interp != NULL) {
int count;
Tcl_Obj *objPtr;
-
+
Tcl_Seek(errorChan, (Tcl_WideInt)0, SEEK_SET);
objPtr = Tcl_NewObj();
count = Tcl_ReadChars(errorChan, objPtr, -1, 0);
@@ -398,13 +385,12 @@ TclCleanupChildren(interp, numPids, pidPtr, errorChan)
}
/*
- * If a child exited abnormally but didn't output any error information
- * at all, generate an error message here.
+ * If a child exited abnormally but didn't output any error information at
+ * all, generate an error message here.
*/
if ((abnormalExit != 0) && (anyErrorInfo == 0) && (interp != NULL)) {
- Tcl_AppendResult(interp, "child process exited abnormally",
- (char *) NULL);
+ Tcl_AppendResult(interp, "child process exited abnormally", NULL);
}
return result;
}
@@ -414,25 +400,23 @@ TclCleanupChildren(interp, numPids, pidPtr, errorChan)
*
* TclCreatePipeline --
*
- * Given an argc/argv array, instantiate a pipeline of processes
- * as described by the argv.
+ * Given an argc/argv array, instantiate a pipeline of processes as
+ * described by the argv.
*
- * This procedure is unofficially exported for use by BLT.
+ * This function is unofficially exported for use by BLT.
*
* Results:
- * The return value is a count of the number of new processes
- * created, or -1 if an error occurred while creating the pipeline.
- * *pidArrayPtr is filled in with the address of a dynamically
- * allocated array giving the ids of all of the processes. It
- * is up to the caller to free this array when it isn't needed
- * anymore. If inPipePtr is non-NULL, *inPipePtr is filled in
- * with the file id for the input pipe for the pipeline (if any):
- * the caller must eventually close this file. If outPipePtr
- * isn't NULL, then *outPipePtr is filled in with the file id
- * for the output pipe from the pipeline: the caller must close
- * this file. If errFilePtr isn't NULL, then *errFilePtr is filled
- * with a file id that may be used to read error output after the
- * pipeline completes.
+ * The return value is a count of the number of new processes created, or
+ * -1 if an error occurred while creating the pipeline. *pidArrayPtr is
+ * filled in with the address of a dynamically allocated array giving the
+ * ids of all of the processes. It is up to the caller to free this array
+ * when it isn't needed anymore. If inPipePtr is non-NULL, *inPipePtr is
+ * filled in with the file id for the input pipe for the pipeline (if
+ * any): the caller must eventually close this file. If outPipePtr isn't
+ * NULL, then *outPipePtr is filled in with the file id for the output
+ * pipe from the pipeline: the caller must close this file. If errFilePtr
+ * isn't NULL, then *errFilePtr is filled with a file id that may be used
+ * to read error output after the pipeline completes.
*
* Side effects:
* Processes and pipes are created.
@@ -441,67 +425,66 @@ TclCleanupChildren(interp, numPids, pidPtr, errorChan)
*/
int
-TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
- outPipePtr, errFilePtr)
- Tcl_Interp *interp; /* Interpreter to use for error reporting. */
- int argc; /* Number of entries in argv. */
- CONST char **argv; /* Array of strings describing commands in
- * pipeline plus I/O redirection with <,
- * <<, >, etc. Argv[argc] must be NULL. */
- Tcl_Pid **pidArrayPtr; /* Word at *pidArrayPtr gets filled in with
- * address of array of pids for processes
- * in pipeline (first pid is first process
- * in pipeline). */
- TclFile *inPipePtr; /* If non-NULL, input to the pipeline comes
+TclCreatePipeline(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ int argc, /* Number of entries in argv. */
+ CONST char **argv, /* Array of strings describing commands in
+ * pipeline plus I/O redirection with <, <<,
+ * >, etc. Argv[argc] must be NULL. */
+ Tcl_Pid **pidArrayPtr, /* Word at *pidArrayPtr gets filled in with
+ * address of array of pids for processes in
+ * pipeline (first pid is first process in
+ * pipeline). */
+ TclFile *inPipePtr, /* If non-NULL, input to the pipeline comes
* from a pipe (unless overridden by
- * redirection in the command). The file
- * id with which to write to this pipe is
- * stored at *inPipePtr. NULL means command
- * specified its own input source. */
- TclFile *outPipePtr; /* If non-NULL, output to the pipeline goes
- * to a pipe, unless overriden by redirection
- * in the command. The file id with which to
- * read frome this pipe is stored at
- * *outPipePtr. NULL means command specified
- * its own output sink. */
- TclFile *errFilePtr; /* If non-NULL, all stderr output from the
+ * redirection in the command). The file id
+ * with which to write to this pipe is stored
+ * at *inPipePtr. NULL means command specified
+ * its own input source. */
+ TclFile *outPipePtr, /* If non-NULL, output to the pipeline goes to
+ * a pipe, unless overriden by redirection in
+ * the command. The file id with which to read
+ * frome this pipe is stored at *outPipePtr.
+ * NULL means command specified its own output
+ * sink. */
+ TclFile *errFilePtr) /* If non-NULL, all stderr output from the
* pipeline will go to a temporary file
- * created here, and a descriptor to read
- * the file will be left at *errFilePtr.
- * The file will be removed already, so
- * closing this descriptor will be the end
- * of the file. If this is NULL, then
- * all stderr output goes to our stderr.
- * If the pipeline specifies redirection
- * then the file will still be created
- * but it will never get any data. */
+ * created here, and a descriptor to read the
+ * file will be left at *errFilePtr. The file
+ * will be removed already, so closing this
+ * descriptor will be the end of the file. If
+ * this is NULL, then all stderr output goes
+ * to our stderr. If the pipeline specifies
+ * redirection then the file will still be
+ * created but it will never get any data. */
{
- Tcl_Pid *pidPtr = NULL; /* Points to malloc-ed array holding all
- * the pids of child processes. */
- int numPids; /* Actual number of processes that exist
- * at *pidPtr right now. */
- int cmdCount; /* Count of number of distinct commands
- * found in argc/argv. */
- CONST char *inputLiteral = NULL; /* If non-null, then this points to a
- * string containing input data (specified
- * via <<) to be piped to the first process
- * in the pipeline. */
+ Tcl_Pid *pidPtr = NULL; /* Points to malloc-ed array holding all the
+ * pids of child processes. */
+ int numPids; /* Actual number of processes that exist at
+ * *pidPtr right now. */
+ int cmdCount; /* Count of number of distinct commands found
+ * in argc/argv. */
+ CONST char *inputLiteral = NULL;
+ /* If non-null, then this points to a string
+ * containing input data (specified via <<) to
+ * be piped to the first process in the
+ * pipeline. */
TclFile inputFile = NULL; /* If != NULL, gives file to use as input for
* first process in pipeline (specified via <
* or <@). */
- int inputClose = 0; /* If non-zero, then inputFile should be
+ int inputClose = 0; /* If non-zero, then inputFile should be
* closed when cleaning up. */
int inputRelease = 0;
TclFile outputFile = NULL; /* Writable file for output from last command
- * in pipeline (could be file or pipe). NULL
+ * in pipeline (could be file or pipe). NULL
* means use stdout. */
- int outputClose = 0; /* If non-zero, then outputFile should be
+ int outputClose = 0; /* If non-zero, then outputFile should be
* closed when cleaning up. */
int outputRelease = 0;
TclFile errorFile = NULL; /* Writable file for error output from all
- * commands in pipeline. NULL means use
+ * commands in pipeline. NULL means use
* stderr. */
- int errorClose = 0; /* If non-zero, then errorFile should be
+ int errorClose = 0; /* If non-zero, then errorFile should be
* closed when cleaning up. */
int errorRelease = 0;
CONST char *p;
@@ -523,23 +506,23 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
}
Tcl_DStringInit(&execBuffer);
-
+
pipeIn = NULL;
curInFile = NULL;
curOutFile = NULL;
numPids = 0;
/*
- * First, scan through all the arguments to figure out the structure
- * of the pipeline. Process all of the input and output redirection
- * arguments and remove them from the argument list in the pipeline.
- * Count the number of distinct processes (it's the number of "|"
- * arguments plus one) but don't remove the "|" arguments because
- * they'll be used in the second pass to seperate the individual
- * child processes. Cannot start the child processes in this pass
- * because the redirection symbols may appear anywhere in the
- * command line -- e.g., the '<' that specifies the input to the
- * entire pipe may appear at the very end of the argument list.
+ * First, scan through all the arguments to figure out the structure of
+ * the pipeline. Process all of the input and output redirection arguments
+ * and remove them from the argument list in the pipeline. Count the
+ * number of distinct processes (it's the number of "|" arguments plus
+ * one) but don't remove the "|" arguments because they'll be used in the
+ * second pass to seperate the individual child processes. Cannot start
+ * the child processes in this pass because the redirection symbols may
+ * appear anywhere in the command line - e.g., the '<' that specifies the
+ * input to the entire pipe may appear at the very end of the argument
+ * list.
*/
lastBar = -1;
@@ -556,8 +539,7 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
}
if (*p == '\0') {
if ((i == (lastBar + 1)) || (i == (argc - 1))) {
- Tcl_SetResult(interp,
- "illegal use of | or |& in command",
+ Tcl_SetResult(interp, "illegal use of | or |& in command",
TCL_STATIC);
goto error;
}
@@ -584,7 +566,7 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
inputLiteral = ((i + 1) == argc) ? NULL : argv[i + 1];
if (inputLiteral == NULL) {
Tcl_AppendResult(interp, "can't specify \"", argv[i],
- "\" as last word in command", (char *) NULL);
+ "\" as last word in command", NULL);
goto error;
}
skip = 2;
@@ -592,8 +574,8 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
} else {
nextArg = ((i + 1) == argc) ? NULL : argv[i + 1];
inputLiteral = NULL;
- inputFile = FileForRedirect(interp, p, 1, argv[i],
- nextArg, O_RDONLY, &skip, &inputClose, &inputRelease);
+ inputFile = FileForRedirect(interp, p, 1, argv[i], nextArg,
+ O_RDONLY, &skip, &inputClose, &inputRelease);
if (inputFile == NULL) {
goto error;
}
@@ -624,8 +606,8 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
}
/*
- * Close the old output file, but only if the error file is
- * not also using it.
+ * Close the old output file, but only if the error file is not
+ * also using it.
*/
if (outputClose != 0) {
@@ -645,8 +627,8 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
}
}
nextArg = ((i + 1) == argc) ? NULL : argv[i + 1];
- outputFile = FileForRedirect(interp, p, atOK, argv[i],
- nextArg, flags, &skip, &outputClose, &outputRelease);
+ outputFile = FileForRedirect(interp, p, atOK, argv[i], nextArg,
+ flags, &skip, &outputClose, &outputRelease);
if (outputFile == NULL) {
goto error;
}
@@ -686,12 +668,13 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
if (atOK && p[0] == '@' && p[1] == '1' && p[2] == '\0') {
/*
* Special case handling of 2>@1 to redirect stderr to the
- * exec/open output pipe as well. This is meant for the end
- * of the command string, otherwise use |& between commands.
+ * exec/open output pipe as well. This is meant for the end of
+ * the command string, otherwise use |& between commands.
*/
- if (i != argc - 1) {
+
+ if (i != argc-1) {
Tcl_AppendResult(interp, "must specify \"", argv[i],
- "\" as last word in command", (char *) NULL);
+ "\" as last word in command", NULL);
goto error;
}
errorFile = outputFile;
@@ -699,7 +682,7 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
skip = 1;
} else {
nextArg = ((i + 1) == argc) ? NULL : argv[i + 1];
- errorFile = FileForRedirect(interp, p, atOK, argv[i],
+ errorFile = FileForRedirect(interp, p, atOK, argv[i],
nextArg, flags, &skip, &errorClose, &errorRelease);
if (errorFile == NULL) {
goto error;
@@ -723,7 +706,7 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
}
if (needCmd) {
- /* We had a bar followed only by redirections. */
+ /* We had a bar followed only by redirections. */
Tcl_SetResult(interp,
"illegal use of | or |& in command",
@@ -735,27 +718,28 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
if (inputLiteral != NULL) {
/*
* The input for the first process is immediate data coming from
- * Tcl. Create a temporary file for it and put the data into the
+ * Tcl. Create a temporary file for it and put the data into the
* file.
*/
+
inputFile = TclpCreateTempFile(inputLiteral);
if (inputFile == NULL) {
Tcl_AppendResult(interp,
"couldn't create input file for command: ",
- Tcl_PosixError(interp), (char *) NULL);
+ Tcl_PosixError(interp), NULL);
goto error;
}
inputClose = 1;
} else if (inPipePtr != NULL) {
/*
- * The input for the first process in the pipeline is to
- * come from a pipe that can be written from by the caller.
+ * The input for the first process in the pipeline is to come from
+ * a pipe that can be written from by the caller.
*/
if (TclpCreatePipe(&inputFile, inPipePtr) == 0) {
- Tcl_AppendResult(interp,
+ Tcl_AppendResult(interp,
"couldn't create input pipe for command: ",
- Tcl_PosixError(interp), (char *) NULL);
+ Tcl_PosixError(interp), NULL);
goto error;
}
inputClose = 1;
@@ -777,14 +761,14 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
if (outputFile == NULL) {
if (outPipePtr != NULL) {
/*
- * Output from the last process in the pipeline is to go to a
- * pipe that can be read by the caller.
+ * Output from the last process in the pipeline is to go to a pipe
+ * that can be read by the caller.
*/
if (TclpCreatePipe(outPipePtr, &outputFile) == 0) {
- Tcl_AppendResult(interp,
+ Tcl_AppendResult(interp,
"couldn't create output pipe for command: ",
- Tcl_PosixError(interp), (char *) NULL);
+ Tcl_PosixError(interp), NULL);
goto error;
}
outputClose = 1;
@@ -806,16 +790,17 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
if (errorFile == NULL) {
if (errorToOutput == 2) {
/*
- * Handle 2>@1 special case at end of cmd line
+ * Handle 2>@1 special case at end of cmd line.
*/
+
errorFile = outputFile;
} else if (errFilePtr != NULL) {
/*
* Set up the standard error output sink for the pipeline, if
- * requested. Use a temporary file which is opened, then deleted.
+ * requested. Use a temporary file which is opened, then deleted.
* Could potentially just use pipe, but if it filled up it could
- * cause the pipeline to deadlock: we'd be waiting for processes
- * to complete before reading stderr, and processes couldn't
+ * cause the pipeline to deadlock: we'd be waiting for processes
+ * to complete before reading stderr, and processes couldn't
* complete because stderr was backed up.
*/
@@ -823,7 +808,7 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
if (errorFile == NULL) {
Tcl_AppendResult(interp,
"couldn't create error file for command: ",
- Tcl_PosixError(interp), (char *) NULL);
+ Tcl_PosixError(interp), NULL);
goto error;
}
*errFilePtr = errorFile;
@@ -841,10 +826,10 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
}
}
}
-
+
/*
- * Scan through the argc array, creating a process for each
- * group of arguments between the "|" characters.
+ * Scan through the argc array, creating a process for each group of
+ * arguments between the "|" characters.
*/
Tcl_ReapDetachedProcs();
@@ -852,13 +837,13 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
curInFile = inputFile;
- for (i = 0; i < argc; i = lastArg + 1) {
+ for (i = 0; i < argc; i = lastArg + 1) {
int result, joinThisError;
Tcl_Pid pid;
CONST char *oldName;
/*
- * Convert the program name into native form.
+ * Convert the program name into native form.
*/
if (Tcl_TranslateFileName(interp, argv[i], &execBuffer) == NULL) {
@@ -871,20 +856,21 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
joinThisError = 0;
for (lastArg = i; lastArg < argc; lastArg++) {
- if (argv[lastArg][0] == '|') {
- if (argv[lastArg][1] == '\0') {
- break;
- }
- if ((argv[lastArg][1] == '&') && (argv[lastArg][2] == '\0')) {
- joinThisError = 1;
- break;
- }
+ if (argv[lastArg][0] != '|') {
+ continue;
+ }
+ if (argv[lastArg][1] == '\0') {
+ break;
+ }
+ if ((argv[lastArg][1] == '&') && (argv[lastArg][2] == '\0')) {
+ joinThisError = 1;
+ break;
}
}
/*
* If this is the last segment, use the specified outputFile.
- * Otherwise create an intermediate pipe. pipeIn will become the
+ * Otherwise create an intermediate pipe. pipeIn will become the
* curInFile for the next segment of the pipe.
*/
@@ -894,7 +880,7 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
argv[lastArg] = NULL;
if (TclpCreatePipe(&pipeIn, &curOutFile) == 0) {
Tcl_AppendResult(interp, "couldn't create pipe: ",
- Tcl_PosixError(interp), (char *) NULL);
+ Tcl_PosixError(interp), NULL);
goto error;
}
}
@@ -909,7 +895,7 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
* Restore argv[i], since a caller wouldn't expect the contents of
* argv to be modified.
*/
-
+
oldName = argv[i];
argv[i] = Tcl_DStringValue(&execBuffer);
result = TclpCreateProcess(interp, lastArg - i, argv + i,
@@ -924,8 +910,8 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
numPids++;
/*
- * Close off our copies of file descriptors that were set up for
- * this child, then set up the input for the next child.
+ * Close off our copies of file descriptors that were set up for this
+ * child, then set up the input for the next child.
*/
if ((curInFile != NULL) && (curInFile != inputFile)) {
@@ -943,10 +929,10 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr,
*pidArrayPtr = pidPtr;
/*
- * All done. Cleanup open files lying around and then return.
+ * All done. Cleanup open files lying around and then return.
*/
-cleanup:
+ cleanup:
Tcl_DStringFree(&execBuffer);
if (inputClose) {
@@ -967,12 +953,12 @@ cleanup:
return numPids;
/*
- * An error occurred. There could have been extra files open, such
- * as pipes between children. Clean them all up. Detach any child
- * processes that have been created.
+ * An error occurred. There could have been extra files open, such as
+ * pipes between children. Clean them all up. Detach any child processes
+ * that have been created.
*/
-error:
+ error:
if (pipeIn != NULL) {
TclpCloseFile(pipeIn);
}
@@ -1011,28 +997,26 @@ error:
*
* Tcl_OpenCommandChannel --
*
- * Opens an I/O channel to one or more subprocesses specified
- * by argc and argv. The flags argument determines the
- * disposition of the stdio handles. If the TCL_STDIN flag is
- * set then the standard input for the first subprocess will
- * be tied to the channel: writing to the channel will provide
- * input to the subprocess. If TCL_STDIN is not set, then
- * standard input for the first subprocess will be the same as
- * this application's standard input. If TCL_STDOUT is set then
- * standard output from the last subprocess can be read from the
- * channel; otherwise it goes to this application's standard
- * output. If TCL_STDERR is set, standard error output for all
- * subprocesses is returned to the channel and results in an error
- * when the channel is closed; otherwise it goes to this
- * application's standard error. If TCL_ENFORCE_MODE is not set,
- * then argc and argv can redirect the stdio handles to override
- * TCL_STDIN, TCL_STDOUT, and TCL_STDERR; if it is set, then it
- * is an error for argc and argv to override stdio channels for
- * which TCL_STDIN, TCL_STDOUT, and TCL_STDERR have been set.
+ * Opens an I/O channel to one or more subprocesses specified by argc and
+ * argv. The flags argument determines the disposition of the stdio
+ * handles. If the TCL_STDIN flag is set then the standard input for the
+ * first subprocess will be tied to the channel: writing to the channel
+ * will provide input to the subprocess. If TCL_STDIN is not set, then
+ * standard input for the first subprocess will be the same as this
+ * application's standard input. If TCL_STDOUT is set then standard
+ * output from the last subprocess can be read from the channel;
+ * otherwise it goes to this application's standard output. If TCL_STDERR
+ * is set, standard error output for all subprocesses is returned to the
+ * channel and results in an error when the channel is closed; otherwise
+ * it goes to this application's standard error. If TCL_ENFORCE_MODE is
+ * not set, then argc and argv can redirect the stdio handles to override
+ * TCL_STDIN, TCL_STDOUT, and TCL_STDERR; if it is set, then it is an
+ * error for argc and argv to override stdio channels for which
+ * TCL_STDIN, TCL_STDOUT, and TCL_STDERR have been set.
*
* Results:
- * A new command channel, or NULL on failure with an error
- * message left in interp.
+ * A new command channel, or NULL on failure with an error message left
+ * in interp.
*
* Side effects:
* Creates processes, opens pipes.
@@ -1041,12 +1025,12 @@ error:
*/
Tcl_Channel
-Tcl_OpenCommandChannel(interp, argc, argv, flags)
- Tcl_Interp *interp; /* Interpreter for error reporting. Can
- * NOT be NULL. */
- int argc; /* How many arguments. */
- CONST char **argv; /* Array of arguments for command pipe. */
- int flags; /* Or'ed combination of TCL_STDIN, TCL_STDOUT,
+Tcl_OpenCommandChannel(
+ Tcl_Interp *interp, /* Interpreter for error reporting. Can NOT be
+ * NULL. */
+ int argc, /* How many arguments. */
+ CONST char **argv, /* Array of arguments for command pipe. */
+ int flags) /* Or'ed combination of TCL_STDIN, TCL_STDOUT,
* TCL_STDERR, and TCL_ENFORCE_MODE. */
{
TclFile *inPipePtr, *outPipePtr, *errFilePtr;
@@ -1060,7 +1044,7 @@ Tcl_OpenCommandChannel(interp, argc, argv, flags)
inPipePtr = (flags & TCL_STDIN) ? &inPipe : NULL;
outPipePtr = (flags & TCL_STDOUT) ? &outPipe : NULL;
errFilePtr = (flags & TCL_STDERR) ? &errFile : NULL;
-
+
numPids = TclCreatePipeline(interp, argc, argv, &pidPtr, inPipePtr,
outPipePtr, errFilePtr);
@@ -1069,34 +1053,34 @@ Tcl_OpenCommandChannel(interp, argc, argv, flags)
}
/*
- * Verify that the pipes that were created satisfy the
- * readable/writable constraints.
+ * Verify that the pipes that were created satisfy the readable/writable
+ * constraints.
*/
if (flags & TCL_ENFORCE_MODE) {
if ((flags & TCL_STDOUT) && (outPipe == NULL)) {
- Tcl_AppendResult(interp, "can't read output from command:",
- " standard output was redirected", (char *) NULL);
+ Tcl_AppendResult(interp, "can't read output from command:"
+ " standard output was redirected", NULL);
goto error;
}
if ((flags & TCL_STDIN) && (inPipe == NULL)) {
- Tcl_AppendResult(interp, "can't write input to command:",
- " standard input was redirected", (char *) NULL);
+ Tcl_AppendResult(interp, "can't write input to command:"
+ " standard input was redirected", NULL);
goto error;
}
}
-
+
channel = TclpCreateCommandChannel(outPipe, inPipe, errFile,
numPids, pidPtr);
if (channel == (Tcl_Channel) NULL) {
Tcl_AppendResult(interp, "pipe for command could not be created",
- (char *) NULL);
+ NULL);
goto error;
}
return channel;
-error:
+ error:
if (numPids > 0) {
Tcl_DetachPids(numPids, pidPtr);
ckfree((char *) pidPtr);
@@ -1112,3 +1096,11 @@ error:
}
return NULL;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclPkg.c b/generic/tclPkg.c
index 26a9cff..aed80c0 100644
--- a/generic/tclPkg.c
+++ b/generic/tclPkg.c
@@ -1,14 +1,14 @@
-/*
+/*
* tclPkg.c --
*
- * This file implements package and version control for Tcl via
- * the "package" command and a few C APIs.
+ * This file implements package and version control for Tcl via the
+ * "package" command and a few C APIs.
*
* Copyright (c) 1996 Sun Microsystems, Inc.
* Copyright (c) 2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* TIP #268.
* Heavily rewritten to handle the extend version numbers, and extended
@@ -18,70 +18,60 @@
#include "tclInt.h"
/*
- * Each invocation of the "package ifneeded" command creates a structure
- * of the following type, which is used to load the package into the
- * interpreter if it is requested with a "package require" command.
+ * Each invocation of the "package ifneeded" command creates a structure of
+ * the following type, which is used to load the package into the interpreter
+ * if it is requested with a "package require" command.
*/
typedef struct PkgAvail {
char *version; /* Version string; malloc'ed. */
- char *script; /* Script to invoke to provide this version
- * of the package. Malloc'ed and protected
- * by Tcl_Preserve and Tcl_Release. */
- struct PkgAvail *nextPtr; /* Next in list of available versions of
- * the same package. */
+ char *script; /* Script to invoke to provide this version of
+ * the package. Malloc'ed and protected by
+ * Tcl_Preserve and Tcl_Release. */
+ struct PkgAvail *nextPtr; /* Next in list of available versions of the
+ * same package. */
} PkgAvail;
/*
- * For each package that is known in any way to an interpreter, there
- * is one record of the following type. These records are stored in
- * the "packageTable" hash table in the interpreter, keyed by
- * package name such as "Tk" (no version number).
+ * For each package that is known in any way to an interpreter, there is one
+ * record of the following type. These records are stored in the
+ * "packageTable" hash table in the interpreter, keyed by package name such as
+ * "Tk" (no version number).
*/
typedef struct Package {
char *version; /* Version that has been supplied in this
* interpreter via "package provide"
- * (malloc'ed). NULL means the package doesn't
+ * (malloc'ed). NULL means the package doesn't
* exist in this interpreter yet. */
- PkgAvail *availPtr; /* First in list of all available versions
- * of this package. */
+ PkgAvail *availPtr; /* First in list of all available versions of
+ * this package. */
ClientData clientData; /* Client data. */
} Package;
/*
- * Prototypes for procedures defined in this file:
+ * Prototypes for functions defined in this file:
*/
-#ifndef TCL_TIP268
-static int CheckVersion _ANSI_ARGS_((Tcl_Interp *interp,
- CONST char *string));
-static int ComparePkgVersions _ANSI_ARGS_((CONST char *v1,
- CONST char *v2,
- int *satPtr));
-static Package * FindPackage _ANSI_ARGS_((Tcl_Interp *interp,
- CONST char *name));
-#else
static int CheckVersionAndConvert(Tcl_Interp *interp,
- CONST char *string, char** internal, int* stable);
-static int CompareVersions(CONST char *v1i, CONST char *v2i,
+ const char *string, char **internal, int *stable);
+static int CompareVersions(char *v1i, char *v2i,
int *isMajorPtr);
static int CheckRequirement(Tcl_Interp *interp,
- CONST char *string);
-static int CheckAllRequirements(Tcl_Interp* interp, int reqc,
- Tcl_Obj *CONST reqv[]);
-static int RequirementSatisfied(char *havei, CONST char *req);
+ const char *string);
+static int CheckAllRequirements(Tcl_Interp *interp, int reqc,
+ Tcl_Obj *const reqv[]);
+static int RequirementSatisfied(char *havei, const char *req);
static int SomeRequirementSatisfied(char *havei, int reqc,
- Tcl_Obj *CONST reqv[]);
-static void AddRequirementsToResult(Tcl_Interp* interp, int reqc,
- Tcl_Obj *CONST reqv[]);
-static void AddRequirementsToDString(Tcl_DString* dstring,
- int reqc, Tcl_Obj *CONST reqv[]);
-static Package * FindPackage(Tcl_Interp *interp, CONST char *name);
-static const char * PkgRequireCore(Tcl_Interp *interp, CONST char *name,
- int reqx, Tcl_Obj *CONST reqv[],
+ Tcl_Obj *const reqv[]);
+static void AddRequirementsToResult(Tcl_Interp *interp, int reqc,
+ Tcl_Obj *const reqv[]);
+static void AddRequirementsToDString(Tcl_DString *dstring,
+ int reqc, Tcl_Obj *const reqv[]);
+static Package * FindPackage(Tcl_Interp *interp, const char *name);
+static const char * PkgRequireCore(Tcl_Interp *interp, const char *name,
+ int reqc, Tcl_Obj *const reqv[],
ClientData *clientDataPtr);
-#endif
/*
* Helper macros.
@@ -94,56 +84,50 @@ static const char * PkgRequireCore(Tcl_Interp *interp, CONST char *name,
unsigned local__len = (unsigned) (strlen(s) + 1); \
DupBlock((v),(s),local__len); \
} while (0)
-
/*
*----------------------------------------------------------------------
*
* Tcl_PkgProvide / Tcl_PkgProvideEx --
*
- * This procedure is invoked to declare that a particular version
- * of a particular package is now present in an interpreter. There
- * must not be any other version of this package already
- * provided in the interpreter.
+ * This function is invoked to declare that a particular version of a
+ * particular package is now present in an interpreter. There must not be
+ * any other version of this package already provided in the interpreter.
*
* Results:
- * Normally returns TCL_OK; if there is already another version
- * of the package loaded then TCL_ERROR is returned and an error
- * message is left in the interp's result.
+ * Normally returns TCL_OK; if there is already another version of the
+ * package loaded then TCL_ERROR is returned and an error message is left
+ * in the interp's result.
*
* Side effects:
- * The interpreter remembers that this package is available,
- * so that no other version of the package may be provided for
- * the interpreter.
+ * The interpreter remembers that this package is available, so that no
+ * other version of the package may be provided for the interpreter.
*
*----------------------------------------------------------------------
*/
int
-Tcl_PkgProvide(interp, name, version)
- Tcl_Interp *interp; /* Interpreter in which package is now
+Tcl_PkgProvide(
+ Tcl_Interp *interp, /* Interpreter in which package is now
* available. */
- CONST char *name; /* Name of package. */
- CONST char *version; /* Version string for package. */
+ const char *name, /* Name of package. */
+ const char *version) /* Version string for package. */
{
- return Tcl_PkgProvideEx(interp, name, version, (ClientData) NULL);
+ return Tcl_PkgProvideEx(interp, name, version, NULL);
}
int
-Tcl_PkgProvideEx(interp, name, version, clientData)
- Tcl_Interp *interp; /* Interpreter in which package is now
+Tcl_PkgProvideEx(
+ Tcl_Interp *interp, /* Interpreter in which package is now
* available. */
- CONST char *name; /* Name of package. */
- CONST char *version; /* Version string for package. */
- ClientData clientData; /* clientdata for this package (normally
- * used for C callback function table) */
+ const char *name, /* Name of package. */
+ const char *version, /* Version string for package. */
+ ClientData clientData) /* clientdata for this package (normally used
+ * for C callback function table) */
{
Package *pkgPtr;
-#ifdef TCL_TIP268
- char* pvi;
- char* vi;
+ char *pvi, *vi;
int res;
-#endif
pkgPtr = FindPackage(interp, name);
if (pkgPtr->version == NULL) {
@@ -151,12 +135,11 @@ Tcl_PkgProvideEx(interp, name, version, clientData)
pkgPtr->clientData = clientData;
return TCL_OK;
}
-#ifndef TCL_TIP268
- if (ComparePkgVersions(pkgPtr->version, version, (int *) NULL) == 0) {
-#else
- if (CheckVersionAndConvert (interp, pkgPtr->version, &pvi, NULL) != TCL_OK) {
+
+ if (CheckVersionAndConvert(interp, pkgPtr->version, &pvi,
+ NULL) != TCL_OK) {
return TCL_ERROR;
- } else if (CheckVersionAndConvert (interp, version, &vi, NULL) != TCL_OK) {
+ } else if (CheckVersionAndConvert(interp, version, &vi, NULL) != TCL_OK) {
ckfree(pvi);
return TCL_ERROR;
}
@@ -166,14 +149,13 @@ Tcl_PkgProvideEx(interp, name, version, clientData)
ckfree(vi);
if (res == 0) {
-#endif
if (clientData != NULL) {
pkgPtr->clientData = clientData;
}
return TCL_OK;
}
Tcl_AppendResult(interp, "conflicting versions provided for package \"",
- name, "\": ", pkgPtr->version, ", then ", version, (char *) NULL);
+ name, "\": ", pkgPtr->version, ", then ", version, NULL);
return TCL_ERROR;
}
@@ -182,166 +164,134 @@ Tcl_PkgProvideEx(interp, name, version, clientData)
*
* Tcl_PkgRequire / Tcl_PkgRequireEx / Tcl_PkgRequireProc --
*
- * This procedure is called by code that depends on a particular
- * version of a particular package. If the package is not already
- * provided in the interpreter, this procedure invokes a Tcl script
- * to provide it. If the package is already provided, this
- * procedure makes sure that the caller's needs don't conflict with
- * the version that is present.
+ * This function is called by code that depends on a particular version
+ * of a particular package. If the package is not already provided in the
+ * interpreter, this function invokes a Tcl script to provide it. If the
+ * package is already provided, this function makes sure that the
+ * caller's needs don't conflict with the version that is present.
*
* Results:
- * If successful, returns the version string for the currently
- * provided version of the package, which may be different from
- * the "version" argument. If the caller's requirements
- * cannot be met (e.g. the version requested conflicts with
- * a currently provided version, or the required version cannot
- * be found, or the script to provide the required version
- * generates an error), NULL is returned and an error
- * message is left in the interp's result.
+ * If successful, returns the version string for the currently provided
+ * version of the package, which may be different from the "version"
+ * argument. If the caller's requirements cannot be met (e.g. the version
+ * requested conflicts with a currently provided version, or the required
+ * version cannot be found, or the script to provide the required version
+ * generates an error), NULL is returned and an error message is left in
+ * the interp's result.
*
* Side effects:
- * The script from some previous "package ifneeded" command may
- * be invoked to provide the package.
+ * The script from some previous "package ifneeded" command may be
+ * invoked to provide the package.
*
*----------------------------------------------------------------------
*/
-#ifndef TCL_TIP268
-/*
- * Empty definition for Stubs when TIP 268 is not activated.
- */
-int
-Tcl_PkgRequireProc(interp,name,reqc,reqv,clientDataPtr)
- Tcl_Interp *interp; /* Interpreter in which package is now
- * available. */
- CONST char *name; /* Name of desired package. */
- int reqc; /* Requirements constraining the desired version. */
- Tcl_Obj *CONST reqv[]; /* 0 means to use the latest version available. */
- ClientData *clientDataPtr;
-{
- return TCL_ERROR;
-}
-#endif
-
-CONST char *
-Tcl_PkgRequire(interp, name, version, exact)
- Tcl_Interp *interp; /* Interpreter in which package is now
+const char *
+Tcl_PkgRequire(
+ Tcl_Interp *interp, /* Interpreter in which package is now
* available. */
- CONST char *name; /* Name of desired package. */
- CONST char *version; /* Version string for desired version; NULL
+ const char *name, /* Name of desired package. */
+ const char *version, /* Version string for desired version; NULL
* means use the latest version available. */
- int exact; /* Non-zero means that only the particular
+ int exact) /* Non-zero means that only the particular
* version given is acceptable. Zero means use
* the latest compatible version. */
{
- return Tcl_PkgRequireEx(interp, name, version, exact, (ClientData *) NULL);
+ return Tcl_PkgRequireEx(interp, name, version, exact, NULL);
}
-CONST char *
-Tcl_PkgRequireEx(interp, name, version, exact, clientDataPtr)
- Tcl_Interp *interp; /* Interpreter in which package is now
- * available. */
- CONST char *name; /* Name of desired package. */
- CONST char *version; /* Version string for desired version;
- * NULL means use the latest version
+const char *
+Tcl_PkgRequireEx(
+ Tcl_Interp *interp, /* Interpreter in which package is now
* available. */
- int exact; /* Non-zero means that only the particular
- * version given is acceptable. Zero means
- * use the latest compatible version. */
- ClientData *clientDataPtr; /* Used to return the client data for this
- * package. If it is NULL then the client
- * data is not returned. This is unchanged
- * if this call fails for any reason. */
+ const char *name, /* Name of desired package. */
+ const char *version, /* Version string for desired version; NULL
+ * means use the latest version available. */
+ int exact, /* Non-zero means that only the particular
+ * version given is acceptable. Zero means use
+ * the latest compatible version. */
+ ClientData *clientDataPtr) /* Used to return the client data for this
+ * package. If it is NULL then the client data
+ * is not returned. This is unchanged if this
+ * call fails for any reason. */
{
-#ifndef TCL_TIP268
- Package *pkgPtr;
- PkgAvail *availPtr, *bestPtr;
- char *script;
- int code, satisfies, result, pass;
- Tcl_DString command;
-#else
Tcl_Obj *ov;
const char *result = NULL;
-#endif
/*
* If an attempt is being made to load this into a standalone executable
- * on a platform where backlinking is not supported then this must be
- * a shared version of Tcl (Otherwise the load would have failed).
- * Detect this situation by checking that this library has been correctly
+ * on a platform where backlinking is not supported then this must be a
+ * shared version of Tcl (Otherwise the load would have failed). Detect
+ * this situation by checking that this library has been correctly
* initialised. If it has not been then return immediately as nothing will
* work.
*/
-
- if (tclEmptyStringRep == NULL) {
+ if (tclEmptyStringRep == NULL) {
/*
* OK, so what's going on here?
*
- * First, what are we doing? We are performing a check on behalf of
- * one particular caller, Tcl_InitStubs(). When a package is
- * stub-enabled, it is statically linked to libtclstub.a, which
- * contains a copy of Tcl_InitStubs(). When a stub-enabled package
- * is loaded, its *_Init() function is supposed to call
- * Tcl_InitStubs() before calling any other functions in the Tcl
- * library. The first Tcl function called by Tcl_InitStubs() through
- * the stub table is Tcl_PkgRequireEx(), so this code right here is
- * the first code that is part of the original Tcl library in the
- * executable that gets executed on behalf of a newly loaded
- * stub-enabled package.
+ * First, what are we doing? We are performing a check on behalf of
+ * one particular caller, Tcl_InitStubs(). When a package is stub-
+ * enabled, it is statically linked to libtclstub.a, which contains a
+ * copy of Tcl_InitStubs(). When a stub-enabled package is loaded, its
+ * *_Init() function is supposed to call Tcl_InitStubs() before
+ * calling any other functions in the Tcl library. The first Tcl
+ * function called by Tcl_InitStubs() through the stub table is
+ * Tcl_PkgRequireEx(), so this code right here is the first code that
+ * is part of the original Tcl library in the executable that gets
+ * executed on behalf of a newly loaded stub-enabled package.
*
* One easy error for the developer/builder of a stub-enabled package
* to make is to forget to define USE_TCL_STUBS when compiling the
- * package. When that happens, the package will contain symbols
- * that are references to the Tcl library, rather than function
- * pointers referencing the stub table. On platforms that lack
- * backlinking, those unresolved references may cause the loading
- * of the package to also load a second copy of the Tcl library,
- * leading to all kinds of trouble. We would like to catch that
- * error and report a useful message back to the user. That's
- * what we're doing.
+ * package. When that happens, the package will contain symbols that
+ * are references to the Tcl library, rather than function pointers
+ * referencing the stub table. On platforms that lack backlinking,
+ * those unresolved references may cause the loading of the package to
+ * also load a second copy of the Tcl library, leading to all kinds of
+ * trouble. We would like to catch that error and report a useful
+ * message back to the user. That's what we're doing.
*
- * Second, how does this work? If we reach this point, then the
- * global variable tclEmptyStringRep has the value NULL. Compare
- * that with the definition of tclEmptyStringRep near the top of
- * the file generic/tclObj.c. It clearly should not have the value
- * NULL; it should point to the char tclEmptyString. If we see it
- * having the value NULL, then somehow we are seeing a Tcl library
- * that isn't completely initialized, and that's an indicator for the
- * error condition described above. (Further explanation is welcome.)
+ * Second, how does this work? If we reach this point, then the global
+ * variable tclEmptyStringRep has the value NULL. Compare that with
+ * the definition of tclEmptyStringRep near the top of the file
+ * generic/tclObj.c. It clearly should not have the value NULL; it
+ * should point to the char tclEmptyString. If we see it having the
+ * value NULL, then somehow we are seeing a Tcl library that isn't
+ * completely initialized, and that's an indicator for the error
+ * condition described above. (Further explanation is welcome.)
*
- * Third, so what do we do about it? This situation indicates
- * the package we just loaded wasn't properly compiled to be
- * stub-enabled, yet it thinks it is stub-enabled (it called
- * Tcl_InitStubs()). We want to report that the package just
- * loaded is broken, so we want to place an error message in
- * the interpreter result and return NULL to indicate failure
- * to Tcl_InitStubs() so that it will also fail. (Further
- * explanation why we don't want to Tcl_Panic() is welcome.
+ * Third, so what do we do about it? This situation indicates the
+ * package we just loaded wasn't properly compiled to be stub-enabled,
+ * yet it thinks it is stub-enabled (it called Tcl_InitStubs()). We
+ * want to report that the package just loaded is broken, so we want
+ * to place an error message in the interpreter result and return NULL
+ * to indicate failure to Tcl_InitStubs() so that it will also fail.
+ * (Further explanation why we don't want to Tcl_Panic() is welcome.
* After all, two Tcl libraries can't be a good thing!)
*
- * Trouble is that's going to be tricky. We're now using a Tcl
- * library that's not fully initialized. In particular, it
- * doesn't have a proper value for tclEmptyStringRep. The
- * Tcl_Obj system heavily depends on the value of tclEmptyStringRep
- * and all of Tcl depends (increasingly) on the Tcl_Obj system, we
- * need to correct that flaw before making the calls to set the
- * interpreter result to the error message. That's the only flaw
- * corrected; other problems with initialization of the Tcl library
- * are not remedied, so be very careful about adding any other calls
- * here without checking how they behave when initialization is
- * incomplete.
+ * Trouble is that's going to be tricky. We're now using a Tcl library
+ * that's not fully initialized. In particular, it doesn't have a
+ * proper value for tclEmptyStringRep. The Tcl_Obj system heavily
+ * depends on the value of tclEmptyStringRep and all of Tcl depends
+ * (increasingly) on the Tcl_Obj system, we need to correct that flaw
+ * before making the calls to set the interpreter result to the error
+ * message. That's the only flaw corrected; other problems with
+ * initialization of the Tcl library are not remedied, so be very
+ * careful about adding any other calls here without checking how they
+ * behave when initialization is incomplete.
*/
tclEmptyStringRep = &tclEmptyString;
- Tcl_AppendResult(interp, "Cannot load package \"", name,
- "\" in standalone executable: This package is not ",
- "compiled with stub support", NULL);
- return NULL;
+ Tcl_AppendResult(interp, "Cannot load package \"", name,
+ "\" in standalone executable: This package is not "
+ "compiled with stub support", NULL);
+ return NULL;
}
-#ifdef TCL_TIP268
- /* Translate between old and new API, and defer to the new function. */
+ /*
+ * Translate between old and new API, and defer to the new function.
+ */
if (version == NULL) {
result = PkgRequireCore(interp, name, 0, NULL, clientDataPtr);
@@ -354,9 +304,9 @@ Tcl_PkgRequireEx(interp, name, version, exact, clientDataPtr)
if (exact) {
Tcl_AppendStringsToObj(ov, "-", version, NULL);
}
- Tcl_IncrRefCount (ov);
+ Tcl_IncrRefCount(ov);
result = PkgRequireCore(interp, name, 1, &ov, clientDataPtr);
- Tcl_DecrRefCount (ov);
+ TclDecrRefCount(ov);
}
return result;
@@ -364,14 +314,14 @@ Tcl_PkgRequireEx(interp, name, version, exact, clientDataPtr)
int
Tcl_PkgRequireProc(
- Tcl_Interp *interp, /* Interpreter in which package is now
+ Tcl_Interp *interp, /* Interpreter in which package is now
* available. */
- CONST char *name, /* Name of desired package. */
- int reqc, /* Requirements constraining the desired
+ const char *name, /* Name of desired package. */
+ int reqc, /* Requirements constraining the desired
* version. */
- Tcl_Obj *CONST reqv[], /* 0 means to use the latest version
+ Tcl_Obj *const reqv[], /* 0 means to use the latest version
* available. */
- ClientData *clientDataPtr)
+ ClientData *clientDataPtr)
{
const char *result =
PkgRequireCore(interp, name, reqc, reqv, clientDataPtr);
@@ -385,26 +335,24 @@ Tcl_PkgRequireProc(
static const char *
PkgRequireCore(
- Tcl_Interp *interp, /* Interpreter in which package is now
+ Tcl_Interp *interp, /* Interpreter in which package is now
* available. */
- CONST char *name, /* Name of desired package. */
- int reqc, /* Requirements constraining the desired
+ const char *name, /* Name of desired package. */
+ int reqc, /* Requirements constraining the desired
* version. */
- Tcl_Obj *CONST reqv[], /* 0 means to use the latest version
+ Tcl_Obj *const reqv[], /* 0 means to use the latest version
* available. */
- ClientData *clientDataPtr)
+ ClientData *clientDataPtr)
{
Interp *iPtr = (Interp *) interp;
Package *pkgPtr;
PkgAvail *availPtr, *bestPtr, *bestStablePtr;
- char *availVersion, *bestVersion; /* Internal rep. of versions */
- int availStable;
- char *script;
- int code, satisfies, pass;
+ char *availVersion, *bestVersion;
+ /* Internal rep. of versions */
+ int availStable, code, satisfies, pass;
+ char *script, *pkgVersionI;
Tcl_DString command;
- char* pkgVersionI;
-#endif
/*
* It can take up to three passes to find the package: one pass to run the
* "package unknown" script, one to run the "package ifneeded" script for
@@ -412,45 +360,32 @@ PkgRequireCore(
* the "package ifneeded" script.
*/
- for (pass = 1; ; pass++) {
+ for (pass=1 ;; pass++) {
pkgPtr = FindPackage(interp, name);
if (pkgPtr->version != NULL) {
break;
}
- /*
- * Check whether we're already attempting to load some version
- * of this package (circular dependency detection).
+ /*
+ * Check whether we're already attempting to load some version of this
+ * package (circular dependency detection).
*/
if (pkgPtr->clientData != NULL) {
- Tcl_AppendResult(interp, "circular package dependency: ",
+ Tcl_AppendResult(interp, "circular package dependency: "
"attempt to provide ", name, " ",
- (char *)(pkgPtr->clientData), " requires ", name, NULL);
-#ifndef TCL_TIP268
- if (version != NULL) {
- Tcl_AppendResult(interp, " ", version, NULL);
- }
-#else
- AddRequirementsToResult (interp, reqc, reqv);
-#endif
+ (char *) pkgPtr->clientData, " requires ", name, NULL);
+ AddRequirementsToResult(interp, reqc, reqv);
return NULL;
}
/*
* The package isn't yet present. Search the list of available
- * versions and invoke the script for the best available version.
- *
- * For TIP 268 we are actually locating the best, and the best stable
- * version. One of them is then chosen based on the selection mode.
+ * versions and invoke the script for the best available version. We
+ * are actually locating the best, and the best stable version. One of
+ * them is then chosen based on the selection mode.
*/
-#ifndef TCL_TIP268
- bestPtr = NULL;
- for (availPtr = pkgPtr->availPtr; availPtr != NULL;
- availPtr = availPtr->nextPtr) {
- if ((bestPtr != NULL) && (ComparePkgVersions(availPtr->version,
- bestPtr->version, (int *) NULL) <= 0)) {
-#else
+
bestPtr = NULL;
bestStablePtr = NULL;
bestVersion = NULL;
@@ -459,34 +394,32 @@ PkgRequireCore(
availPtr = availPtr->nextPtr) {
if (CheckVersionAndConvert(interp, availPtr->version,
&availVersion, &availStable) != TCL_OK) {
- /* The provided version number has invalid syntax. This
+ /*
+ * The provided version number has invalid syntax. This
* should not happen. This should have been caught by the
* 'package ifneeded' registering the package.
*/
-#endif
+
continue;
}
-#ifndef TCL_TIP268
- if (version != NULL) {
- result = ComparePkgVersions(availPtr->version, version,
- &satisfies);
- if ((result != 0) && exact) {
-#else
+
if (bestPtr != NULL) {
- int res = CompareVersions (availVersion, bestVersion, NULL);
+ int res = CompareVersions(availVersion, bestVersion, NULL);
+
+ /*
+ * Note: Use internal reps!
+ */
- /* Note: Use internal reps! */
if (res <= 0) {
/*
* The version of the package sought is not as good as the
* currently selected version. Ignore it.
*/
+
ckfree(availVersion);
availVersion = NULL;
-#endif
continue;
}
-#ifdef TCL_TIP268
}
/* We have found a version which is better than our max. */
@@ -495,24 +428,19 @@ PkgRequireCore(
/* Check satisfaction of requirements. */
satisfies = SomeRequirementSatisfied(availVersion, reqc, reqv);
-#endif
if (!satisfies) {
-#ifdef TCL_TIP268
ckfree(availVersion);
availVersion = NULL;
-#endif
continue;
}
}
bestPtr = availPtr;
-#ifdef TCL_TIP268
if (bestVersion != NULL) {
ckfree(bestVersion);
}
bestVersion = availVersion;
- availVersion = NULL;
/*
* If this new best version is stable then it also has to be
@@ -525,10 +453,11 @@ PkgRequireCore(
}
if (bestVersion != NULL) {
- ckfree(bestVersion);
+ ckfree(bestVersion);
}
- /* Now choose a version among the two best. For 'latest' we simply
+ /*
+ * Now choose a version among the two best. For 'latest' we simply
* take (actually keep) the best. For 'stable' we take the best
* stable, if there is any, or the best if there is nothing stable.
*/
@@ -536,8 +465,8 @@ PkgRequireCore(
if ((iPtr->packagePrefer == PKG_PREFER_STABLE)
&& (bestStablePtr != NULL)) {
bestPtr = bestStablePtr;
-#endif
}
+
if (bestPtr != NULL) {
/*
* We found an ifneeded script for the package. Be careful while
@@ -546,7 +475,7 @@ PkgRequireCore(
* will still exist when the script completes.
*/
- CONST char *versionToProvide = bestPtr->version;
+ const char *versionToProvide = bestPtr->version;
script = bestPtr->script;
pkgPtr->clientData = (ClientData) versionToProvide;
@@ -557,60 +486,15 @@ PkgRequireCore(
pkgPtr = FindPackage(interp, name);
if (code == TCL_OK) {
-#ifdef TCL_TIP268
Tcl_ResetResult(interp);
-#endif
if (pkgPtr->version == NULL) {
-#ifndef TCL_TIP268
- Tcl_ResetResult(interp);
-#endif
code = TCL_ERROR;
Tcl_AppendResult(interp, "attempt to provide package ",
name, " ", versionToProvide,
" failed: no version of package ", name,
" provided", NULL);
-#ifndef TCL_TIP268
- } else if (0 != ComparePkgVersions(
- pkgPtr->version, versionToProvide, NULL)) {
- /* At this point, it is clear that a prior
- * [package ifneeded] command lied to us. It said
- * that to get a particular version of a particular
- * package, we needed to evaluate a particular script.
- * However, we evaluated that script and got a different
- * version than we were told. This is an error, and we
- * ought to report it.
- *
- * However, we've been letting this type of error slide
- * for a long time, and as a result, a lot of packages
- * suffer from them.
- *
- * It's a bit too harsh to make a large number of
- * existing packages start failing by releasing a
- * new patch release, so we forgive this type of error
- * for the rest of the Tcl 8.4 series.
- *
- * We considered reporting a warning, but in practice
- * even that appears too harsh a change for a patch release.
- *
- * We limit the error reporting to only
- * the situation where a broken ifneeded script leads
- * to a failure to satisfy the requirement.
- */
- if (version) {
- result = ComparePkgVersions(
- pkgPtr->version, version, &satisfies);
- if (result && (exact || !satisfies)) {
- Tcl_ResetResult(interp);
- code = TCL_ERROR;
- Tcl_AppendResult(interp,
- "attempt to provide package ", name, " ",
- versionToProvide, " failed: package ",
- name, " ", pkgPtr->version,
- " provided instead", NULL);
-#else
} else {
char *pvi, *vi;
- int res;
if (CheckVersionAndConvert(interp, pkgPtr->version, &pvi,
NULL) != TCL_OK) {
@@ -620,66 +504,36 @@ PkgRequireCore(
ckfree(pvi);
code = TCL_ERROR;
} else {
- res = CompareVersions(pvi, vi, NULL);
- ckfree(vi);
+ int res = CompareVersions(pvi, vi, NULL);
+ ckfree(pvi);
+ ckfree(vi);
if (res != 0) {
- /* At this point, it is clear that a prior
- * [package ifneeded] command lied to us. It said
- * that to get a particular version of a particular
- * package, we needed to evaluate a particular
- * script. However, we evaluated that script and
- * got a different version than we were told.
- * This is an error, and we ought to report it.
- *
- * However, we've been letting this type of error
- * slide for a long time, and as a result, a lot
- * of packages suffer from them.
- *
- * It's a bit too harsh to make a large number of
- * existing packages start failing by releasing a
- * new patch release, so we forgive this type of
- * error for the rest of the Tcl 8.4 series.
- *
- * We considered reporting a warning, but in
- * practice even that appears too harsh a change
- * for a patch release.
- *
- * We limit the error reporting to only the
- * situation where a broken ifneeded script leads
- * to a failure to satisfy the requirement.
- */
-
- if (reqc > 0) {
- satisfies = SomeRequirementSatisfied(pvi,
- reqc, reqv);
- if (!satisfies) {
- code = TCL_ERROR;
- Tcl_AppendResult(interp,
- "attempt to provide package ",
- name, " ", versionToProvide,
- " failed: package ", name, " ",
- pkgPtr->version,
- " provided instead", NULL);
- }
- }
-#endif
+ code = TCL_ERROR;
+ Tcl_AppendResult(interp,
+ "attempt to provide package ", name, " ",
+ versionToProvide, " failed: package ",
+ name, " ", pkgPtr->version,
+ " provided instead", NULL);
}
-#ifdef TCL_TIP268
- ckfree(pvi);
-#endif
}
}
} else if (code != TCL_ERROR) {
Tcl_Obj *codePtr = Tcl_NewIntObj(code);
+
Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "attempt to provide package ",
- name, " ", versionToProvide, " failed: ",
- "bad return code: ", Tcl_GetString(codePtr), NULL);
- Tcl_DecrRefCount(codePtr);
+ Tcl_AppendResult(interp, "attempt to provide package ", name,
+ " ", versionToProvide, " failed: bad return code: ",
+ TclGetString(codePtr), NULL);
+ TclDecrRefCount(codePtr);
code = TCL_ERROR;
}
+ if (code == TCL_ERROR) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (\"package ifneeded %s %s\" script)",
+ name, versionToProvide));
+ }
Tcl_Release((ClientData) versionToProvide);
if (code != TCL_OK) {
@@ -688,12 +542,12 @@ PkgRequireCore(
* package wasn't loaded properly, so the package system
* should not remember an improper load.
*
- * This is consistent with our returning NULL. If we're not
+ * This is consistent with our returning NULL. If we're not
* willing to tell our caller we got a particular version, we
* shouldn't store that version for telling future callers
* either.
*/
- Tcl_AddErrorInfo(interp, "\n (\"package ifneeded\" script)");
+
if (pkgPtr->version != NULL) {
ckfree(pkgPtr->version);
pkgPtr->version = NULL;
@@ -720,30 +574,23 @@ PkgRequireCore(
Tcl_DStringInit(&command);
Tcl_DStringAppend(&command, script, -1);
Tcl_DStringAppendElement(&command, name);
-#ifndef TCL_TIP268
- Tcl_DStringAppend(&command, " ", 1);
- Tcl_DStringAppend(&command, (version != NULL) ? version : "{}",
- -1);
- if (exact) {
- Tcl_DStringAppend(&command, " -exact", 7);
- }
-#else
AddRequirementsToDString(&command, reqc, reqv);
-#endif
+
code = Tcl_EvalEx(interp, Tcl_DStringValue(&command),
- Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
+ Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
Tcl_DStringFree(&command);
if ((code != TCL_OK) && (code != TCL_ERROR)) {
Tcl_Obj *codePtr = Tcl_NewIntObj(code);
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, "bad return code: ",
- Tcl_GetString(codePtr), NULL);
+ TclGetString(codePtr), NULL);
Tcl_DecrRefCount(codePtr);
code = TCL_ERROR;
}
if (code == TCL_ERROR) {
- Tcl_AddErrorInfo(interp, "\n (\"package unknown\" script)");
+ Tcl_AddErrorInfo(interp,
+ "\n (\"package unknown\" script)");
return NULL;
}
Tcl_ResetResult(interp);
@@ -751,14 +598,8 @@ PkgRequireCore(
}
if (pkgPtr->version == NULL) {
- Tcl_AppendResult(interp, "can't find package ", name, (char *) NULL);
-#ifndef TCL_TIP268
- if (version != NULL) {
- Tcl_AppendResult(interp, " ", version, (char *) NULL);
- }
-#else
+ Tcl_AppendResult(interp, "can't find package ", name, NULL);
AddRequirementsToResult(interp, reqc, reqv);
-#endif
return NULL;
}
@@ -767,13 +608,6 @@ PkgRequireCore(
* provided version meets the current requirements.
*/
-#ifndef TCL_TIP268
- if (version == NULL) {
- if (clientDataPtr) {
- *clientDataPtr = pkgPtr->clientData;
- }
- return pkgPtr->version;
-#else
if (reqc == 0) {
satisfies = 1;
} else {
@@ -781,27 +615,18 @@ PkgRequireCore(
satisfies = SomeRequirementSatisfied(pkgVersionI, reqc, reqv);
ckfree(pkgVersionI);
-#endif
}
-#ifndef TCL_TIP268
- result = ComparePkgVersions(pkgPtr->version, version, &satisfies);
- if ((satisfies && !exact) || (result == 0)) {
-#else
+
if (satisfies) {
-#endif
if (clientDataPtr) {
*clientDataPtr = pkgPtr->clientData;
}
return pkgPtr->version;
}
+
Tcl_AppendResult(interp, "version conflict for package \"", name,
- "\": have ", pkgPtr->version,
-#ifndef TCL_TIP268
- ", need ", version, (char *) NULL);
-#else
- ", need", (char*) NULL);
- AddRequirementsToResult (interp, reqc, reqv);
-#endif
+ "\": have ", pkgPtr->version, ", need", NULL);
+ AddRequirementsToResult(interp, reqc, reqv);
return NULL;
}
@@ -810,16 +635,15 @@ PkgRequireCore(
*
* Tcl_PkgPresent / Tcl_PkgPresentEx --
*
- * Checks to see whether the specified package is present. If it
- * is not then no additional action is taken.
+ * Checks to see whether the specified package is present. If it is not
+ * then no additional action is taken.
*
* Results:
- * If successful, returns the version string for the currently
- * provided version of the package, which may be different from
- * the "version" argument. If the caller's requirements
- * cannot be met (e.g. the version requested conflicts with
- * a currently provided version), NULL is returned and an error
- * message is left in interp->result.
+ * If successful, returns the version string for the currently provided
+ * version of the package, which may be different from the "version"
+ * argument. If the caller's requirements cannot be met (e.g. the version
+ * requested conflicts with a currently provided version), NULL is
+ * returned and an error message is left in interp->result.
*
* Side effects:
* None.
@@ -827,36 +651,34 @@ PkgRequireCore(
*----------------------------------------------------------------------
*/
-CONST char *
-Tcl_PkgPresent(interp, name, version, exact)
- Tcl_Interp *interp; /* Interpreter in which package is now
+const char *
+Tcl_PkgPresent(
+ Tcl_Interp *interp, /* Interpreter in which package is now
* available. */
- CONST char *name; /* Name of desired package. */
- CONST char *version; /* Version string for desired version;
- * NULL means use the latest version
- * available. */
- int exact; /* Non-zero means that only the particular
- * version given is acceptable. Zero means
- * use the latest compatible version. */
+ const char *name, /* Name of desired package. */
+ const char *version, /* Version string for desired version; NULL
+ * means use the latest version available. */
+ int exact) /* Non-zero means that only the particular
+ * version given is acceptable. Zero means use
+ * the latest compatible version. */
{
- return Tcl_PkgPresentEx(interp, name, version, exact, (ClientData *) NULL);
+ return Tcl_PkgPresentEx(interp, name, version, exact, NULL);
}
-CONST char *
-Tcl_PkgPresentEx(interp, name, version, exact, clientDataPtr)
- Tcl_Interp *interp; /* Interpreter in which package is now
- * available. */
- CONST char *name; /* Name of desired package. */
- CONST char *version; /* Version string for desired version;
- * NULL means use the latest version
+const char *
+Tcl_PkgPresentEx(
+ Tcl_Interp *interp, /* Interpreter in which package is now
* available. */
- int exact; /* Non-zero means that only the particular
- * version given is acceptable. Zero means
- * use the latest compatible version. */
- ClientData *clientDataPtr; /* Used to return the client data for this
- * package. If it is NULL then the client
- * data is not returned. This is unchanged
- * if this call fails for any reason. */
+ const char *name, /* Name of desired package. */
+ const char *version, /* Version string for desired version; NULL
+ * means use the latest version available. */
+ int exact, /* Non-zero means that only the particular
+ * version given is acceptable. Zero means use
+ * the latest compatible version. */
+ ClientData *clientDataPtr) /* Used to return the client data for this
+ * package. If it is NULL then the client data
+ * is not returned. This is unchanged if this
+ * call fails for any reason. */
{
Interp *iPtr = (Interp *) interp;
Tcl_HashEntry *hPtr;
@@ -864,17 +686,22 @@ Tcl_PkgPresentEx(interp, name, version, exact, clientDataPtr)
hPtr = Tcl_FindHashEntry(&iPtr->packageTable, name);
if (hPtr) {
- pkgPtr = (Package *) Tcl_GetHashValue(hPtr);
+ pkgPtr = Tcl_GetHashValue(hPtr);
if (pkgPtr->version != NULL) {
-
/*
- * At this point we know that the package is present. Make sure
+ * At this point we know that the package is present. Make sure
* that the provided version meets the current requirement by
* calling Tcl_PkgRequireEx() to check for us.
*/
- return Tcl_PkgRequireEx(interp, name, version, exact,
- clientDataPtr);
+ const char *foundVersion = Tcl_PkgRequireEx(interp, name, version,
+ exact, clientDataPtr);
+
+ if (foundVersion == NULL) {
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PACKAGE", name,
+ NULL);
+ }
+ return foundVersion;
}
}
@@ -884,6 +711,7 @@ Tcl_PkgPresentEx(interp, name, version, exact, clientDataPtr)
} else {
Tcl_AppendResult(interp, "package ", name, " is not present", NULL);
}
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PACKAGE", name, NULL);
return NULL;
}
@@ -892,8 +720,8 @@ Tcl_PkgPresentEx(interp, name, version, exact, clientDataPtr)
*
* Tcl_PackageObjCmd --
*
- * This procedure is invoked to process the "package" Tcl command.
- * See the user documentation for details on what it does.
+ * This function is invoked to process the "package" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -904,29 +732,23 @@ Tcl_PkgPresentEx(interp, name, version, exact, clientDataPtr)
*----------------------------------------------------------------------
*/
-/* ARGSUSED */
+ /* ARGSUSED */
int
-Tcl_PackageObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_PackageObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- static CONST char *pkgOptions[] = {
- "forget", "ifneeded", "names",
-#ifdef TCL_TIP268
- "prefer",
-#endif
- "present", "provide", "require", "unknown", "vcompare",
- "versions", "vsatisfies", (char *) NULL
+ static const char *pkgOptions[] = {
+ "forget", "ifneeded", "names", "prefer", "present",
+ "provide", "require", "unknown", "vcompare", "versions",
+ "vsatisfies", NULL
};
enum pkgOptions {
- PKG_FORGET, PKG_IFNEEDED, PKG_NAMES,
-#ifdef TCL_TIP268
- PKG_PREFER,
-#endif
- PKG_PRESENT, PKG_PROVIDE, PKG_REQUIRE, PKG_UNKNOWN, PKG_VCOMPARE,
- PKG_VERSIONS, PKG_VSATISFIES
+ PKG_FORGET, PKG_IFNEEDED, PKG_NAMES, PKG_PREFER, PKG_PRESENT,
+ PKG_PROVIDE, PKG_REQUIRE, PKG_UNKNOWN, PKG_VCOMPARE, PKG_VERSIONS,
+ PKG_VSATISFIES
};
Interp *iPtr = (Interp *) interp;
int optionIndex, exact, i, satisfies;
@@ -935,32 +757,29 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
Tcl_HashEntry *hPtr;
Tcl_HashSearch search;
Tcl_HashTable *tablePtr;
- CONST char *version;
- char *argv2, *argv3, *argv4;
-#ifdef TCL_TIP268
- char* iva = NULL;
- char* ivb = NULL;
-#endif
+ const char *version;
+ char *argv2, *argv3, *argv4, *iva = NULL, *ivb = NULL;
if (objc < 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[1], pkgOptions, "option", 0,
- &optionIndex) != TCL_OK) {
+ &optionIndex) != TCL_OK) {
return TCL_ERROR;
}
switch ((enum pkgOptions) optionIndex) {
case PKG_FORGET: {
char *keyString;
+
for (i = 2; i < objc; i++) {
- keyString = Tcl_GetString(objv[i]);
+ keyString = TclGetString(objv[i]);
hPtr = Tcl_FindHashEntry(&iPtr->packageTable, keyString);
if (hPtr == NULL) {
- continue;
+ continue;
}
- pkgPtr = (Package *) Tcl_GetHashValue(hPtr);
+ pkgPtr = Tcl_GetHashValue(hPtr);
Tcl_DeleteHashEntry(hPtr);
if (pkgPtr->version != NULL) {
ckfree(pkgPtr->version);
@@ -977,43 +796,32 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
break;
}
case PKG_IFNEEDED: {
- int length;
-#ifdef TCL_TIP268
- int res;
+ int length, res;
char *argv3i, *avi;
-#endif
if ((objc != 4) && (objc != 5)) {
Tcl_WrongNumArgs(interp, 2, objv, "package version ?script?");
return TCL_ERROR;
}
- argv3 = Tcl_GetString(objv[3]);
-#ifdef TCL_TIP268
+ argv3 = TclGetString(objv[3]);
if (CheckVersionAndConvert(interp, argv3, &argv3i, NULL) != TCL_OK) {
-#else
- if (CheckVersion(interp, argv3) != TCL_OK) {
-#endif
return TCL_ERROR;
}
- argv2 = Tcl_GetString(objv[2]);
+ argv2 = TclGetString(objv[2]);
if (objc == 4) {
hPtr = Tcl_FindHashEntry(&iPtr->packageTable, argv2);
if (hPtr == NULL) {
-#ifdef TCL_TIP268
ckfree(argv3i);
-#endif
return TCL_OK;
}
- pkgPtr = (Package *) Tcl_GetHashValue(hPtr);
+ pkgPtr = Tcl_GetHashValue(hPtr);
} else {
pkgPtr = FindPackage(interp, argv2);
}
argv3 = Tcl_GetStringFromObj(objv[3], &length);
for (availPtr = pkgPtr->availPtr, prevPtr = NULL; availPtr != NULL;
- prevPtr = availPtr, availPtr = availPtr->nextPtr) {
-
-#ifdef TCL_TIP268
+ prevPtr = availPtr, availPtr = availPtr->nextPtr) {
if (CheckVersionAndConvert(interp, availPtr->version, &avi,
NULL) != TCL_OK) {
ckfree(argv3i);
@@ -1024,14 +832,8 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
ckfree(avi);
if (res == 0){
-#else
- if (ComparePkgVersions(availPtr->version, argv3, (int *) NULL)
- == 0) {
-#endif
if (objc == 4) {
-#ifdef TCL_TIP268
ckfree(argv3i);
-#endif
Tcl_SetResult(interp, availPtr->script, TCL_VOLATILE);
return TCL_OK;
}
@@ -1039,9 +841,8 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
break;
}
}
-#ifdef TCL_TIP268
ckfree(argv3i);
-#endif
+
if (objc == 4) {
return TCL_OK;
}
@@ -1061,27 +862,26 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
DupBlock(availPtr->script, argv4, (unsigned) length + 1);
break;
}
- case PKG_NAMES: {
+ case PKG_NAMES:
if (objc != 2) {
Tcl_WrongNumArgs(interp, 2, objv, NULL);
return TCL_ERROR;
}
tablePtr = &iPtr->packageTable;
for (hPtr = Tcl_FirstHashEntry(tablePtr, &search); hPtr != NULL;
- hPtr = Tcl_NextHashEntry(&search)) {
- pkgPtr = (Package *) Tcl_GetHashValue(hPtr);
+ hPtr = Tcl_NextHashEntry(&search)) {
+ pkgPtr = Tcl_GetHashValue(hPtr);
if ((pkgPtr->version != NULL) || (pkgPtr->availPtr != NULL)) {
Tcl_AppendElement(interp, Tcl_GetHashKey(tablePtr, hPtr));
}
}
break;
- }
case PKG_PRESENT: {
const char *name;
if (objc < 3) {
goto require;
}
- argv2 = Tcl_GetString(objv[2]);
+ argv2 = TclGetString(objv[2]);
if ((argv2[0] == '-') && (strcmp(argv2, "-exact") == 0)) {
if (objc != 5) {
goto requireSyntax;
@@ -1100,138 +900,98 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
goto require;
}
}
-#ifndef TCL_TIP268
- version = NULL;
- if (objc == (4 + exact)) {
- version = Tcl_GetString(objv[3 + exact]);
- if (CheckVersion(interp, version) != TCL_OK) {
- return TCL_ERROR;
- }
- } else if ((objc != 3) || exact) {
- goto requireSyntax;
- }
-#else
+
version = NULL;
if (exact) {
- version = Tcl_GetString(objv[4]);
- if (CheckVersionAndConvert(interp, version, NULL, NULL) != TCL_OK) {
+ version = TclGetString(objv[4]);
+ if (CheckVersionAndConvert(interp, version, NULL,
+ NULL) != TCL_OK) {
return TCL_ERROR;
}
} else {
if (CheckAllRequirements(interp, objc-3, objv+3) != TCL_OK) {
return TCL_ERROR;
- }
+ }
if ((objc > 3) && (CheckVersionAndConvert(interp,
TclGetString(objv[3]), NULL, NULL) == TCL_OK)) {
version = TclGetString(objv[3]);
}
}
-#endif
Tcl_PkgPresent(interp, name, version, exact);
return TCL_ERROR;
break;
}
- case PKG_PROVIDE: {
+ case PKG_PROVIDE:
if ((objc != 3) && (objc != 4)) {
Tcl_WrongNumArgs(interp, 2, objv, "package ?version?");
return TCL_ERROR;
}
- argv2 = Tcl_GetString(objv[2]);
+ argv2 = TclGetString(objv[2]);
if (objc == 3) {
hPtr = Tcl_FindHashEntry(&iPtr->packageTable, argv2);
if (hPtr != NULL) {
- pkgPtr = (Package *) Tcl_GetHashValue(hPtr);
+ pkgPtr = Tcl_GetHashValue(hPtr);
if (pkgPtr->version != NULL) {
Tcl_SetResult(interp, pkgPtr->version, TCL_VOLATILE);
}
}
return TCL_OK;
}
- argv3 = Tcl_GetString(objv[3]);
-#ifndef TCL_TIP268
- if (CheckVersion(interp, argv3) != TCL_OK) {
-#else
+ argv3 = TclGetString(objv[3]);
if (CheckVersionAndConvert(interp, argv3, NULL, NULL) != TCL_OK) {
-#endif
return TCL_ERROR;
}
return Tcl_PkgProvide(interp, argv2, argv3);
- }
- case PKG_REQUIRE: {
+ case PKG_REQUIRE:
require:
if (objc < 3) {
requireSyntax:
-#ifndef TCL_TIP268
- Tcl_WrongNumArgs(interp, 2, objv, "?-exact? package ?version?");
-#else
Tcl_WrongNumArgs(interp, 2, objv,
"?-exact? package ?requirement...?");
-#endif
return TCL_ERROR;
}
-#ifndef TCL_TIP268
- argv2 = Tcl_GetString(objv[2]);
- if ((argv2[0] == '-') && (strcmp(argv2, "-exact") == 0)) {
- exact = 1;
- } else {
- exact = 0;
- }
- version = NULL;
- if (objc == (4 + exact)) {
- version = Tcl_GetString(objv[3 + exact]);
- if (CheckVersion(interp, version) != TCL_OK) {
- return TCL_ERROR;
- }
- } else if ((objc != 3) || exact) {
- goto requireSyntax;
- }
- if (exact) {
- argv3 = Tcl_GetString(objv[3]);
- version = Tcl_PkgRequire(interp, argv3, version, exact);
- } else {
- version = Tcl_PkgRequire(interp, argv2, version, exact);
- }
- if (version == NULL) {
- return TCL_ERROR;
- }
- Tcl_SetObjResult( interp, Tcl_NewStringObj( version, -1 ) );
-#else
+
version = NULL;
- argv2 = Tcl_GetString(objv[2]);
+
+ argv2 = TclGetString(objv[2]);
if ((argv2[0] == '-') && (strcmp(argv2, "-exact") == 0)) {
- Tcl_Obj* ov;
+ Tcl_Obj *ov;
int res;
if (objc != 5) {
goto requireSyntax;
}
- version = Tcl_GetString(objv[4]);
- if (CheckVersionAndConvert(interp, version, NULL, NULL) != TCL_OK) {
+
+ version = TclGetString(objv[4]);
+ if (CheckVersionAndConvert(interp, version, NULL,
+ NULL) != TCL_OK) {
return TCL_ERROR;
}
- /* Create a new-style requirement for the exact version. */
+ /*
+ * Create a new-style requirement for the exact version.
+ */
ov = Tcl_NewStringObj(version, -1);
Tcl_AppendStringsToObj(ov, "-", version, NULL);
version = NULL;
- argv3 = Tcl_GetString(objv[3]);
+ argv3 = TclGetString(objv[3]);
- Tcl_IncrRefCount (ov);
+ Tcl_IncrRefCount(ov);
res = Tcl_PkgRequireProc(interp, argv3, 1, &ov, NULL);
- Tcl_DecrRefCount (ov);
+ TclDecrRefCount(ov);
return res;
} else {
- if (CheckAllRequirements (interp, objc-3, objv+3) != TCL_OK) {
+ if (CheckAllRequirements(interp, objc-3, objv+3) != TCL_OK) {
return TCL_ERROR;
}
+
return Tcl_PkgRequireProc(interp, argv2, objc-3, objv+3, NULL);
}
-#endif
break;
- }
case PKG_UNKNOWN: {
int length;
+
if (objc == 2) {
if (iPtr->packageUnknown != NULL) {
Tcl_SetResult(interp, iPtr->packageUnknown, TCL_VOLATILE);
@@ -1244,7 +1004,7 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
if (argv2[0] == 0) {
iPtr->packageUnknown = NULL;
} else {
- DupBlock(iPtr->packageUnknown, argv2, (unsigned) length + 1);
+ DupBlock(iPtr->packageUnknown, argv2, (unsigned) length+1);
}
} else {
Tcl_WrongNumArgs(interp, 2, objv, "?command?");
@@ -1252,85 +1012,89 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
}
break;
}
-#ifdef TCL_TIP268
case PKG_PREFER: {
- /* See tclInt.h for the enum, just before Interp */
- static CONST char *pkgPreferOptions[] = {
+ static const char *pkgPreferOptions[] = {
"latest", "stable", NULL
};
+ /*
+ * See tclInt.h for the enum, just before Interp.
+ */
+
if (objc > 3) {
Tcl_WrongNumArgs(interp, 2, objv, "?latest|stable?");
return TCL_ERROR;
} else if (objc == 3) {
- /* Set value. */
- int new;
+ /*
+ * Seting the value.
+ */
+
+ int newPref;
+
if (Tcl_GetIndexFromObj(interp, objv[2], pkgPreferOptions,
- "preference", 0, &new) != TCL_OK) {
+ "preference", 0, &newPref) != TCL_OK) {
return TCL_ERROR;
}
- if (new < iPtr->packagePrefer) {
- iPtr->packagePrefer = new;
+
+ if (newPref < iPtr->packagePrefer) {
+ iPtr->packagePrefer = newPref;
}
}
- /* Always return current value. */
+
+ /*
+ * Always return current value.
+ */
+
Tcl_SetObjResult(interp,
Tcl_NewStringObj(pkgPreferOptions[iPtr->packagePrefer], -1));
break;
}
-#endif
- case PKG_VCOMPARE: {
+ case PKG_VCOMPARE:
if (objc != 4) {
Tcl_WrongNumArgs(interp, 2, objv, "version1 version2");
return TCL_ERROR;
}
- argv3 = Tcl_GetString(objv[3]);
- argv2 = Tcl_GetString(objv[2]);
-#ifndef TCL_TIP268
- if ((CheckVersion(interp, argv2) != TCL_OK)
- || (CheckVersion(interp, argv3) != TCL_OK)) {
- return TCL_ERROR;
- }
- Tcl_SetObjResult(interp, Tcl_NewIntObj(
- ComparePkgVersions(argv2, argv3, (int *) NULL)));
-#else
- if ((CheckVersionAndConvert (interp, argv2, &iva, NULL) != TCL_OK)
- || (CheckVersionAndConvert (interp, argv3, &ivb, NULL)
- != TCL_OK)) {
+ argv3 = TclGetString(objv[3]);
+ argv2 = TclGetString(objv[2]);
+ if (CheckVersionAndConvert(interp, argv2, &iva, NULL) != TCL_OK ||
+ CheckVersionAndConvert(interp, argv3, &ivb, NULL) != TCL_OK) {
if (iva != NULL) {
ckfree(iva);
}
- /* ivb cannot be set in this branch */
+
+ /*
+ * ivb cannot be set in this branch.
+ */
+
return TCL_ERROR;
}
- /* Comparison is done on the internal representation */
+ /*
+ * Comparison is done on the internal representation.
+ */
+
Tcl_SetObjResult(interp,
Tcl_NewIntObj(CompareVersions(iva, ivb, NULL)));
ckfree(iva);
ckfree(ivb);
-#endif
break;
- }
- case PKG_VERSIONS: {
+ case PKG_VERSIONS:
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "package");
return TCL_ERROR;
}
- argv2 = Tcl_GetString(objv[2]);
+ argv2 = TclGetString(objv[2]);
hPtr = Tcl_FindHashEntry(&iPtr->packageTable, argv2);
if (hPtr != NULL) {
- pkgPtr = (Package *) Tcl_GetHashValue(hPtr);
+ pkgPtr = Tcl_GetHashValue(hPtr);
for (availPtr = pkgPtr->availPtr; availPtr != NULL;
- availPtr = availPtr->nextPtr) {
+ availPtr = availPtr->nextPtr) {
Tcl_AppendElement(interp, availPtr->version);
}
}
break;
- }
case PKG_VSATISFIES: {
-#ifdef TCL_TIP268
- char* argv2i = NULL;
+ char *argv2i = NULL;
if (objc < 4) {
Tcl_WrongNumArgs(interp, 2, objv,
@@ -1338,8 +1102,8 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
return TCL_ERROR;
}
- argv2 = Tcl_GetString(objv[2]);
- if ((CheckVersionAndConvert(interp, argv2, &argv2i, NULL) != TCL_OK)) {
+ argv2 = TclGetString(objv[2]);
+ if (CheckVersionAndConvert(interp, argv2, &argv2i, NULL) != TCL_OK) {
return TCL_ERROR;
} else if (CheckAllRequirements(interp, objc-3, objv+3) != TCL_OK) {
ckfree(argv2i);
@@ -1347,27 +1111,13 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
}
satisfies = SomeRequirementSatisfied(argv2i, objc-3, objv+3);
- ckfree (argv2i);
-#else
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "version1 version2");
- return TCL_ERROR;
- }
- argv3 = Tcl_GetString(objv[3]);
- argv2 = Tcl_GetString(objv[2]);
- if ((CheckVersion(interp, argv2) != TCL_OK)
- || (CheckVersion(interp, argv3) != TCL_OK)) {
- return TCL_ERROR;
- }
- ComparePkgVersions(argv2, argv3, &satisfies);
-#endif
+ ckfree(argv2i);
- Tcl_SetObjResult(interp, Tcl_NewIntObj(satisfies));
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(satisfies));
break;
}
- default: {
- panic("Tcl_PackageObjCmd: bad option index to pkgOptions");
- }
+ default:
+ Tcl_Panic("Tcl_PackageObjCmd: bad option index to pkgOptions");
}
return TCL_OK;
}
@@ -1377,13 +1127,12 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
*
* FindPackage --
*
- * This procedure finds the Package record for a particular package
- * in a particular interpreter, creating a record if one doesn't
- * already exist.
+ * This function finds the Package record for a particular package in a
+ * particular interpreter, creating a record if one doesn't already
+ * exist.
*
* Results:
- * The return value is a pointer to the Package record for the
- * package.
+ * The return value is a pointer to the Package record for the package.
*
* Side effects:
* A new Package record may be created.
@@ -1392,24 +1141,24 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
*/
static Package *
-FindPackage(interp, name)
- Tcl_Interp *interp; /* Interpreter to use for package lookup. */
- CONST char *name; /* Name of package to fine. */
+FindPackage(
+ Tcl_Interp *interp, /* Interpreter to use for package lookup. */
+ const char *name) /* Name of package to fine. */
{
Interp *iPtr = (Interp *) interp;
Tcl_HashEntry *hPtr;
- int new;
+ int isNew;
Package *pkgPtr;
- hPtr = Tcl_CreateHashEntry(&iPtr->packageTable, name, &new);
- if (new) {
+ hPtr = Tcl_CreateHashEntry(&iPtr->packageTable, name, &isNew);
+ if (isNew) {
pkgPtr = (Package *) ckalloc(sizeof(Package));
pkgPtr->version = NULL;
pkgPtr->availPtr = NULL;
pkgPtr->clientData = NULL;
Tcl_SetHashValue(hPtr, pkgPtr);
} else {
- pkgPtr = (Package *) Tcl_GetHashValue(hPtr);
+ pkgPtr = Tcl_GetHashValue(hPtr);
}
return pkgPtr;
}
@@ -1419,9 +1168,8 @@ FindPackage(interp, name)
*
* TclFreePackageInfo --
*
- * This procedure is called during interpreter deletion to
- * free all of the package-related information for the
- * interpreter.
+ * This function is called during interpreter deletion to free all of the
+ * package-related information for the interpreter.
*
* Results:
* None.
@@ -1433,8 +1181,8 @@ FindPackage(interp, name)
*/
void
-TclFreePackageInfo(iPtr)
- Interp *iPtr; /* Interpreter that is being deleted. */
+TclFreePackageInfo(
+ Interp *iPtr) /* Interpereter that is being deleted. */
{
Package *pkgPtr;
Tcl_HashSearch search;
@@ -1442,8 +1190,8 @@ TclFreePackageInfo(iPtr)
PkgAvail *availPtr;
for (hPtr = Tcl_FirstHashEntry(&iPtr->packageTable, &search);
- hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
- pkgPtr = (Package *) Tcl_GetHashValue(hPtr);
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ pkgPtr = Tcl_GetHashValue(hPtr);
if (pkgPtr->version != NULL) {
ckfree(pkgPtr->version);
}
@@ -1465,15 +1213,16 @@ TclFreePackageInfo(iPtr)
/*
*----------------------------------------------------------------------
*
- * CheckVersion / CheckVersionAndConvert --
+ * CheckVersionAndConvert --
*
- * This procedure checks to see whether a version number has
- * valid syntax.
+ * This function checks to see whether a version number has valid syntax.
+ * It also generates a semi-internal representation (string rep of a list
+ * of numbers).
*
* Results:
- * If string is a properly formed version number the TCL_OK
- * is returned. Otherwise TCL_ERROR is returned and an error
- * message is left in the interp's result.
+ * If string is a properly formed version number the TCL_OK is returned.
+ * Otherwise TCL_ERROR is returned and an error message is left in the
+ * interp's result.
*
* Side effects:
* None.
@@ -1481,60 +1230,31 @@ TclFreePackageInfo(iPtr)
*----------------------------------------------------------------------
*/
-#ifndef TCL_TIP268
static int
-CheckVersion(interp, string)
- Tcl_Interp *interp; /* Used for error reporting. */
- CONST char *string; /* Supposedly a version number, which is
- * groups of decimal digits separated
- * by dots. */
-{
- CONST char *p = string;
- char prevChar;
- if (!isdigit(UCHAR(*p))) { /* INTL: digit */
- goto error;
- }
- for (prevChar = *p, p++; *p != 0; p++) {
- if (!isdigit(UCHAR(*p)) &&
- ((*p != '.') || (prevChar == '.'))) { /* INTL: digit */
- goto error;
- }
- prevChar = *p;
- }
- if (prevChar != '.') {
- return TCL_OK;
- }
-
- error:
- Tcl_AppendResult(interp, "expected version number but got \"",
- string, "\"", (char *) NULL);
- return TCL_ERROR;
-}
-#else
-static int
-CheckVersionAndConvert(interp, string, internal, stable)
- Tcl_Interp *interp; /* Used for error reporting. */
- CONST char *string; /* Supposedly a version number, which is
+CheckVersionAndConvert(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ const char *string, /* Supposedly a version number, which is
* groups of decimal digits separated by
* dots. */
- char** internal; /* Internal normalized representation */
- int* stable; /* Flag: Version is (un)stable. */
+ char **internal, /* Internal normalized representation */
+ int *stable) /* Flag: Version is (un)stable. */
{
- CONST char *p = string;
+ const char *p = string;
char prevChar;
int hasunstable = 0;
/*
* 4* assuming that each char is a separator (a,b become ' -x ').
* 4+ to have spce for an additional -2 at the end
*/
- char* ibuf = ckalloc(4+4*strlen(string));
- char* ip = ibuf;
+ char *ibuf = ckalloc(4 + 4*strlen(string));
+ char *ip = ibuf;
- /* Basic rules
+ /*
+ * Basic rules
* (1) First character has to be a digit.
* (2) All other characters have to be a digit or '.'
* (3) Two '.'s may not follow each other.
-
+ *
* TIP 268, Modified rules
* (1) s.a.
* (2) All other characters have to be a digit, 'a', 'b', or '.'
@@ -1543,20 +1263,23 @@ CheckVersionAndConvert(interp, string, internal, stable)
* (5) Neither 'a', nor 'b' may occur before or after a '.'
*/
- if (!isdigit(UCHAR(*p))) { /* INTL: digit */
+ if (!isdigit(UCHAR(*p))) { /* INTL: digit */
goto error;
}
+
*ip++ = *p;
+
for (prevChar = *p, p++; *p != 0; p++) {
- if ((!isdigit(UCHAR(*p))) && (((*p != '.') && (*p != 'a')
- && (*p != 'b')) || ((hasunstable && ((*p == 'a')
- || (*p == 'b'))) || (((prevChar == 'a') || (prevChar == 'b')
- || (prevChar == '.')) && (*p == '.')) || (((*p == 'a')
- || (*p == 'b') || (*p == '.')) && (prevChar == '.'))))) {
- /* INTL: digit */
+ if (!isdigit(UCHAR(*p)) && /* INTL: digit */
+ ((*p!='.' && *p!='a' && *p!='b') ||
+ ((hasunstable && (*p=='a' || *p=='b')) ||
+ ((prevChar=='a' || prevChar=='b' || prevChar=='.')
+ && (*p=='.')) ||
+ ((*p=='a' || *p=='b' || *p=='.') && prevChar=='.')))) {
goto error;
}
- if ((*p == 'a') || (*p == 'b')) {
+
+ if (*p == 'a' || *p == 'b') {
hasunstable = 1;
}
@@ -1583,9 +1306,10 @@ CheckVersionAndConvert(interp, string, internal, stable)
} else {
*ip++ = *p;
}
+
prevChar = *p;
}
- if ((prevChar != '.') && (prevChar != 'a') && (prevChar != 'b')) {
+ if (prevChar!='.' && prevChar!='a' && prevChar!='b') {
*ip = '\0';
if (internal != NULL) {
*internal = ibuf;
@@ -1598,27 +1322,25 @@ CheckVersionAndConvert(interp, string, internal, stable)
return TCL_OK;
}
- error:
+ error:
ckfree(ibuf);
- Tcl_AppendResult(interp, "expected version number but got \"",
- string, "\"", (char *) NULL);
+ Tcl_AppendResult(interp, "expected version number but got \"", string,
+ "\"", NULL);
return TCL_ERROR;
}
-#endif
/*
*----------------------------------------------------------------------
*
- * ComparePkgVersions / CompareVersions --
+ * CompareVersions --
*
- * This procedure compares two version numbers. (268: in internal rep).
+ * This function compares two version numbers (in internal rep).
*
* Results:
- * The return value is -1 if v1 is less than v2, 0 if the two
- * version numbers are the same, and 1 if v1 is greater than v2.
- * If *satPtr is non-NULL, the word it points to is filled in
- * with 1 if v2 >= v1 and both numbers have the same major number
- * or 0 otherwise.
+ * The return value is -1 if v1 is less than v2, 0 if the two version
+ * numbers are the same, and 1 if v1 is greater than v2. If *satPtr is
+ * non-NULL, the word it points to is filled in with 1 if v2 >= v1 and
+ * both numbers have the same major number or 0 otherwise.
*
* Side effects:
* None.
@@ -1626,142 +1348,157 @@ CheckVersionAndConvert(interp, string, internal, stable)
*----------------------------------------------------------------------
*/
-#ifndef TCL_TIP268
static int
-ComparePkgVersions(v1, v2, satPtr)
- CONST char *v1;
- CONST char *v2; /* Versions strings, of form 2.1.3 (any
- * number of version numbers). */
- int *satPtr; /* If non-null, the word pointed to is
- * filled in with a 0/1 value. 1 means
- * v1 "satisfies" v2: v1 is greater than
- * or equal to v2 and both version numbers
- * have the same major number. */
+CompareVersions(
+ char *v1, char *v2, /* Versions strings, of form 2.1.3 (any number
+ * of version numbers). */
+ int *isMajorPtr) /* If non-null, the word pointed to is filled
+ * in with a 0/1 value. 1 means that the
+ * difference occured in the first element. */
{
- int thisIsMajor, n1, n2;
+ int thisIsMajor, res, flip;
+ char *s1, *e1, *s2, *e2, o1, o2;
/*
* Each iteration of the following loop processes one number from each
* string, terminated by a " " (space). If those numbers don't match then
* the comparison is over; otherwise, we loop back for the next number.
+ *
+ * TIP 268.
+ * This is identical the function 'ComparePkgVersion', but using the new
+ * space separator as used by the internal rep of version numbers. The
+ * special separators 'a' and 'b' have already been dealt with in
+ * 'CheckVersionAndConvert', they were translated into numbers as well.
+ * This keeps the comparison sane. Otherwise we would have to compare
+ * numerics, the separators, and also deal with the special case of
+ * end-of-string compared to separators. The semi-list rep we get here is
+ * much easier to handle, as it is still regular.
+ *
+ * Rewritten to not compute a numeric value for the extracted version
+ * number, but do string comparison. Skip any leading zeros for that to
+ * work. This change breaks through the 32bit-limit on version numbers.
*/
thisIsMajor = 1;
+ s1 = v1;
+ s2 = v2;
+
while (1) {
- /* Parse one decimal number from the front of each string. */
+ /*
+ * Parse one decimal number from the front of each string. Skip
+ * leading zeros. Terminate found number for upcoming string-wise
+ * comparison, if needed.
+ */
- n1 = n2 = 0;
- while ((*v1 != 0) && (*v1 != '.')) {
- n1 = 10*n1 + (*v1 - '0');
- v1++;
+ while ((*s1 != 0) && (*s1 == '0')) {
+ s1++;
}
- while ((*v2 != 0) && (*v2 != '.')) {
- n2 = 10*n2 + (*v2 - '0');
- v2++;
+ while ((*s2 != 0) && (*s2 == '0')) {
+ s2++;
}
/*
- * Compare and go on to the next version number if the current numbers
- * match.
+ * s1, s2 now point to the beginnings of the numbers to compare. Test
+ * for their signs first, as shortcut to the result (different signs),
+ * or determines if result has to be flipped (both negative). If there
+ * is no shortcut we have to insert terminators later to limit the
+ * strcmp.
*/
- if (n1 != n2) {
+ if ((*s1 == '-') && (*s2 != '-')) {
+ /* s1 < 0, s2 >= 0 => s1 < s2 */
+ res = -1;
break;
}
- if (*v1 != 0) {
- v1++;
- } else if (*v2 == 0) {
+ if ((*s1 != '-') && (*s2 == '-')) {
+ /* s1 >= 0, s2 < 0 => s1 > s2 */
+ res = 1;
break;
}
- if (*v2 != 0) {
- v2++;
+
+ if ((*s1 == '-') && (*s2 == '-')) {
+ /* a < b => -a > -b, etc. */
+ s1++;
+ s2++;
+ flip = 1;
+ } else {
+ flip = 0;
}
- thisIsMajor = 0;
- }
- if (satPtr != NULL) {
- *satPtr = (n1 == n2) || ((n1 > n2) && !thisIsMajor);
- }
- if (n1 > n2) {
- return 1;
- } else if (n1 == n2) {
- return 0;
- } else {
- return -1;
- }
-}
-#else
-static int
-CompareVersions(v1, v2, isMajorPtr)
- CONST char *v1; /* Versions strings, of form 2.1.3 (any number */
- CONST char *v2; /* of version numbers). */
- int *isMajorPtr; /* If non-null, the word pointed to is filled
- * in with a 0/1 value. 1 means that the difference
- * occured in the first element. */
-{
- int thisIsMajor, n1, n2;
- int res, flip;
- /*
- * Each iteration of the following loop processes one number from each
- * string, terminated by a " " (space). If those numbers don't match then
- * the comparison is over; otherwise, we loop back for the next number.
- *
- * TIP 268.
- * This is identical the function 'ComparePkgVersion', but using the new
- * space separator as used by the internal rep of version numbers. The
- * special separators 'a' and 'b' have already been dealt with in
- * 'CheckVersionAndConvert', they were translated into numbers as
- * well. This keeps the comparison sane. Otherwise we would have to
- * compare numerics, the separators, and also deal with the special case
- * of end-of-string compared to separators. The semi-list rep we get here
- * is much easier to handle, as it is still regular.
- */
+ /*
+ * The string comparison is needed, so now we determine where the
+ * numbers end.
+ */
- thisIsMajor = 1;
- while (1) {
- /* Parse one decimal number from the front of each string. */
-
- n1 = n2 = 0;
- flip = 0;
- while ((*v1 != 0) && (*v1 != ' ')) {
- if (*v1 == '-') {flip = 1 ; v1++ ; continue;}
- n1 = 10*n1 + (*v1 - '0');
- v1++;
+ e1 = s1;
+ while ((*e1 != 0) && (*e1 != ' ')) {
+ e1++;
+ }
+ e2 = s2;
+ while ((*e2 != 0) && (*e2 != ' ')) {
+ e2++;
}
- if (flip) n1 = -n1;
- flip = 0;
- while ((*v2 != 0) && (*v2 != ' ')) {
- if (*v2 == '-') {flip = 1; v2++ ; continue;}
- n2 = 10*n2 + (*v2 - '0');
- v2++;
+
+ /*
+ * s1 .. e1 and s2 .. e2 now bracket the numbers to compare. Insert
+ * terminators, compare, and restore actual contents. First however
+ * another shortcut. Compare lengths. Shorter string is smaller
+ * number! Thus we strcmp only strings of identical length.
+ */
+
+ if ((e1-s1) < (e2-s2)) {
+ res = -1;
+ } else if ((e2-s2) < (e1-s1)) {
+ res = 1;
+ } else {
+ o1 = *e1;
+ *e1 = '\0';
+ o2 = *e2;
+ *e2 = '\0';
+
+ res = strcmp(s1, s2);
+ res = (res < 0) ? -1 : (res ? 1 : 0);
+
+ *e1 = o1;
+ *e2 = o2;
}
- if (flip) n2 = -n2;
/*
- * Compare and go on to the next version number if the current numbers
- * match.
+ * Stop comparing segments when a difference has been found. Here we
+ * may have to flip the result to account for signs.
*/
- if (n1 != n2) {
+ if (res != 0) {
+ if (flip) {
+ res = -res;
+ }
break;
}
- if (*v1 != 0) {
- v1++;
- } else if (*v2 == 0) {
+
+ /*
+ * Go on to the next version number if the current numbers match.
+ * However stop processing if the end of both numbers has been
+ * reached.
+ */
+
+ s1 = e1;
+ s2 = e2;
+
+ if (*s1 != 0) {
+ s1++;
+ } else if (*s2 == 0) {
+ /*
+ * s1, s2 both at the end => identical
+ */
+
+ res = 0;
break;
}
- if (*v2 != 0) {
- v2++;
+ if (*s2 != 0) {
+ s2++;
}
thisIsMajor = 0;
}
- if (n1 > n2) {
- res = 1;
- } else if (n1 == n2) {
- res = 0;
- } else {
- res = -1;
- }
if (isMajorPtr != NULL) {
*isMajorPtr = thisIsMajor;
@@ -1775,13 +1512,12 @@ CompareVersions(v1, v2, isMajorPtr)
*
* CheckAllRequirements --
*
- * This function checks to see whether all requirements in a set
- * have valid syntax.
+ * This function checks to see whether all requirements in a set have
+ * valid syntax.
*
* Results:
- * TCL_OK is returned if all requirements are valid.
- * Otherwise TCL_ERROR is returned and an error message
- * is left in the interp's result.
+ * TCL_OK is returned if all requirements are valid. Otherwise TCL_ERROR
+ * is returned and an error message is left in the interp's result.
*
* Side effects:
* May modify the interpreter result.
@@ -1790,14 +1526,15 @@ CompareVersions(v1, v2, isMajorPtr)
*/
static int
-CheckAllRequirements(interp, reqc, reqv)
- Tcl_Interp* interp;
- int reqc; /* Requirements to check. */
- Tcl_Obj *CONST reqv[];
+CheckAllRequirements(
+ Tcl_Interp *interp,
+ int reqc, /* Requirements to check. */
+ Tcl_Obj *const reqv[])
{
int i;
+
for (i = 0; i < reqc; i++) {
- if ((CheckRequirement(interp, Tcl_GetString(reqv[i])) != TCL_OK)) {
+ if ((CheckRequirement(interp, TclGetString(reqv[i])) != TCL_OK)) {
return TCL_ERROR;
}
}
@@ -1823,43 +1560,52 @@ CheckAllRequirements(interp, reqc, reqv)
*/
static int
-CheckRequirement(interp, string)
- Tcl_Interp *interp; /* Used for error reporting. */
- CONST char *string; /* Supposedly a requirement. */
+CheckRequirement(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ const char *string) /* Supposedly a requirement. */
{
- /* Syntax of requirement = version
- * = version-version
- * = version-
+ /*
+ * Syntax of requirement = version
+ * = version-version
+ * = version-
*/
- char* dash = NULL;
- char* buf;
+ char *dash = NULL, *buf;
- dash = strchr (string, '-');
+ dash = strchr(string, '-');
if (dash == NULL) {
- /* no dash found, has to be a simple version */
- return CheckVersionAndConvert (interp, string, NULL, NULL);
+ /*
+ * No dash found, has to be a simple version.
+ */
+
+ return CheckVersionAndConvert(interp, string, NULL, NULL);
}
- if (strchr (dash+1, '-') != NULL) {
- /* More dashes found after the first. This is wrong. */
+
+ if (strchr(dash+1, '-') != NULL) {
+ /*
+ * More dashes found after the first. This is wrong.
+ */
+
Tcl_AppendResult(interp, "expected versionMin-versionMax but got \"",
string, "\"", NULL);
return TCL_ERROR;
}
- /* Exactly one dash is present. Copy the string, split at the location of
+ /*
+ * Exactly one dash is present. Copy the string, split at the location of
* dash and check that both parts are versions. Note that the max part can
- * be empty.
+ * be empty. Also note that the string allocated with strdup() must be
+ * freed with free() and not ckfree().
*/
DupString(buf, string);
- dash = buf + (dash - string);
- *dash = '\0'; /* buf now <=> min part */
- dash ++; /* dash now <=> max part */
+ dash = buf + (dash - string);
+ *dash = '\0'; /* buf now <=> min part */
+ dash++; /* dash now <=> max part */
- if ((CheckVersionAndConvert(interp, buf, NULL, NULL) != TCL_OK)
- || ((*dash != '\0')
- && (CheckVersionAndConvert(interp, dash, NULL, NULL) != TCL_OK))) {
+ if ((CheckVersionAndConvert(interp, buf, NULL, NULL) != TCL_OK) ||
+ ((*dash != '\0') &&
+ (CheckVersionAndConvert(interp, dash, NULL, NULL) != TCL_OK))) {
ckfree(buf);
return TCL_ERROR;
}
@@ -1885,20 +1631,23 @@ CheckRequirement(interp, string)
*/
static void
-AddRequirementsToResult(interp, reqc, reqv)
- Tcl_Interp* interp;
- int reqc; /* Requirements constraining the desired version. */
- Tcl_Obj *CONST reqv[]; /* 0 means use the latest version available. */
+AddRequirementsToResult(
+ Tcl_Interp *interp,
+ int reqc, /* Requirements constraining the desired
+ * version. */
+ Tcl_Obj *const reqv[]) /* 0 means to use the latest version
+ * available. */
{
if (reqc > 0) {
int i;
+
for (i = 0; i < reqc; i++) {
int length;
char *v = Tcl_GetStringFromObj(reqv[i], &length);
if ((length & 0x1) && (v[length/2] == '-')
&& (strncmp(v, v+((length+1)/2), length/2) == 0)) {
- Tcl_AppendResult(interp, " ", v+((length+1)/2), NULL);
+ Tcl_AppendResult(interp, " exactly ", v+((length+1)/2), NULL);
} else {
Tcl_AppendResult(interp, " ", v, NULL);
}
@@ -1923,19 +1672,22 @@ AddRequirementsToResult(interp, reqc, reqv)
*/
static void
-AddRequirementsToDString(dstring, reqc, reqv)
- Tcl_DString* dstring;
- int reqc; /* Requirements constraining the desired version. */
- Tcl_Obj *CONST reqv[]; /* 0 means use the latest version available. */
+AddRequirementsToDString(
+ Tcl_DString *dsPtr,
+ int reqc, /* Requirements constraining the desired
+ * version. */
+ Tcl_Obj *const reqv[]) /* 0 means to use the latest version
+ * available. */
{
if (reqc > 0) {
int i;
+
for (i = 0; i < reqc; i++) {
- Tcl_DStringAppend(dstring, " ", 1);
- Tcl_DStringAppend(dstring, TclGetString(reqv[i]), -1);
+ Tcl_DStringAppend(dsPtr, " ", 1);
+ Tcl_DStringAppend(dsPtr, TclGetString(reqv[i]), -1);
}
} else {
- Tcl_DStringAppend(dstring, " 0-", -1);
+ Tcl_DStringAppend(dsPtr, " 0-", -1);
}
}
@@ -1944,14 +1696,13 @@ AddRequirementsToDString(dstring, reqc, reqv)
*
* SomeRequirementSatisfied --
*
- * This function checks to see whether a version satisfies at
- * least one of a set of requirements.
+ * This function checks to see whether a version satisfies at least one
+ * of a set of requirements.
*
* Results:
- * If the requirements are satisfied 1 is returned.
- * Otherwise 0 is returned. The function assumes
- * that all pieces have valid syntax. And is allowed
- * to make that assumption.
+ * If the requirements are satisfied 1 is returned. Otherwise 0 is
+ * returned. The function assumes that all pieces have valid syntax. And
+ * is allowed to make that assumption.
*
* Side effects:
* None.
@@ -1960,17 +1711,18 @@ AddRequirementsToDString(dstring, reqc, reqv)
*/
static int
-SomeRequirementSatisfied(availVersionI, reqc, reqv)
- char *availVersionI; /* Candidate version to check against the
+SomeRequirementSatisfied(
+ char *availVersionI, /* Candidate version to check against the
* requirements. */
- int reqc; /* Requirements constraining the desired
+ int reqc, /* Requirements constraining the desired
* version. */
- Tcl_Obj *CONST reqv[]; /* 0 means use the latest version available. */
+ Tcl_Obj *const reqv[]) /* 0 means to use the latest version
+ * available. */
{
int i;
for (i = 0; i < reqc; i++) {
- if (RequirementSatisfied(availVersionI, Tcl_GetString(reqv[i]))) {
+ if (RequirementSatisfied(availVersionI, TclGetString(reqv[i]))) {
return 1;
}
}
@@ -1985,10 +1737,9 @@ SomeRequirementSatisfied(availVersionI, reqc, reqv)
* This function checks to see whether a version satisfies a requirement.
*
* Results:
- * If the requirement is satisfied 1 is returned.
- * Otherwise 0 is returned. The function assumes
- * that all pieces have valid syntax. And is allowed
- * to make that assumption.
+ * If the requirement is satisfied 1 is returned. Otherwise 0 is
+ * returned. The function assumes that all pieces have valid syntax, and
+ * is allowed to make that assumption.
*
* Side effects:
* None.
@@ -1997,75 +1748,80 @@ SomeRequirementSatisfied(availVersionI, reqc, reqv)
*/
static int
-RequirementSatisfied(havei, req)
- char *havei; /* Version string, of candidate package we have */
- CONST char *req; /* Requirement string the candidate has to satisfy */
+RequirementSatisfied(
+ char *havei, /* Version string, of candidate package we
+ * have. */
+ const char *req) /* Requirement string the candidate has to
+ * satisfy. */
{
- /* The have candidate is already in internal rep. */
+ /*
+ * The have candidate is already in internal rep.
+ */
int satisfied, res;
- char* dash = NULL;
- char* buf, *min, *max;
+ char *dash = NULL, *buf, *min, *max;
- dash = strchr (req, '-');
+ dash = strchr(req, '-');
if (dash == NULL) {
- /* No dash found, is a simple version, fallback to regular check.
- * The 'CheckVersionAndConvert' cannot fail. We pad the requirement with
+ /*
+ * No dash found, is a simple version, fallback to regular check. The
+ * 'CheckVersionAndConvert' cannot fail. We pad the requirement with
* 'a0', i.e '-2' before doing the comparison to properly accept
* unstables as well.
*/
- char* reqi = NULL;
+ char *reqi = NULL;
int thisIsMajor;
- CheckVersionAndConvert (NULL, req, &reqi, NULL);
- strcat (reqi, " -2");
+ CheckVersionAndConvert(NULL, req, &reqi, NULL);
+ strcat(reqi, " -2");
res = CompareVersions(havei, reqi, &thisIsMajor);
satisfied = (res == 0) || ((res == 1) && !thisIsMajor);
ckfree(reqi);
return satisfied;
}
- /* Exactly one dash is present (Assumption of valid syntax). Copy the req,
- * split at the location of dash and check that both parts are
- * versions. Note that the max part can be empty.
+ /*
+ * Exactly one dash is present (Assumption of valid syntax). Copy the req,
+ * split at the location of dash and check that both parts are versions.
+ * Note that the max part can be empty.
*/
DupString(buf, req);
- dash = buf + (dash - req);
- *dash = '\0'; /* buf now <=> min part */
- dash ++; /* dash now <=> max part */
+ dash = buf + (dash - req);
+ *dash = '\0'; /* buf now <=> min part */
+ dash++; /* dash now <=> max part */
if (*dash == '\0') {
- /* We have a min, but no max. For the comparison we generate the
+ /*
+ * We have a min, but no max. For the comparison we generate the
* internal rep, padded with 'a0' i.e. '-2'.
*/
- /* No max part, unbound */
-
- CheckVersionAndConvert (NULL, buf, &min, NULL);
- strcat (min, " -2");
+ CheckVersionAndConvert(NULL, buf, &min, NULL);
+ strcat(min, " -2");
satisfied = (CompareVersions(havei, min, NULL) >= 0);
ckfree(min);
ckfree(buf);
return satisfied;
}
- /* We have both min and max, and generate their internal reps.
- * When identical we compare as is, otherwise we pad with 'a0'
- * to ove the range a bit.
+ /*
+ * We have both min and max, and generate their internal reps. When
+ * identical we compare as is, otherwise we pad with 'a0' to ove the range
+ * a bit.
*/
- CheckVersionAndConvert (NULL, buf, &min, NULL);
- CheckVersionAndConvert (NULL, dash, &max, NULL);
+ CheckVersionAndConvert(NULL, buf, &min, NULL);
+ CheckVersionAndConvert(NULL, dash, &max, NULL);
if (CompareVersions(min, max, NULL) == 0) {
satisfied = (CompareVersions(min, havei, NULL) == 0);
} else {
- strcat (min, " -2");
- strcat (max, " -2");
+ strcat(min, " -2");
+ strcat(max, " -2");
satisfied = ((CompareVersions(min, havei, NULL) <= 0) &&
- (CompareVersions(havei, max, NULL) < 0));
+ (CompareVersions(havei, max, NULL) < 0));
}
ckfree(min);
@@ -2075,10 +1831,55 @@ RequirementSatisfied(havei, req)
}
/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_PkgInitStubsCheck --
+ *
+ * This is a replacement routine for Tcl_InitStubs() that is called
+ * from code where -DUSE_TCL_STUBS has not been enabled.
+ *
+ * Results:
+ * Returns the version of a conforming stubs table, or NULL, if
+ * the table version doesn't satisfy the requested requirements,
+ * according to historical practice.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+const char *
+Tcl_PkgInitStubsCheck(
+ Tcl_Interp *interp,
+ const char * version,
+ int exact)
+{
+ const char *actualVersion = Tcl_PkgPresent(interp, "Tcl", version, 0);
+
+ if (exact && actualVersion) {
+ const char *p = version;
+ int count = 0;
+
+ while (*p) {
+ count += !isdigit(UCHAR(*p++));
+ }
+ if (count == 1) {
+ if (0 != strncmp(version, actualVersion, strlen(version))) {
+ /* Construct error message */
+ Tcl_PkgPresent(interp, "Tcl", version, 1);
+ return NULL;
+ }
+ } else {
+ return Tcl_PkgPresent(interp, "Tcl", version, 1);
+ }
+ }
+ return actualVersion;
+}
+/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
*/
-#endif
diff --git a/generic/tclPkgConfig.c b/generic/tclPkgConfig.c
new file mode 100644
index 0000000..4eed372
--- /dev/null
+++ b/generic/tclPkgConfig.c
@@ -0,0 +1,135 @@
+/*
+ * tclPkgConfig.c --
+ *
+ * This file contains the configuration information to embed into the tcl
+ * binary library.
+ *
+ * Copyright (c) 2002 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+/* Note, the definitions in this module are influenced by the following C
+ * preprocessor macros:
+ *
+ * OSCMa = shortcut for "old style configuration macro activates"
+ * NSCMdt = shortcut for "new style configuration macro declares that"
+ *
+ * - TCL_THREADS OSCMa compilation as threaded core.
+ * - TCL_MEM_DEBUG OSCMa memory debugging.
+ * - TCL_COMPILE_DEBUG OSCMa debugging of bytecode compiler.
+ * - TCL_COMPILE_STATS OSCMa bytecode compiler statistics.
+ *
+ * - TCL_CFG_DO64BIT NSCMdt tcl is compiled for a 64bit system.
+ * - TCL_CFG_DEBUG NSCMdt tcl is compiled with symbol info on.
+ * - TCL_CFG_OPTIMIZED NSCMdt tcl is compiled with cc optimizations on
+ * - TCL_CFG_PROFILED NSCMdt tcl is compiled with profiling info.
+ *
+ * - CFG_RUNTIME_* Paths to various stuff at runtime.
+ * - CFG_INSTALL_* Paths to various stuff at installation time.
+ *
+ * - TCL_CFGVAL_ENCODING string containing the encoding used for the
+ * configuration values.
+ */
+
+#include "tclInt.h"
+
+/*
+ * Use C preprocessor statements to define the various values for the embedded
+ * configuration information.
+ */
+
+#ifdef TCL_THREADS
+# define CFG_THREADED "1"
+#else
+# define CFG_THREADED "0"
+#endif
+
+#ifdef TCL_MEM_DEBUG
+# define CFG_MEMDEBUG "1"
+#else
+# define CFG_MEMDEBUG "0"
+#endif
+
+#ifdef TCL_COMPILE_DEBUG
+# define CFG_COMPILE_DEBUG "1"
+#else
+# define CFG_COMPILE_DEBUG "0"
+#endif
+
+#ifdef TCL_COMPILE_STATS
+# define CFG_COMPILE_STATS "1"
+#else
+# define CFG_COMPILE_STATS "0"
+#endif
+
+#ifdef TCL_CFG_DO64BIT
+# define CFG_64 "1"
+#else
+# define CFG_64 "0"
+#endif
+
+#ifdef TCL_CFG_DEBUG
+# define CFG_DEBUG "1"
+#else
+# define CFG_DEBUG "0"
+#endif
+
+#ifdef TCL_CFG_OPTIMIZED
+# define CFG_OPTIMIZED "1"
+#else
+# define CFG_OPTIMIZED "0"
+#endif
+
+#ifdef TCL_CFG_PROFILED
+# define CFG_PROFILED "1"
+#else
+# define CFG_PROFILED "0"
+#endif
+
+static Tcl_Config cfg[] = {
+ {"debug", CFG_DEBUG},
+ {"threaded", CFG_THREADED},
+ {"profiled", CFG_PROFILED},
+ {"64bit", CFG_64},
+ {"optimized", CFG_OPTIMIZED},
+ {"mem_debug", CFG_MEMDEBUG},
+ {"compile_debug", CFG_COMPILE_DEBUG},
+ {"compile_stats", CFG_COMPILE_STATS},
+
+ /* Runtime paths to various stuff */
+
+ {"libdir,runtime", CFG_RUNTIME_LIBDIR},
+ {"bindir,runtime", CFG_RUNTIME_BINDIR},
+ {"scriptdir,runtime", CFG_RUNTIME_SCRDIR},
+ {"includedir,runtime", CFG_RUNTIME_INCDIR},
+ {"docdir,runtime", CFG_RUNTIME_DOCDIR},
+
+ /* Installation paths to various stuff */
+
+ {"libdir,install", CFG_INSTALL_LIBDIR},
+ {"bindir,install", CFG_INSTALL_BINDIR},
+ {"scriptdir,install", CFG_INSTALL_SCRDIR},
+ {"includedir,install", CFG_INSTALL_INCDIR},
+ {"docdir,install", CFG_INSTALL_DOCDIR},
+
+ /* Last entry, closes the array */
+ {NULL, NULL}
+};
+
+void
+TclInitEmbeddedConfigurationInformation(
+ Tcl_Interp* interp) /* Interpreter the configuration command is
+ * registered in. */
+{
+ Tcl_RegisterConfig(interp, "tcl", cfg, TCL_CFGVAL_ENCODING);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclPlatDecls.h b/generic/tclPlatDecls.h
index c6fad72..ccb8c8f 100644
--- a/generic/tclPlatDecls.h
+++ b/generic/tclPlatDecls.h
@@ -10,20 +10,29 @@
#ifndef _TCLPLATDECLS
#define _TCLPLATDECLS
+#undef TCL_STORAGE_CLASS
+#ifdef BUILD_tcl
+# define TCL_STORAGE_CLASS DLLEXPORT
+#else
+# ifdef USE_TCL_STUBS
+# define TCL_STORAGE_CLASS
+# else
+# define TCL_STORAGE_CLASS DLLIMPORT
+# endif
+#endif
+
/*
* Pull in the typedef of TCHAR for windows.
*/
-#if defined(__CYGWIN__)
- typedef char TCHAR;
-#elif defined(__WIN32__) && !defined(_TCHAR_DEFINED)
+#if defined(__WIN32__) && !defined(_TCHAR_DEFINED)
# include <tchar.h>
# ifndef _TCHAR_DEFINED
/* Borland seems to forget to set this. */
- typedef _TCHAR TCHAR;
+ typedef _TCHAR TCHAR;
# define _TCHAR_DEFINED
# endif
# if defined(_MSC_VER) && defined(__STDC__)
- /* MSVC++ misses this. */
+ /* VS2005 SP1 misses this. See [Bug #3110161] */
typedef _TCHAR TCHAR;
# endif
#endif
@@ -34,83 +43,51 @@
* Exported function declarations:
*/
-#ifdef __WIN32__
-/* 0 */
-EXTERN TCHAR * Tcl_WinUtfToTChar _ANSI_ARGS_((CONST char * str,
- int len, Tcl_DString * dsPtr));
-/* 1 */
-EXTERN char * Tcl_WinTCharToUtf _ANSI_ARGS_((CONST TCHAR * str,
- int len, Tcl_DString * dsPtr));
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
+#ifdef __WIN32__ /* WIN */
+#ifndef Tcl_WinUtfToTChar_TCL_DECLARED
+#define Tcl_WinUtfToTChar_TCL_DECLARED
/* 0 */
-EXTERN void Tcl_MacSetEventProc _ANSI_ARGS_((
- Tcl_MacConvertEventPtr procPtr));
+EXTERN TCHAR * Tcl_WinUtfToTChar(CONST char *str, int len,
+ Tcl_DString *dsPtr);
+#endif
+#ifndef Tcl_WinTCharToUtf_TCL_DECLARED
+#define Tcl_WinTCharToUtf_TCL_DECLARED
/* 1 */
-EXTERN char * Tcl_MacConvertTextResource _ANSI_ARGS_((
- Handle resource));
-/* 2 */
-EXTERN int Tcl_MacEvalResource _ANSI_ARGS_((Tcl_Interp * interp,
- CONST char * resourceName,
- int resourceNumber, CONST char * fileName));
-/* 3 */
-EXTERN Handle Tcl_MacFindResource _ANSI_ARGS_((Tcl_Interp * interp,
- long resourceType, CONST char * resourceName,
- int resourceNumber, CONST char * resFileRef,
- int * releaseIt));
-/* 4 */
-EXTERN int Tcl_GetOSTypeFromObj _ANSI_ARGS_((
- Tcl_Interp * interp, Tcl_Obj * objPtr,
- OSType * osTypePtr));
-/* 5 */
-EXTERN void Tcl_SetOSTypeObj _ANSI_ARGS_((Tcl_Obj * objPtr,
- OSType osType));
-/* 6 */
-EXTERN Tcl_Obj * Tcl_NewOSTypeObj _ANSI_ARGS_((OSType osType));
-/* 7 */
-EXTERN int strncasecmp _ANSI_ARGS_((CONST char * s1,
- CONST char * s2, size_t n));
-/* 8 */
-EXTERN int strcasecmp _ANSI_ARGS_((CONST char * s1,
- CONST char * s2));
-#endif /* MAC_TCL */
-#ifdef MAC_OSX_TCL
+EXTERN char * Tcl_WinTCharToUtf(CONST TCHAR *str, int len,
+ Tcl_DString *dsPtr);
+#endif
+#endif /* WIN */
+#ifdef MAC_OSX_TCL /* MACOSX */
+#ifndef Tcl_MacOSXOpenBundleResources_TCL_DECLARED
+#define Tcl_MacOSXOpenBundleResources_TCL_DECLARED
/* 0 */
-EXTERN int Tcl_MacOSXOpenBundleResources _ANSI_ARGS_((
- Tcl_Interp * interp, CONST char * bundleName,
- int hasResourceFile, int maxPathLen,
- char * libraryPath));
+EXTERN int Tcl_MacOSXOpenBundleResources(Tcl_Interp *interp,
+ CONST char *bundleName, int hasResourceFile,
+ int maxPathLen, char *libraryPath);
+#endif
+#ifndef Tcl_MacOSXOpenVersionedBundleResources_TCL_DECLARED
+#define Tcl_MacOSXOpenVersionedBundleResources_TCL_DECLARED
/* 1 */
-EXTERN int Tcl_MacOSXOpenVersionedBundleResources _ANSI_ARGS_((
- Tcl_Interp * interp, CONST char * bundleName,
- CONST char * bundleVersion,
- int hasResourceFile, int maxPathLen,
- char * libraryPath));
-#endif /* MAC_OSX_TCL */
+EXTERN int Tcl_MacOSXOpenVersionedBundleResources(
+ Tcl_Interp *interp, CONST char *bundleName,
+ CONST char *bundleVersion,
+ int hasResourceFile, int maxPathLen,
+ char *libraryPath);
+#endif
+#endif /* MACOSX */
typedef struct TclPlatStubs {
int magic;
struct TclPlatStubHooks *hooks;
-#ifdef __WIN32__
- TCHAR * (*tcl_WinUtfToTChar) _ANSI_ARGS_((CONST char * str, int len, Tcl_DString * dsPtr)); /* 0 */
- char * (*tcl_WinTCharToUtf) _ANSI_ARGS_((CONST TCHAR * str, int len, Tcl_DString * dsPtr)); /* 1 */
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
- void (*tcl_MacSetEventProc) _ANSI_ARGS_((Tcl_MacConvertEventPtr procPtr)); /* 0 */
- char * (*tcl_MacConvertTextResource) _ANSI_ARGS_((Handle resource)); /* 1 */
- int (*tcl_MacEvalResource) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * resourceName, int resourceNumber, CONST char * fileName)); /* 2 */
- Handle (*tcl_MacFindResource) _ANSI_ARGS_((Tcl_Interp * interp, long resourceType, CONST char * resourceName, int resourceNumber, CONST char * resFileRef, int * releaseIt)); /* 3 */
- int (*tcl_GetOSTypeFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, OSType * osTypePtr)); /* 4 */
- void (*tcl_SetOSTypeObj) _ANSI_ARGS_((Tcl_Obj * objPtr, OSType osType)); /* 5 */
- Tcl_Obj * (*tcl_NewOSTypeObj) _ANSI_ARGS_((OSType osType)); /* 6 */
- int (*strncasecmp) _ANSI_ARGS_((CONST char * s1, CONST char * s2, size_t n)); /* 7 */
- int (*strcasecmp) _ANSI_ARGS_((CONST char * s1, CONST char * s2)); /* 8 */
-#endif /* MAC_TCL */
-#ifdef MAC_OSX_TCL
- int (*tcl_MacOSXOpenBundleResources) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * bundleName, int hasResourceFile, int maxPathLen, char * libraryPath)); /* 0 */
- int (*tcl_MacOSXOpenVersionedBundleResources) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * bundleName, CONST char * bundleVersion, int hasResourceFile, int maxPathLen, char * libraryPath)); /* 1 */
-#endif /* MAC_OSX_TCL */
+#ifdef __WIN32__ /* WIN */
+ TCHAR * (*tcl_WinUtfToTChar) (CONST char *str, int len, Tcl_DString *dsPtr); /* 0 */
+ char * (*tcl_WinTCharToUtf) (CONST TCHAR *str, int len, Tcl_DString *dsPtr); /* 1 */
+#endif /* WIN */
+#ifdef MAC_OSX_TCL /* MACOSX */
+ int (*tcl_MacOSXOpenBundleResources) (Tcl_Interp *interp, CONST char *bundleName, int hasResourceFile, int maxPathLen, char *libraryPath); /* 0 */
+ int (*tcl_MacOSXOpenVersionedBundleResources) (Tcl_Interp *interp, CONST char *bundleName, CONST char *bundleVersion, int hasResourceFile, int maxPathLen, char *libraryPath); /* 1 */
+#endif /* MACOSX */
} TclPlatStubs;
#ifdef __cplusplus
@@ -127,7 +104,7 @@ extern TclPlatStubs *tclPlatStubsPtr;
* Inline function declarations:
*/
-#ifdef __WIN32__
+#ifdef __WIN32__ /* WIN */
#ifndef Tcl_WinUtfToTChar
#define Tcl_WinUtfToTChar \
(tclPlatStubsPtr->tcl_WinUtfToTChar) /* 0 */
@@ -136,46 +113,8 @@ extern TclPlatStubs *tclPlatStubsPtr;
#define Tcl_WinTCharToUtf \
(tclPlatStubsPtr->tcl_WinTCharToUtf) /* 1 */
#endif
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
-#ifndef Tcl_MacSetEventProc
-#define Tcl_MacSetEventProc \
- (tclPlatStubsPtr->tcl_MacSetEventProc) /* 0 */
-#endif
-#ifndef Tcl_MacConvertTextResource
-#define Tcl_MacConvertTextResource \
- (tclPlatStubsPtr->tcl_MacConvertTextResource) /* 1 */
-#endif
-#ifndef Tcl_MacEvalResource
-#define Tcl_MacEvalResource \
- (tclPlatStubsPtr->tcl_MacEvalResource) /* 2 */
-#endif
-#ifndef Tcl_MacFindResource
-#define Tcl_MacFindResource \
- (tclPlatStubsPtr->tcl_MacFindResource) /* 3 */
-#endif
-#ifndef Tcl_GetOSTypeFromObj
-#define Tcl_GetOSTypeFromObj \
- (tclPlatStubsPtr->tcl_GetOSTypeFromObj) /* 4 */
-#endif
-#ifndef Tcl_SetOSTypeObj
-#define Tcl_SetOSTypeObj \
- (tclPlatStubsPtr->tcl_SetOSTypeObj) /* 5 */
-#endif
-#ifndef Tcl_NewOSTypeObj
-#define Tcl_NewOSTypeObj \
- (tclPlatStubsPtr->tcl_NewOSTypeObj) /* 6 */
-#endif
-#ifndef strncasecmp
-#define strncasecmp \
- (tclPlatStubsPtr->strncasecmp) /* 7 */
-#endif
-#ifndef strcasecmp
-#define strcasecmp \
- (tclPlatStubsPtr->strcasecmp) /* 8 */
-#endif
-#endif /* MAC_TCL */
-#ifdef MAC_OSX_TCL
+#endif /* WIN */
+#ifdef MAC_OSX_TCL /* MACOSX */
#ifndef Tcl_MacOSXOpenBundleResources
#define Tcl_MacOSXOpenBundleResources \
(tclPlatStubsPtr->tcl_MacOSXOpenBundleResources) /* 0 */
@@ -184,12 +123,15 @@ extern TclPlatStubs *tclPlatStubsPtr;
#define Tcl_MacOSXOpenVersionedBundleResources \
(tclPlatStubsPtr->tcl_MacOSXOpenVersionedBundleResources) /* 1 */
#endif
-#endif /* MAC_OSX_TCL */
+#endif /* MACOSX */
#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */
/* !END!: Do not edit above this line. */
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLIMPORT
+
#endif /* _TCLPLATDECLS */
diff --git a/generic/tclPort.h b/generic/tclPort.h
index f4fb831..23c6191 100644
--- a/generic/tclPort.h
+++ b/generic/tclPort.h
@@ -14,16 +14,25 @@
#ifndef _TCLPORT
#define _TCLPORT
+#ifdef HAVE_TCL_CONFIG_H
+#include "tclConfig.h"
+#endif
+#if defined(_WIN32)
+# include "tclWinPort.h"
+#endif
#include "tcl.h"
+#if !defined(_WIN32)
+# include "tclUnixPort.h"
+#endif
-#if defined(__WIN32__)
-# include "tclWinPort.h"
-#else
-# if defined(MAC_TCL)
-# include "tclMacPort.h"
-# else
-# include "tclUnixPort.h"
-# endif
+#if defined(__CYGWIN__)
+# define USE_PUTENV 1
+# define USE_PUTENV_FOR_UNSET 1
+/* On Cygwin, the environment is imported from the Cygwin DLL. */
+ DLLIMPORT extern char **__cygwin_environ;
+ DLLIMPORT extern int cygwin_conv_to_win32_path(const char *, char *);
+# define environ __cygwin_environ
+# define timezone _timezone
#endif
#if !defined(LLONG_MIN)
diff --git a/generic/tclPosixStr.c b/generic/tclPosixStr.c
index 258996f..a11b532 100644
--- a/generic/tclPosixStr.c
+++ b/generic/tclPosixStr.c
@@ -1,9 +1,8 @@
-/*
+/*
* tclPosixStr.c --
*
- * This file contains procedures that generate strings
- * corresponding to various POSIX-related codes, such
- * as errno and signals.
+ * This file contains procedures that generate strings corresponding to
+ * various POSIX-related codes, such as errno and signals.
*
* Copyright (c) 1991-1994 The Regents of the University of California.
* Copyright (c) 1994-1996 Sun Microsystems, Inc.
@@ -13,7 +12,6 @@
*/
#include "tclInt.h"
-#include "tclPort.h"
/*
*----------------------------------------------------------------------
@@ -23,9 +21,9 @@
* Return a textual identifier for the current errno value.
*
* Results:
- * This procedure returns a machine-readable textual identifier
- * that corresponds to the current errno value (e.g. "EPERM").
- * The identifier is the same as the #define name in errno.h.
+ * This procedure returns a machine-readable textual identifier that
+ * corresponds to the current errno value (e.g. "EPERM"). The identifier
+ * is the same as the #define name in errno.h.
*
* Side effects:
* None.
@@ -34,425 +32,425 @@
*/
CONST char *
-Tcl_ErrnoId()
+Tcl_ErrnoId(void)
{
switch (errno) {
#if defined(E2BIG) && (!defined(EOVERFLOW) || (E2BIG != EOVERFLOW))
- case E2BIG: return "E2BIG";
+ case E2BIG: return "E2BIG";
#endif
#ifdef EACCES
- case EACCES: return "EACCES";
+ case EACCES: return "EACCES";
#endif
#ifdef EADDRINUSE
- case EADDRINUSE: return "EADDRINUSE";
+ case EADDRINUSE: return "EADDRINUSE";
#endif
#ifdef EADDRNOTAVAIL
- case EADDRNOTAVAIL: return "EADDRNOTAVAIL";
+ case EADDRNOTAVAIL: return "EADDRNOTAVAIL";
#endif
#ifdef EADV
- case EADV: return "EADV";
+ case EADV: return "EADV";
#endif
#ifdef EAFNOSUPPORT
- case EAFNOSUPPORT: return "EAFNOSUPPORT";
+ case EAFNOSUPPORT: return "EAFNOSUPPORT";
#endif
#ifdef EAGAIN
- case EAGAIN: return "EAGAIN";
+ case EAGAIN: return "EAGAIN";
#endif
#ifdef EALIGN
- case EALIGN: return "EALIGN";
+ case EALIGN: return "EALIGN";
#endif
#if defined(EALREADY) && (!defined(EBUSY) || (EALREADY != EBUSY))
- case EALREADY: return "EALREADY";
+ case EALREADY: return "EALREADY";
#endif
#ifdef EBADE
- case EBADE: return "EBADE";
+ case EBADE: return "EBADE";
#endif
#ifdef EBADF
- case EBADF: return "EBADF";
+ case EBADF: return "EBADF";
#endif
#ifdef EBADFD
- case EBADFD: return "EBADFD";
+ case EBADFD: return "EBADFD";
#endif
#ifdef EBADMSG
- case EBADMSG: return "EBADMSG";
+ case EBADMSG: return "EBADMSG";
#endif
#ifdef EBADR
- case EBADR: return "EBADR";
+ case EBADR: return "EBADR";
#endif
#ifdef EBADRPC
- case EBADRPC: return "EBADRPC";
+ case EBADRPC: return "EBADRPC";
#endif
#ifdef EBADRQC
- case EBADRQC: return "EBADRQC";
+ case EBADRQC: return "EBADRQC";
#endif
#ifdef EBADSLT
- case EBADSLT: return "EBADSLT";
+ case EBADSLT: return "EBADSLT";
#endif
#ifdef EBFONT
- case EBFONT: return "EBFONT";
+ case EBFONT: return "EBFONT";
#endif
#ifdef EBUSY
- case EBUSY: return "EBUSY";
+ case EBUSY: return "EBUSY";
#endif
#ifdef ECHILD
- case ECHILD: return "ECHILD";
+ case ECHILD: return "ECHILD";
#endif
#ifdef ECHRNG
- case ECHRNG: return "ECHRNG";
+ case ECHRNG: return "ECHRNG";
#endif
#ifdef ECOMM
- case ECOMM: return "ECOMM";
+ case ECOMM: return "ECOMM";
#endif
#ifdef ECONNABORTED
- case ECONNABORTED: return "ECONNABORTED";
+ case ECONNABORTED: return "ECONNABORTED";
#endif
#ifdef ECONNREFUSED
- case ECONNREFUSED: return "ECONNREFUSED";
+ case ECONNREFUSED: return "ECONNREFUSED";
#endif
#ifdef ECONNRESET
- case ECONNRESET: return "ECONNRESET";
+ case ECONNRESET: return "ECONNRESET";
#endif
#if defined(EDEADLK) && (!defined(EWOULDBLOCK) || (EDEADLK != EWOULDBLOCK))
- case EDEADLK: return "EDEADLK";
+ case EDEADLK: return "EDEADLK";
#endif
#if defined(EDEADLOCK) && (!defined(EDEADLK) || (EDEADLOCK != EDEADLK))
- case EDEADLOCK: return "EDEADLOCK";
+ case EDEADLOCK: return "EDEADLOCK";
#endif
#ifdef EDESTADDRREQ
- case EDESTADDRREQ: return "EDESTADDRREQ";
+ case EDESTADDRREQ: return "EDESTADDRREQ";
#endif
#ifdef EDIRTY
- case EDIRTY: return "EDIRTY";
+ case EDIRTY: return "EDIRTY";
#endif
#ifdef EDOM
- case EDOM: return "EDOM";
+ case EDOM: return "EDOM";
#endif
#ifdef EDOTDOT
- case EDOTDOT: return "EDOTDOT";
+ case EDOTDOT: return "EDOTDOT";
#endif
#ifdef EDQUOT
- case EDQUOT: return "EDQUOT";
+ case EDQUOT: return "EDQUOT";
#endif
#ifdef EDUPPKG
- case EDUPPKG: return "EDUPPKG";
+ case EDUPPKG: return "EDUPPKG";
#endif
#ifdef EEXIST
- case EEXIST: return "EEXIST";
+ case EEXIST: return "EEXIST";
#endif
#ifdef EFAULT
- case EFAULT: return "EFAULT";
+ case EFAULT: return "EFAULT";
#endif
#ifdef EFBIG
- case EFBIG: return "EFBIG";
+ case EFBIG: return "EFBIG";
#endif
#ifdef EHOSTDOWN
- case EHOSTDOWN: return "EHOSTDOWN";
+ case EHOSTDOWN: return "EHOSTDOWN";
#endif
#ifdef EHOSTUNREACH
- case EHOSTUNREACH: return "EHOSTUNREACH";
+ case EHOSTUNREACH: return "EHOSTUNREACH";
#endif
#if defined(EIDRM) && (!defined(EINPROGRESS) || (EIDRM != EINPROGRESS))
- case EIDRM: return "EIDRM";
+ case EIDRM: return "EIDRM";
#endif
#ifdef EINIT
- case EINIT: return "EINIT";
+ case EINIT: return "EINIT";
#endif
#ifdef EINPROGRESS
- case EINPROGRESS: return "EINPROGRESS";
+ case EINPROGRESS: return "EINPROGRESS";
#endif
#ifdef EINTR
- case EINTR: return "EINTR";
+ case EINTR: return "EINTR";
#endif
#ifdef EINVAL
- case EINVAL: return "EINVAL";
+ case EINVAL: return "EINVAL";
#endif
#ifdef EIO
- case EIO: return "EIO";
+ case EIO: return "EIO";
#endif
#ifdef EISCONN
- case EISCONN: return "EISCONN";
+ case EISCONN: return "EISCONN";
#endif
#ifdef EISDIR
- case EISDIR: return "EISDIR";
+ case EISDIR: return "EISDIR";
#endif
#ifdef EISNAME
- case EISNAM: return "EISNAM";
+ case EISNAM: return "EISNAM";
#endif
#ifdef ELBIN
- case ELBIN: return "ELBIN";
+ case ELBIN: return "ELBIN";
#endif
#ifdef EL2HLT
- case EL2HLT: return "EL2HLT";
+ case EL2HLT: return "EL2HLT";
#endif
#ifdef EL2NSYNC
- case EL2NSYNC: return "EL2NSYNC";
+ case EL2NSYNC: return "EL2NSYNC";
#endif
#ifdef EL3HLT
- case EL3HLT: return "EL3HLT";
+ case EL3HLT: return "EL3HLT";
#endif
#ifdef EL3RST
- case EL3RST: return "EL3RST";
+ case EL3RST: return "EL3RST";
#endif
#ifdef ELIBACC
- case ELIBACC: return "ELIBACC";
+ case ELIBACC: return "ELIBACC";
#endif
#ifdef ELIBBAD
- case ELIBBAD: return "ELIBBAD";
+ case ELIBBAD: return "ELIBBAD";
#endif
#ifdef ELIBEXEC
- case ELIBEXEC: return "ELIBEXEC";
+ case ELIBEXEC: return "ELIBEXEC";
#endif
#ifdef ELIBMAX
- case ELIBMAX: return "ELIBMAX";
+ case ELIBMAX: return "ELIBMAX";
#endif
#ifdef ELIBSCN
- case ELIBSCN: return "ELIBSCN";
+ case ELIBSCN: return "ELIBSCN";
#endif
#ifdef ELNRNG
- case ELNRNG: return "ELNRNG";
+ case ELNRNG: return "ELNRNG";
#endif
#if defined(ELOOP) && (!defined(ENOENT) || (ELOOP != ENOENT))
- case ELOOP: return "ELOOP";
+ case ELOOP: return "ELOOP";
#endif
#ifdef EMFILE
- case EMFILE: return "EMFILE";
+ case EMFILE: return "EMFILE";
#endif
#ifdef EMLINK
- case EMLINK: return "EMLINK";
+ case EMLINK: return "EMLINK";
#endif
#ifdef EMSGSIZE
- case EMSGSIZE: return "EMSGSIZE";
+ case EMSGSIZE: return "EMSGSIZE";
#endif
#ifdef EMULTIHOP
- case EMULTIHOP: return "EMULTIHOP";
+ case EMULTIHOP: return "EMULTIHOP";
#endif
#ifdef ENAMETOOLONG
- case ENAMETOOLONG: return "ENAMETOOLONG";
+ case ENAMETOOLONG: return "ENAMETOOLONG";
#endif
#ifdef ENAVAIL
- case ENAVAIL: return "ENAVAIL";
+ case ENAVAIL: return "ENAVAIL";
#endif
#ifdef ENET
- case ENET: return "ENET";
+ case ENET: return "ENET";
#endif
#ifdef ENETDOWN
- case ENETDOWN: return "ENETDOWN";
+ case ENETDOWN: return "ENETDOWN";
#endif
#ifdef ENETRESET
- case ENETRESET: return "ENETRESET";
+ case ENETRESET: return "ENETRESET";
#endif
#ifdef ENETUNREACH
- case ENETUNREACH: return "ENETUNREACH";
+ case ENETUNREACH: return "ENETUNREACH";
#endif
#ifdef ENFILE
- case ENFILE: return "ENFILE";
+ case ENFILE: return "ENFILE";
#endif
#ifdef ENOANO
- case ENOANO: return "ENOANO";
+ case ENOANO: return "ENOANO";
#endif
#if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR))
- case ENOBUFS: return "ENOBUFS";
+ case ENOBUFS: return "ENOBUFS";
#endif
#ifdef ENOCSI
- case ENOCSI: return "ENOCSI";
+ case ENOCSI: return "ENOCSI";
#endif
#if defined(ENODATA) && (!defined(ECONNREFUSED) || (ENODATA != ECONNREFUSED))
- case ENODATA: return "ENODATA";
+ case ENODATA: return "ENODATA";
#endif
#ifdef ENODEV
- case ENODEV: return "ENODEV";
+ case ENODEV: return "ENODEV";
#endif
#ifdef ENOENT
- case ENOENT: return "ENOENT";
+ case ENOENT: return "ENOENT";
#endif
#ifdef ENOEXEC
- case ENOEXEC: return "ENOEXEC";
+ case ENOEXEC: return "ENOEXEC";
#endif
#ifdef ENOLCK
- case ENOLCK: return "ENOLCK";
+ case ENOLCK: return "ENOLCK";
#endif
#if defined(ENOLINK) && (!defined(ESOCKTNOSUPPORT) || (ESOCKTNOSUPPORT != ENOLINK))
- case ENOLINK: return "ENOLINK";
+ case ENOLINK: return "ENOLINK";
#endif
#ifdef ENOMEM
- case ENOMEM: return "ENOMEM";
+ case ENOMEM: return "ENOMEM";
#endif
#ifdef ENOMSG
- case ENOMSG: return "ENOMSG";
+ case ENOMSG: return "ENOMSG";
#endif
#ifdef ENONET
- case ENONET: return "ENONET";
+ case ENONET: return "ENONET";
#endif
#ifdef ENOPKG
- case ENOPKG: return "ENOPKG";
+ case ENOPKG: return "ENOPKG";
#endif
#if defined(ENOPROTOOPT) && (!defined(EPFNOSUPPORT) || (EPFNOSUPPORT != ENOPROTOOPT))
- case ENOPROTOOPT: return "ENOPROTOOPT";
+ case ENOPROTOOPT: return "ENOPROTOOPT";
#endif
#ifdef ENOSPC
- case ENOSPC: return "ENOSPC";
+ case ENOSPC: return "ENOSPC";
#endif
#if defined(ENOSR) && (!defined(ENAMETOOLONG) || (ENAMETOOLONG != ENOSR))
- case ENOSR: return "ENOSR";
+ case ENOSR: return "ENOSR";
#endif
#if defined(ENOSTR) && (!defined(ENOTTY) || (ENOTTY != ENOSTR))
- case ENOSTR: return "ENOSTR";
+ case ENOSTR: return "ENOSTR";
#endif
#ifdef ENOSYM
- case ENOSYM: return "ENOSYM";
+ case ENOSYM: return "ENOSYM";
#endif
#ifdef ENOSYS
- case ENOSYS: return "ENOSYS";
+ case ENOSYS: return "ENOSYS";
#endif
#ifdef ENOTBLK
- case ENOTBLK: return "ENOTBLK";
+ case ENOTBLK: return "ENOTBLK";
#endif
#ifdef ENOTCONN
- case ENOTCONN: return "ENOTCONN";
+ case ENOTCONN: return "ENOTCONN";
#endif
#ifdef ENOTDIR
- case ENOTDIR: return "ENOTDIR";
+ case ENOTDIR: return "ENOTDIR";
#endif
#if defined(ENOTEMPTY) && (!defined(EEXIST) || (ENOTEMPTY != EEXIST))
- case ENOTEMPTY: return "ENOTEMPTY";
+ case ENOTEMPTY: return "ENOTEMPTY";
#endif
#ifdef ENOTNAM
- case ENOTNAM: return "ENOTNAM";
+ case ENOTNAM: return "ENOTNAM";
#endif
#ifdef ENOTSOCK
- case ENOTSOCK: return "ENOTSOCK";
+ case ENOTSOCK: return "ENOTSOCK";
#endif
#ifdef ENOTSUP
- case ENOTSUP: return "ENOTSUP";
+ case ENOTSUP: return "ENOTSUP";
#endif
#ifdef ENOTTY
- case ENOTTY: return "ENOTTY";
+ case ENOTTY: return "ENOTTY";
#endif
#ifdef ENOTUNIQ
- case ENOTUNIQ: return "ENOTUNIQ";
+ case ENOTUNIQ: return "ENOTUNIQ";
#endif
#ifdef ENXIO
- case ENXIO: return "ENXIO";
+ case ENXIO: return "ENXIO";
#endif
#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (ENOTSUP != EOPNOTSUPP))
- case EOPNOTSUPP: return "EOPNOTSUPP";
+ case EOPNOTSUPP: return "EOPNOTSUPP";
#endif
#if defined(EOVERFLOW) && (!defined(EFBIG) || (EOVERFLOW != EFBIG)) && (!defined(EINVAL) || (EOVERFLOW != EINVAL))
- case EOVERFLOW: return "EOVERFLOW";
+ case EOVERFLOW: return "EOVERFLOW";
#endif
#ifdef EPERM
- case EPERM: return "EPERM";
+ case EPERM: return "EPERM";
#endif
#if defined(EPFNOSUPPORT) && (!defined(ENOLCK) || (ENOLCK != EPFNOSUPPORT))
- case EPFNOSUPPORT: return "EPFNOSUPPORT";
+ case EPFNOSUPPORT: return "EPFNOSUPPORT";
#endif
#ifdef EPIPE
- case EPIPE: return "EPIPE";
+ case EPIPE: return "EPIPE";
#endif
#ifdef EPROCLIM
- case EPROCLIM: return "EPROCLIM";
+ case EPROCLIM: return "EPROCLIM";
#endif
#ifdef EPROCUNAVAIL
- case EPROCUNAVAIL: return "EPROCUNAVAIL";
+ case EPROCUNAVAIL: return "EPROCUNAVAIL";
#endif
#ifdef EPROGMISMATCH
- case EPROGMISMATCH: return "EPROGMISMATCH";
+ case EPROGMISMATCH: return "EPROGMISMATCH";
#endif
#ifdef EPROGUNAVAIL
- case EPROGUNAVAIL: return "EPROGUNAVAIL";
+ case EPROGUNAVAIL: return "EPROGUNAVAIL";
#endif
#ifdef EPROTO
- case EPROTO: return "EPROTO";
+ case EPROTO: return "EPROTO";
#endif
#ifdef EPROTONOSUPPORT
- case EPROTONOSUPPORT: return "EPROTONOSUPPORT";
+ case EPROTONOSUPPORT: return "EPROTONOSUPPORT";
#endif
#ifdef EPROTOTYPE
- case EPROTOTYPE: return "EPROTOTYPE";
+ case EPROTOTYPE: return "EPROTOTYPE";
#endif
#ifdef ERANGE
- case ERANGE: return "ERANGE";
+ case ERANGE: return "ERANGE";
#endif
#if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED))
- case EREFUSED: return "EREFUSED";
+ case EREFUSED: return "EREFUSED";
#endif
#ifdef EREMCHG
- case EREMCHG: return "EREMCHG";
+ case EREMCHG: return "EREMCHG";
#endif
#ifdef EREMDEV
- case EREMDEV: return "EREMDEV";
+ case EREMDEV: return "EREMDEV";
#endif
#ifdef EREMOTE
- case EREMOTE: return "EREMOTE";
+ case EREMOTE: return "EREMOTE";
#endif
#ifdef EREMOTEIO
- case EREMOTEIO: return "EREMOTEIO";
+ case EREMOTEIO: return "EREMOTEIO";
#endif
#ifdef EREMOTERELEASE
- case EREMOTERELEASE: return "EREMOTERELEASE";
+ case EREMOTERELEASE: return "EREMOTERELEASE";
#endif
#ifdef EROFS
- case EROFS: return "EROFS";
+ case EROFS: return "EROFS";
#endif
#ifdef ERPCMISMATCH
- case ERPCMISMATCH: return "ERPCMISMATCH";
+ case ERPCMISMATCH: return "ERPCMISMATCH";
#endif
#ifdef ERREMOTE
- case ERREMOTE: return "ERREMOTE";
+ case ERREMOTE: return "ERREMOTE";
#endif
#ifdef ESHUTDOWN
- case ESHUTDOWN: return "ESHUTDOWN";
+ case ESHUTDOWN: return "ESHUTDOWN";
#endif
#ifdef ESOCKTNOSUPPORT
- case ESOCKTNOSUPPORT: return "ESOCKTNOSUPPORT";
+ case ESOCKTNOSUPPORT: return "ESOCKTNOSUPPORT";
#endif
#ifdef ESPIPE
- case ESPIPE: return "ESPIPE";
+ case ESPIPE: return "ESPIPE";
#endif
#ifdef ESRCH
- case ESRCH: return "ESRCH";
+ case ESRCH: return "ESRCH";
#endif
#ifdef ESRMNT
- case ESRMNT: return "ESRMNT";
+ case ESRMNT: return "ESRMNT";
#endif
#ifdef ESTALE
- case ESTALE: return "ESTALE";
+ case ESTALE: return "ESTALE";
#endif
#ifdef ESUCCESS
- case ESUCCESS: return "ESUCCESS";
+ case ESUCCESS: return "ESUCCESS";
#endif
#if defined(ETIME) && (!defined(ELOOP) || (ETIME != ELOOP))
- case ETIME: return "ETIME";
+ case ETIME: return "ETIME";
#endif
#if defined(ETIMEDOUT) && (!defined(ENOSTR) || (ETIMEDOUT != ENOSTR))
- case ETIMEDOUT: return "ETIMEDOUT";
+ case ETIMEDOUT: return "ETIMEDOUT";
#endif
#ifdef ETOOMANYREFS
- case ETOOMANYREFS: return "ETOOMANYREFS";
+ case ETOOMANYREFS: return "ETOOMANYREFS";
#endif
#ifdef ETXTBSY
- case ETXTBSY: return "ETXTBSY";
+ case ETXTBSY: return "ETXTBSY";
#endif
#ifdef EUCLEAN
- case EUCLEAN: return "EUCLEAN";
+ case EUCLEAN: return "EUCLEAN";
#endif
#ifdef EUNATCH
- case EUNATCH: return "EUNATCH";
+ case EUNATCH: return "EUNATCH";
#endif
#ifdef EUSERS
- case EUSERS: return "EUSERS";
+ case EUSERS: return "EUSERS";
#endif
#ifdef EVERSION
- case EVERSION: return "EVERSION";
+ case EVERSION: return "EVERSION";
#endif
#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
- case EWOULDBLOCK: return "EWOULDBLOCK";
+ case EWOULDBLOCK: return "EWOULDBLOCK";
#endif
#ifdef EXDEV
- case EXDEV: return "EXDEV";
+ case EXDEV: return "EXDEV";
#endif
#ifdef EXFULL
- case EXFULL: return "EXFULL";
+ case EXFULL: return "EXFULL";
#endif
}
return "unknown error";
@@ -463,17 +461,15 @@ Tcl_ErrnoId()
*
* Tcl_ErrnoMsg --
*
- * Return a human-readable message corresponding to a given
- * errno value.
+ * Return a human-readable message corresponding to a given errno value.
*
* Results:
- * The return value is the standard POSIX error message for
- * errno. This procedure is used instead of strerror because
- * strerror returns slightly different values on different
- * machines (e.g. different capitalizations), which cause
- * problems for things such as regression tests. This procedure
- * provides messages for most standard errors, then it calls
- * strerror for things it doesn't understand.
+ * The return value is the standard POSIX error message for errno. This
+ * procedure is used instead of strerror because strerror returns
+ * slightly different values on different machines (e.g. different
+ * capitalizations), which cause problems for things such as regression
+ * tests. This procedure provides messages for most standard errors, then
+ * it calls strerror for things it doesn't understand.
*
* Side effects:
* None.
@@ -482,433 +478,433 @@ Tcl_ErrnoId()
*/
CONST char *
-Tcl_ErrnoMsg(err)
- int err; /* Error number (such as in errno variable). */
+Tcl_ErrnoMsg(
+ int err) /* Error number (such as in errno variable). */
{
switch (err) {
#if defined(E2BIG) && (!defined(EOVERFLOW) || (E2BIG != EOVERFLOW))
- case E2BIG: return "argument list too long";
+ case E2BIG: return "argument list too long";
#endif
#ifdef EACCES
- case EACCES: return "permission denied";
+ case EACCES: return "permission denied";
#endif
#ifdef EADDRINUSE
- case EADDRINUSE: return "address already in use";
+ case EADDRINUSE: return "address already in use";
#endif
#ifdef EADDRNOTAVAIL
- case EADDRNOTAVAIL: return "can't assign requested address";
+ case EADDRNOTAVAIL: return "can't assign requested address";
#endif
#ifdef EADV
- case EADV: return "advertise error";
+ case EADV: return "advertise error";
#endif
#ifdef EAFNOSUPPORT
- case EAFNOSUPPORT: return "address family not supported by protocol family";
+ case EAFNOSUPPORT: return "address family not supported by protocol family";
#endif
#ifdef EAGAIN
- case EAGAIN: return "resource temporarily unavailable";
+ case EAGAIN: return "resource temporarily unavailable";
#endif
#ifdef EALIGN
- case EALIGN: return "EALIGN";
+ case EALIGN: return "EALIGN";
#endif
#if defined(EALREADY) && (!defined(EBUSY) || (EALREADY != EBUSY))
- case EALREADY: return "operation already in progress";
+ case EALREADY: return "operation already in progress";
#endif
#ifdef EBADE
- case EBADE: return "bad exchange descriptor";
+ case EBADE: return "bad exchange descriptor";
#endif
#ifdef EBADF
- case EBADF: return "bad file number";
+ case EBADF: return "bad file number";
#endif
#ifdef EBADFD
- case EBADFD: return "file descriptor in bad state";
+ case EBADFD: return "file descriptor in bad state";
#endif
#ifdef EBADMSG
- case EBADMSG: return "not a data message";
+ case EBADMSG: return "not a data message";
#endif
#ifdef EBADR
- case EBADR: return "bad request descriptor";
+ case EBADR: return "bad request descriptor";
#endif
#ifdef EBADRPC
- case EBADRPC: return "RPC structure is bad";
+ case EBADRPC: return "RPC structure is bad";
#endif
#ifdef EBADRQC
- case EBADRQC: return "bad request code";
+ case EBADRQC: return "bad request code";
#endif
#ifdef EBADSLT
- case EBADSLT: return "invalid slot";
+ case EBADSLT: return "invalid slot";
#endif
#ifdef EBFONT
- case EBFONT: return "bad font file format";
+ case EBFONT: return "bad font file format";
#endif
#ifdef EBUSY
- case EBUSY: return "file busy";
+ case EBUSY: return "file busy";
#endif
#ifdef ECHILD
- case ECHILD: return "no children";
+ case ECHILD: return "no children";
#endif
#ifdef ECHRNG
- case ECHRNG: return "channel number out of range";
+ case ECHRNG: return "channel number out of range";
#endif
#ifdef ECOMM
- case ECOMM: return "communication error on send";
+ case ECOMM: return "communication error on send";
#endif
#ifdef ECONNABORTED
- case ECONNABORTED: return "software caused connection abort";
+ case ECONNABORTED: return "software caused connection abort";
#endif
#ifdef ECONNREFUSED
- case ECONNREFUSED: return "connection refused";
+ case ECONNREFUSED: return "connection refused";
#endif
#ifdef ECONNRESET
- case ECONNRESET: return "connection reset by peer";
+ case ECONNRESET: return "connection reset by peer";
#endif
#if defined(EDEADLK) && (!defined(EWOULDBLOCK) || (EDEADLK != EWOULDBLOCK))
- case EDEADLK: return "resource deadlock avoided";
+ case EDEADLK: return "resource deadlock avoided";
#endif
#if defined(EDEADLOCK) && (!defined(EDEADLK) || (EDEADLOCK != EDEADLK))
- case EDEADLOCK: return "resource deadlock avoided";
+ case EDEADLOCK: return "resource deadlock avoided";
#endif
#ifdef EDESTADDRREQ
- case EDESTADDRREQ: return "destination address required";
+ case EDESTADDRREQ: return "destination address required";
#endif
#ifdef EDIRTY
- case EDIRTY: return "mounting a dirty fs w/o force";
+ case EDIRTY: return "mounting a dirty fs w/o force";
#endif
#ifdef EDOM
- case EDOM: return "math argument out of range";
+ case EDOM: return "math argument out of range";
#endif
#ifdef EDOTDOT
- case EDOTDOT: return "cross mount point";
+ case EDOTDOT: return "cross mount point";
#endif
#ifdef EDQUOT
- case EDQUOT: return "disk quota exceeded";
+ case EDQUOT: return "disk quota exceeded";
#endif
#ifdef EDUPPKG
- case EDUPPKG: return "duplicate package name";
+ case EDUPPKG: return "duplicate package name";
#endif
#ifdef EEXIST
- case EEXIST: return "file already exists";
+ case EEXIST: return "file already exists";
#endif
#ifdef EFAULT
- case EFAULT: return "bad address in system call argument";
+ case EFAULT: return "bad address in system call argument";
#endif
#ifdef EFBIG
- case EFBIG: return "file too large";
+ case EFBIG: return "file too large";
#endif
#ifdef EHOSTDOWN
- case EHOSTDOWN: return "host is down";
+ case EHOSTDOWN: return "host is down";
#endif
#ifdef EHOSTUNREACH
- case EHOSTUNREACH: return "host is unreachable";
+ case EHOSTUNREACH: return "host is unreachable";
#endif
#if defined(EIDRM) && (!defined(EINPROGRESS) || (EIDRM != EINPROGRESS))
- case EIDRM: return "identifier removed";
+ case EIDRM: return "identifier removed";
#endif
#ifdef EINIT
- case EINIT: return "initialization error";
+ case EINIT: return "initialization error";
#endif
#ifdef EINPROGRESS
- case EINPROGRESS: return "operation now in progress";
+ case EINPROGRESS: return "operation now in progress";
#endif
#ifdef EINTR
- case EINTR: return "interrupted system call";
+ case EINTR: return "interrupted system call";
#endif
#ifdef EINVAL
- case EINVAL: return "invalid argument";
+ case EINVAL: return "invalid argument";
#endif
#ifdef EIO
- case EIO: return "I/O error";
+ case EIO: return "I/O error";
#endif
#ifdef EISCONN
- case EISCONN: return "socket is already connected";
+ case EISCONN: return "socket is already connected";
#endif
#ifdef EISDIR
- case EISDIR: return "illegal operation on a directory";
+ case EISDIR: return "illegal operation on a directory";
#endif
#ifdef EISNAME
- case EISNAM: return "is a name file";
+ case EISNAM: return "is a name file";
#endif
#ifdef ELBIN
- case ELBIN: return "ELBIN";
+ case ELBIN: return "ELBIN";
#endif
#ifdef EL2HLT
- case EL2HLT: return "level 2 halted";
+ case EL2HLT: return "level 2 halted";
#endif
#ifdef EL2NSYNC
- case EL2NSYNC: return "level 2 not synchronized";
+ case EL2NSYNC: return "level 2 not synchronized";
#endif
#ifdef EL3HLT
- case EL3HLT: return "level 3 halted";
+ case EL3HLT: return "level 3 halted";
#endif
#ifdef EL3RST
- case EL3RST: return "level 3 reset";
+ case EL3RST: return "level 3 reset";
#endif
#ifdef ELIBACC
- case ELIBACC: return "can not access a needed shared library";
+ case ELIBACC: return "can not access a needed shared library";
#endif
#ifdef ELIBBAD
- case ELIBBAD: return "accessing a corrupted shared library";
+ case ELIBBAD: return "accessing a corrupted shared library";
#endif
#ifdef ELIBEXEC
- case ELIBEXEC: return "can not exec a shared library directly";
+ case ELIBEXEC: return "can not exec a shared library directly";
#endif
#ifdef ELIBMAX
- case ELIBMAX: return
- "attempting to link in more shared libraries than system limit";
+ case ELIBMAX: return
+ "attempting to link in more shared libraries than system limit";
#endif
#ifdef ELIBSCN
- case ELIBSCN: return ".lib section in a.out corrupted";
+ case ELIBSCN: return ".lib section in a.out corrupted";
#endif
#ifdef ELNRNG
- case ELNRNG: return "link number out of range";
+ case ELNRNG: return "link number out of range";
#endif
#if defined(ELOOP) && (!defined(ENOENT) || (ELOOP != ENOENT))
- case ELOOP: return "too many levels of symbolic links";
+ case ELOOP: return "too many levels of symbolic links";
#endif
#ifdef EMFILE
- case EMFILE: return "too many open files";
+ case EMFILE: return "too many open files";
#endif
#ifdef EMLINK
- case EMLINK: return "too many links";
+ case EMLINK: return "too many links";
#endif
#ifdef EMSGSIZE
- case EMSGSIZE: return "message too long";
+ case EMSGSIZE: return "message too long";
#endif
#ifdef EMULTIHOP
- case EMULTIHOP: return "multihop attempted";
+ case EMULTIHOP: return "multihop attempted";
#endif
#ifdef ENAMETOOLONG
- case ENAMETOOLONG: return "file name too long";
+ case ENAMETOOLONG: return "file name too long";
#endif
#ifdef ENAVAIL
- case ENAVAIL: return "not available";
+ case ENAVAIL: return "not available";
#endif
#ifdef ENET
- case ENET: return "ENET";
+ case ENET: return "ENET";
#endif
#ifdef ENETDOWN
- case ENETDOWN: return "network is down";
+ case ENETDOWN: return "network is down";
#endif
#ifdef ENETRESET
- case ENETRESET: return "network dropped connection on reset";
+ case ENETRESET: return "network dropped connection on reset";
#endif
#ifdef ENETUNREACH
- case ENETUNREACH: return "network is unreachable";
+ case ENETUNREACH: return "network is unreachable";
#endif
#ifdef ENFILE
- case ENFILE: return "file table overflow";
+ case ENFILE: return "file table overflow";
#endif
#ifdef ENOANO
- case ENOANO: return "anode table overflow";
+ case ENOANO: return "anode table overflow";
#endif
#if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR))
- case ENOBUFS: return "no buffer space available";
+ case ENOBUFS: return "no buffer space available";
#endif
#ifdef ENOCSI
- case ENOCSI: return "no CSI structure available";
+ case ENOCSI: return "no CSI structure available";
#endif
#if defined(ENODATA) && (!defined(ECONNREFUSED) || (ENODATA != ECONNREFUSED))
- case ENODATA: return "no data available";
+ case ENODATA: return "no data available";
#endif
#ifdef ENODEV
- case ENODEV: return "no such device";
+ case ENODEV: return "no such device";
#endif
#ifdef ENOENT
- case ENOENT: return "no such file or directory";
+ case ENOENT: return "no such file or directory";
#endif
#ifdef ENOEXEC
- case ENOEXEC: return "exec format error";
+ case ENOEXEC: return "exec format error";
#endif
#ifdef ENOLCK
- case ENOLCK: return "no locks available";
+ case ENOLCK: return "no locks available";
#endif
#if defined(ENOLINK) && (!defined(ESOCKTNOSUPPORT) || (ESOCKTNOSUPPORT != ENOLINK))
- case ENOLINK: return "link has been severed";
+ case ENOLINK: return "link has been severed";
#endif
#ifdef ENOMEM
- case ENOMEM: return "not enough memory";
+ case ENOMEM: return "not enough memory";
#endif
#ifdef ENOMSG
- case ENOMSG: return "no message of desired type";
+ case ENOMSG: return "no message of desired type";
#endif
#ifdef ENONET
- case ENONET: return "machine is not on the network";
+ case ENONET: return "machine is not on the network";
#endif
#ifdef ENOPKG
- case ENOPKG: return "package not installed";
+ case ENOPKG: return "package not installed";
#endif
#if defined(ENOPROTOOPT) && (!defined(EPFNOSUPPORT) || (EPFNOSUPPORT != ENOPROTOOPT))
- case ENOPROTOOPT: return "bad protocol option";
+ case ENOPROTOOPT: return "bad protocol option";
#endif
#ifdef ENOSPC
- case ENOSPC: return "no space left on device";
+ case ENOSPC: return "no space left on device";
#endif
#if defined(ENOSR) && (!defined(ENAMETOOLONG) || (ENAMETOOLONG != ENOSR))
- case ENOSR: return "out of stream resources";
+ case ENOSR: return "out of stream resources";
#endif
#if defined(ENOSTR) && (!defined(ENOTTY) || (ENOTTY != ENOSTR))
- case ENOSTR: return "not a stream device";
+ case ENOSTR: return "not a stream device";
#endif
#ifdef ENOSYM
- case ENOSYM: return "unresolved symbol name";
+ case ENOSYM: return "unresolved symbol name";
#endif
#ifdef ENOSYS
- case ENOSYS: return "function not implemented";
+ case ENOSYS: return "function not implemented";
#endif
#ifdef ENOTBLK
- case ENOTBLK: return "block device required";
+ case ENOTBLK: return "block device required";
#endif
#ifdef ENOTCONN
- case ENOTCONN: return "socket is not connected";
+ case ENOTCONN: return "socket is not connected";
#endif
#ifdef ENOTDIR
- case ENOTDIR: return "not a directory";
+ case ENOTDIR: return "not a directory";
#endif
#if defined(ENOTEMPTY) && (!defined(EEXIST) || (ENOTEMPTY != EEXIST))
- case ENOTEMPTY: return "directory not empty";
+ case ENOTEMPTY: return "directory not empty";
#endif
#ifdef ENOTNAM
- case ENOTNAM: return "not a name file";
+ case ENOTNAM: return "not a name file";
#endif
#ifdef ENOTSOCK
- case ENOTSOCK: return "socket operation on non-socket";
+ case ENOTSOCK: return "socket operation on non-socket";
#endif
#ifdef ENOTSUP
- case ENOTSUP: return "operation not supported";
+ case ENOTSUP: return "operation not supported";
#endif
#ifdef ENOTTY
- case ENOTTY: return "inappropriate device for ioctl";
+ case ENOTTY: return "inappropriate device for ioctl";
#endif
#ifdef ENOTUNIQ
- case ENOTUNIQ: return "name not unique on network";
+ case ENOTUNIQ: return "name not unique on network";
#endif
#ifdef ENXIO
- case ENXIO: return "no such device or address";
+ case ENXIO: return "no such device or address";
#endif
#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (ENOTSUP != EOPNOTSUPP))
- case EOPNOTSUPP: return "operation not supported on socket";
+ case EOPNOTSUPP: return "operation not supported on socket";
#endif
#if defined(EOVERFLOW) && (!defined(EFBIG) || (EOVERFLOW != EFBIG)) && (!defined(EINVAL) || (EOVERFLOW != EINVAL))
- case EOVERFLOW: return "file too big";
+ case EOVERFLOW: return "file too big";
#endif
#ifdef EPERM
- case EPERM: return "not owner";
+ case EPERM: return "not owner";
#endif
#if defined(EPFNOSUPPORT) && (!defined(ENOLCK) || (ENOLCK != EPFNOSUPPORT))
- case EPFNOSUPPORT: return "protocol family not supported";
+ case EPFNOSUPPORT: return "protocol family not supported";
#endif
#ifdef EPIPE
- case EPIPE: return "broken pipe";
+ case EPIPE: return "broken pipe";
#endif
#ifdef EPROCLIM
- case EPROCLIM: return "too many processes";
+ case EPROCLIM: return "too many processes";
#endif
#ifdef EPROCUNAVAIL
- case EPROCUNAVAIL: return "bad procedure for program";
+ case EPROCUNAVAIL: return "bad procedure for program";
#endif
#ifdef EPROGMISMATCH
- case EPROGMISMATCH: return "program version wrong";
+ case EPROGMISMATCH: return "program version wrong";
#endif
#ifdef EPROGUNAVAIL
- case EPROGUNAVAIL: return "RPC program not available";
+ case EPROGUNAVAIL: return "RPC program not available";
#endif
#ifdef EPROTO
- case EPROTO: return "protocol error";
+ case EPROTO: return "protocol error";
#endif
#ifdef EPROTONOSUPPORT
- case EPROTONOSUPPORT: return "protocol not supported";
+ case EPROTONOSUPPORT: return "protocol not supported";
#endif
#ifdef EPROTOTYPE
- case EPROTOTYPE: return "protocol wrong type for socket";
+ case EPROTOTYPE: return "protocol wrong type for socket";
#endif
#ifdef ERANGE
- case ERANGE: return "math result unrepresentable";
+ case ERANGE: return "math result unrepresentable";
#endif
#if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED))
- case EREFUSED: return "EREFUSED";
+ case EREFUSED: return "EREFUSED";
#endif
#ifdef EREMCHG
- case EREMCHG: return "remote address changed";
+ case EREMCHG: return "remote address changed";
#endif
#ifdef EREMDEV
- case EREMDEV: return "remote device";
+ case EREMDEV: return "remote device";
#endif
#ifdef EREMOTE
- case EREMOTE: return "pathname hit remote file system";
+ case EREMOTE: return "pathname hit remote file system";
#endif
#ifdef EREMOTEIO
- case EREMOTEIO: return "remote i/o error";
+ case EREMOTEIO: return "remote i/o error";
#endif
#ifdef EREMOTERELEASE
- case EREMOTERELEASE: return "EREMOTERELEASE";
+ case EREMOTERELEASE: return "EREMOTERELEASE";
#endif
#ifdef EROFS
- case EROFS: return "read-only file system";
+ case EROFS: return "read-only file system";
#endif
#ifdef ERPCMISMATCH
- case ERPCMISMATCH: return "RPC version is wrong";
+ case ERPCMISMATCH: return "RPC version is wrong";
#endif
#ifdef ERREMOTE
- case ERREMOTE: return "object is remote";
+ case ERREMOTE: return "object is remote";
#endif
#ifdef ESHUTDOWN
- case ESHUTDOWN: return "can't send after socket shutdown";
+ case ESHUTDOWN: return "can't send after socket shutdown";
#endif
#ifdef ESOCKTNOSUPPORT
- case ESOCKTNOSUPPORT: return "socket type not supported";
+ case ESOCKTNOSUPPORT: return "socket type not supported";
#endif
#ifdef ESPIPE
- case ESPIPE: return "invalid seek";
+ case ESPIPE: return "invalid seek";
#endif
#ifdef ESRCH
- case ESRCH: return "no such process";
+ case ESRCH: return "no such process";
#endif
#ifdef ESRMNT
- case ESRMNT: return "srmount error";
+ case ESRMNT: return "srmount error";
#endif
#ifdef ESTALE
- case ESTALE: return "stale remote file handle";
+ case ESTALE: return "stale remote file handle";
#endif
#ifdef ESUCCESS
- case ESUCCESS: return "Error 0";
+ case ESUCCESS: return "Error 0";
#endif
#if defined(ETIME) && (!defined(ELOOP) || (ETIME != ELOOP))
- case ETIME: return "timer expired";
+ case ETIME: return "timer expired";
#endif
#if defined(ETIMEDOUT) && (!defined(ENOSTR) || (ETIMEDOUT != ENOSTR))
- case ETIMEDOUT: return "connection timed out";
+ case ETIMEDOUT: return "connection timed out";
#endif
#ifdef ETOOMANYREFS
- case ETOOMANYREFS: return "too many references: can't splice";
+ case ETOOMANYREFS: return "too many references: can't splice";
#endif
#ifdef ETXTBSY
- case ETXTBSY: return "text file or pseudo-device busy";
+ case ETXTBSY: return "text file or pseudo-device busy";
#endif
#ifdef EUCLEAN
- case EUCLEAN: return "structure needs cleaning";
+ case EUCLEAN: return "structure needs cleaning";
#endif
#ifdef EUNATCH
- case EUNATCH: return "protocol driver not attached";
+ case EUNATCH: return "protocol driver not attached";
#endif
#ifdef EUSERS
- case EUSERS: return "too many users";
+ case EUSERS: return "too many users";
#endif
#ifdef EVERSION
- case EVERSION: return "version mismatch";
+ case EVERSION: return "version mismatch";
#endif
#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
- case EWOULDBLOCK: return "operation would block";
+ case EWOULDBLOCK: return "operation would block";
#endif
#ifdef EXDEV
- case EXDEV: return "cross-domain link";
+ case EXDEV: return "cross-domain link";
#endif
#ifdef EXFULL
- case EXFULL: return "message tables full";
+ case EXFULL: return "message tables full";
#endif
- default:
+ default:
#ifdef NO_STRERROR
- return "unknown POSIX error";
+ return "unknown POSIX error";
#else
- return strerror(err);
+ return strerror(err);
#endif
}
}
@@ -921,9 +917,9 @@ Tcl_ErrnoMsg(err)
* Return a textual identifier for a signal number.
*
* Results:
- * This procedure returns a machine-readable textual identifier
- * that corresponds to sig. The identifier is the same as the
- * #define name in signal.h.
+ * This procedure returns a machine-readable textual identifier that
+ * corresponds to sig. The identifier is the same as the #define name in
+ * signal.h.
*
* Side effects:
* None.
@@ -932,114 +928,117 @@ Tcl_ErrnoMsg(err)
*/
CONST char *
-Tcl_SignalId(sig)
- int sig; /* Number of signal. */
+Tcl_SignalId(
+ int sig) /* Number of signal. */
{
switch (sig) {
#ifdef SIGABRT
- case SIGABRT: return "SIGABRT";
+ case SIGABRT: return "SIGABRT";
#endif
#ifdef SIGALRM
- case SIGALRM: return "SIGALRM";
+ case SIGALRM: return "SIGALRM";
#endif
#ifdef SIGBUS
- case SIGBUS: return "SIGBUS";
+ case SIGBUS: return "SIGBUS";
#endif
#ifdef SIGCHLD
- case SIGCHLD: return "SIGCHLD";
+ case SIGCHLD: return "SIGCHLD";
#endif
#if defined(SIGCLD) && (!defined(SIGCHLD) || (SIGCLD != SIGCHLD))
- case SIGCLD: return "SIGCLD";
+ case SIGCLD: return "SIGCLD";
#endif
#ifdef SIGCONT
- case SIGCONT: return "SIGCONT";
+ case SIGCONT: return "SIGCONT";
#endif
#if defined(SIGEMT) && (!defined(SIGXCPU) || (SIGEMT != SIGXCPU))
- case SIGEMT: return "SIGEMT";
+ case SIGEMT: return "SIGEMT";
#endif
#ifdef SIGFPE
- case SIGFPE: return "SIGFPE";
+ case SIGFPE: return "SIGFPE";
#endif
#ifdef SIGHUP
- case SIGHUP: return "SIGHUP";
+ case SIGHUP: return "SIGHUP";
#endif
#ifdef SIGILL
- case SIGILL: return "SIGILL";
+ case SIGILL: return "SIGILL";
#endif
#ifdef SIGINT
- case SIGINT: return "SIGINT";
+ case SIGINT: return "SIGINT";
#endif
#ifdef SIGIO
- case SIGIO: return "SIGIO";
+ case SIGIO: return "SIGIO";
#endif
#if defined(SIGIOT) && (!defined(SIGABRT) || (SIGIOT != SIGABRT))
- case SIGIOT: return "SIGIOT";
+ case SIGIOT: return "SIGIOT";
#endif
#ifdef SIGKILL
- case SIGKILL: return "SIGKILL";
+ case SIGKILL: return "SIGKILL";
#endif
#if defined(SIGLOST) && (!defined(SIGIOT) || (SIGLOST != SIGIOT)) && (!defined(SIGURG) || (SIGLOST != SIGURG)) && (!defined(SIGPROF) || (SIGLOST != SIGPROF)) && (!defined(SIGIO) || (SIGLOST != SIGIO))
- case SIGLOST: return "SIGLOST";
+ case SIGLOST: return "SIGLOST";
#endif
#ifdef SIGPIPE
- case SIGPIPE: return "SIGPIPE";
+ case SIGPIPE: return "SIGPIPE";
#endif
#if defined(SIGPOLL) && (!defined(SIGIO) || (SIGPOLL != SIGIO))
- case SIGPOLL: return "SIGPOLL";
+ case SIGPOLL: return "SIGPOLL";
#endif
#ifdef SIGPROF
- case SIGPROF: return "SIGPROF";
+ case SIGPROF: return "SIGPROF";
#endif
#if defined(SIGPWR) && (!defined(SIGXFSZ) || (SIGPWR != SIGXFSZ)) && (!defined(SIGLOST) || (SIGPWR != SIGLOST))
- case SIGPWR: return "SIGPWR";
+ case SIGPWR: return "SIGPWR";
#endif
#ifdef SIGQUIT
- case SIGQUIT: return "SIGQUIT";
+ case SIGQUIT: return "SIGQUIT";
#endif
#if defined(SIGSEGV) && (!defined(SIGBUS) || (SIGSEGV != SIGBUS))
- case SIGSEGV: return "SIGSEGV";
+ case SIGSEGV: return "SIGSEGV";
#endif
#ifdef SIGSTOP
- case SIGSTOP: return "SIGSTOP";
+ case SIGSTOP: return "SIGSTOP";
#endif
#ifdef SIGSYS
- case SIGSYS: return "SIGSYS";
+ case SIGSYS: return "SIGSYS";
#endif
#ifdef SIGTERM
- case SIGTERM: return "SIGTERM";
+ case SIGTERM: return "SIGTERM";
#endif
#ifdef SIGTRAP
- case SIGTRAP: return "SIGTRAP";
+ case SIGTRAP: return "SIGTRAP";
#endif
#ifdef SIGTSTP
- case SIGTSTP: return "SIGTSTP";
+ case SIGTSTP: return "SIGTSTP";
#endif
#ifdef SIGTTIN
- case SIGTTIN: return "SIGTTIN";
+ case SIGTTIN: return "SIGTTIN";
#endif
#ifdef SIGTTOU
- case SIGTTOU: return "SIGTTOU";
+ case SIGTTOU: return "SIGTTOU";
#endif
#if defined(SIGURG) && (!defined(SIGIO) || (SIGURG != SIGIO))
- case SIGURG: return "SIGURG";
+ case SIGURG: return "SIGURG";
#endif
#if defined(SIGUSR1) && (!defined(SIGIO) || (SIGUSR1 != SIGIO))
- case SIGUSR1: return "SIGUSR1";
+ case SIGUSR1: return "SIGUSR1";
#endif
#if defined(SIGUSR2) && (!defined(SIGURG) || (SIGUSR2 != SIGURG))
- case SIGUSR2: return "SIGUSR2";
+ case SIGUSR2: return "SIGUSR2";
#endif
#ifdef SIGVTALRM
- case SIGVTALRM: return "SIGVTALRM";
+ case SIGVTALRM: return "SIGVTALRM";
#endif
#ifdef SIGWINCH
- case SIGWINCH: return "SIGWINCH";
+ case SIGWINCH: return "SIGWINCH";
#endif
#ifdef SIGXCPU
- case SIGXCPU: return "SIGXCPU";
+ case SIGXCPU: return "SIGXCPU";
#endif
#ifdef SIGXFSZ
- case SIGXFSZ: return "SIGXFSZ";
+ case SIGXFSZ: return "SIGXFSZ";
+#endif
+#if defined(SIGINFO) && (!defined(SIGPWR) || (SIGINFO != SIGPWR))
+ case SIGINFO: return "SIGINFO";
#endif
}
return "unknown signal";
@@ -1053,9 +1052,8 @@ Tcl_SignalId(sig)
* Return a human-readable message describing a signal.
*
* Results:
- * This procedure returns a string describing sig that should
- * make sense to a human. It may not be easy for a machine
- * to parse.
+ * This procedure returns a string describing sig that should make sense
+ * to a human. It may not be easy for a machine to parse.
*
* Side effects:
* None.
@@ -1064,115 +1062,126 @@ Tcl_SignalId(sig)
*/
CONST char *
-Tcl_SignalMsg(sig)
- int sig; /* Number of signal. */
+Tcl_SignalMsg(
+ int sig) /* Number of signal. */
{
switch (sig) {
#ifdef SIGABRT
- case SIGABRT: return "SIGABRT";
+ case SIGABRT: return "SIGABRT";
#endif
#ifdef SIGALRM
- case SIGALRM: return "alarm clock";
+ case SIGALRM: return "alarm clock";
#endif
#ifdef SIGBUS
- case SIGBUS: return "bus error";
+ case SIGBUS: return "bus error";
#endif
#ifdef SIGCHLD
- case SIGCHLD: return "child status changed";
+ case SIGCHLD: return "child status changed";
#endif
#if defined(SIGCLD) && (!defined(SIGCHLD) || (SIGCLD != SIGCHLD))
- case SIGCLD: return "child status changed";
+ case SIGCLD: return "child status changed";
#endif
#ifdef SIGCONT
- case SIGCONT: return "continue after stop";
+ case SIGCONT: return "continue after stop";
#endif
#if defined(SIGEMT) && (!defined(SIGXCPU) || (SIGEMT != SIGXCPU))
- case SIGEMT: return "EMT instruction";
+ case SIGEMT: return "EMT instruction";
#endif
#ifdef SIGFPE
- case SIGFPE: return "floating-point exception";
+ case SIGFPE: return "floating-point exception";
#endif
#ifdef SIGHUP
- case SIGHUP: return "hangup";
+ case SIGHUP: return "hangup";
#endif
#ifdef SIGILL
- case SIGILL: return "illegal instruction";
+ case SIGILL: return "illegal instruction";
#endif
#ifdef SIGINT
- case SIGINT: return "interrupt";
+ case SIGINT: return "interrupt";
#endif
#ifdef SIGIO
- case SIGIO: return "input/output possible on file";
+ case SIGIO: return "input/output possible on file";
#endif
#if defined(SIGIOT) && (!defined(SIGABRT) || (SIGABRT != SIGIOT))
- case SIGIOT: return "IOT instruction";
+ case SIGIOT: return "IOT instruction";
#endif
#ifdef SIGKILL
- case SIGKILL: return "kill signal";
+ case SIGKILL: return "kill signal";
#endif
#if defined(SIGLOST) && (!defined(SIGIOT) || (SIGLOST != SIGIOT)) && (!defined(SIGURG) || (SIGLOST != SIGURG)) && (!defined(SIGPROF) || (SIGLOST != SIGPROF)) && (!defined(SIGIO) || (SIGLOST != SIGIO))
- case SIGLOST: return "resource lost";
+ case SIGLOST: return "resource lost";
#endif
#ifdef SIGPIPE
- case SIGPIPE: return "write on pipe with no readers";
+ case SIGPIPE: return "write on pipe with no readers";
#endif
#if defined(SIGPOLL) && (!defined(SIGIO) || (SIGPOLL != SIGIO))
- case SIGPOLL: return "input/output possible on file";
+ case SIGPOLL: return "input/output possible on file";
#endif
#ifdef SIGPROF
- case SIGPROF: return "profiling alarm";
+ case SIGPROF: return "profiling alarm";
#endif
#if defined(SIGPWR) && (!defined(SIGXFSZ) || (SIGPWR != SIGXFSZ)) && (!defined(SIGLOST) || (SIGPWR != SIGLOST))
- case SIGPWR: return "power-fail restart";
+ case SIGPWR: return "power-fail restart";
#endif
#ifdef SIGQUIT
- case SIGQUIT: return "quit signal";
+ case SIGQUIT: return "quit signal";
#endif
#if defined(SIGSEGV) && (!defined(SIGBUS) || (SIGSEGV != SIGBUS))
- case SIGSEGV: return "segmentation violation";
+ case SIGSEGV: return "segmentation violation";
#endif
#ifdef SIGSTOP
- case SIGSTOP: return "stop";
+ case SIGSTOP: return "stop";
#endif
#ifdef SIGSYS
- case SIGSYS: return "bad argument to system call";
+ case SIGSYS: return "bad argument to system call";
#endif
#ifdef SIGTERM
- case SIGTERM: return "software termination signal";
+ case SIGTERM: return "software termination signal";
#endif
#ifdef SIGTRAP
- case SIGTRAP: return "trace trap";
+ case SIGTRAP: return "trace trap";
#endif
#ifdef SIGTSTP
- case SIGTSTP: return "stop signal from tty";
+ case SIGTSTP: return "stop signal from tty";
#endif
#ifdef SIGTTIN
- case SIGTTIN: return "background tty read";
+ case SIGTTIN: return "background tty read";
#endif
#ifdef SIGTTOU
- case SIGTTOU: return "background tty write";
+ case SIGTTOU: return "background tty write";
#endif
#if defined(SIGURG) && (!defined(SIGIO) || (SIGURG != SIGIO))
- case SIGURG: return "urgent I/O condition";
+ case SIGURG: return "urgent I/O condition";
#endif
#if defined(SIGUSR1) && (!defined(SIGIO) || (SIGUSR1 != SIGIO))
- case SIGUSR1: return "user-defined signal 1";
+ case SIGUSR1: return "user-defined signal 1";
#endif
#if defined(SIGUSR2) && (!defined(SIGURG) || (SIGUSR2 != SIGURG))
- case SIGUSR2: return "user-defined signal 2";
+ case SIGUSR2: return "user-defined signal 2";
#endif
#ifdef SIGVTALRM
- case SIGVTALRM: return "virtual time alarm";
+ case SIGVTALRM: return "virtual time alarm";
#endif
#ifdef SIGWINCH
- case SIGWINCH: return "window changed";
+ case SIGWINCH: return "window changed";
#endif
#ifdef SIGXCPU
- case SIGXCPU: return "exceeded CPU time limit";
+ case SIGXCPU: return "exceeded CPU time limit";
#endif
#ifdef SIGXFSZ
- case SIGXFSZ: return "exceeded file size limit";
+ case SIGXFSZ: return "exceeded file size limit";
+#endif
+#if defined(SIGINFO) && (!defined(SIGPWR) || (SIGINFO != SIGPWR))
+ case SIGINFO: return "information request";
#endif
}
return "unknown signal";
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclPreserve.c b/generic/tclPreserve.c
index 006c92b..0dc669c 100644
--- a/generic/tclPreserve.c
+++ b/generic/tclPreserve.c
@@ -1,69 +1,71 @@
-/*
+/*
* tclPreserve.c --
*
- * This file contains a collection of procedures that are used
- * to make sure that widget records and other data structures
- * aren't reallocated when there are nested procedures that
- * depend on their existence.
+ * This file contains a collection of functions that are used to make
+ * sure that widget records and other data structures aren't reallocated
+ * when there are nested functions that depend on their existence.
*
* Copyright (c) 1991-1994 The Regents of the University of California.
* Copyright (c) 1994-1998 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
/*
- * The following data structure is used to keep track of all the
- * Tcl_Preserve calls that are still in effect. It grows as needed
- * to accommodate any number of calls in effect.
+ * The following data structure is used to keep track of all the Tcl_Preserve
+ * calls that are still in effect. It grows as needed to accommodate any
+ * number of calls in effect.
*/
typedef struct {
ClientData clientData; /* Address of preserved block. */
- int refCount; /* Number of Tcl_Preserve calls in effect
- * for block. */
+ int refCount; /* Number of Tcl_Preserve calls in effect for
+ * block. */
int mustFree; /* Non-zero means Tcl_EventuallyFree was
* called while a Tcl_Preserve call was in
- * effect, so the structure must be freed
- * when refCount becomes zero. */
- Tcl_FreeProc *freeProc; /* Procedure to call to free. */
+ * effect, so the structure must be freed when
+ * refCount becomes zero. */
+ Tcl_FreeProc *freeProc; /* Function to call to free. */
} Reference;
-static Reference *refArray; /* First in array of references. */
-static int spaceAvl = 0; /* Total number of structures available
- * at *firstRefPtr. */
-static int inUse = 0; /* Count of structures currently in use
- * in refArray. */
-#define INITIAL_SIZE 2
+/*
+ * Global data structures used to hold the list of preserved data references.
+ * These variables are protected by "preserveMutex".
+ */
+
+static Reference *refArray = NULL; /* First in array of references. */
+static int spaceAvl = 0; /* Total number of structures available at
+ * *firstRefPtr. */
+static int inUse = 0; /* Count of structures currently in use in
+ * refArray. */
TCL_DECLARE_MUTEX(preserveMutex)/* To protect the above statics */
+#define INITIAL_SIZE 2 /* Initial number of reference slots to make */
+
/*
- * The following data structure is used to keep track of whether an
- * arbitrary block of memory has been deleted. This is used by the
- * TclHandle code to avoid the more time-expensive algorithm of
- * Tcl_Preserve(). This mechanism is mainly used when we have lots of
- * references to a few big, expensive objects that we don't want to live
- * any longer than necessary.
+ * The following data structure is used to keep track of whether an arbitrary
+ * block of memory has been deleted. This is used by the TclHandle code to
+ * avoid the more time-expensive algorithm of Tcl_Preserve(). This mechanism
+ * is mainly used when we have lots of references to a few big, expensive
+ * objects that we don't want to live any longer than necessary.
*/
typedef struct HandleStruct {
- VOID *ptr; /* Pointer to the memory block being
- * tracked. This field will become NULL when
- * the memory block is deleted. This field
- * must be the first in the structure. */
+ void *ptr; /* Pointer to the memory block being tracked.
+ * This field will become NULL when the memory
+ * block is deleted. This field must be the
+ * first in the structure. */
#ifdef TCL_MEM_DEBUG
- VOID *ptr2; /* Backup copy of the abpve pointer used to
+ void *ptr2; /* Backup copy of the above pointer used to
* ensure that the contents of the handle are
* not changed by anyone else. */
#endif
int refCount; /* Number of TclHandlePreserve() calls in
* effect on this handle. */
} HandleStruct;
-
-
/*
*----------------------------------------------------------------------
@@ -83,12 +85,12 @@ typedef struct HandleStruct {
/* ARGSUSED */
void
-TclFinalizePreserve()
+TclFinalizePreserve(void)
{
Tcl_MutexLock(&preserveMutex);
if (spaceAvl != 0) {
ckfree((char *) refArray);
- refArray = (Reference *) NULL;
+ refArray = NULL;
inUse = 0;
spaceAvl = 0;
}
@@ -100,34 +102,34 @@ TclFinalizePreserve()
*
* Tcl_Preserve --
*
- * This procedure is used by a procedure to declare its interest
- * in a particular block of memory, so that the block will not be
- * reallocated until a matching call to Tcl_Release has been made.
+ * This function is used by a function to declare its interest in a
+ * particular block of memory, so that the block will not be reallocated
+ * until a matching call to Tcl_Release has been made.
*
* Results:
* None.
*
* Side effects:
- * Information is retained so that the block of memory will
- * not be freed until at least the matching call to Tcl_Release.
+ * Information is retained so that the block of memory will not be freed
+ * until at least the matching call to Tcl_Release.
*
*----------------------------------------------------------------------
*/
void
-Tcl_Preserve(clientData)
- ClientData clientData; /* Pointer to malloc'ed block of memory. */
+Tcl_Preserve(
+ ClientData clientData) /* Pointer to malloc'ed block of memory. */
{
Reference *refPtr;
int i;
/*
- * See if there is already a reference for this pointer. If so,
- * just increment its reference count.
+ * See if there is already a reference for this pointer. If so, just
+ * increment its reference count.
*/
Tcl_MutexLock(&preserveMutex);
- for (i = 0, refPtr = refArray; i < inUse; i++, refPtr++) {
+ for (i=0, refPtr=refArray ; i<inUse ; i++, refPtr++) {
if (refPtr->clientData == clientData) {
refPtr->refCount++;
Tcl_MutexUnlock(&preserveMutex);
@@ -136,26 +138,14 @@ Tcl_Preserve(clientData)
}
/*
- * Make a reference array if it doesn't already exist, or make it
- * bigger if it is full.
+ * Make a reference array if it doesn't already exist, or make it bigger
+ * if it is full.
*/
if (inUse == spaceAvl) {
- if (spaceAvl == 0) {
- refArray = (Reference *) ckalloc((unsigned)
- (INITIAL_SIZE*sizeof(Reference)));
- spaceAvl = INITIAL_SIZE;
- } else {
- Reference *new;
-
- new = (Reference *) ckalloc((unsigned)
- (2*spaceAvl*sizeof(Reference)));
- memcpy((VOID *) new, (VOID *) refArray,
- spaceAvl*sizeof(Reference));
- ckfree((char *) refArray);
- refArray = new;
- spaceAvl *= 2;
- }
+ spaceAvl = spaceAvl ? 2*spaceAvl : INITIAL_SIZE;
+ refArray = (Reference *) ckrealloc((char *) refArray,
+ spaceAvl * sizeof(Reference));
}
/*
@@ -176,71 +166,79 @@ Tcl_Preserve(clientData)
*
* Tcl_Release --
*
- * This procedure is called to cancel a previous call to
- * Tcl_Preserve, thereby allowing a block of memory to be
- * freed (if no one else cares about it).
+ * This function is called to cancel a previous call to Tcl_Preserve,
+ * thereby allowing a block of memory to be freed (if no one else cares
+ * about it).
*
* Results:
* None.
*
* Side effects:
- * If Tcl_EventuallyFree has been called for clientData, and if
- * no other call to Tcl_Preserve is still in effect, the block of
- * memory is freed.
+ * If Tcl_EventuallyFree has been called for clientData, and if no other
+ * call to Tcl_Preserve is still in effect, the block of memory is freed.
*
*----------------------------------------------------------------------
*/
void
-Tcl_Release(clientData)
- ClientData clientData; /* Pointer to malloc'ed block of memory. */
+Tcl_Release(
+ ClientData clientData) /* Pointer to malloc'ed block of memory. */
{
Reference *refPtr;
- int mustFree;
- Tcl_FreeProc *freeProc;
int i;
Tcl_MutexLock(&preserveMutex);
- for (i = 0, refPtr = refArray; i < inUse; i++, refPtr++) {
+ for (i=0, refPtr=refArray ; i<inUse ; i++, refPtr++) {
+ int mustFree;
+ Tcl_FreeProc *freeProc;
+
if (refPtr->clientData != clientData) {
continue;
}
- refPtr->refCount--;
- if (refPtr->refCount == 0) {
-
- /*
- * Must remove information from the slot before calling freeProc
- * to avoid reentrancy problems if the freeProc calls Tcl_Preserve
- * on the same clientData. Copy down the last reference in the
- * array to overwrite the current slot.
- */
-
- freeProc = refPtr->freeProc;
- mustFree = refPtr->mustFree;
- inUse--;
- if (i < inUse) {
- refArray[i] = refArray[inUse];
- }
- if (mustFree) {
- if (freeProc == TCL_DYNAMIC) {
- ckfree((char *) clientData);
- } else {
- Tcl_MutexUnlock(&preserveMutex);
- (*freeProc)((char *) clientData);
- return;
- }
- }
+
+ if (--refPtr->refCount != 0) {
+ Tcl_MutexUnlock(&preserveMutex);
+ return;
}
+
+ /*
+ * Must remove information from the slot before calling freeProc to
+ * avoid reentrancy problems if the freeProc calls Tcl_Preserve on the
+ * same clientData. Copy down the last reference in the array to
+ * overwrite the current slot.
+ */
+
+ freeProc = refPtr->freeProc;
+ mustFree = refPtr->mustFree;
+ inUse--;
+ if (i < inUse) {
+ refArray[i] = refArray[inUse];
+ }
+
+ /*
+ * Now committed to disposing the data. But first, we've patched up
+ * all the global data structures so we should release the mutex now.
+ * Only then should we dabble around with potentially-slow memory
+ * managers...
+ */
+
Tcl_MutexUnlock(&preserveMutex);
+ if (mustFree) {
+ if (freeProc == TCL_DYNAMIC) {
+ ckfree((char *) clientData);
+ } else {
+ (*freeProc)((char *) clientData);
+ }
+ }
return;
}
Tcl_MutexUnlock(&preserveMutex);
/*
- * Reference not found. This is a bug in the caller.
+ * Reference not found. This is a bug in the caller.
*/
- panic("Tcl_Release couldn't find reference for 0x%x", clientData);
+ Tcl_Panic("Tcl_Release couldn't find reference for 0x%x", PTR2UINT(clientData));
}
/*
@@ -248,10 +246,9 @@ Tcl_Release(clientData)
*
* Tcl_EventuallyFree --
*
- * Free up a block of memory, unless a call to Tcl_Preserve is in
- * effect for that block. In this case, defer the free until all
- * calls to Tcl_Preserve have been undone by matching calls to
- * Tcl_Release.
+ * Free up a block of memory, unless a call to Tcl_Preserve is in effect
+ * for that block. In this case, defer the free until all calls to
+ * Tcl_Preserve have been undone by matching calls to Tcl_Release.
*
* Results:
* None.
@@ -263,16 +260,16 @@ Tcl_Release(clientData)
*/
void
-Tcl_EventuallyFree(clientData, freeProc)
- ClientData clientData; /* Pointer to malloc'ed block of memory. */
- Tcl_FreeProc *freeProc; /* Procedure to actually do free. */
+Tcl_EventuallyFree(
+ ClientData clientData, /* Pointer to malloc'ed block of memory. */
+ Tcl_FreeProc *freeProc) /* Function to actually do free. */
{
Reference *refPtr;
int i;
/*
- * See if there is a reference for this pointer. If so, set its
- * "mustFree" flag (the flag had better not be set already!).
+ * See if there is a reference for this pointer. If so, set its "mustFree"
+ * flag (the flag had better not be set already!).
*/
Tcl_MutexLock(&preserveMutex);
@@ -281,7 +278,8 @@ Tcl_EventuallyFree(clientData, freeProc)
continue;
}
if (refPtr->mustFree) {
- panic("Tcl_EventuallyFree called twice for 0x%x\n", clientData);
+ Tcl_Panic("Tcl_EventuallyFree called twice for 0x%x",
+ PTR2UINT(clientData));
}
refPtr->mustFree = 1;
refPtr->freeProc = freeProc;
@@ -306,31 +304,29 @@ Tcl_EventuallyFree(clientData, freeProc)
*
* TclHandleCreate --
*
- * Allocate a handle that contains enough information to determine
- * if an arbitrary malloc'd block has been deleted. This is
- * used to avoid the more time-expensive algorithm of Tcl_Preserve().
+ * Allocate a handle that contains enough information to determine if an
+ * arbitrary malloc'd block has been deleted. This is used to avoid the
+ * more time-expensive algorithm of Tcl_Preserve().
*
* Results:
* The return value is a TclHandle that refers to the given malloc'd
- * block. Doubly dereferencing the returned handle will give
- * back the pointer to the block, or will give NULL if the block has
- * been deleted.
+ * block. Doubly dereferencing the returned handle will give back the
+ * pointer to the block, or will give NULL if the block has been deleted.
*
* Side effects:
- * The caller must keep track of this handle (generally by storing
- * it in a field in the malloc'd block) and call TclHandleFree()
- * on this handle when the block is deleted. Everything else that
- * wishes to keep track of whether the malloc'd block has been deleted
- * should use calls to TclHandlePreserve() and TclHandleRelease()
- * on the associated handle.
+ * The caller must keep track of this handle (generally by storing it in
+ * a field in the malloc'd block) and call TclHandleFree() on this handle
+ * when the block is deleted. Everything else that wishes to keep track
+ * of whether the malloc'd block has been deleted should use calls to
+ * TclHandlePreserve() and TclHandleRelease() on the associated handle.
*
*---------------------------------------------------------------------------
*/
TclHandle
-TclHandleCreate(ptr)
- VOID *ptr; /* Pointer to an arbitrary block of memory
- * to be tracked for deletion. Must not be
+TclHandleCreate(
+ void *ptr) /* Pointer to an arbitrary block of memory to
+ * be tracked for deletion. Must not be
* NULL. */
{
HandleStruct *handlePtr;
@@ -349,11 +345,10 @@ TclHandleCreate(ptr)
*
* TclHandleFree --
*
- * Called when the arbitrary malloc'd block associated with the
- * handle is being deleted. Modifies the handle so that doubly
- * dereferencing it will give NULL. This informs any user of the
- * handle that the block of memory formerly referenced by the
- * handle has been freed.
+ * Called when the arbitrary malloc'd block associated with the handle is
+ * being deleted. Modifies the handle so that doubly dereferencing it
+ * will give NULL. This informs any user of the handle that the block of
+ * memory formerly referenced by the handle has been freed.
*
* Results:
* None.
@@ -365,21 +360,21 @@ TclHandleCreate(ptr)
*/
void
-TclHandleFree(handle)
- TclHandle handle; /* Previously created handle associated
- * with a malloc'd block that is being
- * deleted. The handle is modified so that
- * doubly dereferencing it will give NULL. */
+TclHandleFree(
+ TclHandle handle) /* Previously created handle associated with a
+ * malloc'd block that is being deleted. The
+ * handle is modified so that doubly
+ * dereferencing it will give NULL. */
{
HandleStruct *handlePtr;
handlePtr = (HandleStruct *) handle;
#ifdef TCL_MEM_DEBUG
if (handlePtr->refCount == 0x61616161) {
- panic("using previously disposed TclHandle %x", handlePtr);
+ Tcl_Panic("using previously disposed TclHandle %x", handlePtr);
}
if (handlePtr->ptr2 != handlePtr->ptr) {
- panic("someone has changed the block referenced by the handle %x\nfrom %x to %x",
+ Tcl_Panic("someone has changed the block referenced by the handle %x\nfrom %x to %x",
handlePtr, handlePtr->ptr2, handlePtr->ptr);
}
#endif
@@ -394,36 +389,35 @@ TclHandleFree(handle)
*
* TclHandlePreserve --
*
- * Declare an interest in the arbitrary malloc'd block associated
- * with the handle.
+ * Declare an interest in the arbitrary malloc'd block associated with
+ * the handle.
*
* Results:
* The return value is the handle argument, with its ref count
* incremented.
*
* Side effects:
- * For each call to TclHandlePreserve(), there should be a matching
- * call to TclHandleRelease() when the caller is no longer interested
- * in the malloc'd block associated with the handle.
+ * For each call to TclHandlePreserve(), there should be a matching call
+ * to TclHandleRelease() when the caller is no longer interested in the
+ * malloc'd block associated with the handle.
*
*---------------------------------------------------------------------------
*/
TclHandle
-TclHandlePreserve(handle)
- TclHandle handle; /* Declare an interest in the block of
- * memory referenced by this handle. */
+TclHandlePreserve(
+ TclHandle handle) /* Declare an interest in the block of memory
+ * referenced by this handle. */
{
HandleStruct *handlePtr;
handlePtr = (HandleStruct *) handle;
#ifdef TCL_MEM_DEBUG
if (handlePtr->refCount == 0x61616161) {
- panic("using previously disposed TclHandle %x", handlePtr);
+ Tcl_Panic("using previously disposed TclHandle %x", handlePtr);
}
- if ((handlePtr->ptr != NULL)
- && (handlePtr->ptr != handlePtr->ptr2)) {
- panic("someone has changed the block referenced by the handle %x\nfrom %x to %x",
+ if ((handlePtr->ptr != NULL) && (handlePtr->ptr != handlePtr->ptr2)) {
+ Tcl_Panic("someone has changed the block referenced by the handle %x\nfrom %x to %x",
handlePtr, handlePtr->ptr2, handlePtr->ptr);
}
#endif
@@ -437,35 +431,34 @@ TclHandlePreserve(handle)
*
* TclHandleRelease --
*
- * This procedure is called to release an interest in the malloc'd
- * block associated with the handle.
+ * This function is called to release an interest in the malloc'd block
+ * associated with the handle.
*
* Results:
* None.
*
* Side effects:
- * The ref count of the handle is decremented. If the malloc'd block
- * has been freed and if no one is using the handle any more, the
- * handle will be reclaimed.
+ * The ref count of the handle is decremented. If the malloc'd block has
+ * been freed and if no one is using the handle any more, the handle will
+ * be reclaimed.
*
*---------------------------------------------------------------------------
*/
-
+
void
-TclHandleRelease(handle)
- TclHandle handle; /* Unregister interest in the block of
- * memory referenced by this handle. */
+TclHandleRelease(
+ TclHandle handle) /* Unregister interest in the block of memory
+ * referenced by this handle. */
{
HandleStruct *handlePtr;
handlePtr = (HandleStruct *) handle;
#ifdef TCL_MEM_DEBUG
if (handlePtr->refCount == 0x61616161) {
- panic("using previously disposed TclHandle %x", handlePtr);
+ Tcl_Panic("using previously disposed TclHandle %x", handlePtr);
}
- if ((handlePtr->ptr != NULL)
- && (handlePtr->ptr != handlePtr->ptr2)) {
- panic("someone has changed the block referenced by the handle %x\nfrom %x to %x",
+ if ((handlePtr->ptr != NULL) && (handlePtr->ptr != handlePtr->ptr2)) {
+ Tcl_Panic("someone has changed the block referenced by the handle %x\nfrom %x to %x",
handlePtr, handlePtr->ptr2, handlePtr->ptr);
}
#endif
@@ -474,4 +467,11 @@ TclHandleRelease(handle)
ckfree((char *) handlePtr);
}
}
-
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclProc.c b/generic/tclProc.c
index abfd152..89bd0b9 100644
--- a/generic/tclProc.c
+++ b/generic/tclProc.c
@@ -1,15 +1,16 @@
/*
* tclProc.c --
*
- * This file contains routines that implement Tcl procedures,
- * including the "proc" and "uplevel" commands.
+ * This file contains routines that implement Tcl procedures, including
+ * the "proc" and "uplevel" commands.
*
* Copyright (c) 1987-1993 The Regents of the University of California.
* Copyright (c) 1994-1998 Sun Microsystems, Inc.
+ * Copyright (c) 2004-2006 Miguel Sofer
* Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
@@ -19,19 +20,30 @@
* Prototypes for static functions in this file
*/
-static void ProcBodyDup _ANSI_ARGS_((Tcl_Obj *srcPtr, Tcl_Obj *dupPtr));
-static void ProcBodyFree _ANSI_ARGS_((Tcl_Obj *objPtr));
-static int ProcBodySetFromAny _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
-static void ProcBodyUpdateString _ANSI_ARGS_((Tcl_Obj *objPtr));
-static int ProcCompileProc _ANSI_ARGS_((Tcl_Interp *interp,
- Proc *procPtr, Tcl_Obj *bodyPtr, Namespace *nsPtr,
- CONST char *description, CONST char *procName,
- Proc **procPtrPtr));
-static int ProcessProcResultCode _ANSI_ARGS_((Tcl_Interp *interp,
- char *procName, int nameLen, int returnCode));
-static int TclCompileNoOp _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
+static void DupLambdaInternalRep(Tcl_Obj *objPtr,
+ Tcl_Obj *copyPtr);
+static void FreeLambdaInternalRep(Tcl_Obj *objPtr);
+static int InitArgsAndLocals(Tcl_Interp *interp,
+ Tcl_Obj *procNameObj, int skip);
+static void InitResolvedLocals(Tcl_Interp *interp,
+ ByteCode *codePtr, Var *defPtr,
+ Namespace *nsPtr);
+static void InitLocalCache(Proc *procPtr);
+static int PushProcCallFrame(ClientData clientData,
+ register Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[], int isLambda);
+static void ProcBodyDup(Tcl_Obj *srcPtr, Tcl_Obj *dupPtr);
+static void ProcBodyFree(Tcl_Obj *objPtr);
+static int ProcWrongNumArgs(Tcl_Interp *interp, int skip);
+static void MakeProcError(Tcl_Interp *interp,
+ Tcl_Obj *procNameObj);
+static void MakeLambdaError(Tcl_Interp *interp,
+ Tcl_Obj *procNameObj);
+static int SetLambdaFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
+static int ProcCompileProc(Tcl_Interp *interp, Proc *procPtr,
+ Tcl_Obj *bodyPtr, Namespace *nsPtr,
+ CONST char *description, CONST char *procName,
+ Proc **procPtrPtr);
/*
* The ProcBodyObjType type
@@ -39,10 +51,44 @@ static int TclCompileNoOp _ANSI_ARGS_((Tcl_Interp *interp,
Tcl_ObjType tclProcBodyType = {
"procbody", /* name for this type */
- ProcBodyFree, /* FreeInternalRep procedure */
- ProcBodyDup, /* DupInternalRep procedure */
- ProcBodyUpdateString, /* UpdateString procedure */
- ProcBodySetFromAny /* SetFromAny procedure */
+ ProcBodyFree, /* FreeInternalRep function */
+ ProcBodyDup, /* DupInternalRep function */
+ NULL, /* UpdateString function; Tcl_GetString and
+ * Tcl_GetStringFromObj should panic
+ * instead. */
+ NULL /* SetFromAny function; Tcl_ConvertToType
+ * should panic instead. */
+};
+
+/*
+ * The [upvar]/[uplevel] level reference type. Uses the twoPtrValue field,
+ * encoding the type of level reference in ptr1 and the actual parsed out
+ * offset in ptr2.
+ *
+ * Uses the default behaviour throughout, and never disposes of the string
+ * rep; it's just a cache type.
+ */
+
+static Tcl_ObjType levelReferenceType = {
+ "levelReference",
+ NULL, NULL, NULL, NULL
+};
+
+/*
+ * The type of lambdas. Note that every lambda will *always* have a string
+ * representation.
+ *
+ * Internally, ptr1 is a pointer to a Proc instance that is not bound to a
+ * command name, and ptr2 is a pointer to the namespace that the Proc instance
+ * will execute within.
+ */
+
+static Tcl_ObjType lambdaType = {
+ "lambdaExpr", /* name */
+ FreeLambdaInternalRep, /* freeIntRepProc */
+ DupLambdaInternalRep, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ SetLambdaFromAny /* setFromAnyProc */
};
/*
@@ -50,7 +96,7 @@ Tcl_ObjType tclProcBodyType = {
*
* Tcl_ProcObjCmd --
*
- * This object-based procedure is invoked to process the "proc" Tcl
+ * This object-based function is invoked to process the "proc" Tcl
* command. See the user documentation for details on what it does.
*
* Results:
@@ -64,11 +110,11 @@ Tcl_ObjType tclProcBodyType = {
/* ARGSUSED */
int
-Tcl_ProcObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_ProcObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
register Interp *iPtr = (Interp *) interp;
Proc *procPtr;
@@ -84,47 +130,48 @@ Tcl_ProcObjCmd(dummy, interp, objc, objv)
}
/*
- * Determine the namespace where the procedure should reside. Unless
- * the command name includes namespace qualifiers, this will be the
- * current namespace.
+ * Determine the namespace where the procedure should reside. Unless the
+ * command name includes namespace qualifiers, this will be the current
+ * namespace.
*/
fullName = TclGetString(objv[1]);
- TclGetNamespaceForQualName(interp, fullName, (Namespace *) NULL,
- 0, &nsPtr, &altNsPtr, &cxtNsPtr, &procName);
+ TclGetNamespaceForQualName(interp, fullName, NULL, 0,
+ &nsPtr, &altNsPtr, &cxtNsPtr, &procName);
if (nsPtr == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "can't create procedure \"", fullName,
- "\": unknown namespace", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "can't create procedure \"", fullName,
+ "\": unknown namespace", NULL);
+ return TCL_ERROR;
}
if (procName == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "can't create procedure \"", fullName,
- "\": bad procedure name", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "can't create procedure \"", fullName,
+ "\": bad procedure name", NULL);
+ return TCL_ERROR;
}
if ((nsPtr != iPtr->globalNsPtr)
&& (procName != NULL) && (procName[0] == ':')) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "can't create procedure \"", procName,
+ Tcl_AppendResult(interp, "can't create procedure \"", procName,
"\" in non-global namespace with name starting with \":\"",
- (char *) NULL);
- return TCL_ERROR;
+ NULL);
+ return TCL_ERROR;
}
/*
- * Create the data structure to represent the procedure.
+ * Create the data structure to represent the procedure.
*/
+
if (TclCreateProc(interp, nsPtr, procName, objv[2], objv[3],
- &procPtr) != TCL_OK) {
- return TCL_ERROR;
+ &procPtr) != TCL_OK) {
+ Tcl_AddErrorInfo(interp, "\n (creating proc \"");
+ Tcl_AddErrorInfo(interp, procName);
+ Tcl_AddErrorInfo(interp, "\")");
+ return TCL_ERROR;
}
/*
- * Now create a command for the procedure. This will initially be in
- * the current namespace unless the procedure's name included namespace
+ * Now create a command for the procedure. This will initially be in the
+ * current namespace unless the procedure's name included namespace
* qualifiers. To create the new command in the right namespace, we
* generate a fully qualified name for it.
*/
@@ -136,12 +183,11 @@ Tcl_ProcObjCmd(dummy, interp, objc, objv)
}
Tcl_DStringAppend(&ds, procName, -1);
- Tcl_CreateCommand(interp, Tcl_DStringValue(&ds), TclProcInterpProc,
- (ClientData) procPtr, TclProcDeleteProc);
cmd = Tcl_CreateObjCommand(interp, Tcl_DStringValue(&ds),
TclObjInterpProc, (ClientData) procPtr, TclProcDeleteProc);
Tcl_DStringFree(&ds);
+
/*
* Now initialize the new procedure's cmdPtr field. This will be used
* later when the procedure is called to determine what namespace the
@@ -151,113 +197,133 @@ Tcl_ProcObjCmd(dummy, interp, objc, objv)
procPtr->cmdPtr = (Command *) cmd;
-#ifdef TCL_TIP280
- /* TIP #280 Remember the line the procedure body is starting on. In a
- * Byte code context we ask the engine to provide us with the necessary
+ /*
+ * TIP #280: Remember the line the procedure body is starting on. In a
+ * bytecode context we ask the engine to provide us with the necessary
* information. This is for the initialization of the byte code compiler
* when the body is used for the first time.
+ *
+ * This code is nearly identical to the #280 code in SetLambdaFromAny, see
+ * this file. The differences are the different index of the body in the
+ * line array of the context, and the lamdba code requires some special
+ * processing. Find a way to factor the common elements into a single
+ * function.
*/
if (iPtr->cmdFramePtr) {
- CmdFrame context = *iPtr->cmdFramePtr;
-
- if (context.type == TCL_LOCATION_BC) {
- TclGetSrcInfoForPc (&context);
- /* May get path in context */
- } else if (context.type == TCL_LOCATION_SOURCE) {
- /* context now holds another reference */
- Tcl_IncrRefCount (context.data.eval.path);
- }
+ CmdFrame *contextPtr;
- /* type == TCL_LOCATION_PREBC implies that 'line' is NULL here! We
- * cannot assume that 'line' is valid here, we have to check. If the
- * outer context is an eval (bc, prebc, eval) we do not save any
- * information. Counting relative to the beginning of the proc body is
- * more sensible than counting relative to the outer eval block.
- */
+ contextPtr = (CmdFrame *) TclStackAlloc(interp, sizeof(CmdFrame));
+ *contextPtr = *iPtr->cmdFramePtr;
- if ((context.type == TCL_LOCATION_SOURCE) &&
- context.line &&
- (context.nline >= 4) &&
- (context.line [3] >= 0)) {
- int isNew;
- Tcl_HashEntry* hePtr;
- CmdFrame* cfPtr = (CmdFrame*) ckalloc (sizeof (CmdFrame));
-
- cfPtr->level = -1;
- cfPtr->type = context.type;
- cfPtr->line = (int*) ckalloc (sizeof (int));
- cfPtr->line [0] = context.line [3];
- cfPtr->nline = 1;
- cfPtr->framePtr = NULL;
- cfPtr->nextPtr = NULL;
-
- if (context.type == TCL_LOCATION_SOURCE) {
- cfPtr->data.eval.path = context.data.eval.path;
- /* Transfer of reference. The reference going away (release of
- * the context) is replaced by the reference in the
- * constructed cmdframe */
- } else {
- cfPtr->type = TCL_LOCATION_EVAL;
- cfPtr->data.eval.path = NULL;
- }
+ if (contextPtr->type == TCL_LOCATION_BC) {
+ /*
+ * Retrieve source information from the bytecode, if possible. If
+ * the information is retrieved successfully, context.type will be
+ * TCL_LOCATION_SOURCE and the reference held by
+ * context.data.eval.path will be counted.
+ */
- cfPtr->cmd.str.cmd = NULL;
- cfPtr->cmd.str.len = 0;
+ TclGetSrcInfoForPc(contextPtr);
+ } else if (contextPtr->type == TCL_LOCATION_SOURCE) {
+ /*
+ * The copy into 'context' up above has created another reference
+ * to 'context.data.eval.path'; account for it.
+ */
- hePtr = Tcl_CreateHashEntry (iPtr->linePBodyPtr, (char*) procPtr,
- &isNew);
- if (!isNew) {
- /*
- * Get the old command frame and release it. See also
- * TclProcCleanupProc in this file. Currently it seems as if
- * only the procbodytest::proc command of the testsuite is
- * able to trigger this situation.
- */
+ Tcl_IncrRefCount(contextPtr->data.eval.path);
+ }
+
+ if (contextPtr->type == TCL_LOCATION_SOURCE) {
+ /*
+ * We can account for source location within a proc only if the
+ * proc body was not created by substitution.
+ */
+
+ if (contextPtr->line
+ && (contextPtr->nline >= 4) && (contextPtr->line[3] >= 0)) {
+ int isNew;
+ Tcl_HashEntry* hePtr;
+ CmdFrame *cfPtr = (CmdFrame *) ckalloc(sizeof(CmdFrame));
+
+ cfPtr->level = -1;
+ cfPtr->type = contextPtr->type;
+ cfPtr->line = (int *) ckalloc(sizeof(int));
+ cfPtr->line[0] = contextPtr->line[3];
+ cfPtr->nline = 1;
+ cfPtr->framePtr = NULL;
+ cfPtr->nextPtr = NULL;
+
+ cfPtr->data.eval.path = contextPtr->data.eval.path;
+ Tcl_IncrRefCount(cfPtr->data.eval.path);
+
+ cfPtr->cmd.str.cmd = NULL;
+ cfPtr->cmd.str.len = 0;
+
+ hePtr = Tcl_CreateHashEntry(iPtr->linePBodyPtr, (char *) procPtr, &isNew);
+ if (!isNew) {
+ /*
+ * Get the old command frame and release it. See also
+ * TclProcCleanupProc in this file. Currently it seems as
+ * if only the procbodytest::proc command of the testsuite
+ * is able to trigger this situation.
+ */
- CmdFrame* cfOldPtr = (CmdFrame *) Tcl_GetHashValue(hePtr);
+ CmdFrame* cfOldPtr = (CmdFrame *) Tcl_GetHashValue(hePtr);
- if (cfOldPtr->type == TCL_LOCATION_SOURCE) {
- Tcl_DecrRefCount(cfOldPtr->data.eval.path);
- cfOldPtr->data.eval.path = NULL;
+ if (cfOldPtr->type == TCL_LOCATION_SOURCE) {
+ Tcl_DecrRefCount(cfOldPtr->data.eval.path);
+ cfOldPtr->data.eval.path = NULL;
+ }
+ ckfree((char *) cfOldPtr->line);
+ cfOldPtr->line = NULL;
+ ckfree((char *) cfOldPtr);
}
- ckfree((char *) cfOldPtr->line);
- cfOldPtr->line = NULL;
- ckfree((char *) cfOldPtr);
+ Tcl_SetHashValue(hePtr, cfPtr);
}
- Tcl_SetHashValue (hePtr, cfPtr);
+
+ /*
+ * 'contextPtr' is going out of scope; account for the reference that
+ * it's holding to the path name.
+ */
+
+ Tcl_DecrRefCount(contextPtr->data.eval.path);
+ contextPtr->data.eval.path = NULL;
}
+ TclStackFree(interp, contextPtr);
}
-#endif
/*
- * Optimize for noop procs: if the body is not precompiled (like a TclPro
+ * Optimize for no-op procs: if the body is not precompiled (like a TclPro
* procbody), and the argument list is just "args" and the body is empty,
- * define a compileProc to compile a noop.
+ * define a compileProc to compile a no-op.
*
* Notes:
- * - cannot be done for any argument list without having different
- * compiled/not-compiled behaviour in the "wrong argument #" case,
- * or making this code much more complicated. In any case, it doesn't
- * seem to make a lot of sense to verify the number of arguments we
- * are about to ignore ...
- * - could be enhanced to handle also non-empty bodies that contain
- * only comments; however, parsing the body will slow down the
- * compilation of all procs whose argument list is just _args_ */
+ * - cannot be done for any argument list without having different
+ * compiled/not-compiled behaviour in the "wrong argument #" case, or
+ * making this code much more complicated. In any case, it doesn't
+ * seem to make a lot of sense to verify the number of arguments we
+ * are about to ignore ...
+ * - could be enhanced to handle also non-empty bodies that contain only
+ * comments; however, parsing the body will slow down the compilation
+ * of all procs whose argument list is just _args_
+ */
if (objv[3]->typePtr == &tclProcBodyType) {
goto done;
}
- procArgs = Tcl_GetString(objv[2]);
+ procArgs = TclGetString(objv[2]);
while (*procArgs == ' ') {
procArgs++;
}
if ((procArgs[0] == 'a') && (strncmp(procArgs, "args", 4) == 0)) {
+ int numBytes;
+
procArgs +=4;
- while(*procArgs != '\0') {
+ while (*procArgs != '\0') {
if (*procArgs != ' ') {
goto done;
}
@@ -268,12 +334,9 @@ Tcl_ProcObjCmd(dummy, interp, objc, objv)
* The argument list is just "args"; check the body
*/
- procBody = Tcl_GetString(objv[3]);
- while (*procBody != '\0') {
- if (!isspace(UCHAR(*procBody))) {
- goto done;
- }
- procBody++;
+ procBody = Tcl_GetStringFromObj(objv[3], &numBytes);
+ if (TclParseAllWhiteSpace(procBody, numBytes) < numBytes) {
+ goto done;
}
/*
@@ -283,7 +346,7 @@ Tcl_ProcObjCmd(dummy, interp, objc, objv)
((Command *) cmd)->compileProc = TclCompileNoOp;
}
- done:
+ done:
return TCL_OK;
}
@@ -292,34 +355,35 @@ Tcl_ProcObjCmd(dummy, interp, objc, objv)
*
* TclCreateProc --
*
- * Creates the data associated with a Tcl procedure definition.
- * This procedure knows how to handle two types of body objects:
- * strings and procbody. Strings are the traditional (and common) value
- * for bodies, procbody are values created by extensions that have
- * loaded a previously compiled script.
+ * Creates the data associated with a Tcl procedure definition. This
+ * function knows how to handle two types of body objects: strings and
+ * procbody. Strings are the traditional (and common) value for bodies,
+ * procbody are values created by extensions that have loaded a
+ * previously compiled script.
*
* Results:
- * Returns TCL_OK on success, along with a pointer to a Tcl
- * procedure definition in procPtrPtr. This definition should
- * be freed by calling TclCleanupProc() when it is no longer
- * needed. Returns TCL_ERROR if anything goes wrong.
+ * Returns TCL_OK on success, along with a pointer to a Tcl procedure
+ * definition in procPtrPtr where the cmdPtr field is not initialised.
+ * This definition should be freed by calling TclProcCleanupProc() when
+ * it is no longer needed. Returns TCL_ERROR if anything goes wrong.
*
* Side effects:
- * If anything goes wrong, this procedure returns an error
- * message in the interpreter.
+ * If anything goes wrong, this function returns an error message in the
+ * interpreter.
*
*----------------------------------------------------------------------
*/
+
int
-TclCreateProc(interp, nsPtr, procName, argsPtr, bodyPtr, procPtrPtr)
- Tcl_Interp *interp; /* interpreter containing proc */
- Namespace *nsPtr; /* namespace containing this proc */
- CONST char *procName; /* unqualified name of this proc */
- Tcl_Obj *argsPtr; /* description of arguments */
- Tcl_Obj *bodyPtr; /* command body */
- Proc **procPtrPtr; /* returns: pointer to proc data */
+TclCreateProc(
+ Tcl_Interp *interp, /* Interpreter containing proc. */
+ Namespace *nsPtr, /* Namespace containing this proc. */
+ CONST char *procName, /* Unqualified name of this proc. */
+ Tcl_Obj *argsPtr, /* Description of arguments. */
+ Tcl_Obj *bodyPtr, /* Command body. */
+ Proc **procPtrPtr) /* Returns: pointer to proc data. */
{
- Interp *iPtr = (Interp*)interp;
+ Interp *iPtr = (Interp *) interp;
CONST char **argArray = NULL;
register Proc *procPtr;
@@ -330,46 +394,44 @@ TclCreateProc(interp, nsPtr, procName, argsPtr, bodyPtr, procPtrPtr)
int precompiled = 0;
if (bodyPtr->typePtr == &tclProcBodyType) {
- /*
- * Because the body is a TclProProcBody, the actual body is already
- * compiled, and it is not shared with anyone else, so it's OK not to
- * unshare it (as a matter of fact, it is bad to unshare it, because
- * there may be no source code).
- *
- * We don't create and initialize a Proc structure for the procedure;
- * rather, we use what is in the body object. Note that
- * we initialize its cmdPtr field below after we've created the command
- * for the procedure. We increment the ref count of the Proc struct
- * since the command (soon to be created) will be holding a reference
- * to it.
- */
-
- procPtr = (Proc *) bodyPtr->internalRep.otherValuePtr;
- procPtr->iPtr = iPtr;
- procPtr->refCount++;
- precompiled = 1;
+ /*
+ * Because the body is a TclProProcBody, the actual body is already
+ * compiled, and it is not shared with anyone else, so it's OK not to
+ * unshare it (as a matter of fact, it is bad to unshare it, because
+ * there may be no source code).
+ *
+ * We don't create and initialize a Proc structure for the procedure;
+ * rather, we use what is in the body object. We increment the ref
+ * count of the Proc struct since the command (soon to be created)
+ * will be holding a reference to it.
+ */
+
+ procPtr = bodyPtr->internalRep.otherValuePtr;
+ procPtr->iPtr = iPtr;
+ procPtr->refCount++;
+ precompiled = 1;
} else {
- /*
- * If the procedure's body object is shared because its string value is
- * identical to, e.g., the body of another procedure, we must create a
- * private copy for this procedure to use. Such sharing of procedure
- * bodies is rare but can cause problems. A procedure body is compiled
- * in a context that includes the number of compiler-allocated "slots"
- * for local variables. Each formal parameter is given a local variable
- * slot (the "procPtr->numCompiledLocals = numArgs" assignment
- * below). This means that the same code can not be shared by two
- * procedures that have a different number of arguments, even if their
- * bodies are identical. Note that we don't use Tcl_DuplicateObj since
- * we would not want any bytecode internal representation.
- */
-
- if (Tcl_IsShared(bodyPtr)) {
-#ifdef TCL_TIP280
+ /*
+ * If the procedure's body object is shared because its string value
+ * is identical to, e.g., the body of another procedure, we must
+ * create a private copy for this procedure to use. Such sharing of
+ * procedure bodies is rare but can cause problems. A procedure body
+ * is compiled in a context that includes the number of "slots"
+ * allocated by the compiler for local variables. There is a local
+ * variable slot for each formal parameter (the
+ * "procPtr->numCompiledLocals = numArgs" assignment below). This
+ * means that the same code can not be shared by two procedures that
+ * have a different number of arguments, even if their bodies are
+ * identical. Note that we don't use Tcl_DuplicateObj since we would
+ * not want any bytecode internal representation.
+ */
+
+ if (Tcl_IsShared(bodyPtr)) {
Tcl_Obj* sharedBodyPtr = bodyPtr;
-#endif
- bytes = Tcl_GetStringFromObj(bodyPtr, &length);
- bodyPtr = Tcl_NewStringObj(bytes, length);
-#ifdef TCL_TIP280
+
+ bytes = TclGetStringFromObj(bodyPtr, &length);
+ bodyPtr = Tcl_NewStringObj(bytes, length);
+
/*
* TIP #280.
* Ensure that the continuation line data for the original body is
@@ -377,121 +439,111 @@ TclCreateProc(interp, nsPtr, procName, argsPtr, bodyPtr, procPtrPtr)
*/
TclContinuationsCopy (bodyPtr, sharedBodyPtr);
-#endif
- }
+ }
- /*
- * Create and initialize a Proc structure for the procedure. Note that
- * we initialize its cmdPtr field below after we've created the command
- * for the procedure. We increment the ref count of the procedure's
- * body object since there will be a reference to it in the Proc
- * structure.
- */
+ /*
+ * Create and initialize a Proc structure for the procedure. We
+ * increment the ref count of the procedure's body object since there
+ * will be a reference to it in the Proc structure.
+ */
- Tcl_IncrRefCount(bodyPtr);
+ Tcl_IncrRefCount(bodyPtr);
- procPtr = (Proc *) ckalloc(sizeof(Proc));
- procPtr->iPtr = iPtr;
- procPtr->refCount = 1;
- procPtr->bodyPtr = bodyPtr;
- procPtr->numArgs = 0; /* actual argument count is set below. */
- procPtr->numCompiledLocals = 0;
- procPtr->firstLocalPtr = NULL;
- procPtr->lastLocalPtr = NULL;
+ procPtr = (Proc *) ckalloc(sizeof(Proc));
+ procPtr->iPtr = iPtr;
+ procPtr->refCount = 1;
+ procPtr->bodyPtr = bodyPtr;
+ procPtr->numArgs = 0; /* Actual argument count is set below. */
+ procPtr->numCompiledLocals = 0;
+ procPtr->firstLocalPtr = NULL;
+ procPtr->lastLocalPtr = NULL;
}
/*
- * Break up the argument list into argument specifiers, then process
- * each argument specifier.
- * If the body is precompiled, processing is limited to checking that
- * the the parsed argument is consistent with the one stored in the
- * Proc.
- * THIS FAILS IF THE ARG LIST OBJECT'S STRING REP CONTAINS NULLS.
+ * Break up the argument list into argument specifiers, then process each
+ * argument specifier. If the body is precompiled, processing is limited
+ * to checking that the parsed argument is consistent with the one stored
+ * in the Proc.
+ *
+ * THIS FAILS IF THE ARG LIST OBJECT'S STRING REP CONTAINS NULS.
*/
- args = Tcl_GetStringFromObj(argsPtr, &length);
+ args = TclGetStringFromObj(argsPtr, &length);
result = Tcl_SplitList(interp, args, &numArgs, &argArray);
if (result != TCL_OK) {
- goto procError;
+ goto procError;
}
if (precompiled) {
- if (numArgs > procPtr->numArgs) {
- char buf[64 + TCL_INTEGER_SPACE + TCL_INTEGER_SPACE];
- sprintf(buf, "\": arg list contains %d entries, precompiled header expects %d",
- numArgs, procPtr->numArgs);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "procedure \"", procName,
- buf, (char *) NULL);
- goto procError;
- }
- localPtr = procPtr->firstLocalPtr;
+ if (numArgs > procPtr->numArgs) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "procedure \"%s\": arg list contains %d entries, "
+ "precompiled header expects %d", procName, numArgs,
+ procPtr->numArgs));
+ goto procError;
+ }
+ localPtr = procPtr->firstLocalPtr;
} else {
- procPtr->numArgs = numArgs;
- procPtr->numCompiledLocals = numArgs;
- }
- for (i = 0; i < numArgs; i++) {
- int fieldCount, nameLength, valueLength;
- CONST char **fieldValues;
-
- /*
- * Now divide the specifier up into name and default.
- */
-
- result = Tcl_SplitList(interp, argArray[i], &fieldCount,
- &fieldValues);
- if (result != TCL_OK) {
- goto procError;
- }
- if (fieldCount > 2) {
- ckfree((char *) fieldValues);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "too many fields in argument specifier \"",
- argArray[i], "\"", (char *) NULL);
- goto procError;
- }
- if ((fieldCount == 0) || (*fieldValues[0] == 0)) {
- ckfree((char *) fieldValues);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "procedure \"", procName,
- "\" has argument with no name", (char *) NULL);
- goto procError;
- }
-
- nameLength = strlen(fieldValues[0]);
- if (fieldCount == 2) {
- valueLength = strlen(fieldValues[1]);
- } else {
- valueLength = 0;
- }
-
- /*
- * Check that the formal parameter name is a scalar.
- */
-
- p = fieldValues[0];
- while (*p != '\0') {
- if (*p == '(') {
- CONST char *q = p;
- do {
+ procPtr->numArgs = numArgs;
+ procPtr->numCompiledLocals = numArgs;
+ }
+
+ for (i = 0; i < numArgs; i++) {
+ int fieldCount, nameLength, valueLength;
+ CONST char **fieldValues;
+
+ /*
+ * Now divide the specifier up into name and default.
+ */
+
+ result = Tcl_SplitList(interp, argArray[i], &fieldCount,
+ &fieldValues);
+ if (result != TCL_OK) {
+ goto procError;
+ }
+ if (fieldCount > 2) {
+ ckfree((char *) fieldValues);
+ Tcl_AppendResult(interp,
+ "too many fields in argument specifier \"",
+ argArray[i], "\"", NULL);
+ goto procError;
+ }
+ if ((fieldCount == 0) || (*fieldValues[0] == 0)) {
+ ckfree((char *) fieldValues);
+ Tcl_AppendResult(interp, "argument with no name", NULL);
+ goto procError;
+ }
+
+ nameLength = strlen(fieldValues[0]);
+ if (fieldCount == 2) {
+ valueLength = strlen(fieldValues[1]);
+ } else {
+ valueLength = 0;
+ }
+
+ /*
+ * Check that the formal parameter name is a scalar.
+ */
+
+ p = fieldValues[0];
+ while (*p != '\0') {
+ if (*p == '(') {
+ CONST char *q = p;
+ do {
q++;
} while (*q != '\0');
q--;
- if (*q == ')') { /* we have an array element */
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "procedure \"", procName,
- "\" has formal parameter \"", fieldValues[0],
- "\" that is an array element",
- (char *) NULL);
+ if (*q == ')') { /* We have an array element. */
+ Tcl_AppendResult(interp, "formal parameter \"",
+ fieldValues[0],
+ "\" is an array element", NULL);
ckfree((char *) fieldValues);
goto procError;
}
} else if ((*p == ':') && (*(p+1) == ':')) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "procedure \"", procName,
- "\" has formal parameter \"", fieldValues[0],
- "\" that is not a simple name",
- (char *) NULL);
+ Tcl_AppendResult(interp, "formal parameter \"",
+ fieldValues[0],
+ "\" is not a simple name", NULL);
ckfree((char *) fieldValues);
goto procError;
}
@@ -500,116 +552,117 @@ TclCreateProc(interp, nsPtr, procName, argsPtr, bodyPtr, procPtrPtr)
if (precompiled) {
/*
- * Compare the parsed argument with the stored one.
- * For the flags, we and out VAR_UNDEFINED to support bridging
- * precompiled <= 8.3 code in 8.4 where this is now used as an
- * optimization indicator. Yes, this is a hack. -- hobbs
+ * Compare the parsed argument with the stored one. Note that the
+ * only flag value that makes sense at this point is VAR_ARGUMENT
+ * (its value was kept the same as pre VarReform to simplify
+ * tbcload's processing of older byetcodes).
+ *
+ * The only other flag vlaue that is important to retrieve from
+ * precompiled procs is VAR_TEMPORARY (also unchanged). It is
+ * needed later when retrieving the variable names.
*/
if ((localPtr->nameLength != nameLength)
|| (strcmp(localPtr->name, fieldValues[0]))
|| (localPtr->frameIndex != i)
- || ((localPtr->flags & ~VAR_UNDEFINED)
- != (VAR_SCALAR | VAR_ARGUMENT))
- || ((localPtr->defValuePtr == NULL)
- && (fieldCount == 2))
- || ((localPtr->defValuePtr != NULL)
- && (fieldCount != 2))) {
- char buf[80 + TCL_INTEGER_SPACE];
- sprintf(buf, "\": formal parameter %d is inconsistent with precompiled body",
- i);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "procedure \"", procName,
- buf, (char *) NULL);
+ || !(localPtr->flags & VAR_ARGUMENT)
+ || (localPtr->defValuePtr == NULL && fieldCount == 2)
+ || (localPtr->defValuePtr != NULL && fieldCount != 2)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "procedure \"%s\": formal parameter %d is "
+ "inconsistent with precompiled body", procName, i));
ckfree((char *) fieldValues);
goto procError;
}
- /*
- * compare the default value if any
- */
-
- if (localPtr->defValuePtr != NULL) {
- int tmpLength;
- char *tmpPtr = Tcl_GetStringFromObj(localPtr->defValuePtr,
- &tmpLength);
- if ((valueLength != tmpLength)
- || (strncmp(fieldValues[1], tmpPtr,
- (size_t) tmpLength))) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "procedure \"", procName,
- "\": formal parameter \"",
- fieldValues[0],
- "\" has default value inconsistent with precompiled body",
- (char *) NULL);
- ckfree((char *) fieldValues);
- goto procError;
- }
- }
-
- localPtr = localPtr->nextPtr;
- } else {
- /*
- * Allocate an entry in the runtime procedure frame's array of
- * local variables for the argument.
- */
-
- localPtr = (CompiledLocal *) ckalloc((unsigned)
- (sizeof(CompiledLocal) - sizeof(localPtr->name)
- + nameLength+1));
- if (procPtr->firstLocalPtr == NULL) {
- procPtr->firstLocalPtr = procPtr->lastLocalPtr = localPtr;
- } else {
- procPtr->lastLocalPtr->nextPtr = localPtr;
- procPtr->lastLocalPtr = localPtr;
- }
- localPtr->nextPtr = NULL;
- localPtr->nameLength = nameLength;
- localPtr->frameIndex = i;
- localPtr->flags = VAR_SCALAR | VAR_ARGUMENT;
- localPtr->resolveInfo = NULL;
-
- if (fieldCount == 2) {
- localPtr->defValuePtr =
- Tcl_NewStringObj(fieldValues[1], valueLength);
- Tcl_IncrRefCount(localPtr->defValuePtr);
- } else {
- localPtr->defValuePtr = NULL;
- }
- memcpy(localPtr->name, fieldValues[0], nameLength + 1);
+ /*
+ * Compare the default value if any.
+ */
+
+ if (localPtr->defValuePtr != NULL) {
+ int tmpLength;
+ char *tmpPtr = TclGetStringFromObj(localPtr->defValuePtr,
+ &tmpLength);
+
+ if ((valueLength != tmpLength) ||
+ strncmp(fieldValues[1], tmpPtr, (size_t) tmpLength)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "procedure \"%s\": formal parameter \"%s\" has "
+ "default value inconsistent with precompiled body",
+ procName, fieldValues[0]));
+ ckfree((char *) fieldValues);
+ goto procError;
+ }
+ }
+ if ((i == numArgs - 1)
+ && (localPtr->nameLength == 4)
+ && (localPtr->name[0] == 'a')
+ && (strcmp(localPtr->name, "args") == 0)) {
+ localPtr->flags |= VAR_IS_ARGS;
+ }
+
+ localPtr = localPtr->nextPtr;
+ } else {
+ /*
+ * Allocate an entry in the runtime procedure frame's array of
+ * local variables for the argument.
+ */
+
+ localPtr = (CompiledLocal *) ckalloc((unsigned)
+ (sizeof(CompiledLocal) - sizeof(localPtr->name)
+ + nameLength + 1));
+ if (procPtr->firstLocalPtr == NULL) {
+ procPtr->firstLocalPtr = procPtr->lastLocalPtr = localPtr;
+ } else {
+ procPtr->lastLocalPtr->nextPtr = localPtr;
+ procPtr->lastLocalPtr = localPtr;
+ }
+ localPtr->nextPtr = NULL;
+ localPtr->nameLength = nameLength;
+ localPtr->frameIndex = i;
+ localPtr->flags = VAR_ARGUMENT;
+ localPtr->resolveInfo = NULL;
+
+ if (fieldCount == 2) {
+ localPtr->defValuePtr =
+ Tcl_NewStringObj(fieldValues[1], valueLength);
+ Tcl_IncrRefCount(localPtr->defValuePtr);
+ } else {
+ localPtr->defValuePtr = NULL;
+ }
+ memcpy(localPtr->name, fieldValues[0], nameLength + 1);
+ if ((i == numArgs - 1)
+ && (localPtr->nameLength == 4)
+ && (localPtr->name[0] == 'a')
+ && (strcmp(localPtr->name, "args") == 0)) {
+ localPtr->flags |= VAR_IS_ARGS;
+ }
}
- ckfree((char *) fieldValues);
+ ckfree((char *) fieldValues);
}
- /*
- * Now initialize the new procedure's cmdPtr field. This will be used
- * later when the procedure is called to determine what namespace the
- * procedure will run in. This will be different than the current
- * namespace if the proc was renamed into a different namespace.
- */
-
*procPtrPtr = procPtr;
ckfree((char *) argArray);
return TCL_OK;
-procError:
+ procError:
if (precompiled) {
- procPtr->refCount--;
+ procPtr->refCount--;
} else {
- Tcl_DecrRefCount(bodyPtr);
- while (procPtr->firstLocalPtr != NULL) {
- localPtr = procPtr->firstLocalPtr;
- procPtr->firstLocalPtr = localPtr->nextPtr;
+ Tcl_DecrRefCount(bodyPtr);
+ while (procPtr->firstLocalPtr != NULL) {
+ localPtr = procPtr->firstLocalPtr;
+ procPtr->firstLocalPtr = localPtr->nextPtr;
- defPtr = localPtr->defValuePtr;
- if (defPtr != NULL) {
- Tcl_DecrRefCount(defPtr);
- }
+ defPtr = localPtr->defValuePtr;
+ if (defPtr != NULL) {
+ Tcl_DecrRefCount(defPtr);
+ }
- ckfree((char *) localPtr);
- }
- ckfree((char *) procPtr);
+ ckfree((char *) localPtr);
+ }
+ ckfree((char *) procPtr);
}
if (argArray != NULL) {
ckfree((char *) argArray);
@@ -622,19 +675,19 @@ procError:
*
* TclGetFrame --
*
- * Given a description of a procedure frame, such as the first
- * argument to an "uplevel" or "upvar" command, locate the
- * call frame for the appropriate level of procedure.
+ * Given a description of a procedure frame, such as the first argument
+ * to an "uplevel" or "upvar" command, locate the call frame for the
+ * appropriate level of procedure.
*
* Results:
- * The return value is -1 if an error occurred in finding the frame
- * (in this case an error message is left in the interp's result).
- * 1 is returned if string was either a number or a number preceded
- * by "#" and it specified a valid frame. 0 is returned if string
- * isn't one of the two things above (in this case, the lookup
- * acts as if string were "1"). The variable pointed to by
- * framePtrPtr is filled in with the address of the desired frame
- * (unless an error occurs, in which case it isn't modified).
+ * The return value is -1 if an error occurred in finding the frame (in
+ * this case an error message is left in the interp's result). 1 is
+ * returned if string was either a number or a number preceded by "#" and
+ * it specified a valid frame. 0 is returned if string isn't one of the
+ * two things above (in this case, the lookup acts as if string were
+ * "1"). The variable pointed to by framePtrPtr is filled in with the
+ * address of the desired frame (unless an error occurs, in which case it
+ * isn't modified).
*
* Side effects:
* None.
@@ -643,11 +696,11 @@ procError:
*/
int
-TclGetFrame(interp, string, framePtrPtr)
- Tcl_Interp *interp; /* Interpreter in which to find frame. */
- CONST char *string; /* String describing frame. */
- CallFrame **framePtrPtr; /* Store pointer to frame here (or NULL
- * if global frame indicated). */
+TclGetFrame(
+ Tcl_Interp *interp, /* Interpreter in which to find frame. */
+ CONST char *name, /* String describing frame. */
+ CallFrame **framePtrPtr) /* Store pointer to frame here (or NULL if
+ * global frame indicated). */
{
register Interp *iPtr = (Interp *) interp;
int curLevel, level, result;
@@ -658,47 +711,166 @@ TclGetFrame(interp, string, framePtrPtr)
*/
result = 1;
- curLevel = (iPtr->varFramePtr == NULL) ? 0 : iPtr->varFramePtr->level;
- if (*string == '#') {
- if (Tcl_GetInt(interp, string+1, &level) != TCL_OK) {
- return -1;
+ curLevel = iPtr->varFramePtr->level;
+ if (*name== '#') {
+ if (Tcl_GetInt(interp, name+1, &level) != TCL_OK || level < 0) {
+ goto levelError;
+ }
+ } else if (isdigit(UCHAR(*name))) { /* INTL: digit */
+ if (Tcl_GetInt(interp, name, &level) != TCL_OK) {
+ goto levelError;
+ }
+ level = curLevel - level;
+ } else {
+ level = curLevel - 1;
+ result = 0;
+ }
+
+ /*
+ * Figure out which frame to use, and return it to the caller.
+ */
+
+ for (framePtr = iPtr->varFramePtr; framePtr != NULL;
+ framePtr = framePtr->callerVarPtr) {
+ if (framePtr->level == level) {
+ break;
+ }
+ }
+ if (framePtr == NULL) {
+ goto levelError;
+ }
+
+ *framePtrPtr = framePtr;
+ return result;
+
+ levelError:
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "bad level \"", name, "\"", NULL);
+ return -1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclObjGetFrame --
+ *
+ * Given a description of a procedure frame, such as the first argument
+ * to an "uplevel" or "upvar" command, locate the call frame for the
+ * appropriate level of procedure.
+ *
+ * Results:
+ * The return value is -1 if an error occurred in finding the frame (in
+ * this case an error message is left in the interp's result). 1 is
+ * returned if objPtr was either a number or a number preceded by "#" and
+ * it specified a valid frame. 0 is returned if objPtr isn't one of the
+ * two things above (in this case, the lookup acts as if objPtr were
+ * "1"). The variable pointed to by framePtrPtr is filled in with the
+ * address of the desired frame (unless an error occurs, in which case it
+ * isn't modified).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclObjGetFrame(
+ Tcl_Interp *interp, /* Interpreter in which to find frame. */
+ Tcl_Obj *objPtr, /* Object describing frame. */
+ CallFrame **framePtrPtr) /* Store pointer to frame here (or NULL if
+ * global frame indicated). */
+{
+ register Interp *iPtr = (Interp *) interp;
+ int curLevel, level, result;
+ CallFrame *framePtr;
+ CONST char *name = TclGetString(objPtr);
+
+ /*
+ * Parse object to figure out which level number to go to.
+ */
+
+ result = 1;
+ curLevel = iPtr->varFramePtr->level;
+ if (objPtr->typePtr == &levelReferenceType) {
+ if (PTR2INT(objPtr->internalRep.twoPtrValue.ptr1)) {
+ level = curLevel - PTR2INT(objPtr->internalRep.twoPtrValue.ptr2);
+ } else {
+ level = PTR2INT(objPtr->internalRep.twoPtrValue.ptr2);
}
if (level < 0) {
- levelError:
- Tcl_AppendResult(interp, "bad level \"", string, "\"",
- (char *) NULL);
- return -1;
+ goto levelError;
+ }
+ /* TODO: Consider skipping the typePtr checks */
+ } else if (objPtr->typePtr == &tclIntType
+#ifndef NO_WIDE_TYPE
+ || objPtr->typePtr == &tclWideIntType
+#endif
+ ) {
+ if (TclGetIntFromObj(NULL, objPtr, &level) != TCL_OK || level < 0) {
+ goto levelError;
+ }
+ level = curLevel - level;
+ } else if (*name == '#') {
+ if (Tcl_GetInt(interp, name+1, &level) != TCL_OK || level < 0) {
+ goto levelError;
}
- } else if (isdigit(UCHAR(*string))) { /* INTL: digit */
- if (Tcl_GetInt(interp, string, &level) != TCL_OK) {
+
+ /*
+ * Cache for future reference.
+ *
+ * TODO: Use the new ptrAndLongRep intrep
+ */
+
+ TclFreeIntRep(objPtr);
+ objPtr->typePtr = &levelReferenceType;
+ objPtr->internalRep.twoPtrValue.ptr1 = (void *) 0;
+ objPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(level);
+ } else if (isdigit(UCHAR(*name))) { /* INTL: digit */
+ if (Tcl_GetInt(interp, name, &level) != TCL_OK) {
return -1;
}
+
+ /*
+ * Cache for future reference.
+ *
+ * TODO: Use the new ptrAndLongRep intrep
+ */
+
+ TclFreeIntRep(objPtr);
+ objPtr->typePtr = &levelReferenceType;
+ objPtr->internalRep.twoPtrValue.ptr1 = (void *) 1;
+ objPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(level);
level = curLevel - level;
} else {
+ /*
+ * Don't cache as the object *isn't* a level reference.
+ */
+
level = curLevel - 1;
result = 0;
}
/*
- * Figure out which frame to use, and modify the interpreter so
- * its variables come from that frame.
+ * Figure out which frame to use, and return it to the caller.
*/
- if (level == 0) {
- framePtr = NULL;
- } else {
- for (framePtr = iPtr->varFramePtr; framePtr != NULL;
- framePtr = framePtr->callerVarPtr) {
- if (framePtr->level == level) {
- break;
- }
- }
- if (framePtr == NULL) {
- goto levelError;
+ for (framePtr = iPtr->varFramePtr; framePtr != NULL;
+ framePtr = framePtr->callerVarPtr) {
+ if (framePtr->level == level) {
+ break;
}
}
+ if (framePtr == NULL) {
+ goto levelError;
+ }
*framePtrPtr = framePtr;
return result;
+
+ levelError:
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "bad level \"", name, "\"", NULL);
+ return -1;
}
/*
@@ -706,8 +878,8 @@ TclGetFrame(interp, string, framePtrPtr)
*
* Tcl_UplevelObjCmd --
*
- * This object procedure is invoked to process the "uplevel" Tcl
- * command. See the user documentation for details on what it does.
+ * This object function is invoked to process the "uplevel" Tcl command.
+ * See the user documentation for details on what it does.
*
* Results:
* A standard Tcl object result value.
@@ -720,19 +892,18 @@ TclGetFrame(interp, string, framePtrPtr)
/* ARGSUSED */
int
-Tcl_UplevelObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_UplevelObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
register Interp *iPtr = (Interp *) interp;
- char *optLevel;
int result;
CallFrame *savedVarFramePtr, *framePtr;
if (objc < 2) {
- uplevelSyntax:
+ uplevelSyntax:
Tcl_WrongNumArgs(interp, 1, objv, "?level? command ?arg ...?");
return TCL_ERROR;
}
@@ -741,8 +912,7 @@ Tcl_UplevelObjCmd(dummy, interp, objc, objv)
* Find the level to use for executing the command.
*/
- optLevel = TclGetString(objv[1]);
- result = TclGetFrame(interp, optLevel, &framePtr);
+ result = TclObjGetFrame(interp, objv[1], &framePtr);
if (result == -1) {
return TCL_ERROR;
}
@@ -764,30 +934,30 @@ Tcl_UplevelObjCmd(dummy, interp, objc, objv)
*/
if (objc == 1) {
-#ifdef TCL_TIP280
- /* TIP #280. Make argument location available to eval'd script */
+ /*
+ * TIP #280. Make argument location available to eval'd script
+ */
+
CmdFrame* invoker = NULL;
int word = 0;
+
TclArgumentGet (interp, objv[0], &invoker, &word);
- result = TclEvalObjEx(interp, objv[0], TCL_EVAL_DIRECT, invoker, word);
-#else
- result = Tcl_EvalObjEx(interp, objv[0], TCL_EVAL_DIRECT);
-#endif
+ result = TclEvalObjEx(interp, objv[0], 0, invoker, word);
} else {
/*
* More than one argument: concatenate them together with spaces
- * between, then evaluate the result. Tcl_EvalObjEx will delete
- * the object when it decrements its refcount after eval'ing it.
+ * between, then evaluate the result. Tcl_EvalObjEx will delete the
+ * object when it decrements its refcount after eval'ing it.
*/
+
Tcl_Obj *objPtr;
objPtr = Tcl_ConcatObj(objc, objv);
result = Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_DIRECT);
}
if (result == TCL_ERROR) {
- char msg[32 + TCL_INTEGER_SPACE];
- sprintf(msg, "\n (\"uplevel\" body line %d)", interp->errorLine);
- Tcl_AddObjErrorInfo(interp, msg, -1);
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (\"uplevel\" body line %d)", interp->errorLine));
}
/*
@@ -803,18 +973,17 @@ Tcl_UplevelObjCmd(dummy, interp, objc, objv)
*
* TclFindProc --
*
- * Given the name of a procedure, return a pointer to the
- * record describing the procedure. The procedure will be
- * looked up using the usual rules: first in the current
- * namespace and then in the global namespace.
+ * Given the name of a procedure, return a pointer to the record
+ * describing the procedure. The procedure will be looked up using the
+ * usual rules: first in the current namespace and then in the global
+ * namespace.
*
* Results:
- * NULL is returned if the name doesn't correspond to any
- * procedure. Otherwise, the return value is a pointer to
- * the procedure's record. If the name is found but refers
- * to an imported command that points to a "real" procedure
- * defined in another namespace, a pointer to that "real"
- * procedure's structure is returned.
+ * NULL is returned if the name doesn't correspond to any procedure.
+ * Otherwise, the return value is a pointer to the procedure's record. If
+ * the name is found but refers to an imported command that points to a
+ * "real" procedure defined in another namespace, a pointer to that
+ * "real" procedure's structure is returned.
*
* Side effects:
* None.
@@ -823,18 +992,17 @@ Tcl_UplevelObjCmd(dummy, interp, objc, objv)
*/
Proc *
-TclFindProc(iPtr, procName)
- Interp *iPtr; /* Interpreter in which to look. */
- CONST char *procName; /* Name of desired procedure. */
+TclFindProc(
+ Interp *iPtr, /* Interpreter in which to look. */
+ CONST char *procName) /* Name of desired procedure. */
{
Tcl_Command cmd;
Tcl_Command origCmd;
Command *cmdPtr;
- cmd = Tcl_FindCommand((Tcl_Interp *) iPtr, procName,
- (Tcl_Namespace *) NULL, /*flags*/ 0);
+ cmd = Tcl_FindCommand((Tcl_Interp *) iPtr, procName, NULL, /*flags*/ 0);
if (cmd == (Tcl_Command) NULL) {
- return NULL;
+ return NULL;
}
cmdPtr = (Command *) cmd;
@@ -842,10 +1010,10 @@ TclFindProc(iPtr, procName)
if (origCmd != NULL) {
cmdPtr = (Command *) origCmd;
}
- if (cmdPtr->proc != TclProcInterpProc) {
+ if (cmdPtr->objProc != TclObjInterpProc) {
return NULL;
}
- return (Proc *) cmdPtr->clientData;
+ return (Proc *) cmdPtr->objClientData;
}
/*
@@ -856,9 +1024,9 @@ TclFindProc(iPtr, procName)
* Tells whether a command is a Tcl procedure or not.
*
* Results:
- * If the given command is actually a Tcl procedure, the
- * return value is the address of the record describing
- * the procedure. Otherwise the return value is 0.
+ * If the given command is actually a Tcl procedure, the return value is
+ * the address of the record describing the procedure. Otherwise the
+ * return value is 0.
*
* Side effects:
* None.
@@ -867,8 +1035,8 @@ TclFindProc(iPtr, procName)
*/
Proc *
-TclIsProc(cmdPtr)
- Command *cmdPtr; /* Command to test. */
+TclIsProc(
+ Command *cmdPtr) /* Command to test. */
{
Tcl_Command origCmd;
@@ -876,8 +1044,8 @@ TclIsProc(cmdPtr)
if (origCmd != NULL) {
cmdPtr = (Command *) origCmd;
}
- if (cmdPtr->proc == TclProcInterpProc) {
- return (Proc *) cmdPtr->clientData;
+ if (cmdPtr->objProc == TclObjInterpProc) {
+ return (Proc *) cmdPtr->objClientData;
}
return (Proc *) 0;
}
@@ -885,310 +1053,657 @@ TclIsProc(cmdPtr)
/*
*----------------------------------------------------------------------
*
- * TclProcInterpProc --
+ * InitArgsAndLocals --
*
- * When a Tcl procedure gets invoked with an argc/argv array of
- * strings, this routine gets invoked to interpret the procedure.
+ * This routine is invoked in order to initialize the arguments and other
+ * compiled locals table for a new call frame.
*
* Results:
- * A standard Tcl result value, usually TCL_OK.
+ * A standard Tcl result.
*
* Side effects:
- * Depends on the commands in the procedure.
+ * Allocates memory on the stack for the compiled local variables, the
+ * caller is responsible for freeing them. Initialises all variables. May
+ * invoke various name resolvers in order to determine which variables
+ * are being referenced at runtime.
*
*----------------------------------------------------------------------
*/
-int
-TclProcInterpProc(clientData, interp, argc, argv)
- ClientData clientData; /* Record describing procedure to be
- * interpreted. */
- Tcl_Interp *interp; /* Interpreter in which procedure was
- * invoked. */
- int argc; /* Count of number of arguments to this
- * procedure. */
- register CONST char **argv; /* Argument values. */
+static int
+ProcWrongNumArgs(
+ Tcl_Interp *interp, int skip)
{
- register Tcl_Obj *objPtr;
- register int i;
- int result;
+ CallFrame *framePtr = ((Interp *)interp)->varFramePtr;
+ register Proc *procPtr = framePtr->procPtr;
+ register Var *defPtr;
+ int localCt = procPtr->numCompiledLocals, numArgs, i;
+ Tcl_Obj **desiredObjs;
+ const char *final = NULL;
/*
- * This procedure generates an objv array for object arguments that hold
- * the argv strings. It starts out with stack-allocated space but uses
- * dynamically-allocated storage if needed.
+ * Build up desired argument list for Tcl_WrongNumArgs
*/
-#define NUM_ARGS 20
- Tcl_Obj *(objStorage[NUM_ARGS]);
- register Tcl_Obj **objv = objStorage;
-
- /*
- * Create the object argument array "objv". Make sure objv is large
- * enough to hold the objc arguments plus 1 extra for the zero
- * end-of-objv word.
- */
+ numArgs = framePtr->procPtr->numArgs;
+ desiredObjs = (Tcl_Obj **) TclStackAlloc(interp,
+ (int) sizeof(Tcl_Obj *) * (numArgs+1));
- if ((argc + 1) > NUM_ARGS) {
- objv = (Tcl_Obj **)
- ckalloc((unsigned)(argc + 1) * sizeof(Tcl_Obj *));
+ if (framePtr->isProcCallFrame & FRAME_IS_LAMBDA) {
+ desiredObjs[0] = Tcl_NewStringObj("lambdaExpr", -1);
+ } else {
+#ifdef AVOID_HACKS_FOR_ITCL
+ desiredObjs[0] = framePtr->objv[skip-1];
+#else
+ desiredObjs[0] = Tcl_NewListObj(skip, framePtr->objv);
+#endif /* AVOID_HACKS_FOR_ITCL */
}
-
- for (i = 0; i < argc; i++) {
- objv[i] = Tcl_NewStringObj(argv[i], -1);
- Tcl_IncrRefCount(objv[i]);
+ Tcl_IncrRefCount(desiredObjs[0]);
+
+ defPtr = (Var *) (&framePtr->localCachePtr->varName0 + localCt);
+ for (i=1 ; i<=numArgs ; i++, defPtr++) {
+ Tcl_Obj *argObj;
+ Tcl_Obj *namePtr = localName(framePtr, i-1);
+
+ if (defPtr->value.objPtr != NULL) {
+ TclNewObj(argObj);
+ Tcl_AppendStringsToObj(argObj, "?", TclGetString(namePtr), "?", NULL);
+ } else if (defPtr->flags & VAR_IS_ARGS) {
+ numArgs--;
+ final = "...";
+ break;
+ } else {
+ argObj = namePtr;
+ Tcl_IncrRefCount(namePtr);
+ }
+ desiredObjs[i] = argObj;
}
- objv[argc] = 0;
-
- /*
- * Use TclObjInterpProc to actually interpret the procedure.
- */
- result = TclObjInterpProc(clientData, interp, argc, objv);
+ Tcl_ResetResult(interp);
+ Tcl_WrongNumArgs(interp, numArgs+1, desiredObjs, final);
- /*
- * Move the interpreter's object result to the string result,
- * then reset the object result.
- */
-
- Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
- TCL_VOLATILE);
+ for (i=0 ; i<=numArgs ; i++) {
+ Tcl_DecrRefCount(desiredObjs[i]);
+ }
+ TclStackFree(interp, desiredObjs);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclInitCompiledLocals --
+ *
+ * This routine is invoked in order to initialize the compiled locals
+ * table for a new call frame.
+ *
+ * DEPRECATED: functionality has been inlined elsewhere; this function
+ * remains to insure binary compatibility with Itcl.
+ *
- /*
- * Decrement the ref counts on the objv elements since we are done
- * with them.
- */
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May invoke various name resolvers in order to determine which
+ * variables are being referenced at runtime.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+TclInitCompiledLocals(
+ Tcl_Interp *interp, /* Current interpreter. */
+ CallFrame *framePtr, /* Call frame to initialize. */
+ Namespace *nsPtr) /* Pointer to current namespace. */
+{
+ Var *varPtr = framePtr->compiledLocals;
+ Tcl_Obj *bodyPtr;
+ ByteCode *codePtr;
- for (i = 0; i < argc; i++) {
- objPtr = objv[i];
- TclDecrRefCount(objPtr);
+ bodyPtr = framePtr->procPtr->bodyPtr;
+ if (bodyPtr->typePtr != &tclByteCodeType) {
+ Tcl_Panic("body object for proc attached to frame is not a byte code type");
}
+ codePtr = bodyPtr->internalRep.otherValuePtr;
- /*
- * Free the objv array if malloc'ed storage was used.
- */
-
- if (objv != objStorage) {
- ckfree((char *) objv);
+ if (framePtr->numCompiledLocals) {
+ if (!codePtr->localCachePtr) {
+ InitLocalCache(framePtr->procPtr) ;
+ }
+ framePtr->localCachePtr = codePtr->localCachePtr;
+ framePtr->localCachePtr->refCount++;
}
- return result;
-#undef NUM_ARGS
+
+ InitResolvedLocals(interp, codePtr, varPtr, nsPtr);
}
/*
*----------------------------------------------------------------------
*
- * TclObjInterpProc --
+ * InitResolvedLocals --
*
- * When a Tcl procedure gets invoked during bytecode evaluation, this
- * object-based routine gets invoked to interpret the procedure.
+ * This routine is invoked in order to initialize the compiled locals
+ * table for a new call frame.
*
* Results:
- * A standard Tcl object result value.
+ * None.
*
* Side effects:
- * Depends on the commands in the procedure.
+ * May invoke various name resolvers in order to determine which
+ * variables are being referenced at runtime.
*
*----------------------------------------------------------------------
*/
-int
-TclObjInterpProc(clientData, interp, objc, objv)
- ClientData clientData; /* Record describing procedure to be
- * interpreted. */
- register Tcl_Interp *interp; /* Interpreter in which procedure was
- * invoked. */
- int objc; /* Count of number of arguments to this
- * procedure. */
- Tcl_Obj *CONST objv[]; /* Argument value objects. */
+static void
+InitResolvedLocals(
+ Tcl_Interp *interp, /* Current interpreter. */
+ ByteCode *codePtr,
+ Var *varPtr,
+ Namespace *nsPtr) /* Pointer to current namespace. */
{
Interp *iPtr = (Interp *) interp;
- Proc *procPtr = (Proc *) clientData;
- Namespace *nsPtr = procPtr->cmdPtr->nsPtr;
- CallFrame frame;
- register CallFrame *framePtr = &frame;
- register Var *varPtr;
- register CompiledLocal *localPtr;
- char *procName;
- int nameLen, localCt, numArgs, argCt, i, result;
+ int haveResolvers = (nsPtr->compiledVarResProc || iPtr->resolverPtr);
+ CompiledLocal *firstLocalPtr, *localPtr;
+ int varNum;
+ Tcl_ResolvedVarInfo *resVarInfo;
/*
- * This procedure generates an array "compiledLocals" that holds the
- * storage for local variables. It starts out with stack-allocated space
- * but uses dynamically-allocated storage if needed.
+ * Find the localPtr corresponding to varPtr
*/
-#define NUM_LOCALS 20
- Var localStorage[NUM_LOCALS];
- Var *compiledLocals = localStorage;
+ varNum = varPtr - iPtr->framePtr->compiledLocals;
+ localPtr = iPtr->framePtr->procPtr->firstLocalPtr;
+ while (varNum--) {
+ localPtr = localPtr->nextPtr;
+ }
- /*
- * Get the procedure's name.
- */
+ if (!(haveResolvers && (codePtr->flags & TCL_BYTECODE_RESOLVE_VARS))) {
+ /*
+ * Initialize the array of local variables stored in the call frame.
+ * Some variables may have special resolution rules. In that case, we
+ * call their "resolver" procs to get our hands on the variable, and
+ * we make the compiled local a link to the real variable.
+ */
+
+ doInitResolvedLocals:
+ for (; localPtr != NULL; varPtr++, localPtr = localPtr->nextPtr) {
+ varPtr->flags = 0;
+ varPtr->value.objPtr = NULL;
+
+ /*
+ * Now invoke the resolvers to determine the exact variables
+ * that should be used.
+ */
- procName = Tcl_GetStringFromObj(objv[0], &nameLen);
+ resVarInfo = localPtr->resolveInfo;
+ if (resVarInfo && resVarInfo->fetchProc) {
+ Var *resolvedVarPtr = (Var *)
+ (*resVarInfo->fetchProc)(interp, resVarInfo);
+ if (resolvedVarPtr) {
+ if (TclIsVarInHash(resolvedVarPtr)) {
+ VarHashRefCount(resolvedVarPtr)++;
+ }
+ varPtr->flags = VAR_LINK;
+ varPtr->value.linkPtr = resolvedVarPtr;
+ }
+ }
+ }
+ return;
+ }
/*
- * If necessary, compile the procedure's body. The compiler will
- * allocate frame slots for the procedure's non-argument local
- * variables. Note that compiling the body might increase
- * procPtr->numCompiledLocals if new local variables are found
- * while compiling.
+ * This is the first run after a recompile, or else the resolver epoch
+ * has changed: update the resolver cache.
*/
- result = ProcCompileProc(interp, procPtr, procPtr->bodyPtr, nsPtr,
- "body of proc", procName, &procPtr);
+ firstLocalPtr = localPtr;
+ for (; localPtr != NULL; localPtr = localPtr->nextPtr) {
+ if (localPtr->resolveInfo) {
+ if (localPtr->resolveInfo->deleteProc) {
+ localPtr->resolveInfo->deleteProc(localPtr->resolveInfo);
+ } else {
+ ckfree((char *) localPtr->resolveInfo);
+ }
+ localPtr->resolveInfo = NULL;
+ }
+ localPtr->flags &= ~VAR_RESOLVED;
+
+ if (haveResolvers &&
+ !(localPtr->flags & (VAR_ARGUMENT|VAR_TEMPORARY))) {
+ ResolverScheme *resPtr = iPtr->resolverPtr;
+ Tcl_ResolvedVarInfo *vinfo;
+ int result;
+
+ if (nsPtr->compiledVarResProc) {
+ result = (*nsPtr->compiledVarResProc)(nsPtr->interp,
+ localPtr->name, localPtr->nameLength,
+ (Tcl_Namespace *) nsPtr, &vinfo);
+ } else {
+ result = TCL_CONTINUE;
+ }
- if (result != TCL_OK) {
- return result;
+ while ((result == TCL_CONTINUE) && resPtr) {
+ if (resPtr->compiledVarResProc) {
+ result = (*resPtr->compiledVarResProc)(nsPtr->interp,
+ localPtr->name, localPtr->nameLength,
+ (Tcl_Namespace *) nsPtr, &vinfo);
+ }
+ resPtr = resPtr->nextPtr;
+ }
+ if (result == TCL_OK) {
+ localPtr->resolveInfo = vinfo;
+ localPtr->flags |= VAR_RESOLVED;
+ }
+ }
}
+ localPtr = firstLocalPtr;
+ codePtr->flags &= ~TCL_BYTECODE_RESOLVE_VARS;
+ goto doInitResolvedLocals;
+}
- /*
- * Create the "compiledLocals" array. Make sure it is large enough to
- * hold all the procedure's compiled local variables, including its
- * formal parameters.
- */
+void
+TclFreeLocalCache(
+ Tcl_Interp *interp,
+ LocalCache *localCachePtr)
+{
+ int i;
+ Tcl_Obj **namePtrPtr = &localCachePtr->varName0;
- localCt = procPtr->numCompiledLocals;
- if (localCt > NUM_LOCALS) {
- compiledLocals = (Var *) ckalloc((unsigned) localCt * sizeof(Var));
+ for (i = 0; i < localCachePtr->numVars; i++, namePtrPtr++) {
+ Tcl_Obj *objPtr = *namePtrPtr;
+ /*
+ * Note that this can be called with interp==NULL, on interp
+ * deletion. In that case, the literal table and objects go away
+ * on their own.
+ */
+ if (objPtr) {
+ if (interp) {
+ TclReleaseLiteral(interp, objPtr);
+ } else {
+ Tcl_DecrRefCount(objPtr);
+ }
+ }
}
+ ckfree((char *) localCachePtr);
+}
+
+static void
+InitLocalCache(Proc *procPtr)
+{
+ Interp *iPtr = procPtr->iPtr;
+ ByteCode *codePtr = procPtr->bodyPtr->internalRep.otherValuePtr;
+ int localCt = procPtr->numCompiledLocals;
+ int numArgs = procPtr->numArgs, i = 0;
+
+ Tcl_Obj **namePtr;
+ Var *varPtr;
+ LocalCache *localCachePtr;
+ CompiledLocal *localPtr;
+ int new;
/*
- * Set up and push a new call frame for the new procedure invocation.
- * This call frame will execute in the proc's namespace, which might
- * be different than the current namespace. The proc's namespace is
- * that of its command, which can change if the command is renamed
- * from one namespace to another.
+ * Cache the names and initial values of local variables; store the
+ * cache in both the framePtr for this execution and in the codePtr
+ * for future calls.
*/
- result = Tcl_PushCallFrame(interp, (Tcl_CallFrame *) framePtr,
- (Tcl_Namespace *) nsPtr, /*isProcCallFrame*/ 1);
+ localCachePtr = (LocalCache *) ckalloc(sizeof(LocalCache)
+ + (localCt-1)*sizeof(Tcl_Obj *)
+ + numArgs*sizeof(Var));
- if (result != TCL_OK) {
- return result;
+ namePtr = &localCachePtr->varName0;
+ varPtr = (Var *) (namePtr + localCt);
+ localPtr = procPtr->firstLocalPtr;
+ while (localPtr) {
+ if (TclIsVarTemporary(localPtr)) {
+ *namePtr = NULL;
+ } else {
+ *namePtr = TclCreateLiteral(iPtr, localPtr->name,
+ localPtr->nameLength, /* hash */ (unsigned int) -1,
+ &new, /* nsPtr */ NULL, 0, NULL);
+ Tcl_IncrRefCount(*namePtr);
+ }
+
+ if (i < numArgs) {
+ varPtr->flags = (localPtr->flags & VAR_IS_ARGS);
+ varPtr->value.objPtr = localPtr->defValuePtr;
+ varPtr++;
+ i++;
+ }
+ namePtr++;
+ localPtr=localPtr->nextPtr;
}
+ codePtr->localCachePtr = localCachePtr;
+ localCachePtr->refCount = 1;
+ localCachePtr->numVars = localCt;
+}
- framePtr->objc = objc;
- framePtr->objv = objv; /* ref counts for args are incremented below */
+static int
+InitArgsAndLocals(
+ register Tcl_Interp *interp,/* Interpreter in which procedure was
+ * invoked. */
+ Tcl_Obj *procNameObj, /* Procedure name for error reporting. */
+ int skip) /* Number of initial arguments to be skipped,
+ * i.e., words in the "command name". */
+{
+ CallFrame *framePtr = ((Interp *)interp)->varFramePtr;
+ register Proc *procPtr = framePtr->procPtr;
+ ByteCode *codePtr = procPtr->bodyPtr->internalRep.otherValuePtr;
+ register Var *varPtr, *defPtr;
+ int localCt = procPtr->numCompiledLocals, numArgs, argCt, i, imax;
+ Tcl_Obj *const *argObjs;
/*
- * Initialize and resolve compiled variable references.
+ * Make sure that the local cache of variable names and initial values has
+ * been initialised properly .
*/
- framePtr->procPtr = procPtr;
- framePtr->numCompiledLocals = localCt;
- framePtr->compiledLocals = compiledLocals;
+ if (localCt) {
+ if (!codePtr->localCachePtr) {
+ InitLocalCache(procPtr) ;
+ }
+ framePtr->localCachePtr = codePtr->localCachePtr;
+ framePtr->localCachePtr->refCount++;
+ defPtr = (Var *) (&framePtr->localCachePtr->varName0 + localCt);
+ } else {
+ defPtr = NULL;
+ }
+
+ /*
+ * Create the "compiledLocals" array. Make sure it is large enough to hold
+ * all the procedure's compiled local variables, including its formal
+ * parameters.
+ */
- TclInitCompiledLocals(interp, framePtr, nsPtr);
+ varPtr = (Var*) TclStackAlloc(interp, (int)(localCt*sizeof(Var)));
+ framePtr->compiledLocals = varPtr;
+ framePtr->numCompiledLocals = localCt;
/*
- * Match and assign the call's actual parameters to the procedure's
- * formal arguments. The formal arguments are described by the first
- * numArgs entries in both the Proc structure's local variable list and
- * the call frame's local variable array.
+ * Match and assign the call's actual parameters to the procedure's formal
+ * arguments. The formal arguments are described by the first numArgs
+ * entries in both the Proc structure's local variable list and the call
+ * frame's local variable array.
*/
numArgs = procPtr->numArgs;
- varPtr = framePtr->compiledLocals;
- localPtr = procPtr->firstLocalPtr;
- argCt = objc;
- for (i = 1, argCt -= 1; i <= numArgs; i++, argCt--) {
- if (!TclIsVarArgument(localPtr)) {
- panic("TclObjInterpProc: local variable %s is not argument but should be",
- localPtr->name);
- return TCL_ERROR;
- }
- if (TclIsVarTemporary(localPtr)) {
- panic("TclObjInterpProc: local variable %d is temporary but should be an argument", i);
- return TCL_ERROR;
+ argCt = framePtr->objc - skip; /* Set it to the number of args to the
+ * procedure. */
+ argObjs = framePtr->objv + skip;
+ if (numArgs == 0) {
+ if (argCt) {
+ goto incorrectArgs;
+ } else {
+ goto correctArgs;
}
+ }
+ imax = ((argCt < numArgs-1) ? argCt : numArgs-1);
+ for (i = 0; i < imax; i++, varPtr++, defPtr++) {
+ /*
+ * "Normal" arguments; last formal is special, depends on it being
+ * 'args'.
+ */
+ Tcl_Obj *objPtr = argObjs[i];
+
+ varPtr->flags = 0;
+ varPtr->value.objPtr = objPtr;
+ Tcl_IncrRefCount(objPtr); /* Local var is a reference. */
+ }
+ for (; i < numArgs-1; i++, varPtr++, defPtr++) {
/*
- * Handle the special case of the last formal being "args". When
- * it occurs, assign it a list consisting of all the remaining
- * actual arguments.
+ * This loop is entered if argCt < (numArgs-1). Set default values;
+ * last formal is special.
*/
- if ((i == numArgs) && ((localPtr->name[0] == 'a')
- && (strcmp(localPtr->name, "args") == 0))) {
- Tcl_Obj *listPtr = Tcl_NewListObj(argCt, &(objv[i]));
- varPtr->value.objPtr = listPtr;
- Tcl_IncrRefCount(listPtr); /* local var is a reference */
- TclClearVarUndefined(varPtr);
- argCt = 0;
- break; /* done processing args */
- } else if (argCt > 0) {
- Tcl_Obj *objPtr = objv[i];
- varPtr->value.objPtr = objPtr;
- TclClearVarUndefined(varPtr);
- Tcl_IncrRefCount(objPtr); /* since the local variable now has
- * another reference to object. */
- } else if (localPtr->defValuePtr != NULL) {
- Tcl_Obj *objPtr = localPtr->defValuePtr;
+ Tcl_Obj *objPtr = defPtr->value.objPtr;
+
+ if (objPtr) {
+ varPtr->flags = 0;
varPtr->value.objPtr = objPtr;
- TclClearVarUndefined(varPtr);
- Tcl_IncrRefCount(objPtr); /* since the local variable now has
- * another reference to object. */
+ Tcl_IncrRefCount(objPtr); /* Local var reference. */
} else {
goto incorrectArgs;
}
- varPtr++;
- localPtr = localPtr->nextPtr;
}
- if (argCt > 0) {
- Tcl_Obj *objResult;
- int len, flags;
- incorrectArgs:
- /*
- * Build up equivalent to Tcl_WrongNumArgs message for proc
- */
+ /*
+ * When we get here, the last formal argument remains to be defined:
+ * defPtr and varPtr point to the last argument to be initialized.
+ */
- Tcl_ResetResult(interp);
- objResult = Tcl_GetObjResult(interp);
- Tcl_AppendToObj(objResult, "wrong # args: should be \"", -1);
- /*
- * Quote the proc name if it contains spaces (Bug 942757).
- */
+ varPtr->flags = 0;
+ if (defPtr->flags & VAR_IS_ARGS) {
+ Tcl_Obj *listPtr = Tcl_NewListObj(argCt-i, argObjs+i);
- len = Tcl_ScanCountedElement(procName, nameLen, &flags);
- if (len != nameLen) {
- char *procName1 = ckalloc((unsigned) len + 1);
- len = Tcl_ConvertCountedElement(procName, nameLen, procName1, flags);
- Tcl_AppendToObj(objResult, procName1, len);
- ckfree(procName1);
+ varPtr->value.objPtr = listPtr;
+ Tcl_IncrRefCount(listPtr); /* Local var is a reference. */
+ } else if (argCt == numArgs) {
+ Tcl_Obj *objPtr = argObjs[i];
+
+ varPtr->value.objPtr = objPtr;
+ Tcl_IncrRefCount(objPtr); /* Local var is a reference. */
+ } else if ((argCt < numArgs) && (defPtr->value.objPtr != NULL)) {
+ Tcl_Obj *objPtr = defPtr->value.objPtr;
+
+ varPtr->value.objPtr = objPtr;
+ Tcl_IncrRefCount(objPtr); /* Local var is a reference. */
+ } else {
+ goto incorrectArgs;
+ }
+ varPtr++;
+
+ /*
+ * Initialise and resolve the remaining compiledLocals. In the absence of
+ * resolvers, they are undefined local vars: (flags=0, value=NULL).
+ */
+
+ correctArgs:
+ if (numArgs < localCt) {
+ if (!framePtr->nsPtr->compiledVarResProc && !((Interp *)interp)->resolverPtr) {
+ memset(varPtr, 0, (localCt - numArgs)*sizeof(Var));
} else {
- Tcl_AppendToObj(objResult, procName, len);
+ InitResolvedLocals(interp, codePtr, varPtr, framePtr->nsPtr);
}
+ }
- localPtr = procPtr->firstLocalPtr;
- for (i = 1; i <= numArgs; i++) {
- if (localPtr->defValuePtr != NULL) {
- Tcl_AppendStringsToObj(objResult,
- " ?", localPtr->name, "?", (char *) NULL);
- } else {
- Tcl_AppendStringsToObj(objResult,
- " ", localPtr->name, (char *) NULL);
- }
- localPtr = localPtr->nextPtr;
- }
- Tcl_AppendStringsToObj(objResult, "\"", (char *) NULL);
+ return TCL_OK;
- result = TCL_ERROR;
- goto procDone;
+
+ incorrectArgs:
+ /*
+ * Initialise all compiled locals to avoid problems at DeleteLocalVars.
+ */
+
+ memset(varPtr, 0, ((framePtr->compiledLocals + localCt)-varPtr)*sizeof(Var));
+ return ProcWrongNumArgs(interp, skip);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PushProcCallFrame --
+ *
+ * Compiles a proc body if necessary, then pushes a CallFrame suitable
+ * for executing it.
+ *
+ * Results:
+ * A standard Tcl object result value.
+ *
+ * Side effects:
+ * The proc's body may be recompiled. A CallFrame is pushed, it will have
+ * to be popped by the caller.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+PushProcCallFrame(
+ ClientData clientData, /* Record describing procedure to be
+ * interpreted. */
+ register Tcl_Interp *interp,/* Interpreter in which procedure was
+ * invoked. */
+ int objc, /* Count of number of arguments to this
+ * procedure. */
+ Tcl_Obj *CONST objv[], /* Argument value objects. */
+ int isLambda) /* 1 if this is a call by ApplyObjCmd: it
+ * needs special rules for error msg */
+{
+ Proc *procPtr = (Proc *) clientData;
+ Namespace *nsPtr = procPtr->cmdPtr->nsPtr;
+ CallFrame *framePtr, **framePtrPtr;
+ int result;
+ ByteCode *codePtr;
+
+ /*
+ * If necessary (i.e. if we haven't got a suitable compilation already
+ * cached) compile the procedure's body. The compiler will allocate frame
+ * slots for the procedure's non-argument local variables. Note that
+ * compiling the body might increase procPtr->numCompiledLocals if new
+ * local variables are found while compiling.
+ */
+
+ if (procPtr->bodyPtr->typePtr == &tclByteCodeType) {
+ Interp *iPtr = (Interp *) interp;
+
+ /*
+ * When we've got bytecode, this is the check for validity. That is,
+ * the bytecode must be for the right interpreter (no cross-leaks!),
+ * the code must be from the current epoch (so subcommand compilation
+ * is up-to-date), the namespace must match (so variable handling
+ * is right) and the resolverEpoch must match (so that new shadowed
+ * commands and/or resolver changes are considered).
+ */
+
+ codePtr = procPtr->bodyPtr->internalRep.otherValuePtr;
+ if (((Interp *) *codePtr->interpHandle != iPtr)
+ || (codePtr->compileEpoch != iPtr->compileEpoch)
+ || (codePtr->nsPtr != nsPtr)
+ || (codePtr->nsEpoch != nsPtr->resolverEpoch)) {
+ goto doCompilation;
+ }
+ } else {
+ doCompilation:
+ result = ProcCompileProc(interp, procPtr, procPtr->bodyPtr, nsPtr,
+ (isLambda ? "body of lambda term" : "body of proc"),
+ TclGetString(objv[isLambda]), &procPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
}
/*
- * Invoke the commands in the procedure's body.
+ * Set up and push a new call frame for the new procedure invocation.
+ * This call frame will execute in the proc's namespace, which might be
+ * different than the current namespace. The proc's namespace is that of
+ * its command, which can change if the command is renamed from one
+ * namespace to another.
*/
-#ifdef TCL_COMPILE_DEBUG
+ framePtrPtr = &framePtr;
+ result = TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr,
+ (Tcl_Namespace *) nsPtr,
+ (isLambda? (FRAME_IS_PROC|FRAME_IS_LAMBDA) : FRAME_IS_PROC));
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ framePtr->objc = objc;
+ framePtr->objv = objv;
+ framePtr->procPtr = procPtr;
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclObjInterpProc --
+ *
+ * When a Tcl procedure gets invoked during bytecode evaluation, this
+ * object-based routine gets invoked to interpret the procedure.
+ *
+ * Results:
+ * A standard Tcl object result value.
+ *
+ * Side effects:
+ * Depends on the commands in the procedure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclObjInterpProc(
+ ClientData clientData, /* Record describing procedure to be
+ * interpreted. */
+ register Tcl_Interp *interp,/* Interpreter in which procedure was
+ * invoked. */
+ int objc, /* Count of number of arguments to this
+ * procedure. */
+ Tcl_Obj *CONST objv[]) /* Argument value objects. */
+{
+ int result;
+
+ result = PushProcCallFrame(clientData, interp, objc, objv, /*isLambda*/ 0);
+ if (result == TCL_OK) {
+ return TclObjInterpProcCore(interp, objv[0], 1, &MakeProcError);
+ } else {
+ return TCL_ERROR;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclObjInterpProcCore --
+ *
+ * When a Tcl procedure, lambda term or anything else that works like a
+ * procedure gets invoked during bytecode evaluation, this object-based
+ * routine gets invoked to interpret the body.
+ *
+ * Results:
+ * A standard Tcl object result value.
+ *
+ * Side effects:
+ * Nearly anything; depends on the commands in the procedure body.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclObjInterpProcCore(
+ register Tcl_Interp *interp,/* Interpreter in which procedure was
+ * invoked. */
+ Tcl_Obj *procNameObj, /* Procedure name for error reporting. */
+ int skip, /* Number of initial arguments to be skipped,
+ * i.e., words in the "command name". */
+ ProcErrorProc errorProc) /* How to convert results from the script into
+ * results of the overall procedure. */
+{
+ Interp *iPtr = (Interp *) interp;
+ register Proc *procPtr = iPtr->varFramePtr->procPtr;
+ int result;
+ CallFrame *freePtr;
+
+ result = InitArgsAndLocals(interp, procNameObj, skip);
+ if (result != TCL_OK) {
+ goto procDone;
+ }
+
+#if defined(TCL_COMPILE_DEBUG)
if (tclTraceExec >= 1) {
- fprintf(stdout, "Calling proc ");
- for (i = 0; i < objc; i++) {
- TclPrintObject(stdout, objv[i], 15);
+ register CallFrame *framePtr = iPtr->varFramePtr;
+ register int i;
+
+ if (framePtr->isProcCallFrame & FRAME_IS_LAMBDA) {
+ fprintf(stdout, "Calling lambda ");
+ } else {
+ fprintf(stdout, "Calling proc ");
+ }
+ for (i = 0; i < framePtr->objc; i++) {
+ TclPrintObject(stdout, framePtr->objv[i], 15);
fprintf(stdout, " ");
}
fprintf(stdout, "\n");
@@ -1200,40 +1715,117 @@ TclObjInterpProc(clientData, interp, objc, objv)
if (TCL_DTRACE_PROC_ARGS_ENABLED()) {
char *a[10];
int i = 0;
+ int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0;
while (i < 10) {
- a[i] = i < objc ? TclGetString(objv[i]) : NULL; i++;
+ a[i] = (l < iPtr->varFramePtr->objc ?
+ TclGetString(iPtr->varFramePtr->objv[l]) : NULL); i++; l++;
}
TCL_DTRACE_PROC_ARGS(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7],
a[8], a[9]);
}
-#endif /* USE_DTRACE */
+ if (TCL_DTRACE_PROC_INFO_ENABLED() && iPtr->cmdFramePtr) {
+ Tcl_Obj *info = TclInfoFrame(interp, iPtr->cmdFramePtr);
+ char *a[4]; int i[2];
- iPtr->returnCode = TCL_OK;
- procPtr->refCount++;
- if (TCL_DTRACE_PROC_ENTRY_ENABLED()) {
- TCL_DTRACE_PROC_ENTRY(TclGetString(objv[0]), objc - 1,
- (Tcl_Obj **)(objv + 1));
+ TclDTraceInfo(info, a, i);
+ TCL_DTRACE_PROC_INFO(a[0], a[1], a[2], a[3], i[0], i[1]);
+ TclDecrRefCount(info);
}
-#ifndef TCL_TIP280
- result = TclCompEvalObj(interp, procPtr->bodyPtr);
-#else
- /* TIP #280: No need to set the invoking context here. The body has
- * already been compiled, so the part of CompEvalObj using it is bypassed.
+#endif /* USE_DTRACE */
+
+ /*
+ * Invoke the commands in the procedure's body.
*/
- result = TclCompEvalObj(interp, procPtr->bodyPtr, NULL, 0);
-#endif
- if (TCL_DTRACE_PROC_RETURN_ENABLED()) {
- TCL_DTRACE_PROC_RETURN(TclGetString(objv[0]), result);
+ procPtr->refCount++;
+ iPtr->numLevels++;
+
+ if (TclInterpReady(interp) == TCL_ERROR) {
+ result = TCL_ERROR;
+ } else {
+ register ByteCode *codePtr =
+ procPtr->bodyPtr->internalRep.otherValuePtr;
+
+ codePtr->refCount++;
+#ifdef USE_DTRACE
+ if (TCL_DTRACE_PROC_ENTRY_ENABLED()) {
+ int l;
+
+ l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 2 : 1;
+ TCL_DTRACE_PROC_ENTRY(TclGetString(procNameObj),
+ iPtr->varFramePtr->objc - l,
+ (Tcl_Obj **)(iPtr->varFramePtr->objv + l));
+ }
+#endif /* USE_DTRACE */
+ result = TclExecuteByteCode(interp, codePtr);
+ if (TCL_DTRACE_PROC_RETURN_ENABLED()) {
+ TCL_DTRACE_PROC_RETURN(TclGetString(procNameObj), result);
+ }
+ codePtr->refCount--;
+ if (codePtr->refCount <= 0) {
+ TclCleanupByteCode(codePtr);
+ }
}
+
+ iPtr->numLevels--;
procPtr->refCount--;
if (procPtr->refCount <= 0) {
TclProcCleanupProc(procPtr);
}
- if (result != TCL_OK) {
- result = ProcessProcResultCode(interp, procName, nameLen, result);
+ /*
+ * Process the result code.
+ */
+
+ switch (result) {
+ case TCL_RETURN:
+ /*
+ * If it is a 'return', do the TIP#90 processing now.
+ */
+
+ result = TclUpdateReturnInfo((Interp *) interp);
+ break;
+
+ case TCL_CONTINUE:
+ case TCL_BREAK:
+ /*
+ * It's an error to get to this point from a 'break' or 'continue', so
+ * transform to an error now.
+ */
+
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "invoked \"",
+ ((result == TCL_BREAK) ? "break" : "continue"),
+ "\" outside of a loop", NULL);
+ result = TCL_ERROR;
+
+ /*
+ * Fall through to the TCL_ERROR handling code.
+ */
+
+ case TCL_ERROR:
+ /*
+ * Now it _must_ be an error, so we need to log it as such. This means
+ * filling out the error trace. Luckily, we just hand this off to the
+ * function handed to us as an argument.
+ */
+
+ (*errorProc)(interp, procNameObj);
+
+ default:
+ /*
+ * Process other results (OK and non-standard) by doing nothing
+ * special, skipping directly to the code afterwards that cleans up
+ * associated memory.
+ *
+ * Non-standard results are processed by passing them through quickly.
+ * This means they all work as exceptions, unwinding the stack quickly
+ * and neatly. Who knows how well they are handled by third-party code
+ * though...
+ */
+
+ (void) 0; /* do nothing */
}
#ifdef USE_DTRACE
@@ -1241,23 +1833,26 @@ TclObjInterpProc(clientData, interp, objc, objv)
Tcl_Obj *r;
r = Tcl_GetObjResult(interp);
- TCL_DTRACE_PROC_RESULT(TclGetString(objv[0]), result,
+ TCL_DTRACE_PROC_RESULT(TclGetString(procNameObj), result,
TclGetString(r), r);
}
#endif /* USE_DTRACE */
+ procDone:
/*
- * Pop and free the call frame for this procedure invocation, then
- * free the compiledLocals array if malloc'ed storage was used.
+ * Free the stack-allocated compiled locals and CallFrame. It is important
+ * to pop the call frame without freeing it first: the compiledLocals
+ * cannot be freed before the frame is popped, as the local variables must
+ * be deleted. But the compiledLocals must be freed first, as they were
+ * allocated later on the stack.
*/
- procDone:
- Tcl_PopCallFrame(interp);
- if (compiledLocals != localStorage) {
- ckfree((char *) compiledLocals);
- }
+ freePtr = iPtr->framePtr;
+ Tcl_PopCallFrame(interp); /* Pop but do not free. */
+ TclStackFree(interp, freePtr->compiledLocals);
+ /* Free compiledLocals. */
+ TclStackFree(interp, freePtr); /* Free CallFrame. */
return result;
-#undef NUM_LOCALS
}
/*
@@ -1265,150 +1860,149 @@ TclObjInterpProc(clientData, interp, objc, objv)
*
* TclProcCompileProc --
*
- * Called just before a procedure is executed to compile the
- * body to byte codes. If the type of the body is not
- * "byte code" or if the compile conditions have changed
- * (namespace context, epoch counters, etc.) then the body
- * is recompiled. Otherwise, this procedure does nothing.
+ * Called just before a procedure is executed to compile the body to byte
+ * codes. If the type of the body is not "byte code" or if the compile
+ * conditions have changed (namespace context, epoch counters, etc.) then
+ * the body is recompiled. Otherwise, this function does nothing.
*
* Results:
* None.
*
* Side effects:
- * May change the internal representation of the body object
- * to compiled code.
+ * May change the internal representation of the body object to compiled
+ * code.
*
*----------------------------------------------------------------------
*/
int
-TclProcCompileProc(interp, procPtr, bodyPtr, nsPtr, description, procName)
- Tcl_Interp *interp; /* Interpreter containing procedure. */
- Proc *procPtr; /* Data associated with procedure. */
- Tcl_Obj *bodyPtr; /* Body of proc. (Usually procPtr->bodyPtr,
- * but could be any code fragment compiled
- * in the context of this procedure.) */
- Namespace *nsPtr; /* Namespace containing procedure. */
- CONST char *description; /* string describing this body of code. */
- CONST char *procName; /* Name of this procedure. */
+TclProcCompileProc(
+ Tcl_Interp *interp, /* Interpreter containing procedure. */
+ Proc *procPtr, /* Data associated with procedure. */
+ Tcl_Obj *bodyPtr, /* Body of proc. (Usually procPtr->bodyPtr,
+ * but could be any code fragment compiled in
+ * the context of this procedure.) */
+ Namespace *nsPtr, /* Namespace containing procedure. */
+ CONST char *description, /* string describing this body of code. */
+ CONST char *procName) /* Name of this procedure. */
{
- return ProcCompileProc(interp, procPtr, bodyPtr, nsPtr,
- description, procName, NULL);
+ return ProcCompileProc(interp, procPtr, bodyPtr, nsPtr, description,
+ procName, NULL);
}
static int
-ProcCompileProc(interp, procPtr, bodyPtr, nsPtr, description,
- procName, procPtrPtr)
- Tcl_Interp *interp; /* Interpreter containing procedure. */
- Proc *procPtr; /* Data associated with procedure. */
- Tcl_Obj *bodyPtr; /* Body of proc. (Usually procPtr->bodyPtr,
- * but could be any code fragment compiled
- * in the context of this procedure.) */
- Namespace *nsPtr; /* Namespace containing procedure. */
- CONST char *description; /* string describing this body of code. */
- CONST char *procName; /* Name of this procedure. */
- Proc **procPtrPtr; /* points to storage where a replacement
- * (Proc *) value may be written, when
- * appropriate */
+ProcCompileProc(
+ Tcl_Interp *interp, /* Interpreter containing procedure. */
+ Proc *procPtr, /* Data associated with procedure. */
+ Tcl_Obj *bodyPtr, /* Body of proc. (Usually procPtr->bodyPtr,
+ * but could be any code fragment compiled in
+ * the context of this procedure.) */
+ Namespace *nsPtr, /* Namespace containing procedure. */
+ CONST char *description, /* string describing this body of code. */
+ CONST char *procName, /* Name of this procedure. */
+ Proc **procPtrPtr) /* Points to storage where a replacement
+ * (Proc *) value may be written. */
{
- Interp *iPtr = (Interp*)interp;
- int i, result;
- Tcl_CallFrame frame;
- ByteCode *codePtr = (ByteCode *) bodyPtr->internalRep.otherValuePtr;
+ Interp *iPtr = (Interp *) interp;
+ int i;
+ Tcl_CallFrame *framePtr;
+ ByteCode *codePtr = bodyPtr->internalRep.otherValuePtr;
CompiledLocal *localPtr;
/*
- * If necessary, compile the procedure's body. The compiler will
- * allocate frame slots for the procedure's non-argument local
- * variables. If the ByteCode already exists, make sure it hasn't been
- * invalidated by someone redefining a core command (this might make the
- * compiled code wrong). Also, if the code was compiled in/for a
- * different interpreter, we recompile it. Note that compiling the body
- * might increase procPtr->numCompiledLocals if new local variables are
- * found while compiling.
+ * If necessary, compile the procedure's body. The compiler will allocate
+ * frame slots for the procedure's non-argument local variables. If the
+ * ByteCode already exists, make sure it hasn't been invalidated by
+ * someone redefining a core command (this might make the compiled code
+ * wrong). Also, if the code was compiled in/for a different interpreter,
+ * we recompile it. Note that compiling the body might increase
+ * procPtr->numCompiledLocals if new local variables are found while
+ * compiling.
*
- * Precompiled procedure bodies, however, are immutable and therefore
- * they are not recompiled, even if things have changed.
+ * Precompiled procedure bodies, however, are immutable and therefore they
+ * are not recompiled, even if things have changed.
*/
if (bodyPtr->typePtr == &tclByteCodeType) {
- if (((Interp *) *codePtr->interpHandle != iPtr)
- || (codePtr->compileEpoch != iPtr->compileEpoch)
- || (codePtr->nsPtr != nsPtr)) {
- if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
- if ((Interp *) *codePtr->interpHandle != iPtr) {
- Tcl_AppendResult(interp,
- "a precompiled script jumped interps", NULL);
- return TCL_ERROR;
- }
- codePtr->compileEpoch = iPtr->compileEpoch;
- codePtr->nsPtr = nsPtr;
- } else {
- (*tclByteCodeType.freeIntRepProc)(bodyPtr);
- bodyPtr->typePtr = (Tcl_ObjType *) NULL;
- }
+ if (((Interp *) *codePtr->interpHandle == iPtr)
+ && (codePtr->compileEpoch == iPtr->compileEpoch)
+ && (codePtr->nsPtr == nsPtr)
+ && (codePtr->nsEpoch == nsPtr->resolverEpoch)) {
+ return TCL_OK;
+ } else {
+ if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {
+ if ((Interp *) *codePtr->interpHandle != iPtr) {
+ Tcl_AppendResult(interp,
+ "a precompiled script jumped interps", NULL);
+ return TCL_ERROR;
+ }
+ codePtr->compileEpoch = iPtr->compileEpoch;
+ codePtr->nsPtr = nsPtr;
+ } else {
+ bodyPtr->typePtr->freeIntRepProc(bodyPtr);
+ bodyPtr->typePtr = NULL;
+ }
}
}
if (bodyPtr->typePtr != &tclByteCodeType) {
- int numChars;
- char *ellipsis;
+ Tcl_HashEntry *hePtr;
#ifdef TCL_COMPILE_DEBUG
if (tclTraceCompile >= 1) {
/*
- * Display a line summarizing the top level command we
- * are about to compile.
+ * Display a line summarizing the top level command we are about
+ * to compile.
*/
- numChars = strlen(procName);
- ellipsis = "";
- if (numChars > 50) {
- numChars = 50;
- ellipsis = "...";
- }
- fprintf(stdout, "Compiling %s \"%.*s%s\"\n",
- description, numChars, procName, ellipsis);
+ Tcl_Obj *message;
+
+ TclNewLiteralStringObj(message, "Compiling ");
+ Tcl_IncrRefCount(message);
+ Tcl_AppendStringsToObj(message, description, " \"", NULL);
+ Tcl_AppendLimitedToObj(message, procName, -1, 50, NULL);
+ fprintf(stdout, "%s\"\n", TclGetString(message));
+ Tcl_DecrRefCount(message);
}
#endif
/*
- * Plug the current procPtr into the interpreter and coerce
- * the code body to byte codes. The interpreter needs to
- * know which proc it's compiling so that it can access its
- * list of compiled locals.
+ * Plug the current procPtr into the interpreter and coerce the code
+ * body to byte codes. The interpreter needs to know which proc it's
+ * compiling so that it can access its list of compiled locals.
*
- * TRICKY NOTE: Be careful to push a call frame with the
- * proper namespace context, so that the byte codes are
- * compiled in the appropriate class context.
+ * TRICKY NOTE: Be careful to push a call frame with the proper
+ * namespace context, so that the byte codes are compiled in the
+ * appropriate class context.
*/
if (procPtrPtr != NULL && procPtr->refCount > 1) {
Tcl_Command token;
Tcl_CmdInfo info;
- Proc *new = (Proc *) ckalloc(sizeof(Proc));
-
- new->iPtr = procPtr->iPtr;
- new->refCount = 1;
- new->cmdPtr = procPtr->cmdPtr;
- token = (Tcl_Command) new->cmdPtr;
- new->bodyPtr = Tcl_DuplicateObj(bodyPtr);
- bodyPtr = new->bodyPtr;
+ Proc *newProc = (Proc *) ckalloc(sizeof(Proc));
+
+ newProc->iPtr = procPtr->iPtr;
+ newProc->refCount = 1;
+ newProc->cmdPtr = procPtr->cmdPtr;
+ token = (Tcl_Command) newProc->cmdPtr;
+ newProc->bodyPtr = Tcl_DuplicateObj(bodyPtr);
+ bodyPtr = newProc->bodyPtr;
Tcl_IncrRefCount(bodyPtr);
- new->numArgs = procPtr->numArgs;
+ newProc->numArgs = procPtr->numArgs;
- new->numCompiledLocals = new->numArgs;
- new->firstLocalPtr = NULL;
- new->lastLocalPtr = NULL;
+ newProc->numCompiledLocals = newProc->numArgs;
+ newProc->firstLocalPtr = NULL;
+ newProc->lastLocalPtr = NULL;
localPtr = procPtr->firstLocalPtr;
- for (i = 0; i < new->numArgs; i++, localPtr = localPtr->nextPtr) {
+ for (i=0; i<newProc->numArgs; i++, localPtr=localPtr->nextPtr) {
CompiledLocal *copy = (CompiledLocal *) ckalloc((unsigned)
- (sizeof(CompiledLocal) -sizeof(localPtr->name)
- + localPtr->nameLength + 1));
- if (new->firstLocalPtr == NULL) {
- new->firstLocalPtr = new->lastLocalPtr = copy;
+ (sizeof(CompiledLocal) - sizeof(localPtr->name)
+ + localPtr->nameLength + 1));
+
+ if (newProc->firstLocalPtr == NULL) {
+ newProc->firstLocalPtr = newProc->lastLocalPtr = copy;
} else {
- new->lastLocalPtr->nextPtr = copy;
- new->lastLocalPtr = copy;
+ newProc->lastLocalPtr->nextPtr = copy;
+ newProc->lastLocalPtr = copy;
}
copy->nextPtr = NULL;
copy->nameLength = localPtr->nameLength;
@@ -1419,97 +2013,58 @@ ProcCompileProc(interp, procPtr, bodyPtr, nsPtr, description,
Tcl_IncrRefCount(copy->defValuePtr);
}
copy->resolveInfo = localPtr->resolveInfo;
- memcpy(copy->name, localPtr->name, localPtr->nameLength + 1);
+ memcpy(copy->name, localPtr->name, localPtr->nameLength + 1);
}
+ /*
+ * Reset the ClientData
+ */
- /* Reset the ClientData */
Tcl_GetCommandInfoFromToken(token, &info);
if (info.objClientData == (ClientData) procPtr) {
- info.objClientData = (ClientData) new;
+ info.objClientData = (ClientData) newProc;
}
if (info.clientData == (ClientData) procPtr) {
- info.clientData = (ClientData) new;
+ info.clientData = (ClientData) newProc;
}
if (info.deleteData == (ClientData) procPtr) {
- info.deleteData = (ClientData) new;
+ info.deleteData = (ClientData) newProc;
}
Tcl_SetCommandInfoFromToken(token, &info);
procPtr->refCount--;
- *procPtrPtr = procPtr = new;
+ *procPtrPtr = procPtr = newProc;
}
iPtr->compiledProcPtr = procPtr;
- result = Tcl_PushCallFrame(interp, &frame,
- (Tcl_Namespace*)nsPtr, /* isProcCallFrame */ 0);
+ (void) TclPushStackFrame(interp, &framePtr,
+ (Tcl_Namespace *) nsPtr, /* isProcCallFrame */ 0);
- if (result == TCL_OK) {
-#ifdef TCL_TIP280
- /* TIP #280. We get the invoking context from the cmdFrame
- * which was saved by 'Tcl_ProcObjCmd' (using linePBodyPtr).
- */
+ /*
+ * TIP #280: We get the invoking context from the cmdFrame which
+ * was saved by 'Tcl_ProcObjCmd' (using linePBodyPtr).
+ */
- Tcl_HashEntry* hePtr = Tcl_FindHashEntry (iPtr->linePBodyPtr, (char *) procPtr);
+ hePtr = Tcl_FindHashEntry(iPtr->linePBodyPtr, (char *) procPtr);
- /* Constructed saved frame has body as word 0. See Tcl_ProcObjCmd.
- */
- iPtr->invokeWord = 0;
- iPtr->invokeCmdFramePtr = (hePtr
- ? (CmdFrame*) Tcl_GetHashValue (hePtr)
- : NULL);
-#endif
- result = tclByteCodeType.setFromAnyProc(interp, bodyPtr);
-#ifdef TCL_TIP280
- iPtr->invokeCmdFramePtr = NULL;
-#endif
- Tcl_PopCallFrame(interp);
- }
+ /*
+ * Constructed saved frame has body as word 0. See Tcl_ProcObjCmd.
+ */
- if (result != TCL_OK) {
- if (result == TCL_ERROR) {
- char buf[100 + TCL_INTEGER_SPACE];
-
- numChars = strlen(procName);
- ellipsis = "";
- if (numChars > 50) {
- numChars = 50;
- ellipsis = "...";
- }
- while ( (procName[numChars] & 0xC0) == 0x80 ) {
- /*
- * Back up truncation point so that we don't truncate
- * in the middle of a multi-byte character (in UTF-8)
- */
- numChars--;
- ellipsis = "...";
- }
- sprintf(buf, "\n (compiling %s \"%.*s%s\", line %d)",
- description, numChars, procName, ellipsis,
- interp->errorLine);
- Tcl_AddObjErrorInfo(interp, buf, -1);
- }
- return result;
- }
+ iPtr->invokeWord = 0;
+ iPtr->invokeCmdFramePtr =
+ (hePtr ? (CmdFrame *) Tcl_GetHashValue(hePtr) : NULL);
+ (void) tclByteCodeType.setFromAnyProc(interp, bodyPtr);
+ iPtr->invokeCmdFramePtr = NULL;
+ TclPopStackFrame(interp);
} else if (codePtr->nsEpoch != nsPtr->resolverEpoch) {
-
/*
- * The resolver epoch has changed, but we only need to invalidate
- * the resolver cache.
+ * The resolver epoch has changed, but we only need to invalidate the
+ * resolver cache.
*/
- for (localPtr = procPtr->firstLocalPtr; localPtr != NULL;
- localPtr = localPtr->nextPtr) {
- localPtr->flags &= ~(VAR_RESOLVED);
- if (localPtr->resolveInfo) {
- if (localPtr->resolveInfo->deleteProc) {
- localPtr->resolveInfo->deleteProc(localPtr->resolveInfo);
- } else {
- ckfree((char*)localPtr->resolveInfo);
- }
- localPtr->resolveInfo = NULL;
- }
- }
+ codePtr->nsEpoch = nsPtr->resolverEpoch;
+ codePtr->flags |= TCL_BYTECODE_RESOLVE_VARS;
}
return TCL_OK;
}
@@ -1517,68 +2072,36 @@ ProcCompileProc(interp, procPtr, bodyPtr, nsPtr, description,
/*
*----------------------------------------------------------------------
*
- * ProcessProcResultCode --
+ * MakeProcError --
*
- * Procedure called by TclObjInterpProc to process a return code other
- * than TCL_OK returned by a Tcl procedure.
+ * Function called by TclObjInterpProc to create the stack information
+ * upon an error from a procedure.
*
* Results:
- * Depending on the argument return code, the result returned is
- * another return code and the interpreter's result is set to a value
- * to supplement that return code.
+ * The interpreter's error info trace is set to a value that supplements
+ * the error code.
*
* Side effects:
- * If the result returned is TCL_ERROR, traceback information about
- * the procedure just executed is appended to the interpreter's
- * "errorInfo" variable.
+ * none.
*
*----------------------------------------------------------------------
*/
-static int
-ProcessProcResultCode(interp, procName, nameLen, returnCode)
- Tcl_Interp *interp; /* The interpreter in which the procedure
- * was called and returned returnCode. */
- char *procName; /* Name of the procedure. Used for error
+static void
+MakeProcError(
+ Tcl_Interp *interp, /* The interpreter in which the procedure was
+ * called. */
+ Tcl_Obj *procNameObj) /* Name of the procedure. Used for error
* messages and trace information. */
- int nameLen; /* Number of bytes in procedure's name. */
- int returnCode; /* The unexpected result code. */
{
- Interp *iPtr = (Interp *) interp;
- char msg[100 + TCL_INTEGER_SPACE];
- char *ellipsis = "";
-
- if (returnCode == TCL_OK) {
- return TCL_OK;
- }
- if ((returnCode > TCL_CONTINUE) || (returnCode < TCL_OK)) {
- return returnCode;
- }
- if (returnCode == TCL_RETURN) {
- return TclUpdateReturnInfo(iPtr);
- }
- if (returnCode != TCL_ERROR) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp), ((returnCode == TCL_BREAK)
- ? "invoked \"break\" outside of a loop"
- : "invoked \"continue\" outside of a loop"), -1);
- }
- if (nameLen > 60) {
- nameLen = 60;
- ellipsis = "...";
- }
- while ( (procName[nameLen] & 0xC0) == 0x80 ) {
- /*
- * Back up truncation point so that we don't truncate in the
- * middle of a multi-byte character (in UTF-8)
- */
- nameLen--;
- ellipsis = "...";
- }
- sprintf(msg, "\n (procedure \"%.*s%s\" line %d)", nameLen, procName,
- ellipsis, iPtr->errorLine);
- Tcl_AddObjErrorInfo(interp, msg, -1);
- return TCL_ERROR;
+ int overflow, limit = 60, nameLen;
+ const char *procName = Tcl_GetStringFromObj(procNameObj, &nameLen);
+
+ overflow = (nameLen > limit);
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (procedure \"%.*s%s\" line %d)",
+ (overflow ? limit : nameLen), procName,
+ (overflow ? "..." : ""), interp->errorLine));
}
/*
@@ -1586,24 +2109,24 @@ ProcessProcResultCode(interp, procName, nameLen, returnCode)
*
* TclProcDeleteProc --
*
- * This procedure is invoked just before a command procedure is
- * removed from an interpreter. Its job is to release all the
- * resources allocated to the procedure.
+ * This function is invoked just before a command procedure is removed
+ * from an interpreter. Its job is to release all the resources allocated
+ * to the procedure.
*
* Results:
* None.
*
* Side effects:
- * Memory gets freed, unless the procedure is actively being
- * executed. In this case the cleanup is delayed until the
- * last call to the current procedure completes.
+ * Memory gets freed, unless the procedure is actively being executed.
+ * In this case the cleanup is delayed until the last call to the current
+ * procedure completes.
*
*----------------------------------------------------------------------
*/
void
-TclProcDeleteProc(clientData)
- ClientData clientData; /* Procedure to be deleted. */
+TclProcDeleteProc(
+ ClientData clientData) /* Procedure to be deleted. */
{
Proc *procPtr = (Proc *) clientData;
@@ -1618,9 +2141,8 @@ TclProcDeleteProc(clientData)
*
* TclProcCleanupProc --
*
- * This procedure does all the real work of freeing up a Proc
- * structure. It's called only when the structure's reference
- * count becomes zero.
+ * This function does all the real work of freeing up a Proc structure.
+ * It's called only when the structure's reference count becomes zero.
*
* Results:
* None.
@@ -1632,33 +2154,31 @@ TclProcDeleteProc(clientData)
*/
void
-TclProcCleanupProc(procPtr)
- register Proc *procPtr; /* Procedure to be deleted. */
+TclProcCleanupProc(
+ register Proc *procPtr) /* Procedure to be deleted. */
{
register CompiledLocal *localPtr;
Tcl_Obj *bodyPtr = procPtr->bodyPtr;
Tcl_Obj *defPtr;
Tcl_ResolvedVarInfo *resVarInfo;
-#ifdef TCL_TIP280
- Tcl_HashEntry* hePtr = NULL;
- CmdFrame* cfPtr = NULL;
- Interp* iPtr = procPtr->iPtr;
-#endif
+ Tcl_HashEntry *hePtr = NULL;
+ CmdFrame *cfPtr = NULL;
+ Interp *iPtr = procPtr->iPtr;
if (bodyPtr != NULL) {
Tcl_DecrRefCount(bodyPtr);
}
- for (localPtr = procPtr->firstLocalPtr; localPtr != NULL; ) {
+ for (localPtr = procPtr->firstLocalPtr; localPtr != NULL; ) {
CompiledLocal *nextPtr = localPtr->nextPtr;
- resVarInfo = localPtr->resolveInfo;
+ resVarInfo = localPtr->resolveInfo;
if (resVarInfo) {
if (resVarInfo->deleteProc) {
(*resVarInfo->deleteProc)(resVarInfo);
} else {
ckfree((char *) resVarInfo);
}
- }
+ }
if (localPtr->defValuePtr != NULL) {
defPtr = localPtr->defValuePtr;
@@ -1669,27 +2189,32 @@ TclProcCleanupProc(procPtr)
}
ckfree((char *) procPtr);
-#ifdef TCL_TIP280
- /* TIP #280. Release the location data associated with this Proc
+ /*
+ * TIP #280: Release the location data associated with this Proc
* structure, if any. The interpreter may not exist (For example for
- * procbody structurues created by tbcload.
+ * procbody structures created by tbcload. See also Tcl_ProcObjCmd(), when
+ * the same ProcPtr is overwritten with a new CmdFrame.
*/
- if (!iPtr) return;
+ if (!iPtr) {
+ return;
+ }
- hePtr = Tcl_FindHashEntry (iPtr->linePBodyPtr, (char *) procPtr);
- if (!hePtr) return;
+ hePtr = Tcl_FindHashEntry(iPtr->linePBodyPtr, (char *) procPtr);
+ if (!hePtr) {
+ return;
+ }
- cfPtr = (CmdFrame*) Tcl_GetHashValue (hePtr);
+ cfPtr = (CmdFrame *) Tcl_GetHashValue(hePtr);
if (cfPtr->type == TCL_LOCATION_SOURCE) {
- Tcl_DecrRefCount (cfPtr->data.eval.path);
+ Tcl_DecrRefCount(cfPtr->data.eval.path);
cfPtr->data.eval.path = NULL;
}
- ckfree ((char*) cfPtr->line); cfPtr->line = NULL;
- ckfree ((char*) cfPtr);
- Tcl_DeleteHashEntry (hePtr);
-#endif
+ ckfree((char *) cfPtr->line);
+ cfPtr->line = NULL;
+ ckfree((char *) cfPtr);
+ Tcl_DeleteHashEntry(hePtr);
}
/*
@@ -1697,47 +2222,44 @@ TclProcCleanupProc(procPtr)
*
* TclUpdateReturnInfo --
*
- * This procedure is called when procedures return, and at other
- * points where the TCL_RETURN code is used. It examines fields
- * such as iPtr->returnCode and iPtr->errorCode and modifies
- * the real return status accordingly.
+ * This function is called when procedures return, and at other points
+ * where the TCL_RETURN code is used. It examines the returnLevel and
+ * returnCode to determine the real return status.
*
* Results:
- * The return value is the true completion code to use for
- * the procedure, instead of TCL_RETURN.
+ * The return value is the true completion code to use for the procedure
+ * or script, instead of TCL_RETURN.
*
* Side effects:
- * The errorInfo and errorCode variables may get modified.
+ * None.
*
*----------------------------------------------------------------------
*/
int
-TclUpdateReturnInfo(iPtr)
- Interp *iPtr; /* Interpreter for which TCL_RETURN
- * exception is being processed. */
+TclUpdateReturnInfo(
+ Interp *iPtr) /* Interpreter for which TCL_RETURN exception
+ * is being processed. */
{
- int code;
- char *errorCode;
- Tcl_Obj *objPtr;
+ int code = TCL_RETURN;
- code = iPtr->returnCode;
- iPtr->returnCode = TCL_OK;
- if (code == TCL_ERROR) {
- errorCode = ((iPtr->errorCode != NULL) ? iPtr->errorCode : "NONE");
- objPtr = Tcl_NewStringObj(errorCode, -1);
- Tcl_IncrRefCount(objPtr);
- Tcl_ObjSetVar2((Tcl_Interp *) iPtr, iPtr->execEnvPtr->errorCode,
- NULL, objPtr, TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(objPtr);
- iPtr->flags |= ERROR_CODE_SET;
- if (iPtr->errorInfo != NULL) {
- objPtr = Tcl_NewStringObj(iPtr->errorInfo, -1);
- Tcl_IncrRefCount(objPtr);
- Tcl_ObjSetVar2((Tcl_Interp *) iPtr, iPtr->execEnvPtr->errorInfo,
- NULL, objPtr, TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(objPtr);
- iPtr->flags |= ERR_IN_PROGRESS;
+ iPtr->returnLevel--;
+ if (iPtr->returnLevel < 0) {
+ Tcl_Panic("TclUpdateReturnInfo: negative return level");
+ }
+ if (iPtr->returnLevel == 0) {
+ /*
+ * Now we've reached the level to return the requested -code.
+ * Since iPtr->returnLevel and iPtr->returnCode have completed
+ * their task, we now reset them to default values so that any
+ * bare "return TCL_RETURN" that may follow will work [Bug 2152286].
+ */
+
+ code = iPtr->returnCode;
+ iPtr->returnLevel = 1;
+ iPtr->returnCode = TCL_OK;
+ if (code == TCL_ERROR) {
+ iPtr->flags |= ERR_LEGACY_COPY;
}
}
return code;
@@ -1746,49 +2268,24 @@ TclUpdateReturnInfo(iPtr)
/*
*----------------------------------------------------------------------
*
- * TclGetInterpProc --
- *
- * Returns a pointer to the TclProcInterpProc procedure; this is different
- * from the value obtained from the TclProcInterpProc reference on systems
- * like Windows where import and export versions of a procedure exported
- * by a DLL exist.
- *
- * Results:
- * Returns the internal address of the TclProcInterpProc procedure.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-TclCmdProcType
-TclGetInterpProc()
-{
- return (TclCmdProcType) TclProcInterpProc;
-}
-
-/*
- *----------------------------------------------------------------------
- *
* TclGetObjInterpProc --
*
- * Returns a pointer to the TclObjInterpProc procedure; this is different
- * from the value obtained from the TclObjInterpProc reference on systems
- * like Windows where import and export versions of a procedure exported
- * by a DLL exist.
+ * Returns a pointer to the TclObjInterpProc function; this is different
+ * from the value obtained from the TclObjInterpProc reference on systems
+ * like Windows where import and export versions of a function exported
+ * by a DLL exist.
*
* Results:
- * Returns the internal address of the TclObjInterpProc procedure.
+ * Returns the internal address of the TclObjInterpProc function.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
TclObjCmdProcType
-TclGetObjInterpProc()
+TclGetObjInterpProc(void)
{
return (TclObjCmdProcType) TclObjInterpProc;
}
@@ -1798,38 +2295,37 @@ TclGetObjInterpProc()
*
* TclNewProcBodyObj --
*
- * Creates a new object, of type "procbody", whose internal
- * representation is the given Proc struct.
- * The newly created object's reference count is 0.
+ * Creates a new object, of type "procbody", whose internal
+ * representation is the given Proc struct. The newly created object's
+ * reference count is 0.
*
* Results:
- * Returns a pointer to a newly allocated Tcl_Obj, 0 on error.
+ * Returns a pointer to a newly allocated Tcl_Obj, NULL on error.
*
* Side effects:
- * The reference count in the ByteCode attached to the Proc is bumped up
- * by one, since the internal rep stores a pointer to it.
+ * The reference count in the ByteCode attached to the Proc is bumped up
+ * by one, since the internal rep stores a pointer to it.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
-TclNewProcBodyObj(procPtr)
- Proc *procPtr; /* the Proc struct to store as the internal
- * representation. */
+TclNewProcBodyObj(
+ Proc *procPtr) /* the Proc struct to store as the internal
+ * representation. */
{
Tcl_Obj *objPtr;
if (!procPtr) {
- return (Tcl_Obj *) NULL;
+ return NULL;
}
- objPtr = Tcl_NewStringObj("", 0);
-
+ TclNewObj(objPtr);
if (objPtr) {
- objPtr->typePtr = &tclProcBodyType;
- objPtr->internalRep.otherValuePtr = (VOID *) procPtr;
+ objPtr->typePtr = &tclProcBodyType;
+ objPtr->internalRep.otherValuePtr = procPtr;
- procPtr->refCount++;
+ procPtr->refCount++;
}
return objPtr;
@@ -1840,27 +2336,27 @@ TclNewProcBodyObj(procPtr)
*
* ProcBodyDup --
*
- * Tcl_ObjType's Dup function for the proc body object.
- * Bumps the reference count on the Proc stored in the internal
- * representation.
+ * Tcl_ObjType's Dup function for the proc body object. Bumps the
+ * reference count on the Proc stored in the internal representation.
*
* Results:
- * None.
+ * None.
*
* Side effects:
- * Sets up the object in dupPtr to be a duplicate of the one in srcPtr.
+ * Sets up the object in dupPtr to be a duplicate of the one in srcPtr.
*
*----------------------------------------------------------------------
*/
-static void ProcBodyDup(srcPtr, dupPtr)
- Tcl_Obj *srcPtr; /* object to copy */
- Tcl_Obj *dupPtr; /* target object for the duplication */
+static void
+ProcBodyDup(
+ Tcl_Obj *srcPtr, /* Object to copy. */
+ Tcl_Obj *dupPtr) /* Target object for the duplication. */
{
- Proc *procPtr = (Proc *) srcPtr->internalRep.otherValuePtr;
+ Proc *procPtr = srcPtr->internalRep.otherValuePtr;
dupPtr->typePtr = &tclProcBodyType;
- dupPtr->internalRep.otherValuePtr = (VOID *) procPtr;
+ dupPtr->internalRep.otherValuePtr = procPtr;
procPtr->refCount++;
}
@@ -1869,130 +2365,540 @@ static void ProcBodyDup(srcPtr, dupPtr)
*
* ProcBodyFree --
*
- * Tcl_ObjType's Free function for the proc body object.
- * The reference count on its Proc struct is decreased by 1; if the count
- * reaches 0, the proc is freed.
+ * Tcl_ObjType's Free function for the proc body object. The reference
+ * count on its Proc struct is decreased by 1; if the count reaches 0,
+ * the proc is freed.
*
* Results:
- * None.
+ * None.
*
* Side effects:
- * If the reference count on the Proc struct reaches 0, the struct is freed.
+ * If the reference count on the Proc struct reaches 0, the struct is
+ * freed.
*
*----------------------------------------------------------------------
*/
static void
-ProcBodyFree(objPtr)
- Tcl_Obj *objPtr; /* the object to clean up */
+ProcBodyFree(
+ Tcl_Obj *objPtr) /* The object to clean up. */
{
- Proc *procPtr = (Proc *) objPtr->internalRep.otherValuePtr;
+ Proc *procPtr = objPtr->internalRep.otherValuePtr;
+
procPtr->refCount--;
if (procPtr->refCount <= 0) {
- TclProcCleanupProc(procPtr);
+ TclProcCleanupProc(procPtr);
}
}
/*
*----------------------------------------------------------------------
*
- * ProcBodySetFromAny --
- *
- * Tcl_ObjType's SetFromAny function for the proc body object.
- * Calls panic.
- *
- * Results:
- * Theoretically returns a TCL result code.
+ * DupLambdaInternalRep, FreeLambdaInternalRep, SetLambdaFromAny --
*
- * Side effects:
- * Calls panic, since we can't set the value of the object from a string
- * representation (or any other internal ones).
+ * How to manage the internal representations of lambda term objects.
+ * Syntactically they look like a two- or three-element list, where the
+ * first element is the formal arguments, the second is the the body, and
+ * the (optional) third is the namespace to execute the lambda term
+ * within (the global namespace is assumed if it is absent).
*
*----------------------------------------------------------------------
*/
+static void
+DupLambdaInternalRep(
+ Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
+ register Tcl_Obj *copyPtr) /* Object with internal rep to set. */
+{
+ Proc *procPtr = srcPtr->internalRep.twoPtrValue.ptr1;
+ Tcl_Obj *nsObjPtr = srcPtr->internalRep.twoPtrValue.ptr2;
+
+ copyPtr->internalRep.twoPtrValue.ptr1 = procPtr;
+ copyPtr->internalRep.twoPtrValue.ptr2 = nsObjPtr;
+
+ procPtr->refCount++;
+ Tcl_IncrRefCount(nsObjPtr);
+ copyPtr->typePtr = &lambdaType;
+}
+
+static void
+FreeLambdaInternalRep(
+ register Tcl_Obj *objPtr) /* CmdName object with internal representation
+ * to free. */
+{
+ Proc *procPtr = objPtr->internalRep.twoPtrValue.ptr1;
+ Tcl_Obj *nsObjPtr = objPtr->internalRep.twoPtrValue.ptr2;
+
+ procPtr->refCount--;
+ if (procPtr->refCount == 0) {
+ TclProcCleanupProc(procPtr);
+ }
+ TclDecrRefCount(nsObjPtr);
+ objPtr->typePtr = NULL;
+}
+
static int
-ProcBodySetFromAny(interp, objPtr)
- Tcl_Interp *interp; /* current interpreter */
- Tcl_Obj *objPtr; /* object pointer */
+SetLambdaFromAny(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ register Tcl_Obj *objPtr) /* The object to convert. */
{
- panic("called ProcBodySetFromAny");
+ Interp *iPtr = (Interp *) interp;
+ char *name;
+ Tcl_Obj *argsPtr, *bodyPtr, *nsObjPtr, **objv, *errPtr;
+ int objc, result;
+ Proc *procPtr;
+
+ if (interp == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Convert objPtr to list type first; if it cannot be converted, or if its
+ * length is not 2, then it cannot be converted to lambdaType.
+ */
+
+ result = TclListObjGetElements(NULL, objPtr, &objc, &objv);
+ if ((result != TCL_OK) || ((objc != 2) && (objc != 3))) {
+ TclNewLiteralStringObj(errPtr, "can't interpret \"");
+ Tcl_AppendObjToObj(errPtr, objPtr);
+ Tcl_AppendToObj(errPtr, "\" as a lambda expression", -1);
+ Tcl_SetObjResult(interp, errPtr);
+ return TCL_ERROR;
+ }
+
+ argsPtr = objv[0];
+ bodyPtr = objv[1];
+
+ /*
+ * Create and initialize the Proc struct. The cmdPtr field is set to NULL
+ * to signal that this is an anonymous function.
+ */
+
+ name = TclGetString(objPtr);
+
+ if (TclCreateProc(interp, /*ignored nsPtr*/ NULL, name, argsPtr, bodyPtr,
+ &procPtr) != TCL_OK) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (parsing lambda expression \"%s\")", name));
+ return TCL_ERROR;
+ }
+
+ /*
+ * CAREFUL: TclCreateProc returns refCount==1! [Bug 1578454]
+ * procPtr->refCount = 1;
+ */
+
+ procPtr->cmdPtr = NULL;
+
+ /*
+ * TIP #280: Remember the line the apply body is starting on. In a Byte
+ * code context we ask the engine to provide us with the necessary
+ * information. This is for the initialization of the byte code compiler
+ * when the body is used for the first time.
+ *
+ * NOTE: The body is the second word in the 'objPtr'. Its location,
+ * accessible through 'context.line[1]' (see below) is therefore only the
+ * first approximation of the actual line the body is on. We have to use
+ * the string rep of the 'objPtr' to determine the exact line. This is
+ * available already through 'name'. Use 'TclListLines', see 'switch'
+ * (tclCmdMZ.c).
+ *
+ * This code is nearly identical to the #280 code in Tcl_ProcObjCmd, see
+ * this file. The differences are the different index of the body in the
+ * line array of the context, and the special processing mentioned in the
+ * previous paragraph to track into the list. Find a way to factor the
+ * common elements into a single function.
+ */
+
+ if (iPtr->cmdFramePtr) {
+ CmdFrame *contextPtr;
+
+ contextPtr = (CmdFrame *) TclStackAlloc(interp, sizeof(CmdFrame));
+ *contextPtr = *iPtr->cmdFramePtr;
+
+ if (contextPtr->type == TCL_LOCATION_BC) {
+ /*
+ * Retrieve the source context from the bytecode. This call
+ * accounts for the reference to the source file, if any, held in
+ * 'context.data.eval.path'.
+ */
+
+ TclGetSrcInfoForPc(contextPtr);
+ } else if (contextPtr->type == TCL_LOCATION_SOURCE) {
+ /*
+ * We created a new reference to the source file path name when we
+ * created 'context' above. Account for the reference.
+ */
+
+ Tcl_IncrRefCount(contextPtr->data.eval.path);
+
+ }
+
+ if (contextPtr->type == TCL_LOCATION_SOURCE) {
+ /*
+ * We can record source location within a lambda only if the body
+ * was not created by substitution.
+ */
+
+ if (contextPtr->line
+ && (contextPtr->nline >= 2) && (contextPtr->line[1] >= 0)) {
+ int isNew, buf[2];
+ CmdFrame *cfPtr = (CmdFrame *) ckalloc(sizeof(CmdFrame));
+
+ /*
+ * Move from approximation (line of list cmd word) to actual
+ * location (line of 2nd list element).
+ */
+
+ TclListLines(objPtr, contextPtr->line[1], 2, buf, NULL);
+
+ cfPtr->level = -1;
+ cfPtr->type = contextPtr->type;
+ cfPtr->line = (int *) ckalloc(sizeof(int));
+ cfPtr->line[0] = buf[1];
+ cfPtr->nline = 1;
+ cfPtr->framePtr = NULL;
+ cfPtr->nextPtr = NULL;
+
+ cfPtr->data.eval.path = contextPtr->data.eval.path;
+ Tcl_IncrRefCount(cfPtr->data.eval.path);
+
+ cfPtr->cmd.str.cmd = NULL;
+ cfPtr->cmd.str.len = 0;
+
+ Tcl_SetHashValue(Tcl_CreateHashEntry(iPtr->linePBodyPtr,
+ (char *) procPtr, &isNew), cfPtr);
+ }
+
+ /*
+ * 'contextPtr' is going out of scope. Release the reference that
+ * it's holding to the source file path
+ */
+
+ Tcl_DecrRefCount(contextPtr->data.eval.path);
+ }
+ TclStackFree(interp, contextPtr);
+ }
+
+ /*
+ * Set the namespace for this lambda: given by objv[2] understood as a
+ * global reference, or else global per default.
+ */
+
+ if (objc == 2) {
+ TclNewLiteralStringObj(nsObjPtr, "::");
+ } else {
+ char *nsName = TclGetString(objv[2]);
+
+ if ((*nsName != ':') || (*(nsName+1) != ':')) {
+ TclNewLiteralStringObj(nsObjPtr, "::");
+ Tcl_AppendObjToObj(nsObjPtr, objv[2]);
+ } else {
+ nsObjPtr = objv[2];
+ }
+ }
+
+ Tcl_IncrRefCount(nsObjPtr);
/*
- * this to keep compilers happy.
+ * Free the list internalrep of objPtr - this will free argsPtr, but
+ * bodyPtr retains a reference from the Proc structure. Then finish the
+ * conversion to lambdaType.
*/
+ objPtr->typePtr->freeIntRepProc(objPtr);
+
+ objPtr->internalRep.twoPtrValue.ptr1 = procPtr;
+ objPtr->internalRep.twoPtrValue.ptr2 = nsObjPtr;
+ objPtr->typePtr = &lambdaType;
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * ProcBodyUpdateString --
+ * Tcl_ApplyObjCmd --
*
- * Tcl_ObjType's UpdateString function for the proc body object.
- * Calls panic.
+ * This object-based function is invoked to process the "apply" Tcl
+ * command. See the user documentation for details on what it does.
*
* Results:
- * None.
+ * A standard Tcl object result value.
*
* Side effects:
- * Calls panic, since we this type has no string representation.
+ * Depends on the content of the lambda term (i.e., objv[1]).
*
*----------------------------------------------------------------------
*/
-static void
-ProcBodyUpdateString(objPtr)
- Tcl_Obj *objPtr; /* the object to update */
+int
+Tcl_ApplyObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
- panic("called ProcBodyUpdateString");
-}
+ Interp *iPtr = (Interp *) interp;
+ Proc *procPtr = NULL;
+ Tcl_Obj *lambdaPtr, *nsObjPtr;
+ int result, isRootEnsemble;
+ Command cmd;
+ Tcl_Namespace *nsPtr;
+ ExtraFrameInfo efi;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "lambdaExpr ?arg1 arg2 ...?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Set lambdaPtr, convert it to lambdaType in the current interp if
+ * necessary.
+ */
+
+ lambdaPtr = objv[1];
+ if (lambdaPtr->typePtr == &lambdaType) {
+ procPtr = lambdaPtr->internalRep.twoPtrValue.ptr1;
+ }
+
+#define JOE_EXTENSION 0
+#if JOE_EXTENSION
+ else {
+ /*
+ * Joe English's suggestion to allow cmdNames to function as lambdas.
+ * Also requires making tclCmdNameType non-static in tclObj.c
+ */
+
+ Tcl_Obj *elemPtr;
+ int numElem;
+
+ if ((lambdaPtr->typePtr == &tclCmdNameType) ||
+ (TclListObjGetElements(interp, lambdaPtr, &numElem,
+ &elemPtr) == TCL_OK && numElem == 1)) {
+ return Tcl_EvalObjv(interp, objc-1, objv+1, 0);
+ }
+ }
+#endif
+
+ if ((procPtr == NULL) || (procPtr->iPtr != iPtr)) {
+ result = SetLambdaFromAny(interp, lambdaPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ procPtr = lambdaPtr->internalRep.twoPtrValue.ptr1;
+ }
+ memset(&cmd, 0, sizeof(Command));
+ procPtr->cmdPtr = &cmd;
+ /*
+ * TIP#280 (semi-)HACK!
+ *
+ * Using cmd.clientData to tell [info frame] how to render the
+ * 'lambdaPtr'. The InfoFrameCmd will detect this case by testing cmd.hPtr
+ * for NULL. This condition holds here because of the 'memset' above, and
+ * nowhere else (in the core). Regular commands always have a valid
+ * 'hPtr', and lambda's never.
+ */
+
+ efi.length = 1;
+ efi.fields[0].name = "lambda";
+ efi.fields[0].proc = NULL;
+ efi.fields[0].clientData = lambdaPtr;
+ cmd.clientData = &efi;
+
+ /*
+ * Find the namespace where this lambda should run, and push a call frame
+ * for that namespace. Note that TclObjInterpProc() will pop it.
+ */
+
+ nsObjPtr = lambdaPtr->internalRep.twoPtrValue.ptr2;
+ result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ cmd.nsPtr = (Namespace *) nsPtr;
+
+ isRootEnsemble = (iPtr->ensembleRewrite.sourceObjs == NULL);
+ if (isRootEnsemble) {
+ iPtr->ensembleRewrite.sourceObjs = objv;
+ iPtr->ensembleRewrite.numRemovedObjs = 1;
+ iPtr->ensembleRewrite.numInsertedObjs = 0;
+ } else {
+ iPtr->ensembleRewrite.numInsertedObjs -= 1;
+ }
+
+ result = PushProcCallFrame((ClientData) procPtr, interp, objc, objv, 1);
+ if (result == TCL_OK) {
+ result = TclObjInterpProcCore(interp, objv[1], 2, &MakeLambdaError);
+ }
+
+ if (isRootEnsemble) {
+ iPtr->ensembleRewrite.sourceObjs = NULL;
+ iPtr->ensembleRewrite.numRemovedObjs = 0;
+ iPtr->ensembleRewrite.numInsertedObjs = 0;
+ }
+
+ return result;
+}
+
/*
*----------------------------------------------------------------------
*
- * TclCompileNoOp --
+ * MakeLambdaError --
*
- * Procedure called to compile noOp's
+ * Function called by TclObjInterpProc to create the stack information
+ * upon an error from a lambda term.
*
* Results:
- * The return value is TCL_OK, indicating successful compilation.
+ * The interpreter's error info trace is set to a value that supplements
+ * the error code.
*
* Side effects:
- * Instructions are added to envPtr to execute a noOp at runtime.
+ * none.
*
*----------------------------------------------------------------------
*/
-static int
-TclCompileNoOp(interp, parsePtr, envPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Parse *parsePtr; /* Points to a parse structure for the
- * command created by Tcl_ParseCommand. */
- CompileEnv *envPtr; /* Holds resulting instructions. */
+static void
+MakeLambdaError(
+ Tcl_Interp *interp, /* The interpreter in which the procedure was
+ * called. */
+ Tcl_Obj *procNameObj) /* Name of the procedure. Used for error
+ * messages and trace information. */
+{
+ int overflow, limit = 60, nameLen;
+ const char *procName = Tcl_GetStringFromObj(procNameObj, &nameLen);
+
+ overflow = (nameLen > limit);
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (lambda term \"%.*s%s\" line %d)",
+ (overflow ? limit : nameLen), procName,
+ (overflow ? "..." : ""), interp->errorLine));
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DisassembleObjCmd --
+ *
+ * Implementation of the "::tcl::unsupported::disassemble" command. This
+ * command is not documented, but will disassemble procedures, lambda
+ * terms and general scripts. Note that will compile terms if necessary
+ * in order to disassemble them.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_DisassembleObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
- Tcl_Token *tokenPtr;
- int i, code;
- int savedStackDepth = envPtr->currStackDepth;
-
- tokenPtr = parsePtr->tokenPtr;
- for(i = 1; i < parsePtr->numWords; i++) {
- tokenPtr = tokenPtr + tokenPtr->numComponents + 1;
- envPtr->currStackDepth = savedStackDepth;
-
- if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
- code = TclCompileTokens(interp, tokenPtr+1,
- tokenPtr->numComponents, envPtr);
- if (code != TCL_OK) {
- return code;
+ static const char *types[] = {
+ "lambda", "proc", "script", NULL
+ };
+ enum Types {
+ DISAS_LAMBDA, DISAS_PROC, DISAS_SCRIPT
+ };
+ int idx, result;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "type procName|lambdaTerm|script");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[1], types, "type", 0, &idx)!=TCL_OK){
+ return TCL_ERROR;
+ }
+
+ switch ((enum Types) idx) {
+ case DISAS_LAMBDA: {
+ Proc *procPtr = NULL;
+ Command cmd;
+ Tcl_Obj *nsObjPtr;
+ Tcl_Namespace *nsPtr;
+
+ /*
+ * Compile (if uncompiled) and disassemble a lambda term.
+ */
+
+ if (objv[2]->typePtr == &lambdaType) {
+ procPtr = objv[2]->internalRep.twoPtrValue.ptr1;
+ }
+ if (procPtr == NULL || procPtr->iPtr != (Interp *) interp) {
+ result = SetLambdaFromAny(interp, objv[2]);
+ if (result != TCL_OK) {
+ return result;
}
- TclEmitOpcode(INST_POP, envPtr);
+ procPtr = objv[2]->internalRep.twoPtrValue.ptr1;
}
+
+ memset(&cmd, 0, sizeof(Command));
+ nsObjPtr = objv[2]->internalRep.twoPtrValue.ptr2;
+ result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ cmd.nsPtr = (Namespace *) nsPtr;
+ procPtr->cmdPtr = &cmd;
+ result = PushProcCallFrame(procPtr, interp, objc, objv, 1);
+ if (result != TCL_OK) {
+ return result;
+ }
+ TclPopStackFrame(interp);
+ if (((ByteCode *) procPtr->bodyPtr->internalRep.otherValuePtr)->flags
+ & TCL_BYTECODE_PRECOMPILED) {
+ Tcl_AppendResult(interp, "may not disassemble prebuilt bytecode",
+ NULL);
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, TclDisassembleByteCodeObj(procPtr->bodyPtr));
+ break;
+ }
+ case DISAS_PROC: {
+ Proc *procPtr = TclFindProc((Interp *) interp, TclGetString(objv[2]));
+
+ if (procPtr == NULL) {
+ Tcl_AppendResult(interp, "\"", TclGetString(objv[2]),
+ "\" isn't a procedure", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Compile (if uncompiled) and disassemble a procedure.
+ */
+
+ result = PushProcCallFrame(procPtr, interp, 2, objv+1, 1);
+ if (result != TCL_OK) {
+ return result;
+ }
+ TclPopStackFrame(interp);
+ if (((ByteCode *) procPtr->bodyPtr->internalRep.otherValuePtr)->flags
+ & TCL_BYTECODE_PRECOMPILED) {
+ Tcl_AppendResult(interp, "may not disassemble prebuilt bytecode",
+ NULL);
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, TclDisassembleByteCodeObj(procPtr->bodyPtr));
+ break;
+ }
+ case DISAS_SCRIPT:
+ /*
+ * Compile and disassemble a script.
+ */
+
+ if (objv[2]->typePtr != &tclByteCodeType) {
+ if (TclSetByteCodeFromAny(interp, objv[2], NULL, NULL) != TCL_OK){
+ return TCL_ERROR;
+ }
+ }
+ Tcl_SetObjResult(interp, TclDisassembleByteCodeObj(objv[2]));
+ break;
}
- envPtr->currStackDepth = savedStackDepth;
- TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0), envPtr);
return TCL_OK;
}
@@ -2003,4 +2909,3 @@ TclCompileNoOp(interp, parsePtr, envPtr)
* fill-column: 78
* End:
*/
-
diff --git a/generic/tclRegexp.c b/generic/tclRegexp.c
index c161d69..d340f4c 100644
--- a/generic/tclRegexp.c
+++ b/generic/tclRegexp.c
@@ -1,24 +1,23 @@
-/*
+/*
* tclRegexp.c --
*
- * This file contains the public interfaces to the Tcl regular
- * expression mechanism.
+ * This file contains the public interfaces to the Tcl regular expression
+ * mechanism.
*
* Copyright (c) 1998 by 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.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
#include "tclRegexp.h"
/*
*----------------------------------------------------------------------
- * The routines in this file use Henry Spencer's regular expression
- * package contained in the following additional source files:
+ * The routines in this file use Henry Spencer's regular expression package
+ * contained in the following additional source files:
*
* regc_color.c regc_cvec.c regc_lex.c
* regc_nfa.c regcomp.c regcustom.h
@@ -27,23 +26,23 @@
* regfronts.c regguts.h
*
* Copyright (c) 1998 Henry Spencer. All rights reserved.
- *
+ *
* Development of this software was funded, in part, by Cray Research Inc.,
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
- * Corporation, none of whom are responsible for the results. The author
- * thanks all of them.
- *
+ * Corporation, none of whom are responsible for the results. The author
+ * thanks all of them.
+ *
* Redistribution and use in source and binary forms -- with or without
* modification -- are permitted for any purpose, provided that
* redistributions in source form retain this entire copyright notice and
* indicate the origin and nature of any modifications.
- *
- * I'd appreciate being given credit for this package in the documentation
- * of software which uses it, but that is not a requirement.
- *
+ *
+ * I'd appreciate being given credit for this package in the documentation of
+ * software which uses it, but that is not a requirement.
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
@@ -67,15 +66,14 @@
typedef struct ThreadSpecificData {
int initialized; /* Set to 1 when the module is initialized. */
- char *patterns[NUM_REGEXPS];/* Strings corresponding to compiled
- * regular expression patterns. NULL
- * means that this slot isn't used.
- * Malloc-ed. */
+ char *patterns[NUM_REGEXPS];/* Strings corresponding to compiled regular
+ * expression patterns. NULL means that this
+ * slot isn't used. Malloc-ed. */
int patLengths[NUM_REGEXPS];/* Number of non-null characters in
- * corresponding entry in patterns.
- * -1 means entry isn't used. */
+ * corresponding entry in patterns. -1 means
+ * entry isn't used. */
struct TclRegexp *regexps[NUM_REGEXPS];
- /* Compiled forms of above strings. Also
+ /* Compiled forms of above strings. Also
* malloc-ed, or NULL if not in use yet. */
} ThreadSpecificData;
@@ -85,49 +83,46 @@ static Tcl_ThreadDataKey dataKey;
* Declarations for functions used only in this file.
*/
-static TclRegexp * CompileRegexp _ANSI_ARGS_((Tcl_Interp *interp,
- CONST char *pattern, int length, int flags));
-static void DupRegexpInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
- Tcl_Obj *copyPtr));
-static void FinalizeRegexp _ANSI_ARGS_((ClientData clientData));
-static void FreeRegexp _ANSI_ARGS_((TclRegexp *regexpPtr));
-static void FreeRegexpInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr));
-static int RegExpExecUniChar _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_RegExp re, CONST Tcl_UniChar *uniString,
- int numChars, int nmatches, int flags));
-static int SetRegexpFromAny _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
+static TclRegexp * CompileRegexp(Tcl_Interp *interp, const char *pattern,
+ int length, int flags);
+static void DupRegexpInternalRep(Tcl_Obj *srcPtr,
+ Tcl_Obj *copyPtr);
+static void FinalizeRegexp(ClientData clientData);
+static void FreeRegexp(TclRegexp *regexpPtr);
+static void FreeRegexpInternalRep(Tcl_Obj *objPtr);
+static int RegExpExecUniChar(Tcl_Interp *interp, Tcl_RegExp re,
+ const Tcl_UniChar *uniString, int numChars,
+ int nmatches, int flags);
+static int SetRegexpFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
/*
- * The regular expression Tcl object type. This serves as a cache
- * of the compiled form of the regular expression.
+ * The regular expression Tcl object type. This serves as a cache of the
+ * compiled form of the regular expression.
*/
-static Tcl_ObjType tclRegexpType = {
+Tcl_ObjType tclRegexpType = {
"regexp", /* name */
FreeRegexpInternalRep, /* freeIntRepProc */
DupRegexpInternalRep, /* dupIntRepProc */
NULL, /* updateStringProc */
SetRegexpFromAny /* setFromAnyProc */
};
-
/*
*----------------------------------------------------------------------
*
* Tcl_RegExpCompile --
*
- * Compile a regular expression into a form suitable for fast
- * matching. This procedure is DEPRECATED in favor of the
- * object version of the command.
+ * Compile a regular expression into a form suitable for fast matching.
+ * This function is DEPRECATED in favor of the object version of the
+ * command.
*
* Results:
- * The return value is a pointer to the compiled form of string,
- * suitable for passing to Tcl_RegExpExec. This compiled form
- * is only valid up until the next call to this procedure, so
- * don't keep these around for a long time! If an error occurred
- * while compiling the pattern, then NULL is returned and an error
- * message is left in the interp's result.
+ * The return value is a pointer to the compiled form of string, suitable
+ * for passing to Tcl_RegExpExec. This compiled form is only valid up
+ * until the next call to this function, so don't keep these around for a
+ * long time! If an error occurred while compiling the pattern, then NULL
+ * is returned and an error message is left in the interp's result.
*
* Side effects:
* Updates the cache of compiled regexps.
@@ -136,13 +131,13 @@ static Tcl_ObjType tclRegexpType = {
*/
Tcl_RegExp
-Tcl_RegExpCompile(interp, string)
- Tcl_Interp *interp; /* For use in error reporting and
- * to access the interp regexp cache. */
- CONST char *string; /* String for which to produce
- * compiled regular expression. */
+Tcl_RegExpCompile(
+ Tcl_Interp *interp, /* For use in error reporting and to access
+ * the interp regexp cache. */
+ const char *pattern) /* String for which to produce compiled
+ * regular expression. */
{
- return (Tcl_RegExp) CompileRegexp(interp, string, (int) strlen(string),
+ return (Tcl_RegExp) CompileRegexp(interp, pattern, (int) strlen(pattern),
REG_ADVANCED);
}
@@ -151,15 +146,14 @@ Tcl_RegExpCompile(interp, string)
*
* Tcl_RegExpExec --
*
- * Execute the regular expression matcher using a compiled form
- * of a regular expression and save information about any match
- * that is found.
+ * Execute the regular expression matcher using a compiled form of a
+ * regular expression and save information about any match that is found.
*
* Results:
- * If an error occurs during the matching operation then -1
- * is returned and the interp's result contains an error message.
- * Otherwise the return value is 1 if a matching range is
- * found and 0 if there is no matching range.
+ * If an error occurs during the matching operation then -1 is returned
+ * and the interp's result contains an error message. Otherwise the
+ * return value is 1 if a matching range is found and 0 if there is no
+ * matching range.
*
* Side effects:
* None.
@@ -168,27 +162,27 @@ Tcl_RegExpCompile(interp, string)
*/
int
-Tcl_RegExpExec(interp, re, string, start)
- Tcl_Interp *interp; /* Interpreter to use for error reporting. */
- Tcl_RegExp re; /* Compiled regular expression; must have
- * been returned by previous call to
+Tcl_RegExpExec(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ Tcl_RegExp re, /* Compiled regular expression; must have been
+ * returned by previous call to
* Tcl_GetRegExpFromObj. */
- CONST char *string; /* String against which to match re. */
- CONST char *start; /* If string is part of a larger string,
- * this identifies beginning of larger
- * string, so that "^" won't match. */
+ const char *text, /* Text against which to match re. */
+ const char *start) /* If text is part of a larger string, this
+ * identifies beginning of larger string, so
+ * that "^" won't match. */
{
int flags, result, numChars;
TclRegexp *regexp = (TclRegexp *)re;
Tcl_DString ds;
- CONST Tcl_UniChar *ustr;
+ const Tcl_UniChar *ustr;
/*
- * If the starting point is offset from the beginning of the buffer,
- * then we need to tell the regexp engine not to match "^".
+ * If the starting point is offset from the beginning of the buffer, then
+ * we need to tell the regexp engine not to match "^".
*/
- if (string > start) {
+ if (text > start) {
flags = REG_NOTBOL;
} else {
flags = 0;
@@ -198,7 +192,7 @@ Tcl_RegExpExec(interp, re, string, start)
* Remember the string for use by Tcl_RegExpRange().
*/
- regexp->string = string;
+ regexp->string = text;
regexp->objPtr = NULL;
/*
@@ -206,10 +200,10 @@ Tcl_RegExpExec(interp, re, string, start)
*/
Tcl_DStringInit(&ds);
- ustr = Tcl_UtfToUniCharDString(string, -1, &ds);
+ ustr = Tcl_UtfToUniCharDString(text, -1, &ds);
numChars = Tcl_DStringLength(&ds) / sizeof(Tcl_UniChar);
- result = RegExpExecUniChar(interp, re, ustr, numChars,
- -1 /* nmatches */, flags);
+ result = RegExpExecUniChar(interp, re, ustr, numChars, -1 /* nmatches */,
+ flags);
Tcl_DStringFree(&ds);
return result;
@@ -225,7 +219,7 @@ Tcl_RegExpExec(interp, re, string, start)
*
* Results:
* The variables at *startPtr and *endPtr are modified to hold the
- * addresses of the endpoints of the range given by index. If the
+ * addresses of the endpoints of the range given by index. If the
* specified range doesn't exist then NULLs are returned.
*
* Side effects:
@@ -235,19 +229,19 @@ Tcl_RegExpExec(interp, re, string, start)
*/
void
-Tcl_RegExpRange(re, index, startPtr, endPtr)
- Tcl_RegExp re; /* Compiled regular expression that has
- * been passed to Tcl_RegExpExec. */
- int index; /* 0 means give the range of the entire
- * match, > 0 means give the range of
- * a matching subrange. */
- CONST char **startPtr; /* Store address of first character in
- * (sub-) range here. */
- CONST char **endPtr; /* Store address of character just after last
- * in (sub-) range here. */
+Tcl_RegExpRange(
+ Tcl_RegExp re, /* Compiled regular expression that has been
+ * passed to Tcl_RegExpExec. */
+ int index, /* 0 means give the range of the entire match,
+ * > 0 means give the range of a matching
+ * subrange. */
+ const char **startPtr, /* Store address of first character in
+ * (sub-)range here. */
+ const char **endPtr) /* Store address of character just after last
+ * in (sub-)range here. */
{
TclRegexp *regexpPtr = (TclRegexp *) re;
- CONST char *string;
+ const char *string;
if ((size_t) index > regexpPtr->re.re_nsub) {
*startPtr = *endPtr = NULL;
@@ -255,7 +249,7 @@ Tcl_RegExpRange(re, index, startPtr, endPtr)
*startPtr = *endPtr = NULL;
} else {
if (regexpPtr->objPtr) {
- string = Tcl_GetString(regexpPtr->objPtr);
+ string = TclGetString(regexpPtr->objPtr);
} else {
string = regexpPtr->string;
}
@@ -270,14 +264,13 @@ Tcl_RegExpRange(re, index, startPtr, endPtr)
* RegExpExecUniChar --
*
* Execute the regular expression matcher using a compiled form of a
- * regular expression and save information about any match that is
- * found.
+ * regular expression and save information about any match that is found.
*
* Results:
- * If an error occurs during the matching operation then -1 is
- * returned and an error message is left in interp's result.
- * Otherwise the return value is 1 if a matching range was found or
- * 0 if there was no matching range.
+ * If an error occurs during the matching operation then -1 is returned
+ * and an error message is left in interp's result. Otherwise the return
+ * value is 1 if a matching range was found or 0 if there was no matching
+ * range.
*
* Side effects:
* None.
@@ -286,17 +279,17 @@ Tcl_RegExpRange(re, index, startPtr, endPtr)
*/
static int
-RegExpExecUniChar(interp, re, wString, numChars, nmatches, flags)
- Tcl_Interp *interp; /* Interpreter to use for error reporting. */
- Tcl_RegExp re; /* Compiled regular expression; returned by
- * a previous call to Tcl_GetRegExpFromObj */
- CONST Tcl_UniChar *wString; /* String against which to match re. */
- int numChars; /* Length of Tcl_UniChar string (must
- * be >= 0). */
- int nmatches; /* How many subexpression matches (counting
- * the whole match as subexpression 0) are
- * of interest. -1 means "don't know". */
- int flags; /* Regular expression flags. */
+RegExpExecUniChar(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ Tcl_RegExp re, /* Compiled regular expression; returned by a
+ * previous call to Tcl_GetRegExpFromObj */
+ const Tcl_UniChar *wString, /* String against which to match re. */
+ int numChars, /* Length of Tcl_UniChar string (must be
+ * >=0). */
+ int nmatches, /* How many subexpression matches (counting
+ * the whole match as subexpression 0) are of
+ * interest. -1 means "don't know". */
+ int flags) /* Regular expression flags. */
{
int status;
TclRegexp *regexpPtr = (TclRegexp *) re;
@@ -338,8 +331,8 @@ RegExpExecUniChar(interp, re, wString, numChars, nmatches, flags)
*
* Results:
* The variables at *startPtr and *endPtr are modified to hold the
- * offsets of the endpoints of the range given by index. If the
- * specified range doesn't exist then -1s are supplied.
+ * offsets of the endpoints of the range given by index. If the specified
+ * range doesn't exist then -1s are supplied.
*
* Side effects:
* None.
@@ -348,17 +341,17 @@ RegExpExecUniChar(interp, re, wString, numChars, nmatches, flags)
*/
void
-TclRegExpRangeUniChar(re, index, startPtr, endPtr)
- Tcl_RegExp re; /* Compiled regular expression that has
- * been passed to Tcl_RegExpExec. */
- int index; /* 0 means give the range of the entire
- * match, > 0 means give the range of
- * a matching subrange, -1 means the
- * range of the rm_extend field. */
- int *startPtr; /* Store address of first character in
- * (sub-) range here. */
- int *endPtr; /* Store address of character just after last
- * in (sub-) range here. */
+TclRegExpRangeUniChar(
+ Tcl_RegExp re, /* Compiled regular expression that has been
+ * passed to Tcl_RegExpExec. */
+ int index, /* 0 means give the range of the entire match,
+ * > 0 means give the range of a matching
+ * subrange, -1 means the range of the
+ * rm_extend field. */
+ int *startPtr, /* Store address of first character in
+ * (sub-)range here. */
+ int *endPtr) /* Store address of character just after last
+ * in (sub-)range here. */
{
TclRegexp *regexpPtr = (TclRegexp *) re;
@@ -382,10 +375,9 @@ TclRegExpRangeUniChar(re, index, startPtr, endPtr)
* See if a string matches a regular expression.
*
* Results:
- * If an error occurs during the matching operation then -1
- * is returned and the interp's result contains an error message.
- * Otherwise the return value is 1 if "string" matches "pattern"
- * and 0 otherwise.
+ * If an error occurs during the matching operation then -1 is returned
+ * and the interp's result contains an error message. Otherwise the
+ * return value is 1 if "text" matches "pattern" and 0 otherwise.
*
* Side effects:
* None.
@@ -394,11 +386,10 @@ TclRegExpRangeUniChar(re, index, startPtr, endPtr)
*/
int
-Tcl_RegExpMatch(interp, string, pattern)
- Tcl_Interp *interp; /* Used for error reporting. May be NULL. */
- CONST char *string; /* String. */
- CONST char *pattern; /* Regular expression to match against
- * string. */
+Tcl_RegExpMatch(
+ Tcl_Interp *interp, /* Used for error reporting. May be NULL. */
+ const char *text, /* Text to search for pattern matches. */
+ const char *pattern) /* Regular expression to match against text. */
{
Tcl_RegExp re;
@@ -406,7 +397,7 @@ Tcl_RegExpMatch(interp, string, pattern)
if (re == NULL) {
return -1;
}
- return Tcl_RegExpExec(interp, re, string, string);
+ return Tcl_RegExpExec(interp, re, text, text);
}
/*
@@ -417,10 +408,9 @@ Tcl_RegExpMatch(interp, string, pattern)
* Execute a precompiled regexp against the given object.
*
* Results:
- * If an error occurs during the matching operation then -1
- * is returned and the interp's result contains an error message.
- * Otherwise the return value is 1 if "string" matches "pattern"
- * and 0 otherwise.
+ * If an error occurs during the matching operation then -1 is returned
+ * and the interp's result contains an error message. Otherwise the
+ * return value is 1 if "string" matches "pattern" and 0 otherwise.
*
* Side effects:
* Converts the object to a Unicode object.
@@ -429,38 +419,59 @@ Tcl_RegExpMatch(interp, string, pattern)
*/
int
-Tcl_RegExpExecObj(interp, re, objPtr, offset, nmatches, flags)
- Tcl_Interp *interp; /* Interpreter to use for error reporting. */
- Tcl_RegExp re; /* Compiled regular expression; must have
- * been returned by previous call to
+Tcl_RegExpExecObj(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ Tcl_RegExp re, /* Compiled regular expression; must have been
+ * returned by previous call to
* Tcl_GetRegExpFromObj. */
- Tcl_Obj *objPtr; /* String against which to match re. */
- int offset; /* Character index that marks where matching
+ Tcl_Obj *textObj, /* Text against which to match re. */
+ int offset, /* Character index that marks where matching
* should begin. */
- int nmatches; /* How many subexpression matches (counting
- * the whole match as subexpression 0) are
- * of interest. -1 means all of them. */
- int flags; /* Regular expression execution flags. */
+ int nmatches, /* How many subexpression matches (counting
+ * the whole match as subexpression 0) are of
+ * interest. -1 means all of them. */
+ int flags) /* Regular expression execution flags. */
{
TclRegexp *regexpPtr = (TclRegexp *) re;
Tcl_UniChar *udata;
int length;
+ int reflags = regexpPtr->flags;
+#define TCL_REG_GLOBOK_FLAGS (TCL_REG_ADVANCED | TCL_REG_NOSUB | TCL_REG_NOCASE)
+
+ /*
+ * Take advantage of the equivalent glob pattern, if one exists.
+ * This is possible based only on the right mix of incoming flags (0)
+ * and regexp compile flags.
+ */
+ if ((offset == 0) && (nmatches == 0) && (flags == 0)
+ && !(reflags & ~TCL_REG_GLOBOK_FLAGS)
+ && (regexpPtr->globObjPtr != NULL)) {
+ int nocase = (reflags & TCL_REG_NOCASE) ? TCL_MATCH_NOCASE : 0;
+
+ /*
+ * Pass to TclStringMatchObj for obj-specific handling.
+ * XXX: Currently doesn't take advantage of exact-ness that
+ * XXX: TclReToGlob tells us about
+ */
+
+ return TclStringMatchObj(textObj, regexpPtr->globObjPtr, nocase);
+ }
/*
* Save the target object so we can extract strings from it later.
*/
regexpPtr->string = NULL;
- regexpPtr->objPtr = objPtr;
+ regexpPtr->objPtr = textObj;
- udata = Tcl_GetUnicodeFromObj(objPtr, &length);
+ udata = Tcl_GetUnicodeFromObj(textObj, &length);
if (offset > length) {
offset = length;
}
udata += offset;
length -= offset;
-
+
return RegExpExecUniChar(interp, re, udata, length, nmatches, flags);
}
@@ -472,10 +483,9 @@ Tcl_RegExpExecObj(interp, re, objPtr, offset, nmatches, flags)
* See if an object matches a regular expression.
*
* Results:
- * If an error occurs during the matching operation then -1
- * is returned and the interp's result contains an error message.
- * Otherwise the return value is 1 if "string" matches "pattern"
- * and 0 otherwise.
+ * If an error occurs during the matching operation then -1 is returned
+ * and the interp's result contains an error message. Otherwise the
+ * return value is 1 if "text" matches "pattern" and 0 otherwise.
*
* Side effects:
* Changes the internal rep of the pattern and string objects.
@@ -484,10 +494,10 @@ Tcl_RegExpExecObj(interp, re, objPtr, offset, nmatches, flags)
*/
int
-Tcl_RegExpMatchObj(interp, stringObj, patternObj)
- Tcl_Interp *interp; /* Used for error reporting. May be NULL. */
- Tcl_Obj *stringObj; /* Object containing the String to search. */
- Tcl_Obj *patternObj; /* Regular expression to match against
+Tcl_RegExpMatchObj(
+ Tcl_Interp *interp, /* Used for error reporting. May be NULL. */
+ Tcl_Obj *textObj, /* Object containing the String to search. */
+ Tcl_Obj *patternObj) /* Regular expression to match against
* string. */
{
Tcl_RegExp re;
@@ -497,7 +507,7 @@ Tcl_RegExpMatchObj(interp, stringObj, patternObj)
if (re == NULL) {
return -1;
}
- return Tcl_RegExpExecObj(interp, re, stringObj, 0 /* offset */,
+ return Tcl_RegExpExecObj(interp, re, textObj, 0 /* offset */,
0 /* nmatches */, 0 /* flags */);
}
@@ -518,9 +528,9 @@ Tcl_RegExpMatchObj(interp, stringObj, patternObj)
*/
void
-Tcl_RegExpGetInfo(regexp, infoPtr)
- Tcl_RegExp regexp; /* Pattern from which to get subexpressions. */
- Tcl_RegExpInfo *infoPtr; /* Match information is stored here. */
+Tcl_RegExpGetInfo(
+ Tcl_RegExp regexp, /* Pattern from which to get subexpressions. */
+ Tcl_RegExpInfo *infoPtr) /* Match information is stored here. */
{
TclRegexp *regexpPtr = (TclRegexp *) regexp;
@@ -534,14 +544,14 @@ Tcl_RegExpGetInfo(regexp, infoPtr)
*
* Tcl_GetRegExpFromObj --
*
- * Compile a regular expression into a form suitable for fast
- * matching. This procedure caches the result in a Tcl_Obj.
+ * Compile a regular expression into a form suitable for fast matching.
+ * This function caches the result in a Tcl_Obj.
*
* Results:
- * The return value is a pointer to the compiled form of string,
- * suitable for passing to Tcl_RegExpExec. If an error occurred
- * while compiling the pattern, then NULL is returned and an error
- * message is left in the interp's result.
+ * The return value is a pointer to the compiled form of string, suitable
+ * for passing to Tcl_RegExpExec. If an error occurred while compiling
+ * the pattern, then NULL is returned and an error message is left in the
+ * interp's result.
*
* Side effects:
* Updates the native rep of the Tcl_Obj.
@@ -550,25 +560,28 @@ Tcl_RegExpGetInfo(regexp, infoPtr)
*/
Tcl_RegExp
-Tcl_GetRegExpFromObj(interp, objPtr, flags)
- Tcl_Interp *interp; /* For use in error reporting, and to access
+Tcl_GetRegExpFromObj(
+ Tcl_Interp *interp, /* For use in error reporting, and to access
* the interp regexp cache. */
- Tcl_Obj *objPtr; /* Object whose string rep contains regular
- * expression pattern. Internal rep will be
+ Tcl_Obj *objPtr, /* Object whose string rep contains regular
+ * expression pattern. Internal rep will be
* changed to compiled form of this regular
* expression. */
- int flags; /* Regular expression compilation flags. */
+ int flags) /* Regular expression compilation flags. */
{
int length;
- Tcl_ObjType *typePtr;
TclRegexp *regexpPtr;
char *pattern;
- typePtr = objPtr->typePtr;
+ /*
+ * This is OK because we only actually interpret this value properly as a
+ * TclRegexp* when the type is tclRegexpType.
+ */
+
regexpPtr = (TclRegexp *) objPtr->internalRep.otherValuePtr;
- if ((typePtr != &tclRegexpType) || (regexpPtr->flags != flags)) {
- pattern = Tcl_GetStringFromObj(objPtr, &length);
+ if ((objPtr->typePtr != &tclRegexpType) || (regexpPtr->flags != flags)) {
+ pattern = TclGetStringFromObj(objPtr, &length);
regexpPtr = CompileRegexp(interp, pattern, length, flags);
if (regexpPtr == NULL) {
@@ -577,7 +590,7 @@ Tcl_GetRegExpFromObj(interp, objPtr, flags)
/*
* Add a reference to the regexp so it will persist even if it is
- * pushed out of the current thread's regexp cache. This reference
+ * pushed out of the current thread's regexp cache. This reference
* will be removed when the object's internal rep is freed.
*/
@@ -587,10 +600,8 @@ Tcl_GetRegExpFromObj(interp, objPtr, flags)
* Free the old representation and set our type.
*/
- if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
- (*typePtr->freeIntRepProc)(objPtr);
- }
- objPtr->internalRep.otherValuePtr = (VOID *) regexpPtr;
+ TclFreeIntRep(objPtr);
+ objPtr->internalRep.otherValuePtr = (void *) regexpPtr;
objPtr->typePtr = &tclRegexpType;
}
return (Tcl_RegExp) regexpPtr;
@@ -604,10 +615,10 @@ Tcl_GetRegExpFromObj(interp, objPtr, flags)
* Return information about a compiled regular expression.
*
* Results:
- * The return value is -1 for failure, 0 for success, although at
- * the moment there's nothing that could fail. On success, a list
- * is left in the interp's result: first element is the subexpression
- * count, second is a list of re_info bit names.
+ * The return value is -1 for failure, 0 for success, although at the
+ * moment there's nothing that could fail. On success, a list is left in
+ * the interp's result: first element is the subexpression count, second
+ * is a list of re_info bit names.
*
* Side effects:
* None.
@@ -616,16 +627,16 @@ Tcl_GetRegExpFromObj(interp, objPtr, flags)
*/
int
-TclRegAbout(interp, re)
- Tcl_Interp *interp; /* For use in variable assignment. */
- Tcl_RegExp re; /* The compiled regular expression. */
+TclRegAbout(
+ Tcl_Interp *interp, /* For use in variable assignment. */
+ Tcl_RegExp re) /* The compiled regular expression. */
{
- TclRegexp *regexpPtr = (TclRegexp *)re;
- char buf[TCL_INTEGER_SPACE];
- static struct infoname {
+ TclRegexp *regexpPtr = (TclRegexp *) re;
+ struct infoname {
int bit;
- char *text;
- } infonames[] = {
+ const char *text;
+ };
+ static const struct infoname infonames[] = {
{REG_UBACKREF, "REG_UBACKREF"},
{REG_ULOOKAHEAD, "REG_ULOOKAHEAD"},
{REG_UBOUNDS, "REG_UBOUNDS"},
@@ -640,37 +651,40 @@ TclRegAbout(interp, re)
{REG_UEMPTYMATCH, "REG_UEMPTYMATCH"},
{REG_UIMPOSSIBLE, "REG_UIMPOSSIBLE"},
{REG_USHORTEST, "REG_USHORTEST"},
- {0, ""}
+ {0, NULL}
};
- struct infoname *inf;
- int n;
+ const struct infoname *inf;
+ Tcl_Obj *infoObj;
+
+ /*
+ * The reset here guarantees that the interpreter result is empty and
+ * unshared. This means that we can use Tcl_ListObjAppendElement on the
+ * result object quite safely.
+ */
Tcl_ResetResult(interp);
- sprintf(buf, "%u", (unsigned)(regexpPtr->re.re_nsub));
- Tcl_AppendElement(interp, buf);
+ /*
+ * Assume that there will never be more than INT_MAX subexpressions. This
+ * is a pretty reasonable assumption; the RE engine doesn't scale _that_
+ * well and Tcl has other limits that constrain things as well...
+ */
+
+ Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(interp),
+ Tcl_NewIntObj((int) regexpPtr->re.re_nsub));
/*
- * Must count bits before generating list, because we must know
- * whether {} are needed before we start appending names.
+ * Now append a list of all the bit-flags set for the RE.
*/
- n = 0;
- for (inf = infonames; inf->bit != 0; inf++) {
- if (regexpPtr->re.re_info&inf->bit) {
- n++;
- }
- }
- if (n != 1) {
- Tcl_AppendResult(interp, " {", NULL);
- }
- for (inf = infonames; inf->bit != 0; inf++) {
- if (regexpPtr->re.re_info&inf->bit) {
- Tcl_AppendElement(interp, inf->text);
+
+ TclNewObj(infoObj);
+ for (inf=infonames ; inf->bit != 0 ; inf++) {
+ if (regexpPtr->re.re_info & inf->bit) {
+ Tcl_ListObjAppendElement(NULL, infoObj,
+ Tcl_NewStringObj(inf->text, -1));
}
}
- if (n != 1) {
- Tcl_AppendResult(interp, "}", NULL);
- }
+ Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(interp), infoObj);
return 0;
}
@@ -692,26 +706,25 @@ TclRegAbout(interp, re)
*/
void
-TclRegError(interp, msg, status)
- Tcl_Interp *interp; /* Interpreter for error reporting. */
- CONST char *msg; /* Message to prepend to error. */
- int status; /* Status code to report. */
+TclRegError(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ const char *msg, /* Message to prepend to error. */
+ int status) /* Status code to report. */
{
char buf[100]; /* ample in practice */
char cbuf[100]; /* lots in practice */
size_t n;
- char *p;
+ const char *p;
Tcl_ResetResult(interp);
- n = TclReError(status, (regex_t *)NULL, buf, sizeof(buf));
+ n = TclReError(status, NULL, buf, sizeof(buf));
p = (n > sizeof(buf)) ? "..." : "";
Tcl_AppendResult(interp, msg, buf, p, NULL);
sprintf(cbuf, "%d", status);
- (VOID) TclReError(REG_ITOA, (regex_t *)NULL, cbuf, sizeof(cbuf));
+ (void) TclReError(REG_ITOA, NULL, cbuf, sizeof(cbuf));
Tcl_SetErrorCode(interp, "REGEXP", cbuf, buf, NULL);
}
-
/*
*----------------------------------------------------------------------
@@ -731,8 +744,8 @@ TclRegError(interp, msg, status)
*/
static void
-FreeRegexpInternalRep(objPtr)
- Tcl_Obj *objPtr; /* Regexp object with internal rep to free. */
+FreeRegexpInternalRep(
+ Tcl_Obj *objPtr) /* Regexp object with internal rep to free. */
{
TclRegexp *regexpRepPtr = (TclRegexp *) objPtr->internalRep.otherValuePtr;
@@ -743,6 +756,7 @@ FreeRegexpInternalRep(objPtr)
if (--(regexpRepPtr->refCount) <= 0) {
FreeRegexp(regexpRepPtr);
}
+ objPtr->typePtr = NULL;
}
/*
@@ -750,8 +764,8 @@ FreeRegexpInternalRep(objPtr)
*
* DupRegexpInternalRep --
*
- * We copy the reference to the compiled regexp and bump its
- * reference count.
+ * We copy the reference to the compiled regexp and bump its reference
+ * count.
*
* Results:
* None.
@@ -763,11 +777,12 @@ FreeRegexpInternalRep(objPtr)
*/
static void
-DupRegexpInternalRep(srcPtr, copyPtr)
- Tcl_Obj *srcPtr; /* Object with internal rep to copy. */
- Tcl_Obj *copyPtr; /* Object with internal rep to set. */
+DupRegexpInternalRep(
+ Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
+ Tcl_Obj *copyPtr) /* Object with internal rep to set. */
{
TclRegexp *regexpPtr = (TclRegexp *) srcPtr->internalRep.otherValuePtr;
+
regexpPtr->refCount++;
copyPtr->internalRep.otherValuePtr = srcPtr->internalRep.otherValuePtr;
copyPtr->typePtr = &tclRegexpType;
@@ -794,9 +809,9 @@ DupRegexpInternalRep(srcPtr, copyPtr)
*/
static int
-SetRegexpFromAny(interp, objPtr)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- Tcl_Obj *objPtr; /* The object to convert. */
+SetRegexpFromAny(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tcl_Obj *objPtr) /* The object to convert. */
{
if (Tcl_GetRegExpFromObj(interp, objPtr, REG_ADVANCED) == NULL) {
return TCL_ERROR;
@@ -809,37 +824,36 @@ SetRegexpFromAny(interp, objPtr)
*
* CompileRegexp --
*
- * Attempt to compile the given regexp pattern. If the compiled
- * regular expression can be found in the per-thread cache, it
- * will be used instead of compiling a new copy.
+ * Attempt to compile the given regexp pattern. If the compiled regular
+ * expression can be found in the per-thread cache, it will be used
+ * instead of compiling a new copy.
*
* Results:
- * The return value is a pointer to a newly allocated TclRegexp
- * that represents the compiled pattern, or NULL if the pattern
- * could not be compiled. If NULL is returned, an error message is
- * left in the interp's result.
+ * The return value is a pointer to a newly allocated TclRegexp that
+ * represents the compiled pattern, or NULL if the pattern could not be
+ * compiled. If NULL is returned, an error message is left in the
+ * interp's result.
*
* Side effects:
- * The thread-local regexp cache is updated and a new TclRegexp may
- * be allocated.
+ * The thread-local regexp cache is updated and a new TclRegexp may be
+ * allocated.
*
*----------------------------------------------------------------------
*/
static TclRegexp *
-CompileRegexp(interp, string, length, flags)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- CONST char *string; /* The regexp to compile (UTF-8). */
- int length; /* The length of the string in bytes. */
- int flags; /* Compilation flags. */
+CompileRegexp(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ const char *string, /* The regexp to compile (UTF-8). */
+ int length, /* The length of the string in bytes. */
+ int flags) /* Compilation flags. */
{
TclRegexp *regexpPtr;
- CONST Tcl_UniChar *uniString;
- int numChars;
+ const Tcl_UniChar *uniString;
+ int numChars, status, i, exact;
Tcl_DString stringBuf;
- int status, i;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
+
if (!tsdPtr->initialized) {
tsdPtr->initialized = 1;
Tcl_CreateThreadExitHandler(FinalizeRegexp, NULL);
@@ -847,14 +861,14 @@ CompileRegexp(interp, string, length, flags)
/*
* This routine maintains a second-level regular expression cache in
- * addition to the per-object regexp cache. The per-thread cache is needed
+ * addition to the per-object regexp cache. The per-thread cache is needed
* to handle the case where for various reasons the object is lost between
* invocations of the regexp command, but the literal pattern is the same.
*/
/*
- * Check the per-thread compiled regexp cache. We can only reuse
- * a regexp if it has the same pattern and the same flags.
+ * Check the per-thread compiled regexp cache. We can only reuse a regexp
+ * if it has the same pattern and the same flags.
*/
for (i = 0; (i < NUM_REGEXPS) && (tsdPtr->patterns[i] != NULL); i++) {
@@ -862,8 +876,8 @@ CompileRegexp(interp, string, length, flags)
&& (tsdPtr->regexps[i]->flags == flags)
&& (strcmp(string, tsdPtr->patterns[i]) == 0)) {
/*
- * Move the matched pattern to the first slot in the
- * cache and shift the other patterns down one position.
+ * Move the matched pattern to the first slot in the cache and
+ * shift the other patterns down one position.
*/
if (i != 0) {
@@ -888,7 +902,7 @@ CompileRegexp(interp, string, length, flags)
/*
* This is a new expression, so compile it and add it to the cache.
*/
-
+
regexpPtr = (TclRegexp *) ckalloc(sizeof(TclRegexp));
regexpPtr->objPtr = NULL;
regexpPtr->string = NULL;
@@ -919,15 +933,29 @@ CompileRegexp(interp, string, length, flags)
ckfree((char *)regexpPtr);
if (interp) {
TclRegError(interp,
- "couldn't compile regular expression pattern: ",
- status);
+ "couldn't compile regular expression pattern: ", status);
}
return NULL;
}
/*
- * Allocate enough space for all of the subexpressions, plus one
- * extra for the entire pattern.
+ * Convert RE to a glob pattern equivalent, if any, and cache it. If this
+ * is not possible, then globObjPtr will be NULL. This is used by
+ * Tcl_RegExpExecObj to optionally do a fast match (avoids RE engine).
+ */
+
+ if (TclReToGlob(NULL, string, length, &stringBuf, &exact) == TCL_OK) {
+ regexpPtr->globObjPtr = Tcl_NewStringObj(Tcl_DStringValue(&stringBuf),
+ Tcl_DStringLength(&stringBuf));
+ Tcl_IncrRefCount(regexpPtr->globObjPtr);
+ Tcl_DStringFree(&stringBuf);
+ } else {
+ regexpPtr->globObjPtr = NULL;
+ }
+
+ /*
+ * Allocate enough space for all of the subexpressions, plus one extra for
+ * the entire pattern.
*/
regexpPtr->matches = (regmatch_t *) ckalloc(
@@ -981,10 +1009,13 @@ CompileRegexp(interp, string, length, flags)
*/
static void
-FreeRegexp(regexpPtr)
- TclRegexp *regexpPtr; /* Compiled regular expression to free. */
+FreeRegexp(
+ TclRegexp *regexpPtr) /* Compiled regular expression to free. */
{
TclReFree(&regexpPtr->re);
+ if (regexpPtr->globObjPtr) {
+ TclDecrRefCount(regexpPtr->globObjPtr);
+ }
if (regexpPtr->matches) {
ckfree((char *) regexpPtr->matches);
}
@@ -996,8 +1027,7 @@ FreeRegexp(regexpPtr)
*
* FinalizeRegexp --
*
- * Release the storage associated with the per-thread regexp
- * cache.
+ * Release the storage associated with the per-thread regexp cache.
*
* Results:
* None.
@@ -1009,8 +1039,8 @@ FreeRegexp(regexpPtr)
*/
static void
-FinalizeRegexp(clientData)
- ClientData clientData; /* Not used. */
+FinalizeRegexp(
+ ClientData clientData) /* Not used. */
{
int i;
TclRegexp *regexpPtr;
@@ -1030,3 +1060,11 @@ FinalizeRegexp(clientData)
*/
tsdPtr->initialized = 0;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclRegexp.h b/generic/tclRegexp.h
index f4c4cb6..8650776 100644
--- a/generic/tclRegexp.h
+++ b/generic/tclRegexp.h
@@ -1,14 +1,14 @@
-/*
+/*
* tclRegexp.h --
*
- * This file contains definitions used internally by Henry
- * Spencer's regular expression code.
+ * This file contains definitions used internally by Henry Spencer's
+ * regular expression code.
*
* Copyright (c) 1998 by 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.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#ifndef _TCLREGEXP
@@ -16,18 +16,12 @@
#include "regex.h"
-#ifdef BUILD_tcl
-# undef TCL_STORAGE_CLASS
-# define TCL_STORAGE_CLASS DLLEXPORT
-#endif
-
/*
- * The TclRegexp structure encapsulates a compiled regex_t,
- * the flags that were used to compile it, and an array of pointers
- * that are used to indicate subexpressions after a call to Tcl_RegExpExec.
- * Note that the string and objPtr are mutually exclusive. These values
- * are needed by Tcl_RegExpRange in order to return pointers into the
- * original string.
+ * The TclRegexp structure encapsulates a compiled regex_t, the flags that
+ * were used to compile it, and an array of pointers that are used to indicate
+ * subexpressions after a call to Tcl_RegExpExec. Note that the string and
+ * objPtr are mutually exclusive. These values are needed by Tcl_RegExpRange
+ * in order to return pointers into the original string.
*/
typedef struct TclRegexp {
@@ -36,6 +30,7 @@ typedef struct TclRegexp {
* subexpressions. */
CONST char *string; /* Last string passed to Tcl_RegExpExec. */
Tcl_Obj *objPtr; /* Last object passed to Tcl_RegExpExecObj. */
+ Tcl_Obj *globObjPtr; /* Glob pattern rep of RE or NULL if none. */
regmatch_t *matches; /* Array of indices into the Tcl_UniChar
* representation of the last string matched
* with this regexp to indicate the location
@@ -47,3 +42,11 @@ typedef struct TclRegexp {
} TclRegexp;
#endif /* _TCLREGEXP */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclResolve.c b/generic/tclResolve.c
index 4463436..8bb5e2b 100644
--- a/generic/tclResolve.c
+++ b/generic/tclResolve.c
@@ -1,111 +1,107 @@
/*
* tclResolve.c --
*
- * Contains hooks for customized command/variable name resolution
- * schemes. These hooks allow extensions like [incr Tcl] to add
- * their own name resolution rules to the Tcl language. Rules can
- * be applied to a particular namespace, to the interpreter as a
- * whole, or both.
+ * Contains hooks for customized command/variable name resolution
+ * schemes. These hooks allow extensions like [incr Tcl] to add their own
+ * name resolution rules to the Tcl language. Rules can be applied to a
+ * particular namespace, to the interpreter as a whole, or both.
*
* Copyright (c) 1998 Lucent Technologies, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
/*
- * Declarations for procedures local to this file:
+ * Declarations for functions local to this file:
*/
-static void BumpCmdRefEpochs _ANSI_ARGS_((Namespace *nsPtr));
-
+static void BumpCmdRefEpochs(Namespace *nsPtr);
/*
*----------------------------------------------------------------------
*
* Tcl_AddInterpResolvers --
*
- * Adds a set of command/variable resolution procedures to an
- * interpreter. These procedures are consulted when commands
- * are resolved in Tcl_FindCommand, and when variables are
- * resolved in TclLookupVar and LookupCompiledLocal. Each
- * namespace may also have its own set of resolution procedures
- * which take precedence over those for the interpreter.
+ * Adds a set of command/variable resolution functions to an interpreter.
+ * These functions are consulted when commands are resolved in
+ * Tcl_FindCommand, and when variables are resolved in TclLookupVar and
+ * LookupCompiledLocal. Each namespace may also have its own set of
+ * resolution functions which take precedence over those for the
+ * interpreter.
*
- * When a name is resolved, it is handled as follows. First,
- * the name is passed to the resolution procedures for the
- * namespace. If not resolved, the name is passed to each of
- * the resolution procedures added to the interpreter. Finally,
- * if still not resolved, the name is handled using the default
- * Tcl rules for name resolution.
+ * When a name is resolved, it is handled as follows. First, the name is
+ * passed to the resolution functions for the namespace. If not resolved,
+ * the name is passed to each of the resolution functions added to the
+ * interpreter. Finally, if still not resolved, the name is handled using
+ * the default Tcl rules for name resolution.
*
* Results:
- * Returns pointers to the current name resolution procedures
- * in the cmdProcPtr, varProcPtr and compiledVarProcPtr
- * arguments.
+ * Returns pointers to the current name resolution functions in the
+ * cmdProcPtr, varProcPtr and compiledVarProcPtr arguments.
*
* Side effects:
- * If a compiledVarProc is specified, this procedure bumps the
- * compileEpoch for the interpreter, forcing all code to be
- * recompiled. If a cmdProc is specified, this procedure bumps
- * the cmdRefEpoch in all namespaces, forcing commands to be
- * resolved again using the new rules.
+ * If a compiledVarProc is specified, this function bumps the
+ * compileEpoch for the interpreter, forcing all code to be recompiled.
+ * If a cmdProc is specified, this function bumps the cmdRefEpoch in all
+ * namespaces, forcing commands to be resolved again using the new rules.
*
*----------------------------------------------------------------------
*/
void
-Tcl_AddInterpResolvers(interp, name, cmdProc, varProc, compiledVarProc)
-
- Tcl_Interp *interp; /* Interpreter whose name resolution
- * rules are being modified. */
- CONST char *name; /* Name of this resolution scheme. */
- Tcl_ResolveCmdProc *cmdProc; /* New procedure for command
- * resolution */
- Tcl_ResolveVarProc *varProc; /* Procedure for variable resolution
- * at runtime */
- Tcl_ResolveCompiledVarProc *compiledVarProc;
- /* Procedure for variable resolution
- * at compile time. */
+Tcl_AddInterpResolvers(
+ Tcl_Interp *interp, /* Interpreter whose name resolution rules are
+ * being modified. */
+ CONST char *name, /* Name of this resolution scheme. */
+ Tcl_ResolveCmdProc *cmdProc,/* New function for command resolution. */
+ Tcl_ResolveVarProc *varProc,/* Function for variable resolution at
+ * runtime. */
+ Tcl_ResolveCompiledVarProc *compiledVarProc)
+ /* Function for variable resolution at compile
+ * time. */
{
- Interp *iPtr = (Interp*)interp;
+ Interp *iPtr = (Interp *) interp;
ResolverScheme *resPtr;
/*
- * Since we're adding a new name resolution scheme, we must force
- * all code to be recompiled to use the new scheme. If there
- * are new compiled variable resolution rules, bump the compiler
- * epoch to invalidate compiled code. If there are new command
- * resolution rules, bump the cmdRefEpoch in all namespaces.
+ * Since we're adding a new name resolution scheme, we must force all code
+ * to be recompiled to use the new scheme. If there are new compiled
+ * variable resolution rules, bump the compiler epoch to invalidate
+ * compiled code. If there are new command resolution rules, bump the
+ * cmdRefEpoch in all namespaces.
*/
+
if (compiledVarProc) {
- iPtr->compileEpoch++;
+ iPtr->compileEpoch++;
}
if (cmdProc) {
- BumpCmdRefEpochs(iPtr->globalNsPtr);
+ BumpCmdRefEpochs(iPtr->globalNsPtr);
}
/*
- * Look for an existing scheme with the given name. If found,
- * then replace its rules.
+ * Look for an existing scheme with the given name. If found, then replace
+ * its rules.
*/
- for (resPtr = iPtr->resolverPtr; resPtr != NULL; resPtr = resPtr->nextPtr) {
- if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) {
- resPtr->cmdResProc = cmdProc;
- resPtr->varResProc = varProc;
- resPtr->compiledVarResProc = compiledVarProc;
- return;
- }
+
+ for (resPtr=iPtr->resolverPtr ; resPtr!=NULL ; resPtr=resPtr->nextPtr) {
+ if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) {
+ resPtr->cmdResProc = cmdProc;
+ resPtr->varResProc = varProc;
+ resPtr->compiledVarResProc = compiledVarProc;
+ return;
+ }
}
/*
- * Otherwise, this is a new scheme. Add it to the FRONT
- * of the linked list, so that it overrides existing schemes.
+ * Otherwise, this is a new scheme. Add it to the FRONT of the linked
+ * list, so that it overrides existing schemes.
*/
+
resPtr = (ResolverScheme *) ckalloc(sizeof(ResolverScheme));
- resPtr->name = (char*)ckalloc((unsigned)(strlen(name)+1));
+ resPtr->name = (char *) ckalloc((unsigned)(strlen(name) + 1));
strcpy(resPtr->name, name);
resPtr->cmdResProc = cmdProc;
resPtr->varResProc = varProc;
@@ -119,15 +115,14 @@ Tcl_AddInterpResolvers(interp, name, cmdProc, varProc, compiledVarProc)
*
* Tcl_GetInterpResolvers --
*
- * Looks for a set of command/variable resolution procedures with
- * the given name in an interpreter. These procedures are
- * registered by calling Tcl_AddInterpResolvers.
+ * Looks for a set of command/variable resolution functions with the
+ * given name in an interpreter. These functions are registered by
+ * calling Tcl_AddInterpResolvers.
*
* Results:
- * If the name is recognized, this procedure returns non-zero,
- * along with pointers to the name resolution procedures in
- * the Tcl_ResolverInfo structure. If the name is not recognized,
- * this procedure returns zero.
+ * If the name is recognized, this function returns non-zero, along with
+ * pointers to the name resolution functions in the Tcl_ResolverInfo
+ * structure. If the name is not recognized, this function returns zero.
*
* Side effects:
* None.
@@ -136,28 +131,29 @@ Tcl_AddInterpResolvers(interp, name, cmdProc, varProc, compiledVarProc)
*/
int
-Tcl_GetInterpResolvers(interp, name, resInfoPtr)
-
- Tcl_Interp *interp; /* Interpreter whose name resolution
- * rules are being queried. */
- CONST char *name; /* Look for a scheme with this name. */
- Tcl_ResolverInfo *resInfoPtr; /* Returns pointers to the procedures,
- * if found */
+Tcl_GetInterpResolvers(
+ Tcl_Interp *interp, /* Interpreter whose name resolution rules are
+ * being queried. */
+ CONST char *name, /* Look for a scheme with this name. */
+ Tcl_ResolverInfo *resInfoPtr)
+ /* Returns pointers to the functions, if
+ * found */
{
- Interp *iPtr = (Interp*)interp;
+ Interp *iPtr = (Interp *) interp;
ResolverScheme *resPtr;
/*
- * Look for an existing scheme with the given name. If found,
- * then return pointers to its procedures.
+ * Look for an existing scheme with the given name. If found, then return
+ * pointers to its functions.
*/
- for (resPtr = iPtr->resolverPtr; resPtr != NULL; resPtr = resPtr->nextPtr) {
- if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) {
+
+ for (resPtr=iPtr->resolverPtr ; resPtr!=NULL ; resPtr=resPtr->nextPtr) {
+ if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) {
resInfoPtr->cmdResProc = resPtr->cmdResProc;
resInfoPtr->varResProc = resPtr->varResProc;
resInfoPtr->compiledVarResProc = resPtr->compiledVarResProc;
- return 1;
- }
+ return 1;
+ }
}
return 0;
@@ -168,68 +164,69 @@ Tcl_GetInterpResolvers(interp, name, resInfoPtr)
*
* Tcl_RemoveInterpResolvers --
*
- * Removes a set of command/variable resolution procedures
- * previously added by Tcl_AddInterpResolvers. The next time
- * a command/variable name is resolved, these procedures
- * won't be consulted.
+ * Removes a set of command/variable resolution functions previously
+ * added by Tcl_AddInterpResolvers. The next time a command/variable name
+ * is resolved, these functions won't be consulted.
*
* Results:
- * Returns non-zero if the name was recognized and the
- * resolution scheme was deleted. Returns zero otherwise.
+ * Returns non-zero if the name was recognized and the resolution scheme
+ * was deleted. Returns zero otherwise.
*
* Side effects:
- * If a scheme with a compiledVarProc was deleted, this procedure
- * bumps the compileEpoch for the interpreter, forcing all code
- * to be recompiled. If a scheme with a cmdProc was deleted,
- * this procedure bumps the cmdRefEpoch in all namespaces,
- * forcing commands to be resolved again using the new rules.
+ * If a scheme with a compiledVarProc was deleted, this function bumps
+ * the compileEpoch for the interpreter, forcing all code to be
+ * recompiled. If a scheme with a cmdProc was deleted, this function
+ * bumps the cmdRefEpoch in all namespaces, forcing commands to be
+ * resolved again using the new rules.
*
*----------------------------------------------------------------------
*/
int
-Tcl_RemoveInterpResolvers(interp, name)
-
- Tcl_Interp *interp; /* Interpreter whose name resolution
- * rules are being modified. */
- CONST char *name; /* Name of the scheme to be removed. */
+Tcl_RemoveInterpResolvers(
+ Tcl_Interp *interp, /* Interpreter whose name resolution rules are
+ * being modified. */
+ CONST char *name) /* Name of the scheme to be removed. */
{
- Interp *iPtr = (Interp*)interp;
+ Interp *iPtr = (Interp *) interp;
ResolverScheme **prevPtrPtr, *resPtr;
/*
- * Look for an existing scheme with the given name.
+ * Look for an existing scheme with the given name.
*/
+
prevPtrPtr = &iPtr->resolverPtr;
- for (resPtr = iPtr->resolverPtr; resPtr != NULL; resPtr = resPtr->nextPtr) {
- if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) {
- break;
- }
- prevPtrPtr = &resPtr->nextPtr;
+ for (resPtr=iPtr->resolverPtr ; resPtr!=NULL ; resPtr=resPtr->nextPtr) {
+ if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) {
+ break;
+ }
+ prevPtrPtr = &resPtr->nextPtr;
}
/*
- * If we found the scheme, delete it.
+ * If we found the scheme, delete it.
*/
+
if (resPtr) {
- /*
- * If we're deleting a scheme with compiled variable resolution
- * rules, bump the compiler epoch to invalidate compiled code.
- * If we're deleting a scheme with command resolution rules,
- * bump the cmdRefEpoch in all namespaces.
- */
- if (resPtr->compiledVarResProc) {
- iPtr->compileEpoch++;
- }
- if (resPtr->cmdResProc) {
- BumpCmdRefEpochs(iPtr->globalNsPtr);
- }
-
- *prevPtrPtr = resPtr->nextPtr;
- ckfree(resPtr->name);
- ckfree((char *) resPtr);
-
- return 1;
+ /*
+ * If we're deleting a scheme with compiled variable resolution rules,
+ * bump the compiler epoch to invalidate compiled code. If we're
+ * deleting a scheme with command resolution rules, bump the
+ * cmdRefEpoch in all namespaces.
+ */
+
+ if (resPtr->compiledVarResProc) {
+ iPtr->compileEpoch++;
+ }
+ if (resPtr->cmdResProc) {
+ BumpCmdRefEpochs(iPtr->globalNsPtr);
+ }
+
+ *prevPtrPtr = resPtr->nextPtr;
+ ckfree(resPtr->name);
+ ckfree((char *) resPtr);
+
+ return 1;
}
return 0;
}
@@ -239,134 +236,127 @@ Tcl_RemoveInterpResolvers(interp, name)
*
* BumpCmdRefEpochs --
*
- * This procedure is used to bump the cmdRefEpoch counters in
- * the specified namespace and all of its child namespaces.
- * It is used whenever name resolution schemes are added/removed
- * from an interpreter, to invalidate all command references.
+ * This function is used to bump the cmdRefEpoch counters in the
+ * specified namespace and all of its child namespaces. It is used
+ * whenever name resolution schemes are added/removed from an
+ * interpreter, to invalidate all command references.
*
* Results:
* None.
*
* Side effects:
- * Bumps the cmdRefEpoch in the specified namespace and its
- * children, recursively.
+ * Bumps the cmdRefEpoch in the specified namespace and its children,
+ * recursively.
*
*----------------------------------------------------------------------
*/
static void
-BumpCmdRefEpochs(nsPtr)
- Namespace *nsPtr; /* Namespace being modified. */
+BumpCmdRefEpochs(
+ Namespace *nsPtr) /* Namespace being modified. */
{
Tcl_HashEntry *entry;
Tcl_HashSearch search;
- Namespace *childNsPtr;
nsPtr->cmdRefEpoch++;
for (entry = Tcl_FirstHashEntry(&nsPtr->childTable, &search);
- entry != NULL;
- entry = Tcl_NextHashEntry(&search)) {
-
- childNsPtr = (Namespace *) Tcl_GetHashValue(entry);
- BumpCmdRefEpochs(childNsPtr);
+ entry != NULL; entry = Tcl_NextHashEntry(&search)) {
+ Namespace *childNsPtr = (Namespace *) Tcl_GetHashValue(entry);
+ BumpCmdRefEpochs(childNsPtr);
}
+ TclInvalidateNsPath(nsPtr);
}
-
/*
*----------------------------------------------------------------------
*
* Tcl_SetNamespaceResolvers --
*
- * Sets the command/variable resolution procedures for a namespace,
- * thereby changing the way that command/variable names are
- * interpreted. This allows extension writers to support different
- * name resolution schemes, such as those for object-oriented
- * packages.
- *
- * Command resolution is handled by a procedure of the following
- * type:
- *
- * typedef int (Tcl_ResolveCmdProc) _ANSI_ARGS_((
- * Tcl_Interp* interp, CONST char* name, Tcl_Namespace *context,
- * int flags, Tcl_Command *rPtr));
- *
- * Whenever a command is executed or Tcl_FindCommand is invoked
- * within the namespace, this procedure is called to resolve the
- * command name. If this procedure is able to resolve the name,
- * it should return the status code TCL_OK, along with the
- * corresponding Tcl_Command in the rPtr argument. Otherwise,
- * the procedure can return TCL_CONTINUE, and the command will
- * be treated under the usual name resolution rules. Or, it can
- * return TCL_ERROR, and the command will be considered invalid.
- *
- * Variable resolution is handled by two procedures. The first
- * is called whenever a variable needs to be resolved at compile
- * time:
- *
- * typedef int (Tcl_ResolveCompiledVarProc) _ANSI_ARGS_((
- * Tcl_Interp* interp, CONST char* name, Tcl_Namespace *context,
- * Tcl_ResolvedVarInfo *rPtr));
- *
- * If this procedure is able to resolve the name, it should return
- * the status code TCL_OK, along with variable resolution info in
- * the rPtr argument; this info will be used to set up compiled
- * locals in the call frame at runtime. The procedure may also
- * return TCL_CONTINUE, and the variable will be treated under
- * the usual name resolution rules. Or, it can return TCL_ERROR,
- * and the variable will be considered invalid.
- *
- * Another procedure is used whenever a variable needs to be
- * resolved at runtime but it is not recognized as a compiled local.
- * (For example, the variable may be requested via
- * Tcl_FindNamespaceVar.) This procedure has the following type:
- *
- * typedef int (Tcl_ResolveVarProc) _ANSI_ARGS_((
- * Tcl_Interp* interp, CONST char* name, Tcl_Namespace *context,
- * int flags, Tcl_Var *rPtr));
- *
- * This procedure is quite similar to the compile-time version.
- * It returns the same status codes, but if variable resolution
- * succeeds, this procedure returns a Tcl_Var directly via the
- * rPtr argument.
+ * Sets the command/variable resolution functions for a namespace,
+ * thereby changing the way that command/variable names are interpreted.
+ * This allows extension writers to support different name resolution
+ * schemes, such as those for object-oriented packages.
+ *
+ * Command resolution is handled by a function of the following type:
+ *
+ * typedef int (*Tcl_ResolveCmdProc)(Tcl_Interp *interp,
+ * CONST char *name, Tcl_Namespace *context,
+ * int flags, Tcl_Command *rPtr);
+ *
+ * Whenever a command is executed or Tcl_FindCommand is invoked within
+ * the namespace, this function is called to resolve the command name. If
+ * this function is able to resolve the name, it should return the status
+ * code TCL_OK, along with the corresponding Tcl_Command in the rPtr
+ * argument. Otherwise, the function can return TCL_CONTINUE, and the
+ * command will be treated under the usual name resolution rules. Or, it
+ * can return TCL_ERROR, and the command will be considered invalid.
+ *
+ * Variable resolution is handled by two functions. The first is called
+ * whenever a variable needs to be resolved at compile time:
+ *
+ * typedef int (*Tcl_ResolveCompiledVarProc)(Tcl_Interp *interp,
+ * CONST char *name, Tcl_Namespace *context,
+ * Tcl_ResolvedVarInfo *rPtr);
+ *
+ * If this function is able to resolve the name, it should return the
+ * status code TCL_OK, along with variable resolution info in the rPtr
+ * argument; this info will be used to set up compiled locals in the call
+ * frame at runtime. The function may also return TCL_CONTINUE, and the
+ * variable will be treated under the usual name resolution rules. Or, it
+ * can return TCL_ERROR, and the variable will be considered invalid.
+ *
+ * Another function is used whenever a variable needs to be resolved at
+ * runtime but it is not recognized as a compiled local. (For example,
+ * the variable may be requested via Tcl_FindNamespaceVar.) This function
+ * has the following type:
+ *
+ * typedef int (*Tcl_ResolveVarProc)(Tcl_Interp *interp,
+ * CONST char *name, Tcl_Namespace *context,
+ * int flags, Tcl_Var *rPtr);
+ *
+ * This function is quite similar to the compile-time version. It returns
+ * the same status codes, but if variable resolution succeeds, this
+ * function returns a Tcl_Var directly via the rPtr argument.
*
* Results:
* Nothing.
*
* Side effects:
- * Bumps the command epoch counter for the namespace, invalidating
- * all command references in that namespace. Also bumps the
- * resolver epoch counter for the namespace, forcing all code
- * in the namespace to be recompiled.
+ * Bumps the command epoch counter for the namespace, invalidating all
+ * command references in that namespace. Also bumps the resolver epoch
+ * counter for the namespace, forcing all code in the namespace to be
+ * recompiled.
*
*----------------------------------------------------------------------
*/
void
-Tcl_SetNamespaceResolvers(namespacePtr, cmdProc, varProc, compiledVarProc)
- Tcl_Namespace *namespacePtr; /* Namespace whose resolution rules
- * are being modified. */
- Tcl_ResolveCmdProc *cmdProc; /* Procedure for command resolution */
- Tcl_ResolveVarProc *varProc; /* Procedure for variable resolution
- * at runtime */
- Tcl_ResolveCompiledVarProc *compiledVarProc;
- /* Procedure for variable resolution
- * at compile time. */
+Tcl_SetNamespaceResolvers(
+ Tcl_Namespace *namespacePtr,/* Namespace whose resolution rules are being
+ * modified. */
+ Tcl_ResolveCmdProc *cmdProc,/* Function for command resolution */
+ Tcl_ResolveVarProc *varProc,/* Function for variable resolution at
+ * run-time */
+ Tcl_ResolveCompiledVarProc *compiledVarProc)
+ /* Function for variable resolution at compile
+ * time. */
{
- Namespace *nsPtr = (Namespace*)namespacePtr;
+ Namespace *nsPtr = (Namespace *) namespacePtr;
/*
- * Plug in the new command resolver, and bump the epoch counters
- * so that all code will have to be recompiled and all commands
- * will have to be resolved again using the new policy.
+ * Plug in the new command resolver, and bump the epoch counters so that
+ * all code will have to be recompiled and all commands will have to be
+ * resolved again using the new policy.
*/
+
nsPtr->cmdResProc = cmdProc;
nsPtr->varResProc = varProc;
nsPtr->compiledVarResProc = compiledVarProc;
nsPtr->cmdRefEpoch++;
nsPtr->resolverEpoch++;
+ TclInvalidateNsPath(nsPtr);
}
/*
@@ -374,17 +364,15 @@ Tcl_SetNamespaceResolvers(namespacePtr, cmdProc, varProc, compiledVarProc)
*
* Tcl_GetNamespaceResolvers --
*
- * Returns the current command/variable resolution procedures
- * for a namespace. By default, these procedures are NULL.
- * New procedures can be installed by calling
- * Tcl_SetNamespaceResolvers, to provide new name resolution
- * rules.
+ * Returns the current command/variable resolution functions for a
+ * namespace. By default, these functions are NULL. New functions can be
+ * installed by calling Tcl_SetNamespaceResolvers, to provide new name
+ * resolution rules.
*
* Results:
- * Returns non-zero if any name resolution procedures have been
- * assigned to this namespace; also returns pointers to the
- * procedures in the Tcl_ResolverInfo structure. Returns zero
- * otherwise.
+ * Returns non-zero if any name resolution functions have been assigned
+ * to this namespace; also returns pointers to the functions in the
+ * Tcl_ResolverInfo structure. Returns zero otherwise.
*
* Side effects:
* None.
@@ -393,24 +381,30 @@ Tcl_SetNamespaceResolvers(namespacePtr, cmdProc, varProc, compiledVarProc)
*/
int
-Tcl_GetNamespaceResolvers(namespacePtr, resInfoPtr)
-
- Tcl_Namespace *namespacePtr; /* Namespace whose resolution rules
- * are being modified. */
- Tcl_ResolverInfo *resInfoPtr; /* Returns: pointers for all
- * name resolution procedures
- * assigned to this namespace. */
+Tcl_GetNamespaceResolvers(
+ Tcl_Namespace *namespacePtr,/* Namespace whose resolution rules are being
+ * modified. */
+ Tcl_ResolverInfo *resInfoPtr)
+ /* Returns: pointers for all name resolution
+ * functions assigned to this namespace. */
{
- Namespace *nsPtr = (Namespace*)namespacePtr;
+ Namespace *nsPtr = (Namespace *) namespacePtr;
resInfoPtr->cmdResProc = nsPtr->cmdResProc;
resInfoPtr->varResProc = nsPtr->varResProc;
resInfoPtr->compiledVarResProc = nsPtr->compiledVarResProc;
- if (nsPtr->cmdResProc != NULL ||
- nsPtr->varResProc != NULL ||
- nsPtr->compiledVarResProc != NULL) {
+ if (nsPtr->cmdResProc != NULL || nsPtr->varResProc != NULL ||
+ nsPtr->compiledVarResProc != NULL) {
return 1;
}
return 0;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclResult.c b/generic/tclResult.c
index 6dbdd90..7b58d44 100644
--- a/generic/tclResult.c
+++ b/generic/tclResult.c
@@ -1,39 +1,207 @@
-/*
+/*
* tclResult.c --
*
* This file contains code to manage the interpreter result.
*
* Copyright (c) 1997 by Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
/*
- * Function prototypes for local procedures in this file:
+ * Indices of the standard return options dictionary keys.
+ */
+
+enum returnKeys {
+ KEY_CODE, KEY_ERRORCODE, KEY_ERRORINFO, KEY_ERRORLINE,
+ KEY_LEVEL, KEY_OPTIONS, KEY_LAST
+};
+
+/*
+ * Function prototypes for local functions in this file:
*/
-static void ResetObjResult _ANSI_ARGS_((Interp *iPtr));
-static void SetupAppendBuffer _ANSI_ARGS_((Interp *iPtr,
- int newSpace));
+static Tcl_Obj ** GetKeys(void);
+static void ReleaseKeys(ClientData clientData);
+static void ResetObjResult(Interp *iPtr);
+static void SetupAppendBuffer(Interp *iPtr, int newSpace);
+/*
+ * This structure is used to take a snapshot of the interpreter state in
+ * Tcl_SaveInterpState. You can snapshot the state, execute a command, and
+ * then back up to the result or the error that was previously in progress.
+ */
+
+typedef struct InterpState {
+ int status; /* return code status */
+ int flags; /* Each remaining field saves the */
+ int returnLevel; /* corresponding field of the Interp */
+ int returnCode; /* struct. These fields taken together are */
+ Tcl_Obj *errorInfo; /* the "state" of the interp. */
+ Tcl_Obj *errorCode;
+ Tcl_Obj *returnOpts;
+ Tcl_Obj *objResult;
+} InterpState;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SaveInterpState --
+ *
+ * Fills a token with a snapshot of the current state of the interpreter.
+ * The snapshot can be restored at any point by TclRestoreInterpState.
+ *
+ * The token returned must be eventally passed to one of the routines
+ * TclRestoreInterpState or TclDiscardInterpState, or there will be a
+ * memory leak.
+ *
+ * Results:
+ * Returns a token representing the interp state.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_InterpState
+Tcl_SaveInterpState(
+ Tcl_Interp *interp, /* Interpreter's state to be saved */
+ int status) /* status code for current operation */
+{
+ Interp *iPtr = (Interp *)interp;
+ InterpState *statePtr = (InterpState *)ckalloc(sizeof(InterpState));
+
+ statePtr->status = status;
+ statePtr->flags = iPtr->flags & ERR_ALREADY_LOGGED;
+ statePtr->returnLevel = iPtr->returnLevel;
+ statePtr->returnCode = iPtr->returnCode;
+ statePtr->errorInfo = iPtr->errorInfo;
+ if (statePtr->errorInfo) {
+ Tcl_IncrRefCount(statePtr->errorInfo);
+ }
+ statePtr->errorCode = iPtr->errorCode;
+ if (statePtr->errorCode) {
+ Tcl_IncrRefCount(statePtr->errorCode);
+ }
+ statePtr->returnOpts = iPtr->returnOpts;
+ if (statePtr->returnOpts) {
+ Tcl_IncrRefCount(statePtr->returnOpts);
+ }
+ statePtr->objResult = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(statePtr->objResult);
+ return (Tcl_InterpState) statePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_RestoreInterpState --
+ *
+ * Accepts an interp and a token previously returned by
+ * Tcl_SaveInterpState. Restore the state of the interp to what it was at
+ * the time of the Tcl_SaveInterpState call.
+ *
+ * Results:
+ * Returns the status value originally passed in to Tcl_SaveInterpState.
+ *
+ * Side effects:
+ * Restores the interp state and frees memory held by token.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_RestoreInterpState(
+ Tcl_Interp *interp, /* Interpreter's state to be restored. */
+ Tcl_InterpState state) /* Saved interpreter state. */
+{
+ Interp *iPtr = (Interp *)interp;
+ InterpState *statePtr = (InterpState *)state;
+ int status = statePtr->status;
+
+ iPtr->flags &= ~ERR_ALREADY_LOGGED;
+ iPtr->flags |= (statePtr->flags & ERR_ALREADY_LOGGED);
+
+ iPtr->returnLevel = statePtr->returnLevel;
+ iPtr->returnCode = statePtr->returnCode;
+ if (iPtr->errorInfo) {
+ Tcl_DecrRefCount(iPtr->errorInfo);
+ }
+ iPtr->errorInfo = statePtr->errorInfo;
+ if (iPtr->errorInfo) {
+ Tcl_IncrRefCount(iPtr->errorInfo);
+ }
+ if (iPtr->errorCode) {
+ Tcl_DecrRefCount(iPtr->errorCode);
+ }
+ iPtr->errorCode = statePtr->errorCode;
+ if (iPtr->errorCode) {
+ Tcl_IncrRefCount(iPtr->errorCode);
+ }
+ if (iPtr->returnOpts) {
+ Tcl_DecrRefCount(iPtr->returnOpts);
+ }
+ iPtr->returnOpts = statePtr->returnOpts;
+ if (iPtr->returnOpts) {
+ Tcl_IncrRefCount(iPtr->returnOpts);
+ }
+ Tcl_SetObjResult(interp, statePtr->objResult);
+ Tcl_DiscardInterpState(state);
+ return status;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DiscardInterpState --
+ *
+ * Accepts a token previously returned by Tcl_SaveInterpState. Frees the
+ * memory it uses.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Frees memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DiscardInterpState(
+ Tcl_InterpState state) /* saved interpreter state */
+{
+ InterpState *statePtr = (InterpState *)state;
+
+ if (statePtr->errorInfo) {
+ Tcl_DecrRefCount(statePtr->errorInfo);
+ }
+ if (statePtr->errorCode) {
+ Tcl_DecrRefCount(statePtr->errorCode);
+ }
+ if (statePtr->returnOpts) {
+ Tcl_DecrRefCount(statePtr->returnOpts);
+ }
+ Tcl_DecrRefCount(statePtr->objResult);
+ ckfree((char *) statePtr);
+}
/*
*----------------------------------------------------------------------
*
* Tcl_SaveResult --
*
- * Takes a snapshot of the current result state of the interpreter.
- * The snapshot can be restored at any point by
- * Tcl_RestoreResult. Note that this routine does not
- * preserve the errorCode, errorInfo, or flags fields so it
- * should not be used if an error is in progress.
+ * Takes a snapshot of the current result state of the interpreter. The
+ * snapshot can be restored at any point by Tcl_RestoreResult. Note that
+ * this routine does not preserve the errorCode, errorInfo, or flags
+ * fields so it should not be used if an error is in progress.
*
- * Once a snapshot is saved, it must be restored by calling
- * Tcl_RestoreResult, or discarded by calling
- * Tcl_DiscardResult.
+ * Once a snapshot is saved, it must be restored by calling
+ * Tcl_RestoreResult, or discarded by calling Tcl_DiscardResult.
*
* Results:
* None.
@@ -45,24 +213,24 @@ static void SetupAppendBuffer _ANSI_ARGS_((Interp *iPtr,
*/
void
-Tcl_SaveResult(interp, statePtr)
- Tcl_Interp *interp; /* Interpreter to save. */
- Tcl_SavedResult *statePtr; /* Pointer to state structure. */
+Tcl_SaveResult(
+ Tcl_Interp *interp, /* Interpreter to save. */
+ Tcl_SavedResult *statePtr) /* Pointer to state structure. */
{
Interp *iPtr = (Interp *) interp;
/*
- * Move the result object into the save state. Note that we don't need
- * to change its refcount because we're moving it, not adding a new
- * reference. Put an empty object into the interpreter.
+ * Move the result object into the save state. Note that we don't need to
+ * change its refcount because we're moving it, not adding a new
+ * reference. Put an empty object into the interpreter.
*/
statePtr->objResultPtr = iPtr->objResultPtr;
- iPtr->objResultPtr = Tcl_NewObj();
- Tcl_IncrRefCount(iPtr->objResultPtr);
+ iPtr->objResultPtr = Tcl_NewObj();
+ Tcl_IncrRefCount(iPtr->objResultPtr);
/*
- * Save the string result.
+ * Save the string result.
*/
statePtr->freeProc = iPtr->freeProc;
@@ -105,23 +273,23 @@ Tcl_SaveResult(interp, statePtr)
*
* Tcl_RestoreResult --
*
- * Restores the state of the interpreter to a snapshot taken
- * by Tcl_SaveResult. After this call, the token for
- * the interpreter state is no longer valid.
+ * Restores the state of the interpreter to a snapshot taken by
+ * Tcl_SaveResult. After this call, the token for the interpreter state
+ * is no longer valid.
*
* Results:
- * None.
+ * None.
*
* Side effects:
- * Restores the interpreter result.
+ * Restores the interpreter result.
*
*----------------------------------------------------------------------
*/
void
-Tcl_RestoreResult(interp, statePtr)
- Tcl_Interp* interp; /* Interpreter being restored. */
- Tcl_SavedResult *statePtr; /* State returned by Tcl_SaveResult. */
+Tcl_RestoreResult(
+ Tcl_Interp *interp, /* Interpreter being restored. */
+ Tcl_SavedResult *statePtr) /* State returned by Tcl_SaveResult. */
{
Interp *iPtr = (Interp *) interp;
@@ -145,7 +313,7 @@ Tcl_RestoreResult(interp, statePtr)
*/
if (iPtr->appendResult != NULL) {
- ckfree((char *)iPtr->appendResult);
+ ckfree((char *) iPtr->appendResult);
}
iPtr->appendResult = statePtr->appendResult;
@@ -173,23 +341,22 @@ Tcl_RestoreResult(interp, statePtr)
*
* Tcl_DiscardResult --
*
- * Frees the memory associated with an interpreter snapshot
- * taken by Tcl_SaveResult. If the snapshot is not
- * restored, this procedure must be called to discard it,
- * or the memory will be lost.
+ * Frees the memory associated with an interpreter snapshot taken by
+ * Tcl_SaveResult. If the snapshot is not restored, this function must be
+ * called to discard it, or the memory will be lost.
*
* Results:
- * None.
+ * None.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
void
-Tcl_DiscardResult(statePtr)
- Tcl_SavedResult *statePtr; /* State returned by Tcl_SaveResult. */
+Tcl_DiscardResult(
+ Tcl_SavedResult *statePtr) /* State returned by Tcl_SaveResult. */
{
TclDecrRefCount(statePtr->objResultPtr);
@@ -209,39 +376,39 @@ Tcl_DiscardResult(statePtr)
*
* Tcl_SetResult --
*
- * Arrange for "string" to be the Tcl return value.
+ * Arrange for "result" to be the Tcl return value.
*
* Results:
* None.
*
* Side effects:
- * interp->result is left pointing either to "string" (if "copy" is 0)
- * or to a copy of string. Also, the object result is reset.
+ * interp->result is left pointing either to "result" or to a copy of it.
+ * Also, the object result is reset.
*
*----------------------------------------------------------------------
*/
void
-Tcl_SetResult(interp, string, freeProc)
- Tcl_Interp *interp; /* Interpreter with which to associate the
+Tcl_SetResult(
+ Tcl_Interp *interp, /* Interpreter with which to associate the
* return value. */
- register char *string; /* Value to be returned. If NULL, the
- * result is set to an empty string. */
- Tcl_FreeProc *freeProc; /* Gives information about the string:
- * TCL_STATIC, TCL_VOLATILE, or the address
- * of a Tcl_FreeProc such as free. */
+ register char *result, /* Value to be returned. If NULL, the result
+ * is set to an empty string. */
+ Tcl_FreeProc *freeProc) /* Gives information about the string:
+ * TCL_STATIC, TCL_VOLATILE, or the address of
+ * a Tcl_FreeProc such as free. */
{
Interp *iPtr = (Interp *) interp;
int length;
register Tcl_FreeProc *oldFreeProc = iPtr->freeProc;
char *oldResult = iPtr->result;
- if (string == NULL) {
+ if (result == NULL) {
iPtr->resultSpace[0] = 0;
iPtr->result = iPtr->resultSpace;
iPtr->freeProc = 0;
} else if (freeProc == TCL_VOLATILE) {
- length = strlen(string);
+ length = strlen(result);
if (length > TCL_RESULT_SIZE) {
iPtr->result = (char *) ckalloc((unsigned) length+1);
iPtr->freeProc = TCL_DYNAMIC;
@@ -249,16 +416,16 @@ Tcl_SetResult(interp, string, freeProc)
iPtr->result = iPtr->resultSpace;
iPtr->freeProc = 0;
}
- strcpy(iPtr->result, string);
+ strcpy(iPtr->result, result);
} else {
- iPtr->result = string;
+ iPtr->result = result;
iPtr->freeProc = freeProc;
}
/*
- * If the old result was dynamically-allocated, free it up. Do it
- * here, rather than at the beginning, in case the new result value
- * was part of the old result value.
+ * If the old result was dynamically-allocated, free it up. Do it here,
+ * rather than at the beginning, in case the new result value was part of
+ * the old result value.
*/
if (oldFreeProc != 0) {
@@ -294,17 +461,17 @@ Tcl_SetResult(interp, string, freeProc)
*/
CONST char *
-Tcl_GetStringResult(interp)
- register Tcl_Interp *interp; /* Interpreter whose result to return. */
+Tcl_GetStringResult(
+ register Tcl_Interp *interp)/* Interpreter whose result to return. */
{
/*
- * If the string result is empty, move the object result to the
- * string result, then reset the object result.
+ * If the string result is empty, move the object result to the string
+ * result, then reset the object result.
*/
-
+
if (*(interp->result) == 0) {
Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
- TCL_VOLATILE);
+ TCL_VOLATILE);
}
return interp->result;
}
@@ -320,22 +487,20 @@ Tcl_GetStringResult(interp)
* None.
*
* Side effects:
- * interp->objResultPtr is left pointing to the object referenced
- * by objPtr. The object's reference count is incremented since
- * there is now a new reference to it. The reference count for any
- * old objResultPtr value is decremented. Also, the string result
- * is reset.
+ * interp->objResultPtr is left pointing to the object referenced by
+ * objPtr. The object's reference count is incremented since there is now
+ * a new reference to it. The reference count for any old objResultPtr
+ * value is decremented. Also, the string result is reset.
*
*----------------------------------------------------------------------
*/
void
-Tcl_SetObjResult(interp, objPtr)
- Tcl_Interp *interp; /* Interpreter with which to associate the
+Tcl_SetObjResult(
+ Tcl_Interp *interp, /* Interpreter with which to associate the
* return object value. */
- register Tcl_Obj *objPtr; /* Tcl object to be returned. If NULL, the
- * obj result is made an empty string
- * object. */
+ register Tcl_Obj *objPtr) /* Tcl object to be returned. If NULL, the obj
+ * result is made an empty string object. */
{
register Interp *iPtr = (Interp *) interp;
register Tcl_Obj *oldObjResult = iPtr->objResultPtr;
@@ -344,10 +509,10 @@ Tcl_SetObjResult(interp, objPtr)
Tcl_IncrRefCount(objPtr); /* since interp result is a reference */
/*
- * We wait until the end to release the old object result, in case
- * we are setting the result to itself.
+ * We wait until the end to release the old object result, in case we are
+ * setting the result to itself.
*/
-
+
TclDecrRefCount(oldObjResult);
/*
@@ -372,41 +537,41 @@ Tcl_SetObjResult(interp, objPtr)
* Tcl_GetObjResult --
*
* Returns an interpreter's result value as a Tcl object. The object's
- * reference count is not modified; the caller must do that if it
- * needs to hold on to a long-term reference to it.
+ * reference count is not modified; the caller must do that if it needs
+ * to hold on to a long-term reference to it.
*
* Results:
* The interpreter's result as an object.
*
* Side effects:
- * If the interpreter has a non-empty string result, the result object
- * is either empty or stale because some procedure set interp->result
- * directly. If so, the string result is moved to the result object
- * then the string result is reset.
+ * If the interpreter has a non-empty string result, the result object is
+ * either empty or stale because some function set interp->result
+ * directly. If so, the string result is moved to the result object then
+ * the string result is reset.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
-Tcl_GetObjResult(interp)
- Tcl_Interp *interp; /* Interpreter whose result to return. */
+Tcl_GetObjResult(
+ Tcl_Interp *interp) /* Interpreter whose result to return. */
{
register Interp *iPtr = (Interp *) interp;
Tcl_Obj *objResultPtr;
int length;
/*
- * If the string result is non-empty, move the string result to the
- * object result, then reset the string result.
+ * If the string result is non-empty, move the string result to the object
+ * result, then reset the string result.
*/
-
+
if (*(iPtr->result) != 0) {
ResetObjResult(iPtr);
-
+
objResultPtr = iPtr->objResultPtr;
length = strlen(iPtr->result);
TclInitStringRep(objResultPtr, iPtr->result, length);
-
+
if (iPtr->freeProc != NULL) {
if (iPtr->freeProc == TCL_DYNAMIC) {
ckfree(iPtr->result);
@@ -426,110 +591,51 @@ Tcl_GetObjResult(interp)
*
* Tcl_AppendResultVA --
*
- * Append a variable number of strings onto the interpreter's string
- * result.
+ * Append a variable number of strings onto the interpreter's result.
*
* Results:
* None.
*
* Side effects:
- * The result of the interpreter given by the first argument is
- * extended by the strings in the va_list (up to a terminating NULL
- * argument).
+ * The result of the interpreter given by the first argument is extended
+ * by the strings in the va_list (up to a terminating NULL argument).
*
- * If the string result is empty, the object result is moved to the
- * string result, then the object result is reset.
+ * If the string result is non-empty, the object result forced to be a
+ * duplicate of it first. There will be a string result afterwards.
*
*----------------------------------------------------------------------
*/
void
-Tcl_AppendResultVA (interp, argList)
- Tcl_Interp *interp; /* Interpreter with which to associate the
+Tcl_AppendResultVA(
+ Tcl_Interp *interp, /* Interpreter with which to associate the
* return value. */
- va_list argList; /* Variable argument list. */
+ va_list argList) /* Variable argument list. */
{
-#define STATIC_LIST_SIZE 16
- Interp *iPtr = (Interp *) interp;
- char *string, *static_list[STATIC_LIST_SIZE];
- char **args = static_list;
- int nargs_space = STATIC_LIST_SIZE;
- int nargs, newSpace, i;
-
- /*
- * If the string result is empty, move the object result to the
- * string result, then reset the object result.
- */
+ Tcl_Obj *objPtr = Tcl_GetObjResult(interp);
- if (*(iPtr->result) == 0) {
- Tcl_SetResult((Tcl_Interp *) iPtr,
- TclGetString(Tcl_GetObjResult((Tcl_Interp *) iPtr)),
- TCL_VOLATILE);
- }
-
- /*
- * Scan through all the arguments to see how much space is needed
- * and save pointers to the arguments in the args array,
- * reallocating as necessary.
- */
-
- nargs = 0;
- newSpace = 0;
- while (1) {
- string = va_arg(argList, char *);
- if (string == NULL) {
- break;
- }
- if (nargs >= nargs_space) {
- /*
- * Expand the args buffer
- */
- nargs_space += STATIC_LIST_SIZE;
- if (args == static_list) {
- args = (void *)ckalloc(nargs_space * sizeof(char *));
- for (i = 0; i < nargs; ++i) {
- args[i] = static_list[i];
- }
- } else {
- args = (void *)ckrealloc((void *)args,
- nargs_space * sizeof(char *));
- }
- }
- newSpace += strlen(string);
- args[nargs++] = string;
+ if (Tcl_IsShared(objPtr)) {
+ objPtr = Tcl_DuplicateObj(objPtr);
}
+ Tcl_AppendStringsToObjVA(objPtr, argList);
+ Tcl_SetObjResult(interp, objPtr);
/*
- * If the append buffer isn't already setup and large enough to hold
- * the new data, set it up.
+ * Strictly we should call Tcl_GetStringResult(interp) here to make sure
+ * that interp->result is correct according to the old contract, but that
+ * makes the performance of much code (e.g. in Tk) absolutely awful. So we
+ * leave it out; code that really wants interp->result can just insert the
+ * calls to Tcl_GetStringResult() itself. [Patch 1041072 discussion]
*/
- if ((iPtr->result != iPtr->appendResult)
- || (iPtr->appendResult[iPtr->appendUsed] != 0)
- || ((newSpace + iPtr->appendUsed) >= iPtr->appendAvl)) {
- SetupAppendBuffer(iPtr, newSpace);
- }
-
+#ifdef USE_DIRECT_INTERP_RESULT_ACCESS
/*
- * Now go through all the argument strings again, copying them into the
- * buffer.
+ * Ensure that the interp->result is legal so old Tcl 7.* code still
+ * works. There's still embarrasingly much of it about...
*/
- for (i = 0; i < nargs; ++i) {
- string = args[i];
- strcpy(iPtr->appendResult + iPtr->appendUsed, string);
- iPtr->appendUsed += strlen(string);
- }
-
- /*
- * If we had to allocate a buffer from the heap,
- * free it now.
- */
-
- if (args != static_list) {
- ckfree((void *)args);
- }
-#undef STATIC_LIST_SIZE
+ (void) Tcl_GetStringResult(interp);
+#endif /* USE_DIRECT_INTERP_RESULT_ACCESS */
}
/*
@@ -537,30 +643,29 @@ Tcl_AppendResultVA (interp, argList)
*
* Tcl_AppendResult --
*
- * Append a variable number of strings onto the interpreter's string
- * result.
+ * Append a variable number of strings onto the interpreter's result.
*
* Results:
* None.
*
* Side effects:
- * The result of the interpreter given by the first argument is
- * extended by the strings given by the second and following arguments
- * (up to a terminating NULL argument).
+ * The result of the interpreter given by the first argument is extended
+ * by the strings given by the second and following arguments (up to a
+ * terminating NULL argument).
*
- * If the string result is empty, the object result is moved to the
- * string result, then the object result is reset.
+ * If the string result is non-empty, the object result forced to be a
+ * duplicate of it first. There will be a string result afterwards.
*
*----------------------------------------------------------------------
*/
void
-Tcl_AppendResult TCL_VARARGS_DEF(Tcl_Interp *,arg1)
+Tcl_AppendResult(
+ Tcl_Interp *interp, ...)
{
- Tcl_Interp *interp;
va_list argList;
- interp = TCL_VARARGS_START(Tcl_Interp *,arg1,argList);
+ va_start(argList, interp);
Tcl_AppendResultVA(interp, argList);
va_end(argList);
}
@@ -577,10 +682,10 @@ Tcl_AppendResult TCL_VARARGS_DEF(Tcl_Interp *,arg1)
* None.
*
* Side effects:
- * The result in the interpreter given by the first argument is
- * extended with a list element converted from string. A separator
- * space is added before the converted list element unless the current
- * result is empty, contains the single character "{", or ends in " {".
+ * The result in the interpreter given by the first argument is extended
+ * with a list element converted from string. A separator space is added
+ * before the converted list element unless the current result is empty,
+ * contains the single character "{", or ends in " {".
*
* If the string result is empty, the object result is moved to the
* string result, then the object result is reset.
@@ -589,11 +694,11 @@ Tcl_AppendResult TCL_VARARGS_DEF(Tcl_Interp *,arg1)
*/
void
-Tcl_AppendElement(interp, string)
- Tcl_Interp *interp; /* Interpreter whose result is to be
+Tcl_AppendElement(
+ Tcl_Interp *interp, /* Interpreter whose result is to be
* extended. */
- CONST char *string; /* String to convert to list element and
- * add to result. */
+ CONST char *element) /* String to convert to list element and add
+ * to result. */
{
Interp *iPtr = (Interp *) interp;
char *dst;
@@ -601,30 +706,27 @@ Tcl_AppendElement(interp, string)
int flags;
/*
- * If the string result is empty, move the object result to the
- * string result, then reset the object result.
+ * If the string result is empty, move the object result to the string
+ * result, then reset the object result.
*/
- if (*(iPtr->result) == 0) {
- Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
- TCL_VOLATILE);
- }
+ (void) Tcl_GetStringResult(interp);
/*
- * See how much space is needed, and grow the append buffer if
- * needed to accommodate the list element.
+ * See how much space is needed, and grow the append buffer if needed to
+ * accommodate the list element.
*/
- size = Tcl_ScanElement(string, &flags) + 1;
+ size = Tcl_ScanElement(element, &flags) + 1;
if ((iPtr->result != iPtr->appendResult)
|| (iPtr->appendResult[iPtr->appendUsed] != 0)
|| ((size + iPtr->appendUsed) >= iPtr->appendAvl)) {
- SetupAppendBuffer(iPtr, size+iPtr->appendUsed);
+ SetupAppendBuffer(iPtr, size+iPtr->appendUsed);
}
/*
- * Convert the string into a list element and copy it to the
- * buffer that's forming, with a space separator if needed.
+ * Convert the string into a list element and copy it to the buffer that's
+ * forming, with a space separator if needed.
*/
dst = iPtr->appendResult + iPtr->appendUsed;
@@ -632,8 +734,16 @@ Tcl_AppendElement(interp, string)
iPtr->appendUsed++;
*dst = ' ';
dst++;
+
+ /*
+ * If we need a space to separate this element from preceding stuff,
+ * then this element will not lead a list, and need not have it's
+ * leading '#' quoted.
+ */
+
+ flags |= TCL_DONT_QUOTE_HASH;
}
- iPtr->appendUsed += Tcl_ConvertElement(string, dst, flags);
+ iPtr->appendUsed += Tcl_ConvertElement(element, dst, flags);
}
/*
@@ -641,10 +751,10 @@ Tcl_AppendElement(interp, string)
*
* SetupAppendBuffer --
*
- * This procedure makes sure that there is an append buffer properly
- * initialized, if necessary, from the interpreter's result, and
- * that it has at least enough room to accommodate newSpace new
- * bytes of information.
+ * This function makes sure that there is an append buffer properly
+ * initialized, if necessary, from the interpreter's result, and that it
+ * has at least enough room to accommodate newSpace new bytes of
+ * information.
*
* Results:
* None.
@@ -656,10 +766,10 @@ Tcl_AppendElement(interp, string)
*/
static void
-SetupAppendBuffer(iPtr, newSpace)
- Interp *iPtr; /* Interpreter whose result is being set up. */
- int newSpace; /* Make sure that at least this many bytes
- * of new information may be added. */
+SetupAppendBuffer(
+ Interp *iPtr, /* Interpreter whose result is being set up. */
+ int newSpace) /* Make sure that at least this many bytes of
+ * new information may be added. */
{
int totalSpace;
@@ -671,9 +781,9 @@ SetupAppendBuffer(iPtr, newSpace)
if (iPtr->result != iPtr->appendResult) {
/*
- * If an oversized buffer was used recently, then free it up
- * so we go back to a smaller buffer. This avoids tying up
- * memory forever after a large operation.
+ * If an oversized buffer was used recently, then free it up so we go
+ * back to a smaller buffer. This avoids tying up memory forever after
+ * a large operation.
*/
if (iPtr->appendAvl > 500) {
@@ -685,13 +795,13 @@ SetupAppendBuffer(iPtr, newSpace)
} else if (iPtr->result[iPtr->appendUsed] != 0) {
/*
* Most likely someone has modified a result created by
- * Tcl_AppendResult et al. so that it has a different size.
- * Just recompute the size.
+ * Tcl_AppendResult et al. so that it has a different size. Just
+ * recompute the size.
*/
iPtr->appendUsed = strlen(iPtr->result);
}
-
+
totalSpace = newSpace + iPtr->appendUsed;
if (totalSpace >= iPtr->appendAvl) {
char *new;
@@ -711,7 +821,7 @@ SetupAppendBuffer(iPtr, newSpace)
} else if (iPtr->result != iPtr->appendResult) {
strcpy(iPtr->appendResult, iPtr->result);
}
-
+
Tcl_FreeResult((Tcl_Interp *) iPtr);
iPtr->result = iPtr->appendResult;
}
@@ -721,9 +831,9 @@ SetupAppendBuffer(iPtr, newSpace)
*
* Tcl_FreeResult --
*
- * This procedure frees up the memory associated with an interpreter's
+ * This function frees up the memory associated with an interpreter's
* string result. It also resets the interpreter's result object.
- * Tcl_FreeResult is most commonly used when a procedure is about to
+ * Tcl_FreeResult is most commonly used when a function is about to
* replace one result value with another.
*
* Results:
@@ -731,19 +841,19 @@ SetupAppendBuffer(iPtr, newSpace)
*
* Side effects:
* Frees the memory associated with interp's string result and sets
- * interp->freeProc to zero, but does not change interp->result or
- * clear error state. Resets interp's result object to an unshared
- * empty object.
+ * interp->freeProc to zero, but does not change interp->result or clear
+ * error state. Resets interp's result object to an unshared empty
+ * object.
*
*----------------------------------------------------------------------
*/
void
-Tcl_FreeResult(interp)
- register Tcl_Interp *interp; /* Interpreter for which to free result. */
+Tcl_FreeResult(
+ register Tcl_Interp *interp)/* Interpreter for which to free result. */
{
register Interp *iPtr = (Interp *) interp;
-
+
if (iPtr->freeProc != NULL) {
if (iPtr->freeProc == TCL_DYNAMIC) {
ckfree(iPtr->result);
@@ -752,7 +862,7 @@ Tcl_FreeResult(interp)
}
iPtr->freeProc = 0;
}
-
+
ResetObjResult(iPtr);
}
@@ -761,24 +871,23 @@ Tcl_FreeResult(interp)
*
* Tcl_ResetResult --
*
- * This procedure resets both the interpreter's string and object
- * results.
+ * This function resets both the interpreter's string and object results.
*
* Results:
* None.
*
* Side effects:
- * It resets the result object to an unshared empty object. It
- * then restores the interpreter's string result area to its default
- * initialized state, freeing up any memory that may have been
- * allocated. It also clears any error information for the interpreter.
+ * It resets the result object to an unshared empty object. It then
+ * restores the interpreter's string result area to its default
+ * initialized state, freeing up any memory that may have been allocated.
+ * It also clears any error information for the interpreter.
*
*----------------------------------------------------------------------
*/
void
-Tcl_ResetResult(interp)
- register Tcl_Interp *interp; /* Interpreter for which to clear result. */
+Tcl_ResetResult(
+ register Tcl_Interp *interp)/* Interpreter for which to clear result. */
{
register Interp *iPtr = (Interp *) interp;
@@ -793,7 +902,31 @@ Tcl_ResetResult(interp)
}
iPtr->result = iPtr->resultSpace;
iPtr->resultSpace[0] = 0;
- iPtr->flags &= ~(ERR_ALREADY_LOGGED | ERR_IN_PROGRESS | ERROR_CODE_SET);
+ if (iPtr->errorCode) {
+ /* Legacy support */
+ if (iPtr->flags & ERR_LEGACY_COPY) {
+ Tcl_ObjSetVar2(interp, iPtr->ecVar, NULL,
+ iPtr->errorCode, TCL_GLOBAL_ONLY);
+ }
+ Tcl_DecrRefCount(iPtr->errorCode);
+ iPtr->errorCode = NULL;
+ }
+ if (iPtr->errorInfo) {
+ /* Legacy support */
+ if (iPtr->flags & ERR_LEGACY_COPY) {
+ Tcl_ObjSetVar2(interp, iPtr->eiVar, NULL,
+ iPtr->errorInfo, TCL_GLOBAL_ONLY);
+ }
+ Tcl_DecrRefCount(iPtr->errorInfo);
+ iPtr->errorInfo = NULL;
+ }
+ iPtr->returnLevel = 1;
+ iPtr->returnCode = TCL_OK;
+ if (iPtr->returnOpts) {
+ Tcl_DecrRefCount(iPtr->returnOpts);
+ iPtr->returnOpts = NULL;
+ }
+ iPtr->flags &= ~(ERR_ALREADY_LOGGED | ERR_LEGACY_COPY);
}
/*
@@ -801,22 +934,22 @@ Tcl_ResetResult(interp)
*
* ResetObjResult --
*
- * Procedure used to reset an interpreter's Tcl result object.
+ * Function used to reset an interpreter's Tcl result object.
*
* Results:
* None.
*
* Side effects:
* Resets the interpreter's result object to an unshared empty string
- * object with ref count one. It does not clear any error information
- * in the interpreter.
+ * object with ref count one. It does not clear any error information in
+ * the interpreter.
*
*----------------------------------------------------------------------
*/
static void
-ResetObjResult(iPtr)
- register Interp *iPtr; /* Points to the interpreter whose result
+ResetObjResult(
+ register Interp *iPtr) /* Points to the interpreter whose result
* object should be reset. */
{
register Tcl_Obj *objResultPtr = iPtr->objResultPtr;
@@ -827,17 +960,15 @@ ResetObjResult(iPtr)
Tcl_IncrRefCount(objResultPtr);
iPtr->objResultPtr = objResultPtr;
} else {
- if ((objResultPtr->bytes != NULL)
- && (objResultPtr->bytes != tclEmptyStringRep)) {
- ckfree((char *) objResultPtr->bytes);
- }
- objResultPtr->bytes = tclEmptyStringRep;
- objResultPtr->length = 0;
- if ((objResultPtr->typePtr != NULL)
- && (objResultPtr->typePtr->freeIntRepProc != NULL)) {
- objResultPtr->typePtr->freeIntRepProc(objResultPtr);
+ if (objResultPtr->bytes != tclEmptyStringRep) {
+ if (objResultPtr->bytes) {
+ ckfree((char *) objResultPtr->bytes);
+ }
+ objResultPtr->bytes = tclEmptyStringRep;
+ objResultPtr->length = 0;
}
- objResultPtr->typePtr = (Tcl_ObjType *) NULL;
+ TclFreeIntRep(objResultPtr);
+ objResultPtr->typePtr = NULL;
}
}
@@ -846,48 +977,40 @@ ResetObjResult(iPtr)
*
* Tcl_SetErrorCodeVA --
*
- * This procedure is called to record machine-readable information
- * about an error that is about to be returned.
+ * This function is called to record machine-readable information about
+ * an error that is about to be returned.
*
* Results:
* None.
*
* Side effects:
- * The errorCode global variable is modified to hold all of the
- * arguments to this procedure, in a list form with each argument
- * becoming one element of the list. A flag is set internally
- * to remember that errorCode has been set, so the variable doesn't
- * get set automatically when the error is returned.
+ * The errorCode field of the interp is modified to hold all of the
+ * arguments to this function, in a list form with each argument becoming
+ * one element of the list.
*
*----------------------------------------------------------------------
*/
void
-Tcl_SetErrorCodeVA (interp, argList)
- Tcl_Interp *interp; /* Interpreter in which to access the errorCode
- * variable. */
- va_list argList; /* Variable argument list. */
+Tcl_SetErrorCodeVA(
+ Tcl_Interp *interp, /* Interpreter in which to set errorCode */
+ va_list argList) /* Variable argument list. */
{
- char *string;
- int flags;
- Interp *iPtr = (Interp *) interp;
+ Tcl_Obj *errorObj = Tcl_NewObj();
/*
- * Scan through the arguments one at a time, appending them to
- * $errorCode as list elements.
+ * Scan through the arguments one at a time, appending them to the
+ * errorCode field as list elements.
*/
- flags = TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT;
while (1) {
- string = va_arg(argList, char *);
- if (string == NULL) {
+ char *elem = va_arg(argList, char *);
+ if (elem == NULL) {
break;
}
- (void) Tcl_SetVar2((Tcl_Interp *) iPtr, "errorCode",
- (char *) NULL, string, flags);
- flags |= TCL_APPEND_VALUE;
+ Tcl_ListObjAppendElement(NULL, errorObj, Tcl_NewStringObj(elem, -1));
}
- iPtr->flags |= ERROR_CODE_SET;
+ Tcl_SetObjErrorCode(interp, errorObj);
}
/*
@@ -895,34 +1018,32 @@ Tcl_SetErrorCodeVA (interp, argList)
*
* Tcl_SetErrorCode --
*
- * This procedure is called to record machine-readable information
- * about an error that is about to be returned.
+ * This function is called to record machine-readable information about
+ * an error that is about to be returned.
*
* Results:
* None.
*
* Side effects:
- * The errorCode global variable is modified to hold all of the
- * arguments to this procedure, in a list form with each argument
- * becoming one element of the list. A flag is set internally
- * to remember that errorCode has been set, so the variable doesn't
- * get set automatically when the error is returned.
+ * The errorCode field of the interp is modified to hold all of the
+ * arguments to this function, in a list form with each argument becoming
+ * one element of the list.
*
*----------------------------------------------------------------------
*/
- /* VARARGS2 */
+
void
-Tcl_SetErrorCode TCL_VARARGS_DEF(Tcl_Interp *,arg1)
+Tcl_SetErrorCode(
+ Tcl_Interp *interp, ...)
{
- Tcl_Interp *interp;
va_list argList;
/*
- * Scan through the arguments one at a time, appending them to
- * $errorCode as list elements.
+ * Scan through the arguments one at a time, appending them to the
+ * errorCode field as list elements.
*/
- interp = TCL_VARARGS_START(Tcl_Interp *,arg1,argList);
+ va_start(argList, interp);
Tcl_SetErrorCodeVA(interp, argList);
va_end(argList);
}
@@ -932,32 +1053,484 @@ Tcl_SetErrorCode TCL_VARARGS_DEF(Tcl_Interp *,arg1)
*
* Tcl_SetObjErrorCode --
*
- * This procedure is called to record machine-readable information
- * about an error that is about to be returned. The caller should
- * build a list object up and pass it to this routine.
+ * This function is called to record machine-readable information about
+ * an error that is about to be returned. The caller should build a list
+ * object up and pass it to this routine.
*
* Results:
* None.
*
* Side effects:
- * The errorCode global variable is modified to be the new value.
- * A flag is set internally to remember that errorCode has been
- * set, so the variable doesn't get set automatically when the
- * error is returned.
+ * The errorCode field of the interp is set to the new value.
*
*----------------------------------------------------------------------
*/
void
-Tcl_SetObjErrorCode(interp, errorObjPtr)
- Tcl_Interp *interp;
- Tcl_Obj *errorObjPtr;
+Tcl_SetObjErrorCode(
+ Tcl_Interp *interp,
+ Tcl_Obj *errorObjPtr)
+{
+ Interp *iPtr = (Interp *) interp;
+
+ if (iPtr->errorCode) {
+ Tcl_DecrRefCount(iPtr->errorCode);
+ }
+ iPtr->errorCode = errorObjPtr;
+ Tcl_IncrRefCount(iPtr->errorCode);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetKeys --
+ *
+ * Returns a Tcl_Obj * array of the standard keys used in the return
+ * options dictionary.
+ *
+ * Broadly sharing one copy of these key values helps with both memory
+ * efficiency and dictionary lookup times.
+ *
+ * Results:
+ * A Tcl_Obj * array.
+ *
+ * Side effects:
+ * First time called in a thread, creates the keys (allocating memory)
+ * and arranges for their cleanup at thread exit.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj **
+GetKeys(void)
{
- Interp *iPtr;
-
- iPtr = (Interp *) interp;
- Tcl_SetVar2Ex(interp, "errorCode", NULL, errorObjPtr, TCL_GLOBAL_ONLY);
- iPtr->flags |= ERROR_CODE_SET;
+ static Tcl_ThreadDataKey returnKeysKey;
+ Tcl_Obj **keys = Tcl_GetThreadData(&returnKeysKey,
+ (int) (KEY_LAST * sizeof(Tcl_Obj *)));
+
+ if (keys[0] == NULL) {
+ /*
+ * First call in this thread, create the keys...
+ */
+
+ int i;
+
+ TclNewLiteralStringObj(keys[KEY_CODE], "-code");
+ TclNewLiteralStringObj(keys[KEY_ERRORCODE], "-errorcode");
+ TclNewLiteralStringObj(keys[KEY_ERRORINFO], "-errorinfo");
+ TclNewLiteralStringObj(keys[KEY_ERRORLINE], "-errorline");
+ TclNewLiteralStringObj(keys[KEY_LEVEL], "-level");
+ TclNewLiteralStringObj(keys[KEY_OPTIONS], "-options");
+
+ for (i = KEY_CODE; i < KEY_LAST; i++) {
+ Tcl_IncrRefCount(keys[i]);
+ }
+
+ /*
+ * ... and arrange for their clenaup.
+ */
+
+ Tcl_CreateThreadExitHandler(ReleaseKeys, (ClientData) keys);
+ }
+ return keys;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReleaseKeys --
+ *
+ * Called as a thread exit handler to cleanup return options dictionary
+ * keys.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Frees memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ReleaseKeys(
+ ClientData clientData)
+{
+ Tcl_Obj **keys = (Tcl_Obj **)clientData;
+ int i;
+
+ for (i = KEY_CODE; i < KEY_LAST; i++) {
+ Tcl_DecrRefCount(keys[i]);
+ keys[i] = NULL;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclProcessReturn --
+ *
+ * Does the work of the [return] command based on the code, level, and
+ * returnOpts arguments. Note that the code argument must agree with the
+ * -code entry in returnOpts and the level argument must agree with the
+ * -level entry in returnOpts, as is the case for values returned from
+ * TclMergeReturnOptions.
+ *
+ * Results:
+ * Returns the return code the [return] command should return.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclProcessReturn(
+ Tcl_Interp *interp,
+ int code,
+ int level,
+ Tcl_Obj *returnOpts)
+{
+ Interp *iPtr = (Interp *) interp;
+ Tcl_Obj *valuePtr;
+ Tcl_Obj **keys = GetKeys();
+
+ /*
+ * Store the merged return options.
+ */
+
+ if (iPtr->returnOpts != returnOpts) {
+ if (iPtr->returnOpts) {
+ Tcl_DecrRefCount(iPtr->returnOpts);
+ }
+ iPtr->returnOpts = returnOpts;
+ Tcl_IncrRefCount(iPtr->returnOpts);
+ }
+
+ if (code == TCL_ERROR) {
+ if (iPtr->errorInfo) {
+ Tcl_DecrRefCount(iPtr->errorInfo);
+ iPtr->errorInfo = NULL;
+ }
+ Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORINFO], &valuePtr);
+ if (valuePtr != NULL) {
+ int infoLen;
+
+ (void) TclGetStringFromObj(valuePtr, &infoLen);
+ if (infoLen) {
+ iPtr->errorInfo = valuePtr;
+ Tcl_IncrRefCount(iPtr->errorInfo);
+ iPtr->flags |= ERR_ALREADY_LOGGED;
+ }
+ }
+ Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORCODE], &valuePtr);
+ if (valuePtr != NULL) {
+ Tcl_SetObjErrorCode(interp, valuePtr);
+ } else {
+ Tcl_SetErrorCode(interp, "NONE", NULL);
+ }
+
+ Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORLINE], &valuePtr);
+ if (valuePtr != NULL) {
+ TclGetIntFromObj(NULL, valuePtr, &iPtr->errorLine);
+ }
+ }
+ if (level != 0) {
+ iPtr->returnLevel = level;
+ iPtr->returnCode = code;
+ return TCL_RETURN;
+ }
+ if (code == TCL_ERROR) {
+ iPtr->flags |= ERR_LEGACY_COPY;
+ }
+ return code;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMergeReturnOptions --
+ *
+ * Parses, checks, and stores the options to the [return] command.
+ *
+ * Results:
+ * Returns TCL_ERROR is any of the option values are invalid. Otherwise,
+ * returns TCL_OK, and writes the returnOpts, code, and level values to
+ * the pointers provided.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclMergeReturnOptions(
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[], /* Argument objects. */
+ Tcl_Obj **optionsPtrPtr, /* If not NULL, points to space for a (Tcl_Obj
+ * *) where the pointer to the merged return
+ * options dictionary should be written */
+ int *codePtr, /* If not NULL, points to space where the
+ * -code value should be written */
+ int *levelPtr) /* If not NULL, points to space where the
+ * -level value should be written */
+{
+ int code=TCL_OK;
+ int level = 1;
+ Tcl_Obj *valuePtr;
+ Tcl_Obj *returnOpts = Tcl_NewObj();
+ Tcl_Obj **keys = GetKeys();
+
+ for (; objc > 1; objv += 2, objc -= 2) {
+ int optLen;
+ CONST char *opt = TclGetStringFromObj(objv[0], &optLen);
+ int compareLen;
+ CONST char *compare =
+ TclGetStringFromObj(keys[KEY_OPTIONS], &compareLen);
+
+ if ((optLen == compareLen) && (strcmp(opt, compare) == 0)) {
+ Tcl_DictSearch search;
+ int done = 0;
+ Tcl_Obj *keyPtr;
+ Tcl_Obj *dict = objv[1];
+
+ nestedOptions:
+ if (TCL_ERROR == Tcl_DictObjFirst(NULL, dict, &search,
+ &keyPtr, &valuePtr, &done)) {
+ /*
+ * Value is not a legal dictionary.
+ */
+
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "bad ", compare,
+ " value: expected dictionary but got \"",
+ TclGetString(objv[1]), "\"", NULL);
+ goto error;
+ }
+
+ while (!done) {
+ Tcl_DictObjPut(NULL, returnOpts, keyPtr, valuePtr);
+ Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done);
+ }
+
+ Tcl_DictObjGet(NULL, returnOpts, keys[KEY_OPTIONS], &valuePtr);
+ if (valuePtr != NULL) {
+ dict = valuePtr;
+ Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_OPTIONS]);
+ goto nestedOptions;
+ }
+
+ } else {
+ Tcl_DictObjPut(NULL, returnOpts, objv[0], objv[1]);
+ }
+ }
+
+ /*
+ * Check for bogus -code value.
+ */
+
+ Tcl_DictObjGet(NULL, returnOpts, keys[KEY_CODE], &valuePtr);
+ if ((valuePtr != NULL)
+ && (TCL_ERROR == TclGetIntFromObj(NULL, valuePtr, &code))) {
+ static CONST char *returnCodes[] = {
+ "ok", "error", "return", "break", "continue", NULL
+ };
+
+ if (TCL_ERROR == Tcl_GetIndexFromObj(NULL, valuePtr, returnCodes,
+ NULL, TCL_EXACT, &code)) {
+ /*
+ * Value is not a legal return code.
+ */
+
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "bad completion code \"",
+ TclGetString(valuePtr),
+ "\": must be ok, error, return, break, "
+ "continue, or an integer", NULL);
+ goto error;
+ }
+ }
+ if (valuePtr != NULL) {
+ Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_CODE]);
+ }
+
+ /*
+ * Check for bogus -level value.
+ */
+
+ Tcl_DictObjGet(NULL, returnOpts, keys[KEY_LEVEL], &valuePtr);
+ if (valuePtr != NULL) {
+ if ((TCL_ERROR == TclGetIntFromObj(NULL, valuePtr, &level))
+ || (level < 0)) {
+ /*
+ * Value is not a legal level.
+ */
+
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "bad -level value: "
+ "expected non-negative integer but got \"",
+ TclGetString(valuePtr), "\"", NULL);
+ goto error;
+ }
+ Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_LEVEL]);
+ }
+
+ /*
+ * Check for bogus -errorcode value.
+ */
+
+ Tcl_DictObjGet(NULL, returnOpts, keys[KEY_ERRORCODE], &valuePtr);
+ if (valuePtr != NULL) {
+ int length;
+
+ if (TCL_ERROR == Tcl_ListObjLength(NULL, valuePtr, &length )) {
+ /*
+ * Value is not a list, which is illegal for -errorcode.
+ */
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "bad -errorcode value: "
+ "expected a list but got \"",
+ TclGetString(valuePtr), "\"", NULL);
+ goto error;
+ }
+ }
+
+ /*
+ * Convert [return -code return -level X] to [return -code ok -level X+1]
+ */
+
+ if (code == TCL_RETURN) {
+ level++;
+ code = TCL_OK;
+ }
+
+ if (codePtr != NULL) {
+ *codePtr = code;
+ }
+ if (levelPtr != NULL) {
+ *levelPtr = level;
+ }
+
+ if (optionsPtrPtr == NULL) {
+ /*
+ * Not passing back the options (?!), so clean them up.
+ */
+
+ Tcl_DecrRefCount(returnOpts);
+ } else {
+ *optionsPtrPtr = returnOpts;
+ }
+ return TCL_OK;
+
+ error:
+ Tcl_DecrRefCount(returnOpts);
+ return TCL_ERROR;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * Tcl_GetReturnOptions --
+ *
+ * Packs up the interp state into a dictionary of return options.
+ *
+ * Results:
+ * A dictionary of return options.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tcl_GetReturnOptions(
+ Tcl_Interp *interp,
+ int result)
+{
+ Interp *iPtr = (Interp *) interp;
+ Tcl_Obj *options;
+ Tcl_Obj **keys = GetKeys();
+
+ if (iPtr->returnOpts) {
+ options = Tcl_DuplicateObj(iPtr->returnOpts);
+ } else {
+ options = Tcl_NewObj();
+ }
+
+ if (result == TCL_RETURN) {
+ Tcl_DictObjPut(NULL, options, keys[KEY_CODE],
+ Tcl_NewIntObj(iPtr->returnCode));
+ Tcl_DictObjPut(NULL, options, keys[KEY_LEVEL],
+ Tcl_NewIntObj(iPtr->returnLevel));
+ } else {
+ Tcl_DictObjPut(NULL, options, keys[KEY_CODE],
+ Tcl_NewIntObj(result));
+ Tcl_DictObjPut(NULL, options, keys[KEY_LEVEL],
+ Tcl_NewIntObj(0));
+ }
+
+ if (result == TCL_ERROR) {
+ Tcl_AddObjErrorInfo(interp, "", -1);
+ }
+ if (iPtr->errorCode) {
+ Tcl_DictObjPut(NULL, options, keys[KEY_ERRORCODE], iPtr->errorCode);
+ }
+ if (iPtr->errorInfo) {
+ Tcl_DictObjPut(NULL, options, keys[KEY_ERRORINFO], iPtr->errorInfo);
+ Tcl_DictObjPut(NULL, options, keys[KEY_ERRORLINE],
+ Tcl_NewIntObj(iPtr->errorLine));
+ }
+ return options;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * Tcl_SetReturnOptions --
+ *
+ * Accepts an interp and a dictionary of return options, and sets the
+ * return options of the interp to match the dictionary.
+ *
+ * Results:
+ * A standard status code. Usually TCL_OK, but TCL_ERROR if an invalid
+ * option value was found in the dictionary. If a -level value of 0 is in
+ * the dictionary, then the -code value in the dictionary will be
+ * returned (TCL_OK default).
+ *
+ * Side effects:
+ * Sets the state of the interp.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+int
+Tcl_SetReturnOptions(
+ Tcl_Interp *interp,
+ Tcl_Obj *options)
+{
+ int objc, level, code;
+ Tcl_Obj **objv, *mergedOpts;
+
+ Tcl_IncrRefCount(options);
+ if (TCL_ERROR == TclListObjGetElements(interp, options, &objc, &objv)
+ || (objc % 2)) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "expected dict but got \"",
+ TclGetString(options), "\"", NULL);
+ code = TCL_ERROR;
+ } else if (TCL_ERROR == TclMergeReturnOptions(interp, objc, objv,
+ &mergedOpts, &code, &level)) {
+ code = TCL_ERROR;
+ } else {
+ code = TclProcessReturn(interp, code, level, mergedOpts);
+ }
+
+ Tcl_DecrRefCount(options);
+ return code;
}
/*
@@ -965,83 +1538,72 @@ Tcl_SetObjErrorCode(interp, errorObjPtr)
*
* TclTransferResult --
*
- * Copy the result (and error information) from one interp to
- * another. Used when one interp has caused another interp to
- * evaluate a script and then wants to transfer the results back
- * to itself.
+ * Copy the result (and error information) from one interp to another.
+ * Used when one interp has caused another interp to evaluate a script
+ * and then wants to transfer the results back to itself.
*
- * This routine copies the string reps of the result and error
- * information. It does not simply increment the refcounts of the
- * result and error information objects themselves.
- * It is not legal to exchange objects between interps, because an
- * object may be kept alive by one interp, but have an internal rep
- * that is only valid while some other interp is alive.
+ * This routine copies the string reps of the result and error
+ * information. It does not simply increment the refcounts of the result
+ * and error information objects themselves. It is not legal to exchange
+ * objects between interps, because an object may be kept alive by one
+ * interp, but have an internal rep that is only valid while some other
+ * interp is alive.
*
* Results:
* The target interp's result is set to a copy of the source interp's
- * result. The source's error information "$errorInfo" may be
- * appended to the target's error information and the source's error
- * code "$errorCode" may be stored in the target's error code.
+ * result. The source's errorInfo field may be transferred to the
+ * target's errorInfo field, and the source's errorCode field may be
+ * transferred to the target's errorCode field.
*
* Side effects:
* None.
*
*-------------------------------------------------------------------------
*/
-
+
void
-TclTransferResult(sourceInterp, result, targetInterp)
- Tcl_Interp *sourceInterp; /* Interp whose result and error information
- * should be moved to the target interp.
- * After moving result, this interp's result
+TclTransferResult(
+ Tcl_Interp *sourceInterp, /* Interp whose result and error information
+ * should be moved to the target interp.
+ * After moving result, this interp's result
* is reset. */
- int result; /* TCL_OK if just the result should be copied,
- * TCL_ERROR if both the result and error
+ int result, /* TCL_OK if just the result should be copied,
+ * TCL_ERROR if both the result and error
* information should be copied. */
- Tcl_Interp *targetInterp; /* Interp where result and error information
- * should be stored. If source and target
- * are the same, nothing is done. */
+ Tcl_Interp *targetInterp) /* Interp where result and error information
+ * should be stored. If source and target are
+ * the same, nothing is done. */
{
- Interp *iPtr;
- Tcl_Obj *objPtr;
+ Interp *tiPtr = (Interp *) targetInterp;
+ Interp *siPtr = (Interp *) sourceInterp;
if (sourceInterp == targetInterp) {
return;
}
- if (result == TCL_ERROR) {
+ if (result == TCL_OK && siPtr->returnOpts == NULL) {
/*
- * An error occurred, so transfer error information from the source
- * interpreter to the target interpreter. Setting the flags tells
- * the target interp that it has inherited a partial traceback
- * chain, not just a simple error message.
+ * Special optimization for the common case of normal command return
+ * code and no explicit return options.
*/
- iPtr = (Interp *) sourceInterp;
- if ((iPtr->flags & ERR_ALREADY_LOGGED) == 0) {
- Tcl_AddErrorInfo(sourceInterp, "");
- }
- iPtr->flags &= ~(ERR_ALREADY_LOGGED);
-
- Tcl_ResetResult(targetInterp);
-
- objPtr = Tcl_GetVar2Ex(sourceInterp, "errorInfo", NULL,
- TCL_GLOBAL_ONLY);
- if (objPtr) {
- Tcl_SetVar2Ex(targetInterp, "errorInfo", NULL, objPtr,
- TCL_GLOBAL_ONLY);
- ((Interp *) targetInterp)->flags |= ERR_IN_PROGRESS;
+ if (tiPtr->returnOpts) {
+ Tcl_DecrRefCount(tiPtr->returnOpts);
+ tiPtr->returnOpts = NULL;
}
-
- objPtr = Tcl_GetVar2Ex(sourceInterp, "errorCode", NULL,
- TCL_GLOBAL_ONLY);
- if (objPtr) {
- Tcl_SetObjErrorCode(targetInterp, objPtr);
- }
-
+ } else {
+ Tcl_SetReturnOptions(targetInterp,
+ Tcl_GetReturnOptions(sourceInterp, result));
+ tiPtr->flags &= ~(ERR_ALREADY_LOGGED);
}
-
- ((Interp *) targetInterp)->returnCode = ((Interp *) sourceInterp)->returnCode;
Tcl_SetObjResult(targetInterp, Tcl_GetObjResult(sourceInterp));
Tcl_ResetResult(sourceInterp);
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclScan.c b/generic/tclScan.c
index b72bd88..d83c8c9 100644
--- a/generic/tclScan.c
+++ b/generic/tclScan.c
@@ -1,41 +1,31 @@
-/*
+/*
* tclScan.c --
*
* This file contains the implementation of the "scan" command.
*
* Copyright (c) 1998 by Scriptics Corporation.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-/*
- * For strtoll() and strtoull() declarations on some platforms...
- */
-#include "tclPort.h"
/*
* Flag values used by Tcl_ScanObjCmd.
*/
-#define SCAN_NOSKIP 0x1 /* Don't skip blanks. */
-#define SCAN_SUPPRESS 0x2 /* Suppress assignment. */
-#define SCAN_UNSIGNED 0x4 /* Read an unsigned value. */
-#define SCAN_WIDTH 0x8 /* A width value was supplied. */
-
-#define SCAN_SIGNOK 0x10 /* A +/- character is allowed. */
-#define SCAN_NODIGITS 0x20 /* No digits have been scanned. */
-#define SCAN_NOZERO 0x40 /* No zero digits have been scanned. */
-#define SCAN_XOK 0x80 /* An 'x' is allowed. */
-#define SCAN_PTOK 0x100 /* Decimal point is allowed. */
-#define SCAN_EXPOK 0x200 /* An exponent is allowed. */
+#define SCAN_NOSKIP 0x1 /* Don't skip blanks. */
+#define SCAN_SUPPRESS 0x2 /* Suppress assignment. */
+#define SCAN_UNSIGNED 0x4 /* Read an unsigned value. */
+#define SCAN_WIDTH 0x8 /* A width value was supplied. */
-#define SCAN_LONGER 0x400 /* Asked for a wide value. */
+#define SCAN_LONGER 0x400 /* Asked for a wide value. */
+#define SCAN_BIG 0x800 /* Asked for a bignum value. */
/*
- * The following structure contains the information associated with
- * a character set.
+ * The following structure contains the information associated with a
+ * character set.
*/
typedef struct CharSet {
@@ -53,20 +43,20 @@ typedef struct CharSet {
* Declarations for functions used only in this file.
*/
-static char * BuildCharSet _ANSI_ARGS_((CharSet *cset, char *format));
-static int CharInSet _ANSI_ARGS_((CharSet *cset, int ch));
-static void ReleaseCharSet _ANSI_ARGS_((CharSet *cset));
-static int ValidateFormat _ANSI_ARGS_((Tcl_Interp *interp, char *format,
- int numVars, int *totalVars));
+static char * BuildCharSet(CharSet *cset, char *format);
+static int CharInSet(CharSet *cset, int ch);
+static void ReleaseCharSet(CharSet *cset);
+static int ValidateFormat(Tcl_Interp *interp, char *format,
+ int numVars, int *totalVars);
/*
*----------------------------------------------------------------------
*
* BuildCharSet --
*
- * This function examines a character set format specification
- * and builds a CharSet containing the individual characters and
- * character ranges specified.
+ * This function examines a character set format specification and builds
+ * a CharSet containing the individual characters and character ranges
+ * specified.
*
* Results:
* Returns the next format position.
@@ -78,16 +68,16 @@ static int ValidateFormat _ANSI_ARGS_((Tcl_Interp *interp, char *format,
*/
static char *
-BuildCharSet(cset, format)
- CharSet *cset;
- char *format; /* Points to first char of set. */
+BuildCharSet(
+ CharSet *cset,
+ char *format) /* Points to first char of set. */
{
Tcl_UniChar ch, start;
int offset, nranges;
char *end;
memset(cset, 0, sizeof(CharSet));
-
+
offset = Tcl_UtfToUniChar(format, &ch);
if (ch == '^') {
cset->exclude = 1;
@@ -111,8 +101,8 @@ BuildCharSet(cset, format)
end += Tcl_UtfToUniChar(end, &ch);
}
- cset->chars = (Tcl_UniChar *) ckalloc(sizeof(Tcl_UniChar)
- * (end - format - 1));
+ cset->chars = (Tcl_UniChar *)
+ ckalloc(sizeof(Tcl_UniChar) * (end - format - 1));
if (nranges > 0) {
cset->ranges = (struct Range *) ckalloc(sizeof(struct Range)*nranges);
} else {
@@ -133,8 +123,8 @@ BuildCharSet(cset, format)
while (ch != ']') {
if (*format == '-') {
/*
- * This may be the first character of a range, so don't add
- * it yet.
+ * This may be the first character of a range, so don't add it
+ * yet.
*/
start = ch;
@@ -161,7 +151,7 @@ BuildCharSet(cset, format)
} else {
cset->ranges[cset->nranges].start = ch;
cset->ranges[cset->nranges].end = start;
- }
+ }
cset->nranges++;
}
} else {
@@ -189,13 +179,14 @@ BuildCharSet(cset, format)
*/
static int
-CharInSet(cset, c)
- CharSet *cset;
- int c; /* Character to test, passed as int because
- * of non-ANSI prototypes. */
+CharInSet(
+ CharSet *cset,
+ int c) /* Character to test, passed as int because of
+ * non-ANSI prototypes. */
{
Tcl_UniChar ch = (Tcl_UniChar) c;
int i, match = 0;
+
for (i = 0; i < cset->nchars; i++) {
if (cset->chars[i] == ch) {
match = 1;
@@ -204,14 +195,13 @@ CharInSet(cset, c)
}
if (!match) {
for (i = 0; i < cset->nranges; i++) {
- if ((cset->ranges[i].start <= ch)
- && (ch <= cset->ranges[i].end)) {
+ if ((cset->ranges[i].start <= ch) && (ch <= cset->ranges[i].end)) {
match = 1;
break;
}
}
}
- return (cset->exclude ? !match : match);
+ return (cset->exclude ? !match : match);
}
/*
@@ -231,8 +221,8 @@ CharInSet(cset, c)
*/
static void
-ReleaseCharSet(cset)
- CharSet *cset;
+ReleaseCharSet(
+ CharSet *cset)
{
ckfree((char *)cset->chars);
if (cset->ranges) {
@@ -245,8 +235,8 @@ ReleaseCharSet(cset)
*
* ValidateFormat --
*
- * Parse the format string and verify that it is properly formed
- * and that there are exactly enough variables on the command line.
+ * Parse the format string and verify that it is properly formed and that
+ * there are exactly enough variables on the command line.
*
* Results:
* A standard Tcl result.
@@ -258,33 +248,27 @@ ReleaseCharSet(cset)
*/
static int
-ValidateFormat(interp, format, numVars, totalSubs)
- Tcl_Interp *interp; /* Current interpreter. */
- char *format; /* The format string. */
- int numVars; /* The number of variables passed to the
- * scan command. */
- int *totalSubs; /* The number of variables that will be
+ValidateFormat(
+ Tcl_Interp *interp, /* Current interpreter. */
+ char *format, /* The format string. */
+ int numVars, /* The number of variables passed to the scan
+ * command. */
+ int *totalSubs) /* The number of variables that will be
* required. */
{
-#define STATIC_LIST_SIZE 16
int gotXpg, gotSequential, value, i, flags;
char *end;
Tcl_UniChar ch;
- int staticAssign[STATIC_LIST_SIZE];
- int *nassign = staticAssign;
- int objIndex, xpgSize, nspace = STATIC_LIST_SIZE;
+ int objIndex, xpgSize, nspace = numVars;
+ int *nassign = (int *) TclStackAlloc(interp, nspace * sizeof(int));
char buf[TCL_UTF_MAX+1];
/*
- * Initialize an array that records the number of times a variable
- * is assigned to by the format string. We use this to detect if
- * a variable is multiply assigned or left unassigned.
+ * Initialize an array that records the number of times a variable is
+ * assigned to by the format string. We use this to detect if a variable
+ * is multiply assigned or left unassigned.
*/
- if (numVars > nspace) {
- nassign = (int*)ckalloc(sizeof(int) * numVars);
- nspace = numVars;
- }
for (i = 0; i < nspace; i++) {
nassign[i] = 0;
}
@@ -309,14 +293,14 @@ ValidateFormat(interp, format, numVars, totalSubs)
goto xpgCheckDone;
}
- if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
+ if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
/*
- * Check for an XPG3-style %n$ specification. Note: there
- * must not be a mixture of XPG3 specs and non-XPG3 specs
- * in the same format string.
+ * Check for an XPG3-style %n$ specification. Note: there must
+ * not be a mixture of XPG3 specs and non-XPG3 specs in the same
+ * format string.
*/
- value = strtoul(format-1, &end, 10); /* INTL: "C" locale. */
+ value = strtoul(format-1, &end, 10); /* INTL: "C" locale. */
if (*end != '$') {
goto notXpg;
}
@@ -333,31 +317,31 @@ ValidateFormat(interp, format, numVars, totalSubs)
/*
* In the case where no vars are specified, the user can
* specify %9999$ legally, so we have to consider special
- * rules for growing the assign array. 'value' is
- * guaranteed to be > 0.
+ * rules for growing the assign array. 'value' is guaranteed
+ * to be > 0.
*/
xpgSize = (xpgSize > value) ? xpgSize : value;
}
goto xpgCheckDone;
}
- notXpg:
+ notXpg:
gotSequential = 1;
if (gotXpg) {
- mixedXPG:
+ mixedXPG:
Tcl_SetResult(interp,
"cannot mix \"%\" and \"%n$\" conversion specifiers",
TCL_STATIC);
goto error;
}
- xpgCheckDone:
+ xpgCheckDone:
/*
* Parse any width specifier.
*/
- if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
- value = strtoul(format-1, &format, 10); /* INTL: "C" locale. */
+ if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
+ value = strtoul(format-1, &format, 10); /* INTL: "C" locale. */
flags |= SCAN_WIDTH;
format += Tcl_UtfToUniChar(format, &ch);
}
@@ -368,6 +352,12 @@ ValidateFormat(interp, format, numVars, totalSubs)
switch (ch) {
case 'l':
+ if (*format == 'l') {
+ flags |= SCAN_BIG;
+ format += 1;
+ format += Tcl_UtfToUniChar(format, &ch);
+ break;
+ }
case 'L':
flags |= SCAN_LONGER;
case 'h':
@@ -383,104 +373,104 @@ ValidateFormat(interp, format, numVars, totalSubs)
*/
switch (ch) {
- case 'c':
- if (flags & SCAN_WIDTH) {
- Tcl_SetResult(interp,
- "field width may not be specified in %c conversion",
- TCL_STATIC);
- goto error;
- }
- /*
- * Fall through!
- */
- case 'n':
- case 's':
- if (flags & SCAN_LONGER) {
- invalidLonger:
- buf[Tcl_UniCharToUtf(ch, buf)] = '\0';
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "'l' modifier may not be specified in %", buf,
- " conversion", NULL);
- goto error;
- }
- /*
- * Fall through!
- */
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'i':
- case 'o':
- case 'u':
- case 'x':
- break;
- /*
- * Bracket terms need special checking
- */
- case '[':
- if (flags & SCAN_LONGER) {
- goto invalidLonger;
- }
+ case 'c':
+ if (flags & SCAN_WIDTH) {
+ Tcl_SetResult(interp,
+ "field width may not be specified in %c conversion",
+ TCL_STATIC);
+ goto error;
+ }
+ /*
+ * Fall through!
+ */
+ case 'n':
+ case 's':
+ if (flags & (SCAN_LONGER|SCAN_BIG)) {
+ invalidFieldSize:
+ buf[Tcl_UniCharToUtf(ch, buf)] = '\0';
+ Tcl_AppendResult(interp,
+ "field size modifier may not be specified in %", buf,
+ " conversion", NULL);
+ goto error;
+ }
+ /*
+ * Fall through!
+ */
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'i':
+ case 'o':
+ case 'x':
+ break;
+ case 'u':
+ if (flags & SCAN_BIG) {
+ Tcl_SetResult(interp,
+ "unsigned bignum scans are invalid", TCL_STATIC);
+ goto error;
+ }
+ break;
+ /*
+ * Bracket terms need special checking
+ */
+ case '[':
+ if (flags & (SCAN_LONGER|SCAN_BIG)) {
+ goto invalidFieldSize;
+ }
+ if (*format == '\0') {
+ goto badSet;
+ }
+ format += Tcl_UtfToUniChar(format, &ch);
+ if (ch == '^') {
if (*format == '\0') {
goto badSet;
}
format += Tcl_UtfToUniChar(format, &ch);
- if (ch == '^') {
- if (*format == '\0') {
- goto badSet;
- }
- format += Tcl_UtfToUniChar(format, &ch);
- }
- if (ch == ']') {
- if (*format == '\0') {
- goto badSet;
- }
- format += Tcl_UtfToUniChar(format, &ch);
+ }
+ if (ch == ']') {
+ if (*format == '\0') {
+ goto badSet;
}
- while (ch != ']') {
- if (*format == '\0') {
- goto badSet;
- }
- format += Tcl_UtfToUniChar(format, &ch);
+ format += Tcl_UtfToUniChar(format, &ch);
+ }
+ while (ch != ']') {
+ if (*format == '\0') {
+ goto badSet;
}
- break;
- badSet:
- Tcl_SetResult(interp, "unmatched [ in format string",
- TCL_STATIC);
- goto error;
- default:
+ format += Tcl_UtfToUniChar(format, &ch);
+ }
+ break;
+ badSet:
+ Tcl_SetResult(interp, "unmatched [ in format string",
+ TCL_STATIC);
+ goto error;
+ default:
{
char buf[TCL_UTF_MAX+1];
buf[Tcl_UniCharToUtf(ch, buf)] = '\0';
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "bad scan conversion character \"", buf, "\"", NULL);
+ Tcl_AppendResult(interp, "bad scan conversion character \"",
+ buf, "\"", NULL);
goto error;
}
}
if (!(flags & SCAN_SUPPRESS)) {
if (objIndex >= nspace) {
/*
- * Expand the nassign buffer. If we are using XPG specifiers,
- * make sure that we grow to a large enough size. xpgSize is
+ * Expand the nassign buffer. If we are using XPG specifiers,
+ * make sure that we grow to a large enough size. xpgSize is
* guaranteed to be at least one larger than objIndex.
*/
+
value = nspace;
if (xpgSize) {
nspace = xpgSize;
} else {
- nspace += STATIC_LIST_SIZE;
- }
- if (nassign == staticAssign) {
- nassign = (void *)ckalloc(nspace * sizeof(int));
- for (i = 0; i < STATIC_LIST_SIZE; ++i) {
- nassign[i] = staticAssign[i];
- }
- } else {
- nassign = (void *)ckrealloc((void *)nassign,
- nspace * sizeof(int));
+ nspace += 16; /* formerly STATIC_LIST_SIZE */
}
+ nassign = (int *) TclStackRealloc(interp, nassign,
+ nspace * sizeof(int));
for (i = value; i < nspace; i++) {
nassign[i] = 0;
}
@@ -506,39 +496,39 @@ ValidateFormat(interp, format, numVars, totalSubs)
}
for (i = 0; i < numVars; i++) {
if (nassign[i] > 1) {
- Tcl_SetResult(interp, "variable is assigned by multiple \"%n$\" conversion specifiers", TCL_STATIC);
+ Tcl_SetResult(interp,
+ "variable is assigned by multiple \"%n$\" conversion specifiers",
+ TCL_STATIC);
goto error;
} else if (!xpgSize && (nassign[i] == 0)) {
/*
- * If the space is empty, and xpgSize is 0 (means XPG wasn't
- * used, and/or numVars != 0), then too many vars were given
+ * If the space is empty, and xpgSize is 0 (means XPG wasn't used,
+ * and/or numVars != 0), then too many vars were given
*/
- Tcl_SetResult(interp, "variable is not assigned by any conversion specifiers", TCL_STATIC);
+
+ Tcl_SetResult(interp,
+ "variable is not assigned by any conversion specifiers",
+ TCL_STATIC);
goto error;
}
}
- if (nassign != staticAssign) {
- ckfree((char *)nassign);
- }
+ TclStackFree(interp, nassign);
return TCL_OK;
- badIndex:
+ badIndex:
if (gotXpg) {
Tcl_SetResult(interp, "\"%n$\" argument index out of range",
TCL_STATIC);
} else {
- Tcl_SetResult(interp,
+ Tcl_SetResult(interp,
"different numbers of variable names and field specifiers",
TCL_STATIC);
}
- error:
- if (nassign != staticAssign) {
- ckfree((char *)nassign);
- }
+ error:
+ TclStackFree(interp, nassign);
return TCL_ERROR;
-#undef STATIC_LIST_SIZE
}
/*
@@ -546,8 +536,8 @@ ValidateFormat(interp, format, numVars, totalSubs)
*
* Tcl_ScanObjCmd --
*
- * This procedure is invoked to process the "scan" Tcl command.
- * See the user documentation for details on what it does.
+ * This function is invoked to process the "scan" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -560,35 +550,29 @@ ValidateFormat(interp, format, numVars, totalSubs)
/* ARGSUSED */
int
-Tcl_ScanObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_ScanObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
char *format;
int numVars, nconversions, totalVars = -1;
int objIndex, offset, i, result, code;
long value;
- char *string, *end, *baseString;
+ CONST char *string, *end, *baseString;
char op = 0;
- int base = 0;
- int underflow = 0;
- size_t width;
- long (*fn)() = NULL;
-#ifndef TCL_WIDE_INT_IS_LONG
- Tcl_WideInt (*lfn)() = NULL;
+ int width, underflow = 0;
Tcl_WideInt wideValue;
-#endif
Tcl_UniChar ch, sch;
Tcl_Obj **objs = NULL, *objPtr = NULL;
int flags;
- char buf[513]; /* Temporary buffer to hold scanned
- * number strings before they are
- * passed to strtoul. */
+ char buf[513]; /* Temporary buffer to hold scanned number
+ * strings before they are passed to
+ * strtoul. */
if (objc < 3) {
- Tcl_WrongNumArgs(interp, 1, objv,
+ Tcl_WrongNumArgs(interp, 1, objv,
"string format ?varName varName ...?");
return TCL_ERROR;
}
@@ -599,7 +583,7 @@ Tcl_ScanObjCmd(dummy, interp, objc, objv)
/*
* Check for errors in the format string.
*/
-
+
if (ValidateFormat(interp, format, numVars, &totalVars) == TCL_ERROR) {
return TCL_ERROR;
}
@@ -619,14 +603,15 @@ Tcl_ScanObjCmd(dummy, interp, objc, objv)
baseString = string;
/*
- * Iterate over the format string filling in the result objects until
- * we reach the end of input, the end of the format string, or there
- * is a mismatch.
+ * Iterate over the format string filling in the result objects until we
+ * reach the end of input, the end of the format string, or there is a
+ * mismatch.
*/
objIndex = 0;
nconversions = 0;
while (*format != '\0') {
+ int parseFlag = TCL_PARSE_NO_WHITESPACE;
format += Tcl_UtfToUniChar(format, &ch);
flags = 0;
@@ -646,9 +631,9 @@ Tcl_ScanObjCmd(dummy, interp, objc, objv)
}
continue;
}
-
+
if (ch != '%') {
- literal:
+ literal:
if (*string == '\0') {
underflow = 1;
goto done;
@@ -666,17 +651,18 @@ Tcl_ScanObjCmd(dummy, interp, objc, objv)
}
/*
- * Check for assignment suppression ('*') or an XPG3-style
- * assignment ('%n$').
+ * Check for assignment suppression ('*') or an XPG3-style assignment
+ * ('%n$').
*/
if (ch == '*') {
flags |= SCAN_SUPPRESS;
format += Tcl_UtfToUniChar(format, &ch);
- } else if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
- value = strtoul(format-1, &end, 10); /* INTL: "C" locale. */
- if (*end == '$') {
- format = end+1;
+ } else if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
+ char *formatEnd;
+ value = strtoul(format-1, &formatEnd, 10);/* INTL: "C" locale. */
+ if (*formatEnd == '$') {
+ format = formatEnd+1;
format += Tcl_UtfToUniChar(format, &ch);
objIndex = (int) value - 1;
}
@@ -686,8 +672,8 @@ Tcl_ScanObjCmd(dummy, interp, objc, objv)
* Parse any width specifier.
*/
- if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
- width = strtoul(format-1, &format, 10); /* INTL: "C" locale. */
+ if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
+ width = (int) strtoul(format-1, &format, 10);/* INTL: "C" locale. */
format += Tcl_UtfToUniChar(format, &ch);
} else {
width = 0;
@@ -699,6 +685,12 @@ Tcl_ScanObjCmd(dummy, interp, objc, objv)
switch (ch) {
case 'l':
+ if (*format == 'l') {
+ flags |= SCAN_BIG;
+ format += 1;
+ format += Tcl_UtfToUniChar(format, &ch);
+ break;
+ }
case 'L':
flags |= SCAN_LONGER;
/*
@@ -713,90 +705,70 @@ Tcl_ScanObjCmd(dummy, interp, objc, objv)
*/
switch (ch) {
- case 'n':
- if (!(flags & SCAN_SUPPRESS)) {
- objPtr = Tcl_NewIntObj(string - baseString);
- Tcl_IncrRefCount(objPtr);
- objs[objIndex++] = objPtr;
- }
- nconversions++;
- continue;
+ case 'n':
+ if (!(flags & SCAN_SUPPRESS)) {
+ objPtr = Tcl_NewIntObj(string - baseString);
+ Tcl_IncrRefCount(objPtr);
+ objs[objIndex++] = objPtr;
+ }
+ nconversions++;
+ continue;
- case 'd':
- op = 'i';
- base = 10;
- fn = (long (*)())strtol;
-#ifndef TCL_WIDE_INT_IS_LONG
- lfn = (Tcl_WideInt (*)())strtoll;
-#endif
- break;
- case 'i':
- op = 'i';
- base = 0;
- fn = (long (*)())strtol;
-#ifndef TCL_WIDE_INT_IS_LONG
- lfn = (Tcl_WideInt (*)())strtoll;
-#endif
- break;
- case 'o':
- op = 'i';
- base = 8;
- fn = (long (*)())strtoul;
-#ifndef TCL_WIDE_INT_IS_LONG
- lfn = (Tcl_WideInt (*)())strtoull;
-#endif
- break;
- case 'x':
- op = 'i';
- base = 16;
- fn = (long (*)())strtoul;
-#ifndef TCL_WIDE_INT_IS_LONG
- lfn = (Tcl_WideInt (*)())strtoull;
-#endif
- break;
- case 'u':
- op = 'i';
- base = 10;
- flags |= SCAN_UNSIGNED;
- fn = (long (*)())strtoul;
-#ifndef TCL_WIDE_INT_IS_LONG
- lfn = (Tcl_WideInt (*)())strtoull;
-#endif
- break;
+ case 'd':
+ op = 'i';
+ parseFlag |= TCL_PARSE_DECIMAL_ONLY;
+ break;
+ case 'i':
+ op = 'i';
+ parseFlag |= TCL_PARSE_SCAN_PREFIXES;
+ break;
+ case 'o':
+ op = 'i';
+ parseFlag |= TCL_PARSE_OCTAL_ONLY | TCL_PARSE_SCAN_PREFIXES;
+ break;
+ case 'x':
+ op = 'i';
+ parseFlag |= TCL_PARSE_HEXADECIMAL_ONLY;
+ break;
+ case 'u':
+ op = 'i';
+ parseFlag |= TCL_PARSE_DECIMAL_ONLY;
+ flags |= SCAN_UNSIGNED;
+ break;
- case 'f':
- case 'e':
- case 'g':
- op = 'f';
- break;
+ case 'f':
+ case 'e':
+ case 'g':
+ op = 'f';
+ break;
- case 's':
- op = 's';
- break;
+ case 's':
+ op = 's';
+ break;
- case 'c':
- op = 'c';
- flags |= SCAN_NOSKIP;
- break;
- case '[':
- op = '[';
- flags |= SCAN_NOSKIP;
- break;
+ case 'c':
+ op = 'c';
+ flags |= SCAN_NOSKIP;
+ break;
+ case '[':
+ op = '[';
+ flags |= SCAN_NOSKIP;
+ break;
}
/*
- * At this point, we will need additional characters from the
- * string to proceed.
+ * At this point, we will need additional characters from the string
+ * to proceed.
*/
if (*string == '\0') {
underflow = 1;
goto done;
}
-
+
/*
- * Skip any leading whitespace at the beginning of a field unless
- * the format suppresses this behavior.
+ * Skip any leading whitespace at the beginning of a field unless the
+ * format suppresses this behavior.
*/
if (!(flags & SCAN_NOSKIP)) {
@@ -816,373 +788,217 @@ Tcl_ScanObjCmd(dummy, interp, objc, objv)
/*
* Perform the requested scanning operation.
*/
-
+
switch (op) {
- case 's':
- /*
- * Scan a string up to width characters or whitespace.
- */
+ case 's':
+ /*
+ * Scan a string up to width characters or whitespace.
+ */
- if (width == 0) {
- width = (size_t) ~0;
- }
- end = string;
- while (*end != '\0') {
- offset = Tcl_UtfToUniChar(end, &sch);
- if (Tcl_UniCharIsSpace(sch)) {
- break;
- }
- end += offset;
- if (--width == 0) {
- break;
- }
+ if (width == 0) {
+ width = ~0;
+ }
+ end = string;
+ while (*end != '\0') {
+ offset = Tcl_UtfToUniChar(end, &sch);
+ if (Tcl_UniCharIsSpace(sch)) {
+ break;
}
- if (!(flags & SCAN_SUPPRESS)) {
- objPtr = Tcl_NewStringObj(string, end-string);
- Tcl_IncrRefCount(objPtr);
- objs[objIndex++] = objPtr;
+ end += offset;
+ if (--width == 0) {
+ break;
}
- string = end;
- break;
-
- case '[': {
- CharSet cset;
+ }
+ if (!(flags & SCAN_SUPPRESS)) {
+ objPtr = Tcl_NewStringObj(string, end-string);
+ Tcl_IncrRefCount(objPtr);
+ objs[objIndex++] = objPtr;
+ }
+ string = end;
+ break;
- if (width == 0) {
- width = (size_t) ~0;
- }
- end = string;
+ case '[': {
+ CharSet cset;
- format = BuildCharSet(&cset, format);
- while (*end != '\0') {
- offset = Tcl_UtfToUniChar(end, &sch);
- if (!CharInSet(&cset, (int)sch)) {
- break;
- }
- end += offset;
- if (--width == 0) {
- break;
- }
- }
- ReleaseCharSet(&cset);
+ if (width == 0) {
+ width = ~0;
+ }
+ end = string;
- if (string == end) {
- /*
- * Nothing matched the range, stop processing
- */
- goto done;
+ format = BuildCharSet(&cset, format);
+ while (*end != '\0') {
+ offset = Tcl_UtfToUniChar(end, &sch);
+ if (!CharInSet(&cset, (int)sch)) {
+ break;
}
- if (!(flags & SCAN_SUPPRESS)) {
- objPtr = Tcl_NewStringObj(string, end-string);
- Tcl_IncrRefCount(objPtr);
- objs[objIndex++] = objPtr;
+ end += offset;
+ if (--width == 0) {
+ break;
}
- string = end;
-
- break;
}
- case 'c':
- /*
- * Scan a single Unicode character.
- */
-
- string += Tcl_UtfToUniChar(string, &sch);
- if (!(flags & SCAN_SUPPRESS)) {
- objPtr = Tcl_NewIntObj((int)sch);
- Tcl_IncrRefCount(objPtr);
- objs[objIndex++] = objPtr;
- }
- break;
+ ReleaseCharSet(&cset);
- case 'i':
+ if (string == end) {
/*
- * Scan an unsigned or signed integer.
+ * Nothing matched the range, stop processing.
*/
+ goto done;
+ }
+ if (!(flags & SCAN_SUPPRESS)) {
+ objPtr = Tcl_NewStringObj(string, end-string);
+ Tcl_IncrRefCount(objPtr);
+ objs[objIndex++] = objPtr;
+ }
+ string = end;
- if ((width == 0) || (width > sizeof(buf) - 1)) {
- width = sizeof(buf) - 1;
- }
- flags |= SCAN_SIGNOK | SCAN_NODIGITS | SCAN_NOZERO;
- for (end = buf; width > 0; width--) {
- switch (*string) {
- /*
- * The 0 digit has special meaning at the beginning of
- * a number. If we are unsure of the base, it
- * indicates that we are in base 8 or base 16 (if it is
- * followed by an 'x').
- *
- * 8.1 - 8.3.4 incorrectly handled 0x... base-16
- * cases for %x by not reading the 0x as the
- * auto-prelude for base-16. [Bug #495213]
- */
- case '0':
- if (base == 0) {
- base = 8;
- flags |= SCAN_XOK;
- }
- if (base == 16) {
- flags |= SCAN_XOK;
- }
- if (flags & SCAN_NOZERO) {
- flags &= ~(SCAN_SIGNOK | SCAN_NODIGITS
- | SCAN_NOZERO);
- } else {
- flags &= ~(SCAN_SIGNOK | SCAN_XOK
- | SCAN_NODIGITS);
- }
- goto addToInt;
-
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7':
- if (base == 0) {
- base = 10;
- }
- flags &= ~(SCAN_SIGNOK | SCAN_XOK | SCAN_NODIGITS);
- goto addToInt;
-
- case '8': case '9':
- if (base == 0) {
- base = 10;
- }
- if (base <= 8) {
- break;
- }
- flags &= ~(SCAN_SIGNOK | SCAN_XOK | SCAN_NODIGITS);
- goto addToInt;
-
- case 'A': case 'B': case 'C':
- case 'D': case 'E': case 'F':
- case 'a': case 'b': case 'c':
- case 'd': case 'e': case 'f':
- if (base <= 10) {
- break;
- }
- flags &= ~(SCAN_SIGNOK | SCAN_XOK | SCAN_NODIGITS);
- goto addToInt;
-
- case '+': case '-':
- if (flags & SCAN_SIGNOK) {
- flags &= ~SCAN_SIGNOK;
- goto addToInt;
- }
- break;
-
- case 'x': case 'X':
- if ((flags & SCAN_XOK) && (end == buf+1)) {
- base = 16;
- flags &= ~SCAN_XOK;
- goto addToInt;
- }
- break;
- }
-
- /*
- * We got an illegal character so we are done accumulating.
- */
-
- break;
+ break;
+ }
+ case 'c':
+ /*
+ * Scan a single Unicode character.
+ */
- addToInt:
- /*
- * Add the character to the temporary buffer.
- */
+ string += Tcl_UtfToUniChar(string, &sch);
+ if (!(flags & SCAN_SUPPRESS)) {
+ objPtr = Tcl_NewIntObj((int)sch);
+ Tcl_IncrRefCount(objPtr);
+ objs[objIndex++] = objPtr;
+ }
+ break;
- *end++ = *string++;
- if (*string == '\0') {
- break;
+ case 'i':
+ /*
+ * Scan an unsigned or signed integer.
+ */
+ objPtr = Tcl_NewLongObj(0);
+ Tcl_IncrRefCount(objPtr);
+ if (width == 0) {
+ width = ~0;
+ }
+ if (TCL_OK != TclParseNumber(NULL, objPtr, NULL, string, width,
+ &end, TCL_PARSE_INTEGER_ONLY | parseFlag)) {
+ Tcl_DecrRefCount(objPtr);
+ if (width < 0) {
+ if (*end == '\0') {
+ underflow = 1;
}
- }
-
- /*
- * Check to see if we need to back up because we only got a
- * sign or a trailing x after a 0.
- */
-
- if (flags & SCAN_NODIGITS) {
- if (*string == '\0') {
+ } else {
+ if (end == string + width) {
underflow = 1;
}
- goto done;
- } else if (end[-1] == 'x' || end[-1] == 'X') {
- end--;
- string--;
}
-
-
- /*
- * Scan the value from the temporary buffer. If we are
- * returning a large unsigned value, we have to convert it back
- * to a string since Tcl only supports signed values.
- */
-
- if (!(flags & SCAN_SUPPRESS)) {
- *end = '\0';
-#ifndef TCL_WIDE_INT_IS_LONG
- if (flags & SCAN_LONGER) {
- wideValue = (Tcl_WideInt) (*lfn)(buf, NULL, base);
- if ((flags & SCAN_UNSIGNED) && (wideValue < 0)) {
- /* INTL: ISO digit */
- sprintf(buf, "%" TCL_LL_MODIFIER "u",
- (Tcl_WideUInt)wideValue);
- objPtr = Tcl_NewStringObj(buf, -1);
- } else {
- objPtr = Tcl_NewWideIntObj(wideValue);
- }
- } else {
-#endif /* !TCL_WIDE_INT_IS_LONG */
- value = (long) (*fn)(buf, NULL, base);
- if ((flags & SCAN_UNSIGNED) && (value < 0)) {
- sprintf(buf, "%lu", value); /* INTL: ISO digit */
- objPtr = Tcl_NewStringObj(buf, -1);
- } else if ((flags & SCAN_LONGER)
- || (unsigned long) value > UINT_MAX) {
- objPtr = Tcl_NewLongObj(value);
- } else {
- objPtr = Tcl_NewIntObj(value);
- }
-#ifndef TCL_WIDE_INT_IS_LONG
+ goto done;
+ }
+ string = end;
+ if (flags & SCAN_SUPPRESS) {
+ Tcl_DecrRefCount(objPtr);
+ break;
+ }
+ if (flags & SCAN_LONGER) {
+ if (Tcl_GetWideIntFromObj(NULL, objPtr, &wideValue) != TCL_OK) {
+ wideValue = ~(Tcl_WideUInt)0 >> 1; /* WIDE_MAX */
+ if (TclGetString(objPtr)[0] == '-') {
+ wideValue++; /* WIDE_MAX + 1 = WIDE_MIN */
}
-#endif
- Tcl_IncrRefCount(objPtr);
- objs[objIndex++] = objPtr;
}
-
- break;
-
- case 'f':
- /*
- * Scan a floating point number
- */
-
- if ((width == 0) || (width > sizeof(buf) - 1)) {
- width = sizeof(buf) - 1;
+ if ((flags & SCAN_UNSIGNED) && (wideValue < 0)) {
+ sprintf(buf, "%" TCL_LL_MODIFIER "u",
+ (Tcl_WideUInt)wideValue);
+ Tcl_SetStringObj(objPtr, buf, -1);
+ } else {
+ Tcl_SetWideIntObj(objPtr, wideValue);
}
- flags &= ~SCAN_LONGER;
- flags |= SCAN_SIGNOK | SCAN_NODIGITS | SCAN_PTOK | SCAN_EXPOK;
- for (end = buf; width > 0; width--) {
- switch (*string) {
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- case '8': case '9':
- flags &= ~(SCAN_SIGNOK | SCAN_NODIGITS);
- goto addToFloat;
- case '+': case '-':
- if (flags & SCAN_SIGNOK) {
- flags &= ~SCAN_SIGNOK;
- goto addToFloat;
- }
- break;
- case '.':
- if (flags & SCAN_PTOK) {
- flags &= ~(SCAN_SIGNOK | SCAN_PTOK);
- goto addToFloat;
- }
- break;
- case 'e': case 'E':
- /*
- * An exponent is not allowed until there has
- * been at least one digit.
- */
-
- if ((flags & (SCAN_NODIGITS | SCAN_EXPOK))
- == SCAN_EXPOK) {
- flags = (flags & ~(SCAN_EXPOK|SCAN_PTOK))
- | SCAN_SIGNOK | SCAN_NODIGITS;
- goto addToFloat;
- }
- break;
- }
-
- /*
- * We got an illegal character so we are done accumulating.
- */
-
- break;
-
- addToFloat:
- /*
- * Add the character to the temporary buffer.
- */
-
- *end++ = *string++;
- if (*string == '\0') {
- break;
+ } else if (!(flags & SCAN_BIG)) {
+ if (TclGetLongFromObj(NULL, objPtr, &value) != TCL_OK) {
+ if (TclGetString(objPtr)[0] == '-') {
+ value = LONG_MIN;
+ } else {
+ value = LONG_MAX;
}
}
+ if ((flags & SCAN_UNSIGNED) && (value < 0)) {
+ sprintf(buf, "%lu", value); /* INTL: ISO digit */
+ Tcl_SetStringObj(objPtr, buf, -1);
+ } else {
+ Tcl_SetLongObj(objPtr, value);
+ }
+ }
+ objs[objIndex++] = objPtr;
+ break;
- /*
- * Check to see if we need to back up because we saw a
- * trailing 'e' or sign.
- */
+ case 'f':
+ /*
+ * Scan a floating point number
+ */
- if (flags & SCAN_NODIGITS) {
- if (flags & SCAN_EXPOK) {
- /*
- * There were no digits at all so scanning has
- * failed and we are done.
- */
- if (*string == '\0') {
- underflow = 1;
- }
- goto done;
+ objPtr = Tcl_NewDoubleObj(0.0);
+ Tcl_IncrRefCount(objPtr);
+ if (width == 0) {
+ width = ~0;
+ }
+ if (TCL_OK != TclParseNumber(NULL, objPtr, NULL, string, width,
+ &end, TCL_PARSE_DECIMAL_ONLY | TCL_PARSE_NO_WHITESPACE)) {
+ Tcl_DecrRefCount(objPtr);
+ if (width < 0) {
+ if (*end == '\0') {
+ underflow = 1;
}
-
- /*
- * We got a bad exponent ('e' and maybe a sign).
- */
-
- end--;
- string--;
- if (*end != 'e' && *end != 'E') {
- end--;
- string--;
+ } else {
+ if (end == string + width) {
+ underflow = 1;
}
}
-
- /*
- * Scan the value from the temporary buffer.
- */
-
- if (!(flags & SCAN_SUPPRESS)) {
- double dvalue;
- *end = '\0';
- dvalue = strtod(buf, NULL);
- objPtr = Tcl_NewDoubleObj(dvalue);
- Tcl_IncrRefCount(objPtr);
- objs[objIndex++] = objPtr;
+ goto done;
+ } else if (flags & SCAN_SUPPRESS) {
+ Tcl_DecrRefCount(objPtr);
+ string = end;
+ } else {
+ double dvalue;
+ if (Tcl_GetDoubleFromObj(NULL, objPtr, &dvalue) != TCL_OK) {
+#ifdef ACCEPT_NAN
+ if (objPtr->typePtr == &tclDoubleType) {
+ dvalue = objPtr->internalRep.doubleValue;
+ } else
+#endif
+ {
+ Tcl_DecrRefCount(objPtr);
+ goto done;
+ }
}
- break;
+ Tcl_SetDoubleObj(objPtr, dvalue);
+ objs[objIndex++] = objPtr;
+ string = end;
+ }
}
nconversions++;
}
- done:
+ done:
result = 0;
code = TCL_OK;
if (numVars) {
/*
- * In this case, variables were specified (classic scan)
+ * In this case, variables were specified (classic scan).
*/
+
for (i = 0; i < totalVars; i++) {
- if (objs[i] != NULL) {
- Tcl_Obj *tmpPtr;
-
- result++;
- tmpPtr = Tcl_ObjSetVar2(interp, objv[i+3], NULL, objs[i], 0);
- Tcl_DecrRefCount(objs[i]);
- if (tmpPtr == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "couldn't set variable \"",
- Tcl_GetString(objv[i+3]), "\"", (char *) NULL);
- code = TCL_ERROR;
- }
+ if (objs[i] == NULL) {
+ continue;
+ }
+ result++;
+ if (Tcl_ObjSetVar2(interp, objv[i+3], NULL, objs[i], 0) == NULL) {
+ Tcl_AppendResult(interp, "couldn't set variable \"",
+ TclGetString(objv[i+3]), "\"", NULL);
+ code = TCL_ERROR;
}
+ Tcl_DecrRefCount(objs[i]);
}
} else {
/*
* Here no vars were specified, we want a list returned (inline scan)
*/
+
objPtr = Tcl_NewObj();
for (i = 0; i < totalVars; i++) {
if (objs[i] != NULL) {
@@ -1190,9 +1006,10 @@ Tcl_ScanObjCmd(dummy, interp, objc, objv)
Tcl_DecrRefCount(objs[i]);
} else {
/*
- * More %-specifiers than matching chars, so we
- * just spit out empty strings for these
+ * More %-specifiers than matching chars, so we just spit out
+ * empty strings for these.
*/
+
Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewObj());
}
}
@@ -1218,3 +1035,11 @@ Tcl_ScanObjCmd(dummy, interp, objc, objv)
}
return code;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclStrToD.c b/generic/tclStrToD.c
new file mode 100755
index 0000000..aa78c51
--- /dev/null
+++ b/generic/tclStrToD.c
@@ -0,0 +1,5001 @@
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclStrToD.c --
+ *
+ * This file contains a collection of procedures for managing conversions
+ * to/from floating-point in Tcl. They include TclParseNumber, which
+ * parses numbers from strings; TclDoubleDigits, which formats numbers
+ * into strings of digits, and procedures for interconversion among
+ * 'double' and 'mp_int' types.
+ *
+ * Copyright (c) 2005 by Kevin B. Kenny. All rights reserved.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *----------------------------------------------------------------------
+ */
+
+#include "tclInt.h"
+#include "tommath.h"
+#include <math.h>
+
+/*
+ * Define KILL_OCTAL to suppress interpretation of numbers with leading zero
+ * as octal. (Ceterum censeo: numeros octonarios delendos esse.)
+ */
+
+#undef KILL_OCTAL
+
+/*
+ * This code supports (at least hypothetically), IBM, Cray, VAX and IEEE-754
+ * floating point; of these, only IEEE-754 can represent NaN. IEEE-754 can be
+ * uniquely determined by radix and by the widths of significand and exponent.
+ */
+
+#if (FLT_RADIX == 2) && (DBL_MANT_DIG == 53) && (DBL_MAX_EXP == 1024)
+# define IEEE_FLOATING_POINT
+#endif
+
+/*
+ * gcc on x86 needs access to rounding controls, because of a questionable
+ * feature where it retains intermediate results as IEEE 'long double' values
+ * somewhat unpredictably. It is tempting to include fpu_control.h, but that
+ * file exists only on Linux; it is missing on Cygwin and MinGW. Most gcc-isms
+ * and ix86-isms are factored out here.
+ */
+
+#if defined(__GNUC__) && defined(__i386)
+typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__)));
+#define _FPU_GETCW(cw) __asm__ __volatile__ ("fnstcw %0" : "=m" (*&cw))
+#define _FPU_SETCW(cw) __asm__ __volatile__ ("fldcw %0" : : "m" (*&cw))
+# define FPU_IEEE_ROUNDING 0x027f
+# define ADJUST_FPU_CONTROL_WORD
+#endif
+
+/* Sun ProC needs sunmath for rounding control on x86 like gcc above.
+ *
+ *
+ */
+#if defined(__sun) && defined(__i386) && !defined(__GNUC__)
+#include <sunmath.h>
+#endif
+
+/*
+ * MIPS floating-point units need special settings in control registers
+ * to use gradual underflow as we expect. This fix is for the MIPSpro
+ * compiler.
+ */
+#if defined(__sgi) && defined(_COMPILER_VERSION)
+#include <sys/fpu.h>
+#endif
+/*
+ * HP's PA_RISC architecture uses 7ff4000000000000 to represent a quiet NaN.
+ * Everyone else uses 7ff8000000000000. (Why, HP, why?)
+ */
+
+#ifdef __hppa
+# define NAN_START 0x7ff4
+# define NAN_MASK (((Tcl_WideUInt) 1) << 50)
+#else
+# define NAN_START 0x7ff8
+# define NAN_MASK (((Tcl_WideUInt) 1) << 51)
+#endif
+
+/*
+ * Constants used by this file (most of which are only ever calculated at
+ * runtime).
+ */
+
+/* Magic constants */
+
+#define LOG10_2 0.3010299956639812
+#define TWO_OVER_3LOG10 0.28952965460216784
+#define LOG10_3HALVES_PLUS_FUDGE 0.1760912590558
+
+/* Definitions of the parts of an IEEE754-format floating point number */
+
+#define SIGN_BIT 0x80000000
+ /* Mask for the sign bit in the first
+ * word of a double */
+#define EXP_MASK 0x7ff00000
+ /* Mask for the exponent field in the
+ * first word of a double */
+#define EXP_SHIFT 20
+ /* Shift count to make the exponent an
+ * integer */
+#define HIDDEN_BIT (((Tcl_WideUInt) 0x00100000) << 32)
+ /* Hidden 1 bit for the significand */
+#define HI_ORDER_SIG_MASK 0x000fffff
+ /* Mask for the high-order part of the
+ * significand in the first word of a
+ * double */
+#define SIG_MASK (((Tcl_WideUInt) HI_ORDER_SIG_MASK << 32) \
+ | 0xffffffff)
+ /* Mask for the 52-bit significand. */
+#define FP_PRECISION 53
+ /* Number of bits of significand plus the
+ * hidden bit */
+#define EXPONENT_BIAS 0x3ff
+ /* Bias of the exponent 0 */
+
+/* Derived quantities */
+
+#define TEN_PMAX 22
+ /* floor(FP_PRECISION*log(2)/log(5)) */
+#define QUICK_MAX 14
+ /* floor((FP_PRECISION-1)*log(2)/log(10)) - 1 */
+#define BLETCH 0x10
+ /* Highest power of two that is greater than
+ * DBL_MAX_10_EXP, divided by 16 */
+#define DIGIT_GROUP 8
+ /* floor(DIGIT_BIT*log(2)/log(10)) */
+
+/* Union used to dismantle floating point numbers. */
+
+typedef union Double {
+ struct {
+#ifdef WORDS_BIGENDIAN
+ int word0;
+ int word1;
+#else
+ int word1;
+ int word0;
+#endif
+ } w;
+ double d;
+ Tcl_WideUInt q;
+} Double;
+
+static int maxpow10_wide; /* The powers of ten that can be represented
+ * exactly as wide integers. */
+static Tcl_WideUInt *pow10_wide;
+#define MAXPOW 22
+static double pow10vals[MAXPOW+1];
+ /* The powers of ten that can be represented
+ * exactly as IEEE754 doubles. */
+static int mmaxpow; /* Largest power of ten that can be
+ * represented exactly in a 'double'. */
+static int log10_DIGIT_MAX; /* The number of decimal digits that fit in an
+ * mp_digit. */
+static int log2FLT_RADIX; /* Logarithm of the floating point radix. */
+static int mantBits; /* Number of bits in a double's significand */
+static mp_int pow5[9]; /* Table of powers of 5**(2**n), up to
+ * 5**256 */
+static double tiny = 0.0; /* The smallest representable double */
+static int maxDigits; /* The maximum number of digits to the left of
+ * the decimal point of a double. */
+static int minDigits; /* The maximum number of digits to the right
+ * of the decimal point in a double. */
+static int mantDIGIT; /* Number of mp_digit's needed to hold the
+ * significand of a double. */
+static const double pow_10_2_n[] = { /* Inexact higher powers of ten. */
+ 1.0,
+ 100.0,
+ 10000.0,
+ 1.0e+8,
+ 1.0e+16,
+ 1.0e+32,
+ 1.0e+64,
+ 1.0e+128,
+ 1.0e+256
+};
+
+static int n770_fp; /* Flag is 1 on Nokia N770 floating point.
+ * Nokia's floating point has the words
+ * reversed: if big-endian is 7654 3210,
+ * and little-endian is 0123 4567,
+ * then Nokia's FP is 4567 0123;
+ * little-endian within the 32-bit words
+ * but big-endian between them. */
+
+/* Table of powers of 5 that are small enough to fit in an mp_digit. */
+
+static const mp_digit dpow5[13] = {
+ 1, 5, 25, 125,
+ 625, 3125, 15625, 78125,
+ 390625, 1953125, 9765625, 48828125,
+ 244140625
+};
+
+/* Table of powers: pow5_13[n] = 5**(13*2**(n+1)) */
+static mp_int pow5_13[5]; /* Table of powers: 5**13, 5**26, 5**52,
+ * 5**104, 5**208 */
+static const double tens[] = {
+ 1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09,
+ 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+ 1e20, 1e21, 1e22
+};
+
+static const int itens [] = {
+ 1,
+ 10,
+ 100,
+ 1000,
+ 10000,
+ 100000,
+ 1000000,
+ 10000000,
+ 100000000
+};
+
+static const Tcl_WideUInt wtens[] = {
+ 1, 10, 100, 1000, 10000, 100000, 1000000,
+ (Tcl_WideUInt) 1000000*10, (Tcl_WideUInt) 1000000*100,
+ (Tcl_WideUInt) 1000000*1000, (Tcl_WideUInt) 1000000*10000,
+ (Tcl_WideUInt) 1000000*100000, (Tcl_WideUInt) 1000000*1000000,
+ (Tcl_WideUInt) 1000000*1000000*10, (Tcl_WideUInt) 1000000*1000000*100,
+ (Tcl_WideUInt) 1000000*1000000*1000,(Tcl_WideUInt) 1000000*1000000*10000
+
+};
+
+static const double bigtens[] = {
+ 1e016, 1e032, 1e064, 1e128, 1e256
+};
+#define N_BIGTENS 5
+
+static const int log2pow5[27] = {
+ 01, 3, 5, 7, 10, 12, 14, 17, 19, 21,
+ 24, 26, 28, 31, 33, 35, 38, 40, 42, 45,
+ 47, 49, 52, 54, 56, 59, 61
+};
+#define N_LOG2POW5 27
+
+static const Tcl_WideUInt wuipow5[27] = {
+ (Tcl_WideUInt) 1, /* 5**0 */
+ (Tcl_WideUInt) 5,
+ (Tcl_WideUInt) 25,
+ (Tcl_WideUInt) 125,
+ (Tcl_WideUInt) 625,
+ (Tcl_WideUInt) 3125, /* 5**5 */
+ (Tcl_WideUInt) 3125*5,
+ (Tcl_WideUInt) 3125*25,
+ (Tcl_WideUInt) 3125*125,
+ (Tcl_WideUInt) 3125*625,
+ (Tcl_WideUInt) 3125*3125, /* 5**10 */
+ (Tcl_WideUInt) 3125*3125*5,
+ (Tcl_WideUInt) 3125*3125*25,
+ (Tcl_WideUInt) 3125*3125*125,
+ (Tcl_WideUInt) 3125*3125*625,
+ (Tcl_WideUInt) 3125*3125*3125, /* 5**15 */
+ (Tcl_WideUInt) 3125*3125*3125*5,
+ (Tcl_WideUInt) 3125*3125*3125*25,
+ (Tcl_WideUInt) 3125*3125*3125*125,
+ (Tcl_WideUInt) 3125*3125*3125*625,
+ (Tcl_WideUInt) 3125*3125*3125*3125, /* 5**20 */
+ (Tcl_WideUInt) 3125*3125*3125*3125*5,
+ (Tcl_WideUInt) 3125*3125*3125*3125*25,
+ (Tcl_WideUInt) 3125*3125*3125*3125*125,
+ (Tcl_WideUInt) 3125*3125*3125*3125*625,
+ (Tcl_WideUInt) 3125*3125*3125*3125*3125, /* 5**25 */
+ (Tcl_WideUInt) 3125*3125*3125*3125*3125*5 /* 5**26 */
+};
+
+/*
+ * Static functions defined in this file.
+ */
+
+static int AccumulateDecimalDigit(unsigned, int,
+ Tcl_WideUInt *, mp_int *, int);
+static double MakeHighPrecisionDouble(int signum,
+ mp_int *significand, int nSigDigs, int exponent);
+static double MakeLowPrecisionDouble(int signum,
+ Tcl_WideUInt significand, int nSigDigs,
+ int exponent);
+static double MakeNaN(int signum, Tcl_WideUInt tag);
+static double RefineApproximation(double approx,
+ mp_int *exactSignificand, int exponent);
+static void MulPow5(mp_int*, unsigned, mp_int*);
+static int NormalizeRightward(Tcl_WideUInt*);
+static int RequiredPrecision(Tcl_WideUInt);
+static void DoubleToExpAndSig(double, Tcl_WideUInt*, int*, int*);
+static void TakeAbsoluteValue(Double*, int*);
+static char* FormatInfAndNaN(Double*, int*, char**);
+static char* FormatZero(int*, char**);
+static int ApproximateLog10(Tcl_WideUInt, int, int);
+static int BetterLog10(double, int, int*);
+static void ComputeScale(int, int, int*, int*, int*, int*);
+static void SetPrecisionLimits(int, int, int*, int*, int*, int*);
+static char* BumpUp(char*, char*, int*);
+static int AdjustRange(double*, int);
+static char* ShorteningQuickFormat(double, int, int, double,
+ char*, int*);
+static char* StrictQuickFormat(double, int, int, double,
+ char*, int*);
+static char* QuickConversion(double, int, int, int, int, int, int,
+ int*, char**);
+static void CastOutPowersOf2(int*, int*, int*);
+static char* ShorteningInt64Conversion(Double*, int, Tcl_WideUInt,
+ int, int, int, int, int, int, int, int, int,
+ int, int, int*, char**);
+static char* StrictInt64Conversion(Double*, int, Tcl_WideUInt,
+ int, int, int, int, int, int,
+ int, int, int*, char**);
+static int ShouldBankerRoundUpPowD(mp_int*, int, int);
+static int ShouldBankerRoundUpToNextPowD(mp_int*, mp_int*,
+ int, int, int, mp_int*);
+static char* ShorteningBignumConversionPowD(Double* dPtr,
+ int convType, Tcl_WideUInt bw, int b2, int b5,
+ int m2plus, int m2minus, int m5,
+ int sd, int k, int len,
+ int ilim, int ilim1, int* decpt,
+ char** endPtr);
+static char* StrictBignumConversionPowD(Double* dPtr, int convType,
+ Tcl_WideUInt bw, int b2, int b5,
+ int sd, int k, int len,
+ int ilim, int ilim1, int* decpt,
+ char** endPtr);
+static int ShouldBankerRoundUp(mp_int*, mp_int*, int);
+static int ShouldBankerRoundUpToNext(mp_int*, mp_int*, mp_int*,
+ int, int, mp_int*);
+static char* ShorteningBignumConversion(Double* dPtr, int convType,
+ Tcl_WideUInt bw, int b2,
+ int m2plus, int m2minus,
+ int s2, int s5, int k, int len,
+ int ilim, int ilim1, int* decpt,
+ char** endPtr);
+static char* StrictBignumConversion(Double* dPtr, int convType,
+ Tcl_WideUInt bw, int b2,
+ int s2, int s5, int k, int len,
+ int ilim, int ilim1, int* decpt,
+ char** endPtr);
+static double BignumToBiasedFrExp(mp_int *big, int *machexp);
+static double Pow10TimesFrExp(int exponent, double fraction,
+ int *machexp);
+static double SafeLdExp(double fraction, int exponent);
+static Tcl_WideUInt Nokia770Twiddle(Tcl_WideUInt w);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclParseNumber --
+ *
+ * Scans bytes, interpreted as characters in Tcl's internal encoding, and
+ * parses the longest prefix that is the string representation of a
+ * number in a format recognized by Tcl.
+ *
+ * The arguments bytes, numBytes, and objPtr are the inputs which
+ * determine the string to be parsed. If bytes is non-NULL, it points to
+ * the first byte to be scanned. If bytes is NULL, then objPtr must be
+ * non-NULL, and the string representation of objPtr will be scanned
+ * (generated first, if necessary). The numBytes argument determines the
+ * number of bytes to be scanned. If numBytes is negative, the first NUL
+ * byte encountered will terminate the scan. If numBytes is non-negative,
+ * then no more than numBytes bytes will be scanned.
+ *
+ * The argument flags is an input that controls the numeric formats
+ * recognized by the parser. The flag bits are:
+ *
+ * - TCL_PARSE_INTEGER_ONLY: accept only integer values; reject
+ * strings that denote floating point values (or accept only the
+ * leading portion of them that are integer values).
+ * - TCL_PARSE_SCAN_PREFIXES: ignore the prefixes 0b and 0o that are
+ * not part of the [scan] command's vocabulary. Use only in
+ * combination with TCL_PARSE_INTEGER_ONLY.
+ * - TCL_PARSE_OCTAL_ONLY: parse only in the octal format, whether
+ * or not a prefix is present that would lead to octal parsing.
+ * Use only in combination with TCL_PARSE_INTEGER_ONLY.
+ * - TCL_PARSE_HEXADECIMAL_ONLY: parse only in the hexadecimal format,
+ * whether or not a prefix is present that would lead to
+ * hexadecimal parsing. Use only in combination with
+ * TCL_PARSE_INTEGER_ONLY.
+ * - TCL_PARSE_DECIMAL_ONLY: parse only in the decimal format, no
+ * matter whether a 0 prefix would normally force a different
+ * base.
+ * - TCL_PARSE_NO_WHITESPACE: reject any leading/trailing whitespace
+ *
+ * The arguments interp and expected are inputs that control error
+ * message generation. If interp is NULL, no error message will be
+ * generated. If interp is non-NULL, then expected must also be non-NULL.
+ * When TCL_ERROR is returned, an error message will be left in the
+ * result of interp, and the expected argument will appear in the error
+ * message as the thing TclParseNumber expected, but failed to find in
+ * the string.
+ *
+ * The arguments objPtr and endPtrPtr as well as the return code are the
+ * outputs.
+ *
+ * When the parser cannot find any prefix of the string that matches a
+ * format it is looking for, TCL_ERROR is returned and an error message
+ * may be generated and returned as described above. The contents of
+ * objPtr will not be changed. If endPtrPtr is non-NULL, a pointer to the
+ * character in the string that terminated the scan will be written to
+ * *endPtrPtr.
+ *
+ * When the parser determines that the entire string matches a format it
+ * is looking for, TCL_OK is returned, and if objPtr is non-NULL, then
+ * the internal rep and Tcl_ObjType of objPtr are set to the "canonical"
+ * numeric value that matches the scanned string. If endPtrPtr is not
+ * NULL, a pointer to the end of the string will be written to *endPtrPtr
+ * (that is, either bytes+numBytes or a pointer to a terminating NUL
+ * byte).
+ *
+ * When the parser determines that a partial string matches a format it
+ * is looking for, the value of endPtrPtr determines what happens:
+ *
+ * - If endPtrPtr is NULL, then TCL_ERROR is returned, with error message
+ * generation as above.
+ *
+ * - If endPtrPtr is non-NULL, then TCL_OK is returned and objPtr
+ * internals are set as above. Also, a pointer to the first
+ * character following the parsed numeric string is written to
+ * *endPtrPtr.
+ *
+ * In some cases where the string being scanned is the string rep of
+ * objPtr, this routine can leave objPtr in an inconsistent state where
+ * its string rep and its internal rep do not agree. In these cases the
+ * internal rep will be in agreement with only some substring of the
+ * string rep. This might happen if the caller passes in a non-NULL bytes
+ * value that points somewhere into the string rep. It might happen if
+ * the caller passes in a numBytes value that limits the scan to only a
+ * prefix of the string rep. Or it might happen if a non-NULL value of
+ * endPtrPtr permits a TCL_OK return from only a partial string match. It
+ * is the responsibility of the caller to detect and correct such
+ * inconsistencies when they can and do arise.
+ *
+ * Results:
+ * Returns a standard Tcl result.
+ *
+ * Side effects:
+ * The string representaton of objPtr may be generated.
+ *
+ * The internal representation and Tcl_ObjType of objPtr may be changed.
+ * This may involve allocation and/or freeing of memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclParseNumber(
+ Tcl_Interp *interp, /* Used for error reporting. May be NULL. */
+ Tcl_Obj *objPtr, /* Object to receive the internal rep. */
+ const char *expected, /* Description of the type of number the
+ * caller expects to be able to parse
+ * ("integer", "boolean value", etc.). */
+ const char *bytes, /* Pointer to the start of the string to
+ * scan. */
+ int numBytes, /* Maximum number of bytes to scan, see
+ * above. */
+ const char **endPtrPtr, /* Place to store pointer to the character
+ * that terminated the scan. */
+ int flags) /* Flags governing the parse. */
+{
+ enum State {
+ INITIAL, SIGNUM, ZERO, ZERO_X,
+ ZERO_O, ZERO_B, BINARY,
+ HEXADECIMAL, OCTAL, BAD_OCTAL, DECIMAL,
+ LEADING_RADIX_POINT, FRACTION,
+ EXPONENT_START, EXPONENT_SIGNUM, EXPONENT,
+ sI, sIN, sINF, sINFI, sINFIN, sINFINI, sINFINIT, sINFINITY
+#ifdef IEEE_FLOATING_POINT
+ , sN, sNA, sNAN, sNANPAREN, sNANHEX, sNANFINISH
+#endif
+ } state = INITIAL;
+ enum State acceptState = INITIAL;
+
+ int signum = 0; /* Sign of the number being parsed */
+ Tcl_WideUInt significandWide = 0;
+ /* Significand of the number being parsed (if
+ * no overflow) */
+ mp_int significandBig; /* Significand of the number being parsed (if
+ * it overflows significandWide) */
+ int significandOverflow = 0;/* Flag==1 iff significandBig is used */
+ Tcl_WideUInt octalSignificandWide = 0;
+ /* Significand of an octal number; needed
+ * because we don't know whether a number with
+ * a leading zero is octal or decimal until
+ * we've scanned forward to a '.' or 'e' */
+ mp_int octalSignificandBig; /* Significand of octal number once
+ * octalSignificandWide overflows */
+ int octalSignificandOverflow = 0;
+ /* Flag==1 if octalSignificandBig is used */
+ int numSigDigs = 0; /* Number of significant digits in the decimal
+ * significand */
+ int numTrailZeros = 0; /* Number of trailing zeroes at the current
+ * point in the parse. */
+ int numDigitsAfterDp = 0; /* Number of digits scanned after the decimal
+ * point */
+ int exponentSignum = 0; /* Signum of the exponent of a floating point
+ * number */
+ long exponent = 0; /* Exponent of a floating point number */
+ const char *p; /* Pointer to next character to scan */
+ size_t len; /* Number of characters remaining after p */
+ const char *acceptPoint; /* Pointer to position after last character in
+ * an acceptable number */
+ size_t acceptLen; /* Number of characters following that
+ * point. */
+ int status = TCL_OK; /* Status to return to caller */
+ char d = 0; /* Last hexadecimal digit scanned; initialized
+ * to avoid a compiler warning. */
+ int shift = 0; /* Amount to shift when accumulating binary */
+ int explicitOctal = 0;
+
+#define ALL_BITS (~(Tcl_WideUInt)0)
+#define MOST_BITS (ALL_BITS >> 1)
+
+ /*
+ * Initialize bytes to start of the object's string rep if the caller
+ * didn't pass anything else.
+ */
+
+ if (bytes == NULL) {
+ bytes = TclGetString(objPtr);
+ }
+
+ p = bytes;
+ len = numBytes;
+ acceptPoint = p;
+ acceptLen = len;
+ while (1) {
+ char c = len ? *p : '\0';
+ switch (state) {
+
+ case INITIAL:
+ /*
+ * Initial state. Acceptable characters are +, -, digits, period,
+ * I, N, and whitespace.
+ */
+
+ if (TclIsSpaceProc(c)) {
+ if (flags & TCL_PARSE_NO_WHITESPACE) {
+ goto endgame;
+ }
+ break;
+ } else if (c == '+') {
+ state = SIGNUM;
+ break;
+ } else if (c == '-') {
+ signum = 1;
+ state = SIGNUM;
+ break;
+ }
+ /* FALLTHROUGH */
+
+ case SIGNUM:
+ /*
+ * Scanned a leading + or -. Acceptable characters are digits,
+ * period, I, and N.
+ */
+
+ if (c == '0') {
+ if (flags & TCL_PARSE_DECIMAL_ONLY) {
+ state = DECIMAL;
+ } else {
+ state = ZERO;
+ }
+ break;
+ } else if (flags & TCL_PARSE_HEXADECIMAL_ONLY) {
+ goto zerox;
+ } else if (flags & TCL_PARSE_OCTAL_ONLY) {
+ goto zeroo;
+ } else if (isdigit(UCHAR(c))) {
+ significandWide = c - '0';
+ numSigDigs = 1;
+ state = DECIMAL;
+ break;
+ } else if (flags & TCL_PARSE_INTEGER_ONLY) {
+ goto endgame;
+ } else if (c == '.') {
+ state = LEADING_RADIX_POINT;
+ break;
+ } else if (c == 'I' || c == 'i') {
+ state = sI;
+ break;
+#ifdef IEEE_FLOATING_POINT
+ } else if (c == 'N' || c == 'n') {
+ state = sN;
+ break;
+#endif
+ }
+ goto endgame;
+
+ case ZERO:
+ /*
+ * Scanned a leading zero (perhaps with a + or -). Acceptable
+ * inputs are digits, period, X, b, and E. If 8 or 9 is encountered,
+ * the number can't be octal. This state and the OCTAL state
+ * differ only in whether they recognize 'X' and 'b'.
+ */
+
+ acceptState = state;
+ acceptPoint = p;
+ acceptLen = len;
+ if (c == 'x' || c == 'X') {
+ state = ZERO_X;
+ break;
+ }
+ if (flags & TCL_PARSE_HEXADECIMAL_ONLY) {
+ goto zerox;
+ }
+ if (flags & TCL_PARSE_SCAN_PREFIXES) {
+ goto zeroo;
+ }
+ if (c == 'b' || c == 'B') {
+ state = ZERO_B;
+ break;
+ }
+ if (c == 'o' || c == 'O') {
+ explicitOctal = 1;
+ state = ZERO_O;
+ break;
+ }
+#ifdef KILL_OCTAL
+ goto decimal;
+#endif
+ /* FALLTHROUGH */
+
+ case OCTAL:
+ /*
+ * Scanned an optional + or -, followed by a string of octal
+ * digits. Acceptable inputs are more digits, period, or E. If 8
+ * or 9 is encountered, commit to floating point.
+ */
+
+ acceptState = state;
+ acceptPoint = p;
+ acceptLen = len;
+ /* FALLTHROUGH */
+ case ZERO_O:
+ zeroo:
+ if (c == '0') {
+ numTrailZeros++;
+ state = OCTAL;
+ break;
+ } else if (c >= '1' && c <= '7') {
+ if (objPtr != NULL) {
+ shift = 3 * (numTrailZeros + 1);
+ significandOverflow = AccumulateDecimalDigit(
+ (unsigned)(c-'0'), numTrailZeros,
+ &significandWide, &significandBig,
+ significandOverflow);
+
+ if (!octalSignificandOverflow) {
+ /*
+ * Shifting by more bits than are in the value being
+ * shifted is at least de facto nonportable. Check for
+ * too large shifts first.
+ */
+
+ if ((octalSignificandWide != 0)
+ && (((size_t)shift >=
+ CHAR_BIT*sizeof(Tcl_WideUInt))
+ || (octalSignificandWide >
+ (~(Tcl_WideUInt)0 >> shift)))) {
+ octalSignificandOverflow = 1;
+ TclBNInitBignumFromWideUInt(&octalSignificandBig,
+ octalSignificandWide);
+ }
+ }
+ if (!octalSignificandOverflow) {
+ octalSignificandWide =
+ (octalSignificandWide << shift) + (c - '0');
+ } else {
+ mp_mul_2d(&octalSignificandBig, shift,
+ &octalSignificandBig);
+ mp_add_d(&octalSignificandBig, (mp_digit)(c - '0'),
+ &octalSignificandBig);
+ }
+ }
+ if (numSigDigs != 0) {
+ numSigDigs += numTrailZeros+1;
+ } else {
+ numSigDigs = 1;
+ }
+ numTrailZeros = 0;
+ state = OCTAL;
+ break;
+ }
+ /* FALLTHROUGH */
+
+ case BAD_OCTAL:
+ if (explicitOctal) {
+ /*
+ * No forgiveness for bad digits in explicitly octal numbers.
+ */
+
+ goto endgame;
+ }
+ if (flags & TCL_PARSE_INTEGER_ONLY) {
+ /*
+ * No seeking floating point when parsing only integer.
+ */
+
+ goto endgame;
+ }
+#ifndef KILL_OCTAL
+
+ /*
+ * Scanned a number with a leading zero that contains an 8, 9,
+ * radix point or E. This is an invalid octal number, but might
+ * still be floating point.
+ */
+
+ if (c == '0') {
+ numTrailZeros++;
+ state = BAD_OCTAL;
+ break;
+ } else if (isdigit(UCHAR(c))) {
+ if (objPtr != NULL) {
+ significandOverflow = AccumulateDecimalDigit(
+ (unsigned)(c-'0'), numTrailZeros,
+ &significandWide, &significandBig,
+ significandOverflow);
+ }
+ if (numSigDigs != 0) {
+ numSigDigs += (numTrailZeros + 1);
+ } else {
+ numSigDigs = 1;
+ }
+ numTrailZeros = 0;
+ state = BAD_OCTAL;
+ break;
+ } else if (c == '.') {
+ state = FRACTION;
+ break;
+ } else if (c == 'E' || c == 'e') {
+ state = EXPONENT_START;
+ break;
+ }
+#endif
+ goto endgame;
+
+ /*
+ * Scanned 0x. If state is HEXADECIMAL, scanned at least one
+ * character following the 0x. The only acceptable inputs are
+ * hexadecimal digits.
+ */
+
+ case HEXADECIMAL:
+ acceptState = state;
+ acceptPoint = p;
+ acceptLen = len;
+ /* FALLTHROUGH */
+
+ case ZERO_X:
+ zerox:
+ if (c == '0') {
+ numTrailZeros++;
+ state = HEXADECIMAL;
+ break;
+ } else if (isdigit(UCHAR(c))) {
+ d = (c-'0');
+ } else if (c >= 'A' && c <= 'F') {
+ d = (c-'A'+10);
+ } else if (c >= 'a' && c <= 'f') {
+ d = (c-'a'+10);
+ } else {
+ goto endgame;
+ }
+ if (objPtr != NULL) {
+ shift = 4 * (numTrailZeros + 1);
+ if (!significandOverflow) {
+ /*
+ * Shifting by more bits than are in the value being
+ * shifted is at least de facto nonportable. Check for too
+ * large shifts first.
+ */
+
+ if (significandWide != 0 &&
+ ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
+ significandWide > (~(Tcl_WideUInt)0 >> shift))) {
+ significandOverflow = 1;
+ TclBNInitBignumFromWideUInt(&significandBig,
+ significandWide);
+ }
+ }
+ if (!significandOverflow) {
+ significandWide = (significandWide << shift) + d;
+ } else {
+ mp_mul_2d(&significandBig, shift, &significandBig);
+ mp_add_d(&significandBig, (mp_digit) d, &significandBig);
+ }
+ }
+ numTrailZeros = 0;
+ state = HEXADECIMAL;
+ break;
+
+ case BINARY:
+ acceptState = state;
+ acceptPoint = p;
+ acceptLen = len;
+ case ZERO_B:
+ if (c == '0') {
+ numTrailZeros++;
+ state = BINARY;
+ break;
+ } else if (c != '1') {
+ goto endgame;
+ }
+ if (objPtr != NULL) {
+ shift = numTrailZeros + 1;
+ if (!significandOverflow) {
+ /*
+ * Shifting by more bits than are in the value being
+ * shifted is at least de facto nonportable. Check for too
+ * large shifts first.
+ */
+
+ if (significandWide != 0 &&
+ ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
+ significandWide > (~(Tcl_WideUInt)0 >> shift))) {
+ significandOverflow = 1;
+ TclBNInitBignumFromWideUInt(&significandBig,
+ significandWide);
+ }
+ }
+ if (!significandOverflow) {
+ significandWide = (significandWide << shift) + 1;
+ } else {
+ mp_mul_2d(&significandBig, shift, &significandBig);
+ mp_add_d(&significandBig, (mp_digit) 1, &significandBig);
+ }
+ }
+ numTrailZeros = 0;
+ state = BINARY;
+ break;
+
+ case DECIMAL:
+ /*
+ * Scanned an optional + or - followed by a string of decimal
+ * digits.
+ */
+
+#ifdef KILL_OCTAL
+ decimal:
+#endif
+ acceptState = state;
+ acceptPoint = p;
+ acceptLen = len;
+ if (c == '0') {
+ numTrailZeros++;
+ state = DECIMAL;
+ break;
+ } else if (isdigit(UCHAR(c))) {
+ if (objPtr != NULL) {
+ significandOverflow = AccumulateDecimalDigit(
+ (unsigned)(c - '0'), numTrailZeros,
+ &significandWide, &significandBig,
+ significandOverflow);
+ }
+ numSigDigs += numTrailZeros+1;
+ numTrailZeros = 0;
+ state = DECIMAL;
+ break;
+ } else if (flags & TCL_PARSE_INTEGER_ONLY) {
+ goto endgame;
+ } else if (c == '.') {
+ state = FRACTION;
+ break;
+ } else if (c == 'E' || c == 'e') {
+ state = EXPONENT_START;
+ break;
+ }
+ goto endgame;
+
+ /*
+ * Found a decimal point. If no digits have yet been scanned, E is
+ * not allowed; otherwise, it introduces the exponent. If at least
+ * one digit has been found, we have a possible complete number.
+ */
+
+ case FRACTION:
+ acceptState = state;
+ acceptPoint = p;
+ acceptLen = len;
+ if (c == 'E' || c=='e') {
+ state = EXPONENT_START;
+ break;
+ }
+ /* FALLTHROUGH */
+
+ case LEADING_RADIX_POINT:
+ if (c == '0') {
+ numDigitsAfterDp++;
+ numTrailZeros++;
+ state = FRACTION;
+ break;
+ } else if (isdigit(UCHAR(c))) {
+ numDigitsAfterDp++;
+ if (objPtr != NULL) {
+ significandOverflow = AccumulateDecimalDigit(
+ (unsigned)(c-'0'), numTrailZeros,
+ &significandWide, &significandBig,
+ significandOverflow);
+ }
+ if (numSigDigs != 0) {
+ numSigDigs += numTrailZeros+1;
+ } else {
+ numSigDigs = 1;
+ }
+ numTrailZeros = 0;
+ state = FRACTION;
+ break;
+ }
+ goto endgame;
+
+ case EXPONENT_START:
+ /*
+ * Scanned the E at the start of an exponent. Make sure a legal
+ * character follows before using the C library strtol routine,
+ * which allows whitespace.
+ */
+
+ if (c == '+') {
+ state = EXPONENT_SIGNUM;
+ break;
+ } else if (c == '-') {
+ exponentSignum = 1;
+ state = EXPONENT_SIGNUM;
+ break;
+ }
+ /* FALLTHROUGH */
+
+ case EXPONENT_SIGNUM:
+ /*
+ * Found the E at the start of the exponent, followed by a sign
+ * character.
+ */
+
+ if (isdigit(UCHAR(c))) {
+ exponent = c - '0';
+ state = EXPONENT;
+ break;
+ }
+ goto endgame;
+
+ case EXPONENT:
+ /*
+ * Found an exponent with at least one digit. Accumulate it,
+ * making sure to hard-pin it to LONG_MAX on overflow.
+ */
+
+ acceptState = state;
+ acceptPoint = p;
+ acceptLen = len;
+ if (isdigit(UCHAR(c))) {
+ if (exponent < (LONG_MAX - 9) / 10) {
+ exponent = 10 * exponent + (c - '0');
+ } else {
+ exponent = LONG_MAX;
+ }
+ state = EXPONENT;
+ break;
+ }
+ goto endgame;
+
+ /*
+ * Parse out INFINITY by simply spelling it out. INF is accepted
+ * as an abbreviation; other prefices are not.
+ */
+
+ case sI:
+ if (c == 'n' || c == 'N') {
+ state = sIN;
+ break;
+ }
+ goto endgame;
+ case sIN:
+ if (c == 'f' || c == 'F') {
+ state = sINF;
+ break;
+ }
+ goto endgame;
+ case sINF:
+ acceptState = state;
+ acceptPoint = p;
+ acceptLen = len;
+ if (c == 'i' || c == 'I') {
+ state = sINFI;
+ break;
+ }
+ goto endgame;
+ case sINFI:
+ if (c == 'n' || c == 'N') {
+ state = sINFIN;
+ break;
+ }
+ goto endgame;
+ case sINFIN:
+ if (c == 'i' || c == 'I') {
+ state = sINFINI;
+ break;
+ }
+ goto endgame;
+ case sINFINI:
+ if (c == 't' || c == 'T') {
+ state = sINFINIT;
+ break;
+ }
+ goto endgame;
+ case sINFINIT:
+ if (c == 'y' || c == 'Y') {
+ state = sINFINITY;
+ break;
+ }
+ goto endgame;
+
+ /*
+ * Parse NaN's.
+ */
+#ifdef IEEE_FLOATING_POINT
+ case sN:
+ if (c == 'a' || c == 'A') {
+ state = sNA;
+ break;
+ }
+ goto endgame;
+ case sNA:
+ if (c == 'n' || c == 'N') {
+ state = sNAN;
+ break;
+ }
+ goto endgame;
+ case sNAN:
+ acceptState = state;
+ acceptPoint = p;
+ acceptLen = len;
+ if (c == '(') {
+ state = sNANPAREN;
+ break;
+ }
+ goto endgame;
+
+ /*
+ * Parse NaN(hexdigits)
+ */
+ case sNANHEX:
+ if (c == ')') {
+ state = sNANFINISH;
+ break;
+ }
+ /* FALLTHROUGH */
+ case sNANPAREN:
+ if (TclIsSpaceProc(c)) {
+ break;
+ }
+ if (numSigDigs < 13) {
+ if (c >= '0' && c <= '9') {
+ d = c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ d = 10 + c - 'a';
+ } else if (c >= 'A' && c <= 'F') {
+ d = 10 + c - 'A';
+ }
+ significandWide = (significandWide << 4) + d;
+ state = sNANHEX;
+ break;
+ }
+ goto endgame;
+ case sNANFINISH:
+#endif
+
+ case sINFINITY:
+ acceptState = state;
+ acceptPoint = p;
+ acceptLen = len;
+ goto endgame;
+ }
+ p++;
+ len--;
+ }
+
+ endgame:
+ if (acceptState == INITIAL) {
+ /*
+ * No numeric string at all found.
+ */
+
+ status = TCL_ERROR;
+ if (endPtrPtr != NULL) {
+ *endPtrPtr = p;
+ }
+ } else {
+ /*
+ * Back up to the last accepting state in the lexer.
+ */
+
+ p = acceptPoint;
+ len = acceptLen;
+ if (!(flags & TCL_PARSE_NO_WHITESPACE)) {
+ /*
+ * Accept trailing whitespace.
+ */
+
+ while (len != 0 && TclIsSpaceProc(*p)) {
+ p++;
+ len--;
+ }
+ }
+ if (endPtrPtr == NULL) {
+ if ((len != 0) && ((numBytes > 0) || (*p != '\0'))) {
+ status = TCL_ERROR;
+ }
+ } else {
+ *endPtrPtr = p;
+ }
+ }
+
+ /*
+ * Generate and store the appropriate internal rep.
+ */
+
+ if (status == TCL_OK && objPtr != NULL) {
+ TclFreeIntRep(objPtr);
+ switch (acceptState) {
+ case SIGNUM:
+ case BAD_OCTAL:
+ case ZERO_X:
+ case ZERO_O:
+ case ZERO_B:
+ case LEADING_RADIX_POINT:
+ case EXPONENT_START:
+ case EXPONENT_SIGNUM:
+ case sI:
+ case sIN:
+ case sINFI:
+ case sINFIN:
+ case sINFINI:
+ case sINFINIT:
+#ifdef IEEE_FLOATING_POINT
+ case sN:
+ case sNA:
+ case sNANPAREN:
+ case sNANHEX:
+ Tcl_Panic("TclParseNumber: bad acceptState %d parsing '%s'",
+ acceptState, bytes);
+#endif
+ case BINARY:
+ shift = numTrailZeros;
+ if (!significandOverflow && significandWide != 0 &&
+ ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
+ significandWide > (MOST_BITS + signum) >> shift)) {
+ significandOverflow = 1;
+ TclBNInitBignumFromWideUInt(&significandBig, significandWide);
+ }
+ if (shift) {
+ if (!significandOverflow) {
+ significandWide <<= shift;
+ } else {
+ mp_mul_2d(&significandBig, shift, &significandBig);
+ }
+ }
+ goto returnInteger;
+
+ case HEXADECIMAL:
+ /*
+ * Returning a hex integer. Final scaling step.
+ */
+
+ shift = 4 * numTrailZeros;
+ if (!significandOverflow && significandWide !=0 &&
+ ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
+ significandWide > (MOST_BITS + signum) >> shift)) {
+ significandOverflow = 1;
+ TclBNInitBignumFromWideUInt(&significandBig, significandWide);
+ }
+ if (shift) {
+ if (!significandOverflow) {
+ significandWide <<= shift;
+ } else {
+ mp_mul_2d(&significandBig, shift, &significandBig);
+ }
+ }
+ goto returnInteger;
+
+ case OCTAL:
+ /*
+ * Returning an octal integer. Final scaling step
+ */
+
+ shift = 3 * numTrailZeros;
+ if (!octalSignificandOverflow && octalSignificandWide != 0 &&
+ ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
+ octalSignificandWide > (MOST_BITS + signum) >> shift)) {
+ octalSignificandOverflow = 1;
+ TclBNInitBignumFromWideUInt(&octalSignificandBig,
+ octalSignificandWide);
+ }
+ if (shift) {
+ if (!octalSignificandOverflow) {
+ octalSignificandWide <<= shift;
+ } else {
+ mp_mul_2d(&octalSignificandBig, shift,
+ &octalSignificandBig);
+ }
+ }
+ if (!octalSignificandOverflow) {
+ if (octalSignificandWide >
+ (Tcl_WideUInt)(((~(unsigned long)0) >> 1) + signum)) {
+#ifndef NO_WIDE_TYPE
+ if (octalSignificandWide <= (MOST_BITS + signum)) {
+ objPtr->typePtr = &tclWideIntType;
+ if (signum) {
+ objPtr->internalRep.wideValue =
+ - (Tcl_WideInt) octalSignificandWide;
+ } else {
+ objPtr->internalRep.wideValue =
+ (Tcl_WideInt) octalSignificandWide;
+ }
+ break;
+ }
+#endif
+ TclBNInitBignumFromWideUInt(&octalSignificandBig,
+ octalSignificandWide);
+ octalSignificandOverflow = 1;
+ } else {
+ objPtr->typePtr = &tclIntType;
+ if (signum) {
+ objPtr->internalRep.longValue =
+ - (long) octalSignificandWide;
+ } else {
+ objPtr->internalRep.longValue =
+ (long) octalSignificandWide;
+ }
+ }
+ }
+ if (octalSignificandOverflow) {
+ if (signum) {
+ mp_neg(&octalSignificandBig, &octalSignificandBig);
+ }
+ TclSetBignumIntRep(objPtr, &octalSignificandBig);
+ }
+ break;
+
+ case ZERO:
+ case DECIMAL:
+ significandOverflow = AccumulateDecimalDigit(0, numTrailZeros-1,
+ &significandWide, &significandBig, significandOverflow);
+ if (!significandOverflow && (significandWide > MOST_BITS+signum)) {
+ significandOverflow = 1;
+ TclBNInitBignumFromWideUInt(&significandBig, significandWide);
+ }
+ returnInteger:
+ if (!significandOverflow) {
+ if (significandWide >
+ (Tcl_WideUInt)(((~(unsigned long)0) >> 1) + signum)) {
+#ifndef NO_WIDE_TYPE
+ if (significandWide <= MOST_BITS+signum) {
+ objPtr->typePtr = &tclWideIntType;
+ if (signum) {
+ objPtr->internalRep.wideValue =
+ - (Tcl_WideInt) significandWide;
+ } else {
+ objPtr->internalRep.wideValue =
+ (Tcl_WideInt) significandWide;
+ }
+ break;
+ }
+#endif
+ TclBNInitBignumFromWideUInt(&significandBig,
+ significandWide);
+ significandOverflow = 1;
+ } else {
+ objPtr->typePtr = &tclIntType;
+ if (signum) {
+ objPtr->internalRep.longValue =
+ - (long) significandWide;
+ } else {
+ objPtr->internalRep.longValue =
+ (long) significandWide;
+ }
+ }
+ }
+ if (significandOverflow) {
+ if (signum) {
+ mp_neg(&significandBig, &significandBig);
+ }
+ TclSetBignumIntRep(objPtr, &significandBig);
+ }
+ break;
+
+ case FRACTION:
+ case EXPONENT:
+
+ /*
+ * Here, we're parsing a floating-point number. 'significandWide'
+ * or 'significandBig' contains the exact significand, according
+ * to whether 'significandOverflow' is set. The desired floating
+ * point value is significand * 10**k, where
+ * k = numTrailZeros+exponent-numDigitsAfterDp.
+ */
+
+ objPtr->typePtr = &tclDoubleType;
+ if (exponentSignum) {
+ exponent = - exponent;
+ }
+ if (!significandOverflow) {
+ objPtr->internalRep.doubleValue = MakeLowPrecisionDouble(
+ signum, significandWide, numSigDigs,
+ (numTrailZeros + exponent - numDigitsAfterDp));
+ } else {
+ objPtr->internalRep.doubleValue = MakeHighPrecisionDouble(
+ signum, &significandBig, numSigDigs,
+ (numTrailZeros + exponent - numDigitsAfterDp));
+ }
+ break;
+
+ case sINF:
+ case sINFINITY:
+ if (signum) {
+ objPtr->internalRep.doubleValue = -HUGE_VAL;
+ } else {
+ objPtr->internalRep.doubleValue = HUGE_VAL;
+ }
+ objPtr->typePtr = &tclDoubleType;
+ break;
+
+#ifdef IEEE_FLOATING_POINT
+ case sNAN:
+ case sNANFINISH:
+ objPtr->internalRep.doubleValue = MakeNaN(signum, significandWide);
+ objPtr->typePtr = &tclDoubleType;
+ break;
+#endif
+ case INITIAL:
+ /* This case only to silence compiler warning */
+ Tcl_Panic("TclParseNumber: state INITIAL can't happen here");
+ }
+ }
+
+ /*
+ * Format an error message when an invalid number is encountered.
+ */
+
+ if (status != TCL_OK) {
+ if (interp != NULL) {
+ Tcl_Obj *msg;
+
+ TclNewLiteralStringObj(msg, "expected ");
+ Tcl_AppendToObj(msg, expected, -1);
+ Tcl_AppendToObj(msg, " but got \"", -1);
+ Tcl_AppendLimitedToObj(msg, bytes, numBytes, 50, "");
+ Tcl_AppendToObj(msg, "\"", -1);
+ if (state == BAD_OCTAL) {
+ Tcl_AppendToObj(msg, " (looks like invalid octal number)", -1);
+ }
+ Tcl_SetObjResult(interp, msg);
+ Tcl_SetErrorCode(interp, "TCL", "VALUE", "NUMBER", NULL);
+ }
+ }
+
+ /*
+ * Free memory.
+ */
+
+ if (octalSignificandOverflow) {
+ mp_clear(&octalSignificandBig);
+ }
+ if (significandOverflow) {
+ mp_clear(&significandBig);
+ }
+ return status;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AccumulateDecimalDigit --
+ *
+ * Consume a decimal digit in a number being scanned.
+ *
+ * Results:
+ * Returns 1 if the number has overflowed to a bignum, 0 if it still fits
+ * in a wide integer.
+ *
+ * Side effects:
+ * Updates either the wide or bignum representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+AccumulateDecimalDigit(
+ unsigned digit, /* Digit being scanned. */
+ int numZeros, /* Count of zero digits preceding the digit
+ * being scanned. */
+ Tcl_WideUInt *wideRepPtr, /* Representation of the partial number as a
+ * wide integer. */
+ mp_int *bignumRepPtr, /* Representation of the partial number as a
+ * bignum. */
+ int bignumFlag) /* Flag == 1 if the number overflowed previous
+ * to this digit. */
+{
+ int i, n;
+ Tcl_WideUInt w;
+
+ /*
+ * Try wide multiplication first
+ */
+
+ if (!bignumFlag) {
+ w = *wideRepPtr;
+ if (w == 0) {
+ /*
+ * There's no need to multiply if the multiplicand is zero.
+ */
+
+ *wideRepPtr = digit;
+ return 0;
+ } else if (numZeros >= maxpow10_wide
+ || w > ((~(Tcl_WideUInt)0)-digit)/pow10_wide[numZeros+1]) {
+ /*
+ * Wide multiplication will overflow. Expand the
+ * number to a bignum and fall through into the bignum case.
+ */
+
+ TclBNInitBignumFromWideUInt(bignumRepPtr, w);
+ } else {
+ /*
+ * Wide multiplication.
+ */
+ *wideRepPtr = w * pow10_wide[numZeros+1] + digit;
+ return 0;
+ }
+ }
+
+ /*
+ * Bignum multiplication.
+ */
+
+ if (numZeros < log10_DIGIT_MAX) {
+ /*
+ * Up to about 8 zeros - single digit multiplication.
+ */
+
+ mp_mul_d(bignumRepPtr, (mp_digit) pow10_wide[numZeros+1],
+ bignumRepPtr);
+ mp_add_d(bignumRepPtr, (mp_digit) digit, bignumRepPtr);
+ } else {
+ /*
+ * More than single digit multiplication. Multiply by the appropriate
+ * small powers of 5, and then shift. Large strings of zeroes are
+ * eaten 256 at a time; this is less efficient than it could be, but
+ * seems implausible. We presume that DIGIT_BIT is at least 27. The
+ * first multiplication, by up to 10**7, is done with a one-DIGIT
+ * multiply (this presumes that DIGIT_BIT >= 24).
+ */
+
+ n = numZeros + 1;
+ mp_mul_d(bignumRepPtr, (mp_digit) pow10_wide[n&0x7], bignumRepPtr);
+ for (i=3; i<=7; ++i) {
+ if (n & (1 << i)) {
+ mp_mul(bignumRepPtr, pow5+i, bignumRepPtr);
+ }
+ }
+ while (n >= 256) {
+ mp_mul(bignumRepPtr, pow5+8, bignumRepPtr);
+ n -= 256;
+ }
+ mp_mul_2d(bignumRepPtr, (int)(numZeros+1)&~0x7, bignumRepPtr);
+ mp_add_d(bignumRepPtr, (mp_digit) digit, bignumRepPtr);
+ }
+
+ return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MakeLowPrecisionDouble --
+ *
+ * Makes the double precision number, signum*significand*10**exponent.
+ *
+ * Results:
+ * Returns the constructed number.
+ *
+ * Common cases, where there are few enough digits that the number can be
+ * represented with at most roundoff, are handled specially here. If the
+ * number requires more than one rounded operation to compute, the code
+ * promotes the significand to a bignum and calls MakeHighPrecisionDouble
+ * to do it instead.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static double
+MakeLowPrecisionDouble(
+ int signum, /* 1 if the number is negative, 0 otherwise */
+ Tcl_WideUInt significand, /* Significand of the number */
+ int numSigDigs, /* Number of digits in the significand */
+ int exponent) /* Power of ten */
+{
+ double retval; /* Value of the number */
+ mp_int significandBig; /* Significand expressed as a bignum */
+
+ /*
+ * With gcc on x86, the floating point rounding mode is double-extended.
+ * This causes the result of double-precision calculations to be rounded
+ * twice: once to the precision of double-extended and then again to the
+ * precision of double. Double-rounding introduces gratuitous errors of 1
+ * ulp, so we need to change rounding mode to 53-bits.
+ */
+
+#if defined(__GNUC__) && defined(__i386)
+ fpu_control_t roundTo53Bits = 0x027f;
+ fpu_control_t oldRoundingMode;
+ _FPU_GETCW(oldRoundingMode);
+ _FPU_SETCW(roundTo53Bits);
+#endif
+#if defined(__sun) && defined(__i386) && !defined(__GNUC__)
+ ieee_flags("set","precision","double",NULL);
+#endif
+
+ /*
+ * Test for the easy cases.
+ */
+
+ if (numSigDigs <= DBL_DIG) {
+ if (exponent >= 0) {
+ if (exponent <= mmaxpow) {
+ /*
+ * The significand is an exact integer, and so is
+ * 10**exponent. The product will be correct to within 1/2 ulp
+ * without special handling.
+ */
+
+ retval = (double)(Tcl_WideInt)significand * pow10vals[exponent];
+ goto returnValue;
+ } else {
+ int diff = DBL_DIG - numSigDigs;
+ if (exponent-diff <= mmaxpow) {
+ /*
+ * 10**exponent is not an exact integer, but
+ * 10**(exponent-diff) is exact, and so is
+ * significand*10**diff, so we can still compute the value
+ * with only one roundoff.
+ */
+
+ volatile double factor =
+ (double)(Tcl_WideInt)significand * pow10vals[diff];
+ retval = factor * pow10vals[exponent-diff];
+ goto returnValue;
+ }
+ }
+ } else {
+ if (exponent >= -mmaxpow) {
+ /*
+ * 10**-exponent is an exact integer, and so is the
+ * significand. Compute the result by one division, again with
+ * only one rounding.
+ */
+
+ retval = (double)(Tcl_WideInt)significand / pow10vals[-exponent];
+ goto returnValue;
+ }
+ }
+ }
+
+ /*
+ * All the easy cases have failed. Promote ths significand to bignum and
+ * call MakeHighPrecisionDouble to do it the hard way.
+ */
+
+ TclBNInitBignumFromWideUInt(&significandBig, significand);
+ retval = MakeHighPrecisionDouble(0, &significandBig, numSigDigs,
+ exponent);
+ mp_clear(&significandBig);
+
+ /*
+ * Come here to return the computed value.
+ */
+
+ returnValue:
+ if (signum) {
+ retval = -retval;
+ }
+
+ /*
+ * On gcc on x86, restore the floating point mode word.
+ */
+
+#if defined(__GNUC__) && defined(__i386)
+ _FPU_SETCW(oldRoundingMode);
+#endif
+#if defined(__sun) && defined(__i386) && !defined(__GNUC__)
+ ieee_flags("clear","precision",NULL,NULL);
+#endif
+
+ return retval;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MakeHighPrecisionDouble --
+ *
+ * Makes the double precision number, signum*significand*10**exponent.
+ *
+ * Results:
+ * Returns the constructed number.
+ *
+ * MakeHighPrecisionDouble is used when arbitrary-precision arithmetic is
+ * needed to ensure correct rounding. It begins by calculating a
+ * low-precision approximation to the desired number, and then refines
+ * the answer in high precision.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static double
+MakeHighPrecisionDouble(
+ int signum, /* 1=negative, 0=nonnegative */
+ mp_int *significand, /* Exact significand of the number */
+ int numSigDigs, /* Number of significant digits */
+ int exponent) /* Power of 10 by which to multiply */
+{
+ double retval;
+ int machexp; /* Machine exponent of a power of 10 */
+
+ /*
+ * With gcc on x86, the floating point rounding mode is double-extended.
+ * This causes the result of double-precision calculations to be rounded
+ * twice: once to the precision of double-extended and then again to the
+ * precision of double. Double-rounding introduces gratuitous errors of 1
+ * ulp, so we need to change rounding mode to 53-bits.
+ */
+
+#if defined(__GNUC__) && defined(__i386)
+ fpu_control_t roundTo53Bits = 0x027f;
+ fpu_control_t oldRoundingMode;
+ _FPU_GETCW(oldRoundingMode);
+ _FPU_SETCW(roundTo53Bits);
+#endif
+#if defined(__sun) && defined(__i386) && !defined(__GNUC__)
+ ieee_flags("set","precision","double",NULL);
+#endif
+
+ /*
+ * Quick checks for over/underflow.
+ */
+
+ if (numSigDigs+exponent-1 > maxDigits) {
+ retval = HUGE_VAL;
+ goto returnValue;
+ }
+ if (numSigDigs+exponent-1 < minDigits) {
+ retval = 0;
+ goto returnValue;
+ }
+
+ /*
+ * Develop a first approximation to the significand. It is tempting simply
+ * to force bignum to double, but that will overflow on input numbers like
+ * 1.[string repeat 0 1000]1; while this is a not terribly likely
+ * scenario, we still have to deal with it. Use fraction and exponent
+ * instead. Once we have the significand, multiply by 10**exponent. Test
+ * for overflow. Convert back to a double, and test for underflow.
+ */
+
+ retval = BignumToBiasedFrExp(significand, &machexp);
+ retval = Pow10TimesFrExp(exponent, retval, &machexp);
+ if (machexp > DBL_MAX_EXP*log2FLT_RADIX) {
+ retval = HUGE_VAL;
+ goto returnValue;
+ }
+ retval = SafeLdExp(retval, machexp);
+ if (tiny == 0.0) {
+ tiny = SafeLdExp(1.0, DBL_MIN_EXP * log2FLT_RADIX - mantBits);
+ }
+ if (retval < tiny) {
+ retval = tiny;
+ }
+
+ /*
+ * Refine the result twice. (The second refinement should be necessary
+ * only if the best approximation is a power of 2 minus 1/2 ulp).
+ */
+
+ retval = RefineApproximation(retval, significand, exponent);
+ retval = RefineApproximation(retval, significand, exponent);
+
+ /*
+ * Come here to return the computed value.
+ */
+
+ returnValue:
+ if (signum) {
+ retval = -retval;
+ }
+
+ /*
+ * On gcc on x86, restore the floating point mode word.
+ */
+
+#if defined(__GNUC__) && defined(__i386)
+ _FPU_SETCW(oldRoundingMode);
+#endif
+#if defined(__sun) && defined(__i386) && !defined(__GNUC__)
+ ieee_flags("clear","precision",NULL,NULL);
+#endif
+ return retval;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MakeNaN --
+ *
+ * Makes a "Not a Number" given a set of bits to put in the tag bits
+ *
+ * Note that a signalling NaN is never returned.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef IEEE_FLOATING_POINT
+static double
+MakeNaN(
+ int signum, /* Sign bit (1=negative, 0=nonnegative */
+ Tcl_WideUInt tags) /* Tag bits to put in the NaN */
+{
+ union {
+ Tcl_WideUInt iv;
+ double dv;
+ } theNaN;
+
+ theNaN.iv = tags;
+ theNaN.iv &= (((Tcl_WideUInt) 1) << 51) - 1;
+ if (signum) {
+ theNaN.iv |= ((Tcl_WideUInt) (0x8000 | NAN_START)) << 48;
+ } else {
+ theNaN.iv |= ((Tcl_WideUInt) NAN_START) << 48;
+ }
+ if (n770_fp) {
+ theNaN.iv = Nokia770Twiddle(theNaN.iv);
+ }
+ return theNaN.dv;
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RefineApproximation --
+ *
+ * Given a poor approximation to a floating point number, returns a
+ * better one. (The better approximation is correct to within 1 ulp, and
+ * is entirely correct if the poor approximation is correct to 1 ulp.)
+ *
+ * Results:
+ * Returns the improved result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static double
+RefineApproximation(
+ double approxResult, /* Approximate result of conversion */
+ mp_int *exactSignificand, /* Integer significand */
+ int exponent) /* Power of 10 to multiply by significand */
+{
+ int M2, M5; /* Powers of 2 and of 5 needed to put the
+ * decimal and binary numbers over a common
+ * denominator. */
+ double significand; /* Sigificand of the binary number */
+ int binExponent; /* Exponent of the binary number */
+ int msb; /* Most significant bit position of an
+ * intermediate result */
+ int nDigits; /* Number of mp_digit's in an intermediate
+ * result */
+ mp_int twoMv; /* Approx binary value expressed as an exact
+ * integer scaled by the multiplier 2M */
+ mp_int twoMd; /* Exact decimal value expressed as an exact
+ * integer scaled by the multiplier 2M */
+ int scale; /* Scale factor for M */
+ int multiplier; /* Power of two to scale M */
+ double num, den; /* Numerator and denominator of the correction
+ * term */
+ double quot; /* Correction term */
+ double minincr; /* Lower bound on the absolute value of the
+ * correction term. */
+ int i;
+
+ /*
+ * The first approximation is always low. If we find that it's HUGE_VAL,
+ * we're done.
+ */
+
+ if (approxResult == HUGE_VAL) {
+ return approxResult;
+ }
+
+ /*
+ * Find a common denominator for the decimal and binary fractions. The
+ * common denominator will be 2**M2 + 5**M5.
+ */
+
+ significand = frexp(approxResult, &binExponent);
+ i = mantBits - binExponent;
+ if (i < 0) {
+ M2 = 0;
+ } else {
+ M2 = i;
+ }
+ if (exponent > 0) {
+ M5 = 0;
+ } else {
+ M5 = -exponent;
+ if ((M5-1) > M2) {
+ M2 = M5-1;
+ }
+ }
+
+ /*
+ * The floating point number is significand*2**binExponent. Compute the
+ * large integer significand*2**(binExponent+M2+1). The 2**-1 bit of the
+ * significand (the most significant) corresponds to the
+ * 2**(binExponent+M2 + 1) bit of 2*M2*v. Allocate enough digits to hold
+ * that quantity, then convert the significand to a large integer, scaled
+ * appropriately. Then multiply by the appropriate power of 5.
+ */
+
+ msb = binExponent + M2; /* 1008 */
+ nDigits = msb / DIGIT_BIT + 1;
+ mp_init_size(&twoMv, nDigits);
+ i = (msb % DIGIT_BIT + 1);
+ twoMv.used = nDigits;
+ significand *= SafeLdExp(1.0, i);
+ while (--nDigits >= 0) {
+ twoMv.dp[nDigits] = (mp_digit) significand;
+ significand -= (mp_digit) significand;
+ significand = SafeLdExp(significand, DIGIT_BIT);
+ }
+ for (i = 0; i <= 8; ++i) {
+ if (M5 & (1 << i)) {
+ mp_mul(&twoMv, pow5+i, &twoMv);
+ }
+ }
+
+ /*
+ * Collect the decimal significand as a high precision integer. The least
+ * significant bit corresponds to bit M2+exponent+1 so it will need to be
+ * shifted left by that many bits after being multiplied by
+ * 5**(M5+exponent).
+ */
+
+ mp_init_copy(&twoMd, exactSignificand);
+ for (i=0; i<=8; ++i) {
+ if ((M5+exponent) & (1 << i)) {
+ mp_mul(&twoMd, pow5+i, &twoMd);
+ }
+ }
+ mp_mul_2d(&twoMd, M2+exponent+1, &twoMd);
+ mp_sub(&twoMd, &twoMv, &twoMd);
+
+ /*
+ * The result, 2Mv-2Md, needs to be divided by 2M to yield a correction
+ * term. Because 2M may well overflow a double, we need to scale the
+ * denominator by a factor of 2**binExponent-mantBits
+ */
+
+ scale = binExponent - mantBits - 1;
+
+ mp_set(&twoMv, 1);
+ for (i=0; i<=8; ++i) {
+ if (M5 & (1 << i)) {
+ mp_mul(&twoMv, pow5+i, &twoMv);
+ }
+ }
+ multiplier = M2 + scale + 1;
+ if (multiplier > 0) {
+ mp_mul_2d(&twoMv, multiplier, &twoMv);
+ } else if (multiplier < 0) {
+ mp_div_2d(&twoMv, -multiplier, &twoMv, NULL);
+ }
+
+ /*
+ * If the result is less than unity, the error is less than 1/2 unit in
+ * the last place, so there's no correction to make.
+ */
+
+ if (mp_cmp_mag(&twoMd, &twoMv) == MP_LT) {
+ mp_clear(&twoMd);
+ mp_clear(&twoMv);
+ return approxResult;
+ }
+
+ /*
+ * Convert the numerator and denominator of the corrector term accurately
+ * to floating point numbers.
+ */
+
+ num = TclBignumToDouble(&twoMd);
+ den = TclBignumToDouble(&twoMv);
+
+ quot = SafeLdExp(num/den, scale);
+ minincr = SafeLdExp(1.0, binExponent-mantBits);
+
+ if (quot<0. && quot>-minincr) {
+ quot = -minincr;
+ } else if (quot>0. && quot<minincr) {
+ quot = minincr;
+ }
+
+ mp_clear(&twoMd);
+ mp_clear(&twoMv);
+
+ return approxResult + quot;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MultPow5 --
+ *
+ * Multiply a bignum by a power of 5.
+ *
+ * Side effects:
+ * Stores base*5**n in result
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static void
+MulPow5(mp_int* base, /* Number to multiply */
+ unsigned n, /* Power of 5 to multiply by */
+ mp_int* result) /* Place to store the result */
+{
+ mp_int* p = base;
+ int n13 = n / 13;
+ int r = n % 13;
+ if (r != 0) {
+ mp_mul_d(p, dpow5[r], result);
+ p = result;
+ }
+ r = 0;
+ while (n13 != 0) {
+ if (n13 & 1) {
+ mp_mul(p, pow5_13+r, result);
+ p = result;
+ }
+ n13 >>= 1;
+ ++r;
+ }
+ if (p != result) {
+ mp_copy(p, result);
+ }
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * NormalizeRightward --
+ *
+ * Shifts a number rightward until it is odd (that is, until the
+ * least significant bit is nonzero.
+ *
+ * Results:
+ * Returns the number of bit positions by which the number was shifted.
+ *
+ * Side effects:
+ * Shifts the number in place; *wPtr is replaced by the shifted number.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static int
+NormalizeRightward(Tcl_WideUInt* wPtr)
+ /* INOUT: Number to shift */
+{
+ int rv = 0;
+ Tcl_WideUInt w = *wPtr;
+ if (!(w & (Tcl_WideUInt) 0xffffffff)) {
+ w >>= 32; rv += 32;
+ }
+ if (!(w & (Tcl_WideUInt) 0xffff)) {
+ w >>= 16; rv += 16;
+ }
+ if (!(w & (Tcl_WideUInt) 0xff)) {
+ w >>= 8; rv += 8;
+ }
+ if (!(w & (Tcl_WideUInt) 0xf)) {
+ w >>= 4; rv += 4;
+ }
+ if (!(w & 0x3)) {
+ w >>= 2; rv += 2;
+ }
+ if (!(w & 0x1)) {
+ w >>= 1; ++rv;
+ }
+ *wPtr = w;
+ return rv;
+}
+
+/*
+ *-----------------------------------------------------------------------------0
+ *
+ * RequiredPrecision --
+ *
+ * Determines the number of bits needed to hold an intger.
+ *
+ * Results:
+ * Returns the position of the most significant bit (0 - 63).
+ * Returns 0 if the number is zero.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static int
+RequiredPrecision(Tcl_WideUInt w)
+ /* Number to interrogate */
+{
+ int rv;
+ unsigned long wi;
+ if (w & ((Tcl_WideUInt) 0xffffffff << 32)) {
+ wi = (unsigned long) (w >> 32); rv = 32;
+ } else {
+ wi = (unsigned long) w; rv = 0;
+ }
+ if (wi & 0xffff0000) {
+ wi >>= 16; rv += 16;
+ }
+ if (wi & 0xff00) {
+ wi >>= 8; rv += 8;
+ }
+ if (wi & 0xf0) {
+ wi >>= 4; rv += 4;
+ }
+ if (wi & 0xc) {
+ wi >>= 2; rv += 2;
+ }
+ if (wi & 0x2) {
+ wi >>= 1; ++rv;
+ }
+ if (wi & 0x1) {
+ ++rv;
+ }
+ return rv;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * DoubleToExpAndSig --
+ *
+ * Separates a 'double' into exponent and significand.
+ *
+ * Side effects:
+ * Stores the significand in '*significand' and the exponent in
+ * '*expon' so that dv == significand * 2.0**expon, and significand
+ * is odd. Also stores the position of the leftmost 1-bit in 'significand'
+ * in 'bits'.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static void
+DoubleToExpAndSig(double dv, /* Number to convert */
+ Tcl_WideUInt* significand,
+ /* OUTPUT: Significand of the number */
+ int* expon, /* OUTPUT: Exponent to multiply the number by */
+ int* bits) /* OUTPUT: Number of significant bits */
+{
+ Double d; /* Number being converted */
+ Tcl_WideUInt z; /* Significand under construction */
+ int de; /* Exponent of the number */
+ int k; /* Bit count */
+
+ d.d = dv;
+
+ /* Extract exponent and significand */
+
+ de = (d.w.word0 & EXP_MASK) >> EXP_SHIFT;
+ z = d.q & SIG_MASK;
+ if (de != 0) {
+ z |= HIDDEN_BIT;
+ k = NormalizeRightward(&z);
+ *bits = FP_PRECISION - k;
+ *expon = k + (de - EXPONENT_BIAS) - (FP_PRECISION-1);
+ } else {
+ k = NormalizeRightward(&z);
+ *expon = k + (de - EXPONENT_BIAS) - (FP_PRECISION-1) + 1;
+ *bits = RequiredPrecision(z);
+ }
+ *significand = z;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * TakeAbsoluteValue --
+ *
+ * Takes the absolute value of a 'double' including 0, Inf and NaN
+ *
+ * Side effects:
+ * The 'double' in *d is replaced with its absolute value. The
+ * signum is stored in 'sign': 1 for negative, 0 for nonnegative.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static void
+TakeAbsoluteValue(Double* d, /* Number to replace with absolute value */
+ int* sign) /* Place to put the signum */
+{
+ if (d->w.word0 & SIGN_BIT) {
+ *sign = 1;
+ d->w.word0 &= ~SIGN_BIT;
+ } else {
+ *sign = 0;
+ }
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * FormatInfAndNaN --
+ *
+ * Bailout for formatting infinities and Not-A-Number.
+ *
+ * Results:
+ * Returns one of the strings 'Infinity' and 'NaN'.
+ *
+ * Side effects:
+ * Stores 9999 in *decpt, and sets '*endPtr' to designate the
+ * terminating NUL byte of the string if 'endPtr' is not NULL.
+ *
+ * The string returned must be freed by the caller using 'ckfree'.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static char*
+FormatInfAndNaN(Double* d, /* Exceptional number to format */
+ int* decpt, /* Decimal point to set to a bogus value */
+ char** endPtr) /* Pointer to the end of the formatted data */
+{
+ char* retval;
+ *decpt = 9999;
+ if (!(d->w.word1) && !(d->w.word0 & HI_ORDER_SIG_MASK)) {
+ retval = ckalloc(9);
+ strcpy(retval, "Infinity");
+ if (endPtr) {
+ *endPtr = retval + 8;
+ }
+ } else {
+ retval = ckalloc(4);
+ strcpy(retval, "NaN");
+ if (endPtr) {
+ *endPtr = retval + 3;
+ }
+ }
+ return retval;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * FormatZero --
+ *
+ * Bailout to format a zero floating-point number.
+ *
+ * Results:
+ * Returns the constant string "0"
+ *
+ * Side effects:
+ * Stores 1 in '*decpt' and puts a pointer to the NUL byte terminating
+ * the string in '*endPtr' if 'endPtr' is not NULL.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static char*
+FormatZero(int* decpt, /* Location of the decimal point */
+ char** endPtr) /* Pointer to the end of the formatted data */
+{
+ char* retval = ckalloc(2);
+ strcpy(retval, "0");
+ if (endPtr) {
+ *endPtr = retval+1;
+ }
+ *decpt = 0;
+ return retval;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * ApproximateLog10 --
+ *
+ * Computes a two-term Taylor series approximation to the common
+ * log of a number, and computes the number's binary log.
+ *
+ * Results:
+ * Return an approximation to floor(log10(bw*2**be)) that is either
+ * exact or 1 too high.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static int
+ApproximateLog10(Tcl_WideUInt bw,
+ /* Integer significand of the number */
+ int be, /* Power of two to scale bw */
+ int bbits) /* Number of bits of precision in bw */
+{
+ int i; /* Log base 2 of the number */
+ int k; /* Floor(Log base 10 of the number) */
+ double ds; /* Mantissa of the number */
+ Double d2;
+
+ /*
+ * Compute i and d2 such that d = d2*2**i, and 1 < d2 < 2.
+ * Compute an approximation to log10(d),
+ * log10(d) ~ log10(2) * i + log10(1.5)
+ * + (significand-1.5)/(1.5 * log(10))
+ */
+
+ d2.q = bw << (FP_PRECISION - bbits) & SIG_MASK;
+ d2.w.word0 |= (EXPONENT_BIAS) << EXP_SHIFT;
+ i = be + bbits - 1;
+ ds = (d2.d - 1.5) * TWO_OVER_3LOG10
+ + LOG10_3HALVES_PLUS_FUDGE
+ + LOG10_2 * i;
+ k = (int) ds;
+ if (k > ds) {
+ --k;
+ }
+ return k;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * BetterLog10 --
+ *
+ * Improves the result of ApproximateLog10 for numbers in the range
+ * 1 .. 10**(TEN_PMAX)-1
+ *
+ * Side effects:
+ * Sets k_check to 0 if the new result is known to be exact, and to
+ * 1 if it may still be one too high.
+ *
+ * Results:
+ * Returns the improved approximation to log10(d)
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static int
+BetterLog10(double d, /* Original number to format */
+ int k, /* Characteristic(Log base 10) of the number */
+ int* k_check) /* Flag == 1 if k is inexact */
+{
+ /*
+ * Performance hack. If k is in the range 0..TEN_PMAX, then we can
+ * use a powers-of-ten table to check it.
+ */
+ if (k >= 0 && k <= TEN_PMAX) {
+ if (d < tens[k]) {
+ k--;
+ }
+ *k_check = 0;
+ } else {
+ *k_check = 1;
+ }
+ return k;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * ComputeScale --
+ *
+ * Prepares to format a floating-point number as decimal.
+ *
+ * Parameters:
+ * floor(log10*x) is k (or possibly k-1). floor(log2(x) is i.
+ * The significand of x requires bbits bits to represent.
+ *
+ * Results:
+ * Determines integers b2, b5, s2, s5 so that sig*2**b2*5**b5/2**s2*2**s5
+ * exactly represents the value of the x/10**k. This value will lie
+ * in the range [1 .. 10), and allows for computing successive digits
+ * by multiplying sig%10 by 10.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static void
+ComputeScale(int be, /* Exponent part of number: d = bw * 2**be */
+ int k, /* Characteristic of log10(number) */
+ int* b2, /* OUTPUT: Power of 2 in the numerator */
+ int* b5, /* OUTPUT: Power of 5 in the numerator */
+ int* s2, /* OUTPUT: Power of 2 in the denominator */
+ int* s5) /* OUTPUT: Power of 5 in the denominator */
+{
+
+ /*
+ * Scale numerator and denominator powers of 2 so that the
+ * input binary number is the ratio of integers
+ */
+ if (be <= 0) {
+ *b2 = 0;
+ *s2 = -be;
+ } else {
+ *b2 = be;
+ *s2 = 0;
+ }
+
+ /*
+ * Scale numerator and denominator so that the output decimal number
+ * is the ratio of integers
+ */
+ if (k >= 0) {
+ *b5 = 0;
+ *s5 = k;
+ *s2 += k;
+ } else {
+ *b2 -= k;
+ *b5 = -k;
+ *s5 = 0;
+ }
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * SetPrecisionLimits --
+ *
+ * Determines how many digits of significance should be computed
+ * (and, hence, how much memory need be allocated) for formatting a
+ * floating point number.
+ *
+ * Given that 'k' is floor(log10(x)):
+ * if 'shortest' format is used, there will be at most 18 digits in the result.
+ * if 'F' format is used, there will be at most 'ndigits' + k + 1 digits
+ * if 'E' format is used, there will be exactly 'ndigits' digits.
+ *
+ * Side effects:
+ * Adjusts '*ndigitsPtr' to have a valid value.
+ * Stores the maximum memory allocation needed in *iPtr.
+ * Sets '*iLimPtr' to the limiting number of digits to convert if k
+ * has been guessed correctly, and '*iLim1Ptr' to the limiting number
+ * of digits to convert if k has been guessed to be one too high.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static void
+SetPrecisionLimits(int convType,
+ /* Type of conversion:
+ * TCL_DD_SHORTEST
+ * TCL_DD_STEELE0
+ * TCL_DD_E_FMT
+ * TCL_DD_F_FMT */
+ int k, /* Floor(log10(number to convert)) */
+ int* ndigitsPtr,
+ /* IN/OUT: Number of digits requested
+ * (Will be adjusted if needed) */
+ int* iPtr, /* OUT: Maximum number of digits
+ * to return */
+ int *iLimPtr,/* OUT: Number of digits of significance
+ * if the bignum method is used.*/
+ int *iLim1Ptr)
+ /* OUT: Number of digits of significance
+ * if the quick method is used. */
+{
+ switch(convType) {
+ case TCL_DD_SHORTEST0:
+ case TCL_DD_STEELE0:
+ *iLimPtr = *iLim1Ptr = -1;
+ *iPtr = 18;
+ *ndigitsPtr = 0;
+ break;
+ case TCL_DD_E_FORMAT:
+ if (*ndigitsPtr <= 0) {
+ *ndigitsPtr = 1;
+ }
+ *iLimPtr = *iLim1Ptr = *iPtr = *ndigitsPtr;
+ break;
+ case TCL_DD_F_FORMAT:
+ *iPtr = *ndigitsPtr + k + 1;
+ *iLimPtr = *iPtr;
+ *iLim1Ptr = *iPtr - 1;
+ if (*iPtr <= 0) {
+ *iPtr = 1;
+ }
+ break;
+ default:
+ *iPtr = -1;
+ *iLimPtr = -1;
+ *iLim1Ptr = -1;
+ Tcl_Panic("impossible conversion type in TclDoubleDigits");
+ }
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * BumpUp --
+ *
+ * Increases a string of digits ending in a series of nines to
+ * designate the next higher number. xxxxb9999... -> xxxx(b+1)0000...
+ *
+ * Results:
+ * Returns a pointer to the end of the adjusted string.
+ *
+ * Side effects:
+ * In the case that the string consists solely of '999999', sets it
+ * to "1" and moves the decimal point (*kPtr) one place to the right.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+inline static char*
+BumpUp(char* s, /* Cursor pointing one past the end of the
+ * string */
+ char* retval, /* Start of the string of digits */
+ int* kPtr) /* Position of the decimal point */
+{
+ while (*--s == '9') {
+ if (s == retval) {
+ ++(*kPtr);
+ *s = '1';
+ return s+1;
+ }
+ }
+ ++*s;
+ ++s;
+ return s;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * AdjustRange --
+ *
+ * Rescales a 'double' in preparation for formatting it using the
+ * 'quick' double-to-string method.
+ *
+ * Results:
+ * Returns the precision that has been lost in the prescaling as
+ * a count of units in the least significant place.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static int
+AdjustRange(double* dPtr, /* INOUT: Number to adjust */
+ int k) /* IN: floor(log10(d)) */
+{
+ int ieps; /* Number of roundoff errors that have
+ * accumulated */
+ double d = *dPtr; /* Number to adjust */
+ double ds;
+ int i, j, j1;
+
+ ieps = 2;
+
+ if (k > 0) {
+ /*
+ * The number must be reduced to bring it into range.
+ */
+ ds = tens[k & 0xf];
+ j = k >> 4;
+ if (j & BLETCH) {
+ j &= (BLETCH-1);
+ d /= bigtens[N_BIGTENS - 1];
+ ieps++;
+ }
+ i = 0;
+ for (; j != 0; j>>=1) {
+ if (j & 1) {
+ ds *= bigtens[i];
+ ++ieps;
+ }
+ ++i;
+ }
+ d /= ds;
+ } else if ((j1 = -k) != 0) {
+ /*
+ * The number must be increased to bring it into range
+ */
+ d *= tens[j1 & 0xf];
+ i = 0;
+ for (j = j1>>4; j; j>>=1) {
+ if (j & 1) {
+ ieps++;
+ d *= bigtens[i];
+ }
+ ++i;
+ }
+ }
+
+ *dPtr = d;
+ return ieps;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * ShorteningQuickFormat --
+ *
+ * Returns a 'quick' format of a double precision number to a string
+ * of digits, preferring a shorter string of digits if the shorter
+ * string is still within 1/2 ulp of the number.
+ *
+ * Results:
+ * Returns the string of digits. Returns NULL if the 'quick' method
+ * fails and the bignum method must be used.
+ *
+ * Side effects:
+ * Stores the position of the decimal point at '*kPtr'.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static char*
+ShorteningQuickFormat(double d, /* Number to convert */
+ int k, /* floor(log10(d)) */
+ int ilim, /* Number of significant digits to return */
+ double eps,
+ /* Estimated roundoff error */
+ char* retval,
+ /* Buffer to receive the digit string */
+ int* kPtr)
+ /* Pointer to stash the position of
+ * the decimal point */
+{
+ char* s = retval; /* Cursor in the return value */
+ int digit; /* Current digit */
+ int i;
+
+ eps = 0.5 / tens[ilim-1] - eps;
+ i = 0;
+ for (;;) {
+ /* Convert a digit */
+
+ digit = (int) d;
+ d -= digit;
+ *s++ = '0' + digit;
+
+ /*
+ * Truncate the conversion if the string of digits is within
+ * 1/2 ulp of the actual value.
+ */
+
+ if (d < eps) {
+ *kPtr = k;
+ return s;
+ }
+ if ((1. - d) < eps) {
+ *kPtr = k;
+ return BumpUp(s, retval, kPtr);
+ }
+
+ /*
+ * Bail out if the conversion fails to converge to a sufficiently
+ * precise value
+ */
+
+ if (++i >= ilim) {
+ return NULL;
+ }
+
+ /*
+ * Bring the next digit to the integer part.
+ */
+
+ eps *= 10;
+ d *= 10.0;
+ }
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * StrictQuickFormat --
+ *
+ * Convert a double precision number of a string of a precise number
+ * of digits, using the 'quick' double precision method.
+ *
+ * Results:
+ * Returns the digit string, or NULL if the bignum method must be
+ * used to do the formatting.
+ *
+ * Side effects:
+ * Stores the position of the decimal point in '*kPtr'.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static char*
+StrictQuickFormat(double d, /* Number to convert */
+ int k, /* floor(log10(d)) */
+ int ilim, /* Number of significant digits to return */
+ double eps, /* Estimated roundoff error */
+ char* retval, /* Start of the digit string */
+ int* kPtr) /* Pointer to stash the position of
+ * the decimal point */
+{
+ char* s = retval; /* Cursor in the return value */
+ int digit; /* Current digit of the answer */
+ int i;
+
+ eps *= tens[ilim-1];
+ i = 1;
+ for (;;) {
+ /* Extract a digit */
+ digit = (int) d;
+ d -= digit;
+ if (d == 0.0) {
+ ilim = i;
+ }
+ *s++ = '0' + digit;
+
+ /*
+ * When the given digit count is reached, handle trailing strings
+ * of 0 and 9.
+ */
+ if (i == ilim) {
+ if (d > 0.5 + eps) {
+ *kPtr = k;
+ return BumpUp(s, retval, kPtr);
+ } else if (d < 0.5 - eps) {
+ while (*--s == '0') {
+ /* do nothing */
+ }
+ s++;
+ *kPtr = k;
+ return s;
+ } else {
+ return NULL;
+ }
+ }
+
+ /* Advance to the next digit */
+ ++i;
+ d *= 10.0;
+ }
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * QuickConversion --
+ *
+ * Converts a floating point number the 'quick' way, when only a limited
+ * number of digits is required and floating point arithmetic can
+ * therefore be used for the intermediate results.
+ *
+ * Results:
+ * Returns the converted string, or NULL if the bignum method must
+ * be used.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static char*
+QuickConversion(double e, /* Number to format */
+ int k, /* floor(log10(d)), approximately */
+ int k_check, /* 0 if k is exact, 1 if it may be too high */
+ int flags, /* Flags passed to dtoa:
+ * TCL_DD_SHORTEN_FLAG */
+ int len, /* Length of the return value */
+ int ilim, /* Number of digits to store */
+ int ilim1, /* Number of digits to store if we
+ * musguessed k */
+ int* decpt, /* OUTPUT: Location of the decimal point */
+ char** endPtr) /* OUTPUT: Pointer to the terminal null byte */
+{
+ int ieps; /* Number of 1-ulp roundoff errors that have
+ * accumulated in the calculation*/
+ Double eps; /* Estimated roundoff error */
+ char* retval; /* Returned string */
+ char* end; /* Pointer to the terminal null byte in the
+ * returned string */
+ volatile double d; /* Workaround for a bug in mingw gcc 3.4.5 */
+
+ /*
+ * Bring d into the range [1 .. 10)
+ */
+ ieps = AdjustRange(&e, k);
+ d = e;
+
+ /*
+ * If the guessed value of k didn't get d into range, adjust it
+ * by one. If that leaves us outside the range in which quick format
+ * is accurate, bail out.
+ */
+ if (k_check && d < 1. && ilim > 0) {
+ if (ilim1 < 0) {
+ return NULL;
+ }
+ ilim = ilim1;
+ --k;
+ d *= 10.0;
+ ++ieps;
+ }
+
+ /*
+ * Compute estimated roundoff error
+ */
+ eps.d = ieps * d + 7.;
+ eps.w.word0 -= (FP_PRECISION-1) << EXP_SHIFT;
+
+ /*
+ * Handle the peculiar case where the result has no significant
+ * digits.
+ */
+ retval = ckalloc(len + 1);
+ if (ilim == 0) {
+ d -= 5.;
+ if (d > eps.d) {
+ *retval = '1';
+ *decpt = k;
+ return retval;
+ } else if (d < -eps.d) {
+ *decpt = k;
+ return retval;
+ } else {
+ ckfree(retval);
+ return NULL;
+ }
+ }
+
+ /* Format the digit string */
+
+ if (flags & TCL_DD_SHORTEN_FLAG) {
+ end = ShorteningQuickFormat(d, k, ilim, eps.d, retval, decpt);
+ } else {
+ end = StrictQuickFormat(d, k, ilim, eps.d, retval, decpt);
+ }
+ if (end == NULL) {
+ ckfree(retval);
+ return NULL;
+ }
+ *end = '\0';
+ if (endPtr != NULL) {
+ *endPtr = end;
+ }
+ return retval;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * CastOutPowersOf2 --
+ *
+ * Adjust the factors 'b2', 'm2', and 's2' to cast out common powers
+ * of 2 from numerator and denominator in preparation for the 'bignum'
+ * method of floating point conversion.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static void
+CastOutPowersOf2(int* b2, /* Power of 2 to multiply the significand */
+ int* m2, /* Power of 2 to multiply 1/2 ulp */
+ int* s2) /* Power of 2 to multiply the common
+ * denominator */
+{
+ int i;
+ if (*m2 > 0 && *s2 > 0) { /* Find the smallest power of 2 in the
+ * numerator */
+ if (*m2 < *s2) { /* Find the lowest common denominatorr */
+ i = *m2;
+ } else {
+ i = *s2;
+ }
+ *b2 -= i; /* Reduce to lowest terms */
+ *m2 -= i;
+ *s2 -= i;
+ }
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * ShorteningInt64Conversion --
+ *
+ * Converts a double-precision number to the shortest string of
+ * digits that reconverts exactly to the given number, or to
+ * 'ilim' digits if that will yield a shorter result. The numerator and
+ * denominator in David Gay's conversion algorithm are known to fit
+ * in Tcl_WideUInt, giving considerably faster arithmetic than mp_int's.
+ *
+ * Results:
+ * Returns the string of significant decimal digits, in newly
+ * allocated memory
+ *
+ * Side effects:
+ * Stores the location of the decimal point in '*decpt' and the
+ * location of the terminal null byte in '*endPtr'.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static char*
+ShorteningInt64Conversion(Double* dPtr,
+ /* Original number to convert */
+ int convType,
+ /* Type of conversion (shortest, Steele,
+ E format, F format) */
+ Tcl_WideUInt bw,
+ /* Integer significand */
+ int b2, int b5,
+ /* Scale factor for the significand
+ * in the numerator */
+ int m2plus, int m2minus, int m5,
+ /* Scale factors for 1/2 ulp in
+ * the numerator (will be different if
+ * bw == 1 */
+ int s2, int s5,
+ /* Scale factors for the denominator */
+ int k,
+ /* Number of output digits before the decimal
+ * point */
+ int len,
+ /* Number of digits to allocate */
+ int ilim,
+ /* Number of digits to convert if b >= s */
+ int ilim1,
+ /* Number of digits to convert if b < s */
+ int* decpt,
+ /* OUTPUT: Position of the decimal point */
+ char** endPtr)
+ /* OUTPUT: Position of the terminal '\0'
+ * at the end of the returned string */
+{
+
+ char* retval = ckalloc(len + 1);
+ /* Output buffer */
+ Tcl_WideUInt b = (bw * wuipow5[b5]) << b2;
+ /* Numerator of the fraction being converted */
+ Tcl_WideUInt S = wuipow5[s5] << s2;
+ /* Denominator of the fraction being
+ * converted */
+ Tcl_WideUInt mplus, mminus; /* Ranges for testing whether the result
+ * is within roundoff of being exact */
+ int digit; /* Current output digit */
+ char* s = retval; /* Cursor in the output buffer */
+ int i; /* Current position in the output buffer */
+
+ /* Adjust if the logarithm was guessed wrong */
+
+ if (b < S) {
+ b = 10 * b;
+ ++m2plus; ++m2minus; ++m5;
+ ilim = ilim1;
+ --k;
+ }
+
+ /* Compute roundoff ranges */
+
+ mplus = wuipow5[m5] << m2plus;
+ mminus = wuipow5[m5] << m2minus;
+
+ /* Loop through the digits */
+
+ i = 1;
+ for (;;) {
+ digit = (int)(b / S);
+ if (digit > 10) {
+ Tcl_Panic("wrong digit!");
+ }
+ b = b % S;
+
+ /*
+ * Does the current digit put us on the low side of the exact value
+ * but within within roundoff of being exact?
+ */
+ if (b < mplus
+ || (b == mplus
+ && convType != TCL_DD_STEELE0
+ && (dPtr->w.word1 & 1) == 0)) {
+ /*
+ * Make sure we shouldn't be rounding *up* instead,
+ * in case the next number above is closer
+ */
+ if (2 * b > S
+ || (2 * b == S
+ && (digit & 1) != 0)) {
+ ++digit;
+ if (digit == 10) {
+ *s++ = '9';
+ s = BumpUp(s, retval, &k);
+ break;
+ }
+ }
+
+ /* Stash the current digit */
+
+ *s++ = '0' + digit;
+ break;
+ }
+
+ /*
+ * Does one plus the current digit put us within roundoff of the
+ * number?
+ */
+ if (b > S - mminus
+ || (b == S - mminus
+ && convType != TCL_DD_STEELE0
+ && (dPtr->w.word1 & 1) == 0)) {
+ if (digit == 9) {
+ *s++ = '9';
+ s = BumpUp(s, retval, &k);
+ break;
+ }
+ ++digit;
+ *s++ = '0' + digit;
+ break;
+ }
+
+ /*
+ * Have we converted all the requested digits?
+ */
+ *s++ = '0' + digit;
+ if (i == ilim) {
+ if (2*b > S
+ || (2*b == S && (digit & 1) != 0)) {
+ s = BumpUp(s, retval, &k);
+ }
+ break;
+ }
+
+ /* Advance to the next digit */
+
+ b = 10 * b;
+ mplus = 10 * mplus;
+ mminus = 10 * mminus;
+ ++i;
+ }
+
+ /*
+ * Endgame - store the location of the decimal point and the end of the
+ * string.
+ */
+ *s = '\0';
+ *decpt = k;
+ if (endPtr) {
+ *endPtr = s;
+ }
+ return retval;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * StrictInt64Conversion --
+ *
+ * Converts a double-precision number to a fixed-length string of
+ * 'ilim' digits that reconverts exactly to the given number.
+ * ('ilim' should be replaced with 'ilim1' in the case where
+ * log10(d) has been overestimated). The numerator and
+ * denominator in David Gay's conversion algorithm are known to fit
+ * in Tcl_WideUInt, giving considerably faster arithmetic than mp_int's.
+ *
+ * Results:
+ * Returns the string of significant decimal digits, in newly
+ * allocated memory
+ *
+ * Side effects:
+ * Stores the location of the decimal point in '*decpt' and the
+ * location of the terminal null byte in '*endPtr'.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static char*
+StrictInt64Conversion(Double* dPtr,
+ /* Original number to convert */
+ int convType,
+ /* Type of conversion (shortest, Steele,
+ E format, F format) */
+ Tcl_WideUInt bw,
+ /* Integer significand */
+ int b2, int b5,
+ /* Scale factor for the significand
+ * in the numerator */
+ int s2, int s5,
+ /* Scale factors for the denominator */
+ int k,
+ /* Number of output digits before the decimal
+ * point */
+ int len,
+ /* Number of digits to allocate */
+ int ilim,
+ /* Number of digits to convert if b >= s */
+ int ilim1,
+ /* Number of digits to convert if b < s */
+ int* decpt,
+ /* OUTPUT: Position of the decimal point */
+ char** endPtr)
+ /* OUTPUT: Position of the terminal '\0'
+ * at the end of the returned string */
+{
+
+ char* retval = ckalloc(len + 1);
+ /* Output buffer */
+ Tcl_WideUInt b = (bw * wuipow5[b5]) << b2;
+ /* Numerator of the fraction being converted */
+ Tcl_WideUInt S = wuipow5[s5] << s2;
+ /* Denominator of the fraction being
+ * converted */
+ int digit; /* Current output digit */
+ char* s = retval; /* Cursor in the output buffer */
+ int i; /* Current position in the output buffer */
+
+ /* Adjust if the logarithm was guessed wrong */
+
+ if (b < S) {
+ b = 10 * b;
+ ilim = ilim1;
+ --k;
+ }
+
+ /* Loop through the digits */
+
+ i = 1;
+ for (;;) {
+ digit = (int)(b / S);
+ if (digit > 10) {
+ Tcl_Panic("wrong digit!");
+ }
+ b = b % S;
+
+ /*
+ * Have we converted all the requested digits?
+ */
+ *s++ = '0' + digit;
+ if (i == ilim) {
+ if (2*b > S
+ || (2*b == S && (digit & 1) != 0)) {
+ s = BumpUp(s, retval, &k);
+ } else {
+ while (*--s == '0') {
+ /* do nothing */
+ }
+ ++s;
+ }
+ break;
+ }
+
+ /* Advance to the next digit */
+
+ b = 10 * b;
+ ++i;
+ }
+
+ /*
+ * Endgame - store the location of the decimal point and the end of the
+ * string.
+ */
+ *s = '\0';
+ *decpt = k;
+ if (endPtr) {
+ *endPtr = s;
+ }
+ return retval;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * ShouldBankerRoundUpPowD --
+ *
+ * Test whether bankers' rounding should round a digit up. Assumption
+ * is made that the denominator of the fraction being tested is
+ * a power of 2**DIGIT_BIT.
+ *
+ * Results:
+ * Returns 1 iff the fraction is more than 1/2, or if the fraction
+ * is exactly 1/2 and the digit is odd.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static int
+ShouldBankerRoundUpPowD(mp_int* b,
+ /* Numerator of the fraction */
+ int sd, /* Denominator is 2**(sd*DIGIT_BIT) */
+ int isodd)
+ /* 1 if the digit is odd, 0 if even */
+{
+ int i;
+ static const mp_digit topbit = (1<<(DIGIT_BIT-1));
+ if (b->used < sd || (b->dp[sd-1] & topbit) == 0) {
+ return 0;
+ }
+ if (b->dp[sd-1] != topbit) {
+ return 1;
+ }
+ for (i = sd-2; i >= 0; --i) {
+ if (b->dp[i] != 0) {
+ return 1;
+ }
+ }
+ return isodd;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * ShouldBankerRoundUpToNextPowD --
+ *
+ * Tests whether bankers' rounding will round down in the
+ * "denominator is a power of 2**MP_DIGIT" case.
+ *
+ * Results:
+ * Returns 1 if the rounding will be performed - which increases the
+ * digit by one - and 0 otherwise.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static int
+ShouldBankerRoundUpToNextPowD(mp_int* b,
+ /* Numerator of the fraction */
+ mp_int* m,
+ /* Numerator of the rounding tolerance */
+ int sd,
+ /* Common denominator is 2**(sd*DIGIT_BIT) */
+ int convType,
+ /* Conversion type: STEELE defeats
+ * round-to-even (Not sure why one wants to
+ * do this; I copied it from Gay) FIXME */
+ int isodd,
+ /* 1 if the integer significand is odd */
+ mp_int* temp)
+ /* Work area for the calculation */
+{
+ int i;
+
+ /*
+ * Compare B and S-m -- which is the same as comparing B+m and S --
+ * which we do by computing b+m and doing a bitwhack compare against
+ * 2**(DIGIT_BIT*sd)
+ */
+ mp_add(b, m, temp);
+ if (temp->used <= sd) { /* too few digits to be > S */
+ return 0;
+ }
+ if (temp->used > sd+1 || temp->dp[sd] > 1) {
+ /* >= 2s */
+ return 1;
+ }
+ for (i = sd-1; i >= 0; --i) {
+ /* check for ==s */
+ if (temp->dp[i] != 0) { /* > s */
+ return 1;
+ }
+ }
+ if (convType == TCL_DD_STEELE0) {
+ /* biased rounding */
+ return 0;
+ }
+ return isodd;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * ShorteningBignumConversionPowD --
+ *
+ * Converts a double-precision number to the shortest string of
+ * digits that reconverts exactly to the given number, or to
+ * 'ilim' digits if that will yield a shorter result. The denominator
+ * in David Gay's conversion algorithm is known to be a power of
+ * 2**DIGIT_BIT, and hence the division in the main loop may be replaced
+ * by a digit shift and mask.
+ *
+ * Results:
+ * Returns the string of significant decimal digits, in newly
+ * allocated memory
+ *
+ * Side effects:
+ * Stores the location of the decimal point in '*decpt' and the
+ * location of the terminal null byte in '*endPtr'.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static char*
+ShorteningBignumConversionPowD(Double* dPtr,
+ /* Original number to convert */
+ int convType,
+ /* Type of conversion (shortest, Steele,
+ E format, F format) */
+ Tcl_WideUInt bw,
+ /* Integer significand */
+ int b2, int b5,
+ /* Scale factor for the significand
+ * in the numerator */
+ int m2plus, int m2minus, int m5,
+ /* Scale factors for 1/2 ulp in
+ * the numerator (will be different if
+ * bw == 1 */
+ int sd,
+ /* Scale factor for the denominator */
+ int k,
+ /* Number of output digits before the decimal
+ * point */
+ int len,
+ /* Number of digits to allocate */
+ int ilim,
+ /* Number of digits to convert if b >= s */
+ int ilim1,
+ /* Number of digits to convert if b < s */
+ int* decpt,
+ /* OUTPUT: Position of the decimal point */
+ char** endPtr)
+ /* OUTPUT: Position of the terminal '\0'
+ * at the end of the returned string */
+{
+
+ char* retval = ckalloc(len + 1);
+ /* Output buffer */
+ mp_int b; /* Numerator of the fraction being converted */
+ mp_int mplus, mminus; /* Bounds for roundoff */
+ mp_digit digit; /* Current output digit */
+ char* s = retval; /* Cursor in the output buffer */
+ int i; /* Index in the output buffer */
+ mp_int temp;
+ int r1;
+
+ /*
+ * b = bw * 2**b2 * 5**b5
+ * mminus = 5**m5
+ */
+
+ TclBNInitBignumFromWideUInt(&b, bw);
+ mp_init_set_int(&mminus, 1);
+ MulPow5(&b, b5, &b);
+ mp_mul_2d(&b, b2, &b);
+
+ /* Adjust if the logarithm was guessed wrong */
+
+ if (b.used <= sd) {
+ mp_mul_d(&b, 10, &b);
+ ++m2plus; ++m2minus; ++m5;
+ ilim = ilim1;
+ --k;
+ }
+
+ /*
+ * mminus = 5**m5 * 2**m2minus
+ * mplus = 5**m5 * 2**m2plus
+ */
+
+ mp_mul_2d(&mminus, m2minus, &mminus);
+ MulPow5(&mminus, m5, &mminus);
+ if (m2plus > m2minus) {
+ mp_init_copy(&mplus, &mminus);
+ mp_mul_2d(&mplus, m2plus-m2minus, &mplus);
+ }
+ mp_init(&temp);
+
+ /* Loop through the digits. Do division and mod by s == 2**(sd*DIGIT_BIT)
+ * by mp_digit extraction */
+
+ i = 0;
+ for (;;) {
+ if (b.used <= sd) {
+ digit = 0;
+ } else {
+ digit = b.dp[sd];
+ if (b.used > sd+1 || digit >= 10) {
+ Tcl_Panic("wrong digit!");
+ }
+ --b.used; mp_clamp(&b);
+ }
+
+ /*
+ * Does the current digit put us on the low side of the exact value
+ * but within within roundoff of being exact?
+ */
+
+ r1 = mp_cmp_mag(&b, (m2plus > m2minus)? &mplus : &mminus);
+ if (r1 == MP_LT
+ || (r1 == MP_EQ
+ && convType != TCL_DD_STEELE0
+ && (dPtr->w.word1 & 1) == 0)) {
+ /*
+ * Make sure we shouldn't be rounding *up* instead,
+ * in case the next number above is closer
+ */
+ if (ShouldBankerRoundUpPowD(&b, sd, digit&1)) {
+ ++digit;
+ if (digit == 10) {
+ *s++ = '9';
+ s = BumpUp(s, retval, &k);
+ break;
+ }
+ }
+
+ /* Stash the last digit */
+
+ *s++ = '0' + digit;
+ break;
+ }
+
+ /*
+ * Does one plus the current digit put us within roundoff of the
+ * number?
+ */
+
+ if (ShouldBankerRoundUpToNextPowD(&b, &mminus, sd,
+ convType, dPtr->w.word1 & 1,
+ &temp)) {
+ if (digit == 9) {
+ *s++ = '9';
+ s = BumpUp(s, retval, &k);
+ break;
+ }
+ ++digit;
+ *s++ = '0' + digit;
+ break;
+ }
+
+ /*
+ * Have we converted all the requested digits?
+ */
+ *s++ = '0' + digit;
+ if (i == ilim) {
+ if (ShouldBankerRoundUpPowD(&b, sd, digit&1)) {
+ s = BumpUp(s, retval, &k);
+ }
+ break;
+ }
+
+ /* Advance to the next digit */
+
+ mp_mul_d(&b, 10, &b);
+ mp_mul_d(&mminus, 10, &mminus);
+ if (m2plus > m2minus) {
+ mp_mul_2d(&mminus, m2plus-m2minus, &mplus);
+ }
+ ++i;
+ }
+
+ /*
+ * Endgame - store the location of the decimal point and the end of the
+ * string.
+ */
+ if (m2plus > m2minus) {
+ mp_clear(&mplus);
+ }
+ mp_clear_multi(&b, &mminus, &temp, NULL);
+ *s = '\0';
+ *decpt = k;
+ if (endPtr) {
+ *endPtr = s;
+ }
+ return retval;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * StrictBignumConversionPowD --
+ *
+ * Converts a double-precision number to a fixed-lengt string of
+ * 'ilim' digits (or 'ilim1' if log10(d) has been overestimated.)
+ * The denominator in David Gay's conversion algorithm is known to
+ * be a power of 2**DIGIT_BIT, and hence the division in the main
+ * loop may be replaced by a digit shift and mask.
+ *
+ * Results:
+ * Returns the string of significant decimal digits, in newly
+ * allocated memory.
+ *
+ * Side effects:
+ * Stores the location of the decimal point in '*decpt' and the
+ * location of the terminal null byte in '*endPtr'.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static char*
+StrictBignumConversionPowD(Double* dPtr,
+ /* Original number to convert */
+ int convType,
+ /* Type of conversion (shortest, Steele,
+ E format, F format) */
+ Tcl_WideUInt bw,
+ /* Integer significand */
+ int b2, int b5,
+ /* Scale factor for the significand
+ * in the numerator */
+ int sd,
+ /* Scale factor for the denominator */
+ int k,
+ /* Number of output digits before the decimal
+ * point */
+ int len,
+ /* Number of digits to allocate */
+ int ilim,
+ /* Number of digits to convert if b >= s */
+ int ilim1,
+ /* Number of digits to convert if b < s */
+ int* decpt,
+ /* OUTPUT: Position of the decimal point */
+ char** endPtr)
+ /* OUTPUT: Position of the terminal '\0'
+ * at the end of the returned string */
+{
+
+ char* retval = ckalloc(len + 1);
+ /* Output buffer */
+ mp_int b; /* Numerator of the fraction being converted */
+ mp_digit digit; /* Current output digit */
+ char* s = retval; /* Cursor in the output buffer */
+ int i; /* Index in the output buffer */
+ mp_int temp;
+
+ /*
+ * b = bw * 2**b2 * 5**b5
+ */
+
+ TclBNInitBignumFromWideUInt(&b, bw);
+ MulPow5(&b, b5, &b);
+ mp_mul_2d(&b, b2, &b);
+
+ /* Adjust if the logarithm was guessed wrong */
+
+ if (b.used <= sd) {
+ mp_mul_d(&b, 10, &b);
+ ilim = ilim1;
+ --k;
+ }
+ mp_init(&temp);
+
+ /*
+ * Loop through the digits. Do division and mod by s == 2**(sd*DIGIT_BIT)
+ * by mp_digit extraction
+ */
+
+ i = 1;
+ for (;;) {
+ if (b.used <= sd) {
+ digit = 0;
+ } else {
+ digit = b.dp[sd];
+ if (b.used > sd+1 || digit >= 10) {
+ Tcl_Panic("wrong digit!");
+ }
+ --b.used; mp_clamp(&b);
+ }
+
+ /*
+ * Have we converted all the requested digits?
+ */
+ *s++ = '0' + digit;
+ if (i == ilim) {
+ if (ShouldBankerRoundUpPowD(&b, sd, digit&1)) {
+ s = BumpUp(s, retval, &k);
+ } else {
+ while (*--s == '0') {
+ /* do nothing */
+ }
+ ++s;
+ }
+ break;
+ }
+
+ /* Advance to the next digit */
+
+ mp_mul_d(&b, 10, &b);
+ ++i;
+ }
+
+ /*
+ * Endgame - store the location of the decimal point and the end of the
+ * string.
+ */
+ mp_clear_multi(&b, &temp, NULL);
+ *s = '\0';
+ *decpt = k;
+ if (endPtr) {
+ *endPtr = s;
+ }
+ return retval;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * ShouldBankerRoundUp --
+ *
+ * Tests whether a digit should be rounded up or down when finishing
+ * bignum-based floating point conversion.
+ *
+ * Results:
+ * Returns 1 if the number needs to be rounded up, 0 otherwise.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static int
+ShouldBankerRoundUp(mp_int* twor,
+ /* 2x the remainder from thd division that
+ * produced the last digit */
+ mp_int* S, /* Denominator */
+ int isodd) /* Flag == 1 if the last digit is odd */
+{
+ int r = mp_cmp_mag(twor, S);
+ switch (r) {
+ case MP_LT:
+ return 0;
+ case MP_EQ:
+ return isodd;
+ case MP_GT:
+ return 1;
+ }
+ Tcl_Panic("in ShouldBankerRoundUp, trichotomy fails!");
+ return 0;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * ShouldBankerRoundUpToNext --
+ *
+ * Tests whether the remainder is great enough to force rounding
+ * to the next higher digit.
+ *
+ * Results:
+ * Returns 1 if the number should be rounded up, 0 otherwise.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static int
+ShouldBankerRoundUpToNext(mp_int* b,
+ /* Remainder from the division that produced
+ * the last digit. */
+ mp_int* m,
+ /* Numerator of the rounding tolerance */
+ mp_int* S,
+ /* Denominator */
+ int convType,
+ /* Conversion type: STEELE0 defeats
+ * round-to-even. (Not sure why one would
+ * want this; I coped it from Gay. FIXME */
+ int isodd,
+ /* 1 if the integer significand is odd */
+ mp_int* temp)
+ /* Work area needed for the calculation */
+{
+ int r;
+ /* Compare b and S-m: this is the same as comparing B+m and S. */
+ mp_add(b, m, temp);
+ r = mp_cmp_mag(temp, S);
+ switch(r) {
+ case MP_LT:
+ return 0;
+ case MP_EQ:
+ if (convType == TCL_DD_STEELE0) {
+ return 0;
+ } else {
+ return isodd;
+ }
+ case MP_GT:
+ return 1;
+ }
+ Tcl_Panic("in ShouldBankerRoundUpToNext, trichotomy fails!");
+ return 0;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * ShorteningBignumConversion --
+ *
+ * Convert a floating point number to a variable-length digit string
+ * using the multiprecision method.
+ *
+ * Results:
+ * Returns the string of digits.
+ *
+ * Side effects:
+ * Stores the position of the decimal point in *decpt.
+ * Stores a pointer to the end of the number in *endPtr.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static char*
+ShorteningBignumConversion(Double* dPtr,
+ /* Original number being converted */
+ int convType,
+ /* Conversion type */
+ Tcl_WideUInt bw,
+ /* Integer significand and exponent */
+ int b2,
+ /* Scale factor for the significand */
+ int m2plus, int m2minus,
+ /* Scale factors for 1/2 ulp in numerator */
+ int s2, int s5,
+ /* Scale factors for denominator */
+ int k,
+ /* Guessed position of the decimal point */
+ int len,
+ /* Size of the digit buffer to allocate */
+ int ilim,
+ /* Number of digits to convert if b >= s */
+ int ilim1,
+ /* Number of digits to convert if b < s */
+ int* decpt,
+ /* OUTPUT: Position of the decimal point */
+ char** endPtr)
+ /* OUTPUT: Pointer to the end of the number */
+{
+ char* retval = ckalloc(len+1);
+ /* Buffer of digits to return */
+ char* s = retval; /* Cursor in the return value */
+ mp_int b; /* Numerator of the result */
+ mp_int mminus; /* 1/2 ulp below the result */
+ mp_int mplus; /* 1/2 ulp above the result */
+ mp_int S; /* Denominator of the result */
+ mp_int dig; /* Current digit of the result */
+ int digit; /* Current digit of the result */
+ mp_int temp; /* Work area */
+ int minit = 1; /* Fudge factor for when we misguess k */
+ int i;
+ int r1;
+
+ /*
+ * b = bw * 2**b2 * 5**b5
+ * S = 2**s2 * 5*s5
+ */
+
+ TclBNInitBignumFromWideUInt(&b, bw);
+ mp_mul_2d(&b, b2, &b);
+ mp_init_set_int(&S, 1);
+ MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S);
+
+ /*
+ * Handle the case where we guess the position of the decimal point
+ * wrong.
+ */
+
+ if (mp_cmp_mag(&b, &S) == MP_LT) {
+ mp_mul_d(&b, 10, &b);
+ minit = 10;
+ ilim =ilim1;
+ --k;
+ }
+
+ /* mminus = 2**m2minus * 5**m5 */
+
+ mp_init_set_int(&mminus, minit);
+ mp_mul_2d(&mminus, m2minus, &mminus);
+ if (m2plus > m2minus) {
+ mp_init_copy(&mplus, &mminus);
+ mp_mul_2d(&mplus, m2plus-m2minus, &mplus);
+ }
+ mp_init(&temp);
+
+ /* Loop through the digits */
+
+ mp_init(&dig);
+ i = 1;
+ for (;;) {
+ mp_div(&b, &S, &dig, &b);
+ if (dig.used > 1 || dig.dp[0] >= 10) {
+ Tcl_Panic("wrong digit!");
+ }
+ digit = dig.dp[0];
+
+ /*
+ * Does the current digit leave us with a remainder small enough to
+ * round to it?
+ */
+
+ r1 = mp_cmp_mag(&b, (m2plus > m2minus)? &mplus : &mminus);
+ if (r1 == MP_LT
+ || (r1 == MP_EQ
+ && convType != TCL_DD_STEELE0
+ && (dPtr->w.word1 & 1) == 0)) {
+ mp_mul_2d(&b, 1, &b);
+ if (ShouldBankerRoundUp(&b, &S, digit&1)) {
+ ++digit;
+ if (digit == 10) {
+ *s++ = '9';
+ s = BumpUp(s, retval, &k);
+ break;
+ }
+ }
+ *s++ = '0' + digit;
+ break;
+ }
+
+ /*
+ * Does the current digit leave us with a remainder large enough
+ * to commit to rounding up to the next higher digit?
+ */
+
+ if (ShouldBankerRoundUpToNext(&b, &mminus, &S, convType,
+ dPtr->w.word1 & 1, &temp)) {
+ ++digit;
+ if (digit == 10) {
+ *s++ = '9';
+ s = BumpUp(s, retval, &k);
+ break;
+ }
+ *s++ = '0' + digit;
+ break;
+ }
+
+ /* Have we converted all the requested digits? */
+
+ *s++ = '0' + digit;
+ if (i == ilim) {
+ mp_mul_2d(&b, 1, &b);
+ if (ShouldBankerRoundUp(&b, &S, digit&1)) {
+ s = BumpUp(s, retval, &k);
+ }
+ break;
+ }
+
+ /* Advance to the next digit */
+
+ if (s5 > 0) {
+
+ /* Can possibly shorten the denominator */
+ mp_mul_2d(&b, 1, &b);
+ mp_mul_2d(&mminus, 1, &mminus);
+ if (m2plus > m2minus) {
+ mp_mul_2d(&mplus, 1, &mplus);
+ }
+ mp_div_d(&S, 5, &S, NULL);
+ --s5;
+ /*
+ * IDEA: It might possibly be a win to fall back to
+ * int64 arithmetic here if S < 2**64/10. But it's
+ * a win only for a fairly narrow range of magnitudes
+ * so perhaps not worth bothering. We already know that
+ * we shorten the denominator by at least 1 mp_digit, perhaps
+ * 2. as we do the conversion for 17 digits of significance.
+ * Possible savings:
+ * 10**26 1 trip through loop before fallback possible
+ * 10**27 1 trip
+ * 10**28 2 trips
+ * 10**29 3 trips
+ * 10**30 4 trips
+ * 10**31 5 trips
+ * 10**32 6 trips
+ * 10**33 7 trips
+ * 10**34 8 trips
+ * 10**35 9 trips
+ * 10**36 10 trips
+ * 10**37 11 trips
+ * 10**38 12 trips
+ * 10**39 13 trips
+ * 10**40 14 trips
+ * 10**41 15 trips
+ * 10**42 16 trips
+ * thereafter no gain.
+ */
+ } else {
+ mp_mul_d(&b, 10, &b);
+ mp_mul_d(&mminus, 10, &mminus);
+ if (m2plus > m2minus) {
+ mp_mul_2d(&mplus, 10, &mplus);
+ }
+ }
+
+ ++i;
+ }
+
+
+ /*
+ * Endgame - store the location of the decimal point and the end of the
+ * string.
+ */
+ if (m2plus > m2minus) {
+ mp_clear(&mplus);
+ }
+ mp_clear_multi(&b, &mminus, &temp, &dig, &S, NULL);
+ *s = '\0';
+ *decpt = k;
+ if (endPtr) {
+ *endPtr = s;
+ }
+ return retval;
+
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * StrictBignumConversion --
+ *
+ * Convert a floating point number to a fixed-length digit string
+ * using the multiprecision method.
+ *
+ * Results:
+ * Returns the string of digits.
+ *
+ * Side effects:
+ * Stores the position of the decimal point in *decpt.
+ * Stores a pointer to the end of the number in *endPtr.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+inline static char*
+StrictBignumConversion(Double* dPtr,
+ /* Original number being converted */
+ int convType,
+ /* Conversion type */
+ Tcl_WideUInt bw,
+ /* Integer significand and exponent */
+ int b2, /* Scale factor for the significand */
+ int s2, int s5,
+ /* Scale factors for denominator */
+ int k, /* Guessed position of the decimal point */
+ int len, /* Size of the digit buffer to allocate */
+ int ilim,
+ /* Number of digits to convert if b >= s */
+ int ilim1,
+ /* Number of digits to convert if b < s */
+ int* decpt,
+ /* OUTPUT: Position of the decimal point */
+ char** endPtr)
+ /* OUTPUT: Pointer to the end of the number */
+{
+ char* retval = ckalloc(len+1);
+ /* Buffer of digits to return */
+ char* s = retval; /* Cursor in the return value */
+ mp_int b; /* Numerator of the result */
+ mp_int S; /* Denominator of the result */
+ mp_int dig; /* Current digit of the result */
+ int digit; /* Current digit of the result */
+ mp_int temp; /* Work area */
+ int g; /* Size of the current digit groun */
+ int i, j;
+
+ /*
+ * b = bw * 2**b2 * 5**b5
+ * S = 2**s2 * 5*s5
+ */
+
+ mp_init_multi(&temp, &dig, NULL);
+ TclBNInitBignumFromWideUInt(&b, bw);
+ mp_mul_2d(&b, b2, &b);
+ mp_init_set_int(&S, 1);
+ MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S);
+
+ /*
+ * Handle the case where we guess the position of the decimal point
+ * wrong.
+ */
+
+ if (mp_cmp_mag(&b, &S) == MP_LT) {
+ mp_mul_d(&b, 10, &b);
+ ilim =ilim1;
+ --k;
+ }
+
+ /* Convert the leading digit */
+
+ i = 0;
+ mp_div(&b, &S, &dig, &b);
+ if (dig.used > 1 || dig.dp[0] >= 10) {
+ Tcl_Panic("wrong digit!");
+ }
+ digit = dig.dp[0];
+
+ /* Is a single digit all that was requested? */
+
+ *s++ = '0' + digit;
+ if (++i >= ilim) {
+ mp_mul_2d(&b, 1, &b);
+ if (ShouldBankerRoundUp(&b, &S, digit&1)) {
+ s = BumpUp(s, retval, &k);
+ }
+ } else {
+
+ for (;;) {
+
+ /* Shift by a group of digits. */
+
+ g = ilim - i;
+ if (g > DIGIT_GROUP) {
+ g = DIGIT_GROUP;
+ }
+ if (s5 >= g) {
+ mp_div_d(&S, dpow5[g], &S, NULL);
+ s5 -= g;
+ } else if (s5 > 0) {
+ mp_div_d(&S, dpow5[s5], &S, NULL);
+ mp_mul_d(&b, dpow5[g - s5], &b);
+ s5 = 0;
+ } else {
+ mp_mul_d(&b, dpow5[g], &b);
+ }
+ mp_mul_2d(&b, g, &b);
+
+ /*
+ * As with the shortening bignum conversion, it's possible at
+ * this point that we will have reduced the denominator to
+ * less than 2**64/10, at which point it would be possible to
+ * fall back to to int64 arithmetic. But the potential payoff
+ * is tremendously less - unless we're working in F format -
+ * because we know that three groups of digits will always
+ * suffice for %#.17e, the longest format that doesn't introduce
+ * empty precision.
+ */
+
+ /* Extract the next group of digits */
+
+ mp_div(&b, &S, &dig, &b);
+ if (dig.used > 1) {
+ Tcl_Panic("wrong digit!");
+ }
+ digit = dig.dp[0];
+ for (j = g-1; j >= 0; --j) {
+ int t = itens[j];
+ *s++ = digit / t + '0';
+ digit %= t;
+ }
+ i += g;
+
+ /* Have we converted all the requested digits? */
+
+ if (i == ilim) {
+ mp_mul_2d(&b, 1, &b);
+ if (ShouldBankerRoundUp(&b, &S, digit&1)) {
+ s = BumpUp(s, retval, &k);
+ } else {
+ while (*--s == '0') {
+ /* do nothing */
+ }
+ ++s;
+ }
+ break;
+ }
+ }
+ }
+ /*
+ * Endgame - store the location of the decimal point and the end of the
+ * string.
+ */
+ mp_clear_multi(&b, &S, &temp, &dig, NULL);
+ *s = '\0';
+ *decpt = k;
+ if (endPtr) {
+ *endPtr = s;
+ }
+ return retval;
+
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * TclDoubleDigits --
+ *
+ * Core of Tcl's conversion of double-precision floating point numbers
+ * to decimal.
+ *
+ * Results:
+ * Returns a newly-allocated string of digits.
+ *
+ * Side effects:
+ * Sets *decpt to the index of the character in the string before the
+ * place that the decimal point should go. If 'endPtr' is not NULL,
+ * sets endPtr to point to the terminating '\0' byte of the string.
+ * Sets *sign to 1 if a minus sign should be printed with the number,
+ * or 0 if a plus sign (or no sign) should appear.
+ *
+ * This function is a service routine that produces the string of digits
+ * for floating-point-to-decimal conversion. It can do a number of things
+ * according to the 'flags' argument. Valid values for 'flags' include:
+ * TCL_DD_SHORTEST - This is the default for floating point conversion
+ * if ::tcl_precision is 0. It constructs the shortest string
+ * of digits that will reconvert to the given number when scanned.
+ * For floating point numbers that are exactly between two
+ * decimal numbers, it resolves using the 'round to even' rule.
+ * With this value, the 'ndigits' parameter is ignored.
+ * TCL_DD_STEELE - This value is not recommended and may be removed
+ * in the future. It follows the conversion algorithm outlined
+ * in "How to Print Floating-Point Numbers Accurately" by
+ * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90,
+ * pp. 112-126]. This rule has the effect of rendering 1e23
+ * as 9.9999999999999999e22 - which is a 'better' approximation
+ * in the sense that it will reconvert correctly even if
+ * a subsequent input conversion is 'round up' or 'round down'
+ * rather than 'round to nearest', but is surprising otherwise.
+ * TCL_DD_E_FORMAT - This value is used to prepare numbers for %e
+ * format conversion (or for default floating->string if
+ * tcl_precision is not 0). It constructs a string of at most
+ * 'ndigits' digits, choosing the one that is closest to the
+ * given number (and resolving ties with 'round to even').
+ * It is allowed to return fewer than 'ndigits' if the number
+ * converts exactly; if the TCL_DD_E_FORMAT|TCL_DD_SHORTEN_FLAG
+ * is supplied instead, it also returns fewer digits if the
+ * shorter string will still reconvert to the given input number.
+ * In any case, strings of trailing zeroes are suppressed.
+ * TCL_DD_F_FORMAT - This value is used to prepare numbers for %f
+ * format conversion. It requests that conversion proceed until
+ * 'ndigits' digits after the decimal point have been converted.
+ * It is possible for this format to result in a zero-length
+ * string if the number is sufficiently small. Again, it
+ * is permissible for TCL_DD_F_FORMAT to return fewer digits
+ * for a number that converts exactly, and changing the
+ * argument to TCL_DD_F_FORMAT|TCL_DD_SHORTEN_FLAG will allow
+ * the routine also to return fewer digits if the shorter string
+ * will still reconvert without loss to the given input number.
+ * Strings of trailing zeroes are suppressed.
+ *
+ * To any of these flags may be OR'ed TCL_DD_NO_QUICK; this flag
+ * requires all calculations to be done in exact arithmetic. Normally,
+ * E and F format with fewer than about 14 digits will be done with
+ * a quick floating point approximation and fall back on the exact
+ * arithmetic only if the input number is close enough to the
+ * midpoint between two decimal strings that more precision is needed
+ * to resolve which string is correct.
+ *
+ * The value stored in the 'decpt' argument on return may be negative
+ * (indicating that the decimal point falls to the left of the string)
+ * or greater than the length of the string. In addition, the value -9999
+ * is used as a sentinel to indicate that the string is one of the special
+ * values "Infinity" and "NaN", and that no decimal point should be inserted.
+ *
+ *-----------------------------------------------------------------------------
+ */
+char*
+TclDoubleDigits(double dv, /* Number to convert */
+ int ndigits, /* Number of digits requested */
+ int flags, /* Conversion flags */
+ int* decpt, /* OUTPUT: Position of the decimal point */
+ int* sign, /* OUTPUT: 1 if the result is negative */
+ char** endPtr) /* OUTPUT: If not NULL, receives a pointer
+ * to one character beyond the end
+ * of the returned string */
+{
+ int convType = (flags & TCL_DD_CONVERSION_TYPE_MASK);
+ /* Type of conversion being performed
+ * TCL_DD_SHORTEST0
+ * TCL_DD_STEELE0
+ * TCL_DD_E_FORMAT
+ * TCL_DD_F_FORMAT */
+ Double d; /* Union for deconstructing doubles */
+ Tcl_WideUInt bw; /* Integer significand */
+ int be; /* Power of 2 by which b must be multiplied */
+ int bbits; /* Number of bits needed to represent b */
+ int denorm; /* Flag == 1 iff the input number was
+ * denormalized */
+ int k; /* Estimate of floor(log10(d)) */
+ int k_check; /* Flag == 1 if d is near enough to a
+ * power of ten that k must be checked */
+ int b2, b5, s2, s5; /* Powers of 2 and 5 in the numerator and
+ * denominator of intermediate results */
+ int ilim = -1, ilim1 = -1; /* Number of digits to convert, and number
+ * to convert if log10(d) has been
+ * overestimated */
+ char* retval; /* Return value from this function */
+ int i = -1;
+
+ /* Put the input number into a union for bit-whacking */
+
+ d.d = dv;
+
+ /*
+ * Handle the cases of negative numbers (by taking the absolute value:
+ * this includes -Inf and -NaN!), infinity, Not a Number, and zero.
+ */
+
+ TakeAbsoluteValue(&d, sign);
+ if ((d.w.word0 & EXP_MASK) == EXP_MASK) {
+ return FormatInfAndNaN(&d, decpt, endPtr);
+ }
+ if (d.d == 0.0) {
+ return FormatZero(decpt, endPtr);
+ }
+
+ /*
+ * Unpack the floating point into a wide integer and an exponent.
+ * Determine the number of bits that the big integer requires, and
+ * compute a quick approximation (which may be one too high) of
+ * ceil(log10(d.d)).
+ */
+ denorm = ((d.w.word0 & EXP_MASK) == 0);
+ DoubleToExpAndSig(d.d, &bw, &be, &bbits);
+ k = ApproximateLog10(bw, be, bbits);
+ k = BetterLog10(d.d, k, &k_check);
+
+ /* At this point, we have:
+ * d is the number to convert.
+ * bw are significand and exponent: d == bw*2**be,
+ * bbits is the length of bw: 2**bbits-1 <= bw < 2**bbits
+ * k is either ceil(log10(d)) or ceil(log10(d))+1. k_check is 0
+ * if we know that k is exactly ceil(log10(d)) and 1 if we need to
+ * check.
+ * We want a rational number
+ * r = b * 10**(1-k) = bw * 2**b2 * 5**b5 / (2**s2 / 5**s5),
+ * with b2, b5, s2, s5 >= 0. Note that the most significant decimal
+ * digit is floor(r) and that successive digits can be obtained
+ * by setting r <- 10*floor(r) (or b <= 10 * (b % S)).
+ * Find appropriate b2, b5, s2, s5.
+ */
+
+ ComputeScale(be, k, &b2, &b5, &s2, &s5);
+
+ /*
+ * Correct an incorrect caller-supplied 'ndigits'.
+ * Also determine:
+ * i = The maximum number of decimal digits that will be returned in the
+ * formatted string. This is k + 1 + ndigits for F format, 18 for
+ * shortest and Steele, and ndigits for E format.
+ * ilim = The number of significant digits to convert if
+ * k has been guessed correctly. This is -1 for shortest and Steele
+ * (which stop when all significance has been lost), 'ndigits'
+ * for E format, and 'k + 1 + ndigits' for F format.
+ * ilim1 = The minimum number of significant digits to convert if
+ * k has been guessed 1 too high. This, too, is -1 for shortest
+ * and Steele, and 'ndigits' for E format, but it's 'ndigits-1'
+ * for F format.
+ */
+
+ SetPrecisionLimits(convType, k, &ndigits, &i, &ilim, &ilim1);
+
+ /*
+ * Try to do low-precision conversion in floating point rather
+ * than resorting to expensive multiprecision arithmetic
+ */
+ if (ilim >= 0 && ilim <= QUICK_MAX && !(flags & TCL_DD_NO_QUICK)) {
+ if ((retval = QuickConversion(d.d, k, k_check, flags,
+ i, ilim, ilim1,
+ decpt, endPtr)) != NULL) {
+ return retval;
+ }
+ }
+
+ /*
+ * For shortening conversions, determine the upper and lower bounds
+ * for the remainder at which we can stop.
+ * m+ = (2**m2plus * 5**m5) / (2**s2 * 5**s5) is the limit on the
+ * high side, and
+ * m- = (2**m2minus * 5**m5) / (2**s2 * 5**s5) is the limit on the
+ * low side.
+ * We may need to increase s2 to put m2plus, m2minus, b2 over a
+ * common denominator.
+ */
+
+ if (flags & TCL_DD_SHORTEN_FLAG) {
+ int m2minus = b2;
+ int m2plus;
+ int m5 = b5;
+ int len = i;
+
+ /*
+ * Find the quantity i so that (2**i*5**b5)/(2**s2*5**s5)
+ * is 1/2 unit in the least significant place of the floating
+ * point number.
+ */
+ if (denorm) {
+ i = be + EXPONENT_BIAS + (FP_PRECISION-1);
+ } else {
+ i = 1 + FP_PRECISION - bbits;
+ }
+ b2 += i;
+ s2 += i;
+
+ /*
+ * Reduce the fractions to lowest terms, since the above calculation
+ * may have left excess powers of 2 in numerator and denominator
+ */
+ CastOutPowersOf2(&b2, &m2minus, &s2);
+
+ /*
+ * In the special case where bw==1, the nearest floating point number
+ * to it on the low side is 1/4 ulp below it. Adjust accordingly.
+ */
+ m2plus = m2minus;
+ if (!denorm && bw == 1) {
+ ++b2;
+ ++s2;
+ ++m2plus;
+ }
+
+ if (s5+1 < N_LOG2POW5
+ && s2+1 + log2pow5[s5+1] <= 64) {
+ /*
+ * If 10*2**s2*5**s5 == 2**(s2+1)+5**(s5+1) fits in a 64-bit
+ * word, then all our intermediate calculations can be done
+ * using exact 64-bit arithmetic with no need for expensive
+ * multiprecision operations. (This will be true for all numbers
+ * in the range [1.0e-3 .. 1.0e+24]).
+ */
+
+ return ShorteningInt64Conversion(&d, convType, bw, b2, b5,
+ m2plus, m2minus, m5,
+ s2, s5, k, len, ilim, ilim1,
+ decpt, endPtr);
+ } else if (s5 == 0) {
+ /*
+ * The denominator is a power of 2, so we can replace division
+ * by digit shifts. First we round up s2 to a multiple of
+ * DIGIT_BIT, and adjust m2 and b2 accordingly. Then we launch
+ * into a version of the comparison that's specialized for
+ * the 'power of mp_digit in the denominator' case.
+ */
+ if (s2 % DIGIT_BIT != 0) {
+ int delta = DIGIT_BIT - (s2 % DIGIT_BIT);
+ b2 += delta;
+ m2plus += delta;
+ m2minus += delta;
+ s2 += delta;
+ }
+ return ShorteningBignumConversionPowD(&d, convType, bw, b2, b5,
+ m2plus, m2minus, m5,
+ s2/DIGIT_BIT, k, len,
+ ilim, ilim1, decpt, endPtr);
+ } else {
+
+ /*
+ * Alas, there's no helpful special case; use full-up
+ * bignum arithmetic for the conversion
+ */
+
+ return ShorteningBignumConversion(&d, convType, bw,
+ b2, m2plus, m2minus,
+ s2, s5, k, len,
+ ilim, ilim1, decpt, endPtr);
+
+ }
+
+ } else {
+
+ /* Non-shortening conversion */
+
+ int len = i;
+
+ /* Reduce numerator and denominator to lowest terms */
+
+ if (b2 >= s2 && s2 > 0) {
+ b2 -= s2; s2 = 0;
+ } else if (s2 >= b2 && b2 > 0) {
+ s2 -= b2; b2 = 0;
+ }
+
+ if (s5+1 < N_LOG2POW5
+ && s2+1 + log2pow5[s5+1] <= 64) {
+ /*
+ * If 10*2**s2*5**s5 == 2**(s2+1)+5**(s5+1) fits in a 64-bit
+ * word, then all our intermediate calculations can be done
+ * using exact 64-bit arithmetic with no need for expensive
+ * multiprecision operations.
+ */
+
+ return StrictInt64Conversion(&d, convType, bw, b2, b5,
+ s2, s5, k, len, ilim, ilim1,
+ decpt, endPtr);
+
+ } else if (s5 == 0) {
+ /*
+ * The denominator is a power of 2, so we can replace division
+ * by digit shifts. First we round up s2 to a multiple of
+ * DIGIT_BIT, and adjust m2 and b2 accordingly. Then we launch
+ * into a version of the comparison that's specialized for
+ * the 'power of mp_digit in the denominator' case.
+ */
+ if (s2 % DIGIT_BIT != 0) {
+ int delta = DIGIT_BIT - (s2 % DIGIT_BIT);
+ b2 += delta;
+ s2 += delta;
+ }
+ return StrictBignumConversionPowD(&d, convType, bw, b2, b5,
+ s2/DIGIT_BIT, k, len,
+ ilim, ilim1, decpt, endPtr);
+ } else {
+ /*
+ * There are no helpful special cases, but at least we know
+ * in advance how many digits we will convert. We can run the
+ * conversion in steps of DIGIT_GROUP digits, so as to
+ * have many fewer mp_int divisions.
+ */
+ return StrictBignumConversion(&d, convType, bw, b2, s2, s5,
+ k, len, ilim, ilim1, decpt, endPtr);
+ }
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclInitDoubleConversion --
+ *
+ * Initializes constants that are needed for conversions to and from
+ * 'double'
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The log base 2 of the floating point radix, the number of bits in a
+ * double mantissa, and a table of the powers of five and ten are
+ * computed and stored.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclInitDoubleConversion(void)
+{
+ int i;
+ int x;
+ Tcl_WideUInt u;
+ double d;
+
+#ifdef IEEE_FLOATING_POINT
+ union {
+ double dv;
+ Tcl_WideUInt iv;
+ } bitwhack;
+#endif
+
+#if defined(__sgi) && defined(_COMPILER_VERSION)
+ union fpc_csr mipsCR;
+
+ mipsCR.fc_word = get_fpc_csr();
+ mipsCR.fc_struct.flush = 0;
+ set_fpc_csr(mipsCR.fc_word);
+#endif
+
+ /*
+ * Initialize table of powers of 10 expressed as wide integers.
+ */
+
+ maxpow10_wide = (int)
+ floor(sizeof(Tcl_WideUInt) * CHAR_BIT * log(2.) / log(10.));
+ pow10_wide = (Tcl_WideUInt *)
+ ckalloc((maxpow10_wide + 1) * sizeof(Tcl_WideUInt));
+ u = 1;
+ for (i = 0; i < maxpow10_wide; ++i) {
+ pow10_wide[i] = u;
+ u *= 10;
+ }
+ pow10_wide[i] = u;
+
+ /*
+ * Determine how many bits of precision a double has, and how many
+ * decimal digits that represents.
+ */
+
+ if (frexp((double) FLT_RADIX, &log2FLT_RADIX) != 0.5) {
+ Tcl_Panic("This code doesn't work on a decimal machine!");
+ }
+ log2FLT_RADIX--;
+ mantBits = DBL_MANT_DIG * log2FLT_RADIX;
+ d = 1.0;
+
+ /*
+ * Initialize a table of powers of ten that can be exactly represented
+ * in a double.
+ */
+
+ x = (int) (DBL_MANT_DIG * log((double) FLT_RADIX) / log(5.0));
+ if (x < MAXPOW) {
+ mmaxpow = x;
+ } else {
+ mmaxpow = MAXPOW;
+ }
+ for (i=0 ; i<=mmaxpow ; ++i) {
+ pow10vals[i] = d;
+ d *= 10.0;
+ }
+
+ /*
+ * Initialize a table of large powers of five.
+ */
+
+ for (i=0; i<9; ++i) {
+ mp_init(pow5 + i);
+ }
+ mp_set(pow5, 5);
+ for (i=0; i<8; ++i) {
+ mp_sqr(pow5+i, pow5+i+1);
+ }
+ mp_init_set_int(pow5_13, 1220703125);
+ for (i = 1; i < 5; ++i) {
+ mp_init(pow5_13 + i);
+ mp_sqr(pow5_13 + i - 1, pow5_13 + i);
+ }
+
+ /*
+ * Determine the number of decimal digits to the left and right of the
+ * decimal point in the largest and smallest double, the smallest double
+ * that differs from zero, and the number of mp_digits needed to represent
+ * the significand of a double.
+ */
+
+ maxDigits = (int) ((DBL_MAX_EXP * log((double) FLT_RADIX)
+ + 0.5 * log(10.)) / log(10.));
+ minDigits = (int) floor((DBL_MIN_EXP - DBL_MANT_DIG)
+ * log((double) FLT_RADIX) / log(10.));
+ mantDIGIT = (mantBits + DIGIT_BIT-1) / DIGIT_BIT;
+ log10_DIGIT_MAX = (int) floor(DIGIT_BIT * log(2.) / log(10.));
+
+ /*
+ * Nokia 770's software-emulated floating point is "middle endian": the
+ * bytes within a 32-bit word are little-endian (like the native
+ * integers), but the two words of a 'double' are presented most
+ * significant word first.
+ */
+
+#ifdef IEEE_FLOATING_POINT
+ bitwhack.dv = 1.000000238418579;
+ /* 3ff0 0000 4000 0000 */
+ if ((bitwhack.iv >> 32) == 0x3ff00000) {
+ n770_fp = 0;
+ } else if ((bitwhack.iv & 0xffffffff) == 0x3ff00000) {
+ n770_fp = 1;
+ } else {
+ Tcl_Panic("unknown floating point word order on this machine");
+ }
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclFinalizeDoubleConversion --
+ *
+ * Cleans up this file on exit.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Memory allocated by TclInitDoubleConversion is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclFinalizeDoubleConversion(void)
+{
+ int i;
+
+ ckfree((char *) pow10_wide);
+ for (i=0; i<9; ++i) {
+ mp_clear(pow5 + i);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_InitBignumFromDouble --
+ *
+ * Extracts the integer part of a double and converts it to an arbitrary
+ * precision integer.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Initializes the bignum supplied, and stores the converted number in
+ * it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_InitBignumFromDouble(
+ Tcl_Interp *interp, /* For error message */
+ double d, /* Number to convert */
+ mp_int *b) /* Place to store the result */
+{
+ double fract;
+ int expt;
+
+ /*
+ * Infinite values can't convert to bignum.
+ */
+
+ if (TclIsInfinite(d)) {
+ if (interp != NULL) {
+ const char *s = "integer value too large to represent";
+
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
+ Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL);
+ }
+ return TCL_ERROR;
+ }
+
+ fract = frexp(d,&expt);
+ if (expt <= 0) {
+ mp_init(b);
+ mp_zero(b);
+ } else {
+ Tcl_WideInt w = (Tcl_WideInt) ldexp(fract, mantBits);
+ int shift = expt - mantBits;
+
+ TclBNInitBignumFromWideInt(b, w);
+ if (shift < 0) {
+ mp_div_2d(b, -shift, b, NULL);
+ } else if (shift > 0) {
+ mp_mul_2d(b, shift, b);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclBignumToDouble --
+ *
+ * Convert an arbitrary-precision integer to a native floating point
+ * number.
+ *
+ * Results:
+ * Returns the converted number. Sets errno to ERANGE if the number is
+ * too large to convert.
+ *
+ *----------------------------------------------------------------------
+ */
+
+double
+TclBignumToDouble(
+ mp_int *a) /* Integer to convert. */
+{
+ mp_int b;
+ int bits, shift, i, lsb;
+ double r;
+
+
+ /*
+ * We need a 'mantBits'-bit significand. Determine what shift will
+ * give us that.
+ */
+
+ bits = mp_count_bits(a);
+ if (bits > DBL_MAX_EXP*log2FLT_RADIX) {
+ errno = ERANGE;
+ if (a->sign == MP_ZPOS) {
+ return HUGE_VAL;
+ } else {
+ return -HUGE_VAL;
+ }
+ }
+ shift = mantBits - bits;
+
+ /*
+ * If shift > 0, shift the significand left by the requisite number of
+ * bits. If shift == 0, the significand is already exactly 'mantBits'
+ * in length. If shift < 0, we will need to shift the significand right
+ * by the requisite number of bits, and round it. If the '1-shift'
+ * least significant bits are 0, but the 'shift'th bit is nonzero,
+ * then the significand lies exactly between two values and must be
+ * 'rounded to even'.
+ */
+
+ mp_init(&b);
+ if (shift == 0) {
+ mp_copy(a, &b);
+ } else if (shift > 0) {
+ mp_mul_2d(a, shift, &b);
+ } else if (shift < 0) {
+ lsb = mp_cnt_lsb(a);
+ if (lsb == -1-shift) {
+
+ /*
+ * Round to even
+ */
+
+ mp_div_2d(a, -shift, &b, NULL);
+ if (mp_isodd(&b)) {
+ if (b.sign == MP_ZPOS) {
+ mp_add_d(&b, 1, &b);
+ } else {
+ mp_sub_d(&b, 1, &b);
+ }
+ }
+ } else {
+
+ /*
+ * Ordinary rounding
+ */
+
+ mp_div_2d(a, -1-shift, &b, NULL);
+ if (b.sign == MP_ZPOS) {
+ mp_add_d(&b, 1, &b);
+ } else {
+ mp_sub_d(&b, 1, &b);
+ }
+ mp_div_2d(&b, 1, &b, NULL);
+ }
+ }
+
+ /*
+ * Accumulate the result, one mp_digit at a time.
+ */
+
+ r = 0.0;
+ for (i=b.used-1 ; i>=0 ; --i) {
+ r = ldexp(r, DIGIT_BIT) + b.dp[i];
+ }
+ mp_clear(&b);
+
+ /*
+ * Scale the result to the correct number of bits.
+ */
+
+ r = ldexp(r, bits - mantBits);
+
+ /*
+ * Return the result with the appropriate sign.
+ */
+
+ if (a->sign == MP_ZPOS) {
+ return r;
+ } else {
+ return -r;
+ }
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * TclCeil --
+ *
+ * Computes the smallest floating point number that is at least the
+ * mp_int argument.
+ *
+ * Results:
+ * Returns the floating point number.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+double
+TclCeil(
+ mp_int *a) /* Integer to convert. */
+{
+ double r = 0.0;
+ mp_int b;
+
+ mp_init(&b);
+ if (mp_cmp_d(a, 0) == MP_LT) {
+ mp_neg(a, &b);
+ r = -TclFloor(&b);
+ } else {
+ int bits = mp_count_bits(a);
+
+ if (bits > DBL_MAX_EXP*log2FLT_RADIX) {
+ r = HUGE_VAL;
+ } else {
+ int i, exact = 1, shift = mantBits - bits;
+
+ if (shift > 0) {
+ mp_mul_2d(a, shift, &b);
+ } else if (shift < 0) {
+ mp_int d;
+ mp_init(&d);
+ mp_div_2d(a, -shift, &b, &d);
+ exact = mp_iszero(&d);
+ mp_clear(&d);
+ } else {
+ mp_copy(a, &b);
+ }
+ if (!exact) {
+ mp_add_d(&b, 1, &b);
+ }
+ for (i=b.used-1 ; i>=0 ; --i) {
+ r = ldexp(r, DIGIT_BIT) + b.dp[i];
+ }
+ r = ldexp(r, bits - mantBits);
+ }
+ }
+ mp_clear(&b);
+ return r;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * TclFloor --
+ *
+ * Computes the largest floating point number less than or equal to
+ * the mp_int argument.
+ *
+ * Results:
+ * Returns the floating point value.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+double
+TclFloor(
+ mp_int *a) /* Integer to convert. */
+{
+ double r = 0.0;
+ mp_int b;
+
+ mp_init(&b);
+ if (mp_cmp_d(a, 0) == MP_LT) {
+ mp_neg(a, &b);
+ r = -TclCeil(&b);
+ } else {
+ int bits = mp_count_bits(a);
+
+ if (bits > DBL_MAX_EXP*log2FLT_RADIX) {
+ r = DBL_MAX;
+ } else {
+ int i, shift = mantBits - bits;
+
+ if (shift > 0) {
+ mp_mul_2d(a, shift, &b);
+ } else if (shift < 0) {
+ mp_div_2d(a, -shift, &b, NULL);
+ } else {
+ mp_copy(a, &b);
+ }
+ for (i=b.used-1 ; i>=0 ; --i) {
+ r = ldexp(r, DIGIT_BIT) + b.dp[i];
+ }
+ r = ldexp(r, bits - mantBits);
+ }
+ }
+ mp_clear(&b);
+ return r;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BignumToBiasedFrExp --
+ *
+ * Convert an arbitrary-precision integer to a native floating point
+ * number in the range [0.5,1) times a power of two. NOTE: Intentionally
+ * converts to a number that's a few ulp too small, so that
+ * RefineApproximation will not overflow near the high end of the
+ * machine's arithmetic range.
+ *
+ * Results:
+ * Returns the converted number.
+ *
+ * Side effects:
+ * Stores the exponent of two in 'machexp'.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static double
+BignumToBiasedFrExp(
+ mp_int *a, /* Integer to convert */
+ int *machexp) /* Power of two */
+{
+ mp_int b;
+ int bits;
+ int shift;
+ int i;
+ double r;
+
+ /*
+ * Determine how many bits we need, and extract that many from the input.
+ * Round to nearest unit in the last place.
+ */
+
+ bits = mp_count_bits(a);
+ shift = mantBits - 2 - bits;
+ mp_init(&b);
+ if (shift > 0) {
+ mp_mul_2d(a, shift, &b);
+ } else if (shift < 0) {
+ mp_div_2d(a, -shift, &b, NULL);
+ } else {
+ mp_copy(a, &b);
+ }
+
+ /*
+ * Accumulate the result, one mp_digit at a time.
+ */
+
+ r = 0.0;
+ for (i=b.used-1; i>=0; --i) {
+ r = ldexp(r, DIGIT_BIT) + b.dp[i];
+ }
+ mp_clear(&b);
+
+ /*
+ * Return the result with the appropriate sign.
+ */
+
+ *machexp = bits - mantBits + 2;
+ return ((a->sign == MP_ZPOS) ? r : -r);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pow10TimesFrExp --
+ *
+ * Multiply a power of ten by a number expressed as fraction and
+ * exponent.
+ *
+ * Results:
+ * Returns the significand of the result.
+ *
+ * Side effects:
+ * Overwrites the 'machexp' parameter with the exponent of the result.
+ *
+ * Assumes that 'exponent' is such that 10**exponent would be a double, even
+ * though 'fraction*10**(machexp+exponent)' might overflow.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static double
+Pow10TimesFrExp(
+ int exponent, /* Power of 10 to multiply by */
+ double fraction, /* Significand of multiplicand */
+ int *machexp) /* On input, exponent of multiplicand. On
+ * output, exponent of result. */
+{
+ int i, j;
+ int expt = *machexp;
+ double retval = fraction;
+
+ if (exponent > 0) {
+ /*
+ * Multiply by 10**exponent
+ */
+
+ retval = frexp(retval * pow10vals[exponent&0xf], &j);
+ expt += j;
+ for (i=4; i<9; ++i) {
+ if (exponent & (1<<i)) {
+ retval = frexp(retval * pow_10_2_n[i], &j);
+ expt += j;
+ }
+ }
+ } else if (exponent < 0) {
+ /*
+ * Divide by 10**-exponent
+ */
+
+ retval = frexp(retval / pow10vals[(-exponent) & 0xf], &j);
+ expt += j;
+ for (i=4; i<9; ++i) {
+ if ((-exponent) & (1<<i)) {
+ retval = frexp(retval / pow_10_2_n[i], &j);
+ expt += j;
+ }
+ }
+ }
+
+ *machexp = expt;
+ return retval;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SafeLdExp --
+ *
+ * Do an 'ldexp' operation, but handle denormals gracefully.
+ *
+ * Results:
+ * Returns the appropriately scaled value.
+ *
+ * On some platforms, 'ldexp' fails when presented with a number too
+ * small to represent as a normalized double. This routine does 'ldexp'
+ * in two steps for those numbers, to return correctly denormalized
+ * values.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static double
+SafeLdExp(
+ double fract,
+ int expt)
+{
+ int minexpt = DBL_MIN_EXP * log2FLT_RADIX;
+ volatile double a, b, retval;
+
+ if (expt < minexpt) {
+ a = ldexp(fract, expt - mantBits - minexpt);
+ b = ldexp(1.0, mantBits + minexpt);
+ retval = a * b;
+ } else {
+ retval = ldexp(fract, expt);
+ }
+ return retval;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclFormatNaN --
+ *
+ * Makes the string representation of a "Not a Number"
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Stores the string representation in the supplied buffer, which must be
+ * at least TCL_DOUBLE_SPACE characters.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclFormatNaN(
+ double value, /* The Not-a-Number to format. */
+ char *buffer) /* String representation. */
+{
+#ifndef IEEE_FLOATING_POINT
+ strcpy(buffer, "NaN");
+ return;
+#else
+ union {
+ double dv;
+ Tcl_WideUInt iv;
+ } bitwhack;
+
+ bitwhack.dv = value;
+ if (n770_fp) {
+ bitwhack.iv = Nokia770Twiddle(bitwhack.iv);
+ }
+ if (bitwhack.iv & ((Tcl_WideUInt) 1 << 63)) {
+ bitwhack.iv &= ~ ((Tcl_WideUInt) 1 << 63);
+ *buffer++ = '-';
+ }
+ *buffer++ = 'N';
+ *buffer++ = 'a';
+ *buffer++ = 'N';
+ bitwhack.iv &= (((Tcl_WideUInt) 1) << 51) - 1;
+ if (bitwhack.iv != 0) {
+ sprintf(buffer, "(%" TCL_LL_MODIFIER "x)", bitwhack.iv);
+ } else {
+ *buffer = '\0';
+ }
+#endif /* IEEE_FLOATING_POINT */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Nokia770Twiddle --
+ *
+ * Transpose the two words of a number for Nokia 770 floating
+ * point handling.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_WideUInt
+Nokia770Twiddle(
+ Tcl_WideUInt w) /* Number to transpose */
+{
+ return (((w >> 32) & 0xffffffff) | (w << 32));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclNokia770Doubles --
+ *
+ * Transpose the two words of a number for Nokia 770 floating
+ * point handling.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclNokia770Doubles(void)
+{
+ return n770_fp;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c
index 6a9d832..13dda54 100644
--- a/generic/tclStringObj.c
+++ b/generic/tclStringObj.c
@@ -1,108 +1,111 @@
-/*
+/*
* tclStringObj.c --
*
- * This file contains procedures that implement string operations on Tcl
- * objects. Some string operations work with UTF strings and others
- * require Unicode format. Functions that require knowledge of the width
+ * This file contains functions that implement string operations on Tcl
+ * objects. Some string operations work with UTF strings and others
+ * require Unicode format. Functions that require knowledge of the width
* of each character, such as indexing, operate on Unicode data.
*
- * A Unicode string is an internationalized string. Conceptually, a
- * Unicode string is an array of 16-bit quantities organized as a sequence
- * of properly formed UTF-8 characters. There is a one-to-one map between
- * Unicode and UTF characters. Because Unicode characters have a fixed
- * width, operations such as indexing operate on Unicode data. The String
- * object is optimized for the case where each UTF char in a string is
- * only one byte. In this case, we store the value of numChars, but we
- * don't store the Unicode data (unless Tcl_GetUnicode is explicitly
- * called).
- *
- * The String object type stores one or both formats. The default
- * behavior is to store UTF. Once Unicode is calculated by a function, it
+ * A Unicode string is an internationalized string. Conceptually, a
+ * Unicode string is an array of 16-bit quantities organized as a
+ * sequence of properly formed UTF-8 characters. There is a one-to-one
+ * map between Unicode and UTF characters. Because Unicode characters
+ * have a fixed width, operations such as indexing operate on Unicode
+ * data. The String object is optimized for the case where each UTF char
+ * in a string is only one byte. In this case, we store the value of
+ * numChars, but we don't store the Unicode data (unless Tcl_GetUnicode
+ * is explicitly called).
+ *
+ * The String object type stores one or both formats. The default
+ * behavior is to store UTF. Once Unicode is calculated by a function, it
* is stored in the internal rep for future access (without an additional
* O(n) cost).
*
* To allow many appends to be done to an object without constantly
* reallocating the space for the string or Unicode representation, we
* allocate double the space for the string or Unicode and use the
- * internal representation to keep track of how much space is used
- * vs. allocated.
+ * internal representation to keep track of how much space is used vs.
+ * allocated.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright (c) 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.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
+#include "tommath.h"
/*
- * Prototypes for procedures defined later in this file:
+ * Prototypes for functions defined later in this file:
*/
-static void AppendUnicodeToUnicodeRep _ANSI_ARGS_((
- Tcl_Obj *objPtr, CONST Tcl_UniChar *unicode,
- int appendNumChars));
-static void AppendUnicodeToUtfRep _ANSI_ARGS_((
- Tcl_Obj *objPtr, CONST Tcl_UniChar *unicode,
- int numChars));
-static void AppendUtfToUnicodeRep _ANSI_ARGS_((Tcl_Obj *objPtr,
- CONST char *bytes, int numBytes));
-static void AppendUtfToUtfRep _ANSI_ARGS_((Tcl_Obj *objPtr,
- CONST char *bytes, int numBytes));
-static void DupStringInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr,
- Tcl_Obj *copyPtr));
-static void FillUnicodeRep _ANSI_ARGS_((Tcl_Obj *objPtr));
-static void FreeStringInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr));
-static void GrowUnicodeBuffer _ANSI_ARGS_((Tcl_Obj *objPtr,
- int needed));
-static int SetStringFromAny _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
+static void AppendPrintfToObjVA(Tcl_Obj *objPtr,
+ const char *format, va_list argList);
+static void AppendUnicodeToUnicodeRep(Tcl_Obj *objPtr,
+ const Tcl_UniChar *unicode, int appendNumChars);
+static void AppendUnicodeToUtfRep(Tcl_Obj *objPtr,
+ const Tcl_UniChar *unicode, int numChars);
+static void AppendUtfToUnicodeRep(Tcl_Obj *objPtr,
+ const char *bytes, int numBytes);
+static void AppendUtfToUtfRep(Tcl_Obj *objPtr,
+ const char *bytes, int numBytes);
+static void DupStringInternalRep(Tcl_Obj *objPtr,
+ Tcl_Obj *copyPtr);
+static void FillUnicodeRep(Tcl_Obj *objPtr);
+static void FreeStringInternalRep(Tcl_Obj *objPtr);
+static void GrowUnicodeBuffer(Tcl_Obj *objPtr, int needed);
+static int SetStringFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
static void SetUnicodeObj(Tcl_Obj *objPtr,
- CONST Tcl_UniChar *unicode, int numChars);
-static int UnicodeLength _ANSI_ARGS_((CONST Tcl_UniChar *unicode));
-static void UpdateStringOfString _ANSI_ARGS_((Tcl_Obj *objPtr));
+ const Tcl_UniChar *unicode, int numChars);
+static int UnicodeLength(const Tcl_UniChar *unicode);
+static void UpdateStringOfString(Tcl_Obj *objPtr);
/*
* The structure below defines the string Tcl object type by means of
- * procedures that can be invoked by generic object code.
+ * functions that can be invoked by generic object code.
*/
Tcl_ObjType tclStringType = {
- "string", /* name */
- FreeStringInternalRep, /* freeIntRepPro */
- DupStringInternalRep, /* dupIntRepProc */
- UpdateStringOfString, /* updateStringProc */
- SetStringFromAny /* setFromAnyProc */
+ "string", /* name */
+ FreeStringInternalRep, /* freeIntRepPro */
+ DupStringInternalRep, /* dupIntRepProc */
+ UpdateStringOfString, /* updateStringProc */
+ SetStringFromAny /* setFromAnyProc */
};
/*
- * The following structure is the internal rep for a String object.
- * It keeps track of how much memory has been used and how much has been
- * allocated for the Unicode and UTF string to enable growing and
- * shrinking of the UTF and Unicode reps of the String object with fewer
- * mallocs. To optimize string length and indexing operations, this
- * structure also stores the number of characters (same of UTF and Unicode!)
- * once that value has been computed.
+ * The following structure is the internal rep for a String object. It keeps
+ * track of how much memory has been used and how much has been allocated for
+ * the Unicode and UTF string to enable growing and shrinking of the UTF and
+ * Unicode reps of the String object with fewer mallocs. To optimize string
+ * length and indexing operations, this structure also stores the number of
+ * characters (same of UTF and Unicode!) once that value has been computed.
+ *
+ * Under normal configurations, what Tcl calls "Unicode" is actually UTF-16
+ * restricted to the Basic Multilingual Plane (i.e. U+00000 to U+0FFFF). This
+ * can be officially modified by altering the definition of Tcl_UniChar in
+ * tcl.h, but do not do that unless you are sure what you're doing!
*/
typedef struct String {
- int numChars; /* The number of chars in the string.
- * -1 means this value has not been
- * calculated. >= 0 means that there is a
- * valid Unicode rep, or that the number
- * of UTF bytes == the number of chars. */
- size_t allocated; /* The amount of space actually allocated
- * for the UTF string (minus 1 byte for
- * the termination char). */
- size_t uallocated; /* The amount of space actually allocated
- * for the Unicode string (minus 2 bytes for
- * the termination char). */
- int hasUnicode; /* Boolean determining whether the string
- * has a Unicode representation. */
- Tcl_UniChar unicode[2]; /* The array of Unicode chars. The actual
- * size of this field depends on the
- * 'uallocated' field above. */
+ int numChars; /* The number of chars in the string. -1 means
+ * this value has not been calculated. >= 0
+ * means that there is a valid Unicode rep, or
+ * that the number of UTF bytes == the number
+ * of chars. */
+ size_t allocated; /* The amount of space actually allocated for
+ * the UTF string (minus 1 byte for the
+ * termination char). */
+ size_t uallocated; /* The amount of space actually allocated for
+ * the Unicode string (minus 2 bytes for the
+ * termination char). */
+ int hasUnicode; /* Boolean determining whether the string has
+ * a Unicode representation. */
+ Tcl_UniChar unicode[2]; /* The array of Unicode chars. The actual size
+ * of this field depends on the 'uallocated'
+ * field above. */
} String;
#define STRING_MAXCHARS \
@@ -125,9 +128,9 @@ typedef struct String {
(String *) attemptckrealloc((char *) ptr, \
(unsigned) STRING_SIZE(STRING_UALLOC(numChars)) )
#define GET_STRING(objPtr) \
- ((String *) (objPtr)->internalRep.otherValuePtr)
+ ((String *) (objPtr)->internalRep.otherValuePtr)
#define SET_STRING(objPtr, stringPtr) \
- (objPtr)->internalRep.otherValuePtr = (VOID *) (stringPtr)
+ ((objPtr)->internalRep.otherValuePtr = (void *) (stringPtr))
/*
* TCL STRING GROWTH ALGORITHM
@@ -138,31 +141,31 @@ typedef struct String {
* Attempt to allocate 2 * (originalLength + appendLength)
* On failure:
* attempt to allocate originalLength + 2*appendLength +
- * TCL_GROWTH_MIN_ALLOC
+ * TCL_GROWTH_MIN_ALLOC
*
* This algorithm allows very good performance, as it rapidly increases the
* memory allocated for a given string, which minimizes the number of
- * reallocations that must be performed. However, using only the doubling
- * algorithm can lead to a significant waste of memory. In particular, it
- * may fail even when there is sufficient memory available to complete the
- * append request (but there is not 2 * totalLength memory available). So when
- * the doubling fails (because there is not enough memory available), the
+ * reallocations that must be performed. However, using only the doubling
+ * algorithm can lead to a significant waste of memory. In particular, it may
+ * fail even when there is sufficient memory available to complete the append
+ * request (but there is not 2*totalLength memory available). So when the
+ * doubling fails (because there is not enough memory available), the
* algorithm requests a smaller amount of memory, which is still enough to
- * cover the request, but which hopefully will be less than the total available
- * memory.
- *
- * The addition of TCL_GROWTH_MIN_ALLOC allows for efficient handling
- * of very small appends. Without this extra slush factor, a sequence
- * of several small appends would cause several memory allocations.
- * As long as TCL_GROWTH_MIN_ALLOC is a reasonable size, we can
- * avoid that behavior.
+ * cover the request, but which hopefully will be less than the total
+ * available memory.
+ *
+ * The addition of TCL_GROWTH_MIN_ALLOC allows for efficient handling of very
+ * small appends. Without this extra slush factor, a sequence of several small
+ * appends would cause several memory allocations. As long as
+ * TCL_GROWTH_MIN_ALLOC is a reasonable size, we can avoid that behavior.
*
* The growth algorithm can be tuned by adjusting the following parameters:
*
* TCL_GROWTH_MIN_ALLOC Additional space, in bytes, to allocate when
- * the double allocation has failed.
- * Default is 1024 (1 kilobyte).
+ * the double allocation has failed. Default is
+ * 1024 (1 kilobyte).
*/
+
#ifndef TCL_GROWTH_MIN_ALLOC
#define TCL_GROWTH_MIN_ALLOC 1024
#endif
@@ -215,60 +218,55 @@ GrowUnicodeBuffer(
*
* Tcl_NewStringObj --
*
- * This procedure is normally called when not debugging: i.e., when
+ * This function is normally called when not debugging: i.e., when
* TCL_MEM_DEBUG is not defined. It creates a new string object and
* initializes it from the byte pointer and length arguments.
*
- * When TCL_MEM_DEBUG is defined, this procedure just returns the
- * result of calling the debugging version Tcl_DbNewStringObj.
+ * When TCL_MEM_DEBUG is defined, this function just returns the result
+ * of calling the debugging version Tcl_DbNewStringObj.
*
* Results:
* A newly created string object is returned that has ref count zero.
*
* Side effects:
- * The new object's internal string representation will be set to a
- * copy of the length bytes starting at "bytes". If "length" is
- * negative, use bytes up to the first NULL byte; i.e., assume "bytes"
- * points to a C-style NULL-terminated string. The object's type is set
- * to NULL. An extra NULL is added to the end of the new object's byte
- * array.
+ * The new object's internal string representation will be set to a copy
+ * of the length bytes starting at "bytes". If "length" is negative, use
+ * bytes up to the first NUL byte; i.e., assume "bytes" points to a
+ * C-style NUL-terminated string. The object's type is set to NULL. An
+ * extra NUL is added to the end of the new object's byte array.
*
*----------------------------------------------------------------------
*/
#ifdef TCL_MEM_DEBUG
#undef Tcl_NewStringObj
-
Tcl_Obj *
-Tcl_NewStringObj(bytes, length)
- CONST char *bytes; /* Points to the first of the length bytes
+Tcl_NewStringObj(
+ const char *bytes, /* Points to the first of the length bytes
* used to initialize the new object. */
- int length; /* The number of bytes to copy from "bytes"
- * when initializing the new object. If
- * negative, use bytes up to the first
- * NULL byte. */
+ int length) /* The number of bytes to copy from "bytes"
+ * when initializing the new object. If
+ * negative, use bytes up to the first NUL
+ * byte. */
{
return Tcl_DbNewStringObj(bytes, length, "unknown", 0);
}
-
#else /* if not TCL_MEM_DEBUG */
-
Tcl_Obj *
-Tcl_NewStringObj(bytes, length)
- CONST char *bytes; /* Points to the first of the length bytes
+Tcl_NewStringObj(
+ const char *bytes, /* Points to the first of the length bytes
* used to initialize the new object. */
- int length; /* The number of bytes to copy from "bytes"
- * when initializing the new object. If
- * negative, use bytes up to the first
- * NULL byte. */
+ int length) /* The number of bytes to copy from "bytes"
+ * when initializing the new object. If
+ * negative, use bytes up to the first NUL
+ * byte. */
{
register Tcl_Obj *objPtr;
if (length < 0) {
length = (bytes? strlen(bytes) : 0);
}
- TclNewObj(objPtr);
- TclInitStringRep(objPtr, bytes, length);
+ TclNewStringObj(objPtr, bytes, length);
return objPtr;
}
#endif /* TCL_MEM_DEBUG */
@@ -278,45 +276,43 @@ Tcl_NewStringObj(bytes, length)
*
* Tcl_DbNewStringObj --
*
- * This procedure is normally called when debugging: i.e., when
+ * This function is normally called when debugging: i.e., when
* TCL_MEM_DEBUG is defined. It creates new string objects. It is the
- * same as the Tcl_NewStringObj procedure above except that it calls
+ * same as the Tcl_NewStringObj function above except that it calls
* Tcl_DbCkalloc directly with the file name and line number from its
* caller. This simplifies debugging since then the [memory active]
- * command will report the correct file name and line number when
+ * command will report the correct file name and line number when
* reporting objects that haven't been freed.
*
- * When TCL_MEM_DEBUG is not defined, this procedure just returns the
+ * When TCL_MEM_DEBUG is not defined, this function just returns the
* result of calling Tcl_NewStringObj.
*
* Results:
* A newly created string object is returned that has ref count zero.
*
* Side effects:
- * The new object's internal string representation will be set to a
- * copy of the length bytes starting at "bytes". If "length" is
- * negative, use bytes up to the first NULL byte; i.e., assume "bytes"
- * points to a C-style NULL-terminated string. The object's type is set
- * to NULL. An extra NULL is added to the end of the new object's byte
- * array.
+ * The new object's internal string representation will be set to a copy
+ * of the length bytes starting at "bytes". If "length" is negative, use
+ * bytes up to the first NUL byte; i.e., assume "bytes" points to a
+ * C-style NUL-terminated string. The object's type is set to NULL. An
+ * extra NUL is added to the end of the new object's byte array.
*
*----------------------------------------------------------------------
*/
#ifdef TCL_MEM_DEBUG
-
Tcl_Obj *
-Tcl_DbNewStringObj(bytes, length, file, line)
- CONST char *bytes; /* Points to the first of the length bytes
+Tcl_DbNewStringObj(
+ const char *bytes, /* Points to the first of the length bytes
* used to initialize the new object. */
- int length; /* The number of bytes to copy from "bytes"
- * when initializing the new object. If
- * negative, use bytes up to the first
- * NULL byte. */
- CONST char *file; /* The name of the source file calling this
- * procedure; used for debugging. */
- int line; /* Line number in the source file; used
- * for debugging. */
+ int length, /* The number of bytes to copy from "bytes"
+ * when initializing the new object. If
+ * negative, use bytes up to the first NUL
+ * byte. */
+ const char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
register Tcl_Obj *objPtr;
@@ -327,21 +323,19 @@ Tcl_DbNewStringObj(bytes, length, file, line)
TclInitStringRep(objPtr, bytes, length);
return objPtr;
}
-
#else /* if not TCL_MEM_DEBUG */
-
Tcl_Obj *
-Tcl_DbNewStringObj(bytes, length, file, line)
- CONST char *bytes; /* Points to the first of the length bytes
+Tcl_DbNewStringObj(
+ const char *bytes, /* Points to the first of the length bytes
* used to initialize the new object. */
- register int length; /* The number of bytes to copy from "bytes"
- * when initializing the new object. If
- * negative, use bytes up to the first
- * NULL byte. */
- CONST char *file; /* The name of the source file calling this
- * procedure; used for debugging. */
- int line; /* Line number in the source file; used
- * for debugging. */
+ register int length, /* The number of bytes to copy from "bytes"
+ * when initializing the new object. If
+ * negative, use bytes up to the first NUL
+ * byte. */
+ const char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
return Tcl_NewStringObj(bytes, length);
}
@@ -352,14 +346,13 @@ Tcl_DbNewStringObj(bytes, length, file, line)
*
* Tcl_NewUnicodeObj --
*
- * This procedure is creates a new String object and initializes
- * it from the given Unicode String. If the Utf String is the same size
- * as the Unicode string, don't duplicate the data.
+ * This function is creates a new String object and initializes it from
+ * the given Unicode String. If the Utf String is the same size as the
+ * Unicode string, don't duplicate the data.
*
* Results:
- * The newly created object is returned. This object will have no
- * initial string representation. The returned object has a ref count
- * of 0.
+ * The newly created object is returned. This object will have no initial
+ * string representation. The returned object has a ref count of 0.
*
* Side effects:
* Memory allocated for new object and copy of Unicode argument.
@@ -368,10 +361,10 @@ Tcl_DbNewStringObj(bytes, length, file, line)
*/
Tcl_Obj *
-Tcl_NewUnicodeObj(unicode, numChars)
- CONST Tcl_UniChar *unicode; /* The unicode string used to initialize
- * the new object. */
- int numChars; /* Number of characters in the unicode
+Tcl_NewUnicodeObj(
+ const Tcl_UniChar *unicode, /* The unicode string used to initialize the
+ * new object. */
+ int numChars) /* Number of characters in the unicode
* string. */
{
Tcl_Obj *objPtr;
@@ -392,60 +385,63 @@ Tcl_NewUnicodeObj(unicode, numChars)
* Pointer to unicode string representing the unicode object.
*
* Side effects:
- * Frees old internal rep. Allocates memory for new "String"
- * internal rep.
+ * Frees old internal rep. Allocates memory for new "String" internal
+ * rep.
*
*----------------------------------------------------------------------
*/
int
-Tcl_GetCharLength(objPtr)
- Tcl_Obj *objPtr; /* The String object to get the num chars of. */
+Tcl_GetCharLength(
+ Tcl_Obj *objPtr) /* The String object to get the num chars
+ * of. */
{
String *stringPtr;
-
+
SetStringFromAny(NULL, objPtr);
stringPtr = GET_STRING(objPtr);
/*
- * If numChars is unknown, then calculate the number of characaters
- * while populating the Unicode string.
+ * If numChars is unknown, then calculate the number of characaters while
+ * populating the Unicode string.
*/
-
+
if (stringPtr->numChars == -1) {
register int i = objPtr->length;
register unsigned char *str = (unsigned char *) objPtr->bytes;
/*
* This is a speed sensitive function, so run specially over the
- * string to count continuous ascii characters before resorting
- * to the Tcl_NumUtfChars call. This is a long form of:
- stringPtr->numChars = Tcl_NumUtfChars(objPtr->bytes, objPtr->length);
- */
+ * string to count continuous ascii characters before resorting to the
+ * Tcl_NumUtfChars call. This is a long form of:
+ stringPtr->numChars = Tcl_NumUtfChars(objPtr->bytes,objPtr->length);
+ *
+ * TODO: Consider macro-izing this.
+ */
- while (i && (*str < 0xC0)) { i--; str++; }
+ while (i && (*str < 0xC0)) {
+ i--;
+ str++;
+ }
stringPtr->numChars = objPtr->length - i;
if (i) {
stringPtr->numChars += Tcl_NumUtfChars(objPtr->bytes
+ (objPtr->length - i), i);
}
- if (stringPtr->numChars == objPtr->length) {
-
+ if (stringPtr->numChars == objPtr->length) {
/*
- * Since we've just calculated the number of chars, and all
- * UTF chars are 1-byte long, we don't need to store the
- * unicode string.
+ * Since we've just calculated the number of chars, and all UTF
+ * chars are 1-byte long, we don't need to store the unicode
+ * string.
*/
stringPtr->hasUnicode = 0;
-
} else {
-
/*
- * Since we've just calucalated the number of chars, and not
- * all UTF chars are 1-byte long, go ahead and populate the
- * unicode string.
+ * Since we've just calucalated the number of chars, and not all
+ * UTF chars are 1-byte long, go ahead and populate the unicode
+ * string.
*/
FillUnicodeRep(objPtr);
@@ -454,7 +450,7 @@ Tcl_GetCharLength(objPtr)
* We need to fetch the pointer again because we have just
* reallocated the structure to make room for the Unicode data.
*/
-
+
stringPtr = GET_STRING(objPtr);
}
}
@@ -466,8 +462,8 @@ Tcl_GetCharLength(objPtr)
*
* Tcl_GetUniChar --
*
- * Get the index'th Unicode character from the String object. The
- * index is assumed to be in the appropriate range.
+ * Get the index'th Unicode character from the String object. The index
+ * is assumed to be in the appropriate range.
*
* Results:
* Returns the index'th Unicode character in the Object.
@@ -479,22 +475,21 @@ Tcl_GetCharLength(objPtr)
*/
Tcl_UniChar
-Tcl_GetUniChar(objPtr, index)
- Tcl_Obj *objPtr; /* The object to get the Unicode charater from. */
- int index; /* Get the index'th Unicode character. */
+Tcl_GetUniChar(
+ Tcl_Obj *objPtr, /* The object to get the Unicode charater
+ * from. */
+ int index) /* Get the index'th Unicode character. */
{
Tcl_UniChar unichar;
String *stringPtr;
-
+
SetStringFromAny(NULL, objPtr);
stringPtr = GET_STRING(objPtr);
if (stringPtr->numChars == -1) {
-
/*
- * We haven't yet calculated the length, so we don't have the
- * Unicode str. We need to know the number of chars before we
- * can do indexing.
+ * We haven't yet calculated the length, so we don't have the Unicode
+ * str. We need to know the number of chars before we can do indexing.
*/
Tcl_GetCharLength(objPtr);
@@ -503,15 +498,14 @@ Tcl_GetUniChar(objPtr, index)
* We need to fetch the pointer again because we may have just
* reallocated the structure.
*/
-
+
stringPtr = GET_STRING(objPtr);
}
if (stringPtr->hasUnicode == 0) {
-
/*
- * All of the characters in the Utf string are 1 byte chars,
- * so we don't store the unicode char. We get the Utf string
- * and convert the index'th byte to a Unicode character.
+ * All of the characters in the Utf string are 1 byte chars, so we
+ * don't store the unicode char. We get the Utf string and convert the
+ * index'th byte to a Unicode character.
*/
unichar = (Tcl_UniChar) objPtr->bytes[index];
@@ -526,10 +520,10 @@ Tcl_GetUniChar(objPtr, index)
*
* Tcl_GetUnicode --
*
- * Get the Unicode form of the String object. If
- * the object is not already a String object, it will be converted
- * to one. If the String object does not have a Unicode rep, then
- * one is create from the UTF string format.
+ * Get the Unicode form of the String object. If the object is not
+ * already a String object, it will be converted to one. If the String
+ * object does not have a Unicode rep, then one is create from the UTF
+ * string format.
*
* Results:
* Returns a pointer to the object's internal Unicode string.
@@ -541,31 +535,31 @@ Tcl_GetUniChar(objPtr, index)
*/
Tcl_UniChar *
-Tcl_GetUnicode(objPtr)
- Tcl_Obj *objPtr; /* The object to find the unicode string for. */
+Tcl_GetUnicode(
+ Tcl_Obj *objPtr) /* The object to find the unicode string
+ * for. */
{
String *stringPtr;
-
+
SetStringFromAny(NULL, objPtr);
stringPtr = GET_STRING(objPtr);
-
- if ((stringPtr->numChars == -1) || (stringPtr->hasUnicode == 0)) {
+ if ((stringPtr->numChars == -1) || (stringPtr->hasUnicode == 0)) {
/*
- * We haven't yet calculated the length, or all of the characters
- * in the Utf string are 1 byte chars (so we didn't store the
- * unicode str). Since this function must return a unicode string,
- * and one has not yet been stored, force the Unicode to be
- * calculated and stored now.
+ * We haven't yet calculated the length, or all of the characters in
+ * the Utf string are 1 byte chars (so we didn't store the unicode
+ * str). Since this function must return a unicode string, and one has
+ * not yet been stored, force the Unicode to be calculated and stored
+ * now.
*/
FillUnicodeRep(objPtr);
/*
- * We need to fetch the pointer again because we have just
- * reallocated the structure to make room for the Unicode data.
+ * We need to fetch the pointer again because we have just reallocated
+ * the structure to make room for the Unicode data.
*/
-
+
stringPtr = GET_STRING(objPtr);
}
return stringPtr->unicode;
@@ -576,10 +570,10 @@ Tcl_GetUnicode(objPtr)
*
* Tcl_GetUnicodeFromObj --
*
- * Get the Unicode form of the String object with length. If
- * the object is not already a String object, it will be converted
- * to one. If the String object does not have a Unicode rep, then
- * one is create from the UTF string format.
+ * Get the Unicode form of the String object with length. If the object
+ * is not already a String object, it will be converted to one. If the
+ * String object does not have a Unicode rep, then one is create from the
+ * UTF string format.
*
* Results:
* Returns a pointer to the object's internal Unicode string.
@@ -591,34 +585,34 @@ Tcl_GetUnicode(objPtr)
*/
Tcl_UniChar *
-Tcl_GetUnicodeFromObj(objPtr, lengthPtr)
- Tcl_Obj *objPtr; /* The object to find the unicode string for. */
- int *lengthPtr; /* If non-NULL, the location where the
- * string rep's unichar length should be
- * stored. If NULL, no length is stored. */
+Tcl_GetUnicodeFromObj(
+ Tcl_Obj *objPtr, /* The object to find the unicode string
+ * for. */
+ int *lengthPtr) /* If non-NULL, the location where the string
+ * rep's unichar length should be stored. If
+ * NULL, no length is stored. */
{
String *stringPtr;
-
+
SetStringFromAny(NULL, objPtr);
stringPtr = GET_STRING(objPtr);
-
- if ((stringPtr->numChars == -1) || (stringPtr->hasUnicode == 0)) {
+ if ((stringPtr->numChars == -1) || (stringPtr->hasUnicode == 0)) {
/*
- * We haven't yet calculated the length, or all of the characters
- * in the Utf string are 1 byte chars (so we didn't store the
- * unicode str). Since this function must return a unicode string,
- * and one has not yet been stored, force the Unicode to be
- * calculated and stored now.
+ * We haven't yet calculated the length, or all of the characters in
+ * the Utf string are 1 byte chars (so we didn't store the unicode
+ * str). Since this function must return a unicode string, and one has
+ * not yet been stored, force the Unicode to be calculated and stored
+ * now.
*/
FillUnicodeRep(objPtr);
/*
- * We need to fetch the pointer again because we have just
- * reallocated the structure to make room for the Unicode data.
+ * We need to fetch the pointer again because we have just reallocated
+ * the structure to make room for the Unicode data.
*/
-
+
stringPtr = GET_STRING(objPtr);
}
@@ -633,10 +627,10 @@ Tcl_GetUnicodeFromObj(objPtr, lengthPtr)
*
* Tcl_GetRange --
*
- * Create a Tcl Object that contains the chars between first and last
- * of the object indicated by "objPtr". If the object is not already
- * a String object, convert it to one. The first and last indices
- * are assumed to be in the appropriate range.
+ * Create a Tcl Object that contains the chars between first and last of
+ * the object indicated by "objPtr". If the object is not already a
+ * String object, convert it to one. The first and last indices are
+ * assumed to be in the appropriate range.
*
* Results:
* Returns a new Tcl Object of the String type.
@@ -648,23 +642,21 @@ Tcl_GetUnicodeFromObj(objPtr, lengthPtr)
*/
Tcl_Obj *
-Tcl_GetRange(objPtr, first, last)
- Tcl_Obj *objPtr; /* The Tcl object to find the range of. */
- int first; /* First index of the range. */
- int last; /* Last index of the range. */
+Tcl_GetRange(
+ Tcl_Obj *objPtr, /* The Tcl object to find the range of. */
+ int first, /* First index of the range. */
+ int last) /* Last index of the range. */
{
Tcl_Obj *newObjPtr; /* The Tcl object to find the range of. */
String *stringPtr;
-
+
SetStringFromAny(NULL, objPtr);
stringPtr = GET_STRING(objPtr);
if (stringPtr->numChars == -1) {
-
/*
- * We haven't yet calculated the length, so we don't have the
- * Unicode str. We need to know the number of chars before we
- * can do indexing.
+ * We haven't yet calculated the length, so we don't have the Unicode
+ * str. We need to know the number of chars before we can do indexing.
*/
Tcl_GetCharLength(objPtr);
@@ -673,26 +665,26 @@ Tcl_GetRange(objPtr, first, last)
* We need to fetch the pointer again because we may have just
* reallocated the structure.
*/
-
+
stringPtr = GET_STRING(objPtr);
}
- if (objPtr->bytes && stringPtr->numChars == objPtr->length) {
- char *str = Tcl_GetString(objPtr);
+ if (objPtr->bytes && (stringPtr->numChars == objPtr->length)) {
+ char *str = TclGetString(objPtr);
/*
- * All of the characters in the Utf string are 1 byte chars,
- * so we don't store the unicode char. Create a new string
- * object containing the specified range of chars.
+ * All of the characters in the Utf string are 1 byte chars, so we
+ * don't store the unicode char. Create a new string object containing
+ * the specified range of chars.
*/
-
+
newObjPtr = Tcl_NewStringObj(&str[first], last-first+1);
/*
- * Since we know the new string only has 1-byte chars, we
- * can set it's numChars field.
+ * Since we know the new string only has 1-byte chars, we can set it's
+ * numChars field.
*/
-
+
SetStringFromAny(NULL, newObjPtr);
stringPtr = GET_STRING(newObjPtr);
stringPtr->numChars = last-first+1;
@@ -709,49 +701,44 @@ Tcl_GetRange(objPtr, first, last)
* Tcl_SetStringObj --
*
* Modify an object to hold a string that is a copy of the bytes
- * indicated by the byte pointer and length arguments.
+ * indicated by the byte pointer and length arguments.
*
* Results:
* None.
*
* Side effects:
- * The object's string representation will be set to a copy of
- * the "length" bytes starting at "bytes". If "length" is negative, use
- * bytes up to the first NULL byte; i.e., assume "bytes" points to a
- * C-style NULL-terminated string. The object's old string and internal
+ * The object's string representation will be set to a copy of the
+ * "length" bytes starting at "bytes". If "length" is negative, use bytes
+ * up to the first NUL byte; i.e., assume "bytes" points to a C-style
+ * NUL-terminated string. The object's old string and internal
* representations are freed and the object's type is set NULL.
*
*----------------------------------------------------------------------
*/
void
-Tcl_SetStringObj(objPtr, bytes, length)
- register Tcl_Obj *objPtr; /* Object whose internal rep to init. */
- CONST char *bytes; /* Points to the first of the length bytes
+Tcl_SetStringObj(
+ register Tcl_Obj *objPtr, /* Object whose internal rep to init. */
+ const char *bytes, /* Points to the first of the length bytes
* used to initialize the object. */
- register int length; /* The number of bytes to copy from "bytes"
- * when initializing the object. If
- * negative, use bytes up to the first
- * NULL byte.*/
+ register int length) /* The number of bytes to copy from "bytes"
+ * when initializing the object. If negative,
+ * use bytes up to the first NUL byte.*/
{
- register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
-
if (Tcl_IsShared(objPtr)) {
- panic("Tcl_SetStringObj called with shared object");
+ Tcl_Panic("%s called with shared object", "Tcl_SetStringObj");
}
/*
* Set the type to NULL and free any internal rep for the old type.
*/
- if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
- oldTypePtr->freeIntRepProc(objPtr);
- }
+ TclFreeIntRep(objPtr);
objPtr->typePtr = NULL;
/*
- * Free any old string rep, then set the string rep to a copy of
- * the length bytes starting at "bytes".
+ * Free any old string rep, then set the string rep to a copy of the
+ * length bytes starting at "bytes".
*/
Tcl_InvalidateStringRep(objPtr);
@@ -766,30 +753,29 @@ Tcl_SetStringObj(objPtr, bytes, length)
*
* Tcl_SetObjLength --
*
- * This procedure changes the length of the string representation
- * of an object.
+ * This function changes the length of the string representation of an
+ * object.
*
* Results:
* None.
*
* Side effects:
- * If the size of objPtr's string representation is greater than
- * length, then it is reduced to length and a new terminating null
- * byte is stored in the strength. If the length of the string
- * representation is greater than length, the storage space is
- * reallocated to the given length; a null byte is stored at the
- * end, but other bytes past the end of the original string
- * representation are undefined. The object's internal
+ * If the size of objPtr's string representation is greater than length,
+ * then it is reduced to length and a new terminating null byte is stored
+ * in the strength. If the length of the string representation is greater
+ * than length, the storage space is reallocated to the given length; a
+ * null byte is stored at the end, but other bytes past the end of the
+ * original string representation are undefined. The object's internal
* representation is changed to "expendable string".
*
*----------------------------------------------------------------------
*/
void
-Tcl_SetObjLength(objPtr, length)
- register Tcl_Obj *objPtr; /* Pointer to object. This object must
- * not currently be shared. */
- register int length; /* Number of bytes desired for string
+Tcl_SetObjLength(
+ register Tcl_Obj *objPtr, /* Pointer to object. This object must not
+ * currently be shared. */
+ register int length) /* Number of bytes desired for string
* representation of object, not including
* terminating null byte. */
{
@@ -804,64 +790,83 @@ Tcl_SetObjLength(objPtr, length)
"%d (integer overflow?)", length);
}
if (Tcl_IsShared(objPtr)) {
- panic("Tcl_SetObjLength called with shared object");
+ Tcl_Panic("%s called with shared object", "Tcl_SetObjLength");
}
SetStringFromAny(NULL, objPtr);
-
+
stringPtr = GET_STRING(objPtr);
-
- /* Check that we're not extending a pure unicode string */
-
- if ((size_t)length > stringPtr->allocated &&
- (objPtr->bytes != NULL || stringPtr->hasUnicode == 0)) {
- char *new;
+ /*
+ * Check that we're not extending a pure unicode string.
+ */
+
+ if ((size_t)length > stringPtr->allocated &&
+ (objPtr->bytes != NULL || stringPtr->hasUnicode == 0)) {
/*
- * Not enough space in current string. Reallocate the string
- * space and free the old string.
+ * Not enough space in current string. Reallocate the string space and
+ * free the old string.
*/
- if (objPtr->bytes != tclEmptyStringRep && objPtr->bytes != NULL) {
- new = (char *) ckrealloc((char *)objPtr->bytes,
- (unsigned)(length+1));
+
+ if (objPtr->bytes != tclEmptyStringRep) {
+ objPtr->bytes = ckrealloc((char *) objPtr->bytes,
+ (unsigned) (length + 1));
} else {
- new = (char *) ckalloc((unsigned) (length+1));
+ char *newBytes = ckalloc((unsigned) (length+1));
+
if (objPtr->bytes != NULL && objPtr->length != 0) {
- memcpy((VOID *) new, (VOID *) objPtr->bytes,
- (size_t) objPtr->length);
+ memcpy(newBytes, objPtr->bytes, (size_t) objPtr->length);
Tcl_InvalidateStringRep(objPtr);
}
+ objPtr->bytes = newBytes;
}
- objPtr->bytes = new;
stringPtr->allocated = length;
- /* Invalidate the unicode data. */
+
+ /*
+ * Invalidate the unicode data.
+ */
+
stringPtr->hasUnicode = 0;
}
-
+
if (objPtr->bytes != NULL) {
- objPtr->length = length;
- if (objPtr->bytes != tclEmptyStringRep) {
- /* Ensure the string is NULL-terminated */
- objPtr->bytes[length] = 0;
- }
- /* Invalidate the unicode data. */
- stringPtr->numChars = -1;
- stringPtr->hasUnicode = 0;
+ objPtr->length = length;
+ if (objPtr->bytes != tclEmptyStringRep) {
+ /*
+ * Ensure the string is NUL-terminated.
+ */
+
+ objPtr->bytes[length] = 0;
+ }
+
+ /*
+ * Invalidate the unicode data.
+ */
+
+ stringPtr->numChars = -1;
+ stringPtr->hasUnicode = 0;
} else {
- /* Changing length of pure unicode string */
- size_t uallocated = STRING_UALLOC(length);
+ /*
+ * Changing length of pure unicode string.
+ */
+
+ size_t uallocated = STRING_UALLOC(length);
stringCheckLimits(length);
- if (uallocated > stringPtr->uallocated) {
+ if (uallocated > stringPtr->uallocated) {
stringPtr = stringRealloc(stringPtr, length);
- SET_STRING(objPtr, stringPtr);
- stringPtr->uallocated = uallocated;
- }
- stringPtr->numChars = length;
- stringPtr->hasUnicode = (length > 0);
- /* Ensure the string is NULL-terminated */
- stringPtr->unicode[length] = 0;
- stringPtr->allocated = 0;
- objPtr->length = 0;
+ SET_STRING(objPtr, stringPtr);
+ stringPtr->uallocated = uallocated;
+ }
+ stringPtr->numChars = length;
+ stringPtr->hasUnicode = (length > 0);
+
+ /*
+ * Ensure the string is NUL-terminated.
+ */
+
+ stringPtr->unicode[length] = 0;
+ stringPtr->allocated = 0;
+ objPtr->length = 0;
}
}
@@ -870,30 +875,29 @@ Tcl_SetObjLength(objPtr, length)
*
* Tcl_AttemptSetObjLength --
*
- * This procedure changes the length of the string representation
- * of an object. It uses the attempt* (non-panic'ing) memory allocators.
+ * This function changes the length of the string representation of an
+ * object. It uses the attempt* (non-panic'ing) memory allocators.
*
* Results:
* 1 if the requested memory was allocated, 0 otherwise.
*
* Side effects:
- * If the size of objPtr's string representation is greater than
- * length, then it is reduced to length and a new terminating null
- * byte is stored in the strength. If the length of the string
- * representation is greater than length, the storage space is
- * reallocated to the given length; a null byte is stored at the
- * end, but other bytes past the end of the original string
- * representation are undefined. The object's internal
+ * If the size of objPtr's string representation is greater than length,
+ * then it is reduced to length and a new terminating null byte is stored
+ * in the strength. If the length of the string representation is greater
+ * than length, the storage space is reallocated to the given length; a
+ * null byte is stored at the end, but other bytes past the end of the
+ * original string representation are undefined. The object's internal
* representation is changed to "expendable string".
*
*----------------------------------------------------------------------
*/
int
-Tcl_AttemptSetObjLength(objPtr, length)
- register Tcl_Obj *objPtr; /* Pointer to object. This object must
- * not currently be shared. */
- register int length; /* Number of bytes desired for string
+Tcl_AttemptSetObjLength(
+ register Tcl_Obj *objPtr, /* Pointer to object. This object must not
+ * currently be shared. */
+ register int length) /* Number of bytes desired for string
* representation of object, not including
* terminating null byte. */
{
@@ -907,56 +911,72 @@ Tcl_AttemptSetObjLength(objPtr, length)
return 0;
}
if (Tcl_IsShared(objPtr)) {
- panic("Tcl_AttemptSetObjLength called with shared object");
+ Tcl_Panic("%s called with shared object", "Tcl_AttemptSetObjLength");
}
SetStringFromAny(NULL, objPtr);
-
+
stringPtr = GET_STRING(objPtr);
- /* Check that we're not extending a pure unicode string */
+ /*
+ * Check that we're not extending a pure unicode string.
+ */
- if (length > (int) stringPtr->allocated &&
+ if (length > (int) stringPtr->allocated &&
(objPtr->bytes != NULL || stringPtr->hasUnicode == 0)) {
- char *new;
+ char *newBytes;
/*
- * Not enough space in current string. Reallocate the string
- * space and free the old string.
+ * Not enough space in current string. Reallocate the string space and
+ * free the old string.
*/
- if (objPtr->bytes != tclEmptyStringRep && objPtr->bytes != NULL) {
- new = (char *) attemptckrealloc((char *)objPtr->bytes,
- (unsigned)(length+1));
- if (new == NULL) {
+
+ if (objPtr->bytes != tclEmptyStringRep) {
+ newBytes = attemptckrealloc(objPtr->bytes,
+ (unsigned)(length + 1));
+ if (newBytes == NULL) {
return 0;
}
} else {
- new = (char *) attemptckalloc((unsigned) (length+1));
- if (new == NULL) {
+ newBytes = attemptckalloc((unsigned) (length + 1));
+ if (newBytes == NULL) {
return 0;
}
if (objPtr->bytes != NULL && objPtr->length != 0) {
- memcpy((VOID *) new, (VOID *) objPtr->bytes,
- (size_t) objPtr->length);
- Tcl_InvalidateStringRep(objPtr);
+ memcpy(newBytes, objPtr->bytes, (size_t) objPtr->length);
+ Tcl_InvalidateStringRep(objPtr);
}
}
- objPtr->bytes = new;
+ objPtr->bytes = newBytes;
stringPtr->allocated = length;
- /* Invalidate the unicode data. */
+
+ /*
+ * Invalidate the unicode data.
+ */
+
stringPtr->hasUnicode = 0;
}
-
+
if (objPtr->bytes != NULL) {
objPtr->length = length;
if (objPtr->bytes != tclEmptyStringRep) {
- /* Ensure the string is NULL-terminated */
+ /*
+ * Ensure the string is NULL-terminated.
+ */
+
objPtr->bytes[length] = 0;
}
- /* Invalidate the unicode data. */
+
+ /*
+ * Invalidate the unicode data.
+ */
+
stringPtr->numChars = -1;
stringPtr->hasUnicode = 0;
} else {
- /* Changing length of pure unicode string */
+ /*
+ * Changing length of pure unicode string.
+ */
+
size_t uallocated = STRING_UALLOC(length);
if (length > STRING_MAXCHARS) {
return 0;
@@ -965,14 +985,18 @@ Tcl_AttemptSetObjLength(objPtr, length)
if (uallocated > stringPtr->uallocated) {
stringPtr = stringAttemptRealloc(stringPtr, length);
if (stringPtr == NULL) {
- return 0;
+ return 0;
}
SET_STRING(objPtr, stringPtr);
stringPtr->uallocated = uallocated;
}
stringPtr->numChars = length;
stringPtr->hasUnicode = (length > 0);
- /* Ensure the string is NULL-terminated */
+
+ /*
+ * Ensure the string is NUL-terminated.
+ */
+
stringPtr->unicode[length] = 0;
stringPtr->allocated = 0;
objPtr->length = 0;
@@ -997,21 +1021,17 @@ Tcl_AttemptSetObjLength(objPtr, length)
*/
void
-Tcl_SetUnicodeObj(objPtr, unicode, numChars)
- Tcl_Obj *objPtr; /* The object to set the string of. */
- CONST Tcl_UniChar *unicode; /* The unicode string used to initialize
- * the object. */
- int numChars; /* Number of characters in the unicode
+Tcl_SetUnicodeObj(
+ Tcl_Obj *objPtr, /* The object to set the string of. */
+ const Tcl_UniChar *unicode, /* The unicode string used to initialize the
+ * object. */
+ int numChars) /* Number of characters in the unicode
* string. */
{
- Tcl_ObjType *typePtr = objPtr->typePtr;
-
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("%s called with shared object", "Tcl_SetUnicodeObj");
}
- if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
- typePtr->freeIntRepProc(objPtr);
- }
+ TclFreeIntRep(objPtr);
SetUnicodeObj(objPtr, unicode, numChars);
}
@@ -1031,11 +1051,11 @@ UnicodeLength(
}
static void
-SetUnicodeObj(objPtr, unicode, numChars)
- Tcl_Obj *objPtr; /* The object to set the string of. */
- CONST Tcl_UniChar *unicode; /* The unicode string used to initialize
- * the object. */
- int numChars; /* Number of characters in the unicode
+SetUnicodeObj(
+ Tcl_Obj *objPtr, /* The object to set the string of. */
+ const Tcl_UniChar *unicode, /* The unicode string used to initialize the
+ * object. */
+ int numChars) /* Number of characters in the unicode
* string. */
{
String *stringPtr;
@@ -1048,7 +1068,7 @@ SetUnicodeObj(objPtr, unicode, numChars)
/*
* Allocate enough space for the String structure + Unicode string.
*/
-
+
stringCheckLimits(numChars);
uallocated = STRING_UALLOC(numChars);
stringPtr = (String *) ckalloc(STRING_SIZE(uallocated));
@@ -1057,7 +1077,7 @@ SetUnicodeObj(objPtr, unicode, numChars)
stringPtr->uallocated = uallocated;
stringPtr->hasUnicode = (numChars > 0);
stringPtr->allocated = 0;
- memcpy((VOID *) stringPtr->unicode, (VOID *) unicode, uallocated);
+ memcpy(stringPtr->unicode, unicode, uallocated);
stringPtr->unicode[numChars] = 0;
Tcl_InvalidateStringRep(objPtr);
@@ -1068,35 +1088,42 @@ SetUnicodeObj(objPtr, unicode, numChars)
/*
*----------------------------------------------------------------------
*
- * Tcl_AppendToObj --
+ * Tcl_AppendLimitedToObj --
*
- * This procedure appends a sequence of bytes to an object.
+ * This function appends a limited number of bytes from a sequence of
+ * bytes to an object, marking any limitation with an ellipsis.
*
* Results:
* None.
*
* Side effects:
- * The bytes at *bytes are appended to the string representation
- * of objPtr.
+ * The bytes at *bytes are appended to the string representation of
+ * objPtr.
*
*----------------------------------------------------------------------
*/
void
-Tcl_AppendToObj(objPtr, bytes, length)
- register Tcl_Obj *objPtr; /* Points to the object to append to. */
- CONST char *bytes; /* Points to the bytes to append to the
+Tcl_AppendLimitedToObj(
+ register Tcl_Obj *objPtr, /* Points to the object to append to. */
+ const char *bytes, /* Points to the bytes to append to the
* object. */
- register int length; /* The number of bytes to append from
- * "bytes". If < 0, then append all bytes
- * up to NULL byte. */
+ register int length, /* The number of bytes available to be
+ * appended from "bytes". If < 0, then all
+ * bytes up to a NUL byte are available. */
+ register int limit, /* The maximum number of bytes to append to
+ * the object. */
+ const char *ellipsis) /* Ellipsis marker string, appended to the
+ * object to indicate not all available bytes
+ * at "bytes" were appended. */
{
String *stringPtr;
+ int toCopy = 0;
if (Tcl_IsShared(objPtr)) {
- panic("Tcl_AppendToObj called with shared object");
+ Tcl_Panic("%s called with shared object", "Tcl_AppendLimitedToObj");
}
-
+
SetStringFromAny(NULL, objPtr);
if (length < 0) {
@@ -1106,29 +1133,76 @@ Tcl_AppendToObj(objPtr, bytes, length)
return;
}
+ if (length <= limit) {
+ toCopy = length;
+ } else {
+ if (ellipsis == NULL) {
+ ellipsis = "...";
+ }
+ toCopy = Tcl_UtfPrev(bytes+limit+1-strlen(ellipsis), bytes) - bytes;
+ }
+
/*
- * If objPtr has a valid Unicode rep, then append the Unicode
- * conversion of "bytes" to the objPtr's Unicode rep, otherwise
- * append "bytes" to objPtr's string rep.
+ * If objPtr has a valid Unicode rep, then append the Unicode conversion
+ * of "bytes" to the objPtr's Unicode rep, otherwise append "bytes" to
+ * objPtr's string rep.
*/
stringPtr = GET_STRING(objPtr);
if (stringPtr->hasUnicode != 0) {
- AppendUtfToUnicodeRep(objPtr, bytes, length);
+ AppendUtfToUnicodeRep(objPtr, bytes, toCopy);
+ } else {
+ AppendUtfToUtfRep(objPtr, bytes, toCopy);
+ }
- stringPtr = GET_STRING(objPtr);
+ if (length <= limit) {
+ return;
+ }
+
+ stringPtr = GET_STRING(objPtr);
+ if (stringPtr->hasUnicode != 0) {
+ AppendUtfToUnicodeRep(objPtr, ellipsis, -1);
} else {
- AppendUtfToUtfRep(objPtr, bytes, length);
+ AppendUtfToUtfRep(objPtr, ellipsis, -1);
}
}
/*
*----------------------------------------------------------------------
*
+ * Tcl_AppendToObj --
+ *
+ * This function appends a sequence of bytes to an object.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The bytes at *bytes are appended to the string representation of
+ * objPtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_AppendToObj(
+ register Tcl_Obj *objPtr, /* Points to the object to append to. */
+ const char *bytes, /* Points to the bytes to append to the
+ * object. */
+ register int length) /* The number of bytes to append from "bytes".
+ * If < 0, then append all bytes up to NUL
+ * byte. */
+{
+ Tcl_AppendLimitedToObj(objPtr, bytes, length, INT_MAX, NULL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tcl_AppendUnicodeToObj --
*
- * This procedure appends a Unicode string to an object in the
- * most efficient manner possible. Length must be >= 0.
+ * This function appends a Unicode string to an object in the most
+ * efficient manner possible. Length must be >= 0.
*
* Results:
* None.
@@ -1140,16 +1214,16 @@ Tcl_AppendToObj(objPtr, bytes, length)
*/
void
-Tcl_AppendUnicodeToObj(objPtr, unicode, length)
- register Tcl_Obj *objPtr; /* Points to the object to append to. */
- CONST Tcl_UniChar *unicode; /* The unicode string to append to the
- * object. */
- int length; /* Number of chars in "unicode". */
+Tcl_AppendUnicodeToObj(
+ register Tcl_Obj *objPtr, /* Points to the object to append to. */
+ const Tcl_UniChar *unicode, /* The unicode string to append to the
+ * object. */
+ int length) /* Number of chars in "unicode". */
{
String *stringPtr;
if (Tcl_IsShared(objPtr)) {
- panic("Tcl_AppendUnicodeToObj called with shared object");
+ Tcl_Panic("%s called with shared object", "Tcl_AppendUnicodeToObj");
}
if (length == 0) {
@@ -1160,9 +1234,9 @@ Tcl_AppendUnicodeToObj(objPtr, unicode, length)
stringPtr = GET_STRING(objPtr);
/*
- * If objPtr has a valid Unicode rep, then append the "unicode"
- * to the objPtr's Unicode rep, otherwise the UTF conversion of
- * "unicode" to objPtr's string rep.
+ * If objPtr has a valid Unicode rep, then append the "unicode" to the
+ * objPtr's Unicode rep, otherwise the UTF conversion of "unicode" to
+ * objPtr's string rep.
*/
if (stringPtr->hasUnicode != 0) {
@@ -1177,23 +1251,23 @@ Tcl_AppendUnicodeToObj(objPtr, unicode, length)
*
* Tcl_AppendObjToObj --
*
- * This procedure appends the string rep of one object to another.
+ * This function appends the string rep of one object to another.
* "objPtr" cannot be a shared object.
*
* Results:
* None.
*
* Side effects:
- * The string rep of appendObjPtr is appended to the string
+ * The string rep of appendObjPtr is appended to the string
* representation of objPtr.
*
*----------------------------------------------------------------------
*/
void
-Tcl_AppendObjToObj(objPtr, appendObjPtr)
- Tcl_Obj *objPtr; /* Points to the object to append to. */
- Tcl_Obj *appendObjPtr; /* Object to append. */
+Tcl_AppendObjToObj(
+ Tcl_Obj *objPtr, /* Points to the object to append to. */
+ Tcl_Obj *appendObjPtr) /* Object to append. */
{
String *stringPtr;
int length, numChars, allOneByteChars;
@@ -1202,25 +1276,22 @@ Tcl_AppendObjToObj(objPtr, appendObjPtr)
SetStringFromAny(NULL, objPtr);
/*
- * If objPtr has a valid Unicode rep, then get a Unicode string
- * from appendObjPtr and append it.
+ * If objPtr has a valid Unicode rep, then get a Unicode string from
+ * appendObjPtr and append it.
*/
stringPtr = GET_STRING(objPtr);
if (stringPtr->hasUnicode != 0) {
-
/*
* If appendObjPtr is not of the "String" type, don't convert it.
*/
if (appendObjPtr->typePtr == &tclStringType) {
stringPtr = GET_STRING(appendObjPtr);
- if ((stringPtr->numChars == -1)
- || (stringPtr->hasUnicode == 0)) {
-
+ if ((stringPtr->numChars == -1) || (stringPtr->hasUnicode == 0)) {
/*
- * If appendObjPtr is a string obj with no valid Unicode
- * rep, then fill its unicode rep.
+ * If appendObjPtr is a string obj with no valid Unicode rep,
+ * then fill its unicode rep.
*/
FillUnicodeRep(appendObjPtr);
@@ -1229,19 +1300,19 @@ Tcl_AppendObjToObj(objPtr, appendObjPtr)
AppendUnicodeToUnicodeRep(objPtr, stringPtr->unicode,
stringPtr->numChars);
} else {
- bytes = Tcl_GetStringFromObj(appendObjPtr, &length);
+ bytes = TclGetStringFromObj(appendObjPtr, &length);
AppendUtfToUnicodeRep(objPtr, bytes, length);
}
return;
}
/*
- * Append to objPtr's UTF string rep. If we know the number of
- * characters in both objects before appending, then set the combined
- * number of characters in the final (appended-to) object.
+ * Append to objPtr's UTF string rep. If we know the number of characters
+ * in both objects before appending, then set the combined number of
+ * characters in the final (appended-to) object.
*/
- bytes = Tcl_GetStringFromObj(appendObjPtr, &length);
+ bytes = TclGetStringFromObj(appendObjPtr, &length);
allOneByteChars = 0;
numChars = stringPtr->numChars;
@@ -1266,8 +1337,8 @@ Tcl_AppendObjToObj(objPtr, appendObjPtr)
*
* AppendUnicodeToUnicodeRep --
*
- * This procedure appends the contents of "unicode" to the Unicode
- * rep of "objPtr". objPtr must already have a valid Unicode rep.
+ * This function appends the contents of "unicode" to the Unicode rep of
+ * "objPtr". objPtr must already have a valid Unicode rep.
*
* Results:
* None.
@@ -1279,13 +1350,13 @@ Tcl_AppendObjToObj(objPtr, appendObjPtr)
*/
static void
-AppendUnicodeToUnicodeRep(objPtr, unicode, appendNumChars)
- Tcl_Obj *objPtr; /* Points to the object to append to. */
- CONST Tcl_UniChar *unicode; /* String to append. */
- int appendNumChars; /* Number of chars of "unicode" to append. */
+AppendUnicodeToUnicodeRep(
+ Tcl_Obj *objPtr, /* Points to the object to append to. */
+ const Tcl_UniChar *unicode, /* String to append. */
+ int appendNumChars) /* Number of chars of "unicode" to append. */
{
String *stringPtr;
- size_t numChars;
+ int numChars;
if (appendNumChars < 0) {
appendNumChars = UnicodeLength(unicode);
@@ -1298,11 +1369,11 @@ AppendUnicodeToUnicodeRep(objPtr, unicode, appendNumChars)
stringPtr = GET_STRING(objPtr);
/*
- * If not enough space has been allocated for the unicode rep,
- * reallocate the internal rep object with additional space. First
- * try to double the required allocation; if that fails, try a more
- * modest increase. See the "TCL STRING GROWTH ALGORITHM" comment at
- * the top of this file for an explanation of this growth algorithm.
+ * If not enough space has been allocated for the unicode rep, reallocate
+ * the internal rep object with additional space. First try to double the
+ * required allocation; if that fails, try a more modest increase. See the
+ * "TCL STRING GROWTH ALGORITHM" comment at the top of this file for an
+ * explanation of this growth algorithm.
*/
numChars = stringPtr->numChars + appendNumChars;
@@ -1315,11 +1386,11 @@ AppendUnicodeToUnicodeRep(objPtr, unicode, appendNumChars)
* due to the reallocs below.
*/
int offset = -1;
- if (unicode >= stringPtr->unicode && unicode <= stringPtr->unicode
+ if (unicode >= stringPtr->unicode && unicode <= stringPtr->unicode
+ 1 + stringPtr->uallocated / sizeof(Tcl_UniChar)) {
offset = unicode - stringPtr->unicode;
}
-
+
GrowUnicodeBuffer(objPtr, numChars);
stringPtr = GET_STRING(objPtr);
@@ -1334,7 +1405,7 @@ AppendUnicodeToUnicodeRep(objPtr, unicode, appendNumChars)
* trailing null.
*/
- memcpy((VOID*) (stringPtr->unicode + stringPtr->numChars), unicode,
+ memcpy(stringPtr->unicode + stringPtr->numChars, unicode,
appendNumChars * sizeof(Tcl_UniChar));
stringPtr->unicode[numChars] = 0;
stringPtr->numChars = numChars;
@@ -1348,8 +1419,8 @@ AppendUnicodeToUnicodeRep(objPtr, unicode, appendNumChars)
*
* AppendUnicodeToUtfRep --
*
- * This procedure converts the contents of "unicode" to UTF and
- * appends the UTF to the string rep of "objPtr".
+ * This function converts the contents of "unicode" to UTF and appends
+ * the UTF to the string rep of "objPtr".
*
* Results:
* None.
@@ -1361,14 +1432,14 @@ AppendUnicodeToUnicodeRep(objPtr, unicode, appendNumChars)
*/
static void
-AppendUnicodeToUtfRep(objPtr, unicode, numChars)
- Tcl_Obj *objPtr; /* Points to the object to append to. */
- CONST Tcl_UniChar *unicode; /* String to convert to UTF. */
- int numChars; /* Number of chars of "unicode" to convert. */
+AppendUnicodeToUtfRep(
+ Tcl_Obj *objPtr, /* Points to the object to append to. */
+ const Tcl_UniChar *unicode, /* String to convert to UTF. */
+ int numChars) /* Number of chars of "unicode" to convert. */
{
Tcl_DString dsPtr;
- CONST char *bytes;
-
+ const char *bytes;
+
if (numChars < 0) {
numChars = UnicodeLength(unicode);
}
@@ -1387,9 +1458,9 @@ AppendUnicodeToUtfRep(objPtr, unicode, numChars)
*
* AppendUtfToUnicodeRep --
*
- * This procedure converts the contents of "bytes" to Unicode and
- * appends the Unicode to the Unicode rep of "objPtr". objPtr must
- * already have a valid Unicode rep.
+ * This function converts the contents of "bytes" to Unicode and appends
+ * the Unicode to the Unicode rep of "objPtr". objPtr must already have a
+ * valid Unicode rep.
*
* Results:
* None.
@@ -1401,10 +1472,10 @@ AppendUnicodeToUtfRep(objPtr, unicode, numChars)
*/
static void
-AppendUtfToUnicodeRep(objPtr, bytes, numBytes)
- Tcl_Obj *objPtr; /* Points to the object to append to. */
- CONST char *bytes; /* String to convert to Unicode. */
- int numBytes; /* Number of bytes of "bytes" to convert. */
+AppendUtfToUnicodeRep(
+ Tcl_Obj *objPtr, /* Points to the object to append to. */
+ const char *bytes, /* String to convert to Unicode. */
+ int numBytes) /* Number of bytes of "bytes" to convert. */
{
Tcl_DString dsPtr;
int numChars;
@@ -1416,7 +1487,7 @@ AppendUtfToUnicodeRep(objPtr, bytes, numBytes)
if (numBytes == 0) {
return;
}
-
+
Tcl_DStringInit(&dsPtr);
numChars = Tcl_NumUtfChars(bytes, numBytes);
unicode = (Tcl_UniChar *)Tcl_UtfToUniCharDString(bytes, numBytes, &dsPtr);
@@ -1429,8 +1500,8 @@ AppendUtfToUnicodeRep(objPtr, bytes, numBytes)
*
* AppendUtfToUtfRep --
*
- * This procedure appends "numBytes" bytes of "bytes" to the UTF string
- * rep of "objPtr". objPtr must already have a valid String rep.
+ * This function appends "numBytes" bytes of "bytes" to the UTF string
+ * rep of "objPtr". objPtr must already have a valid String rep.
*
* Results:
* None.
@@ -1442,10 +1513,10 @@ AppendUtfToUnicodeRep(objPtr, bytes, numBytes)
*/
static void
-AppendUtfToUtfRep(objPtr, bytes, numBytes)
- Tcl_Obj *objPtr; /* Points to the object to append to. */
- CONST char *bytes; /* String to append. */
- int numBytes; /* Number of bytes of "bytes" to append. */
+AppendUtfToUtfRep(
+ Tcl_Obj *objPtr, /* Points to the object to append to. */
+ const char *bytes, /* String to append. */
+ int numBytes) /* Number of bytes of "bytes" to append. */
{
String *stringPtr;
int newLength, oldLength;
@@ -1470,7 +1541,7 @@ AppendUtfToUtfRep(objPtr, bytes, numBytes)
stringPtr = GET_STRING(objPtr);
if (newLength > (int) stringPtr->allocated) {
- /*
+ /*
* Protect against case where unicode points into the existing
* stringPtr->unicode array. Force it to follow any relocations
* due to the reallocs below.
@@ -1482,10 +1553,10 @@ AppendUtfToUtfRep(objPtr, bytes, numBytes)
}
/*
- * There isn't currently enough space in the string representation
- * so allocate additional space. First, try to double the length
- * required. If that fails, try a more modest allocation. See the
- * "TCL STRING GROWTH ALGORITHM" comment at the top of this file for an
+ * There isn't currently enough space in the string representation so
+ * allocate additional space. First, try to double the length
+ * required. If that fails, try a more modest allocation. See the "TCL
+ * STRING GROWTH ALGORITHM" comment at the top of this file for an
* explanation of this growth algorithm.
*/
@@ -1497,7 +1568,7 @@ AppendUtfToUtfRep(objPtr, bytes, numBytes)
unsigned int limit = INT_MAX - newLength;
unsigned int extra = numBytes + TCL_GROWTH_MIN_ALLOC;
int growth = (int) ((extra > limit) ? limit : extra);
-
+
Tcl_SetObjLength(objPtr, newLength + growth);
}
@@ -1510,12 +1581,11 @@ AppendUtfToUtfRep(objPtr, bytes, numBytes)
/*
* Invalidate the unicode data.
*/
-
+
stringPtr->numChars = -1;
stringPtr->hasUnicode = 0;
-
- memcpy((VOID *) (objPtr->bytes + oldLength), (VOID *) bytes,
- (size_t) numBytes);
+
+ memcpy(objPtr->bytes + oldLength, bytes, (size_t) numBytes);
objPtr->bytes[newLength] = 0;
objPtr->length = newLength;
}
@@ -1525,23 +1595,23 @@ AppendUtfToUtfRep(objPtr, bytes, numBytes)
*
* Tcl_AppendStringsToObjVA --
*
- * This procedure appends one or more null-terminated strings
- * to an object.
+ * This function appends one or more null-terminated strings to an
+ * object.
*
* Results:
* None.
*
* Side effects:
- * The contents of all the string arguments are appended to the
- * string representation of objPtr.
+ * The contents of all the string arguments are appended to the string
+ * representation of objPtr.
*
*----------------------------------------------------------------------
*/
void
-Tcl_AppendStringsToObjVA (objPtr, argList)
- Tcl_Obj *objPtr; /* Points to the object to append to. */
- va_list argList; /* Variable argument list. */
+Tcl_AppendStringsToObjVA(
+ Tcl_Obj *objPtr, /* Points to the object to append to. */
+ va_list argList) /* Variable argument list. */
{
#define STATIC_LIST_SIZE 16
String *stringPtr;
@@ -1553,7 +1623,7 @@ Tcl_AppendStringsToObjVA (objPtr, argList)
int nargs, i;
if (Tcl_IsShared(objPtr)) {
- panic("Tcl_AppendStringsToObj called with shared object");
+ Tcl_Panic("%s called with shared object", "Tcl_AppendStringsToObj");
}
SetStringFromAny(NULL, objPtr);
@@ -1566,10 +1636,10 @@ Tcl_AppendStringsToObjVA (objPtr, argList)
(void) Tcl_GetStringFromObj(objPtr, &oldLength);
/*
- * Figure out how much space is needed for all the strings, and
- * expand the string representation if it isn't big enough. If no
- * bytes would be appended, just return. Note that on some platforms
- * (notably OS/390) the argList is an array so we need to use memcpy.
+ * Figure out how much space is needed for all the strings, and expand the
+ * string representation if it isn't big enough. If no bytes would be
+ * appended, just return. Note that on some platforms (notably OS/390) the
+ * argList is an array so we need to use memcpy.
*/
nargs = 0;
@@ -1579,21 +1649,22 @@ Tcl_AppendStringsToObjVA (objPtr, argList)
if (string == NULL) {
break;
}
- if (nargs >= nargs_space) {
- /*
- * Expand the args buffer
- */
- nargs_space += STATIC_LIST_SIZE;
- if (args == static_list) {
- args = (void *)ckalloc(nargs_space * sizeof(char *));
- for (i = 0; i < nargs; ++i) {
- args[i] = static_list[i];
- }
- } else {
- args = (void *)ckrealloc((void *)args,
+ if (nargs >= nargs_space) {
+ /*
+ * Expand the args buffer.
+ */
+
+ nargs_space += STATIC_LIST_SIZE;
+ if (args == static_list) {
+ args = (void *) ckalloc(nargs_space * sizeof(char *));
+ for (i = 0; i < nargs; ++i) {
+ args[i] = static_list[i];
+ }
+ } else {
+ args = (void *) ckrealloc((void *) args,
nargs_space * sizeof(char *));
- }
- }
+ }
+ }
newLength += strlen(string);
args[nargs++] = string;
}
@@ -1603,17 +1674,16 @@ Tcl_AppendStringsToObjVA (objPtr, argList)
stringPtr = GET_STRING(objPtr);
if (oldLength + newLength > (int) stringPtr->allocated) {
-
/*
- * There isn't currently enough space in the string
- * representation, so allocate additional space. If the current
- * string representation isn't empty (i.e. it looks like we're
- * doing a series of appends) then try to allocate extra space to
- * accomodate future growth: first try to double the required memory;
- * if that fails, try a more modest allocation. See the "TCL STRING
- * GROWTH ALGORITHM" comment at the top of this file for an explanation
- * of this growth algorithm. Otherwise, if the current string
- * representation is empty, exactly enough memory is allocated.
+ * There isn't currently enough space in the string representation, so
+ * allocate additional space. If the current string representation
+ * isn't empty (i.e. it looks like we're doing a series of appends)
+ * then try to allocate extra space to accomodate future growth: first
+ * try to double the required memory; if that fails, try a more modest
+ * allocation. See the "TCL STRING GROWTH ALGORITHM" comment at the
+ * top of this file for an explanation of this growth algorithm.
+ * Otherwise, if the current string representation is empty, exactly
+ * enough memory is allocated.
*/
if (oldLength == 0) {
@@ -1622,20 +1692,20 @@ Tcl_AppendStringsToObjVA (objPtr, argList)
attemptLength = 2 * (oldLength + newLength);
if (Tcl_AttemptSetObjLength(objPtr, attemptLength) == 0) {
attemptLength = oldLength + (2 * newLength) +
- TCL_GROWTH_MIN_ALLOC;
+ TCL_GROWTH_MIN_ALLOC;
Tcl_SetObjLength(objPtr, attemptLength);
}
}
}
/*
- * Make a second pass through the arguments, appending all the
- * strings to the object.
+ * Make a second pass through the arguments, appending all the strings to
+ * the object.
*/
dst = objPtr->bytes + oldLength;
for (i = 0; i < nargs; ++i) {
- string = args[i];
+ string = args[i];
if (string == NULL) {
break;
}
@@ -1647,10 +1717,10 @@ Tcl_AppendStringsToObjVA (objPtr, argList)
}
/*
- * Add a null byte to terminate the string. However, be careful:
- * it's possible that the object is totally empty (if it was empty
- * originally and there was nothing to append). In this case dst is
- * NULL; just leave everything alone.
+ * Add a null byte to terminate the string. However, be careful: it's
+ * possible that the object is totally empty (if it was empty originally
+ * and there was nothing to append). In this case dst is NULL; just leave
+ * everything alone.
*/
if (dst != NULL) {
@@ -1658,14 +1728,13 @@ Tcl_AppendStringsToObjVA (objPtr, argList)
}
objPtr->length = oldLength + newLength;
- done:
+ done:
/*
- * If we had to allocate a buffer from the heap,
- * free it now.
+ * If we had to allocate a buffer from the heap, free it now.
*/
-
+
if (args != static_list) {
- ckfree((void *)args);
+ ckfree((void *) args);
}
#undef STATIC_LIST_SIZE
}
@@ -1675,37 +1744,1051 @@ Tcl_AppendStringsToObjVA (objPtr, argList)
*
* Tcl_AppendStringsToObj --
*
- * This procedure appends one or more null-terminated strings
- * to an object.
+ * This function appends one or more null-terminated strings to an
+ * object.
*
* Results:
* None.
*
* Side effects:
- * The contents of all the string arguments are appended to the
- * string representation of objPtr.
+ * The contents of all the string arguments are appended to the string
+ * representation of objPtr.
*
*----------------------------------------------------------------------
*/
void
-Tcl_AppendStringsToObj TCL_VARARGS_DEF(Tcl_Obj *,arg1)
+Tcl_AppendStringsToObj(
+ Tcl_Obj *objPtr,
+ ...)
{
- register Tcl_Obj *objPtr;
va_list argList;
- objPtr = TCL_VARARGS_START(Tcl_Obj *,arg1,argList);
+ va_start(argList, objPtr);
Tcl_AppendStringsToObjVA(objPtr, argList);
va_end(argList);
}
/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AppendFormatToObj --
+ *
+ * This function appends a list of Tcl_Obj's to a Tcl_Obj according to
+ * the formatting instructions embedded in the format string. The
+ * formatting instructions are inspired by sprintf(). Returns TCL_OK when
+ * successful. If there's an error in the arguments, TCL_ERROR is
+ * returned, and an error message is written to the interp, if non-NULL.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_AppendFormatToObj(
+ Tcl_Interp *interp,
+ Tcl_Obj *appendObj,
+ const char *format,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ const char *span = format, *msg;
+ int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0;
+ int originalLength, limit;
+ static const char *mixedXPG =
+ "cannot mix \"%\" and \"%n$\" conversion specifiers";
+ static const char *badIndex[2] = {
+ "not enough arguments for all format specifiers",
+ "\"%n$\" argument index out of range"
+ };
+ static const char *overflow = "max size for a Tcl value exceeded";
+
+ if (Tcl_IsShared(appendObj)) {
+ Tcl_Panic("%s called with shared object", "Tcl_AppendFormatToObj");
+ }
+ TclGetStringFromObj(appendObj, &originalLength);
+ limit = INT_MAX - originalLength;
+
+ /*
+ * Format string is NUL-terminated.
+ */
+
+ while (*format != '\0') {
+ char *end;
+ int gotMinus, gotHash, gotZero, gotSpace, gotPlus, sawFlag;
+ int width, gotPrecision, precision, useShort, useWide, useBig;
+ int newXpg, numChars, allocSegment = 0, segmentLimit, segmentNumBytes;
+ Tcl_Obj *segment;
+ Tcl_UniChar ch;
+ int step = Tcl_UtfToUniChar(format, &ch);
+
+ format += step;
+ if (ch != '%') {
+ numBytes += step;
+ continue;
+ }
+ if (numBytes) {
+ if (numBytes > limit) {
+ msg = overflow;
+ goto errorMsg;
+ }
+ Tcl_AppendToObj(appendObj, span, numBytes);
+ limit -= numBytes;
+ numBytes = 0;
+ }
+
+ /*
+ * Saw a % : process the format specifier.
+ *
+ * Step 0. Handle special case of escaped format marker (i.e., %%).
+ */
+
+ step = Tcl_UtfToUniChar(format, &ch);
+ if (ch == '%') {
+ span = format;
+ numBytes = step;
+ format += step;
+ continue;
+ }
+
+ /*
+ * Step 1. XPG3 position specifier
+ */
+
+ newXpg = 0;
+ if (isdigit(UCHAR(ch))) {
+ int position = strtoul(format, &end, 10);
+ if (*end == '$') {
+ newXpg = 1;
+ objIndex = position - 1;
+ format = end + 1;
+ step = Tcl_UtfToUniChar(format, &ch);
+ }
+ }
+ if (newXpg) {
+ if (gotSequential) {
+ msg = mixedXPG;
+ goto errorMsg;
+ }
+ gotXpg = 1;
+ } else {
+ if (gotXpg) {
+ msg = mixedXPG;
+ goto errorMsg;
+ }
+ gotSequential = 1;
+ }
+ if ((objIndex < 0) || (objIndex >= objc)) {
+ msg = badIndex[gotXpg];
+ goto errorMsg;
+ }
+
+ /*
+ * Step 2. Set of flags.
+ */
+
+ gotMinus = gotHash = gotZero = gotSpace = gotPlus = 0;
+ sawFlag = 1;
+ do {
+ switch (ch) {
+ case '-':
+ gotMinus = 1;
+ break;
+ case '#':
+ gotHash = 1;
+ break;
+ case '0':
+ gotZero = 1;
+ break;
+ case ' ':
+ gotSpace = 1;
+ break;
+ case '+':
+ gotPlus = 1;
+ break;
+ default:
+ sawFlag = 0;
+ }
+ if (sawFlag) {
+ format += step;
+ step = Tcl_UtfToUniChar(format, &ch);
+ }
+ } while (sawFlag);
+
+ /*
+ * Step 3. Minimum field width.
+ */
+
+ width = 0;
+ if (isdigit(UCHAR(ch))) {
+ width = strtoul(format, &end, 10);
+ format = end;
+ step = Tcl_UtfToUniChar(format, &ch);
+ } else if (ch == '*') {
+ if (objIndex >= objc - 1) {
+ msg = badIndex[gotXpg];
+ goto errorMsg;
+ }
+ if (TclGetIntFromObj(interp, objv[objIndex], &width) != TCL_OK) {
+ goto error;
+ }
+ if (width < 0) {
+ width = -width;
+ gotMinus = 1;
+ }
+ objIndex++;
+ format += step;
+ step = Tcl_UtfToUniChar(format, &ch);
+ }
+ if (width > limit) {
+ msg = overflow;
+ goto errorMsg;
+ }
+
+ /*
+ * Step 4. Precision.
+ */
+
+ gotPrecision = precision = 0;
+ if (ch == '.') {
+ gotPrecision = 1;
+ format += step;
+ step = Tcl_UtfToUniChar(format, &ch);
+ }
+ if (isdigit(UCHAR(ch))) {
+ precision = strtoul(format, &end, 10);
+ format = end;
+ step = Tcl_UtfToUniChar(format, &ch);
+ } else if (ch == '*') {
+ if (objIndex >= objc - 1) {
+ msg = badIndex[gotXpg];
+ goto errorMsg;
+ }
+ if (TclGetIntFromObj(interp, objv[objIndex], &precision)
+ != TCL_OK) {
+ goto error;
+ }
+
+ /*
+ * TODO: Check this truncation logic.
+ */
+
+ if (precision < 0) {
+ precision = 0;
+ }
+ objIndex++;
+ format += step;
+ step = Tcl_UtfToUniChar(format, &ch);
+ }
+
+ /*
+ * Step 5. Length modifier.
+ */
+
+ useShort = useWide = useBig = 0;
+ if (ch == 'h') {
+ useShort = 1;
+ format += step;
+ step = Tcl_UtfToUniChar(format, &ch);
+ } else if (ch == 'l') {
+ format += step;
+ step = Tcl_UtfToUniChar(format, &ch);
+ if (ch == 'l') {
+ useBig = 1;
+ format += step;
+ step = Tcl_UtfToUniChar(format, &ch);
+ } else {
+#ifndef TCL_WIDE_INT_IS_LONG
+ useWide = 1;
+#endif
+ }
+ }
+
+ format += step;
+ span = format;
+
+ /*
+ * Step 6. The actual conversion character.
+ */
+
+ segment = objv[objIndex];
+ numChars = -1;
+ if (ch == 'i') {
+ ch = 'd';
+ }
+ switch (ch) {
+ case '\0':
+ msg = "format string ended in middle of field specifier";
+ goto errorMsg;
+ case 's':
+ if (gotPrecision) {
+ numChars = Tcl_GetCharLength(segment);
+ if (precision < numChars) {
+ segment = Tcl_GetRange(segment, 0, precision - 1);
+ numChars = precision;
+ Tcl_IncrRefCount(segment);
+ allocSegment = 1;
+ }
+ }
+ break;
+ case 'c': {
+ char buf[TCL_UTF_MAX];
+ int code, length;
+
+ if (TclGetIntFromObj(interp, segment, &code) != TCL_OK) {
+ goto error;
+ }
+ length = Tcl_UniCharToUtf(code, buf);
+ segment = Tcl_NewStringObj(buf, length);
+ Tcl_IncrRefCount(segment);
+ allocSegment = 1;
+ break;
+ }
+
+ case 'u':
+ if (useBig) {
+ msg = "unsigned bignum format is invalid";
+ goto errorMsg;
+ }
+ case 'd':
+ case 'o':
+ case 'x':
+ case 'X': {
+ short int s = 0; /* Silence compiler warning; only defined and
+ * used when useShort is true. */
+ long l;
+ Tcl_WideInt w;
+ mp_int big;
+ int toAppend, isNegative = 0;
+
+ if (useBig) {
+ if (Tcl_GetBignumFromObj(interp, segment, &big) != TCL_OK) {
+ goto error;
+ }
+ isNegative = (mp_cmp_d(&big, 0) == MP_LT);
+ } else if (useWide) {
+ if (Tcl_GetWideIntFromObj(NULL, segment, &w) != TCL_OK) {
+ Tcl_Obj *objPtr;
+
+ if (Tcl_GetBignumFromObj(interp,segment,&big) != TCL_OK) {
+ goto error;
+ }
+ mp_mod_2d(&big, (int) CHAR_BIT*sizeof(Tcl_WideInt), &big);
+ objPtr = Tcl_NewBignumObj(&big);
+ Tcl_IncrRefCount(objPtr);
+ Tcl_GetWideIntFromObj(NULL, objPtr, &w);
+ Tcl_DecrRefCount(objPtr);
+ }
+ isNegative = (w < (Tcl_WideInt)0);
+ } else if (TclGetLongFromObj(NULL, segment, &l) != TCL_OK) {
+ if (Tcl_GetWideIntFromObj(NULL, segment, &w) != TCL_OK) {
+ Tcl_Obj *objPtr;
+
+ if (Tcl_GetBignumFromObj(interp,segment,&big) != TCL_OK) {
+ goto error;
+ }
+ mp_mod_2d(&big, (int) CHAR_BIT * sizeof(long), &big);
+ objPtr = Tcl_NewBignumObj(&big);
+ Tcl_IncrRefCount(objPtr);
+ TclGetLongFromObj(NULL, objPtr, &l);
+ Tcl_DecrRefCount(objPtr);
+ } else {
+ l = Tcl_WideAsLong(w);
+ }
+ if (useShort) {
+ s = (short int) l;
+ isNegative = (s < (short int)0);
+ } else {
+ isNegative = (l < (long)0);
+ }
+ } else if (useShort) {
+ s = (short int) l;
+ isNegative = (s < (short int)0);
+ } else {
+ isNegative = (l < (long)0);
+ }
+
+ segment = Tcl_NewObj();
+ allocSegment = 1;
+ segmentLimit = INT_MAX;
+ Tcl_IncrRefCount(segment);
+
+ if ((isNegative || gotPlus || gotSpace) && (useBig || (ch == 'd'))) {
+ Tcl_AppendToObj(segment, (isNegative ? "-" : gotPlus ? "+" : " "), 1);
+ segmentLimit -= 1;
+ }
+
+ if (gotHash) {
+ switch (ch) {
+ case 'o':
+ Tcl_AppendToObj(segment, "0", 1);
+ segmentLimit -= 1;
+ precision--;
+ break;
+ case 'x':
+ case 'X':
+ Tcl_AppendToObj(segment, "0x", 2);
+ segmentLimit -= 2;
+ break;
+ }
+ }
+
+ switch (ch) {
+ case 'd': {
+ int length;
+ Tcl_Obj *pure;
+ const char *bytes;
+
+ if (useShort) {
+ pure = Tcl_NewIntObj((int)(s));
+ } else if (useWide) {
+ pure = Tcl_NewWideIntObj(w);
+ } else if (useBig) {
+ pure = Tcl_NewBignumObj(&big);
+ } else {
+ pure = Tcl_NewLongObj(l);
+ }
+ Tcl_IncrRefCount(pure);
+ bytes = TclGetStringFromObj(pure, &length);
+
+ /*
+ * Already did the sign above.
+ */
+
+ if (*bytes == '-') {
+ length--;
+ bytes++;
+ }
+ toAppend = length;
+
+ /*
+ * Canonical decimal string reps for integers are composed
+ * entirely of one-byte encoded characters, so "length" is the
+ * number of chars.
+ */
+
+ if (gotPrecision) {
+ if (length < precision) {
+ segmentLimit -= (precision - length);
+ }
+ while (length < precision) {
+ Tcl_AppendToObj(segment, "0", 1);
+ length++;
+ }
+ gotZero = 0;
+ }
+ if (gotZero) {
+ length += Tcl_GetCharLength(segment);
+ if (length < width) {
+ segmentLimit -= (width - length);
+ }
+ while (length < width) {
+ Tcl_AppendToObj(segment, "0", 1);
+ length++;
+ }
+ }
+ if (toAppend > segmentLimit) {
+ msg = overflow;
+ goto errorMsg;
+ }
+ Tcl_AppendToObj(segment, bytes, toAppend);
+ Tcl_DecrRefCount(pure);
+ break;
+ }
+
+ case 'u':
+ case 'o':
+ case 'x':
+ case 'X': {
+ Tcl_WideUInt bits = (Tcl_WideUInt)0;
+ Tcl_WideInt numDigits = (Tcl_WideInt)0;
+ int length, numBits = 4, base = 16;
+ int index = 0, shift = 0;
+ Tcl_Obj *pure;
+ char *bytes;
+
+ if (ch == 'u') {
+ base = 10;
+ }
+ if (ch == 'o') {
+ base = 8;
+ numBits = 3;
+ }
+ if (useShort) {
+ unsigned short int us = (unsigned short int) s;
+
+ bits = (Tcl_WideUInt) us;
+ while (us) {
+ numDigits++;
+ us /= base;
+ }
+ } else if (useWide) {
+ Tcl_WideUInt uw = (Tcl_WideUInt) w;
+
+ bits = uw;
+ while (uw) {
+ numDigits++;
+ uw /= base;
+ }
+ } else if (useBig && big.used) {
+ int leftover = (big.used * DIGIT_BIT) % numBits;
+ mp_digit mask = (~(mp_digit)0) << (DIGIT_BIT-leftover);
+
+ numDigits = 1 +
+ (((Tcl_WideInt)big.used * DIGIT_BIT) / numBits);
+ while ((mask & big.dp[big.used-1]) == 0) {
+ numDigits--;
+ mask >>= numBits;
+ }
+ if (numDigits > INT_MAX) {
+ msg = overflow;
+ goto errorMsg;
+ }
+ } else if (!useBig) {
+ unsigned long int ul = (unsigned long int) l;
+
+ bits = (Tcl_WideUInt) ul;
+ while (ul) {
+ numDigits++;
+ ul /= base;
+ }
+ }
+
+ /*
+ * Need to be sure zero becomes "0", not "".
+ */
+
+ if ((numDigits == 0) && !((ch == 'o') && gotHash)) {
+ numDigits = 1;
+ }
+ pure = Tcl_NewObj();
+ Tcl_SetObjLength(pure, (int)numDigits);
+ bytes = TclGetString(pure);
+ toAppend = length = (int)numDigits;
+ while (numDigits--) {
+ int digitOffset;
+
+ if (useBig && big.used) {
+ if (index < big.used && (size_t) shift <
+ CHAR_BIT*sizeof(Tcl_WideUInt) - DIGIT_BIT) {
+ bits |= (((Tcl_WideUInt)big.dp[index++]) <<shift);
+ shift += DIGIT_BIT;
+ }
+ shift -= numBits;
+ }
+ digitOffset = (int) (bits % base);
+ if (digitOffset > 9) {
+ bytes[numDigits] = 'a' + digitOffset - 10;
+ } else {
+ bytes[numDigits] = '0' + digitOffset;
+ }
+ bits /= base;
+ }
+ if (useBig) {
+ mp_clear(&big);
+ }
+ if (gotPrecision) {
+ if (length < precision) {
+ segmentLimit -= (precision - length);
+ }
+ while (length < precision) {
+ Tcl_AppendToObj(segment, "0", 1);
+ length++;
+ }
+ gotZero = 0;
+ }
+ if (gotZero) {
+ length += Tcl_GetCharLength(segment);
+ if (length < width) {
+ segmentLimit -= (width - length);
+ }
+ while (length < width) {
+ Tcl_AppendToObj(segment, "0", 1);
+ length++;
+ }
+ }
+ if (toAppend > segmentLimit) {
+ msg = overflow;
+ goto errorMsg;
+ }
+ Tcl_AppendObjToObj(segment, pure);
+ Tcl_DecrRefCount(pure);
+ break;
+ }
+
+ }
+ break;
+ }
+
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G': {
+#define MAX_FLOAT_SIZE 320
+ char spec[2*TCL_INTEGER_SPACE + 9], *p = spec;
+ double d;
+ int length = MAX_FLOAT_SIZE;
+ char *bytes;
+
+ if (Tcl_GetDoubleFromObj(interp, segment, &d) != TCL_OK) {
+ /* TODO: Figure out ACCEPT_NAN here */
+ goto error;
+ }
+ *p++ = '%';
+ if (gotMinus) {
+ *p++ = '-';
+ }
+ if (gotHash) {
+ *p++ = '#';
+ }
+ if (gotZero) {
+ *p++ = '0';
+ }
+ if (gotSpace) {
+ *p++ = ' ';
+ }
+ if (gotPlus) {
+ *p++ = '+';
+ }
+ if (width) {
+ p += sprintf(p, "%d", width);
+ if (width > length) {
+ length = width;
+ }
+ }
+ if (gotPrecision) {
+ *p++ = '.';
+ p += sprintf(p, "%d", precision);
+ if (precision > INT_MAX - length) {
+ msg=overflow;
+ goto errorMsg;
+ }
+ length += precision;
+ }
+
+ /*
+ * Don't pass length modifiers!
+ */
+
+ *p++ = (char) ch;
+ *p = '\0';
+
+ segment = Tcl_NewObj();
+ allocSegment = 1;
+ if (!Tcl_AttemptSetObjLength(segment, length)) {
+ msg = overflow;
+ goto errorMsg;
+ }
+ bytes = TclGetString(segment);
+ if (!Tcl_AttemptSetObjLength(segment, sprintf(bytes, spec, d))) {
+ msg = overflow;
+ goto errorMsg;
+ }
+ break;
+ }
+ default:
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp,
+ Tcl_ObjPrintf("bad field specifier \"%c\"", ch));
+ }
+ goto error;
+ }
+
+ switch (ch) {
+ case 'E':
+ case 'G':
+ case 'X': {
+ Tcl_SetObjLength(segment, Tcl_UtfToUpper(TclGetString(segment)));
+ }
+ }
+
+ if (width > 0) {
+ if (numChars < 0) {
+ numChars = Tcl_GetCharLength(segment);
+ }
+ if (!gotMinus) {
+ if (numChars < width) {
+ limit -= (width - numChars);
+ }
+ while (numChars < width) {
+ Tcl_AppendToObj(appendObj, (gotZero ? "0" : " "), 1);
+ numChars++;
+ }
+ }
+ }
+
+ Tcl_GetStringFromObj(segment, &segmentNumBytes);
+ if (segmentNumBytes > limit) {
+ if (allocSegment) {
+ Tcl_DecrRefCount(segment);
+ }
+ msg = overflow;
+ goto errorMsg;
+ }
+ Tcl_AppendObjToObj(appendObj, segment);
+ limit -= segmentNumBytes;
+ if (allocSegment) {
+ Tcl_DecrRefCount(segment);
+ }
+ if (width > 0) {
+ if (numChars < width) {
+ limit -= (width - numChars);
+ }
+ while (numChars < width) {
+ Tcl_AppendToObj(appendObj, (gotZero ? "0" : " "), 1);
+ numChars++;
+ }
+ }
+
+ objIndex += gotSequential;
+ }
+ if (numBytes) {
+ if (numBytes > limit) {
+ msg = overflow;
+ goto errorMsg;
+ }
+ Tcl_AppendToObj(appendObj, span, numBytes);
+ limit -= numBytes;
+ numBytes = 0;
+ }
+
+ return TCL_OK;
+
+ errorMsg:
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1));
+ }
+ error:
+ Tcl_SetObjLength(appendObj, originalLength);
+ return TCL_ERROR;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tcl_Format--
+ *
+ * Results:
+ * A refcount zero Tcl_Obj.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tcl_Format(
+ Tcl_Interp *interp,
+ const char *format,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ int result;
+ Tcl_Obj *objPtr = Tcl_NewObj();
+ result = Tcl_AppendFormatToObj(interp, objPtr, format, objc, objv);
+ if (result != TCL_OK) {
+ Tcl_DecrRefCount(objPtr);
+ return NULL;
+ }
+ return objPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AppendPrintfToObjVA --
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+AppendPrintfToObjVA(
+ Tcl_Obj *objPtr,
+ const char *format,
+ va_list argList)
+{
+ int code, objc;
+ Tcl_Obj **objv, *list = Tcl_NewObj();
+ const char *p;
+ char *end;
+
+ p = format;
+ Tcl_IncrRefCount(list);
+ while (*p != '\0') {
+ int size = 0, seekingConversion = 1, gotPrecision = 0;
+ int lastNum = -1;
+
+ if (*p++ != '%') {
+ continue;
+ }
+ if (*p == '%') {
+ p++;
+ continue;
+ }
+ do {
+ switch (*p) {
+
+ case '\0':
+ seekingConversion = 0;
+ break;
+ case 's': {
+ const char *q, *end, *bytes = va_arg(argList, char *);
+ seekingConversion = 0;
+
+ /*
+ * The buffer to copy characters from starts at bytes and ends
+ * at either the first NUL byte, or after lastNum bytes, when
+ * caller has indicated a limit.
+ */
+
+ end = bytes;
+ while ((!gotPrecision || lastNum--) && (*end != '\0')) {
+ end++;
+ }
+
+ /*
+ * Within that buffer, we trim both ends if needed so that we
+ * copy only whole characters, and avoid copying any partial
+ * multi-byte characters.
+ */
+
+ q = Tcl_UtfPrev(end, bytes);
+ if (!Tcl_UtfCharComplete(q, (int)(end - q))) {
+ end = q;
+ }
+
+ q = bytes + TCL_UTF_MAX;
+ while ((bytes < end) && (bytes < q)
+ && ((*bytes & 0xC0) == 0x80)) {
+ bytes++;
+ }
+
+ Tcl_ListObjAppendElement(NULL, list,
+ Tcl_NewStringObj(bytes , (int)(end - bytes)));
+
+ break;
+ }
+ case 'c':
+ case 'i':
+ case 'u':
+ case 'd':
+ case 'o':
+ case 'x':
+ case 'X':
+ seekingConversion = 0;
+ switch (size) {
+ case -1:
+ case 0:
+ Tcl_ListObjAppendElement(NULL, list, Tcl_NewLongObj(
+ (long int)va_arg(argList, int)));
+ break;
+ case 1:
+ Tcl_ListObjAppendElement(NULL, list, Tcl_NewLongObj(
+ va_arg(argList, long int)));
+ break;
+ }
+ break;
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G':
+ Tcl_ListObjAppendElement(NULL, list, Tcl_NewDoubleObj(
+ va_arg(argList, double)));
+ seekingConversion = 0;
+ break;
+ case '*':
+ lastNum = (int)va_arg(argList, int);
+ Tcl_ListObjAppendElement(NULL, list, Tcl_NewIntObj(lastNum));
+ p++;
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ lastNum = (int) strtoul(p, &end, 10);
+ p = end;
+ break;
+ case '.':
+ gotPrecision = 1;
+ p++;
+ break;
+ /* TODO: support for wide (and bignum?) arguments */
+ case 'l':
+ size = 1;
+ p++;
+ break;
+ case 'h':
+ size = -1;
+ default:
+ p++;
+ }
+ } while (seekingConversion);
+ }
+ TclListObjGetElements(NULL, list, &objc, &objv);
+ code = Tcl_AppendFormatToObj(NULL, objPtr, format, objc, objv);
+ if (code != TCL_OK) {
+ Tcl_AppendPrintfToObj(objPtr,
+ "Unable to format \"%s\" with supplied arguments: %s",
+ format, Tcl_GetString(list));
+ }
+ Tcl_DecrRefCount(list);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tcl_AppendPrintfToObj --
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+Tcl_AppendPrintfToObj(
+ Tcl_Obj *objPtr,
+ const char *format,
+ ...)
+{
+ va_list argList;
+
+ va_start(argList, format);
+ AppendPrintfToObjVA(objPtr, format, argList);
+ va_end(argList);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tcl_ObjPrintf --
+ *
+ * Results:
+ * A refcount zero Tcl_Obj.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tcl_ObjPrintf(
+ const char *format,
+ ...)
+{
+ va_list argList;
+ Tcl_Obj *objPtr = Tcl_NewObj();
+
+ va_start(argList, format);
+ AppendPrintfToObjVA(objPtr, format, argList);
+ va_end(argList);
+ return objPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclStringObjReverse --
+ *
+ * Implements the [string reverse] operation.
+ *
+ * Results:
+ * An unshared Tcl value which is the [string reverse] of the argument
+ * supplied. When sharing rules permit, the returned value might be
+ * the argument with modifications done in place.
+ *
+ * Side effects:
+ * May allocate a new Tcl_Obj.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclStringObjReverse(
+ Tcl_Obj *objPtr)
+{
+ String *stringPtr;
+ int numChars = Tcl_GetCharLength(objPtr);
+ int i = 0, lastCharIdx = numChars - 1;
+ char *bytes;
+
+ if (numChars <= 1) {
+ return objPtr;
+ }
+
+ stringPtr = GET_STRING(objPtr);
+ if (stringPtr->hasUnicode) {
+ Tcl_UniChar *source = stringPtr->unicode;
+
+ if (Tcl_IsShared(objPtr)) {
+ Tcl_UniChar *dest, ch = 0;
+
+ /*
+ * Create a non-empty, pure unicode value, so we can coax
+ * Tcl_SetObjLength into growing the unicode rep buffer.
+ */
+
+ Tcl_Obj *resultPtr = Tcl_NewUnicodeObj(&ch, 1);
+ Tcl_SetObjLength(resultPtr, numChars);
+ dest = Tcl_GetUnicode(resultPtr);
+
+ while (i < numChars) {
+ dest[i++] = source[lastCharIdx--];
+ }
+ return resultPtr;
+ }
+
+ while (i < lastCharIdx) {
+ Tcl_UniChar tmp = source[lastCharIdx];
+ source[lastCharIdx--] = source[i];
+ source[i++] = tmp;
+ }
+ Tcl_InvalidateStringRep(objPtr);
+ stringPtr->allocated = 0;
+ return objPtr;
+ }
+
+ bytes = TclGetString(objPtr);
+ if (Tcl_IsShared(objPtr)) {
+ char *dest;
+ Tcl_Obj *resultPtr = Tcl_NewObj();
+ Tcl_SetObjLength(resultPtr, numChars);
+ dest = TclGetString(resultPtr);
+ while (i < numChars) {
+ dest[i++] = bytes[lastCharIdx--];
+ }
+ return resultPtr;
+ }
+
+ while (i < lastCharIdx) {
+ char tmp = bytes[lastCharIdx];
+ bytes[lastCharIdx--] = bytes[i];
+ bytes[i++] = tmp;
+ }
+ return objPtr;
+}
+
+/*
*---------------------------------------------------------------------------
*
* FillUnicodeRep --
*
* Populate the Unicode internal rep with the Unicode form of its string
- * rep. The object must alread have a "String" internal rep.
+ * rep. The object must alread have a "String" internal rep.
*
* Results:
* None.
@@ -1717,15 +2800,15 @@ Tcl_AppendStringsToObj TCL_VARARGS_DEF(Tcl_Obj *,arg1)
*/
static void
-FillUnicodeRep(objPtr)
- Tcl_Obj *objPtr; /* The object in which to fill the unicode rep. */
+FillUnicodeRep(
+ Tcl_Obj *objPtr) /* The object in which to fill the unicode
+ * rep. */
{
String *stringPtr;
size_t uallocated;
- char *src, *srcEnd;
+ char *srcEnd, *src = objPtr->bytes;
Tcl_UniChar *dst;
- src = objPtr->bytes;
-
+
stringPtr = GET_STRING(objPtr);
if (stringPtr->numChars == -1) {
stringPtr->numChars = Tcl_NumUtfChars(src, objPtr->length);
@@ -1742,13 +2825,13 @@ FillUnicodeRep(objPtr)
/*
* Convert src to Unicode and store the coverted data in "unicode".
*/
-
+
srcEnd = src + objPtr->length;
for (dst = stringPtr->unicode; src < srcEnd; dst++) {
src += TclUtfToUniChar(src, dst);
}
*dst = 0;
-
+
SET_STRING(objPtr, stringPtr);
}
@@ -1757,8 +2840,8 @@ FillUnicodeRep(objPtr)
*
* DupStringInternalRep --
*
- * Initialize the internal representation of a new Tcl_Obj to a
- * copy of the internal representation of an existing string object.
+ * Initialize the internal representation of a new Tcl_Obj to a copy of
+ * the internal representation of an existing string object.
*
* Results:
* None.
@@ -1771,32 +2854,31 @@ FillUnicodeRep(objPtr)
*/
static void
-DupStringInternalRep(srcPtr, copyPtr)
- register Tcl_Obj *srcPtr; /* Object with internal rep to copy. Must
- * have an internal rep of type "String". */
- register Tcl_Obj *copyPtr; /* Object with internal rep to set. Must
- * not currently have an internal rep.*/
+DupStringInternalRep(
+ register Tcl_Obj *srcPtr, /* Object with internal rep to copy. Must have
+ * an internal rep of type "String". */
+ register Tcl_Obj *copyPtr) /* Object with internal rep to set. Must not
+ * currently have an internal rep.*/
{
String *srcStringPtr = GET_STRING(srcPtr);
String *copyStringPtr = NULL;
/*
- * If the src obj is a string of 1-byte Utf chars, then copy the
- * string rep of the source object and create an "empty" Unicode
- * internal rep for the new object. Otherwise, copy Unicode
- * internal rep, and invalidate the string rep of the new object.
+ * If the src obj is a string of 1-byte Utf chars, then copy the string
+ * rep of the source object and create an "empty" Unicode internal rep for
+ * the new object. Otherwise, copy Unicode internal rep, and invalidate
+ * the string rep of the new object.
*/
-
+
if (srcStringPtr->hasUnicode == 0) {
- copyStringPtr = (String *) ckalloc(sizeof(String));
+ copyStringPtr = (String *) ckalloc(sizeof(String));
copyStringPtr->uallocated = 0;
} else {
copyStringPtr = (String *) ckalloc(
- STRING_SIZE(srcStringPtr->uallocated));
+ STRING_SIZE(srcStringPtr->uallocated));
copyStringPtr->uallocated = srcStringPtr->uallocated;
- memcpy((VOID *) copyStringPtr->unicode,
- (VOID *) srcStringPtr->unicode,
+ memcpy(copyStringPtr->unicode, srcStringPtr->unicode,
(size_t) srcStringPtr->numChars * sizeof(Tcl_UniChar));
copyStringPtr->unicode[srcStringPtr->numChars] = 0;
}
@@ -1805,9 +2887,9 @@ DupStringInternalRep(srcPtr, copyPtr)
copyStringPtr->allocated = srcStringPtr->allocated;
/*
- * Tricky point: the string value was copied by generic object
- * management code, so it doesn't contain any extra bytes that
- * might exist in the source object.
+ * Tricky point: the string value was copied by generic object management
+ * code, so it doesn't contain any extra bytes that might exist in the
+ * source object.
*/
copyStringPtr->allocated = copyPtr->length;
@@ -1827,21 +2909,21 @@ DupStringInternalRep(srcPtr, copyPtr)
* This operation always succeeds and returns TCL_OK.
*
* Side effects:
- * Any old internal reputation for objPtr is freed and the
- * internal representation is set to "String".
+ * Any old internal reputation for objPtr is freed and the internal
+ * representation is set to "String".
*
*----------------------------------------------------------------------
*/
static int
-SetStringFromAny(interp, objPtr)
- Tcl_Interp *interp; /* Used for error reporting if not NULL. */
- register Tcl_Obj *objPtr; /* The object to convert. */
+SetStringFromAny(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ register Tcl_Obj *objPtr) /* The object to convert. */
{
/*
- * The Unicode object is optimized for the case where each UTF char
- * in a string is only one byte. In this case, we store the value of
- * numChars, but we don't copy the bytes to the unicodeObj->unicode.
+ * The Unicode object is optimized for the case where each UTF char in a
+ * string is only one byte. In this case, we store the value of numChars,
+ * but we don't copy the bytes to the unicodeObj->unicode.
*/
if (objPtr->typePtr != &tclStringType) {
@@ -1851,9 +2933,7 @@ SetStringFromAny(interp, objPtr)
if (objPtr->bytes == NULL) {
objPtr->typePtr->updateStringProc(objPtr);
}
- if ((objPtr->typePtr->freeIntRepProc) != NULL) {
- (*objPtr->typePtr->freeIntRepProc)(objPtr);
- }
+ TclFreeIntRep(objPtr);
}
objPtr->typePtr = &tclStringType;
@@ -1867,10 +2947,10 @@ SetStringFromAny(interp, objPtr)
stringPtr->hasUnicode = 0;
if (objPtr->bytes != NULL) {
- stringPtr->allocated = objPtr->length;
- if (objPtr->bytes != tclEmptyStringRep) {
- objPtr->bytes[objPtr->length] = 0;
- }
+ stringPtr->allocated = objPtr->length;
+ if (objPtr->bytes != tclEmptyStringRep) {
+ objPtr->bytes[objPtr->length] = 0;
+ }
} else {
objPtr->length = 0;
}
@@ -1891,15 +2971,15 @@ SetStringFromAny(interp, objPtr)
* None.
*
* Side effects:
- * The object's string may be set by converting its Unicode
- * represention to UTF format.
+ * The object's string may be set by converting its Unicode represention
+ * to UTF format.
*
*----------------------------------------------------------------------
*/
static void
-UpdateStringOfString(objPtr)
- Tcl_Obj *objPtr; /* Object with string rep to update. */
+UpdateStringOfString(
+ Tcl_Obj *objPtr) /* Object with string rep to update. */
{
int i, size;
Tcl_UniChar *unicode;
@@ -1909,12 +2989,10 @@ UpdateStringOfString(objPtr)
stringPtr = GET_STRING(objPtr);
if ((objPtr->bytes == NULL) || (stringPtr->allocated == 0)) {
-
if (stringPtr->numChars <= 0) {
-
/*
- * If there is no Unicode rep, or the string has 0 chars,
- * then set the string rep to an empty string.
+ * If there is no Unicode rep, or the string has 0 chars, then set
+ * the string rep to an empty string.
*/
objPtr->bytes = tclEmptyStringRep;
@@ -1925,12 +3003,12 @@ UpdateStringOfString(objPtr)
unicode = stringPtr->unicode;
/*
- * Translate the Unicode string to UTF. "size" will hold the
- * amount of space the UTF string needs.
+ * Translate the Unicode string to UTF. "size" will hold the amount of
+ * space the UTF string needs.
*/
if (stringPtr->numChars <= INT_MAX/TCL_UTF_MAX
- && stringPtr->allocated >= (size_t) (stringPtr->numChars * TCL_UTF_MAX)) {
+ && stringPtr->allocated >= stringPtr->numChars * (size_t)TCL_UTF_MAX) {
goto copyBytes;
}
@@ -1961,21 +3039,30 @@ UpdateStringOfString(objPtr)
*
* FreeStringInternalRep --
*
- * Deallocate the storage associated with a String data object's
- * internal representation.
+ * Deallocate the storage associated with a String data object's internal
+ * representation.
*
* Results:
* None.
*
* Side effects:
- * Frees memory.
+ * Frees memory.
*
*----------------------------------------------------------------------
*/
static void
-FreeStringInternalRep(objPtr)
- Tcl_Obj *objPtr; /* Object with internal rep to free. */
+FreeStringInternalRep(
+ Tcl_Obj *objPtr) /* Object with internal rep to free. */
{
ckfree((char *) GET_STRING(objPtr));
+ objPtr->typePtr = NULL;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c
index a81f3e8..d8a300c 100644
--- a/generic/tclStubInit.c
+++ b/generic/tclStubInit.c
@@ -10,7 +10,7 @@
*/
#include "tclInt.h"
-#include "tclPort.h"
+#include "tommath.h"
/*
* Remove macros that will interfere with the definitions below.
@@ -44,7 +44,7 @@
Tcl_NotifierProcs tclOriginalNotifier = {
Tcl_SetTimer,
Tcl_WaitForEvent,
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+#if !defined(__WIN32__) /* UNIX */
Tcl_CreateFileHandler,
Tcl_DeleteFileHandler,
#else
@@ -57,6 +57,12 @@ Tcl_NotifierProcs tclOriginalNotifier = {
NULL
};
+MODULE_SCOPE TclIntStubs tclIntStubs;
+MODULE_SCOPE TclIntPlatStubs tclIntPlatStubs;
+MODULE_SCOPE TclPlatStubs tclPlatStubs;
+MODULE_SCOPE TclStubs tclStubs;
+MODULE_SCOPE TclTomMathStubs tclTomMathStubs;
+
/*
* WARNING: The contents of this file is automatically generated by the
* tools/genStubs.tcl script. Any modifications to the function declarations
@@ -69,35 +75,19 @@ TclIntStubs tclIntStubs = {
TCL_STUB_MAGIC,
NULL,
NULL, /* 0 */
- TclAccessDeleteProc, /* 1 */
- TclAccessInsertProc, /* 2 */
+ NULL, /* 1 */
+ NULL, /* 2 */
TclAllocateFreeObjects, /* 3 */
NULL, /* 4 */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
- TclCleanupChildren, /* 5 */
-#endif /* UNIX */
-#ifdef __WIN32__
TclCleanupChildren, /* 5 */
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
- NULL, /* 5 */
-#endif /* MAC_TCL */
TclCleanupCommand, /* 6 */
TclCopyAndCollapse, /* 7 */
TclCopyChannel, /* 8 */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
- TclCreatePipeline, /* 9 */
-#endif /* UNIX */
-#ifdef __WIN32__
TclCreatePipeline, /* 9 */
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
- NULL, /* 9 */
-#endif /* MAC_TCL */
TclCreateProc, /* 10 */
TclDeleteCompiledLocalVars, /* 11 */
TclDeleteVars, /* 12 */
- TclDoGlob, /* 13 */
+ NULL, /* 13 */
TclDumpMemoryInfo, /* 14 */
NULL, /* 15 */
TclExprFloatError, /* 16 */
@@ -111,13 +101,13 @@ TclIntStubs tclIntStubs = {
TclFormatInt, /* 24 */
TclFreePackageInfo, /* 25 */
NULL, /* 26 */
- TclGetDate, /* 27 */
+ NULL, /* 27 */
TclpGetDefaultStdChannel, /* 28 */
NULL, /* 29 */
NULL, /* 30 */
TclGetExtension, /* 31 */
TclGetFrame, /* 32 */
- TclGetInterpProc, /* 33 */
+ NULL, /* 33 */
TclGetIntForIndex, /* 34 */
NULL, /* 35 */
TclGetLong, /* 36 */
@@ -127,16 +117,16 @@ TclIntStubs tclIntStubs = {
TclGetOpenMode, /* 40 */
TclGetOriginalCommand, /* 41 */
TclpGetUserHome, /* 42 */
- TclGlobalInvoke, /* 43 */
+ NULL, /* 43 */
TclGuessPackageName, /* 44 */
TclHideUnsafeCommands, /* 45 */
TclInExit, /* 46 */
NULL, /* 47 */
NULL, /* 48 */
- TclIncrVar2, /* 49 */
+ NULL, /* 49 */
TclInitCompiledLocals, /* 50 */
TclInterpInit, /* 51 */
- TclInvoke, /* 52 */
+ NULL, /* 52 */
TclInvokeObjectCommand, /* 53 */
TclInvokeStringCommand, /* 54 */
TclIsProc, /* 55 */
@@ -149,9 +139,9 @@ TclIntStubs tclIntStubs = {
TclObjCommandComplete, /* 62 */
TclObjInterpProc, /* 63 */
TclObjInvoke, /* 64 */
- TclObjInvokeGlobal, /* 65 */
- TclOpenFileChannelDeleteProc, /* 66 */
- TclOpenFileChannelInsertProc, /* 67 */
+ NULL, /* 65 */
+ NULL, /* 66 */
+ NULL, /* 67 */
NULL, /* 68 */
TclpAlloc, /* 69 */
NULL, /* 70 */
@@ -178,7 +168,7 @@ TclIntStubs tclIntStubs = {
TclProcCleanupProc, /* 91 */
TclProcCompileProc, /* 92 */
TclProcDeleteProc, /* 93 */
- TclProcInterpProc, /* 94 */
+ NULL, /* 94 */
NULL, /* 95 */
TclRenameCommand, /* 96 */
TclResetShadowedCmdRefs, /* 97 */
@@ -188,18 +178,10 @@ TclIntStubs tclIntStubs = {
TclSetPreInitScript, /* 101 */
TclSetupEnv, /* 102 */
TclSockGetPort, /* 103 */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
TclSockMinimumBuffers, /* 104 */
-#endif /* UNIX */
-#ifdef __WIN32__
- TclSockMinimumBuffers, /* 104 */
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
- NULL, /* 104 */
-#endif /* MAC_TCL */
NULL, /* 105 */
- TclStatDeleteProc, /* 106 */
- TclStatInsertProc, /* 107 */
+ NULL, /* 106 */
+ NULL, /* 107 */
TclTeardownNamespace, /* 108 */
TclUpdateReturnInfo, /* 109 */
NULL, /* 110 */
@@ -226,13 +208,13 @@ TclIntStubs tclIntStubs = {
Tcl_SetNamespaceResolvers, /* 131 */
TclpHasSockets, /* 132 */
TclpGetDate, /* 133 */
- TclpStrftime, /* 134 */
- TclpCheckStackSpace, /* 135 */
+ NULL, /* 134 */
+ NULL, /* 135 */
NULL, /* 136 */
NULL, /* 137 */
TclGetEnv, /* 138 */
NULL, /* 139 */
- TclLooksLikeInt, /* 140 */
+ NULL, /* 140 */
TclpGetCwd, /* 141 */
TclSetByteCodeFromAny, /* 142 */
TclAddLiteralObj, /* 143 */
@@ -267,11 +249,11 @@ TclIntStubs tclIntStubs = {
TclInThreadExit, /* 172 */
TclUniCharMatch, /* 173 */
NULL, /* 174 */
- NULL, /* 175 */
- NULL, /* 176 */
- NULL, /* 177 */
- NULL, /* 178 */
- NULL, /* 179 */
+ TclCallVarTraces, /* 175 */
+ TclCleanupVar, /* 176 */
+ TclVarErrMsg, /* 177 */
+ Tcl_SetStartupScript, /* 178 */
+ Tcl_GetStartupScript, /* 179 */
NULL, /* 180 */
NULL, /* 181 */
TclpLocaltime, /* 182 */
@@ -290,14 +272,64 @@ TclIntStubs tclIntStubs = {
NULL, /* 195 */
NULL, /* 196 */
NULL, /* 197 */
- NULL, /* 198 */
- TclMatchIsTrivial, /* 199 */
+ TclObjGetFrame, /* 198 */
+ NULL, /* 199 */
+ TclpObjRemoveDirectory, /* 200 */
+ TclpObjCopyDirectory, /* 201 */
+ TclpObjCreateDirectory, /* 202 */
+ TclpObjDeleteFile, /* 203 */
+ TclpObjCopyFile, /* 204 */
+ TclpObjRenameFile, /* 205 */
+ TclpObjStat, /* 206 */
+ TclpObjAccess, /* 207 */
+ TclpOpenFileChannel, /* 208 */
+ NULL, /* 209 */
+ NULL, /* 210 */
+ NULL, /* 211 */
+ TclpFindExecutable, /* 212 */
+ TclGetObjNameOfExecutable, /* 213 */
+ TclSetObjNameOfExecutable, /* 214 */
+ TclStackAlloc, /* 215 */
+ TclStackFree, /* 216 */
+ TclPushStackFrame, /* 217 */
+ TclPopStackFrame, /* 218 */
+ NULL, /* 219 */
+ NULL, /* 220 */
+ NULL, /* 221 */
+ NULL, /* 222 */
+ NULL, /* 223 */
+ TclGetPlatform, /* 224 */
+ TclTraceDictPath, /* 225 */
+ TclObjBeingDeleted, /* 226 */
+ TclSetNsPath, /* 227 */
+ TclObjInterpProcCore, /* 228 */
+ TclPtrMakeUpvar, /* 229 */
+ TclObjLookupVar, /* 230 */
+ TclGetNamespaceFromObj, /* 231 */
+ TclEvalObjEx, /* 232 */
+ TclGetSrcInfoForPc, /* 233 */
+ TclVarHashCreateVar, /* 234 */
+ TclInitVarHashTable, /* 235 */
+ TclBackgroundException, /* 236 */
+ NULL, /* 237 */
+ NULL, /* 238 */
+ NULL, /* 239 */
+ NULL, /* 240 */
+ NULL, /* 241 */
+ NULL, /* 242 */
+ TclDbDumpActiveObjects, /* 243 */
+ NULL, /* 244 */
+ NULL, /* 245 */
+ NULL, /* 246 */
+ NULL, /* 247 */
+ NULL, /* 248 */
+ TclDoubleDigits, /* 249 */
};
TclIntPlatStubs tclIntPlatStubs = {
TCL_STUB_MAGIC,
NULL,
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
TclGetAndDetachPids, /* 0 */
TclpCloseFile, /* 1 */
TclpCreateCommandChannel, /* 2 */
@@ -312,8 +344,9 @@ TclIntPlatStubs tclIntPlatStubs = {
TclpLocaltime_unix, /* 11 */
TclpGmtime_unix, /* 12 */
TclpInetNtoa, /* 13 */
+ TclUnixCopyFile, /* 14 */
#endif /* UNIX */
-#ifdef __WIN32__
+#ifdef __WIN32__ /* WIN */
TclWinConvertError, /* 0 */
TclWinConvertWSAError, /* 1 */
TclWinGetServByName, /* 2 */
@@ -339,65 +372,116 @@ TclIntPlatStubs tclIntPlatStubs = {
TclpCreateTempFile, /* 22 */
TclpGetTZName, /* 23 */
TclWinNoBackslash, /* 24 */
- TclWinGetPlatform, /* 25 */
+ NULL, /* 25 */
TclWinSetInterfaces, /* 26 */
TclWinFlushDirtyChannels, /* 27 */
TclWinResetInterfaces, /* 28 */
TclWinCPUID, /* 29 */
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
- TclpSysAlloc, /* 0 */
- TclpSysFree, /* 1 */
- TclpSysRealloc, /* 2 */
- TclpExit, /* 3 */
- FSpGetDefaultDir, /* 4 */
- FSpSetDefaultDir, /* 5 */
- FSpFindFolder, /* 6 */
- GetGlobalMouseTcl, /* 7 */
- FSpGetDirectoryIDTcl, /* 8 */
- FSpOpenResFileCompatTcl, /* 9 */
- FSpCreateResFileCompatTcl, /* 10 */
- FSpLocationFromPath, /* 11 */
- FSpPathFromLocation, /* 12 */
- TclMacExitHandler, /* 13 */
- TclMacInitExitToShell, /* 14 */
- TclMacInstallExitToShellPatch, /* 15 */
- TclMacOSErrorToPosixError, /* 16 */
- TclMacRemoveTimer, /* 17 */
- TclMacStartTimer, /* 18 */
- TclMacTimerExpired, /* 19 */
- TclMacRegisterResourceFork, /* 20 */
- TclMacUnRegisterResourceFork, /* 21 */
- TclMacCreateEnv, /* 22 */
- TclMacFOpenHack, /* 23 */
- TclpGetTZName, /* 24 */
- TclMacChmod, /* 25 */
- FSpLLocationFromPath, /* 26 */
-#endif /* MAC_TCL */
+#endif /* WIN */
+#ifdef MAC_OSX_TCL /* MACOSX */
+ TclGetAndDetachPids, /* 0 */
+ TclpCloseFile, /* 1 */
+ TclpCreateCommandChannel, /* 2 */
+ TclpCreatePipe, /* 3 */
+ TclpCreateProcess, /* 4 */
+ NULL, /* 5 */
+ TclpMakeFile, /* 6 */
+ TclpOpenFile, /* 7 */
+ TclUnixWaitForFile, /* 8 */
+ TclpCreateTempFile, /* 9 */
+ TclpReaddir, /* 10 */
+ TclpLocaltime_unix, /* 11 */
+ TclpGmtime_unix, /* 12 */
+ TclpInetNtoa, /* 13 */
+ TclUnixCopyFile, /* 14 */
+ TclMacOSXGetFileAttribute, /* 15 */
+ TclMacOSXSetFileAttribute, /* 16 */
+ TclMacOSXCopyFileAttributes, /* 17 */
+ TclMacOSXMatchType, /* 18 */
+ TclMacOSXNotifierAddRunLoopMode, /* 19 */
+#endif /* MACOSX */
};
TclPlatStubs tclPlatStubs = {
TCL_STUB_MAGIC,
NULL,
-#ifdef __WIN32__
+#ifdef __WIN32__ /* WIN */
Tcl_WinUtfToTChar, /* 0 */
Tcl_WinTCharToUtf, /* 1 */
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
- Tcl_MacSetEventProc, /* 0 */
- Tcl_MacConvertTextResource, /* 1 */
- Tcl_MacEvalResource, /* 2 */
- Tcl_MacFindResource, /* 3 */
- Tcl_GetOSTypeFromObj, /* 4 */
- Tcl_SetOSTypeObj, /* 5 */
- Tcl_NewOSTypeObj, /* 6 */
- strncasecmp, /* 7 */
- strcasecmp, /* 8 */
-#endif /* MAC_TCL */
-#ifdef MAC_OSX_TCL
+#endif /* WIN */
+#ifdef MAC_OSX_TCL /* MACOSX */
Tcl_MacOSXOpenBundleResources, /* 0 */
Tcl_MacOSXOpenVersionedBundleResources, /* 1 */
-#endif /* MAC_OSX_TCL */
+#endif /* MACOSX */
+};
+
+TclTomMathStubs tclTomMathStubs = {
+ TCL_STUB_MAGIC,
+ NULL,
+ TclBN_epoch, /* 0 */
+ TclBN_revision, /* 1 */
+ TclBN_mp_add, /* 2 */
+ TclBN_mp_add_d, /* 3 */
+ TclBN_mp_and, /* 4 */
+ TclBN_mp_clamp, /* 5 */
+ TclBN_mp_clear, /* 6 */
+ TclBN_mp_clear_multi, /* 7 */
+ TclBN_mp_cmp, /* 8 */
+ TclBN_mp_cmp_d, /* 9 */
+ TclBN_mp_cmp_mag, /* 10 */
+ TclBN_mp_copy, /* 11 */
+ TclBN_mp_count_bits, /* 12 */
+ TclBN_mp_div, /* 13 */
+ TclBN_mp_div_d, /* 14 */
+ TclBN_mp_div_2, /* 15 */
+ TclBN_mp_div_2d, /* 16 */
+ TclBN_mp_div_3, /* 17 */
+ TclBN_mp_exch, /* 18 */
+ TclBN_mp_expt_d, /* 19 */
+ TclBN_mp_grow, /* 20 */
+ TclBN_mp_init, /* 21 */
+ TclBN_mp_init_copy, /* 22 */
+ TclBN_mp_init_multi, /* 23 */
+ TclBN_mp_init_set, /* 24 */
+ TclBN_mp_init_size, /* 25 */
+ TclBN_mp_lshd, /* 26 */
+ TclBN_mp_mod, /* 27 */
+ TclBN_mp_mod_2d, /* 28 */
+ TclBN_mp_mul, /* 29 */
+ TclBN_mp_mul_d, /* 30 */
+ TclBN_mp_mul_2, /* 31 */
+ TclBN_mp_mul_2d, /* 32 */
+ TclBN_mp_neg, /* 33 */
+ TclBN_mp_or, /* 34 */
+ TclBN_mp_radix_size, /* 35 */
+ TclBN_mp_read_radix, /* 36 */
+ TclBN_mp_rshd, /* 37 */
+ TclBN_mp_shrink, /* 38 */
+ TclBN_mp_set, /* 39 */
+ TclBN_mp_sqr, /* 40 */
+ TclBN_mp_sqrt, /* 41 */
+ TclBN_mp_sub, /* 42 */
+ TclBN_mp_sub_d, /* 43 */
+ TclBN_mp_to_unsigned_bin, /* 44 */
+ TclBN_mp_to_unsigned_bin_n, /* 45 */
+ TclBN_mp_toradix_n, /* 46 */
+ TclBN_mp_unsigned_bin_size, /* 47 */
+ TclBN_mp_xor, /* 48 */
+ TclBN_mp_zero, /* 49 */
+ TclBN_reverse, /* 50 */
+ TclBN_fast_s_mp_mul_digs, /* 51 */
+ TclBN_fast_s_mp_sqr, /* 52 */
+ TclBN_mp_karatsuba_mul, /* 53 */
+ TclBN_mp_karatsuba_sqr, /* 54 */
+ TclBN_mp_toom_mul, /* 55 */
+ TclBN_mp_toom_sqr, /* 56 */
+ TclBN_s_mp_add, /* 57 */
+ TclBN_s_mp_mul_digs, /* 58 */
+ TclBN_s_mp_sqr, /* 59 */
+ TclBN_s_mp_sub, /* 60 */
+ TclBN_mp_init_set_int, /* 61 */
+ TclBN_mp_set_int, /* 62 */
+ TclBN_mp_cnt_lsb, /* 63 */
};
static TclStubHooks tclStubHooks = {
@@ -418,24 +502,24 @@ TclStubs tclStubs = {
Tcl_DbCkalloc, /* 6 */
Tcl_DbCkfree, /* 7 */
Tcl_DbCkrealloc, /* 8 */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
Tcl_CreateFileHandler, /* 9 */
#endif /* UNIX */
-#ifdef __WIN32__
- NULL, /* 9 */
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
+#ifdef __WIN32__ /* WIN */
NULL, /* 9 */
-#endif /* MAC_TCL */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+#endif /* WIN */
+#ifdef MAC_OSX_TCL /* MACOSX */
+ Tcl_CreateFileHandler, /* 9 */
+#endif /* MACOSX */
+#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
Tcl_DeleteFileHandler, /* 10 */
#endif /* UNIX */
-#ifdef __WIN32__
- NULL, /* 10 */
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
+#ifdef __WIN32__ /* WIN */
NULL, /* 10 */
-#endif /* MAC_TCL */
+#endif /* WIN */
+#ifdef MAC_OSX_TCL /* MACOSX */
+ Tcl_DeleteFileHandler, /* 10 */
+#endif /* MACOSX */
Tcl_SetTimer, /* 11 */
Tcl_Sleep, /* 12 */
Tcl_WaitForEvent, /* 13 */
@@ -536,15 +620,7 @@ TclStubs tclStubs = {
Tcl_DeleteHashEntry, /* 108 */
Tcl_DeleteHashTable, /* 109 */
Tcl_DeleteInterp, /* 110 */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
- Tcl_DetachPids, /* 111 */
-#endif /* UNIX */
-#ifdef __WIN32__
Tcl_DetachPids, /* 111 */
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
- NULL, /* 111 */
-#endif /* MAC_TCL */
Tcl_DeleteTimerHandler, /* 112 */
Tcl_DeleteTrace, /* 113 */
Tcl_DontCallWhenDeleted, /* 114 */
@@ -600,15 +676,15 @@ TclStubs tclStubs = {
Tcl_GetMaster, /* 164 */
Tcl_GetNameOfExecutable, /* 165 */
Tcl_GetObjResult, /* 166 */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
Tcl_GetOpenFile, /* 167 */
#endif /* UNIX */
-#ifdef __WIN32__
+#ifdef __WIN32__ /* WIN */
NULL, /* 167 */
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
- NULL, /* 167 */
-#endif /* MAC_TCL */
+#endif /* WIN */
+#ifdef MAC_OSX_TCL /* MACOSX */
+ Tcl_GetOpenFile, /* 167 */
+#endif /* MACOSX */
Tcl_GetPathType, /* 168 */
Tcl_Gets, /* 169 */
Tcl_GetsObj, /* 170 */
@@ -638,15 +714,7 @@ TclStubs tclStubs = {
Tcl_NotifyChannel, /* 194 */
Tcl_ObjGetVar2, /* 195 */
Tcl_ObjSetVar2, /* 196 */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
Tcl_OpenCommandChannel, /* 197 */
-#endif /* UNIX */
-#ifdef __WIN32__
- Tcl_OpenCommandChannel, /* 197 */
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
- NULL, /* 197 */
-#endif /* MAC_TCL */
Tcl_OpenFileChannel, /* 198 */
Tcl_OpenTcpClient, /* 199 */
Tcl_OpenTcpServer, /* 200 */
@@ -656,15 +724,7 @@ TclStubs tclStubs = {
Tcl_PosixError, /* 204 */
Tcl_QueueEvent, /* 205 */
Tcl_Read, /* 206 */
-#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
- Tcl_ReapDetachedProcs, /* 207 */
-#endif /* UNIX */
-#ifdef __WIN32__
Tcl_ReapDetachedProcs, /* 207 */
-#endif /* __WIN32__ */
-#ifdef MAC_TCL
- NULL, /* 207 */
-#endif /* MAC_TCL */
Tcl_RecordAndEval, /* 208 */
Tcl_RecordAndEvalObj, /* 209 */
Tcl_RegisterChannel, /* 210 */
@@ -951,86 +1011,92 @@ TclStubs tclStubs = {
Tcl_Seek, /* 491 */
Tcl_Tell, /* 492 */
Tcl_ChannelWideSeekProc, /* 493 */
- NULL, /* 494 */
- NULL, /* 495 */
- NULL, /* 496 */
- NULL, /* 497 */
- NULL, /* 498 */
- NULL, /* 499 */
- NULL, /* 500 */
- NULL, /* 501 */
- NULL, /* 502 */
- NULL, /* 503 */
- NULL, /* 504 */
- NULL, /* 505 */
- NULL, /* 506 */
- NULL, /* 507 */
- NULL, /* 508 */
- NULL, /* 509 */
- NULL, /* 510 */
- NULL, /* 511 */
- NULL, /* 512 */
- NULL, /* 513 */
- NULL, /* 514 */
- NULL, /* 515 */
- NULL, /* 516 */
- NULL, /* 517 */
- NULL, /* 518 */
- NULL, /* 519 */
- NULL, /* 520 */
- NULL, /* 521 */
- NULL, /* 522 */
- NULL, /* 523 */
- NULL, /* 524 */
- NULL, /* 525 */
- NULL, /* 526 */
- NULL, /* 527 */
- NULL, /* 528 */
- NULL, /* 529 */
- NULL, /* 530 */
- NULL, /* 531 */
- NULL, /* 532 */
- NULL, /* 533 */
- NULL, /* 534 */
- NULL, /* 535 */
- NULL, /* 536 */
- NULL, /* 537 */
- NULL, /* 538 */
- NULL, /* 539 */
- NULL, /* 540 */
- NULL, /* 541 */
- NULL, /* 542 */
- NULL, /* 543 */
- NULL, /* 544 */
- NULL, /* 545 */
- NULL, /* 546 */
- NULL, /* 547 */
- NULL, /* 548 */
- NULL, /* 549 */
- NULL, /* 550 */
- NULL, /* 551 */
- NULL, /* 552 */
- NULL, /* 553 */
+ Tcl_DictObjPut, /* 494 */
+ Tcl_DictObjGet, /* 495 */
+ Tcl_DictObjRemove, /* 496 */
+ Tcl_DictObjSize, /* 497 */
+ Tcl_DictObjFirst, /* 498 */
+ Tcl_DictObjNext, /* 499 */
+ Tcl_DictObjDone, /* 500 */
+ Tcl_DictObjPutKeyList, /* 501 */
+ Tcl_DictObjRemoveKeyList, /* 502 */
+ Tcl_NewDictObj, /* 503 */
+ Tcl_DbNewDictObj, /* 504 */
+ Tcl_RegisterConfig, /* 505 */
+ Tcl_CreateNamespace, /* 506 */
+ Tcl_DeleteNamespace, /* 507 */
+ Tcl_AppendExportList, /* 508 */
+ Tcl_Export, /* 509 */
+ Tcl_Import, /* 510 */
+ Tcl_ForgetImport, /* 511 */
+ Tcl_GetCurrentNamespace, /* 512 */
+ Tcl_GetGlobalNamespace, /* 513 */
+ Tcl_FindNamespace, /* 514 */
+ Tcl_FindCommand, /* 515 */
+ Tcl_GetCommandFromObj, /* 516 */
+ Tcl_GetCommandFullName, /* 517 */
+ Tcl_FSEvalFileEx, /* 518 */
+ Tcl_SetExitProc, /* 519 */
+ Tcl_LimitAddHandler, /* 520 */
+ Tcl_LimitRemoveHandler, /* 521 */
+ Tcl_LimitReady, /* 522 */
+ Tcl_LimitCheck, /* 523 */
+ Tcl_LimitExceeded, /* 524 */
+ Tcl_LimitSetCommands, /* 525 */
+ Tcl_LimitSetTime, /* 526 */
+ Tcl_LimitSetGranularity, /* 527 */
+ Tcl_LimitTypeEnabled, /* 528 */
+ Tcl_LimitTypeExceeded, /* 529 */
+ Tcl_LimitTypeSet, /* 530 */
+ Tcl_LimitTypeReset, /* 531 */
+ Tcl_LimitGetCommands, /* 532 */
+ Tcl_LimitGetTime, /* 533 */
+ Tcl_LimitGetGranularity, /* 534 */
+ Tcl_SaveInterpState, /* 535 */
+ Tcl_RestoreInterpState, /* 536 */
+ Tcl_DiscardInterpState, /* 537 */
+ Tcl_SetReturnOptions, /* 538 */
+ Tcl_GetReturnOptions, /* 539 */
+ Tcl_IsEnsemble, /* 540 */
+ Tcl_CreateEnsemble, /* 541 */
+ Tcl_FindEnsemble, /* 542 */
+ Tcl_SetEnsembleSubcommandList, /* 543 */
+ Tcl_SetEnsembleMappingDict, /* 544 */
+ Tcl_SetEnsembleUnknownHandler, /* 545 */
+ Tcl_SetEnsembleFlags, /* 546 */
+ Tcl_GetEnsembleSubcommandList, /* 547 */
+ Tcl_GetEnsembleMappingDict, /* 548 */
+ Tcl_GetEnsembleUnknownHandler, /* 549 */
+ Tcl_GetEnsembleFlags, /* 550 */
+ Tcl_GetEnsembleNamespace, /* 551 */
+ Tcl_SetTimeProc, /* 552 */
+ Tcl_QueryTimeProc, /* 553 */
Tcl_ChannelThreadActionProc, /* 554 */
- NULL, /* 555 */
- NULL, /* 556 */
- NULL, /* 557 */
- NULL, /* 558 */
- NULL, /* 559 */
- NULL, /* 560 */
- NULL, /* 561 */
- NULL, /* 562 */
- NULL, /* 563 */
- NULL, /* 564 */
- NULL, /* 565 */
- NULL, /* 566 */
- NULL, /* 567 */
- NULL, /* 568 */
- NULL, /* 569 */
- NULL, /* 570 */
- NULL, /* 571 */
- NULL, /* 572 */
+ Tcl_NewBignumObj, /* 555 */
+ Tcl_DbNewBignumObj, /* 556 */
+ Tcl_SetBignumObj, /* 557 */
+ Tcl_GetBignumFromObj, /* 558 */
+ Tcl_TakeBignumFromObj, /* 559 */
+ Tcl_TruncateChannel, /* 560 */
+ Tcl_ChannelTruncateProc, /* 561 */
+ Tcl_SetChannelErrorInterp, /* 562 */
+ Tcl_GetChannelErrorInterp, /* 563 */
+ Tcl_SetChannelError, /* 564 */
+ Tcl_GetChannelError, /* 565 */
+ Tcl_InitBignumFromDouble, /* 566 */
+ Tcl_GetNamespaceUnknownHandler, /* 567 */
+ Tcl_SetNamespaceUnknownHandler, /* 568 */
+ Tcl_GetEncodingFromObj, /* 569 */
+ Tcl_GetEncodingSearchPath, /* 570 */
+ Tcl_SetEncodingSearchPath, /* 571 */
+ Tcl_GetEncodingNameFromEnvironment, /* 572 */
Tcl_PkgRequireProc, /* 573 */
+ Tcl_AppendObjToErrorInfo, /* 574 */
+ Tcl_AppendLimitedToObj, /* 575 */
+ Tcl_Format, /* 576 */
+ Tcl_AppendFormatToObj, /* 577 */
+ Tcl_ObjPrintf, /* 578 */
+ Tcl_AppendPrintfToObj, /* 579 */
};
/* !END!: Do not edit above this line. */
diff --git a/generic/tclStubLib.c b/generic/tclStubLib.c
index 1ab7ff3..1f5b436 100644
--- a/generic/tclStubLib.c
+++ b/generic/tclStubLib.c
@@ -1,20 +1,20 @@
-/*
+/*
* tclStubLib.c --
*
- * Stub object that will be statically linked into extensions that wish
+ * Stub object that will be statically linked into extensions that want
* to access Tcl.
*
* Copyright (c) 1998-1999 by Scriptics Corporation.
* Copyright (c) 1998 Paul Duffin.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
/*
- * We need to ensure that we use the stub macros so that this file contains
- * no references to any of the stub functions. This will make it possible
- * to build an extension that references Tcl_InitStubs but doesn't end up
+ * We need to ensure that we use the stub macros so that this file contains no
+ * references to any of the stub functions. This will make it possible to
+ * build an extension that references Tcl_InitStubs but doesn't end up
* including the rest of the stub functions.
*/
@@ -24,46 +24,53 @@
#undef USE_TCL_STUB_PROCS
#include "tclInt.h"
-#include "tclPort.h"
/*
- * Ensure that Tcl_InitStubs is built as an exported symbol. The other stub
- * functions should be built as non-exported symbols.
+ * Tcl_InitStubs and stub table pointers are built as exported symbols.
*/
TclStubs *tclStubsPtr = NULL;
TclPlatStubs *tclPlatStubsPtr = NULL;
TclIntStubs *tclIntStubsPtr = NULL;
TclIntPlatStubs *tclIntPlatStubsPtr = NULL;
-
-static TclStubs * HasStubSupport _ANSI_ARGS_((Tcl_Interp *interp));
+TclTomMathStubs* tclTomMathStubsPtr = NULL;
static TclStubs *
-HasStubSupport (interp)
- Tcl_Interp *interp;
+HasStubSupport(
+ Tcl_Interp *interp)
{
Interp *iPtr = (Interp *) interp;
if (iPtr->stubTable && (iPtr->stubTable->magic == TCL_STUB_MAGIC)) {
return iPtr->stubTable;
}
- interp->result = "This interpreter does not support stubs-enabled extensions.";
- interp->freeProc = TCL_STATIC;
+ interp->result =
+ "This interpreter does not support stubs-enabled extensions.";
+ interp->freeProc = TCL_STATIC;
return NULL;
}
/*
+ * Use our own isdigit to avoid linking to libc on windows
+ */
+
+static int isDigit(const int c)
+{
+ return (c >= '0' && c <= '9');
+}
+
+/*
*----------------------------------------------------------------------
*
* Tcl_InitStubs --
*
- * Tries to initialise the stub table pointers and ensures that
- * the correct version of Tcl is loaded.
+ * Tries to initialise the stub table pointers and ensures that the
+ * correct version of Tcl is loaded.
*
* Results:
- * The actual version of Tcl that satisfies the request, or
- * NULL to indicate that an error occurred.
+ * The actual version of Tcl that satisfies the request, or NULL to
+ * indicate that an error occurred.
*
* Side effects:
* Sets the stub table pointers.
@@ -76,18 +83,18 @@ HasStubSupport (interp)
#endif
CONST char *
-Tcl_InitStubs (interp, version, exact)
- Tcl_Interp *interp;
- CONST char *version;
- int exact;
+Tcl_InitStubs(
+ Tcl_Interp *interp,
+ CONST char *version,
+ int exact)
{
CONST char *actualVersion = NULL;
ClientData pkgData = NULL;
/*
- * We can't optimize this check by caching tclStubsPtr because
- * that prevents apps from being able to load/unload Tcl dynamically
- * multiple times. [Bug 615304]
+ * We can't optimize this check by caching tclStubsPtr because that
+ * prevents apps from being able to load/unload Tcl dynamically multiple
+ * times. [Bug 615304]
*/
tclStubsPtr = HasStubSupport(interp);
@@ -95,10 +102,36 @@ Tcl_InitStubs (interp, version, exact)
return NULL;
}
- actualVersion = Tcl_PkgRequireEx(interp, "Tcl", version, exact, &pkgData);
+ actualVersion = Tcl_PkgRequireEx(interp, "Tcl", version, 0, &pkgData);
if (actualVersion == NULL) {
return NULL;
}
+ if (exact) {
+ CONST char *p = version;
+ int count = 0;
+
+ while (*p) {
+ count += !isDigit(*p++);
+ }
+ if (count == 1) {
+ CONST char *q = actualVersion;
+
+ p = version;
+ while (*p && (*p == *q)) {
+ p++; q++;
+ }
+ if (*p) {
+ /* Construct error message */
+ Tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL);
+ return NULL;
+ }
+ } else {
+ actualVersion = Tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL);
+ if (actualVersion == NULL) {
+ return NULL;
+ }
+ }
+ }
tclStubsPtr = (TclStubs*)pkgData;
if (tclStubsPtr->hooks) {
@@ -110,6 +143,63 @@ Tcl_InitStubs (interp, version, exact)
tclIntStubsPtr = NULL;
tclIntPlatStubsPtr = NULL;
}
-
+
return actualVersion;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclTomMathInitStubs --
+ *
+ * Initializes the Stubs table for Tcl's subset of libtommath
+ *
+ * Results:
+ * Returns a standard Tcl result.
+ *
+ * This procedure should not be called directly, but rather through
+ * the TclTomMath_InitStubs macro, to insure that the Stubs table
+ * matches the header files used in compilation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TclTomMathInitializeStubs
+#undef TclTomMathInitializeStubs
+#endif
+
+CONST char*
+TclTomMathInitializeStubs(
+ Tcl_Interp* interp, /* Tcl interpreter */
+ CONST char* version, /* Tcl version needed */
+ int epoch, /* Stubs table epoch from the header files */
+ int revision /* Stubs table revision number from the
+ * header files */
+) {
+ int exact = 0;
+ const char* packageName = "tcl::tommath";
+ const char* errMsg = NULL;
+ ClientData pkgClientData = NULL;
+ const char* actualVersion =
+ Tcl_PkgRequireEx(interp, packageName, version, exact, &pkgClientData);
+ TclTomMathStubs* stubsPtr = (TclTomMathStubs*) pkgClientData;
+ if (actualVersion == NULL) {
+ return NULL;
+ }
+ if (pkgClientData == NULL) {
+ errMsg = "missing stub table pointer";
+ } else if ((stubsPtr->tclBN_epoch)() != epoch) {
+ errMsg = "epoch number mismatch";
+ } else if ((stubsPtr->tclBN_revision)() != revision) {
+ errMsg = "requires a later revision";
+ } else {
+ tclTomMathStubsPtr = stubsPtr;
+ return actualVersion;
+ }
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "error loading ", packageName,
+ " (requested version ", version,
+ ", actual version ", actualVersion,
+ "): ", errMsg, NULL);
+ return NULL;
+}
diff --git a/generic/tclTest.c b/generic/tclTest.c
index 9acbc5e..130bc38 100644
--- a/generic/tclTest.c
+++ b/generic/tclTest.c
@@ -1,23 +1,24 @@
-/*
+/*
* tclTest.c --
*
- * This file contains C command procedures for a bunch of additional
- * Tcl commands that are used for testing out Tcl's C interfaces.
- * These commands are not normally included in Tcl applications;
- * they're only used for testing.
+ * This file contains C command functions for a bunch of additional Tcl
+ * commands that are used for testing out Tcl's C interfaces. These
+ * commands are not normally included in Tcl applications; they're only
+ * used for testing.
*
* Copyright (c) 1993-1994 The Regents of the University of California.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
* Copyright (c) 1998-2000 Ajuba Solutions.
* Copyright (c) 2003 by Kevin B. Kenny. All rights reserved.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
+#include <math.h>
+
#define TCL_TEST
#include "tclInt.h"
-#include "tclPort.h"
/*
* Required for Testregexp*Cmd
@@ -39,56 +40,57 @@
*/
/*
- * Dynamic string shared by TestdcallCmd and DelCallbackProc; used
- * to collect the results of the various deletion callbacks.
+ * Dynamic string shared by TestdcallCmd and DelCallbackProc; used to collect
+ * the results of the various deletion callbacks.
*/
static Tcl_DString delString;
static Tcl_Interp *delInterp;
/*
- * One of the following structures exists for each asynchronous
- * handler created by the "testasync" command".
+ * One of the following structures exists for each asynchronous handler
+ * created by the "testasync" command".
*/
typedef struct TestAsyncHandler {
- int id; /* Identifier for this handler. */
- Tcl_AsyncHandler handler; /* Tcl's token for the handler. */
- char *command; /* Command to invoke when the
- * handler is invoked. */
- struct TestAsyncHandler *nextPtr; /* Next is list of handlers. */
+ int id; /* Identifier for this handler. */
+ Tcl_AsyncHandler handler; /* Tcl's token for the handler. */
+ char *command; /* Command to invoke when the handler is
+ * invoked. */
+ struct TestAsyncHandler *nextPtr;
+ /* Next is list of handlers. */
} TestAsyncHandler;
static TestAsyncHandler *firstHandler = NULL;
/*
- * The dynamic string below is used by the "testdstring" command
- * to test the dynamic string facilities.
+ * The dynamic string below is used by the "testdstring" command to test the
+ * dynamic string facilities.
*/
static Tcl_DString dstring;
/*
- * The command trace below is used by the "testcmdtraceCmd" command
- * to test the command tracing facilities.
+ * The command trace below is used by the "testcmdtraceCmd" command to test
+ * the command tracing facilities.
*/
static Tcl_Trace cmdTrace;
/*
- * One of the following structures exists for each command created
- * by TestdelCmd:
+ * One of the following structures exists for each command created by
+ * TestdelCmd:
*/
typedef struct DelCmd {
Tcl_Interp *interp; /* Interpreter in which command exists. */
- char *deleteCmd; /* Script to execute when command is
- * deleted. Malloc'ed. */
+ char *deleteCmd; /* Script to execute when command is deleted.
+ * Malloc'ed. */
} DelCmd;
/*
* The following is used to keep track of an encoding that invokes a Tcl
- * command.
+ * command.
*/
typedef struct TclEncoding {
@@ -98,332 +100,343 @@ typedef struct TclEncoding {
} TclEncoding;
/*
- * The counter below is used to determine if the TestsaveresultFree
- * routine was called for a result.
+ * The counter below is used to determine if the TestsaveresultFree routine
+ * was called for a result.
*/
static int freeCount;
/*
- * Boolean flag used by the "testsetmainloop" and "testexitmainloop"
- * commands.
+ * Boolean flag used by the "testsetmainloop" and "testexitmainloop" commands.
*/
+
static int exitMainLoop = 0;
/*
* Event structure used in testing the event queue management procedures.
*/
+
typedef struct TestEvent {
Tcl_Event header; /* Header common to all events */
- Tcl_Interp* interp; /* Interpreter that will handle the event */
- Tcl_Obj* command; /* Command to evaluate when the event occurs */
- Tcl_Obj* tag; /* Tag for this event used to delete it */
+ Tcl_Interp *interp; /* Interpreter that will handle the event */
+ Tcl_Obj *command; /* Command to evaluate when the event occurs */
+ Tcl_Obj *tag; /* Tag for this event used to delete it */
} TestEvent;
/*
+ * Simple detach/attach facility for testchannel cut|splice. Allow testing of
+ * channel transfer in core testsuite.
+ */
+
+typedef struct TestChannel {
+ Tcl_Channel chan; /* Detached channel */
+ struct TestChannel *nextPtr;/* Next in detached channel pool */
+} TestChannel;
+
+static TestChannel *firstDetached;
+
+/*
* Forward declarations for procedures defined later in this file:
*/
-int Tcltest_Init _ANSI_ARGS_((Tcl_Interp *interp));
-static int AsyncHandlerProc _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int code));
-static void CleanupTestSetassocdataTests _ANSI_ARGS_((
- ClientData clientData, Tcl_Interp *interp));
-static void CmdDelProc1 _ANSI_ARGS_((ClientData clientData));
-static void CmdDelProc2 _ANSI_ARGS_((ClientData clientData));
-static int CmdProc1 _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int CmdProc2 _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static void CmdTraceDeleteProc _ANSI_ARGS_((
+int Tcltest_Init(Tcl_Interp *interp);
+static int AsyncHandlerProc(ClientData clientData,
+ Tcl_Interp *interp, int code);
+#ifdef TCL_THREADS
+static Tcl_ThreadCreateType AsyncThreadProc(ClientData);
+#endif
+static void CleanupTestSetassocdataTests(
+ ClientData clientData, Tcl_Interp *interp);
+static void CmdDelProc1(ClientData clientData);
+static void CmdDelProc2(ClientData clientData);
+static int CmdProc1(ClientData clientData,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int CmdProc2(ClientData clientData,
+ Tcl_Interp *interp, int argc, const char **argv);
+static void CmdTraceDeleteProc(
ClientData clientData, Tcl_Interp *interp,
int level, char *command, Tcl_CmdProc *cmdProc,
ClientData cmdClientData, int argc,
- char **argv));
-static void CmdTraceProc _ANSI_ARGS_((ClientData clientData,
+ char **argv);
+static void CmdTraceProc(ClientData clientData,
Tcl_Interp *interp, int level, char *command,
Tcl_CmdProc *cmdProc, ClientData cmdClientData,
- int argc, char **argv));
-static int CreatedCommandProc _ANSI_ARGS_((
+ int argc, char **argv);
+static int CreatedCommandProc(
ClientData clientData, Tcl_Interp *interp,
- int argc, CONST char **argv));
-static int CreatedCommandProc2 _ANSI_ARGS_((
+ int argc, const char **argv);
+static int CreatedCommandProc2(
ClientData clientData, Tcl_Interp *interp,
- int argc, CONST char **argv));
-static void DelCallbackProc _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp));
-static int DelCmdProc _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static void DelDeleteProc _ANSI_ARGS_((ClientData clientData));
-static void EncodingFreeProc _ANSI_ARGS_((ClientData clientData));
-static int EncodingToUtfProc _ANSI_ARGS_((ClientData clientData,
- CONST char *src, int srcLen, int flags,
+ int argc, const char **argv);
+static void DelCallbackProc(ClientData clientData,
+ Tcl_Interp *interp);
+static int DelCmdProc(ClientData clientData,
+ Tcl_Interp *interp, int argc, const char **argv);
+static void DelDeleteProc(ClientData clientData);
+static void EncodingFreeProc(ClientData clientData);
+static int EncodingToUtfProc(ClientData clientData,
+ const char *src, int srcLen, int flags,
Tcl_EncodingState *statePtr, char *dst,
int dstLen, int *srcReadPtr, int *dstWrotePtr,
- int *dstCharsPtr));
-static int EncodingFromUtfProc _ANSI_ARGS_((ClientData clientData,
- CONST char *src, int srcLen, int flags,
+ int *dstCharsPtr);
+static int EncodingFromUtfProc(ClientData clientData,
+ const char *src, int srcLen, int flags,
Tcl_EncodingState *statePtr, char *dst,
int dstLen, int *srcReadPtr, int *dstWrotePtr,
- int *dstCharsPtr));
-static void ExitProcEven _ANSI_ARGS_((ClientData clientData));
-static void ExitProcOdd _ANSI_ARGS_((ClientData clientData));
-static int GetTimesCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static void MainLoop _ANSI_ARGS_((void));
-static int NoopCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int NoopObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int ObjTraceProc _ANSI_ARGS_(( ClientData clientData,
- Tcl_Interp* interp,
- int level,
- CONST char* command,
- Tcl_Command commandToken,
- int objc,
- Tcl_Obj *CONST objv[] ));
-static void ObjTraceDeleteProc _ANSI_ARGS_(( ClientData ));
-static void PrintParse _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Parse *parsePtr));
-static void SpecialFree _ANSI_ARGS_((char *blockPtr));
-static int StaticInitProc _ANSI_ARGS_((Tcl_Interp *interp));
-static int TestaccessprocCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int PretendTclpAccess _ANSI_ARGS_((CONST char *path,
- int mode));
-static int TestAccessProc1 _ANSI_ARGS_((CONST char *path,
- int mode));
-static int TestAccessProc2 _ANSI_ARGS_((CONST char *path,
- int mode));
-static int TestAccessProc3 _ANSI_ARGS_((CONST char *path,
- int mode));
-static int TestasyncCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestcmdinfoCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestcmdtokenCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestcmdtraceCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestcreatecommandCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestdcallCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestdelCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestdelassocdataCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestdstringCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestencodingObjCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int TestevalexObjCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int TestevalobjvObjCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int TesteventObjCmd _ANSI_ARGS_((ClientData unused,
- Tcl_Interp* interp,
- int argc,
- Tcl_Obj *CONST objv[]));
-static int TesteventProc _ANSI_ARGS_((Tcl_Event* event,
- int flags));
-static int TesteventDeleteProc _ANSI_ARGS_((
- Tcl_Event* event,
- ClientData clientData));
-static int TestexithandlerCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestexprlongCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestexprlongobjCmd _ANSI_ARGS_((ClientData dummy,
+ int *dstCharsPtr);
+static void ExitProcEven(ClientData clientData);
+static void ExitProcOdd(ClientData clientData);
+static int GetTimesCmd(ClientData clientData,
+ Tcl_Interp *interp, int argc, const char **argv);
+static void MainLoop(void);
+static int NoopCmd(ClientData clientData,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int NoopObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int ObjTraceProc(ClientData clientData,
+ Tcl_Interp *interp, int level, const char *command,
+ Tcl_Command commandToken, int objc,
+ Tcl_Obj *const objv[]);
+static void ObjTraceDeleteProc(ClientData clientData);
+static void PrintParse(Tcl_Interp *interp, Tcl_Parse *parsePtr);
+static void SpecialFree(char *blockPtr);
+static int StaticInitProc(Tcl_Interp *interp);
+#undef USE_OBSOLETE_FS_HOOKS
+#ifdef USE_OBSOLETE_FS_HOOKS
+static int TestaccessprocCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestopenfilechannelprocCmd(
+ ClientData dummy, Tcl_Interp *interp, int argc,
+ const char **argv);
+static int TeststatprocCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int PretendTclpAccess(const char *path, int mode);
+static int TestAccessProc1(const char *path, int mode);
+static int TestAccessProc2(const char *path, int mode);
+static int TestAccessProc3(const char *path, int mode);
+static Tcl_Channel PretendTclpOpenFileChannel(
+ Tcl_Interp *interp, const char *fileName,
+ const char *modeString, int permissions);
+static Tcl_Channel TestOpenFileChannelProc1(
+ Tcl_Interp *interp, const char *fileName,
+ const char *modeString, int permissions);
+static Tcl_Channel TestOpenFileChannelProc2(
+ Tcl_Interp *interp, const char *fileName,
+ const char *modeString, int permissions);
+static Tcl_Channel TestOpenFileChannelProc3(
+ Tcl_Interp *interp, const char *fileName,
+ const char *modeString, int permissions);
+static int PretendTclpStat(const char *path, struct stat *buf);
+static int TestStatProc1(const char *path, struct stat *buf);
+static int TestStatProc2(const char *path, struct stat *buf);
+static int TestStatProc3(const char *path, struct stat *buf);
+#endif
+static int TestasyncCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestcmdinfoCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestcmdtokenCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestcmdtraceCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestconcatobjCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestcreatecommandCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestdcallCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestdelCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestdelassocdataCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestdoubledigitsObjCmd(ClientData dummy,
+ Tcl_Interp* interp,
+ int objc, Tcl_Obj* const objv[]);
+static int TestdstringCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestencodingObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int TestevalexObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int TestevalobjvObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int TesteventObjCmd(ClientData unused,
+ Tcl_Interp *interp, int argc,
+ Tcl_Obj *const objv[]);
+static int TesteventProc(Tcl_Event *event, int flags);
+static int TesteventDeleteProc(Tcl_Event *event,
+ ClientData clientData);
+static int TestexithandlerCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestexprlongCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestexprlongobjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int TestexprdoubleCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestexprdoubleobjCmd(ClientData dummy,
Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int TestexprparserObjCmd _ANSI_ARGS_((ClientData dummy,
+ Tcl_Obj *const objv[]);
+static int TestexprparserObjCmd(ClientData dummy,
Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int TestexprstringCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestfileCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-static int TestfilelinkCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-static int TestfeventCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestgetassocdataCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestgetplatformCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestgetvarfullnameCmd _ANSI_ARGS_((
+ Tcl_Obj *const objv[]);
+static int TestexprstringCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestfileCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
+static int TestfilelinkCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
+static int TestfeventCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestgetassocdataCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestgetintCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestgetplatformCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestgetvarfullnameCmd(
ClientData dummy, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-static int TestinterpdeleteCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestlinkCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestlocaleCmd _ANSI_ARGS_((ClientData dummy,
+ int objc, Tcl_Obj *const objv[]);
+static int TestinterpdeleteCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestlinkCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestlocaleCmd(ClientData dummy,
Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int TestMathFunc _ANSI_ARGS_((ClientData clientData,
+ Tcl_Obj *const objv[]);
+static int TestMathFunc(ClientData clientData,
Tcl_Interp *interp, Tcl_Value *args,
- Tcl_Value *resultPtr));
-static int TestMathFunc2 _ANSI_ARGS_((ClientData clientData,
+ Tcl_Value *resultPtr);
+static int TestMathFunc2(ClientData clientData,
Tcl_Interp *interp, Tcl_Value *args,
- Tcl_Value *resultPtr));
-static int TestmainthreadCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestsetmainloopCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestexitmainloopCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static Tcl_Channel PretendTclpOpenFileChannel _ANSI_ARGS_((
- Tcl_Interp *interp, CONST char *fileName,
- CONST char *modeString, int permissions));
-static Tcl_Channel TestOpenFileChannelProc1 _ANSI_ARGS_((
- Tcl_Interp *interp, CONST char *fileName,
- CONST char *modeString, int permissions));
-static Tcl_Channel TestOpenFileChannelProc2 _ANSI_ARGS_((
- Tcl_Interp *interp, CONST char *fileName,
- CONST char *modeString, int permissions));
-static Tcl_Channel TestOpenFileChannelProc3 _ANSI_ARGS_((
- Tcl_Interp *interp, CONST char *fileName,
- CONST char *modeString, int permissions));
-static int TestpanicCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestparserObjCmd _ANSI_ARGS_((ClientData dummy,
+ Tcl_Value *resultPtr);
+static int TestmainthreadCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestsetmainloopCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestexitmainloopCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestpanicCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestparserObjCmd(ClientData dummy,
Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int TestparsevarObjCmd _ANSI_ARGS_((ClientData dummy,
+ Tcl_Obj *const objv[]);
+static int TestparsevarObjCmd(ClientData dummy,
Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int TestparsevarnameObjCmd _ANSI_ARGS_((ClientData dummy,
+ Tcl_Obj *const objv[]);
+static int TestparsevarnameObjCmd(ClientData dummy,
Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int TestregexpObjCmd _ANSI_ARGS_((ClientData dummy,
+ Tcl_Obj *const objv[]);
+static int TestregexpObjCmd(ClientData dummy,
Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static void TestregexpXflags _ANSI_ARGS_((char *string,
- int length, int *cflagsPtr, int *eflagsPtr));
-static int TestsaveresultCmd _ANSI_ARGS_((ClientData dummy,
+ Tcl_Obj *const objv[]);
+static int TestreturnObjCmd(ClientData dummy,
Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static void TestsaveresultFree _ANSI_ARGS_((char *blockPtr));
-static int TestsetassocdataCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestsetCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestseterrorcodeCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestsetobjerrorcodeCmd _ANSI_ARGS_((
+ Tcl_Obj *const objv[]);
+static void TestregexpXflags(char *string,
+ int length, int *cflagsPtr, int *eflagsPtr);
+static int TestsaveresultCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static void TestsaveresultFree(char *blockPtr);
+static int TestsetassocdataCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestsetCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int Testset2Cmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestseterrorcodeCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestsetobjerrorcodeCmd(
ClientData dummy, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-static int TestopenfilechannelprocCmd _ANSI_ARGS_((
- ClientData dummy, Tcl_Interp *interp, int argc,
- CONST char **argv));
-static int TestsetplatformCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TeststaticpkgCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int PretendTclpStat _ANSI_ARGS_((CONST char *path,
- Tcl_StatBuf *buf));
-static int TestStatProc1 _ANSI_ARGS_((CONST char *path,
- Tcl_StatBuf *buf));
-static int TestStatProc2 _ANSI_ARGS_((CONST char *path,
- Tcl_StatBuf *buf));
-static int TestStatProc3 _ANSI_ARGS_((CONST char *path,
- Tcl_StatBuf *buf));
-static int TeststatprocCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TesttranslatefilenameCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestupvarCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestWrongNumArgsObjCmd _ANSI_ARGS_((
+ int objc, Tcl_Obj *const objv[]);
+static int TestsetplatformCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TeststaticpkgCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TesttranslatefilenameCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestupvarCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestWrongNumArgsObjCmd(
ClientData clientData, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-static int TestGetIndexFromObjStructObjCmd _ANSI_ARGS_((
+ int objc, Tcl_Obj *const objv[]);
+static int TestGetIndexFromObjStructObjCmd(
ClientData clientData, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[]));
-static int TestChannelCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestChannelEventCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, CONST char **argv));
-/* Filesystem testing */
-
-static int TestFilesystemObjCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int TestSimpleFilesystemObjCmd _ANSI_ARGS_((
- ClientData dummy, Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-
-static void TestReport _ANSI_ARGS_ ((CONST char* cmd, Tcl_Obj* arg1,
- Tcl_Obj* arg2));
-
-static Tcl_Obj* TestReportGetNativePath _ANSI_ARGS_ ((
- Tcl_Obj* pathObjPtr));
-
-static int TestReportStat _ANSI_ARGS_ ((Tcl_Obj *path,
- Tcl_StatBuf *buf));
-static int TestReportAccess _ANSI_ARGS_ ((Tcl_Obj *path,
- int mode));
-static Tcl_Channel TestReportOpenFileChannel _ANSI_ARGS_ ((
+ int objc, Tcl_Obj *const objv[]);
+static int TestChannelCmd(ClientData clientData,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestChannelEventCmd(ClientData clientData,
+ Tcl_Interp *interp, int argc, const char **argv);
+static int TestFilesystemObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int TestSimpleFilesystemObjCmd(
+ ClientData dummy, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static void TestReport(const char *cmd, Tcl_Obj *arg1,
+ Tcl_Obj *arg2);
+static Tcl_Obj * TestReportGetNativePath(Tcl_Obj *pathPtr);
+static int TestReportStat(Tcl_Obj *path, Tcl_StatBuf *buf);
+static int TestReportAccess(Tcl_Obj *path, int mode);
+static Tcl_Channel TestReportOpenFileChannel(
Tcl_Interp *interp, Tcl_Obj *fileName,
- int mode, int permissions));
-static int TestReportMatchInDirectory _ANSI_ARGS_ ((
+ int mode, int permissions);
+static int TestReportMatchInDirectory(Tcl_Interp *interp,
+ Tcl_Obj *resultPtr, Tcl_Obj *dirPtr,
+ const char *pattern, Tcl_GlobTypeData *types);
+static int TestReportChdir(Tcl_Obj *dirName);
+static int TestReportLstat(Tcl_Obj *path, Tcl_StatBuf *buf);
+static int TestReportCopyFile(Tcl_Obj *src, Tcl_Obj *dst);
+static int TestReportDeleteFile(Tcl_Obj *path);
+static int TestReportRenameFile(Tcl_Obj *src, Tcl_Obj *dst);
+static int TestReportCreateDirectory(Tcl_Obj *path);
+static int TestReportCopyDirectory(Tcl_Obj *src,
+ Tcl_Obj *dst, Tcl_Obj **errorPtr);
+static int TestReportRemoveDirectory(Tcl_Obj *path,
+ int recursive, Tcl_Obj **errorPtr);
+static int TestReportLoadFile(Tcl_Interp *interp,
+ Tcl_Obj *fileName, Tcl_LoadHandle *handlePtr,
+ Tcl_FSUnloadFileProc **unloadProcPtr);
+static Tcl_Obj * TestReportLink(Tcl_Obj *path,
+ Tcl_Obj *to, int linkType);
+static const char ** TestReportFileAttrStrings(
+ Tcl_Obj *fileName, Tcl_Obj **objPtrRef);
+static int TestReportFileAttrsGet(Tcl_Interp *interp,
+ int index, Tcl_Obj *fileName, Tcl_Obj **objPtrRef);
+static int TestReportFileAttrsSet(Tcl_Interp *interp,
+ int index, Tcl_Obj *fileName, Tcl_Obj *objPtr);
+static int TestReportUtime(Tcl_Obj *fileName,
+ struct utimbuf *tval);
+static int TestReportNormalizePath(Tcl_Interp *interp,
+ Tcl_Obj *pathPtr, int nextCheckpoint);
+static int TestReportInFilesystem(Tcl_Obj *pathPtr, ClientData *clientDataPtr);
+static void TestReportFreeInternalRep(ClientData clientData);
+static ClientData TestReportDupInternalRep(ClientData clientData);
+
+static int SimpleStat(Tcl_Obj *path, Tcl_StatBuf *buf);
+static int SimpleAccess(Tcl_Obj *path, int mode);
+static Tcl_Channel SimpleOpenFileChannel(Tcl_Interp *interp,
+ Tcl_Obj *fileName, int mode, int permissions);
+static Tcl_Obj * SimpleListVolumes(void);
+static int SimplePathInFilesystem(
+ Tcl_Obj *pathPtr, ClientData *clientDataPtr);
+static Tcl_Obj * SimpleRedirect(Tcl_Obj *pathPtr);
+static int SimpleMatchInDirectory(
Tcl_Interp *interp, Tcl_Obj *resultPtr,
- Tcl_Obj *dirPtr, CONST char *pattern,
- Tcl_GlobTypeData *types));
-static int TestReportChdir _ANSI_ARGS_ ((Tcl_Obj *dirName));
-static int TestReportLstat _ANSI_ARGS_ ((Tcl_Obj *path,
- Tcl_StatBuf *buf));
-static int TestReportCopyFile _ANSI_ARGS_ ((Tcl_Obj *src,
- Tcl_Obj *dst));
-static int TestReportDeleteFile _ANSI_ARGS_ ((Tcl_Obj *path));
-static int TestReportRenameFile _ANSI_ARGS_ ((Tcl_Obj *src,
- Tcl_Obj *dst));
-static int TestReportCreateDirectory _ANSI_ARGS_ ((Tcl_Obj *path));
-static int TestReportCopyDirectory _ANSI_ARGS_ ((Tcl_Obj *src,
- Tcl_Obj *dst, Tcl_Obj **errorPtr));
-static int TestReportRemoveDirectory _ANSI_ARGS_ ((Tcl_Obj *path,
- int recursive, Tcl_Obj **errorPtr));
-static int TestReportLoadFile _ANSI_ARGS_ ((Tcl_Interp *interp,
- Tcl_Obj *fileName,
- Tcl_LoadHandle *handlePtr,
- Tcl_FSUnloadFileProc **unloadProcPtr));
-static Tcl_Obj * TestReportLink _ANSI_ARGS_ ((Tcl_Obj *path,
- Tcl_Obj *to, int linkType));
-static CONST char** TestReportFileAttrStrings _ANSI_ARGS_ ((
- Tcl_Obj *fileName, Tcl_Obj **objPtrRef));
-static int TestReportFileAttrsGet _ANSI_ARGS_ ((Tcl_Interp *interp,
- int index, Tcl_Obj *fileName, Tcl_Obj **objPtrRef));
-static int TestReportFileAttrsSet _ANSI_ARGS_ ((Tcl_Interp *interp,
- int index, Tcl_Obj *fileName, Tcl_Obj *objPtr));
-static int TestReportUtime _ANSI_ARGS_ ((Tcl_Obj *fileName,
- struct utimbuf *tval));
-static int TestReportNormalizePath _ANSI_ARGS_ ((
- Tcl_Interp *interp, Tcl_Obj *pathPtr,
- int nextCheckpoint));
-static int TestReportInFilesystem _ANSI_ARGS_ ((Tcl_Obj *pathPtr, ClientData *clientDataPtr));
-static void TestReportFreeInternalRep _ANSI_ARGS_ ((ClientData clientData));
-static ClientData TestReportDupInternalRep _ANSI_ARGS_ ((ClientData clientData));
-
-static int SimpleStat _ANSI_ARGS_ ((Tcl_Obj *path,
- Tcl_StatBuf *buf));
-static int SimpleAccess _ANSI_ARGS_ ((Tcl_Obj *path,
- int mode));
-static Tcl_Channel SimpleOpenFileChannel _ANSI_ARGS_ ((
- Tcl_Interp *interp, Tcl_Obj *fileName,
- int mode, int permissions));
-static Tcl_Obj* SimpleListVolumes _ANSI_ARGS_ ((void));
-static int SimplePathInFilesystem _ANSI_ARGS_ ((
- Tcl_Obj *pathPtr, ClientData *clientDataPtr));
-static Tcl_Obj* SimpleCopy _ANSI_ARGS_ ((Tcl_Obj *pathPtr));
-static int TestNumUtfCharsCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
+ Tcl_Obj *dirPtr, const char *pattern,
+ Tcl_GlobTypeData *types);
+static int TestNumUtfCharsCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int TestHashSystemHashCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
static Tcl_Filesystem testReportingFilesystem = {
"reporting",
@@ -448,11 +461,11 @@ static Tcl_Filesystem testReportingFilesystem = {
&TestReportFileAttrsGet,
&TestReportFileAttrsSet,
&TestReportCreateDirectory,
- &TestReportRemoveDirectory,
+ &TestReportRemoveDirectory,
&TestReportDeleteFile,
&TestReportCopyFile,
&TestReportRenameFile,
- &TestReportCopyDirectory,
+ &TestReportCopyDirectory,
&TestReportLstat,
&TestReportLoadFile,
NULL /* cwd */,
@@ -480,7 +493,7 @@ static Tcl_Filesystem simpleFilesystem = {
&SimpleStat,
&SimpleAccess,
&SimpleOpenFileChannel,
- NULL,
+ &SimpleMatchInDirectory,
NULL,
/* We choose not to support symbolic links inside our vfs's */
NULL,
@@ -489,14 +502,14 @@ static Tcl_Filesystem simpleFilesystem = {
NULL,
NULL,
NULL,
- NULL,
+ NULL,
NULL,
/* No copy file - fallback will occur at Tcl level */
NULL,
/* No rename file - fallback will occur at Tcl level */
NULL,
/* No copy directory - fallback will occur at Tcl level */
- NULL,
+ NULL,
/* Use stat for lstat */
NULL,
/* No load - fallback on core implementation */
@@ -509,25 +522,25 @@ static Tcl_Filesystem simpleFilesystem = {
/*
* External (platform specific) initialization routine, these declarations
- * explicitly don't use EXTERN since this code does not get compiled
- * into the library:
+ * explicitly don't use EXTERN since this code does not get compiled into the
+ * library:
*/
-extern int TclplatformtestInit _ANSI_ARGS_((Tcl_Interp *interp));
-extern int TclThread_Init _ANSI_ARGS_((Tcl_Interp *interp));
+extern int TclplatformtestInit(Tcl_Interp *interp);
+extern int TclThread_Init(Tcl_Interp *interp);
/*
*----------------------------------------------------------------------
*
* Tcltest_Init --
*
- * This procedure performs application-specific initialization.
- * Most applications, especially those that incorporate additional
- * packages, will have their own version of this procedure.
+ * 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.
+ * 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.
@@ -536,159 +549,157 @@ extern int TclThread_Init _ANSI_ARGS_((Tcl_Interp *interp));
*/
int
-Tcltest_Init(interp)
- Tcl_Interp *interp; /* Interpreter for application. */
+Tcltest_Init(
+ Tcl_Interp *interp) /* Interpreter for application. */
{
Tcl_ValueType t3ArgTypes[2];
Tcl_Obj *listPtr;
Tcl_Obj **objv;
int objc, index;
- static CONST char *specialOptions[] = {
+ static const char *specialOptions[] = {
"-appinitprocerror", "-appinitprocdeleteinterp",
- "-appinitprocclosestderr", "-appinitprocsetrcfile", (char *) NULL
+ "-appinitprocclosestderr", "-appinitprocsetrcfile", NULL
};
-#ifndef TCL_TIP268
- if (Tcl_PkgProvide(interp, "Tcltest", TCL_VERSION) == TCL_ERROR) {
-#else
/* TIP #268: Full patchlevel instead of just major.minor */
+
if (Tcl_PkgProvide(interp, "Tcltest", TCL_PATCH_LEVEL) == TCL_ERROR) {
-#endif
- return TCL_ERROR;
+ return TCL_ERROR;
}
/*
* Create additional commands and math functions for testing Tcl.
*/
- Tcl_CreateCommand(interp, "gettimes", GetTimesCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
- Tcl_CreateCommand(interp, "noop", NoopCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
- Tcl_CreateObjCommand(interp, "noop", NoopObjCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
+ Tcl_CreateCommand(interp, "gettimes", GetTimesCmd, (ClientData) 0, NULL);
+ Tcl_CreateCommand(interp, "noop", NoopCmd, (ClientData) 0, NULL);
+ Tcl_CreateObjCommand(interp, "noop", NoopObjCmd, (ClientData) 0, NULL);
Tcl_CreateObjCommand(interp, "testwrongnumargs", TestWrongNumArgsObjCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
- Tcl_CreateObjCommand(interp, "testfilesystem", TestFilesystemObjCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
- Tcl_CreateObjCommand(interp, "testsimplefilesystem", TestSimpleFilesystemObjCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
+ Tcl_CreateObjCommand(interp, "testfilesystem", TestFilesystemObjCmd,
+ (ClientData) 0, NULL);
+ Tcl_CreateObjCommand(interp, "testsimplefilesystem", TestSimpleFilesystemObjCmd,
+ (ClientData) 0, NULL);
Tcl_CreateObjCommand(interp, "testgetindexfromobjstruct",
- TestGetIndexFromObjStructObjCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
+ TestGetIndexFromObjStructObjCmd, (ClientData) 0, NULL);
+#ifdef USE_OBSOLETE_FS_HOOKS
Tcl_CreateCommand(interp, "testaccessproc", TestaccessprocCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
- Tcl_CreateCommand(interp, "testasync", TestasyncCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
+ NULL);
+ Tcl_CreateCommand(interp, "testopenfilechannelproc",
+ TestopenfilechannelprocCmd, (ClientData) 0, NULL);
+ Tcl_CreateCommand(interp, "teststatproc", TeststatprocCmd, (ClientData) 0,
+ NULL);
+#endif
+ Tcl_CreateCommand(interp, "testasync", TestasyncCmd, (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testchannel", TestChannelCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testchannelevent", TestChannelEventCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testcmdtoken", TestcmdtokenCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
+ NULL);
Tcl_CreateCommand(interp, "testcmdinfo", TestcmdinfoCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
+ NULL);
Tcl_CreateCommand(interp, "testcmdtrace", TestcmdtraceCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
+ Tcl_CreateCommand(interp, "testconcatobj", TestconcatobjCmd,
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testcreatecommand", TestcreatecommandCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
- Tcl_CreateCommand(interp, "testdcall", TestdcallCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
- Tcl_CreateCommand(interp, "testdel", TestdelCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
+ Tcl_CreateCommand(interp, "testdcall", TestdcallCmd, (ClientData) 0, NULL);
+ Tcl_CreateCommand(interp, "testdel", TestdelCmd, (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testdelassocdata", TestdelassocdataCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
+ Tcl_CreateObjCommand(interp, "testdoubledigits", TestdoubledigitsObjCmd,
+ NULL, NULL);
Tcl_DStringInit(&dstring);
Tcl_CreateCommand(interp, "testdstring", TestdstringCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
+ NULL);
Tcl_CreateObjCommand(interp, "testencoding", TestencodingObjCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
+ NULL);
Tcl_CreateObjCommand(interp, "testevalex", TestevalexObjCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateObjCommand(interp, "testevalobjv", TestevalobjvObjCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
- Tcl_CreateObjCommand( interp, "testevent", TesteventObjCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc*) NULL );
+ (ClientData) 0, NULL);
+ Tcl_CreateObjCommand(interp, "testevent", TesteventObjCmd,
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testexithandler", TestexithandlerCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testexprlong", TestexprlongCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateObjCommand(interp, "testexprlongobj", TestexprlongobjCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
+ Tcl_CreateCommand(interp, "testexprdouble", TestexprdoubleCmd,
+ (ClientData) 0, NULL);
+ Tcl_CreateObjCommand(interp, "testexprdoubleobj", TestexprdoubleobjCmd,
+ (ClientData) 0, NULL);
Tcl_CreateObjCommand(interp, "testexprparser", TestexprparserObjCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testexprstring", TestexprstringCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testfevent", TestfeventCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
- Tcl_CreateObjCommand(interp, "testfilelink", TestfilelinkCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ NULL);
+ Tcl_CreateObjCommand(interp, "testfilelink", TestfilelinkCmd,
+ (ClientData) 0, NULL);
Tcl_CreateObjCommand(interp, "testfile", TestfileCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
+ Tcl_CreateObjCommand(interp, "testhashsystemhash",
+ TestHashSystemHashCmd, (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testgetassocdata", TestgetassocdataCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
+ Tcl_CreateCommand(interp, "testgetint", TestgetintCmd,
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testgetplatform", TestgetplatformCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateObjCommand(interp, "testgetvarfullname",
- TestgetvarfullnameCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
+ TestgetvarfullnameCmd, (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testinterpdelete", TestinterpdeleteCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
- Tcl_CreateCommand(interp, "testlink", TestlinkCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
+ Tcl_CreateCommand(interp, "testlink", TestlinkCmd, (ClientData) 0, NULL);
Tcl_CreateObjCommand(interp, "testlocale", TestlocaleCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
- Tcl_CreateCommand(interp, "testopenfilechannelproc",
- TestopenfilechannelprocCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
- Tcl_CreateCommand(interp, "testpanic", TestpanicCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
+ NULL);
+ Tcl_CreateCommand(interp, "testpanic", TestpanicCmd, (ClientData) 0, NULL);
Tcl_CreateObjCommand(interp, "testparser", TestparserObjCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateObjCommand(interp, "testparsevar", TestparsevarObjCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateObjCommand(interp, "testparsevarname", TestparsevarnameObjCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateObjCommand(interp, "testregexp", TestregexpObjCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
+ Tcl_CreateObjCommand(interp, "testreturn", TestreturnObjCmd,
+ (ClientData) 0, NULL);
Tcl_CreateObjCommand(interp, "testsaveresult", TestsaveresultCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testsetassocdata", TestsetassocdataCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testsetnoerr", TestsetCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testseterr", TestsetCmd,
- (ClientData) TCL_LEAVE_ERR_MSG, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) TCL_LEAVE_ERR_MSG, NULL);
+ Tcl_CreateCommand(interp, "testset2", Testset2Cmd,
+ (ClientData) TCL_LEAVE_ERR_MSG, NULL);
Tcl_CreateCommand(interp, "testseterrorcode", TestseterrorcodeCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
- Tcl_CreateObjCommand(interp, "testsetobjerrorcode",
- TestsetobjerrorcodeCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
+ Tcl_CreateObjCommand(interp, "testsetobjerrorcode",
+ TestsetobjerrorcodeCmd, (ClientData) 0, NULL);
Tcl_CreateObjCommand(interp, "testnumutfchars",
- TestNumUtfCharsCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
+ TestNumUtfCharsCmd, (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testsetplatform", TestsetplatformCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "teststaticpkg", TeststaticpkgCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testtranslatefilename",
- TesttranslatefilenameCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
- Tcl_CreateCommand(interp, "testupvar", TestupvarCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
- Tcl_CreateMathFunc(interp, "T1", 0, (Tcl_ValueType *) NULL, TestMathFunc,
- (ClientData) 123);
- Tcl_CreateMathFunc(interp, "T2", 0, (Tcl_ValueType *) NULL, TestMathFunc,
- (ClientData) 345);
- Tcl_CreateCommand(interp, "teststatproc", TeststatprocCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
+ TesttranslatefilenameCmd, (ClientData) 0, NULL);
+ Tcl_CreateCommand(interp, "testupvar", TestupvarCmd, (ClientData) 0, NULL);
+ Tcl_CreateMathFunc(interp, "T1", 0, NULL, TestMathFunc, (ClientData) 123);
+ Tcl_CreateMathFunc(interp, "T2", 0, NULL, TestMathFunc, (ClientData) 345);
Tcl_CreateCommand(interp, "testmainthread", TestmainthreadCmd, (ClientData) 0,
- (Tcl_CmdDeleteProc *) NULL);
+ NULL);
Tcl_CreateCommand(interp, "testsetmainloop", TestsetmainloopCmd,
- (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) NULL, NULL);
Tcl_CreateCommand(interp, "testexitmainloop", TestexitmainloopCmd,
- (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) NULL, NULL);
t3ArgTypes[0] = TCL_EITHER;
t3ArgTypes[1] = TCL_EITHER;
Tcl_CreateMathFunc(interp, "T3", 2, t3ArgTypes, TestMathFunc2,
@@ -706,40 +717,37 @@ Tcltest_Init(interp)
listPtr = Tcl_GetVar2Ex(interp, "argv", NULL, TCL_GLOBAL_ONLY);
if (listPtr != NULL) {
- if (Tcl_ListObjGetElements(interp, listPtr, &objc, &objv) != TCL_OK) {
+ if (Tcl_ListObjGetElements(interp, listPtr, &objc, &objv) != TCL_OK) {
return TCL_ERROR;
- }
- if (objc && (Tcl_GetIndexFromObj(NULL, objv[0], specialOptions, NULL,
+ }
+ if (objc && (Tcl_GetIndexFromObj(NULL, objv[0], specialOptions, NULL,
TCL_EXACT, &index) == TCL_OK)) {
switch (index) {
- case 0: {
- return TCL_ERROR;
- }
- case 1: {
- Tcl_DeleteInterp(interp);
- return TCL_ERROR;
- }
- case 2: {
- int mode;
- Tcl_UnregisterChannel(interp,
- Tcl_GetChannel(interp, "stderr", &mode));
- return TCL_ERROR;
- }
- case 3: {
- if (objc-1) {
- Tcl_SetVar2Ex(interp, "tcl_rcFileName", NULL,
- objv[1], TCL_GLOBAL_ONLY);
- }
- return TCL_ERROR;
- }
+ case 0:
+ return TCL_ERROR;
+ case 1:
+ Tcl_DeleteInterp(interp);
+ return TCL_ERROR;
+ case 2: {
+ int mode;
+ Tcl_UnregisterChannel(interp,
+ Tcl_GetChannel(interp, "stderr", &mode));
+ return TCL_ERROR;
}
- }
+ case 3:
+ if (objc-1) {
+ Tcl_SetVar2Ex(interp, "tcl_rcFileName", NULL, objv[1],
+ TCL_GLOBAL_ONLY);
+ }
+ return TCL_ERROR;
+ }
+ }
}
-
+
/*
* And finally add any platform specific test commands.
*/
-
+
return TclplatformtestInit(interp);
}
@@ -762,11 +770,11 @@ Tcltest_Init(interp)
/* ARGSUSED */
static int
-TestasyncCmd(dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestasyncCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
TestAsyncHandler *asyncPtr, *prevPtr;
int id, code;
@@ -842,24 +850,50 @@ TestasyncCmd(dummy, interp, argc, argv)
}
Tcl_SetResult(interp, (char *)argv[3], TCL_VOLATILE);
return code;
+#ifdef TCL_THREADS
+ } else if (strcmp(argv[1], "marklater") == 0) {
+ if (argc != 3) {
+ goto wrongNumArgs;
+ }
+ if (Tcl_GetInt(interp, argv[2], &id) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ for (asyncPtr = firstHandler; asyncPtr != NULL;
+ asyncPtr = asyncPtr->nextPtr) {
+ if (asyncPtr->id == id) {
+ Tcl_ThreadId threadID;
+ if (Tcl_CreateThread(&threadID, AsyncThreadProc,
+ (ClientData) asyncPtr, TCL_THREAD_STACK_DEFAULT,
+ TCL_THREAD_NOFLAGS) != TCL_OK) {
+ Tcl_SetResult(interp, "can't create thread", TCL_STATIC);
+ return TCL_ERROR;
+ }
+ break;
+ }
+ }
+ } else {
+ Tcl_AppendResult(interp, "bad option \"", argv[1],
+ "\": must be create, delete, int, mark, or marklater", NULL);
+ return TCL_ERROR;
+#else /* !TCL_THREADS */
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be create, delete, int, or mark",
- (char *) NULL);
+ "\": must be create, delete, int, or mark", NULL);
return TCL_ERROR;
+#endif
}
return TCL_OK;
}
static int
-AsyncHandlerProc(clientData, interp, code)
- ClientData clientData; /* Pointer to TestAsyncHandler structure. */
- Tcl_Interp *interp; /* Interpreter in which command was
+AsyncHandlerProc(
+ ClientData clientData, /* Pointer to TestAsyncHandler structure. */
+ Tcl_Interp *interp, /* Interpreter in which command was
* executed, or NULL. */
- int code; /* Current return code from command. */
+ int code) /* Current return code from command. */
{
TestAsyncHandler *asyncPtr = (TestAsyncHandler *) clientData;
- CONST char *listArgv[4], *cmd;
+ const char *listArgv[4], *cmd;
char string[TCL_INTEGER_SPACE];
TclFormatInt(string, code);
@@ -872,9 +906,8 @@ AsyncHandlerProc(clientData, interp, code)
code = Tcl_Eval(interp, cmd);
} else {
/*
- * this should not happen, but by definition of how async
- * handlers are invoked, it's possible. Better error
- * checking is needed here.
+ * this should not happen, but by definition of how async handlers are
+ * invoked, it's possible. Better error checking is needed here.
*/
}
ckfree((char *)cmd);
@@ -884,11 +917,41 @@ AsyncHandlerProc(clientData, interp, code)
/*
*----------------------------------------------------------------------
*
+ * AsyncThreadProc --
+ *
+ * Delivers an asynchronous event to a handler in another thread.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Invokes Tcl_AsyncMark on the handler
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TCL_THREADS
+static Tcl_ThreadCreateType
+AsyncThreadProc(
+ ClientData clientData) /* Parameter is a pointer to a
+ * TestAsyncHandler, defined above. */
+{
+ TestAsyncHandler *asyncPtr = clientData;
+ Tcl_Sleep(1);
+ Tcl_AsyncMark(asyncPtr->handler);
+ Tcl_ExitThread(TCL_OK);
+ TCL_THREAD_CREATE_RETURN;
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
* TestcmdinfoCmd --
*
- * This procedure implements the "testcmdinfo" command. It is used
- * to test Tcl_GetCommandInfo, Tcl_SetCommandInfo, and command creation
- * and deletion.
+ * This procedure implements the "testcmdinfo" command. It is used to
+ * test Tcl_GetCommandInfo, Tcl_SetCommandInfo, and command creation and
+ * deletion.
*
* Results:
* A standard Tcl result.
@@ -901,17 +964,17 @@ AsyncHandlerProc(clientData, interp, code)
/* ARGSUSED */
static int
-TestcmdinfoCmd(dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestcmdinfoCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
Tcl_CmdInfo info;
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " option cmdName\"", (char *) NULL);
+ " option cmdName\"", NULL);
return TCL_ERROR;
}
if (strcmp(argv[1], "create") == 0) {
@@ -928,34 +991,33 @@ TestcmdinfoCmd(dummy, interp, argc, argv)
}
if (info.proc == CmdProc1) {
Tcl_AppendResult(interp, "CmdProc1", " ",
- (char *) info.clientData, (char *) NULL);
+ (char *) info.clientData, NULL);
} else if (info.proc == CmdProc2) {
Tcl_AppendResult(interp, "CmdProc2", " ",
- (char *) info.clientData, (char *) NULL);
+ (char *) info.clientData, NULL);
} else {
- Tcl_AppendResult(interp, "unknown", (char *) NULL);
+ Tcl_AppendResult(interp, "unknown", NULL);
}
if (info.deleteProc == CmdDelProc1) {
Tcl_AppendResult(interp, " CmdDelProc1", " ",
- (char *) info.deleteData, (char *) NULL);
+ (char *) info.deleteData, NULL);
} else if (info.deleteProc == CmdDelProc2) {
Tcl_AppendResult(interp, " CmdDelProc2", " ",
- (char *) info.deleteData, (char *) NULL);
+ (char *) info.deleteData, NULL);
} else {
- Tcl_AppendResult(interp, " unknown", (char *) NULL);
+ Tcl_AppendResult(interp, " unknown", NULL);
}
- Tcl_AppendResult(interp, " ", info.namespacePtr->fullName,
- (char *) NULL);
+ Tcl_AppendResult(interp, " ", info.namespacePtr->fullName, NULL);
if (info.isNativeObjectProc) {
- Tcl_AppendResult(interp, " nativeObjectProc", (char *) NULL);
+ Tcl_AppendResult(interp, " nativeObjectProc", NULL);
} else {
- Tcl_AppendResult(interp, " stringProc", (char *) NULL);
+ Tcl_AppendResult(interp, " stringProc", NULL);
}
} else if (strcmp(argv[1], "modify") == 0) {
info.proc = CmdProc2;
info.clientData = (ClientData) "new_command_data";
info.objProc = NULL;
- info.objClientData = (ClientData) NULL;
+ info.objClientData = (ClientData) NULL;
info.deleteProc = CmdDelProc2;
info.deleteData = (ClientData) "new_delete_data";
if (Tcl_SetCommandInfo(interp, argv[2], &info) == 0) {
@@ -965,8 +1027,7 @@ TestcmdinfoCmd(dummy, interp, argc, argv)
}
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be create, delete, get, or modify",
- (char *) NULL);
+ "\": must be create, delete, get, or modify", NULL);
return TCL_ERROR;
}
return TCL_OK;
@@ -974,33 +1035,31 @@ TestcmdinfoCmd(dummy, interp, argc, argv)
/*ARGSUSED*/
static int
-CmdProc1(clientData, interp, argc, argv)
- ClientData clientData; /* String to return. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
-{
- Tcl_AppendResult(interp, "CmdProc1 ", (char *) clientData,
- (char *) NULL);
+CmdProc1(
+ ClientData clientData, /* String to return. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
+{
+ Tcl_AppendResult(interp, "CmdProc1 ", (char *) clientData, NULL);
return TCL_OK;
}
/*ARGSUSED*/
static int
-CmdProc2(clientData, interp, argc, argv)
- ClientData clientData; /* String to return. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
-{
- Tcl_AppendResult(interp, "CmdProc2 ", (char *) clientData,
- (char *) NULL);
+CmdProc2(
+ ClientData clientData, /* String to return. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
+{
+ Tcl_AppendResult(interp, "CmdProc2 ", (char *) clientData, NULL);
return TCL_OK;
}
static void
-CmdDelProc1(clientData)
- ClientData clientData; /* String to save. */
+CmdDelProc1(
+ ClientData clientData) /* String to save. */
{
Tcl_DStringInit(&delString);
Tcl_DStringAppend(&delString, "CmdDelProc1 ", -1);
@@ -1008,8 +1067,8 @@ CmdDelProc1(clientData)
}
static void
-CmdDelProc2(clientData)
- ClientData clientData; /* String to save. */
+CmdDelProc2(
+ ClientData clientData) /* String to save. */
{
Tcl_DStringInit(&delString);
Tcl_DStringAppend(&delString, "CmdDelProc2 ", -1);
@@ -1021,9 +1080,8 @@ CmdDelProc2(clientData)
*
* TestcmdtokenCmd --
*
- * This procedure implements the "testcmdtoken" command. It is used
- * to test Tcl_Command tokens and procedures such as
- * Tcl_GetCommandFullName.
+ * This procedure implements the "testcmdtoken" command. It is used to
+ * test Tcl_Command tokens and procedures such as Tcl_GetCommandFullName.
*
* Results:
* A standard Tcl result.
@@ -1036,11 +1094,11 @@ CmdDelProc2(clientData)
/* ARGSUSED */
static int
-TestcmdtokenCmd(dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestcmdtokenCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
Tcl_Command token;
int *l;
@@ -1048,20 +1106,20 @@ TestcmdtokenCmd(dummy, interp, argc, argv)
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " option arg\"", (char *) NULL);
+ " option arg\"", NULL);
return TCL_ERROR;
}
if (strcmp(argv[1], "create") == 0) {
token = Tcl_CreateCommand(interp, argv[2], CmdProc1,
- (ClientData) "original", (Tcl_CmdDeleteProc *) NULL);
- sprintf(buf, "%p", (VOID *)token);
+ (ClientData) "original", NULL);
+ sprintf(buf, "%p", (void *)token);
Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if (strcmp(argv[1], "name") == 0) {
Tcl_Obj *objPtr;
if (sscanf(argv[2], "%p", &l) != 1) {
Tcl_AppendResult(interp, "bad command token \"", argv[2],
- "\"", (char *) NULL);
+ "\"", NULL);
return TCL_ERROR;
}
@@ -1069,12 +1127,12 @@ TestcmdtokenCmd(dummy, interp, argc, argv)
Tcl_GetCommandFullName(interp, (Tcl_Command) l, objPtr);
Tcl_AppendElement(interp,
- Tcl_GetCommandName(interp, (Tcl_Command) l));
+ Tcl_GetCommandName(interp, (Tcl_Command) l));
Tcl_AppendElement(interp, Tcl_GetString(objPtr));
Tcl_DecrRefCount(objPtr);
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be create or name", (char *) NULL);
+ "\": must be create or name", NULL);
return TCL_ERROR;
}
return TCL_OK;
@@ -1100,25 +1158,25 @@ TestcmdtokenCmd(dummy, interp, argc, argv)
/* ARGSUSED */
static int
-TestcmdtraceCmd(dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestcmdtraceCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
Tcl_DString buffer;
int result;
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " option script\"", (char *) NULL);
+ " option script\"", NULL);
return TCL_ERROR;
}
if (strcmp(argv[1], "tracetest") == 0) {
Tcl_DStringInit(&buffer);
cmdTrace = Tcl_CreateTrace(interp, 50000,
- (Tcl_CmdTraceProc *) CmdTraceProc, (ClientData) &buffer);
+ (Tcl_CmdTraceProc *) CmdTraceProc, (ClientData) &buffer);
result = Tcl_Eval(interp, argv[2]);
if (result == TCL_OK) {
Tcl_ResetResult(interp);
@@ -1129,13 +1187,13 @@ TestcmdtraceCmd(dummy, interp, argc, argv)
} else if (strcmp(argv[1], "deletetest") == 0) {
/*
* Create a command trace then eval a script to check whether it is
- * called. Note that this trace procedure removes itself as a
- * further check of the robustness of the trace proc calling code in
+ * called. Note that this trace procedure removes itself as a further
+ * check of the robustness of the trace proc calling code in
* TclExecuteByteCode.
*/
-
+
cmdTrace = Tcl_CreateTrace(interp, 50000,
- (Tcl_CmdTraceProc *) CmdTraceDeleteProc, (ClientData) NULL);
+ (Tcl_CmdTraceProc *) CmdTraceDeleteProc, (ClientData) NULL);
Tcl_Eval(interp, argv[2]);
} else if (strcmp(argv[1], "leveltest") == 0) {
Interp *iPtr = (Interp *) interp;
@@ -1149,26 +1207,26 @@ TestcmdtraceCmd(dummy, interp, argc, argv)
}
Tcl_DeleteTrace(interp, cmdTrace);
Tcl_DStringFree(&buffer);
- } else if ( strcmp(argv[1], "resulttest" ) == 0 ) {
+ } else if (strcmp(argv[1], "resulttest") == 0) {
/* Create an object-based trace, then eval a script. This is used
* to test return codes other than TCL_OK from the trace engine.
*/
+
static int deleteCalled;
+
deleteCalled = 0;
- cmdTrace = Tcl_CreateObjTrace( interp, 50000,
- TCL_ALLOW_INLINE_COMPILATION,
- ObjTraceProc,
- (ClientData) &deleteCalled,
- ObjTraceDeleteProc );
- result = Tcl_Eval( interp, argv[ 2 ] );
- Tcl_DeleteTrace( interp, cmdTrace );
- if ( !deleteCalled ) {
- Tcl_SetResult( interp, "Delete wasn't called", TCL_STATIC );
+ cmdTrace = Tcl_CreateObjTrace(interp, 50000,
+ TCL_ALLOW_INLINE_COMPILATION, ObjTraceProc,
+ (ClientData) &deleteCalled, ObjTraceDeleteProc);
+ result = Tcl_Eval(interp, argv[2]);
+ Tcl_DeleteTrace(interp, cmdTrace);
+ if (!deleteCalled) {
+ Tcl_SetResult(interp, "Delete wasn't called", TCL_STATIC);
return TCL_ERROR;
} else {
return result;
}
- } else if ( strcmp(argv[1], "doubletest" ) == 0 ) {
+ } else if (strcmp(argv[1], "doubletest") == 0) {
Tcl_Trace t1, t2;
Tcl_DStringInit(&buffer);
@@ -1186,28 +1244,26 @@ TestcmdtraceCmd(dummy, interp, argc, argv)
Tcl_DStringFree(&buffer);
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be tracetest, deletetest, doubletest or resulttest",
- (char *) NULL);
+ "\": must be tracetest, deletetest, doubletest or resulttest", NULL);
return TCL_ERROR;
}
return TCL_OK;
}
static void
-CmdTraceProc(clientData, interp, level, command, cmdProc, cmdClientData,
- argc, argv)
- ClientData clientData; /* Pointer to buffer in which the
+CmdTraceProc(
+ ClientData clientData, /* Pointer to buffer in which the
* command and arguments are appended.
* Accumulates test result. */
- Tcl_Interp *interp; /* Current interpreter. */
- int level; /* Current trace level. */
- char *command; /* The command being traced (after
+ Tcl_Interp *interp, /* Current interpreter. */
+ int level, /* Current trace level. */
+ char *command, /* The command being traced (after
* substitutions). */
- Tcl_CmdProc *cmdProc; /* Points to command's command procedure. */
- ClientData cmdClientData; /* Client data associated with command
+ Tcl_CmdProc *cmdProc, /* Points to command's command procedure. */
+ ClientData cmdClientData, /* Client data associated with command
* procedure. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int argc, /* Number of arguments. */
+ char **argv) /* Argument strings. */
{
Tcl_DString *bufPtr = (Tcl_DString *) clientData;
int i;
@@ -1222,49 +1278,49 @@ CmdTraceProc(clientData, interp, level, command, cmdProc, cmdClientData,
}
static void
-CmdTraceDeleteProc(clientData, interp, level, command, cmdProc,
- cmdClientData, argc, argv)
- ClientData clientData; /* Unused. */
- Tcl_Interp *interp; /* Current interpreter. */
- int level; /* Current trace level. */
- char *command; /* The command being traced (after
+CmdTraceDeleteProc(
+ ClientData clientData, /* Unused. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int level, /* Current trace level. */
+ char *command, /* The command being traced (after
* substitutions). */
- Tcl_CmdProc *cmdProc; /* Points to command's command procedure. */
- ClientData cmdClientData; /* Client data associated with command
+ Tcl_CmdProc *cmdProc, /* Points to command's command procedure. */
+ ClientData cmdClientData, /* Client data associated with command
* procedure. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int argc, /* Number of arguments. */
+ char **argv) /* Argument strings. */
{
/*
- * Remove ourselves to test whether calling Tcl_DeleteTrace within
- * a trace callback causes the for loop in TclExecuteByteCode that
- * calls traces to reference freed memory.
+ * Remove ourselves to test whether calling Tcl_DeleteTrace within a trace
+ * callback causes the for loop in TclExecuteByteCode that calls traces to
+ * reference freed memory.
*/
-
+
Tcl_DeleteTrace(interp, cmdTrace);
}
static int
-ObjTraceProc( clientData, interp, level, command, token, objc, objv )
- ClientData clientData; /* unused */
- Tcl_Interp* interp; /* Tcl interpreter */
- int level; /* Execution level */
- CONST char* command; /* Command being executed */
- Tcl_Command token; /* Command information */
- int objc; /* Parameter count */
- Tcl_Obj *CONST objv[]; /* Parameter list */
-{
- CONST char* word = Tcl_GetString( objv[ 0 ] );
- if ( !strcmp( word, "Error" ) ) {
- Tcl_SetObjResult( interp, Tcl_NewStringObj( command, -1 ) );
+ObjTraceProc(
+ ClientData clientData, /* unused */
+ Tcl_Interp *interp, /* Tcl interpreter */
+ int level, /* Execution level */
+ const char *command, /* Command being executed */
+ Tcl_Command token, /* Command information */
+ int objc, /* Parameter count */
+ Tcl_Obj *const objv[]) /* Parameter list */
+{
+ const char *word = Tcl_GetString(objv[0]);
+
+ if (!strcmp(word, "Error")) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(command, -1));
return TCL_ERROR;
- } else if ( !strcmp( word, "Break" ) ) {
+ } else if (!strcmp(word, "Break")) {
return TCL_BREAK;
- } else if ( !strcmp( word, "Continue" ) ) {
+ } else if (!strcmp(word, "Continue")) {
return TCL_CONTINUE;
- } else if ( !strcmp( word, "Return" ) ) {
+ } else if (!strcmp(word, "Return")) {
return TCL_RETURN;
- } else if ( !strcmp( word, "OtherStatus" ) ) {
+ } else if (!strcmp(word, "OtherStatus")) {
return 6;
} else {
return TCL_OK;
@@ -1272,10 +1328,10 @@ ObjTraceProc( clientData, interp, level, command, token, objc, objv )
}
static void
-ObjTraceDeleteProc( clientData )
- ClientData clientData;
+ObjTraceDeleteProc(
+ ClientData clientData)
{
- int * intPtr = (int *) clientData;
+ int *intPtr = (int *) clientData;
*intPtr = 1; /* Record that the trace was deleted */
}
@@ -1284,11 +1340,11 @@ ObjTraceDeleteProc( clientData )
*
* TestcreatecommandCmd --
*
- * This procedure implements the "testcreatecommand" command. It is
- * used to test that the Tcl_CreateCommand creates a new command in
- * the namespace specified as part of its name, if any. It also
- * checks that the namespace code ignore single ":"s in the middle
- * or end of a command name.
+ * This procedure implements the "testcreatecommand" command. It is used
+ * to test that the Tcl_CreateCommand creates a new command in the
+ * namespace specified as part of its name, if any. It also checks that
+ * the namespace code ignore single ":"s in the middle or end of a
+ * command name.
*
* Results:
* A standard Tcl result.
@@ -1301,44 +1357,41 @@ ObjTraceDeleteProc( clientData )
*/
static int
-TestcreatecommandCmd(dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestcreatecommandCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " option\"", (char *) NULL);
+ " option\"", NULL);
return TCL_ERROR;
}
if (strcmp(argv[1], "create") == 0) {
Tcl_CreateCommand(interp, "test_ns_basic::createdcommand",
- CreatedCommandProc, (ClientData) NULL,
- (Tcl_CmdDeleteProc *) NULL);
+ CreatedCommandProc, (ClientData) NULL, NULL);
} else if (strcmp(argv[1], "delete") == 0) {
Tcl_DeleteCommand(interp, "test_ns_basic::createdcommand");
} else if (strcmp(argv[1], "create2") == 0) {
Tcl_CreateCommand(interp, "value:at:",
- CreatedCommandProc2, (ClientData) NULL,
- (Tcl_CmdDeleteProc *) NULL);
+ CreatedCommandProc2, (ClientData) NULL, NULL);
} else if (strcmp(argv[1], "delete2") == 0) {
Tcl_DeleteCommand(interp, "value:at:");
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be create, delete, create2, or delete2",
- (char *) NULL);
+ "\": must be create, delete, create2, or delete2", NULL);
return TCL_ERROR;
}
return TCL_OK;
}
static int
-CreatedCommandProc(clientData, interp, argc, argv)
- ClientData clientData; /* String to return. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+CreatedCommandProc(
+ ClientData clientData, /* String to return. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
Tcl_CmdInfo info;
int found;
@@ -1347,20 +1400,20 @@ CreatedCommandProc(clientData, interp, argc, argv)
&info);
if (!found) {
Tcl_AppendResult(interp, "CreatedCommandProc could not get command info for test_ns_basic::createdcommand",
- (char *) NULL);
+ NULL);
return TCL_ERROR;
}
Tcl_AppendResult(interp, "CreatedCommandProc in ",
- info.namespacePtr->fullName, (char *) NULL);
+ info.namespacePtr->fullName, NULL);
return TCL_OK;
}
static int
-CreatedCommandProc2(clientData, interp, argc, argv)
- ClientData clientData; /* String to return. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+CreatedCommandProc2(
+ ClientData clientData, /* String to return. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
Tcl_CmdInfo info;
int found;
@@ -1368,11 +1421,11 @@ CreatedCommandProc2(clientData, interp, argc, argv)
found = Tcl_GetCommandInfo(interp, "value:at:", &info);
if (!found) {
Tcl_AppendResult(interp, "CreatedCommandProc2 could not get command info for test_ns_basic::createdcommand",
- (char *) NULL);
+ NULL);
return TCL_ERROR;
}
Tcl_AppendResult(interp, "CreatedCommandProc2 in ",
- info.namespacePtr->fullName, (char *) NULL);
+ info.namespacePtr->fullName, NULL);
return TCL_OK;
}
@@ -1395,11 +1448,11 @@ CreatedCommandProc2(clientData, interp, argc, argv)
/* ARGSUSED */
static int
-TestdcallCmd(dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestdcallCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
int i, id;
@@ -1411,10 +1464,10 @@ TestdcallCmd(dummy, interp, argc, argv)
}
if (id < 0) {
Tcl_DontCallWhenDeleted(delInterp, DelCallbackProc,
- (ClientData) (-id));
+ (ClientData) INT2PTR(-id));
} else {
Tcl_CallWhenDeleted(delInterp, DelCallbackProc,
- (ClientData) id);
+ (ClientData) INT2PTR(id));
}
}
Tcl_DeleteInterp(delInterp);
@@ -1427,12 +1480,11 @@ TestdcallCmd(dummy, interp, argc, argv)
*/
static void
-DelCallbackProc(clientData, interp)
- ClientData clientData; /* Numerical value to append to
- * delString. */
- Tcl_Interp *interp; /* Interpreter being deleted. */
+DelCallbackProc(
+ ClientData clientData, /* Numerical value to append to delString. */
+ Tcl_Interp *interp) /* Interpreter being deleted. */
{
- int id = (int) clientData;
+ int id = PTR2INT(clientData);
char buffer[TCL_INTEGER_SPACE];
TclFormatInt(buffer, id);
@@ -1461,11 +1513,11 @@ DelCallbackProc(clientData, interp)
/* ARGSUSED */
static int
-TestdelCmd(dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestdelCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
DelCmd *dPtr;
Tcl_Interp *slave;
@@ -1491,23 +1543,23 @@ TestdelCmd(dummy, interp, argc, argv)
}
static int
-DelCmdProc(clientData, interp, argc, argv)
- ClientData clientData; /* String result to return. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+DelCmdProc(
+ ClientData clientData, /* String result to return. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
DelCmd *dPtr = (DelCmd *) clientData;
- Tcl_AppendResult(interp, dPtr->deleteCmd, (char *) NULL);
+ Tcl_AppendResult(interp, dPtr->deleteCmd, NULL);
ckfree(dPtr->deleteCmd);
ckfree((char *) dPtr);
return TCL_OK;
}
static void
-DelDeleteProc(clientData)
- ClientData clientData; /* String command to evaluate. */
+DelDeleteProc(
+ ClientData clientData) /* String command to evaluate. */
{
DelCmd *dPtr = (DelCmd *) clientData;
@@ -1536,22 +1588,118 @@ DelDeleteProc(clientData)
*/
static int
-TestdelassocdataCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestdelassocdataCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
if (argc != 2) {
- Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
- " data_key\"", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
+ " data_key\"", NULL);
+ return TCL_ERROR;
}
Tcl_DeleteAssocData(interp, argv[1]);
return TCL_OK;
}
/*
+ *-----------------------------------------------------------------------------
+ *
+ * TestdoubledigitsCmd --
+ *
+ * This procedure implements the 'testdoubledigits' command. It is
+ * used to test the low-level floating-point formatting primitives
+ * in Tcl.
+ *
+ * Usage:
+ * testdoubledigits fpval ndigits type ?shorten"
+ *
+ * Parameters:
+ * fpval - Floating-point value to format.
+ * ndigits - Digit count to request from Tcl_DoubleDigits
+ * type - One of 'shortest', 'Steele', 'e', 'f'
+ * shorten - Indicates that the 'shorten' flag should be passed in.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+TestdoubledigitsObjCmd(ClientData unused,
+ /* NULL */
+ Tcl_Interp* interp,
+ /* Tcl interpreter */
+ int objc,
+ /* Parameter count */
+ Tcl_Obj* const objv[])
+ /* Parameter vector */
+{
+ static const char* options[] = {
+ "shortest",
+ "Steele",
+ "e",
+ "f",
+ NULL
+ };
+ static const int types[] = {
+ TCL_DD_SHORTEST,
+ TCL_DD_STEELE,
+ TCL_DD_E_FORMAT,
+ TCL_DD_F_FORMAT
+ };
+
+ const Tcl_ObjType* doubleType;
+ double d;
+ int status;
+ int ndigits;
+ int type;
+ int decpt;
+ int signum;
+ char* str;
+ char* endPtr;
+ Tcl_Obj* strObj;
+ Tcl_Obj* retval;
+
+ if (objc < 4 || objc > 5) {
+ Tcl_WrongNumArgs(interp, 1, objv, "fpval ndigits type ?shorten?");
+ return TCL_ERROR;
+ }
+ status = Tcl_GetDoubleFromObj(interp, objv[1], &d);
+ if (status != TCL_OK) {
+ doubleType = Tcl_GetObjType("double");
+ if (objv[1]->typePtr == doubleType
+ || TclIsNaN(objv[1]->internalRep.doubleValue)) {
+ status = TCL_OK;
+ memcpy(&d, &(objv[1]->internalRep.doubleValue), sizeof(double));
+ }
+ }
+ if (status != TCL_OK
+ || Tcl_GetIntFromObj(interp, objv[2], &ndigits) != TCL_OK
+ || Tcl_GetIndexFromObj(interp, objv[3], options, "conversion type",
+ TCL_EXACT, &type) != TCL_OK) {
+ fprintf(stderr, "bad value? %g\n", d);
+ return TCL_ERROR;
+ }
+ type = types[type];
+ if (objc > 4) {
+ if (strcmp(Tcl_GetString(objv[4]), "shorten")) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("bad flag", -1));
+ return TCL_ERROR;
+ }
+ type |= TCL_DD_SHORTEN_FLAG;
+ }
+ str = TclDoubleDigits(d, ndigits, type, &decpt, &signum, &endPtr);
+ strObj = Tcl_NewStringObj(str, endPtr-str);
+ ckfree(str);
+ retval = Tcl_NewListObj(1, &strObj);
+ Tcl_ListObjAppendElement(NULL, retval, Tcl_NewIntObj(decpt));
+ strObj = Tcl_NewStringObj(signum ? "-" : "+", 1);
+ Tcl_ListObjAppendElement(NULL, retval, strObj);
+ Tcl_SetObjResult(interp, retval);
+ return TCL_OK;
+}
+
+/*
*----------------------------------------------------------------------
*
* TestdstringCmd --
@@ -1570,11 +1718,11 @@ TestdelassocdataCmd(clientData, interp, argc, argv)
/* ARGSUSED */
static int
-TestdstringCmd(dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestdstringCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
int count;
@@ -1630,13 +1778,13 @@ TestdstringCmd(dummy, interp, argc, argv)
} else {
Tcl_AppendResult(interp, "bad gresult option \"", argv[2],
"\": must be staticsmall, staticlarge, free, or special",
- (char *) NULL);
+ NULL);
return TCL_ERROR;
}
Tcl_DStringGetResult(interp, &dstring);
} else if (strcmp(argv[1], "length") == 0) {
char buf[TCL_INTEGER_SPACE];
-
+
if (argc != 2) {
goto wrongNumArgs;
}
@@ -1662,8 +1810,8 @@ TestdstringCmd(dummy, interp, argc, argv)
Tcl_DStringStartSublist(&dstring);
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be append, element, end, free, get, length, ",
- "result, trunc, or start", (char *) NULL);
+ "\": must be append, element, end, free, get, length, "
+ "result, trunc, or start", NULL);
return TCL_ERROR;
}
return TCL_OK;
@@ -1699,92 +1847,82 @@ static void SpecialFree(blockPtr)
/* ARGSUSED */
static int
-TestencodingObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+TestencodingObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Encoding encoding;
int index, length;
char *string;
TclEncoding *encodingPtr;
- static CONST char *optionStrings[] = {
- "create", "delete", "path",
- NULL
+ static const char *optionStrings[] = {
+ "create", "delete", NULL
};
enum options {
- ENC_CREATE, ENC_DELETE, ENC_PATH
+ ENC_CREATE, ENC_DELETE
};
-
+
if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
&index) != TCL_OK) {
return TCL_ERROR;
}
switch ((enum options) index) {
- case ENC_CREATE: {
- Tcl_EncodingType type;
+ case ENC_CREATE: {
+ Tcl_EncodingType type;
- if (objc != 5) {
- return TCL_ERROR;
- }
- encodingPtr = (TclEncoding *) ckalloc(sizeof(TclEncoding));
- encodingPtr->interp = interp;
+ if (objc != 5) {
+ return TCL_ERROR;
+ }
+ encodingPtr = (TclEncoding *) ckalloc(sizeof(TclEncoding));
+ encodingPtr->interp = interp;
- string = Tcl_GetStringFromObj(objv[3], &length);
- encodingPtr->toUtfCmd = (char *) ckalloc((unsigned) (length + 1));
- memcpy(encodingPtr->toUtfCmd, string, (unsigned) length + 1);
+ string = Tcl_GetStringFromObj(objv[3], &length);
+ encodingPtr->toUtfCmd = (char *) ckalloc((unsigned) (length + 1));
+ memcpy(encodingPtr->toUtfCmd, string, (unsigned) length + 1);
- string = Tcl_GetStringFromObj(objv[4], &length);
- encodingPtr->fromUtfCmd = (char *) ckalloc((unsigned) (length + 1));
- memcpy(encodingPtr->fromUtfCmd, string, (unsigned) (length + 1));
+ string = Tcl_GetStringFromObj(objv[4], &length);
+ encodingPtr->fromUtfCmd = (char *) ckalloc((unsigned) (length + 1));
+ memcpy(encodingPtr->fromUtfCmd, string, (unsigned) (length + 1));
- string = Tcl_GetStringFromObj(objv[2], &length);
+ string = Tcl_GetStringFromObj(objv[2], &length);
- type.encodingName = string;
- type.toUtfProc = EncodingToUtfProc;
- type.fromUtfProc = EncodingFromUtfProc;
- type.freeProc = EncodingFreeProc;
- type.clientData = (ClientData) encodingPtr;
- type.nullSize = 1;
+ type.encodingName = string;
+ type.toUtfProc = EncodingToUtfProc;
+ type.fromUtfProc = EncodingFromUtfProc;
+ type.freeProc = EncodingFreeProc;
+ type.clientData = (ClientData) encodingPtr;
+ type.nullSize = 1;
- Tcl_CreateEncoding(&type);
- break;
- }
- case ENC_DELETE: {
- if (objc != 3) {
- return TCL_ERROR;
- }
- encoding = Tcl_GetEncoding(NULL, Tcl_GetString(objv[2]));
- Tcl_FreeEncoding(encoding);
- Tcl_FreeEncoding(encoding);
- break;
- }
- case ENC_PATH: {
- if (objc == 2) {
- Tcl_SetObjResult(interp, TclGetLibraryPath());
- } else {
- TclSetLibraryPath(objv[2]);
- }
- break;
+ Tcl_CreateEncoding(&type);
+ break;
+ }
+ case ENC_DELETE:
+ if (objc != 3) {
+ return TCL_ERROR;
}
+ encoding = Tcl_GetEncoding(NULL, Tcl_GetString(objv[2]));
+ Tcl_FreeEncoding(encoding);
+ Tcl_FreeEncoding(encoding);
+ break;
}
return TCL_OK;
}
-static int
-EncodingToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
- srcReadPtr, dstWrotePtr, dstCharsPtr)
- ClientData clientData; /* TclEncoding structure. */
- CONST char *src; /* Source string in specified encoding. */
- int srcLen; /* Source string length in bytes. */
- int flags; /* Conversion control flags. */
- Tcl_EncodingState *statePtr;/* Current state. */
- char *dst; /* Output buffer. */
- int dstLen; /* The maximum length of output buffer. */
- int *srcReadPtr; /* Filled with number of bytes read. */
- int *dstWrotePtr; /* Filled with number of bytes stored. */
- int *dstCharsPtr; /* Filled with number of chars stored. */
+
+static int
+EncodingToUtfProc(
+ ClientData clientData, /* TclEncoding structure. */
+ const char *src, /* Source string in specified encoding. */
+ int srcLen, /* Source string length in bytes. */
+ int flags, /* Conversion control flags. */
+ Tcl_EncodingState *statePtr,/* Current state. */
+ char *dst, /* Output buffer. */
+ int dstLen, /* The maximum length of output buffer. */
+ int *srcReadPtr, /* Filled with number of bytes read. */
+ int *dstWrotePtr, /* Filled with number of bytes stored. */
+ int *dstCharsPtr) /* Filled with number of chars stored. */
{
int len;
TclEncoding *encodingPtr;
@@ -1804,19 +1942,19 @@ EncodingToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
*dstCharsPtr = len;
return TCL_OK;
}
-static int
-EncodingFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
- srcReadPtr, dstWrotePtr, dstCharsPtr)
- ClientData clientData; /* TclEncoding structure. */
- CONST char *src; /* Source string in specified encoding. */
- int srcLen; /* Source string length in bytes. */
- int flags; /* Conversion control flags. */
- Tcl_EncodingState *statePtr;/* Current state. */
- char *dst; /* Output buffer. */
- int dstLen; /* The maximum length of output buffer. */
- int *srcReadPtr; /* Filled with number of bytes read. */
- int *dstWrotePtr; /* Filled with number of bytes stored. */
- int *dstCharsPtr; /* Filled with number of chars stored. */
+
+static int
+EncodingFromUtfProc(
+ ClientData clientData, /* TclEncoding structure. */
+ const char *src, /* Source string in specified encoding. */
+ int srcLen, /* Source string length in bytes. */
+ int flags, /* Conversion control flags. */
+ Tcl_EncodingState *statePtr,/* Current state. */
+ char *dst, /* Output buffer. */
+ int dstLen, /* The maximum length of output buffer. */
+ int *srcReadPtr, /* Filled with number of bytes read. */
+ int *dstWrotePtr, /* Filled with number of bytes stored. */
+ int *dstCharsPtr) /* Filled with number of chars stored. */
{
int len;
TclEncoding *encodingPtr;
@@ -1836,9 +1974,10 @@ EncodingFromUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen,
*dstCharsPtr = len;
return TCL_OK;
}
+
static void
-EncodingFreeProc(clientData)
- ClientData clientData; /* ClientData associated with type. */
+EncodingFreeProc(
+ ClientData clientData) /* ClientData associated with type. */
{
TclEncoding *encodingPtr;
@@ -1866,60 +2005,31 @@ EncodingFreeProc(clientData)
*/
static int
-TestevalexObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+TestevalexObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- Interp *iPtr = (Interp *) interp;
- int code, oldFlags, length, flags;
- char *string;
-
- if (objc == 1) {
- /*
- * The command was invoked with no arguments, so just toggle
- * the flag that determines whether we use Tcl_EvalEx.
- */
-
- if (iPtr->flags & USE_EVAL_DIRECT) {
- iPtr->flags &= ~USE_EVAL_DIRECT;
- Tcl_SetResult(interp, "disabling direct evaluation", TCL_STATIC);
- } else {
- iPtr->flags |= USE_EVAL_DIRECT;
- Tcl_SetResult(interp, "enabling direct evaluation", TCL_STATIC);
- }
- return TCL_OK;
- }
+ int length, flags;
+ char *script;
flags = 0;
if (objc == 3) {
- string = Tcl_GetStringFromObj(objv[2], &length);
- if (strcmp(string, "global") != 0) {
- Tcl_AppendResult(interp, "bad value \"", string,
- "\": must be global", (char *) NULL);
+ char *global = Tcl_GetStringFromObj(objv[2], &length);
+ if (strcmp(global, "global") != 0) {
+ Tcl_AppendResult(interp, "bad value \"", global,
+ "\": must be global", NULL);
return TCL_ERROR;
}
flags = TCL_EVAL_GLOBAL;
} else if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "script ?global?");
- return TCL_ERROR;
+ return TCL_ERROR;
}
- Tcl_SetResult(interp, "xxx", TCL_STATIC);
- /*
- * Note, we have to set the USE_EVAL_DIRECT flag in the interpreter
- * in addition to calling Tcl_EvalEx. This is needed so that even nested
- * commands are evaluated directly.
- */
-
- oldFlags = iPtr->flags;
- iPtr->flags |= USE_EVAL_DIRECT;
- string = Tcl_GetStringFromObj(objv[1], &length);
- code = Tcl_EvalEx(interp, string, length, flags);
- iPtr->flags = (iPtr->flags & ~USE_EVAL_DIRECT)
- | (oldFlags & USE_EVAL_DIRECT);
- return code;
+ script = Tcl_GetStringFromObj(objv[1], &length);
+ return Tcl_EvalEx(interp, script, length, flags);
}
/*
@@ -1940,17 +2050,17 @@ TestevalexObjCmd(dummy, interp, objc, objv)
*/
static int
-TestevalobjvObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+TestevalobjvObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
int evalGlobal;
if (objc < 3) {
Tcl_WrongNumArgs(interp, 1, objv, "global word ?word ...?");
- return TCL_ERROR;
+ return TCL_ERROR;
}
if (Tcl_GetIntFromObj(interp, objv[1], &evalGlobal) != TCL_OK) {
return TCL_ERROR;
@@ -1989,74 +2099,67 @@ TestevalobjvObjCmd(dummy, interp, objc, objv)
*/
static int
-TesteventObjCmd( ClientData unused, /* Not used */
- Tcl_Interp* interp, /* Tcl interpreter */
- int objc, /* Parameter count */
- Tcl_Obj *CONST objv[] ) /* Parameter vector */
-{
-
- static CONST char* subcommands[] = { /* Possible subcommands */
- "queue",
- "delete",
- NULL
+TesteventObjCmd(
+ ClientData unused, /* Not used */
+ Tcl_Interp *interp, /* Tcl interpreter */
+ int objc, /* Parameter count */
+ Tcl_Obj *const objv[]) /* Parameter vector */
+{
+ static const char *subcommands[] = { /* Possible subcommands */
+ "queue", "delete", NULL
};
int subCmdIndex; /* Index of the chosen subcommand */
- static CONST char* positions[] = { /* Possible queue positions */
- "head",
- "tail",
- "mark",
- NULL
+ static const char *positions[] = { /* Possible queue positions */
+ "head", "tail", "mark", NULL
};
int posIndex; /* Index of the chosen position */
- static CONST Tcl_QueuePosition posNum[] = {
- /* Interpretation of the chosen position */
+ static const Tcl_QueuePosition posNum[] = {
+ /* Interpretation of the chosen position */
TCL_QUEUE_HEAD,
TCL_QUEUE_TAIL,
TCL_QUEUE_MARK
};
- TestEvent* ev; /* Event to be queued */
+ TestEvent *ev; /* Event to be queued */
- if ( objc < 2 ) {
- Tcl_WrongNumArgs( interp, 1, objv, "subcommand ?args?" );
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?");
return TCL_ERROR;
}
- if ( Tcl_GetIndexFromObj( interp, objv[1], subcommands, "subcommand",
- TCL_EXACT, &subCmdIndex ) != TCL_OK ) {
+ if (Tcl_GetIndexFromObj(interp, objv[1], subcommands, "subcommand",
+ TCL_EXACT, &subCmdIndex) != TCL_OK) {
return TCL_ERROR;
}
- switch ( subCmdIndex ) {
+ switch (subCmdIndex) {
case 0: /* queue */
- if ( objc != 5 ) {
- Tcl_WrongNumArgs( interp, 2, objv, "name position script" );
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "name position script");
return TCL_ERROR;
}
- if ( Tcl_GetIndexFromObj( interp, objv[3], positions,
- "position specifier", TCL_EXACT,
- &posIndex ) != TCL_OK ) {
+ if (Tcl_GetIndexFromObj(interp, objv[3], positions,
+ "position specifier", TCL_EXACT, &posIndex) != TCL_OK) {
return TCL_ERROR;
}
- ev = (TestEvent*) ckalloc( sizeof( TestEvent ) );
+ ev = (TestEvent *) ckalloc(sizeof(TestEvent));
ev->header.proc = TesteventProc;
ev->header.nextPtr = NULL;
ev->interp = interp;
- ev->command = objv[ 4 ];
- Tcl_IncrRefCount( ev->command );
- ev->tag = objv[ 2 ];
- Tcl_IncrRefCount( ev->tag );
- Tcl_QueueEvent( (Tcl_Event*) ev, posNum[ posIndex ] );
+ ev->command = objv[4];
+ Tcl_IncrRefCount(ev->command);
+ ev->tag = objv[2];
+ Tcl_IncrRefCount(ev->tag);
+ Tcl_QueueEvent((Tcl_Event *) ev, posNum[posIndex]);
break;
case 1: /* delete */
- if ( objc != 3 ) {
- Tcl_WrongNumArgs( interp, 2, objv, "name" );
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "name");
return TCL_ERROR;
}
- Tcl_DeleteEvents( TesteventDeleteProc, objv[ 2 ] );
+ Tcl_DeleteEvents(TesteventDeleteProc, objv[2]);
break;
}
return TCL_OK;
-
}
/*
@@ -2066,49 +2169,49 @@ TesteventObjCmd( ClientData unused, /* Not used */
*
* Delivers a test event to the Tcl interpreter as part of event
* queue testing.
- *
+ *
* Results:
* Returns 1 if the event has been serviced, 0 otherwise.
*
* Side effects:
- * Evaluates the event's callback script, so has whatever
- * side effects the callback has. The return value of the
- * callback script becomes the return value of this function.
- * If the callback script reports an error, it is reported as
- * a background error.
+ * Evaluates the event's callback script, so has whatever side effects
+ * the callback has. The return value of the callback script becomes the
+ * return value of this function. If the callback script reports an
+ * error, it is reported as a background error.
*
*----------------------------------------------------------------------
*/
static int
-TesteventProc( Tcl_Event* event, /* Event to deliver */
- int flags ) /* Current flags for Tcl_ServiceEvent */
-{
- TestEvent * ev = (TestEvent *) event;
- Tcl_Interp* interp = ev->interp;
- Tcl_Obj* command = ev->command;
- int result = Tcl_EvalObjEx( interp, command,
- TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT );
+TesteventProc(
+ Tcl_Event *event, /* Event to deliver */
+ int flags) /* Current flags for Tcl_ServiceEvent */
+{
+ TestEvent *ev = (TestEvent *) event;
+ Tcl_Interp *interp = ev->interp;
+ Tcl_Obj *command = ev->command;
+ int result = Tcl_EvalObjEx(interp, command,
+ TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT);
int retval;
- if ( result != TCL_OK ) {
- Tcl_AddErrorInfo( interp,
- " (command bound to \"testevent\" callback)" );
- Tcl_BackgroundError( interp );
+
+ if (result != TCL_OK) {
+ Tcl_AddErrorInfo(interp,
+ " (command bound to \"testevent\" callback)");
+ Tcl_BackgroundError(interp);
return 1; /* Avoid looping on errors */
}
- if ( Tcl_GetBooleanFromObj( interp,
- Tcl_GetObjResult( interp ),
- &retval ) != TCL_OK ) {
- Tcl_AddErrorInfo( interp,
- " (return value from \"testevent\" callback)" );
- Tcl_BackgroundError( interp );
+ if (Tcl_GetBooleanFromObj(interp, Tcl_GetObjResult(interp),
+ &retval) != TCL_OK) {
+ Tcl_AddErrorInfo(interp,
+ " (return value from \"testevent\" callback)");
+ Tcl_BackgroundError(interp);
return 1;
}
- if ( retval ) {
- Tcl_DecrRefCount( ev->tag );
- Tcl_DecrRefCount( ev->command );
+ if (retval) {
+ Tcl_DecrRefCount(ev->tag);
+ Tcl_DecrRefCount(ev->command);
}
-
+
return retval;
}
@@ -2131,25 +2234,26 @@ TesteventProc( Tcl_Event* event, /* Event to deliver */
*/
static int
-TesteventDeleteProc( Tcl_Event* event, /* Event to examine */
- ClientData clientData ) /* Tcl_Obj containing the name
- * of the event(s) to remove */
+TesteventDeleteProc(
+ Tcl_Event *event, /* Event to examine */
+ ClientData clientData) /* Tcl_Obj containing the name of the event(s)
+ * to remove */
{
- TestEvent* ev; /* Event to examine */
- char* evNameStr;
- Tcl_Obj* targetName; /* Name of the event(s) to delete */
- char* targetNameStr;
+ TestEvent *ev; /* Event to examine */
+ char *evNameStr;
+ Tcl_Obj *targetName; /* Name of the event(s) to delete */
+ char *targetNameStr;
- if ( event->proc != TesteventProc ) {
+ if (event->proc != TesteventProc) {
return 0;
}
- targetName = (Tcl_Obj*) clientData;
- targetNameStr = (char*) Tcl_GetStringFromObj( targetName, NULL );
- ev = (TestEvent*) event;
- evNameStr = Tcl_GetStringFromObj( ev->tag, NULL );
- if ( strcmp( evNameStr, targetNameStr ) == 0 ) {
- Tcl_DecrRefCount( ev->tag );
- Tcl_DecrRefCount( ev->command );
+ targetName = (Tcl_Obj *) clientData;
+ targetNameStr = (char *) Tcl_GetStringFromObj(targetName, NULL);
+ ev = (TestEvent *) event;
+ evNameStr = Tcl_GetStringFromObj(ev->tag, NULL);
+ if (strcmp(evNameStr, targetNameStr) == 0) {
+ Tcl_DecrRefCount(ev->tag);
+ Tcl_DecrRefCount(ev->command);
return 1;
} else {
return 0;
@@ -2174,54 +2278,62 @@ TesteventDeleteProc( Tcl_Event* event, /* Event to examine */
*/
static int
-TestexithandlerCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestexithandlerCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
int value;
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
- " create|delete value\"", (char *) NULL);
- return TCL_ERROR;
+ " create|delete value\"", NULL);
+ return TCL_ERROR;
}
if (Tcl_GetInt(interp, argv[2], &value) != TCL_OK) {
return TCL_ERROR;
}
if (strcmp(argv[1], "create") == 0) {
Tcl_CreateExitHandler((value & 1) ? ExitProcOdd : ExitProcEven,
- (ClientData) value);
+ (ClientData) INT2PTR(value));
} else if (strcmp(argv[1], "delete") == 0) {
Tcl_DeleteExitHandler((value & 1) ? ExitProcOdd : ExitProcEven,
- (ClientData) value);
+ (ClientData) INT2PTR(value));
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be create or delete", (char *) NULL);
+ "\": must be create or delete", NULL);
return TCL_ERROR;
}
return TCL_OK;
}
static void
-ExitProcOdd(clientData)
- ClientData clientData; /* Integer value to print. */
+ExitProcOdd(
+ ClientData clientData) /* Integer value to print. */
{
char buf[16 + TCL_INTEGER_SPACE];
+ size_t len;
- sprintf(buf, "odd %d\n", (int) clientData);
- write(1, buf, strlen(buf));
+ sprintf(buf, "odd %d\n", PTR2INT(clientData));
+ len = strlen(buf);
+ if (len != (size_t) write(1, buf, len)) {
+ Tcl_Panic("ExitProcOdd: unable to write to stdout");
+ }
}
static void
-ExitProcEven(clientData)
- ClientData clientData; /* Integer value to print. */
+ExitProcEven(
+ ClientData clientData) /* Integer value to print. */
{
char buf[16 + TCL_INTEGER_SPACE];
+ size_t len;
- sprintf(buf, "even %d\n", (int) clientData);
- write(1, buf, strlen(buf));
+ sprintf(buf, "even %d\n", PTR2INT(clientData));
+ len = strlen(buf);
+ if (len != (size_t) write(1, buf, len)) {
+ Tcl_Panic("ExitProcEven: unable to write to stdout");
+ }
}
/*
@@ -2242,20 +2354,25 @@ ExitProcEven(clientData)
*/
static int
-TestexprlongCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestexprlongCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
long exprResult;
char buf[4 + TCL_INTEGER_SPACE];
int result;
-
+
+ if (argc != 2) {
+ Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
+ " expression\"", NULL);
+ return TCL_ERROR;
+ }
Tcl_SetResult(interp, "This is a result", TCL_STATIC);
- result = Tcl_ExprLong(interp, "4+1", &exprResult);
+ result = Tcl_ExprLong(interp, argv[1], &exprResult);
if (result != TCL_OK) {
- return result;
+ return result;
}
sprintf(buf, ": %ld", exprResult);
Tcl_AppendResult(interp, buf, NULL);
@@ -2280,11 +2397,11 @@ TestexprlongCmd(clientData, interp, argc, argv)
*/
static int
-TestexprlongobjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST *objv; /* Argument objects. */
+TestexprlongobjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const *objv) /* Argument objects. */
{
long exprResult;
char buf[4 + TCL_INTEGER_SPACE];
@@ -2297,7 +2414,7 @@ TestexprlongobjCmd(clientData, interp, objc, objv)
Tcl_SetResult(interp, "This is a result", TCL_STATIC);
result = Tcl_ExprLongObj(interp, objv[1], &exprResult);
if (result != TCL_OK) {
- return result;
+ return result;
}
sprintf(buf, ": %ld", exprResult);
Tcl_AppendResult(interp, buf, NULL);
@@ -2307,6 +2424,93 @@ TestexprlongobjCmd(clientData, interp, objc, objv)
/*
*----------------------------------------------------------------------
*
+ * TestexprdoubleCmd --
+ *
+ * This procedure verifies that Tcl_ExprDouble does not modify the
+ * interpreter result if there is no error.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TestexprdoubleCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
+{
+ double exprResult;
+ char buf[4 + TCL_DOUBLE_SPACE];
+ int result;
+
+ if (argc != 2) {
+ Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
+ " expression\"", NULL);
+ return TCL_ERROR;
+ }
+ Tcl_SetResult(interp, "This is a result", TCL_STATIC);
+ result = Tcl_ExprDouble(interp, argv[1], &exprResult);
+ if (result != TCL_OK) {
+ return result;
+ }
+ strcpy(buf, ": ");
+ Tcl_PrintDouble(interp, exprResult, buf+2);
+ Tcl_AppendResult(interp, buf, NULL);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestexprdoubleobjCmd --
+ *
+ * This procedure verifies that Tcl_ExprLongObj does not modify the
+ * interpreter result if there is no error.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TestexprdoubleobjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const *objv) /* Argument objects. */
+{
+ double exprResult;
+ char buf[4 + TCL_DOUBLE_SPACE];
+ int result;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "expression");
+ return TCL_ERROR;
+ }
+ Tcl_SetResult(interp, "This is a result", TCL_STATIC);
+ result = Tcl_ExprDoubleObj(interp, objv[1], &exprResult);
+ if (result != TCL_OK) {
+ return result;
+ }
+ strcpy(buf, ": ");
+ Tcl_PrintDouble(interp, exprResult, buf+2);
+ Tcl_AppendResult(interp, buf, NULL);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TestexprstringCmd --
*
* This procedure tests the basic operation of Tcl_ExprString.
@@ -2321,16 +2525,16 @@ TestexprlongobjCmd(clientData, interp, objc, objv)
*/
static int
-TestexprstringCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestexprstringCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
if (argc != 2) {
- Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
- " expression\"", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
+ " expression\"", NULL);
+ return TCL_ERROR;
}
return Tcl_ExprString(interp, argv[1]);
}
@@ -2340,9 +2544,8 @@ TestexprstringCmd(clientData, interp, argc, argv)
*
* TestfilelinkCmd --
*
- * This procedure implements the "testfilelink" command. It is used
- * to test the effects of creating and manipulating filesystem links
- * in Tcl.
+ * This procedure implements the "testfilelink" command. It is used to
+ * test the effects of creating and manipulating filesystem links in Tcl.
*
* Results:
* A standard Tcl result.
@@ -2354,11 +2557,11 @@ TestexprstringCmd(clientData, interp, argc, argv)
*/
static int
-TestfilelinkCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* The argument objects. */
+TestfilelinkCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* The argument objects. */
{
Tcl_Obj *contents;
@@ -2366,35 +2569,35 @@ TestfilelinkCmd(clientData, interp, objc, objv)
Tcl_WrongNumArgs(interp, 1, objv, "source ?target?");
return TCL_ERROR;
}
-
+
if (Tcl_FSConvertToPathType(interp, objv[1]) != TCL_OK) {
return TCL_ERROR;
}
-
+
if (objc == 3) {
/* Create link from source to target */
- contents = Tcl_FSLink(objv[1], objv[2],
- TCL_CREATE_SYMBOLIC_LINK|TCL_CREATE_HARD_LINK);
+ contents = Tcl_FSLink(objv[1], objv[2],
+ TCL_CREATE_SYMBOLIC_LINK|TCL_CREATE_HARD_LINK);
if (contents == NULL) {
- Tcl_AppendResult(interp, "could not create link from \"",
- Tcl_GetString(objv[1]), "\" to \"",
- Tcl_GetString(objv[2]), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ Tcl_AppendResult(interp, "could not create link from \"",
+ Tcl_GetString(objv[1]), "\" to \"",
+ Tcl_GetString(objv[2]), "\": ",
+ Tcl_PosixError(interp), NULL);
return TCL_ERROR;
}
} else {
/* Read link */
contents = Tcl_FSLink(objv[1], NULL, 0);
if (contents == NULL) {
- Tcl_AppendResult(interp, "could not read link \"",
- Tcl_GetString(objv[1]), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ Tcl_AppendResult(interp, "could not read link \"",
+ Tcl_GetString(objv[1]), "\": ",
+ Tcl_PosixError(interp), NULL);
return TCL_ERROR;
}
}
Tcl_SetObjResult(interp, contents);
if (objc == 2) {
- /*
+ /*
* If we are creating a link, this will actually just
* be objv[3], and we don't own it
*/
@@ -2421,22 +2624,22 @@ TestfilelinkCmd(clientData, interp, objc, objv)
*/
static int
-TestgetassocdataCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestgetassocdataCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
char *res;
-
+
if (argc != 2) {
- Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
- " data_key\"", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
+ " data_key\"", NULL);
+ return TCL_ERROR;
}
res = (char *) Tcl_GetAssocData(interp, argv[1], NULL);
if (res != NULL) {
- Tcl_AppendResult(interp, res, NULL);
+ Tcl_AppendResult(interp, res, NULL);
}
return TCL_OK;
}
@@ -2459,25 +2662,21 @@ TestgetassocdataCmd(clientData, interp, argc, argv)
*/
static int
-TestgetplatformCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestgetplatformCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
- static CONST char *platformStrings[] = { "unix", "mac", "windows" };
+ static const char *platformStrings[] = { "unix", "mac", "windows" };
TclPlatformType *platform;
-#ifdef __WIN32__
- platform = TclWinGetPlatform();
-#else
- platform = &tclPlatform;
-#endif
-
+ platform = TclGetPlatform();
+
if (argc != 1) {
- Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
- (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
+ NULL);
+ return TCL_ERROR;
}
Tcl_AppendResult(interp, platformStrings[*platform], NULL);
@@ -2504,22 +2703,22 @@ TestgetplatformCmd(clientData, interp, argc, argv)
/* ARGSUSED */
static int
-TestinterpdeleteCmd(dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestinterpdeleteCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
Tcl_Interp *slaveToDelete;
if (argc != 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " path\"", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " path\"", NULL);
+ return TCL_ERROR;
}
slaveToDelete = Tcl_GetSlave(interp, argv[1]);
- if (slaveToDelete == (Tcl_Interp *) NULL) {
- return TCL_ERROR;
+ if (slaveToDelete == NULL) {
+ return TCL_ERROR;
}
Tcl_DeleteInterp(slaveToDelete);
return TCL_OK;
@@ -2545,17 +2744,26 @@ TestinterpdeleteCmd(dummy, interp, argc, argv)
/* ARGSUSED */
static int
-TestlinkCmd(dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestlinkCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
static int intVar = 43;
static int boolVar = 4;
static double realVar = 1.23;
static Tcl_WideInt wideVar = Tcl_LongAsWide(79);
static char *stringVar = NULL;
+ static char charVar = '@';
+ static unsigned char ucharVar = 130;
+ static short shortVar = 3000;
+ static unsigned short ushortVar = 60000;
+ static unsigned int uintVar = 0xbeeffeed;
+ static long longVar = 123456789L;
+ static unsigned long ulongVar = 3456789012UL;
+ static float floatVar = 4.5;
+ static Tcl_WideUInt uwideVar = (Tcl_WideUInt) Tcl_LongAsWide(123);
static int created = 0;
char buffer[2*TCL_DOUBLE_SPACE];
int writable, flag;
@@ -2563,14 +2771,16 @@ TestlinkCmd(dummy, interp, argc, argv)
if (argc < 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " option ?arg arg arg arg arg?\"", (char *) NULL);
+ " option ?arg arg arg arg arg arg arg arg arg arg arg arg"
+ " arg arg?\"", NULL);
return TCL_ERROR;
}
if (strcmp(argv[1], "create") == 0) {
- if (argc != 7) {
+ if (argc != 16) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " ", argv[1],
- " intRO realRO boolRO stringRO wideRO\"", (char *) NULL);
+ " intRO realRO boolRO stringRO wideRO charRO ucharRO shortRO"
+ " ushortRO uintRO longRO ulongRO floatRO uwideRO\"", NULL);
return TCL_ERROR;
}
if (created) {
@@ -2579,6 +2789,15 @@ TestlinkCmd(dummy, interp, argc, argv)
Tcl_UnlinkVar(interp, "bool");
Tcl_UnlinkVar(interp, "string");
Tcl_UnlinkVar(interp, "wide");
+ Tcl_UnlinkVar(interp, "char");
+ Tcl_UnlinkVar(interp, "uchar");
+ Tcl_UnlinkVar(interp, "short");
+ Tcl_UnlinkVar(interp, "ushort");
+ Tcl_UnlinkVar(interp, "uint");
+ Tcl_UnlinkVar(interp, "long");
+ Tcl_UnlinkVar(interp, "ulong");
+ Tcl_UnlinkVar(interp, "float");
+ Tcl_UnlinkVar(interp, "uwide");
}
created = 1;
if (Tcl_GetBoolean(interp, argv[2], &writable) != TCL_OK) {
@@ -2621,17 +2840,99 @@ TestlinkCmd(dummy, interp, argc, argv)
TCL_LINK_WIDE_INT | flag) != TCL_OK) {
return TCL_ERROR;
}
+ if (Tcl_GetBoolean(interp, argv[7], &writable) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
+ if (Tcl_LinkVar(interp, "char", (char *) &charVar,
+ TCL_LINK_CHAR | flag) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetBoolean(interp, argv[8], &writable) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
+ if (Tcl_LinkVar(interp, "uchar", (char *) &ucharVar,
+ TCL_LINK_UCHAR | flag) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetBoolean(interp, argv[9], &writable) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
+ if (Tcl_LinkVar(interp, "short", (char *) &shortVar,
+ TCL_LINK_SHORT | flag) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetBoolean(interp, argv[10], &writable) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
+ if (Tcl_LinkVar(interp, "ushort", (char *) &ushortVar,
+ TCL_LINK_USHORT | flag) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetBoolean(interp, argv[11], &writable) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
+ if (Tcl_LinkVar(interp, "uint", (char *) &uintVar,
+ TCL_LINK_UINT | flag) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetBoolean(interp, argv[12], &writable) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
+ if (Tcl_LinkVar(interp, "long", (char *) &longVar,
+ TCL_LINK_LONG | flag) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetBoolean(interp, argv[13], &writable) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
+ if (Tcl_LinkVar(interp, "ulong", (char *) &ulongVar,
+ TCL_LINK_ULONG | flag) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetBoolean(interp, argv[14], &writable) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
+ if (Tcl_LinkVar(interp, "float", (char *) &floatVar,
+ TCL_LINK_FLOAT | flag) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetBoolean(interp, argv[15], &writable) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
+ if (Tcl_LinkVar(interp, "uwide", (char *) &uwideVar,
+ TCL_LINK_WIDE_UINT | flag) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
} else if (strcmp(argv[1], "delete") == 0) {
Tcl_UnlinkVar(interp, "int");
Tcl_UnlinkVar(interp, "real");
Tcl_UnlinkVar(interp, "bool");
Tcl_UnlinkVar(interp, "string");
Tcl_UnlinkVar(interp, "wide");
+ Tcl_UnlinkVar(interp, "char");
+ Tcl_UnlinkVar(interp, "uchar");
+ Tcl_UnlinkVar(interp, "short");
+ Tcl_UnlinkVar(interp, "ushort");
+ Tcl_UnlinkVar(interp, "uint");
+ Tcl_UnlinkVar(interp, "long");
+ Tcl_UnlinkVar(interp, "ulong");
+ Tcl_UnlinkVar(interp, "float");
+ Tcl_UnlinkVar(interp, "uwide");
created = 0;
} else if (strcmp(argv[1], "get") == 0) {
TclFormatInt(buffer, intVar);
Tcl_AppendElement(interp, buffer);
- Tcl_PrintDouble((Tcl_Interp *) NULL, realVar, buffer);
+ Tcl_PrintDouble(NULL, realVar, buffer);
Tcl_AppendElement(interp, buffer);
TclFormatInt(buffer, boolVar);
Tcl_AppendElement(interp, buffer);
@@ -2642,12 +2943,36 @@ TestlinkCmd(dummy, interp, argc, argv)
tmp = Tcl_NewWideIntObj(wideVar);
Tcl_AppendElement(interp, Tcl_GetString(tmp));
Tcl_DecrRefCount(tmp);
+ TclFormatInt(buffer, (int) charVar);
+ Tcl_AppendElement(interp, buffer);
+ TclFormatInt(buffer, (int) ucharVar);
+ Tcl_AppendElement(interp, buffer);
+ TclFormatInt(buffer, (int) shortVar);
+ Tcl_AppendElement(interp, buffer);
+ TclFormatInt(buffer, (int) ushortVar);
+ Tcl_AppendElement(interp, buffer);
+ TclFormatInt(buffer, (int) uintVar);
+ Tcl_AppendElement(interp, buffer);
+ tmp = Tcl_NewLongObj(longVar);
+ Tcl_AppendElement(interp, Tcl_GetString(tmp));
+ Tcl_DecrRefCount(tmp);
+ tmp = Tcl_NewLongObj((long)ulongVar);
+ Tcl_AppendElement(interp, Tcl_GetString(tmp));
+ Tcl_DecrRefCount(tmp);
+ Tcl_PrintDouble(NULL, (double)floatVar, buffer);
+ Tcl_AppendElement(interp, buffer);
+ tmp = Tcl_NewWideIntObj((Tcl_WideInt)uwideVar);
+ Tcl_AppendElement(interp, Tcl_GetString(tmp));
+ Tcl_DecrRefCount(tmp);
} else if (strcmp(argv[1], "set") == 0) {
- if (argc != 7) {
+ int v;
+
+ if (argc != 16) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " ", argv[1],
- " intValue realValue boolValue stringValue wideValue\"",
- (char *) NULL);
+ " intValue realValue boolValue stringValue wideValue"
+ " charValue ucharValue shortValue ushortValue uintValue"
+ " longValue ulongValue floatValue uwideValue\"", NULL);
return TCL_ERROR;
}
if (argv[2][0] != 0) {
@@ -2684,12 +3009,74 @@ TestlinkCmd(dummy, interp, argc, argv)
}
Tcl_DecrRefCount(tmp);
}
+ if (argv[7][0]) {
+ if (Tcl_GetInt(interp, argv[7], &v) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ charVar = (char) v;
+ }
+ if (argv[8][0]) {
+ if (Tcl_GetInt(interp, argv[8], &v) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ ucharVar = (unsigned char) v;
+ }
+ if (argv[9][0]) {
+ if (Tcl_GetInt(interp, argv[9], &v) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ shortVar = (short) v;
+ }
+ if (argv[10][0]) {
+ if (Tcl_GetInt(interp, argv[10], &v) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ ushortVar = (unsigned short) v;
+ }
+ if (argv[11][0]) {
+ if (Tcl_GetInt(interp, argv[11], &v) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ uintVar = (unsigned int) v;
+ }
+ if (argv[12][0]) {
+ if (Tcl_GetInt(interp, argv[12], &v) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ longVar = (long) v;
+ }
+ if (argv[13][0]) {
+ if (Tcl_GetInt(interp, argv[13], &v) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ ulongVar = (unsigned long) v;
+ }
+ if (argv[14][0]) {
+ double d;
+ if (Tcl_GetDouble(interp, argv[14], &d) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ floatVar = (float) d;
+ }
+ if (argv[15][0]) {
+ Tcl_WideInt w;
+ tmp = Tcl_NewStringObj(argv[15], -1);
+ if (Tcl_GetWideIntFromObj(interp, tmp, &w) != TCL_OK) {
+ Tcl_DecrRefCount(tmp);
+ return TCL_ERROR;
+ }
+ Tcl_DecrRefCount(tmp);
+ uwideVar = (Tcl_WideUInt) w;
+ }
} else if (strcmp(argv[1], "update") == 0) {
- if (argc != 7) {
+ int v;
+
+ if (argc != 16) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " ", argv[1],
- "intValue realValue boolValue stringValue wideValue\"",
- (char *) NULL);
+ " intValue realValue boolValue stringValue wideValue"
+ " charValue ucharValue shortValue ushortValue uintValue"
+ " longValue ulongValue floatValue uwideValue\"", NULL);
return TCL_ERROR;
}
if (argv[2][0] != 0) {
@@ -2731,10 +3118,77 @@ TestlinkCmd(dummy, interp, argc, argv)
Tcl_DecrRefCount(tmp);
Tcl_UpdateLinkedVar(interp, "wide");
}
+ if (argv[7][0]) {
+ if (Tcl_GetInt(interp, argv[7], &v) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ charVar = (char) v;
+ Tcl_UpdateLinkedVar(interp, "char");
+ }
+ if (argv[8][0]) {
+ if (Tcl_GetInt(interp, argv[8], &v) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ ucharVar = (unsigned char) v;
+ Tcl_UpdateLinkedVar(interp, "uchar");
+ }
+ if (argv[9][0]) {
+ if (Tcl_GetInt(interp, argv[9], &v) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ shortVar = (short) v;
+ Tcl_UpdateLinkedVar(interp, "short");
+ }
+ if (argv[10][0]) {
+ if (Tcl_GetInt(interp, argv[10], &v) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ ushortVar = (unsigned short) v;
+ Tcl_UpdateLinkedVar(interp, "ushort");
+ }
+ if (argv[11][0]) {
+ if (Tcl_GetInt(interp, argv[11], &v) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ uintVar = (unsigned int) v;
+ Tcl_UpdateLinkedVar(interp, "uint");
+ }
+ if (argv[12][0]) {
+ if (Tcl_GetInt(interp, argv[12], &v) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ longVar = (long) v;
+ Tcl_UpdateLinkedVar(interp, "long");
+ }
+ if (argv[13][0]) {
+ if (Tcl_GetInt(interp, argv[13], &v) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ ulongVar = (unsigned long) v;
+ Tcl_UpdateLinkedVar(interp, "ulong");
+ }
+ if (argv[14][0]) {
+ double d;
+ if (Tcl_GetDouble(interp, argv[14], &d) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ floatVar = (float) d;
+ Tcl_UpdateLinkedVar(interp, "float");
+ }
+ if (argv[15][0]) {
+ Tcl_WideInt w;
+ tmp = Tcl_NewStringObj(argv[15], -1);
+ if (Tcl_GetWideIntFromObj(interp, tmp, &w) != TCL_OK) {
+ Tcl_DecrRefCount(tmp);
+ return TCL_ERROR;
+ }
+ Tcl_DecrRefCount(tmp);
+ uwideVar = (Tcl_WideUInt) w;
+ Tcl_UpdateLinkedVar(interp, "uwide");
+ }
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": should be create, delete, get, set, or update",
- (char *) NULL);
+ "\": should be create, delete, get, set, or update", NULL);
return TCL_ERROR;
}
return TCL_OK;
@@ -2758,17 +3212,17 @@ TestlinkCmd(dummy, interp, argc, argv)
*/
static int
-TestlocaleCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* The argument objects. */
+TestlocaleCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* The argument objects. */
{
int index;
char *locale;
- static CONST char *optionStrings[] = {
- "ctype", "numeric", "time", "collate", "monetary",
+ static const char *optionStrings[] = {
+ "ctype", "numeric", "time", "collate", "monetary",
"all", NULL
};
static int lcTypes[] = {
@@ -2784,7 +3238,7 @@ TestlocaleCmd(clientData, interp, objc, objv)
Tcl_WrongNumArgs(interp, 1, objv, "category ?locale?");
return TCL_ERROR;
}
-
+
if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
&index) != TCL_OK) {
return TCL_ERROR;
@@ -2821,14 +3275,14 @@ TestlocaleCmd(clientData, interp, objc, objv)
/* ARGSUSED */
static int
-TestMathFunc(clientData, interp, args, resultPtr)
- ClientData clientData; /* Integer value to return. */
- Tcl_Interp *interp; /* Not used. */
- Tcl_Value *args; /* Not used. */
- Tcl_Value *resultPtr; /* Where to store result. */
+TestMathFunc(
+ ClientData clientData, /* Integer value to return. */
+ Tcl_Interp *interp, /* Not used. */
+ Tcl_Value *args, /* Not used. */
+ Tcl_Value *resultPtr) /* Where to store result. */
{
resultPtr->type = TCL_INT;
- resultPtr->intValue = (int) clientData;
+ resultPtr->intValue = PTR2INT(clientData);
return TCL_OK;
}
@@ -2851,26 +3305,25 @@ TestMathFunc(clientData, interp, args, resultPtr)
/* ARGSUSED */
static int
-TestMathFunc2(clientData, interp, args, resultPtr)
- ClientData clientData; /* Integer value to return. */
- Tcl_Interp *interp; /* Used to report errors. */
- Tcl_Value *args; /* Points to an array of two
- * Tcl_Value structs for the
- * two arguments. */
- Tcl_Value *resultPtr; /* Where to store the result. */
+TestMathFunc2(
+ ClientData clientData, /* Integer value to return. */
+ Tcl_Interp *interp, /* Used to report errors. */
+ Tcl_Value *args, /* Points to an array of two Tcl_Value structs
+ * for the two arguments. */
+ Tcl_Value *resultPtr) /* Where to store the result. */
{
int result = TCL_OK;
-
+
/*
* Return the maximum of the two arguments with the correct type.
*/
-
+
if (args[0].type == TCL_INT) {
int i0 = args[0].intValue;
-
+
if (args[1].type == TCL_INT) {
int i1 = args[1].intValue;
-
+
resultPtr->type = TCL_INT;
resultPtr->intValue = ((i0 > i1)? i0 : i1);
} else if (args[1].type == TCL_DOUBLE) {
@@ -2891,10 +3344,10 @@ TestMathFunc2(clientData, interp, args, resultPtr)
}
} else if (args[0].type == TCL_DOUBLE) {
double d0 = args[0].doubleValue;
-
+
if (args[1].type == TCL_INT) {
double d1 = args[1].intValue;
-
+
resultPtr->type = TCL_DOUBLE;
resultPtr->doubleValue = ((d0 > d1)? d0 : d1);
} else if (args[1].type == TCL_DOUBLE) {
@@ -2913,10 +3366,10 @@ TestMathFunc2(clientData, interp, args, resultPtr)
}
} else if (args[0].type == TCL_WIDE_INT) {
Tcl_WideInt w0 = args[0].wideValue;
-
+
if (args[1].type == TCL_INT) {
Tcl_WideInt w1 = Tcl_LongAsWide(args[1].intValue);
-
+
resultPtr->type = TCL_WIDE_INT;
resultPtr->wideValue = ((w0 > w1)? w0 : w1);
} else if (args[1].type == TCL_DOUBLE) {
@@ -2959,9 +3412,9 @@ TestMathFunc2(clientData, interp, args, resultPtr)
*/
/* ARGSUSED */
static void
-CleanupTestSetassocdataTests(clientData, interp)
- ClientData clientData; /* Data to be released. */
- Tcl_Interp *interp; /* Interpreter being deleted. */
+CleanupTestSetassocdataTests(
+ ClientData clientData, /* Data to be released. */
+ Tcl_Interp *interp) /* Interpreter being deleted. */
{
ckfree((char *) clientData);
}
@@ -2984,11 +3437,11 @@ CleanupTestSetassocdataTests(clientData, interp)
*/
static int
-TestparserObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* The argument objects. */
+TestparserObjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* The argument objects. */
{
char *script;
int length, dummy;
@@ -3040,11 +3493,11 @@ TestparserObjCmd(clientData, interp, objc, objv)
*/
static int
-TestexprparserObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* The argument objects. */
+TestexprparserObjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* The argument objects. */
{
char *script;
int length, dummy;
@@ -3061,6 +3514,10 @@ TestexprparserObjCmd(clientData, interp, objc, objv)
if (length == 0) {
length = dummy;
}
+ parse.commentStart = NULL;
+ parse.commentSize = 0;
+ parse.commandStart = NULL;
+ parse.commandSize = 0;
if (Tcl_ParseExpr(interp, script, length, &parse) != TCL_OK) {
Tcl_AddErrorInfo(interp, "\n (remainder of expr: \"");
Tcl_AddErrorInfo(interp, parse.term);
@@ -3097,10 +3554,10 @@ TestexprparserObjCmd(clientData, interp, objc, objv)
*/
static void
-PrintParse(interp, parsePtr)
- Tcl_Interp *interp; /* Interpreter whose result is to be set to
+PrintParse(
+ Tcl_Interp *interp, /* Interpreter whose result is to be set to
* the contents of a parse structure. */
- Tcl_Parse *parsePtr; /* Parse structure to print out. */
+ Tcl_Parse *parsePtr) /* Parse structure to print out. */
{
Tcl_Obj *objPtr;
char *typeString;
@@ -3109,56 +3566,58 @@ PrintParse(interp, parsePtr)
objPtr = Tcl_GetObjResult(interp);
if (parsePtr->commentSize > 0) {
- Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr,
+ Tcl_ListObjAppendElement(NULL, objPtr,
Tcl_NewStringObj(parsePtr->commentStart,
parsePtr->commentSize));
} else {
- Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr,
- Tcl_NewStringObj("-", 1));
+ Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewStringObj("-", 1));
}
- Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr,
+ Tcl_ListObjAppendElement(NULL, objPtr,
Tcl_NewStringObj(parsePtr->commandStart, parsePtr->commandSize));
- Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr,
+ Tcl_ListObjAppendElement(NULL, objPtr,
Tcl_NewIntObj(parsePtr->numWords));
for (i = 0; i < parsePtr->numTokens; i++) {
tokenPtr = &parsePtr->tokenPtr[i];
switch (tokenPtr->type) {
- case TCL_TOKEN_WORD:
- typeString = "word";
- break;
- case TCL_TOKEN_SIMPLE_WORD:
- typeString = "simple";
- break;
- case TCL_TOKEN_TEXT:
- typeString = "text";
- break;
- case TCL_TOKEN_BS:
- typeString = "backslash";
- break;
- case TCL_TOKEN_COMMAND:
- typeString = "command";
- break;
- case TCL_TOKEN_VARIABLE:
- typeString = "variable";
- break;
- case TCL_TOKEN_SUB_EXPR:
- typeString = "subexpr";
- break;
- case TCL_TOKEN_OPERATOR:
- typeString = "operator";
- break;
- default:
- typeString = "??";
- break;
+ case TCL_TOKEN_EXPAND_WORD:
+ typeString = "expand";
+ break;
+ case TCL_TOKEN_WORD:
+ typeString = "word";
+ break;
+ case TCL_TOKEN_SIMPLE_WORD:
+ typeString = "simple";
+ break;
+ case TCL_TOKEN_TEXT:
+ typeString = "text";
+ break;
+ case TCL_TOKEN_BS:
+ typeString = "backslash";
+ break;
+ case TCL_TOKEN_COMMAND:
+ typeString = "command";
+ break;
+ case TCL_TOKEN_VARIABLE:
+ typeString = "variable";
+ break;
+ case TCL_TOKEN_SUB_EXPR:
+ typeString = "subexpr";
+ break;
+ case TCL_TOKEN_OPERATOR:
+ typeString = "operator";
+ break;
+ default:
+ typeString = "??";
+ break;
}
- Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr,
+ Tcl_ListObjAppendElement(NULL, objPtr,
Tcl_NewStringObj(typeString, -1));
- Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr,
+ Tcl_ListObjAppendElement(NULL, objPtr,
Tcl_NewStringObj(tokenPtr->start, tokenPtr->size));
- Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr,
+ Tcl_ListObjAppendElement(NULL, objPtr,
Tcl_NewIntObj(tokenPtr->numComponents));
}
- Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr,
+ Tcl_ListObjAppendElement(NULL, objPtr,
Tcl_NewStringObj(parsePtr->commandStart + parsePtr->commandSize,
-1));
}
@@ -3181,14 +3640,13 @@ PrintParse(interp, parsePtr)
*/
static int
-TestparsevarObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* The argument objects. */
+TestparsevarObjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* The argument objects. */
{
- CONST char *value;
- CONST char *name, *termPtr;
+ const char *value, *name, *termPtr;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "varName");
@@ -3223,11 +3681,11 @@ TestparsevarObjCmd(clientData, interp, objc, objv)
*/
static int
-TestparsevarnameObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* The argument objects. */
+TestparsevarnameObjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* The argument objects. */
{
char *script;
int append, length, dummy;
@@ -3272,10 +3730,10 @@ TestparsevarnameObjCmd(clientData, interp, objc, objv)
*
* TestregexpObjCmd --
*
- * This procedure implements the "testregexp" command. It is
- * used to give a direct interface for regexp flags. It's identical
- * to Tcl_RegexpObjCmd except for the -xflags option, and the
- * consequences thereof (including the REG_EXPECT kludge).
+ * This procedure implements the "testregexp" command. It is used to give
+ * a direct interface for regexp flags. It's identical to
+ * Tcl_RegexpObjCmd except for the -xflags option, and the consequences
+ * thereof (including the REG_EXPECT kludge).
*
* Results:
* A standard Tcl result.
@@ -3288,11 +3746,11 @@ TestparsevarnameObjCmd(clientData, interp, objc, objv)
/* ARGSUSED */
static int
-TestregexpObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+TestregexpObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
int i, ii, indices, stringLength, match, about;
int hasxflags, cflags, eflags;
@@ -3300,11 +3758,11 @@ TestregexpObjCmd(dummy, interp, objc, objv)
char *string;
Tcl_Obj *objPtr;
Tcl_RegExpInfo info;
- static CONST char *options[] = {
+ static const char *options[] = {
"-indices", "-nocase", "-about", "-expanded",
"-line", "-linestop", "-lineanchor",
"-xflags",
- "--", (char *) NULL
+ "--", NULL
};
enum options {
REGEXP_INDICES, REGEXP_NOCASE, REGEXP_ABOUT, REGEXP_EXPANDED,
@@ -3318,7 +3776,7 @@ TestregexpObjCmd(dummy, interp, objc, objv)
cflags = REG_ADVANCED;
eflags = 0;
hasxflags = 0;
-
+
for (i = 1; i < objc; i++) {
char *name;
int index;
@@ -3332,46 +3790,37 @@ TestregexpObjCmd(dummy, interp, objc, objv)
return TCL_ERROR;
}
switch ((enum options) index) {
- case REGEXP_INDICES: {
- indices = 1;
- break;
- }
- case REGEXP_NOCASE: {
- cflags |= REG_ICASE;
- break;
- }
- case REGEXP_ABOUT: {
- about = 1;
- break;
- }
- case REGEXP_EXPANDED: {
- cflags |= REG_EXPANDED;
- break;
- }
- case REGEXP_MULTI: {
- cflags |= REG_NEWLINE;
- break;
- }
- case REGEXP_NOCROSS: {
- cflags |= REG_NLSTOP;
- break;
- }
- case REGEXP_NEWL: {
- cflags |= REG_NLANCH;
- break;
- }
- case REGEXP_XFLAGS: {
- hasxflags = 1;
- break;
- }
- case REGEXP_LAST: {
- i++;
- goto endOfForLoop;
- }
+ case REGEXP_INDICES:
+ indices = 1;
+ break;
+ case REGEXP_NOCASE:
+ cflags |= REG_ICASE;
+ break;
+ case REGEXP_ABOUT:
+ about = 1;
+ break;
+ case REGEXP_EXPANDED:
+ cflags |= REG_EXPANDED;
+ break;
+ case REGEXP_MULTI:
+ cflags |= REG_NEWLINE;
+ break;
+ case REGEXP_NOCROSS:
+ cflags |= REG_NLSTOP;
+ break;
+ case REGEXP_NEWL:
+ cflags |= REG_NLANCH;
+ break;
+ case REGEXP_XFLAGS:
+ hasxflags = 1;
+ break;
+ case REGEXP_LAST:
+ i++;
+ goto endOfForLoop;
}
}
- endOfForLoop:
+ endOfForLoop:
if (objc - i < hasxflags + 2 - about) {
Tcl_WrongNumArgs(interp, 1, objv,
"?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?");
@@ -3391,7 +3840,6 @@ TestregexpObjCmd(dummy, interp, objc, objv)
if (regExpr == NULL) {
return TCL_ERROR;
}
- objPtr = objv[1];
if (about) {
if (TclRegAbout(interp, regExpr) < 0) {
@@ -3400,6 +3848,7 @@ TestregexpObjCmd(dummy, interp, objc, objv)
return TCL_OK;
}
+ objPtr = objv[1];
match = Tcl_RegExpExecObj(interp, regExpr, objPtr, 0 /* offset */,
objc-2 /* nmatches */, eflags);
@@ -3409,13 +3858,13 @@ TestregexpObjCmd(dummy, interp, objc, objv)
if (match == 0) {
/*
* Set the interpreter's object result to an integer object w/
- * value 0.
+ * value 0.
*/
-
+
Tcl_SetIntObj(Tcl_GetObjResult(interp), 0);
if (objc > 2 && (cflags&REG_EXPECT) && indices) {
char *varName;
- CONST char *value;
+ const char *value;
int start, end;
char resinfo[TCL_INTEGER_SPACE * 2];
@@ -3425,12 +3874,12 @@ TestregexpObjCmd(dummy, interp, objc, objv)
value = Tcl_SetVar(interp, varName, resinfo, 0);
if (value == NULL) {
Tcl_AppendResult(interp, "couldn't set variable \"",
- varName, "\"", (char *) NULL);
+ varName, "\"", NULL);
return TCL_ERROR;
}
} else if (cflags & TCL_REG_CANMATCH) {
char *varName;
- CONST char *value;
+ const char *value;
char resinfo[TCL_INTEGER_SPACE * 2];
Tcl_RegExpGetInfo(regExpr, &info);
@@ -3439,7 +3888,7 @@ TestregexpObjCmd(dummy, interp, objc, objv)
value = Tcl_SetVar(interp, varName, resinfo, 0);
if (value == NULL) {
Tcl_AppendResult(interp, "couldn't set variable \"",
- varName, "\"", (char *) NULL);
+ varName, "\"", NULL);
return TCL_ERROR;
}
}
@@ -3458,7 +3907,7 @@ TestregexpObjCmd(dummy, interp, objc, objv)
for (i = 0; i < objc; i++) {
int start, end;
Tcl_Obj *newPtr, *varPtr, *valuePtr;
-
+
varPtr = objv[i];
ii = ((cflags&REG_EXPECT) && i == objc-1) ? -1 : i;
if (indices) {
@@ -3475,10 +3924,10 @@ TestregexpObjCmd(dummy, interp, objc, objv)
}
/*
- * Adjust index so it refers to the last character in the
- * match instead of the first character after the match.
+ * Adjust index so it refers to the last character in the match
+ * instead of the first character after the match.
*/
-
+
if (end >= 0) {
end--;
}
@@ -3498,20 +3947,18 @@ TestregexpObjCmd(dummy, interp, objc, objv)
info.matches[ii].end - 1);
}
}
- Tcl_IncrRefCount(newPtr);
valuePtr = Tcl_ObjSetVar2(interp, varPtr, NULL, newPtr, 0);
- Tcl_DecrRefCount(newPtr);
if (valuePtr == NULL) {
Tcl_AppendResult(interp, "couldn't set variable \"",
- Tcl_GetString(varPtr), "\"", (char *) NULL);
+ Tcl_GetString(varPtr), "\"", NULL);
return TCL_ERROR;
}
}
/*
- * Set the interpreter's object result to an integer object w/ value 1.
+ * Set the interpreter's object result to an integer object w/ value 1.
*/
-
+
Tcl_SetIntObj(Tcl_GetObjResult(interp), 1);
return TCL_OK;
}
@@ -3534,86 +3981,68 @@ TestregexpObjCmd(dummy, interp, objc, objv)
*/
static void
-TestregexpXflags(string, length, cflagsPtr, eflagsPtr)
- char *string; /* The string of flags. */
- int length; /* The length of the string in bytes. */
- int *cflagsPtr; /* compile flags word */
- int *eflagsPtr; /* exec flags word */
+TestregexpXflags(
+ char *string, /* The string of flags. */
+ int length, /* The length of the string in bytes. */
+ int *cflagsPtr, /* compile flags word */
+ int *eflagsPtr) /* exec flags word */
{
- int i;
- int cflags;
- int eflags;
+ int i, cflags, eflags;
cflags = *cflagsPtr;
eflags = *eflagsPtr;
for (i = 0; i < length; i++) {
switch (string[i]) {
- case 'a': {
- cflags |= REG_ADVF;
- break;
- }
- case 'b': {
- cflags &= ~REG_ADVANCED;
- break;
- }
- case 'c': {
- cflags |= TCL_REG_CANMATCH;
- break;
- }
- case 'e': {
- cflags &= ~REG_ADVANCED;
- cflags |= REG_EXTENDED;
- break;
- }
- case 'q': {
- cflags &= ~REG_ADVANCED;
- cflags |= REG_QUOTE;
- break;
- }
- case 'o': { /* o for opaque */
- cflags |= REG_NOSUB;
- break;
- }
- case 's': { /* s for start */
- cflags |= REG_BOSONLY;
- break;
- }
- case '+': {
- cflags |= REG_FAKE;
- break;
- }
- case ',': {
- cflags |= REG_PROGRESS;
- break;
- }
- case '.': {
- cflags |= REG_DUMP;
- break;
- }
- case ':': {
- eflags |= REG_MTRACE;
- break;
- }
- case ';': {
- eflags |= REG_FTRACE;
- break;
- }
- case '^': {
- eflags |= REG_NOTBOL;
- break;
- }
- case '$': {
- eflags |= REG_NOTEOL;
- break;
- }
- case 't': {
- cflags |= REG_EXPECT;
- break;
- }
- case '%': {
- eflags |= REG_SMALL;
- break;
- }
+ case 'a':
+ cflags |= REG_ADVF;
+ break;
+ case 'b':
+ cflags &= ~REG_ADVANCED;
+ break;
+ case 'c':
+ cflags |= TCL_REG_CANMATCH;
+ break;
+ case 'e':
+ cflags &= ~REG_ADVANCED;
+ cflags |= REG_EXTENDED;
+ break;
+ case 'q':
+ cflags &= ~REG_ADVANCED;
+ cflags |= REG_QUOTE;
+ break;
+ case 'o': /* o for opaque */
+ cflags |= REG_NOSUB;
+ break;
+ case 's': /* s for start */
+ cflags |= REG_BOSONLY;
+ break;
+ case '+':
+ cflags |= REG_FAKE;
+ break;
+ case ',':
+ cflags |= REG_PROGRESS;
+ break;
+ case '.':
+ cflags |= REG_DUMP;
+ break;
+ case ':':
+ eflags |= REG_MTRACE;
+ break;
+ case ';':
+ eflags |= REG_FTRACE;
+ break;
+ case '^':
+ eflags |= REG_NOTBOL;
+ break;
+ case '$':
+ eflags |= REG_NOTEOL;
+ break;
+ case 't':
+ cflags |= REG_EXPECT;
+ break;
+ case '%':
+ eflags |= REG_SMALL;
+ break;
}
}
@@ -3624,6 +4053,37 @@ TestregexpXflags(string, length, cflagsPtr, eflagsPtr)
/*
*----------------------------------------------------------------------
*
+ * TestreturnObjCmd --
+ *
+ * This procedure implements the "testreturn" command. It is
+ * used to verify that a
+ * return TCL_RETURN;
+ * has same behavior as
+ * return Tcl_SetReturnOptions(interp, Tcl_NewObj());
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+TestreturnObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ return TCL_RETURN;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TestsetassocdataCmd --
*
* This procedure implements the "testsetassocdata" command. It is used
@@ -3640,20 +4100,19 @@ TestregexpXflags(string, length, cflagsPtr, eflagsPtr)
*/
static int
-TestsetassocdataCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
-{
- char *buf;
- char *oldData;
+TestsetassocdataCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
+{
+ char *buf, *oldData;
Tcl_InterpDeleteProc *procPtr;
-
+
if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
- " data_key data_item\"", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
+ " data_key data_item\"", NULL);
+ return TCL_ERROR;
}
buf = ckalloc((unsigned) strlen(argv[2]) + 1);
@@ -3668,8 +4127,8 @@ TestsetassocdataCmd(clientData, interp, argc, argv)
if ((oldData != NULL) && (procPtr == CleanupTestSetassocdataTests)) {
ckfree(oldData);
}
-
- Tcl_SetAssocData(interp, argv[1], CleanupTestSetassocdataTests,
+
+ Tcl_SetAssocData(interp, argv[1], CleanupTestSetassocdataTests,
(ClientData) buf);
return TCL_OK;
}
@@ -3693,37 +4152,31 @@ TestsetassocdataCmd(clientData, interp, argc, argv)
*/
static int
-TestsetplatformCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestsetplatformCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
size_t length;
TclPlatformType *platform;
-#ifdef __WIN32__
- platform = TclWinGetPlatform();
-#else
- platform = &tclPlatform;
-#endif
-
+ platform = TclGetPlatform();
+
if (argc != 2) {
- Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
- " platform\"", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
+ " platform\"", NULL);
+ return TCL_ERROR;
}
length = strlen(argv[1]);
if (strncmp(argv[1], "unix", length) == 0) {
*platform = TCL_PLATFORM_UNIX;
- } else if (strncmp(argv[1], "mac", length) == 0) {
- *platform = TCL_PLATFORM_MAC;
} else if (strncmp(argv[1], "windows", length) == 0) {
*platform = TCL_PLATFORM_WINDOWS;
} else {
- Tcl_AppendResult(interp, "unsupported platform: should be one of ",
- "unix, mac, or windows", (char *) NULL);
+ Tcl_AppendResult(interp, "unsupported platform: should be one of "
+ "unix, or windows", NULL);
return TCL_ERROR;
}
return TCL_OK;
@@ -3748,17 +4201,17 @@ TestsetplatformCmd(clientData, interp, argc, argv)
*/
static int
-TeststaticpkgCmd(dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TeststaticpkgCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
int safe, loaded;
if (argc != 4) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"",
- argv[0], " pkgName safe loaded\"", (char *) NULL);
+ argv[0], " pkgName safe loaded\"", NULL);
return TCL_ERROR;
}
if (Tcl_GetInt(interp, argv[2], &safe) != TCL_OK) {
@@ -3773,9 +4226,9 @@ TeststaticpkgCmd(dummy, interp, argc, argv)
}
static int
-StaticInitProc(interp)
- Tcl_Interp *interp; /* Interpreter in which package
- * is supposedly being loaded. */
+StaticInitProc(
+ Tcl_Interp *interp) /* Interpreter in which package is supposedly
+ * being loaded. */
{
Tcl_SetVar(interp, "x", "loaded", TCL_GLOBAL_ONLY);
return TCL_OK;
@@ -3799,18 +4252,18 @@ StaticInitProc(interp)
*/
static int
-TesttranslatefilenameCmd(dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TesttranslatefilenameCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
Tcl_DString buffer;
- CONST char *result;
+ const char *result;
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"",
- argv[0], " path\"", (char *) NULL);
+ argv[0], " path\"", NULL);
return TCL_ERROR;
}
result = Tcl_TranslateFileName(interp, argv[1], &buffer);
@@ -3841,17 +4294,17 @@ TesttranslatefilenameCmd(dummy, interp, argc, argv)
/* ARGSUSED */
static int
-TestupvarCmd(dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestupvarCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
int flags = 0;
-
+
if ((argc != 5) && (argc != 6)) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"",
- argv[0], " level name ?name2? dest global\"", (char *) NULL);
+ argv[0], " level name ?name2? dest global\"", NULL);
return TCL_ERROR;
}
@@ -3868,8 +4321,8 @@ TestupvarCmd(dummy, interp, argc, argv)
} else if (strcmp(argv[5], "namespace") == 0) {
flags = TCL_NAMESPACE_ONLY;
}
- return Tcl_UpVar2(interp, argv[1], argv[2],
- (argv[3][0] == 0) ? (char *) NULL : argv[3], argv[4],
+ return Tcl_UpVar2(interp, argv[1], argv[2],
+ (argv[3][0] == 0) ? NULL : argv[3], argv[4],
flags);
}
}
@@ -3879,9 +4332,8 @@ TestupvarCmd(dummy, interp, argc, argv)
*
* TestseterrorcodeCmd --
*
- * This procedure implements the "testseterrorcodeCmd".
- * This tests up to five elements passed to the
- * Tcl_SetErrorCode command.
+ * This procedure implements the "testseterrorcodeCmd". This tests up to
+ * five elements passed to the Tcl_SetErrorCode command.
*
* Results:
* A standard Tcl result. Always returns TCL_ERROR so that
@@ -3895,11 +4347,11 @@ TestupvarCmd(dummy, interp, argc, argv)
/* ARGSUSED */
static int
-TestseterrorcodeCmd(dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestseterrorcodeCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
if (argc > 6) {
Tcl_SetResult(interp, "too many args", TCL_STATIC);
@@ -3930,22 +4382,13 @@ TestseterrorcodeCmd(dummy, interp, argc, argv)
/* ARGSUSED */
static int
-TestsetobjerrorcodeCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* The argument objects. */
+TestsetobjerrorcodeCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* The argument objects. */
{
- Tcl_Obj *listObjPtr;
-
- if (objc > 1) {
- listObjPtr = Tcl_ConcatObj(objc - 1, objv + 1);
- } else {
- listObjPtr = Tcl_NewObj();
- }
- Tcl_IncrRefCount(listObjPtr);
- Tcl_SetObjErrorCode(interp, listObjPtr);
- Tcl_DecrRefCount(listObjPtr);
+ Tcl_SetObjErrorCode(interp, Tcl_ConcatObj(objc - 1, objv + 1));
return TCL_ERROR;
}
@@ -3968,11 +4411,11 @@ TestsetobjerrorcodeCmd(dummy, interp, objc, objv)
/* ARGSUSED */
static int
-TestfeventCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestfeventCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
static Tcl_Interp *interp2 = NULL;
int code;
@@ -3980,46 +4423,46 @@ TestfeventCmd(clientData, interp, argc, argv)
if (argc < 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " option ?arg arg ...?", (char *) NULL);
+ " option ?arg arg ...?", NULL);
return TCL_ERROR;
}
if (strcmp(argv[1], "cmd") == 0) {
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " cmd script", (char *) NULL);
+ " cmd script", NULL);
return TCL_ERROR;
}
- if (interp2 != (Tcl_Interp *) NULL) {
- code = Tcl_GlobalEval(interp2, argv[2]);
+ if (interp2 != NULL) {
+ code = Tcl_GlobalEval(interp2, argv[2]);
Tcl_SetObjResult(interp, Tcl_GetObjResult(interp2));
- return code;
- } else {
- Tcl_AppendResult(interp,
- "called \"testfevent code\" before \"testfevent create\"",
- (char *) NULL);
- return TCL_ERROR;
- }
+ return code;
+ } else {
+ Tcl_AppendResult(interp,
+ "called \"testfevent code\" before \"testfevent create\"",
+ NULL);
+ return TCL_ERROR;
+ }
} else if (strcmp(argv[1], "create") == 0) {
if (interp2 != NULL) {
- Tcl_DeleteInterp(interp2);
+ Tcl_DeleteInterp(interp2);
}
- interp2 = Tcl_CreateInterp();
+ interp2 = Tcl_CreateInterp();
return Tcl_Init(interp2);
} else if (strcmp(argv[1], "delete") == 0) {
if (interp2 != NULL) {
- Tcl_DeleteInterp(interp2);
+ Tcl_DeleteInterp(interp2);
}
interp2 = NULL;
} else if (strcmp(argv[1], "share") == 0) {
- if (interp2 != NULL) {
- chan = Tcl_GetChannel(interp, argv[2], NULL);
- if (chan == (Tcl_Channel) NULL) {
- return TCL_ERROR;
- }
- Tcl_RegisterChannel(interp2, chan);
- }
- }
-
+ if (interp2 != NULL) {
+ chan = Tcl_GetChannel(interp, argv[2], NULL);
+ if (chan == (Tcl_Channel) NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_RegisterChannel(interp2, chan);
+ }
+ }
+
return TCL_OK;
}
@@ -4031,7 +4474,7 @@ TestfeventCmd(clientData, interp, argc, argv)
* Calls the panic routine.
*
* Results:
- * Always returns TCL_OK.
+ * Always returns TCL_OK.
*
* Side effects:
* May exit application.
@@ -4040,37 +4483,37 @@ TestfeventCmd(clientData, interp, argc, argv)
*/
static int
-TestpanicCmd(dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
-{
- CONST char *argString;
-
+TestpanicCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
+{
+ const char *argString;
+
/*
* Put the arguments into a var args structure
* Append all of the arguments together separated by spaces
*/
argString = Tcl_Merge(argc-1, argv+1);
- panic(argString);
+ Tcl_Panic("%s", argString);
ckfree((char *)argString);
-
+
return TCL_OK;
}
-
+
static int
-TestfileCmd(dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- Tcl_Obj *CONST argv[]; /* The argument objects. */
+TestfileCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ Tcl_Obj *const argv[]) /* The argument objects. */
{
int force, i, j, result;
Tcl_Obj *error = NULL;
char *subcmd;
-
+
if (argc < 3) {
return TCL_ERROR;
}
@@ -4078,7 +4521,7 @@ TestfileCmd(dummy, interp, argc, argv)
force = 0;
i = 2;
if (strcmp(Tcl_GetString(argv[2]), "-force") == 0) {
- force = 1;
+ force = 1;
i = 3;
}
@@ -4087,30 +4530,30 @@ TestfileCmd(dummy, interp, argc, argv)
}
for (j = i; j < argc; j++) {
- if (Tcl_FSGetNormalizedPath(interp, argv[j]) == NULL) {
+ if (Tcl_FSGetNormalizedPath(interp, argv[j]) == NULL) {
return TCL_ERROR;
}
}
subcmd = Tcl_GetString(argv[1]);
-
+
if (strcmp(subcmd, "mv") == 0) {
result = TclpObjRenameFile(argv[i], argv[i + 1]);
} else if (strcmp(subcmd, "cp") == 0) {
- result = TclpObjCopyFile(argv[i], argv[i + 1]);
+ result = TclpObjCopyFile(argv[i], argv[i + 1]);
} else if (strcmp(subcmd, "rm") == 0) {
- result = TclpObjDeleteFile(argv[i]);
+ result = TclpObjDeleteFile(argv[i]);
} else if (strcmp(subcmd, "mkdir") == 0) {
- result = TclpObjCreateDirectory(argv[i]);
+ result = TclpObjCreateDirectory(argv[i]);
} else if (strcmp(subcmd, "cpdir") == 0) {
- result = TclpObjCopyDirectory(argv[i], argv[i + 1], &error);
+ result = TclpObjCopyDirectory(argv[i], argv[i + 1], &error);
} else if (strcmp(subcmd, "rmdir") == 0) {
- result = TclpObjRemoveDirectory(argv[i], force, &error);
+ result = TclpObjRemoveDirectory(argv[i], force, &error);
} else {
- result = TCL_ERROR;
+ result = TCL_ERROR;
goto end;
}
-
+
if (result != TCL_OK) {
if (error != NULL) {
if (Tcl_GetString(error)[0] != '\0') {
@@ -4118,11 +4561,10 @@ TestfileCmd(dummy, interp, argc, argv)
}
Tcl_DecrRefCount(error);
}
- Tcl_AppendResult(interp, Tcl_ErrnoId(), (char *) NULL);
+ Tcl_AppendResult(interp, Tcl_ErrnoId(), NULL);
}
- end:
-
+ end:
return result;
}
@@ -4144,24 +4586,24 @@ TestfileCmd(dummy, interp, argc, argv)
*/
static int
-TestgetvarfullnameCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* The argument objects. */
+TestgetvarfullnameCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* The argument objects. */
{
char *name, *arg;
int flags = 0;
Tcl_Namespace *namespacePtr;
- Tcl_CallFrame frame;
+ Tcl_CallFrame *framePtr;
Tcl_Var variable;
int result;
if (objc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, "name scope");
- return TCL_ERROR;
+ return TCL_ERROR;
}
-
+
name = Tcl_GetString(objv[1]);
arg = Tcl_GetString(objv[2]);
@@ -4172,30 +4614,29 @@ TestgetvarfullnameCmd(dummy, interp, objc, objv)
}
/*
- * This command, like any other created with Tcl_Create[Obj]Command,
- * runs in the global namespace. As a "namespace-aware" command that
- * needs to run in a particular namespace, it must activate that
- * namespace itself.
+ * This command, like any other created with Tcl_Create[Obj]Command, runs
+ * in the global namespace. As a "namespace-aware" command that needs to
+ * run in a particular namespace, it must activate that namespace itself.
*/
if (flags == TCL_NAMESPACE_ONLY) {
- namespacePtr = Tcl_FindNamespace(interp, "::test_ns_var",
- (Tcl_Namespace *) NULL, TCL_LEAVE_ERR_MSG);
+ namespacePtr = Tcl_FindNamespace(interp, "::test_ns_var", NULL,
+ TCL_LEAVE_ERR_MSG);
if (namespacePtr == NULL) {
return TCL_ERROR;
}
- result = Tcl_PushCallFrame(interp, &frame, namespacePtr,
- /*isProcCallFrame*/ 0);
+ result = TclPushStackFrame(interp, &framePtr, namespacePtr,
+ /*isProcCallFrame*/ 0);
if (result != TCL_OK) {
return result;
}
}
-
- variable = Tcl_FindNamespaceVar(interp, name, (Tcl_Namespace *) NULL,
+
+ variable = Tcl_FindNamespaceVar(interp, name, NULL,
(flags | TCL_LEAVE_ERR_MSG));
if (flags == TCL_NAMESPACE_ONLY) {
- Tcl_PopCallFrame(interp);
+ TclPopStackFrame(interp);
}
if (variable == (Tcl_Var) NULL) {
return TCL_ERROR;
@@ -4209,10 +4650,9 @@ TestgetvarfullnameCmd(dummy, interp, objc, objv)
*
* GetTimesCmd --
*
- * This procedure implements the "gettimes" command. It is
- * used for computing the time needed for various basic operations
- * such as reading variables, allocating memory, sprintf, converting
- * variables, etc.
+ * This procedure implements the "gettimes" command. It is used for
+ * computing the time needed for various basic operations such as reading
+ * variables, allocating memory, sprintf, converting variables, etc.
*
* Results:
* A standard Tcl result.
@@ -4224,19 +4664,18 @@ TestgetvarfullnameCmd(dummy, interp, objc, objv)
*/
static int
-GetTimesCmd(unused, interp, argc, argv)
- ClientData unused; /* Unused. */
- Tcl_Interp *interp; /* The current interpreter. */
- int argc; /* The number of arguments. */
- CONST char **argv; /* The argument strings. */
+GetTimesCmd(
+ ClientData unused, /* Unused. */
+ Tcl_Interp *interp, /* The current interpreter. */
+ int argc, /* The number of arguments. */
+ const char **argv) /* The argument strings. */
{
Interp *iPtr = (Interp *) interp;
int i, n;
double timePer;
Tcl_Time start, stop;
- Tcl_Obj *objPtr;
- Tcl_Obj **objv;
- CONST char *s;
+ Tcl_Obj *objPtr, **objv;
+ const char *s;
char newString[TCL_INTEGER_SPACE];
/* alloc & free 100000 times */
@@ -4249,7 +4688,7 @@ GetTimesCmd(unused, interp, argc, argv)
Tcl_GetTime(&stop);
timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
fprintf(stderr, " %.3f usec per alloc+free\n", timePer/100000);
-
+
/* alloc 5000 times */
fprintf(stderr, "alloc 5000 6 word items\n");
objv = (Tcl_Obj **) ckalloc(5000 * sizeof(Tcl_Obj *));
@@ -4260,7 +4699,7 @@ GetTimesCmd(unused, interp, argc, argv)
Tcl_GetTime(&stop);
timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
fprintf(stderr, " %.3f usec per alloc\n", timePer/5000);
-
+
/* free 5000 times */
fprintf(stderr, "free 5000 6 word items\n");
Tcl_GetTime(&start);
@@ -4280,7 +4719,7 @@ GetTimesCmd(unused, interp, argc, argv)
Tcl_GetTime(&stop);
timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
fprintf(stderr, " %.3f usec per Tcl_NewObj\n", timePer/5000);
-
+
/* Tcl_DecrRefCount 5000 times */
fprintf(stderr, "Tcl_DecrRefCount 5000 times\n");
Tcl_GetTime(&start);
@@ -4318,7 +4757,7 @@ GetTimesCmd(unused, interp, argc, argv)
fprintf(stderr, " %.3f usec per Tcl_GetIntFromObj of \"12345\"\n",
timePer/100000);
Tcl_DecrRefCount(objPtr);
-
+
/* Tcl_GetInt 100000 times */
fprintf(stderr, "Tcl_GetInt of \"12345\" 100000 times\n");
Tcl_GetTime(&start);
@@ -4381,7 +4820,7 @@ GetTimesCmd(unused, interp, argc, argv)
timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
fprintf(stderr, " %.3f usec per Tcl_GetVar of a==\"12345\"\n",
timePer/100000);
-
+
Tcl_ResetResult(interp);
return TCL_OK;
}
@@ -4404,11 +4843,11 @@ GetTimesCmd(unused, interp, argc, argv)
*/
static int
-NoopCmd(unused, interp, argc, argv)
- ClientData unused; /* Unused. */
- Tcl_Interp *interp; /* The current interpreter. */
- int argc; /* The number of arguments. */
- CONST char **argv; /* The argument strings. */
+NoopCmd(
+ ClientData unused, /* Unused. */
+ Tcl_Interp *interp, /* The current interpreter. */
+ int argc, /* The number of arguments. */
+ const char **argv) /* The argument strings. */
{
return TCL_OK;
}
@@ -4431,11 +4870,11 @@ NoopCmd(unused, interp, argc, argv)
*/
static int
-NoopObjCmd(unused, interp, objc, objv)
- ClientData unused; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* The argument objects. */
+NoopObjCmd(
+ ClientData unused, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* The argument objects. */
{
return TCL_OK;
}
@@ -4459,34 +4898,66 @@ NoopObjCmd(unused, interp, objc, objv)
/* ARGSUSED */
static int
-TestsetCmd(data, interp, argc, argv)
- ClientData data; /* Additional flags for Get/SetVar2. */
- register Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestsetCmd(
+ ClientData data, /* Additional flags for Get/SetVar2. */
+ register Tcl_Interp *interp,/* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
- int flags = (int) data;
- CONST char *value;
+ int flags = PTR2INT(data);
+ const char *value;
if (argc == 2) {
- Tcl_SetResult(interp, "before get", TCL_STATIC);
- value = Tcl_GetVar2(interp, argv[1], (char *) NULL, flags);
- if (value == NULL) {
- return TCL_ERROR;
- }
+ Tcl_SetResult(interp, "before get", TCL_STATIC);
+ value = Tcl_GetVar2(interp, argv[1], NULL, flags);
+ if (value == NULL) {
+ return TCL_ERROR;
+ }
Tcl_AppendElement(interp, value);
- return TCL_OK;
+ return TCL_OK;
} else if (argc == 3) {
Tcl_SetResult(interp, "before set", TCL_STATIC);
- value = Tcl_SetVar2(interp, argv[1], (char *) NULL, argv[2], flags);
- if (value == NULL) {
- return TCL_ERROR;
- }
+ value = Tcl_SetVar2(interp, argv[1], NULL, argv[2], flags);
+ if (value == NULL) {
+ return TCL_ERROR;
+ }
Tcl_AppendElement(interp, value);
return TCL_OK;
} else {
Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " varName ?newValue?\"", (char *) NULL);
+ argv[0], " varName ?newValue?\"", NULL);
+ return TCL_ERROR;
+ }
+}
+static int
+Testset2Cmd(
+ ClientData data, /* Additional flags for Get/SetVar2. */
+ register Tcl_Interp *interp,/* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
+{
+ int flags = PTR2INT(data);
+ const char *value;
+
+ if (argc == 3) {
+ Tcl_SetResult(interp, "before get", TCL_STATIC);
+ value = Tcl_GetVar2(interp, argv[1], argv[2], flags);
+ if (value == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_AppendElement(interp, value);
+ return TCL_OK;
+ } else if (argc == 4) {
+ Tcl_SetResult(interp, "before set", TCL_STATIC);
+ value = Tcl_SetVar2(interp, argv[1], argv[2], argv[3], flags);
+ if (value == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_AppendElement(interp, value);
+ return TCL_OK;
+ } else {
+ Tcl_AppendResult(interp, "wrong # args: should be \"",
+ argv[0], " varName elemName ?newValue?\"", NULL);
return TCL_ERROR;
}
}
@@ -4496,9 +4967,8 @@ TestsetCmd(data, interp, argc, argv)
*
* TestsaveresultCmd --
*
- * Implements the "testsaveresult" cmd that is used when testing
- * the Tcl_SaveResult, Tcl_RestoreResult, and
- * Tcl_DiscardResult interfaces.
+ * Implements the "testsaveresult" cmd that is used when testing the
+ * Tcl_SaveResult, Tcl_RestoreResult, and Tcl_DiscardResult interfaces.
*
* Results:
* A standard Tcl result.
@@ -4511,16 +4981,16 @@ TestsetCmd(data, interp, argc, argv)
/* ARGSUSED */
static int
-TestsaveresultCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- register Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* The argument objects. */
+TestsaveresultCmd(
+ ClientData dummy, /* Not used. */
+ register Tcl_Interp *interp,/* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* The argument objects. */
{
int discard, result, index;
Tcl_SavedResult state;
Tcl_Obj *objPtr;
- static CONST char *optionStrings[] = {
+ static const char *optionStrings[] = {
"append", "dynamic", "free", "object", "small", NULL
};
enum options {
@@ -4533,7 +5003,7 @@ TestsaveresultCmd(dummy, interp, objc, objv)
if (objc != 4) {
Tcl_WrongNumArgs(interp, 1, objv, "type script discard");
- return TCL_ERROR;
+ return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
&index) != TCL_OK) {
@@ -4545,25 +5015,26 @@ TestsaveresultCmd(dummy, interp, objc, objv)
objPtr = NULL; /* Lint. */
switch ((enum options) index) {
- case RESULT_SMALL:
- Tcl_SetResult(interp, "small result", TCL_VOLATILE);
- break;
- case RESULT_APPEND:
- Tcl_AppendResult(interp, "append result", NULL);
- break;
- case RESULT_FREE: {
- char *buf = ckalloc(200);
- strcpy(buf, "free result");
- Tcl_SetResult(interp, buf, TCL_DYNAMIC);
- break;
- }
- case RESULT_DYNAMIC:
- Tcl_SetResult(interp, "dynamic result", TestsaveresultFree);
- break;
- case RESULT_OBJECT:
- objPtr = Tcl_NewStringObj("object result", -1);
- Tcl_SetObjResult(interp, objPtr);
- break;
+ case RESULT_SMALL:
+ Tcl_SetResult(interp, "small result", TCL_VOLATILE);
+ break;
+ case RESULT_APPEND:
+ Tcl_AppendResult(interp, "append result", NULL);
+ break;
+ case RESULT_FREE: {
+ char *buf = ckalloc(200);
+
+ strcpy(buf, "free result");
+ Tcl_SetResult(interp, buf, TCL_DYNAMIC);
+ break;
+ }
+ case RESULT_DYNAMIC:
+ Tcl_SetResult(interp, "dynamic result", TestsaveresultFree);
+ break;
+ case RESULT_OBJECT:
+ objPtr = Tcl_NewStringObj("object result", -1);
+ Tcl_SetObjResult(interp, objPtr);
+ break;
}
freeCount = 0;
@@ -4583,19 +5054,20 @@ TestsaveresultCmd(dummy, interp, objc, objv)
}
switch ((enum options) index) {
- case RESULT_DYNAMIC: {
- int present = interp->freeProc == TestsaveresultFree;
- int called = freeCount;
- Tcl_AppendElement(interp, called ? "called" : "notCalled");
- Tcl_AppendElement(interp, present ? "present" : "missing");
- break;
- }
- case RESULT_OBJECT:
- Tcl_AppendElement(interp, Tcl_GetObjResult(interp) == objPtr
- ? "same" : "different");
- break;
- default:
- break;
+ case RESULT_DYNAMIC: {
+ int present = interp->freeProc == TestsaveresultFree;
+ int called = freeCount;
+
+ Tcl_AppendElement(interp, called ? "called" : "notCalled");
+ Tcl_AppendElement(interp, present ? "present" : "missing");
+ break;
+ }
+ case RESULT_OBJECT:
+ Tcl_AppendElement(interp, Tcl_GetObjResult(interp) == objPtr
+ ? "same" : "different");
+ break;
+ default:
+ break;
}
return result;
}
@@ -4617,11 +5089,12 @@ TestsaveresultCmd(dummy, interp, objc, objv)
*/
static void
-TestsaveresultFree(blockPtr)
- char *blockPtr;
+TestsaveresultFree(
+ char *blockPtr)
{
freeCount++;
}
+#ifdef USE_OBSOLETE_FS_HOOKS
/*
*----------------------------------------------------------------------
@@ -4641,18 +5114,18 @@ TestsaveresultFree(blockPtr)
*/
static int
-TeststatprocCmd (dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- register Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TeststatprocCmd(
+ ClientData dummy, /* Not used. */
+ register Tcl_Interp *interp,/* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
TclStatProc_ *proc;
int retVal;
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " option arg\"", (char *) NULL);
+ argv[0], " option arg\"", NULL);
return TCL_ERROR;
}
@@ -4665,41 +5138,40 @@ TeststatprocCmd (dummy, interp, argc, argv)
} else if (strcmp(argv[2], "TestStatProc3") == 0) {
proc = TestStatProc3;
} else {
- Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": ",
- "must be TclpStat, ",
- "TestStatProc1, TestStatProc2, or TestStatProc3",
- (char *) NULL);
+ Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": "
+ "must be TclpStat, "
+ "TestStatProc1, TestStatProc2, or TestStatProc3", NULL);
return TCL_ERROR;
}
if (strcmp(argv[1], "insert") == 0) {
if (proc == PretendTclpStat) {
- Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": ",
- "must be ",
- "TestStatProc1, TestStatProc2, or TestStatProc3",
- (char *) NULL);
+ Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": "
+ "must be "
+ "TestStatProc1, TestStatProc2, or TestStatProc3", NULL);
return TCL_ERROR;
}
retVal = TclStatInsertProc(proc);
} else if (strcmp(argv[1], "delete") == 0) {
retVal = TclStatDeleteProc(proc);
} else {
- Tcl_AppendResult(interp, "bad option \"", argv[1], "\": ",
- "must be insert or delete", (char *) NULL);
+ Tcl_AppendResult(interp, "bad option \"", argv[1], "\": "
+ "must be insert or delete", NULL);
return TCL_ERROR;
}
if (retVal == TCL_ERROR) {
- Tcl_AppendResult(interp, "\"", argv[2], "\": ",
- "could not be ", argv[1], "ed", (char *) NULL);
+ Tcl_AppendResult(interp, "\"", argv[2], "\": "
+ "could not be ", argv[1], "ed", NULL);
}
return retVal;
}
-static int PretendTclpStat(path, buf)
- CONST char *path;
- Tcl_StatBuf *buf;
+static int
+PretendTclpStat(
+ const char *path,
+ struct stat *buf)
{
int ret;
Tcl_Obj *pathPtr = Tcl_NewStringObj(path, -1);
@@ -4737,8 +5209,8 @@ static int PretendTclpStat(path, buf)
* Note that ino_t/ino64_t is unsigned...
*/
- if (OUT_OF_URANGE(realBuf.st_ino) || OUT_OF_RANGE(realBuf.st_size)
-# ifdef HAVE_ST_BLOCKS
+ if (OUT_OF_URANGE(realBuf.st_ino) || OUT_OF_RANGE(realBuf.st_size)
+# ifdef HAVE_STRUCT_STAT_ST_BLOCKS
|| OUT_OF_RANGE(realBuf.st_blocks)
# endif
) {
@@ -4746,9 +5218,9 @@ static int PretendTclpStat(path, buf)
errno = EOVERFLOW;
# else
# ifdef EFBIG
- errno = EFBIG;
+ errno = EFBIG;
# else
-# error "what error should be returned for a value out of range?"
+# error "what error should be returned for a value out of range?"
# endif
# endif
return -1;
@@ -4758,11 +5230,11 @@ static int PretendTclpStat(path, buf)
# undef OUT_OF_URANGE
/*
- * Copy across all supported fields, with possible type
- * coercions on those fields that change between the normal
- * and lf64 versions of the stat structure (on Solaris at
- * least.) This is slow when the structure sizes coincide,
- * but that's what you get for mixing interfaces...
+ * Copy across all supported fields, with possible type coercions on
+ * those fields that change between the normal and lf64 versions of
+ * the stat structure (on Solaris at least.) This is slow when the
+ * structure sizes coincide, but that's what you get for mixing
+ * interfaces...
*/
buf->st_mode = realBuf.st_mode;
@@ -4776,8 +5248,10 @@ static int PretendTclpStat(path, buf)
buf->st_atime = realBuf.st_atime;
buf->st_mtime = realBuf.st_mtime;
buf->st_ctime = realBuf.st_ctime;
-# ifdef HAVE_ST_BLOCKS
+# ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
buf->st_blksize = realBuf.st_blksize;
+# endif
+# ifdef HAVE_STRUCT_STAT_ST_BLOCKS
buf->st_blocks = (blkcnt_t) realBuf.st_blocks;
# endif
}
@@ -4785,42 +5259,36 @@ static int PretendTclpStat(path, buf)
#endif /* TCL_WIDE_INT_IS_LONG */
}
-/* Be careful in the compares in these tests, since the Macintosh puts a
- * leading : in the beginning of non-absolute paths before passing them
- * into the file command procedures.
- */
-
static int
-TestStatProc1(path, buf)
- CONST char *path;
- Tcl_StatBuf *buf;
+TestStatProc1(
+ const char *path,
+ struct stat *buf)
{
- memset(buf, 0, sizeof(Tcl_StatBuf));
+ memset(buf, 0, sizeof(struct stat));
buf->st_size = 1234;
return ((strstr(path, "testStat1%.fil") == NULL) ? -1 : 0);
}
-
static int
-TestStatProc2(path, buf)
- CONST char *path;
- Tcl_StatBuf *buf;
+TestStatProc2(
+ const char *path,
+ struct stat *buf)
{
- memset(buf, 0, sizeof(Tcl_StatBuf));
+ memset(buf, 0, sizeof(struct stat));
buf->st_size = 2345;
return ((strstr(path, "testStat2%.fil") == NULL) ? -1 : 0);
}
-
static int
-TestStatProc3(path, buf)
- CONST char *path;
- Tcl_StatBuf *buf;
+TestStatProc3(
+ const char *path,
+ struct stat *buf)
{
- memset(buf, 0, sizeof(Tcl_StatBuf));
+ memset(buf, 0, sizeof(struct stat));
buf->st_size = 3456;
return ((strstr(path, "testStat3%.fil") == NULL) ? -1 : 0);
}
+#endif
/*
*----------------------------------------------------------------------
@@ -4840,11 +5308,11 @@ TestStatProc3(path, buf)
*/
static int
-TestmainthreadCmd (dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- register Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestmainthreadCmd(
+ ClientData dummy, /* Not used. */
+ register Tcl_Interp *interp,/* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
if (argc == 1) {
Tcl_Obj *idObj = Tcl_NewLongObj((long)Tcl_GetCurrentThread());
@@ -4900,11 +5368,11 @@ MainLoop(void)
*/
static int
-TestsetmainloopCmd (dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- register Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestsetmainloopCmd(
+ ClientData dummy, /* Not used. */
+ register Tcl_Interp *interp,/* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
exitMainLoop = 0;
Tcl_SetMainLoop(MainLoop);
@@ -4929,15 +5397,16 @@ TestsetmainloopCmd (dummy, interp, argc, argv)
*/
static int
-TestexitmainloopCmd (dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- register Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestexitmainloopCmd(
+ ClientData dummy, /* Not used. */
+ register Tcl_Interp *interp,/* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
exitMainLoop = 1;
return TCL_OK;
}
+#ifdef USE_OBSOLETE_FS_HOOKS
/*
*----------------------------------------------------------------------
@@ -4957,18 +5426,18 @@ TestexitmainloopCmd (dummy, interp, argc, argv)
*/
static int
-TestaccessprocCmd (dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- register Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestaccessprocCmd(
+ ClientData dummy, /* Not used. */
+ register Tcl_Interp *interp,/* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
TclAccessProc_ *proc;
int retVal;
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " option arg\"", (char *) NULL);
+ argv[0], " option arg\"", NULL);
return TCL_ERROR;
}
@@ -4981,41 +5450,40 @@ TestaccessprocCmd (dummy, interp, argc, argv)
} else if (strcmp(argv[2], "TestAccessProc3") == 0) {
proc = TestAccessProc3;
} else {
- Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": ",
- "must be TclpAccess, ",
- "TestAccessProc1, TestAccessProc2, or TestAccessProc3",
- (char *) NULL);
+ Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": "
+ "must be TclpAccess, "
+ "TestAccessProc1, TestAccessProc2, or TestAccessProc3", NULL);
return TCL_ERROR;
}
if (strcmp(argv[1], "insert") == 0) {
if (proc == PretendTclpAccess) {
- Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": ",
- "must be ",
- "TestAccessProc1, TestAccessProc2, or TestAccessProc3",
- (char *) NULL);
+ Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": must be "
+ "TestAccessProc1, TestAccessProc2, or TestAccessProc3"
+ NULL);
return TCL_ERROR;
}
retVal = TclAccessInsertProc(proc);
} else if (strcmp(argv[1], "delete") == 0) {
retVal = TclAccessDeleteProc(proc);
} else {
- Tcl_AppendResult(interp, "bad option \"", argv[1], "\": ",
- "must be insert or delete", (char *) NULL);
+ Tcl_AppendResult(interp, "bad option \"", argv[1], "\": "
+ "must be insert or delete", NULL);
return TCL_ERROR;
}
if (retVal == TCL_ERROR) {
- Tcl_AppendResult(interp, "\"", argv[2], "\": ",
- "could not be ", argv[1], "ed", (char *) NULL);
+ Tcl_AppendResult(interp, "\"", argv[2], "\": "
+ "could not be ", argv[1], "ed", NULL);
}
return retVal;
}
-static int PretendTclpAccess(path, mode)
- CONST char *path;
- int mode;
+static int
+PretendTclpAccess(
+ const char *path,
+ int mode)
{
int ret;
Tcl_Obj *pathPtr = Tcl_NewStringObj(path, -1);
@@ -5026,27 +5494,25 @@ static int PretendTclpAccess(path, mode)
}
static int
-TestAccessProc1(path, mode)
- CONST char *path;
- int mode;
+TestAccessProc1(
+ const char *path,
+ int mode)
{
return ((strstr(path, "testAccess1%.fil") == NULL) ? -1 : 0);
}
-
static int
-TestAccessProc2(path, mode)
- CONST char *path;
- int mode;
+TestAccessProc2(
+ const char *path,
+ int mode)
{
return ((strstr(path, "testAccess2%.fil") == NULL) ? -1 : 0);
}
-
static int
-TestAccessProc3(path, mode)
- CONST char *path;
- int mode;
+TestAccessProc3(
+ const char *path,
+ int mode)
{
return ((strstr(path, "testAccess3%.fil") == NULL) ? -1 : 0);
}
@@ -5056,8 +5522,9 @@ TestAccessProc3(path, mode)
*
* TestopenfilechannelprocCmd --
*
- * Implements the "testTclOpenFileChannelProc" cmd that is used to test the
- * 'TclOpenFileChannelInsertProc' & 'TclOpenFileChannelDeleteProc' C Apis.
+ * Implements the "testTclOpenFileChannelProc" cmd that is used to test
+ * the 'TclOpenFileChannelInsertProc' & 'TclOpenFileChannelDeleteProc' C
+ * Apis.
*
* Results:
* A standard Tcl result.
@@ -5069,18 +5536,18 @@ TestAccessProc3(path, mode)
*/
static int
-TestopenfilechannelprocCmd (dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- register Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestopenfilechannelprocCmd(
+ ClientData dummy, /* Not used. */
+ register Tcl_Interp *interp,/* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
TclOpenFileChannelProc_ *proc;
int retVal;
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " option arg\"", (char *) NULL);
+ argv[0], " option arg\"", NULL);
return TCL_ERROR;
}
@@ -5093,50 +5560,47 @@ TestopenfilechannelprocCmd (dummy, interp, argc, argv)
} else if (strcmp(argv[2], "TestOpenFileChannelProc3") == 0) {
proc = TestOpenFileChannelProc3;
} else {
- Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": ",
- "must be TclpOpenFileChannel, ",
- "TestOpenFileChannelProc1, TestOpenFileChannelProc2, or ",
- "TestOpenFileChannelProc3",
- (char *) NULL);
+ Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": "
+ "must be TclpOpenFileChannel, "
+ "TestOpenFileChannelProc1, TestOpenFileChannelProc2, or "
+ "TestOpenFileChannelProc3", NULL);
return TCL_ERROR;
}
if (strcmp(argv[1], "insert") == 0) {
if (proc == PretendTclpOpenFileChannel) {
- Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": ",
- "must be ",
- "TestOpenFileChannelProc1, TestOpenFileChannelProc2, or ",
- "TestOpenFileChannelProc3",
- (char *) NULL);
+ Tcl_AppendResult(interp, "bad arg \"", argv[1], "\": "
+ "must be "
+ "TestOpenFileChannelProc1, TestOpenFileChannelProc2, or "
+ "TestOpenFileChannelProc3", NULL);
return TCL_ERROR;
}
retVal = TclOpenFileChannelInsertProc(proc);
} else if (strcmp(argv[1], "delete") == 0) {
retVal = TclOpenFileChannelDeleteProc(proc);
} else {
- Tcl_AppendResult(interp, "bad option \"", argv[1], "\": ",
- "must be insert or delete", (char *) NULL);
+ Tcl_AppendResult(interp, "bad option \"", argv[1], "\": "
+ "must be insert or delete", NULL);
return TCL_ERROR;
}
if (retVal == TCL_ERROR) {
- Tcl_AppendResult(interp, "\"", argv[2], "\": ",
- "could not be ", argv[1], "ed", (char *) NULL);
+ Tcl_AppendResult(interp, "\"", argv[2], "\": "
+ "could not be ", argv[1], "ed", NULL);
}
return retVal;
}
static Tcl_Channel
-PretendTclpOpenFileChannel(interp, fileName, modeString, permissions)
- Tcl_Interp *interp; /* Interpreter for error reporting;
- * can be NULL. */
- CONST char *fileName; /* Name of file to open. */
- CONST char *modeString; /* A list of POSIX open modes or
- * a string such as "rw". */
- int permissions; /* If the open involves creating a
- * file, with what modes to create
- * it? */
+PretendTclpOpenFileChannel(
+ Tcl_Interp *interp, /* Interpreter for error reporting; can be
+ * NULL. */
+ const char *fileName, /* Name of file to open. */
+ const char *modeString, /* A list of POSIX open modes or
+ * a string such as "rw". */
+ int permissions) /* If the open involves creating a file, with
+ * what modes to create it? */
{
Tcl_Channel ret;
int mode, seekFlag;
@@ -5152,11 +5616,10 @@ PretendTclpOpenFileChannel(interp, fileName, modeString, permissions)
if (ret != NULL) {
if (seekFlag) {
if (Tcl_Seek(ret, (Tcl_WideInt)0, SEEK_END) < (Tcl_WideInt)0) {
- if (interp != (Tcl_Interp *) NULL) {
+ if (interp != NULL) {
Tcl_AppendResult(interp,
- "could not seek to end of file while opening \"",
- fileName, "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ "could not seek to end of file while opening \"",
+ fileName, "\": ", Tcl_PosixError(interp), NULL);
}
Tcl_Close(NULL, ret);
return NULL;
@@ -5167,53 +5630,52 @@ PretendTclpOpenFileChannel(interp, fileName, modeString, permissions)
}
static Tcl_Channel
-TestOpenFileChannelProc1(interp, fileName, modeString, permissions)
- Tcl_Interp *interp; /* Interpreter for error reporting;
- * can be NULL. */
- CONST char *fileName; /* Name of file to open. */
- CONST char *modeString; /* A list of POSIX open modes or
- * a string such as "rw". */
- int permissions; /* If the open involves creating a
- * file, with what modes to create
- * it? */
-{
- CONST char *expectname="testOpenFileChannel1%.fil";
+TestOpenFileChannelProc1(
+ Tcl_Interp *interp, /* Interpreter for error reporting; can be
+ * NULL. */
+ const char *fileName, /* Name of file to open. */
+ const char *modeString, /* A list of POSIX open modes or
+ * a string such as "rw". */
+ int permissions) /* If the open involves creating a file, with
+ * what modes to create it? */
+{
+ const char *expectname = "testOpenFileChannel1%.fil";
Tcl_DString ds;
-
+
Tcl_DStringInit(&ds);
Tcl_JoinPath(1, &expectname, &ds);
if (!strcmp(Tcl_DStringValue(&ds), fileName)) {
Tcl_DStringFree(&ds);
- return (PretendTclpOpenFileChannel(interp, "__testOpenFileChannel1%__.fil",
+ return (PretendTclpOpenFileChannel(interp,
+ "__testOpenFileChannel1%__.fil",
modeString, permissions));
} else {
Tcl_DStringFree(&ds);
- return (NULL);
+ return NULL;
}
}
-
static Tcl_Channel
-TestOpenFileChannelProc2(interp, fileName, modeString, permissions)
- Tcl_Interp *interp; /* Interpreter for error reporting;
- * can be NULL. */
- CONST char *fileName; /* Name of file to open. */
- CONST char *modeString; /* A list of POSIX open modes or
- * a string such as "rw". */
- int permissions; /* If the open involves creating a
- * file, with what modes to create
- * it? */
-{
- CONST char *expectname="testOpenFileChannel2%.fil";
+TestOpenFileChannelProc2(
+ Tcl_Interp *interp, /* Interpreter for error reporting; can be
+ * NULL. */
+ const char *fileName, /* Name of file to open. */
+ const char *modeString, /* A list of POSIX open modes or
+ * a string such as "rw". */
+ int permissions) /* If the open involves creating a file, with
+ * what modes to create it? */
+{
+ const char *expectname = "testOpenFileChannel2%.fil";
Tcl_DString ds;
-
+
Tcl_DStringInit(&ds);
Tcl_JoinPath(1, &expectname, &ds);
if (!strcmp(Tcl_DStringValue(&ds), fileName)) {
Tcl_DStringFree(&ds);
- return (PretendTclpOpenFileChannel(interp, "__testOpenFileChannel2%__.fil",
+ return (PretendTclpOpenFileChannel(interp,
+ "__testOpenFileChannel2%__.fil",
modeString, permissions));
} else {
Tcl_DStringFree(&ds);
@@ -5221,21 +5683,19 @@ TestOpenFileChannelProc2(interp, fileName, modeString, permissions)
}
}
-
static Tcl_Channel
-TestOpenFileChannelProc3(interp, fileName, modeString, permissions)
- Tcl_Interp *interp; /* Interpreter for error reporting;
- * can be NULL. */
- CONST char *fileName; /* Name of file to open. */
- CONST char *modeString; /* A list of POSIX open modes or
- * a string such as "rw". */
- int permissions; /* If the open involves creating a
- * file, with what modes to create
- * it? */
-{
- CONST char *expectname="testOpenFileChannel3%.fil";
+TestOpenFileChannelProc3(
+ Tcl_Interp *interp, /* Interpreter for error reporting; can be
+ * NULL. */
+ const char *fileName, /* Name of file to open. */
+ const char *modeString, /* A list of POSIX open modes or a string such
+ * as "rw". */
+ int permissions) /* If the open involves creating a file, with
+ * what modes to create it? */
+{
+ const char *expectname = "testOpenFileChannel3%.fil";
Tcl_DString ds;
-
+
Tcl_DStringInit(&ds);
Tcl_JoinPath(1, &expectname, &ds);
@@ -5248,6 +5708,7 @@ TestOpenFileChannelProc3(interp, fileName, modeString, permissions)
return (NULL);
}
}
+#endif
/*
*----------------------------------------------------------------------
@@ -5268,13 +5729,13 @@ TestOpenFileChannelProc3(interp, fileName, modeString, permissions)
/* ARGSUSED */
static int
-TestChannelCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Interpreter for result. */
- int argc; /* Count of additional args. */
- CONST char **argv; /* Additional arg strings. */
+TestChannelCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter for result. */
+ int argc, /* Count of additional args. */
+ const char **argv) /* Additional arg strings. */
{
- CONST char *cmdName; /* Sub command. */
+ const char *cmdName; /* Sub command. */
Tcl_HashTable *hTblPtr; /* Hash table of channels. */
Tcl_HashSearch hSearch; /* Search variable. */
Tcl_HashEntry *hPtr; /* Search variable. */
@@ -5283,28 +5744,49 @@ TestChannelCmd(clientData, interp, argc, argv)
Tcl_Channel chan; /* The opaque type. */
size_t len; /* Length of subcommand string. */
int IOQueued; /* How much IO is queued inside channel? */
- ChannelBuffer *bufPtr; /* For iterating over queued IO. */
char buf[TCL_INTEGER_SPACE];/* For sprintf. */
int mode; /* rw mode of the channel */
-
+
if (argc < 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " subcommand ?additional args..?\"", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " subcommand ?additional args..?\"", NULL);
+ return TCL_ERROR;
}
cmdName = argv[1];
len = strlen(cmdName);
- chanPtr = (Channel *) NULL;
+ chanPtr = NULL;
if (argc > 2) {
- chan = Tcl_GetChannel(interp, argv[2], &mode);
- if (chan == (Tcl_Channel) NULL) {
- return TCL_ERROR;
- }
- chanPtr = (Channel *) chan;
+ if ((cmdName[0] == 's') && (strncmp(cmdName, "splice", len) == 0)) {
+ /* For splice access the pool of detached channels.
+ * Locate channel, remove from the list.
+ */
+
+ TestChannel **nextPtrPtr, *curPtr;
+
+ chan = (Tcl_Channel) NULL;
+ for (nextPtrPtr = &firstDetached, curPtr = firstDetached;
+ curPtr != NULL;
+ nextPtrPtr = &(curPtr->nextPtr), curPtr = curPtr->nextPtr) {
+
+ if (strcmp(argv[2], Tcl_GetChannelName(curPtr->chan)) == 0) {
+ *nextPtrPtr = curPtr->nextPtr;
+ curPtr->nextPtr = NULL;
+ chan = curPtr->chan;
+ ckfree((char *) curPtr);
+ break;
+ }
+ }
+ } else {
+ chan = Tcl_GetChannel(interp, argv[2], &mode);
+ }
+ if (chan == (Tcl_Channel) NULL) {
+ return TCL_ERROR;
+ }
+ chanPtr = (Channel *) chan;
statePtr = chanPtr->state;
- chanPtr = statePtr->topChanPtr;
+ chanPtr = statePtr->topChanPtr;
chan = (Tcl_Channel) chanPtr;
} else {
/* lint */
@@ -5312,329 +5794,350 @@ TestChannelCmd(clientData, interp, argc, argv)
chan = NULL;
}
+ if ((cmdName[0] == 's') && (strncmp(cmdName, "setchannelerror", len) == 0)) {
+
+ Tcl_Obj *msg = Tcl_NewStringObj(argv[3],-1);
+
+ Tcl_IncrRefCount(msg);
+ Tcl_SetChannelError(chan, msg);
+ Tcl_DecrRefCount(msg);
+
+ Tcl_GetChannelError(chan, &msg);
+ Tcl_SetObjResult(interp, msg);
+ Tcl_DecrRefCount(msg);
+ return TCL_OK;
+ }
+ if ((cmdName[0] == 's') && (strncmp(cmdName, "setchannelerrorinterp", len) == 0)) {
+
+ Tcl_Obj *msg = Tcl_NewStringObj(argv[3],-1);
+
+ Tcl_IncrRefCount(msg);
+ Tcl_SetChannelErrorInterp(interp, msg);
+ Tcl_DecrRefCount(msg);
+
+ Tcl_GetChannelErrorInterp(interp, &msg);
+ Tcl_SetObjResult(interp, msg);
+ Tcl_DecrRefCount(msg);
+ return TCL_OK;
+ }
+
+ /*
+ * "cut" is actually more a simplified detach facility as provided by the
+ * Thread package. Without the safeguards of a regular command (no
+ * checking that the command is truly cut'able, no mutexes for
+ * thread-safety). Its complementary command is "splice", see below.
+ */
+
if ((cmdName[0] == 'c') && (strncmp(cmdName, "cut", len) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " cut channelName\"", (char *) NULL);
- return TCL_ERROR;
- }
- Tcl_CutChannel(chan);
- return TCL_OK;
+ TestChannel *det;
+
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " cut channelName\"", NULL);
+ return TCL_ERROR;
+ }
+
+ Tcl_RegisterChannel(NULL, chan); /* prevent closing */
+ Tcl_UnregisterChannel(interp, chan);
+
+ Tcl_CutChannel(chan);
+
+ /* Remember the channel in the pool of detached channels */
+
+ det = (TestChannel *) ckalloc(sizeof(TestChannel));
+ det->chan = chan;
+ det->nextPtr = firstDetached;
+ firstDetached = det;
+
+ return TCL_OK;
}
if ((cmdName[0] == 'c') &&
(strncmp(cmdName, "clearchannelhandlers", len) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " clearchannelhandlers channelName\"", (char *) NULL);
- return TCL_ERROR;
- }
- Tcl_ClearChannelHandlers(chan);
- return TCL_OK;
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " clearchannelhandlers channelName\"", NULL);
+ return TCL_ERROR;
+ }
+ Tcl_ClearChannelHandlers(chan);
+ return TCL_OK;
}
if ((cmdName[0] == 'i') && (strncmp(cmdName, "info", len) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " info channelName\"", (char *) NULL);
- return TCL_ERROR;
- }
- Tcl_AppendElement(interp, argv[2]);
- Tcl_AppendElement(interp, Tcl_ChannelName(chanPtr->typePtr));
- if (statePtr->flags & TCL_READABLE) {
- Tcl_AppendElement(interp, "read");
- } else {
- Tcl_AppendElement(interp, "");
- }
- if (statePtr->flags & TCL_WRITABLE) {
- Tcl_AppendElement(interp, "write");
- } else {
- Tcl_AppendElement(interp, "");
- }
- if (statePtr->flags & CHANNEL_NONBLOCKING) {
- Tcl_AppendElement(interp, "nonblocking");
- } else {
- Tcl_AppendElement(interp, "blocking");
- }
- if (statePtr->flags & CHANNEL_LINEBUFFERED) {
- Tcl_AppendElement(interp, "line");
- } else if (statePtr->flags & CHANNEL_UNBUFFERED) {
- Tcl_AppendElement(interp, "none");
- } else {
- Tcl_AppendElement(interp, "full");
- }
- if (statePtr->flags & BG_FLUSH_SCHEDULED) {
- Tcl_AppendElement(interp, "async_flush");
- } else {
- Tcl_AppendElement(interp, "");
- }
- if (statePtr->flags & CHANNEL_EOF) {
- Tcl_AppendElement(interp, "eof");
- } else {
- Tcl_AppendElement(interp, "");
- }
- if (statePtr->flags & CHANNEL_BLOCKED) {
- Tcl_AppendElement(interp, "blocked");
- } else {
- Tcl_AppendElement(interp, "unblocked");
- }
- if (statePtr->inputTranslation == TCL_TRANSLATE_AUTO) {
- Tcl_AppendElement(interp, "auto");
- if (statePtr->flags & INPUT_SAW_CR) {
- Tcl_AppendElement(interp, "saw_cr");
- } else {
- Tcl_AppendElement(interp, "");
- }
- } else if (statePtr->inputTranslation == TCL_TRANSLATE_LF) {
- Tcl_AppendElement(interp, "lf");
- Tcl_AppendElement(interp, "");
- } else if (statePtr->inputTranslation == TCL_TRANSLATE_CR) {
- Tcl_AppendElement(interp, "cr");
- Tcl_AppendElement(interp, "");
- } else if (statePtr->inputTranslation == TCL_TRANSLATE_CRLF) {
- Tcl_AppendElement(interp, "crlf");
- if (statePtr->flags & INPUT_SAW_CR) {
- Tcl_AppendElement(interp, "queued_cr");
- } else {
- Tcl_AppendElement(interp, "");
- }
- }
- if (statePtr->outputTranslation == TCL_TRANSLATE_AUTO) {
- Tcl_AppendElement(interp, "auto");
- } else if (statePtr->outputTranslation == TCL_TRANSLATE_LF) {
- Tcl_AppendElement(interp, "lf");
- } else if (statePtr->outputTranslation == TCL_TRANSLATE_CR) {
- Tcl_AppendElement(interp, "cr");
- } else if (statePtr->outputTranslation == TCL_TRANSLATE_CRLF) {
- Tcl_AppendElement(interp, "crlf");
- }
- for (IOQueued = 0, bufPtr = statePtr->inQueueHead;
- bufPtr != (ChannelBuffer *) NULL;
- bufPtr = bufPtr->nextPtr) {
- IOQueued += bufPtr->nextAdded - bufPtr->nextRemoved;
- }
- TclFormatInt(buf, IOQueued);
- Tcl_AppendElement(interp, buf);
-
- IOQueued = 0;
- if (statePtr->curOutPtr != (ChannelBuffer *) NULL) {
- IOQueued = statePtr->curOutPtr->nextAdded -
- statePtr->curOutPtr->nextRemoved;
- }
- for (bufPtr = statePtr->outQueueHead;
- bufPtr != (ChannelBuffer *) NULL;
- bufPtr = bufPtr->nextPtr) {
- IOQueued += (bufPtr->nextAdded - bufPtr->nextRemoved);
- }
- TclFormatInt(buf, IOQueued);
- Tcl_AppendElement(interp, buf);
-
- TclFormatInt(buf, (int)Tcl_Tell((Tcl_Channel) chanPtr));
- Tcl_AppendElement(interp, buf);
-
- TclFormatInt(buf, statePtr->refCount);
- Tcl_AppendElement(interp, buf);
-
- return TCL_OK;
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " info channelName\"", NULL);
+ return TCL_ERROR;
+ }
+ Tcl_AppendElement(interp, argv[2]);
+ Tcl_AppendElement(interp, Tcl_ChannelName(chanPtr->typePtr));
+ if (statePtr->flags & TCL_READABLE) {
+ Tcl_AppendElement(interp, "read");
+ } else {
+ Tcl_AppendElement(interp, "");
+ }
+ if (statePtr->flags & TCL_WRITABLE) {
+ Tcl_AppendElement(interp, "write");
+ } else {
+ Tcl_AppendElement(interp, "");
+ }
+ if (statePtr->flags & CHANNEL_NONBLOCKING) {
+ Tcl_AppendElement(interp, "nonblocking");
+ } else {
+ Tcl_AppendElement(interp, "blocking");
+ }
+ if (statePtr->flags & CHANNEL_LINEBUFFERED) {
+ Tcl_AppendElement(interp, "line");
+ } else if (statePtr->flags & CHANNEL_UNBUFFERED) {
+ Tcl_AppendElement(interp, "none");
+ } else {
+ Tcl_AppendElement(interp, "full");
+ }
+ if (statePtr->flags & BG_FLUSH_SCHEDULED) {
+ Tcl_AppendElement(interp, "async_flush");
+ } else {
+ Tcl_AppendElement(interp, "");
+ }
+ if (statePtr->flags & CHANNEL_EOF) {
+ Tcl_AppendElement(interp, "eof");
+ } else {
+ Tcl_AppendElement(interp, "");
+ }
+ if (statePtr->flags & CHANNEL_BLOCKED) {
+ Tcl_AppendElement(interp, "blocked");
+ } else {
+ Tcl_AppendElement(interp, "unblocked");
+ }
+ if (statePtr->inputTranslation == TCL_TRANSLATE_AUTO) {
+ Tcl_AppendElement(interp, "auto");
+ if (statePtr->flags & INPUT_SAW_CR) {
+ Tcl_AppendElement(interp, "saw_cr");
+ } else {
+ Tcl_AppendElement(interp, "");
+ }
+ } else if (statePtr->inputTranslation == TCL_TRANSLATE_LF) {
+ Tcl_AppendElement(interp, "lf");
+ Tcl_AppendElement(interp, "");
+ } else if (statePtr->inputTranslation == TCL_TRANSLATE_CR) {
+ Tcl_AppendElement(interp, "cr");
+ Tcl_AppendElement(interp, "");
+ } else if (statePtr->inputTranslation == TCL_TRANSLATE_CRLF) {
+ Tcl_AppendElement(interp, "crlf");
+ if (statePtr->flags & INPUT_SAW_CR) {
+ Tcl_AppendElement(interp, "queued_cr");
+ } else {
+ Tcl_AppendElement(interp, "");
+ }
+ }
+ if (statePtr->outputTranslation == TCL_TRANSLATE_AUTO) {
+ Tcl_AppendElement(interp, "auto");
+ } else if (statePtr->outputTranslation == TCL_TRANSLATE_LF) {
+ Tcl_AppendElement(interp, "lf");
+ } else if (statePtr->outputTranslation == TCL_TRANSLATE_CR) {
+ Tcl_AppendElement(interp, "cr");
+ } else if (statePtr->outputTranslation == TCL_TRANSLATE_CRLF) {
+ Tcl_AppendElement(interp, "crlf");
+ }
+ IOQueued = Tcl_InputBuffered(chan);
+ TclFormatInt(buf, IOQueued);
+ Tcl_AppendElement(interp, buf);
+
+ IOQueued = Tcl_OutputBuffered(chan);
+ TclFormatInt(buf, IOQueued);
+ Tcl_AppendElement(interp, buf);
+
+ TclFormatInt(buf, (int)Tcl_Tell(chan));
+ Tcl_AppendElement(interp, buf);
+
+ TclFormatInt(buf, statePtr->refCount);
+ Tcl_AppendElement(interp, buf);
+
+ return TCL_OK;
}
if ((cmdName[0] == 'i') &&
- (strncmp(cmdName, "inputbuffered", len) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "channel name required",
- (char *) NULL);
- return TCL_ERROR;
- }
-
- for (IOQueued = 0, bufPtr = statePtr->inQueueHead;
- bufPtr != (ChannelBuffer *) NULL;
- bufPtr = bufPtr->nextPtr) {
- IOQueued += bufPtr->nextAdded - bufPtr->nextRemoved;
- }
- TclFormatInt(buf, IOQueued);
- Tcl_AppendResult(interp, buf, (char *) NULL);
- return TCL_OK;
+ (strncmp(cmdName, "inputbuffered", len) == 0)) {
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "channel name required", NULL);
+ return TCL_ERROR;
+ }
+ IOQueued = Tcl_InputBuffered(chan);
+ TclFormatInt(buf, IOQueued);
+ Tcl_AppendResult(interp, buf, NULL);
+ return TCL_OK;
}
if ((cmdName[0] == 'i') && (strncmp(cmdName, "isshared", len) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "channel name required", (char *) NULL);
- return TCL_ERROR;
- }
-
- TclFormatInt(buf, Tcl_IsChannelShared(chan));
- Tcl_AppendResult(interp, buf, (char *) NULL);
- return TCL_OK;
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "channel name required", NULL);
+ return TCL_ERROR;
+ }
+
+ TclFormatInt(buf, Tcl_IsChannelShared(chan));
+ Tcl_AppendResult(interp, buf, NULL);
+ return TCL_OK;
}
if ((cmdName[0] == 'i') && (strncmp(cmdName, "isstandard", len) == 0)) {
if (argc != 3) {
- Tcl_AppendResult(interp, "channel name required", (char *) NULL);
+ Tcl_AppendResult(interp, "channel name required", NULL);
return TCL_ERROR;
}
-
+
TclFormatInt(buf, Tcl_IsStandardChannel(chan));
- Tcl_AppendResult(interp, buf, (char *) NULL);
+ Tcl_AppendResult(interp, buf, NULL);
return TCL_OK;
}
if ((cmdName[0] == 'm') && (strncmp(cmdName, "mode", len) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "channel name required",
- (char *) NULL);
- return TCL_ERROR;
- }
-
- if (statePtr->flags & TCL_READABLE) {
- Tcl_AppendElement(interp, "read");
- } else {
- Tcl_AppendElement(interp, "");
- }
- if (statePtr->flags & TCL_WRITABLE) {
- Tcl_AppendElement(interp, "write");
- } else {
- Tcl_AppendElement(interp, "");
- }
- return TCL_OK;
- }
-
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "channel name required", NULL);
+ return TCL_ERROR;
+ }
+
+ if (statePtr->flags & TCL_READABLE) {
+ Tcl_AppendElement(interp, "read");
+ } else {
+ Tcl_AppendElement(interp, "");
+ }
+ if (statePtr->flags & TCL_WRITABLE) {
+ Tcl_AppendElement(interp, "write");
+ } else {
+ Tcl_AppendElement(interp, "");
+ }
+ return TCL_OK;
+ }
+
if ((cmdName[0] == 'm') && (strncmp(cmdName, "mthread", len) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "channel name required",
- (char *) NULL);
- return TCL_ERROR;
- }
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "channel name required", NULL);
+ return TCL_ERROR;
+ }
- TclFormatInt(buf, (long) Tcl_GetChannelThread(chan));
- Tcl_AppendResult(interp, buf, (char *) NULL);
- return TCL_OK;
+ TclFormatInt(buf, (long) Tcl_GetChannelThread(chan));
+ Tcl_AppendResult(interp, buf, NULL);
+ return TCL_OK;
}
if ((cmdName[0] == 'n') && (strncmp(cmdName, "name", len) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "channel name required",
- (char *) NULL);
- return TCL_ERROR;
- }
- Tcl_AppendResult(interp, statePtr->channelName, (char *) NULL);
- return TCL_OK;
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "channel name required", NULL);
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult(interp, statePtr->channelName, NULL);
+ return TCL_OK;
}
if ((cmdName[0] == 'o') && (strncmp(cmdName, "open", len) == 0)) {
- hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL);
- if (hTblPtr == (Tcl_HashTable *) NULL) {
- return TCL_OK;
- }
- for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
- hPtr != (Tcl_HashEntry *) NULL;
+ hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL);
+ if (hTblPtr == NULL) {
+ return TCL_OK;
+ }
+ for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
+ hPtr != NULL;
hPtr = Tcl_NextHashEntry(&hSearch)) {
- Tcl_AppendElement(interp, Tcl_GetHashKey(hTblPtr, hPtr));
- }
- return TCL_OK;
+ Tcl_AppendElement(interp, Tcl_GetHashKey(hTblPtr, hPtr));
+ }
+ return TCL_OK;
}
if ((cmdName[0] == 'o') &&
- (strncmp(cmdName, "outputbuffered", len) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "channel name required",
- (char *) NULL);
- return TCL_ERROR;
- }
-
- IOQueued = 0;
- if (statePtr->curOutPtr != (ChannelBuffer *) NULL) {
- IOQueued = statePtr->curOutPtr->nextAdded -
- statePtr->curOutPtr->nextRemoved;
- }
- for (bufPtr = statePtr->outQueueHead;
- bufPtr != (ChannelBuffer *) NULL;
- bufPtr = bufPtr->nextPtr) {
- IOQueued += (bufPtr->nextAdded - bufPtr->nextRemoved);
- }
- TclFormatInt(buf, IOQueued);
- Tcl_AppendResult(interp, buf, (char *) NULL);
- return TCL_OK;
+ (strncmp(cmdName, "outputbuffered", len) == 0)) {
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "channel name required", NULL);
+ return TCL_ERROR;
+ }
+
+ IOQueued = Tcl_OutputBuffered(chan);
+ TclFormatInt(buf, IOQueued);
+ Tcl_AppendResult(interp, buf, NULL);
+ return TCL_OK;
}
if ((cmdName[0] == 'q') &&
- (strncmp(cmdName, "queuedcr", len) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "channel name required",
- (char *) NULL);
- return TCL_ERROR;
- }
+ (strncmp(cmdName, "queuedcr", len) == 0)) {
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "channel name required", NULL);
+ return TCL_ERROR;
+ }
- Tcl_AppendResult(interp,
- (statePtr->flags & INPUT_SAW_CR) ? "1" : "0",
- (char *) NULL);
- return TCL_OK;
+ Tcl_AppendResult(interp,
+ (statePtr->flags & INPUT_SAW_CR) ? "1" : "0", NULL);
+ return TCL_OK;
}
if ((cmdName[0] == 'r') && (strncmp(cmdName, "readable", len) == 0)) {
- hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL);
- if (hTblPtr == (Tcl_HashTable *) NULL) {
- return TCL_OK;
- }
- for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
- hPtr != (Tcl_HashEntry *) NULL;
+ hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL);
+ if (hTblPtr == NULL) {
+ return TCL_OK;
+ }
+ for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
+ hPtr != NULL;
hPtr = Tcl_NextHashEntry(&hSearch)) {
- chanPtr = (Channel *) Tcl_GetHashValue(hPtr);
+ chanPtr = (Channel *) Tcl_GetHashValue(hPtr);
statePtr = chanPtr->state;
- if (statePtr->flags & TCL_READABLE) {
- Tcl_AppendElement(interp, Tcl_GetHashKey(hTblPtr, hPtr));
- }
- }
- return TCL_OK;
+ if (statePtr->flags & TCL_READABLE) {
+ Tcl_AppendElement(interp, Tcl_GetHashKey(hTblPtr, hPtr));
+ }
+ }
+ return TCL_OK;
}
if ((cmdName[0] == 'r') && (strncmp(cmdName, "refcount", len) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "channel name required",
- (char *) NULL);
- return TCL_ERROR;
- }
-
- TclFormatInt(buf, statePtr->refCount);
- Tcl_AppendResult(interp, buf, (char *) NULL);
- return TCL_OK;
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "channel name required", NULL);
+ return TCL_ERROR;
+ }
+
+ TclFormatInt(buf, statePtr->refCount);
+ Tcl_AppendResult(interp, buf, NULL);
+ return TCL_OK;
}
+ /*
+ * "splice" is actually more a simplified attach facility as provided by
+ * the Thread package. Without the safeguards of a regular command (no
+ * checking that the command is truly cut'able, no mutexes for
+ * thread-safety). Its complementary command is "cut", see above.
+ */
+
if ((cmdName[0] == 's') && (strncmp(cmdName, "splice", len) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "channel name required", (char *) NULL);
- return TCL_ERROR;
- }
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "channel name required", NULL);
+ return TCL_ERROR;
+ }
+
+ Tcl_SpliceChannel(chan);
+
+ Tcl_RegisterChannel(interp, chan);
+ Tcl_UnregisterChannel(NULL, chan);
- Tcl_SpliceChannel(chan);
- return TCL_OK;
+ return TCL_OK;
}
if ((cmdName[0] == 't') && (strncmp(cmdName, "type", len) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "channel name required",
- (char *) NULL);
- return TCL_ERROR;
- }
- Tcl_AppendResult(interp, Tcl_ChannelName(chanPtr->typePtr),
- (char *) NULL);
- return TCL_OK;
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "channel name required", NULL);
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult(interp, Tcl_ChannelName(chanPtr->typePtr), NULL);
+ return TCL_OK;
}
if ((cmdName[0] == 'w') && (strncmp(cmdName, "writable", len) == 0)) {
- hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL);
- if (hTblPtr == (Tcl_HashTable *) NULL) {
- return TCL_OK;
- }
- for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
- hPtr != (Tcl_HashEntry *) NULL;
- hPtr = Tcl_NextHashEntry(&hSearch)) {
- chanPtr = (Channel *) Tcl_GetHashValue(hPtr);
+ hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL);
+ if (hTblPtr == NULL) {
+ return TCL_OK;
+ }
+ for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) {
+ chanPtr = (Channel *) Tcl_GetHashValue(hPtr);
statePtr = chanPtr->state;
- if (statePtr->flags & TCL_WRITABLE) {
- Tcl_AppendElement(interp, Tcl_GetHashKey(hTblPtr, hPtr));
- }
- }
- return TCL_OK;
+ if (statePtr->flags & TCL_WRITABLE) {
+ Tcl_AppendElement(interp, Tcl_GetHashKey(hTblPtr, hPtr));
+ }
+ }
+ return TCL_OK;
}
if ((cmdName[0] == 't') && (strncmp(cmdName, "transform", len) == 0)) {
@@ -5642,14 +6145,14 @@ TestChannelCmd(clientData, interp, argc, argv)
* Syntax: transform channel -command command
*/
- if (argc != 5) {
+ if (argc != 5) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " transform channelId -command cmd\"", (char *) NULL);
- return TCL_ERROR;
- }
+ " transform channelId -command cmd\"", NULL);
+ return TCL_ERROR;
+ }
if (strcmp(argv[3], "-command") != 0) {
Tcl_AppendResult(interp, "bad argument \"", argv[3],
- "\": should be \"-command\"", (char *) NULL);
+ "\": should be \"-command\"", NULL);
return TCL_ERROR;
}
@@ -5662,18 +6165,17 @@ TestChannelCmd(clientData, interp, argc, argv)
* Syntax: unstack channel
*/
- if (argc != 3) {
+ if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " unstack channel\"", (char *) NULL);
- return TCL_ERROR;
- }
+ " unstack channel\"", NULL);
+ return TCL_ERROR;
+ }
return Tcl_UnstackChannel(interp, chan);
}
- Tcl_AppendResult(interp, "bad option \"", cmdName, "\": should be ",
- "cut, clearchannelhandlers, info, isshared, mode, open, "
- "readable, splice, writable, transform, unstack",
- (char *) NULL);
+ Tcl_AppendResult(interp, "bad option \"", cmdName, "\": should be "
+ "cut, clearchannelhandlers, info, isshared, mode, open, "
+ "readable, splice, writable, transform, unstack", NULL);
return TCL_ERROR;
}
@@ -5682,8 +6184,8 @@ TestChannelCmd(clientData, interp, argc, argv)
*
* TestChannelEventCmd --
*
- * This procedure implements the "testchannelevent" command. It is
- * used to test the Tcl channel event mechanism.
+ * This procedure implements the "testchannelevent" command. It is used
+ * to test the Tcl channel event mechanism.
*
* Results:
* A standard Tcl result.
@@ -5696,198 +6198,198 @@ TestChannelCmd(clientData, interp, argc, argv)
/* ARGSUSED */
static int
-TestChannelEventCmd(dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestChannelEventCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
{
Tcl_Obj *resultListPtr;
Channel *chanPtr;
ChannelState *statePtr; /* state info for channel */
EventScriptRecord *esPtr, *prevEsPtr, *nextEsPtr;
- CONST char *cmd;
+ const char *cmd;
int index, i, mask, len;
if ((argc < 3) || (argc > 5)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " channelName cmd ?arg1? ?arg2?\"", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " channelName cmd ?arg1? ?arg2?\"", NULL);
+ return TCL_ERROR;
}
chanPtr = (Channel *) Tcl_GetChannel(interp, argv[1], NULL);
- if (chanPtr == (Channel *) NULL) {
- return TCL_ERROR;
+ if (chanPtr == NULL) {
+ return TCL_ERROR;
}
statePtr = chanPtr->state;
cmd = argv[2];
len = strlen(cmd);
if ((cmd[0] == 'a') && (strncmp(cmd, "add", (unsigned) len) == 0)) {
- if (argc != 5) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " channelName add eventSpec script\"", (char *) NULL);
- return TCL_ERROR;
- }
- if (strcmp(argv[3], "readable") == 0) {
- mask = TCL_READABLE;
- } else if (strcmp(argv[3], "writable") == 0) {
- mask = TCL_WRITABLE;
- } else if (strcmp(argv[3], "none") == 0) {
- mask = 0;
+ if (argc != 5) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " channelName add eventSpec script\"", NULL);
+ return TCL_ERROR;
+ }
+ if (strcmp(argv[3], "readable") == 0) {
+ mask = TCL_READABLE;
+ } else if (strcmp(argv[3], "writable") == 0) {
+ mask = TCL_WRITABLE;
+ } else if (strcmp(argv[3], "none") == 0) {
+ mask = 0;
} else {
- Tcl_AppendResult(interp, "bad event name \"", argv[3],
- "\": must be readable, writable, or none", (char *) NULL);
- return TCL_ERROR;
- }
-
- esPtr = (EventScriptRecord *) ckalloc((unsigned)
- sizeof(EventScriptRecord));
- esPtr->nextPtr = statePtr->scriptRecordPtr;
- statePtr->scriptRecordPtr = esPtr;
-
- esPtr->chanPtr = chanPtr;
- esPtr->interp = interp;
- esPtr->mask = mask;
+ Tcl_AppendResult(interp, "bad event name \"", argv[3],
+ "\": must be readable, writable, or none", NULL);
+ return TCL_ERROR;
+ }
+
+ esPtr = (EventScriptRecord *) ckalloc((unsigned)
+ sizeof(EventScriptRecord));
+ esPtr->nextPtr = statePtr->scriptRecordPtr;
+ statePtr->scriptRecordPtr = esPtr;
+
+ esPtr->chanPtr = chanPtr;
+ esPtr->interp = interp;
+ esPtr->mask = mask;
esPtr->scriptPtr = Tcl_NewStringObj(argv[4], -1);
Tcl_IncrRefCount(esPtr->scriptPtr);
- Tcl_CreateChannelHandler((Tcl_Channel) chanPtr, mask,
- TclChannelEventScriptInvoker, (ClientData) esPtr);
-
- return TCL_OK;
+ Tcl_CreateChannelHandler((Tcl_Channel) chanPtr, mask,
+ TclChannelEventScriptInvoker, (ClientData) esPtr);
+
+ return TCL_OK;
}
if ((cmd[0] == 'd') && (strncmp(cmd, "delete", (unsigned) len) == 0)) {
- if (argc != 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " channelName delete index\"", (char *) NULL);
- return TCL_ERROR;
- }
- if (Tcl_GetInt(interp, argv[3], &index) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (index < 0) {
- Tcl_AppendResult(interp, "bad event index: ", argv[3],
- ": must be nonnegative", (char *) NULL);
- return TCL_ERROR;
- }
- for (i = 0, esPtr = statePtr->scriptRecordPtr;
- (i < index) && (esPtr != (EventScriptRecord *) NULL);
+ if (argc != 4) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " channelName delete index\"", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetInt(interp, argv[3], &index) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ if (index < 0) {
+ Tcl_AppendResult(interp, "bad event index: ", argv[3],
+ ": must be nonnegative", NULL);
+ return TCL_ERROR;
+ }
+ for (i = 0, esPtr = statePtr->scriptRecordPtr;
+ (i < index) && (esPtr != NULL);
i++, esPtr = esPtr->nextPtr) {
/* Empty loop body. */
- }
- if (esPtr == (EventScriptRecord *) NULL) {
- Tcl_AppendResult(interp, "bad event index ", argv[3],
- ": out of range", (char *) NULL);
- return TCL_ERROR;
- }
- if (esPtr == statePtr->scriptRecordPtr) {
- statePtr->scriptRecordPtr = esPtr->nextPtr;
- } else {
- for (prevEsPtr = statePtr->scriptRecordPtr;
- (prevEsPtr != (EventScriptRecord *) NULL) &&
+ }
+ if (esPtr == NULL) {
+ Tcl_AppendResult(interp, "bad event index ", argv[3],
+ ": out of range", NULL);
+ return TCL_ERROR;
+ }
+ if (esPtr == statePtr->scriptRecordPtr) {
+ statePtr->scriptRecordPtr = esPtr->nextPtr;
+ } else {
+ for (prevEsPtr = statePtr->scriptRecordPtr;
+ (prevEsPtr != NULL) &&
(prevEsPtr->nextPtr != esPtr);
prevEsPtr = prevEsPtr->nextPtr) {
- /* Empty loop body. */
- }
- if (prevEsPtr == (EventScriptRecord *) NULL) {
- panic("TestChannelEventCmd: damaged event script list");
- }
- prevEsPtr->nextPtr = esPtr->nextPtr;
- }
- Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr,
- TclChannelEventScriptInvoker, (ClientData) esPtr);
+ /* Empty loop body. */
+ }
+ if (prevEsPtr == NULL) {
+ Tcl_Panic("TestChannelEventCmd: damaged event script list");
+ }
+ prevEsPtr->nextPtr = esPtr->nextPtr;
+ }
+ Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr,
+ TclChannelEventScriptInvoker, (ClientData) esPtr);
Tcl_DecrRefCount(esPtr->scriptPtr);
- ckfree((char *) esPtr);
+ ckfree((char *) esPtr);
- return TCL_OK;
+ return TCL_OK;
}
if ((cmd[0] == 'l') && (strncmp(cmd, "list", (unsigned) len) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " channelName list\"", (char *) NULL);
- return TCL_ERROR;
- }
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " channelName list\"", NULL);
+ return TCL_ERROR;
+ }
resultListPtr = Tcl_GetObjResult(interp);
- for (esPtr = statePtr->scriptRecordPtr;
- esPtr != (EventScriptRecord *) NULL;
+ for (esPtr = statePtr->scriptRecordPtr;
+ esPtr != NULL;
esPtr = esPtr->nextPtr) {
if (esPtr->mask) {
- Tcl_ListObjAppendElement(interp, resultListPtr, Tcl_NewStringObj(
+ Tcl_ListObjAppendElement(interp, resultListPtr, Tcl_NewStringObj(
(esPtr->mask == TCL_READABLE) ? "readable" : "writable", -1));
- } else {
- Tcl_ListObjAppendElement(interp, resultListPtr,
+ } else {
+ Tcl_ListObjAppendElement(interp, resultListPtr,
Tcl_NewStringObj("none", -1));
}
- Tcl_ListObjAppendElement(interp, resultListPtr, esPtr->scriptPtr);
- }
+ Tcl_ListObjAppendElement(interp, resultListPtr, esPtr->scriptPtr);
+ }
Tcl_SetObjResult(interp, resultListPtr);
- return TCL_OK;
+ return TCL_OK;
}
if ((cmd[0] == 'r') && (strncmp(cmd, "removeall", (unsigned) len) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " channelName removeall\"", (char *) NULL);
- return TCL_ERROR;
- }
- for (esPtr = statePtr->scriptRecordPtr;
- esPtr != (EventScriptRecord *) NULL;
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " channelName removeall\"", NULL);
+ return TCL_ERROR;
+ }
+ for (esPtr = statePtr->scriptRecordPtr;
+ esPtr != NULL;
esPtr = nextEsPtr) {
- nextEsPtr = esPtr->nextPtr;
- Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr,
- TclChannelEventScriptInvoker, (ClientData) esPtr);
+ nextEsPtr = esPtr->nextPtr;
+ Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr,
+ TclChannelEventScriptInvoker, (ClientData) esPtr);
Tcl_DecrRefCount(esPtr->scriptPtr);
- ckfree((char *) esPtr);
- }
- statePtr->scriptRecordPtr = (EventScriptRecord *) NULL;
- return TCL_OK;
- }
-
- if ((cmd[0] == 's') && (strncmp(cmd, "set", (unsigned) len) == 0)) {
- if (argc != 5) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " channelName delete index event\"", (char *) NULL);
- return TCL_ERROR;
- }
- if (Tcl_GetInt(interp, argv[3], &index) == TCL_ERROR) {
- return TCL_ERROR;
- }
- if (index < 0) {
- Tcl_AppendResult(interp, "bad event index: ", argv[3],
- ": must be nonnegative", (char *) NULL);
- return TCL_ERROR;
- }
- for (i = 0, esPtr = statePtr->scriptRecordPtr;
- (i < index) && (esPtr != (EventScriptRecord *) NULL);
+ ckfree((char *) esPtr);
+ }
+ statePtr->scriptRecordPtr = NULL;
+ return TCL_OK;
+ }
+
+ if ((cmd[0] == 's') && (strncmp(cmd, "set", (unsigned) len) == 0)) {
+ if (argc != 5) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " channelName delete index event\"", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetInt(interp, argv[3], &index) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ if (index < 0) {
+ Tcl_AppendResult(interp, "bad event index: ", argv[3],
+ ": must be nonnegative", NULL);
+ return TCL_ERROR;
+ }
+ for (i = 0, esPtr = statePtr->scriptRecordPtr;
+ (i < index) && (esPtr != NULL);
i++, esPtr = esPtr->nextPtr) {
/* Empty loop body. */
- }
- if (esPtr == (EventScriptRecord *) NULL) {
- Tcl_AppendResult(interp, "bad event index ", argv[3],
- ": out of range", (char *) NULL);
- return TCL_ERROR;
- }
-
- if (strcmp(argv[4], "readable") == 0) {
- mask = TCL_READABLE;
- } else if (strcmp(argv[4], "writable") == 0) {
- mask = TCL_WRITABLE;
- } else if (strcmp(argv[4], "none") == 0) {
- mask = 0;
+ }
+ if (esPtr == NULL) {
+ Tcl_AppendResult(interp, "bad event index ", argv[3],
+ ": out of range", NULL);
+ return TCL_ERROR;
+ }
+
+ if (strcmp(argv[4], "readable") == 0) {
+ mask = TCL_READABLE;
+ } else if (strcmp(argv[4], "writable") == 0) {
+ mask = TCL_WRITABLE;
+ } else if (strcmp(argv[4], "none") == 0) {
+ mask = 0;
} else {
- Tcl_AppendResult(interp, "bad event name \"", argv[4],
- "\": must be readable, writable, or none", (char *) NULL);
- return TCL_ERROR;
- }
+ Tcl_AppendResult(interp, "bad event name \"", argv[4],
+ "\": must be readable, writable, or none", NULL);
+ return TCL_ERROR;
+ }
esPtr->mask = mask;
- Tcl_CreateChannelHandler((Tcl_Channel) chanPtr, mask,
- TclChannelEventScriptInvoker, (ClientData) esPtr);
+ Tcl_CreateChannelHandler((Tcl_Channel) chanPtr, mask,
+ TclChannelEventScriptInvoker, (ClientData) esPtr);
return TCL_OK;
- }
- Tcl_AppendResult(interp, "bad command ", cmd, ", must be one of ",
- "add, delete, list, set, or removeall", (char *) NULL);
+ }
+ Tcl_AppendResult(interp, "bad command ", cmd, ", must be one of "
+ "add, delete, list, set, or removeall", NULL);
return TCL_ERROR;
}
@@ -5908,11 +6410,11 @@ TestChannelEventCmd(dummy, interp, argc, argv)
*/
static int
-TestWrongNumArgsObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+TestWrongNumArgsObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
int i, length;
char *msg;
@@ -5925,7 +6427,7 @@ TestWrongNumArgsObjCmd(dummy, interp, objc, objv)
Tcl_SetResult(interp, "insufficient arguments", TCL_STATIC);
return TCL_ERROR;
}
-
+
if (Tcl_GetIntFromObj(interp, objv[1], &i) != TCL_OK) {
return TCL_ERROR;
}
@@ -5934,7 +6436,7 @@ TestWrongNumArgsObjCmd(dummy, interp, objc, objv)
if (length == 0) {
msg = NULL;
}
-
+
if (i > objc - 3) {
/*
* Asked for more arguments than were given.
@@ -5964,14 +6466,14 @@ TestWrongNumArgsObjCmd(dummy, interp, objc, objv)
*/
static int
-TestGetIndexFromObjStructObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+TestGetIndexFromObjStructObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
char *ary[] = {
- "a", "b", "c", "d", "e", "f", (char *)NULL,(char *)NULL
+ "a", "b", "c", "d", "e", "f", NULL, NULL
};
int idx,target;
@@ -5980,7 +6482,7 @@ TestGetIndexFromObjStructObjCmd(dummy, interp, objc, objv)
return TCL_ERROR;
}
if (Tcl_GetIndexFromObjStruct(interp, objv[1], ary, 2*sizeof(char *),
- "dummy", 0, &idx) != TCL_OK) {
+ "dummy", 0, &idx) != TCL_OK) {
return TCL_ERROR;
}
if (Tcl_GetIntFromObj(interp, objv[2], &target) != TCL_OK) {
@@ -5990,7 +6492,7 @@ TestGetIndexFromObjStructObjCmd(dummy, interp, objc, objv)
char buffer[64];
sprintf(buffer, "%d", idx);
Tcl_AppendResult(interp, "index value comparison failed: got ",
- buffer, NULL);
+ buffer, NULL);
sprintf(buffer, "%d", target);
Tcl_AppendResult(interp, " when ", buffer, " expected", NULL);
return TCL_ERROR;
@@ -6004,9 +6506,9 @@ TestGetIndexFromObjStructObjCmd(dummy, interp, objc, objv)
*
* TestFilesystemObjCmd --
*
- * This procedure implements the "testfilesystem" command. It is
- * used to test Tcl_FSRegister, Tcl_FSUnregister, and can be used
- * to test that the pluggable filesystem works.
+ * This procedure implements the "testfilesystem" command. It is used to
+ * test Tcl_FSRegister, Tcl_FSUnregister, and can be used to test that
+ * the pluggable filesystem works.
*
* Results:
* A standard Tcl result.
@@ -6018,15 +6520,15 @@ TestGetIndexFromObjStructObjCmd(dummy, interp, objc, objv)
*/
static int
-TestFilesystemObjCmd(dummy, interp, objc, objv)
- ClientData dummy;
- Tcl_Interp *interp;
- int objc;
- Tcl_Obj *CONST objv[];
+TestFilesystemObjCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const objv[])
{
int res, boolVal;
char *msg;
-
+
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "boolean");
return TCL_ERROR;
@@ -6045,78 +6547,90 @@ TestFilesystemObjCmd(dummy, interp, objc, objv)
return res;
}
-static int
-TestReportInFilesystem(Tcl_Obj *pathPtr, ClientData *clientDataPtr)
+static int
+TestReportInFilesystem(
+ Tcl_Obj *pathPtr,
+ ClientData *clientDataPtr)
{
- static Tcl_Obj* lastPathPtr = NULL;
-
+ static Tcl_Obj *lastPathPtr = NULL;
+ Tcl_Obj *newPathPtr;
+
if (pathPtr == lastPathPtr) {
/* Reject all files second time around */
- return -1;
- } else {
- Tcl_Obj * newPathPtr;
- /* Try to claim all files first time around */
-
- newPathPtr = Tcl_DuplicateObj(pathPtr);
- lastPathPtr = newPathPtr;
- Tcl_IncrRefCount(newPathPtr);
- if (Tcl_FSGetFileSystemForPath(newPathPtr) == NULL) {
- /* Nothing claimed it. Therefore we don't either */
- Tcl_DecrRefCount(newPathPtr);
- lastPathPtr = NULL;
- return -1;
- } else {
- lastPathPtr = NULL;
- *clientDataPtr = (ClientData) newPathPtr;
- return TCL_OK;
- }
+ return -1;
}
+
+ /* Try to claim all files first time around */
+
+ newPathPtr = Tcl_DuplicateObj(pathPtr);
+ lastPathPtr = newPathPtr;
+ Tcl_IncrRefCount(newPathPtr);
+ if (Tcl_FSGetFileSystemForPath(newPathPtr) == NULL) {
+ /* Nothing claimed it. Therefore we don't either */
+ Tcl_DecrRefCount(newPathPtr);
+ lastPathPtr = NULL;
+ return -1;
+ }
+ lastPathPtr = NULL;
+ *clientDataPtr = (ClientData) newPathPtr;
+ return TCL_OK;
}
-/*
- * Simple helper function to extract the native vfs representation of a
- * path object, or NULL if no such representation exists.
+/*
+ * Simple helper function to extract the native vfs representation of a path
+ * object, or NULL if no such representation exists.
*/
-static Tcl_Obj*
-TestReportGetNativePath(Tcl_Obj* pathObjPtr) {
- return (Tcl_Obj*) Tcl_FSGetInternalRep(pathObjPtr, &testReportingFilesystem);
+
+static Tcl_Obj *
+TestReportGetNativePath(
+ Tcl_Obj *pathPtr)
+{
+ return (Tcl_Obj*) Tcl_FSGetInternalRep(pathPtr, &testReportingFilesystem);
}
-static void
-TestReportFreeInternalRep(ClientData clientData) {
- Tcl_Obj *nativeRep = (Tcl_Obj*)clientData;
+static void
+TestReportFreeInternalRep(
+ ClientData clientData)
+{
+ Tcl_Obj *nativeRep = (Tcl_Obj *) clientData;
+
if (nativeRep != NULL) {
/* Free the path */
Tcl_DecrRefCount(nativeRep);
}
}
-static ClientData
-TestReportDupInternalRep(ClientData clientData) {
- Tcl_Obj *original = (Tcl_Obj*)clientData;
+static ClientData
+TestReportDupInternalRep(
+ ClientData clientData)
+{
+ Tcl_Obj *original = (Tcl_Obj *) clientData;
+
Tcl_IncrRefCount(original);
return clientData;
}
static void
-TestReport(cmd, path, arg2)
- CONST char* cmd;
- Tcl_Obj* path;
- Tcl_Obj* arg2;
+TestReport(
+ const char *cmd,
+ Tcl_Obj *path,
+ Tcl_Obj *arg2)
{
- Tcl_Interp* interp = (Tcl_Interp*) Tcl_FSData(&testReportingFilesystem);
+ Tcl_Interp *interp = (Tcl_Interp *) Tcl_FSData(&testReportingFilesystem);
+
if (interp == NULL) {
/* This is bad, but not much we can do about it */
} else {
- /*
- * No idea why I decided to program this up using the
- * old string-based API, but there you go. We should
- * convert it to objects.
+ /*
+ * No idea why I decided to program this up using the old string-based
+ * API, but there you go. We should convert it to objects.
*/
+
Tcl_SavedResult savedResult;
Tcl_DString ds;
+
Tcl_DStringInit(&ds);
- Tcl_DStringAppend(&ds, "lappend filesystemReport ",-1);
+ Tcl_DStringAppend(&ds, "lappend filesystemReport ", -1);
Tcl_DStringStartSublist(&ds);
Tcl_DStringAppendElement(&ds, cmd);
if (path != NULL) {
@@ -6134,254 +6648,259 @@ TestReport(cmd, path, arg2)
}
static int
-TestReportStat(path, buf)
- Tcl_Obj *path; /* Path of file to stat (in current CP). */
- Tcl_StatBuf *buf; /* Filled with results of stat call. */
+TestReportStat(
+ Tcl_Obj *path, /* Path of file to stat (in current CP). */
+ Tcl_StatBuf *buf) /* Filled with results of stat call. */
{
- TestReport("stat",path, NULL);
- return Tcl_FSStat(TestReportGetNativePath(path),buf);
+ TestReport("stat", path, NULL);
+ return Tcl_FSStat(TestReportGetNativePath(path), buf);
}
+
static int
-TestReportLstat(path, buf)
- Tcl_Obj *path; /* Path of file to stat (in current CP). */
- Tcl_StatBuf *buf; /* Filled with results of stat call. */
+TestReportLstat(
+ Tcl_Obj *path, /* Path of file to stat (in current CP). */
+ Tcl_StatBuf *buf) /* Filled with results of stat call. */
{
- TestReport("lstat",path, NULL);
- return Tcl_FSLstat(TestReportGetNativePath(path),buf);
+ TestReport("lstat", path, NULL);
+ return Tcl_FSLstat(TestReportGetNativePath(path), buf);
}
+
static int
-TestReportAccess(path, mode)
- Tcl_Obj *path; /* Path of file to access (in current CP). */
- int mode; /* Permission setting. */
+TestReportAccess(
+ Tcl_Obj *path, /* Path of file to access (in current CP). */
+ int mode) /* Permission setting. */
{
- TestReport("access",path,NULL);
- return Tcl_FSAccess(TestReportGetNativePath(path),mode);
+ TestReport("access", path, NULL);
+ return Tcl_FSAccess(TestReportGetNativePath(path), mode);
}
+
static Tcl_Channel
-TestReportOpenFileChannel(interp, fileName, mode, permissions)
- Tcl_Interp *interp; /* Interpreter for error reporting;
- * can be NULL. */
- Tcl_Obj *fileName; /* Name of file to open. */
- int mode; /* POSIX open mode. */
- int permissions; /* If the open involves creating a
- * file, with what modes to create
- * it? */
-{
- TestReport("open",fileName, NULL);
+TestReportOpenFileChannel(
+ Tcl_Interp *interp, /* Interpreter for error reporting; can be
+ * NULL. */
+ Tcl_Obj *fileName, /* Name of file to open. */
+ int mode, /* POSIX open mode. */
+ int permissions) /* If the open involves creating a file, with
+ * what modes to create it? */
+{
+ TestReport("open", fileName, NULL);
return TclpOpenFileChannel(interp, TestReportGetNativePath(fileName),
- mode, permissions);
+ mode, permissions);
}
static int
-TestReportMatchInDirectory(interp, resultPtr, dirPtr, pattern, types)
- Tcl_Interp *interp; /* Interpreter to receive results. */
- Tcl_Obj *resultPtr; /* Object to lappend results. */
- Tcl_Obj *dirPtr; /* Contains path to directory to search. */
- CONST char *pattern; /* Pattern to match against. */
- Tcl_GlobTypeData *types; /* Object containing list of acceptable types.
+TestReportMatchInDirectory(
+ Tcl_Interp *interp, /* Interpreter for error messages. */
+ Tcl_Obj *resultPtr, /* Object to lappend results. */
+ Tcl_Obj *dirPtr, /* Contains path to directory to search. */
+ const char *pattern, /* Pattern to match against. */
+ Tcl_GlobTypeData *types) /* Object containing list of acceptable types.
* May be NULL. */
{
if (types != NULL && types->type & TCL_GLOB_TYPE_MOUNT) {
- TestReport("matchmounts",dirPtr, NULL);
+ TestReport("matchmounts", dirPtr, NULL);
return TCL_OK;
} else {
- TestReport("matchindirectory",dirPtr, NULL);
- return Tcl_FSMatchInDirectory(interp, resultPtr,
- TestReportGetNativePath(dirPtr), pattern,
- types);
+ TestReport("matchindirectory", dirPtr, NULL);
+ return Tcl_FSMatchInDirectory(interp, resultPtr,
+ TestReportGetNativePath(dirPtr), pattern, types);
}
}
+
static int
-TestReportChdir(dirName)
- Tcl_Obj *dirName;
+TestReportChdir(
+ Tcl_Obj *dirName)
{
- TestReport("chdir",dirName,NULL);
+ TestReport("chdir", dirName, NULL);
return Tcl_FSChdir(TestReportGetNativePath(dirName));
}
+
static int
-TestReportLoadFile(interp, fileName,
- handlePtr, unloadProcPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Obj *fileName; /* Name of the file containing the desired
+TestReportLoadFile(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *fileName, /* Name of the file containing the desired
* code. */
- Tcl_LoadHandle *handlePtr; /* Filled with token for dynamically loaded
- * file which will be passed back to
+ Tcl_LoadHandle *handlePtr, /* Filled with token for dynamically loaded
+ * file which will be passed back to
* (*unloadProcPtr)() to unload the file. */
- Tcl_FSUnloadFileProc **unloadProcPtr;
+ Tcl_FSUnloadFileProc **unloadProcPtr)
/* Filled with address of Tcl_FSUnloadFileProc
* function which should be used for
* this file. */
{
- TestReport("loadfile",fileName,NULL);
- return Tcl_FSLoadFile(interp, TestReportGetNativePath(fileName), NULL, NULL,
- NULL, NULL, handlePtr, unloadProcPtr);
+ TestReport("loadfile", fileName, NULL);
+ return Tcl_FSLoadFile(interp, TestReportGetNativePath(fileName), NULL,
+ NULL, NULL, NULL, handlePtr, unloadProcPtr);
}
+
static Tcl_Obj *
-TestReportLink(path, to, linkType)
- Tcl_Obj *path; /* Path of file to readlink or link */
- Tcl_Obj *to; /* Path of file to link to, or NULL */
- int linkType;
+TestReportLink(
+ Tcl_Obj *path, /* Path of file to readlink or link */
+ Tcl_Obj *to, /* Path of file to link to, or NULL */
+ int linkType)
{
- TestReport("link",path,to);
+ TestReport("link", path, to);
return Tcl_FSLink(TestReportGetNativePath(path), to, linkType);
}
+
static int
-TestReportRenameFile(src, dst)
- Tcl_Obj *src; /* Pathname of file or dir to be renamed
+TestReportRenameFile(
+ Tcl_Obj *src, /* Pathname of file or dir to be renamed
* (UTF-8). */
- Tcl_Obj *dst; /* New pathname of file or directory
+ Tcl_Obj *dst) /* New pathname of file or directory
* (UTF-8). */
{
- TestReport("renamefile",src,dst);
- return Tcl_FSRenameFile(TestReportGetNativePath(src),
- TestReportGetNativePath(dst));
+ TestReport("renamefile", src, dst);
+ return Tcl_FSRenameFile(TestReportGetNativePath(src),
+ TestReportGetNativePath(dst));
}
-static int
-TestReportCopyFile(src, dst)
- Tcl_Obj *src; /* Pathname of file to be copied (UTF-8). */
- Tcl_Obj *dst; /* Pathname of file to copy to (UTF-8). */
+
+static int
+TestReportCopyFile(
+ Tcl_Obj *src, /* Pathname of file to be copied (UTF-8). */
+ Tcl_Obj *dst) /* Pathname of file to copy to (UTF-8). */
{
- TestReport("copyfile",src,dst);
- return Tcl_FSCopyFile(TestReportGetNativePath(src),
- TestReportGetNativePath(dst));
+ TestReport("copyfile", src, dst);
+ return Tcl_FSCopyFile(TestReportGetNativePath(src),
+ TestReportGetNativePath(dst));
}
+
static int
-TestReportDeleteFile(path)
- Tcl_Obj *path; /* Pathname of file to be removed (UTF-8). */
+TestReportDeleteFile(
+ Tcl_Obj *path) /* Pathname of file to be removed (UTF-8). */
{
- TestReport("deletefile",path,NULL);
+ TestReport("deletefile", path, NULL);
return Tcl_FSDeleteFile(TestReportGetNativePath(path));
}
+
static int
-TestReportCreateDirectory(path)
- Tcl_Obj *path; /* Pathname of directory to create (UTF-8). */
+TestReportCreateDirectory(
+ Tcl_Obj *path) /* Pathname of directory to create (UTF-8). */
{
- TestReport("createdirectory",path,NULL);
+ TestReport("createdirectory", path, NULL);
return Tcl_FSCreateDirectory(TestReportGetNativePath(path));
}
+
static int
-TestReportCopyDirectory(src, dst, errorPtr)
- Tcl_Obj *src; /* Pathname of directory to be copied
+TestReportCopyDirectory(
+ Tcl_Obj *src, /* Pathname of directory to be copied
* (UTF-8). */
- Tcl_Obj *dst; /* Pathname of target directory (UTF-8). */
- Tcl_Obj **errorPtr; /* If non-NULL, to be filled with UTF-8 name
- * of file causing error. */
+ Tcl_Obj *dst, /* Pathname of target directory (UTF-8). */
+ Tcl_Obj **errorPtr) /* If non-NULL, to be filled with UTF-8 name
+ * of file causing error. */
{
- TestReport("copydirectory",src,dst);
- return Tcl_FSCopyDirectory(TestReportGetNativePath(src),
- TestReportGetNativePath(dst), errorPtr);
+ TestReport("copydirectory", src, dst);
+ return Tcl_FSCopyDirectory(TestReportGetNativePath(src),
+ TestReportGetNativePath(dst), errorPtr);
}
+
static int
-TestReportRemoveDirectory(path, recursive, errorPtr)
- Tcl_Obj *path; /* Pathname of directory to be removed
+TestReportRemoveDirectory(
+ Tcl_Obj *path, /* Pathname of directory to be removed
* (UTF-8). */
- int recursive; /* If non-zero, removes directories that
+ int recursive, /* If non-zero, removes directories that
* are nonempty. Otherwise, will only remove
* empty directories. */
- Tcl_Obj **errorPtr; /* If non-NULL, to be filled with UTF-8 name
- * of file causing error. */
+ Tcl_Obj **errorPtr) /* If non-NULL, to be filled with UTF-8 name
+ * of file causing error. */
{
- TestReport("removedirectory",path,NULL);
- return Tcl_FSRemoveDirectory(TestReportGetNativePath(path), recursive,
- errorPtr);
+ TestReport("removedirectory", path, NULL);
+ return Tcl_FSRemoveDirectory(TestReportGetNativePath(path), recursive,
+ errorPtr);
}
-static CONST char**
-TestReportFileAttrStrings(fileName, objPtrRef)
- Tcl_Obj* fileName;
- Tcl_Obj** objPtrRef;
+
+static const char **
+TestReportFileAttrStrings(
+ Tcl_Obj *fileName,
+ Tcl_Obj **objPtrRef)
{
- TestReport("fileattributestrings",fileName,NULL);
+ TestReport("fileattributestrings", fileName, NULL);
return Tcl_FSFileAttrStrings(TestReportGetNativePath(fileName), objPtrRef);
}
+
static int
-TestReportFileAttrsGet(interp, index, fileName, objPtrRef)
- Tcl_Interp *interp; /* The interpreter for error reporting. */
- int index; /* index of the attribute command. */
- Tcl_Obj *fileName; /* filename we are operating on. */
- Tcl_Obj **objPtrRef; /* for output. */
+TestReportFileAttrsGet(
+ Tcl_Interp *interp, /* The interpreter for error reporting. */
+ int index, /* index of the attribute command. */
+ Tcl_Obj *fileName, /* filename we are operating on. */
+ Tcl_Obj **objPtrRef) /* for output. */
{
- TestReport("fileattributesget",fileName,NULL);
- return Tcl_FSFileAttrsGet(interp, index,
- TestReportGetNativePath(fileName), objPtrRef);
+ TestReport("fileattributesget", fileName, NULL);
+ return Tcl_FSFileAttrsGet(interp, index,
+ TestReportGetNativePath(fileName), objPtrRef);
}
+
static int
-TestReportFileAttrsSet(interp, index, fileName, objPtr)
- Tcl_Interp *interp; /* The interpreter for error reporting. */
- int index; /* index of the attribute command. */
- Tcl_Obj *fileName; /* filename we are operating on. */
- Tcl_Obj *objPtr; /* for input. */
-{
- TestReport("fileattributesset",fileName,objPtr);
- return Tcl_FSFileAttrsSet(interp, index,
- TestReportGetNativePath(fileName), objPtr);
-}
-static int
-TestReportUtime (fileName, tval)
- Tcl_Obj* fileName;
- struct utimbuf *tval;
-{
- TestReport("utime",fileName,NULL);
+TestReportFileAttrsSet(
+ Tcl_Interp *interp, /* The interpreter for error reporting. */
+ int index, /* index of the attribute command. */
+ Tcl_Obj *fileName, /* filename we are operating on. */
+ Tcl_Obj *objPtr) /* for input. */
+{
+ TestReport("fileattributesset", fileName, objPtr);
+ return Tcl_FSFileAttrsSet(interp, index,
+ TestReportGetNativePath(fileName), objPtr);
+}
+
+static int
+TestReportUtime(
+ Tcl_Obj *fileName,
+ struct utimbuf *tval)
+{
+ TestReport("utime", fileName, NULL);
return Tcl_FSUtime(TestReportGetNativePath(fileName), tval);
}
+
static int
-TestReportNormalizePath(interp, pathPtr, nextCheckpoint)
- Tcl_Interp *interp;
- Tcl_Obj *pathPtr;
- int nextCheckpoint;
+TestReportNormalizePath(
+ Tcl_Interp *interp,
+ Tcl_Obj *pathPtr,
+ int nextCheckpoint)
{
- TestReport("normalizepath",pathPtr,NULL);
+ TestReport("normalizepath", pathPtr, NULL);
return nextCheckpoint;
}
-static int
-SimplePathInFilesystem(Tcl_Obj *pathPtr, ClientData *clientDataPtr) {
- CONST char *str = Tcl_GetString(pathPtr);
- if (strncmp(str,"simplefs:/",10)) {
+static int
+SimplePathInFilesystem(
+ Tcl_Obj *pathPtr,
+ ClientData *clientDataPtr)
+{
+ const char *str = Tcl_GetString(pathPtr);
+
+ if (strncmp(str, "simplefs:/", 10)) {
return -1;
}
return TCL_OK;
}
-/*
- * Since TclCopyChannel insists on an interpreter, we use this
- * to simplify our test scripts. Would be better if it could
- * copy without an interp
- */
-static Tcl_Interp *simpleInterpPtr = NULL;
-/* We use this to ensure we clean up after ourselves */
-static Tcl_Obj *tempFile = NULL;
-
-/*
- * This is a very 'hacky' filesystem which is used just to
- * test two important features of the vfs code: (1) that
- * you can load a shared library from a vfs, (2) that when
- * copying files from one fs to another, the 'mtime' is
- * preserved.
- *
- * It treats any file in 'simplefs:/' as a file, and
- * artificially creates a real file on the fly which it uses
- * to extract information from. The real file it uses is
- * whatever follows the trailing '/' (e.g. 'foo' in 'simplefs:/foo'),
- * and that file is assumed to exist in the native pwd, and is
- * copied over to the native temporary directory where it is
- * accessed.
- *
- * Please do not consider this filesystem a model of how
- * things are to be done. It is quite the opposite! But, it
- * does allow us to test two important features.
- *
- * Finally: this fs can only be used from one interpreter.
+/*
+ * This is a slightly 'hacky' filesystem which is used just to test a few
+ * important features of the vfs code: (1) that you can load a shared library
+ * from a vfs, (2) that when copying files from one fs to another, the 'mtime'
+ * is preserved. (3) that recursive cross-filesystem directory copies have the
+ * correct behaviour with/without -force.
+ *
+ * It treats any file in 'simplefs:/' as a file, which it routes to the
+ * current directory. The real file it uses is whatever follows the trailing
+ * '/' (e.g. 'foo' in 'simplefs:/foo'), and that file exists or not according
+ * to what is in the native pwd.
+ *
+ * Please do not consider this filesystem a model of how things are to be
+ * done. It is quite the opposite! But, it does allow us to test some
+ * important features.
*/
+
static int
-TestSimpleFilesystemObjCmd(dummy, interp, objc, objv)
- ClientData dummy;
- Tcl_Interp *interp;
- int objc;
- Tcl_Obj *CONST objv[];
+TestSimpleFilesystemObjCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const objv[])
{
int res, boolVal;
char *msg;
-
+
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "boolean");
return TCL_ERROR;
@@ -6392,129 +6911,138 @@ TestSimpleFilesystemObjCmd(dummy, interp, objc, objv)
if (boolVal) {
res = Tcl_FSRegister((ClientData)interp, &simpleFilesystem);
msg = (res == TCL_OK) ? "registered" : "failed";
- simpleInterpPtr = interp;
} else {
- if (tempFile != NULL) {
- Tcl_FSDeleteFile(tempFile);
- Tcl_DecrRefCount(tempFile);
- tempFile = NULL;
- }
res = Tcl_FSUnregister(&simpleFilesystem);
msg = (res == TCL_OK) ? "unregistered" : "failed";
- simpleInterpPtr = NULL;
}
Tcl_SetResult(interp, msg, TCL_VOLATILE);
return res;
}
-/*
- * Treats a file name 'simplefs:/foo' by copying the file 'foo'
- * in the current (native) directory to a temporary native file,
- * and then returns that native file.
+/*
+ * Treats a file name 'simplefs:/foo' by using the file 'foo' in the current
+ * (native) directory.
*/
-static Tcl_Obj*
-SimpleCopy(pathPtr)
- Tcl_Obj *pathPtr; /* Name of file to copy. */
+
+static Tcl_Obj *
+SimpleRedirect(
+ Tcl_Obj *pathPtr) /* Name of file to copy. */
{
- int res;
- CONST char *str;
+ int len;
+ const char *str;
Tcl_Obj *origPtr;
- Tcl_Obj *tempPtr;
- tempPtr = TclpTempFileName();
- Tcl_IncrRefCount(tempPtr);
-
- /*
+ /*
* We assume the same name in the current directory is ok.
*/
- str = Tcl_GetString(pathPtr);
+
+ str = Tcl_GetStringFromObj(pathPtr, &len);
+ if (len < 10 || strncmp(str, "simplefs:/", 10)) {
+ /* Probably shouldn't ever reach here */
+ Tcl_IncrRefCount(pathPtr);
+ return pathPtr;
+ }
origPtr = Tcl_NewStringObj(str+10,-1);
Tcl_IncrRefCount(origPtr);
+ return origPtr;
+}
- res = TclCrossFilesystemCopy(simpleInterpPtr, origPtr, tempPtr);
- Tcl_DecrRefCount(origPtr);
+static int
+SimpleMatchInDirectory(
+ Tcl_Interp *interp, /* Interpreter for error
+ * messages. */
+ Tcl_Obj *resultPtr, /* Object to lappend results. */
+ Tcl_Obj *dirPtr, /* Contains path to directory to search. */
+ const char *pattern, /* Pattern to match against. */
+ Tcl_GlobTypeData *types) /* Object containing list of acceptable types.
+ * May be NULL. */
+{
+ int res;
+ Tcl_Obj *origPtr;
+ Tcl_Obj *resPtr;
- if (res != TCL_OK) {
- Tcl_FSDeleteFile(tempPtr);
- Tcl_DecrRefCount(tempPtr);
- return NULL;
+ /* We only provide a new volume, therefore no mounts at all */
+ if (types != NULL && types->type & TCL_GLOB_TYPE_MOUNT) {
+ return TCL_OK;
}
- return tempPtr;
+
+ /*
+ * We assume the same name in the current directory is ok.
+ */
+ resPtr = Tcl_NewObj();
+ Tcl_IncrRefCount(resPtr);
+ origPtr = SimpleRedirect(dirPtr);
+ res = Tcl_FSMatchInDirectory(interp, resPtr, origPtr, pattern, types);
+ if (res == TCL_OK) {
+ int gLength, j;
+ Tcl_ListObjLength(NULL, resPtr, &gLength);
+ for (j = 0; j < gLength; j++) {
+ Tcl_Obj *gElt, *nElt;
+ Tcl_ListObjIndex(NULL, resPtr, j, &gElt);
+ nElt = Tcl_NewStringObj("simplefs:/",10);
+ Tcl_AppendObjToObj(nElt, gElt);
+ Tcl_ListObjAppendElement(NULL, resultPtr, nElt);
+ }
+ }
+ Tcl_DecrRefCount(origPtr);
+ Tcl_DecrRefCount(resPtr);
+ return res;
}
static Tcl_Channel
-SimpleOpenFileChannel(interp, pathPtr, mode, permissions)
- Tcl_Interp *interp; /* Interpreter for error reporting;
- * can be NULL. */
- Tcl_Obj *pathPtr; /* Name of file to open. */
- int mode; /* POSIX open mode. */
- int permissions; /* If the open involves creating a
- * file, with what modes to create
- * it? */
+SimpleOpenFileChannel(
+ Tcl_Interp *interp, /* Interpreter for error reporting; can be
+ * NULL. */
+ Tcl_Obj *pathPtr, /* Name of file to open. */
+ int mode, /* POSIX open mode. */
+ int permissions) /* If the open involves creating a file, with
+ * what modes to create it? */
{
Tcl_Obj *tempPtr;
Tcl_Channel chan;
-
+
if ((mode != 0) && !(mode & O_RDONLY)) {
- Tcl_AppendResult(interp, "read-only",
- (char *) NULL);
+ Tcl_AppendResult(interp, "read-only", NULL);
return NULL;
}
-
- tempPtr = SimpleCopy(pathPtr);
-
- if (tempPtr == NULL) {
- return NULL;
- }
-
- chan = Tcl_FSOpenFileChannel(interp, tempPtr, "r", permissions);
- if (tempFile != NULL) {
- Tcl_FSDeleteFile(tempFile);
- Tcl_DecrRefCount(tempFile);
- tempFile = NULL;
- }
- /*
- * Store file pointer in this global variable so we can delete
- * it later
- */
- tempFile = tempPtr;
+ tempPtr = SimpleRedirect(pathPtr);
+ chan = Tcl_FSOpenFileChannel(interp, tempPtr, "r", permissions);
+ Tcl_DecrRefCount(tempPtr);
return chan;
}
static int
-SimpleAccess(pathPtr, mode)
- Tcl_Obj *pathPtr; /* Path of file to access (in current CP). */
- int mode; /* Permission setting. */
+SimpleAccess(
+ Tcl_Obj *pathPtr, /* Path of file to access (in current CP). */
+ int mode) /* Permission setting. */
{
- /* All files exist */
- return TCL_OK;
+ Tcl_Obj *tempPtr = SimpleRedirect(pathPtr);
+ int res = Tcl_FSAccess(tempPtr, mode);
+
+ Tcl_DecrRefCount(tempPtr);
+ return res;
}
static int
-SimpleStat(pathPtr, bufPtr)
- Tcl_Obj *pathPtr; /* Path of file to stat (in current CP). */
- Tcl_StatBuf *bufPtr; /* Filled with results of stat call. */
+SimpleStat(
+ Tcl_Obj *pathPtr, /* Path of file to stat (in current CP). */
+ Tcl_StatBuf *bufPtr) /* Filled with results of stat call. */
{
- Tcl_Obj *tempPtr = SimpleCopy(pathPtr);
- if (tempPtr == NULL) {
- /* We just pretend the file exists anyway */
- return TCL_OK;
- } else {
- int res = Tcl_FSStat(tempPtr, bufPtr);
- Tcl_FSDeleteFile(tempPtr);
- Tcl_DecrRefCount(tempPtr);
- return res;
- }
+ Tcl_Obj *tempPtr = SimpleRedirect(pathPtr);
+ int res = Tcl_FSStat(tempPtr, bufPtr);
+
+ Tcl_DecrRefCount(tempPtr);
+ return res;
}
-static Tcl_Obj*
+static Tcl_Obj *
SimpleListVolumes(void)
{
/* Add one new volume */
Tcl_Obj *retVal;
- retVal = Tcl_NewStringObj("simplefs:/",-1);
+ retVal = Tcl_NewStringObj("simplefs:/", -1);
Tcl_IncrRefCount(retVal);
return retVal;
}
@@ -6522,15 +7050,17 @@ SimpleListVolumes(void)
/*
* Used to check correct string-length determining in Tcl_NumUtfChars
*/
+
static int
-TestNumUtfCharsCmd(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- Tcl_Obj *CONST objv[];
+TestNumUtfCharsCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const objv[])
{
if (objc > 1) {
int len = -1;
+
if (objc > 2) {
(void) Tcl_GetStringFromObj(objv[1], &len);
}
@@ -6539,3 +7069,421 @@ TestNumUtfCharsCmd(clientData, interp, objc, objv)
}
return TCL_OK;
}
+
+/*
+ * Used to do basic checks of the TCL_HASH_KEY_SYSTEM_HASH flag
+ */
+
+static int
+TestHashSystemHashCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ static Tcl_HashKeyType hkType = {
+ TCL_HASH_KEY_TYPE_VERSION, TCL_HASH_KEY_SYSTEM_HASH,
+ NULL, NULL, NULL, NULL
+ };
+ Tcl_HashTable hash;
+ Tcl_HashEntry *hPtr;
+ int i, isNew, limit = 100;
+
+ if (objc>1 && Tcl_GetIntFromObj(interp, objv[1], &limit)!=TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ Tcl_InitCustomHashTable(&hash, TCL_CUSTOM_TYPE_KEYS, &hkType);
+
+ if (hash.numEntries != 0) {
+ Tcl_AppendResult(interp, "non-zero initial size", NULL);
+ Tcl_DeleteHashTable(&hash);
+ return TCL_ERROR;
+ }
+
+ for (i=0 ; i<limit ; i++) {
+ hPtr = Tcl_CreateHashEntry(&hash, (char *) INT2PTR(i), &isNew);
+ if (!isNew) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(i));
+ Tcl_AppendToObj(Tcl_GetObjResult(interp)," creation problem",-1);
+ Tcl_DeleteHashTable(&hash);
+ return TCL_ERROR;
+ }
+ Tcl_SetHashValue(hPtr, (ClientData) INT2PTR(i+42));
+ }
+
+ if (hash.numEntries != limit) {
+ Tcl_AppendResult(interp, "unexpected maximal size", NULL);
+ Tcl_DeleteHashTable(&hash);
+ return TCL_ERROR;
+ }
+
+ for (i=0 ; i<limit ; i++) {
+ hPtr = Tcl_FindHashEntry(&hash, (char *) INT2PTR(i));
+ if (hPtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(i));
+ Tcl_AppendToObj(Tcl_GetObjResult(interp)," lookup problem",-1);
+ Tcl_DeleteHashTable(&hash);
+ return TCL_ERROR;
+ }
+ if (PTR2INT(Tcl_GetHashValue(hPtr)) != i+42) {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(i));
+ Tcl_AppendToObj(Tcl_GetObjResult(interp)," value problem",-1);
+ Tcl_DeleteHashTable(&hash);
+ return TCL_ERROR;
+ }
+ Tcl_DeleteHashEntry(hPtr);
+ }
+
+ if (hash.numEntries != 0) {
+ Tcl_AppendResult(interp, "non-zero final size", NULL);
+ Tcl_DeleteHashTable(&hash);
+ return TCL_ERROR;
+ }
+
+ Tcl_DeleteHashTable(&hash);
+ Tcl_AppendResult(interp, "OK", NULL);
+ return TCL_OK;
+}
+
+/*
+ * Used for testing Tcl_GetInt which is no longer used directly by the
+ * core very much.
+ */
+static int
+TestgetintCmd(
+ ClientData dummy,
+ Tcl_Interp *interp,
+ int argc,
+ const char **argv)
+{
+ if (argc < 2) {
+ Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
+ return TCL_ERROR;
+ } else {
+ int val, i, total=0;
+ char buf[TCL_INTEGER_SPACE];
+
+ for (i=1 ; i<argc ; i++) {
+ if (Tcl_GetInt(interp, argv[i], &val) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ total += val;
+ }
+ TclFormatInt(buf, total);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ return TCL_OK;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestconcatobjCmd --
+ *
+ * This procedure implements the "testconcatobj" command. It is used
+ * to test that Tcl_ConcatObj does indeed return a fresh Tcl_Obj in all
+ * cases and thet it never corrupts its arguments. In other words, that
+ * [Bug 1447328] was fixed properly.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TestconcatobjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
+{
+ Tcl_Obj *list1Ptr, *list2Ptr, *emptyPtr, *concatPtr, *tmpPtr;
+ int result = TCL_OK, len;
+ Tcl_Obj *objv[3];
+
+ /*
+ * Set the start of the error message as obj result; it will be cleared at
+ * the end if no errors were found.
+ */
+
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("Tcl_ConcatObj is unsafe:", -1));
+
+ emptyPtr = Tcl_NewObj();
+
+ list1Ptr = Tcl_NewStringObj("foo bar sum", -1);
+ Tcl_ListObjLength(NULL, list1Ptr, &len);
+ if (list1Ptr->bytes != NULL) {
+ ckfree((char *) list1Ptr->bytes);
+ list1Ptr->bytes = NULL;
+ }
+
+ list2Ptr = Tcl_NewStringObj("eeny meeny", -1);
+ Tcl_ListObjLength(NULL, list2Ptr, &len);
+ if (list2Ptr->bytes != NULL) {
+ ckfree((char *) list2Ptr->bytes);
+ list2Ptr->bytes = NULL;
+ }
+
+ /*
+ * Verify that concat'ing a list obj with one or more empty strings does
+ * return a fresh Tcl_Obj (see also [Bug 2055782]).
+ */
+
+ tmpPtr = Tcl_DuplicateObj(list1Ptr);
+
+ objv[0] = tmpPtr;
+ objv[1] = emptyPtr;
+ concatPtr = Tcl_ConcatObj(2, objv);
+ if (concatPtr->refCount != 0) {
+ result = TCL_ERROR;
+ Tcl_AppendResult(interp,
+ "\n\t* (a) concatObj does not have refCount 0", NULL);
+ }
+ if (concatPtr == tmpPtr) {
+ result = TCL_ERROR;
+ Tcl_AppendResult(interp, "\n\t* (a) concatObj is not a new obj ",
+ NULL);
+ switch (tmpPtr->refCount) {
+ case 0:
+ Tcl_AppendResult(interp, "(no new refCount)", NULL);
+ break;
+ case 1:
+ Tcl_AppendResult(interp, "(refCount added)", NULL);
+ break;
+ default:
+ Tcl_AppendResult(interp, "(more than one refCount added!)", NULL);
+ Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
+ }
+ tmpPtr = Tcl_DuplicateObj(list1Ptr);
+ objv[0] = tmpPtr;
+ }
+ Tcl_DecrRefCount(concatPtr);
+
+ Tcl_IncrRefCount(tmpPtr);
+ concatPtr = Tcl_ConcatObj(2, objv);
+ if (concatPtr->refCount != 0) {
+ result = TCL_ERROR;
+ Tcl_AppendResult(interp,
+ "\n\t* (b) concatObj does not have refCount 0", NULL);
+ }
+ if (concatPtr == tmpPtr) {
+ result = TCL_ERROR;
+ Tcl_AppendResult(interp, "\n\t* (b) concatObj is not a new obj ",
+ NULL);
+ switch (tmpPtr->refCount) {
+ case 0:
+ Tcl_AppendResult(interp, "(refCount removed?)", NULL);
+ Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
+ break;
+ case 1:
+ Tcl_AppendResult(interp, "(no new refCount)", NULL);
+ break;
+ case 2:
+ Tcl_AppendResult(interp, "(refCount added)", NULL);
+ Tcl_DecrRefCount(tmpPtr);
+ break;
+ default:
+ Tcl_AppendResult(interp, "(more than one refCount added!)", NULL);
+ Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
+ }
+ tmpPtr = Tcl_DuplicateObj(list1Ptr);
+ objv[0] = tmpPtr;
+ }
+ Tcl_DecrRefCount(concatPtr);
+
+ objv[0] = emptyPtr;
+ objv[1] = tmpPtr;
+ objv[2] = emptyPtr;
+ concatPtr = Tcl_ConcatObj(3, objv);
+ if (concatPtr->refCount != 0) {
+ result = TCL_ERROR;
+ Tcl_AppendResult(interp,
+ "\n\t* (c) concatObj does not have refCount 0", NULL);
+ }
+ if (concatPtr == tmpPtr) {
+ result = TCL_ERROR;
+ Tcl_AppendResult(interp, "\n\t* (c) concatObj is not a new obj ",
+ NULL);
+ switch (tmpPtr->refCount) {
+ case 0:
+ Tcl_AppendResult(interp, "(no new refCount)", NULL);
+ break;
+ case 1:
+ Tcl_AppendResult(interp, "(refCount added)", NULL);
+ break;
+ default:
+ Tcl_AppendResult(interp, "(more than one refCount added!)", NULL);
+ Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
+ }
+ tmpPtr = Tcl_DuplicateObj(list1Ptr);
+ objv[1] = tmpPtr;
+ }
+ Tcl_DecrRefCount(concatPtr);
+
+ Tcl_IncrRefCount(tmpPtr);
+ concatPtr = Tcl_ConcatObj(3, objv);
+ if (concatPtr->refCount != 0) {
+ result = TCL_ERROR;
+ Tcl_AppendResult(interp,
+ "\n\t* (d) concatObj does not have refCount 0", NULL);
+ }
+ if (concatPtr == tmpPtr) {
+ result = TCL_ERROR;
+ Tcl_AppendResult(interp, "\n\t* (d) concatObj is not a new obj ",
+ NULL);
+ switch (tmpPtr->refCount) {
+ case 0:
+ Tcl_AppendResult(interp, "(refCount removed?)", NULL);
+ Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
+ break;
+ case 1:
+ Tcl_AppendResult(interp, "(no new refCount)", NULL);
+ break;
+ case 2:
+ Tcl_AppendResult(interp, "(refCount added)", NULL);
+ Tcl_DecrRefCount(tmpPtr);
+ break;
+ default:
+ Tcl_AppendResult(interp, "(more than one refCount added!)", NULL);
+ Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
+ }
+ tmpPtr = Tcl_DuplicateObj(list1Ptr);
+ objv[1] = tmpPtr;
+ }
+ Tcl_DecrRefCount(concatPtr);
+
+ /*
+ * Verify that an unshared list is not corrupted when concat'ing things to
+ * it.
+ */
+
+ objv[0] = tmpPtr;
+ objv[1] = list2Ptr;
+ concatPtr = Tcl_ConcatObj(2, objv);
+ if (concatPtr->refCount != 0) {
+ result = TCL_ERROR;
+ Tcl_AppendResult(interp,
+ "\n\t* (e) concatObj does not have refCount 0", NULL);
+ }
+ if (concatPtr == tmpPtr) {
+ int len;
+
+ result = TCL_ERROR;
+ Tcl_AppendResult(interp, "\n\t* (e) concatObj is not a new obj ",
+ NULL);
+
+ (void) Tcl_ListObjLength(NULL, concatPtr, &len);
+ switch (tmpPtr->refCount) {
+ case 3:
+ Tcl_AppendResult(interp, "(failed to concat)", NULL);
+ break;
+ default:
+ Tcl_AppendResult(interp, "(corrupted input!)", NULL);
+ }
+ if (Tcl_IsShared(tmpPtr)) {
+ Tcl_DecrRefCount(tmpPtr);
+ }
+ tmpPtr = Tcl_DuplicateObj(list1Ptr);
+ objv[0] = tmpPtr;
+ }
+ Tcl_DecrRefCount(concatPtr);
+
+ objv[0] = tmpPtr;
+ objv[1] = list2Ptr;
+ Tcl_IncrRefCount(tmpPtr);
+ concatPtr = Tcl_ConcatObj(2, objv);
+ if (concatPtr->refCount != 0) {
+ result = TCL_ERROR;
+ Tcl_AppendResult(interp,
+ "\n\t* (f) concatObj does not have refCount 0", NULL);
+ }
+ if (concatPtr == tmpPtr) {
+ int len;
+
+ result = TCL_ERROR;
+ Tcl_AppendResult(interp, "\n\t* (f) concatObj is not a new obj ",
+ NULL);
+
+ (void) Tcl_ListObjLength(NULL, concatPtr, &len);
+ switch (tmpPtr->refCount) {
+ case 3:
+ Tcl_AppendResult(interp, "(failed to concat)", NULL);
+ break;
+ default:
+ Tcl_AppendResult(interp, "(corrupted input!)", NULL);
+ }
+ if (Tcl_IsShared(tmpPtr)) {
+ Tcl_DecrRefCount(tmpPtr);
+ }
+ tmpPtr = Tcl_DuplicateObj(list1Ptr);
+ objv[0] = tmpPtr;
+ }
+ Tcl_DecrRefCount(concatPtr);
+
+ objv[0] = tmpPtr;
+ objv[1] = list2Ptr;
+ Tcl_IncrRefCount(tmpPtr);
+ Tcl_IncrRefCount(tmpPtr);
+ concatPtr = Tcl_ConcatObj(2, objv);
+ if (concatPtr->refCount != 0) {
+ result = TCL_ERROR;
+ Tcl_AppendResult(interp,
+ "\n\t* (g) concatObj does not have refCount 0", NULL);
+ }
+ if (concatPtr == tmpPtr) {
+ int len;
+
+ result = TCL_ERROR;
+ Tcl_AppendResult(interp, "\n\t* (g) concatObj is not a new obj ",
+ NULL);
+
+ (void) Tcl_ListObjLength(NULL, concatPtr, &len);
+ switch (tmpPtr->refCount) {
+ case 3:
+ Tcl_AppendResult(interp, "(failed to concat)", NULL);
+ break;
+ default:
+ Tcl_AppendResult(interp, "(corrupted input!)", NULL);
+ }
+ Tcl_DecrRefCount(tmpPtr);
+ if (Tcl_IsShared(tmpPtr)) {
+ Tcl_DecrRefCount(tmpPtr);
+ }
+ tmpPtr = Tcl_DuplicateObj(list1Ptr);
+ objv[0] = tmpPtr;
+ }
+ Tcl_DecrRefCount(concatPtr);
+
+ /*
+ * Clean everything up. Note that we don't actually know how many
+ * references there are to tmpPtr here; in the no-error case, it should be
+ * five... [Bug 2895367]
+ */
+
+ Tcl_DecrRefCount(list1Ptr);
+ Tcl_DecrRefCount(list2Ptr);
+ Tcl_DecrRefCount(emptyPtr);
+ while (tmpPtr->refCount > 1) {
+ Tcl_DecrRefCount(tmpPtr);
+ }
+ Tcl_DecrRefCount(tmpPtr);
+
+ if (result == TCL_OK) {
+ Tcl_ResetResult(interp);
+ }
+ return result;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclTestObj.c b/generic/tclTestObj.c
index a55704a..37286e3 100644
--- a/generic/tclTestObj.c
+++ b/generic/tclTestObj.c
@@ -1,61 +1,57 @@
-/*
+/*
* tclTestObj.c --
*
- * This file contains C command procedures for the additional Tcl
- * commands that are used for testing implementations of the Tcl object
- * types. These commands are not normally included in Tcl
- * applications; they're only used for testing.
+ * This file contains C command functions for the additional Tcl commands
+ * that are used for testing implementations of the Tcl object types.
+ * These commands are not normally included in Tcl applications; they're
+ * only used for testing.
*
* Copyright (c) 1995-1998 Sun Microsystems, Inc.
* Copyright (c) 1999 by Scriptics Corporation.
+ * Copyright (c) 2005 by Kevin B. Kenny. All rights reserved.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
+#include "tommath.h"
/*
* An array of Tcl_Obj pointers used in the commands that operate on or get
- * the values of Tcl object-valued variables. varPtr[i] is the i-th
- * variable's Tcl_Obj *.
+ * the values of Tcl object-valued variables. varPtr[i] is the i-th variable's
+ * Tcl_Obj *.
*/
#define NUMBER_OF_OBJECT_VARS 20
static Tcl_Obj *varPtr[NUMBER_OF_OBJECT_VARS];
/*
- * Forward declarations for procedures defined later in this file:
+ * Forward declarations for functions defined later in this file:
*/
-static int CheckIfVarUnset _ANSI_ARGS_((Tcl_Interp *interp,
- int varIndex));
-static int GetVariableIndex _ANSI_ARGS_((Tcl_Interp *interp,
- char *string, int *indexPtr));
-static void SetVarToObj _ANSI_ARGS_((int varIndex,
- Tcl_Obj *objPtr));
-int TclObjTest_Init _ANSI_ARGS_((Tcl_Interp *interp));
-static int TestbooleanobjCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int TestconvertobjCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int TestdoubleobjCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int TestindexobjCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int TestintobjCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int TestobjCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-static int TeststringobjCmd _ANSI_ARGS_((ClientData dummy,
+static int CheckIfVarUnset(Tcl_Interp *interp, int varIndex);
+static int GetVariableIndex(Tcl_Interp *interp,
+ const char *string, int *indexPtr);
+static void SetVarToObj(int varIndex, Tcl_Obj *objPtr);
+int TclObjTest_Init(Tcl_Interp *interp);
+static int TestbignumobjCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int TestbooleanobjCmd(ClientData dummy,
Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
+ Tcl_Obj *const objv[]);
+static int TestdoubleobjCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int TestindexobjCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int TestintobjCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int TestlistobjCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int TestobjCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int TeststringobjCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
typedef struct TestString {
int numChars;
@@ -63,14 +59,13 @@ typedef struct TestString {
size_t uallocated;
Tcl_UniChar unicode[2];
} TestString;
-
/*
*----------------------------------------------------------------------
*
* TclObjTest_Init --
*
- * This procedure creates additional commands that are used to test the
+ * This function creates additional commands that are used to test the
* Tcl object support.
*
* Results:
@@ -84,154 +79,213 @@ typedef struct TestString {
*/
int
-TclObjTest_Init(interp)
- Tcl_Interp *interp;
+TclObjTest_Init(
+ Tcl_Interp *interp)
{
register int i;
-
+
for (i = 0; i < NUMBER_OF_OBJECT_VARS; i++) {
varPtr[i] = NULL;
}
-
+
+ Tcl_CreateObjCommand(interp, "testbignumobj", TestbignumobjCmd,
+ (ClientData) 0, NULL);
Tcl_CreateObjCommand(interp, "testbooleanobj", TestbooleanobjCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
- Tcl_CreateObjCommand(interp, "testconvertobj", TestconvertobjCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateObjCommand(interp, "testdoubleobj", TestdoubleobjCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateObjCommand(interp, "testintobj", TestintobjCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateObjCommand(interp, "testindexobj", TestindexobjCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
- Tcl_CreateObjCommand(interp, "testobj", TestobjCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
+ Tcl_CreateObjCommand(interp, "testlistobj", TestlistobjCmd,
+ (ClientData) 0, NULL);
+ Tcl_CreateObjCommand(interp, "testobj", TestobjCmd, (ClientData) 0, NULL);
Tcl_CreateObjCommand(interp, "teststringobj", TeststringobjCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * TestbooleanobjCmd --
+ * TestbignumobjCmd --
*
- * This procedure implements the "testbooleanobj" command. It is used
- * to test the boolean Tcl object type implementation.
+ * This function implmenets the "testbignumobj" command. It is used
+ * to exercise the bignum Tcl object type implementation.
*
* Results:
- * A standard Tcl object result.
+ * Returns a standard Tcl object result.
*
* Side effects:
- * Creates and frees boolean objects, and also converts objects to
- * have boolean type.
+ * Creates and frees bignum objects; converts objects to have bignum
+ * type.
*
*----------------------------------------------------------------------
*/
static int
-TestbooleanobjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+TestbignumobjCmd(
+ ClientData clientData, /* unused */
+ Tcl_Interp *interp, /* Tcl interpreter */
+ int objc, /* Argument count */
+ Tcl_Obj *const objv[]) /* Argument vector */
{
- int varIndex, boolValue;
- char *index, *subCmd;
+ const char * subcmds[] = {
+ "set", "get", "mult10", "div10", NULL
+ };
+ enum options {
+ BIGNUM_SET, BIGNUM_GET, BIGNUM_MULT10, BIGNUM_DIV10
+ };
+
+ int index, varIndex;
+ char* string;
+ mp_int bignumValue, newValue;
if (objc < 3) {
- wrongNumArgs:
- Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?...");
return TCL_ERROR;
}
-
- index = Tcl_GetString(objv[2]);
- if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) {
+ if (Tcl_GetIndexFromObj(interp, objv[1], subcmds, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ string = Tcl_GetString(objv[2]);
+ if (GetVariableIndex(interp, string, &varIndex) != TCL_OK) {
return TCL_ERROR;
}
- subCmd = Tcl_GetString(objv[1]);
- if (strcmp(subCmd, "set") == 0) {
+ switch (index) {
+ case BIGNUM_SET:
if (objc != 4) {
- goto wrongNumArgs;
+ Tcl_WrongNumArgs(interp, 2, objv, "var value");
+ return TCL_ERROR;
}
- if (Tcl_GetBooleanFromObj(interp, objv[3], &boolValue) != TCL_OK) {
+ string = Tcl_GetString(objv[3]);
+ if (mp_init(&bignumValue) != MP_OKAY) {
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("error in mp_init", -1));
+ return TCL_ERROR;
+ }
+ if (mp_read_radix(&bignumValue, string, 10) != MP_OKAY) {
+ mp_clear(&bignumValue);
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("error in mp_read_radix", -1));
return TCL_ERROR;
}
/*
* If the object currently bound to the variable with index varIndex
* has ref count 1 (i.e. the object is unshared) we can modify that
- * object directly. Otherwise, if RC>1 (i.e. the object is shared),
+ * object directly. Otherwise, if RC>1 (i.e. the object is shared),
* we must create a new object to modify/set and decrement the old
* formerly-shared object's ref count. This is "copy on write".
*/
if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) {
- Tcl_SetBooleanObj(varPtr[varIndex], boolValue);
+ Tcl_SetBignumObj(varPtr[varIndex], &bignumValue);
} else {
- SetVarToObj(varIndex, Tcl_NewBooleanObj(boolValue));
+ SetVarToObj(varIndex, Tcl_NewBignumObj(&bignumValue));
}
- Tcl_SetObjResult(interp, varPtr[varIndex]);
- } else if (strcmp(subCmd, "get") == 0) {
+ break;
+
+ case BIGNUM_GET:
if (objc != 3) {
- goto wrongNumArgs;
+ Tcl_WrongNumArgs(interp, 2, objv, "varIndex");
+ return TCL_ERROR;
}
if (CheckIfVarUnset(interp, varIndex)) {
return TCL_ERROR;
}
- Tcl_SetObjResult(interp, varPtr[varIndex]);
- } else if (strcmp(subCmd, "not") == 0) {
+ break;
+
+ case BIGNUM_MULT10:
if (objc != 3) {
- goto wrongNumArgs;
+ Tcl_WrongNumArgs(interp, 2, objv, "varIndex");
+ return TCL_ERROR;
}
if (CheckIfVarUnset(interp, varIndex)) {
return TCL_ERROR;
}
- if (Tcl_GetBooleanFromObj(interp, varPtr[varIndex],
- &boolValue) != TCL_OK) {
+ if (Tcl_GetBignumFromObj(interp, varPtr[varIndex],
+ &bignumValue) != TCL_OK) {
return TCL_ERROR;
}
+ if (mp_init(&newValue) != MP_OKAY
+ || (mp_mul_d(&bignumValue, 10, &newValue) != MP_OKAY)) {
+ mp_clear(&bignumValue);
+ mp_clear(&newValue);
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("error in mp_mul_d", -1));
+ return TCL_ERROR;
+ }
+ mp_clear(&bignumValue);
if (!Tcl_IsShared(varPtr[varIndex])) {
- Tcl_SetBooleanObj(varPtr[varIndex], !boolValue);
+ Tcl_SetBignumObj(varPtr[varIndex], &newValue);
} else {
- SetVarToObj(varIndex, Tcl_NewBooleanObj(!boolValue));
+ SetVarToObj(varIndex, Tcl_NewBignumObj(&newValue));
+ }
+ break;
+
+ case BIGNUM_DIV10:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "varIndex");
+ return TCL_ERROR;
+ }
+ if (CheckIfVarUnset(interp, varIndex)) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetBignumFromObj(interp, varPtr[varIndex],
+ &bignumValue) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (mp_init(&newValue) != MP_OKAY
+ || (mp_div_d(&bignumValue, 10, &newValue, NULL) != MP_OKAY)) {
+ mp_clear(&bignumValue);
+ mp_clear(&newValue);
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj("error in mp_div_d", -1));
+ return TCL_ERROR;
+ }
+ mp_clear(&bignumValue);
+ if (!Tcl_IsShared(varPtr[varIndex])) {
+ Tcl_SetBignumObj(varPtr[varIndex], &newValue);
+ } else {
+ SetVarToObj(varIndex, Tcl_NewBignumObj(&newValue));
}
- Tcl_SetObjResult(interp, varPtr[varIndex]);
- } else {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "bad option \"", Tcl_GetString(objv[1]),
- "\": must be set, get, or not", (char *) NULL);
- return TCL_ERROR;
}
+
+ Tcl_SetObjResult(interp, varPtr[varIndex]);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * TestconvertobjCmd --
+ * TestbooleanobjCmd --
*
- * This procedure implements the "testconvertobj" command. It is used
- * to test converting objects to new types.
+ * This function implements the "testbooleanobj" command. It is used to
+ * test the boolean Tcl object type implementation.
*
* Results:
* A standard Tcl object result.
*
* Side effects:
- * Converts objects to new types.
+ * Creates and frees boolean objects, and also converts objects to
+ * have boolean type.
*
*----------------------------------------------------------------------
*/
static int
-TestconvertobjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+TestbooleanobjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- char *subCmd;
- char buf[20];
+ int varIndex, boolValue;
+ char *index, *subCmd;
if (objc < 3) {
wrongNumArgs:
@@ -239,22 +293,63 @@ TestconvertobjCmd(clientData, interp, objc, objv)
return TCL_ERROR;
}
+ index = Tcl_GetString(objv[2]);
+ if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
subCmd = Tcl_GetString(objv[1]);
- if (strcmp(subCmd, "double") == 0) {
- double d;
+ if (strcmp(subCmd, "set") == 0) {
+ if (objc != 4) {
+ goto wrongNumArgs;
+ }
+ if (Tcl_GetBooleanFromObj(interp, objv[3], &boolValue) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * If the object currently bound to the variable with index varIndex
+ * has ref count 1 (i.e. the object is unshared) we can modify that
+ * object directly. Otherwise, if RC>1 (i.e. the object is shared),
+ * we must create a new object to modify/set and decrement the old
+ * formerly-shared object's ref count. This is "copy on write".
+ */
+ if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) {
+ Tcl_SetBooleanObj(varPtr[varIndex], boolValue);
+ } else {
+ SetVarToObj(varIndex, Tcl_NewBooleanObj(boolValue));
+ }
+ Tcl_SetObjResult(interp, varPtr[varIndex]);
+ } else if (strcmp(subCmd, "get") == 0) {
if (objc != 3) {
goto wrongNumArgs;
}
- if (Tcl_GetDoubleFromObj(interp, objv[2], &d) != TCL_OK) {
+ if (CheckIfVarUnset(interp, varIndex)) {
return TCL_ERROR;
}
- sprintf(buf, "%f", d);
- Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
+ Tcl_SetObjResult(interp, varPtr[varIndex]);
+ } else if (strcmp(subCmd, "not") == 0) {
+ if (objc != 3) {
+ goto wrongNumArgs;
+ }
+ if (CheckIfVarUnset(interp, varIndex)) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetBooleanFromObj(interp, varPtr[varIndex],
+ &boolValue) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (!Tcl_IsShared(varPtr[varIndex])) {
+ Tcl_SetBooleanObj(varPtr[varIndex], !boolValue);
+ } else {
+ SetVarToObj(varIndex, Tcl_NewBooleanObj(!boolValue));
+ }
+ Tcl_SetObjResult(interp, varPtr[varIndex]);
} else {
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
"bad option \"", Tcl_GetString(objv[1]),
- "\": must be double", (char *) NULL);
+ "\": must be set, get, or not", NULL);
return TCL_ERROR;
}
return TCL_OK;
@@ -265,8 +360,8 @@ TestconvertobjCmd(clientData, interp, objc, objv)
*
* TestdoubleobjCmd --
*
- * This procedure implements the "testdoubleobj" command. It is used
- * to test the double-precision floating point Tcl object type
+ * This function implements the "testdoubleobj" command. It is used to
+ * test the double-precision floating point Tcl object type
* implementation.
*
* Results:
@@ -280,16 +375,16 @@ TestconvertobjCmd(clientData, interp, objc, objv)
*/
static int
-TestdoubleobjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+TestdoubleobjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
int varIndex;
double doubleValue;
char *index, *subCmd, *string;
-
+
if (objc < 3) {
wrongNumArgs:
Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
@@ -314,8 +409,8 @@ TestdoubleobjCmd(clientData, interp, objc, objv)
/*
* If the object currently bound to the variable with index varIndex
* has ref count 1 (i.e. the object is unshared) we can modify that
- * object directly. Otherwise, if RC>1 (i.e. the object is shared),
- * we must create a new object to modify/set and decrement the old
+ * object directly. Otherwise, if RC>1 (i.e. the object is shared), we
+ * must create a new object to modify/set and decrement the old
* formerly-shared object's ref count. This is "copy on write".
*/
@@ -370,7 +465,7 @@ TestdoubleobjCmd(clientData, interp, objc, objv)
} else {
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
"bad option \"", Tcl_GetString(objv[1]),
- "\": must be set, get, mult10, or div10", (char *) NULL);
+ "\": must be set, get, mult10, or div10", NULL);
return TCL_ERROR;
}
return TCL_OK;
@@ -381,7 +476,7 @@ TestdoubleobjCmd(clientData, interp, objc, objv)
*
* TestindexobjCmd --
*
- * This procedure implements the "testindexobj" command. It is used to
+ * This function implements the "testindexobj" command. It is used to
* test the index Tcl object type implementation.
*
* Results:
@@ -395,15 +490,15 @@ TestdoubleobjCmd(clientData, interp, objc, objv)
*/
static int
-TestindexobjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+TestindexobjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
int allowAbbrev, index, index2, setError, i, result;
- CONST char **argv;
- static CONST char *tablePtr[] = {"a", "b", "check", (char *) NULL};
+ const char **argv;
+ static const char *tablePtr[] = {"a", "b", "check", NULL};
/*
* Keep this structure declaration in sync with tclIndexObj.c
*/
@@ -417,20 +512,19 @@ TestindexobjCmd(clientData, interp, objc, objv)
if ((objc == 3) && (strcmp(Tcl_GetString(objv[1]),
"check") == 0)) {
/*
- * This code checks to be sure that the results of
- * Tcl_GetIndexFromObj are properly cached in the object and
- * returned on subsequent lookups.
+ * This code checks to be sure that the results of Tcl_GetIndexFromObj
+ * are properly cached in the object and returned on subsequent
+ * lookups.
*/
if (Tcl_GetIntFromObj(interp, objv[2], &index2) != TCL_OK) {
return TCL_ERROR;
}
- Tcl_GetIndexFromObj((Tcl_Interp *) NULL, objv[1], tablePtr,
- "token", 0, &index);
+ Tcl_GetIndexFromObj(NULL, objv[1], tablePtr, "token", 0, &index);
indexRep = (struct IndexRep *) objv[1]->internalRep.otherValuePtr;
indexRep->index = index2;
- result = Tcl_GetIndexFromObj((Tcl_Interp *) NULL, objv[1],
+ result = Tcl_GetIndexFromObj(NULL, objv[1],
tablePtr, "token", 0, &index);
if (result == TCL_OK) {
Tcl_SetIntObj(Tcl_GetObjResult(interp), index);
@@ -450,17 +544,17 @@ TestindexobjCmd(clientData, interp, objc, objv)
return TCL_ERROR;
}
- argv = (CONST char **) ckalloc((unsigned) ((objc-3) * sizeof(char *)));
+ argv = (const char **) ckalloc((unsigned) ((objc-3) * sizeof(char *)));
for (i = 4; i < objc; i++) {
argv[i-4] = Tcl_GetString(objv[i]);
}
argv[objc-4] = NULL;
-
+
/*
- * Tcl_GetIndexFromObj assumes that the table is statically-allocated
- * so that its address is different for each index object. If we
- * accidently allocate a table at the same address as that cached in
- * the index object, clear out the object's cached state.
+ * Tcl_GetIndexFromObj assumes that the table is statically-allocated so
+ * that its address is different for each index object. If we accidently
+ * allocate a table at the same address as that cached in the index
+ * object, clear out the object's cached state.
*/
if ( objv[3]->typePtr != NULL
@@ -486,7 +580,7 @@ TestindexobjCmd(clientData, interp, objc, objv)
*
* TestintobjCmd --
*
- * This procedure implements the "testintobj" command. It is used to
+ * This function implements the "testintobj" command. It is used to
* test the int Tcl object type implementation.
*
* Results:
@@ -500,16 +594,16 @@ TestindexobjCmd(clientData, interp, objc, objv)
*/
static int
-TestintobjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+TestintobjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
int intValue, varIndex, i;
long longValue;
char *index, *subCmd, *string;
-
+
if (objc < 3) {
wrongNumArgs:
Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
@@ -535,8 +629,8 @@ TestintobjCmd(clientData, interp, objc, objv)
/*
* If the object currently bound to the variable with index varIndex
* has ref count 1 (i.e. the object is unshared) we can modify that
- * object directly. Otherwise, if RC>1 (i.e. the object is shared),
- * we must create a new object to modify/set and decrement the old
+ * object directly. Otherwise, if RC>1 (i.e. the object is shared), we
+ * must create a new object to modify/set and decrement the old
* formerly-shared object's ref count. This is "copy on write".
*/
@@ -616,18 +710,18 @@ TestintobjCmd(clientData, interp, objc, objv)
Tcl_AppendToObj(Tcl_GetObjResult(interp), string, -1);
} else if (strcmp(subCmd, "inttoobigtest") == 0) {
/*
- * If long ints have more bits than ints on this platform, verify
- * that Tcl_GetIntFromObj returns an error if the long int held
- * in an integer object's internal representation is too large
- * to fit in an int.
+ * If long ints have more bits than ints on this platform, verify that
+ * Tcl_GetIntFromObj returns an error if the long int held in an
+ * integer object's internal representation is too large to fit in an
+ * int.
*/
-
+
if (objc != 3) {
goto wrongNumArgs;
}
#if (INT_MAX == LONG_MAX) /* int is same size as long int */
Tcl_AppendToObj(Tcl_GetObjResult(interp), "1", -1);
-#else
+#else
if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) {
Tcl_SetLongObj(varPtr[varIndex], LONG_MAX);
} else {
@@ -677,19 +771,114 @@ TestintobjCmd(clientData, interp, objc, objv)
} else {
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
"bad option \"", Tcl_GetString(objv[1]),
- "\": must be set, get, get2, mult10, or div10",
- (char *) NULL);
+ "\": must be set, get, get2, mult10, or div10", NULL);
return TCL_ERROR;
}
return TCL_OK;
}
/*
+ *-----------------------------------------------------------------------------
+ *
+ * TestlistobjCmd --
+ *
+ * This function implements the 'testlistobj' command. It is used to
+ * test a few possible corner cases in list object manipulation from
+ * C code that cannot occur at the Tcl level.
+ *
+ * Results:
+ * A standard Tcl object result.
+ *
+ * Side effects:
+ * Creates, manipulates and frees list objects.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+TestlistobjCmd(
+ ClientData clientData, /* Not used */
+ Tcl_Interp *interp, /* Tcl interpreter */
+ int objc, /* Number of arguments */
+ Tcl_Obj *const objv[]) /* Argument objects */
+{
+ /* Subcommands supported by this command */
+ const char* subcommands[] = {
+ "set",
+ "get",
+ "replace"
+ };
+ enum listobjCmdIndex {
+ LISTOBJ_SET,
+ LISTOBJ_GET,
+ LISTOBJ_REPLACE
+ };
+
+ const char* index; /* Argument giving the variable number */
+ int varIndex; /* Variable number converted to binary */
+ int cmdIndex; /* Ordinal number of the subcommand */
+ int first; /* First index in the list */
+ int count; /* Count of elements in a list */
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg...?");
+ return TCL_ERROR;
+ }
+ index = Tcl_GetString(objv[2]);
+ if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[1], subcommands, "command",
+ 0, &cmdIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch(cmdIndex) {
+ case LISTOBJ_SET:
+ if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) {
+ Tcl_SetListObj(varPtr[varIndex], objc-3, objv+3);
+ } else {
+ SetVarToObj(varIndex, Tcl_NewListObj(objc-3, objv+3));
+ }
+ Tcl_SetObjResult(interp, varPtr[varIndex]);
+ break;
+
+ case LISTOBJ_GET:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "varIndex");
+ return TCL_ERROR;
+ }
+ if (CheckIfVarUnset(interp, varIndex)) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, varPtr[varIndex]);
+ break;
+
+ case LISTOBJ_REPLACE:
+ if (objc < 5) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "varIndex start count ?element...?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[3], &first) != TCL_OK
+ || Tcl_GetIntFromObj(interp, objv[4], &count) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_IsShared(varPtr[varIndex])) {
+ SetVarToObj(varIndex, Tcl_DuplicateObj(varPtr[varIndex]));
+ }
+ Tcl_ResetResult(interp);
+ return Tcl_ListObjReplace(interp, varPtr[varIndex], first, count,
+ objc-5, objv+5);
+ }
+ return TCL_OK;
+}
+
+/*
*----------------------------------------------------------------------
*
* TestobjCmd --
*
- * This procedure implements the "testobj" command. It is used to test
+ * This function implements the "testobj" command. It is used to test
* the type-independent portions of the Tcl object type implementation.
*
* Results:
@@ -702,16 +891,16 @@ TestintobjCmd(clientData, interp, objc, objv)
*/
static int
-TestobjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+TestobjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
int varIndex, destIndex, i;
char *index, *subCmd, *string;
Tcl_ObjType *targetType;
-
+
if (objc < 2) {
wrongNumArgs:
Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
@@ -751,7 +940,7 @@ TestobjCmd(clientData, interp, objc, objv)
typeName = Tcl_GetString(objv[3]);
if ((targetType = Tcl_GetObjType(typeName)) == NULL) {
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "no type ", typeName, " found", (char *) NULL);
+ "no type ", typeName, " found", NULL);
return TCL_ERROR;
}
if (Tcl_ConvertToType(interp, varPtr[varIndex], targetType)
@@ -810,13 +999,13 @@ TestobjCmd(clientData, interp, objc, objv)
SetVarToObj(varIndex, Tcl_NewObj());
Tcl_SetObjResult(interp, varPtr[varIndex]);
} else if (strcmp(subCmd, "objtype") == 0) {
- char *typeName;
+ const char *typeName;
/*
* return an object containing the name of the argument's type
* of internal rep. If none exists, return "none".
*/
-
+
if (objc != 3) {
goto wrongNumArgs;
}
@@ -868,11 +1057,9 @@ TestobjCmd(clientData, interp, objc, objv)
}
} else {
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "bad option \"",
- Tcl_GetString(objv[1]),
- "\": must be assign, convert, duplicate, freeallvars, ",
- "newobj, objcount, objtype, refcount, type, or types",
- (char *) NULL);
+ "bad option \"", Tcl_GetString(objv[1]),
+ "\": must be assign, convert, duplicate, freeallvars, "
+ "newobj, objcount, objtype, refcount, type, or types", NULL);
return TCL_ERROR;
}
return TCL_OK;
@@ -883,7 +1070,7 @@ TestobjCmd(clientData, interp, objc, objv)
*
* TeststringobjCmd --
*
- * This procedure implements the "teststringobj" command. It is used to
+ * This function implements the "teststringobj" command. It is used to
* test the string Tcl object type implementation.
*
* Results:
@@ -897,21 +1084,21 @@ TestobjCmd(clientData, interp, objc, objv)
*/
static int
-TeststringobjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+TeststringobjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
int varIndex, option, i, length;
Tcl_UniChar *unicode;
#define MAX_STRINGS 11
char *index, *string, *strings[MAX_STRINGS+1];
TestString *strPtr;
- static CONST char *options[] = {
+ static const char *options[] = {
"append", "appendstrings", "get", "get2", "length", "length2",
- "set", "set2", "setlength", "ualloc", "getunicode",
- "appendself", "appendself2", (char *) NULL
+ "set", "set2", "setlength", "ualloc", "getunicode",
+ "appendself", "appendself2", NULL
};
if (objc < 3) {
@@ -940,12 +1127,12 @@ TeststringobjCmd(clientData, interp, objc, objv)
if (varPtr[varIndex] == NULL) {
SetVarToObj(varIndex, Tcl_NewObj());
}
-
+
/*
* If the object bound to variable "varIndex" is shared, we must
- * "copy on write" and append to a copy of the object.
+ * "copy on write" and append to a copy of the object.
*/
-
+
if (Tcl_IsShared(varPtr[varIndex])) {
SetVarToObj(varIndex, Tcl_DuplicateObj(varPtr[varIndex]));
}
@@ -963,7 +1150,7 @@ TeststringobjCmd(clientData, interp, objc, objv)
/*
* If the object bound to variable "varIndex" is shared, we must
- * "copy on write" and append to a copy of the object.
+ * "copy on write" and append to a copy of the object.
*/
if (Tcl_IsShared(varPtr[varIndex])) {
@@ -1027,13 +1214,13 @@ TeststringobjCmd(clientData, interp, objc, objv)
/*
* If the object currently bound to the variable with index
- * varIndex has ref count 1 (i.e. the object is unshared) we
- * can modify that object directly. Otherwise, if RC>1 (i.e.
- * the object is shared), we must create a new object to
- * modify/set and decrement the old formerly-shared object's
- * ref count. This is "copy on write".
+ * varIndex has ref count 1 (i.e. the object is unshared) we can
+ * modify that object directly. Otherwise, if RC>1 (i.e. the
+ * object is shared), we must create a new object to modify/set
+ * and decrement the old formerly-shared object's ref count. This
+ * is "copy on write".
*/
-
+
string = Tcl_GetStringFromObj(objv[3], &length);
if ((varPtr[varIndex] != NULL)
&& !Tcl_IsShared(varPtr[varIndex])) {
@@ -1158,17 +1345,17 @@ TeststringobjCmd(clientData, interp, objc, objv)
* None.
*
* Side effects:
- * This routine handles ref counting details for assignment:
- * i.e. the old value's ref count must be decremented (if not NULL) and
- * the new one incremented (also if not NULL).
+ * This routine handles ref counting details for assignment: i.e. the old
+ * value's ref count must be decremented (if not NULL) and the new one
+ * incremented (also if not NULL).
*
*----------------------------------------------------------------------
*/
static void
-SetVarToObj(varIndex, objPtr)
- int varIndex; /* Designates the assignment variable. */
- Tcl_Obj *objPtr; /* Points to object to assign to var. */
+SetVarToObj(
+ int varIndex, /* Designates the assignment variable. */
+ Tcl_Obj *objPtr) /* Points to object to assign to var. */
{
if (varPtr[varIndex] != NULL) {
Tcl_DecrRefCount(varPtr[varIndex]);
@@ -1196,15 +1383,15 @@ SetVarToObj(varIndex, objPtr)
*/
static int
-GetVariableIndex(interp, string, indexPtr)
- Tcl_Interp *interp; /* Interpreter for error reporting. */
- char *string; /* String containing a variable index
- * specified as a nonnegative number less
- * than NUMBER_OF_OBJECT_VARS. */
- int *indexPtr; /* Place to store converted result. */
+GetVariableIndex(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ const char *string, /* String containing a variable index
+ * specified as a nonnegative number less than
+ * NUMBER_OF_OBJECT_VARS. */
+ int *indexPtr) /* Place to store converted result. */
{
int index;
-
+
if (Tcl_GetInt(interp, string, &index) != TCL_OK) {
return TCL_ERROR;
}
@@ -1223,7 +1410,7 @@ GetVariableIndex(interp, string, indexPtr)
*
* CheckIfVarUnset --
*
- * Utility procedure that checks whether a test variable is readable:
+ * Utility function that checks whether a test variable is readable:
* i.e., that varPtr[varIndex] is non-NULL.
*
* Results:
@@ -1237,13 +1424,13 @@ GetVariableIndex(interp, string, indexPtr)
*/
static int
-CheckIfVarUnset(interp, varIndex)
- Tcl_Interp *interp; /* Interpreter for error reporting. */
- int varIndex; /* Index of the test variable to check. */
+CheckIfVarUnset(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ int varIndex) /* Index of the test variable to check. */
{
if (varPtr[varIndex] == NULL) {
char buf[32 + TCL_INTEGER_SPACE];
-
+
sprintf(buf, "variable %d is unset (NULL)", varIndex);
Tcl_ResetResult(interp);
Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
@@ -1251,3 +1438,11 @@ CheckIfVarUnset(interp, varIndex)
}
return 0;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclTestProcBodyObj.c b/generic/tclTestProcBodyObj.c
index 5a17260..88bd1c3 100644
--- a/generic/tclTestProcBodyObj.c
+++ b/generic/tclTestProcBodyObj.c
@@ -1,14 +1,14 @@
-/*
+/*
* tclTestProcBodyObj.c --
*
- * Implements the "procbodytest" package, which contains commands
- * to test creation of Tcl procedures whose body argument is a
- * Tcl_Obj of type "procbody" rather than a string.
+ * Implements the "procbodytest" package, which contains commands to test
+ * creation of Tcl procedures whose body argument is a Tcl_Obj of type
+ * "procbody" rather than a string.
*
* Copyright (c) 1998 by Scriptics Corporation.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
@@ -42,31 +42,26 @@ typedef struct CmdTable
* Declarations for functions defined in this file.
*/
-static int ProcBodyTestProcObjCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-static int ProcBodyTestInitInternal _ANSI_ARGS_((Tcl_Interp *interp,
- int isSafe));
-static int RegisterCommand _ANSI_ARGS_((Tcl_Interp* interp,
- char *namespace, CONST CmdTable *cmdTablePtr));
-int Procbodytest_Init _ANSI_ARGS_((Tcl_Interp * interp));
-int Procbodytest_SafeInit _ANSI_ARGS_((Tcl_Interp * interp));
+static int ProcBodyTestProcObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
+static int ProcBodyTestInitInternal(Tcl_Interp *interp, int isSafe);
+static int RegisterCommand(Tcl_Interp* interp,
+ char *namespace, CONST CmdTable *cmdTablePtr);
+int Procbodytest_Init(Tcl_Interp * interp);
+int Procbodytest_SafeInit(Tcl_Interp * interp);
/*
* List of commands to create when the package is loaded; must go after the
* declarations of the enable command procedure.
*/
-static CONST CmdTable commands[] =
-{
+static CONST CmdTable commands[] = {
{ procCommand, ProcBodyTestProcObjCmd, 1 },
-
{ 0, 0, 0 }
};
-static CONST CmdTable safeCommands[] =
-{
+static CONST CmdTable safeCommands[] = {
{ procCommand, ProcBodyTestProcObjCmd, 1 },
-
{ 0, 0, 0 }
};
@@ -75,7 +70,7 @@ static CONST CmdTable safeCommands[] =
*
* Procbodytest_Init --
*
- * This procedure initializes the "procbodytest" package.
+ * This function initializes the "procbodytest" package.
*
* Results:
* A standard Tcl result.
@@ -87,8 +82,8 @@ static CONST CmdTable safeCommands[] =
*/
int
-Procbodytest_Init(interp)
- Tcl_Interp *interp; /* the Tcl interpreter for which the package
+Procbodytest_Init(
+ Tcl_Interp *interp) /* the Tcl interpreter for which the package
* is initialized */
{
return ProcBodyTestInitInternal(interp, 0);
@@ -99,7 +94,7 @@ Procbodytest_Init(interp)
*
* Procbodytest_SafeInit --
*
- * This procedure initializes the "procbodytest" package.
+ * This function initializes the "procbodytest" package.
*
* Results:
* A standard Tcl result.
@@ -111,8 +106,8 @@ Procbodytest_Init(interp)
*/
int
-Procbodytest_SafeInit(interp)
- Tcl_Interp *interp; /* the Tcl interpreter for which the package
+Procbodytest_SafeInit(
+ Tcl_Interp *interp) /* the Tcl interpreter for which the package
* is initialized */
{
return ProcBodyTestInitInternal(interp, 1);
@@ -123,7 +118,7 @@ Procbodytest_SafeInit(interp)
*
* RegisterCommand --
*
- * This procedure registers a command in the context of the given namespace.
+ * This function registers a command in the context of the given namespace.
*
* Results:
* A standard Tcl result.
@@ -135,11 +130,11 @@ Procbodytest_SafeInit(interp)
*/
static int RegisterCommand(interp, namespace, cmdTablePtr)
- Tcl_Interp* interp; /* the Tcl interpreter for which the
- * operation is performed */
- char *namespace; /* the namespace in which the command
- * is registered */
- CONST CmdTable *cmdTablePtr; /* the command to register */
+ Tcl_Interp* interp; /* the Tcl interpreter for which the operation
+ * is performed */
+ char *namespace; /* the namespace in which the command is
+ * registered */
+ CONST CmdTable *cmdTablePtr;/* the command to register */
{
char buf[128];
@@ -149,7 +144,7 @@ static int RegisterCommand(interp, namespace, cmdTablePtr)
if (Tcl_Eval(interp, buf) != TCL_OK)
return TCL_ERROR;
}
-
+
sprintf(buf, "%s::%s", namespace, cmdTablePtr->cmdName);
Tcl_CreateObjCommand(interp, buf, cmdTablePtr->proc, 0, 0);
@@ -161,7 +156,7 @@ static int RegisterCommand(interp, namespace, cmdTablePtr)
*
* ProcBodyTestInitInternal --
*
- * This procedure initializes the Loader package.
+ * This function initializes the Loader package.
* The isSafe flag is 1 if the interpreter is safe, 0 otherwise.
*
* Results:
@@ -174,10 +169,10 @@ static int RegisterCommand(interp, namespace, cmdTablePtr)
*/
static int
-ProcBodyTestInitInternal(interp, isSafe)
- Tcl_Interp *interp; /* the Tcl interpreter for which the package
+ProcBodyTestInitInternal(
+ Tcl_Interp *interp, /* the Tcl interpreter for which the package
* is initialized */
- int isSafe; /* 1 if this is a safe interpreter */
+ int isSafe) /* 1 if this is a safe interpreter */
{
CONST CmdTable *cmdTablePtr;
@@ -187,7 +182,7 @@ ProcBodyTestInitInternal(interp, isSafe)
return TCL_ERROR;
}
}
-
+
return Tcl_PkgProvide(interp, packageName, packageVersion);
}
@@ -225,20 +220,20 @@ ProcBodyTestInitInternal(interp, isSafe)
*/
static int
-ProcBodyTestProcObjCmd (dummy, interp, objc, objv)
- ClientData dummy; /* context; not used */
- Tcl_Interp *interp; /* the current interpreter */
- int objc; /* argument count */
- Tcl_Obj *CONST objv[]; /* arguments */
+ProcBodyTestProcObjCmd(
+ ClientData dummy, /* context; not used */
+ Tcl_Interp *interp, /* the current interpreter */
+ int objc, /* argument count */
+ Tcl_Obj *const objv[]) /* arguments */
{
char *fullName;
Tcl_Command procCmd;
Command *cmdPtr;
- Proc *procPtr = (Proc *) NULL;
+ Proc *procPtr = NULL;
Tcl_Obj *bodyObjPtr;
Tcl_Obj *myobjv[5];
int result;
-
+
if (objc != 4) {
Tcl_WrongNumArgs(interp, 1, objv, "newName argsList bodyName");
return TCL_ERROR;
@@ -247,10 +242,9 @@ ProcBodyTestProcObjCmd (dummy, interp, objc, objv)
/*
* Find the Command pointer to this procedure
*/
-
- fullName = Tcl_GetStringFromObj(objv[3], (int *) NULL);
- procCmd = Tcl_FindCommand(interp, fullName, (Tcl_Namespace *) NULL,
- TCL_LEAVE_ERR_MSG);
+
+ fullName = Tcl_GetStringFromObj(objv[3], NULL);
+ procCmd = Tcl_FindCommand(interp, fullName, NULL, TCL_LEAVE_ERR_MSG);
if (procCmd == NULL) {
return TCL_ERROR;
}
@@ -259,38 +253,27 @@ ProcBodyTestProcObjCmd (dummy, interp, objc, objv)
/*
* check that this is a procedure and not a builtin command:
- * If a procedure, cmdPtr->objProc is either 0 or TclObjInterpProc,
- * and cmdPtr->proc is either 0 or TclProcInterpProc.
- * Also, the compile proc should be 0, but we don't check for that.
+ * If a procedure, cmdPtr->objProc is TclObjInterpProc.
*/
- if (((cmdPtr->objProc != NULL)
- && (cmdPtr->objProc != TclGetObjInterpProc()))
- || ((cmdPtr->proc != NULL)
- && (cmdPtr->proc != TclGetInterpProc()))) {
+ if (cmdPtr->objProc != TclGetObjInterpProc()) {
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "command \"", fullName,
- "\" is not a Tcl procedure", (char *) NULL);
+ "command \"", fullName, "\" is not a Tcl procedure", NULL);
return TCL_ERROR;
}
/*
* it is a Tcl procedure: the client data is the Proc structure
*/
-
- if (cmdPtr->objProc != NULL) {
- procPtr = (Proc *) cmdPtr->objClientData;
- } else if (cmdPtr->proc != NULL) {
- procPtr = (Proc *) cmdPtr->clientData;
- }
+ procPtr = (Proc *) cmdPtr->objClientData;
if (procPtr == NULL) {
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
"procedure \"", fullName,
- "\" does not have a Proc struct!", (char *) NULL);
+ "\" does not have a Proc struct!", NULL);
return TCL_ERROR;
}
-
+
/*
* create a new object, initialize our argument vector, call into Tcl
*/
@@ -299,7 +282,7 @@ ProcBodyTestProcObjCmd (dummy, interp, objc, objv)
if (bodyObjPtr == NULL) {
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
"failed to create a procbody object for procedure \"",
- fullName, "\"", (char *) NULL);
+ fullName, "\"", NULL);
return TCL_ERROR;
}
Tcl_IncrRefCount(bodyObjPtr);
@@ -308,10 +291,18 @@ ProcBodyTestProcObjCmd (dummy, interp, objc, objv)
myobjv[1] = objv[1];
myobjv[2] = objv[2];
myobjv[3] = bodyObjPtr;
- myobjv[4] = (Tcl_Obj *) NULL;
+ myobjv[4] = NULL;
result = Tcl_ProcObjCmd((ClientData) NULL, interp, objc, myobjv);
Tcl_DecrRefCount(bodyObjPtr);
return result;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclThread.c b/generic/tclThread.c
index c2f769d..8384107 100644
--- a/generic/tclThread.c
+++ b/generic/tclThread.c
@@ -1,22 +1,21 @@
-/*
+/*
* tclThread.c --
*
- * This file implements Platform independent thread operations.
- * Most of the real work is done in the platform dependent files.
+ * This file implements Platform independent thread operations. Most of
+ * the real work is done in the platform dependent files.
*
* Copyright (c) 1998 by Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
/*
- * There are three classes of synchronization objects:
- * mutexes, thread data keys, and condition variables.
- * The following are used to record the memory used for these
- * objects so they can be finalized.
+ * There are three classes of synchronization objects: mutexes, thread data
+ * keys, and condition variables. The following are used to record the memory
+ * used for these objects so they can be finalized.
*
* These statics are guarded by the mutex in the caller of
* TclRememberThreadData, e.g., TclpThreadDataKeyInit
@@ -33,19 +32,19 @@ static SyncObjRecord mutexRecord = {0, 0, NULL};
static SyncObjRecord condRecord = {0, 0, NULL};
/*
- * Prototypes of functions used only in this file
+ * Prototypes of functions used only in this file.
*/
-
-static void RememberSyncObject _ANSI_ARGS_((char *objPtr,
- SyncObjRecord *recPtr));
-static void ForgetSyncObject _ANSI_ARGS_((char *objPtr,
- SyncObjRecord *recPtr));
-/*
+static void ForgetSyncObject(char *objPtr, SyncObjRecord *recPtr);
+static void RememberSyncObject(char *objPtr,
+ SyncObjRecord *recPtr);
+
+/*
* Several functions are #defined to nothing in tcl.h if TCL_THREADS is not
- * specified. Here we undo that so the procedures are defined in the
- * stubs table.
+ * specified. Here we undo that so the functions are defined in the stubs
+ * table.
*/
+
#ifndef TCL_THREADS
#undef Tcl_MutexLock
#undef Tcl_MutexUnlock
@@ -54,61 +53,51 @@ static void ForgetSyncObject _ANSI_ARGS_((char *objPtr,
#undef Tcl_ConditionWait
#undef Tcl_ConditionFinalize
#endif
-
/*
*----------------------------------------------------------------------
*
* Tcl_GetThreadData --
*
- * This procedure allocates and initializes a chunk of thread
- * local storage.
+ * This function allocates and initializes a chunk of thread local
+ * storage.
*
* Results:
* A thread-specific pointer to the data structure.
*
* Side effects:
- * Will allocate memory the first time this thread calls for
- * this chunk of storage.
+ * Will allocate memory the first time this thread calls for this chunk
+ * of storage.
*
*----------------------------------------------------------------------
*/
-VOID *
-Tcl_GetThreadData(keyPtr, size)
- Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk */
- int size; /* Size of storage block */
+void *
+Tcl_GetThreadData(
+ Tcl_ThreadDataKey *keyPtr, /* Identifier for the data chunk */
+ int size) /* Size of storage block */
{
- VOID *result;
+ void *result;
#ifdef TCL_THREADS
-
- /*
- * See if this is the first thread to init this key.
- */
-
- if (*keyPtr == NULL) {
- TclpThreadDataKeyInit(keyPtr);
- }
-
/*
* Initialize the key for this thread.
*/
-
result = TclpThreadDataKeyGet(keyPtr);
+
if (result == NULL) {
- result = (VOID *)ckalloc((size_t)size);
- memset(result, 0, (size_t)size);
+ result = ckalloc((size_t) size);
+ memset(result, 0, (size_t) size);
TclpThreadDataKeySet(keyPtr, result);
}
-#else
+#else /* TCL_THREADS */
if (*keyPtr == NULL) {
- result = (VOID *)ckalloc((size_t)size);
- memset((char *)result, 0, (size_t)size);
+ result = ckalloc((size_t) size);
+ memset(result, 0, (size_t) size);
*keyPtr = (Tcl_ThreadDataKey)result;
- TclRememberDataKey(keyPtr);
+ RememberSyncObject((char *) keyPtr, &keyRecord);
}
- result = *(VOID **)keyPtr;
-#endif
+ result = * (void **) keyPtr;
+#endif /* TCL_THREADS */
return result;
}
@@ -117,11 +106,11 @@ Tcl_GetThreadData(keyPtr, size)
*
* TclThreadDataKeyGet --
*
- * This procedure returns a pointer to a block of thread local storage.
+ * This function returns a pointer to a block of thread local storage.
*
* Results:
- * A thread-specific pointer to the data structure, or NULL
- * if the memory has not been assigned to this key for this thread.
+ * A thread-specific pointer to the data structure, or NULL if the memory
+ * has not been assigned to this key for this thread.
*
* Side effects:
* None.
@@ -129,61 +118,27 @@ Tcl_GetThreadData(keyPtr, size)
*----------------------------------------------------------------------
*/
-VOID *
-TclThreadDataKeyGet(keyPtr)
- Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
- * really (pthread_key_t **) */
-{
-#ifdef TCL_THREADS
- return (VOID *)TclpThreadDataKeyGet(keyPtr);
-#else
- char *result = *(char **)keyPtr;
- return (VOID *)result;
-#endif /* TCL_THREADS */
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TclThreadDataKeySet --
- *
- * This procedure sets a thread local storage pointer.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The assigned value will be returned by TclpThreadDataKeyGet.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclThreadDataKeySet(keyPtr, data)
- Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
- * really (pthread_key_t **) */
- VOID *data; /* Thread local storage */
+void *
+TclThreadDataKeyGet(
+ Tcl_ThreadDataKey *keyPtr) /* Identifier for the data chunk, really
+ * (pthread_key_t **) */
{
#ifdef TCL_THREADS
- if (*keyPtr == NULL) {
- TclpThreadDataKeyInit(keyPtr);
- }
- TclpThreadDataKeySet(keyPtr, data);
-#else
- *keyPtr = (Tcl_ThreadDataKey)data;
+ return TclpThreadDataKeyGet(keyPtr);
+#else /* TCL_THREADS */
+ char *result = *(char **) keyPtr;
+ return result;
#endif /* TCL_THREADS */
}
-
/*
*----------------------------------------------------------------------
*
* RememberSyncObject
*
- * Keep a list of (mutexes/condition variable/data key)
- * used during finalization.
+ * Keep a list of (mutexes/condition variable/data key) used during
+ * finalization.
*
* Assume master lock is held.
*
@@ -197,22 +152,23 @@ TclThreadDataKeySet(keyPtr, data)
*/
static void
-RememberSyncObject(objPtr, recPtr)
- char *objPtr; /* Pointer to sync object */
- SyncObjRecord *recPtr; /* Record of sync objects */
+RememberSyncObject(
+ char *objPtr, /* Pointer to sync object */
+ SyncObjRecord *recPtr) /* Record of sync objects */
{
char **newList;
int i, j;
+
/*
- * Reuse any free slot in the list.
+ * Reuse any free slot in the list.
*/
for (i=0 ; i < recPtr->num ; ++i) {
if (recPtr->list[i] == NULL) {
recPtr->list[i] = objPtr;
return;
- }
+ }
}
/*
@@ -222,14 +178,14 @@ RememberSyncObject(objPtr, recPtr)
if (recPtr->num >= recPtr->max) {
recPtr->max += 8;
- newList = (char **)ckalloc(recPtr->max * sizeof(char *));
- for (i=0, j=0 ; i < recPtr->num ; i++) {
- if (recPtr->list[i] != NULL) {
+ newList = (char **) ckalloc(recPtr->max * sizeof(char *));
+ for (i=0,j=0 ; i<recPtr->num ; i++) {
+ if (recPtr->list[i] != NULL) {
newList[j++] = recPtr->list[i];
- }
+ }
}
if (recPtr->list != NULL) {
- ckfree((char *)recPtr->list);
+ ckfree((char *) recPtr->list);
}
recPtr->list = newList;
recPtr->num = j;
@@ -244,7 +200,7 @@ RememberSyncObject(objPtr, recPtr)
*
* ForgetSyncObject
*
- * Remove a single object from the list.
+ * Remove a single object from the list.
* Assume master lock is held.
*
* Results:
@@ -257,9 +213,9 @@ RememberSyncObject(objPtr, recPtr)
*/
static void
-ForgetSyncObject(objPtr, recPtr)
- char *objPtr; /* Pointer to sync object */
- SyncObjRecord *recPtr; /* Record of sync objects */
+ForgetSyncObject(
+ char *objPtr, /* Pointer to sync object */
+ SyncObjRecord *recPtr) /* Record of sync objects */
{
int i;
@@ -276,7 +232,7 @@ ForgetSyncObject(objPtr, recPtr)
*
* TclRememberMutex
*
- * Keep a list of mutexes used during finalization.
+ * Keep a list of mutexes used during finalization.
* Assume master lock is held.
*
* Results:
@@ -289,8 +245,8 @@ ForgetSyncObject(objPtr, recPtr)
*/
void
-TclRememberMutex(mutexPtr)
- Tcl_Mutex *mutexPtr;
+TclRememberMutex(
+ Tcl_Mutex *mutexPtr)
{
RememberSyncObject((char *)mutexPtr, &mutexRecord);
}
@@ -298,10 +254,10 @@ TclRememberMutex(mutexPtr)
/*
*----------------------------------------------------------------------
*
- * Tcl_MutexFinalize
+ * Tcl_MutexFinalize --
*
- * Finalize a single mutex and remove it from the
- * list of remembered objects.
+ * Finalize a single mutex and remove it from the list of remembered
+ * objects.
*
* Results:
* None.
@@ -313,47 +269,23 @@ TclRememberMutex(mutexPtr)
*/
void
-Tcl_MutexFinalize(mutexPtr)
- Tcl_Mutex *mutexPtr;
+Tcl_MutexFinalize(
+ Tcl_Mutex *mutexPtr)
{
#ifdef TCL_THREADS
TclpFinalizeMutex(mutexPtr);
#endif
TclpMasterLock();
- ForgetSyncObject((char *)mutexPtr, &mutexRecord);
+ ForgetSyncObject((char *) mutexPtr, &mutexRecord);
TclpMasterUnlock();
}
/*
*----------------------------------------------------------------------
*
- * TclRememberDataKey
- *
- * Keep a list of thread data keys used during finalization.
- * Assume master lock is held.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Add to the key list.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclRememberDataKey(keyPtr)
- Tcl_ThreadDataKey *keyPtr;
-{
- RememberSyncObject((char *)keyPtr, &keyRecord);
-}
-
-/*
- *----------------------------------------------------------------------
- *
* TclRememberCondition
*
- * Keep a list of condition variables used during finalization.
+ * Keep a list of condition variables used during finalization.
* Assume master lock is held.
*
* Results:
@@ -366,19 +298,19 @@ TclRememberDataKey(keyPtr)
*/
void
-TclRememberCondition(condPtr)
- Tcl_Condition *condPtr;
+TclRememberCondition(
+ Tcl_Condition *condPtr)
{
- RememberSyncObject((char *)condPtr, &condRecord);
+ RememberSyncObject((char *) condPtr, &condRecord);
}
/*
*----------------------------------------------------------------------
*
- * Tcl_ConditionFinalize
+ * Tcl_ConditionFinalize --
*
- * Finalize a single condition variable and remove it from the
- * list of remembered objects.
+ * Finalize a single condition variable and remove it from the list of
+ * remembered objects.
*
* Results:
* None.
@@ -390,14 +322,14 @@ TclRememberCondition(condPtr)
*/
void
-Tcl_ConditionFinalize(condPtr)
- Tcl_Condition *condPtr;
+Tcl_ConditionFinalize(
+ Tcl_Condition *condPtr)
{
#ifdef TCL_THREADS
TclpFinalizeCondition(condPtr);
#endif
TclpMasterLock();
- ForgetSyncObject((char *)condPtr, &condRecord);
+ ForgetSyncObject((char *) condPtr, &condRecord);
TclpMasterUnlock();
}
@@ -406,8 +338,8 @@ Tcl_ConditionFinalize(condPtr)
*
* TclFinalizeThreadData --
*
- * This procedure cleans up the thread-local storage. This is
- * called once for each thread.
+ * This function cleans up the thread-local storage. This is called once
+ * for each thread.
*
* Results:
* None.
@@ -419,24 +351,9 @@ Tcl_ConditionFinalize(condPtr)
*/
void
-TclFinalizeThreadData()
+TclFinalizeThreadData(void)
{
- int i;
- Tcl_ThreadDataKey *keyPtr;
-
- TclpMasterLock();
- for (i=0 ; i<keyRecord.num ; i++) {
- keyPtr = (Tcl_ThreadDataKey *) keyRecord.list[i];
-#ifdef TCL_THREADS
- TclpFinalizeThreadData(keyPtr);
-#else
- if (*keyPtr != NULL) {
- ckfree((char *)*keyPtr);
- *keyPtr = NULL;
- }
-#endif
- }
- TclpMasterUnlock();
+ TclpFinalizeThreadDataThread();
}
/*
@@ -444,8 +361,8 @@ TclFinalizeThreadData()
*
* TclFinalizeSynchronization --
*
- * This procedure cleans up all synchronization objects:
- * mutexes, condition variables, and thread-local storage.
+ * This function cleans up all synchronization objects: mutexes,
+ * condition variables, and thread-local storage.
*
* Results:
* None.
@@ -457,25 +374,41 @@ TclFinalizeThreadData()
*/
void
-TclFinalizeSynchronization()
+TclFinalizeSynchronization(void)
{
-#ifdef TCL_THREADS
+ int i;
+ void *blockPtr;
Tcl_ThreadDataKey *keyPtr;
+#ifdef TCL_THREADS
Tcl_Mutex *mutexPtr;
Tcl_Condition *condPtr;
- int i;
TclpMasterLock();
- for (i=0 ; i<keyRecord.num ; i++) {
- keyPtr = (Tcl_ThreadDataKey *)keyRecord.list[i];
- TclpFinalizeThreadDataKey(keyPtr);
- }
+#endif
+
+ /*
+ * If we're running unthreaded, the TSD blocks are simply stored inside
+ * their thread data keys. Free them here.
+ */
+
if (keyRecord.list != NULL) {
- ckfree((char *)keyRecord.list);
+ for (i=0 ; i<keyRecord.num ; i++) {
+ keyPtr = (Tcl_ThreadDataKey *) keyRecord.list[i];
+ blockPtr = (void *) *keyPtr;
+ ckfree(blockPtr);
+ }
+ ckfree((char *) keyRecord.list);
keyRecord.list = NULL;
}
keyRecord.max = 0;
keyRecord.num = 0;
+
+#ifdef TCL_THREADS
+ /*
+ * Call thread storage master cleanup.
+ */
+
+ TclFinalizeThreadStorage();
for (i=0 ; i<mutexRecord.num ; i++) {
mutexPtr = (Tcl_Mutex *)mutexRecord.list[i];
@@ -484,45 +417,37 @@ TclFinalizeSynchronization()
}
}
if (mutexRecord.list != NULL) {
- ckfree((char *)mutexRecord.list);
+ ckfree((char *) mutexRecord.list);
mutexRecord.list = NULL;
}
mutexRecord.max = 0;
mutexRecord.num = 0;
for (i=0 ; i<condRecord.num ; i++) {
- condPtr = (Tcl_Condition *)condRecord.list[i];
+ condPtr = (Tcl_Condition *) condRecord.list[i];
if (condPtr != NULL) {
TclpFinalizeCondition(condPtr);
}
}
if (condRecord.list != NULL) {
- ckfree((char *)condRecord.list);
+ ckfree((char *) condRecord.list);
condRecord.list = NULL;
}
condRecord.max = 0;
condRecord.num = 0;
TclpMasterUnlock();
-#else
- if (keyRecord.list != NULL) {
- ckfree((char *)keyRecord.list);
- keyRecord.list = NULL;
- }
- keyRecord.max = 0;
- keyRecord.num = 0;
-#endif
+#endif /* TCL_THREADS */
}
-
/*
*----------------------------------------------------------------------
*
* Tcl_ExitThread --
*
- * This procedure is called to terminate the current thread.
- * This should be used by extensions that create threads with
- * additional interpreters in them.
+ * This function is called to terminate the current thread. This should
+ * be used by extensions that create threads with additional interpreters
+ * in them.
*
* Results:
* None.
@@ -534,8 +459,8 @@ TclFinalizeSynchronization()
*/
void
-Tcl_ExitThread(status)
- int status;
+Tcl_ExitThread(
+ int status)
{
Tcl_FinalizeThread();
#ifdef TCL_THREADS
@@ -550,10 +475,9 @@ Tcl_ExitThread(status)
*
* Tcl_ConditionWait, et al. --
*
- * These noop procedures are provided so the stub table does
- * not have to be conditionalized for threads. The real
- * implementations of these functions live in the platform
- * specific files.
+ * These noop functions are provided so the stub table does not have to
+ * be conditionalized for threads. The real implementations of these
+ * functions live in the platform specific files.
*
* Results:
* None.
@@ -566,31 +490,39 @@ Tcl_ExitThread(status)
#undef Tcl_ConditionWait
void
-Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
- Tcl_Condition *condPtr; /* Really (pthread_cond_t **) */
- Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */
- Tcl_Time *timePtr; /* Timeout on waiting period */
+Tcl_ConditionWait(
+ Tcl_Condition *condPtr, /* Really (pthread_cond_t **) */
+ Tcl_Mutex *mutexPtr, /* Really (pthread_mutex_t **) */
+ Tcl_Time *timePtr) /* Timeout on waiting period */
{
}
#undef Tcl_ConditionNotify
void
-Tcl_ConditionNotify(condPtr)
- Tcl_Condition *condPtr;
+Tcl_ConditionNotify(
+ Tcl_Condition *condPtr)
{
}
#undef Tcl_MutexLock
void
-Tcl_MutexLock(mutexPtr)
- Tcl_Mutex *mutexPtr;
+Tcl_MutexLock(
+ Tcl_Mutex *mutexPtr)
{
}
#undef Tcl_MutexUnlock
void
-Tcl_MutexUnlock(mutexPtr)
- Tcl_Mutex *mutexPtr;
+Tcl_MutexUnlock(
+ Tcl_Mutex *mutexPtr)
{
}
-#endif
+#endif /* !TCL_THREADS */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclThreadAlloc.c b/generic/tclThreadAlloc.c
index ad9f0a0..bea85bd 100755..100644
--- a/generic/tclThreadAlloc.c
+++ b/generic/tclThreadAlloc.c
@@ -2,31 +2,22 @@
* tclThreadAlloc.c --
*
* This is a very fast storage allocator for used with threads (designed
- * avoid lock contention). The basic strategy is to allocate memory in
- * fixed size blocks from block caches.
- *
+ * avoid lock contention). The basic strategy is to allocate memory in
+ * fixed size blocks from block caches.
+ *
* The Initial Developer of the Original Code is America Online, Inc.
* Portions created by AOL are Copyright (C) 1999 America Online, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-
-#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) && !defined(TCL_MEM_DEBUG)
-
-#ifdef WIN32
-#include "tclWinInt.h"
-#else
-extern Tcl_Mutex *TclpNewAllocMutex(void);
-extern void *TclpGetAllocCache(void);
-extern void TclpSetAllocCache(void *);
-#endif
+#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
/*
- * If range checking is enabled, an additional byte will be allocated
- * to store the magic number at the end of the requested memory.
+ * If range checking is enabled, an additional byte will be allocated to store
+ * the magic number at the end of the requested memory.
*/
#ifndef RCHECK
@@ -38,33 +29,21 @@ extern void TclpSetAllocCache(void *);
#endif
/*
- * The following define the number of Tcl_Obj's to allocate/move
- * at a time and the high water mark to prune a per-thread cache.
- * On a 32 bit system, sizeof(Tcl_Obj) = 24 so 800 * 24 = ~16k.
- *
+ * The following define the number of Tcl_Obj's to allocate/move at a time and
+ * the high water mark to prune a per-thread cache. On a 32 bit system,
+ * sizeof(Tcl_Obj) = 24 so 800 * 24 = ~16k.
*/
-
-#define NOBJALLOC 800
+
+#define NOBJALLOC 800
#define NOBJHIGH 1200
/*
- * Alignment for allocated memory.
+ * The following union stores accounting information for each block including
+ * two small magic numbers and a bucket number when in use or a next pointer
+ * when free. The original requested size (not including the Block overhead)
+ * is also maintained.
*/
-#if defined(__APPLE__)
-#define ALLOCALIGN 16
-#else
-#define ALLOCALIGN 8
-#endif
-
-/*
- * The following union stores accounting information for
- * each block including two small magic numbers and
- * a bucket number when in use or a next pointer when
- * free. The original requested size (not including
- * the Block overhead) is also maintained.
- */
-
typedef union Block {
struct {
union {
@@ -78,93 +57,95 @@ typedef union Block {
} u;
size_t reqSize; /* Requested allocation size. */
} b;
- unsigned char padding[ALLOCALIGN];
+ unsigned char padding[TCL_ALLOCALIGN];
} Block;
-#define b_next b.u.next
-#define b_bucket b.u.s.bucket
-#define b_magic1 b.u.s.magic1
-#define b_magic2 b.u.s.magic2
-#define MAGIC 0xef
-#define b_reqsize b.reqSize
+#define nextBlock b.u.next
+#define sourceBucket b.u.s.bucket
+#define magicNum1 b.u.s.magic1
+#define magicNum2 b.u.s.magic2
+#define MAGIC 0xEF
+#define blockReqSize b.reqSize
/*
* The following defines the minimum and and maximum block sizes and the number
* of buckets in the bucket cache.
*/
-#define MINALLOC ((sizeof(Block) + 8 + (ALLOCALIGN-1)) & ~(ALLOCALIGN-1))
+#define MINALLOC ((sizeof(Block) + 8 + (TCL_ALLOCALIGN-1)) & ~(TCL_ALLOCALIGN-1))
#define NBUCKETS (11 - (MINALLOC >> 5))
#define MAXALLOC (MINALLOC << (NBUCKETS - 1))
/*
- * The following structure defines a bucket of blocks with
- * various accounting and statistics information.
+ * The following structure defines a bucket of blocks with various accounting
+ * and statistics information.
*/
typedef struct Bucket {
- Block *firstPtr;
- long nfree;
- long nget;
- long nput;
- long nwait;
- long nlock;
- long nrequest;
+ Block *firstPtr; /* First block available */
+ long numFree; /* Number of blocks available */
+
+ /* All fields below for accounting only */
+
+ long numRemoves; /* Number of removes from bucket */
+ long numInserts; /* Number of inserts into bucket */
+ long numWaits; /* Number of waits to acquire a lock */
+ long numLocks; /* Number of locks acquired */
+ long totalAssigned; /* Total space assigned to bucket */
} Bucket;
/*
- * The following structure defines a cache of buckets and objs.
+ * The following structure defines a cache of buckets and objs, of which there
+ * will be (at most) one per thread.
*/
typedef struct Cache {
- struct Cache *nextPtr;
- Tcl_ThreadId owner;
- Tcl_Obj *firstObjPtr;
- int nobjs;
- int nsysalloc;
- Bucket buckets[NBUCKETS];
+ struct Cache *nextPtr; /* Linked list of cache entries */
+ Tcl_ThreadId owner; /* Which thread's cache is this? */
+ Tcl_Obj *firstObjPtr; /* List of free objects for thread */
+ int numObjects; /* Number of objects for thread */
+ int totalAssigned; /* Total space assigned to thread */
+ Bucket buckets[NBUCKETS]; /* The buckets for this thread */
} Cache;
/*
- * The following array specifies various per-bucket
- * limits and locks. The values are statically initialized
- * to avoid calculating them repeatedly.
+ * The following array specifies various per-bucket limits and locks. The
+ * values are statically initialized to avoid calculating them repeatedly.
*/
-struct binfo {
- size_t blocksize; /* Bucket blocksize. */
- int maxblocks; /* Max blocks before move to share. */
- int nmove; /* Num blocks to move to share. */
- Tcl_Mutex *lockPtr; /* Share bucket lock. */
-} binfo[NBUCKETS];
+static struct {
+ size_t blockSize; /* Bucket blocksize. */
+ int maxBlocks; /* Max blocks before move to share. */
+ int numMove; /* Num blocks to move to share. */
+ Tcl_Mutex *lockPtr; /* Share bucket lock. */
+} bucketInfo[NBUCKETS];
/*
* Static functions defined in this file.
*/
-static void LockBucket(Cache *cachePtr, int bucket);
-static void UnlockBucket(Cache *cachePtr, int bucket);
-static void PutBlocks(Cache *cachePtr, int bucket, int nmove);
-static int GetBlocks(Cache *cachePtr, int bucket);
-static Block *Ptr2Block(char *ptr);
-static char *Block2Ptr(Block *blockPtr, int bucket, unsigned int reqsize);
-static void MoveObjs(Cache *fromPtr, Cache *toPtr, int nmove);
+static Cache * GetCache(void);
+static void LockBucket(Cache *cachePtr, int bucket);
+static void UnlockBucket(Cache *cachePtr, int bucket);
+static void PutBlocks(Cache *cachePtr, int bucket, int numMove);
+static int GetBlocks(Cache *cachePtr, int bucket);
+static Block * Ptr2Block(char *ptr);
+static char * Block2Ptr(Block *blockPtr, int bucket, unsigned int reqSize);
+static void MoveObjs(Cache *fromPtr, Cache *toPtr, int numMove);
/*
- * Local variables defined in this file and initialized at
- * startup.
+ * Local variables defined in this file and initialized at startup.
*/
static Tcl_Mutex *listLockPtr;
static Tcl_Mutex *objLockPtr;
-static Cache sharedCache;
-static Cache *sharedPtr = &sharedCache;
-static Cache *firstCachePtr = &sharedCache;
-
+static Cache sharedCache;
+static Cache *sharedPtr = &sharedCache;
+static Cache *firstCachePtr = &sharedCache;
/*
*----------------------------------------------------------------------
*
- * GetCache ---
+ * GetCache ---
*
* Gets per-thread memory cache, allocating it if necessary.
*
@@ -172,7 +153,7 @@ static Cache *firstCachePtr = &sharedCache;
* Pointer to cache.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
@@ -196,10 +177,11 @@ GetCache(void)
listLockPtr = TclpNewAllocMutex();
objLockPtr = TclpNewAllocMutex();
for (i = 0; i < NBUCKETS; ++i) {
- binfo[i].blocksize = MINALLOC << i;
- binfo[i].maxblocks = 1 << (NBUCKETS - 1 - i);
- binfo[i].nmove = i < NBUCKETS-1 ? 1 << (NBUCKETS - 2 - i) : 1;
- binfo[i].lockPtr = TclpNewAllocMutex();
+ bucketInfo[i].blockSize = MINALLOC << i;
+ bucketInfo[i].maxBlocks = 1 << (NBUCKETS - 1 - i);
+ bucketInfo[i].numMove = i < NBUCKETS - 1 ?
+ 1 << (NBUCKETS - 2 - i) : 1;
+ bucketInfo[i].lockPtr = TclpNewAllocMutex();
}
}
Tcl_MutexUnlock(initLockPtr);
@@ -211,25 +193,24 @@ GetCache(void)
cachePtr = TclpGetAllocCache();
if (cachePtr == NULL) {
- cachePtr = calloc(1, sizeof(Cache));
- if (cachePtr == NULL) {
- panic("alloc: could not allocate new cache");
- }
- Tcl_MutexLock(listLockPtr);
- cachePtr->nextPtr = firstCachePtr;
- firstCachePtr = cachePtr;
- Tcl_MutexUnlock(listLockPtr);
- cachePtr->owner = Tcl_GetCurrentThread();
+ cachePtr = calloc(1, sizeof(Cache));
+ if (cachePtr == NULL) {
+ Tcl_Panic("alloc: could not allocate new cache");
+ }
+ Tcl_MutexLock(listLockPtr);
+ cachePtr->nextPtr = firstCachePtr;
+ firstCachePtr = cachePtr;
+ Tcl_MutexUnlock(listLockPtr);
+ cachePtr->owner = Tcl_GetCurrentThread();
TclpSetAllocCache(cachePtr);
}
return cachePtr;
}
-
/*
*----------------------------------------------------------------------
*
- * TclFreeAllocCache --
+ * TclFreeAllocCache --
*
* Flush and delete a cache, removing from list of caches.
*
@@ -243,7 +224,8 @@ GetCache(void)
*/
void
-TclFreeAllocCache(void *arg)
+TclFreeAllocCache(
+ void *arg)
{
Cache *cachePtr = arg;
Cache **nextPtrPtr;
@@ -254,8 +236,8 @@ TclFreeAllocCache(void *arg)
*/
for (bucket = 0; bucket < NBUCKETS; ++bucket) {
- if (cachePtr->buckets[bucket].nfree > 0) {
- PutBlocks(cachePtr, bucket, cachePtr->buckets[bucket].nfree);
+ if (cachePtr->buckets[bucket].numFree > 0) {
+ PutBlocks(cachePtr, bucket, cachePtr->buckets[bucket].numFree);
}
}
@@ -263,10 +245,10 @@ TclFreeAllocCache(void *arg)
* Flush objs.
*/
- if (cachePtr->nobjs > 0) {
- Tcl_MutexLock(objLockPtr);
- MoveObjs(cachePtr, sharedPtr, cachePtr->nobjs);
- Tcl_MutexUnlock(objLockPtr);
+ if (cachePtr->numObjects > 0) {
+ Tcl_MutexLock(objLockPtr);
+ MoveObjs(cachePtr, sharedPtr, cachePtr->numObjects);
+ Tcl_MutexUnlock(objLockPtr);
}
/*
@@ -283,12 +265,11 @@ TclFreeAllocCache(void *arg)
Tcl_MutexUnlock(listLockPtr);
free(cachePtr);
}
-
/*
*----------------------------------------------------------------------
*
- * TclpAlloc --
+ * TclpAlloc --
*
* Allocate memory.
*
@@ -302,19 +283,20 @@ TclFreeAllocCache(void *arg)
*/
char *
-TclpAlloc(unsigned int reqsize)
+TclpAlloc(
+ unsigned int reqSize)
{
- Cache *cachePtr;
- Block *blockPtr;
- register int bucket;
- size_t size;
+ Cache *cachePtr;
+ Block *blockPtr;
+ register int bucket;
+ size_t size;
if (sizeof(int) >= sizeof(size_t)) {
/* An unsigned int overflow can also be a size_t overflow */
const size_t zero = 0;
const size_t max = ~zero;
- if (((size_t) reqsize) > max - sizeof(Block) - RCHECK) {
+ if (((size_t) reqSize) > max - sizeof(Block) - RCHECK) {
/* Requested allocation exceeds memory */
return NULL;
}
@@ -324,50 +306,48 @@ TclpAlloc(unsigned int reqsize)
if (cachePtr == NULL) {
cachePtr = GetCache();
}
-
+
/*
- * Increment the requested size to include room for
- * the Block structure. Call malloc() directly if the
- * required amount is greater than the largest block,
- * otherwise pop the smallest block large enough,
+ * Increment the requested size to include room for the Block structure.
+ * Call malloc() directly if the required amount is greater than the
+ * largest block, otherwise pop the smallest block large enough,
* allocating more blocks if necessary.
*/
- blockPtr = NULL;
- size = reqsize + sizeof(Block);
+ blockPtr = NULL;
+ size = reqSize + sizeof(Block);
#if RCHECK
++size;
#endif
if (size > MAXALLOC) {
bucket = NBUCKETS;
- blockPtr = malloc(size);
+ blockPtr = malloc(size);
if (blockPtr != NULL) {
- cachePtr->nsysalloc += reqsize;
+ cachePtr->totalAssigned += reqSize;
}
} else {
- bucket = 0;
- while (binfo[bucket].blocksize < size) {
- ++bucket;
- }
- if (cachePtr->buckets[bucket].nfree || GetBlocks(cachePtr, bucket)) {
+ bucket = 0;
+ while (bucketInfo[bucket].blockSize < size) {
+ ++bucket;
+ }
+ if (cachePtr->buckets[bucket].numFree || GetBlocks(cachePtr, bucket)) {
blockPtr = cachePtr->buckets[bucket].firstPtr;
- cachePtr->buckets[bucket].firstPtr = blockPtr->b_next;
- --cachePtr->buckets[bucket].nfree;
- ++cachePtr->buckets[bucket].nget;
- cachePtr->buckets[bucket].nrequest += reqsize;
+ cachePtr->buckets[bucket].firstPtr = blockPtr->nextBlock;
+ --cachePtr->buckets[bucket].numFree;
+ ++cachePtr->buckets[bucket].numRemoves;
+ cachePtr->buckets[bucket].totalAssigned += reqSize;
}
}
if (blockPtr == NULL) {
- return NULL;
+ return NULL;
}
- return Block2Ptr(blockPtr, bucket, reqsize);
+ return Block2Ptr(blockPtr, bucket, reqSize);
}
-
/*
*----------------------------------------------------------------------
*
- * TclpFree --
+ * TclpFree --
*
* Return blocks to the thread block cache.
*
@@ -381,49 +361,52 @@ TclpAlloc(unsigned int reqsize)
*/
void
-TclpFree(char *ptr)
+TclpFree(
+ char *ptr)
{
- if (ptr != NULL) {
- Cache *cachePtr = TclpGetAllocCache();
- Block *blockPtr;
- int bucket;
+ Cache *cachePtr;
+ Block *blockPtr;
+ int bucket;
- if (cachePtr == NULL) {
- cachePtr = GetCache();
- }
-
- /*
- * Get the block back from the user pointer and
- * call system free directly for large blocks.
- * Otherwise, push the block back on the bucket and
- * move blocks to the shared cache if there are now
- * too many free.
- */
+ if (ptr == NULL) {
+ return;
+ }
- blockPtr = Ptr2Block(ptr);
- bucket = blockPtr->b_bucket;
- if (bucket == NBUCKETS) {
- cachePtr->nsysalloc -= blockPtr->b_reqsize;
- free(blockPtr);
- } else {
- cachePtr->buckets[bucket].nrequest -= blockPtr->b_reqsize;
- blockPtr->b_next = cachePtr->buckets[bucket].firstPtr;
- cachePtr->buckets[bucket].firstPtr = blockPtr;
- ++cachePtr->buckets[bucket].nfree;
- ++cachePtr->buckets[bucket].nput;
- if (cachePtr != sharedPtr &&
- cachePtr->buckets[bucket].nfree > binfo[bucket].maxblocks) {
- PutBlocks(cachePtr, bucket, binfo[bucket].nmove);
- }
- }
+ cachePtr = TclpGetAllocCache();
+ if (cachePtr == NULL) {
+ cachePtr = GetCache();
}
-}
+ /*
+ * Get the block back from the user pointer and call system free directly
+ * for large blocks. Otherwise, push the block back on the bucket and move
+ * blocks to the shared cache if there are now too many free.
+ */
+
+ blockPtr = Ptr2Block(ptr);
+ bucket = blockPtr->sourceBucket;
+ if (bucket == NBUCKETS) {
+ cachePtr->totalAssigned -= blockPtr->blockReqSize;
+ free(blockPtr);
+ return;
+ }
+
+ cachePtr->buckets[bucket].totalAssigned -= blockPtr->blockReqSize;
+ blockPtr->nextBlock = cachePtr->buckets[bucket].firstPtr;
+ cachePtr->buckets[bucket].firstPtr = blockPtr;
+ ++cachePtr->buckets[bucket].numFree;
+ ++cachePtr->buckets[bucket].numInserts;
+
+ if (cachePtr != sharedPtr &&
+ cachePtr->buckets[bucket].numFree > bucketInfo[bucket].maxBlocks) {
+ PutBlocks(cachePtr, bucket, bucketInfo[bucket].numMove);
+ }
+}
/*
*----------------------------------------------------------------------
*
- * TclpRealloc --
+ * TclpRealloc --
*
* Re-allocate memory to a larger or smaller size.
*
@@ -437,16 +420,18 @@ TclpFree(char *ptr)
*/
char *
-TclpRealloc(char *ptr, unsigned int reqsize)
+TclpRealloc(
+ char *ptr,
+ unsigned int reqSize)
{
Cache *cachePtr;
Block *blockPtr;
- void *new;
+ void *newPtr;
size_t size, min;
int bucket;
if (ptr == NULL) {
- return TclpAlloc(reqsize);
+ return TclpAlloc(reqSize);
}
if (sizeof(int) >= sizeof(size_t)) {
@@ -454,7 +439,7 @@ TclpRealloc(char *ptr, unsigned int reqsize)
const size_t zero = 0;
const size_t max = ~zero;
- if (((size_t) reqsize) > max - sizeof(Block) - RCHECK) {
+ if (((size_t) reqSize) > max - sizeof(Block) - RCHECK) {
/* Requested allocation exceeds memory */
return NULL;
}
@@ -466,54 +451,52 @@ TclpRealloc(char *ptr, unsigned int reqsize)
}
/*
- * If the block is not a system block and fits in place,
- * simply return the existing pointer. Otherwise, if the block
- * is a system block and the new size would also require a system
- * block, call realloc() directly.
+ * If the block is not a system block and fits in place, simply return the
+ * existing pointer. Otherwise, if the block is a system block and the new
+ * size would also require a system block, call realloc() directly.
*/
blockPtr = Ptr2Block(ptr);
- size = reqsize + sizeof(Block);
+ size = reqSize + sizeof(Block);
#if RCHECK
++size;
#endif
- bucket = blockPtr->b_bucket;
+ bucket = blockPtr->sourceBucket;
if (bucket != NBUCKETS) {
if (bucket > 0) {
- min = binfo[bucket-1].blocksize;
+ min = bucketInfo[bucket-1].blockSize;
} else {
min = 0;
}
- if (size > min && size <= binfo[bucket].blocksize) {
- cachePtr->buckets[bucket].nrequest -= blockPtr->b_reqsize;
- cachePtr->buckets[bucket].nrequest += reqsize;
- return Block2Ptr(blockPtr, bucket, reqsize);
+ if (size > min && size <= bucketInfo[bucket].blockSize) {
+ cachePtr->buckets[bucket].totalAssigned -= blockPtr->blockReqSize;
+ cachePtr->buckets[bucket].totalAssigned += reqSize;
+ return Block2Ptr(blockPtr, bucket, reqSize);
}
} else if (size > MAXALLOC) {
- cachePtr->nsysalloc -= blockPtr->b_reqsize;
- cachePtr->nsysalloc += reqsize;
+ cachePtr->totalAssigned -= blockPtr->blockReqSize;
+ cachePtr->totalAssigned += reqSize;
blockPtr = realloc(blockPtr, size);
if (blockPtr == NULL) {
return NULL;
}
- return Block2Ptr(blockPtr, NBUCKETS, reqsize);
+ return Block2Ptr(blockPtr, NBUCKETS, reqSize);
}
/*
* Finally, perform an expensive malloc/copy/free.
*/
- new = TclpAlloc(reqsize);
- if (new != NULL) {
- if (reqsize > blockPtr->b_reqsize) {
- reqsize = blockPtr->b_reqsize;
+ newPtr = TclpAlloc(reqSize);
+ if (newPtr != NULL) {
+ if (reqSize > blockPtr->blockReqSize) {
+ reqSize = blockPtr->blockReqSize;
}
- memcpy(new, ptr, reqsize);
- TclpFree(ptr);
+ memcpy(newPtr, ptr, reqSize);
+ TclpFree(ptr);
}
- return new;
+ return newPtr;
}
-
/*
*----------------------------------------------------------------------
@@ -526,8 +509,8 @@ TclpRealloc(char *ptr, unsigned int reqsize)
* Pointer to uninitialized Tcl_Obj.
*
* Side effects:
- * May move Tcl_Obj's from shared cached or allocate new Tcl_Obj's
- * if list is empty.
+ * May move Tcl_Obj's from shared cached or allocate new Tcl_Obj's if
+ * list is empty.
*
*----------------------------------------------------------------------
*/
@@ -536,37 +519,39 @@ Tcl_Obj *
TclThreadAllocObj(void)
{
register Cache *cachePtr = TclpGetAllocCache();
- register int nmove;
register Tcl_Obj *objPtr;
- Tcl_Obj *newObjsPtr;
if (cachePtr == NULL) {
cachePtr = GetCache();
}
/*
- * Get this thread's obj list structure and move
- * or allocate new objs if necessary.
+ * Get this thread's obj list structure and move or allocate new objs if
+ * necessary.
*/
-
- if (cachePtr->nobjs == 0) {
- Tcl_MutexLock(objLockPtr);
- nmove = sharedPtr->nobjs;
- if (nmove > 0) {
- if (nmove > NOBJALLOC) {
- nmove = NOBJALLOC;
+
+ if (cachePtr->numObjects == 0) {
+ register int numMove;
+
+ Tcl_MutexLock(objLockPtr);
+ numMove = sharedPtr->numObjects;
+ if (numMove > 0) {
+ if (numMove > NOBJALLOC) {
+ numMove = NOBJALLOC;
}
- MoveObjs(sharedPtr, cachePtr, nmove);
+ MoveObjs(sharedPtr, cachePtr, numMove);
}
- Tcl_MutexUnlock(objLockPtr);
- if (cachePtr->nobjs == 0) {
- cachePtr->nobjs = nmove = NOBJALLOC;
- newObjsPtr = malloc(sizeof(Tcl_Obj) * nmove);
+ Tcl_MutexUnlock(objLockPtr);
+ if (cachePtr->numObjects == 0) {
+ Tcl_Obj *newObjsPtr;
+
+ cachePtr->numObjects = numMove = NOBJALLOC;
+ newObjsPtr = malloc(sizeof(Tcl_Obj) * numMove);
if (newObjsPtr == NULL) {
- panic("alloc: could not allocate %d new objects", nmove);
+ Tcl_Panic("alloc: could not allocate %d new objects", numMove);
}
- while (--nmove >= 0) {
- objPtr = &newObjsPtr[nmove];
+ while (--numMove >= 0) {
+ objPtr = &newObjsPtr[numMove];
objPtr->internalRep.otherValuePtr = cachePtr->firstObjPtr;
cachePtr->firstObjPtr = objPtr;
}
@@ -579,10 +564,9 @@ TclThreadAllocObj(void)
objPtr = cachePtr->firstObjPtr;
cachePtr->firstObjPtr = objPtr->internalRep.otherValuePtr;
- --cachePtr->nobjs;
+ --cachePtr->numObjects;
return objPtr;
}
-
/*
*----------------------------------------------------------------------
@@ -595,14 +579,14 @@ TclThreadAllocObj(void)
* None.
*
* Side effects:
- * May move free Tcl_Obj's to shared list upon hitting high
- * water mark.
+ * May move free Tcl_Obj's to shared list upon hitting high water mark.
*
*----------------------------------------------------------------------
*/
void
-TclThreadFreeObj(Tcl_Obj *objPtr)
+TclThreadFreeObj(
+ Tcl_Obj *objPtr)
{
Cache *cachePtr = TclpGetAllocCache();
@@ -613,23 +597,22 @@ TclThreadFreeObj(Tcl_Obj *objPtr)
/*
* Get this thread's list and push on the free Tcl_Obj.
*/
-
+
objPtr->internalRep.otherValuePtr = cachePtr->firstObjPtr;
cachePtr->firstObjPtr = objPtr;
- ++cachePtr->nobjs;
-
+ ++cachePtr->numObjects;
+
/*
- * If the number of free objects has exceeded the high
- * water mark, move some blocks to the shared list.
+ * If the number of free objects has exceeded the high water mark, move
+ * some blocks to the shared list.
*/
-
- if (cachePtr->nobjs > NOBJHIGH) {
+
+ if (cachePtr->numObjects > NOBJHIGH) {
Tcl_MutexLock(objLockPtr);
MoveObjs(cachePtr, sharedPtr, NOBJALLOC);
Tcl_MutexUnlock(objLockPtr);
}
}
-
/*
*----------------------------------------------------------------------
@@ -642,13 +625,14 @@ TclThreadFreeObj(Tcl_Obj *objPtr)
* None.
*
* Side effects:
- * List appended to given dstring.
+ * List appended to given dstring.
*
*----------------------------------------------------------------------
*/
void
-Tcl_GetMemoryInfo(Tcl_DString *dsPtr)
+Tcl_GetMemoryInfo(
+ Tcl_DString *dsPtr)
{
Cache *cachePtr;
char buf[200];
@@ -659,28 +643,27 @@ Tcl_GetMemoryInfo(Tcl_DString *dsPtr)
while (cachePtr != NULL) {
Tcl_DStringStartSublist(dsPtr);
if (cachePtr == sharedPtr) {
- Tcl_DStringAppendElement(dsPtr, "shared");
+ Tcl_DStringAppendElement(dsPtr, "shared");
} else {
- sprintf(buf, "thread%d", (int) cachePtr->owner);
- Tcl_DStringAppendElement(dsPtr, buf);
+ sprintf(buf, "thread%p", cachePtr->owner);
+ Tcl_DStringAppendElement(dsPtr, buf);
}
for (n = 0; n < NBUCKETS; ++n) {
- sprintf(buf, "%lu %ld %ld %ld %ld %ld %ld",
- (unsigned long) binfo[n].blocksize,
- cachePtr->buckets[n].nfree,
- cachePtr->buckets[n].nget,
- cachePtr->buckets[n].nput,
- cachePtr->buckets[n].nrequest,
- cachePtr->buckets[n].nlock,
- cachePtr->buckets[n].nwait);
+ sprintf(buf, "%lu %ld %ld %ld %ld %ld %ld",
+ (unsigned long) bucketInfo[n].blockSize,
+ cachePtr->buckets[n].numFree,
+ cachePtr->buckets[n].numRemoves,
+ cachePtr->buckets[n].numInserts,
+ cachePtr->buckets[n].totalAssigned,
+ cachePtr->buckets[n].numLocks,
+ cachePtr->buckets[n].numWaits);
Tcl_DStringAppendElement(dsPtr, buf);
}
Tcl_DStringEndSublist(dsPtr);
- cachePtr = cachePtr->nextPtr;
+ cachePtr = cachePtr->nextPtr;
}
Tcl_MutexUnlock(listLockPtr);
}
-
/*
*----------------------------------------------------------------------
@@ -693,45 +676,46 @@ Tcl_GetMemoryInfo(Tcl_DString *dsPtr)
* None.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
static void
-MoveObjs(Cache *fromPtr, Cache *toPtr, int nmove)
+MoveObjs(
+ Cache *fromPtr,
+ Cache *toPtr,
+ int numMove)
{
register Tcl_Obj *objPtr = fromPtr->firstObjPtr;
Tcl_Obj *fromFirstObjPtr = objPtr;
- toPtr->nobjs += nmove;
- fromPtr->nobjs -= nmove;
+ toPtr->numObjects += numMove;
+ fromPtr->numObjects -= numMove;
/*
- * Find the last object to be moved; set the next one
- * (the first one not to be moved) as the first object
- * in the 'from' cache.
+ * Find the last object to be moved; set the next one (the first one not
+ * to be moved) as the first object in the 'from' cache.
*/
- while (--nmove) {
+ while (--numMove) {
objPtr = objPtr->internalRep.otherValuePtr;
}
- fromPtr->firstObjPtr = objPtr->internalRep.otherValuePtr;
+ fromPtr->firstObjPtr = objPtr->internalRep.otherValuePtr;
/*
- * Move all objects as a block - they are already linked to
- * each other, we just have to update the first and last.
+ * Move all objects as a block - they are already linked to each other, we
+ * just have to update the first and last.
*/
objPtr->internalRep.otherValuePtr = toPtr->firstObjPtr;
toPtr->firstObjPtr = fromFirstObjPtr;
}
-
/*
*----------------------------------------------------------------------
*
- * Block2Ptr, Ptr2Block --
+ * Block2Ptr, Ptr2Block --
*
* Convert between internal blocks and user pointers.
*
@@ -745,84 +729,91 @@ MoveObjs(Cache *fromPtr, Cache *toPtr, int nmove)
*/
static char *
-Block2Ptr(Block *blockPtr, int bucket, unsigned int reqsize)
+Block2Ptr(
+ Block *blockPtr,
+ int bucket,
+ unsigned int reqSize)
{
register void *ptr;
- blockPtr->b_magic1 = blockPtr->b_magic2 = MAGIC;
- blockPtr->b_bucket = bucket;
- blockPtr->b_reqsize = reqsize;
+ blockPtr->magicNum1 = blockPtr->magicNum2 = MAGIC;
+ blockPtr->sourceBucket = bucket;
+ blockPtr->blockReqSize = reqSize;
ptr = ((void *) (blockPtr + 1));
#if RCHECK
- ((unsigned char *)(ptr))[reqsize] = MAGIC;
+ ((unsigned char *)(ptr))[reqSize] = MAGIC;
#endif
return (char *) ptr;
}
static Block *
-Ptr2Block(char *ptr)
+Ptr2Block(
+ char *ptr)
{
register Block *blockPtr;
blockPtr = (((Block *) ptr) - 1);
- if (blockPtr->b_magic1 != MAGIC
+ if (blockPtr->magicNum1 != MAGIC || blockPtr->magicNum2 != MAGIC) {
+ Tcl_Panic("alloc: invalid block: %p: %x %x",
+ blockPtr, blockPtr->magicNum1, blockPtr->magicNum2);
+ }
#if RCHECK
- || ((unsigned char *) ptr)[blockPtr->b_reqsize] != MAGIC
-#endif
- || blockPtr->b_magic2 != MAGIC) {
- panic("alloc: invalid block: %p: %x %x %x\n",
- blockPtr, blockPtr->b_magic1, blockPtr->b_magic2,
- ((unsigned char *) ptr)[blockPtr->b_reqsize]);
+ if (((unsigned char *) ptr)[blockPtr->blockReqSize] != MAGIC) {
+ Tcl_Panic("alloc: invalid block: %p: %x %x %x",
+ blockPtr, blockPtr->magicNum1, blockPtr->magicNum2,
+ ((unsigned char *) ptr)[blockPtr->blockReqSize]);
}
+#endif
return blockPtr;
}
-
/*
*----------------------------------------------------------------------
*
- * LockBucket, UnlockBucket --
+ * LockBucket, UnlockBucket --
*
* Set/unset the lock to access a bucket in the shared cache.
*
* Results:
- * None.
+ * None.
*
* Side effects:
- * Lock activity and contention are monitored globally and on
- * a per-cache basis.
+ * Lock activity and contention are monitored globally and on a per-cache
+ * basis.
*
*----------------------------------------------------------------------
*/
static void
-LockBucket(Cache *cachePtr, int bucket)
+LockBucket(
+ Cache *cachePtr,
+ int bucket)
{
#if 0
- if (Tcl_MutexTryLock(binfo[bucket].lockPtr) != TCL_OK) {
- Tcl_MutexLock(binfo[bucket].lockPtr);
- ++cachePtr->buckets[bucket].nwait;
- ++sharedPtr->buckets[bucket].nwait;
+ if (Tcl_MutexTryLock(bucketInfo[bucket].lockPtr) != TCL_OK) {
+ Tcl_MutexLock(bucketInfo[bucket].lockPtr);
+ ++cachePtr->buckets[bucket].numWaits;
+ ++sharedPtr->buckets[bucket].numWaits;
}
#else
- Tcl_MutexLock(binfo[bucket].lockPtr);
+ Tcl_MutexLock(bucketInfo[bucket].lockPtr);
#endif
- ++cachePtr->buckets[bucket].nlock;
- ++sharedPtr->buckets[bucket].nlock;
+ ++cachePtr->buckets[bucket].numLocks;
+ ++sharedPtr->buckets[bucket].numLocks;
}
-
static void
-UnlockBucket(Cache *cachePtr, int bucket)
+UnlockBucket(
+ Cache *cachePtr,
+ int bucket)
{
- Tcl_MutexUnlock(binfo[bucket].lockPtr);
+ Tcl_MutexUnlock(bucketInfo[bucket].lockPtr);
}
-
/*
*----------------------------------------------------------------------
*
- * PutBlocks --
+ * PutBlocks --
*
* Return unused blocks to the shared cache.
*
@@ -836,40 +827,42 @@ UnlockBucket(Cache *cachePtr, int bucket)
*/
static void
-PutBlocks(Cache *cachePtr, int bucket, int nmove)
+PutBlocks(
+ Cache *cachePtr,
+ int bucket,
+ int numMove)
{
register Block *lastPtr, *firstPtr;
- register int n = nmove;
+ register int n = numMove;
/*
- * Before acquiring the lock, walk the block list to find
- * the last block to be moved.
+ * Before acquiring the lock, walk the block list to find the last block
+ * to be moved.
*/
firstPtr = lastPtr = cachePtr->buckets[bucket].firstPtr;
while (--n > 0) {
- lastPtr = lastPtr->b_next;
+ lastPtr = lastPtr->nextBlock;
}
- cachePtr->buckets[bucket].firstPtr = lastPtr->b_next;
- cachePtr->buckets[bucket].nfree -= nmove;
+ cachePtr->buckets[bucket].firstPtr = lastPtr->nextBlock;
+ cachePtr->buckets[bucket].numFree -= numMove;
/*
- * Aquire the lock and place the list of blocks at the front
- * of the shared cache bucket.
+ * Aquire the lock and place the list of blocks at the front of the shared
+ * cache bucket.
*/
LockBucket(cachePtr, bucket);
- lastPtr->b_next = sharedPtr->buckets[bucket].firstPtr;
+ lastPtr->nextBlock = sharedPtr->buckets[bucket].firstPtr;
sharedPtr->buckets[bucket].firstPtr = firstPtr;
- sharedPtr->buckets[bucket].nfree += nmove;
+ sharedPtr->buckets[bucket].numFree += numMove;
UnlockBucket(cachePtr, bucket);
}
-
/*
*----------------------------------------------------------------------
*
- * GetBlocks --
+ * GetBlocks --
*
* Get more blocks for a bucket.
*
@@ -883,67 +876,69 @@ PutBlocks(Cache *cachePtr, int bucket, int nmove)
*/
static int
-GetBlocks(Cache *cachePtr, int bucket)
+GetBlocks(
+ Cache *cachePtr,
+ int bucket)
{
register Block *blockPtr;
register int n;
- register size_t size;
/*
- * First, atttempt to move blocks from the shared cache. Note
- * the potentially dirty read of nfree before acquiring the lock
- * which is a slight performance enhancement. The value is
- * verified after the lock is actually acquired.
+ * First, atttempt to move blocks from the shared cache. Note the
+ * potentially dirty read of numFree before acquiring the lock which is a
+ * slight performance enhancement. The value is verified after the lock is
+ * actually acquired.
*/
-
- if (cachePtr != sharedPtr && sharedPtr->buckets[bucket].nfree > 0) {
+
+ if (cachePtr != sharedPtr && sharedPtr->buckets[bucket].numFree > 0) {
LockBucket(cachePtr, bucket);
- if (sharedPtr->buckets[bucket].nfree > 0) {
+ if (sharedPtr->buckets[bucket].numFree > 0) {
/*
- * Either move the entire list or walk the list to find
- * the last block to move.
+ * Either move the entire list or walk the list to find the last
+ * block to move.
*/
- n = binfo[bucket].nmove;
- if (n >= sharedPtr->buckets[bucket].nfree) {
+ n = bucketInfo[bucket].numMove;
+ if (n >= sharedPtr->buckets[bucket].numFree) {
cachePtr->buckets[bucket].firstPtr =
- sharedPtr->buckets[bucket].firstPtr;
- cachePtr->buckets[bucket].nfree =
- sharedPtr->buckets[bucket].nfree;
+ sharedPtr->buckets[bucket].firstPtr;
+ cachePtr->buckets[bucket].numFree =
+ sharedPtr->buckets[bucket].numFree;
sharedPtr->buckets[bucket].firstPtr = NULL;
- sharedPtr->buckets[bucket].nfree = 0;
+ sharedPtr->buckets[bucket].numFree = 0;
} else {
blockPtr = sharedPtr->buckets[bucket].firstPtr;
cachePtr->buckets[bucket].firstPtr = blockPtr;
- sharedPtr->buckets[bucket].nfree -= n;
- cachePtr->buckets[bucket].nfree = n;
+ sharedPtr->buckets[bucket].numFree -= n;
+ cachePtr->buckets[bucket].numFree = n;
while (--n > 0) {
- blockPtr = blockPtr->b_next;
+ blockPtr = blockPtr->nextBlock;
}
- sharedPtr->buckets[bucket].firstPtr = blockPtr->b_next;
- blockPtr->b_next = NULL;
+ sharedPtr->buckets[bucket].firstPtr = blockPtr->nextBlock;
+ blockPtr->nextBlock = NULL;
}
}
UnlockBucket(cachePtr, bucket);
}
-
- if (cachePtr->buckets[bucket].nfree == 0) {
+
+ if (cachePtr->buckets[bucket].numFree == 0) {
+ register size_t size;
/*
- * If no blocks could be moved from shared, first look for a
- * larger block in this cache to split up.
+ * If no blocks could be moved from shared, first look for a larger
+ * block in this cache to split up.
*/
- blockPtr = NULL;
+ blockPtr = NULL;
n = NBUCKETS;
size = 0; /* lint */
while (--n > bucket) {
- if (cachePtr->buckets[n].nfree > 0) {
- size = binfo[n].blocksize;
+ if (cachePtr->buckets[n].numFree > 0) {
+ size = bucketInfo[n].blockSize;
blockPtr = cachePtr->buckets[n].firstPtr;
- cachePtr->buckets[n].firstPtr = blockPtr->b_next;
- --cachePtr->buckets[n].nfree;
+ cachePtr->buckets[n].firstPtr = blockPtr->nextBlock;
+ --cachePtr->buckets[n].numFree;
break;
}
}
@@ -964,26 +959,26 @@ GetBlocks(Cache *cachePtr, int bucket)
* Split the larger block into smaller blocks for this bucket.
*/
- n = size / binfo[bucket].blocksize;
- cachePtr->buckets[bucket].nfree = n;
+ n = size / bucketInfo[bucket].blockSize;
+ cachePtr->buckets[bucket].numFree = n;
cachePtr->buckets[bucket].firstPtr = blockPtr;
while (--n > 0) {
- blockPtr->b_next = (Block *)
- ((char *) blockPtr + binfo[bucket].blocksize);
- blockPtr = blockPtr->b_next;
+ blockPtr->nextBlock = (Block *)
+ ((char *) blockPtr + bucketInfo[bucket].blockSize);
+ blockPtr = blockPtr->nextBlock;
}
- blockPtr->b_next = NULL;
+ blockPtr->nextBlock = NULL;
}
return 1;
}
-
+
/*
*----------------------------------------------------------------------
*
* TclFinalizeThreadAlloc --
*
- * This procedure is used to destroy all private resources used in
- * this file.
+ * This procedure is used to destroy all private resources used in this
+ * file.
*
* Results:
* None.
@@ -995,13 +990,13 @@ GetBlocks(Cache *cachePtr, int bucket)
*/
void
-TclFinalizeThreadAlloc()
+TclFinalizeThreadAlloc(void)
{
unsigned int i;
for (i = 0; i < NBUCKETS; ++i) {
- TclpFreeAllocMutex(binfo[i].lockPtr);
- binfo[i].lockPtr = NULL;
+ TclpFreeAllocMutex(bucketInfo[i].lockPtr);
+ bucketInfo[i].lockPtr = NULL;
}
TclpFreeAllocMutex(objLockPtr);
@@ -1013,15 +1008,37 @@ TclFinalizeThreadAlloc()
TclpFreeAllocCache(NULL);
}
-#else /* ! defined(TCL_THREADS) && ! defined(USE_THREAD_ALLOC) */
+#else /* !(TCL_THREADS && USE_THREAD_ALLOC) */
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetMemoryInfo --
+ *
+ * Return a list-of-lists of memory stats.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * List appended to given dstring.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+Tcl_GetMemoryInfo(
+ Tcl_DString *dsPtr)
+{
+ Tcl_Panic("Tcl_GetMemoryInfo called when threaded memory allocator not in use");
+}
+
/*
*----------------------------------------------------------------------
*
* TclFinalizeThreadAlloc --
*
- * This procedure is used to destroy all private resources used in
- * this file.
+ * This procedure is used to destroy all private resources used in this
+ * file.
*
* Results:
* None.
@@ -1033,9 +1050,16 @@ TclFinalizeThreadAlloc()
*/
void
-TclFinalizeThreadAlloc()
+TclFinalizeThreadAlloc(void)
{
- Tcl_Panic("TclFinalizeThreadAlloc called when threaded memory allocator not in use.");
+ Tcl_Panic("TclFinalizeThreadAlloc called when threaded memory allocator not in use");
}
-
-#endif /* TCL_THREADS */
+#endif /* TCL_THREADS && USE_THREAD_ALLOC */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclThreadJoin.c b/generic/tclThreadJoin.c
index f3c6abd..3a905b5 100644
--- a/generic/tclThreadJoin.c
+++ b/generic/tclThreadJoin.c
@@ -1,69 +1,66 @@
-/*
+/*
* tclThreadJoin.c --
*
- * This file implements a platform independent emulation layer for
- * the handling of joinable threads. The Mac and Windows platforms
- * use this code to provide the functionality of joining threads.
- * This code is currently not necessary on Unix.
+ * This file implements a platform independent emulation layer for the
+ * handling of joinable threads. The Windows platform uses this code to
+ * provide the functionality of joining threads. This code is currently
+ * not necessary on Unix.
*
* Copyright (c) 2000 by Scriptics Corporation
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#if defined(WIN32) || defined(MAC_TCL)
+#ifdef WIN32
-/* The information about each joinable thread is remembered in a
- * structure as defined below.
+/*
+ * The information about each joinable thread is remembered in a structure as
+ * defined below.
*/
typedef struct JoinableThread {
- Tcl_ThreadId id; /* The id of the joinable thread */
- int result; /* A place for the result after the
- * demise of the thread */
- int done; /* Boolean flag. Initialized to 0
- * and set to 1 after the exit of
- * the thread. This allows a thread
- * requesting a join to detect when
- * waiting is not necessary. */
- int waitedUpon; /* Boolean flag. Initialized to 0
- * and set to 1 by the thread waiting
- * for this one via Tcl_JoinThread.
- * Used to lock any other thread
- * trying to wait on this one.
- */
- Tcl_Mutex threadMutex; /* The mutex used to serialize access
- * to this structure. */
- Tcl_Condition cond; /* This is the condition a thread has
- * to wait upon to get notified of the
- * end of the described thread. It is
- * signaled indirectly by
- * Tcl_ExitThread. */
- struct JoinableThread* nextThreadPtr; /* Reference to the next thread in the
- * list of joinable threads */
+ Tcl_ThreadId id; /* The id of the joinable thread. */
+ int result; /* A place for the result after the demise of
+ * the thread. */
+ int done; /* Boolean flag. Initialized to 0 and set to 1
+ * after the exit of the thread. This allows a
+ * thread requesting a join to detect when
+ * waiting is not necessary. */
+ int waitedUpon; /* Boolean flag. Initialized to 0 and set to 1
+ * by the thread waiting for this one via
+ * Tcl_JoinThread. Used to lock any other
+ * thread trying to wait on this one. */
+ Tcl_Mutex threadMutex; /* The mutex used to serialize access to this
+ * structure. */
+ Tcl_Condition cond; /* This is the condition a thread has to wait
+ * upon to get notified of the end of the
+ * described thread. It is signaled indirectly
+ * by Tcl_ExitThread. */
+ struct JoinableThread *nextThreadPtr;
+ /* Reference to the next thread in the list of
+ * joinable threads. */
} JoinableThread;
-/* The following variable is used to maintain the global list of all
- * joinable threads. Usage by a thread is allowed only if the
- * thread acquired the 'joinMutex'.
+/*
+ * The following variable is used to maintain the global list of all joinable
+ * threads. Usage by a thread is allowed only if the thread acquired the
+ * 'joinMutex'.
*/
TCL_DECLARE_MUTEX(joinMutex)
static JoinableThread* firstThreadPtr;
-
-
/*
*----------------------------------------------------------------------
*
* TclJoinThread --
*
- * This procedure waits for the exit of the thread with the specified
- * id and returns its result.
+ * This procedure waits for the exit of the thread with the specified id
+ * and returns its result.
*
* Results:
* A standard tcl result signaling the overall success/failure of the
@@ -72,135 +69,139 @@ static JoinableThread* firstThreadPtr;
*
* Side effects:
* Deallocates the memory allocated by TclRememberJoinableThread.
- * Removes the data associated to the thread waited upon from the
- * list of joinable threads.
+ * Removes the data associated to the thread waited upon from the list of
+ * joinable threads.
*
*----------------------------------------------------------------------
*/
int
-TclJoinThread(id, result)
- Tcl_ThreadId id; /* The id of the thread to wait upon. */
- int* result; /* Reference to a location for the result
- * of the thread we are waiting upon. */
+TclJoinThread(
+ Tcl_ThreadId id, /* The id of the thread to wait upon. */
+ int *result) /* Reference to a location for the result of
+ * the thread we are waiting upon. */
{
- /* Steps done here:
+ JoinableThread *threadPtr;
+
+ /*
+ * Steps done here:
* i. Acquire the joinMutex and search for the thread.
* ii. Error out if it could not be found.
* iii. If found, switch from exclusive access to the list to exclusive
- * access to the thread structure.
+ * access to the thread structure.
* iv. Error out if some other is already waiting.
* v. Skip the waiting part of the thread is already done.
* vi. Wait for the thread to exit, mark it as waited upon too.
- * vii. Get the result form the structure,
+ * vii. Get the result form the structure,
* viii. switch to exclusive access of the list,
* ix. remove the structure from the list,
* x. then switch back to exclusive access to the structure
* xi. and delete it.
*/
- JoinableThread* threadPtr;
+ Tcl_MutexLock(&joinMutex);
- Tcl_MutexLock (&joinMutex);
-
- for (threadPtr = firstThreadPtr;
- (threadPtr != (JoinableThread*) NULL) && (threadPtr->id != id);
- threadPtr = threadPtr->nextThreadPtr)
- /* empty body */
- ;
+ threadPtr = firstThreadPtr;
+ while (threadPtr!=NULL && threadPtr->id!=id) {
+ threadPtr = threadPtr->nextThreadPtr;
+ }
- if (threadPtr == (JoinableThread*) NULL) {
- /* Thread not found. Either not joinable, or already waited
- * upon and exited. Whatever, an error is in order.
+ if (threadPtr == NULL) {
+ /*
+ * Thread not found. Either not joinable, or already waited upon and
+ * exited. Whatever, an error is in order.
*/
- Tcl_MutexUnlock (&joinMutex);
- return TCL_ERROR;
+ Tcl_MutexUnlock(&joinMutex);
+ return TCL_ERROR;
}
- /* [1] If we don't lock the structure before giving up exclusive access
- * to the list some other thread just completing its wait on the same
- * thread can delete the structure from under us, leaving us with a
- * dangling pointer.
+ /*
+ * [1] If we don't lock the structure before giving up exclusive access to
+ * the list some other thread just completing its wait on the same thread
+ * can delete the structure from under us, leaving us with a dangling
+ * pointer.
*/
- Tcl_MutexLock (&threadPtr->threadMutex);
- Tcl_MutexUnlock (&joinMutex);
+ Tcl_MutexLock(&threadPtr->threadMutex);
+ Tcl_MutexUnlock(&joinMutex);
- /* [2] Now that we have the structure mutex any other thread that just
- * tries to delete structure will wait at location [3] until we are
- * done with the structure. And in that case we are done with it
- * rather quickly as 'waitedUpon' will be set and we will have to
- * error out.
+ /*
+ * [2] Now that we have the structure mutex any other thread that just
+ * tries to delete structure will wait at location [3] until we are done
+ * with the structure. And in that case we are done with it rather quickly
+ * as 'waitedUpon' will be set and we will have to error out.
*/
if (threadPtr->waitedUpon) {
- Tcl_MutexUnlock (&threadPtr->threadMutex);
+ Tcl_MutexUnlock(&threadPtr->threadMutex);
return TCL_ERROR;
}
- /* We are waiting now, let other threads recognize this
+ /*
+ * We are waiting now, let other threads recognize this.
*/
threadPtr->waitedUpon = 1;
while (!threadPtr->done) {
- Tcl_ConditionWait (&threadPtr->cond, &threadPtr->threadMutex, NULL);
+ Tcl_ConditionWait(&threadPtr->cond, &threadPtr->threadMutex, NULL);
}
- /* We have to release the structure before trying to access the list
- * again or we can run into deadlock with a thread at [1] (see above)
- * because of us holding the structure and the other holding the list.
- * There is no problem with dangling pointers here as 'waitedUpon == 1'
- * is still valid and any other thread will error out and not come to
- * this place. IOW, the fact that we are here also means that no other
- * thread came here before us and is able to delete the structure.
+ /*
+ * We have to release the structure before trying to access the list again
+ * or we can run into deadlock with a thread at [1] (see above) because of
+ * us holding the structure and the other holding the list. There is no
+ * problem with dangling pointers here as 'waitedUpon == 1' is still valid
+ * and any other thread will error out and not come to this place. IOW,
+ * the fact that we are here also means that no other thread came here
+ * before us and is able to delete the structure.
*/
- Tcl_MutexUnlock (&threadPtr->threadMutex);
- Tcl_MutexLock (&joinMutex);
+ Tcl_MutexUnlock(&threadPtr->threadMutex);
+ Tcl_MutexLock(&joinMutex);
- /* We have to search the list again as its structure may (may, almost
+ /*
+ * We have to search the list again as its structure may (may, almost
* certainly) have changed while we were waiting. Especially now is the
- * time to compute the predecessor in the list. Any earlier result can
- * be dangling by now.
+ * time to compute the predecessor in the list. Any earlier result can be
+ * dangling by now.
*/
if (firstThreadPtr == threadPtr) {
- firstThreadPtr = threadPtr->nextThreadPtr;
+ firstThreadPtr = threadPtr->nextThreadPtr;
} else {
- JoinableThread* prevThreadPtr;
-
- for (prevThreadPtr = firstThreadPtr;
- prevThreadPtr->nextThreadPtr != threadPtr;
- prevThreadPtr = prevThreadPtr->nextThreadPtr)
- /* empty body */
- ;
+ JoinableThread *prevThreadPtr = firstThreadPtr;
+ while (prevThreadPtr->nextThreadPtr != threadPtr) {
+ prevThreadPtr = prevThreadPtr->nextThreadPtr;
+ }
prevThreadPtr->nextThreadPtr = threadPtr->nextThreadPtr;
}
- Tcl_MutexUnlock (&joinMutex);
+ Tcl_MutexUnlock(&joinMutex);
- /* [3] Now that the structure is not part of the list anymore no other
+ /*
+ * [3] Now that the structure is not part of the list anymore no other
* thread can acquire its mutex from now on. But it is possible that
- * another thread is still holding the mutex though, see location [2].
- * So we have to acquire the mutex one more time to wait for that thread
- * to finish. We can (and have to) release the mutex immediately.
+ * another thread is still holding the mutex though, see location [2]. So
+ * we have to acquire the mutex one more time to wait for that thread to
+ * finish. We can (and have to) release the mutex immediately.
*/
- Tcl_MutexLock (&threadPtr->threadMutex);
- Tcl_MutexUnlock (&threadPtr->threadMutex);
+ Tcl_MutexLock(&threadPtr->threadMutex);
+ Tcl_MutexUnlock(&threadPtr->threadMutex);
- /* Copy the result to us, finalize the synchronisation objects, then
- * free the structure and return.
+ /*
+ * Copy the result to us, finalize the synchronisation objects, then free
+ * the structure and return.
*/
*result = threadPtr->result;
- Tcl_ConditionFinalize (&threadPtr->cond);
- Tcl_MutexFinalize (&threadPtr->threadMutex);
- ckfree ((VOID*) threadPtr);
+ Tcl_ConditionFinalize(&threadPtr->cond);
+ Tcl_MutexFinalize(&threadPtr->threadMutex);
+ ckfree((char *) threadPtr);
return TCL_OK;
}
@@ -211,39 +212,37 @@ TclJoinThread(id, result)
* TclRememberJoinableThread --
*
* This procedure remebers a thread as joinable. Only a call to
- * TclJoinThread will remove the structre created (and initialized)
- * here. IOW, not waiting upon a joinable thread will cause memory
- * leaks.
+ * TclJoinThread will remove the structre created (and initialized) here.
+ * IOW, not waiting upon a joinable thread will cause memory leaks.
*
* Results:
* None.
*
* Side effects:
- * Allocates memory, adds it to the global list of all joinable
- * threads.
+ * Allocates memory, adds it to the global list of all joinable threads.
*
*----------------------------------------------------------------------
*/
-VOID
-TclRememberJoinableThread(id)
- Tcl_ThreadId id; /* The thread to remember as joinable */
+void
+TclRememberJoinableThread(
+ Tcl_ThreadId id) /* The thread to remember as joinable */
{
- JoinableThread* threadPtr;
+ JoinableThread *threadPtr;
- threadPtr = (JoinableThread*) ckalloc (sizeof (JoinableThread));
- threadPtr->id = id;
- threadPtr->done = 0;
- threadPtr->waitedUpon = 0;
+ threadPtr = (JoinableThread *) ckalloc(sizeof(JoinableThread));
+ threadPtr->id = id;
+ threadPtr->done = 0;
+ threadPtr->waitedUpon = 0;
threadPtr->threadMutex = (Tcl_Mutex) NULL;
- threadPtr->cond = (Tcl_Condition) NULL;
+ threadPtr->cond = (Tcl_Condition) NULL;
- Tcl_MutexLock (&joinMutex);
+ Tcl_MutexLock(&joinMutex);
threadPtr->nextThreadPtr = firstThreadPtr;
- firstThreadPtr = threadPtr;
+ firstThreadPtr = threadPtr;
- Tcl_MutexUnlock (&joinMutex);
+ Tcl_MutexUnlock(&joinMutex);
}
/*
@@ -251,9 +250,9 @@ TclRememberJoinableThread(id)
*
* TclSignalExitThread --
*
- * This procedure signals that the specified thread is done with
- * its work. If the thread is joinable this signal is propagated
- * to the thread waiting upon it.
+ * This procedure signals that the specified thread is done with its
+ * work. If the thread is joinable this signal is propagated to the
+ * thread waiting upon it.
*
* Results:
* None.
@@ -264,46 +263,54 @@ TclRememberJoinableThread(id)
*----------------------------------------------------------------------
*/
-VOID
-TclSignalExitThread(id,result)
- Tcl_ThreadId id; /* Id of the thread signaling its exit */
- int result; /* The result from the thread */
+void
+TclSignalExitThread(
+ Tcl_ThreadId id, /* Id of the thread signaling its exit. */
+ int result) /* The result from the thread. */
{
- JoinableThread* threadPtr;
+ JoinableThread *threadPtr;
- Tcl_MutexLock (&joinMutex);
+ Tcl_MutexLock(&joinMutex);
- for (threadPtr = firstThreadPtr;
- (threadPtr != (JoinableThread*) NULL) && (threadPtr->id != id);
- threadPtr = threadPtr->nextThreadPtr)
- /* empty body */
- ;
+ threadPtr = firstThreadPtr;
+ while ((threadPtr != NULL) && (threadPtr->id != id)) {
+ threadPtr = threadPtr->nextThreadPtr;
+ }
- if (threadPtr == (JoinableThread*) NULL) {
- /* Thread not found. Not joinable. No problem, nothing to do.
+ if (threadPtr == NULL) {
+ /*
+ * Thread not found. Not joinable. No problem, nothing to do.
*/
- Tcl_MutexUnlock (&joinMutex);
+ Tcl_MutexUnlock(&joinMutex);
return;
}
- /* Switch over the exclusive access from the list to the structure,
- * then store the result, set the flag and notify the waiting thread,
- * provided that it exists. The order of lock/unlock ensures that a
- * thread entering 'TclJoinThread' will not interfere with us.
+ /*
+ * Switch over the exclusive access from the list to the structure, then
+ * store the result, set the flag and notify the waiting thread, provided
+ * that it exists. The order of lock/unlock ensures that a thread entering
+ * 'TclJoinThread' will not interfere with us.
*/
- Tcl_MutexLock (&threadPtr->threadMutex);
- Tcl_MutexUnlock (&joinMutex);
+ Tcl_MutexLock(&threadPtr->threadMutex);
+ Tcl_MutexUnlock(&joinMutex);
- threadPtr->done = 1;
+ threadPtr->done = 1;
threadPtr->result = result;
if (threadPtr->waitedUpon) {
- Tcl_ConditionNotify (&threadPtr->cond);
+ Tcl_ConditionNotify(&threadPtr->cond);
}
- Tcl_MutexUnlock (&threadPtr->threadMutex);
+ Tcl_MutexUnlock(&threadPtr->threadMutex);
}
-
-#endif /* WIN32 || MAC_TCL */
+#endif /* WIN32 */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclThreadStorage.c b/generic/tclThreadStorage.c
new file mode 100644
index 0000000..f1df888
--- /dev/null
+++ b/generic/tclThreadStorage.c
@@ -0,0 +1,597 @@
+/*
+ * tclThreadStorage.c --
+ *
+ * This file implements platform independent thread storage operations.
+ *
+ * Copyright (c) 2003-2004 by Joe Mistachkin
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tclInt.h"
+
+#if defined(TCL_THREADS)
+
+/*
+ * This is the thread storage cache array and it's accompanying mutex. The
+ * elements are pairs of thread Id and an associated hash table pointer; the
+ * hash table being pointed to contains the thread storage for it's associated
+ * thread. The purpose of this cache is to minimize the number of hash table
+ * lookups in the master thread storage hash table.
+ */
+
+static Tcl_Mutex threadStorageLock;
+
+/*
+ * This is the struct used for a thread storage cache slot. It contains the
+ * owning thread Id and the associated hash table pointer.
+ */
+
+typedef struct ThreadStorage {
+ Tcl_ThreadId id; /* the owning thread id */
+ Tcl_HashTable *hashTablePtr;/* the hash table for the thread */
+} ThreadStorage;
+
+/*
+ * These are the prototypes for the custom hash table allocation functions
+ * used by the thread storage subsystem.
+ */
+
+static Tcl_HashEntry * AllocThreadStorageEntry(Tcl_HashTable *tablePtr,
+ void *keyPtr);
+static void FreeThreadStorageEntry(Tcl_HashEntry *hPtr);
+static Tcl_HashTable * ThreadStorageGetHashTable(Tcl_ThreadId id);
+
+/*
+ * This is the hash key type for thread storage. We MUST use this in
+ * combination with the new hash key type flag TCL_HASH_KEY_SYSTEM_HASH
+ * because these hash tables MAY be used by the threaded memory allocator.
+ */
+
+static Tcl_HashKeyType tclThreadStorageHashKeyType = {
+ TCL_HASH_KEY_TYPE_VERSION, /* version */
+ TCL_HASH_KEY_SYSTEM_HASH | TCL_HASH_KEY_RANDOMIZE_HASH,
+ /* flags */
+ NULL, /* hashKeyProc */
+ NULL, /* compareKeysProc */
+ AllocThreadStorageEntry, /* allocEntryProc */
+ FreeThreadStorageEntry /* freeEntryProc */
+};
+
+/*
+ * This is an invalid thread value.
+ */
+
+#define STORAGE_INVALID_THREAD (Tcl_ThreadId)0
+
+/*
+ * This is the value for an invalid thread storage key.
+ */
+
+#define STORAGE_INVALID_KEY 0
+
+/*
+ * This is the first valid key for use by external callers. All the values
+ * below this are RESERVED for future use.
+ */
+
+#define STORAGE_FIRST_KEY 1
+
+/*
+ * This is the default number of thread storage cache slots. This define may
+ * need to be fine tuned for maximum performance.
+ */
+
+#define STORAGE_CACHE_SLOTS 97
+
+/*
+ * This is the master thread storage hash table. It is keyed on thread Id and
+ * contains values that are hash tables for each thread. The thread specific
+ * hash tables contain the actual thread storage.
+ */
+
+static Tcl_HashTable threadStorageHashTable;
+
+/*
+ * This is the next thread data key value to use. We increment this everytime
+ * we "allocate" one. It is initially set to 1 in TclInitThreadStorage.
+ */
+
+static int nextThreadStorageKey = STORAGE_INVALID_KEY;
+
+/*
+ * This is the master thread storage cache. Per Kevin Kenny's idea, this
+ * prevents unnecessary lookups for threads that use a lot of thread storage.
+ */
+
+static volatile ThreadStorage threadStorageCache[STORAGE_CACHE_SLOTS];
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AllocThreadStorageEntry --
+ *
+ * Allocate space for a Tcl_HashEntry using TclpSysAlloc (not ckalloc).
+ * We do this because the threaded memory allocator MAY use the thread
+ * storage hash tables.
+ *
+ * Results:
+ * The return value is a pointer to the created entry.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_HashEntry *
+AllocThreadStorageEntry(
+ Tcl_HashTable *tablePtr, /* Hash table. */
+ void *keyPtr) /* Key to store in the hash table entry. */
+{
+ Tcl_HashEntry *hPtr;
+
+ hPtr = (Tcl_HashEntry *) TclpSysAlloc(sizeof(Tcl_HashEntry), 0);
+ hPtr->key.oneWordValue = keyPtr;
+ hPtr->clientData = NULL;
+
+ return hPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeThreadStorageEntry --
+ *
+ * Frees space for a Tcl_HashEntry using TclpSysFree (not ckfree). We do
+ * this because the threaded memory allocator MAY use the thread storage
+ * hash tables.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeThreadStorageEntry(
+ Tcl_HashEntry *hPtr) /* Hash entry to free. */
+{
+ TclpSysFree((char *) hPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ThreadStorageGetHashTable --
+ *
+ * This procedure returns a hash table pointer to be used for thread
+ * storage for the specified thread.
+ *
+ * Results:
+ * A hash table pointer for the specified thread, or NULL if the hash
+ * table has not been created yet.
+ *
+ * Side effects:
+ * May change an entry in the master thread storage cache to point to the
+ * specified thread and it's associated hash table.
+ *
+ * Thread safety:
+ * This function assumes that integer operations are safe (atomic)
+ * on all (currently) supported Tcl platforms. Hence there are
+ * places where shared integer arithmetic is done w/o protective locks.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_HashTable *
+ThreadStorageGetHashTable(
+ Tcl_ThreadId id) /* Id of thread to get hash table for */
+{
+ int index = PTR2UINT(id) % STORAGE_CACHE_SLOTS;
+ Tcl_HashEntry *hPtr;
+ int isNew;
+ Tcl_HashTable *hashTablePtr;
+
+ /*
+ * It's important that we pick up the hash table pointer BEFORE comparing
+ * thread Id in case another thread is in the critical region changing
+ * things out from under you.
+ *
+ * Thread safety: threadStorageCache is accessed w/o locks in order to
+ * avoid serialization of all threads at this hot-spot. It is safe to
+ * do this here because (threadStorageCache[index].id != id) test below
+ * should be atomic on all (currently) supported platforms and there
+ * are no devastatig side effects of the test.
+ *
+ * Note Valgrind users: this place will show up as a race-condition in
+ * helgrind-tool output. To silence this warnings, define VALGRIND
+ * symbol at compilation time.
+ */
+
+#if !defined(VALGRIND)
+ hashTablePtr = threadStorageCache[index].hashTablePtr;
+ if (threadStorageCache[index].id != id) {
+ Tcl_MutexLock(&threadStorageLock);
+#else
+ Tcl_MutexLock(&threadStorageLock);
+ hashTablePtr = threadStorageCache[index].hashTablePtr;
+ if (threadStorageCache[index].id != id) {
+#endif
+
+ /*
+ * It's not in the cache, so we look it up...
+ */
+
+ hPtr = Tcl_FindHashEntry(&threadStorageHashTable, (char *) id);
+
+ if (hPtr != NULL) {
+ /*
+ * We found it, extract the hash table pointer.
+ */
+
+ hashTablePtr = Tcl_GetHashValue(hPtr);
+ } else {
+ /*
+ * The thread specific hash table is not found.
+ */
+
+ hashTablePtr = NULL;
+ }
+
+ if (hashTablePtr == NULL) {
+ hashTablePtr = (Tcl_HashTable *)
+ TclpSysAlloc(sizeof(Tcl_HashTable), 0);
+
+ if (hashTablePtr == NULL) {
+ Tcl_Panic("could not allocate thread specific hash table, "
+ "TclpSysAlloc failed from ThreadStorageGetHashTable!");
+ }
+ Tcl_InitCustomHashTable(hashTablePtr, TCL_CUSTOM_TYPE_KEYS,
+ &tclThreadStorageHashKeyType);
+
+ /*
+ * Add new thread storage hash table to the master hash table.
+ */
+
+ hPtr = Tcl_CreateHashEntry(&threadStorageHashTable, (char *) id,
+ &isNew);
+
+ if (hPtr == NULL) {
+ Tcl_Panic("Tcl_CreateHashEntry failed from "
+ "ThreadStorageGetHashTable!");
+ }
+ Tcl_SetHashValue(hPtr, hashTablePtr);
+ }
+
+ /*
+ * Now, we put it in the cache since it is highly likely it will be
+ * needed again shortly.
+ */
+
+ threadStorageCache[index].id = id;
+ threadStorageCache[index].hashTablePtr = hashTablePtr;
+#if !defined(VALGRIND)
+ Tcl_MutexUnlock(&threadStorageLock);
+ }
+#else
+ }
+ Tcl_MutexUnlock(&threadStorageLock);
+#endif
+
+ return hashTablePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclInitThreadStorage --
+ *
+ * Initializes the thread storage allocator.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * This procedure initializes the master hash table that maps thread ID
+ * onto the individual index tables that map thread data key to thread
+ * data. It also creates a cache that enables fast lookup of the thread
+ * data block array for a recently executing thread without using
+ * spinlocks.
+ *
+ * This procedure is called from an extremely early point in Tcl's
+ * initialization. In particular, it may not use ckalloc/ckfree because they
+ * may depend on thread-local storage (it uses TclpSysAlloc and TclpSysFree
+ * instead). It may not depend on synchronization primitives - but no threads
+ * other than the master thread have yet been launched.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclInitThreadStorage(void)
+{
+ Tcl_InitCustomHashTable(&threadStorageHashTable, TCL_CUSTOM_TYPE_KEYS,
+ &tclThreadStorageHashKeyType);
+
+ /*
+ * We also initialize the cache.
+ */
+
+ memset((void*) &threadStorageCache, 0,
+ sizeof(ThreadStorage) * STORAGE_CACHE_SLOTS);
+
+ /*
+ * Now, we set the first value to be used for a thread data key.
+ */
+
+ nextThreadStorageKey = STORAGE_FIRST_KEY;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpThreadDataKeyGet --
+ *
+ * This procedure returns a pointer to a block of thread local storage.
+ *
+ * Results:
+ * A thread-specific pointer to the data structure, or NULL if the memory
+ * has not been assigned to this key for this thread.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void *
+TclpThreadDataKeyGet(
+ Tcl_ThreadDataKey *keyPtr) /* Identifier for the data chunk, really
+ * (int**) */
+{
+ Tcl_HashTable *hashTablePtr =
+ ThreadStorageGetHashTable(Tcl_GetCurrentThread());
+ Tcl_HashEntry *hPtr = Tcl_FindHashEntry(hashTablePtr, (char *) keyPtr);
+
+ if (hPtr == NULL) {
+ return NULL;
+ }
+ return Tcl_GetHashValue(hPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpThreadDataKeySet --
+ *
+ * This procedure sets the pointer to a block of thread local storage.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets up the thread so future calls to TclpThreadDataKeyGet with this
+ * key will return the data pointer.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpThreadDataKeySet(
+ Tcl_ThreadDataKey *keyPtr, /* Identifier for the data chunk, really
+ * (pthread_key_t **) */
+ void *data) /* Thread local storage */
+{
+ Tcl_HashTable *hashTablePtr;
+ Tcl_HashEntry *hPtr;
+ int dummy;
+
+ hashTablePtr = ThreadStorageGetHashTable(Tcl_GetCurrentThread());
+ hPtr = Tcl_CreateHashEntry(hashTablePtr, (char *)keyPtr, &dummy);
+
+ Tcl_SetHashValue(hPtr, data);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpFinalizeThreadDataThread --
+ *
+ * This procedure cleans up the thread storage hash table for the
+ * current thread.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Frees all associated thread storage, all hash table entries for
+ * the thread's thread storage, and the hash table itself.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpFinalizeThreadDataThread(void)
+{
+ Tcl_ThreadId id = Tcl_GetCurrentThread();
+ /* Id of the thread to finalize. */
+ int index = PTR2UINT(id) % STORAGE_CACHE_SLOTS;
+ Tcl_HashEntry *hPtr; /* Hash entry for current thread in master
+ * table. */
+ Tcl_HashTable* hashTablePtr;/* Pointer to the hash table holding TSD
+ * blocks for the current thread*/
+ Tcl_HashSearch search; /* Search object to walk the TSD blocks in the
+ * designated thread */
+ Tcl_HashEntry *hPtr2; /* Hash entry for a TSD block in the
+ * designated thread. */
+
+ Tcl_MutexLock(&threadStorageLock);
+ hPtr = Tcl_FindHashEntry(&threadStorageHashTable, (char*)id);
+ if (hPtr == NULL) {
+ hashTablePtr = NULL;
+ } else {
+ /*
+ * We found it, extract the hash table pointer.
+ */
+
+ hashTablePtr = Tcl_GetHashValue(hPtr);
+ Tcl_DeleteHashEntry(hPtr);
+
+ /*
+ * Make sure cache entry for this thread is NULL.
+ */
+
+ if (threadStorageCache[index].id == id) {
+ /*
+ * We do not step on another thread's cache entry. This is
+ * especially important if we are creating and exiting a lot of
+ * threads.
+ */
+
+ threadStorageCache[index].id = STORAGE_INVALID_THREAD;
+ threadStorageCache[index].hashTablePtr = NULL;
+ }
+ }
+ Tcl_MutexUnlock(&threadStorageLock);
+
+ /*
+ * The thread's hash table has been extracted and removed from the master
+ * hash table. Now clean up the thread.
+ */
+
+ if (hashTablePtr != NULL) {
+ /*
+ * Free all TSD
+ */
+
+ for (hPtr2 = Tcl_FirstHashEntry(hashTablePtr, &search); hPtr2 != NULL;
+ hPtr2 = Tcl_NextHashEntry(&search)) {
+ void *blockPtr = Tcl_GetHashValue(hPtr2);
+
+ if (blockPtr != NULL) {
+ /*
+ * The block itself was allocated in Tcl_GetThreadData using
+ * ckalloc; use ckfree to dispose of it.
+ */
+
+ ckfree(blockPtr);
+ }
+ }
+
+ /*
+ * Delete thread specific hash table and free the struct.
+ */
+
+ Tcl_DeleteHashTable(hashTablePtr);
+ TclpSysFree((char *) hashTablePtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclFinalizeThreadStorage --
+ *
+ * This procedure cleans up the master thread storage hash table, all
+ * thread specific hash tables, and the thread storage cache.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The master thread storage hash table and thread storage cache are
+ * reset to their initial (empty) state.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclFinalizeThreadStorage(void)
+{
+ Tcl_HashSearch search; /* We need to hit every thread with this
+ * search. */
+ Tcl_HashEntry *hPtr; /* Hash entry for current thread in master
+ * table. */
+ Tcl_MutexLock(&threadStorageLock);
+
+ /*
+ * We are going to delete the hash table for every thread now. This hash
+ * table should be empty at this point, except for one entry for the
+ * current thread.
+ */
+
+ for (hPtr = Tcl_FirstHashEntry(&threadStorageHashTable, &search);
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ Tcl_HashTable *hashTablePtr = Tcl_GetHashValue(hPtr);
+
+ if (hashTablePtr != NULL) {
+ /*
+ * Delete thread specific hash table for the thread in question
+ * and free the struct.
+ */
+
+ Tcl_DeleteHashTable(hashTablePtr);
+ TclpSysFree((char *)hashTablePtr);
+ }
+
+ /*
+ * Delete thread specific entry from master hash table.
+ */
+
+ Tcl_SetHashValue(hPtr, NULL);
+ }
+
+ Tcl_DeleteHashTable(&threadStorageHashTable);
+
+ /*
+ * Clear out the thread storage cache as well.
+ */
+
+ memset((void*) &threadStorageCache, 0,
+ sizeof(ThreadStorage) * STORAGE_CACHE_SLOTS);
+
+ /*
+ * Reset this to zero, it will be set to STORAGE_FIRST_KEY if the thread
+ * storage subsystem gets reinitialized
+ */
+
+ nextThreadStorageKey = STORAGE_INVALID_KEY;
+
+ Tcl_MutexUnlock(&threadStorageLock);
+}
+
+#else /* !defined(TCL_THREADS) */
+
+/*
+ * Stub functions for non-threaded builds
+ */
+
+void
+TclInitThreadStorage(void)
+{
+}
+
+void
+TclpFinalizeThreadDataThread(void)
+{
+}
+
+void
+TclFinalizeThreadStorage(void)
+{
+}
+
+#endif /* defined(TCL_THREADS) && defined(USE_THREAD_STORAGE) */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclThreadTest.c b/generic/tclThreadTest.c
index d298e5b..960c7dc 100644
--- a/generic/tclThreadTest.c
+++ b/generic/tclThreadTest.c
@@ -1,29 +1,31 @@
-/*
+/*
* tclThreadTest.c --
*
- * This file implements the testthread command. Eventually this
- * should be tclThreadCmd.c
+ * This file implements the testthread command. Eventually this should be
+ * tclThreadCmd.c
* Some of this code is based on work done by Richard Hipp on behalf of
* Conservation Through Innovation, Limited, with their permission.
*
* Copyright (c) 1998 by Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
+extern int Tcltest_Init(Tcl_Interp *interp);
+
#ifdef TCL_THREADS
/*
- * Each thread has an single instance of the following structure. There
- * is one instance of this structure per thread even if that thread contains
- * multiple interpreters. The interpreter identified by this structure is
- * the main interpreter for the thread.
- *
- * The main interpreter is the one that will process any messages
- * received by a thread. Any thread can send messages but only the
- * main interpreter can receive them.
+ * Each thread has an single instance of the following structure. There is one
+ * instance of this structure per thread even if that thread contains multiple
+ * interpreters. The interpreter identified by this structure is the main
+ * interpreter for the thread.
+ *
+ * The main interpreter is the one that will process any messages received by
+ * a thread. Any thread can send messages but only the main interpreter can
+ * receive them.
*/
typedef struct ThreadSpecificData {
@@ -36,8 +38,8 @@ typedef struct ThreadSpecificData {
static Tcl_ThreadDataKey dataKey;
/*
- * This list is used to list all threads that have interpreters.
- * This is protected by threadMutex.
+ * This list is used to list all threads that have interpreters. This is
+ * protected by threadMutex.
*/
static struct ThreadSpecificData *threadList;
@@ -55,16 +57,18 @@ static struct ThreadSpecificData *threadList;
*/
typedef struct ThreadCtrl {
- char *script; /* The TCL command this thread should execute */
- int flags; /* Initial value of the "flags" field in the
- * ThreadSpecificData structure for the new thread.
- * Might contain TP_Detached or TP_TclThread. */
- Tcl_Condition condWait;
- /* This condition variable is used to synchronize
- * the parent and child threads. The child won't run
- * until it acquires threadMutex, and the parent function
- * won't complete until signaled on this condition
- * variable. */
+ char *script; /* The Tcl command this thread should
+ * execute */
+ int flags; /* Initial value of the "flags" field in the
+ * ThreadSpecificData structure for the new
+ * thread. Might contain TP_Detached or
+ * TP_TclThread. */
+ Tcl_Condition condWait; /* This condition variable is used to
+ * synchronize the parent and child threads.
+ * The child won't run until it acquires
+ * threadMutex, and the parent function won't
+ * complete until signaled on this condition
+ * variable. */
} ThreadCtrl;
/*
@@ -75,8 +79,8 @@ typedef struct ThreadEvent {
Tcl_Event event; /* Must be first */
char *script; /* The script to execute. */
struct ThreadEventResult *resultPtr;
- /* To communicate the result. This is
- * NULL if we don't care about it. */
+ /* To communicate the result. This is NULL if
+ * we don't care about it. */
} ThreadEvent;
typedef struct ThreadEventResult {
@@ -102,9 +106,9 @@ static ThreadEventResult *resultList;
static Tcl_ThreadId errorThreadId;
static char *errorProcString;
-/*
- * Access to the list of threads and to the thread send results is
- * guarded by this mutex.
+/*
+ * Access to the list of threads and to the thread send results is guarded by
+ * this mutex.
*/
TCL_DECLARE_MUTEX(threadMutex)
@@ -112,28 +116,28 @@ TCL_DECLARE_MUTEX(threadMutex)
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLEXPORT
-EXTERN int TclThread_Init _ANSI_ARGS_((Tcl_Interp *interp));
-EXTERN int Tcl_ThreadObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
-EXTERN int TclCreateThread _ANSI_ARGS_((Tcl_Interp *interp,
- char *script, int joinable));
-EXTERN int TclThreadList _ANSI_ARGS_((Tcl_Interp *interp));
-EXTERN int TclThreadSend _ANSI_ARGS_((Tcl_Interp *interp, Tcl_ThreadId id,
- char *script, int wait));
+EXTERN int TclThread_Init(Tcl_Interp *interp);
+EXTERN int Tcl_ThreadObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+EXTERN int TclCreateThread(Tcl_Interp *interp, char *script,
+ int joinable);
+EXTERN int TclThreadList(Tcl_Interp *interp);
+EXTERN int TclThreadSend(Tcl_Interp *interp, Tcl_ThreadId id,
+ char *script, int wait);
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT
-Tcl_ThreadCreateType NewTestThread _ANSI_ARGS_((ClientData clientData));
-static void ListRemove _ANSI_ARGS_((ThreadSpecificData *tsdPtr));
-static void ListUpdateInner _ANSI_ARGS_((ThreadSpecificData *tsdPtr));
-static int ThreadEventProc _ANSI_ARGS_((Tcl_Event *evPtr, int mask));
-static void ThreadErrorProc _ANSI_ARGS_((Tcl_Interp *interp));
-static void ThreadFreeProc _ANSI_ARGS_((ClientData clientData));
-static int ThreadDeleteEvent _ANSI_ARGS_((Tcl_Event *eventPtr,
- ClientData clientData));
-static void ThreadExitProc _ANSI_ARGS_((ClientData clientData));
-
+Tcl_ThreadCreateType NewTestThread(ClientData clientData);
+static void ListRemove(ThreadSpecificData *tsdPtr);
+static void ListUpdateInner(ThreadSpecificData *tsdPtr);
+static int ThreadEventProc(Tcl_Event *evPtr, int mask);
+static void ThreadErrorProc(Tcl_Interp *interp);
+static void ThreadFreeProc(ClientData clientData);
+static int ThreadDeleteEvent(Tcl_Event *eventPtr,
+ ClientData clientData);
+static void ThreadExitProc(ClientData clientData);
/*
*----------------------------------------------------------------------
@@ -152,15 +156,12 @@ static void ThreadExitProc _ANSI_ARGS_((ClientData clientData));
*/
int
-TclThread_Init(interp)
- Tcl_Interp *interp; /* The current Tcl interpreter */
+TclThread_Init(
+ Tcl_Interp *interp) /* The current Tcl interpreter */
{
-
- Tcl_CreateObjCommand(interp,"testthread", Tcl_ThreadObjCmd,
- (ClientData)NULL ,NULL);
- if (Tcl_PkgProvide(interp, "Thread", "1.0" ) != TCL_OK) {
- return TCL_ERROR;
- }
+
+ Tcl_CreateObjCommand(interp, "testthread", Tcl_ThreadObjCmd,
+ (ClientData) NULL, NULL);
return TCL_OK;
}
@@ -170,8 +171,8 @@ TclThread_Init(interp)
*
* Tcl_ThreadObjCmd --
*
- * This procedure is invoked to process the "testthread" Tcl command.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "testthread" Tcl command. See
+ * the user documentation for details on what it does.
*
* thread create ?-joinable? ?script?
* thread send id ?-async? script
@@ -193,30 +194,33 @@ TclThread_Init(interp)
/* ARGSUSED */
int
-Tcl_ThreadObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_ThreadObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
int option;
- static CONST char *threadOptions[] = {"create", "exit", "id", "join", "names",
- "send", "wait", "errorproc",
- (char *) NULL};
- enum options {THREAD_CREATE, THREAD_EXIT, THREAD_ID, THREAD_JOIN,
- THREAD_NAMES, THREAD_SEND, THREAD_WAIT, THREAD_ERRORPROC};
+ static const char *threadOptions[] = {
+ "create", "exit", "id", "join", "names",
+ "send", "wait", "errorproc", NULL
+ };
+ enum options {
+ THREAD_CREATE, THREAD_EXIT, THREAD_ID, THREAD_JOIN, THREAD_NAMES,
+ THREAD_SEND, THREAD_WAIT, THREAD_ERRORPROC
+ };
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "option ?args?");
return TCL_ERROR;
}
- if (Tcl_GetIndexFromObj(interp, objv[1], threadOptions,
- "option", 0, &option) != TCL_OK) {
+ if (Tcl_GetIndexFromObj(interp, objv[1], threadOptions, "option", 0,
+ &option) != TCL_OK) {
return TCL_ERROR;
}
- /*
+ /*
* Make sure the initial thread is on the list before doing anything.
*/
@@ -229,158 +233,158 @@ Tcl_ThreadObjCmd(dummy, interp, objc, objv)
}
switch ((enum options)option) {
- case THREAD_CREATE: {
- char *script;
- int joinable, len;
-
- if (objc == 2) {
- /* Neither joinable nor special script
- */
+ case THREAD_CREATE: {
+ char *script;
+ int joinable, len;
- joinable = 0;
- script = "testthread wait"; /* Just enter the event loop */
+ if (objc == 2) {
+ /*
+ * Neither joinable nor special script
+ */
- } else if (objc == 3) {
- /* Possibly -joinable, then no special script,
- * no joinable, then its a script.
- */
+ joinable = 0;
+ script = "testthread wait"; /* Just enter event loop */
+ } else if (objc == 3) {
+ /*
+ * Possibly -joinable, then no special script, no joinable, then
+ * its a script.
+ */
- script = Tcl_GetString(objv[2]);
- len = strlen (script);
+ script = Tcl_GetStringFromObj(objv[2], &len);
- if ((len > 1) &&
+ if ((len > 1) &&
(script [0] == '-') && (script [1] == 'j') &&
(0 == strncmp (script, "-joinable", (size_t) len))) {
- joinable = 1;
- script = "testthread wait"; /* Just enter the event loop
- */
- } else {
- /* Remember the script */
- joinable = 0;
- }
- } else if (objc == 4) {
- /* Definitely a script available, but is the flag
- * -joinable ?
+ joinable = 1;
+ script = "testthread wait"; /* Just enter event loop */
+ } else {
+ /*
+ * Remember the script
*/
- script = Tcl_GetString(objv[2]);
- len = strlen (script);
+ joinable = 0;
+ }
+ } else if (objc == 4) {
+ /*
+ * Definitely a script available, but is the flag -joinable?
+ */
- joinable = ((len > 1) &&
- (script [0] == '-') && (script [1] == 'j') &&
- (0 == strncmp (script, "-joinable", (size_t) len)));
+ script = Tcl_GetStringFromObj(objv[2], &len);
- script = Tcl_GetString(objv[3]);
- } else {
- Tcl_WrongNumArgs(interp, 2, objv, "?-joinable? ?script?");
- return TCL_ERROR;
- }
- return TclCreateThread(interp, script, joinable);
+ joinable = ((len > 1) &&
+ (script [0] == '-') && (script [1] == 'j') &&
+ (0 == strncmp(script, "-joinable", (size_t) len)));
+
+ script = Tcl_GetString(objv[3]);
+ } else {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-joinable? ?script?");
+ return TCL_ERROR;
}
- case THREAD_EXIT: {
- if (objc > 2) {
- Tcl_WrongNumArgs(interp, 1, objv, NULL);
- return TCL_ERROR;
- }
- ListRemove(NULL);
- Tcl_ExitThread(0);
- return TCL_OK;
+ return TclCreateThread(interp, script, joinable);
+ }
+ case THREAD_EXIT:
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return TCL_ERROR;
}
- case THREAD_ID:
- if (objc == 2) {
- Tcl_Obj *idObj = Tcl_NewLongObj((long)Tcl_GetCurrentThread());
- Tcl_SetObjResult(interp, idObj);
- return TCL_OK;
- } else {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- return TCL_ERROR;
- }
- case THREAD_JOIN: {
- long id;
- int result, status;
+ ListRemove(NULL);
+ Tcl_ExitThread(0);
+ return TCL_OK;
+ case THREAD_ID:
+ if (objc == 2) {
+ Tcl_Obj *idObj = Tcl_NewLongObj((long) Tcl_GetCurrentThread());
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 1, objv, "join id");
- return TCL_ERROR;
- }
- if (Tcl_GetLongFromObj(interp, objv[2], &id) != TCL_OK) {
- return TCL_ERROR;
- }
+ Tcl_SetObjResult(interp, idObj);
+ return TCL_OK;
+ } else {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return TCL_ERROR;
+ }
+ case THREAD_JOIN: {
+ long id;
+ int result, status;
- result = Tcl_JoinThread ((Tcl_ThreadId) id, &status);
- if (result == TCL_OK) {
- Tcl_SetIntObj (Tcl_GetObjResult (interp), status);
- } else {
- char buf [20];
- sprintf (buf, "%ld", id);
- Tcl_AppendResult (interp, "cannot join thread ", buf, NULL);
- }
- return result;
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "id");
+ return TCL_ERROR;
}
- case THREAD_NAMES: {
- if (objc > 2) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- return TCL_ERROR;
- }
- return TclThreadList(interp);
+ if (Tcl_GetLongFromObj(interp, objv[2], &id) != TCL_OK) {
+ return TCL_ERROR;
}
- case THREAD_SEND: {
- long id;
- char *script;
- int wait, arg;
- if ((objc != 4) && (objc != 5)) {
- Tcl_WrongNumArgs(interp, 1, objv, "send ?-async? id script");
- return TCL_ERROR;
- }
- if (objc == 5) {
- if (strcmp("-async", Tcl_GetString(objv[2])) != 0) {
- Tcl_WrongNumArgs(interp, 1, objv, "send ?-async? id script");
- return TCL_ERROR;
- }
- wait = 0;
- arg = 3;
- } else {
- wait = 1;
- arg = 2;
- }
- if (Tcl_GetLongFromObj(interp, objv[arg], &id) != TCL_OK) {
+ result = Tcl_JoinThread ((Tcl_ThreadId) id, &status);
+ if (result == TCL_OK) {
+ Tcl_SetIntObj (Tcl_GetObjResult (interp), status);
+ } else {
+ char buf [20];
+
+ sprintf(buf, "%ld", id);
+ Tcl_AppendResult(interp, "cannot join thread ", buf, NULL);
+ }
+ return result;
+ }
+ case THREAD_NAMES:
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return TCL_ERROR;
+ }
+ return TclThreadList(interp);
+ case THREAD_SEND: {
+ long id;
+ char *script;
+ int wait, arg;
+
+ if ((objc != 4) && (objc != 5)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-async? id script");
+ return TCL_ERROR;
+ }
+ if (objc == 5) {
+ if (strcmp("-async", Tcl_GetString(objv[2])) != 0) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?-async? id script");
return TCL_ERROR;
}
- arg++;
- script = Tcl_GetString(objv[arg]);
- return TclThreadSend(interp, (Tcl_ThreadId) id, script, wait);
+ wait = 0;
+ arg = 3;
+ } else {
+ wait = 1;
+ arg = 2;
}
- case THREAD_WAIT: {
- while (1) {
- (void) Tcl_DoOneEvent(TCL_ALL_EVENTS);
- }
+ if (Tcl_GetLongFromObj(interp, objv[arg], &id) != TCL_OK) {
+ return TCL_ERROR;
}
- case THREAD_ERRORPROC: {
- /*
- * Arrange for this proc to handle thread death errors.
- */
+ arg++;
+ script = Tcl_GetString(objv[arg]);
+ return TclThreadSend(interp, (Tcl_ThreadId) id, script, wait);
+ }
+ case THREAD_ERRORPROC: {
+ /*
+ * Arrange for this proc to handle thread death errors.
+ */
- char *proc;
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 1, objv, "errorproc proc");
- return TCL_ERROR;
- }
- Tcl_MutexLock(&threadMutex);
- errorThreadId = Tcl_GetCurrentThread();
- if (errorProcString) {
- ckfree(errorProcString);
- }
- proc = Tcl_GetString(objv[2]);
- errorProcString = ckalloc(strlen(proc)+1);
- strcpy(errorProcString, proc);
- Tcl_MutexUnlock(&threadMutex);
- return TCL_OK;
+ char *proc;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "proc");
+ return TCL_ERROR;
+ }
+ Tcl_MutexLock(&threadMutex);
+ errorThreadId = Tcl_GetCurrentThread();
+ if (errorProcString) {
+ ckfree(errorProcString);
+ }
+ proc = Tcl_GetString(objv[2]);
+ errorProcString = ckalloc(strlen(proc)+1);
+ strcpy(errorProcString, proc);
+ Tcl_MutexUnlock(&threadMutex);
+ return TCL_OK;
+ }
+ case THREAD_WAIT:
+ while (1) {
+ (void) Tcl_DoOneEvent(TCL_ALL_EVENTS);
}
}
return TCL_OK;
}
-
/*
*----------------------------------------------------------------------
@@ -388,7 +392,7 @@ Tcl_ThreadObjCmd(dummy, interp, objc, objv)
* TclCreateThread --
*
* This procedure is invoked to create a thread containing an interp to
- * run a script. This returns after the thread has started executing.
+ * run a script. This returns after the thread has started executing.
*
* Results:
* A standard Tcl result, which is the thread ID.
@@ -401,10 +405,10 @@ Tcl_ThreadObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-TclCreateThread(interp, script, joinable)
- Tcl_Interp *interp; /* Current interpreter. */
- char *script; /* Script to execute */
- int joinable; /* Flag, joinable thread or not */
+TclCreateThread(
+ Tcl_Interp *interp, /* Current interpreter. */
+ char *script, /* Script to execute */
+ int joinable) /* Flag, joinable thread or not */
{
ThreadCtrl ctrl;
Tcl_ThreadId id;
@@ -417,10 +421,10 @@ TclCreateThread(interp, script, joinable)
Tcl_MutexLock(&threadMutex);
if (Tcl_CreateThread(&id, NewTestThread, (ClientData) &ctrl,
- TCL_THREAD_STACK_DEFAULT, joinable) != TCL_OK) {
+ TCL_THREAD_STACK_DEFAULT, joinable) != TCL_OK) {
Tcl_MutexUnlock(&threadMutex);
- Tcl_AppendResult(interp,"can't create a new thread",NULL);
- ckfree((void*)ctrl.script);
+ Tcl_AppendResult(interp, "can't create a new thread", NULL);
+ ckfree((char *) ctrl.script);
return TCL_ERROR;
}
@@ -440,32 +444,32 @@ TclCreateThread(interp, script, joinable)
*
* NewTestThread --
*
- * This routine is the "main()" for a new thread whose task is to
- * execute a single TCL script. The argument to this function is
- * a pointer to a structure that contains the text of the TCL script
- * to be executed.
- *
- * Space to hold the script field of the ThreadControl structure passed
- * in as the only argument was obtained from malloc() and must be freed
- * by this function before it exits. Space to hold the ThreadControl
- * structure itself is released by the calling function, and the
- * two condition variables in the ThreadControl structure are destroyed
- * by the calling function. The calling function will destroy the
- * ThreadControl structure and the condition variable as soon as
- * ctrlPtr->condWait is signaled, so this routine must make copies of
- * any data it might need after that point.
+ * This routine is the "main()" for a new thread whose task is to execute
+ * a single Tcl script. The argument to this function is a pointer to a
+ * structure that contains the text of the TCL script to be executed.
+ *
+ * Space to hold the script field of the ThreadControl structure passed
+ * in as the only argument was obtained from malloc() and must be freed
+ * by this function before it exits. Space to hold the ThreadControl
+ * structure itself is released by the calling function, and the two
+ * condition variables in the ThreadControl structure are destroyed by
+ * the calling function. The calling function will destroy the
+ * ThreadControl structure and the condition variable as soon as
+ * ctrlPtr->condWait is signaled, so this routine must make copies of any
+ * data it might need after that point.
*
* Results:
- * none
+ * None
*
* Side effects:
- * A TCL script is executed in a new thread.
+ * A Tcl script is executed in a new thread.
*
*------------------------------------------------------------------------
*/
+
Tcl_ThreadCreateType
-NewTestThread(clientData)
- ClientData clientData;
+NewTestThread(
+ ClientData clientData)
{
ThreadCtrl *ctrlPtr = (ThreadCtrl*)clientData;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -481,16 +485,25 @@ NewTestThread(clientData)
result = TclThread_Init(tsdPtr->interp);
/*
+ * This is part of the test facility. Initialize _ALL_ test commands for
+ * use by the new thread.
+ */
+
+ result = Tcltest_Init(tsdPtr->interp);
+
+ /*
* Update the list of threads.
*/
Tcl_MutexLock(&threadMutex);
ListUpdateInner(tsdPtr);
+
/*
- * We need to keep a pointer to the alloc'ed mem of the script
- * we are eval'ing, for the case that we exit during evaluation
+ * We need to keep a pointer to the alloc'ed mem of the script we are
+ * eval'ing, for the case that we exit during evaluation
*/
- threadEvalScript = (char *) ckalloc(strlen(ctrlPtr->script)+1);
+
+ threadEvalScript = ckalloc(strlen(ctrlPtr->script)+1);
strcpy(threadEvalScript, ctrlPtr->script);
Tcl_CreateThreadExitHandler(ThreadExitProc, (ClientData) threadEvalScript);
@@ -529,22 +542,23 @@ NewTestThread(clientData)
*
* ThreadErrorProc --
*
- * Send a message to the thread willing to hear about errors.
+ * Send a message to the thread willing to hear about errors.
*
* Results:
- * none
+ * None
*
* Side effects:
- * Send an event.
+ * Send an event.
*
*------------------------------------------------------------------------
*/
+
static void
-ThreadErrorProc(interp)
- Tcl_Interp *interp; /* Interp that failed */
+ThreadErrorProc(
+ Tcl_Interp *interp) /* Interp that failed */
{
Tcl_Channel errChannel;
- CONST char *errorInfo, *argv[3];
+ const char *errorInfo, *argv[3];
char *script;
char buf[TCL_DOUBLE_SPACE+1];
sprintf(buf, "%ld", (long) Tcl_GetCurrentThread());
@@ -573,20 +587,21 @@ ThreadErrorProc(interp)
*
* ListUpdateInner --
*
- * Add the thread local storage to the list. This assumes
- * the caller has obtained the mutex.
+ * Add the thread local storage to the list. This assumes the caller has
+ * obtained the mutex.
*
* Results:
- * none
+ * None
*
* Side effects:
- * Add the thread local storage to its list.
+ * Add the thread local storage to its list.
*
*------------------------------------------------------------------------
*/
+
static void
-ListUpdateInner(tsdPtr)
- ThreadSpecificData *tsdPtr;
+ListUpdateInner(
+ ThreadSpecificData *tsdPtr)
{
if (tsdPtr == NULL) {
tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -605,20 +620,21 @@ ListUpdateInner(tsdPtr)
*
* ListRemove --
*
- * Remove the thread local storage from its list. This grabs the
- * mutex to protect the list.
+ * Remove the thread local storage from its list. This grabs the mutex to
+ * protect the list.
*
* Results:
- * none
+ * None
*
* Side effects:
- * Remove the thread local storage from its list.
+ * Remove the thread local storage from its list.
*
*------------------------------------------------------------------------
*/
+
static void
-ListRemove(tsdPtr)
- ThreadSpecificData *tsdPtr;
+ListRemove(
+ ThreadSpecificData *tsdPtr)
{
if (tsdPtr == NULL) {
tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -635,7 +651,6 @@ ListRemove(tsdPtr)
tsdPtr->nextPtr = tsdPtr->prevPtr = 0;
Tcl_MutexUnlock(&threadMutex);
}
-
/*
*------------------------------------------------------------------------
@@ -653,8 +668,8 @@ ListRemove(tsdPtr)
*------------------------------------------------------------------------
*/
int
-TclThreadList(interp)
- Tcl_Interp *interp;
+TclThreadList(
+ Tcl_Interp *interp)
{
ThreadSpecificData *tsdPtr;
Tcl_Obj *listPtr;
@@ -663,13 +678,12 @@ TclThreadList(interp)
Tcl_MutexLock(&threadMutex);
for (tsdPtr = threadList ; tsdPtr ; tsdPtr = tsdPtr->nextPtr) {
Tcl_ListObjAppendElement(interp, listPtr,
- Tcl_NewLongObj((long)tsdPtr->threadId));
+ Tcl_NewLongObj((long) tsdPtr->threadId));
}
Tcl_MutexUnlock(&threadMutex);
Tcl_SetObjResult(interp, listPtr);
return TCL_OK;
}
-
/*
*------------------------------------------------------------------------
@@ -686,12 +700,13 @@ TclThreadList(interp)
*
*------------------------------------------------------------------------
*/
+
int
-TclThreadSend(interp, id, script, wait)
- Tcl_Interp *interp; /* The current interpreter. */
- Tcl_ThreadId id; /* Thread Id of other interpreter. */
- char *script; /* The script to evaluate. */
- int wait; /* If 1, we block for the result. */
+TclThreadSend(
+ Tcl_Interp *interp, /* The current interpreter. */
+ Tcl_ThreadId id, /* Thread Id of other interpreter. */
+ char *script, /* The script to evaluate. */
+ int wait) /* If 1, we block for the result. */
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
ThreadEvent *threadEventPtr;
@@ -699,7 +714,7 @@ TclThreadSend(interp, id, script, wait)
int found, code;
Tcl_ThreadId threadId = (Tcl_ThreadId) id;
- /*
+ /*
* Verify the thread exists.
*/
@@ -718,8 +733,8 @@ TclThreadSend(interp, id, script, wait)
}
/*
- * Short circut sends to ourself. Ought to do something with -async,
- * like run in an idle handler.
+ * Short circut sends to ourself. Ought to do something with -async, like
+ * run in an idle handler.
*/
if (threadId == Tcl_GetCurrentThread()) {
@@ -727,7 +742,7 @@ TclThreadSend(interp, id, script, wait)
return Tcl_GlobalEval(interp, script);
}
- /*
+ /*
* Create the event for its event queue.
*/
@@ -750,7 +765,7 @@ TclThreadSend(interp, id, script, wait)
resultPtr->errorInfo = NULL;
resultPtr->errorCode = NULL;
- /*
+ /*
* Maintain the cleanup list.
*/
@@ -770,7 +785,7 @@ TclThreadSend(interp, id, script, wait)
*/
threadEventPtr->event.proc = ThreadEventProc;
- Tcl_ThreadQueueEvent(threadId, (Tcl_Event *)threadEventPtr,
+ Tcl_ThreadQueueEvent(threadId, (Tcl_Event *)threadEventPtr,
TCL_QUEUE_TAIL);
Tcl_ThreadAlert(threadId);
@@ -779,7 +794,7 @@ TclThreadSend(interp, id, script, wait)
return TCL_OK;
}
- /*
+ /*
* Block on the results and then get them.
*/
@@ -824,7 +839,6 @@ TclThreadSend(interp, id, script, wait)
return code;
}
-
/*
*------------------------------------------------------------------------
@@ -841,17 +855,18 @@ TclThreadSend(interp, id, script, wait)
*
*------------------------------------------------------------------------
*/
+
static int
-ThreadEventProc(evPtr, mask)
- Tcl_Event *evPtr; /* Really ThreadEvent */
- int mask;
+ThreadEventProc(
+ Tcl_Event *evPtr, /* Really ThreadEvent */
+ int mask)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
ThreadEvent *threadEventPtr = (ThreadEvent *)evPtr;
ThreadEventResult *resultPtr = threadEventPtr->resultPtr;
Tcl_Interp *interp = tsdPtr->interp;
int code;
- CONST char *result, *errorCode, *errorInfo;
+ const char *result, *errorCode, *errorInfo;
if (interp == NULL) {
code = TCL_ERROR;
@@ -913,10 +928,11 @@ ThreadEventProc(evPtr, mask)
*
*------------------------------------------------------------------------
*/
+
/* ARGSUSED */
static void
-ThreadFreeProc(clientData)
- ClientData clientData;
+ThreadFreeProc(
+ ClientData clientData)
{
if (clientData) {
ckfree((char *) clientData);
@@ -939,20 +955,23 @@ ThreadFreeProc(clientData)
*
*------------------------------------------------------------------------
*/
+
/* ARGSUSED */
static int
-ThreadDeleteEvent(eventPtr, clientData)
- Tcl_Event *eventPtr; /* Really ThreadEvent */
- ClientData clientData; /* dummy */
+ThreadDeleteEvent(
+ Tcl_Event *eventPtr, /* Really ThreadEvent */
+ ClientData clientData) /* dummy */
{
if (eventPtr->proc == ThreadEventProc) {
ckfree((char *) ((ThreadEvent *) eventPtr)->script);
return 1;
}
+
/*
- * If it was NULL, we were in the middle of servicing the event
- * and it should be removed
+ * If it was NULL, we were in the middle of servicing the event and it
+ * should be removed
*/
+
return (eventPtr->proc == NULL);
}
@@ -961,21 +980,22 @@ ThreadDeleteEvent(eventPtr, clientData)
*
* ThreadExitProc --
*
- * This is called when the thread exits.
+ * This is called when the thread exits.
*
* Results:
* None.
*
* Side effects:
- * It unblocks anyone that is waiting on a send to this thread.
- * It cleans up any events in the event queue for this thread.
+ * It unblocks anyone that is waiting on a send to this thread. It cleans
+ * up any events in the event queue for this thread.
*
*------------------------------------------------------------------------
*/
+
/* ARGSUSED */
static void
-ThreadExitProc(clientData)
- ClientData clientData;
+ThreadExitProc(
+ ClientData clientData)
{
char *threadEvalScript = (char *) clientData;
ThreadEventResult *resultPtr, *nextPtr;
@@ -993,9 +1013,10 @@ ThreadExitProc(clientData)
nextPtr = resultPtr->nextPtr;
if (resultPtr->srcThreadId == self) {
/*
- * We are going away. By freeing up the result we signal
- * to the other thread we don't care about the result.
+ * We are going away. By freeing up the result we signal to the
+ * other thread we don't care about the result.
*/
+
if (resultPtr->prevPtr) {
resultPtr->prevPtr->nextPtr = resultPtr->nextPtr;
} else {
@@ -1006,15 +1027,16 @@ ThreadExitProc(clientData)
}
resultPtr->nextPtr = resultPtr->prevPtr = 0;
resultPtr->eventPtr->resultPtr = NULL;
- ckfree((char *)resultPtr);
+ ckfree((char *) resultPtr);
} else if (resultPtr->dstThreadId == self) {
/*
- * Dang. The target is going away. Unblock the caller.
- * The result string must be dynamically allocated because
- * the main thread is going to call free on it.
+ * Dang. The target is going away. Unblock the caller. The result
+ * string must be dynamically allocated because the main thread is
+ * going to call free on it.
*/
char *msg = "target thread died";
+
resultPtr->result = ckalloc(strlen(msg)+1);
strcpy(resultPtr->result, msg);
resultPtr->code = TCL_ERROR;
@@ -1023,5 +1045,12 @@ ThreadExitProc(clientData)
}
Tcl_MutexUnlock(&threadMutex);
}
-
#endif /* TCL_THREADS */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclTimer.c b/generic/tclTimer.c
index d472b17..33838ec 100644
--- a/generic/tclTimer.c
+++ b/generic/tclTimer.c
@@ -1,4 +1,4 @@
-/*
+/*
* tclTimer.c --
*
* This file provides timer event management facilities for Tcl,
@@ -6,75 +6,73 @@
*
* Copyright (c) 1997 by Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
/*
* For each timer callback that's pending there is one record of the following
- * type. The normal handlers (created by Tcl_CreateTimerHandler) are chained
+ * type. The normal handlers (created by Tcl_CreateTimerHandler) are chained
* together in a list sorted by time (earliest event first).
*/
typedef struct TimerHandler {
- Tcl_Time time; /* When timer is to fire. */
- Tcl_TimerProc *proc; /* Procedure to call. */
- ClientData clientData; /* Argument to pass to proc. */
- Tcl_TimerToken token; /* Identifies handler so it can be
- * deleted. */
- struct TimerHandler *nextPtr; /* Next event in queue, or NULL for
- * end of queue. */
+ Tcl_Time time; /* When timer is to fire. */
+ Tcl_TimerProc *proc; /* Function to call. */
+ ClientData clientData; /* Argument to pass to proc. */
+ Tcl_TimerToken token; /* Identifies handler so it can be deleted. */
+ struct TimerHandler *nextPtr;
+ /* Next event in queue, or NULL for end of
+ * queue. */
} TimerHandler;
/*
- * The data structure below is used by the "after" command to remember
- * the command to be executed later. All of the pending "after" commands
- * for an interpreter are linked together in a list.
+ * The data structure below is used by the "after" command to remember the
+ * command to be executed later. All of the pending "after" commands for an
+ * interpreter are linked together in a list.
*/
typedef struct AfterInfo {
struct AfterAssocData *assocPtr;
- /* Pointer to the "tclAfter" assocData for
- * the interp in which command will be
+ /* Pointer to the "tclAfter" assocData for the
+ * interp in which command will be
* executed. */
Tcl_Obj *commandPtr; /* Command to execute. */
- int id; /* Integer identifier for command; used to
+ int id; /* Integer identifier for command; used to
* cancel it. */
- Tcl_TimerToken token; /* Used to cancel the "after" command. NULL
- * means that the command is run as an
- * idle handler rather than as a timer
- * handler. NULL means this is an "after
- * idle" handler rather than a
- * timer handler. */
+ Tcl_TimerToken token; /* Used to cancel the "after" command. NULL
+ * means that the command is run as an idle
+ * handler rather than as a timer handler.
+ * NULL means this is an "after idle" handler
+ * rather than a timer handler. */
struct AfterInfo *nextPtr; /* Next in list of all "after" commands for
* this interpreter. */
} AfterInfo;
/*
- * One of the following structures is associated with each interpreter
- * for which an "after" command has ever been invoked. A pointer to
- * this structure is stored in the AssocData for the "tclAfter" key.
+ * One of the following structures is associated with each interpreter for
+ * which an "after" command has ever been invoked. A pointer to this structure
+ * is stored in the AssocData for the "tclAfter" key.
*/
typedef struct AfterAssocData {
Tcl_Interp *interp; /* The interpreter for which this data is
* registered. */
- AfterInfo *firstAfterPtr; /* First in list of all "after" commands
- * still pending for this interpreter, or
- * NULL if none. */
+ AfterInfo *firstAfterPtr; /* First in list of all "after" commands still
+ * pending for this interpreter, or NULL if
+ * none. */
} AfterAssocData;
/*
- * There is one of the following structures for each of the
- * handlers declared in a call to Tcl_DoWhenIdle. All of the
- * currently-active handlers are linked together into a list.
+ * There is one of the following structures for each of the handlers declared
+ * in a call to Tcl_DoWhenIdle. All of the currently-active handlers are
+ * linked together into a list.
*/
typedef struct IdleHandler {
- Tcl_IdleProc (*proc); /* Procedure to call. */
+ Tcl_IdleProc (*proc); /* Function to call. */
ClientData clientData; /* Value to pass to proc. */
int generation; /* Used to distinguish older handlers from
* recently-created ones. */
@@ -82,53 +80,69 @@ typedef struct IdleHandler {
} IdleHandler;
/*
- * The timer and idle queues are per-thread because they are associated
- * with the notifier, which is also per-thread.
+ * The timer and idle queues are per-thread because they are associated with
+ * the notifier, which is also per-thread.
*
- * All static variables used in this file are collected into a single
- * instance of the following structure. For multi-threaded implementations,
- * there is one instance of this structure for each thread.
+ * All static variables used in this file are collected into a single instance
+ * of the following structure. For multi-threaded implementations, there is
+ * one instance of this structure for each thread.
*
- * Notice that different structures with the same name appear in other
- * files. The structure defined below is used in this file only.
+ * Notice that different structures with the same name appear in other files.
+ * The structure defined below is used in this file only.
*/
typedef struct ThreadSpecificData {
TimerHandler *firstTimerHandlerPtr; /* First event in queue. */
- int lastTimerId; /* Timer identifier of most recently
- * created timer. */
+ int lastTimerId; /* Timer identifier of most recently created
+ * timer. */
int timerPending; /* 1 if a timer event is in the queue. */
IdleHandler *idleList; /* First in list of all idle handlers. */
IdleHandler *lastIdlePtr; /* Last in list (or NULL for empty list). */
- int idleGeneration; /* Used to fill in the "generation" fields
- * of IdleHandler structures. Increments
- * each time Tcl_DoOneEvent starts calling
- * idle handlers, so that all old handlers
- * can be called without calling any of the
- * new ones created by old ones. */
+ int idleGeneration; /* Used to fill in the "generation" fields of
+ * IdleHandler structures. Increments each
+ * time Tcl_DoOneEvent starts calling idle
+ * handlers, so that all old handlers can be
+ * called without calling any of the new ones
+ * created by old ones. */
int afterId; /* For unique identifiers of after events. */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
/*
- * Prototypes for procedures referenced only in this file:
+ * Helper macros for working with times. TCL_TIME_BEFORE encodes how to write
+ * the ordering relation on (normalized) times, and TCL_TIME_DIFF_MS computes
+ * the number of milliseconds difference between two times. Both macros use
+ * both of their arguments multiple times, so make sure they are cheap and
+ * side-effect free. The "prototypes" for these macros are:
+ *
+ * static int TCL_TIME_BEFORE(Tcl_Time t1, Tcl_Time t2);
+ * static long TCL_TIME_DIFF_MS(Tcl_Time t1, Tcl_Time t2);
+ */
+
+#define TCL_TIME_BEFORE(t1, t2) \
+ (((t1).sec<(t2).sec) || ((t1).sec==(t2).sec && (t1).usec<(t2).usec))
+
+#define TCL_TIME_DIFF_MS(t1, t2) \
+ (1000*((Tcl_WideInt)(t1).sec - (Tcl_WideInt)(t2).sec) + \
+ ((long)(t1).usec - (long)(t2).usec)/1000)
+
+/*
+ * Prototypes for functions referenced only in this file:
*/
-static void AfterCleanupProc _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp));
-static void AfterProc _ANSI_ARGS_((ClientData clientData));
-static void FreeAfterPtr _ANSI_ARGS_((AfterInfo *afterPtr));
-static AfterInfo * GetAfterEvent _ANSI_ARGS_((AfterAssocData *assocPtr,
- Tcl_Obj *commandPtr));
-static ThreadSpecificData *InitTimer _ANSI_ARGS_((void));
-static void TimerExitProc _ANSI_ARGS_((ClientData clientData));
-static int TimerHandlerEventProc _ANSI_ARGS_((Tcl_Event *evPtr,
- int flags));
-static void TimerCheckProc _ANSI_ARGS_((ClientData clientData,
- int flags));
-static void TimerSetupProc _ANSI_ARGS_((ClientData clientData,
- int flags));
+static void AfterCleanupProc(ClientData clientData,
+ Tcl_Interp *interp);
+static int AfterDelay(Tcl_Interp *interp, Tcl_WideInt ms);
+static void AfterProc(ClientData clientData);
+static void FreeAfterPtr(AfterInfo *afterPtr);
+static AfterInfo * GetAfterEvent(AfterAssocData *assocPtr,
+ Tcl_Obj *commandPtr);
+static ThreadSpecificData *InitTimer(void);
+static void TimerExitProc(ClientData clientData);
+static int TimerHandlerEventProc(Tcl_Event *evPtr, int flags);
+static void TimerCheckProc(ClientData clientData, int flags);
+static void TimerSetupProc(ClientData clientData, int flags);
/*
*----------------------------------------------------------------------
@@ -147,10 +161,10 @@ static void TimerSetupProc _ANSI_ARGS_((ClientData clientData,
*/
static ThreadSpecificData *
-InitTimer()
+InitTimer(void)
{
- ThreadSpecificData *tsdPtr =
- (ThreadSpecificData *) TclThreadDataKeyGet(&dataKey);
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ TclThreadDataKeyGet(&dataKey);
if (tsdPtr == NULL) {
tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -165,8 +179,8 @@ InitTimer()
*
* TimerExitProc --
*
- * This function is call at exit or unload time to remove the
- * timer and idle event sources.
+ * This function is call at exit or unload time to remove the timer and
+ * idle event sources.
*
* Results:
* None.
@@ -178,15 +192,16 @@ InitTimer()
*/
static void
-TimerExitProc(clientData)
- ClientData clientData; /* Not used. */
+TimerExitProc(
+ ClientData clientData) /* Not used. */
{
- ThreadSpecificData *tsdPtr =
- (ThreadSpecificData *) TclThreadDataKeyGet(&dataKey);
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ TclThreadDataKeyGet(&dataKey);
Tcl_DeleteEventSource(TimerSetupProc, TimerCheckProc, NULL);
if (tsdPtr != NULL) {
register TimerHandler *timerHandlerPtr;
+
timerHandlerPtr = tsdPtr->firstTimerHandlerPtr;
while (timerHandlerPtr != NULL) {
tsdPtr->firstTimerHandlerPtr = timerHandlerPtr->nextPtr;
@@ -201,55 +216,82 @@ TimerExitProc(clientData)
*
* Tcl_CreateTimerHandler --
*
- * Arrange for a given procedure to be invoked at a particular
- * time in the future.
+ * Arrange for a given function to be invoked at a particular time in the
+ * future.
*
* Results:
- * The return value is a token for the timer event, which
- * may be used to delete the event before it fires.
+ * The return value is a token for the timer event, which may be used to
+ * delete the event before it fires.
*
* Side effects:
- * When milliseconds have elapsed, proc will be invoked
- * exactly once.
+ * When milliseconds have elapsed, proc will be invoked exactly once.
*
*--------------------------------------------------------------
*/
Tcl_TimerToken
-Tcl_CreateTimerHandler(milliseconds, proc, clientData)
- int milliseconds; /* How many milliseconds to wait
- * before invoking proc. */
- Tcl_TimerProc *proc; /* Procedure to invoke. */
- ClientData clientData; /* Arbitrary data to pass to proc. */
+Tcl_CreateTimerHandler(
+ int milliseconds, /* How many milliseconds to wait before
+ * invoking proc. */
+ Tcl_TimerProc *proc, /* Function to invoke. */
+ ClientData clientData) /* Arbitrary data to pass to proc. */
{
- register TimerHandler *timerHandlerPtr, *tPtr2, *prevPtr;
Tcl_Time time;
- ThreadSpecificData *tsdPtr;
-
- tsdPtr = InitTimer();
-
- timerHandlerPtr = (TimerHandler *) ckalloc(sizeof(TimerHandler));
/*
* Compute when the event should fire.
*/
Tcl_GetTime(&time);
- timerHandlerPtr->time.sec = time.sec + milliseconds/1000;
- timerHandlerPtr->time.usec = time.usec + (milliseconds%1000)*1000;
- if (timerHandlerPtr->time.usec >= 1000000) {
- timerHandlerPtr->time.usec -= 1000000;
- timerHandlerPtr->time.sec += 1;
+ time.sec += milliseconds/1000;
+ time.usec += (milliseconds%1000)*1000;
+ if (time.usec >= 1000000) {
+ time.usec -= 1000000;
+ time.sec += 1;
}
+ return TclCreateAbsoluteTimerHandler(&time, proc, clientData);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TclCreateAbsoluteTimerHandler --
+ *
+ * Arrange for a given function to be invoked at a particular time in the
+ * future.
+ *
+ * Results:
+ * The return value is a token for the timer event, which may be used to
+ * delete the event before it fires.
+ *
+ * Side effects:
+ * When the time in timePtr has been reached, proc will be invoked
+ * exactly once.
+ *
+ *--------------------------------------------------------------
+ */
+
+Tcl_TimerToken
+TclCreateAbsoluteTimerHandler(
+ Tcl_Time *timePtr,
+ Tcl_TimerProc *proc,
+ ClientData clientData)
+{
+ register TimerHandler *timerHandlerPtr, *tPtr2, *prevPtr;
+ ThreadSpecificData *tsdPtr;
+
+ tsdPtr = InitTimer();
+ timerHandlerPtr = (TimerHandler *) ckalloc(sizeof(TimerHandler));
/*
- * Fill in other fields for the event.
+ * Fill in fields for the event.
*/
+ memcpy((void *)&timerHandlerPtr->time, (void *)timePtr, sizeof(Tcl_Time));
timerHandlerPtr->proc = proc;
timerHandlerPtr->clientData = clientData;
tsdPtr->lastTimerId++;
- timerHandlerPtr->token = (Tcl_TimerToken) tsdPtr->lastTimerId;
+ timerHandlerPtr->token = (Tcl_TimerToken) INT2PTR(tsdPtr->lastTimerId);
/*
* Add the event to the queue in the correct position
@@ -258,9 +300,7 @@ Tcl_CreateTimerHandler(milliseconds, proc, clientData)
for (tPtr2 = tsdPtr->firstTimerHandlerPtr, prevPtr = NULL; tPtr2 != NULL;
prevPtr = tPtr2, tPtr2 = tPtr2->nextPtr) {
- if ((tPtr2->time.sec > timerHandlerPtr->time.sec)
- || ((tPtr2->time.sec == timerHandlerPtr->time.sec)
- && (tPtr2->time.usec > timerHandlerPtr->time.usec))) {
+ if (TCL_TIME_BEFORE(timerHandlerPtr->time, tPtr2->time)) {
break;
}
}
@@ -287,17 +327,16 @@ Tcl_CreateTimerHandler(milliseconds, proc, clientData)
* None.
*
* Side effects:
- * Destroy the timer callback identified by TimerToken,
- * so that its associated procedure will not be called.
- * If the callback has already fired, or if the given
- * token doesn't exist, then nothing happens.
+ * Destroy the timer callback identified by TimerToken, so that its
+ * associated function will not be called. If the callback has already
+ * fired, or if the given token doesn't exist, then nothing happens.
*
*--------------------------------------------------------------
*/
void
-Tcl_DeleteTimerHandler(token)
- Tcl_TimerToken token; /* Result previously returned by
+Tcl_DeleteTimerHandler(
+ Tcl_TimerToken token) /* Result previously returned by
* Tcl_DeleteTimerHandler. */
{
register TimerHandler *timerHandlerPtr, *prevPtr;
@@ -328,9 +367,9 @@ Tcl_DeleteTimerHandler(token)
*
* TimerSetupProc --
*
- * This function is called by Tcl_DoOneEvent to setup the timer
- * event source for before blocking. This routine checks both the
- * idle and after timer lists.
+ * This function is called by Tcl_DoOneEvent to setup the timer event
+ * source for before blocking. This routine checks both the idle and
+ * after timer lists.
*
* Results:
* None.
@@ -342,9 +381,9 @@ Tcl_DeleteTimerHandler(token)
*/
static void
-TimerSetupProc(data, flags)
- ClientData data; /* Not used. */
- int flags; /* Event flags as passed to Tcl_DoOneEvent. */
+TimerSetupProc(
+ ClientData data, /* Not used. */
+ int flags) /* Event flags as passed to Tcl_DoOneEvent. */
{
Tcl_Time blockTime;
ThreadSpecificData *tsdPtr = InitTimer();
@@ -378,7 +417,7 @@ TimerSetupProc(data, flags)
} else {
return;
}
-
+
Tcl_SetMaxBlockTime(&blockTime);
}
@@ -387,9 +426,9 @@ TimerSetupProc(data, flags)
*
* TimerCheckProc --
*
- * This function is called by Tcl_DoOneEvent to check the timer
- * event source for events. This routine checks both the
- * idle and after timer lists.
+ * This function is called by Tcl_DoOneEvent to check the timer event
+ * source for events. This routine checks both the idle and after timer
+ * lists.
*
* Results:
* None.
@@ -401,9 +440,9 @@ TimerSetupProc(data, flags)
*/
static void
-TimerCheckProc(data, flags)
- ClientData data; /* Not used. */
- int flags; /* Event flags as passed to Tcl_DoOneEvent. */
+TimerCheckProc(
+ ClientData data, /* Not used. */
+ int flags) /* Event flags as passed to Tcl_DoOneEvent. */
{
Tcl_Event *timerEvPtr;
Tcl_Time blockTime;
@@ -446,28 +485,27 @@ TimerCheckProc(data, flags)
*
* TimerHandlerEventProc --
*
- * This procedure is called by Tcl_ServiceEvent when a timer event
- * reaches the front of the event queue. This procedure handles
- * the event by invoking the callbacks for all timers that are
- * ready.
+ * This function is called by Tcl_ServiceEvent when a timer event reaches
+ * the front of the event queue. This function handles the event by
+ * invoking the callbacks for all timers that are ready.
*
* Results:
- * Returns 1 if the event was handled, meaning it should be removed
- * from the queue. Returns 0 if the event was not handled, meaning
- * it should stay on the queue. The only time the event isn't
- * handled is if the TCL_TIMER_EVENTS flag bit isn't set.
+ * Returns 1 if the event was handled, meaning it should be removed from
+ * the queue. Returns 0 if the event was not handled, meaning it should
+ * stay on the queue. The only time the event isn't handled is if the
+ * TCL_TIMER_EVENTS flag bit isn't set.
*
* Side effects:
- * Whatever the timer handler callback procedures do.
+ * Whatever the timer handler callback functions do.
*
*----------------------------------------------------------------------
*/
static int
-TimerHandlerEventProc(evPtr, flags)
- Tcl_Event *evPtr; /* Event to service. */
- int flags; /* Flags that indicate what events to
- * handle, such as TCL_FILE_EVENTS. */
+TimerHandlerEventProc(
+ Tcl_Event *evPtr, /* Event to service. */
+ int flags) /* Flags that indicate what events to handle,
+ * such as TCL_FILE_EVENTS. */
{
TimerHandler *timerHandlerPtr, **nextPtrPtr;
Tcl_Time time;
@@ -475,9 +513,9 @@ TimerHandlerEventProc(evPtr, flags)
ThreadSpecificData *tsdPtr = InitTimer();
/*
- * Do nothing if timers aren't enabled. This leaves the event on the
- * queue, so we will get to it as soon as ServiceEvents() is called
- * with timers enabled.
+ * Do nothing if timers aren't enabled. This leaves the event on the
+ * queue, so we will get to it as soon as ServiceEvents() is called with
+ * timers enabled.
*/
if (!(flags & TCL_TIMER_EVENTS)) {
@@ -485,30 +523,28 @@ TimerHandlerEventProc(evPtr, flags)
}
/*
- * The code below is trickier than it may look, for the following
- * reasons:
+ * The code below is trickier than it may look, for the following reasons:
*
- * 1. New handlers can get added to the list while the current
- * one is being processed. If new ones get added, we don't
- * want to process them during this pass through the list to avoid
- * starving other event sources. This is implemented using the
- * token number in the handler: new handlers will have a
- * newer token than any of the ones currently on the list.
- * 2. The handler can call Tcl_DoOneEvent, so we have to remove
- * the handler from the list before calling it. Otherwise an
- * infinite loop could result.
- * 3. Tcl_DeleteTimerHandler can be called to remove an element from
- * the list while a handler is executing, so the list could
- * change structure during the call.
- * 4. Because we only fetch the current time before entering the loop,
- * the only way a new timer will even be considered runnable is if
- * its expiration time is within the same millisecond as the
- * current time. This is fairly likely on Windows, since it has
- * a course granularity clock. Since timers are placed
- * on the queue in time order with the most recently created
- * handler appearing after earlier ones with the same expiration
- * time, we don't have to worry about newer generation timers
- * appearing before later ones.
+ * 1. New handlers can get added to the list while the current one is
+ * being processed. If new ones get added, we don't want to process
+ * them during this pass through the list to avoid starving other event
+ * sources. This is implemented using the token number in the handler:
+ * new handlers will have a newer token than any of the ones currently
+ * on the list.
+ * 2. The handler can call Tcl_DoOneEvent, so we have to remove the
+ * handler from the list before calling it. Otherwise an infinite loop
+ * could result.
+ * 3. Tcl_DeleteTimerHandler can be called to remove an element from the
+ * list while a handler is executing, so the list could change
+ * structure during the call.
+ * 4. Because we only fetch the current time before entering the loop, the
+ * only way a new timer will even be considered runnable is if its
+ * expiration time is within the same millisecond as the current time.
+ * This is fairly likely on Windows, since it has a course granularity
+ * clock. Since timers are placed on the queue in time order with the
+ * most recently created handler appearing after earlier ones with the
+ * same expiration time, we don't have to worry about newer generation
+ * timers appearing before later ones.
*/
tsdPtr->timerPending = 0;
@@ -520,10 +556,8 @@ TimerHandlerEventProc(evPtr, flags)
if (timerHandlerPtr == NULL) {
break;
}
-
- if ((timerHandlerPtr->time.sec > time.sec)
- || ((timerHandlerPtr->time.sec == time.sec)
- && (timerHandlerPtr->time.usec > time.usec))) {
+
+ if (TCL_TIME_BEFORE(time, timerHandlerPtr->time)) {
break;
}
@@ -531,13 +565,13 @@ TimerHandlerEventProc(evPtr, flags)
* Bail out if the next timer is of a newer generation.
*/
- if ((currentTimerId - (int)timerHandlerPtr->token) < 0) {
+ if ((currentTimerId - PTR2INT(timerHandlerPtr->token)) < 0) {
break;
}
/*
- * Remove the handler from the queue before invoking it,
- * to avoid potential reentrancy problems.
+ * Remove the handler from the queue before invoking it, to avoid
+ * potential reentrancy problems.
*/
(*nextPtrPtr) = timerHandlerPtr->nextPtr;
@@ -553,24 +587,24 @@ TimerHandlerEventProc(evPtr, flags)
*
* Tcl_DoWhenIdle --
*
- * Arrange for proc to be invoked the next time the system is
- * idle (i.e., just before the next time that Tcl_DoOneEvent
- * would have to wait for something to happen).
+ * Arrange for proc to be invoked the next time the system is idle (i.e.,
+ * just before the next time that Tcl_DoOneEvent would have to wait for
+ * something to happen).
*
* Results:
* None.
*
* Side effects:
- * Proc will eventually be called, with clientData as argument.
- * See the manual entry for details.
+ * Proc will eventually be called, with clientData as argument. See the
+ * manual entry for details.
*
*--------------------------------------------------------------
*/
void
-Tcl_DoWhenIdle(proc, clientData)
- Tcl_IdleProc *proc; /* Procedure to invoke. */
- ClientData clientData; /* Arbitrary value to pass to proc. */
+Tcl_DoWhenIdle(
+ Tcl_IdleProc *proc, /* Function to invoke. */
+ ClientData clientData) /* Arbitrary value to pass to proc. */
{
register IdleHandler *idlePtr;
Tcl_Time blockTime;
@@ -598,23 +632,23 @@ Tcl_DoWhenIdle(proc, clientData)
*
* Tcl_CancelIdleCall --
*
- * If there are any when-idle calls requested to a given procedure
- * with given clientData, cancel all of them.
+ * If there are any when-idle calls requested to a given function with
+ * given clientData, cancel all of them.
*
* Results:
* None.
*
* Side effects:
- * If the proc/clientData combination were on the when-idle list,
- * they are removed so that they will never be called.
+ * If the proc/clientData combination were on the when-idle list, they
+ * are removed so that they will never be called.
*
*----------------------------------------------------------------------
*/
void
-Tcl_CancelIdleCall(proc, clientData)
- Tcl_IdleProc *proc; /* Procedure that was previously registered. */
- ClientData clientData; /* Arbitrary value to pass to proc. */
+Tcl_CancelIdleCall(
+ Tcl_IdleProc *proc, /* Function that was previously registered. */
+ ClientData clientData) /* Arbitrary value to pass to proc. */
{
register IdleHandler *idlePtr, *prevPtr;
IdleHandler *nextPtr;
@@ -645,14 +679,13 @@ Tcl_CancelIdleCall(proc, clientData)
*
* TclServiceIdle --
*
- * This procedure is invoked by the notifier when it becomes
- * idle. It will invoke all idle handlers that are present at
- * the time the call is invoked, but not those added during idle
- * processing.
+ * This function is invoked by the notifier when it becomes idle. It will
+ * invoke all idle handlers that are present at the time the call is
+ * invoked, but not those added during idle processing.
*
* Results:
- * The return value is 1 if TclServiceIdle found something to
- * do, otherwise return value is 0.
+ * The return value is 1 if TclServiceIdle found something to do,
+ * otherwise return value is 0.
*
* Side effects:
* Invokes all pending idle handlers.
@@ -661,7 +694,7 @@ Tcl_CancelIdleCall(proc, clientData)
*/
int
-TclServiceIdle()
+TclServiceIdle(void)
{
IdleHandler *idlePtr;
int oldGeneration;
@@ -676,22 +709,20 @@ TclServiceIdle()
tsdPtr->idleGeneration++;
/*
- * The code below is trickier than it may look, for the following
- * reasons:
+ * The code below is trickier than it may look, for the following reasons:
*
- * 1. New handlers can get added to the list while the current
- * one is being processed. If new ones get added, we don't
- * want to process them during this pass through the list (want
- * to check for other work to do first). This is implemented
- * using the generation number in the handler: new handlers
- * will have a different generation than any of the ones currently
- * on the list.
- * 2. The handler can call Tcl_DoOneEvent, so we have to remove
- * the handler from the list before calling it. Otherwise an
- * infinite loop could result.
- * 3. Tcl_CancelIdleCall can be called to remove an element from
- * the list while a handler is executing, so the list could
- * change structure during the call.
+ * 1. New handlers can get added to the list while the current one is
+ * being processed. If new ones get added, we don't want to process
+ * them during this pass through the list (want to check for other work
+ * to do first). This is implemented using the generation number in the
+ * handler: new handlers will have a different generation than any of
+ * the ones currently on the list.
+ * 2. The handler can call Tcl_DoOneEvent, so we have to remove the
+ * handler from the list before calling it. Otherwise an infinite loop
+ * could result.
+ * 3. Tcl_CancelIdleCall can be called to remove an element from the list
+ * while a handler is executing, so the list could change structure
+ * during the call.
*/
for (idlePtr = tsdPtr->idleList;
@@ -718,8 +749,8 @@ TclServiceIdle()
*
* Tcl_AfterObjCmd --
*
- * This procedure is invoked to process the "after" Tcl command.
- * See the user documentation for details on what it does.
+ * This function is invoked to process the "after" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -732,21 +763,21 @@ TclServiceIdle()
/* ARGSUSED */
int
-Tcl_AfterObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Unused */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_AfterObjCmd(
+ ClientData clientData, /* Unused */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
- int ms;
+ Tcl_WideInt ms; /* Number of milliseconds to wait */
+ Tcl_Time wakeup;
AfterInfo *afterPtr;
AfterAssocData *assocPtr;
int length;
- char *argString;
int index;
char buf[16 + TCL_INTEGER_SPACE];
static CONST char *afterSubCmds[] = {
- "cancel", "idle", "info", (char *) NULL
+ "cancel", "idle", "info", NULL
};
enum afterSubCmds {AFTER_CANCEL, AFTER_IDLE, AFTER_INFO};
ThreadSpecificData *tsdPtr = InitTimer();
@@ -757,11 +788,11 @@ Tcl_AfterObjCmd(clientData, interp, objc, objv)
}
/*
- * Create the "after" information associated for this interpreter,
- * if it doesn't already exist.
+ * Create the "after" information associated for this interpreter, if it
+ * doesn't already exist.
*/
- assocPtr = Tcl_GetAssocData( interp, "tclAfter", NULL );
+ assocPtr = Tcl_GetAssocData(interp, "tclAfter", NULL);
if (assocPtr == NULL) {
assocPtr = (AfterAssocData *) ckalloc(sizeof(AfterAssocData));
assocPtr->interp = interp;
@@ -774,23 +805,35 @@ Tcl_AfterObjCmd(clientData, interp, objc, objv)
* First lets see if the command was passed a number as the first argument.
*/
- if (objv[1]->typePtr == &tclIntType) {
- ms = (int) objv[1]->internalRep.longValue;
- goto processInteger;
- }
- argString = Tcl_GetStringFromObj(objv[1], &length);
- if (argString[0] == '+' || argString[0] == '-'
- || isdigit(UCHAR(argString[0]))) { /* INTL: digit */
- if (Tcl_GetIntFromObj(interp, objv[1], &ms) != TCL_OK) {
+ if (objv[1]->typePtr == &tclIntType
+#ifndef NO_WIDE_TYPE
+ || objv[1]->typePtr == &tclWideIntType
+#endif
+ || objv[1]->typePtr == &tclBignumType
+ || ( Tcl_GetIndexFromObj(NULL, objv[1], afterSubCmds, "", 0,
+ &index) != TCL_OK )) {
+ index = -1;
+ if (Tcl_GetWideIntFromObj(NULL, objv[1], &ms) != TCL_OK) {
+ Tcl_AppendResult(interp, "bad argument \"",
+ Tcl_GetString(objv[1]),
+ "\": must be cancel, idle, info, or an integer",
+ NULL);
return TCL_ERROR;
}
-processInteger:
+ }
+
+ /*
+ * At this point, either index = -1 and ms contains the number of ms
+ * to wait, or else index is the index of a subcommand.
+ */
+
+ switch (index) {
+ case -1: {
if (ms < 0) {
ms = 0;
}
if (objc == 2) {
- Tcl_Sleep(ms);
- return TCL_OK;
+ return AfterDelay(interp, ms);
}
afterPtr = (AfterInfo *) ckalloc((unsigned) (sizeof(AfterInfo)));
afterPtr->assocPtr = assocPtr;
@@ -800,135 +843,202 @@ processInteger:
afterPtr->commandPtr = Tcl_ConcatObj(objc-2, objv+2);
}
Tcl_IncrRefCount(afterPtr->commandPtr);
+
/*
- * The variable below is used to generate unique identifiers for
- * after commands. This id can wrap around, which can potentially
- * cause problems. However, there are not likely to be problems
- * in practice, because after commands can only be requested to
- * about a month in the future, and wrap-around is unlikely to
- * occur in less than about 1-10 years. Thus it's unlikely that
- * any old ids will still be around when wrap-around occurs.
+ * The variable below is used to generate unique identifiers for after
+ * commands. This id can wrap around, which can potentially cause
+ * problems. However, there are not likely to be problems in practice,
+ * because after commands can only be requested to about a month in
+ * the future, and wrap-around is unlikely to occur in less than about
+ * 1-10 years. Thus it's unlikely that any old ids will still be
+ * around when wrap-around occurs.
*/
+
afterPtr->id = tsdPtr->afterId;
tsdPtr->afterId += 1;
- afterPtr->token = Tcl_CreateTimerHandler(ms, AfterProc,
- (ClientData) afterPtr);
+ Tcl_GetTime(&wakeup);
+ wakeup.sec += (long)(ms / 1000);
+ wakeup.usec += ((long)(ms % 1000)) * 1000;
+ if (wakeup.usec > 1000000) {
+ wakeup.sec++;
+ wakeup.usec -= 1000000;
+ }
+ afterPtr->token = TclCreateAbsoluteTimerHandler(&wakeup, AfterProc,
+ (ClientData) afterPtr);
afterPtr->nextPtr = assocPtr->firstAfterPtr;
assocPtr->firstAfterPtr = afterPtr;
- sprintf(buf, "after#%d", afterPtr->id);
- Tcl_AppendResult(interp, buf, (char *) NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("after#%d", afterPtr->id));
return TCL_OK;
}
+ case AFTER_CANCEL: {
+ Tcl_Obj *commandPtr;
+ char *command, *tempCommand;
+ int tempLength;
- /*
- * If it's not a number it must be a subcommand.
- */
-
- if (Tcl_GetIndexFromObj(NULL, objv[1], afterSubCmds, "argument",
- 0, &index) != TCL_OK) {
- Tcl_AppendResult(interp, "bad argument \"", argString,
- "\": must be cancel, idle, info, or a number",
- (char *) NULL);
- return TCL_ERROR;
- }
- switch ((enum afterSubCmds) index) {
- case AFTER_CANCEL: {
- Tcl_Obj *commandPtr;
- char *command, *tempCommand;
- int tempLength;
-
- if (objc < 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "id|command");
- return TCL_ERROR;
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "id|command");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ commandPtr = objv[2];
+ } else {
+ commandPtr = Tcl_ConcatObj(objc-2, objv+2);;
+ }
+ command = Tcl_GetStringFromObj(commandPtr, &length);
+ for (afterPtr = assocPtr->firstAfterPtr; afterPtr != NULL;
+ afterPtr = afterPtr->nextPtr) {
+ tempCommand = Tcl_GetStringFromObj(afterPtr->commandPtr,
+ &tempLength);
+ if ((length == tempLength)
+ && (memcmp((void*) command, (void*) tempCommand,
+ (unsigned) length) == 0)) {
+ break;
}
- if (objc == 3) {
- commandPtr = objv[2];
+ }
+ if (afterPtr == NULL) {
+ afterPtr = GetAfterEvent(assocPtr, commandPtr);
+ }
+ if (objc != 3) {
+ Tcl_DecrRefCount(commandPtr);
+ }
+ if (afterPtr != NULL) {
+ if (afterPtr->token != NULL) {
+ Tcl_DeleteTimerHandler(afterPtr->token);
} else {
- commandPtr = Tcl_ConcatObj(objc-2, objv+2);;
+ Tcl_CancelIdleCall(AfterProc, (ClientData) afterPtr);
}
- command = Tcl_GetStringFromObj(commandPtr, &length);
- for (afterPtr = assocPtr->firstAfterPtr; afterPtr != NULL;
+ FreeAfterPtr(afterPtr);
+ }
+ break;
+ }
+ case AFTER_IDLE:
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "script script ...");
+ return TCL_ERROR;
+ }
+ afterPtr = (AfterInfo *) ckalloc((unsigned) (sizeof(AfterInfo)));
+ afterPtr->assocPtr = assocPtr;
+ if (objc == 3) {
+ afterPtr->commandPtr = objv[2];
+ } else {
+ afterPtr->commandPtr = Tcl_ConcatObj(objc-2, objv+2);
+ }
+ Tcl_IncrRefCount(afterPtr->commandPtr);
+ afterPtr->id = tsdPtr->afterId;
+ tsdPtr->afterId += 1;
+ afterPtr->token = NULL;
+ afterPtr->nextPtr = assocPtr->firstAfterPtr;
+ assocPtr->firstAfterPtr = afterPtr;
+ Tcl_DoWhenIdle(AfterProc, (ClientData) afterPtr);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("after#%d", afterPtr->id));
+ break;
+ case AFTER_INFO: {
+ Tcl_Obj *resultListPtr;
+
+ if (objc == 2) {
+ for (afterPtr = assocPtr->firstAfterPtr; afterPtr != NULL;
afterPtr = afterPtr->nextPtr) {
- tempCommand = Tcl_GetStringFromObj(afterPtr->commandPtr,
- &tempLength);
- if ((length == tempLength)
- && (memcmp((void*) command, (void*) tempCommand,
- (unsigned) length) == 0)) {
- break;
- }
- }
- if (afterPtr == NULL) {
- afterPtr = GetAfterEvent(assocPtr, commandPtr);
- }
- if (objc != 3) {
- Tcl_DecrRefCount(commandPtr);
- }
- if (afterPtr != NULL) {
- if (afterPtr->token != NULL) {
- Tcl_DeleteTimerHandler(afterPtr->token);
- } else {
- Tcl_CancelIdleCall(AfterProc, (ClientData) afterPtr);
+ if (assocPtr->interp == interp) {
+ sprintf(buf, "after#%d", afterPtr->id);
+ Tcl_AppendElement(interp, buf);
}
- FreeAfterPtr(afterPtr);
}
- break;
+ return TCL_OK;
+ }
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?id?");
+ return TCL_ERROR;
+ }
+ afterPtr = GetAfterEvent(assocPtr, objv[2]);
+ if (afterPtr == NULL) {
+ Tcl_AppendResult(interp, "event \"", TclGetString(objv[2]),
+ "\" doesn't exist", NULL);
+ return TCL_ERROR;
}
- case AFTER_IDLE:
- if (objc < 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "script script ...");
+ resultListPtr = Tcl_NewObj();
+ Tcl_ListObjAppendElement(interp, resultListPtr, afterPtr->commandPtr);
+ Tcl_ListObjAppendElement(interp, resultListPtr, Tcl_NewStringObj(
+ (afterPtr->token == NULL) ? "idle" : "timer", -1));
+ Tcl_SetObjResult(interp, resultListPtr);
+ break;
+ }
+ default:
+ Tcl_Panic("Tcl_AfterObjCmd: bad subcommand index to afterSubCmds");
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AfterDelay --
+ *
+ * Implements the blocking delay behaviour of [after $time]. Tricky
+ * because it has to take into account any time limit that has been set.
+ *
+ * Results:
+ * Standard Tcl result code (with error set if an error occurred due to a
+ * time limit being exceeded).
+ *
+ * Side effects:
+ * May adjust the time limit granularity marker.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+AfterDelay(
+ Tcl_Interp *interp,
+ Tcl_WideInt ms)
+{
+ Interp *iPtr = (Interp *) interp;
+
+ Tcl_Time endTime, now;
+ Tcl_WideInt diff;
+
+ Tcl_GetTime(&endTime);
+ endTime.sec += (long)(ms/1000);
+ endTime.usec += ((int)(ms%1000))*1000;
+ if (endTime.usec >= 1000000) {
+ endTime.sec++;
+ endTime.usec -= 1000000;
+ }
+
+ do {
+ Tcl_GetTime(&now);
+ if (iPtr->limit.timeEvent != NULL
+ && TCL_TIME_BEFORE(iPtr->limit.time, now)) {
+ iPtr->limit.granularityTicker = 0;
+ if (Tcl_LimitCheck(interp) != TCL_OK) {
return TCL_ERROR;
}
- afterPtr = (AfterInfo *) ckalloc((unsigned) (sizeof(AfterInfo)));
- afterPtr->assocPtr = assocPtr;
- if (objc == 3) {
- afterPtr->commandPtr = objv[2];
- } else {
- afterPtr->commandPtr = Tcl_ConcatObj(objc-2, objv+2);
+ }
+ if (iPtr->limit.timeEvent == NULL
+ || TCL_TIME_BEFORE(endTime, iPtr->limit.time)) {
+ diff = TCL_TIME_DIFF_MS(endTime, now);
+#ifndef TCL_WIDE_INT_IS_LONG
+ if (diff > LONG_MAX) {
+ diff = LONG_MAX;
}
- Tcl_IncrRefCount(afterPtr->commandPtr);
- afterPtr->id = tsdPtr->afterId;
- tsdPtr->afterId += 1;
- afterPtr->token = NULL;
- afterPtr->nextPtr = assocPtr->firstAfterPtr;
- assocPtr->firstAfterPtr = afterPtr;
- Tcl_DoWhenIdle(AfterProc, (ClientData) afterPtr);
- sprintf(buf, "after#%d", afterPtr->id);
- Tcl_AppendResult(interp, buf, (char *) NULL);
- break;
- case AFTER_INFO: {
- Tcl_Obj *resultListPtr;
-
- if (objc == 2) {
- for (afterPtr = assocPtr->firstAfterPtr; afterPtr != NULL;
- afterPtr = afterPtr->nextPtr) {
- if (assocPtr->interp == interp) {
- sprintf(buf, "after#%d", afterPtr->id);
- Tcl_AppendElement(interp, buf);
- }
- }
- return TCL_OK;
+#endif
+ if (diff > 0) {
+ Tcl_Sleep((long)diff);
}
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "?id?");
- return TCL_ERROR;
+ } else {
+ diff = TCL_TIME_DIFF_MS(iPtr->limit.time, now);
+#ifndef TCL_WIDE_INT_IS_LONG
+ if (diff > LONG_MAX) {
+ diff = LONG_MAX;
}
- afterPtr = GetAfterEvent(assocPtr, objv[2]);
- if (afterPtr == NULL) {
- Tcl_AppendResult(interp, "event \"", Tcl_GetString(objv[2]),
- "\" doesn't exist", (char *) NULL);
+#endif
+ if (diff > 0) {
+ Tcl_Sleep((long)diff);
+ }
+ if (Tcl_LimitCheck(interp) != TCL_OK) {
return TCL_ERROR;
}
- resultListPtr = Tcl_GetObjResult(interp);
- Tcl_ListObjAppendElement(interp, resultListPtr, afterPtr->commandPtr);
- Tcl_ListObjAppendElement(interp, resultListPtr, Tcl_NewStringObj(
- (afterPtr->token == NULL) ? "idle" : "timer", -1));
- Tcl_SetObjResult(interp, resultListPtr);
- break;
- }
- default: {
- panic("Tcl_AfterObjCmd: bad subcommand index to afterSubCmds");
}
- }
+ } while (TCL_TIME_BEFORE(now, endTime));
return TCL_OK;
}
@@ -937,13 +1047,13 @@ processInteger:
*
* GetAfterEvent --
*
- * This procedure parses an "after" id such as "after#4" and
- * returns a pointer to the AfterInfo structure.
+ * This function parses an "after" id such as "after#4" and returns a
+ * pointer to the AfterInfo structure.
*
* Results:
- * The return value is either a pointer to an AfterInfo structure,
- * if one is found that corresponds to "cmdString" and is for interp,
- * or NULL if no corresponding after event can be found.
+ * The return value is either a pointer to an AfterInfo structure, if one
+ * is found that corresponds to "cmdString" and is for interp, or NULL if
+ * no corresponding after event can be found.
*
* Side effects:
* None.
@@ -952,18 +1062,18 @@ processInteger:
*/
static AfterInfo *
-GetAfterEvent(assocPtr, commandPtr)
- AfterAssocData *assocPtr; /* Points to "after"-related information for
+GetAfterEvent(
+ AfterAssocData *assocPtr, /* Points to "after"-related information for
* this interpreter. */
- Tcl_Obj *commandPtr;
+ Tcl_Obj *commandPtr)
{
- char *cmdString; /* Textual identifier for after event, such
- * as "after#6". */
+ char *cmdString; /* Textual identifier for after event, such as
+ * "after#6". */
AfterInfo *afterPtr;
int id;
char *end;
- cmdString = Tcl_GetString(commandPtr);
+ cmdString = TclGetString(commandPtr);
if (strncmp(cmdString, "after#", 6) != 0) {
return NULL;
}
@@ -986,37 +1096,34 @@ GetAfterEvent(assocPtr, commandPtr)
*
* AfterProc --
*
- * Timer callback to execute commands registered with the
- * "after" command.
+ * Timer callback to execute commands registered with the "after"
+ * command.
*
* Results:
* None.
*
* Side effects:
- * Executes whatever command was specified. If the command
- * returns an error, then the command "bgerror" is invoked
- * to process the error; if bgerror fails then information
- * about the error is output on stderr.
+ * Executes whatever command was specified. If the command returns an
+ * error, then the command "bgerror" is invoked to process the error; if
+ * bgerror fails then information about the error is output on stderr.
*
*----------------------------------------------------------------------
*/
static void
-AfterProc(clientData)
- ClientData clientData; /* Describes command to execute. */
+AfterProc(
+ ClientData clientData) /* Describes command to execute. */
{
AfterInfo *afterPtr = (AfterInfo *) clientData;
AfterAssocData *assocPtr = afterPtr->assocPtr;
AfterInfo *prevPtr;
int result;
Tcl_Interp *interp;
- char *script;
- int numBytes;
/*
- * First remove the callback from our list of callbacks; otherwise
- * someone could delete the callback while it's being executed, which
- * could cause a core dump.
+ * First remove the callback from our list of callbacks; otherwise someone
+ * could delete the callback while it's being executed, which could cause
+ * a core dump.
*/
if (assocPtr->firstAfterPtr == afterPtr) {
@@ -1035,14 +1142,13 @@ AfterProc(clientData)
interp = assocPtr->interp;
Tcl_Preserve((ClientData) interp);
- script = Tcl_GetStringFromObj(afterPtr->commandPtr, &numBytes);
- result = Tcl_EvalEx(interp, script, numBytes, TCL_EVAL_GLOBAL);
+ result = Tcl_EvalObjEx(interp, afterPtr->commandPtr, TCL_EVAL_GLOBAL);
if (result != TCL_OK) {
Tcl_AddErrorInfo(interp, "\n (\"after\" script)");
- Tcl_BackgroundError(interp);
+ TclBackgroundException(interp, result);
}
Tcl_Release((ClientData) interp);
-
+
/*
* Free the memory for the callback.
*/
@@ -1056,10 +1162,9 @@ AfterProc(clientData)
*
* FreeAfterPtr --
*
- * This procedure removes an "after" command from the list of
- * those that are pending and frees its resources. This procedure
- * does *not* cancel the timer handler; if that's needed, the
- * caller must do it.
+ * This function removes an "after" command from the list of those that
+ * are pending and frees its resources. This function does *not* cancel
+ * the timer handler; if that's needed, the caller must do it.
*
* Results:
* None.
@@ -1071,8 +1176,8 @@ AfterProc(clientData)
*/
static void
-FreeAfterPtr(afterPtr)
- AfterInfo *afterPtr; /* Command to be deleted. */
+FreeAfterPtr(
+ AfterInfo *afterPtr) /* Command to be deleted. */
{
AfterInfo *prevPtr;
AfterAssocData *assocPtr = afterPtr->assocPtr;
@@ -1095,7 +1200,7 @@ FreeAfterPtr(afterPtr)
*
* AfterCleanupProc --
*
- * This procedure is invoked whenever an interpreter is deleted
+ * This function is invoked whenever an interpreter is deleted
* to cleanup the AssocData for "tclAfter".
*
* Results:
@@ -1109,10 +1214,10 @@ FreeAfterPtr(afterPtr)
/* ARGSUSED */
static void
-AfterCleanupProc(clientData, interp)
- ClientData clientData; /* Points to AfterAssocData for the
+AfterCleanupProc(
+ ClientData clientData, /* Points to AfterAssocData for the
* interpreter. */
- Tcl_Interp *interp; /* Interpreter that is being deleted. */
+ Tcl_Interp *interp) /* Interpreter that is being deleted. */
{
AfterAssocData *assocPtr = (AfterAssocData *) clientData;
AfterInfo *afterPtr;
@@ -1130,3 +1235,11 @@ AfterCleanupProc(clientData, interp)
}
ckfree((char *) assocPtr);
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclTomMath.decls b/generic/tclTomMath.decls
new file mode 100644
index 0000000..191312f
--- /dev/null
+++ b/generic/tclTomMath.decls
@@ -0,0 +1,222 @@
+# tclTomMath.decls --
+#
+# This file contains the declarations for the functions in
+# 'libtommath' that are contained within the Tcl library.
+# This file is used to generate the 'tclTomMathDecls.h' and
+# 'tclTomMathStub.c' files.
+#
+# If you edit this file, advance the revision number (and the epoch
+# if the new stubs are not backward compatible) in tclTomMathDecls.h
+#
+# Copyright (c) 2005 by Kevin B. Kenny. All rights reserved.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+library tcl
+
+# Define the unsupported generic interfaces.
+
+interface tclTomMath
+# hooks {tclTomMathInt}
+
+# Declare each of the functions in the Tcl tommath interface
+
+declare 0 generic {
+ int TclBN_epoch(void)
+}
+declare 1 generic {
+ int TclBN_revision(void)
+}
+
+declare 2 generic {
+ int TclBN_mp_add(mp_int *a, mp_int *b, mp_int *c)
+}
+declare 3 generic {
+ int TclBN_mp_add_d(mp_int *a, mp_digit b, mp_int *c)
+}
+declare 4 generic {
+ int TclBN_mp_and(mp_int *a, mp_int *b, mp_int *c)
+}
+declare 5 generic {
+ void TclBN_mp_clamp(mp_int *a)
+}
+declare 6 generic {
+ void TclBN_mp_clear(mp_int *a)
+}
+declare 7 generic {
+ void TclBN_mp_clear_multi(mp_int *a, ...)
+}
+declare 8 generic {
+ int TclBN_mp_cmp(mp_int *a, mp_int *b)
+}
+declare 9 generic {
+ int TclBN_mp_cmp_d(mp_int *a, mp_digit b)
+}
+declare 10 generic {
+ int TclBN_mp_cmp_mag(mp_int *a, mp_int *b)
+}
+declare 11 generic {
+ int TclBN_mp_copy(mp_int *a, mp_int *b)
+}
+declare 12 generic {
+ int TclBN_mp_count_bits(mp_int *a)
+}
+declare 13 generic {
+ int TclBN_mp_div(mp_int *a, mp_int *b, mp_int *q, mp_int *r)
+}
+declare 14 generic {
+ int TclBN_mp_div_d(mp_int *a, mp_digit b, mp_int *q, mp_digit *r)
+}
+declare 15 generic {
+ int TclBN_mp_div_2(mp_int *a, mp_int *q)
+}
+declare 16 generic {
+ int TclBN_mp_div_2d(mp_int *a, int b, mp_int *q, mp_int *r)
+}
+declare 17 generic {
+ int TclBN_mp_div_3(mp_int *a, mp_int *q, mp_digit *r)
+}
+declare 18 generic {
+ void TclBN_mp_exch(mp_int *a, mp_int *b)
+}
+declare 19 generic {
+ int TclBN_mp_expt_d(mp_int *a, mp_digit b, mp_int *c)
+}
+declare 20 generic {
+ int TclBN_mp_grow(mp_int *a, int size)
+}
+declare 21 generic {
+ int TclBN_mp_init(mp_int *a)
+}
+declare 22 generic {
+ int TclBN_mp_init_copy(mp_int *a, mp_int *b)
+}
+declare 23 generic {
+ int TclBN_mp_init_multi(mp_int *a, ...)
+}
+declare 24 generic {
+ int TclBN_mp_init_set(mp_int *a, mp_digit b)
+}
+declare 25 generic {
+ int TclBN_mp_init_size(mp_int *a, int size)
+}
+declare 26 generic {
+ int TclBN_mp_lshd(mp_int *a, int shift)
+}
+declare 27 generic {
+ int TclBN_mp_mod(mp_int *a, mp_int *b, mp_int *r)
+}
+declare 28 generic {
+ int TclBN_mp_mod_2d(mp_int *a, int b, mp_int *r)
+}
+declare 29 generic {
+ int TclBN_mp_mul(mp_int *a, mp_int *b, mp_int *p)
+}
+declare 30 generic {
+ int TclBN_mp_mul_d(mp_int *a, mp_digit b, mp_int *p)
+}
+declare 31 generic {
+ int TclBN_mp_mul_2(mp_int *a, mp_int *p)
+}
+declare 32 generic {
+ int TclBN_mp_mul_2d(mp_int *a, int d, mp_int *p)
+}
+declare 33 generic {
+ int TclBN_mp_neg(mp_int *a, mp_int *b)
+}
+declare 34 generic {
+ int TclBN_mp_or(mp_int *a, mp_int *b, mp_int *c)
+}
+declare 35 generic {
+ int TclBN_mp_radix_size(mp_int *a, int radix, int *size)
+}
+declare 36 generic {
+ int TclBN_mp_read_radix(mp_int *a, const char *str, int radix)
+}
+declare 37 generic {
+ void TclBN_mp_rshd(mp_int *a, int shift)
+}
+declare 38 generic {
+ int TclBN_mp_shrink(mp_int *a)
+}
+declare 39 generic {
+ void TclBN_mp_set(mp_int *a, mp_digit b)
+}
+declare 40 generic {
+ int TclBN_mp_sqr(mp_int *a, mp_int *b)
+}
+declare 41 generic {
+ int TclBN_mp_sqrt(mp_int *a, mp_int *b)
+}
+declare 42 generic {
+ int TclBN_mp_sub(mp_int *a, mp_int *b, mp_int *c)
+}
+declare 43 generic {
+ int TclBN_mp_sub_d(mp_int *a, mp_digit b, mp_int *c)
+}
+declare 44 generic {
+ int TclBN_mp_to_unsigned_bin(mp_int *a, unsigned char *b)
+}
+declare 45 generic {
+ int TclBN_mp_to_unsigned_bin_n(mp_int *a, unsigned char *b,
+ unsigned long *outlen)
+}
+declare 46 generic {
+ int TclBN_mp_toradix_n(mp_int *a, char *str, int radix, int maxlen)
+}
+declare 47 generic {
+ int TclBN_mp_unsigned_bin_size(mp_int *a)
+}
+declare 48 generic {
+ int TclBN_mp_xor(mp_int *a, mp_int *b, mp_int *c)
+}
+declare 49 generic {
+ void TclBN_mp_zero(mp_int *a)
+}
+
+# internal routines to libtommath - should not be called but must be
+# exported to accommodate the "tommath" extension
+
+declare 50 generic {
+ void TclBN_reverse(unsigned char *s, int len)
+}
+declare 51 generic {
+ int TclBN_fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs)
+}
+declare 52 generic {
+ int TclBN_fast_s_mp_sqr(mp_int *a, mp_int *b)
+}
+declare 53 generic {
+ int TclBN_mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c)
+}
+declare 54 generic {
+ int TclBN_mp_karatsuba_sqr(mp_int *a, mp_int *b)
+}
+declare 55 generic {
+ int TclBN_mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
+}
+declare 56 generic {
+ int TclBN_mp_toom_sqr(mp_int *a, mp_int *b)
+}
+declare 57 generic {
+ int TclBN_s_mp_add(mp_int *a, mp_int *b, mp_int *c)
+}
+declare 58 generic {
+ int TclBN_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs)
+}
+declare 59 generic {
+ int TclBN_s_mp_sqr(mp_int *a, mp_int *b)
+}
+declare 60 generic {
+ int TclBN_s_mp_sub(mp_int *a, mp_int *b, mp_int *c)
+}
+declare 61 {
+ int TclBN_mp_init_set_int(mp_int* a, unsigned long i)
+}
+declare 62 {
+ int TclBN_mp_set_int(mp_int* a, unsigned long i)
+}
+declare 63 {
+ int TclBN_mp_cnt_lsb(mp_int* a)
+}
diff --git a/generic/tclTomMath.h b/generic/tclTomMath.h
new file mode 100644
index 0000000..550dafa
--- /dev/null
+++ b/generic/tclTomMath.h
@@ -0,0 +1,836 @@
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+#ifndef BN_H_
+#define BN_H_
+
+#include <tclTomMathDecls.h>
+#ifndef MODULE_SCOPE
+#define MODULE_SCOPE extern
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+
+#ifndef MIN
+ #define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+
+#ifndef MAX
+ #define MAX(x,y) ((x)>(y)?(x):(y))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+
+/* C++ compilers don't like assigning void * to mp_digit * */
+#define OPT_CAST(x) (x *)
+
+#else
+
+/* C on the other hand doesn't care */
+#define OPT_CAST(x)
+
+#endif
+
+
+/* detect 64-bit mode if possible */
+#if defined(NEVER) /* 128-bit ints fail in too many places */
+ #if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT))
+ #define MP_64BIT
+ #endif
+#endif
+
+/* some default configurations.
+ *
+ * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits
+ * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits
+ *
+ * At the very least a mp_digit must be able to hold 7 bits
+ * [any size beyond that is ok provided it doesn't overflow the data type]
+ */
+#ifdef MP_8BIT
+#ifndef MP_DIGIT_DECLARED
+ typedef unsigned char mp_digit;
+#define MP_DIGIT_DECLARED
+#endif
+ typedef unsigned short mp_word;
+#elif defined(MP_16BIT)
+#ifndef MP_DIGIT_DECLARED
+ typedef unsigned short mp_digit;
+#define MP_DIGIT_DECLARED
+#endif
+ typedef unsigned long mp_word;
+#elif defined(MP_64BIT)
+ /* for GCC only on supported platforms */
+#ifndef CRYPT
+ typedef unsigned long long ulong64;
+ typedef signed long long long64;
+#endif
+
+#ifndef MP_DIGIT_DECLARED
+ typedef unsigned long mp_digit;
+#define MP_DIGIT_DECLARED
+#endif
+ typedef unsigned long mp_word __attribute__ ((mode(TI)));
+
+ #define DIGIT_BIT 60
+#else
+ /* this is the default case, 28-bit digits */
+
+ /* this is to make porting into LibTomCrypt easier :-) */
+#ifndef CRYPT
+ #if defined(_MSC_VER) || defined(__BORLANDC__)
+ typedef unsigned __int64 ulong64;
+ typedef signed __int64 long64;
+ #else
+ typedef unsigned long long ulong64;
+ typedef signed long long long64;
+ #endif
+#endif
+
+#ifndef MP_DIGIT_DECLARED
+ typedef unsigned int mp_digit;
+#define MP_DIGIT_DECLARED
+#endif
+ typedef ulong64 mp_word;
+
+#ifdef MP_31BIT
+ /* this is an extension that uses 31-bit digits */
+ #define DIGIT_BIT 31
+#else
+ /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */
+ #define DIGIT_BIT 28
+ #define MP_28BIT
+#endif
+#endif
+
+/* define heap macros */
+#if 0 /* these are macros in tclTomMathDecls.h */
+#ifndef CRYPT
+ /* default to libc stuff */
+ #ifndef XMALLOC
+ #define XMALLOC malloc
+ #define XFREE free
+ #define XREALLOC realloc
+ #define XCALLOC calloc
+ #else
+ /* prototypes for our heap functions */
+ extern void *XMALLOC(size_t n);
+ extern void *XREALLOC(void *p, size_t n);
+ extern void *XCALLOC(size_t n, size_t s);
+ extern void XFREE(void *p);
+ #endif
+#endif
+#endif
+
+
+/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */
+#ifndef DIGIT_BIT
+ #define DIGIT_BIT ((int)((CHAR_BIT * sizeof(mp_digit) - 1))) /* bits per digit */
+#endif
+
+#define MP_DIGIT_BIT DIGIT_BIT
+#define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
+#define MP_DIGIT_MAX MP_MASK
+
+/* equalities */
+#define MP_LT -1 /* less than */
+#define MP_EQ 0 /* equal to */
+#define MP_GT 1 /* greater than */
+
+#define MP_ZPOS 0 /* positive integer */
+#define MP_NEG 1 /* negative */
+
+#define MP_OKAY 0 /* ok result */
+#define MP_MEM -2 /* out of mem */
+#define MP_VAL -3 /* invalid input */
+#define MP_RANGE MP_VAL
+
+#define MP_YES 1 /* yes response */
+#define MP_NO 0 /* no response */
+
+/* Primality generation flags */
+#define LTM_PRIME_BBS 0x0001 /* BBS style prime */
+#define LTM_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */
+#define LTM_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */
+
+typedef int mp_err;
+
+/* you'll have to tune these... */
+#if defined(BUILD_tcl) || !defined(_WIN32)
+MODULE_SCOPE int KARATSUBA_MUL_CUTOFF,
+ KARATSUBA_SQR_CUTOFF,
+ TOOM_MUL_CUTOFF,
+ TOOM_SQR_CUTOFF;
+#endif
+
+/* define this to use lower memory usage routines (exptmods mostly) */
+/* #define MP_LOW_MEM */
+
+/* default precision */
+#ifndef MP_PREC
+ #ifndef MP_LOW_MEM
+ #define MP_PREC 32 /* default digits of precision */
+ #else
+ #define MP_PREC 8 /* default digits of precision */
+ #endif
+#endif
+
+/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
+#define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))
+
+/* the infamous mp_int structure */
+#ifndef MP_INT_DECLARED
+#define MP_INT_DECLARED
+typedef struct mp_int mp_int;
+#endif
+struct mp_int {
+ int used, alloc, sign;
+ mp_digit *dp;
+};
+
+/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
+typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);
+
+
+#define USED(m) ((m)->used)
+#define DIGIT(m,k) ((m)->dp[(k)])
+#define SIGN(m) ((m)->sign)
+
+/* error code to char* string */
+/*
+char *mp_error_to_string(int code);
+*/
+
+/* ---> init and deinit bignum functions <--- */
+/* init a bignum */
+/*
+int mp_init(mp_int *a);
+*/
+
+/* free a bignum */
+/*
+void mp_clear(mp_int *a);
+*/
+
+/* init a null terminated series of arguments */
+/*
+int mp_init_multi(mp_int *mp, ...);
+*/
+
+/* clear a null terminated series of arguments */
+/*
+void mp_clear_multi(mp_int *mp, ...);
+*/
+
+/* exchange two ints */
+/*
+void mp_exch(mp_int *a, mp_int *b);
+*/
+
+/* shrink ram required for a bignum */
+/*
+int mp_shrink(mp_int *a);
+*/
+
+/* grow an int to a given size */
+/*
+int mp_grow(mp_int *a, int size);
+*/
+
+/* init to a given number of digits */
+/*
+int mp_init_size(mp_int *a, int size);
+*/
+
+/* ---> Basic Manipulations <--- */
+#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
+#define mp_iseven(a) (((a)->used == 0 || (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
+#define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
+
+/* set to zero */
+/*
+void mp_zero(mp_int *a);
+*/
+
+/* set to a digit */
+/*
+void mp_set(mp_int *a, mp_digit b);
+*/
+
+/* set a 32-bit const */
+/*
+int mp_set_int(mp_int *a, unsigned long b);
+*/
+
+/* get a 32-bit value */
+unsigned long mp_get_int(mp_int * a);
+
+/* initialize and set a digit */
+/*
+int mp_init_set (mp_int * a, mp_digit b);
+*/
+
+/* initialize and set 32-bit value */
+/*
+int mp_init_set_int (mp_int * a, unsigned long b);
+*/
+
+/* copy, b = a */
+/*
+int mp_copy(mp_int *a, mp_int *b);
+*/
+
+/* inits and copies, a = b */
+/*
+int mp_init_copy(mp_int *a, mp_int *b);
+*/
+
+/* trim unused digits */
+/*
+void mp_clamp(mp_int *a);
+*/
+
+/* ---> digit manipulation <--- */
+
+/* right shift by "b" digits */
+/*
+void mp_rshd(mp_int *a, int b);
+*/
+
+/* left shift by "b" digits */
+/*
+int mp_lshd(mp_int *a, int b);
+*/
+
+/* c = a / 2**b */
+/*
+int mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d);
+*/
+
+/* b = a/2 */
+/*
+int mp_div_2(mp_int *a, mp_int *b);
+*/
+
+/* c = a * 2**b */
+/*
+int mp_mul_2d(mp_int *a, int b, mp_int *c);
+*/
+
+/* b = a*2 */
+/*
+int mp_mul_2(mp_int *a, mp_int *b);
+*/
+
+/* c = a mod 2**d */
+/*
+int mp_mod_2d(mp_int *a, int b, mp_int *c);
+*/
+
+/* computes a = 2**b */
+/*
+int mp_2expt(mp_int *a, int b);
+*/
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+/*
+int mp_cnt_lsb(mp_int *a);
+*/
+
+/* I Love Earth! */
+
+/* makes a pseudo-random int of a given size */
+/*
+int mp_rand(mp_int *a, int digits);
+*/
+
+/* ---> binary operations <--- */
+/* c = a XOR b */
+/*
+int mp_xor(mp_int *a, mp_int *b, mp_int *c);
+*/
+
+/* c = a OR b */
+/*
+int mp_or(mp_int *a, mp_int *b, mp_int *c);
+*/
+
+/* c = a AND b */
+/*
+int mp_and(mp_int *a, mp_int *b, mp_int *c);
+*/
+
+/* ---> Basic arithmetic <--- */
+
+/* b = -a */
+/*
+int mp_neg(mp_int *a, mp_int *b);
+*/
+
+/* b = |a| */
+/*
+int mp_abs(mp_int *a, mp_int *b);
+*/
+
+/* compare a to b */
+/*
+int mp_cmp(mp_int *a, mp_int *b);
+*/
+
+/* compare |a| to |b| */
+/*
+int mp_cmp_mag(mp_int *a, mp_int *b);
+*/
+
+/* c = a + b */
+/*
+int mp_add(mp_int *a, mp_int *b, mp_int *c);
+*/
+
+/* c = a - b */
+/*
+int mp_sub(mp_int *a, mp_int *b, mp_int *c);
+*/
+
+/* c = a * b */
+/*
+int mp_mul(mp_int *a, mp_int *b, mp_int *c);
+*/
+
+/* b = a*a */
+/*
+int mp_sqr(mp_int *a, mp_int *b);
+*/
+
+/* a/b => cb + d == a */
+/*
+int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+*/
+
+/* c = a mod b, 0 <= c < b */
+/*
+int mp_mod(mp_int *a, mp_int *b, mp_int *c);
+*/
+
+/* ---> single digit functions <--- */
+
+/* compare against a single digit */
+/*
+int mp_cmp_d(mp_int *a, mp_digit b);
+*/
+
+/* c = a + b */
+/*
+int mp_add_d(mp_int *a, mp_digit b, mp_int *c);
+*/
+
+/* c = a - b */
+/*
+int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);
+*/
+
+/* c = a * b */
+/*
+int mp_mul_d(mp_int *a, mp_digit b, mp_int *c);
+*/
+
+/* a/b => cb + d == a */
+/*
+int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d);
+*/
+
+/* a/3 => 3c + d == a */
+/*
+int mp_div_3(mp_int *a, mp_int *c, mp_digit *d);
+*/
+
+/* c = a**b */
+/*
+int mp_expt_d(mp_int *a, mp_digit b, mp_int *c);
+*/
+
+/* c = a mod b, 0 <= c < b */
+/*
+int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c);
+*/
+
+/* ---> number theory <--- */
+
+/* d = a + b (mod c) */
+/*
+int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+*/
+
+/* d = a - b (mod c) */
+/*
+int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+*/
+
+/* d = a * b (mod c) */
+/*
+int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+*/
+
+/* c = a * a (mod b) */
+/*
+int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c);
+*/
+
+/* c = 1/a (mod b) */
+/*
+int mp_invmod(mp_int *a, mp_int *b, mp_int *c);
+*/
+
+/* c = (a, b) */
+/*
+int mp_gcd(mp_int *a, mp_int *b, mp_int *c);
+*/
+
+/* produces value such that U1*a + U2*b = U3 */
+/*
+int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3);
+*/
+
+/* c = [a, b] or (a*b)/(a, b) */
+/*
+int mp_lcm(mp_int *a, mp_int *b, mp_int *c);
+*/
+
+/* finds one of the b'th root of a, such that |c|**b <= |a|
+ *
+ * returns error if a < 0 and b is even
+ */
+/*
+int mp_n_root(mp_int *a, mp_digit b, mp_int *c);
+*/
+
+/* special sqrt algo */
+/*
+int mp_sqrt(mp_int *arg, mp_int *ret);
+*/
+
+/* is number a square? */
+/*
+int mp_is_square(mp_int *arg, int *ret);
+*/
+
+/* computes the jacobi c = (a | n) (or Legendre if b is prime) */
+/*
+int mp_jacobi(mp_int *a, mp_int *n, int *c);
+*/
+
+/* used to setup the Barrett reduction for a given modulus b */
+/*
+int mp_reduce_setup(mp_int *a, mp_int *b);
+*/
+
+/* Barrett Reduction, computes a (mod b) with a precomputed value c
+ *
+ * Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely
+ * compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code].
+ */
+/*
+int mp_reduce(mp_int *a, mp_int *b, mp_int *c);
+*/
+
+/* setups the montgomery reduction */
+/*
+int mp_montgomery_setup(mp_int *a, mp_digit *mp);
+*/
+
+/* computes a = B**n mod b without division or multiplication useful for
+ * normalizing numbers in a Montgomery system.
+ */
+/*
+int mp_montgomery_calc_normalization(mp_int *a, mp_int *b);
+*/
+
+/* computes x/R == x (mod N) via Montgomery Reduction */
+/*
+int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
+*/
+
+/* returns 1 if a is a valid DR modulus */
+/*
+int mp_dr_is_modulus(mp_int *a);
+*/
+
+/* sets the value of "d" required for mp_dr_reduce */
+/*
+void mp_dr_setup(mp_int *a, mp_digit *d);
+*/
+
+/* reduces a modulo b using the Diminished Radix method */
+/*
+int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp);
+*/
+
+/* returns true if a can be reduced with mp_reduce_2k */
+/*
+int mp_reduce_is_2k(mp_int *a);
+*/
+
+/* determines k value for 2k reduction */
+/*
+int mp_reduce_2k_setup(mp_int *a, mp_digit *d);
+*/
+
+/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
+/*
+int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);
+*/
+
+/* returns true if a can be reduced with mp_reduce_2k_l */
+/*
+int mp_reduce_is_2k_l(mp_int *a);
+*/
+
+/* determines k value for 2k reduction */
+/*
+int mp_reduce_2k_setup_l(mp_int *a, mp_int *d);
+*/
+
+/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
+/*
+int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d);
+*/
+
+/* d = a**b (mod c) */
+/*
+int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+*/
+
+/* ---> Primes <--- */
+
+/* number of primes */
+#ifdef MP_8BIT
+ #define PRIME_SIZE 31
+#else
+ #define PRIME_SIZE 256
+#endif
+
+/* table of first PRIME_SIZE primes */
+#if defined(BUILD_tcl) || !defined(_WIN32)
+MODULE_SCOPE const mp_digit ltm_prime_tab[];
+#endif
+
+/* result=1 if a is divisible by one of the first PRIME_SIZE primes */
+/*
+int mp_prime_is_divisible(mp_int *a, int *result);
+*/
+
+/* performs one Fermat test of "a" using base "b".
+ * Sets result to 0 if composite or 1 if probable prime
+ */
+/*
+int mp_prime_fermat(mp_int *a, mp_int *b, int *result);
+*/
+
+/* performs one Miller-Rabin test of "a" using base "b".
+ * Sets result to 0 if composite or 1 if probable prime
+ */
+/*
+int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result);
+*/
+
+/* This gives [for a given bit size] the number of trials required
+ * such that Miller-Rabin gives a prob of failure lower than 2^-96
+ */
+/*
+int mp_prime_rabin_miller_trials(int size);
+*/
+
+/* performs t rounds of Miller-Rabin on "a" using the first
+ * t prime bases. Also performs an initial sieve of trial
+ * division. Determines if "a" is prime with probability
+ * of error no more than (1/4)**t.
+ *
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+/*
+int mp_prime_is_prime(mp_int *a, int t, int *result);
+*/
+
+/* finds the next prime after the number "a" using "t" trials
+ * of Miller-Rabin.
+ *
+ * bbs_style = 1 means the prime must be congruent to 3 mod 4
+ */
+/*
+int mp_prime_next_prime(mp_int *a, int t, int bbs_style);
+*/
+
+/* makes a truly random prime of a given size (bytes),
+ * call with bbs = 1 if you want it to be congruent to 3 mod 4
+ *
+ * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ * The prime generated will be larger than 2^(8*size).
+ */
+#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)
+
+/* makes a truly random prime of a given size (bits),
+ *
+ * Flags are as follows:
+ *
+ * LTM_PRIME_BBS - make prime congruent to 3 mod 4
+ * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
+ * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
+ * LTM_PRIME_2MSB_ON - make the 2nd highest bit one
+ *
+ * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ */
+/*
+int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat);
+*/
+
+/* ---> radix conversion <--- */
+/*
+int mp_count_bits(mp_int *a);
+*/
+
+/*
+int mp_unsigned_bin_size(mp_int *a);
+*/
+/*
+int mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c);
+*/
+/*
+int mp_to_unsigned_bin(mp_int *a, unsigned char *b);
+*/
+/*
+int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen);
+*/
+
+/*
+int mp_signed_bin_size(mp_int *a);
+*/
+/*
+int mp_read_signed_bin(mp_int *a, const unsigned char *b, int c);
+*/
+/*
+int mp_to_signed_bin(mp_int *a, unsigned char *b);
+*/
+/*
+int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen);
+*/
+
+/*
+int mp_read_radix(mp_int *a, const char *str, int radix);
+*/
+/*
+int mp_toradix(mp_int *a, char *str, int radix);
+*/
+/*
+int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen);
+*/
+/*
+int mp_radix_size(mp_int *a, int radix, int *size);
+*/
+
+/*
+int mp_fread(mp_int *a, int radix, FILE *stream);
+*/
+/*
+int mp_fwrite(mp_int *a, int radix, FILE *stream);
+*/
+
+#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
+#define mp_raw_size(mp) mp_signed_bin_size(mp)
+#define mp_toraw(mp, str) mp_to_signed_bin((mp), (str))
+#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
+#define mp_mag_size(mp) mp_unsigned_bin_size(mp)
+#define mp_tomag(mp, str) mp_to_unsigned_bin((mp), (str))
+
+#define mp_tobinary(M, S) mp_toradix((M), (S), 2)
+#define mp_tooctal(M, S) mp_toradix((M), (S), 8)
+#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
+#define mp_tohex(M, S) mp_toradix((M), (S), 16)
+
+/* lowlevel functions, do not call! */
+/*
+int s_mp_add(mp_int *a, mp_int *b, mp_int *c);
+*/
+/*
+int s_mp_sub(mp_int *a, mp_int *b, mp_int *c);
+*/
+#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)
+/*
+int fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+*/
+/*
+int s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+*/
+/*
+int fast_s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+*/
+/*
+int s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+*/
+/*
+int fast_s_mp_sqr(mp_int *a, mp_int *b);
+*/
+/*
+int s_mp_sqr(mp_int *a, mp_int *b);
+*/
+/*
+int mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c);
+*/
+/*
+int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c);
+*/
+/*
+int mp_karatsuba_sqr(mp_int *a, mp_int *b);
+*/
+/*
+int mp_toom_sqr(mp_int *a, mp_int *b);
+*/
+/*
+int fast_mp_invmod(mp_int *a, mp_int *b, mp_int *c);
+*/
+/*
+int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c);
+*/
+/*
+int fast_mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
+*/
+/*
+int mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int mode);
+*/
+/*
+int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int mode);
+*/
+/*
+void bn_reverse(unsigned char *s, int len);
+*/
+
+#if defined(BUILD_tcl) || !defined(_WIN32)
+MODULE_SCOPE const char *mp_s_rmap;
+#endif
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff --git a/generic/tclTomMathDecls.h b/generic/tclTomMathDecls.h
new file mode 100644
index 0000000..4d5515b
--- /dev/null
+++ b/generic/tclTomMathDecls.h
@@ -0,0 +1,819 @@
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclTomMathDecls.h --
+ *
+ * This file contains the declarations for the 'libtommath'
+ * functions that are exported by the Tcl library.
+ *
+ * Copyright (c) 2005 by Kevin B. Kenny. All rights reserved.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TCLTOMMATHDECLS
+#define _TCLTOMMATHDECLS
+
+#include "tcl.h"
+
+/*
+ * Define the version of the Stubs table that's exported for tommath
+ */
+
+#define TCLTOMMATH_EPOCH 0
+#define TCLTOMMATH_REVISION 0
+
+#define Tcl_TomMath_InitStubs(interp,version) \
+ (TclTomMathInitializeStubs((interp),(version),\
+ TCLTOMMATH_EPOCH,TCLTOMMATH_REVISION))
+
+/* Define custom memory allocation for libtommath */
+
+/* MODULE_SCOPE void* TclBNAlloc( size_t ); */
+#define TclBNAlloc(s) ((void*)ckalloc((size_t)(s)))
+/* MODULE_SCOPE void* TclBNRealloc( void*, size_t ); */
+#define TclBNRealloc(x,s) ((void*)ckrealloc((char*)(x),(size_t)(s)))
+/* MODULE_SCOPE void TclBNFree( void* ); */
+#define TclBNFree(x) (ckfree((char*)(x)))
+/* MODULE_SCOPE void* TclBNCalloc( size_t, size_t ); */
+/* unused - no macro */
+
+#define XMALLOC(x) TclBNAlloc(x)
+#define XFREE(x) TclBNFree(x)
+#define XREALLOC(x,n) TclBNRealloc(x,n)
+#define XCALLOC(n,x) TclBNCalloc(n,x)
+
+/* Rename the global symbols in libtommath to avoid linkage conflicts */
+
+#define KARATSUBA_MUL_CUTOFF TclBNKaratsubaMulCutoff
+#define KARATSUBA_SQR_CUTOFF TclBNKaratsubaSqrCutoff
+#define TOOM_MUL_CUTOFF TclBNToomMulCutoff
+#define TOOM_SQR_CUTOFF TclBNToomSqrCutoff
+
+#define bn_reverse TclBN_reverse
+#define fast_s_mp_mul_digs TclBN_fast_s_mp_mul_digs
+#define fast_s_mp_sqr TclBN_fast_s_mp_sqr
+#define mp_add TclBN_mp_add
+#define mp_add_d TclBN_mp_add_d
+#define mp_and TclBN_mp_and
+#define mp_clamp TclBN_mp_clamp
+#define mp_clear TclBN_mp_clear
+#define mp_clear_multi TclBN_mp_clear_multi
+#define mp_cmp TclBN_mp_cmp
+#define mp_cmp_d TclBN_mp_cmp_d
+#define mp_cmp_mag TclBN_mp_cmp_mag
+#define mp_cnt_lsb TclBN_mp_cnt_lsb
+#define mp_copy TclBN_mp_copy
+#define mp_count_bits TclBN_mp_count_bits
+#define mp_div TclBN_mp_div
+#define mp_div_2 TclBN_mp_div_2
+#define mp_div_2d TclBN_mp_div_2d
+#define mp_div_3 TclBN_mp_div_3
+#define mp_div_d TclBN_mp_div_d
+#define mp_exch TclBN_mp_exch
+#define mp_expt_d TclBN_mp_expt_d
+#define mp_grow TclBN_mp_grow
+#define mp_init TclBN_mp_init
+#define mp_init_copy TclBN_mp_init_copy
+#define mp_init_multi TclBN_mp_init_multi
+#define mp_init_set TclBN_mp_init_set
+#define mp_init_set_int TclBN_mp_init_set_int
+#define mp_init_size TclBN_mp_init_size
+#define mp_karatsuba_mul TclBN_mp_karatsuba_mul
+#define mp_karatsuba_sqr TclBN_mp_karatsuba_sqr
+#define mp_lshd TclBN_mp_lshd
+#define mp_mod TclBN_mp_mod
+#define mp_mod_2d TclBN_mp_mod_2d
+#define mp_mul TclBN_mp_mul
+#define mp_mul_2 TclBN_mp_mul_2
+#define mp_mul_2d TclBN_mp_mul_2d
+#define mp_mul_d TclBN_mp_mul_d
+#define mp_neg TclBN_mp_neg
+#define mp_or TclBN_mp_or
+#define mp_radix_size TclBN_mp_radix_size
+#define mp_read_radix TclBN_mp_read_radix
+#define mp_rshd TclBN_mp_rshd
+#define mp_s_rmap TclBNMpSRmap
+#define mp_set TclBN_mp_set
+#define mp_set_int TclBN_mp_set_int
+#define mp_shrink TclBN_mp_shrink
+#define mp_sqr TclBN_mp_sqr
+#define mp_sqrt TclBN_mp_sqrt
+#define mp_sub TclBN_mp_sub
+#define mp_sub_d TclBN_mp_sub_d
+#define mp_to_unsigned_bin TclBN_mp_to_unsigned_bin
+#define mp_to_unsigned_bin_n TclBN_mp_to_unsigned_bin_n
+#define mp_toom_mul TclBN_mp_toom_mul
+#define mp_toom_sqr TclBN_mp_toom_sqr
+#define mp_toradix_n TclBN_mp_toradix_n
+#define mp_unsigned_bin_size TclBN_mp_unsigned_bin_size
+#define mp_xor TclBN_mp_xor
+#define mp_zero TclBN_mp_zero
+#define s_mp_add TclBN_s_mp_add
+#define s_mp_mul_digs TclBN_s_mp_mul_digs
+#define s_mp_sqr TclBN_s_mp_sqr
+#define s_mp_sub TclBN_s_mp_sub
+
+#undef TCL_STORAGE_CLASS
+#ifdef BUILD_tcl
+# define TCL_STORAGE_CLASS DLLEXPORT
+#else
+# ifdef USE_TCL_STUBS
+# define TCL_STORAGE_CLASS
+# else
+# define TCL_STORAGE_CLASS DLLIMPORT
+# endif
+#endif
+
+/*
+ * WARNING: This file is automatically generated by the tools/genStubs.tcl
+ * script. Any modifications to the function declarations below should be made
+ * in the generic/tclInt.decls script.
+ */
+
+/* !BEGIN!: Do not edit below this line. */
+
+/*
+ * Exported function declarations:
+ */
+
+#ifndef TclBN_epoch_TCL_DECLARED
+#define TclBN_epoch_TCL_DECLARED
+/* 0 */
+EXTERN int TclBN_epoch(void);
+#endif
+#ifndef TclBN_revision_TCL_DECLARED
+#define TclBN_revision_TCL_DECLARED
+/* 1 */
+EXTERN int TclBN_revision(void);
+#endif
+#ifndef TclBN_mp_add_TCL_DECLARED
+#define TclBN_mp_add_TCL_DECLARED
+/* 2 */
+EXTERN int TclBN_mp_add(mp_int *a, mp_int *b, mp_int *c);
+#endif
+#ifndef TclBN_mp_add_d_TCL_DECLARED
+#define TclBN_mp_add_d_TCL_DECLARED
+/* 3 */
+EXTERN int TclBN_mp_add_d(mp_int *a, mp_digit b, mp_int *c);
+#endif
+#ifndef TclBN_mp_and_TCL_DECLARED
+#define TclBN_mp_and_TCL_DECLARED
+/* 4 */
+EXTERN int TclBN_mp_and(mp_int *a, mp_int *b, mp_int *c);
+#endif
+#ifndef TclBN_mp_clamp_TCL_DECLARED
+#define TclBN_mp_clamp_TCL_DECLARED
+/* 5 */
+EXTERN void TclBN_mp_clamp(mp_int *a);
+#endif
+#ifndef TclBN_mp_clear_TCL_DECLARED
+#define TclBN_mp_clear_TCL_DECLARED
+/* 6 */
+EXTERN void TclBN_mp_clear(mp_int *a);
+#endif
+#ifndef TclBN_mp_clear_multi_TCL_DECLARED
+#define TclBN_mp_clear_multi_TCL_DECLARED
+/* 7 */
+EXTERN void TclBN_mp_clear_multi(mp_int *a, ...);
+#endif
+#ifndef TclBN_mp_cmp_TCL_DECLARED
+#define TclBN_mp_cmp_TCL_DECLARED
+/* 8 */
+EXTERN int TclBN_mp_cmp(mp_int *a, mp_int *b);
+#endif
+#ifndef TclBN_mp_cmp_d_TCL_DECLARED
+#define TclBN_mp_cmp_d_TCL_DECLARED
+/* 9 */
+EXTERN int TclBN_mp_cmp_d(mp_int *a, mp_digit b);
+#endif
+#ifndef TclBN_mp_cmp_mag_TCL_DECLARED
+#define TclBN_mp_cmp_mag_TCL_DECLARED
+/* 10 */
+EXTERN int TclBN_mp_cmp_mag(mp_int *a, mp_int *b);
+#endif
+#ifndef TclBN_mp_copy_TCL_DECLARED
+#define TclBN_mp_copy_TCL_DECLARED
+/* 11 */
+EXTERN int TclBN_mp_copy(mp_int *a, mp_int *b);
+#endif
+#ifndef TclBN_mp_count_bits_TCL_DECLARED
+#define TclBN_mp_count_bits_TCL_DECLARED
+/* 12 */
+EXTERN int TclBN_mp_count_bits(mp_int *a);
+#endif
+#ifndef TclBN_mp_div_TCL_DECLARED
+#define TclBN_mp_div_TCL_DECLARED
+/* 13 */
+EXTERN int TclBN_mp_div(mp_int *a, mp_int *b, mp_int *q,
+ mp_int *r);
+#endif
+#ifndef TclBN_mp_div_d_TCL_DECLARED
+#define TclBN_mp_div_d_TCL_DECLARED
+/* 14 */
+EXTERN int TclBN_mp_div_d(mp_int *a, mp_digit b, mp_int *q,
+ mp_digit *r);
+#endif
+#ifndef TclBN_mp_div_2_TCL_DECLARED
+#define TclBN_mp_div_2_TCL_DECLARED
+/* 15 */
+EXTERN int TclBN_mp_div_2(mp_int *a, mp_int *q);
+#endif
+#ifndef TclBN_mp_div_2d_TCL_DECLARED
+#define TclBN_mp_div_2d_TCL_DECLARED
+/* 16 */
+EXTERN int TclBN_mp_div_2d(mp_int *a, int b, mp_int *q,
+ mp_int *r);
+#endif
+#ifndef TclBN_mp_div_3_TCL_DECLARED
+#define TclBN_mp_div_3_TCL_DECLARED
+/* 17 */
+EXTERN int TclBN_mp_div_3(mp_int *a, mp_int *q, mp_digit *r);
+#endif
+#ifndef TclBN_mp_exch_TCL_DECLARED
+#define TclBN_mp_exch_TCL_DECLARED
+/* 18 */
+EXTERN void TclBN_mp_exch(mp_int *a, mp_int *b);
+#endif
+#ifndef TclBN_mp_expt_d_TCL_DECLARED
+#define TclBN_mp_expt_d_TCL_DECLARED
+/* 19 */
+EXTERN int TclBN_mp_expt_d(mp_int *a, mp_digit b, mp_int *c);
+#endif
+#ifndef TclBN_mp_grow_TCL_DECLARED
+#define TclBN_mp_grow_TCL_DECLARED
+/* 20 */
+EXTERN int TclBN_mp_grow(mp_int *a, int size);
+#endif
+#ifndef TclBN_mp_init_TCL_DECLARED
+#define TclBN_mp_init_TCL_DECLARED
+/* 21 */
+EXTERN int TclBN_mp_init(mp_int *a);
+#endif
+#ifndef TclBN_mp_init_copy_TCL_DECLARED
+#define TclBN_mp_init_copy_TCL_DECLARED
+/* 22 */
+EXTERN int TclBN_mp_init_copy(mp_int *a, mp_int *b);
+#endif
+#ifndef TclBN_mp_init_multi_TCL_DECLARED
+#define TclBN_mp_init_multi_TCL_DECLARED
+/* 23 */
+EXTERN int TclBN_mp_init_multi(mp_int *a, ...);
+#endif
+#ifndef TclBN_mp_init_set_TCL_DECLARED
+#define TclBN_mp_init_set_TCL_DECLARED
+/* 24 */
+EXTERN int TclBN_mp_init_set(mp_int *a, mp_digit b);
+#endif
+#ifndef TclBN_mp_init_size_TCL_DECLARED
+#define TclBN_mp_init_size_TCL_DECLARED
+/* 25 */
+EXTERN int TclBN_mp_init_size(mp_int *a, int size);
+#endif
+#ifndef TclBN_mp_lshd_TCL_DECLARED
+#define TclBN_mp_lshd_TCL_DECLARED
+/* 26 */
+EXTERN int TclBN_mp_lshd(mp_int *a, int shift);
+#endif
+#ifndef TclBN_mp_mod_TCL_DECLARED
+#define TclBN_mp_mod_TCL_DECLARED
+/* 27 */
+EXTERN int TclBN_mp_mod(mp_int *a, mp_int *b, mp_int *r);
+#endif
+#ifndef TclBN_mp_mod_2d_TCL_DECLARED
+#define TclBN_mp_mod_2d_TCL_DECLARED
+/* 28 */
+EXTERN int TclBN_mp_mod_2d(mp_int *a, int b, mp_int *r);
+#endif
+#ifndef TclBN_mp_mul_TCL_DECLARED
+#define TclBN_mp_mul_TCL_DECLARED
+/* 29 */
+EXTERN int TclBN_mp_mul(mp_int *a, mp_int *b, mp_int *p);
+#endif
+#ifndef TclBN_mp_mul_d_TCL_DECLARED
+#define TclBN_mp_mul_d_TCL_DECLARED
+/* 30 */
+EXTERN int TclBN_mp_mul_d(mp_int *a, mp_digit b, mp_int *p);
+#endif
+#ifndef TclBN_mp_mul_2_TCL_DECLARED
+#define TclBN_mp_mul_2_TCL_DECLARED
+/* 31 */
+EXTERN int TclBN_mp_mul_2(mp_int *a, mp_int *p);
+#endif
+#ifndef TclBN_mp_mul_2d_TCL_DECLARED
+#define TclBN_mp_mul_2d_TCL_DECLARED
+/* 32 */
+EXTERN int TclBN_mp_mul_2d(mp_int *a, int d, mp_int *p);
+#endif
+#ifndef TclBN_mp_neg_TCL_DECLARED
+#define TclBN_mp_neg_TCL_DECLARED
+/* 33 */
+EXTERN int TclBN_mp_neg(mp_int *a, mp_int *b);
+#endif
+#ifndef TclBN_mp_or_TCL_DECLARED
+#define TclBN_mp_or_TCL_DECLARED
+/* 34 */
+EXTERN int TclBN_mp_or(mp_int *a, mp_int *b, mp_int *c);
+#endif
+#ifndef TclBN_mp_radix_size_TCL_DECLARED
+#define TclBN_mp_radix_size_TCL_DECLARED
+/* 35 */
+EXTERN int TclBN_mp_radix_size(mp_int *a, int radix, int *size);
+#endif
+#ifndef TclBN_mp_read_radix_TCL_DECLARED
+#define TclBN_mp_read_radix_TCL_DECLARED
+/* 36 */
+EXTERN int TclBN_mp_read_radix(mp_int *a, CONST char *str,
+ int radix);
+#endif
+#ifndef TclBN_mp_rshd_TCL_DECLARED
+#define TclBN_mp_rshd_TCL_DECLARED
+/* 37 */
+EXTERN void TclBN_mp_rshd(mp_int *a, int shift);
+#endif
+#ifndef TclBN_mp_shrink_TCL_DECLARED
+#define TclBN_mp_shrink_TCL_DECLARED
+/* 38 */
+EXTERN int TclBN_mp_shrink(mp_int *a);
+#endif
+#ifndef TclBN_mp_set_TCL_DECLARED
+#define TclBN_mp_set_TCL_DECLARED
+/* 39 */
+EXTERN void TclBN_mp_set(mp_int *a, mp_digit b);
+#endif
+#ifndef TclBN_mp_sqr_TCL_DECLARED
+#define TclBN_mp_sqr_TCL_DECLARED
+/* 40 */
+EXTERN int TclBN_mp_sqr(mp_int *a, mp_int *b);
+#endif
+#ifndef TclBN_mp_sqrt_TCL_DECLARED
+#define TclBN_mp_sqrt_TCL_DECLARED
+/* 41 */
+EXTERN int TclBN_mp_sqrt(mp_int *a, mp_int *b);
+#endif
+#ifndef TclBN_mp_sub_TCL_DECLARED
+#define TclBN_mp_sub_TCL_DECLARED
+/* 42 */
+EXTERN int TclBN_mp_sub(mp_int *a, mp_int *b, mp_int *c);
+#endif
+#ifndef TclBN_mp_sub_d_TCL_DECLARED
+#define TclBN_mp_sub_d_TCL_DECLARED
+/* 43 */
+EXTERN int TclBN_mp_sub_d(mp_int *a, mp_digit b, mp_int *c);
+#endif
+#ifndef TclBN_mp_to_unsigned_bin_TCL_DECLARED
+#define TclBN_mp_to_unsigned_bin_TCL_DECLARED
+/* 44 */
+EXTERN int TclBN_mp_to_unsigned_bin(mp_int *a, unsigned char *b);
+#endif
+#ifndef TclBN_mp_to_unsigned_bin_n_TCL_DECLARED
+#define TclBN_mp_to_unsigned_bin_n_TCL_DECLARED
+/* 45 */
+EXTERN int TclBN_mp_to_unsigned_bin_n(mp_int *a,
+ unsigned char *b, unsigned long *outlen);
+#endif
+#ifndef TclBN_mp_toradix_n_TCL_DECLARED
+#define TclBN_mp_toradix_n_TCL_DECLARED
+/* 46 */
+EXTERN int TclBN_mp_toradix_n(mp_int *a, char *str, int radix,
+ int maxlen);
+#endif
+#ifndef TclBN_mp_unsigned_bin_size_TCL_DECLARED
+#define TclBN_mp_unsigned_bin_size_TCL_DECLARED
+/* 47 */
+EXTERN int TclBN_mp_unsigned_bin_size(mp_int *a);
+#endif
+#ifndef TclBN_mp_xor_TCL_DECLARED
+#define TclBN_mp_xor_TCL_DECLARED
+/* 48 */
+EXTERN int TclBN_mp_xor(mp_int *a, mp_int *b, mp_int *c);
+#endif
+#ifndef TclBN_mp_zero_TCL_DECLARED
+#define TclBN_mp_zero_TCL_DECLARED
+/* 49 */
+EXTERN void TclBN_mp_zero(mp_int *a);
+#endif
+#ifndef TclBN_reverse_TCL_DECLARED
+#define TclBN_reverse_TCL_DECLARED
+/* 50 */
+EXTERN void TclBN_reverse(unsigned char *s, int len);
+#endif
+#ifndef TclBN_fast_s_mp_mul_digs_TCL_DECLARED
+#define TclBN_fast_s_mp_mul_digs_TCL_DECLARED
+/* 51 */
+EXTERN int TclBN_fast_s_mp_mul_digs(mp_int *a, mp_int *b,
+ mp_int *c, int digs);
+#endif
+#ifndef TclBN_fast_s_mp_sqr_TCL_DECLARED
+#define TclBN_fast_s_mp_sqr_TCL_DECLARED
+/* 52 */
+EXTERN int TclBN_fast_s_mp_sqr(mp_int *a, mp_int *b);
+#endif
+#ifndef TclBN_mp_karatsuba_mul_TCL_DECLARED
+#define TclBN_mp_karatsuba_mul_TCL_DECLARED
+/* 53 */
+EXTERN int TclBN_mp_karatsuba_mul(mp_int *a, mp_int *b,
+ mp_int *c);
+#endif
+#ifndef TclBN_mp_karatsuba_sqr_TCL_DECLARED
+#define TclBN_mp_karatsuba_sqr_TCL_DECLARED
+/* 54 */
+EXTERN int TclBN_mp_karatsuba_sqr(mp_int *a, mp_int *b);
+#endif
+#ifndef TclBN_mp_toom_mul_TCL_DECLARED
+#define TclBN_mp_toom_mul_TCL_DECLARED
+/* 55 */
+EXTERN int TclBN_mp_toom_mul(mp_int *a, mp_int *b, mp_int *c);
+#endif
+#ifndef TclBN_mp_toom_sqr_TCL_DECLARED
+#define TclBN_mp_toom_sqr_TCL_DECLARED
+/* 56 */
+EXTERN int TclBN_mp_toom_sqr(mp_int *a, mp_int *b);
+#endif
+#ifndef TclBN_s_mp_add_TCL_DECLARED
+#define TclBN_s_mp_add_TCL_DECLARED
+/* 57 */
+EXTERN int TclBN_s_mp_add(mp_int *a, mp_int *b, mp_int *c);
+#endif
+#ifndef TclBN_s_mp_mul_digs_TCL_DECLARED
+#define TclBN_s_mp_mul_digs_TCL_DECLARED
+/* 58 */
+EXTERN int TclBN_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c,
+ int digs);
+#endif
+#ifndef TclBN_s_mp_sqr_TCL_DECLARED
+#define TclBN_s_mp_sqr_TCL_DECLARED
+/* 59 */
+EXTERN int TclBN_s_mp_sqr(mp_int *a, mp_int *b);
+#endif
+#ifndef TclBN_s_mp_sub_TCL_DECLARED
+#define TclBN_s_mp_sub_TCL_DECLARED
+/* 60 */
+EXTERN int TclBN_s_mp_sub(mp_int *a, mp_int *b, mp_int *c);
+#endif
+#ifndef TclBN_mp_init_set_int_TCL_DECLARED
+#define TclBN_mp_init_set_int_TCL_DECLARED
+/* 61 */
+EXTERN int TclBN_mp_init_set_int(mp_int*a, unsigned long i);
+#endif
+#ifndef TclBN_mp_set_int_TCL_DECLARED
+#define TclBN_mp_set_int_TCL_DECLARED
+/* 62 */
+EXTERN int TclBN_mp_set_int(mp_int*a, unsigned long i);
+#endif
+#ifndef TclBN_mp_cnt_lsb_TCL_DECLARED
+#define TclBN_mp_cnt_lsb_TCL_DECLARED
+/* 63 */
+EXTERN int TclBN_mp_cnt_lsb(mp_int*a);
+#endif
+
+typedef struct TclTomMathStubs {
+ int magic;
+ struct TclTomMathStubHooks *hooks;
+
+ int (*tclBN_epoch) (void); /* 0 */
+ int (*tclBN_revision) (void); /* 1 */
+ int (*tclBN_mp_add) (mp_int *a, mp_int *b, mp_int *c); /* 2 */
+ int (*tclBN_mp_add_d) (mp_int *a, mp_digit b, mp_int *c); /* 3 */
+ int (*tclBN_mp_and) (mp_int *a, mp_int *b, mp_int *c); /* 4 */
+ void (*tclBN_mp_clamp) (mp_int *a); /* 5 */
+ void (*tclBN_mp_clear) (mp_int *a); /* 6 */
+ void (*tclBN_mp_clear_multi) (mp_int *a, ...); /* 7 */
+ int (*tclBN_mp_cmp) (mp_int *a, mp_int *b); /* 8 */
+ int (*tclBN_mp_cmp_d) (mp_int *a, mp_digit b); /* 9 */
+ int (*tclBN_mp_cmp_mag) (mp_int *a, mp_int *b); /* 10 */
+ int (*tclBN_mp_copy) (mp_int *a, mp_int *b); /* 11 */
+ int (*tclBN_mp_count_bits) (mp_int *a); /* 12 */
+ int (*tclBN_mp_div) (mp_int *a, mp_int *b, mp_int *q, mp_int *r); /* 13 */
+ int (*tclBN_mp_div_d) (mp_int *a, mp_digit b, mp_int *q, mp_digit *r); /* 14 */
+ int (*tclBN_mp_div_2) (mp_int *a, mp_int *q); /* 15 */
+ int (*tclBN_mp_div_2d) (mp_int *a, int b, mp_int *q, mp_int *r); /* 16 */
+ int (*tclBN_mp_div_3) (mp_int *a, mp_int *q, mp_digit *r); /* 17 */
+ void (*tclBN_mp_exch) (mp_int *a, mp_int *b); /* 18 */
+ int (*tclBN_mp_expt_d) (mp_int *a, mp_digit b, mp_int *c); /* 19 */
+ int (*tclBN_mp_grow) (mp_int *a, int size); /* 20 */
+ int (*tclBN_mp_init) (mp_int *a); /* 21 */
+ int (*tclBN_mp_init_copy) (mp_int *a, mp_int *b); /* 22 */
+ int (*tclBN_mp_init_multi) (mp_int *a, ...); /* 23 */
+ int (*tclBN_mp_init_set) (mp_int *a, mp_digit b); /* 24 */
+ int (*tclBN_mp_init_size) (mp_int *a, int size); /* 25 */
+ int (*tclBN_mp_lshd) (mp_int *a, int shift); /* 26 */
+ int (*tclBN_mp_mod) (mp_int *a, mp_int *b, mp_int *r); /* 27 */
+ int (*tclBN_mp_mod_2d) (mp_int *a, int b, mp_int *r); /* 28 */
+ int (*tclBN_mp_mul) (mp_int *a, mp_int *b, mp_int *p); /* 29 */
+ int (*tclBN_mp_mul_d) (mp_int *a, mp_digit b, mp_int *p); /* 30 */
+ int (*tclBN_mp_mul_2) (mp_int *a, mp_int *p); /* 31 */
+ int (*tclBN_mp_mul_2d) (mp_int *a, int d, mp_int *p); /* 32 */
+ int (*tclBN_mp_neg) (mp_int *a, mp_int *b); /* 33 */
+ int (*tclBN_mp_or) (mp_int *a, mp_int *b, mp_int *c); /* 34 */
+ int (*tclBN_mp_radix_size) (mp_int *a, int radix, int *size); /* 35 */
+ int (*tclBN_mp_read_radix) (mp_int *a, CONST char *str, int radix); /* 36 */
+ void (*tclBN_mp_rshd) (mp_int *a, int shift); /* 37 */
+ int (*tclBN_mp_shrink) (mp_int *a); /* 38 */
+ void (*tclBN_mp_set) (mp_int *a, mp_digit b); /* 39 */
+ int (*tclBN_mp_sqr) (mp_int *a, mp_int *b); /* 40 */
+ int (*tclBN_mp_sqrt) (mp_int *a, mp_int *b); /* 41 */
+ int (*tclBN_mp_sub) (mp_int *a, mp_int *b, mp_int *c); /* 42 */
+ int (*tclBN_mp_sub_d) (mp_int *a, mp_digit b, mp_int *c); /* 43 */
+ int (*tclBN_mp_to_unsigned_bin) (mp_int *a, unsigned char *b); /* 44 */
+ int (*tclBN_mp_to_unsigned_bin_n) (mp_int *a, unsigned char *b, unsigned long *outlen); /* 45 */
+ int (*tclBN_mp_toradix_n) (mp_int *a, char *str, int radix, int maxlen); /* 46 */
+ int (*tclBN_mp_unsigned_bin_size) (mp_int *a); /* 47 */
+ int (*tclBN_mp_xor) (mp_int *a, mp_int *b, mp_int *c); /* 48 */
+ void (*tclBN_mp_zero) (mp_int *a); /* 49 */
+ void (*tclBN_reverse) (unsigned char *s, int len); /* 50 */
+ int (*tclBN_fast_s_mp_mul_digs) (mp_int *a, mp_int *b, mp_int *c, int digs); /* 51 */
+ int (*tclBN_fast_s_mp_sqr) (mp_int *a, mp_int *b); /* 52 */
+ int (*tclBN_mp_karatsuba_mul) (mp_int *a, mp_int *b, mp_int *c); /* 53 */
+ int (*tclBN_mp_karatsuba_sqr) (mp_int *a, mp_int *b); /* 54 */
+ int (*tclBN_mp_toom_mul) (mp_int *a, mp_int *b, mp_int *c); /* 55 */
+ int (*tclBN_mp_toom_sqr) (mp_int *a, mp_int *b); /* 56 */
+ int (*tclBN_s_mp_add) (mp_int *a, mp_int *b, mp_int *c); /* 57 */
+ int (*tclBN_s_mp_mul_digs) (mp_int *a, mp_int *b, mp_int *c, int digs); /* 58 */
+ int (*tclBN_s_mp_sqr) (mp_int *a, mp_int *b); /* 59 */
+ int (*tclBN_s_mp_sub) (mp_int *a, mp_int *b, mp_int *c); /* 60 */
+ int (*tclBN_mp_init_set_int) (mp_int*a, unsigned long i); /* 61 */
+ int (*tclBN_mp_set_int) (mp_int*a, unsigned long i); /* 62 */
+ int (*tclBN_mp_cnt_lsb) (mp_int*a); /* 63 */
+} TclTomMathStubs;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern TclTomMathStubs *tclTomMathStubsPtr;
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS)
+
+/*
+ * Inline function declarations:
+ */
+
+#ifndef TclBN_epoch
+#define TclBN_epoch \
+ (tclTomMathStubsPtr->tclBN_epoch) /* 0 */
+#endif
+#ifndef TclBN_revision
+#define TclBN_revision \
+ (tclTomMathStubsPtr->tclBN_revision) /* 1 */
+#endif
+#ifndef TclBN_mp_add
+#define TclBN_mp_add \
+ (tclTomMathStubsPtr->tclBN_mp_add) /* 2 */
+#endif
+#ifndef TclBN_mp_add_d
+#define TclBN_mp_add_d \
+ (tclTomMathStubsPtr->tclBN_mp_add_d) /* 3 */
+#endif
+#ifndef TclBN_mp_and
+#define TclBN_mp_and \
+ (tclTomMathStubsPtr->tclBN_mp_and) /* 4 */
+#endif
+#ifndef TclBN_mp_clamp
+#define TclBN_mp_clamp \
+ (tclTomMathStubsPtr->tclBN_mp_clamp) /* 5 */
+#endif
+#ifndef TclBN_mp_clear
+#define TclBN_mp_clear \
+ (tclTomMathStubsPtr->tclBN_mp_clear) /* 6 */
+#endif
+#ifndef TclBN_mp_clear_multi
+#define TclBN_mp_clear_multi \
+ (tclTomMathStubsPtr->tclBN_mp_clear_multi) /* 7 */
+#endif
+#ifndef TclBN_mp_cmp
+#define TclBN_mp_cmp \
+ (tclTomMathStubsPtr->tclBN_mp_cmp) /* 8 */
+#endif
+#ifndef TclBN_mp_cmp_d
+#define TclBN_mp_cmp_d \
+ (tclTomMathStubsPtr->tclBN_mp_cmp_d) /* 9 */
+#endif
+#ifndef TclBN_mp_cmp_mag
+#define TclBN_mp_cmp_mag \
+ (tclTomMathStubsPtr->tclBN_mp_cmp_mag) /* 10 */
+#endif
+#ifndef TclBN_mp_copy
+#define TclBN_mp_copy \
+ (tclTomMathStubsPtr->tclBN_mp_copy) /* 11 */
+#endif
+#ifndef TclBN_mp_count_bits
+#define TclBN_mp_count_bits \
+ (tclTomMathStubsPtr->tclBN_mp_count_bits) /* 12 */
+#endif
+#ifndef TclBN_mp_div
+#define TclBN_mp_div \
+ (tclTomMathStubsPtr->tclBN_mp_div) /* 13 */
+#endif
+#ifndef TclBN_mp_div_d
+#define TclBN_mp_div_d \
+ (tclTomMathStubsPtr->tclBN_mp_div_d) /* 14 */
+#endif
+#ifndef TclBN_mp_div_2
+#define TclBN_mp_div_2 \
+ (tclTomMathStubsPtr->tclBN_mp_div_2) /* 15 */
+#endif
+#ifndef TclBN_mp_div_2d
+#define TclBN_mp_div_2d \
+ (tclTomMathStubsPtr->tclBN_mp_div_2d) /* 16 */
+#endif
+#ifndef TclBN_mp_div_3
+#define TclBN_mp_div_3 \
+ (tclTomMathStubsPtr->tclBN_mp_div_3) /* 17 */
+#endif
+#ifndef TclBN_mp_exch
+#define TclBN_mp_exch \
+ (tclTomMathStubsPtr->tclBN_mp_exch) /* 18 */
+#endif
+#ifndef TclBN_mp_expt_d
+#define TclBN_mp_expt_d \
+ (tclTomMathStubsPtr->tclBN_mp_expt_d) /* 19 */
+#endif
+#ifndef TclBN_mp_grow
+#define TclBN_mp_grow \
+ (tclTomMathStubsPtr->tclBN_mp_grow) /* 20 */
+#endif
+#ifndef TclBN_mp_init
+#define TclBN_mp_init \
+ (tclTomMathStubsPtr->tclBN_mp_init) /* 21 */
+#endif
+#ifndef TclBN_mp_init_copy
+#define TclBN_mp_init_copy \
+ (tclTomMathStubsPtr->tclBN_mp_init_copy) /* 22 */
+#endif
+#ifndef TclBN_mp_init_multi
+#define TclBN_mp_init_multi \
+ (tclTomMathStubsPtr->tclBN_mp_init_multi) /* 23 */
+#endif
+#ifndef TclBN_mp_init_set
+#define TclBN_mp_init_set \
+ (tclTomMathStubsPtr->tclBN_mp_init_set) /* 24 */
+#endif
+#ifndef TclBN_mp_init_size
+#define TclBN_mp_init_size \
+ (tclTomMathStubsPtr->tclBN_mp_init_size) /* 25 */
+#endif
+#ifndef TclBN_mp_lshd
+#define TclBN_mp_lshd \
+ (tclTomMathStubsPtr->tclBN_mp_lshd) /* 26 */
+#endif
+#ifndef TclBN_mp_mod
+#define TclBN_mp_mod \
+ (tclTomMathStubsPtr->tclBN_mp_mod) /* 27 */
+#endif
+#ifndef TclBN_mp_mod_2d
+#define TclBN_mp_mod_2d \
+ (tclTomMathStubsPtr->tclBN_mp_mod_2d) /* 28 */
+#endif
+#ifndef TclBN_mp_mul
+#define TclBN_mp_mul \
+ (tclTomMathStubsPtr->tclBN_mp_mul) /* 29 */
+#endif
+#ifndef TclBN_mp_mul_d
+#define TclBN_mp_mul_d \
+ (tclTomMathStubsPtr->tclBN_mp_mul_d) /* 30 */
+#endif
+#ifndef TclBN_mp_mul_2
+#define TclBN_mp_mul_2 \
+ (tclTomMathStubsPtr->tclBN_mp_mul_2) /* 31 */
+#endif
+#ifndef TclBN_mp_mul_2d
+#define TclBN_mp_mul_2d \
+ (tclTomMathStubsPtr->tclBN_mp_mul_2d) /* 32 */
+#endif
+#ifndef TclBN_mp_neg
+#define TclBN_mp_neg \
+ (tclTomMathStubsPtr->tclBN_mp_neg) /* 33 */
+#endif
+#ifndef TclBN_mp_or
+#define TclBN_mp_or \
+ (tclTomMathStubsPtr->tclBN_mp_or) /* 34 */
+#endif
+#ifndef TclBN_mp_radix_size
+#define TclBN_mp_radix_size \
+ (tclTomMathStubsPtr->tclBN_mp_radix_size) /* 35 */
+#endif
+#ifndef TclBN_mp_read_radix
+#define TclBN_mp_read_radix \
+ (tclTomMathStubsPtr->tclBN_mp_read_radix) /* 36 */
+#endif
+#ifndef TclBN_mp_rshd
+#define TclBN_mp_rshd \
+ (tclTomMathStubsPtr->tclBN_mp_rshd) /* 37 */
+#endif
+#ifndef TclBN_mp_shrink
+#define TclBN_mp_shrink \
+ (tclTomMathStubsPtr->tclBN_mp_shrink) /* 38 */
+#endif
+#ifndef TclBN_mp_set
+#define TclBN_mp_set \
+ (tclTomMathStubsPtr->tclBN_mp_set) /* 39 */
+#endif
+#ifndef TclBN_mp_sqr
+#define TclBN_mp_sqr \
+ (tclTomMathStubsPtr->tclBN_mp_sqr) /* 40 */
+#endif
+#ifndef TclBN_mp_sqrt
+#define TclBN_mp_sqrt \
+ (tclTomMathStubsPtr->tclBN_mp_sqrt) /* 41 */
+#endif
+#ifndef TclBN_mp_sub
+#define TclBN_mp_sub \
+ (tclTomMathStubsPtr->tclBN_mp_sub) /* 42 */
+#endif
+#ifndef TclBN_mp_sub_d
+#define TclBN_mp_sub_d \
+ (tclTomMathStubsPtr->tclBN_mp_sub_d) /* 43 */
+#endif
+#ifndef TclBN_mp_to_unsigned_bin
+#define TclBN_mp_to_unsigned_bin \
+ (tclTomMathStubsPtr->tclBN_mp_to_unsigned_bin) /* 44 */
+#endif
+#ifndef TclBN_mp_to_unsigned_bin_n
+#define TclBN_mp_to_unsigned_bin_n \
+ (tclTomMathStubsPtr->tclBN_mp_to_unsigned_bin_n) /* 45 */
+#endif
+#ifndef TclBN_mp_toradix_n
+#define TclBN_mp_toradix_n \
+ (tclTomMathStubsPtr->tclBN_mp_toradix_n) /* 46 */
+#endif
+#ifndef TclBN_mp_unsigned_bin_size
+#define TclBN_mp_unsigned_bin_size \
+ (tclTomMathStubsPtr->tclBN_mp_unsigned_bin_size) /* 47 */
+#endif
+#ifndef TclBN_mp_xor
+#define TclBN_mp_xor \
+ (tclTomMathStubsPtr->tclBN_mp_xor) /* 48 */
+#endif
+#ifndef TclBN_mp_zero
+#define TclBN_mp_zero \
+ (tclTomMathStubsPtr->tclBN_mp_zero) /* 49 */
+#endif
+#ifndef TclBN_reverse
+#define TclBN_reverse \
+ (tclTomMathStubsPtr->tclBN_reverse) /* 50 */
+#endif
+#ifndef TclBN_fast_s_mp_mul_digs
+#define TclBN_fast_s_mp_mul_digs \
+ (tclTomMathStubsPtr->tclBN_fast_s_mp_mul_digs) /* 51 */
+#endif
+#ifndef TclBN_fast_s_mp_sqr
+#define TclBN_fast_s_mp_sqr \
+ (tclTomMathStubsPtr->tclBN_fast_s_mp_sqr) /* 52 */
+#endif
+#ifndef TclBN_mp_karatsuba_mul
+#define TclBN_mp_karatsuba_mul \
+ (tclTomMathStubsPtr->tclBN_mp_karatsuba_mul) /* 53 */
+#endif
+#ifndef TclBN_mp_karatsuba_sqr
+#define TclBN_mp_karatsuba_sqr \
+ (tclTomMathStubsPtr->tclBN_mp_karatsuba_sqr) /* 54 */
+#endif
+#ifndef TclBN_mp_toom_mul
+#define TclBN_mp_toom_mul \
+ (tclTomMathStubsPtr->tclBN_mp_toom_mul) /* 55 */
+#endif
+#ifndef TclBN_mp_toom_sqr
+#define TclBN_mp_toom_sqr \
+ (tclTomMathStubsPtr->tclBN_mp_toom_sqr) /* 56 */
+#endif
+#ifndef TclBN_s_mp_add
+#define TclBN_s_mp_add \
+ (tclTomMathStubsPtr->tclBN_s_mp_add) /* 57 */
+#endif
+#ifndef TclBN_s_mp_mul_digs
+#define TclBN_s_mp_mul_digs \
+ (tclTomMathStubsPtr->tclBN_s_mp_mul_digs) /* 58 */
+#endif
+#ifndef TclBN_s_mp_sqr
+#define TclBN_s_mp_sqr \
+ (tclTomMathStubsPtr->tclBN_s_mp_sqr) /* 59 */
+#endif
+#ifndef TclBN_s_mp_sub
+#define TclBN_s_mp_sub \
+ (tclTomMathStubsPtr->tclBN_s_mp_sub) /* 60 */
+#endif
+#ifndef TclBN_mp_init_set_int
+#define TclBN_mp_init_set_int \
+ (tclTomMathStubsPtr->tclBN_mp_init_set_int) /* 61 */
+#endif
+#ifndef TclBN_mp_set_int
+#define TclBN_mp_set_int \
+ (tclTomMathStubsPtr->tclBN_mp_set_int) /* 62 */
+#endif
+#ifndef TclBN_mp_cnt_lsb
+#define TclBN_mp_cnt_lsb \
+ (tclTomMathStubsPtr->tclBN_mp_cnt_lsb) /* 63 */
+#endif
+
+#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */
+
+/* !END!: Do not edit above this line. */
+
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLIMPORT
+
+#endif /* _TCLINTDECLS */
diff --git a/generic/tclTomMathInt.h b/generic/tclTomMathInt.h
new file mode 100644
index 0000000..1b9eb64
--- /dev/null
+++ b/generic/tclTomMathInt.h
@@ -0,0 +1,2 @@
+#include "tclTomMath.h"
+#include "tommath_class.h"
diff --git a/generic/tclTomMathInterface.c b/generic/tclTomMathInterface.c
new file mode 100644
index 0000000..6e5dac3
--- /dev/null
+++ b/generic/tclTomMathInterface.c
@@ -0,0 +1,311 @@
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclTomMathInterface.c --
+ *
+ * This file contains procedures that are used as a 'glue' layer between
+ * Tcl and libtommath.
+ *
+ * Copyright (c) 2005 by Kevin B. Kenny. All rights reserved.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tclInt.h"
+#include "tommath.h"
+#include <limits.h>
+
+extern TclTomMathStubs tclTomMathStubs;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclTommath_Init --
+ *
+ * Initializes the TclTomMath 'package', which exists as a
+ * placeholder so that the package data can be used to hold
+ * a stub table pointer.
+ *
+ * Results:
+ * Returns a standard Tcl result.
+ *
+ * Side effects:
+ * Installs the stub table for tommath.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclTommath_Init(
+ Tcl_Interp* interp /* Tcl interpreter */
+) {
+ /* TIP #268: Full patchlevel instead of just major.minor */
+
+ if (Tcl_PkgProvideEx(interp, "tcl::tommath", TCL_PATCH_LEVEL,
+ (ClientData)&tclTomMathStubs) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclBN_epoch --
+ *
+ * Return the epoch number of the TclTomMath stubs table
+ *
+ * Results:
+ * Returns an arbitrary integer that does not decrease with
+ * release. Stubs tables with different epochs are incompatible.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclBN_epoch(void)
+{
+ return TCLTOMMATH_EPOCH;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclBN_revision --
+ *
+ * Returns the revision level of the TclTomMath stubs table
+ *
+ * Results:
+ * Returns an arbitrary integer that increases with revisions.
+ * If a client requires a given epoch and revision, any Stubs table
+ * with the same epoch and an equal or higher revision satisfies
+ * the request.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclBN_revision(void)
+{
+ return TCLTOMMATH_REVISION;
+}
+#if 0
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclBNAlloc --
+ *
+ * Allocate memory for libtommath.
+ *
+ * Results:
+ * Returns a pointer to the allocated block.
+ *
+ * This procedure is a wrapper around Tcl_Alloc, needed because of a
+ * mismatched type signature between Tcl_Alloc and malloc.
+ *
+ *----------------------------------------------------------------------
+ */
+
+extern void *
+TclBNAlloc(
+ size_t x)
+{
+ return (void *) Tcl_Alloc((unsigned int) x);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclBNRealloc --
+ *
+ * Change the size of an allocated block of memory in libtommath
+ *
+ * Results:
+ * Returns a pointer to the allocated block.
+ *
+ * This procedure is a wrapper around Tcl_Realloc, needed because of a
+ * mismatched type signature between Tcl_Realloc and realloc.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void *
+TclBNRealloc(
+ void *p,
+ size_t s)
+{
+ return (void *) Tcl_Realloc((char *) p, (unsigned int) s);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclBNFree --
+ *
+ * Free allocated memory in libtommath.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is freed.
+ *
+ * This function is simply a wrapper around Tcl_Free, needed in libtommath
+ * because of a type mismatch between free and Tcl_Free.
+ *
+ *----------------------------------------------------------------------
+ */
+
+extern void
+TclBNFree(
+ void *p)
+{
+ Tcl_Free((char *) p);
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclBNInitBignumFromLong --
+ *
+ * Allocate and initialize a 'bignum' from a native 'long'.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The 'bignum' is constructed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+extern void
+TclBNInitBignumFromLong(
+ mp_int *a,
+ long initVal)
+{
+ int status;
+ unsigned long v;
+ mp_digit* p;
+
+ /*
+ * Allocate enough memory to hold the largest possible long
+ */
+
+ status = mp_init_size(a,
+ (CHAR_BIT * sizeof(long) + DIGIT_BIT - 1) / DIGIT_BIT);
+ if (status != MP_OKAY) {
+ Tcl_Panic("initialization failure in TclBNInitBignumFromLong");
+ }
+
+ /*
+ * Convert arg to sign and magnitude.
+ */
+
+ if (initVal < 0) {
+ a->sign = MP_NEG;
+ v = -initVal;
+ } else {
+ a->sign = MP_ZPOS;
+ v = initVal;
+ }
+
+ /*
+ * Store the magnitude in the bignum.
+ */
+
+ p = a->dp;
+ while (v) {
+ *p++ = (mp_digit) (v & MP_MASK);
+ v >>= MP_DIGIT_BIT;
+ }
+ a->used = p - a->dp;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclBNInitBignumFromWideInt --
+ *
+ * Allocate and initialize a 'bignum' from a Tcl_WideInt
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The 'bignum' is constructed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+extern void
+TclBNInitBignumFromWideInt(
+ mp_int *a, /* Bignum to initialize */
+ Tcl_WideInt v) /* Initial value */
+{
+ if (v < (Tcl_WideInt)0) {
+ TclBNInitBignumFromWideUInt(a, (Tcl_WideUInt)(-v));
+ mp_neg(a, a);
+ } else {
+ TclBNInitBignumFromWideUInt(a, (Tcl_WideUInt)v);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclBNInitBignumFromWideUInt --
+ *
+ * Allocate and initialize a 'bignum' from a Tcl_WideUInt
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The 'bignum' is constructed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+extern void
+TclBNInitBignumFromWideUInt(
+ mp_int *a, /* Bignum to initialize */
+ Tcl_WideUInt v) /* Initial value */
+{
+ int status;
+ mp_digit *p;
+
+ /*
+ * Allocate enough memory to hold the largest possible Tcl_WideUInt.
+ */
+
+ status = mp_init_size(a,
+ (CHAR_BIT * sizeof(Tcl_WideUInt) + DIGIT_BIT - 1) / DIGIT_BIT);
+ if (status != MP_OKAY) {
+ Tcl_Panic("initialization failure in TclBNInitBignumFromWideUInt");
+ }
+
+ a->sign = MP_ZPOS;
+
+ /*
+ * Store the magnitude in the bignum.
+ */
+
+ p = a->dp;
+ while (v) {
+ *p++ = (mp_digit) (v & MP_MASK);
+ v >>= MP_DIGIT_BIT;
+ }
+ a->used = p - a->dp;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclTrace.c b/generic/tclTrace.c
new file mode 100644
index 0000000..28e6934
--- /dev/null
+++ b/generic/tclTrace.c
@@ -0,0 +1,3230 @@
+/*
+ * tclTrace.c --
+ *
+ * This file contains code to handle most trace management.
+ *
+ * Copyright (c) 1987-1993 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-2000 Scriptics Corporation.
+ * Copyright (c) 2002 ActiveState Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tclInt.h"
+
+/*
+ * Structures used to hold information about variable traces:
+ */
+
+typedef struct {
+ int flags; /* Operations for which Tcl command is to be
+ * invoked. */
+ size_t length; /* Number of non-NUL chars. in command. */
+ char command[4]; /* Space for Tcl command to invoke. Actual
+ * size will be as large as necessary to hold
+ * command. This field must be the last in the
+ * structure, so that it can be larger than 4
+ * bytes. */
+} TraceVarInfo;
+
+typedef struct {
+ VarTrace traceInfo;
+ TraceVarInfo traceCmdInfo;
+} CombinedTraceVarInfo;
+
+/*
+ * Structure used to hold information about command traces:
+ */
+
+typedef struct {
+ int flags; /* Operations for which Tcl command is to be
+ * invoked. */
+ size_t length; /* Number of non-NUL chars. in command. */
+ Tcl_Trace stepTrace; /* Used for execution traces, when tracing
+ * inside the given command */
+ int startLevel; /* Used for bookkeeping with step execution
+ * traces, store the level at which the step
+ * trace was invoked */
+ char *startCmd; /* Used for bookkeeping with step execution
+ * traces, store the command name which
+ * invoked step trace */
+ int curFlags; /* Trace flags for the current command */
+ int curCode; /* Return code for the current command */
+ int refCount; /* Used to ensure this structure is not
+ * deleted too early. Keeps track of how many
+ * pieces of code have a pointer to this
+ * structure. */
+ char command[4]; /* Space for Tcl command to invoke. Actual
+ * size will be as large as necessary to hold
+ * command. This field must be the last in the
+ * structure, so that it can be larger than 4
+ * bytes. */
+} TraceCommandInfo;
+
+/*
+ * Used by command execution traces. Note that we assume in the code that
+ * TCL_TRACE_ENTER_DURING_EXEC == 4 * TCL_TRACE_ENTER_EXEC and that
+ * TCL_TRACE_LEAVE_DURING_EXEC == 4 * TCL_TRACE_LEAVE_EXEC.
+ *
+ * TCL_TRACE_ENTER_DURING_EXEC - Trace each command inside the command
+ * currently being traced, before execution.
+ * TCL_TRACE_LEAVE_DURING_EXEC - Trace each command inside the command
+ * currently being traced, after execution.
+ * TCL_TRACE_ANY_EXEC - OR'd combination of all EXEC flags.
+ * TCL_TRACE_EXEC_IN_PROGRESS - The callback function on this trace is
+ * currently executing. Therefore we don't let
+ * further traces execute.
+ * TCL_TRACE_EXEC_DIRECT - This execution trace is triggered directly
+ * by the command being traced, not because of
+ * an internal trace.
+ * The flags 'TCL_TRACE_DESTROYED' and 'TCL_INTERP_DESTROYED' may also be used
+ * in command execution traces.
+ */
+
+#define TCL_TRACE_ENTER_DURING_EXEC 4
+#define TCL_TRACE_LEAVE_DURING_EXEC 8
+#define TCL_TRACE_ANY_EXEC 15
+#define TCL_TRACE_EXEC_IN_PROGRESS 0x10
+#define TCL_TRACE_EXEC_DIRECT 0x20
+
+/*
+ * Forward declarations for functions defined in this file:
+ */
+
+typedef int (Tcl_TraceTypeObjCmd)(Tcl_Interp *interp, int optionIndex,
+ int objc, Tcl_Obj *const objv[]);
+
+static Tcl_TraceTypeObjCmd TraceVariableObjCmd;
+static Tcl_TraceTypeObjCmd TraceCommandObjCmd;
+static Tcl_TraceTypeObjCmd TraceExecutionObjCmd;
+
+/*
+ * Each subcommand has a number of 'types' to which it can apply. Currently
+ * 'execution', 'command' and 'variable' are the only types supported. These
+ * three arrays MUST be kept in sync! In the future we may provide an API to
+ * add to the list of supported trace types.
+ */
+
+static const char *traceTypeOptions[] = {
+ "execution", "command", "variable", NULL
+};
+static Tcl_TraceTypeObjCmd *traceSubCmds[] = {
+ TraceExecutionObjCmd,
+ TraceCommandObjCmd,
+ TraceVariableObjCmd,
+};
+
+/*
+ * Declarations for local functions to this file:
+ */
+
+static int CallTraceFunction(Tcl_Interp *interp, Trace *tracePtr,
+ Command *cmdPtr, const char *command, int numChars,
+ int objc, Tcl_Obj *const objv[]);
+static char * TraceVarProc(ClientData clientData, Tcl_Interp *interp,
+ const char *name1, const char *name2, int flags);
+static void TraceCommandProc(ClientData clientData,
+ Tcl_Interp *interp, const char *oldName,
+ const char *newName, int flags);
+static Tcl_CmdObjTraceProc TraceExecutionProc;
+static int StringTraceProc(ClientData clientData,
+ Tcl_Interp *interp, int level,
+ const char *command, Tcl_Command commandInfo,
+ int objc, Tcl_Obj *const objv[]);
+static void StringTraceDeleteProc(ClientData clientData);
+static void DisposeTraceResult(int flags, char *result);
+static int TraceVarEx(Tcl_Interp *interp, const char *part1,
+ const char *part2, register VarTrace *tracePtr);
+
+/*
+ * The following structure holds the client data for string-based
+ * trace procs
+ */
+
+typedef struct StringTraceData {
+ ClientData clientData; /* Client data from Tcl_CreateTrace */
+ Tcl_CmdTraceProc *proc; /* Trace function from Tcl_CreateTrace */
+} StringTraceData;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_TraceObjCmd --
+ *
+ * This function is invoked to process the "trace" Tcl command. See the
+ * user documentation for details on what it does.
+ *
+ * Standard syntax as of Tcl 8.4 is:
+ * trace {add|info|remove} {command|variable} name ops cmd
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+int
+Tcl_TraceObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int optionIndex;
+ char *name, *flagOps, *p;
+ /* Main sub commands to 'trace' */
+ static const char *traceOptions[] = {
+ "add", "info", "remove",
+#ifndef TCL_REMOVE_OBSOLETE_TRACES
+ "variable", "vdelete", "vinfo",
+#endif
+ NULL
+ };
+ /* 'OLD' options are pre-Tcl-8.4 style */
+ enum traceOptions {
+ TRACE_ADD, TRACE_INFO, TRACE_REMOVE,
+#ifndef TCL_REMOVE_OBSOLETE_TRACES
+ TRACE_OLD_VARIABLE, TRACE_OLD_VDELETE, TRACE_OLD_VINFO
+#endif
+ };
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objv[1], traceOptions,
+ "option", 0, &optionIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum traceOptions) optionIndex) {
+ case TRACE_ADD:
+ case TRACE_REMOVE: {
+ /*
+ * All sub commands of trace add/remove must take at least one more
+ * argument. Beyond that we let the subcommand itself control the
+ * argument structure.
+ */
+
+ int typeIndex;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "type ?arg arg ...?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[2], traceTypeOptions, "option",
+ 0, &typeIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return (traceSubCmds[typeIndex])(interp, optionIndex, objc, objv);
+ }
+ case TRACE_INFO: {
+ /*
+ * All sub commands of trace info must take exactly two more arguments
+ * which name the type of thing being traced and the name of the thing
+ * being traced.
+ */
+
+ int typeIndex;
+ if (objc < 3) {
+ /*
+ * Delegate other complaints to the type-specific code which can
+ * give a better error message.
+ */
+
+ Tcl_WrongNumArgs(interp, 2, objv, "type name");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[2], traceTypeOptions, "option",
+ 0, &typeIndex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return (traceSubCmds[typeIndex])(interp, optionIndex, objc, objv);
+ break;
+ }
+
+#ifndef TCL_REMOVE_OBSOLETE_TRACES
+ case TRACE_OLD_VARIABLE:
+ case TRACE_OLD_VDELETE: {
+ Tcl_Obj *copyObjv[6];
+ Tcl_Obj *opsList;
+ int code, numFlags;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "name ops command");
+ return TCL_ERROR;
+ }
+
+ opsList = Tcl_NewObj();
+ Tcl_IncrRefCount(opsList);
+ flagOps = Tcl_GetStringFromObj(objv[3], &numFlags);
+ if (numFlags == 0) {
+ Tcl_DecrRefCount(opsList);
+ goto badVarOps;
+ }
+ for (p = flagOps; *p != 0; p++) {
+ Tcl_Obj *opObj;
+
+ if (*p == 'r') {
+ TclNewLiteralStringObj(opObj, "read");
+ } else if (*p == 'w') {
+ TclNewLiteralStringObj(opObj, "write");
+ } else if (*p == 'u') {
+ TclNewLiteralStringObj(opObj, "unset");
+ } else if (*p == 'a') {
+ TclNewLiteralStringObj(opObj, "array");
+ } else {
+ Tcl_DecrRefCount(opsList);
+ goto badVarOps;
+ }
+ Tcl_ListObjAppendElement(NULL, opsList, opObj);
+ }
+ copyObjv[0] = NULL;
+ memcpy(copyObjv+1, objv, objc*sizeof(Tcl_Obj *));
+ copyObjv[4] = opsList;
+ if (optionIndex == TRACE_OLD_VARIABLE) {
+ code = (traceSubCmds[2])(interp, TRACE_ADD, objc+1, copyObjv);
+ } else {
+ code = (traceSubCmds[2])(interp, TRACE_REMOVE, objc+1, copyObjv);
+ }
+ Tcl_DecrRefCount(opsList);
+ return code;
+ }
+ case TRACE_OLD_VINFO: {
+ ClientData clientData;
+ char ops[5];
+ Tcl_Obj *resultListPtr, *pairObjPtr, *elemObjPtr;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "name");
+ return TCL_ERROR;
+ }
+ resultListPtr = Tcl_NewObj();
+ clientData = 0;
+ name = Tcl_GetString(objv[2]);
+ while ((clientData = Tcl_VarTraceInfo(interp, name, 0,
+ TraceVarProc, clientData)) != 0) {
+
+ TraceVarInfo *tvarPtr = (TraceVarInfo *) clientData;
+
+ pairObjPtr = Tcl_NewListObj(0, NULL);
+ p = ops;
+ if (tvarPtr->flags & TCL_TRACE_READS) {
+ *p = 'r';
+ p++;
+ }
+ if (tvarPtr->flags & TCL_TRACE_WRITES) {
+ *p = 'w';
+ p++;
+ }
+ if (tvarPtr->flags & TCL_TRACE_UNSETS) {
+ *p = 'u';
+ p++;
+ }
+ if (tvarPtr->flags & TCL_TRACE_ARRAY) {
+ *p = 'a';
+ p++;
+ }
+ *p = '\0';
+
+ /*
+ * Build a pair (2-item list) with the ops string as the first obj
+ * element and the tvarPtr->command string as the second obj
+ * element. Append the pair (as an element) to the end of the
+ * result object list.
+ */
+
+ elemObjPtr = Tcl_NewStringObj(ops, -1);
+ Tcl_ListObjAppendElement(NULL, pairObjPtr, elemObjPtr);
+ elemObjPtr = Tcl_NewStringObj(tvarPtr->command, -1);
+ Tcl_ListObjAppendElement(NULL, pairObjPtr, elemObjPtr);
+ Tcl_ListObjAppendElement(interp, resultListPtr, pairObjPtr);
+ }
+ Tcl_SetObjResult(interp, resultListPtr);
+ break;
+ }
+#endif /* TCL_REMOVE_OBSOLETE_TRACES */
+ }
+ return TCL_OK;
+
+ badVarOps:
+ Tcl_AppendResult(interp, "bad operations \"", flagOps,
+ "\": should be one or more of rwua", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TraceExecutionObjCmd --
+ *
+ * Helper function for Tcl_TraceObjCmd; implements the [trace
+ * {add|remove|info} execution ...] subcommands. See the user
+ * documentation for details on what these do.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * Depends on the operation (add, remove, or info) being performed; may
+ * add or remove command traces on a command.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TraceExecutionObjCmd(
+ Tcl_Interp *interp, /* Current interpreter. */
+ int optionIndex, /* Add, info or remove */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int commandLength, index;
+ char *name, *command;
+ size_t length;
+ enum traceOptions {
+ TRACE_ADD, TRACE_INFO, TRACE_REMOVE
+ };
+ static const char *opStrings[] = {
+ "enter", "leave", "enterstep", "leavestep", NULL
+ };
+ enum operations {
+ TRACE_EXEC_ENTER, TRACE_EXEC_LEAVE,
+ TRACE_EXEC_ENTER_STEP, TRACE_EXEC_LEAVE_STEP
+ };
+
+ switch ((enum traceOptions) optionIndex) {
+ case TRACE_ADD:
+ case TRACE_REMOVE: {
+ int flags = 0;
+ int i, listLen, result;
+ Tcl_Obj **elemPtrs;
+
+ if (objc != 6) {
+ Tcl_WrongNumArgs(interp, 3, objv, "name opList command");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Make sure the ops argument is a list object; get its length and a
+ * pointer to its array of element pointers.
+ */
+
+ result = Tcl_ListObjGetElements(interp, objv[4], &listLen, &elemPtrs);
+ if (result != TCL_OK) {
+ return result;
+ }
+ if (listLen == 0) {
+ Tcl_SetResult(interp, "bad operation list \"\": must be "
+ "one or more of enter, leave, enterstep, or leavestep",
+ TCL_STATIC);
+ return TCL_ERROR;
+ }
+ for (i = 0; i < listLen; i++) {
+ if (Tcl_GetIndexFromObj(interp, elemPtrs[i], opStrings,
+ "operation", TCL_EXACT, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum operations) index) {
+ case TRACE_EXEC_ENTER:
+ flags |= TCL_TRACE_ENTER_EXEC;
+ break;
+ case TRACE_EXEC_LEAVE:
+ flags |= TCL_TRACE_LEAVE_EXEC;
+ break;
+ case TRACE_EXEC_ENTER_STEP:
+ flags |= TCL_TRACE_ENTER_DURING_EXEC;
+ break;
+ case TRACE_EXEC_LEAVE_STEP:
+ flags |= TCL_TRACE_LEAVE_DURING_EXEC;
+ break;
+ }
+ }
+ command = Tcl_GetStringFromObj(objv[5], &commandLength);
+ length = (size_t) commandLength;
+ if ((enum traceOptions) optionIndex == TRACE_ADD) {
+ TraceCommandInfo *tcmdPtr;
+
+ tcmdPtr = (TraceCommandInfo *) ckalloc((unsigned)
+ (sizeof(TraceCommandInfo) - sizeof(tcmdPtr->command)
+ + length + 1));
+ tcmdPtr->flags = flags;
+ tcmdPtr->stepTrace = NULL;
+ tcmdPtr->startLevel = 0;
+ tcmdPtr->startCmd = NULL;
+ tcmdPtr->length = length;
+ tcmdPtr->refCount = 1;
+ flags |= TCL_TRACE_DELETE;
+ if (flags & (TCL_TRACE_ENTER_DURING_EXEC |
+ TCL_TRACE_LEAVE_DURING_EXEC)) {
+ flags |= (TCL_TRACE_ENTER_EXEC | TCL_TRACE_LEAVE_EXEC);
+ }
+ memcpy(tcmdPtr->command, command, length+1);
+ name = Tcl_GetString(objv[3]);
+ if (Tcl_TraceCommand(interp, name, flags, TraceCommandProc,
+ (ClientData) tcmdPtr) != TCL_OK) {
+ ckfree((char *) tcmdPtr);
+ return TCL_ERROR;
+ }
+ } else {
+ /*
+ * Search through all of our traces on this command to see if
+ * there's one with the given command. If so, then delete the
+ * first one that matches.
+ */
+
+ TraceCommandInfo *tcmdPtr;
+ ClientData clientData = NULL;
+ name = Tcl_GetString(objv[3]);
+
+ /*
+ * First ensure the name given is valid.
+ */
+
+ if (Tcl_FindCommand(interp,name,NULL,TCL_LEAVE_ERR_MSG) == NULL) {
+ return TCL_ERROR;
+ }
+
+ while ((clientData = Tcl_CommandTraceInfo(interp, name, 0,
+ TraceCommandProc, clientData)) != NULL) {
+ tcmdPtr = (TraceCommandInfo *) clientData;
+
+ /*
+ * In checking the 'flags' field we must remove any extraneous
+ * flags which may have been temporarily added by various
+ * pieces of the trace mechanism.
+ */
+
+ if ((tcmdPtr->length == length)
+ && ((tcmdPtr->flags & (TCL_TRACE_ANY_EXEC |
+ TCL_TRACE_RENAME | TCL_TRACE_DELETE)) == flags)
+ && (strncmp(command, tcmdPtr->command,
+ (size_t) length) == 0)) {
+ flags |= TCL_TRACE_DELETE;
+ if (flags & (TCL_TRACE_ENTER_DURING_EXEC |
+ TCL_TRACE_LEAVE_DURING_EXEC)) {
+ flags |= (TCL_TRACE_ENTER_EXEC | TCL_TRACE_LEAVE_EXEC);
+ }
+ Tcl_UntraceCommand(interp, name, flags,
+ TraceCommandProc, clientData);
+ if (tcmdPtr->stepTrace != NULL) {
+ /*
+ * We need to remove the interpreter-wide trace which
+ * we created to allow 'step' traces.
+ */
+
+ Tcl_DeleteTrace(interp, tcmdPtr->stepTrace);
+ tcmdPtr->stepTrace = NULL;
+ if (tcmdPtr->startCmd != NULL) {
+ ckfree((char *) tcmdPtr->startCmd);
+ }
+ }
+ if (tcmdPtr->flags & TCL_TRACE_EXEC_IN_PROGRESS) {
+ /*
+ * Postpone deletion.
+ */
+
+ tcmdPtr->flags = 0;
+ }
+ if ((--tcmdPtr->refCount) <= 0) {
+ ckfree((char *) tcmdPtr);
+ }
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case TRACE_INFO: {
+ ClientData clientData;
+ Tcl_Obj *resultListPtr, *eachTraceObjPtr, *elemObjPtr;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "name");
+ return TCL_ERROR;
+ }
+
+ clientData = NULL;
+ name = Tcl_GetString(objv[3]);
+
+ /*
+ * First ensure the name given is valid.
+ */
+
+ if (Tcl_FindCommand(interp, name, NULL, TCL_LEAVE_ERR_MSG) == NULL) {
+ return TCL_ERROR;
+ }
+
+ resultListPtr = Tcl_NewListObj(0, NULL);
+ while ((clientData = Tcl_CommandTraceInfo(interp, name, 0,
+ TraceCommandProc, clientData)) != NULL) {
+ int numOps = 0;
+ Tcl_Obj *opObj;
+ TraceCommandInfo *tcmdPtr = (TraceCommandInfo *) clientData;
+
+ /*
+ * Build a list with the ops list as the first obj element and the
+ * tcmdPtr->command string as the second obj element. Append this
+ * list (as an element) to the end of the result object list.
+ */
+
+ elemObjPtr = Tcl_NewListObj(0, NULL);
+ Tcl_IncrRefCount(elemObjPtr);
+ if (tcmdPtr->flags & TCL_TRACE_ENTER_EXEC) {
+ TclNewLiteralStringObj(opObj, "enter");
+ Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj);
+ }
+ if (tcmdPtr->flags & TCL_TRACE_LEAVE_EXEC) {
+ TclNewLiteralStringObj(opObj, "leave");
+ Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj);
+ }
+ if (tcmdPtr->flags & TCL_TRACE_ENTER_DURING_EXEC) {
+ TclNewLiteralStringObj(opObj, "enterstep");
+ Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj);
+ }
+ if (tcmdPtr->flags & TCL_TRACE_LEAVE_DURING_EXEC) {
+ TclNewLiteralStringObj(opObj, "leavestep");
+ Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj);
+ }
+ Tcl_ListObjLength(NULL, elemObjPtr, &numOps);
+ if (0 == numOps) {
+ Tcl_DecrRefCount(elemObjPtr);
+ continue;
+ }
+ eachTraceObjPtr = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(NULL, eachTraceObjPtr, elemObjPtr);
+ Tcl_DecrRefCount(elemObjPtr);
+ elemObjPtr = NULL;
+
+ Tcl_ListObjAppendElement(NULL, eachTraceObjPtr,
+ Tcl_NewStringObj(tcmdPtr->command, -1));
+ Tcl_ListObjAppendElement(interp, resultListPtr, eachTraceObjPtr);
+ }
+ Tcl_SetObjResult(interp, resultListPtr);
+ break;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TraceCommandObjCmd --
+ *
+ * Helper function for Tcl_TraceObjCmd; implements the [trace
+ * {add|info|remove} command ...] subcommands. See the user documentation
+ * for details on what these do.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * Depends on the operation (add, remove, or info) being performed; may
+ * add or remove command traces on a command.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TraceCommandObjCmd(
+ Tcl_Interp *interp, /* Current interpreter. */
+ int optionIndex, /* Add, info or remove */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int commandLength, index;
+ char *name, *command;
+ size_t length;
+ enum traceOptions { TRACE_ADD, TRACE_INFO, TRACE_REMOVE };
+ static const char *opStrings[] = { "delete", "rename", NULL };
+ enum operations { TRACE_CMD_DELETE, TRACE_CMD_RENAME };
+
+ switch ((enum traceOptions) optionIndex) {
+ case TRACE_ADD:
+ case TRACE_REMOVE: {
+ int flags = 0;
+ int i, listLen, result;
+ Tcl_Obj **elemPtrs;
+
+ if (objc != 6) {
+ Tcl_WrongNumArgs(interp, 3, objv, "name opList command");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Make sure the ops argument is a list object; get its length and a
+ * pointer to its array of element pointers.
+ */
+
+ result = Tcl_ListObjGetElements(interp, objv[4], &listLen, &elemPtrs);
+ if (result != TCL_OK) {
+ return result;
+ }
+ if (listLen == 0) {
+ Tcl_SetResult(interp, "bad operation list \"\": must be "
+ "one or more of delete or rename", TCL_STATIC);
+ return TCL_ERROR;
+ }
+
+ for (i = 0; i < listLen; i++) {
+ if (Tcl_GetIndexFromObj(interp, elemPtrs[i], opStrings,
+ "operation", TCL_EXACT, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum operations) index) {
+ case TRACE_CMD_RENAME:
+ flags |= TCL_TRACE_RENAME;
+ break;
+ case TRACE_CMD_DELETE:
+ flags |= TCL_TRACE_DELETE;
+ break;
+ }
+ }
+
+ command = Tcl_GetStringFromObj(objv[5], &commandLength);
+ length = (size_t) commandLength;
+ if ((enum traceOptions) optionIndex == TRACE_ADD) {
+ TraceCommandInfo *tcmdPtr;
+
+ tcmdPtr = (TraceCommandInfo *) ckalloc((unsigned)
+ (sizeof(TraceCommandInfo) - sizeof(tcmdPtr->command)
+ + length + 1));
+ tcmdPtr->flags = flags;
+ tcmdPtr->stepTrace = NULL;
+ tcmdPtr->startLevel = 0;
+ tcmdPtr->startCmd = NULL;
+ tcmdPtr->length = length;
+ tcmdPtr->refCount = 1;
+ flags |= TCL_TRACE_DELETE;
+ memcpy(tcmdPtr->command, command, length+1);
+ name = Tcl_GetString(objv[3]);
+ if (Tcl_TraceCommand(interp, name, flags, TraceCommandProc,
+ (ClientData) tcmdPtr) != TCL_OK) {
+ ckfree((char *) tcmdPtr);
+ return TCL_ERROR;
+ }
+ } else {
+ /*
+ * Search through all of our traces on this command to see if
+ * there's one with the given command. If so, then delete the
+ * first one that matches.
+ */
+
+ TraceCommandInfo *tcmdPtr;
+ ClientData clientData = NULL;
+ name = Tcl_GetString(objv[3]);
+
+ /*
+ * First ensure the name given is valid.
+ */
+
+ if (Tcl_FindCommand(interp,name,NULL,TCL_LEAVE_ERR_MSG) == NULL) {
+ return TCL_ERROR;
+ }
+
+ while ((clientData = Tcl_CommandTraceInfo(interp, name, 0,
+ TraceCommandProc, clientData)) != NULL) {
+ tcmdPtr = (TraceCommandInfo *) clientData;
+ if ((tcmdPtr->length == length)
+ && (tcmdPtr->flags == flags)
+ && (strncmp(command, tcmdPtr->command,
+ (size_t) length) == 0)) {
+ Tcl_UntraceCommand(interp, name, flags | TCL_TRACE_DELETE,
+ TraceCommandProc, clientData);
+ tcmdPtr->flags |= TCL_TRACE_DESTROYED;
+ if ((--tcmdPtr->refCount) <= 0) {
+ ckfree((char *) tcmdPtr);
+ }
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case TRACE_INFO: {
+ ClientData clientData;
+ Tcl_Obj *resultListPtr, *eachTraceObjPtr, *elemObjPtr;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "name");
+ return TCL_ERROR;
+ }
+
+ clientData = NULL;
+ name = Tcl_GetString(objv[3]);
+
+ /*
+ * First ensure the name given is valid.
+ */
+
+ if (Tcl_FindCommand(interp, name, NULL, TCL_LEAVE_ERR_MSG) == NULL) {
+ return TCL_ERROR;
+ }
+
+ resultListPtr = Tcl_NewListObj(0, NULL);
+ while ((clientData = Tcl_CommandTraceInfo(interp, name, 0,
+ TraceCommandProc, clientData)) != NULL) {
+ int numOps = 0;
+ Tcl_Obj *opObj;
+ TraceCommandInfo *tcmdPtr = (TraceCommandInfo *) clientData;
+
+ /*
+ * Build a list with the ops list as the first obj element and the
+ * tcmdPtr->command string as the second obj element. Append this
+ * list (as an element) to the end of the result object list.
+ */
+
+ elemObjPtr = Tcl_NewListObj(0, NULL);
+ Tcl_IncrRefCount(elemObjPtr);
+ if (tcmdPtr->flags & TCL_TRACE_RENAME) {
+ TclNewLiteralStringObj(opObj, "rename");
+ Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj);
+ }
+ if (tcmdPtr->flags & TCL_TRACE_DELETE) {
+ TclNewLiteralStringObj(opObj, "delete");
+ Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj);
+ }
+ Tcl_ListObjLength(NULL, elemObjPtr, &numOps);
+ if (0 == numOps) {
+ Tcl_DecrRefCount(elemObjPtr);
+ continue;
+ }
+ eachTraceObjPtr = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(NULL, eachTraceObjPtr, elemObjPtr);
+ Tcl_DecrRefCount(elemObjPtr);
+
+ elemObjPtr = Tcl_NewStringObj(tcmdPtr->command, -1);
+ Tcl_ListObjAppendElement(NULL, eachTraceObjPtr, elemObjPtr);
+ Tcl_ListObjAppendElement(interp, resultListPtr, eachTraceObjPtr);
+ }
+ Tcl_SetObjResult(interp, resultListPtr);
+ break;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TraceVariableObjCmd --
+ *
+ * Helper function for Tcl_TraceObjCmd; implements the [trace
+ * {add|info|remove} variable ...] subcommands. See the user
+ * documentation for details on what these do.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * Depends on the operation (add, remove, or info) being performed; may
+ * add or remove variable traces on a variable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TraceVariableObjCmd(
+ Tcl_Interp *interp, /* Current interpreter. */
+ int optionIndex, /* Add, info or remove */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int commandLength, index;
+ char *name, *command;
+ size_t length;
+ enum traceOptions { TRACE_ADD, TRACE_INFO, TRACE_REMOVE };
+ static const char *opStrings[] = {
+ "array", "read", "unset", "write", NULL
+ };
+ enum operations {
+ TRACE_VAR_ARRAY, TRACE_VAR_READ, TRACE_VAR_UNSET, TRACE_VAR_WRITE
+ };
+
+ switch ((enum traceOptions) optionIndex) {
+ case TRACE_ADD:
+ case TRACE_REMOVE: {
+ int flags = 0;
+ int i, listLen, result;
+ Tcl_Obj **elemPtrs;
+
+ if (objc != 6) {
+ Tcl_WrongNumArgs(interp, 3, objv, "name opList command");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Make sure the ops argument is a list object; get its length and a
+ * pointer to its array of element pointers.
+ */
+
+ result = Tcl_ListObjGetElements(interp, objv[4], &listLen, &elemPtrs);
+ if (result != TCL_OK) {
+ return result;
+ }
+ if (listLen == 0) {
+ Tcl_SetResult(interp, "bad operation list \"\": must be "
+ "one or more of array, read, unset, or write", TCL_STATIC);
+ return TCL_ERROR;
+ }
+ for (i = 0; i < listLen ; i++) {
+ if (Tcl_GetIndexFromObj(interp, elemPtrs[i], opStrings,
+ "operation", TCL_EXACT, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum operations) index) {
+ case TRACE_VAR_ARRAY:
+ flags |= TCL_TRACE_ARRAY;
+ break;
+ case TRACE_VAR_READ:
+ flags |= TCL_TRACE_READS;
+ break;
+ case TRACE_VAR_UNSET:
+ flags |= TCL_TRACE_UNSETS;
+ break;
+ case TRACE_VAR_WRITE:
+ flags |= TCL_TRACE_WRITES;
+ break;
+ }
+ }
+ command = Tcl_GetStringFromObj(objv[5], &commandLength);
+ length = (size_t) commandLength;
+ if ((enum traceOptions) optionIndex == TRACE_ADD) {
+ CombinedTraceVarInfo *ctvarPtr;
+
+ ctvarPtr = (CombinedTraceVarInfo *) ckalloc((unsigned)
+ (sizeof(CombinedTraceVarInfo) + length + 1
+ - sizeof(ctvarPtr->traceCmdInfo.command)));
+ ctvarPtr->traceCmdInfo.flags = flags;
+ if (objv[0] == NULL) {
+ ctvarPtr->traceCmdInfo.flags |= TCL_TRACE_OLD_STYLE;
+ }
+ ctvarPtr->traceCmdInfo.length = length;
+ flags |= TCL_TRACE_UNSETS | TCL_TRACE_RESULT_OBJECT;
+ memcpy(ctvarPtr->traceCmdInfo.command, command, length+1);
+ ctvarPtr->traceInfo.traceProc = TraceVarProc;
+ ctvarPtr->traceInfo.clientData = (ClientData)
+ &ctvarPtr->traceCmdInfo;
+ ctvarPtr->traceInfo.flags = flags;
+ name = Tcl_GetString(objv[3]);
+ if (TraceVarEx(interp,name,NULL,(VarTrace*)ctvarPtr) != TCL_OK) {
+ ckfree((char *) ctvarPtr);
+ return TCL_ERROR;
+ }
+ } else {
+ /*
+ * Search through all of our traces on this variable to see if
+ * there's one with the given command. If so, then delete the
+ * first one that matches.
+ */
+
+ TraceVarInfo *tvarPtr;
+ ClientData clientData = 0;
+ name = Tcl_GetString(objv[3]);
+ while ((clientData = Tcl_VarTraceInfo(interp, name, 0,
+ TraceVarProc, clientData)) != 0) {
+ tvarPtr = (TraceVarInfo *) clientData;
+ if ((tvarPtr->length == length)
+ && ((tvarPtr->flags & ~TCL_TRACE_OLD_STYLE)==flags)
+ && (strncmp(command, tvarPtr->command,
+ (size_t) length) == 0)) {
+ Tcl_UntraceVar2(interp, name, NULL,
+ flags | TCL_TRACE_UNSETS | TCL_TRACE_RESULT_OBJECT,
+ TraceVarProc, clientData);
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case TRACE_INFO: {
+ ClientData clientData;
+ Tcl_Obj *resultListPtr, *eachTraceObjPtr, *elemObjPtr;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "name");
+ return TCL_ERROR;
+ }
+
+ resultListPtr = Tcl_NewObj();
+ clientData = 0;
+ name = Tcl_GetString(objv[3]);
+ while ((clientData = Tcl_VarTraceInfo(interp, name, 0, TraceVarProc,
+ clientData)) != 0) {
+ Tcl_Obj *opObj;
+ TraceVarInfo *tvarPtr = (TraceVarInfo *) clientData;
+
+ /*
+ * Build a list with the ops list as the first obj element and the
+ * tcmdPtr->command string as the second obj element. Append this
+ * list (as an element) to the end of the result object list.
+ */
+
+ elemObjPtr = Tcl_NewListObj(0, NULL);
+ if (tvarPtr->flags & TCL_TRACE_ARRAY) {
+ TclNewLiteralStringObj(opObj, "array");
+ Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj);
+ }
+ if (tvarPtr->flags & TCL_TRACE_READS) {
+ TclNewLiteralStringObj(opObj, "read");
+ Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj);
+ }
+ if (tvarPtr->flags & TCL_TRACE_WRITES) {
+ TclNewLiteralStringObj(opObj, "write");
+ Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj);
+ }
+ if (tvarPtr->flags & TCL_TRACE_UNSETS) {
+ TclNewLiteralStringObj(opObj, "unset");
+ Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj);
+ }
+ eachTraceObjPtr = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(NULL, eachTraceObjPtr, elemObjPtr);
+
+ elemObjPtr = Tcl_NewStringObj(tvarPtr->command, -1);
+ Tcl_ListObjAppendElement(NULL, eachTraceObjPtr, elemObjPtr);
+ Tcl_ListObjAppendElement(interp, resultListPtr,
+ eachTraceObjPtr);
+ }
+ Tcl_SetObjResult(interp, resultListPtr);
+ break;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_CommandTraceInfo --
+ *
+ * Return the clientData value associated with a trace on a command.
+ * This function can also be used to step through all of the traces on a
+ * particular command that have the same trace function.
+ *
+ * Results:
+ * The return value is the clientData value associated with a trace on
+ * the given command. Information will only be returned for a trace with
+ * proc as trace function. If the clientData argument is NULL then the
+ * first such trace is returned; otherwise, the next relevant one after
+ * the one given by clientData will be returned. If the command doesn't
+ * exist then an error message is left in the interpreter and NULL is
+ * returned. Also, if there are no (more) traces for the given command,
+ * NULL is returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ClientData
+Tcl_CommandTraceInfo(
+ Tcl_Interp *interp, /* Interpreter containing command. */
+ const char *cmdName, /* Name of command. */
+ int flags, /* OR-ed combo or TCL_GLOBAL_ONLY,
+ * TCL_NAMESPACE_ONLY (can be 0). */
+ Tcl_CommandTraceProc *proc, /* Function assocated with trace. */
+ ClientData prevClientData) /* If non-NULL, gives last value returned by
+ * this function, so this call will return the
+ * next trace after that one. If NULL, this
+ * call will return the first trace. */
+{
+ Command *cmdPtr;
+ register CommandTrace *tracePtr;
+
+ cmdPtr = (Command *) Tcl_FindCommand(interp, cmdName, NULL,
+ TCL_LEAVE_ERR_MSG);
+ if (cmdPtr == NULL) {
+ return NULL;
+ }
+
+ /*
+ * Find the relevant trace, if any, and return its clientData.
+ */
+
+ tracePtr = cmdPtr->tracePtr;
+ if (prevClientData != NULL) {
+ for (; tracePtr!=NULL ; tracePtr=tracePtr->nextPtr) {
+ if ((tracePtr->clientData == prevClientData)
+ && (tracePtr->traceProc == proc)) {
+ tracePtr = tracePtr->nextPtr;
+ break;
+ }
+ }
+ }
+ for (; tracePtr!=NULL ; tracePtr=tracePtr->nextPtr) {
+ if (tracePtr->traceProc == proc) {
+ return tracePtr->clientData;
+ }
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_TraceCommand --
+ *
+ * Arrange for rename/deletes to a command to cause a function to be
+ * invoked, which can monitor the operations.
+ *
+ * Also optionally arrange for execution of that command to cause a
+ * function to be invoked.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * A trace is set up on the command given by cmdName, such that future
+ * changes to the command will be intermediated by proc. See the manual
+ * entry for complete details on the calling sequence for proc.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_TraceCommand(
+ Tcl_Interp *interp, /* Interpreter in which command is to be
+ * traced. */
+ const char *cmdName, /* Name of command. */
+ int flags, /* OR-ed collection of bits, including any of
+ * TCL_TRACE_RENAME, TCL_TRACE_DELETE, and any
+ * of the TRACE_*_EXEC flags */
+ Tcl_CommandTraceProc *proc, /* Function to call when specified ops are
+ * invoked upon cmdName. */
+ ClientData clientData) /* Arbitrary argument to pass to proc. */
+{
+ Command *cmdPtr;
+ register CommandTrace *tracePtr;
+
+ cmdPtr = (Command *) Tcl_FindCommand(interp, cmdName, NULL,
+ TCL_LEAVE_ERR_MSG);
+ if (cmdPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Set up trace information.
+ */
+
+ tracePtr = (CommandTrace *) ckalloc(sizeof(CommandTrace));
+ tracePtr->traceProc = proc;
+ tracePtr->clientData = clientData;
+ tracePtr->flags = flags &
+ (TCL_TRACE_RENAME | TCL_TRACE_DELETE | TCL_TRACE_ANY_EXEC);
+ tracePtr->nextPtr = cmdPtr->tracePtr;
+ tracePtr->refCount = 1;
+ cmdPtr->tracePtr = tracePtr;
+ if (tracePtr->flags & TCL_TRACE_ANY_EXEC) {
+ cmdPtr->flags |= CMD_HAS_EXEC_TRACES;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_UntraceCommand --
+ *
+ * Remove a previously-created trace for a command.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If there exists a trace for the command given by cmdName with the
+ * given flags, proc, and clientData, then that trace is removed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_UntraceCommand(
+ Tcl_Interp *interp, /* Interpreter containing command. */
+ const char *cmdName, /* Name of command. */
+ int flags, /* OR-ed collection of bits, including any of
+ * TCL_TRACE_RENAME, TCL_TRACE_DELETE, and any
+ * of the TRACE_*_EXEC flags */
+ Tcl_CommandTraceProc *proc, /* Function assocated with trace. */
+ ClientData clientData) /* Arbitrary argument to pass to proc. */
+{
+ register CommandTrace *tracePtr;
+ CommandTrace *prevPtr;
+ Command *cmdPtr;
+ Interp *iPtr = (Interp *) interp;
+ ActiveCommandTrace *activePtr;
+ int hasExecTraces = 0;
+
+ cmdPtr = (Command *) Tcl_FindCommand(interp, cmdName, NULL,
+ TCL_LEAVE_ERR_MSG);
+ if (cmdPtr == NULL) {
+ return;
+ }
+
+ flags &= (TCL_TRACE_RENAME | TCL_TRACE_DELETE | TCL_TRACE_ANY_EXEC);
+
+ for (tracePtr = cmdPtr->tracePtr, prevPtr = NULL; ;
+ prevPtr = tracePtr, tracePtr = tracePtr->nextPtr) {
+ if (tracePtr == NULL) {
+ return;
+ }
+ if ((tracePtr->traceProc == proc)
+ && ((tracePtr->flags & (TCL_TRACE_RENAME | TCL_TRACE_DELETE |
+ TCL_TRACE_ANY_EXEC)) == flags)
+ && (tracePtr->clientData == clientData)) {
+ if (tracePtr->flags & TCL_TRACE_ANY_EXEC) {
+ hasExecTraces = 1;
+ }
+ break;
+ }
+ }
+
+ /*
+ * The code below makes it possible to delete traces while traces are
+ * active: it makes sure that the deleted trace won't be processed by
+ * CallCommandTraces.
+ */
+
+ for (activePtr = iPtr->activeCmdTracePtr; activePtr != NULL;
+ activePtr = activePtr->nextPtr) {
+ if (activePtr->nextTracePtr == tracePtr) {
+ if (activePtr->reverseScan) {
+ activePtr->nextTracePtr = prevPtr;
+ } else {
+ activePtr->nextTracePtr = tracePtr->nextPtr;
+ }
+ }
+ }
+ if (prevPtr == NULL) {
+ cmdPtr->tracePtr = tracePtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = tracePtr->nextPtr;
+ }
+ tracePtr->flags = 0;
+
+ if ((--tracePtr->refCount) <= 0) {
+ ckfree((char *) tracePtr);
+ }
+
+ if (hasExecTraces) {
+ for (tracePtr = cmdPtr->tracePtr, prevPtr = NULL; tracePtr != NULL ;
+ prevPtr = tracePtr, tracePtr = tracePtr->nextPtr) {
+ if (tracePtr->flags & TCL_TRACE_ANY_EXEC) {
+ return;
+ }
+ }
+
+ /*
+ * None of the remaining traces on this command are execution traces.
+ * We therefore remove this flag:
+ */
+
+ cmdPtr->flags &= ~CMD_HAS_EXEC_TRACES;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TraceCommandProc --
+ *
+ * This function is called to handle command changes that have been
+ * traced using the "trace" command, when using the 'rename' or 'delete'
+ * options.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depends on the command associated with the trace.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static void
+TraceCommandProc(
+ ClientData clientData, /* Information about the command trace. */
+ Tcl_Interp *interp, /* Interpreter containing command. */
+ const char *oldName, /* Name of command being changed. */
+ const char *newName, /* New name of command. Empty string or NULL
+ * means command is being deleted (renamed to
+ * ""). */
+ int flags) /* OR-ed bits giving operation and other
+ * information. */
+{
+ TraceCommandInfo *tcmdPtr = (TraceCommandInfo *) clientData;
+ int code;
+ Tcl_DString cmd;
+
+ tcmdPtr->refCount++;
+
+ if ((tcmdPtr->flags & flags) && !Tcl_InterpDeleted(interp)
+ && !Tcl_LimitExceeded(interp)) {
+ /*
+ * Generate a command to execute by appending list elements for the
+ * old and new command name and the operation.
+ */
+
+ Tcl_DStringInit(&cmd);
+ Tcl_DStringAppend(&cmd, tcmdPtr->command, (int) tcmdPtr->length);
+ Tcl_DStringAppendElement(&cmd, oldName);
+ Tcl_DStringAppendElement(&cmd, (newName ? newName : ""));
+ if (flags & TCL_TRACE_RENAME) {
+ Tcl_DStringAppend(&cmd, " rename", 7);
+ } else if (flags & TCL_TRACE_DELETE) {
+ Tcl_DStringAppend(&cmd, " delete", 7);
+ }
+
+ /*
+ * Execute the command. We discard any object result the command
+ * returns.
+ *
+ * Add the TCL_TRACE_DESTROYED flag to tcmdPtr to indicate to other
+ * areas that this will be destroyed by us, otherwise a double-free
+ * might occur depending on what the eval does.
+ */
+
+ if (flags & TCL_TRACE_DESTROYED) {
+ tcmdPtr->flags |= TCL_TRACE_DESTROYED;
+ }
+ code = Tcl_EvalEx(interp, Tcl_DStringValue(&cmd),
+ Tcl_DStringLength(&cmd), 0);
+ if (code != TCL_OK) {
+ /* We ignore errors in these traced commands */
+ /*** QUESTION: Use Tcl_BackgroundError(interp); instead? ***/
+ }
+ Tcl_DStringFree(&cmd);
+ }
+
+ /*
+ * We delete when the trace was destroyed or if this is a delete trace,
+ * because command deletes are unconditional, so the trace must go away.
+ */
+
+ if (flags & (TCL_TRACE_DESTROYED | TCL_TRACE_DELETE)) {
+ int untraceFlags = tcmdPtr->flags;
+ Tcl_InterpState state;
+
+ if (tcmdPtr->stepTrace != NULL) {
+ Tcl_DeleteTrace(interp, tcmdPtr->stepTrace);
+ tcmdPtr->stepTrace = NULL;
+ if (tcmdPtr->startCmd != NULL) {
+ ckfree((char *) tcmdPtr->startCmd);
+ }
+ }
+ if (tcmdPtr->flags & TCL_TRACE_EXEC_IN_PROGRESS) {
+ /*
+ * Postpone deletion, until exec trace returns.
+ */
+
+ tcmdPtr->flags = 0;
+ }
+
+ /*
+ * We need to construct the same flags for Tcl_UntraceCommand as were
+ * passed to Tcl_TraceCommand. Reproduce the processing of [trace add
+ * execution/command]. Be careful to keep this code in sync with that.
+ */
+
+ if (untraceFlags & TCL_TRACE_ANY_EXEC) {
+ untraceFlags |= TCL_TRACE_DELETE;
+ if (untraceFlags & (TCL_TRACE_ENTER_DURING_EXEC
+ | TCL_TRACE_LEAVE_DURING_EXEC)) {
+ untraceFlags |= (TCL_TRACE_ENTER_EXEC | TCL_TRACE_LEAVE_EXEC);
+ }
+ } else if (untraceFlags & TCL_TRACE_RENAME) {
+ untraceFlags |= TCL_TRACE_DELETE;
+ }
+
+ /*
+ * Remove the trace since TCL_TRACE_DESTROYED tells us to, or the
+ * command we're tracing has just gone away. Then decrement the
+ * clientData refCount that was set up by trace creation.
+ *
+ * Note that we save the (return) state of the interpreter to prevent
+ * bizarre error messages.
+ */
+
+ state = Tcl_SaveInterpState(interp, TCL_OK);
+ Tcl_UntraceCommand(interp, oldName, untraceFlags,
+ TraceCommandProc, clientData);
+ (void) Tcl_RestoreInterpState(interp, state);
+ tcmdPtr->refCount--;
+ }
+ if ((--tcmdPtr->refCount) <= 0) {
+ ckfree((char *) tcmdPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCheckExecutionTraces --
+ *
+ * Checks on all current command execution traces, and invokes functions
+ * which have been registered. This function can be used by other code
+ * which performs execution to unify the tracing system, so that
+ * execution traces will function for that other code.
+ *
+ * For instance extensions like [incr Tcl] which use their own execution
+ * technique can make use of Tcl's tracing.
+ *
+ * This function is called by 'TclEvalObjvInternal'
+ *
+ * Results:
+ * The return value is a standard Tcl completion code such as TCL_OK or
+ * TCL_ERROR, etc.
+ *
+ * Side effects:
+ * Those side effects made by any trace functions called.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCheckExecutionTraces(
+ Tcl_Interp *interp, /* The current interpreter. */
+ const char *command, /* Pointer to beginning of the current command
+ * string. */
+ int numChars, /* The number of characters in 'command' which
+ * are part of the command string. */
+ Command *cmdPtr, /* Points to command's Command struct. */
+ int code, /* The current result code. */
+ int traceFlags, /* Current tracing situation. */
+ int objc, /* Number of arguments for the command. */
+ Tcl_Obj *const objv[]) /* Pointers to Tcl_Obj of each argument. */
+{
+ Interp *iPtr = (Interp *) interp;
+ CommandTrace *tracePtr, *lastTracePtr;
+ ActiveCommandTrace active;
+ int curLevel;
+ int traceCode = TCL_OK;
+ Tcl_InterpState state = NULL;
+
+ if (cmdPtr->tracePtr == NULL) {
+ return traceCode;
+ }
+
+ curLevel = iPtr->varFramePtr->level;
+
+ active.nextPtr = iPtr->activeCmdTracePtr;
+ iPtr->activeCmdTracePtr = &active;
+
+ active.cmdPtr = cmdPtr;
+ lastTracePtr = NULL;
+ for (tracePtr = cmdPtr->tracePtr;
+ (traceCode == TCL_OK) && (tracePtr != NULL);
+ tracePtr = active.nextTracePtr) {
+ if (traceFlags & TCL_TRACE_LEAVE_EXEC) {
+ /*
+ * Execute the trace command in order of creation for "leave".
+ */
+
+ active.reverseScan = 1;
+ active.nextTracePtr = NULL;
+ tracePtr = cmdPtr->tracePtr;
+ while (tracePtr->nextPtr != lastTracePtr) {
+ active.nextTracePtr = tracePtr;
+ tracePtr = tracePtr->nextPtr;
+ }
+ } else {
+ active.reverseScan = 0;
+ active.nextTracePtr = tracePtr->nextPtr;
+ }
+ if (tracePtr->traceProc == TraceCommandProc) {
+ TraceCommandInfo *tcmdPtr = (TraceCommandInfo *)
+ tracePtr->clientData;
+
+ if (tcmdPtr->flags != 0) {
+ tcmdPtr->curFlags = traceFlags | TCL_TRACE_EXEC_DIRECT;
+ tcmdPtr->curCode = code;
+ tcmdPtr->refCount++;
+ if (state == NULL) {
+ state = Tcl_SaveInterpState(interp, code);
+ }
+ traceCode = TraceExecutionProc((ClientData) tcmdPtr, interp,
+ curLevel, command, (Tcl_Command) cmdPtr, objc, objv);
+ if ((--tcmdPtr->refCount) <= 0) {
+ ckfree((char *) tcmdPtr);
+ }
+ }
+ }
+ if (active.nextTracePtr) {
+ lastTracePtr = active.nextTracePtr->nextPtr;
+ }
+ }
+ iPtr->activeCmdTracePtr = active.nextPtr;
+ if (state) {
+ (void) Tcl_RestoreInterpState(interp, state);
+ }
+
+ return(traceCode);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCheckInterpTraces --
+ *
+ * Checks on all current traces, and invokes functions which have been
+ * registered. This function can be used by other code which performs
+ * execution to unify the tracing system. For instance extensions like
+ * [incr Tcl] which use their own execution technique can make use of
+ * Tcl's tracing.
+ *
+ * This function is called by 'TclEvalObjvInternal'
+ *
+ * Results:
+ * The return value is a standard Tcl completion code such as TCL_OK or
+ * TCL_ERROR, etc.
+ *
+ * Side effects:
+ * Those side effects made by any trace functions called.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclCheckInterpTraces(
+ Tcl_Interp *interp, /* The current interpreter. */
+ const char *command, /* Pointer to beginning of the current command
+ * string. */
+ int numChars, /* The number of characters in 'command' which
+ * are part of the command string. */
+ Command *cmdPtr, /* Points to command's Command struct. */
+ int code, /* The current result code. */
+ int traceFlags, /* Current tracing situation. */
+ int objc, /* Number of arguments for the command. */
+ Tcl_Obj *const objv[]) /* Pointers to Tcl_Obj of each argument. */
+{
+ Interp *iPtr = (Interp *) interp;
+ Trace *tracePtr, *lastTracePtr;
+ ActiveInterpTrace active;
+ int curLevel;
+ int traceCode = TCL_OK;
+ Tcl_InterpState state = NULL;
+
+ if ((iPtr->tracePtr == NULL)
+ || (iPtr->flags & INTERP_TRACE_IN_PROGRESS)) {
+ return(traceCode);
+ }
+
+ curLevel = iPtr->numLevels;
+
+ active.nextPtr = iPtr->activeInterpTracePtr;
+ iPtr->activeInterpTracePtr = &active;
+
+ lastTracePtr = NULL;
+ for (tracePtr = iPtr->tracePtr;
+ (traceCode == TCL_OK) && (tracePtr != NULL);
+ tracePtr = active.nextTracePtr) {
+ if (traceFlags & TCL_TRACE_ENTER_EXEC) {
+ /*
+ * Execute the trace command in reverse order of creation for
+ * "enterstep" operation. The order is changed for "enterstep"
+ * instead of for "leavestep" as was done in
+ * TclCheckExecutionTraces because for step traces,
+ * Tcl_CreateObjTrace creates one more linked list of traces which
+ * results in one more reversal of trace invocation.
+ */
+
+ active.reverseScan = 1;
+ active.nextTracePtr = NULL;
+ tracePtr = iPtr->tracePtr;
+ while (tracePtr->nextPtr != lastTracePtr) {
+ active.nextTracePtr = tracePtr;
+ tracePtr = tracePtr->nextPtr;
+ }
+ if (active.nextTracePtr) {
+ lastTracePtr = active.nextTracePtr->nextPtr;
+ }
+ } else {
+ active.reverseScan = 0;
+ active.nextTracePtr = tracePtr->nextPtr;
+ }
+
+ if (tracePtr->level > 0 && curLevel > tracePtr->level) {
+ continue;
+ }
+
+ if (!(tracePtr->flags & TCL_TRACE_EXEC_IN_PROGRESS)) {
+ /*
+ * The proc invoked might delete the traced command which which
+ * might try to free tracePtr. We want to use tracePtr until the
+ * end of this if section, so we use Tcl_Preserve() and
+ * Tcl_Release() to be sure it is not freed while we still need
+ * it.
+ */
+
+ Tcl_Preserve((ClientData) tracePtr);
+ tracePtr->flags |= TCL_TRACE_EXEC_IN_PROGRESS;
+ if (state == NULL) {
+ state = Tcl_SaveInterpState(interp, code);
+ }
+
+ if (tracePtr->flags &
+ (TCL_TRACE_ENTER_EXEC | TCL_TRACE_LEAVE_EXEC)) {
+ /*
+ * New style trace.
+ */
+
+ if (tracePtr->flags & traceFlags) {
+ if (tracePtr->proc == TraceExecutionProc) {
+ TraceCommandInfo *tcmdPtr = (TraceCommandInfo *)
+ tracePtr->clientData;
+
+ tcmdPtr->curFlags = traceFlags;
+ tcmdPtr->curCode = code;
+ }
+ traceCode = (tracePtr->proc)(tracePtr->clientData,
+ interp, curLevel, command, (Tcl_Command) cmdPtr,
+ objc, objv);
+ }
+ } else {
+ /*
+ * Old-style trace.
+ */
+
+ if (traceFlags & TCL_TRACE_ENTER_EXEC) {
+ /*
+ * Old-style interpreter-wide traces only trigger before
+ * the command is executed.
+ */
+
+ traceCode = CallTraceFunction(interp, tracePtr, cmdPtr,
+ command, numChars, objc, objv);
+ }
+ }
+ tracePtr->flags &= ~TCL_TRACE_EXEC_IN_PROGRESS;
+ Tcl_Release((ClientData) tracePtr);
+ }
+ }
+ iPtr->activeInterpTracePtr = active.nextPtr;
+ if (state) {
+ if (traceCode == TCL_OK) {
+ (void) Tcl_RestoreInterpState(interp, state);
+ } else {
+ Tcl_DiscardInterpState(state);
+ }
+ }
+
+ return(traceCode);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CallTraceFunction --
+ *
+ * Invokes a trace function registered with an interpreter. These
+ * functions trace command execution. Currently this trace function is
+ * called with the address of the string-based Tcl_CmdProc for the
+ * command, not the Tcl_ObjCmdProc.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Those side effects made by the trace function.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CallTraceFunction(
+ Tcl_Interp *interp, /* The current interpreter. */
+ register Trace *tracePtr, /* Describes the trace function to call. */
+ Command *cmdPtr, /* Points to command's Command struct. */
+ const char *command, /* Points to the first character of the
+ * command's source before substitutions. */
+ int numChars, /* The number of characters in the command's
+ * source. */
+ register int objc, /* Number of arguments for the command. */
+ Tcl_Obj *const objv[]) /* Pointers to Tcl_Obj of each argument. */
+{
+ Interp *iPtr = (Interp *) interp;
+ char *commandCopy;
+ int traceCode;
+
+ /*
+ * Copy the command characters into a new string.
+ */
+
+ commandCopy = TclStackAlloc(interp, (unsigned) (numChars + 1));
+ memcpy(commandCopy, command, (size_t) numChars);
+ commandCopy[numChars] = '\0';
+
+ /*
+ * Call the trace function then free allocated storage.
+ */
+
+ traceCode = (tracePtr->proc)(tracePtr->clientData, (Tcl_Interp *) iPtr,
+ iPtr->numLevels, commandCopy, (Tcl_Command) cmdPtr, objc, objv);
+
+ TclStackFree(interp, commandCopy);
+ return traceCode;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CommandObjTraceDeleted --
+ *
+ * Ensure the trace is correctly deleted by decrementing its refCount and
+ * only deleting if no other references exist.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May release memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CommandObjTraceDeleted(
+ ClientData clientData)
+{
+ TraceCommandInfo *tcmdPtr = (TraceCommandInfo *) clientData;
+
+ if ((--tcmdPtr->refCount) <= 0) {
+ ckfree((char *) tcmdPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TraceExecutionProc --
+ *
+ * This function is invoked whenever code relevant to a 'trace execution'
+ * command is executed. It is called in one of two ways in Tcl's core:
+ *
+ * (i) by the TclCheckExecutionTraces, when an execution trace has been
+ * triggered.
+ * (ii) by TclCheckInterpTraces, when a prior execution trace has created
+ * a trace of the internals of a procedure, passing in this function as
+ * the one to be called.
+ *
+ * Results:
+ * The return value is a standard Tcl completion code such as TCL_OK or
+ * TCL_ERROR, etc.
+ *
+ * Side effects:
+ * May invoke an arbitrary Tcl procedure, and may create or delete an
+ * interpreter-wide trace.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TraceExecutionProc(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int level,
+ const char *command,
+ Tcl_Command cmdInfo,
+ int objc,
+ struct Tcl_Obj *const objv[])
+{
+ int call = 0;
+ Interp *iPtr = (Interp *) interp;
+ TraceCommandInfo *tcmdPtr = (TraceCommandInfo *) clientData;
+ int flags = tcmdPtr->curFlags;
+ int code = tcmdPtr->curCode;
+ int traceCode = TCL_OK;
+
+ if (tcmdPtr->flags & TCL_TRACE_EXEC_IN_PROGRESS) {
+ /*
+ * Inside any kind of execution trace callback, we do not allow any
+ * further execution trace callbacks to be called for the same trace.
+ */
+
+ return traceCode;
+ }
+
+ if (!Tcl_InterpDeleted(interp) && !Tcl_LimitExceeded(interp)) {
+ /*
+ * Check whether the current call is going to eval arbitrary Tcl code
+ * with a generated trace, or whether we are only going to setup
+ * interpreter-wide traces to implement the 'step' traces. This latter
+ * situation can happen if we create a command trace without either
+ * before or after operations, but with either of the step operations.
+ */
+
+ if (flags & TCL_TRACE_EXEC_DIRECT) {
+ call = flags & tcmdPtr->flags &
+ (TCL_TRACE_ENTER_EXEC | TCL_TRACE_LEAVE_EXEC);
+ } else {
+ call = 1;
+ }
+
+ /*
+ * First, if we have returned back to the level at which we created an
+ * interpreter trace for enterstep and/or leavestep execution traces,
+ * we remove it here.
+ */
+
+ if ((flags & TCL_TRACE_LEAVE_EXEC) && (tcmdPtr->stepTrace != NULL)
+ && (level == tcmdPtr->startLevel)
+ && (strcmp(command, tcmdPtr->startCmd) == 0)) {
+ Tcl_DeleteTrace(interp, tcmdPtr->stepTrace);
+ tcmdPtr->stepTrace = NULL;
+ if (tcmdPtr->startCmd != NULL) {
+ ckfree((char *) tcmdPtr->startCmd);
+ }
+ }
+
+ /*
+ * Second, create the tcl callback, if required.
+ */
+
+ if (call) {
+ Tcl_DString cmd;
+ Tcl_DString sub;
+ int i, saveInterpFlags;
+
+ Tcl_DStringInit(&cmd);
+ Tcl_DStringAppend(&cmd, tcmdPtr->command, (int)tcmdPtr->length);
+
+ /*
+ * Append command with arguments.
+ */
+
+ Tcl_DStringInit(&sub);
+ for (i = 0; i < objc; i++) {
+ Tcl_DStringAppendElement(&sub, Tcl_GetString(objv[i]));
+ }
+ Tcl_DStringAppendElement(&cmd, Tcl_DStringValue(&sub));
+ Tcl_DStringFree(&sub);
+
+ if (flags & TCL_TRACE_ENTER_EXEC) {
+ /*
+ * Append trace operation.
+ */
+
+ if (flags & TCL_TRACE_EXEC_DIRECT) {
+ Tcl_DStringAppendElement(&cmd, "enter");
+ } else {
+ Tcl_DStringAppendElement(&cmd, "enterstep");
+ }
+ } else if (flags & TCL_TRACE_LEAVE_EXEC) {
+ Tcl_Obj *resultCode;
+ char *resultCodeStr;
+
+ /*
+ * Append result code.
+ */
+
+ resultCode = Tcl_NewIntObj(code);
+ resultCodeStr = Tcl_GetString(resultCode);
+ Tcl_DStringAppendElement(&cmd, resultCodeStr);
+ Tcl_DecrRefCount(resultCode);
+
+ /*
+ * Append result string.
+ */
+
+ Tcl_DStringAppendElement(&cmd, Tcl_GetStringResult(interp));
+
+ /*
+ * Append trace operation.
+ */
+
+ if (flags & TCL_TRACE_EXEC_DIRECT) {
+ Tcl_DStringAppendElement(&cmd, "leave");
+ } else {
+ Tcl_DStringAppendElement(&cmd, "leavestep");
+ }
+ } else {
+ Tcl_Panic("TraceExecutionProc: bad flag combination");
+ }
+
+ /*
+ * Execute the command. We discard any object result the command
+ * returns.
+ */
+
+ saveInterpFlags = iPtr->flags;
+ iPtr->flags |= INTERP_TRACE_IN_PROGRESS;
+ tcmdPtr->flags |= TCL_TRACE_EXEC_IN_PROGRESS;
+ tcmdPtr->refCount++;
+
+ /*
+ * This line can have quite arbitrary side-effects, including
+ * deleting the trace, the command being traced, or even the
+ * interpreter.
+ */
+
+ traceCode = Tcl_Eval(interp, Tcl_DStringValue(&cmd));
+ tcmdPtr->flags &= ~TCL_TRACE_EXEC_IN_PROGRESS;
+
+ /*
+ * Restore the interp tracing flag to prevent cmd traces from
+ * affecting interp traces.
+ */
+
+ iPtr->flags = saveInterpFlags;
+ if (tcmdPtr->flags == 0) {
+ flags |= TCL_TRACE_DESTROYED;
+ }
+ Tcl_DStringFree(&cmd);
+ }
+
+ /*
+ * Third, if there are any step execution traces for this proc, we
+ * register an interpreter trace to invoke enterstep and/or leavestep
+ * traces. We also need to save the current stack level and the proc
+ * string in startLevel and startCmd so that we can delete this
+ * interpreter trace when it reaches the end of this proc.
+ */
+
+ if ((flags & TCL_TRACE_ENTER_EXEC) && (tcmdPtr->stepTrace == NULL)
+ && (tcmdPtr->flags & (TCL_TRACE_ENTER_DURING_EXEC |
+ TCL_TRACE_LEAVE_DURING_EXEC))) {
+ register unsigned len = strlen(command) + 1;
+
+ tcmdPtr->startLevel = level;
+ tcmdPtr->startCmd = ckalloc(len);
+ memcpy(tcmdPtr->startCmd, command, len);
+ tcmdPtr->refCount++;
+ tcmdPtr->stepTrace = Tcl_CreateObjTrace(interp, 0,
+ (tcmdPtr->flags & TCL_TRACE_ANY_EXEC) >> 2,
+ TraceExecutionProc, (ClientData)tcmdPtr,
+ CommandObjTraceDeleted);
+ }
+ }
+ if (flags & TCL_TRACE_DESTROYED) {
+ if (tcmdPtr->stepTrace != NULL) {
+ Tcl_DeleteTrace(interp, tcmdPtr->stepTrace);
+ tcmdPtr->stepTrace = NULL;
+ if (tcmdPtr->startCmd != NULL) {
+ ckfree(tcmdPtr->startCmd);
+ }
+ }
+ }
+ if (call) {
+ if ((--tcmdPtr->refCount) <= 0) {
+ ckfree((char *) tcmdPtr);
+ }
+ }
+ return traceCode;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TraceVarProc --
+ *
+ * This function is called to handle variable accesses that have been
+ * traced using the "trace" command.
+ *
+ * Results:
+ * Normally returns NULL. If the trace command returns an error, then
+ * this function returns an error string.
+ *
+ * Side effects:
+ * Depends on the command associated with the trace.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static char *
+TraceVarProc(
+ ClientData clientData, /* Information about the variable trace. */
+ Tcl_Interp *interp, /* Interpreter containing variable. */
+ const char *name1, /* Name of variable or array. */
+ const char *name2, /* Name of element within array; NULL means
+ * scalar variable is being referenced. */
+ int flags) /* OR-ed bits giving operation and other
+ * information. */
+{
+ TraceVarInfo *tvarPtr = (TraceVarInfo *) clientData;
+ char *result;
+ int code, destroy = 0;
+ Tcl_DString cmd;
+
+ /*
+ * We might call Tcl_Eval() below, and that might evaluate [trace vdelete]
+ * which might try to free tvarPtr. We want to use tvarPtr until the end
+ * of this function, so we use Tcl_Preserve() and Tcl_Release() to be sure
+ * it is not freed while we still need it.
+ */
+
+ result = NULL;
+ if ((tvarPtr->flags & flags) && !Tcl_InterpDeleted(interp)
+ && !Tcl_LimitExceeded(interp)) {
+ if (tvarPtr->length != (size_t) 0) {
+ /*
+ * Generate a command to execute by appending list elements for
+ * the two variable names and the operation.
+ */
+
+ Tcl_DStringInit(&cmd);
+ Tcl_DStringAppend(&cmd, tvarPtr->command, (int) tvarPtr->length);
+ Tcl_DStringAppendElement(&cmd, name1);
+ Tcl_DStringAppendElement(&cmd, (name2 ? name2 : ""));
+#ifndef TCL_REMOVE_OBSOLETE_TRACES
+ if (tvarPtr->flags & TCL_TRACE_OLD_STYLE) {
+ if (flags & TCL_TRACE_ARRAY) {
+ Tcl_DStringAppend(&cmd, " a", 2);
+ } else if (flags & TCL_TRACE_READS) {
+ Tcl_DStringAppend(&cmd, " r", 2);
+ } else if (flags & TCL_TRACE_WRITES) {
+ Tcl_DStringAppend(&cmd, " w", 2);
+ } else if (flags & TCL_TRACE_UNSETS) {
+ Tcl_DStringAppend(&cmd, " u", 2);
+ }
+ } else {
+#endif
+ if (flags & TCL_TRACE_ARRAY) {
+ Tcl_DStringAppend(&cmd, " array", 6);
+ } else if (flags & TCL_TRACE_READS) {
+ Tcl_DStringAppend(&cmd, " read", 5);
+ } else if (flags & TCL_TRACE_WRITES) {
+ Tcl_DStringAppend(&cmd, " write", 6);
+ } else if (flags & TCL_TRACE_UNSETS) {
+ Tcl_DStringAppend(&cmd, " unset", 6);
+ }
+#ifndef TCL_REMOVE_OBSOLETE_TRACES
+ }
+#endif
+
+ /*
+ * Execute the command. We discard any object result the command
+ * returns.
+ *
+ * Add the TCL_TRACE_DESTROYED flag to tvarPtr to indicate to
+ * other areas that this will be destroyed by us, otherwise a
+ * double-free might occur depending on what the eval does.
+ */
+
+ if ((flags & TCL_TRACE_DESTROYED)
+ && !(tvarPtr->flags & TCL_TRACE_DESTROYED)) {
+ destroy = 1;
+ tvarPtr->flags |= TCL_TRACE_DESTROYED;
+ }
+ code = Tcl_EvalEx(interp, Tcl_DStringValue(&cmd),
+ Tcl_DStringLength(&cmd), 0);
+ if (code != TCL_OK) { /* copy error msg to result */
+ Tcl_Obj *errMsgObj = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(errMsgObj);
+ result = (char *) errMsgObj;
+ }
+ Tcl_DStringFree(&cmd);
+ }
+ }
+ if (destroy && result != NULL) {
+ register Tcl_Obj *errMsgObj = (Tcl_Obj *) result;
+
+ Tcl_DecrRefCount(errMsgObj);
+ result = NULL;
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_CreateObjTrace --
+ *
+ * Arrange for a function to be called to trace command execution.
+ *
+ * Results:
+ * The return value is a token for the trace, which may be passed to
+ * Tcl_DeleteTrace to eliminate the trace.
+ *
+ * Side effects:
+ * From now on, proc will be called just before a command function is
+ * called to execute a Tcl command. Calls to proc will have the following
+ * form:
+ *
+ * void proc(ClientData clientData,
+ * Tcl_Interp * interp,
+ * int level,
+ * const char * command,
+ * Tcl_Command commandInfo,
+ * int objc,
+ * Tcl_Obj *const objv[]);
+ *
+ * The 'clientData' and 'interp' arguments to 'proc' will be the same as
+ * the arguments to Tcl_CreateObjTrace. The 'level' argument gives the
+ * nesting depth of command interpretation within the interpreter. The
+ * 'command' argument is the ASCII text of the command being evaluated -
+ * before any substitutions are performed. The 'commandInfo' argument
+ * gives a handle to the command procedure that will be evaluated. The
+ * 'objc' and 'objv' parameters give the parameter vector that will be
+ * passed to the command procedure. Proc does not return a value.
+ *
+ * It is permissible for 'proc' to call Tcl_SetCommandTokenInfo to change
+ * the command procedure or client data for the command being evaluated,
+ * and these changes will take effect with the current evaluation.
+ *
+ * The 'level' argument specifies the maximum nesting level of calls to
+ * be traced. If the execution depth of the interpreter exceeds 'level',
+ * the trace callback is not executed.
+ *
+ * The 'flags' argument is either zero or the value,
+ * TCL_ALLOW_INLINE_COMPILATION. If the TCL_ALLOW_INLINE_COMPILATION flag
+ * is not present, the bytecode compiler will not generate inline code
+ * for Tcl's built-in commands. This behavior will have a significant
+ * impact on performance, but will ensure that all command evaluations
+ * are traced. If the TCL_ALLOW_INLINE_COMPILATION flag is present, the
+ * bytecode compiler will have its normal behavior of compiling in-line
+ * code for some of Tcl's built-in commands. In this case, the tracing
+ * will be imprecise - in-line code will not be traced - but run-time
+ * performance will be improved. The latter behavior is desired for many
+ * applications such as profiling of run time.
+ *
+ * When the trace is deleted, the 'delProc' function will be invoked,
+ * passing it the original client data.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Trace
+Tcl_CreateObjTrace(
+ Tcl_Interp *interp, /* Tcl interpreter */
+ int level, /* Maximum nesting level */
+ int flags, /* Flags, see above */
+ Tcl_CmdObjTraceProc *proc, /* Trace callback */
+ ClientData clientData, /* Client data for the callback */
+ Tcl_CmdObjTraceDeleteProc *delProc)
+ /* Function to call when trace is deleted */
+{
+ register Trace *tracePtr;
+ register Interp *iPtr = (Interp *) interp;
+
+ /*
+ * Test if this trace allows inline compilation of commands.
+ */
+
+ if (!(flags & TCL_ALLOW_INLINE_COMPILATION)) {
+ if (iPtr->tracesForbiddingInline == 0) {
+ /*
+ * When the first trace forbidding inline compilation is created,
+ * invalidate existing compiled code for this interpreter and
+ * arrange (by setting the DONT_COMPILE_CMDS_INLINE flag) that
+ * when compiling new code, no commands will be compiled inline
+ * (i.e., into an inline sequence of instructions). We do this
+ * because commands that were compiled inline will never result in
+ * a command trace being called.
+ */
+
+ iPtr->compileEpoch++;
+ iPtr->flags |= DONT_COMPILE_CMDS_INLINE;
+ }
+ iPtr->tracesForbiddingInline++;
+ }
+
+ tracePtr = (Trace *) ckalloc(sizeof(Trace));
+ tracePtr->level = level;
+ tracePtr->proc = proc;
+ tracePtr->clientData = clientData;
+ tracePtr->delProc = delProc;
+ tracePtr->nextPtr = iPtr->tracePtr;
+ tracePtr->flags = flags;
+ iPtr->tracePtr = tracePtr;
+
+ return (Tcl_Trace) tracePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_CreateTrace --
+ *
+ * Arrange for a function to be called to trace command execution.
+ *
+ * Results:
+ * The return value is a token for the trace, which may be passed to
+ * Tcl_DeleteTrace to eliminate the trace.
+ *
+ * Side effects:
+ * From now on, proc will be called just before a command procedure is
+ * called to execute a Tcl command. Calls to proc will have the following
+ * form:
+ *
+ * void
+ * proc(clientData, interp, level, command, cmdProc, cmdClientData,
+ * argc, argv)
+ * ClientData clientData;
+ * Tcl_Interp *interp;
+ * int level;
+ * char *command;
+ * int (*cmdProc)();
+ * ClientData cmdClientData;
+ * int argc;
+ * char **argv;
+ * {
+ * }
+ *
+ * The clientData and interp arguments to proc will be the same as the
+ * corresponding arguments to this function. Level gives the nesting
+ * level of command interpretation for this interpreter (0 corresponds to
+ * top level). Command gives the ASCII text of the raw command, cmdProc
+ * and cmdClientData give the function that will be called to process the
+ * command and the ClientData value it will receive, and argc and argv
+ * give the arguments to the command, after any argument parsing and
+ * substitution. Proc does not return a value.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Trace
+Tcl_CreateTrace(
+ Tcl_Interp *interp, /* Interpreter in which to create trace. */
+ int level, /* Only call proc for commands at nesting
+ * level<=argument level (1=>top level). */
+ Tcl_CmdTraceProc *proc, /* Function to call before executing each
+ * command. */
+ ClientData clientData) /* Arbitrary value word to pass to proc. */
+{
+ StringTraceData *data = (StringTraceData *)
+ ckalloc(sizeof(StringTraceData));
+
+ data->clientData = clientData;
+ data->proc = proc;
+ return Tcl_CreateObjTrace(interp, level, 0, StringTraceProc,
+ (ClientData) data, StringTraceDeleteProc);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringTraceProc --
+ *
+ * Invoke a string-based trace function from an object-based callback.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Whatever the string-based trace function does.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+StringTraceProc(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int level,
+ const char *command,
+ Tcl_Command commandInfo,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ StringTraceData *data = (StringTraceData *) clientData;
+ Command *cmdPtr = (Command *) commandInfo;
+ const char **argv; /* Args to pass to string trace proc */
+ int i;
+
+ /*
+ * This is a bit messy because we have to emulate the old trace interface,
+ * which uses strings for everything.
+ */
+
+ argv = (const char **) TclStackAlloc(interp,
+ (unsigned) ((objc + 1) * sizeof(const char *)));
+ for (i = 0; i < objc; i++) {
+ argv[i] = Tcl_GetString(objv[i]);
+ }
+ argv[objc] = 0;
+
+ /*
+ * Invoke the command function. Note that we cast away const-ness on two
+ * parameters for compatibility with legacy code; the code MUST NOT modify
+ * either command or argv.
+ */
+
+ (data->proc)(data->clientData, interp, level, (char *) command,
+ cmdPtr->proc, cmdPtr->clientData, objc, argv);
+ TclStackFree(interp, (void *) argv);
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StringTraceDeleteProc --
+ *
+ * Clean up memory when a string-based trace is deleted.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Allocated memory is returned to the system.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+StringTraceDeleteProc(
+ ClientData clientData)
+{
+ ckfree((char *) clientData);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DeleteTrace --
+ *
+ * Remove a trace.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * From now on there will be no more calls to the function given in
+ * trace.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DeleteTrace(
+ Tcl_Interp *interp, /* Interpreter that contains trace. */
+ Tcl_Trace trace) /* Token for trace (returned previously by
+ * Tcl_CreateTrace). */
+{
+ Interp *iPtr = (Interp *) interp;
+ Trace *prevPtr, *tracePtr = (Trace *) trace;
+ register Trace **tracePtr2 = &(iPtr->tracePtr);
+ ActiveInterpTrace *activePtr;
+
+ /*
+ * Locate the trace entry in the interpreter's trace list, and remove it
+ * from the list.
+ */
+
+ prevPtr = NULL;
+ while ((*tracePtr2) != NULL && (*tracePtr2) != tracePtr) {
+ prevPtr = *tracePtr2;
+ tracePtr2 = &((*tracePtr2)->nextPtr);
+ }
+ if (*tracePtr2 == NULL) {
+ return;
+ }
+ (*tracePtr2) = (*tracePtr2)->nextPtr;
+
+ /*
+ * The code below makes it possible to delete traces while traces are
+ * active: it makes sure that the deleted trace won't be processed by
+ * TclCheckInterpTraces.
+ */
+
+ for (activePtr = iPtr->activeInterpTracePtr; activePtr != NULL;
+ activePtr = activePtr->nextPtr) {
+ if (activePtr->nextTracePtr == tracePtr) {
+ if (activePtr->reverseScan) {
+ activePtr->nextTracePtr = prevPtr;
+ } else {
+ activePtr->nextTracePtr = tracePtr->nextPtr;
+ }
+ }
+ }
+
+ /*
+ * If the trace forbids bytecode compilation, change the interpreter's
+ * state. If bytecode compilation is now permitted, flag the fact and
+ * advance the compilation epoch so that procs will be recompiled to take
+ * advantage of it.
+ */
+
+ if (!(tracePtr->flags & TCL_ALLOW_INLINE_COMPILATION)) {
+ iPtr->tracesForbiddingInline--;
+ if (iPtr->tracesForbiddingInline == 0) {
+ iPtr->flags &= ~DONT_COMPILE_CMDS_INLINE;
+ iPtr->compileEpoch++;
+ }
+ }
+
+ /*
+ * Execute any delete callback.
+ */
+
+ if (tracePtr->delProc != NULL) {
+ (tracePtr->delProc)(tracePtr->clientData);
+ }
+
+ /*
+ * Delete the trace object.
+ */
+
+ Tcl_EventuallyFree((char *) tracePtr, TCL_DYNAMIC);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclTraceVarExists --
+ *
+ * This is called from info exists. We need to trigger read and/or array
+ * traces because they may end up creating a variable that doesn't
+ * currently exist.
+ *
+ * Results:
+ * A pointer to the Var structure, or NULL.
+ *
+ * Side effects:
+ * May fill in error messages in the interp.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Var *
+TclVarTraceExists(
+ Tcl_Interp *interp, /* The interpreter */
+ const char *varName) /* The variable name */
+{
+ Var *varPtr;
+ Var *arrayPtr;
+
+ /*
+ * The choice of "create" flag values is delicate here, and matches the
+ * semantics of GetVar. Things are still not perfect, however, because if
+ * you do "info exists x" you get a varPtr and therefore trigger traces.
+ * However, if you do "info exists x(i)", then you only get a varPtr if x
+ * is already known to be an array. Otherwise you get NULL, and no trace
+ * is triggered. This matches Tcl 7.6 semantics.
+ */
+
+ varPtr = TclLookupVar(interp, varName, NULL, 0, "access",
+ /*createPart1*/ 0, /*createPart2*/ 1, &arrayPtr);
+
+ if (varPtr == NULL) {
+ return NULL;
+ }
+
+ if ((varPtr->flags & VAR_TRACED_READ)
+ || (arrayPtr && (arrayPtr->flags & VAR_TRACED_READ))) {
+ TclCallVarTraces((Interp *)interp, arrayPtr, varPtr, varName, NULL,
+ TCL_TRACE_READS, /* leaveErrMsg */ 0);
+ }
+
+ /*
+ * If the variable doesn't exist anymore and no-one's using it, then free
+ * up the relevant structures and hash table entries.
+ */
+
+ if (TclIsVarUndefined(varPtr)) {
+ TclCleanupVar(varPtr, arrayPtr);
+ return NULL;
+ }
+
+ return varPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCallVarTraces --
+ *
+ * This function is invoked to find and invoke relevant trace functions
+ * associated with a particular operation on a variable. This function
+ * invokes traces both on the variable and on its containing array (where
+ * relevant).
+ *
+ * Results:
+ * Returns TCL_OK to indicate normal operation. Returns TCL_ERROR if
+ * invocation of a trace function indicated an error. When TCL_ERROR is
+ * returned and leaveErrMsg is true, then the errorInfo field of iPtr has
+ * information about the error placed in it.
+ *
+ * Side effects:
+ * Almost anything can happen, depending on trace; this function itself
+ * doesn't have any side effects.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclObjCallVarTraces(
+ Interp *iPtr, /* Interpreter containing variable. */
+ register Var *arrayPtr, /* Pointer to array variable that contains the
+ * variable, or NULL if the variable isn't an
+ * element of an array. */
+ Var *varPtr, /* Variable whose traces are to be invoked. */
+ Tcl_Obj *part1Ptr,
+ Tcl_Obj *part2Ptr, /* Variable's two-part name. */
+ int flags, /* Flags passed to trace functions: indicates
+ * what's happening to variable, plus maybe
+ * TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY */
+ int leaveErrMsg, /* If true, and one of the traces indicates an
+ * error, then leave an error message and
+ * stack trace information in *iPTr. */
+ int index) /* Index into the local variable table of the
+ * variable, or -1. Only used when part1Ptr is
+ * NULL. */
+{
+ char *part1, *part2;
+
+ if (!part1Ptr) {
+ part1Ptr = localName(iPtr->varFramePtr, index);
+ }
+ part1 = TclGetString(part1Ptr);
+ part2 = part2Ptr? TclGetString(part2Ptr) : NULL;
+
+ return TclCallVarTraces(iPtr, arrayPtr, varPtr, part1, part2, flags,
+ leaveErrMsg);
+}
+
+int
+TclCallVarTraces(
+ Interp *iPtr, /* Interpreter containing variable. */
+ register Var *arrayPtr, /* Pointer to array variable that contains the
+ * variable, or NULL if the variable isn't an
+ * element of an array. */
+ Var *varPtr, /* Variable whose traces are to be invoked. */
+ const char *part1,
+ const char *part2, /* Variable's two-part name. */
+ int flags, /* Flags passed to trace functions: indicates
+ * what's happening to variable, plus maybe
+ * TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY */
+ int leaveErrMsg) /* If true, and one of the traces indicates an
+ * error, then leave an error message and
+ * stack trace information in *iPTr. */
+{
+ register VarTrace *tracePtr;
+ ActiveVarTrace active;
+ char *result;
+ const char *openParen, *p;
+ Tcl_DString nameCopy;
+ int copiedName;
+ int code = TCL_OK;
+ int disposeFlags = 0;
+ Tcl_InterpState state = NULL;
+ Tcl_HashEntry *hPtr;
+ int traceflags = flags & VAR_ALL_TRACES;
+
+ /*
+ * If there are already similar trace functions active for the variable,
+ * don't call them again.
+ */
+
+ if (TclIsVarTraceActive(varPtr)) {
+ return code;
+ }
+ TclSetVarTraceActive(varPtr);
+ if (TclIsVarInHash(varPtr)) {
+ VarHashRefCount(varPtr)++;
+ }
+ if (arrayPtr && TclIsVarInHash(arrayPtr)) {
+ VarHashRefCount(arrayPtr)++;
+ }
+
+ /*
+ * If the variable name hasn't been parsed into array name and element, do
+ * it here. If there really is an array element, make a copy of the
+ * original name so that NULLs can be inserted into it to separate the
+ * names (can't modify the name string in place, because the string might
+ * get used by the callbacks we invoke).
+ */
+
+ copiedName = 0;
+ if (part2 == NULL) {
+ for (p = part1; *p ; p++) {
+ if (*p == '(') {
+ openParen = p;
+ do {
+ p++;
+ } while (*p != '\0');
+ p--;
+ if (*p == ')') {
+ int offset = (openParen - part1);
+ char *newPart1;
+
+ Tcl_DStringInit(&nameCopy);
+ Tcl_DStringAppend(&nameCopy, part1, (p-part1));
+ newPart1 = Tcl_DStringValue(&nameCopy);
+ newPart1[offset] = 0;
+ part1 = newPart1;
+ part2 = newPart1 + offset + 1;
+ copiedName = 1;
+ }
+ break;
+ }
+ }
+ }
+
+ /*
+ * Ignore any caller-provided TCL_INTERP_DESTROYED flag. Only we can
+ * set it correctly.
+ */
+
+ flags &= ~TCL_INTERP_DESTROYED;
+
+ /*
+ * Invoke traces on the array containing the variable, if relevant.
+ */
+
+ result = NULL;
+ active.nextPtr = iPtr->activeVarTracePtr;
+ iPtr->activeVarTracePtr = &active;
+ Tcl_Preserve((ClientData) iPtr);
+ if (arrayPtr && !TclIsVarTraceActive(arrayPtr)
+ && (arrayPtr->flags & traceflags)) {
+ hPtr = Tcl_FindHashEntry(&iPtr->varTraces, (char *) arrayPtr);
+ active.varPtr = arrayPtr;
+ for (tracePtr = (VarTrace *) Tcl_GetHashValue(hPtr);
+ tracePtr != NULL; tracePtr = active.nextTracePtr) {
+ active.nextTracePtr = tracePtr->nextPtr;
+ if (!(tracePtr->flags & flags)) {
+ continue;
+ }
+ Tcl_Preserve((ClientData) tracePtr);
+ if (state == NULL) {
+ state = Tcl_SaveInterpState((Tcl_Interp *)iPtr, code);
+ }
+ if (Tcl_InterpDeleted((Tcl_Interp *)iPtr)) {
+ flags |= TCL_INTERP_DESTROYED;
+ }
+ result = (*tracePtr->traceProc)(tracePtr->clientData,
+ (Tcl_Interp *) iPtr, part1, part2, flags);
+ if (result != NULL) {
+ if (flags & TCL_TRACE_UNSETS) {
+ /*
+ * Ignore errors in unset traces.
+ */
+
+ DisposeTraceResult(tracePtr->flags, result);
+ } else {
+ disposeFlags = tracePtr->flags;
+ code = TCL_ERROR;
+ }
+ }
+ Tcl_Release((ClientData) tracePtr);
+ if (code == TCL_ERROR) {
+ goto done;
+ }
+ }
+ }
+
+ /*
+ * Invoke traces on the variable itself.
+ */
+
+ if (flags & TCL_TRACE_UNSETS) {
+ flags |= TCL_TRACE_DESTROYED;
+ }
+ active.varPtr = varPtr;
+ if (varPtr->flags & traceflags) {
+ hPtr = Tcl_FindHashEntry(&iPtr->varTraces, (char *) varPtr);
+ for (tracePtr = (VarTrace *) Tcl_GetHashValue(hPtr);
+ tracePtr != NULL; tracePtr = active.nextTracePtr) {
+ active.nextTracePtr = tracePtr->nextPtr;
+ if (!(tracePtr->flags & flags)) {
+ continue;
+ }
+ Tcl_Preserve((ClientData) tracePtr);
+ if (state == NULL) {
+ state = Tcl_SaveInterpState((Tcl_Interp *)iPtr, code);
+ }
+ if (Tcl_InterpDeleted((Tcl_Interp *)iPtr)) {
+ flags |= TCL_INTERP_DESTROYED;
+ }
+ result = (*tracePtr->traceProc)(tracePtr->clientData,
+ (Tcl_Interp *) iPtr, part1, part2, flags);
+ if (result != NULL) {
+ if (flags & TCL_TRACE_UNSETS) {
+ /*
+ * Ignore errors in unset traces.
+ */
+
+ DisposeTraceResult(tracePtr->flags, result);
+ } else {
+ disposeFlags = tracePtr->flags;
+ code = TCL_ERROR;
+ }
+ }
+ Tcl_Release((ClientData) tracePtr);
+ if (code == TCL_ERROR) {
+ goto done;
+ }
+ }
+ }
+
+ /*
+ * Restore the variable's flags, remove the record of our active traces,
+ * and then return.
+ */
+
+ done:
+ if (code == TCL_ERROR) {
+ if (leaveErrMsg) {
+ const char *verb = "";
+ const char *type = "";
+
+ switch (flags&(TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_ARRAY)) {
+ case TCL_TRACE_READS:
+ verb = "read";
+ type = verb;
+ break;
+ case TCL_TRACE_WRITES:
+ verb = "set";
+ type = "write";
+ break;
+ case TCL_TRACE_ARRAY:
+ verb = "trace array";
+ type = "array";
+ break;
+ }
+
+ if (disposeFlags & TCL_TRACE_RESULT_OBJECT) {
+ Tcl_SetObjResult((Tcl_Interp *)iPtr, (Tcl_Obj *) result);
+ } else {
+ Tcl_SetResult((Tcl_Interp *)iPtr, result, TCL_STATIC);
+ }
+ Tcl_AddErrorInfo((Tcl_Interp *)iPtr, "");
+
+ Tcl_AppendObjToErrorInfo((Tcl_Interp *)iPtr, Tcl_ObjPrintf(
+ "\n (%s trace on \"%s%s%s%s\")", type, part1,
+ (part2 ? "(" : ""), (part2 ? part2 : ""),
+ (part2 ? ")" : "") ));
+ if (disposeFlags & TCL_TRACE_RESULT_OBJECT) {
+ TclVarErrMsg((Tcl_Interp *) iPtr, part1, part2, verb,
+ Tcl_GetString((Tcl_Obj *) result));
+ } else {
+ TclVarErrMsg((Tcl_Interp *) iPtr, part1, part2, verb, result);
+ }
+ iPtr->flags &= ~(ERR_ALREADY_LOGGED);
+ Tcl_DiscardInterpState(state);
+ } else {
+ (void) Tcl_RestoreInterpState((Tcl_Interp *)iPtr, state);
+ }
+ DisposeTraceResult(disposeFlags,result);
+ } else if (state) {
+ if (code == TCL_OK) {
+ code = Tcl_RestoreInterpState((Tcl_Interp *)iPtr, state);
+ } else {
+ Tcl_DiscardInterpState(state);
+ }
+ }
+
+ if (arrayPtr && TclIsVarInHash(arrayPtr)) {
+ VarHashRefCount(arrayPtr)--;
+ }
+ if (copiedName) {
+ Tcl_DStringFree(&nameCopy);
+ }
+ TclClearVarTraceActive(varPtr);
+ if (TclIsVarInHash(varPtr)) {
+ VarHashRefCount(varPtr)--;
+ }
+ iPtr->activeVarTracePtr = active.nextPtr;
+ Tcl_Release((ClientData) iPtr);
+ return code;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DisposeTraceResult--
+ *
+ * This function is called to dispose of the result returned from a trace
+ * function. The disposal method appropriate to the type of result is
+ * determined by flags.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The memory allocated for the trace result may be freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DisposeTraceResult(
+ int flags, /* Indicates type of result to determine
+ * proper disposal method. */
+ char *result) /* The result returned from a trace function
+ * to be disposed. */
+{
+ if (flags & TCL_TRACE_RESULT_DYNAMIC) {
+ ckfree(result);
+ } else if (flags & TCL_TRACE_RESULT_OBJECT) {
+ Tcl_DecrRefCount((Tcl_Obj *) result);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_UntraceVar --
+ *
+ * Remove a previously-created trace for a variable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If there exists a trace for the variable given by varName with the
+ * given flags, proc, and clientData, then that trace is removed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_UntraceVar(
+ Tcl_Interp *interp, /* Interpreter containing variable. */
+ const char *varName, /* Name of variable; may end with "(index)" to
+ * signify an array reference. */
+ int flags, /* OR-ed collection of bits describing current
+ * trace, including any of TCL_TRACE_READS,
+ * TCL_TRACE_WRITES, TCL_TRACE_UNSETS,
+ * TCL_GLOBAL_ONLY and TCL_NAMESPACE_ONLY. */
+ Tcl_VarTraceProc *proc, /* Function assocated with trace. */
+ ClientData clientData) /* Arbitrary argument to pass to proc. */
+{
+ Tcl_UntraceVar2(interp, varName, NULL, flags, proc, clientData);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_UntraceVar2 --
+ *
+ * Remove a previously-created trace for a variable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If there exists a trace for the variable given by part1 and part2 with
+ * the given flags, proc, and clientData, then that trace is removed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_UntraceVar2(
+ Tcl_Interp *interp, /* Interpreter containing variable. */
+ const char *part1, /* Name of variable or array. */
+ const char *part2, /* Name of element within array; NULL means
+ * trace applies to scalar variable or array
+ * as-a-whole. */
+ int flags, /* OR-ed collection of bits describing current
+ * trace, including any of TCL_TRACE_READS,
+ * TCL_TRACE_WRITES, TCL_TRACE_UNSETS,
+ * TCL_GLOBAL_ONLY, and TCL_NAMESPACE_ONLY. */
+ Tcl_VarTraceProc *proc, /* Function assocated with trace. */
+ ClientData clientData) /* Arbitrary argument to pass to proc. */
+{
+ register VarTrace *tracePtr;
+ VarTrace *prevPtr, *nextPtr;
+ Var *varPtr, *arrayPtr;
+ Interp *iPtr = (Interp *) interp;
+ ActiveVarTrace *activePtr;
+ int flagMask, allFlags = 0;
+ Tcl_HashEntry *hPtr;
+
+ /*
+ * Set up a mask to mask out the parts of the flags that we are not
+ * interested in now.
+ */
+
+ flagMask = TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY;
+ varPtr = TclLookupVar(interp, part1, part2, flags & flagMask, /*msg*/ NULL,
+ /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
+ if (varPtr == NULL || !(varPtr->flags & VAR_ALL_TRACES & flags)) {
+ return;
+ }
+
+ /*
+ * Set up a mask to mask out the parts of the flags that we are not
+ * interested in now.
+ */
+
+ flagMask = TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS |
+ TCL_TRACE_ARRAY | TCL_TRACE_RESULT_DYNAMIC | TCL_TRACE_RESULT_OBJECT;
+#ifndef TCL_REMOVE_OBSOLETE_TRACES
+ flagMask |= TCL_TRACE_OLD_STYLE;
+#endif
+ flags &= flagMask;
+
+ hPtr = Tcl_FindHashEntry(&iPtr->varTraces,
+ (char *) varPtr);
+ for (tracePtr = (VarTrace *) Tcl_GetHashValue(hPtr), prevPtr = NULL; ;
+ prevPtr = tracePtr, tracePtr = tracePtr->nextPtr) {
+ if (tracePtr == NULL) {
+ goto updateFlags;
+ }
+ if ((tracePtr->traceProc == proc) && (tracePtr->flags == flags)
+ && (tracePtr->clientData == clientData)) {
+ break;
+ }
+ allFlags |= tracePtr->flags;
+ }
+
+ /*
+ * The code below makes it possible to delete traces while traces are
+ * active: it makes sure that the deleted trace won't be processed by
+ * TclCallVarTraces.
+ *
+ * Caveat (Bug 3062331): When an unset trace handler on a variable
+ * tries to delete a different unset trace handler on the same variable,
+ * the results may be surprising. When variable unset traces fire, the
+ * traced variable is already gone. So the TclLookupVar() call above
+ * will not find that variable, and not finding it will never reach here
+ * to perform the deletion. This means callers of Tcl_UntraceVar*()
+ * attempting to delete unset traces from within the handler of another
+ * unset trace have to account for the possibility that their call to
+ * Tcl_UntraceVar*() is a no-op.
+ */
+
+ for (activePtr = iPtr->activeVarTracePtr; activePtr != NULL;
+ activePtr = activePtr->nextPtr) {
+ if (activePtr->nextTracePtr == tracePtr) {
+ activePtr->nextTracePtr = tracePtr->nextPtr;
+ }
+ }
+ nextPtr = tracePtr->nextPtr;
+ if (prevPtr == NULL) {
+ if (nextPtr) {
+ Tcl_SetHashValue(hPtr, nextPtr);
+ } else {
+ Tcl_DeleteHashEntry(hPtr);
+ }
+ } else {
+ prevPtr->nextPtr = nextPtr;
+ }
+ tracePtr->nextPtr = NULL;
+ Tcl_EventuallyFree((ClientData) tracePtr, TCL_DYNAMIC);
+
+ for (tracePtr = nextPtr; tracePtr != NULL;
+ tracePtr = tracePtr->nextPtr) {
+ allFlags |= tracePtr->flags;
+ }
+
+ updateFlags:
+ varPtr->flags &= ~VAR_ALL_TRACES;
+ if (allFlags & VAR_ALL_TRACES) {
+ varPtr->flags |= (allFlags & VAR_ALL_TRACES);
+ } else if (TclIsVarUndefined(varPtr)) {
+ /*
+ * If this is the last trace on the variable, and the variable is
+ * unset and unused, then free up the variable.
+ */
+
+ TclCleanupVar(varPtr, NULL);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_VarTraceInfo --
+ *
+ * Return the clientData value associated with a trace on a variable.
+ * This function can also be used to step through all of the traces on a
+ * particular variable that have the same trace function.
+ *
+ * Results:
+ * The return value is the clientData value associated with a trace on
+ * the given variable. Information will only be returned for a trace with
+ * proc as trace function. If the clientData argument is NULL then the
+ * first such trace is returned; otherwise, the next relevant one after
+ * the one given by clientData will be returned. If the variable doesn't
+ * exist, or if there are no (more) traces for it, then NULL is returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ClientData
+Tcl_VarTraceInfo(
+ Tcl_Interp *interp, /* Interpreter containing variable. */
+ const char *varName, /* Name of variable; may end with "(index)" to
+ * signify an array reference. */
+ int flags, /* OR-ed combo or TCL_GLOBAL_ONLY,
+ * TCL_NAMESPACE_ONLY (can be 0). */
+ Tcl_VarTraceProc *proc, /* Function assocated with trace. */
+ ClientData prevClientData) /* If non-NULL, gives last value returned by
+ * this function, so this call will return the
+ * next trace after that one. If NULL, this
+ * call will return the first trace. */
+{
+ return Tcl_VarTraceInfo2(interp, varName, NULL, flags, proc,
+ prevClientData);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_VarTraceInfo2 --
+ *
+ * Same as Tcl_VarTraceInfo, except takes name in two pieces instead of
+ * one.
+ *
+ * Results:
+ * Same as Tcl_VarTraceInfo.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ClientData
+Tcl_VarTraceInfo2(
+ Tcl_Interp *interp, /* Interpreter containing variable. */
+ const char *part1, /* Name of variable or array. */
+ const char *part2, /* Name of element within array; NULL means
+ * trace applies to scalar variable or array
+ * as-a-whole. */
+ int flags, /* OR-ed combination of TCL_GLOBAL_ONLY,
+ * TCL_NAMESPACE_ONLY. */
+ Tcl_VarTraceProc *proc, /* Function assocated with trace. */
+ ClientData prevClientData) /* If non-NULL, gives last value returned by
+ * this function, so this call will return the
+ * next trace after that one. If NULL, this
+ * call will return the first trace. */
+{
+ Interp *iPtr = (Interp *) interp;
+ register VarTrace *tracePtr;
+ Var *varPtr, *arrayPtr;
+ Tcl_HashEntry *hPtr;
+
+ varPtr = TclLookupVar(interp, part1, part2,
+ flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY), /*msg*/ NULL,
+ /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
+ if (varPtr == NULL) {
+ return NULL;
+ }
+
+ /*
+ * Find the relevant trace, if any, and return its clientData.
+ */
+
+ hPtr = Tcl_FindHashEntry(&iPtr->varTraces,
+ (char *) varPtr);
+
+ if (hPtr) {
+ tracePtr = Tcl_GetHashValue(hPtr);
+
+ if (prevClientData != NULL) {
+ for ( ; tracePtr != NULL; tracePtr = tracePtr->nextPtr) {
+ if ((tracePtr->clientData == prevClientData)
+ && (tracePtr->traceProc == proc)) {
+ tracePtr = tracePtr->nextPtr;
+ break;
+ }
+ }
+ }
+ for (; tracePtr!=NULL ; tracePtr=tracePtr->nextPtr) {
+ if (tracePtr->traceProc == proc) {
+ return tracePtr->clientData;
+ }
+ }
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_TraceVar --
+ *
+ * Arrange for reads and/or writes to a variable to cause a function to
+ * be invoked, which can monitor the operations and/or change their
+ * actions.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * A trace is set up on the variable given by varName, such that future
+ * references to the variable will be intermediated by proc. See the
+ * manual entry for complete details on the calling sequence for proc.
+ * The variable's flags are updated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_TraceVar(
+ Tcl_Interp *interp, /* Interpreter in which variable is to be
+ * traced. */
+ const char *varName, /* Name of variable; may end with "(index)" to
+ * signify an array reference. */
+ int flags, /* OR-ed collection of bits, including any of
+ * TCL_TRACE_READS, TCL_TRACE_WRITES,
+ * TCL_TRACE_UNSETS, TCL_GLOBAL_ONLY, and
+ * TCL_NAMESPACE_ONLY. */
+ Tcl_VarTraceProc *proc, /* Function to call when specified ops are
+ * invoked upon varName. */
+ ClientData clientData) /* Arbitrary argument to pass to proc. */
+{
+ return Tcl_TraceVar2(interp, varName, NULL, flags, proc, clientData);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_TraceVar2 --
+ *
+ * Arrange for reads and/or writes to a variable to cause a function to
+ * be invoked, which can monitor the operations and/or change their
+ * actions.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * A trace is set up on the variable given by part1 and part2, such that
+ * future references to the variable will be intermediated by proc. See
+ * the manual entry for complete details on the calling sequence for
+ * proc. The variable's flags are updated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_TraceVar2(
+ Tcl_Interp *interp, /* Interpreter in which variable is to be
+ * traced. */
+ const char *part1, /* Name of scalar variable or array. */
+ const char *part2, /* Name of element within array; NULL means
+ * trace applies to scalar variable or array
+ * as-a-whole. */
+ int flags, /* OR-ed collection of bits, including any of
+ * TCL_TRACE_READS, TCL_TRACE_WRITES,
+ * TCL_TRACE_UNSETS, TCL_GLOBAL_ONLY, and
+ * TCL_NAMESPACE_ONLY. */
+ Tcl_VarTraceProc *proc, /* Function to call when specified ops are
+ * invoked upon varName. */
+ ClientData clientData) /* Arbitrary argument to pass to proc. */
+{
+ register VarTrace *tracePtr;
+ int result;
+
+ tracePtr = (VarTrace *) ckalloc(sizeof(VarTrace));
+ tracePtr->traceProc = proc;
+ tracePtr->clientData = clientData;
+ tracePtr->flags = flags;
+
+ result = TraceVarEx(interp, part1, part2, tracePtr);
+
+ if (result != TCL_OK) {
+ ckfree((char *) tracePtr);
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TraceVarEx --
+ *
+ * Arrange for reads and/or writes to a variable to cause a function to
+ * be invoked, which can monitor the operations and/or change their
+ * actions.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * A trace is set up on the variable given by part1 and part2, such that
+ * future references to the variable will be intermediated by the
+ * traceProc listed in tracePtr. See the manual entry for complete
+ * details on the calling sequence for proc.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TraceVarEx(
+ Tcl_Interp *interp, /* Interpreter in which variable is to be
+ * traced. */
+ const char *part1, /* Name of scalar variable or array. */
+ const char *part2, /* Name of element within array; NULL means
+ * trace applies to scalar variable or array
+ * as-a-whole. */
+ register VarTrace *tracePtr)/* Structure containing flags, traceProc and
+ * clientData fields. Others should be left
+ * blank. Will be ckfree()d (eventually) if
+ * this function returns TCL_OK, and up to
+ * caller to free if this function returns
+ * TCL_ERROR. */
+{
+ Interp *iPtr = (Interp *) interp;
+ Var *varPtr, *arrayPtr;
+ int flagMask, isNew;
+ Tcl_HashEntry *hPtr;
+
+ /*
+ * We strip 'flags' down to just the parts which are relevant to
+ * TclLookupVar, to avoid conflicts between trace flags and internal
+ * namespace flags such as 'TCL_FIND_ONLY_NS'. This can now occur since we
+ * have trace flags with values 0x1000 and higher.
+ */
+
+ flagMask = TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY;
+ varPtr = TclLookupVar(interp, part1, part2,
+ (tracePtr->flags & flagMask) | TCL_LEAVE_ERR_MSG,
+ "trace", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
+ if (varPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Check for a nonsense flag combination. Note that this is a Tcl_Panic()
+ * because there should be no code path that ever sets both flags.
+ */
+
+ if ((tracePtr->flags&TCL_TRACE_RESULT_DYNAMIC)
+ && (tracePtr->flags&TCL_TRACE_RESULT_OBJECT)) {
+ Tcl_Panic("bad result flag combination");
+ }
+
+ /*
+ * Set up trace information.
+ */
+
+ flagMask = TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS |
+ TCL_TRACE_ARRAY | TCL_TRACE_RESULT_DYNAMIC | TCL_TRACE_RESULT_OBJECT;
+#ifndef TCL_REMOVE_OBSOLETE_TRACES
+ flagMask |= TCL_TRACE_OLD_STYLE;
+#endif
+ tracePtr->flags = tracePtr->flags & flagMask;
+
+ hPtr = Tcl_CreateHashEntry(&iPtr->varTraces, (char *) varPtr, &isNew);
+ if (isNew) {
+ tracePtr->nextPtr = NULL;
+ } else {
+ tracePtr->nextPtr = (VarTrace *) Tcl_GetHashValue(hPtr);
+ }
+ Tcl_SetHashValue(hPtr, (char *) tracePtr);
+
+ /*
+ * Mark the variable as traced so we know to call them.
+ */
+
+ varPtr->flags |= (tracePtr->flags & VAR_ALL_TRACES);
+
+ return TCL_OK;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclUniData.c b/generic/tclUniData.c
index 50f8587..83b3058 100644
--- a/generic/tclUniData.c
+++ b/generic/tclUniData.c
@@ -23,7 +23,7 @@
* to the same alternate page number.
*/
-static CONST unsigned short pageMap[] = {
+static const unsigned short pageMap[] = {
0, 1, 2, 3, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7, 15, 16, 17,
18, 19, 20, 21, 22, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 7, 32,
7, 33, 7, 7, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 42, 42, 45,
@@ -160,7 +160,7 @@ static CONST unsigned short pageMap[] = {
* set of character attributes.
*/
-static CONST unsigned char groupMap[] = {
+static const unsigned char groupMap[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 4, 3, 3, 3, 5, 6, 3, 7, 3, 8,
3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 7, 7, 7, 3, 3, 10, 10, 10,
@@ -745,7 +745,7 @@ static CONST unsigned char groupMap[] = {
* highest field so we can easily sign extend.
*/
-static CONST int groups[] = {
+static const int groups[] = {
0, 15, 12, 25, 27, 21, 22, 26, 20, 9, 134217793, 28, 19, 134217858,
29, 2, 23, 16, 11, 1178599554, 24, -507510654, 4194369, 4194434,
-834666431, 973078658, -507510719, 1258291330, -817889150, 880803905,
diff --git a/generic/tclUtf.c b/generic/tclUtf.c
index a6decd9..00b652e 100644
--- a/generic/tclUtf.c
+++ b/generic/tclUtf.c
@@ -5,8 +5,8 @@
*
* Copyright (c) 1997-1998 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
@@ -18,46 +18,46 @@
#include "tclUniData.c"
/*
- * The following macros are used for fast character category tests. The
- * x_BITS values are shifted right by the category value to determine whether
- * the given category is included in the set.
- */
+ * The following macros are used for fast character category tests. The x_BITS
+ * values are shifted right by the category value to determine whether the
+ * given category is included in the set.
+ */
#define ALPHA_BITS ((1 << UPPERCASE_LETTER) | (1 << LOWERCASE_LETTER) \
- | (1 << TITLECASE_LETTER) | (1 << MODIFIER_LETTER) | (1 << OTHER_LETTER))
+ | (1 << TITLECASE_LETTER) | (1 << MODIFIER_LETTER) | (1<<OTHER_LETTER))
#define DIGIT_BITS (1 << DECIMAL_DIGIT_NUMBER)
#define SPACE_BITS ((1 << SPACE_SEPARATOR) | (1 << LINE_SEPARATOR) \
- | (1 << PARAGRAPH_SEPARATOR))
+ | (1 << PARAGRAPH_SEPARATOR))
#define CONNECTOR_BITS (1 << CONNECTOR_PUNCTUATION)
#define PRINT_BITS (ALPHA_BITS | DIGIT_BITS | SPACE_BITS | \
- (1 << NON_SPACING_MARK) | (1 << ENCLOSING_MARK) | \
- (1 << COMBINING_SPACING_MARK) | (1 << LETTER_NUMBER) | \
- (1 << OTHER_NUMBER) | (1 << CONNECTOR_PUNCTUATION) | \
- (1 << DASH_PUNCTUATION) | (1 << OPEN_PUNCTUATION) | \
- (1 << CLOSE_PUNCTUATION) | (1 << INITIAL_QUOTE_PUNCTUATION) | \
- (1 << FINAL_QUOTE_PUNCTUATION) | (1 << OTHER_PUNCTUATION) | \
- (1 << MATH_SYMBOL) | (1 << CURRENCY_SYMBOL) | \
- (1 << MODIFIER_SYMBOL) | (1 << OTHER_SYMBOL))
+ (1 << NON_SPACING_MARK) | (1 << ENCLOSING_MARK) | \
+ (1 << COMBINING_SPACING_MARK) | (1 << LETTER_NUMBER) | \
+ (1 << OTHER_NUMBER) | (1 << CONNECTOR_PUNCTUATION) | \
+ (1 << DASH_PUNCTUATION) | (1 << OPEN_PUNCTUATION) | \
+ (1 << CLOSE_PUNCTUATION) | (1 << INITIAL_QUOTE_PUNCTUATION) | \
+ (1 << FINAL_QUOTE_PUNCTUATION) | (1 << OTHER_PUNCTUATION) | \
+ (1 << MATH_SYMBOL) | (1 << CURRENCY_SYMBOL) | \
+ (1 << MODIFIER_SYMBOL) | (1 << OTHER_SYMBOL))
#define PUNCT_BITS ((1 << CONNECTOR_PUNCTUATION) | \
- (1 << DASH_PUNCTUATION) | (1 << OPEN_PUNCTUATION) | \
- (1 << CLOSE_PUNCTUATION) | (1 << INITIAL_QUOTE_PUNCTUATION) | \
- (1 << FINAL_QUOTE_PUNCTUATION) | (1 << OTHER_PUNCTUATION))
+ (1 << DASH_PUNCTUATION) | (1 << OPEN_PUNCTUATION) | \
+ (1 << CLOSE_PUNCTUATION) | (1 << INITIAL_QUOTE_PUNCTUATION) | \
+ (1 << FINAL_QUOTE_PUNCTUATION) | (1 << OTHER_PUNCTUATION))
/*
- * Unicode characters less than this value are represented by themselves
- * in UTF-8 strings.
+ * Unicode characters less than this value are represented by themselves in
+ * UTF-8 strings.
*/
#define UNICODE_SELF 0x80
/*
- * The following structures are used when mapping between Unicode (UCS-2)
- * and UTF-8.
+ * The following structures are used when mapping between Unicode (UCS-2) and
+ * UTF-8.
*/
static CONST unsigned char totalBytes[256] = {
@@ -87,11 +87,10 @@ static CONST unsigned char totalBytes[256] = {
};
/*
- * Procedures used only in this module.
+ * Functions used only in this module.
*/
-static int UtfCount _ANSI_ARGS_((int ch));
-
+static int UtfCount(int ch);
/*
*---------------------------------------------------------------------------
@@ -108,10 +107,10 @@ static int UtfCount _ANSI_ARGS_((int ch));
*
*---------------------------------------------------------------------------
*/
-
+
INLINE static int
-UtfCount(ch)
- int ch; /* The Tcl_UniChar whose size is returned. */
+UtfCount(
+ int ch) /* The Tcl_UniChar whose size is returned. */
{
if ((ch > 0) && (ch < UNICODE_SELF)) {
return 1;
@@ -142,68 +141,68 @@ UtfCount(ch)
* Tcl_UniCharToUtf --
*
* Store the given Tcl_UniChar as a sequence of UTF-8 bytes in the
- * provided buffer. Equivalent to Plan 9 runetochar().
+ * provided buffer. Equivalent to Plan 9 runetochar().
*
* Results:
- * The return values is the number of bytes in the buffer that
- * were consumed.
+ * The return values is the number of bytes in the buffer that were
+ * consumed.
*
* Side effects:
* None.
*
*---------------------------------------------------------------------------
*/
-
+
INLINE int
-Tcl_UniCharToUtf(ch, str)
- int ch; /* The Tcl_UniChar to be stored in the
+Tcl_UniCharToUtf(
+ int ch, /* The Tcl_UniChar to be stored in the
* buffer. */
- char *str; /* Buffer in which the UTF-8 representation
- * of the Tcl_UniChar is stored. Buffer must
- * be large enough to hold the UTF-8 character
+ char *buf) /* Buffer in which the UTF-8 representation of
+ * the Tcl_UniChar is stored. Buffer must be
+ * large enough to hold the UTF-8 character
* (at most TCL_UTF_MAX bytes). */
{
if ((ch > 0) && (ch < UNICODE_SELF)) {
- str[0] = (char) ch;
+ buf[0] = (char) ch;
return 1;
}
if (ch >= 0) {
if (ch <= 0x7FF) {
- str[1] = (char) ((ch | 0x80) & 0xBF);
- str[0] = (char) ((ch >> 6) | 0xC0);
+ buf[1] = (char) ((ch | 0x80) & 0xBF);
+ buf[0] = (char) ((ch >> 6) | 0xC0);
return 2;
}
if (ch <= 0xFFFF) {
three:
- str[2] = (char) ((ch | 0x80) & 0xBF);
- str[1] = (char) (((ch >> 6) | 0x80) & 0xBF);
- str[0] = (char) ((ch >> 12) | 0xE0);
+ buf[2] = (char) ((ch | 0x80) & 0xBF);
+ buf[1] = (char) (((ch >> 6) | 0x80) & 0xBF);
+ buf[0] = (char) ((ch >> 12) | 0xE0);
return 3;
}
#if TCL_UTF_MAX > 3
if (ch <= 0x1FFFFF) {
- str[3] = (char) ((ch | 0x80) & 0xBF);
- str[2] = (char) (((ch >> 6) | 0x80) & 0xBF);
- str[1] = (char) (((ch >> 12) | 0x80) & 0xBF);
- str[0] = (char) ((ch >> 18) | 0xF0);
+ buf[3] = (char) ((ch | 0x80) & 0xBF);
+ buf[2] = (char) (((ch >> 6) | 0x80) & 0xBF);
+ buf[1] = (char) (((ch >> 12) | 0x80) & 0xBF);
+ buf[0] = (char) ((ch >> 18) | 0xF0);
return 4;
}
if (ch <= 0x3FFFFFF) {
- str[4] = (char) ((ch | 0x80) & 0xBF);
- str[3] = (char) (((ch >> 6) | 0x80) & 0xBF);
- str[2] = (char) (((ch >> 12) | 0x80) & 0xBF);
- str[1] = (char) (((ch >> 18) | 0x80) & 0xBF);
- str[0] = (char) ((ch >> 24) | 0xF8);
+ buf[4] = (char) ((ch | 0x80) & 0xBF);
+ buf[3] = (char) (((ch >> 6) | 0x80) & 0xBF);
+ buf[2] = (char) (((ch >> 12) | 0x80) & 0xBF);
+ buf[1] = (char) (((ch >> 18) | 0x80) & 0xBF);
+ buf[0] = (char) ((ch >> 24) | 0xF8);
return 5;
}
if (ch <= 0x7FFFFFFF) {
- str[5] = (char) ((ch | 0x80) & 0xBF);
- str[4] = (char) (((ch >> 6) | 0x80) & 0xBF);
- str[3] = (char) (((ch >> 12) | 0x80) & 0xBF);
- str[2] = (char) (((ch >> 18) | 0x80) & 0xBF);
- str[1] = (char) (((ch >> 24) | 0x80) & 0xBF);
- str[0] = (char) ((ch >> 30) | 0xFC);
+ buf[5] = (char) ((ch | 0x80) & 0xBF);
+ buf[4] = (char) (((ch >> 6) | 0x80) & 0xBF);
+ buf[3] = (char) (((ch >> 12) | 0x80) & 0xBF);
+ buf[2] = (char) (((ch >> 18) | 0x80) & 0xBF);
+ buf[1] = (char) (((ch >> 24) | 0x80) & 0xBF);
+ buf[0] = (char) ((ch >> 30) | 0xFC);
return 6;
}
#endif
@@ -222,23 +221,22 @@ Tcl_UniCharToUtf(ch, str)
*
* Results:
* The return value is a pointer to the UTF-8 representation of the
- * Unicode string. Storage for the return value is appended to the
- * end of dsPtr.
+ * Unicode string. Storage for the return value is appended to the end of
+ * dsPtr.
*
* Side effects:
* None.
*
*---------------------------------------------------------------------------
*/
-
+
char *
-Tcl_UniCharToUtfDString(wString, numChars, dsPtr)
- CONST Tcl_UniChar *wString; /* Unicode string to convert to UTF-8. */
- int numChars; /* Length of Unicode string in Tcl_UniChars
+Tcl_UniCharToUtfDString(
+ CONST Tcl_UniChar *uniStr, /* Unicode string to convert to UTF-8. */
+ int uniLength, /* Length of Unicode string in Tcl_UniChars
* (must be >= 0). */
- Tcl_DString *dsPtr; /* UTF-8 representation of string is
- * appended to this previously initialized
- * DString. */
+ Tcl_DString *dsPtr) /* UTF-8 representation of string is appended
+ * to this previously initialized DString. */
{
CONST Tcl_UniChar *w, *wEnd;
char *p, *string;
@@ -250,12 +248,12 @@ Tcl_UniCharToUtfDString(wString, numChars, dsPtr)
*/
oldLength = Tcl_DStringLength(dsPtr);
- Tcl_DStringSetLength(dsPtr, (oldLength + numChars + 1) * TCL_UTF_MAX);
+ Tcl_DStringSetLength(dsPtr, (oldLength + uniLength + 1) * TCL_UTF_MAX);
string = Tcl_DStringValue(dsPtr) + oldLength;
p = string;
- wEnd = wString + numChars;
- for (w = wString; w < wEnd; ) {
+ wEnd = uniStr + uniLength;
+ for (w = uniStr; w < wEnd; ) {
p += Tcl_UniCharToUtf(*w, p);
w++;
}
@@ -269,16 +267,16 @@ Tcl_UniCharToUtfDString(wString, numChars, dsPtr)
*
* Tcl_UtfToUniChar --
*
- * Extract the Tcl_UniChar represented by the UTF-8 string. Bad
- * UTF-8 sequences are converted to valid Tcl_UniChars and processing
- * continues. Equivalent to Plan 9 chartorune().
+ * Extract the Tcl_UniChar represented by the UTF-8 string. Bad UTF-8
+ * sequences are converted to valid Tcl_UniChars and processing
+ * continues. Equivalent to Plan 9 chartorune().
*
- * The caller must ensure that the source buffer is long enough that
- * this routine does not run off the end and dereference non-existent
- * memory looking for trail bytes. If the source buffer is known to
- * be '\0' terminated, this cannot happen. Otherwise, the caller
- * should call Tcl_UtfCharComplete() before calling this routine to
- * ensure that enough bytes remain in the string.
+ * The caller must ensure that the source buffer is long enough that this
+ * routine does not run off the end and dereference non-existent memory
+ * looking for trail bytes. If the source buffer is known to be '\0'
+ * terminated, this cannot happen. Otherwise, the caller should call
+ * Tcl_UtfCharComplete() before calling this routine to ensure that
+ * enough bytes remain in the string.
*
* Results:
* *chPtr is filled with the Tcl_UniChar, and the return value is the
@@ -289,20 +287,20 @@ Tcl_UniCharToUtfDString(wString, numChars, dsPtr)
*
*---------------------------------------------------------------------------
*/
-
+
int
-Tcl_UtfToUniChar(str, chPtr)
- register CONST char *str; /* The UTF-8 string. */
- register Tcl_UniChar *chPtr; /* Filled with the Tcl_UniChar represented
- * by the UTF-8 string. */
+Tcl_UtfToUniChar(
+ register CONST char *src, /* The UTF-8 string. */
+ register Tcl_UniChar *chPtr)/* Filled with the Tcl_UniChar represented by
+ * the UTF-8 string. */
{
register int byte;
-
+
/*
* Unroll 1 to 3 byte UTF-8 sequences, use loop to handle longer ones.
*/
- byte = *((unsigned char *) str);
+ byte = *((unsigned char *) src);
if (byte < 0xC0) {
/*
* Handles properly formed UTF-8 characters between 0x01 and 0x7F.
@@ -313,14 +311,15 @@ Tcl_UtfToUniChar(str, chPtr)
*chPtr = (Tcl_UniChar) byte;
return 1;
} else if (byte < 0xE0) {
- if ((str[1] & 0xC0) == 0x80) {
+ if ((src[1] & 0xC0) == 0x80) {
/*
* Two-byte-character lead-byte followed by a trail-byte.
*/
- *chPtr = (Tcl_UniChar) (((byte & 0x1F) << 6) | (str[1] & 0x3F));
+ *chPtr = (Tcl_UniChar) (((byte & 0x1F) << 6) | (src[1] & 0x3F));
return 2;
}
+
/*
* A two-byte-character lead-byte not followed by trail-byte
* represents itself.
@@ -329,15 +328,16 @@ Tcl_UtfToUniChar(str, chPtr)
*chPtr = (Tcl_UniChar) byte;
return 1;
} else if (byte < 0xF0) {
- if (((str[1] & 0xC0) == 0x80) && ((str[2] & 0xC0) == 0x80)) {
+ if (((src[1] & 0xC0) == 0x80) && ((src[2] & 0xC0) == 0x80)) {
/*
* Three-byte-character lead byte followed by two trail bytes.
*/
- *chPtr = (Tcl_UniChar) (((byte & 0x0F) << 12)
- | ((str[1] & 0x3F) << 6) | (str[2] & 0x3F));
+ *chPtr = (Tcl_UniChar) (((byte & 0x0F) << 12)
+ | ((src[1] & 0x3F) << 6) | (src[2] & 0x3F));
return 3;
}
+
/*
* A three-byte-character lead-byte not followed by two trail-bytes
* represents itself.
@@ -347,7 +347,7 @@ Tcl_UtfToUniChar(str, chPtr)
return 1;
}
#if TCL_UTF_MAX > 3
- else {
+ {
int ch, total, trail;
total = totalBytes[byte];
@@ -355,13 +355,13 @@ Tcl_UtfToUniChar(str, chPtr)
if (trail > 0) {
ch = byte & (0x3F >> trail);
do {
- str++;
- if ((*str & 0xC0) != 0x80) {
+ src++;
+ if ((*src & 0xC0) != 0x80) {
*chPtr = byte;
return 1;
}
ch <<= 6;
- ch |= (*str & 0x3F);
+ ch |= (*src & 0x3F);
trail--;
} while (trail > 0);
*chPtr = ch;
@@ -383,9 +383,8 @@ Tcl_UtfToUniChar(str, chPtr)
*
* Results:
* The return value is a pointer to the Unicode representation of the
- * UTF-8 string. Storage for the return value is appended to the
- * end of dsPtr. The Unicode string is terminated with a Unicode
- * NULL character.
+ * UTF-8 string. Storage for the return value is appended to the end of
+ * dsPtr. The Unicode string is terminated with a Unicode NULL character.
*
* Side effects:
* None.
@@ -394,11 +393,11 @@ Tcl_UtfToUniChar(str, chPtr)
*/
Tcl_UniChar *
-Tcl_UtfToUniCharDString(string, length, dsPtr)
- CONST char *string; /* UTF-8 string to convert to Unicode. */
- int length; /* Length of UTF-8 string in bytes, or -1
- * for strlen(). */
- Tcl_DString *dsPtr; /* Unicode representation of string is
+Tcl_UtfToUniCharDString(
+ CONST char *src, /* UTF-8 string to convert to Unicode. */
+ int length, /* Length of UTF-8 string in bytes, or -1 for
+ * strlen(). */
+ Tcl_DString *dsPtr) /* Unicode representation of string is
* appended to this previously initialized
* DString. */
{
@@ -407,12 +406,12 @@ Tcl_UtfToUniCharDString(string, length, dsPtr)
int oldLength;
if (length < 0) {
- length = strlen(string);
+ length = strlen(src);
}
/*
- * Unicode string length in Tcl_UniChars will be <= UTF-8 string length
- * in bytes.
+ * Unicode string length in Tcl_UniChars will be <= UTF-8 string length in
+ * bytes.
*/
oldLength = Tcl_DStringLength(dsPtr);
@@ -421,8 +420,8 @@ Tcl_UtfToUniCharDString(string, length, dsPtr)
wString = (Tcl_UniChar *) (Tcl_DStringValue(dsPtr) + oldLength);
w = wString;
- end = string + length;
- for (p = string; p < end; ) {
+ end = src + length;
+ for (p = src; p < end; ) {
p += TclUtfToUniChar(p, w);
w++;
}
@@ -438,9 +437,9 @@ Tcl_UtfToUniCharDString(string, length, dsPtr)
*
* Tcl_UtfCharComplete --
*
- * Determine if the UTF-8 string of the given length is long enough
- * to be decoded by Tcl_UtfToUniChar(). This does not ensure that the
- * UTF-8 string is properly formed. Equivalent to Plan 9 fullrune().
+ * Determine if the UTF-8 string of the given length is long enough to be
+ * decoded by Tcl_UtfToUniChar(). This does not ensure that the UTF-8
+ * string is properly formed. Equivalent to Plan 9 fullrune().
*
* Results:
* The return value is 0 if the string is not long enough, non-zero
@@ -453,15 +452,15 @@ Tcl_UtfToUniCharDString(string, length, dsPtr)
*/
int
-Tcl_UtfCharComplete(str, len)
- CONST char *str; /* String to check if first few bytes
- * contain a complete UTF-8 character. */
- int len; /* Length of above string in bytes. */
+Tcl_UtfCharComplete(
+ CONST char *src, /* String to check if first few bytes contain
+ * a complete UTF-8 character. */
+ int length) /* Length of above string in bytes. */
{
int ch;
- ch = *((unsigned char *) str);
- return len >= totalBytes[ch];
+ ch = *((unsigned char *) src);
+ return length >= totalBytes[ch];
}
/*
@@ -469,23 +468,23 @@ Tcl_UtfCharComplete(str, len)
*
* Tcl_NumUtfChars --
*
- * Returns the number of characters (not bytes) in the UTF-8 string,
- * not including the terminating NULL byte. This is equivalent to
- * Plan 9 utflen() and utfnlen().
+ * Returns the number of characters (not bytes) in the UTF-8 string, not
+ * including the terminating NULL byte. This is equivalent to Plan 9
+ * utflen() and utfnlen().
*
* Results:
- * As above.
+ * As above.
*
* Side effects:
* None.
*
*---------------------------------------------------------------------------
*/
-
-int
-Tcl_NumUtfChars(str, len)
- register CONST char *str; /* The UTF-8 string to measure. */
- int len; /* The length of the string in bytes, or -1
+
+int
+Tcl_NumUtfChars(
+ register CONST char *src, /* The UTF-8 string to measure. */
+ int length) /* The length of the string in bytes, or -1
* for strlen(string). */
{
Tcl_UniChar ch;
@@ -495,27 +494,27 @@ Tcl_NumUtfChars(str, len)
/*
* The separate implementations are faster.
*
- * Since this is a time-sensitive function, we also do the check for
- * the single-byte char case specially.
+ * Since this is a time-sensitive function, we also do the check for the
+ * single-byte char case specially.
*/
i = 0;
- if (len < 0) {
- while (*str != '\0') {
- str += TclUtfToUniChar(str, chPtr);
+ if (length < 0) {
+ while (*src != '\0') {
+ src += TclUtfToUniChar(src, chPtr);
i++;
}
} else {
register int n;
- while (len > 0) {
- if (UCHAR(*str) < 0xC0) {
- len--;
- str++;
+ while (length > 0) {
+ if (UCHAR(*src) < 0xC0) {
+ length--;
+ src++;
} else {
- n = Tcl_UtfToUniChar(str, chPtr);
- len -= n;
- str += n;
+ n = Tcl_UtfToUniChar(src, chPtr);
+ length -= n;
+ src += n;
}
i++;
}
@@ -528,37 +527,37 @@ Tcl_NumUtfChars(str, len)
*
* Tcl_UtfFindFirst --
*
- * Returns a pointer to the first occurance of the given Tcl_UniChar
- * in the NULL-terminated UTF-8 string. The NULL terminator is
- * considered part of the UTF-8 string. Equivalent to Plan 9
- * utfrune().
+ * Returns a pointer to the first occurance of the given Tcl_UniChar in
+ * the NULL-terminated UTF-8 string. The NULL terminator is considered
+ * part of the UTF-8 string. Equivalent to Plan 9 utfrune().
*
* Results:
- * As above. If the Tcl_UniChar does not exist in the given string,
- * the return value is NULL.
+ * As above. If the Tcl_UniChar does not exist in the given string, the
+ * return value is NULL.
*
* Side effects:
* None.
*
*---------------------------------------------------------------------------
*/
+
CONST char *
-Tcl_UtfFindFirst(string, ch)
- CONST char *string; /* The UTF-8 string to be searched. */
- int ch; /* The Tcl_UniChar to search for. */
+Tcl_UtfFindFirst(
+ CONST char *src, /* The UTF-8 string to be searched. */
+ int ch) /* The Tcl_UniChar to search for. */
{
int len;
Tcl_UniChar find;
-
+
while (1) {
- len = TclUtfToUniChar(string, &find);
+ len = TclUtfToUniChar(src, &find);
if (find == ch) {
- return string;
+ return src;
}
- if (*string == '\0') {
+ if (*src == '\0') {
return NULL;
}
- string += len;
+ src += len;
}
}
@@ -567,14 +566,13 @@ Tcl_UtfFindFirst(string, ch)
*
* Tcl_UtfFindLast --
*
- * Returns a pointer to the last occurance of the given Tcl_UniChar
- * in the NULL-terminated UTF-8 string. The NULL terminator is
- * considered part of the UTF-8 string. Equivalent to Plan 9
- * utfrrune().
+ * Returns a pointer to the last occurance of the given Tcl_UniChar in
+ * the NULL-terminated UTF-8 string. The NULL terminator is considered
+ * part of the UTF-8 string. Equivalent to Plan 9 utfrrune().
*
* Results:
- * As above. If the Tcl_UniChar does not exist in the given string,
- * the return value is NULL.
+ * As above. If the Tcl_UniChar does not exist in the given string, the
+ * return value is NULL.
*
* Side effects:
* None.
@@ -583,24 +581,24 @@ Tcl_UtfFindFirst(string, ch)
*/
CONST char *
-Tcl_UtfFindLast(string, ch)
- CONST char *string; /* The UTF-8 string to be searched. */
- int ch; /* The Tcl_UniChar to search for. */
+Tcl_UtfFindLast(
+ CONST char *src, /* The UTF-8 string to be searched. */
+ int ch) /* The Tcl_UniChar to search for. */
{
int len;
Tcl_UniChar find;
CONST char *last;
-
+
last = NULL;
while (1) {
- len = TclUtfToUniChar(string, &find);
+ len = TclUtfToUniChar(src, &find);
if (find == ch) {
- last = string;
+ last = src;
}
- if (*string == '\0') {
+ if (*src == '\0') {
break;
}
- string += len;
+ src += len;
}
return last;
}
@@ -610,28 +608,27 @@ Tcl_UtfFindLast(string, ch)
*
* Tcl_UtfNext --
*
- * Given a pointer to some current location in a UTF-8 string,
- * move forward one character. The caller must ensure that they
- * are not asking for the next character after the last character
- * in the string.
+ * Given a pointer to some current location in a UTF-8 string, move
+ * forward one character. The caller must ensure that they are not asking
+ * for the next character after the last character in the string.
*
* Results:
- * The return value is the pointer to the next character in
- * the UTF-8 string.
+ * The return value is the pointer to the next character in the UTF-8
+ * string.
*
* Side effects:
* None.
*
*---------------------------------------------------------------------------
*/
-
+
CONST char *
-Tcl_UtfNext(str)
- CONST char *str; /* The current location in the string. */
+Tcl_UtfNext(
+ CONST char *src) /* The current location in the string. */
{
Tcl_UniChar ch;
- return str + TclUtfToUniChar(str, &ch);
+ return src + TclUtfToUniChar(src, &ch);
}
/*
@@ -639,15 +636,15 @@ Tcl_UtfNext(str)
*
* Tcl_UtfPrev --
*
- * Given a pointer to some current location in a UTF-8 string,
- * move backwards one character. This works correctly when the
- * pointer is in the middle of a UTF-8 character.
+ * Given a pointer to some current location in a UTF-8 string, move
+ * backwards one character. This works correctly when the pointer is in
+ * the middle of a UTF-8 character.
*
* Results:
- * The return value is a pointer to the previous character in the
- * UTF-8 string. If the current location was already at the
- * beginning of the string, the return value will also be a
- * pointer to the beginning of the string.
+ * The return value is a pointer to the previous character in the UTF-8
+ * string. If the current location was already at the beginning of the
+ * string, the return value will also be a pointer to the beginning of
+ * the string.
*
* Side effects:
* None.
@@ -656,21 +653,20 @@ Tcl_UtfNext(str)
*/
CONST char *
-Tcl_UtfPrev(str, start)
- CONST char *str; /* The current location in the string. */
- CONST char *start; /* Pointer to the beginning of the
- * string, to avoid going backwards too
- * far. */
+Tcl_UtfPrev(
+ CONST char *src, /* The current location in the string. */
+ CONST char *start) /* Pointer to the beginning of the string, to
+ * avoid going backwards too far. */
{
CONST char *look;
int i, byte;
-
- str--;
- look = str;
+
+ src--;
+ look = src;
for (i = 0; i < TCL_UTF_MAX; i++) {
if (look < start) {
- if (str < start) {
- str = start;
+ if (src < start) {
+ src = start;
}
break;
}
@@ -683,16 +679,16 @@ Tcl_UtfPrev(str, start)
}
look--;
}
- return str;
+ return src;
}
-
+
/*
*---------------------------------------------------------------------------
*
* Tcl_UniCharAtIndex --
*
- * Returns the Unicode character represented at the specified
- * character (not byte) position in the UTF-8 string.
+ * Returns the Unicode character represented at the specified character
+ * (not byte) position in the UTF-8 string.
*
* Results:
* As above.
@@ -702,11 +698,11 @@ Tcl_UtfPrev(str, start)
*
*---------------------------------------------------------------------------
*/
-
+
Tcl_UniChar
-Tcl_UniCharAtIndex(src, index)
- register CONST char *src; /* The UTF-8 string to dereference. */
- register int index; /* The position of the desired character. */
+Tcl_UniCharAtIndex(
+ register CONST char *src, /* The UTF-8 string to dereference. */
+ register int index) /* The position of the desired character. */
{
Tcl_UniChar ch;
@@ -722,8 +718,8 @@ Tcl_UniCharAtIndex(src, index)
*
* Tcl_UtfAtIndex --
*
- * Returns a pointer to the specified character (not byte) position
- * in the UTF-8 string.
+ * Returns a pointer to the specified character (not byte) position in
+ * the UTF-8 string.
*
* Results:
* As above.
@@ -735,12 +731,12 @@ Tcl_UniCharAtIndex(src, index)
*/
CONST char *
-Tcl_UtfAtIndex(src, index)
- register CONST char *src; /* The UTF-8 string. */
- register int index; /* The position of the desired character. */
+Tcl_UtfAtIndex(
+ register CONST char *src, /* The UTF-8 string. */
+ register int index) /* The position of the desired character. */
{
Tcl_UniChar ch;
-
+
while (index > 0) {
index--;
src += TclUtfToUniChar(src, &ch);
@@ -757,31 +753,30 @@ Tcl_UtfAtIndex(src, index)
*
* Results:
* Stores the bytes represented by the backslash sequence in dst and
- * returns the number of bytes written to dst. At most TCL_UTF_MAX
- * bytes are written to dst; dst must have been large enough to accept
- * those bytes. If readPtr isn't NULL then it is filled in with a
- * count of the number of bytes in the backslash sequence.
+ * returns the number of bytes written to dst. At most TCL_UTF_MAX bytes
+ * are written to dst; dst must have been large enough to accept those
+ * bytes. If readPtr isn't NULL then it is filled in with a count of the
+ * number of bytes in the backslash sequence.
*
* Side effects:
- * The maximum number of bytes it takes to represent a Unicode
- * character in UTF-8 is guaranteed to be less than the number of
- * bytes used to express the backslash sequence that represents
- * that Unicode character. If the target buffer into which the
- * caller is going to store the bytes that represent the Unicode
- * character is at least as large as the source buffer from which
- * the backslashed sequence was extracted, no buffer overruns should
- * occur.
+ * The maximum number of bytes it takes to represent a Unicode character
+ * in UTF-8 is guaranteed to be less than the number of bytes used to
+ * express the backslash sequence that represents that Unicode character.
+ * If the target buffer into which the caller is going to store the bytes
+ * that represent the Unicode character is at least as large as the
+ * source buffer from which the backslashed sequence was extracted, no
+ * buffer overruns should occur.
*
*---------------------------------------------------------------------------
*/
int
-Tcl_UtfBackslash(src, readPtr, dst)
- CONST char *src; /* Points to the backslash character of
- * a backslash sequence. */
- int *readPtr; /* Fill in with number of characters read
- * from src, unless NULL. */
- char *dst; /* Filled with the bytes represented by the
+Tcl_UtfBackslash(
+ CONST char *src, /* Points to the backslash character of a
+ * backslash sequence. */
+ int *readPtr, /* Fill in with number of characters read from
+ * src, unless NULL. */
+ char *dst) /* Filled with the bytes represented by the
* backslash sequence. */
{
#define LINE_LENGTH 128
@@ -790,7 +785,10 @@ Tcl_UtfBackslash(src, readPtr, dst)
result = TclParseBackslash(src, LINE_LENGTH, &numRead, dst);
if (numRead == LINE_LENGTH) {
- /* We ate a whole line. Pay the price of a strlen() */
+ /*
+ * We ate a whole line. Pay the price of a strlen()
+ */
+
result = TclParseBackslash(src, (int)strlen(src), &numRead, dst);
}
if (readPtr != NULL) {
@@ -804,12 +802,12 @@ Tcl_UtfBackslash(src, readPtr, dst)
*
* Tcl_UtfToUpper --
*
- * Convert lowercase characters to uppercase characters in a UTF
- * string in place. The conversion may shrink the UTF string.
+ * Convert lowercase characters to uppercase characters in a UTF string
+ * in place. The conversion may shrink the UTF string.
*
* Results:
- * Returns the number of bytes in the resulting string
- * excluding the trailing null.
+ * Returns the number of bytes in the resulting string excluding the
+ * trailing null.
*
* Side effects:
* Writes a terminating null after the last converted character.
@@ -818,8 +816,8 @@ Tcl_UtfBackslash(src, readPtr, dst)
*/
int
-Tcl_UtfToUpper(str)
- char *str; /* String to convert in place. */
+Tcl_UtfToUpper(
+ char *str) /* String to convert in place. */
{
Tcl_UniChar ch, upChar;
char *src, *dst;
@@ -831,15 +829,15 @@ Tcl_UtfToUpper(str)
src = dst = str;
while (*src) {
- bytes = TclUtfToUniChar(src, &ch);
+ bytes = TclUtfToUniChar(src, &ch);
upChar = Tcl_UniCharToUpper(ch);
/*
- * To keep badly formed Utf strings from getting inflated by
- * the conversion (thereby causing a segfault), only copy the
- * upper case char to dst if its size is <= the original char.
+ * To keep badly formed Utf strings from getting inflated by the
+ * conversion (thereby causing a segfault), only copy the upper case
+ * char to dst if its size is <= the original char.
*/
-
+
if (bytes < UtfCount(upChar)) {
memcpy(dst, src, (size_t) bytes);
dst += bytes;
@@ -857,12 +855,12 @@ Tcl_UtfToUpper(str)
*
* Tcl_UtfToLower --
*
- * Convert uppercase characters to lowercase characters in a UTF
- * string in place. The conversion may shrink the UTF string.
+ * Convert uppercase characters to lowercase characters in a UTF string
+ * in place. The conversion may shrink the UTF string.
*
* Results:
- * Returns the number of bytes in the resulting string
- * excluding the trailing null.
+ * Returns the number of bytes in the resulting string excluding the
+ * trailing null.
*
* Side effects:
* Writes a terminating null after the last converted character.
@@ -871,13 +869,13 @@ Tcl_UtfToUpper(str)
*/
int
-Tcl_UtfToLower(str)
- char *str; /* String to convert in place. */
+Tcl_UtfToLower(
+ char *str) /* String to convert in place. */
{
Tcl_UniChar ch, lowChar;
char *src, *dst;
int bytes;
-
+
/*
* Iterate over the string until we hit the terminating null.
*/
@@ -888,11 +886,11 @@ Tcl_UtfToLower(str)
lowChar = Tcl_UniCharToLower(ch);
/*
- * To keep badly formed Utf strings from getting inflated by
- * the conversion (thereby causing a segfault), only copy the
- * lower case char to dst if its size is <= the original char.
+ * To keep badly formed Utf strings from getting inflated by the
+ * conversion (thereby causing a segfault), only copy the lower case
+ * char to dst if its size is <= the original char.
*/
-
+
if (bytes < UtfCount(lowChar)) {
memcpy(dst, src, (size_t) bytes);
dst += bytes;
@@ -910,13 +908,13 @@ Tcl_UtfToLower(str)
*
* Tcl_UtfToTitle --
*
- * Changes the first character of a UTF string to title case or
- * uppercase and the rest of the string to lowercase. The
- * conversion happens in place and may shrink the UTF string.
+ * Changes the first character of a UTF string to title case or uppercase
+ * and the rest of the string to lowercase. The conversion happens in
+ * place and may shrink the UTF string.
*
* Results:
- * Returns the number of bytes in the resulting string
- * excluding the trailing null.
+ * Returns the number of bytes in the resulting string excluding the
+ * trailing null.
*
* Side effects:
* Writes a terminating null after the last converted character.
@@ -925,13 +923,13 @@ Tcl_UtfToLower(str)
*/
int
-Tcl_UtfToTitle(str)
- char *str; /* String to convert in place. */
+Tcl_UtfToTitle(
+ char *str) /* String to convert in place. */
{
Tcl_UniChar ch, titleChar, lowChar;
char *src, *dst;
int bytes;
-
+
/*
* Capitalize the first character and then lowercase the rest of the
* characters until we get to a null.
@@ -972,8 +970,8 @@ Tcl_UtfToTitle(str)
*
* TclpUtfNcmp2 --
*
- * Compare at most n bytes of utf-8 strings cs and ct. Both cs
- * and ct are assumed to be at least n bytes long.
+ * Compare at most numBytes bytes of utf-8 strings cs and ct. Both cs and
+ * ct are assumed to be at least numBytes bytes long.
*
* Results:
* Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct.
@@ -985,26 +983,28 @@ Tcl_UtfToTitle(str)
*/
int
-TclpUtfNcmp2(cs, ct, n)
- CONST char *cs; /* UTF string to compare to ct. */
- CONST char *ct; /* UTF string cs is compared to. */
- unsigned long n; /* Number of *bytes* to compare. */
+TclpUtfNcmp2(
+ CONST char *cs, /* UTF string to compare to ct. */
+ CONST char *ct, /* UTF string cs is compared to. */
+ unsigned long numBytes) /* Number of *bytes* to compare. */
{
/*
- * We can't simply call 'memcmp(cs, ct, n);' because we need to check
- * for Tcl's \xC0\x80 non-utf-8 null encoding.
- * Otherwise utf-8 lexes fine in the strcmp manner.
+ * We can't simply call 'memcmp(cs, ct, numBytes);' because we need to
+ * check for Tcl's \xC0\x80 non-utf-8 null encoding. Otherwise utf-8 lexes
+ * fine in the strcmp manner.
*/
+
register int result = 0;
- for ( ; n != 0; n--, cs++, ct++) {
+ for ( ; numBytes != 0; numBytes--, cs++, ct++) {
if (*cs != *ct) {
result = UCHAR(*cs) - UCHAR(*ct);
break;
}
}
- if (n && ((UCHAR(*cs) == 0xC0) || (UCHAR(*ct) == 0xC0))) {
+ if (numBytes && ((UCHAR(*cs) == 0xC0) || (UCHAR(*ct) == 0xC0))) {
unsigned char c1, c2;
+
c1 = ((UCHAR(*cs) == 0xC0) && (UCHAR(cs[1]) == 0x80)) ? 0 : UCHAR(*cs);
c2 = ((UCHAR(*ct) == 0xC0) && (UCHAR(ct[1]) == 0x80)) ? 0 : UCHAR(*ct);
result = (c1 - c2);
@@ -1017,8 +1017,8 @@ TclpUtfNcmp2(cs, ct, n)
*
* Tcl_UtfNcmp --
*
- * Compare at most n UTF chars of string cs to string ct. Both cs
- * and ct are assumed to be at least n UTF chars long.
+ * Compare at most numChars UTF chars of string cs to string ct. Both cs
+ * and ct are assumed to be at least numChars UTF chars long.
*
* Results:
* Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct.
@@ -1030,23 +1030,26 @@ TclpUtfNcmp2(cs, ct, n)
*/
int
-Tcl_UtfNcmp(cs, ct, n)
- CONST char *cs; /* UTF string to compare to ct. */
- CONST char *ct; /* UTF string cs is compared to. */
- unsigned long n; /* Number of UTF chars to compare. */
+Tcl_UtfNcmp(
+ CONST char *cs, /* UTF string to compare to ct. */
+ CONST char *ct, /* UTF string cs is compared to. */
+ unsigned long numChars) /* Number of UTF chars to compare. */
{
Tcl_UniChar ch1, ch2;
+
/*
- * Cannot use 'memcmp(cs, ct, n);' as byte representation of
- * \u0000 (the pair of bytes 0xc0,0x80) is larger than byte
- * representation of \u0001 (the byte 0x01.)
+ * Cannot use 'memcmp(cs, ct, n);' as byte representation of \u0000 (the
+ * pair of bytes 0xc0,0x80) is larger than byte representation of \u0001
+ * (the byte 0x01.)
*/
- while (n-- > 0) {
+
+ while (numChars-- > 0) {
/*
- * n must be interpreted as chars, not bytes.
- * This should be called only when both strings are of
- * at least n chars long (no need for \0 check)
+ * n must be interpreted as chars, not bytes. This should be called
+ * only when both strings are of at least n chars long (no need for \0
+ * check)
*/
+
cs += TclUtfToUniChar(cs, &ch1);
ct += TclUtfToUniChar(ct, &ch2);
if (ch1 != ch2) {
@@ -1061,9 +1064,9 @@ Tcl_UtfNcmp(cs, ct, n)
*
* Tcl_UtfNcasecmp --
*
- * Compare at most n UTF chars of string cs to string ct case
- * insensitive. Both cs and ct are assumed to be at least n
- * UTF chars long.
+ * Compare at most numChars UTF chars of string cs to string ct case
+ * insensitive. Both cs and ct are assumed to be at least numChars UTF
+ * chars long.
*
* Results:
* Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct.
@@ -1075,13 +1078,13 @@ Tcl_UtfNcmp(cs, ct, n)
*/
int
-Tcl_UtfNcasecmp(cs, ct, n)
- CONST char *cs; /* UTF string to compare to ct. */
- CONST char *ct; /* UTF string cs is compared to. */
- unsigned long n; /* Number of UTF chars to compare. */
+Tcl_UtfNcasecmp(
+ CONST char *cs, /* UTF string to compare to ct. */
+ CONST char *ct, /* UTF string cs is compared to. */
+ unsigned long numChars) /* Number of UTF chars to compare. */
{
Tcl_UniChar ch1, ch2;
- while (n-- > 0) {
+ while (numChars-- > 0) {
/*
* n must be interpreted as chars, not bytes.
* This should be called only when both strings are of
@@ -1117,8 +1120,8 @@ Tcl_UtfNcasecmp(cs, ct, n)
*/
Tcl_UniChar
-Tcl_UniCharToUpper(ch)
- int ch; /* Unicode character to convert. */
+Tcl_UniCharToUpper(
+ int ch) /* Unicode character to convert. */
{
int info = GetUniCharInfo(ch);
@@ -1146,8 +1149,8 @@ Tcl_UniCharToUpper(ch)
*/
Tcl_UniChar
-Tcl_UniCharToLower(ch)
- int ch; /* Unicode character to convert. */
+Tcl_UniCharToLower(
+ int ch) /* Unicode character to convert. */
{
int info = GetUniCharInfo(ch);
@@ -1175,8 +1178,8 @@ Tcl_UniCharToLower(ch)
*/
Tcl_UniChar
-Tcl_UniCharToTitle(ch)
- int ch; /* Unicode character to convert. */
+Tcl_UniCharToTitle(
+ int ch) /* Unicode character to convert. */
{
int info = GetUniCharInfo(ch);
int mode = GetCaseType(info);
@@ -1199,7 +1202,7 @@ Tcl_UniCharToTitle(ch)
*
* Tcl_UniCharLen --
*
- * Find the length of a UniChar string. The str input must be null
+ * Find the length of a UniChar string. The str input must be null
* terminated.
*
* Results:
@@ -1212,14 +1215,14 @@ Tcl_UniCharToTitle(ch)
*/
int
-Tcl_UniCharLen(str)
- CONST Tcl_UniChar *str; /* Unicode string to find length of. */
+Tcl_UniCharLen(
+ CONST Tcl_UniChar *uniStr) /* Unicode string to find length of. */
{
int len = 0;
-
- while (*str != '\0') {
+
+ while (*uniStr != '\0') {
len++;
- str++;
+ uniStr++;
}
return len;
}
@@ -1229,11 +1232,11 @@ Tcl_UniCharLen(str)
*
* Tcl_UniCharNcmp --
*
- * Compare at most n unichars of string cs to string ct. Both cs
- * and ct are assumed to be at least n unichars long.
+ * Compare at most numChars unichars of string ucs to string uct.
+ * Both ucs and uct are assumed to be at least numChars unichars long.
*
* Results:
- * Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct.
+ * Return <0 if ucs < uct, 0 if ucs == uct, or >0 if ucs > uct.
*
* Side effects:
* None.
@@ -1242,24 +1245,26 @@ Tcl_UniCharLen(str)
*/
int
-Tcl_UniCharNcmp(cs, ct, n)
- CONST Tcl_UniChar *cs; /* Unicode string to compare to ct. */
- CONST Tcl_UniChar *ct; /* Unicode string cs is compared to. */
- unsigned long n; /* Number of unichars to compare. */
+Tcl_UniCharNcmp(
+ CONST Tcl_UniChar *ucs, /* Unicode string to compare to uct. */
+ CONST Tcl_UniChar *uct, /* Unicode string ucs is compared to. */
+ unsigned long numChars) /* Number of unichars to compare. */
{
#ifdef WORDS_BIGENDIAN
/*
* We are definitely on a big-endian machine; memcmp() is safe
*/
- return memcmp(cs, ct, n*sizeof(Tcl_UniChar));
+
+ return memcmp(ucs, uct, numChars*sizeof(Tcl_UniChar));
#else /* !WORDS_BIGENDIAN */
/*
* We can't simply call memcmp() because that is not lexically correct.
*/
- for ( ; n != 0; cs++, ct++, n--) {
- if (*cs != *ct) {
- return (*cs - *ct);
+
+ for ( ; numChars != 0; ucs++, uct++, numChars--) {
+ if (*ucs != *uct) {
+ return (*ucs - *uct);
}
}
return 0;
@@ -1271,12 +1276,12 @@ Tcl_UniCharNcmp(cs, ct, n)
*
* Tcl_UniCharNcasecmp --
*
- * Compare at most n unichars of string cs to string ct case
- * insensitive. Both cs and ct are assumed to be at least n
+ * Compare at most numChars unichars of string ucs to string uct case
+ * insensitive. Both ucs and uct are assumed to be at least numChars
* unichars long.
*
* Results:
- * Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct.
+ * Return <0 if ucs < uct, 0 if ucs == uct, or >0 if ucs > uct.
*
* Side effects:
* None.
@@ -1285,15 +1290,16 @@ Tcl_UniCharNcmp(cs, ct, n)
*/
int
-Tcl_UniCharNcasecmp(cs, ct, n)
- CONST Tcl_UniChar *cs; /* Unicode string to compare to ct. */
- CONST Tcl_UniChar *ct; /* Unicode string cs is compared to. */
- unsigned long n; /* Number of unichars to compare. */
+Tcl_UniCharNcasecmp(
+ CONST Tcl_UniChar *ucs, /* Unicode string to compare to uct. */
+ CONST Tcl_UniChar *uct, /* Unicode string ucs is compared to. */
+ unsigned long numChars) /* Number of unichars to compare. */
{
- for ( ; n != 0; n--, cs++, ct++) {
- if (*cs != *ct) {
- Tcl_UniChar lcs = Tcl_UniCharToLower(*cs);
- Tcl_UniChar lct = Tcl_UniCharToLower(*ct);
+ for ( ; numChars != 0; numChars--, ucs++, uct++) {
+ if (*ucs != *uct) {
+ Tcl_UniChar lcs = Tcl_UniCharToLower(*ucs);
+ Tcl_UniChar lct = Tcl_UniCharToLower(*uct);
+
if (lcs != lct) {
return (lcs - lct);
}
@@ -1319,8 +1325,8 @@ Tcl_UniCharNcasecmp(cs, ct, n)
*/
int
-Tcl_UniCharIsAlnum(ch)
- int ch; /* Unicode character to test. */
+Tcl_UniCharIsAlnum(
+ int ch) /* Unicode character to test. */
{
register int category = (GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK);
@@ -1344,8 +1350,8 @@ Tcl_UniCharIsAlnum(ch)
*/
int
-Tcl_UniCharIsAlpha(ch)
- int ch; /* Unicode character to test. */
+Tcl_UniCharIsAlpha(
+ int ch) /* Unicode character to test. */
{
register int category = (GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK);
return ((ALPHA_BITS >> category) & 1);
@@ -1368,8 +1374,8 @@ Tcl_UniCharIsAlpha(ch)
*/
int
-Tcl_UniCharIsControl(ch)
- int ch; /* Unicode character to test. */
+Tcl_UniCharIsControl(
+ int ch) /* Unicode character to test. */
{
return ((GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK) == CONTROL);
}
@@ -1391,11 +1397,10 @@ Tcl_UniCharIsControl(ch)
*/
int
-Tcl_UniCharIsDigit(ch)
- int ch; /* Unicode character to test. */
+Tcl_UniCharIsDigit(
+ int ch) /* Unicode character to test. */
{
- return ((GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK)
- == DECIMAL_DIGIT_NUMBER);
+ return (GetUniCharInfo(ch)&UNICODE_CATEGORY_MASK) == DECIMAL_DIGIT_NUMBER;
}
/*
@@ -1415,8 +1420,8 @@ Tcl_UniCharIsDigit(ch)
*/
int
-Tcl_UniCharIsGraph(ch)
- int ch; /* Unicode character to test. */
+Tcl_UniCharIsGraph(
+ int ch) /* Unicode character to test. */
{
register int category = (GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK);
return (((PRINT_BITS >> category) & 1) && ((unsigned char) ch != ' '));
@@ -1439,8 +1444,8 @@ Tcl_UniCharIsGraph(ch)
*/
int
-Tcl_UniCharIsLower(ch)
- int ch; /* Unicode character to test. */
+Tcl_UniCharIsLower(
+ int ch) /* Unicode character to test. */
{
return ((GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK) == LOWERCASE_LETTER);
}
@@ -1462,8 +1467,8 @@ Tcl_UniCharIsLower(ch)
*/
int
-Tcl_UniCharIsPrint(ch)
- int ch; /* Unicode character to test. */
+Tcl_UniCharIsPrint(
+ int ch) /* Unicode character to test. */
{
register int category = (GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK);
return ((PRINT_BITS >> category) & 1);
@@ -1486,8 +1491,8 @@ Tcl_UniCharIsPrint(ch)
*/
int
-Tcl_UniCharIsPunct(ch)
- int ch; /* Unicode character to test. */
+Tcl_UniCharIsPunct(
+ int ch) /* Unicode character to test. */
{
register int category = (GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK);
return ((PUNCT_BITS >> category) & 1);
@@ -1510,8 +1515,8 @@ Tcl_UniCharIsPunct(ch)
*/
int
-Tcl_UniCharIsSpace(ch)
- int ch; /* Unicode character to test. */
+Tcl_UniCharIsSpace(
+ int ch) /* Unicode character to test. */
{
register int category;
@@ -1521,7 +1526,7 @@ Tcl_UniCharIsSpace(ch)
*/
if (ch < 0x80) {
- return isspace(UCHAR(ch)); /* INTL: ISO space */
+ return TclIsSpaceProc((char)ch);
} else {
category = (GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK);
return ((SPACE_BITS >> category) & 1);
@@ -1545,8 +1550,8 @@ Tcl_UniCharIsSpace(ch)
*/
int
-Tcl_UniCharIsUpper(ch)
- int ch; /* Unicode character to test. */
+Tcl_UniCharIsUpper(
+ int ch) /* Unicode character to test. */
{
return ((GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK) == UPPERCASE_LETTER);
}
@@ -1556,8 +1561,7 @@ Tcl_UniCharIsUpper(ch)
*
* Tcl_UniCharIsWordChar --
*
- * Test if a character is alphanumeric or a connector punctuation
- * mark.
+ * Test if a character is alphanumeric or a connector punctuation mark.
*
* Results:
* Returns 1 if character is a word character.
@@ -1569,8 +1573,8 @@ Tcl_UniCharIsUpper(ch)
*/
int
-Tcl_UniCharIsWordChar(ch)
- int ch; /* Unicode character to test. */
+Tcl_UniCharIsWordChar(
+ int ch) /* Unicode character to test. */
{
register int category = (GetUniCharInfo(ch) & UNICODE_CATEGORY_MASK);
@@ -1583,17 +1587,16 @@ Tcl_UniCharIsWordChar(ch)
* Tcl_UniCharCaseMatch --
*
* See if a particular Unicode string matches a particular pattern.
- * Allows case insensitivity. This is the Unicode equivalent of
- * the char* Tcl_StringCaseMatch. The UniChar strings must be
- * NULL-terminated. This has no provision for counted UniChar
- * strings, thus should not be used where NULLs are expected in the
- * UniChar string. Use TclUniCharMatch where possible.
+ * Allows case insensitivity. This is the Unicode equivalent of the char*
+ * Tcl_StringCaseMatch. The UniChar strings must be NULL-terminated.
+ * This has no provision for counted UniChar strings, thus should not be
+ * used where NULLs are expected in the UniChar string. Use
+ * TclUniCharMatch where possible.
*
* Results:
- * The return value is 1 if string matches pattern, and
- * 0 otherwise. The matching operation permits the following
- * special characters in the pattern: *?\[] (see the manual
- * entry for details on what these mean).
+ * The return value is 1 if string matches pattern, and 0 otherwise. The
+ * matching operation permits the following special characters in the
+ * pattern: *?\[] (see the manual entry for details on what these mean).
*
* Side effects:
* None.
@@ -1602,44 +1605,48 @@ Tcl_UniCharIsWordChar(ch)
*/
int
-Tcl_UniCharCaseMatch(string, pattern, nocase)
- CONST Tcl_UniChar *string; /* Unicode String. */
- CONST Tcl_UniChar *pattern; /* Pattern, which may contain special
+Tcl_UniCharCaseMatch(
+ CONST Tcl_UniChar *uniStr, /* Unicode String. */
+ CONST Tcl_UniChar *uniPattern,
+ /* Pattern, which may contain special
* characters. */
- int nocase; /* 0 for case sensitive, 1 for insensitive */
+ int nocase) /* 0 for case sensitive, 1 for insensitive */
{
Tcl_UniChar ch1, p;
-
+
while (1) {
- p = *pattern;
-
+ p = *uniPattern;
+
/*
- * See if we're at the end of both the pattern and the string. If
- * so, we succeeded. If we're at the end of the pattern but not at
- * the end of the string, we failed.
+ * See if we're at the end of both the pattern and the string. If so,
+ * we succeeded. If we're at the end of the pattern but not at the end
+ * of the string, we failed.
*/
-
+
if (p == 0) {
- return (*string == 0);
+ return (*uniStr == 0);
}
- if ((*string == 0) && (p != '*')) {
+ if ((*uniStr == 0) && (p != '*')) {
return 0;
}
/*
- * Check for a "*" as the next pattern character. It matches any
- * substring. We handle this by skipping all the characters up to the
+ * Check for a "*" as the next pattern character. It matches any
+ * substring. We handle this by skipping all the characters up to the
* next matching one in the pattern, and then calling ourselves
* recursively for each postfix of string, until either we match or we
* reach the end of the string.
*/
-
+
if (p == '*') {
/*
* Skip all successive *'s in the pattern
*/
- while (*(++pattern) == '*') {}
- p = *pattern;
+
+ while (*(++uniPattern) == '*') {
+ /* empty body */
+ }
+ p = *uniPattern;
if (p == 0) {
return 1;
}
@@ -1652,63 +1659,67 @@ Tcl_UniCharCaseMatch(string, pattern, nocase)
* quickly if the next char in the pattern isn't a special
* character
*/
+
if ((p != '[') && (p != '?') && (p != '\\')) {
if (nocase) {
- while (*string && (p != *string)
- && (p != Tcl_UniCharToLower(*string))) {
- string++;
+ while (*uniStr && (p != *uniStr)
+ && (p != Tcl_UniCharToLower(*uniStr))) {
+ uniStr++;
}
} else {
- while (*string && (p != *string)) { string++; }
+ while (*uniStr && (p != *uniStr)) {
+ uniStr++;
+ }
}
}
- if (Tcl_UniCharCaseMatch(string, pattern, nocase)) {
+ if (Tcl_UniCharCaseMatch(uniStr, uniPattern, nocase)) {
return 1;
}
- if (*string == 0) {
+ if (*uniStr == 0) {
return 0;
}
- string++;
+ uniStr++;
}
}
/*
- * Check for a "?" as the next pattern character. It matches
- * any single character.
+ * Check for a "?" as the next pattern character. It matches any
+ * single character.
*/
if (p == '?') {
- pattern++;
- string++;
+ uniPattern++;
+ uniStr++;
continue;
}
/*
- * Check for a "[" as the next pattern character. It is followed
- * by a list of characters that are acceptable, or by a range
- * (two characters separated by "-").
+ * Check for a "[" as the next pattern character. It is followed by a
+ * list of characters that are acceptable, or by a range (two
+ * characters separated by "-").
*/
-
+
if (p == '[') {
Tcl_UniChar startChar, endChar;
- pattern++;
- ch1 = (nocase ? Tcl_UniCharToLower(*string) : *string);
- string++;
+ uniPattern++;
+ ch1 = (nocase ? Tcl_UniCharToLower(*uniStr) : *uniStr);
+ uniStr++;
while (1) {
- if ((*pattern == ']') || (*pattern == 0)) {
+ if ((*uniPattern == ']') || (*uniPattern == 0)) {
return 0;
}
- startChar = (nocase ? Tcl_UniCharToLower(*pattern) : *pattern);
- pattern++;
- if (*pattern == '-') {
- pattern++;
- if (*pattern == 0) {
+ startChar = (nocase ? Tcl_UniCharToLower(*uniPattern)
+ : *uniPattern);
+ uniPattern++;
+ if (*uniPattern == '-') {
+ uniPattern++;
+ if (*uniPattern == 0) {
return 0;
}
- endChar = (nocase ? Tcl_UniCharToLower(*pattern)
- : *pattern);
- pattern++;
+ endChar = (nocase ? Tcl_UniCharToLower(*uniPattern)
+ : *uniPattern);
+ uniPattern++;
if (((startChar <= ch1) && (ch1 <= endChar))
|| ((endChar <= ch1) && (ch1 <= startChar))) {
/*
@@ -1720,42 +1731,43 @@ Tcl_UniCharCaseMatch(string, pattern, nocase)
break;
}
}
- while (*pattern != ']') {
- if (*pattern == 0) {
- pattern--;
+ while (*uniPattern != ']') {
+ if (*uniPattern == 0) {
+ uniPattern--;
break;
}
- pattern++;
+ uniPattern++;
}
- pattern++;
+ uniPattern++;
continue;
}
/*
- * If the next pattern character is '\', just strip off the '\'
- * so we do exact matching on the character that follows.
+ * If the next pattern character is '\', just strip off the '\' so we
+ * do exact matching on the character that follows.
*/
if (p == '\\') {
- if (*(++pattern) == '\0') {
+ if (*(++uniPattern) == '\0') {
return 0;
}
}
/*
- * There's no special character. Just make sure that the next
- * bytes of each string match.
+ * There's no special character. Just make sure that the next bytes of
+ * each string match.
*/
if (nocase) {
- if (Tcl_UniCharToLower(*string) != Tcl_UniCharToLower(*pattern)) {
+ if (Tcl_UniCharToLower(*uniStr) !=
+ Tcl_UniCharToLower(*uniPattern)) {
return 0;
}
- } else if (*string != *pattern) {
+ } else if (*uniStr != *uniPattern) {
return 0;
}
- string++;
- pattern++;
+ uniStr++;
+ uniPattern++;
}
}
@@ -1765,15 +1777,14 @@ Tcl_UniCharCaseMatch(string, pattern, nocase)
* TclUniCharMatch --
*
* See if a particular Unicode string matches a particular pattern.
- * Allows case insensitivity. This is the Unicode equivalent of the
- * char* Tcl_StringCaseMatch. This variant of Tcl_UniCharCaseMatch
- * uses counted Strings, so embedded NULLs are allowed.
+ * Allows case insensitivity. This is the Unicode equivalent of the char*
+ * Tcl_StringCaseMatch. This variant of Tcl_UniCharCaseMatch uses counted
+ * Strings, so embedded NULLs are allowed.
*
* Results:
- * The return value is 1 if string matches pattern, and
- * 0 otherwise. The matching operation permits the following
- * special characters in the pattern: *?\[] (see the manual
- * entry for details on what these mean).
+ * The return value is 1 if string matches pattern, and 0 otherwise. The
+ * matching operation permits the following special characters in the
+ * pattern: *?\[] (see the manual entry for details on what these mean).
*
* Side effects:
* None.
@@ -1782,25 +1793,25 @@ Tcl_UniCharCaseMatch(string, pattern, nocase)
*/
int
-TclUniCharMatch(string, strLen, pattern, ptnLen, nocase)
- CONST Tcl_UniChar *string; /* Unicode String. */
- int strLen; /* length of String */
- CONST Tcl_UniChar *pattern; /* Pattern, which may contain special
+TclUniCharMatch(
+ CONST Tcl_UniChar *string, /* Unicode String. */
+ int strLen, /* Length of String */
+ CONST Tcl_UniChar *pattern, /* Pattern, which may contain special
* characters. */
- int ptnLen; /* length of Pattern */
- int nocase; /* 0 for case sensitive, 1 for insensitive */
+ int ptnLen, /* Length of Pattern */
+ int nocase) /* 0 for case sensitive, 1 for insensitive */
{
CONST Tcl_UniChar *stringEnd, *patternEnd;
Tcl_UniChar p;
- stringEnd = string + strLen;
+ stringEnd = string + strLen;
patternEnd = pattern + ptnLen;
while (1) {
/*
- * See if we're at the end of both the pattern and the string. If
- * so, we succeeded. If we're at the end of the pattern but not at
- * the end of the string, we failed.
+ * See if we're at the end of both the pattern and the string. If so,
+ * we succeeded. If we're at the end of the pattern but not at the end
+ * of the string, we failed.
*/
if (pattern == patternEnd) {
@@ -1812,18 +1823,21 @@ TclUniCharMatch(string, strLen, pattern, ptnLen, nocase)
}
/*
- * Check for a "*" as the next pattern character. It matches any
- * substring. We handle this by skipping all the characters up to the
+ * Check for a "*" as the next pattern character. It matches any
+ * substring. We handle this by skipping all the characters up to the
* next matching one in the pattern, and then calling ourselves
* recursively for each postfix of string, until either we match or we
* reach the end of the string.
*/
-
+
if (p == '*') {
/*
- * Skip all successive *'s in the pattern
+ * Skip all successive *'s in the pattern.
*/
- while (*(++pattern) == '*') {}
+
+ while (*(++pattern) == '*') {
+ /* empty body */
+ }
if (pattern == patternEnd) {
return 1;
}
@@ -1835,8 +1849,9 @@ TclUniCharMatch(string, strLen, pattern, ptnLen, nocase)
/*
* Optimization for matching - cruise through the string
* quickly if the next char in the pattern isn't a special
- * character
+ * character.
*/
+
if ((p != '[') && (p != '?') && (p != '\\')) {
if (nocase) {
while ((string < stringEnd) && (p != *string)
@@ -1861,8 +1876,8 @@ TclUniCharMatch(string, strLen, pattern, ptnLen, nocase)
}
/*
- * Check for a "?" as the next pattern character. It matches
- * any single character.
+ * Check for a "?" as the next pattern character. It matches any
+ * single character.
*/
if (p == '?') {
@@ -1872,11 +1887,11 @@ TclUniCharMatch(string, strLen, pattern, ptnLen, nocase)
}
/*
- * Check for a "[" as the next pattern character. It is followed
- * by a list of characters that are acceptable, or by a range
- * (two characters separated by "-").
+ * Check for a "[" as the next pattern character. It is followed by a
+ * list of characters that are acceptable, or by a range (two
+ * characters separated by "-").
*/
-
+
if (p == '[') {
Tcl_UniChar ch1, startChar, endChar;
@@ -1920,8 +1935,8 @@ TclUniCharMatch(string, strLen, pattern, ptnLen, nocase)
}
/*
- * If the next pattern character is '\', just strip off the '\'
- * so we do exact matching on the character that follows.
+ * If the next pattern character is '\', just strip off the '\' so we
+ * do exact matching on the character that follows.
*/
if (p == '\\') {
@@ -1931,8 +1946,8 @@ TclUniCharMatch(string, strLen, pattern, ptnLen, nocase)
}
/*
- * There's no special character. Just make sure that the next
- * bytes of each string match.
+ * There's no special character. Just make sure that the next bytes of
+ * each string match.
*/
if (nocase) {
@@ -1946,3 +1961,11 @@ TclUniCharMatch(string, strLen, pattern, ptnLen, nocase)
pattern++;
}
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclUtil.c b/generic/tclUtil.c
index 19332c8..eaa7eae 100644
--- a/generic/tclUtil.c
+++ b/generic/tclUtil.c
@@ -1,118 +1,466 @@
-/*
+/*
* tclUtil.c --
*
- * This file contains utility procedures that are used by many Tcl
+ * This file contains utility functions that are used by many Tcl
* commands.
*
* Copyright (c) 1987-1993 The Regents of the University of California.
* Copyright (c) 1994-1998 Sun Microsystems, Inc.
- * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
+ * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
+#include <float.h>
+#include <math.h>
/*
- * The following variable holds the full path name of the binary
- * from which this application was executed, or NULL if it isn't
- * know. The value of the variable is set by the procedure
- * Tcl_FindExecutable. The storage space is dynamically allocated.
+ * The absolute pathname of the executable in which this Tcl library is
+ * running.
*/
-char *tclExecutableName = NULL;
-char *tclNativeExecutableName = NULL;
+static ProcessGlobalValue executableName = {
+ 0, 0, NULL, NULL, NULL, NULL, NULL
+};
/*
- * The following values are used in the flags returned by Tcl_ScanElement
- * and used by Tcl_ConvertElement. The value TCL_DONT_USE_BRACES is also
- * defined in tcl.h; make sure its value doesn't overlap with any of the
- * values below.
- *
- * TCL_DONT_USE_BRACES - 1 means the string mustn't be enclosed in
- * braces (e.g. it contains unmatched braces,
- * or ends in a backslash character, or user
- * just doesn't want braces); handle all
- * special characters by adding backslashes.
- * USE_BRACES - 1 means the string contains a special
- * character that can be handled simply by
- * enclosing the entire argument in braces.
- * BRACES_UNMATCHED - 1 means that braces aren't properly matched
- * in the argument.
+ * The following values are used in the flags arguments of Tcl*Scan*Element and
+ * Tcl*Convert*Element. The values TCL_DONT_USE_BRACES and TCL_DONT_QUOTE_HASH
+ * are defined in tcl.h, like so:
+ *
+#define TCL_DONT_USE_BRACES 1
+#define TCL_DONT_QUOTE_HASH 8
+ *
+ * Those are public flag bits which callers of the public routines
+ * Tcl_Convert*Element() can use to indicate:
+ *
+ * TCL_DONT_USE_BRACES - 1 means the caller is insisting that brace
+ * quoting not be used when converting the list
+ * element.
+ * TCL_DONT_QUOTE_HASH - 1 means the caller insists that a leading hash
+ * character ('#') should *not* be quoted. This
+ * is appropriate when the caller can guarantee
+ * the element is not the first element of a
+ * list, so [eval] cannot mis-parse the element
+ * as a comment.
+ *
+ * The remaining values which can be carried by the flags of these routines
+ * are for internal use only. Make sure they do not overlap with the public
+ * values above.
+ *
+ * The Tcl*Scan*Element() routines make a determination which of 4 modes of
+ * conversion is most appropriate for Tcl*Convert*Element() to perform, and
+ * sets two bits of the flags value to indicate the mode selected.
+ *
+ * CONVERT_NONE The element needs no quoting. Its literal string
+ * is suitable as is.
+ * CONVERT_BRACE The conversion should be enclosing the literal string
+ * in braces.
+ * CONVERT_ESCAPE The conversion should be using backslashes to escape
+ * any characters in the string that require it.
+ * CONVERT_MASK A mask value used to extract the conversion mode from
+ * the flags argument.
+ * Also indicates a strange conversion mode where all
+ * special characters are escaped with backslashes
+ * *except for braces*. This is a strange and unnecessary
+ * case, but it's part of the historical way in which
+ * lists have been formatted in Tcl. To experiment with
+ * removing this case, set the value of COMPAT to 0.
+ *
+ * One last flag value is used only by callers of TclScanElement(). The flag
+ * value produced by a call to Tcl*Scan*Element() will never leave this bit
+ * set.
+ *
+ * CONVERT_ANY The caller of TclScanElement() declares it can make
+ * no promise about what public flags will be passed to
+ * the matching call of TclConvertElement(). As such,
+ * TclScanElement() has to determine the worst case
+ * destination buffer length over all possibilities, and
+ * in other cases this means an overestimate of the
+ * required size.
+ *
+ * For more details, see the comments on the Tcl*Scan*Element and
+ * Tcl*Convert*Element routines.
*/
-#define USE_BRACES 2
-#define BRACES_UNMATCHED 4
+#define COMPAT 1
+#define CONVERT_NONE 0
+#define CONVERT_BRACE 2
+#define CONVERT_ESCAPE 4
+#define CONVERT_MASK (CONVERT_BRACE | CONVERT_ESCAPE)
+#define CONVERT_ANY 16
/*
- * The following values determine the precision used when converting
- * floating-point values to strings. This information is linked to all
- * of the tcl_precision variables in all interpreters via the procedure
- * TclPrecTraceProc.
+ * The following key is used by Tcl_PrintDouble and TclPrecTraceProc to
+ * access the precision to be used for double formatting.
*/
-static char precisionString[10] = "12";
- /* The string value of all the tcl_precision
- * variables. */
-static char precisionFormat[10] = "%.12g";
- /* The format string actually used in calls
- * to sprintf. */
-TCL_DECLARE_MUTEX(precisionMutex)
+static Tcl_ThreadDataKey precisionKey;
/*
- * Prototypes for procedures defined later in this file.
+ * Prototypes for functions defined later in this file.
*/
-static void UpdateStringOfEndOffset _ANSI_ARGS_((Tcl_Obj* objPtr));
-static int SetEndOffsetFromAny _ANSI_ARGS_((Tcl_Interp* interp,
- Tcl_Obj* objPtr));
+static void ClearHash(Tcl_HashTable *tablePtr);
+static void FreeProcessGlobalValue(ClientData clientData);
+static void FreeThreadHash(ClientData clientData);
+static Tcl_HashTable * GetThreadHash(Tcl_ThreadDataKey *keyPtr);
+static int SetEndOffsetFromAny(Tcl_Interp* interp,
+ Tcl_Obj* objPtr);
+static void UpdateStringOfEndOffset(Tcl_Obj* objPtr);
/*
- * The following is the Tcl object type definition for an object
- * that represents a list index in the form, "end-offset". It is
- * used as a performance optimization in TclGetIntForIndex. The
- * internal rep is an integer, so no memory management is required
- * for it.
+ * The following is the Tcl object type definition for an object that
+ * represents a list index in the form, "end-offset". It is used as a
+ * performance optimization in TclGetIntForIndex. The internal rep is an
+ * integer, so no memory management is required for it.
*/
Tcl_ObjType tclEndOffsetType = {
"end-offset", /* name */
- (Tcl_FreeInternalRepProc*) NULL, /* freeIntRepProc */
- (Tcl_DupInternalRepProc*) NULL, /* dupIntRepProc */
+ NULL, /* freeIntRepProc */
+ NULL, /* dupIntRepProc */
UpdateStringOfEndOffset, /* updateStringProc */
- SetEndOffsetFromAny
+ SetEndOffsetFromAny
};
+
+/*
+ * * STRING REPRESENTATION OF LISTS * * *
+ *
+ * The next several routines implement the conversions of strings to and
+ * from Tcl lists. To understand their operation, the rules of parsing
+ * and generating the string representation of lists must be known. Here
+ * we describe them in one place.
+ *
+ * A list is made up of zero or more elements. Any string is a list if
+ * it is made up of alternating substrings of element-separating ASCII
+ * whitespace and properly formatted elements.
+ *
+ * The ASCII characters which can make up the whitespace between list
+ * elements are:
+ *
+ * \u0009 \t TAB
+ * \u000A \n NEWLINE
+ * \u000B \v VERTICAL TAB
+ * \u000C \f FORM FEED
+ * \u000D \r CARRIAGE RETURN
+ * \u0020 SPACE
+ *
+ * NOTE: differences between this and other places where Tcl defines a role
+ * for "whitespace".
+ *
+ * * Unlike command parsing, here NEWLINE is just another whitespace
+ * character; its role as a command terminator in a script has no
+ * importance here.
+ *
+ * * Unlike command parsing, the BACKSLASH NEWLINE sequence is not
+ * considered to be a whitespace character.
+ *
+ * * Other Unicode whitespace characters (recognized by
+ * [string is space] or Tcl_UniCharIsSpace()) do not play any role
+ * as element separators in Tcl lists.
+ *
+ * * The NUL byte ought not appear, as it is not in strings properly
+ * encoded for Tcl, but if it is present, it is not treated as
+ * separating whitespace, or a string terminator. It is just
+ * another character in a list element.
+ *
+ * The interpretaton of a formatted substring as a list element follows
+ * rules similar to the parsing of the words of a command in a Tcl script.
+ * Backslash substitution plays a key role, and is defined exactly as it is
+ * in command parsing. The same routine, TclParseBackslash() is used in both
+ * command parsing and list parsing.
+ *
+ * NOTE: This means that if and when backslash substitution rules ever
+ * change for command parsing, the interpretation of strings as lists also
+ * changes.
+ *
+ * Backslash substitution replaces an "escape sequence" of one or more
+ * characters starting with
+ * \u005c \ BACKSLASH
+ * with a single character. The one character escape sequent case happens
+ * only when BACKSLASH is the last character in the string. In all other
+ * cases, the escape sequence is at least two characters long.
+ *
+ * The formatted substrings are interpreted as element values according to
+ * the following cases:
+ *
+ * * If the first character of a formatted substring is
+ * \u007b { OPEN BRACE
+ * then the end of the substring is the matching
+ * \u007d } CLOSE BRACE
+ * character, where matching is determined by counting nesting levels,
+ * and not including any brace characters that are contained within a
+ * backslash escape sequence in the nesting count. Having found the
+ * matching brace, all characters between the braces are the string
+ * value of the element. If no matching close brace is found before the
+ * end of the string, the string is not a Tcl list. If the character
+ * following the close brace is not an element separating whitespace
+ * character, or the end of the string, then the string is not a Tcl list.
+ *
+ * NOTE: this differs from a brace-quoted word in the parsing of a
+ * Tcl command only in its treatment of the backslash-newline sequence.
+ * In a list element, the literal characters in the backslash-newline
+ * sequence become part of the element value. In a script word,
+ * conversion to a single SPACE character is done.
+ *
+ * NOTE: Most list element values can be represented by a formatted
+ * substring using brace quoting. The exceptions are any element value
+ * that includes an unbalanced brace not in a backslash escape sequence,
+ * and any value that ends with a backslash not itself in a backslash
+ * escape sequence.
+ *
+ * * If the first character of a formatted substring is
+ * \u0022 " QUOTE
+ * then the end of the substring is the next QUOTE character, not counting
+ * any QUOTE characters that are contained within a backslash escape
+ * sequence. If no next QUOTE is found before the end of the string, the
+ * string is not a Tcl list. If the character following the closing QUOTE
+ * is not an element separating whitespace character, or the end of the
+ * string, then the string is not a Tcl list. Having found the limits
+ * of the substring, the element value is produced by performing backslash
+ * substitution on the character sequence between the open and close QUOTEs.
+ *
+ * NOTE: Any element value can be represented by this style of formatting,
+ * given suitable choice of backslash escape sequences.
+ *
+ * * All other formatted substrings are terminated by the next element
+ * separating whitespace character in the string. Having found the limits
+ * of the substring, the element value is produced by performing backslash
+ * substitution on it.
+ *
+ * NOTE: Any element value can be represented by this style of formatting,
+ * given suitable choice of backslash escape sequences, with one exception.
+ * The empty string cannot be represented as a list element without the use
+ * of either braces or quotes to delimit it.
+ *
+ * This collection of parsing rules is implemented in the routine
+ * TclFindElement().
+ *
+ * In order to produce lists that can be parsed by these rules, we need
+ * the ability to distinguish between characters that are part of a list
+ * element value from characters providing syntax that define the structure
+ * of the list. This means that our code that generates lists must at a
+ * minimum be able to produce escape sequences for the 10 characters
+ * identified above that have significance to a list parser.
+ *
+ * * * CANONICAL LISTS * * * * *
+ *
+ * In addition to the basic rules for parsing strings into Tcl lists, there
+ * are additional properties to be met by the set of list values that are
+ * generated by Tcl. Such list values are often said to be in "canonical
+ * form":
+ *
+ * * When any canonical list is evaluated as a Tcl script, it is a script
+ * of either zero commands (an empty list) or exactly one command. The
+ * command word is exactly the first element of the list, and each argument
+ * word is exactly one of the following elements of the list. This means
+ * that any characters that have special meaning during script evaluation
+ * need special treatment when canonical lists are produced:
+ *
+ * * Whitespace between elements may not include NEWLINE.
+ * * The command terminating character,
+ * \u003b ; SEMICOLON
+ * must be BRACEd, QUOTEd, or escaped so that it does not terminate
+ * the command prematurely.
+ * * Any of the characters that begin substitutions in scripts,
+ * \u0024 $ DOLLAR
+ * \u005b [ OPEN BRACKET
+ * \u005c \ BACKSLASH
+ * need to be BRACEd or escaped.
+ * * In any list where the first character of the first element is
+ * \u0023 # HASH
+ * that HASH character must be BRACEd, QUOTEd, or escaped so that it
+ * does not convert the command into a comment.
+ * * Any list element that contains the character sequence
+ * BACKSLASH NEWLINE cannot be formatted with BRACEs. The
+ * BACKSLASH character must be represented by an escape
+ * sequence, and unless QUOTEs are used, the NEWLINE must
+ * be as well.
+ *
+ * * It is also guaranteed that one can use a canonical list as a building
+ * block of a larger script within command substitution, as in this example:
+ * set script "puts \[[list $cmd $arg]]"; eval $script
+ * To support this usage, any appearance of the character
+ * \u005d ] CLOSE BRACKET
+ * in a list element must be BRACEd, QUOTEd, or escaped.
+ *
+ * * Finally it is guaranteed that enclosing a canonical list in braces
+ * produces a new value that is also a canonical list. This new list has
+ * length 1, and its only element is the original canonical list. This
+ * same guarantee also makes it possible to construct scripts where an
+ * argument word is given a list value by enclosing the canonical form
+ * of that list in braces:
+ * set script "puts {[list $one $two $three]}"; eval $script
+ * This sort of coding was once fairly common, though it's become more
+ * idiomatic to see the following instead:
+ * set script [list puts [list $one $two $three]]; eval $script
+ * In order to support this guarantee, every canonical list must have
+ * balance when counting those braces that are not in escape sequences.
+ *
+ * Within these constraints, the canonical list generation routines
+ * TclScanElement() and TclConvertElement() attempt to generate the string
+ * for any list that is easiest to read. When an element value is itself
+ * acceptable as the formatted substring, it is usually used (CONVERT_NONE).
+ * When some quoting or escaping is required, use of BRACEs (CONVERT_BRACE)
+ * is usually preferred over the use of escape sequences (CONVERT_ESCAPE).
+ * There are some exceptions to both of these preferences for reasons of
+ * code simplicity, efficiency, and continuation of historical habits.
+ * Canonical lists never use the QUOTE formatting to delimit their elements
+ * because that form of quoting does not nest, which makes construction of
+ * nested lists far too much trouble. Canonical lists always use only a
+ * single SPACE character for element-separating whitespace.
+ *
+ * * * FUTURE CONSIDERATIONS * * *
+ *
+ * When a list element requires quoting or escaping due to a CLOSE BRACKET
+ * character or an internal QUOTE character, a strange formatting mode is
+ * recommended. For example, if the value "a{b]c}d" is converted by the
+ * usual modes:
+ *
+ * CONVERT_BRACE: a{b]c}d => {a{b]c}d}
+ * CONVERT_ESCAPE: a{b]c}d => a\{b\]c\}d
+ *
+ * we get perfectly usable formatted list elements. However, this is not
+ * what Tcl releases have been producing. Instead, we have:
+ *
+ * CONVERT_MASK: a{b]c}d => a{b\]c}d
+ *
+ * where the CLOSE BRACKET is escaped, but the BRACEs are not. The same
+ * effect can be seen replacing ] with " in this example. There does not
+ * appear to be any functional or aesthetic purpose for this strange
+ * additional mode. The sole purpose I can see for preserving it is to
+ * keep generating the same formatted lists programmers have become accustomed
+ * to, and perhaps written tests to expect. That is, compatibility only.
+ * The additional code complexity required to support this mode is significant.
+ * The lines of code supporting it are delimited in the routines below with
+ * #if COMPAT directives. This makes it easy to experiment with eliminating
+ * this formatting mode simply with "#define COMPAT 0" above. I believe
+ * this is worth considering.
+ *
+ * Another consideration is the treatment of QUOTE characters in list elements.
+ * TclConvertElement() must have the ability to produce the escape sequence
+ * \" so that when a list element begins with a QUOTE we do not confuse
+ * that first character with a QUOTE used as list syntax to define list
+ * structure. However, that is the only place where QUOTE characters need
+ * quoting. In this way, handling QUOTE could really be much more like
+ * the way we handle HASH which also needs quoting and escaping only in
+ * particular situations. Following up this could increase the set of
+ * list elements that can use the CONVERT_NONE formatting mode.
+ *
+ * More speculative is that the demands of canonical list form require brace
+ * balance for the list as a whole, while the current implementation achieves
+ * this by establishing brace balance for every element.
+ *
+ * Finally, a reminder that the rules for parsing and formatting lists are
+ * closely tied together with the rules for parsing and evaluating scripts,
+ * and will need to evolve in sync.
+ */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMaxListLength --
+ *
+ * Given 'bytes' pointing to 'numBytes' bytes, scan through them and
+ * count the number of whitespace runs that could be list element
+ * separators. If 'numBytes' is -1, scan to the terminating '\0'.
+ * Not a full list parser. Typically used to get a quick and dirty
+ * overestimate of length size in order to allocate space for an
+ * actual list parser to operate with.
+ *
+ * Results:
+ * Returns the largest number of list elements that could possibly
+ * be in this string, interpreted as a Tcl list. If 'endPtr' is not
+ * NULL, writes a pointer to the end of the string scanned there.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclMaxListLength(
+ CONST char *bytes,
+ int numBytes,
+ CONST char **endPtr)
+{
+ int count = 0;
+
+ if ((numBytes == 0) || ((numBytes == -1) && (*bytes == '\0'))) {
+ /* Empty string case - quick exit */
+ goto done;
+ }
+ /* No list element before leading white space */
+ count += 1 - TclIsSpaceProc(*bytes);
+
+ /* Count white space runs as potential element separators */
+ while (numBytes) {
+ if ((numBytes == -1) && (*bytes == '\0')) {
+ break;
+ }
+ if (TclIsSpaceProc(*bytes)) {
+ /* Space run started; bump count */
+ count++;
+ do {
+ bytes++;
+ numBytes -= (numBytes != -1);
+ } while (numBytes && TclIsSpaceProc(*bytes));
+ if ((numBytes == 0) || ((numBytes == -1) && (*bytes == '\0'))) {
+ break;
+ }
+ /* (*bytes) is non-space; return to counting state */
+ }
+ bytes++;
+ numBytes -= (numBytes != -1);
+ }
+
+ /* No list element following trailing white space */
+ count -= TclIsSpaceProc(bytes[-1]);
+
+ done:
+ if (endPtr) {
+ *endPtr = bytes;
+ }
+ return count;
+}
/*
*----------------------------------------------------------------------
*
* TclFindElement --
*
- * Given a pointer into a Tcl list, locate the first (or next)
- * element in the list.
+ * Given a pointer into a Tcl list, locate the first (or next) element in
+ * the list.
*
* Results:
- * The return value is normally TCL_OK, which means that the
- * element was successfully located. If TCL_ERROR is returned
- * it means that list didn't have proper list structure;
- * the interp's result contains a more detailed error message.
+ * The return value is normally TCL_OK, which means that the element was
+ * successfully located. If TCL_ERROR is returned it means that list
+ * didn't have proper list structure; the interp's result contains a more
+ * detailed error message.
*
* If TCL_OK is returned, then *elementPtr will be set to point to the
* first element of list, and *nextPtr will be set to point to the
* character just after any white space following the last character
- * that's part of the element. If this is the last argument in the
- * list, then *nextPtr will point just after the last character in the
- * list (i.e., at the character at list+listLength). If sizePtr is
- * non-NULL, *sizePtr is filled in with the number of characters in the
- * element. If the element is in braces, then *elementPtr will point
- * to the character after the opening brace and *sizePtr will not
- * include either of the braces. If there isn't an element in the list,
- * *sizePtr will be zero, and both *elementPtr and *termPtr will point
- * just after the last character in the list. Note: this procedure does
- * NOT collapse backslash sequences.
+ * that's part of the element. If this is the last argument in the list,
+ * then *nextPtr will point just after the last character in the list
+ * (i.e., at the character at list+listLength). If sizePtr is non-NULL,
+ * *sizePtr is filled in with the number of bytes in the element. If
+ * the element is in braces, then *elementPtr will point to the character
+ * after the opening brace and *sizePtr will not include either of the
+ * braces. If there isn't an element in the list, *sizePtr will be zero,
+ * and both *elementPtr and *nextPtr will point just after the last
+ * character in the list. If literalPtr is non-NULL, *literalPtr is set
+ * to a boolean value indicating whether the substring returned as
+ * the values of **elementPtr and *sizePtr is the literal value of
+ * a list element. If not, a call to TclCopyAndCollapse() is needed
+ * to produce the actual value of the list element. Note: this function
+ * does NOT collapse backslash sequences, but uses *literalPtr to tell
+ * callers when it is required for them to do so.
*
* Side effects:
* None.
@@ -121,25 +469,27 @@ Tcl_ObjType tclEndOffsetType = {
*/
int
-TclFindElement(interp, list, listLength, elementPtr, nextPtr, sizePtr,
- bracePtr)
- Tcl_Interp *interp; /* Interpreter to use for error reporting.
- * If NULL, then no error message is left
- * after errors. */
- CONST char *list; /* Points to the first byte of a string
+TclFindElement(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. If
+ * NULL, then no error message is left after
+ * errors. */
+ CONST char *list, /* Points to the first byte of a string
* containing a Tcl list with zero or more
* elements (possibly in braces). */
- int listLength; /* Number of bytes in the list's string. */
- CONST char **elementPtr; /* Where to put address of first significant
+ int listLength, /* Number of bytes in the list's string. */
+ CONST char **elementPtr, /* Where to put address of first significant
* character in first element of list. */
- CONST char **nextPtr; /* Fill in with location of character just
+ CONST char **nextPtr, /* Fill in with location of character just
* after all white space following end of
* argument (next arg or end of list). */
- int *sizePtr; /* If non-zero, fill in with size of
+ int *sizePtr, /* If non-zero, fill in with size of
* element. */
- int *bracePtr; /* If non-zero, fill in with non-zero/zero
- * to indicate that arg was/wasn't
- * in braces. */
+ int *literalPtr) /* If non-zero, fill in with non-zero/zero to
+ * indicate that the substring of *sizePtr
+ * bytes starting at **elementPtr is/is not
+ * the literal list element and therefore
+ * does not/does require a call to
+ * TclCopyAndCollapse() by the caller. */
{
CONST char *p = list;
CONST char *elemStart; /* Points to first byte of first element. */
@@ -148,16 +498,17 @@ TclFindElement(interp, list, listLength, elementPtr, nextPtr, sizePtr,
int inQuotes = 0;
int size = 0; /* lint. */
int numChars;
+ int literal = 1;
CONST char *p2;
-
+
/*
- * Skim off leading white space and check for an opening brace or
- * quote. We treat embedded NULLs in the list as bytes belonging to
- * a list element.
+ * Skim off leading white space and check for an opening brace or quote.
+ * We treat embedded NULLs in the list as bytes belonging to a list
+ * element.
*/
limit = (list + listLength);
- while ((p < limit) && (isspace(UCHAR(*p)))) { /* INTL: ISO space. */
+ while ((p < limit) && (TclIsSpaceProc(*p))) {
p++;
}
if (p == limit) { /* no element found */
@@ -173,9 +524,6 @@ TclFindElement(interp, list, listLength, elementPtr, nextPtr, sizePtr,
p++;
}
elemStart = p;
- if (bracePtr != 0) {
- *bracePtr = openBraces;
- }
/*
* Find element's end (a space, close brace, or the end of the string).
@@ -183,123 +531,119 @@ TclFindElement(interp, list, listLength, elementPtr, nextPtr, sizePtr,
while (p < limit) {
switch (*p) {
-
/*
* Open brace: don't treat specially unless the element is in
* braces. In this case, keep a nesting count.
*/
- case '{':
- if (openBraces != 0) {
- openBraces++;
- }
- break;
+ case '{':
+ if (openBraces != 0) {
+ openBraces++;
+ }
+ break;
/*
* Close brace: if element is in braces, keep nesting count and
* quit when the last close brace is seen.
*/
- case '}':
- if (openBraces > 1) {
- openBraces--;
- } else if (openBraces == 1) {
- size = (p - elemStart);
- p++;
- if ((p >= limit)
- || isspace(UCHAR(*p))) { /* INTL: ISO space. */
- goto done;
- }
+ case '}':
+ if (openBraces > 1) {
+ openBraces--;
+ } else if (openBraces == 1) {
+ size = (p - elemStart);
+ p++;
+ if ((p >= limit) || TclIsSpaceProc(*p)) {
+ goto done;
+ }
- /*
- * Garbage after the closing brace; return an error.
- */
-
- if (interp != NULL) {
- char buf[100];
-
- p2 = p;
- while ((p2 < limit)
- && (!isspace(UCHAR(*p2))) /* INTL: ISO space. */
- && (p2 < p+20)) {
- p2++;
- }
- sprintf(buf,
- "list element in braces followed by \"%.*s\" instead of space",
- (int) (p2-p), p);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ /*
+ * Garbage after the closing brace; return an error.
+ */
+
+ if (interp != NULL) {
+ p2 = p;
+ while ((p2 < limit) && (!TclIsSpaceProc(*p2))
+ && (p2 < p+20)) {
+ p2++;
}
- return TCL_ERROR;
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "list element in braces followed by \"%.*s\" "
+ "instead of space", (int) (p2-p), p));
}
- break;
+ return TCL_ERROR;
+ }
+ break;
/*
- * Backslash: skip over everything up to the end of the
- * backslash sequence.
+ * Backslash: skip over everything up to the end of the backslash
+ * sequence.
*/
- case '\\': {
- TclParseBackslash(p, limit - p, &numChars, NULL);
- p += (numChars - 1);
- break;
+ case '\\':
+ if (openBraces == 0) {
+ /*
+ * A backslash sequence not within a brace quoted element
+ * means the value of the element is different from the
+ * substring we are parsing. A call to TclCopyAndCollapse()
+ * is needed to produce the element value. Inform the caller.
+ */
+ literal = 0;
}
+ TclParseBackslash(p, limit - p, &numChars, NULL);
+ p += (numChars - 1);
+ break;
/*
* Space: ignore if element is in braces or quotes; otherwise
* terminate element.
*/
- case ' ':
- case '\f':
- case '\n':
- case '\r':
- case '\t':
- case '\v':
- if ((openBraces == 0) && !inQuotes) {
- size = (p - elemStart);
- goto done;
- }
- break;
+ case ' ':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ case '\v':
+ if ((openBraces == 0) && !inQuotes) {
+ size = (p - elemStart);
+ goto done;
+ }
+ break;
/*
* Double-quote: if element is in quotes then terminate it.
*/
- case '"':
- if (inQuotes) {
- size = (p - elemStart);
- p++;
- if ((p >= limit)
- || isspace(UCHAR(*p))) { /* INTL: ISO space */
- goto done;
- }
+ case '"':
+ if (inQuotes) {
+ size = (p - elemStart);
+ p++;
+ if ((p >= limit) || TclIsSpaceProc(*p)) {
+ goto done;
+ }
- /*
- * Garbage after the closing quote; return an error.
- */
-
- if (interp != NULL) {
- char buf[100];
-
- p2 = p;
- while ((p2 < limit)
- && (!isspace(UCHAR(*p2))) /* INTL: ISO space */
- && (p2 < p+20)) {
- p2++;
- }
- sprintf(buf,
- "list element in quotes followed by \"%.*s\" %s",
- (int) (p2-p), p, "instead of space");
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ /*
+ * Garbage after the closing quote; return an error.
+ */
+
+ if (interp != NULL) {
+ p2 = p;
+ while ((p2 < limit) && (!TclIsSpaceProc(*p2))
+ && (p2 < p+20)) {
+ p2++;
}
- return TCL_ERROR;
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "list element in quotes followed by \"%.*s\" "
+ "instead of space", (int) (p2-p), p));
}
- break;
+ return TCL_ERROR;
+ }
+ break;
}
p++;
}
-
/*
* End of list: terminate element.
*/
@@ -321,8 +665,8 @@ TclFindElement(interp, list, listLength, elementPtr, nextPtr, sizePtr,
size = (p - elemStart);
}
- done:
- while ((p < limit) && (isspace(UCHAR(*p)))) { /* INTL: ISO space. */
+ done:
+ while ((p < limit) && (TclIsSpaceProc(*p))) {
p++;
}
*elementPtr = elemStart;
@@ -330,6 +674,9 @@ TclFindElement(interp, list, listLength, elementPtr, nextPtr, sizePtr,
if (sizePtr != 0) {
*sizePtr = size;
}
+ if (literalPtr != 0) {
+ *literalPtr = literal;
+ }
return TCL_OK;
}
@@ -338,7 +685,7 @@ TclFindElement(interp, list, listLength, elementPtr, nextPtr, sizePtr,
*
* TclCopyAndCollapse --
*
- * Copy a string and eliminate any backslashes that aren't in braces.
+ * Copy a string and substitute all backslash escape sequences
*
* Results:
* Count bytes get copied from src to dst. Along the way, backslash
@@ -353,10 +700,10 @@ TclFindElement(interp, list, listLength, elementPtr, nextPtr, sizePtr,
*/
int
-TclCopyAndCollapse(count, src, dst)
- int count; /* Number of bytes to copy from src. */
- CONST char *src; /* Copy from here... */
- char *dst; /* ... to here. */
+TclCopyAndCollapse(
+ int count, /* Number of byte to copy from src. */
+ CONST char *src, /* Copy from here... */
+ char *dst) /* ... to here. */
{
int newCount = 0;
@@ -390,21 +737,19 @@ TclCopyAndCollapse(count, src, dst)
* Splits a list up into its constituent fields.
*
* Results
- * The return value is normally TCL_OK, which means that
- * the list was successfully split up. If TCL_ERROR is
- * returned, it means that "list" didn't have proper list
- * structure; the interp's result will contain a more detailed
- * error message.
- *
- * *argvPtr will be filled in with the address of an array
- * whose elements point to the elements of list, in order.
- * *argcPtr will get filled in with the number of valid elements
- * in the array. A single block of memory is dynamically allocated
- * to hold both the argv array and a copy of the list (with
- * backslashes and braces removed in the standard way).
- * The caller must eventually free this memory by calling free()
- * on *argvPtr. Note: *argvPtr and *argcPtr are only modified
- * if the procedure returns normally.
+ * The return value is normally TCL_OK, which means that the list was
+ * successfully split up. If TCL_ERROR is returned, it means that "list"
+ * didn't have proper list structure; the interp's result will contain a
+ * more detailed error message.
+ *
+ * *argvPtr will be filled in with the address of an array whose elements
+ * point to the elements of list, in order. *argcPtr will get filled in
+ * with the number of valid elements in the array. A single block of
+ * memory is dynamically allocated to hold both the argv array and a copy
+ * of the list (with backslashes and braces removed in the standard way).
+ * The caller must eventually free this memory by calling free() on
+ * *argvPtr. Note: *argvPtr and *argcPtr are only modified if the
+ * function returns normally.
*
* Side effects:
* Memory is allocated.
@@ -413,54 +758,40 @@ TclCopyAndCollapse(count, src, dst)
*/
int
-Tcl_SplitList(interp, list, argcPtr, argvPtr)
- Tcl_Interp *interp; /* Interpreter to use for error reporting.
- * If NULL, no error message is left. */
- CONST char *list; /* Pointer to string with list structure. */
- int *argcPtr; /* Pointer to location to fill in with
- * the number of elements in the list. */
- CONST char ***argvPtr; /* Pointer to place to store pointer to
- * array of pointers to list elements. */
+Tcl_SplitList(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. If
+ * NULL, no error message is left. */
+ CONST char *list, /* Pointer to string with list structure. */
+ int *argcPtr, /* Pointer to location to fill in with the
+ * number of elements in the list. */
+ CONST char ***argvPtr) /* Pointer to place to store pointer to array
+ * of pointers to list elements. */
{
- CONST char **argv;
- CONST char *l;
+ CONST char **argv, *end, *element;
char *p;
- int length, size, i, result, elSize, brace;
- CONST char *element;
+ int length, size, i, result, elSize;
/*
- * Figure out how much space to allocate. There must be enough
- * space for both the array of pointers and also for a copy of
- * the list. To estimate the number of pointers needed, count
- * the number of space characters in the list.
+ * Allocate enough space to work in. A (CONST char *) for each
+ * (possible) list element plus one more for terminating NULL,
+ * plus as many bytes as in the original string value, plus one
+ * more for a terminating '\0'. Space used to hold element separating
+ * white space in the original string gets re-purposed to hold '\0'
+ * characters in the argv array.
*/
- for (size = 2, l = list; *l != 0; l++) {
- if (isspace(UCHAR(*l))) { /* INTL: ISO space. */
- size++;
- /* Consecutive space can only count as a single list delimiter */
- while (1) {
- char next = *(l + 1);
- if (next == '\0') {
- break;
- }
- ++l;
- if (isspace(UCHAR(next))) {
- continue;
- }
- break;
- }
- }
- }
- length = l - list;
+ size = TclMaxListLength(list, -1, &end) + 1;
+ length = end - list;
argv = (CONST char **) ckalloc((unsigned)
((size * sizeof(char *)) + length + 1));
+
for (i = 0, p = ((char *) argv) + size*sizeof(char *);
*list != 0; i++) {
CONST char *prevList = list;
-
- result = TclFindElement(interp, list, length, &element,
- &list, &elSize, &brace);
+ int literal;
+
+ result = TclFindElement(interp, list, length, &element, &list,
+ &elSize, &literal);
length -= (list - prevList);
if (result != TCL_OK) {
ckfree((char *) argv);
@@ -478,14 +809,13 @@ Tcl_SplitList(interp, list, argcPtr, argvPtr)
return TCL_ERROR;
}
argv[i] = p;
- if (brace) {
- memcpy((VOID *) p, (VOID *) element, (size_t) elSize);
+ if (literal) {
+ memcpy(p, element, (size_t) elSize);
p += elSize;
*p = 0;
p++;
} else {
- TclCopyAndCollapse(elSize, element, p);
- p += elSize+1;
+ p += 1 + TclCopyAndCollapse(elSize, element, p);
}
}
@@ -500,17 +830,15 @@ Tcl_SplitList(interp, list, argcPtr, argvPtr)
*
* Tcl_ScanElement --
*
- * This procedure is a companion procedure to Tcl_ConvertElement.
- * It scans a string to see what needs to be done to it (e.g. add
- * backslashes or enclosing braces) to make the string into a
- * valid Tcl list element.
+ * This function is a companion function to Tcl_ConvertElement. It scans
+ * a string to see what needs to be done to it (e.g. add backslashes or
+ * enclosing braces) to make the string into a valid Tcl list element.
*
* Results:
- * The return value is an overestimate of the number of characters
- * that will be needed by Tcl_ConvertElement to produce a valid
- * list element from string. The word at *flagPtr is filled in
- * with a value needed by Tcl_ConvertElement when doing the actual
- * conversion.
+ * The return value is an overestimate of the number of bytes that
+ * will be needed by Tcl_ConvertElement to produce a valid list element
+ * from src. The word at *flagPtr is filled in with a value needed by
+ * Tcl_ConvertElement when doing the actual conversion.
*
* Side effects:
* None.
@@ -519,12 +847,12 @@ Tcl_SplitList(interp, list, argcPtr, argvPtr)
*/
int
-Tcl_ScanElement(string, flagPtr)
- register CONST char *string; /* String to convert to list element. */
- register int *flagPtr; /* Where to store information to guide
- * Tcl_ConvertCountedElement. */
+Tcl_ScanElement(
+ register CONST char *src, /* String to convert to list element. */
+ register int *flagPtr) /* Where to store information to guide
+ * Tcl_ConvertCountedElement. */
{
- return Tcl_ScanCountedElement(string, -1, flagPtr);
+ return Tcl_ScanCountedElement(src, -1, flagPtr);
}
/*
@@ -532,19 +860,17 @@ Tcl_ScanElement(string, flagPtr)
*
* Tcl_ScanCountedElement --
*
- * This procedure is a companion procedure to
- * Tcl_ConvertCountedElement. It scans a string to see what
- * needs to be done to it (e.g. add backslashes or enclosing
- * braces) to make the string into a valid Tcl list element.
- * If length is -1, then the string is scanned up to the first
- * null byte.
+ * This function is a companion function to Tcl_ConvertCountedElement. It
+ * scans a string to see what needs to be done to it (e.g. add
+ * backslashes or enclosing braces) to make the string into a valid Tcl
+ * list element. If length is -1, then the string is scanned from src up
+ * to the first null byte.
*
* Results:
- * The return value is an overestimate of the number of characters
- * that will be needed by Tcl_ConvertCountedElement to produce a
- * valid list element from string. The word at *flagPtr is
- * filled in with a value needed by Tcl_ConvertCountedElement
- * when doing the actual conversion.
+ * The return value is an overestimate of the number of bytes that
+ * will be needed by Tcl_ConvertCountedElement to produce a valid list
+ * element from src. The word at *flagPtr is filled in with a value
+ * needed by Tcl_ConvertCountedElement when doing the actual conversion.
*
* Side effects:
* None.
@@ -553,115 +879,266 @@ Tcl_ScanElement(string, flagPtr)
*/
int
-Tcl_ScanCountedElement(string, length, flagPtr)
- CONST char *string; /* String to convert to Tcl list element. */
- int length; /* Number of bytes in string, or -1. */
- int *flagPtr; /* Where to store information to guide
+Tcl_ScanCountedElement(
+ CONST char *src, /* String to convert to Tcl list element. */
+ int length, /* Number of bytes in src, or -1. */
+ int *flagPtr) /* Where to store information to guide
* Tcl_ConvertElement. */
{
- int flags, nestingLevel;
- register CONST char *p, *lastChar;
+ int flags = CONVERT_ANY;
+ int numBytes = TclScanElement(src, length, &flags);
- /*
- * This procedure and Tcl_ConvertElement together do two things:
- *
- * 1. They produce a proper list, one that will yield back the
- * argument strings when evaluated or when disassembled with
- * Tcl_SplitList. This is the most important thing.
- *
- * 2. They try to produce legible output, which means minimizing the
- * use of backslashes (using braces instead). However, there are
- * some situations where backslashes must be used (e.g. an element
- * like "{abc": the leading brace will have to be backslashed.
- * For each element, one of three things must be done:
- *
- * (a) Use the element as-is (it doesn't contain any special
- * characters). This is the most desirable option.
- *
- * (b) Enclose the element in braces, but leave the contents alone.
- * This happens if the element contains embedded space, or if it
- * contains characters with special interpretation ($, [, ;, or \),
- * or if it starts with a brace or double-quote, or if there are
- * no characters in the element.
- *
- * (c) Don't enclose the element in braces, but add backslashes to
- * prevent special interpretation of special characters. This is a
- * last resort used when the argument would normally fall under case
- * (b) but contains unmatched braces. It also occurs if the last
- * character of the argument is a backslash or if the element contains
- * a backslash followed by newline.
- *
- * The procedure figures out how many bytes will be needed to store
- * the result (actually, it overestimates). It also collects information
- * about the element in the form of a flags word.
- *
- * Note: list elements produced by this procedure and
- * Tcl_ConvertCountedElement must have the property that they can be
- * enclosing in curly braces to make sub-lists. This means, for
- * example, that we must not leave unmatched curly braces in the
- * resulting list element. This property is necessary in order for
- * procedures like Tcl_DStringStartSublist to work.
- */
+ *flagPtr = flags;
+ return numBytes;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclScanElement --
+ *
+ * This function is a companion function to TclConvertElement. It
+ * scans a string to see what needs to be done to it (e.g. add
+ * backslashes or enclosing braces) to make the string into a valid Tcl
+ * list element. If length is -1, then the string is scanned from src up
+ * to the first null byte. A NULL value for src is treated as an
+ * empty string. The incoming value of *flagPtr is a report from the
+ * caller what additional flags it will pass to TclConvertElement().
+ *
+ * Results:
+ * The recommended formatting mode for the element is determined and
+ * a value is written to *flagPtr indicating that recommendation. This
+ * recommendation is combined with the incoming flag values in *flagPtr
+ * set by the caller to determine how many bytes will be needed by
+ * TclConvertElement() in which to write the formatted element following
+ * the recommendation modified by the flag values. This number of bytes
+ * is the return value of the routine. In some situations it may be
+ * an overestimate, but so long as the caller passes the same flags
+ * to TclConvertElement(), it will be large enough.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
- nestingLevel = 0;
- flags = 0;
- if (string == NULL) {
- string = "";
- }
- if (length == -1) {
- length = strlen(string);
+int
+TclScanElement(
+ CONST char *src, /* String to convert to Tcl list element. */
+ int length, /* Number of bytes in src, or -1. */
+ int *flagPtr) /* Where to store information to guide
+ * Tcl_ConvertElement. */
+{
+ CONST char *p = src;
+ int nestingLevel = 0; /* Brace nesting count */
+ int forbidNone = 0; /* Do not permit CONVERT_NONE mode. Something
+ needs protection or escape. */
+ int requireEscape = 0; /* Force use of CONVERT_ESCAPE mode. For some
+ * reason bare or brace-quoted form fails. */
+ int extra = 0; /* Count of number of extra bytes needed for
+ * formatted element, assuming we use escape
+ * sequences in formatting. */
+ int bytesNeeded; /* Buffer length computed to complete the
+ * element formatting in the selected mode. */
+#if COMPAT
+ int preferEscape = 0; /* Use preferences to track whether to use */
+ int preferBrace = 0; /* CONVERT_MASK mode. */
+ int braceCount = 0; /* Count of all braces '{' '}' seen. */
+#endif
+
+ if ((p == NULL) || (length == 0) || ((*p == '\0') && (length == -1))) {
+ /* Empty string element must be brace quoted. */
+ *flagPtr = CONVERT_BRACE;
+ return 2;
}
- lastChar = string + length;
- p = string;
- if ((p == lastChar) || (*p == '{') || (*p == '"')) {
- flags |= USE_BRACES;
+
+ if ((*p == '{') || (*p == '"')) {
+ /*
+ * Must escape or protect so leading character of value is not
+ * misinterpreted as list element delimiting syntax.
+ */
+ forbidNone = 1;
+#if COMPAT
+ preferBrace = 1;
+#endif
}
- for ( ; p < lastChar; p++) {
+
+ while (length) {
switch (*p) {
- case '{':
- nestingLevel++;
- break;
- case '}':
- nestingLevel--;
- if (nestingLevel < 0) {
- flags |= TCL_DONT_USE_BRACES|BRACES_UNMATCHED;
- }
- break;
- case '[':
- case '$':
- case ';':
- case ' ':
- case '\f':
- case '\n':
- case '\r':
- case '\t':
- case '\v':
- flags |= USE_BRACES;
+ case '{':
+#if COMPAT
+ braceCount++;
+#endif
+ extra++; /* Escape '{' => '\{' */
+ nestingLevel++;
+ break;
+ case '}':
+#if COMPAT
+ braceCount++;
+#endif
+ extra++; /* Escape '}' => '\}' */
+ nestingLevel--;
+ if (nestingLevel < 0) {
+ /* Unbalanced braces! Cannot format with brace quoting. */
+ requireEscape = 1;
+ }
+ break;
+ case ']':
+ case '"':
+#if COMPAT
+ forbidNone = 1;
+ extra++; /* Escapes all just prepend a backslash */
+ preferEscape = 1;
+ break;
+#else
+ /* FLOW THROUGH */
+#endif
+ case '[':
+ case '$':
+ case ';':
+ case ' ':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ case '\v':
+ forbidNone = 1;
+ extra++; /* Escape sequences all one byte longer. */
+#if COMPAT
+ preferBrace = 1;
+#endif
+ break;
+ case '\\':
+ extra++; /* Escape '\' => '\\' */
+ if ((length == 1) || ((length == -1) && (p[1] == '\0'))) {
+ /* Final backslash. Cannot format with brace quoting. */
+ requireEscape = 1;
break;
- case '\\':
- if ((p+1 == lastChar) || (p[1] == '\n')) {
- flags = TCL_DONT_USE_BRACES | BRACES_UNMATCHED;
- } else {
- int size;
-
- TclParseBackslash(p, lastChar - p, &size, NULL);
- p += size-1;
- flags |= USE_BRACES;
- }
+ }
+ if (p[1] == '\n') {
+ extra++; /* Escape newline => '\n', one byte longer */
+ /* Backslash newline sequence. Brace quoting not permitted. */
+ requireEscape = 1;
+ length -= (length > 0);
+ p++;
break;
+ }
+ if ((p[1] == '{') || (p[1] == '}') || (p[1] == '\\')) {
+ extra++; /* Escape sequences all one byte longer. */
+ length -= (length > 0);
+ p++;
+ }
+ forbidNone = 1;
+#if COMPAT
+ preferBrace = 1;
+#endif
+ break;
+ case '\0':
+ if (length == -1) {
+ goto endOfString;
+ }
+ /* TODO: Panic on improper encoding? */
+ break;
}
+ length -= (length > 0);
+ p++;
}
+
+ endOfString:
if (nestingLevel != 0) {
- flags = TCL_DONT_USE_BRACES | BRACES_UNMATCHED;
+ /* Unbalanced braces! Cannot format with brace quoting. */
+ requireEscape = 1;
}
- *flagPtr = flags;
- /*
- * Allow enough space to backslash every character plus leave
- * two spaces for braces.
- */
+ /* We need at least as many bytes as are in the element value... */
+ bytesNeeded = p - src;
- return 2*(p-string) + 2;
+ if (requireEscape) {
+ /*
+ * We must use escape sequences. Add all the extra bytes needed
+ * to have room to create them.
+ */
+ bytesNeeded += extra;
+ /* Make room to escape leading #, if needed. */
+ if ((*src == '#') && !(*flagPtr & TCL_DONT_QUOTE_HASH)) {
+ bytesNeeded++;
+ }
+ *flagPtr = CONVERT_ESCAPE;
+ goto overflowCheck;
+ }
+ if (*flagPtr & CONVERT_ANY) {
+ /*
+ * The caller has not let us know what flags it will pass to
+ * TclConvertElement() so compute the max size we might need for
+ * any possible choice. Normally the formatting using escape
+ * sequences is the longer one, and a minimum "extra" value of 2
+ * makes sure we don't request too small a buffer in those edge
+ * cases where that's not true.
+ */
+ if (extra < 2) {
+ extra = 2;
+ }
+ *flagPtr &= ~CONVERT_ANY;
+ *flagPtr |= TCL_DONT_USE_BRACES;
+ }
+ if (forbidNone) {
+ /* We must request some form of quoting of escaping... */
+#if COMPAT
+ if (preferEscape && !preferBrace) {
+ /*
+ * If we are quoting solely due to ] or internal " characters
+ * use the CONVERT_MASK mode where we escape all special
+ * characters except for braces. "extra" counted space needed
+ * to escape braces too, so substract "braceCount" to get our
+ * actual needs.
+ */
+ bytesNeeded += (extra - braceCount);
+ /* Make room to escape leading #, if needed. */
+ if ((*src == '#') && !(*flagPtr & TCL_DONT_QUOTE_HASH)) {
+ bytesNeeded++;
+ }
+ /*
+ * If the caller reports it will direct TclConvertElement() to
+ * use full escapes on the element, add back the bytes needed to
+ * escape the braces.
+ */
+ if (*flagPtr & TCL_DONT_USE_BRACES) {
+ bytesNeeded += braceCount;
+ }
+ *flagPtr = CONVERT_MASK;
+ goto overflowCheck;
+ }
+#endif
+ if (*flagPtr & TCL_DONT_USE_BRACES) {
+ /*
+ * If the caller reports it will direct TclConvertElement() to
+ * use escapes, add the extra bytes needed to have room for them.
+ */
+ bytesNeeded += extra;
+ /* Make room to escape leading #, if needed. */
+ if ((*src == '#') && !(*flagPtr & TCL_DONT_QUOTE_HASH)) {
+ bytesNeeded++;
+ }
+ } else {
+ /* Add 2 bytes for room for the enclosing braces. */
+ bytesNeeded += 2;
+ }
+ *flagPtr = CONVERT_BRACE;
+ goto overflowCheck;
+ }
+
+ /* So far, no need to quote or escape anything. */
+ if ((*src == '#') && !(*flagPtr & TCL_DONT_QUOTE_HASH)) {
+ /* If we need to quote a leading #, make room to enclose in braces. */
+ bytesNeeded += 2;
+ }
+ *flagPtr = CONVERT_NONE;
+
+ overflowCheck:
+ if (bytesNeeded < 0) {
+ Tcl_Panic("TclScanElement: string length overflow");
+ }
+ return bytesNeeded;
}
/*
@@ -669,16 +1146,15 @@ Tcl_ScanCountedElement(string, length, flagPtr)
*
* Tcl_ConvertElement --
*
- * This is a companion procedure to Tcl_ScanElement. Given
- * the information produced by Tcl_ScanElement, this procedure
- * converts a string to a list element equal to that string.
+ * This is a companion function to Tcl_ScanElement. Given the information
+ * produced by Tcl_ScanElement, this function converts a string to a list
+ * element equal to that string.
*
* Results:
- * Information is copied to *dst in the form of a list element
- * identical to src (i.e. if Tcl_SplitList is applied to dst it
- * will produce a string identical to src). The return value is
- * a count of the number of characters copied (not including the
- * terminating NULL character).
+ * Information is copied to *dst in the form of a list element identical
+ * to src (i.e. if Tcl_SplitList is applied to dst it will produce a
+ * string identical to src). The return value is a count of the number of
+ * characters copied (not including the terminating NULL character).
*
* Side effects:
* None.
@@ -687,10 +1163,10 @@ Tcl_ScanCountedElement(string, length, flagPtr)
*/
int
-Tcl_ConvertElement(src, dst, flags)
- register CONST char *src; /* Source information for list element. */
- register char *dst; /* Place to put list-ified element. */
- register int flags; /* Flags produced by Tcl_ScanElement. */
+Tcl_ConvertElement(
+ register CONST char *src, /* Source information for list element. */
+ register char *dst, /* Place to put list-ified element. */
+ register int flags) /* Flags produced by Tcl_ScanElement. */
{
return Tcl_ConvertCountedElement(src, -1, dst, flags);
}
@@ -700,17 +1176,15 @@ Tcl_ConvertElement(src, dst, flags)
*
* Tcl_ConvertCountedElement --
*
- * This is a companion procedure to Tcl_ScanCountedElement. Given
- * the information produced by Tcl_ScanCountedElement, this
- * procedure converts a string to a list element equal to that
- * string.
+ * This is a companion function to Tcl_ScanCountedElement. Given the
+ * information produced by Tcl_ScanCountedElement, this function converts
+ * a string to a list element equal to that string.
*
* Results:
- * Information is copied to *dst in the form of a list element
- * identical to src (i.e. if Tcl_SplitList is applied to dst it
- * will produce a string identical to src). The return value is
- * a count of the number of characters copied (not including the
- * terminating NULL character).
+ * Information is copied to *dst in the form of a list element identical
+ * to src (i.e. if Tcl_SplitList is applied to dst it will produce a
+ * string identical to src). The return value is a count of the number of
+ * characters copied (not including the terminating NULL character).
*
* Side effects:
* None.
@@ -719,118 +1193,177 @@ Tcl_ConvertElement(src, dst, flags)
*/
int
-Tcl_ConvertCountedElement(src, length, dst, flags)
- register CONST char *src; /* Source information for list element. */
- int length; /* Number of bytes in src, or -1. */
- char *dst; /* Place to put list-ified element. */
- int flags; /* Flags produced by Tcl_ScanElement. */
+Tcl_ConvertCountedElement(
+ register CONST char *src, /* Source information for list element. */
+ int length, /* Number of bytes in src, or -1. */
+ char *dst, /* Place to put list-ified element. */
+ int flags) /* Flags produced by Tcl_ScanElement. */
{
- register char *p = dst;
- register CONST char *lastChar;
+ int numBytes = TclConvertElement(src, length, dst, flags);
+ dst[numBytes] = '\0';
+ return numBytes;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclConvertElement --
+ *
+ * This is a companion function to TclScanElement. Given the
+ * information produced by TclScanElement, this function converts
+ * a string to a list element equal to that string.
+ *
+ * Results:
+ * Information is copied to *dst in the form of a list element identical
+ * to src (i.e. if Tcl_SplitList is applied to dst it will produce a
+ * string identical to src). The return value is a count of the number of
+ * characters copied (not including the terminating NULL character).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
- /*
- * See the comment block at the beginning of the Tcl_ScanElement
- * code for details of how this works.
- */
+int TclConvertElement(
+ register CONST char *src, /* Source information for list element. */
+ int length, /* Number of bytes in src, or -1. */
+ char *dst, /* Place to put list-ified element. */
+ int flags) /* Flags produced by Tcl_ScanElement. */
+{
+ int conversion = flags & CONVERT_MASK;
+ char *p = dst;
- if (src && length == -1) {
- length = strlen(src);
+ /* Let the caller demand we use escape sequences rather than braces. */
+ if ((flags & TCL_DONT_USE_BRACES) && (conversion & CONVERT_BRACE)) {
+ conversion = CONVERT_ESCAPE;
}
- if ((src == NULL) || (length == 0)) {
- p[0] = '{';
- p[1] = '}';
- p[2] = 0;
- return 2;
+
+ /* No matter what the caller demands, empty string must be braced! */
+ if ((src == NULL) || (length == 0) || ((*src == '\0') && (length == -1))) {
+ src = tclEmptyStringRep;
+ length = 0;
+ conversion = CONVERT_BRACE;
+ }
+
+ /* Escape leading hash as needed and requested. */
+ if ((*src == '#') && !(flags & TCL_DONT_QUOTE_HASH)) {
+ if (conversion == CONVERT_ESCAPE) {
+ p[0] = '\\';
+ p[1] = '#';
+ p += 2;
+ src++;
+ length -= (length > 0);
+ } else {
+ conversion = CONVERT_BRACE;
+ }
}
- lastChar = src + length;
- if ((flags & USE_BRACES) && !(flags & TCL_DONT_USE_BRACES)) {
+
+ /* No escape or quoting needed. Copy the literal string value. */
+ if (conversion == CONVERT_NONE) {
+ if (length == -1) {
+ /* TODO: INT_MAX overflow? */
+ while (*src) {
+ *p++ = *src++;
+ }
+ return p - dst;
+ } else {
+ memcpy(dst, src, length);
+ return length;
+ }
+ }
+
+ /* Formatted string is original string enclosed in braces. */
+ if (conversion == CONVERT_BRACE) {
*p = '{';
p++;
- for ( ; src != lastChar; src++, p++) {
- *p = *src;
+ if (length == -1) {
+ /* TODO: INT_MAX overflow? */
+ while (*src) {
+ *p++ = *src++;
+ }
+ } else {
+ memcpy(p, src, length);
+ p += length;
}
*p = '}';
p++;
- } else {
- if (*src == '{') {
- /*
- * Can't have a leading brace unless the whole element is
- * enclosed in braces. Add a backslash before the brace.
- * Furthermore, this may destroy the balance between open
- * and close braces, so set BRACES_UNMATCHED.
- */
+ return p - dst;
+ }
- p[0] = '\\';
- p[1] = '{';
- p += 2;
- src++;
- flags |= BRACES_UNMATCHED;
- }
- for (; src != lastChar; src++) {
- switch (*src) {
- case ']':
- case '[':
- case '$':
- case ';':
- case ' ':
- case '\\':
- case '"':
- *p = '\\';
- p++;
- break;
- case '{':
- case '}':
- /*
- * It may not seem necessary to backslash braces, but
- * it is. The reason for this is that the resulting
- * list element may actually be an element of a sub-list
- * enclosed in braces (e.g. if Tcl_DStringStartSublist
- * has been invoked), so there may be a brace mismatch
- * if the braces aren't backslashed.
- */
-
- if (flags & BRACES_UNMATCHED) {
- *p = '\\';
- p++;
- }
- break;
- case '\f':
- *p = '\\';
- p++;
- *p = 'f';
- p++;
- continue;
- case '\n':
- *p = '\\';
- p++;
- *p = 'n';
- p++;
- continue;
- case '\r':
- *p = '\\';
- p++;
- *p = 'r';
- p++;
- continue;
- case '\t':
- *p = '\\';
- p++;
- *p = 't';
- p++;
- continue;
- case '\v':
- *p = '\\';
- p++;
- *p = 'v';
- p++;
- continue;
+ /* conversion == CONVERT_ESCAPE or CONVERT_MASK */
+
+ /* Formatted string is original string converted to escape sequences. */
+ for ( ; length; src++, length -= (length > 0)) {
+ switch (*src) {
+ case ']':
+ case '[':
+ case '$':
+ case ';':
+ case ' ':
+ case '\\':
+ case '"':
+ *p = '\\';
+ p++;
+ break;
+ case '{':
+ case '}':
+#if COMPAT
+ if (conversion == CONVERT_ESCAPE) {
+#endif
+ *p = '\\';
+ p++;
+#if COMPAT
}
- *p = *src;
+#endif
+ break;
+ case '\f':
+ *p = '\\';
+ p++;
+ *p = 'f';
+ p++;
+ continue;
+ case '\n':
+ *p = '\\';
+ p++;
+ *p = 'n';
+ p++;
+ continue;
+ case '\r':
+ *p = '\\';
p++;
+ *p = 'r';
+ p++;
+ continue;
+ case '\t':
+ *p = '\\';
+ p++;
+ *p = 't';
+ p++;
+ continue;
+ case '\v':
+ *p = '\\';
+ p++;
+ *p = 'v';
+ p++;
+ continue;
+ case '\0':
+ if (length == -1) {
+ return p - dst;
+ }
+ /*
+ * If we reach this point, there's an embedded NULL in the
+ * string range being processed, which should not happen when
+ * the encoding rules for Tcl strings are properly followed.
+ * If the day ever comes when we stop tolerating such things,
+ * this is where to put the Tcl_Panic().
+ */
+ break;
}
+ *p = *src;
+ p++;
}
- *p = '\0';
- return p-dst;
+ return p - dst;
}
/*
@@ -838,15 +1371,14 @@ Tcl_ConvertCountedElement(src, length, dst, flags)
*
* Tcl_Merge --
*
- * Given a collection of strings, merge them together into a
- * single string that has proper Tcl list structured (i.e.
- * Tcl_SplitList may be used to retrieve strings equal to the
- * original elements, and Tcl_Eval will parse the string back
- * into its original elements).
+ * Given a collection of strings, merge them together into a single
+ * string that has proper Tcl list structured (i.e. Tcl_SplitList may be
+ * used to retrieve strings equal to the original elements, and Tcl_Eval
+ * will parse the string back into its original elements).
*
* Results:
- * The return value is the address of a dynamically-allocated
- * string containing the merged list.
+ * The return value is the address of a dynamically-allocated string
+ * containing the merged list.
*
* Side effects:
* None.
@@ -855,16 +1387,25 @@ Tcl_ConvertCountedElement(src, length, dst, flags)
*/
char *
-Tcl_Merge(argc, argv)
- int argc; /* How many strings to merge. */
- CONST char * CONST *argv; /* Array of string values. */
+Tcl_Merge(
+ int argc, /* How many strings to merge. */
+ CONST char * CONST *argv) /* Array of string values. */
{
# define LOCAL_SIZE 20
- int localFlags[LOCAL_SIZE], *flagPtr;
- int numChars;
- char *result;
- char *dst;
- int i;
+ int localFlags[LOCAL_SIZE], *flagPtr = NULL;
+ int i, bytesNeeded = 0;
+ char *result, *dst;
+ const int maxFlags = UINT_MAX / sizeof(int);
+
+ if (argc == 0) {
+ /*
+ * Handle empty list case first, so logic of the general case
+ * can be simpler.
+ */
+ result = ckalloc(1);
+ result[0] = '\0';
+ return result;
+ }
/*
* Pass 1: estimate space, gather flags.
@@ -872,31 +1413,48 @@ Tcl_Merge(argc, argv)
if (argc <= LOCAL_SIZE) {
flagPtr = localFlags;
+ } else if (argc > maxFlags) {
+ /*
+ * We cannot allocate a large enough flag array to format this
+ * list in one pass. We could imagine converting this routine
+ * to a multi-pass implementation, but for sizeof(int) == 4,
+ * the limit is a max of 2^30 list elements and since each element
+ * is at least one byte formatted, and requires one byte space
+ * between it and the next one, that a minimum space requirement
+ * of 2^31 bytes, which is already INT_MAX. If we tried to format
+ * a list of > maxFlags elements, we're just going to overflow
+ * the size limits on the formatted string anyway, so just issue
+ * that same panic early.
+ */
+ Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
} else {
flagPtr = (int *) ckalloc((unsigned) argc*sizeof(int));
}
- numChars = 1;
for (i = 0; i < argc; i++) {
- numChars += Tcl_ScanElement(argv[i], &flagPtr[i]) + 1;
+ flagPtr[i] = ( i ? TCL_DONT_QUOTE_HASH : 0 );
+ bytesNeeded += TclScanElement(argv[i], -1, &flagPtr[i]);
+ if (bytesNeeded < 0) {
+ Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
+ }
+ }
+ if (bytesNeeded > INT_MAX - argc + 1) {
+ Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
}
+ bytesNeeded += argc;
/*
* Pass two: copy into the result area.
*/
- result = (char *) ckalloc((unsigned) numChars);
+ result = ckalloc((unsigned) bytesNeeded);
dst = result;
for (i = 0; i < argc; i++) {
- numChars = Tcl_ConvertElement(argv[i], dst, flagPtr[i]);
- dst += numChars;
+ flagPtr[i] |= ( i ? TCL_DONT_QUOTE_HASH : 0 );
+ dst += TclConvertElement(argv[i], -1, dst, flagPtr[i]);
*dst = ' ';
dst++;
}
- if (dst == result) {
- *dst = 0;
- } else {
- dst[-1] = 0;
- }
+ dst[-1] = 0;
if (flagPtr != localFlags) {
ckfree((char *) flagPtr);
@@ -912,10 +1470,10 @@ Tcl_Merge(argc, argv)
* Figure out how to handle a backslash sequence.
*
* Results:
- * The return value is the character that should be substituted
- * in place of the backslash sequence that starts at src. If
- * readPtr isn't NULL then it is filled in with a count of the
- * number of characters in the backslash sequence.
+ * The return value is the character that should be substituted in place
+ * of the backslash sequence that starts at src. If readPtr isn't NULL
+ * then it is filled in with a count of the number of characters in the
+ * backslash sequence.
*
* Side effects:
* None.
@@ -924,11 +1482,11 @@ Tcl_Merge(argc, argv)
*/
char
-Tcl_Backslash(src, readPtr)
- CONST char *src; /* Points to the backslash character of
- * a backslash sequence. */
- int *readPtr; /* Fill in with number of characters read
- * from src, unless NULL. */
+Tcl_Backslash(
+ CONST char *src, /* Points to the backslash character of a
+ * backslash sequence. */
+ int *readPtr) /* Fill in with number of characters read from
+ * src, unless NULL. */
{
char buf[TCL_UTF_MAX];
Tcl_UniChar ch;
@@ -941,73 +1499,228 @@ Tcl_Backslash(src, readPtr)
/*
*----------------------------------------------------------------------
*
+ * TclTrimRight --
+ * Takes two counted strings in the Tcl encoding which must both be
+ * null terminated. Conceptually trims from the right side of the
+ * first string all characters found in the second string.
+ *
+ * Results:
+ * The number of bytes to be removed from the end of the string.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclTrimRight(
+ const char *bytes, /* String to be trimmed... */
+ int numBytes, /* ...and its length in bytes */
+ const char *trim, /* String of trim characters... */
+ int numTrim) /* ...and its length in bytes */
+{
+ const char *p = bytes + numBytes;
+ int pInc;
+
+ if ((bytes[numBytes] != '\0') || (trim[numTrim] != '\0')) {
+ Tcl_Panic("TclTrimRight works only on null-terminated strings");
+ }
+
+ /* Empty strings -> nothing to do */
+ if ((numBytes == 0) || (numTrim == 0)) {
+ return 0;
+ }
+
+ /* Outer loop: iterate over string to be trimmed */
+ do {
+ Tcl_UniChar ch1;
+ const char *q = trim;
+ int bytesLeft = numTrim;
+
+ p = Tcl_UtfPrev(p, bytes);
+ pInc = TclUtfToUniChar(p, &ch1);
+
+ /* Inner loop: scan trim string for match to current character */
+ do {
+ Tcl_UniChar ch2;
+ int qInc = TclUtfToUniChar(q, &ch2);
+
+ if (ch1 == ch2) {
+ break;
+ }
+
+ q += qInc;
+ bytesLeft -= qInc;
+ } while (bytesLeft);
+
+ if (bytesLeft == 0) {
+ /* No match; trim task done; *p is last non-trimmed char */
+ p += pInc;
+ break;
+ }
+ } while (p > bytes);
+
+ return numBytes - (p - bytes);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclTrimLeft --
+ * Takes two counted strings in the Tcl encoding which must both be
+ * null terminated. Conceptually trims from the left side of the
+ * first string all characters found in the second string.
+ *
+ * Results:
+ * The number of bytes to be removed from the start of the string.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclTrimLeft(
+ const char *bytes, /* String to be trimmed... */
+ int numBytes, /* ...and its length in bytes */
+ const char *trim, /* String of trim characters... */
+ int numTrim) /* ...and its length in bytes */
+{
+ const char *p = bytes;
+
+ if ((bytes[numBytes] != '\0') || (trim[numTrim] != '\0')) {
+ Tcl_Panic("TclTrimLeft works only on null-terminated strings");
+ }
+
+ /* Empty strings -> nothing to do */
+ if ((numBytes == 0) || (numTrim == 0)) {
+ return 0;
+ }
+
+ /* Outer loop: iterate over string to be trimmed */
+ do {
+ Tcl_UniChar ch1;
+ int pInc = TclUtfToUniChar(p, &ch1);
+ const char *q = trim;
+ int bytesLeft = numTrim;
+
+ /* Inner loop: scan trim string for match to current character */
+ do {
+ Tcl_UniChar ch2;
+ int qInc = TclUtfToUniChar(q, &ch2);
+
+ if (ch1 == ch2) {
+ break;
+ }
+
+ q += qInc;
+ bytesLeft -= qInc;
+ } while (bytesLeft);
+
+ if (bytesLeft == 0) {
+ /* No match; trim task done; *p is first non-trimmed char */
+ break;
+ }
+
+ p += pInc;
+ numBytes -= pInc;
+ } while (numBytes);
+
+ return p - bytes;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tcl_Concat --
*
* Concatenate a set of strings into a single large string.
*
* Results:
- * The return value is dynamically-allocated string containing
- * a concatenation of all the strings in argv, with spaces between
- * the original argv elements.
+ * The return value is dynamically-allocated string containing a
+ * concatenation of all the strings in argv, with spaces between the
+ * original argv elements.
*
* Side effects:
- * Memory is allocated for the result; the caller is responsible
- * for freeing the memory.
+ * Memory is allocated for the result; the caller is responsible for
+ * freeing the memory.
*
*----------------------------------------------------------------------
*/
+/* The whitespace characters trimmed during [concat] operations */
+#define CONCAT_WS " \f\v\r\t\n"
+#define CONCAT_WS_SIZE (int) (sizeof(CONCAT_WS "") - 1)
+
char *
-Tcl_Concat(argc, argv)
- int argc; /* Number of strings to concatenate. */
- CONST char * CONST *argv; /* Array of strings to concatenate. */
+Tcl_Concat(
+ int argc, /* Number of strings to concatenate. */
+ CONST char * CONST *argv) /* Array of strings to concatenate. */
{
- int totalSize, i;
- char *p;
- char *result;
+ int i, needSpace = 0, bytesNeeded = 0;
+ char *result, *p;
- for (totalSize = 1, i = 0; i < argc; i++) {
- totalSize += strlen(argv[i]) + 1;
- }
- result = (char *) ckalloc((unsigned) totalSize);
+ /* Dispose of the empty result corner case first to simplify later code */
if (argc == 0) {
- *result = '\0';
+ result = (char *) ckalloc(1);
+ result[0] = '\0';
return result;
}
- for (p = result, i = 0; i < argc; i++) {
- CONST char *element;
- int length;
+ /* First allocate the result buffer at the size required */
+ for (i = 0; i < argc; i++) {
+ bytesNeeded += strlen(argv[i]);
+ if (bytesNeeded < 0) {
+ Tcl_Panic("Tcl_Concat: max size of Tcl value exceeded");
+ }
+ }
+ if (bytesNeeded + argc - 1 < 0) {
/*
- * Clip white space off the front and back of the string
- * to generate a neater result, and ignore any empty
- * elements.
+ * Panic test could be tighter, but not going to bother for
+ * this legacy routine.
*/
+ Tcl_Panic("Tcl_Concat: max size of Tcl value exceeded");
+ }
+ /* All element bytes + (argc - 1) spaces + 1 terminating NULL */
+ result = (char *) ckalloc((unsigned) (bytesNeeded + argc));
+ for (p = result, i = 0; i < argc; i++) {
+ int trim, elemLength;
+ const char *element;
+
element = argv[i];
- while (isspace(UCHAR(*element))) { /* INTL: ISO space. */
- element++;
- }
- for (length = strlen(element);
- (length > 0)
- && (isspace(UCHAR(element[length-1]))) /* INTL: ISO space. */
- && ((length < 2) || (element[length-2] != '\\'));
- length--) {
- /* Null loop body. */
- }
- if (length == 0) {
+ elemLength = strlen(argv[i]);
+
+ /* Trim away the leading whitespace */
+ trim = TclTrimLeft(element, elemLength, CONCAT_WS, CONCAT_WS_SIZE);
+ element += trim;
+ elemLength -= trim;
+
+ /*
+ * Trim away the trailing whitespace. Do not permit trimming
+ * to expose a final backslash character.
+ */
+
+ trim = TclTrimRight(element, elemLength, CONCAT_WS, CONCAT_WS_SIZE);
+ trim -= trim && (element[elemLength - trim - 1] == '\\');
+ elemLength -= trim;
+
+ /* If we're left with empty element after trimming, do nothing */
+ if (elemLength == 0) {
continue;
}
- memcpy((VOID *) p, (VOID *) element, (size_t) length);
- p += length;
- *p = ' ';
- p++;
- }
- if (p != result) {
- p[-1] = 0;
- } else {
- *p = 0;
+
+ /* Append to the result with space if needed */
+ if (needSpace) {
+ *p++ = ' ';
+ }
+ memcpy(p, element, (size_t) elemLength);
+ p += elemLength;
+ needSpace = 1;
}
+ *p = '\0';
return result;
}
@@ -1020,8 +1733,8 @@ Tcl_Concat(argc, argv)
* object with spaces between the original strings.
*
* Results:
- * The return value is a new string object containing a concatenation
- * of the strings in objv. Its ref count is zero.
+ * The return value is a new string object containing a concatenation of
+ * the strings in objv. Its ref count is zero.
*
* Side effects:
* A new object is created.
@@ -1030,27 +1743,29 @@ Tcl_Concat(argc, argv)
*/
Tcl_Obj *
-Tcl_ConcatObj(objc, objv)
- int objc; /* Number of objects to concatenate. */
- Tcl_Obj *CONST objv[]; /* Array of objects to concatenate. */
+Tcl_ConcatObj(
+ int objc, /* Number of objects to concatenate. */
+ Tcl_Obj *CONST objv[]) /* Array of objects to concatenate. */
{
- int allocSize, finalSize, length, elemLength, i;
- char *p;
- char *element;
- char *concatStr;
- Tcl_Obj *objPtr;
+ int i, elemLength, needSpace = 0, bytesNeeded = 0;
+ const char *element;
+ Tcl_Obj *objPtr, *resPtr;
/*
- * Check first to see if all the items are of list type. If so,
- * we will concat them together as lists, and return a list object.
- * This is only valid when the lists have no current string
- * representation, since we don't know what the original type was.
- * An original string rep may have lost some whitespace info when
- * converted which could be important.
+ * Check first to see if all the items are of list type or empty. If so,
+ * we will concat them together as lists, and return a list object. This
+ * is only valid when the lists are in canonical form.
*/
+
for (i = 0; i < objc; i++) {
+ int length;
+
objPtr = objv[i];
- if ((objPtr->typePtr != &tclListType) || (objPtr->bytes != NULL)) {
+ if (TclListObjIsCanonical(objPtr)) {
+ continue;
+ }
+ Tcl_GetStringFromObj(objPtr, &length);
+ if (length > 0) {
break;
}
}
@@ -1058,92 +1773,90 @@ Tcl_ConcatObj(objc, objv)
Tcl_Obj **listv;
int listc;
- objPtr = Tcl_NewListObj(0, NULL);
+ resPtr = NULL;
for (i = 0; i < objc; i++) {
/*
- * Tcl_ListObjAppendList could be used here, but this saves
- * us a bit of type checking (since we've already done it)
- * Use of INT_MAX tells us to always put the new stuff on
- * the end. It will be set right in Tcl_ListObjReplace.
+ * Tcl_ListObjAppendList could be used here, but this saves us a
+ * bit of type checking (since we've already done it). Use of
+ * INT_MAX tells us to always put the new stuff on the end. It
+ * will be set right in Tcl_ListObjReplace.
+ * Note that all objs at this point are either lists or have an
+ * empty string rep.
*/
- Tcl_ListObjGetElements(NULL, objv[i], &listc, &listv);
- Tcl_ListObjReplace(NULL, objPtr, INT_MAX, 0, listc, listv);
- }
- return objPtr;
- }
- allocSize = 0;
- for (i = 0; i < objc; i++) {
- objPtr = objv[i];
- element = Tcl_GetStringFromObj(objPtr, &length);
- if ((element != NULL) && (length > 0)) {
- allocSize += (length + 1);
+ objPtr = objv[i];
+ if (objPtr->bytes && objPtr->length == 0) {
+ continue;
+ }
+ TclListObjGetElements(NULL, objPtr, &listc, &listv);
+ if (listc) {
+ if (resPtr) {
+ Tcl_ListObjReplace(NULL, resPtr, INT_MAX, 0, listc, listv);
+ } else {
+ resPtr = TclListObjCopy(NULL, objPtr);
+ }
+ }
}
- }
- if (allocSize == 0) {
- allocSize = 1; /* enough for the NULL byte at end */
+ if (!resPtr) {
+ resPtr = Tcl_NewObj();
+ }
+ return resPtr;
}
/*
- * Allocate storage for the concatenated result. Note that allocSize
- * is one more than the total number of characters, and so includes
- * room for the terminating NULL byte.
+ * Something cannot be determined to be safe, so build the concatenation
+ * the slow way, using the string representations.
*/
-
- concatStr = (char *) ckalloc((unsigned) allocSize);
+ /* First try to pre-allocate the size required */
+ for (i = 0; i < objc; i++) {
+ element = TclGetStringFromObj(objv[i], &elemLength);
+ bytesNeeded += elemLength;
+ if (bytesNeeded < 0) {
+ break;
+ }
+ }
/*
- * Now concatenate the elements. Clip white space off the front and back
- * to generate a neater result, and ignore any empty elements. Also put
- * a null byte at the end.
+ * Does not matter if this fails, will simply try later to build up
+ * the string with each Append reallocating as needed with the usual
+ * string append algorithm. When that fails it will report the error.
*/
+ TclNewObj(resPtr);
+ Tcl_AttemptSetObjLength(resPtr, bytesNeeded + objc - 1);
+ Tcl_SetObjLength(resPtr, 0);
- finalSize = 0;
- if (objc == 0) {
- *concatStr = '\0';
- } else {
- p = concatStr;
- for (i = 0; i < objc; i++) {
- objPtr = objv[i];
- element = Tcl_GetStringFromObj(objPtr, &elemLength);
- while ((elemLength > 0) && (UCHAR(*element) < 127)
- && isspace(UCHAR(*element))) { /* INTL: ISO C space. */
- element++;
- elemLength--;
- }
+ for (i = 0; i < objc; i++) {
+ int trim;
+
+ element = TclGetStringFromObj(objv[i], &elemLength);
- /*
- * Trim trailing white space. But, be careful not to trim
- * a space character if it is preceded by a backslash: in
- * this case it could be significant.
- */
+ /* Trim away the leading whitespace */
+ trim = TclTrimLeft(element, elemLength, CONCAT_WS, CONCAT_WS_SIZE);
+ element += trim;
+ elemLength -= trim;
- while ((elemLength > 0) && (UCHAR(element[elemLength-1]) < 127)
- && isspace(UCHAR(element[elemLength-1])) /* INTL: ISO C space. */
- && ((elemLength < 2) || (element[elemLength-2] != '\\'))) {
- elemLength--;
- }
- if (elemLength == 0) {
- continue; /* nothing left of this element */
- }
- memcpy((VOID *) p, (VOID *) element, (size_t) elemLength);
- p += elemLength;
- *p = ' ';
- p++;
- finalSize += (elemLength + 1);
- }
- if (p != concatStr) {
- p[-1] = 0;
- finalSize -= 1; /* we overwrote the final ' ' */
- } else {
- *p = 0;
- }
+ /*
+ * Trim away the trailing whitespace. Do not permit trimming
+ * to expose a final backslash character.
+ */
+
+ trim = TclTrimRight(element, elemLength, CONCAT_WS, CONCAT_WS_SIZE);
+ trim -= trim && (element[elemLength - trim - 1] == '\\');
+ elemLength -= trim;
+
+ /* If we're left with empty element after trimming, do nothing */
+ if (elemLength == 0) {
+ continue;
+ }
+
+ /* Append to the result with space if needed */
+ if (needSpace) {
+ Tcl_AppendToObj(resPtr, " ", 1);
+ }
+ Tcl_AppendToObj(resPtr, element, elemLength);
+ needSpace = 1;
}
-
- TclNewObj(objPtr);
- objPtr->bytes = concatStr;
- objPtr->length = finalSize;
- return objPtr;
+ return resPtr;
}
/*
@@ -1154,10 +1867,9 @@ Tcl_ConcatObj(objc, objv)
* See if a particular string matches a particular pattern.
*
* Results:
- * The return value is 1 if string matches pattern, and
- * 0 otherwise. The matching operation permits the following
- * special characters in the pattern: *?\[] (see the manual
- * entry for details on what these mean).
+ * The return value is 1 if string matches pattern, and 0 otherwise. The
+ * matching operation permits the following special characters in the
+ * pattern: *?\[] (see the manual entry for details on what these mean).
*
* Side effects:
* None.
@@ -1166,12 +1878,12 @@ Tcl_ConcatObj(objc, objv)
*/
int
-Tcl_StringMatch(string, pattern)
- CONST char *string; /* String. */
- CONST char *pattern; /* Pattern, which may contain special
+Tcl_StringMatch(
+ CONST char *str, /* String. */
+ CONST char *pattern) /* Pattern, which may contain special
* characters. */
{
- return Tcl_StringCaseMatch(string, pattern, 0);
+ return Tcl_StringCaseMatch(str, pattern, 0);
}
/*
@@ -1179,14 +1891,13 @@ Tcl_StringMatch(string, pattern)
*
* Tcl_StringCaseMatch --
*
- * See if a particular string matches a particular pattern.
- * Allows case insensitivity.
+ * See if a particular string matches a particular pattern. Allows case
+ * insensitivity.
*
* Results:
- * The return value is 1 if string matches pattern, and
- * 0 otherwise. The matching operation permits the following
- * special characters in the pattern: *?\[] (see the manual
- * entry for details on what these mean).
+ * The return value is 1 if string matches pattern, and 0 otherwise. The
+ * matching operation permits the following special characters in the
+ * pattern: *?\[] (see the manual entry for details on what these mean).
*
* Side effects:
* None.
@@ -1195,127 +1906,133 @@ Tcl_StringMatch(string, pattern)
*/
int
-Tcl_StringCaseMatch(string, pattern, nocase)
- CONST char *string; /* String. */
- CONST char *pattern; /* Pattern, which may contain special
+Tcl_StringCaseMatch(
+ CONST char *str, /* String. */
+ CONST char *pattern, /* Pattern, which may contain special
* characters. */
- int nocase; /* 0 for case sensitive, 1 for insensitive */
+ int nocase) /* 0 for case sensitive, 1 for insensitive */
{
int p, charLen;
CONST char *pstart = pattern;
Tcl_UniChar ch1, ch2;
-
+
while (1) {
p = *pattern;
-
+
/*
- * See if we're at the end of both the pattern and the string. If
- * so, we succeeded. If we're at the end of the pattern but not at
- * the end of the string, we failed.
+ * See if we're at the end of both the pattern and the string. If so,
+ * we succeeded. If we're at the end of the pattern but not at the end
+ * of the string, we failed.
*/
-
+
if (p == '\0') {
- return (*string == '\0');
+ return (*str == '\0');
}
- if ((*string == '\0') && (p != '*')) {
+ if ((*str == '\0') && (p != '*')) {
return 0;
}
/*
- * Check for a "*" as the next pattern character. It matches
- * any substring. We handle this by calling ourselves
- * recursively for each postfix of string, until either we
- * match or we reach the end of the string.
+ * Check for a "*" as the next pattern character. It matches any
+ * substring. We handle this by calling ourselves recursively for each
+ * postfix of string, until either we match or we reach the end of the
+ * string.
*/
-
+
if (p == '*') {
/*
* Skip all successive *'s in the pattern
*/
+
while (*(++pattern) == '*') {}
p = *pattern;
if (p == '\0') {
return 1;
}
+
/*
* This is a special case optimization for single-byte utf.
*/
+
if (UCHAR(*pattern) < 0x80) {
ch2 = (Tcl_UniChar)
- (nocase ? tolower(UCHAR(*pattern)) : UCHAR(*pattern));
+ (nocase ? tolower(UCHAR(*pattern)) : UCHAR(*pattern));
} else {
Tcl_UtfToUniChar(pattern, &ch2);
if (nocase) {
ch2 = Tcl_UniCharToLower(ch2);
}
}
+
while (1) {
/*
* Optimization for matching - cruise through the string
* quickly if the next char in the pattern isn't a special
* character
*/
+
if ((p != '[') && (p != '?') && (p != '\\')) {
if (nocase) {
- while (*string) {
- charLen = TclUtfToUniChar(string, &ch1);
+ while (*str) {
+ charLen = TclUtfToUniChar(str, &ch1);
if (ch2==ch1 || ch2==Tcl_UniCharToLower(ch1)) {
break;
}
- string += charLen;
+ str += charLen;
}
} else {
/*
* There's no point in trying to make this code
- * shorter, as the number of bytes you want to
- * compare each time is non-constant.
+ * shorter, as the number of bytes you want to compare
+ * each time is non-constant.
*/
- while (*string) {
- charLen = TclUtfToUniChar(string, &ch1);
+
+ while (*str) {
+ charLen = TclUtfToUniChar(str, &ch1);
if (ch2 == ch1) {
break;
}
- string += charLen;
+ str += charLen;
}
}
}
- if (Tcl_StringCaseMatch(string, pattern, nocase)) {
+ if (Tcl_StringCaseMatch(str, pattern, nocase)) {
return 1;
}
- if (*string == '\0') {
+ if (*str == '\0') {
return 0;
}
- string += TclUtfToUniChar(string, &ch1);
+ str += TclUtfToUniChar(str, &ch1);
}
}
/*
- * Check for a "?" as the next pattern character. It matches
- * any single character.
+ * Check for a "?" as the next pattern character. It matches any
+ * single character.
*/
if (p == '?') {
pattern++;
- string += TclUtfToUniChar(string, &ch1);
+ str += TclUtfToUniChar(str, &ch1);
continue;
}
/*
- * Check for a "[" as the next pattern character. It is followed
- * by a list of characters that are acceptable, or by a range
- * (two characters separated by "-").
+ * Check for a "[" as the next pattern character. It is followed by a
+ * list of characters that are acceptable, or by a range (two
+ * characters separated by "-").
*/
if (p == '[') {
Tcl_UniChar startChar, endChar;
pattern++;
- if (UCHAR(*string) < 0x80) {
+ if (UCHAR(*str) < 0x80) {
ch1 = (Tcl_UniChar)
- (nocase ? tolower(UCHAR(*string)) : UCHAR(*string));
- string++;
+ (nocase ? tolower(UCHAR(*str)) : UCHAR(*str));
+ str++;
} else {
- string += Tcl_UtfToUniChar(string, &ch1);
+ str += Tcl_UtfToUniChar(str, &ch1);
if (nocase) {
ch1 = Tcl_UniCharToLower(ch1);
}
@@ -1325,8 +2042,8 @@ Tcl_StringCaseMatch(string, pattern, nocase)
return 0;
}
if (UCHAR(*pattern) < 0x80) {
- startChar = (Tcl_UniChar)
- (nocase ? tolower(UCHAR(*pattern)) : UCHAR(*pattern));
+ startChar = (Tcl_UniChar) (nocase
+ ? tolower(UCHAR(*pattern)) : UCHAR(*pattern));
pattern++;
} else {
pattern += Tcl_UtfToUniChar(pattern, &startChar);
@@ -1340,9 +2057,8 @@ Tcl_StringCaseMatch(string, pattern, nocase)
return 0;
}
if (UCHAR(*pattern) < 0x80) {
- endChar = (Tcl_UniChar)
- (nocase ? tolower(UCHAR(*pattern))
- : UCHAR(*pattern));
+ endChar = (Tcl_UniChar) (nocase
+ ? tolower(UCHAR(*pattern)) : UCHAR(*pattern));
pattern++;
} else {
pattern += Tcl_UtfToUniChar(pattern, &endChar);
@@ -1374,8 +2090,8 @@ Tcl_StringCaseMatch(string, pattern, nocase)
}
/*
- * If the next pattern character is '\', just strip off the '\'
- * so we do exact matching on the character that follows.
+ * If the next pattern character is '\', just strip off the '\' so we
+ * do exact matching on the character that follows.
*/
if (p == '\\') {
@@ -1386,11 +2102,11 @@ Tcl_StringCaseMatch(string, pattern, nocase)
}
/*
- * There's no special character. Just make sure that the next
- * bytes of each string match.
+ * There's no special character. Just make sure that the next bytes of
+ * each string match.
*/
- string += TclUtfToUniChar(string, &ch1);
+ str += TclUtfToUniChar(str, &ch1);
pattern += TclUtfToUniChar(pattern, &ch2);
if (nocase) {
if (Tcl_UniCharToLower(ch1) != Tcl_UniCharToLower(ch2)) {
@@ -1405,14 +2121,16 @@ Tcl_StringCaseMatch(string, pattern, nocase)
/*
*----------------------------------------------------------------------
*
- * TclMatchIsTrivial --
+ * TclByteArrayMatch --
*
- * Test whether a particular glob pattern is a trivial pattern.
- * (i.e. where matching is the same as equality testing).
+ * See if a particular string matches a particular pattern. Does not
+ * allow for case insensitivity.
+ * Parallels tclUtf.c:TclUniCharMatch, adjusted for char* and sans nocase.
*
* Results:
- * A boolean indicating whether the pattern is free of all of the
- * glob special chars.
+ * The return value is 1 if string matches pattern, and 0 otherwise. The
+ * matching operation permits the following special characters in the
+ * pattern: *?\[] (see the manual entry for details on what these mean).
*
* Side effects:
* None.
@@ -1421,32 +2139,222 @@ Tcl_StringCaseMatch(string, pattern, nocase)
*/
int
-TclMatchIsTrivial(pattern)
- CONST char *pattern;
+TclByteArrayMatch(
+ const unsigned char *string, /* String. */
+ int strLen, /* Length of String */
+ const unsigned char *pattern, /* Pattern, which may contain special
+ * characters. */
+ int ptnLen, /* Length of Pattern */
+ int flags)
{
- CONST char *p = pattern;
+ const unsigned char *stringEnd, *patternEnd;
+ unsigned char p;
+
+ stringEnd = string + strLen;
+ patternEnd = pattern + ptnLen;
while (1) {
- switch (*p++) {
- case '\0':
- return 1;
- case '*':
- case '?':
- case '[':
- case '\\':
+ /*
+ * See if we're at the end of both the pattern and the string. If so,
+ * we succeeded. If we're at the end of the pattern but not at the end
+ * of the string, we failed.
+ */
+
+ if (pattern == patternEnd) {
+ return (string == stringEnd);
+ }
+ p = *pattern;
+ if ((string == stringEnd) && (p != '*')) {
+ return 0;
+ }
+
+ /*
+ * Check for a "*" as the next pattern character. It matches any
+ * substring. We handle this by skipping all the characters up to the
+ * next matching one in the pattern, and then calling ourselves
+ * recursively for each postfix of string, until either we match or we
+ * reach the end of the string.
+ */
+
+ if (p == '*') {
+ /*
+ * Skip all successive *'s in the pattern.
+ */
+
+ while ((++pattern < patternEnd) && (*pattern == '*')) {
+ /* empty body */
+ }
+ if (pattern == patternEnd) {
+ return 1;
+ }
+ p = *pattern;
+ while (1) {
+ /*
+ * Optimization for matching - cruise through the string
+ * quickly if the next char in the pattern isn't a special
+ * character.
+ */
+
+ if ((p != '[') && (p != '?') && (p != '\\')) {
+ while ((string < stringEnd) && (p != *string)) {
+ string++;
+ }
+ }
+ if (TclByteArrayMatch(string, stringEnd - string,
+ pattern, patternEnd - pattern, 0)) {
+ return 1;
+ }
+ if (string == stringEnd) {
+ return 0;
+ }
+ string++;
+ }
+ }
+
+ /*
+ * Check for a "?" as the next pattern character. It matches any
+ * single character.
+ */
+
+ if (p == '?') {
+ pattern++;
+ string++;
+ continue;
+ }
+
+ /*
+ * Check for a "[" as the next pattern character. It is followed by a
+ * list of characters that are acceptable, or by a range (two
+ * characters separated by "-").
+ */
+
+ if (p == '[') {
+ unsigned char ch1, startChar, endChar;
+
+ pattern++;
+ ch1 = *string;
+ string++;
+ while (1) {
+ if ((*pattern == ']') || (pattern == patternEnd)) {
+ return 0;
+ }
+ startChar = *pattern;
+ pattern++;
+ if (*pattern == '-') {
+ pattern++;
+ if (pattern == patternEnd) {
+ return 0;
+ }
+ endChar = *pattern;
+ pattern++;
+ if (((startChar <= ch1) && (ch1 <= endChar))
+ || ((endChar <= ch1) && (ch1 <= startChar))) {
+ /*
+ * Matches ranges of form [a-z] or [z-a].
+ */
+ break;
+ }
+ } else if (startChar == ch1) {
+ break;
+ }
+ }
+ while (*pattern != ']') {
+ if (pattern == patternEnd) {
+ pattern--;
+ break;
+ }
+ pattern++;
+ }
+ pattern++;
+ continue;
+ }
+
+ /*
+ * If the next pattern character is '\', just strip off the '\' so we
+ * do exact matching on the character that follows.
+ */
+
+ if (p == '\\') {
+ if (++pattern == patternEnd) {
+ return 0;
+ }
+ }
+
+ /*
+ * There's no special character. Just make sure that the next bytes of
+ * each string match.
+ */
+
+ if (*string != *pattern) {
return 0;
}
+ string++;
+ pattern++;
}
}
/*
*----------------------------------------------------------------------
*
+ * TclStringMatchObj --
+ *
+ * See if a particular string matches a particular pattern.
+ * Allows case insensitivity. This is the generic multi-type handler
+ * for the various matching algorithms.
+ *
+ * Results:
+ * The return value is 1 if string matches pattern, and 0 otherwise. The
+ * matching operation permits the following special characters in the
+ * pattern: *?\[] (see the manual entry for details on what these mean).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclStringMatchObj(
+ Tcl_Obj *strObj, /* string object. */
+ Tcl_Obj *ptnObj, /* pattern object. */
+ int flags) /* Only TCL_MATCH_NOCASE should be passed or 0. */
+{
+ int match, length, plen;
+
+ /*
+ * Promote based on the type of incoming object.
+ * XXX: Currently doesn't take advantage of exact-ness that
+ * XXX: TclReToGlob tells us about
+ trivial = nocase ? 0 : TclMatchIsTrivial(TclGetString(ptnObj));
+ */
+
+ if ((strObj->typePtr == &tclStringType)) {
+ Tcl_UniChar *udata, *uptn;
+
+ udata = Tcl_GetUnicodeFromObj(strObj, &length);
+ uptn = Tcl_GetUnicodeFromObj(ptnObj, &plen);
+ match = TclUniCharMatch(udata, length, uptn, plen, flags);
+ } else if ((strObj->typePtr == &tclByteArrayType) && !flags) {
+ unsigned char *data, *ptn;
+
+ data = Tcl_GetByteArrayFromObj(strObj, &length);
+ ptn = Tcl_GetByteArrayFromObj(ptnObj, &plen);
+ match = TclByteArrayMatch(data, length, ptn, plen, 0);
+ } else {
+ match = Tcl_StringCaseMatch(TclGetString(strObj),
+ TclGetString(ptnObj), flags);
+ }
+ return match;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tcl_DStringInit --
*
- * Initializes a dynamic string, discarding any previous contents
- * of the string (Tcl_DStringFree should have been called already
- * if the dynamic string was previously in use).
+ * Initializes a dynamic string, discarding any previous contents of the
+ * string (Tcl_DStringFree should have been called already if the dynamic
+ * string was previously in use).
*
* Results:
* None.
@@ -1458,8 +2366,8 @@ TclMatchIsTrivial(pattern)
*/
void
-Tcl_DStringInit(dsPtr)
- Tcl_DString *dsPtr; /* Pointer to structure for dynamic string. */
+Tcl_DStringInit(
+ Tcl_DString *dsPtr) /* Pointer to structure for dynamic string. */
{
dsPtr->string = dsPtr->staticSpace;
dsPtr->length = 0;
@@ -1472,66 +2380,63 @@ Tcl_DStringInit(dsPtr)
*
* Tcl_DStringAppend --
*
- * Append more characters to the current value of a dynamic string.
+ * Append more bytes to the current value of a dynamic string.
*
* Results:
* The return value is a pointer to the dynamic string's new value.
*
* Side effects:
- * Length bytes from string (or all of string if length is less
- * than zero) are added to the current value of the string. Memory
- * gets reallocated if needed to accomodate the string's new size.
+ * Length bytes from "bytes" (or all of "bytes" if length is less than
+ * zero) are added to the current value of the string. Memory gets
+ * reallocated if needed to accomodate the string's new size.
*
*----------------------------------------------------------------------
*/
char *
-Tcl_DStringAppend(dsPtr, string, length)
- Tcl_DString *dsPtr; /* Structure describing dynamic string. */
- CONST char *string; /* String to append. If length is -1 then
- * this must be null-terminated. */
- int length; /* Number of characters from string to
- * append. If < 0, then append all of string,
- * up to null at end. */
+Tcl_DStringAppend(
+ Tcl_DString *dsPtr, /* Structure describing dynamic string. */
+ CONST char *bytes, /* String to append. If length is -1 then this
+ * must be null-terminated. */
+ int length) /* Number of bytes from "bytes" to append. If
+ * < 0, then append all of bytes, up to null
+ * at end. */
{
int newSize;
char *dst;
CONST char *end;
if (length < 0) {
- length = strlen(string);
+ length = strlen(bytes);
}
newSize = length + dsPtr->length;
/*
- * Allocate a larger buffer for the string if the current one isn't
- * large enough. Allocate extra space in the new buffer so that there
- * will be room to grow before we have to allocate again.
+ * Allocate a larger buffer for the string if the current one isn't large
+ * enough. Allocate extra space in the new buffer so that there will be
+ * room to grow before we have to allocate again.
*/
if (newSize >= dsPtr->spaceAvl) {
dsPtr->spaceAvl = newSize * 2;
if (dsPtr->string == dsPtr->staticSpace) {
- char *newString;
+ char *newString = ckalloc((unsigned) dsPtr->spaceAvl);
- newString = (char *) ckalloc((unsigned) dsPtr->spaceAvl);
- memcpy((VOID *) newString, (VOID *) dsPtr->string,
- (size_t) dsPtr->length);
+ memcpy(newString, dsPtr->string, (size_t) dsPtr->length);
dsPtr->string = newString;
} else {
- dsPtr->string = (char *) ckrealloc((VOID *) dsPtr->string,
+ dsPtr->string = ckrealloc((void *) dsPtr->string,
(size_t) dsPtr->spaceAvl);
}
}
/*
- * Copy the new string into the buffer at the end of the old
- * one.
+ * Copy the new string into the buffer at the end of the old one.
*/
- for (dst = dsPtr->string + dsPtr->length, end = string+length;
- string < end; string++, dst++) {
- *dst = *string;
+ for (dst = dsPtr->string + dsPtr->length, end = bytes+length;
+ bytes < end; bytes++, dst++) {
+ *dst = *bytes;
}
*dst = '\0';
dsPtr->length += length;
@@ -1549,62 +2454,67 @@ Tcl_DStringAppend(dsPtr, string, length)
* The return value is a pointer to the dynamic string's new value.
*
* Side effects:
- * String is reformatted as a list element and added to the current
- * value of the string. Memory gets reallocated if needed to
- * accomodate the string's new size.
+ * String is reformatted as a list element and added to the current value
+ * of the string. Memory gets reallocated if needed to accomodate the
+ * string's new size.
*
*----------------------------------------------------------------------
*/
char *
-Tcl_DStringAppendElement(dsPtr, string)
- Tcl_DString *dsPtr; /* Structure describing dynamic string. */
- CONST char *string; /* String to append. Must be
+Tcl_DStringAppendElement(
+ Tcl_DString *dsPtr, /* Structure describing dynamic string. */
+ CONST char *element) /* String to append. Must be
* null-terminated. */
{
- int newSize, flags, strSize;
- char *dst;
-
- strSize = ((string == NULL) ? 0 : strlen(string));
- newSize = Tcl_ScanCountedElement(string, strSize, &flags)
- + dsPtr->length + 1;
+ char *dst = dsPtr->string + dsPtr->length;
+ int needSpace = TclNeedSpace(dsPtr->string, dst);
+ int flags = needSpace ? TCL_DONT_QUOTE_HASH : 0;
+ int newSize = dsPtr->length + needSpace
+ + TclScanElement(element, -1, &flags);
/*
- * Allocate a larger buffer for the string if the current one isn't
- * large enough. Allocate extra space in the new buffer so that there
- * will be room to grow before we have to allocate again.
- * SPECIAL NOTE: must use memcpy, not strcpy, to copy the string
- * to a larger buffer, since there may be embedded NULLs in the
- * string in some cases.
+ * Allocate a larger buffer for the string if the current one isn't large
+ * enough. Allocate extra space in the new buffer so that there will be
+ * room to grow before we have to allocate again. SPECIAL NOTE: must use
+ * memcpy, not strcpy, to copy the string to a larger buffer, since there
+ * may be embedded NULLs in the string in some cases.
*/
if (newSize >= dsPtr->spaceAvl) {
dsPtr->spaceAvl = newSize * 2;
if (dsPtr->string == dsPtr->staticSpace) {
- char *newString;
+ char *newString = ckalloc((unsigned) dsPtr->spaceAvl);
- newString = (char *) ckalloc((unsigned) dsPtr->spaceAvl);
- memcpy((VOID *) newString, (VOID *) dsPtr->string,
- (size_t) dsPtr->length);
+ memcpy(newString, dsPtr->string, (size_t) dsPtr->length);
dsPtr->string = newString;
} else {
- dsPtr->string = (char *) ckrealloc((VOID *) dsPtr->string,
+ dsPtr->string = (char *) ckrealloc((void *) dsPtr->string,
(size_t) dsPtr->spaceAvl);
}
+ dst = dsPtr->string + dsPtr->length;
}
/*
- * Convert the new string to a list element and copy it into the
- * buffer at the end, with a space, if needed.
+ * Convert the new string to a list element and copy it into the buffer at
+ * the end, with a space, if needed.
*/
- dst = dsPtr->string + dsPtr->length;
- if (TclNeedSpace(dsPtr->string, dst)) {
+ if (needSpace) {
*dst = ' ';
dst++;
dsPtr->length++;
+
+ /*
+ * If we need a space to separate this element from preceding stuff,
+ * then this element will not lead a list, and need not have it's
+ * leading '#' quoted.
+ */
+
+ flags |= TCL_DONT_QUOTE_HASH;
}
- dsPtr->length += Tcl_ConvertCountedElement(string, strSize, dst, flags);
+ dsPtr->length += TclConvertElement(element, -1, dst, flags);
+ dsPtr->string[dsPtr->length] = '\0';
return dsPtr->string;
}
@@ -1613,25 +2523,24 @@ Tcl_DStringAppendElement(dsPtr, string)
*
* Tcl_DStringSetLength --
*
- * Change the length of a dynamic string. This can cause the
- * string to either grow or shrink, depending on the value of
- * length.
+ * Change the length of a dynamic string. This can cause the string to
+ * either grow or shrink, depending on the value of length.
*
* Results:
* None.
*
* Side effects:
- * The length of dsPtr is changed to length and a null byte is
- * stored at that position in the string. If length is larger
- * than the space allocated for dsPtr, then a panic occurs.
+ * The length of dsPtr is changed to length and a null byte is stored at
+ * that position in the string. If length is larger than the space
+ * allocated for dsPtr, then a panic occurs.
*
*----------------------------------------------------------------------
*/
void
-Tcl_DStringSetLength(dsPtr, length)
- Tcl_DString *dsPtr; /* Structure describing dynamic string. */
- int length; /* New length for dynamic string. */
+Tcl_DStringSetLength(
+ Tcl_DString *dsPtr, /* Structure describing dynamic string. */
+ int length) /* New length for dynamic string. */
{
int newsize;
@@ -1640,15 +2549,15 @@ Tcl_DStringSetLength(dsPtr, length)
}
if (length >= dsPtr->spaceAvl) {
/*
- * There are two interesting cases here. In the first case, the user
- * may be trying to allocate a large buffer of a specific size. It
+ * There are two interesting cases here. In the first case, the user
+ * may be trying to allocate a large buffer of a specific size. It
* would be wasteful to overallocate that buffer, so we just allocate
- * enough for the requested size plus the trailing null byte. In the
+ * enough for the requested size plus the trailing null byte. In the
* second case, we are growing the buffer incrementally, so we need
- * behavior similar to Tcl_DStringAppend. The requested length will
- * usually be a small delta above the current spaceAvl, so we'll end up
- * doubling the old size. This won't grow the buffer quite as quickly,
- * but it should be close enough.
+ * behavior similar to Tcl_DStringAppend. The requested length will
+ * usually be a small delta above the current spaceAvl, so we'll end
+ * up doubling the old size. This won't grow the buffer quite as
+ * quickly, but it should be close enough.
*/
newsize = dsPtr->spaceAvl * 2;
@@ -1658,14 +2567,12 @@ Tcl_DStringSetLength(dsPtr, length)
dsPtr->spaceAvl = length + 1;
}
if (dsPtr->string == dsPtr->staticSpace) {
- char *newString;
+ char *newString = ckalloc((unsigned) dsPtr->spaceAvl);
- newString = (char *) ckalloc((unsigned) dsPtr->spaceAvl);
- memcpy((VOID *) newString, (VOID *) dsPtr->string,
- (size_t) dsPtr->length);
+ memcpy(newString, dsPtr->string, (size_t) dsPtr->length);
dsPtr->string = newString;
} else {
- dsPtr->string = (char *) ckrealloc((VOID *) dsPtr->string,
+ dsPtr->string = (char *) ckrealloc((void *) dsPtr->string,
(size_t) dsPtr->spaceAvl);
}
}
@@ -1678,21 +2585,22 @@ Tcl_DStringSetLength(dsPtr, length)
*
* Tcl_DStringFree --
*
- * Frees up any memory allocated for the dynamic string and
- * reinitializes the string to an empty state.
+ * Frees up any memory allocated for the dynamic string and reinitializes
+ * the string to an empty state.
*
* Results:
* None.
*
* Side effects:
- * The previous contents of the dynamic string are lost, and
- * the new value is an empty string.
+ * The previous contents of the dynamic string are lost, and the new
+ * value is an empty string.
*
- *---------------------------------------------------------------------- */
+ *----------------------------------------------------------------------
+ */
void
-Tcl_DStringFree(dsPtr)
- Tcl_DString *dsPtr; /* Structure describing dynamic string. */
+Tcl_DStringFree(
+ Tcl_DString *dsPtr) /* Structure describing dynamic string. */
{
if (dsPtr->string != dsPtr->staticSpace) {
ckfree(dsPtr->string);
@@ -1708,29 +2616,28 @@ Tcl_DStringFree(dsPtr)
*
* Tcl_DStringResult --
*
- * This procedure moves the value of a dynamic string into an
- * interpreter as its string result. Afterwards, the dynamic string
- * is reset to an empty string.
+ * This function moves the value of a dynamic string into an interpreter
+ * as its string result. Afterwards, the dynamic string is reset to an
+ * empty string.
*
* Results:
* None.
*
* Side effects:
- * The string is "moved" to interp's result, and any existing
- * string result for interp is freed. dsPtr is reinitialized to
- * an empty string.
+ * The string is "moved" to interp's result, and any existing string
+ * result for interp is freed. dsPtr is reinitialized to an empty string.
*
*----------------------------------------------------------------------
*/
void
-Tcl_DStringResult(interp, dsPtr)
- Tcl_Interp *interp; /* Interpreter whose result is to be reset. */
- Tcl_DString *dsPtr; /* Dynamic string that is to become the
+Tcl_DStringResult(
+ Tcl_Interp *interp, /* Interpreter whose result is to be reset. */
+ Tcl_DString *dsPtr) /* Dynamic string that is to become the
* result of interp. */
{
Tcl_ResetResult(interp);
-
+
if (dsPtr->string != dsPtr->staticSpace) {
interp->result = dsPtr->string;
interp->freeProc = TCL_DYNAMIC;
@@ -1740,7 +2647,7 @@ Tcl_DStringResult(interp, dsPtr)
} else {
Tcl_SetResult(interp, dsPtr->string, TCL_VOLATILE);
}
-
+
dsPtr->string = dsPtr->staticSpace;
dsPtr->length = 0;
dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE;
@@ -1752,14 +2659,14 @@ Tcl_DStringResult(interp, dsPtr)
*
* Tcl_DStringGetResult --
*
- * This procedure moves an interpreter's result into a dynamic string.
+ * This function moves an interpreter's result into a dynamic string.
*
* Results:
* None.
*
* Side effects:
- * The interpreter's string result is cleared, and the previous
- * contents of dsPtr are freed.
+ * The interpreter's string result is cleared, and the previous contents
+ * of dsPtr are freed.
*
* If the string result is empty, the object result is moved to the
* string result, then the object result is reset.
@@ -1768,26 +2675,23 @@ Tcl_DStringResult(interp, dsPtr)
*/
void
-Tcl_DStringGetResult(interp, dsPtr)
- Tcl_Interp *interp; /* Interpreter whose result is to be reset. */
- Tcl_DString *dsPtr; /* Dynamic string that is to become the
- * result of interp. */
+Tcl_DStringGetResult(
+ Tcl_Interp *interp, /* Interpreter whose result is to be reset. */
+ Tcl_DString *dsPtr) /* Dynamic string that is to become the result
+ * of interp. */
{
Interp *iPtr = (Interp *) interp;
-
+
if (dsPtr->string != dsPtr->staticSpace) {
ckfree(dsPtr->string);
}
/*
- * If the string result is empty, move the object result to the
- * string result, then reset the object result.
+ * If the string result is empty, move the object result to the string
+ * result, then reset the object result.
*/
- if (*(iPtr->result) == 0) {
- Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
- TCL_VOLATILE);
- }
+ (void) Tcl_GetStringResult(interp);
dsPtr->length = strlen(iPtr->result);
if (iPtr->freeProc != NULL) {
@@ -1796,7 +2700,7 @@ Tcl_DStringGetResult(interp, dsPtr)
dsPtr->spaceAvl = dsPtr->length+1;
} else {
dsPtr->string = (char *) ckalloc((unsigned) (dsPtr->length+1));
- strcpy(dsPtr->string, iPtr->result);
+ memcpy(dsPtr->string, iPtr->result, (unsigned) dsPtr->length+1);
(*iPtr->freeProc)(iPtr->result);
}
dsPtr->spaceAvl = dsPtr->length+1;
@@ -1809,9 +2713,9 @@ Tcl_DStringGetResult(interp, dsPtr)
dsPtr->string = (char *) ckalloc((unsigned) (dsPtr->length + 1));
dsPtr->spaceAvl = dsPtr->length + 1;
}
- strcpy(dsPtr->string, iPtr->result);
+ memcpy(dsPtr->string, iPtr->result, (unsigned) dsPtr->length+1);
}
-
+
iPtr->result = iPtr->resultSpace;
iPtr->resultSpace[0] = 0;
}
@@ -1821,9 +2725,9 @@ Tcl_DStringGetResult(interp, dsPtr)
*
* Tcl_DStringStartSublist --
*
- * This procedure adds the necessary information to a dynamic
- * string (e.g. " {" to start a sublist. Future element
- * appends will be in the sublist rather than the main list.
+ * This function adds the necessary information to a dynamic string
+ * (e.g. " {") to start a sublist. Future element appends will be in the
+ * sublist rather than the main list.
*
* Results:
* None.
@@ -1835,8 +2739,8 @@ Tcl_DStringGetResult(interp, dsPtr)
*/
void
-Tcl_DStringStartSublist(dsPtr)
- Tcl_DString *dsPtr; /* Dynamic string. */
+Tcl_DStringStartSublist(
+ Tcl_DString *dsPtr) /* Dynamic string. */
{
if (TclNeedSpace(dsPtr->string, dsPtr->string + dsPtr->length)) {
Tcl_DStringAppend(dsPtr, " {", -1);
@@ -1850,10 +2754,9 @@ Tcl_DStringStartSublist(dsPtr)
*
* Tcl_DStringEndSublist --
*
- * This procedure adds the necessary characters to a dynamic
- * string to end a sublist (e.g. "}"). Future element appends
- * will be in the enclosing (sub)list rather than the current
- * sublist.
+ * This function adds the necessary characters to a dynamic string to end
+ * a sublist (e.g. "}"). Future element appends will be in the enclosing
+ * (sub)list rather than the current sublist.
*
* Results:
* None.
@@ -1865,8 +2768,8 @@ Tcl_DStringStartSublist(dsPtr)
*/
void
-Tcl_DStringEndSublist(dsPtr)
- Tcl_DString *dsPtr; /* Dynamic string. */
+Tcl_DStringEndSublist(
+ Tcl_DString *dsPtr) /* Dynamic string. */
{
Tcl_DStringAppend(dsPtr, "}", -1);
}
@@ -1876,14 +2779,14 @@ Tcl_DStringEndSublist(dsPtr)
*
* Tcl_PrintDouble --
*
- * Given a floating-point value, this procedure converts it to
- * an ASCII string using.
+ * Given a floating-point value, this function converts it to an ASCII
+ * string using.
*
* Results:
- * The ASCII equivalent of "value" is written at "dst". It is
- * written using the current precision, and it is guaranteed to
- * contain a decimal point or exponent, so that it looks like
- * a floating-point value and not an integer.
+ * The ASCII equivalent of "value" is written at "dst". It is written
+ * using the current precision, and it is guaranteed to contain a decimal
+ * point or exponent, so that it looks like a floating-point value and
+ * not an integer.
*
* Side effects:
* None.
@@ -1892,43 +2795,158 @@ Tcl_DStringEndSublist(dsPtr)
*/
void
-Tcl_PrintDouble(interp, value, dst)
- Tcl_Interp *interp; /* Interpreter whose tcl_precision
- * variable used to be used to control
- * printing. It's ignored now. */
- double value; /* Value to print as string. */
- char *dst; /* Where to store converted value;
- * must have at least TCL_DOUBLE_SPACE
- * characters. */
+Tcl_PrintDouble(
+ Tcl_Interp *interp, /* Interpreter whose tcl_precision variable
+ * used to be used to control printing. It's
+ * ignored now. */
+ double value, /* Value to print as string. */
+ char *dst) /* Where to store converted value; must have
+ * at least TCL_DOUBLE_SPACE characters. */
{
char *p, c;
- Tcl_UniChar ch;
+ int exponent;
+ int signum;
+ char* digits;
+ char* end;
- Tcl_MutexLock(&precisionMutex);
- sprintf(dst, precisionFormat, value);
- Tcl_MutexUnlock(&precisionMutex);
+ int *precisionPtr = Tcl_GetThreadData(&precisionKey, (int)sizeof(int));
/*
- * If the ASCII result looks like an integer, add ".0" so that it
- * doesn't look like an integer anymore. This prevents floating-point
- * values from being converted to integers unintentionally.
- * Check for ASCII specifically to speed up the function.
- */
+ * Handle NaN.
+ */
- for (p = dst; *p != 0; ) {
- if (UCHAR(*p) < 0x80) {
- c = *p++;
- } else {
- p += Tcl_UtfToUniChar(p, &ch);
- c = UCHAR(ch);
+ if (TclIsNaN(value)) {
+ TclFormatNaN(value, dst);
+ return;
}
- if ((c == '.') || isalpha(UCHAR(c))) { /* INTL: ISO only. */
+
+ /*
+ * Handle infinities.
+ */
+
+ if (TclIsInfinite(value)) {
+ /*
+ * Remember to copy the terminating NUL too.
+ */
+
+ if (value < 0) {
+ memcpy(dst, "-Inf", 5);
+ } else {
+ memcpy(dst, "Inf", 4);
+ }
return;
}
+
+ /*
+ * Ordinary (normal and denormal) values.
+ */
+
+ if (*precisionPtr == 0) {
+ digits = TclDoubleDigits(value, -1, TCL_DD_SHORTEST,
+ &exponent, &signum, &end);
+ } else {
+ /*
+ * There are at least two possible interpretations for tcl_precision.
+ *
+ * The first is, "choose the decimal representation having
+ * $tcl_precision digits of significance that is nearest to the
+ * given number, breaking ties by rounding to even, and then
+ * trimming trailing zeros." This gives the greatest possible
+ * precision in the decimal string, but offers the anomaly that
+ * [expr 0.1] will be "0.10000000000000001".
+ *
+ * The second is "choose the decimal representation having at
+ * most $tcl_precision digits of significance that is nearest
+ * to the given number. If no such representation converts
+ * exactly to the given number, choose the one that is closest,
+ * breaking ties by rounding to even. If more than one such
+ * representation converts exactly to the given number, choose
+ * the shortest, breaking ties in favour of the nearest, breaking
+ * remaining ties in favour of the one ending in an even digit."
+ *
+ * Tcl 8.4 implements the first of these, which gives rise to
+ * anomalies in formatting:
+ *
+ * % expr 0.1
+ * 0.10000000000000001
+ * % expr 0.01
+ * 0.01
+ * % expr 1e-7
+ * 9.9999999999999995e-08
+ *
+ * For human readability, it appears better to choose the second rule,
+ * and let [expr 0.1] return 0.1. But for 8.4 compatibility, we
+ * prefer the first (the recommended zero value for tcl_precision
+ * avoids the problem entirely).
+ *
+ * Uncomment TCL_DD_SHORTEN_FLAG in the next call to prefer the
+ * method that allows floating point values to be shortened if
+ * it can be done without loss of precision.
+ */
+
+ digits = TclDoubleDigits(value, *precisionPtr,
+ TCL_DD_E_FORMAT /* | TCL_DD_SHORTEN_FLAG */,
+ &exponent, &signum, &end);
+ }
+ if (signum) {
+ *dst++ = '-';
+ }
+ p = digits;
+ if (exponent < -4 || exponent > 16) {
+ /*
+ * E format for numbers < 1e-3 or >= 1e17.
+ */
+
+ *dst++ = *p++;
+ c = *p;
+ if (c != '\0') {
+ *dst++ = '.';
+ while (c != '\0') {
+ *dst++ = c;
+ c = *++p;
+ }
+ }
+ /*
+ * Tcl 8.4 appears to format with at least a two-digit exponent; \
+ * preserve that behaviour when tcl_precision != 0
+ */
+ if (*precisionPtr == 0) {
+ sprintf(dst, "e%+d", exponent);
+ } else {
+ sprintf(dst, "e%+03d", exponent);
+ }
+ } else {
+ /*
+ * F format for others.
+ */
+
+ if (exponent < 0) {
+ *dst++ = '0';
+ }
+ c = *p;
+ while (exponent-- >= 0) {
+ if (c != '\0') {
+ *dst++ = c;
+ c = *++p;
+ } else {
+ *dst++ = '0';
+ }
+ }
+ *dst++ = '.';
+ if (c == '\0') {
+ *dst++ = '0';
+ } else {
+ while (++exponent < -1) {
+ *dst++ = '0';
+ }
+ while (c != '\0') {
+ *dst++ = c;
+ c = *++p;
+ }
+ }
+ *dst++ = '\0';
}
- p[0] = '.';
- p[1] = '0';
- p[2] = 0;
+ ckfree(digits);
}
/*
@@ -1936,33 +2954,33 @@ Tcl_PrintDouble(interp, value, dst)
*
* TclPrecTraceProc --
*
- * This procedure is invoked whenever the variable "tcl_precision"
- * is written.
+ * This function is invoked whenever the variable "tcl_precision" is
+ * written.
*
* Results:
- * Returns NULL if all went well, or an error message if the
- * new value for the variable doesn't make sense.
+ * Returns NULL if all went well, or an error message if the new value
+ * for the variable doesn't make sense.
*
* Side effects:
- * If the new value doesn't make sense then this procedure
- * undoes the effect of the variable modification. Otherwise
- * it modifies the format string that's used by Tcl_PrintDouble.
+ * If the new value doesn't make sense then this function undoes the
+ * effect of the variable modification. Otherwise it modifies the format
+ * string that's used by Tcl_PrintDouble.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
char *
-TclPrecTraceProc(clientData, interp, name1, name2, flags)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Interpreter containing variable. */
- CONST char *name1; /* Name of variable. */
- CONST char *name2; /* Second part of variable name. */
- int flags; /* Information about what happened. */
+TclPrecTraceProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter containing variable. */
+ CONST char *name1, /* Name of variable. */
+ CONST char *name2, /* Second part of variable name. */
+ int flags) /* Information about what happened. */
{
- CONST char *value;
- char *end;
+ Tcl_Obj* value;
int prec;
+ int *precisionPtr = Tcl_GetThreadData(&precisionKey, (int) sizeof(int));
/*
* If the variable is unset, then recreate the trace.
@@ -1974,54 +2992,39 @@ TclPrecTraceProc(clientData, interp, name1, name2, flags)
TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES
|TCL_TRACE_UNSETS, TclPrecTraceProc, clientData);
}
- return (char *) NULL;
+ return NULL;
}
/*
- * When the variable is read, reset its value from our shared
- * value. This is needed in case the variable was modified in
- * some other interpreter so that this interpreter's value is
- * out of date.
+ * When the variable is read, reset its value from our shared value. This
+ * is needed in case the variable was modified in some other interpreter
+ * so that this interpreter's value is out of date.
*/
- Tcl_MutexLock(&precisionMutex);
if (flags & TCL_TRACE_READS) {
- Tcl_SetVar2(interp, name1, name2, precisionString,
+ Tcl_SetVar2Ex(interp, name1, name2, Tcl_NewIntObj(*precisionPtr),
flags & TCL_GLOBAL_ONLY);
- Tcl_MutexUnlock(&precisionMutex);
- return (char *) NULL;
+ return NULL;
}
/*
- * The variable is being written. Check the new value and disallow
- * it if it isn't reasonable or if this is a safe interpreter (we
- * don't want safe interpreters messing up the precision of other
- * interpreters).
+ * The variable is being written. Check the new value and disallow it if
+ * it isn't reasonable or if this is a safe interpreter (we don't want
+ * safe interpreters messing up the precision of other interpreters).
*/
if (Tcl_IsSafe(interp)) {
- Tcl_SetVar2(interp, name1, name2, precisionString,
- flags & TCL_GLOBAL_ONLY);
- Tcl_MutexUnlock(&precisionMutex);
return "can't modify precision from a safe interpreter";
}
- value = Tcl_GetVar2(interp, name1, name2, flags & TCL_GLOBAL_ONLY);
- if (value == NULL) {
- value = "";
- }
- prec = strtoul(value, &end, 10);
- if ((prec <= 0) || (prec > TCL_MAX_PREC) || (prec > 100) ||
- (end == value) || (*end != 0)) {
- Tcl_SetVar2(interp, name1, name2, precisionString,
- flags & TCL_GLOBAL_ONLY);
- Tcl_MutexUnlock(&precisionMutex);
+ value = Tcl_GetVar2Ex(interp, name1, name2, flags & TCL_GLOBAL_ONLY);
+ if (value == NULL
+ || Tcl_GetIntFromObj((Tcl_Interp*) NULL, value, &prec) != TCL_OK
+ || prec < 0 || prec > TCL_MAX_PREC) {
return "improper value for precision";
}
- TclFormatInt(precisionString, prec);
- sprintf(precisionFormat, "%%.%dg", prec);
- Tcl_MutexUnlock(&precisionMutex);
- return (char *) NULL;
+ *precisionPtr = prec;
+ return NULL;
}
/*
@@ -2029,9 +3032,8 @@ TclPrecTraceProc(clientData, interp, name1, name2, flags)
*
* TclNeedSpace --
*
- * This procedure checks to see whether it is appropriate to
- * add a space before appending a new list element to an
- * existing string.
+ * This function checks to see whether it is appropriate to add a space
+ * before appending a new list element to an existing string.
*
* Results:
* The return value is 1 if a space is appropriate, 0 otherwise.
@@ -2043,24 +3045,25 @@ TclPrecTraceProc(clientData, interp, name1, name2, flags)
*/
int
-TclNeedSpace(start, end)
- CONST char *start; /* First character in string. */
- CONST char *end; /* End of string (place where space will
- * be added, if appropriate). */
+TclNeedSpace(
+ CONST char *start, /* First character in string. */
+ CONST char *end) /* End of string (place where space will be
+ * added, if appropriate). */
{
/*
- * A space is needed unless either
+ * A space is needed unless either:
* (a) we're at the start of the string, or
*/
+
if (end == start) {
return 0;
}
/*
- * (b) we're at the start of a nested list-element, quoted with an
- * open curly brace; we can be nested arbitrarily deep, so long
- * as the first curly brace starts an element, so backtrack over
- * open curly braces that are trailing characters of the string; and
+ * (b) we're at the start of a nested list-element, quoted with an open
+ * curly brace; we can be nested arbitrarily deep, so long as the
+ * first curly brace starts an element, so backtrack over open curly
+ * braces that are trailing characters of the string; and
*/
end = Tcl_UtfPrev(end, start);
@@ -2073,39 +3076,39 @@ TclNeedSpace(start, end)
/*
* (c) the trailing character of the string is already a list-element
- * separator (according to TclFindElement); that is, one of these
- * characters:
- * \u0009 \t TAB
- * \u000A \n NEWLINE
- * \u000B \v VERTICAL TAB
- * \u000C \f FORM FEED
- * \u000D \r CARRIAGE RETURN
- * \u0020 SPACE
- * with the condition that the penultimate character is not a
- * backslash.
+ * separator (according to TclFindElement); that is, one of these
+ * characters:
+ * \u0009 \t TAB
+ * \u000A \n NEWLINE
+ * \u000B \v VERTICAL TAB
+ * \u000C \f FORM FEED
+ * \u000D \r CARRIAGE RETURN
+ * \u0020 SPACE
+ * with the condition that the penultimate character is not a
+ * backslash.
*/
if (*end > 0x20) {
/*
- * Performance tweak. All ASCII spaces are <= 0x20. So get
- * a quick answer for most characters before comparing against
- * all spaces in the switch below.
+ * Performance tweak. All ASCII spaces are <= 0x20. So get a quick
+ * answer for most characters before comparing against all spaces in
+ * the switch below.
*
- * NOTE: Remove this if other Unicode spaces ever get accepted
- * as list-element separators.
+ * NOTE: Remove this if other Unicode spaces ever get accepted as
+ * list-element separators.
*/
return 1;
}
switch (*end) {
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- case '\v':
- case '\f':
- if ((end == start) || (end[-1] != '\\')) {
- return 0;
- }
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ case '\v':
+ case '\f':
+ if ((end == start) || (end[-1] != '\\')) {
+ return 0;
+ }
}
return 1;
}
@@ -2120,7 +3123,9 @@ TclNeedSpace(start, end)
* inserted at the start of the buffer. A null character is inserted at
* the end of the formatted characters. It is the caller's
* responsibility to ensure that enough storage is available. This
- * procedure has the effect of sprintf(buffer, "%d", n) but is faster.
+ * procedure has the effect of sprintf(buffer, "%ld", n) but is faster
+ * as proven in benchmarks. This is key to UpdateStringOfInt, which
+ * is a common path for a lot of code (e.g. int-indexed arrays).
*
* Results:
* An integer representing the number of characters formatted, not
@@ -2161,8 +3166,7 @@ TclFormatInt(buffer, n)
*/
if (n == -n) {
- sprintf(buffer, "%ld", n);
- return strlen(buffer);
+ return sprintf(buffer, "%ld", n);
}
/*
@@ -2198,133 +3202,119 @@ TclFormatInt(buffer, n)
/*
*----------------------------------------------------------------------
*
- * TclLooksLikeInt --
- *
- * This procedure decides whether the leading characters of a
- * string look like an integer or something else (such as a
- * floating-point number or string).
- *
- * Results:
- * The return value is 1 if the leading characters of p look
- * like a valid Tcl integer. If they look like a floating-point
- * number (e.g. "e01" or "2.4"), or if they don't look like a
- * number at all, then 0 is returned.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclLooksLikeInt(bytes, length)
- register CONST char *bytes; /* Points to first byte of the string. */
- int length; /* Number of bytes in the string. If < 0
- * bytes up to the first null byte are
- * considered (if they may appear in an
- * integer). */
-{
- register CONST char *p;
-
- if ((bytes == NULL) && (length > 0)) {
- Tcl_Panic("TclLooksLikeInt: cannot scan %d bytes from NULL", length);
- }
-
- if (length < 0) {
- length = (bytes? strlen(bytes) : 0);
- }
-
- p = bytes;
- while (length && isspace(UCHAR(*p))) { /* INTL: ISO space. */
- length--; p++;
- }
- if (length == 0) {
- return 0;
- }
- if ((*p == '+') || (*p == '-')) {
- p++; length--;
- }
-
- return (0 != TclParseInteger(p, length));
-}
-
-/*
- *----------------------------------------------------------------------
- *
* TclGetIntForIndex --
*
- * This procedure returns an integer corresponding to the list index
- * held in a Tcl object. The Tcl object's value is expected to be
- * either an integer or a string of the form "end([+-]integer)?".
+ * This function returns an integer corresponding to the list index held
+ * in a Tcl object. The Tcl object's value is expected to be in the
+ * format integer([+-]integer)? or the format end([+-]integer)?.
*
* Results:
* The return value is normally TCL_OK, which means that the index was
- * successfully stored into the location referenced by "indexPtr". If
- * the Tcl object referenced by "objPtr" has the value "end", the
- * value stored is "endValue". If "objPtr"s values is not of the form
- * "end([+-]integer)?" and
- * can not be converted to an integer, TCL_ERROR is returned and, if
- * "interp" is non-NULL, an error message is left in the interpreter's
- * result object.
+ * successfully stored into the location referenced by "indexPtr". If the
+ * Tcl object referenced by "objPtr" has the value "end", the value
+ * stored is "endValue". If "objPtr"s values is not of one of the
+ * expected formats, TCL_ERROR is returned and, if "interp" is non-NULL,
+ * an error message is left in the interpreter's result object.
*
* Side effects:
- * The object referenced by "objPtr" might be converted to an
- * integer, wide integer, or end-based-index object.
+ * The object referenced by "objPtr" might be converted to an integer,
+ * wide integer, or end-based-index object.
*
*----------------------------------------------------------------------
*/
int
-TclGetIntForIndex(interp, objPtr, endValue, indexPtr)
- Tcl_Interp *interp; /* Interpreter to use for error reporting.
- * If NULL, then no error message is left
- * after errors. */
- Tcl_Obj *objPtr; /* Points to an object containing either
- * "end" or an integer. */
- int endValue; /* The value to be stored at "indexPtr" if
+TclGetIntForIndex(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. If
+ * NULL, then no error message is left after
+ * errors. */
+ Tcl_Obj *objPtr, /* Points to an object containing either "end"
+ * or an integer. */
+ int endValue, /* The value to be stored at "indexPtr" if
* "objPtr" holds "end". */
- int *indexPtr; /* Location filled in with an integer
+ int *indexPtr) /* Location filled in with an integer
* representing an index. */
{
- if (Tcl_GetIntFromObj(NULL, objPtr, indexPtr) == TCL_OK) {
+ int length;
+ char *opPtr, *bytes;
+
+ if (TclGetIntFromObj(NULL, objPtr, indexPtr) == TCL_OK) {
return TCL_OK;
}
if (SetEndOffsetFromAny(NULL, objPtr) == TCL_OK) {
/*
- * If the object is already an offset from the end of the
- * list, or can be converted to one, use it.
+ * If the object is already an offset from the end of the list, or can
+ * be converted to one, use it.
*/
*indexPtr = endValue + objPtr->internalRep.longValue;
+ return TCL_OK;
+ }
+
+ bytes = TclGetStringFromObj(objPtr, &length);
+
+ /*
+ * Leading whitespace is acceptable in an index.
+ */
+
+ while (length && TclIsSpaceProc(*bytes)) {
+ bytes++;
+ length--;
+ }
+
+ if (TclParseNumber(NULL, NULL, NULL, bytes, length, (const char **)&opPtr,
+ TCL_PARSE_INTEGER_ONLY | TCL_PARSE_NO_WHITESPACE) == TCL_OK) {
+ int code, first, second;
+ char savedOp = *opPtr;
+
+ if ((savedOp != '+') && (savedOp != '-')) {
+ goto parseError;
+ }
+ if (TclIsSpaceProc(opPtr[1])) {
+ goto parseError;
+ }
+ *opPtr = '\0';
+ code = Tcl_GetInt(interp, bytes, &first);
+ *opPtr = savedOp;
+ if (code == TCL_ERROR) {
+ goto parseError;
+ }
+ if (TCL_ERROR == Tcl_GetInt(interp, opPtr+1, &second)) {
+ goto parseError;
+ }
+ if (savedOp == '+') {
+ *indexPtr = first + second;
+ } else {
+ *indexPtr = first - second;
+ }
+ return TCL_OK;
+ }
+
+ /*
+ * Report a parse error.
+ */
+
+ parseError:
+ if (interp != NULL) {
+ char *bytes = Tcl_GetString(objPtr);
- } else {
/*
- * Report a parse error.
+ * The result might not be empty; this resets it which should be both
+ * a cheap operation, and of little problem because this is an
+ * error-generation path anyway.
*/
- if (interp != NULL) {
- char *bytes = Tcl_GetString(objPtr);
- /*
- * The result might not be empty; this resets it which
- * should be both a cheap operation, and of little problem
- * because this is an error-generation path anyway.
- */
- Tcl_ResetResult(interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "bad index \"", bytes,
- "\": must be integer or end?-integer?",
- (char *) NULL);
- if (!strncmp(bytes, "end-", 3)) {
- bytes += 3;
- }
- TclCheckBadOctal(interp, bytes);
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "bad index \"", bytes,
+ "\": must be integer?[+-]integer? or end?[+-]integer?", NULL);
+ if (!strncmp(bytes, "end-", 4)) {
+ bytes += 4;
}
-
- return TCL_ERROR;
+ TclCheckBadOctal(interp, bytes);
}
-
- return TCL_OK;
+
+ return TCL_ERROR;
}
/*
@@ -2341,16 +3331,15 @@ TclGetIntForIndex(interp, objPtr, endValue, indexPtr)
* Side effects:
* Stores a valid string in the object's string rep.
*
- * This procedure does NOT free any earlier string rep. If it is
- * called on an object that already has a valid string rep, it will
- * leak memory.
+ * This function does NOT free any earlier string rep. If it is called on an
+ * object that already has a valid string rep, it will leak memory.
*
*----------------------------------------------------------------------
*/
static void
-UpdateStringOfEndOffset(objPtr)
- register Tcl_Obj* objPtr;
+UpdateStringOfEndOffset(
+ register Tcl_Obj* objPtr)
{
char buffer[TCL_INTEGER_SPACE + sizeof("end") + 1];
register int len;
@@ -2361,8 +3350,8 @@ UpdateStringOfEndOffset(objPtr)
buffer[len++] = '-';
len += TclFormatInt(buffer+len, -(objPtr->internalRep.longValue));
}
- objPtr->bytes = ckalloc((unsigned) (len+1));
- strcpy(objPtr->bytes, buffer);
+ objPtr->bytes = ckalloc((unsigned) len+1);
+ memcpy(objPtr->bytes, buffer, (unsigned) len+1);
objPtr->length = len;
}
@@ -2371,100 +3360,104 @@ UpdateStringOfEndOffset(objPtr)
*
* SetEndOffsetFromAny --
*
- * Look for a string of the form "end-offset" and convert it
- * to an internal representation holding the offset.
+ * Look for a string of the form "end[+-]offset" and convert it to an
+ * internal representation holding the offset.
*
* Results:
* Returns TCL_OK if ok, TCL_ERROR if the string was badly formed.
*
* Side effects:
- * If interp is not NULL, stores an error message in the
- * interpreter result.
+ * If interp is not NULL, stores an error message in the interpreter
+ * result.
*
*----------------------------------------------------------------------
*/
static int
-SetEndOffsetFromAny(interp, objPtr)
- Tcl_Interp* interp; /* Tcl interpreter or NULL */
- Tcl_Obj* objPtr; /* Pointer to the object to parse */
+SetEndOffsetFromAny(
+ Tcl_Interp *interp, /* Tcl interpreter or NULL */
+ Tcl_Obj *objPtr) /* Pointer to the object to parse */
{
int offset; /* Offset in the "end-offset" expression */
- Tcl_ObjType* oldTypePtr = objPtr->typePtr;
- /* Old internal rep type of the object */
register char* bytes; /* String rep of the object */
int length; /* Length of the object's string rep */
- /* If it's already the right type, we're fine. */
+ /*
+ * If it's already the right type, we're fine.
+ */
if (objPtr->typePtr == &tclEndOffsetType) {
return TCL_OK;
}
- /* Check for a string rep of the right form. */
+ /*
+ * Check for a string rep of the right form.
+ */
- bytes = Tcl_GetStringFromObj(objPtr, &length);
+ bytes = TclGetStringFromObj(objPtr, &length);
if ((*bytes != 'e') || (strncmp(bytes, "end",
(size_t)((length > 3) ? 3 : length)) != 0)) {
if (interp != NULL) {
Tcl_ResetResult(interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "bad index \"", bytes,
- "\": must be end?-integer?",
- (char*) NULL);
+ Tcl_AppendResult(interp, "bad index \"", bytes,
+ "\": must be end?[+-]integer?", NULL);
}
return TCL_ERROR;
}
- /* Convert the string rep */
+ /*
+ * Convert the string rep.
+ */
if (length <= 3) {
offset = 0;
- } else if ((length > 4) && (bytes[3] == '-')) {
+ } else if ((length > 4) && ((bytes[3] == '-') || (bytes[3] == '+'))) {
/*
- * This is our limited string expression evaluator. Pass everything
+ * This is our limited string expression evaluator. Pass everything
* after "end-" to Tcl_GetInt, then reverse for offset.
*/
+
+ if (TclIsSpaceProc(bytes[4])) {
+ return TCL_ERROR;
+ }
if (Tcl_GetInt(interp, bytes+4, &offset) != TCL_OK) {
return TCL_ERROR;
}
- offset = -offset;
+ if (bytes[3] == '-') {
+ offset = -offset;
+ }
} else {
/*
- * Conversion failed. Report the error.
+ * Conversion failed. Report the error.
*/
+
if (interp != NULL) {
Tcl_ResetResult(interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "bad index \"", bytes,
- "\": must be integer or end?-integer?",
- (char *) NULL);
+ Tcl_AppendResult(interp, "bad index \"", bytes,
+ "\": must be end?[+-]integer?", NULL);
}
return TCL_ERROR;
}
/*
- * The conversion succeeded. Free the old internal rep and set
- * the new one.
+ * The conversion succeeded. Free the old internal rep and set the new
+ * one.
*/
- if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
- oldTypePtr->freeIntRepProc(objPtr);
- }
-
+ TclFreeIntRep(objPtr);
objPtr->internalRep.longValue = offset;
objPtr->typePtr = &tclEndOffsetType;
return TCL_OK;
-}
+}
/*
*----------------------------------------------------------------------
*
* TclCheckBadOctal --
*
- * This procedure checks for a bad octal value and appends a
- * meaningful error to the interp's result.
+ * This function checks for a bad octal value and appends a meaningful
+ * error to the interp's result.
*
* Results:
* 1 if the argument was a bad octal, else 0.
@@ -2476,41 +3469,48 @@ SetEndOffsetFromAny(interp, objPtr)
*/
int
-TclCheckBadOctal(interp, value)
- Tcl_Interp *interp; /* Interpreter to use for error reporting.
- * If NULL, then no error message is left
- * after errors. */
- CONST char *value; /* String to check. */
+TclCheckBadOctal(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. If
+ * NULL, then no error message is left after
+ * errors. */
+ CONST char *value) /* String to check. */
{
register CONST char *p = value;
/*
- * A frequent mistake is invalid octal values due to an unwanted
- * leading zero. Try to generate a meaningful error message.
+ * A frequent mistake is invalid octal values due to an unwanted leading
+ * zero. Try to generate a meaningful error message.
*/
- while (isspace(UCHAR(*p))) { /* INTL: ISO space. */
+ while (TclIsSpaceProc(*p)) {
p++;
}
if (*p == '+' || *p == '-') {
p++;
}
if (*p == '0') {
+ if ((p[1] == 'o') || p[1] == 'O') {
+ p+=2;
+ }
while (isdigit(UCHAR(*p))) { /* INTL: digit. */
p++;
}
- while (isspace(UCHAR(*p))) { /* INTL: ISO space. */
+ while (TclIsSpaceProc(*p)) {
p++;
}
if (*p == '\0') {
- /* Reached end of string */
+ /*
+ * Reached end of string.
+ */
+
if (interp != NULL) {
/*
- * Don't reset the result here because we want this result
- * to be added to an existing error message as extra info.
+ * Don't reset the result here because we want this result to
+ * be added to an existing error message as extra info.
*/
+
Tcl_AppendResult(interp, " (looks like invalid octal number)",
- (char *) NULL);
+ NULL);
}
return 1;
}
@@ -2521,28 +3521,353 @@ TclCheckBadOctal(interp, value)
/*
*----------------------------------------------------------------------
*
+ * ClearHash --
+ *
+ * Remove all the entries in the hash table *tablePtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ClearHash(
+ Tcl_HashTable *tablePtr)
+{
+ Tcl_HashSearch search;
+ Tcl_HashEntry *hPtr;
+
+ for (hPtr = Tcl_FirstHashEntry(tablePtr, &search); hPtr != NULL;
+ hPtr = Tcl_NextHashEntry(&search)) {
+ Tcl_Obj *objPtr = (Tcl_Obj *) Tcl_GetHashValue(hPtr);
+ Tcl_DecrRefCount(objPtr);
+ Tcl_DeleteHashEntry(hPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetThreadHash --
+ *
+ * Get a thread-specific (Tcl_HashTable *) associated with a thread data
+ * key.
+ *
+ * Results:
+ * The Tcl_HashTable * corresponding to *keyPtr.
+ *
+ * Side effects:
+ * The first call on a keyPtr in each thread creates a new Tcl_HashTable,
+ * and registers a thread exit handler to dispose of it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_HashTable *
+GetThreadHash(
+ Tcl_ThreadDataKey *keyPtr)
+{
+ Tcl_HashTable **tablePtrPtr = (Tcl_HashTable **)
+ Tcl_GetThreadData(keyPtr, (int) sizeof(Tcl_HashTable *));
+
+ if (NULL == *tablePtrPtr) {
+ *tablePtrPtr = (Tcl_HashTable *)ckalloc(sizeof(Tcl_HashTable));
+ Tcl_CreateThreadExitHandler(FreeThreadHash, (ClientData)*tablePtrPtr);
+ Tcl_InitHashTable(*tablePtrPtr, TCL_ONE_WORD_KEYS);
+ }
+ return *tablePtrPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeThreadHash --
+ *
+ * Thread exit handler used by GetThreadHash to dispose of a thread hash
+ * table.
+ *
+ * Side effects:
+ * Frees a Tcl_HashTable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeThreadHash(
+ ClientData clientData)
+{
+ Tcl_HashTable *tablePtr = (Tcl_HashTable *) clientData;
+
+ ClearHash(tablePtr);
+ Tcl_DeleteHashTable(tablePtr);
+ ckfree((char *) tablePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeProcessGlobalValue --
+ *
+ * Exit handler used by Tcl(Set|Get)ProcessGlobalValue to cleanup a
+ * ProcessGlobalValue at exit.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeProcessGlobalValue(
+ ClientData clientData)
+{
+ ProcessGlobalValue *pgvPtr = (ProcessGlobalValue *) clientData;
+
+ pgvPtr->epoch++;
+ pgvPtr->numBytes = 0;
+ ckfree(pgvPtr->value);
+ pgvPtr->value = NULL;
+ if (pgvPtr->encoding) {
+ Tcl_FreeEncoding(pgvPtr->encoding);
+ pgvPtr->encoding = NULL;
+ }
+ Tcl_MutexFinalize(&pgvPtr->mutex);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclSetProcessGlobalValue --
+ *
+ * Utility routine to set a global value shared by all threads in the
+ * process while keeping a thread-local copy as well.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclSetProcessGlobalValue(
+ ProcessGlobalValue *pgvPtr,
+ Tcl_Obj *newValue,
+ Tcl_Encoding encoding)
+{
+ CONST char *bytes;
+ Tcl_HashTable *cacheMap;
+ Tcl_HashEntry *hPtr;
+ int dummy;
+
+ Tcl_MutexLock(&pgvPtr->mutex);
+
+ /*
+ * Fill the global string value.
+ */
+
+ pgvPtr->epoch++;
+ if (NULL != pgvPtr->value) {
+ ckfree(pgvPtr->value);
+ } else {
+ Tcl_CreateExitHandler(FreeProcessGlobalValue, (ClientData) pgvPtr);
+ }
+ bytes = Tcl_GetStringFromObj(newValue, &pgvPtr->numBytes);
+ pgvPtr->value = ckalloc((unsigned) pgvPtr->numBytes + 1);
+ memcpy(pgvPtr->value, bytes, (unsigned) pgvPtr->numBytes + 1);
+ if (pgvPtr->encoding) {
+ Tcl_FreeEncoding(pgvPtr->encoding);
+ }
+ pgvPtr->encoding = encoding;
+
+ /*
+ * Fill the local thread copy directly with the Tcl_Obj value to avoid
+ * loss of the intrep. Increment newValue refCount early to handle case
+ * where we set a PGV to itself.
+ */
+
+ Tcl_IncrRefCount(newValue);
+ cacheMap = GetThreadHash(&pgvPtr->key);
+ ClearHash(cacheMap);
+ hPtr = Tcl_CreateHashEntry(cacheMap,
+ (char *) INT2PTR(pgvPtr->epoch), &dummy);
+ Tcl_SetHashValue(hPtr, (ClientData) newValue);
+ Tcl_MutexUnlock(&pgvPtr->mutex);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetProcessGlobalValue --
+ *
+ * Retrieve a global value shared among all threads of the process,
+ * preferring a thread-local copy as long as it remains valid.
+ *
+ * Results:
+ * Returns a (Tcl_Obj *) that holds a copy of the global value.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclGetProcessGlobalValue(
+ ProcessGlobalValue *pgvPtr)
+{
+ Tcl_Obj *value = NULL;
+ Tcl_HashTable *cacheMap;
+ Tcl_HashEntry *hPtr;
+ int epoch = pgvPtr->epoch;
+
+ if (pgvPtr->encoding) {
+ Tcl_Encoding current = Tcl_GetEncoding(NULL, NULL);
+
+ if (pgvPtr->encoding != current) {
+ /*
+ * The system encoding has changed since the master string value
+ * was saved. Convert the master value to be based on the new
+ * system encoding.
+ */
+
+ Tcl_DString native, newValue;
+
+ Tcl_MutexLock(&pgvPtr->mutex);
+ pgvPtr->epoch++;
+ epoch = pgvPtr->epoch;
+ Tcl_UtfToExternalDString(pgvPtr->encoding, pgvPtr->value,
+ pgvPtr->numBytes, &native);
+ Tcl_ExternalToUtfDString(current, Tcl_DStringValue(&native),
+ Tcl_DStringLength(&native), &newValue);
+ Tcl_DStringFree(&native);
+ ckfree(pgvPtr->value);
+ pgvPtr->value = ckalloc((unsigned int)
+ Tcl_DStringLength(&newValue) + 1);
+ memcpy(pgvPtr->value, Tcl_DStringValue(&newValue),
+ (size_t) Tcl_DStringLength(&newValue) + 1);
+ Tcl_DStringFree(&newValue);
+ Tcl_FreeEncoding(pgvPtr->encoding);
+ pgvPtr->encoding = current;
+ Tcl_MutexUnlock(&pgvPtr->mutex);
+ } else {
+ Tcl_FreeEncoding(current);
+ }
+ }
+ cacheMap = GetThreadHash(&pgvPtr->key);
+ hPtr = Tcl_FindHashEntry(cacheMap, (char *) INT2PTR(epoch));
+ if (NULL == hPtr) {
+ int dummy;
+
+ /*
+ * No cache for the current epoch - must be a new one.
+ *
+ * First, clear the cacheMap, as anything in it must refer to some
+ * expired epoch.
+ */
+
+ ClearHash(cacheMap);
+
+ /*
+ * If no thread has set the shared value, call the initializer.
+ */
+
+ Tcl_MutexLock(&pgvPtr->mutex);
+ if ((NULL == pgvPtr->value) && (pgvPtr->proc)) {
+ pgvPtr->epoch++;
+ (*(pgvPtr->proc))(&pgvPtr->value, &pgvPtr->numBytes,
+ &pgvPtr->encoding);
+ if (pgvPtr->value == NULL) {
+ Tcl_Panic("PGV Initializer did not initialize");
+ }
+ Tcl_CreateExitHandler(FreeProcessGlobalValue, (ClientData)pgvPtr);
+ }
+
+ /*
+ * Store a copy of the shared value in our epoch-indexed cache.
+ */
+
+ value = Tcl_NewStringObj(pgvPtr->value, pgvPtr->numBytes);
+ hPtr = Tcl_CreateHashEntry(cacheMap,
+ (char *) INT2PTR(pgvPtr->epoch), &dummy);
+ Tcl_MutexUnlock(&pgvPtr->mutex);
+ Tcl_SetHashValue(hPtr, (ClientData) value);
+ Tcl_IncrRefCount(value);
+ }
+ return (Tcl_Obj *) Tcl_GetHashValue(hPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclSetObjNameOfExecutable --
+ *
+ * This function stores the absolute pathname of the executable file
+ * (normally as computed by TclpFindExecutable).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Stores the executable name.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclSetObjNameOfExecutable(
+ Tcl_Obj *name,
+ Tcl_Encoding encoding)
+{
+ TclSetProcessGlobalValue(&executableName, name, encoding);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetObjNameOfExecutable --
+ *
+ * This function retrieves the absolute pathname of the application in
+ * which the Tcl library is running, usually as previously stored by
+ * TclpFindExecutable(). This function call is the C API equivalent to
+ * the "info nameofexecutable" command.
+ *
+ * Results:
+ * A pointer to an "fsPath" Tcl_Obj, or to an empty Tcl_Obj if the
+ * pathname of the application is unknown.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclGetObjNameOfExecutable(void)
+{
+ return TclGetProcessGlobalValue(&executableName);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tcl_GetNameOfExecutable --
*
- * This procedure simply returns a pointer to the internal full
- * path name of the executable file as computed by
- * Tcl_FindExecutable. This procedure call is the C API
- * equivalent to the "info nameofexecutable" command.
+ * This function retrieves the absolute pathname of the application in
+ * which the Tcl library is running, and returns it in string form.
+ *
+ * The returned string belongs to Tcl and should be copied if the caller
+ * plans to keep it, to guard against it becoming invalid.
*
* Results:
- * A pointer to the internal string or NULL if the internal full
- * path name has not been computed or unknown.
+ * A pointer to the internal string or NULL if the internal full path
+ * name has not been computed or unknown.
*
* Side effects:
- * The object referenced by "objPtr" might be converted to an
- * integer object.
+ * None.
*
*----------------------------------------------------------------------
*/
CONST char *
-Tcl_GetNameOfExecutable()
+Tcl_GetNameOfExecutable(void)
{
- return tclExecutableName;
+ int numBytes;
+ const char *bytes =
+ Tcl_GetStringFromObj(TclGetObjNameOfExecutable(), &numBytes);
+
+ if (numBytes == 0) {
+ return NULL;
+ }
+ return bytes;
}
/*
@@ -2550,7 +3875,9 @@ Tcl_GetNameOfExecutable()
*
* TclpGetTime --
*
- * Deprecated synonym for Tcl_GetTime.
+ * Deprecated synonym for Tcl_GetTime. This function is provided for the
+ * benefit of extensions written before Tcl_GetTime was exported from the
+ * library.
*
* Results:
* None.
@@ -2558,15 +3885,265 @@ Tcl_GetNameOfExecutable()
* Side effects:
* Stores current time in the buffer designated by "timePtr"
*
- * This procedure is provided for the benefit of extensions written
- * before Tcl_GetTime was exported from the library.
- *
*----------------------------------------------------------------------
*/
void
-TclpGetTime(timePtr)
- Tcl_Time* timePtr;
+TclpGetTime(
+ Tcl_Time *timePtr)
{
Tcl_GetTime(timePtr);
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetPlatform --
+ *
+ * This is a kludge that allows the test library to get access the
+ * internal tclPlatform variable.
+ *
+ * Results:
+ * Returns a pointer to the tclPlatform variable.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TclPlatformType *
+TclGetPlatform(void)
+{
+ return &tclPlatform;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclReToGlob --
+ *
+ * Attempt to convert a regular expression to an equivalent glob pattern.
+ *
+ * Results:
+ * Returns TCL_OK on success, TCL_ERROR on failure. If interp is not
+ * NULL, an error message is placed in the result. On success, the
+ * DString will contain an exact equivalent glob pattern. The caller is
+ * responsible for calling Tcl_DStringFree on success. If exactPtr is not
+ * NULL, it will be 1 if an exact match qualifies.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclReToGlob(
+ Tcl_Interp *interp,
+ const char *reStr,
+ int reStrLen,
+ Tcl_DString *dsPtr,
+ int *exactPtr)
+{
+ int anchorLeft, anchorRight, lastIsStar, numStars;
+ char *dsStr, *dsStrStart, *msg;
+ const char *p, *strEnd;
+
+ strEnd = reStr + reStrLen;
+ Tcl_DStringInit(dsPtr);
+
+ /*
+ * "***=xxx" == "*xxx*", watch for glob-sensitive chars.
+ */
+
+ if ((reStrLen >= 4) && (memcmp("***=", reStr, 4) == 0)) {
+ /*
+ * At most, the glob pattern has length 2*reStrLen + 2 to
+ * backslash escape every character and have * at each end.
+ */
+ Tcl_DStringSetLength(dsPtr, 2*reStrLen + 2);
+ dsStr = dsStrStart = Tcl_DStringValue(dsPtr);
+ *dsStr++ = '*';
+ for (p = reStr + 4; p < strEnd; p++) {
+ switch (*p) {
+ case '\\': case '*': case '[': case ']': case '?':
+ /* Only add \ where necessary for glob */
+ *dsStr++ = '\\';
+ /* fall through */
+ default:
+ *dsStr++ = *p;
+ break;
+ }
+ }
+ *dsStr++ = '*';
+ Tcl_DStringSetLength(dsPtr, dsStr - dsStrStart);
+ if (exactPtr) {
+ *exactPtr = 0;
+ }
+ return TCL_OK;
+ }
+
+ /*
+ * At most, the glob pattern has length reStrLen + 2 to account
+ * for possible * at each end.
+ */
+
+ Tcl_DStringSetLength(dsPtr, reStrLen + 2);
+ dsStr = dsStrStart = Tcl_DStringValue(dsPtr);
+
+ /*
+ * Check for anchored REs (ie ^foo$), so we can use string equal if
+ * possible. Do not alter the start of str so we can free it correctly.
+ *
+ * Keep track of the last char being an unescaped star to prevent
+ * multiple instances. Simpler than checking that the last star
+ * may be escaped.
+ */
+
+ msg = NULL;
+ p = reStr;
+ anchorRight = 0;
+ lastIsStar = 0;
+ numStars = 0;
+
+ if (*p == '^') {
+ anchorLeft = 1;
+ p++;
+ } else {
+ anchorLeft = 0;
+ *dsStr++ = '*';
+ lastIsStar = 1;
+ }
+
+ for ( ; p < strEnd; p++) {
+ switch (*p) {
+ case '\\':
+ p++;
+ switch (*p) {
+ case 'a':
+ *dsStr++ = '\a';
+ break;
+ case 'b':
+ *dsStr++ = '\b';
+ break;
+ case 'f':
+ *dsStr++ = '\f';
+ break;
+ case 'n':
+ *dsStr++ = '\n';
+ break;
+ case 'r':
+ *dsStr++ = '\r';
+ break;
+ case 't':
+ *dsStr++ = '\t';
+ break;
+ case 'v':
+ *dsStr++ = '\v';
+ break;
+ case 'B': case '\\':
+ *dsStr++ = '\\';
+ *dsStr++ = '\\';
+ anchorLeft = 0; /* prevent exact match */
+ break;
+ case '*': case '[': case ']': case '?':
+ /* Only add \ where necessary for glob */
+ *dsStr++ = '\\';
+ anchorLeft = 0; /* prevent exact match */
+ /* fall through */
+ case '{': case '}': case '(': case ')': case '+':
+ case '.': case '|': case '^': case '$':
+ *dsStr++ = *p;
+ break;
+ default:
+ msg = "invalid escape sequence";
+ goto invalidGlob;
+ }
+ break;
+ case '.':
+ anchorLeft = 0; /* prevent exact match */
+ if (p+1 < strEnd) {
+ if (p[1] == '*') {
+ p++;
+ if (!lastIsStar) {
+ *dsStr++ = '*';
+ lastIsStar = 1;
+ numStars++;
+ }
+ continue;
+ } else if (p[1] == '+') {
+ p++;
+ *dsStr++ = '?';
+ *dsStr++ = '*';
+ lastIsStar = 1;
+ numStars++;
+ continue;
+ }
+ }
+ *dsStr++ = '?';
+ break;
+ case '$':
+ if (p+1 != strEnd) {
+ msg = "$ not anchor";
+ goto invalidGlob;
+ }
+ anchorRight = 1;
+ break;
+ case '*': case '+': case '?': case '|': case '^':
+ case '{': case '}': case '(': case ')': case '[': case ']':
+ msg = "unhandled RE special char";
+ goto invalidGlob;
+ break;
+ default:
+ *dsStr++ = *p;
+ break;
+ }
+ lastIsStar = 0;
+ }
+ if (numStars > 1) {
+ /*
+ * Heuristic: if >1 non-anchoring *, the risk is large that glob
+ * matching is slower than the RE engine, so report invalid.
+ */
+ msg = "excessive recursive glob backtrack potential";
+ goto invalidGlob;
+ }
+
+ if (!anchorRight && !lastIsStar) {
+ *dsStr++ = '*';
+ }
+ Tcl_DStringSetLength(dsPtr, dsStr - dsStrStart);
+
+ if (exactPtr) {
+ *exactPtr = (anchorLeft && anchorRight);
+ }
+
+#if 0
+ fprintf(stderr, "INPUT RE '%.*s' OUTPUT GLOB '%s' anchor %d:%d \n",
+ reStrLen, reStr,
+ Tcl_DStringValue(dsPtr), anchorLeft, anchorRight);
+ fflush(stderr);
+#endif
+ return TCL_OK;
+
+ invalidGlob:
+#if 0
+ fprintf(stderr, "INPUT RE '%.*s' NO OUTPUT GLOB %s (%c)\n",
+ reStrLen, reStr, msg, *p);
+ fflush(stderr);
+#endif
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, msg, NULL);
+ }
+ Tcl_DStringFree(dsPtr);
+ return TCL_ERROR;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tclVar.c b/generic/tclVar.c
index a434bae..aaf1cb9 100644
--- a/generic/tclVar.c
+++ b/generic/tclVar.c
@@ -1,8 +1,8 @@
-/*
+/*
* tclVar.c --
*
- * This file contains routines that implement Tcl variables
- * (both scalars and arrays).
+ * This file contains routines that implement Tcl variables (both scalars
+ * and arrays).
*
* The implementation of arrays is modelled after an initial
* implementation by Mark Diekhans and Karl Lehenbauer.
@@ -10,147 +10,324 @@
* Copyright (c) 1987-1994 The Regents of the University of California.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
* Copyright (c) 1998-1999 by Scriptics Corporation.
- * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
+ * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved.
+ * Copyright (c) 2007 Miguel Sofer
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
+/*
+ * Prototypes for the variable hash key methods.
+ */
+
+static Tcl_HashEntry * AllocVarEntry(Tcl_HashTable *tablePtr, void *keyPtr);
+static void FreeVarEntry(Tcl_HashEntry *hPtr);
+static int CompareVarKeys(void *keyPtr, Tcl_HashEntry *hPtr);
+static unsigned int HashVarKey(Tcl_HashTable *tablePtr, void *keyPtr);
+
+static Tcl_HashKeyType tclVarHashKeyType = {
+ TCL_HASH_KEY_TYPE_VERSION, /* version */
+ 0, /* flags */
+ HashVarKey, /* hashKeyProc */
+ CompareVarKeys, /* compareKeysProc */
+ AllocVarEntry, /* allocEntryProc */
+ FreeVarEntry /* freeEntryProc */
+};
+
+static inline Var * VarHashCreateVar(TclVarHashTable *tablePtr,
+ Tcl_Obj *key, int *newPtr);
+static inline Var * VarHashFirstVar(TclVarHashTable *tablePtr,
+ Tcl_HashSearch *searchPtr);
+static inline Var * VarHashNextVar(Tcl_HashSearch *searchPtr);
+static inline void CleanupVar(Var *varPtr, Var *arrayPtr);
+
+#define VarHashGetValue(hPtr) \
+ ((Var *) ((char *)hPtr - TclOffset(VarInHash, entry)))
+
+static inline Var *
+VarHashCreateVar(
+ TclVarHashTable *tablePtr,
+ Tcl_Obj *key,
+ int *newPtr)
+{
+ Tcl_HashEntry *hPtr = Tcl_CreateHashEntry((Tcl_HashTable *) tablePtr,
+ (char *) key, newPtr);
+
+ if (hPtr) {
+ return VarHashGetValue(hPtr);
+ } else {
+ return NULL;
+ }
+}
+
+#define VarHashFindVar(tablePtr, key) \
+ VarHashCreateVar((tablePtr), (key), NULL)
+#define VarHashInvalidateEntry(varPtr) \
+ ((varPtr)->flags |= VAR_DEAD_HASH)
+#define VarHashDeleteEntry(varPtr) \
+ Tcl_DeleteHashEntry(&(((VarInHash *) varPtr)->entry))
+
+#define VarHashFirstEntry(tablePtr, searchPtr) \
+ Tcl_FirstHashEntry((Tcl_HashTable *) (tablePtr), (searchPtr))
+
+#define VarHashNextEntry(searchPtr) \
+ Tcl_NextHashEntry((searchPtr))
+
+static inline Var *
+VarHashFirstVar(
+ TclVarHashTable *tablePtr,
+ Tcl_HashSearch *searchPtr)
+{
+ Tcl_HashEntry *hPtr = VarHashFirstEntry(tablePtr, searchPtr);
+
+ if (hPtr) {
+ return VarHashGetValue(hPtr);
+ } else {
+ return NULL;
+ }
+}
+
+static inline Var *
+VarHashNextVar(
+ Tcl_HashSearch *searchPtr)
+{
+ Tcl_HashEntry *hPtr = VarHashNextEntry(searchPtr);
+
+ if (hPtr) {
+ return VarHashGetValue(hPtr);
+ } else {
+ return NULL;
+ }
+}
+
+#define VarHashGetKey(varPtr) \
+ (((VarInHash *)(varPtr))->entry.key.objPtr)
+
+#define VarHashDeleteTable(tablePtr) \
+ Tcl_DeleteHashTable((Tcl_HashTable *) (tablePtr))
/*
- * The strings below are used to indicate what went wrong when a
- * variable access is denied.
+ * The strings below are used to indicate what went wrong when a variable
+ * access is denied.
*/
-static CONST char *noSuchVar = "no such variable";
-static CONST char *isArray = "variable is array";
-static CONST char *needArray = "variable isn't array";
-static CONST char *noSuchElement = "no such element in array";
-static CONST char *danglingElement =
- "upvar refers to element in deleted array";
-static CONST char *danglingVar =
- "upvar refers to variable in deleted namespace";
-static CONST char *badNamespace = "parent namespace doesn't exist";
-static CONST char *missingName = "missing variable name";
-static CONST char *isArrayElement = "name refers to an element in an array";
+static const char *noSuchVar = "no such variable";
+static const char *isArray = "variable is array";
+static const char *needArray = "variable isn't array";
+static const char *noSuchElement = "no such element in array";
+static const char *danglingElement =
+ "upvar refers to element in deleted array";
+static const char *danglingVar =
+ "upvar refers to variable in deleted namespace";
+static const char *badNamespace = "parent namespace doesn't exist";
+static const char *missingName = "missing variable name";
+static const char *isArrayElement =
+ "name refers to an element in an array";
/*
- * Forward references to procedures defined later in this file:
+ * A test to see if we are in a call frame that has local variables. This is
+ * true if we are inside a procedure body.
*/
-static int CallVarTraces _ANSI_ARGS_((Interp *iPtr, Var *arrayPtr,
- Var *varPtr, CONST char *part1, CONST char *part2,
- int flags, CONST int leaveErrMsg));
-static void CleanupVar _ANSI_ARGS_((Var *varPtr,
- Var *arrayPtr));
-static void DeleteSearches _ANSI_ARGS_((Var *arrayVarPtr));
-static void DeleteArray _ANSI_ARGS_((Interp *iPtr,
- CONST char *arrayName, Var *varPtr, int flags));
-static void DisposeTraceResult _ANSI_ARGS_((int flags,
- char *result));
-static int ObjMakeUpvar _ANSI_ARGS_((Tcl_Interp *interp,
- CallFrame *framePtr, Tcl_Obj *otherP1Ptr,
- CONST char *otherP2, CONST int otherFlags,
- CONST char *myName, int myFlags, int index));
-static Var * NewVar _ANSI_ARGS_((void));
-static ArraySearch * ParseSearchId _ANSI_ARGS_((Tcl_Interp *interp,
- CONST Var *varPtr, CONST char *varName,
- Tcl_Obj *handleObj));
-static void VarErrMsg _ANSI_ARGS_((Tcl_Interp *interp,
- CONST char *part1, CONST char *part2,
- CONST char *operation, CONST char *reason));
-static int SetArraySearchObj _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
-static void UnsetVarStruct _ANSI_ARGS_((Var *varPtr, Var *arrayPtr,
- Interp *iPtr, CONST char *part1, CONST char *part2,
- int flags));
+#define HasLocalVars(framePtr) ((framePtr)->isProcCallFrame & FRAME_IS_PROC)
/*
- * Functions defined in this file that may be exported in the future
- * for use by the bytecode compiler and engine or to the public interface.
+ * Forward references to functions defined later in this file:
*/
-Var * TclLookupSimpleVar _ANSI_ARGS_((Tcl_Interp *interp,
- CONST char *varName, int flags, CONST int create,
- CONST char **errMsgPtr, int *indexPtr));
-int TclObjUnsetVar2 _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *part1Ptr, CONST char *part2, int flags));
+static void AppendLocals(Tcl_Interp *interp, Tcl_Obj *listPtr,
+ Tcl_Obj *patternPtr, int includeLinks);
+static void DeleteSearches(Interp *iPtr, Var *arrayVarPtr);
+static void DeleteArray(Interp *iPtr, Tcl_Obj *arrayNamePtr,
+ Var *varPtr, int flags);
+static Tcl_Var ObjFindNamespaceVar(Tcl_Interp *interp,
+ Tcl_Obj *namePtr, Tcl_Namespace *contextNsPtr,
+ int flags);
+static int ObjMakeUpvar(Tcl_Interp *interp,
+ CallFrame *framePtr, Tcl_Obj *otherP1Ptr,
+ const char *otherP2, const int otherFlags,
+ Tcl_Obj *myNamePtr, int myFlags, int index);
+static ArraySearch * ParseSearchId(Tcl_Interp *interp, const Var *varPtr,
+ Tcl_Obj *varNamePtr, Tcl_Obj *handleObj);
+static void UnsetVarStruct(Var *varPtr, Var *arrayPtr,
+ Interp *iPtr, Tcl_Obj *part1Ptr,
+ Tcl_Obj *part2Ptr, int flags);
+static int SetArraySearchObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr);
-static Tcl_FreeInternalRepProc FreeLocalVarName;
-static Tcl_DupInternalRepProc DupLocalVarName;
-static Tcl_UpdateStringProc UpdateLocalVarName;
-static Tcl_FreeInternalRepProc FreeNsVarName;
-static Tcl_DupInternalRepProc DupNsVarName;
-static Tcl_FreeInternalRepProc FreeParsedVarName;
-static Tcl_DupInternalRepProc DupParsedVarName;
-static Tcl_UpdateStringProc UpdateParsedVarName;
+/*
+ * Functions defined in this file that may be exported in the future for use
+ * by the bytecode compiler and engine or to the public interface.
+ */
+
+MODULE_SCOPE Var * TclLookupSimpleVar(Tcl_Interp *interp,
+ Tcl_Obj *varNamePtr, int flags, const int create,
+ const char **errMsgPtr, int *indexPtr);
+
+static Tcl_DupInternalRepProc DupLocalVarName;
+static Tcl_FreeInternalRepProc FreeLocalVarName;
+static Tcl_UpdateStringProc PanicOnUpdateVarName;
+
+static Tcl_FreeInternalRepProc FreeParsedVarName;
+static Tcl_DupInternalRepProc DupParsedVarName;
+static Tcl_UpdateStringProc UpdateParsedVarName;
+
+static Tcl_UpdateStringProc PanicOnUpdateVarName;
+static Tcl_SetFromAnyProc PanicOnSetVarName;
/*
* Types of Tcl_Objs used to cache variable lookups.
*
- *
* localVarName - INTERNALREP DEFINITION:
- * twoPtrValue.ptr1 = pointer to the corresponding Proc
- * twoPtrValue.ptr2 = index into locals table
+ * ptrAndLongRep.ptr: pointer to name obj in varFramePtr->localCache
+ * or NULL if it is this same obj
+ * ptrAndLongRep.value: index into locals table
*
* nsVarName - INTERNALREP DEFINITION:
- * twoPtrValue.ptr1: pointer to the namespace containing the
- * reference
- * twoPtrValue.ptr2: pointer to the corresponding Var
+ * twoPtrValue.ptr1: pointer to the namespace containing the reference
+ * twoPtrValue.ptr2: pointer to the corresponding Var
*
* parsedVarName - INTERNALREP DEFINITION:
- * twoPtrValue.ptr1 = pointer to the array name Tcl_Obj,
- * or NULL if it is a scalar variable
- * twoPtrValue.ptr2 = pointer to the element name string
- * (owned by this Tcl_Obj), or NULL if
- * it is a scalar variable
+ * twoPtrValue.ptr1: pointer to the array name Tcl_Obj, or NULL if it is a
+ * scalar variable
+ * twoPtrValue.ptr2: pointer to the element name string (owned by this
+ * Tcl_Obj), or NULL if it is a scalar variable
*/
-static Tcl_ObjType tclLocalVarNameType = {
+static Tcl_ObjType localVarNameType = {
"localVarName",
- FreeLocalVarName, DupLocalVarName, UpdateLocalVarName, NULL
+ FreeLocalVarName, DupLocalVarName, PanicOnUpdateVarName, PanicOnSetVarName
};
+/*
+ * Caching of namespace variables disabled: no simple way was found to avoid
+ * interfering with the resolver's idea of variable existence. A cached
+ * varName may keep a variable's name in the namespace's hash table, which is
+ * the resolver's criterion for existence (see test namespace-17.10).
+ */
+
+#define ENABLE_NS_VARNAME_CACHING 0
+
+#if ENABLE_NS_VARNAME_CACHING
+static Tcl_FreeInternalRepProc FreeNsVarName;
+static Tcl_DupInternalRepProc DupNsVarName;
+
static Tcl_ObjType tclNsVarNameType = {
"namespaceVarName",
- FreeNsVarName, DupNsVarName, NULL, NULL
+ FreeNsVarName, DupNsVarName, PanicOnUpdateVarName, PanicOnSetVarName
};
+#endif
static Tcl_ObjType tclParsedVarNameType = {
"parsedVarName",
- FreeParsedVarName, DupParsedVarName, UpdateParsedVarName, NULL
+ FreeParsedVarName, DupParsedVarName, UpdateParsedVarName, PanicOnSetVarName
};
/*
* Type of Tcl_Objs used to speed up array searches.
*
* INTERNALREP DEFINITION:
- * twoPtrValue.ptr1 = searchIdNumber as offset from (char*)NULL
- * twoPtrValue.ptr2 = variableNameStartInString as offset from (char*)NULL
+ * twoPtrValue.ptr1: searchIdNumber (cast to pointer)
+ * twoPtrValue.ptr2: variableNameStartInString (cast to pointer)
*
- * Note that the value stored in ptr2 is the offset into the string of
- * the start of the variable name and not the address of the variable
- * name itself, as this can be safely copied.
+ * Note that the value stored in ptr2 is the offset into the string of the
+ * start of the variable name and not the address of the variable name itself,
+ * as this can be safely copied.
*/
+
Tcl_ObjType tclArraySearchType = {
"array search",
NULL, NULL, NULL, SetArraySearchObj
};
+
+Var *
+TclVarHashCreateVar(
+ TclVarHashTable *tablePtr,
+ const char *key,
+ int *newPtr)
+{
+ Tcl_Obj *keyPtr;
+ Var *varPtr;
+
+ keyPtr = Tcl_NewStringObj(key, -1);
+ Tcl_IncrRefCount(keyPtr);
+ varPtr = VarHashCreateVar(tablePtr, keyPtr, newPtr);
+ Tcl_DecrRefCount(keyPtr);
+ return varPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclCleanupVar --
+ *
+ * This function is called when it looks like it may be OK to free up a
+ * variable's storage. If the variable is in a hashtable, its Var
+ * structure and hash table entry will be freed along with those of its
+ * containing array, if any. This function is called, for example, when
+ * a trace on a variable deletes a variable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If the variable (or its containing array) really is dead and in a
+ * hashtable, then its Var structure, and possibly its hash table entry,
+ * is freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static inline void
+CleanupVar(
+ Var *varPtr, /* Pointer to variable that may be a candidate
+ * for being expunged. */
+ Var *arrayPtr) /* Array that contains the variable, or NULL
+ * if this variable isn't an array element. */
+{
+ if (TclIsVarUndefined(varPtr) && TclIsVarInHash(varPtr)
+ && !TclIsVarTraced(varPtr)
+ && (VarHashRefCount(varPtr) == !TclIsVarDeadHash(varPtr))) {
+ if (VarHashRefCount(varPtr) == 0) {
+ ckfree((char *) varPtr);
+ } else {
+ VarHashDeleteEntry(varPtr);
+ }
+ }
+ if (arrayPtr != NULL && TclIsVarUndefined(arrayPtr) &&
+ TclIsVarInHash(arrayPtr) && !TclIsVarTraced(arrayPtr) &&
+ (VarHashRefCount(arrayPtr) == !TclIsVarDeadHash(arrayPtr))) {
+ if (VarHashRefCount(arrayPtr) == 0) {
+ ckfree((char *) arrayPtr);
+ } else {
+ VarHashDeleteEntry(arrayPtr);
+ }
+ }
+}
+
+void
+TclCleanupVar(
+ Var *varPtr, /* Pointer to variable that may be a candidate
+ * for being expunged. */
+ Var *arrayPtr) /* Array that contains the variable, or NULL
+ * if this variable isn't an array element. */
+{
+ CleanupVar(varPtr, arrayPtr);
+}
/*
*----------------------------------------------------------------------
*
* TclLookupVar --
*
- * This procedure is used to locate a variable given its name(s). It
- * has been mostly superseded by TclObjLookupVar, it is now only used
- * by the string-based interfaces. It is kept in tcl8.4 mainly because
- * it is in the internal stubs table, so that some extension may be
- * calling it.
+ * This function is used to locate a variable given its name(s). It has
+ * been mostly superseded by TclObjLookupVar, it is now only used by the
+ * trace code. It is kept in tcl8.5 mainly because it is in the internal
+ * stubs table, so that some extension may be calling it.
*
* Results:
* The return value is a pointer to the variable structure indicated by
@@ -164,14 +341,14 @@ Tcl_ObjType tclArraySearchType = {
*
* If the variable isn't found and creation wasn't specified, or some
* other error occurs, NULL is returned and an error message is left in
- * the interp's result if TCL_LEAVE_ERR_MSG is set in flags.
+ * the interp's result if TCL_LEAVE_ERR_MSG is set in flags.
*
- * Note: it's possible for the variable returned to be VAR_UNDEFINED
- * even if createPart1 or createPart2 are 1 (these only cause the hash
- * table entry or array to be created). For example, the variable might
- * be a global that has been unset but is still referenced by a
- * procedure, or a variable that has been unset but it only being kept
- * in existence (if VAR_UNDEFINED) by a trace.
+ * Note: it's possible for the variable returned to be VAR_UNDEFINED even
+ * if createPart1 or createPart2 are 1 (these only cause the hash table
+ * entry or array to be created). For example, the variable might be a
+ * global that has been unset but is still referenced by a procedure, or
+ * a variable that has been unset but it only being kept in existence (if
+ * VAR_UNDEFINED) by a trace.
*
* Side effects:
* New hashtable entries may be created if createPart1 or createPart2
@@ -179,132 +356,58 @@ Tcl_ObjType tclArraySearchType = {
*
*----------------------------------------------------------------------
*/
+
Var *
-TclLookupVar(interp, part1, part2, flags, msg, createPart1, createPart2,
- arrayPtrPtr)
- Tcl_Interp *interp; /* Interpreter to use for lookup. */
- CONST char *part1; /* If part2 isn't NULL, this is the name of
- * an array. Otherwise, this
- * is a full variable name that could
- * include a parenthesized array element. */
- CONST char *part2; /* Name of element within array, or NULL. */
- int flags; /* Only TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
+TclLookupVar(
+ Tcl_Interp *interp, /* Interpreter to use for lookup. */
+ const char *part1, /* If part2 isn't NULL, this is the name of an
+ * array. Otherwise, this is a full variable
+ * name that could include a parenthesized
+ * array element. */
+ const char *part2, /* Name of element within array, or NULL. */
+ int flags, /* Only TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
* and TCL_LEAVE_ERR_MSG bits matter. */
- CONST char *msg; /* Verb to use in error messages, e.g.
- * "read" or "set". Only needed if
- * TCL_LEAVE_ERR_MSG is set in flags. */
- int createPart1; /* If 1, create hash table entry for part 1
- * of name, if it doesn't already exist. If
- * 0, return error if it doesn't exist. */
- int createPart2; /* If 1, create hash table entry for part 2
- * of name, if it doesn't already exist. If
- * 0, return error if it doesn't exist. */
- Var **arrayPtrPtr; /* If the name refers to an element of an
+ const char *msg, /* Verb to use in error messages, e.g. "read"
+ * or "set". Only needed if TCL_LEAVE_ERR_MSG
+ * is set in flags. */
+ int createPart1, /* If 1, create hash table entry for part 1 of
+ * name, if it doesn't already exist. If 0,
+ * return error if it doesn't exist. */
+ int createPart2, /* If 1, create hash table entry for part 2 of
+ * name, if it doesn't already exist. If 0,
+ * return error if it doesn't exist. */
+ Var **arrayPtrPtr) /* If the name refers to an element of an
* array, *arrayPtrPtr gets filled in with
- * address of array variable. Otherwise
- * this is set to NULL. */
+ * address of array variable. Otherwise this
+ * is set to NULL. */
{
+ Tcl_Obj *part1Ptr;
Var *varPtr;
- CONST char *elName; /* Name of array element or NULL; may be
- * same as part2, or may be openParen+1. */
- int openParen, closeParen;
- /* If this procedure parses a name into
- * array and index, these are the offsets to
- * the parens around the index. Otherwise
- * they are -1. */
- register CONST char *p;
- CONST char *errMsg = NULL;
- int index;
-#define VAR_NAME_BUF_SIZE 26
- char buffer[VAR_NAME_BUF_SIZE];
- char *newVarName = buffer;
-
- varPtr = NULL;
- *arrayPtrPtr = NULL;
- openParen = closeParen = -1;
-
- /*
- * Parse part1 into array name and index.
- * Always check if part1 is an array element name and allow it only if
- * part2 is not given.
- * (if one does not care about creating array elements that can't be used
- * from tcl, and prefer slightly better performance, one can put
- * the following in an if (part2 == NULL) { ... } block and remove
- * the part2's test and error reporting or move that code in array set)
- */
- elName = part2;
- for (p = part1; *p ; p++) {
- if (*p == '(') {
- openParen = p - part1;
- do {
- p++;
- } while (*p != '\0');
- p--;
- if (*p == ')') {
- if (part2 != NULL) {
- if (flags & TCL_LEAVE_ERR_MSG) {
- VarErrMsg(interp, part1, part2, msg, needArray);
- }
- return NULL;
- }
- closeParen = p - part1;
- } else {
- openParen = -1;
- }
- break;
- }
- }
- if (openParen != -1) {
- if (closeParen >= VAR_NAME_BUF_SIZE) {
- newVarName = ckalloc((unsigned int) (closeParen+1));
- }
- memcpy(newVarName, part1, (unsigned int) closeParen);
- newVarName[openParen] = '\0';
- newVarName[closeParen] = '\0';
- part1 = newVarName;
- elName = newVarName + openParen + 1;
- }
+ part1Ptr = Tcl_NewStringObj(part1, -1);
+ Tcl_IncrRefCount(part1Ptr);
- varPtr = TclLookupSimpleVar(interp, part1, flags,
- createPart1, &errMsg, &index);
- if (varPtr == NULL) {
- if ((errMsg != NULL) && (flags & TCL_LEAVE_ERR_MSG)) {
- VarErrMsg(interp, part1, elName, msg, errMsg);
- }
- } else {
- while (TclIsVarLink(varPtr)) {
- varPtr = varPtr->value.linkPtr;
- }
- if (elName != NULL) {
- *arrayPtrPtr = varPtr;
- varPtr = TclLookupArrayElement(interp, part1, elName, flags,
- msg, createPart1, createPart2, varPtr);
- }
- }
- if (newVarName != buffer) {
- ckfree(newVarName);
- }
+ varPtr = TclObjLookupVar(interp, part1Ptr, part2, flags, msg,
+ createPart1, createPart2, arrayPtrPtr);
+ TclDecrRefCount(part1Ptr);
return varPtr;
-
-#undef VAR_NAME_BUF_SIZE
}
/*
*----------------------------------------------------------------------
*
- * TclObjLookupVar --
+ * TclObjLookupVar, TclObjLookupVarEx --
*
- * This procedure is used by virtually all of the variable code to
- * locate a variable given its name(s). The parsing into array/element
- * components and (if possible) the lookup results are cached in
- * part1Ptr, which is converted to one of the varNameTypes.
+ * This function is used by virtually all of the variable code to locate
+ * a variable given its name(s). The parsing into array/element
+ * components and (if possible) the lookup results are cached in
+ * part1Ptr, which is converted to one of the varNameTypes.
*
* Results:
* The return value is a pointer to the variable structure indicated by
- * part1Ptr and part2, or NULL if the variable couldn't be found. If
- * the variable is found, *arrayPtrPtr is filled with the address of the
+ * part1Ptr and part2, or NULL if the variable couldn't be found. If *
+ * the variable is found, *arrayPtrPtr is filled with the address of the
* variable structure for the array that contains the variable (or NULL
* if the variable is a scalar). If the variable can't be found and
* either createPart1 or createPart2 are 1, a new as-yet-undefined
@@ -313,48 +416,91 @@ TclLookupVar(interp, part1, part2, flags, msg, createPart1, createPart2,
*
* If the variable isn't found and creation wasn't specified, or some
* other error occurs, NULL is returned and an error message is left in
- * the interp's result if TCL_LEAVE_ERR_MSG is set in flags.
+ * the interp's result if TCL_LEAVE_ERR_MSG is set in flags.
*
- * Note: it's possible for the variable returned to be VAR_UNDEFINED
- * even if createPart1 or createPart2 are 1 (these only cause the hash
- * table entry or array to be created). For example, the variable might
- * be a global that has been unset but is still referenced by a
- * procedure, or a variable that has been unset but it only being kept
- * in existence (if VAR_UNDEFINED) by a trace.
+ * Note: it's possible for the variable returned to be VAR_UNDEFINED even
+ * if createPart1 or createPart2 are 1 (these only cause the hash table
+ * entry or array to be created). For example, the variable might be a
+ * global that has been unset but is still referenced by a procedure, or
+ * a variable that has been unset but it only being kept in existence (if
+ * VAR_UNDEFINED) by a trace.
*
* Side effects:
* New hashtable entries may be created if createPart1 or createPart2
- * are 1.
- * The object part1Ptr is converted to one of tclLocalVarNameType,
- * tclNsVarNameType or tclParsedVarNameType and caches as much of the
- * lookup as it can.
+ * are 1. The object part1Ptr is converted to one of localVarNameType,
+ * tclNsVarNameType or tclParsedVarNameType and caches as much of the
+ * lookup as it can.
*
*----------------------------------------------------------------------
*/
+
Var *
-TclObjLookupVar(interp, part1Ptr, part2, flags, msg, createPart1, createPart2,
- arrayPtrPtr)
- Tcl_Interp *interp; /* Interpreter to use for lookup. */
- register Tcl_Obj *part1Ptr; /* If part2 isn't NULL, this is the name
- * of an array. Otherwise, this is a full
- * variable name that could include a parenthesized
+TclObjLookupVar(
+ Tcl_Interp *interp, /* Interpreter to use for lookup. */
+ register Tcl_Obj *part1Ptr, /* If part2 isn't NULL, this is the name of an
+ * array. Otherwise, this is a full variable
+ * name that could include a parenthesized
* array element. */
- CONST char *part2; /* Name of element within array, or NULL. */
- int flags; /* Only TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
+ const char *part2, /* Name of element within array, or NULL. */
+ int flags, /* Only TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
+ * and TCL_LEAVE_ERR_MSG bits matter. */
+ const char *msg, /* Verb to use in error messages, e.g. "read"
+ * or "set". Only needed if TCL_LEAVE_ERR_MSG
+ * is set in flags. */
+ const int createPart1, /* If 1, create hash table entry for part 1 of
+ * name, if it doesn't already exist. If 0,
+ * return error if it doesn't exist. */
+ const int createPart2, /* If 1, create hash table entry for part 2 of
+ * name, if it doesn't already exist. If 0,
+ * return error if it doesn't exist. */
+ Var **arrayPtrPtr) /* If the name refers to an element of an
+ * array, *arrayPtrPtr gets filled in with
+ * address of array variable. Otherwise this
+ * is set to NULL. */
+{
+ Tcl_Obj *part2Ptr;
+ Var *resPtr;
+
+ if (part2) {
+ part2Ptr = Tcl_NewStringObj(part2, -1);
+ Tcl_IncrRefCount(part2Ptr);
+ } else {
+ part2Ptr = NULL;
+ }
+
+ resPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr,
+ flags, msg, createPart1, createPart2, arrayPtrPtr);
+
+ if (part2Ptr) {
+ Tcl_DecrRefCount(part2Ptr);
+ }
+
+ return resPtr;
+}
+
+Var *
+TclObjLookupVarEx(
+ Tcl_Interp *interp, /* Interpreter to use for lookup. */
+ Tcl_Obj *part1Ptr, /* If part2Ptr isn't NULL, this is the name of
+ * an array. Otherwise, this is a full
+ * variable name that could include a
+ * parenthesized array element. */
+ Tcl_Obj *part2Ptr, /* Name of element within array, or NULL. */
+ int flags, /* Only TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
* and TCL_LEAVE_ERR_MSG bits matter. */
- CONST char *msg; /* Verb to use in error messages, e.g.
- * "read" or "set". Only needed if
- * TCL_LEAVE_ERR_MSG is set in flags. */
- CONST int createPart1; /* If 1, create hash table entry for part 1
- * of name, if it doesn't already exist. If
- * 0, return error if it doesn't exist. */
- CONST int createPart2; /* If 1, create hash table entry for part 2
- * of name, if it doesn't already exist. If
- * 0, return error if it doesn't exist. */
- Var **arrayPtrPtr; /* If the name refers to an element of an
+ const char *msg, /* Verb to use in error messages, e.g. "read"
+ * or "set". Only needed if TCL_LEAVE_ERR_MSG
+ * is set in flags. */
+ const int createPart1, /* If 1, create hash table entry for part 1 of
+ * name, if it doesn't already exist. If 0,
+ * return error if it doesn't exist. */
+ const int createPart2, /* If 1, create hash table entry for part 2 of
+ * name, if it doesn't already exist. If 0,
+ * return error if it doesn't exist. */
+ Var **arrayPtrPtr) /* If the name refers to an element of an
* array, *arrayPtrPtr gets filled in with
- * address of array variable. Otherwise
- * this is set to NULL. */
+ * address of array variable. Otherwise this
+ * is set to NULL. */
{
Interp *iPtr = (Interp *) interp;
register Var *varPtr; /* Points to the variable's in-frame Var
@@ -363,117 +509,148 @@ TclObjLookupVar(interp, part1Ptr, part2, flags, msg, createPart1, createPart2,
int index, len1, len2;
int parsed = 0;
Tcl_Obj *objPtr;
- Tcl_ObjType *typePtr = part1Ptr->typePtr;
- CONST char *errMsg = NULL;
+ const Tcl_ObjType *typePtr = part1Ptr->typePtr;
+ const char *errMsg = NULL;
CallFrame *varFramePtr = iPtr->varFramePtr;
+#if ENABLE_NS_VARNAME_CACHING
Namespace *nsPtr;
-
- /*
- * If part1Ptr is a tclParsedVarNameType, separate it into the
- * pre-parsed parts.
- */
+#endif
+ char *part2 = part2Ptr? TclGetString(part2Ptr):NULL;
+ char *newPart2 = NULL;
*arrayPtrPtr = NULL;
- if (typePtr == &tclParsedVarNameType) {
- if (part1Ptr->internalRep.twoPtrValue.ptr1 != NULL) {
- if (part2 != NULL) {
- /*
- * ERROR: part1Ptr is already an array element, cannot
- * specify a part2.
- */
- if (flags & TCL_LEAVE_ERR_MSG) {
- part1 = TclGetString(part1Ptr);
- VarErrMsg(interp, part1, part2, msg, needArray);
- }
- return NULL;
- }
- part2 = (char *) part1Ptr->internalRep.twoPtrValue.ptr2;
- part1Ptr = (Tcl_Obj *) part1Ptr->internalRep.twoPtrValue.ptr1;
- typePtr = part1Ptr->typePtr;
- }
- parsed = 1;
- }
- part1 = Tcl_GetStringFromObj(part1Ptr, &len1);
+#if ENABLE_NS_VARNAME_CACHING
+ if (varFramePtr) {
+ nsPtr = varFramePtr->nsPtr;
+ } else {
+ /*
+ * Some variables in the global ns have to be initialized before the
+ * root call frame is in place.
+ */
- nsPtr = ((varFramePtr == NULL)? iPtr->globalNsPtr : varFramePtr->nsPtr);
- if (nsPtr->varResProc != NULL || iPtr->resolverPtr != NULL) {
- goto doParse;
+ nsPtr = NULL;
}
-
- if (typePtr == &tclLocalVarNameType) {
- Proc *procPtr = (Proc *) part1Ptr->internalRep.twoPtrValue.ptr1;
- int localIndex = (int) part1Ptr->internalRep.twoPtrValue.ptr2;
- int useLocal;
+#endif
- useLocal = ((varFramePtr != NULL) && varFramePtr->isProcCallFrame
- && !(flags & (TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY)));
- if (useLocal && (procPtr == varFramePtr->procPtr)) {
+ if (typePtr == &localVarNameType) {
+ int localIndex;
+
+ localVarNameTypeHandling:
+ localIndex = (int) part1Ptr->internalRep.ptrAndLongRep.value;
+ if (HasLocalVars(varFramePtr)
+ && !(flags & (TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY))
+ && (localIndex < varFramePtr->numCompiledLocals)) {
/*
- * part1Ptr points to an indexed local variable of the
- * correct procedure: use the cached value.
+ * Use the cached index if the names coincide.
*/
-
- varPtr = &(varFramePtr->compiledLocals[localIndex]);
- goto donePart1;
+
+ Tcl_Obj *namePtr = (Tcl_Obj *)
+ part1Ptr->internalRep.ptrAndLongRep.ptr;
+ Tcl_Obj *checkNamePtr = localName(iPtr->varFramePtr, localIndex);
+
+ if ((!namePtr && (checkNamePtr == part1Ptr)) ||
+ (namePtr && (checkNamePtr == namePtr))) {
+ varPtr = (Var *) &(varFramePtr->compiledLocals[localIndex]);
+ goto donePart1;
+ }
}
goto doneParsing;
+#if ENABLE_NS_VARNAME_CACHING
} else if (typePtr == &tclNsVarNameType) {
- Namespace *cachedNsPtr;
int useGlobal, useReference;
+ Namespace *cachedNsPtr = part1Ptr->internalRep.twoPtrValue.ptr1;
+ varPtr = part1Ptr->internalRep.twoPtrValue.ptr2;
+
+ useGlobal = (cachedNsPtr == iPtr->globalNsPtr) && (
+ (flags & TCL_GLOBAL_ONLY) ||
+ (part1[0]==':' && part1[1]==':') ||
+ (!HasLocalVars(varFramePtr) && (nsPtr==iPtr->globalNsPtr)));
- varPtr = (Var *) part1Ptr->internalRep.twoPtrValue.ptr2;
- cachedNsPtr = (Namespace *) part1Ptr->internalRep.twoPtrValue.ptr1;
- useGlobal = (cachedNsPtr == iPtr->globalNsPtr)
- && ((flags & TCL_GLOBAL_ONLY)
- || ((*part1 == ':') && (*(part1+1) == ':'))
- || (varFramePtr == NULL)
- || (!varFramePtr->isProcCallFrame
- && (nsPtr == iPtr->globalNsPtr)));
- useReference = useGlobal || ((cachedNsPtr == nsPtr)
- && ((flags & TCL_NAMESPACE_ONLY)
- || (varFramePtr && !varFramePtr->isProcCallFrame
- && !(flags & TCL_GLOBAL_ONLY)
- /* careful: an undefined ns variable could
- * be hiding a valid global reference. */
- && !(varPtr->flags & VAR_UNDEFINED))));
- if (useReference && (varPtr->hPtr != NULL)) {
+ useReference = useGlobal || ((cachedNsPtr == nsPtr) && (
+ (flags & TCL_NAMESPACE_ONLY) ||
+ (!HasLocalVars(varFramePtr) && !(flags & TCL_GLOBAL_ONLY) &&
+ /*
+ * Careful: an undefined ns variable could be hiding a valid
+ * global reference.
+ */
+ !TclIsVarUndefined(varPtr))));
+
+ if (useReference && !TclIsVarDeadHash(varPtr)) {
/*
- * A straight global or namespace reference, use it. It isn't
- * so simple to deal with 'implicit' namespace references, i.e.,
- * those where the reference could be to either a namespace
- * or a global variable. Those we lookup again.
+ * A straight global or namespace reference, use it. It isn't so
+ * simple to deal with 'implicit' namespace references, i.e.,
+ * those where the reference could be to either a namespace or a
+ * global variable. Those we lookup again.
*
- * If (varPtr->hPtr == NULL), this might be a reference to a
+ * If TclIsVarDeadHash(varPtr), this might be a reference to a
* variable in a deleted namespace, kept alive by e.g. part1Ptr.
* We could conceivably be so unlucky that a new namespace was
- * created at the same address as the deleted one, so to be
- * safe we test for a valid hPtr.
+ * created at the same address as the deleted one, so to be safe
+ * we test for a valid hPtr.
*/
+
goto donePart1;
}
goto doneParsing;
+#endif
}
- doParse:
+ /*
+ * If part1Ptr is a tclParsedVarNameType, separate it into the pre-parsed
+ * parts.
+ */
+
+ if (typePtr == &tclParsedVarNameType) {
+ if (part1Ptr->internalRep.twoPtrValue.ptr1 != NULL) {
+ if (part2Ptr != NULL) {
+ /*
+ * ERROR: part1Ptr is already an array element, cannot specify
+ * a part2.
+ */
+
+ if (flags & TCL_LEAVE_ERR_MSG) {
+ TclObjVarErrMsg(interp, part1Ptr, part2Ptr, msg,
+ noSuchVar, -1);
+ }
+ return NULL;
+ }
+ part2 = newPart2 = part1Ptr->internalRep.twoPtrValue.ptr2;
+ if (newPart2) {
+ part2Ptr = Tcl_NewStringObj(newPart2, -1);
+ Tcl_IncrRefCount(part2Ptr);
+ }
+ part1Ptr = part1Ptr->internalRep.twoPtrValue.ptr1;
+ typePtr = part1Ptr->typePtr;
+ if (typePtr == &localVarNameType) {
+ goto localVarNameTypeHandling;
+ }
+ }
+ parsed = 1;
+ }
+ part1 = TclGetStringFromObj(part1Ptr, &len1);
+
if (!parsed && (*(part1 + len1 - 1) == ')')) {
/*
* part1Ptr is possibly an unparsed array element.
*/
+
register int i;
- char *newPart2;
+
len2 = -1;
for (i = 0; i < len1; i++) {
if (*(part1 + i) == '(') {
- if (part2 != NULL) {
+ if (part2Ptr != NULL) {
if (flags & TCL_LEAVE_ERR_MSG) {
- VarErrMsg(interp, part1, part2, msg, needArray);
+ TclObjVarErrMsg(interp, part1Ptr, part2Ptr, msg,
+ needArray, -1);
}
- }
+ return NULL;
+ }
/*
- * part1Ptr points to an array element; first copy
- * the element name to a new string part2.
+ * part1Ptr points to an array element; first copy the element
+ * name to a new string part2.
*/
part2 = part1 + i + 1;
@@ -484,30 +661,30 @@ TclObjLookupVar(interp, part1Ptr, part2, flags, msg, createPart1, createPart2,
memcpy(newPart2, part2, (unsigned int) len2);
*(newPart2+len2) = '\0';
part2 = newPart2;
+ part2Ptr = Tcl_NewStringObj(newPart2, -1);
+ Tcl_IncrRefCount(part2Ptr);
/*
- * Free the internal rep of the original part1Ptr, now
- * renamed objPtr, and set it to tclParsedVarNameType.
+ * Free the internal rep of the original part1Ptr, now renamed
+ * objPtr, and set it to tclParsedVarNameType.
*/
objPtr = part1Ptr;
- if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
- typePtr->freeIntRepProc(objPtr);
- }
+ TclFreeIntRep(objPtr);
objPtr->typePtr = &tclParsedVarNameType;
/*
- * Define a new string object to hold the new part1Ptr, i.e.,
+ * Define a new string object to hold the new part1Ptr, i.e.,
* the array name. Set the internal rep of objPtr, reset
- * typePtr and part1 to contain the references to the
- * array name.
+ * typePtr and part1 to contain the references to the array
+ * name.
*/
- part1Ptr = Tcl_NewStringObj(part1, len1);
+ TclNewStringObj(part1Ptr, part1, len1);
Tcl_IncrRefCount(part1Ptr);
- objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) part1Ptr;
- objPtr->internalRep.twoPtrValue.ptr2 = (VOID *) part2;
+ objPtr->internalRep.twoPtrValue.ptr1 = part1Ptr;
+ objPtr->internalRep.twoPtrValue.ptr2 = (void *) part2;
typePtr = part1Ptr->typePtr;
part1 = TclGetString(part1Ptr);
@@ -515,23 +692,24 @@ TclObjLookupVar(interp, part1Ptr, part2, flags, msg, createPart1, createPart2,
}
}
}
-
- doneParsing:
+
+ doneParsing:
/*
- * part1Ptr is not an array element; look it up, and convert
- * it to one of the cached types if possible.
+ * part1Ptr is not an array element; look it up, and convert it to one of
+ * the cached types if possible.
*/
- if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
- typePtr->freeIntRepProc(part1Ptr);
- part1Ptr->typePtr = NULL;
- }
+ TclFreeIntRep(part1Ptr);
+ part1Ptr->typePtr = NULL;
- varPtr = TclLookupSimpleVar(interp, part1, flags,
- createPart1, &errMsg, &index);
+ varPtr = TclLookupSimpleVar(interp, part1Ptr, flags, createPart1,
+ &errMsg, &index);
if (varPtr == NULL) {
if ((errMsg != NULL) && (flags & TCL_LEAVE_ERR_MSG)) {
- VarErrMsg(interp, part1, part2, msg, errMsg);
+ TclObjVarErrMsg(interp, part1Ptr, part2Ptr, msg, errMsg, -1);
+ }
+ if (newPart2) {
+ Tcl_DecrRefCount(part2Ptr);
}
return NULL;
}
@@ -541,52 +719,51 @@ TclObjLookupVar(interp, part1Ptr, part2, flags, msg, createPart1, createPart2,
*/
if (index >= 0) {
- /*
+ /*
* An indexed local variable.
*/
- Proc *procPtr = ((Interp *) interp)->varFramePtr->procPtr;
-
- part1Ptr->typePtr = &tclLocalVarNameType;
- procPtr->refCount++;
- part1Ptr->internalRep.twoPtrValue.ptr1 = (VOID *) procPtr;
- part1Ptr->internalRep.twoPtrValue.ptr2 = (VOID *) index;
-#if 0
- /*
- * TEMPORARYLY DISABLED tclNsVarNameType
- *
- * This optimisation will hopefully be turned back on soon.
- * Miguel Sofer, 2004-05-22
- */
-
+ part1Ptr->typePtr = &localVarNameType;
+ if (part1Ptr != localName(iPtr->varFramePtr, index)) {
+ part1Ptr->internalRep.ptrAndLongRep.ptr =
+ localName(iPtr->varFramePtr, index);
+ Tcl_IncrRefCount((Tcl_Obj *)
+ part1Ptr->internalRep.ptrAndLongRep.ptr);
+ } else {
+ part1Ptr->internalRep.ptrAndLongRep.ptr = NULL;
+ }
+ part1Ptr->internalRep.ptrAndLongRep.value = (long) index;
+#if ENABLE_NS_VARNAME_CACHING
} else if (index > -3) {
/*
* A cacheable namespace or global variable.
*/
+
Namespace *nsPtr;
-
- nsPtr = ((index == -1)? iPtr->globalNsPtr : varFramePtr->nsPtr);
+
+ nsPtr = ((index == -1) ? iPtr->globalNsPtr : varFramePtr->nsPtr);
varPtr->refCount++;
part1Ptr->typePtr = &tclNsVarNameType;
- part1Ptr->internalRep.twoPtrValue.ptr1 = (VOID *) nsPtr;
- part1Ptr->internalRep.twoPtrValue.ptr2 = (VOID *) varPtr;
+ part1Ptr->internalRep.twoPtrValue.ptr1 = nsPtr;
+ part1Ptr->internalRep.twoPtrValue.ptr2 = varPtr;
#endif
} else {
/*
* At least mark part1Ptr as already parsed.
*/
+
part1Ptr->typePtr = &tclParsedVarNameType;
part1Ptr->internalRep.twoPtrValue.ptr1 = NULL;
part1Ptr->internalRep.twoPtrValue.ptr2 = NULL;
}
-
- donePart1:
+
+ donePart1:
#if 0
if (varPtr == NULL) {
if (flags & TCL_LEAVE_ERR_MSG) {
part1 = TclGetString(part1Ptr);
- VarErrMsg(interp, part1, part2, msg,
- "Cached variable reference is NULL.");
+ TclObjVarErrMsg(interp, part1Ptr, part2Ptr, msg,
+ "Cached variable reference is NULL.", -1);
}
return NULL;
}
@@ -595,63 +772,71 @@ TclObjLookupVar(interp, part1Ptr, part2, flags, msg, createPart1, createPart2,
varPtr = varPtr->value.linkPtr;
}
- if (part2 != NULL) {
+ if (part2Ptr != NULL) {
/*
* Array element sought: look it up.
*/
- part1 = TclGetString(part1Ptr);
*arrayPtrPtr = varPtr;
- varPtr = TclLookupArrayElement(interp, part1, part2,
- flags, msg, createPart1, createPart2, varPtr);
+ varPtr = TclLookupArrayElement(interp, part1Ptr, part2Ptr, flags, msg,
+ createPart1, createPart2, varPtr, -1);
+ if (newPart2) {
+ Tcl_DecrRefCount(part2Ptr);
+ }
}
return varPtr;
}
/*
- * This flag bit should not interfere with TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
- * or TCL_LEAVE_ERR_MSG; it signals that the variable lookup is performed for
- * upvar (or similar) purposes, with slightly different rules:
- * - Bug #696893 - variable is either proc-local or in the current
- * namespace; never follow the second (global) resolution path
- * - Bug #631741 - do not use special namespace or interp resolvers
+ * This flag bit should not interfere with TCL_GLOBAL_ONLY,
+ * TCL_NAMESPACE_ONLY, or TCL_LEAVE_ERR_MSG; it signals that the variable
+ * lookup is performed for upvar (or similar) purposes, with slightly
+ * different rules:
+ * - Bug #696893 - variable is either proc-local or in the current
+ * namespace; never follow the second (global) resolution path
+ * - Bug #631741 - do not use special namespace or interp resolvers
+ *
+ * It should also not collide with the (deprecated) TCL_PARSE_PART1 flag
+ * (Bug #835020)
*/
-#define LOOKUP_FOR_UPVAR 0x40000
+
+#define AVOID_RESOLVERS 0x40000
/*
*----------------------------------------------------------------------
*
* TclLookupSimpleVar --
*
- * This procedure is used by to locate a simple variable (i.e., not
- * an array element) given its name.
+ * This function is used by to locate a simple variable (i.e., not an
+ * array element) given its name.
*
* Results:
* The return value is a pointer to the variable structure indicated by
- * varName, or NULL if the variable couldn't be found. If the variable
- * can't be found and create is 1, a new as-yet-undefined (VAR_UNDEFINED)
- * variable structure is created, entered into a hash table, and returned.
- *
- * If the current CallFrame corresponds to a proc and the variable found is
- * one of the compiledLocals, its index is placed in *indexPtr. Otherwise,
- * *indexPtr will be set to (according to the needs of TclObjLookupVar):
- * -1 a global reference
- * -2 a reference to a namespace variable
- * -3 a non-cachable reference, i.e., one of:
- * . non-indexed local var
- * . a reference of unknown origin;
- * . resolution by a namespace or interp resolver
+ * varName, or NULL if the variable couldn't be found. If the variable
+ * can't be found and create is 1, a new as-yet-undefined (VAR_UNDEFINED)
+ * variable structure is created, entered into a hash table, and
+ * returned.
+ *
+ * If the current CallFrame corresponds to a proc and the variable found
+ * is one of the compiledLocals, its index is placed in *indexPtr.
+ * Otherwise, *indexPtr will be set to (according to the needs of
+ * TclObjLookupVar):
+ * -1 a global reference
+ * -2 a reference to a namespace variable
+ * -3 a non-cachable reference, i.e., one of:
+ * . non-indexed local var
+ * . a reference of unknown origin;
+ * . resolution by a namespace or interp resolver
*
* If the variable isn't found and creation wasn't specified, or some
* other error occurs, NULL is returned and the corresponding error
- * message is left in *errMsgPtr.
+ * message is left in *errMsgPtr.
*
- * Note: it's possible for the variable returned to be VAR_UNDEFINED
- * even if create is 1 (this only causes the hash table entry to be
- * created). For example, the variable might be a global that has been
- * unset but is still referenced by a procedure, or a variable that has
- * been unset but it only being kept in existence (if VAR_UNDEFINED) by
- * a trace.
+ * Note: it's possible for the variable returned to be VAR_UNDEFINED even
+ * if create is 1 (this only causes the hash table entry to be created).
+ * For example, the variable might be a global that has been unset but is
+ * still referenced by a procedure, or a variable that has been unset but
+ * it only being kept in existence (if VAR_UNDEFINED) by a trace.
*
* Side effects:
* A new hashtable entry may be created if create is 1.
@@ -660,206 +845,191 @@ TclObjLookupVar(interp, part1Ptr, part2, flags, msg, createPart1, createPart2,
*/
Var *
-TclLookupSimpleVar(interp, varName, flags, create, errMsgPtr, indexPtr)
- Tcl_Interp *interp; /* Interpreter to use for lookup. */
- CONST char *varName; /* This is a simple variable name that could
- * representa scalar or an array. */
- int flags; /* Only TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
- * LOOKUP_FOR_UPVAR and TCL_LEAVE_ERR_MSG bits
+TclLookupSimpleVar(
+ Tcl_Interp *interp, /* Interpreter to use for lookup. */
+ Tcl_Obj *varNamePtr, /* This is a simple variable name that could
+ * represent a scalar or an array. */
+ int flags, /* Only TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
+ * AVOID_RESOLVERS and TCL_LEAVE_ERR_MSG bits
* matter. */
- CONST int create; /* If 1, create hash table entry for varname,
- * if it doesn't already exist. If 0, return
+ const int create, /* If 1, create hash table entry for varname,
+ * if it doesn't already exist. If 0, return
* error if it doesn't exist. */
- CONST char **errMsgPtr;
- int *indexPtr;
-{
+ const char **errMsgPtr,
+ int *indexPtr)
+{
Interp *iPtr = (Interp *) interp;
CallFrame *varFramePtr = iPtr->varFramePtr;
/* Points to the procedure call frame whose
- * variables are currently in use. Same as
- * the current procedure's frame, if any,
- * unless an "uplevel" is executing. */
- Tcl_HashTable *tablePtr; /* Points to the hashtable, if any, in which
+ * variables are currently in use. Same as the
+ * current procedure's frame, if any, unless
+ * an "uplevel" is executing. */
+ TclVarHashTable *tablePtr; /* Points to the hashtable, if any, in which
* to look up the variable. */
- Tcl_Var var; /* Used to search for global names. */
+ Tcl_Var var; /* Used to search for global names. */
Var *varPtr; /* Points to the Var structure returned for
* the variable. */
Namespace *varNsPtr, *cxtNsPtr, *dummy1Ptr, *dummy2Ptr;
ResolverScheme *resPtr;
- Tcl_HashEntry *hPtr;
- int new, i, result;
+ int isNew, i, result;
+ const char *varName = TclGetString(varNamePtr);
varPtr = NULL;
- varNsPtr = NULL; /* set non-NULL if a nonlocal variable */
+ varNsPtr = NULL; /* Set non-NULL if a nonlocal variable. */
*indexPtr = -3;
- if ((flags & TCL_GLOBAL_ONLY) || iPtr->varFramePtr == NULL) {
- cxtNsPtr = iPtr->globalNsPtr;
+ if (flags & TCL_GLOBAL_ONLY) {
+ cxtNsPtr = iPtr->globalNsPtr;
} else {
- cxtNsPtr = iPtr->varFramePtr->nsPtr;
+ cxtNsPtr = iPtr->varFramePtr->nsPtr;
}
/*
- * If this namespace has a variable resolver, then give it first
- * crack at the variable resolution. It may return a Tcl_Var
- * value, it may signal to continue onward, or it may signal
- * an error.
+ * If this namespace has a variable resolver, then give it first crack at
+ * the variable resolution. It may return a Tcl_Var value, it may signal
+ * to continue onward, or it may signal an error.
*/
- if ((cxtNsPtr->varResProc != NULL || iPtr->resolverPtr != NULL)
- && !(flags & LOOKUP_FOR_UPVAR)) {
- resPtr = iPtr->resolverPtr;
-
- if (cxtNsPtr->varResProc) {
- result = (*cxtNsPtr->varResProc)(interp, varName,
+ if ((cxtNsPtr->varResProc != NULL || iPtr->resolverPtr != NULL)
+ && !(flags & AVOID_RESOLVERS)) {
+ resPtr = iPtr->resolverPtr;
+ if (cxtNsPtr->varResProc) {
+ result = (*cxtNsPtr->varResProc)(interp, varName,
(Tcl_Namespace *) cxtNsPtr, flags, &var);
- } else {
- result = TCL_CONTINUE;
- }
+ } else {
+ result = TCL_CONTINUE;
+ }
- while (result == TCL_CONTINUE && resPtr) {
- if (resPtr->varResProc) {
- result = (*resPtr->varResProc)(interp, varName,
+ while (result == TCL_CONTINUE && resPtr) {
+ if (resPtr->varResProc) {
+ result = (*resPtr->varResProc)(interp, varName,
(Tcl_Namespace *) cxtNsPtr, flags, &var);
- }
- resPtr = resPtr->nextPtr;
- }
-
- if (result == TCL_OK) {
- varPtr = (Var *) var;
- return varPtr;
- } else if (result != TCL_CONTINUE) {
+ }
+ resPtr = resPtr->nextPtr;
+ }
+
+ if (result == TCL_OK) {
+ return (Var *) var;
+ } else if (result != TCL_CONTINUE) {
return NULL;
- }
+ }
}
/*
* Look up varName. Look it up as either a namespace variable or as a
- * local variable in a procedure call frame (varFramePtr).
- * Interpret varName as a namespace variable if:
+ * local variable in a procedure call frame (varFramePtr). Interpret
+ * varName as a namespace variable if:
* 1) so requested by a TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY flag,
* 2) there is no active frame (we're at the global :: scope),
- * 3) the active frame was pushed to define the namespace context
- * for a "namespace eval" or "namespace inscope" command,
+ * 3) the active frame was pushed to define the namespace context for a
+ * "namespace eval" or "namespace inscope" command,
* 4) the name has namespace qualifiers ("::"s).
- * Otherwise, if varName is a local variable, search first in the
- * frame's array of compiler-allocated local variables, then in its
- * hashtable for runtime-created local variables.
+ * Otherwise, if varName is a local variable, search first in the frame's
+ * array of compiler-allocated local variables, then in its hashtable for
+ * runtime-created local variables.
*
- * If create and the variable isn't found, create the variable and,
- * if necessary, create varFramePtr's local var hashtable.
+ * If create and the variable isn't found, create the variable and, if
+ * necessary, create varFramePtr's local var hashtable.
*/
if (((flags & (TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY)) != 0)
- || (varFramePtr == NULL)
- || !varFramePtr->isProcCallFrame
+ || !HasLocalVars(varFramePtr)
|| (strstr(varName, "::") != NULL)) {
- CONST char *tail;
- int lookGlobal;
-
- lookGlobal = (flags & TCL_GLOBAL_ONLY)
- || (cxtNsPtr == iPtr->globalNsPtr)
- || ((*varName == ':') && (*(varName+1) == ':'));
+ const char *tail;
+ int lookGlobal = (flags & TCL_GLOBAL_ONLY)
+ || (cxtNsPtr == iPtr->globalNsPtr)
+ || ((*varName == ':') && (*(varName+1) == ':'));
+
if (lookGlobal) {
*indexPtr = -1;
- flags = (flags | TCL_GLOBAL_ONLY) & ~(TCL_NAMESPACE_ONLY|LOOKUP_FOR_UPVAR);
+ flags = (flags | TCL_GLOBAL_ONLY) & ~TCL_NAMESPACE_ONLY;
} else {
- if (flags & LOOKUP_FOR_UPVAR) {
- flags = (flags | TCL_NAMESPACE_ONLY) & ~LOOKUP_FOR_UPVAR;
+ if (flags & AVOID_RESOLVERS) {
+ flags = (flags | TCL_NAMESPACE_ONLY);
}
if (flags & TCL_NAMESPACE_ONLY) {
*indexPtr = -2;
}
- }
+ }
/*
- * Don't pass TCL_LEAVE_ERR_MSG, we may yet create the variable,
- * or otherwise generate our own error!
+ * Don't pass TCL_LEAVE_ERR_MSG, we may yet create the variable, or
+ * otherwise generate our own error!
*/
- var = Tcl_FindNamespaceVar(interp, varName, (Tcl_Namespace *) cxtNsPtr,
- flags & ~TCL_LEAVE_ERR_MSG);
- if (var != (Tcl_Var) NULL) {
- varPtr = (Var *) var;
- }
+
+ varPtr = (Var *) ObjFindNamespaceVar(interp, varNamePtr,
+ (Tcl_Namespace *) cxtNsPtr,
+ (flags | AVOID_RESOLVERS) & ~TCL_LEAVE_ERR_MSG);
if (varPtr == NULL) {
- if (create) { /* var wasn't found so create it */
+ Tcl_Obj *tailPtr;
+
+ if (create) { /* Var wasn't found so create it. */
TclGetNamespaceForQualName(interp, varName, cxtNsPtr,
flags, &varNsPtr, &dummy1Ptr, &dummy2Ptr, &tail);
if (varNsPtr == NULL) {
*errMsgPtr = badNamespace;
return NULL;
- }
- if (tail == NULL) {
+ } else if (tail == NULL) {
*errMsgPtr = missingName;
return NULL;
}
- hPtr = Tcl_CreateHashEntry(&varNsPtr->varTable, tail, &new);
- varPtr = NewVar();
- Tcl_SetHashValue(hPtr, varPtr);
- varPtr->hPtr = hPtr;
- varPtr->nsPtr = varNsPtr;
- if ((lookGlobal) || (varNsPtr == NULL)) {
+ if (tail != varName) {
+ tailPtr = Tcl_NewStringObj(tail, -1);
+ } else {
+ tailPtr = varNamePtr;
+ }
+ varPtr = VarHashCreateVar(&varNsPtr->varTable, tailPtr,
+ &isNew);
+ if (lookGlobal) {
/*
* The variable was created starting from the global
- * namespace: a global reference is returned even if
- * it wasn't explicitly requested.
+ * namespace: a global reference is returned even if it
+ * wasn't explicitly requested.
*/
+
*indexPtr = -1;
} else {
*indexPtr = -2;
}
- } else { /* var wasn't found and not to create it */
+ } else { /* Var wasn't found and not to create it. */
*errMsgPtr = noSuchVar;
return NULL;
}
}
- } else { /* local var: look in frame varFramePtr */
- Proc *procPtr = varFramePtr->procPtr;
- int localCt = procPtr->numCompiledLocals;
- CompiledLocal *localPtr = procPtr->firstLocalPtr;
- Var *localVarPtr = varFramePtr->compiledLocals;
- int varNameLen = strlen(varName);
-
- for (i = 0; i < localCt; i++) {
- if (!TclIsVarTemporary(localPtr)) {
- register char *localName = localVarPtr->name;
+ } else { /* Local var: look in frame varFramePtr. */
+ int localCt = varFramePtr->numCompiledLocals;
+ Tcl_Obj **objPtrPtr = &varFramePtr->localCachePtr->varName0;
+
+ for (i=0 ; i<localCt ; i++, objPtrPtr++) {
+ register Tcl_Obj *objPtr = *objPtrPtr;
+
+ if (objPtr) {
+ char *localName = TclGetString(objPtr);
+
if ((varName[0] == localName[0])
- && (varNameLen == localPtr->nameLength)
- && (strcmp(varName, localName) == 0)) {
+ && (strcmp(varName, localName) == 0)) {
*indexPtr = i;
- return localVarPtr;
+ return (Var *) &varFramePtr->compiledLocals[i];
}
}
- localVarPtr++;
- localPtr = localPtr->nextPtr;
}
tablePtr = varFramePtr->varTablePtr;
if (create) {
if (tablePtr == NULL) {
- tablePtr = (Tcl_HashTable *)
- ckalloc(sizeof(Tcl_HashTable));
- Tcl_InitHashTable(tablePtr, TCL_STRING_KEYS);
+ tablePtr = (TclVarHashTable *)
+ ckalloc(sizeof(TclVarHashTable));
+ TclInitVarHashTable(tablePtr, NULL);
varFramePtr->varTablePtr = tablePtr;
}
- hPtr = Tcl_CreateHashEntry(tablePtr, varName, &new);
- if (new) {
- varPtr = NewVar();
- Tcl_SetHashValue(hPtr, varPtr);
- varPtr->hPtr = hPtr;
- varPtr->nsPtr = NULL; /* a local variable */
- } else {
- varPtr = (Var *) Tcl_GetHashValue(hPtr);
- }
+ varPtr = VarHashCreateVar(tablePtr, varNamePtr, &isNew);
} else {
- hPtr = NULL;
+ varPtr = NULL;
if (tablePtr != NULL) {
- hPtr = Tcl_FindHashEntry(tablePtr, varName);
+ varPtr = VarHashFindVar(tablePtr, varNamePtr);
}
- if (hPtr == NULL) {
+ if (varPtr == NULL) {
*errMsgPtr = noSuchVar;
- return NULL;
}
- varPtr = (Var *) Tcl_GetHashValue(hPtr);
}
}
return varPtr;
@@ -870,69 +1040,73 @@ TclLookupSimpleVar(interp, varName, flags, create, errMsgPtr, indexPtr)
*
* TclLookupArrayElement --
*
- * This procedure is used to locate a variable which is in an array's
- * hashtable given a pointer to the array's Var structure and the
- * element's name.
+ * This function is used to locate a variable which is in an array's
+ * hashtable given a pointer to the array's Var structure and the
+ * element's name.
*
* Results:
- * The return value is a pointer to the variable structure , or NULL if
- * the variable couldn't be found.
+ * The return value is a pointer to the variable structure , or NULL if
+ * the variable couldn't be found.
*
- * If arrayPtr points to a variable that isn't an array and createPart1
- * is 1, the corresponding variable will be converted to an array.
- * Otherwise, NULL is returned and an error message is left in
- * the interp's result if TCL_LEAVE_ERR_MSG is set in flags.
+ * If arrayPtr points to a variable that isn't an array and createPart1
+ * is 1, the corresponding variable will be converted to an array.
+ * Otherwise, NULL is returned and an error message is left in the
+ * interp's result if TCL_LEAVE_ERR_MSG is set in flags.
*
- * If the variable is not found and createPart2 is 1, the variable is
- * created. Otherwise, NULL is returned and an error message is left in
+ * If the variable is not found and createPart2 is 1, the variable is
+ * created. Otherwise, NULL is returned and an error message is left in
* the interp's result if TCL_LEAVE_ERR_MSG is set in flags.
*
- * Note: it's possible for the variable returned to be VAR_UNDEFINED
- * even if createPart1 or createPart2 are 1 (these only cause the hash
- * table entry or array to be created). For example, the variable might
- * be a global that has been unset but is still referenced by a
- * procedure, or a variable that has been unset but it only being kept
- * in existence (if VAR_UNDEFINED) by a trace.
+ * Note: it's possible for the variable returned to be VAR_UNDEFINED even
+ * if createPart1 or createPart2 are 1 (these only cause the hash table
+ * entry or array to be created). For example, the variable might be a
+ * global that has been unset but is still referenced by a procedure, or
+ * a variable that has been unset but it only being kept in existence (if
+ * VAR_UNDEFINED) by a trace.
*
* Side effects:
- * The variable at arrayPtr may be converted to be an array if
- * createPart1 is 1. A new hashtable entry may be created if createPart2
- * is 1.
+ * The variable at arrayPtr may be converted to be an array if
+ * createPart1 is 1. A new hashtable entry may be created if createPart2
+ * is 1.
*
*----------------------------------------------------------------------
*/
Var *
-TclLookupArrayElement(interp, arrayName, elName, flags, msg, createArray, createElem, arrayPtr)
- Tcl_Interp *interp; /* Interpreter to use for lookup. */
- CONST char *arrayName; /* This is the name of the array. */
- CONST char *elName; /* Name of element within array. */
- CONST int flags; /* Only TCL_LEAVE_ERR_MSG bit matters. */
- CONST char *msg; /* Verb to use in error messages, e.g.
- * "read" or "set". Only needed if
- * TCL_LEAVE_ERR_MSG is set in flags. */
- CONST int createArray; /* If 1, transform arrayName to be an array
- * if it isn't one yet and the transformation
- * is possible. If 0, return error if it
- * isn't already an array. */
- CONST int createElem; /* If 1, create hash table entry for the
- * element, if it doesn't already exist. If
- * 0, return error if it doesn't exist. */
- Var *arrayPtr; /* Pointer to the array's Var structure. */
+TclLookupArrayElement(
+ Tcl_Interp *interp, /* Interpreter to use for lookup. */
+ Tcl_Obj *arrayNamePtr, /* This is the name of the array, or NULL if
+ * index>= 0. */
+ Tcl_Obj *elNamePtr, /* Name of element within array. */
+ const int flags, /* Only TCL_LEAVE_ERR_MSG bit matters. */
+ const char *msg, /* Verb to use in error messages, e.g. "read"
+ * or "set". Only needed if TCL_LEAVE_ERR_MSG
+ * is set in flags. */
+ const int createArray, /* If 1, transform arrayName to be an array if
+ * it isn't one yet and the transformation is
+ * possible. If 0, return error if it isn't
+ * already an array. */
+ const int createElem, /* If 1, create hash table entry for the
+ * element, if it doesn't already exist. If 0,
+ * return error if it doesn't exist. */
+ Var *arrayPtr, /* Pointer to the array's Var structure. */
+ int index) /* If >=0, the index of the local array. */
{
- Tcl_HashEntry *hPtr;
- int new;
+ int isNew;
Var *varPtr;
+ TclVarHashTable *tablePtr;
+ Namespace *nsPtr;
/*
- * We're dealing with an array element. Make sure the variable is an
- * array and look up the element (create the element if desired).
+ * We're dealing with an array element. Make sure the variable is an array
+ * and look up the element (create the element if desired).
*/
if (TclIsVarUndefined(arrayPtr) && !TclIsVarArrayElement(arrayPtr)) {
if (!createArray) {
if (flags & TCL_LEAVE_ERR_MSG) {
- VarErrMsg(interp, arrayName, elName, msg, noSuchVar);
+ TclObjVarErrMsg(interp, arrayNamePtr, elNamePtr, msg,
+ noSuchVar, index);
}
return NULL;
}
@@ -941,47 +1115,54 @@ TclLookupArrayElement(interp, arrayName, elName, flags, msg, createArray, create
* Make sure we are not resurrecting a namespace variable from a
* deleted namespace!
*/
- if ((arrayPtr->flags & VAR_IN_HASHTABLE) && (arrayPtr->hPtr == NULL)) {
+
+ if (TclIsVarDeadHash(arrayPtr)) {
if (flags & TCL_LEAVE_ERR_MSG) {
- VarErrMsg(interp, arrayName, elName, msg, danglingVar);
+ TclObjVarErrMsg(interp, arrayNamePtr, elNamePtr, msg,
+ danglingVar, index);
}
return NULL;
}
TclSetVarArray(arrayPtr);
- TclClearVarUndefined(arrayPtr);
- arrayPtr->value.tablePtr =
- (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
- Tcl_InitHashTable(arrayPtr->value.tablePtr, TCL_STRING_KEYS);
+ tablePtr = (TclVarHashTable *) ckalloc(sizeof(TclVarHashTable));
+ arrayPtr->value.tablePtr = tablePtr;
+
+ if (TclIsVarInHash(arrayPtr) && TclGetVarNsPtr(arrayPtr)) {
+ nsPtr = TclGetVarNsPtr(arrayPtr);
+ } else {
+ nsPtr = NULL;
+ }
+ TclInitVarHashTable(arrayPtr->value.tablePtr, nsPtr);
} else if (!TclIsVarArray(arrayPtr)) {
if (flags & TCL_LEAVE_ERR_MSG) {
- VarErrMsg(interp, arrayName, elName, msg, needArray);
+ TclObjVarErrMsg(interp, arrayNamePtr, elNamePtr, msg, needArray,
+ index);
}
return NULL;
}
if (createElem) {
- hPtr = Tcl_CreateHashEntry(arrayPtr->value.tablePtr, elName, &new);
- if (new) {
- if (arrayPtr->searchPtr != NULL) {
- DeleteSearches(arrayPtr);
+ varPtr = VarHashCreateVar(arrayPtr->value.tablePtr, elNamePtr,
+ &isNew);
+ if (isNew) {
+ if (arrayPtr->flags & VAR_SEARCH_ACTIVE) {
+ DeleteSearches((Interp *) interp, arrayPtr);
}
- varPtr = NewVar();
- Tcl_SetHashValue(hPtr, varPtr);
- varPtr->hPtr = hPtr;
- varPtr->nsPtr = arrayPtr->nsPtr;
TclSetVarArrayElement(varPtr);
}
} else {
- hPtr = Tcl_FindHashEntry(arrayPtr->value.tablePtr, elName);
- if (hPtr == NULL) {
+ varPtr = VarHashFindVar(arrayPtr->value.tablePtr, elNamePtr);
+ if (varPtr == NULL) {
if (flags & TCL_LEAVE_ERR_MSG) {
- VarErrMsg(interp, arrayName, elName, msg, noSuchElement);
+ TclObjVarErrMsg(interp, arrayNamePtr, elNamePtr, msg,
+ noSuchElement, index);
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ELEMENT",
+ TclGetString(elNamePtr), NULL);
}
- return NULL;
}
}
- return (Var *) Tcl_GetHashValue(hPtr);
+ return varPtr;
}
/*
@@ -993,9 +1174,9 @@ TclLookupArrayElement(interp, arrayName, elName, flags, msg, createArray, create
*
* Results:
* The return value points to the current value of varName as a string.
- * If the variable is not defined or can't be read because of a clash
- * in array usage then a NULL pointer is returned and an error message
- * is left in the interp's result if the TCL_LEAVE_ERR_MSG flag is set.
+ * If the variable is not defined or can't be read because of a clash in
+ * array usage then a NULL pointer is returned and an error message is
+ * left in the interp's result if the TCL_LEAVE_ERR_MSG flag is set.
* Note: the return value is only valid up until the next change to the
* variable; if you depend on the value lasting longer than that, then
* make yourself a private copy.
@@ -1006,16 +1187,16 @@ TclLookupArrayElement(interp, arrayName, elName, flags, msg, createArray, create
*----------------------------------------------------------------------
*/
-CONST char *
-Tcl_GetVar(interp, varName, flags)
- Tcl_Interp *interp; /* Command interpreter in which varName is
- * to be looked up. */
- CONST char *varName; /* Name of a variable in interp. */
- int flags; /* OR-ed combination of TCL_GLOBAL_ONLY,
+const char *
+Tcl_GetVar(
+ Tcl_Interp *interp, /* Command interpreter in which varName is to
+ * be looked up. */
+ const char *varName, /* Name of a variable in interp. */
+ int flags) /* OR-ed combination of TCL_GLOBAL_ONLY,
* TCL_NAMESPACE_ONLY or TCL_LEAVE_ERR_MSG
* bits. */
{
- return Tcl_GetVar2(interp, varName, (char *) NULL, flags);
+ return Tcl_GetVar2(interp, varName, NULL, flags);
}
/*
@@ -1023,17 +1204,17 @@ Tcl_GetVar(interp, varName, flags)
*
* Tcl_GetVar2 --
*
- * Return the value of a Tcl variable as a string, given a two-part
- * name consisting of array name and element within array.
+ * Return the value of a Tcl variable as a string, given a two-part name
+ * consisting of array name and element within array.
*
* Results:
- * The return value points to the current value of the variable given
- * by part1 and part2 as a string. If the specified variable doesn't
- * exist, or if there is a clash in array usage, then NULL is returned
- * and a message will be left in the interp's result if the
- * TCL_LEAVE_ERR_MSG flag is set. Note: the return value is only valid
- * up until the next change to the variable; if you depend on the value
- * lasting longer than that, then make yourself a private copy.
+ * The return value points to the current value of the variable given by
+ * part1 and part2 as a string. If the specified variable doesn't exist,
+ * or if there is a clash in array usage, then NULL is returned and a
+ * message will be left in the interp's result if the TCL_LEAVE_ERR_MSG
+ * flag is set. Note: the return value is only valid up until the next
+ * change to the variable; if you depend on the value lasting longer than
+ * that, then make yourself a private copy.
*
* Side effects:
* None.
@@ -1041,17 +1222,17 @@ Tcl_GetVar(interp, varName, flags)
*----------------------------------------------------------------------
*/
-CONST char *
-Tcl_GetVar2(interp, part1, part2, flags)
- Tcl_Interp *interp; /* Command interpreter in which variable is
- * to be looked up. */
- CONST char *part1; /* Name of an array (if part2 is non-NULL)
- * or the name of a variable. */
- CONST char *part2; /* If non-NULL, gives the name of an element
+const char *
+Tcl_GetVar2(
+ Tcl_Interp *interp, /* Command interpreter in which variable is to
+ * be looked up. */
+ const char *part1, /* Name of an array (if part2 is non-NULL) or
+ * the name of a variable. */
+ const char *part2, /* If non-NULL, gives the name of an element
* in the array part1. */
- int flags; /* OR-ed combination of TCL_GLOBAL_ONLY,
- * TCL_NAMESPACE_ONLY and TCL_LEAVE_ERR_MSG
- * bits. */
+ int flags) /* OR-ed combination of TCL_GLOBAL_ONLY,
+ * TCL_NAMESPACE_ONLY and TCL_LEAVE_ERR_MSG *
+ * bits. */
{
Tcl_Obj *objPtr;
@@ -1067,8 +1248,8 @@ Tcl_GetVar2(interp, part1, part2, flags)
*
* Tcl_GetVar2Ex --
*
- * Return the value of a Tcl variable as a Tcl object, given a
- * two-part name consisting of array name and element within array.
+ * Return the value of a Tcl variable as a Tcl object, given a two-part
+ * name consisting of array name and element within array.
*
* Results:
* The return value points to the current object value of the variable
@@ -1078,35 +1259,43 @@ Tcl_GetVar2(interp, part1, part2, flags)
* TCL_LEAVE_ERR_MSG flag is set.
*
* Side effects:
- * The ref count for the returned object is _not_ incremented to
- * reflect the returned reference; if you want to keep a reference to
- * the object you must increment its ref count yourself.
+ * The ref count for the returned object is _not_ incremented to reflect
+ * the returned reference; if you want to keep a reference to the object
+ * you must increment its ref count yourself.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
-Tcl_GetVar2Ex(interp, part1, part2, flags)
- Tcl_Interp *interp; /* Command interpreter in which variable is
- * to be looked up. */
- CONST char *part1; /* Name of an array (if part2 is non-NULL)
- * or the name of a variable. */
- CONST char *part2; /* If non-NULL, gives the name of an element
+Tcl_GetVar2Ex(
+ Tcl_Interp *interp, /* Command interpreter in which variable is to
+ * be looked up. */
+ const char *part1, /* Name of an array (if part2 is non-NULL) or
+ * the name of a variable. */
+ const char *part2, /* If non-NULL, gives the name of an element
* in the array part1. */
- int flags; /* OR-ed combination of TCL_GLOBAL_ONLY,
- * and TCL_LEAVE_ERR_MSG bits. */
+ int flags) /* OR-ed combination of TCL_GLOBAL_ONLY, and
+ * TCL_LEAVE_ERR_MSG bits. */
{
- Var *varPtr, *arrayPtr;
+ Tcl_Obj *part1Ptr, *part2Ptr, *resPtr;
- /* Filter to pass through only the flags this interface supports. */
- flags &= (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG);
- varPtr = TclLookupVar(interp, part1, part2, flags, "read",
- /*createPart1*/ 0, /*createPart2*/ 1, &arrayPtr);
- if (varPtr == NULL) {
- return NULL;
+ part1Ptr = Tcl_NewStringObj(part1, -1);
+ Tcl_IncrRefCount(part1Ptr);
+ if (part2) {
+ part2Ptr = Tcl_NewStringObj(part2, -1);
+ Tcl_IncrRefCount(part2Ptr);
+ } else {
+ part2Ptr = NULL;
+ }
+
+ resPtr = Tcl_ObjGetVar2(interp, part1Ptr, part2Ptr, flags);
+
+ Tcl_DecrRefCount(part1Ptr);
+ if (part2Ptr) {
+ Tcl_DecrRefCount(part2Ptr);
}
- return TclPtrGetVar(interp, varPtr, arrayPtr, part1, part2, flags);
+ return resPtr;
}
/*
@@ -1114,8 +1303,8 @@ Tcl_GetVar2Ex(interp, part1, part2, flags)
*
* Tcl_ObjGetVar2 --
*
- * Return the value of a Tcl variable as a Tcl object, given a
- * two-part name consisting of array name and element within array.
+ * Return the value of a Tcl variable as a Tcl object, given a two-part
+ * name consisting of array name and element within array.
*
* Results:
* The return value points to the current object value of the variable
@@ -1125,41 +1314,41 @@ Tcl_GetVar2Ex(interp, part1, part2, flags)
* TCL_LEAVE_ERR_MSG flag is set.
*
* Side effects:
- * The ref count for the returned object is _not_ incremented to
- * reflect the returned reference; if you want to keep a reference to
- * the object you must increment its ref count yourself.
+ * The ref count for the returned object is _not_ incremented to reflect
+ * the returned reference; if you want to keep a reference to the object
+ * you must increment its ref count yourself.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
-Tcl_ObjGetVar2(interp, part1Ptr, part2Ptr, flags)
- Tcl_Interp *interp; /* Command interpreter in which variable is
- * to be looked up. */
- register Tcl_Obj *part1Ptr; /* Points to an object holding the name of
- * an array (if part2 is non-NULL) or the
- * name of a variable. */
- register Tcl_Obj *part2Ptr; /* If non-null, points to an object holding
+Tcl_ObjGetVar2(
+ Tcl_Interp *interp, /* Command interpreter in which variable is to
+ * be looked up. */
+ register Tcl_Obj *part1Ptr, /* Points to an object holding the name of an
+ * array (if part2 is non-NULL) or the name of
+ * a variable. */
+ register Tcl_Obj *part2Ptr, /* If non-null, points to an object holding
* the name of an element in the array
* part1Ptr. */
- int flags; /* OR-ed combination of TCL_GLOBAL_ONLY and
+ int flags) /* OR-ed combination of TCL_GLOBAL_ONLY and
* TCL_LEAVE_ERR_MSG bits. */
{
Var *varPtr, *arrayPtr;
- char *part1, *part2;
- part1 = Tcl_GetString(part1Ptr);
- part2 = ((part2Ptr == NULL) ? NULL : Tcl_GetString(part2Ptr));
-
- /* Filter to pass through only the flags this interface supports. */
+ /*
+ * Filter to pass through only the flags this interface supports.
+ */
+
flags &= (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG);
- varPtr = TclObjLookupVar(interp, part1Ptr, part2, flags, "read",
- /*createPart1*/ 0, /*createPart2*/ 1, &arrayPtr);
+ varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, flags, "read",
+ /*createPart1*/ 0, /*createPart2*/ 1, &arrayPtr);
if (varPtr == NULL) {
return NULL;
}
- return TclPtrGetVar(interp, varPtr, arrayPtr, part1, part2, flags);
+ return TclPtrGetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr,
+ flags, -1);
}
/*
@@ -1167,50 +1356,53 @@ Tcl_ObjGetVar2(interp, part1Ptr, part2Ptr, flags)
*
* TclPtrGetVar --
*
- * Return the value of a Tcl variable as a Tcl object, given the
- * pointers to the variable's (and possibly containing array's)
- * VAR structure.
+ * Return the value of a Tcl variable as a Tcl object, given the pointers
+ * to the variable's (and possibly containing array's) VAR structure.
*
* Results:
* The return value points to the current object value of the variable
- * given by varPtr. If the specified variable doesn't exist, or if there
- * is a clash in array usage, then NULL is returned and a message will be
- * left in the interpreter's result if the TCL_LEAVE_ERR_MSG flag is set.
+ * given by varPtr. If the specified variable doesn't exist, or if there
+ * is a clash in array usage, then NULL is returned and a message will be
+ * left in the interpreter's result if the TCL_LEAVE_ERR_MSG flag is set.
*
* Side effects:
- * The ref count for the returned object is _not_ incremented to
- * reflect the returned reference; if you want to keep a reference to
- * the object you must increment its ref count yourself.
+ * The ref count for the returned object is _not_ incremented to reflect
+ * the returned reference; if you want to keep a reference to the object
+ * you must increment its ref count yourself.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
-TclPtrGetVar(interp, varPtr, arrayPtr, part1, part2, flags)
- Tcl_Interp *interp; /* Command interpreter in which variable is
- * to be looked up. */
- register Var *varPtr; /* The variable to be read.*/
- Var *arrayPtr; /* NULL for scalar variables, pointer to
- * the containing array otherwise. */
- CONST char *part1; /* Name of an array (if part2 is non-NULL)
- * or the name of a variable. */
- CONST char *part2; /* If non-NULL, gives the name of an element
+TclPtrGetVar(
+ Tcl_Interp *interp, /* Command interpreter in which variable is to
+ * be looked up. */
+ register Var *varPtr, /* The variable to be read.*/
+ Var *arrayPtr, /* NULL for scalar variables, pointer to the
+ * containing array otherwise. */
+ Tcl_Obj *part1Ptr, /* Name of an array (if part2 is non-NULL) or
+ * the name of a variable. */
+ Tcl_Obj *part2Ptr, /* If non-NULL, gives the name of an element
* in the array part1. */
- CONST int flags; /* OR-ed combination of TCL_GLOBAL_ONLY,
- * and TCL_LEAVE_ERR_MSG bits. */
+ const int flags, /* OR-ed combination of TCL_GLOBAL_ONLY, and
+ * TCL_LEAVE_ERR_MSG bits. */
+ int index) /* Index into the local variable table of the
+ * variable, or -1. Only used when part1Ptr is
+ * NULL. */
{
Interp *iPtr = (Interp *) interp;
- CONST char *msg;
+ const char *msg;
/*
- * Invoke any traces that have been set for the variable.
+ * Invoke any read traces that have been set for the variable.
*/
- if ((varPtr->tracePtr != NULL)
- || ((arrayPtr != NULL) && (arrayPtr->tracePtr != NULL))) {
- if (TCL_ERROR == CallVarTraces(iPtr, arrayPtr, varPtr, part1, part2,
+ if ((varPtr->flags & VAR_TRACED_READ)
+ || (arrayPtr && (arrayPtr->flags & VAR_TRACED_READ))) {
+ if (TCL_ERROR == TclObjCallVarTraces(iPtr, arrayPtr, varPtr,
+ part1Ptr, part2Ptr,
(flags & (TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY))
- | TCL_TRACE_READS, (flags & TCL_LEAVE_ERR_MSG))) {
+ | TCL_TRACE_READS, (flags & TCL_LEAVE_ERR_MSG), index)) {
goto errorReturn;
}
}
@@ -1218,31 +1410,31 @@ TclPtrGetVar(interp, varPtr, arrayPtr, part1, part2, flags)
/*
* Return the element if it's an existing scalar variable.
*/
-
+
if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)) {
return varPtr->value.objPtr;
}
-
+
if (flags & TCL_LEAVE_ERR_MSG) {
- if (TclIsVarUndefined(varPtr) && (arrayPtr != NULL)
- && !TclIsVarUndefined(arrayPtr)) {
+ if (TclIsVarUndefined(varPtr) && arrayPtr
+ && !TclIsVarUndefined(arrayPtr)) {
msg = noSuchElement;
} else if (TclIsVarArray(varPtr)) {
msg = isArray;
} else {
msg = noSuchVar;
}
- VarErrMsg(interp, part1, part2, "read", msg);
+ TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "read", msg, index);
}
/*
- * An error. If the variable doesn't exist anymore and no-one's using
- * it, then free up the relevant structures and hash table entries.
+ * An error. If the variable doesn't exist anymore and no-one's using it,
+ * then free up the relevant structures and hash table entries.
*/
- errorReturn:
+ errorReturn:
if (TclIsVarUndefined(varPtr)) {
- CleanupVar(varPtr, arrayPtr);
+ TclCleanupVar(varPtr, arrayPtr);
}
return NULL;
}
@@ -1252,8 +1444,8 @@ TclPtrGetVar(interp, varPtr, arrayPtr, part1, part2, flags)
*
* Tcl_SetObjCmd --
*
- * This procedure is invoked to process the "set" Tcl command.
- * See the user documentation for details on what it does.
+ * This function is invoked to process the "set" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result value.
@@ -1266,23 +1458,22 @@ TclPtrGetVar(interp, varPtr, arrayPtr, part1, part2, flags)
/* ARGSUSED */
int
-Tcl_SetObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- register Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_SetObjCmd(
+ ClientData dummy, /* Not used. */
+ register Tcl_Interp *interp,/* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Obj *varValueObj;
if (objc == 2) {
- varValueObj = Tcl_ObjGetVar2(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG);
+ varValueObj = Tcl_ObjGetVar2(interp, objv[1], NULL,TCL_LEAVE_ERR_MSG);
if (varValueObj == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, varValueObj);
return TCL_OK;
} else if (objc == 3) {
-
varValueObj = Tcl_ObjSetVar2(interp, objv[1], NULL, objv[2],
TCL_LEAVE_ERR_MSG);
if (varValueObj == NULL) {
@@ -1305,33 +1496,33 @@ Tcl_SetObjCmd(dummy, interp, objc, objv)
*
* Results:
* Returns a pointer to the malloc'ed string which is the character
- * representation of the variable's new value. The caller must not
- * modify this string. If the write operation was disallowed then NULL
- * is returned; if the TCL_LEAVE_ERR_MSG flag is set, then an
- * explanatory message will be left in the interp's result. Note that the
- * returned string may not be the same as newValue; this is because
- * variable traces may modify the variable's value.
+ * representation of the variable's new value. The caller must not modify
+ * this string. If the write operation was disallowed then NULL is
+ * returned; if the TCL_LEAVE_ERR_MSG flag is set, then an explanatory
+ * message will be left in the interp's result. Note that the returned
+ * string may not be the same as newValue; this is because variable
+ * traces may modify the variable's value.
*
* Side effects:
- * If varName is defined as a local or global variable in interp,
- * its value is changed to newValue. If varName isn't currently
- * defined, then a new global variable by that name is created.
+ * If varName is defined as a local or global variable in interp, its
+ * value is changed to newValue. If varName isn't currently defined, then
+ * a new global variable by that name is created.
*
*----------------------------------------------------------------------
*/
-CONST char *
-Tcl_SetVar(interp, varName, newValue, flags)
- Tcl_Interp *interp; /* Command interpreter in which varName is
- * to be looked up. */
- CONST char *varName; /* Name of a variable in interp. */
- CONST char *newValue; /* New value for varName. */
- int flags; /* Various flags that tell how to set value:
- * any of TCL_GLOBAL_ONLY,
- * TCL_NAMESPACE_ONLY, TCL_APPEND_VALUE,
- * TCL_LIST_ELEMENT, TCL_LEAVE_ERR_MSG. */
+const char *
+Tcl_SetVar(
+ Tcl_Interp *interp, /* Command interpreter in which varName is to
+ * be looked up. */
+ const char *varName, /* Name of a variable in interp. */
+ const char *newValue, /* New value for varName. */
+ int flags) /* Various flags that tell how to set value:
+ * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
+ * TCL_APPEND_VALUE, TCL_LIST_ELEMENT,
+ * TCL_LEAVE_ERR_MSG. */
{
- return Tcl_SetVar2(interp, varName, (char *) NULL, newValue, flags);
+ return Tcl_SetVar2(interp, varName, NULL, newValue, flags);
}
/*
@@ -1339,57 +1530,55 @@ Tcl_SetVar(interp, varName, newValue, flags)
*
* Tcl_SetVar2 --
*
- * Given a two-part variable name, which may refer either to a
- * scalar variable or an element of an array, change the value
- * of the variable. If the named scalar or array or element
- * doesn't exist then create one.
+ * Given a two-part variable name, which may refer either to a scalar
+ * variable or an element of an array, change the value of the variable.
+ * If the named scalar or array or element doesn't exist then create one.
*
* Results:
* Returns a pointer to the malloc'ed string which is the character
- * representation of the variable's new value. The caller must not
- * modify this string. If the write operation was disallowed because an
- * array was expected but not found (or vice versa), then NULL is
- * returned; if the TCL_LEAVE_ERR_MSG flag is set, then an explanatory
- * message will be left in the interp's result. Note that the returned
- * string may not be the same as newValue; this is because variable
- * traces may modify the variable's value.
+ * representation of the variable's new value. The caller must not modify
+ * this string. If the write operation was disallowed because an array
+ * was expected but not found (or vice versa), then NULL is returned; if
+ * the TCL_LEAVE_ERR_MSG flag is set, then an explanatory message will be
+ * left in the interp's result. Note that the returned string may not be
+ * the same as newValue; this is because variable traces may modify the
+ * variable's value.
*
* Side effects:
- * The value of the given variable is set. If either the array
- * or the entry didn't exist then a new one is created.
+ * The value of the given variable is set. If either the array or the
+ * entry didn't exist then a new one is created.
*
*----------------------------------------------------------------------
*/
-CONST char *
-Tcl_SetVar2(interp, part1, part2, newValue, flags)
- Tcl_Interp *interp; /* Command interpreter in which variable is
- * to be looked up. */
- CONST char *part1; /* If part2 is NULL, this is name of scalar
- * variable. Otherwise it is the name of
- * an array. */
- CONST char *part2; /* Name of an element within an array, or
+const char *
+Tcl_SetVar2(
+ Tcl_Interp *interp, /* Command interpreter in which variable is to
+ * be looked up. */
+ const char *part1, /* If part2 is NULL, this is name of scalar
+ * variable. Otherwise it is the name of an
+ * array. */
+ const char *part2, /* Name of an element within an array, or
* NULL. */
- CONST char *newValue; /* New value for variable. */
- int flags; /* Various flags that tell how to set value:
- * any of TCL_GLOBAL_ONLY,
- * TCL_NAMESPACE_ONLY, TCL_APPEND_VALUE,
- * TCL_LIST_ELEMENT, or TCL_LEAVE_ERR_MSG */
+ const char *newValue, /* New value for variable. */
+ int flags) /* Various flags that tell how to set value:
+ * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
+ * TCL_APPEND_VALUE, TCL_LIST_ELEMENT, or
+ * TCL_LEAVE_ERR_MSG. */
{
register Tcl_Obj *valuePtr;
Tcl_Obj *varValuePtr;
/*
- * Create an object holding the variable's new value and use
- * Tcl_SetVar2Ex to actually set the variable.
+ * Create an object holding the variable's new value and use Tcl_SetVar2Ex
+ * to actually set the variable.
*/
valuePtr = Tcl_NewStringObj(newValue, -1);
Tcl_IncrRefCount(valuePtr);
-
varValuePtr = Tcl_SetVar2Ex(interp, part1, part2, valuePtr, flags);
- Tcl_DecrRefCount(valuePtr); /* done with the object */
-
+ Tcl_DecrRefCount(valuePtr);
+
if (varValuePtr == NULL) {
return NULL;
}
@@ -1409,10 +1598,10 @@ Tcl_SetVar2(interp, part1, part2, newValue, flags)
* Results:
* Returns a pointer to the Tcl_Obj holding the new value of the
* variable. If the write operation was disallowed because an array was
- * expected but not found (or vice versa), then NULL is returned; if
- * the TCL_LEAVE_ERR_MSG flag is set, then an explanatory message will
- * be left in the interpreter's result. Note that the returned object
- * may not be the same one referenced by newValuePtr; this is because
+ * expected but not found (or vice versa), then NULL is returned; if the
+ * TCL_LEAVE_ERR_MSG flag is set, then an explanatory message will be
+ * left in the interpreter's result. Note that the returned object may
+ * not be the same one referenced by newValuePtr; this is because
* variable traces may modify the variable's value.
*
* Side effects:
@@ -1421,46 +1610,52 @@ Tcl_SetVar2(interp, part1, part2, newValue, flags)
*
* The reference count is decremented for any old value of the variable
* and incremented for its new value. If the new value for the variable
- * is not the same one referenced by newValuePtr (perhaps as a result
- * of a variable trace), then newValuePtr's ref count is left unchanged
- * by Tcl_SetVar2Ex. newValuePtr's ref count is also left unchanged if
- * we are appending it as a string value: that is, if "flags" includes
+ * is not the same one referenced by newValuePtr (perhaps as a result of
+ * a variable trace), then newValuePtr's ref count is left unchanged by
+ * Tcl_SetVar2Ex. newValuePtr's ref count is also left unchanged if we
+ * are appending it as a string value: that is, if "flags" includes
* TCL_APPEND_VALUE but not TCL_LIST_ELEMENT.
*
* The reference count for the returned object is _not_ incremented: if
- * you want to keep a reference to the object you must increment its
- * ref count yourself.
+ * you want to keep a reference to the object you must increment its ref
+ * count yourself.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
-Tcl_SetVar2Ex(interp, part1, part2, newValuePtr, flags)
- Tcl_Interp *interp; /* Command interpreter in which variable is
- * to be found. */
- CONST char *part1; /* Name of an array (if part2 is non-NULL)
- * or the name of a variable. */
- CONST char *part2; /* If non-NULL, gives the name of an element
+Tcl_SetVar2Ex(
+ Tcl_Interp *interp, /* Command interpreter in which variable is to
+ * be found. */
+ const char *part1, /* Name of an array (if part2 is non-NULL) or
+ * the name of a variable. */
+ const char *part2, /* If non-NULL, gives the name of an element
* in the array part1. */
- Tcl_Obj *newValuePtr; /* New value for variable. */
- int flags; /* Various flags that tell how to set value:
- * any of TCL_GLOBAL_ONLY,
- * TCL_NAMESPACE_ONLY, TCL_APPEND_VALUE,
- * TCL_LIST_ELEMENT or TCL_LEAVE_ERR_MSG. */
+ Tcl_Obj *newValuePtr, /* New value for variable. */
+ int flags) /* Various flags that tell how to set value:
+ * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
+ * TCL_APPEND_VALUE, TCL_LIST_ELEMENT or
+ * TCL_LEAVE_ERR_MSG. */
{
- Var *varPtr, *arrayPtr;
+ Tcl_Obj *part1Ptr, *part2Ptr, *resPtr;
- /* Filter to pass through only the flags this interface supports. */
- flags &= (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG
- |TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
- varPtr = TclLookupVar(interp, part1, part2, flags, "set",
- /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
- if (varPtr == NULL) {
- return NULL;
+ part1Ptr = Tcl_NewStringObj(part1, -1);
+ Tcl_IncrRefCount(part1Ptr);
+ if (part2) {
+ part2Ptr = Tcl_NewStringObj(part2, -1);
+ Tcl_IncrRefCount(part2Ptr);
+ } else {
+ part2Ptr = NULL;
}
- return TclPtrSetVar(interp, varPtr, arrayPtr, part1, part2,
- newValuePtr, flags);
+ resPtr = Tcl_ObjSetVar2(interp, part1Ptr, part2Ptr, newValuePtr, flags);
+
+ Tcl_DecrRefCount(part1Ptr);
+ if (part2Ptr) {
+ Tcl_DecrRefCount(part2Ptr);
+ }
+
+ return resPtr;
}
/*
@@ -1468,16 +1663,16 @@ Tcl_SetVar2Ex(interp, part1, part2, newValuePtr, flags)
*
* Tcl_ObjSetVar2 --
*
- * This function is the same as Tcl_SetVar2Ex above, except the
- * variable names are passed in Tcl object instead of strings.
+ * This function is the same as Tcl_SetVar2Ex above, except the variable
+ * names are passed in Tcl object instead of strings.
*
* Results:
* Returns a pointer to the Tcl_Obj holding the new value of the
* variable. If the write operation was disallowed because an array was
- * expected but not found (or vice versa), then NULL is returned; if
- * the TCL_LEAVE_ERR_MSG flag is set, then an explanatory message will
- * be left in the interpreter's result. Note that the returned object
- * may not be the same one referenced by newValuePtr; this is because
+ * expected but not found (or vice versa), then NULL is returned; if the
+ * TCL_LEAVE_ERR_MSG flag is set, then an explanatory message will be
+ * left in the interpreter's result. Note that the returned object may
+ * not be the same one referenced by newValuePtr; this is because
* variable traces may modify the variable's value.
*
* Side effects:
@@ -1488,80 +1683,85 @@ Tcl_SetVar2Ex(interp, part1, part2, newValuePtr, flags)
*/
Tcl_Obj *
-Tcl_ObjSetVar2(interp, part1Ptr, part2Ptr, newValuePtr, flags)
- Tcl_Interp *interp; /* Command interpreter in which variable is
- * to be found. */
- register Tcl_Obj *part1Ptr; /* Points to an object holding the name of
- * an array (if part2 is non-NULL) or the
- * name of a variable. */
- register Tcl_Obj *part2Ptr; /* If non-null, points to an object holding
+Tcl_ObjSetVar2(
+ Tcl_Interp *interp, /* Command interpreter in which variable is to
+ * be found. */
+ register Tcl_Obj *part1Ptr, /* Points to an object holding the name of an
+ * array (if part2 is non-NULL) or the name of
+ * a variable. */
+ register Tcl_Obj *part2Ptr, /* If non-NULL, points to an object holding
* the name of an element in the array
* part1Ptr. */
- Tcl_Obj *newValuePtr; /* New value for variable. */
- int flags; /* Various flags that tell how to set value:
- * any of TCL_GLOBAL_ONLY,
- * TCL_NAMESPACE_ONLY, TCL_APPEND_VALUE,
- * TCL_LIST_ELEMENT, or TCL_LEAVE_ERR_MSG. */
+ Tcl_Obj *newValuePtr, /* New value for variable. */
+ int flags) /* Various flags that tell how to set value:
+ * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
+ * TCL_APPEND_VALUE, TCL_LIST_ELEMENT, or
+ * TCL_LEAVE_ERR_MSG. */
{
Var *varPtr, *arrayPtr;
- char *part1, *part2;
- part1 = TclGetString(part1Ptr);
- part2 = ((part2Ptr == NULL) ? NULL : Tcl_GetString(part2Ptr));
+ /*
+ * Filter to pass through only the flags this interface supports.
+ */
- /* Filter to pass through only the flags this interface supports. */
flags &= (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG
|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
- varPtr = TclObjLookupVar(interp, part1Ptr, part2, flags, "set",
+ varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, flags, "set",
/*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
if (varPtr == NULL) {
+ if (newValuePtr->refCount == 0) {
+ Tcl_DecrRefCount(newValuePtr);
+ }
return NULL;
}
- return TclPtrSetVar(interp, varPtr, arrayPtr, part1, part2,
- newValuePtr, flags);
+ return TclPtrSetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr,
+ newValuePtr, flags, -1);
}
-
/*
*----------------------------------------------------------------------
*
* TclPtrSetVar --
*
- * This function is the same as Tcl_SetVar2Ex above, except that
- * it requires pointers to the variable's Var structs in addition
- * to the variable names.
+ * This function is the same as Tcl_SetVar2Ex above, except that it
+ * requires pointers to the variable's Var structs in addition to the
+ * variable names.
*
* Results:
* Returns a pointer to the Tcl_Obj holding the new value of the
* variable. If the write operation was disallowed because an array was
- * expected but not found (or vice versa), then NULL is returned; if
- * the TCL_LEAVE_ERR_MSG flag is set, then an explanatory message will
- * be left in the interpreter's result. Note that the returned object
- * may not be the same one referenced by newValuePtr; this is because
+ * expected but not found (or vice versa), then NULL is returned; if the
+ * TCL_LEAVE_ERR_MSG flag is set, then an explanatory message will be
+ * left in the interpreter's result. Note that the returned object may
+ * not be the same one referenced by newValuePtr; this is because
* variable traces may modify the variable's value.
*
* Side effects:
* The value of the given variable is set. If either the array or the
* entry didn't exist then a new variable is created.
-
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
-TclPtrSetVar(interp, varPtr, arrayPtr, part1, part2, newValuePtr, flags)
- Tcl_Interp *interp; /* Command interpreter in which variable is
- * to be looked up. */
- register Var *varPtr;
- Var *arrayPtr;
- CONST char *part1; /* Name of an array (if part2 is non-NULL)
- * or the name of a variable. */
- CONST char *part2; /* If non-NULL, gives the name of an element
+TclPtrSetVar(
+ Tcl_Interp *interp, /* Command interpreter in which variable is to
+ * be looked up. */
+ register Var *varPtr, /* Reference to the variable to set. */
+ Var *arrayPtr, /* Reference to the array containing the
+ * variable, or NULL if the variable is a
+ * scalar. */
+ Tcl_Obj *part1Ptr, /* Name of an array (if part2 is non-NULL) or
+ * the name of a variable. NULL if the 'index'
+ * parameter is >= 0 */
+ Tcl_Obj *part2Ptr, /* If non-NULL, gives the name of an element
* in the array part1. */
- Tcl_Obj *newValuePtr; /* New value for variable. */
- CONST int flags; /* OR-ed combination of TCL_GLOBAL_ONLY,
- * and TCL_LEAVE_ERR_MSG bits. */
+ Tcl_Obj *newValuePtr, /* New value for variable. */
+ const int flags, /* OR-ed combination of TCL_GLOBAL_ONLY, and
+ * TCL_LEAVE_ERR_MSG bits. */
+ int index) /* Index of local var where part1 is to be
+ * found. */
{
Interp *iPtr = (Interp *) interp;
Tcl_Obj *oldValuePtr;
@@ -1570,85 +1770,93 @@ TclPtrSetVar(interp, varPtr, arrayPtr, part1, part2, newValuePtr, flags)
/*
* If the variable is in a hashtable and its hPtr field is NULL, then we
- * may have an upvar to an array element where the array was deleted
- * or an upvar to a namespace variable whose namespace was deleted.
- * Generate an error (allowing the variable to be reset would screw up
- * our storage allocation and is meaningless anyway).
+ * may have an upvar to an array element where the array was deleted or an
+ * upvar to a namespace variable whose namespace was deleted. Generate an
+ * error (allowing the variable to be reset would screw up our storage
+ * allocation and is meaningless anyway).
*/
- if ((varPtr->flags & VAR_IN_HASHTABLE) && (varPtr->hPtr == NULL)) {
+ if (TclIsVarDeadHash(varPtr)) {
if (flags & TCL_LEAVE_ERR_MSG) {
if (TclIsVarArrayElement(varPtr)) {
- VarErrMsg(interp, part1, part2, "set", danglingElement);
+ TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "set",
+ danglingElement, index);
} else {
- VarErrMsg(interp, part1, part2, "set", danglingVar);
+ TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "set",
+ danglingVar, index);
}
}
- return NULL;
+ goto earlyError;
}
/*
* It's an error to try to set an array variable itself.
*/
- if (TclIsVarArray(varPtr) && !TclIsVarUndefined(varPtr)) {
+ if (TclIsVarArray(varPtr)) {
if (flags & TCL_LEAVE_ERR_MSG) {
- VarErrMsg(interp, part1, part2, "set", isArray);
+ TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "set", isArray,index);
}
- return NULL;
+ goto earlyError;
}
/*
- * Invoke any read traces that have been set for the variable if it
+ * Invoke any read traces that have been set for the variable if it is
* requested. This was done for INST_LAPPEND_* but that was inconsistent
* with the non-bc instruction, and would cause failures trying to
* lappend to any non-existing ::env var, which is inconsistent with
- * documented behavior. [Bug #3057639].
+ * documented behavior. [Bug #3057639]
*/
- if ((flags & TCL_TRACE_READS) && ((varPtr->tracePtr != NULL)
- || ((arrayPtr != NULL) && (arrayPtr->tracePtr != NULL)))) {
- if (TCL_ERROR == CallVarTraces(iPtr, arrayPtr, varPtr, part1, part2,
- TCL_TRACE_READS, (flags & TCL_LEAVE_ERR_MSG))) {
- return NULL;
+ if ((flags & TCL_TRACE_READS) && ((varPtr->flags & VAR_TRACED_READ)
+ || (arrayPtr && (arrayPtr->flags & VAR_TRACED_READ)))) {
+ if (TCL_ERROR == TclObjCallVarTraces(iPtr, arrayPtr, varPtr,
+ part1Ptr, part2Ptr,
+ TCL_TRACE_READS, (flags & TCL_LEAVE_ERR_MSG), index)) {
+ goto earlyError;
}
}
/*
- * Set the variable's new value. If appending, append the new value to
- * the variable, either as a list element or as a string. Also, if
- * appending, then if the variable's old value is unshared we can modify
- * it directly, otherwise we must create a new copy to modify: this is
- * "copy on write".
+ * Set the variable's new value. If appending, append the new value to the
+ * variable, either as a list element or as a string. Also, if appending,
+ * then if the variable's old value is unshared we can modify it directly,
+ * otherwise we must create a new copy to modify: this is "copy on write".
*/
+ oldValuePtr = varPtr->value.objPtr;
if (flags & TCL_LIST_ELEMENT && !(flags & TCL_APPEND_VALUE)) {
- TclSetVarUndefined(varPtr);
+ varPtr->value.objPtr = NULL;
}
- oldValuePtr = varPtr->value.objPtr;
if (flags & (TCL_APPEND_VALUE|TCL_LIST_ELEMENT)) {
+#if 0
+ /*
+ * Can't happen now!
+ */
+
if (TclIsVarUndefined(varPtr) && (oldValuePtr != NULL)) {
- Tcl_DecrRefCount(oldValuePtr); /* discard old value */
+ TclDecrRefCount(oldValuePtr); /* Discard old value. */
varPtr->value.objPtr = NULL;
oldValuePtr = NULL;
}
- if (flags & TCL_LIST_ELEMENT) { /* append list element */
+#endif
+ if (flags & TCL_LIST_ELEMENT) { /* Append list element. */
if (oldValuePtr == NULL) {
TclNewObj(oldValuePtr);
varPtr->value.objPtr = oldValuePtr;
- Tcl_IncrRefCount(oldValuePtr); /* since var is referenced */
+ Tcl_IncrRefCount(oldValuePtr); /* Since var is referenced. */
} else if (Tcl_IsShared(oldValuePtr)) {
varPtr->value.objPtr = Tcl_DuplicateObj(oldValuePtr);
- Tcl_DecrRefCount(oldValuePtr);
+ TclDecrRefCount(oldValuePtr);
oldValuePtr = varPtr->value.objPtr;
- Tcl_IncrRefCount(oldValuePtr); /* since var is referenced */
+ Tcl_IncrRefCount(oldValuePtr); /* Since var is referenced. */
}
result = Tcl_ListObjAppendElement(interp, oldValuePtr,
newValuePtr);
if (result != TCL_OK) {
- return NULL;
+ goto earlyError;
}
- } else { /* append string */
+ } else { /* Append string. */
/*
* We append newValuePtr's bytes but don't change its ref count.
*/
@@ -1657,51 +1865,45 @@ TclPtrSetVar(interp, varPtr, arrayPtr, part1, part2, newValuePtr, flags)
varPtr->value.objPtr = newValuePtr;
Tcl_IncrRefCount(newValuePtr);
} else {
- if (Tcl_IsShared(oldValuePtr)) { /* append to copy */
+ if (Tcl_IsShared(oldValuePtr)) { /* Append to copy. */
varPtr->value.objPtr = Tcl_DuplicateObj(oldValuePtr);
-#ifdef TCL_TIP280
+
/*
* TIP #280.
- * Ensure that the continuation line data for the
- * string is not lost and applies to the extended
- * script as well.
+ * Ensure that the continuation line data for the string
+ * is not lost and applies to the extended script as well.
*/
TclContinuationsCopy (varPtr->value.objPtr, oldValuePtr);
-#endif
+
TclDecrRefCount(oldValuePtr);
oldValuePtr = varPtr->value.objPtr;
- Tcl_IncrRefCount(oldValuePtr); /* since var is ref */
+ Tcl_IncrRefCount(oldValuePtr); /* Since var is ref */
}
Tcl_AppendObjToObj(oldValuePtr, newValuePtr);
}
}
} else if (newValuePtr != oldValuePtr) {
/*
- * In this case we are replacing the value, so we don't need to
- * do more than swap the objects.
+ * In this case we are replacing the value, so we don't need to do
+ * more than swap the objects.
*/
varPtr->value.objPtr = newValuePtr;
- Tcl_IncrRefCount(newValuePtr); /* var is another ref */
+ Tcl_IncrRefCount(newValuePtr); /* Var is another ref. */
if (oldValuePtr != NULL) {
- TclDecrRefCount(oldValuePtr); /* discard old value */
+ TclDecrRefCount(oldValuePtr); /* Discard old value. */
}
}
- TclSetVarScalar(varPtr);
- TclClearVarUndefined(varPtr);
- if (arrayPtr != NULL) {
- TclClearVarUndefined(arrayPtr);
- }
/*
* Invoke any write traces for the variable.
*/
- if ((varPtr->tracePtr != NULL)
- || ((arrayPtr != NULL) && (arrayPtr->tracePtr != NULL))) {
- if (TCL_ERROR == CallVarTraces(iPtr, arrayPtr, varPtr, part1, part2,
- (flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY))
- | TCL_TRACE_WRITES, (flags & TCL_LEAVE_ERR_MSG))) {
+ if ((varPtr->flags & VAR_TRACED_WRITE)
+ || (arrayPtr && (arrayPtr->flags & VAR_TRACED_WRITE))) {
+ if (TCL_ERROR == TclObjCallVarTraces(iPtr, arrayPtr, varPtr, part1Ptr,
+ part2Ptr, (flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY))
+ | TCL_TRACE_WRITES, (flags & TCL_LEAVE_ERR_MSG), index)) {
goto cleanup;
}
}
@@ -1709,7 +1911,7 @@ TclPtrSetVar(interp, varPtr, arrayPtr, part1, part2, newValuePtr, flags)
/*
* Return the variable's value unless the variable was changed in some
* gross way by a trace (e.g. it was unset and then recreated as an
- * array).
+ * array).
*/
if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)) {
@@ -1720,36 +1922,42 @@ TclPtrSetVar(interp, varPtr, arrayPtr, part1, part2, newValuePtr, flags)
* A trace changed the value in some gross way. Return an empty string
* object.
*/
-
+
resultPtr = iPtr->emptyObjPtr;
/*
- * If the variable doesn't exist anymore and no-one's using it, then
- * free up the relevant structures and hash table entries.
+ * If the variable doesn't exist anymore and no-one's using it, then free
+ * up the relevant structures and hash table entries.
*/
- cleanup:
+ cleanup:
if (TclIsVarUndefined(varPtr)) {
- CleanupVar(varPtr, arrayPtr);
+ TclCleanupVar(varPtr, arrayPtr);
}
return resultPtr;
+
+ earlyError:
+ if (newValuePtr->refCount == 0) {
+ Tcl_DecrRefCount(newValuePtr);
+ }
+ goto cleanup;
}
/*
*----------------------------------------------------------------------
*
- * TclIncrVar2 --
+ * TclIncrObjVar2 --
*
* Given a two-part variable name, which may refer either to a scalar
- * variable or an element of an array, increment the Tcl object value
- * of the variable by a specified amount.
+ * variable or an element of an array, increment the Tcl object value of
+ * the variable by a specified Tcl_Obj increment value.
*
* Results:
* Returns a pointer to the Tcl_Obj holding the new value of the
- * variable. If the specified variable doesn't exist, or there is a
- * clash in array usage, or an error occurs while executing variable
- * traces, then NULL is returned and a message will be left in
- * the interpreter's result.
+ * variable. If the specified variable doesn't exist, or there is a clash
+ * in array usage, or an error occurs while executing variable traces,
+ * then NULL is returned and a message will be left in the interpreter's
+ * result.
*
* Side effects:
* The value of the given variable is incremented by the specified
@@ -1762,53 +1970,48 @@ TclPtrSetVar(interp, varPtr, arrayPtr, part1, part2, newValuePtr, flags)
*/
Tcl_Obj *
-TclIncrVar2(interp, part1Ptr, part2Ptr, incrAmount, flags)
- Tcl_Interp *interp; /* Command interpreter in which variable is
- * to be found. */
- Tcl_Obj *part1Ptr; /* Points to an object holding the name of
- * an array (if part2 is non-NULL) or the
- * name of a variable. */
- Tcl_Obj *part2Ptr; /* If non-null, points to an object holding
+TclIncrObjVar2(
+ Tcl_Interp *interp, /* Command interpreter in which variable is to
+ * be found. */
+ Tcl_Obj *part1Ptr, /* Points to an object holding the name of an
+ * array (if part2 is non-NULL) or the name of
+ * a variable. */
+ Tcl_Obj *part2Ptr, /* If non-null, points to an object holding
* the name of an element in the array
* part1Ptr. */
- long incrAmount; /* Amount to be added to variable. */
- int flags; /* Various flags that tell how to incr value:
- * any of TCL_GLOBAL_ONLY,
- * TCL_NAMESPACE_ONLY, TCL_APPEND_VALUE,
- * TCL_LIST_ELEMENT, TCL_LEAVE_ERR_MSG. */
+ Tcl_Obj *incrPtr, /* Amount to be added to variable. */
+ int flags) /* Various flags that tell how to incr value:
+ * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
+ * TCL_APPEND_VALUE, TCL_LIST_ELEMENT,
+ * TCL_LEAVE_ERR_MSG. */
{
Var *varPtr, *arrayPtr;
- char *part1, *part2;
- part1 = TclGetString(part1Ptr);
- part2 = ((part2Ptr == NULL)? NULL : TclGetString(part2Ptr));
-
- varPtr = TclObjLookupVar(interp, part1Ptr, part2, flags, "read",
- 0, 1, &arrayPtr);
+ varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, flags, "read",
+ 1, 1, &arrayPtr);
if (varPtr == NULL) {
Tcl_AddObjErrorInfo(interp,
"\n (reading value of variable to increment)", -1);
return NULL;
}
- return TclPtrIncrVar(interp, varPtr, arrayPtr, part1, part2,
- incrAmount, flags);
+ return TclPtrIncrObjVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr,
+ incrPtr, flags, -1);
}
/*
*----------------------------------------------------------------------
*
- * TclPtrIncrVar --
+ * TclPtrIncrObjVar --
*
- * Given the pointers to a variable and possible containing array,
- * increment the Tcl object value of the variable by a specified
- * amount.
+ * Given the pointers to a variable and possible containing array,
+ * increment the Tcl object value of the variable by a Tcl_Obj increment.
*
* Results:
* Returns a pointer to the Tcl_Obj holding the new value of the
- * variable. If the specified variable doesn't exist, or there is a
- * clash in array usage, or an error occurs while executing variable
- * traces, then NULL is returned and a message will be left in
- * the interpreter's result.
+ * variable. If the specified variable doesn't exist, or there is a clash
+ * in array usage, or an error occurs while executing variable traces,
+ * then NULL is returned and a message will be left in the interpreter's
+ * result.
*
* Side effects:
* The value of the given variable is incremented by the specified
@@ -1821,81 +2024,57 @@ TclIncrVar2(interp, part1Ptr, part2Ptr, incrAmount, flags)
*/
Tcl_Obj *
-TclPtrIncrVar(interp, varPtr, arrayPtr, part1, part2, incrAmount, flags)
- Tcl_Interp *interp; /* Command interpreter in which variable is
- * to be found. */
- Var *varPtr;
- Var *arrayPtr;
- CONST char *part1; /* Points to an object holding the name of
- * an array (if part2 is non-NULL) or the
- * name of a variable. */
- CONST char *part2; /* If non-null, points to an object holding
+TclPtrIncrObjVar(
+ Tcl_Interp *interp, /* Command interpreter in which variable is to
+ * be found. */
+ Var *varPtr, /* Reference to the variable to set. */
+ Var *arrayPtr, /* Reference to the array containing the
+ * variable, or NULL if the variable is a
+ * scalar. */
+ Tcl_Obj *part1Ptr, /* Points to an object holding the name of an
+ * array (if part2 is non-NULL) or the name of
+ * a variable. */
+ Tcl_Obj *part2Ptr, /* If non-null, points to an object holding
* the name of an element in the array
* part1Ptr. */
- CONST long incrAmount; /* Amount to be added to variable. */
- CONST int flags; /* Various flags that tell how to incr value:
- * any of TCL_GLOBAL_ONLY,
- * TCL_NAMESPACE_ONLY, TCL_APPEND_VALUE,
- * TCL_LIST_ELEMENT, TCL_LEAVE_ERR_MSG. */
+ Tcl_Obj *incrPtr, /* Increment value. */
+/* TODO: Which of these flag values really make sense? */
+ const int flags, /* Various flags that tell how to incr value:
+ * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
+ * TCL_APPEND_VALUE, TCL_LIST_ELEMENT,
+ * TCL_LEAVE_ERR_MSG. */
+ int index) /* Index into the local variable table of the
+ * variable, or -1. Only used when part1Ptr is
+ * NULL. */
{
- register Tcl_Obj *varValuePtr;
- int createdNewObj; /* Set 1 if var's value object is shared
- * so we must increment a copy (i.e. copy
- * on write). */
- long i;
-
- varValuePtr = TclPtrGetVar(interp, varPtr, arrayPtr, part1, part2, flags);
+ register Tcl_Obj *varValuePtr, *newValuePtr = NULL;
+ int duplicated, code;
+ if (TclIsVarInHash(varPtr)) {
+ VarHashRefCount(varPtr)++;
+ }
+ varValuePtr = TclPtrGetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr,
+ flags, index);
+ if (TclIsVarInHash(varPtr)) {
+ VarHashRefCount(varPtr)--;
+ }
if (varValuePtr == NULL) {
- Tcl_AddObjErrorInfo(interp,
- "\n (reading value of variable to increment)", -1);
- return NULL;
+ varValuePtr = Tcl_NewIntObj(0);
}
-
- /*
- * Increment the variable's value. If the object is unshared we can
- * modify it directly, otherwise we must create a new copy to modify:
- * this is "copy on write". Then free the variable's old string
- * representation, if any, since it will no longer be valid.
- */
-
- createdNewObj = 0;
if (Tcl_IsShared(varValuePtr)) {
+ duplicated = 1;
varValuePtr = Tcl_DuplicateObj(varValuePtr);
- createdNewObj = 1;
- }
- if (varValuePtr->typePtr == &tclWideIntType) {
- Tcl_WideInt wide;
- TclGetWide(wide,varValuePtr);
- Tcl_SetWideIntObj(varValuePtr, wide + Tcl_LongAsWide(incrAmount));
- } else if (varValuePtr->typePtr == &tclIntType) {
- i = varValuePtr->internalRep.longValue;
- Tcl_SetIntObj(varValuePtr, i + incrAmount);
} else {
- /*
- * Not an integer or wide internal-rep...
- */
- Tcl_WideInt wide;
- if (Tcl_GetWideIntFromObj(interp, varValuePtr, &wide) != TCL_OK) {
- if (createdNewObj) {
- Tcl_DecrRefCount(varValuePtr); /* free unneeded copy */
- }
- return NULL;
- }
- if (wide <= Tcl_LongAsWide(LONG_MAX)
- && wide >= Tcl_LongAsWide(LONG_MIN)) {
- Tcl_SetLongObj(varValuePtr, Tcl_WideAsLong(wide) + incrAmount);
- } else {
- Tcl_SetWideIntObj(varValuePtr, wide + Tcl_LongAsWide(incrAmount));
- }
+ duplicated = 0;
}
-
- /*
- * Store the variable's new value and run any write traces.
- */
-
- return TclPtrSetVar(interp, varPtr, arrayPtr, part1, part2,
- varValuePtr, flags);
+ code = TclIncrObj(interp, varValuePtr, incrPtr);
+ if (code == TCL_OK) {
+ newValuePtr = TclPtrSetVar(interp, varPtr, arrayPtr, part1Ptr,
+ part2Ptr, varValuePtr, flags, index);
+ } else if (duplicated) {
+ Tcl_DecrRefCount(varValuePtr);
+ }
+ return newValuePtr;
}
/*
@@ -1906,30 +2085,30 @@ TclPtrIncrVar(interp, varPtr, arrayPtr, part1, part2, incrAmount, flags)
* Delete a variable, so that it may not be accessed anymore.
*
* Results:
- * Returns TCL_OK if the variable was successfully deleted, TCL_ERROR
- * if the variable can't be unset. In the event of an error,
- * if the TCL_LEAVE_ERR_MSG flag is set then an error message
- * is left in the interp's result.
+ * Returns TCL_OK if the variable was successfully deleted, TCL_ERROR if
+ * the variable can't be unset. In the event of an error, if the
+ * TCL_LEAVE_ERR_MSG flag is set then an error message is left in the
+ * interp's result.
*
* Side effects:
- * If varName is defined as a local or global variable in interp,
- * it is deleted.
+ * If varName is defined as a local or global variable in interp, it is
+ * deleted.
*
*----------------------------------------------------------------------
*/
int
-Tcl_UnsetVar(interp, varName, flags)
- Tcl_Interp *interp; /* Command interpreter in which varName is
- * to be looked up. */
- CONST char *varName; /* Name of a variable in interp. May be
- * either a scalar name or an array name
- * or an element in an array. */
- int flags; /* OR-ed combination of any of
+Tcl_UnsetVar(
+ Tcl_Interp *interp, /* Command interpreter in which varName is to
+ * be looked up. */
+ const char *varName, /* Name of a variable in interp. May be either
+ * a scalar name or an array name or an
+ * element in an array. */
+ int flags) /* OR-ed combination of any of
* TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY or
* TCL_LEAVE_ERR_MSG. */
{
- return Tcl_UnsetVar2(interp, varName, (char *) NULL, flags);
+ return Tcl_UnsetVar2(interp, varName, NULL, flags);
}
/*
@@ -1940,42 +2119,52 @@ Tcl_UnsetVar(interp, varName, flags)
* Delete a variable, given a 2-part name.
*
* Results:
- * Returns TCL_OK if the variable was successfully deleted, TCL_ERROR
- * if the variable can't be unset. In the event of an error,
- * if the TCL_LEAVE_ERR_MSG flag is set then an error message
- * is left in the interp's result.
+ * Returns TCL_OK if the variable was successfully deleted, TCL_ERROR if
+ * the variable can't be unset. In the event of an error, if the
+ * TCL_LEAVE_ERR_MSG flag is set then an error message is left in the
+ * interp's result.
*
* Side effects:
- * If part1 and part2 indicate a local or global variable in interp,
- * it is deleted. If part1 is an array name and part2 is NULL, then
- * the whole array is deleted.
+ * If part1 and part2 indicate a local or global variable in interp, it
+ * is deleted. If part1 is an array name and part2 is NULL, then the
+ * whole array is deleted.
*
*----------------------------------------------------------------------
*/
int
-Tcl_UnsetVar2(interp, part1, part2, flags)
- Tcl_Interp *interp; /* Command interpreter in which varName is
- * to be looked up. */
- CONST char *part1; /* Name of variable or array. */
- CONST char *part2; /* Name of element within array or NULL. */
- int flags; /* OR-ed combination of any of
+Tcl_UnsetVar2(
+ Tcl_Interp *interp, /* Command interpreter in which varName is to
+ * be looked up. */
+ const char *part1, /* Name of variable or array. */
+ const char *part2, /* Name of element within array or NULL. */
+ int flags) /* OR-ed combination of any of
* TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
* TCL_LEAVE_ERR_MSG. */
{
int result;
- Tcl_Obj *part1Ptr;
+ Tcl_Obj *part1Ptr, *part2Ptr = NULL;
part1Ptr = Tcl_NewStringObj(part1, -1);
Tcl_IncrRefCount(part1Ptr);
- /* Filter to pass through only the flags this interface supports. */
+ if (part2) {
+ part2Ptr = Tcl_NewStringObj(part2, -1);
+ Tcl_IncrRefCount(part2Ptr);
+ }
+
+ /*
+ * Filter to pass through only the flags this interface supports.
+ */
+
flags &= (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG);
- result = TclObjUnsetVar2(interp, part1Ptr, part2, flags);
- TclDecrRefCount(part1Ptr);
+ result = TclObjUnsetVar2(interp, part1Ptr, part2Ptr, flags);
+ Tcl_DecrRefCount(part1Ptr);
+ if (part2Ptr) {
+ Tcl_DecrRefCount(part2Ptr);
+ }
return result;
}
-
/*
*----------------------------------------------------------------------
@@ -1985,26 +2174,26 @@ Tcl_UnsetVar2(interp, part1, part2, flags)
* Delete a variable, given a 2-object name.
*
* Results:
- * Returns TCL_OK if the variable was successfully deleted, TCL_ERROR
- * if the variable can't be unset. In the event of an error,
- * if the TCL_LEAVE_ERR_MSG flag is set then an error message
- * is left in the interp's result.
+ * Returns TCL_OK if the variable was successfully deleted, TCL_ERROR if
+ * the variable can't be unset. In the event of an error, if the
+ * TCL_LEAVE_ERR_MSG flag is set then an error message is left in the
+ * interp's result.
*
* Side effects:
- * If part1ptr and part2Ptr indicate a local or global variable in interp,
- * it is deleted. If part1Ptr is an array name and part2Ptr is NULL, then
- * the whole array is deleted.
+ * If part1ptr and part2Ptr indicate a local or global variable in
+ * interp, it is deleted. If part1Ptr is an array name and part2Ptr is
+ * NULL, then the whole array is deleted.
*
*----------------------------------------------------------------------
*/
int
-TclObjUnsetVar2(interp, part1Ptr, part2, flags)
- Tcl_Interp *interp; /* Command interpreter in which varName is
- * to be looked up. */
- Tcl_Obj *part1Ptr; /* Name of variable or array. */
- CONST char *part2; /* Name of element within array or NULL. */
- int flags; /* OR-ed combination of any of
+TclObjUnsetVar2(
+ Tcl_Interp *interp, /* Command interpreter in which varName is to
+ * be looked up. */
+ Tcl_Obj *part1Ptr, /* Name of variable or array. */
+ Tcl_Obj *part2Ptr, /* Name of element within array or NULL. */
+ int flags) /* OR-ed combination of any of
* TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
* TCL_LEAVE_ERR_MSG. */
{
@@ -2012,49 +2201,51 @@ TclObjUnsetVar2(interp, part1Ptr, part2, flags)
Interp *iPtr = (Interp *) interp;
Var *arrayPtr;
int result;
- char *part1;
- part1 = TclGetString(part1Ptr);
- varPtr = TclObjLookupVar(interp, part1Ptr, part2, flags, "unset",
+ varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, flags, "unset",
/*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
if (varPtr == NULL) {
return TCL_ERROR;
}
-
+
result = (TclIsVarUndefined(varPtr)? TCL_ERROR : TCL_OK);
/*
* Keep the variable alive until we're done with it. We used to
- * increase/decrease the refCount for each operation, making it
- * hard to find [Bug 735335] - caused by unsetting the variable
- * whose value was the variable's name.
+ * increase/decrease the refCount for each operation, making it hard to
+ * find [Bug 735335] - caused by unsetting the variable whose value was
+ * the variable's name.
*/
-
- varPtr->refCount++;
- UnsetVarStruct(varPtr, arrayPtr, iPtr, part1, part2, flags);
+ if (TclIsVarInHash(varPtr)) {
+ VarHashRefCount(varPtr)++;
+ }
+
+ UnsetVarStruct(varPtr, arrayPtr, iPtr, part1Ptr, part2Ptr, flags);
/*
* It's an error to unset an undefined variable.
*/
-
+
if (result != TCL_OK) {
if (flags & TCL_LEAVE_ERR_MSG) {
- VarErrMsg(interp, part1, part2, "unset",
- ((arrayPtr == NULL) ? noSuchVar : noSuchElement));
+ TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "unset",
+ ((arrayPtr == NULL) ? noSuchVar : noSuchElement), -1);
}
}
+#if ENABLE_NS_VARNAME_CACHING
/*
- * Try to avoid keeping the Var struct allocated due to a tclNsVarNameType
+ * Try to avoid keeping the Var struct allocated due to a tclNsVarNameType
* keeping a reference. This removes some additional exteriorisations of
* [Bug 736729], but may be a good thing independently of the bug.
*/
if (part1Ptr->typePtr == &tclNsVarNameType) {
- part1Ptr->typePtr->freeIntRepProc(part1Ptr);
+ TclFreeIntRep(part1Ptr);
part1Ptr->typePtr = NULL;
}
+#endif
/*
* Finally, if the variable is truly not in use then free up its Var
@@ -2062,8 +2253,10 @@ TclObjUnsetVar2(interp, part1Ptr, part2, flags)
* its value object, if any, was decremented above.
*/
- varPtr->refCount--;
- CleanupVar(varPtr, arrayPtr);
+ if (TclIsVarInHash(varPtr)) {
+ VarHashRefCount(varPtr)--;
+ CleanupVar(varPtr, arrayPtr);
+ }
return result;
}
@@ -2081,492 +2274,166 @@ TclObjUnsetVar2(interp, part1Ptr, part2, flags)
*
* Side effects:
* If the arguments indicate a local or global variable in iPtr, it is
- * unset and deleted.
+ * unset and deleted.
*
*----------------------------------------------------------------------
*/
static void
-UnsetVarStruct(varPtr, arrayPtr, iPtr, part1, part2, flags)
- Var *varPtr;
- Var *arrayPtr;
- Interp *iPtr;
- CONST char *part1;
- CONST char *part2;
- int flags;
+UnsetVarStruct(
+ Var *varPtr,
+ Var *arrayPtr,
+ Interp *iPtr,
+ Tcl_Obj *part1Ptr,
+ Tcl_Obj *part2Ptr,
+ int flags)
{
Var dummyVar;
- Var *dummyVarPtr;
- ActiveVarTrace *activePtr;
-
- if ((arrayPtr != NULL) && (arrayPtr->searchPtr != NULL)) {
- DeleteSearches(arrayPtr);
- }
-
- /*
- * For global/upvar variables referenced in procedures, decrement
- * the reference count on the variable referred to, and free
- * the referenced variable if it's no longer needed.
- */
+ int traced = TclIsVarTraced(varPtr)
+ || (arrayPtr && (arrayPtr->flags & VAR_TRACED_UNSET));
- if (TclIsVarLink(varPtr)) {
- Var *linkPtr = varPtr->value.linkPtr;
- linkPtr->refCount--;
- if ((linkPtr->refCount == 0) && TclIsVarUndefined(linkPtr)
- && (linkPtr->tracePtr == NULL)
- && (linkPtr->flags & VAR_IN_HASHTABLE)) {
- if (linkPtr->hPtr != NULL) {
- Tcl_DeleteHashEntry(linkPtr->hPtr);
- }
- ckfree((char *) linkPtr);
- }
+ if (arrayPtr && (arrayPtr->flags & VAR_SEARCH_ACTIVE)) {
+ DeleteSearches(iPtr, arrayPtr);
+ } else if (varPtr->flags & VAR_SEARCH_ACTIVE) {
+ DeleteSearches(iPtr, varPtr);
}
/*
- * The code below is tricky, because of the possibility that
- * a trace procedure might try to access a variable being
- * deleted. To handle this situation gracefully, do things
- * in three steps:
- * 1. Copy the contents of the variable to a dummy variable
- * structure, and mark the original Var structure as undefined.
+ * The code below is tricky, because of the possibility that a trace
+ * function might try to access a variable being deleted. To handle this
+ * situation gracefully, do things in three steps:
+ * 1. Copy the contents of the variable to a dummy variable structure, and
+ * mark the original Var structure as undefined.
* 2. Invoke traces and clean up the variable, using the dummy copy.
- * 3. If at the end of this the original variable is still
- * undefined and has no outstanding references, then delete
- * it (but it could have gotten recreated by a trace).
+ * 3. If at the end of this the original variable is still undefined and
+ * has no outstanding references, then delete it (but it could have
+ * gotten recreated by a trace).
*/
dummyVar = *varPtr;
+ dummyVar.flags &= ~VAR_ALL_HASH;
TclSetVarUndefined(varPtr);
- TclSetVarScalar(varPtr);
- varPtr->value.objPtr = NULL; /* dummyVar points to any value object */
- varPtr->tracePtr = NULL;
- varPtr->searchPtr = NULL;
/*
- * Call trace procedures for the variable being deleted. Then delete
- * its traces. Be sure to abort any other traces for the variable
- * that are still pending. Special tricks:
- * 1. We need to increment varPtr's refCount around this: CallVarTraces
+ * Call trace functions for the variable being deleted. Then delete its
+ * traces. Be sure to abort any other traces for the variable that are
+ * still pending. Special tricks:
+ * 1. We need to increment varPtr's refCount around this: TclCallVarTraces
* will use dummyVar so it won't increment varPtr's refCount itself.
- * 2. Turn off the VAR_TRACE_ACTIVE flag in dummyVar: we want to
- * call unset traces even if other traces are pending.
+ * 2. Turn off the VAR_TRACE_ACTIVE flag in dummyVar: we want to call
+ * unset traces even if other traces are pending.
*/
- if ((dummyVar.tracePtr != NULL)
- || ((arrayPtr != NULL) && (arrayPtr->tracePtr != NULL))) {
- dummyVar.flags &= ~VAR_TRACE_ACTIVE;
- CallVarTraces(iPtr, arrayPtr, &dummyVar, part1, part2,
- (flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY))
- | TCL_TRACE_UNSETS, /* leaveErrMsg */ 0);
- while (dummyVar.tracePtr != NULL) {
- VarTrace *tracePtr = dummyVar.tracePtr;
- dummyVar.tracePtr = tracePtr->nextPtr;
- Tcl_EventuallyFree((ClientData) tracePtr, TCL_DYNAMIC);
- }
- for (activePtr = iPtr->activeVarTracePtr; activePtr != NULL;
- activePtr = activePtr->nextPtr) {
- if (activePtr->varPtr == varPtr) {
- activePtr->nextTracePtr = NULL;
- }
- }
- }
+ if (traced) {
+ VarTrace *tracePtr = NULL;
+ Tcl_HashEntry *tPtr = NULL;
- /*
- * If the variable is an array, delete all of its elements. This must be
- * done after calling the traces on the array, above (that's the way
- * traces are defined). If it is a scalar, "discard" its object
- * (decrement the ref count of its object, if any).
- */
-
- dummyVarPtr = &dummyVar;
- if (TclIsVarArray(dummyVarPtr) && !TclIsVarUndefined(dummyVarPtr)) {
- DeleteArray(iPtr, part1, dummyVarPtr, (flags
- & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY)) | TCL_TRACE_UNSETS);
- }
- if (TclIsVarScalar(dummyVarPtr)
- && (dummyVarPtr->value.objPtr != NULL)) {
- Tcl_Obj *objPtr = dummyVarPtr->value.objPtr;
- TclDecrRefCount(objPtr);
- dummyVarPtr->value.objPtr = NULL;
- }
-
- /*
- * If the variable was a namespace variable, decrement its reference count.
- */
-
- if (varPtr->flags & VAR_NAMESPACE_VAR) {
- varPtr->flags &= ~VAR_NAMESPACE_VAR;
- varPtr->refCount--;
- }
-
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_TraceVar --
- *
- * Arrange for reads and/or writes to a variable to cause a
- * procedure to be invoked, which can monitor the operations
- * and/or change their actions.
- *
- * Results:
- * A standard Tcl return value.
- *
- * Side effects:
- * A trace is set up on the variable given by varName, such that
- * future references to the variable will be intermediated by
- * proc. See the manual entry for complete details on the calling
- * sequence for proc.
- *
- *----------------------------------------------------------------------
- */
-
-int
-Tcl_TraceVar(interp, varName, flags, proc, clientData)
- Tcl_Interp *interp; /* Interpreter in which variable is
- * to be traced. */
- CONST char *varName; /* Name of variable; may end with "(index)"
- * to signify an array reference. */
- int flags; /* OR-ed collection of bits, including any
- * of TCL_TRACE_READS, TCL_TRACE_WRITES,
- * TCL_TRACE_UNSETS, TCL_GLOBAL_ONLY, and
- * TCL_NAMESPACE_ONLY. */
- Tcl_VarTraceProc *proc; /* Procedure to call when specified ops are
- * invoked upon varName. */
- ClientData clientData; /* Arbitrary argument to pass to proc. */
-{
- return Tcl_TraceVar2(interp, varName, (char *) NULL,
- flags, proc, clientData);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_TraceVar2 --
- *
- * Arrange for reads and/or writes to a variable to cause a
- * procedure to be invoked, which can monitor the operations
- * and/or change their actions.
- *
- * Results:
- * A standard Tcl return value.
- *
- * Side effects:
- * A trace is set up on the variable given by part1 and part2, such
- * that future references to the variable will be intermediated by
- * proc. See the manual entry for complete details on the calling
- * sequence for proc.
- *
- *----------------------------------------------------------------------
- */
+ if (TclIsVarTraced(&dummyVar)) {
+ /*
+ * Transfer any existing traces on var, IF there are unset traces.
+ * Otherwise just delete them.
+ */
-int
-Tcl_TraceVar2(interp, part1, part2, flags, proc, clientData)
- Tcl_Interp *interp; /* Interpreter in which variable is
- * to be traced. */
- CONST char *part1; /* Name of scalar variable or array. */
- CONST char *part2; /* Name of element within array; NULL means
- * trace applies to scalar variable or array
- * as-a-whole. */
- int flags; /* OR-ed collection of bits, including any
- * of TCL_TRACE_READS, TCL_TRACE_WRITES,
- * TCL_TRACE_UNSETS, TCL_GLOBAL_ONLY,
- * and TCL_NAMESPACE_ONLY. */
- Tcl_VarTraceProc *proc; /* Procedure to call when specified ops are
- * invoked upon varName. */
- ClientData clientData; /* Arbitrary argument to pass to proc. */
-{
- Var *varPtr, *arrayPtr;
- register VarTrace *tracePtr;
- int flagMask;
-
- /*
- * We strip 'flags' down to just the parts which are relevant to
- * TclLookupVar, to avoid conflicts between trace flags and
- * internal namespace flags such as 'FIND_ONLY_NS'. This can
- * now occur since we have trace flags with values 0x1000 and higher.
- */
- flagMask = TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY;
- varPtr = TclLookupVar(interp, part1, part2,
- (flags & flagMask) | TCL_LEAVE_ERR_MSG,
- "trace", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
- if (varPtr == NULL) {
- return TCL_ERROR;
- }
+ int isNew;
+ Tcl_HashEntry *tPtr =
+ Tcl_FindHashEntry(&iPtr->varTraces, (char *) varPtr);
+
+ tracePtr = Tcl_GetHashValue(tPtr);
+ varPtr->flags &= ~VAR_ALL_TRACES;
+ Tcl_DeleteHashEntry(tPtr);
+ if (dummyVar.flags & VAR_TRACED_UNSET) {
+ tPtr = Tcl_CreateHashEntry(&iPtr->varTraces,
+ (char *) &dummyVar, &isNew);
+ Tcl_SetHashValue(tPtr, tracePtr);
+ } else {
+ tPtr = NULL;
+ }
+ }
- /*
- * Check for a nonsense flag combination. Note that this is a
- * panic() because there should be no code path that ever sets
- * both flags.
- */
- if ((flags&TCL_TRACE_RESULT_DYNAMIC) && (flags&TCL_TRACE_RESULT_OBJECT)) {
- panic("bad result flag combination");
- }
+ if ((dummyVar.flags & VAR_TRACED_UNSET)
+ || (arrayPtr && (arrayPtr->flags & VAR_TRACED_UNSET))) {
+ dummyVar.flags &= ~VAR_TRACE_ACTIVE;
+ TclObjCallVarTraces(iPtr, arrayPtr, &dummyVar, part1Ptr, part2Ptr,
+ (flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY))
+ | TCL_TRACE_UNSETS,
+ /* leaveErrMsg */ 0, -1);
- /*
- * Set up trace information.
- */
+ /*
+ * The traces that we just called may have triggered a change in
+ * the set of traces. [Bug 2629338]
+ */
- flagMask = TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS |
- TCL_TRACE_ARRAY | TCL_TRACE_RESULT_DYNAMIC | TCL_TRACE_RESULT_OBJECT;
-#ifndef TCL_REMOVE_OBSOLETE_TRACES
- flagMask |= TCL_TRACE_OLD_STYLE;
-#endif
- tracePtr = (VarTrace *) ckalloc(sizeof(VarTrace));
- tracePtr->traceProc = proc;
- tracePtr->clientData = clientData;
- tracePtr->flags = flags & flagMask;
- tracePtr->nextPtr = varPtr->tracePtr;
- varPtr->tracePtr = tracePtr;
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_UntraceVar --
- *
- * Remove a previously-created trace for a variable.
- *
- * Results:
- * None.
- *
- * Side effects:
- * If there exists a trace for the variable given by varName
- * with the given flags, proc, and clientData, then that trace
- * is removed.
- *
- *----------------------------------------------------------------------
- */
+ tracePtr = NULL;
+ if (TclIsVarTraced(&dummyVar)) {
+ tPtr = Tcl_FindHashEntry(&iPtr->varTraces, (char *) &dummyVar);
+ tracePtr = Tcl_GetHashValue(tPtr);
+ }
-void
-Tcl_UntraceVar(interp, varName, flags, proc, clientData)
- Tcl_Interp *interp; /* Interpreter containing variable. */
- CONST char *varName; /* Name of variable; may end with "(index)"
- * to signify an array reference. */
- int flags; /* OR-ed collection of bits describing
- * current trace, including any of
- * TCL_TRACE_READS, TCL_TRACE_WRITES,
- * TCL_TRACE_UNSETS, TCL_GLOBAL_ONLY
- * and TCL_NAMESPACE_ONLY. */
- Tcl_VarTraceProc *proc; /* Procedure assocated with trace. */
- ClientData clientData; /* Arbitrary argument to pass to proc. */
-{
- Tcl_UntraceVar2(interp, varName, (char *) NULL, flags, proc, clientData);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_UntraceVar2 --
- *
- * Remove a previously-created trace for a variable.
- *
- * Results:
- * None.
- *
- * Side effects:
- * If there exists a trace for the variable given by part1
- * and part2 with the given flags, proc, and clientData, then
- * that trace is removed.
- *
- *----------------------------------------------------------------------
- */
+ if (tPtr) {
+ Tcl_DeleteHashEntry(tPtr);
+ }
+ }
-void
-Tcl_UntraceVar2(interp, part1, part2, flags, proc, clientData)
- Tcl_Interp *interp; /* Interpreter containing variable. */
- CONST char *part1; /* Name of variable or array. */
- CONST char *part2; /* Name of element within array; NULL means
- * trace applies to scalar variable or array
- * as-a-whole. */
- int flags; /* OR-ed collection of bits describing
- * current trace, including any of
- * TCL_TRACE_READS, TCL_TRACE_WRITES,
- * TCL_TRACE_UNSETS, TCL_GLOBAL_ONLY,
- * and TCL_NAMESPACE_ONLY. */
- Tcl_VarTraceProc *proc; /* Procedure assocated with trace. */
- ClientData clientData; /* Arbitrary argument to pass to proc. */
-{
- register VarTrace *tracePtr;
- VarTrace *prevPtr;
- Var *varPtr, *arrayPtr;
- Interp *iPtr = (Interp *) interp;
- ActiveVarTrace *activePtr;
- int flagMask;
-
- /*
- * Set up a mask to mask out the parts of the flags that we are not
- * interested in now.
- */
- flagMask = TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY;
- varPtr = TclLookupVar(interp, part1, part2, flags & flagMask,
- /*msg*/ (char *) NULL,
- /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
- if (varPtr == NULL) {
- return;
- }
+ if (tracePtr) {
+ ActiveVarTrace *activePtr;
+ while (tracePtr) {
+ VarTrace *prevPtr = tracePtr;
- /*
- * Set up a mask to mask out the parts of the flags that we are not
- * interested in now.
- */
- flagMask = TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS |
- TCL_TRACE_ARRAY | TCL_TRACE_RESULT_DYNAMIC | TCL_TRACE_RESULT_OBJECT;
-#ifndef TCL_REMOVE_OBSOLETE_TRACES
- flagMask |= TCL_TRACE_OLD_STYLE;
-#endif
- flags &= flagMask;
- for (tracePtr = varPtr->tracePtr, prevPtr = NULL; ;
- prevPtr = tracePtr, tracePtr = tracePtr->nextPtr) {
- if (tracePtr == NULL) {
- return;
- }
- if ((tracePtr->traceProc == proc) && (tracePtr->flags == flags)
- && (tracePtr->clientData == clientData)) {
- break;
+ tracePtr = tracePtr->nextPtr;
+ prevPtr->nextPtr = NULL;
+ Tcl_EventuallyFree((ClientData) prevPtr, TCL_DYNAMIC);
+ }
+ for (activePtr = iPtr->activeVarTracePtr; activePtr != NULL;
+ activePtr = activePtr->nextPtr) {
+ if (activePtr->varPtr == varPtr) {
+ activePtr->nextTracePtr = NULL;
+ }
+ }
+ dummyVar.flags &= ~VAR_ALL_TRACES;
}
}
- /*
- * The code below makes it possible to delete traces while traces
- * are active: it makes sure that the deleted trace won't be
- * processed by CallVarTraces.
- */
-
- for (activePtr = iPtr->activeVarTracePtr; activePtr != NULL;
- activePtr = activePtr->nextPtr) {
- if (activePtr->nextTracePtr == tracePtr) {
- activePtr->nextTracePtr = tracePtr->nextPtr;
- }
- }
- if (prevPtr == NULL) {
- varPtr->tracePtr = tracePtr->nextPtr;
- } else {
- prevPtr->nextPtr = tracePtr->nextPtr;
- }
- Tcl_EventuallyFree((ClientData) tracePtr, TCL_DYNAMIC);
+ if (TclIsVarScalar(&dummyVar) && (dummyVar.value.objPtr != NULL)) {
+ /*
+ * Decrement the ref count of the var's value.
+ */
- /*
- * If this is the last trace on the variable, and the variable is
- * unset and unused, then free up the variable.
- */
+ Tcl_Obj *objPtr = dummyVar.value.objPtr;
- if (TclIsVarUndefined(varPtr)) {
- CleanupVar(varPtr, (Var *) NULL);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_VarTraceInfo --
- *
- * Return the clientData value associated with a trace on a
- * variable. This procedure can also be used to step through
- * all of the traces on a particular variable that have the
- * same trace procedure.
- *
- * Results:
- * The return value is the clientData value associated with
- * a trace on the given variable. Information will only be
- * returned for a trace with proc as trace procedure. If
- * the clientData argument is NULL then the first such trace is
- * returned; otherwise, the next relevant one after the one
- * given by clientData will be returned. If the variable
- * doesn't exist, or if there are no (more) traces for it,
- * then NULL is returned.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
+ TclDecrRefCount(objPtr);
+ } else if (TclIsVarArray(&dummyVar)) {
+ /*
+ * If the variable is an array, delete all of its elements. This must
+ * be done after calling and deleting the traces on the array, above
+ * (that's the way traces are defined). If the array name is not
+ * present and is required for a trace on some element, it will be
+ * computed at DeleteArray.
+ */
-ClientData
-Tcl_VarTraceInfo(interp, varName, flags, proc, prevClientData)
- Tcl_Interp *interp; /* Interpreter containing variable. */
- CONST char *varName; /* Name of variable; may end with "(index)"
- * to signify an array reference. */
- int flags; /* OR-ed combo or TCL_GLOBAL_ONLY,
- * TCL_NAMESPACE_ONLY (can be 0). */
- Tcl_VarTraceProc *proc; /* Procedure assocated with trace. */
- ClientData prevClientData; /* If non-NULL, gives last value returned
- * by this procedure, so this call will
- * return the next trace after that one.
- * If NULL, this call will return the
- * first trace. */
-{
- return Tcl_VarTraceInfo2(interp, varName, (char *) NULL,
- flags, proc, prevClientData);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_VarTraceInfo2 --
- *
- * Same as Tcl_VarTraceInfo, except takes name in two pieces
- * instead of one.
- *
- * Results:
- * Same as Tcl_VarTraceInfo.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
+ DeleteArray(iPtr, part1Ptr, (Var *) &dummyVar, (flags
+ & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY)) | TCL_TRACE_UNSETS);
+ } else if (TclIsVarLink(&dummyVar)) {
+ /*
+ * For global/upvar variables referenced in procedures, decrement the
+ * reference count on the variable referred to, and free the
+ * referenced variable if it's no longer needed.
+ */
-ClientData
-Tcl_VarTraceInfo2(interp, part1, part2, flags, proc, prevClientData)
- Tcl_Interp *interp; /* Interpreter containing variable. */
- CONST char *part1; /* Name of variable or array. */
- CONST char *part2; /* Name of element within array; NULL means
- * trace applies to scalar variable or array
- * as-a-whole. */
- int flags; /* OR-ed combination of TCL_GLOBAL_ONLY,
- * TCL_NAMESPACE_ONLY. */
- Tcl_VarTraceProc *proc; /* Procedure assocated with trace. */
- ClientData prevClientData; /* If non-NULL, gives last value returned
- * by this procedure, so this call will
- * return the next trace after that one.
- * If NULL, this call will return the
- * first trace. */
-{
- register VarTrace *tracePtr;
- Var *varPtr, *arrayPtr;
+ Var *linkPtr = dummyVar.value.linkPtr;
- varPtr = TclLookupVar(interp, part1, part2,
- flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY),
- /*msg*/ (char *) NULL,
- /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
- if (varPtr == NULL) {
- return NULL;
+ if (TclIsVarInHash(linkPtr)) {
+ VarHashRefCount(linkPtr)--;
+ CleanupVar(linkPtr, NULL);
+ }
}
/*
- * Find the relevant trace, if any, and return its clientData.
+ * If the variable was a namespace variable, decrement its reference
+ * count.
*/
- tracePtr = varPtr->tracePtr;
- if (prevClientData != NULL) {
- for ( ; tracePtr != NULL; tracePtr = tracePtr->nextPtr) {
- if ((tracePtr->clientData == prevClientData)
- && (tracePtr->traceProc == proc)) {
- tracePtr = tracePtr->nextPtr;
- break;
- }
- }
- }
- for ( ; tracePtr != NULL; tracePtr = tracePtr->nextPtr) {
- if (tracePtr->traceProc == proc) {
- return tracePtr->clientData;
- }
- }
- return NULL;
+ TclClearVarNamespaceVar(varPtr);
}
/*
@@ -2574,7 +2441,7 @@ Tcl_VarTraceInfo2(interp, part1, part2, flags, proc, prevClientData)
*
* Tcl_UnsetObjCmd --
*
- * This object-based procedure is invoked to process the "unset" Tcl
+ * This object-based function is invoked to process the "unset" Tcl
* command. See the user documentation for details on what it does.
*
* Results:
@@ -2588,49 +2455,47 @@ Tcl_VarTraceInfo2(interp, part1, part2, flags, proc, prevClientData)
/* ARGSUSED */
int
-Tcl_UnsetObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_UnsetObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
register int i, flags = TCL_LEAVE_ERR_MSG;
register char *name;
- if (objc < 1) {
- Tcl_WrongNumArgs(interp, 1, objv,
- "?-nocomplain? ?--? ?varName varName ...?");
- return TCL_ERROR;
- } else if (objc == 1) {
+ if (objc == 1) {
/*
- * Do nothing if no arguments supplied, so as to match
- * command documentation.
+ * Do nothing if no arguments supplied, so as to match command
+ * documentation.
*/
+
return TCL_OK;
}
/*
- * Simple, restrictive argument parsing. The only options are --
- * and -nocomplain (which must come first and be given exactly to
- * be an option).
+ * Simple, restrictive argument parsing. The only options are -- and
+ * -nocomplain (which must come first and be given exactly to be an
+ * option).
*/
+
i = 1;
name = TclGetString(objv[i]);
if (name[0] == '-') {
- if (strcmp("-nocomplain", name) == 0) {
+ if (strcmp("-nocomplain", name) == 0) {
i++;
- if (i == objc) {
+ if (i == objc) {
return TCL_OK;
}
- flags = 0;
- name = TclGetString(objv[i]);
- }
- if (strcmp("--", name) == 0) {
- i++;
- }
+ flags = 0;
+ name = TclGetString(objv[i]);
+ }
+ if (strcmp("--", name) == 0) {
+ i++;
+ }
}
- for (; i < objc; i++) {
+ for (; i < objc; i++) {
if ((TclObjUnsetVar2(interp, objv[i], NULL, flags) != TCL_OK)
&& (flags == TCL_LEAVE_ERR_MSG)) {
return TCL_ERROR;
@@ -2644,8 +2509,8 @@ Tcl_UnsetObjCmd(dummy, interp, objc, objv)
*
* Tcl_AppendObjCmd --
*
- * This object-based procedure is invoked to process the "append"
- * Tcl command. See the user documentation for details on what it does.
+ * This object-based function is invoked to process the "append" Tcl
+ * command. See the user documentation for details on what it does.
*
* Results:
* A standard Tcl object result value.
@@ -2658,18 +2523,15 @@ Tcl_UnsetObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_AppendObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_AppendObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Var *varPtr, *arrayPtr;
- char *part1;
-
register Tcl_Obj *varValuePtr = NULL;
- /* Initialized to avoid compiler
- * warning. */
+ /* Initialized to avoid compiler warning. */
int i;
if (objc < 2) {
@@ -2678,27 +2540,26 @@ Tcl_AppendObjCmd(dummy, interp, objc, objv)
}
if (objc == 2) {
- varValuePtr = Tcl_ObjGetVar2(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG);
+ varValuePtr = Tcl_ObjGetVar2(interp, objv[1], NULL,TCL_LEAVE_ERR_MSG);
if (varValuePtr == NULL) {
return TCL_ERROR;
}
} else {
- varPtr = TclObjLookupVar(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG,
+ varPtr = TclObjLookupVarEx(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG,
"set", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
- part1 = TclGetString(objv[1]);
if (varPtr == NULL) {
return TCL_ERROR;
}
- for (i = 2; i < objc; i++) {
+ for (i=2 ; i<objc ; i++) {
/*
- * Note that we do not need to increase the refCount of
- * the Var pointers: should a trace delete the variable,
- * the return value of TclPtrSetVar will be NULL, and we
- * will not access the variable again.
+ * Note that we do not need to increase the refCount of the Var
+ * pointers: should a trace delete the variable, the return value
+ * of TclPtrSetVar will be NULL or emptyObjPtr, and we will not
+ * access the variable again.
*/
- varValuePtr = TclPtrSetVar(interp, varPtr, arrayPtr, part1, NULL,
- objv[i], (TCL_APPEND_VALUE | TCL_LEAVE_ERR_MSG));
+ varValuePtr = TclPtrSetVar(interp, varPtr, arrayPtr, objv[1],
+ NULL, objv[i], TCL_APPEND_VALUE|TCL_LEAVE_ERR_MSG, -1);
if ((varValuePtr == NULL) ||
(varValuePtr == ((Interp *) interp)->emptyObjPtr)) {
return TCL_ERROR;
@@ -2714,8 +2575,8 @@ Tcl_AppendObjCmd(dummy, interp, objc, objv)
*
* Tcl_LappendObjCmd --
*
- * This object-based procedure is invoked to process the "lappend"
- * Tcl command. See the user documentation for details on what it does.
+ * This object-based function is invoked to process the "lappend" Tcl
+ * command. See the user documentation for details on what it does.
*
* Results:
* A standard Tcl object result value.
@@ -2728,157 +2589,114 @@ Tcl_AppendObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_LappendObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_LappendObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Obj *varValuePtr, *newValuePtr;
- register List *listRepPtr;
- register Tcl_Obj **elemPtrs;
- int numElems, numRequired, createdNewObj, i, j;
+ int numElems, createdNewObj;
Var *varPtr, *arrayPtr;
- char *part1;
+ int result;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "varName ?value value ...?");
return TCL_ERROR;
}
if (objc == 2) {
- newValuePtr = Tcl_ObjGetVar2(interp, objv[1], (Tcl_Obj *) NULL, 0);
+ newValuePtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0);
if (newValuePtr == NULL) {
/*
* The variable doesn't exist yet. Just create it with an empty
* initial value.
*/
-
- varValuePtr = Tcl_NewObj();
- Tcl_IncrRefCount(varValuePtr);
+
+ TclNewObj(varValuePtr);
newValuePtr = Tcl_ObjSetVar2(interp, objv[1], NULL, varValuePtr,
TCL_LEAVE_ERR_MSG);
- Tcl_DecrRefCount(varValuePtr);
if (newValuePtr == NULL) {
return TCL_ERROR;
}
} else {
- int result;
-
- result = Tcl_ListObjLength(interp, newValuePtr, &numElems);
+ result = TclListObjLength(interp, newValuePtr, &numElems);
if (result != TCL_OK) {
return result;
}
- }
+ }
} else {
/*
- * We have arguments to append. We used to call Tcl_SetVar2 to
- * append each argument one at a time to ensure that traces were run
- * for each append step. We now append the arguments all at once
- * because it's faster. Note that a read trace and a write trace for
- * the variable will now each only be called once. Also, if the
- * variable's old value is unshared we modify it directly, otherwise
- * we create a new copy to modify: this is "copy on write".
- *
- * Note that you have to protect the variable pointers around
- * the TclPtrGetVar call to insure that they remain valid
- * even if the variable was undefined and unused.
+ * We have arguments to append. We used to call Tcl_SetVar2 to append
+ * each argument one at a time to ensure that traces were run for each
+ * append step. We now append the arguments all at once because it's
+ * faster. Note that a read trace and a write trace for the variable
+ * will now each only be called once. Also, if the variable's old
+ * value is unshared we modify it directly, otherwise we create a new
+ * copy to modify: this is "copy on write".
+ */
+
+ createdNewObj = 0;
+
+ /*
+ * Protect the variable pointers around the TclPtrGetVar call
+ * to insure that they remain valid even if the variable was undefined
+ * and unused.
*/
- varPtr = TclObjLookupVar(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG,
+ varPtr = TclObjLookupVarEx(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG,
"set", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
if (varPtr == NULL) {
return TCL_ERROR;
}
- varPtr->refCount++;
- if (arrayPtr != NULL) {
- arrayPtr->refCount++;
+ if (TclIsVarInHash(varPtr)) {
+ VarHashRefCount(varPtr)++;
}
- part1 = TclGetString(objv[1]);
- varValuePtr = TclPtrGetVar(interp, varPtr, arrayPtr, part1, NULL,
- TCL_LEAVE_ERR_MSG);
- varPtr->refCount--;
- if (arrayPtr != NULL) {
- arrayPtr->refCount--;
+ if (arrayPtr && TclIsVarInHash(arrayPtr)) {
+ VarHashRefCount(arrayPtr)++;
+ }
+ varValuePtr = TclPtrGetVar(interp, varPtr, arrayPtr, objv[1], NULL,
+ TCL_LEAVE_ERR_MSG, -1);
+ if (TclIsVarInHash(varPtr)) {
+ VarHashRefCount(varPtr)--;
+ }
+ if (arrayPtr && TclIsVarInHash(arrayPtr)) {
+ VarHashRefCount(arrayPtr)--;
}
- createdNewObj = 0;
if (varValuePtr == NULL) {
/*
* We couldn't read the old value: either the var doesn't yet
- * exist or it's an array element. If it's new, we will try to
+ * exist or it's an array element. If it's new, we will try to
* create it with Tcl_ObjSetVar2 below.
*/
-
- varValuePtr = Tcl_NewObj();
+
+ TclNewObj(varValuePtr);
createdNewObj = 1;
- } else if (Tcl_IsShared(varValuePtr)) {
+ } else if (Tcl_IsShared(varValuePtr)) {
varValuePtr = Tcl_DuplicateObj(varValuePtr);
createdNewObj = 1;
}
- /*
- * Convert the variable's old value to a list object if necessary.
- */
-
- if (varValuePtr->typePtr != &tclListType) {
- int result = tclListType.setFromAnyProc(interp, varValuePtr);
- if (result != TCL_OK) {
- if (createdNewObj) {
- Tcl_DecrRefCount(varValuePtr); /* free unneeded obj. */
- }
- return result;
- }
+ result = TclListObjLength(interp, varValuePtr, &numElems);
+ if (result == TCL_OK) {
+ result = Tcl_ListObjReplace(interp, varValuePtr, numElems, 0,
+ (objc-2), (objv+2));
}
- listRepPtr = (List *) varValuePtr->internalRep.twoPtrValue.ptr1;
- elemPtrs = listRepPtr->elements;
- numElems = listRepPtr->elemCount;
-
- /*
- * If there is no room in the current array of element pointers,
- * allocate a new, larger array and copy the pointers to it.
- */
-
- numRequired = numElems + (objc-2);
- if (numRequired > listRepPtr->maxElemCount) {
- int newMax = (2 * numRequired);
- Tcl_Obj **newElemPtrs = (Tcl_Obj **)
- ckalloc((unsigned) (newMax * sizeof(Tcl_Obj *)));
-
- memcpy((VOID *) newElemPtrs, (VOID *) elemPtrs,
- (size_t) (numElems * sizeof(Tcl_Obj *)));
- listRepPtr->maxElemCount = newMax;
- listRepPtr->elements = newElemPtrs;
- ckfree((char *) elemPtrs);
- elemPtrs = newElemPtrs;
+ if (result != TCL_OK) {
+ if (createdNewObj) {
+ TclDecrRefCount(varValuePtr); /* Free unneeded obj. */
+ }
+ return result;
}
/*
- * Insert the new elements at the end of the list.
- */
-
- for (i = 2, j = numElems; i < objc; i++, j++) {
- elemPtrs[j] = objv[i];
- Tcl_IncrRefCount(objv[i]);
- }
- listRepPtr->elemCount = numRequired;
-
- /*
- * Invalidate and free any old string representation since it no
- * longer reflects the list's internal representation.
- */
-
- Tcl_InvalidateStringRep(varValuePtr);
-
- /*
* Now store the list object back into the variable. If there is an
- * error setting the new value, decrement its ref count if it
- * was new and we didn't create the variable.
+ * error setting the new value, decrement its ref count if it was new
+ * and we didn't create the variable.
*/
-
- Tcl_IncrRefCount(varValuePtr);
- newValuePtr = TclPtrSetVar(interp, varPtr, arrayPtr, part1, NULL,
- varValuePtr, TCL_LEAVE_ERR_MSG);
- Tcl_DecrRefCount(varValuePtr);
+
+ newValuePtr = TclPtrSetVar(interp, varPtr, arrayPtr, objv[1], NULL,
+ varValuePtr, TCL_LEAVE_ERR_MSG, -1);
if (newValuePtr == NULL) {
return TCL_ERROR;
}
@@ -2898,7 +2716,7 @@ Tcl_LappendObjCmd(dummy, interp, objc, objv)
*
* Tcl_ArrayObjCmd --
*
- * This object-based procedure is invoked to process the "array" Tcl
+ * This object-based function is invoked to process the "array" Tcl
* command. See the user documentation for details on what it does.
*
* Results:
@@ -2912,34 +2730,34 @@ Tcl_LappendObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_ArrayObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_ArrayObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
/*
* The list of constants below should match the arrayOptions string array
* below.
*/
- enum {ARRAY_ANYMORE, ARRAY_DONESEARCH, ARRAY_EXISTS, ARRAY_GET,
- ARRAY_NAMES, ARRAY_NEXTELEMENT, ARRAY_SET, ARRAY_SIZE,
- ARRAY_STARTSEARCH, ARRAY_STATISTICS, ARRAY_UNSET};
- static CONST char *arrayOptions[] = {
+ enum {
+ ARRAY_ANYMORE, ARRAY_DONESEARCH, ARRAY_EXISTS, ARRAY_GET,
+ ARRAY_NAMES, ARRAY_NEXTELEMENT, ARRAY_SET, ARRAY_SIZE,
+ ARRAY_STARTSEARCH, ARRAY_STATISTICS, ARRAY_UNSET
+ };
+ static const char *arrayOptions[] = {
"anymore", "donesearch", "exists", "get", "names", "nextelement",
- "set", "size", "startsearch", "statistics", "unset", (char *) NULL
+ "set", "size", "startsearch", "statistics", "unset", NULL
};
Interp *iPtr = (Interp *) interp;
Var *varPtr, *arrayPtr;
Tcl_HashEntry *hPtr;
- Tcl_Obj *resultPtr, *varNamePtr;
+ Tcl_Obj *varNamePtr;
int notArray;
- char *varName;
int index, result;
-
if (objc < 3) {
Tcl_WrongNumArgs(interp, 1, objv, "option arrayName ?arg ...?");
return TCL_ERROR;
@@ -2947,36 +2765,35 @@ Tcl_ArrayObjCmd(dummy, interp, objc, objv)
if (Tcl_GetIndexFromObj(interp, objv[1], arrayOptions, "option",
0, &index) != TCL_OK) {
- return TCL_ERROR;
+ return TCL_ERROR;
}
/*
* Locate the array variable
*/
-
+
varNamePtr = objv[2];
- varName = TclGetString(varNamePtr);
- varPtr = TclObjLookupVar(interp, varNamePtr, NULL, /*flags*/ 0,
- /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
+ varPtr = TclObjLookupVarEx(interp, varNamePtr, NULL, /*flags*/ 0,
+ /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
/*
- * Special array trace used to keep the env array in sync for
- * array names, array get, etc.
+ * Special array trace used to keep the env array in sync for array names,
+ * array get, etc.
*/
- if (varPtr != NULL && varPtr->tracePtr != NULL
+ if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY)
&& (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) {
- if (TCL_ERROR == CallVarTraces(iPtr, arrayPtr, varPtr, varName, NULL,
+ if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNamePtr, NULL,
(TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY|
- TCL_TRACE_ARRAY), /* leaveErrMsg */ 1)) {
+ TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) {
return TCL_ERROR;
}
}
/*
- * Verify that it is indeed an array variable. This test comes after
- * the traces - the variable may actually become an array as an effect
- * of said traces.
+ * Verify that it is indeed an array variable. This test comes after the
+ * traces - the variable may actually become an array as an effect of said
+ * traces.
*/
notArray = 0;
@@ -2985,424 +2802,505 @@ Tcl_ArrayObjCmd(dummy, interp, objc, objv)
notArray = 1;
}
- /*
- * We have to wait to get the resultPtr until here because
- * CallVarTraces can affect the result.
- */
+ switch (index) {
+ case ARRAY_ANYMORE: {
+ ArraySearch *searchPtr;
- resultPtr = Tcl_GetObjResult(interp);
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "arrayName searchId");
+ return TCL_ERROR;
+ }
+ if (notArray) {
+ goto error;
+ }
+ searchPtr = ParseSearchId(interp, varPtr, varNamePtr, objv[3]);
+ if (searchPtr == NULL) {
+ return TCL_ERROR;
+ }
+ while (1) {
+ Var *varPtr2;
- switch (index) {
- case ARRAY_ANYMORE: {
- ArraySearch *searchPtr;
-
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "arrayName searchId");
- return TCL_ERROR;
- }
- if (notArray) {
- goto error;
+ if (searchPtr->nextEntry != NULL) {
+ varPtr2 = VarHashGetValue(searchPtr->nextEntry);
+ if (!TclIsVarUndefined(varPtr2)) {
+ break;
+ }
}
- searchPtr = ParseSearchId(interp, varPtr, varName, objv[3]);
- if (searchPtr == NULL) {
- return TCL_ERROR;
+ searchPtr->nextEntry = Tcl_NextHashEntry(&searchPtr->search);
+ if (searchPtr->nextEntry == NULL) {
+ Tcl_SetObjResult(interp, iPtr->execEnvPtr->constants[0]);
+ return TCL_OK;
}
- while (1) {
- Var *varPtr2;
+ }
+ Tcl_SetObjResult(interp, iPtr->execEnvPtr->constants[1]);
+ break;
+ }
+ case ARRAY_DONESEARCH: {
+ ArraySearch *searchPtr, *prevPtr;
- if (searchPtr->nextEntry != NULL) {
- varPtr2 = (Var *) Tcl_GetHashValue(searchPtr->nextEntry);
- if (!TclIsVarUndefined(varPtr2)) {
- break;
- }
- }
- searchPtr->nextEntry = Tcl_NextHashEntry(&searchPtr->search);
- if (searchPtr->nextEntry == NULL) {
- Tcl_SetIntObj(resultPtr, 0);
- return TCL_OK;
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "arrayName searchId");
+ return TCL_ERROR;
+ }
+ if (notArray) {
+ goto error;
+ }
+ searchPtr = ParseSearchId(interp, varPtr, varNamePtr, objv[3]);
+ if (searchPtr == NULL) {
+ return TCL_ERROR;
+ }
+ hPtr = Tcl_FindHashEntry(&iPtr->varSearches,(char *) varPtr);
+ if (searchPtr == Tcl_GetHashValue(hPtr)) {
+ if (searchPtr->nextPtr) {
+ Tcl_SetHashValue(hPtr, searchPtr->nextPtr);
+ } else {
+ varPtr->flags &= ~VAR_SEARCH_ACTIVE;
+ Tcl_DeleteHashEntry(hPtr);
+ }
+ } else {
+ for (prevPtr=Tcl_GetHashValue(hPtr) ;; prevPtr=prevPtr->nextPtr) {
+ if (prevPtr->nextPtr == searchPtr) {
+ prevPtr->nextPtr = searchPtr->nextPtr;
+ break;
}
}
- Tcl_SetIntObj(resultPtr, 1);
- break;
}
- case ARRAY_DONESEARCH: {
- ArraySearch *searchPtr, *prevPtr;
+ ckfree((char *) searchPtr);
+ break;
+ }
+ case ARRAY_NEXTELEMENT: {
+ ArraySearch *searchPtr;
+ Tcl_HashEntry *hPtr;
+ Var *varPtr2;
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "arrayName searchId");
- return TCL_ERROR;
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "arrayName searchId");
+ return TCL_ERROR;
+ }
+ if (notArray) {
+ goto error;
+ }
+ searchPtr = ParseSearchId(interp, varPtr, varNamePtr, objv[3]);
+ if (searchPtr == NULL) {
+ return TCL_ERROR;
+ }
+ while (1) {
+ hPtr = searchPtr->nextEntry;
+ if (hPtr == NULL) {
+ hPtr = Tcl_NextHashEntry(&searchPtr->search);
+ if (hPtr == NULL) {
+ return TCL_OK;
+ }
+ } else {
+ searchPtr->nextEntry = NULL;
}
- if (notArray) {
- goto error;
+ varPtr2 = VarHashGetValue(hPtr);
+ if (!TclIsVarUndefined(varPtr2)) {
+ break;
}
- searchPtr = ParseSearchId(interp, varPtr, varName, objv[3]);
- if (searchPtr == NULL) {
- return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, VarHashGetKey(varPtr2));
+ break;
+ }
+ case ARRAY_STARTSEARCH: {
+ ArraySearch *searchPtr;
+ int isNew;
+ char *varName = TclGetString(varNamePtr);
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "arrayName");
+ return TCL_ERROR;
+ }
+ if (notArray) {
+ goto error;
+ }
+ searchPtr = (ArraySearch *) ckalloc(sizeof(ArraySearch));
+ hPtr = Tcl_CreateHashEntry(&iPtr->varSearches,
+ (char *) varPtr, &isNew);
+ if (isNew) {
+ searchPtr->id = 1;
+ Tcl_AppendResult(interp, "s-1-", varName, NULL);
+ varPtr->flags |= VAR_SEARCH_ACTIVE;
+ searchPtr->nextPtr = NULL;
+ } else {
+ char string[TCL_INTEGER_SPACE];
+
+ searchPtr->id = ((ArraySearch *) Tcl_GetHashValue(hPtr))->id + 1;
+ TclFormatInt(string, searchPtr->id);
+ Tcl_AppendResult(interp, "s-", string, "-", varName, NULL);
+ searchPtr->nextPtr = Tcl_GetHashValue(hPtr);
+ }
+ searchPtr->varPtr = varPtr;
+ searchPtr->nextEntry = VarHashFirstEntry(varPtr->value.tablePtr,
+ &searchPtr->search);
+ Tcl_SetHashValue(hPtr, searchPtr);
+ break;
+ }
+
+ case ARRAY_EXISTS:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "arrayName");
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, iPtr->execEnvPtr->constants[!notArray]);
+ break;
+ case ARRAY_GET: {
+ Tcl_HashSearch search;
+ Var *varPtr2;
+ char *pattern = NULL;
+ char *name;
+ Tcl_Obj *namePtr, *valuePtr, *nameLstPtr, *tmpResPtr, **namePtrPtr;
+ int i, count;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "arrayName ?pattern?");
+ return TCL_ERROR;
+ }
+ if (notArray) {
+ return TCL_OK;
+ }
+ if (objc == 4) {
+ pattern = TclGetString(objv[3]);
+ }
+
+ /*
+ * Store the array names in a new object.
+ */
+
+ TclNewObj(nameLstPtr);
+ Tcl_IncrRefCount(nameLstPtr);
+ if ((pattern != NULL) && TclMatchIsTrivial(pattern)) {
+ varPtr2 = VarHashFindVar(varPtr->value.tablePtr, objv[3]);
+ if (varPtr2 == NULL) {
+ goto searchDone;
}
- if (varPtr->searchPtr == searchPtr) {
- varPtr->searchPtr = searchPtr->nextPtr;
- } else {
- for (prevPtr = varPtr->searchPtr; ;
- prevPtr = prevPtr->nextPtr) {
- if (prevPtr->nextPtr == searchPtr) {
- prevPtr->nextPtr = searchPtr->nextPtr;
- break;
- }
- }
+ if (TclIsVarUndefined(varPtr2)) {
+ goto searchDone;
}
- ckfree((char *) searchPtr);
- break;
- }
- case ARRAY_EXISTS: {
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "arrayName");
- return TCL_ERROR;
+ result = Tcl_ListObjAppendElement(interp, nameLstPtr,
+ VarHashGetKey(varPtr2));
+ if (result != TCL_OK) {
+ TclDecrRefCount(nameLstPtr);
+ return result;
}
- Tcl_SetIntObj(resultPtr, !notArray);
- break;
+ goto searchDone;
}
- case ARRAY_GET: {
- Tcl_HashSearch search;
- Var *varPtr2;
- char *pattern = NULL;
- char *name;
- Tcl_Obj *namePtr, *valuePtr, *nameLstPtr, *tmpResPtr, **namePtrPtr;
- int i, count;
-
- if ((objc != 3) && (objc != 4)) {
- Tcl_WrongNumArgs(interp, 2, objv, "arrayName ?pattern?");
- return TCL_ERROR;
- }
- if (notArray) {
- return TCL_OK;
+ for (varPtr2 = VarHashFirstVar(varPtr->value.tablePtr, &search);
+ varPtr2; varPtr2 = VarHashNextVar(&search)) {
+ if (TclIsVarUndefined(varPtr2)) {
+ continue;
}
- if (objc == 4) {
- pattern = TclGetString(objv[3]);
+ namePtr = VarHashGetKey(varPtr2);
+ name = TclGetString(namePtr);
+ if ((objc == 4) && !Tcl_StringMatch(name, pattern)) {
+ continue; /* Element name doesn't match pattern. */
}
- /*
- * Store the array names in a new object.
- */
+ result = Tcl_ListObjAppendElement(interp, nameLstPtr, namePtr);
+ if (result != TCL_OK) {
+ TclDecrRefCount(nameLstPtr);
+ return result;
+ }
+ }
- nameLstPtr = Tcl_NewObj();
- Tcl_IncrRefCount(nameLstPtr);
+ searchDone:
+ /*
+ * Make sure the Var structure of the array is not removed by a trace
+ * while we're working.
+ */
- for (hPtr = Tcl_FirstHashEntry(varPtr->value.tablePtr, &search);
- hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
- varPtr2 = (Var *) Tcl_GetHashValue(hPtr);
- if (TclIsVarUndefined(varPtr2)) {
- continue;
- }
- name = Tcl_GetHashKey(varPtr->value.tablePtr, hPtr);
- if ((objc == 4) && !Tcl_StringMatch(name, pattern)) {
- continue; /* element name doesn't match pattern */
- }
-
- namePtr = Tcl_NewStringObj(name, -1);
- result = Tcl_ListObjAppendElement(interp, nameLstPtr,
- namePtr);
- if (result != TCL_OK) {
- Tcl_DecrRefCount(namePtr); /* free unneeded name obj */
- Tcl_DecrRefCount(nameLstPtr);
- return result;
- }
- }
+ if (TclIsVarInHash(varPtr)) {
+ VarHashRefCount(varPtr)++;
+ }
- /*
- * Make sure the Var structure of the array is not removed by
- * a trace while we're working.
- */
+ /*
+ * Get the array values corresponding to each element name.
+ */
- varPtr->refCount++;
+ TclNewObj(tmpResPtr);
+ result = Tcl_ListObjGetElements(interp, nameLstPtr, &count,
+ &namePtrPtr);
+ if (result != TCL_OK) {
+ goto errorInArrayGet;
+ }
- /*
- * Get the array values corresponding to each element name
- */
+ for (i=0 ; i<count ; i++) {
+ namePtr = *namePtrPtr++;
+ valuePtr = Tcl_ObjGetVar2(interp, objv[2], namePtr,
+ TCL_LEAVE_ERR_MSG);
+ if (valuePtr == NULL) {
+ /*
+ * Some trace played a trick on us; we need to diagnose to
+ * adapt our behaviour: was the array element unset, or did
+ * the modification modify the complete array?
+ */
- tmpResPtr = Tcl_NewObj();
- result = Tcl_ListObjGetElements(interp, nameLstPtr,
- &count, &namePtrPtr);
- if (result != TCL_OK) {
- goto errorInArrayGet;
- }
-
- for (i = 0; i < count; i++) {
- namePtr = *namePtrPtr++;
- valuePtr = Tcl_ObjGetVar2(interp, objv[2], namePtr,
- TCL_LEAVE_ERR_MSG);
- if (valuePtr == NULL) {
+ if (TclIsVarArray(varPtr)) {
/*
- * Some trace played a trick on us; we need to diagnose to
- * adapt our behaviour: was the array element unset, or did
- * the modification modify the complete array?
+ * The array itself looks OK, the variable was undefined:
+ * forget it.
*/
- if (TclIsVarArray(varPtr) && !TclIsVarUndefined(varPtr)) {
- /*
- * The array itself looks OK, the variable was
- * undefined: forget it.
- */
-
- continue;
- } else {
- result = TCL_ERROR;
- goto errorInArrayGet;
- }
- }
- result = Tcl_ListObjAppendElement(interp, tmpResPtr, namePtr);
- if (result != TCL_OK) {
- goto errorInArrayGet;
- }
- result = Tcl_ListObjAppendElement(interp, tmpResPtr, valuePtr);
- if (result != TCL_OK) {
+ continue;
+ } else {
+ result = TCL_ERROR;
goto errorInArrayGet;
}
}
- varPtr->refCount--;
- Tcl_SetObjResult(interp, tmpResPtr);
- Tcl_DecrRefCount(nameLstPtr);
- break;
+ result = Tcl_DictObjPut(interp, tmpResPtr, namePtr, valuePtr);
+ if (result != TCL_OK) {
+ goto errorInArrayGet;
+ }
+ }
+ if (TclIsVarInHash(varPtr)) {
+ VarHashRefCount(varPtr)--;
+ }
+ Tcl_SetObjResult(interp, tmpResPtr);
+ TclDecrRefCount(nameLstPtr);
+ break;
- errorInArrayGet:
- varPtr->refCount--;
- Tcl_DecrRefCount(nameLstPtr);
- Tcl_DecrRefCount(tmpResPtr); /* free unneeded temp result obj */
- return result;
+ errorInArrayGet:
+ if (TclIsVarInHash(varPtr)) {
+ VarHashRefCount(varPtr)--;
}
- case ARRAY_NAMES: {
- Tcl_HashSearch search;
- Var *varPtr2;
- char *pattern = NULL;
- char *name;
- Tcl_Obj *namePtr;
- int mode, matched = 0;
- static CONST char *options[] = {
- "-exact", "-glob", "-regexp", (char *) NULL
- };
- enum options { OPT_EXACT, OPT_GLOB, OPT_REGEXP };
-
- mode = OPT_GLOB;
-
- if ((objc < 3) || (objc > 5)) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "arrayName ?mode? ?pattern?");
+ TclDecrRefCount(nameLstPtr);
+ TclDecrRefCount(tmpResPtr); /* Free unneeded temp result. */
+ return result;
+ }
+ case ARRAY_NAMES: {
+ Tcl_HashSearch search;
+ Var *varPtr2;
+ char *pattern;
+ char *name;
+ Tcl_Obj *namePtr, *resultPtr, *patternPtr;
+ int mode, matched = 0;
+ static const char *options[] = {
+ "-exact", "-glob", "-regexp", NULL
+ };
+ enum options { OPT_EXACT, OPT_GLOB, OPT_REGEXP };
+
+ mode = OPT_GLOB;
+
+ if ((objc < 3) || (objc > 5)) {
+ Tcl_WrongNumArgs(interp, 2,objv, "arrayName ?mode? ?pattern?");
+ return TCL_ERROR;
+ }
+ if (notArray) {
+ return TCL_OK;
+ }
+ if (objc == 4) {
+ patternPtr = objv[3];
+ pattern = TclGetString(patternPtr);
+ } else if (objc == 5) {
+ patternPtr = objv[4];
+ pattern = TclGetString(patternPtr);
+ if (Tcl_GetIndexFromObj(interp, objv[3], options, "option", 0,
+ &mode) != TCL_OK) {
return TCL_ERROR;
}
- if (notArray) {
- return TCL_OK;
- }
- if (objc == 4) {
- pattern = Tcl_GetString(objv[3]);
- } else if (objc == 5) {
- pattern = Tcl_GetString(objv[4]);
- if (Tcl_GetIndexFromObj(interp, objv[3], options, "option",
- 0, &mode) != TCL_OK) {
- return TCL_ERROR;
- }
- }
- for (hPtr = Tcl_FirstHashEntry(varPtr->value.tablePtr, &search);
- hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
- varPtr2 = (Var *) Tcl_GetHashValue(hPtr);
- if (TclIsVarUndefined(varPtr2)) {
- continue;
- }
- name = Tcl_GetHashKey(varPtr->value.tablePtr, hPtr);
- if (objc > 3) {
- switch ((enum options) mode) {
- case OPT_EXACT:
- matched = (strcmp(name, pattern) == 0);
- break;
- case OPT_GLOB:
- matched = Tcl_StringMatch(name, pattern);
- break;
- case OPT_REGEXP:
- matched = Tcl_RegExpMatch(interp, name,
- pattern);
- if (matched < 0) {
- return TCL_ERROR;
- }
- break;
- }
- if (matched == 0) {
- continue;
- }
- }
-
- namePtr = Tcl_NewStringObj(name, -1);
- result = Tcl_ListObjAppendElement(interp, resultPtr, namePtr);
+ } else {
+ patternPtr = NULL;
+ pattern = NULL;
+ }
+ TclNewObj(resultPtr);
+ if (((enum options) mode)==OPT_GLOB && pattern!=NULL &&
+ TclMatchIsTrivial(pattern)) {
+ varPtr2 = VarHashFindVar(varPtr->value.tablePtr, patternPtr);
+ if ((varPtr2 != NULL) && !TclIsVarUndefined(varPtr2)) {
+ result = Tcl_ListObjAppendElement(interp, resultPtr,
+ VarHashGetKey(varPtr2));
if (result != TCL_OK) {
- Tcl_DecrRefCount(namePtr); /* free unneeded name obj */
+ TclDecrRefCount(resultPtr);
return result;
}
}
- break;
+ Tcl_SetObjResult(interp, resultPtr);
+ return TCL_OK;
}
- case ARRAY_NEXTELEMENT: {
- ArraySearch *searchPtr;
- Tcl_HashEntry *hPtr;
-
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "arrayName searchId");
- return TCL_ERROR;
- }
- if (notArray) {
- goto error;
- }
- searchPtr = ParseSearchId(interp, varPtr, varName, objv[3]);
- if (searchPtr == NULL) {
- return TCL_ERROR;
+ for (varPtr2=VarHashFirstVar(varPtr->value.tablePtr, &search);
+ varPtr2!=NULL ; varPtr2=VarHashNextVar(&search)) {
+ if (TclIsVarUndefined(varPtr2)) {
+ continue;
}
- while (1) {
- Var *varPtr2;
-
- hPtr = searchPtr->nextEntry;
- if (hPtr == NULL) {
- hPtr = Tcl_NextHashEntry(&searchPtr->search);
- if (hPtr == NULL) {
- return TCL_OK;
+ namePtr = VarHashGetKey(varPtr2);
+ name = TclGetString(namePtr);
+ if (objc > 3) {
+ switch ((enum options) mode) {
+ case OPT_EXACT:
+ matched = (strcmp(name, pattern) == 0);
+ break;
+ case OPT_GLOB:
+ matched = Tcl_StringMatch(name, pattern);
+ break;
+ case OPT_REGEXP:
+ matched = Tcl_RegExpMatch(interp, name, pattern);
+ if (matched < 0) {
+ TclDecrRefCount(resultPtr);
+ return TCL_ERROR;
}
- } else {
- searchPtr->nextEntry = NULL;
- }
- varPtr2 = (Var *) Tcl_GetHashValue(hPtr);
- if (!TclIsVarUndefined(varPtr2)) {
break;
}
+ if (matched == 0) {
+ continue;
+ }
}
- Tcl_SetStringObj(resultPtr,
- Tcl_GetHashKey(varPtr->value.tablePtr, hPtr), -1);
- break;
- }
- case ARRAY_SET: {
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "arrayName list");
- return TCL_ERROR;
+
+ result = Tcl_ListObjAppendElement(interp, resultPtr, namePtr);
+ if (result != TCL_OK) {
+ TclDecrRefCount(namePtr); /* Free unneeded name obj. */
+ return result;
}
- return(TclArraySet(interp, objv[2], objv[3]));
}
- case ARRAY_SIZE: {
+ Tcl_SetObjResult(interp, resultPtr);
+ break;
+ }
+ case ARRAY_SET:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "arrayName list");
+ return TCL_ERROR;
+ }
+ return TclArraySet(interp, objv[2], objv[3]);
+ case ARRAY_UNSET:
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "arrayName ?pattern?");
+ return TCL_ERROR;
+ }
+ if (notArray) {
+ return TCL_OK;
+ }
+ if (objc == 3) {
+ /*
+ * When no pattern is given, just unset the whole array.
+ */
+
+ return TclObjUnsetVar2(interp, varNamePtr, NULL, 0);
+ } else {
Tcl_HashSearch search;
- Var *varPtr2;
- int size;
+ Var *varPtr2, *protectedVarPtr;
+ const char *pattern = TclGetString(objv[3]);
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "arrayName");
- return TCL_ERROR;
- }
- size = 0;
- if (!notArray) {
- for (hPtr = Tcl_FirstHashEntry(varPtr->value.tablePtr,
- &search);
- hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
- varPtr2 = (Var *) Tcl_GetHashValue(hPtr);
- if (TclIsVarUndefined(varPtr2)) {
- continue;
- }
- size++;
- }
- }
- Tcl_SetIntObj(resultPtr, size);
- break;
- }
- case ARRAY_STARTSEARCH: {
- ArraySearch *searchPtr;
+ /*
+ * With a trivial pattern, we can just unset.
+ */
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "arrayName");
- return TCL_ERROR;
- }
- if (notArray) {
- goto error;
+ if (TclMatchIsTrivial(pattern)) {
+ varPtr2 = VarHashFindVar(varPtr->value.tablePtr, objv[3]);
+ if (varPtr2 != NULL && !TclIsVarUndefined(varPtr2)) {
+ return TclObjUnsetVar2(interp, varNamePtr, objv[3], 0);
+ }
+ return TCL_OK;
}
- searchPtr = (ArraySearch *) ckalloc(sizeof(ArraySearch));
- if (varPtr->searchPtr == NULL) {
- searchPtr->id = 1;
- Tcl_AppendStringsToObj(resultPtr, "s-1-", varName,
- (char *) NULL);
- } else {
- char string[TCL_INTEGER_SPACE];
- searchPtr->id = varPtr->searchPtr->id + 1;
- TclFormatInt(string, searchPtr->id);
- Tcl_AppendStringsToObj(resultPtr, "s-", string, "-", varName,
- (char *) NULL);
- }
- searchPtr->varPtr = varPtr;
- searchPtr->nextEntry = Tcl_FirstHashEntry(varPtr->value.tablePtr,
- &searchPtr->search);
- searchPtr->nextPtr = varPtr->searchPtr;
- varPtr->searchPtr = searchPtr;
- break;
- }
+ /*
+ * Non-trivial case (well, deeply tricky really). We peek inside
+ * the hash iterator in order to allow us to guarantee that the
+ * following element in the array will not be scrubbed until we
+ * have dealt with it. This stops the overall iterator from ending
+ * up pointing into deallocated memory. [Bug 2939073]
+ */
- case ARRAY_STATISTICS: {
- CONST char *stats;
+ protectedVarPtr = NULL;
+ for (varPtr2=VarHashFirstVar(varPtr->value.tablePtr, &search);
+ varPtr2!=NULL ; varPtr2=VarHashNextVar(&search)) {
+ /*
+ * Drop the extra ref immediately. We don't need to free it at
+ * this point though; we'll be unsetting it if necessary soon.
+ */
- if (notArray) {
- goto error;
- }
+ if (varPtr2 == protectedVarPtr) {
+ VarHashRefCount(varPtr2)--;
+ }
- stats = Tcl_HashStats(varPtr->value.tablePtr);
- if (stats != NULL) {
- Tcl_SetStringObj(Tcl_GetObjResult(interp), stats, -1);
- ckfree((void *)stats);
- } else {
- Tcl_SetResult(interp, "error reading array statistics",
- TCL_STATIC);
- return TCL_ERROR;
- }
- break;
- }
-
- case ARRAY_UNSET: {
- Tcl_HashSearch search;
- Var *varPtr2;
- char *pattern = NULL;
- char *name;
-
- if ((objc != 3) && (objc != 4)) {
- Tcl_WrongNumArgs(interp, 2, objv, "arrayName ?pattern?");
- return TCL_ERROR;
- }
- if (notArray) {
- return TCL_OK;
- }
- if (objc == 3) {
/*
- * When no pattern is given, just unset the whole array
+ * Guard the next item in the search chain by incrementing its
+ * refcount. This guarantees that the hash table iterator
+ * won't be dangling on the next time through the loop.
*/
- if (TclObjUnsetVar2(interp, varNamePtr, NULL, 0)
- != TCL_OK) {
- return TCL_ERROR;
+
+ if (search.nextEntryPtr != NULL) {
+ protectedVarPtr = VarHashGetValue(search.nextEntryPtr);
+ VarHashRefCount(protectedVarPtr)++;
+ } else {
+ protectedVarPtr = NULL;
}
- } else {
- pattern = Tcl_GetString(objv[3]);
- for (hPtr = Tcl_FirstHashEntry(varPtr->value.tablePtr,
- &search);
- hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
- varPtr2 = (Var *) Tcl_GetHashValue(hPtr);
- if (TclIsVarUndefined(varPtr2)) {
- continue;
- }
- name = Tcl_GetHashKey(varPtr->value.tablePtr, hPtr);
- if (Tcl_StringMatch(name, pattern) &&
- (TclObjUnsetVar2(interp, varNamePtr, name, 0)
- != TCL_OK)) {
+
+ if (!TclIsVarUndefined(varPtr2)) {
+ Tcl_Obj *namePtr = VarHashGetKey(varPtr2);
+
+ if (Tcl_StringMatch(TclGetString(namePtr), pattern)
+ && TclObjUnsetVar2(interp, varNamePtr, namePtr,
+ 0) != TCL_OK) {
+ /*
+ * If we incremented a refcount, we must decrement it
+ * here as we will not be coming back properly due to
+ * the error.
+ */
+
+ if (protectedVarPtr) {
+ VarHashRefCount(protectedVarPtr)--;
+ CleanupVar(protectedVarPtr, varPtr);
+ }
return TCL_ERROR;
}
+ } else {
+ CleanupVar(varPtr2, varPtr);
}
}
break;
}
+
+ case ARRAY_SIZE: {
+ Tcl_HashSearch search;
+ Var *varPtr2;
+ int size;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "arrayName");
+ return TCL_ERROR;
+ }
+ size = 0;
+
+ /*
+ * Must iterate in order to get chance to check for present but
+ * "undefined" entries.
+ */
+
+ if (!notArray) {
+ for (varPtr2=VarHashFirstVar(varPtr->value.tablePtr, &search);
+ varPtr2!=NULL ; varPtr2=VarHashNextVar(&search)) {
+ if (TclIsVarUndefined(varPtr2)) {
+ continue;
+ }
+ size++;
+ }
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(size));
+ break;
+ }
+
+ case ARRAY_STATISTICS: {
+ const char *stats;
+
+ if (notArray) {
+ goto error;
+ }
+
+ stats = Tcl_HashStats((Tcl_HashTable *) varPtr->value.tablePtr);
+ if (stats != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(stats, -1));
+ ckfree((void *)stats);
+ } else {
+ Tcl_SetResult(interp,"error reading array statistics",TCL_STATIC);
+ return TCL_ERROR;
+ }
+ break;
+ }
}
return TCL_OK;
- error:
- Tcl_AppendStringsToObj(resultPtr, "\"", varName, "\" isn't an array",
- (char *) NULL);
+ error:
+ Tcl_AppendResult(interp, "\"", TclGetString(varNamePtr),
+ "\" isn't an array", NULL);
return TCL_ERROR;
}
@@ -3411,9 +3309,9 @@ Tcl_ArrayObjCmd(dummy, interp, objc, objv)
*
* TclArraySet --
*
- * Set the elements of an array. If there are no elements to
- * set, create an empty array. This routine is used by the
- * Tcl_ArrayObjCmd and by the TclSetupEnv routine.
+ * Set the elements of an array. If there are no elements to set, create
+ * an empty array. This routine is used by the Tcl_ArrayObjCmd and by the
+ * TclSetupEnv routine.
*
* Results:
* A standard Tcl result object.
@@ -3425,104 +3323,149 @@ Tcl_ArrayObjCmd(dummy, interp, objc, objv)
*/
int
-TclArraySet(interp, arrayNameObj, arrayElemObj)
- Tcl_Interp *interp; /* Current interpreter. */
- Tcl_Obj *arrayNameObj; /* The array name. */
- Tcl_Obj *arrayElemObj; /* The array elements list. If this is
+TclArraySet(
+ Tcl_Interp *interp, /* Current interpreter. */
+ Tcl_Obj *arrayNameObj, /* The array name. */
+ Tcl_Obj *arrayElemObj) /* The array elements list or dict. If this is
* NULL, create an empty array. */
{
Var *varPtr, *arrayPtr;
- Tcl_Obj **elemPtrs;
- int result, elemLen, i, nameLen;
- char *varName, *p;
-
- varName = Tcl_GetStringFromObj(arrayNameObj, &nameLen);
- p = varName + nameLen - 1;
- if (*p == ')') {
- while (--p >= varName) {
- if (*p == '(') {
- VarErrMsg(interp, varName, NULL, "set", needArray);
- return TCL_ERROR;
- }
- }
- }
+ int result, i;
- varPtr = TclObjLookupVar(interp, arrayNameObj, NULL,
+ varPtr = TclObjLookupVarEx(interp, arrayNameObj, NULL,
/*flags*/ TCL_LEAVE_ERR_MSG, /*msg*/ "set", /*createPart1*/ 1,
- /*createPart2*/ 0, &arrayPtr);
+ /*createPart2*/ 1, &arrayPtr);
if (varPtr == NULL) {
return TCL_ERROR;
}
+ if (arrayPtr) {
+ CleanupVar(varPtr, arrayPtr);
+ TclObjVarErrMsg(interp, arrayNameObj, NULL, "set", needArray, -1);
+ return TCL_ERROR;
+ }
+
+ if (arrayElemObj == NULL) {
+ goto ensureArray;
+ }
+
+ /*
+ * Install the contents of the dictionary or list into the array.
+ */
+
+ if (arrayElemObj->typePtr == &tclDictType) {
+ Tcl_Obj *keyPtr, *valuePtr;
+ Tcl_DictSearch search;
+ int done;
+
+ if (Tcl_DictObjSize(interp, arrayElemObj, &done) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (done == 0) {
+ /*
+ * Empty, so we'll just force the array to be properly existing
+ * instead.
+ */
+
+ goto ensureArray;
+ }
+
+ /*
+ * Don't need to look at result of Tcl_DictObjFirst as we've just
+ * successfully used a dictionary operation on the same object.
+ */
+
+ for (Tcl_DictObjFirst(interp, arrayElemObj, &search,
+ &keyPtr, &valuePtr, &done) ; !done ;
+ Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done)) {
+ /*
+ * At this point, it would be nice if the key was directly usable
+ * by the array. This isn't the case though.
+ */
+
+ Var *elemVarPtr = TclLookupArrayElement(interp, arrayNameObj,
+ keyPtr, TCL_LEAVE_ERR_MSG, "set", 1, 1, varPtr, -1);
+
+ if ((elemVarPtr == NULL) ||
+ (TclPtrSetVar(interp, elemVarPtr, varPtr, arrayNameObj,
+ keyPtr, valuePtr, TCL_LEAVE_ERR_MSG, -1) == NULL)) {
+ Tcl_DictObjDone(&search);
+ return TCL_ERROR;
+ }
+ }
+ return TCL_OK;
+ } else {
+ /*
+ * Not a dictionary, so assume (and convert to, for backward-
+ * -compatability reasons) a list.
+ */
- if (arrayElemObj != NULL) {
- result = Tcl_ListObjGetElements(interp, arrayElemObj,
+ int elemLen;
+ Tcl_Obj **elemPtrs, *copyListObj;
+
+ result = TclListObjGetElements(interp, arrayElemObj,
&elemLen, &elemPtrs);
if (result != TCL_OK) {
return result;
}
if (elemLen & 1) {
- Tcl_ResetResult(interp);
- Tcl_AppendToObj(Tcl_GetObjResult(interp),
- "list must have an even number of elements", -1);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "list must have an even number of elements", -1));
return TCL_ERROR;
}
- if (elemLen > 0) {
- /*
- * We needn't worry about traces invalidating arrayPtr:
- * should that be the case, TclPtrSetVar will return NULL
- * so that we break out of the loop and return an error.
- */
+ if (elemLen == 0) {
+ goto ensureArray;
+ }
- for (i = 0; i < elemLen; i += 2) {
- char *part2 = TclGetString(elemPtrs[i]);
- Var *elemVarPtr = TclLookupArrayElement(interp, varName,
- part2, TCL_LEAVE_ERR_MSG, "set", 1, 1, varPtr);
- if ((elemVarPtr == NULL) ||
- (TclPtrSetVar(interp, elemVarPtr, varPtr, varName,
- part2, elemPtrs[i+1], TCL_LEAVE_ERR_MSG) == NULL)) {
- result = TCL_ERROR;
- break;
- }
+ /*
+ * We needn't worry about traces invalidating arrayPtr: should that be
+ * the case, TclPtrSetVar will return NULL so that we break out of the
+ * loop and return an error.
+ */
- /*
- * The TclPtrSetVar call might have shimmered
- * arrayElemObj to another type, so re-fetch
- * the pointers for safety.
- */
- Tcl_ListObjGetElements(NULL, arrayElemObj,
- &elemLen, &elemPtrs);
+ copyListObj = TclListObjCopy(NULL, arrayElemObj);
+ for (i=0 ; i<elemLen ; i+=2) {
+ Var *elemVarPtr = TclLookupArrayElement(interp, arrayNameObj,
+ elemPtrs[i], TCL_LEAVE_ERR_MSG, "set", 1, 1, varPtr, -1);
+
+ if ((elemVarPtr == NULL) ||
+ (TclPtrSetVar(interp, elemVarPtr, varPtr, arrayNameObj,
+ elemPtrs[i],elemPtrs[i+1],TCL_LEAVE_ERR_MSG,-1) == NULL)){
+ result = TCL_ERROR;
+ break;
}
- return result;
}
+ Tcl_DecrRefCount(copyListObj);
+ return result;
}
-
+
/*
- * The list is empty make sure we have an array, or create
- * one if necessary.
+ * The list is empty make sure we have an array, or create one if
+ * necessary.
*/
-
+
+ ensureArray:
if (varPtr != NULL) {
- if (!TclIsVarUndefined(varPtr) && TclIsVarArray(varPtr)) {
+ if (TclIsVarArray(varPtr)) {
/*
* Already an array, done.
*/
-
+
return TCL_OK;
}
if (TclIsVarArrayElement(varPtr) || !TclIsVarUndefined(varPtr)) {
/*
* Either an array element, or a scalar: lose!
*/
-
- VarErrMsg(interp, varName, (char *)NULL, "array set", needArray);
+
+ TclObjVarErrMsg(interp, arrayNameObj, NULL, "array set",
+ needArray, -1);
return TCL_ERROR;
}
}
TclSetVarArray(varPtr);
- TclClearVarUndefined(varPtr);
- varPtr->value.tablePtr =
- (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
- Tcl_InitHashTable(varPtr->value.tablePtr, TCL_STRING_KEYS);
+ varPtr->value.tablePtr = (TclVarHashTable *)
+ ckalloc(sizeof(TclVarHashTable));
+ TclInitVarHashTable(varPtr->value.tablePtr, TclGetVarNsPtr(varPtr));
return TCL_OK;
}
@@ -3531,12 +3474,12 @@ TclArraySet(interp, arrayNameObj, arrayElemObj)
*
* ObjMakeUpvar --
*
- * This procedure does all of the work of the "global" and "upvar"
+ * This function does all of the work of the "global" and "upvar"
* commands.
*
* Results:
- * A standard Tcl completion code. If an error occurs then an
- * error message is left in iPtr->result.
+ * A standard Tcl completion code. If an error occurs then an error
+ * message is left in iPtr->result.
*
* Side effects:
* The variable given by myName is linked to the variable in framePtr
@@ -3547,40 +3490,43 @@ TclArraySet(interp, arrayNameObj, arrayElemObj)
*/
static int
-ObjMakeUpvar(interp, framePtr, otherP1Ptr, otherP2, otherFlags, myName, myFlags, index)
- Tcl_Interp *interp; /* Interpreter containing variables. Used
- * for error messages, too. */
- CallFrame *framePtr; /* Call frame containing "other" variable.
+ObjMakeUpvar(
+ Tcl_Interp *interp, /* Interpreter containing variables. Used for
+ * error messages, too. */
+ CallFrame *framePtr, /* Call frame containing "other" variable.
* NULL means use global :: context. */
- Tcl_Obj *otherP1Ptr;
- CONST char *otherP2; /* Two-part name of variable in framePtr. */
- CONST int otherFlags; /* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY:
+ Tcl_Obj *otherP1Ptr,
+ const char *otherP2, /* Two-part name of variable in framePtr. */
+ const int otherFlags, /* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY:
* indicates scope of "other" variable. */
- CONST char *myName; /* Name of variable which will refer to
+ Tcl_Obj *myNamePtr, /* Name of variable which will refer to
* otherP1/otherP2. Must be a scalar. */
- int myFlags; /* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY:
+ int myFlags, /* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY:
* indicates scope of myName. */
- int index; /* If the variable to be linked is an indexed
- * scalar, this is its index. Otherwise, -1. */
+ int index) /* If the variable to be linked is an indexed
+ * scalar, this is its index. Otherwise, -1 */
{
Interp *iPtr = (Interp *) interp;
- Var *otherPtr, *varPtr, *arrayPtr;
+ Var *otherPtr, *arrayPtr;
CallFrame *varFramePtr;
- CONST char *errMsg;
/*
- * Find "other" in "framePtr". If not looking up other in just the
- * current namespace, temporarily replace the current var frame
- * pointer in the interpreter in order to use TclObjLookupVar.
+ * Find "other" in "framePtr". If not looking up other in just the current
+ * namespace, temporarily replace the current var frame pointer in the
+ * interpreter in order to use TclObjLookupVar.
*/
+ if (framePtr == NULL) {
+ framePtr = iPtr->rootFramePtr;
+ }
+
varFramePtr = iPtr->varFramePtr;
if (!(otherFlags & TCL_NAMESPACE_ONLY)) {
iPtr->varFramePtr = framePtr;
}
otherPtr = TclObjLookupVar(interp, otherP1Ptr, otherP2,
(otherFlags | TCL_LEAVE_ERR_MSG), "access",
- /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
+ /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
if (!(otherFlags & TCL_NAMESPACE_ONLY)) {
iPtr->varFramePtr = varFramePtr;
}
@@ -3588,63 +3534,161 @@ ObjMakeUpvar(interp, framePtr, otherP1Ptr, otherP2, otherFlags, myName, myFlags,
return TCL_ERROR;
}
+ /*
+ * Check that we are not trying to create a namespace var linked to a
+ * local variable in a procedure. If we allowed this, the local
+ * variable in the shorter-lived procedure frame could go away leaving
+ * the namespace var's reference invalid.
+ */
+
+ if (index < 0) {
+ if (!(arrayPtr != NULL
+ ? (TclIsVarInHash(arrayPtr) && TclGetVarNsPtr(arrayPtr))
+ : (TclIsVarInHash(otherPtr) && TclGetVarNsPtr(otherPtr)))
+ && ((myFlags & (TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY))
+ || (varFramePtr == NULL)
+ || !HasLocalVars(varFramePtr)
+ || (strstr(TclGetString(myNamePtr), "::") != NULL))) {
+ Tcl_AppendResult((Tcl_Interp *) iPtr, "bad variable name \"",
+ TclGetString(myNamePtr), "\": upvar won't create "
+ "namespace variable that refers to procedure variable",
+ NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ return TclPtrObjMakeUpvar(interp, otherPtr, myNamePtr, myFlags, index);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclPtrMakeUpvar --
+ *
+ * This procedure does all of the work of the "global" and "upvar"
+ * commands.
+ *
+ * Results:
+ * A standard Tcl completion code. If an error occurs then an error
+ * message is left in iPtr->result.
+ *
+ * Side effects:
+ * The variable given by myName is linked to the variable in framePtr
+ * given by otherP1 and otherP2, so that references to myName are
+ * redirected to the other variable like a symbolic link.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclPtrMakeUpvar(
+ Tcl_Interp *interp, /* Interpreter containing variables. Used for
+ * error messages, too. */
+ Var *otherPtr, /* Pointer to the variable being linked-to. */
+ const char *myName, /* Name of variable which will refer to
+ * otherP1/otherP2. Must be a scalar. */
+ int myFlags, /* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY:
+ * indicates scope of myName. */
+ int index) /* If the variable to be linked is an indexed
+ * scalar, this is its index. Otherwise, -1 */
+{
+ Tcl_Obj *myNamePtr;
+ int result;
+
+ if (myName) {
+ myNamePtr = Tcl_NewStringObj(myName, -1);
+ Tcl_IncrRefCount(myNamePtr);
+ } else {
+ myNamePtr = NULL;
+ }
+ result = TclPtrObjMakeUpvar(interp, otherPtr, myNamePtr, myFlags, index);
+ if (myNamePtr) {
+ Tcl_DecrRefCount(myNamePtr);
+ }
+ return result;
+}
+
+int
+TclPtrObjMakeUpvar(
+ Tcl_Interp *interp, /* Interpreter containing variables. Used for
+ * error messages, too. */
+ Var *otherPtr, /* Pointer to the variable being linked-to. */
+ Tcl_Obj *myNamePtr, /* Name of variable which will refer to
+ * otherP1/otherP2. Must be a scalar. */
+ int myFlags, /* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY:
+ * indicates scope of myName. */
+ int index) /* If the variable to be linked is an indexed
+ * scalar, this is its index. Otherwise, -1 */
+{
+ Interp *iPtr = (Interp *) interp;
+ CallFrame *varFramePtr = iPtr->varFramePtr;
+ const char *errMsg, *p, *myName;
+ Var *varPtr;
+
if (index >= 0) {
- if (!varFramePtr->isProcCallFrame) {
- panic("ObjMakeUpvar called with an index outside from a proc.\n");
+ if (!HasLocalVars(varFramePtr)) {
+ Tcl_Panic("ObjMakeUpvar called with an index outside from a proc");
}
- varPtr = &(varFramePtr->compiledLocals[index]);
+ varPtr = (Var *) &(varFramePtr->compiledLocals[index]);
+ myNamePtr = localName(iPtr->varFramePtr, index);
+ myName = myNamePtr? TclGetString(myNamePtr) : NULL;
} else {
/*
- * Check that we are not trying to create a namespace var linked to
- * a local variable in a procedure. If we allowed this, the local
- * variable in the shorter-lived procedure frame could go away
- * leaving the namespace var's reference invalid.
+ * Do not permit the new variable to look like an array reference, as
+ * it will not be reachable in that case [Bug 600812, TIP 184]. The
+ * "definition" of what "looks like an array reference" is consistent
+ * (and must remain consistent) with the code in TclObjLookupVar().
*/
-
- if (((otherP2 ? arrayPtr->nsPtr : otherPtr->nsPtr) == NULL)
- && ((myFlags & (TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY))
- || (varFramePtr == NULL)
- || !varFramePtr->isProcCallFrame
- || (strstr(myName, "::") != NULL))) {
- Tcl_AppendResult((Tcl_Interp *) iPtr, "bad variable name \"",
- myName, "\": upvar won't create namespace variable that ",
- "refers to procedure variable", (char *) NULL);
- return TCL_ERROR;
+
+ myName = TclGetString(myNamePtr);
+ p = strstr(myName, "(");
+ if (p != NULL) {
+ p += strlen(p)-1;
+ if (*p == ')') {
+ /*
+ * myName looks like an array reference.
+ */
+
+ Tcl_AppendResult((Tcl_Interp *) iPtr, "bad variable name \"",
+ myName, "\": upvar won't create a scalar variable "
+ "that looks like an array element", NULL);
+ return TCL_ERROR;
+ }
}
-
+
/*
* Lookup and eventually create the new variable. Set the flag bit
- * LOOKUP_FOR_UPVAR to indicate the special resolution rules for
- * upvar purposes:
+ * AVOID_RESOLVERS to indicate the special resolution rules for upvar
+ * purposes:
* - Bug #696893 - variable is either proc-local or in the current
- * namespace; never follow the second (global) resolution path
- * - Bug #631741 - do not use special namespace or interp resolvers
+ * namespace; never follow the second (global) resolution path.
+ * - Bug #631741 - do not use special namespace or interp resolvers.
*/
-
- varPtr = TclLookupSimpleVar(interp, myName, (myFlags | LOOKUP_FOR_UPVAR),
- /* create */ 1, &errMsg, &index);
+
+ varPtr = TclLookupSimpleVar(interp, myNamePtr,
+ myFlags|AVOID_RESOLVERS, /* create */ 1, &errMsg, &index);
if (varPtr == NULL) {
- VarErrMsg(interp, myName, NULL, "create", errMsg);
+ TclObjVarErrMsg(interp, myNamePtr, NULL, "create", errMsg, -1);
return TCL_ERROR;
}
}
if (varPtr == otherPtr) {
Tcl_SetResult((Tcl_Interp *) iPtr,
- "can't upvar from variable to itself", TCL_STATIC);
+ "can't upvar from variable to itself", TCL_STATIC);
return TCL_ERROR;
}
- if (varPtr->tracePtr != NULL) {
+ if (TclIsVarTraced(varPtr)) {
Tcl_AppendResult((Tcl_Interp *) iPtr, "variable \"", myName,
- "\" has traces: can't use for upvar", (char *) NULL);
+ "\" has traces: can't use for upvar", NULL);
return TCL_ERROR;
} else if (!TclIsVarUndefined(varPtr)) {
/*
* The variable already existed. Make sure this variable "varPtr"
- * isn't the same as "otherPtr" (avoid circular links). Also, if
- * it's not an upvar then it's an error. If it is an upvar, then
- * just disconnect it from the thing it currently refers to.
+ * isn't the same as "otherPtr" (avoid circular links). Also, if it's
+ * not an upvar then it's an error. If it is an upvar, then just
+ * disconnect it from the thing it currently refers to.
*/
if (TclIsVarLink(varPtr)) {
@@ -3652,20 +3696,23 @@ ObjMakeUpvar(interp, framePtr, otherP1Ptr, otherP2, otherFlags, myName, myFlags,
if (linkPtr == otherPtr) {
return TCL_OK;
}
- linkPtr->refCount--;
- if (TclIsVarUndefined(linkPtr)) {
- CleanupVar(linkPtr, (Var *) NULL);
+ if (TclIsVarInHash(linkPtr)) {
+ VarHashRefCount(linkPtr)--;
+ if (TclIsVarUndefined(linkPtr)) {
+ CleanupVar(linkPtr, NULL);
+ }
}
} else {
Tcl_AppendResult((Tcl_Interp *) iPtr, "variable \"", myName,
- "\" already exists", (char *) NULL);
+ "\" already exists", NULL);
return TCL_ERROR;
}
}
TclSetVarLink(varPtr);
- TclClearVarUndefined(varPtr);
varPtr->value.linkPtr = otherPtr;
- otherPtr->refCount++;
+ if (TclIsVarInHash(otherPtr)) {
+ VarHashRefCount(otherPtr)++;
+ }
return TCL_OK;
}
@@ -3674,33 +3721,32 @@ ObjMakeUpvar(interp, framePtr, otherP1Ptr, otherP2, otherFlags, myName, myFlags,
*
* Tcl_UpVar --
*
- * This procedure links one variable to another, just like
- * the "upvar" command.
+ * This function links one variable to another, just like the "upvar"
+ * command.
*
* Results:
- * A standard Tcl completion code. If an error occurs then
- * an error message is left in the interp's result.
+ * A standard Tcl completion code. If an error occurs then an error
+ * message is left in the interp's result.
*
* Side effects:
* The variable in frameName whose name is given by varName becomes
- * accessible under the name localName, so that references to
- * localName are redirected to the other variable like a symbolic
- * link.
+ * accessible under the name localName, so that references to localName
+ * are redirected to the other variable like a symbolic link.
*
*----------------------------------------------------------------------
*/
int
-Tcl_UpVar(interp, frameName, varName, localName, flags)
- Tcl_Interp *interp; /* Command interpreter in which varName is
- * to be looked up. */
- CONST char *frameName; /* Name of the frame containing the source
+Tcl_UpVar(
+ Tcl_Interp *interp, /* Command interpreter in which varName is to
+ * be looked up. */
+ const char *frameName, /* Name of the frame containing the source
* variable, such as "1" or "#0". */
- CONST char *varName; /* Name of a variable in interp to link to.
- * May be either a scalar name or an
- * element in an array. */
- CONST char *localName; /* Name of link variable. */
- int flags; /* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY:
+ const char *varName, /* Name of a variable in interp to link to.
+ * May be either a scalar name or an element
+ * in an array. */
+ const char *localName, /* Name of link variable. */
+ int flags) /* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY:
* indicates scope of localName. */
{
return Tcl_UpVar2(interp, frameName, varName, NULL, localName, flags);
@@ -3711,38 +3757,37 @@ Tcl_UpVar(interp, frameName, varName, localName, flags)
*
* Tcl_UpVar2 --
*
- * This procedure links one variable to another, just like
- * the "upvar" command.
+ * This function links one variable to another, just like the "upvar"
+ * command.
*
* Results:
- * A standard Tcl completion code. If an error occurs then
- * an error message is left in the interp's result.
+ * A standard Tcl completion code. If an error occurs then an error
+ * message is left in the interp's result.
*
* Side effects:
- * The variable in frameName whose name is given by part1 and
- * part2 becomes accessible under the name localName, so that
- * references to localName are redirected to the other variable
- * like a symbolic link.
+ * The variable in frameName whose name is given by part1 and part2
+ * becomes accessible under the name localName, so that references to
+ * localName are redirected to the other variable like a symbolic link.
*
*----------------------------------------------------------------------
*/
int
-Tcl_UpVar2(interp, frameName, part1, part2, localName, flags)
- Tcl_Interp *interp; /* Interpreter containing variables. Used
- * for error messages too. */
- CONST char *frameName; /* Name of the frame containing the source
+Tcl_UpVar2(
+ Tcl_Interp *interp, /* Interpreter containing variables. Used for
+ * error messages too. */
+ const char *frameName, /* Name of the frame containing the source
* variable, such as "1" or "#0". */
- CONST char *part1;
- CONST char *part2; /* Two parts of source variable name to
- * link to. */
- CONST char *localName; /* Name of link variable. */
- int flags; /* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY:
+ const char *part1,
+ const char *part2, /* Two parts of source variable name to link
+ * to. */
+ const char *localName, /* Name of link variable. */
+ int flags) /* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY:
* indicates scope of localName. */
{
int result;
CallFrame *framePtr;
- Tcl_Obj *part1Ptr;
+ Tcl_Obj *part1Ptr, *localNamePtr;
if (TclGetFrame(interp, frameName, &framePtr) == -1) {
return TCL_ERROR;
@@ -3750,10 +3795,13 @@ Tcl_UpVar2(interp, frameName, part1, part2, localName, flags)
part1Ptr = Tcl_NewStringObj(part1, -1);
Tcl_IncrRefCount(part1Ptr);
- result = ObjMakeUpvar(interp, framePtr, part1Ptr, part2, 0,
- localName, flags, -1);
- TclDecrRefCount(part1Ptr);
+ localNamePtr = Tcl_NewStringObj(localName, -1);
+ Tcl_IncrRefCount(localNamePtr);
+ result = ObjMakeUpvar(interp, framePtr, part1Ptr, part2, 0,
+ localNamePtr, flags, -1);
+ Tcl_DecrRefCount(part1Ptr);
+ Tcl_DecrRefCount(localNamePtr);
return result;
}
@@ -3762,50 +3810,59 @@ Tcl_UpVar2(interp, frameName, part1, part2, localName, flags)
*
* Tcl_GetVariableFullName --
*
- * Given a Tcl_Var token returned by Tcl_FindNamespaceVar, this
- * procedure appends to an object the namespace variable's full
- * name, qualified by a sequence of parent namespace names.
+ * Given a Tcl_Var token returned by Tcl_FindNamespaceVar, this function
+ * appends to an object the namespace variable's full name, qualified by
+ * a sequence of parent namespace names.
*
* Results:
- * None.
+ * None.
*
* Side effects:
- * The variable's fully-qualified name is appended to the string
+ * The variable's fully-qualified name is appended to the string
* representation of objPtr.
*
*----------------------------------------------------------------------
*/
void
-Tcl_GetVariableFullName(interp, variable, objPtr)
- Tcl_Interp *interp; /* Interpreter containing the variable. */
- Tcl_Var variable; /* Token for the variable returned by a
+Tcl_GetVariableFullName(
+ Tcl_Interp *interp, /* Interpreter containing the variable. */
+ Tcl_Var variable, /* Token for the variable returned by a
* previous call to Tcl_FindNamespaceVar. */
- Tcl_Obj *objPtr; /* Points to the object onto which the
+ Tcl_Obj *objPtr) /* Points to the object onto which the
* variable's full name is appended. */
{
Interp *iPtr = (Interp *) interp;
register Var *varPtr = (Var *) variable;
- char *name;
+ Tcl_Obj *namePtr;
+ Namespace *nsPtr;
/*
- * Add the full name of the containing namespace (if any), followed by
- * the "::" separator, then the variable name.
+ * Add the full name of the containing namespace (if any), followed by the
+ * "::" separator, then the variable name.
*/
- if (varPtr != NULL) {
+ if (varPtr) {
if (!TclIsVarArrayElement(varPtr)) {
- if (varPtr->nsPtr != NULL) {
- Tcl_AppendToObj(objPtr, varPtr->nsPtr->fullName, -1);
- if (varPtr->nsPtr != iPtr->globalNsPtr) {
+ nsPtr = TclGetVarNsPtr(varPtr);
+ if (nsPtr) {
+ Tcl_AppendToObj(objPtr, nsPtr->fullName, -1);
+ if (nsPtr != iPtr->globalNsPtr) {
Tcl_AppendToObj(objPtr, "::", 2);
}
}
- if (varPtr->name != NULL) {
- Tcl_AppendToObj(objPtr, varPtr->name, -1);
- } else if (varPtr->hPtr != NULL) {
- name = Tcl_GetHashKey(varPtr->hPtr->tablePtr, varPtr->hPtr);
- Tcl_AppendToObj(objPtr, name, -1);
+ if (TclIsVarInHash(varPtr)) {
+ if (!TclIsVarDeadHash(varPtr)) {
+ namePtr = VarHashGetKey(varPtr);
+ Tcl_AppendObjToObj(objPtr, namePtr);
+ }
+ } else if (iPtr->varFramePtr->procPtr) {
+ int index = varPtr - iPtr->varFramePtr->compiledLocals;
+
+ if (index < iPtr->varFramePtr->numCompiledLocals) {
+ namePtr = localName(iPtr->varFramePtr, index);
+ Tcl_AppendObjToObj(objPtr, namePtr);
+ }
}
}
}
@@ -3816,7 +3873,7 @@ Tcl_GetVariableFullName(interp, variable, objPtr)
*
* Tcl_GlobalObjCmd --
*
- * This object-based procedure is invoked to process the "global" Tcl
+ * This object-based function is invoked to process the "global" Tcl
* command. See the user documentation for details on what it does.
*
* Results:
@@ -3829,14 +3886,14 @@ Tcl_GetVariableFullName(interp, variable, objPtr)
*/
int
-Tcl_GlobalObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_GlobalObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Interp *iPtr = (Interp *) interp;
- register Tcl_Obj *objPtr;
+ register Tcl_Obj *objPtr, *tailPtr;
char *varName;
register char *tail;
int result, i;
@@ -3849,43 +3906,53 @@ Tcl_GlobalObjCmd(dummy, interp, objc, objv)
/*
* If we are not executing inside a Tcl procedure, just return.
*/
-
- if ((iPtr->varFramePtr == NULL)
- || !iPtr->varFramePtr->isProcCallFrame) {
+
+ if (!HasLocalVars(iPtr->varFramePtr)) {
return TCL_OK;
}
- for (i = 1; i < objc; i++) {
+ for (i=1 ; i<objc ; i++) {
/*
* Make a local variable linked to its counterpart in the global ::
* namespace.
*/
-
+
objPtr = objv[i];
varName = TclGetString(objPtr);
/*
* The variable name might have a scope qualifier, but the name for
- * the local "link" variable must be the simple name at the tail.
+ * the local "link" variable must be the simple name at the tail.
*/
- for (tail = varName; *tail != '\0'; tail++) {
+ for (tail=varName ; *tail!='\0' ; tail++) {
/* empty body */
}
- while ((tail > varName) && ((*tail != ':') || (*(tail-1) != ':'))) {
- tail--;
+ while ((tail > varName) && ((*tail != ':') || (*(tail-1) != ':'))) {
+ tail--;
}
- if ((*tail == ':') && (tail > varName)) {
- tail++;
+ if ((*tail == ':') && (tail > varName)) {
+ tail++;
+ }
+
+ if (tail == varName) {
+ tailPtr = objPtr;
+ } else {
+ tailPtr = Tcl_NewStringObj(tail, -1);
+ Tcl_IncrRefCount(tailPtr);
}
/*
* Link to the variable "varName" in the global :: namespace.
*/
-
- result = ObjMakeUpvar(interp, (CallFrame *) NULL,
- objPtr, NULL, /*otherFlags*/ TCL_GLOBAL_ONLY,
- /*myName*/ tail, /*myFlags*/ 0, -1);
+
+ result = ObjMakeUpvar(interp, NULL, objPtr, NULL,
+ TCL_GLOBAL_ONLY, /*myName*/ tailPtr, /*myFlags*/ 0, -1);
+
+ if (tail != varName) {
+ Tcl_DecrRefCount(tailPtr);
+ }
+
if (result != TCL_OK) {
return result;
}
@@ -3908,104 +3975,100 @@ Tcl_GlobalObjCmd(dummy, interp, objc, objv)
* optional.
*
* If the variable does not exist, it is created and given the optional
- * value. If it already exists, it is simply set to the optional
- * value. Normally, "name" is an unqualified name, so it is created in
- * the current namespace. If it includes namespace qualifiers, it can
- * be created in another namespace.
+ * value. If it already exists, it is simply set to the optional value.
+ * Normally, "name" is an unqualified name, so it is created in the
+ * current namespace. If it includes namespace qualifiers, it can be
+ * created in another namespace.
*
- * If the variable command is executed inside a Tcl procedure, it
- * creates a local variable linked to the newly-created namespace
- * variable.
+ * If the variable command is executed inside a Tcl procedure, it creates
+ * a local variable linked to the newly-created namespace variable.
*
* Results:
- * Returns TCL_OK if the variable is found or created. Returns
- * TCL_ERROR if anything goes wrong.
+ * Returns TCL_OK if the variable is found or created. Returns TCL_ERROR
+ * if anything goes wrong.
*
* Side effects:
- * If anything goes wrong, this procedure returns an error message
- * as the result in the interpreter's result object.
+ * If anything goes wrong, this function returns an error message as the
+ * result in the interpreter's result object.
*
*----------------------------------------------------------------------
*/
int
-Tcl_VariableObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_VariableObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Interp *iPtr = (Interp *) interp;
char *varName, *tail, *cp;
Var *varPtr, *arrayPtr;
Tcl_Obj *varValuePtr;
int i, result;
- Tcl_Obj *varNamePtr;
+ Tcl_Obj *varNamePtr, *tailPtr;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "?name value...? name ?value?");
return TCL_ERROR;
}
- for (i = 1; i < objc; i = i+2) {
+ for (i=1 ; i<objc ; i+=2) {
/*
- * Look up each variable in the current namespace context, creating
- * it if necessary.
+ * Look up each variable in the current namespace context, creating it
+ * if necessary.
*/
-
+
varNamePtr = objv[i];
varName = TclGetString(varNamePtr);
- varPtr = TclObjLookupVar(interp, varNamePtr, NULL,
- (TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG), "define",
- /*createPart1*/ 1, /*createPart2*/ 0, &arrayPtr);
-
- if (arrayPtr != NULL) {
- /*
- * Variable cannot be an element in an array. If arrayPtr is
- * non-null, it is, so throw up an error and return.
- */
- VarErrMsg(interp, varName, NULL, "define", isArrayElement);
- return TCL_ERROR;
- }
+ varPtr = TclObjLookupVarEx(interp, varNamePtr, NULL,
+ (TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG), "define",
+ /*createPart1*/ 1, /*createPart2*/ 0, &arrayPtr);
+
+ if (arrayPtr != NULL) {
+ /*
+ * Variable cannot be an element in an array. If arrayPtr is
+ * non-NULL, it is, so throw up an error and return.
+ */
+
+ TclObjVarErrMsg(interp, varNamePtr, NULL, "define",
+ isArrayElement, -1);
+ return TCL_ERROR;
+ }
if (varPtr == NULL) {
return TCL_ERROR;
}
/*
- * Mark the variable as a namespace variable and increment its
+ * Mark the variable as a namespace variable and increment its
* reference count so that it will persist until its namespace is
* destroyed or until the variable is unset.
*/
- if (!(varPtr->flags & VAR_NAMESPACE_VAR)) {
- varPtr->flags |= VAR_NAMESPACE_VAR;
- varPtr->refCount++;
- }
+ TclSetVarNamespaceVar(varPtr);
/*
* If a value was specified, set the variable to that value.
- * Otherwise, if the variable is new, leave it undefined.
- * (If the variable already exists and no value was specified,
- * leave its value unchanged; just create the local link if
- * we're in a Tcl procedure).
+ * Otherwise, if the variable is new, leave it undefined. (If the
+ * variable already exists and no value was specified, leave its value
+ * unchanged; just create the local link if we're in a Tcl procedure).
*/
- if (i+1 < objc) { /* a value was specified */
- varValuePtr = TclPtrSetVar(interp, varPtr, arrayPtr, varName, NULL,
- objv[i+1], (TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG));
+ if (i+1 < objc) { /* A value was specified. */
+ varValuePtr = TclPtrSetVar(interp, varPtr, arrayPtr, varNamePtr,
+ NULL, objv[i+1], TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG,-1);
if (varValuePtr == NULL) {
return TCL_ERROR;
}
}
/*
- * If we are executing inside a Tcl procedure, create a local
- * variable linked to the new namespace variable "varName".
+ * If we are executing inside a Tcl procedure, create a local variable
+ * linked to the new namespace variable "varName".
*/
- if ((iPtr->varFramePtr != NULL)
- && iPtr->varFramePtr->isProcCallFrame) {
+ if (HasLocalVars(iPtr->varFramePtr)) {
/*
* varName might have a scope qualifier, but the name for the
* local "link" variable must be the simple name at the tail.
@@ -4014,23 +4077,34 @@ Tcl_VariableObjCmd(dummy, interp, objc, objv)
* consecutive ":" characters).
*/
- for (tail = cp = varName; *cp != '\0'; ) {
+ for (tail=cp=varName ; *cp!='\0' ;) {
if (*cp++ == ':') {
while (*cp == ':') {
tail = ++cp;
}
}
}
-
+
/*
* Create a local link "tail" to the variable "varName" in the
* current namespace.
*/
-
- result = ObjMakeUpvar(interp, (CallFrame *) NULL,
- /*otherP1*/ varNamePtr, /*otherP2*/ NULL,
- /*otherFlags*/ TCL_NAMESPACE_ONLY,
- /*myName*/ tail, /*myFlags*/ 0, -1);
+
+ if (tail == varName) {
+ tailPtr = varNamePtr;
+ } else {
+ tailPtr = Tcl_NewStringObj(tail, -1);
+ Tcl_IncrRefCount(tailPtr);
+ }
+
+ result = ObjMakeUpvar(interp, NULL, varNamePtr, /*otherP2*/ NULL,
+ /*otherFlags*/ TCL_NAMESPACE_ONLY,
+ /*myName*/ tailPtr, /*myFlags*/ 0, -1);
+
+ if (tail != varName) {
+ Tcl_DecrRefCount(tailPtr);
+ }
+
if (result != TCL_OK) {
return result;
}
@@ -4044,8 +4118,8 @@ Tcl_VariableObjCmd(dummy, interp, objc, objv)
*
* Tcl_UpvarObjCmd --
*
- * This object-based procedure is invoked to process the "upvar"
- * Tcl command. See the user documentation for details on what it does.
+ * This object-based function is invoked to process the "upvar" Tcl
+ * command. See the user documentation for details on what it does.
*
* Results:
* A standard Tcl object result value.
@@ -4058,18 +4132,17 @@ Tcl_VariableObjCmd(dummy, interp, objc, objv)
/* ARGSUSED */
int
-Tcl_UpvarObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
+Tcl_UpvarObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
CallFrame *framePtr;
- char *frameSpec, *localName;
int result;
if (objc < 3) {
- upvarSyntax:
+ upvarSyntax:
Tcl_WrongNumArgs(interp, 1, objv,
"?level? otherVar localVar ?otherVar localVar ...?");
return TCL_ERROR;
@@ -4077,11 +4150,10 @@ Tcl_UpvarObjCmd(dummy, interp, objc, objv)
/*
* Find the call frame containing each of the "other variables" to be
- * linked to.
+ * linked to.
*/
- frameSpec = TclGetString(objv[1]);
- result = TclGetFrame(interp, frameSpec, &framePtr);
+ result = TclObjGetFrame(interp, objv[1], &framePtr);
if (result == -1) {
return TCL_ERROR;
}
@@ -4092,15 +4164,14 @@ Tcl_UpvarObjCmd(dummy, interp, objc, objv)
objv += result+1;
/*
- * Iterate over each (other variable, local variable) pair.
- * Divide the other variable name into two parts, then call
- * MakeUpvar to do all the work of linking it to the local variable.
+ * Iterate over each (other variable, local variable) pair. Divide the
+ * other variable name into two parts, then call MakeUpvar to do all the
+ * work of linking it to the local variable.
*/
- for ( ; objc > 0; objc -= 2, objv += 2) {
- localName = TclGetString(objv[1]);
+ for (; objc>0 ; objc-=2, objv+=2) {
result = ObjMakeUpvar(interp, framePtr, /* othervarName */ objv[0],
- NULL, 0, /* myVarName */ localName, /*flags*/ 0, -1);
+ NULL, 0, /* myVarName */ objv[1], /*flags*/ 0, -1);
if (result != TCL_OK) {
return TCL_ERROR;
}
@@ -4111,321 +4182,27 @@ Tcl_UpvarObjCmd(dummy, interp, objc, objv)
/*
*----------------------------------------------------------------------
*
- * DisposeTraceResult--
- *
- * This procedure is called to dispose of the result returned from
- * a trace procedure. The disposal method appropriate to the type
- * of result is determined by flags.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The memory allocated for the trace result may be freed.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-DisposeTraceResult(flags, result)
- int flags; /* Indicates type of result to determine
- * proper disposal method */
- char *result; /* The result returned from a trace
- * procedure to be disposed */
-{
- if (flags & TCL_TRACE_RESULT_DYNAMIC) {
- ckfree(result);
- } else if (flags & TCL_TRACE_RESULT_OBJECT) {
- Tcl_DecrRefCount((Tcl_Obj *) result);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * CallVarTraces --
- *
- * This procedure is invoked to find and invoke relevant
- * trace procedures associated with a particular operation on
- * a variable. This procedure invokes traces both on the
- * variable and on its containing array (where relevant).
- *
- * Results:
- * Returns TCL_OK to indicate normal operation. Returns TCL_ERROR
- * if invocation of a trace procedure indicated an error. When
- * TCL_ERROR is returned and leaveErrMsg is true, then the
- * ::errorInfo variable of iPtr has information about the error
- * appended to it.
- *
- * Side effects:
- * Almost anything can happen, depending on trace; this procedure
- * itself doesn't have any side effects.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-CallVarTraces(iPtr, arrayPtr, varPtr, part1, part2, flags, leaveErrMsg)
- Interp *iPtr; /* Interpreter containing variable. */
- register Var *arrayPtr; /* Pointer to array variable that contains
- * the variable, or NULL if the variable
- * isn't an element of an array. */
- Var *varPtr; /* Variable whose traces are to be
- * invoked. */
- CONST char *part1;
- CONST char *part2; /* Variable's two-part name. */
- int flags; /* Flags passed to trace procedures:
- * indicates what's happening to variable,
- * plus other stuff like TCL_GLOBAL_ONLY,
- * or TCL_NAMESPACE_ONLY. */
- CONST int leaveErrMsg; /* If true, and one of the traces indicates an
- * error, then leave an error message and stack
- * trace information in *iPTr. */
-{
- register VarTrace *tracePtr;
- ActiveVarTrace active;
- char *result;
- CONST char *openParen, *p;
- Tcl_DString nameCopy;
- int copiedName;
- int code = TCL_OK;
- int disposeFlags = 0;
- int saveErrFlags = iPtr->flags
- & (ERR_IN_PROGRESS | ERR_ALREADY_LOGGED | ERROR_CODE_SET);
-
- /*
- * If there are already similar trace procedures active for the
- * variable, don't call them again.
- */
-
- if (varPtr->flags & VAR_TRACE_ACTIVE) {
- return code;
- }
- varPtr->flags |= VAR_TRACE_ACTIVE;
- varPtr->refCount++;
- if (arrayPtr != NULL) {
- arrayPtr->refCount++;
- }
-
- /*
- * If the variable name hasn't been parsed into array name and
- * element, do it here. If there really is an array element,
- * make a copy of the original name so that NULLs can be
- * inserted into it to separate the names (can't modify the name
- * string in place, because the string might get used by the
- * callbacks we invoke).
- */
-
- copiedName = 0;
- if (part2 == NULL) {
- for (p = part1; *p ; p++) {
- if (*p == '(') {
- openParen = p;
- do {
- p++;
- } while (*p != '\0');
- p--;
- if (*p == ')') {
- int offset = (openParen - part1);
- char *newPart1;
- Tcl_DStringInit(&nameCopy);
- Tcl_DStringAppend(&nameCopy, part1, (p-part1));
- newPart1 = Tcl_DStringValue(&nameCopy);
- newPart1[offset] = 0;
- part1 = newPart1;
- part2 = newPart1 + offset + 1;
- copiedName = 1;
- }
- break;
- }
- }
- }
-
- /*
- * Invoke traces on the array containing the variable, if relevant.
- */
-
- result = NULL;
- active.nextPtr = iPtr->activeVarTracePtr;
- iPtr->activeVarTracePtr = &active;
- Tcl_Preserve((ClientData) iPtr);
- if (arrayPtr != NULL && !(arrayPtr->flags & VAR_TRACE_ACTIVE)) {
- active.varPtr = arrayPtr;
- for (tracePtr = arrayPtr->tracePtr; tracePtr != NULL;
- tracePtr = active.nextTracePtr) {
- active.nextTracePtr = tracePtr->nextPtr;
- if (!(tracePtr->flags & flags)) {
- continue;
- }
- Tcl_Preserve((ClientData) tracePtr);
- if (Tcl_InterpDeleted((Tcl_Interp *)iPtr)) {
- flags |= TCL_INTERP_DESTROYED;
- }
- result = (*tracePtr->traceProc)(tracePtr->clientData,
- (Tcl_Interp *) iPtr, part1, part2, flags);
- if (result != NULL) {
- if (flags & TCL_TRACE_UNSETS) {
- /* Ignore errors in unset traces */
- DisposeTraceResult(tracePtr->flags, result);
- } else {
- disposeFlags = tracePtr->flags;
- code = TCL_ERROR;
- }
- }
- Tcl_Release((ClientData) tracePtr);
- if (code == TCL_ERROR) {
- goto done;
- }
- }
- }
-
- /*
- * Invoke traces on the variable itself.
- */
-
- if (flags & TCL_TRACE_UNSETS) {
- flags |= TCL_TRACE_DESTROYED;
- }
- active.varPtr = varPtr;
- for (tracePtr = varPtr->tracePtr; tracePtr != NULL;
- tracePtr = active.nextTracePtr) {
- active.nextTracePtr = tracePtr->nextPtr;
- if (!(tracePtr->flags & flags)) {
- continue;
- }
- Tcl_Preserve((ClientData) tracePtr);
- if (Tcl_InterpDeleted((Tcl_Interp *)iPtr)) {
- flags |= TCL_INTERP_DESTROYED;
- }
- result = (*tracePtr->traceProc)(tracePtr->clientData,
- (Tcl_Interp *) iPtr, part1, part2, flags);
- if (result != NULL) {
- if (flags & TCL_TRACE_UNSETS) {
- /* Ignore errors in unset traces */
- DisposeTraceResult(tracePtr->flags, result);
- } else {
- disposeFlags = tracePtr->flags;
- code = TCL_ERROR;
- }
- }
- Tcl_Release((ClientData) tracePtr);
- if (code == TCL_ERROR) {
- goto done;
- }
- }
-
- /*
- * Restore the variable's flags, remove the record of our active
- * traces, and then return.
- */
-
- done:
- if (code == TCL_OK) {
- iPtr->flags |= saveErrFlags;
- }
- if (code == TCL_ERROR) {
- if (leaveErrMsg) {
- CONST char *type = "";
- switch (flags&(TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_ARRAY)) {
- case TCL_TRACE_READS: {
- type = "read";
- break;
- }
- case TCL_TRACE_WRITES: {
- type = "set";
- break;
- }
- case TCL_TRACE_ARRAY: {
- type = "trace array";
- break;
- }
- }
- if (disposeFlags & TCL_TRACE_RESULT_OBJECT) {
- VarErrMsg((Tcl_Interp *) iPtr, part1, part2, type,
- Tcl_GetString((Tcl_Obj *) result));
- } else {
- VarErrMsg((Tcl_Interp *) iPtr, part1, part2, type, result);
- }
- }
- DisposeTraceResult(disposeFlags,result);
- }
-
- if (arrayPtr != NULL) {
- arrayPtr->refCount--;
- }
- if (copiedName) {
- Tcl_DStringFree(&nameCopy);
- }
- varPtr->flags &= ~VAR_TRACE_ACTIVE;
- varPtr->refCount--;
- iPtr->activeVarTracePtr = active.nextPtr;
- Tcl_Release((ClientData) iPtr);
- return code;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * NewVar --
- *
- * Create a new heap-allocated variable that will eventually be
- * entered into a hashtable.
- *
- * Results:
- * The return value is a pointer to the new variable structure. It is
- * marked as a scalar variable (and not a link or array variable). Its
- * value initially is NULL. The variable is not part of any hash table
- * yet. Since it will be in a hashtable and not in a call frame, its
- * name field is set NULL. It is initially marked as undefined.
- *
- * Side effects:
- * Storage gets allocated.
- *
- *----------------------------------------------------------------------
- */
-
-static Var *
-NewVar()
-{
- register Var *varPtr;
-
- varPtr = (Var *) ckalloc(sizeof(Var));
- varPtr->value.objPtr = NULL;
- varPtr->name = NULL;
- varPtr->nsPtr = NULL;
- varPtr->hPtr = NULL;
- varPtr->refCount = 0;
- varPtr->tracePtr = NULL;
- varPtr->searchPtr = NULL;
- varPtr->flags = (VAR_SCALAR | VAR_UNDEFINED | VAR_IN_HASHTABLE);
- return varPtr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
* SetArraySearchObj --
*
- * This function converts the given tcl object into one that
- * has the "array search" internal type.
+ * This function converts the given tcl object into one that has the
+ * "array search" internal type.
*
* Results:
- * TCL_OK if the conversion succeeded, and TCL_ERROR if it failed
- * (when an error message will be placed in the interpreter's
- * result.)
+ * TCL_OK if the conversion succeeded, and TCL_ERROR if it failed (when
+ * an error message will be placed in the interpreter's result.)
*
* Side effects:
- * Updates the internal type and representation of the object to
- * make this an array-search object. See the tclArraySearchType
- * declaration above for details of the internal representation.
+ * Updates the internal type and representation of the object to make
+ * this an array-search object. See the tclArraySearchType declaration
+ * above for details of the internal representation.
*
*----------------------------------------------------------------------
*/
static int
-SetArraySearchObj(interp, objPtr)
- Tcl_Interp *interp;
- Tcl_Obj *objPtr;
+SetArraySearchObj(
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr)
{
char *string;
char *end;
@@ -4436,35 +4213,37 @@ SetArraySearchObj(interp, objPtr)
* Get the string representation. Make it up-to-date if necessary.
*/
- string = Tcl_GetString(objPtr);
+ string = TclGetString(objPtr);
/*
* Parse the id into the three parts separated by dashes.
*/
+
if ((string[0] != 's') || (string[1] != '-')) {
- syntax:
- Tcl_AppendResult(interp, "illegal search identifier \"", string,
- "\"", (char *) NULL);
- return TCL_ERROR;
+ goto syntax;
}
id = strtoul(string+2, &end, 10);
if ((end == (string+2)) || (*end != '-')) {
goto syntax;
}
+
/*
- * Can't perform value check in this context, so place reference
- * to place in string to use for the check in the object instead.
+ * Can't perform value check in this context, so place reference to place
+ * in string to use for the check in the object instead.
*/
+
end++;
offset = end - string;
- if (objPtr->typePtr != NULL && objPtr->typePtr->freeIntRepProc != NULL) {
- objPtr->typePtr->freeIntRepProc(objPtr);
- }
+ TclFreeIntRep(objPtr);
objPtr->typePtr = &tclArraySearchType;
- objPtr->internalRep.twoPtrValue.ptr1 = (VOID *)(((char *)NULL)+id);
- objPtr->internalRep.twoPtrValue.ptr2 = (VOID *)(((char *)NULL)+offset);
+ objPtr->internalRep.twoPtrValue.ptr1 = INT2PTR(id);
+ objPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(offset);
return TCL_OK;
+
+ syntax:
+ Tcl_AppendResult(interp, "illegal search identifier \"",string,"\"",NULL);
+ return TCL_ERROR;
}
/*
@@ -4472,13 +4251,13 @@ SetArraySearchObj(interp, objPtr)
*
* ParseSearchId --
*
- * This procedure translates from a tcl object to a pointer to an
- * active array search (if there is one that matches the string).
+ * This function translates from a tcl object to a pointer to an active
+ * array search (if there is one that matches the string).
*
* Results:
- * The return value is a pointer to the array search indicated
- * by string, or NULL if there isn't one. If NULL is returned,
- * the interp's result contains an error message.
+ * The return value is a pointer to the array search indicated by string,
+ * or NULL if there isn't one. If NULL is returned, the interp's result
+ * contains an error message.
*
* Side effects:
* The tcl object might have its internal type and representation
@@ -4488,62 +4267,81 @@ SetArraySearchObj(interp, objPtr)
*/
static ArraySearch *
-ParseSearchId(interp, varPtr, varName, handleObj)
- Tcl_Interp *interp; /* Interpreter containing variable. */
- CONST Var *varPtr; /* Array variable search is for. */
- CONST char *varName; /* Name of array variable that search is
+ParseSearchId(
+ Tcl_Interp *interp, /* Interpreter containing variable. */
+ const Var *varPtr, /* Array variable search is for. */
+ Tcl_Obj *varNamePtr, /* Name of array variable that search is
* supposed to be for. */
- Tcl_Obj *handleObj; /* Object containing id of search. Must have
+ Tcl_Obj *handleObj) /* Object containing id of search. Must have
* form "search-num-var" where "num" is a
* decimal number and "var" is a variable
* name. */
{
+ Interp *iPtr = (Interp *) interp;
register char *string;
register size_t offset;
int id;
ArraySearch *searchPtr;
+ char *varName = TclGetString(varNamePtr);
/*
* Parse the id.
*/
+
if (Tcl_ConvertToType(interp, handleObj, &tclArraySearchType) != TCL_OK) {
return NULL;
}
+
/*
- * Cast is safe, since always came from an int in the first place.
+ * Extract the information out of the Tcl_Obj.
*/
- id = (int)(((char*)handleObj->internalRep.twoPtrValue.ptr1) -
- ((char*)NULL));
- string = Tcl_GetString(handleObj);
- offset = (((char*)handleObj->internalRep.twoPtrValue.ptr2) -
- ((char*)NULL));
+
+#if 1
+ id = PTR2INT(handleObj->internalRep.twoPtrValue.ptr1);
+ string = TclGetString(handleObj);
+ offset = PTR2INT(handleObj->internalRep.twoPtrValue.ptr2);
+#else
+ id = (int)(((char *) handleObj->internalRep.twoPtrValue.ptr1) -
+ ((char *) NULL));
+ string = TclGetString(handleObj);
+ offset = (((char *) handleObj->internalRep.twoPtrValue.ptr2) -
+ ((char *) NULL));
+#endif
+
/*
- * This test cannot be placed inside the Tcl_Obj machinery, since
- * it is dependent on the variable context.
+ * This test cannot be placed inside the Tcl_Obj machinery, since it is
+ * dependent on the variable context.
*/
+
if (strcmp(string+offset, varName) != 0) {
Tcl_AppendResult(interp, "search identifier \"", string,
- "\" isn't for variable \"", varName, "\"", (char *) NULL);
- return NULL;
+ "\" isn't for variable \"", varName, "\"", NULL);
+ goto badLookup;
}
/*
- * Search through the list of active searches on the interpreter
- * to see if the desired one exists.
+ * Search through the list of active searches on the interpreter to see if
+ * the desired one exists.
*
- * Note that we cannot store the searchPtr directly in the Tcl_Obj
- * as that would run into trouble when DeleteSearches() was called
- * so we must scan this list every time.
+ * Note that we cannot store the searchPtr directly in the Tcl_Obj as that
+ * would run into trouble when DeleteSearches() was called so we must scan
+ * this list every time.
*/
- for (searchPtr = varPtr->searchPtr; searchPtr != NULL;
- searchPtr = searchPtr->nextPtr) {
- if (searchPtr->id == id) {
- return searchPtr;
+ if (varPtr->flags & VAR_SEARCH_ACTIVE) {
+ Tcl_HashEntry *hPtr =
+ Tcl_FindHashEntry(&iPtr->varSearches, (char *) varPtr);
+
+ for (searchPtr = (ArraySearch *) Tcl_GetHashValue(hPtr);
+ searchPtr != NULL; searchPtr = searchPtr->nextPtr) {
+ if (searchPtr->id == id) {
+ return searchPtr;
+ }
}
}
- Tcl_AppendResult(interp, "couldn't find search \"", string, "\"",
- (char *) NULL);
+ Tcl_AppendResult(interp, "couldn't find search \"", string, "\"", NULL);
+ badLookup:
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAYSEARCH", string, NULL);
return NULL;
}
@@ -4552,8 +4350,8 @@ ParseSearchId(interp, varPtr, varName, handleObj)
*
* DeleteSearches --
*
- * This procedure is called to free up all of the searches
- * associated with an array variable.
+ * This function is called to free up all of the searches associated
+ * with an array variable.
*
* Results:
* None.
@@ -4565,16 +4363,23 @@ ParseSearchId(interp, varPtr, varName, handleObj)
*/
static void
-DeleteSearches(arrayVarPtr)
- register Var *arrayVarPtr; /* Variable whose searches are
- * to be deleted. */
+DeleteSearches(
+ Interp *iPtr,
+ register Var *arrayVarPtr) /* Variable whose searches are to be
+ * deleted. */
{
- ArraySearch *searchPtr;
-
- while (arrayVarPtr->searchPtr != NULL) {
- searchPtr = arrayVarPtr->searchPtr;
- arrayVarPtr->searchPtr = searchPtr->nextPtr;
- ckfree((char *) searchPtr);
+ ArraySearch *searchPtr, *nextPtr;
+ Tcl_HashEntry *sPtr;
+
+ if (arrayVarPtr->flags & VAR_SEARCH_ACTIVE) {
+ sPtr = Tcl_FindHashEntry(&iPtr->varSearches, (char *) arrayVarPtr);
+ for (searchPtr = (ArraySearch *) Tcl_GetHashValue(sPtr);
+ searchPtr != NULL; searchPtr = nextPtr) {
+ nextPtr = searchPtr->nextPtr;
+ ckfree((char *) searchPtr);
+ }
+ arrayVarPtr->flags &= ~VAR_SEARCH_ACTIVE;
+ Tcl_DeleteHashEntry(sPtr);
}
}
@@ -4583,108 +4388,119 @@ DeleteSearches(arrayVarPtr)
*
* TclDeleteNamespaceVars --
*
- * This procedure is called to recycle all the storage space
- * associated with a namespace's table of variables.
+ * This function is called to recycle all the storage space associated
+ * with a namespace's table of variables.
*
* Results:
* None.
*
* Side effects:
- * Variables are deleted and trace procedures are invoked, if
- * any are declared.
+ * Variables are deleted and trace functions are invoked, if any are
+ * declared.
*
*----------------------------------------------------------------------
*/
void
-TclDeleteNamespaceVars(nsPtr)
- Namespace *nsPtr;
+TclDeleteNamespaceVars(
+ Namespace *nsPtr)
{
- Tcl_HashTable *tablePtr = &nsPtr->varTable;
+ TclVarHashTable *tablePtr = &nsPtr->varTable;
Tcl_Interp *interp = nsPtr->interp;
Interp *iPtr = (Interp *)interp;
Tcl_HashSearch search;
- Tcl_HashEntry *hPtr;
int flags = 0;
- Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+ Var *varPtr;
/*
- * Determine what flags to pass to the trace callback procedures.
+ * Determine what flags to pass to the trace callback functions.
*/
if (nsPtr == iPtr->globalNsPtr) {
flags = TCL_GLOBAL_ONLY;
- } else if (nsPtr == currNsPtr) {
+ } else if (nsPtr == (Namespace *) TclGetCurrentNamespace(interp)) {
flags = TCL_NAMESPACE_ONLY;
}
- for (hPtr = Tcl_FirstHashEntry(tablePtr, &search); hPtr != NULL;
- hPtr = Tcl_FirstHashEntry(tablePtr, &search)) {
- register Var *varPtr = (Var *) Tcl_GetHashValue(hPtr);
+ for (varPtr = VarHashFirstVar(tablePtr, &search); varPtr != NULL;
+ varPtr = VarHashFirstVar(tablePtr, &search)) {
Tcl_Obj *objPtr = Tcl_NewObj();
- varPtr->refCount++; /* Make sure we get to remove from hash */
- Tcl_IncrRefCount(objPtr);
+ Tcl_IncrRefCount(objPtr);
+
+ VarHashRefCount(varPtr)++; /* Make sure we get to remove from
+ * hash. */
Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr, objPtr);
- UnsetVarStruct(varPtr, NULL, iPtr, Tcl_GetString(objPtr), NULL, flags);
+ UnsetVarStruct(varPtr, NULL, iPtr, /* part1 */ objPtr,
+ NULL, flags);
Tcl_DecrRefCount(objPtr); /* free no longer needed obj */
- varPtr->refCount--;
- /* Remove the variable from the table and force it undefined
- * in case an unset trace brought it back from the dead */
- Tcl_DeleteHashEntry(hPtr);
- varPtr->hPtr = NULL;
- TclSetVarUndefined(varPtr);
- TclSetVarScalar(varPtr);
- while (varPtr->tracePtr != NULL) {
- VarTrace *tracePtr = varPtr->tracePtr;
- varPtr->tracePtr = tracePtr->nextPtr;
- Tcl_EventuallyFree((ClientData) tracePtr, TCL_DYNAMIC);
+ /*
+ * Remove the variable from the table and force it undefined in case
+ * an unset trace brought it back from the dead.
+ */
+
+ if (TclIsVarTraced(varPtr)) {
+ ActiveVarTrace *activePtr;
+ Tcl_HashEntry *tPtr = Tcl_FindHashEntry(&iPtr->varTraces,
+ (char *) varPtr);
+ VarTrace *tracePtr = (VarTrace *) Tcl_GetHashValue(tPtr);
+
+ while (tracePtr) {
+ VarTrace *prevPtr = tracePtr;
+
+ tracePtr = tracePtr->nextPtr;
+ prevPtr->nextPtr = NULL;
+ Tcl_EventuallyFree((ClientData) prevPtr, TCL_DYNAMIC);
+ }
+ Tcl_DeleteHashEntry(tPtr);
+ varPtr->flags &= ~VAR_ALL_TRACES;
+ for (activePtr = iPtr->activeVarTracePtr; activePtr != NULL;
+ activePtr = activePtr->nextPtr) {
+ if (activePtr->varPtr == varPtr) {
+ activePtr->nextTracePtr = NULL;
+ }
+ }
}
- CleanupVar(varPtr, NULL);
+ VarHashRefCount(varPtr)--;
+ VarHashDeleteEntry(varPtr);
}
- Tcl_DeleteHashTable(tablePtr);
+ VarHashDeleteTable(tablePtr);
}
-
/*
*----------------------------------------------------------------------
*
* TclDeleteVars --
*
- * This procedure is called to recycle all the storage space
- * associated with a table of variables. For this procedure
- * to work correctly, it must not be possible for any of the
- * variables in the table to be accessed from Tcl commands
- * (e.g. from trace procedures).
+ * This function is called to recycle all the storage space associated
+ * with a table of variables. For this function to work correctly, it
+ * must not be possible for any of the variables in the table to be
+ * accessed from Tcl commands (e.g. from trace functions).
*
* Results:
* None.
*
* Side effects:
- * Variables are deleted and trace procedures are invoked, if
- * any are declared.
+ * Variables are deleted and trace functions are invoked, if any are
+ * declared.
*
*----------------------------------------------------------------------
*/
void
-TclDeleteVars(iPtr, tablePtr)
- Interp *iPtr; /* Interpreter to which variables belong. */
- Tcl_HashTable *tablePtr; /* Hash table containing variables to
+TclDeleteVars(
+ Interp *iPtr, /* Interpreter to which variables belong. */
+ TclVarHashTable *tablePtr) /* Hash table containing variables to
* delete. */
{
Tcl_Interp *interp = (Tcl_Interp *) iPtr;
Tcl_HashSearch search;
- Tcl_HashEntry *hPtr;
register Var *varPtr;
- Var *linkPtr;
int flags;
- ActiveVarTrace *activePtr;
- Tcl_Obj *objPtr;
- Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+ Namespace *currNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
/*
- * Determine what flags to pass to the trace callback procedures.
+ * Determine what flags to pass to the trace callback functions.
*/
flags = TCL_TRACE_UNSETS;
@@ -4694,102 +4510,13 @@ TclDeleteVars(iPtr, tablePtr)
flags |= TCL_NAMESPACE_ONLY;
}
- for (hPtr = Tcl_FirstHashEntry(tablePtr, &search); hPtr != NULL;
- hPtr = Tcl_NextHashEntry(&search)) {
- varPtr = (Var *) Tcl_GetHashValue(hPtr);
-
- /*
- * For global/upvar variables referenced in procedures, decrement
- * the reference count on the variable referred to, and free
- * the referenced variable if it's no longer needed. Don't delete
- * the hash entry for the other variable if it's in the same table
- * as us: this will happen automatically later on.
- */
-
- if (TclIsVarLink(varPtr)) {
- linkPtr = varPtr->value.linkPtr;
- linkPtr->refCount--;
- if ((linkPtr->refCount == 0) && TclIsVarUndefined(linkPtr)
- && (linkPtr->tracePtr == NULL)
- && (linkPtr->flags & VAR_IN_HASHTABLE)) {
- if (linkPtr->hPtr == NULL) {
- ckfree((char *) linkPtr);
- } else if (linkPtr->hPtr->tablePtr != tablePtr) {
- Tcl_DeleteHashEntry(linkPtr->hPtr);
- ckfree((char *) linkPtr);
- }
- }
- }
-
- /*
- * Invoke traces on the variable that is being deleted, then
- * free up the variable's space (no need to free the hash entry
- * here, unless we're dealing with a global variable: the
- * hash entries will be deleted automatically when the whole
- * table is deleted). Note that we give CallVarTraces the variable's
- * fully-qualified name so that any called trace procedures can
- * refer to these variables being deleted.
- */
-
- if (varPtr->tracePtr != NULL) {
- objPtr = Tcl_NewObj();
- Tcl_IncrRefCount(objPtr); /* until done with traces */
- Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr, objPtr);
- CallVarTraces(iPtr, (Var *) NULL, varPtr, Tcl_GetString(objPtr),
- NULL, flags, /* leaveErrMsg */ 0);
- Tcl_DecrRefCount(objPtr); /* free no longer needed obj */
-
- while (varPtr->tracePtr != NULL) {
- VarTrace *tracePtr = varPtr->tracePtr;
- varPtr->tracePtr = tracePtr->nextPtr;
- Tcl_EventuallyFree((ClientData) tracePtr, TCL_DYNAMIC);
- }
- for (activePtr = iPtr->activeVarTracePtr; activePtr != NULL;
- activePtr = activePtr->nextPtr) {
- if (activePtr->varPtr == varPtr) {
- activePtr->nextTracePtr = NULL;
- }
- }
- }
-
- if (TclIsVarArray(varPtr)) {
- DeleteArray(iPtr, Tcl_GetHashKey(tablePtr, hPtr), varPtr,
- flags);
- varPtr->value.tablePtr = NULL;
- }
- if (TclIsVarScalar(varPtr) && (varPtr->value.objPtr != NULL)) {
- objPtr = varPtr->value.objPtr;
- TclDecrRefCount(objPtr);
- varPtr->value.objPtr = NULL;
- }
- varPtr->hPtr = NULL;
- varPtr->tracePtr = NULL;
- TclSetVarUndefined(varPtr);
- TclSetVarScalar(varPtr);
-
- /*
- * If the variable was a namespace variable, decrement its
- * reference count. We are in the process of destroying its
- * namespace so that namespace will no longer "refer" to the
- * variable.
- */
-
- if (varPtr->flags & VAR_NAMESPACE_VAR) {
- varPtr->flags &= ~VAR_NAMESPACE_VAR;
- varPtr->refCount--;
- }
-
- /*
- * Recycle the variable's memory space if there aren't any upvar's
- * pointing to it. If there are upvars to this variable, then the
- * variable will get freed when the last upvar goes away.
- */
+ for (varPtr = VarHashFirstVar(tablePtr, &search); varPtr != NULL;
+ varPtr = VarHashFirstVar(tablePtr, &search)) {
- if (varPtr->refCount == 0) {
- ckfree((char *) varPtr); /* this Var must be VAR_IN_HASHTABLE */
- }
+ UnsetVarStruct(varPtr, NULL, iPtr, VarHashGetKey(varPtr), NULL, flags);
+ VarHashDeleteEntry(varPtr);
}
- Tcl_DeleteHashTable(tablePtr);
+ VarHashDeleteTable(tablePtr);
}
/*
@@ -4797,104 +4524,41 @@ TclDeleteVars(iPtr, tablePtr)
*
* TclDeleteCompiledLocalVars --
*
- * This procedure is called to recycle storage space associated with
- * the compiler-allocated array of local variables in a procedure call
- * frame. This procedure resembles TclDeleteVars above except that each
- * variable is stored in a call frame and not a hash table. For this
- * procedure to work correctly, it must not be possible for any of the
- * variable in the table to be accessed from Tcl commands (e.g. from
- * trace procedures).
+ * This function is called to recycle storage space associated with the
+ * compiler-allocated array of local variables in a procedure call frame.
+ * This function resembles TclDeleteVars above except that each variable
+ * is stored in a call frame and not a hash table. For this function to
+ * work correctly, it must not be possible for any of the variable in the
+ * table to be accessed from Tcl commands (e.g. from trace functions).
*
* Results:
* None.
*
* Side effects:
- * Variables are deleted and trace procedures are invoked, if
- * any are declared.
+ * Variables are deleted and trace functions are invoked, if any are
+ * declared.
*
*----------------------------------------------------------------------
*/
void
-TclDeleteCompiledLocalVars(iPtr, framePtr)
- Interp *iPtr; /* Interpreter to which variables belong. */
- CallFrame *framePtr; /* Procedure call frame containing
- * compiler-assigned local variables to
- * delete. */
+TclDeleteCompiledLocalVars(
+ Interp *iPtr, /* Interpreter to which variables belong. */
+ CallFrame *framePtr) /* Procedure call frame containing compiler-
+ * assigned local variables to delete. */
{
register Var *varPtr;
- int flags; /* Flags passed to trace procedures. */
- Var *linkPtr;
- ActiveVarTrace *activePtr;
int numLocals, i;
+ Tcl_Obj **namePtrPtr;
- flags = TCL_TRACE_UNSETS;
numLocals = framePtr->numCompiledLocals;
varPtr = framePtr->compiledLocals;
- for (i = 0; i < numLocals; i++) {
- /*
- * For global/upvar variables referenced in procedures, decrement
- * the reference count on the variable referred to, and free
- * the referenced variable if it's no longer needed. Don't delete
- * the hash entry for the other variable if it's in the same table
- * as us: this will happen automatically later on.
- */
-
- if (TclIsVarLink(varPtr)) {
- linkPtr = varPtr->value.linkPtr;
- linkPtr->refCount--;
- if ((linkPtr->refCount == 0) && TclIsVarUndefined(linkPtr)
- && (linkPtr->tracePtr == NULL)
- && (linkPtr->flags & VAR_IN_HASHTABLE)) {
- if (linkPtr->hPtr == NULL) {
- ckfree((char *) linkPtr);
- } else {
- Tcl_DeleteHashEntry(linkPtr->hPtr);
- ckfree((char *) linkPtr);
- }
- }
- }
-
- /*
- * Invoke traces on the variable that is being deleted. Then delete
- * the variable's trace records.
- */
-
- if (varPtr->tracePtr != NULL) {
- CallVarTraces(iPtr, (Var *) NULL, varPtr, varPtr->name, NULL,
- flags, /* leaveErrMsg */ 0);
- while (varPtr->tracePtr != NULL) {
- VarTrace *tracePtr = varPtr->tracePtr;
- varPtr->tracePtr = tracePtr->nextPtr;
- Tcl_EventuallyFree((ClientData) tracePtr, TCL_DYNAMIC);
- }
- for (activePtr = iPtr->activeVarTracePtr; activePtr != NULL;
- activePtr = activePtr->nextPtr) {
- if (activePtr->varPtr == varPtr) {
- activePtr->nextTracePtr = NULL;
- }
- }
- }
-
- /*
- * Now if the variable is an array, delete its element hash table.
- * Otherwise, if it's a scalar variable, decrement the ref count
- * of its value.
- */
-
- if (TclIsVarArray(varPtr) && (varPtr->value.tablePtr != NULL)) {
- DeleteArray(iPtr, varPtr->name, varPtr, flags);
- }
- if (TclIsVarScalar(varPtr) && (varPtr->value.objPtr != NULL)) {
- TclDecrRefCount(varPtr->value.objPtr);
- varPtr->value.objPtr = NULL;
- }
- varPtr->hPtr = NULL;
- varPtr->tracePtr = NULL;
- TclSetVarUndefined(varPtr);
- TclSetVarScalar(varPtr);
- varPtr++;
+ namePtrPtr = &localName(framePtr, 0);
+ for (i=0 ; i<numLocals ; i++, namePtrPtr++, varPtr++) {
+ UnsetVarStruct(varPtr, NULL, iPtr, *namePtrPtr, NULL,
+ TCL_TRACE_UNSETS);
}
+ framePtr->numCompiledLocals = 0;
}
/*
@@ -4902,384 +4566,308 @@ TclDeleteCompiledLocalVars(iPtr, framePtr)
*
* DeleteArray --
*
- * This procedure is called to free up everything in an array
- * variable. It's the caller's responsibility to make sure
- * that the array is no longer accessible before this procedure
- * is called.
+ * This function is called to free up everything in an array variable.
+ * It's the caller's responsibility to make sure that the array is no
+ * longer accessible before this function is called.
*
* Results:
* None.
*
* Side effects:
* All storage associated with varPtr's array elements is deleted
- * (including the array's hash table). Deletion trace procedures for
- * array elements are invoked, then deleted. Any pending traces for
- * array elements are also deleted.
+ * (including the array's hash table). Deletion trace functions for
+ * array elements are invoked, then deleted. Any pending traces for array
+ * elements are also deleted.
*
*----------------------------------------------------------------------
*/
static void
-DeleteArray(iPtr, arrayName, varPtr, flags)
- Interp *iPtr; /* Interpreter containing array. */
- CONST char *arrayName; /* Name of array (used for trace
- * callbacks). */
- Var *varPtr; /* Pointer to variable structure. */
- int flags; /* Flags to pass to CallVarTraces:
- * TCL_TRACE_UNSETS and sometimes
- * TCL_NAMESPACE_ONLY, or
- * TCL_GLOBAL_ONLY. */
+DeleteArray(
+ Interp *iPtr, /* Interpreter containing array. */
+ Tcl_Obj *arrayNamePtr, /* Name of array (used for trace callbacks),
+ * or NULL if it is to be computed on
+ * demand. */
+ Var *varPtr, /* Pointer to variable structure. */
+ int flags) /* Flags to pass to TclCallVarTraces:
+ * TCL_TRACE_UNSETS and sometimes
+ * TCL_NAMESPACE_ONLY or TCL_GLOBAL_ONLY. */
{
Tcl_HashSearch search;
- register Tcl_HashEntry *hPtr;
+ Tcl_HashEntry *tPtr;
register Var *elPtr;
ActiveVarTrace *activePtr;
Tcl_Obj *objPtr;
+ VarTrace *tracePtr;
- DeleteSearches(varPtr);
- for (hPtr = Tcl_FirstHashEntry(varPtr->value.tablePtr, &search);
- hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
- elPtr = (Var *) Tcl_GetHashValue(hPtr);
+ if (varPtr->flags & VAR_SEARCH_ACTIVE) {
+ DeleteSearches(iPtr, varPtr);
+ }
+ for (elPtr = VarHashFirstVar(varPtr->value.tablePtr, &search);
+ elPtr != NULL; elPtr = VarHashNextVar(&search)) {
if (TclIsVarScalar(elPtr) && (elPtr->value.objPtr != NULL)) {
objPtr = elPtr->value.objPtr;
TclDecrRefCount(objPtr);
elPtr->value.objPtr = NULL;
}
- elPtr->hPtr = NULL;
- if (elPtr->tracePtr != NULL) {
- elPtr->flags &= ~VAR_TRACE_ACTIVE;
- CallVarTraces(iPtr, (Var *) NULL, elPtr, arrayName,
- Tcl_GetHashKey(varPtr->value.tablePtr, hPtr), flags,
- /* leaveErrMsg */ 0);
- while (elPtr->tracePtr != NULL) {
- VarTrace *tracePtr = elPtr->tracePtr;
- elPtr->tracePtr = tracePtr->nextPtr;
- Tcl_EventuallyFree((ClientData) tracePtr,TCL_DYNAMIC);
+
+ /*
+ * Lie about the validity of the hashtable entry. In this way the
+ * variables will be deleted by VarHashDeleteTable.
+ */
+
+ VarHashInvalidateEntry(elPtr);
+ if (TclIsVarTraced(elPtr)) {
+ /*
+ * Compute the array name if it was not supplied.
+ */
+
+ if (elPtr->flags & VAR_TRACED_UNSET) {
+ Tcl_Obj *elNamePtr = VarHashGetKey(elPtr);
+
+ elPtr->flags &= ~VAR_TRACE_ACTIVE;
+ TclObjCallVarTraces(iPtr, NULL, elPtr, arrayNamePtr,
+ elNamePtr, flags,/* leaveErrMsg */ 0, -1);
}
+ tPtr = Tcl_FindHashEntry(&iPtr->varTraces, (char *) elPtr);
+ tracePtr = (VarTrace *) Tcl_GetHashValue(tPtr);
+ while (tracePtr) {
+ VarTrace *prevPtr = tracePtr;
+
+ tracePtr = tracePtr->nextPtr;
+ Tcl_EventuallyFree((ClientData) prevPtr, TCL_DYNAMIC);
+ }
+ Tcl_DeleteHashEntry(tPtr);
+ elPtr->flags &= ~VAR_ALL_TRACES;
for (activePtr = iPtr->activeVarTracePtr; activePtr != NULL;
- activePtr = activePtr->nextPtr) {
+ activePtr = activePtr->nextPtr) {
if (activePtr->varPtr == elPtr) {
activePtr->nextTracePtr = NULL;
}
}
}
TclSetVarUndefined(elPtr);
- TclSetVarScalar(elPtr);
/*
* Even though array elements are not supposed to be namespace
- * variables, some combinations of [upvar] and [variable] may
- * create such beasts - see [Bug 604239]. This is necessary to
- * avoid leaking the corresponding Var struct, and is otherwise
- * harmless.
+ * variables, some combinations of [upvar] and [variable] may create
+ * such beasts - see [Bug 604239]. This is necessary to avoid leaking
+ * the corresponding Var struct, and is otherwise harmless.
*/
- if (elPtr->flags & VAR_NAMESPACE_VAR) {
- elPtr->flags &= ~VAR_NAMESPACE_VAR;
- elPtr->refCount--;
- }
- if (elPtr->refCount == 0) {
- ckfree((char *) elPtr); /* element Vars are VAR_IN_HASHTABLE */
- }
+ TclClearVarNamespaceVar(elPtr);
}
- Tcl_DeleteHashTable(varPtr->value.tablePtr);
+ VarHashDeleteTable(varPtr->value.tablePtr);
ckfree((char *) varPtr->value.tablePtr);
}
/*
*----------------------------------------------------------------------
*
- * CleanupVar --
+ * TclTclObjVarErrMsg --
*
- * This procedure is called when it looks like it may be OK to free up
- * a variable's storage. If the variable is in a hashtable, its Var
- * structure and hash table entry will be freed along with those of its
- * containing array, if any. This procedure is called, for example,
- * when a trace on a variable deletes a variable.
+ * Generate a reasonable error message describing why a variable
+ * operation failed.
*
* Results:
* None.
*
* Side effects:
- * If the variable (or its containing array) really is dead and in a
- * hashtable, then its Var structure, and possibly its hash table
- * entry, is freed up.
+ * The interp's result is set to hold a message identifying the variable
+ * given by part1 and part2 and describing why the variable operation
+ * failed.
*
*----------------------------------------------------------------------
*/
-static void
-CleanupVar(varPtr, arrayPtr)
- Var *varPtr; /* Pointer to variable that may be a
- * candidate for being expunged. */
- Var *arrayPtr; /* Array that contains the variable, or
- * NULL if this variable isn't an array
- * element. */
+void
+TclVarErrMsg(
+ Tcl_Interp *interp, /* Interpreter in which to record message. */
+ const char *part1,
+ const char *part2, /* Variable's two-part name. */
+ const char *operation, /* String describing operation that failed,
+ * e.g. "read", "set", or "unset". */
+ const char *reason) /* String describing why operation failed. */
{
- if (TclIsVarUndefined(varPtr) && (varPtr->refCount == 0)
- && (varPtr->tracePtr == NULL)
- && (varPtr->flags & VAR_IN_HASHTABLE)) {
- if (varPtr->hPtr != NULL) {
- Tcl_DeleteHashEntry(varPtr->hPtr);
- }
- ckfree((char *) varPtr);
+ Tcl_Obj *part1Ptr = NULL, *part2Ptr = NULL;
+
+ part1Ptr = Tcl_NewStringObj(part1, -1);
+ Tcl_IncrRefCount(part1Ptr);
+ if (part2) {
+ part2Ptr = Tcl_NewStringObj(part2, -1);
+ Tcl_IncrRefCount(part2Ptr);
+ } else {
+ part2 = NULL;
}
- if (arrayPtr != NULL) {
- if (TclIsVarUndefined(arrayPtr) && (arrayPtr->refCount == 0)
- && (arrayPtr->tracePtr == NULL)
- && (arrayPtr->flags & VAR_IN_HASHTABLE)) {
- if (arrayPtr->hPtr != NULL) {
- Tcl_DeleteHashEntry(arrayPtr->hPtr);
- }
- ckfree((char *) arrayPtr);
- }
+
+ TclObjVarErrMsg(interp, part1Ptr, part2Ptr, operation, reason, -1);
+
+ Tcl_DecrRefCount(part1Ptr);
+ if (part2Ptr) {
+ Tcl_DecrRefCount(part2Ptr);
}
}
-/*
- *----------------------------------------------------------------------
- *
- * VarErrMsg --
- *
- * Generate a reasonable error message describing why a variable
- * operation failed.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The interp's result is set to hold a message identifying the
- * variable given by part1 and part2 and describing why the
- * variable operation failed.
- *
- *----------------------------------------------------------------------
- */
-static void
-VarErrMsg(interp, part1, part2, operation, reason)
- Tcl_Interp *interp; /* Interpreter in which to record message. */
- CONST char *part1;
- CONST char *part2; /* Variable's two-part name. */
- CONST char *operation; /* String describing operation that failed,
- * e.g. "read", "set", or "unset". */
- CONST char *reason; /* String describing why operation failed. */
+void
+TclObjVarErrMsg(
+ Tcl_Interp *interp, /* Interpreter in which to record message. */
+ Tcl_Obj *part1Ptr, /* (may be NULL, if index >= 0) */
+ Tcl_Obj *part2Ptr, /* Variable's two-part name. */
+ const char *operation, /* String describing operation that failed,
+ * e.g. "read", "set", or "unset". */
+ const char *reason, /* String describing why operation failed. */
+ int index) /* Index into the local variable table of the
+ * variable, or -1. Only used when part1Ptr is
+ * NULL. */
{
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "can't ", operation, " \"", part1,
- (char *) NULL);
- if (part2 != NULL) {
- Tcl_AppendResult(interp, "(", part2, ")", (char *) NULL);
+ if (!part1Ptr) {
+ part1Ptr = localName(((Interp *)interp)->varFramePtr, index);
}
- Tcl_AppendResult(interp, "\": ", reason, (char *) NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("can't %s \"%s%s%s%s\": %s",
+ operation, TclGetString(part1Ptr), (part2Ptr ? "(" : ""),
+ (part2Ptr ? TclGetString(part2Ptr) : ""), (part2Ptr ? ")" : ""),
+ reason));
}
/*
*----------------------------------------------------------------------
*
- * TclTraceVarExists --
- *
- * This is called from info exists. We need to trigger read
- * and/or array traces because they may end up creating a
- * variable that doesn't currently exist.
- *
- * Results:
- * A pointer to the Var structure, or NULL.
- *
- * Side effects:
- * May fill in error messages in the interp.
+ * Internal functions for variable name object types --
*
*----------------------------------------------------------------------
*/
-Var *
-TclVarTraceExists(interp, varName)
- Tcl_Interp *interp; /* The interpreter */
- CONST char *varName; /* The variable name */
-{
- Var *varPtr;
- Var *arrayPtr;
-
- /*
- * The choice of "create" flag values is delicate here, and
- * matches the semantics of GetVar. Things are still not perfect,
- * however, because if you do "info exists x" you get a varPtr
- * and therefore trigger traces. However, if you do
- * "info exists x(i)", then you only get a varPtr if x is already
- * known to be an array. Otherwise you get NULL, and no trace
- * is triggered. This matches Tcl 7.6 semantics.
- */
-
- varPtr = TclLookupVar(interp, varName, (char *) NULL,
- 0, "access", /*createPart1*/ 0, /*createPart2*/ 1, &arrayPtr);
-
- if (varPtr == NULL) {
- return NULL;
- }
-
- if ((varPtr->tracePtr != NULL)
- || ((arrayPtr != NULL) && (arrayPtr->tracePtr != NULL))) {
- CallVarTraces((Interp *)interp, arrayPtr, varPtr, varName, NULL,
- TCL_TRACE_READS, /* leaveErrMsg */ 0);
- }
-
- /*
- * If the variable doesn't exist anymore and no-one's using
- * it, then free up the relevant structures and hash table entries.
- */
+/*
+ * Panic functions that should never be called in normal operation.
+ */
- if (TclIsVarUndefined(varPtr)) {
- CleanupVar(varPtr, arrayPtr);
- return NULL;
- }
+static void
+PanicOnUpdateVarName(
+ Tcl_Obj *objPtr)
+{
+ Tcl_Panic("%s of type %s should not be called", "updateStringProc",
+ objPtr->typePtr->name);
+}
- return varPtr;
+static int
+PanicOnSetVarName(
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr)
+{
+ Tcl_Panic("%s of type %s should not be called", "setFromAnyProc",
+ objPtr->typePtr->name);
+ return TCL_ERROR;
}
-
-/*
- *----------------------------------------------------------------------
- *
- * Internal functions for variable name object types --
- *
- *----------------------------------------------------------------------
- */
-/*
+/*
* localVarName -
*
* INTERNALREP DEFINITION:
- * twoPtrValue.ptr1 = pointer to the corresponding Proc
- * twoPtrValue.ptr2 = index into locals table
-*/
-
-static void
-FreeLocalVarName(objPtr)
- Tcl_Obj *objPtr;
-{
- register Proc *procPtr = (Proc *) objPtr->internalRep.twoPtrValue.ptr1;
- procPtr->refCount--;
- if (procPtr->refCount <= 0) {
- TclProcCleanupProc(procPtr);
- }
-}
+ * ptrAndLongRep.ptr: pointer to name obj in varFramePtr->localCache
+ * or NULL if it is this same obj
+ * ptrAndLongRep.value: index into locals table
+ */
static void
-DupLocalVarName(srcPtr, dupPtr)
- Tcl_Obj *srcPtr;
- Tcl_Obj *dupPtr;
+FreeLocalVarName(
+ Tcl_Obj *objPtr)
{
- register Proc *procPtr = (Proc *) srcPtr->internalRep.twoPtrValue.ptr1;
-
- dupPtr->internalRep.twoPtrValue.ptr1 = (VOID *) procPtr;
- dupPtr->internalRep.twoPtrValue.ptr2 = srcPtr->internalRep.twoPtrValue.ptr2;
- procPtr->refCount++;
- dupPtr->typePtr = &tclLocalVarNameType;
+ Tcl_Obj *namePtr = (Tcl_Obj *) objPtr->internalRep.ptrAndLongRep.ptr;
+ if (namePtr) {
+ Tcl_DecrRefCount(namePtr);
+ }
+ objPtr->typePtr = NULL;
}
static void
-UpdateLocalVarName(objPtr)
- Tcl_Obj *objPtr;
+DupLocalVarName(
+ Tcl_Obj *srcPtr,
+ Tcl_Obj *dupPtr)
{
- Proc *procPtr = (Proc *) objPtr->internalRep.twoPtrValue.ptr1;
- unsigned int index = (unsigned int) objPtr->internalRep.twoPtrValue.ptr2;
- CompiledLocal *localPtr = procPtr->firstLocalPtr;
- unsigned int nameLen;
+ Tcl_Obj *namePtr = srcPtr->internalRep.ptrAndLongRep.ptr;
- if (localPtr == NULL) {
- goto emptyName;
- }
- while (index--) {
- localPtr = localPtr->nextPtr;
- if (localPtr == NULL) {
- goto emptyName;
- }
+ if (!namePtr) {
+ namePtr = srcPtr;
}
+ dupPtr->internalRep.ptrAndLongRep.ptr = namePtr;
+ Tcl_IncrRefCount(namePtr);
- nameLen = (unsigned int) localPtr->nameLength;
- objPtr->bytes = ckalloc(nameLen + 1);
- memcpy(objPtr->bytes, localPtr->name, nameLen + 1);
- objPtr->length = nameLen;
- return;
-
- emptyName:
- objPtr->bytes = ckalloc(1);
- *(objPtr->bytes) = '\0';
- objPtr->length = 0;
+ dupPtr->internalRep.ptrAndLongRep.value =
+ srcPtr->internalRep.ptrAndLongRep.value;
+ dupPtr->typePtr = &localVarNameType;
}
-/*
+#if ENABLE_NS_VARNAME_CACHING
+/*
* nsVarName -
*
* INTERNALREP DEFINITION:
- * twoPtrValue.ptr1: pointer to the namespace containing the
- * reference.
- * twoPtrValue.ptr2: pointer to the corresponding Var
-*/
+ * twoPtrValue.ptr1: pointer to the namespace containing the reference.
+ * twoPtrValue.ptr2: pointer to the corresponding Var
+ */
-static void
-FreeNsVarName(objPtr)
- Tcl_Obj *objPtr;
+static void
+FreeNsVarName(
+ Tcl_Obj *objPtr)
{
- register Var *varPtr = (Var *) objPtr->internalRep.twoPtrValue.ptr2;
+ register Var *varPtr = objPtr->internalRep.twoPtrValue.ptr2;
- varPtr->refCount--;
- if (TclIsVarUndefined(varPtr) && (varPtr->refCount <= 0)) {
- if (TclIsVarLink(varPtr)) {
- Var *linkPtr = varPtr->value.linkPtr;
- linkPtr->refCount--;
- if (TclIsVarUndefined(linkPtr) && (linkPtr->refCount <= 0)) {
- CleanupVar(linkPtr, (Var *) NULL);
- }
+ if (TclIsVarInHash(varPtr)) {
+ varPtr->refCount--;
+ if (TclIsVarUndefined(varPtr) && (varPtr->refCount == 0)) {
+ CleanupVar(varPtr, NULL);
}
- CleanupVar(varPtr, NULL);
}
+ objPtr->typePtr = NULL;
}
static void
-DupNsVarName(srcPtr, dupPtr)
- Tcl_Obj *srcPtr;
- Tcl_Obj *dupPtr;
+DupNsVarName(
+ Tcl_Obj *srcPtr,
+ Tcl_Obj *dupPtr)
{
- Namespace *nsPtr = (Namespace *) srcPtr->internalRep.twoPtrValue.ptr1;
- register Var *varPtr = (Var *) srcPtr->internalRep.twoPtrValue.ptr2;
+ Namespace *nsPtr = srcPtr->internalRep.twoPtrValue.ptr1;
+ register Var *varPtr = srcPtr->internalRep.twoPtrValue.ptr2;
- dupPtr->internalRep.twoPtrValue.ptr1 = (VOID *) nsPtr;
- dupPtr->internalRep.twoPtrValue.ptr2 = (VOID *) varPtr;
- varPtr->refCount++;
+ dupPtr->internalRep.twoPtrValue.ptr1 = nsPtr;
+ dupPtr->internalRep.twoPtrValue.ptr2 = varPtr;
+ if (TclIsVarInHash(varPtr)) {
+ varPtr->refCount++;
+ }
dupPtr->typePtr = &tclNsVarNameType;
}
+#endif
-/*
+/*
* parsedVarName -
*
* INTERNALREP DEFINITION:
- * twoPtrValue.ptr1 = pointer to the array name Tcl_Obj
- * (NULL if scalar)
- * twoPtrValue.ptr2 = pointer to the element name string
- * (owned by this Tcl_Obj), or NULL if
- * it is a scalar variable
+ * twoPtrValue.ptr1 = pointer to the array name Tcl_Obj (NULL if scalar)
+ * twoPtrValue.ptr2 = pointer to the element name string (owned by this
+ * Tcl_Obj), or NULL if it is a scalar variable
*/
-static void
-FreeParsedVarName(objPtr)
- Tcl_Obj *objPtr;
+static void
+FreeParsedVarName(
+ Tcl_Obj *objPtr)
{
- register Tcl_Obj *arrayPtr =
- (Tcl_Obj *) objPtr->internalRep.twoPtrValue.ptr1;
- register char *elem = (char *) objPtr->internalRep.twoPtrValue.ptr2;
-
+ register Tcl_Obj *arrayPtr = objPtr->internalRep.twoPtrValue.ptr1;
+ register char *elem = objPtr->internalRep.twoPtrValue.ptr2;
+
if (arrayPtr != NULL) {
TclDecrRefCount(arrayPtr);
ckfree(elem);
}
+ objPtr->typePtr = NULL;
}
static void
-DupParsedVarName(srcPtr, dupPtr)
- Tcl_Obj *srcPtr;
- Tcl_Obj *dupPtr;
+DupParsedVarName(
+ Tcl_Obj *srcPtr,
+ Tcl_Obj *dupPtr)
{
- register Tcl_Obj *arrayPtr =
- (Tcl_Obj *) srcPtr->internalRep.twoPtrValue.ptr1;
- register char *elem = (char *) srcPtr->internalRep.twoPtrValue.ptr2;
+ register Tcl_Obj *arrayPtr = srcPtr->internalRep.twoPtrValue.ptr1;
+ register char *elem = srcPtr->internalRep.twoPtrValue.ptr2;
char *elemCopy;
unsigned int elemLen;
@@ -5292,30 +4880,31 @@ DupParsedVarName(srcPtr, dupPtr)
elem = elemCopy;
}
- dupPtr->internalRep.twoPtrValue.ptr1 = (VOID *) arrayPtr;
- dupPtr->internalRep.twoPtrValue.ptr2 = (VOID *) elem;
+ dupPtr->internalRep.twoPtrValue.ptr1 = arrayPtr;
+ dupPtr->internalRep.twoPtrValue.ptr2 = elem;
dupPtr->typePtr = &tclParsedVarNameType;
}
static void
-UpdateParsedVarName(objPtr)
- Tcl_Obj *objPtr;
+UpdateParsedVarName(
+ Tcl_Obj *objPtr)
{
- Tcl_Obj *arrayPtr = (Tcl_Obj *) objPtr->internalRep.twoPtrValue.ptr1;
- char *part2 = (char *) objPtr->internalRep.twoPtrValue.ptr2;
+ Tcl_Obj *arrayPtr = objPtr->internalRep.twoPtrValue.ptr1;
+ char *part2 = objPtr->internalRep.twoPtrValue.ptr2;
char *part1, *p;
int len1, len2, totalLen;
if (arrayPtr == NULL) {
/*
- * This is a parsed scalar name: what is it
- * doing here?
+ * This is a parsed scalar name: what is it doing here?
*/
- panic("ERROR: scalar parsedVarName without a string rep.\n");
+
+ Tcl_Panic("scalar parsedVarName without a string rep");
}
- part1 = Tcl_GetStringFromObj(arrayPtr, &len1);
+
+ part1 = TclGetStringFromObj(arrayPtr, &len1);
len2 = strlen(part2);
-
+
totalLen = len1 + len2 + 2;
p = ckalloc((unsigned int) totalLen + 1);
objPtr->bytes = p;
@@ -5327,5 +4916,751 @@ UpdateParsedVarName(objPtr)
memcpy(p, part2, (unsigned int) len2);
p += len2;
*p++ = ')';
- *p = '\0';
+ *p = '\0';
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_FindNamespaceVar -- MOVED OVER from tclNamesp.c
+ *
+ * Searches for a namespace variable, a variable not local to a
+ * procedure. The variable can be either a scalar or an array, but may
+ * not be an element of an array.
+ *
+ * Results:
+ * Returns a token for the variable if it is found. Otherwise, if it
+ * can't be found or there is an error, returns NULL and leaves an error
+ * message in the interpreter's result object if "flags" contains
+ * TCL_LEAVE_ERR_MSG.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Var
+Tcl_FindNamespaceVar(
+ Tcl_Interp *interp, /* The interpreter in which to find the
+ * variable. */
+ const char *name, /* Variable's name. If it starts with "::",
+ * will be looked up in global namespace.
+ * Else, looked up first in contextNsPtr
+ * (current namespace if contextNsPtr is
+ * NULL), then in global namespace. */
+ Tcl_Namespace *contextNsPtr,/* Ignored if TCL_GLOBAL_ONLY flag set.
+ * Otherwise, points to namespace in which to
+ * resolve name. If NULL, look up name in the
+ * current namespace. */
+ int flags) /* An OR'd combination of: AVOID_RESOLVERS,
+ * TCL_GLOBAL_ONLY (look up name only in
+ * global namespace), TCL_NAMESPACE_ONLY (look
+ * up only in contextNsPtr, or the current
+ * namespace if contextNsPtr is NULL), and
+ * TCL_LEAVE_ERR_MSG. If both TCL_GLOBAL_ONLY
+ * and TCL_NAMESPACE_ONLY are given,
+ * TCL_GLOBAL_ONLY is ignored. */
+{
+ Tcl_Obj *namePtr = Tcl_NewStringObj(name, -1);
+ Tcl_Var var;
+
+ Tcl_IncrRefCount(namePtr);
+ var = ObjFindNamespaceVar(interp, namePtr, contextNsPtr, flags);
+ Tcl_DecrRefCount(namePtr);
+ return var;
+}
+
+static Tcl_Var
+ObjFindNamespaceVar(
+ Tcl_Interp *interp, /* The interpreter in which to find the
+ * variable. */
+ Tcl_Obj *namePtr, /* Variable's name. If it starts with "::",
+ * will be looked up in global namespace.
+ * Else, looked up first in contextNsPtr
+ * (current namespace if contextNsPtr is
+ * NULL), then in global namespace. */
+ Tcl_Namespace *contextNsPtr,/* Ignored if TCL_GLOBAL_ONLY flag set.
+ * Otherwise, points to namespace in which to
+ * resolve name. If NULL, look up name in the
+ * current namespace. */
+ int flags) /* An OR'd combination of: AVOID_RESOLVERS,
+ * TCL_GLOBAL_ONLY (look up name only in
+ * global namespace), TCL_NAMESPACE_ONLY (look
+ * up only in contextNsPtr, or the current
+ * namespace if contextNsPtr is NULL), and
+ * TCL_LEAVE_ERR_MSG. If both TCL_GLOBAL_ONLY
+ * and TCL_NAMESPACE_ONLY are given,
+ * TCL_GLOBAL_ONLY is ignored. */
+{
+ Interp *iPtr = (Interp *) interp;
+ ResolverScheme *resPtr;
+ Namespace *nsPtr[2], *cxtNsPtr;
+ const char *simpleName;
+ Var *varPtr;
+ register int search;
+ int result;
+ Tcl_Var var;
+ Tcl_Obj *simpleNamePtr;
+ char *name = TclGetString(namePtr);
+
+ /*
+ * If this namespace has a variable resolver, then give it first crack at
+ * the variable resolution. It may return a Tcl_Var value, it may signal
+ * to continue onward, or it may signal an error.
+ */
+
+ if ((flags & TCL_GLOBAL_ONLY) != 0) {
+ cxtNsPtr = (Namespace *) TclGetGlobalNamespace(interp);
+ } else if (contextNsPtr != NULL) {
+ cxtNsPtr = (Namespace *) contextNsPtr;
+ } else {
+ cxtNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
+ }
+
+ if (!(flags & AVOID_RESOLVERS) &&
+ (cxtNsPtr->varResProc != NULL || iPtr->resolverPtr != NULL)) {
+ resPtr = iPtr->resolverPtr;
+
+ if (cxtNsPtr->varResProc) {
+ result = (*cxtNsPtr->varResProc)(interp, name,
+ (Tcl_Namespace *) cxtNsPtr, flags, &var);
+ } else {
+ result = TCL_CONTINUE;
+ }
+
+ while (result == TCL_CONTINUE && resPtr) {
+ if (resPtr->varResProc) {
+ result = (*resPtr->varResProc)(interp, name,
+ (Tcl_Namespace *) cxtNsPtr, flags, &var);
+ }
+ resPtr = resPtr->nextPtr;
+ }
+
+ if (result == TCL_OK) {
+ return var;
+ } else if (result != TCL_CONTINUE) {
+ return (Tcl_Var) NULL;
+ }
+ }
+
+ /*
+ * Find the namespace(s) that contain the variable.
+ */
+
+ TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr,
+ flags, &nsPtr[0], &nsPtr[1], &cxtNsPtr, &simpleName);
+
+ /*
+ * Look for the variable in the variable table of its namespace. Be sure
+ * to check both possible search paths: from the specified namespace
+ * context and from the global namespace.
+ */
+
+ varPtr = NULL;
+ if (simpleName != name) {
+ simpleNamePtr = Tcl_NewStringObj(simpleName, -1);
+ Tcl_IncrRefCount(simpleNamePtr);
+ } else {
+ simpleNamePtr = namePtr;
+ }
+
+ for (search = 0; (search < 2) && (varPtr == NULL); search++) {
+ if ((nsPtr[search] != NULL) && (simpleName != NULL)) {
+ varPtr = VarHashFindVar(&nsPtr[search]->varTable, simpleNamePtr);
+ }
+ }
+ if (simpleName != name) {
+ Tcl_DecrRefCount(simpleNamePtr);
+ }
+ if ((varPtr == NULL) && (flags & TCL_LEAVE_ERR_MSG)) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "unknown variable \"", name, "\"", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", name, NULL);
+ }
+ return (Tcl_Var) varPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InfoVarsCmd -- (moved over from tclCmdIL.c)
+ *
+ * Called to implement the "info vars" command that returns the list of
+ * variables in the interpreter that match an optional pattern. The
+ * pattern, if any, consists of an optional sequence of namespace names
+ * separated by "::" qualifiers, which is followed by a glob-style
+ * pattern that restricts which variables are returned. Handles the
+ * following syntax:
+ *
+ * info vars ?pattern?
+ *
+ * Results:
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ *
+ * Side effects:
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclInfoVarsCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Interp *iPtr = (Interp *) interp;
+ char *varName, *pattern;
+ const char *simplePattern;
+ Tcl_HashSearch search;
+ Var *varPtr;
+ Namespace *nsPtr;
+ Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
+ Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
+ Tcl_Obj *listPtr, *elemObjPtr;
+ int specificNsInPattern = 0;/* Init. to avoid compiler warning. */
+ Tcl_Obj *simplePatternPtr = NULL, *varNamePtr;
+
+ /*
+ * Get the pattern and find the "effective namespace" in which to list
+ * variables. We only use this effective namespace if there's no active
+ * Tcl procedure frame.
+ */
+
+ if (objc == 1) {
+ simplePattern = NULL;
+ nsPtr = currNsPtr;
+ specificNsInPattern = 0;
+ } else if (objc == 2) {
+ /*
+ * From the pattern, get the effective namespace and the simple
+ * pattern (no namespace qualifiers or ::'s) at the end. If an error
+ * was found while parsing the pattern, return it. Otherwise, if the
+ * namespace wasn't found, just leave nsPtr NULL: we will return an
+ * empty list since no variables there can be found.
+ */
+
+ Namespace *dummy1NsPtr, *dummy2NsPtr;
+
+ pattern = TclGetString(objv[1]);
+ TclGetNamespaceForQualName(interp, pattern, (Namespace *) NULL,
+ /*flags*/ 0, &nsPtr, &dummy1NsPtr, &dummy2NsPtr,
+ &simplePattern);
+
+ if (nsPtr != NULL) { /* We successfully found the pattern's ns. */
+ specificNsInPattern = (strcmp(simplePattern, pattern) != 0);
+ if (simplePattern == pattern) {
+ simplePatternPtr = objv[1];
+ } else {
+ simplePatternPtr = Tcl_NewStringObj(simplePattern, -1);
+ }
+ Tcl_IncrRefCount(simplePatternPtr);
+ }
+ } else {
+ Tcl_WrongNumArgs(interp, 1, objv, "?pattern?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * If the namespace specified in the pattern wasn't found, just return.
+ */
+
+ if (nsPtr == NULL) {
+ return TCL_OK;
+ }
+
+ listPtr = Tcl_NewListObj(0, NULL);
+
+ if (!(iPtr->varFramePtr->isProcCallFrame & FRAME_IS_PROC)
+ || specificNsInPattern) {
+ /*
+ * There is no frame pointer, the frame pointer was pushed only to
+ * activate a namespace, or we are in a procedure call frame but a
+ * specific namespace was specified. Create a list containing only the
+ * variables in the effective namespace's variable table.
+ */
+
+ if (simplePattern && TclMatchIsTrivial(simplePattern)) {
+ /*
+ * If we can just do hash lookups, that simplifies things a lot.
+ */
+
+ varPtr = VarHashFindVar(&nsPtr->varTable, simplePatternPtr);
+ if (varPtr) {
+ if (!TclIsVarUndefined(varPtr)
+ || TclIsVarNamespaceVar(varPtr)) {
+ if (specificNsInPattern) {
+ elemObjPtr = Tcl_NewObj();
+ Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr,
+ elemObjPtr);
+ } else {
+ elemObjPtr = VarHashGetKey(varPtr);
+ }
+ Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
+ }
+ } else if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
+ varPtr = VarHashFindVar(&globalNsPtr->varTable,
+ simplePatternPtr);
+ if (varPtr) {
+ if (!TclIsVarUndefined(varPtr)
+ || TclIsVarNamespaceVar(varPtr)) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ VarHashGetKey(varPtr));
+ }
+ }
+ }
+ } else {
+ /*
+ * Have to scan the tables of variables.
+ */
+
+ varPtr = VarHashFirstVar(&nsPtr->varTable, &search);
+ while (varPtr) {
+ if (!TclIsVarUndefined(varPtr)
+ || TclIsVarNamespaceVar(varPtr)) {
+ varNamePtr = VarHashGetKey(varPtr);
+ varName = TclGetString(varNamePtr);
+ if ((simplePattern == NULL)
+ || Tcl_StringMatch(varName, simplePattern)) {
+ if (specificNsInPattern) {
+ elemObjPtr = Tcl_NewObj();
+ Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr,
+ elemObjPtr);
+ } else {
+ elemObjPtr = varNamePtr;
+ }
+ Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
+ }
+ }
+ varPtr = VarHashNextVar(&search);
+ }
+
+ /*
+ * If the effective namespace isn't the global :: namespace, and a
+ * specific namespace wasn't requested in the pattern (i.e., the
+ * pattern only specifies variable names), then add in all global
+ * :: variables that match the simple pattern. Of course, add in
+ * only those variables that aren't hidden by a variable in the
+ * effective namespace.
+ */
+
+ if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
+ varPtr = VarHashFirstVar(&globalNsPtr->varTable,&search);
+ while (varPtr) {
+ if (!TclIsVarUndefined(varPtr)
+ || TclIsVarNamespaceVar(varPtr)) {
+ varNamePtr = VarHashGetKey(varPtr);
+ varName = TclGetString(varNamePtr);
+ if ((simplePattern == NULL)
+ || Tcl_StringMatch(varName, simplePattern)) {
+ if (VarHashFindVar(&nsPtr->varTable,
+ varNamePtr) == NULL) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ varNamePtr);
+ }
+ }
+ }
+ varPtr = VarHashNextVar(&search);
+ }
+ }
+ }
+ } else if (((Interp *)interp)->varFramePtr->procPtr != NULL) {
+ AppendLocals(interp, listPtr, simplePatternPtr, 1);
+ }
+
+ if (simplePatternPtr) {
+ Tcl_DecrRefCount(simplePatternPtr);
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InfoGlobalsCmd -- (moved over from tclCmdIL.c)
+ *
+ * Called to implement the "info globals" command that returns the list
+ * of global variables matching an optional pattern. Handles the
+ * following syntax:
+ *
+ * info globals ?pattern?
+ *
+ * Results:
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ *
+ * Side effects:
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclInfoGlobalsCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ char *varName, *pattern;
+ Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
+ Tcl_HashSearch search;
+ Var *varPtr;
+ Tcl_Obj *listPtr, *varNamePtr, *patternPtr;
+
+ if (objc == 1) {
+ pattern = NULL;
+ } else if (objc == 2) {
+ pattern = TclGetString(objv[1]);
+
+ /*
+ * Strip leading global-namespace qualifiers. [Bug 1057461]
+ */
+
+ if (pattern[0] == ':' && pattern[1] == ':') {
+ while (*pattern == ':') {
+ pattern++;
+ }
+ }
+ } else {
+ Tcl_WrongNumArgs(interp, 1, objv, "?pattern?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Scan through the global :: namespace's variable table and create a list
+ * of all global variables that match the pattern.
+ */
+
+ listPtr = Tcl_NewListObj(0, NULL);
+ if (pattern != NULL && TclMatchIsTrivial(pattern)) {
+ if (pattern == TclGetString(objv[1])) {
+ patternPtr = objv[1];
+ } else {
+ patternPtr = Tcl_NewStringObj(pattern, -1);
+ }
+ Tcl_IncrRefCount(patternPtr);
+
+ varPtr = VarHashFindVar(&globalNsPtr->varTable, patternPtr);
+ if (varPtr) {
+ if (!TclIsVarUndefined(varPtr)) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ VarHashGetKey(varPtr));
+ }
+ }
+ Tcl_DecrRefCount(patternPtr);
+ } else {
+ for (varPtr = VarHashFirstVar(&globalNsPtr->varTable, &search);
+ varPtr != NULL;
+ varPtr = VarHashNextVar(&search)) {
+ if (TclIsVarUndefined(varPtr)) {
+ continue;
+ }
+ varNamePtr = VarHashGetKey(varPtr);
+ varName = TclGetString(varNamePtr);
+ if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr, varNamePtr);
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclInfoLocalsCmd -- (moved over from tclCmdIl.c)
+ *
+ * Called to implement the "info locals" command to return a list of
+ * local variables that match an optional pattern. Handles the following
+ * syntax:
+ *
+ * info locals ?pattern?
+ *
+ * Results:
+ * Returns TCL_OK if successful and TCL_ERROR if there is an error.
+ *
+ * Side effects:
+ * Returns a result in the interpreter's result object. If there is an
+ * error, the result is an error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclInfoLocalsCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Interp *iPtr = (Interp *) interp;
+ Tcl_Obj *patternPtr;
+ Tcl_Obj *listPtr;
+
+ if (objc == 1) {
+ patternPtr = NULL;
+ } else if (objc == 2) {
+ patternPtr = objv[1];
+ } else {
+ Tcl_WrongNumArgs(interp, 1, objv, "?pattern?");
+ return TCL_ERROR;
+ }
+
+ if (!(iPtr->varFramePtr->isProcCallFrame & FRAME_IS_PROC )) {
+ return TCL_OK;
+ }
+
+ /*
+ * Return a list containing names of first the compiled locals (i.e. the
+ * ones stored in the call frame), then the variables in the local hash
+ * table (if one exists).
+ */
+
+ listPtr = Tcl_NewListObj(0, NULL);
+ AppendLocals(interp, listPtr, patternPtr, 0);
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AppendLocals --
+ *
+ * Append the local variables for the current frame to the specified list
+ * object.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+AppendLocals(
+ Tcl_Interp *interp, /* Current interpreter. */
+ Tcl_Obj *listPtr, /* List object to append names to. */
+ Tcl_Obj *patternPtr, /* Pattern to match against. */
+ int includeLinks) /* 1 if upvars should be included, else 0. */
+{
+ Interp *iPtr = (Interp *) interp;
+ Var *varPtr;
+ int i, localVarCt;
+ Tcl_Obj **varNamePtr;
+ char *varName;
+ TclVarHashTable *localVarTablePtr;
+ Tcl_HashSearch search;
+ const char *pattern = patternPtr? TclGetString(patternPtr) : NULL;
+ Tcl_Obj *objNamePtr;
+
+ localVarCt = iPtr->varFramePtr->numCompiledLocals;
+ varPtr = iPtr->varFramePtr->compiledLocals;
+ localVarTablePtr = iPtr->varFramePtr->varTablePtr;
+ varNamePtr = &iPtr->varFramePtr->localCachePtr->varName0;
+
+ for (i = 0; i < localVarCt; i++, varNamePtr++) {
+ /*
+ * Skip nameless (temporary) variables and undefined variables.
+ */
+
+ if (*varNamePtr && !TclIsVarUndefined(varPtr)
+ && (includeLinks || !TclIsVarLink(varPtr))) {
+ varName = TclGetString(*varNamePtr);
+ if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr, *varNamePtr);
+ }
+ }
+ varPtr++;
+ }
+
+ /*
+ * Do nothing if no local variables.
+ */
+
+ if (localVarTablePtr == NULL) {
+ return;
+ }
+
+ /*
+ * Check for the simple and fast case.
+ */
+
+ if ((pattern != NULL) && TclMatchIsTrivial(pattern)) {
+ varPtr = VarHashFindVar(localVarTablePtr, patternPtr);
+ if (varPtr != NULL) {
+ if (!TclIsVarUndefined(varPtr)
+ && (includeLinks || !TclIsVarLink(varPtr))) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ VarHashGetKey(varPtr));
+ }
+ }
+ return;
+ }
+
+ /*
+ * Scan over and process all local variables.
+ */
+
+ for (varPtr = VarHashFirstVar(localVarTablePtr, &search);
+ varPtr != NULL;
+ varPtr = VarHashNextVar(&search)) {
+ if (!TclIsVarUndefined(varPtr)
+ && (includeLinks || !TclIsVarLink(varPtr))) {
+ objNamePtr = VarHashGetKey(varPtr);
+ varName = TclGetString(objNamePtr);
+ if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr, objNamePtr);
+ }
+ }
+ }
+}
+
+/*
+ * Hash table implementation - first, just copy and adapt the obj key stuff
+ */
+
+void
+TclInitVarHashTable(
+ TclVarHashTable *tablePtr,
+ Namespace *nsPtr)
+{
+ Tcl_InitCustomHashTable(&tablePtr->table,
+ TCL_CUSTOM_TYPE_KEYS, &tclVarHashKeyType);
+ tablePtr->nsPtr = nsPtr;
+}
+
+static Tcl_HashEntry *
+AllocVarEntry(
+ Tcl_HashTable *tablePtr, /* Hash table. */
+ void *keyPtr) /* Key to store in the hash table entry. */
+{
+ Tcl_Obj *objPtr = (Tcl_Obj *) keyPtr;
+ Tcl_HashEntry *hPtr;
+ Var *varPtr;
+
+ varPtr = (Var *) ckalloc(sizeof(VarInHash));
+ varPtr->flags = VAR_IN_HASHTABLE;
+ varPtr->value.objPtr = NULL;
+ VarHashRefCount(varPtr) = 1;
+
+ hPtr = &(((VarInHash *)varPtr)->entry);
+ Tcl_SetHashValue(hPtr, varPtr);
+ hPtr->key.objPtr = objPtr;
+ Tcl_IncrRefCount(objPtr);
+
+ return hPtr;
}
+
+static void
+FreeVarEntry(
+ Tcl_HashEntry *hPtr)
+{
+ Var *varPtr = VarHashGetValue(hPtr);
+ Tcl_Obj *objPtr = hPtr->key.objPtr;
+
+ if (TclIsVarUndefined(varPtr) && !TclIsVarTraced(varPtr)
+ && (VarHashRefCount(varPtr) == 1)) {
+ ckfree((char *) varPtr);
+ } else {
+ VarHashInvalidateEntry(varPtr);
+ TclSetVarUndefined(varPtr);
+ VarHashRefCount(varPtr)--;
+ }
+ Tcl_DecrRefCount(objPtr);
+}
+
+static int
+CompareVarKeys(
+ void *keyPtr, /* New key to compare. */
+ Tcl_HashEntry *hPtr) /* Existing key to compare. */
+{
+ Tcl_Obj *objPtr1 = (Tcl_Obj *) keyPtr;
+ Tcl_Obj *objPtr2 = hPtr->key.objPtr;
+ register const char *p1, *p2;
+ register int l1, l2;
+
+ /*
+ * If the object pointers are the same then they match.
+ */
+
+ if (objPtr1 == objPtr2) {
+ return 1;
+ }
+
+ /*
+ * Don't use Tcl_GetStringFromObj as it would prevent l1 and l2 being in a
+ * register.
+ */
+
+ p1 = TclGetString(objPtr1);
+ l1 = objPtr1->length;
+ p2 = TclGetString(objPtr2);
+ l2 = objPtr2->length;
+
+ /*
+ * Only compare if the string representations are of the same length.
+ */
+
+ if (l1 == l2) {
+ for (;; p1++, p2++, l1--) {
+ if (*p1 != *p2) {
+ break;
+ }
+ if (l1 == 0) {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static unsigned int
+HashVarKey(
+ Tcl_HashTable *tablePtr, /* Hash table. */
+ void *keyPtr) /* Key from which to compute hash value. */
+{
+ Tcl_Obj *objPtr = (Tcl_Obj *) keyPtr;
+ const char *string = TclGetString(objPtr);
+ int length = objPtr->length;
+ unsigned int result = 0;
+ int i;
+
+ /*
+ * I tried a zillion different hash functions and asked many other people
+ * for advice. Many people had their own favorite functions, all
+ * different, but no-one had much idea why they were good ones. I chose
+ * the one below (multiply by 9 and add new character) because of the
+ * following reasons:
+ *
+ * 1. Multiplying by 10 is perfect for keys that are decimal strings, and
+ * multiplying by 9 is just about as good.
+ * 2. Times-9 is (shift-left-3) plus (old). This means that each
+ * character's bits hang around in the low-order bits of the hash value
+ * for ever, plus they spread fairly rapidly up to the high-order bits
+ * to fill out the hash value. This seems works well both for decimal
+ * and non-decimal strings.
+ */
+
+ for (i=0 ; i<length ; i++) {
+ result += (result << 3) + string[i];
+ }
+ return result;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/generic/tommath.h b/generic/tommath.h
new file mode 100644
index 0000000..028a84d
--- /dev/null
+++ b/generic/tommath.h
@@ -0,0 +1 @@
+#include "tclTomMathInt.h"
diff --git a/library/auto.tcl b/library/auto.tcl
index 519388d..55fc90f 100644
--- a/library/auto.tcl
+++ b/library/auto.tcl
@@ -14,24 +14,27 @@
#
# Destroy all cached information for auto-loading and auto-execution,
# so that the information gets recomputed the next time it's needed.
-# Also delete any procedures that are listed in the auto-load index
-# except those defined in this file.
+# Also delete any commands that are listed in the auto-load index.
#
# Arguments:
# None.
proc auto_reset {} {
- global auto_execs auto_index auto_oldpath
- foreach p [info procs] {
- if {[info exists auto_index($p)] && ![string match auto_* $p]
- && ([lsearch -exact {unknown pkg_mkIndex tclPkgSetup
- tcl_findLibrary pkg_compareExtension
- tclPkgUnknown tcl::MacOSXPkgUnknown
- tcl::MacPkgUnknown} $p] < 0)} {
- rename $p {}
+ if {[array exists ::auto_index]} {
+ foreach cmdName [array names ::auto_index] {
+ set fqcn [namespace which $cmdName]
+ if {$fqcn eq ""} {continue}
+ rename $fqcn {}
+ }
+ }
+ unset -nocomplain ::auto_execs ::auto_index ::tcl::auto_oldpath
+ if {[catch {llength $::auto_path}]} {
+ set ::auto_path [list [info library]]
+ } else {
+ if {[info library] ni $::auto_path} {
+ lappend ::auto_path [info library]
}
}
- unset -nocomplain auto_execs auto_index auto_oldpath
}
# tcl_findLibrary --
@@ -50,7 +53,7 @@ proc auto_reset {} {
proc tcl_findLibrary {basename version patch initScript enVarName varName} {
upvar #0 $varName the_library
- global env errorInfo
+ global env
set dirs {}
set errors {}
@@ -73,13 +76,12 @@ proc tcl_findLibrary {basename version patch initScript enVarName varName} {
# 2. In the package script directory registered within
# the configuration of the package itself.
- #
- # Only do this for Tcl 8.5+, when Tcl_RegsiterConfig() is available.
- #if {[catch {
- # ::${basename}::pkgconfig get scriptdir,runtime
- #} value] == 0} {
- # lappend dirs $value
- #}
+
+ if {[catch {
+ ::${basename}::pkgconfig get scriptdir,runtime
+ } value] == 0} {
+ lappend dirs $value
+ }
# 3. Relative to auto_path directories. This checks relative to the
# Tcl library as well as allowing loading of libraries added to the
@@ -97,24 +99,22 @@ proc tcl_findLibrary {basename version patch initScript enVarName varName} {
# ../lib/foo1.0 (From bin directory in install hierarchy)
# ../../lib/foo1.0 (From bin/arch directory in install hierarchy)
# ../library (From unix directory in build hierarchy)
- set parentDir [file dirname [file dirname [info nameofexecutable]]]
- set grandParentDir [file dirname $parentDir]
- lappend dirs [file join $parentDir lib $basename$version]
- lappend dirs [file join $grandParentDir lib $basename$version]
- lappend dirs [file join $parentDir library]
-
+ #
# Remaining locations are out of date (when relevant, they ought
- # to be covered by the $::auto_path seach above).
+ # to be covered by the $::auto_path seach above) and disabled.
#
# ../../library (From unix/arch directory in build hierarchy)
# ../../foo1.0.1/library
# (From unix directory in parallel build hierarchy)
# ../../../foo1.0.1/library
# (From unix/arch directory in parallel build hierarchy)
- #
- # For the sake of extra compatibility safety, we keep adding these
- # paths during the 8.4.* release series.
- if {1} {
+
+ set parentDir [file dirname [file dirname [info nameofexecutable]]]
+ set grandParentDir [file dirname $parentDir]
+ lappend dirs [file join $parentDir lib $basename$version]
+ lappend dirs [file join $grandParentDir lib $basename$version]
+ lappend dirs [file join $parentDir library]
+ if {0} {
lappend dirs [file join $grandParentDir library]
lappend dirs [file join $grandParentDir $basename$patch library]
lappend dirs [file join [file dirname $grandParentDir] \
@@ -124,17 +124,11 @@ proc tcl_findLibrary {basename version patch initScript enVarName varName} {
# uniquify $dirs in order
array set seen {}
foreach i $dirs {
- # For Tcl 8.4.9, we've disabled the use of [file normalize] here.
- # This means that two different path names that are the same path
- # in normalized form, will both remain on the search path. There
- # should be no harm in that, just a bit more file system access
- # than is strictly necessary.
- #
- # [file normalize] has been disabled because of reports it has
- # caused difficulties with the freewrap utility. To keep
- # compatibility with freewrap's needs, we'll keep this disabled
- # throughout the 8.4.x (x >= 9) releases. See Bug 1072136.
- if {1 || [interp issafe]} {
+ # Take note that the [file normalize] below has been noted to
+ # cause difficulties for the freewrap utility. See Bug 1072136.
+ # Until freewrap resolves the matter, one might work around the
+ # problem by disabling that branch.
+ if {[interp issafe]} {
set norm $i
} else {
set norm [file normalize $i]
@@ -152,10 +146,11 @@ proc tcl_findLibrary {basename version patch initScript enVarName varName} {
# we have a source command, but no file exists command
if {[interp issafe] || [file exists $file]} {
- if {![catch {uplevel #0 [list source $file]} msg]} {
+ if {![catch {uplevel #0 [list source $file]} msg opts]} {
return
} else {
- append errors "$file: $msg\n$errorInfo\n"
+ append errors "$file: $msg\n"
+ append errors [dict get $opts -errorinfo]\n
}
}
}
@@ -195,8 +190,6 @@ if {[interp issafe]} {
# are given auto_mkindex will look for *.tcl.
proc auto_mkindex {dir args} {
- global errorCode errorInfo
-
if {[interp issafe]} {
error "can't generate index within safe interpreter"
}
@@ -217,14 +210,12 @@ proc auto_mkindex {dir args} {
}
auto_mkindex_parser::init
- foreach file [eval [linsert $args 0 glob --]] {
- if {[catch {auto_mkindex_parser::mkindex $file} msg] == 0} {
+ foreach file [glob -- {*}$args] {
+ if {[catch {auto_mkindex_parser::mkindex $file} msg opts] == 0} {
append index $msg
} else {
- set code $errorCode
- set info $errorInfo
cd $oldDir
- error $msg $info $code
+ return -options $opts $msg
}
}
auto_mkindex_parser::cleanup
@@ -239,7 +230,6 @@ proc auto_mkindex {dir args} {
# code for "proc" at the beginning of the line.
proc auto_mkindex_old {dir args} {
- global errorCode errorInfo
set oldDir [pwd]
cd $dir
set dir [pwd]
@@ -253,7 +243,7 @@ proc auto_mkindex_old {dir args} {
if {[llength $args] == 0} {
set args *.tcl
}
- foreach file [eval [linsert $args 0 glob --]] {
+ foreach file [glob -- {*}$args] {
set f ""
set error [catch {
set f [open $file]
@@ -265,13 +255,11 @@ proc auto_mkindex_old {dir args} {
}
}
close $f
- } msg]
+ } msg opts]
if {$error} {
- set code $errorCode
- set info $errorInfo
catch {close $f}
cd $oldDir
- error $msg $info $code
+ return -options $opts $msg
}
}
set f ""
@@ -280,13 +268,12 @@ proc auto_mkindex_old {dir args} {
puts -nonewline $f $index
close $f
cd $oldDir
- } msg]
+ } msg opts]
if {$error} {
- set code $errorCode
- set info $errorInfo
catch {close $f}
cd $oldDir
error $msg $info $code
+ return -options $opts $msg
}
}
@@ -301,7 +288,10 @@ namespace eval auto_mkindex_parser {
variable scriptFile "" ;# name of file being processed
variable contextStack "" ;# stack of namespace scopes
variable imports "" ;# keeps track of all imported cmds
- variable initCommands "" ;# list of commands that create aliases
+ variable initCommands ;# list of commands that create aliases
+ if {![info exists initCommands]} {
+ set initCommands [list]
+ }
proc init {} {
variable parser
@@ -371,8 +361,8 @@ proc auto_mkindex_parser::mkindex {file} {
# in case there were any $ in the proc name. This will cause a problem
# if somebody actually tries to have a \0 in their proc name. Too bad
# for them.
- set contents [string map "$ \u0000" $contents]
-
+ set contents [string map [list \$ \0] $contents]
+
set index ""
set contextStack ""
set imports ""
@@ -516,10 +506,14 @@ proc auto_mkindex_parser::fullname {name} {
} elseif {![string match ::* $name]} {
set name "::$name"
}
-
+
# Earlier, mkindex replaced all $'s with \0. Now, we have to reverse
# that replacement.
- return [string map "\u0000 $" $name]
+ return [string map [list \0 \$] $name]
+}
+
+if {[llength $::auto_mkindex_parser::initCommands]} {
+ return
}
# Register all of the procedures for the auto_mkindex parser that
diff --git a/library/clock.tcl b/library/clock.tcl
new file mode 100644
index 0000000..8bce49f
--- /dev/null
+++ b/library/clock.tcl
@@ -0,0 +1,4688 @@
+#----------------------------------------------------------------------
+#
+# clock.tcl --
+#
+# This file implements the portions of the [clock] ensemble that
+# are coded in Tcl. Refer to the users' manual to see the description
+# of the [clock] command and its subcommands.
+#
+#
+#----------------------------------------------------------------------
+#
+# Copyright (c) 2004,2005,2006,2007 by Kevin B. Kenny
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+#----------------------------------------------------------------------
+
+# We must have message catalogs that support the root locale, and
+# we need access to the Registry on Windows systems.
+
+uplevel \#0 {
+ package require msgcat 1.4
+ if { $::tcl_platform(platform) eq {windows} } {
+ if { [catch { package require registry 1.1 }] } {
+ namespace eval ::tcl::clock [list variable NoRegistry {}]
+ }
+ }
+}
+
+# Put the library directory into the namespace for the ensemble
+# so that the library code can find message catalogs and time zone
+# definition files.
+
+namespace eval ::tcl::clock \
+ [list variable LibDir [file dirname [info script]]]
+
+#----------------------------------------------------------------------
+#
+# clock --
+#
+# Manipulate times.
+#
+# The 'clock' command manipulates time. Refer to the user documentation
+# for the available subcommands and what they do.
+#
+#----------------------------------------------------------------------
+
+namespace eval ::tcl::clock {
+
+ # Export the subcommands
+
+ namespace export format
+ namespace export clicks
+ namespace export microseconds
+ namespace export milliseconds
+ namespace export scan
+ namespace export seconds
+ namespace export add
+
+ # Import the message catalog commands that we use.
+
+ namespace import ::msgcat::mcload
+ namespace import ::msgcat::mclocale
+
+}
+
+#----------------------------------------------------------------------
+#
+# ::tcl::clock::Initialize --
+#
+# Finish initializing the 'clock' subsystem
+#
+# Results:
+# None.
+#
+# Side effects:
+# Namespace variable in the 'clock' subsystem are initialized.
+#
+# The '::tcl::clock::Initialize' procedure initializes the namespace
+# variables and root locale message catalog for the 'clock' subsystem.
+# It is broken into a procedure rather than simply evaluated as a script
+# so that it will be able to use local variables, avoiding the dangers
+# of 'creative writing' as in Bug 1185933.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::Initialize {} {
+
+ rename ::tcl::clock::Initialize {}
+
+ variable LibDir
+
+ # Define the Greenwich time zone
+
+ proc InitTZData {} {
+ variable TZData
+ array unset TZData
+ set TZData(:Etc/GMT) {
+ {-9223372036854775808 0 0 GMT}
+ }
+ set TZData(:GMT) $TZData(:Etc/GMT)
+ set TZData(:Etc/UTC) {
+ {-9223372036854775808 0 0 UTC}
+ }
+ set TZData(:UTC) $TZData(:Etc/UTC)
+ set TZData(:localtime) {}
+ }
+ InitTZData
+
+ # Define the message catalog for the root locale.
+
+ ::msgcat::mcmset {} {
+ AM {am}
+ BCE {B.C.E.}
+ CE {C.E.}
+ DATE_FORMAT {%m/%d/%Y}
+ DATE_TIME_FORMAT {%a %b %e %H:%M:%S %Y}
+ DAYS_OF_WEEK_ABBREV {
+ Sun Mon Tue Wed Thu Fri Sat
+ }
+ DAYS_OF_WEEK_FULL {
+ Sunday Monday Tuesday Wednesday Thursday Friday Saturday
+ }
+ GREGORIAN_CHANGE_DATE 2299161
+ LOCALE_DATE_FORMAT {%m/%d/%Y}
+ LOCALE_DATE_TIME_FORMAT {%a %b %e %H:%M:%S %Y}
+ LOCALE_ERAS {}
+ LOCALE_NUMERALS {
+ 00 01 02 03 04 05 06 07 08 09
+ 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
+ }
+ LOCALE_TIME_FORMAT {%H:%M:%S}
+ LOCALE_YEAR_FORMAT {%EC%Ey}
+ MONTHS_ABBREV {
+ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
+ }
+ MONTHS_FULL {
+ January February March
+ April May June
+ July August September
+ October November December
+ }
+ PM {pm}
+ TIME_FORMAT {%H:%M:%S}
+ TIME_FORMAT_12 {%I:%M:%S %P}
+ TIME_FORMAT_24 {%H:%M}
+ TIME_FORMAT_24_SECS {%H:%M:%S}
+ }
+
+ # Define a few Gregorian change dates for other locales. In most cases
+ # the change date follows a language, because a nation's colonies changed
+ # at the same time as the nation itself. In many cases, different
+ # national boundaries existed; the dominating rule is to follow the
+ # nation's capital.
+
+ # Italy, Spain, Portugal, Poland
+
+ ::msgcat::mcset it GREGORIAN_CHANGE_DATE 2299161
+ ::msgcat::mcset es GREGORIAN_CHANGE_DATE 2299161
+ ::msgcat::mcset pt GREGORIAN_CHANGE_DATE 2299161
+ ::msgcat::mcset pl GREGORIAN_CHANGE_DATE 2299161
+
+ # France, Austria
+
+ ::msgcat::mcset fr GREGORIAN_CHANGE_DATE 2299227
+
+ # For Belgium, we follow Southern Netherlands; Liege Diocese
+ # changed several weeks later.
+
+ ::msgcat::mcset fr_BE GREGORIAN_CHANGE_DATE 2299238
+ ::msgcat::mcset nl_BE GREGORIAN_CHANGE_DATE 2299238
+
+ # Austria
+
+ ::msgcat::mcset de_AT GREGORIAN_CHANGE_DATE 2299527
+
+ # Hungary
+
+ ::msgcat::mcset hu GREGORIAN_CHANGE_DATE 2301004
+
+ # Germany, Norway, Denmark (Catholic Germany changed earlier)
+
+ ::msgcat::mcset de_DE GREGORIAN_CHANGE_DATE 2342032
+ ::msgcat::mcset nb GREGORIAN_CHANGE_DATE 2342032
+ ::msgcat::mcset nn GREGORIAN_CHANGE_DATE 2342032
+ ::msgcat::mcset no GREGORIAN_CHANGE_DATE 2342032
+ ::msgcat::mcset da GREGORIAN_CHANGE_DATE 2342032
+
+ # Holland (Brabant, Gelderland, Flanders, Friesland, etc. changed
+ # at various times)
+
+ ::msgcat::mcset nl GREGORIAN_CHANGE_DATE 2342165
+
+ # Protestant Switzerland (Catholic cantons changed earlier)
+
+ ::msgcat::mcset fr_CH GREGORIAN_CHANGE_DATE 2361342
+ ::msgcat::mcset it_CH GREGORIAN_CHANGE_DATE 2361342
+ ::msgcat::mcset de_CH GREGORIAN_CHANGE_DATE 2361342
+
+ # English speaking countries
+
+ ::msgcat::mcset en GREGORIAN_CHANGE_DATE 2361222
+
+ # Sweden (had several changes onto and off of the Gregorian calendar)
+
+ ::msgcat::mcset sv GREGORIAN_CHANGE_DATE 2361390
+
+ # Russia
+
+ ::msgcat::mcset ru GREGORIAN_CHANGE_DATE 2421639
+
+ # Romania (Transylvania changed earler - perhaps de_RO should show
+ # the earlier date?)
+
+ ::msgcat::mcset ro GREGORIAN_CHANGE_DATE 2422063
+
+ # Greece
+
+ ::msgcat::mcset el GREGORIAN_CHANGE_DATE 2423480
+
+ #------------------------------------------------------------------
+ #
+ # CONSTANTS
+ #
+ #------------------------------------------------------------------
+
+ # Paths at which binary time zone data for the Olson libraries
+ # are known to reside on various operating systems
+
+ variable ZoneinfoPaths {}
+ foreach path {
+ /usr/share/zoneinfo
+ /usr/share/lib/zoneinfo
+ /usr/lib/zoneinfo
+ /usr/local/etc/zoneinfo
+ } {
+ if { [file isdirectory $path] } {
+ lappend ZoneinfoPaths $path
+ }
+ }
+
+ # Define the directories for time zone data and message catalogs.
+
+ variable DataDir [file join $LibDir tzdata]
+ variable MsgDir [file join $LibDir msgs]
+
+ # Number of days in the months, in common years and leap years.
+
+ variable DaysInRomanMonthInCommonYear \
+ { 31 28 31 30 31 30 31 31 30 31 30 31 }
+ variable DaysInRomanMonthInLeapYear \
+ { 31 29 31 30 31 30 31 31 30 31 30 31 }
+ variable DaysInPriorMonthsInCommonYear [list 0]
+ variable DaysInPriorMonthsInLeapYear [list 0]
+ set i 0
+ foreach j $DaysInRomanMonthInCommonYear {
+ lappend DaysInPriorMonthsInCommonYear [incr i $j]
+ }
+ set i 0
+ foreach j $DaysInRomanMonthInLeapYear {
+ lappend DaysInPriorMonthsInLeapYear [incr i $j]
+ }
+
+ # Another epoch (Hi, Jeff!)
+
+ variable Roddenberry 1946
+
+ # Integer ranges
+
+ variable MINWIDE -9223372036854775808
+ variable MAXWIDE 9223372036854775807
+
+ # Day before Leap Day
+
+ variable FEB_28 58
+
+ # Translation table to map Windows TZI onto cities, so that
+ # the Olson rules can apply. In some cases the mapping is ambiguous,
+ # so it's wise to specify $::env(TCL_TZ) rather than simply depending
+ # on the system time zone.
+
+ # The keys are long lists of values obtained from the time zone
+ # information in the Registry. In order, the list elements are:
+ # Bias StandardBias DaylightBias
+ # StandardDate.wYear StandardDate.wMonth StandardDate.wDayOfWeek
+ # StandardDate.wDay StandardDate.wHour StandardDate.wMinute
+ # StandardDate.wSecond StandardDate.wMilliseconds
+ # DaylightDate.wYear DaylightDate.wMonth DaylightDate.wDayOfWeek
+ # DaylightDate.wDay DaylightDate.wHour DaylightDate.wMinute
+ # DaylightDate.wSecond DaylightDate.wMilliseconds
+ # The values are the names of time zones where those rules apply.
+ # There is considerable ambiguity in certain zones; an attempt has
+ # been made to make a reasonable guess, but this table needs to be
+ # taken with a grain of salt.
+
+ variable WinZoneInfo [dict create {*}{
+ {-43200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Kwajalein
+ {-39600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Midway
+ {-36000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Honolulu
+ {-32400 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Anchorage
+ {-28800 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Los_Angeles
+ {-28800 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Tijuana
+ {-25200 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Denver
+ {-25200 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Chihuahua
+ {-25200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Phoenix
+ {-21600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Regina
+ {-21600 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Chicago
+ {-21600 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Mexico_City
+ {-18000 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/New_York
+ {-18000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Indianapolis
+ {-14400 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Caracas
+ {-14400 0 3600 0 3 6 2 23 59 59 999 0 10 6 2 23 59 59 999}
+ :America/Santiago
+ {-14400 0 3600 0 2 0 5 2 0 0 0 0 11 0 1 2 0 0 0} :America/Manaus
+ {-14400 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Halifax
+ {-12600 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/St_Johns
+ {-10800 0 3600 0 2 0 2 2 0 0 0 0 10 0 3 2 0 0 0} :America/Sao_Paulo
+ {-10800 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Godthab
+ {-10800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Buenos_Aires
+ {-10800 0 3600 0 2 0 5 2 0 0 0 0 11 0 1 2 0 0 0} :America/Brasilia
+ {-10800 0 3600 0 3 0 2 2 0 0 0 0 10 0 1 2 0 0 0} :America/Montevideo
+ {-7200 0 3600 0 9 0 5 2 0 0 0 0 3 0 5 2 0 0 0} :America/Noronha
+ {-3600 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Atlantic/Azores
+ {-3600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Atlantic/Cape_Verde
+ {0 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :UTC
+ {0 0 3600 0 10 0 5 2 0 0 0 0 3 0 5 1 0 0 0} :Europe/London
+ {3600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Africa/Kinshasa
+ {3600 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :CET
+ {7200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Africa/Harare
+ {7200 0 3600 0 9 4 5 23 59 59 0 0 4 4 5 23 59 59 0}
+ :Africa/Cairo
+ {7200 0 3600 0 10 0 5 4 0 0 0 0 3 0 5 3 0 0 0} :Europe/Helsinki
+ {7200 0 3600 0 9 0 3 2 0 0 0 0 3 5 5 2 0 0 0} :Asia/Jerusalem
+ {7200 0 3600 0 9 0 5 1 0 0 0 0 3 0 5 0 0 0 0} :Europe/Bucharest
+ {7200 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Europe/Athens
+ {7200 0 3600 0 9 5 5 1 0 0 0 0 3 4 5 0 0 0 0} :Asia/Amman
+ {7200 0 3600 0 10 6 5 23 59 59 999 0 3 0 5 0 0 0 0}
+ :Asia/Beirut
+ {7200 0 -3600 0 4 0 1 2 0 0 0 0 9 0 1 2 0 0 0} :Africa/Windhoek
+ {10800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Riyadh
+ {10800 0 3600 0 10 0 1 4 0 0 0 0 4 0 1 3 0 0 0} :Asia/Baghdad
+ {10800 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Europe/Moscow
+ {12600 0 3600 0 9 2 4 2 0 0 0 0 3 0 1 2 0 0 0} :Asia/Tehran
+ {14400 0 3600 0 10 0 5 5 0 0 0 0 3 0 5 4 0 0 0} :Asia/Baku
+ {14400 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Muscat
+ {14400 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Asia/Tbilisi
+ {16200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Kabul
+ {18000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Karachi
+ {18000 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Asia/Yekaterinburg
+ {19800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Calcutta
+ {20700 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Katmandu
+ {21600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Dhaka
+ {21600 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Asia/Novosibirsk
+ {23400 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Rangoon
+ {25200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Bangkok
+ {25200 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Asia/Krasnoyarsk
+ {28800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Chongqing
+ {28800 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Asia/Irkutsk
+ {32400 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Tokyo
+ {32400 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Asia/Yakutsk
+ {34200 0 3600 0 3 0 5 3 0 0 0 0 10 0 5 2 0 0 0} :Australia/Adelaide
+ {34200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Australia/Darwin
+ {36000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Australia/Brisbane
+ {36000 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Asia/Vladivostok
+ {36000 0 3600 0 3 0 5 3 0 0 0 0 10 0 1 2 0 0 0} :Australia/Hobart
+ {36000 0 3600 0 3 0 5 3 0 0 0 0 10 0 5 2 0 0 0} :Australia/Sydney
+ {39600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Noumea
+ {43200 0 3600 0 3 0 3 3 0 0 0 0 10 0 1 2 0 0 0} :Pacific/Auckland
+ {43200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Fiji
+ {46800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Tongatapu
+ }]
+
+ # Groups of fields that specify the date, priorities, and
+ # code bursts that determine Julian Day Number given those groups.
+ # The code in [clock scan] will choose the highest priority
+ # (lowest numbered) set of fields that determines the date.
+
+ variable DateParseActions {
+
+ { seconds } 0 {}
+
+ { julianDay } 1 {}
+
+ { era century yearOfCentury month dayOfMonth } 2 {
+ dict set date year [expr { 100 * [dict get $date century]
+ + [dict get $date yearOfCentury] }]
+ set date [GetJulianDayFromEraYearMonthDay $date[set date {}] \
+ $changeover]
+ }
+ { era century yearOfCentury dayOfYear } 2 {
+ dict set date year [expr { 100 * [dict get $date century]
+ + [dict get $date yearOfCentury] }]
+ set date [GetJulianDayFromEraYearDay $date[set date {}] \
+ $changeover]
+ }
+
+ { century yearOfCentury month dayOfMonth } 3 {
+ dict set date era CE
+ dict set date year [expr { 100 * [dict get $date century]
+ + [dict get $date yearOfCentury] }]
+ set date [GetJulianDayFromEraYearMonthDay $date[set date {}] \
+ $changeover]
+ }
+ { century yearOfCentury dayOfYear } 3 {
+ dict set date era CE
+ dict set date year [expr { 100 * [dict get $date century]
+ + [dict get $date yearOfCentury] }]
+ set date [GetJulianDayFromEraYearDay $date[set date {}] \
+ $changeover]
+ }
+ { iso8601Century iso8601YearOfCentury iso8601Week dayOfWeek } 3 {
+ dict set date era CE
+ dict set date iso8601Year \
+ [expr { 100 * [dict get $date iso8601Century]
+ + [dict get $date iso8601YearOfCentury] }]
+ set date [GetJulianDayFromEraYearWeekDay $date[set date {}] \
+ $changeover]
+ }
+
+ { yearOfCentury month dayOfMonth } 4 {
+ set date [InterpretTwoDigitYear $date[set date {}] $baseTime]
+ dict set date era CE
+ set date [GetJulianDayFromEraYearMonthDay $date[set date {}] \
+ $changeover]
+ }
+ { yearOfCentury dayOfYear } 4 {
+ set date [InterpretTwoDigitYear $date[set date {}] $baseTime]
+ dict set date era CE
+ set date [GetJulianDayFromEraYearDay $date[set date {}] \
+ $changeover]
+ }
+ { iso8601YearOfCentury iso8601Week dayOfWeek } 4 {
+ set date [InterpretTwoDigitYear \
+ $date[set date {}] $baseTime \
+ iso8601YearOfCentury iso8601Year]
+ dict set date era CE
+ set date [GetJulianDayFromEraYearWeekDay $date[set date {}] \
+ $changeover]
+ }
+
+ { month dayOfMonth } 5 {
+ set date [AssignBaseYear $date[set date {}] \
+ $baseTime $timeZone $changeover]
+ set date [GetJulianDayFromEraYearMonthDay $date[set date {}] \
+ $changeover]
+ }
+ { dayOfYear } 5 {
+ set date [AssignBaseYear $date[set date {}] \
+ $baseTime $timeZone $changeover]
+ set date [GetJulianDayFromEraYearDay $date[set date {}] \
+ $changeover]
+ }
+ { iso8601Week dayOfWeek } 5 {
+ set date [AssignBaseIso8601Year $date[set date {}] \
+ $baseTime $timeZone $changeover]
+ set date [GetJulianDayFromEraYearWeekDay $date[set date {}] \
+ $changeover]
+ }
+
+ { dayOfMonth } 6 {
+ set date [AssignBaseMonth $date[set date {}] \
+ $baseTime $timeZone $changeover]
+ set date [GetJulianDayFromEraYearMonthDay $date[set date {}] \
+ $changeover]
+ }
+
+ { dayOfWeek } 7 {
+ set date [AssignBaseWeek $date[set date {}] \
+ $baseTime $timeZone $changeover]
+ set date [GetJulianDayFromEraYearWeekDay $date[set date {}] \
+ $changeover]
+ }
+
+ {} 8 {
+ set date [AssignBaseJulianDay $date[set date {}] \
+ $baseTime $timeZone $changeover]
+ }
+ }
+
+ # Groups of fields that specify time of day, priorities,
+ # and code that processes them
+
+ variable TimeParseActions {
+
+ seconds 1 {}
+
+ { hourAMPM minute second amPmIndicator } 2 {
+ dict set date secondOfDay [InterpretHMSP $date]
+ }
+ { hour minute second } 2 {
+ dict set date secondOfDay [InterpretHMS $date]
+ }
+
+ { hourAMPM minute amPmIndicator } 3 {
+ dict set date second 0
+ dict set date secondOfDay [InterpretHMSP $date]
+ }
+ { hour minute } 3 {
+ dict set date second 0
+ dict set date secondOfDay [InterpretHMS $date]
+ }
+
+ { hourAMPM amPmIndicator } 4 {
+ dict set date minute 0
+ dict set date second 0
+ dict set date secondOfDay [InterpretHMSP $date]
+ }
+ { hour } 4 {
+ dict set date minute 0
+ dict set date second 0
+ dict set date secondOfDay [InterpretHMS $date]
+ }
+
+ { } 5 {
+ dict set date secondOfDay 0
+ }
+ }
+
+ # Legacy time zones, used primarily for parsing RFC822 dates.
+
+ variable LegacyTimeZone [dict create \
+ gmt +0000 \
+ ut +0000 \
+ utc +0000 \
+ bst +0100 \
+ wet +0000 \
+ wat -0100 \
+ at -0200 \
+ nft -0330 \
+ nst -0330 \
+ ndt -0230 \
+ ast -0400 \
+ adt -0300 \
+ est -0500 \
+ edt -0400 \
+ cst -0600 \
+ cdt -0500 \
+ mst -0700 \
+ mdt -0600 \
+ pst -0800 \
+ pdt -0700 \
+ yst -0900 \
+ ydt -0800 \
+ hst -1000 \
+ hdt -0900 \
+ cat -1000 \
+ ahst -1000 \
+ nt -1100 \
+ idlw -1200 \
+ cet +0100 \
+ cest +0200 \
+ met +0100 \
+ mewt +0100 \
+ mest +0200 \
+ swt +0100 \
+ sst +0200 \
+ fwt +0100 \
+ fst +0200 \
+ eet +0200 \
+ eest +0300 \
+ bt +0300 \
+ it +0330 \
+ zp4 +0400 \
+ zp5 +0500 \
+ ist +0530 \
+ zp6 +0600 \
+ wast +0700 \
+ wadt +0800 \
+ jt +0730 \
+ cct +0800 \
+ jst +0900 \
+ kst +0900 \
+ cast +0930 \
+ jdt +1000 \
+ kdt +1000 \
+ cadt +1030 \
+ east +1000 \
+ eadt +1030 \
+ gst +1000 \
+ nzt +1200 \
+ nzst +1200 \
+ nzdt +1300 \
+ idle +1200 \
+ a +0100 \
+ b +0200 \
+ c +0300 \
+ d +0400 \
+ e +0500 \
+ f +0600 \
+ g +0700 \
+ h +0800 \
+ i +0900 \
+ k +1000 \
+ l +1100 \
+ m +1200 \
+ n -0100 \
+ o -0200 \
+ p -0300 \
+ q -0400 \
+ r -0500 \
+ s -0600 \
+ t -0700 \
+ u -0800 \
+ v -0900 \
+ w -1000 \
+ x -1100 \
+ y -1200 \
+ z +0000 \
+ ]
+
+ # Caches
+
+ variable LocaleNumeralCache {}; # Dictionary whose keys are locale
+ # names and whose values are pairs
+ # comprising regexes matching numerals
+ # in the given locales and dictionaries
+ # mapping the numerals to their numeric
+ # values.
+ variable McLoaded {}; # Dictionary whose keys are locales
+ # in which [mcload] has been executed
+ # and whose values are second-level
+ # dictionaries indexed by message
+ # name and giving message text.
+ # variable CachedSystemTimeZone; # If 'CachedSystemTimeZone' exists,
+ # it contains the value of the
+ # system time zone, as determined from
+ # the environment.
+ variable TimeZoneBad {}; # Dictionary whose keys are time zone
+ # names and whose values are 1 if
+ # the time zone is unknown and 0
+ # if it is known.
+ variable TZData; # Array whose keys are time zone names
+ # and whose values are lists of quads
+ # comprising start time, UTC offset,
+ # Daylight Saving Time indicator, and
+ # time zone abbreviation.
+ variable FormatProc; # Array mapping format group
+ # and locale to the name of a procedure
+ # that renders the given format
+}
+::tcl::clock::Initialize
+
+#----------------------------------------------------------------------
+#
+# clock format --
+#
+# Formats a count of seconds since the Posix Epoch as a time
+# of day.
+#
+# The 'clock format' command formats times of day for output.
+# Refer to the user documentation to see what it does.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::format { args } {
+
+ variable FormatProc
+ variable TZData
+
+ lassign [ParseFormatArgs {*}$args] format locale timezone
+ set locale [string tolower $locale]
+ set clockval [lindex $args 0]
+
+ # Get the data for time changes in the given zone
+
+ if {$timezone eq ""} {
+ set timezone [GetSystemTimeZone]
+ }
+ if {![info exists TZData($timezone)]} {
+ if {[catch {SetupTimeZone $timezone} retval opts]} {
+ dict unset opts -errorinfo
+ return -options $opts $retval
+ }
+ }
+
+ # Build a procedure to format the result. Cache the built procedure's
+ # name in the 'FormatProc' array to avoid losing its internal
+ # representation, which contains the name resolution.
+
+ set procName formatproc'$format'$locale
+ set procName [namespace current]::[string map {: {\:} \\ {\\}} $procName]
+ if {[info exists FormatProc($procName)]} {
+ set procName $FormatProc($procName)
+ } else {
+ set FormatProc($procName) \
+ [ParseClockFormatFormat $procName $format $locale]
+ }
+
+ return [$procName $clockval $timezone]
+
+}
+
+#----------------------------------------------------------------------
+#
+# ParseClockFormatFormat --
+#
+# Builds and caches a procedure that formats a time value.
+#
+# Parameters:
+# format -- Format string to use
+# locale -- Locale in which the format string is to be interpreted
+#
+# Results:
+# Returns the name of the newly-built procedure.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::ParseClockFormatFormat {procName format locale} {
+
+ if {[namespace which $procName] ne {}} {
+ return $procName
+ }
+
+ # Map away the locale-dependent composite format groups
+
+ EnterLocale $locale oldLocale
+
+ # Change locale if a fresh locale has been given on the command line.
+
+ set status [catch {
+
+ ParseClockFormatFormat2 $format $locale $procName
+
+ } result opts]
+
+ # Restore the locale
+
+ if { [info exists oldLocale] } {
+ mclocale $oldLocale
+ }
+
+ # Return either the error or the proc name
+
+ if { $status == 1 } {
+ if { [lindex [dict get $opts -errorcode] 0] eq {clock} } {
+ return -code error $result
+ } else {
+ return -options $opts $result
+ }
+ } else {
+ return $result
+ }
+
+}
+
+proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} {
+
+ set didLocaleEra 0
+ set didLocaleNumerals 0
+ set preFormatCode \
+ [string map [list @GREGORIAN_CHANGE_DATE@ \
+ [mc GREGORIAN_CHANGE_DATE]] \
+ {
+ variable TZData
+ set date [GetDateFields $clockval \
+ $TZData($timezone) \
+ @GREGORIAN_CHANGE_DATE@]
+ }]
+ set formatString {}
+ set substituents {}
+ set state {}
+
+ set format [LocalizeFormat $locale $format]
+
+ foreach char [split $format {}] {
+ switch -exact -- $state {
+ {} {
+ if { [string equal % $char] } {
+ set state percent
+ } else {
+ append formatString $char
+ }
+ }
+ percent { # Character following a '%' character
+ set state {}
+ switch -exact -- $char {
+ % { # A literal character, '%'
+ append formatString %%
+ }
+ a { # Day of week, abbreviated
+ append formatString %s
+ append substituents \
+ [string map \
+ [list @DAYS_OF_WEEK_ABBREV@ \
+ [list [mc DAYS_OF_WEEK_ABBREV]]] \
+ { [lindex @DAYS_OF_WEEK_ABBREV@ \
+ [expr {[dict get $date dayOfWeek] \
+ % 7}]]}]
+ }
+ A { # Day of week, spelt out.
+ append formatString %s
+ append substituents \
+ [string map \
+ [list @DAYS_OF_WEEK_FULL@ \
+ [list [mc DAYS_OF_WEEK_FULL]]] \
+ { [lindex @DAYS_OF_WEEK_FULL@ \
+ [expr {[dict get $date dayOfWeek] \
+ % 7}]]}]
+ }
+ b - h { # Name of month, abbreviated.
+ append formatString %s
+ append substituents \
+ [string map \
+ [list @MONTHS_ABBREV@ \
+ [list [mc MONTHS_ABBREV]]] \
+ { [lindex @MONTHS_ABBREV@ \
+ [expr {[dict get $date month]-1}]]}]
+ }
+ B { # Name of month, spelt out
+ append formatString %s
+ append substituents \
+ [string map \
+ [list @MONTHS_FULL@ \
+ [list [mc MONTHS_FULL]]] \
+ { [lindex @MONTHS_FULL@ \
+ [expr {[dict get $date month]-1}]]}]
+ }
+ C { # Century number
+ append formatString %02d
+ append substituents \
+ { [expr {[dict get $date year] / 100}]}
+ }
+ d { # Day of month, with leading zero
+ append formatString %02d
+ append substituents { [dict get $date dayOfMonth]}
+ }
+ e { # Day of month, without leading zero
+ append formatString %2d
+ append substituents { [dict get $date dayOfMonth]}
+ }
+ E { # Format group in a locale-dependent
+ # alternative era
+ set state percentE
+ if {!$didLocaleEra} {
+ append preFormatCode \
+ [string map \
+ [list @LOCALE_ERAS@ \
+ [list [mc LOCALE_ERAS]]] \
+ {
+ set date [GetLocaleEra \
+ $date[set date {}] \
+ @LOCALE_ERAS@]}] \n
+ set didLocaleEra 1
+ }
+ if {!$didLocaleNumerals} {
+ append preFormatCode \
+ [list set localeNumerals \
+ [mc LOCALE_NUMERALS]] \n
+ set didLocaleNumerals 1
+ }
+ }
+ g { # Two-digit year relative to ISO8601
+ # week number
+ append formatString %02d
+ append substituents \
+ { [expr { [dict get $date iso8601Year] % 100 }]}
+ }
+ G { # Four-digit year relative to ISO8601
+ # week number
+ append formatString %02d
+ append substituents { [dict get $date iso8601Year]}
+ }
+ H { # Hour in the 24-hour day, leading zero
+ append formatString %02d
+ append substituents \
+ { [expr { [dict get $date localSeconds] \
+ / 3600 % 24}]}
+ }
+ I { # Hour AM/PM, with leading zero
+ append formatString %02d
+ append substituents \
+ { [expr { ( ( ( [dict get $date localSeconds] \
+ % 86400 ) \
+ + 86400 \
+ - 3600 ) \
+ / 3600 ) \
+ % 12 + 1 }] }
+ }
+ j { # Day of year (001-366)
+ append formatString %03d
+ append substituents { [dict get $date dayOfYear]}
+ }
+ J { # Julian Day Number
+ append formatString %07ld
+ append substituents { [dict get $date julianDay]}
+ }
+ k { # Hour (0-23), no leading zero
+ append formatString %2d
+ append substituents \
+ { [expr { [dict get $date localSeconds]
+ / 3600
+ % 24 }]}
+ }
+ l { # Hour (12-11), no leading zero
+ append formatString %2d
+ append substituents \
+ { [expr { ( ( ( [dict get $date localSeconds]
+ % 86400 )
+ + 86400
+ - 3600 )
+ / 3600 )
+ % 12 + 1 }]}
+ }
+ m { # Month number, leading zero
+ append formatString %02d
+ append substituents { [dict get $date month]}
+ }
+ M { # Minute of the hour, leading zero
+ append formatString %02d
+ append substituents \
+ { [expr { [dict get $date localSeconds]
+ / 60
+ % 60 }]}
+ }
+ n { # A literal newline
+ append formatString \n
+ }
+ N { # Month number, no leading zero
+ append formatString %2d
+ append substituents { [dict get $date month]}
+ }
+ O { # A format group in the locale's
+ # alternative numerals
+ set state percentO
+ if {!$didLocaleNumerals} {
+ append preFormatCode \
+ [list set localeNumerals \
+ [mc LOCALE_NUMERALS]] \n
+ set didLocaleNumerals 1
+ }
+ }
+ p { # Localized 'AM' or 'PM' indicator
+ # converted to uppercase
+ append formatString %s
+ append preFormatCode \
+ [list set AM [string toupper [mc AM]]] \n \
+ [list set PM [string toupper [mc PM]]] \n
+ append substituents \
+ { [expr {(([dict get $date localSeconds]
+ % 86400) < 43200) ?
+ $AM : $PM}]}
+ }
+ P { # Localized 'AM' or 'PM' indicator
+ append formatString %s
+ append preFormatCode \
+ [list set am [mc AM]] \n \
+ [list set pm [mc PM]] \n
+ append substituents \
+ { [expr {(([dict get $date localSeconds]
+ % 86400) < 43200) ?
+ $am : $pm}]}
+
+ }
+ Q { # Hi, Jeff!
+ append formatString %s
+ append substituents { [FormatStarDate $date]}
+ }
+ s { # Seconds from the Posix Epoch
+ append formatString %s
+ append substituents { [dict get $date seconds]}
+ }
+ S { # Second of the minute, with
+ # leading zero
+ append formatString %02d
+ append substituents \
+ { [expr { [dict get $date localSeconds]
+ % 60 }]}
+ }
+ t { # A literal tab character
+ append formatString \t
+ }
+ u { # Day of the week (1-Monday, 7-Sunday)
+ append formatString %1d
+ append substituents { [dict get $date dayOfWeek]}
+ }
+ U { # Week of the year (00-53). The
+ # first Sunday of the year is the
+ # first day of week 01
+ append formatString %02d
+ append preFormatCode {
+ set dow [dict get $date dayOfWeek]
+ if { $dow == 7 } {
+ set dow 0
+ }
+ incr dow
+ set UweekNumber \
+ [expr { ( [dict get $date dayOfYear]
+ - $dow + 7 )
+ / 7 }]
+ }
+ append substituents { $UweekNumber}
+ }
+ V { # The ISO8601 week number
+ append formatString %02d
+ append substituents { [dict get $date iso8601Week]}
+ }
+ w { # Day of the week (0-Sunday,
+ # 6-Saturday)
+ append formatString %1d
+ append substituents \
+ { [expr { [dict get $date dayOfWeek] % 7 }]}
+ }
+ W { # Week of the year (00-53). The first
+ # Monday of the year is the first day
+ # of week 01.
+ append preFormatCode {
+ set WweekNumber \
+ [expr { ( [dict get $date dayOfYear]
+ - [dict get $date dayOfWeek]
+ + 7 )
+ / 7 }]
+ }
+ append formatString %02d
+ append substituents { $WweekNumber}
+ }
+ y { # The two-digit year of the century
+ append formatString %02d
+ append substituents \
+ { [expr { [dict get $date year] % 100 }]}
+ }
+ Y { # The four-digit year
+ append formatString %04d
+ append substituents { [dict get $date year]}
+ }
+ z { # The time zone as hours and minutes
+ # east (+) or west (-) of Greenwich
+ append formatString %s
+ append substituents { [FormatNumericTimeZone \
+ [dict get $date tzOffset]]}
+ }
+ Z { # The name of the time zone
+ append formatString %s
+ append substituents { [dict get $date tzName]}
+ }
+ % { # A literal percent character
+ append formatString %%
+ }
+ default { # An unknown escape sequence
+ append formatString %% $char
+ }
+ }
+ }
+ percentE { # Character following %E
+ set state {}
+ switch -exact -- $char {
+ E {
+ append formatString %s
+ append substituents { } \
+ [string map \
+ [list @BCE@ [list [mc BCE]] \
+ @CE@ [list [mc CE]]] \
+ {[dict get {BCE @BCE@ CE @CE@} \
+ [dict get $date era]]}]
+ }
+ C { # Locale-dependent era
+ append formatString %s
+ append substituents { [dict get $date localeEra]}
+ }
+ y { # Locale-dependent year of the era
+ append preFormatCode {
+ set y [dict get $date localeYear]
+ if { $y >= 0 && $y < 100 } {
+ set Eyear [lindex $localeNumerals $y]
+ } else {
+ set Eyear $y
+ }
+ }
+ append formatString %s
+ append substituents { $Eyear}
+ }
+ default { # Unknown %E format group
+ append formatString %%E $char
+ }
+ }
+ }
+ percentO { # Character following %O
+ set state {}
+ switch -exact -- $char {
+ d - e { # Day of the month in alternative
+ # numerals
+ append formatString %s
+ append substituents \
+ { [lindex $localeNumerals \
+ [dict get $date dayOfMonth]]}
+ }
+ H - k { # Hour of the day in alternative
+ # numerals
+ append formatString %s
+ append substituents \
+ { [lindex $localeNumerals \
+ [expr { [dict get $date localSeconds]
+ / 3600
+ % 24 }]]}
+ }
+ I - l { # Hour (12-11) AM/PM in alternative
+ # numerals
+ append formatString %s
+ append substituents \
+ { [lindex $localeNumerals \
+ [expr { ( ( ( [dict get $date localSeconds]
+ % 86400 )
+ + 86400
+ - 3600 )
+ / 3600 )
+ % 12 + 1 }]]}
+ }
+ m { # Month number in alternative numerals
+ append formatString %s
+ append substituents \
+ { [lindex $localeNumerals [dict get $date month]]}
+ }
+ M { # Minute of the hour in alternative
+ # numerals
+ append formatString %s
+ append substituents \
+ { [lindex $localeNumerals \
+ [expr { [dict get $date localSeconds]
+ / 60
+ % 60 }]]}
+ }
+ S { # Second of the minute in alternative
+ # numerals
+ append formatString %s
+ append substituents \
+ { [lindex $localeNumerals \
+ [expr { [dict get $date localSeconds]
+ % 60 }]]}
+ }
+ u { # Day of the week (Monday=1,Sunday=7)
+ # in alternative numerals
+ append formatString %s
+ append substituents \
+ { [lindex $localeNumerals \
+ [dict get $date dayOfWeek]]}
+ }
+ w { # Day of the week (Sunday=0,Saturday=6)
+ # in alternative numerals
+ append formatString %s
+ append substituents \
+ { [lindex $localeNumerals \
+ [expr { [dict get $date dayOfWeek] % 7 }]]}
+ }
+ y { # Year of the century in alternative
+ # numerals
+ append formatString %s
+ append substituents \
+ { [lindex $localeNumerals \
+ [expr { [dict get $date year] % 100 }]]}
+ }
+ default { # Unknown format group
+ append formatString %%O $char
+ }
+ }
+ }
+ }
+ }
+
+ # Clean up any improperly terminated groups
+
+ switch -exact -- $state {
+ percent {
+ append formatString %%
+ }
+ percentE {
+ append retval %%E
+ }
+ percentO {
+ append retval %%O
+ }
+ }
+
+ proc $procName {clockval timezone} "
+ $preFormatCode
+ return \[::format [list $formatString] $substituents\]
+ "
+
+ # puts [list $procName [info args $procName] [info body $procName]]
+
+ return $procName
+}
+
+#----------------------------------------------------------------------
+#
+# clock scan --
+#
+# Inputs a count of seconds since the Posix Epoch as a time
+# of day.
+#
+# The 'clock format' command scans times of day on input.
+# Refer to the user documentation to see what it does.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::scan { args } {
+
+ set format {}
+
+ # Check the count of args
+
+ if { [llength $args] < 1 || [llength $args] % 2 != 1 } {
+ set cmdName "clock scan"
+ return -code error \
+ -errorcode [list CLOCK wrongNumArgs] \
+ "wrong \# args: should be\
+ \"$cmdName string\
+ ?-base seconds?\
+ ?-format string? ?-gmt boolean?\
+ ?-locale LOCALE? ?-timezone ZONE?\""
+ }
+
+ # Set defaults
+
+ set base [clock seconds]
+ set string [lindex $args 0]
+ set format {}
+ set gmt 0
+ set locale c
+ set timezone [GetSystemTimeZone]
+
+ # Pick up command line options.
+
+ foreach { flag value } [lreplace $args 0 0] {
+ set saw($flag) {}
+ switch -exact -- $flag {
+ -b - -ba - -bas - -base {
+ set base $value
+ }
+ -f - -fo - -for - -form - -forma - -format {
+ set format $value
+ }
+ -g - -gm - -gmt {
+ set gmt $value
+ }
+ -l - -lo - -loc - -loca - -local - -locale {
+ set locale [string tolower $value]
+ }
+ -t - -ti - -tim - -time - -timez - -timezo - -timezon - -timezone {
+ set timezone $value
+ }
+ default {
+ return -code error \
+ -errorcode [list CLOCK badSwitch $flag] \
+ "bad switch \"$flag\",\
+ must be -base, -format, -gmt, -locale or -timezone"
+ }
+ }
+ }
+
+ # Check options for validity
+
+ if { [info exists saw(-gmt)] && [info exists saw(-timezone)] } {
+ return -code error \
+ -errorcode [list CLOCK gmtWithTimezone] \
+ "cannot use -gmt and -timezone in same call"
+ }
+ if { [catch { expr { wide($base) } } result] } {
+ return -code error \
+ "expected integer but got \"$base\""
+ }
+ if { ![string is boolean $gmt] } {
+ return -code error \
+ "expected boolean value but got \"$gmt\""
+ } else {
+ if { $gmt } {
+ set timezone :GMT
+ }
+ }
+
+ if { ![info exists saw(-format)] } {
+ # Perhaps someday we'll localize the legacy code. Right now,
+ # it's not localized.
+ if { [info exists saw(-locale)] } {
+ return -code error \
+ -errorcode [list CLOCK flagWithLegacyFormat] \
+ "legacy \[clock scan\] does not support -locale"
+
+ }
+ return [FreeScan $string $base $timezone $locale]
+ }
+
+ # Change locale if a fresh locale has been given on the command line.
+
+ EnterLocale $locale oldLocale
+
+ set status [catch {
+
+ # Map away the locale-dependent composite format groups
+
+ set scanner [ParseClockScanFormat $format $locale]
+ $scanner $string $base $timezone
+
+ } result opts]
+
+ # Restore the locale
+
+ if { [info exists oldLocale] } {
+ mclocale $oldLocale
+ }
+
+ if { $status == 1 } {
+ if { [lindex [dict get $opts -errorcode] 0] eq {clock} } {
+ return -code error $result
+ } else {
+ return -options $opts $result
+ }
+ } else {
+ return $result
+ }
+
+}
+
+#----------------------------------------------------------------------
+#
+# FreeScan --
+#
+# Scans a time in free format
+#
+# Parameters:
+# string - String containing the time to scan
+# base - Base time, expressed in seconds from the Epoch
+# timezone - Default time zone in which the time will be expressed
+# locale - (Unused) Name of the locale where the time will be scanned.
+#
+# Results:
+# Returns the date and time extracted from the string in seconds
+# from the epoch
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::FreeScan { string base timezone locale } {
+
+ variable TZData
+
+ # Get the data for time changes in the given zone
+
+ if {[catch {SetupTimeZone $timezone} retval opts]} {
+ dict unset opts -errorinfo
+ return -options $opts $retval
+ }
+
+ # Extract year, month and day from the base time for the
+ # parser to use as defaults
+
+ set date [GetDateFields \
+ $base \
+ $TZData($timezone) \
+ 2361222]
+ dict set date secondOfDay [expr { [dict get $date localSeconds]
+ % 86400 }]
+
+ # Parse the date. The parser will return a list comprising
+ # date, time, time zone, relative month/day/seconds, relative
+ # weekday, ordinal month.
+
+ set status [catch {
+ Oldscan $string \
+ [dict get $date year] \
+ [dict get $date month] \
+ [dict get $date dayOfMonth]
+ } result]
+ if { $status != 0 } {
+ return -code error "unable to convert date-time string \"$string\": $result"
+ }
+
+ lassign $result parseDate parseTime parseZone parseRel \
+ parseWeekday parseOrdinalMonth
+
+ # If the caller supplied a date in the string, update the 'date' dict
+ # with the value. If the caller didn't specify a time with the date,
+ # default to midnight.
+
+ if { [llength $parseDate] > 0 } {
+ lassign $parseDate y m d
+ if { $y < 100 } {
+ if { $y >= 39 } {
+ incr y 1900
+ } else {
+ incr y 2000
+ }
+ }
+ dict set date era CE
+ dict set date year $y
+ dict set date month $m
+ dict set date dayOfMonth $d
+ if { $parseTime eq {} } {
+ set parseTime 0
+ }
+ }
+
+ # If the caller supplied a time zone in the string, it comes back
+ # as a two-element list; the first element is the number of minutes
+ # east of Greenwich, and the second is a Daylight Saving Time
+ # indicator ( 1 == yes, 0 == no, -1 == unknown ). We make it into
+ # a time zone indicator of +-hhmm.
+
+ if { [llength $parseZone] > 0 } {
+ lassign $parseZone minEast dstFlag
+ set timezone [FormatNumericTimeZone \
+ [expr { 60 * $minEast + 3600 * $dstFlag }]]
+ SetupTimeZone $timezone
+ }
+ dict set date tzName $timezone
+
+ # Assemble date, time, zone into seconds-from-epoch
+
+ set date [GetJulianDayFromEraYearMonthDay $date[set date {}] 2361222]
+ if { $parseTime ne {} } {
+ dict set date secondOfDay $parseTime
+ } elseif { [llength $parseWeekday] != 0
+ || [llength $parseOrdinalMonth] != 0
+ || ( [llength $parseRel] != 0
+ && ( [lindex $parseRel 0] != 0
+ || [lindex $parseRel 1] != 0 ) ) } {
+ dict set date secondOfDay 0
+ }
+
+ dict set date localSeconds \
+ [expr { -210866803200
+ + ( 86400 * wide([dict get $date julianDay]) )
+ + [dict get $date secondOfDay] }]
+ dict set date tzName $timezone
+ set date [ConvertLocalToUTC $date[set date {}] $TZData($timezone) 2361222]
+ set seconds [dict get $date seconds]
+
+ # Do relative times
+
+ if { [llength $parseRel] > 0 } {
+ lassign $parseRel relMonth relDay relSecond
+ set seconds [add $seconds \
+ $relMonth months $relDay days $relSecond seconds \
+ -timezone $timezone -locale $locale]
+ }
+
+ # Do relative weekday
+
+ if { [llength $parseWeekday] > 0 } {
+
+ lassign $parseWeekday dayOrdinal dayOfWeek
+ set date2 [GetDateFields $seconds $TZData($timezone) 2361222]
+ dict set date2 era CE
+ set jdwkday [WeekdayOnOrBefore $dayOfWeek \
+ [expr { [dict get $date2 julianDay]
+ + 6 }]]
+ incr jdwkday [expr { 7 * $dayOrdinal }]
+ if { $dayOrdinal > 0 } {
+ incr jdwkday -7
+ }
+ dict set date2 secondOfDay \
+ [expr { [dict get $date2 localSeconds] % 86400 }]
+ dict set date2 julianDay $jdwkday
+ dict set date2 localSeconds \
+ [expr { -210866803200
+ + ( 86400 * wide([dict get $date2 julianDay]) )
+ + [dict get $date secondOfDay] }]
+ dict set date2 tzName $timezone
+ set date2 [ConvertLocalToUTC $date2[set date2 {}] $TZData($timezone) \
+ 2361222]
+ set seconds [dict get $date2 seconds]
+
+ }
+
+ # Do relative month
+
+ if { [llength $parseOrdinalMonth] > 0 } {
+
+ lassign $parseOrdinalMonth monthOrdinal monthNumber
+ if { $monthOrdinal > 0 } {
+ set monthDiff [expr { $monthNumber - [dict get $date month] }]
+ if { $monthDiff <= 0 } {
+ incr monthDiff 12
+ }
+ incr monthOrdinal -1
+ } else {
+ set monthDiff [expr { [dict get $date month] - $monthNumber }]
+ if { $monthDiff >= 0 } {
+ incr monthDiff -12
+ }
+ incr monthOrdinal
+ }
+ set seconds [add $seconds $monthOrdinal years $monthDiff months \
+ -timezone $timezone -locale $locale]
+
+ }
+
+ return $seconds
+}
+
+
+#----------------------------------------------------------------------
+#
+# ParseClockScanFormat --
+#
+# Parses a format string given to [clock scan -format]
+#
+# Parameters:
+# formatString - The format being parsed
+# locale - The current locale
+#
+# Results:
+# Constructs and returns a procedure that accepts the
+# string being scanned, the base time, and the time zone.
+# The procedure will either return the scanned time or
+# else throw an error that should be rethrown to the caller
+# of [clock scan]
+#
+# Side effects:
+# The given procedure is defined in the ::tcl::clock
+# namespace. Scan procedures are not deleted once installed.
+#
+# Why do we parse dates by defining a procedure to parse them?
+# The reason is that by doing so, we have one convenient place to
+# cache all the information: the regular expressions that match the
+# patterns (which will be compiled), the code that assembles the
+# date information, everything lands in one place. In this way,
+# when a given format is reused at run time, all the information
+# of how to apply it is available in a single place.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::ParseClockScanFormat {formatString locale} {
+
+ # Check whether the format has been parsed previously, and return
+ # the existing recognizer if it has.
+
+ set procName scanproc'$formatString'$locale
+ set procName [namespace current]::[string map {: {\:} \\ {\\}} $procName]
+ if { [namespace which $procName] != {} } {
+ return $procName
+ }
+
+ variable DateParseActions
+ variable TimeParseActions
+
+ # Localize the %x, %X, etc. groups
+
+ set formatString [LocalizeFormat $locale $formatString]
+
+ # Condense whitespace
+
+ regsub -all {[[:space:]]+} $formatString { } formatString
+
+ # Walk through the groups of the format string. In this loop, we
+ # accumulate:
+ # - a regular expression that matches the string,
+ # - the count of capturing brackets in the regexp
+ # - a set of code that post-processes the fields captured by the regexp,
+ # - a dictionary whose keys are the names of fields that are present
+ # in the format string.
+
+ set re {^[[:space:]]*}
+ set captureCount 0
+ set postcode {}
+ set fieldSet [dict create]
+ set fieldCount 0
+ set postSep {}
+ set state {}
+
+ foreach c [split $formatString {}] {
+ switch -exact -- $state {
+ {} {
+ if { $c eq "%" } {
+ set state %
+ } elseif { $c eq " " } {
+ append re {[[:space:]]+}
+ } else {
+ if { ! [string is alnum $c] } {
+ append re \\
+ }
+ append re $c
+ }
+ }
+ % {
+ set state {}
+ switch -exact -- $c {
+ % {
+ append re %
+ }
+ { } {
+ append re "\[\[:space:\]\]*"
+ }
+ a - A { # Day of week, in words
+ set l {}
+ foreach \
+ i {7 1 2 3 4 5 6} \
+ abr [mc DAYS_OF_WEEK_ABBREV] \
+ full [mc DAYS_OF_WEEK_FULL] {
+ dict set l [string tolower $abr] $i
+ dict set l [string tolower $full] $i
+ incr i
+ }
+ lassign [UniquePrefixRegexp $l] regex lookup
+ append re ( $regex )
+ dict set fieldSet dayOfWeek [incr fieldCount]
+ append postcode "dict set date dayOfWeek \[" \
+ "dict get " [list $lookup] " " \
+ \[ {string tolower $field} [incr captureCount] \] \
+ "\]\n"
+ }
+ b - B - h { # Name of month
+ set i 0
+ set l {}
+ foreach \
+ abr [mc MONTHS_ABBREV] \
+ full [mc MONTHS_FULL] {
+ incr i
+ dict set l [string tolower $abr] $i
+ dict set l [string tolower $full] $i
+ }
+ lassign [UniquePrefixRegexp $l] regex lookup
+ append re ( $regex )
+ dict set fieldSet month [incr fieldCount]
+ append postcode "dict set date month \[" \
+ "dict get " [list $lookup] \
+ " " \[ {string tolower $field} \
+ [incr captureCount] \] \
+ "\]\n"
+ }
+ C { # Gregorian century
+ append re \\s*(\\d\\d?)
+ dict set fieldSet century [incr fieldCount]
+ append postcode "dict set date century \[" \
+ "::scan \$field" [incr captureCount] " %d" \
+ "\]\n"
+ }
+ d - e { # Day of month
+ append re \\s*(\\d\\d?)
+ dict set fieldSet dayOfMonth [incr fieldCount]
+ append postcode "dict set date dayOfMonth \[" \
+ "::scan \$field" [incr captureCount] " %d" \
+ "\]\n"
+ }
+ E { # Prefix for locale-specific codes
+ set state %E
+ }
+ g { # ISO8601 2-digit year
+ append re \\s*(\\d\\d)
+ dict set fieldSet iso8601YearOfCentury \
+ [incr fieldCount]
+ append postcode \
+ "dict set date iso8601YearOfCentury \[" \
+ "::scan \$field" [incr captureCount] " %d" \
+ "\]\n"
+ }
+ G { # ISO8601 4-digit year
+ append re \\s*(\\d\\d)(\\d\\d)
+ dict set fieldSet iso8601Century [incr fieldCount]
+ dict set fieldSet iso8601YearOfCentury \
+ [incr fieldCount]
+ append postcode \
+ "dict set date iso8601Century \[" \
+ "::scan \$field" [incr captureCount] " %d" \
+ "\]\n" \
+ "dict set date iso8601YearOfCentury \[" \
+ "::scan \$field" [incr captureCount] " %d" \
+ "\]\n"
+ }
+ H - k { # Hour of day
+ append re \\s*(\\d\\d?)
+ dict set fieldSet hour [incr fieldCount]
+ append postcode "dict set date hour \[" \
+ "::scan \$field" [incr captureCount] " %d" \
+ "\]\n"
+ }
+ I - l { # Hour, AM/PM
+ append re \\s*(\\d\\d?)
+ dict set fieldSet hourAMPM [incr fieldCount]
+ append postcode "dict set date hourAMPM \[" \
+ "::scan \$field" [incr captureCount] " %d" \
+ "\]\n"
+ }
+ j { # Day of year
+ append re \\s*(\\d\\d?\\d?)
+ dict set fieldSet dayOfYear [incr fieldCount]
+ append postcode "dict set date dayOfYear \[" \
+ "::scan \$field" [incr captureCount] " %d" \
+ "\]\n"
+ }
+ J { # Julian Day Number
+ append re \\s*(\\d+)
+ dict set fieldSet julianDay [incr fieldCount]
+ append postcode "dict set date julianDay \[" \
+ "::scan \$field" [incr captureCount] " %ld" \
+ "\]\n"
+ }
+ m - N { # Month number
+ append re \\s*(\\d\\d?)
+ dict set fieldSet month [incr fieldCount]
+ append postcode "dict set date month \[" \
+ "::scan \$field" [incr captureCount] " %d" \
+ "\]\n"
+ }
+ M { # Minute
+ append re \\s*(\\d\\d?)
+ dict set fieldSet minute [incr fieldCount]
+ append postcode "dict set date minute \[" \
+ "::scan \$field" [incr captureCount] " %d" \
+ "\]\n"
+ }
+ n { # Literal newline
+ append re \\n
+ }
+ O { # Prefix for locale numerics
+ set state %O
+ }
+ p - P { # AM/PM indicator
+ set l [list [string tolower [mc AM]] 0 \
+ [string tolower [mc PM]] 1]
+ lassign [UniquePrefixRegexp $l] regex lookup
+ append re ( $regex )
+ dict set fieldSet amPmIndicator [incr fieldCount]
+ append postcode "dict set date amPmIndicator \[" \
+ "dict get " [list $lookup] " \[string tolower " \
+ "\$field" \
+ [incr captureCount] \
+ "\]\]\n"
+ }
+ Q { # Hi, Jeff!
+ append re {Stardate\s+([-+]?\d+)(\d\d\d)[.](\d)}
+ incr captureCount
+ dict set fieldSet seconds [incr fieldCount]
+ append postcode {dict set date seconds } \[ \
+ {ParseStarDate $field} [incr captureCount] \
+ { $field} [incr captureCount] \
+ { $field} [incr captureCount] \
+ \] \n
+ }
+ s { # Seconds from Posix Epoch
+ # This next case is insanely difficult,
+ # because it's problematic to determine
+ # whether the field is actually within
+ # the range of a wide integer.
+ append re {\s*([-+]?\d+)}
+ dict set fieldSet seconds [incr fieldCount]
+ append postcode {dict set date seconds } \[ \
+ {ScanWide $field} [incr captureCount] \] \n
+ }
+ S { # Second
+ append re \\s*(\\d\\d?)
+ dict set fieldSet second [incr fieldCount]
+ append postcode "dict set date second \[" \
+ "::scan \$field" [incr captureCount] " %d" \
+ "\]\n"
+ }
+ t { # Literal tab character
+ append re \\t
+ }
+ u - w { # Day number within week, 0 or 7 == Sun
+ # 1=Mon, 6=Sat
+ append re \\s*(\\d)
+ dict set fieldSet dayOfWeek [incr fieldCount]
+ append postcode {::scan $field} [incr captureCount] \
+ { %d dow} \n \
+ {
+ if { $dow == 0 } {
+ set dow 7
+ } elseif { $dow > 7 } {
+ return -code error \
+ -errorcode [list CLOCK badDayOfWeek] \
+ "day of week is greater than 7"
+ }
+ dict set date dayOfWeek $dow
+ }
+ }
+ U { # Week of year. The
+ # first Sunday of the year is the
+ # first day of week 01. No scan rule
+ # uses this group.
+ append re \\s*\\d\\d?
+ }
+ V { # Week of ISO8601 year
+
+ append re \\s*(\\d\\d?)
+ dict set fieldSet iso8601Week [incr fieldCount]
+ append postcode "dict set date iso8601Week \[" \
+ "::scan \$field" [incr captureCount] " %d" \
+ "\]\n"
+ }
+ W { # Week of the year (00-53). The first
+ # Monday of the year is the first day
+ # of week 01. No scan rule uses this
+ # group.
+ append re \\s*\\d\\d?
+ }
+ y { # Two-digit Gregorian year
+ append re \\s*(\\d\\d?)
+ dict set fieldSet yearOfCentury [incr fieldCount]
+ append postcode "dict set date yearOfCentury \[" \
+ "::scan \$field" [incr captureCount] " %d" \
+ "\]\n"
+ }
+ Y { # 4-digit Gregorian year
+ append re \\s*(\\d\\d)(\\d\\d)
+ dict set fieldSet century [incr fieldCount]
+ dict set fieldSet yearOfCentury [incr fieldCount]
+ append postcode \
+ "dict set date century \[" \
+ "::scan \$field" [incr captureCount] " %d" \
+ "\]\n" \
+ "dict set date yearOfCentury \[" \
+ "::scan \$field" [incr captureCount] " %d" \
+ "\]\n"
+ }
+ z - Z { # Time zone name
+ append re {(?:([-+]\d\d(?::?\d\d(?::?\d\d)?)?)|([[:alnum:]]{1,4}))}
+ dict set fieldSet tzName [incr fieldCount]
+ append postcode \
+ {if } \{ { $field} [incr captureCount] \
+ { ne "" } \} { } \{ \n \
+ {dict set date tzName $field} \
+ $captureCount \n \
+ \} { else } \{ \n \
+ {dict set date tzName } \[ \
+ {ConvertLegacyTimeZone $field} \
+ [incr captureCount] \] \n \
+ \} \n \
+ }
+ % { # Literal percent character
+ append re %
+ }
+ default {
+ append re %
+ if { ! [string is alnum $c] } {
+ append re \\
+ }
+ append re $c
+ }
+ }
+ }
+ %E {
+ switch -exact -- $c {
+ C { # Locale-dependent era
+ set d {}
+ foreach triple [mc LOCALE_ERAS] {
+ lassign $triple t symbol year
+ dict set d [string tolower $symbol] $year
+ }
+ lassign [UniquePrefixRegexp $d] regex lookup
+ append re (?: $regex )
+ }
+ E {
+ set l {}
+ dict set l [string tolower [mc BCE]] BCE
+ dict set l [string tolower [mc CE]] CE
+ dict set l b.c.e. BCE
+ dict set l c.e. CE
+ dict set l b.c. BCE
+ dict set l a.d. CE
+ lassign [UniquePrefixRegexp $l] regex lookup
+ append re ( $regex )
+ dict set fieldSet era [incr fieldCount]
+ append postcode "dict set date era \["\
+ "dict get " [list $lookup] \
+ { } \[ {string tolower $field} \
+ [incr captureCount] \] \
+ "\]\n"
+ }
+ y { # Locale-dependent year of the era
+ lassign [LocaleNumeralMatcher $locale] regex lookup
+ append re $regex
+ incr captureCount
+ }
+ default {
+ append re %E
+ if { ! [string is alnum $c] } {
+ append re \\
+ }
+ append re $c
+ }
+ }
+ set state {}
+ }
+ %O {
+ switch -exact -- $c {
+ d - e {
+ lassign [LocaleNumeralMatcher $locale] regex lookup
+ append re $regex
+ dict set fieldSet dayOfMonth [incr fieldCount]
+ append postcode "dict set date dayOfMonth \[" \
+ "dict get " [list $lookup] " \$field" \
+ [incr captureCount] \
+ "\]\n"
+ }
+ H - k {
+ lassign [LocaleNumeralMatcher $locale] regex lookup
+ append re $regex
+ dict set fieldSet hour [incr fieldCount]
+ append postcode "dict set date hour \[" \
+ "dict get " [list $lookup] " \$field" \
+ [incr captureCount] \
+ "\]\n"
+ }
+ I - l {
+ lassign [LocaleNumeralMatcher $locale] regex lookup
+ append re $regex
+ dict set fieldSet hourAMPM [incr fieldCount]
+ append postcode "dict set date hourAMPM \[" \
+ "dict get " [list $lookup] " \$field" \
+ [incr captureCount] \
+ "\]\n"
+ }
+ m {
+ lassign [LocaleNumeralMatcher $locale] regex lookup
+ append re $regex
+ dict set fieldSet month [incr fieldCount]
+ append postcode "dict set date month \[" \
+ "dict get " [list $lookup] " \$field" \
+ [incr captureCount] \
+ "\]\n"
+ }
+ M {
+ lassign [LocaleNumeralMatcher $locale] regex lookup
+ append re $regex
+ dict set fieldSet minute [incr fieldCount]
+ append postcode "dict set date minute \[" \
+ "dict get " [list $lookup] " \$field" \
+ [incr captureCount] \
+ "\]\n"
+ }
+ S {
+ lassign [LocaleNumeralMatcher $locale] regex lookup
+ append re $regex
+ dict set fieldSet second [incr fieldCount]
+ append postcode "dict set date second \[" \
+ "dict get " [list $lookup] " \$field" \
+ [incr captureCount] \
+ "\]\n"
+ }
+ u - w {
+ lassign [LocaleNumeralMatcher $locale] regex lookup
+ append re $regex
+ dict set fieldSet dayOfWeek [incr fieldCount]
+ append postcode "set dow \[dict get " [list $lookup] \
+ { $field} [incr captureCount] \] \n \
+ {
+ if { $dow == 0 } {
+ set dow 7
+ } elseif { $dow > 7 } {
+ return -code error \
+ -errorcode [list CLOCK badDayOfWeek] \
+ "day of week is greater than 7"
+ }
+ dict set date dayOfWeek $dow
+ }
+ }
+ y {
+ lassign [LocaleNumeralMatcher $locale] regex lookup
+ append re $regex
+ dict set fieldSet yearOfCentury [incr fieldCount]
+ append postcode {dict set date yearOfCentury } \[ \
+ {dict get } [list $lookup] { $field} \
+ [incr captureCount] \] \n
+ }
+ default {
+ append re %O
+ if { ! [string is alnum $c] } {
+ append re \\
+ }
+ append re $c
+ }
+ }
+ set state {}
+ }
+ }
+ }
+
+ # Clean up any unfinished format groups
+
+ append re $state \\s*\$
+
+ # Build the procedure
+
+ set procBody {}
+ append procBody "variable ::tcl::clock::TZData" \n
+ append procBody "if \{ !\[ regexp -nocase [list $re] \$string ->"
+ for { set i 1 } { $i <= $captureCount } { incr i } {
+ append procBody " " field $i
+ }
+ append procBody "\] \} \{" \n
+ append procBody {
+ return -code error -errorcode [list CLOCK badInputString] \
+ {input string does not match supplied format}
+ }
+ append procBody \}\n
+ append procBody "set date \[dict create\]" \n
+ append procBody {dict set date tzName $timeZone} \n
+ append procBody $postcode
+ append procBody [list set changeover [mc GREGORIAN_CHANGE_DATE]] \n
+
+ # Get time zone if needed
+
+ if { ![dict exists $fieldSet seconds]
+ && ![dict exists $fieldSet starDate] } {
+ if { [dict exists $fieldSet tzName] } {
+ append procBody {
+ set timeZone [dict get $date tzName]
+ }
+ }
+ append procBody {
+ ::tcl::clock::SetupTimeZone $timeZone
+ }
+ }
+
+ # Add code that gets Julian Day Number from the fields.
+
+ append procBody [MakeParseCodeFromFields $fieldSet $DateParseActions]
+
+ # Get time of day
+
+ append procBody [MakeParseCodeFromFields $fieldSet $TimeParseActions]
+
+ # Assemble seconds, and convert local nominal time to UTC.
+
+ if { ![dict exists $fieldSet seconds]
+ && ![dict exists $fieldSet starDate] } {
+ append procBody {
+ if { [dict get $date julianDay] > 5373484 } {
+ return -code error -errorcode [list CLOCK dateTooLarge] \
+ "requested date too large to represent"
+ }
+ dict set date localSeconds \
+ [expr { -210866803200
+ + ( 86400 * wide([dict get $date julianDay]) )
+ + [dict get $date secondOfDay] }]
+ }
+ append procBody {
+ set date [::tcl::clock::ConvertLocalToUTC $date[set date {}] \
+ $TZData($timeZone) \
+ $changeover]
+ }
+ }
+
+ # Return result
+
+ append procBody {return [dict get $date seconds]} \n
+
+ proc $procName { string baseTime timeZone } $procBody
+
+ # puts [list proc $procName [list string baseTime timeZone] $procBody]
+
+ return $procName
+}
+
+#----------------------------------------------------------------------
+#
+# LocaleNumeralMatcher --
+#
+# Composes a regexp that captures the numerals in the given
+# locale, and a dictionary to map them to conventional numerals.
+#
+# Parameters:
+# locale - Name of the current locale
+#
+# Results:
+# Returns a two-element list comprising the regexp and the
+# dictionary.
+#
+# Side effects:
+# Caches the result.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::LocaleNumeralMatcher {l} {
+
+ variable LocaleNumeralCache
+
+ if { ![dict exists $LocaleNumeralCache $l] } {
+ set d {}
+ set i 0
+ set sep \(
+ foreach n [mc LOCALE_NUMERALS] {
+ dict set d $n $i
+ regsub -all {[^[:alnum:]]} $n \\\\& subex
+ append re $sep $subex
+ set sep |
+ incr i
+ }
+ append re \)
+ dict set LocaleNumeralCache $l [list $re $d]
+ }
+ return [dict get $LocaleNumeralCache $l]
+}
+
+
+
+#----------------------------------------------------------------------
+#
+# UniquePrefixRegexp --
+#
+# Composes a regexp that performs unique-prefix matching. The
+# RE matches one of a supplied set of strings, or any unique
+# prefix thereof.
+#
+# Parameters:
+# data - List of alternating match-strings and values.
+# Match-strings with distinct values are considered
+# distinct.
+#
+# Results:
+# Returns a two-element list. The first is a regexp that
+# matches any unique prefix of any of the strings. The second
+# is a dictionary whose keys are match values from the regexp
+# and whose values are the corresponding values from 'data'.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::UniquePrefixRegexp { data } {
+
+ # The 'successors' dictionary will contain, for each string that
+ # is a prefix of any key, all characters that may follow that
+ # prefix. The 'prefixMapping' dictionary will have keys that
+ # are prefixes of keys and values that correspond to the keys.
+
+ set prefixMapping [dict create]
+ set successors [dict create {} {}]
+
+ # Walk the key-value pairs
+
+ foreach { key value } $data {
+
+ # Construct all prefixes of the key;
+
+ set prefix {}
+ foreach char [split $key {}] {
+ set oldPrefix $prefix
+ dict set successors $oldPrefix $char {}
+ append prefix $char
+
+ # Put the prefixes in the 'prefixMapping' and 'successors'
+ # dictionaries
+
+ dict lappend prefixMapping $prefix $value
+ if { ![dict exists $successors $prefix] } {
+ dict set successors $prefix {}
+ }
+ }
+ }
+
+ # Identify those prefixes that designate unique values, and
+ # those that are the full keys
+
+ set uniquePrefixMapping {}
+ dict for { key valueList } $prefixMapping {
+ if { [llength $valueList] == 1 } {
+ dict set uniquePrefixMapping $key [lindex $valueList 0]
+ }
+ }
+ foreach { key value } $data {
+ dict set uniquePrefixMapping $key $value
+ }
+
+ # Construct the re.
+
+ return [list \
+ [MakeUniquePrefixRegexp $successors $uniquePrefixMapping {}] \
+ $uniquePrefixMapping]
+}
+
+#----------------------------------------------------------------------
+#
+# MakeUniquePrefixRegexp --
+#
+# Service procedure for 'UniquePrefixRegexp' that constructs
+# a regular expresison that matches the unique prefixes.
+#
+# Parameters:
+# successors - Dictionary whose keys are all prefixes
+# of keys passed to 'UniquePrefixRegexp' and whose
+# values are dictionaries whose keys are the characters
+# that may follow those prefixes.
+# uniquePrefixMapping - Dictionary whose keys are the unique
+# prefixes and whose values are not examined.
+# prefixString - Current prefix being processed.
+#
+# Results:
+# Returns a constructed regular expression that matches the set
+# of unique prefixes beginning with the 'prefixString'.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::MakeUniquePrefixRegexp { successors
+ uniquePrefixMapping
+ prefixString } {
+
+ # Get the characters that may follow the current prefix string
+
+ set schars [lsort -ascii [dict keys [dict get $successors $prefixString]]]
+ if { [llength $schars] == 0 } {
+ return {}
+ }
+
+ # If there is more than one successor character, or if the current
+ # prefix is a unique prefix, surround the generated re with non-capturing
+ # parentheses.
+
+ set re {}
+ if { [dict exists $uniquePrefixMapping $prefixString]
+ || [llength $schars] > 1 } {
+ append re "(?:"
+ }
+
+ # Generate a regexp that matches the successors.
+
+ set sep ""
+ foreach { c } $schars {
+ set nextPrefix $prefixString$c
+ regsub -all {[^[:alnum:]]} $c \\\\& rechar
+ append re $sep $rechar \
+ [MakeUniquePrefixRegexp \
+ $successors $uniquePrefixMapping $nextPrefix]
+ set sep |
+ }
+
+ # If the current prefix is a unique prefix, make all following text
+ # optional. Otherwise, if there is more than one successor character,
+ # close the non-capturing parentheses.
+
+ if { [dict exists $uniquePrefixMapping $prefixString] } {
+ append re ")?"
+ } elseif { [llength $schars] > 1 } {
+ append re ")"
+ }
+
+ return $re
+}
+
+#----------------------------------------------------------------------
+#
+# MakeParseCodeFromFields --
+#
+# Composes Tcl code to extract the Julian Day Number from a
+# dictionary containing date fields.
+#
+# Parameters:
+# dateFields -- Dictionary whose keys are fields of the date,
+# and whose values are the rightmost positions
+# at which those fields appear.
+# parseActions -- List of triples: field set, priority, and
+# code to emit. Smaller priorities are better, and
+# the list must be in ascending order by priority
+#
+# Results:
+# Returns a burst of code that extracts the day number from the
+# given date.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::MakeParseCodeFromFields { dateFields parseActions } {
+
+ set currPrio 999
+ set currFieldPos [list]
+ set currCodeBurst {
+ error "in ::tcl::clock::MakeParseCodeFromFields: can't happen"
+ }
+
+ foreach { fieldSet prio parseAction } $parseActions {
+
+ # If we've found an answer that's better than any that follow,
+ # quit now.
+
+ if { $prio > $currPrio } {
+ break
+ }
+
+ # Accumulate the field positions that are used in the current
+ # field grouping.
+
+ set fieldPos [list]
+ set ok true
+ foreach field $fieldSet {
+ if { ! [dict exists $dateFields $field] } {
+ set ok 0
+ break
+ }
+ lappend fieldPos [dict get $dateFields $field]
+ }
+
+ # Quit if we don't have a complete set of fields
+ if { !$ok } {
+ continue
+ }
+
+ # Determine whether the current answer is better than the last.
+
+ set fPos [lsort -integer -decreasing $fieldPos]
+
+ if { $prio == $currPrio } {
+ foreach currPos $currFieldPos newPos $fPos {
+ if { ![string is integer $newPos]
+ || ![string is integer $currPos]
+ || $newPos > $currPos } {
+ break
+ }
+ if { $newPos < $currPos } {
+ set ok 0
+ break
+ }
+ }
+ }
+ if { !$ok } {
+ continue
+ }
+
+ # Remember the best possibility for extracting date information
+
+ set currPrio $prio
+ set currFieldPos $fPos
+ set currCodeBurst $parseAction
+
+ }
+
+ return $currCodeBurst
+
+}
+
+#----------------------------------------------------------------------
+#
+# EnterLocale --
+#
+# Switch [mclocale] to a given locale if necessary
+#
+# Parameters:
+# locale -- Desired locale
+# oldLocaleVar -- Name of a variable in caller's scope that
+# tracks the previous locale name.
+#
+# Results:
+# Returns the locale that was previously current.
+#
+# Side effects:
+# Does [mclocale]. If necessary, uses [mcload] to load the
+# designated locale's files, and tracks that it has done so
+# in the 'McLoaded' variable.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::EnterLocale { locale oldLocaleVar } {
+
+ upvar 1 $oldLocaleVar oldLocale
+
+ variable MsgDir
+ variable McLoaded
+
+ set oldLocale [mclocale]
+ if { $locale eq {system} } {
+
+ if { $::tcl_platform(platform) ne {windows} } {
+
+ # On a non-windows platform, the 'system' locale is
+ # the same as the 'current' locale
+
+ set locale current
+ } else {
+
+ # On a windows platform, the 'system' locale is
+ # adapted from the 'current' locale by applying the
+ # date and time formats from the Control Panel.
+ # First, load the 'current' locale if it's not yet loaded
+
+ if {![dict exists $McLoaded $oldLocale] } {
+ mcload $MsgDir
+ dict set McLoaded $oldLocale {}
+ }
+
+ # Make a new locale string for the system locale, and
+ # get the Control Panel information
+
+ set locale ${oldLocale}_windows
+ if { ![dict exists $McLoaded $locale] } {
+ LoadWindowsDateTimeFormats $locale
+ dict set McLoaded $locale {}
+ }
+ }
+ }
+ if { $locale eq {current}} {
+ set locale $oldLocale
+ unset oldLocale
+ } elseif { $locale eq $oldLocale } {
+ unset oldLocale
+ } else {
+ mclocale $locale
+ }
+ if { ![dict exists $McLoaded $locale] } {
+ mcload $MsgDir
+ dict set McLoaded $locale {}
+ }
+
+}
+
+#----------------------------------------------------------------------
+#
+# LoadWindowsDateTimeFormats --
+#
+# Load the date/time formats from the Control Panel in Windows
+# and convert them so that they're usable by Tcl.
+#
+# Parameters:
+# locale - Name of the locale in whose message catalog
+# the converted formats are to be stored.
+#
+# Results:
+# None.
+#
+# Side effects:
+# Updates the given message catalog with the locale strings.
+#
+# Presumes that on entry, [mclocale] is set to the current locale,
+# so that default strings can be obtained if the Registry query
+# fails.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::LoadWindowsDateTimeFormats { locale } {
+
+ # Bail out if we can't find the Registry
+
+ variable NoRegistry
+ if { [info exists NoRegistry] } return
+
+ if { ![catch {
+ registry get "HKEY_CURRENT_USER\\Control Panel\\International" \
+ sShortDate
+ } string] } {
+ set quote {}
+ set datefmt {}
+ foreach { unquoted quoted } [split $string '] {
+ append datefmt $quote [string map {
+ dddd %A
+ ddd %a
+ dd %d
+ d %e
+ MMMM %B
+ MMM %b
+ MM %m
+ M %N
+ yyyy %Y
+ yy %y
+ y %y
+ gg {}
+ } $unquoted]
+ if { $quoted eq {} } {
+ set quote '
+ } else {
+ set quote $quoted
+ }
+ }
+ ::msgcat::mcset $locale DATE_FORMAT $datefmt
+ }
+
+ if { ![catch {
+ registry get "HKEY_CURRENT_USER\\Control Panel\\International" \
+ sLongDate
+ } string] } {
+ set quote {}
+ set ldatefmt {}
+ foreach { unquoted quoted } [split $string '] {
+ append ldatefmt $quote [string map {
+ dddd %A
+ ddd %a
+ dd %d
+ d %e
+ MMMM %B
+ MMM %b
+ MM %m
+ M %N
+ yyyy %Y
+ yy %y
+ y %y
+ gg {}
+ } $unquoted]
+ if { $quoted eq {} } {
+ set quote '
+ } else {
+ set quote $quoted
+ }
+ }
+ ::msgcat::mcset $locale LOCALE_DATE_FORMAT $ldatefmt
+ }
+
+ if { ![catch {
+ registry get "HKEY_CURRENT_USER\\Control Panel\\International" \
+ sTimeFormat
+ } string] } {
+ set quote {}
+ set timefmt {}
+ foreach { unquoted quoted } [split $string '] {
+ append timefmt $quote [string map {
+ HH %H
+ H %k
+ hh %I
+ h %l
+ mm %M
+ m %M
+ ss %S
+ s %S
+ tt %p
+ t %p
+ } $unquoted]
+ if { $quoted eq {} } {
+ set quote '
+ } else {
+ set quote $quoted
+ }
+ }
+ ::msgcat::mcset $locale TIME_FORMAT $timefmt
+ }
+
+ catch {
+ ::msgcat::mcset $locale DATE_TIME_FORMAT "$datefmt $timefmt"
+ }
+ catch {
+ ::msgcat::mcset $locale LOCALE_DATE_TIME_FORMAT "$ldatefmt $timefmt"
+ }
+
+ return
+
+}
+
+#----------------------------------------------------------------------
+#
+# LocalizeFormat --
+#
+# Map away locale-dependent format groups in a clock format.
+#
+# Parameters:
+# locale -- Current [mclocale] locale, supplied to avoid
+# an extra call
+# format -- Format supplied to [clock scan] or [clock format]
+#
+# Results:
+# Returns the string with locale-dependent composite format
+# groups substituted out.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::LocalizeFormat { locale format } {
+
+ variable McLoaded
+
+ if { [dict exists $McLoaded $locale FORMAT $format] } {
+ return [dict get $McLoaded $locale FORMAT $format]
+ }
+ set inFormat $format
+
+ # Handle locale-dependent format groups by mapping them out of the format
+ # string. Note that the order of the [string map] operations is
+ # significant because later formats can refer to later ones; for example
+ # %c can refer to %X, which in turn can refer to %T.
+
+ set list {
+ %% %%
+ %D %m/%d/%Y
+ %+ {%a %b %e %H:%M:%S %Z %Y}
+ }
+ lappend list %EY [string map $list [mc LOCALE_YEAR_FORMAT]]
+ lappend list %T [string map $list [mc TIME_FORMAT_24_SECS]]
+ lappend list %R [string map $list [mc TIME_FORMAT_24]]
+ lappend list %r [string map $list [mc TIME_FORMAT_12]]
+ lappend list %X [string map $list [mc TIME_FORMAT]]
+ lappend list %EX [string map $list [mc LOCALE_TIME_FORMAT]]
+ lappend list %x [string map $list [mc DATE_FORMAT]]
+ lappend list %Ex [string map $list [mc LOCALE_DATE_FORMAT]]
+ lappend list %c [string map $list [mc DATE_TIME_FORMAT]]
+ lappend list %Ec [string map $list [mc LOCALE_DATE_TIME_FORMAT]]
+ set format [string map $list $format]
+
+ dict set McLoaded $locale FORMAT $inFormat $format
+ return $format
+}
+
+#----------------------------------------------------------------------
+#
+# FormatNumericTimeZone --
+#
+# Formats a time zone as +hhmmss
+#
+# Parameters:
+# z - Time zone in seconds east of Greenwich
+#
+# Results:
+# Returns the time zone formatted in a numeric form
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::FormatNumericTimeZone { z } {
+
+ if { $z < 0 } {
+ set z [expr { - $z }]
+ set retval -
+ } else {
+ set retval +
+ }
+ append retval [::format %02d [expr { $z / 3600 }]]
+ set z [expr { $z % 3600 }]
+ append retval [::format %02d [expr { $z / 60 }]]
+ set z [expr { $z % 60 }]
+ if { $z != 0 } {
+ append retval [::format %02d $z]
+ }
+ return $retval
+
+}
+
+#----------------------------------------------------------------------
+#
+# FormatStarDate --
+#
+# Formats a date as a StarDate.
+#
+# Parameters:
+# date - Dictionary containing 'year', 'dayOfYear', and
+# 'localSeconds' fields.
+#
+# Results:
+# Returns the given date formatted as a StarDate.
+#
+# Side effects:
+# None.
+#
+# Jeff Hobbs put this in to support an atrocious pun about Tcl being
+# "Enterprise ready." Now we're stuck with it.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::FormatStarDate { date } {
+
+ variable Roddenberry
+
+ # Get day of year, zero based
+
+ set doy [expr { [dict get $date dayOfYear] - 1 }]
+
+ # Determine whether the year is a leap year
+
+ set lp [IsGregorianLeapYear $date]
+
+ # Convert day of year to a fractional year
+
+ if { $lp } {
+ set fractYear [expr { 1000 * $doy / 366 }]
+ } else {
+ set fractYear [expr { 1000 * $doy / 365 }]
+ }
+
+ # Put together the StarDate
+
+ return [::format "Stardate %02d%03d.%1d" \
+ [expr { [dict get $date year] - $Roddenberry }] \
+ $fractYear \
+ [expr { [dict get $date localSeconds] % 86400
+ / ( 86400 / 10 ) }]]
+}
+
+#----------------------------------------------------------------------
+#
+# ParseStarDate --
+#
+# Parses a StarDate
+#
+# Parameters:
+# year - Year from the Roddenberry epoch
+# fractYear - Fraction of a year specifiying the day of year.
+# fractDay - Fraction of a day
+#
+# Results:
+# Returns a count of seconds from the Posix epoch.
+#
+# Side effects:
+# None.
+#
+# Jeff Hobbs put this in to support an atrocious pun about Tcl being
+# "Enterprise ready." Now we're stuck with it.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::ParseStarDate { year fractYear fractDay } {
+
+ variable Roddenberry
+
+ # Build a tentative date from year and fraction.
+
+ set date [dict create \
+ gregorian 1 \
+ era CE \
+ year [expr { $year + $Roddenberry }] \
+ dayOfYear [expr { $fractYear * 365 / 1000 + 1 }]]
+ set date [GetJulianDayFromGregorianEraYearDay $date[set date {}]]
+
+ # Determine whether the given year is a leap year
+
+ set lp [IsGregorianLeapYear $date]
+
+ # Reconvert the fractional year according to whether the given
+ # year is a leap year
+
+ if { $lp } {
+ dict set date dayOfYear \
+ [expr { $fractYear * 366 / 1000 + 1 }]
+ } else {
+ dict set date dayOfYear \
+ [expr { $fractYear * 365 / 1000 + 1 }]
+ }
+ dict unset date julianDay
+ dict unset date gregorian
+ set date [GetJulianDayFromGregorianEraYearDay $date[set date {}]]
+
+ return [expr { 86400 * [dict get $date julianDay]
+ - 210866803200
+ + ( 86400 / 10 ) * $fractDay }]
+
+}
+
+#----------------------------------------------------------------------
+#
+# ScanWide --
+#
+# Scans a wide integer from an input
+#
+# Parameters:
+# str - String containing a decimal wide integer
+#
+# Results:
+# Returns the string as a pure wide integer. Throws an error if
+# the string is misformatted or out of range.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::ScanWide { str } {
+ set count [::scan $str {%ld %c} result junk]
+ if { $count != 1 } {
+ return -code error -errorcode [list CLOCK notAnInteger $str] \
+ "\"$str\" is not an integer"
+ }
+ if { [incr result 0] != $str } {
+ return -code error -errorcode [list CLOCK integervalueTooLarge] \
+ "integer value too large to represent"
+ }
+ return $result
+}
+
+#----------------------------------------------------------------------
+#
+# InterpretTwoDigitYear --
+#
+# Given a date that contains only the year of the century,
+# determines the target value of a two-digit year.
+#
+# Parameters:
+# date - Dictionary containing fields of the date.
+# baseTime - Base time relative to which the date is expressed.
+# twoDigitField - Name of the field that stores the two-digit year.
+# Default is 'yearOfCentury'
+# fourDigitField - Name of the field that will receive the four-digit
+# year. Default is 'year'
+#
+# Results:
+# Returns the dictionary augmented with the four-digit year, stored in
+# the given key.
+#
+# Side effects:
+# None.
+#
+# The current rule for interpreting a two-digit year is that the year
+# shall be between 1937 and 2037, thus staying within the range of a
+# 32-bit signed value for time. This rule may change to a sliding
+# window in future versions, so the 'baseTime' parameter (which is
+# currently ignored) is provided in the procedure signature.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::InterpretTwoDigitYear { date baseTime
+ { twoDigitField yearOfCentury }
+ { fourDigitField year } } {
+
+ set yr [dict get $date $twoDigitField]
+ if { $yr <= 37 } {
+ dict set date $fourDigitField [expr { $yr + 2000 }]
+ } else {
+ dict set date $fourDigitField [expr { $yr + 1900 }]
+ }
+ return $date
+
+}
+
+#----------------------------------------------------------------------
+#
+# AssignBaseYear --
+#
+# Places the number of the current year into a dictionary.
+#
+# Parameters:
+# date - Dictionary value to update
+# baseTime - Base time from which to extract the year, expressed
+# in seconds from the Posix epoch
+# timezone - the time zone in which the date is being scanned
+# changeover - the Julian Day on which the Gregorian calendar
+# was adopted in the target locale.
+#
+# Results:
+# Returns the dictionary with the current year assigned.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::AssignBaseYear { date baseTime timezone changeover } {
+
+ variable TZData
+
+ # Find the Julian Day Number corresponding to the base time, and
+ # find the Gregorian year corresponding to that Julian Day.
+
+ set date2 [GetDateFields $baseTime $TZData($timezone) $changeover]
+
+ # Store the converted year
+
+ dict set date era [dict get $date2 era]
+ dict set date year [dict get $date2 year]
+
+ return $date
+
+}
+
+#----------------------------------------------------------------------
+#
+# AssignBaseIso8601Year --
+#
+# Determines the base year in the ISO8601 fiscal calendar.
+#
+# Parameters:
+# date - Dictionary containing the fields of the date that
+# is to be augmented with the base year.
+# baseTime - Base time expressed in seconds from the Posix epoch.
+# timeZone - Target time zone
+# changeover - Julian Day of adoption of the Gregorian calendar in
+# the target locale.
+#
+# Results:
+# Returns the given date with "iso8601Year" set to the
+# base year.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::AssignBaseIso8601Year {date baseTime timeZone changeover} {
+
+ variable TZData
+
+ # Find the Julian Day Number corresponding to the base time
+
+ set date2 [GetDateFields $baseTime $TZData($timeZone) $changeover]
+
+ # Calculate the ISO8601 date and transfer the year
+
+ dict set date era CE
+ dict set date iso8601Year [dict get $date2 iso8601Year]
+ return $date
+}
+
+#----------------------------------------------------------------------
+#
+# AssignBaseMonth --
+#
+# Places the number of the current year and month into a
+# dictionary.
+#
+# Parameters:
+# date - Dictionary value to update
+# baseTime - Time from which the year and month are to be
+# obtained, expressed in seconds from the Posix epoch.
+# timezone - Name of the desired time zone
+# changeover - Julian Day on which the Gregorian calendar was adopted.
+#
+# Results:
+# Returns the dictionary with the base year and month assigned.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::AssignBaseMonth {date baseTime timezone changeover} {
+
+ variable TZData
+
+ # Find the year and month corresponding to the base time
+
+ set date2 [GetDateFields $baseTime $TZData($timezone) $changeover]
+ dict set date era [dict get $date2 era]
+ dict set date year [dict get $date2 year]
+ dict set date month [dict get $date2 month]
+ return $date
+
+}
+
+#----------------------------------------------------------------------
+#
+# AssignBaseWeek --
+#
+# Determines the base year and week in the ISO8601 fiscal calendar.
+#
+# Parameters:
+# date - Dictionary containing the fields of the date that
+# is to be augmented with the base year and week.
+# baseTime - Base time expressed in seconds from the Posix epoch.
+# changeover - Julian Day on which the Gregorian calendar was adopted
+# in the target locale.
+#
+# Results:
+# Returns the given date with "iso8601Year" set to the
+# base year and "iso8601Week" to the week number.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::AssignBaseWeek {date baseTime timeZone changeover} {
+
+ variable TZData
+
+ # Find the Julian Day Number corresponding to the base time
+
+ set date2 [GetDateFields $baseTime $TZData($timeZone) $changeover]
+
+ # Calculate the ISO8601 date and transfer the year
+
+ dict set date era CE
+ dict set date iso8601Year [dict get $date2 iso8601Year]
+ dict set date iso8601Week [dict get $date2 iso8601Week]
+ return $date
+}
+
+#----------------------------------------------------------------------
+#
+# AssignBaseJulianDay --
+#
+# Determines the base day for a time-of-day conversion.
+#
+# Parameters:
+# date - Dictionary that is to get the base day
+# baseTime - Base time expressed in seconds from the Posix epoch
+# changeover - Julian day on which the Gregorian calendar was
+# adpoted in the target locale.
+#
+# Results:
+# Returns the given dictionary augmented with a 'julianDay' field
+# that contains the base day.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::AssignBaseJulianDay { date baseTime timeZone changeover } {
+
+ variable TZData
+
+ # Find the Julian Day Number corresponding to the base time
+
+ set date2 [GetDateFields $baseTime $TZData($timeZone) $changeover]
+ dict set date julianDay [dict get $date2 julianDay]
+
+ return $date
+}
+
+#----------------------------------------------------------------------
+#
+# InterpretHMSP --
+#
+# Interprets a time in the form "hh:mm:ss am".
+#
+# Parameters:
+# date -- Dictionary containing "hourAMPM", "minute", "second"
+# and "amPmIndicator" fields.
+#
+# Results:
+# Returns the number of seconds from local midnight.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::InterpretHMSP { date } {
+
+ set hr [dict get $date hourAMPM]
+ if { $hr == 12 } {
+ set hr 0
+ }
+ if { [dict get $date amPmIndicator] } {
+ incr hr 12
+ }
+ dict set date hour $hr
+ return [InterpretHMS $date[set date {}]]
+
+}
+
+#----------------------------------------------------------------------
+#
+# InterpretHMS --
+#
+# Interprets a 24-hour time "hh:mm:ss"
+#
+# Parameters:
+# date -- Dictionary containing the "hour", "minute" and "second"
+# fields.
+#
+# Results:
+# Returns the given dictionary augmented with a "secondOfDay"
+# field containing the number of seconds from local midnight.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::InterpretHMS { date } {
+
+ return [expr { ( [dict get $date hour] * 60
+ + [dict get $date minute] ) * 60
+ + [dict get $date second] }]
+
+}
+
+#----------------------------------------------------------------------
+#
+# GetSystemTimeZone --
+#
+# Determines the system time zone, which is the default for the
+# 'clock' command if no other zone is supplied.
+#
+# Parameters:
+# None.
+#
+# Results:
+# Returns the system time zone.
+#
+# Side effects:
+# Stores the sustem time zone in the 'CachedSystemTimeZone'
+# variable, since determining it may be an expensive process.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::GetSystemTimeZone {} {
+
+ variable CachedSystemTimeZone
+ variable TimeZoneBad
+
+ if {[set result [getenv TCL_TZ]] ne {}} {
+ set timezone $result
+ } elseif {[set result [getenv TZ]] ne {}} {
+ set timezone $result
+ } elseif { [info exists CachedSystemTimeZone] } {
+ set timezone $CachedSystemTimeZone
+ } elseif { $::tcl_platform(platform) eq {windows} } {
+ set timezone [GuessWindowsTimeZone]
+ } elseif { [file exists /etc/localtime]
+ && ![catch {ReadZoneinfoFile \
+ Tcl/Localtime /etc/localtime}] } {
+ set timezone :Tcl/Localtime
+ } else {
+ set timezone :localtime
+ }
+ set CachedSystemTimeZone $timezone
+ if { ![dict exists $TimeZoneBad $timezone] } {
+ dict set TimeZoneBad $timezone [catch {SetupTimeZone $timezone}]
+ }
+ if { [dict get $TimeZoneBad $timezone] } {
+ return :localtime
+ } else {
+ return $timezone
+ }
+
+}
+
+#----------------------------------------------------------------------
+#
+# ConvertLegacyTimeZone --
+#
+# Given an alphanumeric time zone identifier and the system
+# time zone, convert the alphanumeric identifier to an
+# unambiguous time zone.
+#
+# Parameters:
+# tzname - Name of the time zone to convert
+#
+# Results:
+# Returns a time zone name corresponding to tzname, but
+# in an unambiguous form, generally +hhmm.
+#
+# This procedure is implemented primarily to allow the parsing of
+# RFC822 date/time strings. Processing a time zone name on input
+# is not recommended practice, because there is considerable room
+# for ambiguity; for instance, is BST Brazilian Standard Time, or
+# British Summer Time?
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::ConvertLegacyTimeZone { tzname } {
+
+ variable LegacyTimeZone
+
+ set tzname [string tolower $tzname]
+ if { ![dict exists $LegacyTimeZone $tzname] } {
+ return -code error -errorcode [list CLOCK badTZName $tzname] \
+ "time zone \"$tzname\" not found"
+ } else {
+ return [dict get $LegacyTimeZone $tzname]
+ }
+
+}
+
+#----------------------------------------------------------------------
+#
+# SetupTimeZone --
+#
+# Given the name or specification of a time zone, sets up
+# its in-memory data.
+#
+# Parameters:
+# tzname - Name of a time zone
+#
+# Results:
+# Unless the time zone is ':localtime', sets the TZData array
+# to contain the lookup table for local<->UTC conversion.
+# Returns an error if the time zone cannot be parsed.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::SetupTimeZone { timezone } {
+
+ variable TZData
+
+ if {! [info exists TZData($timezone)] } {
+ variable MINWIDE
+ if { $timezone eq {:localtime} } {
+
+ # Nothing to do, we'll convert using the localtime function
+
+ } elseif { [regexp {^([-+])(\d\d)(?::?(\d\d)(?::?(\d\d))?)?} $timezone \
+ -> s hh mm ss] } {
+
+ # Make a fixed offset
+
+ ::scan $hh %d hh
+ if { $mm eq {} } {
+ set mm 0
+ } else {
+ ::scan $mm %d mm
+ }
+ if { $ss eq {} } {
+ set ss 0
+ } else {
+ ::scan $ss %d ss
+ }
+ set offset [expr { ( $hh * 60 + $mm ) * 60 + $ss }]
+ if { $s eq {-} } {
+ set offset [expr { - $offset }]
+ }
+ set TZData($timezone) [list [list $MINWIDE $offset -1 $timezone]]
+
+ } elseif { [string index $timezone 0] eq {:} } {
+
+ # Convert using a time zone file
+
+ if {
+ [catch {
+ LoadTimeZoneFile [string range $timezone 1 end]
+ }]
+ && [catch {
+ LoadZoneinfoFile [string range $timezone 1 end]
+ }]
+ } {
+ return -code error \
+ -errorcode [list CLOCK badTimeZone $timezone] \
+ "time zone \"$timezone\" not found"
+ }
+
+ } elseif { ![catch {ParsePosixTimeZone $timezone} tzfields] } {
+
+ # This looks like a POSIX time zone - try to process it
+
+ if { [catch {ProcessPosixTimeZone $tzfields} data opts] } {
+ if { [lindex [dict get $opts -errorcode] 0] eq {CLOCK} } {
+ dict unset opts -errorinfo
+ }
+ return -options $opts $data
+ } else {
+ set TZData($timezone) $data
+ }
+
+ } else {
+
+ # We couldn't parse this as a POSIX time zone. Try
+ # again with a time zone file - this time without a colon
+
+ if { [catch { LoadTimeZoneFile $timezone }]
+ && [catch { LoadZoneinfoFile $timezone } - opts] } {
+ dict unset opts -errorinfo
+ return -options $opts "time zone $timezone not found"
+ }
+ set TZData($timezone) $TZData(:$timezone)
+ }
+ }
+
+ return
+}
+
+#----------------------------------------------------------------------
+#
+# GuessWindowsTimeZone --
+#
+# Determines the system time zone on windows.
+#
+# Parameters:
+# None.
+#
+# Results:
+# Returns a time zone specifier that corresponds to the system
+# time zone information found in the Registry.
+#
+# Bugs:
+# Fixed dates for DST change are unimplemented at present, because
+# no time zone information supplied with Windows actually uses
+# them!
+#
+# On a Windows system where neither $env(TCL_TZ) nor $env(TZ) is
+# specified, GuessWindowsTimeZone looks in the Registry for the
+# system time zone information. It then attempts to find an entry
+# in WinZoneInfo for a time zone that uses the same rules. If
+# it finds one, it returns it; otherwise, it constructs a Posix-style
+# time zone string and returns that.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::GuessWindowsTimeZone {} {
+
+ variable WinZoneInfo
+ variable NoRegistry
+ variable TimeZoneBad
+
+ if { [info exists NoRegistry] } {
+ return :localtime
+ }
+
+ # Dredge time zone information out of the registry
+
+ if { [catch {
+ set rpath HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\TimeZoneInformation
+ set data [list \
+ [expr { -60
+ * [registry get $rpath Bias] }] \
+ [expr { -60
+ * [registry get $rpath StandardBias] }] \
+ [expr { -60 \
+ * [registry get $rpath DaylightBias] }]]
+ set stdtzi [registry get $rpath StandardStart]
+ foreach ind {0 2 14 4 6 8 10 12} {
+ binary scan $stdtzi @${ind}s val
+ lappend data $val
+ }
+ set daytzi [registry get $rpath DaylightStart]
+ foreach ind {0 2 14 4 6 8 10 12} {
+ binary scan $daytzi @${ind}s val
+ lappend data $val
+ }
+ }] } {
+
+ # Missing values in the Registry - bail out
+
+ return :localtime
+ }
+
+ # Make up a Posix time zone specifier if we can't find one.
+ # Check here that the tzdata file exists, in case we're running
+ # in an environment (e.g. starpack) where tzdata is incomplete.
+ # (Bug 1237907)
+
+ if { [dict exists $WinZoneInfo $data] } {
+ set tzname [dict get $WinZoneInfo $data]
+ if { ! [dict exists $TimeZoneBad $tzname] } {
+ dict set TimeZoneBad $tzname [catch {SetupTimeZone $tzname}]
+ }
+ } else {
+ set tzname {}
+ }
+ if { $tzname eq {} || [dict get $TimeZoneBad $tzname] } {
+ lassign $data \
+ bias stdBias dstBias \
+ stdYear stdMonth stdDayOfWeek stdDayOfMonth \
+ stdHour stdMinute stdSecond stdMillisec \
+ dstYear dstMonth dstDayOfWeek dstDayOfMonth \
+ dstHour dstMinute dstSecond dstMillisec
+ set stdDelta [expr { $bias + $stdBias }]
+ set dstDelta [expr { $bias + $dstBias }]
+ if { $stdDelta <= 0 } {
+ set stdSignum +
+ set stdDelta [expr { - $stdDelta }]
+ set dispStdSignum -
+ } else {
+ set stdSignum -
+ set dispStdSignum +
+ }
+ set hh [::format %02d [expr { $stdDelta / 3600 }]]
+ set mm [::format %02d [expr { ($stdDelta / 60 ) % 60 }]]
+ set ss [::format %02d [expr { $stdDelta % 60 }]]
+ set tzname {}
+ append tzname < $dispStdSignum $hh $mm > $stdSignum $hh : $mm : $ss
+ if { $stdMonth >= 0 } {
+ if { $dstDelta <= 0 } {
+ set dstSignum +
+ set dstDelta [expr { - $dstDelta }]
+ set dispDstSignum -
+ } else {
+ set dstSignum -
+ set dispDstSignum +
+ }
+ set hh [::format %02d [expr { $dstDelta / 3600 }]]
+ set mm [::format %02d [expr { ($dstDelta / 60 ) % 60 }]]
+ set ss [::format %02d [expr { $dstDelta % 60 }]]
+ append tzname < $dispDstSignum $hh $mm > $dstSignum $hh : $mm : $ss
+ if { $dstYear == 0 } {
+ append tzname ,M $dstMonth . $dstDayOfMonth . $dstDayOfWeek
+ } else {
+ # I have not been able to find any locale on which
+ # Windows converts time zone on a fixed day of the year,
+ # hence don't know how to interpret the fields.
+ # If someone can inform me, I'd be glad to code it up.
+ # For right now, we bail out in such a case.
+ return :localtime
+ }
+ append tzname / [::format %02d $dstHour] \
+ : [::format %02d $dstMinute] \
+ : [::format %02d $dstSecond]
+ if { $stdYear == 0 } {
+ append tzname ,M $stdMonth . $stdDayOfMonth . $stdDayOfWeek
+ } else {
+ # I have not been able to find any locale on which
+ # Windows converts time zone on a fixed day of the year,
+ # hence don't know how to interpret the fields.
+ # If someone can inform me, I'd be glad to code it up.
+ # For right now, we bail out in such a case.
+ return :localtime
+ }
+ append tzname / [::format %02d $stdHour] \
+ : [::format %02d $stdMinute] \
+ : [::format %02d $stdSecond]
+ }
+ dict set WinZoneInfo $data $tzname
+ }
+
+ return [dict get $WinZoneInfo $data]
+
+}
+
+#----------------------------------------------------------------------
+#
+# LoadTimeZoneFile --
+#
+# Load the data file that specifies the conversion between a
+# given time zone and Greenwich.
+#
+# Parameters:
+# fileName -- Name of the file to load
+#
+# Results:
+# None.
+#
+# Side effects:
+# TZData(:fileName) contains the time zone data
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::LoadTimeZoneFile { fileName } {
+ variable DataDir
+ variable TZData
+
+ if { [info exists TZData($fileName)] } {
+ return
+ }
+
+ # Since an unsafe interp uses the [clock] command in the master,
+ # this code is security sensitive. Make sure that the path name
+ # cannot escape the given directory.
+
+ if { ![regexp {^[[.-.][:alpha:]_]+(?:/[[.-.][:alpha:]_]+)*$} $fileName] } {
+ return -code error \
+ -errorcode [list CLOCK badTimeZone $:fileName] \
+ "time zone \":$fileName\" not valid"
+ }
+ if { [catch {
+ source -encoding utf-8 [file join $DataDir $fileName]
+ }] } {
+ return -code error \
+ -errorcode [list CLOCK badTimeZone :$fileName] \
+ "time zone \":$fileName\" not found"
+ }
+ return
+}
+
+#----------------------------------------------------------------------
+#
+# LoadZoneinfoFile --
+#
+# Loads a binary time zone information file in Olson format.
+#
+# Parameters:
+# fileName - Relative path name of the file to load.
+#
+# Results:
+# Returns an empty result normally; returns an error if no
+# Olson file was found or the file was malformed in some way.
+#
+# Side effects:
+# TZData(:fileName) contains the time zone data
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::LoadZoneinfoFile { fileName } {
+
+ variable ZoneinfoPaths
+
+ # Since an unsafe interp uses the [clock] command in the master,
+ # this code is security sensitive. Make sure that the path name
+ # cannot escape the given directory.
+
+ if { ![regexp {^[[.-.][:alpha:]_]+(?:/[[.-.][:alpha:]_]+)*$} $fileName] } {
+ return -code error \
+ -errorcode [list CLOCK badTimeZone $:fileName] \
+ "time zone \":$fileName\" not valid"
+ }
+ foreach d $ZoneinfoPaths {
+ set fname [file join $d $fileName]
+ if { [file readable $fname] && [file isfile $fname] } {
+ break
+ }
+ unset fname
+ }
+ ReadZoneinfoFile $fileName $fname
+}
+
+#----------------------------------------------------------------------
+#
+# ReadZoneinfoFile --
+#
+# Loads a binary time zone information file in Olson format.
+#
+# Parameters:
+# fileName - Name of the time zone (relative path name of the
+# file).
+# fname - Absolute path name of the file.
+#
+# Results:
+# Returns an empty result normally; returns an error if no
+# Olson file was found or the file was malformed in some way.
+#
+# Side effects:
+# TZData(:fileName) contains the time zone data
+#
+#----------------------------------------------------------------------
+
+
+proc ::tcl::clock::ReadZoneinfoFile {fileName fname} {
+ variable MINWIDE
+ variable TZData
+ if { ![info exists fname] } {
+ return -code error "$fileName not found"
+ }
+
+ if { [file size $fname] > 262144 } {
+ return -code error "$fileName too big"
+ }
+
+ # Suck in all the data from the file
+
+ set f [open $fname r]
+ fconfigure $f -translation binary
+ set d [read $f]
+ close $f
+
+ # The file begins with a magic number, sixteen reserved bytes,
+ # and then six 4-byte integers giving counts of fileds in the file.
+
+ binary scan $d a4a1x15IIIIII \
+ magic version nIsGMT nIsStd nLeap nTime nType nChar
+ set seek 44
+ set ilen 4
+ set iformat I
+ if { $magic != {TZif} } {
+ return -code error "$fileName not a time zone information file"
+ }
+ if { $nType > 255 } {
+ return -code error "$fileName contains too many time types"
+ }
+ # Accept only Posix-style zoneinfo. Sorry, 'leaps' bigots.
+ if { $nLeap != 0 } {
+ return -code error "$fileName contains leap seconds"
+ }
+
+ # In a version 2 file, we use the second part of the file, which
+ # contains 64-bit transition times.
+
+ if {$version eq "2"} {
+ set seek [expr {44
+ + 5 * $nTime
+ + 6 * $nType
+ + 4 * $nLeap
+ + $nIsStd
+ + $nIsGMT
+ + $nChar
+ }]
+ binary scan $d @${seek}a4a1x15IIIIII \
+ magic version nIsGMT nIsStd nLeap nTime nType nChar
+ if {$magic ne {TZif}} {
+ return -code error "seek address $seek miscomputed, magic = $magic"
+ }
+ set iformat W
+ set ilen 8
+ incr seek 44
+ }
+
+ # Next come ${nTime} transition times, followed by ${nTime} time type
+ # codes. The type codes are unsigned 1-byte quantities. We insert an
+ # arbitrary start time in front of the transitions.
+
+ binary scan $d @${seek}${iformat}${nTime}c${nTime} times tempCodes
+ incr seek [expr { ($ilen + 1) * $nTime }]
+ set times [linsert $times 0 $MINWIDE]
+ set codes {}
+ foreach c $tempCodes {
+ lappend codes [expr { $c & 0xff }]
+ }
+ set codes [linsert $codes 0 0]
+
+ # Next come ${nType} time type descriptions, each of which has an
+ # offset (seconds east of GMT), a DST indicator, and an index into
+ # the abbreviation text.
+
+ for { set i 0 } { $i < $nType } { incr i } {
+ binary scan $d @${seek}Icc gmtOff isDst abbrInd
+ lappend types [list $gmtOff $isDst $abbrInd]
+ incr seek 6
+ }
+
+ # Next come $nChar characters of time zone name abbreviations,
+ # which are null-terminated.
+ # We build them up into a dictionary indexed by character index,
+ # because that's what's in the indices above.
+
+ binary scan $d @${seek}a${nChar} abbrs
+ incr seek ${nChar}
+ set abbrList [split $abbrs \0]
+ set i 0
+ set abbrevs {}
+ foreach a $abbrList {
+ dict set abbrevs $i $a
+ incr i [expr { [string length $a] + 1 }]
+ }
+
+ # Package up a list of tuples, each of which contains transition time,
+ # seconds east of Greenwich, DST flag and time zone abbreviation.
+
+ set r {}
+ set lastTime $MINWIDE
+ foreach t $times c $codes {
+ if { $t < $lastTime } {
+ return -code error "$fileName has times out of order"
+ }
+ set lastTime $t
+ lassign [lindex $types $c] gmtoff isDst abbrInd
+ set abbrev [dict get $abbrevs $abbrInd]
+ lappend r [list $t $gmtoff $isDst $abbrev]
+ }
+
+ # In a version 2 file, there is also a POSIX-style time zone description
+ # at the very end of the file. To get to it, skip over
+ # nLeap leap second values (8 bytes each),
+ # nIsStd standard/DST indicators and nIsGMT UTC/local indicators.
+
+ if {$version eq {2}} {
+ set seek [expr {$seek + 8 * $nLeap + $nIsStd + $nIsGMT + 1}]
+ set last [string first \n $d $seek]
+ set posix [string range $d $seek [expr {$last-1}]]
+ if {[llength $posix] > 0} {
+ set posixFields [ParsePosixTimeZone $posix]
+ foreach tuple [ProcessPosixTimeZone $posixFields] {
+ lassign $tuple t gmtoff isDst abbrev
+ if {$t > $lastTime} {
+ lappend r $tuple
+ }
+ }
+ }
+ }
+
+ set TZData(:$fileName) $r
+
+ return
+}
+
+#----------------------------------------------------------------------
+#
+# ParsePosixTimeZone --
+#
+# Parses the TZ environment variable in Posix form
+#
+# Parameters:
+# tz Time zone specifier to be interpreted
+#
+# Results:
+# Returns a dictionary whose values contain the various pieces of
+# the time zone specification.
+#
+# Side effects:
+# None.
+#
+# Errors:
+# Throws an error if the syntax of the time zone is incorrect.
+#
+# The following keys are present in the dictionary:
+# stdName - Name of the time zone when Daylight Saving Time
+# is not in effect.
+# stdSignum - Sign (+, -, or empty) of the offset from Greenwich
+# to the given (non-DST) time zone. + and the empty
+# string denote zones west of Greenwich, - denotes east
+# of Greenwich; this is contrary to the ISO convention
+# but follows Posix.
+# stdHours - Hours part of the offset from Greenwich to the given
+# (non-DST) time zone.
+# stdMinutes - Minutes part of the offset from Greenwich to the
+# given (non-DST) time zone. Empty denotes zero.
+# stdSeconds - Seconds part of the offset from Greenwich to the
+# given (non-DST) time zone. Empty denotes zero.
+# dstName - Name of the time zone when DST is in effect, or the
+# empty string if the time zone does not observe Daylight
+# Saving Time.
+# dstSignum, dstHours, dstMinutes, dstSeconds -
+# Fields corresponding to stdSignum, stdHours, stdMinutes,
+# stdSeconds for the Daylight Saving Time version of the
+# time zone. If dstHours is empty, it is presumed to be 1.
+# startDayOfYear - The ordinal number of the day of the year on which
+# Daylight Saving Time begins. If this field is
+# empty, then DST begins on a given month-week-day,
+# as below.
+# startJ - The letter J, or an empty string. If a J is present in
+# this field, then startDayOfYear does not count February 29
+# even in leap years.
+# startMonth - The number of the month in which Daylight Saving Time
+# begins, supplied if startDayOfYear is empty. If both
+# startDayOfYear and startMonth are empty, then US rules
+# are presumed.
+# startWeekOfMonth - The number of the week in the month in which
+# Daylight Saving Time begins, in the range 1-5.
+# 5 denotes the last week of the month even in a
+# 4-week month.
+# startDayOfWeek - The number of the day of the week (Sunday=0,
+# Saturday=6) on which Daylight Saving Time begins.
+# startHours - The hours part of the time of day at which Daylight
+# Saving Time begins. An empty string is presumed to be 2.
+# startMinutes - The minutes part of the time of day at which DST begins.
+# An empty string is presumed zero.
+# startSeconds - The seconds part of the time of day at which DST begins.
+# An empty string is presumed zero.
+# endDayOfYear, endJ, endMonth, endWeekOfMonth, endDayOfWeek,
+# endHours, endMinutes, endSeconds -
+# Specify the end of DST in the same way that the start* fields
+# specify the beginning of DST.
+#
+# This procedure serves only to break the time specifier into fields.
+# No attempt is made to canonicalize the fields or supply default values.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::ParsePosixTimeZone { tz } {
+
+ if {[regexp -expanded -nocase -- {
+ ^
+ # 1 - Standard time zone name
+ ([[:alpha:]]+ | <[-+[:alnum:]]+>)
+ # 2 - Standard time zone offset, signum
+ ([-+]?)
+ # 3 - Standard time zone offset, hours
+ ([[:digit:]]{1,2})
+ (?:
+ # 4 - Standard time zone offset, minutes
+ : ([[:digit:]]{1,2})
+ (?:
+ # 5 - Standard time zone offset, seconds
+ : ([[:digit:]]{1,2} )
+ )?
+ )?
+ (?:
+ # 6 - DST time zone name
+ ([[:alpha:]]+ | <[-+[:alnum:]]+>)
+ (?:
+ (?:
+ # 7 - DST time zone offset, signum
+ ([-+]?)
+ # 8 - DST time zone offset, hours
+ ([[:digit:]]{1,2})
+ (?:
+ # 9 - DST time zone offset, minutes
+ : ([[:digit:]]{1,2})
+ (?:
+ # 10 - DST time zone offset, seconds
+ : ([[:digit:]]{1,2})
+ )?
+ )?
+ )?
+ (?:
+ ,
+ (?:
+ # 11 - Optional J in n and Jn form 12 - Day of year
+ ( J ? ) ( [[:digit:]]+ )
+ | M
+ # 13 - Month number 14 - Week of month 15 - Day of week
+ ( [[:digit:]] + )
+ [.] ( [[:digit:]] + )
+ [.] ( [[:digit:]] + )
+ )
+ (?:
+ # 16 - Start time of DST - hours
+ / ( [[:digit:]]{1,2} )
+ (?:
+ # 17 - Start time of DST - minutes
+ : ( [[:digit:]]{1,2} )
+ (?:
+ # 18 - Start time of DST - seconds
+ : ( [[:digit:]]{1,2} )
+ )?
+ )?
+ )?
+ ,
+ (?:
+ # 19 - Optional J in n and Jn form 20 - Day of year
+ ( J ? ) ( [[:digit:]]+ )
+ | M
+ # 21 - Month number 22 - Week of month 23 - Day of week
+ ( [[:digit:]] + )
+ [.] ( [[:digit:]] + )
+ [.] ( [[:digit:]] + )
+ )
+ (?:
+ # 24 - End time of DST - hours
+ / ( [[:digit:]]{1,2} )
+ (?:
+ # 25 - End time of DST - minutes
+ : ( [[:digit:]]{1,2} )
+ (?:
+ # 26 - End time of DST - seconds
+ : ( [[:digit:]]{1,2} )
+ )?
+ )?
+ )?
+ )?
+ )?
+ )?
+ $
+ } $tz -> x(stdName) x(stdSignum) x(stdHours) x(stdMinutes) x(stdSeconds) \
+ x(dstName) x(dstSignum) x(dstHours) x(dstMinutes) x(dstSeconds) \
+ x(startJ) x(startDayOfYear) \
+ x(startMonth) x(startWeekOfMonth) x(startDayOfWeek) \
+ x(startHours) x(startMinutes) x(startSeconds) \
+ x(endJ) x(endDayOfYear) \
+ x(endMonth) x(endWeekOfMonth) x(endDayOfWeek) \
+ x(endHours) x(endMinutes) x(endSeconds)] } {
+
+ # it's a good timezone
+
+ return [array get x]
+
+ } else {
+
+ return -code error\
+ -errorcode [list CLOCK badTimeZone $tz] \
+ "unable to parse time zone specification \"$tz\""
+
+ }
+
+}
+
+#----------------------------------------------------------------------
+#
+# ProcessPosixTimeZone --
+#
+# Handle a Posix time zone after it's been broken out into
+# fields.
+#
+# Parameters:
+# z - Dictionary returned from 'ParsePosixTimeZone'
+#
+# Results:
+# Returns time zone information for the 'TZData' array.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::ProcessPosixTimeZone { z } {
+
+ variable MINWIDE
+ variable TZData
+
+ # Determine the standard time zone name and seconds east of Greenwich
+
+ set stdName [dict get $z stdName]
+ if { [string index $stdName 0] eq {<} } {
+ set stdName [string range $stdName 1 end-1]
+ }
+ if { [dict get $z stdSignum] eq {-} } {
+ set stdSignum +1
+ } else {
+ set stdSignum -1
+ }
+ set stdHours [lindex [::scan [dict get $z stdHours] %d] 0]
+ if { [dict get $z stdMinutes] ne {} } {
+ set stdMinutes [lindex [::scan [dict get $z stdMinutes] %d] 0]
+ } else {
+ set stdMinutes 0
+ }
+ if { [dict get $z stdSeconds] ne {} } {
+ set stdSeconds [lindex [::scan [dict get $z stdSeconds] %d] 0]
+ } else {
+ set stdSeconds 0
+ }
+ set stdOffset [expr { ( ( $stdHours * 60 + $stdMinutes )
+ * 60 + $stdSeconds )
+ * $stdSignum }]
+ set data [list [list $MINWIDE $stdOffset 0 $stdName]]
+
+ # If there's no daylight zone, we're done
+
+ set dstName [dict get $z dstName]
+ if { $dstName eq {} } {
+ return $data
+ }
+ if { [string index $dstName 0] eq {<} } {
+ set dstName [string range $dstName 1 end-1]
+ }
+
+ # Determine the daylight name
+
+ if { [dict get $z dstSignum] eq {-} } {
+ set dstSignum +1
+ } else {
+ set dstSignum -1
+ }
+ if { [dict get $z dstHours] eq {} } {
+ set dstOffset [expr { 3600 + $stdOffset }]
+ } else {
+ set dstHours [lindex [::scan [dict get $z dstHours] %d] 0]
+ if { [dict get $z dstMinutes] ne {} } {
+ set dstMinutes [lindex [::scan [dict get $z dstMinutes] %d] 0]
+ } else {
+ set dstMinutes 0
+ }
+ if { [dict get $z dstSeconds] ne {} } {
+ set dstSeconds [lindex [::scan [dict get $z dstSeconds] %d] 0]
+ } else {
+ set dstSeconds 0
+ }
+ set dstOffset [expr { ( ( $dstHours * 60 + $dstMinutes )
+ * 60 + $dstSeconds )
+ * $dstSignum }]
+ }
+
+ # Fill in defaults for European or US DST rules
+ # US start time is the second Sunday in March
+ # EU start time is the last Sunday in March
+ # US end time is the first Sunday in November.
+ # EU end time is the last Sunday in October
+
+ if { [dict get $z startDayOfYear] eq {}
+ && [dict get $z startMonth] eq {} } {
+ if {($stdSignum * $stdHours>=0) && ($stdSignum * $stdHours<=12)} {
+ # EU
+ dict set z startWeekOfMonth 5
+ if {$stdHours>2} {
+ dict set z startHours 2
+ } else {
+ dict set z startHours [expr {$stdHours+1}]
+ }
+ } else {
+ # US
+ dict set z startWeekOfMonth 2
+ dict set z startHours 2
+ }
+ dict set z startMonth 3
+ dict set z startDayOfWeek 0
+ dict set z startMinutes 0
+ dict set z startSeconds 0
+ }
+ if { [dict get $z endDayOfYear] eq {}
+ && [dict get $z endMonth] eq {} } {
+ if {($stdSignum * $stdHours>=0) && ($stdSignum * $stdHours<=12)} {
+ # EU
+ dict set z endMonth 10
+ dict set z endWeekOfMonth 5
+ if {$stdHours>2} {
+ dict set z endHours 3
+ } else {
+ dict set z endHours [expr {$stdHours+2}]
+ }
+ } else {
+ # US
+ dict set z endMonth 11
+ dict set z endWeekOfMonth 1
+ dict set z endHours 2
+ }
+ dict set z endDayOfWeek 0
+ dict set z endMinutes 0
+ dict set z endSeconds 0
+ }
+
+ # Put DST in effect in all years from 1916 to 2099.
+
+ for { set y 1916 } { $y < 2099 } { incr y } {
+ set startTime [DeterminePosixDSTTime $z start $y]
+ incr startTime [expr { - wide($stdOffset) }]
+ set endTime [DeterminePosixDSTTime $z end $y]
+ incr endTime [expr { - wide($dstOffset) }]
+ if { $startTime < $endTime } {
+ lappend data \
+ [list $startTime $dstOffset 1 $dstName] \
+ [list $endTime $stdOffset 0 $stdName]
+ } else {
+ lappend data \
+ [list $endTime $stdOffset 0 $stdName] \
+ [list $startTime $dstOffset 1 $dstName]
+ }
+ }
+
+ return $data
+
+}
+
+#----------------------------------------------------------------------
+#
+# DeterminePosixDSTTime --
+#
+# Determines the time that Daylight Saving Time starts or ends
+# from a Posix time zone specification.
+#
+# Parameters:
+# z - Time zone data returned from ParsePosixTimeZone.
+# Missing fields are expected to be filled in with
+# default values.
+# bound - The word 'start' or 'end'
+# y - The year for which the transition time is to be determined.
+#
+# Results:
+# Returns the transition time as a count of seconds from
+# the epoch. The time is relative to the wall clock, not UTC.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::DeterminePosixDSTTime { z bound y } {
+
+ variable FEB_28
+
+ # Determine the start or end day of DST
+
+ set date [dict create era CE year $y]
+ set doy [dict get $z ${bound}DayOfYear]
+ if { $doy ne {} } {
+
+ # Time was specified as a day of the year
+
+ if { [dict get $z ${bound}J] ne {}
+ && [IsGregorianLeapYear $y]
+ && ( $doy > $FEB_28 ) } {
+ incr doy
+ }
+ dict set date dayOfYear $doy
+ set date [GetJulianDayFromEraYearDay $date[set date {}] 2361222]
+ } else {
+
+ # Time was specified as a day of the week within a month
+
+ dict set date month [dict get $z ${bound}Month]
+ dict set date dayOfWeek [dict get $z ${bound}DayOfWeek]
+ set dowim [dict get $z ${bound}WeekOfMonth]
+ if { $dowim >= 5 } {
+ set dowim -1
+ }
+ dict set date dayOfWeekInMonth $dowim
+ set date [GetJulianDayFromEraYearMonthWeekDay $date[set date {}] 2361222]
+
+ }
+
+ set jd [dict get $date julianDay]
+ set seconds [expr { wide($jd) * wide(86400)
+ - wide(210866803200) }]
+
+ set h [dict get $z ${bound}Hours]
+ if { $h eq {} } {
+ set h 2
+ } else {
+ set h [lindex [::scan $h %d] 0]
+ }
+ set m [dict get $z ${bound}Minutes]
+ if { $m eq {} } {
+ set m 0
+ } else {
+ set m [lindex [::scan $m %d] 0]
+ }
+ set s [dict get $z ${bound}Seconds]
+ if { $s eq {} } {
+ set s 0
+ } else {
+ set s [lindex [::scan $s %d] 0]
+ }
+ set tod [expr { ( $h * 60 + $m ) * 60 + $s }]
+ return [expr { $seconds + $tod }]
+
+}
+
+#----------------------------------------------------------------------
+#
+# GetLocaleEra --
+#
+# Given local time expressed in seconds from the Posix epoch,
+# determine localized era and year within the era.
+#
+# Parameters:
+# date - Dictionary that must contain the keys, 'localSeconds',
+# whose value is expressed as the appropriate local time;
+# and 'year', whose value is the Gregorian year.
+# etable - Value of the LOCALE_ERAS key in the message catalogue
+# for the target locale.
+#
+# Results:
+# Returns the dictionary, augmented with the keys, 'localeEra'
+# and 'localeYear'.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::GetLocaleEra { date etable } {
+
+ set index [BSearch $etable [dict get $date localSeconds]]
+ if { $index < 0} {
+ dict set date localeEra \
+ [::format %02d [expr { [dict get $date year] / 100 }]]
+ dict set date localeYear \
+ [expr { [dict get $date year] % 100 }]
+ } else {
+ dict set date localeEra [lindex $etable $index 1]
+ dict set date localeYear [expr { [dict get $date year]
+ - [lindex $etable $index 2] }]
+ }
+ return $date
+
+}
+
+#----------------------------------------------------------------------
+#
+# GetJulianDayFromEraYearDay --
+#
+# Given a year, month and day on the Gregorian calendar, determines
+# the Julian Day Number beginning at noon on that date.
+#
+# Parameters:
+# date -- A dictionary in which the 'era', 'year', and
+# 'dayOfYear' slots are populated. The calendar in use
+# is determined by the date itself relative to:
+# changeover -- Julian day on which the Gregorian calendar was
+# adopted in the current locale.
+#
+# Results:
+# Returns the given dictionary augmented with a 'julianDay' key
+# whose value is the desired Julian Day Number, and a 'gregorian'
+# key that specifies whether the calendar is Gregorian (1) or
+# Julian (0).
+#
+# Side effects:
+# None.
+#
+# Bugs:
+# This code needs to be moved to the C layer.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::GetJulianDayFromEraYearDay {date changeover} {
+
+ # Get absolute year number from the civil year
+
+ switch -exact -- [dict get $date era] {
+ BCE {
+ set year [expr { 1 - [dict get $date year] }]
+ }
+ CE {
+ set year [dict get $date year]
+ }
+ }
+ set ym1 [expr { $year - 1 }]
+
+ # Try the Gregorian calendar first.
+
+ dict set date gregorian 1
+ set jd [expr { 1721425
+ + [dict get $date dayOfYear]
+ + ( 365 * $ym1 )
+ + ( $ym1 / 4 )
+ - ( $ym1 / 100 )
+ + ( $ym1 / 400 ) }]
+
+ # If the date is before the Gregorian change, use the Julian calendar.
+
+ if { $jd < $changeover } {
+ dict set date gregorian 0
+ set jd [expr { 1721423
+ + [dict get $date dayOfYear]
+ + ( 365 * $ym1 )
+ + ( $ym1 / 4 ) }]
+ }
+
+ dict set date julianDay $jd
+ return $date
+}
+
+#----------------------------------------------------------------------
+#
+# GetJulianDayFromEraYearMonthWeekDay --
+#
+# Determines the Julian Day number corresponding to the nth
+# given day-of-the-week in a given month.
+#
+# Parameters:
+# date - Dictionary containing the keys, 'era', 'year', 'month'
+# 'weekOfMonth', 'dayOfWeek', and 'dayOfWeekInMonth'.
+# changeover - Julian Day of adoption of the Gregorian calendar
+#
+# Results:
+# Returns the given dictionary, augmented with a 'julianDay' key.
+#
+# Side effects:
+# None.
+#
+# Bugs:
+# This code needs to be moved to the C layer.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::GetJulianDayFromEraYearMonthWeekDay {date changeover} {
+
+ # Come up with a reference day; either the zeroeth day of the
+ # given month (dayOfWeekInMonth >= 0) or the seventh day of the
+ # following month (dayOfWeekInMonth < 0)
+
+ set date2 $date
+ set week [dict get $date dayOfWeekInMonth]
+ if { $week >= 0 } {
+ dict set date2 dayOfMonth 0
+ } else {
+ dict incr date2 month
+ dict set date2 dayOfMonth 7
+ }
+ set date2 [GetJulianDayFromEraYearMonthDay $date2[set date2 {}] \
+ $changeover]
+ set wd0 [WeekdayOnOrBefore [dict get $date dayOfWeek] \
+ [dict get $date2 julianDay]]
+ dict set date julianDay [expr { $wd0 + 7 * $week }]
+ return $date
+
+}
+
+#----------------------------------------------------------------------
+#
+# IsGregorianLeapYear --
+#
+# Determines whether a given date represents a leap year in the
+# Gregorian calendar.
+#
+# Parameters:
+# date -- The date to test. The fields, 'era', 'year' and 'gregorian'
+# must be set.
+#
+# Results:
+# Returns 1 if the year is a leap year, 0 otherwise.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::IsGregorianLeapYear { date } {
+
+ switch -exact -- [dict get $date era] {
+ BCE {
+ set year [expr { 1 - [dict get $date year]}]
+ }
+ CE {
+ set year [dict get $date year]
+ }
+ }
+ if { $year % 4 != 0 } {
+ return 0
+ } elseif { ![dict get $date gregorian] } {
+ return 1
+ } elseif { $year % 400 == 0 } {
+ return 1
+ } elseif { $year % 100 == 0 } {
+ return 0
+ } else {
+ return 1
+ }
+
+}
+
+#----------------------------------------------------------------------
+#
+# WeekdayOnOrBefore --
+#
+# Determine the nearest day of week (given by the 'weekday'
+# parameter, Sunday==0) on or before a given Julian Day.
+#
+# Parameters:
+# weekday -- Day of the week
+# j -- Julian Day number
+#
+# Results:
+# Returns the Julian Day Number of the desired date.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::WeekdayOnOrBefore { weekday j } {
+
+ set k [expr { ( $weekday + 6 ) % 7 }]
+ return [expr { $j - ( $j - $k ) % 7 }]
+
+}
+
+#----------------------------------------------------------------------
+#
+# BSearch --
+#
+# Service procedure that does binary search in several places
+# inside the 'clock' command.
+#
+# Parameters:
+# list - List of lists, sorted in ascending order by the
+# first elements
+# key - Value to search for
+#
+# Results:
+# Returns the index of the greatest element in $list that is less
+# than or equal to $key.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::BSearch { list key } {
+
+ if {[llength $list] == 0} {
+ return -1
+ }
+ if { $key < [lindex $list 0 0] } {
+ return -1
+ }
+
+ set l 0
+ set u [expr { [llength $list] - 1 }]
+
+ while { $l < $u } {
+
+ # At this point, we know that
+ # $k >= [lindex $list $l 0]
+ # Either $u == [llength $list] or else $k < [lindex $list $u+1 0]
+ # We find the midpoint of the interval {l,u} rounded UP, compare
+ # against it, and set l or u to maintain the invariant. Note
+ # that the interval shrinks at each step, guaranteeing convergence.
+
+ set m [expr { ( $l + $u + 1 ) / 2 }]
+ if { $key >= [lindex $list $m 0] } {
+ set l $m
+ } else {
+ set u [expr { $m - 1 }]
+ }
+ }
+
+ return $l
+}
+
+#----------------------------------------------------------------------
+#
+# clock add --
+#
+# Adds an offset to a given time.
+#
+# Syntax:
+# clock add clockval ?count unit?... ?-option value?
+#
+# Parameters:
+# clockval -- Starting time value
+# count -- Amount of a unit of time to add
+# unit -- Unit of time to add, must be one of:
+# years year months month weeks week
+# days day hours hour minutes minute
+# seconds second
+#
+# Options:
+# -gmt BOOLEAN
+# (Deprecated) Flag synonymous with '-timezone :GMT'
+# -timezone ZONE
+# Name of the time zone in which calculations are to be done.
+# -locale NAME
+# Name of the locale in which calculations are to be done.
+# Used to determine the Gregorian change date.
+#
+# Results:
+# Returns the given time adjusted by the given offset(s) in
+# order.
+#
+# Notes:
+# It is possible that adding a number of months or years will adjust
+# the day of the month as well. For instance, the time at
+# one month after 31 January is either 28 or 29 February, because
+# February has fewer than 31 days.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::add { clockval args } {
+
+ if { [llength $args] % 2 != 0 } {
+ set cmdName "clock add"
+ return -code error \
+ -errorcode [list CLOCK wrongNumArgs] \
+ "wrong \# args: should be\
+ \"$cmdName clockval ?number units?...\
+ ?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?\""
+ }
+ if { [catch { expr {wide($clockval)} } result] } {
+ return -code error $result
+ }
+
+ set offsets {}
+ set gmt 0
+ set locale c
+ set timezone [GetSystemTimeZone]
+
+ foreach { a b } $args {
+
+ if { [string is integer -strict $a] } {
+
+ lappend offsets $a $b
+
+ } else {
+
+ switch -exact -- $a {
+
+ -g - -gm - -gmt {
+ set gmt $b
+ }
+ -l - -lo - -loc - -loca - -local - -locale {
+ set locale [string tolower $b]
+ }
+ -t - -ti - -tim - -time - -timez - -timezo - -timezon -
+ -timezone {
+ set timezone $b
+ }
+ default {
+ return -code error \
+ -errorcode [list CLOCK badSwitch $a] \
+ "bad switch \"$a\",\
+ must be -gmt, -locale or -timezone"
+ }
+ }
+ }
+ }
+
+ # Check options for validity
+
+ if { [info exists saw(-gmt)] && [info exists saw(-timezone)] } {
+ return -code error \
+ -errorcode [list CLOCK gmtWithTimezone] \
+ "cannot use -gmt and -timezone in same call"
+ }
+ if { [catch { expr { wide($clockval) } } result] } {
+ return -code error \
+ "expected integer but got \"$clockval\""
+ }
+ if { ![string is boolean $gmt] } {
+ return -code error \
+ "expected boolean value but got \"$gmt\""
+ } else {
+ if { $gmt } {
+ set timezone :GMT
+ }
+ }
+
+ EnterLocale $locale oldLocale
+
+ set changeover [mc GREGORIAN_CHANGE_DATE]
+
+ if {[catch {SetupTimeZone $timezone} retval opts]} {
+ dict unset opts -errorinfo
+ return -options $opts $retval
+ }
+
+ set status [catch {
+
+ foreach { quantity unit } $offsets {
+
+ switch -exact -- $unit {
+
+ years - year {
+ set clockval \
+ [AddMonths [expr { 12 * $quantity }] \
+ $clockval $timezone $changeover]
+ }
+ months - month {
+ set clockval [AddMonths $quantity $clockval $timezone \
+ $changeover]
+ }
+
+ weeks - week {
+ set clockval [AddDays [expr { 7 * $quantity }] \
+ $clockval $timezone $changeover]
+ }
+ days - day {
+ set clockval [AddDays $quantity $clockval $timezone \
+ $changeover]
+ }
+
+ hours - hour {
+ set clockval [expr { 3600 * $quantity + $clockval }]
+ }
+ minutes - minute {
+ set clockval [expr { 60 * $quantity + $clockval }]
+ }
+ seconds - second {
+ set clockval [expr { $quantity + $clockval }]
+ }
+
+ default {
+ error "unknown unit \"$unit\", must be \
+ years, months, weeks, days, hours, minutes or seconds" \
+ "unknown unit \"$unit\", must be \
+ years, months, weeks, days, hours, minutes or seconds" \
+ [list CLOCK badUnit $unit]
+ }
+ }
+ }
+ } result opts]
+
+ # Restore the locale
+
+ if { [info exists oldLocale] } {
+ mclocale $oldLocale
+ }
+
+ if { $status == 1 } {
+ if { [lindex [dict get $opts -errorcode] 0] eq {CLOCK} } {
+ dict unset opts -errorinfo
+ }
+ return -options $opts $result
+ } else {
+ return $clockval
+ }
+
+}
+
+#----------------------------------------------------------------------
+#
+# AddMonths --
+#
+# Add a given number of months to a given clock value in a given
+# time zone.
+#
+# Parameters:
+# months - Number of months to add (may be negative)
+# clockval - Seconds since the epoch before the operation
+# timezone - Time zone in which the operation is to be performed
+#
+# Results:
+# Returns the new clock value as a number of seconds since
+# the epoch.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::AddMonths { months clockval timezone changeover } {
+
+ variable DaysInRomanMonthInCommonYear
+ variable DaysInRomanMonthInLeapYear
+ variable TZData
+
+ # Convert the time to year, month, day, and fraction of day.
+
+ set date [GetDateFields $clockval $TZData($timezone) $changeover]
+ dict set date secondOfDay [expr { [dict get $date localSeconds]
+ % 86400 }]
+ dict set date tzName $timezone
+
+ # Add the requisite number of months
+
+ set m [dict get $date month]
+ incr m $months
+ incr m -1
+ set delta [expr { $m / 12 }]
+ set mm [expr { $m % 12 }]
+ dict set date month [expr { $mm + 1 }]
+ dict incr date year $delta
+
+ # If the date doesn't exist in the current month, repair it
+
+ if { [IsGregorianLeapYear $date] } {
+ set hath [lindex $DaysInRomanMonthInLeapYear $mm]
+ } else {
+ set hath [lindex $DaysInRomanMonthInCommonYear $mm]
+ }
+ if { [dict get $date dayOfMonth] > $hath } {
+ dict set date dayOfMonth $hath
+ }
+
+ # Reconvert to a number of seconds
+
+ set date [GetJulianDayFromEraYearMonthDay \
+ $date[set date {}]\
+ $changeover]
+ dict set date localSeconds \
+ [expr { -210866803200
+ + ( 86400 * wide([dict get $date julianDay]) )
+ + [dict get $date secondOfDay] }]
+ set date [ConvertLocalToUTC $date[set date {}] $TZData($timezone) \
+ $changeover]
+
+ return [dict get $date seconds]
+
+}
+
+#----------------------------------------------------------------------
+#
+# AddDays --
+#
+# Add a given number of days to a given clock value in a given
+# time zone.
+#
+# Parameters:
+# days - Number of days to add (may be negative)
+# clockval - Seconds since the epoch before the operation
+# timezone - Time zone in which the operation is to be performed
+# changeover - Julian Day on which the Gregorian calendar was adopted
+# in the target locale.
+#
+# Results:
+# Returns the new clock value as a number of seconds since
+# the epoch.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::AddDays { days clockval timezone changeover } {
+
+ variable TZData
+
+ # Convert the time to Julian Day
+
+ set date [GetDateFields $clockval $TZData($timezone) $changeover]
+ dict set date secondOfDay [expr { [dict get $date localSeconds]
+ % 86400 }]
+ dict set date tzName $timezone
+
+ # Add the requisite number of days
+
+ dict incr date julianDay $days
+
+ # Reconvert to a number of seconds
+
+ dict set date localSeconds \
+ [expr { -210866803200
+ + ( 86400 * wide([dict get $date julianDay]) )
+ + [dict get $date secondOfDay] }]
+ set date [ConvertLocalToUTC $date[set date {}] $TZData($timezone) \
+ $changeover]
+
+ return [dict get $date seconds]
+
+}
+
+#----------------------------------------------------------------------
+#
+# mc --
+#
+# Wrapper around ::msgcat::mc that caches the result according
+# to the locale.
+#
+# Parameters:
+# Accepts the name of the message to retrieve.
+#
+# Results:
+# Returns the message text.
+#
+# Side effects:
+# Caches the message text.
+#
+# Notes:
+# Only the single-argument version of [mc] is supported.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::mc { name } {
+ variable McLoaded
+ set Locale [mclocale]
+ if { [dict exists $McLoaded $Locale $name] } {
+ return [dict get $McLoaded $Locale $name]
+ } else {
+ set val [::msgcat::mc $name]
+ dict set McLoaded $Locale $name $val
+ return $val
+ }
+}
+
+#----------------------------------------------------------------------
+#
+# ClearCaches --
+#
+# Clears all caches to reclaim the memory used in [clock]
+#
+# Parameters:
+# None.
+#
+# Results:
+# None.
+#
+# Side effects:
+# Caches are cleared.
+#
+#----------------------------------------------------------------------
+
+proc ::tcl::clock::ClearCaches {} {
+
+ variable FormatProc
+ variable LocaleNumeralCache
+ variable McLoaded
+ variable CachedSystemTimeZone
+ variable TimeZoneBad
+
+ foreach p [info procs [namespace current]::scanproc'*] {
+ rename $p {}
+ }
+ foreach p [info procs [namespace current]::formatproc'*] {
+ rename $p {}
+ }
+
+ catch {unset FormatProc}
+ set LocaleNumeralCache {}
+ set McLoaded {}
+ catch {unset CachedSystemTimeZone}
+ set TimeZoneBad {}
+ InitTZData
+
+}
diff --git a/library/dde/pkgIndex.tcl b/library/dde/pkgIndex.tcl
index f993012..3125ada 100644
--- a/library/dde/pkgIndex.tcl
+++ b/library/dde/pkgIndex.tcl
@@ -1,7 +1,7 @@
if {![package vsatisfies [package provide Tcl] 8]} {return}
if {[string compare $::tcl_platform(platform) windows]} {return}
if {[info exists ::tcl_platform(debug)]} {
- package ifneeded dde 1.2.4 [list load [file join $dir tcldde12g.dll] dde]
+ package ifneeded dde 1.3.2 [list load [file join $dir tcldde13g.dll] dde]
} else {
- package ifneeded dde 1.2.4 [list load [file join $dir tcldde12.dll] dde]
+ package ifneeded dde 1.3.2 [list load [file join $dir tcldde13.dll] dde]
}
diff --git a/library/history.tcl b/library/history.tcl
index 1fbb4ed..888d144 100644
--- a/library/history.tcl
+++ b/library/history.tcl
@@ -254,7 +254,7 @@ proc history {args} {
if {![info exists history($i)]} {
continue
}
- set cmd [string map [list \n \n\t] [string trimright $history($i) \ \n]]
+ set cmd [string map [list \n \n\t] [string trimright $history($i) \ \n]]
append result $newline[format "%6d %s" $i $cmd]
set newline \n
}
diff --git a/library/http/http.tcl b/library/http/http.tcl
index e8a7c1e..aaef2b8 100644
--- a/library/http/http.tcl
+++ b/library/http/http.tcl
@@ -1,45 +1,38 @@
# http.tcl --
#
# Client-side HTTP for GET, POST, and HEAD commands. These routines can
-# be used in untrusted code that uses the Safesock security policy. These
-# procedures use a callback interface to avoid using vwait, which is not
-# defined in the safe base.
+# be used in untrusted code that uses the Safesock security policy.
+# These procedures use a callback interface to avoid using vwait, which
+# is not defined in the safe base.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
-# Rough version history:
-# 1.0 Old http_get interface.
-# 2.0 http:: namespace and http::geturl.
-# 2.1 Added callbacks to handle arriving data, and timeouts.
-# 2.2 Added ability to fetch into a channel.
-# 2.3 Added SSL support, and ability to post from a channel. This version
-# also cleans up error cases and eliminates the "ioerror" status in
-# favor of raising an error
-# 2.4 Added -binary option to http::geturl and charset element to the state
-# array.
-
package require Tcl 8.4
-# Keep this in sync with pkgIndex.tcl and with the install directories
-# in Makefiles
-package provide http 2.5.5
+# Keep this in sync with pkgIndex.tcl and with the install directories in
+# Makefiles
+package provide http 2.7.6
namespace eval http {
+ # Allow resourcing to not clobber existing data
+
variable http
- array set http {
- -accept */*
- -proxyhost {}
- -proxyport {}
- -proxyfilter http::ProxyRequired
- -urlencoding utf-8
+ if {![info exists http]} {
+ array set http {
+ -accept */*
+ -proxyhost {}
+ -proxyport {}
+ -proxyfilter http::ProxyRequired
+ -urlencoding utf-8
+ }
+ set http(-useragent) "Tcl http client package [package provide http]"
}
- set http(-useragent) "Tcl http client package [package provide http]"
proc init {} {
# Set up the map for quoting chars. RFC3986 Section 2.3 say percent
- # encode all except: "... percent-encoded octets in the ranges of ALPHA
- # (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D), period (%2E),
- # underscore (%5F), or tilde (%7E) should not be created by URI
+ # encode all except: "... percent-encoded octets in the ranges of
+ # ALPHA (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D), period
+ # (%2E), underscore (%5F), or tilde (%7E) should not be created by URI
# producers ..."
for {set i 0} {$i <= 256} {incr i} {
set c [format %c $i]
@@ -50,33 +43,65 @@ namespace eval http {
# These are handled specially
set map(\n) %0d%0a
variable formMap [array get map]
+
+ # Create a map for HTTP/1.1 open sockets
+ variable socketmap
+ if {[info exists socketmap]} {
+ # Close but don't remove open sockets on re-init
+ foreach {url sock} [array get socketmap] {
+ catch {close $sock}
+ }
+ }
+ array set socketmap {}
}
init
variable urlTypes
- array set urlTypes {
- http {80 ::socket}
+ if {![info exists urlTypes]} {
+ set urlTypes(http) [list 80 ::socket]
}
variable encodings [string tolower [encoding names]]
# This can be changed, but iso8859-1 is the RFC standard.
- variable defaultCharset "iso8859-1"
+ variable defaultCharset
+ if {![info exists defaultCharset]} {
+ set defaultCharset "iso8859-1"
+ }
- # Force RFC 3986 strictness in geturl url verification? Not for 8.4.x
- variable strict 0
+ # Force RFC 3986 strictness in geturl url verification?
+ variable strict
+ if {![info exists strict]} {
+ set strict 1
+ }
+
+ # Let user control default keepalive for compatibility
+ variable defaultKeepalive
+ if {![info exists defaultKeepalive]} {
+ set defaultKeepalive 0
+ }
namespace export geturl config reset wait formatQuery register unregister
# Useful, but not exported: data size status code
}
+# http::Log --
+#
+# Debugging output -- define this to observe HTTP/1.1 socket usage.
+# Should echo any args received.
+#
+# Arguments:
+# msg Message to output
+#
+proc http::Log {args} {}
+
# http::register --
#
# See documentation for details.
#
# Arguments:
-# proto URL protocol prefix, e.g. https
-# port Default port for protocol
-# command Command to use to create socket
+# proto URL protocol prefix, e.g. https
+# port Default port for protocol
+# command Command to use to create socket
# Results:
# list of port and command that was registered.
@@ -90,7 +115,7 @@ proc http::register {proto port command} {
# Unregisters URL protocol handler
#
# Arguments:
-# proto URL protocol prefix, e.g. https
+# proto URL protocol prefix, e.g. https
# Results:
# list of port and command that was unregistered.
@@ -125,21 +150,19 @@ proc http::config {args} {
return $result
}
set options [string map {- ""} $options]
- set pat ^-([join $options |])$
+ set pat ^-(?:[join $options |])$
if {[llength $args] == 1} {
set flag [lindex $args 0]
- if {[regexp -- $pat $flag]} {
- return $http($flag)
- } else {
+ if {![regexp -- $pat $flag]} {
return -code error "Unknown option $flag, must be: $usage"
}
+ return $http($flag)
} else {
foreach {flag value} $args {
- if {[regexp -- $pat $flag]} {
- set http($flag) $value
- } else {
+ if {![regexp -- $pat $flag]} {
return -code error "Unknown option $flag, must be: $usage"
}
+ set http($flag) $value
}
}
}
@@ -152,33 +175,81 @@ proc http::config {args} {
# 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.
+# 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}} {
+proc http::Finish {token {errormsg ""} {skipCB 0}} {
variable $token
upvar 0 $token state
global errorInfo errorCode
- if {[string length $errormsg] != 0} {
+ if {$errormsg ne ""} {
set state(error) [list $errormsg $errorInfo $errorCode]
- set state(status) error
+ set state(status) "error"
+ }
+ if {
+ ($state(status) eq "timeout") || ($state(status) eq "error") ||
+ ([info exists state(connection)] && ($state(connection) eq "close"))
+ } then {
+ CloseSocket $state(sock) $token
+ }
+ if {[info exists state(after)]} {
+ after cancel $state(after)
}
- 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} {
+ if {$errormsg eq ""} {
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)
+ # Command callback may already have unset our state
+ unset -nocomplain state(-command)
+ }
+}
+
+# http::CloseSocket -
+#
+# Close a socket and remove it from the persistent sockets table. If
+# possible an http token is included here but when we are called from a
+# fileevent on remote closure we need to find the correct entry - hence
+# the second section.
+
+proc ::http::CloseSocket {s {token {}}} {
+ variable socketmap
+ catch {fileevent $s readable {}}
+ set conn_id {}
+ if {$token ne ""} {
+ variable $token
+ upvar 0 $token state
+ if {[info exists state(socketinfo)]} {
+ set conn_id $state(socketinfo)
+ }
+ } else {
+ set map [array get socketmap]
+ set ndx [lsearch -exact $map $s]
+ if {$ndx != -1} {
+ incr ndx -1
+ set conn_id [lindex $map $ndx]
+ }
+ }
+ if {$conn_id eq {} || ![info exists socketmap($conn_id)]} {
+ Log "Closing socket $s (no connection info)"
+ if {[catch {close $s} err]} {
+ Log "Error: $err"
+ }
+ } else {
+ if {[info exists socketmap($conn_id)]} {
+ Log "Closing connection $conn_id (sock $socketmap($conn_id))"
+ if {[catch {close $socketmap($conn_id)} err]} {
+ Log "Error: $err"
+ }
+ unset socketmap($conn_id)
+ } else {
+ Log "Cannot close connection $conn_id - no socket in socket map"
}
}
}
@@ -194,7 +265,7 @@ proc http::Finish { token {errormsg ""} {skipCB 0}} {
# Side Effects:
# See Finish
-proc http::reset { token {why reset} } {
+proc http::reset {token {why reset}} {
variable $token
upvar 0 $token state
set state(status) $why
@@ -217,13 +288,14 @@ proc http::reset { token {why reset} } {
# 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.
+# 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 } {
+proc http::geturl {url args} {
variable http
variable urlTypes
variable defaultCharset
+ variable defaultKeepalive
variable strict
# Initialize the state variable, an array. We'll return the name of this
@@ -241,47 +313,58 @@ proc http::geturl { url args } {
array set state {
-binary false
- -blocksize 8192
+ -blocksize 8192
-queryblocksize 8192
- -validate 0
- -headers {}
- -timeout 0
- -type application/x-www-form-urlencoded
+ -validate 0
+ -headers {}
+ -timeout 0
+ -type application/x-www-form-urlencoded
-queryprogress {}
- state header
+ -protocol 1.1
+ binary 0
+ state connecting
meta {}
coding {}
currentsize 0
totalsize 0
querylength 0
queryoffset 0
- type text/html
- body {}
+ type text/html
+ body {}
status ""
- http ""
+ http ""
+ connection close
}
+ set state(-keepalive) $defaultKeepalive
+ set state(-strict) $strict
# These flags have their types verified [Bug 811170]
array set type {
-binary boolean
-blocksize integer
-queryblocksize integer
- -validate boolean
+ -strict boolean
-timeout integer
+ -validate boolean
}
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 {
+ -binary -blocksize -channel -command -handler -headers -keepalive
+ -method -myaddr -progress -protocol -query -queryblocksize
+ -querychannel -queryprogress -strict -timeout -type -validate
+ }
+ set usage [join [lsort $options] ", "]
set options [string map {- ""} $options]
- set pat ^-([join $options |])$
+ set pat ^-(?:[join $options |])$
foreach {flag value} $args {
- if {[regexp $pat $flag]} {
+ if {[regexp -- $pat $flag]} {
# Validate numbers
- if {[info exists type($flag)] && \
- ![string is $type($flag) -strict $value]} {
+ if {
+ [info exists type($flag)] &&
+ ![string is $type($flag) -strict $value]
+ } then {
unset $token
- return -code error "Bad value for $flag ($value), must be $type($flag)"
+ return -code error \
+ "Bad value for $flag ($value), must be $type($flag)"
}
set state($flag) $value
} else {
@@ -320,7 +403,9 @@ proc http::geturl { url args } {
# 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
+ #
+ # 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".
@@ -331,8 +416,8 @@ proc http::geturl { url args } {
# 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).
+ # URL that are going to the server are correctly encoded. This is only
+ # done if $state(-strict) is true (inherited from $::http::strict).
set URLmatcher {(?x) # this is _expanded_ syntax
^
@@ -346,7 +431,7 @@ proc http::geturl { url args } {
( [^/:\#?]+ ) # <host part of authority>
(?: : (\d+) )? # <port part of authority>
)?
- ( / [^\#?]* (?: \? [^\#?]* )?)? # <path> (including query)
+ ( / [^\#]*)? # <path> (including query)
(?: \# (.*) )? # <fragment>
$
}
@@ -365,7 +450,7 @@ proc http::geturl { url args } {
# 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} {
+ if {$port ne "" && $port > 65535} {
unset $token
return -code error "Invalid port number: $port"
}
@@ -378,7 +463,7 @@ proc http::geturl { url args } {
(?: [-\w.~!$&'()*+,;=:] | %[0-9a-f][0-9a-f] )+
$
}
- if {$strict && ![regexp -- $validityRE $user]} {
+ if {$state(-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]} {
@@ -398,19 +483,19 @@ proc http::geturl { url args } {
(?: \? (?: [-\w.~!$&'()*+,;=:@/?] | %[0-9a-f][0-9a-f] )* )?
$
}
- if {$strict && ![regexp -- $validityRE $srvurl]} {
+ if {$state(-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"
+ "Illegal encoding character usage \"$bad\" in URL path"
}
return -code error "Illegal characters in URL path"
}
} else {
set srvurl /
}
- if {[string length $proto] == 0} {
+ if {$proto eq ""} {
set proto http
}
if {![info exists urlTypes($proto)]} {
@@ -420,7 +505,7 @@ proc http::geturl { url args } {
set defport [lindex $urlTypes($proto) 0]
set defcmd [lindex $urlTypes($proto) 1]
- if {[string length $port] == 0} {
+ if {$port eq ""} {
set port $defport
}
if {![catch {$http(-proxyfilter) $host} proxy]} {
@@ -445,71 +530,100 @@ proc http::geturl { url args } {
# If a timeout is specified we set up the after event and arrange for an
# asynchronous socket connection.
+ set sockopts [list]
if {$state(-timeout) > 0} {
set state(after) [after $state(-timeout) \
[list http::reset $token timeout]]
- set async -async
- } else {
- set async ""
+ lappend sockopts -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]} {
+ if {[info exists phost] && ($phost ne "")} {
set srvurl $url
- set conStat [catch {eval $defcmd $async {$phost $pport}} s]
+ set targetAddr [list $phost $pport]
} else {
- set conStat [catch {eval $defcmd $async {$host $port}} s]
+ set targetAddr [list $host $port]
}
-
- 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
+ # Proxy connections aren't shared among different hosts.
+ set state(socketinfo) $host:$port
+
+ # See if we are supposed to use a previously opened channel.
+ if {$state(-keepalive)} {
+ variable socketmap
+ if {[info exists socketmap($state(socketinfo))]} {
+ if {[catch {fconfigure $socketmap($state(socketinfo))}]} {
+ Log "WARNING: socket for $state(socketinfo) was closed"
+ unset socketmap($state(socketinfo))
+ } else {
+ set sock $socketmap($state(socketinfo))
+ Log "reusing socket $sock for $state(socketinfo)"
+ catch {fileevent $sock writable {}}
+ catch {fileevent $sock readable {}}
+ }
+ }
+ # don't automatically close this connection socket
+ set state(connection) {}
+ }
+ if {![info exists sock]} {
+ # Pass -myaddr directly to the socket command
+ if {[info exists state(-myaddr)]} {
+ lappend sockopts -myaddr $state(-myaddr)
+ }
+ if {[catch {eval $defcmd $sockopts $targetAddr} sock]} {
+ # 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 state(sock) $sock
+ Finish $token "" 1
+ cleanup $token
+ return -code error $sock
+ }
+ }
+ set state(sock) $sock
+ Log "Using $sock for $state(socketinfo)" \
+ [expr {$state(-keepalive)?"keepalive":""}]
+ if {$state(-keepalive)} {
+ set socketmap($state(socketinfo)) $sock
}
- set state(sock) $s
# Wait for the connection to complete.
if {$state(-timeout) > 0} {
- fileevent $s writable [list http::Connect $token]
+ fileevent $sock 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.
+ # command callback may have cleaned up the token. If so we end up
+ # here with nothing left to do.
+ return $token
+ } elseif {$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
- } 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) ""
}
+ set state(status) ""
}
# Send data in cr-lf format, but accept any line terminators
- fconfigure $s -translation {auto crlf} -buffersize $state(-blocksize)
+ fconfigure $sock -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}
+ catch {fconfigure $sock -blocking off}
set how GET
if {$isQuery} {
set state(querylength) [string length $state(-query)]
@@ -530,29 +644,62 @@ proc http::geturl { url args } {
fconfigure $state(-querychannel) -blocking 1 -translation binary
set contDone 0
}
+ if {[info exists state(-method)] && $state(-method) ne ""} {
+ set how $state(-method)
+ }
if {[catch {
- puts $s "$how $srvurl HTTP/1.0"
- puts $s "Accept: $http(-accept)"
- if {$port == $defport} {
+ puts $sock "$how $srvurl HTTP/$state(-protocol)"
+ puts $sock "Accept: $http(-accept)"
+ array set hdrs $state(-headers)
+ if {[info exists hdrs(Host)]} {
+ # Allow Host spoofing. [Bug 928154]
+ puts $sock "Host: $hdrs(Host)"
+ } elseif {$port == $defport} {
# Don't add port in this case, to handle broken servers. [Bug
- # 504508]
- puts $s "Host: $host"
+ # #504508]
+ puts $sock "Host: $host"
} else {
- puts $s "Host: $host:$port"
+ puts $sock "Host: $host:$port"
}
- puts $s "User-Agent: $http(-useragent)"
+ unset hdrs
+ puts $sock "User-Agent: $http(-useragent)"
+ if {$state(-protocol) == 1.0 && $state(-keepalive)} {
+ puts $sock "Connection: keep-alive"
+ }
+ if {$state(-protocol) > 1.0 && !$state(-keepalive)} {
+ puts $sock "Connection: close" ;# RFC2616 sec 8.1.2.1
+ }
+ if {[info exists phost] && ($phost ne "") && $state(-keepalive)} {
+ puts $sock "Proxy-Connection: Keep-Alive"
+ }
+ set accept_encoding_seen 0
foreach {key value} $state(-headers) {
+ if {[string equal -nocase $key "host"]} {
+ continue
+ }
+ if {[string equal -nocase $key "accept-encoding"]} {
+ set accept_encoding_seen 1
+ }
set value [string map [list \n "" \r ""] $value]
set key [string trim $key]
- if {$key eq "Content-Length"} {
+ if {[string equal -nocase $key "content-length"]} {
set contDone 1
set state(querylength) $value
}
if {[string length $key]} {
- puts $s "$key: $value"
+ puts $sock "$key: $value"
}
}
+ # Soft zlib dependency check - no package require
+ if {
+ !$accept_encoding_seen &&
+ ([package vsatisfies [package provide Tcl] 8.6]
+ || [llength [package provide zlib]]) &&
+ !([info exists state(-channel)] || [info exists state(-handler)])
+ } then {
+ puts $sock "Accept-Encoding: gzip, identity, *;q=0.1"
+ }
if {$isQueryChannel && $state(querylength) == 0} {
# Try to determine size of data in channel. If we cannot seek, the
# surrounding catch will trap us
@@ -572,29 +719,30 @@ proc http::geturl { url args } {
# 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.
+ # 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)"
+ puts $sock "Content-Type: $state(-type)"
if {!$contDone} {
- puts $s "Content-Length: $state(querylength)"
+ puts $sock "Content-Length: $state(querylength)"
}
- puts $s ""
- fconfigure $s -translation {auto binary}
- fileevent $s writable [list http::Write $token]
+ puts $sock ""
+ fconfigure $sock -translation {auto binary}
+ fileevent $sock writable [list http::Write $token]
} else {
- puts $s ""
- flush $s
- fileevent $s readable [list http::Event $token]
+ puts $sock ""
+ flush $sock
+ fileevent $sock readable [list http::Event $sock $token]
}
- if {! [info exists state(-command)]} {
+ if {![info exists state(-command)]} {
# geturl does EVERYTHING asynchronously, so if the user calls it
# synchronously, we just do a wait here.
@@ -605,7 +753,7 @@ proc http::geturl { url args } {
return -code error [lindex $state(error) 0]
}
}
- } err]} {
+ } err]} then {
# The socket probably was never connected, or the connection dropped
# later.
@@ -637,7 +785,9 @@ proc http::data {token} {
return $state(body)
}
proc http::status {token} {
- if {![info exists $token]} { return "error" }
+ if {![info exists $token]} {
+ return "error"
+ }
variable $token
upvar 0 $token state
return $state(status)
@@ -708,9 +858,11 @@ 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
+ if {
+ [eof $state(sock)] ||
+ [string length [fconfigure $state(sock) -error]]
+ } then {
+ Finish $token "connect failed [fconfigure $state(sock) -error]" 1
} else {
set state(status) connect
fileevent $state(sock) writable {}
@@ -731,7 +883,7 @@ proc http::Connect {token} {
proc http::Write {token} {
variable $token
upvar 0 $token state
- set s $state(sock)
+ set sock $state(sock)
# Output a block. Tcl will buffer this if the socket blocks
set done 0
@@ -742,9 +894,9 @@ proc http::Write {token} {
# 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}]]
+ puts -nonewline $sock \
+ [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)
@@ -754,13 +906,13 @@ proc http::Write {token} {
# Copy blocks from the query channel
set outStr [read $state(-querychannel) $state(-queryblocksize)]
- puts -nonewline $s $outStr
+ puts -nonewline $sock $outStr
incr state(queryoffset) [string length $outStr]
if {[eof $state(-querychannel)]} {
set done 1
}
}
- } err]} {
+ } err]} then {
# Do not call Finish here, but instead let the read half of the socket
# process whatever server reply there is to get.
@@ -768,16 +920,16 @@ proc http::Write {token} {
set done 1
}
if {$done} {
- catch {flush $s}
- fileevent $s writable {}
- fileevent $s readable [list http::Event $token]
+ catch {flush $sock}
+ fileevent $sock writable {}
+ fileevent $sock readable [list http::Event $sock $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)]
+ eval $state(-queryprogress) \
+ [list $token $state(querylength) $state(queryoffset)]
}
}
@@ -786,114 +938,248 @@ proc http::Write {token} {
# Handle input on the socket
#
# Arguments
+# sock The socket receiving input.
# token The token returned from http::geturl
#
# Side Effects
# Read the socket and handle callbacks.
-proc http::Event {token} {
+proc http::Event {sock token} {
variable $token
upvar 0 $token state
- set s $state(sock)
- if {$state(state) eq "header"} {
- if {[catch {gets $s line} n]} {
+ if {![info exists state]} {
+ Log "Event $sock with invalid token '$token' - remote close?"
+ if {![eof $sock]} {
+ if {[set d [read $sock]] ne ""} {
+ Log "WARNING: additional data left on closed socket"
+ }
+ }
+ CloseSocket $sock
+ return
+ }
+ if {$state(state) eq "connecting"} {
+ if {[catch {gets $sock state(http)} n]} {
+ return [Finish $token $n]
+ } elseif {$n >= 0} {
+ set state(state) "header"
+ }
+ } elseif {$state(state) eq "header"} {
+ if {[catch {gets $sock line} n]} {
return [Finish $token $n]
} elseif {$n == 0} {
- variable encodings
+ # We have now read all headers
+ # We ignore HTTP/1.1 100 Continue returns. RFC2616 sec 8.2.3
+ if {$state(http) == "" || [lindex $state(http) 1] == 100} {
+ return
+ }
+
set state(state) body
- if {$state(-binary) || ![string match -nocase text* $state(type)]
- || [string match *gzip* $state(coding)]
- || [string match *compress* $state(coding)]} {
+
+ # If doing a HEAD, then we won't get any body
+ if {$state(-validate)} {
+ Eof $token
+ return
+ }
+
+ # For non-chunked transfer we may have no body - in this case we
+ # may get no further file event if the connection doesn't close
+ # and no more data is sent. We can tell and must finish up now -
+ # not later.
+ if {
+ !(([info exists state(connection)]
+ && ($state(connection) eq "close"))
+ || [info exists state(transfer)])
+ && ($state(totalsize) == 0)
+ } then {
+ Log "body size is 0 and no events likely - complete."
+ Eof $token
+ return
+ }
+
+ # We have to use binary translation to count bytes properly.
+ fconfigure $sock -translation binary
+
+ if {
+ $state(-binary) || ![string match -nocase text* $state(type)]
+ } then {
# Turn off conversions for non-text data
- fconfigure $s -translation binary
+ set state(binary) 1
+ }
+ if {
+ $state(binary) || [string match *gzip* $state(coding)] ||
+ [string match *compress* $state(coding)]
+ } then {
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)]} {
+ if {
+ [info exists state(-channel)] &&
+ ![info exists state(-handler)]
+ } then {
# Initiate a sequence of background fcopies
- fileevent $s readable {}
- CopyStart $s $token
+ fileevent $sock readable {}
+ CopyStart $sock $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]
- }
+ # Process header lines
if {[regexp -nocase {^([^:]+):(.+)$} $line x key value]} {
+ switch -- [string tolower $key] {
+ content-type {
+ set state(type) [string trim [string tolower $value]]
+ # grab the optional charset information
+ if {[regexp -nocase \
+ {charset\s*=\s*\"((?:[^""]|\\\")*)\"} \
+ $state(type) -> cs]} {
+ set state(charset) [string map {{\"} \"} $cs]
+ } else {
+ regexp -nocase {charset\s*=\s*(\S+?);?} \
+ $state(type) -> state(charset)
+ }
+ }
+ content-length {
+ set state(totalsize) [string trim $value]
+ }
+ content-encoding {
+ set state(coding) [string trim $value]
+ }
+ transfer-encoding {
+ set state(transfer) \
+ [string trim [string tolower $value]]
+ }
+ proxy-connection -
+ connection {
+ set state(connection) \
+ [string trim [string tolower $value]]
+ }
+ }
lappend state(meta) $key [string trim $value]
- } elseif {[string match HTTP* $line]} {
- set state(http) $line
}
}
} else {
+ # Now reading body
if {[catch {
if {[info exists state(-handler)]} {
- set n [eval $state(-handler) {$s $token}]
+ set n [eval $state(-handler) [list $sock $token]]
+ } elseif {[info exists state(transfer_final)]} {
+ set line [getTextLine $sock]
+ set n [string length $line]
+ if {$n > 0} {
+ Log "found $n bytes following final chunk"
+ append state(transfer_final) $line
+ } else {
+ Log "final chunk part"
+ Eof $token
+ }
+ } elseif {
+ [info exists state(transfer)]
+ && $state(transfer) eq "chunked"
+ } then {
+ set size 0
+ set chunk [getTextLine $sock]
+ set n [string length $chunk]
+ if {[string trim $chunk] ne ""} {
+ scan $chunk %x size
+ if {$size != 0} {
+ set bl [fconfigure $sock -blocking]
+ fconfigure $sock -blocking 1
+ set chunk [read $sock $size]
+ fconfigure $sock -blocking $bl
+ set n [string length $chunk]
+ if {$n >= 0} {
+ append state(body) $chunk
+ }
+ if {$size != [string length $chunk]} {
+ Log "WARNING: mis-sized chunk:\
+ was [string length $chunk], should be $size"
+ }
+ getTextLine $sock
+ } else {
+ set state(transfer_final) {}
+ }
+ }
} else {
- set block [read $s $state(-blocksize)]
+ #Log "read non-chunk $state(currentsize) of $state(totalsize)"
+ set block [read $sock $state(-blocksize)]
set n [string length $block]
if {$n >= 0} {
append state(body) $block
}
}
- if {$n >= 0} {
- incr state(currentsize) $n
+ if {[info exists state]} {
+ if {$n >= 0} {
+ incr state(currentsize) $n
+ }
+ # If Content-Length - check for end of data.
+ if {
+ ($state(totalsize) > 0)
+ && ($state(currentsize) >= $state(totalsize))
+ } then {
+ Eof $token
+ }
}
- } err]} {
+ } err]} then {
return [Finish $token $err]
} else {
if {[info exists state(-progress)]} {
eval $state(-progress) \
- {$token $state(totalsize) $state(currentsize)}
+ [list $token $state(totalsize) $state(currentsize)]
}
}
}
- if {[eof $s]} {
- Eof $token
+ # catch as an Eof above may have closed the socket already
+ if {![catch {eof $sock} eof] && $eof} {
+ if {[info exists $token]} {
+ set state(connection) close
+ Eof $token
+ } else {
+ # open connection closed on a token that has been cleaned up.
+ CloseSocket $sock
+ }
return
}
}
+# http::getTextLine --
+#
+# Get one line with the stream in blocking crlf mode
+#
+# Arguments
+# sock The socket receiving input.
+#
+# Results:
+# The line of text, without trailing newline
+
+proc http::getTextLine {sock} {
+ set tr [fconfigure $sock -translation]
+ set bl [fconfigure $sock -blocking]
+ fconfigure $sock -translation crlf -blocking 1
+ set r [gets $sock]
+ fconfigure $sock -translation $tr -blocking $bl
+ return $r
+}
+
# http::CopyStart
#
# Error handling wrapper around fcopy
#
# Arguments
-# s The socket to copy from
+# sock 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} {
+proc http::CopyStart {sock token} {
variable $token
upvar 0 $token state
if {[catch {
- fcopy $s $state(-channel) -size $state(-blocksize) -command \
+ fcopy $sock $state(-channel) -size $state(-blocksize) -command \
[list http::CopyDone $token]
- } err]} {
+ } err]} then {
Finish $token $err
}
}
@@ -912,18 +1198,19 @@ proc http::CopyStart {s token} {
proc http::CopyDone {token count {error {}}} {
variable $token
upvar 0 $token state
- set s $state(sock)
+ set sock $state(sock)
incr state(currentsize) $count
if {[info exists state(-progress)]} {
- eval $state(-progress) {$token $state(totalsize) $state(currentsize)}
+ eval $state(-progress) \
+ [list $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} {
+ } elseif {[catch {eof $sock} iseof] || $iseof} {
Eof $token
} else {
- CopyStart $s $token
+ CopyStart $sock $token
}
}
@@ -937,7 +1224,7 @@ proc http::CopyDone {token count {error {}}} {
# Side Effects
# Clean up the socket
-proc http::Eof {token} {
+proc http::Eof {token {force 0}} {
variable $token
upvar 0 $token state
if {$state(state) eq "header"} {
@@ -946,7 +1233,35 @@ proc http::Eof {token} {
} else {
set state(status) ok
}
- set state(state) eof
+
+ if {($state(coding) eq "gzip") && [string length $state(body)] > 0} {
+ if {[catch {
+ if {[package vsatisfies [package present Tcl] 8.6]} {
+ # The zlib integration into 8.6 includes proper gzip support
+ set state(body) [zlib gunzip $state(body)]
+ } else {
+ set state(body) [Gunzip $state(body)]
+ }
+ } err]} then {
+ return [Finish $token $err]
+ }
+ }
+
+ if {!$state(binary)} {
+ # 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 enc [CharsetToEncoding $state(charset)]
+ if {$enc ne "binary"} {
+ set state(body) [encoding convertfrom $enc $state(body)]
+ }
+
+ # Translate text line endings.
+ set state(body) [string map {\r\n \n \r \n} $state(body)]
+ }
+
Finish $token
}
@@ -964,9 +1279,9 @@ proc http::wait {token} {
variable $token
upvar 0 $token state
- if {![info exists state(status)] || [string length $state(status)] == 0} {
+ if {![info exists state(status)] || $state(status) eq ""} {
# We must wait on the original variable name, not the upvar alias
- vwait $token\(status)
+ vwait ${token}(status)
}
return [status $token]
@@ -974,7 +1289,7 @@ proc http::wait {token} {
# http::formatQuery --
#
-# See documentation for details. Call http::formatQuery with an even
+# 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.
#
@@ -1042,14 +1357,110 @@ proc http::mapReply {string} {
proc http::ProxyRequired {host} {
variable http
if {[info exists http(-proxyhost)] && [string length $http(-proxyhost)]} {
- if {![info exists http(-proxyport)] || \
- ![string length $http(-proxyport)]} {
+ if {
+ ![info exists http(-proxyport)] ||
+ ![string length $http(-proxyport)]
+ } then {
set http(-proxyport) 8080
}
return [list $http(-proxyhost) $http(-proxyport)]
}
}
+# http::CharsetToEncoding --
+#
+# Tries to map a given IANA charset to a tcl encoding. If no encoding
+# can be found, returns binary.
+#
+
+proc http::CharsetToEncoding {charset} {
+ variable encodings
+
+ set charset [string tolower $charset]
+ if {[regexp {iso-?8859-([0-9]+)} $charset -> num]} {
+ set encoding "iso8859-$num"
+ } elseif {[regexp {iso-?2022-(jp|kr)} $charset -> ext]} {
+ set encoding "iso2022-$ext"
+ } elseif {[regexp {shift[-_]?js} $charset]} {
+ set encoding "shiftjis"
+ } elseif {[regexp {(?:windows|cp)-?([0-9]+)} $charset -> num]} {
+ set encoding "cp$num"
+ } elseif {$charset eq "us-ascii"} {
+ set encoding "ascii"
+ } elseif {[regexp {(?:iso-?)?lat(?:in)?-?([0-9]+)} $charset -> num]} {
+ switch -- $num {
+ 5 {set encoding "iso8859-9"}
+ 1 - 2 - 3 {
+ set encoding "iso8859-$num"
+ }
+ }
+ } else {
+ # other charset, like euc-xx, utf-8,... may directly map to encoding
+ set encoding $charset
+ }
+ set idx [lsearch -exact $encodings $encoding]
+ if {$idx >= 0} {
+ return $encoding
+ } else {
+ return "binary"
+ }
+}
+
+# http::Gunzip --
+#
+# Decompress data transmitted using the gzip transfer coding.
+#
+
+# FIX ME: redo using zlib sinflate
+proc http::Gunzip {data} {
+ binary scan $data Scb5icc magic method flags time xfl os
+ set pos 10
+ if {$magic != 0x1f8b} {
+ return -code error "invalid data: supplied data is not in gzip format"
+ }
+ if {$method != 8} {
+ return -code error "invalid compression method"
+ }
+
+ # lassign [split $flags ""] f_text f_crc f_extra f_name f_comment
+ foreach {f_text f_crc f_extra f_name f_comment} [split $flags ""] break
+ set extra ""
+ if {$f_extra} {
+ binary scan $data @${pos}S xlen
+ incr pos 2
+ set extra [string range $data $pos $xlen]
+ set pos [incr xlen]
+ }
+
+ set name ""
+ if {$f_name} {
+ set ndx [string first \0 $data $pos]
+ set name [string range $data $pos $ndx]
+ set pos [incr ndx]
+ }
+
+ set comment ""
+ if {$f_comment} {
+ set ndx [string first \0 $data $pos]
+ set comment [string range $data $pos $ndx]
+ set pos [incr ndx]
+ }
+
+ set fcrc ""
+ if {$f_crc} {
+ set fcrc [string range $data $pos [incr pos]]
+ incr pos
+ }
+
+ binary scan [string range $data end-7 end] ii crc size
+ set inflated [zlib inflate [string range $data $pos end-8]]
+ set chk [zlib crc32 $inflated]
+ if {($crc & 0xffffffff) != ($chk & 0xffffffff)} {
+ return -code error "invalid data: checksum mismatch $crc != $chk"
+ }
+ return $inflated
+}
+
# Local variables:
# indent-tabs-mode: t
# End:
diff --git a/library/http/pkgIndex.tcl b/library/http/pkgIndex.tcl
index cf6a1ff..fed5829 100644
--- a/library/http/pkgIndex.tcl
+++ b/library/http/pkgIndex.tcl
@@ -1,12 +1,4 @@
# Tcl package index file, version 1.1
-# This file is generated by the "pkg_mkIndex" command
-# and sourced either when an application starts up or
-# by a "package unknown" script. It invokes the
-# "package ifneeded" command to set up package-related
-# information so that packages will be loaded automatically
-# in response to "package require" commands. When this
-# script is sourced, the variable $dir must contain the
-# full path name of this file's directory.
if {![package vsatisfies [package provide Tcl] 8.4]} {return}
-package ifneeded http 2.5.5 [list tclPkgSetup $dir http 2.5.5 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister ::http::mapReply}}}]
+package ifneeded http 2.7.6 [list tclPkgSetup $dir http 2.7.6 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister ::http::mapReply}}}]
diff --git a/library/init.tcl b/library/init.tcl
index 8a53c69..1dd5881 100644
--- a/library/init.tcl
+++ b/library/init.tcl
@@ -6,6 +6,7 @@
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 Scriptics Corporation.
+# Copyright (c) 2004 by Kevin B. Kenny. All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -14,7 +15,7 @@
if {[info commands package] == ""} {
error "version mismatch: library\nscripts expect Tcl version 7.5b1 or later but the loaded version is\nonly [info patchlevel]"
}
-package require -exact Tcl 8.4
+package require -exact Tcl 8.5.10
# Compute the auto path to use in this interpreter.
# The values on the path come from several locations:
@@ -22,7 +23,7 @@ package require -exact Tcl 8.4
# The environment variable TCLLIBPATH
#
# tcl_library, which is the directory containing this init.tcl script.
-# tclInitScript.h searches around for the directory containing this
+# [tclInit] (Tcl_Init()) searches around for the directory containing this
# init.tcl and defines tcl_library to that location before sourcing it.
#
# The parent directory of tcl_library. Adding the parent
@@ -35,7 +36,6 @@ package require -exact Tcl 8.4
# tcl_pkgPath, which is set by the platform-specific initialization routines
# On UNIX it is compiled in
# On Windows, it is not used
-# On Macintosh it is "Tool Command Language" in the Extensions folder
if {![info exists auto_path]} {
if {[info exists env(TCLLIBPATH)]} {
@@ -46,30 +46,74 @@ if {![info exists auto_path]} {
}
namespace eval tcl {
variable Dir
- if {[info library] ne ""} {
- foreach Dir [list [info library] [file dirname [info library]]] {
- if {[lsearch -exact $::auto_path $Dir] < 0} {
- lappend ::auto_path $Dir
- }
+ foreach Dir [list $::tcl_library [file dirname $::tcl_library]] {
+ if {$Dir ni $::auto_path} {
+ lappend ::auto_path $Dir
}
}
set Dir [file join [file dirname [file dirname \
[info nameofexecutable]]] lib]
- if {[lsearch -exact $::auto_path $Dir] < 0} {
+ if {$Dir ni $::auto_path} {
lappend ::auto_path $Dir
}
- if {[info exists ::tcl_pkgPath]} {
+ catch {
foreach Dir $::tcl_pkgPath {
- if {[lsearch -exact $::auto_path $Dir] < 0} {
+ if {$Dir ni $::auto_path} {
lappend ::auto_path $Dir
}
}
}
+
+ if {![interp issafe]} {
+ variable Path [encoding dirs]
+ set Dir [file join $::tcl_library encoding]
+ if {$Dir ni $Path} {
+ lappend Path $Dir
+ encoding dirs $Path
+ }
+ }
+
+ # TIP #255 min and max functions
+ namespace eval mathfunc {
+ proc min {args} {
+ if {[llength $args] == 0} {
+ return -code error \
+ "too few arguments to math function \"min\""
+ }
+ set val Inf
+ foreach arg $args {
+ # This will handle forcing the numeric value without
+ # ruining the internal type of a numeric object
+ if {[catch {expr {double($arg)}} err]} {
+ return -code error $err
+ }
+ if {$arg < $val} { set val $arg }
+ }
+ return $val
+ }
+ proc max {args} {
+ if {[llength $args] == 0} {
+ return -code error \
+ "too few arguments to math function \"max\""
+ }
+ set val -Inf
+ foreach arg $args {
+ # This will handle forcing the numeric value without
+ # ruining the internal type of a numeric object
+ if {[catch {expr {double($arg)}} err]} {
+ return -code error $err
+ }
+ if {$arg > $val} { set val $arg }
+ }
+ return $val
+ }
+ namespace export min max
+ }
}
-
+
# Windows specific end of initialization
-if {(![interp issafe]) && $tcl_platform(platform) eq "windows"} {
+if {(![interp issafe]) && ($tcl_platform(platform) eq "windows")} {
namespace eval tcl {
proc EnvTraceProc {lo n1 n2 op} {
set x $::env($n2)
@@ -109,16 +153,42 @@ if {(![interp issafe]) && $tcl_platform(platform) eq "windows"} {
# Setup the unknown package handler
-package unknown tclPkgUnknown
-if {![interp issafe]} {
- # setup platform specific unknown package handlers
- if {$::tcl_platform(platform) eq "unix"
- && $::tcl_platform(os) eq "Darwin"} {
- package unknown [list tcl::MacOSXPkgUnknown [package unknown]]
- }
- if {$::tcl_platform(platform) eq "macintosh"} {
- package unknown [list tcl::MacPkgUnknown [package unknown]]
+if {[interp issafe]} {
+ package unknown {::tcl::tm::UnknownHandler ::tclPkgUnknown}
+} else {
+ # Set up search for Tcl Modules (TIP #189).
+ # and setup platform specific unknown package handlers
+ if {$::tcl_platform(os) eq "Darwin"
+ && $::tcl_platform(platform) eq "unix"} {
+ package unknown {::tcl::tm::UnknownHandler \
+ {::tcl::MacOSXPkgUnknown ::tclPkgUnknown}}
+ } else {
+ package unknown {::tcl::tm::UnknownHandler ::tclPkgUnknown}
+ }
+
+ # Set up the 'clock' ensemble
+
+ namespace eval ::tcl::clock [list variable TclLibDir $::tcl_library]
+
+ proc clock args {
+ namespace eval ::tcl::clock [list namespace ensemble create -command \
+ [uplevel 1 [list namespace origin [lindex [info level 0] 0]]] \
+ -subcommands {
+ add clicks format microseconds milliseconds scan seconds
+ }]
+
+ # Auto-loading stubs for 'clock.tcl'
+
+ foreach cmd {add format scan} {
+ proc ::tcl::clock::$cmd args {
+ variable TclLibDir
+ source -encoding utf-8 [file join $TclLibDir clock.tcl]
+ return [uplevel 1 [info level 0]]
+ }
+ }
+
+ return [uplevel 1 [info level 0]]
}
}
@@ -126,13 +196,11 @@ if {![interp issafe]} {
if {[namespace which -command exec] eq ""} {
- # Some machines, such as the Macintosh, do not have exec. Also, on all
+ # Some machines do not have exec. Also, on all
# platforms, safe interpreters do not have exec.
set auto_noexec 1
}
-set errorCode ""
-set errorInfo ""
# Define a log command (which can be overwitten to log errors
# differently, specially when stderr is not available)
@@ -166,72 +234,74 @@ if {[namespace which -command tclLog] eq ""} {
# command, including the command name.
proc unknown args {
- global auto_noexec auto_noload env unknown_pending tcl_interactive
- global errorCode errorInfo
+ variable ::tcl::UnknownPending
+ global auto_noexec auto_noload env tcl_interactive
# If the command word has the form "namespace inscope ns cmd"
# then concatenate its arguments onto the end and evaluate it.
set cmd [lindex $args 0]
if {[regexp "^:*namespace\[ \t\n\]+inscope" $cmd] && [llength $cmd] == 4} {
+ #return -code error "You need an {*}"
set arglist [lrange $args 1 end]
- set ret [catch {uplevel 1 ::$cmd $arglist} result]
- if {$ret == 0} {
- return $result
- } else {
- return -code $ret -errorcode $errorCode $result
- }
+ set ret [catch {uplevel 1 ::$cmd $arglist} result opts]
+ dict unset opts -errorinfo
+ dict incr opts -level
+ return -options $opts $result
}
- # Save the values of errorCode and errorInfo variables, since they
- # may get modified if caught errors occur below. The variables will
- # be restored just before re-executing the missing command.
-
- # Safety check in case something unsets the variables
- # ::errorInfo or ::errorCode. [Bug 1063707]
- if {![info exists errorCode]} {
- set errorCode ""
- }
- if {![info exists errorInfo]} {
- set errorInfo ""
- }
- set savedErrorCode $errorCode
- set savedErrorInfo $errorInfo
+ catch {set savedErrorInfo $::errorInfo}
+ catch {set savedErrorCode $::errorCode}
set name $cmd
if {![info exists auto_noload]} {
#
# Make sure we're not trying to load the same proc twice.
#
- if {[info exists unknown_pending($name)]} {
- return -code error "self-referential recursion in \"unknown\" for command \"$name\"";
- }
- set unknown_pending($name) pending;
- set ret [catch {auto_load $name [uplevel 1 {::namespace current}]} msg]
- unset unknown_pending($name);
+ if {[info exists UnknownPending($name)]} {
+ return -code error "self-referential recursion\
+ in \"unknown\" for command \"$name\"";
+ }
+ set UnknownPending($name) pending;
+ set ret [catch {
+ auto_load $name [uplevel 1 {::namespace current}]
+ } msg opts]
+ unset UnknownPending($name);
if {$ret != 0} {
- append errorInfo "\n (autoloading \"$name\")"
- return -code $ret -errorcode $errorCode -errorinfo $errorInfo $msg
+ dict append opts -errorinfo "\n (autoloading \"$name\")"
+ return -options $opts $msg
}
- if {![array size unknown_pending]} {
- unset unknown_pending
+ if {![array size UnknownPending]} {
+ unset UnknownPending
}
if {$msg} {
- set errorCode $savedErrorCode
- set errorInfo $savedErrorInfo
- set code [catch {uplevel 1 $args} msg]
+ if {[info exists savedErrorCode]} {
+ set ::errorCode $savedErrorCode
+ } else {
+ unset -nocomplain ::errorCode
+ }
+ if {[info exists savedErrorInfo]} {
+ set ::errorInfo $savedErrorInfo
+ } else {
+ unset -nocomplain ::errorInfo
+ }
+ set code [catch {uplevel 1 $args} msg opts]
if {$code == 1} {
#
# Compute stack trace contribution from the [uplevel].
# Note the dependence on how Tcl_AddErrorInfo, etc.
# construct the stack trace.
#
+ set errorInfo [dict get $opts -errorinfo]
+ set errorCode [dict get $opts -errorcode]
set cinfo $args
- set ellipsis ""
- while {[string bytelength $cinfo] > 150} {
- set cinfo [string range $cinfo 0 end-1]
- set ellipsis "..."
+ if {[string bytelength $cinfo] > 150} {
+ set cinfo [string range $cinfo 0 150]
+ while {[string bytelength $cinfo] > 150} {
+ set cinfo [string range $cinfo 0 end-1]
+ }
+ append cinfo ...
}
- append cinfo $ellipsis "\"\n (\"uplevel\" body line 1)"
+ append cinfo "\"\n (\"uplevel\" body line 1)"
append cinfo "\n invoked from within"
append cinfo "\n\"uplevel 1 \$args\""
#
@@ -244,7 +314,9 @@ proc unknown args {
# The stack has only the eval from the expanded command
# Do not generate any stack trace here.
#
- return -code error -errorcode $errorCode $msg
+ dict unset opts -errorinfo
+ dict incr opts -level
+ return -options $opts $msg
}
#
# Stack trace is nested, trim off just the contribution
@@ -261,32 +333,33 @@ proc unknown args {
#
if {$errorInfo ne "$einfo$expect"} {
error "Tcl bug: unexpected stack trace in \"unknown\"" {} \
- [list CORE UNKNOWN BADTRACE $expect $errorInfo]
+ [list CORE UNKNOWN BADTRACE $einfo $expect $errorInfo]
}
return -code error -errorcode $errorCode \
-errorinfo $einfo $msg
} else {
- return -code $code $msg
+ dict incr opts -level
+ return -options $opts $msg
}
}
}
- if {([info level] == 1) && [info script] eq "" \
+ if {([info level] == 1) && ([info script] eq "") \
&& [info exists tcl_interactive] && $tcl_interactive} {
if {![info exists auto_noexec]} {
set new [auto_execok $name]
if {$new ne ""} {
- set errorCode $savedErrorCode
- set errorInfo $savedErrorInfo
set redir ""
if {[namespace which -command console] eq ""} {
set redir ">&@stdout <@stdin"
}
- return [uplevel 1 exec $redir $new [lrange $args 1 end]]
+ uplevel 1 [list ::catch \
+ [concat exec $redir $new [lrange $args 1 end]] \
+ ::tcl::UnknownResult ::tcl::UnknownOptions]
+ dict incr ::tcl::UnknownOptions -level
+ return -options $::tcl::UnknownOptions $::tcl::UnknownResult
}
}
- set errorCode $savedErrorCode
- set errorInfo $savedErrorInfo
if {$name eq "!!"} {
set newcmd [history event]
} elseif {[regexp {^!(.+)$} $name -> event]} {
@@ -298,7 +371,10 @@ proc unknown args {
if {[info exists newcmd]} {
tclLog $newcmd
history change $newcmd 0
- return [uplevel 1 $newcmd]
+ uplevel 1 [list ::catch $newcmd \
+ ::tcl::UnknownResult ::tcl::UnknownOptions]
+ dict incr ::tcl::UnknownOptions -level
+ return -options $::tcl::UnknownOptions $::tcl::UnknownResult
}
set ret [catch {set candidates [info commands $name*]} msg]
@@ -306,9 +382,9 @@ proc unknown args {
set name ""
}
if {$ret != 0} {
- return -code $ret -errorcode $errorCode \
- "error in unknown while checking if \"$name\" is\
- a unique command abbreviation:\n$msg"
+ dict append opts -errorinfo \
+ "\n (expanding command prefix \"$name\" in unknown)"
+ return -options $opts $msg
}
# Filter out bogus matches when $name contained
# a glob-special char [Bug 946952]
@@ -325,7 +401,10 @@ proc unknown args {
}
}
if {[llength $cmds] == 1} {
- return [uplevel 1 [lreplace $args 0 0 [lindex $cmds 0]]]
+ uplevel 1 [list ::catch [lreplace $args 0 0 [lindex $cmds 0]] \
+ ::tcl::UnknownResult ::tcl::UnknownOptions]
+ dict incr ::tcl::UnknownOptions -level
+ return -options $::tcl::UnknownOptions $::tcl::UnknownResult
}
if {[llength $cmds]} {
return -code error "ambiguous command name \"$name\": [lsort $cmds]"
@@ -347,7 +426,7 @@ proc unknown args {
# for instance. If not given, namespace current is used.
proc auto_load {cmd {namespace {}}} {
- global auto_index auto_oldpath auto_path
+ global auto_index auto_path
if {$namespace eq ""} {
set namespace [uplevel 1 [list ::namespace current]]
@@ -399,9 +478,10 @@ proc auto_load {cmd {namespace {}}} {
# None.
proc auto_load_index {} {
- global auto_index auto_oldpath auto_path errorInfo errorCode
+ variable ::tcl::auto_oldpath
+ global auto_index auto_path
- if {[info exists auto_oldpath] && $auto_oldpath eq $auto_path} {
+ if {[info exists auto_oldpath] && ($auto_oldpath eq $auto_path)} {
return 0
}
set auto_oldpath $auto_path
@@ -424,7 +504,7 @@ proc auto_load_index {} {
eval [read $f]
} elseif {$id eq "# Tcl autoload index file: each line identifies a Tcl"} {
while {[gets $f line] >= 0} {
- if {[string index $line 0] eq "#"
+ if {([string index $line 0] eq "#") \
|| ([llength $line] != 2)} {
continue
}
@@ -435,12 +515,12 @@ proc auto_load_index {} {
} else {
error "[file join $dir tclIndex] isn't a proper Tcl index file"
}
- } msg]
+ } msg opts]
if {$f ne ""} {
close $f
}
if {$error} {
- error $msg $errorInfo $errorCode
+ return -options $opts $msg
}
}
}
@@ -577,10 +657,10 @@ proc auto_execok name {
# Add an initial ; to have the {} extension check first.
set execExtensions [split ";$env(PATHEXT)" ";"]
} else {
- set execExtensions [list {} .com .exe .bat]
+ set execExtensions [list {} .com .exe .bat .cmd]
}
- if {[lsearch -exact $shellBuiltins $name] != -1} {
+ if {$name in $shellBuiltins} {
# When this is command.com for some reason on Win2K, Tcl won't
# exec it unless the case is right, which this corrects. COMSPEC
# may not point to a real file, so do the check.
@@ -620,7 +700,7 @@ proc auto_execok name {
foreach dir [split $path {;}] {
# Skip already checked directories
- if {[info exists checked($dir)] || $dir eq {}} { continue }
+ if {[info exists checked($dir)] || ($dir eq {})} { continue }
set checked($dir) {}
foreach ext $execExtensions {
set file [file join $dir ${name}${ext}]
@@ -680,10 +760,11 @@ proc auto_execok name {
proc tcl::CopyDirectory {action src dest} {
set nsrc [file normalize $src]
set ndest [file normalize $dest]
+
if {$action eq "renaming"} {
# Can't rename volumes. We could give a more precise
# error message here, but that would break the test suite.
- if {[lsearch -exact [file volumes] $nsrc] != -1} {
+ if {$nsrc in [file volumes]} {
return -code error "error $action \"$src\" to\
\"$dest\": trying to rename a volume or move a directory\
into itself"
@@ -696,17 +777,22 @@ proc tcl::CopyDirectory {action src dest} {
into itself"
}
if {$action eq "copying"} {
- return -code error "error $action \"$src\" to\
- \"$dest\": file already exists"
+ # We used to throw an error here, but, looking more closely
+ # at the core copy code in tclFCmd.c, if the destination
+ # exists, then we should only call this function if -force
+ # is true, which means we just want to over-write. So,
+ # the following code is now commented out.
+ #
+ # return -code error "error $action \"$src\" to\
+ # \"$dest\": file already exists"
} else {
# Depending on the platform, and on the current
# working directory, the directories '.', '..'
# can be returned in various combinations. Anyway,
# if any other file is returned, we must signal an error.
set existing [glob -nocomplain -directory $dest * .*]
- eval [linsert \
- [glob -nocomplain -directory $dest -type hidden * .*] 0 \
- lappend existing]
+ lappend existing {*}[glob -nocomplain -directory $dest \
+ -type hidden * .*]
foreach s $existing {
if {([file tail $s] ne ".") && ([file tail $s] ne "..")} {
return -code error "error $action \"$src\" to\
@@ -734,10 +820,10 @@ proc tcl::CopyDirectory {action src dest} {
# or filesystems hidden files may have other interpretations.
set filelist [concat [glob -nocomplain -directory $src *] \
[glob -nocomplain -directory $src -types hidden *]]
-
+
foreach s [lsort -unique $filelist] {
if {([file tail $s] ne ".") && ([file tail $s] ne "..")} {
- file copy $s [file join $dest [file tail $s]]
+ file copy -force $s [file join $dest [file tail $s]]
}
}
return
diff --git a/library/ldAout.tcl b/library/ldAout.tcl
deleted file mode 100644
index bd520a3..0000000
--- a/library/ldAout.tcl
+++ /dev/null
@@ -1,231 +0,0 @@
-# ldAout.tcl --
-#
-# This "tclldAout" procedure in this script acts as a replacement
-# for the "ld" command when linking an object file that will be
-# loaded dynamically into Tcl or Tk using pseudo-static linking.
-#
-# Parameters:
-# The arguments to the script are the command line options for
-# an "ld" command.
-#
-# Results:
-# The "ld" command is parsed, and the "-o" option determines the
-# module name. ".a" and ".o" options are accumulated.
-# The input archives and object files are examined with the "nm"
-# command to determine whether the modules initialization
-# entry and safe initialization entry are present. A trivial
-# C function that locates the entries is composed, compiled, and
-# its .o file placed before all others in the command; then
-# "ld" is executed to bind the objects together.
-#
-# Copyright (c) 1995, by General Electric Company. All rights reserved.
-#
-# See the file "license.terms" for information on usage and redistribution
-# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-#
-# This work was supported in part by the ARPA Manufacturing Automation
-# and Design Engineering (MADE) Initiative through ARPA contract
-# F33615-94-C-4400.
-
-proc tclLdAout {{cc {}} {shlib_suffix {}} {shlib_cflags none}} {
- global env
- global argv
-
- if {[string equal $cc ""]} {
- set cc $env(CC)
- }
-
- # if only two parameters are supplied there is assumed that the
- # only shlib_suffix is missing. This parameter is anyway available
- # as "info sharedlibextension" too, so there is no need to transfer
- # 3 parameters to the function tclLdAout. For compatibility, this
- # function now accepts both 2 and 3 parameters.
-
- if {[string equal $shlib_suffix ""]} {
- set shlib_cflags $env(SHLIB_CFLAGS)
- } elseif {[string equal $shlib_cflags "none"]} {
- set shlib_cflags $shlib_suffix
- }
-
- # seenDotO is nonzero if a .o or .a file has been seen
- set seenDotO 0
-
- # minusO is nonzero if the last command line argument was "-o".
- set minusO 0
-
- # head has command line arguments up to but not including the first
- # .o or .a file. tail has the rest of the arguments.
- set head {}
- set tail {}
-
- # nmCommand is the "nm" command that lists global symbols from the
- # object files.
- set nmCommand {|nm -g}
-
- # entryProtos is the table of _Init and _SafeInit prototypes found in the
- # module.
- set entryProtos {}
-
- # entryPoints is the table of _Init and _SafeInit entries found in the
- # module.
- set entryPoints {}
-
- # libraries is the list of -L and -l flags to the linker.
- set libraries {}
- set libdirs {}
-
- # Process command line arguments
- foreach a $argv {
- if {!$minusO && [regexp {\.[ao]$} $a]} {
- set seenDotO 1
- lappend nmCommand $a
- }
- if {$minusO} {
- set outputFile $a
- set minusO 0
- } elseif {![string compare $a -o]} {
- set minusO 1
- }
- if {[regexp {^-[lL]} $a]} {
- lappend libraries $a
- if {[regexp {^-L} $a]} {
- lappend libdirs [string range $a 2 end]
- }
- } elseif {$seenDotO} {
- lappend tail $a
- } else {
- lappend head $a
- }
- }
- lappend libdirs /lib /usr/lib
-
- # MIPS -- If there are corresponding G0 libraries, replace the
- # ordinary ones with the G0 ones.
-
- set libs {}
- foreach lib $libraries {
- if {[regexp {^-l} $lib]} {
- set lname [string range $lib 2 end]
- foreach dir $libdirs {
- if {[file exists [file join $dir lib${lname}_G0.a]]} {
- set lname ${lname}_G0
- break
- }
- }
- lappend libs -l$lname
- } else {
- lappend libs $lib
- }
- }
- set libraries $libs
-
- # Extract the module name from the "-o" option
-
- if {![info exists outputFile]} {
- error "-o option must be supplied to link a Tcl load module"
- }
- set m [file tail $outputFile]
- if {[regexp {\.a$} $outputFile]} {
- set shlib_suffix .a
- } else {
- set shlib_suffix ""
- }
- if {[regexp {\..*$} $outputFile match]} {
- set l [expr {[string length $m] - [string length $match]}]
- } else {
- error "Output file does not appear to have a suffix"
- }
- set modName [string tolower $m 0 [expr {$l-1}]]
- if {[regexp {^lib} $modName]} {
- set modName [string range $modName 3 end]
- }
- if {[regexp {[0-9\.]*(_g0)?$} $modName match]} {
- set modName [string range $modName 0 [expr {[string length $modName]-[string length $match]-1}]]
- }
- set modName [string totitle $modName]
-
- # Catalog initialization entry points found in the module
-
- set f [open $nmCommand r]
- while {[gets $f l] >= 0} {
- if {[regexp {T[ ]*_?([A-Z][a-z0-9_]*_(Safe)?Init(__FP10Tcl_Interp)?)$} $l trash symbol]} {
- if {![regexp {_?([A-Z][a-z0-9_]*_(Safe)?Init)} $symbol trash s]} {
- set s $symbol
- }
- append entryProtos {extern int } $symbol { (); } \n
- append entryPoints { } \{ { "} $s {", } $symbol { } \} , \n
- }
- }
- close $f
-
- if {[string equal $entryPoints ""]} {
- error "No entry point found in objects"
- }
-
- # Compose a C function that resolves the initialization entry points and
- # embeds the required libraries in the object code.
-
- set C {#include <string.h>}
- append C \n
- append C {char TclLoadLibraries_} $modName { [] =} \n
- append C { "@LIBS: } $libraries {";} \n
- append C $entryProtos
- append C {static struct } \{ \n
- append C { char * name;} \n
- append C { int (*value)();} \n
- append C \} {dictionary [] = } \{ \n
- append C $entryPoints
- append C { 0, 0 } \n \} \; \n
- append C {typedef struct Tcl_Interp Tcl_Interp;} \n
- append C {typedef int Tcl_PackageInitProc (Tcl_Interp *);} \n
- append C {Tcl_PackageInitProc *} \n
- append C TclLoadDictionary_ $modName { (symbol)} \n
- append C { CONST char * symbol;} \n
- append C {
- {
- int i;
- for (i = 0; dictionary [i] . name != 0; ++i) {
- if (!strcmp (symbol, dictionary [i] . name)) {
- return dictionary [i].value;
- }
- }
- return 0;
- }
- }
- append C \n
-
-
- # Write the C module and compile it
-
- set cFile tcl$modName.c
- set f [open $cFile w]
- puts -nonewline $f $C
- close $f
- set ccCommand "$cc -c $shlib_cflags $cFile"
- puts stderr $ccCommand
- eval exec $ccCommand
-
- # Now compose and execute the ld command that packages the module
-
- if {[string equal $shlib_suffix ".a"]} {
- set ldCommand "ar cr $outputFile"
- regsub { -o} $tail {} tail
- } else {
- set ldCommand ld
- foreach item $head {
- lappend ldCommand $item
- }
- }
- lappend ldCommand tcl$modName.o
- foreach item $tail {
- lappend ldCommand $item
- }
- puts stderr $ldCommand
- eval exec $ldCommand
- if {[string equal $shlib_suffix ".a"]} {
- exec ranlib $outputFile
- }
-
- # Clean up working files
- exec /bin/rm $cFile [file rootname $cFile].o
-}
diff --git a/library/msgcat/msgcat.tcl b/library/msgcat/msgcat.tcl
index 7e663cf..369ed52 100644
--- a/library/msgcat/msgcat.tcl
+++ b/library/msgcat/msgcat.tcl
@@ -10,10 +10,10 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-package require Tcl 8.2
+package require Tcl 8.5
# When the version number changes, be sure to update the pkgIndex.tcl file,
# and the installation directory in the Makefiles.
-package provide msgcat 1.3.4
+package provide msgcat 1.4.4
namespace eval msgcat {
namespace export mc mcload mclocale mcmax mcmset mcpreferences mcset \
@@ -26,13 +26,14 @@ namespace eval msgcat {
variable Loclist {}
# Records the mapping between source strings and translated strings. The
- # array key is of the form "<locale>,<namespace>,<src>" and the value is
+ # dict key is of the form "<locale> <namespace> <src>", where locale and
+ # namespace should be themselves dict values and the value is
# the translated string.
- array set Msgs {}
+ variable Msgs [dict create]
# Map of language codes used in Windows registry to those of ISO-639
- if { [string equal $::tcl_platform(platform) windows] } {
- array set WinRegToISO639 {
+ if { $::tcl_platform(platform) eq "windows" } {
+ variable WinRegToISO639 [dict create {*}{
01 ar 0401 ar_SA 0801 ar_IQ 0c01 ar_EG 1001 ar_LY 1401 ar_DZ
1801 ar_MA 1c01 ar_TN 2001 ar_OM 2401 ar_YE 2801 ar_SY
2c01 ar_JO 3001 ar_LB 3401 ar_KW 3801 ar_AE 3c01 ar_BH
@@ -157,7 +158,7 @@ namespace eval msgcat {
77 so 0477 so_SO
78 sit 0478 sit_CN
79 pap 0479 pap_AN
- }
+ }]
}
}
@@ -174,7 +175,7 @@ namespace eval msgcat {
# args Args to pass to the format command
#
# Results:
-# Returns the translatd string. Propagates errors thrown by the
+# Returns the translated string. Propagates errors thrown by the
# format command.
proc msgcat::mc {src args} {
@@ -186,23 +187,22 @@ proc msgcat::mc {src args} {
variable Locale
set ns [uplevel 1 [list ::namespace current]]
-
+
while {$ns != ""} {
foreach loc $Loclist {
- if {[info exists Msgs($loc,$ns,$src)]} {
+ if {[dict exists $Msgs $loc $ns $src]} {
if {[llength $args] == 0} {
- return $Msgs($loc,$ns,$src)
+ return [dict get $Msgs $loc $ns $src]
} else {
- return [uplevel 1 \
- [linsert $args 0 ::format $Msgs($loc,$ns,$src)]]
+ return [format [dict get $Msgs $loc $ns $src] {*}$args]
}
}
}
set ns [namespace parent $ns]
}
# we have not found the translation
- return [uplevel 1 \
- [linsert $args 0 [::namespace origin mcunknown] $Locale $src]]
+ return [uplevel 1 [list [namespace origin mcunknown] \
+ $Locale $src {*}$args]]
}
# msgcat::mclocale --
@@ -223,7 +223,8 @@ proc msgcat::mclocale {args} {
set len [llength $args]
if {$len > 1} {
- error {wrong # args: should be "mclocale ?newLocale?"}
+ return -code error "wrong # args: should be\
+ \"[lindex [info level 0] 0] ?newLocale?\""
}
if {$len == 1} {
@@ -236,9 +237,13 @@ proc msgcat::mclocale {args} {
set Loclist {}
set word ""
foreach part [split $Locale _] {
- set word [string trimleft "${word}_${part}" _]
- set Loclist [linsert $Loclist 0 $word]
+ set word [string trim "${word}_${part}" _]
+ if {$word ne [lindex $Loclist 0]} {
+ set Loclist [linsert $Loclist 0 $word]
+ }
}
+ lappend Loclist {}
+ set Locale [lindex $Loclist 0]
}
return $Locale
}
@@ -273,13 +278,13 @@ proc msgcat::mcpreferences {} {
proc msgcat::mcload {langdir} {
set x 0
foreach p [mcpreferences] {
+ if { $p eq {} } {
+ set p ROOT
+ }
set langfile [file join $langdir $p.msg]
if {[file exists $langfile]} {
incr x
- set fid [open $langfile "r"]
- fconfigure $fid -encoding utf-8
- uplevel 1 [read $fid]
- close $fid
+ uplevel 1 [list ::source -encoding utf-8 $langfile]
}
}
return $x
@@ -301,12 +306,14 @@ proc msgcat::mcload {langdir} {
proc msgcat::mcset {locale src {dest ""}} {
variable Msgs
if {[llength [info level 0]] == 3} { ;# dest not specified
- set dest $src
+ set dest $src
}
set ns [uplevel 1 [list ::namespace current]]
- set Msgs([string tolower $locale],$ns,$src) $dest
+ set locale [string tolower $locale]
+
+ dict set Msgs $locale $ns $src $dest
return $dest
}
@@ -326,16 +333,17 @@ proc msgcat::mcmset {locale pairs } {
set length [llength $pairs]
if {$length % 2} {
- error {bad translation list: should be "mcmset locale {src dest ...}"}
+ return -code error "bad translation list:\
+ should be \"[lindex [info level 0] 0] locale {src dest ...}\""
}
-
+
set locale [string tolower $locale]
set ns [uplevel 1 [list ::namespace current]]
-
+
foreach {src dest} $pairs {
- set Msgs($locale,$ns,$src) $dest
+ dict set Msgs $locale $ns $src $dest
}
-
+
return $length
}
@@ -344,7 +352,7 @@ proc msgcat::mcmset {locale pairs } {
# This routine is called by msgcat::mc if a translation cannot
# be found for a string. This routine is intended to be replaced
# by an application specific routine for error reporting
-# purposes. The default behavior is to return the source string.
+# purposes. The default behavior is to return the source string.
# If additional args are specified, the format command will be used
# to work them into the traslated string.
#
@@ -358,7 +366,7 @@ proc msgcat::mcmset {locale pairs } {
proc msgcat::mcunknown {locale src args} {
if {[llength $args]} {
- return [uplevel 1 [linsert $args 0 ::format $src]]
+ return [format $src {*}$args]
} else {
return $src
}
@@ -366,7 +374,7 @@ proc msgcat::mcunknown {locale src args} {
# msgcat::mcmax --
#
-# Calculates the maximun length of the translated strings of the given
+# Calculates the maximum length of the translated strings of the given
# list.
#
# Arguments:
@@ -381,7 +389,7 @@ proc msgcat::mcmax {args} {
set translated [uplevel 1 [list [namespace origin mc] $string]]
set len [string length $translated]
if {$len>$max} {
- set max $len
+ set max $len
}
}
return $max
@@ -418,13 +426,16 @@ proc msgcat::ConvertLocale {value} {
# Initialize the default locale
proc msgcat::Init {} {
+ global env tcl_platform
+
#
# set default locale, try to get from environment
#
foreach varName {LC_ALL LC_MESSAGES LANG} {
- if {[info exists ::env($varName)]
- && ![string equal "" $::env($varName)]} {
- if {![catch {mclocale [ConvertLocale $::env($varName)]}]} {
+ if {[info exists env($varName)] && ("" ne $env($varName))} {
+ if {![catch {
+ mclocale [ConvertLocale $env($varName)]
+ }]} {
return
}
}
@@ -432,11 +443,10 @@ proc msgcat::Init {} {
#
# On Darwin, fallback to current CFLocale identifier if available.
#
- if {[string equal $::tcl_platform(os) Darwin]
- && [string equal $::tcl_platform(platform) unix]
- && [info exists ::tcl::mac::locale]
- && ![string equal $::tcl::mac::locale ""]} {
- if {![catch {mclocale [ConvertLocale $::tcl::mac::locale]}]} {
+ if {[info exists ::tcl::mac::locale] && $::tcl::mac::locale ne ""} {
+ if {![catch {
+ mclocale [ConvertLocale $::tcl::mac::locale]
+ }]} {
return
}
}
@@ -444,17 +454,19 @@ proc msgcat::Init {} {
# The rest of this routine is special processing for Windows;
# all other platforms, get out now.
#
- if { ![string equal $::tcl_platform(platform) windows] } {
+ if {$tcl_platform(platform) ne "windows"} {
mclocale C
return
}
#
# On Windows, try to set locale depending on registry settings,
- # or fall back on locale of "C".
+ # or fall back on locale of "C".
#
- set key {HKEY_CURRENT_USER\Control Panel\International}
- if {[catch {package require registry}] \
- || [catch {registry get $key "locale"} locale]} {
+ if {[catch {
+ package require registry
+ set key {HKEY_CURRENT_USER\Control Panel\International}
+ set locale [registry get $key "locale"]
+ }]} {
mclocale C
return
}
@@ -470,7 +482,9 @@ proc msgcat::Init {} {
variable WinRegToISO639
set locale [string tolower $locale]
while {[string length $locale]} {
- if {![catch {mclocale [ConvertLocale $WinRegToISO639($locale)]}]} {
+ if {![catch {
+ mclocale [ConvertLocale [dict get $WinRegToISO639 $locale]]
+ }]} {
return
}
set locale [string range $locale 1 end]
diff --git a/library/msgcat/pkgIndex.tcl b/library/msgcat/pkgIndex.tcl
index 5888ddb..17ad5db 100644
--- a/library/msgcat/pkgIndex.tcl
+++ b/library/msgcat/pkgIndex.tcl
@@ -1,2 +1,2 @@
-if {![package vsatisfies [package provide Tcl] 8.2]} {return}
-package ifneeded msgcat 1.3.4 [list source [file join $dir msgcat.tcl]]
+if {![package vsatisfies [package provide Tcl] 8.5]} {return}
+package ifneeded msgcat 1.4.4 [list source [file join $dir msgcat.tcl]]
diff --git a/library/msgs/af.msg b/library/msgs/af.msg
new file mode 100755
index 0000000..0892615
--- /dev/null
+++ b/library/msgs/af.msg
@@ -0,0 +1,49 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset af DAYS_OF_WEEK_ABBREV [list \
+ "So"\
+ "Ma"\
+ "Di"\
+ "Wo"\
+ "Do"\
+ "Vr"\
+ "Sa"]
+ ::msgcat::mcset af DAYS_OF_WEEK_FULL [list \
+ "Sondag"\
+ "Maandag"\
+ "Dinsdag"\
+ "Woensdag"\
+ "Donderdag"\
+ "Vrydag"\
+ "Saterdag"]
+ ::msgcat::mcset af MONTHS_ABBREV [list \
+ "Jan"\
+ "Feb"\
+ "Mar"\
+ "Apr"\
+ "Mei"\
+ "Jun"\
+ "Jul"\
+ "Aug"\
+ "Sep"\
+ "Okt"\
+ "Nov"\
+ "Des"\
+ ""]
+ ::msgcat::mcset af MONTHS_FULL [list \
+ "Januarie"\
+ "Februarie"\
+ "Maart"\
+ "April"\
+ "Mei"\
+ "Junie"\
+ "Julie"\
+ "Augustus"\
+ "September"\
+ "Oktober"\
+ "November"\
+ "Desember"\
+ ""]
+ ::msgcat::mcset af AM "VM"
+ ::msgcat::mcset af PM "NM"
+}
diff --git a/library/msgs/af_za.msg b/library/msgs/af_za.msg
new file mode 100755
index 0000000..fef48ad
--- /dev/null
+++ b/library/msgs/af_za.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset af_ZA DATE_FORMAT "%d %B %Y"
+ ::msgcat::mcset af_ZA TIME_FORMAT_12 "%l:%M:%S %P"
+ ::msgcat::mcset af_ZA DATE_TIME_FORMAT "%d %B %Y %l:%M:%S %P %z"
+}
diff --git a/library/msgs/ar.msg b/library/msgs/ar.msg
new file mode 100755
index 0000000..257157f
--- /dev/null
+++ b/library/msgs/ar.msg
@@ -0,0 +1,54 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset ar DAYS_OF_WEEK_ABBREV [list \
+ "\u062d"\
+ "\u0646"\
+ "\u062b"\
+ "\u0631"\
+ "\u062e"\
+ "\u062c"\
+ "\u0633"]
+ ::msgcat::mcset ar DAYS_OF_WEEK_FULL [list \
+ "\u0627\u0644\u0623\u062d\u062f"\
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646"\
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621"\
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621"\
+ "\u0627\u0644\u062e\u0645\u064a\u0633"\
+ "\u0627\u0644\u062c\u0645\u0639\u0629"\
+ "\u0627\u0644\u0633\u0628\u062a"]
+ ::msgcat::mcset ar MONTHS_ABBREV [list \
+ "\u064a\u0646\u0627"\
+ "\u0641\u0628\u0631"\
+ "\u0645\u0627\u0631"\
+ "\u0623\u0628\u0631"\
+ "\u0645\u0627\u064a"\
+ "\u064a\u0648\u0646"\
+ "\u064a\u0648\u0644"\
+ "\u0623\u063a\u0633"\
+ "\u0633\u0628\u062a"\
+ "\u0623\u0643\u062a"\
+ "\u0646\u0648\u0641"\
+ "\u062f\u064a\u0633"\
+ ""]
+ ::msgcat::mcset ar MONTHS_FULL [list \
+ "\u064a\u0646\u0627\u064a\u0631"\
+ "\u0641\u0628\u0631\u0627\u064a\u0631"\
+ "\u0645\u0627\u0631\u0633"\
+ "\u0623\u0628\u0631\u064a\u0644"\
+ "\u0645\u0627\u064a\u0648"\
+ "\u064a\u0648\u0646\u064a\u0648"\
+ "\u064a\u0648\u0644\u064a\u0648"\
+ "\u0623\u063a\u0633\u0637\u0633"\
+ "\u0633\u0628\u062a\u0645\u0628\u0631"\
+ "\u0623\u0643\u062a\u0648\u0628\u0631"\
+ "\u0646\u0648\u0641\u0645\u0628\u0631"\
+ "\u062f\u064a\u0633\u0645\u0628\u0631"\
+ ""]
+ ::msgcat::mcset ar BCE "\u0642.\u0645"
+ ::msgcat::mcset ar CE "\u0645"
+ ::msgcat::mcset ar AM "\u0635"
+ ::msgcat::mcset ar PM "\u0645"
+ ::msgcat::mcset ar DATE_FORMAT "%d/%m/%Y"
+ ::msgcat::mcset ar TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset ar DATE_TIME_FORMAT "%d/%m/%Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/ar_in.msg b/library/msgs/ar_in.msg
new file mode 100755
index 0000000..185e49c
--- /dev/null
+++ b/library/msgs/ar_in.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset ar_IN DATE_FORMAT "%A %d %B %Y"
+ ::msgcat::mcset ar_IN TIME_FORMAT_12 "%I:%M:%S %z"
+ ::msgcat::mcset ar_IN DATE_TIME_FORMAT "%A %d %B %Y %I:%M:%S %z %z"
+}
diff --git a/library/msgs/ar_jo.msg b/library/msgs/ar_jo.msg
new file mode 100755
index 0000000..0f5e269
--- /dev/null
+++ b/library/msgs/ar_jo.msg
@@ -0,0 +1,39 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset ar_JO DAYS_OF_WEEK_ABBREV [list \
+ "\u0627\u0644\u0623\u062d\u062f"\
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646"\
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621"\
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621"\
+ "\u0627\u0644\u062e\u0645\u064a\u0633"\
+ "\u0627\u0644\u062c\u0645\u0639\u0629"\
+ "\u0627\u0644\u0633\u0628\u062a"]
+ ::msgcat::mcset ar_JO MONTHS_ABBREV [list \
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\
+ "\u0634\u0628\u0627\u0637"\
+ "\u0622\u0630\u0627\u0631"\
+ "\u0646\u064a\u0633\u0627\u0646"\
+ "\u0646\u0648\u0627\u0631"\
+ "\u062d\u0632\u064a\u0631\u0627\u0646"\
+ "\u062a\u0645\u0648\u0632"\
+ "\u0622\u0628"\
+ "\u0623\u064a\u0644\u0648\u0644"\
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644"\
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"\
+ ""]
+ ::msgcat::mcset ar_JO MONTHS_FULL [list \
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\
+ "\u0634\u0628\u0627\u0637"\
+ "\u0622\u0630\u0627\u0631"\
+ "\u0646\u064a\u0633\u0627\u0646"\
+ "\u0646\u0648\u0627\u0631"\
+ "\u062d\u0632\u064a\u0631\u0627\u0646"\
+ "\u062a\u0645\u0648\u0632"\
+ "\u0622\u0628"\
+ "\u0623\u064a\u0644\u0648\u0644"\
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644"\
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"\
+ ""]
+}
diff --git a/library/msgs/ar_lb.msg b/library/msgs/ar_lb.msg
new file mode 100755
index 0000000..e62acd3
--- /dev/null
+++ b/library/msgs/ar_lb.msg
@@ -0,0 +1,39 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset ar_LB DAYS_OF_WEEK_ABBREV [list \
+ "\u0627\u0644\u0623\u062d\u062f"\
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646"\
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621"\
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621"\
+ "\u0627\u0644\u062e\u0645\u064a\u0633"\
+ "\u0627\u0644\u062c\u0645\u0639\u0629"\
+ "\u0627\u0644\u0633\u0628\u062a"]
+ ::msgcat::mcset ar_LB MONTHS_ABBREV [list \
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\
+ "\u0634\u0628\u0627\u0637"\
+ "\u0622\u0630\u0627\u0631"\
+ "\u0646\u064a\u0633\u0627\u0646"\
+ "\u0646\u0648\u0627\u0631"\
+ "\u062d\u0632\u064a\u0631\u0627\u0646"\
+ "\u062a\u0645\u0648\u0632"\
+ "\u0622\u0628"\
+ "\u0623\u064a\u0644\u0648\u0644"\
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644"\
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"\
+ ""]
+ ::msgcat::mcset ar_LB MONTHS_FULL [list \
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\
+ "\u0634\u0628\u0627\u0637"\
+ "\u0622\u0630\u0627\u0631"\
+ "\u0646\u064a\u0633\u0627\u0646"\
+ "\u0646\u0648\u0627\u0631"\
+ "\u062d\u0632\u064a\u0631\u0627\u0646"\
+ "\u062a\u0645\u0648\u0632"\
+ "\u0622\u0628"\
+ "\u0623\u064a\u0644\u0648\u0644"\
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644"\
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"\
+ ""]
+}
diff --git a/library/msgs/ar_sy.msg b/library/msgs/ar_sy.msg
new file mode 100755
index 0000000..d5e1c87
--- /dev/null
+++ b/library/msgs/ar_sy.msg
@@ -0,0 +1,39 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset ar_SY DAYS_OF_WEEK_ABBREV [list \
+ "\u0627\u0644\u0623\u062d\u062f"\
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646"\
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621"\
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621"\
+ "\u0627\u0644\u062e\u0645\u064a\u0633"\
+ "\u0627\u0644\u062c\u0645\u0639\u0629"\
+ "\u0627\u0644\u0633\u0628\u062a"]
+ ::msgcat::mcset ar_SY MONTHS_ABBREV [list \
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\
+ "\u0634\u0628\u0627\u0637"\
+ "\u0622\u0630\u0627\u0631"\
+ "\u0646\u064a\u0633\u0627\u0646"\
+ "\u0646\u0648\u0627\u0631"\
+ "\u062d\u0632\u064a\u0631\u0627\u0646"\
+ "\u062a\u0645\u0648\u0632"\
+ "\u0622\u0628"\
+ "\u0623\u064a\u0644\u0648\u0644"\
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644"\
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"\
+ ""]
+ ::msgcat::mcset ar_SY MONTHS_FULL [list \
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\
+ "\u0634\u0628\u0627\u0637"\
+ "\u0622\u0630\u0627\u0631"\
+ "\u0646\u064a\u0633\u0627\u0646"\
+ "\u0646\u0648\u0627\u0631\u0627\u0646"\
+ "\u062d\u0632\u064a\u0631"\
+ "\u062a\u0645\u0648\u0632"\
+ "\u0622\u0628"\
+ "\u0623\u064a\u0644\u0648\u0644"\
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644"\
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"\
+ ""]
+}
diff --git a/library/msgs/be.msg b/library/msgs/be.msg
new file mode 100755
index 0000000..379a1d7
--- /dev/null
+++ b/library/msgs/be.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset be DAYS_OF_WEEK_ABBREV [list \
+ "\u043d\u0434"\
+ "\u043f\u043d"\
+ "\u0430\u0442"\
+ "\u0441\u0440"\
+ "\u0447\u0446"\
+ "\u043f\u0442"\
+ "\u0441\u0431"]
+ ::msgcat::mcset be DAYS_OF_WEEK_FULL [list \
+ "\u043d\u044f\u0434\u0437\u0435\u043b\u044f"\
+ "\u043f\u0430\u043d\u044f\u0434\u0437\u0435\u043b\u0430\u043a"\
+ "\u0430\u045e\u0442\u043e\u0440\u0430\u043a"\
+ "\u0441\u0435\u0440\u0430\u0434\u0430"\
+ "\u0447\u0430\u0446\u0432\u0435\u0440"\
+ "\u043f\u044f\u0442\u043d\u0456\u0446\u0430"\
+ "\u0441\u0443\u0431\u043e\u0442\u0430"]
+ ::msgcat::mcset be MONTHS_ABBREV [list \
+ "\u0441\u0442\u0434"\
+ "\u043b\u044e\u0442"\
+ "\u0441\u043a\u0432"\
+ "\u043a\u0440\u0441"\
+ "\u043c\u0430\u0439"\
+ "\u0447\u0440\u0432"\
+ "\u043b\u043f\u043d"\
+ "\u0436\u043d\u0432"\
+ "\u0432\u0440\u0441"\
+ "\u043a\u0441\u0442"\
+ "\u043b\u0441\u0442"\
+ "\u0441\u043d\u0436"\
+ ""]
+ ::msgcat::mcset be MONTHS_FULL [list \
+ "\u0441\u0442\u0443\u0434\u0437\u0435\u043d\u044f"\
+ "\u043b\u044e\u0442\u0430\u0433\u0430"\
+ "\u0441\u0430\u043a\u0430\u0432\u0456\u043a\u0430"\
+ "\u043a\u0440\u0430\u0441\u0430\u0432\u0456\u043a\u0430"\
+ "\u043c\u0430\u044f"\
+ "\u0447\u0440\u0432\u0435\u043d\u044f"\
+ "\u043b\u0456\u043f\u0435\u043d\u044f"\
+ "\u0436\u043d\u0456\u045e\u043d\u044f"\
+ "\u0432\u0435\u0440\u0430\u0441\u043d\u044f"\
+ "\u043a\u0430\u0441\u0442\u0440\u044b\u0447\u043d\u0456\u043a\u0430"\
+ "\u043b\u0438\u0441\u0442\u0430\u043f\u0430\u0434\u0430"\
+ "\u0441\u043d\u0435\u0436\u043d\u044f"\
+ ""]
+ ::msgcat::mcset be BCE "\u0434\u0430 \u043d.\u0435."
+ ::msgcat::mcset be CE "\u043d.\u0435."
+ ::msgcat::mcset be DATE_FORMAT "%e.%m.%Y"
+ ::msgcat::mcset be TIME_FORMAT "%k.%M.%S"
+ ::msgcat::mcset be DATE_TIME_FORMAT "%e.%m.%Y %k.%M.%S %z"
+}
diff --git a/library/msgs/bg.msg b/library/msgs/bg.msg
new file mode 100755
index 0000000..ff17759
--- /dev/null
+++ b/library/msgs/bg.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset bg DAYS_OF_WEEK_ABBREV [list \
+ "\u041d\u0434"\
+ "\u041f\u043d"\
+ "\u0412\u0442"\
+ "\u0421\u0440"\
+ "\u0427\u0442"\
+ "\u041f\u0442"\
+ "\u0421\u0431"]
+ ::msgcat::mcset bg DAYS_OF_WEEK_FULL [list \
+ "\u041d\u0435\u0434\u0435\u043b\u044f"\
+ "\u041f\u043e\u043d\u0435\u0434\u0435\u043b\u043d\u0438\u043a"\
+ "\u0412\u0442\u043e\u0440\u043d\u0438\u043a"\
+ "\u0421\u0440\u044f\u0434\u0430"\
+ "\u0427\u0435\u0442\u0432\u044a\u0440\u0442\u044a\u043a"\
+ "\u041f\u0435\u0442\u044a\u043a"\
+ "\u0421\u044a\u0431\u043e\u0442\u0430"]
+ ::msgcat::mcset bg MONTHS_ABBREV [list \
+ "I"\
+ "II"\
+ "III"\
+ "IV"\
+ "V"\
+ "VI"\
+ "VII"\
+ "VIII"\
+ "IX"\
+ "X"\
+ "XI"\
+ "XII"\
+ ""]
+ ::msgcat::mcset bg MONTHS_FULL [list \
+ "\u042f\u043d\u0443\u0430\u0440\u0438"\
+ "\u0424\u0435\u0432\u0440\u0443\u0430\u0440\u0438"\
+ "\u041c\u0430\u0440\u0442"\
+ "\u0410\u043f\u0440\u0438\u043b"\
+ "\u041c\u0430\u0439"\
+ "\u042e\u043d\u0438"\
+ "\u042e\u043b\u0438"\
+ "\u0410\u0432\u0433\u0443\u0441\u0442"\
+ "\u0421\u0435\u043f\u0442\u0435\u043c\u0432\u0440\u0438"\
+ "\u041e\u043a\u0442\u043e\u043c\u0432\u0440\u0438"\
+ "\u041d\u043e\u0435\u043c\u0432\u0440\u0438"\
+ "\u0414\u0435\u043a\u0435\u043c\u0432\u0440\u0438"\
+ ""]
+ ::msgcat::mcset bg BCE "\u043f\u0440.\u043d.\u0435."
+ ::msgcat::mcset bg CE "\u043d.\u0435."
+ ::msgcat::mcset bg DATE_FORMAT "%Y-%m-%e"
+ ::msgcat::mcset bg TIME_FORMAT "%k:%M:%S"
+ ::msgcat::mcset bg DATE_TIME_FORMAT "%Y-%m-%e %k:%M:%S %z"
+}
diff --git a/library/msgs/bn.msg b/library/msgs/bn.msg
new file mode 100755
index 0000000..664b9d8
--- /dev/null
+++ b/library/msgs/bn.msg
@@ -0,0 +1,49 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset bn DAYS_OF_WEEK_ABBREV [list \
+ "\u09b0\u09ac\u09bf"\
+ "\u09b8\u09cb\u09ae"\
+ "\u09ae\u0999\u0997\u09b2"\
+ "\u09ac\u09c1\u09a7"\
+ "\u09ac\u09c3\u09b9\u09b8\u09cd\u09aa\u09a4\u09bf"\
+ "\u09b6\u09c1\u0995\u09cd\u09b0"\
+ "\u09b6\u09a8\u09bf"]
+ ::msgcat::mcset bn DAYS_OF_WEEK_FULL [list \
+ "\u09b0\u09ac\u09bf\u09ac\u09be\u09b0"\
+ "\u09b8\u09cb\u09ae\u09ac\u09be\u09b0"\
+ "\u09ae\u0999\u0997\u09b2\u09ac\u09be\u09b0"\
+ "\u09ac\u09c1\u09a7\u09ac\u09be\u09b0"\
+ "\u09ac\u09c3\u09b9\u09b8\u09cd\u09aa\u09a4\u09bf\u09ac\u09be\u09b0"\
+ "\u09b6\u09c1\u0995\u09cd\u09b0\u09ac\u09be\u09b0"\
+ "\u09b6\u09a8\u09bf\u09ac\u09be\u09b0"]
+ ::msgcat::mcset bn MONTHS_ABBREV [list \
+ "\u099c\u09be\u09a8\u09c1\u09df\u09be\u09b0\u09c0"\
+ "\u09ab\u09c7\u09ac\u09cd\u09b0\u09c1\u09df\u09be\u09b0\u09c0"\
+ "\u09ae\u09be\u09b0\u09cd\u099a"\
+ "\u098f\u09aa\u09cd\u09b0\u09bf\u09b2"\
+ "\u09ae\u09c7"\
+ "\u099c\u09c1\u09a8"\
+ "\u099c\u09c1\u09b2\u09be\u0987"\
+ "\u0986\u0997\u09b8\u09cd\u099f"\
+ "\u09b8\u09c7\u09aa\u09cd\u099f\u09c7\u09ae\u09cd\u09ac\u09b0"\
+ "\u0985\u0995\u09cd\u099f\u09cb\u09ac\u09b0"\
+ "\u09a8\u09ad\u09c7\u09ae\u09cd\u09ac\u09b0"\
+ "\u09a1\u09bf\u09b8\u09c7\u09ae\u09cd\u09ac\u09b0"\
+ ""]
+ ::msgcat::mcset bn MONTHS_FULL [list \
+ "\u099c\u09be\u09a8\u09c1\u09df\u09be\u09b0\u09c0"\
+ "\u09ab\u09c7\u09ac\u09cd\u09b0\u09c1\u09df\u09be\u09b0\u09c0"\
+ "\u09ae\u09be\u09b0\u09cd\u099a"\
+ "\u098f\u09aa\u09cd\u09b0\u09bf\u09b2"\
+ "\u09ae\u09c7"\
+ "\u099c\u09c1\u09a8"\
+ "\u099c\u09c1\u09b2\u09be\u0987"\
+ "\u0986\u0997\u09b8\u09cd\u099f"\
+ "\u09b8\u09c7\u09aa\u09cd\u099f\u09c7\u09ae\u09cd\u09ac\u09b0"\
+ "\u0985\u0995\u09cd\u099f\u09cb\u09ac\u09b0"\
+ "\u09a8\u09ad\u09c7\u09ae\u09cd\u09ac\u09b0"\
+ "\u09a1\u09bf\u09b8\u09c7\u09ae\u09cd\u09ac\u09b0"\
+ ""]
+ ::msgcat::mcset bn AM "\u09aa\u09c2\u09b0\u09cd\u09ac\u09be\u09b9\u09cd\u09a3"
+ ::msgcat::mcset bn PM "\u0985\u09aa\u09b0\u09be\u09b9\u09cd\u09a3"
+}
diff --git a/library/msgs/bn_in.msg b/library/msgs/bn_in.msg
new file mode 100755
index 0000000..28c000f
--- /dev/null
+++ b/library/msgs/bn_in.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset bn_IN DATE_FORMAT "%A %d %b %Y"
+ ::msgcat::mcset bn_IN TIME_FORMAT_12 "%I:%M:%S %z"
+ ::msgcat::mcset bn_IN DATE_TIME_FORMAT "%A %d %b %Y %I:%M:%S %z %z"
+}
diff --git a/library/msgs/ca.msg b/library/msgs/ca.msg
new file mode 100755
index 0000000..36c9772
--- /dev/null
+++ b/library/msgs/ca.msg
@@ -0,0 +1,50 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset ca DAYS_OF_WEEK_ABBREV [list \
+ "dg."\
+ "dl."\
+ "dt."\
+ "dc."\
+ "dj."\
+ "dv."\
+ "ds."]
+ ::msgcat::mcset ca DAYS_OF_WEEK_FULL [list \
+ "diumenge"\
+ "dilluns"\
+ "dimarts"\
+ "dimecres"\
+ "dijous"\
+ "divendres"\
+ "dissabte"]
+ ::msgcat::mcset ca MONTHS_ABBREV [list \
+ "gen."\
+ "feb."\
+ "mar\u00e7"\
+ "abr."\
+ "maig"\
+ "juny"\
+ "jul."\
+ "ag."\
+ "set."\
+ "oct."\
+ "nov."\
+ "des."\
+ ""]
+ ::msgcat::mcset ca MONTHS_FULL [list \
+ "gener"\
+ "febrer"\
+ "mar\u00e7"\
+ "abril"\
+ "maig"\
+ "juny"\
+ "juliol"\
+ "agost"\
+ "setembre"\
+ "octubre"\
+ "novembre"\
+ "desembre"\
+ ""]
+ ::msgcat::mcset ca DATE_FORMAT "%d/%m/%Y"
+ ::msgcat::mcset ca TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset ca DATE_TIME_FORMAT "%d/%m/%Y %H:%M:%S %z"
+}
diff --git a/library/msgs/cs.msg b/library/msgs/cs.msg
new file mode 100755
index 0000000..8db8bdd
--- /dev/null
+++ b/library/msgs/cs.msg
@@ -0,0 +1,54 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset cs DAYS_OF_WEEK_ABBREV [list \
+ "Ne"\
+ "Po"\
+ "\u00dat"\
+ "St"\
+ "\u010ct"\
+ "P\u00e1"\
+ "So"]
+ ::msgcat::mcset cs DAYS_OF_WEEK_FULL [list \
+ "Ned\u011ble"\
+ "Pond\u011bl\u00ed"\
+ "\u00dater\u00fd"\
+ "St\u0159eda"\
+ "\u010ctvrtek"\
+ "P\u00e1tek"\
+ "Sobota"]
+ ::msgcat::mcset cs MONTHS_ABBREV [list \
+ "I"\
+ "II"\
+ "III"\
+ "IV"\
+ "V"\
+ "VI"\
+ "VII"\
+ "VIII"\
+ "IX"\
+ "X"\
+ "XI"\
+ "XII"\
+ ""]
+ ::msgcat::mcset cs MONTHS_FULL [list \
+ "leden"\
+ "\u00fanor"\
+ "b\u0159ezen"\
+ "duben"\
+ "kv\u011bten"\
+ "\u010derven"\
+ "\u010dervenec"\
+ "srpen"\
+ "z\u00e1\u0159\u00ed"\
+ "\u0159\u00edjen"\
+ "listopad"\
+ "prosinec"\
+ ""]
+ ::msgcat::mcset cs BCE "p\u0159.Kr."
+ ::msgcat::mcset cs CE "po Kr."
+ ::msgcat::mcset cs AM "dop."
+ ::msgcat::mcset cs PM "odp."
+ ::msgcat::mcset cs DATE_FORMAT "%e.%m.%Y"
+ ::msgcat::mcset cs TIME_FORMAT "%k:%M:%S"
+ ::msgcat::mcset cs DATE_TIME_FORMAT "%e.%m.%Y %k:%M:%S %z"
+}
diff --git a/library/msgs/da.msg b/library/msgs/da.msg
new file mode 100755
index 0000000..e4fec7f
--- /dev/null
+++ b/library/msgs/da.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset da DAYS_OF_WEEK_ABBREV [list \
+ "s\u00f8"\
+ "ma"\
+ "ti"\
+ "on"\
+ "to"\
+ "fr"\
+ "l\u00f8"]
+ ::msgcat::mcset da DAYS_OF_WEEK_FULL [list \
+ "s\u00f8ndag"\
+ "mandag"\
+ "tirsdag"\
+ "onsdag"\
+ "torsdag"\
+ "fredag"\
+ "l\u00f8rdag"]
+ ::msgcat::mcset da MONTHS_ABBREV [list \
+ "jan"\
+ "feb"\
+ "mar"\
+ "apr"\
+ "maj"\
+ "jun"\
+ "jul"\
+ "aug"\
+ "sep"\
+ "okt"\
+ "nov"\
+ "dec"\
+ ""]
+ ::msgcat::mcset da MONTHS_FULL [list \
+ "januar"\
+ "februar"\
+ "marts"\
+ "april"\
+ "maj"\
+ "juni"\
+ "juli"\
+ "august"\
+ "september"\
+ "oktober"\
+ "november"\
+ "december"\
+ ""]
+ ::msgcat::mcset da BCE "f.Kr."
+ ::msgcat::mcset da CE "e.Kr."
+ ::msgcat::mcset da DATE_FORMAT "%d-%m-%Y"
+ ::msgcat::mcset da TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset da DATE_TIME_FORMAT "%d-%m-%Y %H:%M:%S %z"
+}
diff --git a/library/msgs/de.msg b/library/msgs/de.msg
new file mode 100755
index 0000000..9eb3145
--- /dev/null
+++ b/library/msgs/de.msg
@@ -0,0 +1,54 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset de DAYS_OF_WEEK_ABBREV [list \
+ "So"\
+ "Mo"\
+ "Di"\
+ "Mi"\
+ "Do"\
+ "Fr"\
+ "Sa"]
+ ::msgcat::mcset de DAYS_OF_WEEK_FULL [list \
+ "Sonntag"\
+ "Montag"\
+ "Dienstag"\
+ "Mittwoch"\
+ "Donnerstag"\
+ "Freitag"\
+ "Samstag"]
+ ::msgcat::mcset de MONTHS_ABBREV [list \
+ "Jan"\
+ "Feb"\
+ "Mrz"\
+ "Apr"\
+ "Mai"\
+ "Jun"\
+ "Jul"\
+ "Aug"\
+ "Sep"\
+ "Okt"\
+ "Nov"\
+ "Dez"\
+ ""]
+ ::msgcat::mcset de MONTHS_FULL [list \
+ "Januar"\
+ "Februar"\
+ "M\u00e4rz"\
+ "April"\
+ "Mai"\
+ "Juni"\
+ "Juli"\
+ "August"\
+ "September"\
+ "Oktober"\
+ "November"\
+ "Dezember"\
+ ""]
+ ::msgcat::mcset de BCE "v. Chr."
+ ::msgcat::mcset de CE "n. Chr."
+ ::msgcat::mcset de AM "vorm."
+ ::msgcat::mcset de PM "nachm."
+ ::msgcat::mcset de DATE_FORMAT "%d.%m.%Y"
+ ::msgcat::mcset de TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset de DATE_TIME_FORMAT "%d.%m.%Y %H:%M:%S %z"
+}
diff --git a/library/msgs/de_at.msg b/library/msgs/de_at.msg
new file mode 100755
index 0000000..61bc266
--- /dev/null
+++ b/library/msgs/de_at.msg
@@ -0,0 +1,35 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset de_AT MONTHS_ABBREV [list \
+ "J\u00e4n"\
+ "Feb"\
+ "M\u00e4r"\
+ "Apr"\
+ "Mai"\
+ "Jun"\
+ "Jul"\
+ "Aug"\
+ "Sep"\
+ "Okt"\
+ "Nov"\
+ "Dez"\
+ ""]
+ ::msgcat::mcset de_AT MONTHS_FULL [list \
+ "J\u00e4nner"\
+ "Februar"\
+ "M\u00e4rz"\
+ "April"\
+ "Mai"\
+ "Juni"\
+ "Juli"\
+ "August"\
+ "September"\
+ "Oktober"\
+ "November"\
+ "Dezember"\
+ ""]
+ ::msgcat::mcset de_AT DATE_FORMAT "%Y-%m-%d"
+ ::msgcat::mcset de_AT TIME_FORMAT "%T"
+ ::msgcat::mcset de_AT TIME_FORMAT_12 "%T"
+ ::msgcat::mcset de_AT DATE_TIME_FORMAT "%a %d %b %Y %T %z"
+}
diff --git a/library/msgs/de_be.msg b/library/msgs/de_be.msg
new file mode 100755
index 0000000..3614763
--- /dev/null
+++ b/library/msgs/de_be.msg
@@ -0,0 +1,53 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset de_BE DAYS_OF_WEEK_ABBREV [list \
+ "Son"\
+ "Mon"\
+ "Die"\
+ "Mit"\
+ "Don"\
+ "Fre"\
+ "Sam"]
+ ::msgcat::mcset de_BE DAYS_OF_WEEK_FULL [list \
+ "Sonntag"\
+ "Montag"\
+ "Dienstag"\
+ "Mittwoch"\
+ "Donnerstag"\
+ "Freitag"\
+ "Samstag"]
+ ::msgcat::mcset de_BE MONTHS_ABBREV [list \
+ "Jan"\
+ "Feb"\
+ "M\u00e4r"\
+ "Apr"\
+ "Mai"\
+ "Jun"\
+ "Jul"\
+ "Aug"\
+ "Sep"\
+ "Okt"\
+ "Nov"\
+ "Dez"\
+ ""]
+ ::msgcat::mcset de_BE MONTHS_FULL [list \
+ "Januar"\
+ "Februar"\
+ "M\u00e4rz"\
+ "April"\
+ "Mai"\
+ "Juni"\
+ "Juli"\
+ "August"\
+ "September"\
+ "Oktober"\
+ "November"\
+ "Dezember"\
+ ""]
+ ::msgcat::mcset de_BE AM "vorm"
+ ::msgcat::mcset de_BE PM "nachm"
+ ::msgcat::mcset de_BE DATE_FORMAT "%Y-%m-%d"
+ ::msgcat::mcset de_BE TIME_FORMAT "%T"
+ ::msgcat::mcset de_BE TIME_FORMAT_12 "%T"
+ ::msgcat::mcset de_BE DATE_TIME_FORMAT "%a %d %b %Y %T %z"
+}
diff --git a/library/msgs/el.msg b/library/msgs/el.msg
new file mode 100755
index 0000000..ac19f62
--- /dev/null
+++ b/library/msgs/el.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset el DAYS_OF_WEEK_ABBREV [list \
+ "\u039a\u03c5\u03c1"\
+ "\u0394\u03b5\u03c5"\
+ "\u03a4\u03c1\u03b9"\
+ "\u03a4\u03b5\u03c4"\
+ "\u03a0\u03b5\u03bc"\
+ "\u03a0\u03b1\u03c1"\
+ "\u03a3\u03b1\u03b2"]
+ ::msgcat::mcset el DAYS_OF_WEEK_FULL [list \
+ "\u039a\u03c5\u03c1\u03b9\u03b1\u03ba\u03ae"\
+ "\u0394\u03b5\u03c5\u03c4\u03ad\u03c1\u03b1"\
+ "\u03a4\u03c1\u03af\u03c4\u03b7"\
+ "\u03a4\u03b5\u03c4\u03ac\u03c1\u03c4\u03b7"\
+ "\u03a0\u03ad\u03bc\u03c0\u03c4\u03b7"\
+ "\u03a0\u03b1\u03c1\u03b1\u03c3\u03ba\u03b5\u03c5\u03ae"\
+ "\u03a3\u03ac\u03b2\u03b2\u03b1\u03c4\u03bf"]
+ ::msgcat::mcset el MONTHS_ABBREV [list \
+ "\u0399\u03b1\u03bd"\
+ "\u03a6\u03b5\u03b2"\
+ "\u039c\u03b1\u03c1"\
+ "\u0391\u03c0\u03c1"\
+ "\u039c\u03b1\u03ca"\
+ "\u0399\u03bf\u03c5\u03bd"\
+ "\u0399\u03bf\u03c5\u03bb"\
+ "\u0391\u03c5\u03b3"\
+ "\u03a3\u03b5\u03c0"\
+ "\u039f\u03ba\u03c4"\
+ "\u039d\u03bf\u03b5"\
+ "\u0394\u03b5\u03ba"\
+ ""]
+ ::msgcat::mcset el MONTHS_FULL [list \
+ "\u0399\u03b1\u03bd\u03bf\u03c5\u03ac\u03c1\u03b9\u03bf\u03c2"\
+ "\u03a6\u03b5\u03b2\u03c1\u03bf\u03c5\u03ac\u03c1\u03b9\u03bf\u03c2"\
+ "\u039c\u03ac\u03c1\u03c4\u03b9\u03bf\u03c2"\
+ "\u0391\u03c0\u03c1\u03af\u03bb\u03b9\u03bf\u03c2"\
+ "\u039c\u03ac\u03ca\u03bf\u03c2"\
+ "\u0399\u03bf\u03cd\u03bd\u03b9\u03bf\u03c2"\
+ "\u0399\u03bf\u03cd\u03bb\u03b9\u03bf\u03c2"\
+ "\u0391\u03cd\u03b3\u03bf\u03c5\u03c3\u03c4\u03bf\u03c2"\
+ "\u03a3\u03b5\u03c0\u03c4\u03ad\u03bc\u03b2\u03c1\u03b9\u03bf\u03c2"\
+ "\u039f\u03ba\u03c4\u03ce\u03b2\u03c1\u03b9\u03bf\u03c2"\
+ "\u039d\u03bf\u03ad\u03bc\u03b2\u03c1\u03b9\u03bf\u03c2"\
+ "\u0394\u03b5\u03ba\u03ad\u03bc\u03b2\u03c1\u03b9\u03bf\u03c2"\
+ ""]
+ ::msgcat::mcset el AM "\u03c0\u03bc"
+ ::msgcat::mcset el PM "\u03bc\u03bc"
+ ::msgcat::mcset el DATE_FORMAT "%e/%m/%Y"
+ ::msgcat::mcset el TIME_FORMAT_12 "%l:%M:%S %P"
+ ::msgcat::mcset el DATE_TIME_FORMAT "%e/%m/%Y %l:%M:%S %P %z"
+}
diff --git a/library/msgs/en_au.msg b/library/msgs/en_au.msg
new file mode 100755
index 0000000..7f9870c
--- /dev/null
+++ b/library/msgs/en_au.msg
@@ -0,0 +1,7 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset en_AU DATE_FORMAT "%e/%m/%Y"
+ ::msgcat::mcset en_AU TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset en_AU TIME_FORMAT_12 "%I:%M:%S %P %z"
+ ::msgcat::mcset en_AU DATE_TIME_FORMAT "%e/%m/%Y %H:%M:%S %z"
+}
diff --git a/library/msgs/en_be.msg b/library/msgs/en_be.msg
new file mode 100755
index 0000000..5072986
--- /dev/null
+++ b/library/msgs/en_be.msg
@@ -0,0 +1,7 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset en_BE DATE_FORMAT "%d %b %Y"
+ ::msgcat::mcset en_BE TIME_FORMAT "%k:%M:%S"
+ ::msgcat::mcset en_BE TIME_FORMAT_12 "%k h %M min %S s %z"
+ ::msgcat::mcset en_BE DATE_TIME_FORMAT "%d %b %Y %k:%M:%S %z"
+}
diff --git a/library/msgs/en_bw.msg b/library/msgs/en_bw.msg
new file mode 100755
index 0000000..8fd20c7
--- /dev/null
+++ b/library/msgs/en_bw.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset en_BW DATE_FORMAT "%d %B %Y"
+ ::msgcat::mcset en_BW TIME_FORMAT_12 "%l:%M:%S %P"
+ ::msgcat::mcset en_BW DATE_TIME_FORMAT "%d %B %Y %l:%M:%S %P %z"
+}
diff --git a/library/msgs/en_ca.msg b/library/msgs/en_ca.msg
new file mode 100755
index 0000000..278efe7
--- /dev/null
+++ b/library/msgs/en_ca.msg
@@ -0,0 +1,7 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset en_CA DATE_FORMAT "%d/%m/%y"
+ ::msgcat::mcset en_CA TIME_FORMAT "%r"
+ ::msgcat::mcset en_CA TIME_FORMAT_12 "%I:%M:%S %p"
+ ::msgcat::mcset en_CA DATE_TIME_FORMAT "%a %d %b %Y %r %z"
+}
diff --git a/library/msgs/en_gb.msg b/library/msgs/en_gb.msg
new file mode 100755
index 0000000..5c61c43
--- /dev/null
+++ b/library/msgs/en_gb.msg
@@ -0,0 +1,7 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset en_GB DATE_FORMAT "%d/%m/%y"
+ ::msgcat::mcset en_GB TIME_FORMAT "%T"
+ ::msgcat::mcset en_GB TIME_FORMAT_12 "%T"
+ ::msgcat::mcset en_GB DATE_TIME_FORMAT "%a %d %b %Y %T %z"
+}
diff --git a/library/msgs/en_hk.msg b/library/msgs/en_hk.msg
new file mode 100755
index 0000000..8b33bc0
--- /dev/null
+++ b/library/msgs/en_hk.msg
@@ -0,0 +1,8 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset en_HK AM "AM"
+ ::msgcat::mcset en_HK PM "PM"
+ ::msgcat::mcset en_HK DATE_FORMAT "%B %e, %Y"
+ ::msgcat::mcset en_HK TIME_FORMAT_12 "%l:%M:%S %P"
+ ::msgcat::mcset en_HK DATE_TIME_FORMAT "%B %e, %Y %l:%M:%S %P %z"
+}
diff --git a/library/msgs/en_ie.msg b/library/msgs/en_ie.msg
new file mode 100755
index 0000000..ba621cf
--- /dev/null
+++ b/library/msgs/en_ie.msg
@@ -0,0 +1,7 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset en_IE DATE_FORMAT "%d/%m/%y"
+ ::msgcat::mcset en_IE TIME_FORMAT "%T"
+ ::msgcat::mcset en_IE TIME_FORMAT_12 "%T"
+ ::msgcat::mcset en_IE DATE_TIME_FORMAT "%a %d %b %Y %T %z"
+}
diff --git a/library/msgs/en_in.msg b/library/msgs/en_in.msg
new file mode 100755
index 0000000..a1f155d
--- /dev/null
+++ b/library/msgs/en_in.msg
@@ -0,0 +1,8 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset en_IN AM "AM"
+ ::msgcat::mcset en_IN PM "PM"
+ ::msgcat::mcset en_IN DATE_FORMAT "%d %B %Y"
+ ::msgcat::mcset en_IN TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset en_IN DATE_TIME_FORMAT "%d %B %Y %H:%M:%S %z"
+}
diff --git a/library/msgs/en_nz.msg b/library/msgs/en_nz.msg
new file mode 100755
index 0000000..b419017
--- /dev/null
+++ b/library/msgs/en_nz.msg
@@ -0,0 +1,7 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset en_NZ DATE_FORMAT "%e/%m/%Y"
+ ::msgcat::mcset en_NZ TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset en_NZ TIME_FORMAT_12 "%I:%M:%S %P %z"
+ ::msgcat::mcset en_NZ DATE_TIME_FORMAT "%e/%m/%Y %H:%M:%S %z"
+}
diff --git a/library/msgs/en_ph.msg b/library/msgs/en_ph.msg
new file mode 100755
index 0000000..682666d
--- /dev/null
+++ b/library/msgs/en_ph.msg
@@ -0,0 +1,8 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset en_PH AM "AM"
+ ::msgcat::mcset en_PH PM "PM"
+ ::msgcat::mcset en_PH DATE_FORMAT "%B %e, %Y"
+ ::msgcat::mcset en_PH TIME_FORMAT_12 "%l:%M:%S %P"
+ ::msgcat::mcset en_PH DATE_TIME_FORMAT "%B %e, %Y %l:%M:%S %P %z"
+}
diff --git a/library/msgs/en_sg.msg b/library/msgs/en_sg.msg
new file mode 100755
index 0000000..4dc5b1d
--- /dev/null
+++ b/library/msgs/en_sg.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset en_SG DATE_FORMAT "%d %b %Y"
+ ::msgcat::mcset en_SG TIME_FORMAT_12 "%P %I:%M:%S"
+ ::msgcat::mcset en_SG DATE_TIME_FORMAT "%d %b %Y %P %I:%M:%S %z"
+}
diff --git a/library/msgs/en_za.msg b/library/msgs/en_za.msg
new file mode 100755
index 0000000..fe43797
--- /dev/null
+++ b/library/msgs/en_za.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset en_ZA DATE_FORMAT "%Y/%m/%d"
+ ::msgcat::mcset en_ZA TIME_FORMAT_12 "%I:%M:%S"
+ ::msgcat::mcset en_ZA DATE_TIME_FORMAT "%Y/%m/%d %I:%M:%S %z"
+}
diff --git a/library/msgs/en_zw.msg b/library/msgs/en_zw.msg
new file mode 100755
index 0000000..2a5804f
--- /dev/null
+++ b/library/msgs/en_zw.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset en_ZW DATE_FORMAT "%d %B %Y"
+ ::msgcat::mcset en_ZW TIME_FORMAT_12 "%l:%M:%S %P"
+ ::msgcat::mcset en_ZW DATE_TIME_FORMAT "%d %B %Y %l:%M:%S %P %z"
+}
diff --git a/library/msgs/eo.msg b/library/msgs/eo.msg
new file mode 100755
index 0000000..1d2a24f
--- /dev/null
+++ b/library/msgs/eo.msg
@@ -0,0 +1,54 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset eo DAYS_OF_WEEK_ABBREV [list \
+ "di"\
+ "lu"\
+ "ma"\
+ "me"\
+ "\u0135a"\
+ "ve"\
+ "sa"]
+ ::msgcat::mcset eo DAYS_OF_WEEK_FULL [list \
+ "diman\u0109o"\
+ "lundo"\
+ "mardo"\
+ "merkredo"\
+ "\u0135a\u016ddo"\
+ "vendredo"\
+ "sabato"]
+ ::msgcat::mcset eo MONTHS_ABBREV [list \
+ "jan"\
+ "feb"\
+ "mar"\
+ "apr"\
+ "maj"\
+ "jun"\
+ "jul"\
+ "a\u016dg"\
+ "sep"\
+ "okt"\
+ "nov"\
+ "dec"\
+ ""]
+ ::msgcat::mcset eo MONTHS_FULL [list \
+ "januaro"\
+ "februaro"\
+ "marto"\
+ "aprilo"\
+ "majo"\
+ "junio"\
+ "julio"\
+ "a\u016dgusto"\
+ "septembro"\
+ "oktobro"\
+ "novembro"\
+ "decembro"\
+ ""]
+ ::msgcat::mcset eo BCE "aK"
+ ::msgcat::mcset eo CE "pK"
+ ::msgcat::mcset eo AM "atm"
+ ::msgcat::mcset eo PM "ptm"
+ ::msgcat::mcset eo DATE_FORMAT "%Y-%b-%d"
+ ::msgcat::mcset eo TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset eo DATE_TIME_FORMAT "%Y-%b-%d %H:%M:%S %z"
+}
diff --git a/library/msgs/es.msg b/library/msgs/es.msg
new file mode 100755
index 0000000..a24f0a1
--- /dev/null
+++ b/library/msgs/es.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset es DAYS_OF_WEEK_ABBREV [list \
+ "dom"\
+ "lun"\
+ "mar"\
+ "mi\u00e9"\
+ "jue"\
+ "vie"\
+ "s\u00e1b"]
+ ::msgcat::mcset es DAYS_OF_WEEK_FULL [list \
+ "domingo"\
+ "lunes"\
+ "martes"\
+ "mi\u00e9rcoles"\
+ "jueves"\
+ "viernes"\
+ "s\u00e1bado"]
+ ::msgcat::mcset es MONTHS_ABBREV [list \
+ "ene"\
+ "feb"\
+ "mar"\
+ "abr"\
+ "may"\
+ "jun"\
+ "jul"\
+ "ago"\
+ "sep"\
+ "oct"\
+ "nov"\
+ "dic"\
+ ""]
+ ::msgcat::mcset es MONTHS_FULL [list \
+ "enero"\
+ "febrero"\
+ "marzo"\
+ "abril"\
+ "mayo"\
+ "junio"\
+ "julio"\
+ "agosto"\
+ "septiembre"\
+ "octubre"\
+ "noviembre"\
+ "diciembre"\
+ ""]
+ ::msgcat::mcset es BCE "a.C."
+ ::msgcat::mcset es CE "d.C."
+ ::msgcat::mcset es DATE_FORMAT "%e de %B de %Y"
+ ::msgcat::mcset es TIME_FORMAT "%k:%M:%S"
+ ::msgcat::mcset es DATE_TIME_FORMAT "%e de %B de %Y %k:%M:%S %z"
+}
diff --git a/library/msgs/es_ar.msg b/library/msgs/es_ar.msg
new file mode 100755
index 0000000..7d35027
--- /dev/null
+++ b/library/msgs/es_ar.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset es_AR DATE_FORMAT "%d/%m/%Y"
+ ::msgcat::mcset es_AR TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset es_AR DATE_TIME_FORMAT "%d/%m/%Y %H:%M:%S %z"
+}
diff --git a/library/msgs/es_bo.msg b/library/msgs/es_bo.msg
new file mode 100755
index 0000000..498ad0d
--- /dev/null
+++ b/library/msgs/es_bo.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset es_BO DATE_FORMAT "%d-%m-%Y"
+ ::msgcat::mcset es_BO TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset es_BO DATE_TIME_FORMAT "%d-%m-%Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/es_cl.msg b/library/msgs/es_cl.msg
new file mode 100755
index 0000000..31d465c
--- /dev/null
+++ b/library/msgs/es_cl.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset es_CL DATE_FORMAT "%d-%m-%Y"
+ ::msgcat::mcset es_CL TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset es_CL DATE_TIME_FORMAT "%d-%m-%Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/es_co.msg b/library/msgs/es_co.msg
new file mode 100755
index 0000000..77e57f0
--- /dev/null
+++ b/library/msgs/es_co.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset es_CO DATE_FORMAT "%e/%m/%Y"
+ ::msgcat::mcset es_CO TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset es_CO DATE_TIME_FORMAT "%e/%m/%Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/es_cr.msg b/library/msgs/es_cr.msg
new file mode 100755
index 0000000..7a652fa
--- /dev/null
+++ b/library/msgs/es_cr.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset es_CR DATE_FORMAT "%d/%m/%Y"
+ ::msgcat::mcset es_CR TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset es_CR DATE_TIME_FORMAT "%d/%m/%Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/es_do.msg b/library/msgs/es_do.msg
new file mode 100755
index 0000000..0e283da
--- /dev/null
+++ b/library/msgs/es_do.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset es_DO DATE_FORMAT "%m/%d/%Y"
+ ::msgcat::mcset es_DO TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset es_DO DATE_TIME_FORMAT "%m/%d/%Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/es_ec.msg b/library/msgs/es_ec.msg
new file mode 100755
index 0000000..9e921e0
--- /dev/null
+++ b/library/msgs/es_ec.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset es_EC DATE_FORMAT "%d/%m/%Y"
+ ::msgcat::mcset es_EC TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset es_EC DATE_TIME_FORMAT "%d/%m/%Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/es_gt.msg b/library/msgs/es_gt.msg
new file mode 100755
index 0000000..ecd6faf
--- /dev/null
+++ b/library/msgs/es_gt.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset es_GT DATE_FORMAT "%e/%m/%Y"
+ ::msgcat::mcset es_GT TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset es_GT DATE_TIME_FORMAT "%e/%m/%Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/es_hn.msg b/library/msgs/es_hn.msg
new file mode 100755
index 0000000..a758ca2
--- /dev/null
+++ b/library/msgs/es_hn.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset es_HN DATE_FORMAT "%m-%d-%Y"
+ ::msgcat::mcset es_HN TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset es_HN DATE_TIME_FORMAT "%m-%d-%Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/es_mx.msg b/library/msgs/es_mx.msg
new file mode 100755
index 0000000..7cfb545
--- /dev/null
+++ b/library/msgs/es_mx.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset es_MX DATE_FORMAT "%e/%m/%Y"
+ ::msgcat::mcset es_MX TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset es_MX DATE_TIME_FORMAT "%e/%m/%Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/es_ni.msg b/library/msgs/es_ni.msg
new file mode 100755
index 0000000..7c39495
--- /dev/null
+++ b/library/msgs/es_ni.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset es_NI DATE_FORMAT "%m-%d-%Y"
+ ::msgcat::mcset es_NI TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset es_NI DATE_TIME_FORMAT "%m-%d-%Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/es_pa.msg b/library/msgs/es_pa.msg
new file mode 100755
index 0000000..cecacdc
--- /dev/null
+++ b/library/msgs/es_pa.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset es_PA DATE_FORMAT "%m/%d/%Y"
+ ::msgcat::mcset es_PA TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset es_PA DATE_TIME_FORMAT "%m/%d/%Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/es_pe.msg b/library/msgs/es_pe.msg
new file mode 100755
index 0000000..9f90595
--- /dev/null
+++ b/library/msgs/es_pe.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset es_PE DATE_FORMAT "%d/%m/%Y"
+ ::msgcat::mcset es_PE TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset es_PE DATE_TIME_FORMAT "%d/%m/%Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/es_pr.msg b/library/msgs/es_pr.msg
new file mode 100755
index 0000000..8511b12
--- /dev/null
+++ b/library/msgs/es_pr.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset es_PR DATE_FORMAT "%m-%d-%Y"
+ ::msgcat::mcset es_PR TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset es_PR DATE_TIME_FORMAT "%m-%d-%Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/es_py.msg b/library/msgs/es_py.msg
new file mode 100755
index 0000000..aa93d36
--- /dev/null
+++ b/library/msgs/es_py.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset es_PY DATE_FORMAT "%d/%m/%Y"
+ ::msgcat::mcset es_PY TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset es_PY DATE_TIME_FORMAT "%d/%m/%Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/es_sv.msg b/library/msgs/es_sv.msg
new file mode 100755
index 0000000..fc7954d
--- /dev/null
+++ b/library/msgs/es_sv.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset es_SV DATE_FORMAT "%m-%d-%Y"
+ ::msgcat::mcset es_SV TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset es_SV DATE_TIME_FORMAT "%m-%d-%Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/es_uy.msg b/library/msgs/es_uy.msg
new file mode 100755
index 0000000..b33525c
--- /dev/null
+++ b/library/msgs/es_uy.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset es_UY DATE_FORMAT "%d/%m/%Y"
+ ::msgcat::mcset es_UY TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset es_UY DATE_TIME_FORMAT "%d/%m/%Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/es_ve.msg b/library/msgs/es_ve.msg
new file mode 100755
index 0000000..7c2a7b0
--- /dev/null
+++ b/library/msgs/es_ve.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset es_VE DATE_FORMAT "%d/%m/%Y"
+ ::msgcat::mcset es_VE TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset es_VE DATE_TIME_FORMAT "%d/%m/%Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/et.msg b/library/msgs/et.msg
new file mode 100755
index 0000000..8d32e9e
--- /dev/null
+++ b/library/msgs/et.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset et DAYS_OF_WEEK_ABBREV [list \
+ "P"\
+ "E"\
+ "T"\
+ "K"\
+ "N"\
+ "R"\
+ "L"]
+ ::msgcat::mcset et DAYS_OF_WEEK_FULL [list \
+ "p\u00fchap\u00e4ev"\
+ "esmasp\u00e4ev"\
+ "teisip\u00e4ev"\
+ "kolmap\u00e4ev"\
+ "neljap\u00e4ev"\
+ "reede"\
+ "laup\u00e4ev"]
+ ::msgcat::mcset et MONTHS_ABBREV [list \
+ "Jaan"\
+ "Veebr"\
+ "M\u00e4rts"\
+ "Apr"\
+ "Mai"\
+ "Juuni"\
+ "Juuli"\
+ "Aug"\
+ "Sept"\
+ "Okt"\
+ "Nov"\
+ "Dets"\
+ ""]
+ ::msgcat::mcset et MONTHS_FULL [list \
+ "Jaanuar"\
+ "Veebruar"\
+ "M\u00e4rts"\
+ "Aprill"\
+ "Mai"\
+ "Juuni"\
+ "Juuli"\
+ "August"\
+ "September"\
+ "Oktoober"\
+ "November"\
+ "Detsember"\
+ ""]
+ ::msgcat::mcset et BCE "e.m.a."
+ ::msgcat::mcset et CE "m.a.j."
+ ::msgcat::mcset et DATE_FORMAT "%e-%m-%Y"
+ ::msgcat::mcset et TIME_FORMAT "%k:%M:%S"
+ ::msgcat::mcset et DATE_TIME_FORMAT "%e-%m-%Y %k:%M:%S %z"
+}
diff --git a/library/msgs/eu.msg b/library/msgs/eu.msg
new file mode 100755
index 0000000..cf708b6
--- /dev/null
+++ b/library/msgs/eu.msg
@@ -0,0 +1,47 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset eu DAYS_OF_WEEK_ABBREV [list \
+ "igandea"\
+ "astelehena"\
+ "asteartea"\
+ "asteazkena"\
+ "osteguna"\
+ "ostirala"\
+ "larunbata"]
+ ::msgcat::mcset eu DAYS_OF_WEEK_FULL [list \
+ "igandea"\
+ "astelehena"\
+ "asteartea"\
+ "asteazkena"\
+ "osteguna"\
+ "ostirala"\
+ "larunbata"]
+ ::msgcat::mcset eu MONTHS_ABBREV [list \
+ "urt"\
+ "ots"\
+ "mar"\
+ "api"\
+ "mai"\
+ "eka"\
+ "uzt"\
+ "abu"\
+ "ira"\
+ "urr"\
+ "aza"\
+ "abe"\
+ ""]
+ ::msgcat::mcset eu MONTHS_FULL [list \
+ "urtarrila"\
+ "otsaila"\
+ "martxoa"\
+ "apirila"\
+ "maiatza"\
+ "ekaina"\
+ "uztaila"\
+ "abuztua"\
+ "iraila"\
+ "urria"\
+ "azaroa"\
+ "abendua"\
+ ""]
+}
diff --git a/library/msgs/eu_es.msg b/library/msgs/eu_es.msg
new file mode 100755
index 0000000..2694418
--- /dev/null
+++ b/library/msgs/eu_es.msg
@@ -0,0 +1,7 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset eu_ES DATE_FORMAT "%a, %Yeko %bren %da"
+ ::msgcat::mcset eu_ES TIME_FORMAT "%T"
+ ::msgcat::mcset eu_ES TIME_FORMAT_12 "%T"
+ ::msgcat::mcset eu_ES DATE_TIME_FORMAT "%y-%m-%d %T %z"
+}
diff --git a/library/msgs/fa.msg b/library/msgs/fa.msg
new file mode 100755
index 0000000..89b2f90
--- /dev/null
+++ b/library/msgs/fa.msg
@@ -0,0 +1,47 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset fa DAYS_OF_WEEK_ABBREV [list \
+ "\u06cc\u2214"\
+ "\u062f\u2214"\
+ "\u0633\u2214"\
+ "\u0686\u2214"\
+ "\u067e\u2214"\
+ "\u062c\u2214"\
+ "\u0634\u2214"]
+ ::msgcat::mcset fa DAYS_OF_WEEK_FULL [list \
+ "\u06cc\u06cc\u200c\u0634\u0646\u0628\u0647"\
+ "\u062f\u0648\u0634\u0646\u0628\u0647"\
+ "\u0633\u0647\u200c\u0634\u0646\u0628\u0647"\
+ "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647"\
+ "\u067e\u0646\u062c\u200c\u0634\u0646\u0628\u0647"\
+ "\u062c\u0645\u0639\u0647"\
+ "\u0634\u0646\u0628\u0647"]
+ ::msgcat::mcset fa MONTHS_ABBREV [list \
+ "\u0698\u0627\u0646"\
+ "\u0641\u0648\u0631"\
+ "\u0645\u0627\u0631"\
+ "\u0622\u0648\u0631"\
+ "\u0645\u0640\u0647"\
+ "\u0698\u0648\u0646"\
+ "\u0698\u0648\u06cc"\
+ "\u0627\u0648\u062a"\
+ "\u0633\u067e\u062a"\
+ "\u0627\u0643\u062a"\
+ "\u0646\u0648\u0627"\
+ "\u062f\u0633\u0627"\
+ ""]
+ ::msgcat::mcset fa MONTHS_FULL [list \
+ "\u0698\u0627\u0646\u0648\u06cc\u0647"\
+ "\u0641\u0648\u0631\u0648\u06cc\u0647"\
+ "\u0645\u0627\u0631\u0633"\
+ "\u0622\u0648\u0631\u06cc\u0644"\
+ "\u0645\u0647"\
+ "\u0698\u0648\u0626\u0646"\
+ "\u0698\u0648\u0626\u06cc\u0647"\
+ "\u0627\u0648\u062a"\
+ "\u0633\u067e\u062a\u0627\u0645\u0628\u0631"\
+ "\u0627\u0643\u062a\u0628\u0631"\
+ "\u0646\u0648\u0627\u0645\u0628\u0631"\
+ "\u062f\u0633\u0627\u0645\u0628\u0631"\
+ ""]
+}
diff --git a/library/msgs/fa_in.msg b/library/msgs/fa_in.msg
new file mode 100755
index 0000000..adc9e91
--- /dev/null
+++ b/library/msgs/fa_in.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset fa_IN DAYS_OF_WEEK_ABBREV [list \
+ "\u06cc\u2214"\
+ "\u062f\u2214"\
+ "\u0633\u2214"\
+ "\u0686\u2214"\
+ "\u067e\u2214"\
+ "\u062c\u2214"\
+ "\u0634\u2214"]
+ ::msgcat::mcset fa_IN DAYS_OF_WEEK_FULL [list \
+ "\u06cc\u06cc\u200c\u0634\u0646\u0628\u0647"\
+ "\u062f\u0648\u0634\u0646\u0628\u0647"\
+ "\u0633\u0647\u200c\u0634\u0646\u0628\u0647"\
+ "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647"\
+ "\u067e\u0646\u062c\u200c\u0634\u0646\u0628\u0647"\
+ "\u062c\u0645\u0639\u0647"\
+ "\u0634\u0646\u0628\u0647"]
+ ::msgcat::mcset fa_IN MONTHS_ABBREV [list \
+ "\u0698\u0627\u0646"\
+ "\u0641\u0648\u0631"\
+ "\u0645\u0627\u0631"\
+ "\u0622\u0648\u0631"\
+ "\u0645\u0640\u0647"\
+ "\u0698\u0648\u0646"\
+ "\u0698\u0648\u06cc"\
+ "\u0627\u0648\u062a"\
+ "\u0633\u067e\u062a"\
+ "\u0627\u0643\u062a"\
+ "\u0646\u0648\u0627"\
+ "\u062f\u0633\u0627"\
+ ""]
+ ::msgcat::mcset fa_IN MONTHS_FULL [list \
+ "\u0698\u0627\u0646\u0648\u06cc\u0647"\
+ "\u0641\u0648\u0631\u0648\u06cc\u0647"\
+ "\u0645\u0627\u0631\u0633"\
+ "\u0622\u0648\u0631\u06cc\u0644"\
+ "\u0645\u0647"\
+ "\u0698\u0648\u0626\u0646"\
+ "\u0698\u0648\u0626\u06cc\u0647"\
+ "\u0627\u0648\u062a"\
+ "\u0633\u067e\u062a\u0627\u0645\u0628\u0631"\
+ "\u0627\u0643\u062a\u0628\u0631"\
+ "\u0646\u0648\u0627\u0645\u0628\u0631"\
+ "\u062f\u0633\u0627\u0645\u0628\u0631"\
+ ""]
+ ::msgcat::mcset fa_IN AM "\u0635\u0628\u062d"
+ ::msgcat::mcset fa_IN PM "\u0639\u0635\u0631"
+ ::msgcat::mcset fa_IN DATE_FORMAT "%A %d %B %Y"
+ ::msgcat::mcset fa_IN TIME_FORMAT_12 "%I:%M:%S %z"
+ ::msgcat::mcset fa_IN DATE_TIME_FORMAT "%A %d %B %Y %I:%M:%S %z %z"
+}
diff --git a/library/msgs/fa_ir.msg b/library/msgs/fa_ir.msg
new file mode 100755
index 0000000..597ce9d
--- /dev/null
+++ b/library/msgs/fa_ir.msg
@@ -0,0 +1,9 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset fa_IR AM "\u0635\u0628\u062d"
+ ::msgcat::mcset fa_IR PM "\u0639\u0635\u0631"
+ ::msgcat::mcset fa_IR DATE_FORMAT "%d\u2044%m\u2044%Y"
+ ::msgcat::mcset fa_IR TIME_FORMAT "%S:%M:%H"
+ ::msgcat::mcset fa_IR TIME_FORMAT_12 "%S:%M:%l %P"
+ ::msgcat::mcset fa_IR DATE_TIME_FORMAT "%d\u2044%m\u2044%Y %S:%M:%H %z"
+}
diff --git a/library/msgs/fi.msg b/library/msgs/fi.msg
new file mode 100755
index 0000000..acabba0
--- /dev/null
+++ b/library/msgs/fi.msg
@@ -0,0 +1,50 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset fi DAYS_OF_WEEK_ABBREV [list \
+ "su"\
+ "ma"\
+ "ti"\
+ "ke"\
+ "to"\
+ "pe"\
+ "la"]
+ ::msgcat::mcset fi DAYS_OF_WEEK_FULL [list \
+ "sunnuntai"\
+ "maanantai"\
+ "tiistai"\
+ "keskiviikko"\
+ "torstai"\
+ "perjantai"\
+ "lauantai"]
+ ::msgcat::mcset fi MONTHS_ABBREV [list \
+ "tammi"\
+ "helmi"\
+ "maalis"\
+ "huhti"\
+ "touko"\
+ "kes\u00e4"\
+ "hein\u00e4"\
+ "elo"\
+ "syys"\
+ "loka"\
+ "marras"\
+ "joulu"\
+ ""]
+ ::msgcat::mcset fi MONTHS_FULL [list \
+ "tammikuu"\
+ "helmikuu"\
+ "maaliskuu"\
+ "huhtikuu"\
+ "toukokuu"\
+ "kes\u00e4kuu"\
+ "hein\u00e4kuu"\
+ "elokuu"\
+ "syyskuu"\
+ "lokakuu"\
+ "marraskuu"\
+ "joulukuu"\
+ ""]
+ ::msgcat::mcset fi DATE_FORMAT "%e.%m.%Y"
+ ::msgcat::mcset fi TIME_FORMAT "%k:%M:%S"
+ ::msgcat::mcset fi DATE_TIME_FORMAT "%e.%m.%Y %k:%M:%S %z"
+}
diff --git a/library/msgs/fo.msg b/library/msgs/fo.msg
new file mode 100755
index 0000000..4696e62
--- /dev/null
+++ b/library/msgs/fo.msg
@@ -0,0 +1,47 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset fo DAYS_OF_WEEK_ABBREV [list \
+ "sun"\
+ "m\u00e1n"\
+ "t\u00fds"\
+ "mik"\
+ "h\u00f3s"\
+ "fr\u00ed"\
+ "ley"]
+ ::msgcat::mcset fo DAYS_OF_WEEK_FULL [list \
+ "sunnudagur"\
+ "m\u00e1nadagur"\
+ "t\u00fdsdagur"\
+ "mikudagur"\
+ "h\u00f3sdagur"\
+ "fr\u00edggjadagur"\
+ "leygardagur"]
+ ::msgcat::mcset fo MONTHS_ABBREV [list \
+ "jan"\
+ "feb"\
+ "mar"\
+ "apr"\
+ "mai"\
+ "jun"\
+ "jul"\
+ "aug"\
+ "sep"\
+ "okt"\
+ "nov"\
+ "des"\
+ ""]
+ ::msgcat::mcset fo MONTHS_FULL [list \
+ "januar"\
+ "februar"\
+ "mars"\
+ "apr\u00edl"\
+ "mai"\
+ "juni"\
+ "juli"\
+ "august"\
+ "september"\
+ "oktober"\
+ "november"\
+ "desember"\
+ ""]
+}
diff --git a/library/msgs/fo_fo.msg b/library/msgs/fo_fo.msg
new file mode 100755
index 0000000..2392b8e
--- /dev/null
+++ b/library/msgs/fo_fo.msg
@@ -0,0 +1,7 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset fo_FO DATE_FORMAT "%d/%m-%Y"
+ ::msgcat::mcset fo_FO TIME_FORMAT "%T"
+ ::msgcat::mcset fo_FO TIME_FORMAT_12 "%T"
+ ::msgcat::mcset fo_FO DATE_TIME_FORMAT "%a %d %b %Y %T %z"
+}
diff --git a/library/msgs/fr.msg b/library/msgs/fr.msg
new file mode 100755
index 0000000..55b19bf
--- /dev/null
+++ b/library/msgs/fr.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset fr DAYS_OF_WEEK_ABBREV [list \
+ "dim."\
+ "lun."\
+ "mar."\
+ "mer."\
+ "jeu."\
+ "ven."\
+ "sam."]
+ ::msgcat::mcset fr DAYS_OF_WEEK_FULL [list \
+ "dimanche"\
+ "lundi"\
+ "mardi"\
+ "mercredi"\
+ "jeudi"\
+ "vendredi"\
+ "samedi"]
+ ::msgcat::mcset fr MONTHS_ABBREV [list \
+ "janv."\
+ "f\u00e9vr."\
+ "mars"\
+ "avr."\
+ "mai"\
+ "juin"\
+ "juil."\
+ "ao\u00fbt"\
+ "sept."\
+ "oct."\
+ "nov."\
+ "d\u00e9c."\
+ ""]
+ ::msgcat::mcset fr MONTHS_FULL [list \
+ "janvier"\
+ "f\u00e9vrier"\
+ "mars"\
+ "avril"\
+ "mai"\
+ "juin"\
+ "juillet"\
+ "ao\u00fbt"\
+ "septembre"\
+ "octobre"\
+ "novembre"\
+ "d\u00e9cembre"\
+ ""]
+ ::msgcat::mcset fr BCE "av. J.-C."
+ ::msgcat::mcset fr CE "ap. J.-C."
+ ::msgcat::mcset fr DATE_FORMAT "%e %B %Y"
+ ::msgcat::mcset fr TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset fr DATE_TIME_FORMAT "%e %B %Y %H:%M:%S %z"
+}
diff --git a/library/msgs/fr_be.msg b/library/msgs/fr_be.msg
new file mode 100755
index 0000000..cdb13bd
--- /dev/null
+++ b/library/msgs/fr_be.msg
@@ -0,0 +1,7 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset fr_BE DATE_FORMAT "%d/%m/%y"
+ ::msgcat::mcset fr_BE TIME_FORMAT "%T"
+ ::msgcat::mcset fr_BE TIME_FORMAT_12 "%T"
+ ::msgcat::mcset fr_BE DATE_TIME_FORMAT "%a %d %b %Y %T %z"
+}
diff --git a/library/msgs/fr_ca.msg b/library/msgs/fr_ca.msg
new file mode 100755
index 0000000..00ccfff
--- /dev/null
+++ b/library/msgs/fr_ca.msg
@@ -0,0 +1,7 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset fr_CA DATE_FORMAT "%Y-%m-%d"
+ ::msgcat::mcset fr_CA TIME_FORMAT "%T"
+ ::msgcat::mcset fr_CA TIME_FORMAT_12 "%T"
+ ::msgcat::mcset fr_CA DATE_TIME_FORMAT "%a %d %b %Y %T %z"
+}
diff --git a/library/msgs/fr_ch.msg b/library/msgs/fr_ch.msg
new file mode 100755
index 0000000..7e2bac7
--- /dev/null
+++ b/library/msgs/fr_ch.msg
@@ -0,0 +1,7 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset fr_CH DATE_FORMAT "%d. %m. %y"
+ ::msgcat::mcset fr_CH TIME_FORMAT "%T"
+ ::msgcat::mcset fr_CH TIME_FORMAT_12 "%T"
+ ::msgcat::mcset fr_CH DATE_TIME_FORMAT "%a %d %b %Y %T %z"
+}
diff --git a/library/msgs/ga.msg b/library/msgs/ga.msg
new file mode 100755
index 0000000..6edf13a
--- /dev/null
+++ b/library/msgs/ga.msg
@@ -0,0 +1,47 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset ga DAYS_OF_WEEK_ABBREV [list \
+ "Domh"\
+ "Luan"\
+ "M\u00e1irt"\
+ "C\u00e9ad"\
+ "D\u00e9ar"\
+ "Aoine"\
+ "Sath"]
+ ::msgcat::mcset ga DAYS_OF_WEEK_FULL [list \
+ "D\u00e9 Domhnaigh"\
+ "D\u00e9 Luain"\
+ "D\u00e9 M\u00e1irt"\
+ "D\u00e9 C\u00e9adaoin"\
+ "D\u00e9ardaoin"\
+ "D\u00e9 hAoine"\
+ "D\u00e9 Sathairn"]
+ ::msgcat::mcset ga MONTHS_ABBREV [list \
+ "Ean"\
+ "Feabh"\
+ "M\u00e1rta"\
+ "Aib"\
+ "Beal"\
+ "Meith"\
+ "I\u00fail"\
+ "L\u00fan"\
+ "MF\u00f3mh"\
+ "DF\u00f3mh"\
+ "Samh"\
+ "Noll"\
+ ""]
+ ::msgcat::mcset ga MONTHS_FULL [list \
+ "Ean\u00e1ir"\
+ "Feabhra"\
+ "M\u00e1rta"\
+ "Aibre\u00e1n"\
+ "M\u00ed na Bealtaine"\
+ "Meith"\
+ "I\u00fail"\
+ "L\u00fanasa"\
+ "Me\u00e1n F\u00f3mhair"\
+ "Deireadh F\u00f3mhair"\
+ "M\u00ed na Samhna"\
+ "M\u00ed na Nollag"\
+ ""]
+}
diff --git a/library/msgs/ga_ie.msg b/library/msgs/ga_ie.msg
new file mode 100755
index 0000000..b6acbbc
--- /dev/null
+++ b/library/msgs/ga_ie.msg
@@ -0,0 +1,7 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset ga_IE DATE_FORMAT "%d.%m.%y"
+ ::msgcat::mcset ga_IE TIME_FORMAT "%T"
+ ::msgcat::mcset ga_IE TIME_FORMAT_12 "%T"
+ ::msgcat::mcset ga_IE DATE_TIME_FORMAT "%a %d %b %Y %T %z"
+}
diff --git a/library/msgs/gl.msg b/library/msgs/gl.msg
new file mode 100755
index 0000000..4b869e8
--- /dev/null
+++ b/library/msgs/gl.msg
@@ -0,0 +1,47 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset gl DAYS_OF_WEEK_ABBREV [list \
+ "Dom"\
+ "Lun"\
+ "Mar"\
+ "M\u00e9r"\
+ "Xov"\
+ "Ven"\
+ "S\u00e1b"]
+ ::msgcat::mcset gl DAYS_OF_WEEK_FULL [list \
+ "Domingo"\
+ "Luns"\
+ "Martes"\
+ "M\u00e9rcores"\
+ "Xoves"\
+ "Venres"\
+ "S\u00e1bado"]
+ ::msgcat::mcset gl MONTHS_ABBREV [list \
+ "Xan"\
+ "Feb"\
+ "Mar"\
+ "Abr"\
+ "Mai"\
+ "Xu\u00f1"\
+ "Xul"\
+ "Ago"\
+ "Set"\
+ "Out"\
+ "Nov"\
+ "Dec"\
+ ""]
+ ::msgcat::mcset gl MONTHS_FULL [list \
+ "Xaneiro"\
+ "Febreiro"\
+ "Marzo"\
+ "Abril"\
+ "Maio"\
+ "Xu\u00f1o"\
+ "Xullo"\
+ "Agosto"\
+ "Setembro"\
+ "Outubro"\
+ "Novembro"\
+ "Decembro"\
+ ""]
+}
diff --git a/library/msgs/gl_es.msg b/library/msgs/gl_es.msg
new file mode 100755
index 0000000..d4ed270
--- /dev/null
+++ b/library/msgs/gl_es.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset gl_ES DATE_FORMAT "%d %B %Y"
+ ::msgcat::mcset gl_ES TIME_FORMAT_12 "%l:%M:%S %P"
+ ::msgcat::mcset gl_ES DATE_TIME_FORMAT "%d %B %Y %l:%M:%S %P %z"
+}
diff --git a/library/msgs/gv.msg b/library/msgs/gv.msg
new file mode 100755
index 0000000..7d332ad
--- /dev/null
+++ b/library/msgs/gv.msg
@@ -0,0 +1,47 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset gv DAYS_OF_WEEK_ABBREV [list \
+ "Jed"\
+ "Jel"\
+ "Jem"\
+ "Jerc"\
+ "Jerd"\
+ "Jeh"\
+ "Jes"]
+ ::msgcat::mcset gv DAYS_OF_WEEK_FULL [list \
+ "Jedoonee"\
+ "Jelhein"\
+ "Jemayrt"\
+ "Jercean"\
+ "Jerdein"\
+ "Jeheiney"\
+ "Jesarn"]
+ ::msgcat::mcset gv MONTHS_ABBREV [list \
+ "J-guer"\
+ "T-arree"\
+ "Mayrnt"\
+ "Avrril"\
+ "Boaldyn"\
+ "M-souree"\
+ "J-souree"\
+ "Luanistyn"\
+ "M-fouyir"\
+ "J-fouyir"\
+ "M.Houney"\
+ "M.Nollick"\
+ ""]
+ ::msgcat::mcset gv MONTHS_FULL [list \
+ "Jerrey-geuree"\
+ "Toshiaght-arree"\
+ "Mayrnt"\
+ "Averil"\
+ "Boaldyn"\
+ "Mean-souree"\
+ "Jerrey-souree"\
+ "Luanistyn"\
+ "Mean-fouyir"\
+ "Jerrey-fouyir"\
+ "Mee Houney"\
+ "Mee ny Nollick"\
+ ""]
+}
diff --git a/library/msgs/gv_gb.msg b/library/msgs/gv_gb.msg
new file mode 100755
index 0000000..5e96e6f
--- /dev/null
+++ b/library/msgs/gv_gb.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset gv_GB DATE_FORMAT "%d %B %Y"
+ ::msgcat::mcset gv_GB TIME_FORMAT_12 "%l:%M:%S %P"
+ ::msgcat::mcset gv_GB DATE_TIME_FORMAT "%d %B %Y %l:%M:%S %P %z"
+}
diff --git a/library/msgs/he.msg b/library/msgs/he.msg
new file mode 100755
index 0000000..4fd921d
--- /dev/null
+++ b/library/msgs/he.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset he DAYS_OF_WEEK_ABBREV [list \
+ "\u05d0"\
+ "\u05d1"\
+ "\u05d2"\
+ "\u05d3"\
+ "\u05d4"\
+ "\u05d5"\
+ "\u05e9"]
+ ::msgcat::mcset he DAYS_OF_WEEK_FULL [list \
+ "\u05d9\u05d5\u05dd \u05e8\u05d0\u05e9\u05d5\u05df"\
+ "\u05d9\u05d5\u05dd \u05e9\u05e0\u05d9"\
+ "\u05d9\u05d5\u05dd \u05e9\u05dc\u05d9\u05e9\u05d9"\
+ "\u05d9\u05d5\u05dd \u05e8\u05d1\u05d9\u05e2\u05d9"\
+ "\u05d9\u05d5\u05dd \u05d7\u05de\u05d9\u05e9\u05d9"\
+ "\u05d9\u05d5\u05dd \u05e9\u05d9\u05e9\u05d9"\
+ "\u05e9\u05d1\u05ea"]
+ ::msgcat::mcset he MONTHS_ABBREV [list \
+ "\u05d9\u05e0\u05d5"\
+ "\u05e4\u05d1\u05e8"\
+ "\u05de\u05e8\u05e5"\
+ "\u05d0\u05e4\u05e8"\
+ "\u05de\u05d0\u05d9"\
+ "\u05d9\u05d5\u05e0"\
+ "\u05d9\u05d5\u05dc"\
+ "\u05d0\u05d5\u05d2"\
+ "\u05e1\u05e4\u05d8"\
+ "\u05d0\u05d5\u05e7"\
+ "\u05e0\u05d5\u05d1"\
+ "\u05d3\u05e6\u05de"\
+ ""]
+ ::msgcat::mcset he MONTHS_FULL [list \
+ "\u05d9\u05e0\u05d5\u05d0\u05e8"\
+ "\u05e4\u05d1\u05e8\u05d5\u05d0\u05e8"\
+ "\u05de\u05e8\u05e5"\
+ "\u05d0\u05e4\u05e8\u05d9\u05dc"\
+ "\u05de\u05d0\u05d9"\
+ "\u05d9\u05d5\u05e0\u05d9"\
+ "\u05d9\u05d5\u05dc\u05d9"\
+ "\u05d0\u05d5\u05d2\u05d5\u05e1\u05d8"\
+ "\u05e1\u05e4\u05d8\u05de\u05d1\u05e8"\
+ "\u05d0\u05d5\u05e7\u05d8\u05d5\u05d1\u05e8"\
+ "\u05e0\u05d5\u05d1\u05de\u05d1\u05e8"\
+ "\u05d3\u05e6\u05de\u05d1\u05e8"\
+ ""]
+ ::msgcat::mcset he BCE "\u05dc\u05e1\u05d4\u0022\u05e0"
+ ::msgcat::mcset he CE "\u05dc\u05e4\u05e1\u05d4\u0022\u05e0"
+ ::msgcat::mcset he DATE_FORMAT "%d/%m/%Y"
+ ::msgcat::mcset he TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset he DATE_TIME_FORMAT "%d/%m/%Y %H:%M:%S %z"
+}
diff --git a/library/msgs/hi.msg b/library/msgs/hi.msg
new file mode 100755
index 0000000..50c9fb8
--- /dev/null
+++ b/library/msgs/hi.msg
@@ -0,0 +1,39 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset hi DAYS_OF_WEEK_FULL [list \
+ "\u0930\u0935\u093f\u0935\u093e\u0930"\
+ "\u0938\u094b\u092e\u0935\u093e\u0930"\
+ "\u092e\u0902\u0917\u0932\u0935\u093e\u0930"\
+ "\u092c\u0941\u0927\u0935\u093e\u0930"\
+ "\u0917\u0941\u0930\u0941\u0935\u093e\u0930"\
+ "\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930"\
+ "\u0936\u0928\u093f\u0935\u093e\u0930"]
+ ::msgcat::mcset hi MONTHS_ABBREV [list \
+ "\u091c\u0928\u0935\u0930\u0940"\
+ "\u092b\u093c\u0930\u0935\u0930\u0940"\
+ "\u092e\u093e\u0930\u094d\u091a"\
+ "\u0905\u092a\u094d\u0930\u0947\u0932"\
+ "\u092e\u0908"\
+ "\u091c\u0942\u0928"\
+ "\u091c\u0941\u0932\u093e\u0908"\
+ "\u0905\u0917\u0938\u094d\u0924"\
+ "\u0938\u093f\u0924\u092e\u094d\u092c\u0930"\
+ "\u0905\u0915\u094d\u091f\u0942\u092c\u0930"\
+ "\u0928\u0935\u092e\u094d\u092c\u0930"\
+ "\u0926\u093f\u0938\u092e\u094d\u092c\u0930"]
+ ::msgcat::mcset hi MONTHS_FULL [list \
+ "\u091c\u0928\u0935\u0930\u0940"\
+ "\u092b\u093c\u0930\u0935\u0930\u0940"\
+ "\u092e\u093e\u0930\u094d\u091a"\
+ "\u0905\u092a\u094d\u0930\u0947\u0932"\
+ "\u092e\u0908"\
+ "\u091c\u0942\u0928"\
+ "\u091c\u0941\u0932\u093e\u0908"\
+ "\u0905\u0917\u0938\u094d\u0924"\
+ "\u0938\u093f\u0924\u092e\u094d\u092c\u0930"\
+ "\u0905\u0915\u094d\u091f\u0942\u092c\u0930"\
+ "\u0928\u0935\u092e\u094d\u092c\u0930"\
+ "\u0926\u093f\u0938\u092e\u094d\u092c\u0930"]
+ ::msgcat::mcset hi AM "\u0908\u0938\u093e\u092a\u0942\u0930\u094d\u0935"
+ ::msgcat::mcset hi PM "."
+}
diff --git a/library/msgs/hi_in.msg b/library/msgs/hi_in.msg
new file mode 100755
index 0000000..239793f
--- /dev/null
+++ b/library/msgs/hi_in.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset hi_IN DATE_FORMAT "%d %M %Y"
+ ::msgcat::mcset hi_IN TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset hi_IN DATE_TIME_FORMAT "%d %M %Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/hr.msg b/library/msgs/hr.msg
new file mode 100755
index 0000000..cec145b
--- /dev/null
+++ b/library/msgs/hr.msg
@@ -0,0 +1,50 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset hr DAYS_OF_WEEK_ABBREV [list \
+ "ned"\
+ "pon"\
+ "uto"\
+ "sri"\
+ "\u010det"\
+ "pet"\
+ "sub"]
+ ::msgcat::mcset hr DAYS_OF_WEEK_FULL [list \
+ "nedjelja"\
+ "ponedjeljak"\
+ "utorak"\
+ "srijeda"\
+ "\u010detvrtak"\
+ "petak"\
+ "subota"]
+ ::msgcat::mcset hr MONTHS_ABBREV [list \
+ "sij"\
+ "vel"\
+ "o\u017eu"\
+ "tra"\
+ "svi"\
+ "lip"\
+ "srp"\
+ "kol"\
+ "ruj"\
+ "lis"\
+ "stu"\
+ "pro"\
+ ""]
+ ::msgcat::mcset hr MONTHS_FULL [list \
+ "sije\u010danj"\
+ "velja\u010da"\
+ "o\u017eujak"\
+ "travanj"\
+ "svibanj"\
+ "lipanj"\
+ "srpanj"\
+ "kolovoz"\
+ "rujan"\
+ "listopad"\
+ "studeni"\
+ "prosinac"\
+ ""]
+ ::msgcat::mcset hr DATE_FORMAT "%Y.%m.%d"
+ ::msgcat::mcset hr TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset hr DATE_TIME_FORMAT "%Y.%m.%d %H:%M:%S %z"
+}
diff --git a/library/msgs/hu.msg b/library/msgs/hu.msg
new file mode 100755
index 0000000..e5e68d9
--- /dev/null
+++ b/library/msgs/hu.msg
@@ -0,0 +1,54 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset hu DAYS_OF_WEEK_ABBREV [list \
+ "V"\
+ "H"\
+ "K"\
+ "Sze"\
+ "Cs"\
+ "P"\
+ "Szo"]
+ ::msgcat::mcset hu DAYS_OF_WEEK_FULL [list \
+ "vas\u00e1rnap"\
+ "h\u00e9tf\u0151"\
+ "kedd"\
+ "szerda"\
+ "cs\u00fct\u00f6rt\u00f6k"\
+ "p\u00e9ntek"\
+ "szombat"]
+ ::msgcat::mcset hu MONTHS_ABBREV [list \
+ "jan."\
+ "febr."\
+ "m\u00e1rc."\
+ "\u00e1pr."\
+ "m\u00e1j."\
+ "j\u00fan."\
+ "j\u00fal."\
+ "aug."\
+ "szept."\
+ "okt."\
+ "nov."\
+ "dec."\
+ ""]
+ ::msgcat::mcset hu MONTHS_FULL [list \
+ "janu\u00e1r"\
+ "febru\u00e1r"\
+ "m\u00e1rcius"\
+ "\u00e1prilis"\
+ "m\u00e1jus"\
+ "j\u00fanius"\
+ "j\u00falius"\
+ "augusztus"\
+ "szeptember"\
+ "okt\u00f3ber"\
+ "november"\
+ "december"\
+ ""]
+ ::msgcat::mcset hu BCE "i.e."
+ ::msgcat::mcset hu CE "i.u."
+ ::msgcat::mcset hu AM "DE"
+ ::msgcat::mcset hu PM "DU"
+ ::msgcat::mcset hu DATE_FORMAT "%Y.%m.%d."
+ ::msgcat::mcset hu TIME_FORMAT "%k:%M:%S"
+ ::msgcat::mcset hu DATE_TIME_FORMAT "%Y.%m.%d. %k:%M:%S %z"
+}
diff --git a/library/msgs/id.msg b/library/msgs/id.msg
new file mode 100755
index 0000000..17c6bb5
--- /dev/null
+++ b/library/msgs/id.msg
@@ -0,0 +1,47 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset id DAYS_OF_WEEK_ABBREV [list \
+ "Min"\
+ "Sen"\
+ "Sel"\
+ "Rab"\
+ "Kam"\
+ "Jum"\
+ "Sab"]
+ ::msgcat::mcset id DAYS_OF_WEEK_FULL [list \
+ "Minggu"\
+ "Senin"\
+ "Selasa"\
+ "Rabu"\
+ "Kamis"\
+ "Jumat"\
+ "Sabtu"]
+ ::msgcat::mcset id MONTHS_ABBREV [list \
+ "Jan"\
+ "Peb"\
+ "Mar"\
+ "Apr"\
+ "Mei"\
+ "Jun"\
+ "Jul"\
+ "Agu"\
+ "Sep"\
+ "Okt"\
+ "Nov"\
+ "Des"\
+ ""]
+ ::msgcat::mcset id MONTHS_FULL [list \
+ "Januari"\
+ "Pebruari"\
+ "Maret"\
+ "April"\
+ "Mei"\
+ "Juni"\
+ "Juli"\
+ "Agustus"\
+ "September"\
+ "Oktober"\
+ "November"\
+ "Desember"\
+ ""]
+}
diff --git a/library/msgs/id_id.msg b/library/msgs/id_id.msg
new file mode 100755
index 0000000..bb672c1
--- /dev/null
+++ b/library/msgs/id_id.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset id_ID DATE_FORMAT "%d %B %Y"
+ ::msgcat::mcset id_ID TIME_FORMAT_12 "%l:%M:%S %P"
+ ::msgcat::mcset id_ID DATE_TIME_FORMAT "%d %B %Y %l:%M:%S %P %z"
+}
diff --git a/library/msgs/is.msg b/library/msgs/is.msg
new file mode 100755
index 0000000..adc2d2a
--- /dev/null
+++ b/library/msgs/is.msg
@@ -0,0 +1,50 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset is DAYS_OF_WEEK_ABBREV [list \
+ "sun."\
+ "m\u00e1n."\
+ "\u00feri."\
+ "mi\u00f0."\
+ "fim."\
+ "f\u00f6s."\
+ "lau."]
+ ::msgcat::mcset is DAYS_OF_WEEK_FULL [list \
+ "sunnudagur"\
+ "m\u00e1nudagur"\
+ "\u00feri\u00f0judagur"\
+ "mi\u00f0vikudagur"\
+ "fimmtudagur"\
+ "f\u00f6studagur"\
+ "laugardagur"]
+ ::msgcat::mcset is MONTHS_ABBREV [list \
+ "jan."\
+ "feb."\
+ "mar."\
+ "apr."\
+ "ma\u00ed"\
+ "j\u00fan."\
+ "j\u00fal."\
+ "\u00e1g\u00fa."\
+ "sep."\
+ "okt."\
+ "n\u00f3v."\
+ "des."\
+ ""]
+ ::msgcat::mcset is MONTHS_FULL [list \
+ "jan\u00faar"\
+ "febr\u00faar"\
+ "mars"\
+ "apr\u00edl"\
+ "ma\u00ed"\
+ "j\u00fan\u00ed"\
+ "j\u00fal\u00ed"\
+ "\u00e1g\u00fast"\
+ "september"\
+ "okt\u00f3ber"\
+ "n\u00f3vember"\
+ "desember"\
+ ""]
+ ::msgcat::mcset is DATE_FORMAT "%e.%m.%Y"
+ ::msgcat::mcset is TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset is DATE_TIME_FORMAT "%e.%m.%Y %H:%M:%S %z"
+}
diff --git a/library/msgs/it.msg b/library/msgs/it.msg
new file mode 100755
index 0000000..b641cde
--- /dev/null
+++ b/library/msgs/it.msg
@@ -0,0 +1,54 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset it DAYS_OF_WEEK_ABBREV [list \
+ "dom"\
+ "lun"\
+ "mar"\
+ "mer"\
+ "gio"\
+ "ven"\
+ "sab"]
+ ::msgcat::mcset it DAYS_OF_WEEK_FULL [list \
+ "domenica"\
+ "luned\u00ec"\
+ "marted\u00ec"\
+ "mercoled\u00ec"\
+ "gioved\u00ec"\
+ "venerd\u00ec"\
+ "sabato"]
+ ::msgcat::mcset it MONTHS_ABBREV [list \
+ "gen"\
+ "feb"\
+ "mar"\
+ "apr"\
+ "mag"\
+ "giu"\
+ "lug"\
+ "ago"\
+ "set"\
+ "ott"\
+ "nov"\
+ "dic"\
+ ""]
+ ::msgcat::mcset it MONTHS_FULL [list \
+ "gennaio"\
+ "febbraio"\
+ "marzo"\
+ "aprile"\
+ "maggio"\
+ "giugno"\
+ "luglio"\
+ "agosto"\
+ "settembre"\
+ "ottobre"\
+ "novembre"\
+ "dicembre"\
+ ""]
+ ::msgcat::mcset it BCE "aC"
+ ::msgcat::mcset it CE "dC"
+ ::msgcat::mcset it AM "m."
+ ::msgcat::mcset it PM "p."
+ ::msgcat::mcset it DATE_FORMAT "%d %B %Y"
+ ::msgcat::mcset it TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset it DATE_TIME_FORMAT "%d %B %Y %H:%M:%S %z"
+}
diff --git a/library/msgs/it_ch.msg b/library/msgs/it_ch.msg
new file mode 100755
index 0000000..b36ed36
--- /dev/null
+++ b/library/msgs/it_ch.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset it_CH DATE_FORMAT "%e. %B %Y"
+ ::msgcat::mcset it_CH TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset it_CH DATE_TIME_FORMAT "%e. %B %Y %H:%M:%S %z"
+}
diff --git a/library/msgs/ja.msg b/library/msgs/ja.msg
new file mode 100755
index 0000000..2767665
--- /dev/null
+++ b/library/msgs/ja.msg
@@ -0,0 +1,44 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset ja DAYS_OF_WEEK_ABBREV [list \
+ "\u65e5"\
+ "\u6708"\
+ "\u706b"\
+ "\u6c34"\
+ "\u6728"\
+ "\u91d1"\
+ "\u571f"]
+ ::msgcat::mcset ja DAYS_OF_WEEK_FULL [list \
+ "\u65e5\u66dc\u65e5"\
+ "\u6708\u66dc\u65e5"\
+ "\u706b\u66dc\u65e5"\
+ "\u6c34\u66dc\u65e5"\
+ "\u6728\u66dc\u65e5"\
+ "\u91d1\u66dc\u65e5"\
+ "\u571f\u66dc\u65e5"]
+ ::msgcat::mcset ja MONTHS_FULL [list \
+ "1\u6708"\
+ "2\u6708"\
+ "3\u6708"\
+ "4\u6708"\
+ "5\u6708"\
+ "6\u6708"\
+ "7\u6708"\
+ "8\u6708"\
+ "9\u6708"\
+ "10\u6708"\
+ "11\u6708"\
+ "12\u6708"]
+ ::msgcat::mcset ja BCE "\u7d00\u5143\u524d"
+ ::msgcat::mcset ja CE "\u897f\u66a6"
+ ::msgcat::mcset ja AM "\u5348\u524d"
+ ::msgcat::mcset ja PM "\u5348\u5f8c"
+ ::msgcat::mcset ja DATE_FORMAT "%Y/%m/%d"
+ ::msgcat::mcset ja TIME_FORMAT "%k:%M:%S"
+ ::msgcat::mcset ja TIME_FORMAT_12 "%P %I:%M:%S"
+ ::msgcat::mcset ja DATE_TIME_FORMAT "%Y/%m/%d %k:%M:%S %z"
+ ::msgcat::mcset ja LOCALE_DATE_FORMAT "%EY\u5e74%m\u6708%d\u65e5"
+ ::msgcat::mcset ja LOCALE_TIME_FORMAT "%H\u6642%M\u5206%S\u79d2"
+ ::msgcat::mcset ja LOCALE_DATE_TIME_FORMAT "%EY\u5e74%m\u6708%d\u65e5 (%a) %H\u6642%M\u5206%S\u79d2 %z"
+ ::msgcat::mcset ja LOCALE_ERAS "\u007b-9223372036854775808 \u897f\u66a6 0\u007d \u007b-3061011600 \u660e\u6cbb 1867\u007d \u007b-1812186000 \u5927\u6b63 1911\u007d \u007b-1357635600 \u662d\u548c 1925\u007d \u007b600220800 \u5e73\u6210 1988\u007d"
+}
diff --git a/library/msgs/kl.msg b/library/msgs/kl.msg
new file mode 100755
index 0000000..d877bfe
--- /dev/null
+++ b/library/msgs/kl.msg
@@ -0,0 +1,47 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset kl DAYS_OF_WEEK_ABBREV [list \
+ "sab"\
+ "ata"\
+ "mar"\
+ "pin"\
+ "sis"\
+ "tal"\
+ "arf"]
+ ::msgcat::mcset kl DAYS_OF_WEEK_FULL [list \
+ "sabaat"\
+ "ataasinngorneq"\
+ "marlunngorneq"\
+ "pingasunngorneq"\
+ "sisamanngorneq"\
+ "tallimanngorneq"\
+ "arfininngorneq"]
+ ::msgcat::mcset kl MONTHS_ABBREV [list \
+ "jan"\
+ "feb"\
+ "mar"\
+ "apr"\
+ "maj"\
+ "jun"\
+ "jul"\
+ "aug"\
+ "sep"\
+ "okt"\
+ "nov"\
+ "dec"\
+ ""]
+ ::msgcat::mcset kl MONTHS_FULL [list \
+ "januari"\
+ "februari"\
+ "martsi"\
+ "aprili"\
+ "maji"\
+ "juni"\
+ "juli"\
+ "augustusi"\
+ "septemberi"\
+ "oktoberi"\
+ "novemberi"\
+ "decemberi"\
+ ""]
+}
diff --git a/library/msgs/kl_gl.msg b/library/msgs/kl_gl.msg
new file mode 100755
index 0000000..403aa10
--- /dev/null
+++ b/library/msgs/kl_gl.msg
@@ -0,0 +1,7 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset kl_GL DATE_FORMAT "%d %b %Y"
+ ::msgcat::mcset kl_GL TIME_FORMAT "%T"
+ ::msgcat::mcset kl_GL TIME_FORMAT_12 "%T"
+ ::msgcat::mcset kl_GL DATE_TIME_FORMAT "%a %d %b %Y %T %z"
+}
diff --git a/library/msgs/ko.msg b/library/msgs/ko.msg
new file mode 100755
index 0000000..0cd17a1
--- /dev/null
+++ b/library/msgs/ko.msg
@@ -0,0 +1,55 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset ko DAYS_OF_WEEK_ABBREV [list \
+ "\uc77c"\
+ "\uc6d4"\
+ "\ud654"\
+ "\uc218"\
+ "\ubaa9"\
+ "\uae08"\
+ "\ud1a0"]
+ ::msgcat::mcset ko DAYS_OF_WEEK_FULL [list \
+ "\uc77c\uc694\uc77c"\
+ "\uc6d4\uc694\uc77c"\
+ "\ud654\uc694\uc77c"\
+ "\uc218\uc694\uc77c"\
+ "\ubaa9\uc694\uc77c"\
+ "\uae08\uc694\uc77c"\
+ "\ud1a0\uc694\uc77c"]
+ ::msgcat::mcset ko MONTHS_ABBREV [list \
+ "1\uc6d4"\
+ "2\uc6d4"\
+ "3\uc6d4"\
+ "4\uc6d4"\
+ "5\uc6d4"\
+ "6\uc6d4"\
+ "7\uc6d4"\
+ "8\uc6d4"\
+ "9\uc6d4"\
+ "10\uc6d4"\
+ "11\uc6d4"\
+ "12\uc6d4"\
+ ""]
+ ::msgcat::mcset ko MONTHS_FULL [list \
+ "1\uc6d4"\
+ "2\uc6d4"\
+ "3\uc6d4"\
+ "4\uc6d4"\
+ "5\uc6d4"\
+ "6\uc6d4"\
+ "7\uc6d4"\
+ "8\uc6d4"\
+ "9\uc6d4"\
+ "10\uc6d4"\
+ "11\uc6d4"\
+ "12\uc6d4"\
+ ""]
+ ::msgcat::mcset ko AM "\uc624\uc804"
+ ::msgcat::mcset ko PM "\uc624\ud6c4"
+ ::msgcat::mcset ko DATE_FORMAT "%Y-%m-%d"
+ ::msgcat::mcset ko TIME_FORMAT_12 "%P %l:%M:%S"
+ ::msgcat::mcset ko DATE_TIME_FORMAT "%Y-%m-%d %P %l:%M:%S %z"
+ ::msgcat::mcset ko LOCALE_DATE_FORMAT "%Y\ub144%B%Od\uc77c"
+ ::msgcat::mcset ko LOCALE_TIME_FORMAT "%H\uc2dc%M\ubd84%S\ucd08"
+ ::msgcat::mcset ko LOCALE_DATE_TIME_FORMAT "%A %Y\ub144%B%Od\uc77c%H\uc2dc%M\ubd84%S\ucd08 %z"
+}
diff --git a/library/msgs/ko_kr.msg b/library/msgs/ko_kr.msg
new file mode 100755
index 0000000..ea5bbd7
--- /dev/null
+++ b/library/msgs/ko_kr.msg
@@ -0,0 +1,8 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset ko_KR BCE "\uae30\uc6d0\uc804"
+ ::msgcat::mcset ko_KR CE "\uc11c\uae30"
+ ::msgcat::mcset ko_KR DATE_FORMAT "%Y.%m.%d"
+ ::msgcat::mcset ko_KR TIME_FORMAT_12 "%P %l:%M:%S"
+ ::msgcat::mcset ko_KR DATE_TIME_FORMAT "%Y.%m.%d %P %l:%M:%S %z"
+}
diff --git a/library/msgs/kok.msg b/library/msgs/kok.msg
new file mode 100755
index 0000000..0869f20
--- /dev/null
+++ b/library/msgs/kok.msg
@@ -0,0 +1,39 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset kok DAYS_OF_WEEK_FULL [list \
+ "\u0906\u0926\u093f\u0924\u094d\u092f\u0935\u093e\u0930"\
+ "\u0938\u094b\u092e\u0935\u093e\u0930"\
+ "\u092e\u0902\u0917\u0933\u093e\u0930"\
+ "\u092c\u0941\u0927\u0935\u093e\u0930"\
+ "\u0917\u0941\u0930\u0941\u0935\u093e\u0930"\
+ "\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930"\
+ "\u0936\u0928\u093f\u0935\u093e\u0930"]
+ ::msgcat::mcset kok MONTHS_ABBREV [list \
+ "\u091c\u093e\u0928\u0947\u0935\u093e\u0930\u0940"\
+ "\u092b\u0947\u092c\u0943\u0935\u093e\u0930\u0940"\
+ "\u092e\u093e\u0930\u094d\u091a"\
+ "\u090f\u092a\u094d\u0930\u093f\u0932"\
+ "\u092e\u0947"\
+ "\u091c\u0942\u0928"\
+ "\u091c\u0941\u0932\u0948"\
+ "\u0913\u0917\u0938\u094d\u091f"\
+ "\u0938\u0947\u092a\u094d\u091f\u0947\u0902\u092c\u0930"\
+ "\u0913\u0915\u094d\u091f\u094b\u092c\u0930"\
+ "\u0928\u094b\u0935\u094d\u0939\u0947\u0902\u092c\u0930"\
+ "\u0921\u093f\u0938\u0947\u0902\u092c\u0930"]
+ ::msgcat::mcset kok MONTHS_FULL [list \
+ "\u091c\u093e\u0928\u0947\u0935\u093e\u0930\u0940"\
+ "\u092b\u0947\u092c\u094d\u0930\u0941\u0935\u093e\u0930\u0940"\
+ "\u092e\u093e\u0930\u094d\u091a"\
+ "\u090f\u092a\u094d\u0930\u093f\u0932"\
+ "\u092e\u0947"\
+ "\u091c\u0942\u0928"\
+ "\u091c\u0941\u0932\u0948"\
+ "\u0913\u0917\u0938\u094d\u091f"\
+ "\u0938\u0947\u092a\u094d\u091f\u0947\u0902\u092c\u0930"\
+ "\u0913\u0915\u094d\u091f\u094b\u092c\u0930"\
+ "\u0928\u094b\u0935\u094d\u0939\u0947\u0902\u092c\u0930"\
+ "\u0921\u093f\u0938\u0947\u0902\u092c\u0930"]
+ ::msgcat::mcset kok AM "\u0915\u094d\u0930\u093f\u0938\u094d\u0924\u092a\u0942\u0930\u094d\u0935"
+ ::msgcat::mcset kok PM "\u0915\u094d\u0930\u093f\u0938\u094d\u0924\u0936\u0916\u093e"
+}
diff --git a/library/msgs/kok_in.msg b/library/msgs/kok_in.msg
new file mode 100755
index 0000000..abcb1ff
--- /dev/null
+++ b/library/msgs/kok_in.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset kok_IN DATE_FORMAT "%d %M %Y"
+ ::msgcat::mcset kok_IN TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset kok_IN DATE_TIME_FORMAT "%d %M %Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/kw.msg b/library/msgs/kw.msg
new file mode 100755
index 0000000..aaf79b3
--- /dev/null
+++ b/library/msgs/kw.msg
@@ -0,0 +1,47 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset kw DAYS_OF_WEEK_ABBREV [list \
+ "Sul"\
+ "Lun"\
+ "Mth"\
+ "Mhr"\
+ "Yow"\
+ "Gwe"\
+ "Sad"]
+ ::msgcat::mcset kw DAYS_OF_WEEK_FULL [list \
+ "De Sul"\
+ "De Lun"\
+ "De Merth"\
+ "De Merher"\
+ "De Yow"\
+ "De Gwener"\
+ "De Sadorn"]
+ ::msgcat::mcset kw MONTHS_ABBREV [list \
+ "Gen"\
+ "Whe"\
+ "Mer"\
+ "Ebr"\
+ "Me"\
+ "Evn"\
+ "Gor"\
+ "Est"\
+ "Gwn"\
+ "Hed"\
+ "Du"\
+ "Kev"\
+ ""]
+ ::msgcat::mcset kw MONTHS_FULL [list \
+ "Mys Genver"\
+ "Mys Whevrel"\
+ "Mys Merth"\
+ "Mys Ebrel"\
+ "Mys Me"\
+ "Mys Evan"\
+ "Mys Gortheren"\
+ "Mye Est"\
+ "Mys Gwyngala"\
+ "Mys Hedra"\
+ "Mys Du"\
+ "Mys Kevardhu"\
+ ""]
+}
diff --git a/library/msgs/kw_gb.msg b/library/msgs/kw_gb.msg
new file mode 100755
index 0000000..2967680
--- /dev/null
+++ b/library/msgs/kw_gb.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset kw_GB DATE_FORMAT "%d %B %Y"
+ ::msgcat::mcset kw_GB TIME_FORMAT_12 "%l:%M:%S %P"
+ ::msgcat::mcset kw_GB DATE_TIME_FORMAT "%d %B %Y %l:%M:%S %P %z"
+}
diff --git a/library/msgs/lt.msg b/library/msgs/lt.msg
new file mode 100755
index 0000000..27b0985
--- /dev/null
+++ b/library/msgs/lt.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset lt DAYS_OF_WEEK_ABBREV [list \
+ "Sk"\
+ "Pr"\
+ "An"\
+ "Tr"\
+ "Kt"\
+ "Pn"\
+ "\u0160t"]
+ ::msgcat::mcset lt DAYS_OF_WEEK_FULL [list \
+ "Sekmadienis"\
+ "Pirmadienis"\
+ "Antradienis"\
+ "Tre\u010diadienis"\
+ "Ketvirtadienis"\
+ "Penktadienis"\
+ "\u0160e\u0161tadienis"]
+ ::msgcat::mcset lt MONTHS_ABBREV [list \
+ "Sau"\
+ "Vas"\
+ "Kov"\
+ "Bal"\
+ "Geg"\
+ "Bir"\
+ "Lie"\
+ "Rgp"\
+ "Rgs"\
+ "Spa"\
+ "Lap"\
+ "Grd"\
+ ""]
+ ::msgcat::mcset lt MONTHS_FULL [list \
+ "Sausio"\
+ "Vasario"\
+ "Kovo"\
+ "Baland\u017eio"\
+ "Gegu\u017e\u0117s"\
+ "Bir\u017eelio"\
+ "Liepos"\
+ "Rugpj\u016b\u010dio"\
+ "Rugs\u0117jo"\
+ "Spalio"\
+ "Lapkri\u010dio"\
+ "Gruod\u017eio"\
+ ""]
+ ::msgcat::mcset lt BCE "pr.Kr."
+ ::msgcat::mcset lt CE "po.Kr."
+ ::msgcat::mcset lt DATE_FORMAT "%Y.%m.%e"
+ ::msgcat::mcset lt TIME_FORMAT "%H.%M.%S"
+ ::msgcat::mcset lt DATE_TIME_FORMAT "%Y.%m.%e %H.%M.%S %z"
+}
diff --git a/library/msgs/lv.msg b/library/msgs/lv.msg
new file mode 100755
index 0000000..a037b15
--- /dev/null
+++ b/library/msgs/lv.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset lv DAYS_OF_WEEK_ABBREV [list \
+ "Sv"\
+ "P"\
+ "O"\
+ "T"\
+ "C"\
+ "Pk"\
+ "S"]
+ ::msgcat::mcset lv DAYS_OF_WEEK_FULL [list \
+ "sv\u0113tdiena"\
+ "pirmdiena"\
+ "otrdiena"\
+ "tre\u0161diena"\
+ "ceturdien"\
+ "piektdiena"\
+ "sestdiena"]
+ ::msgcat::mcset lv MONTHS_ABBREV [list \
+ "Jan"\
+ "Feb"\
+ "Mar"\
+ "Apr"\
+ "Maijs"\
+ "J\u016bn"\
+ "J\u016bl"\
+ "Aug"\
+ "Sep"\
+ "Okt"\
+ "Nov"\
+ "Dec"\
+ ""]
+ ::msgcat::mcset lv MONTHS_FULL [list \
+ "janv\u0101ris"\
+ "febru\u0101ris"\
+ "marts"\
+ "apr\u012blis"\
+ "maijs"\
+ "j\u016bnijs"\
+ "j\u016blijs"\
+ "augusts"\
+ "septembris"\
+ "oktobris"\
+ "novembris"\
+ "decembris"\
+ ""]
+ ::msgcat::mcset lv BCE "pm\u0113"
+ ::msgcat::mcset lv CE "m\u0113"
+ ::msgcat::mcset lv DATE_FORMAT "%Y.%e.%m"
+ ::msgcat::mcset lv TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset lv DATE_TIME_FORMAT "%Y.%e.%m %H:%M:%S %z"
+}
diff --git a/library/msgs/mk.msg b/library/msgs/mk.msg
new file mode 100755
index 0000000..41cf60d
--- /dev/null
+++ b/library/msgs/mk.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset mk DAYS_OF_WEEK_ABBREV [list \
+ "\u043d\u0435\u0434."\
+ "\u043f\u043e\u043d."\
+ "\u0432\u0442."\
+ "\u0441\u0440\u0435."\
+ "\u0447\u0435\u0442."\
+ "\u043f\u0435\u0442."\
+ "\u0441\u0430\u0431."]
+ ::msgcat::mcset mk DAYS_OF_WEEK_FULL [list \
+ "\u043d\u0435\u0434\u0435\u043b\u0430"\
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u043d\u0438\u043a"\
+ "\u0432\u0442\u043e\u0440\u043d\u0438\u043a"\
+ "\u0441\u0440\u0435\u0434\u0430"\
+ "\u0447\u0435\u0442\u0432\u0440\u0442\u043e\u043a"\
+ "\u043f\u0435\u0442\u043e\u043a"\
+ "\u0441\u0430\u0431\u043e\u0442\u0430"]
+ ::msgcat::mcset mk MONTHS_ABBREV [list \
+ "\u0458\u0430\u043d."\
+ "\u0444\u0435\u0432."\
+ "\u043c\u0430\u0440."\
+ "\u0430\u043f\u0440."\
+ "\u043c\u0430\u0458."\
+ "\u0458\u0443\u043d."\
+ "\u0458\u0443\u043b."\
+ "\u0430\u0432\u0433."\
+ "\u0441\u0435\u043f\u0442."\
+ "\u043e\u043a\u0442."\
+ "\u043d\u043e\u0435\u043c."\
+ "\u0434\u0435\u043a\u0435\u043c."\
+ ""]
+ ::msgcat::mcset mk MONTHS_FULL [list \
+ "\u0458\u0430\u043d\u0443\u0430\u0440\u0438"\
+ "\u0444\u0435\u0432\u0440\u0443\u0430\u0440\u0438"\
+ "\u043c\u0430\u0440\u0442"\
+ "\u0430\u043f\u0440\u0438\u043b"\
+ "\u043c\u0430\u0458"\
+ "\u0458\u0443\u043d\u0438"\
+ "\u0458\u0443\u043b\u0438"\
+ "\u0430\u0432\u0433\u0443\u0441\u0442"\
+ "\u0441\u0435\u043f\u0442\u0435\u043c\u0432\u0440\u0438"\
+ "\u043e\u043a\u0442\u043e\u043c\u0432\u0440\u0438"\
+ "\u043d\u043e\u0435\u043c\u0432\u0440\u0438"\
+ "\u0434\u0435\u043a\u0435\u043c\u0432\u0440\u0438"\
+ ""]
+ ::msgcat::mcset mk BCE "\u043f\u0440.\u043d.\u0435."
+ ::msgcat::mcset mk CE "\u0430\u0435."
+ ::msgcat::mcset mk DATE_FORMAT "%e.%m.%Y"
+ ::msgcat::mcset mk TIME_FORMAT "%H:%M:%S %z"
+ ::msgcat::mcset mk DATE_TIME_FORMAT "%e.%m.%Y %H:%M:%S %z %z"
+}
diff --git a/library/msgs/mr.msg b/library/msgs/mr.msg
new file mode 100755
index 0000000..cea427a
--- /dev/null
+++ b/library/msgs/mr.msg
@@ -0,0 +1,39 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset mr DAYS_OF_WEEK_FULL [list \
+ "\u0930\u0935\u093f\u0935\u093e\u0930"\
+ "\u0938\u094b\u092e\u0935\u093e\u0930"\
+ "\u092e\u0902\u0917\u0933\u0935\u093e\u0930"\
+ "\u092e\u0902\u0917\u0933\u0935\u093e\u0930"\
+ "\u0917\u0941\u0930\u0941\u0935\u093e\u0930"\
+ "\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930"\
+ "\u0936\u0928\u093f\u0935\u093e\u0930"]
+ ::msgcat::mcset mr MONTHS_ABBREV [list \
+ "\u091c\u093e\u0928\u0947\u0935\u093e\u0930\u0940"\
+ "\u092b\u0947\u092c\u0943\u0935\u093e\u0930\u0940"\
+ "\u092e\u093e\u0930\u094d\u091a"\
+ "\u090f\u092a\u094d\u0930\u093f\u0932"\
+ "\u092e\u0947"\
+ "\u091c\u0942\u0928"\
+ "\u091c\u0941\u0932\u0948"\
+ "\u0913\u0917\u0938\u094d\u091f"\
+ "\u0938\u0947\u092a\u094d\u091f\u0947\u0902\u092c\u0930"\
+ "\u0913\u0915\u094d\u091f\u094b\u092c\u0930"\
+ "\u0928\u094b\u0935\u094d\u0939\u0947\u0902\u092c\u0930"\
+ "\u0921\u093f\u0938\u0947\u0902\u092c\u0930"]
+ ::msgcat::mcset mr MONTHS_FULL [list \
+ "\u091c\u093e\u0928\u0947\u0935\u093e\u0930\u0940"\
+ "\u092b\u0947\u092c\u0943\u0935\u093e\u0930\u0940"\
+ "\u092e\u093e\u0930\u094d\u091a"\
+ "\u090f\u092a\u094d\u0930\u093f\u0932"\
+ "\u092e\u0947"\
+ "\u091c\u0942\u0928"\
+ "\u091c\u0941\u0932\u0948"\
+ "\u0913\u0917\u0938\u094d\u091f"\
+ "\u0938\u0947\u092a\u094d\u091f\u0947\u0902\u092c\u0930"\
+ "\u0913\u0915\u094d\u091f\u094b\u092c\u0930"\
+ "\u0928\u094b\u0935\u094d\u0939\u0947\u0902\u092c\u0930"\
+ "\u0921\u093f\u0938\u0947\u0902\u092c\u0930"]
+ ::msgcat::mcset mr AM "BC"
+ ::msgcat::mcset mr PM "AD"
+}
diff --git a/library/msgs/mr_in.msg b/library/msgs/mr_in.msg
new file mode 100755
index 0000000..1889da5
--- /dev/null
+++ b/library/msgs/mr_in.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset mr_IN DATE_FORMAT "%d %M %Y"
+ ::msgcat::mcset mr_IN TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset mr_IN DATE_TIME_FORMAT "%d %M %Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/ms.msg b/library/msgs/ms.msg
new file mode 100755
index 0000000..e954431
--- /dev/null
+++ b/library/msgs/ms.msg
@@ -0,0 +1,47 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset ms DAYS_OF_WEEK_ABBREV [list \
+ "Aha"\
+ "Isn"\
+ "Sei"\
+ "Rab"\
+ "Kha"\
+ "Jum"\
+ "Sab"]
+ ::msgcat::mcset ms DAYS_OF_WEEK_FULL [list \
+ "Ahad"\
+ "Isnin"\
+ "Selasa"\
+ "Rahu"\
+ "Khamis"\
+ "Jumaat"\
+ "Sabtu"]
+ ::msgcat::mcset ms MONTHS_ABBREV [list \
+ "Jan"\
+ "Feb"\
+ "Mac"\
+ "Apr"\
+ "Mei"\
+ "Jun"\
+ "Jul"\
+ "Ogos"\
+ "Sep"\
+ "Okt"\
+ "Nov"\
+ "Dis"\
+ ""]
+ ::msgcat::mcset ms MONTHS_FULL [list \
+ "Januari"\
+ "Februari"\
+ "Mac"\
+ "April"\
+ "Mei"\
+ "Jun"\
+ "Julai"\
+ "Ogos"\
+ "September"\
+ "Oktober"\
+ "November"\
+ "Disember"\
+ ""]
+}
diff --git a/library/msgs/ms_my.msg b/library/msgs/ms_my.msg
new file mode 100755
index 0000000..c1f93d4
--- /dev/null
+++ b/library/msgs/ms_my.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset ms_MY DATE_FORMAT "%A %d %b %Y"
+ ::msgcat::mcset ms_MY TIME_FORMAT_12 "%I:%M:%S %z"
+ ::msgcat::mcset ms_MY DATE_TIME_FORMAT "%A %d %b %Y %I:%M:%S %z %z"
+}
diff --git a/library/msgs/mt.msg b/library/msgs/mt.msg
new file mode 100755
index 0000000..ddd5446
--- /dev/null
+++ b/library/msgs/mt.msg
@@ -0,0 +1,27 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset mt DAYS_OF_WEEK_ABBREV [list \
+ "\u0126ad"\
+ "Tne"\
+ "Tli"\
+ "Erb"\
+ "\u0126am"\
+ "\u0120im"]
+ ::msgcat::mcset mt MONTHS_ABBREV [list \
+ "Jan"\
+ "Fra"\
+ "Mar"\
+ "Apr"\
+ "Mej"\
+ "\u0120un"\
+ "Lul"\
+ "Awi"\
+ "Set"\
+ "Ott"\
+ "Nov"]
+ ::msgcat::mcset mt BCE "QK"
+ ::msgcat::mcset mt CE ""
+ ::msgcat::mcset mt DATE_FORMAT "%A, %e ta %B, %Y"
+ ::msgcat::mcset mt TIME_FORMAT_12 "%l:%M:%S %P"
+ ::msgcat::mcset mt DATE_TIME_FORMAT "%A, %e ta %B, %Y %l:%M:%S %P %z"
+}
diff --git a/library/msgs/nb.msg b/library/msgs/nb.msg
new file mode 100755
index 0000000..90d49a3
--- /dev/null
+++ b/library/msgs/nb.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset nb DAYS_OF_WEEK_ABBREV [list \
+ "s\u00f8"\
+ "ma"\
+ "ti"\
+ "on"\
+ "to"\
+ "fr"\
+ "l\u00f8"]
+ ::msgcat::mcset nb DAYS_OF_WEEK_FULL [list \
+ "s\u00f8ndag"\
+ "mandag"\
+ "tirsdag"\
+ "onsdag"\
+ "torsdag"\
+ "fredag"\
+ "l\u00f8rdag"]
+ ::msgcat::mcset nb MONTHS_ABBREV [list \
+ "jan"\
+ "feb"\
+ "mar"\
+ "apr"\
+ "mai"\
+ "jun"\
+ "jul"\
+ "aug"\
+ "sep"\
+ "okt"\
+ "nov"\
+ "des"\
+ ""]
+ ::msgcat::mcset nb MONTHS_FULL [list \
+ "januar"\
+ "februar"\
+ "mars"\
+ "april"\
+ "mai"\
+ "juni"\
+ "juli"\
+ "august"\
+ "september"\
+ "oktober"\
+ "november"\
+ "desember"\
+ ""]
+ ::msgcat::mcset nb BCE "f.Kr."
+ ::msgcat::mcset nb CE "e.Kr."
+ ::msgcat::mcset nb DATE_FORMAT "%e. %B %Y"
+ ::msgcat::mcset nb TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset nb DATE_TIME_FORMAT "%e. %B %Y %H:%M:%S %z"
+}
diff --git a/library/msgs/nl.msg b/library/msgs/nl.msg
new file mode 100755
index 0000000..4c5c675
--- /dev/null
+++ b/library/msgs/nl.msg
@@ -0,0 +1,50 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset nl DAYS_OF_WEEK_ABBREV [list \
+ "zo"\
+ "ma"\
+ "di"\
+ "wo"\
+ "do"\
+ "vr"\
+ "za"]
+ ::msgcat::mcset nl DAYS_OF_WEEK_FULL [list \
+ "zondag"\
+ "maandag"\
+ "dinsdag"\
+ "woensdag"\
+ "donderdag"\
+ "vrijdag"\
+ "zaterdag"]
+ ::msgcat::mcset nl MONTHS_ABBREV [list \
+ "jan"\
+ "feb"\
+ "mrt"\
+ "apr"\
+ "mei"\
+ "jun"\
+ "jul"\
+ "aug"\
+ "sep"\
+ "okt"\
+ "nov"\
+ "dec"\
+ ""]
+ ::msgcat::mcset nl MONTHS_FULL [list \
+ "januari"\
+ "februari"\
+ "maart"\
+ "april"\
+ "mei"\
+ "juni"\
+ "juli"\
+ "augustus"\
+ "september"\
+ "oktober"\
+ "november"\
+ "december"\
+ ""]
+ ::msgcat::mcset nl DATE_FORMAT "%e %B %Y"
+ ::msgcat::mcset nl TIME_FORMAT "%k:%M:%S"
+ ::msgcat::mcset nl DATE_TIME_FORMAT "%e %B %Y %k:%M:%S %z"
+}
diff --git a/library/msgs/nl_be.msg b/library/msgs/nl_be.msg
new file mode 100755
index 0000000..4b19670
--- /dev/null
+++ b/library/msgs/nl_be.msg
@@ -0,0 +1,7 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset nl_BE DATE_FORMAT "%d-%m-%y"
+ ::msgcat::mcset nl_BE TIME_FORMAT "%T"
+ ::msgcat::mcset nl_BE TIME_FORMAT_12 "%T"
+ ::msgcat::mcset nl_BE DATE_TIME_FORMAT "%a %d %b %Y %T %z"
+}
diff --git a/library/msgs/nn.msg b/library/msgs/nn.msg
new file mode 100755
index 0000000..bd61ac9
--- /dev/null
+++ b/library/msgs/nn.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset nn DAYS_OF_WEEK_ABBREV [list \
+ "su"\
+ "m\u00e5"\
+ "ty"\
+ "on"\
+ "to"\
+ "fr"\
+ "lau"]
+ ::msgcat::mcset nn DAYS_OF_WEEK_FULL [list \
+ "sundag"\
+ "m\u00e5ndag"\
+ "tysdag"\
+ "onsdag"\
+ "torsdag"\
+ "fredag"\
+ "laurdag"]
+ ::msgcat::mcset nn MONTHS_ABBREV [list \
+ "jan"\
+ "feb"\
+ "mar"\
+ "apr"\
+ "mai"\
+ "jun"\
+ "jul"\
+ "aug"\
+ "sep"\
+ "okt"\
+ "nov"\
+ "des"\
+ ""]
+ ::msgcat::mcset nn MONTHS_FULL [list \
+ "januar"\
+ "februar"\
+ "mars"\
+ "april"\
+ "mai"\
+ "juni"\
+ "juli"\
+ "august"\
+ "september"\
+ "oktober"\
+ "november"\
+ "desember"\
+ ""]
+ ::msgcat::mcset nn BCE "f.Kr."
+ ::msgcat::mcset nn CE "e.Kr."
+ ::msgcat::mcset nn DATE_FORMAT "%e. %B %Y"
+ ::msgcat::mcset nn TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset nn DATE_TIME_FORMAT "%e. %B %Y %H:%M:%S %z"
+}
diff --git a/library/msgs/pl.msg b/library/msgs/pl.msg
new file mode 100755
index 0000000..d206f4b
--- /dev/null
+++ b/library/msgs/pl.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset pl DAYS_OF_WEEK_ABBREV [list \
+ "N"\
+ "Pn"\
+ "Wt"\
+ "\u015ar"\
+ "Cz"\
+ "Pt"\
+ "So"]
+ ::msgcat::mcset pl DAYS_OF_WEEK_FULL [list \
+ "niedziela"\
+ "poniedzia\u0142ek"\
+ "wtorek"\
+ "\u015broda"\
+ "czwartek"\
+ "pi\u0105tek"\
+ "sobota"]
+ ::msgcat::mcset pl MONTHS_ABBREV [list \
+ "sty"\
+ "lut"\
+ "mar"\
+ "kwi"\
+ "maj"\
+ "cze"\
+ "lip"\
+ "sie"\
+ "wrz"\
+ "pa\u017a"\
+ "lis"\
+ "gru"\
+ ""]
+ ::msgcat::mcset pl MONTHS_FULL [list \
+ "stycze\u0144"\
+ "luty"\
+ "marzec"\
+ "kwiecie\u0144"\
+ "maj"\
+ "czerwiec"\
+ "lipiec"\
+ "sierpie\u0144"\
+ "wrzesie\u0144"\
+ "pa\u017adziernik"\
+ "listopad"\
+ "grudzie\u0144"\
+ ""]
+ ::msgcat::mcset pl BCE "p.n.e."
+ ::msgcat::mcset pl CE "n.e."
+ ::msgcat::mcset pl DATE_FORMAT "%Y-%m-%d"
+ ::msgcat::mcset pl TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset pl DATE_TIME_FORMAT "%Y-%m-%d %H:%M:%S %z"
+}
diff --git a/library/msgs/pt.msg b/library/msgs/pt.msg
new file mode 100755
index 0000000..96fdb35
--- /dev/null
+++ b/library/msgs/pt.msg
@@ -0,0 +1,50 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset pt DAYS_OF_WEEK_ABBREV [list \
+ "Dom"\
+ "Seg"\
+ "Ter"\
+ "Qua"\
+ "Qui"\
+ "Sex"\
+ "S\u00e1b"]
+ ::msgcat::mcset pt DAYS_OF_WEEK_FULL [list \
+ "Domingo"\
+ "Segunda-feira"\
+ "Ter\u00e7a-feira"\
+ "Quarta-feira"\
+ "Quinta-feira"\
+ "Sexta-feira"\
+ "S\u00e1bado"]
+ ::msgcat::mcset pt MONTHS_ABBREV [list \
+ "Jan"\
+ "Fev"\
+ "Mar"\
+ "Abr"\
+ "Mai"\
+ "Jun"\
+ "Jul"\
+ "Ago"\
+ "Set"\
+ "Out"\
+ "Nov"\
+ "Dez"\
+ ""]
+ ::msgcat::mcset pt MONTHS_FULL [list \
+ "Janeiro"\
+ "Fevereiro"\
+ "Mar\u00e7o"\
+ "Abril"\
+ "Maio"\
+ "Junho"\
+ "Julho"\
+ "Agosto"\
+ "Setembro"\
+ "Outubro"\
+ "Novembro"\
+ "Dezembro"\
+ ""]
+ ::msgcat::mcset pt DATE_FORMAT "%d-%m-%Y"
+ ::msgcat::mcset pt TIME_FORMAT "%k:%M:%S"
+ ::msgcat::mcset pt DATE_TIME_FORMAT "%d-%m-%Y %k:%M:%S %z"
+}
diff --git a/library/msgs/pt_br.msg b/library/msgs/pt_br.msg
new file mode 100755
index 0000000..8684327
--- /dev/null
+++ b/library/msgs/pt_br.msg
@@ -0,0 +1,7 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset pt_BR DATE_FORMAT "%d-%m-%Y"
+ ::msgcat::mcset pt_BR TIME_FORMAT "%T"
+ ::msgcat::mcset pt_BR TIME_FORMAT_12 "%T"
+ ::msgcat::mcset pt_BR DATE_TIME_FORMAT "%a %d %b %Y %T %z"
+}
diff --git a/library/msgs/ro.msg b/library/msgs/ro.msg
new file mode 100755
index 0000000..bdd7c61
--- /dev/null
+++ b/library/msgs/ro.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset ro DAYS_OF_WEEK_ABBREV [list \
+ "D"\
+ "L"\
+ "Ma"\
+ "Mi"\
+ "J"\
+ "V"\
+ "S"]
+ ::msgcat::mcset ro DAYS_OF_WEEK_FULL [list \
+ "duminic\u0103"\
+ "luni"\
+ "mar\u0163i"\
+ "miercuri"\
+ "joi"\
+ "vineri"\
+ "s\u00eemb\u0103t\u0103"]
+ ::msgcat::mcset ro MONTHS_ABBREV [list \
+ "Ian"\
+ "Feb"\
+ "Mar"\
+ "Apr"\
+ "Mai"\
+ "Iun"\
+ "Iul"\
+ "Aug"\
+ "Sep"\
+ "Oct"\
+ "Nov"\
+ "Dec"\
+ ""]
+ ::msgcat::mcset ro MONTHS_FULL [list \
+ "ianuarie"\
+ "februarie"\
+ "martie"\
+ "aprilie"\
+ "mai"\
+ "iunie"\
+ "iulie"\
+ "august"\
+ "septembrie"\
+ "octombrie"\
+ "noiembrie"\
+ "decembrie"\
+ ""]
+ ::msgcat::mcset ro BCE "d.C."
+ ::msgcat::mcset ro CE "\u00ee.d.C."
+ ::msgcat::mcset ro DATE_FORMAT "%d.%m.%Y"
+ ::msgcat::mcset ro TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset ro DATE_TIME_FORMAT "%d.%m.%Y %H:%M:%S %z"
+}
diff --git a/library/msgs/ru.msg b/library/msgs/ru.msg
new file mode 100755
index 0000000..65b075d
--- /dev/null
+++ b/library/msgs/ru.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset ru DAYS_OF_WEEK_ABBREV [list \
+ "\u0412\u0441"\
+ "\u041f\u043d"\
+ "\u0412\u0442"\
+ "\u0421\u0440"\
+ "\u0427\u0442"\
+ "\u041f\u0442"\
+ "\u0421\u0431"]
+ ::msgcat::mcset ru DAYS_OF_WEEK_FULL [list \
+ "\u0432\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435"\
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a"\
+ "\u0432\u0442\u043e\u0440\u043d\u0438\u043a"\
+ "\u0441\u0440\u0435\u0434\u0430"\
+ "\u0447\u0435\u0442\u0432\u0435\u0440\u0433"\
+ "\u043f\u044f\u0442\u043d\u0438\u0446\u0430"\
+ "\u0441\u0443\u0431\u0431\u043e\u0442\u0430"]
+ ::msgcat::mcset ru MONTHS_ABBREV [list \
+ "\u044f\u043d\u0432"\
+ "\u0444\u0435\u0432"\
+ "\u043c\u0430\u0440"\
+ "\u0430\u043f\u0440"\
+ "\u043c\u0430\u0439"\
+ "\u0438\u044e\u043d"\
+ "\u0438\u044e\u043b"\
+ "\u0430\u0432\u0433"\
+ "\u0441\u0435\u043d"\
+ "\u043e\u043a\u0442"\
+ "\u043d\u043e\u044f"\
+ "\u0434\u0435\u043a"\
+ ""]
+ ::msgcat::mcset ru MONTHS_FULL [list \
+ "\u042f\u043d\u0432\u0430\u0440\u044c"\
+ "\u0424\u0435\u0432\u0440\u0430\u043b\u044c"\
+ "\u041c\u0430\u0440\u0442"\
+ "\u0410\u043f\u0440\u0435\u043b\u044c"\
+ "\u041c\u0430\u0439"\
+ "\u0418\u044e\u043d\u044c"\
+ "\u0418\u044e\u043b\u044c"\
+ "\u0410\u0432\u0433\u0443\u0441\u0442"\
+ "\u0421\u0435\u043d\u0442\u044f\u0431\u0440\u044c"\
+ "\u041e\u043a\u0442\u044f\u0431\u0440\u044c"\
+ "\u041d\u043e\u044f\u0431\u0440\u044c"\
+ "\u0414\u0435\u043a\u0430\u0431\u0440\u044c"\
+ ""]
+ ::msgcat::mcset ru BCE "\u0434\u043e \u043d.\u044d."
+ ::msgcat::mcset ru CE "\u043d.\u044d."
+ ::msgcat::mcset ru DATE_FORMAT "%d.%m.%Y"
+ ::msgcat::mcset ru TIME_FORMAT "%k:%M:%S"
+ ::msgcat::mcset ru DATE_TIME_FORMAT "%d.%m.%Y %k:%M:%S %z"
+}
diff --git a/library/msgs/ru_ua.msg b/library/msgs/ru_ua.msg
new file mode 100755
index 0000000..6e1f8a8
--- /dev/null
+++ b/library/msgs/ru_ua.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset ru_UA DATE_FORMAT "%d.%m.%Y"
+ ::msgcat::mcset ru_UA TIME_FORMAT "%k:%M:%S"
+ ::msgcat::mcset ru_UA DATE_TIME_FORMAT "%d.%m.%Y %k:%M:%S %z"
+}
diff --git a/library/msgs/sh.msg b/library/msgs/sh.msg
new file mode 100755
index 0000000..6ee0fc7
--- /dev/null
+++ b/library/msgs/sh.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset sh DAYS_OF_WEEK_ABBREV [list \
+ "Ned"\
+ "Pon"\
+ "Uto"\
+ "Sre"\
+ "\u010cet"\
+ "Pet"\
+ "Sub"]
+ ::msgcat::mcset sh DAYS_OF_WEEK_FULL [list \
+ "Nedelja"\
+ "Ponedeljak"\
+ "Utorak"\
+ "Sreda"\
+ "\u010cetvrtak"\
+ "Petak"\
+ "Subota"]
+ ::msgcat::mcset sh MONTHS_ABBREV [list \
+ "Jan"\
+ "Feb"\
+ "Mar"\
+ "Apr"\
+ "Maj"\
+ "Jun"\
+ "Jul"\
+ "Avg"\
+ "Sep"\
+ "Okt"\
+ "Nov"\
+ "Dec"\
+ ""]
+ ::msgcat::mcset sh MONTHS_FULL [list \
+ "Januar"\
+ "Februar"\
+ "Mart"\
+ "April"\
+ "Maj"\
+ "Juni"\
+ "Juli"\
+ "Avgust"\
+ "Septembar"\
+ "Oktobar"\
+ "Novembar"\
+ "Decembar"\
+ ""]
+ ::msgcat::mcset sh BCE "p. n. e."
+ ::msgcat::mcset sh CE "n. e."
+ ::msgcat::mcset sh DATE_FORMAT "%d.%m.%Y."
+ ::msgcat::mcset sh TIME_FORMAT "%k.%M.%S"
+ ::msgcat::mcset sh DATE_TIME_FORMAT "%d.%m.%Y. %k.%M.%S %z"
+}
diff --git a/library/msgs/sk.msg b/library/msgs/sk.msg
new file mode 100755
index 0000000..9b2f0aa
--- /dev/null
+++ b/library/msgs/sk.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset sk DAYS_OF_WEEK_ABBREV [list \
+ "Ne"\
+ "Po"\
+ "Ut"\
+ "St"\
+ "\u0160t"\
+ "Pa"\
+ "So"]
+ ::msgcat::mcset sk DAYS_OF_WEEK_FULL [list \
+ "Nede\u013ee"\
+ "Pondelok"\
+ "Utorok"\
+ "Streda"\
+ "\u0160tvrtok"\
+ "Piatok"\
+ "Sobota"]
+ ::msgcat::mcset sk MONTHS_ABBREV [list \
+ "jan"\
+ "feb"\
+ "mar"\
+ "apr"\
+ "m\u00e1j"\
+ "j\u00fan"\
+ "j\u00fal"\
+ "aug"\
+ "sep"\
+ "okt"\
+ "nov"\
+ "dec"\
+ ""]
+ ::msgcat::mcset sk MONTHS_FULL [list \
+ "janu\u00e1r"\
+ "febru\u00e1r"\
+ "marec"\
+ "apr\u00edl"\
+ "m\u00e1j"\
+ "j\u00fan"\
+ "j\u00fal"\
+ "august"\
+ "september"\
+ "okt\u00f3ber"\
+ "november"\
+ "december"\
+ ""]
+ ::msgcat::mcset sk BCE "pred n.l."
+ ::msgcat::mcset sk CE "n.l."
+ ::msgcat::mcset sk DATE_FORMAT "%e.%m.%Y"
+ ::msgcat::mcset sk TIME_FORMAT "%k:%M:%S"
+ ::msgcat::mcset sk DATE_TIME_FORMAT "%e.%m.%Y %k:%M:%S %z"
+}
diff --git a/library/msgs/sl.msg b/library/msgs/sl.msg
new file mode 100755
index 0000000..42bc509
--- /dev/null
+++ b/library/msgs/sl.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset sl DAYS_OF_WEEK_ABBREV [list \
+ "Ned"\
+ "Pon"\
+ "Tor"\
+ "Sre"\
+ "\u010cet"\
+ "Pet"\
+ "Sob"]
+ ::msgcat::mcset sl DAYS_OF_WEEK_FULL [list \
+ "Nedelja"\
+ "Ponedeljek"\
+ "Torek"\
+ "Sreda"\
+ "\u010cetrtek"\
+ "Petek"\
+ "Sobota"]
+ ::msgcat::mcset sl MONTHS_ABBREV [list \
+ "jan"\
+ "feb"\
+ "mar"\
+ "apr"\
+ "maj"\
+ "jun"\
+ "jul"\
+ "avg"\
+ "sep"\
+ "okt"\
+ "nov"\
+ "dec"\
+ ""]
+ ::msgcat::mcset sl MONTHS_FULL [list \
+ "januar"\
+ "februar"\
+ "marec"\
+ "april"\
+ "maj"\
+ "junij"\
+ "julij"\
+ "avgust"\
+ "september"\
+ "oktober"\
+ "november"\
+ "december"\
+ ""]
+ ::msgcat::mcset sl BCE "pr.n.\u0161."
+ ::msgcat::mcset sl CE "po Kr."
+ ::msgcat::mcset sl DATE_FORMAT "%Y.%m.%e"
+ ::msgcat::mcset sl TIME_FORMAT "%k:%M:%S"
+ ::msgcat::mcset sl DATE_TIME_FORMAT "%Y.%m.%e %k:%M:%S %z"
+}
diff --git a/library/msgs/sq.msg b/library/msgs/sq.msg
new file mode 100755
index 0000000..8fb1fce
--- /dev/null
+++ b/library/msgs/sq.msg
@@ -0,0 +1,54 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset sq DAYS_OF_WEEK_ABBREV [list \
+ "Die"\
+ "H\u00ebn"\
+ "Mar"\
+ "M\u00ebr"\
+ "Enj"\
+ "Pre"\
+ "Sht"]
+ ::msgcat::mcset sq DAYS_OF_WEEK_FULL [list \
+ "e diel"\
+ "e h\u00ebn\u00eb"\
+ "e mart\u00eb"\
+ "e m\u00ebrkur\u00eb"\
+ "e enjte"\
+ "e premte"\
+ "e shtun\u00eb"]
+ ::msgcat::mcset sq MONTHS_ABBREV [list \
+ "Jan"\
+ "Shk"\
+ "Mar"\
+ "Pri"\
+ "Maj"\
+ "Qer"\
+ "Kor"\
+ "Gsh"\
+ "Sht"\
+ "Tet"\
+ "N\u00ebn"\
+ "Dhj"\
+ ""]
+ ::msgcat::mcset sq MONTHS_FULL [list \
+ "janar"\
+ "shkurt"\
+ "mars"\
+ "prill"\
+ "maj"\
+ "qershor"\
+ "korrik"\
+ "gusht"\
+ "shtator"\
+ "tetor"\
+ "n\u00ebntor"\
+ "dhjetor"\
+ ""]
+ ::msgcat::mcset sq BCE "p.e.r."
+ ::msgcat::mcset sq CE "n.e.r."
+ ::msgcat::mcset sq AM "PD"
+ ::msgcat::mcset sq PM "MD"
+ ::msgcat::mcset sq DATE_FORMAT "%Y-%m-%d"
+ ::msgcat::mcset sq TIME_FORMAT_12 "%l:%M:%S.%P"
+ ::msgcat::mcset sq DATE_TIME_FORMAT "%Y-%m-%d %l:%M:%S.%P %z"
+}
diff --git a/library/msgs/sr.msg b/library/msgs/sr.msg
new file mode 100755
index 0000000..7576668
--- /dev/null
+++ b/library/msgs/sr.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset sr DAYS_OF_WEEK_ABBREV [list \
+ "\u041d\u0435\u0434"\
+ "\u041f\u043e\u043d"\
+ "\u0423\u0442\u043e"\
+ "\u0421\u0440\u0435"\
+ "\u0427\u0435\u0442"\
+ "\u041f\u0435\u0442"\
+ "\u0421\u0443\u0431"]
+ ::msgcat::mcset sr DAYS_OF_WEEK_FULL [list \
+ "\u041d\u0435\u0434\u0435\u0459\u0430"\
+ "\u041f\u043e\u043d\u0435\u0434\u0435\u0459\u0430\u043a"\
+ "\u0423\u0442\u043e\u0440\u0430\u043a"\
+ "\u0421\u0440\u0435\u0434\u0430"\
+ "\u0427\u0435\u0442\u0432\u0440\u0442\u0430\u043a"\
+ "\u041f\u0435\u0442\u0430\u043a"\
+ "\u0421\u0443\u0431\u043e\u0442\u0430"]
+ ::msgcat::mcset sr MONTHS_ABBREV [list \
+ "\u0408\u0430\u043d"\
+ "\u0424\u0435\u0431"\
+ "\u041c\u0430\u0440"\
+ "\u0410\u043f\u0440"\
+ "\u041c\u0430\u0458"\
+ "\u0408\u0443\u043d"\
+ "\u0408\u0443\u043b"\
+ "\u0410\u0432\u0433"\
+ "\u0421\u0435\u043f"\
+ "\u041e\u043a\u0442"\
+ "\u041d\u043e\u0432"\
+ "\u0414\u0435\u0446"\
+ ""]
+ ::msgcat::mcset sr MONTHS_FULL [list \
+ "\u0408\u0430\u043d\u0443\u0430\u0440"\
+ "\u0424\u0435\u0431\u0440\u0443\u0430\u0440"\
+ "\u041c\u0430\u0440\u0442"\
+ "\u0410\u043f\u0440\u0438\u043b"\
+ "\u041c\u0430\u0458"\
+ "\u0408\u0443\u043d\u0438"\
+ "\u0408\u0443\u043b\u0438"\
+ "\u0410\u0432\u0433\u0443\u0441\u0442"\
+ "\u0421\u0435\u043f\u0442\u0435\u043c\u0431\u0430\u0440"\
+ "\u041e\u043a\u0442\u043e\u0431\u0430\u0440"\
+ "\u041d\u043e\u0432\u0435\u043c\u0431\u0430\u0440"\
+ "\u0414\u0435\u0446\u0435\u043c\u0431\u0430\u0440"\
+ ""]
+ ::msgcat::mcset sr BCE "\u043f. \u043d. \u0435."
+ ::msgcat::mcset sr CE "\u043d. \u0435"
+ ::msgcat::mcset sr DATE_FORMAT "%Y.%m.%e"
+ ::msgcat::mcset sr TIME_FORMAT "%k.%M.%S"
+ ::msgcat::mcset sr DATE_TIME_FORMAT "%Y.%m.%e %k.%M.%S %z"
+}
diff --git a/library/msgs/sv.msg b/library/msgs/sv.msg
new file mode 100755
index 0000000..f7a67c6
--- /dev/null
+++ b/library/msgs/sv.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset sv DAYS_OF_WEEK_ABBREV [list \
+ "s\u00f6"\
+ "m\u00e5"\
+ "ti"\
+ "on"\
+ "to"\
+ "fr"\
+ "l\u00f6"]
+ ::msgcat::mcset sv DAYS_OF_WEEK_FULL [list \
+ "s\u00f6ndag"\
+ "m\u00e5ndag"\
+ "tisdag"\
+ "onsdag"\
+ "torsdag"\
+ "fredag"\
+ "l\u00f6rdag"]
+ ::msgcat::mcset sv MONTHS_ABBREV [list \
+ "jan"\
+ "feb"\
+ "mar"\
+ "apr"\
+ "maj"\
+ "jun"\
+ "jul"\
+ "aug"\
+ "sep"\
+ "okt"\
+ "nov"\
+ "dec"\
+ ""]
+ ::msgcat::mcset sv MONTHS_FULL [list \
+ "januari"\
+ "februari"\
+ "mars"\
+ "april"\
+ "maj"\
+ "juni"\
+ "juli"\
+ "augusti"\
+ "september"\
+ "oktober"\
+ "november"\
+ "december"\
+ ""]
+ ::msgcat::mcset sv BCE "f.Kr."
+ ::msgcat::mcset sv CE "e.Kr."
+ ::msgcat::mcset sv DATE_FORMAT "%Y-%m-%d"
+ ::msgcat::mcset sv TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset sv DATE_TIME_FORMAT "%Y-%m-%d %H:%M:%S %z"
+}
diff --git a/library/msgs/sw.msg b/library/msgs/sw.msg
new file mode 100755
index 0000000..b888b43
--- /dev/null
+++ b/library/msgs/sw.msg
@@ -0,0 +1,49 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset sw DAYS_OF_WEEK_ABBREV [list \
+ "Jpi"\
+ "Jtt"\
+ "Jnn"\
+ "Jtn"\
+ "Alh"\
+ "Iju"\
+ "Jmo"]
+ ::msgcat::mcset sw DAYS_OF_WEEK_FULL [list \
+ "Jumapili"\
+ "Jumatatu"\
+ "Jumanne"\
+ "Jumatano"\
+ "Alhamisi"\
+ "Ijumaa"\
+ "Jumamosi"]
+ ::msgcat::mcset sw MONTHS_ABBREV [list \
+ "Jan"\
+ "Feb"\
+ "Mar"\
+ "Apr"\
+ "Mei"\
+ "Jun"\
+ "Jul"\
+ "Ago"\
+ "Sep"\
+ "Okt"\
+ "Nov"\
+ "Des"\
+ ""]
+ ::msgcat::mcset sw MONTHS_FULL [list \
+ "Januari"\
+ "Februari"\
+ "Machi"\
+ "Aprili"\
+ "Mei"\
+ "Juni"\
+ "Julai"\
+ "Agosti"\
+ "Septemba"\
+ "Oktoba"\
+ "Novemba"\
+ "Desemba"\
+ ""]
+ ::msgcat::mcset sw BCE "KK"
+ ::msgcat::mcset sw CE "BK"
+}
diff --git a/library/msgs/ta.msg b/library/msgs/ta.msg
new file mode 100755
index 0000000..4abb90c
--- /dev/null
+++ b/library/msgs/ta.msg
@@ -0,0 +1,39 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset ta DAYS_OF_WEEK_FULL [list \
+ "\u0b9e\u0bbe\u0baf\u0bbf\u0bb1\u0bc1"\
+ "\u0ba4\u0bbf\u0b99\u0bcd\u0b95\u0bb3\u0bcd"\
+ "\u0b9a\u0bc6\u0bb5\u0bcd\u0bb5\u0bbe\u0baf\u0bcd"\
+ "\u0baa\u0bc1\u0ba4\u0ba9\u0bcd"\
+ "\u0bb5\u0bbf\u0baf\u0bbe\u0bb4\u0ba9\u0bcd"\
+ "\u0bb5\u0bc6\u0bb3\u0bcd\u0bb3\u0bbf"\
+ "\u0b9a\u0ba9\u0bbf"]
+ ::msgcat::mcset ta MONTHS_ABBREV [list \
+ "\u0b9c\u0ba9\u0bb5\u0bb0\u0bbf"\
+ "\u0baa\u0bc6\u0baa\u0bcd\u0bb0\u0bb5\u0bb0\u0bbf"\
+ "\u0bae\u0bbe\u0bb0\u0bcd\u0b9a\u0bcd"\
+ "\u0b8f\u0baa\u0bcd\u0bb0\u0bb2\u0bcd"\
+ "\u0bae\u0bc7"\
+ "\u0b9c\u0bc2\u0ba9\u0bcd"\
+ "\u0b9c\u0bc2\u0bb2\u0bc8"\
+ "\u0b86\u0b95\u0bb8\u0bcd\u0b9f\u0bcd"\
+ "\u0b9a\u0bc6\u0baa\u0bcd\u0b9f\u0bae\u0bcd\u0baa\u0bb0\u0bcd"\
+ "\u0b85\u0b95\u0bcd\u0b9f\u0bcb\u0baa\u0bb0\u0bcd"\
+ "\u0ba8\u0bb5\u0bae\u0bcd\u0baa\u0bb0\u0bcd"\
+ "\u0b9f\u0bbf\u0b9a\u0bae\u0bcd\u0baa\u0bb0\u0bcdr"]
+ ::msgcat::mcset ta MONTHS_FULL [list \
+ "\u0b9c\u0ba9\u0bb5\u0bb0\u0bbf"\
+ "\u0baa\u0bc6\u0baa\u0bcd\u0bb0\u0bb5\u0bb0\u0bbf"\
+ "\u0bae\u0bbe\u0bb0\u0bcd\u0b9a\u0bcd"\
+ "\u0b8f\u0baa\u0bcd\u0bb0\u0bb2\u0bcd"\
+ "\u0bae\u0bc7"\
+ "\u0b9c\u0bc2\u0ba9\u0bcd"\
+ "\u0b9c\u0bc2\u0bb2\u0bc8"\
+ "\u0b86\u0b95\u0bb8\u0bcd\u0b9f\u0bcd"\
+ "\u0b9a\u0bc6\u0baa\u0bcd\u0b9f\u0bae\u0bcd\u0baa\u0bb0\u0bcd"\
+ "\u0b85\u0b95\u0bcd\u0b9f\u0bcb\u0baa\u0bb0\u0bcd"\
+ "\u0ba8\u0bb5\u0bae\u0bcd\u0baa\u0bb0\u0bcd"\
+ "\u0b9f\u0bbf\u0b9a\u0bae\u0bcd\u0baa\u0bb0\u0bcdr"]
+ ::msgcat::mcset ta AM "\u0b95\u0bbf\u0bae\u0bc1"
+ ::msgcat::mcset ta PM "\u0b95\u0bbf\u0baa\u0bbf"
+}
diff --git a/library/msgs/ta_in.msg b/library/msgs/ta_in.msg
new file mode 100755
index 0000000..24590ac
--- /dev/null
+++ b/library/msgs/ta_in.msg
@@ -0,0 +1,6 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset ta_IN DATE_FORMAT "%d %M %Y"
+ ::msgcat::mcset ta_IN TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset ta_IN DATE_TIME_FORMAT "%d %M %Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/te.msg b/library/msgs/te.msg
new file mode 100755
index 0000000..6111473
--- /dev/null
+++ b/library/msgs/te.msg
@@ -0,0 +1,47 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset te DAYS_OF_WEEK_ABBREV [list \
+ "\u0c06\u0c26\u0c3f"\
+ "\u0c38\u0c4b\u0c2e"\
+ "\u0c2e\u0c02\u0c17\u0c33"\
+ "\u0c2c\u0c41\u0c27"\
+ "\u0c17\u0c41\u0c30\u0c41"\
+ "\u0c36\u0c41\u0c15\u0c4d\u0c30"\
+ "\u0c36\u0c28\u0c3f"]
+ ::msgcat::mcset te DAYS_OF_WEEK_FULL [list \
+ "\u0c06\u0c26\u0c3f\u0c35\u0c3e\u0c30\u0c02"\
+ "\u0c38\u0c4b\u0c2e\u0c35\u0c3e\u0c30\u0c02"\
+ "\u0c2e\u0c02\u0c17\u0c33\u0c35\u0c3e\u0c30\u0c02"\
+ "\u0c2c\u0c41\u0c27\u0c35\u0c3e\u0c30\u0c02"\
+ "\u0c17\u0c41\u0c30\u0c41\u0c35\u0c3e\u0c30\u0c02"\
+ "\u0c36\u0c41\u0c15\u0c4d\u0c30\u0c35\u0c3e\u0c30\u0c02"\
+ "\u0c36\u0c28\u0c3f\u0c35\u0c3e\u0c30\u0c02"]
+ ::msgcat::mcset te MONTHS_ABBREV [list \
+ "\u0c1c\u0c28\u0c35\u0c30\u0c3f"\
+ "\u0c2b\u0c3f\u0c2c\u0c4d\u0c30\u0c35\u0c30\u0c3f"\
+ "\u0c2e\u0c3e\u0c30\u0c4d\u0c1a\u0c3f"\
+ "\u0c0f\u0c2a\u0c4d\u0c30\u0c3f\u0c32\u0c4d"\
+ "\u0c2e\u0c47"\
+ "\u0c1c\u0c42\u0c28\u0c4d"\
+ "\u0c1c\u0c42\u0c32\u0c48"\
+ "\u0c06\u0c17\u0c38\u0c4d\u0c1f\u0c41"\
+ "\u0c38\u0c46\u0c2a\u0c4d\u0c1f\u0c46\u0c02\u0c2c\u0c30\u0c4d"\
+ "\u0c05\u0c15\u0c4d\u0c1f\u0c4b\u0c2c\u0c30\u0c4d"\
+ "\u0c28\u0c35\u0c02\u0c2c\u0c30\u0c4d"\
+ "\u0c21\u0c3f\u0c38\u0c46\u0c02\u0c2c\u0c30\u0c4d"\
+ ""]
+ ::msgcat::mcset te MONTHS_FULL [list \
+ "\u0c1c\u0c28\u0c35\u0c30\u0c3f"\
+ "\u0c2b\u0c3f\u0c2c\u0c4d\u0c30\u0c35\u0c30\u0c3f"\
+ "\u0c2e\u0c3e\u0c30\u0c4d\u0c1a\u0c3f"\
+ "\u0c0f\u0c2a\u0c4d\u0c30\u0c3f\u0c32\u0c4d"\
+ "\u0c2e\u0c47"\
+ "\u0c1c\u0c42\u0c28\u0c4d"\
+ "\u0c1c\u0c42\u0c32\u0c48"\
+ "\u0c06\u0c17\u0c38\u0c4d\u0c1f\u0c41"\
+ "\u0c38\u0c46\u0c2a\u0c4d\u0c1f\u0c46\u0c02\u0c2c\u0c30\u0c4d"\
+ "\u0c05\u0c15\u0c4d\u0c1f\u0c4b\u0c2c\u0c30\u0c4d"\
+ "\u0c28\u0c35\u0c02\u0c2c\u0c30\u0c4d"\
+ "\u0c21\u0c3f\u0c38\u0c46\u0c02\u0c2c\u0c30\u0c4d"\
+ ""]
+}
diff --git a/library/msgs/te_in.msg b/library/msgs/te_in.msg
new file mode 100755
index 0000000..61638b5
--- /dev/null
+++ b/library/msgs/te_in.msg
@@ -0,0 +1,8 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset te_IN AM "\u0c2a\u0c42\u0c30\u0c4d\u0c35\u0c3e\u0c39\u0c4d\u0c28"
+ ::msgcat::mcset te_IN PM "\u0c05\u0c2a\u0c30\u0c3e\u0c39\u0c4d\u0c28"
+ ::msgcat::mcset te_IN DATE_FORMAT "%d/%m/%Y"
+ ::msgcat::mcset te_IN TIME_FORMAT_12 "%I:%M:%S %P"
+ ::msgcat::mcset te_IN DATE_TIME_FORMAT "%d/%m/%Y %I:%M:%S %P %z"
+}
diff --git a/library/msgs/th.msg b/library/msgs/th.msg
new file mode 100755
index 0000000..7486c35
--- /dev/null
+++ b/library/msgs/th.msg
@@ -0,0 +1,54 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset th DAYS_OF_WEEK_ABBREV [list \
+ "\u0e2d\u0e32."\
+ "\u0e08."\
+ "\u0e2d."\
+ "\u0e1e."\
+ "\u0e1e\u0e24."\
+ "\u0e28."\
+ "\u0e2a."]
+ ::msgcat::mcset th DAYS_OF_WEEK_FULL [list \
+ "\u0e27\u0e31\u0e19\u0e2d\u0e32\u0e17\u0e34\u0e15\u0e22\u0e4c"\
+ "\u0e27\u0e31\u0e19\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c"\
+ "\u0e27\u0e31\u0e19\u0e2d\u0e31\u0e07\u0e04\u0e32\u0e23"\
+ "\u0e27\u0e31\u0e19\u0e1e\u0e38\u0e18"\
+ "\u0e27\u0e31\u0e19\u0e1e\u0e24\u0e2b\u0e31\u0e2a\u0e1a\u0e14\u0e35"\
+ "\u0e27\u0e31\u0e19\u0e28\u0e38\u0e01\u0e23\u0e4c"\
+ "\u0e27\u0e31\u0e19\u0e40\u0e2a\u0e32\u0e23\u0e4c"]
+ ::msgcat::mcset th MONTHS_ABBREV [list \
+ "\u0e21.\u0e04."\
+ "\u0e01.\u0e1e."\
+ "\u0e21\u0e35.\u0e04."\
+ "\u0e40\u0e21.\u0e22."\
+ "\u0e1e.\u0e04."\
+ "\u0e21\u0e34.\u0e22."\
+ "\u0e01.\u0e04."\
+ "\u0e2a.\u0e04."\
+ "\u0e01.\u0e22."\
+ "\u0e15.\u0e04."\
+ "\u0e1e.\u0e22."\
+ "\u0e18.\u0e04."\
+ ""]
+ ::msgcat::mcset th MONTHS_FULL [list \
+ "\u0e21\u0e01\u0e23\u0e32\u0e04\u0e21"\
+ "\u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c"\
+ "\u0e21\u0e35\u0e19\u0e32\u0e04\u0e21"\
+ "\u0e40\u0e21\u0e29\u0e32\u0e22\u0e19"\
+ "\u0e1e\u0e24\u0e29\u0e20\u0e32\u0e04\u0e21"\
+ "\u0e21\u0e34\u0e16\u0e38\u0e19\u0e32\u0e22\u0e19"\
+ "\u0e01\u0e23\u0e01\u0e0e\u0e32\u0e04\u0e21"\
+ "\u0e2a\u0e34\u0e07\u0e2b\u0e32\u0e04\u0e21"\
+ "\u0e01\u0e31\u0e19\u0e22\u0e32\u0e22\u0e19"\
+ "\u0e15\u0e38\u0e25\u0e32\u0e04\u0e21"\
+ "\u0e1e\u0e24\u0e28\u0e08\u0e34\u0e01\u0e32\u0e22\u0e19"\
+ "\u0e18\u0e31\u0e19\u0e27\u0e32\u0e04\u0e21"\
+ ""]
+ ::msgcat::mcset th BCE "\u0e25\u0e17\u0e35\u0e48"
+ ::msgcat::mcset th CE "\u0e04.\u0e28."
+ ::msgcat::mcset th AM "\u0e01\u0e48\u0e2d\u0e19\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07"
+ ::msgcat::mcset th PM "\u0e2b\u0e25\u0e31\u0e07\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07"
+ ::msgcat::mcset th DATE_FORMAT "%e/%m/%Y"
+ ::msgcat::mcset th TIME_FORMAT "%k:%M:%S"
+ ::msgcat::mcset th DATE_TIME_FORMAT "%e/%m/%Y %k:%M:%S %z"
+}
diff --git a/library/msgs/tr.msg b/library/msgs/tr.msg
new file mode 100755
index 0000000..7b2ecf9
--- /dev/null
+++ b/library/msgs/tr.msg
@@ -0,0 +1,50 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset tr DAYS_OF_WEEK_ABBREV [list \
+ "Paz"\
+ "Pzt"\
+ "Sal"\
+ "\u00c7ar"\
+ "Per"\
+ "Cum"\
+ "Cmt"]
+ ::msgcat::mcset tr DAYS_OF_WEEK_FULL [list \
+ "Pazar"\
+ "Pazartesi"\
+ "Sal\u0131"\
+ "\u00c7ar\u015famba"\
+ "Per\u015fembe"\
+ "Cuma"\
+ "Cumartesi"]
+ ::msgcat::mcset tr MONTHS_ABBREV [list \
+ "Oca"\
+ "\u015eub"\
+ "Mar"\
+ "Nis"\
+ "May"\
+ "Haz"\
+ "Tem"\
+ "A\u011fu"\
+ "Eyl"\
+ "Eki"\
+ "Kas"\
+ "Ara"\
+ ""]
+ ::msgcat::mcset tr MONTHS_FULL [list \
+ "Ocak"\
+ "\u015eubat"\
+ "Mart"\
+ "Nisan"\
+ "May\u0131s"\
+ "Haziran"\
+ "Temmuz"\
+ "A\u011fustos"\
+ "Eyl\u00fcl"\
+ "Ekim"\
+ "Kas\u0131m"\
+ "Aral\u0131k"\
+ ""]
+ ::msgcat::mcset tr DATE_FORMAT "%d.%m.%Y"
+ ::msgcat::mcset tr TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset tr DATE_TIME_FORMAT "%d.%m.%Y %H:%M:%S %z"
+}
diff --git a/library/msgs/uk.msg b/library/msgs/uk.msg
new file mode 100755
index 0000000..3e24f86
--- /dev/null
+++ b/library/msgs/uk.msg
@@ -0,0 +1,52 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset uk DAYS_OF_WEEK_ABBREV [list \
+ "\u043d\u0434"\
+ "\u043f\u043d"\
+ "\u0432\u0442"\
+ "\u0441\u0440"\
+ "\u0447\u0442"\
+ "\u043f\u0442"\
+ "\u0441\u0431"]
+ ::msgcat::mcset uk DAYS_OF_WEEK_FULL [list \
+ "\u043d\u0435\u0434\u0456\u043b\u044f"\
+ "\u043f\u043e\u043d\u0435\u0434\u0456\u043b\u043e\u043a"\
+ "\u0432\u0456\u0432\u0442\u043e\u0440\u043e\u043a"\
+ "\u0441\u0435\u0440\u0435\u0434\u0430"\
+ "\u0447\u0435\u0442\u0432\u0435\u0440"\
+ "\u043f'\u044f\u0442\u043d\u0438\u0446\u044f"\
+ "\u0441\u0443\u0431\u043e\u0442\u0430"]
+ ::msgcat::mcset uk MONTHS_ABBREV [list \
+ "\u0441\u0456\u0447"\
+ "\u043b\u044e\u0442"\
+ "\u0431\u0435\u0440"\
+ "\u043a\u0432\u0456\u0442"\
+ "\u0442\u0440\u0430\u0432"\
+ "\u0447\u0435\u0440\u0432"\
+ "\u043b\u0438\u043f"\
+ "\u0441\u0435\u0440\u043f"\
+ "\u0432\u0435\u0440"\
+ "\u0436\u043e\u0432\u0442"\
+ "\u043b\u0438\u0441\u0442"\
+ "\u0433\u0440\u0443\u0434"\
+ ""]
+ ::msgcat::mcset uk MONTHS_FULL [list \
+ "\u0441\u0456\u0447\u043d\u044f"\
+ "\u043b\u044e\u0442\u043e\u0433\u043e"\
+ "\u0431\u0435\u0440\u0435\u0436\u043d\u044f"\
+ "\u043a\u0432\u0456\u0442\u043d\u044f"\
+ "\u0442\u0440\u0430\u0432\u043d\u044f"\
+ "\u0447\u0435\u0440\u0432\u043d\u044f"\
+ "\u043b\u0438\u043f\u043d\u044f"\
+ "\u0441\u0435\u0440\u043f\u043d\u044f"\
+ "\u0432\u0435\u0440\u0435\u0441\u043d\u044f"\
+ "\u0436\u043e\u0432\u0442\u043d\u044f"\
+ "\u043b\u0438\u0441\u0442\u043e\u043f\u0430\u0434\u0430"\
+ "\u0433\u0440\u0443\u0434\u043d\u044f"\
+ ""]
+ ::msgcat::mcset uk BCE "\u0434\u043e \u043d.\u0435."
+ ::msgcat::mcset uk CE "\u043f\u0456\u0441\u043b\u044f \u043d.\u0435."
+ ::msgcat::mcset uk DATE_FORMAT "%e/%m/%Y"
+ ::msgcat::mcset uk TIME_FORMAT "%k:%M:%S"
+ ::msgcat::mcset uk DATE_TIME_FORMAT "%e/%m/%Y %k:%M:%S %z"
+}
diff --git a/library/msgs/vi.msg b/library/msgs/vi.msg
new file mode 100755
index 0000000..c98b2a6
--- /dev/null
+++ b/library/msgs/vi.msg
@@ -0,0 +1,50 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset vi DAYS_OF_WEEK_ABBREV [list \
+ "Th 2"\
+ "Th 3"\
+ "Th 4"\
+ "Th 5"\
+ "Th 6"\
+ "Th 7"\
+ "CN"]
+ ::msgcat::mcset vi DAYS_OF_WEEK_FULL [list \
+ "Th\u01b0\u0301 hai"\
+ "Th\u01b0\u0301 ba"\
+ "Th\u01b0\u0301 t\u01b0"\
+ "Th\u01b0\u0301 n\u0103m"\
+ "Th\u01b0\u0301 s\u00e1u"\
+ "Th\u01b0\u0301 ba\u0309y"\
+ "Chu\u0309 nh\u00e2\u0323t"]
+ ::msgcat::mcset vi MONTHS_ABBREV [list \
+ "Thg 1"\
+ "Thg 2"\
+ "Thg 3"\
+ "Thg 4"\
+ "Thg 5"\
+ "Thg 6"\
+ "Thg 7"\
+ "Thg 8"\
+ "Thg 9"\
+ "Thg 10"\
+ "Thg 11"\
+ "Thg 12"\
+ ""]
+ ::msgcat::mcset vi MONTHS_FULL [list \
+ "Th\u00e1ng m\u00f4\u0323t"\
+ "Th\u00e1ng hai"\
+ "Th\u00e1ng ba"\
+ "Th\u00e1ng t\u01b0"\
+ "Th\u00e1ng n\u0103m"\
+ "Th\u00e1ng s\u00e1u"\
+ "Th\u00e1ng ba\u0309y"\
+ "Th\u00e1ng t\u00e1m"\
+ "Th\u00e1ng ch\u00edn"\
+ "Th\u00e1ng m\u01b0\u01a1\u0300i"\
+ "Th\u00e1ng m\u01b0\u01a1\u0300i m\u00f4\u0323t"\
+ "Th\u00e1ng m\u01b0\u01a1\u0300i hai"\
+ ""]
+ ::msgcat::mcset vi DATE_FORMAT "%d %b %Y"
+ ::msgcat::mcset vi TIME_FORMAT "%H:%M:%S"
+ ::msgcat::mcset vi DATE_TIME_FORMAT "%d %b %Y %H:%M:%S %z"
+}
diff --git a/library/msgs/zh.msg b/library/msgs/zh.msg
new file mode 100755
index 0000000..b799a32
--- /dev/null
+++ b/library/msgs/zh.msg
@@ -0,0 +1,55 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset zh DAYS_OF_WEEK_ABBREV [list \
+ "\u661f\u671f\u65e5"\
+ "\u661f\u671f\u4e00"\
+ "\u661f\u671f\u4e8c"\
+ "\u661f\u671f\u4e09"\
+ "\u661f\u671f\u56db"\
+ "\u661f\u671f\u4e94"\
+ "\u661f\u671f\u516d"]
+ ::msgcat::mcset zh DAYS_OF_WEEK_FULL [list \
+ "\u661f\u671f\u65e5"\
+ "\u661f\u671f\u4e00"\
+ "\u661f\u671f\u4e8c"\
+ "\u661f\u671f\u4e09"\
+ "\u661f\u671f\u56db"\
+ "\u661f\u671f\u4e94"\
+ "\u661f\u671f\u516d"]
+ ::msgcat::mcset zh MONTHS_ABBREV [list \
+ "\u4e00\u6708"\
+ "\u4e8c\u6708"\
+ "\u4e09\u6708"\
+ "\u56db\u6708"\
+ "\u4e94\u6708"\
+ "\u516d\u6708"\
+ "\u4e03\u6708"\
+ "\u516b\u6708"\
+ "\u4e5d\u6708"\
+ "\u5341\u6708"\
+ "\u5341\u4e00\u6708"\
+ "\u5341\u4e8c\u6708"\
+ ""]
+ ::msgcat::mcset zh MONTHS_FULL [list \
+ "\u4e00\u6708"\
+ "\u4e8c\u6708"\
+ "\u4e09\u6708"\
+ "\u56db\u6708"\
+ "\u4e94\u6708"\
+ "\u516d\u6708"\
+ "\u4e03\u6708"\
+ "\u516b\u6708"\
+ "\u4e5d\u6708"\
+ "\u5341\u6708"\
+ "\u5341\u4e00\u6708"\
+ "\u5341\u4e8c\u6708"\
+ ""]
+ ::msgcat::mcset zh BCE "\u516c\u5143\u524d"
+ ::msgcat::mcset zh CE "\u516c\u5143"
+ ::msgcat::mcset zh AM "\u4e0a\u5348"
+ ::msgcat::mcset zh PM "\u4e0b\u5348"
+ ::msgcat::mcset zh LOCALE_NUMERALS "\u3007 \u4e00 \u4e8c \u4e09 \u56db \u4e94 \u516d \u4e03 \u516b \u4e5d \u5341 \u5341\u4e00 \u5341\u4e8c \u5341\u4e09 \u5341\u56db \u5341\u4e94 \u5341\u516d \u5341\u4e03 \u5341\u516b \u5341\u4e5d \u4e8c\u5341 \u5eff\u4e00 \u5eff\u4e8c \u5eff\u4e09 \u5eff\u56db \u5eff\u4e94 \u5eff\u516d \u5eff\u4e03 \u5eff\u516b \u5eff\u4e5d \u4e09\u5341 \u5345\u4e00 \u5345\u4e8c \u5345\u4e09 \u5345\u56db \u5345\u4e94 \u5345\u516d \u5345\u4e03 \u5345\u516b \u5345\u4e5d \u56db\u5341 \u56db\u5341\u4e00 \u56db\u5341\u4e8c \u56db\u5341\u4e09 \u56db\u5341\u56db \u56db\u5341\u4e94 \u56db\u5341\u516d \u56db\u5341\u4e03 \u56db\u5341\u516b \u56db\u5341\u4e5d \u4e94\u5341 \u4e94\u5341\u4e00 \u4e94\u5341\u4e8c \u4e94\u5341\u4e09 \u4e94\u5341\u56db \u4e94\u5341\u4e94 \u4e94\u5341\u516d \u4e94\u5341\u4e03 \u4e94\u5341\u516b \u4e94\u5341\u4e5d \u516d\u5341 \u516d\u5341\u4e00 \u516d\u5341\u4e8c \u516d\u5341\u4e09 \u516d\u5341\u56db \u516d\u5341\u4e94 \u516d\u5341\u516d \u516d\u5341\u4e03 \u516d\u5341\u516b \u516d\u5341\u4e5d \u4e03\u5341 \u4e03\u5341\u4e00 \u4e03\u5341\u4e8c \u4e03\u5341\u4e09 \u4e03\u5341\u56db \u4e03\u5341\u4e94 \u4e03\u5341\u516d \u4e03\u5341\u4e03 \u4e03\u5341\u516b \u4e03\u5341\u4e5d \u516b\u5341 \u516b\u5341\u4e00 \u516b\u5341\u4e8c \u516b\u5341\u4e09 \u516b\u5341\u56db \u516b\u5341\u4e94 \u516b\u5341\u516d \u516b\u5341\u4e03 \u516b\u5341\u516b \u516b\u5341\u4e5d \u4e5d\u5341 \u4e5d\u5341\u4e00 \u4e5d\u5341\u4e8c \u4e5d\u5341\u4e09 \u4e5d\u5341\u56db \u4e5d\u5341\u4e94 \u4e5d\u5341\u516d \u4e5d\u5341\u4e03 \u4e5d\u5341\u516b \u4e5d\u5341\u4e5d"
+ ::msgcat::mcset zh LOCALE_DATE_FORMAT "\u516c\u5143%Y\u5e74%B%Od\u65e5"
+ ::msgcat::mcset zh LOCALE_TIME_FORMAT "%OH\u65f6%OM\u5206%OS\u79d2"
+ ::msgcat::mcset zh LOCALE_DATE_TIME_FORMAT "%A %Y\u5e74%B%Od\u65e5%OH\u65f6%OM\u5206%OS\u79d2 %z"
+}
diff --git a/library/msgs/zh_cn.msg b/library/msgs/zh_cn.msg
new file mode 100755
index 0000000..d62ce77
--- /dev/null
+++ b/library/msgs/zh_cn.msg
@@ -0,0 +1,7 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset zh_CN DATE_FORMAT "%Y-%m-%e"
+ ::msgcat::mcset zh_CN TIME_FORMAT "%k:%M:%S"
+ ::msgcat::mcset zh_CN TIME_FORMAT_12 "%P%I\u65f6%M\u5206%S\u79d2"
+ ::msgcat::mcset zh_CN DATE_TIME_FORMAT "%Y-%m-%e %k:%M:%S %z"
+}
diff --git a/library/msgs/zh_hk.msg b/library/msgs/zh_hk.msg
new file mode 100755
index 0000000..badb1dd
--- /dev/null
+++ b/library/msgs/zh_hk.msg
@@ -0,0 +1,28 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset zh_HK DAYS_OF_WEEK_ABBREV [list \
+ "\u65e5"\
+ "\u4e00"\
+ "\u4e8c"\
+ "\u4e09"\
+ "\u56db"\
+ "\u4e94"\
+ "\u516d"]
+ ::msgcat::mcset zh_HK MONTHS_ABBREV [list \
+ "1\u6708"\
+ "2\u6708"\
+ "3\u6708"\
+ "4\u6708"\
+ "5\u6708"\
+ "6\u6708"\
+ "7\u6708"\
+ "8\u6708"\
+ "9\u6708"\
+ "10\u6708"\
+ "11\u6708"\
+ "12\u6708"\
+ ""]
+ ::msgcat::mcset zh_HK DATE_FORMAT "%Y\u5e74%m\u6708%e\u65e5"
+ ::msgcat::mcset zh_HK TIME_FORMAT_12 "%P%I:%M:%S"
+ ::msgcat::mcset zh_HK DATE_TIME_FORMAT "%Y\u5e74%m\u6708%e\u65e5 %P%I:%M:%S %z"
+}
diff --git a/library/msgs/zh_sg.msg b/library/msgs/zh_sg.msg
new file mode 100755
index 0000000..a2f3e39
--- /dev/null
+++ b/library/msgs/zh_sg.msg
@@ -0,0 +1,8 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset zh_SG AM "\u4e0a\u5348"
+ ::msgcat::mcset zh_SG PM "\u4e2d\u5348"
+ ::msgcat::mcset zh_SG DATE_FORMAT "%d %B %Y"
+ ::msgcat::mcset zh_SG TIME_FORMAT_12 "%P %I:%M:%S"
+ ::msgcat::mcset zh_SG DATE_TIME_FORMAT "%d %B %Y %P %I:%M:%S %z"
+}
diff --git a/library/msgs/zh_tw.msg b/library/msgs/zh_tw.msg
new file mode 100755
index 0000000..e0796b1
--- /dev/null
+++ b/library/msgs/zh_tw.msg
@@ -0,0 +1,8 @@
+# created by tools/loadICU.tcl -- do not edit
+namespace eval ::tcl::clock {
+ ::msgcat::mcset zh_TW BCE "\u6c11\u570b\u524d"
+ ::msgcat::mcset zh_TW CE "\u6c11\u570b"
+ ::msgcat::mcset zh_TW DATE_FORMAT "%Y/%m/%e"
+ ::msgcat::mcset zh_TW TIME_FORMAT_12 "%P %I:%M:%S"
+ ::msgcat::mcset zh_TW DATE_TIME_FORMAT "%Y/%m/%e %P %I:%M:%S %z"
+}
diff --git a/library/opt/optparse.tcl b/library/opt/optparse.tcl
index ec5eb30..c9438a0 100644
--- a/library/opt/optparse.tcl
+++ b/library/opt/optparse.tcl
@@ -11,7 +11,7 @@
package require Tcl 8.2
# When this version number changes, update the pkgIndex.tcl file
# and the install directory in the Makefiles.
-package provide opt 0.4.4.1
+package provide opt 0.4.5
namespace eval ::tcl {
@@ -809,15 +809,15 @@ proc ::tcl::OptCheckType {arg type {typeArgs ""}} {
}
}
- # Auto magic lasy type determination
+ # Auto magic lazy type determination
proc OptGuessType {arg} {
- if {[regexp -nocase {^(true|false)$} $arg]} {
+ if { $arg == "true" || $arg == "false" } {
return boolean
}
- if {[regexp {^(-+)?[0-9]+$} $arg]} {
+ if {[string is integer -strict $arg]} {
return int
}
- if {![catch {expr {double($arg)}}]} {
+ if {[string is double -strict $arg]} {
return float
}
return string
diff --git a/library/opt/pkgIndex.tcl b/library/opt/pkgIndex.tcl
index 754d2ee..c5d3635 100644
--- a/library/opt/pkgIndex.tcl
+++ b/library/opt/pkgIndex.tcl
@@ -9,4 +9,4 @@
# full path name of this file's directory.
if {![package vsatisfies [package provide Tcl] 8.2]} {return}
-package ifneeded opt 0.4.4.1 [list source [file join $dir optparse.tcl]]
+package ifneeded opt 0.4.5 [list source [file join $dir optparse.tcl]]
diff --git a/library/package.tcl b/library/package.tcl
index 3ed8d3c..dc06641 100644
--- a/library/package.tcl
+++ b/library/package.tcl
@@ -10,11 +10,9 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# Create the package namespace
-namespace eval ::pkg {
-}
+namespace eval tcl::Pkg {}
-# pkg_compareExtension --
+# ::tcl::Pkg::CompareExtension --
#
# Used internally by pkg_mkIndex to compare the extension of a file to
# a given extension. On Windows, it uses a case-insensitive comparison
@@ -29,7 +27,7 @@ namespace eval ::pkg {
# Results:
# Returns 1 if the extension matches, 0 otherwise
-proc pkg_compareExtension { fileName {ext {}} } {
+proc tcl::Pkg::CompareExtension { fileName {ext {}} } {
global tcl_platform
if {$ext eq ""} {set ext [info sharedlibextension]}
if {$tcl_platform(platform) eq "windows"} {
@@ -47,7 +45,7 @@ proc pkg_compareExtension { fileName {ext {}} } {
# The current extension does not match; if it is not a numeric
# value, quit, as we are only looking to ignore version number
# extensions. Otherwise we might return 1 in this case:
- # pkg_compareExtension foo.so.bar .so
+ # tcl::Pkg::CompareExtension foo.so.bar .so
# which should not match.
if { ![string is integer -strict [string range $currExt 1 end]] } {
@@ -84,7 +82,6 @@ proc pkg_compareExtension { fileName {ext {}} } {
# dir.
proc pkg_mkIndex {args} {
- global errorCode errorInfo
set usage {"pkg_mkIndex ?-direct? ?-lazy? ?-load pattern? ?-verbose? ?--? dir ?pattern ...?"};
set argCount [llength $args]
@@ -135,13 +132,10 @@ proc pkg_mkIndex {args} {
set patternList [list "*.tcl" "*[info sharedlibextension]"]
}
- set oldDir [pwd]
- cd $dir
-
- if {[catch {eval [linsert $patternList 0 glob --]} fileList]} {
- global errorCode errorInfo
- cd $oldDir
- return -code error -errorcode $errorCode -errorinfo $errorInfo $fileList
+ if {[catch {
+ glob -directory $dir -tails -types {r f} -- {*}$patternList
+ } fileList o]} {
+ return -options $o $fileList
}
foreach file $fileList {
# For each file, figure out what commands and packages it provides.
@@ -153,11 +147,6 @@ proc pkg_mkIndex {args} {
continue
}
- # Changed back to the original directory before initializing the
- # slave in case TCL_LIBRARY is a relative path (e.g. in the test
- # suite).
-
- cd $oldDir
set c [interp create]
# Load into the child any packages currently loaded in the parent
@@ -194,7 +183,6 @@ proc pkg_mkIndex {args} {
$c eval [list wm withdraw .]
}
}
- cd $dir
$c eval {
# Stub out the package command so packages can
@@ -204,7 +192,7 @@ proc pkg_mkIndex {args} {
proc package {what args} {
switch -- $what {
require { return ; # ignore transitive requires }
- default { uplevel 1 [linsert $args 0 __package_orig $what] }
+ default { __package_orig $what {*}$args }
}
}
proc tclPkgUnknown args {}
@@ -224,6 +212,7 @@ proc pkg_mkIndex {args} {
# to generate a pkgIndex.tcl file for the ::tcl namespace.
namespace eval ::tcl {
+ variable dir ;# Current directory being processed
variable file ;# Current file being processed
variable direct ;# -direct flag value
variable x ;# Loop variable
@@ -237,6 +226,7 @@ proc pkg_mkIndex {args} {
}
}
+ $c eval [list set ::tcl::dir $dir]
$c eval [list set ::tcl::file $file]
$c eval [list set ::tcl::direct $direct]
@@ -244,7 +234,8 @@ proc pkg_mkIndex {args} {
# just deleted the unknown procedure. This doesn't handle
# procedures with default arguments.
- foreach p {pkg_compareExtension} {
+ foreach p {::tcl::Pkg::CompareExtension} {
+ $c eval [list namespace eval [namespace qualifiers $p] {}]
$c eval [list proc $p [info args $p] [info body $p]]
}
@@ -259,8 +250,7 @@ proc pkg_mkIndex {args} {
proc ::tcl::GetAllNamespaces {{root ::}} {
set list $root
foreach ns [namespace children $root] {
- eval [linsert [::tcl::GetAllNamespaces $ns] 0 \
- lappend list]
+ lappend list {*}[::tcl::GetAllNamespaces $ns]
}
return $list
}
@@ -283,7 +273,7 @@ proc pkg_mkIndex {args} {
# on some systems (like SunOS) the loader will abort the
# whole application when it gets an error.
- if {[pkg_compareExtension $::tcl::file [info sharedlibextension]]} {
+ if {[::tcl::Pkg::CompareExtension $::tcl::file [info sharedlibextension]]} {
# The "file join ." command below is necessary.
# Without it, if the file name has no \'s and we're
# on UNIX, the load command will invoke the
@@ -291,11 +281,11 @@ proc pkg_mkIndex {args} {
# the wrong file to be used.
set ::tcl::debug loading
- load [file join . $::tcl::file]
+ load [file join $::tcl::dir $::tcl::file]
set ::tcl::type load
} else {
set ::tcl::debug sourcing
- source $::tcl::file
+ source [file join $::tcl::dir $::tcl::file]
set ::tcl::type source
}
@@ -402,7 +392,7 @@ proc pkg_mkIndex {args} {
foreach {name version} $pkg {
break
}
- lappend cmd ::pkg::create -name $name -version $version
+ lappend cmd ::tcl::Pkg::Create -name $name -version $version
foreach spec $files($pkg) {
foreach {file type procs} $spec {
if { $direct } {
@@ -414,10 +404,9 @@ proc pkg_mkIndex {args} {
append index "\n[eval $cmd]"
}
- set f [open pkgIndex.tcl w]
+ set f [open [file join $dir pkgIndex.tcl] w]
puts $f $index
close $f
- cd $oldDir
}
# tclPkgSetup --
@@ -460,8 +449,7 @@ proc tclPkgSetup {dir pkg version files} {
# It is invoked when a package that's needed can't be found. It scans
# the auto_path directories and their immediate children looking for
# pkgIndex.tcl files and sources any such files that are found to setup
-# the package database. (On the Macintosh we also search for pkgIndex
-# TEXT resources in all files.) As it searches, it will recognize changes
+# the package database. As it searches, it will recognize changes
# to the auto_path and scan any new directories.
#
# Arguments:
@@ -469,12 +457,7 @@ proc tclPkgSetup {dir pkg version files} {
# version - Version of desired package. Not used.
# exact - Either "-exact" or omitted. Not used.
-
-proc tclPkgUnknown [expr {
- [info exists tcl_platform(tip,268)]
- ? "name args"
- : "name version {exact {}}"
- }] {
+proc tclPkgUnknown {name args} {
global auto_path env
if {![info exists auto_path]} {
@@ -501,10 +484,11 @@ proc tclPkgUnknown [expr {
* pkgIndex.tcl] {
set dir [file dirname $file]
if {![info exists procdDirs($dir)]} {
- set code [catch {source $file} msg]
- if {$code == 1 && [lindex $::errorCode 0] eq "POSIX"
- && [lindex $::errorCode 1] eq "EACCES"} {
- # $file was not readable; silently ignore
+ set code [catch {source $file} msg opt]
+ if {$code == 1 &&
+ [lindex [dict get $opt -errorcode] 0] eq "POSIX" &&
+ [lindex [dict get $opt -errorcode] 1] eq "EACCES"} {
+ # $file was not readable; silently ignore
continue
}
if {$code} {
@@ -520,10 +504,11 @@ proc tclPkgUnknown [expr {
set file [file join $dir pkgIndex.tcl]
# safe interps usually don't have "file exists",
if {([interp issafe] || [file exists $file])} {
- set code [catch {source $file} msg]
- if {$code == 1 && [lindex $::errorCode 0] eq "POSIX"
- && [lindex $::errorCode 1] eq "EACCES"} {
- # $file was not readable; silently ignore
+ set code [catch {source $file} msg opt]
+ if {$code == 1 &&
+ [lindex [dict get $opt -errorcode] 0] eq "POSIX" &&
+ [lindex [dict get $opt -errorcode] 1] eq "EACCES"} {
+ # $file was not readable; silently ignore
continue
}
if {$code} {
@@ -576,120 +561,15 @@ proc tclPkgUnknown [expr {
# Arguments:
# original - original [package unknown] procedure
# name - Name of desired package. Not used.
-#ifndef TCL_TIP268
-# version - Version of desired package. Not used.
-# exact - Either "-exact" or omitted. Not used.
-#else
-# args - List of requirements. Not used.
-#endif
-
-if {[info exists tcl_platform(tip,268)]} {
- proc tcl::MacOSXPkgUnknown {original name args} {
- # First do the cross-platform default search
- uplevel 1 $original [linsert $args 0 $name]
-
- # Now do MacOSX specific searching
- global auto_path
-
- if {![info exists auto_path]} {
- return
- }
- # Cache the auto_path, because it may change while we run through
- # the first set of pkgIndex.tcl files
- set old_path [set use_path $auto_path]
- while {[llength $use_path]} {
- set dir [lindex $use_path end]
- # get the pkgIndex files out of the subdirectories
- foreach file [glob -directory $dir -join -nocomplain \
- * Resources Scripts pkgIndex.tcl] {
- set dir [file dirname $file]
- if {![info exists procdDirs($dir)]} {
- set code [catch {source $file} msg]
- if {$code == 1 && [lindex $::errorCode 0] eq "POSIX"
- && [lindex $::errorCode 1] eq "EACCES"} {
- # $file was not readable; silently ignore
- continue
- }
- if {$code} {
- tclLog "error reading package index file $file: $msg"
- } else {
- set procdDirs($dir) 1
- }
- }
- }
- set use_path [lrange $use_path 0 end-1]
- if {$old_path ne $auto_path} {
- foreach dir $auto_path {
- lappend use_path $dir
- }
- set old_path $auto_path
- }
- }
- }
-} else {
- proc tcl::MacOSXPkgUnknown {original name version {exact {}}} {
-
- # First do the cross-platform default search
- uplevel 1 $original [list $name $version $exact]
-
- # Now do MacOSX specific searching
- global auto_path
-
- if {![info exists auto_path]} {
- return
- }
- # Cache the auto_path, because it may change while we run through
- # the first set of pkgIndex.tcl files
- set old_path [set use_path $auto_path]
- while {[llength $use_path]} {
- set dir [lindex $use_path end]
- # get the pkgIndex files out of the subdirectories
- foreach file [glob -directory $dir -join -nocomplain \
- * Resources Scripts pkgIndex.tcl] {
- set dir [file dirname $file]
- if {![info exists procdDirs($dir)]} {
- set code [catch {source $file} msg]
- if {$code == 1 && [lindex $::errorCode 0] eq "POSIX"
- && [lindex $::errorCode 1] eq "EACCES"} {
- # $file was not readable; silently ignore
- continue
- }
- if {$code} {
- tclLog "error reading package index file $file: $msg"
- } else {
- set procdDirs($dir) 1
- }
- }
- }
- set use_path [lrange $use_path 0 end-1]
- if {$old_path ne $auto_path} {
- foreach dir $auto_path {
- lappend use_path $dir
- }
- set old_path $auto_path
- }
- }
- }
-}
-
-# tcl::MacPkgUnknown --
-# This procedure extends the "package unknown" function for Mac.
-# It searches for pkgIndex TEXT resources in all files
-# Only installed in interps that are not safe so we don't check
-# for [interp issafe] as in tclPkgUnknown.
-#
-# Arguments:
-# original - original [package unknown] procedure
-# name - Name of desired package. Not used.
# version - Version of desired package. Not used.
# exact - Either "-exact" or omitted. Not used.
-proc tcl::MacPkgUnknown {original name version {exact {}}} {
+proc tcl::MacOSXPkgUnknown {original name args} {
# First do the cross-platform default search
- uplevel 1 $original [list $name $version $exact]
+ uplevel 1 $original [linsert $args 0 $name]
- # Now do Mac specific searching
+ # Now do MacOSX specific searching
global auto_path
if {![info exists auto_path]} {
@@ -699,40 +579,75 @@ proc tcl::MacPkgUnknown {original name version {exact {}}} {
# the first set of pkgIndex.tcl files
set old_path [set use_path $auto_path]
while {[llength $use_path]} {
- # We look for pkgIndex TEXT resources in the resource fork of shared libraries
set dir [lindex $use_path end]
- foreach x [concat [list $dir] [glob -directory $dir -nocomplain *] ] {
- if {[file isdirectory $x] && ![info exists procdDirs($x)]} {
- set dir $x
- foreach x [glob -directory $dir -nocomplain *.shlb] {
- if {[file isfile $x]} {
- set res [resource open $x]
- foreach y [resource list TEXT $res] {
- if {$y eq "pkgIndex"} {source -rsrc pkgIndex}
- }
- catch {resource close $res}
- }
+
+ # Make sure we only scan each directory one time.
+ if {[info exists tclSeenPath($dir)]} {
+ set use_path [lrange $use_path 0 end-1]
+ continue
+ }
+ set tclSeenPath($dir) 1
+
+ # get the pkgIndex files out of the subdirectories
+ foreach file [glob -directory $dir -join -nocomplain \
+ * Resources Scripts pkgIndex.tcl] {
+ set dir [file dirname $file]
+ if {![info exists procdDirs($dir)]} {
+ set code [catch {source $file} msg opt]
+ if {$code == 1 &&
+ [lindex [dict get $opt -errorcode] 0] eq "POSIX" &&
+ [lindex [dict get $opt -errorcode] 1] eq "EACCES"} {
+ # $file was not readable; silently ignore
+ continue
+ }
+ if {$code} {
+ tclLog "error reading package index file $file: $msg"
+ } else {
+ set procdDirs($dir) 1
}
- set procdDirs($dir) 1
}
}
set use_path [lrange $use_path 0 end-1]
- if {$old_path ne $auto_path} {
- foreach dir $auto_path {
+
+ # Check whether any of the index scripts we [source]d above
+ # set a new value for $::auto_path. If so, then find any
+ # new directories on the $::auto_path, and lappend them to
+ # the $use_path we are working from. This gives index scripts
+ # the (arguably unwise) power to expand the index script search
+ # path while the search is in progress.
+ set index 0
+ if {[llength $old_path] == [llength $auto_path]} {
+ foreach dir $auto_path old $old_path {
+ if {$dir ne $old} {
+ # This entry in $::auto_path has changed.
+ break
+ }
+ incr index
+ }
+ }
+
+ # $index now points to the first element of $auto_path that
+ # has changed, or the beginning if $auto_path has changed length
+ # Scan the new elements of $auto_path for directories to add to
+ # $use_path. Don't add directories we've already seen, or ones
+ # already on the $use_path.
+ foreach dir [lrange $auto_path $index end] {
+ if {![info exists tclSeenPath($dir)]
+ && ([lsearch -exact $use_path $dir] == -1) } {
lappend use_path $dir
}
- set old_path $auto_path
}
+ set old_path $auto_path
}
}
-# ::pkg::create --
+# ::tcl::Pkg::Create --
#
# Given a package specification generate a "package ifneeded" statement
# for the package, suitable for inclusion in a pkgIndex.tcl file.
#
# Arguments:
-# args arguments used by the create function:
+# args arguments used by the Create function:
# -name packageName
# -version packageVersion
# -load {filename ?{procs}?}
@@ -752,7 +667,7 @@ proc tcl::MacPkgUnknown {original name version {exact {}}} {
# Results:
# An appropriate "package ifneeded" statement for the package.
-proc ::pkg::create {args} {
+proc ::tcl::Pkg::Create {args} {
append err(usage) "[lindex [info level 0] 0] "
append err(usage) "-name packageName -version packageVersion"
append err(usage) "?-load {filename ?{procs}?}? ... "
@@ -845,3 +760,4 @@ proc ::pkg::create {args} {
return $cmdline
}
+interp alias {} ::pkg::create {} ::tcl::Pkg::Create
diff --git a/library/parray.tcl b/library/parray.tcl
index b544984..3ce9817 100644
--- a/library/parray.tcl
+++ b/library/parray.tcl
@@ -14,13 +14,14 @@ proc parray {a {pattern *}} {
error "\"$a\" isn't an array"
}
set maxl 0
- foreach name [lsort [array names array $pattern]] {
+ set names [lsort [array names array $pattern]]
+ foreach name $names {
if {[string length $name] > $maxl} {
set maxl [string length $name]
}
}
set maxl [expr {$maxl + [string length $a] + 2}]
- foreach name [lsort [array names array $pattern]] {
+ foreach name $names {
set nameString [format %s(%s) $a $name]
puts stdout [format "%-*s = %s" $maxl $nameString $array($name)]
}
diff --git a/library/reg/pkgIndex.tcl b/library/reg/pkgIndex.tcl
index 3aed06f..d2ed72f 100755
--- a/library/reg/pkgIndex.tcl
+++ b/library/reg/pkgIndex.tcl
@@ -1,9 +1,9 @@
if {![package vsatisfies [package provide Tcl] 8]} {return}
if {[string compare $::tcl_platform(platform) windows]} {return}
if {[info exists ::tcl_platform(debug)]} {
- package ifneeded registry 1.1.5 \
- [list load [file join $dir tclreg11g.dll] registry]
+ package ifneeded registry 1.2.1 \
+ [list load [file join $dir tclreg12g.dll] registry]
} else {
- package ifneeded registry 1.1.5 \
- [list load [file join $dir tclreg11.dll] registry]
+ package ifneeded registry 1.2.1 \
+ [list load [file join $dir tclreg12.dll] registry]
}
diff --git a/library/safe.tcl b/library/safe.tcl
index a2ab245..8a99032 100644
--- a/library/safe.tcl
+++ b/library/safe.tcl
@@ -9,914 +9,1106 @@
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
#
-# See the file "license.terms" for information on usage and redistribution
-# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+# See the file "license.terms" for information on usage and redistribution of
+# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# The implementation is based on namespaces. These naming conventions
-# are followed:
+# The implementation is based on namespaces. These naming conventions are
+# followed:
# Private procs starts with uppercase.
# Public procs are exported and starts with lowercase
#
# Needed utilities package
-package require opt 0.4.1;
+package require opt 0.4.1
# Create the safe namespace
namespace eval ::safe {
-
# Exported API:
namespace export interpCreate interpInit interpConfigure interpDelete \
- interpAddToAccessPath interpFindInAccessPath setLogCmd
-
- ####
- #
- # Setup the arguments parsing
- #
- ####
-
- # Make sure that our temporary variable is local to this
- # namespace. [Bug 981733]
- variable temp
-
- # Share the descriptions
- set temp [::tcl::OptKeyRegister {
- {-accessPath -list {} "access path for the slave"}
- {-noStatics "prevent loading of statically linked pkgs"}
- {-statics true "loading of statically linked pkgs"}
- {-nestedLoadOk "allow nested loading"}
- {-nested false "nested loading"}
- {-deleteHook -script {} "delete hook"}
- }]
-
- # create case (slave is optional)
- ::tcl::OptKeyRegister {
- {?slave? -name {} "name of the slave (optional)"}
- } ::safe::interpCreate
- # adding the flags sub programs to the command program
- # (relying on Opt's internal implementation details)
- lappend ::tcl::OptDesc(::safe::interpCreate) $::tcl::OptDesc($temp)
-
- # init and configure (slave is needed)
- ::tcl::OptKeyRegister {
- {slave -name {} "name of the slave"}
- } ::safe::interpIC
- # adding the flags sub programs to the command program
- # (relying on Opt's internal implementation details)
- lappend ::tcl::OptDesc(::safe::interpIC) $::tcl::OptDesc($temp)
- # temp not needed anymore
- ::tcl::OptKeyDelete $temp
-
+ interpAddToAccessPath interpFindInAccessPath setLogCmd
+}
- # Helper function to resolve the dual way of specifying staticsok
- # (either by -noStatics or -statics 0)
- proc InterpStatics {} {
- foreach v {Args statics noStatics} {
- upvar $v $v
- }
- set flag [::tcl::OptProcArgGiven -noStatics];
- if {$flag && (!$noStatics == !$statics)
- && ([::tcl::OptProcArgGiven -statics])} {
- return -code error\
- "conflicting values given for -statics and -noStatics"
- }
- if {$flag} {
- return [expr {!$noStatics}]
- } else {
- return $statics
- }
+# Helper function to resolve the dual way of specifying staticsok (either
+# by -noStatics or -statics 0)
+proc ::safe::InterpStatics {} {
+ foreach v {Args statics noStatics} {
+ upvar $v $v
+ }
+ set flag [::tcl::OptProcArgGiven -noStatics]
+ if {$flag && (!$noStatics == !$statics)
+ && ([::tcl::OptProcArgGiven -statics])} {
+ return -code error\
+ "conflicting values given for -statics and -noStatics"
}
+ if {$flag} {
+ return [expr {!$noStatics}]
+ } else {
+ return $statics
+ }
+}
- # Helper function to resolve the dual way of specifying nested loading
- # (either by -nestedLoadOk or -nested 1)
- proc InterpNested {} {
- foreach v {Args nested nestedLoadOk} {
- upvar $v $v
- }
- set flag [::tcl::OptProcArgGiven -nestedLoadOk];
- # note that the test here is the opposite of the "InterpStatics"
- # one (it is not -noNested... because of the wanted default value)
- if {$flag && (!$nestedLoadOk != !$nested)
- && ([::tcl::OptProcArgGiven -nested])} {
- return -code error\
- "conflicting values given for -nested and -nestedLoadOk"
- }
- if {$flag} {
- # another difference with "InterpStatics"
- return $nestedLoadOk
- } else {
- return $nested
- }
+# Helper function to resolve the dual way of specifying nested loading
+# (either by -nestedLoadOk or -nested 1)
+proc ::safe::InterpNested {} {
+ foreach v {Args nested nestedLoadOk} {
+ upvar $v $v
+ }
+ set flag [::tcl::OptProcArgGiven -nestedLoadOk]
+ # note that the test here is the opposite of the "InterpStatics" one
+ # (it is not -noNested... because of the wanted default value)
+ if {$flag && (!$nestedLoadOk != !$nested)
+ && ([::tcl::OptProcArgGiven -nested])} {
+ return -code error\
+ "conflicting values given for -nested and -nestedLoadOk"
+ }
+ if {$flag} {
+ # another difference with "InterpStatics"
+ return $nestedLoadOk
+ } else {
+ return $nested
}
+}
- ####
- #
- # API entry points that needs argument parsing :
- #
- ####
+####
+#
+# API entry points that needs argument parsing :
+#
+####
+# Interface/entry point function and front end for "Create"
+proc ::safe::interpCreate {args} {
+ set Args [::tcl::OptKeyParse ::safe::interpCreate $args]
+ InterpCreate $slave $accessPath \
+ [InterpStatics] [InterpNested] $deleteHook
+}
- # Interface/entry point function and front end for "Create"
- proc interpCreate {args} {
- set Args [::tcl::OptKeyParse ::safe::interpCreate $args]
- InterpCreate $slave $accessPath \
- [InterpStatics] [InterpNested] $deleteHook
+proc ::safe::interpInit {args} {
+ set Args [::tcl::OptKeyParse ::safe::interpIC $args]
+ if {![::interp exists $slave]} {
+ return -code error "\"$slave\" is not an interpreter"
}
+ InterpInit $slave $accessPath \
+ [InterpStatics] [InterpNested] $deleteHook
+}
- proc interpInit {args} {
- set Args [::tcl::OptKeyParse ::safe::interpIC $args]
- if {![::interp exists $slave]} {
- return -code error "\"$slave\" is not an interpreter"
- }
- InterpInit $slave $accessPath \
- [InterpStatics] [InterpNested] $deleteHook;
+# Check that the given slave is "one of us"
+proc ::safe::CheckInterp {slave} {
+ namespace upvar ::safe S$slave state
+ if {![info exists state] || ![::interp exists $slave]} {
+ return -code error \
+ "\"$slave\" is not an interpreter managed by ::safe::"
}
+}
- proc CheckInterp {slave} {
- if {![IsInterp $slave]} {
- return -code error \
- "\"$slave\" is not an interpreter managed by ::safe::"
+# Interface/entry point function and front end for "Configure". This code
+# is awfully pedestrian because it would need more coupling and support
+# between the way we store the configuration values in safe::interp's and
+# the Opt package. Obviously we would like an OptConfigure to avoid
+# duplicating all this code everywhere.
+# -> TODO (the app should share or access easily the program/value stored
+# by opt)
+
+# This is even more complicated by the boolean flags with no values that
+# we had the bad idea to support for the sake of user simplicity in
+# create/init but which makes life hard in configure...
+# So this will be hopefully written and some integrated with opt1.0
+# (hopefully for tcl8.1 ?)
+proc ::safe::interpConfigure {args} {
+ switch [llength $args] {
+ 1 {
+ # If we have exactly 1 argument the semantic is to return all
+ # the current configuration. We still call OptKeyParse though
+ # we know that "slave" is our given argument because it also
+ # checks for the "-help" option.
+ set Args [::tcl::OptKeyParse ::safe::interpIC $args]
+ CheckInterp $slave
+ namespace upvar ::safe S$slave state
+
+ return [join [list \
+ [list -accessPath $state(access_path)] \
+ [list -statics $state(staticsok)] \
+ [list -nested $state(nestedok)] \
+ [list -deleteHook $state(cleanupHook)]]]
}
- }
-
- # Interface/entry point function and front end for "Configure"
- # This code is awfully pedestrian because it would need
- # more coupling and support between the way we store the
- # configuration values in safe::interp's and the Opt package
- # Obviously we would like an OptConfigure
- # to avoid duplicating all this code everywhere. -> TODO
- # (the app should share or access easily the program/value
- # stored by opt)
- # This is even more complicated by the boolean flags with no values
- # that we had the bad idea to support for the sake of user simplicity
- # in create/init but which makes life hard in configure...
- # So this will be hopefully written and some integrated with opt1.0
- # (hopefully for tcl8.1 ?)
- proc interpConfigure {args} {
- switch [llength $args] {
- 1 {
- # If we have exactly 1 argument
- # the semantic is to return all the current configuration
- # We still call OptKeyParse though we know that "slave"
- # is our given argument because it also checks
- # for the "-help" option.
- set Args [::tcl::OptKeyParse ::safe::interpIC $args]
- CheckInterp $slave
- set res {}
- lappend res [list -accessPath [Set [PathListName $slave]]]
- lappend res [list -statics [Set [StaticsOkName $slave]]]
- lappend res [list -nested [Set [NestedOkName $slave]]]
- lappend res [list -deleteHook [Set [DeleteHookName $slave]]]
- join $res
+ 2 {
+ # If we have exactly 2 arguments the semantic is a "configure
+ # get"
+ lassign $args slave arg
+
+ # get the flag sub program (we 'know' about Opt's internal
+ # representation of data)
+ set desc [lindex [::tcl::OptKeyGetDesc ::safe::interpIC] 2]
+ set hits [::tcl::OptHits desc $arg]
+ if {$hits > 1} {
+ return -code error [::tcl::OptAmbigous $desc $arg]
+ } elseif {$hits == 0} {
+ return -code error [::tcl::OptFlagUsage $desc $arg]
}
- 2 {
- # If we have exactly 2 arguments
- # the semantic is a "configure get"
- ::tcl::Lassign $args slave arg
- # get the flag sub program (we 'know' about Opt's internal
- # representation of data)
- set desc [lindex [::tcl::OptKeyGetDesc ::safe::interpIC] 2]
- set hits [::tcl::OptHits desc $arg]
- if {$hits > 1} {
- return -code error [::tcl::OptAmbigous $desc $arg]
- } elseif {$hits == 0} {
- return -code error [::tcl::OptFlagUsage $desc $arg]
- }
- CheckInterp $slave
- set item [::tcl::OptCurDesc $desc]
- set name [::tcl::OptName $item]
- switch -exact -- $name {
- -accessPath {
- return [list -accessPath [Set [PathListName $slave]]]
- }
- -statics {
- return [list -statics [Set [StaticsOkName $slave]]]
- }
- -nested {
- return [list -nested [Set [NestedOkName $slave]]]
- }
- -deleteHook {
- return [list -deleteHook [Set [DeleteHookName $slave]]]
- }
- -noStatics {
- # it is most probably a set in fact
- # but we would need then to jump to the set part
- # and it is not *sure* that it is a set action
- # that the user want, so force it to use the
- # unambigous -statics ?value? instead:
- return -code error\
- "ambigous query (get or set -noStatics ?)\
+ CheckInterp $slave
+ namespace upvar ::safe S$slave state
+
+ set item [::tcl::OptCurDesc $desc]
+ set name [::tcl::OptName $item]
+ switch -exact -- $name {
+ -accessPath {return [list -accessPath $state(access_path)]}
+ -statics {return [list -statics $state(staticsok)]}
+ -nested {return [list -nested $state(nestedok)]}
+ -deleteHook {return [list -deleteHook $state(cleanupHook)]}
+ -noStatics {
+ # it is most probably a set in fact but we would need
+ # then to jump to the set part and it is not *sure*
+ # that it is a set action that the user want, so force
+ # it to use the unambigous -statics ?value? instead:
+ return -code error\
+ "ambigous query (get or set -noStatics ?)\
use -statics instead"
- }
- -nestedLoadOk {
- return -code error\
- "ambigous query (get or set -nestedLoadOk ?)\
+ }
+ -nestedLoadOk {
+ return -code error\
+ "ambigous query (get or set -nestedLoadOk ?)\
use -nested instead"
- }
- default {
- return -code error "unknown flag $name (bug)"
- }
}
- }
- default {
- # Otherwise we want to parse the arguments like init and create
- # did
- set Args [::tcl::OptKeyParse ::safe::interpIC $args]
- CheckInterp $slave
- # Get the current (and not the default) values of
- # whatever has not been given:
- if {![::tcl::OptProcArgGiven -accessPath]} {
- set doreset 1
- set accessPath [Set [PathListName $slave]]
- } else {
- set doreset 0
+ default {
+ return -code error "unknown flag $name (bug)"
}
- if {(![::tcl::OptProcArgGiven -statics]) \
- && (![::tcl::OptProcArgGiven -noStatics]) } {
- set statics [Set [StaticsOkName $slave]]
- } else {
- set statics [InterpStatics]
- }
- if {([::tcl::OptProcArgGiven -nested]) \
- || ([::tcl::OptProcArgGiven -nestedLoadOk]) } {
- set nested [InterpNested]
+ }
+ }
+ default {
+ # Otherwise we want to parse the arguments like init and
+ # create did
+ set Args [::tcl::OptKeyParse ::safe::interpIC $args]
+ CheckInterp $slave
+ namespace upvar ::safe S$slave state
+
+ # Get the current (and not the default) values of whatever has
+ # not been given:
+ if {![::tcl::OptProcArgGiven -accessPath]} {
+ set doreset 1
+ set accessPath $state(access_path)
+ } else {
+ set doreset 0
+ }
+ if {
+ ![::tcl::OptProcArgGiven -statics]
+ && ![::tcl::OptProcArgGiven -noStatics]
+ } {
+ set statics $state(staticsok)
+ } else {
+ set statics [InterpStatics]
+ }
+ if {
+ [::tcl::OptProcArgGiven -nested] ||
+ [::tcl::OptProcArgGiven -nestedLoadOk]
+ } {
+ set nested [InterpNested]
+ } else {
+ set nested $state(nestedok)
+ }
+ if {![::tcl::OptProcArgGiven -deleteHook]} {
+ set deleteHook $state(cleanupHook)
+ }
+ # we can now reconfigure :
+ InterpSetConfig $slave $accessPath $statics $nested $deleteHook
+ # auto_reset the slave (to completly synch the new access_path)
+ if {$doreset} {
+ if {[catch {::interp eval $slave {auto_reset}} msg]} {
+ Log $slave "auto_reset failed: $msg"
} else {
- set nested [Set [NestedOkName $slave]]
- }
- if {![::tcl::OptProcArgGiven -deleteHook]} {
- set deleteHook [Set [DeleteHookName $slave]]
- }
- # we can now reconfigure :
- InterpSetConfig $slave $accessPath $statics $nested $deleteHook
- # auto_reset the slave (to completly synch the new access_path)
- if {$doreset} {
- if {[catch {::interp eval $slave {auto_reset}} msg]} {
- Log $slave "auto_reset failed: $msg"
- } else {
- Log $slave "successful auto_reset" NOTICE
- }
+ Log $slave "successful auto_reset" NOTICE
}
}
}
}
+}
+####
+#
+# Functions that actually implements the exported APIs
+#
+####
- ####
- #
- # Functions that actually implements the exported APIs
- #
- ####
-
-
- #
- # safe::InterpCreate : doing the real job
- #
- # This procedure creates a safe slave and initializes it with the
- # safe base aliases.
- # NB: slave name must be simple alphanumeric string, no spaces,
- # no (), no {},... {because the state array is stored as part of the name}
- #
- # Returns the slave name.
- #
- # Optional Arguments :
- # + slave name : if empty, generated name will be used
- # + access_path: path list controlling where load/source can occur,
- # if empty: the master auto_path will be used.
- # + staticsok : flag, if 0 :no static package can be loaded (load {} Xxx)
- # if 1 :static packages are ok.
- # + nestedok: flag, if 0 :no loading to sub-sub interps (load xx xx sub)
- # if 1 : multiple levels are ok.
-
- # use the full name and no indent so auto_mkIndex can find us
- proc ::safe::InterpCreate {
- slave
- access_path
- staticsok
- nestedok
- deletehook
- } {
- # Create the slave.
- if {$slave ne ""} {
- ::interp create -safe $slave
- } else {
- # empty argument: generate slave name
- set slave [::interp create -safe]
- }
- Log $slave "Created" NOTICE
-
- # Initialize it. (returns slave name)
- InterpInit $slave $access_path $staticsok $nestedok $deletehook
+#
+# safe::InterpCreate : doing the real job
+#
+# This procedure creates a safe slave and initializes it with the safe
+# base aliases.
+# NB: slave name must be simple alphanumeric string, no spaces, no (), no
+# {},... {because the state array is stored as part of the name}
+#
+# Returns the slave name.
+#
+# Optional Arguments :
+# + slave name : if empty, generated name will be used
+# + access_path: path list controlling where load/source can occur,
+# if empty: the master auto_path will be used.
+# + staticsok : flag, if 0 :no static package can be loaded (load {} Xxx)
+# if 1 :static packages are ok.
+# + nestedok: flag, if 0 :no loading to sub-sub interps (load xx xx sub)
+# if 1 : multiple levels are ok.
+
+# use the full name and no indent so auto_mkIndex can find us
+proc ::safe::InterpCreate {
+ slave
+ access_path
+ staticsok
+ nestedok
+ deletehook
+ } {
+ # Create the slave.
+ if {$slave ne ""} {
+ ::interp create -safe $slave
+ } else {
+ # empty argument: generate slave name
+ set slave [::interp create -safe]
}
+ Log $slave "Created" NOTICE
+ # Initialize it. (returns slave name)
+ InterpInit $slave $access_path $staticsok $nestedok $deletehook
+}
- #
- # InterpSetConfig (was setAccessPath) :
- # Sets up slave virtual auto_path and corresponding structure
- # within the master. Also sets the tcl_library in the slave
- # to be the first directory in the path.
- # Nb: If you change the path after the slave has been initialized
- # you probably need to call "auto_reset" in the slave in order that it
- # gets the right auto_index() array values.
-
- proc ::safe::InterpSetConfig {slave access_path staticsok\
- nestedok deletehook} {
-
- # determine and store the access path if empty
- if {$access_path eq ""} {
- set access_path [uplevel \#0 set auto_path]
- # Make sure that tcl_library is in auto_path
- # and at the first position (needed by setAccessPath)
- set where [lsearch -exact $access_path [info library]]
- if {$where == -1} {
- # not found, add it.
- set access_path [concat [list [info library]] $access_path]
- Log $slave "tcl_library was not in auto_path,\
+#
+# InterpSetConfig (was setAccessPath) :
+# Sets up slave virtual auto_path and corresponding structure within
+# the master. Also sets the tcl_library in the slave to be the first
+# directory in the path.
+# NB: If you change the path after the slave has been initialized you
+# probably need to call "auto_reset" in the slave in order that it gets
+# the right auto_index() array values.
+
+proc ::safe::InterpSetConfig {slave access_path staticsok nestedok deletehook} {
+ global auto_path
+
+ # determine and store the access path if empty
+ if {$access_path eq ""} {
+ set access_path $auto_path
+
+ # Make sure that tcl_library is in auto_path and at the first
+ # position (needed by setAccessPath)
+ set where [lsearch -exact $access_path [info library]]
+ if {$where == -1} {
+ # not found, add it.
+ set access_path [linsert $access_path 0 [info library]]
+ Log $slave "tcl_library was not in auto_path,\
added it to slave's access_path" NOTICE
- } elseif {$where != 0} {
- # not first, move it first
- set access_path [concat [list [info library]]\
- [lreplace $access_path $where $where]]
- Log $slave "tcl_libray was not in first in auto_path,\
+ } elseif {$where != 0} {
+ # not first, move it first
+ set access_path [linsert \
+ [lreplace $access_path $where $where] \
+ 0 [info library]]
+ Log $slave "tcl_libray was not in first in auto_path,\
moved it to front of slave's access_path" NOTICE
-
- }
-
- # Add 1st level sub dirs (will searched by auto loading from tcl
- # code in the slave using glob and thus fail, so we add them
- # here so by default it works the same).
- set access_path [AddSubDirs $access_path]
}
- Log $slave "Setting accessPath=($access_path) staticsok=$staticsok\
+ # Add 1st level sub dirs (will searched by auto loading from tcl
+ # code in the slave using glob and thus fail, so we add them here
+ # so by default it works the same).
+ set access_path [AddSubDirs $access_path]
+ }
+
+ Log $slave "Setting accessPath=($access_path) staticsok=$staticsok\
nestedok=$nestedok deletehook=($deletehook)" NOTICE
- # clear old autopath if it existed
- set nname [PathNumberName $slave]
- if {[Exists $nname]} {
- set n [Set $nname]
- for {set i 0} {$i<$n} {incr i} {
- Unset [PathToken $i $slave]
- }
- }
+ namespace upvar ::safe S$slave state
+
+ # clear old autopath if it existed
+ # build new one
+ # Extend the access list with the paths used to look for Tcl Modules.
+ # We save the virtual form separately as well, as syncing it with the
+ # slave has to be defered until the necessary commands are present for
+ # setup.
+
+ set norm_access_path {}
+ set slave_access_path {}
+ set map_access_path {}
+ set remap_access_path {}
+ set slave_tm_path {}
+
+ set i 0
+ foreach dir $access_path {
+ set token [PathToken $i]
+ lappend slave_access_path $token
+ lappend map_access_path $token $dir
+ lappend remap_access_path $dir $token
+ lappend norm_access_path [file normalize $dir]
+ incr i
+ }
- # build new one
- set slave_auto_path {}
- set i 0
- foreach dir $access_path {
- Set [PathToken $i $slave] $dir
- lappend slave_auto_path "\$[PathToken $i]"
- incr i
- }
- Set $nname $i
- Set [PathListName $slave] $access_path
- Set [VirtualPathListName $slave] $slave_auto_path
+ set morepaths [::tcl::tm::list]
+ while {[llength $morepaths]} {
+ set addpaths $morepaths
+ set morepaths {}
- Set [StaticsOkName $slave] $staticsok
- Set [NestedOkName $slave] $nestedok
- Set [DeleteHookName $slave] $deletehook
+ foreach dir $addpaths {
+ # Prevent the addition of dirs on the tm list to the
+ # result if they are already known.
+ if {[dict exists $remap_access_path $dir]} {
+ continue
+ }
- SyncAccessPath $slave
- }
+ set token [PathToken $i]
+ lappend access_path $dir
+ lappend slave_access_path $token
+ lappend map_access_path $token $dir
+ lappend remap_access_path $dir $token
+ lappend norm_access_path [file normalize $dir]
+ lappend slave_tm_path $token
+ incr i
- #
- #
- # FindInAccessPath:
- # Search for a real directory and returns its virtual Id
- # (including the "$")
-proc ::safe::interpFindInAccessPath {slave path} {
- set access_path [GetAccessPath $slave]
- set where [lsearch -exact $access_path $path]
- if {$where == -1} {
- return -code error "$path not found in access path $access_path"
+ # [Bug 2854929]
+ # Recursively find deeper paths which may contain
+ # modules. Required to handle modules with names like
+ # 'platform::shell', which translate into
+ # 'platform/shell-X.tm', i.e arbitrarily deep
+ # subdirectories.
+ lappend morepaths {*}[glob -nocomplain -directory $dir -type d *]
}
- return "\$[PathToken $where]"
}
- #
- # addToAccessPath:
- # add (if needed) a real directory to access path
- # and return its virtual token (including the "$").
-proc ::safe::interpAddToAccessPath {slave path} {
- # first check if the directory is already in there
- if {![catch {interpFindInAccessPath $slave $path} res]} {
- return $res
- }
- # new one, add it:
- set nname [PathNumberName $slave]
- set n [Set $nname]
- Set [PathToken $n $slave] $path
-
- set token "\$[PathToken $n]"
-
- Lappend [VirtualPathListName $slave] $token
- Lappend [PathListName $slave] $path
- Set $nname [expr {$n+1}]
+ set state(access_path) $access_path
+ set state(access_path,map) $map_access_path
+ set state(access_path,remap) $remap_access_path
+ set state(access_path,norm) $norm_access_path
+ set state(access_path,slave) $slave_access_path
+ set state(tm_path_slave) $slave_tm_path
+ set state(staticsok) $staticsok
+ set state(nestedok) $nestedok
+ set state(cleanupHook) $deletehook
+
+ SyncAccessPath $slave
+}
- SyncAccessPath $slave
+#
+#
+# FindInAccessPath:
+# Search for a real directory and returns its virtual Id (including the
+# "$")
+proc ::safe::interpFindInAccessPath {slave path} {
+ namespace upvar ::safe S$slave state
- return $token
+ if {![dict exists $state(access_path,remap) $path]} {
+ return -code error "$path not found in access path $access_path"
}
- # This procedure applies the initializations to an already existing
- # interpreter. It is useful when you want to install the safe base
- # aliases into a preexisting safe interpreter.
- proc ::safe::InterpInit {
- slave
- access_path
- staticsok
- nestedok
- deletehook
- } {
-
- # Configure will generate an access_path when access_path is
- # empty.
- InterpSetConfig $slave $access_path $staticsok $nestedok $deletehook
-
- # These aliases let the slave load files to define new commands
+ return [dict get $state(access_path,remap) $path]
+}
- # NB we need to add [namespace current], aliases are always
- # absolute paths.
- ::interp alias $slave source {} [namespace current]::AliasSource $slave
- ::interp alias $slave load {} [namespace current]::AliasLoad $slave
+#
+# addToAccessPath:
+# add (if needed) a real directory to access path and return its
+# virtual token (including the "$").
+proc ::safe::interpAddToAccessPath {slave path} {
+ # first check if the directory is already in there
+ # (inlined interpFindInAccessPath).
+ namespace upvar ::safe S$slave state
- # This alias lets the slave use the encoding names, convertfrom,
- # convertto, and system, but not "encoding system <name>" to set
- # the system encoding.
+ if {[dict exists $state(access_path,remap) $path]} {
+ return [dict get $state(access_path,remap) $path]
+ }
- ::interp alias $slave encoding {} [namespace current]::AliasEncoding \
- $slave
+ # new one, add it:
+ set token [PathToken [llength $state(access_path)]]
- # This alias lets the slave have access to a subset of the 'file'
- # command functionality.
+ lappend state(access_path) $path
+ lappend state(access_path,slave) $token
+ lappend state(access_path,map) $token $path
+ lappend state(access_path,remap) $path $token
+ lappend state(access_path,norm) [file normalize $path]
- AliasSubset $slave file file dir.* join root.* ext.* tail \
- path.* split
+ SyncAccessPath $slave
+ return $token
+}
- # This alias interposes on the 'exit' command and cleanly terminates
- # the slave.
+# This procedure applies the initializations to an already existing
+# interpreter. It is useful when you want to install the safe base aliases
+# into a preexisting safe interpreter.
+proc ::safe::InterpInit {
+ slave
+ access_path
+ staticsok
+ nestedok
+ deletehook
+ } {
+ # Configure will generate an access_path when access_path is empty.
+ InterpSetConfig $slave $access_path $staticsok $nestedok $deletehook
+
+ # NB we need to add [namespace current], aliases are always absolute
+ # paths.
+
+ # These aliases let the slave load files to define new commands
+ # This alias lets the slave use the encoding names, convertfrom,
+ # convertto, and system, but not "encoding system <name>" to set the
+ # system encoding.
+ # Handling Tcl Modules, we need a restricted form of Glob.
+ # This alias interposes on the 'exit' command and cleanly terminates
+ # the slave.
+
+ foreach {command alias} {
+ source AliasSource
+ load AliasLoad
+ encoding AliasEncoding
+ exit interpDelete
+ glob AliasGlob
+ } {
+ ::interp alias $slave $command {} [namespace current]::$alias $slave
+ }
- ::interp alias $slave exit {} [namespace current]::interpDelete $slave
+ # This alias lets the slave have access to a subset of the 'file'
+ # command functionality.
- # The allowed slave variables already have been set
- # by Tcl_MakeSafe(3)
+ AliasSubset $slave file \
+ file dir.* join root.* ext.* tail path.* split
+ # Subcommands of info
+ foreach {subcommand alias} {
+ nameofexecutable AliasExeName
+ } {
+ ::interp alias $slave ::tcl::info::$subcommand \
+ {} [namespace current]::$alias $slave
+ }
- # Source init.tcl into the slave, to get auto_load and other
- # procedures defined:
+ # The allowed slave variables already have been set by Tcl_MakeSafe(3)
- # We don't try to use the -rsrc on the mac because it would get
- # confusing if you would want to customize init.tcl
- # for a given set of safe slaves, on all the platforms
- # you just need to give a specific access_path and
- # the mac should be no exception. As there is no
- # obvious full "safe ressources" design nor implementation
- # for the mac, safe interps there will just don't
- # have that ability. (A specific app can still reenable
- # that using custom aliases if they want to).
- # It would also make the security analysis and the Safe Tcl security
- # model platform dependant and thus more error prone.
+ # Source init.tcl and tm.tcl into the slave, to get auto_load and
+ # other procedures defined:
- if {[catch {::interp eval $slave\
- {source [file join $tcl_library init.tcl]}} msg]} {
- Log $slave "can't source init.tcl ($msg)"
- error "can't source init.tcl into slave $slave ($msg)"
- }
+ if {[catch {::interp eval $slave {
+ source [file join $tcl_library init.tcl]
+ }} msg]} {
+ Log $slave "can't source init.tcl ($msg)"
+ return -code error "can't source init.tcl into slave $slave ($msg)"
+ }
- return $slave
+ if {[catch {::interp eval $slave {
+ source [file join $tcl_library tm.tcl]
+ }} msg]} {
+ Log $slave "can't source tm.tcl ($msg)"
+ return -code error "can't source tm.tcl into slave $slave ($msg)"
}
+ # Sync the paths used to search for Tcl modules. This can be done only
+ # now, after tm.tcl was loaded.
+ namespace upvar ::safe S$slave state
+ if {[llength $state(tm_path_slave)] > 0} {
+ ::interp eval $slave [list ::tcl::tm::add {*}$state(tm_path_slave)]
+ }
+ return $slave
+}
- # Add (only if needed, avoid duplicates) 1 level of
- # sub directories to an existing path list.
- # Also removes non directories from the returned list.
- proc AddSubDirs {pathList} {
- set res {}
- foreach dir $pathList {
- if {[file isdirectory $dir]} {
- # check that we don't have it yet as a children
- # of a previous dir
- if {[lsearch -exact $res $dir]<0} {
- lappend res $dir
- }
- foreach sub [glob -directory $dir -nocomplain *] {
- if {([file isdirectory $sub]) \
- && ([lsearch -exact $res $sub]<0) } {
- # new sub dir, add it !
- lappend res $sub
- }
+# Add (only if needed, avoid duplicates) 1 level of sub directories to an
+# existing path list. Also removes non directories from the returned
+# list.
+proc ::safe::AddSubDirs {pathList} {
+ set res {}
+ foreach dir $pathList {
+ if {[file isdirectory $dir]} {
+ # check that we don't have it yet as a children of a previous
+ # dir
+ if {$dir ni $res} {
+ lappend res $dir
+ }
+ foreach sub [glob -directory $dir -nocomplain *] {
+ if {[file isdirectory $sub] && ($sub ni $res)} {
+ # new sub dir, add it !
+ lappend res $sub
}
}
}
- return $res
}
+ return $res
+}
- # This procedure deletes a safe slave managed by Safe Tcl and
- # cleans up associated state:
+# This procedure deletes a safe slave managed by Safe Tcl and cleans up
+# associated state:
proc ::safe::interpDelete {slave} {
-
- Log $slave "About to delete" NOTICE
-
- # If the slave has a cleanup hook registered, call it.
- # check the existance because we might be called to delete an interp
- # which has not been registered with us at all
- set hookname [DeleteHookName $slave]
- if {[Exists $hookname]} {
- set hook [Set $hookname]
- if {![::tcl::Lempty $hook]} {
- # remove the hook now, otherwise if the hook
- # calls us somehow, we'll loop
- Unset $hookname
- if {[catch {eval $hook [list $slave]} err]} {
- Log $slave "Delete hook error ($err)"
- }
+ Log $slave "About to delete" NOTICE
+
+ namespace upvar ::safe S$slave state
+
+ # If the slave has a cleanup hook registered, call it. Check the
+ # existance because we might be called to delete an interp which has
+ # not been registered with us at all
+
+ if {[info exists state(cleanupHook)]} {
+ set hook $state(cleanupHook)
+ if {[llength $hook]} {
+ # remove the hook now, otherwise if the hook calls us somehow,
+ # we'll loop
+ unset state(cleanupHook)
+ if {[catch {
+ {*}$hook $slave
+ } err]} {
+ Log $slave "Delete hook error ($err)"
}
}
+ }
- # Discard the global array of state associated with the slave, and
- # delete the interpreter.
+ # Discard the global array of state associated with the slave, and
+ # delete the interpreter.
- set statename [InterpStateName $slave]
- if {[Exists $statename]} {
- Unset $statename
- }
-
- # if we have been called twice, the interp might have been deleted
- # already
- if {[::interp exists $slave]} {
- ::interp delete $slave
- Log $slave "Deleted" NOTICE
- }
+ if {[info exists state]} {
+ unset state
+ }
- return
+ # if we have been called twice, the interp might have been deleted
+ # already
+ if {[::interp exists $slave]} {
+ ::interp delete $slave
+ Log $slave "Deleted" NOTICE
}
- # Set (or get) the loging mecanism
+ return
+}
+
+# Set (or get) the logging mecanism
proc ::safe::setLogCmd {args} {
variable Log
- if {[llength $args] == 0} {
+ set la [llength $args]
+ if {$la == 0} {
return $Log
+ } elseif {$la == 1} {
+ set Log [lindex $args 0]
} else {
- if {[llength $args] == 1} {
- set Log [lindex $args 0]
- } else {
- set Log $args
+ set Log $args
+ }
+
+ if {$Log eq ""} {
+ # Disable logging completely. Calls to it will be compiled out
+ # of all users.
+ proc ::safe::Log {args} {}
+ } else {
+ # Activate logging, define proper command.
+
+ proc ::safe::Log {slave msg {type ERROR}} {
+ variable Log
+ {*}$Log "$type for slave $slave : $msg"
+ return
}
}
}
- # internal variable
- variable Log {}
+# ------------------- END OF PUBLIC METHODS ------------
- # ------------------- END OF PUBLIC METHODS ------------
+#
+# Sets the slave auto_path to the master recorded value. Also sets
+# tcl_library to the first token of the virtual path.
+#
+proc ::safe::SyncAccessPath {slave} {
+ namespace upvar ::safe S$slave state
+ set slave_access_path $state(access_path,slave)
+ ::interp eval $slave [list set auto_path $slave_access_path]
- #
- # sets the slave auto_path to the master recorded value.
- # also sets tcl_library to the first token of the virtual path.
- #
- proc SyncAccessPath {slave} {
- set slave_auto_path [Set [VirtualPathListName $slave]]
- ::interp eval $slave [list set auto_path $slave_auto_path]
- Log $slave "auto_path in $slave has been set to $slave_auto_path"\
- NOTICE
- ::interp eval $slave [list set tcl_library [lindex $slave_auto_path 0]]
- }
-
- # base name for storing all the slave states
- # the array variable name for slave foo is thus "Sfoo"
- # and for sub slave {foo bar} "Sfoo bar" (spaces are handled
- # ok everywhere (or should))
- # We add the S prefix to avoid that a slave interp called "Log"
- # would smash our "Log" variable.
- proc InterpStateName {slave} {
- return "S$slave"
- }
-
- # Check that the given slave is "one of us"
- proc IsInterp {slave} {
- expr {[Exists [InterpStateName $slave]] && [::interp exists $slave]}
- }
-
- # returns the virtual token for directory number N
- # if the slave argument is given,
- # it will return the corresponding master global variable name
- proc PathToken {n {slave ""}} {
- if {$slave ne ""} {
- return "[InterpStateName $slave](access_path,$n)"
- } else {
- # We need to have a ":" in the token string so
- # [file join] on the mac won't turn it into a relative
- # path.
- return "p(:$n:)"
- }
- }
- # returns the variable name of the complete path list
- proc PathListName {slave} {
- return "[InterpStateName $slave](access_path)"
- }
- # returns the variable name of the complete path list
- proc VirtualPathListName {slave} {
- return "[InterpStateName $slave](access_path_slave)"
- }
- # returns the variable name of the number of items
- proc PathNumberName {slave} {
- return "[InterpStateName $slave](access_path,n)"
- }
- # returns the staticsok flag var name
- proc StaticsOkName {slave} {
- return "[InterpStateName $slave](staticsok)"
+ Log $slave "auto_path in $slave has been set to $slave_access_path"\
+ NOTICE
+
+ # This code assumes that info library is the first element in the
+ # list of auto_path's. See -> InterpSetConfig for the code which
+ # ensures this condition.
+
+ ::interp eval $slave [list \
+ set tcl_library [lindex $slave_access_path 0]]
+}
+
+# Returns the virtual token for directory number N.
+proc ::safe::PathToken {n} {
+ # We need to have a ":" in the token string so [file join] on the
+ # mac won't turn it into a relative path.
+ return "\$p(:$n:)" ;# Form tested by case 7.2
+}
+
+#
+# translate virtual path into real path
+#
+proc ::safe::TranslatePath {slave path} {
+ namespace upvar ::safe S$slave state
+
+ # somehow strip the namespaces 'functionality' out (the danger is that
+ # we would strip valid macintosh "../" queries... :
+ if {[string match "*::*" $path] || [string match "*..*" $path]} {
+ return -code error "invalid characters in path $path"
}
- # returns the nestedok flag var name
- proc NestedOkName {slave} {
- return "[InterpStateName $slave](nestedok)"
+
+ # Use a cached map instead of computed local vars and subst.
+
+ return [string map $state(access_path,map) $path]
+}
+
+# file name control (limit access to files/resources that should be a
+# valid tcl source file)
+proc ::safe::CheckFileName {slave file} {
+ # This used to limit what can be sourced to ".tcl" and forbid files
+ # with more than 1 dot and longer than 14 chars, but I changed that
+ # for 8.4 as a safe interp has enough internal protection already to
+ # allow sourcing anything. - hobbs
+
+ if {![file exists $file]} {
+ # don't tell the file path
+ return -code error "no such file or directory"
}
- # Run some code at the namespace toplevel
- proc Toplevel {args} {
- namespace eval [namespace current] $args
+
+ if {![file readable $file]} {
+ # don't tell the file path
+ return -code error "not readable"
}
- # set/get values
- proc Set {args} {
- eval [linsert $args 0 Toplevel set]
+}
+
+# AliasGlob is the target of the "glob" alias in safe interpreters.
+proc ::safe::AliasGlob {slave args} {
+ Log $slave "GLOB ! $args" NOTICE
+ set cmd {}
+ set at 0
+ array set got {
+ -directory 0
+ -nocomplain 0
+ -join 0
+ -tails 0
+ -- 0
}
- # lappend on toplevel vars
- proc Lappend {args} {
- eval [linsert $args 0 Toplevel lappend]
+
+ if {$::tcl_platform(platform) eq "windows"} {
+ set dirPartRE {^(.*)[\\/]}
+ } else {
+ set dirPartRE {^(.*)/}
}
- # unset a var/token (currently just an global level eval)
- proc Unset {args} {
- eval [linsert $args 0 Toplevel unset]
+
+ set dir {}
+ set virtualdir {}
+
+ while {$at < [llength $args]} {
+ switch -glob -- [set opt [lindex $args $at]] {
+ -nocomplain - -- - -join - -tails {
+ lappend cmd $opt
+ set got($opt) 1
+ incr at
+ }
+ -types - -type {
+ lappend cmd -types [lindex $args [incr at]]
+ incr at
+ }
+ -directory {
+ if {$got($opt)} {
+ return -code error \
+ {"-directory" cannot be used with "-path"}
+ }
+ set got($opt) 1
+ set virtualdir [lindex $args [incr at]]
+ incr at
+ }
+ pkgIndex.tcl {
+ # Oops, this is globbing a subdirectory in regular package
+ # search. That is not wanted. Abort, handler does catch
+ # already (because glob was not defined before). See
+ # package.tcl, lines 484ff in tclPkgUnknown.
+ return -code error "unknown command glob"
+ }
+ -* {
+ Log $slave "Safe base rejecting glob option '$opt'"
+ return -code error "Safe base rejecting glob option '$opt'"
+ }
+ default {
+ break
+ }
+ }
+ if {$got(--)} break
}
- # test existance
- proc Exists {varname} {
- Toplevel info exists $varname
+
+ # Get the real path from the virtual one and check that the path is in the
+ # access path of that slave. Done after basic argument processing so that
+ # we know if -nocomplain is set.
+ if {$got(-directory)} {
+ if {[catch {
+ set dir [TranslatePath $slave $virtualdir]
+ DirInAccessPath $slave $dir
+ } msg]} {
+ Log $slave $msg
+ if {!$got(-nocomplain)} {
+ return -code error "permission denied"
+ } else {
+ return
+ }
+ }
+ lappend cmd -directory $dir
}
- # short cut for access path getting
- proc GetAccessPath {slave} {
- Set [PathListName $slave]
+
+ # Apply the -join semantics ourselves
+ if {$got(-join)} {
+ set args [lreplace $args $at end [join [lrange $args $at end] "/"]]
}
- # short cut for statics ok flag getting
- proc StaticsOk {slave} {
- Set [StaticsOkName $slave]
+
+ # Process remaining pattern arguments
+ set firstPattern [llength $cmd]
+ while {$at < [llength $args]} {
+ set opt [lindex $args $at]
+ incr at
+ if {[regexp $dirPartRE $opt -> thedir] && [catch {
+ set thedir [file join $virtualdir $thedir]
+ DirInAccessPath $slave [TranslatePath $slave $thedir]
+ } msg]} {
+ Log $slave $msg
+ if {$got(-nocomplain)} {
+ continue
+ } else {
+ return -code error "permission denied"
+ }
+ }
+ lappend cmd $opt
}
- # short cut for getting the multiples interps sub loading ok flag
- proc NestedOk {slave} {
- Set [NestedOkName $slave]
+
+ Log $slave "GLOB = $cmd" NOTICE
+
+ if {$got(-nocomplain) && [llength $cmd] eq $firstPattern} {
+ return
}
- # interp deletion storing hook name
- proc DeleteHookName {slave} {
- return [InterpStateName $slave](cleanupHook)
+ if {[catch {
+ ::interp invokehidden $slave glob {*}$cmd
+ } msg]} {
+ Log $slave $msg
+ return -code error "script error"
}
- #
- # translate virtual path into real path
- #
- proc TranslatePath {slave path} {
- # somehow strip the namespaces 'functionality' out (the danger
- # is that we would strip valid macintosh "../" queries... :
- if {[regexp {(::)|(\.\.)} $path]} {
- error "invalid characters in path $path"
- }
- set n [expr {[Set [PathNumberName $slave]]-1}]
- for {} {$n>=0} {incr n -1} {
- # fill the token virtual names with their real value
- set [PathToken $n] [Set [PathToken $n $slave]]
+ Log $slave "GLOB @ $msg" NOTICE
+
+ # Translate path back to what the slave should see.
+ set res {}
+ set l [string length $dir]
+ foreach p $msg {
+ if {[string equal -length $l $dir $p]} {
+ set p [string replace $p 0 [expr {$l-1}] $virtualdir]
}
- # replaces the token by their value
- subst -nobackslashes -nocommands $path
+ lappend res $p
}
+ Log $slave "GLOB @ $res" NOTICE
+ return $res
+}
- # Log eventually log an error
- # to enable error logging, set Log to {puts stderr} for instance
- proc Log {slave msg {type ERROR}} {
- variable Log
- if {[info exists Log] && [llength $Log]} {
- eval $Log [list "$type for slave $slave : $msg"]
+# AliasSource is the target of the "source" alias in safe interpreters.
+
+proc ::safe::AliasSource {slave args} {
+ set argc [llength $args]
+ # Extended for handling of Tcl Modules to allow not only "source
+ # filename", but "source -encoding E filename" as well.
+ if {[lindex $args 0] eq "-encoding"} {
+ incr argc -2
+ set encoding [lindex $args 1]
+ set at 2
+ if {$encoding eq "identity"} {
+ Log $slave "attempt to use the identity encoding"
+ return -code error "permission denied"
}
+ } else {
+ set at 0
+ set encoding {}
+ }
+ if {$argc != 1} {
+ set msg "wrong # args: should be \"source ?-encoding E? fileName\""
+ Log $slave "$msg ($args)"
+ return -code error $msg
+ }
+ set file [lindex $args $at]
+
+ # get the real path from the virtual one.
+ if {[catch {
+ set realfile [TranslatePath $slave $file]
+ } msg]} {
+ Log $slave $msg
+ return -code error "permission denied"
+ }
+
+ # check that the path is in the access path of that slave
+ if {[catch {
+ FileInAccessPath $slave $realfile
+ } msg]} {
+ Log $slave $msg
+ return -code error "permission denied"
}
+ # do the checks on the filename :
+ if {[catch {
+ CheckFileName $slave $realfile
+ } msg]} {
+ Log $slave "$realfile:$msg"
+ return -code error $msg
+ }
- # file name control (limit access to files/ressources that should be
- # a valid tcl source file)
- proc CheckFileName {slave file} {
- # This used to limit what can be sourced to ".tcl" and forbid files
- # with more than 1 dot and longer than 14 chars, but I changed that
- # for 8.4 as a safe interp has enough internal protection already
- # to allow sourcing anything. - hobbs
-
- if {![file exists $file]} {
- # don't tell the file path
- error "no such file or directory"
+ # Passed all the tests, lets source it. Note that we do this all manually
+ # because we want to control [info script] in the slave so information
+ # doesn't leak so much. [Bug 2913625]
+ set old [::interp eval $slave {info script}]
+ set code [catch {
+ set f [open $realfile]
+ fconfigure $f -eofchar \032
+ if {$encoding ne ""} {
+ fconfigure $f -encoding $encoding
}
+ set contents [read $f]
+ close $f
+ ::interp eval $slave [list info script $file]
+ ::interp eval $slave $contents
+ } msg opt]
+ catch {interp eval $slave [list info script $old]}
+ # Note that all non-errors are fine result codes from [source], so we must
+ # take a little care to do it properly. [Bug 2923613]
+ if {$code == 1} {
+ Log $slave $msg
+ return -code error "script error"
+ }
+ return -code $code -options $opt $msg
+}
- if {![file readable $file]} {
- # don't tell the file path
- error "not readable"
- }
+# AliasLoad is the target of the "load" alias in safe interpreters.
+
+proc ::safe::AliasLoad {slave file args} {
+ set argc [llength $args]
+ if {$argc > 2} {
+ set msg "load error: too many arguments"
+ Log $slave "$msg ($argc) {$file $args}"
+ return -code error $msg
}
+ # package name (can be empty if file is not).
+ set package [lindex $args 0]
- # AliasSource is the target of the "source" alias in safe interpreters.
+ namespace upvar ::safe S$slave state
- proc AliasSource {slave args} {
+ # Determine where to load. load use a relative interp path and {}
+ # means self, so we can directly and safely use passed arg.
+ set target [lindex $args 1]
+ if {$target ne ""} {
+ # we will try to load into a sub sub interp; check that we want to
+ # authorize that.
+ if {!$state(nestedok)} {
+ Log $slave "loading to a sub interp (nestedok)\
+ disabled (trying to load $package to $target)"
+ return -code error "permission denied (nested load)"
+ }
+ }
- set argc [llength $args]
- # Allow only "source filename"
- # (and not mac specific -rsrc for instance - see comment in ::init
- # for current rationale)
- if {$argc != 1} {
- set msg "wrong # args: should be \"source fileName\""
- Log $slave "$msg ($args)"
+ # Determine what kind of load is requested
+ if {$file eq ""} {
+ # static package loading
+ if {$package eq ""} {
+ set msg "load error: empty filename and no package name"
+ Log $slave $msg
return -code error $msg
}
- set file [lindex $args 0]
-
- # get the real path from the virtual one.
- if {[catch {set file [TranslatePath $slave $file]} msg]} {
- Log $slave $msg
- return -code error "permission denied"
+ if {!$state(staticsok)} {
+ Log $slave "static packages loading disabled\
+ (trying to load $package to $target)"
+ return -code error "permission denied (static package)"
}
-
- # check that the path is in the access path of that slave
- if {[catch {FileInAccessPath $slave $file} msg]} {
+ } else {
+ # file loading
+
+ # get the real path from the virtual one.
+ if {[catch {
+ set file [TranslatePath $slave $file]
+ } msg]} {
Log $slave $msg
return -code error "permission denied"
}
- # do the checks on the filename :
- if {[catch {CheckFileName $slave $file} msg]} {
- Log $slave "$file:$msg"
- return -code error $msg
- }
-
- # passed all the tests , lets source it:
- if {[catch {::interp invokehidden $slave source $file} msg]} {
+ # check the translated path
+ if {[catch {
+ FileInAccessPath $slave $file
+ } msg]} {
Log $slave $msg
- return -code error "script error"
+ return -code error "permission denied (path)"
}
- return $msg
}
- # AliasLoad is the target of the "load" alias in safe interpreters.
+ if {[catch {
+ ::interp invokehidden $slave load $file $package $target
+ } msg]} {
+ Log $slave $msg
+ return -code error $msg
+ }
- proc AliasLoad {slave file args} {
+ return $msg
+}
- set argc [llength $args]
- if {$argc > 2} {
- set msg "load error: too many arguments"
- Log $slave "$msg ($argc) {$file $args}"
- return -code error $msg
- }
+# FileInAccessPath raises an error if the file is not found in the list of
+# directories contained in the (master side recorded) slave's access path.
- # package name (can be empty if file is not).
- set package [lindex $args 0]
-
- # Determine where to load. load use a relative interp path
- # and {} means self, so we can directly and safely use passed arg.
- set target [lindex $args 1]
- if {$target ne ""} {
- # we will try to load into a sub sub interp
- # check that we want to authorize that.
- if {![NestedOk $slave]} {
- Log $slave "loading to a sub interp (nestedok)\
- disabled (trying to load $package to $target)"
- return -code error "permission denied (nested load)"
- }
-
- }
+# the security here relies on "file dirname" answering the proper
+# result... needs checking ?
+proc ::safe::FileInAccessPath {slave file} {
+ namespace upvar ::safe S$slave state
+ set access_path $state(access_path)
- # Determine what kind of load is requested
- if {$file eq ""} {
- # static package loading
- if {$package eq ""} {
- set msg "load error: empty filename and no package name"
- Log $slave $msg
- return -code error $msg
- }
- if {![StaticsOk $slave]} {
- Log $slave "static packages loading disabled\
- (trying to load $package to $target)"
- return -code error "permission denied (static package)"
- }
- } else {
- # file loading
+ if {[file isdirectory $file]} {
+ return -code error "\"$file\": is a directory"
+ }
+ set parent [file dirname $file]
- # get the real path from the virtual one.
- if {[catch {set file [TranslatePath $slave $file]} msg]} {
- Log $slave $msg
- return -code error "permission denied"
- }
+ # Normalize paths for comparison since lsearch knows nothing of
+ # potential pathname anomalies.
+ set norm_parent [file normalize $parent]
- # check the translated path
- if {[catch {FileInAccessPath $slave $file} msg]} {
- Log $slave $msg
- return -code error "permission denied (path)"
- }
- }
+ namespace upvar ::safe S$slave state
+ if {$norm_parent ni $state(access_path,norm)} {
+ return -code error "\"$file\": not in access_path"
+ }
+}
- if {[catch {::interp invokehidden\
- $slave load $file $package $target} msg]} {
- Log $slave $msg
- return -code error $msg
- }
+proc ::safe::DirInAccessPath {slave dir} {
+ namespace upvar ::safe S$slave state
+ set access_path $state(access_path)
- return $msg
+ if {[file isfile $dir]} {
+ return -code error "\"$dir\": is a file"
}
- # FileInAccessPath raises an error if the file is not found in
- # the list of directories contained in the (master side recorded) slave's
- # access path.
+ # Normalize paths for comparison since lsearch knows nothing of
+ # potential pathname anomalies.
+ set norm_dir [file normalize $dir]
- # the security here relies on "file dirname" answering the proper
- # result.... needs checking ?
- proc FileInAccessPath {slave file} {
+ namespace upvar ::safe S$slave state
+ if {$norm_dir ni $state(access_path,norm)} {
+ return -code error "\"$dir\": not in access_path"
+ }
+}
- set access_path [GetAccessPath $slave]
+# This procedure enables access from a safe interpreter to only a subset
+# of the subcommands of a command:
- if {[file isdirectory $file]} {
- error "\"$file\": is a directory"
- }
- set parent [file dirname $file]
+proc ::safe::Subset {slave command okpat args} {
+ set subcommand [lindex $args 0]
+ if {[regexp $okpat $subcommand]} {
+ return [$command {*}$args]
+ }
+ set msg "not allowed to invoke subcommand $subcommand of $command"
+ Log $slave $msg
+ return -code error $msg
+}
- # Normalize paths for comparison since lsearch knows nothing of
- # potential pathname anomalies.
- set norm_parent [file normalize $parent]
- foreach path $access_path {
- lappend norm_access_path [file normalize $path]
- }
+# This procedure installs an alias in a slave that invokes "safesubset" in
+# the master to execute allowed subcommands. It precomputes the pattern of
+# allowed subcommands; you can use wildcards in the pattern if you wish to
+# allow subcommand abbreviation.
+#
+# Syntax is: AliasSubset slave alias target subcommand1 subcommand2...
- if {[lsearch -exact $norm_access_path $norm_parent] == -1} {
- error "\"$file\": not in access_path"
- }
- }
+proc ::safe::AliasSubset {slave alias target args} {
+ set pat "^([join $args |])\$"
+ ::interp alias $slave $alias {}\
+ [namespace current]::Subset $slave $target $pat
+}
- # This procedure enables access from a safe interpreter to only a subset of
- # the subcommands of a command:
+# AliasEncoding is the target of the "encoding" alias in safe interpreters.
- proc Subset {slave command okpat args} {
- set subcommand [lindex $args 0]
- if {[regexp $okpat $subcommand]} {
- return [eval [linsert $args 0 $command]]
+proc ::safe::AliasEncoding {slave option args} {
+ # Careful; do not want empty option to get through to the [string equal]
+ if {[regexp {^(name.*|convert.*|)$} $option]} {
+ return [::interp invokehidden $slave encoding $option {*}$args]
+ }
+
+ if {[string equal -length [string length $option] $option "system"]} {
+ if {[llength $args] == 0} {
+ # passed all the tests , lets source it:
+ if {[catch {
+ set sysenc [::interp invokehidden $slave encoding system]
+ } msg]} {
+ Log $slave $msg
+ return -code error "script error"
+ }
+ return $sysenc
}
- set msg "not allowed to invoke subcommand $subcommand of $command"
- Log $slave $msg
- error $msg
+ set msg "wrong # args: should be \"encoding system\""
+ set code {TCL WRONGARGS}
+ } else {
+ set msg "bad option \"$option\": must be convertfrom, convertto, names, or system"
+ set code [list TCL LOOKUP INDEX option $option]
}
+ Log $slave $msg
+ return -code error -errorcode $code $msg
+}
+
+# Various minor hiding of platform features. [Bug 2913625]
+
+proc ::safe::AliasExeName {slave} {
+ return ""
+}
- # This procedure installs an alias in a slave that invokes "safesubset"
- # in the master to execute allowed subcommands. It precomputes the pattern
- # of allowed subcommands; you can use wildcards in the pattern if you wish
- # to allow subcommand abbreviation.
+proc ::safe::Setup {} {
+ ####
+ #
+ # Setup the arguments parsing
#
- # Syntax is: AliasSubset slave alias target subcommand1 subcommand2...
+ ####
- proc AliasSubset {slave alias target args} {
- set pat ^(; set sep ""
- foreach sub $args {
- append pat $sep$sub
- set sep |
- }
- append pat )\$
- ::interp alias $slave $alias {}\
- [namespace current]::Subset $slave $target $pat
- }
+ # Share the descriptions
+ set temp [::tcl::OptKeyRegister {
+ {-accessPath -list {} "access path for the slave"}
+ {-noStatics "prevent loading of statically linked pkgs"}
+ {-statics true "loading of statically linked pkgs"}
+ {-nestedLoadOk "allow nested loading"}
+ {-nested false "nested loading"}
+ {-deleteHook -script {} "delete hook"}
+ }]
- # AliasEncoding is the target of the "encoding" alias in safe interpreters.
+ # create case (slave is optional)
+ ::tcl::OptKeyRegister {
+ {?slave? -name {} "name of the slave (optional)"}
+ } ::safe::interpCreate
- proc AliasEncoding {slave args} {
+ # adding the flags sub programs to the command program (relying on Opt's
+ # internal implementation details)
+ lappend ::tcl::OptDesc(::safe::interpCreate) $::tcl::OptDesc($temp)
- set argc [llength $args]
+ # init and configure (slave is needed)
+ ::tcl::OptKeyRegister {
+ {slave -name {} "name of the slave"}
+ } ::safe::interpIC
- set okpat "^(name.*|convert.*)\$"
- set subcommand [lindex $args 0]
+ # adding the flags sub programs to the command program (relying on Opt's
+ # internal implementation details)
+ lappend ::tcl::OptDesc(::safe::interpIC) $::tcl::OptDesc($temp)
- if {[regexp $okpat $subcommand]} {
- return [eval [linsert $args 0 \
- ::interp invokehidden $slave encoding]]
- }
+ # temp not needed anymore
+ ::tcl::OptKeyDelete $temp
- if {[string first $subcommand system] == 0} {
- if {$argc == 1} {
- # passed all the tests , lets source it:
- if {[catch {::interp invokehidden \
- $slave encoding system} msg]} {
- Log $slave $msg
- return -code error "script error"
- }
- } else {
- set msg "wrong # args: should be \"encoding system\""
- Log $slave $msg
- error $msg
- }
- } else {
- set msg "wrong # args: should be \"encoding option ?arg ...?\""
- Log $slave $msg
- error $msg
- }
+ ####
+ #
+ # Default: No logging.
+ #
+ ####
- return $msg
- }
+ setLogCmd {}
+
+ # Log eventually.
+ # To enable error logging, set Log to {puts stderr} for instance,
+ # via setLogCmd.
+ return
+}
+
+namespace eval ::safe {
+ # internal variables
+ # Log command, set via 'setLogCmd'. Logging is disabled when empty.
+ variable Log {}
+
+ # The package maintains a state array per slave interp under its
+ # control. The name of this array is S<interp-name>. This array is
+ # brought into scope where needed, using 'namespace upvar'. The S
+ # prefix is used to avoid that a slave interp called "Log" smashes
+ # the "Log" variable.
+ #
+ # The array's elements are:
+ #
+ # access_path : List of paths accessible to the slave.
+ # access_path,norm : Ditto, in normalized form.
+ # access_path,slave : Ditto, as the path tokens as seen by the slave.
+ # access_path,map : dict ( token -> path )
+ # access_path,remap : dict ( path -> token )
+ # tm_path_slave : List of TM root directories, as tokens seen by the slave.
+ # staticsok : Value of option -statics
+ # nestedok : Value of option -nested
+ # cleanupHook : Value of option -deleteHook
}
+
+::safe::Setup
diff --git a/library/tclIndex b/library/tclIndex
index 16680ea..010616f 100644
--- a/library/tclIndex
+++ b/library/tclIndex
@@ -27,13 +27,10 @@ set auto_index(::tcl::HistRedo) [list source [file join $dir history.tcl]]
set auto_index(::tcl::HistIndex) [list source [file join $dir history.tcl]]
set auto_index(::tcl::HistEvent) [list source [file join $dir history.tcl]]
set auto_index(::tcl::HistChange) [list source [file join $dir history.tcl]]
-set auto_index(tclLdAout) [list source [file join $dir ldAout.tcl]]
-set auto_index(pkg_compareExtension) [list source [file join $dir package.tcl]]
set auto_index(pkg_mkIndex) [list source [file join $dir package.tcl]]
set auto_index(tclPkgSetup) [list source [file join $dir package.tcl]]
set auto_index(tclPkgUnknown) [list source [file join $dir package.tcl]]
set auto_index(::tcl::MacOSXPkgUnknown) [list source [file join $dir package.tcl]]
-set auto_index(::tcl::MacPkgUnknown) [list source [file join $dir package.tcl]]
set auto_index(::pkg::create) [list source [file join $dir package.tcl]]
set auto_index(parray) [list source [file join $dir parray.tcl]]
set auto_index(::safe::InterpStatics) [list source [file join $dir safe.tcl]]
@@ -76,8 +73,15 @@ set auto_index(::safe::AliasLoad) [list source [file join $dir safe.tcl]]
set auto_index(::safe::FileInAccessPath) [list source [file join $dir safe.tcl]]
set auto_index(::safe::Subset) [list source [file join $dir safe.tcl]]
set auto_index(::safe::AliasSubset) [list source [file join $dir safe.tcl]]
+set auto_index(::safe::AliasEncoding) [list source [file join $dir safe.tcl]]
set auto_index(tcl_wordBreakAfter) [list source [file join $dir word.tcl]]
set auto_index(tcl_wordBreakBefore) [list source [file join $dir word.tcl]]
set auto_index(tcl_endOfWord) [list source [file join $dir word.tcl]]
set auto_index(tcl_startOfNextWord) [list source [file join $dir word.tcl]]
set auto_index(tcl_startOfPreviousWord) [list source [file join $dir word.tcl]]
+set auto_index(::tcl::tm::add) [list source [file join $dir tm.tcl]]
+set auto_index(::tcl::tm::remove) [list source [file join $dir tm.tcl]]
+set auto_index(::tcl::tm::list) [list source [file join $dir tm.tcl]]
+set auto_index(::tcl::tm::UnknownHandler) [list source [file join $dir tm.tcl]]
+set auto_index(::tcl::tm::roots) [list source [file join $dir tm.tcl]]
+set auto_index(::tcl::tm::path) [list source [file join $dir tm.tcl]]
diff --git a/library/tcltest/pkgIndex.tcl b/library/tcltest/pkgIndex.tcl
index e569fa5..2eb43a6 100644
--- a/library/tcltest/pkgIndex.tcl
+++ b/library/tcltest/pkgIndex.tcl
@@ -8,5 +8,5 @@
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.
-if {![package vsatisfies [package provide Tcl] 8.3]} {return}
-package ifneeded tcltest 2.2.10 [list source [file join $dir tcltest.tcl]]
+if {![package vsatisfies [package provide Tcl] 8.5]} {return}
+package ifneeded tcltest 2.3.3 [list source [file join $dir tcltest.tcl]]
diff --git a/library/tcltest/tcltest.tcl b/library/tcltest/tcltest.tcl
index 8e70628..af809f6 100644
--- a/library/tcltest/tcltest.tcl
+++ b/library/tcltest/tcltest.tcl
@@ -16,13 +16,13 @@
# Contributions from Don Porter, NIST, 2002. (not subject to US copyright)
# All rights reserved.
-package require Tcl 8.3 ;# uses [glob -directory]
+package require Tcl 8.5 ;# -verbose line uses [info frame]
namespace eval tcltest {
# When the version number changes, be sure to update the pkgIndex.tcl file,
# and the install directory in the Makefiles. When the minor version
# changes (new feature) be sure to update the man page as well.
- variable Version 2.2.10
+ variable Version 2.3.3
# Compatibility support for dumb variables defined in tcltest 1
# Do not use these. Call [package provide Tcl] and [info patchlevel]
@@ -600,22 +600,22 @@ namespace eval tcltest {
}
proc configure args {
RemoveAutoConfigureTraces
- set code [catch {eval Configure $args} msg]
+ set code [catch {Configure {*}$args} msg]
return -code $code $msg
}
proc AcceptVerbose { level } {
set level [AcceptList $level]
if {[llength $level] == 1} {
- if {![regexp {^(pass|body|skip|start|error)$} $level]} {
+ if {![regexp {^(pass|body|skip|start|error|line)$} $level]} {
# translate single characters abbreviations to expanded list
- set level [string map {p pass b body s skip t start e error} \
+ set level [string map {p pass b body s skip t start e error l line} \
[split $level {}]]
}
}
set valid [list]
foreach v $level {
- if {[regexp {^(pass|body|skip|start|error)$} $v]} {
+ if {[regexp {^(pass|body|skip|start|error|line)$} $v]} {
lappend valid $v
}
}
@@ -629,11 +629,12 @@ namespace eval tcltest {
# Default verbosity is to show bodies of failed tests
Option -verbose {body error} {
- Takes any combination of the values 'p', 's', 'b', 't' and 'e'.
+ Takes any combination of the values 'p', 's', 'b', 't', 'e' and 'l'.
Test suite will display all passed tests if 'p' is specified, all
skipped tests if 's' is specified, the bodies of failed tests if
'b' is specified, and when tests start if 't' is specified.
- ErrorInfo is displayed if 'e' is specified.
+ ErrorInfo is displayed if 'e' is specified. Source file line
+ information of failed tests is displayed if 'l' is specified.
} AcceptVerbose verbose
# Match and skip patterns default to the empty list, except for
@@ -794,6 +795,29 @@ namespace eval tcltest {
trace variable Option(-errfile) w \
[namespace code {errorChannel $Option(-errfile) ;#}]
+ proc loadIntoSlaveInterpreter {slave args} {
+ variable Version
+ interp eval $slave [package ifneeded tcltest $Version]
+ interp eval $slave "tcltest::configure {*}{$args}"
+ interp alias $slave ::tcltest::ReportToMaster \
+ {} ::tcltest::ReportedFromSlave
+ }
+ proc ReportedFromSlave {total passed skipped failed because newfiles} {
+ variable numTests
+ variable skippedBecause
+ variable createdNewFiles
+ incr numTests(Total) $total
+ incr numTests(Passed) $passed
+ incr numTests(Skipped) $skipped
+ incr numTests(Failed) $failed
+ foreach {constraint count} $because {
+ incr skippedBecause($constraint) $count
+ }
+ foreach {testfile created} $newfiles {
+ lappend createdNewFiles($testfile) {*}$created
+ }
+ return
+ }
}
#####################################################################
@@ -1417,7 +1441,7 @@ proc tcltest::ProcessFlags {flagArray} {
RemoveAutoConfigureTraces
} else {
set args $flagArray
- while {[llength $args]>1 && [catch {eval [linsert $args 0 configure]} msg]} {
+ while {[llength $args]>1 && [catch {configure {*}$args} msg]} {
# Something went wrong parsing $args for tcltest options
# Check whether the problem is "unknown option"
@@ -1582,7 +1606,7 @@ proc tcltest::Replace::puts {args} {
# If we haven't returned by now, we don't know how to handle the
# input. Let puts handle it.
- return [eval Puts $args]
+ return [Puts {*}$args]
}
# tcltest::Eval --
@@ -1611,8 +1635,7 @@ proc tcltest::Eval {script {ignoreOutput 1}} {
set outData {}
set errData {}
rename ::puts [namespace current]::Replace::Puts
- namespace eval :: \
- [list namespace import [namespace origin Replace::puts]]
+ namespace eval :: [list namespace import [namespace origin Replace::puts]]
namespace import Replace::puts
}
set result [uplevel 1 $script]
@@ -2085,7 +2108,28 @@ proc tcltest::test {name description args} {
if {![IsVerbose body]} {
set body ""
}
- puts [outputChannel] "\n==== $name\
+ puts [outputChannel] "\n"
+ if {[IsVerbose line]} {
+ if {![catch {set testFrame [info frame -1]}] &&
+ [dict get $testFrame type] eq "source"} {
+ set testFile [dict get $testFrame file]
+ set testLine [dict get $testFrame line]
+ } else {
+ set testFile [file normalize [uplevel 1 {info script}]]
+ if {[file readable $testFile]} {
+ set testFd [open $testFile r]
+ set testLine [expr {[lsearch -regexp \
+ [split [read $testFd] "\n"] \
+ "^\[ \t\]*test [string map {. \\.} $name] "]+1}]
+ close $testFd
+ }
+ }
+ if {[info exists testLine]} {
+ puts [outputChannel] "$testFile:$testLine: error: test failed:\
+ $name [string trim $description]"
+ }
+ }
+ puts [outputChannel] "==== $name\
[string trim $description] FAILED"
if {[string length $body]} {
puts [outputChannel] "==== Contents of test case:"
@@ -2333,6 +2377,14 @@ proc tcltest::cleanupTests {{calledFromAllFile 0}} {
FillFilesExisted
set testFileName [file tail [info script]]
+ # Hook to handle reporting to a parent interpreter
+ if {[llength [info commands [namespace current]::ReportToMaster]]} {
+ ReportToMaster $numTests(Total) $numTests(Passed) $numTests(Skipped) \
+ $numTests(Failed) [array get skippedBecause] \
+ [array get createdNewFiles]
+ set testSingleFile false
+ }
+
# Call the cleanup hook
cleanupTestsHook
@@ -2548,7 +2600,7 @@ proc tcltest::cleanupTests {{calledFromAllFile 0}} {
# None
# a lower case version is needed for compatibility with tcltest 1.0
-proc tcltest::getMatchingFiles args {eval GetMatchingFiles $args}
+proc tcltest::getMatchingFiles args {GetMatchingFiles {*}$args}
proc tcltest::GetMatchingFiles { args } {
if {[llength $args]} {
@@ -3308,7 +3360,7 @@ namespace eval tcltest {
-option value ?-option value ...?"
return
}
- if {[catch {eval [linsert $options 0 Configure]} msg]} {
+ if {[catch {Configure {*}$options} msg]} {
Warn "invalid TCLTEST_OPTIONS: \"$options\":\n $msg"
return
}
diff --git a/library/tm.tcl b/library/tm.tcl
new file mode 100644
index 0000000..c5db437
--- /dev/null
+++ b/library/tm.tcl
@@ -0,0 +1,380 @@
+# -*- tcl -*-
+#
+# Searching for Tcl Modules. Defines a procedure, declares it as the
+# primary command for finding packages, however also uses the former
+# 'package unknown' command as a fallback.
+#
+# Locates all possible packages in a directory via a less restricted
+# glob. The targeted directory is derived from the name of the
+# requested package. I.e. the TM scan will look only at directories
+# which can contain the requested package. It will register all
+# packages it found in the directory so that future requests have a
+# higher chance of being fulfilled by the ifneeded database without
+# having to come to us again.
+#
+# We do not remember where we have been and simply rescan targeted
+# directories when invoked again. The reasoning is this:
+#
+# - The only way we get back to the same directory is if someone is
+# trying to [package require] something that wasn't there on the
+# first scan.
+#
+# Either
+# 1) It is there now: If we rescan, you get it; if not you don't.
+#
+# This covers the possibility that the application asked for a
+# package late, and the package was actually added to the
+# installation after the application was started. It shoukld
+# still be able to find it.
+#
+# 2) It still is not there: Either way, you don't get it, but the
+# rescan takes time. This is however an error case and we dont't
+# care that much about it
+#
+# 3) It was there the first time; but for some reason a "package
+# forget" has been run, and "package" doesn't know about it
+# anymore.
+#
+# This can be an indication that the application wishes to reload
+# some functionality. And should work as well.
+#
+# Note that this also strikes a balance between doing a glob targeting
+# a single package, and thus most likely requiring multiple globs of
+# the same directory when the application is asking for many packages,
+# and trying to glob for _everything_ in all subdirectories when
+# looking for a package, which comes with a heavy startup cost.
+#
+# We scan for regular packages only if no satisfying module was found.
+
+namespace eval ::tcl::tm {
+ # Default paths. None yet.
+
+ variable paths {}
+
+ # The regex pattern a file name has to match to make it a Tcl Module.
+
+ set pkgpattern {^([_[:alpha:]][:_[:alnum:]]*)-([[:digit:]].*)[.]tm$}
+
+ # Export the public API
+
+ namespace export path
+ namespace ensemble create -command path -subcommand {add remove list}
+}
+
+# ::tcl::tm::path implementations --
+#
+# Public API to the module path. See specification.
+#
+# Arguments
+# cmd - The subcommand to execute
+# args - The paths to add/remove. Must not appear querying the
+# path with 'list'.
+#
+# Results
+# No result for subcommands 'add' and 'remove'. A list of paths
+# for 'list'.
+#
+# Sideeffects
+# The subcommands 'add' and 'remove' manipulate the list of
+# paths to search for Tcl Modules. The subcommand 'list' has no
+# sideeffects.
+
+proc ::tcl::tm::add {path args} {
+ # PART OF THE ::tcl::tm::path ENSEMBLE
+ #
+ # The path is added at the head to the list of module paths.
+ #
+ # The command enforces the restriction that no path may be an
+ # ancestor directory of any other path on the list. If the new
+ # path violates this restriction an error wil be raised.
+ #
+ # If the path is already present as is no error will be raised and
+ # no action will be taken.
+
+ variable paths
+
+ # We use a copy of the path as source during validation, and
+ # extend it as well. Because we not only have to detect if the new
+ # paths are bogus with respect to the existing paths, but also
+ # between themselves. Otherwise we can still add bogus paths, by
+ # specifying them in a single call. This makes the use of the new
+ # paths simpler as well, a trivial assignment of the collected
+ # paths to the official state var.
+
+ set newpaths $paths
+ foreach p [linsert $args 0 $path] {
+ if {$p in $newpaths} {
+ # Ignore a path already on the list.
+ continue
+ }
+
+ # Search for paths which are subdirectories of the new one. If
+ # there are any then the new path violates the restriction
+ # about ancestors.
+
+ set pos [lsearch -glob $newpaths ${p}/*]
+ # Cannot use "in", we need the position for the message.
+ if {$pos >= 0} {
+ return -code error \
+ "$p is ancestor of existing module path [lindex $newpaths $pos]."
+ }
+
+ # Now look for existing paths which are ancestors of the new
+ # one. This reverse question forces us to loop over the
+ # existing paths, as each element is the pattern, not the new
+ # path :(
+
+ foreach ep $newpaths {
+ if {[string match ${ep}/* $p]} {
+ return -code error \
+ "$p is subdirectory of existing module path $ep."
+ }
+ }
+
+ set newpaths [linsert $newpaths 0 $p]
+ }
+
+ # The validation of the input is complete and successful, and
+ # everything in newpaths is either an old path, or added. We can
+ # now extend the official list of paths, a simple assignment is
+ # sufficient.
+
+ set paths $newpaths
+ return
+}
+
+proc ::tcl::tm::remove {path args} {
+ # PART OF THE ::tcl::tm::path ENSEMBLE
+ #
+ # Removes the path from the list of module paths. The command is
+ # silently ignored if the path is not on the list.
+
+ variable paths
+
+ foreach p [linsert $args 0 $path] {
+ set pos [lsearch -exact $paths $p]
+ if {$pos >= 0} {
+ set paths [lreplace $paths $pos $pos]
+ }
+ }
+}
+
+proc ::tcl::tm::list {} {
+ # PART OF THE ::tcl::tm::path ENSEMBLE
+
+ variable paths
+ return $paths
+}
+
+# ::tcl::tm::UnknownHandler --
+#
+# Unknown handler for Tcl Modules, i.e. packages in module form.
+#
+# Arguments
+# original - Original [package unknown] procedure.
+# name - Name of desired package.
+# version - Version of desired package. Can be the
+# empty string.
+# exact - Either -exact or ommitted.
+#
+# Name, version, and exact are used to determine
+# satisfaction. The original is called iff no satisfaction was
+# achieved. The name is also used to compute the directory to
+# target in the search.
+#
+# Results
+# None.
+#
+# Sideeffects
+# May populate the package ifneeded database with additional
+# provide scripts.
+
+proc ::tcl::tm::UnknownHandler {original name args} {
+ # Import the list of paths to search for packages in module form.
+ # Import the pattern used to check package names in detail.
+
+ variable paths
+ variable pkgpattern
+
+ # Without paths to search we can do nothing. (Except falling back
+ # to the regular search).
+
+ if {[llength $paths]} {
+ set pkgpath [string map {:: /} $name]
+ set pkgroot [file dirname $pkgpath]
+ if {$pkgroot eq "."} {
+ set pkgroot ""
+ }
+
+ # We don't remember a copy of the paths while looping. Tcl
+ # Modules are unable to change the list while we are searching
+ # for them. This also simplifies the loop, as we cannot get
+ # additional directories while iterating over the list. A
+ # simple foreach is sufficient.
+
+ set satisfied 0
+ foreach path $paths {
+ if {![interp issafe] && ![file exists $path]} {
+ continue
+ }
+ set currentsearchpath [file join $path $pkgroot]
+ if {![interp issafe] && ![file exists $currentsearchpath]} {
+ continue
+ }
+ set strip [llength [file split $path]]
+
+ # We can't use glob in safe interps, so enclose the following
+ # in a catch statement, where we get the module files out
+ # of the subdirectories. In other words, Tcl Modules are
+ # not-functional in such an interpreter. This is the same
+ # as for the command "tclPkgUnknown", i.e. the search for
+ # regular packages.
+
+ catch {
+ # We always look for _all_ possible modules in the current
+ # path, to get the max result out of the glob.
+
+ foreach file [glob -nocomplain -directory $currentsearchpath *.tm] {
+ set pkgfilename [join [lrange [file split $file] $strip end] ::]
+
+ if {![regexp -- $pkgpattern $pkgfilename --> pkgname pkgversion]} {
+ # Ignore everything not matching our pattern
+ # for package names.
+ continue
+ }
+ if {[catch {package vcompare $pkgversion 0}]} {
+ # Ignore everything where the version part is
+ # not acceptable to "package vcompare".
+ continue
+ }
+
+ # We have found a candidate, generate a "provide
+ # script" for it, and remember it. Note that we
+ # are using ::list to do this; locally [list]
+ # means something else without the namespace
+ # specifier.
+
+ # NOTE. When making changes to the format of the
+ # provide command generated below CHECK that the
+ # 'LOCATE' procedure in core file
+ # 'platform/shell.tcl' still understands it, or,
+ # if not, update its implementation appropriately.
+ #
+ # Right now LOCATE's implementation assumes that
+ # the path of the package file is the last element
+ # in the list.
+
+ package ifneeded $pkgname $pkgversion \
+ "[::list package provide $pkgname $pkgversion];[::list source -encoding utf-8 $file]"
+
+ # We abort in this unknown handler only if we got
+ # a satisfying candidate for the requested
+ # package. Otherwise we still have to fallback to
+ # the regular package search to complete the
+ # processing.
+
+ if {
+ ($pkgname eq $name) &&
+ [package vsatisfies $pkgversion {*}$args]
+ } then {
+ set satisfied 1
+ # We do not abort the loop, and keep adding
+ # provide scripts for every candidate in the
+ # directory, just remember to not fall back to
+ # the regular search anymore.
+ }
+ }
+ }
+ }
+
+ if {$satisfied} {
+ return
+ }
+ }
+
+ # Fallback to previous command, if existing. See comment above
+ # about ::list...
+
+ if {[llength $original]} {
+ uplevel 1 $original [::linsert $args 0 $name]
+ }
+}
+
+# ::tcl::tm::Defaults --
+#
+# Determines the default search paths.
+#
+# Arguments
+# None
+#
+# Results
+# None.
+#
+# Sideeffects
+# May add paths to the list of defaults.
+
+proc ::tcl::tm::Defaults {} {
+ global env tcl_platform
+
+ lassign [split [info tclversion] .] major minor
+ set exe [file normalize [info nameofexecutable]]
+
+ # Note that we're using [::list], not [list] because [list] means
+ # something other than [::list] in this namespace.
+ roots [::list \
+ [file dirname [info library]] \
+ [file join [file dirname [file dirname $exe]] lib] \
+ ]
+
+ if {$tcl_platform(platform) eq "windows"} {
+ set sep ";"
+ } else {
+ set sep ":"
+ }
+ for {set n $minor} {$n >= 0} {incr n -1} {
+ foreach ev [::list \
+ TCL${major}.${n}_TM_PATH \
+ TCL${major}_${n}_TM_PATH \
+ ] {
+ if {![info exists env($ev)]} continue
+ foreach p [split $env($ev) $sep] {
+ path add $p
+ }
+ }
+ }
+ return
+}
+
+# ::tcl::tm::roots --
+#
+# Public API to the module path. See specification.
+#
+# Arguments
+# paths - List of 'root' paths to derive search paths from.
+#
+# Results
+# No result.
+#
+# Sideeffects
+# Calls 'path add' to paths to the list of module search paths.
+
+proc ::tcl::tm::roots {paths} {
+ foreach {major minor} [split [info tclversion] .] break
+ foreach pa $paths {
+ set p [file join $pa tcl$major]
+ for {set n $minor} {$n >= 0} {incr n -1} {
+ set px [file join $p ${major}.${n}]
+ if {![interp issafe]} { set px [file normalize $px] }
+ path add $px
+ }
+ set px [file join $p site-tcl]
+ if {![interp issafe]} { set px [file normalize $px] }
+ path add $px
+ }
+ return
+}
+
+# Initialization. Set up the default paths, then insert the new
+# handler into the chain.
+
+if {![interp issafe]} { ::tcl::tm::Defaults }
diff --git a/library/tzdata/Africa/Abidjan b/library/tzdata/Africa/Abidjan
new file mode 100644
index 0000000..4b4f5b2
--- /dev/null
+++ b/library/tzdata/Africa/Abidjan
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Abidjan) {
+ {-9223372036854775808 -968 0 LMT}
+ {-1830383032 0 0 GMT}
+}
diff --git a/library/tzdata/Africa/Accra b/library/tzdata/Africa/Accra
new file mode 100644
index 0000000..faf58fb
--- /dev/null
+++ b/library/tzdata/Africa/Accra
@@ -0,0 +1,20 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Accra) {
+ {-9223372036854775808 -52 0 LMT}
+ {-1640995148 0 0 GMT}
+ {-1051920000 1200 1 GHST}
+ {-1041466800 0 0 GMT}
+ {-1020384000 1200 1 GHST}
+ {-1009930800 0 0 GMT}
+ {-988848000 1200 1 GHST}
+ {-978394800 0 0 GMT}
+ {-957312000 1200 1 GHST}
+ {-946858800 0 0 GMT}
+ {-925689600 1200 1 GHST}
+ {-915236400 0 0 GMT}
+ {-894153600 1200 1 GHST}
+ {-883700400 0 0 GMT}
+ {-862617600 1200 1 GHST}
+ {-852164400 0 0 GMT}
+}
diff --git a/library/tzdata/Africa/Addis_Ababa b/library/tzdata/Africa/Addis_Ababa
new file mode 100644
index 0000000..4b92483
--- /dev/null
+++ b/library/tzdata/Africa/Addis_Ababa
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Addis_Ababa) {
+ {-9223372036854775808 9288 0 LMT}
+ {-3155682888 9320 0 ADMT}
+ {-1062210920 10800 0 EAT}
+}
diff --git a/library/tzdata/Africa/Algiers b/library/tzdata/Africa/Algiers
new file mode 100644
index 0000000..fe4de22
--- /dev/null
+++ b/library/tzdata/Africa/Algiers
@@ -0,0 +1,39 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Algiers) {
+ {-9223372036854775808 732 0 LMT}
+ {-2486679072 561 0 PMT}
+ {-1855958961 0 0 WET}
+ {-1689814800 3600 1 WEST}
+ {-1680397200 0 0 WET}
+ {-1665363600 3600 1 WEST}
+ {-1648342800 0 0 WET}
+ {-1635123600 3600 1 WEST}
+ {-1616893200 0 0 WET}
+ {-1604278800 3600 1 WEST}
+ {-1585443600 0 0 WET}
+ {-1574038800 3600 1 WEST}
+ {-1552266000 0 0 WET}
+ {-1539997200 3600 1 WEST}
+ {-1531443600 0 0 WET}
+ {-956365200 3600 1 WEST}
+ {-950486400 0 0 WET}
+ {-942012000 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-796262400 3600 0 CET}
+ {-781052400 7200 1 CEST}
+ {-766630800 3600 0 CET}
+ {-733280400 0 0 WET}
+ {-439430400 3600 0 CET}
+ {-212029200 0 0 WET}
+ {41468400 3600 1 WEST}
+ {54774000 0 0 WET}
+ {231724800 3600 1 WEST}
+ {246240000 3600 0 CET}
+ {259545600 7200 1 CEST}
+ {275274000 3600 0 CET}
+ {309740400 0 0 WET}
+ {325468800 3600 1 WEST}
+ {341802000 0 0 WET}
+ {357523200 3600 0 CET}
+}
diff --git a/library/tzdata/Africa/Asmara b/library/tzdata/Africa/Asmara
new file mode 100755
index 0000000..1f0f13e
--- /dev/null
+++ b/library/tzdata/Africa/Asmara
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Asmara) {
+ {-9223372036854775808 9332 0 LMT}
+ {-3155682932 9332 0 AMT}
+ {-2524530932 9320 0 ADMT}
+ {-1062210920 10800 0 EAT}
+}
diff --git a/library/tzdata/Africa/Asmera b/library/tzdata/Africa/Asmera
new file mode 100644
index 0000000..931c36d
--- /dev/null
+++ b/library/tzdata/Africa/Asmera
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Africa/Asmara)]} {
+ LoadTimeZoneFile Africa/Asmara
+}
+set TZData(:Africa/Asmera) $TZData(:Africa/Asmara)
diff --git a/library/tzdata/Africa/Bamako b/library/tzdata/Africa/Bamako
new file mode 100644
index 0000000..7ed62e0
--- /dev/null
+++ b/library/tzdata/Africa/Bamako
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Bamako) {
+ {-9223372036854775808 -1920 0 LMT}
+ {-1830382080 0 0 GMT}
+ {-1131235200 -3600 0 WAT}
+ {-300841200 0 0 GMT}
+}
diff --git a/library/tzdata/Africa/Bangui b/library/tzdata/Africa/Bangui
new file mode 100644
index 0000000..94f5058
--- /dev/null
+++ b/library/tzdata/Africa/Bangui
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Bangui) {
+ {-9223372036854775808 4460 0 LMT}
+ {-1830388460 3600 0 WAT}
+}
diff --git a/library/tzdata/Africa/Banjul b/library/tzdata/Africa/Banjul
new file mode 100644
index 0000000..a7f0168
--- /dev/null
+++ b/library/tzdata/Africa/Banjul
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Banjul) {
+ {-9223372036854775808 -3996 0 LMT}
+ {-1830380004 -3996 0 BMT}
+ {-1104533604 -3600 0 WAT}
+ {-189385200 0 0 GMT}
+}
diff --git a/library/tzdata/Africa/Bissau b/library/tzdata/Africa/Bissau
new file mode 100644
index 0000000..d51cb9f
--- /dev/null
+++ b/library/tzdata/Africa/Bissau
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Bissau) {
+ {-9223372036854775808 -3740 0 LMT}
+ {-1849388260 -3600 0 WAT}
+ {157770000 0 0 GMT}
+}
diff --git a/library/tzdata/Africa/Blantyre b/library/tzdata/Africa/Blantyre
new file mode 100644
index 0000000..17b58f4
--- /dev/null
+++ b/library/tzdata/Africa/Blantyre
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Blantyre) {
+ {-9223372036854775808 8400 0 LMT}
+ {-2109291600 7200 0 CAT}
+}
diff --git a/library/tzdata/Africa/Brazzaville b/library/tzdata/Africa/Brazzaville
new file mode 100644
index 0000000..b4e0923
--- /dev/null
+++ b/library/tzdata/Africa/Brazzaville
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Brazzaville) {
+ {-9223372036854775808 3668 0 LMT}
+ {-1830387668 3600 0 WAT}
+}
diff --git a/library/tzdata/Africa/Bujumbura b/library/tzdata/Africa/Bujumbura
new file mode 100644
index 0000000..c26d053
--- /dev/null
+++ b/library/tzdata/Africa/Bujumbura
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Bujumbura) {
+ {-9223372036854775808 7048 0 LMT}
+ {-2524528648 7200 0 CAT}
+}
diff --git a/library/tzdata/Africa/Cairo b/library/tzdata/Africa/Cairo
new file mode 100644
index 0000000..165d8c4
--- /dev/null
+++ b/library/tzdata/Africa/Cairo
@@ -0,0 +1,128 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Cairo) {
+ {-9223372036854775808 7500 0 LMT}
+ {-2185409100 7200 0 EET}
+ {-929844000 10800 1 EEST}
+ {-923108400 7200 0 EET}
+ {-906170400 10800 1 EEST}
+ {-892868400 7200 0 EET}
+ {-875844000 10800 1 EEST}
+ {-857790000 7200 0 EET}
+ {-844308000 10800 1 EEST}
+ {-825822000 7200 0 EET}
+ {-812685600 10800 1 EEST}
+ {-794199600 7200 0 EET}
+ {-779853600 10800 1 EEST}
+ {-762663600 7200 0 EET}
+ {-399088800 10800 1 EEST}
+ {-386650800 7200 0 EET}
+ {-368330400 10800 1 EEST}
+ {-355114800 7200 0 EET}
+ {-336790800 10800 1 EEST}
+ {-323654400 7200 0 EET}
+ {-305168400 10800 1 EEST}
+ {-292032000 7200 0 EET}
+ {-273632400 10800 1 EEST}
+ {-260496000 7200 0 EET}
+ {-242096400 10800 1 EEST}
+ {-228960000 7200 0 EET}
+ {-210560400 10800 1 EEST}
+ {-197424000 7200 0 EET}
+ {-178938000 10800 1 EEST}
+ {-165801600 7200 0 EET}
+ {-147402000 10800 1 EEST}
+ {-134265600 7200 0 EET}
+ {-115866000 10800 1 EEST}
+ {-102643200 7200 0 EET}
+ {-84330000 10800 1 EEST}
+ {-71107200 7200 0 EET}
+ {-52707600 10800 1 EEST}
+ {-39484800 7200 0 EET}
+ {-21171600 10800 1 EEST}
+ {-7948800 7200 0 EET}
+ {10364400 10800 1 EEST}
+ {23587200 7200 0 EET}
+ {41900400 10800 1 EEST}
+ {55123200 7200 0 EET}
+ {73522800 10800 1 EEST}
+ {86745600 7200 0 EET}
+ {105058800 10800 1 EEST}
+ {118281600 7200 0 EET}
+ {136594800 10800 1 EEST}
+ {149817600 7200 0 EET}
+ {168130800 10800 1 EEST}
+ {181353600 7200 0 EET}
+ {199753200 10800 1 EEST}
+ {212976000 7200 0 EET}
+ {231289200 10800 1 EEST}
+ {244512000 7200 0 EET}
+ {262825200 10800 1 EEST}
+ {276048000 7200 0 EET}
+ {294361200 10800 1 EEST}
+ {307584000 7200 0 EET}
+ {325983600 10800 1 EEST}
+ {339206400 7200 0 EET}
+ {357519600 10800 1 EEST}
+ {370742400 7200 0 EET}
+ {396399600 10800 1 EEST}
+ {402278400 7200 0 EET}
+ {426812400 10800 1 EEST}
+ {433814400 7200 0 EET}
+ {452214000 10800 1 EEST}
+ {465436800 7200 0 EET}
+ {483750000 10800 1 EEST}
+ {496972800 7200 0 EET}
+ {515286000 10800 1 EEST}
+ {528508800 7200 0 EET}
+ {546822000 10800 1 EEST}
+ {560044800 7200 0 EET}
+ {578444400 10800 1 EEST}
+ {591667200 7200 0 EET}
+ {610412400 10800 1 EEST}
+ {623203200 7200 0 EET}
+ {641516400 10800 1 EEST}
+ {654739200 7200 0 EET}
+ {673052400 10800 1 EEST}
+ {686275200 7200 0 EET}
+ {704674800 10800 1 EEST}
+ {717897600 7200 0 EET}
+ {736210800 10800 1 EEST}
+ {749433600 7200 0 EET}
+ {767746800 10800 1 EEST}
+ {780969600 7200 0 EET}
+ {799020000 10800 1 EEST}
+ {812322000 7200 0 EET}
+ {830469600 10800 1 EEST}
+ {843771600 7200 0 EET}
+ {861919200 10800 1 EEST}
+ {875221200 7200 0 EET}
+ {893368800 10800 1 EEST}
+ {906670800 7200 0 EET}
+ {925423200 10800 1 EEST}
+ {938725200 7200 0 EET}
+ {956872800 10800 1 EEST}
+ {970174800 7200 0 EET}
+ {988322400 10800 1 EEST}
+ {1001624400 7200 0 EET}
+ {1019772000 10800 1 EEST}
+ {1033074000 7200 0 EET}
+ {1051221600 10800 1 EEST}
+ {1064523600 7200 0 EET}
+ {1083276000 10800 1 EEST}
+ {1096578000 7200 0 EET}
+ {1114725600 10800 1 EEST}
+ {1128027600 7200 0 EET}
+ {1146175200 10800 1 EEST}
+ {1158872400 7200 0 EET}
+ {1177624800 10800 1 EEST}
+ {1189112400 7200 0 EET}
+ {1209074400 10800 1 EEST}
+ {1219957200 7200 0 EET}
+ {1240524000 10800 1 EEST}
+ {1250802000 7200 0 EET}
+ {1272578400 10800 1 EEST}
+ {1281474000 7200 0 EET}
+ {1284069600 10800 1 EEST}
+ {1285880400 7200 0 EET}
+}
diff --git a/library/tzdata/Africa/Casablanca b/library/tzdata/Africa/Casablanca
new file mode 100644
index 0000000..0eef1ac
--- /dev/null
+++ b/library/tzdata/Africa/Casablanca
@@ -0,0 +1,32 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Casablanca) {
+ {-9223372036854775808 -1820 0 LMT}
+ {-1773012580 0 0 WET}
+ {-956361600 3600 1 WEST}
+ {-950490000 0 0 WET}
+ {-942019200 3600 1 WEST}
+ {-761187600 0 0 WET}
+ {-617241600 3600 1 WEST}
+ {-605149200 0 0 WET}
+ {-81432000 3600 1 WEST}
+ {-71110800 0 0 WET}
+ {141264000 3600 1 WEST}
+ {147222000 0 0 WET}
+ {199756800 3600 1 WEST}
+ {207702000 0 0 WET}
+ {231292800 3600 1 WEST}
+ {244249200 0 0 WET}
+ {265507200 3600 1 WEST}
+ {271033200 0 0 WET}
+ {448243200 3600 0 CET}
+ {504918000 0 0 WET}
+ {1212278400 3600 1 WEST}
+ {1220223600 0 0 WET}
+ {1243814400 3600 1 WEST}
+ {1250809200 0 0 WET}
+ {1272758400 3600 1 WEST}
+ {1281222000 0 0 WET}
+ {1301788800 3600 1 WEST}
+ {1312066800 0 0 WET}
+}
diff --git a/library/tzdata/Africa/Ceuta b/library/tzdata/Africa/Ceuta
new file mode 100644
index 0000000..882c13d
--- /dev/null
+++ b/library/tzdata/Africa/Ceuta
@@ -0,0 +1,258 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Ceuta) {
+ {-9223372036854775808 -1276 0 LMT}
+ {-2177451524 0 0 WET}
+ {-1630112400 3600 1 WEST}
+ {-1616810400 0 0 WET}
+ {-1451692800 0 0 WET}
+ {-1442451600 3600 1 WEST}
+ {-1427677200 0 0 WET}
+ {-1379293200 3600 1 WEST}
+ {-1364778000 0 0 WET}
+ {-1348448400 3600 1 WEST}
+ {-1333328400 0 0 WET}
+ {-1316394000 3600 1 WEST}
+ {-1301274000 0 0 WET}
+ {-1293840000 0 0 WET}
+ {-81432000 3600 1 WEST}
+ {-71110800 0 0 WET}
+ {141264000 3600 1 WEST}
+ {147222000 0 0 WET}
+ {199756800 3600 1 WEST}
+ {207702000 0 0 WET}
+ {231292800 3600 1 WEST}
+ {244249200 0 0 WET}
+ {265507200 3600 1 WEST}
+ {271033200 0 0 WET}
+ {448243200 3600 0 CET}
+ {504918000 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Africa/Conakry b/library/tzdata/Africa/Conakry
new file mode 100644
index 0000000..d17ce4b
--- /dev/null
+++ b/library/tzdata/Africa/Conakry
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Conakry) {
+ {-9223372036854775808 -3292 0 LMT}
+ {-1830380708 0 0 GMT}
+ {-1131235200 -3600 0 WAT}
+ {-315615600 0 0 GMT}
+}
diff --git a/library/tzdata/Africa/Dakar b/library/tzdata/Africa/Dakar
new file mode 100644
index 0000000..487dc62
--- /dev/null
+++ b/library/tzdata/Africa/Dakar
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Dakar) {
+ {-9223372036854775808 -4184 0 LMT}
+ {-1830379816 -3600 0 WAT}
+ {-902098800 0 0 GMT}
+}
diff --git a/library/tzdata/Africa/Dar_es_Salaam b/library/tzdata/Africa/Dar_es_Salaam
new file mode 100644
index 0000000..e427b9c
--- /dev/null
+++ b/library/tzdata/Africa/Dar_es_Salaam
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Dar_es_Salaam) {
+ {-9223372036854775808 9428 0 LMT}
+ {-1230777428 10800 0 EAT}
+ {-694321200 9885 0 BEAUT}
+ {-284006685 10800 0 EAT}
+}
diff --git a/library/tzdata/Africa/Djibouti b/library/tzdata/Africa/Djibouti
new file mode 100644
index 0000000..0ec510c
--- /dev/null
+++ b/library/tzdata/Africa/Djibouti
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Djibouti) {
+ {-9223372036854775808 10356 0 LMT}
+ {-1846291956 10800 0 EAT}
+}
diff --git a/library/tzdata/Africa/Douala b/library/tzdata/Africa/Douala
new file mode 100644
index 0000000..301a530
--- /dev/null
+++ b/library/tzdata/Africa/Douala
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Douala) {
+ {-9223372036854775808 2328 0 LMT}
+ {-1830386328 3600 0 WAT}
+}
diff --git a/library/tzdata/Africa/El_Aaiun b/library/tzdata/Africa/El_Aaiun
new file mode 100644
index 0000000..a8b9d34
--- /dev/null
+++ b/library/tzdata/Africa/El_Aaiun
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/El_Aaiun) {
+ {-9223372036854775808 -3168 0 LMT}
+ {-1136070432 -3600 0 WAT}
+ {198291600 0 0 WET}
+}
diff --git a/library/tzdata/Africa/Freetown b/library/tzdata/Africa/Freetown
new file mode 100644
index 0000000..c3f2d2e
--- /dev/null
+++ b/library/tzdata/Africa/Freetown
@@ -0,0 +1,36 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Freetown) {
+ {-9223372036854775808 -3180 0 LMT}
+ {-2776979220 -3180 0 FMT}
+ {-1785712020 -3600 0 WAT}
+ {-1091487600 -1200 1 SLST}
+ {-1080949200 -3600 0 WAT}
+ {-1059865200 -1200 1 SLST}
+ {-1049326800 -3600 0 WAT}
+ {-1028329200 -1200 1 SLST}
+ {-1017790800 -3600 0 WAT}
+ {-996793200 -1200 1 SLST}
+ {-986254800 -3600 0 WAT}
+ {-965257200 -1200 1 SLST}
+ {-954718800 -3600 0 WAT}
+ {-933634800 -1200 1 SLST}
+ {-923096400 -3600 0 WAT}
+ {-902098800 -1200 1 SLST}
+ {-891560400 -3600 0 WAT}
+ {-870562800 -1200 1 SLST}
+ {-860024400 -3600 0 WAT}
+ {-410223600 0 0 WAT}
+ {-397180800 3600 1 SLST}
+ {-389235600 0 0 GMT}
+ {-365644800 3600 1 SLST}
+ {-357699600 0 0 GMT}
+ {-334108800 3600 1 SLST}
+ {-326163600 0 0 GMT}
+ {-302486400 3600 1 SLST}
+ {-294541200 0 0 GMT}
+ {-270950400 3600 1 SLST}
+ {-263005200 0 0 GMT}
+ {-239414400 3600 1 SLST}
+ {-231469200 0 0 GMT}
+}
diff --git a/library/tzdata/Africa/Gaborone b/library/tzdata/Africa/Gaborone
new file mode 100644
index 0000000..7753ba0
--- /dev/null
+++ b/library/tzdata/Africa/Gaborone
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Gaborone) {
+ {-9223372036854775808 6220 0 LMT}
+ {-2682294220 7200 0 CAT}
+ {-829526400 10800 1 CAST}
+ {-813805200 7200 0 CAT}
+}
diff --git a/library/tzdata/Africa/Harare b/library/tzdata/Africa/Harare
new file mode 100644
index 0000000..7482b15
--- /dev/null
+++ b/library/tzdata/Africa/Harare
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Harare) {
+ {-9223372036854775808 7452 0 LMT}
+ {-2109290652 7200 0 CAT}
+}
diff --git a/library/tzdata/Africa/Johannesburg b/library/tzdata/Africa/Johannesburg
new file mode 100644
index 0000000..b9a8348
--- /dev/null
+++ b/library/tzdata/Africa/Johannesburg
@@ -0,0 +1,11 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Johannesburg) {
+ {-9223372036854775808 6720 0 LMT}
+ {-2458173120 5400 0 SAST}
+ {-2109288600 7200 0 SAST}
+ {-860976000 10800 1 SAST}
+ {-845254800 7200 0 SAST}
+ {-829526400 10800 1 SAST}
+ {-813805200 7200 0 SAST}
+}
diff --git a/library/tzdata/Africa/Kampala b/library/tzdata/Africa/Kampala
new file mode 100644
index 0000000..ab3f085
--- /dev/null
+++ b/library/tzdata/Africa/Kampala
@@ -0,0 +1,9 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Kampala) {
+ {-9223372036854775808 7780 0 LMT}
+ {-1309745380 10800 0 EAT}
+ {-1262314800 9000 0 BEAT}
+ {-694319400 9885 0 BEAUT}
+ {-410237085 10800 0 EAT}
+}
diff --git a/library/tzdata/Africa/Khartoum b/library/tzdata/Africa/Khartoum
new file mode 100644
index 0000000..dfcac82
--- /dev/null
+++ b/library/tzdata/Africa/Khartoum
@@ -0,0 +1,39 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Khartoum) {
+ {-9223372036854775808 7808 0 LMT}
+ {-1230775808 7200 0 CAT}
+ {10360800 10800 1 CAST}
+ {24786000 7200 0 CAT}
+ {41810400 10800 1 CAST}
+ {56322000 7200 0 CAT}
+ {73432800 10800 1 CAST}
+ {87944400 7200 0 CAT}
+ {104882400 10800 1 CAST}
+ {119480400 7200 0 CAT}
+ {136332000 10800 1 CAST}
+ {151016400 7200 0 CAT}
+ {167781600 10800 1 CAST}
+ {182552400 7200 0 CAT}
+ {199231200 10800 1 CAST}
+ {214174800 7200 0 CAT}
+ {230680800 10800 1 CAST}
+ {245710800 7200 0 CAT}
+ {262735200 10800 1 CAST}
+ {277246800 7200 0 CAT}
+ {294184800 10800 1 CAST}
+ {308782800 7200 0 CAT}
+ {325634400 10800 1 CAST}
+ {340405200 7200 0 CAT}
+ {357084000 10800 1 CAST}
+ {371941200 7200 0 CAT}
+ {388533600 10800 1 CAST}
+ {403477200 7200 0 CAT}
+ {419983200 10800 1 CAST}
+ {435013200 7200 0 CAT}
+ {452037600 10800 1 CAST}
+ {466635600 7200 0 CAT}
+ {483487200 10800 1 CAST}
+ {498171600 7200 0 CAT}
+ {947930400 10800 0 EAT}
+}
diff --git a/library/tzdata/Africa/Kigali b/library/tzdata/Africa/Kigali
new file mode 100644
index 0000000..f723bcd
--- /dev/null
+++ b/library/tzdata/Africa/Kigali
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Kigali) {
+ {-9223372036854775808 7216 0 LMT}
+ {-1091498416 7200 0 CAT}
+}
diff --git a/library/tzdata/Africa/Kinshasa b/library/tzdata/Africa/Kinshasa
new file mode 100644
index 0000000..050c1fa
--- /dev/null
+++ b/library/tzdata/Africa/Kinshasa
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Kinshasa) {
+ {-9223372036854775808 3672 0 LMT}
+ {-2276643672 3600 0 WAT}
+}
diff --git a/library/tzdata/Africa/Lagos b/library/tzdata/Africa/Lagos
new file mode 100644
index 0000000..079572f
--- /dev/null
+++ b/library/tzdata/Africa/Lagos
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Lagos) {
+ {-9223372036854775808 816 0 LMT}
+ {-1588464816 3600 0 WAT}
+}
diff --git a/library/tzdata/Africa/Libreville b/library/tzdata/Africa/Libreville
new file mode 100644
index 0000000..8427551
--- /dev/null
+++ b/library/tzdata/Africa/Libreville
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Libreville) {
+ {-9223372036854775808 2268 0 LMT}
+ {-1830386268 3600 0 WAT}
+}
diff --git a/library/tzdata/Africa/Lome b/library/tzdata/Africa/Lome
new file mode 100644
index 0000000..606625c
--- /dev/null
+++ b/library/tzdata/Africa/Lome
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Lome) {
+ {-9223372036854775808 292 0 LMT}
+ {-2429827492 0 0 GMT}
+}
diff --git a/library/tzdata/Africa/Luanda b/library/tzdata/Africa/Luanda
new file mode 100644
index 0000000..cd1b29e
--- /dev/null
+++ b/library/tzdata/Africa/Luanda
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Luanda) {
+ {-9223372036854775808 3176 0 LMT}
+ {-2461452776 3124 0 AOT}
+ {-1849395124 3600 0 WAT}
+}
diff --git a/library/tzdata/Africa/Lubumbashi b/library/tzdata/Africa/Lubumbashi
new file mode 100644
index 0000000..bd67221
--- /dev/null
+++ b/library/tzdata/Africa/Lubumbashi
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Lubumbashi) {
+ {-9223372036854775808 6592 0 LMT}
+ {-2276646592 7200 0 CAT}
+}
diff --git a/library/tzdata/Africa/Lusaka b/library/tzdata/Africa/Lusaka
new file mode 100644
index 0000000..ed9c30d
--- /dev/null
+++ b/library/tzdata/Africa/Lusaka
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Lusaka) {
+ {-9223372036854775808 6788 0 LMT}
+ {-2109289988 7200 0 CAT}
+}
diff --git a/library/tzdata/Africa/Malabo b/library/tzdata/Africa/Malabo
new file mode 100644
index 0000000..bec0524
--- /dev/null
+++ b/library/tzdata/Africa/Malabo
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Malabo) {
+ {-9223372036854775808 2108 0 LMT}
+ {-1830386108 0 0 GMT}
+ {-190857600 3600 0 WAT}
+}
diff --git a/library/tzdata/Africa/Maputo b/library/tzdata/Africa/Maputo
new file mode 100644
index 0000000..6ee208c
--- /dev/null
+++ b/library/tzdata/Africa/Maputo
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Maputo) {
+ {-9223372036854775808 7820 0 LMT}
+ {-2109291020 7200 0 CAT}
+}
diff --git a/library/tzdata/Africa/Maseru b/library/tzdata/Africa/Maseru
new file mode 100644
index 0000000..21ca968
--- /dev/null
+++ b/library/tzdata/Africa/Maseru
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Maseru) {
+ {-9223372036854775808 6600 0 LMT}
+ {-2109289800 7200 0 SAST}
+ {-829526400 10800 1 SAST}
+ {-813805200 7200 0 SAST}
+}
diff --git a/library/tzdata/Africa/Mbabane b/library/tzdata/Africa/Mbabane
new file mode 100644
index 0000000..4d174d5
--- /dev/null
+++ b/library/tzdata/Africa/Mbabane
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Mbabane) {
+ {-9223372036854775808 7464 0 LMT}
+ {-2109290664 7200 0 SAST}
+}
diff --git a/library/tzdata/Africa/Mogadishu b/library/tzdata/Africa/Mogadishu
new file mode 100644
index 0000000..570d3ea
--- /dev/null
+++ b/library/tzdata/Africa/Mogadishu
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Mogadishu) {
+ {-9223372036854775808 10888 0 LMT}
+ {-2403572488 10800 0 EAT}
+ {-1230778800 9000 0 BEAT}
+ {-410236200 10800 0 EAT}
+}
diff --git a/library/tzdata/Africa/Monrovia b/library/tzdata/Africa/Monrovia
new file mode 100644
index 0000000..1cfff58
--- /dev/null
+++ b/library/tzdata/Africa/Monrovia
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Monrovia) {
+ {-9223372036854775808 -2588 0 LMT}
+ {-2776979812 -2588 0 MMT}
+ {-1604359012 -2670 0 LRT}
+ {73529070 0 0 GMT}
+}
diff --git a/library/tzdata/Africa/Nairobi b/library/tzdata/Africa/Nairobi
new file mode 100644
index 0000000..99b0d70
--- /dev/null
+++ b/library/tzdata/Africa/Nairobi
@@ -0,0 +1,9 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Nairobi) {
+ {-9223372036854775808 8836 0 LMT}
+ {-1309746436 10800 0 EAT}
+ {-1262314800 9000 0 BEAT}
+ {-946780200 9885 0 BEAUT}
+ {-315629085 10800 0 EAT}
+}
diff --git a/library/tzdata/Africa/Ndjamena b/library/tzdata/Africa/Ndjamena
new file mode 100644
index 0000000..af4daaa
--- /dev/null
+++ b/library/tzdata/Africa/Ndjamena
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Ndjamena) {
+ {-9223372036854775808 3612 0 LMT}
+ {-1830387612 3600 0 WAT}
+ {308703600 7200 1 WAST}
+ {321314400 3600 0 WAT}
+}
diff --git a/library/tzdata/Africa/Niamey b/library/tzdata/Africa/Niamey
new file mode 100644
index 0000000..40ded06b
--- /dev/null
+++ b/library/tzdata/Africa/Niamey
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Niamey) {
+ {-9223372036854775808 508 0 LMT}
+ {-1830384508 -3600 0 WAT}
+ {-1131231600 0 0 GMT}
+ {-315619200 3600 0 WAT}
+}
diff --git a/library/tzdata/Africa/Nouakchott b/library/tzdata/Africa/Nouakchott
new file mode 100644
index 0000000..f7369d0
--- /dev/null
+++ b/library/tzdata/Africa/Nouakchott
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Nouakchott) {
+ {-9223372036854775808 -3828 0 LMT}
+ {-1830380172 0 0 GMT}
+ {-1131235200 -3600 0 WAT}
+ {-286930800 0 0 GMT}
+}
diff --git a/library/tzdata/Africa/Ouagadougou b/library/tzdata/Africa/Ouagadougou
new file mode 100644
index 0000000..88a7145
--- /dev/null
+++ b/library/tzdata/Africa/Ouagadougou
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Ouagadougou) {
+ {-9223372036854775808 -364 0 LMT}
+ {-1830383636 0 0 GMT}
+}
diff --git a/library/tzdata/Africa/Porto-Novo b/library/tzdata/Africa/Porto-Novo
new file mode 100644
index 0000000..b89cf1b
--- /dev/null
+++ b/library/tzdata/Africa/Porto-Novo
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Porto-Novo) {
+ {-9223372036854775808 628 0 LMT}
+ {-1830384628 0 0 GMT}
+ {-1131235200 3600 0 WAT}
+}
diff --git a/library/tzdata/Africa/Sao_Tome b/library/tzdata/Africa/Sao_Tome
new file mode 100644
index 0000000..ab1590d
--- /dev/null
+++ b/library/tzdata/Africa/Sao_Tome
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Sao_Tome) {
+ {-9223372036854775808 1616 0 LMT}
+ {-2713912016 -2192 0 LMT}
+ {-1830381808 0 0 GMT}
+}
diff --git a/library/tzdata/Africa/Timbuktu b/library/tzdata/Africa/Timbuktu
new file mode 100644
index 0000000..8057eed
--- /dev/null
+++ b/library/tzdata/Africa/Timbuktu
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Africa/Bamako)]} {
+ LoadTimeZoneFile Africa/Bamako
+}
+set TZData(:Africa/Timbuktu) $TZData(:Africa/Bamako)
diff --git a/library/tzdata/Africa/Tripoli b/library/tzdata/Africa/Tripoli
new file mode 100644
index 0000000..e993249
--- /dev/null
+++ b/library/tzdata/Africa/Tripoli
@@ -0,0 +1,31 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Tripoli) {
+ {-9223372036854775808 3164 0 LMT}
+ {-1577926364 3600 0 CET}
+ {-574902000 7200 1 CEST}
+ {-512175600 7200 1 CEST}
+ {-449888400 7200 1 CEST}
+ {-347158800 7200 0 EET}
+ {378684000 3600 0 CET}
+ {386463600 7200 1 CEST}
+ {402271200 3600 0 CET}
+ {417999600 7200 1 CEST}
+ {433807200 3600 0 CET}
+ {449622000 7200 1 CEST}
+ {465429600 3600 0 CET}
+ {481590000 7200 1 CEST}
+ {496965600 3600 0 CET}
+ {512953200 7200 1 CEST}
+ {528674400 3600 0 CET}
+ {544230000 7200 1 CEST}
+ {560037600 3600 0 CET}
+ {575852400 7200 1 CEST}
+ {591660000 3600 0 CET}
+ {607388400 7200 1 CEST}
+ {623196000 3600 0 CET}
+ {641775600 7200 0 EET}
+ {844034400 3600 0 CET}
+ {860108400 7200 1 CEST}
+ {875916000 7200 0 EET}
+}
diff --git a/library/tzdata/Africa/Tunis b/library/tzdata/Africa/Tunis
new file mode 100644
index 0000000..0c1db4d
--- /dev/null
+++ b/library/tzdata/Africa/Tunis
@@ -0,0 +1,39 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Tunis) {
+ {-9223372036854775808 2444 0 LMT}
+ {-2797202444 561 0 PMT}
+ {-1855958961 3600 0 CET}
+ {-969242400 7200 1 CEST}
+ {-950493600 3600 0 CET}
+ {-941940000 7200 1 CEST}
+ {-891136800 3600 0 CET}
+ {-877827600 7200 1 CEST}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-842918400 3600 0 CET}
+ {-842223600 7200 1 CEST}
+ {-828230400 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-796269600 3600 0 CET}
+ {-781052400 7200 1 CEST}
+ {-766634400 3600 0 CET}
+ {231202800 7200 1 CEST}
+ {243903600 3600 0 CET}
+ {262825200 7200 1 CEST}
+ {276044400 3600 0 CET}
+ {581122800 7200 1 CEST}
+ {591145200 3600 0 CET}
+ {606870000 7200 1 CEST}
+ {622594800 3600 0 CET}
+ {641516400 7200 1 CEST}
+ {654649200 3600 0 CET}
+ {1114902000 7200 1 CEST}
+ {1128038400 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+}
diff --git a/library/tzdata/Africa/Windhoek b/library/tzdata/Africa/Windhoek
new file mode 100644
index 0000000..a655f2e
--- /dev/null
+++ b/library/tzdata/Africa/Windhoek
@@ -0,0 +1,222 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Africa/Windhoek) {
+ {-9223372036854775808 4104 0 LMT}
+ {-2458170504 5400 0 SWAT}
+ {-2109288600 7200 0 SAST}
+ {-860976000 10800 1 SAST}
+ {-845254800 7200 0 SAST}
+ {637970400 7200 0 CAT}
+ {765324000 3600 0 WAT}
+ {778640400 7200 1 WAST}
+ {796780800 3600 0 WAT}
+ {810090000 7200 1 WAST}
+ {828835200 3600 0 WAT}
+ {841539600 7200 1 WAST}
+ {860284800 3600 0 WAT}
+ {873594000 7200 1 WAST}
+ {891734400 3600 0 WAT}
+ {905043600 7200 1 WAST}
+ {923184000 3600 0 WAT}
+ {936493200 7200 1 WAST}
+ {954633600 3600 0 WAT}
+ {967942800 7200 1 WAST}
+ {986083200 3600 0 WAT}
+ {999392400 7200 1 WAST}
+ {1018137600 3600 0 WAT}
+ {1030842000 7200 1 WAST}
+ {1049587200 3600 0 WAT}
+ {1062896400 7200 1 WAST}
+ {1081036800 3600 0 WAT}
+ {1094346000 7200 1 WAST}
+ {1112486400 3600 0 WAT}
+ {1125795600 7200 1 WAST}
+ {1143936000 3600 0 WAT}
+ {1157245200 7200 1 WAST}
+ {1175385600 3600 0 WAT}
+ {1188694800 7200 1 WAST}
+ {1207440000 3600 0 WAT}
+ {1220749200 7200 1 WAST}
+ {1238889600 3600 0 WAT}
+ {1252198800 7200 1 WAST}
+ {1270339200 3600 0 WAT}
+ {1283648400 7200 1 WAST}
+ {1301788800 3600 0 WAT}
+ {1315098000 7200 1 WAST}
+ {1333238400 3600 0 WAT}
+ {1346547600 7200 1 WAST}
+ {1365292800 3600 0 WAT}
+ {1377997200 7200 1 WAST}
+ {1396742400 3600 0 WAT}
+ {1410051600 7200 1 WAST}
+ {1428192000 3600 0 WAT}
+ {1441501200 7200 1 WAST}
+ {1459641600 3600 0 WAT}
+ {1472950800 7200 1 WAST}
+ {1491091200 3600 0 WAT}
+ {1504400400 7200 1 WAST}
+ {1522540800 3600 0 WAT}
+ {1535850000 7200 1 WAST}
+ {1554595200 3600 0 WAT}
+ {1567299600 7200 1 WAST}
+ {1586044800 3600 0 WAT}
+ {1599354000 7200 1 WAST}
+ {1617494400 3600 0 WAT}
+ {1630803600 7200 1 WAST}
+ {1648944000 3600 0 WAT}
+ {1662253200 7200 1 WAST}
+ {1680393600 3600 0 WAT}
+ {1693702800 7200 1 WAST}
+ {1712448000 3600 0 WAT}
+ {1725152400 7200 1 WAST}
+ {1743897600 3600 0 WAT}
+ {1757206800 7200 1 WAST}
+ {1775347200 3600 0 WAT}
+ {1788656400 7200 1 WAST}
+ {1806796800 3600 0 WAT}
+ {1820106000 7200 1 WAST}
+ {1838246400 3600 0 WAT}
+ {1851555600 7200 1 WAST}
+ {1869696000 3600 0 WAT}
+ {1883005200 7200 1 WAST}
+ {1901750400 3600 0 WAT}
+ {1914454800 7200 1 WAST}
+ {1933200000 3600 0 WAT}
+ {1946509200 7200 1 WAST}
+ {1964649600 3600 0 WAT}
+ {1977958800 7200 1 WAST}
+ {1996099200 3600 0 WAT}
+ {2009408400 7200 1 WAST}
+ {2027548800 3600 0 WAT}
+ {2040858000 7200 1 WAST}
+ {2058998400 3600 0 WAT}
+ {2072307600 7200 1 WAST}
+ {2091052800 3600 0 WAT}
+ {2104362000 7200 1 WAST}
+ {2122502400 3600 0 WAT}
+ {2135811600 7200 1 WAST}
+ {2153952000 3600 0 WAT}
+ {2167261200 7200 1 WAST}
+ {2185401600 3600 0 WAT}
+ {2198710800 7200 1 WAST}
+ {2216851200 3600 0 WAT}
+ {2230160400 7200 1 WAST}
+ {2248905600 3600 0 WAT}
+ {2261610000 7200 1 WAST}
+ {2280355200 3600 0 WAT}
+ {2293664400 7200 1 WAST}
+ {2311804800 3600 0 WAT}
+ {2325114000 7200 1 WAST}
+ {2343254400 3600 0 WAT}
+ {2356563600 7200 1 WAST}
+ {2374704000 3600 0 WAT}
+ {2388013200 7200 1 WAST}
+ {2406153600 3600 0 WAT}
+ {2419462800 7200 1 WAST}
+ {2438208000 3600 0 WAT}
+ {2450912400 7200 1 WAST}
+ {2469657600 3600 0 WAT}
+ {2482966800 7200 1 WAST}
+ {2501107200 3600 0 WAT}
+ {2514416400 7200 1 WAST}
+ {2532556800 3600 0 WAT}
+ {2545866000 7200 1 WAST}
+ {2564006400 3600 0 WAT}
+ {2577315600 7200 1 WAST}
+ {2596060800 3600 0 WAT}
+ {2608765200 7200 1 WAST}
+ {2627510400 3600 0 WAT}
+ {2640819600 7200 1 WAST}
+ {2658960000 3600 0 WAT}
+ {2672269200 7200 1 WAST}
+ {2690409600 3600 0 WAT}
+ {2703718800 7200 1 WAST}
+ {2721859200 3600 0 WAT}
+ {2735168400 7200 1 WAST}
+ {2753308800 3600 0 WAT}
+ {2766618000 7200 1 WAST}
+ {2785363200 3600 0 WAT}
+ {2798067600 7200 1 WAST}
+ {2816812800 3600 0 WAT}
+ {2830122000 7200 1 WAST}
+ {2848262400 3600 0 WAT}
+ {2861571600 7200 1 WAST}
+ {2879712000 3600 0 WAT}
+ {2893021200 7200 1 WAST}
+ {2911161600 3600 0 WAT}
+ {2924470800 7200 1 WAST}
+ {2942611200 3600 0 WAT}
+ {2955920400 7200 1 WAST}
+ {2974665600 3600 0 WAT}
+ {2987974800 7200 1 WAST}
+ {3006115200 3600 0 WAT}
+ {3019424400 7200 1 WAST}
+ {3037564800 3600 0 WAT}
+ {3050874000 7200 1 WAST}
+ {3069014400 3600 0 WAT}
+ {3082323600 7200 1 WAST}
+ {3100464000 3600 0 WAT}
+ {3113773200 7200 1 WAST}
+ {3132518400 3600 0 WAT}
+ {3145222800 7200 1 WAST}
+ {3163968000 3600 0 WAT}
+ {3177277200 7200 1 WAST}
+ {3195417600 3600 0 WAT}
+ {3208726800 7200 1 WAST}
+ {3226867200 3600 0 WAT}
+ {3240176400 7200 1 WAST}
+ {3258316800 3600 0 WAT}
+ {3271626000 7200 1 WAST}
+ {3289766400 3600 0 WAT}
+ {3303075600 7200 1 WAST}
+ {3321820800 3600 0 WAT}
+ {3334525200 7200 1 WAST}
+ {3353270400 3600 0 WAT}
+ {3366579600 7200 1 WAST}
+ {3384720000 3600 0 WAT}
+ {3398029200 7200 1 WAST}
+ {3416169600 3600 0 WAT}
+ {3429478800 7200 1 WAST}
+ {3447619200 3600 0 WAT}
+ {3460928400 7200 1 WAST}
+ {3479673600 3600 0 WAT}
+ {3492378000 7200 1 WAST}
+ {3511123200 3600 0 WAT}
+ {3524432400 7200 1 WAST}
+ {3542572800 3600 0 WAT}
+ {3555882000 7200 1 WAST}
+ {3574022400 3600 0 WAT}
+ {3587331600 7200 1 WAST}
+ {3605472000 3600 0 WAT}
+ {3618781200 7200 1 WAST}
+ {3636921600 3600 0 WAT}
+ {3650230800 7200 1 WAST}
+ {3668976000 3600 0 WAT}
+ {3681680400 7200 1 WAST}
+ {3700425600 3600 0 WAT}
+ {3713734800 7200 1 WAST}
+ {3731875200 3600 0 WAT}
+ {3745184400 7200 1 WAST}
+ {3763324800 3600 0 WAT}
+ {3776634000 7200 1 WAST}
+ {3794774400 3600 0 WAT}
+ {3808083600 7200 1 WAST}
+ {3826224000 3600 0 WAT}
+ {3839533200 7200 1 WAST}
+ {3858278400 3600 0 WAT}
+ {3871587600 7200 1 WAST}
+ {3889728000 3600 0 WAT}
+ {3903037200 7200 1 WAST}
+ {3921177600 3600 0 WAT}
+ {3934486800 7200 1 WAST}
+ {3952627200 3600 0 WAT}
+ {3965936400 7200 1 WAST}
+ {3984076800 3600 0 WAT}
+ {3997386000 7200 1 WAST}
+ {4016131200 3600 0 WAT}
+ {4028835600 7200 1 WAST}
+ {4047580800 3600 0 WAT}
+ {4060890000 7200 1 WAST}
+ {4079030400 3600 0 WAT}
+ {4092339600 7200 1 WAST}
+}
diff --git a/library/tzdata/America/Adak b/library/tzdata/America/Adak
new file mode 100644
index 0000000..f3c5e5c
--- /dev/null
+++ b/library/tzdata/America/Adak
@@ -0,0 +1,276 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Adak) {
+ {-9223372036854775808 44001 0 LMT}
+ {-3225356001 -42398 0 LMT}
+ {-2188944802 -39600 0 NST}
+ {-883573200 -39600 0 NST}
+ {-880196400 -36000 1 NWT}
+ {-769395600 -36000 1 NPT}
+ {-765374400 -39600 0 NST}
+ {-757342800 -39600 0 NST}
+ {-86878800 -39600 0 BST}
+ {-31496400 -39600 0 BST}
+ {-21466800 -36000 1 BDT}
+ {-5745600 -39600 0 BST}
+ {9982800 -36000 1 BDT}
+ {25704000 -39600 0 BST}
+ {41432400 -36000 1 BDT}
+ {57758400 -39600 0 BST}
+ {73486800 -36000 1 BDT}
+ {89208000 -39600 0 BST}
+ {104936400 -36000 1 BDT}
+ {120657600 -39600 0 BST}
+ {126709200 -36000 1 BDT}
+ {152107200 -39600 0 BST}
+ {162392400 -36000 1 BDT}
+ {183556800 -39600 0 BST}
+ {199285200 -36000 1 BDT}
+ {215611200 -39600 0 BST}
+ {230734800 -36000 1 BDT}
+ {247060800 -39600 0 BST}
+ {262789200 -36000 1 BDT}
+ {278510400 -39600 0 BST}
+ {294238800 -36000 1 BDT}
+ {309960000 -39600 0 BST}
+ {325688400 -36000 1 BDT}
+ {341409600 -39600 0 BST}
+ {357138000 -36000 1 BDT}
+ {372859200 -39600 0 BST}
+ {388587600 -36000 1 BDT}
+ {404913600 -39600 0 BST}
+ {420037200 -36000 1 BDT}
+ {439034400 -36000 0 HAST}
+ {452088000 -32400 1 HADT}
+ {467809200 -36000 0 HAST}
+ {483537600 -32400 1 HADT}
+ {499258800 -36000 0 HAST}
+ {514987200 -32400 1 HADT}
+ {530708400 -36000 0 HAST}
+ {544622400 -32400 1 HADT}
+ {562158000 -36000 0 HAST}
+ {576072000 -32400 1 HADT}
+ {594212400 -36000 0 HAST}
+ {607521600 -32400 1 HADT}
+ {625662000 -36000 0 HAST}
+ {638971200 -32400 1 HADT}
+ {657111600 -36000 0 HAST}
+ {671025600 -32400 1 HADT}
+ {688561200 -36000 0 HAST}
+ {702475200 -32400 1 HADT}
+ {720010800 -36000 0 HAST}
+ {733924800 -32400 1 HADT}
+ {752065200 -36000 0 HAST}
+ {765374400 -32400 1 HADT}
+ {783514800 -36000 0 HAST}
+ {796824000 -32400 1 HADT}
+ {814964400 -36000 0 HAST}
+ {828878400 -32400 1 HADT}
+ {846414000 -36000 0 HAST}
+ {860328000 -32400 1 HADT}
+ {877863600 -36000 0 HAST}
+ {891777600 -32400 1 HADT}
+ {909313200 -36000 0 HAST}
+ {923227200 -32400 1 HADT}
+ {941367600 -36000 0 HAST}
+ {954676800 -32400 1 HADT}
+ {972817200 -36000 0 HAST}
+ {986126400 -32400 1 HADT}
+ {1004266800 -36000 0 HAST}
+ {1018180800 -32400 1 HADT}
+ {1035716400 -36000 0 HAST}
+ {1049630400 -32400 1 HADT}
+ {1067166000 -36000 0 HAST}
+ {1081080000 -32400 1 HADT}
+ {1099220400 -36000 0 HAST}
+ {1112529600 -32400 1 HADT}
+ {1130670000 -36000 0 HAST}
+ {1143979200 -32400 1 HADT}
+ {1162119600 -36000 0 HAST}
+ {1173614400 -32400 1 HADT}
+ {1194174000 -36000 0 HAST}
+ {1205064000 -32400 1 HADT}
+ {1225623600 -36000 0 HAST}
+ {1236513600 -32400 1 HADT}
+ {1257073200 -36000 0 HAST}
+ {1268568000 -32400 1 HADT}
+ {1289127600 -36000 0 HAST}
+ {1300017600 -32400 1 HADT}
+ {1320577200 -36000 0 HAST}
+ {1331467200 -32400 1 HADT}
+ {1352026800 -36000 0 HAST}
+ {1362916800 -32400 1 HADT}
+ {1383476400 -36000 0 HAST}
+ {1394366400 -32400 1 HADT}
+ {1414926000 -36000 0 HAST}
+ {1425816000 -32400 1 HADT}
+ {1446375600 -36000 0 HAST}
+ {1457870400 -32400 1 HADT}
+ {1478430000 -36000 0 HAST}
+ {1489320000 -32400 1 HADT}
+ {1509879600 -36000 0 HAST}
+ {1520769600 -32400 1 HADT}
+ {1541329200 -36000 0 HAST}
+ {1552219200 -32400 1 HADT}
+ {1572778800 -36000 0 HAST}
+ {1583668800 -32400 1 HADT}
+ {1604228400 -36000 0 HAST}
+ {1615723200 -32400 1 HADT}
+ {1636282800 -36000 0 HAST}
+ {1647172800 -32400 1 HADT}
+ {1667732400 -36000 0 HAST}
+ {1678622400 -32400 1 HADT}
+ {1699182000 -36000 0 HAST}
+ {1710072000 -32400 1 HADT}
+ {1730631600 -36000 0 HAST}
+ {1741521600 -32400 1 HADT}
+ {1762081200 -36000 0 HAST}
+ {1772971200 -32400 1 HADT}
+ {1793530800 -36000 0 HAST}
+ {1805025600 -32400 1 HADT}
+ {1825585200 -36000 0 HAST}
+ {1836475200 -32400 1 HADT}
+ {1857034800 -36000 0 HAST}
+ {1867924800 -32400 1 HADT}
+ {1888484400 -36000 0 HAST}
+ {1899374400 -32400 1 HADT}
+ {1919934000 -36000 0 HAST}
+ {1930824000 -32400 1 HADT}
+ {1951383600 -36000 0 HAST}
+ {1962878400 -32400 1 HADT}
+ {1983438000 -36000 0 HAST}
+ {1994328000 -32400 1 HADT}
+ {2014887600 -36000 0 HAST}
+ {2025777600 -32400 1 HADT}
+ {2046337200 -36000 0 HAST}
+ {2057227200 -32400 1 HADT}
+ {2077786800 -36000 0 HAST}
+ {2088676800 -32400 1 HADT}
+ {2109236400 -36000 0 HAST}
+ {2120126400 -32400 1 HADT}
+ {2140686000 -36000 0 HAST}
+ {2152180800 -32400 1 HADT}
+ {2172740400 -36000 0 HAST}
+ {2183630400 -32400 1 HADT}
+ {2204190000 -36000 0 HAST}
+ {2215080000 -32400 1 HADT}
+ {2235639600 -36000 0 HAST}
+ {2246529600 -32400 1 HADT}
+ {2267089200 -36000 0 HAST}
+ {2277979200 -32400 1 HADT}
+ {2298538800 -36000 0 HAST}
+ {2309428800 -32400 1 HADT}
+ {2329988400 -36000 0 HAST}
+ {2341483200 -32400 1 HADT}
+ {2362042800 -36000 0 HAST}
+ {2372932800 -32400 1 HADT}
+ {2393492400 -36000 0 HAST}
+ {2404382400 -32400 1 HADT}
+ {2424942000 -36000 0 HAST}
+ {2435832000 -32400 1 HADT}
+ {2456391600 -36000 0 HAST}
+ {2467281600 -32400 1 HADT}
+ {2487841200 -36000 0 HAST}
+ {2499336000 -32400 1 HADT}
+ {2519895600 -36000 0 HAST}
+ {2530785600 -32400 1 HADT}
+ {2551345200 -36000 0 HAST}
+ {2562235200 -32400 1 HADT}
+ {2582794800 -36000 0 HAST}
+ {2593684800 -32400 1 HADT}
+ {2614244400 -36000 0 HAST}
+ {2625134400 -32400 1 HADT}
+ {2645694000 -36000 0 HAST}
+ {2656584000 -32400 1 HADT}
+ {2677143600 -36000 0 HAST}
+ {2688638400 -32400 1 HADT}
+ {2709198000 -36000 0 HAST}
+ {2720088000 -32400 1 HADT}
+ {2740647600 -36000 0 HAST}
+ {2751537600 -32400 1 HADT}
+ {2772097200 -36000 0 HAST}
+ {2782987200 -32400 1 HADT}
+ {2803546800 -36000 0 HAST}
+ {2814436800 -32400 1 HADT}
+ {2834996400 -36000 0 HAST}
+ {2846491200 -32400 1 HADT}
+ {2867050800 -36000 0 HAST}
+ {2877940800 -32400 1 HADT}
+ {2898500400 -36000 0 HAST}
+ {2909390400 -32400 1 HADT}
+ {2929950000 -36000 0 HAST}
+ {2940840000 -32400 1 HADT}
+ {2961399600 -36000 0 HAST}
+ {2972289600 -32400 1 HADT}
+ {2992849200 -36000 0 HAST}
+ {3003739200 -32400 1 HADT}
+ {3024298800 -36000 0 HAST}
+ {3035793600 -32400 1 HADT}
+ {3056353200 -36000 0 HAST}
+ {3067243200 -32400 1 HADT}
+ {3087802800 -36000 0 HAST}
+ {3098692800 -32400 1 HADT}
+ {3119252400 -36000 0 HAST}
+ {3130142400 -32400 1 HADT}
+ {3150702000 -36000 0 HAST}
+ {3161592000 -32400 1 HADT}
+ {3182151600 -36000 0 HAST}
+ {3193041600 -32400 1 HADT}
+ {3213601200 -36000 0 HAST}
+ {3225096000 -32400 1 HADT}
+ {3245655600 -36000 0 HAST}
+ {3256545600 -32400 1 HADT}
+ {3277105200 -36000 0 HAST}
+ {3287995200 -32400 1 HADT}
+ {3308554800 -36000 0 HAST}
+ {3319444800 -32400 1 HADT}
+ {3340004400 -36000 0 HAST}
+ {3350894400 -32400 1 HADT}
+ {3371454000 -36000 0 HAST}
+ {3382948800 -32400 1 HADT}
+ {3403508400 -36000 0 HAST}
+ {3414398400 -32400 1 HADT}
+ {3434958000 -36000 0 HAST}
+ {3445848000 -32400 1 HADT}
+ {3466407600 -36000 0 HAST}
+ {3477297600 -32400 1 HADT}
+ {3497857200 -36000 0 HAST}
+ {3508747200 -32400 1 HADT}
+ {3529306800 -36000 0 HAST}
+ {3540196800 -32400 1 HADT}
+ {3560756400 -36000 0 HAST}
+ {3572251200 -32400 1 HADT}
+ {3592810800 -36000 0 HAST}
+ {3603700800 -32400 1 HADT}
+ {3624260400 -36000 0 HAST}
+ {3635150400 -32400 1 HADT}
+ {3655710000 -36000 0 HAST}
+ {3666600000 -32400 1 HADT}
+ {3687159600 -36000 0 HAST}
+ {3698049600 -32400 1 HADT}
+ {3718609200 -36000 0 HAST}
+ {3730104000 -32400 1 HADT}
+ {3750663600 -36000 0 HAST}
+ {3761553600 -32400 1 HADT}
+ {3782113200 -36000 0 HAST}
+ {3793003200 -32400 1 HADT}
+ {3813562800 -36000 0 HAST}
+ {3824452800 -32400 1 HADT}
+ {3845012400 -36000 0 HAST}
+ {3855902400 -32400 1 HADT}
+ {3876462000 -36000 0 HAST}
+ {3887352000 -32400 1 HADT}
+ {3907911600 -36000 0 HAST}
+ {3919406400 -32400 1 HADT}
+ {3939966000 -36000 0 HAST}
+ {3950856000 -32400 1 HADT}
+ {3971415600 -36000 0 HAST}
+ {3982305600 -32400 1 HADT}
+ {4002865200 -36000 0 HAST}
+ {4013755200 -32400 1 HADT}
+ {4034314800 -36000 0 HAST}
+ {4045204800 -32400 1 HADT}
+ {4065764400 -36000 0 HAST}
+ {4076654400 -32400 1 HADT}
+ {4097214000 -36000 0 HAST}
+}
diff --git a/library/tzdata/America/Anchorage b/library/tzdata/America/Anchorage
new file mode 100644
index 0000000..e02dd01
--- /dev/null
+++ b/library/tzdata/America/Anchorage
@@ -0,0 +1,276 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Anchorage) {
+ {-9223372036854775808 50424 0 LMT}
+ {-3225362424 -35976 0 LMT}
+ {-2188951224 -36000 0 CAT}
+ {-883576800 -36000 0 CAWT}
+ {-880200000 -32400 1 CAWT}
+ {-769395600 -32400 0 CAPT}
+ {-765378000 -36000 0 CAPT}
+ {-757346400 -36000 0 CAT}
+ {-86882400 -36000 0 AHST}
+ {-31500000 -36000 0 AHST}
+ {-21470400 -32400 1 AHDT}
+ {-5749200 -36000 0 AHST}
+ {9979200 -32400 1 AHDT}
+ {25700400 -36000 0 AHST}
+ {41428800 -32400 1 AHDT}
+ {57754800 -36000 0 AHST}
+ {73483200 -32400 1 AHDT}
+ {89204400 -36000 0 AHST}
+ {104932800 -32400 1 AHDT}
+ {120654000 -36000 0 AHST}
+ {126705600 -32400 1 AHDT}
+ {152103600 -36000 0 AHST}
+ {162388800 -32400 1 AHDT}
+ {183553200 -36000 0 AHST}
+ {199281600 -32400 1 AHDT}
+ {215607600 -36000 0 AHST}
+ {230731200 -32400 1 AHDT}
+ {247057200 -36000 0 AHST}
+ {262785600 -32400 1 AHDT}
+ {278506800 -36000 0 AHST}
+ {294235200 -32400 1 AHDT}
+ {309956400 -36000 0 AHST}
+ {325684800 -32400 1 AHDT}
+ {341406000 -36000 0 AHST}
+ {357134400 -32400 1 AHDT}
+ {372855600 -36000 0 AHST}
+ {388584000 -32400 1 AHDT}
+ {404910000 -36000 0 AHST}
+ {420033600 -32400 1 AHDT}
+ {439030800 -32400 0 AKST}
+ {452084400 -28800 1 AKDT}
+ {467805600 -32400 0 AKST}
+ {483534000 -28800 1 AKDT}
+ {499255200 -32400 0 AKST}
+ {514983600 -28800 1 AKDT}
+ {530704800 -32400 0 AKST}
+ {544618800 -28800 1 AKDT}
+ {562154400 -32400 0 AKST}
+ {576068400 -28800 1 AKDT}
+ {594208800 -32400 0 AKST}
+ {607518000 -28800 1 AKDT}
+ {625658400 -32400 0 AKST}
+ {638967600 -28800 1 AKDT}
+ {657108000 -32400 0 AKST}
+ {671022000 -28800 1 AKDT}
+ {688557600 -32400 0 AKST}
+ {702471600 -28800 1 AKDT}
+ {720007200 -32400 0 AKST}
+ {733921200 -28800 1 AKDT}
+ {752061600 -32400 0 AKST}
+ {765370800 -28800 1 AKDT}
+ {783511200 -32400 0 AKST}
+ {796820400 -28800 1 AKDT}
+ {814960800 -32400 0 AKST}
+ {828874800 -28800 1 AKDT}
+ {846410400 -32400 0 AKST}
+ {860324400 -28800 1 AKDT}
+ {877860000 -32400 0 AKST}
+ {891774000 -28800 1 AKDT}
+ {909309600 -32400 0 AKST}
+ {923223600 -28800 1 AKDT}
+ {941364000 -32400 0 AKST}
+ {954673200 -28800 1 AKDT}
+ {972813600 -32400 0 AKST}
+ {986122800 -28800 1 AKDT}
+ {1004263200 -32400 0 AKST}
+ {1018177200 -28800 1 AKDT}
+ {1035712800 -32400 0 AKST}
+ {1049626800 -28800 1 AKDT}
+ {1067162400 -32400 0 AKST}
+ {1081076400 -28800 1 AKDT}
+ {1099216800 -32400 0 AKST}
+ {1112526000 -28800 1 AKDT}
+ {1130666400 -32400 0 AKST}
+ {1143975600 -28800 1 AKDT}
+ {1162116000 -32400 0 AKST}
+ {1173610800 -28800 1 AKDT}
+ {1194170400 -32400 0 AKST}
+ {1205060400 -28800 1 AKDT}
+ {1225620000 -32400 0 AKST}
+ {1236510000 -28800 1 AKDT}
+ {1257069600 -32400 0 AKST}
+ {1268564400 -28800 1 AKDT}
+ {1289124000 -32400 0 AKST}
+ {1300014000 -28800 1 AKDT}
+ {1320573600 -32400 0 AKST}
+ {1331463600 -28800 1 AKDT}
+ {1352023200 -32400 0 AKST}
+ {1362913200 -28800 1 AKDT}
+ {1383472800 -32400 0 AKST}
+ {1394362800 -28800 1 AKDT}
+ {1414922400 -32400 0 AKST}
+ {1425812400 -28800 1 AKDT}
+ {1446372000 -32400 0 AKST}
+ {1457866800 -28800 1 AKDT}
+ {1478426400 -32400 0 AKST}
+ {1489316400 -28800 1 AKDT}
+ {1509876000 -32400 0 AKST}
+ {1520766000 -28800 1 AKDT}
+ {1541325600 -32400 0 AKST}
+ {1552215600 -28800 1 AKDT}
+ {1572775200 -32400 0 AKST}
+ {1583665200 -28800 1 AKDT}
+ {1604224800 -32400 0 AKST}
+ {1615719600 -28800 1 AKDT}
+ {1636279200 -32400 0 AKST}
+ {1647169200 -28800 1 AKDT}
+ {1667728800 -32400 0 AKST}
+ {1678618800 -28800 1 AKDT}
+ {1699178400 -32400 0 AKST}
+ {1710068400 -28800 1 AKDT}
+ {1730628000 -32400 0 AKST}
+ {1741518000 -28800 1 AKDT}
+ {1762077600 -32400 0 AKST}
+ {1772967600 -28800 1 AKDT}
+ {1793527200 -32400 0 AKST}
+ {1805022000 -28800 1 AKDT}
+ {1825581600 -32400 0 AKST}
+ {1836471600 -28800 1 AKDT}
+ {1857031200 -32400 0 AKST}
+ {1867921200 -28800 1 AKDT}
+ {1888480800 -32400 0 AKST}
+ {1899370800 -28800 1 AKDT}
+ {1919930400 -32400 0 AKST}
+ {1930820400 -28800 1 AKDT}
+ {1951380000 -32400 0 AKST}
+ {1962874800 -28800 1 AKDT}
+ {1983434400 -32400 0 AKST}
+ {1994324400 -28800 1 AKDT}
+ {2014884000 -32400 0 AKST}
+ {2025774000 -28800 1 AKDT}
+ {2046333600 -32400 0 AKST}
+ {2057223600 -28800 1 AKDT}
+ {2077783200 -32400 0 AKST}
+ {2088673200 -28800 1 AKDT}
+ {2109232800 -32400 0 AKST}
+ {2120122800 -28800 1 AKDT}
+ {2140682400 -32400 0 AKST}
+ {2152177200 -28800 1 AKDT}
+ {2172736800 -32400 0 AKST}
+ {2183626800 -28800 1 AKDT}
+ {2204186400 -32400 0 AKST}
+ {2215076400 -28800 1 AKDT}
+ {2235636000 -32400 0 AKST}
+ {2246526000 -28800 1 AKDT}
+ {2267085600 -32400 0 AKST}
+ {2277975600 -28800 1 AKDT}
+ {2298535200 -32400 0 AKST}
+ {2309425200 -28800 1 AKDT}
+ {2329984800 -32400 0 AKST}
+ {2341479600 -28800 1 AKDT}
+ {2362039200 -32400 0 AKST}
+ {2372929200 -28800 1 AKDT}
+ {2393488800 -32400 0 AKST}
+ {2404378800 -28800 1 AKDT}
+ {2424938400 -32400 0 AKST}
+ {2435828400 -28800 1 AKDT}
+ {2456388000 -32400 0 AKST}
+ {2467278000 -28800 1 AKDT}
+ {2487837600 -32400 0 AKST}
+ {2499332400 -28800 1 AKDT}
+ {2519892000 -32400 0 AKST}
+ {2530782000 -28800 1 AKDT}
+ {2551341600 -32400 0 AKST}
+ {2562231600 -28800 1 AKDT}
+ {2582791200 -32400 0 AKST}
+ {2593681200 -28800 1 AKDT}
+ {2614240800 -32400 0 AKST}
+ {2625130800 -28800 1 AKDT}
+ {2645690400 -32400 0 AKST}
+ {2656580400 -28800 1 AKDT}
+ {2677140000 -32400 0 AKST}
+ {2688634800 -28800 1 AKDT}
+ {2709194400 -32400 0 AKST}
+ {2720084400 -28800 1 AKDT}
+ {2740644000 -32400 0 AKST}
+ {2751534000 -28800 1 AKDT}
+ {2772093600 -32400 0 AKST}
+ {2782983600 -28800 1 AKDT}
+ {2803543200 -32400 0 AKST}
+ {2814433200 -28800 1 AKDT}
+ {2834992800 -32400 0 AKST}
+ {2846487600 -28800 1 AKDT}
+ {2867047200 -32400 0 AKST}
+ {2877937200 -28800 1 AKDT}
+ {2898496800 -32400 0 AKST}
+ {2909386800 -28800 1 AKDT}
+ {2929946400 -32400 0 AKST}
+ {2940836400 -28800 1 AKDT}
+ {2961396000 -32400 0 AKST}
+ {2972286000 -28800 1 AKDT}
+ {2992845600 -32400 0 AKST}
+ {3003735600 -28800 1 AKDT}
+ {3024295200 -32400 0 AKST}
+ {3035790000 -28800 1 AKDT}
+ {3056349600 -32400 0 AKST}
+ {3067239600 -28800 1 AKDT}
+ {3087799200 -32400 0 AKST}
+ {3098689200 -28800 1 AKDT}
+ {3119248800 -32400 0 AKST}
+ {3130138800 -28800 1 AKDT}
+ {3150698400 -32400 0 AKST}
+ {3161588400 -28800 1 AKDT}
+ {3182148000 -32400 0 AKST}
+ {3193038000 -28800 1 AKDT}
+ {3213597600 -32400 0 AKST}
+ {3225092400 -28800 1 AKDT}
+ {3245652000 -32400 0 AKST}
+ {3256542000 -28800 1 AKDT}
+ {3277101600 -32400 0 AKST}
+ {3287991600 -28800 1 AKDT}
+ {3308551200 -32400 0 AKST}
+ {3319441200 -28800 1 AKDT}
+ {3340000800 -32400 0 AKST}
+ {3350890800 -28800 1 AKDT}
+ {3371450400 -32400 0 AKST}
+ {3382945200 -28800 1 AKDT}
+ {3403504800 -32400 0 AKST}
+ {3414394800 -28800 1 AKDT}
+ {3434954400 -32400 0 AKST}
+ {3445844400 -28800 1 AKDT}
+ {3466404000 -32400 0 AKST}
+ {3477294000 -28800 1 AKDT}
+ {3497853600 -32400 0 AKST}
+ {3508743600 -28800 1 AKDT}
+ {3529303200 -32400 0 AKST}
+ {3540193200 -28800 1 AKDT}
+ {3560752800 -32400 0 AKST}
+ {3572247600 -28800 1 AKDT}
+ {3592807200 -32400 0 AKST}
+ {3603697200 -28800 1 AKDT}
+ {3624256800 -32400 0 AKST}
+ {3635146800 -28800 1 AKDT}
+ {3655706400 -32400 0 AKST}
+ {3666596400 -28800 1 AKDT}
+ {3687156000 -32400 0 AKST}
+ {3698046000 -28800 1 AKDT}
+ {3718605600 -32400 0 AKST}
+ {3730100400 -28800 1 AKDT}
+ {3750660000 -32400 0 AKST}
+ {3761550000 -28800 1 AKDT}
+ {3782109600 -32400 0 AKST}
+ {3792999600 -28800 1 AKDT}
+ {3813559200 -32400 0 AKST}
+ {3824449200 -28800 1 AKDT}
+ {3845008800 -32400 0 AKST}
+ {3855898800 -28800 1 AKDT}
+ {3876458400 -32400 0 AKST}
+ {3887348400 -28800 1 AKDT}
+ {3907908000 -32400 0 AKST}
+ {3919402800 -28800 1 AKDT}
+ {3939962400 -32400 0 AKST}
+ {3950852400 -28800 1 AKDT}
+ {3971412000 -32400 0 AKST}
+ {3982302000 -28800 1 AKDT}
+ {4002861600 -32400 0 AKST}
+ {4013751600 -28800 1 AKDT}
+ {4034311200 -32400 0 AKST}
+ {4045201200 -28800 1 AKDT}
+ {4065760800 -32400 0 AKST}
+ {4076650800 -28800 1 AKDT}
+ {4097210400 -32400 0 AKST}
+}
diff --git a/library/tzdata/America/Anguilla b/library/tzdata/America/Anguilla
new file mode 100644
index 0000000..cfe7483
--- /dev/null
+++ b/library/tzdata/America/Anguilla
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Anguilla) {
+ {-9223372036854775808 -15136 0 LMT}
+ {-1825098464 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Antigua b/library/tzdata/America/Antigua
new file mode 100644
index 0000000..5433e9b
--- /dev/null
+++ b/library/tzdata/America/Antigua
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Antigua) {
+ {-9223372036854775808 -14832 0 LMT}
+ {-1825098768 -18000 0 EST}
+ {-599598000 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Araguaina b/library/tzdata/America/Araguaina
new file mode 100644
index 0000000..5073c56
--- /dev/null
+++ b/library/tzdata/America/Araguaina
@@ -0,0 +1,57 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Araguaina) {
+ {-9223372036854775808 -11568 0 LMT}
+ {-1767214032 -10800 0 BRT}
+ {-1206957600 -7200 1 BRST}
+ {-1191362400 -10800 0 BRT}
+ {-1175374800 -7200 1 BRST}
+ {-1159826400 -10800 0 BRT}
+ {-633819600 -7200 1 BRST}
+ {-622069200 -10800 0 BRT}
+ {-602283600 -7200 1 BRST}
+ {-591832800 -10800 0 BRT}
+ {-570747600 -7200 1 BRST}
+ {-560210400 -10800 0 BRT}
+ {-539125200 -7200 1 BRST}
+ {-531352800 -10800 0 BRT}
+ {-191365200 -7200 1 BRST}
+ {-184197600 -10800 0 BRT}
+ {-155163600 -7200 1 BRST}
+ {-150069600 -10800 0 BRT}
+ {-128898000 -7200 1 BRST}
+ {-121125600 -10800 0 BRT}
+ {-99954000 -7200 1 BRST}
+ {-89589600 -10800 0 BRT}
+ {-68418000 -7200 1 BRST}
+ {-57967200 -10800 0 BRT}
+ {499748400 -7200 1 BRST}
+ {511236000 -10800 0 BRT}
+ {530593200 -7200 1 BRST}
+ {540266400 -10800 0 BRT}
+ {562129200 -7200 1 BRST}
+ {571197600 -10800 0 BRT}
+ {592974000 -7200 1 BRST}
+ {602042400 -10800 0 BRT}
+ {624423600 -7200 1 BRST}
+ {634701600 -10800 0 BRT}
+ {653536800 -10800 0 BRT}
+ {811047600 -10800 0 BRT}
+ {813726000 -7200 1 BRST}
+ {824004000 -10800 0 BRT}
+ {844570800 -7200 1 BRST}
+ {856058400 -10800 0 BRT}
+ {876106800 -7200 1 BRST}
+ {888717600 -10800 0 BRT}
+ {908074800 -7200 1 BRST}
+ {919562400 -10800 0 BRT}
+ {938919600 -7200 1 BRST}
+ {951616800 -10800 0 BRT}
+ {970974000 -7200 1 BRST}
+ {982461600 -10800 0 BRT}
+ {1003028400 -7200 1 BRST}
+ {1013911200 -10800 0 BRT}
+ {1036292400 -7200 1 BRST}
+ {1045360800 -10800 0 BRT}
+ {1064368800 -10800 0 BRT}
+}
diff --git a/library/tzdata/America/Argentina/Buenos_Aires b/library/tzdata/America/Argentina/Buenos_Aires
new file mode 100644
index 0000000..73cc8e9
--- /dev/null
+++ b/library/tzdata/America/Argentina/Buenos_Aires
@@ -0,0 +1,67 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Argentina/Buenos_Aires) {
+ {-9223372036854775808 -14028 0 LMT}
+ {-2372097972 -15408 0 CMT}
+ {-1567453392 -14400 0 ART}
+ {-1233432000 -10800 0 ARST}
+ {-1222981200 -14400 0 ART}
+ {-1205956800 -10800 1 ARST}
+ {-1194037200 -14400 0 ART}
+ {-1172865600 -10800 1 ARST}
+ {-1162501200 -14400 0 ART}
+ {-1141329600 -10800 1 ARST}
+ {-1130965200 -14400 0 ART}
+ {-1109793600 -10800 1 ARST}
+ {-1099429200 -14400 0 ART}
+ {-1078257600 -10800 1 ARST}
+ {-1067806800 -14400 0 ART}
+ {-1046635200 -10800 1 ARST}
+ {-1036270800 -14400 0 ART}
+ {-1015099200 -10800 1 ARST}
+ {-1004734800 -14400 0 ART}
+ {-983563200 -10800 1 ARST}
+ {-973198800 -14400 0 ART}
+ {-952027200 -10800 1 ARST}
+ {-941576400 -14400 0 ART}
+ {-931032000 -10800 1 ARST}
+ {-900882000 -14400 0 ART}
+ {-890337600 -10800 1 ARST}
+ {-833749200 -14400 0 ART}
+ {-827265600 -10800 1 ARST}
+ {-752274000 -14400 0 ART}
+ {-733780800 -10800 1 ARST}
+ {-197326800 -14400 0 ART}
+ {-190843200 -10800 1 ARST}
+ {-184194000 -14400 0 ART}
+ {-164491200 -10800 1 ARST}
+ {-152658000 -14400 0 ART}
+ {-132955200 -10800 1 ARST}
+ {-121122000 -14400 0 ART}
+ {-101419200 -10800 1 ARST}
+ {-86821200 -14400 0 ART}
+ {-71092800 -10800 1 ARST}
+ {-54766800 -14400 0 ART}
+ {-39038400 -10800 1 ARST}
+ {-23317200 -14400 0 ART}
+ {-7588800 -10800 0 ART}
+ {128142000 -7200 1 ARST}
+ {136605600 -10800 0 ART}
+ {596948400 -7200 1 ARST}
+ {605066400 -10800 0 ART}
+ {624423600 -7200 1 ARST}
+ {636516000 -10800 0 ART}
+ {656478000 -7200 1 ARST}
+ {667965600 -10800 0 ART}
+ {687927600 -7200 1 ARST}
+ {699415200 -10800 0 ART}
+ {719377200 -7200 1 ARST}
+ {731469600 -10800 0 ART}
+ {938916000 -10800 0 ART}
+ {938919600 -10800 1 ARST}
+ {952056000 -10800 0 ART}
+ {1198983600 -7200 1 ARST}
+ {1205632800 -10800 0 ART}
+ {1224385200 -7200 1 ARST}
+ {1237082400 -10800 0 ART}
+}
diff --git a/library/tzdata/America/Argentina/Catamarca b/library/tzdata/America/Argentina/Catamarca
new file mode 100644
index 0000000..7739203
--- /dev/null
+++ b/library/tzdata/America/Argentina/Catamarca
@@ -0,0 +1,68 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Argentina/Catamarca) {
+ {-9223372036854775808 -15788 0 LMT}
+ {-2372096212 -15408 0 CMT}
+ {-1567453392 -14400 0 ART}
+ {-1233432000 -10800 0 ARST}
+ {-1222981200 -14400 0 ART}
+ {-1205956800 -10800 1 ARST}
+ {-1194037200 -14400 0 ART}
+ {-1172865600 -10800 1 ARST}
+ {-1162501200 -14400 0 ART}
+ {-1141329600 -10800 1 ARST}
+ {-1130965200 -14400 0 ART}
+ {-1109793600 -10800 1 ARST}
+ {-1099429200 -14400 0 ART}
+ {-1078257600 -10800 1 ARST}
+ {-1067806800 -14400 0 ART}
+ {-1046635200 -10800 1 ARST}
+ {-1036270800 -14400 0 ART}
+ {-1015099200 -10800 1 ARST}
+ {-1004734800 -14400 0 ART}
+ {-983563200 -10800 1 ARST}
+ {-973198800 -14400 0 ART}
+ {-952027200 -10800 1 ARST}
+ {-941576400 -14400 0 ART}
+ {-931032000 -10800 1 ARST}
+ {-900882000 -14400 0 ART}
+ {-890337600 -10800 1 ARST}
+ {-833749200 -14400 0 ART}
+ {-827265600 -10800 1 ARST}
+ {-752274000 -14400 0 ART}
+ {-733780800 -10800 1 ARST}
+ {-197326800 -14400 0 ART}
+ {-190843200 -10800 1 ARST}
+ {-184194000 -14400 0 ART}
+ {-164491200 -10800 1 ARST}
+ {-152658000 -14400 0 ART}
+ {-132955200 -10800 1 ARST}
+ {-121122000 -14400 0 ART}
+ {-101419200 -10800 1 ARST}
+ {-86821200 -14400 0 ART}
+ {-71092800 -10800 1 ARST}
+ {-54766800 -14400 0 ART}
+ {-39038400 -10800 1 ARST}
+ {-23317200 -14400 0 ART}
+ {-7588800 -10800 0 ART}
+ {128142000 -7200 1 ARST}
+ {136605600 -10800 0 ART}
+ {596948400 -7200 1 ARST}
+ {605066400 -10800 0 ART}
+ {624423600 -7200 1 ARST}
+ {636516000 -10800 0 ART}
+ {656478000 -7200 1 ARST}
+ {667965600 -14400 0 WART}
+ {687931200 -7200 0 ARST}
+ {699415200 -10800 0 ART}
+ {719377200 -7200 1 ARST}
+ {731469600 -10800 0 ART}
+ {938916000 -10800 0 ART}
+ {938919600 -10800 1 ARST}
+ {952056000 -10800 0 ART}
+ {1086058800 -14400 0 WART}
+ {1087704000 -10800 0 ART}
+ {1198983600 -7200 1 ARST}
+ {1205632800 -10800 0 ART}
+ {1224295200 -10800 0 ART}
+}
diff --git a/library/tzdata/America/Argentina/ComodRivadavia b/library/tzdata/America/Argentina/ComodRivadavia
new file mode 100644
index 0000000..2611a3d
--- /dev/null
+++ b/library/tzdata/America/Argentina/ComodRivadavia
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Argentina/Catamarca)]} {
+ LoadTimeZoneFile America/Argentina/Catamarca
+}
+set TZData(:America/Argentina/ComodRivadavia) $TZData(:America/Argentina/Catamarca)
diff --git a/library/tzdata/America/Argentina/Cordoba b/library/tzdata/America/Argentina/Cordoba
new file mode 100644
index 0000000..b08539e
--- /dev/null
+++ b/library/tzdata/America/Argentina/Cordoba
@@ -0,0 +1,67 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Argentina/Cordoba) {
+ {-9223372036854775808 -15408 0 LMT}
+ {-2372096592 -15408 0 CMT}
+ {-1567453392 -14400 0 ART}
+ {-1233432000 -10800 0 ARST}
+ {-1222981200 -14400 0 ART}
+ {-1205956800 -10800 1 ARST}
+ {-1194037200 -14400 0 ART}
+ {-1172865600 -10800 1 ARST}
+ {-1162501200 -14400 0 ART}
+ {-1141329600 -10800 1 ARST}
+ {-1130965200 -14400 0 ART}
+ {-1109793600 -10800 1 ARST}
+ {-1099429200 -14400 0 ART}
+ {-1078257600 -10800 1 ARST}
+ {-1067806800 -14400 0 ART}
+ {-1046635200 -10800 1 ARST}
+ {-1036270800 -14400 0 ART}
+ {-1015099200 -10800 1 ARST}
+ {-1004734800 -14400 0 ART}
+ {-983563200 -10800 1 ARST}
+ {-973198800 -14400 0 ART}
+ {-952027200 -10800 1 ARST}
+ {-941576400 -14400 0 ART}
+ {-931032000 -10800 1 ARST}
+ {-900882000 -14400 0 ART}
+ {-890337600 -10800 1 ARST}
+ {-833749200 -14400 0 ART}
+ {-827265600 -10800 1 ARST}
+ {-752274000 -14400 0 ART}
+ {-733780800 -10800 1 ARST}
+ {-197326800 -14400 0 ART}
+ {-190843200 -10800 1 ARST}
+ {-184194000 -14400 0 ART}
+ {-164491200 -10800 1 ARST}
+ {-152658000 -14400 0 ART}
+ {-132955200 -10800 1 ARST}
+ {-121122000 -14400 0 ART}
+ {-101419200 -10800 1 ARST}
+ {-86821200 -14400 0 ART}
+ {-71092800 -10800 1 ARST}
+ {-54766800 -14400 0 ART}
+ {-39038400 -10800 1 ARST}
+ {-23317200 -14400 0 ART}
+ {-7588800 -10800 0 ART}
+ {128142000 -7200 1 ARST}
+ {136605600 -10800 0 ART}
+ {596948400 -7200 1 ARST}
+ {605066400 -10800 0 ART}
+ {624423600 -7200 1 ARST}
+ {636516000 -10800 0 ART}
+ {656478000 -7200 1 ARST}
+ {667965600 -14400 0 WART}
+ {687931200 -7200 0 ARST}
+ {699415200 -10800 0 ART}
+ {719377200 -7200 1 ARST}
+ {731469600 -10800 0 ART}
+ {938916000 -10800 0 ART}
+ {938919600 -10800 1 ARST}
+ {952056000 -10800 0 ART}
+ {1198983600 -7200 1 ARST}
+ {1205632800 -10800 0 ART}
+ {1224385200 -7200 1 ARST}
+ {1237082400 -10800 0 ART}
+}
diff --git a/library/tzdata/America/Argentina/Jujuy b/library/tzdata/America/Argentina/Jujuy
new file mode 100644
index 0000000..4f95f8a
--- /dev/null
+++ b/library/tzdata/America/Argentina/Jujuy
@@ -0,0 +1,67 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Argentina/Jujuy) {
+ {-9223372036854775808 -15672 0 LMT}
+ {-2372096328 -15408 0 CMT}
+ {-1567453392 -14400 0 ART}
+ {-1233432000 -10800 0 ARST}
+ {-1222981200 -14400 0 ART}
+ {-1205956800 -10800 1 ARST}
+ {-1194037200 -14400 0 ART}
+ {-1172865600 -10800 1 ARST}
+ {-1162501200 -14400 0 ART}
+ {-1141329600 -10800 1 ARST}
+ {-1130965200 -14400 0 ART}
+ {-1109793600 -10800 1 ARST}
+ {-1099429200 -14400 0 ART}
+ {-1078257600 -10800 1 ARST}
+ {-1067806800 -14400 0 ART}
+ {-1046635200 -10800 1 ARST}
+ {-1036270800 -14400 0 ART}
+ {-1015099200 -10800 1 ARST}
+ {-1004734800 -14400 0 ART}
+ {-983563200 -10800 1 ARST}
+ {-973198800 -14400 0 ART}
+ {-952027200 -10800 1 ARST}
+ {-941576400 -14400 0 ART}
+ {-931032000 -10800 1 ARST}
+ {-900882000 -14400 0 ART}
+ {-890337600 -10800 1 ARST}
+ {-833749200 -14400 0 ART}
+ {-827265600 -10800 1 ARST}
+ {-752274000 -14400 0 ART}
+ {-733780800 -10800 1 ARST}
+ {-197326800 -14400 0 ART}
+ {-190843200 -10800 1 ARST}
+ {-184194000 -14400 0 ART}
+ {-164491200 -10800 1 ARST}
+ {-152658000 -14400 0 ART}
+ {-132955200 -10800 1 ARST}
+ {-121122000 -14400 0 ART}
+ {-101419200 -10800 1 ARST}
+ {-86821200 -14400 0 ART}
+ {-71092800 -10800 1 ARST}
+ {-54766800 -14400 0 ART}
+ {-39038400 -10800 1 ARST}
+ {-23317200 -14400 0 ART}
+ {-7588800 -10800 0 ART}
+ {128142000 -7200 1 ARST}
+ {136605600 -10800 0 ART}
+ {596948400 -7200 1 ARST}
+ {605066400 -10800 0 ART}
+ {624423600 -7200 1 ARST}
+ {636516000 -14400 0 WART}
+ {657086400 -10800 1 WARST}
+ {669178800 -14400 0 WART}
+ {686721600 -7200 1 ARST}
+ {694231200 -7200 0 ART}
+ {699415200 -10800 0 ART}
+ {719377200 -7200 1 ARST}
+ {731469600 -10800 0 ART}
+ {938916000 -10800 0 ART}
+ {938919600 -10800 1 ARST}
+ {952056000 -10800 0 ART}
+ {1198983600 -7200 1 ARST}
+ {1205632800 -10800 0 ART}
+ {1224295200 -10800 0 ART}
+}
diff --git a/library/tzdata/America/Argentina/La_Rioja b/library/tzdata/America/Argentina/La_Rioja
new file mode 100644
index 0000000..835e29d
--- /dev/null
+++ b/library/tzdata/America/Argentina/La_Rioja
@@ -0,0 +1,69 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Argentina/La_Rioja) {
+ {-9223372036854775808 -16044 0 LMT}
+ {-2372095956 -15408 0 CMT}
+ {-1567453392 -14400 0 ART}
+ {-1233432000 -10800 0 ARST}
+ {-1222981200 -14400 0 ART}
+ {-1205956800 -10800 1 ARST}
+ {-1194037200 -14400 0 ART}
+ {-1172865600 -10800 1 ARST}
+ {-1162501200 -14400 0 ART}
+ {-1141329600 -10800 1 ARST}
+ {-1130965200 -14400 0 ART}
+ {-1109793600 -10800 1 ARST}
+ {-1099429200 -14400 0 ART}
+ {-1078257600 -10800 1 ARST}
+ {-1067806800 -14400 0 ART}
+ {-1046635200 -10800 1 ARST}
+ {-1036270800 -14400 0 ART}
+ {-1015099200 -10800 1 ARST}
+ {-1004734800 -14400 0 ART}
+ {-983563200 -10800 1 ARST}
+ {-973198800 -14400 0 ART}
+ {-952027200 -10800 1 ARST}
+ {-941576400 -14400 0 ART}
+ {-931032000 -10800 1 ARST}
+ {-900882000 -14400 0 ART}
+ {-890337600 -10800 1 ARST}
+ {-833749200 -14400 0 ART}
+ {-827265600 -10800 1 ARST}
+ {-752274000 -14400 0 ART}
+ {-733780800 -10800 1 ARST}
+ {-197326800 -14400 0 ART}
+ {-190843200 -10800 1 ARST}
+ {-184194000 -14400 0 ART}
+ {-164491200 -10800 1 ARST}
+ {-152658000 -14400 0 ART}
+ {-132955200 -10800 1 ARST}
+ {-121122000 -14400 0 ART}
+ {-101419200 -10800 1 ARST}
+ {-86821200 -14400 0 ART}
+ {-71092800 -10800 1 ARST}
+ {-54766800 -14400 0 ART}
+ {-39038400 -10800 1 ARST}
+ {-23317200 -14400 0 ART}
+ {-7588800 -10800 0 ART}
+ {128142000 -7200 1 ARST}
+ {136605600 -10800 0 ART}
+ {596948400 -7200 1 ARST}
+ {605066400 -10800 0 ART}
+ {624423600 -7200 1 ARST}
+ {636516000 -10800 0 ART}
+ {656478000 -7200 1 ARST}
+ {667792800 -14400 0 WART}
+ {673588800 -10800 0 ART}
+ {687927600 -7200 1 ARST}
+ {699415200 -10800 0 ART}
+ {719377200 -7200 1 ARST}
+ {731469600 -10800 0 ART}
+ {938916000 -10800 0 ART}
+ {938919600 -10800 1 ARST}
+ {952056000 -10800 0 ART}
+ {1086058800 -14400 0 WART}
+ {1087704000 -10800 0 ART}
+ {1198983600 -7200 1 ARST}
+ {1205632800 -10800 0 ART}
+ {1224295200 -10800 0 ART}
+}
diff --git a/library/tzdata/America/Argentina/Mendoza b/library/tzdata/America/Argentina/Mendoza
new file mode 100644
index 0000000..2c6fb58
--- /dev/null
+++ b/library/tzdata/America/Argentina/Mendoza
@@ -0,0 +1,68 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Argentina/Mendoza) {
+ {-9223372036854775808 -16516 0 LMT}
+ {-2372095484 -15408 0 CMT}
+ {-1567453392 -14400 0 ART}
+ {-1233432000 -10800 0 ARST}
+ {-1222981200 -14400 0 ART}
+ {-1205956800 -10800 1 ARST}
+ {-1194037200 -14400 0 ART}
+ {-1172865600 -10800 1 ARST}
+ {-1162501200 -14400 0 ART}
+ {-1141329600 -10800 1 ARST}
+ {-1130965200 -14400 0 ART}
+ {-1109793600 -10800 1 ARST}
+ {-1099429200 -14400 0 ART}
+ {-1078257600 -10800 1 ARST}
+ {-1067806800 -14400 0 ART}
+ {-1046635200 -10800 1 ARST}
+ {-1036270800 -14400 0 ART}
+ {-1015099200 -10800 1 ARST}
+ {-1004734800 -14400 0 ART}
+ {-983563200 -10800 1 ARST}
+ {-973198800 -14400 0 ART}
+ {-952027200 -10800 1 ARST}
+ {-941576400 -14400 0 ART}
+ {-931032000 -10800 1 ARST}
+ {-900882000 -14400 0 ART}
+ {-890337600 -10800 1 ARST}
+ {-833749200 -14400 0 ART}
+ {-827265600 -10800 1 ARST}
+ {-752274000 -14400 0 ART}
+ {-733780800 -10800 1 ARST}
+ {-197326800 -14400 0 ART}
+ {-190843200 -10800 1 ARST}
+ {-184194000 -14400 0 ART}
+ {-164491200 -10800 1 ARST}
+ {-152658000 -14400 0 ART}
+ {-132955200 -10800 1 ARST}
+ {-121122000 -14400 0 ART}
+ {-101419200 -10800 1 ARST}
+ {-86821200 -14400 0 ART}
+ {-71092800 -10800 1 ARST}
+ {-54766800 -14400 0 ART}
+ {-39038400 -10800 1 ARST}
+ {-23317200 -14400 0 ART}
+ {-7588800 -10800 0 ART}
+ {128142000 -7200 1 ARST}
+ {136605600 -10800 0 ART}
+ {596948400 -7200 1 ARST}
+ {605066400 -10800 0 ART}
+ {624423600 -7200 1 ARST}
+ {636516000 -14400 0 WART}
+ {655963200 -10800 1 WARST}
+ {667796400 -14400 0 WART}
+ {687499200 -10800 1 WARST}
+ {699418800 -14400 0 WART}
+ {719380800 -7200 0 ARST}
+ {731469600 -10800 0 ART}
+ {938916000 -10800 0 ART}
+ {938919600 -10800 1 ARST}
+ {952056000 -10800 0 ART}
+ {1085281200 -14400 0 WART}
+ {1096171200 -10800 0 ART}
+ {1198983600 -7200 1 ARST}
+ {1205632800 -10800 0 ART}
+ {1224295200 -10800 0 ART}
+}
diff --git a/library/tzdata/America/Argentina/Rio_Gallegos b/library/tzdata/America/Argentina/Rio_Gallegos
new file mode 100644
index 0000000..91d37dd
--- /dev/null
+++ b/library/tzdata/America/Argentina/Rio_Gallegos
@@ -0,0 +1,68 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Argentina/Rio_Gallegos) {
+ {-9223372036854775808 -16612 0 LMT}
+ {-2372095388 -15408 0 CMT}
+ {-1567453392 -14400 0 ART}
+ {-1233432000 -10800 0 ARST}
+ {-1222981200 -14400 0 ART}
+ {-1205956800 -10800 1 ARST}
+ {-1194037200 -14400 0 ART}
+ {-1172865600 -10800 1 ARST}
+ {-1162501200 -14400 0 ART}
+ {-1141329600 -10800 1 ARST}
+ {-1130965200 -14400 0 ART}
+ {-1109793600 -10800 1 ARST}
+ {-1099429200 -14400 0 ART}
+ {-1078257600 -10800 1 ARST}
+ {-1067806800 -14400 0 ART}
+ {-1046635200 -10800 1 ARST}
+ {-1036270800 -14400 0 ART}
+ {-1015099200 -10800 1 ARST}
+ {-1004734800 -14400 0 ART}
+ {-983563200 -10800 1 ARST}
+ {-973198800 -14400 0 ART}
+ {-952027200 -10800 1 ARST}
+ {-941576400 -14400 0 ART}
+ {-931032000 -10800 1 ARST}
+ {-900882000 -14400 0 ART}
+ {-890337600 -10800 1 ARST}
+ {-833749200 -14400 0 ART}
+ {-827265600 -10800 1 ARST}
+ {-752274000 -14400 0 ART}
+ {-733780800 -10800 1 ARST}
+ {-197326800 -14400 0 ART}
+ {-190843200 -10800 1 ARST}
+ {-184194000 -14400 0 ART}
+ {-164491200 -10800 1 ARST}
+ {-152658000 -14400 0 ART}
+ {-132955200 -10800 1 ARST}
+ {-121122000 -14400 0 ART}
+ {-101419200 -10800 1 ARST}
+ {-86821200 -14400 0 ART}
+ {-71092800 -10800 1 ARST}
+ {-54766800 -14400 0 ART}
+ {-39038400 -10800 1 ARST}
+ {-23317200 -14400 0 ART}
+ {-7588800 -10800 0 ART}
+ {128142000 -7200 1 ARST}
+ {136605600 -10800 0 ART}
+ {596948400 -7200 1 ARST}
+ {605066400 -10800 0 ART}
+ {624423600 -7200 1 ARST}
+ {636516000 -10800 0 ART}
+ {656478000 -7200 1 ARST}
+ {667965600 -10800 0 ART}
+ {687927600 -7200 1 ARST}
+ {699415200 -10800 0 ART}
+ {719377200 -7200 1 ARST}
+ {731469600 -10800 0 ART}
+ {938916000 -10800 0 ART}
+ {938919600 -10800 1 ARST}
+ {952056000 -10800 0 ART}
+ {1086058800 -14400 0 WART}
+ {1087704000 -10800 0 ART}
+ {1198983600 -7200 1 ARST}
+ {1205632800 -10800 0 ART}
+ {1224295200 -10800 0 ART}
+}
diff --git a/library/tzdata/America/Argentina/Salta b/library/tzdata/America/Argentina/Salta
new file mode 100644
index 0000000..a5a7010
--- /dev/null
+++ b/library/tzdata/America/Argentina/Salta
@@ -0,0 +1,66 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Argentina/Salta) {
+ {-9223372036854775808 -15700 0 LMT}
+ {-2372096300 -15408 0 CMT}
+ {-1567453392 -14400 0 ART}
+ {-1233432000 -10800 0 ARST}
+ {-1222981200 -14400 0 ART}
+ {-1205956800 -10800 1 ARST}
+ {-1194037200 -14400 0 ART}
+ {-1172865600 -10800 1 ARST}
+ {-1162501200 -14400 0 ART}
+ {-1141329600 -10800 1 ARST}
+ {-1130965200 -14400 0 ART}
+ {-1109793600 -10800 1 ARST}
+ {-1099429200 -14400 0 ART}
+ {-1078257600 -10800 1 ARST}
+ {-1067806800 -14400 0 ART}
+ {-1046635200 -10800 1 ARST}
+ {-1036270800 -14400 0 ART}
+ {-1015099200 -10800 1 ARST}
+ {-1004734800 -14400 0 ART}
+ {-983563200 -10800 1 ARST}
+ {-973198800 -14400 0 ART}
+ {-952027200 -10800 1 ARST}
+ {-941576400 -14400 0 ART}
+ {-931032000 -10800 1 ARST}
+ {-900882000 -14400 0 ART}
+ {-890337600 -10800 1 ARST}
+ {-833749200 -14400 0 ART}
+ {-827265600 -10800 1 ARST}
+ {-752274000 -14400 0 ART}
+ {-733780800 -10800 1 ARST}
+ {-197326800 -14400 0 ART}
+ {-190843200 -10800 1 ARST}
+ {-184194000 -14400 0 ART}
+ {-164491200 -10800 1 ARST}
+ {-152658000 -14400 0 ART}
+ {-132955200 -10800 1 ARST}
+ {-121122000 -14400 0 ART}
+ {-101419200 -10800 1 ARST}
+ {-86821200 -14400 0 ART}
+ {-71092800 -10800 1 ARST}
+ {-54766800 -14400 0 ART}
+ {-39038400 -10800 1 ARST}
+ {-23317200 -14400 0 ART}
+ {-7588800 -10800 0 ART}
+ {128142000 -7200 1 ARST}
+ {136605600 -10800 0 ART}
+ {596948400 -7200 1 ARST}
+ {605066400 -10800 0 ART}
+ {624423600 -7200 1 ARST}
+ {636516000 -10800 0 ART}
+ {656478000 -7200 1 ARST}
+ {667965600 -14400 0 WART}
+ {687931200 -7200 0 ARST}
+ {699415200 -10800 0 ART}
+ {719377200 -7200 1 ARST}
+ {731469600 -10800 0 ART}
+ {938916000 -10800 0 ART}
+ {938919600 -10800 1 ARST}
+ {952056000 -10800 0 ART}
+ {1198983600 -7200 1 ARST}
+ {1205632800 -10800 0 ART}
+ {1224295200 -10800 0 ART}
+}
diff --git a/library/tzdata/America/Argentina/San_Juan b/library/tzdata/America/Argentina/San_Juan
new file mode 100644
index 0000000..417e234
--- /dev/null
+++ b/library/tzdata/America/Argentina/San_Juan
@@ -0,0 +1,69 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Argentina/San_Juan) {
+ {-9223372036854775808 -16444 0 LMT}
+ {-2372095556 -15408 0 CMT}
+ {-1567453392 -14400 0 ART}
+ {-1233432000 -10800 0 ARST}
+ {-1222981200 -14400 0 ART}
+ {-1205956800 -10800 1 ARST}
+ {-1194037200 -14400 0 ART}
+ {-1172865600 -10800 1 ARST}
+ {-1162501200 -14400 0 ART}
+ {-1141329600 -10800 1 ARST}
+ {-1130965200 -14400 0 ART}
+ {-1109793600 -10800 1 ARST}
+ {-1099429200 -14400 0 ART}
+ {-1078257600 -10800 1 ARST}
+ {-1067806800 -14400 0 ART}
+ {-1046635200 -10800 1 ARST}
+ {-1036270800 -14400 0 ART}
+ {-1015099200 -10800 1 ARST}
+ {-1004734800 -14400 0 ART}
+ {-983563200 -10800 1 ARST}
+ {-973198800 -14400 0 ART}
+ {-952027200 -10800 1 ARST}
+ {-941576400 -14400 0 ART}
+ {-931032000 -10800 1 ARST}
+ {-900882000 -14400 0 ART}
+ {-890337600 -10800 1 ARST}
+ {-833749200 -14400 0 ART}
+ {-827265600 -10800 1 ARST}
+ {-752274000 -14400 0 ART}
+ {-733780800 -10800 1 ARST}
+ {-197326800 -14400 0 ART}
+ {-190843200 -10800 1 ARST}
+ {-184194000 -14400 0 ART}
+ {-164491200 -10800 1 ARST}
+ {-152658000 -14400 0 ART}
+ {-132955200 -10800 1 ARST}
+ {-121122000 -14400 0 ART}
+ {-101419200 -10800 1 ARST}
+ {-86821200 -14400 0 ART}
+ {-71092800 -10800 1 ARST}
+ {-54766800 -14400 0 ART}
+ {-39038400 -10800 1 ARST}
+ {-23317200 -14400 0 ART}
+ {-7588800 -10800 0 ART}
+ {128142000 -7200 1 ARST}
+ {136605600 -10800 0 ART}
+ {596948400 -7200 1 ARST}
+ {605066400 -10800 0 ART}
+ {624423600 -7200 1 ARST}
+ {636516000 -10800 0 ART}
+ {656478000 -7200 1 ARST}
+ {667792800 -14400 0 WART}
+ {673588800 -10800 0 ART}
+ {687927600 -7200 1 ARST}
+ {699415200 -10800 0 ART}
+ {719377200 -7200 1 ARST}
+ {731469600 -10800 0 ART}
+ {938916000 -10800 0 ART}
+ {938919600 -10800 1 ARST}
+ {952056000 -10800 0 ART}
+ {1085972400 -14400 0 WART}
+ {1090728000 -10800 0 ART}
+ {1198983600 -7200 1 ARST}
+ {1205632800 -10800 0 ART}
+ {1224295200 -10800 0 ART}
+}
diff --git a/library/tzdata/America/Argentina/San_Luis b/library/tzdata/America/Argentina/San_Luis
new file mode 100644
index 0000000..bec1554
--- /dev/null
+++ b/library/tzdata/America/Argentina/San_Luis
@@ -0,0 +1,68 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Argentina/San_Luis) {
+ {-9223372036854775808 -15924 0 LMT}
+ {-2372096076 -15408 0 CMT}
+ {-1567453392 -14400 0 ART}
+ {-1233432000 -10800 0 ARST}
+ {-1222981200 -14400 0 ART}
+ {-1205956800 -10800 1 ARST}
+ {-1194037200 -14400 0 ART}
+ {-1172865600 -10800 1 ARST}
+ {-1162501200 -14400 0 ART}
+ {-1141329600 -10800 1 ARST}
+ {-1130965200 -14400 0 ART}
+ {-1109793600 -10800 1 ARST}
+ {-1099429200 -14400 0 ART}
+ {-1078257600 -10800 1 ARST}
+ {-1067806800 -14400 0 ART}
+ {-1046635200 -10800 1 ARST}
+ {-1036270800 -14400 0 ART}
+ {-1015099200 -10800 1 ARST}
+ {-1004734800 -14400 0 ART}
+ {-983563200 -10800 1 ARST}
+ {-973198800 -14400 0 ART}
+ {-952027200 -10800 1 ARST}
+ {-941576400 -14400 0 ART}
+ {-931032000 -10800 1 ARST}
+ {-900882000 -14400 0 ART}
+ {-890337600 -10800 1 ARST}
+ {-833749200 -14400 0 ART}
+ {-827265600 -10800 1 ARST}
+ {-752274000 -14400 0 ART}
+ {-733780800 -10800 1 ARST}
+ {-197326800 -14400 0 ART}
+ {-190843200 -10800 1 ARST}
+ {-184194000 -14400 0 ART}
+ {-164491200 -10800 1 ARST}
+ {-152658000 -14400 0 ART}
+ {-132955200 -10800 1 ARST}
+ {-121122000 -14400 0 ART}
+ {-101419200 -10800 1 ARST}
+ {-86821200 -14400 0 ART}
+ {-71092800 -10800 1 ARST}
+ {-54766800 -14400 0 ART}
+ {-39038400 -10800 1 ARST}
+ {-23317200 -14400 0 ART}
+ {-7588800 -10800 0 ART}
+ {128142000 -7200 1 ARST}
+ {136605600 -10800 0 ART}
+ {596948400 -7200 1 ARST}
+ {605066400 -10800 0 ART}
+ {624423600 -7200 1 ARST}
+ {631159200 -7200 1 ARST}
+ {637380000 -14400 0 WART}
+ {655963200 -10800 1 WARST}
+ {667796400 -14400 0 WART}
+ {675748800 -10800 0 ART}
+ {938919600 -10800 1 WARST}
+ {952052400 -10800 0 ART}
+ {1085972400 -14400 0 WART}
+ {1090728000 -10800 0 ART}
+ {1198983600 -7200 1 ARST}
+ {1200880800 -10800 0 WART}
+ {1205031600 -14400 0 WART}
+ {1223784000 -10800 1 WARST}
+ {1236481200 -14400 0 WART}
+ {1255233600 -10800 1 WARST}
+}
diff --git a/library/tzdata/America/Argentina/Tucuman b/library/tzdata/America/Argentina/Tucuman
new file mode 100644
index 0000000..3500986
--- /dev/null
+++ b/library/tzdata/America/Argentina/Tucuman
@@ -0,0 +1,69 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Argentina/Tucuman) {
+ {-9223372036854775808 -15652 0 LMT}
+ {-2372096348 -15408 0 CMT}
+ {-1567453392 -14400 0 ART}
+ {-1233432000 -10800 0 ARST}
+ {-1222981200 -14400 0 ART}
+ {-1205956800 -10800 1 ARST}
+ {-1194037200 -14400 0 ART}
+ {-1172865600 -10800 1 ARST}
+ {-1162501200 -14400 0 ART}
+ {-1141329600 -10800 1 ARST}
+ {-1130965200 -14400 0 ART}
+ {-1109793600 -10800 1 ARST}
+ {-1099429200 -14400 0 ART}
+ {-1078257600 -10800 1 ARST}
+ {-1067806800 -14400 0 ART}
+ {-1046635200 -10800 1 ARST}
+ {-1036270800 -14400 0 ART}
+ {-1015099200 -10800 1 ARST}
+ {-1004734800 -14400 0 ART}
+ {-983563200 -10800 1 ARST}
+ {-973198800 -14400 0 ART}
+ {-952027200 -10800 1 ARST}
+ {-941576400 -14400 0 ART}
+ {-931032000 -10800 1 ARST}
+ {-900882000 -14400 0 ART}
+ {-890337600 -10800 1 ARST}
+ {-833749200 -14400 0 ART}
+ {-827265600 -10800 1 ARST}
+ {-752274000 -14400 0 ART}
+ {-733780800 -10800 1 ARST}
+ {-197326800 -14400 0 ART}
+ {-190843200 -10800 1 ARST}
+ {-184194000 -14400 0 ART}
+ {-164491200 -10800 1 ARST}
+ {-152658000 -14400 0 ART}
+ {-132955200 -10800 1 ARST}
+ {-121122000 -14400 0 ART}
+ {-101419200 -10800 1 ARST}
+ {-86821200 -14400 0 ART}
+ {-71092800 -10800 1 ARST}
+ {-54766800 -14400 0 ART}
+ {-39038400 -10800 1 ARST}
+ {-23317200 -14400 0 ART}
+ {-7588800 -10800 0 ART}
+ {128142000 -7200 1 ARST}
+ {136605600 -10800 0 ART}
+ {596948400 -7200 1 ARST}
+ {605066400 -10800 0 ART}
+ {624423600 -7200 1 ARST}
+ {636516000 -10800 0 ART}
+ {656478000 -7200 1 ARST}
+ {667965600 -14400 0 WART}
+ {687931200 -7200 0 ARST}
+ {699415200 -10800 0 ART}
+ {719377200 -7200 1 ARST}
+ {731469600 -10800 0 ART}
+ {938916000 -10800 0 ART}
+ {938919600 -10800 1 ARST}
+ {952056000 -10800 0 ART}
+ {1086058800 -14400 0 WART}
+ {1087099200 -10800 0 ART}
+ {1198983600 -7200 1 ARST}
+ {1205632800 -10800 0 ART}
+ {1224385200 -7200 1 ARST}
+ {1237082400 -10800 0 ART}
+}
diff --git a/library/tzdata/America/Argentina/Ushuaia b/library/tzdata/America/Argentina/Ushuaia
new file mode 100644
index 0000000..4fcf92d
--- /dev/null
+++ b/library/tzdata/America/Argentina/Ushuaia
@@ -0,0 +1,68 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Argentina/Ushuaia) {
+ {-9223372036854775808 -16392 0 LMT}
+ {-2372095608 -15408 0 CMT}
+ {-1567453392 -14400 0 ART}
+ {-1233432000 -10800 0 ARST}
+ {-1222981200 -14400 0 ART}
+ {-1205956800 -10800 1 ARST}
+ {-1194037200 -14400 0 ART}
+ {-1172865600 -10800 1 ARST}
+ {-1162501200 -14400 0 ART}
+ {-1141329600 -10800 1 ARST}
+ {-1130965200 -14400 0 ART}
+ {-1109793600 -10800 1 ARST}
+ {-1099429200 -14400 0 ART}
+ {-1078257600 -10800 1 ARST}
+ {-1067806800 -14400 0 ART}
+ {-1046635200 -10800 1 ARST}
+ {-1036270800 -14400 0 ART}
+ {-1015099200 -10800 1 ARST}
+ {-1004734800 -14400 0 ART}
+ {-983563200 -10800 1 ARST}
+ {-973198800 -14400 0 ART}
+ {-952027200 -10800 1 ARST}
+ {-941576400 -14400 0 ART}
+ {-931032000 -10800 1 ARST}
+ {-900882000 -14400 0 ART}
+ {-890337600 -10800 1 ARST}
+ {-833749200 -14400 0 ART}
+ {-827265600 -10800 1 ARST}
+ {-752274000 -14400 0 ART}
+ {-733780800 -10800 1 ARST}
+ {-197326800 -14400 0 ART}
+ {-190843200 -10800 1 ARST}
+ {-184194000 -14400 0 ART}
+ {-164491200 -10800 1 ARST}
+ {-152658000 -14400 0 ART}
+ {-132955200 -10800 1 ARST}
+ {-121122000 -14400 0 ART}
+ {-101419200 -10800 1 ARST}
+ {-86821200 -14400 0 ART}
+ {-71092800 -10800 1 ARST}
+ {-54766800 -14400 0 ART}
+ {-39038400 -10800 1 ARST}
+ {-23317200 -14400 0 ART}
+ {-7588800 -10800 0 ART}
+ {128142000 -7200 1 ARST}
+ {136605600 -10800 0 ART}
+ {596948400 -7200 1 ARST}
+ {605066400 -10800 0 ART}
+ {624423600 -7200 1 ARST}
+ {636516000 -10800 0 ART}
+ {656478000 -7200 1 ARST}
+ {667965600 -10800 0 ART}
+ {687927600 -7200 1 ARST}
+ {699415200 -10800 0 ART}
+ {719377200 -7200 1 ARST}
+ {731469600 -10800 0 ART}
+ {938916000 -10800 0 ART}
+ {938919600 -10800 1 ARST}
+ {952056000 -10800 0 ART}
+ {1085886000 -14400 0 WART}
+ {1087704000 -10800 0 ART}
+ {1198983600 -7200 1 ARST}
+ {1205632800 -10800 0 ART}
+ {1224295200 -10800 0 ART}
+}
diff --git a/library/tzdata/America/Aruba b/library/tzdata/America/Aruba
new file mode 100644
index 0000000..92f182d
--- /dev/null
+++ b/library/tzdata/America/Aruba
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Aruba) {
+ {-9223372036854775808 -16824 0 LMT}
+ {-1826738376 -16200 0 ANT}
+ {-157750200 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Asuncion b/library/tzdata/America/Asuncion
new file mode 100644
index 0000000..14bbab2
--- /dev/null
+++ b/library/tzdata/America/Asuncion
@@ -0,0 +1,259 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Asuncion) {
+ {-9223372036854775808 -13840 0 LMT}
+ {-2524507760 -13840 0 AMT}
+ {-1206389360 -14400 0 PYT}
+ {86760000 -10800 0 PYT}
+ {134017200 -14400 0 PYT}
+ {162878400 -14400 0 PYT}
+ {181368000 -10800 1 PYST}
+ {194497200 -14400 0 PYT}
+ {212990400 -10800 1 PYST}
+ {226033200 -14400 0 PYT}
+ {244526400 -10800 1 PYST}
+ {257569200 -14400 0 PYT}
+ {276062400 -10800 1 PYST}
+ {291783600 -14400 0 PYT}
+ {307598400 -10800 1 PYST}
+ {323406000 -14400 0 PYT}
+ {339220800 -10800 1 PYST}
+ {354942000 -14400 0 PYT}
+ {370756800 -10800 1 PYST}
+ {386478000 -14400 0 PYT}
+ {402292800 -10800 1 PYST}
+ {418014000 -14400 0 PYT}
+ {433828800 -10800 1 PYST}
+ {449636400 -14400 0 PYT}
+ {465451200 -10800 1 PYST}
+ {481172400 -14400 0 PYT}
+ {496987200 -10800 1 PYST}
+ {512708400 -14400 0 PYT}
+ {528523200 -10800 1 PYST}
+ {544244400 -14400 0 PYT}
+ {560059200 -10800 1 PYST}
+ {575866800 -14400 0 PYT}
+ {591681600 -10800 1 PYST}
+ {607402800 -14400 0 PYT}
+ {625032000 -10800 1 PYST}
+ {638938800 -14400 0 PYT}
+ {654753600 -10800 1 PYST}
+ {670474800 -14400 0 PYT}
+ {686721600 -10800 1 PYST}
+ {699418800 -14400 0 PYT}
+ {718257600 -10800 1 PYST}
+ {733546800 -14400 0 PYT}
+ {749448000 -10800 1 PYST}
+ {762318000 -14400 0 PYT}
+ {780984000 -10800 1 PYST}
+ {793767600 -14400 0 PYT}
+ {812520000 -10800 1 PYST}
+ {825649200 -14400 0 PYT}
+ {844574400 -10800 1 PYST}
+ {856666800 -14400 0 PYT}
+ {876024000 -10800 1 PYST}
+ {888721200 -14400 0 PYT}
+ {907473600 -10800 1 PYST}
+ {920775600 -14400 0 PYT}
+ {938923200 -10800 1 PYST}
+ {952225200 -14400 0 PYT}
+ {970372800 -10800 1 PYST}
+ {983674800 -14400 0 PYT}
+ {1002427200 -10800 1 PYST}
+ {1018148400 -14400 0 PYT}
+ {1030852800 -10800 1 PYST}
+ {1049598000 -14400 0 PYT}
+ {1062907200 -10800 1 PYST}
+ {1081047600 -14400 0 PYT}
+ {1097985600 -10800 1 PYST}
+ {1110682800 -14400 0 PYT}
+ {1129435200 -10800 1 PYST}
+ {1142132400 -14400 0 PYT}
+ {1160884800 -10800 1 PYST}
+ {1173582000 -14400 0 PYT}
+ {1192939200 -10800 1 PYST}
+ {1205031600 -14400 0 PYT}
+ {1224388800 -10800 1 PYST}
+ {1236481200 -14400 0 PYT}
+ {1255838400 -10800 1 PYST}
+ {1270954800 -14400 0 PYT}
+ {1286078400 -10800 1 PYST}
+ {1302404400 -14400 0 PYT}
+ {1317528000 -10800 1 PYST}
+ {1333854000 -14400 0 PYT}
+ {1349582400 -10800 1 PYST}
+ {1365908400 -14400 0 PYT}
+ {1381032000 -10800 1 PYST}
+ {1397358000 -14400 0 PYT}
+ {1412481600 -10800 1 PYST}
+ {1428807600 -14400 0 PYT}
+ {1443931200 -10800 1 PYST}
+ {1460257200 -14400 0 PYT}
+ {1475380800 -10800 1 PYST}
+ {1491706800 -14400 0 PYT}
+ {1506830400 -10800 1 PYST}
+ {1523156400 -14400 0 PYT}
+ {1538884800 -10800 1 PYST}
+ {1555210800 -14400 0 PYT}
+ {1570334400 -10800 1 PYST}
+ {1586660400 -14400 0 PYT}
+ {1601784000 -10800 1 PYST}
+ {1618110000 -14400 0 PYT}
+ {1633233600 -10800 1 PYST}
+ {1649559600 -14400 0 PYT}
+ {1664683200 -10800 1 PYST}
+ {1681009200 -14400 0 PYT}
+ {1696132800 -10800 1 PYST}
+ {1713063600 -14400 0 PYT}
+ {1728187200 -10800 1 PYST}
+ {1744513200 -14400 0 PYT}
+ {1759636800 -10800 1 PYST}
+ {1775962800 -14400 0 PYT}
+ {1791086400 -10800 1 PYST}
+ {1807412400 -14400 0 PYT}
+ {1822536000 -10800 1 PYST}
+ {1838862000 -14400 0 PYT}
+ {1853985600 -10800 1 PYST}
+ {1870311600 -14400 0 PYT}
+ {1886040000 -10800 1 PYST}
+ {1902366000 -14400 0 PYT}
+ {1917489600 -10800 1 PYST}
+ {1933815600 -14400 0 PYT}
+ {1948939200 -10800 1 PYST}
+ {1965265200 -14400 0 PYT}
+ {1980388800 -10800 1 PYST}
+ {1996714800 -14400 0 PYT}
+ {2011838400 -10800 1 PYST}
+ {2028164400 -14400 0 PYT}
+ {2043288000 -10800 1 PYST}
+ {2059614000 -14400 0 PYT}
+ {2075342400 -10800 1 PYST}
+ {2091668400 -14400 0 PYT}
+ {2106792000 -10800 1 PYST}
+ {2123118000 -14400 0 PYT}
+ {2138241600 -10800 1 PYST}
+ {2154567600 -14400 0 PYT}
+ {2169691200 -10800 1 PYST}
+ {2186017200 -14400 0 PYT}
+ {2201140800 -10800 1 PYST}
+ {2217466800 -14400 0 PYT}
+ {2233195200 -10800 1 PYST}
+ {2249521200 -14400 0 PYT}
+ {2264644800 -10800 1 PYST}
+ {2280970800 -14400 0 PYT}
+ {2296094400 -10800 1 PYST}
+ {2312420400 -14400 0 PYT}
+ {2327544000 -10800 1 PYST}
+ {2343870000 -14400 0 PYT}
+ {2358993600 -10800 1 PYST}
+ {2375319600 -14400 0 PYT}
+ {2390443200 -10800 1 PYST}
+ {2406769200 -14400 0 PYT}
+ {2422497600 -10800 1 PYST}
+ {2438823600 -14400 0 PYT}
+ {2453947200 -10800 1 PYST}
+ {2470273200 -14400 0 PYT}
+ {2485396800 -10800 1 PYST}
+ {2501722800 -14400 0 PYT}
+ {2516846400 -10800 1 PYST}
+ {2533172400 -14400 0 PYT}
+ {2548296000 -10800 1 PYST}
+ {2564622000 -14400 0 PYT}
+ {2579745600 -10800 1 PYST}
+ {2596676400 -14400 0 PYT}
+ {2611800000 -10800 1 PYST}
+ {2628126000 -14400 0 PYT}
+ {2643249600 -10800 1 PYST}
+ {2659575600 -14400 0 PYT}
+ {2674699200 -10800 1 PYST}
+ {2691025200 -14400 0 PYT}
+ {2706148800 -10800 1 PYST}
+ {2722474800 -14400 0 PYT}
+ {2737598400 -10800 1 PYST}
+ {2753924400 -14400 0 PYT}
+ {2769652800 -10800 1 PYST}
+ {2785978800 -14400 0 PYT}
+ {2801102400 -10800 1 PYST}
+ {2817428400 -14400 0 PYT}
+ {2832552000 -10800 1 PYST}
+ {2848878000 -14400 0 PYT}
+ {2864001600 -10800 1 PYST}
+ {2880327600 -14400 0 PYT}
+ {2895451200 -10800 1 PYST}
+ {2911777200 -14400 0 PYT}
+ {2926900800 -10800 1 PYST}
+ {2943226800 -14400 0 PYT}
+ {2958955200 -10800 1 PYST}
+ {2975281200 -14400 0 PYT}
+ {2990404800 -10800 1 PYST}
+ {3006730800 -14400 0 PYT}
+ {3021854400 -10800 1 PYST}
+ {3038180400 -14400 0 PYT}
+ {3053304000 -10800 1 PYST}
+ {3069630000 -14400 0 PYT}
+ {3084753600 -10800 1 PYST}
+ {3101079600 -14400 0 PYT}
+ {3116808000 -10800 1 PYST}
+ {3133134000 -14400 0 PYT}
+ {3148257600 -10800 1 PYST}
+ {3164583600 -14400 0 PYT}
+ {3179707200 -10800 1 PYST}
+ {3196033200 -14400 0 PYT}
+ {3211156800 -10800 1 PYST}
+ {3227482800 -14400 0 PYT}
+ {3242606400 -10800 1 PYST}
+ {3258932400 -14400 0 PYT}
+ {3274056000 -10800 1 PYST}
+ {3290382000 -14400 0 PYT}
+ {3306110400 -10800 1 PYST}
+ {3322436400 -14400 0 PYT}
+ {3337560000 -10800 1 PYST}
+ {3353886000 -14400 0 PYT}
+ {3369009600 -10800 1 PYST}
+ {3385335600 -14400 0 PYT}
+ {3400459200 -10800 1 PYST}
+ {3416785200 -14400 0 PYT}
+ {3431908800 -10800 1 PYST}
+ {3448234800 -14400 0 PYT}
+ {3463358400 -10800 1 PYST}
+ {3480289200 -14400 0 PYT}
+ {3495412800 -10800 1 PYST}
+ {3511738800 -14400 0 PYT}
+ {3526862400 -10800 1 PYST}
+ {3543188400 -14400 0 PYT}
+ {3558312000 -10800 1 PYST}
+ {3574638000 -14400 0 PYT}
+ {3589761600 -10800 1 PYST}
+ {3606087600 -14400 0 PYT}
+ {3621211200 -10800 1 PYST}
+ {3637537200 -14400 0 PYT}
+ {3653265600 -10800 1 PYST}
+ {3669591600 -14400 0 PYT}
+ {3684715200 -10800 1 PYST}
+ {3701041200 -14400 0 PYT}
+ {3716164800 -10800 1 PYST}
+ {3732490800 -14400 0 PYT}
+ {3747614400 -10800 1 PYST}
+ {3763940400 -14400 0 PYT}
+ {3779064000 -10800 1 PYST}
+ {3795390000 -14400 0 PYT}
+ {3810513600 -10800 1 PYST}
+ {3826839600 -14400 0 PYT}
+ {3842568000 -10800 1 PYST}
+ {3858894000 -14400 0 PYT}
+ {3874017600 -10800 1 PYST}
+ {3890343600 -14400 0 PYT}
+ {3905467200 -10800 1 PYST}
+ {3921793200 -14400 0 PYT}
+ {3936916800 -10800 1 PYST}
+ {3953242800 -14400 0 PYT}
+ {3968366400 -10800 1 PYST}
+ {3984692400 -14400 0 PYT}
+ {4000420800 -10800 1 PYST}
+ {4016746800 -14400 0 PYT}
+ {4031870400 -10800 1 PYST}
+ {4048196400 -14400 0 PYT}
+ {4063320000 -10800 1 PYST}
+ {4079646000 -14400 0 PYT}
+ {4094769600 -10800 1 PYST}
+}
diff --git a/library/tzdata/America/Atikokan b/library/tzdata/America/Atikokan
new file mode 100755
index 0000000..ca0ac1c
--- /dev/null
+++ b/library/tzdata/America/Atikokan
@@ -0,0 +1,12 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Atikokan) {
+ {-9223372036854775808 -21988 0 LMT}
+ {-2366733212 -21600 0 CST}
+ {-1632067200 -18000 1 CDT}
+ {-1614790800 -21600 0 CST}
+ {-923248800 -18000 1 CDT}
+ {-880214400 -18000 0 CWT}
+ {-769395600 -18000 1 CPT}
+ {-765388800 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Atka b/library/tzdata/America/Atka
new file mode 100644
index 0000000..8da3302
--- /dev/null
+++ b/library/tzdata/America/Atka
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Adak)]} {
+ LoadTimeZoneFile America/Adak
+}
+set TZData(:America/Atka) $TZData(:America/Adak)
diff --git a/library/tzdata/America/Bahia b/library/tzdata/America/Bahia
new file mode 100644
index 0000000..b10a939
--- /dev/null
+++ b/library/tzdata/America/Bahia
@@ -0,0 +1,65 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Bahia) {
+ {-9223372036854775808 -9244 0 LMT}
+ {-1767216356 -10800 0 BRT}
+ {-1206957600 -7200 1 BRST}
+ {-1191362400 -10800 0 BRT}
+ {-1175374800 -7200 1 BRST}
+ {-1159826400 -10800 0 BRT}
+ {-633819600 -7200 1 BRST}
+ {-622069200 -10800 0 BRT}
+ {-602283600 -7200 1 BRST}
+ {-591832800 -10800 0 BRT}
+ {-570747600 -7200 1 BRST}
+ {-560210400 -10800 0 BRT}
+ {-539125200 -7200 1 BRST}
+ {-531352800 -10800 0 BRT}
+ {-191365200 -7200 1 BRST}
+ {-184197600 -10800 0 BRT}
+ {-155163600 -7200 1 BRST}
+ {-150069600 -10800 0 BRT}
+ {-128898000 -7200 1 BRST}
+ {-121125600 -10800 0 BRT}
+ {-99954000 -7200 1 BRST}
+ {-89589600 -10800 0 BRT}
+ {-68418000 -7200 1 BRST}
+ {-57967200 -10800 0 BRT}
+ {499748400 -7200 1 BRST}
+ {511236000 -10800 0 BRT}
+ {530593200 -7200 1 BRST}
+ {540266400 -10800 0 BRT}
+ {562129200 -7200 1 BRST}
+ {571197600 -10800 0 BRT}
+ {592974000 -7200 1 BRST}
+ {602042400 -10800 0 BRT}
+ {624423600 -7200 1 BRST}
+ {634701600 -10800 0 BRT}
+ {656478000 -7200 1 BRST}
+ {666756000 -10800 0 BRT}
+ {687927600 -7200 1 BRST}
+ {697600800 -10800 0 BRT}
+ {719982000 -7200 1 BRST}
+ {728445600 -10800 0 BRT}
+ {750826800 -7200 1 BRST}
+ {761709600 -10800 0 BRT}
+ {782276400 -7200 1 BRST}
+ {793159200 -10800 0 BRT}
+ {813726000 -7200 1 BRST}
+ {824004000 -10800 0 BRT}
+ {844570800 -7200 1 BRST}
+ {856058400 -10800 0 BRT}
+ {876106800 -7200 1 BRST}
+ {888717600 -10800 0 BRT}
+ {908074800 -7200 1 BRST}
+ {919562400 -10800 0 BRT}
+ {938919600 -7200 1 BRST}
+ {951616800 -10800 0 BRT}
+ {970974000 -7200 1 BRST}
+ {982461600 -10800 0 BRT}
+ {1003028400 -7200 1 BRST}
+ {1013911200 -10800 0 BRT}
+ {1036292400 -7200 1 BRST}
+ {1045360800 -10800 0 BRT}
+ {1064368800 -10800 0 BRT}
+}
diff --git a/library/tzdata/America/Bahia_Banderas b/library/tzdata/America/Bahia_Banderas
new file mode 100644
index 0000000..8c40a0e
--- /dev/null
+++ b/library/tzdata/America/Bahia_Banderas
@@ -0,0 +1,222 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Bahia_Banderas) {
+ {-9223372036854775808 -25260 0 LMT}
+ {-1514739600 -25200 0 MST}
+ {-1343066400 -21600 0 CST}
+ {-1234807200 -25200 0 MST}
+ {-1220292000 -21600 0 CST}
+ {-1207159200 -25200 0 MST}
+ {-1191344400 -21600 0 CST}
+ {-873828000 -25200 0 MST}
+ {-661539600 -28800 0 PST}
+ {28800 -25200 0 MST}
+ {828867600 -21600 1 MDT}
+ {846403200 -25200 0 MST}
+ {860317200 -21600 1 MDT}
+ {877852800 -25200 0 MST}
+ {891766800 -21600 1 MDT}
+ {909302400 -25200 0 MST}
+ {923216400 -21600 1 MDT}
+ {941356800 -25200 0 MST}
+ {954666000 -21600 1 MDT}
+ {972806400 -25200 0 MST}
+ {989139600 -21600 1 MDT}
+ {1001836800 -25200 0 MST}
+ {1018170000 -21600 1 MDT}
+ {1035705600 -25200 0 MST}
+ {1049619600 -21600 1 MDT}
+ {1067155200 -25200 0 MST}
+ {1081069200 -21600 1 MDT}
+ {1099209600 -25200 0 MST}
+ {1112518800 -21600 1 MDT}
+ {1130659200 -25200 0 MST}
+ {1143968400 -21600 1 MDT}
+ {1162108800 -25200 0 MST}
+ {1175418000 -21600 1 MDT}
+ {1193558400 -25200 0 MST}
+ {1207472400 -21600 1 MDT}
+ {1225008000 -25200 0 MST}
+ {1238922000 -21600 1 MDT}
+ {1256457600 -25200 0 MST}
+ {1270371600 -18000 0 CDT}
+ {1288508400 -21600 0 CST}
+ {1301817600 -18000 1 CDT}
+ {1319958000 -21600 0 CST}
+ {1333267200 -18000 1 CDT}
+ {1351407600 -21600 0 CST}
+ {1365321600 -18000 1 CDT}
+ {1382857200 -21600 0 CST}
+ {1396771200 -18000 1 CDT}
+ {1414306800 -21600 0 CST}
+ {1428220800 -18000 1 CDT}
+ {1445756400 -21600 0 CST}
+ {1459670400 -18000 1 CDT}
+ {1477810800 -21600 0 CST}
+ {1491120000 -18000 1 CDT}
+ {1509260400 -21600 0 CST}
+ {1522569600 -18000 1 CDT}
+ {1540710000 -21600 0 CST}
+ {1554624000 -18000 1 CDT}
+ {1572159600 -21600 0 CST}
+ {1586073600 -18000 1 CDT}
+ {1603609200 -21600 0 CST}
+ {1617523200 -18000 1 CDT}
+ {1635663600 -21600 0 CST}
+ {1648972800 -18000 1 CDT}
+ {1667113200 -21600 0 CST}
+ {1680422400 -18000 1 CDT}
+ {1698562800 -21600 0 CST}
+ {1712476800 -18000 1 CDT}
+ {1730012400 -21600 0 CST}
+ {1743926400 -18000 1 CDT}
+ {1761462000 -21600 0 CST}
+ {1775376000 -18000 1 CDT}
+ {1792911600 -21600 0 CST}
+ {1806825600 -18000 1 CDT}
+ {1824966000 -21600 0 CST}
+ {1838275200 -18000 1 CDT}
+ {1856415600 -21600 0 CST}
+ {1869724800 -18000 1 CDT}
+ {1887865200 -21600 0 CST}
+ {1901779200 -18000 1 CDT}
+ {1919314800 -21600 0 CST}
+ {1933228800 -18000 1 CDT}
+ {1950764400 -21600 0 CST}
+ {1964678400 -18000 1 CDT}
+ {1982818800 -21600 0 CST}
+ {1996128000 -18000 1 CDT}
+ {2014268400 -21600 0 CST}
+ {2027577600 -18000 1 CDT}
+ {2045718000 -21600 0 CST}
+ {2059027200 -18000 1 CDT}
+ {2077167600 -21600 0 CST}
+ {2091081600 -18000 1 CDT}
+ {2108617200 -21600 0 CST}
+ {2122531200 -18000 1 CDT}
+ {2140066800 -21600 0 CST}
+ {2153980800 -18000 1 CDT}
+ {2172121200 -21600 0 CST}
+ {2185430400 -18000 1 CDT}
+ {2203570800 -21600 0 CST}
+ {2216880000 -18000 1 CDT}
+ {2235020400 -21600 0 CST}
+ {2248934400 -18000 1 CDT}
+ {2266470000 -21600 0 CST}
+ {2280384000 -18000 1 CDT}
+ {2297919600 -21600 0 CST}
+ {2311833600 -18000 1 CDT}
+ {2329369200 -21600 0 CST}
+ {2343283200 -18000 1 CDT}
+ {2361423600 -21600 0 CST}
+ {2374732800 -18000 1 CDT}
+ {2392873200 -21600 0 CST}
+ {2406182400 -18000 1 CDT}
+ {2424322800 -21600 0 CST}
+ {2438236800 -18000 1 CDT}
+ {2455772400 -21600 0 CST}
+ {2469686400 -18000 1 CDT}
+ {2487222000 -21600 0 CST}
+ {2501136000 -18000 1 CDT}
+ {2519276400 -21600 0 CST}
+ {2532585600 -18000 1 CDT}
+ {2550726000 -21600 0 CST}
+ {2564035200 -18000 1 CDT}
+ {2582175600 -21600 0 CST}
+ {2596089600 -18000 1 CDT}
+ {2613625200 -21600 0 CST}
+ {2627539200 -18000 1 CDT}
+ {2645074800 -21600 0 CST}
+ {2658988800 -18000 1 CDT}
+ {2676524400 -21600 0 CST}
+ {2690438400 -18000 1 CDT}
+ {2708578800 -21600 0 CST}
+ {2721888000 -18000 1 CDT}
+ {2740028400 -21600 0 CST}
+ {2753337600 -18000 1 CDT}
+ {2771478000 -21600 0 CST}
+ {2785392000 -18000 1 CDT}
+ {2802927600 -21600 0 CST}
+ {2816841600 -18000 1 CDT}
+ {2834377200 -21600 0 CST}
+ {2848291200 -18000 1 CDT}
+ {2866431600 -21600 0 CST}
+ {2879740800 -18000 1 CDT}
+ {2897881200 -21600 0 CST}
+ {2911190400 -18000 1 CDT}
+ {2929330800 -21600 0 CST}
+ {2942640000 -18000 1 CDT}
+ {2960780400 -21600 0 CST}
+ {2974694400 -18000 1 CDT}
+ {2992230000 -21600 0 CST}
+ {3006144000 -18000 1 CDT}
+ {3023679600 -21600 0 CST}
+ {3037593600 -18000 1 CDT}
+ {3055734000 -21600 0 CST}
+ {3069043200 -18000 1 CDT}
+ {3087183600 -21600 0 CST}
+ {3100492800 -18000 1 CDT}
+ {3118633200 -21600 0 CST}
+ {3132547200 -18000 1 CDT}
+ {3150082800 -21600 0 CST}
+ {3163996800 -18000 1 CDT}
+ {3181532400 -21600 0 CST}
+ {3195446400 -18000 1 CDT}
+ {3212982000 -21600 0 CST}
+ {3226896000 -18000 1 CDT}
+ {3245036400 -21600 0 CST}
+ {3258345600 -18000 1 CDT}
+ {3276486000 -21600 0 CST}
+ {3289795200 -18000 1 CDT}
+ {3307935600 -21600 0 CST}
+ {3321849600 -18000 1 CDT}
+ {3339385200 -21600 0 CST}
+ {3353299200 -18000 1 CDT}
+ {3370834800 -21600 0 CST}
+ {3384748800 -18000 1 CDT}
+ {3402889200 -21600 0 CST}
+ {3416198400 -18000 1 CDT}
+ {3434338800 -21600 0 CST}
+ {3447648000 -18000 1 CDT}
+ {3465788400 -21600 0 CST}
+ {3479702400 -18000 1 CDT}
+ {3497238000 -21600 0 CST}
+ {3511152000 -18000 1 CDT}
+ {3528687600 -21600 0 CST}
+ {3542601600 -18000 1 CDT}
+ {3560137200 -21600 0 CST}
+ {3574051200 -18000 1 CDT}
+ {3592191600 -21600 0 CST}
+ {3605500800 -18000 1 CDT}
+ {3623641200 -21600 0 CST}
+ {3636950400 -18000 1 CDT}
+ {3655090800 -21600 0 CST}
+ {3669004800 -18000 1 CDT}
+ {3686540400 -21600 0 CST}
+ {3700454400 -18000 1 CDT}
+ {3717990000 -21600 0 CST}
+ {3731904000 -18000 1 CDT}
+ {3750044400 -21600 0 CST}
+ {3763353600 -18000 1 CDT}
+ {3781494000 -21600 0 CST}
+ {3794803200 -18000 1 CDT}
+ {3812943600 -21600 0 CST}
+ {3826252800 -18000 1 CDT}
+ {3844393200 -21600 0 CST}
+ {3858307200 -18000 1 CDT}
+ {3875842800 -21600 0 CST}
+ {3889756800 -18000 1 CDT}
+ {3907292400 -21600 0 CST}
+ {3921206400 -18000 1 CDT}
+ {3939346800 -21600 0 CST}
+ {3952656000 -18000 1 CDT}
+ {3970796400 -21600 0 CST}
+ {3984105600 -18000 1 CDT}
+ {4002246000 -21600 0 CST}
+ {4016160000 -18000 1 CDT}
+ {4033695600 -21600 0 CST}
+ {4047609600 -18000 1 CDT}
+ {4065145200 -21600 0 CST}
+ {4079059200 -18000 1 CDT}
+ {4096594800 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Barbados b/library/tzdata/America/Barbados
new file mode 100644
index 0000000..5c06408
--- /dev/null
+++ b/library/tzdata/America/Barbados
@@ -0,0 +1,15 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Barbados) {
+ {-9223372036854775808 -14308 0 LMT}
+ {-1451678492 -14308 0 BMT}
+ {-1199217692 -14400 0 AST}
+ {234943200 -10800 1 ADT}
+ {244616400 -14400 0 AST}
+ {261554400 -10800 1 ADT}
+ {276066000 -14400 0 AST}
+ {293004000 -10800 1 ADT}
+ {307515600 -14400 0 AST}
+ {325058400 -10800 1 ADT}
+ {338706000 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Belem b/library/tzdata/America/Belem
new file mode 100644
index 0000000..ed92fd1
--- /dev/null
+++ b/library/tzdata/America/Belem
@@ -0,0 +1,35 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Belem) {
+ {-9223372036854775808 -11636 0 LMT}
+ {-1767213964 -10800 0 BRT}
+ {-1206957600 -7200 1 BRST}
+ {-1191362400 -10800 0 BRT}
+ {-1175374800 -7200 1 BRST}
+ {-1159826400 -10800 0 BRT}
+ {-633819600 -7200 1 BRST}
+ {-622069200 -10800 0 BRT}
+ {-602283600 -7200 1 BRST}
+ {-591832800 -10800 0 BRT}
+ {-570747600 -7200 1 BRST}
+ {-560210400 -10800 0 BRT}
+ {-539125200 -7200 1 BRST}
+ {-531352800 -10800 0 BRT}
+ {-191365200 -7200 1 BRST}
+ {-184197600 -10800 0 BRT}
+ {-155163600 -7200 1 BRST}
+ {-150069600 -10800 0 BRT}
+ {-128898000 -7200 1 BRST}
+ {-121125600 -10800 0 BRT}
+ {-99954000 -7200 1 BRST}
+ {-89589600 -10800 0 BRT}
+ {-68418000 -7200 1 BRST}
+ {-57967200 -10800 0 BRT}
+ {499748400 -7200 1 BRST}
+ {511236000 -10800 0 BRT}
+ {530593200 -7200 1 BRST}
+ {540266400 -10800 0 BRT}
+ {562129200 -7200 1 BRST}
+ {571197600 -10800 0 BRT}
+ {590032800 -10800 0 BRT}
+}
diff --git a/library/tzdata/America/Belize b/library/tzdata/America/Belize
new file mode 100644
index 0000000..547fd72
--- /dev/null
+++ b/library/tzdata/America/Belize
@@ -0,0 +1,60 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Belize) {
+ {-9223372036854775808 -21168 0 LMT}
+ {-1822500432 -21600 0 CST}
+ {-1616954400 -19800 1 CHDT}
+ {-1606069800 -21600 0 CST}
+ {-1585504800 -19800 1 CHDT}
+ {-1574015400 -21600 0 CST}
+ {-1554055200 -19800 1 CHDT}
+ {-1542565800 -21600 0 CST}
+ {-1522605600 -19800 1 CHDT}
+ {-1511116200 -21600 0 CST}
+ {-1490551200 -19800 1 CHDT}
+ {-1479666600 -21600 0 CST}
+ {-1459101600 -19800 1 CHDT}
+ {-1448217000 -21600 0 CST}
+ {-1427652000 -19800 1 CHDT}
+ {-1416162600 -21600 0 CST}
+ {-1396202400 -19800 1 CHDT}
+ {-1384713000 -21600 0 CST}
+ {-1364752800 -19800 1 CHDT}
+ {-1353263400 -21600 0 CST}
+ {-1333303200 -19800 1 CHDT}
+ {-1321813800 -21600 0 CST}
+ {-1301248800 -19800 1 CHDT}
+ {-1290364200 -21600 0 CST}
+ {-1269799200 -19800 1 CHDT}
+ {-1258914600 -21600 0 CST}
+ {-1238349600 -19800 1 CHDT}
+ {-1226860200 -21600 0 CST}
+ {-1206900000 -19800 1 CHDT}
+ {-1195410600 -21600 0 CST}
+ {-1175450400 -19800 1 CHDT}
+ {-1163961000 -21600 0 CST}
+ {-1143396000 -19800 1 CHDT}
+ {-1132511400 -21600 0 CST}
+ {-1111946400 -19800 1 CHDT}
+ {-1101061800 -21600 0 CST}
+ {-1080496800 -19800 1 CHDT}
+ {-1069612200 -21600 0 CST}
+ {-1049047200 -19800 1 CHDT}
+ {-1037557800 -21600 0 CST}
+ {-1017597600 -19800 1 CHDT}
+ {-1006108200 -21600 0 CST}
+ {-986148000 -19800 1 CHDT}
+ {-974658600 -21600 0 CST}
+ {-954093600 -19800 1 CHDT}
+ {-943209000 -21600 0 CST}
+ {-922644000 -19800 1 CHDT}
+ {-911759400 -21600 0 CST}
+ {-891194400 -19800 1 CHDT}
+ {-879705000 -21600 0 CST}
+ {-859744800 -19800 1 CHDT}
+ {-848255400 -21600 0 CST}
+ {123919200 -18000 1 CDT}
+ {129618000 -21600 0 CST}
+ {409039200 -18000 1 CDT}
+ {413874000 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Blanc-Sablon b/library/tzdata/America/Blanc-Sablon
new file mode 100755
index 0000000..47f161a
--- /dev/null
+++ b/library/tzdata/America/Blanc-Sablon
@@ -0,0 +1,12 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Blanc-Sablon) {
+ {-9223372036854775808 -13708 0 LMT}
+ {-2713896692 -14400 0 AST}
+ {-1632074400 -10800 1 ADT}
+ {-1614798000 -14400 0 AST}
+ {-880221600 -10800 1 AWT}
+ {-769395600 -10800 1 APT}
+ {-765399600 -14400 0 AST}
+ {14400 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Boa_Vista b/library/tzdata/America/Boa_Vista
new file mode 100644
index 0000000..c85bc27
--- /dev/null
+++ b/library/tzdata/America/Boa_Vista
@@ -0,0 +1,40 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Boa_Vista) {
+ {-9223372036854775808 -14560 0 LMT}
+ {-1767211040 -14400 0 AMT}
+ {-1206954000 -10800 1 AMST}
+ {-1191358800 -14400 0 AMT}
+ {-1175371200 -10800 1 AMST}
+ {-1159822800 -14400 0 AMT}
+ {-633816000 -10800 1 AMST}
+ {-622065600 -14400 0 AMT}
+ {-602280000 -10800 1 AMST}
+ {-591829200 -14400 0 AMT}
+ {-570744000 -10800 1 AMST}
+ {-560206800 -14400 0 AMT}
+ {-539121600 -10800 1 AMST}
+ {-531349200 -14400 0 AMT}
+ {-191361600 -10800 1 AMST}
+ {-184194000 -14400 0 AMT}
+ {-155160000 -10800 1 AMST}
+ {-150066000 -14400 0 AMT}
+ {-128894400 -10800 1 AMST}
+ {-121122000 -14400 0 AMT}
+ {-99950400 -10800 1 AMST}
+ {-89586000 -14400 0 AMT}
+ {-68414400 -10800 1 AMST}
+ {-57963600 -14400 0 AMT}
+ {499752000 -10800 1 AMST}
+ {511239600 -14400 0 AMT}
+ {530596800 -10800 1 AMST}
+ {540270000 -14400 0 AMT}
+ {562132800 -10800 1 AMST}
+ {571201200 -14400 0 AMT}
+ {590036400 -14400 0 AMT}
+ {938664000 -14400 0 AMT}
+ {938923200 -10800 1 AMST}
+ {951620400 -14400 0 AMT}
+ {970977600 -10800 1 AMST}
+ {971578800 -14400 0 AMT}
+}
diff --git a/library/tzdata/America/Bogota b/library/tzdata/America/Bogota
new file mode 100644
index 0000000..f727d17
--- /dev/null
+++ b/library/tzdata/America/Bogota
@@ -0,0 +1,9 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Bogota) {
+ {-9223372036854775808 -17780 0 LMT}
+ {-2707671820 -17780 0 BMT}
+ {-1739041420 -18000 0 COT}
+ {704869200 -14400 1 COST}
+ {733896000 -18000 0 COT}
+}
diff --git a/library/tzdata/America/Boise b/library/tzdata/America/Boise
new file mode 100644
index 0000000..62b22a0
--- /dev/null
+++ b/library/tzdata/America/Boise
@@ -0,0 +1,281 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Boise) {
+ {-9223372036854775808 -27889 0 LMT}
+ {-2717640000 -28800 0 PST}
+ {-1633269600 -25200 1 PDT}
+ {-1615129200 -28800 0 PST}
+ {-1601820000 -25200 1 PDT}
+ {-1583679600 -28800 0 PST}
+ {-1471788000 -25200 0 MST}
+ {-880210800 -21600 1 MWT}
+ {-769395600 -21600 1 MPT}
+ {-765388800 -25200 0 MST}
+ {-84380400 -21600 1 MDT}
+ {-68659200 -25200 0 MST}
+ {-52930800 -21600 1 MDT}
+ {-37209600 -25200 0 MST}
+ {-21481200 -21600 1 MDT}
+ {-5760000 -25200 0 MST}
+ {9968400 -21600 1 MDT}
+ {25689600 -25200 0 MST}
+ {41418000 -21600 1 MDT}
+ {57744000 -25200 0 MST}
+ {73472400 -21600 1 MDT}
+ {89193600 -25200 0 MST}
+ {104922000 -21600 1 MDT}
+ {120643200 -25200 0 MST}
+ {126255600 -25200 0 MST}
+ {129114000 -21600 0 MDT}
+ {152092800 -25200 0 MST}
+ {162378000 -21600 1 MDT}
+ {183542400 -25200 0 MST}
+ {199270800 -21600 1 MDT}
+ {215596800 -25200 0 MST}
+ {230720400 -21600 1 MDT}
+ {247046400 -25200 0 MST}
+ {262774800 -21600 1 MDT}
+ {278496000 -25200 0 MST}
+ {294224400 -21600 1 MDT}
+ {309945600 -25200 0 MST}
+ {325674000 -21600 1 MDT}
+ {341395200 -25200 0 MST}
+ {357123600 -21600 1 MDT}
+ {372844800 -25200 0 MST}
+ {388573200 -21600 1 MDT}
+ {404899200 -25200 0 MST}
+ {420022800 -21600 1 MDT}
+ {436348800 -25200 0 MST}
+ {452077200 -21600 1 MDT}
+ {467798400 -25200 0 MST}
+ {483526800 -21600 1 MDT}
+ {499248000 -25200 0 MST}
+ {514976400 -21600 1 MDT}
+ {530697600 -25200 0 MST}
+ {544611600 -21600 1 MDT}
+ {562147200 -25200 0 MST}
+ {576061200 -21600 1 MDT}
+ {594201600 -25200 0 MST}
+ {607510800 -21600 1 MDT}
+ {625651200 -25200 0 MST}
+ {638960400 -21600 1 MDT}
+ {657100800 -25200 0 MST}
+ {671014800 -21600 1 MDT}
+ {688550400 -25200 0 MST}
+ {702464400 -21600 1 MDT}
+ {720000000 -25200 0 MST}
+ {733914000 -21600 1 MDT}
+ {752054400 -25200 0 MST}
+ {765363600 -21600 1 MDT}
+ {783504000 -25200 0 MST}
+ {796813200 -21600 1 MDT}
+ {814953600 -25200 0 MST}
+ {828867600 -21600 1 MDT}
+ {846403200 -25200 0 MST}
+ {860317200 -21600 1 MDT}
+ {877852800 -25200 0 MST}
+ {891766800 -21600 1 MDT}
+ {909302400 -25200 0 MST}
+ {923216400 -21600 1 MDT}
+ {941356800 -25200 0 MST}
+ {954666000 -21600 1 MDT}
+ {972806400 -25200 0 MST}
+ {986115600 -21600 1 MDT}
+ {1004256000 -25200 0 MST}
+ {1018170000 -21600 1 MDT}
+ {1035705600 -25200 0 MST}
+ {1049619600 -21600 1 MDT}
+ {1067155200 -25200 0 MST}
+ {1081069200 -21600 1 MDT}
+ {1099209600 -25200 0 MST}
+ {1112518800 -21600 1 MDT}
+ {1130659200 -25200 0 MST}
+ {1143968400 -21600 1 MDT}
+ {1162108800 -25200 0 MST}
+ {1173603600 -21600 1 MDT}
+ {1194163200 -25200 0 MST}
+ {1205053200 -21600 1 MDT}
+ {1225612800 -25200 0 MST}
+ {1236502800 -21600 1 MDT}
+ {1257062400 -25200 0 MST}
+ {1268557200 -21600 1 MDT}
+ {1289116800 -25200 0 MST}
+ {1300006800 -21600 1 MDT}
+ {1320566400 -25200 0 MST}
+ {1331456400 -21600 1 MDT}
+ {1352016000 -25200 0 MST}
+ {1362906000 -21600 1 MDT}
+ {1383465600 -25200 0 MST}
+ {1394355600 -21600 1 MDT}
+ {1414915200 -25200 0 MST}
+ {1425805200 -21600 1 MDT}
+ {1446364800 -25200 0 MST}
+ {1457859600 -21600 1 MDT}
+ {1478419200 -25200 0 MST}
+ {1489309200 -21600 1 MDT}
+ {1509868800 -25200 0 MST}
+ {1520758800 -21600 1 MDT}
+ {1541318400 -25200 0 MST}
+ {1552208400 -21600 1 MDT}
+ {1572768000 -25200 0 MST}
+ {1583658000 -21600 1 MDT}
+ {1604217600 -25200 0 MST}
+ {1615712400 -21600 1 MDT}
+ {1636272000 -25200 0 MST}
+ {1647162000 -21600 1 MDT}
+ {1667721600 -25200 0 MST}
+ {1678611600 -21600 1 MDT}
+ {1699171200 -25200 0 MST}
+ {1710061200 -21600 1 MDT}
+ {1730620800 -25200 0 MST}
+ {1741510800 -21600 1 MDT}
+ {1762070400 -25200 0 MST}
+ {1772960400 -21600 1 MDT}
+ {1793520000 -25200 0 MST}
+ {1805014800 -21600 1 MDT}
+ {1825574400 -25200 0 MST}
+ {1836464400 -21600 1 MDT}
+ {1857024000 -25200 0 MST}
+ {1867914000 -21600 1 MDT}
+ {1888473600 -25200 0 MST}
+ {1899363600 -21600 1 MDT}
+ {1919923200 -25200 0 MST}
+ {1930813200 -21600 1 MDT}
+ {1951372800 -25200 0 MST}
+ {1962867600 -21600 1 MDT}
+ {1983427200 -25200 0 MST}
+ {1994317200 -21600 1 MDT}
+ {2014876800 -25200 0 MST}
+ {2025766800 -21600 1 MDT}
+ {2046326400 -25200 0 MST}
+ {2057216400 -21600 1 MDT}
+ {2077776000 -25200 0 MST}
+ {2088666000 -21600 1 MDT}
+ {2109225600 -25200 0 MST}
+ {2120115600 -21600 1 MDT}
+ {2140675200 -25200 0 MST}
+ {2152170000 -21600 1 MDT}
+ {2172729600 -25200 0 MST}
+ {2183619600 -21600 1 MDT}
+ {2204179200 -25200 0 MST}
+ {2215069200 -21600 1 MDT}
+ {2235628800 -25200 0 MST}
+ {2246518800 -21600 1 MDT}
+ {2267078400 -25200 0 MST}
+ {2277968400 -21600 1 MDT}
+ {2298528000 -25200 0 MST}
+ {2309418000 -21600 1 MDT}
+ {2329977600 -25200 0 MST}
+ {2341472400 -21600 1 MDT}
+ {2362032000 -25200 0 MST}
+ {2372922000 -21600 1 MDT}
+ {2393481600 -25200 0 MST}
+ {2404371600 -21600 1 MDT}
+ {2424931200 -25200 0 MST}
+ {2435821200 -21600 1 MDT}
+ {2456380800 -25200 0 MST}
+ {2467270800 -21600 1 MDT}
+ {2487830400 -25200 0 MST}
+ {2499325200 -21600 1 MDT}
+ {2519884800 -25200 0 MST}
+ {2530774800 -21600 1 MDT}
+ {2551334400 -25200 0 MST}
+ {2562224400 -21600 1 MDT}
+ {2582784000 -25200 0 MST}
+ {2593674000 -21600 1 MDT}
+ {2614233600 -25200 0 MST}
+ {2625123600 -21600 1 MDT}
+ {2645683200 -25200 0 MST}
+ {2656573200 -21600 1 MDT}
+ {2677132800 -25200 0 MST}
+ {2688627600 -21600 1 MDT}
+ {2709187200 -25200 0 MST}
+ {2720077200 -21600 1 MDT}
+ {2740636800 -25200 0 MST}
+ {2751526800 -21600 1 MDT}
+ {2772086400 -25200 0 MST}
+ {2782976400 -21600 1 MDT}
+ {2803536000 -25200 0 MST}
+ {2814426000 -21600 1 MDT}
+ {2834985600 -25200 0 MST}
+ {2846480400 -21600 1 MDT}
+ {2867040000 -25200 0 MST}
+ {2877930000 -21600 1 MDT}
+ {2898489600 -25200 0 MST}
+ {2909379600 -21600 1 MDT}
+ {2929939200 -25200 0 MST}
+ {2940829200 -21600 1 MDT}
+ {2961388800 -25200 0 MST}
+ {2972278800 -21600 1 MDT}
+ {2992838400 -25200 0 MST}
+ {3003728400 -21600 1 MDT}
+ {3024288000 -25200 0 MST}
+ {3035782800 -21600 1 MDT}
+ {3056342400 -25200 0 MST}
+ {3067232400 -21600 1 MDT}
+ {3087792000 -25200 0 MST}
+ {3098682000 -21600 1 MDT}
+ {3119241600 -25200 0 MST}
+ {3130131600 -21600 1 MDT}
+ {3150691200 -25200 0 MST}
+ {3161581200 -21600 1 MDT}
+ {3182140800 -25200 0 MST}
+ {3193030800 -21600 1 MDT}
+ {3213590400 -25200 0 MST}
+ {3225085200 -21600 1 MDT}
+ {3245644800 -25200 0 MST}
+ {3256534800 -21600 1 MDT}
+ {3277094400 -25200 0 MST}
+ {3287984400 -21600 1 MDT}
+ {3308544000 -25200 0 MST}
+ {3319434000 -21600 1 MDT}
+ {3339993600 -25200 0 MST}
+ {3350883600 -21600 1 MDT}
+ {3371443200 -25200 0 MST}
+ {3382938000 -21600 1 MDT}
+ {3403497600 -25200 0 MST}
+ {3414387600 -21600 1 MDT}
+ {3434947200 -25200 0 MST}
+ {3445837200 -21600 1 MDT}
+ {3466396800 -25200 0 MST}
+ {3477286800 -21600 1 MDT}
+ {3497846400 -25200 0 MST}
+ {3508736400 -21600 1 MDT}
+ {3529296000 -25200 0 MST}
+ {3540186000 -21600 1 MDT}
+ {3560745600 -25200 0 MST}
+ {3572240400 -21600 1 MDT}
+ {3592800000 -25200 0 MST}
+ {3603690000 -21600 1 MDT}
+ {3624249600 -25200 0 MST}
+ {3635139600 -21600 1 MDT}
+ {3655699200 -25200 0 MST}
+ {3666589200 -21600 1 MDT}
+ {3687148800 -25200 0 MST}
+ {3698038800 -21600 1 MDT}
+ {3718598400 -25200 0 MST}
+ {3730093200 -21600 1 MDT}
+ {3750652800 -25200 0 MST}
+ {3761542800 -21600 1 MDT}
+ {3782102400 -25200 0 MST}
+ {3792992400 -21600 1 MDT}
+ {3813552000 -25200 0 MST}
+ {3824442000 -21600 1 MDT}
+ {3845001600 -25200 0 MST}
+ {3855891600 -21600 1 MDT}
+ {3876451200 -25200 0 MST}
+ {3887341200 -21600 1 MDT}
+ {3907900800 -25200 0 MST}
+ {3919395600 -21600 1 MDT}
+ {3939955200 -25200 0 MST}
+ {3950845200 -21600 1 MDT}
+ {3971404800 -25200 0 MST}
+ {3982294800 -21600 1 MDT}
+ {4002854400 -25200 0 MST}
+ {4013744400 -21600 1 MDT}
+ {4034304000 -25200 0 MST}
+ {4045194000 -21600 1 MDT}
+ {4065753600 -25200 0 MST}
+ {4076643600 -21600 1 MDT}
+ {4097203200 -25200 0 MST}
+}
diff --git a/library/tzdata/America/Buenos_Aires b/library/tzdata/America/Buenos_Aires
new file mode 100644
index 0000000..1389195
--- /dev/null
+++ b/library/tzdata/America/Buenos_Aires
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Argentina/Buenos_Aires)]} {
+ LoadTimeZoneFile America/Argentina/Buenos_Aires
+}
+set TZData(:America/Buenos_Aires) $TZData(:America/Argentina/Buenos_Aires)
diff --git a/library/tzdata/America/Cambridge_Bay b/library/tzdata/America/Cambridge_Bay
new file mode 100644
index 0000000..23004bb
--- /dev/null
+++ b/library/tzdata/America/Cambridge_Bay
@@ -0,0 +1,252 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Cambridge_Bay) {
+ {-9223372036854775808 0 0 zzz}
+ {-1577923200 -25200 0 MST}
+ {-880210800 -21600 1 MWT}
+ {-769395600 -21600 1 MPT}
+ {-765388800 -25200 0 MST}
+ {-147891600 -18000 1 MDDT}
+ {-131562000 -25200 0 MST}
+ {325674000 -21600 1 MDT}
+ {341395200 -25200 0 MST}
+ {357123600 -21600 1 MDT}
+ {372844800 -25200 0 MST}
+ {388573200 -21600 1 MDT}
+ {404899200 -25200 0 MST}
+ {420022800 -21600 1 MDT}
+ {436348800 -25200 0 MST}
+ {452077200 -21600 1 MDT}
+ {467798400 -25200 0 MST}
+ {483526800 -21600 1 MDT}
+ {499248000 -25200 0 MST}
+ {514976400 -21600 1 MDT}
+ {530697600 -25200 0 MST}
+ {544611600 -21600 1 MDT}
+ {562147200 -25200 0 MST}
+ {576061200 -21600 1 MDT}
+ {594201600 -25200 0 MST}
+ {607510800 -21600 1 MDT}
+ {625651200 -25200 0 MST}
+ {638960400 -21600 1 MDT}
+ {657100800 -25200 0 MST}
+ {671014800 -21600 1 MDT}
+ {688550400 -25200 0 MST}
+ {702464400 -21600 1 MDT}
+ {720000000 -25200 0 MST}
+ {733914000 -21600 1 MDT}
+ {752054400 -25200 0 MST}
+ {765363600 -21600 1 MDT}
+ {783504000 -25200 0 MST}
+ {796813200 -21600 1 MDT}
+ {814953600 -25200 0 MST}
+ {828867600 -21600 1 MDT}
+ {846403200 -25200 0 MST}
+ {860317200 -21600 1 MDT}
+ {877852800 -25200 0 MST}
+ {891766800 -21600 1 MDT}
+ {909302400 -25200 0 MST}
+ {923216400 -21600 1 MDT}
+ {941360400 -21600 0 CST}
+ {954662400 -18000 1 CDT}
+ {972806400 -18000 0 EST}
+ {973400400 -21600 0 CST}
+ {986115600 -21600 0 MDT}
+ {1004256000 -25200 0 MST}
+ {1018170000 -21600 1 MDT}
+ {1035705600 -25200 0 MST}
+ {1049619600 -21600 1 MDT}
+ {1067155200 -25200 0 MST}
+ {1081069200 -21600 1 MDT}
+ {1099209600 -25200 0 MST}
+ {1112518800 -21600 1 MDT}
+ {1130659200 -25200 0 MST}
+ {1143968400 -21600 1 MDT}
+ {1162108800 -25200 0 MST}
+ {1173603600 -21600 1 MDT}
+ {1194163200 -25200 0 MST}
+ {1205053200 -21600 1 MDT}
+ {1225612800 -25200 0 MST}
+ {1236502800 -21600 1 MDT}
+ {1257062400 -25200 0 MST}
+ {1268557200 -21600 1 MDT}
+ {1289116800 -25200 0 MST}
+ {1300006800 -21600 1 MDT}
+ {1320566400 -25200 0 MST}
+ {1331456400 -21600 1 MDT}
+ {1352016000 -25200 0 MST}
+ {1362906000 -21600 1 MDT}
+ {1383465600 -25200 0 MST}
+ {1394355600 -21600 1 MDT}
+ {1414915200 -25200 0 MST}
+ {1425805200 -21600 1 MDT}
+ {1446364800 -25200 0 MST}
+ {1457859600 -21600 1 MDT}
+ {1478419200 -25200 0 MST}
+ {1489309200 -21600 1 MDT}
+ {1509868800 -25200 0 MST}
+ {1520758800 -21600 1 MDT}
+ {1541318400 -25200 0 MST}
+ {1552208400 -21600 1 MDT}
+ {1572768000 -25200 0 MST}
+ {1583658000 -21600 1 MDT}
+ {1604217600 -25200 0 MST}
+ {1615712400 -21600 1 MDT}
+ {1636272000 -25200 0 MST}
+ {1647162000 -21600 1 MDT}
+ {1667721600 -25200 0 MST}
+ {1678611600 -21600 1 MDT}
+ {1699171200 -25200 0 MST}
+ {1710061200 -21600 1 MDT}
+ {1730620800 -25200 0 MST}
+ {1741510800 -21600 1 MDT}
+ {1762070400 -25200 0 MST}
+ {1772960400 -21600 1 MDT}
+ {1793520000 -25200 0 MST}
+ {1805014800 -21600 1 MDT}
+ {1825574400 -25200 0 MST}
+ {1836464400 -21600 1 MDT}
+ {1857024000 -25200 0 MST}
+ {1867914000 -21600 1 MDT}
+ {1888473600 -25200 0 MST}
+ {1899363600 -21600 1 MDT}
+ {1919923200 -25200 0 MST}
+ {1930813200 -21600 1 MDT}
+ {1951372800 -25200 0 MST}
+ {1962867600 -21600 1 MDT}
+ {1983427200 -25200 0 MST}
+ {1994317200 -21600 1 MDT}
+ {2014876800 -25200 0 MST}
+ {2025766800 -21600 1 MDT}
+ {2046326400 -25200 0 MST}
+ {2057216400 -21600 1 MDT}
+ {2077776000 -25200 0 MST}
+ {2088666000 -21600 1 MDT}
+ {2109225600 -25200 0 MST}
+ {2120115600 -21600 1 MDT}
+ {2140675200 -25200 0 MST}
+ {2152170000 -21600 1 MDT}
+ {2172729600 -25200 0 MST}
+ {2183619600 -21600 1 MDT}
+ {2204179200 -25200 0 MST}
+ {2215069200 -21600 1 MDT}
+ {2235628800 -25200 0 MST}
+ {2246518800 -21600 1 MDT}
+ {2267078400 -25200 0 MST}
+ {2277968400 -21600 1 MDT}
+ {2298528000 -25200 0 MST}
+ {2309418000 -21600 1 MDT}
+ {2329977600 -25200 0 MST}
+ {2341472400 -21600 1 MDT}
+ {2362032000 -25200 0 MST}
+ {2372922000 -21600 1 MDT}
+ {2393481600 -25200 0 MST}
+ {2404371600 -21600 1 MDT}
+ {2424931200 -25200 0 MST}
+ {2435821200 -21600 1 MDT}
+ {2456380800 -25200 0 MST}
+ {2467270800 -21600 1 MDT}
+ {2487830400 -25200 0 MST}
+ {2499325200 -21600 1 MDT}
+ {2519884800 -25200 0 MST}
+ {2530774800 -21600 1 MDT}
+ {2551334400 -25200 0 MST}
+ {2562224400 -21600 1 MDT}
+ {2582784000 -25200 0 MST}
+ {2593674000 -21600 1 MDT}
+ {2614233600 -25200 0 MST}
+ {2625123600 -21600 1 MDT}
+ {2645683200 -25200 0 MST}
+ {2656573200 -21600 1 MDT}
+ {2677132800 -25200 0 MST}
+ {2688627600 -21600 1 MDT}
+ {2709187200 -25200 0 MST}
+ {2720077200 -21600 1 MDT}
+ {2740636800 -25200 0 MST}
+ {2751526800 -21600 1 MDT}
+ {2772086400 -25200 0 MST}
+ {2782976400 -21600 1 MDT}
+ {2803536000 -25200 0 MST}
+ {2814426000 -21600 1 MDT}
+ {2834985600 -25200 0 MST}
+ {2846480400 -21600 1 MDT}
+ {2867040000 -25200 0 MST}
+ {2877930000 -21600 1 MDT}
+ {2898489600 -25200 0 MST}
+ {2909379600 -21600 1 MDT}
+ {2929939200 -25200 0 MST}
+ {2940829200 -21600 1 MDT}
+ {2961388800 -25200 0 MST}
+ {2972278800 -21600 1 MDT}
+ {2992838400 -25200 0 MST}
+ {3003728400 -21600 1 MDT}
+ {3024288000 -25200 0 MST}
+ {3035782800 -21600 1 MDT}
+ {3056342400 -25200 0 MST}
+ {3067232400 -21600 1 MDT}
+ {3087792000 -25200 0 MST}
+ {3098682000 -21600 1 MDT}
+ {3119241600 -25200 0 MST}
+ {3130131600 -21600 1 MDT}
+ {3150691200 -25200 0 MST}
+ {3161581200 -21600 1 MDT}
+ {3182140800 -25200 0 MST}
+ {3193030800 -21600 1 MDT}
+ {3213590400 -25200 0 MST}
+ {3225085200 -21600 1 MDT}
+ {3245644800 -25200 0 MST}
+ {3256534800 -21600 1 MDT}
+ {3277094400 -25200 0 MST}
+ {3287984400 -21600 1 MDT}
+ {3308544000 -25200 0 MST}
+ {3319434000 -21600 1 MDT}
+ {3339993600 -25200 0 MST}
+ {3350883600 -21600 1 MDT}
+ {3371443200 -25200 0 MST}
+ {3382938000 -21600 1 MDT}
+ {3403497600 -25200 0 MST}
+ {3414387600 -21600 1 MDT}
+ {3434947200 -25200 0 MST}
+ {3445837200 -21600 1 MDT}
+ {3466396800 -25200 0 MST}
+ {3477286800 -21600 1 MDT}
+ {3497846400 -25200 0 MST}
+ {3508736400 -21600 1 MDT}
+ {3529296000 -25200 0 MST}
+ {3540186000 -21600 1 MDT}
+ {3560745600 -25200 0 MST}
+ {3572240400 -21600 1 MDT}
+ {3592800000 -25200 0 MST}
+ {3603690000 -21600 1 MDT}
+ {3624249600 -25200 0 MST}
+ {3635139600 -21600 1 MDT}
+ {3655699200 -25200 0 MST}
+ {3666589200 -21600 1 MDT}
+ {3687148800 -25200 0 MST}
+ {3698038800 -21600 1 MDT}
+ {3718598400 -25200 0 MST}
+ {3730093200 -21600 1 MDT}
+ {3750652800 -25200 0 MST}
+ {3761542800 -21600 1 MDT}
+ {3782102400 -25200 0 MST}
+ {3792992400 -21600 1 MDT}
+ {3813552000 -25200 0 MST}
+ {3824442000 -21600 1 MDT}
+ {3845001600 -25200 0 MST}
+ {3855891600 -21600 1 MDT}
+ {3876451200 -25200 0 MST}
+ {3887341200 -21600 1 MDT}
+ {3907900800 -25200 0 MST}
+ {3919395600 -21600 1 MDT}
+ {3939955200 -25200 0 MST}
+ {3950845200 -21600 1 MDT}
+ {3971404800 -25200 0 MST}
+ {3982294800 -21600 1 MDT}
+ {4002854400 -25200 0 MST}
+ {4013744400 -21600 1 MDT}
+ {4034304000 -25200 0 MST}
+ {4045194000 -21600 1 MDT}
+ {4065753600 -25200 0 MST}
+ {4076643600 -21600 1 MDT}
+ {4097203200 -25200 0 MST}
+}
diff --git a/library/tzdata/America/Campo_Grande b/library/tzdata/America/Campo_Grande
new file mode 100644
index 0000000..2cafe14
--- /dev/null
+++ b/library/tzdata/America/Campo_Grande
@@ -0,0 +1,257 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Campo_Grande) {
+ {-9223372036854775808 -13108 0 LMT}
+ {-1767212492 -14400 0 AMT}
+ {-1206954000 -10800 1 AMST}
+ {-1191358800 -14400 0 AMT}
+ {-1175371200 -10800 1 AMST}
+ {-1159822800 -14400 0 AMT}
+ {-633816000 -10800 1 AMST}
+ {-622065600 -14400 0 AMT}
+ {-602280000 -10800 1 AMST}
+ {-591829200 -14400 0 AMT}
+ {-570744000 -10800 1 AMST}
+ {-560206800 -14400 0 AMT}
+ {-539121600 -10800 1 AMST}
+ {-531349200 -14400 0 AMT}
+ {-191361600 -10800 1 AMST}
+ {-184194000 -14400 0 AMT}
+ {-155160000 -10800 1 AMST}
+ {-150066000 -14400 0 AMT}
+ {-128894400 -10800 1 AMST}
+ {-121122000 -14400 0 AMT}
+ {-99950400 -10800 1 AMST}
+ {-89586000 -14400 0 AMT}
+ {-68414400 -10800 1 AMST}
+ {-57963600 -14400 0 AMT}
+ {499752000 -10800 1 AMST}
+ {511239600 -14400 0 AMT}
+ {530596800 -10800 1 AMST}
+ {540270000 -14400 0 AMT}
+ {562132800 -10800 1 AMST}
+ {571201200 -14400 0 AMT}
+ {592977600 -10800 1 AMST}
+ {602046000 -14400 0 AMT}
+ {624427200 -10800 1 AMST}
+ {634705200 -14400 0 AMT}
+ {656481600 -10800 1 AMST}
+ {666759600 -14400 0 AMT}
+ {687931200 -10800 1 AMST}
+ {697604400 -14400 0 AMT}
+ {719985600 -10800 1 AMST}
+ {728449200 -14400 0 AMT}
+ {750830400 -10800 1 AMST}
+ {761713200 -14400 0 AMT}
+ {782280000 -10800 1 AMST}
+ {793162800 -14400 0 AMT}
+ {813729600 -10800 1 AMST}
+ {824007600 -14400 0 AMT}
+ {844574400 -10800 1 AMST}
+ {856062000 -14400 0 AMT}
+ {876110400 -10800 1 AMST}
+ {888721200 -14400 0 AMT}
+ {908078400 -10800 1 AMST}
+ {919566000 -14400 0 AMT}
+ {938923200 -10800 1 AMST}
+ {951620400 -14400 0 AMT}
+ {970977600 -10800 1 AMST}
+ {982465200 -14400 0 AMT}
+ {1003032000 -10800 1 AMST}
+ {1013914800 -14400 0 AMT}
+ {1036296000 -10800 1 AMST}
+ {1045364400 -14400 0 AMT}
+ {1066536000 -10800 1 AMST}
+ {1076814000 -14400 0 AMT}
+ {1099368000 -10800 1 AMST}
+ {1108868400 -14400 0 AMT}
+ {1129435200 -10800 1 AMST}
+ {1140318000 -14400 0 AMT}
+ {1162699200 -10800 1 AMST}
+ {1172372400 -14400 0 AMT}
+ {1192334400 -10800 1 AMST}
+ {1203217200 -14400 0 AMT}
+ {1224388800 -10800 1 AMST}
+ {1234666800 -14400 0 AMT}
+ {1255838400 -10800 1 AMST}
+ {1266721200 -14400 0 AMT}
+ {1287288000 -10800 1 AMST}
+ {1298170800 -14400 0 AMT}
+ {1318737600 -10800 1 AMST}
+ {1330225200 -14400 0 AMT}
+ {1350792000 -10800 1 AMST}
+ {1361070000 -14400 0 AMT}
+ {1382241600 -10800 1 AMST}
+ {1392519600 -14400 0 AMT}
+ {1413691200 -10800 1 AMST}
+ {1424574000 -14400 0 AMT}
+ {1445140800 -10800 1 AMST}
+ {1456023600 -14400 0 AMT}
+ {1476590400 -10800 1 AMST}
+ {1487473200 -14400 0 AMT}
+ {1508040000 -10800 1 AMST}
+ {1518922800 -14400 0 AMT}
+ {1540094400 -10800 1 AMST}
+ {1550372400 -14400 0 AMT}
+ {1571544000 -10800 1 AMST}
+ {1581822000 -14400 0 AMT}
+ {1602993600 -10800 1 AMST}
+ {1613876400 -14400 0 AMT}
+ {1634443200 -10800 1 AMST}
+ {1645326000 -14400 0 AMT}
+ {1665892800 -10800 1 AMST}
+ {1677380400 -14400 0 AMT}
+ {1697342400 -10800 1 AMST}
+ {1708225200 -14400 0 AMT}
+ {1729396800 -10800 1 AMST}
+ {1739674800 -14400 0 AMT}
+ {1760846400 -10800 1 AMST}
+ {1771729200 -14400 0 AMT}
+ {1792296000 -10800 1 AMST}
+ {1803178800 -14400 0 AMT}
+ {1823745600 -10800 1 AMST}
+ {1834628400 -14400 0 AMT}
+ {1855195200 -10800 1 AMST}
+ {1866078000 -14400 0 AMT}
+ {1887249600 -10800 1 AMST}
+ {1897527600 -14400 0 AMT}
+ {1918699200 -10800 1 AMST}
+ {1928977200 -14400 0 AMT}
+ {1950148800 -10800 1 AMST}
+ {1960426800 -14400 0 AMT}
+ {1981598400 -10800 1 AMST}
+ {1992481200 -14400 0 AMT}
+ {2013048000 -10800 1 AMST}
+ {2024535600 -14400 0 AMT}
+ {2044497600 -10800 1 AMST}
+ {2055380400 -14400 0 AMT}
+ {2076552000 -10800 1 AMST}
+ {2086830000 -14400 0 AMT}
+ {2108001600 -10800 1 AMST}
+ {2118884400 -14400 0 AMT}
+ {2139451200 -10800 1 AMST}
+ {2150334000 -14400 0 AMT}
+ {2170900800 -10800 1 AMST}
+ {2181783600 -14400 0 AMT}
+ {2202350400 -10800 1 AMST}
+ {2213233200 -14400 0 AMT}
+ {2234404800 -10800 1 AMST}
+ {2244682800 -14400 0 AMT}
+ {2265854400 -10800 1 AMST}
+ {2276132400 -14400 0 AMT}
+ {2297304000 -10800 1 AMST}
+ {2307582000 -14400 0 AMT}
+ {2328753600 -10800 1 AMST}
+ {2339636400 -14400 0 AMT}
+ {2360203200 -10800 1 AMST}
+ {2371086000 -14400 0 AMT}
+ {2391652800 -10800 1 AMST}
+ {2402535600 -14400 0 AMT}
+ {2423707200 -10800 1 AMST}
+ {2433985200 -14400 0 AMT}
+ {2455156800 -10800 1 AMST}
+ {2465434800 -14400 0 AMT}
+ {2486606400 -10800 1 AMST}
+ {2497489200 -14400 0 AMT}
+ {2518056000 -10800 1 AMST}
+ {2528938800 -14400 0 AMT}
+ {2549505600 -10800 1 AMST}
+ {2560388400 -14400 0 AMT}
+ {2580955200 -10800 1 AMST}
+ {2591838000 -14400 0 AMT}
+ {2613009600 -10800 1 AMST}
+ {2623287600 -14400 0 AMT}
+ {2644459200 -10800 1 AMST}
+ {2654737200 -14400 0 AMT}
+ {2675908800 -10800 1 AMST}
+ {2686791600 -14400 0 AMT}
+ {2707358400 -10800 1 AMST}
+ {2718241200 -14400 0 AMT}
+ {2738808000 -10800 1 AMST}
+ {2749690800 -14400 0 AMT}
+ {2770862400 -10800 1 AMST}
+ {2781140400 -14400 0 AMT}
+ {2802312000 -10800 1 AMST}
+ {2812590000 -14400 0 AMT}
+ {2833761600 -10800 1 AMST}
+ {2844039600 -14400 0 AMT}
+ {2865211200 -10800 1 AMST}
+ {2876094000 -14400 0 AMT}
+ {2896660800 -10800 1 AMST}
+ {2907543600 -14400 0 AMT}
+ {2928110400 -10800 1 AMST}
+ {2938993200 -14400 0 AMT}
+ {2960164800 -10800 1 AMST}
+ {2970442800 -14400 0 AMT}
+ {2991614400 -10800 1 AMST}
+ {3001892400 -14400 0 AMT}
+ {3023064000 -10800 1 AMST}
+ {3033946800 -14400 0 AMT}
+ {3054513600 -10800 1 AMST}
+ {3065396400 -14400 0 AMT}
+ {3085963200 -10800 1 AMST}
+ {3096846000 -14400 0 AMT}
+ {3118017600 -10800 1 AMST}
+ {3128295600 -14400 0 AMT}
+ {3149467200 -10800 1 AMST}
+ {3159745200 -14400 0 AMT}
+ {3180916800 -10800 1 AMST}
+ {3191194800 -14400 0 AMT}
+ {3212366400 -10800 1 AMST}
+ {3223249200 -14400 0 AMT}
+ {3243816000 -10800 1 AMST}
+ {3254698800 -14400 0 AMT}
+ {3275265600 -10800 1 AMST}
+ {3286148400 -14400 0 AMT}
+ {3307320000 -10800 1 AMST}
+ {3317598000 -14400 0 AMT}
+ {3338769600 -10800 1 AMST}
+ {3349047600 -14400 0 AMT}
+ {3370219200 -10800 1 AMST}
+ {3381102000 -14400 0 AMT}
+ {3401668800 -10800 1 AMST}
+ {3412551600 -14400 0 AMT}
+ {3433118400 -10800 1 AMST}
+ {3444001200 -14400 0 AMT}
+ {3464568000 -10800 1 AMST}
+ {3475450800 -14400 0 AMT}
+ {3496622400 -10800 1 AMST}
+ {3506900400 -14400 0 AMT}
+ {3528072000 -10800 1 AMST}
+ {3538350000 -14400 0 AMT}
+ {3559521600 -10800 1 AMST}
+ {3570404400 -14400 0 AMT}
+ {3590971200 -10800 1 AMST}
+ {3601854000 -14400 0 AMT}
+ {3622420800 -10800 1 AMST}
+ {3633303600 -14400 0 AMT}
+ {3654475200 -10800 1 AMST}
+ {3664753200 -14400 0 AMT}
+ {3685924800 -10800 1 AMST}
+ {3696202800 -14400 0 AMT}
+ {3717374400 -10800 1 AMST}
+ {3727652400 -14400 0 AMT}
+ {3748824000 -10800 1 AMST}
+ {3759706800 -14400 0 AMT}
+ {3780273600 -10800 1 AMST}
+ {3791156400 -14400 0 AMT}
+ {3811723200 -10800 1 AMST}
+ {3822606000 -14400 0 AMT}
+ {3843777600 -10800 1 AMST}
+ {3854055600 -14400 0 AMT}
+ {3875227200 -10800 1 AMST}
+ {3885505200 -14400 0 AMT}
+ {3906676800 -10800 1 AMST}
+ {3917559600 -14400 0 AMT}
+ {3938126400 -10800 1 AMST}
+ {3949009200 -14400 0 AMT}
+ {3969576000 -10800 1 AMST}
+ {3980458800 -14400 0 AMT}
+ {4001630400 -10800 1 AMST}
+ {4011908400 -14400 0 AMT}
+ {4033080000 -10800 1 AMST}
+ {4043358000 -14400 0 AMT}
+ {4064529600 -10800 1 AMST}
+ {4074807600 -14400 0 AMT}
+ {4095979200 -10800 1 AMST}
+}
diff --git a/library/tzdata/America/Cancun b/library/tzdata/America/Cancun
new file mode 100644
index 0000000..1620b15
--- /dev/null
+++ b/library/tzdata/America/Cancun
@@ -0,0 +1,216 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Cancun) {
+ {-9223372036854775808 -20824 0 LMT}
+ {-1514743200 -21600 0 CST}
+ {377935200 -18000 0 EST}
+ {828860400 -14400 1 EDT}
+ {846396000 -18000 0 EST}
+ {860310000 -14400 1 EDT}
+ {877845600 -18000 0 EST}
+ {891759600 -14400 1 EDT}
+ {902041200 -18000 0 CDT}
+ {909298800 -21600 0 CST}
+ {923212800 -18000 1 CDT}
+ {941353200 -21600 0 CST}
+ {954662400 -18000 1 CDT}
+ {972802800 -21600 0 CST}
+ {989136000 -18000 1 CDT}
+ {1001833200 -21600 0 CST}
+ {1018166400 -18000 1 CDT}
+ {1035702000 -21600 0 CST}
+ {1049616000 -18000 1 CDT}
+ {1067151600 -21600 0 CST}
+ {1081065600 -18000 1 CDT}
+ {1099206000 -21600 0 CST}
+ {1112515200 -18000 1 CDT}
+ {1130655600 -21600 0 CST}
+ {1143964800 -18000 1 CDT}
+ {1162105200 -21600 0 CST}
+ {1175414400 -18000 1 CDT}
+ {1193554800 -21600 0 CST}
+ {1207468800 -18000 1 CDT}
+ {1225004400 -21600 0 CST}
+ {1238918400 -18000 1 CDT}
+ {1256454000 -21600 0 CST}
+ {1270368000 -18000 1 CDT}
+ {1288508400 -21600 0 CST}
+ {1301817600 -18000 1 CDT}
+ {1319958000 -21600 0 CST}
+ {1333267200 -18000 1 CDT}
+ {1351407600 -21600 0 CST}
+ {1365321600 -18000 1 CDT}
+ {1382857200 -21600 0 CST}
+ {1396771200 -18000 1 CDT}
+ {1414306800 -21600 0 CST}
+ {1428220800 -18000 1 CDT}
+ {1445756400 -21600 0 CST}
+ {1459670400 -18000 1 CDT}
+ {1477810800 -21600 0 CST}
+ {1491120000 -18000 1 CDT}
+ {1509260400 -21600 0 CST}
+ {1522569600 -18000 1 CDT}
+ {1540710000 -21600 0 CST}
+ {1554624000 -18000 1 CDT}
+ {1572159600 -21600 0 CST}
+ {1586073600 -18000 1 CDT}
+ {1603609200 -21600 0 CST}
+ {1617523200 -18000 1 CDT}
+ {1635663600 -21600 0 CST}
+ {1648972800 -18000 1 CDT}
+ {1667113200 -21600 0 CST}
+ {1680422400 -18000 1 CDT}
+ {1698562800 -21600 0 CST}
+ {1712476800 -18000 1 CDT}
+ {1730012400 -21600 0 CST}
+ {1743926400 -18000 1 CDT}
+ {1761462000 -21600 0 CST}
+ {1775376000 -18000 1 CDT}
+ {1792911600 -21600 0 CST}
+ {1806825600 -18000 1 CDT}
+ {1824966000 -21600 0 CST}
+ {1838275200 -18000 1 CDT}
+ {1856415600 -21600 0 CST}
+ {1869724800 -18000 1 CDT}
+ {1887865200 -21600 0 CST}
+ {1901779200 -18000 1 CDT}
+ {1919314800 -21600 0 CST}
+ {1933228800 -18000 1 CDT}
+ {1950764400 -21600 0 CST}
+ {1964678400 -18000 1 CDT}
+ {1982818800 -21600 0 CST}
+ {1996128000 -18000 1 CDT}
+ {2014268400 -21600 0 CST}
+ {2027577600 -18000 1 CDT}
+ {2045718000 -21600 0 CST}
+ {2059027200 -18000 1 CDT}
+ {2077167600 -21600 0 CST}
+ {2091081600 -18000 1 CDT}
+ {2108617200 -21600 0 CST}
+ {2122531200 -18000 1 CDT}
+ {2140066800 -21600 0 CST}
+ {2153980800 -18000 1 CDT}
+ {2172121200 -21600 0 CST}
+ {2185430400 -18000 1 CDT}
+ {2203570800 -21600 0 CST}
+ {2216880000 -18000 1 CDT}
+ {2235020400 -21600 0 CST}
+ {2248934400 -18000 1 CDT}
+ {2266470000 -21600 0 CST}
+ {2280384000 -18000 1 CDT}
+ {2297919600 -21600 0 CST}
+ {2311833600 -18000 1 CDT}
+ {2329369200 -21600 0 CST}
+ {2343283200 -18000 1 CDT}
+ {2361423600 -21600 0 CST}
+ {2374732800 -18000 1 CDT}
+ {2392873200 -21600 0 CST}
+ {2406182400 -18000 1 CDT}
+ {2424322800 -21600 0 CST}
+ {2438236800 -18000 1 CDT}
+ {2455772400 -21600 0 CST}
+ {2469686400 -18000 1 CDT}
+ {2487222000 -21600 0 CST}
+ {2501136000 -18000 1 CDT}
+ {2519276400 -21600 0 CST}
+ {2532585600 -18000 1 CDT}
+ {2550726000 -21600 0 CST}
+ {2564035200 -18000 1 CDT}
+ {2582175600 -21600 0 CST}
+ {2596089600 -18000 1 CDT}
+ {2613625200 -21600 0 CST}
+ {2627539200 -18000 1 CDT}
+ {2645074800 -21600 0 CST}
+ {2658988800 -18000 1 CDT}
+ {2676524400 -21600 0 CST}
+ {2690438400 -18000 1 CDT}
+ {2708578800 -21600 0 CST}
+ {2721888000 -18000 1 CDT}
+ {2740028400 -21600 0 CST}
+ {2753337600 -18000 1 CDT}
+ {2771478000 -21600 0 CST}
+ {2785392000 -18000 1 CDT}
+ {2802927600 -21600 0 CST}
+ {2816841600 -18000 1 CDT}
+ {2834377200 -21600 0 CST}
+ {2848291200 -18000 1 CDT}
+ {2866431600 -21600 0 CST}
+ {2879740800 -18000 1 CDT}
+ {2897881200 -21600 0 CST}
+ {2911190400 -18000 1 CDT}
+ {2929330800 -21600 0 CST}
+ {2942640000 -18000 1 CDT}
+ {2960780400 -21600 0 CST}
+ {2974694400 -18000 1 CDT}
+ {2992230000 -21600 0 CST}
+ {3006144000 -18000 1 CDT}
+ {3023679600 -21600 0 CST}
+ {3037593600 -18000 1 CDT}
+ {3055734000 -21600 0 CST}
+ {3069043200 -18000 1 CDT}
+ {3087183600 -21600 0 CST}
+ {3100492800 -18000 1 CDT}
+ {3118633200 -21600 0 CST}
+ {3132547200 -18000 1 CDT}
+ {3150082800 -21600 0 CST}
+ {3163996800 -18000 1 CDT}
+ {3181532400 -21600 0 CST}
+ {3195446400 -18000 1 CDT}
+ {3212982000 -21600 0 CST}
+ {3226896000 -18000 1 CDT}
+ {3245036400 -21600 0 CST}
+ {3258345600 -18000 1 CDT}
+ {3276486000 -21600 0 CST}
+ {3289795200 -18000 1 CDT}
+ {3307935600 -21600 0 CST}
+ {3321849600 -18000 1 CDT}
+ {3339385200 -21600 0 CST}
+ {3353299200 -18000 1 CDT}
+ {3370834800 -21600 0 CST}
+ {3384748800 -18000 1 CDT}
+ {3402889200 -21600 0 CST}
+ {3416198400 -18000 1 CDT}
+ {3434338800 -21600 0 CST}
+ {3447648000 -18000 1 CDT}
+ {3465788400 -21600 0 CST}
+ {3479702400 -18000 1 CDT}
+ {3497238000 -21600 0 CST}
+ {3511152000 -18000 1 CDT}
+ {3528687600 -21600 0 CST}
+ {3542601600 -18000 1 CDT}
+ {3560137200 -21600 0 CST}
+ {3574051200 -18000 1 CDT}
+ {3592191600 -21600 0 CST}
+ {3605500800 -18000 1 CDT}
+ {3623641200 -21600 0 CST}
+ {3636950400 -18000 1 CDT}
+ {3655090800 -21600 0 CST}
+ {3669004800 -18000 1 CDT}
+ {3686540400 -21600 0 CST}
+ {3700454400 -18000 1 CDT}
+ {3717990000 -21600 0 CST}
+ {3731904000 -18000 1 CDT}
+ {3750044400 -21600 0 CST}
+ {3763353600 -18000 1 CDT}
+ {3781494000 -21600 0 CST}
+ {3794803200 -18000 1 CDT}
+ {3812943600 -21600 0 CST}
+ {3826252800 -18000 1 CDT}
+ {3844393200 -21600 0 CST}
+ {3858307200 -18000 1 CDT}
+ {3875842800 -21600 0 CST}
+ {3889756800 -18000 1 CDT}
+ {3907292400 -21600 0 CST}
+ {3921206400 -18000 1 CDT}
+ {3939346800 -21600 0 CST}
+ {3952656000 -18000 1 CDT}
+ {3970796400 -21600 0 CST}
+ {3984105600 -18000 1 CDT}
+ {4002246000 -21600 0 CST}
+ {4016160000 -18000 1 CDT}
+ {4033695600 -21600 0 CST}
+ {4047609600 -18000 1 CDT}
+ {4065145200 -21600 0 CST}
+ {4079059200 -18000 1 CDT}
+ {4096594800 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Caracas b/library/tzdata/America/Caracas
new file mode 100644
index 0000000..2ba87ae
--- /dev/null
+++ b/library/tzdata/America/Caracas
@@ -0,0 +1,9 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Caracas) {
+ {-9223372036854775808 -16064 0 LMT}
+ {-2524505536 -16060 0 CMT}
+ {-1826739140 -16200 0 VET}
+ {-157750200 -14400 0 VET}
+ {1197183600 -16200 0 VET}
+}
diff --git a/library/tzdata/America/Catamarca b/library/tzdata/America/Catamarca
new file mode 100644
index 0000000..01c8ab6
--- /dev/null
+++ b/library/tzdata/America/Catamarca
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Argentina/Catamarca)]} {
+ LoadTimeZoneFile America/Argentina/Catamarca
+}
+set TZData(:America/Catamarca) $TZData(:America/Argentina/Catamarca)
diff --git a/library/tzdata/America/Cayenne b/library/tzdata/America/Cayenne
new file mode 100644
index 0000000..de3d65b
--- /dev/null
+++ b/library/tzdata/America/Cayenne
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Cayenne) {
+ {-9223372036854775808 -12560 0 LMT}
+ {-1846269040 -14400 0 GFT}
+ {-71092800 -10800 0 GFT}
+}
diff --git a/library/tzdata/America/Cayman b/library/tzdata/America/Cayman
new file mode 100644
index 0000000..ab5d12b
--- /dev/null
+++ b/library/tzdata/America/Cayman
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Cayman) {
+ {-9223372036854775808 -19532 0 LMT}
+ {-2524502068 -18432 0 KMT}
+ {-1827687168 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Chicago b/library/tzdata/America/Chicago
new file mode 100644
index 0000000..545aedb
--- /dev/null
+++ b/library/tzdata/America/Chicago
@@ -0,0 +1,369 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Chicago) {
+ {-9223372036854775808 -21036 0 LMT}
+ {-2717647200 -21600 0 CST}
+ {-1633276800 -18000 1 CDT}
+ {-1615136400 -21600 0 CST}
+ {-1601827200 -18000 1 CDT}
+ {-1583686800 -21600 0 CST}
+ {-1577901600 -21600 0 CST}
+ {-1563724800 -18000 1 CDT}
+ {-1551632400 -21600 0 CST}
+ {-1538928000 -18000 1 CDT}
+ {-1520182800 -21600 0 CST}
+ {-1504454400 -18000 1 CDT}
+ {-1491757200 -21600 0 CST}
+ {-1473004800 -18000 1 CDT}
+ {-1459702800 -21600 0 CST}
+ {-1441555200 -18000 1 CDT}
+ {-1428253200 -21600 0 CST}
+ {-1410105600 -18000 1 CDT}
+ {-1396803600 -21600 0 CST}
+ {-1378656000 -18000 1 CDT}
+ {-1365354000 -21600 0 CST}
+ {-1347206400 -18000 1 CDT}
+ {-1333904400 -21600 0 CST}
+ {-1315152000 -18000 1 CDT}
+ {-1301850000 -21600 0 CST}
+ {-1283702400 -18000 1 CDT}
+ {-1270400400 -21600 0 CST}
+ {-1252252800 -18000 1 CDT}
+ {-1238950800 -21600 0 CST}
+ {-1220803200 -18000 1 CDT}
+ {-1207501200 -21600 0 CST}
+ {-1189353600 -18000 1 CDT}
+ {-1176051600 -21600 0 CST}
+ {-1157299200 -18000 1 CDT}
+ {-1144602000 -21600 0 CST}
+ {-1125849600 -18000 1 CDT}
+ {-1112547600 -21600 0 CST}
+ {-1094400000 -18000 1 CDT}
+ {-1081098000 -21600 0 CST}
+ {-1067788800 -18000 0 EST}
+ {-1045414800 -21600 0 CST}
+ {-1031500800 -18000 1 CDT}
+ {-1018198800 -21600 0 CST}
+ {-1000051200 -18000 1 CDT}
+ {-986749200 -21600 0 CST}
+ {-967996800 -18000 1 CDT}
+ {-955299600 -21600 0 CST}
+ {-936547200 -18000 1 CDT}
+ {-923245200 -21600 0 CST}
+ {-905097600 -18000 1 CDT}
+ {-891795600 -21600 0 CST}
+ {-883591200 -21600 0 CST}
+ {-880214400 -18000 1 CWT}
+ {-769395600 -18000 1 CPT}
+ {-765392400 -21600 0 CST}
+ {-757360800 -21600 0 CST}
+ {-747244800 -18000 1 CDT}
+ {-733942800 -21600 0 CST}
+ {-715795200 -18000 1 CDT}
+ {-702493200 -21600 0 CST}
+ {-684345600 -18000 1 CDT}
+ {-671043600 -21600 0 CST}
+ {-652896000 -18000 1 CDT}
+ {-639594000 -21600 0 CST}
+ {-620841600 -18000 1 CDT}
+ {-608144400 -21600 0 CST}
+ {-589392000 -18000 1 CDT}
+ {-576090000 -21600 0 CST}
+ {-557942400 -18000 1 CDT}
+ {-544640400 -21600 0 CST}
+ {-526492800 -18000 1 CDT}
+ {-513190800 -21600 0 CST}
+ {-495043200 -18000 1 CDT}
+ {-481741200 -21600 0 CST}
+ {-463593600 -18000 1 CDT}
+ {-447267600 -21600 0 CST}
+ {-431539200 -18000 1 CDT}
+ {-415818000 -21600 0 CST}
+ {-400089600 -18000 1 CDT}
+ {-384368400 -21600 0 CST}
+ {-368640000 -18000 1 CDT}
+ {-352918800 -21600 0 CST}
+ {-337190400 -18000 1 CDT}
+ {-321469200 -21600 0 CST}
+ {-305740800 -18000 1 CDT}
+ {-289414800 -21600 0 CST}
+ {-273686400 -18000 1 CDT}
+ {-257965200 -21600 0 CST}
+ {-242236800 -18000 1 CDT}
+ {-226515600 -21600 0 CST}
+ {-210787200 -18000 1 CDT}
+ {-195066000 -21600 0 CST}
+ {-179337600 -18000 1 CDT}
+ {-163616400 -21600 0 CST}
+ {-147888000 -18000 1 CDT}
+ {-131562000 -21600 0 CST}
+ {-116438400 -18000 1 CDT}
+ {-100112400 -21600 0 CST}
+ {-94672800 -21600 0 CST}
+ {-84384000 -18000 1 CDT}
+ {-68662800 -21600 0 CST}
+ {-52934400 -18000 1 CDT}
+ {-37213200 -21600 0 CST}
+ {-21484800 -18000 1 CDT}
+ {-5763600 -21600 0 CST}
+ {9964800 -18000 1 CDT}
+ {25686000 -21600 0 CST}
+ {41414400 -18000 1 CDT}
+ {57740400 -21600 0 CST}
+ {73468800 -18000 1 CDT}
+ {89190000 -21600 0 CST}
+ {104918400 -18000 1 CDT}
+ {120639600 -21600 0 CST}
+ {126691200 -18000 1 CDT}
+ {152089200 -21600 0 CST}
+ {162374400 -18000 1 CDT}
+ {183538800 -21600 0 CST}
+ {199267200 -18000 1 CDT}
+ {215593200 -21600 0 CST}
+ {230716800 -18000 1 CDT}
+ {247042800 -21600 0 CST}
+ {262771200 -18000 1 CDT}
+ {278492400 -21600 0 CST}
+ {294220800 -18000 1 CDT}
+ {309942000 -21600 0 CST}
+ {325670400 -18000 1 CDT}
+ {341391600 -21600 0 CST}
+ {357120000 -18000 1 CDT}
+ {372841200 -21600 0 CST}
+ {388569600 -18000 1 CDT}
+ {404895600 -21600 0 CST}
+ {420019200 -18000 1 CDT}
+ {436345200 -21600 0 CST}
+ {452073600 -18000 1 CDT}
+ {467794800 -21600 0 CST}
+ {483523200 -18000 1 CDT}
+ {499244400 -21600 0 CST}
+ {514972800 -18000 1 CDT}
+ {530694000 -21600 0 CST}
+ {544608000 -18000 1 CDT}
+ {562143600 -21600 0 CST}
+ {576057600 -18000 1 CDT}
+ {594198000 -21600 0 CST}
+ {607507200 -18000 1 CDT}
+ {625647600 -21600 0 CST}
+ {638956800 -18000 1 CDT}
+ {657097200 -21600 0 CST}
+ {671011200 -18000 1 CDT}
+ {688546800 -21600 0 CST}
+ {702460800 -18000 1 CDT}
+ {719996400 -21600 0 CST}
+ {733910400 -18000 1 CDT}
+ {752050800 -21600 0 CST}
+ {765360000 -18000 1 CDT}
+ {783500400 -21600 0 CST}
+ {796809600 -18000 1 CDT}
+ {814950000 -21600 0 CST}
+ {828864000 -18000 1 CDT}
+ {846399600 -21600 0 CST}
+ {860313600 -18000 1 CDT}
+ {877849200 -21600 0 CST}
+ {891763200 -18000 1 CDT}
+ {909298800 -21600 0 CST}
+ {923212800 -18000 1 CDT}
+ {941353200 -21600 0 CST}
+ {954662400 -18000 1 CDT}
+ {972802800 -21600 0 CST}
+ {986112000 -18000 1 CDT}
+ {1004252400 -21600 0 CST}
+ {1018166400 -18000 1 CDT}
+ {1035702000 -21600 0 CST}
+ {1049616000 -18000 1 CDT}
+ {1067151600 -21600 0 CST}
+ {1081065600 -18000 1 CDT}
+ {1099206000 -21600 0 CST}
+ {1112515200 -18000 1 CDT}
+ {1130655600 -21600 0 CST}
+ {1143964800 -18000 1 CDT}
+ {1162105200 -21600 0 CST}
+ {1173600000 -18000 1 CDT}
+ {1194159600 -21600 0 CST}
+ {1205049600 -18000 1 CDT}
+ {1225609200 -21600 0 CST}
+ {1236499200 -18000 1 CDT}
+ {1257058800 -21600 0 CST}
+ {1268553600 -18000 1 CDT}
+ {1289113200 -21600 0 CST}
+ {1300003200 -18000 1 CDT}
+ {1320562800 -21600 0 CST}
+ {1331452800 -18000 1 CDT}
+ {1352012400 -21600 0 CST}
+ {1362902400 -18000 1 CDT}
+ {1383462000 -21600 0 CST}
+ {1394352000 -18000 1 CDT}
+ {1414911600 -21600 0 CST}
+ {1425801600 -18000 1 CDT}
+ {1446361200 -21600 0 CST}
+ {1457856000 -18000 1 CDT}
+ {1478415600 -21600 0 CST}
+ {1489305600 -18000 1 CDT}
+ {1509865200 -21600 0 CST}
+ {1520755200 -18000 1 CDT}
+ {1541314800 -21600 0 CST}
+ {1552204800 -18000 1 CDT}
+ {1572764400 -21600 0 CST}
+ {1583654400 -18000 1 CDT}
+ {1604214000 -21600 0 CST}
+ {1615708800 -18000 1 CDT}
+ {1636268400 -21600 0 CST}
+ {1647158400 -18000 1 CDT}
+ {1667718000 -21600 0 CST}
+ {1678608000 -18000 1 CDT}
+ {1699167600 -21600 0 CST}
+ {1710057600 -18000 1 CDT}
+ {1730617200 -21600 0 CST}
+ {1741507200 -18000 1 CDT}
+ {1762066800 -21600 0 CST}
+ {1772956800 -18000 1 CDT}
+ {1793516400 -21600 0 CST}
+ {1805011200 -18000 1 CDT}
+ {1825570800 -21600 0 CST}
+ {1836460800 -18000 1 CDT}
+ {1857020400 -21600 0 CST}
+ {1867910400 -18000 1 CDT}
+ {1888470000 -21600 0 CST}
+ {1899360000 -18000 1 CDT}
+ {1919919600 -21600 0 CST}
+ {1930809600 -18000 1 CDT}
+ {1951369200 -21600 0 CST}
+ {1962864000 -18000 1 CDT}
+ {1983423600 -21600 0 CST}
+ {1994313600 -18000 1 CDT}
+ {2014873200 -21600 0 CST}
+ {2025763200 -18000 1 CDT}
+ {2046322800 -21600 0 CST}
+ {2057212800 -18000 1 CDT}
+ {2077772400 -21600 0 CST}
+ {2088662400 -18000 1 CDT}
+ {2109222000 -21600 0 CST}
+ {2120112000 -18000 1 CDT}
+ {2140671600 -21600 0 CST}
+ {2152166400 -18000 1 CDT}
+ {2172726000 -21600 0 CST}
+ {2183616000 -18000 1 CDT}
+ {2204175600 -21600 0 CST}
+ {2215065600 -18000 1 CDT}
+ {2235625200 -21600 0 CST}
+ {2246515200 -18000 1 CDT}
+ {2267074800 -21600 0 CST}
+ {2277964800 -18000 1 CDT}
+ {2298524400 -21600 0 CST}
+ {2309414400 -18000 1 CDT}
+ {2329974000 -21600 0 CST}
+ {2341468800 -18000 1 CDT}
+ {2362028400 -21600 0 CST}
+ {2372918400 -18000 1 CDT}
+ {2393478000 -21600 0 CST}
+ {2404368000 -18000 1 CDT}
+ {2424927600 -21600 0 CST}
+ {2435817600 -18000 1 CDT}
+ {2456377200 -21600 0 CST}
+ {2467267200 -18000 1 CDT}
+ {2487826800 -21600 0 CST}
+ {2499321600 -18000 1 CDT}
+ {2519881200 -21600 0 CST}
+ {2530771200 -18000 1 CDT}
+ {2551330800 -21600 0 CST}
+ {2562220800 -18000 1 CDT}
+ {2582780400 -21600 0 CST}
+ {2593670400 -18000 1 CDT}
+ {2614230000 -21600 0 CST}
+ {2625120000 -18000 1 CDT}
+ {2645679600 -21600 0 CST}
+ {2656569600 -18000 1 CDT}
+ {2677129200 -21600 0 CST}
+ {2688624000 -18000 1 CDT}
+ {2709183600 -21600 0 CST}
+ {2720073600 -18000 1 CDT}
+ {2740633200 -21600 0 CST}
+ {2751523200 -18000 1 CDT}
+ {2772082800 -21600 0 CST}
+ {2782972800 -18000 1 CDT}
+ {2803532400 -21600 0 CST}
+ {2814422400 -18000 1 CDT}
+ {2834982000 -21600 0 CST}
+ {2846476800 -18000 1 CDT}
+ {2867036400 -21600 0 CST}
+ {2877926400 -18000 1 CDT}
+ {2898486000 -21600 0 CST}
+ {2909376000 -18000 1 CDT}
+ {2929935600 -21600 0 CST}
+ {2940825600 -18000 1 CDT}
+ {2961385200 -21600 0 CST}
+ {2972275200 -18000 1 CDT}
+ {2992834800 -21600 0 CST}
+ {3003724800 -18000 1 CDT}
+ {3024284400 -21600 0 CST}
+ {3035779200 -18000 1 CDT}
+ {3056338800 -21600 0 CST}
+ {3067228800 -18000 1 CDT}
+ {3087788400 -21600 0 CST}
+ {3098678400 -18000 1 CDT}
+ {3119238000 -21600 0 CST}
+ {3130128000 -18000 1 CDT}
+ {3150687600 -21600 0 CST}
+ {3161577600 -18000 1 CDT}
+ {3182137200 -21600 0 CST}
+ {3193027200 -18000 1 CDT}
+ {3213586800 -21600 0 CST}
+ {3225081600 -18000 1 CDT}
+ {3245641200 -21600 0 CST}
+ {3256531200 -18000 1 CDT}
+ {3277090800 -21600 0 CST}
+ {3287980800 -18000 1 CDT}
+ {3308540400 -21600 0 CST}
+ {3319430400 -18000 1 CDT}
+ {3339990000 -21600 0 CST}
+ {3350880000 -18000 1 CDT}
+ {3371439600 -21600 0 CST}
+ {3382934400 -18000 1 CDT}
+ {3403494000 -21600 0 CST}
+ {3414384000 -18000 1 CDT}
+ {3434943600 -21600 0 CST}
+ {3445833600 -18000 1 CDT}
+ {3466393200 -21600 0 CST}
+ {3477283200 -18000 1 CDT}
+ {3497842800 -21600 0 CST}
+ {3508732800 -18000 1 CDT}
+ {3529292400 -21600 0 CST}
+ {3540182400 -18000 1 CDT}
+ {3560742000 -21600 0 CST}
+ {3572236800 -18000 1 CDT}
+ {3592796400 -21600 0 CST}
+ {3603686400 -18000 1 CDT}
+ {3624246000 -21600 0 CST}
+ {3635136000 -18000 1 CDT}
+ {3655695600 -21600 0 CST}
+ {3666585600 -18000 1 CDT}
+ {3687145200 -21600 0 CST}
+ {3698035200 -18000 1 CDT}
+ {3718594800 -21600 0 CST}
+ {3730089600 -18000 1 CDT}
+ {3750649200 -21600 0 CST}
+ {3761539200 -18000 1 CDT}
+ {3782098800 -21600 0 CST}
+ {3792988800 -18000 1 CDT}
+ {3813548400 -21600 0 CST}
+ {3824438400 -18000 1 CDT}
+ {3844998000 -21600 0 CST}
+ {3855888000 -18000 1 CDT}
+ {3876447600 -21600 0 CST}
+ {3887337600 -18000 1 CDT}
+ {3907897200 -21600 0 CST}
+ {3919392000 -18000 1 CDT}
+ {3939951600 -21600 0 CST}
+ {3950841600 -18000 1 CDT}
+ {3971401200 -21600 0 CST}
+ {3982291200 -18000 1 CDT}
+ {4002850800 -21600 0 CST}
+ {4013740800 -18000 1 CDT}
+ {4034300400 -21600 0 CST}
+ {4045190400 -18000 1 CDT}
+ {4065750000 -21600 0 CST}
+ {4076640000 -18000 1 CDT}
+ {4097199600 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Chihuahua b/library/tzdata/America/Chihuahua
new file mode 100644
index 0000000..5444930
--- /dev/null
+++ b/library/tzdata/America/Chihuahua
@@ -0,0 +1,221 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Chihuahua) {
+ {-9223372036854775808 -25460 0 LMT}
+ {-1514739600 -25200 0 MST}
+ {-1343066400 -21600 0 CST}
+ {-1234807200 -25200 0 MST}
+ {-1220292000 -21600 0 CST}
+ {-1207159200 -25200 0 MST}
+ {-1191344400 -21600 0 CST}
+ {820476000 -21600 0 CST}
+ {828864000 -18000 1 CDT}
+ {846399600 -21600 0 CST}
+ {860313600 -18000 1 CDT}
+ {877849200 -21600 0 CST}
+ {883634400 -21600 0 CST}
+ {891766800 -21600 0 MDT}
+ {909302400 -25200 0 MST}
+ {923216400 -21600 1 MDT}
+ {941356800 -25200 0 MST}
+ {954666000 -21600 1 MDT}
+ {972806400 -25200 0 MST}
+ {989139600 -21600 1 MDT}
+ {1001836800 -25200 0 MST}
+ {1018170000 -21600 1 MDT}
+ {1035705600 -25200 0 MST}
+ {1049619600 -21600 1 MDT}
+ {1067155200 -25200 0 MST}
+ {1081069200 -21600 1 MDT}
+ {1099209600 -25200 0 MST}
+ {1112518800 -21600 1 MDT}
+ {1130659200 -25200 0 MST}
+ {1143968400 -21600 1 MDT}
+ {1162108800 -25200 0 MST}
+ {1175418000 -21600 1 MDT}
+ {1193558400 -25200 0 MST}
+ {1207472400 -21600 1 MDT}
+ {1225008000 -25200 0 MST}
+ {1238922000 -21600 1 MDT}
+ {1256457600 -25200 0 MST}
+ {1270371600 -21600 1 MDT}
+ {1288512000 -25200 0 MST}
+ {1301821200 -21600 1 MDT}
+ {1319961600 -25200 0 MST}
+ {1333270800 -21600 1 MDT}
+ {1351411200 -25200 0 MST}
+ {1365325200 -21600 1 MDT}
+ {1382860800 -25200 0 MST}
+ {1396774800 -21600 1 MDT}
+ {1414310400 -25200 0 MST}
+ {1428224400 -21600 1 MDT}
+ {1445760000 -25200 0 MST}
+ {1459674000 -21600 1 MDT}
+ {1477814400 -25200 0 MST}
+ {1491123600 -21600 1 MDT}
+ {1509264000 -25200 0 MST}
+ {1522573200 -21600 1 MDT}
+ {1540713600 -25200 0 MST}
+ {1554627600 -21600 1 MDT}
+ {1572163200 -25200 0 MST}
+ {1586077200 -21600 1 MDT}
+ {1603612800 -25200 0 MST}
+ {1617526800 -21600 1 MDT}
+ {1635667200 -25200 0 MST}
+ {1648976400 -21600 1 MDT}
+ {1667116800 -25200 0 MST}
+ {1680426000 -21600 1 MDT}
+ {1698566400 -25200 0 MST}
+ {1712480400 -21600 1 MDT}
+ {1730016000 -25200 0 MST}
+ {1743930000 -21600 1 MDT}
+ {1761465600 -25200 0 MST}
+ {1775379600 -21600 1 MDT}
+ {1792915200 -25200 0 MST}
+ {1806829200 -21600 1 MDT}
+ {1824969600 -25200 0 MST}
+ {1838278800 -21600 1 MDT}
+ {1856419200 -25200 0 MST}
+ {1869728400 -21600 1 MDT}
+ {1887868800 -25200 0 MST}
+ {1901782800 -21600 1 MDT}
+ {1919318400 -25200 0 MST}
+ {1933232400 -21600 1 MDT}
+ {1950768000 -25200 0 MST}
+ {1964682000 -21600 1 MDT}
+ {1982822400 -25200 0 MST}
+ {1996131600 -21600 1 MDT}
+ {2014272000 -25200 0 MST}
+ {2027581200 -21600 1 MDT}
+ {2045721600 -25200 0 MST}
+ {2059030800 -21600 1 MDT}
+ {2077171200 -25200 0 MST}
+ {2091085200 -21600 1 MDT}
+ {2108620800 -25200 0 MST}
+ {2122534800 -21600 1 MDT}
+ {2140070400 -25200 0 MST}
+ {2153984400 -21600 1 MDT}
+ {2172124800 -25200 0 MST}
+ {2185434000 -21600 1 MDT}
+ {2203574400 -25200 0 MST}
+ {2216883600 -21600 1 MDT}
+ {2235024000 -25200 0 MST}
+ {2248938000 -21600 1 MDT}
+ {2266473600 -25200 0 MST}
+ {2280387600 -21600 1 MDT}
+ {2297923200 -25200 0 MST}
+ {2311837200 -21600 1 MDT}
+ {2329372800 -25200 0 MST}
+ {2343286800 -21600 1 MDT}
+ {2361427200 -25200 0 MST}
+ {2374736400 -21600 1 MDT}
+ {2392876800 -25200 0 MST}
+ {2406186000 -21600 1 MDT}
+ {2424326400 -25200 0 MST}
+ {2438240400 -21600 1 MDT}
+ {2455776000 -25200 0 MST}
+ {2469690000 -21600 1 MDT}
+ {2487225600 -25200 0 MST}
+ {2501139600 -21600 1 MDT}
+ {2519280000 -25200 0 MST}
+ {2532589200 -21600 1 MDT}
+ {2550729600 -25200 0 MST}
+ {2564038800 -21600 1 MDT}
+ {2582179200 -25200 0 MST}
+ {2596093200 -21600 1 MDT}
+ {2613628800 -25200 0 MST}
+ {2627542800 -21600 1 MDT}
+ {2645078400 -25200 0 MST}
+ {2658992400 -21600 1 MDT}
+ {2676528000 -25200 0 MST}
+ {2690442000 -21600 1 MDT}
+ {2708582400 -25200 0 MST}
+ {2721891600 -21600 1 MDT}
+ {2740032000 -25200 0 MST}
+ {2753341200 -21600 1 MDT}
+ {2771481600 -25200 0 MST}
+ {2785395600 -21600 1 MDT}
+ {2802931200 -25200 0 MST}
+ {2816845200 -21600 1 MDT}
+ {2834380800 -25200 0 MST}
+ {2848294800 -21600 1 MDT}
+ {2866435200 -25200 0 MST}
+ {2879744400 -21600 1 MDT}
+ {2897884800 -25200 0 MST}
+ {2911194000 -21600 1 MDT}
+ {2929334400 -25200 0 MST}
+ {2942643600 -21600 1 MDT}
+ {2960784000 -25200 0 MST}
+ {2974698000 -21600 1 MDT}
+ {2992233600 -25200 0 MST}
+ {3006147600 -21600 1 MDT}
+ {3023683200 -25200 0 MST}
+ {3037597200 -21600 1 MDT}
+ {3055737600 -25200 0 MST}
+ {3069046800 -21600 1 MDT}
+ {3087187200 -25200 0 MST}
+ {3100496400 -21600 1 MDT}
+ {3118636800 -25200 0 MST}
+ {3132550800 -21600 1 MDT}
+ {3150086400 -25200 0 MST}
+ {3164000400 -21600 1 MDT}
+ {3181536000 -25200 0 MST}
+ {3195450000 -21600 1 MDT}
+ {3212985600 -25200 0 MST}
+ {3226899600 -21600 1 MDT}
+ {3245040000 -25200 0 MST}
+ {3258349200 -21600 1 MDT}
+ {3276489600 -25200 0 MST}
+ {3289798800 -21600 1 MDT}
+ {3307939200 -25200 0 MST}
+ {3321853200 -21600 1 MDT}
+ {3339388800 -25200 0 MST}
+ {3353302800 -21600 1 MDT}
+ {3370838400 -25200 0 MST}
+ {3384752400 -21600 1 MDT}
+ {3402892800 -25200 0 MST}
+ {3416202000 -21600 1 MDT}
+ {3434342400 -25200 0 MST}
+ {3447651600 -21600 1 MDT}
+ {3465792000 -25200 0 MST}
+ {3479706000 -21600 1 MDT}
+ {3497241600 -25200 0 MST}
+ {3511155600 -21600 1 MDT}
+ {3528691200 -25200 0 MST}
+ {3542605200 -21600 1 MDT}
+ {3560140800 -25200 0 MST}
+ {3574054800 -21600 1 MDT}
+ {3592195200 -25200 0 MST}
+ {3605504400 -21600 1 MDT}
+ {3623644800 -25200 0 MST}
+ {3636954000 -21600 1 MDT}
+ {3655094400 -25200 0 MST}
+ {3669008400 -21600 1 MDT}
+ {3686544000 -25200 0 MST}
+ {3700458000 -21600 1 MDT}
+ {3717993600 -25200 0 MST}
+ {3731907600 -21600 1 MDT}
+ {3750048000 -25200 0 MST}
+ {3763357200 -21600 1 MDT}
+ {3781497600 -25200 0 MST}
+ {3794806800 -21600 1 MDT}
+ {3812947200 -25200 0 MST}
+ {3826256400 -21600 1 MDT}
+ {3844396800 -25200 0 MST}
+ {3858310800 -21600 1 MDT}
+ {3875846400 -25200 0 MST}
+ {3889760400 -21600 1 MDT}
+ {3907296000 -25200 0 MST}
+ {3921210000 -21600 1 MDT}
+ {3939350400 -25200 0 MST}
+ {3952659600 -21600 1 MDT}
+ {3970800000 -25200 0 MST}
+ {3984109200 -21600 1 MDT}
+ {4002249600 -25200 0 MST}
+ {4016163600 -21600 1 MDT}
+ {4033699200 -25200 0 MST}
+ {4047613200 -21600 1 MDT}
+ {4065148800 -25200 0 MST}
+ {4079062800 -21600 1 MDT}
+ {4096598400 -25200 0 MST}
+}
diff --git a/library/tzdata/America/Coral_Harbour b/library/tzdata/America/Coral_Harbour
new file mode 100644
index 0000000..a27dc03
--- /dev/null
+++ b/library/tzdata/America/Coral_Harbour
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Atikokan)]} {
+ LoadTimeZoneFile America/Atikokan
+}
+set TZData(:America/Coral_Harbour) $TZData(:America/Atikokan)
diff --git a/library/tzdata/America/Cordoba b/library/tzdata/America/Cordoba
new file mode 100644
index 0000000..c881558
--- /dev/null
+++ b/library/tzdata/America/Cordoba
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Argentina/Cordoba)]} {
+ LoadTimeZoneFile America/Argentina/Cordoba
+}
+set TZData(:America/Cordoba) $TZData(:America/Argentina/Cordoba)
diff --git a/library/tzdata/America/Costa_Rica b/library/tzdata/America/Costa_Rica
new file mode 100644
index 0000000..04420a4
--- /dev/null
+++ b/library/tzdata/America/Costa_Rica
@@ -0,0 +1,15 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Costa_Rica) {
+ {-9223372036854775808 -20180 0 LMT}
+ {-2524501420 -20180 0 SJMT}
+ {-1545071020 -21600 0 CST}
+ {288770400 -18000 1 CDT}
+ {297234000 -21600 0 CST}
+ {320220000 -18000 1 CDT}
+ {328683600 -21600 0 CST}
+ {664264800 -18000 1 CDT}
+ {678344400 -21600 0 CST}
+ {695714400 -18000 1 CDT}
+ {700635600 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Cuiaba b/library/tzdata/America/Cuiaba
new file mode 100644
index 0000000..0301862
--- /dev/null
+++ b/library/tzdata/America/Cuiaba
@@ -0,0 +1,257 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Cuiaba) {
+ {-9223372036854775808 -13460 0 LMT}
+ {-1767212140 -14400 0 AMT}
+ {-1206954000 -10800 1 AMST}
+ {-1191358800 -14400 0 AMT}
+ {-1175371200 -10800 1 AMST}
+ {-1159822800 -14400 0 AMT}
+ {-633816000 -10800 1 AMST}
+ {-622065600 -14400 0 AMT}
+ {-602280000 -10800 1 AMST}
+ {-591829200 -14400 0 AMT}
+ {-570744000 -10800 1 AMST}
+ {-560206800 -14400 0 AMT}
+ {-539121600 -10800 1 AMST}
+ {-531349200 -14400 0 AMT}
+ {-191361600 -10800 1 AMST}
+ {-184194000 -14400 0 AMT}
+ {-155160000 -10800 1 AMST}
+ {-150066000 -14400 0 AMT}
+ {-128894400 -10800 1 AMST}
+ {-121122000 -14400 0 AMT}
+ {-99950400 -10800 1 AMST}
+ {-89586000 -14400 0 AMT}
+ {-68414400 -10800 1 AMST}
+ {-57963600 -14400 0 AMT}
+ {499752000 -10800 1 AMST}
+ {511239600 -14400 0 AMT}
+ {530596800 -10800 1 AMST}
+ {540270000 -14400 0 AMT}
+ {562132800 -10800 1 AMST}
+ {571201200 -14400 0 AMT}
+ {592977600 -10800 1 AMST}
+ {602046000 -14400 0 AMT}
+ {624427200 -10800 1 AMST}
+ {634705200 -14400 0 AMT}
+ {656481600 -10800 1 AMST}
+ {666759600 -14400 0 AMT}
+ {687931200 -10800 1 AMST}
+ {697604400 -14400 0 AMT}
+ {719985600 -10800 1 AMST}
+ {728449200 -14400 0 AMT}
+ {750830400 -10800 1 AMST}
+ {761713200 -14400 0 AMT}
+ {782280000 -10800 1 AMST}
+ {793162800 -14400 0 AMT}
+ {813729600 -10800 1 AMST}
+ {824007600 -14400 0 AMT}
+ {844574400 -10800 1 AMST}
+ {856062000 -14400 0 AMT}
+ {876110400 -10800 1 AMST}
+ {888721200 -14400 0 AMT}
+ {908078400 -10800 1 AMST}
+ {919566000 -14400 0 AMT}
+ {938923200 -10800 1 AMST}
+ {951620400 -14400 0 AMT}
+ {970977600 -10800 1 AMST}
+ {982465200 -14400 0 AMT}
+ {1003032000 -10800 1 AMST}
+ {1013914800 -14400 0 AMT}
+ {1036296000 -10800 1 AMST}
+ {1045364400 -14400 0 AMT}
+ {1064372400 -14400 0 AMT}
+ {1096603200 -14400 0 AMT}
+ {1099368000 -10800 1 AMST}
+ {1108868400 -14400 0 AMT}
+ {1129435200 -10800 1 AMST}
+ {1140318000 -14400 0 AMT}
+ {1162699200 -10800 1 AMST}
+ {1172372400 -14400 0 AMT}
+ {1192334400 -10800 1 AMST}
+ {1203217200 -14400 0 AMT}
+ {1224388800 -10800 1 AMST}
+ {1234666800 -14400 0 AMT}
+ {1255838400 -10800 1 AMST}
+ {1266721200 -14400 0 AMT}
+ {1287288000 -10800 1 AMST}
+ {1298170800 -14400 0 AMT}
+ {1318737600 -10800 1 AMST}
+ {1330225200 -14400 0 AMT}
+ {1350792000 -10800 1 AMST}
+ {1361070000 -14400 0 AMT}
+ {1382241600 -10800 1 AMST}
+ {1392519600 -14400 0 AMT}
+ {1413691200 -10800 1 AMST}
+ {1424574000 -14400 0 AMT}
+ {1445140800 -10800 1 AMST}
+ {1456023600 -14400 0 AMT}
+ {1476590400 -10800 1 AMST}
+ {1487473200 -14400 0 AMT}
+ {1508040000 -10800 1 AMST}
+ {1518922800 -14400 0 AMT}
+ {1540094400 -10800 1 AMST}
+ {1550372400 -14400 0 AMT}
+ {1571544000 -10800 1 AMST}
+ {1581822000 -14400 0 AMT}
+ {1602993600 -10800 1 AMST}
+ {1613876400 -14400 0 AMT}
+ {1634443200 -10800 1 AMST}
+ {1645326000 -14400 0 AMT}
+ {1665892800 -10800 1 AMST}
+ {1677380400 -14400 0 AMT}
+ {1697342400 -10800 1 AMST}
+ {1708225200 -14400 0 AMT}
+ {1729396800 -10800 1 AMST}
+ {1739674800 -14400 0 AMT}
+ {1760846400 -10800 1 AMST}
+ {1771729200 -14400 0 AMT}
+ {1792296000 -10800 1 AMST}
+ {1803178800 -14400 0 AMT}
+ {1823745600 -10800 1 AMST}
+ {1834628400 -14400 0 AMT}
+ {1855195200 -10800 1 AMST}
+ {1866078000 -14400 0 AMT}
+ {1887249600 -10800 1 AMST}
+ {1897527600 -14400 0 AMT}
+ {1918699200 -10800 1 AMST}
+ {1928977200 -14400 0 AMT}
+ {1950148800 -10800 1 AMST}
+ {1960426800 -14400 0 AMT}
+ {1981598400 -10800 1 AMST}
+ {1992481200 -14400 0 AMT}
+ {2013048000 -10800 1 AMST}
+ {2024535600 -14400 0 AMT}
+ {2044497600 -10800 1 AMST}
+ {2055380400 -14400 0 AMT}
+ {2076552000 -10800 1 AMST}
+ {2086830000 -14400 0 AMT}
+ {2108001600 -10800 1 AMST}
+ {2118884400 -14400 0 AMT}
+ {2139451200 -10800 1 AMST}
+ {2150334000 -14400 0 AMT}
+ {2170900800 -10800 1 AMST}
+ {2181783600 -14400 0 AMT}
+ {2202350400 -10800 1 AMST}
+ {2213233200 -14400 0 AMT}
+ {2234404800 -10800 1 AMST}
+ {2244682800 -14400 0 AMT}
+ {2265854400 -10800 1 AMST}
+ {2276132400 -14400 0 AMT}
+ {2297304000 -10800 1 AMST}
+ {2307582000 -14400 0 AMT}
+ {2328753600 -10800 1 AMST}
+ {2339636400 -14400 0 AMT}
+ {2360203200 -10800 1 AMST}
+ {2371086000 -14400 0 AMT}
+ {2391652800 -10800 1 AMST}
+ {2402535600 -14400 0 AMT}
+ {2423707200 -10800 1 AMST}
+ {2433985200 -14400 0 AMT}
+ {2455156800 -10800 1 AMST}
+ {2465434800 -14400 0 AMT}
+ {2486606400 -10800 1 AMST}
+ {2497489200 -14400 0 AMT}
+ {2518056000 -10800 1 AMST}
+ {2528938800 -14400 0 AMT}
+ {2549505600 -10800 1 AMST}
+ {2560388400 -14400 0 AMT}
+ {2580955200 -10800 1 AMST}
+ {2591838000 -14400 0 AMT}
+ {2613009600 -10800 1 AMST}
+ {2623287600 -14400 0 AMT}
+ {2644459200 -10800 1 AMST}
+ {2654737200 -14400 0 AMT}
+ {2675908800 -10800 1 AMST}
+ {2686791600 -14400 0 AMT}
+ {2707358400 -10800 1 AMST}
+ {2718241200 -14400 0 AMT}
+ {2738808000 -10800 1 AMST}
+ {2749690800 -14400 0 AMT}
+ {2770862400 -10800 1 AMST}
+ {2781140400 -14400 0 AMT}
+ {2802312000 -10800 1 AMST}
+ {2812590000 -14400 0 AMT}
+ {2833761600 -10800 1 AMST}
+ {2844039600 -14400 0 AMT}
+ {2865211200 -10800 1 AMST}
+ {2876094000 -14400 0 AMT}
+ {2896660800 -10800 1 AMST}
+ {2907543600 -14400 0 AMT}
+ {2928110400 -10800 1 AMST}
+ {2938993200 -14400 0 AMT}
+ {2960164800 -10800 1 AMST}
+ {2970442800 -14400 0 AMT}
+ {2991614400 -10800 1 AMST}
+ {3001892400 -14400 0 AMT}
+ {3023064000 -10800 1 AMST}
+ {3033946800 -14400 0 AMT}
+ {3054513600 -10800 1 AMST}
+ {3065396400 -14400 0 AMT}
+ {3085963200 -10800 1 AMST}
+ {3096846000 -14400 0 AMT}
+ {3118017600 -10800 1 AMST}
+ {3128295600 -14400 0 AMT}
+ {3149467200 -10800 1 AMST}
+ {3159745200 -14400 0 AMT}
+ {3180916800 -10800 1 AMST}
+ {3191194800 -14400 0 AMT}
+ {3212366400 -10800 1 AMST}
+ {3223249200 -14400 0 AMT}
+ {3243816000 -10800 1 AMST}
+ {3254698800 -14400 0 AMT}
+ {3275265600 -10800 1 AMST}
+ {3286148400 -14400 0 AMT}
+ {3307320000 -10800 1 AMST}
+ {3317598000 -14400 0 AMT}
+ {3338769600 -10800 1 AMST}
+ {3349047600 -14400 0 AMT}
+ {3370219200 -10800 1 AMST}
+ {3381102000 -14400 0 AMT}
+ {3401668800 -10800 1 AMST}
+ {3412551600 -14400 0 AMT}
+ {3433118400 -10800 1 AMST}
+ {3444001200 -14400 0 AMT}
+ {3464568000 -10800 1 AMST}
+ {3475450800 -14400 0 AMT}
+ {3496622400 -10800 1 AMST}
+ {3506900400 -14400 0 AMT}
+ {3528072000 -10800 1 AMST}
+ {3538350000 -14400 0 AMT}
+ {3559521600 -10800 1 AMST}
+ {3570404400 -14400 0 AMT}
+ {3590971200 -10800 1 AMST}
+ {3601854000 -14400 0 AMT}
+ {3622420800 -10800 1 AMST}
+ {3633303600 -14400 0 AMT}
+ {3654475200 -10800 1 AMST}
+ {3664753200 -14400 0 AMT}
+ {3685924800 -10800 1 AMST}
+ {3696202800 -14400 0 AMT}
+ {3717374400 -10800 1 AMST}
+ {3727652400 -14400 0 AMT}
+ {3748824000 -10800 1 AMST}
+ {3759706800 -14400 0 AMT}
+ {3780273600 -10800 1 AMST}
+ {3791156400 -14400 0 AMT}
+ {3811723200 -10800 1 AMST}
+ {3822606000 -14400 0 AMT}
+ {3843777600 -10800 1 AMST}
+ {3854055600 -14400 0 AMT}
+ {3875227200 -10800 1 AMST}
+ {3885505200 -14400 0 AMT}
+ {3906676800 -10800 1 AMST}
+ {3917559600 -14400 0 AMT}
+ {3938126400 -10800 1 AMST}
+ {3949009200 -14400 0 AMT}
+ {3969576000 -10800 1 AMST}
+ {3980458800 -14400 0 AMT}
+ {4001630400 -10800 1 AMST}
+ {4011908400 -14400 0 AMT}
+ {4033080000 -10800 1 AMST}
+ {4043358000 -14400 0 AMT}
+ {4064529600 -10800 1 AMST}
+ {4074807600 -14400 0 AMT}
+ {4095979200 -10800 1 AMST}
+}
diff --git a/library/tzdata/America/Curacao b/library/tzdata/America/Curacao
new file mode 100644
index 0000000..443a319
--- /dev/null
+++ b/library/tzdata/America/Curacao
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Curacao) {
+ {-9223372036854775808 -16544 0 LMT}
+ {-1826738656 -16200 0 ANT}
+ {-157750200 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Danmarkshavn b/library/tzdata/America/Danmarkshavn
new file mode 100644
index 0000000..8d66d3a
--- /dev/null
+++ b/library/tzdata/America/Danmarkshavn
@@ -0,0 +1,39 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Danmarkshavn) {
+ {-9223372036854775808 -4480 0 LMT}
+ {-1686091520 -10800 0 WGT}
+ {323845200 -7200 0 WGST}
+ {338950800 -10800 0 WGT}
+ {354675600 -7200 1 WGST}
+ {370400400 -10800 0 WGT}
+ {386125200 -7200 1 WGST}
+ {401850000 -10800 0 WGT}
+ {417574800 -7200 1 WGST}
+ {433299600 -10800 0 WGT}
+ {449024400 -7200 1 WGST}
+ {465354000 -10800 0 WGT}
+ {481078800 -7200 1 WGST}
+ {496803600 -10800 0 WGT}
+ {512528400 -7200 1 WGST}
+ {528253200 -10800 0 WGT}
+ {543978000 -7200 1 WGST}
+ {559702800 -10800 0 WGT}
+ {575427600 -7200 1 WGST}
+ {591152400 -10800 0 WGT}
+ {606877200 -7200 1 WGST}
+ {622602000 -10800 0 WGT}
+ {638326800 -7200 1 WGST}
+ {654656400 -10800 0 WGT}
+ {670381200 -7200 1 WGST}
+ {686106000 -10800 0 WGT}
+ {701830800 -7200 1 WGST}
+ {717555600 -10800 0 WGT}
+ {733280400 -7200 1 WGST}
+ {749005200 -10800 0 WGT}
+ {764730000 -7200 1 WGST}
+ {780454800 -10800 0 WGT}
+ {796179600 -7200 1 WGST}
+ {811904400 -10800 0 WGT}
+ {820465200 0 0 GMT}
+}
diff --git a/library/tzdata/America/Dawson b/library/tzdata/America/Dawson
new file mode 100644
index 0000000..8d2b641
--- /dev/null
+++ b/library/tzdata/America/Dawson
@@ -0,0 +1,256 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Dawson) {
+ {-9223372036854775808 -33460 0 LMT}
+ {-2188996940 -32400 0 YST}
+ {-1632056400 -28800 1 YDT}
+ {-1615125600 -32400 0 YST}
+ {-1596978000 -28800 1 YDT}
+ {-1583164800 -32400 0 YST}
+ {-880203600 -28800 1 YWT}
+ {-769395600 -28800 1 YPT}
+ {-765381600 -32400 0 YST}
+ {-147884400 -25200 1 YDDT}
+ {-131554800 -32400 0 YST}
+ {315561600 -28800 0 PST}
+ {325677600 -25200 1 PDT}
+ {341398800 -28800 0 PST}
+ {357127200 -25200 1 PDT}
+ {372848400 -28800 0 PST}
+ {388576800 -25200 1 PDT}
+ {404902800 -28800 0 PST}
+ {420026400 -25200 1 PDT}
+ {436352400 -28800 0 PST}
+ {452080800 -25200 1 PDT}
+ {467802000 -28800 0 PST}
+ {483530400 -25200 1 PDT}
+ {499251600 -28800 0 PST}
+ {514980000 -25200 1 PDT}
+ {530701200 -28800 0 PST}
+ {544615200 -25200 1 PDT}
+ {562150800 -28800 0 PST}
+ {576064800 -25200 1 PDT}
+ {594205200 -28800 0 PST}
+ {607514400 -25200 1 PDT}
+ {625654800 -28800 0 PST}
+ {638964000 -25200 1 PDT}
+ {657104400 -28800 0 PST}
+ {671018400 -25200 1 PDT}
+ {688554000 -28800 0 PST}
+ {702468000 -25200 1 PDT}
+ {720003600 -28800 0 PST}
+ {733917600 -25200 1 PDT}
+ {752058000 -28800 0 PST}
+ {765367200 -25200 1 PDT}
+ {783507600 -28800 0 PST}
+ {796816800 -25200 1 PDT}
+ {814957200 -28800 0 PST}
+ {828871200 -25200 1 PDT}
+ {846406800 -28800 0 PST}
+ {860320800 -25200 1 PDT}
+ {877856400 -28800 0 PST}
+ {891770400 -25200 1 PDT}
+ {909306000 -28800 0 PST}
+ {923220000 -25200 1 PDT}
+ {941360400 -28800 0 PST}
+ {954669600 -25200 1 PDT}
+ {972810000 -28800 0 PST}
+ {986119200 -25200 1 PDT}
+ {1004259600 -28800 0 PST}
+ {1018173600 -25200 1 PDT}
+ {1035709200 -28800 0 PST}
+ {1049623200 -25200 1 PDT}
+ {1067158800 -28800 0 PST}
+ {1081072800 -25200 1 PDT}
+ {1099213200 -28800 0 PST}
+ {1112522400 -25200 1 PDT}
+ {1130662800 -28800 0 PST}
+ {1143972000 -25200 1 PDT}
+ {1162112400 -28800 0 PST}
+ {1173607200 -25200 1 PDT}
+ {1194166800 -28800 0 PST}
+ {1205056800 -25200 1 PDT}
+ {1225616400 -28800 0 PST}
+ {1236506400 -25200 1 PDT}
+ {1257066000 -28800 0 PST}
+ {1268560800 -25200 1 PDT}
+ {1289120400 -28800 0 PST}
+ {1300010400 -25200 1 PDT}
+ {1320570000 -28800 0 PST}
+ {1331460000 -25200 1 PDT}
+ {1352019600 -28800 0 PST}
+ {1362909600 -25200 1 PDT}
+ {1383469200 -28800 0 PST}
+ {1394359200 -25200 1 PDT}
+ {1414918800 -28800 0 PST}
+ {1425808800 -25200 1 PDT}
+ {1446368400 -28800 0 PST}
+ {1457863200 -25200 1 PDT}
+ {1478422800 -28800 0 PST}
+ {1489312800 -25200 1 PDT}
+ {1509872400 -28800 0 PST}
+ {1520762400 -25200 1 PDT}
+ {1541322000 -28800 0 PST}
+ {1552212000 -25200 1 PDT}
+ {1572771600 -28800 0 PST}
+ {1583661600 -25200 1 PDT}
+ {1604221200 -28800 0 PST}
+ {1615716000 -25200 1 PDT}
+ {1636275600 -28800 0 PST}
+ {1647165600 -25200 1 PDT}
+ {1667725200 -28800 0 PST}
+ {1678615200 -25200 1 PDT}
+ {1699174800 -28800 0 PST}
+ {1710064800 -25200 1 PDT}
+ {1730624400 -28800 0 PST}
+ {1741514400 -25200 1 PDT}
+ {1762074000 -28800 0 PST}
+ {1772964000 -25200 1 PDT}
+ {1793523600 -28800 0 PST}
+ {1805018400 -25200 1 PDT}
+ {1825578000 -28800 0 PST}
+ {1836468000 -25200 1 PDT}
+ {1857027600 -28800 0 PST}
+ {1867917600 -25200 1 PDT}
+ {1888477200 -28800 0 PST}
+ {1899367200 -25200 1 PDT}
+ {1919926800 -28800 0 PST}
+ {1930816800 -25200 1 PDT}
+ {1951376400 -28800 0 PST}
+ {1962871200 -25200 1 PDT}
+ {1983430800 -28800 0 PST}
+ {1994320800 -25200 1 PDT}
+ {2014880400 -28800 0 PST}
+ {2025770400 -25200 1 PDT}
+ {2046330000 -28800 0 PST}
+ {2057220000 -25200 1 PDT}
+ {2077779600 -28800 0 PST}
+ {2088669600 -25200 1 PDT}
+ {2109229200 -28800 0 PST}
+ {2120119200 -25200 1 PDT}
+ {2140678800 -28800 0 PST}
+ {2152173600 -25200 1 PDT}
+ {2172733200 -28800 0 PST}
+ {2183623200 -25200 1 PDT}
+ {2204182800 -28800 0 PST}
+ {2215072800 -25200 1 PDT}
+ {2235632400 -28800 0 PST}
+ {2246522400 -25200 1 PDT}
+ {2267082000 -28800 0 PST}
+ {2277972000 -25200 1 PDT}
+ {2298531600 -28800 0 PST}
+ {2309421600 -25200 1 PDT}
+ {2329981200 -28800 0 PST}
+ {2341476000 -25200 1 PDT}
+ {2362035600 -28800 0 PST}
+ {2372925600 -25200 1 PDT}
+ {2393485200 -28800 0 PST}
+ {2404375200 -25200 1 PDT}
+ {2424934800 -28800 0 PST}
+ {2435824800 -25200 1 PDT}
+ {2456384400 -28800 0 PST}
+ {2467274400 -25200 1 PDT}
+ {2487834000 -28800 0 PST}
+ {2499328800 -25200 1 PDT}
+ {2519888400 -28800 0 PST}
+ {2530778400 -25200 1 PDT}
+ {2551338000 -28800 0 PST}
+ {2562228000 -25200 1 PDT}
+ {2582787600 -28800 0 PST}
+ {2593677600 -25200 1 PDT}
+ {2614237200 -28800 0 PST}
+ {2625127200 -25200 1 PDT}
+ {2645686800 -28800 0 PST}
+ {2656576800 -25200 1 PDT}
+ {2677136400 -28800 0 PST}
+ {2688631200 -25200 1 PDT}
+ {2709190800 -28800 0 PST}
+ {2720080800 -25200 1 PDT}
+ {2740640400 -28800 0 PST}
+ {2751530400 -25200 1 PDT}
+ {2772090000 -28800 0 PST}
+ {2782980000 -25200 1 PDT}
+ {2803539600 -28800 0 PST}
+ {2814429600 -25200 1 PDT}
+ {2834989200 -28800 0 PST}
+ {2846484000 -25200 1 PDT}
+ {2867043600 -28800 0 PST}
+ {2877933600 -25200 1 PDT}
+ {2898493200 -28800 0 PST}
+ {2909383200 -25200 1 PDT}
+ {2929942800 -28800 0 PST}
+ {2940832800 -25200 1 PDT}
+ {2961392400 -28800 0 PST}
+ {2972282400 -25200 1 PDT}
+ {2992842000 -28800 0 PST}
+ {3003732000 -25200 1 PDT}
+ {3024291600 -28800 0 PST}
+ {3035786400 -25200 1 PDT}
+ {3056346000 -28800 0 PST}
+ {3067236000 -25200 1 PDT}
+ {3087795600 -28800 0 PST}
+ {3098685600 -25200 1 PDT}
+ {3119245200 -28800 0 PST}
+ {3130135200 -25200 1 PDT}
+ {3150694800 -28800 0 PST}
+ {3161584800 -25200 1 PDT}
+ {3182144400 -28800 0 PST}
+ {3193034400 -25200 1 PDT}
+ {3213594000 -28800 0 PST}
+ {3225088800 -25200 1 PDT}
+ {3245648400 -28800 0 PST}
+ {3256538400 -25200 1 PDT}
+ {3277098000 -28800 0 PST}
+ {3287988000 -25200 1 PDT}
+ {3308547600 -28800 0 PST}
+ {3319437600 -25200 1 PDT}
+ {3339997200 -28800 0 PST}
+ {3350887200 -25200 1 PDT}
+ {3371446800 -28800 0 PST}
+ {3382941600 -25200 1 PDT}
+ {3403501200 -28800 0 PST}
+ {3414391200 -25200 1 PDT}
+ {3434950800 -28800 0 PST}
+ {3445840800 -25200 1 PDT}
+ {3466400400 -28800 0 PST}
+ {3477290400 -25200 1 PDT}
+ {3497850000 -28800 0 PST}
+ {3508740000 -25200 1 PDT}
+ {3529299600 -28800 0 PST}
+ {3540189600 -25200 1 PDT}
+ {3560749200 -28800 0 PST}
+ {3572244000 -25200 1 PDT}
+ {3592803600 -28800 0 PST}
+ {3603693600 -25200 1 PDT}
+ {3624253200 -28800 0 PST}
+ {3635143200 -25200 1 PDT}
+ {3655702800 -28800 0 PST}
+ {3666592800 -25200 1 PDT}
+ {3687152400 -28800 0 PST}
+ {3698042400 -25200 1 PDT}
+ {3718602000 -28800 0 PST}
+ {3730096800 -25200 1 PDT}
+ {3750656400 -28800 0 PST}
+ {3761546400 -25200 1 PDT}
+ {3782106000 -28800 0 PST}
+ {3792996000 -25200 1 PDT}
+ {3813555600 -28800 0 PST}
+ {3824445600 -25200 1 PDT}
+ {3845005200 -28800 0 PST}
+ {3855895200 -25200 1 PDT}
+ {3876454800 -28800 0 PST}
+ {3887344800 -25200 1 PDT}
+ {3907904400 -28800 0 PST}
+ {3919399200 -25200 1 PDT}
+ {3939958800 -28800 0 PST}
+ {3950848800 -25200 1 PDT}
+ {3971408400 -28800 0 PST}
+ {3982298400 -25200 1 PDT}
+ {4002858000 -28800 0 PST}
+ {4013748000 -25200 1 PDT}
+ {4034307600 -28800 0 PST}
+ {4045197600 -25200 1 PDT}
+ {4065757200 -28800 0 PST}
+ {4076647200 -25200 1 PDT}
+ {4097206800 -28800 0 PST}
+}
diff --git a/library/tzdata/America/Dawson_Creek b/library/tzdata/America/Dawson_Creek
new file mode 100644
index 0000000..9f8c921
--- /dev/null
+++ b/library/tzdata/America/Dawson_Creek
@@ -0,0 +1,64 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Dawson_Creek) {
+ {-9223372036854775808 -28856 0 LMT}
+ {-2713881544 -28800 0 PST}
+ {-1632060000 -25200 1 PDT}
+ {-1614783600 -28800 0 PST}
+ {-880207200 -25200 1 PWT}
+ {-769395600 -25200 1 PPT}
+ {-765385200 -28800 0 PST}
+ {-725817600 -28800 0 PST}
+ {-715788000 -25200 1 PDT}
+ {-702486000 -28800 0 PST}
+ {-684338400 -25200 1 PDT}
+ {-671036400 -28800 0 PST}
+ {-652888800 -25200 1 PDT}
+ {-639586800 -28800 0 PST}
+ {-620834400 -25200 1 PDT}
+ {-608137200 -28800 0 PST}
+ {-589384800 -25200 1 PDT}
+ {-576082800 -28800 0 PST}
+ {-557935200 -25200 1 PDT}
+ {-544633200 -28800 0 PST}
+ {-526485600 -25200 1 PDT}
+ {-513183600 -28800 0 PST}
+ {-495036000 -25200 1 PDT}
+ {-481734000 -28800 0 PST}
+ {-463586400 -25200 1 PDT}
+ {-450284400 -28800 0 PST}
+ {-431532000 -25200 1 PDT}
+ {-418230000 -28800 0 PST}
+ {-400082400 -25200 1 PDT}
+ {-386780400 -28800 0 PST}
+ {-368632800 -25200 1 PDT}
+ {-355330800 -28800 0 PST}
+ {-337183200 -25200 1 PDT}
+ {-323881200 -28800 0 PST}
+ {-305733600 -25200 1 PDT}
+ {-292431600 -28800 0 PST}
+ {-273679200 -25200 1 PDT}
+ {-260982000 -28800 0 PST}
+ {-242229600 -25200 1 PDT}
+ {-226508400 -28800 0 PST}
+ {-210780000 -25200 1 PDT}
+ {-195058800 -28800 0 PST}
+ {-179330400 -25200 1 PDT}
+ {-163609200 -28800 0 PST}
+ {-147880800 -25200 1 PDT}
+ {-131554800 -28800 0 PST}
+ {-116431200 -25200 1 PDT}
+ {-100105200 -28800 0 PST}
+ {-84376800 -25200 1 PDT}
+ {-68655600 -28800 0 PST}
+ {-52927200 -25200 1 PDT}
+ {-37206000 -28800 0 PST}
+ {-21477600 -25200 1 PDT}
+ {-5756400 -28800 0 PST}
+ {9972000 -25200 1 PDT}
+ {25693200 -28800 0 PST}
+ {41421600 -25200 1 PDT}
+ {57747600 -28800 0 PST}
+ {73476000 -25200 1 PDT}
+ {84016800 -25200 0 MST}
+}
diff --git a/library/tzdata/America/Denver b/library/tzdata/America/Denver
new file mode 100644
index 0000000..06bc80d
--- /dev/null
+++ b/library/tzdata/America/Denver
@@ -0,0 +1,291 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Denver) {
+ {-9223372036854775808 -25196 0 LMT}
+ {-2717643600 -25200 0 MST}
+ {-1633273200 -21600 1 MDT}
+ {-1615132800 -25200 0 MST}
+ {-1601823600 -21600 1 MDT}
+ {-1583683200 -25200 0 MST}
+ {-1577898000 -25200 0 MST}
+ {-1570374000 -21600 1 MDT}
+ {-1551628800 -25200 0 MST}
+ {-1538924400 -21600 1 MDT}
+ {-1534089600 -25200 0 MST}
+ {-883587600 -25200 0 MST}
+ {-880210800 -21600 1 MWT}
+ {-769395600 -21600 1 MPT}
+ {-765388800 -25200 0 MST}
+ {-757357200 -25200 0 MST}
+ {-147884400 -21600 1 MDT}
+ {-131558400 -25200 0 MST}
+ {-116434800 -21600 1 MDT}
+ {-100108800 -25200 0 MST}
+ {-94669200 -25200 0 MST}
+ {-84380400 -21600 1 MDT}
+ {-68659200 -25200 0 MST}
+ {-52930800 -21600 1 MDT}
+ {-37209600 -25200 0 MST}
+ {-21481200 -21600 1 MDT}
+ {-5760000 -25200 0 MST}
+ {9968400 -21600 1 MDT}
+ {25689600 -25200 0 MST}
+ {41418000 -21600 1 MDT}
+ {57744000 -25200 0 MST}
+ {73472400 -21600 1 MDT}
+ {89193600 -25200 0 MST}
+ {104922000 -21600 1 MDT}
+ {120643200 -25200 0 MST}
+ {126694800 -21600 1 MDT}
+ {152092800 -25200 0 MST}
+ {162378000 -21600 1 MDT}
+ {183542400 -25200 0 MST}
+ {199270800 -21600 1 MDT}
+ {215596800 -25200 0 MST}
+ {230720400 -21600 1 MDT}
+ {247046400 -25200 0 MST}
+ {262774800 -21600 1 MDT}
+ {278496000 -25200 0 MST}
+ {294224400 -21600 1 MDT}
+ {309945600 -25200 0 MST}
+ {325674000 -21600 1 MDT}
+ {341395200 -25200 0 MST}
+ {357123600 -21600 1 MDT}
+ {372844800 -25200 0 MST}
+ {388573200 -21600 1 MDT}
+ {404899200 -25200 0 MST}
+ {420022800 -21600 1 MDT}
+ {436348800 -25200 0 MST}
+ {452077200 -21600 1 MDT}
+ {467798400 -25200 0 MST}
+ {483526800 -21600 1 MDT}
+ {499248000 -25200 0 MST}
+ {514976400 -21600 1 MDT}
+ {530697600 -25200 0 MST}
+ {544611600 -21600 1 MDT}
+ {562147200 -25200 0 MST}
+ {576061200 -21600 1 MDT}
+ {594201600 -25200 0 MST}
+ {607510800 -21600 1 MDT}
+ {625651200 -25200 0 MST}
+ {638960400 -21600 1 MDT}
+ {657100800 -25200 0 MST}
+ {671014800 -21600 1 MDT}
+ {688550400 -25200 0 MST}
+ {702464400 -21600 1 MDT}
+ {720000000 -25200 0 MST}
+ {733914000 -21600 1 MDT}
+ {752054400 -25200 0 MST}
+ {765363600 -21600 1 MDT}
+ {783504000 -25200 0 MST}
+ {796813200 -21600 1 MDT}
+ {814953600 -25200 0 MST}
+ {828867600 -21600 1 MDT}
+ {846403200 -25200 0 MST}
+ {860317200 -21600 1 MDT}
+ {877852800 -25200 0 MST}
+ {891766800 -21600 1 MDT}
+ {909302400 -25200 0 MST}
+ {923216400 -21600 1 MDT}
+ {941356800 -25200 0 MST}
+ {954666000 -21600 1 MDT}
+ {972806400 -25200 0 MST}
+ {986115600 -21600 1 MDT}
+ {1004256000 -25200 0 MST}
+ {1018170000 -21600 1 MDT}
+ {1035705600 -25200 0 MST}
+ {1049619600 -21600 1 MDT}
+ {1067155200 -25200 0 MST}
+ {1081069200 -21600 1 MDT}
+ {1099209600 -25200 0 MST}
+ {1112518800 -21600 1 MDT}
+ {1130659200 -25200 0 MST}
+ {1143968400 -21600 1 MDT}
+ {1162108800 -25200 0 MST}
+ {1173603600 -21600 1 MDT}
+ {1194163200 -25200 0 MST}
+ {1205053200 -21600 1 MDT}
+ {1225612800 -25200 0 MST}
+ {1236502800 -21600 1 MDT}
+ {1257062400 -25200 0 MST}
+ {1268557200 -21600 1 MDT}
+ {1289116800 -25200 0 MST}
+ {1300006800 -21600 1 MDT}
+ {1320566400 -25200 0 MST}
+ {1331456400 -21600 1 MDT}
+ {1352016000 -25200 0 MST}
+ {1362906000 -21600 1 MDT}
+ {1383465600 -25200 0 MST}
+ {1394355600 -21600 1 MDT}
+ {1414915200 -25200 0 MST}
+ {1425805200 -21600 1 MDT}
+ {1446364800 -25200 0 MST}
+ {1457859600 -21600 1 MDT}
+ {1478419200 -25200 0 MST}
+ {1489309200 -21600 1 MDT}
+ {1509868800 -25200 0 MST}
+ {1520758800 -21600 1 MDT}
+ {1541318400 -25200 0 MST}
+ {1552208400 -21600 1 MDT}
+ {1572768000 -25200 0 MST}
+ {1583658000 -21600 1 MDT}
+ {1604217600 -25200 0 MST}
+ {1615712400 -21600 1 MDT}
+ {1636272000 -25200 0 MST}
+ {1647162000 -21600 1 MDT}
+ {1667721600 -25200 0 MST}
+ {1678611600 -21600 1 MDT}
+ {1699171200 -25200 0 MST}
+ {1710061200 -21600 1 MDT}
+ {1730620800 -25200 0 MST}
+ {1741510800 -21600 1 MDT}
+ {1762070400 -25200 0 MST}
+ {1772960400 -21600 1 MDT}
+ {1793520000 -25200 0 MST}
+ {1805014800 -21600 1 MDT}
+ {1825574400 -25200 0 MST}
+ {1836464400 -21600 1 MDT}
+ {1857024000 -25200 0 MST}
+ {1867914000 -21600 1 MDT}
+ {1888473600 -25200 0 MST}
+ {1899363600 -21600 1 MDT}
+ {1919923200 -25200 0 MST}
+ {1930813200 -21600 1 MDT}
+ {1951372800 -25200 0 MST}
+ {1962867600 -21600 1 MDT}
+ {1983427200 -25200 0 MST}
+ {1994317200 -21600 1 MDT}
+ {2014876800 -25200 0 MST}
+ {2025766800 -21600 1 MDT}
+ {2046326400 -25200 0 MST}
+ {2057216400 -21600 1 MDT}
+ {2077776000 -25200 0 MST}
+ {2088666000 -21600 1 MDT}
+ {2109225600 -25200 0 MST}
+ {2120115600 -21600 1 MDT}
+ {2140675200 -25200 0 MST}
+ {2152170000 -21600 1 MDT}
+ {2172729600 -25200 0 MST}
+ {2183619600 -21600 1 MDT}
+ {2204179200 -25200 0 MST}
+ {2215069200 -21600 1 MDT}
+ {2235628800 -25200 0 MST}
+ {2246518800 -21600 1 MDT}
+ {2267078400 -25200 0 MST}
+ {2277968400 -21600 1 MDT}
+ {2298528000 -25200 0 MST}
+ {2309418000 -21600 1 MDT}
+ {2329977600 -25200 0 MST}
+ {2341472400 -21600 1 MDT}
+ {2362032000 -25200 0 MST}
+ {2372922000 -21600 1 MDT}
+ {2393481600 -25200 0 MST}
+ {2404371600 -21600 1 MDT}
+ {2424931200 -25200 0 MST}
+ {2435821200 -21600 1 MDT}
+ {2456380800 -25200 0 MST}
+ {2467270800 -21600 1 MDT}
+ {2487830400 -25200 0 MST}
+ {2499325200 -21600 1 MDT}
+ {2519884800 -25200 0 MST}
+ {2530774800 -21600 1 MDT}
+ {2551334400 -25200 0 MST}
+ {2562224400 -21600 1 MDT}
+ {2582784000 -25200 0 MST}
+ {2593674000 -21600 1 MDT}
+ {2614233600 -25200 0 MST}
+ {2625123600 -21600 1 MDT}
+ {2645683200 -25200 0 MST}
+ {2656573200 -21600 1 MDT}
+ {2677132800 -25200 0 MST}
+ {2688627600 -21600 1 MDT}
+ {2709187200 -25200 0 MST}
+ {2720077200 -21600 1 MDT}
+ {2740636800 -25200 0 MST}
+ {2751526800 -21600 1 MDT}
+ {2772086400 -25200 0 MST}
+ {2782976400 -21600 1 MDT}
+ {2803536000 -25200 0 MST}
+ {2814426000 -21600 1 MDT}
+ {2834985600 -25200 0 MST}
+ {2846480400 -21600 1 MDT}
+ {2867040000 -25200 0 MST}
+ {2877930000 -21600 1 MDT}
+ {2898489600 -25200 0 MST}
+ {2909379600 -21600 1 MDT}
+ {2929939200 -25200 0 MST}
+ {2940829200 -21600 1 MDT}
+ {2961388800 -25200 0 MST}
+ {2972278800 -21600 1 MDT}
+ {2992838400 -25200 0 MST}
+ {3003728400 -21600 1 MDT}
+ {3024288000 -25200 0 MST}
+ {3035782800 -21600 1 MDT}
+ {3056342400 -25200 0 MST}
+ {3067232400 -21600 1 MDT}
+ {3087792000 -25200 0 MST}
+ {3098682000 -21600 1 MDT}
+ {3119241600 -25200 0 MST}
+ {3130131600 -21600 1 MDT}
+ {3150691200 -25200 0 MST}
+ {3161581200 -21600 1 MDT}
+ {3182140800 -25200 0 MST}
+ {3193030800 -21600 1 MDT}
+ {3213590400 -25200 0 MST}
+ {3225085200 -21600 1 MDT}
+ {3245644800 -25200 0 MST}
+ {3256534800 -21600 1 MDT}
+ {3277094400 -25200 0 MST}
+ {3287984400 -21600 1 MDT}
+ {3308544000 -25200 0 MST}
+ {3319434000 -21600 1 MDT}
+ {3339993600 -25200 0 MST}
+ {3350883600 -21600 1 MDT}
+ {3371443200 -25200 0 MST}
+ {3382938000 -21600 1 MDT}
+ {3403497600 -25200 0 MST}
+ {3414387600 -21600 1 MDT}
+ {3434947200 -25200 0 MST}
+ {3445837200 -21600 1 MDT}
+ {3466396800 -25200 0 MST}
+ {3477286800 -21600 1 MDT}
+ {3497846400 -25200 0 MST}
+ {3508736400 -21600 1 MDT}
+ {3529296000 -25200 0 MST}
+ {3540186000 -21600 1 MDT}
+ {3560745600 -25200 0 MST}
+ {3572240400 -21600 1 MDT}
+ {3592800000 -25200 0 MST}
+ {3603690000 -21600 1 MDT}
+ {3624249600 -25200 0 MST}
+ {3635139600 -21600 1 MDT}
+ {3655699200 -25200 0 MST}
+ {3666589200 -21600 1 MDT}
+ {3687148800 -25200 0 MST}
+ {3698038800 -21600 1 MDT}
+ {3718598400 -25200 0 MST}
+ {3730093200 -21600 1 MDT}
+ {3750652800 -25200 0 MST}
+ {3761542800 -21600 1 MDT}
+ {3782102400 -25200 0 MST}
+ {3792992400 -21600 1 MDT}
+ {3813552000 -25200 0 MST}
+ {3824442000 -21600 1 MDT}
+ {3845001600 -25200 0 MST}
+ {3855891600 -21600 1 MDT}
+ {3876451200 -25200 0 MST}
+ {3887341200 -21600 1 MDT}
+ {3907900800 -25200 0 MST}
+ {3919395600 -21600 1 MDT}
+ {3939955200 -25200 0 MST}
+ {3950845200 -21600 1 MDT}
+ {3971404800 -25200 0 MST}
+ {3982294800 -21600 1 MDT}
+ {4002854400 -25200 0 MST}
+ {4013744400 -21600 1 MDT}
+ {4034304000 -25200 0 MST}
+ {4045194000 -21600 1 MDT}
+ {4065753600 -25200 0 MST}
+ {4076643600 -21600 1 MDT}
+ {4097203200 -25200 0 MST}
+}
diff --git a/library/tzdata/America/Detroit b/library/tzdata/America/Detroit
new file mode 100644
index 0000000..696a663
--- /dev/null
+++ b/library/tzdata/America/Detroit
@@ -0,0 +1,272 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Detroit) {
+ {-9223372036854775808 -19931 0 LMT}
+ {-2051202469 -21600 0 CST}
+ {-1724083200 -18000 0 EST}
+ {-883594800 -18000 0 EST}
+ {-880218000 -14400 1 EWT}
+ {-769395600 -14400 1 EPT}
+ {-765396000 -18000 0 EST}
+ {-757364400 -18000 0 EST}
+ {-684349200 -14400 1 EDT}
+ {-671047200 -18000 0 EST}
+ {-80499600 -14400 1 EDT}
+ {-68666400 -18000 0 EST}
+ {94712400 -18000 0 EST}
+ {104914800 -14400 1 EDT}
+ {120636000 -18000 0 EST}
+ {126687600 -14400 1 EDT}
+ {152085600 -18000 0 EST}
+ {157784400 -18000 0 EST}
+ {167814000 -14400 0 EDT}
+ {183535200 -18000 0 EST}
+ {199263600 -14400 1 EDT}
+ {215589600 -18000 0 EST}
+ {230713200 -14400 1 EDT}
+ {247039200 -18000 0 EST}
+ {262767600 -14400 1 EDT}
+ {278488800 -18000 0 EST}
+ {294217200 -14400 1 EDT}
+ {309938400 -18000 0 EST}
+ {325666800 -14400 1 EDT}
+ {341388000 -18000 0 EST}
+ {357116400 -14400 1 EDT}
+ {372837600 -18000 0 EST}
+ {388566000 -14400 1 EDT}
+ {404892000 -18000 0 EST}
+ {420015600 -14400 1 EDT}
+ {436341600 -18000 0 EST}
+ {452070000 -14400 1 EDT}
+ {467791200 -18000 0 EST}
+ {483519600 -14400 1 EDT}
+ {499240800 -18000 0 EST}
+ {514969200 -14400 1 EDT}
+ {530690400 -18000 0 EST}
+ {544604400 -14400 1 EDT}
+ {562140000 -18000 0 EST}
+ {576054000 -14400 1 EDT}
+ {594194400 -18000 0 EST}
+ {607503600 -14400 1 EDT}
+ {625644000 -18000 0 EST}
+ {638953200 -14400 1 EDT}
+ {657093600 -18000 0 EST}
+ {671007600 -14400 1 EDT}
+ {688543200 -18000 0 EST}
+ {702457200 -14400 1 EDT}
+ {719992800 -18000 0 EST}
+ {733906800 -14400 1 EDT}
+ {752047200 -18000 0 EST}
+ {765356400 -14400 1 EDT}
+ {783496800 -18000 0 EST}
+ {796806000 -14400 1 EDT}
+ {814946400 -18000 0 EST}
+ {828860400 -14400 1 EDT}
+ {846396000 -18000 0 EST}
+ {860310000 -14400 1 EDT}
+ {877845600 -18000 0 EST}
+ {891759600 -14400 1 EDT}
+ {909295200 -18000 0 EST}
+ {923209200 -14400 1 EDT}
+ {941349600 -18000 0 EST}
+ {954658800 -14400 1 EDT}
+ {972799200 -18000 0 EST}
+ {986108400 -14400 1 EDT}
+ {1004248800 -18000 0 EST}
+ {1018162800 -14400 1 EDT}
+ {1035698400 -18000 0 EST}
+ {1049612400 -14400 1 EDT}
+ {1067148000 -18000 0 EST}
+ {1081062000 -14400 1 EDT}
+ {1099202400 -18000 0 EST}
+ {1112511600 -14400 1 EDT}
+ {1130652000 -18000 0 EST}
+ {1143961200 -14400 1 EDT}
+ {1162101600 -18000 0 EST}
+ {1173596400 -14400 1 EDT}
+ {1194156000 -18000 0 EST}
+ {1205046000 -14400 1 EDT}
+ {1225605600 -18000 0 EST}
+ {1236495600 -14400 1 EDT}
+ {1257055200 -18000 0 EST}
+ {1268550000 -14400 1 EDT}
+ {1289109600 -18000 0 EST}
+ {1299999600 -14400 1 EDT}
+ {1320559200 -18000 0 EST}
+ {1331449200 -14400 1 EDT}
+ {1352008800 -18000 0 EST}
+ {1362898800 -14400 1 EDT}
+ {1383458400 -18000 0 EST}
+ {1394348400 -14400 1 EDT}
+ {1414908000 -18000 0 EST}
+ {1425798000 -14400 1 EDT}
+ {1446357600 -18000 0 EST}
+ {1457852400 -14400 1 EDT}
+ {1478412000 -18000 0 EST}
+ {1489302000 -14400 1 EDT}
+ {1509861600 -18000 0 EST}
+ {1520751600 -14400 1 EDT}
+ {1541311200 -18000 0 EST}
+ {1552201200 -14400 1 EDT}
+ {1572760800 -18000 0 EST}
+ {1583650800 -14400 1 EDT}
+ {1604210400 -18000 0 EST}
+ {1615705200 -14400 1 EDT}
+ {1636264800 -18000 0 EST}
+ {1647154800 -14400 1 EDT}
+ {1667714400 -18000 0 EST}
+ {1678604400 -14400 1 EDT}
+ {1699164000 -18000 0 EST}
+ {1710054000 -14400 1 EDT}
+ {1730613600 -18000 0 EST}
+ {1741503600 -14400 1 EDT}
+ {1762063200 -18000 0 EST}
+ {1772953200 -14400 1 EDT}
+ {1793512800 -18000 0 EST}
+ {1805007600 -14400 1 EDT}
+ {1825567200 -18000 0 EST}
+ {1836457200 -14400 1 EDT}
+ {1857016800 -18000 0 EST}
+ {1867906800 -14400 1 EDT}
+ {1888466400 -18000 0 EST}
+ {1899356400 -14400 1 EDT}
+ {1919916000 -18000 0 EST}
+ {1930806000 -14400 1 EDT}
+ {1951365600 -18000 0 EST}
+ {1962860400 -14400 1 EDT}
+ {1983420000 -18000 0 EST}
+ {1994310000 -14400 1 EDT}
+ {2014869600 -18000 0 EST}
+ {2025759600 -14400 1 EDT}
+ {2046319200 -18000 0 EST}
+ {2057209200 -14400 1 EDT}
+ {2077768800 -18000 0 EST}
+ {2088658800 -14400 1 EDT}
+ {2109218400 -18000 0 EST}
+ {2120108400 -14400 1 EDT}
+ {2140668000 -18000 0 EST}
+ {2152162800 -14400 1 EDT}
+ {2172722400 -18000 0 EST}
+ {2183612400 -14400 1 EDT}
+ {2204172000 -18000 0 EST}
+ {2215062000 -14400 1 EDT}
+ {2235621600 -18000 0 EST}
+ {2246511600 -14400 1 EDT}
+ {2267071200 -18000 0 EST}
+ {2277961200 -14400 1 EDT}
+ {2298520800 -18000 0 EST}
+ {2309410800 -14400 1 EDT}
+ {2329970400 -18000 0 EST}
+ {2341465200 -14400 1 EDT}
+ {2362024800 -18000 0 EST}
+ {2372914800 -14400 1 EDT}
+ {2393474400 -18000 0 EST}
+ {2404364400 -14400 1 EDT}
+ {2424924000 -18000 0 EST}
+ {2435814000 -14400 1 EDT}
+ {2456373600 -18000 0 EST}
+ {2467263600 -14400 1 EDT}
+ {2487823200 -18000 0 EST}
+ {2499318000 -14400 1 EDT}
+ {2519877600 -18000 0 EST}
+ {2530767600 -14400 1 EDT}
+ {2551327200 -18000 0 EST}
+ {2562217200 -14400 1 EDT}
+ {2582776800 -18000 0 EST}
+ {2593666800 -14400 1 EDT}
+ {2614226400 -18000 0 EST}
+ {2625116400 -14400 1 EDT}
+ {2645676000 -18000 0 EST}
+ {2656566000 -14400 1 EDT}
+ {2677125600 -18000 0 EST}
+ {2688620400 -14400 1 EDT}
+ {2709180000 -18000 0 EST}
+ {2720070000 -14400 1 EDT}
+ {2740629600 -18000 0 EST}
+ {2751519600 -14400 1 EDT}
+ {2772079200 -18000 0 EST}
+ {2782969200 -14400 1 EDT}
+ {2803528800 -18000 0 EST}
+ {2814418800 -14400 1 EDT}
+ {2834978400 -18000 0 EST}
+ {2846473200 -14400 1 EDT}
+ {2867032800 -18000 0 EST}
+ {2877922800 -14400 1 EDT}
+ {2898482400 -18000 0 EST}
+ {2909372400 -14400 1 EDT}
+ {2929932000 -18000 0 EST}
+ {2940822000 -14400 1 EDT}
+ {2961381600 -18000 0 EST}
+ {2972271600 -14400 1 EDT}
+ {2992831200 -18000 0 EST}
+ {3003721200 -14400 1 EDT}
+ {3024280800 -18000 0 EST}
+ {3035775600 -14400 1 EDT}
+ {3056335200 -18000 0 EST}
+ {3067225200 -14400 1 EDT}
+ {3087784800 -18000 0 EST}
+ {3098674800 -14400 1 EDT}
+ {3119234400 -18000 0 EST}
+ {3130124400 -14400 1 EDT}
+ {3150684000 -18000 0 EST}
+ {3161574000 -14400 1 EDT}
+ {3182133600 -18000 0 EST}
+ {3193023600 -14400 1 EDT}
+ {3213583200 -18000 0 EST}
+ {3225078000 -14400 1 EDT}
+ {3245637600 -18000 0 EST}
+ {3256527600 -14400 1 EDT}
+ {3277087200 -18000 0 EST}
+ {3287977200 -14400 1 EDT}
+ {3308536800 -18000 0 EST}
+ {3319426800 -14400 1 EDT}
+ {3339986400 -18000 0 EST}
+ {3350876400 -14400 1 EDT}
+ {3371436000 -18000 0 EST}
+ {3382930800 -14400 1 EDT}
+ {3403490400 -18000 0 EST}
+ {3414380400 -14400 1 EDT}
+ {3434940000 -18000 0 EST}
+ {3445830000 -14400 1 EDT}
+ {3466389600 -18000 0 EST}
+ {3477279600 -14400 1 EDT}
+ {3497839200 -18000 0 EST}
+ {3508729200 -14400 1 EDT}
+ {3529288800 -18000 0 EST}
+ {3540178800 -14400 1 EDT}
+ {3560738400 -18000 0 EST}
+ {3572233200 -14400 1 EDT}
+ {3592792800 -18000 0 EST}
+ {3603682800 -14400 1 EDT}
+ {3624242400 -18000 0 EST}
+ {3635132400 -14400 1 EDT}
+ {3655692000 -18000 0 EST}
+ {3666582000 -14400 1 EDT}
+ {3687141600 -18000 0 EST}
+ {3698031600 -14400 1 EDT}
+ {3718591200 -18000 0 EST}
+ {3730086000 -14400 1 EDT}
+ {3750645600 -18000 0 EST}
+ {3761535600 -14400 1 EDT}
+ {3782095200 -18000 0 EST}
+ {3792985200 -14400 1 EDT}
+ {3813544800 -18000 0 EST}
+ {3824434800 -14400 1 EDT}
+ {3844994400 -18000 0 EST}
+ {3855884400 -14400 1 EDT}
+ {3876444000 -18000 0 EST}
+ {3887334000 -14400 1 EDT}
+ {3907893600 -18000 0 EST}
+ {3919388400 -14400 1 EDT}
+ {3939948000 -18000 0 EST}
+ {3950838000 -14400 1 EDT}
+ {3971397600 -18000 0 EST}
+ {3982287600 -14400 1 EDT}
+ {4002847200 -18000 0 EST}
+ {4013737200 -14400 1 EDT}
+ {4034296800 -18000 0 EST}
+ {4045186800 -14400 1 EDT}
+ {4065746400 -18000 0 EST}
+ {4076636400 -14400 1 EDT}
+ {4097196000 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Dominica b/library/tzdata/America/Dominica
new file mode 100644
index 0000000..3503a65
--- /dev/null
+++ b/library/tzdata/America/Dominica
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Dominica) {
+ {-9223372036854775808 -14736 0 LMT}
+ {-1846266804 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Edmonton b/library/tzdata/America/Edmonton
new file mode 100644
index 0000000..c4252f8
--- /dev/null
+++ b/library/tzdata/America/Edmonton
@@ -0,0 +1,284 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Edmonton) {
+ {-9223372036854775808 -27232 0 LMT}
+ {-1998663968 -25200 0 MST}
+ {-1632063600 -21600 1 MDT}
+ {-1614787200 -25200 0 MST}
+ {-1600614000 -21600 1 MDT}
+ {-1596816000 -25200 0 MST}
+ {-1567954800 -21600 1 MDT}
+ {-1551628800 -25200 0 MST}
+ {-1536505200 -21600 1 MDT}
+ {-1523203200 -25200 0 MST}
+ {-1504450800 -21600 1 MDT}
+ {-1491753600 -25200 0 MST}
+ {-1473001200 -21600 1 MDT}
+ {-1459699200 -25200 0 MST}
+ {-880210800 -21600 1 MWT}
+ {-769395600 -21600 1 MPT}
+ {-765388800 -25200 0 MST}
+ {-715791600 -21600 1 MDT}
+ {-702489600 -25200 0 MST}
+ {-84380400 -21600 1 MDT}
+ {-68659200 -25200 0 MST}
+ {-21481200 -21600 1 MDT}
+ {-5760000 -25200 0 MST}
+ {73472400 -21600 1 MDT}
+ {89193600 -25200 0 MST}
+ {104922000 -21600 1 MDT}
+ {120643200 -25200 0 MST}
+ {136371600 -21600 1 MDT}
+ {152092800 -25200 0 MST}
+ {167821200 -21600 1 MDT}
+ {183542400 -25200 0 MST}
+ {199270800 -21600 1 MDT}
+ {215596800 -25200 0 MST}
+ {230720400 -21600 1 MDT}
+ {247046400 -25200 0 MST}
+ {262774800 -21600 1 MDT}
+ {278496000 -25200 0 MST}
+ {294224400 -21600 1 MDT}
+ {309945600 -25200 0 MST}
+ {325674000 -21600 1 MDT}
+ {341395200 -25200 0 MST}
+ {357123600 -21600 1 MDT}
+ {372844800 -25200 0 MST}
+ {388573200 -21600 1 MDT}
+ {404899200 -25200 0 MST}
+ {420022800 -21600 1 MDT}
+ {436348800 -25200 0 MST}
+ {452077200 -21600 1 MDT}
+ {467798400 -25200 0 MST}
+ {483526800 -21600 1 MDT}
+ {499248000 -25200 0 MST}
+ {514976400 -21600 1 MDT}
+ {530697600 -25200 0 MST}
+ {536482800 -25200 0 MST}
+ {544611600 -21600 1 MDT}
+ {562147200 -25200 0 MST}
+ {576061200 -21600 1 MDT}
+ {594201600 -25200 0 MST}
+ {607510800 -21600 1 MDT}
+ {625651200 -25200 0 MST}
+ {638960400 -21600 1 MDT}
+ {657100800 -25200 0 MST}
+ {671014800 -21600 1 MDT}
+ {688550400 -25200 0 MST}
+ {702464400 -21600 1 MDT}
+ {720000000 -25200 0 MST}
+ {733914000 -21600 1 MDT}
+ {752054400 -25200 0 MST}
+ {765363600 -21600 1 MDT}
+ {783504000 -25200 0 MST}
+ {796813200 -21600 1 MDT}
+ {814953600 -25200 0 MST}
+ {828867600 -21600 1 MDT}
+ {846403200 -25200 0 MST}
+ {860317200 -21600 1 MDT}
+ {877852800 -25200 0 MST}
+ {891766800 -21600 1 MDT}
+ {909302400 -25200 0 MST}
+ {923216400 -21600 1 MDT}
+ {941356800 -25200 0 MST}
+ {954666000 -21600 1 MDT}
+ {972806400 -25200 0 MST}
+ {986115600 -21600 1 MDT}
+ {1004256000 -25200 0 MST}
+ {1018170000 -21600 1 MDT}
+ {1035705600 -25200 0 MST}
+ {1049619600 -21600 1 MDT}
+ {1067155200 -25200 0 MST}
+ {1081069200 -21600 1 MDT}
+ {1099209600 -25200 0 MST}
+ {1112518800 -21600 1 MDT}
+ {1130659200 -25200 0 MST}
+ {1143968400 -21600 1 MDT}
+ {1162108800 -25200 0 MST}
+ {1173603600 -21600 1 MDT}
+ {1194163200 -25200 0 MST}
+ {1205053200 -21600 1 MDT}
+ {1225612800 -25200 0 MST}
+ {1236502800 -21600 1 MDT}
+ {1257062400 -25200 0 MST}
+ {1268557200 -21600 1 MDT}
+ {1289116800 -25200 0 MST}
+ {1300006800 -21600 1 MDT}
+ {1320566400 -25200 0 MST}
+ {1331456400 -21600 1 MDT}
+ {1352016000 -25200 0 MST}
+ {1362906000 -21600 1 MDT}
+ {1383465600 -25200 0 MST}
+ {1394355600 -21600 1 MDT}
+ {1414915200 -25200 0 MST}
+ {1425805200 -21600 1 MDT}
+ {1446364800 -25200 0 MST}
+ {1457859600 -21600 1 MDT}
+ {1478419200 -25200 0 MST}
+ {1489309200 -21600 1 MDT}
+ {1509868800 -25200 0 MST}
+ {1520758800 -21600 1 MDT}
+ {1541318400 -25200 0 MST}
+ {1552208400 -21600 1 MDT}
+ {1572768000 -25200 0 MST}
+ {1583658000 -21600 1 MDT}
+ {1604217600 -25200 0 MST}
+ {1615712400 -21600 1 MDT}
+ {1636272000 -25200 0 MST}
+ {1647162000 -21600 1 MDT}
+ {1667721600 -25200 0 MST}
+ {1678611600 -21600 1 MDT}
+ {1699171200 -25200 0 MST}
+ {1710061200 -21600 1 MDT}
+ {1730620800 -25200 0 MST}
+ {1741510800 -21600 1 MDT}
+ {1762070400 -25200 0 MST}
+ {1772960400 -21600 1 MDT}
+ {1793520000 -25200 0 MST}
+ {1805014800 -21600 1 MDT}
+ {1825574400 -25200 0 MST}
+ {1836464400 -21600 1 MDT}
+ {1857024000 -25200 0 MST}
+ {1867914000 -21600 1 MDT}
+ {1888473600 -25200 0 MST}
+ {1899363600 -21600 1 MDT}
+ {1919923200 -25200 0 MST}
+ {1930813200 -21600 1 MDT}
+ {1951372800 -25200 0 MST}
+ {1962867600 -21600 1 MDT}
+ {1983427200 -25200 0 MST}
+ {1994317200 -21600 1 MDT}
+ {2014876800 -25200 0 MST}
+ {2025766800 -21600 1 MDT}
+ {2046326400 -25200 0 MST}
+ {2057216400 -21600 1 MDT}
+ {2077776000 -25200 0 MST}
+ {2088666000 -21600 1 MDT}
+ {2109225600 -25200 0 MST}
+ {2120115600 -21600 1 MDT}
+ {2140675200 -25200 0 MST}
+ {2152170000 -21600 1 MDT}
+ {2172729600 -25200 0 MST}
+ {2183619600 -21600 1 MDT}
+ {2204179200 -25200 0 MST}
+ {2215069200 -21600 1 MDT}
+ {2235628800 -25200 0 MST}
+ {2246518800 -21600 1 MDT}
+ {2267078400 -25200 0 MST}
+ {2277968400 -21600 1 MDT}
+ {2298528000 -25200 0 MST}
+ {2309418000 -21600 1 MDT}
+ {2329977600 -25200 0 MST}
+ {2341472400 -21600 1 MDT}
+ {2362032000 -25200 0 MST}
+ {2372922000 -21600 1 MDT}
+ {2393481600 -25200 0 MST}
+ {2404371600 -21600 1 MDT}
+ {2424931200 -25200 0 MST}
+ {2435821200 -21600 1 MDT}
+ {2456380800 -25200 0 MST}
+ {2467270800 -21600 1 MDT}
+ {2487830400 -25200 0 MST}
+ {2499325200 -21600 1 MDT}
+ {2519884800 -25200 0 MST}
+ {2530774800 -21600 1 MDT}
+ {2551334400 -25200 0 MST}
+ {2562224400 -21600 1 MDT}
+ {2582784000 -25200 0 MST}
+ {2593674000 -21600 1 MDT}
+ {2614233600 -25200 0 MST}
+ {2625123600 -21600 1 MDT}
+ {2645683200 -25200 0 MST}
+ {2656573200 -21600 1 MDT}
+ {2677132800 -25200 0 MST}
+ {2688627600 -21600 1 MDT}
+ {2709187200 -25200 0 MST}
+ {2720077200 -21600 1 MDT}
+ {2740636800 -25200 0 MST}
+ {2751526800 -21600 1 MDT}
+ {2772086400 -25200 0 MST}
+ {2782976400 -21600 1 MDT}
+ {2803536000 -25200 0 MST}
+ {2814426000 -21600 1 MDT}
+ {2834985600 -25200 0 MST}
+ {2846480400 -21600 1 MDT}
+ {2867040000 -25200 0 MST}
+ {2877930000 -21600 1 MDT}
+ {2898489600 -25200 0 MST}
+ {2909379600 -21600 1 MDT}
+ {2929939200 -25200 0 MST}
+ {2940829200 -21600 1 MDT}
+ {2961388800 -25200 0 MST}
+ {2972278800 -21600 1 MDT}
+ {2992838400 -25200 0 MST}
+ {3003728400 -21600 1 MDT}
+ {3024288000 -25200 0 MST}
+ {3035782800 -21600 1 MDT}
+ {3056342400 -25200 0 MST}
+ {3067232400 -21600 1 MDT}
+ {3087792000 -25200 0 MST}
+ {3098682000 -21600 1 MDT}
+ {3119241600 -25200 0 MST}
+ {3130131600 -21600 1 MDT}
+ {3150691200 -25200 0 MST}
+ {3161581200 -21600 1 MDT}
+ {3182140800 -25200 0 MST}
+ {3193030800 -21600 1 MDT}
+ {3213590400 -25200 0 MST}
+ {3225085200 -21600 1 MDT}
+ {3245644800 -25200 0 MST}
+ {3256534800 -21600 1 MDT}
+ {3277094400 -25200 0 MST}
+ {3287984400 -21600 1 MDT}
+ {3308544000 -25200 0 MST}
+ {3319434000 -21600 1 MDT}
+ {3339993600 -25200 0 MST}
+ {3350883600 -21600 1 MDT}
+ {3371443200 -25200 0 MST}
+ {3382938000 -21600 1 MDT}
+ {3403497600 -25200 0 MST}
+ {3414387600 -21600 1 MDT}
+ {3434947200 -25200 0 MST}
+ {3445837200 -21600 1 MDT}
+ {3466396800 -25200 0 MST}
+ {3477286800 -21600 1 MDT}
+ {3497846400 -25200 0 MST}
+ {3508736400 -21600 1 MDT}
+ {3529296000 -25200 0 MST}
+ {3540186000 -21600 1 MDT}
+ {3560745600 -25200 0 MST}
+ {3572240400 -21600 1 MDT}
+ {3592800000 -25200 0 MST}
+ {3603690000 -21600 1 MDT}
+ {3624249600 -25200 0 MST}
+ {3635139600 -21600 1 MDT}
+ {3655699200 -25200 0 MST}
+ {3666589200 -21600 1 MDT}
+ {3687148800 -25200 0 MST}
+ {3698038800 -21600 1 MDT}
+ {3718598400 -25200 0 MST}
+ {3730093200 -21600 1 MDT}
+ {3750652800 -25200 0 MST}
+ {3761542800 -21600 1 MDT}
+ {3782102400 -25200 0 MST}
+ {3792992400 -21600 1 MDT}
+ {3813552000 -25200 0 MST}
+ {3824442000 -21600 1 MDT}
+ {3845001600 -25200 0 MST}
+ {3855891600 -21600 1 MDT}
+ {3876451200 -25200 0 MST}
+ {3887341200 -21600 1 MDT}
+ {3907900800 -25200 0 MST}
+ {3919395600 -21600 1 MDT}
+ {3939955200 -25200 0 MST}
+ {3950845200 -21600 1 MDT}
+ {3971404800 -25200 0 MST}
+ {3982294800 -21600 1 MDT}
+ {4002854400 -25200 0 MST}
+ {4013744400 -21600 1 MDT}
+ {4034304000 -25200 0 MST}
+ {4045194000 -21600 1 MDT}
+ {4065753600 -25200 0 MST}
+ {4076643600 -21600 1 MDT}
+ {4097203200 -25200 0 MST}
+}
diff --git a/library/tzdata/America/Eirunepe b/library/tzdata/America/Eirunepe
new file mode 100644
index 0000000..86dcd8f
--- /dev/null
+++ b/library/tzdata/America/Eirunepe
@@ -0,0 +1,40 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Eirunepe) {
+ {-9223372036854775808 -16768 0 LMT}
+ {-1767208832 -18000 0 ACT}
+ {-1206950400 -14400 1 ACST}
+ {-1191355200 -18000 0 ACT}
+ {-1175367600 -14400 1 ACST}
+ {-1159819200 -18000 0 ACT}
+ {-633812400 -14400 1 ACST}
+ {-622062000 -18000 0 ACT}
+ {-602276400 -14400 1 ACST}
+ {-591825600 -18000 0 ACT}
+ {-570740400 -14400 1 ACST}
+ {-560203200 -18000 0 ACT}
+ {-539118000 -14400 1 ACST}
+ {-531345600 -18000 0 ACT}
+ {-191358000 -14400 1 ACST}
+ {-184190400 -18000 0 ACT}
+ {-155156400 -14400 1 ACST}
+ {-150062400 -18000 0 ACT}
+ {-128890800 -14400 1 ACST}
+ {-121118400 -18000 0 ACT}
+ {-99946800 -14400 1 ACST}
+ {-89582400 -18000 0 ACT}
+ {-68410800 -14400 1 ACST}
+ {-57960000 -18000 0 ACT}
+ {499755600 -14400 1 ACST}
+ {511243200 -18000 0 ACT}
+ {530600400 -14400 1 ACST}
+ {540273600 -18000 0 ACT}
+ {562136400 -14400 1 ACST}
+ {571204800 -18000 0 ACT}
+ {590040000 -18000 0 ACT}
+ {749192400 -18000 0 ACT}
+ {750834000 -14400 1 ACST}
+ {761716800 -18000 0 ACT}
+ {780206400 -18000 0 ACT}
+ {1214283600 -14400 0 AMT}
+}
diff --git a/library/tzdata/America/El_Salvador b/library/tzdata/America/El_Salvador
new file mode 100644
index 0000000..75d8129
--- /dev/null
+++ b/library/tzdata/America/El_Salvador
@@ -0,0 +1,10 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/El_Salvador) {
+ {-9223372036854775808 -21408 0 LMT}
+ {-1546279392 -21600 0 CST}
+ {547020000 -18000 1 CDT}
+ {559717200 -21600 0 CST}
+ {578469600 -18000 1 CDT}
+ {591166800 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Ensenada b/library/tzdata/America/Ensenada
new file mode 100644
index 0000000..f600305
--- /dev/null
+++ b/library/tzdata/America/Ensenada
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Tijuana)]} {
+ LoadTimeZoneFile America/Tijuana
+}
+set TZData(:America/Ensenada) $TZData(:America/Tijuana)
diff --git a/library/tzdata/America/Fort_Wayne b/library/tzdata/America/Fort_Wayne
new file mode 100644
index 0000000..9514d57
--- /dev/null
+++ b/library/tzdata/America/Fort_Wayne
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Indiana/Indianapolis)]} {
+ LoadTimeZoneFile America/Indiana/Indianapolis
+}
+set TZData(:America/Fort_Wayne) $TZData(:America/Indiana/Indianapolis)
diff --git a/library/tzdata/America/Fortaleza b/library/tzdata/America/Fortaleza
new file mode 100644
index 0000000..581faa5
--- /dev/null
+++ b/library/tzdata/America/Fortaleza
@@ -0,0 +1,48 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Fortaleza) {
+ {-9223372036854775808 -9240 0 LMT}
+ {-1767216360 -10800 0 BRT}
+ {-1206957600 -7200 1 BRST}
+ {-1191362400 -10800 0 BRT}
+ {-1175374800 -7200 1 BRST}
+ {-1159826400 -10800 0 BRT}
+ {-633819600 -7200 1 BRST}
+ {-622069200 -10800 0 BRT}
+ {-602283600 -7200 1 BRST}
+ {-591832800 -10800 0 BRT}
+ {-570747600 -7200 1 BRST}
+ {-560210400 -10800 0 BRT}
+ {-539125200 -7200 1 BRST}
+ {-531352800 -10800 0 BRT}
+ {-191365200 -7200 1 BRST}
+ {-184197600 -10800 0 BRT}
+ {-155163600 -7200 1 BRST}
+ {-150069600 -10800 0 BRT}
+ {-128898000 -7200 1 BRST}
+ {-121125600 -10800 0 BRT}
+ {-99954000 -7200 1 BRST}
+ {-89589600 -10800 0 BRT}
+ {-68418000 -7200 1 BRST}
+ {-57967200 -10800 0 BRT}
+ {499748400 -7200 1 BRST}
+ {511236000 -10800 0 BRT}
+ {530593200 -7200 1 BRST}
+ {540266400 -10800 0 BRT}
+ {562129200 -7200 1 BRST}
+ {571197600 -10800 0 BRT}
+ {592974000 -7200 1 BRST}
+ {602042400 -10800 0 BRT}
+ {624423600 -7200 1 BRST}
+ {634701600 -10800 0 BRT}
+ {653536800 -10800 0 BRT}
+ {938660400 -10800 0 BRT}
+ {938919600 -7200 1 BRST}
+ {951616800 -10800 0 BRT}
+ {970974000 -7200 1 BRST}
+ {972180000 -10800 0 BRT}
+ {1000350000 -10800 0 BRT}
+ {1003028400 -7200 1 BRST}
+ {1013911200 -10800 0 BRT}
+ {1033437600 -10800 0 BRT}
+}
diff --git a/library/tzdata/America/Glace_Bay b/library/tzdata/America/Glace_Bay
new file mode 100644
index 0000000..84b4822
--- /dev/null
+++ b/library/tzdata/America/Glace_Bay
@@ -0,0 +1,273 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Glace_Bay) {
+ {-9223372036854775808 -14388 0 LMT}
+ {-2131646412 -14400 0 AST}
+ {-1632074400 -10800 1 ADT}
+ {-1614798000 -14400 0 AST}
+ {-880221600 -10800 1 AWT}
+ {-769395600 -10800 1 APT}
+ {-765399600 -14400 0 AST}
+ {-536443200 -14400 0 AST}
+ {-526500000 -10800 1 ADT}
+ {-513198000 -14400 0 AST}
+ {-504907200 -14400 0 AST}
+ {63086400 -14400 0 AST}
+ {73461600 -10800 1 ADT}
+ {89182800 -14400 0 AST}
+ {104911200 -10800 1 ADT}
+ {120632400 -14400 0 AST}
+ {126244800 -14400 0 AST}
+ {136360800 -10800 1 ADT}
+ {152082000 -14400 0 AST}
+ {167810400 -10800 1 ADT}
+ {183531600 -14400 0 AST}
+ {199260000 -10800 1 ADT}
+ {215586000 -14400 0 AST}
+ {230709600 -10800 1 ADT}
+ {247035600 -14400 0 AST}
+ {262764000 -10800 1 ADT}
+ {278485200 -14400 0 AST}
+ {294213600 -10800 1 ADT}
+ {309934800 -14400 0 AST}
+ {325663200 -10800 1 ADT}
+ {341384400 -14400 0 AST}
+ {357112800 -10800 1 ADT}
+ {372834000 -14400 0 AST}
+ {388562400 -10800 1 ADT}
+ {404888400 -14400 0 AST}
+ {420012000 -10800 1 ADT}
+ {436338000 -14400 0 AST}
+ {452066400 -10800 1 ADT}
+ {467787600 -14400 0 AST}
+ {483516000 -10800 1 ADT}
+ {499237200 -14400 0 AST}
+ {514965600 -10800 1 ADT}
+ {530686800 -14400 0 AST}
+ {544600800 -10800 1 ADT}
+ {562136400 -14400 0 AST}
+ {576050400 -10800 1 ADT}
+ {594190800 -14400 0 AST}
+ {607500000 -10800 1 ADT}
+ {625640400 -14400 0 AST}
+ {638949600 -10800 1 ADT}
+ {657090000 -14400 0 AST}
+ {671004000 -10800 1 ADT}
+ {688539600 -14400 0 AST}
+ {702453600 -10800 1 ADT}
+ {719989200 -14400 0 AST}
+ {733903200 -10800 1 ADT}
+ {752043600 -14400 0 AST}
+ {765352800 -10800 1 ADT}
+ {783493200 -14400 0 AST}
+ {796802400 -10800 1 ADT}
+ {814942800 -14400 0 AST}
+ {828856800 -10800 1 ADT}
+ {846392400 -14400 0 AST}
+ {860306400 -10800 1 ADT}
+ {877842000 -14400 0 AST}
+ {891756000 -10800 1 ADT}
+ {909291600 -14400 0 AST}
+ {923205600 -10800 1 ADT}
+ {941346000 -14400 0 AST}
+ {954655200 -10800 1 ADT}
+ {972795600 -14400 0 AST}
+ {986104800 -10800 1 ADT}
+ {1004245200 -14400 0 AST}
+ {1018159200 -10800 1 ADT}
+ {1035694800 -14400 0 AST}
+ {1049608800 -10800 1 ADT}
+ {1067144400 -14400 0 AST}
+ {1081058400 -10800 1 ADT}
+ {1099198800 -14400 0 AST}
+ {1112508000 -10800 1 ADT}
+ {1130648400 -14400 0 AST}
+ {1143957600 -10800 1 ADT}
+ {1162098000 -14400 0 AST}
+ {1173592800 -10800 1 ADT}
+ {1194152400 -14400 0 AST}
+ {1205042400 -10800 1 ADT}
+ {1225602000 -14400 0 AST}
+ {1236492000 -10800 1 ADT}
+ {1257051600 -14400 0 AST}
+ {1268546400 -10800 1 ADT}
+ {1289106000 -14400 0 AST}
+ {1299996000 -10800 1 ADT}
+ {1320555600 -14400 0 AST}
+ {1331445600 -10800 1 ADT}
+ {1352005200 -14400 0 AST}
+ {1362895200 -10800 1 ADT}
+ {1383454800 -14400 0 AST}
+ {1394344800 -10800 1 ADT}
+ {1414904400 -14400 0 AST}
+ {1425794400 -10800 1 ADT}
+ {1446354000 -14400 0 AST}
+ {1457848800 -10800 1 ADT}
+ {1478408400 -14400 0 AST}
+ {1489298400 -10800 1 ADT}
+ {1509858000 -14400 0 AST}
+ {1520748000 -10800 1 ADT}
+ {1541307600 -14400 0 AST}
+ {1552197600 -10800 1 ADT}
+ {1572757200 -14400 0 AST}
+ {1583647200 -10800 1 ADT}
+ {1604206800 -14400 0 AST}
+ {1615701600 -10800 1 ADT}
+ {1636261200 -14400 0 AST}
+ {1647151200 -10800 1 ADT}
+ {1667710800 -14400 0 AST}
+ {1678600800 -10800 1 ADT}
+ {1699160400 -14400 0 AST}
+ {1710050400 -10800 1 ADT}
+ {1730610000 -14400 0 AST}
+ {1741500000 -10800 1 ADT}
+ {1762059600 -14400 0 AST}
+ {1772949600 -10800 1 ADT}
+ {1793509200 -14400 0 AST}
+ {1805004000 -10800 1 ADT}
+ {1825563600 -14400 0 AST}
+ {1836453600 -10800 1 ADT}
+ {1857013200 -14400 0 AST}
+ {1867903200 -10800 1 ADT}
+ {1888462800 -14400 0 AST}
+ {1899352800 -10800 1 ADT}
+ {1919912400 -14400 0 AST}
+ {1930802400 -10800 1 ADT}
+ {1951362000 -14400 0 AST}
+ {1962856800 -10800 1 ADT}
+ {1983416400 -14400 0 AST}
+ {1994306400 -10800 1 ADT}
+ {2014866000 -14400 0 AST}
+ {2025756000 -10800 1 ADT}
+ {2046315600 -14400 0 AST}
+ {2057205600 -10800 1 ADT}
+ {2077765200 -14400 0 AST}
+ {2088655200 -10800 1 ADT}
+ {2109214800 -14400 0 AST}
+ {2120104800 -10800 1 ADT}
+ {2140664400 -14400 0 AST}
+ {2152159200 -10800 1 ADT}
+ {2172718800 -14400 0 AST}
+ {2183608800 -10800 1 ADT}
+ {2204168400 -14400 0 AST}
+ {2215058400 -10800 1 ADT}
+ {2235618000 -14400 0 AST}
+ {2246508000 -10800 1 ADT}
+ {2267067600 -14400 0 AST}
+ {2277957600 -10800 1 ADT}
+ {2298517200 -14400 0 AST}
+ {2309407200 -10800 1 ADT}
+ {2329966800 -14400 0 AST}
+ {2341461600 -10800 1 ADT}
+ {2362021200 -14400 0 AST}
+ {2372911200 -10800 1 ADT}
+ {2393470800 -14400 0 AST}
+ {2404360800 -10800 1 ADT}
+ {2424920400 -14400 0 AST}
+ {2435810400 -10800 1 ADT}
+ {2456370000 -14400 0 AST}
+ {2467260000 -10800 1 ADT}
+ {2487819600 -14400 0 AST}
+ {2499314400 -10800 1 ADT}
+ {2519874000 -14400 0 AST}
+ {2530764000 -10800 1 ADT}
+ {2551323600 -14400 0 AST}
+ {2562213600 -10800 1 ADT}
+ {2582773200 -14400 0 AST}
+ {2593663200 -10800 1 ADT}
+ {2614222800 -14400 0 AST}
+ {2625112800 -10800 1 ADT}
+ {2645672400 -14400 0 AST}
+ {2656562400 -10800 1 ADT}
+ {2677122000 -14400 0 AST}
+ {2688616800 -10800 1 ADT}
+ {2709176400 -14400 0 AST}
+ {2720066400 -10800 1 ADT}
+ {2740626000 -14400 0 AST}
+ {2751516000 -10800 1 ADT}
+ {2772075600 -14400 0 AST}
+ {2782965600 -10800 1 ADT}
+ {2803525200 -14400 0 AST}
+ {2814415200 -10800 1 ADT}
+ {2834974800 -14400 0 AST}
+ {2846469600 -10800 1 ADT}
+ {2867029200 -14400 0 AST}
+ {2877919200 -10800 1 ADT}
+ {2898478800 -14400 0 AST}
+ {2909368800 -10800 1 ADT}
+ {2929928400 -14400 0 AST}
+ {2940818400 -10800 1 ADT}
+ {2961378000 -14400 0 AST}
+ {2972268000 -10800 1 ADT}
+ {2992827600 -14400 0 AST}
+ {3003717600 -10800 1 ADT}
+ {3024277200 -14400 0 AST}
+ {3035772000 -10800 1 ADT}
+ {3056331600 -14400 0 AST}
+ {3067221600 -10800 1 ADT}
+ {3087781200 -14400 0 AST}
+ {3098671200 -10800 1 ADT}
+ {3119230800 -14400 0 AST}
+ {3130120800 -10800 1 ADT}
+ {3150680400 -14400 0 AST}
+ {3161570400 -10800 1 ADT}
+ {3182130000 -14400 0 AST}
+ {3193020000 -10800 1 ADT}
+ {3213579600 -14400 0 AST}
+ {3225074400 -10800 1 ADT}
+ {3245634000 -14400 0 AST}
+ {3256524000 -10800 1 ADT}
+ {3277083600 -14400 0 AST}
+ {3287973600 -10800 1 ADT}
+ {3308533200 -14400 0 AST}
+ {3319423200 -10800 1 ADT}
+ {3339982800 -14400 0 AST}
+ {3350872800 -10800 1 ADT}
+ {3371432400 -14400 0 AST}
+ {3382927200 -10800 1 ADT}
+ {3403486800 -14400 0 AST}
+ {3414376800 -10800 1 ADT}
+ {3434936400 -14400 0 AST}
+ {3445826400 -10800 1 ADT}
+ {3466386000 -14400 0 AST}
+ {3477276000 -10800 1 ADT}
+ {3497835600 -14400 0 AST}
+ {3508725600 -10800 1 ADT}
+ {3529285200 -14400 0 AST}
+ {3540175200 -10800 1 ADT}
+ {3560734800 -14400 0 AST}
+ {3572229600 -10800 1 ADT}
+ {3592789200 -14400 0 AST}
+ {3603679200 -10800 1 ADT}
+ {3624238800 -14400 0 AST}
+ {3635128800 -10800 1 ADT}
+ {3655688400 -14400 0 AST}
+ {3666578400 -10800 1 ADT}
+ {3687138000 -14400 0 AST}
+ {3698028000 -10800 1 ADT}
+ {3718587600 -14400 0 AST}
+ {3730082400 -10800 1 ADT}
+ {3750642000 -14400 0 AST}
+ {3761532000 -10800 1 ADT}
+ {3782091600 -14400 0 AST}
+ {3792981600 -10800 1 ADT}
+ {3813541200 -14400 0 AST}
+ {3824431200 -10800 1 ADT}
+ {3844990800 -14400 0 AST}
+ {3855880800 -10800 1 ADT}
+ {3876440400 -14400 0 AST}
+ {3887330400 -10800 1 ADT}
+ {3907890000 -14400 0 AST}
+ {3919384800 -10800 1 ADT}
+ {3939944400 -14400 0 AST}
+ {3950834400 -10800 1 ADT}
+ {3971394000 -14400 0 AST}
+ {3982284000 -10800 1 ADT}
+ {4002843600 -14400 0 AST}
+ {4013733600 -10800 1 ADT}
+ {4034293200 -14400 0 AST}
+ {4045183200 -10800 1 ADT}
+ {4065742800 -14400 0 AST}
+ {4076632800 -10800 1 ADT}
+ {4097192400 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Godthab b/library/tzdata/America/Godthab
new file mode 100644
index 0000000..3c003cc
--- /dev/null
+++ b/library/tzdata/America/Godthab
@@ -0,0 +1,246 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Godthab) {
+ {-9223372036854775808 -12416 0 LMT}
+ {-1686083584 -10800 0 WGT}
+ {323845200 -7200 0 WGST}
+ {338950800 -10800 0 WGT}
+ {354675600 -7200 1 WGST}
+ {370400400 -10800 0 WGT}
+ {386125200 -7200 1 WGST}
+ {401850000 -10800 0 WGT}
+ {417574800 -7200 1 WGST}
+ {433299600 -10800 0 WGT}
+ {449024400 -7200 1 WGST}
+ {465354000 -10800 0 WGT}
+ {481078800 -7200 1 WGST}
+ {496803600 -10800 0 WGT}
+ {512528400 -7200 1 WGST}
+ {528253200 -10800 0 WGT}
+ {543978000 -7200 1 WGST}
+ {559702800 -10800 0 WGT}
+ {575427600 -7200 1 WGST}
+ {591152400 -10800 0 WGT}
+ {606877200 -7200 1 WGST}
+ {622602000 -10800 0 WGT}
+ {638326800 -7200 1 WGST}
+ {654656400 -10800 0 WGT}
+ {670381200 -7200 1 WGST}
+ {686106000 -10800 0 WGT}
+ {701830800 -7200 1 WGST}
+ {717555600 -10800 0 WGT}
+ {733280400 -7200 1 WGST}
+ {749005200 -10800 0 WGT}
+ {764730000 -7200 1 WGST}
+ {780454800 -10800 0 WGT}
+ {796179600 -7200 1 WGST}
+ {811904400 -10800 0 WGT}
+ {828234000 -7200 1 WGST}
+ {846378000 -10800 0 WGT}
+ {859683600 -7200 1 WGST}
+ {877827600 -10800 0 WGT}
+ {891133200 -7200 1 WGST}
+ {909277200 -10800 0 WGT}
+ {922582800 -7200 1 WGST}
+ {941331600 -10800 0 WGT}
+ {954032400 -7200 1 WGST}
+ {972781200 -10800 0 WGT}
+ {985482000 -7200 1 WGST}
+ {1004230800 -10800 0 WGT}
+ {1017536400 -7200 1 WGST}
+ {1035680400 -10800 0 WGT}
+ {1048986000 -7200 1 WGST}
+ {1067130000 -10800 0 WGT}
+ {1080435600 -7200 1 WGST}
+ {1099184400 -10800 0 WGT}
+ {1111885200 -7200 1 WGST}
+ {1130634000 -10800 0 WGT}
+ {1143334800 -7200 1 WGST}
+ {1162083600 -10800 0 WGT}
+ {1174784400 -7200 1 WGST}
+ {1193533200 -10800 0 WGT}
+ {1206838800 -7200 1 WGST}
+ {1224982800 -10800 0 WGT}
+ {1238288400 -7200 1 WGST}
+ {1256432400 -10800 0 WGT}
+ {1269738000 -7200 1 WGST}
+ {1288486800 -10800 0 WGT}
+ {1301187600 -7200 1 WGST}
+ {1319936400 -10800 0 WGT}
+ {1332637200 -7200 1 WGST}
+ {1351386000 -10800 0 WGT}
+ {1364691600 -7200 1 WGST}
+ {1382835600 -10800 0 WGT}
+ {1396141200 -7200 1 WGST}
+ {1414285200 -10800 0 WGT}
+ {1427590800 -7200 1 WGST}
+ {1445734800 -10800 0 WGT}
+ {1459040400 -7200 1 WGST}
+ {1477789200 -10800 0 WGT}
+ {1490490000 -7200 1 WGST}
+ {1509238800 -10800 0 WGT}
+ {1521939600 -7200 1 WGST}
+ {1540688400 -10800 0 WGT}
+ {1553994000 -7200 1 WGST}
+ {1572138000 -10800 0 WGT}
+ {1585443600 -7200 1 WGST}
+ {1603587600 -10800 0 WGT}
+ {1616893200 -7200 1 WGST}
+ {1635642000 -10800 0 WGT}
+ {1648342800 -7200 1 WGST}
+ {1667091600 -10800 0 WGT}
+ {1679792400 -7200 1 WGST}
+ {1698541200 -10800 0 WGT}
+ {1711846800 -7200 1 WGST}
+ {1729990800 -10800 0 WGT}
+ {1743296400 -7200 1 WGST}
+ {1761440400 -10800 0 WGT}
+ {1774746000 -7200 1 WGST}
+ {1792890000 -10800 0 WGT}
+ {1806195600 -7200 1 WGST}
+ {1824944400 -10800 0 WGT}
+ {1837645200 -7200 1 WGST}
+ {1856394000 -10800 0 WGT}
+ {1869094800 -7200 1 WGST}
+ {1887843600 -10800 0 WGT}
+ {1901149200 -7200 1 WGST}
+ {1919293200 -10800 0 WGT}
+ {1932598800 -7200 1 WGST}
+ {1950742800 -10800 0 WGT}
+ {1964048400 -7200 1 WGST}
+ {1982797200 -10800 0 WGT}
+ {1995498000 -7200 1 WGST}
+ {2014246800 -10800 0 WGT}
+ {2026947600 -7200 1 WGST}
+ {2045696400 -10800 0 WGT}
+ {2058397200 -7200 1 WGST}
+ {2077146000 -10800 0 WGT}
+ {2090451600 -7200 1 WGST}
+ {2108595600 -10800 0 WGT}
+ {2121901200 -7200 1 WGST}
+ {2140045200 -10800 0 WGT}
+ {2153350800 -7200 1 WGST}
+ {2172099600 -10800 0 WGT}
+ {2184800400 -7200 1 WGST}
+ {2203549200 -10800 0 WGT}
+ {2216250000 -7200 1 WGST}
+ {2234998800 -10800 0 WGT}
+ {2248304400 -7200 1 WGST}
+ {2266448400 -10800 0 WGT}
+ {2279754000 -7200 1 WGST}
+ {2297898000 -10800 0 WGT}
+ {2311203600 -7200 1 WGST}
+ {2329347600 -10800 0 WGT}
+ {2342653200 -7200 1 WGST}
+ {2361402000 -10800 0 WGT}
+ {2374102800 -7200 1 WGST}
+ {2392851600 -10800 0 WGT}
+ {2405552400 -7200 1 WGST}
+ {2424301200 -10800 0 WGT}
+ {2437606800 -7200 1 WGST}
+ {2455750800 -10800 0 WGT}
+ {2469056400 -7200 1 WGST}
+ {2487200400 -10800 0 WGT}
+ {2500506000 -7200 1 WGST}
+ {2519254800 -10800 0 WGT}
+ {2531955600 -7200 1 WGST}
+ {2550704400 -10800 0 WGT}
+ {2563405200 -7200 1 WGST}
+ {2582154000 -10800 0 WGT}
+ {2595459600 -7200 1 WGST}
+ {2613603600 -10800 0 WGT}
+ {2626909200 -7200 1 WGST}
+ {2645053200 -10800 0 WGT}
+ {2658358800 -7200 1 WGST}
+ {2676502800 -10800 0 WGT}
+ {2689808400 -7200 1 WGST}
+ {2708557200 -10800 0 WGT}
+ {2721258000 -7200 1 WGST}
+ {2740006800 -10800 0 WGT}
+ {2752707600 -7200 1 WGST}
+ {2771456400 -10800 0 WGT}
+ {2784762000 -7200 1 WGST}
+ {2802906000 -10800 0 WGT}
+ {2816211600 -7200 1 WGST}
+ {2834355600 -10800 0 WGT}
+ {2847661200 -7200 1 WGST}
+ {2866410000 -10800 0 WGT}
+ {2879110800 -7200 1 WGST}
+ {2897859600 -10800 0 WGT}
+ {2910560400 -7200 1 WGST}
+ {2929309200 -10800 0 WGT}
+ {2942010000 -7200 1 WGST}
+ {2960758800 -10800 0 WGT}
+ {2974064400 -7200 1 WGST}
+ {2992208400 -10800 0 WGT}
+ {3005514000 -7200 1 WGST}
+ {3023658000 -10800 0 WGT}
+ {3036963600 -7200 1 WGST}
+ {3055712400 -10800 0 WGT}
+ {3068413200 -7200 1 WGST}
+ {3087162000 -10800 0 WGT}
+ {3099862800 -7200 1 WGST}
+ {3118611600 -10800 0 WGT}
+ {3131917200 -7200 1 WGST}
+ {3150061200 -10800 0 WGT}
+ {3163366800 -7200 1 WGST}
+ {3181510800 -10800 0 WGT}
+ {3194816400 -7200 1 WGST}
+ {3212960400 -10800 0 WGT}
+ {3226266000 -7200 1 WGST}
+ {3245014800 -10800 0 WGT}
+ {3257715600 -7200 1 WGST}
+ {3276464400 -10800 0 WGT}
+ {3289165200 -7200 1 WGST}
+ {3307914000 -10800 0 WGT}
+ {3321219600 -7200 1 WGST}
+ {3339363600 -10800 0 WGT}
+ {3352669200 -7200 1 WGST}
+ {3370813200 -10800 0 WGT}
+ {3384118800 -7200 1 WGST}
+ {3402867600 -10800 0 WGT}
+ {3415568400 -7200 1 WGST}
+ {3434317200 -10800 0 WGT}
+ {3447018000 -7200 1 WGST}
+ {3465766800 -10800 0 WGT}
+ {3479072400 -7200 1 WGST}
+ {3497216400 -10800 0 WGT}
+ {3510522000 -7200 1 WGST}
+ {3528666000 -10800 0 WGT}
+ {3541971600 -7200 1 WGST}
+ {3560115600 -10800 0 WGT}
+ {3573421200 -7200 1 WGST}
+ {3592170000 -10800 0 WGT}
+ {3604870800 -7200 1 WGST}
+ {3623619600 -10800 0 WGT}
+ {3636320400 -7200 1 WGST}
+ {3655069200 -10800 0 WGT}
+ {3668374800 -7200 1 WGST}
+ {3686518800 -10800 0 WGT}
+ {3699824400 -7200 1 WGST}
+ {3717968400 -10800 0 WGT}
+ {3731274000 -7200 1 WGST}
+ {3750022800 -10800 0 WGT}
+ {3762723600 -7200 1 WGST}
+ {3781472400 -10800 0 WGT}
+ {3794173200 -7200 1 WGST}
+ {3812922000 -10800 0 WGT}
+ {3825622800 -7200 1 WGST}
+ {3844371600 -10800 0 WGT}
+ {3857677200 -7200 1 WGST}
+ {3875821200 -10800 0 WGT}
+ {3889126800 -7200 1 WGST}
+ {3907270800 -10800 0 WGT}
+ {3920576400 -7200 1 WGST}
+ {3939325200 -10800 0 WGT}
+ {3952026000 -7200 1 WGST}
+ {3970774800 -10800 0 WGT}
+ {3983475600 -7200 1 WGST}
+ {4002224400 -10800 0 WGT}
+ {4015530000 -7200 1 WGST}
+ {4033674000 -10800 0 WGT}
+ {4046979600 -7200 1 WGST}
+ {4065123600 -10800 0 WGT}
+ {4078429200 -7200 1 WGST}
+ {4096573200 -10800 0 WGT}
+}
diff --git a/library/tzdata/America/Goose_Bay b/library/tzdata/America/Goose_Bay
new file mode 100644
index 0000000..f93b612
--- /dev/null
+++ b/library/tzdata/America/Goose_Bay
@@ -0,0 +1,337 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Goose_Bay) {
+ {-9223372036854775808 -14500 0 LMT}
+ {-2713895900 -12652 0 NST}
+ {-1640982548 -12652 0 NST}
+ {-1632076148 -9052 1 NDT}
+ {-1614799748 -12652 0 NST}
+ {-1609446548 -12652 0 NST}
+ {-1096921748 -12600 0 NST}
+ {-1072989000 -12600 0 NST}
+ {-1061670600 -9000 1 NDT}
+ {-1048973400 -12600 0 NST}
+ {-1030221000 -9000 1 NDT}
+ {-1017523800 -12600 0 NST}
+ {-998771400 -9000 1 NDT}
+ {-986074200 -12600 0 NST}
+ {-966717000 -9000 1 NDT}
+ {-954624600 -12600 0 NST}
+ {-935267400 -9000 1 NDT}
+ {-922570200 -12600 0 NST}
+ {-903817800 -9000 1 NDT}
+ {-891120600 -12600 0 NST}
+ {-872368200 -9000 0 NWT}
+ {-769395600 -9000 1 NPT}
+ {-765401400 -12600 0 NST}
+ {-757369800 -12600 0 NST}
+ {-746044200 -9000 1 NDT}
+ {-733347000 -12600 0 NST}
+ {-714594600 -9000 1 NDT}
+ {-701897400 -12600 0 NST}
+ {-683145000 -9000 1 NDT}
+ {-670447800 -12600 0 NST}
+ {-651695400 -9000 1 NDT}
+ {-638998200 -12600 0 NST}
+ {-619641000 -9000 1 NDT}
+ {-606943800 -12600 0 NST}
+ {-589401000 -9000 1 NDT}
+ {-576099000 -12600 0 NST}
+ {-557951400 -9000 1 NDT}
+ {-544649400 -12600 0 NST}
+ {-526501800 -9000 1 NDT}
+ {-513199800 -12600 0 NST}
+ {-495052200 -9000 1 NDT}
+ {-481750200 -12600 0 NST}
+ {-463602600 -9000 1 NDT}
+ {-450300600 -12600 0 NST}
+ {-431548200 -9000 1 NDT}
+ {-418246200 -12600 0 NST}
+ {-400098600 -9000 1 NDT}
+ {-386796600 -12600 0 NST}
+ {-368649000 -9000 1 NDT}
+ {-355347000 -12600 0 NST}
+ {-337199400 -9000 1 NDT}
+ {-323897400 -12600 0 NST}
+ {-305749800 -9000 1 NDT}
+ {-289423800 -12600 0 NST}
+ {-273695400 -9000 1 NDT}
+ {-257974200 -12600 0 NST}
+ {-242245800 -9000 1 NDT}
+ {-226524600 -12600 0 NST}
+ {-210796200 -9000 1 NDT}
+ {-195075000 -12600 0 NST}
+ {-179346600 -9000 1 NDT}
+ {-163625400 -12600 0 NST}
+ {-147897000 -9000 1 NDT}
+ {-131571000 -12600 0 NST}
+ {-119903400 -14400 0 AST}
+ {-116445600 -10800 1 ADT}
+ {-100119600 -14400 0 AST}
+ {-84391200 -10800 1 ADT}
+ {-68670000 -14400 0 AST}
+ {-52941600 -10800 1 ADT}
+ {-37220400 -14400 0 AST}
+ {-21492000 -10800 1 ADT}
+ {-5770800 -14400 0 AST}
+ {9957600 -10800 1 ADT}
+ {25678800 -14400 0 AST}
+ {41407200 -10800 1 ADT}
+ {57733200 -14400 0 AST}
+ {73461600 -10800 1 ADT}
+ {89182800 -14400 0 AST}
+ {104911200 -10800 1 ADT}
+ {120632400 -14400 0 AST}
+ {136360800 -10800 1 ADT}
+ {152082000 -14400 0 AST}
+ {167810400 -10800 1 ADT}
+ {183531600 -14400 0 AST}
+ {199260000 -10800 1 ADT}
+ {215586000 -14400 0 AST}
+ {230709600 -10800 1 ADT}
+ {247035600 -14400 0 AST}
+ {262764000 -10800 1 ADT}
+ {278485200 -14400 0 AST}
+ {294213600 -10800 1 ADT}
+ {309934800 -14400 0 AST}
+ {325663200 -10800 1 ADT}
+ {341384400 -14400 0 AST}
+ {357112800 -10800 1 ADT}
+ {372834000 -14400 0 AST}
+ {388562400 -10800 1 ADT}
+ {404888400 -14400 0 AST}
+ {420012000 -10800 1 ADT}
+ {436338000 -14400 0 AST}
+ {452066400 -10800 1 ADT}
+ {467787600 -14400 0 AST}
+ {483516000 -10800 1 ADT}
+ {499237200 -14400 0 AST}
+ {514965600 -10800 1 ADT}
+ {530686800 -14400 0 AST}
+ {544593660 -10800 1 ADT}
+ {562129260 -14400 0 AST}
+ {576043260 -7200 1 ADDT}
+ {594180060 -14400 0 AST}
+ {607492860 -10800 1 ADT}
+ {625633260 -14400 0 AST}
+ {638942460 -10800 1 ADT}
+ {657082860 -14400 0 AST}
+ {670996860 -10800 1 ADT}
+ {688532460 -14400 0 AST}
+ {702446460 -10800 1 ADT}
+ {719982060 -14400 0 AST}
+ {733896060 -10800 1 ADT}
+ {752036460 -14400 0 AST}
+ {765345660 -10800 1 ADT}
+ {783486060 -14400 0 AST}
+ {796795260 -10800 1 ADT}
+ {814935660 -14400 0 AST}
+ {828849660 -10800 1 ADT}
+ {846385260 -14400 0 AST}
+ {860299260 -10800 1 ADT}
+ {877834860 -14400 0 AST}
+ {891748860 -10800 1 ADT}
+ {909284460 -14400 0 AST}
+ {923198460 -10800 1 ADT}
+ {941338860 -14400 0 AST}
+ {954648060 -10800 1 ADT}
+ {972788460 -14400 0 AST}
+ {986097660 -10800 1 ADT}
+ {1004238060 -14400 0 AST}
+ {1018152060 -10800 1 ADT}
+ {1035687660 -14400 0 AST}
+ {1049601660 -10800 1 ADT}
+ {1067137260 -14400 0 AST}
+ {1081051260 -10800 1 ADT}
+ {1099191660 -14400 0 AST}
+ {1112500860 -10800 1 ADT}
+ {1130641260 -14400 0 AST}
+ {1143950460 -10800 1 ADT}
+ {1162090860 -14400 0 AST}
+ {1173585660 -10800 1 ADT}
+ {1194145260 -14400 0 AST}
+ {1205035260 -10800 1 ADT}
+ {1225594860 -14400 0 AST}
+ {1236484860 -10800 1 ADT}
+ {1257044460 -14400 0 AST}
+ {1268539260 -10800 1 ADT}
+ {1289098860 -14400 0 AST}
+ {1299988860 -10800 1 ADT}
+ {1320548460 -14400 0 AST}
+ {1331438460 -10800 1 ADT}
+ {1351998060 -14400 0 AST}
+ {1362888060 -10800 1 ADT}
+ {1383447660 -14400 0 AST}
+ {1394337660 -10800 1 ADT}
+ {1414897260 -14400 0 AST}
+ {1425787260 -10800 1 ADT}
+ {1446346860 -14400 0 AST}
+ {1457841660 -10800 1 ADT}
+ {1478401260 -14400 0 AST}
+ {1489291260 -10800 1 ADT}
+ {1509850860 -14400 0 AST}
+ {1520740860 -10800 1 ADT}
+ {1541300460 -14400 0 AST}
+ {1552190460 -10800 1 ADT}
+ {1572750060 -14400 0 AST}
+ {1583640060 -10800 1 ADT}
+ {1604199660 -14400 0 AST}
+ {1615694460 -10800 1 ADT}
+ {1636254060 -14400 0 AST}
+ {1647144060 -10800 1 ADT}
+ {1667703660 -14400 0 AST}
+ {1678593660 -10800 1 ADT}
+ {1699153260 -14400 0 AST}
+ {1710043260 -10800 1 ADT}
+ {1730602860 -14400 0 AST}
+ {1741492860 -10800 1 ADT}
+ {1762052460 -14400 0 AST}
+ {1772942460 -10800 1 ADT}
+ {1793502060 -14400 0 AST}
+ {1804996860 -10800 1 ADT}
+ {1825556460 -14400 0 AST}
+ {1836446460 -10800 1 ADT}
+ {1857006060 -14400 0 AST}
+ {1867896060 -10800 1 ADT}
+ {1888455660 -14400 0 AST}
+ {1899345660 -10800 1 ADT}
+ {1919905260 -14400 0 AST}
+ {1930795260 -10800 1 ADT}
+ {1951354860 -14400 0 AST}
+ {1962849660 -10800 1 ADT}
+ {1983409260 -14400 0 AST}
+ {1994299260 -10800 1 ADT}
+ {2014858860 -14400 0 AST}
+ {2025748860 -10800 1 ADT}
+ {2046308460 -14400 0 AST}
+ {2057198460 -10800 1 ADT}
+ {2077758060 -14400 0 AST}
+ {2088648060 -10800 1 ADT}
+ {2109207660 -14400 0 AST}
+ {2120097660 -10800 1 ADT}
+ {2140657260 -14400 0 AST}
+ {2152152060 -10800 1 ADT}
+ {2172711660 -14400 0 AST}
+ {2183601660 -10800 1 ADT}
+ {2204161260 -14400 0 AST}
+ {2215051260 -10800 1 ADT}
+ {2235610860 -14400 0 AST}
+ {2246500860 -10800 1 ADT}
+ {2267060460 -14400 0 AST}
+ {2277950460 -10800 1 ADT}
+ {2298510060 -14400 0 AST}
+ {2309400060 -10800 1 ADT}
+ {2329959660 -14400 0 AST}
+ {2341454460 -10800 1 ADT}
+ {2362014060 -14400 0 AST}
+ {2372904060 -10800 1 ADT}
+ {2393463660 -14400 0 AST}
+ {2404353660 -10800 1 ADT}
+ {2424913260 -14400 0 AST}
+ {2435803260 -10800 1 ADT}
+ {2456362860 -14400 0 AST}
+ {2467252860 -10800 1 ADT}
+ {2487812460 -14400 0 AST}
+ {2499307260 -10800 1 ADT}
+ {2519866860 -14400 0 AST}
+ {2530756860 -10800 1 ADT}
+ {2551316460 -14400 0 AST}
+ {2562206460 -10800 1 ADT}
+ {2582766060 -14400 0 AST}
+ {2593656060 -10800 1 ADT}
+ {2614215660 -14400 0 AST}
+ {2625105660 -10800 1 ADT}
+ {2645665260 -14400 0 AST}
+ {2656555260 -10800 1 ADT}
+ {2677114860 -14400 0 AST}
+ {2688609660 -10800 1 ADT}
+ {2709169260 -14400 0 AST}
+ {2720059260 -10800 1 ADT}
+ {2740618860 -14400 0 AST}
+ {2751508860 -10800 1 ADT}
+ {2772068460 -14400 0 AST}
+ {2782958460 -10800 1 ADT}
+ {2803518060 -14400 0 AST}
+ {2814408060 -10800 1 ADT}
+ {2834967660 -14400 0 AST}
+ {2846462460 -10800 1 ADT}
+ {2867022060 -14400 0 AST}
+ {2877912060 -10800 1 ADT}
+ {2898471660 -14400 0 AST}
+ {2909361660 -10800 1 ADT}
+ {2929921260 -14400 0 AST}
+ {2940811260 -10800 1 ADT}
+ {2961370860 -14400 0 AST}
+ {2972260860 -10800 1 ADT}
+ {2992820460 -14400 0 AST}
+ {3003710460 -10800 1 ADT}
+ {3024270060 -14400 0 AST}
+ {3035764860 -10800 1 ADT}
+ {3056324460 -14400 0 AST}
+ {3067214460 -10800 1 ADT}
+ {3087774060 -14400 0 AST}
+ {3098664060 -10800 1 ADT}
+ {3119223660 -14400 0 AST}
+ {3130113660 -10800 1 ADT}
+ {3150673260 -14400 0 AST}
+ {3161563260 -10800 1 ADT}
+ {3182122860 -14400 0 AST}
+ {3193012860 -10800 1 ADT}
+ {3213572460 -14400 0 AST}
+ {3225067260 -10800 1 ADT}
+ {3245626860 -14400 0 AST}
+ {3256516860 -10800 1 ADT}
+ {3277076460 -14400 0 AST}
+ {3287966460 -10800 1 ADT}
+ {3308526060 -14400 0 AST}
+ {3319416060 -10800 1 ADT}
+ {3339975660 -14400 0 AST}
+ {3350865660 -10800 1 ADT}
+ {3371425260 -14400 0 AST}
+ {3382920060 -10800 1 ADT}
+ {3403479660 -14400 0 AST}
+ {3414369660 -10800 1 ADT}
+ {3434929260 -14400 0 AST}
+ {3445819260 -10800 1 ADT}
+ {3466378860 -14400 0 AST}
+ {3477268860 -10800 1 ADT}
+ {3497828460 -14400 0 AST}
+ {3508718460 -10800 1 ADT}
+ {3529278060 -14400 0 AST}
+ {3540168060 -10800 1 ADT}
+ {3560727660 -14400 0 AST}
+ {3572222460 -10800 1 ADT}
+ {3592782060 -14400 0 AST}
+ {3603672060 -10800 1 ADT}
+ {3624231660 -14400 0 AST}
+ {3635121660 -10800 1 ADT}
+ {3655681260 -14400 0 AST}
+ {3666571260 -10800 1 ADT}
+ {3687130860 -14400 0 AST}
+ {3698020860 -10800 1 ADT}
+ {3718580460 -14400 0 AST}
+ {3730075260 -10800 1 ADT}
+ {3750634860 -14400 0 AST}
+ {3761524860 -10800 1 ADT}
+ {3782084460 -14400 0 AST}
+ {3792974460 -10800 1 ADT}
+ {3813534060 -14400 0 AST}
+ {3824424060 -10800 1 ADT}
+ {3844983660 -14400 0 AST}
+ {3855873660 -10800 1 ADT}
+ {3876433260 -14400 0 AST}
+ {3887323260 -10800 1 ADT}
+ {3907882860 -14400 0 AST}
+ {3919377660 -10800 1 ADT}
+ {3939937260 -14400 0 AST}
+ {3950827260 -10800 1 ADT}
+ {3971386860 -14400 0 AST}
+ {3982276860 -10800 1 ADT}
+ {4002836460 -14400 0 AST}
+ {4013726460 -10800 1 ADT}
+ {4034286060 -14400 0 AST}
+ {4045176060 -10800 1 ADT}
+ {4065735660 -14400 0 AST}
+ {4076625660 -10800 1 ADT}
+ {4097185260 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Grand_Turk b/library/tzdata/America/Grand_Turk
new file mode 100644
index 0000000..a455dd5
--- /dev/null
+++ b/library/tzdata/America/Grand_Turk
@@ -0,0 +1,249 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Grand_Turk) {
+ {-9223372036854775808 -17072 0 LMT}
+ {-2524504528 -18432 0 KMT}
+ {-1827687168 -18000 0 EST}
+ {294217200 -14400 1 EDT}
+ {309938400 -18000 0 EST}
+ {325666800 -14400 1 EDT}
+ {341388000 -18000 0 EST}
+ {357116400 -14400 1 EDT}
+ {372837600 -18000 0 EST}
+ {388566000 -14400 1 EDT}
+ {404892000 -18000 0 EST}
+ {420015600 -14400 1 EDT}
+ {436341600 -18000 0 EST}
+ {452070000 -14400 1 EDT}
+ {467791200 -18000 0 EST}
+ {483519600 -14400 1 EDT}
+ {499240800 -18000 0 EST}
+ {514969200 -14400 1 EDT}
+ {530690400 -18000 0 EST}
+ {544604400 -14400 1 EDT}
+ {562140000 -18000 0 EST}
+ {576054000 -14400 1 EDT}
+ {594194400 -18000 0 EST}
+ {607503600 -14400 1 EDT}
+ {625644000 -18000 0 EST}
+ {638953200 -14400 1 EDT}
+ {657093600 -18000 0 EST}
+ {671007600 -14400 1 EDT}
+ {688543200 -18000 0 EST}
+ {702457200 -14400 1 EDT}
+ {719992800 -18000 0 EST}
+ {733906800 -14400 1 EDT}
+ {752047200 -18000 0 EST}
+ {765356400 -14400 1 EDT}
+ {783496800 -18000 0 EST}
+ {796806000 -14400 1 EDT}
+ {814946400 -18000 0 EST}
+ {828860400 -14400 1 EDT}
+ {846396000 -18000 0 EST}
+ {860310000 -14400 1 EDT}
+ {877845600 -18000 0 EST}
+ {891759600 -14400 1 EDT}
+ {909295200 -18000 0 EST}
+ {923209200 -14400 1 EDT}
+ {941349600 -18000 0 EST}
+ {954658800 -14400 1 EDT}
+ {972799200 -18000 0 EST}
+ {986108400 -14400 1 EDT}
+ {1004248800 -18000 0 EST}
+ {1018162800 -14400 1 EDT}
+ {1035698400 -18000 0 EST}
+ {1049612400 -14400 1 EDT}
+ {1067148000 -18000 0 EST}
+ {1081062000 -14400 1 EDT}
+ {1099202400 -18000 0 EST}
+ {1112511600 -14400 1 EDT}
+ {1130652000 -18000 0 EST}
+ {1143961200 -14400 1 EDT}
+ {1162101600 -18000 0 EST}
+ {1173596400 -14400 1 EDT}
+ {1194156000 -18000 0 EST}
+ {1205046000 -14400 1 EDT}
+ {1225605600 -18000 0 EST}
+ {1236495600 -14400 1 EDT}
+ {1257055200 -18000 0 EST}
+ {1268550000 -14400 1 EDT}
+ {1289109600 -18000 0 EST}
+ {1299999600 -14400 1 EDT}
+ {1320559200 -18000 0 EST}
+ {1331449200 -14400 1 EDT}
+ {1352008800 -18000 0 EST}
+ {1362898800 -14400 1 EDT}
+ {1383458400 -18000 0 EST}
+ {1394348400 -14400 1 EDT}
+ {1414908000 -18000 0 EST}
+ {1425798000 -14400 1 EDT}
+ {1446357600 -18000 0 EST}
+ {1457852400 -14400 1 EDT}
+ {1478412000 -18000 0 EST}
+ {1489302000 -14400 1 EDT}
+ {1509861600 -18000 0 EST}
+ {1520751600 -14400 1 EDT}
+ {1541311200 -18000 0 EST}
+ {1552201200 -14400 1 EDT}
+ {1572760800 -18000 0 EST}
+ {1583650800 -14400 1 EDT}
+ {1604210400 -18000 0 EST}
+ {1615705200 -14400 1 EDT}
+ {1636264800 -18000 0 EST}
+ {1647154800 -14400 1 EDT}
+ {1667714400 -18000 0 EST}
+ {1678604400 -14400 1 EDT}
+ {1699164000 -18000 0 EST}
+ {1710054000 -14400 1 EDT}
+ {1730613600 -18000 0 EST}
+ {1741503600 -14400 1 EDT}
+ {1762063200 -18000 0 EST}
+ {1772953200 -14400 1 EDT}
+ {1793512800 -18000 0 EST}
+ {1805007600 -14400 1 EDT}
+ {1825567200 -18000 0 EST}
+ {1836457200 -14400 1 EDT}
+ {1857016800 -18000 0 EST}
+ {1867906800 -14400 1 EDT}
+ {1888466400 -18000 0 EST}
+ {1899356400 -14400 1 EDT}
+ {1919916000 -18000 0 EST}
+ {1930806000 -14400 1 EDT}
+ {1951365600 -18000 0 EST}
+ {1962860400 -14400 1 EDT}
+ {1983420000 -18000 0 EST}
+ {1994310000 -14400 1 EDT}
+ {2014869600 -18000 0 EST}
+ {2025759600 -14400 1 EDT}
+ {2046319200 -18000 0 EST}
+ {2057209200 -14400 1 EDT}
+ {2077768800 -18000 0 EST}
+ {2088658800 -14400 1 EDT}
+ {2109218400 -18000 0 EST}
+ {2120108400 -14400 1 EDT}
+ {2140668000 -18000 0 EST}
+ {2152162800 -14400 1 EDT}
+ {2172722400 -18000 0 EST}
+ {2183612400 -14400 1 EDT}
+ {2204172000 -18000 0 EST}
+ {2215062000 -14400 1 EDT}
+ {2235621600 -18000 0 EST}
+ {2246511600 -14400 1 EDT}
+ {2267071200 -18000 0 EST}
+ {2277961200 -14400 1 EDT}
+ {2298520800 -18000 0 EST}
+ {2309410800 -14400 1 EDT}
+ {2329970400 -18000 0 EST}
+ {2341465200 -14400 1 EDT}
+ {2362024800 -18000 0 EST}
+ {2372914800 -14400 1 EDT}
+ {2393474400 -18000 0 EST}
+ {2404364400 -14400 1 EDT}
+ {2424924000 -18000 0 EST}
+ {2435814000 -14400 1 EDT}
+ {2456373600 -18000 0 EST}
+ {2467263600 -14400 1 EDT}
+ {2487823200 -18000 0 EST}
+ {2499318000 -14400 1 EDT}
+ {2519877600 -18000 0 EST}
+ {2530767600 -14400 1 EDT}
+ {2551327200 -18000 0 EST}
+ {2562217200 -14400 1 EDT}
+ {2582776800 -18000 0 EST}
+ {2593666800 -14400 1 EDT}
+ {2614226400 -18000 0 EST}
+ {2625116400 -14400 1 EDT}
+ {2645676000 -18000 0 EST}
+ {2656566000 -14400 1 EDT}
+ {2677125600 -18000 0 EST}
+ {2688620400 -14400 1 EDT}
+ {2709180000 -18000 0 EST}
+ {2720070000 -14400 1 EDT}
+ {2740629600 -18000 0 EST}
+ {2751519600 -14400 1 EDT}
+ {2772079200 -18000 0 EST}
+ {2782969200 -14400 1 EDT}
+ {2803528800 -18000 0 EST}
+ {2814418800 -14400 1 EDT}
+ {2834978400 -18000 0 EST}
+ {2846473200 -14400 1 EDT}
+ {2867032800 -18000 0 EST}
+ {2877922800 -14400 1 EDT}
+ {2898482400 -18000 0 EST}
+ {2909372400 -14400 1 EDT}
+ {2929932000 -18000 0 EST}
+ {2940822000 -14400 1 EDT}
+ {2961381600 -18000 0 EST}
+ {2972271600 -14400 1 EDT}
+ {2992831200 -18000 0 EST}
+ {3003721200 -14400 1 EDT}
+ {3024280800 -18000 0 EST}
+ {3035775600 -14400 1 EDT}
+ {3056335200 -18000 0 EST}
+ {3067225200 -14400 1 EDT}
+ {3087784800 -18000 0 EST}
+ {3098674800 -14400 1 EDT}
+ {3119234400 -18000 0 EST}
+ {3130124400 -14400 1 EDT}
+ {3150684000 -18000 0 EST}
+ {3161574000 -14400 1 EDT}
+ {3182133600 -18000 0 EST}
+ {3193023600 -14400 1 EDT}
+ {3213583200 -18000 0 EST}
+ {3225078000 -14400 1 EDT}
+ {3245637600 -18000 0 EST}
+ {3256527600 -14400 1 EDT}
+ {3277087200 -18000 0 EST}
+ {3287977200 -14400 1 EDT}
+ {3308536800 -18000 0 EST}
+ {3319426800 -14400 1 EDT}
+ {3339986400 -18000 0 EST}
+ {3350876400 -14400 1 EDT}
+ {3371436000 -18000 0 EST}
+ {3382930800 -14400 1 EDT}
+ {3403490400 -18000 0 EST}
+ {3414380400 -14400 1 EDT}
+ {3434940000 -18000 0 EST}
+ {3445830000 -14400 1 EDT}
+ {3466389600 -18000 0 EST}
+ {3477279600 -14400 1 EDT}
+ {3497839200 -18000 0 EST}
+ {3508729200 -14400 1 EDT}
+ {3529288800 -18000 0 EST}
+ {3540178800 -14400 1 EDT}
+ {3560738400 -18000 0 EST}
+ {3572233200 -14400 1 EDT}
+ {3592792800 -18000 0 EST}
+ {3603682800 -14400 1 EDT}
+ {3624242400 -18000 0 EST}
+ {3635132400 -14400 1 EDT}
+ {3655692000 -18000 0 EST}
+ {3666582000 -14400 1 EDT}
+ {3687141600 -18000 0 EST}
+ {3698031600 -14400 1 EDT}
+ {3718591200 -18000 0 EST}
+ {3730086000 -14400 1 EDT}
+ {3750645600 -18000 0 EST}
+ {3761535600 -14400 1 EDT}
+ {3782095200 -18000 0 EST}
+ {3792985200 -14400 1 EDT}
+ {3813544800 -18000 0 EST}
+ {3824434800 -14400 1 EDT}
+ {3844994400 -18000 0 EST}
+ {3855884400 -14400 1 EDT}
+ {3876444000 -18000 0 EST}
+ {3887334000 -14400 1 EDT}
+ {3907893600 -18000 0 EST}
+ {3919388400 -14400 1 EDT}
+ {3939948000 -18000 0 EST}
+ {3950838000 -14400 1 EDT}
+ {3971397600 -18000 0 EST}
+ {3982287600 -14400 1 EDT}
+ {4002847200 -18000 0 EST}
+ {4013737200 -14400 1 EDT}
+ {4034296800 -18000 0 EST}
+ {4045186800 -14400 1 EDT}
+ {4065746400 -18000 0 EST}
+ {4076636400 -14400 1 EDT}
+ {4097196000 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Grenada b/library/tzdata/America/Grenada
new file mode 100644
index 0000000..3c2919b
--- /dev/null
+++ b/library/tzdata/America/Grenada
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Grenada) {
+ {-9223372036854775808 -14820 0 LMT}
+ {-1846266780 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Guadeloupe b/library/tzdata/America/Guadeloupe
new file mode 100644
index 0000000..b1987ce
--- /dev/null
+++ b/library/tzdata/America/Guadeloupe
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Guadeloupe) {
+ {-9223372036854775808 -14768 0 LMT}
+ {-1848254032 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Guatemala b/library/tzdata/America/Guatemala
new file mode 100644
index 0000000..e4db5ac
--- /dev/null
+++ b/library/tzdata/America/Guatemala
@@ -0,0 +1,14 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Guatemala) {
+ {-9223372036854775808 -21724 0 LMT}
+ {-1617040676 -21600 0 CST}
+ {123055200 -18000 1 CDT}
+ {130914000 -21600 0 CST}
+ {422344800 -18000 1 CDT}
+ {433054800 -21600 0 CST}
+ {669708000 -18000 1 CDT}
+ {684219600 -21600 0 CST}
+ {1146376800 -18000 1 CDT}
+ {1159678800 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Guayaquil b/library/tzdata/America/Guayaquil
new file mode 100644
index 0000000..e940a5b
--- /dev/null
+++ b/library/tzdata/America/Guayaquil
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Guayaquil) {
+ {-9223372036854775808 -19160 0 LMT}
+ {-2524502440 -18840 0 QMT}
+ {-1230749160 -18000 0 ECT}
+}
diff --git a/library/tzdata/America/Guyana b/library/tzdata/America/Guyana
new file mode 100644
index 0000000..c58a989
--- /dev/null
+++ b/library/tzdata/America/Guyana
@@ -0,0 +1,9 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Guyana) {
+ {-9223372036854775808 -13960 0 LMT}
+ {-1730578040 -13500 0 GBGT}
+ {-113688900 -13500 0 GYT}
+ {176010300 -10800 0 GYT}
+ {662698800 -14400 0 GYT}
+}
diff --git a/library/tzdata/America/Halifax b/library/tzdata/America/Halifax
new file mode 100644
index 0000000..76f016a
--- /dev/null
+++ b/library/tzdata/America/Halifax
@@ -0,0 +1,361 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Halifax) {
+ {-9223372036854775808 -15264 0 LMT}
+ {-2131645536 -14400 0 AST}
+ {-1696276800 -10800 1 ADT}
+ {-1680469200 -14400 0 AST}
+ {-1640980800 -14400 0 AST}
+ {-1632074400 -10800 1 ADT}
+ {-1614798000 -14400 0 AST}
+ {-1609444800 -14400 0 AST}
+ {-1566763200 -10800 1 ADT}
+ {-1557090000 -14400 0 AST}
+ {-1535486400 -10800 1 ADT}
+ {-1524949200 -14400 0 AST}
+ {-1504468800 -10800 1 ADT}
+ {-1493413200 -14400 0 AST}
+ {-1472414400 -10800 1 ADT}
+ {-1461963600 -14400 0 AST}
+ {-1440964800 -10800 1 ADT}
+ {-1429390800 -14400 0 AST}
+ {-1409515200 -10800 1 ADT}
+ {-1396731600 -14400 0 AST}
+ {-1376856000 -10800 1 ADT}
+ {-1366491600 -14400 0 AST}
+ {-1346616000 -10800 1 ADT}
+ {-1333832400 -14400 0 AST}
+ {-1313956800 -10800 1 ADT}
+ {-1303678800 -14400 0 AST}
+ {-1282507200 -10800 1 ADT}
+ {-1272661200 -14400 0 AST}
+ {-1251057600 -10800 1 ADT}
+ {-1240088400 -14400 0 AST}
+ {-1219608000 -10800 1 ADT}
+ {-1207429200 -14400 0 AST}
+ {-1188763200 -10800 1 ADT}
+ {-1175979600 -14400 0 AST}
+ {-1157313600 -10800 1 ADT}
+ {-1143925200 -14400 0 AST}
+ {-1124049600 -10800 1 ADT}
+ {-1113771600 -14400 0 AST}
+ {-1091390400 -10800 1 ADT}
+ {-1081026000 -14400 0 AST}
+ {-1059854400 -10800 1 ADT}
+ {-1050786000 -14400 0 AST}
+ {-1030910400 -10800 1 ADT}
+ {-1018126800 -14400 0 AST}
+ {-999460800 -10800 1 ADT}
+ {-986677200 -14400 0 AST}
+ {-965592000 -10800 1 ADT}
+ {-955227600 -14400 0 AST}
+ {-935956800 -10800 1 ADT}
+ {-923173200 -14400 0 AST}
+ {-904507200 -10800 1 ADT}
+ {-891723600 -14400 0 AST}
+ {-880221600 -10800 0 AWT}
+ {-769395600 -10800 1 APT}
+ {-765399600 -14400 0 AST}
+ {-757368000 -14400 0 AST}
+ {-747252000 -10800 1 ADT}
+ {-733950000 -14400 0 AST}
+ {-715802400 -10800 1 ADT}
+ {-702500400 -14400 0 AST}
+ {-684352800 -10800 1 ADT}
+ {-671050800 -14400 0 AST}
+ {-652903200 -10800 1 ADT}
+ {-639601200 -14400 0 AST}
+ {-589399200 -10800 1 ADT}
+ {-576097200 -14400 0 AST}
+ {-557949600 -10800 1 ADT}
+ {-544647600 -14400 0 AST}
+ {-526500000 -10800 1 ADT}
+ {-513198000 -14400 0 AST}
+ {-495050400 -10800 1 ADT}
+ {-481748400 -14400 0 AST}
+ {-431546400 -10800 1 ADT}
+ {-418244400 -14400 0 AST}
+ {-400096800 -10800 1 ADT}
+ {-386794800 -14400 0 AST}
+ {-368647200 -10800 1 ADT}
+ {-355345200 -14400 0 AST}
+ {-337197600 -10800 1 ADT}
+ {-323895600 -14400 0 AST}
+ {-242244000 -10800 1 ADT}
+ {-226522800 -14400 0 AST}
+ {-210794400 -10800 1 ADT}
+ {-195073200 -14400 0 AST}
+ {-179344800 -10800 1 ADT}
+ {-163623600 -14400 0 AST}
+ {-147895200 -10800 1 ADT}
+ {-131569200 -14400 0 AST}
+ {-116445600 -10800 1 ADT}
+ {-100119600 -14400 0 AST}
+ {-84391200 -10800 1 ADT}
+ {-68670000 -14400 0 AST}
+ {-52941600 -10800 1 ADT}
+ {-37220400 -14400 0 AST}
+ {-21492000 -10800 1 ADT}
+ {-5770800 -14400 0 AST}
+ {9957600 -10800 1 ADT}
+ {25678800 -14400 0 AST}
+ {41407200 -10800 1 ADT}
+ {57733200 -14400 0 AST}
+ {73461600 -10800 1 ADT}
+ {89182800 -14400 0 AST}
+ {104911200 -10800 1 ADT}
+ {120632400 -14400 0 AST}
+ {126244800 -14400 0 AST}
+ {136360800 -10800 1 ADT}
+ {152082000 -14400 0 AST}
+ {167810400 -10800 1 ADT}
+ {183531600 -14400 0 AST}
+ {199260000 -10800 1 ADT}
+ {215586000 -14400 0 AST}
+ {230709600 -10800 1 ADT}
+ {247035600 -14400 0 AST}
+ {262764000 -10800 1 ADT}
+ {278485200 -14400 0 AST}
+ {294213600 -10800 1 ADT}
+ {309934800 -14400 0 AST}
+ {325663200 -10800 1 ADT}
+ {341384400 -14400 0 AST}
+ {357112800 -10800 1 ADT}
+ {372834000 -14400 0 AST}
+ {388562400 -10800 1 ADT}
+ {404888400 -14400 0 AST}
+ {420012000 -10800 1 ADT}
+ {436338000 -14400 0 AST}
+ {452066400 -10800 1 ADT}
+ {467787600 -14400 0 AST}
+ {483516000 -10800 1 ADT}
+ {499237200 -14400 0 AST}
+ {514965600 -10800 1 ADT}
+ {530686800 -14400 0 AST}
+ {544600800 -10800 1 ADT}
+ {562136400 -14400 0 AST}
+ {576050400 -10800 1 ADT}
+ {594190800 -14400 0 AST}
+ {607500000 -10800 1 ADT}
+ {625640400 -14400 0 AST}
+ {638949600 -10800 1 ADT}
+ {657090000 -14400 0 AST}
+ {671004000 -10800 1 ADT}
+ {688539600 -14400 0 AST}
+ {702453600 -10800 1 ADT}
+ {719989200 -14400 0 AST}
+ {733903200 -10800 1 ADT}
+ {752043600 -14400 0 AST}
+ {765352800 -10800 1 ADT}
+ {783493200 -14400 0 AST}
+ {796802400 -10800 1 ADT}
+ {814942800 -14400 0 AST}
+ {828856800 -10800 1 ADT}
+ {846392400 -14400 0 AST}
+ {860306400 -10800 1 ADT}
+ {877842000 -14400 0 AST}
+ {891756000 -10800 1 ADT}
+ {909291600 -14400 0 AST}
+ {923205600 -10800 1 ADT}
+ {941346000 -14400 0 AST}
+ {954655200 -10800 1 ADT}
+ {972795600 -14400 0 AST}
+ {986104800 -10800 1 ADT}
+ {1004245200 -14400 0 AST}
+ {1018159200 -10800 1 ADT}
+ {1035694800 -14400 0 AST}
+ {1049608800 -10800 1 ADT}
+ {1067144400 -14400 0 AST}
+ {1081058400 -10800 1 ADT}
+ {1099198800 -14400 0 AST}
+ {1112508000 -10800 1 ADT}
+ {1130648400 -14400 0 AST}
+ {1143957600 -10800 1 ADT}
+ {1162098000 -14400 0 AST}
+ {1173592800 -10800 1 ADT}
+ {1194152400 -14400 0 AST}
+ {1205042400 -10800 1 ADT}
+ {1225602000 -14400 0 AST}
+ {1236492000 -10800 1 ADT}
+ {1257051600 -14400 0 AST}
+ {1268546400 -10800 1 ADT}
+ {1289106000 -14400 0 AST}
+ {1299996000 -10800 1 ADT}
+ {1320555600 -14400 0 AST}
+ {1331445600 -10800 1 ADT}
+ {1352005200 -14400 0 AST}
+ {1362895200 -10800 1 ADT}
+ {1383454800 -14400 0 AST}
+ {1394344800 -10800 1 ADT}
+ {1414904400 -14400 0 AST}
+ {1425794400 -10800 1 ADT}
+ {1446354000 -14400 0 AST}
+ {1457848800 -10800 1 ADT}
+ {1478408400 -14400 0 AST}
+ {1489298400 -10800 1 ADT}
+ {1509858000 -14400 0 AST}
+ {1520748000 -10800 1 ADT}
+ {1541307600 -14400 0 AST}
+ {1552197600 -10800 1 ADT}
+ {1572757200 -14400 0 AST}
+ {1583647200 -10800 1 ADT}
+ {1604206800 -14400 0 AST}
+ {1615701600 -10800 1 ADT}
+ {1636261200 -14400 0 AST}
+ {1647151200 -10800 1 ADT}
+ {1667710800 -14400 0 AST}
+ {1678600800 -10800 1 ADT}
+ {1699160400 -14400 0 AST}
+ {1710050400 -10800 1 ADT}
+ {1730610000 -14400 0 AST}
+ {1741500000 -10800 1 ADT}
+ {1762059600 -14400 0 AST}
+ {1772949600 -10800 1 ADT}
+ {1793509200 -14400 0 AST}
+ {1805004000 -10800 1 ADT}
+ {1825563600 -14400 0 AST}
+ {1836453600 -10800 1 ADT}
+ {1857013200 -14400 0 AST}
+ {1867903200 -10800 1 ADT}
+ {1888462800 -14400 0 AST}
+ {1899352800 -10800 1 ADT}
+ {1919912400 -14400 0 AST}
+ {1930802400 -10800 1 ADT}
+ {1951362000 -14400 0 AST}
+ {1962856800 -10800 1 ADT}
+ {1983416400 -14400 0 AST}
+ {1994306400 -10800 1 ADT}
+ {2014866000 -14400 0 AST}
+ {2025756000 -10800 1 ADT}
+ {2046315600 -14400 0 AST}
+ {2057205600 -10800 1 ADT}
+ {2077765200 -14400 0 AST}
+ {2088655200 -10800 1 ADT}
+ {2109214800 -14400 0 AST}
+ {2120104800 -10800 1 ADT}
+ {2140664400 -14400 0 AST}
+ {2152159200 -10800 1 ADT}
+ {2172718800 -14400 0 AST}
+ {2183608800 -10800 1 ADT}
+ {2204168400 -14400 0 AST}
+ {2215058400 -10800 1 ADT}
+ {2235618000 -14400 0 AST}
+ {2246508000 -10800 1 ADT}
+ {2267067600 -14400 0 AST}
+ {2277957600 -10800 1 ADT}
+ {2298517200 -14400 0 AST}
+ {2309407200 -10800 1 ADT}
+ {2329966800 -14400 0 AST}
+ {2341461600 -10800 1 ADT}
+ {2362021200 -14400 0 AST}
+ {2372911200 -10800 1 ADT}
+ {2393470800 -14400 0 AST}
+ {2404360800 -10800 1 ADT}
+ {2424920400 -14400 0 AST}
+ {2435810400 -10800 1 ADT}
+ {2456370000 -14400 0 AST}
+ {2467260000 -10800 1 ADT}
+ {2487819600 -14400 0 AST}
+ {2499314400 -10800 1 ADT}
+ {2519874000 -14400 0 AST}
+ {2530764000 -10800 1 ADT}
+ {2551323600 -14400 0 AST}
+ {2562213600 -10800 1 ADT}
+ {2582773200 -14400 0 AST}
+ {2593663200 -10800 1 ADT}
+ {2614222800 -14400 0 AST}
+ {2625112800 -10800 1 ADT}
+ {2645672400 -14400 0 AST}
+ {2656562400 -10800 1 ADT}
+ {2677122000 -14400 0 AST}
+ {2688616800 -10800 1 ADT}
+ {2709176400 -14400 0 AST}
+ {2720066400 -10800 1 ADT}
+ {2740626000 -14400 0 AST}
+ {2751516000 -10800 1 ADT}
+ {2772075600 -14400 0 AST}
+ {2782965600 -10800 1 ADT}
+ {2803525200 -14400 0 AST}
+ {2814415200 -10800 1 ADT}
+ {2834974800 -14400 0 AST}
+ {2846469600 -10800 1 ADT}
+ {2867029200 -14400 0 AST}
+ {2877919200 -10800 1 ADT}
+ {2898478800 -14400 0 AST}
+ {2909368800 -10800 1 ADT}
+ {2929928400 -14400 0 AST}
+ {2940818400 -10800 1 ADT}
+ {2961378000 -14400 0 AST}
+ {2972268000 -10800 1 ADT}
+ {2992827600 -14400 0 AST}
+ {3003717600 -10800 1 ADT}
+ {3024277200 -14400 0 AST}
+ {3035772000 -10800 1 ADT}
+ {3056331600 -14400 0 AST}
+ {3067221600 -10800 1 ADT}
+ {3087781200 -14400 0 AST}
+ {3098671200 -10800 1 ADT}
+ {3119230800 -14400 0 AST}
+ {3130120800 -10800 1 ADT}
+ {3150680400 -14400 0 AST}
+ {3161570400 -10800 1 ADT}
+ {3182130000 -14400 0 AST}
+ {3193020000 -10800 1 ADT}
+ {3213579600 -14400 0 AST}
+ {3225074400 -10800 1 ADT}
+ {3245634000 -14400 0 AST}
+ {3256524000 -10800 1 ADT}
+ {3277083600 -14400 0 AST}
+ {3287973600 -10800 1 ADT}
+ {3308533200 -14400 0 AST}
+ {3319423200 -10800 1 ADT}
+ {3339982800 -14400 0 AST}
+ {3350872800 -10800 1 ADT}
+ {3371432400 -14400 0 AST}
+ {3382927200 -10800 1 ADT}
+ {3403486800 -14400 0 AST}
+ {3414376800 -10800 1 ADT}
+ {3434936400 -14400 0 AST}
+ {3445826400 -10800 1 ADT}
+ {3466386000 -14400 0 AST}
+ {3477276000 -10800 1 ADT}
+ {3497835600 -14400 0 AST}
+ {3508725600 -10800 1 ADT}
+ {3529285200 -14400 0 AST}
+ {3540175200 -10800 1 ADT}
+ {3560734800 -14400 0 AST}
+ {3572229600 -10800 1 ADT}
+ {3592789200 -14400 0 AST}
+ {3603679200 -10800 1 ADT}
+ {3624238800 -14400 0 AST}
+ {3635128800 -10800 1 ADT}
+ {3655688400 -14400 0 AST}
+ {3666578400 -10800 1 ADT}
+ {3687138000 -14400 0 AST}
+ {3698028000 -10800 1 ADT}
+ {3718587600 -14400 0 AST}
+ {3730082400 -10800 1 ADT}
+ {3750642000 -14400 0 AST}
+ {3761532000 -10800 1 ADT}
+ {3782091600 -14400 0 AST}
+ {3792981600 -10800 1 ADT}
+ {3813541200 -14400 0 AST}
+ {3824431200 -10800 1 ADT}
+ {3844990800 -14400 0 AST}
+ {3855880800 -10800 1 ADT}
+ {3876440400 -14400 0 AST}
+ {3887330400 -10800 1 ADT}
+ {3907890000 -14400 0 AST}
+ {3919384800 -10800 1 ADT}
+ {3939944400 -14400 0 AST}
+ {3950834400 -10800 1 ADT}
+ {3971394000 -14400 0 AST}
+ {3982284000 -10800 1 ADT}
+ {4002843600 -14400 0 AST}
+ {4013733600 -10800 1 ADT}
+ {4034293200 -14400 0 AST}
+ {4045183200 -10800 1 ADT}
+ {4065742800 -14400 0 AST}
+ {4076632800 -10800 1 ADT}
+ {4097192400 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Havana b/library/tzdata/America/Havana
new file mode 100644
index 0000000..f37b98e
--- /dev/null
+++ b/library/tzdata/America/Havana
@@ -0,0 +1,285 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Havana) {
+ {-9223372036854775808 -19768 0 LMT}
+ {-2524501832 -19776 0 HMT}
+ {-1402813824 -18000 0 CST}
+ {-1311534000 -14400 1 CDT}
+ {-1300996800 -18000 0 CST}
+ {-933534000 -14400 1 CDT}
+ {-925675200 -18000 0 CST}
+ {-902084400 -14400 1 CDT}
+ {-893620800 -18000 0 CST}
+ {-870030000 -14400 1 CDT}
+ {-862171200 -18000 0 CST}
+ {-775681200 -14400 1 CDT}
+ {-767822400 -18000 0 CST}
+ {-744231600 -14400 1 CDT}
+ {-736372800 -18000 0 CST}
+ {-144702000 -14400 1 CDT}
+ {-134251200 -18000 0 CST}
+ {-113425200 -14400 1 CDT}
+ {-102542400 -18000 0 CST}
+ {-86295600 -14400 1 CDT}
+ {-72907200 -18000 0 CST}
+ {-54154800 -14400 1 CDT}
+ {-41457600 -18000 0 CST}
+ {-21495600 -14400 1 CDT}
+ {-5774400 -18000 0 CST}
+ {9954000 -14400 1 CDT}
+ {25675200 -18000 0 CST}
+ {41403600 -14400 1 CDT}
+ {57729600 -18000 0 CST}
+ {73458000 -14400 1 CDT}
+ {87364800 -18000 0 CST}
+ {104907600 -14400 1 CDT}
+ {118900800 -18000 0 CST}
+ {136357200 -14400 1 CDT}
+ {150436800 -18000 0 CST}
+ {167806800 -14400 1 CDT}
+ {183528000 -18000 0 CST}
+ {199256400 -14400 1 CDT}
+ {215582400 -18000 0 CST}
+ {230706000 -14400 1 CDT}
+ {247032000 -18000 0 CST}
+ {263365200 -14400 1 CDT}
+ {276667200 -18000 0 CST}
+ {290581200 -14400 1 CDT}
+ {308721600 -18000 0 CST}
+ {322030800 -14400 1 CDT}
+ {340171200 -18000 0 CST}
+ {358318800 -14400 1 CDT}
+ {371620800 -18000 0 CST}
+ {389768400 -14400 1 CDT}
+ {403070400 -18000 0 CST}
+ {421218000 -14400 1 CDT}
+ {434520000 -18000 0 CST}
+ {452667600 -14400 1 CDT}
+ {466574400 -18000 0 CST}
+ {484117200 -14400 1 CDT}
+ {498024000 -18000 0 CST}
+ {511333200 -14400 1 CDT}
+ {529473600 -18000 0 CST}
+ {542782800 -14400 1 CDT}
+ {560923200 -18000 0 CST}
+ {574837200 -14400 1 CDT}
+ {592372800 -18000 0 CST}
+ {606286800 -14400 1 CDT}
+ {623822400 -18000 0 CST}
+ {638946000 -14400 1 CDT}
+ {655876800 -18000 0 CST}
+ {671000400 -14400 1 CDT}
+ {687330000 -18000 0 CST}
+ {702450000 -14400 1 CDT}
+ {718779600 -18000 0 CST}
+ {733899600 -14400 1 CDT}
+ {750229200 -18000 0 CST}
+ {765349200 -14400 1 CDT}
+ {781678800 -18000 0 CST}
+ {796798800 -14400 1 CDT}
+ {813128400 -18000 0 CST}
+ {828853200 -14400 1 CDT}
+ {844578000 -18000 0 CST}
+ {860302800 -14400 1 CDT}
+ {876632400 -18000 0 CST}
+ {891147600 -14400 1 CDT}
+ {909291600 -18000 0 CST}
+ {922597200 -14400 1 CDT}
+ {941346000 -18000 0 CST}
+ {954651600 -14400 1 CDT}
+ {972795600 -18000 0 CST}
+ {986101200 -14400 1 CDT}
+ {1004245200 -18000 0 CST}
+ {1018155600 -14400 1 CDT}
+ {1035694800 -18000 0 CST}
+ {1049605200 -14400 1 CDT}
+ {1067144400 -18000 0 CST}
+ {1081054800 -14400 1 CDT}
+ {1162098000 -18000 0 CST}
+ {1173589200 -14400 1 CDT}
+ {1193547600 -18000 0 CST}
+ {1205643600 -14400 1 CDT}
+ {1224997200 -18000 0 CST}
+ {1236488400 -14400 1 CDT}
+ {1256446800 -18000 0 CST}
+ {1268542800 -14400 1 CDT}
+ {1288501200 -18000 0 CST}
+ {1300597200 -14400 1 CDT}
+ {1319950800 -18000 0 CST}
+ {1331442000 -14400 1 CDT}
+ {1351400400 -18000 0 CST}
+ {1362891600 -14400 1 CDT}
+ {1382850000 -18000 0 CST}
+ {1394341200 -14400 1 CDT}
+ {1414299600 -18000 0 CST}
+ {1425790800 -14400 1 CDT}
+ {1445749200 -18000 0 CST}
+ {1457845200 -14400 1 CDT}
+ {1477803600 -18000 0 CST}
+ {1489294800 -14400 1 CDT}
+ {1509253200 -18000 0 CST}
+ {1520744400 -14400 1 CDT}
+ {1540702800 -18000 0 CST}
+ {1552194000 -14400 1 CDT}
+ {1572152400 -18000 0 CST}
+ {1583643600 -14400 1 CDT}
+ {1603602000 -18000 0 CST}
+ {1615698000 -14400 1 CDT}
+ {1635656400 -18000 0 CST}
+ {1647147600 -14400 1 CDT}
+ {1667106000 -18000 0 CST}
+ {1678597200 -14400 1 CDT}
+ {1698555600 -18000 0 CST}
+ {1710046800 -14400 1 CDT}
+ {1730005200 -18000 0 CST}
+ {1741496400 -14400 1 CDT}
+ {1761454800 -18000 0 CST}
+ {1772946000 -14400 1 CDT}
+ {1792904400 -18000 0 CST}
+ {1805000400 -14400 1 CDT}
+ {1824958800 -18000 0 CST}
+ {1836450000 -14400 1 CDT}
+ {1856408400 -18000 0 CST}
+ {1867899600 -14400 1 CDT}
+ {1887858000 -18000 0 CST}
+ {1899349200 -14400 1 CDT}
+ {1919307600 -18000 0 CST}
+ {1930798800 -14400 1 CDT}
+ {1950757200 -18000 0 CST}
+ {1962853200 -14400 1 CDT}
+ {1982811600 -18000 0 CST}
+ {1994302800 -14400 1 CDT}
+ {2014261200 -18000 0 CST}
+ {2025752400 -14400 1 CDT}
+ {2045710800 -18000 0 CST}
+ {2057202000 -14400 1 CDT}
+ {2077160400 -18000 0 CST}
+ {2088651600 -14400 1 CDT}
+ {2108610000 -18000 0 CST}
+ {2120101200 -14400 1 CDT}
+ {2140059600 -18000 0 CST}
+ {2152155600 -14400 1 CDT}
+ {2172114000 -18000 0 CST}
+ {2183605200 -14400 1 CDT}
+ {2203563600 -18000 0 CST}
+ {2215054800 -14400 1 CDT}
+ {2235013200 -18000 0 CST}
+ {2246504400 -14400 1 CDT}
+ {2266462800 -18000 0 CST}
+ {2277954000 -14400 1 CDT}
+ {2297912400 -18000 0 CST}
+ {2309403600 -14400 1 CDT}
+ {2329362000 -18000 0 CST}
+ {2341458000 -14400 1 CDT}
+ {2361416400 -18000 0 CST}
+ {2372907600 -14400 1 CDT}
+ {2392866000 -18000 0 CST}
+ {2404357200 -14400 1 CDT}
+ {2424315600 -18000 0 CST}
+ {2435806800 -14400 1 CDT}
+ {2455765200 -18000 0 CST}
+ {2467256400 -14400 1 CDT}
+ {2487214800 -18000 0 CST}
+ {2499310800 -14400 1 CDT}
+ {2519269200 -18000 0 CST}
+ {2530760400 -14400 1 CDT}
+ {2550718800 -18000 0 CST}
+ {2562210000 -14400 1 CDT}
+ {2582168400 -18000 0 CST}
+ {2593659600 -14400 1 CDT}
+ {2613618000 -18000 0 CST}
+ {2625109200 -14400 1 CDT}
+ {2645067600 -18000 0 CST}
+ {2656558800 -14400 1 CDT}
+ {2676517200 -18000 0 CST}
+ {2688613200 -14400 1 CDT}
+ {2708571600 -18000 0 CST}
+ {2720062800 -14400 1 CDT}
+ {2740021200 -18000 0 CST}
+ {2751512400 -14400 1 CDT}
+ {2771470800 -18000 0 CST}
+ {2782962000 -14400 1 CDT}
+ {2802920400 -18000 0 CST}
+ {2814411600 -14400 1 CDT}
+ {2834370000 -18000 0 CST}
+ {2846466000 -14400 1 CDT}
+ {2866424400 -18000 0 CST}
+ {2877915600 -14400 1 CDT}
+ {2897874000 -18000 0 CST}
+ {2909365200 -14400 1 CDT}
+ {2929323600 -18000 0 CST}
+ {2940814800 -14400 1 CDT}
+ {2960773200 -18000 0 CST}
+ {2972264400 -14400 1 CDT}
+ {2992222800 -18000 0 CST}
+ {3003714000 -14400 1 CDT}
+ {3023672400 -18000 0 CST}
+ {3035768400 -14400 1 CDT}
+ {3055726800 -18000 0 CST}
+ {3067218000 -14400 1 CDT}
+ {3087176400 -18000 0 CST}
+ {3098667600 -14400 1 CDT}
+ {3118626000 -18000 0 CST}
+ {3130117200 -14400 1 CDT}
+ {3150075600 -18000 0 CST}
+ {3161566800 -14400 1 CDT}
+ {3181525200 -18000 0 CST}
+ {3193016400 -14400 1 CDT}
+ {3212974800 -18000 0 CST}
+ {3225070800 -14400 1 CDT}
+ {3245029200 -18000 0 CST}
+ {3256520400 -14400 1 CDT}
+ {3276478800 -18000 0 CST}
+ {3287970000 -14400 1 CDT}
+ {3307928400 -18000 0 CST}
+ {3319419600 -14400 1 CDT}
+ {3339378000 -18000 0 CST}
+ {3350869200 -14400 1 CDT}
+ {3370827600 -18000 0 CST}
+ {3382923600 -14400 1 CDT}
+ {3402882000 -18000 0 CST}
+ {3414373200 -14400 1 CDT}
+ {3434331600 -18000 0 CST}
+ {3445822800 -14400 1 CDT}
+ {3465781200 -18000 0 CST}
+ {3477272400 -14400 1 CDT}
+ {3497230800 -18000 0 CST}
+ {3508722000 -14400 1 CDT}
+ {3528680400 -18000 0 CST}
+ {3540171600 -14400 1 CDT}
+ {3560130000 -18000 0 CST}
+ {3572226000 -14400 1 CDT}
+ {3592184400 -18000 0 CST}
+ {3603675600 -14400 1 CDT}
+ {3623634000 -18000 0 CST}
+ {3635125200 -14400 1 CDT}
+ {3655083600 -18000 0 CST}
+ {3666574800 -14400 1 CDT}
+ {3686533200 -18000 0 CST}
+ {3698024400 -14400 1 CDT}
+ {3717982800 -18000 0 CST}
+ {3730078800 -14400 1 CDT}
+ {3750037200 -18000 0 CST}
+ {3761528400 -14400 1 CDT}
+ {3781486800 -18000 0 CST}
+ {3792978000 -14400 1 CDT}
+ {3812936400 -18000 0 CST}
+ {3824427600 -14400 1 CDT}
+ {3844386000 -18000 0 CST}
+ {3855877200 -14400 1 CDT}
+ {3875835600 -18000 0 CST}
+ {3887326800 -14400 1 CDT}
+ {3907285200 -18000 0 CST}
+ {3919381200 -14400 1 CDT}
+ {3939339600 -18000 0 CST}
+ {3950830800 -14400 1 CDT}
+ {3970789200 -18000 0 CST}
+ {3982280400 -14400 1 CDT}
+ {4002238800 -18000 0 CST}
+ {4013730000 -14400 1 CDT}
+ {4033688400 -18000 0 CST}
+ {4045179600 -14400 1 CDT}
+ {4065138000 -18000 0 CST}
+ {4076629200 -14400 1 CDT}
+ {4096587600 -18000 0 CST}
+}
diff --git a/library/tzdata/America/Hermosillo b/library/tzdata/America/Hermosillo
new file mode 100644
index 0000000..779020e
--- /dev/null
+++ b/library/tzdata/America/Hermosillo
@@ -0,0 +1,21 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Hermosillo) {
+ {-9223372036854775808 -26632 0 LMT}
+ {-1514739600 -25200 0 MST}
+ {-1343066400 -21600 0 CST}
+ {-1234807200 -25200 0 MST}
+ {-1220292000 -21600 0 CST}
+ {-1207159200 -25200 0 MST}
+ {-1191344400 -21600 0 CST}
+ {-873828000 -25200 0 MST}
+ {-661539600 -28800 0 PST}
+ {28800 -25200 0 MST}
+ {828867600 -21600 1 MDT}
+ {846403200 -25200 0 MST}
+ {860317200 -21600 1 MDT}
+ {877852800 -25200 0 MST}
+ {891766800 -21600 1 MDT}
+ {909302400 -25200 0 MST}
+ {915174000 -25200 0 MST}
+}
diff --git a/library/tzdata/America/Indiana/Indianapolis b/library/tzdata/America/Indiana/Indianapolis
new file mode 100644
index 0000000..63c410c
--- /dev/null
+++ b/library/tzdata/America/Indiana/Indianapolis
@@ -0,0 +1,234 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Indiana/Indianapolis) {
+ {-9223372036854775808 -20678 0 LMT}
+ {-2717647200 -21600 0 CST}
+ {-1633276800 -18000 1 CDT}
+ {-1615136400 -21600 0 CST}
+ {-1601827200 -18000 1 CDT}
+ {-1583686800 -21600 0 CST}
+ {-1577901600 -21600 0 CST}
+ {-900259200 -18000 1 CDT}
+ {-891795600 -21600 0 CST}
+ {-883591200 -21600 0 CST}
+ {-880214400 -18000 1 CWT}
+ {-769395600 -18000 1 CPT}
+ {-765392400 -21600 0 CST}
+ {-757360800 -21600 0 CST}
+ {-747244800 -18000 1 CDT}
+ {-733942800 -21600 0 CST}
+ {-715795200 -18000 1 CDT}
+ {-702493200 -21600 0 CST}
+ {-684345600 -18000 1 CDT}
+ {-671043600 -21600 0 CST}
+ {-652896000 -18000 1 CDT}
+ {-639594000 -21600 0 CST}
+ {-620841600 -18000 1 CDT}
+ {-608144400 -21600 0 CST}
+ {-589392000 -18000 1 CDT}
+ {-576090000 -21600 0 CST}
+ {-557942400 -18000 1 CDT}
+ {-544640400 -21600 0 CST}
+ {-526492800 -18000 1 CDT}
+ {-513190800 -21600 0 CST}
+ {-495043200 -18000 1 CDT}
+ {-481741200 -21600 0 CST}
+ {-463593600 -18000 0 EST}
+ {-386787600 -21600 0 CST}
+ {-368640000 -18000 0 EST}
+ {-31518000 -18000 0 EST}
+ {-21488400 -14400 1 EDT}
+ {-5767200 -18000 0 EST}
+ {9961200 -14400 1 EDT}
+ {25682400 -18000 0 EST}
+ {31554000 -18000 0 EST}
+ {1136091600 -18000 0 EST}
+ {1143961200 -14400 1 EDT}
+ {1162101600 -18000 0 EST}
+ {1173596400 -14400 1 EDT}
+ {1194156000 -18000 0 EST}
+ {1205046000 -14400 1 EDT}
+ {1225605600 -18000 0 EST}
+ {1236495600 -14400 1 EDT}
+ {1257055200 -18000 0 EST}
+ {1268550000 -14400 1 EDT}
+ {1289109600 -18000 0 EST}
+ {1299999600 -14400 1 EDT}
+ {1320559200 -18000 0 EST}
+ {1331449200 -14400 1 EDT}
+ {1352008800 -18000 0 EST}
+ {1362898800 -14400 1 EDT}
+ {1383458400 -18000 0 EST}
+ {1394348400 -14400 1 EDT}
+ {1414908000 -18000 0 EST}
+ {1425798000 -14400 1 EDT}
+ {1446357600 -18000 0 EST}
+ {1457852400 -14400 1 EDT}
+ {1478412000 -18000 0 EST}
+ {1489302000 -14400 1 EDT}
+ {1509861600 -18000 0 EST}
+ {1520751600 -14400 1 EDT}
+ {1541311200 -18000 0 EST}
+ {1552201200 -14400 1 EDT}
+ {1572760800 -18000 0 EST}
+ {1583650800 -14400 1 EDT}
+ {1604210400 -18000 0 EST}
+ {1615705200 -14400 1 EDT}
+ {1636264800 -18000 0 EST}
+ {1647154800 -14400 1 EDT}
+ {1667714400 -18000 0 EST}
+ {1678604400 -14400 1 EDT}
+ {1699164000 -18000 0 EST}
+ {1710054000 -14400 1 EDT}
+ {1730613600 -18000 0 EST}
+ {1741503600 -14400 1 EDT}
+ {1762063200 -18000 0 EST}
+ {1772953200 -14400 1 EDT}
+ {1793512800 -18000 0 EST}
+ {1805007600 -14400 1 EDT}
+ {1825567200 -18000 0 EST}
+ {1836457200 -14400 1 EDT}
+ {1857016800 -18000 0 EST}
+ {1867906800 -14400 1 EDT}
+ {1888466400 -18000 0 EST}
+ {1899356400 -14400 1 EDT}
+ {1919916000 -18000 0 EST}
+ {1930806000 -14400 1 EDT}
+ {1951365600 -18000 0 EST}
+ {1962860400 -14400 1 EDT}
+ {1983420000 -18000 0 EST}
+ {1994310000 -14400 1 EDT}
+ {2014869600 -18000 0 EST}
+ {2025759600 -14400 1 EDT}
+ {2046319200 -18000 0 EST}
+ {2057209200 -14400 1 EDT}
+ {2077768800 -18000 0 EST}
+ {2088658800 -14400 1 EDT}
+ {2109218400 -18000 0 EST}
+ {2120108400 -14400 1 EDT}
+ {2140668000 -18000 0 EST}
+ {2152162800 -14400 1 EDT}
+ {2172722400 -18000 0 EST}
+ {2183612400 -14400 1 EDT}
+ {2204172000 -18000 0 EST}
+ {2215062000 -14400 1 EDT}
+ {2235621600 -18000 0 EST}
+ {2246511600 -14400 1 EDT}
+ {2267071200 -18000 0 EST}
+ {2277961200 -14400 1 EDT}
+ {2298520800 -18000 0 EST}
+ {2309410800 -14400 1 EDT}
+ {2329970400 -18000 0 EST}
+ {2341465200 -14400 1 EDT}
+ {2362024800 -18000 0 EST}
+ {2372914800 -14400 1 EDT}
+ {2393474400 -18000 0 EST}
+ {2404364400 -14400 1 EDT}
+ {2424924000 -18000 0 EST}
+ {2435814000 -14400 1 EDT}
+ {2456373600 -18000 0 EST}
+ {2467263600 -14400 1 EDT}
+ {2487823200 -18000 0 EST}
+ {2499318000 -14400 1 EDT}
+ {2519877600 -18000 0 EST}
+ {2530767600 -14400 1 EDT}
+ {2551327200 -18000 0 EST}
+ {2562217200 -14400 1 EDT}
+ {2582776800 -18000 0 EST}
+ {2593666800 -14400 1 EDT}
+ {2614226400 -18000 0 EST}
+ {2625116400 -14400 1 EDT}
+ {2645676000 -18000 0 EST}
+ {2656566000 -14400 1 EDT}
+ {2677125600 -18000 0 EST}
+ {2688620400 -14400 1 EDT}
+ {2709180000 -18000 0 EST}
+ {2720070000 -14400 1 EDT}
+ {2740629600 -18000 0 EST}
+ {2751519600 -14400 1 EDT}
+ {2772079200 -18000 0 EST}
+ {2782969200 -14400 1 EDT}
+ {2803528800 -18000 0 EST}
+ {2814418800 -14400 1 EDT}
+ {2834978400 -18000 0 EST}
+ {2846473200 -14400 1 EDT}
+ {2867032800 -18000 0 EST}
+ {2877922800 -14400 1 EDT}
+ {2898482400 -18000 0 EST}
+ {2909372400 -14400 1 EDT}
+ {2929932000 -18000 0 EST}
+ {2940822000 -14400 1 EDT}
+ {2961381600 -18000 0 EST}
+ {2972271600 -14400 1 EDT}
+ {2992831200 -18000 0 EST}
+ {3003721200 -14400 1 EDT}
+ {3024280800 -18000 0 EST}
+ {3035775600 -14400 1 EDT}
+ {3056335200 -18000 0 EST}
+ {3067225200 -14400 1 EDT}
+ {3087784800 -18000 0 EST}
+ {3098674800 -14400 1 EDT}
+ {3119234400 -18000 0 EST}
+ {3130124400 -14400 1 EDT}
+ {3150684000 -18000 0 EST}
+ {3161574000 -14400 1 EDT}
+ {3182133600 -18000 0 EST}
+ {3193023600 -14400 1 EDT}
+ {3213583200 -18000 0 EST}
+ {3225078000 -14400 1 EDT}
+ {3245637600 -18000 0 EST}
+ {3256527600 -14400 1 EDT}
+ {3277087200 -18000 0 EST}
+ {3287977200 -14400 1 EDT}
+ {3308536800 -18000 0 EST}
+ {3319426800 -14400 1 EDT}
+ {3339986400 -18000 0 EST}
+ {3350876400 -14400 1 EDT}
+ {3371436000 -18000 0 EST}
+ {3382930800 -14400 1 EDT}
+ {3403490400 -18000 0 EST}
+ {3414380400 -14400 1 EDT}
+ {3434940000 -18000 0 EST}
+ {3445830000 -14400 1 EDT}
+ {3466389600 -18000 0 EST}
+ {3477279600 -14400 1 EDT}
+ {3497839200 -18000 0 EST}
+ {3508729200 -14400 1 EDT}
+ {3529288800 -18000 0 EST}
+ {3540178800 -14400 1 EDT}
+ {3560738400 -18000 0 EST}
+ {3572233200 -14400 1 EDT}
+ {3592792800 -18000 0 EST}
+ {3603682800 -14400 1 EDT}
+ {3624242400 -18000 0 EST}
+ {3635132400 -14400 1 EDT}
+ {3655692000 -18000 0 EST}
+ {3666582000 -14400 1 EDT}
+ {3687141600 -18000 0 EST}
+ {3698031600 -14400 1 EDT}
+ {3718591200 -18000 0 EST}
+ {3730086000 -14400 1 EDT}
+ {3750645600 -18000 0 EST}
+ {3761535600 -14400 1 EDT}
+ {3782095200 -18000 0 EST}
+ {3792985200 -14400 1 EDT}
+ {3813544800 -18000 0 EST}
+ {3824434800 -14400 1 EDT}
+ {3844994400 -18000 0 EST}
+ {3855884400 -14400 1 EDT}
+ {3876444000 -18000 0 EST}
+ {3887334000 -14400 1 EDT}
+ {3907893600 -18000 0 EST}
+ {3919388400 -14400 1 EDT}
+ {3939948000 -18000 0 EST}
+ {3950838000 -14400 1 EDT}
+ {3971397600 -18000 0 EST}
+ {3982287600 -14400 1 EDT}
+ {4002847200 -18000 0 EST}
+ {4013737200 -14400 1 EDT}
+ {4034296800 -18000 0 EST}
+ {4045186800 -14400 1 EDT}
+ {4065746400 -18000 0 EST}
+ {4076636400 -14400 1 EDT}
+ {4097196000 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Indiana/Knox b/library/tzdata/America/Indiana/Knox
new file mode 100644
index 0000000..eee3ff4
--- /dev/null
+++ b/library/tzdata/America/Indiana/Knox
@@ -0,0 +1,285 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Indiana/Knox) {
+ {-9223372036854775808 -20790 0 LMT}
+ {-2717647200 -21600 0 CST}
+ {-1633276800 -18000 1 CDT}
+ {-1615136400 -21600 0 CST}
+ {-1601827200 -18000 1 CDT}
+ {-1583686800 -21600 0 CST}
+ {-880214400 -18000 1 CWT}
+ {-769395600 -18000 1 CPT}
+ {-765392400 -21600 0 CST}
+ {-725824800 -21600 0 CST}
+ {-715795200 -18000 1 CDT}
+ {-702493200 -21600 0 CST}
+ {-684345600 -18000 1 CDT}
+ {-671043600 -21600 0 CST}
+ {-652896000 -18000 1 CDT}
+ {-639594000 -21600 0 CST}
+ {-620841600 -18000 1 CDT}
+ {-608144400 -21600 0 CST}
+ {-589392000 -18000 1 CDT}
+ {-576090000 -21600 0 CST}
+ {-557942400 -18000 1 CDT}
+ {-544640400 -21600 0 CST}
+ {-526492800 -18000 1 CDT}
+ {-513190800 -21600 0 CST}
+ {-495043200 -18000 1 CDT}
+ {-481741200 -21600 0 CST}
+ {-463593600 -18000 1 CDT}
+ {-447267600 -21600 0 CST}
+ {-431539200 -18000 1 CDT}
+ {-415818000 -21600 0 CST}
+ {-400089600 -18000 1 CDT}
+ {-386787600 -21600 0 CST}
+ {-368640000 -18000 1 CDT}
+ {-355338000 -21600 0 CST}
+ {-337190400 -18000 1 CDT}
+ {-321469200 -21600 0 CST}
+ {-305740800 -18000 1 CDT}
+ {-289414800 -21600 0 CST}
+ {-273686400 -18000 1 CDT}
+ {-257965200 -21600 0 CST}
+ {-242236800 -18000 0 EST}
+ {-195066000 -21600 0 CST}
+ {-84384000 -18000 1 CDT}
+ {-68662800 -21600 0 CST}
+ {-52934400 -18000 1 CDT}
+ {-37213200 -21600 0 CST}
+ {-21484800 -18000 1 CDT}
+ {-5763600 -21600 0 CST}
+ {9964800 -18000 1 CDT}
+ {25686000 -21600 0 CST}
+ {41414400 -18000 1 CDT}
+ {57740400 -21600 0 CST}
+ {73468800 -18000 1 CDT}
+ {89190000 -21600 0 CST}
+ {104918400 -18000 1 CDT}
+ {120639600 -21600 0 CST}
+ {126691200 -18000 1 CDT}
+ {152089200 -21600 0 CST}
+ {162374400 -18000 1 CDT}
+ {183538800 -21600 0 CST}
+ {199267200 -18000 1 CDT}
+ {215593200 -21600 0 CST}
+ {230716800 -18000 1 CDT}
+ {247042800 -21600 0 CST}
+ {262771200 -18000 1 CDT}
+ {278492400 -21600 0 CST}
+ {294220800 -18000 1 CDT}
+ {309942000 -21600 0 CST}
+ {325670400 -18000 1 CDT}
+ {341391600 -21600 0 CST}
+ {357120000 -18000 1 CDT}
+ {372841200 -21600 0 CST}
+ {388569600 -18000 1 CDT}
+ {404895600 -21600 0 CST}
+ {420019200 -18000 1 CDT}
+ {436345200 -21600 0 CST}
+ {452073600 -18000 1 CDT}
+ {467794800 -21600 0 CST}
+ {483523200 -18000 1 CDT}
+ {499244400 -21600 0 CST}
+ {514972800 -18000 1 CDT}
+ {530694000 -21600 0 CST}
+ {544608000 -18000 1 CDT}
+ {562143600 -21600 0 CST}
+ {576057600 -18000 1 CDT}
+ {594198000 -21600 0 CST}
+ {607507200 -18000 1 CDT}
+ {625647600 -21600 0 CST}
+ {638956800 -18000 1 CDT}
+ {657097200 -21600 0 CST}
+ {671011200 -18000 1 CDT}
+ {688550400 -18000 0 EST}
+ {1143961200 -21600 0 CST}
+ {1143964800 -18000 1 CDT}
+ {1162105200 -21600 0 CST}
+ {1173600000 -18000 1 CDT}
+ {1194159600 -21600 0 CST}
+ {1205049600 -18000 1 CDT}
+ {1225609200 -21600 0 CST}
+ {1236499200 -18000 1 CDT}
+ {1257058800 -21600 0 CST}
+ {1268553600 -18000 1 CDT}
+ {1289113200 -21600 0 CST}
+ {1300003200 -18000 1 CDT}
+ {1320562800 -21600 0 CST}
+ {1331452800 -18000 1 CDT}
+ {1352012400 -21600 0 CST}
+ {1362902400 -18000 1 CDT}
+ {1383462000 -21600 0 CST}
+ {1394352000 -18000 1 CDT}
+ {1414911600 -21600 0 CST}
+ {1425801600 -18000 1 CDT}
+ {1446361200 -21600 0 CST}
+ {1457856000 -18000 1 CDT}
+ {1478415600 -21600 0 CST}
+ {1489305600 -18000 1 CDT}
+ {1509865200 -21600 0 CST}
+ {1520755200 -18000 1 CDT}
+ {1541314800 -21600 0 CST}
+ {1552204800 -18000 1 CDT}
+ {1572764400 -21600 0 CST}
+ {1583654400 -18000 1 CDT}
+ {1604214000 -21600 0 CST}
+ {1615708800 -18000 1 CDT}
+ {1636268400 -21600 0 CST}
+ {1647158400 -18000 1 CDT}
+ {1667718000 -21600 0 CST}
+ {1678608000 -18000 1 CDT}
+ {1699167600 -21600 0 CST}
+ {1710057600 -18000 1 CDT}
+ {1730617200 -21600 0 CST}
+ {1741507200 -18000 1 CDT}
+ {1762066800 -21600 0 CST}
+ {1772956800 -18000 1 CDT}
+ {1793516400 -21600 0 CST}
+ {1805011200 -18000 1 CDT}
+ {1825570800 -21600 0 CST}
+ {1836460800 -18000 1 CDT}
+ {1857020400 -21600 0 CST}
+ {1867910400 -18000 1 CDT}
+ {1888470000 -21600 0 CST}
+ {1899360000 -18000 1 CDT}
+ {1919919600 -21600 0 CST}
+ {1930809600 -18000 1 CDT}
+ {1951369200 -21600 0 CST}
+ {1962864000 -18000 1 CDT}
+ {1983423600 -21600 0 CST}
+ {1994313600 -18000 1 CDT}
+ {2014873200 -21600 0 CST}
+ {2025763200 -18000 1 CDT}
+ {2046322800 -21600 0 CST}
+ {2057212800 -18000 1 CDT}
+ {2077772400 -21600 0 CST}
+ {2088662400 -18000 1 CDT}
+ {2109222000 -21600 0 CST}
+ {2120112000 -18000 1 CDT}
+ {2140671600 -21600 0 CST}
+ {2152166400 -18000 1 CDT}
+ {2172726000 -21600 0 CST}
+ {2183616000 -18000 1 CDT}
+ {2204175600 -21600 0 CST}
+ {2215065600 -18000 1 CDT}
+ {2235625200 -21600 0 CST}
+ {2246515200 -18000 1 CDT}
+ {2267074800 -21600 0 CST}
+ {2277964800 -18000 1 CDT}
+ {2298524400 -21600 0 CST}
+ {2309414400 -18000 1 CDT}
+ {2329974000 -21600 0 CST}
+ {2341468800 -18000 1 CDT}
+ {2362028400 -21600 0 CST}
+ {2372918400 -18000 1 CDT}
+ {2393478000 -21600 0 CST}
+ {2404368000 -18000 1 CDT}
+ {2424927600 -21600 0 CST}
+ {2435817600 -18000 1 CDT}
+ {2456377200 -21600 0 CST}
+ {2467267200 -18000 1 CDT}
+ {2487826800 -21600 0 CST}
+ {2499321600 -18000 1 CDT}
+ {2519881200 -21600 0 CST}
+ {2530771200 -18000 1 CDT}
+ {2551330800 -21600 0 CST}
+ {2562220800 -18000 1 CDT}
+ {2582780400 -21600 0 CST}
+ {2593670400 -18000 1 CDT}
+ {2614230000 -21600 0 CST}
+ {2625120000 -18000 1 CDT}
+ {2645679600 -21600 0 CST}
+ {2656569600 -18000 1 CDT}
+ {2677129200 -21600 0 CST}
+ {2688624000 -18000 1 CDT}
+ {2709183600 -21600 0 CST}
+ {2720073600 -18000 1 CDT}
+ {2740633200 -21600 0 CST}
+ {2751523200 -18000 1 CDT}
+ {2772082800 -21600 0 CST}
+ {2782972800 -18000 1 CDT}
+ {2803532400 -21600 0 CST}
+ {2814422400 -18000 1 CDT}
+ {2834982000 -21600 0 CST}
+ {2846476800 -18000 1 CDT}
+ {2867036400 -21600 0 CST}
+ {2877926400 -18000 1 CDT}
+ {2898486000 -21600 0 CST}
+ {2909376000 -18000 1 CDT}
+ {2929935600 -21600 0 CST}
+ {2940825600 -18000 1 CDT}
+ {2961385200 -21600 0 CST}
+ {2972275200 -18000 1 CDT}
+ {2992834800 -21600 0 CST}
+ {3003724800 -18000 1 CDT}
+ {3024284400 -21600 0 CST}
+ {3035779200 -18000 1 CDT}
+ {3056338800 -21600 0 CST}
+ {3067228800 -18000 1 CDT}
+ {3087788400 -21600 0 CST}
+ {3098678400 -18000 1 CDT}
+ {3119238000 -21600 0 CST}
+ {3130128000 -18000 1 CDT}
+ {3150687600 -21600 0 CST}
+ {3161577600 -18000 1 CDT}
+ {3182137200 -21600 0 CST}
+ {3193027200 -18000 1 CDT}
+ {3213586800 -21600 0 CST}
+ {3225081600 -18000 1 CDT}
+ {3245641200 -21600 0 CST}
+ {3256531200 -18000 1 CDT}
+ {3277090800 -21600 0 CST}
+ {3287980800 -18000 1 CDT}
+ {3308540400 -21600 0 CST}
+ {3319430400 -18000 1 CDT}
+ {3339990000 -21600 0 CST}
+ {3350880000 -18000 1 CDT}
+ {3371439600 -21600 0 CST}
+ {3382934400 -18000 1 CDT}
+ {3403494000 -21600 0 CST}
+ {3414384000 -18000 1 CDT}
+ {3434943600 -21600 0 CST}
+ {3445833600 -18000 1 CDT}
+ {3466393200 -21600 0 CST}
+ {3477283200 -18000 1 CDT}
+ {3497842800 -21600 0 CST}
+ {3508732800 -18000 1 CDT}
+ {3529292400 -21600 0 CST}
+ {3540182400 -18000 1 CDT}
+ {3560742000 -21600 0 CST}
+ {3572236800 -18000 1 CDT}
+ {3592796400 -21600 0 CST}
+ {3603686400 -18000 1 CDT}
+ {3624246000 -21600 0 CST}
+ {3635136000 -18000 1 CDT}
+ {3655695600 -21600 0 CST}
+ {3666585600 -18000 1 CDT}
+ {3687145200 -21600 0 CST}
+ {3698035200 -18000 1 CDT}
+ {3718594800 -21600 0 CST}
+ {3730089600 -18000 1 CDT}
+ {3750649200 -21600 0 CST}
+ {3761539200 -18000 1 CDT}
+ {3782098800 -21600 0 CST}
+ {3792988800 -18000 1 CDT}
+ {3813548400 -21600 0 CST}
+ {3824438400 -18000 1 CDT}
+ {3844998000 -21600 0 CST}
+ {3855888000 -18000 1 CDT}
+ {3876447600 -21600 0 CST}
+ {3887337600 -18000 1 CDT}
+ {3907897200 -21600 0 CST}
+ {3919392000 -18000 1 CDT}
+ {3939951600 -21600 0 CST}
+ {3950841600 -18000 1 CDT}
+ {3971401200 -21600 0 CST}
+ {3982291200 -18000 1 CDT}
+ {4002850800 -21600 0 CST}
+ {4013740800 -18000 1 CDT}
+ {4034300400 -21600 0 CST}
+ {4045190400 -18000 1 CDT}
+ {4065750000 -21600 0 CST}
+ {4076640000 -18000 1 CDT}
+ {4097199600 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Indiana/Marengo b/library/tzdata/America/Indiana/Marengo
new file mode 100644
index 0000000..3f1d578
--- /dev/null
+++ b/library/tzdata/America/Indiana/Marengo
@@ -0,0 +1,236 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Indiana/Marengo) {
+ {-9223372036854775808 -20723 0 LMT}
+ {-2717647200 -21600 0 CST}
+ {-1633276800 -18000 1 CDT}
+ {-1615136400 -21600 0 CST}
+ {-1601827200 -18000 1 CDT}
+ {-1583686800 -21600 0 CST}
+ {-880214400 -18000 1 CWT}
+ {-769395600 -18000 1 CPT}
+ {-765392400 -21600 0 CST}
+ {-599594400 -21600 0 CST}
+ {-589392000 -18000 1 CDT}
+ {-576090000 -21600 0 CST}
+ {-495043200 -18000 1 CDT}
+ {-481741200 -21600 0 CST}
+ {-463593600 -18000 1 CDT}
+ {-450291600 -21600 0 CST}
+ {-431539200 -18000 1 CDT}
+ {-418237200 -21600 0 CST}
+ {-400089600 -18000 1 CDT}
+ {-386787600 -21600 0 CST}
+ {-368640000 -18000 1 CDT}
+ {-355338000 -21600 0 CST}
+ {-337190400 -18000 1 CDT}
+ {-323888400 -21600 0 CST}
+ {-305740800 -18000 1 CDT}
+ {-292438800 -21600 0 CST}
+ {-273686400 -18000 0 EST}
+ {-31518000 -18000 0 EST}
+ {-21488400 -14400 1 EDT}
+ {-5767200 -18000 0 EST}
+ {9961200 -14400 1 EDT}
+ {25682400 -18000 0 EST}
+ {41410800 -14400 1 EDT}
+ {57736800 -18000 0 EST}
+ {73465200 -14400 1 EDT}
+ {89186400 -18000 0 EST}
+ {104914800 -14400 1 EDT}
+ {120636000 -18000 0 EST}
+ {126687600 -18000 1 CDT}
+ {152089200 -18000 0 EST}
+ {162370800 -14400 1 EDT}
+ {183535200 -18000 0 EST}
+ {189320400 -18000 0 EST}
+ {1136091600 -18000 0 EST}
+ {1143961200 -14400 1 EDT}
+ {1162101600 -18000 0 EST}
+ {1173596400 -14400 1 EDT}
+ {1194156000 -18000 0 EST}
+ {1205046000 -14400 1 EDT}
+ {1225605600 -18000 0 EST}
+ {1236495600 -14400 1 EDT}
+ {1257055200 -18000 0 EST}
+ {1268550000 -14400 1 EDT}
+ {1289109600 -18000 0 EST}
+ {1299999600 -14400 1 EDT}
+ {1320559200 -18000 0 EST}
+ {1331449200 -14400 1 EDT}
+ {1352008800 -18000 0 EST}
+ {1362898800 -14400 1 EDT}
+ {1383458400 -18000 0 EST}
+ {1394348400 -14400 1 EDT}
+ {1414908000 -18000 0 EST}
+ {1425798000 -14400 1 EDT}
+ {1446357600 -18000 0 EST}
+ {1457852400 -14400 1 EDT}
+ {1478412000 -18000 0 EST}
+ {1489302000 -14400 1 EDT}
+ {1509861600 -18000 0 EST}
+ {1520751600 -14400 1 EDT}
+ {1541311200 -18000 0 EST}
+ {1552201200 -14400 1 EDT}
+ {1572760800 -18000 0 EST}
+ {1583650800 -14400 1 EDT}
+ {1604210400 -18000 0 EST}
+ {1615705200 -14400 1 EDT}
+ {1636264800 -18000 0 EST}
+ {1647154800 -14400 1 EDT}
+ {1667714400 -18000 0 EST}
+ {1678604400 -14400 1 EDT}
+ {1699164000 -18000 0 EST}
+ {1710054000 -14400 1 EDT}
+ {1730613600 -18000 0 EST}
+ {1741503600 -14400 1 EDT}
+ {1762063200 -18000 0 EST}
+ {1772953200 -14400 1 EDT}
+ {1793512800 -18000 0 EST}
+ {1805007600 -14400 1 EDT}
+ {1825567200 -18000 0 EST}
+ {1836457200 -14400 1 EDT}
+ {1857016800 -18000 0 EST}
+ {1867906800 -14400 1 EDT}
+ {1888466400 -18000 0 EST}
+ {1899356400 -14400 1 EDT}
+ {1919916000 -18000 0 EST}
+ {1930806000 -14400 1 EDT}
+ {1951365600 -18000 0 EST}
+ {1962860400 -14400 1 EDT}
+ {1983420000 -18000 0 EST}
+ {1994310000 -14400 1 EDT}
+ {2014869600 -18000 0 EST}
+ {2025759600 -14400 1 EDT}
+ {2046319200 -18000 0 EST}
+ {2057209200 -14400 1 EDT}
+ {2077768800 -18000 0 EST}
+ {2088658800 -14400 1 EDT}
+ {2109218400 -18000 0 EST}
+ {2120108400 -14400 1 EDT}
+ {2140668000 -18000 0 EST}
+ {2152162800 -14400 1 EDT}
+ {2172722400 -18000 0 EST}
+ {2183612400 -14400 1 EDT}
+ {2204172000 -18000 0 EST}
+ {2215062000 -14400 1 EDT}
+ {2235621600 -18000 0 EST}
+ {2246511600 -14400 1 EDT}
+ {2267071200 -18000 0 EST}
+ {2277961200 -14400 1 EDT}
+ {2298520800 -18000 0 EST}
+ {2309410800 -14400 1 EDT}
+ {2329970400 -18000 0 EST}
+ {2341465200 -14400 1 EDT}
+ {2362024800 -18000 0 EST}
+ {2372914800 -14400 1 EDT}
+ {2393474400 -18000 0 EST}
+ {2404364400 -14400 1 EDT}
+ {2424924000 -18000 0 EST}
+ {2435814000 -14400 1 EDT}
+ {2456373600 -18000 0 EST}
+ {2467263600 -14400 1 EDT}
+ {2487823200 -18000 0 EST}
+ {2499318000 -14400 1 EDT}
+ {2519877600 -18000 0 EST}
+ {2530767600 -14400 1 EDT}
+ {2551327200 -18000 0 EST}
+ {2562217200 -14400 1 EDT}
+ {2582776800 -18000 0 EST}
+ {2593666800 -14400 1 EDT}
+ {2614226400 -18000 0 EST}
+ {2625116400 -14400 1 EDT}
+ {2645676000 -18000 0 EST}
+ {2656566000 -14400 1 EDT}
+ {2677125600 -18000 0 EST}
+ {2688620400 -14400 1 EDT}
+ {2709180000 -18000 0 EST}
+ {2720070000 -14400 1 EDT}
+ {2740629600 -18000 0 EST}
+ {2751519600 -14400 1 EDT}
+ {2772079200 -18000 0 EST}
+ {2782969200 -14400 1 EDT}
+ {2803528800 -18000 0 EST}
+ {2814418800 -14400 1 EDT}
+ {2834978400 -18000 0 EST}
+ {2846473200 -14400 1 EDT}
+ {2867032800 -18000 0 EST}
+ {2877922800 -14400 1 EDT}
+ {2898482400 -18000 0 EST}
+ {2909372400 -14400 1 EDT}
+ {2929932000 -18000 0 EST}
+ {2940822000 -14400 1 EDT}
+ {2961381600 -18000 0 EST}
+ {2972271600 -14400 1 EDT}
+ {2992831200 -18000 0 EST}
+ {3003721200 -14400 1 EDT}
+ {3024280800 -18000 0 EST}
+ {3035775600 -14400 1 EDT}
+ {3056335200 -18000 0 EST}
+ {3067225200 -14400 1 EDT}
+ {3087784800 -18000 0 EST}
+ {3098674800 -14400 1 EDT}
+ {3119234400 -18000 0 EST}
+ {3130124400 -14400 1 EDT}
+ {3150684000 -18000 0 EST}
+ {3161574000 -14400 1 EDT}
+ {3182133600 -18000 0 EST}
+ {3193023600 -14400 1 EDT}
+ {3213583200 -18000 0 EST}
+ {3225078000 -14400 1 EDT}
+ {3245637600 -18000 0 EST}
+ {3256527600 -14400 1 EDT}
+ {3277087200 -18000 0 EST}
+ {3287977200 -14400 1 EDT}
+ {3308536800 -18000 0 EST}
+ {3319426800 -14400 1 EDT}
+ {3339986400 -18000 0 EST}
+ {3350876400 -14400 1 EDT}
+ {3371436000 -18000 0 EST}
+ {3382930800 -14400 1 EDT}
+ {3403490400 -18000 0 EST}
+ {3414380400 -14400 1 EDT}
+ {3434940000 -18000 0 EST}
+ {3445830000 -14400 1 EDT}
+ {3466389600 -18000 0 EST}
+ {3477279600 -14400 1 EDT}
+ {3497839200 -18000 0 EST}
+ {3508729200 -14400 1 EDT}
+ {3529288800 -18000 0 EST}
+ {3540178800 -14400 1 EDT}
+ {3560738400 -18000 0 EST}
+ {3572233200 -14400 1 EDT}
+ {3592792800 -18000 0 EST}
+ {3603682800 -14400 1 EDT}
+ {3624242400 -18000 0 EST}
+ {3635132400 -14400 1 EDT}
+ {3655692000 -18000 0 EST}
+ {3666582000 -14400 1 EDT}
+ {3687141600 -18000 0 EST}
+ {3698031600 -14400 1 EDT}
+ {3718591200 -18000 0 EST}
+ {3730086000 -14400 1 EDT}
+ {3750645600 -18000 0 EST}
+ {3761535600 -14400 1 EDT}
+ {3782095200 -18000 0 EST}
+ {3792985200 -14400 1 EDT}
+ {3813544800 -18000 0 EST}
+ {3824434800 -14400 1 EDT}
+ {3844994400 -18000 0 EST}
+ {3855884400 -14400 1 EDT}
+ {3876444000 -18000 0 EST}
+ {3887334000 -14400 1 EDT}
+ {3907893600 -18000 0 EST}
+ {3919388400 -14400 1 EDT}
+ {3939948000 -18000 0 EST}
+ {3950838000 -14400 1 EDT}
+ {3971397600 -18000 0 EST}
+ {3982287600 -14400 1 EDT}
+ {4002847200 -18000 0 EST}
+ {4013737200 -14400 1 EDT}
+ {4034296800 -18000 0 EST}
+ {4045186800 -14400 1 EDT}
+ {4065746400 -18000 0 EST}
+ {4076636400 -14400 1 EDT}
+ {4097196000 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Indiana/Petersburg b/library/tzdata/America/Indiana/Petersburg
new file mode 100755
index 0000000..6992bfc
--- /dev/null
+++ b/library/tzdata/America/Indiana/Petersburg
@@ -0,0 +1,247 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Indiana/Petersburg) {
+ {-9223372036854775808 -20947 0 LMT}
+ {-2717647200 -21600 0 CST}
+ {-1633276800 -18000 1 CDT}
+ {-1615136400 -21600 0 CST}
+ {-1601827200 -18000 1 CDT}
+ {-1583686800 -21600 0 CST}
+ {-880214400 -18000 1 CWT}
+ {-769395600 -18000 1 CPT}
+ {-765392400 -21600 0 CST}
+ {-473364000 -21600 0 CST}
+ {-462996000 -18000 1 CDT}
+ {-450291600 -21600 0 CST}
+ {-431539200 -18000 1 CDT}
+ {-418237200 -21600 0 CST}
+ {-400089600 -18000 1 CDT}
+ {-386787600 -21600 0 CST}
+ {-368640000 -18000 1 CDT}
+ {-355338000 -21600 0 CST}
+ {-337190400 -18000 1 CDT}
+ {-323888400 -21600 0 CST}
+ {-305740800 -18000 1 CDT}
+ {-292438800 -21600 0 CST}
+ {-273686400 -18000 1 CDT}
+ {-257965200 -21600 0 CST}
+ {-242236800 -18000 1 CDT}
+ {-226515600 -21600 0 CST}
+ {-210787200 -18000 1 CDT}
+ {-195066000 -21600 0 CST}
+ {-179337600 -18000 1 CDT}
+ {-163616400 -21600 0 CST}
+ {-147888000 -18000 0 EST}
+ {-100112400 -21600 0 CST}
+ {-84384000 -18000 1 CDT}
+ {-68662800 -21600 0 CST}
+ {-52934400 -18000 1 CDT}
+ {-37213200 -21600 0 CST}
+ {-21484800 -18000 1 CDT}
+ {-5763600 -21600 0 CST}
+ {9964800 -18000 1 CDT}
+ {25686000 -21600 0 CST}
+ {41414400 -18000 1 CDT}
+ {57740400 -21600 0 CST}
+ {73468800 -18000 1 CDT}
+ {89190000 -21600 0 CST}
+ {104918400 -18000 1 CDT}
+ {120639600 -21600 0 CST}
+ {126691200 -18000 1 CDT}
+ {152089200 -21600 0 CST}
+ {162374400 -18000 1 CDT}
+ {183538800 -21600 0 CST}
+ {199267200 -18000 1 CDT}
+ {215593200 -21600 0 CST}
+ {230716800 -18000 1 CDT}
+ {247046400 -18000 0 EST}
+ {1143961200 -21600 0 CST}
+ {1143964800 -18000 1 CDT}
+ {1162105200 -21600 0 CST}
+ {1173600000 -18000 1 CDT}
+ {1194163200 -18000 0 EST}
+ {1205046000 -14400 1 EDT}
+ {1225605600 -18000 0 EST}
+ {1236495600 -14400 1 EDT}
+ {1257055200 -18000 0 EST}
+ {1268550000 -14400 1 EDT}
+ {1289109600 -18000 0 EST}
+ {1299999600 -14400 1 EDT}
+ {1320559200 -18000 0 EST}
+ {1331449200 -14400 1 EDT}
+ {1352008800 -18000 0 EST}
+ {1362898800 -14400 1 EDT}
+ {1383458400 -18000 0 EST}
+ {1394348400 -14400 1 EDT}
+ {1414908000 -18000 0 EST}
+ {1425798000 -14400 1 EDT}
+ {1446357600 -18000 0 EST}
+ {1457852400 -14400 1 EDT}
+ {1478412000 -18000 0 EST}
+ {1489302000 -14400 1 EDT}
+ {1509861600 -18000 0 EST}
+ {1520751600 -14400 1 EDT}
+ {1541311200 -18000 0 EST}
+ {1552201200 -14400 1 EDT}
+ {1572760800 -18000 0 EST}
+ {1583650800 -14400 1 EDT}
+ {1604210400 -18000 0 EST}
+ {1615705200 -14400 1 EDT}
+ {1636264800 -18000 0 EST}
+ {1647154800 -14400 1 EDT}
+ {1667714400 -18000 0 EST}
+ {1678604400 -14400 1 EDT}
+ {1699164000 -18000 0 EST}
+ {1710054000 -14400 1 EDT}
+ {1730613600 -18000 0 EST}
+ {1741503600 -14400 1 EDT}
+ {1762063200 -18000 0 EST}
+ {1772953200 -14400 1 EDT}
+ {1793512800 -18000 0 EST}
+ {1805007600 -14400 1 EDT}
+ {1825567200 -18000 0 EST}
+ {1836457200 -14400 1 EDT}
+ {1857016800 -18000 0 EST}
+ {1867906800 -14400 1 EDT}
+ {1888466400 -18000 0 EST}
+ {1899356400 -14400 1 EDT}
+ {1919916000 -18000 0 EST}
+ {1930806000 -14400 1 EDT}
+ {1951365600 -18000 0 EST}
+ {1962860400 -14400 1 EDT}
+ {1983420000 -18000 0 EST}
+ {1994310000 -14400 1 EDT}
+ {2014869600 -18000 0 EST}
+ {2025759600 -14400 1 EDT}
+ {2046319200 -18000 0 EST}
+ {2057209200 -14400 1 EDT}
+ {2077768800 -18000 0 EST}
+ {2088658800 -14400 1 EDT}
+ {2109218400 -18000 0 EST}
+ {2120108400 -14400 1 EDT}
+ {2140668000 -18000 0 EST}
+ {2152162800 -14400 1 EDT}
+ {2172722400 -18000 0 EST}
+ {2183612400 -14400 1 EDT}
+ {2204172000 -18000 0 EST}
+ {2215062000 -14400 1 EDT}
+ {2235621600 -18000 0 EST}
+ {2246511600 -14400 1 EDT}
+ {2267071200 -18000 0 EST}
+ {2277961200 -14400 1 EDT}
+ {2298520800 -18000 0 EST}
+ {2309410800 -14400 1 EDT}
+ {2329970400 -18000 0 EST}
+ {2341465200 -14400 1 EDT}
+ {2362024800 -18000 0 EST}
+ {2372914800 -14400 1 EDT}
+ {2393474400 -18000 0 EST}
+ {2404364400 -14400 1 EDT}
+ {2424924000 -18000 0 EST}
+ {2435814000 -14400 1 EDT}
+ {2456373600 -18000 0 EST}
+ {2467263600 -14400 1 EDT}
+ {2487823200 -18000 0 EST}
+ {2499318000 -14400 1 EDT}
+ {2519877600 -18000 0 EST}
+ {2530767600 -14400 1 EDT}
+ {2551327200 -18000 0 EST}
+ {2562217200 -14400 1 EDT}
+ {2582776800 -18000 0 EST}
+ {2593666800 -14400 1 EDT}
+ {2614226400 -18000 0 EST}
+ {2625116400 -14400 1 EDT}
+ {2645676000 -18000 0 EST}
+ {2656566000 -14400 1 EDT}
+ {2677125600 -18000 0 EST}
+ {2688620400 -14400 1 EDT}
+ {2709180000 -18000 0 EST}
+ {2720070000 -14400 1 EDT}
+ {2740629600 -18000 0 EST}
+ {2751519600 -14400 1 EDT}
+ {2772079200 -18000 0 EST}
+ {2782969200 -14400 1 EDT}
+ {2803528800 -18000 0 EST}
+ {2814418800 -14400 1 EDT}
+ {2834978400 -18000 0 EST}
+ {2846473200 -14400 1 EDT}
+ {2867032800 -18000 0 EST}
+ {2877922800 -14400 1 EDT}
+ {2898482400 -18000 0 EST}
+ {2909372400 -14400 1 EDT}
+ {2929932000 -18000 0 EST}
+ {2940822000 -14400 1 EDT}
+ {2961381600 -18000 0 EST}
+ {2972271600 -14400 1 EDT}
+ {2992831200 -18000 0 EST}
+ {3003721200 -14400 1 EDT}
+ {3024280800 -18000 0 EST}
+ {3035775600 -14400 1 EDT}
+ {3056335200 -18000 0 EST}
+ {3067225200 -14400 1 EDT}
+ {3087784800 -18000 0 EST}
+ {3098674800 -14400 1 EDT}
+ {3119234400 -18000 0 EST}
+ {3130124400 -14400 1 EDT}
+ {3150684000 -18000 0 EST}
+ {3161574000 -14400 1 EDT}
+ {3182133600 -18000 0 EST}
+ {3193023600 -14400 1 EDT}
+ {3213583200 -18000 0 EST}
+ {3225078000 -14400 1 EDT}
+ {3245637600 -18000 0 EST}
+ {3256527600 -14400 1 EDT}
+ {3277087200 -18000 0 EST}
+ {3287977200 -14400 1 EDT}
+ {3308536800 -18000 0 EST}
+ {3319426800 -14400 1 EDT}
+ {3339986400 -18000 0 EST}
+ {3350876400 -14400 1 EDT}
+ {3371436000 -18000 0 EST}
+ {3382930800 -14400 1 EDT}
+ {3403490400 -18000 0 EST}
+ {3414380400 -14400 1 EDT}
+ {3434940000 -18000 0 EST}
+ {3445830000 -14400 1 EDT}
+ {3466389600 -18000 0 EST}
+ {3477279600 -14400 1 EDT}
+ {3497839200 -18000 0 EST}
+ {3508729200 -14400 1 EDT}
+ {3529288800 -18000 0 EST}
+ {3540178800 -14400 1 EDT}
+ {3560738400 -18000 0 EST}
+ {3572233200 -14400 1 EDT}
+ {3592792800 -18000 0 EST}
+ {3603682800 -14400 1 EDT}
+ {3624242400 -18000 0 EST}
+ {3635132400 -14400 1 EDT}
+ {3655692000 -18000 0 EST}
+ {3666582000 -14400 1 EDT}
+ {3687141600 -18000 0 EST}
+ {3698031600 -14400 1 EDT}
+ {3718591200 -18000 0 EST}
+ {3730086000 -14400 1 EDT}
+ {3750645600 -18000 0 EST}
+ {3761535600 -14400 1 EDT}
+ {3782095200 -18000 0 EST}
+ {3792985200 -14400 1 EDT}
+ {3813544800 -18000 0 EST}
+ {3824434800 -14400 1 EDT}
+ {3844994400 -18000 0 EST}
+ {3855884400 -14400 1 EDT}
+ {3876444000 -18000 0 EST}
+ {3887334000 -14400 1 EDT}
+ {3907893600 -18000 0 EST}
+ {3919388400 -14400 1 EDT}
+ {3939948000 -18000 0 EST}
+ {3950838000 -14400 1 EDT}
+ {3971397600 -18000 0 EST}
+ {3982287600 -14400 1 EDT}
+ {4002847200 -18000 0 EST}
+ {4013737200 -14400 1 EDT}
+ {4034296800 -18000 0 EST}
+ {4045186800 -14400 1 EDT}
+ {4065746400 -18000 0 EST}
+ {4076636400 -14400 1 EDT}
+ {4097196000 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Indiana/Tell_City b/library/tzdata/America/Indiana/Tell_City
new file mode 100755
index 0000000..9eebcf7
--- /dev/null
+++ b/library/tzdata/America/Indiana/Tell_City
@@ -0,0 +1,234 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Indiana/Tell_City) {
+ {-9223372036854775808 -20823 0 LMT}
+ {-2717647200 -21600 0 CST}
+ {-1633276800 -18000 1 CDT}
+ {-1615136400 -21600 0 CST}
+ {-1601827200 -18000 1 CDT}
+ {-1583686800 -21600 0 CST}
+ {-880214400 -18000 1 CWT}
+ {-769395600 -18000 1 CPT}
+ {-765392400 -21600 0 CST}
+ {-757360800 -21600 0 CST}
+ {-747244800 -18000 1 CDT}
+ {-733942800 -21600 0 CST}
+ {-526492800 -18000 1 CDT}
+ {-513190800 -21600 0 CST}
+ {-495043200 -18000 1 CDT}
+ {-481741200 -21600 0 CST}
+ {-462996000 -18000 1 CDT}
+ {-450291600 -21600 0 CST}
+ {-431539200 -18000 1 CDT}
+ {-418237200 -21600 0 CST}
+ {-400089600 -18000 1 CDT}
+ {-386787600 -21600 0 CST}
+ {-368640000 -18000 1 CDT}
+ {-355338000 -21600 0 CST}
+ {-337190400 -18000 1 CDT}
+ {-323888400 -21600 0 CST}
+ {-305740800 -18000 1 CDT}
+ {-289414800 -21600 0 CST}
+ {-273686400 -18000 1 CDT}
+ {-260989200 -21600 0 CST}
+ {-242236800 -18000 1 CDT}
+ {-226515600 -21600 0 CST}
+ {-210787200 -18000 1 CDT}
+ {-195066000 -21600 0 CST}
+ {-179337600 -18000 0 EST}
+ {-31518000 -18000 0 EST}
+ {-21488400 -14400 1 EDT}
+ {-5767200 -18000 0 EST}
+ {9961200 -14400 1 EDT}
+ {25682400 -18000 0 EST}
+ {31554000 -18000 0 EST}
+ {1143961200 -21600 0 CST}
+ {1143964800 -18000 1 CDT}
+ {1162105200 -21600 0 CST}
+ {1173600000 -18000 1 CDT}
+ {1194159600 -21600 0 CST}
+ {1205049600 -18000 1 CDT}
+ {1225609200 -21600 0 CST}
+ {1236499200 -18000 1 CDT}
+ {1257058800 -21600 0 CST}
+ {1268553600 -18000 1 CDT}
+ {1289113200 -21600 0 CST}
+ {1300003200 -18000 1 CDT}
+ {1320562800 -21600 0 CST}
+ {1331452800 -18000 1 CDT}
+ {1352012400 -21600 0 CST}
+ {1362902400 -18000 1 CDT}
+ {1383462000 -21600 0 CST}
+ {1394352000 -18000 1 CDT}
+ {1414911600 -21600 0 CST}
+ {1425801600 -18000 1 CDT}
+ {1446361200 -21600 0 CST}
+ {1457856000 -18000 1 CDT}
+ {1478415600 -21600 0 CST}
+ {1489305600 -18000 1 CDT}
+ {1509865200 -21600 0 CST}
+ {1520755200 -18000 1 CDT}
+ {1541314800 -21600 0 CST}
+ {1552204800 -18000 1 CDT}
+ {1572764400 -21600 0 CST}
+ {1583654400 -18000 1 CDT}
+ {1604214000 -21600 0 CST}
+ {1615708800 -18000 1 CDT}
+ {1636268400 -21600 0 CST}
+ {1647158400 -18000 1 CDT}
+ {1667718000 -21600 0 CST}
+ {1678608000 -18000 1 CDT}
+ {1699167600 -21600 0 CST}
+ {1710057600 -18000 1 CDT}
+ {1730617200 -21600 0 CST}
+ {1741507200 -18000 1 CDT}
+ {1762066800 -21600 0 CST}
+ {1772956800 -18000 1 CDT}
+ {1793516400 -21600 0 CST}
+ {1805011200 -18000 1 CDT}
+ {1825570800 -21600 0 CST}
+ {1836460800 -18000 1 CDT}
+ {1857020400 -21600 0 CST}
+ {1867910400 -18000 1 CDT}
+ {1888470000 -21600 0 CST}
+ {1899360000 -18000 1 CDT}
+ {1919919600 -21600 0 CST}
+ {1930809600 -18000 1 CDT}
+ {1951369200 -21600 0 CST}
+ {1962864000 -18000 1 CDT}
+ {1983423600 -21600 0 CST}
+ {1994313600 -18000 1 CDT}
+ {2014873200 -21600 0 CST}
+ {2025763200 -18000 1 CDT}
+ {2046322800 -21600 0 CST}
+ {2057212800 -18000 1 CDT}
+ {2077772400 -21600 0 CST}
+ {2088662400 -18000 1 CDT}
+ {2109222000 -21600 0 CST}
+ {2120112000 -18000 1 CDT}
+ {2140671600 -21600 0 CST}
+ {2152166400 -18000 1 CDT}
+ {2172726000 -21600 0 CST}
+ {2183616000 -18000 1 CDT}
+ {2204175600 -21600 0 CST}
+ {2215065600 -18000 1 CDT}
+ {2235625200 -21600 0 CST}
+ {2246515200 -18000 1 CDT}
+ {2267074800 -21600 0 CST}
+ {2277964800 -18000 1 CDT}
+ {2298524400 -21600 0 CST}
+ {2309414400 -18000 1 CDT}
+ {2329974000 -21600 0 CST}
+ {2341468800 -18000 1 CDT}
+ {2362028400 -21600 0 CST}
+ {2372918400 -18000 1 CDT}
+ {2393478000 -21600 0 CST}
+ {2404368000 -18000 1 CDT}
+ {2424927600 -21600 0 CST}
+ {2435817600 -18000 1 CDT}
+ {2456377200 -21600 0 CST}
+ {2467267200 -18000 1 CDT}
+ {2487826800 -21600 0 CST}
+ {2499321600 -18000 1 CDT}
+ {2519881200 -21600 0 CST}
+ {2530771200 -18000 1 CDT}
+ {2551330800 -21600 0 CST}
+ {2562220800 -18000 1 CDT}
+ {2582780400 -21600 0 CST}
+ {2593670400 -18000 1 CDT}
+ {2614230000 -21600 0 CST}
+ {2625120000 -18000 1 CDT}
+ {2645679600 -21600 0 CST}
+ {2656569600 -18000 1 CDT}
+ {2677129200 -21600 0 CST}
+ {2688624000 -18000 1 CDT}
+ {2709183600 -21600 0 CST}
+ {2720073600 -18000 1 CDT}
+ {2740633200 -21600 0 CST}
+ {2751523200 -18000 1 CDT}
+ {2772082800 -21600 0 CST}
+ {2782972800 -18000 1 CDT}
+ {2803532400 -21600 0 CST}
+ {2814422400 -18000 1 CDT}
+ {2834982000 -21600 0 CST}
+ {2846476800 -18000 1 CDT}
+ {2867036400 -21600 0 CST}
+ {2877926400 -18000 1 CDT}
+ {2898486000 -21600 0 CST}
+ {2909376000 -18000 1 CDT}
+ {2929935600 -21600 0 CST}
+ {2940825600 -18000 1 CDT}
+ {2961385200 -21600 0 CST}
+ {2972275200 -18000 1 CDT}
+ {2992834800 -21600 0 CST}
+ {3003724800 -18000 1 CDT}
+ {3024284400 -21600 0 CST}
+ {3035779200 -18000 1 CDT}
+ {3056338800 -21600 0 CST}
+ {3067228800 -18000 1 CDT}
+ {3087788400 -21600 0 CST}
+ {3098678400 -18000 1 CDT}
+ {3119238000 -21600 0 CST}
+ {3130128000 -18000 1 CDT}
+ {3150687600 -21600 0 CST}
+ {3161577600 -18000 1 CDT}
+ {3182137200 -21600 0 CST}
+ {3193027200 -18000 1 CDT}
+ {3213586800 -21600 0 CST}
+ {3225081600 -18000 1 CDT}
+ {3245641200 -21600 0 CST}
+ {3256531200 -18000 1 CDT}
+ {3277090800 -21600 0 CST}
+ {3287980800 -18000 1 CDT}
+ {3308540400 -21600 0 CST}
+ {3319430400 -18000 1 CDT}
+ {3339990000 -21600 0 CST}
+ {3350880000 -18000 1 CDT}
+ {3371439600 -21600 0 CST}
+ {3382934400 -18000 1 CDT}
+ {3403494000 -21600 0 CST}
+ {3414384000 -18000 1 CDT}
+ {3434943600 -21600 0 CST}
+ {3445833600 -18000 1 CDT}
+ {3466393200 -21600 0 CST}
+ {3477283200 -18000 1 CDT}
+ {3497842800 -21600 0 CST}
+ {3508732800 -18000 1 CDT}
+ {3529292400 -21600 0 CST}
+ {3540182400 -18000 1 CDT}
+ {3560742000 -21600 0 CST}
+ {3572236800 -18000 1 CDT}
+ {3592796400 -21600 0 CST}
+ {3603686400 -18000 1 CDT}
+ {3624246000 -21600 0 CST}
+ {3635136000 -18000 1 CDT}
+ {3655695600 -21600 0 CST}
+ {3666585600 -18000 1 CDT}
+ {3687145200 -21600 0 CST}
+ {3698035200 -18000 1 CDT}
+ {3718594800 -21600 0 CST}
+ {3730089600 -18000 1 CDT}
+ {3750649200 -21600 0 CST}
+ {3761539200 -18000 1 CDT}
+ {3782098800 -21600 0 CST}
+ {3792988800 -18000 1 CDT}
+ {3813548400 -21600 0 CST}
+ {3824438400 -18000 1 CDT}
+ {3844998000 -21600 0 CST}
+ {3855888000 -18000 1 CDT}
+ {3876447600 -21600 0 CST}
+ {3887337600 -18000 1 CDT}
+ {3907897200 -21600 0 CST}
+ {3919392000 -18000 1 CDT}
+ {3939951600 -21600 0 CST}
+ {3950841600 -18000 1 CDT}
+ {3971401200 -21600 0 CST}
+ {3982291200 -18000 1 CDT}
+ {4002850800 -21600 0 CST}
+ {4013740800 -18000 1 CDT}
+ {4034300400 -21600 0 CST}
+ {4045190400 -18000 1 CDT}
+ {4065750000 -21600 0 CST}
+ {4076640000 -18000 1 CDT}
+ {4097199600 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Indiana/Vevay b/library/tzdata/America/Indiana/Vevay
new file mode 100644
index 0000000..8d4157f
--- /dev/null
+++ b/library/tzdata/America/Indiana/Vevay
@@ -0,0 +1,213 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Indiana/Vevay) {
+ {-9223372036854775808 -20416 0 LMT}
+ {-2717647200 -21600 0 CST}
+ {-1633276800 -18000 1 CDT}
+ {-1615136400 -21600 0 CST}
+ {-1601827200 -18000 1 CDT}
+ {-1583686800 -21600 0 CST}
+ {-880214400 -18000 1 CWT}
+ {-769395600 -18000 1 CPT}
+ {-765392400 -21600 0 CST}
+ {-495043200 -18000 0 EST}
+ {-31518000 -18000 0 EST}
+ {-21488400 -14400 1 EDT}
+ {-5767200 -18000 0 EST}
+ {9961200 -14400 1 EDT}
+ {25682400 -18000 0 EST}
+ {41410800 -14400 1 EDT}
+ {57736800 -18000 0 EST}
+ {73465200 -14400 1 EDT}
+ {89186400 -18000 0 EST}
+ {94712400 -18000 0 EST}
+ {1136091600 -18000 0 EST}
+ {1143961200 -14400 1 EDT}
+ {1162101600 -18000 0 EST}
+ {1173596400 -14400 1 EDT}
+ {1194156000 -18000 0 EST}
+ {1205046000 -14400 1 EDT}
+ {1225605600 -18000 0 EST}
+ {1236495600 -14400 1 EDT}
+ {1257055200 -18000 0 EST}
+ {1268550000 -14400 1 EDT}
+ {1289109600 -18000 0 EST}
+ {1299999600 -14400 1 EDT}
+ {1320559200 -18000 0 EST}
+ {1331449200 -14400 1 EDT}
+ {1352008800 -18000 0 EST}
+ {1362898800 -14400 1 EDT}
+ {1383458400 -18000 0 EST}
+ {1394348400 -14400 1 EDT}
+ {1414908000 -18000 0 EST}
+ {1425798000 -14400 1 EDT}
+ {1446357600 -18000 0 EST}
+ {1457852400 -14400 1 EDT}
+ {1478412000 -18000 0 EST}
+ {1489302000 -14400 1 EDT}
+ {1509861600 -18000 0 EST}
+ {1520751600 -14400 1 EDT}
+ {1541311200 -18000 0 EST}
+ {1552201200 -14400 1 EDT}
+ {1572760800 -18000 0 EST}
+ {1583650800 -14400 1 EDT}
+ {1604210400 -18000 0 EST}
+ {1615705200 -14400 1 EDT}
+ {1636264800 -18000 0 EST}
+ {1647154800 -14400 1 EDT}
+ {1667714400 -18000 0 EST}
+ {1678604400 -14400 1 EDT}
+ {1699164000 -18000 0 EST}
+ {1710054000 -14400 1 EDT}
+ {1730613600 -18000 0 EST}
+ {1741503600 -14400 1 EDT}
+ {1762063200 -18000 0 EST}
+ {1772953200 -14400 1 EDT}
+ {1793512800 -18000 0 EST}
+ {1805007600 -14400 1 EDT}
+ {1825567200 -18000 0 EST}
+ {1836457200 -14400 1 EDT}
+ {1857016800 -18000 0 EST}
+ {1867906800 -14400 1 EDT}
+ {1888466400 -18000 0 EST}
+ {1899356400 -14400 1 EDT}
+ {1919916000 -18000 0 EST}
+ {1930806000 -14400 1 EDT}
+ {1951365600 -18000 0 EST}
+ {1962860400 -14400 1 EDT}
+ {1983420000 -18000 0 EST}
+ {1994310000 -14400 1 EDT}
+ {2014869600 -18000 0 EST}
+ {2025759600 -14400 1 EDT}
+ {2046319200 -18000 0 EST}
+ {2057209200 -14400 1 EDT}
+ {2077768800 -18000 0 EST}
+ {2088658800 -14400 1 EDT}
+ {2109218400 -18000 0 EST}
+ {2120108400 -14400 1 EDT}
+ {2140668000 -18000 0 EST}
+ {2152162800 -14400 1 EDT}
+ {2172722400 -18000 0 EST}
+ {2183612400 -14400 1 EDT}
+ {2204172000 -18000 0 EST}
+ {2215062000 -14400 1 EDT}
+ {2235621600 -18000 0 EST}
+ {2246511600 -14400 1 EDT}
+ {2267071200 -18000 0 EST}
+ {2277961200 -14400 1 EDT}
+ {2298520800 -18000 0 EST}
+ {2309410800 -14400 1 EDT}
+ {2329970400 -18000 0 EST}
+ {2341465200 -14400 1 EDT}
+ {2362024800 -18000 0 EST}
+ {2372914800 -14400 1 EDT}
+ {2393474400 -18000 0 EST}
+ {2404364400 -14400 1 EDT}
+ {2424924000 -18000 0 EST}
+ {2435814000 -14400 1 EDT}
+ {2456373600 -18000 0 EST}
+ {2467263600 -14400 1 EDT}
+ {2487823200 -18000 0 EST}
+ {2499318000 -14400 1 EDT}
+ {2519877600 -18000 0 EST}
+ {2530767600 -14400 1 EDT}
+ {2551327200 -18000 0 EST}
+ {2562217200 -14400 1 EDT}
+ {2582776800 -18000 0 EST}
+ {2593666800 -14400 1 EDT}
+ {2614226400 -18000 0 EST}
+ {2625116400 -14400 1 EDT}
+ {2645676000 -18000 0 EST}
+ {2656566000 -14400 1 EDT}
+ {2677125600 -18000 0 EST}
+ {2688620400 -14400 1 EDT}
+ {2709180000 -18000 0 EST}
+ {2720070000 -14400 1 EDT}
+ {2740629600 -18000 0 EST}
+ {2751519600 -14400 1 EDT}
+ {2772079200 -18000 0 EST}
+ {2782969200 -14400 1 EDT}
+ {2803528800 -18000 0 EST}
+ {2814418800 -14400 1 EDT}
+ {2834978400 -18000 0 EST}
+ {2846473200 -14400 1 EDT}
+ {2867032800 -18000 0 EST}
+ {2877922800 -14400 1 EDT}
+ {2898482400 -18000 0 EST}
+ {2909372400 -14400 1 EDT}
+ {2929932000 -18000 0 EST}
+ {2940822000 -14400 1 EDT}
+ {2961381600 -18000 0 EST}
+ {2972271600 -14400 1 EDT}
+ {2992831200 -18000 0 EST}
+ {3003721200 -14400 1 EDT}
+ {3024280800 -18000 0 EST}
+ {3035775600 -14400 1 EDT}
+ {3056335200 -18000 0 EST}
+ {3067225200 -14400 1 EDT}
+ {3087784800 -18000 0 EST}
+ {3098674800 -14400 1 EDT}
+ {3119234400 -18000 0 EST}
+ {3130124400 -14400 1 EDT}
+ {3150684000 -18000 0 EST}
+ {3161574000 -14400 1 EDT}
+ {3182133600 -18000 0 EST}
+ {3193023600 -14400 1 EDT}
+ {3213583200 -18000 0 EST}
+ {3225078000 -14400 1 EDT}
+ {3245637600 -18000 0 EST}
+ {3256527600 -14400 1 EDT}
+ {3277087200 -18000 0 EST}
+ {3287977200 -14400 1 EDT}
+ {3308536800 -18000 0 EST}
+ {3319426800 -14400 1 EDT}
+ {3339986400 -18000 0 EST}
+ {3350876400 -14400 1 EDT}
+ {3371436000 -18000 0 EST}
+ {3382930800 -14400 1 EDT}
+ {3403490400 -18000 0 EST}
+ {3414380400 -14400 1 EDT}
+ {3434940000 -18000 0 EST}
+ {3445830000 -14400 1 EDT}
+ {3466389600 -18000 0 EST}
+ {3477279600 -14400 1 EDT}
+ {3497839200 -18000 0 EST}
+ {3508729200 -14400 1 EDT}
+ {3529288800 -18000 0 EST}
+ {3540178800 -14400 1 EDT}
+ {3560738400 -18000 0 EST}
+ {3572233200 -14400 1 EDT}
+ {3592792800 -18000 0 EST}
+ {3603682800 -14400 1 EDT}
+ {3624242400 -18000 0 EST}
+ {3635132400 -14400 1 EDT}
+ {3655692000 -18000 0 EST}
+ {3666582000 -14400 1 EDT}
+ {3687141600 -18000 0 EST}
+ {3698031600 -14400 1 EDT}
+ {3718591200 -18000 0 EST}
+ {3730086000 -14400 1 EDT}
+ {3750645600 -18000 0 EST}
+ {3761535600 -14400 1 EDT}
+ {3782095200 -18000 0 EST}
+ {3792985200 -14400 1 EDT}
+ {3813544800 -18000 0 EST}
+ {3824434800 -14400 1 EDT}
+ {3844994400 -18000 0 EST}
+ {3855884400 -14400 1 EDT}
+ {3876444000 -18000 0 EST}
+ {3887334000 -14400 1 EDT}
+ {3907893600 -18000 0 EST}
+ {3919388400 -14400 1 EDT}
+ {3939948000 -18000 0 EST}
+ {3950838000 -14400 1 EDT}
+ {3971397600 -18000 0 EST}
+ {3982287600 -14400 1 EDT}
+ {4002847200 -18000 0 EST}
+ {4013737200 -14400 1 EDT}
+ {4034296800 -18000 0 EST}
+ {4045186800 -14400 1 EDT}
+ {4065746400 -18000 0 EST}
+ {4076636400 -14400 1 EDT}
+ {4097196000 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Indiana/Vincennes b/library/tzdata/America/Indiana/Vincennes
new file mode 100755
index 0000000..1af7fc9
--- /dev/null
+++ b/library/tzdata/America/Indiana/Vincennes
@@ -0,0 +1,234 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Indiana/Vincennes) {
+ {-9223372036854775808 -21007 0 LMT}
+ {-2717647200 -21600 0 CST}
+ {-1633276800 -18000 1 CDT}
+ {-1615136400 -21600 0 CST}
+ {-1601827200 -18000 1 CDT}
+ {-1583686800 -21600 0 CST}
+ {-880214400 -18000 1 CWT}
+ {-769395600 -18000 1 CPT}
+ {-765392400 -21600 0 CST}
+ {-757360800 -21600 0 CST}
+ {-747244800 -18000 1 CDT}
+ {-733942800 -21600 0 CST}
+ {-526492800 -18000 1 CDT}
+ {-513190800 -21600 0 CST}
+ {-495043200 -18000 1 CDT}
+ {-481741200 -21600 0 CST}
+ {-462996000 -18000 1 CDT}
+ {-450291600 -21600 0 CST}
+ {-431539200 -18000 1 CDT}
+ {-418237200 -21600 0 CST}
+ {-400089600 -18000 1 CDT}
+ {-386787600 -21600 0 CST}
+ {-368640000 -18000 1 CDT}
+ {-355338000 -21600 0 CST}
+ {-337190400 -18000 1 CDT}
+ {-323888400 -21600 0 CST}
+ {-305740800 -18000 1 CDT}
+ {-289414800 -21600 0 CST}
+ {-273686400 -18000 1 CDT}
+ {-260989200 -21600 0 CST}
+ {-242236800 -18000 1 CDT}
+ {-226515600 -21600 0 CST}
+ {-210787200 -18000 1 CDT}
+ {-195066000 -21600 0 CST}
+ {-179337600 -18000 0 EST}
+ {-31518000 -18000 0 EST}
+ {-21488400 -14400 1 EDT}
+ {-5767200 -18000 0 EST}
+ {9961200 -14400 1 EDT}
+ {25682400 -18000 0 EST}
+ {31554000 -18000 0 EST}
+ {1143961200 -21600 0 CST}
+ {1143964800 -18000 1 CDT}
+ {1162105200 -21600 0 CST}
+ {1173600000 -18000 1 CDT}
+ {1194163200 -18000 0 EST}
+ {1205046000 -14400 1 EDT}
+ {1225605600 -18000 0 EST}
+ {1236495600 -14400 1 EDT}
+ {1257055200 -18000 0 EST}
+ {1268550000 -14400 1 EDT}
+ {1289109600 -18000 0 EST}
+ {1299999600 -14400 1 EDT}
+ {1320559200 -18000 0 EST}
+ {1331449200 -14400 1 EDT}
+ {1352008800 -18000 0 EST}
+ {1362898800 -14400 1 EDT}
+ {1383458400 -18000 0 EST}
+ {1394348400 -14400 1 EDT}
+ {1414908000 -18000 0 EST}
+ {1425798000 -14400 1 EDT}
+ {1446357600 -18000 0 EST}
+ {1457852400 -14400 1 EDT}
+ {1478412000 -18000 0 EST}
+ {1489302000 -14400 1 EDT}
+ {1509861600 -18000 0 EST}
+ {1520751600 -14400 1 EDT}
+ {1541311200 -18000 0 EST}
+ {1552201200 -14400 1 EDT}
+ {1572760800 -18000 0 EST}
+ {1583650800 -14400 1 EDT}
+ {1604210400 -18000 0 EST}
+ {1615705200 -14400 1 EDT}
+ {1636264800 -18000 0 EST}
+ {1647154800 -14400 1 EDT}
+ {1667714400 -18000 0 EST}
+ {1678604400 -14400 1 EDT}
+ {1699164000 -18000 0 EST}
+ {1710054000 -14400 1 EDT}
+ {1730613600 -18000 0 EST}
+ {1741503600 -14400 1 EDT}
+ {1762063200 -18000 0 EST}
+ {1772953200 -14400 1 EDT}
+ {1793512800 -18000 0 EST}
+ {1805007600 -14400 1 EDT}
+ {1825567200 -18000 0 EST}
+ {1836457200 -14400 1 EDT}
+ {1857016800 -18000 0 EST}
+ {1867906800 -14400 1 EDT}
+ {1888466400 -18000 0 EST}
+ {1899356400 -14400 1 EDT}
+ {1919916000 -18000 0 EST}
+ {1930806000 -14400 1 EDT}
+ {1951365600 -18000 0 EST}
+ {1962860400 -14400 1 EDT}
+ {1983420000 -18000 0 EST}
+ {1994310000 -14400 1 EDT}
+ {2014869600 -18000 0 EST}
+ {2025759600 -14400 1 EDT}
+ {2046319200 -18000 0 EST}
+ {2057209200 -14400 1 EDT}
+ {2077768800 -18000 0 EST}
+ {2088658800 -14400 1 EDT}
+ {2109218400 -18000 0 EST}
+ {2120108400 -14400 1 EDT}
+ {2140668000 -18000 0 EST}
+ {2152162800 -14400 1 EDT}
+ {2172722400 -18000 0 EST}
+ {2183612400 -14400 1 EDT}
+ {2204172000 -18000 0 EST}
+ {2215062000 -14400 1 EDT}
+ {2235621600 -18000 0 EST}
+ {2246511600 -14400 1 EDT}
+ {2267071200 -18000 0 EST}
+ {2277961200 -14400 1 EDT}
+ {2298520800 -18000 0 EST}
+ {2309410800 -14400 1 EDT}
+ {2329970400 -18000 0 EST}
+ {2341465200 -14400 1 EDT}
+ {2362024800 -18000 0 EST}
+ {2372914800 -14400 1 EDT}
+ {2393474400 -18000 0 EST}
+ {2404364400 -14400 1 EDT}
+ {2424924000 -18000 0 EST}
+ {2435814000 -14400 1 EDT}
+ {2456373600 -18000 0 EST}
+ {2467263600 -14400 1 EDT}
+ {2487823200 -18000 0 EST}
+ {2499318000 -14400 1 EDT}
+ {2519877600 -18000 0 EST}
+ {2530767600 -14400 1 EDT}
+ {2551327200 -18000 0 EST}
+ {2562217200 -14400 1 EDT}
+ {2582776800 -18000 0 EST}
+ {2593666800 -14400 1 EDT}
+ {2614226400 -18000 0 EST}
+ {2625116400 -14400 1 EDT}
+ {2645676000 -18000 0 EST}
+ {2656566000 -14400 1 EDT}
+ {2677125600 -18000 0 EST}
+ {2688620400 -14400 1 EDT}
+ {2709180000 -18000 0 EST}
+ {2720070000 -14400 1 EDT}
+ {2740629600 -18000 0 EST}
+ {2751519600 -14400 1 EDT}
+ {2772079200 -18000 0 EST}
+ {2782969200 -14400 1 EDT}
+ {2803528800 -18000 0 EST}
+ {2814418800 -14400 1 EDT}
+ {2834978400 -18000 0 EST}
+ {2846473200 -14400 1 EDT}
+ {2867032800 -18000 0 EST}
+ {2877922800 -14400 1 EDT}
+ {2898482400 -18000 0 EST}
+ {2909372400 -14400 1 EDT}
+ {2929932000 -18000 0 EST}
+ {2940822000 -14400 1 EDT}
+ {2961381600 -18000 0 EST}
+ {2972271600 -14400 1 EDT}
+ {2992831200 -18000 0 EST}
+ {3003721200 -14400 1 EDT}
+ {3024280800 -18000 0 EST}
+ {3035775600 -14400 1 EDT}
+ {3056335200 -18000 0 EST}
+ {3067225200 -14400 1 EDT}
+ {3087784800 -18000 0 EST}
+ {3098674800 -14400 1 EDT}
+ {3119234400 -18000 0 EST}
+ {3130124400 -14400 1 EDT}
+ {3150684000 -18000 0 EST}
+ {3161574000 -14400 1 EDT}
+ {3182133600 -18000 0 EST}
+ {3193023600 -14400 1 EDT}
+ {3213583200 -18000 0 EST}
+ {3225078000 -14400 1 EDT}
+ {3245637600 -18000 0 EST}
+ {3256527600 -14400 1 EDT}
+ {3277087200 -18000 0 EST}
+ {3287977200 -14400 1 EDT}
+ {3308536800 -18000 0 EST}
+ {3319426800 -14400 1 EDT}
+ {3339986400 -18000 0 EST}
+ {3350876400 -14400 1 EDT}
+ {3371436000 -18000 0 EST}
+ {3382930800 -14400 1 EDT}
+ {3403490400 -18000 0 EST}
+ {3414380400 -14400 1 EDT}
+ {3434940000 -18000 0 EST}
+ {3445830000 -14400 1 EDT}
+ {3466389600 -18000 0 EST}
+ {3477279600 -14400 1 EDT}
+ {3497839200 -18000 0 EST}
+ {3508729200 -14400 1 EDT}
+ {3529288800 -18000 0 EST}
+ {3540178800 -14400 1 EDT}
+ {3560738400 -18000 0 EST}
+ {3572233200 -14400 1 EDT}
+ {3592792800 -18000 0 EST}
+ {3603682800 -14400 1 EDT}
+ {3624242400 -18000 0 EST}
+ {3635132400 -14400 1 EDT}
+ {3655692000 -18000 0 EST}
+ {3666582000 -14400 1 EDT}
+ {3687141600 -18000 0 EST}
+ {3698031600 -14400 1 EDT}
+ {3718591200 -18000 0 EST}
+ {3730086000 -14400 1 EDT}
+ {3750645600 -18000 0 EST}
+ {3761535600 -14400 1 EDT}
+ {3782095200 -18000 0 EST}
+ {3792985200 -14400 1 EDT}
+ {3813544800 -18000 0 EST}
+ {3824434800 -14400 1 EDT}
+ {3844994400 -18000 0 EST}
+ {3855884400 -14400 1 EDT}
+ {3876444000 -18000 0 EST}
+ {3887334000 -14400 1 EDT}
+ {3907893600 -18000 0 EST}
+ {3919388400 -14400 1 EDT}
+ {3939948000 -18000 0 EST}
+ {3950838000 -14400 1 EDT}
+ {3971397600 -18000 0 EST}
+ {3982287600 -14400 1 EDT}
+ {4002847200 -18000 0 EST}
+ {4013737200 -14400 1 EDT}
+ {4034296800 -18000 0 EST}
+ {4045186800 -14400 1 EDT}
+ {4065746400 -18000 0 EST}
+ {4076636400 -14400 1 EDT}
+ {4097196000 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Indiana/Winamac b/library/tzdata/America/Indiana/Winamac
new file mode 100755
index 0000000..fb6cd37
--- /dev/null
+++ b/library/tzdata/America/Indiana/Winamac
@@ -0,0 +1,240 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Indiana/Winamac) {
+ {-9223372036854775808 -20785 0 LMT}
+ {-2717647200 -21600 0 CST}
+ {-1633276800 -18000 1 CDT}
+ {-1615136400 -21600 0 CST}
+ {-1601827200 -18000 1 CDT}
+ {-1583686800 -21600 0 CST}
+ {-880214400 -18000 1 CWT}
+ {-769395600 -18000 1 CPT}
+ {-765392400 -21600 0 CST}
+ {-757360800 -21600 0 CST}
+ {-747244800 -18000 1 CDT}
+ {-733942800 -21600 0 CST}
+ {-715795200 -18000 1 CDT}
+ {-702493200 -21600 0 CST}
+ {-684345600 -18000 1 CDT}
+ {-671043600 -21600 0 CST}
+ {-652896000 -18000 1 CDT}
+ {-639594000 -21600 0 CST}
+ {-620841600 -18000 1 CDT}
+ {-608144400 -21600 0 CST}
+ {-589392000 -18000 1 CDT}
+ {-576090000 -21600 0 CST}
+ {-557942400 -18000 1 CDT}
+ {-544640400 -21600 0 CST}
+ {-526492800 -18000 1 CDT}
+ {-513190800 -21600 0 CST}
+ {-495043200 -18000 1 CDT}
+ {-481741200 -21600 0 CST}
+ {-463593600 -18000 1 CDT}
+ {-447267600 -21600 0 CST}
+ {-431539200 -18000 1 CDT}
+ {-415818000 -21600 0 CST}
+ {-400089600 -18000 1 CDT}
+ {-386787600 -21600 0 CST}
+ {-368640000 -18000 1 CDT}
+ {-355338000 -21600 0 CST}
+ {-337190400 -18000 1 CDT}
+ {-323888400 -21600 0 CST}
+ {-305740800 -18000 1 CDT}
+ {-292438800 -21600 0 CST}
+ {-273686400 -18000 0 EST}
+ {-31518000 -18000 0 EST}
+ {-21488400 -14400 1 EDT}
+ {-5767200 -18000 0 EST}
+ {9961200 -14400 1 EDT}
+ {25682400 -18000 0 EST}
+ {31554000 -18000 0 EST}
+ {1143961200 -21600 0 CST}
+ {1143964800 -18000 1 CDT}
+ {1162105200 -21600 0 CST}
+ {1173600000 -14400 0 EDT}
+ {1194156000 -18000 0 EST}
+ {1205046000 -14400 1 EDT}
+ {1225605600 -18000 0 EST}
+ {1236495600 -14400 1 EDT}
+ {1257055200 -18000 0 EST}
+ {1268550000 -14400 1 EDT}
+ {1289109600 -18000 0 EST}
+ {1299999600 -14400 1 EDT}
+ {1320559200 -18000 0 EST}
+ {1331449200 -14400 1 EDT}
+ {1352008800 -18000 0 EST}
+ {1362898800 -14400 1 EDT}
+ {1383458400 -18000 0 EST}
+ {1394348400 -14400 1 EDT}
+ {1414908000 -18000 0 EST}
+ {1425798000 -14400 1 EDT}
+ {1446357600 -18000 0 EST}
+ {1457852400 -14400 1 EDT}
+ {1478412000 -18000 0 EST}
+ {1489302000 -14400 1 EDT}
+ {1509861600 -18000 0 EST}
+ {1520751600 -14400 1 EDT}
+ {1541311200 -18000 0 EST}
+ {1552201200 -14400 1 EDT}
+ {1572760800 -18000 0 EST}
+ {1583650800 -14400 1 EDT}
+ {1604210400 -18000 0 EST}
+ {1615705200 -14400 1 EDT}
+ {1636264800 -18000 0 EST}
+ {1647154800 -14400 1 EDT}
+ {1667714400 -18000 0 EST}
+ {1678604400 -14400 1 EDT}
+ {1699164000 -18000 0 EST}
+ {1710054000 -14400 1 EDT}
+ {1730613600 -18000 0 EST}
+ {1741503600 -14400 1 EDT}
+ {1762063200 -18000 0 EST}
+ {1772953200 -14400 1 EDT}
+ {1793512800 -18000 0 EST}
+ {1805007600 -14400 1 EDT}
+ {1825567200 -18000 0 EST}
+ {1836457200 -14400 1 EDT}
+ {1857016800 -18000 0 EST}
+ {1867906800 -14400 1 EDT}
+ {1888466400 -18000 0 EST}
+ {1899356400 -14400 1 EDT}
+ {1919916000 -18000 0 EST}
+ {1930806000 -14400 1 EDT}
+ {1951365600 -18000 0 EST}
+ {1962860400 -14400 1 EDT}
+ {1983420000 -18000 0 EST}
+ {1994310000 -14400 1 EDT}
+ {2014869600 -18000 0 EST}
+ {2025759600 -14400 1 EDT}
+ {2046319200 -18000 0 EST}
+ {2057209200 -14400 1 EDT}
+ {2077768800 -18000 0 EST}
+ {2088658800 -14400 1 EDT}
+ {2109218400 -18000 0 EST}
+ {2120108400 -14400 1 EDT}
+ {2140668000 -18000 0 EST}
+ {2152162800 -14400 1 EDT}
+ {2172722400 -18000 0 EST}
+ {2183612400 -14400 1 EDT}
+ {2204172000 -18000 0 EST}
+ {2215062000 -14400 1 EDT}
+ {2235621600 -18000 0 EST}
+ {2246511600 -14400 1 EDT}
+ {2267071200 -18000 0 EST}
+ {2277961200 -14400 1 EDT}
+ {2298520800 -18000 0 EST}
+ {2309410800 -14400 1 EDT}
+ {2329970400 -18000 0 EST}
+ {2341465200 -14400 1 EDT}
+ {2362024800 -18000 0 EST}
+ {2372914800 -14400 1 EDT}
+ {2393474400 -18000 0 EST}
+ {2404364400 -14400 1 EDT}
+ {2424924000 -18000 0 EST}
+ {2435814000 -14400 1 EDT}
+ {2456373600 -18000 0 EST}
+ {2467263600 -14400 1 EDT}
+ {2487823200 -18000 0 EST}
+ {2499318000 -14400 1 EDT}
+ {2519877600 -18000 0 EST}
+ {2530767600 -14400 1 EDT}
+ {2551327200 -18000 0 EST}
+ {2562217200 -14400 1 EDT}
+ {2582776800 -18000 0 EST}
+ {2593666800 -14400 1 EDT}
+ {2614226400 -18000 0 EST}
+ {2625116400 -14400 1 EDT}
+ {2645676000 -18000 0 EST}
+ {2656566000 -14400 1 EDT}
+ {2677125600 -18000 0 EST}
+ {2688620400 -14400 1 EDT}
+ {2709180000 -18000 0 EST}
+ {2720070000 -14400 1 EDT}
+ {2740629600 -18000 0 EST}
+ {2751519600 -14400 1 EDT}
+ {2772079200 -18000 0 EST}
+ {2782969200 -14400 1 EDT}
+ {2803528800 -18000 0 EST}
+ {2814418800 -14400 1 EDT}
+ {2834978400 -18000 0 EST}
+ {2846473200 -14400 1 EDT}
+ {2867032800 -18000 0 EST}
+ {2877922800 -14400 1 EDT}
+ {2898482400 -18000 0 EST}
+ {2909372400 -14400 1 EDT}
+ {2929932000 -18000 0 EST}
+ {2940822000 -14400 1 EDT}
+ {2961381600 -18000 0 EST}
+ {2972271600 -14400 1 EDT}
+ {2992831200 -18000 0 EST}
+ {3003721200 -14400 1 EDT}
+ {3024280800 -18000 0 EST}
+ {3035775600 -14400 1 EDT}
+ {3056335200 -18000 0 EST}
+ {3067225200 -14400 1 EDT}
+ {3087784800 -18000 0 EST}
+ {3098674800 -14400 1 EDT}
+ {3119234400 -18000 0 EST}
+ {3130124400 -14400 1 EDT}
+ {3150684000 -18000 0 EST}
+ {3161574000 -14400 1 EDT}
+ {3182133600 -18000 0 EST}
+ {3193023600 -14400 1 EDT}
+ {3213583200 -18000 0 EST}
+ {3225078000 -14400 1 EDT}
+ {3245637600 -18000 0 EST}
+ {3256527600 -14400 1 EDT}
+ {3277087200 -18000 0 EST}
+ {3287977200 -14400 1 EDT}
+ {3308536800 -18000 0 EST}
+ {3319426800 -14400 1 EDT}
+ {3339986400 -18000 0 EST}
+ {3350876400 -14400 1 EDT}
+ {3371436000 -18000 0 EST}
+ {3382930800 -14400 1 EDT}
+ {3403490400 -18000 0 EST}
+ {3414380400 -14400 1 EDT}
+ {3434940000 -18000 0 EST}
+ {3445830000 -14400 1 EDT}
+ {3466389600 -18000 0 EST}
+ {3477279600 -14400 1 EDT}
+ {3497839200 -18000 0 EST}
+ {3508729200 -14400 1 EDT}
+ {3529288800 -18000 0 EST}
+ {3540178800 -14400 1 EDT}
+ {3560738400 -18000 0 EST}
+ {3572233200 -14400 1 EDT}
+ {3592792800 -18000 0 EST}
+ {3603682800 -14400 1 EDT}
+ {3624242400 -18000 0 EST}
+ {3635132400 -14400 1 EDT}
+ {3655692000 -18000 0 EST}
+ {3666582000 -14400 1 EDT}
+ {3687141600 -18000 0 EST}
+ {3698031600 -14400 1 EDT}
+ {3718591200 -18000 0 EST}
+ {3730086000 -14400 1 EDT}
+ {3750645600 -18000 0 EST}
+ {3761535600 -14400 1 EDT}
+ {3782095200 -18000 0 EST}
+ {3792985200 -14400 1 EDT}
+ {3813544800 -18000 0 EST}
+ {3824434800 -14400 1 EDT}
+ {3844994400 -18000 0 EST}
+ {3855884400 -14400 1 EDT}
+ {3876444000 -18000 0 EST}
+ {3887334000 -14400 1 EDT}
+ {3907893600 -18000 0 EST}
+ {3919388400 -14400 1 EDT}
+ {3939948000 -18000 0 EST}
+ {3950838000 -14400 1 EDT}
+ {3971397600 -18000 0 EST}
+ {3982287600 -14400 1 EDT}
+ {4002847200 -18000 0 EST}
+ {4013737200 -14400 1 EDT}
+ {4034296800 -18000 0 EST}
+ {4045186800 -14400 1 EDT}
+ {4065746400 -18000 0 EST}
+ {4076636400 -14400 1 EDT}
+ {4097196000 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Indianapolis b/library/tzdata/America/Indianapolis
new file mode 100644
index 0000000..7398545
--- /dev/null
+++ b/library/tzdata/America/Indianapolis
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Indiana/Indianapolis)]} {
+ LoadTimeZoneFile America/Indiana/Indianapolis
+}
+set TZData(:America/Indianapolis) $TZData(:America/Indiana/Indianapolis)
diff --git a/library/tzdata/America/Inuvik b/library/tzdata/America/Inuvik
new file mode 100644
index 0000000..dd0d151
--- /dev/null
+++ b/library/tzdata/America/Inuvik
@@ -0,0 +1,249 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Inuvik) {
+ {-9223372036854775808 0 0 zzz}
+ {-536457600 -28800 0 PST}
+ {-147888000 -21600 1 PDDT}
+ {-131558400 -28800 0 PST}
+ {315558000 -25200 0 MST}
+ {325674000 -21600 1 MDT}
+ {341395200 -25200 0 MST}
+ {357123600 -21600 1 MDT}
+ {372844800 -25200 0 MST}
+ {388573200 -21600 1 MDT}
+ {404899200 -25200 0 MST}
+ {420022800 -21600 1 MDT}
+ {436348800 -25200 0 MST}
+ {452077200 -21600 1 MDT}
+ {467798400 -25200 0 MST}
+ {483526800 -21600 1 MDT}
+ {499248000 -25200 0 MST}
+ {514976400 -21600 1 MDT}
+ {530697600 -25200 0 MST}
+ {544611600 -21600 1 MDT}
+ {562147200 -25200 0 MST}
+ {576061200 -21600 1 MDT}
+ {594201600 -25200 0 MST}
+ {607510800 -21600 1 MDT}
+ {625651200 -25200 0 MST}
+ {638960400 -21600 1 MDT}
+ {657100800 -25200 0 MST}
+ {671014800 -21600 1 MDT}
+ {688550400 -25200 0 MST}
+ {702464400 -21600 1 MDT}
+ {720000000 -25200 0 MST}
+ {733914000 -21600 1 MDT}
+ {752054400 -25200 0 MST}
+ {765363600 -21600 1 MDT}
+ {783504000 -25200 0 MST}
+ {796813200 -21600 1 MDT}
+ {814953600 -25200 0 MST}
+ {828867600 -21600 1 MDT}
+ {846403200 -25200 0 MST}
+ {860317200 -21600 1 MDT}
+ {877852800 -25200 0 MST}
+ {891766800 -21600 1 MDT}
+ {909302400 -25200 0 MST}
+ {923216400 -21600 1 MDT}
+ {941356800 -25200 0 MST}
+ {954666000 -21600 1 MDT}
+ {972806400 -25200 0 MST}
+ {986115600 -21600 1 MDT}
+ {1004256000 -25200 0 MST}
+ {1018170000 -21600 1 MDT}
+ {1035705600 -25200 0 MST}
+ {1049619600 -21600 1 MDT}
+ {1067155200 -25200 0 MST}
+ {1081069200 -21600 1 MDT}
+ {1099209600 -25200 0 MST}
+ {1112518800 -21600 1 MDT}
+ {1130659200 -25200 0 MST}
+ {1143968400 -21600 1 MDT}
+ {1162108800 -25200 0 MST}
+ {1173603600 -21600 1 MDT}
+ {1194163200 -25200 0 MST}
+ {1205053200 -21600 1 MDT}
+ {1225612800 -25200 0 MST}
+ {1236502800 -21600 1 MDT}
+ {1257062400 -25200 0 MST}
+ {1268557200 -21600 1 MDT}
+ {1289116800 -25200 0 MST}
+ {1300006800 -21600 1 MDT}
+ {1320566400 -25200 0 MST}
+ {1331456400 -21600 1 MDT}
+ {1352016000 -25200 0 MST}
+ {1362906000 -21600 1 MDT}
+ {1383465600 -25200 0 MST}
+ {1394355600 -21600 1 MDT}
+ {1414915200 -25200 0 MST}
+ {1425805200 -21600 1 MDT}
+ {1446364800 -25200 0 MST}
+ {1457859600 -21600 1 MDT}
+ {1478419200 -25200 0 MST}
+ {1489309200 -21600 1 MDT}
+ {1509868800 -25200 0 MST}
+ {1520758800 -21600 1 MDT}
+ {1541318400 -25200 0 MST}
+ {1552208400 -21600 1 MDT}
+ {1572768000 -25200 0 MST}
+ {1583658000 -21600 1 MDT}
+ {1604217600 -25200 0 MST}
+ {1615712400 -21600 1 MDT}
+ {1636272000 -25200 0 MST}
+ {1647162000 -21600 1 MDT}
+ {1667721600 -25200 0 MST}
+ {1678611600 -21600 1 MDT}
+ {1699171200 -25200 0 MST}
+ {1710061200 -21600 1 MDT}
+ {1730620800 -25200 0 MST}
+ {1741510800 -21600 1 MDT}
+ {1762070400 -25200 0 MST}
+ {1772960400 -21600 1 MDT}
+ {1793520000 -25200 0 MST}
+ {1805014800 -21600 1 MDT}
+ {1825574400 -25200 0 MST}
+ {1836464400 -21600 1 MDT}
+ {1857024000 -25200 0 MST}
+ {1867914000 -21600 1 MDT}
+ {1888473600 -25200 0 MST}
+ {1899363600 -21600 1 MDT}
+ {1919923200 -25200 0 MST}
+ {1930813200 -21600 1 MDT}
+ {1951372800 -25200 0 MST}
+ {1962867600 -21600 1 MDT}
+ {1983427200 -25200 0 MST}
+ {1994317200 -21600 1 MDT}
+ {2014876800 -25200 0 MST}
+ {2025766800 -21600 1 MDT}
+ {2046326400 -25200 0 MST}
+ {2057216400 -21600 1 MDT}
+ {2077776000 -25200 0 MST}
+ {2088666000 -21600 1 MDT}
+ {2109225600 -25200 0 MST}
+ {2120115600 -21600 1 MDT}
+ {2140675200 -25200 0 MST}
+ {2152170000 -21600 1 MDT}
+ {2172729600 -25200 0 MST}
+ {2183619600 -21600 1 MDT}
+ {2204179200 -25200 0 MST}
+ {2215069200 -21600 1 MDT}
+ {2235628800 -25200 0 MST}
+ {2246518800 -21600 1 MDT}
+ {2267078400 -25200 0 MST}
+ {2277968400 -21600 1 MDT}
+ {2298528000 -25200 0 MST}
+ {2309418000 -21600 1 MDT}
+ {2329977600 -25200 0 MST}
+ {2341472400 -21600 1 MDT}
+ {2362032000 -25200 0 MST}
+ {2372922000 -21600 1 MDT}
+ {2393481600 -25200 0 MST}
+ {2404371600 -21600 1 MDT}
+ {2424931200 -25200 0 MST}
+ {2435821200 -21600 1 MDT}
+ {2456380800 -25200 0 MST}
+ {2467270800 -21600 1 MDT}
+ {2487830400 -25200 0 MST}
+ {2499325200 -21600 1 MDT}
+ {2519884800 -25200 0 MST}
+ {2530774800 -21600 1 MDT}
+ {2551334400 -25200 0 MST}
+ {2562224400 -21600 1 MDT}
+ {2582784000 -25200 0 MST}
+ {2593674000 -21600 1 MDT}
+ {2614233600 -25200 0 MST}
+ {2625123600 -21600 1 MDT}
+ {2645683200 -25200 0 MST}
+ {2656573200 -21600 1 MDT}
+ {2677132800 -25200 0 MST}
+ {2688627600 -21600 1 MDT}
+ {2709187200 -25200 0 MST}
+ {2720077200 -21600 1 MDT}
+ {2740636800 -25200 0 MST}
+ {2751526800 -21600 1 MDT}
+ {2772086400 -25200 0 MST}
+ {2782976400 -21600 1 MDT}
+ {2803536000 -25200 0 MST}
+ {2814426000 -21600 1 MDT}
+ {2834985600 -25200 0 MST}
+ {2846480400 -21600 1 MDT}
+ {2867040000 -25200 0 MST}
+ {2877930000 -21600 1 MDT}
+ {2898489600 -25200 0 MST}
+ {2909379600 -21600 1 MDT}
+ {2929939200 -25200 0 MST}
+ {2940829200 -21600 1 MDT}
+ {2961388800 -25200 0 MST}
+ {2972278800 -21600 1 MDT}
+ {2992838400 -25200 0 MST}
+ {3003728400 -21600 1 MDT}
+ {3024288000 -25200 0 MST}
+ {3035782800 -21600 1 MDT}
+ {3056342400 -25200 0 MST}
+ {3067232400 -21600 1 MDT}
+ {3087792000 -25200 0 MST}
+ {3098682000 -21600 1 MDT}
+ {3119241600 -25200 0 MST}
+ {3130131600 -21600 1 MDT}
+ {3150691200 -25200 0 MST}
+ {3161581200 -21600 1 MDT}
+ {3182140800 -25200 0 MST}
+ {3193030800 -21600 1 MDT}
+ {3213590400 -25200 0 MST}
+ {3225085200 -21600 1 MDT}
+ {3245644800 -25200 0 MST}
+ {3256534800 -21600 1 MDT}
+ {3277094400 -25200 0 MST}
+ {3287984400 -21600 1 MDT}
+ {3308544000 -25200 0 MST}
+ {3319434000 -21600 1 MDT}
+ {3339993600 -25200 0 MST}
+ {3350883600 -21600 1 MDT}
+ {3371443200 -25200 0 MST}
+ {3382938000 -21600 1 MDT}
+ {3403497600 -25200 0 MST}
+ {3414387600 -21600 1 MDT}
+ {3434947200 -25200 0 MST}
+ {3445837200 -21600 1 MDT}
+ {3466396800 -25200 0 MST}
+ {3477286800 -21600 1 MDT}
+ {3497846400 -25200 0 MST}
+ {3508736400 -21600 1 MDT}
+ {3529296000 -25200 0 MST}
+ {3540186000 -21600 1 MDT}
+ {3560745600 -25200 0 MST}
+ {3572240400 -21600 1 MDT}
+ {3592800000 -25200 0 MST}
+ {3603690000 -21600 1 MDT}
+ {3624249600 -25200 0 MST}
+ {3635139600 -21600 1 MDT}
+ {3655699200 -25200 0 MST}
+ {3666589200 -21600 1 MDT}
+ {3687148800 -25200 0 MST}
+ {3698038800 -21600 1 MDT}
+ {3718598400 -25200 0 MST}
+ {3730093200 -21600 1 MDT}
+ {3750652800 -25200 0 MST}
+ {3761542800 -21600 1 MDT}
+ {3782102400 -25200 0 MST}
+ {3792992400 -21600 1 MDT}
+ {3813552000 -25200 0 MST}
+ {3824442000 -21600 1 MDT}
+ {3845001600 -25200 0 MST}
+ {3855891600 -21600 1 MDT}
+ {3876451200 -25200 0 MST}
+ {3887341200 -21600 1 MDT}
+ {3907900800 -25200 0 MST}
+ {3919395600 -21600 1 MDT}
+ {3939955200 -25200 0 MST}
+ {3950845200 -21600 1 MDT}
+ {3971404800 -25200 0 MST}
+ {3982294800 -21600 1 MDT}
+ {4002854400 -25200 0 MST}
+ {4013744400 -21600 1 MDT}
+ {4034304000 -25200 0 MST}
+ {4045194000 -21600 1 MDT}
+ {4065753600 -25200 0 MST}
+ {4076643600 -21600 1 MDT}
+ {4097203200 -25200 0 MST}
+}
diff --git a/library/tzdata/America/Iqaluit b/library/tzdata/America/Iqaluit
new file mode 100644
index 0000000..2a2e9fe
--- /dev/null
+++ b/library/tzdata/America/Iqaluit
@@ -0,0 +1,250 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Iqaluit) {
+ {-9223372036854775808 0 0 zzz}
+ {-865296000 -14400 0 EWT}
+ {-769395600 -14400 1 EPT}
+ {-765396000 -18000 0 EST}
+ {-147898800 -10800 1 EDDT}
+ {-131569200 -18000 0 EST}
+ {325666800 -14400 1 EDT}
+ {341388000 -18000 0 EST}
+ {357116400 -14400 1 EDT}
+ {372837600 -18000 0 EST}
+ {388566000 -14400 1 EDT}
+ {404892000 -18000 0 EST}
+ {420015600 -14400 1 EDT}
+ {436341600 -18000 0 EST}
+ {452070000 -14400 1 EDT}
+ {467791200 -18000 0 EST}
+ {483519600 -14400 1 EDT}
+ {499240800 -18000 0 EST}
+ {514969200 -14400 1 EDT}
+ {530690400 -18000 0 EST}
+ {544604400 -14400 1 EDT}
+ {562140000 -18000 0 EST}
+ {576054000 -14400 1 EDT}
+ {594194400 -18000 0 EST}
+ {607503600 -14400 1 EDT}
+ {625644000 -18000 0 EST}
+ {638953200 -14400 1 EDT}
+ {657093600 -18000 0 EST}
+ {671007600 -14400 1 EDT}
+ {688543200 -18000 0 EST}
+ {702457200 -14400 1 EDT}
+ {719992800 -18000 0 EST}
+ {733906800 -14400 1 EDT}
+ {752047200 -18000 0 EST}
+ {765356400 -14400 1 EDT}
+ {783496800 -18000 0 EST}
+ {796806000 -14400 1 EDT}
+ {814946400 -18000 0 EST}
+ {828860400 -14400 1 EDT}
+ {846396000 -18000 0 EST}
+ {860310000 -14400 1 EDT}
+ {877845600 -18000 0 EST}
+ {891759600 -14400 1 EDT}
+ {909295200 -18000 0 EST}
+ {923209200 -14400 1 EDT}
+ {941353200 -21600 0 CST}
+ {954662400 -18000 1 CDT}
+ {972806400 -18000 0 EST}
+ {986108400 -14400 1 EDT}
+ {1004248800 -18000 0 EST}
+ {1018162800 -14400 1 EDT}
+ {1035698400 -18000 0 EST}
+ {1049612400 -14400 1 EDT}
+ {1067148000 -18000 0 EST}
+ {1081062000 -14400 1 EDT}
+ {1099202400 -18000 0 EST}
+ {1112511600 -14400 1 EDT}
+ {1130652000 -18000 0 EST}
+ {1143961200 -14400 1 EDT}
+ {1162101600 -18000 0 EST}
+ {1173596400 -14400 1 EDT}
+ {1194156000 -18000 0 EST}
+ {1205046000 -14400 1 EDT}
+ {1225605600 -18000 0 EST}
+ {1236495600 -14400 1 EDT}
+ {1257055200 -18000 0 EST}
+ {1268550000 -14400 1 EDT}
+ {1289109600 -18000 0 EST}
+ {1299999600 -14400 1 EDT}
+ {1320559200 -18000 0 EST}
+ {1331449200 -14400 1 EDT}
+ {1352008800 -18000 0 EST}
+ {1362898800 -14400 1 EDT}
+ {1383458400 -18000 0 EST}
+ {1394348400 -14400 1 EDT}
+ {1414908000 -18000 0 EST}
+ {1425798000 -14400 1 EDT}
+ {1446357600 -18000 0 EST}
+ {1457852400 -14400 1 EDT}
+ {1478412000 -18000 0 EST}
+ {1489302000 -14400 1 EDT}
+ {1509861600 -18000 0 EST}
+ {1520751600 -14400 1 EDT}
+ {1541311200 -18000 0 EST}
+ {1552201200 -14400 1 EDT}
+ {1572760800 -18000 0 EST}
+ {1583650800 -14400 1 EDT}
+ {1604210400 -18000 0 EST}
+ {1615705200 -14400 1 EDT}
+ {1636264800 -18000 0 EST}
+ {1647154800 -14400 1 EDT}
+ {1667714400 -18000 0 EST}
+ {1678604400 -14400 1 EDT}
+ {1699164000 -18000 0 EST}
+ {1710054000 -14400 1 EDT}
+ {1730613600 -18000 0 EST}
+ {1741503600 -14400 1 EDT}
+ {1762063200 -18000 0 EST}
+ {1772953200 -14400 1 EDT}
+ {1793512800 -18000 0 EST}
+ {1805007600 -14400 1 EDT}
+ {1825567200 -18000 0 EST}
+ {1836457200 -14400 1 EDT}
+ {1857016800 -18000 0 EST}
+ {1867906800 -14400 1 EDT}
+ {1888466400 -18000 0 EST}
+ {1899356400 -14400 1 EDT}
+ {1919916000 -18000 0 EST}
+ {1930806000 -14400 1 EDT}
+ {1951365600 -18000 0 EST}
+ {1962860400 -14400 1 EDT}
+ {1983420000 -18000 0 EST}
+ {1994310000 -14400 1 EDT}
+ {2014869600 -18000 0 EST}
+ {2025759600 -14400 1 EDT}
+ {2046319200 -18000 0 EST}
+ {2057209200 -14400 1 EDT}
+ {2077768800 -18000 0 EST}
+ {2088658800 -14400 1 EDT}
+ {2109218400 -18000 0 EST}
+ {2120108400 -14400 1 EDT}
+ {2140668000 -18000 0 EST}
+ {2152162800 -14400 1 EDT}
+ {2172722400 -18000 0 EST}
+ {2183612400 -14400 1 EDT}
+ {2204172000 -18000 0 EST}
+ {2215062000 -14400 1 EDT}
+ {2235621600 -18000 0 EST}
+ {2246511600 -14400 1 EDT}
+ {2267071200 -18000 0 EST}
+ {2277961200 -14400 1 EDT}
+ {2298520800 -18000 0 EST}
+ {2309410800 -14400 1 EDT}
+ {2329970400 -18000 0 EST}
+ {2341465200 -14400 1 EDT}
+ {2362024800 -18000 0 EST}
+ {2372914800 -14400 1 EDT}
+ {2393474400 -18000 0 EST}
+ {2404364400 -14400 1 EDT}
+ {2424924000 -18000 0 EST}
+ {2435814000 -14400 1 EDT}
+ {2456373600 -18000 0 EST}
+ {2467263600 -14400 1 EDT}
+ {2487823200 -18000 0 EST}
+ {2499318000 -14400 1 EDT}
+ {2519877600 -18000 0 EST}
+ {2530767600 -14400 1 EDT}
+ {2551327200 -18000 0 EST}
+ {2562217200 -14400 1 EDT}
+ {2582776800 -18000 0 EST}
+ {2593666800 -14400 1 EDT}
+ {2614226400 -18000 0 EST}
+ {2625116400 -14400 1 EDT}
+ {2645676000 -18000 0 EST}
+ {2656566000 -14400 1 EDT}
+ {2677125600 -18000 0 EST}
+ {2688620400 -14400 1 EDT}
+ {2709180000 -18000 0 EST}
+ {2720070000 -14400 1 EDT}
+ {2740629600 -18000 0 EST}
+ {2751519600 -14400 1 EDT}
+ {2772079200 -18000 0 EST}
+ {2782969200 -14400 1 EDT}
+ {2803528800 -18000 0 EST}
+ {2814418800 -14400 1 EDT}
+ {2834978400 -18000 0 EST}
+ {2846473200 -14400 1 EDT}
+ {2867032800 -18000 0 EST}
+ {2877922800 -14400 1 EDT}
+ {2898482400 -18000 0 EST}
+ {2909372400 -14400 1 EDT}
+ {2929932000 -18000 0 EST}
+ {2940822000 -14400 1 EDT}
+ {2961381600 -18000 0 EST}
+ {2972271600 -14400 1 EDT}
+ {2992831200 -18000 0 EST}
+ {3003721200 -14400 1 EDT}
+ {3024280800 -18000 0 EST}
+ {3035775600 -14400 1 EDT}
+ {3056335200 -18000 0 EST}
+ {3067225200 -14400 1 EDT}
+ {3087784800 -18000 0 EST}
+ {3098674800 -14400 1 EDT}
+ {3119234400 -18000 0 EST}
+ {3130124400 -14400 1 EDT}
+ {3150684000 -18000 0 EST}
+ {3161574000 -14400 1 EDT}
+ {3182133600 -18000 0 EST}
+ {3193023600 -14400 1 EDT}
+ {3213583200 -18000 0 EST}
+ {3225078000 -14400 1 EDT}
+ {3245637600 -18000 0 EST}
+ {3256527600 -14400 1 EDT}
+ {3277087200 -18000 0 EST}
+ {3287977200 -14400 1 EDT}
+ {3308536800 -18000 0 EST}
+ {3319426800 -14400 1 EDT}
+ {3339986400 -18000 0 EST}
+ {3350876400 -14400 1 EDT}
+ {3371436000 -18000 0 EST}
+ {3382930800 -14400 1 EDT}
+ {3403490400 -18000 0 EST}
+ {3414380400 -14400 1 EDT}
+ {3434940000 -18000 0 EST}
+ {3445830000 -14400 1 EDT}
+ {3466389600 -18000 0 EST}
+ {3477279600 -14400 1 EDT}
+ {3497839200 -18000 0 EST}
+ {3508729200 -14400 1 EDT}
+ {3529288800 -18000 0 EST}
+ {3540178800 -14400 1 EDT}
+ {3560738400 -18000 0 EST}
+ {3572233200 -14400 1 EDT}
+ {3592792800 -18000 0 EST}
+ {3603682800 -14400 1 EDT}
+ {3624242400 -18000 0 EST}
+ {3635132400 -14400 1 EDT}
+ {3655692000 -18000 0 EST}
+ {3666582000 -14400 1 EDT}
+ {3687141600 -18000 0 EST}
+ {3698031600 -14400 1 EDT}
+ {3718591200 -18000 0 EST}
+ {3730086000 -14400 1 EDT}
+ {3750645600 -18000 0 EST}
+ {3761535600 -14400 1 EDT}
+ {3782095200 -18000 0 EST}
+ {3792985200 -14400 1 EDT}
+ {3813544800 -18000 0 EST}
+ {3824434800 -14400 1 EDT}
+ {3844994400 -18000 0 EST}
+ {3855884400 -14400 1 EDT}
+ {3876444000 -18000 0 EST}
+ {3887334000 -14400 1 EDT}
+ {3907893600 -18000 0 EST}
+ {3919388400 -14400 1 EDT}
+ {3939948000 -18000 0 EST}
+ {3950838000 -14400 1 EDT}
+ {3971397600 -18000 0 EST}
+ {3982287600 -14400 1 EDT}
+ {4002847200 -18000 0 EST}
+ {4013737200 -14400 1 EDT}
+ {4034296800 -18000 0 EST}
+ {4045186800 -14400 1 EDT}
+ {4065746400 -18000 0 EST}
+ {4076636400 -14400 1 EDT}
+ {4097196000 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Jamaica b/library/tzdata/America/Jamaica
new file mode 100644
index 0000000..393d90a8
--- /dev/null
+++ b/library/tzdata/America/Jamaica
@@ -0,0 +1,28 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Jamaica) {
+ {-9223372036854775808 -18432 0 LMT}
+ {-2524503168 -18432 0 KMT}
+ {-1827687168 -18000 0 EST}
+ {136364400 -14400 0 EDT}
+ {152085600 -18000 0 EST}
+ {162370800 -14400 1 EDT}
+ {183535200 -18000 0 EST}
+ {199263600 -14400 1 EDT}
+ {215589600 -18000 0 EST}
+ {230713200 -14400 1 EDT}
+ {247039200 -18000 0 EST}
+ {262767600 -14400 1 EDT}
+ {278488800 -18000 0 EST}
+ {294217200 -14400 1 EDT}
+ {309938400 -18000 0 EST}
+ {325666800 -14400 1 EDT}
+ {341388000 -18000 0 EST}
+ {357116400 -14400 1 EDT}
+ {372837600 -18000 0 EST}
+ {388566000 -14400 1 EDT}
+ {404892000 -18000 0 EST}
+ {420015600 -14400 1 EDT}
+ {436341600 -18000 0 EST}
+ {441781200 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Jujuy b/library/tzdata/America/Jujuy
new file mode 100644
index 0000000..b4c5da3
--- /dev/null
+++ b/library/tzdata/America/Jujuy
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Argentina/Jujuy)]} {
+ LoadTimeZoneFile America/Argentina/Jujuy
+}
+set TZData(:America/Jujuy) $TZData(:America/Argentina/Jujuy)
diff --git a/library/tzdata/America/Juneau b/library/tzdata/America/Juneau
new file mode 100644
index 0000000..fead810
--- /dev/null
+++ b/library/tzdata/America/Juneau
@@ -0,0 +1,276 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Juneau) {
+ {-9223372036854775808 54139 0 LMT}
+ {-3225366139 -32261 0 LMT}
+ {-2188954939 -28800 0 PST}
+ {-883584000 -28800 0 PST}
+ {-880207200 -25200 1 PWT}
+ {-769395600 -25200 1 PPT}
+ {-765385200 -28800 0 PST}
+ {-757353600 -28800 0 PST}
+ {-31507200 -28800 0 PST}
+ {-21477600 -25200 1 PDT}
+ {-5756400 -28800 0 PST}
+ {9972000 -25200 1 PDT}
+ {25693200 -28800 0 PST}
+ {41421600 -25200 1 PDT}
+ {57747600 -28800 0 PST}
+ {73476000 -25200 1 PDT}
+ {89197200 -28800 0 PST}
+ {104925600 -25200 1 PDT}
+ {120646800 -28800 0 PST}
+ {126698400 -25200 1 PDT}
+ {152096400 -28800 0 PST}
+ {162381600 -25200 1 PDT}
+ {183546000 -28800 0 PST}
+ {199274400 -25200 1 PDT}
+ {215600400 -28800 0 PST}
+ {230724000 -25200 1 PDT}
+ {247050000 -28800 0 PST}
+ {262778400 -25200 1 PDT}
+ {278499600 -28800 0 PST}
+ {294228000 -25200 1 PDT}
+ {309949200 -28800 0 PST}
+ {325677600 -32400 0 YST}
+ {325681200 -28800 1 YDT}
+ {341406000 -28800 0 PST}
+ {357127200 -25200 1 PDT}
+ {372848400 -28800 0 PST}
+ {388576800 -25200 1 PDT}
+ {404902800 -28800 0 PST}
+ {420026400 -25200 1 PDT}
+ {439030800 -32400 0 AKST}
+ {452084400 -28800 1 AKDT}
+ {467805600 -32400 0 AKST}
+ {483534000 -28800 1 AKDT}
+ {499255200 -32400 0 AKST}
+ {514983600 -28800 1 AKDT}
+ {530704800 -32400 0 AKST}
+ {544618800 -28800 1 AKDT}
+ {562154400 -32400 0 AKST}
+ {576068400 -28800 1 AKDT}
+ {594208800 -32400 0 AKST}
+ {607518000 -28800 1 AKDT}
+ {625658400 -32400 0 AKST}
+ {638967600 -28800 1 AKDT}
+ {657108000 -32400 0 AKST}
+ {671022000 -28800 1 AKDT}
+ {688557600 -32400 0 AKST}
+ {702471600 -28800 1 AKDT}
+ {720007200 -32400 0 AKST}
+ {733921200 -28800 1 AKDT}
+ {752061600 -32400 0 AKST}
+ {765370800 -28800 1 AKDT}
+ {783511200 -32400 0 AKST}
+ {796820400 -28800 1 AKDT}
+ {814960800 -32400 0 AKST}
+ {828874800 -28800 1 AKDT}
+ {846410400 -32400 0 AKST}
+ {860324400 -28800 1 AKDT}
+ {877860000 -32400 0 AKST}
+ {891774000 -28800 1 AKDT}
+ {909309600 -32400 0 AKST}
+ {923223600 -28800 1 AKDT}
+ {941364000 -32400 0 AKST}
+ {954673200 -28800 1 AKDT}
+ {972813600 -32400 0 AKST}
+ {986122800 -28800 1 AKDT}
+ {1004263200 -32400 0 AKST}
+ {1018177200 -28800 1 AKDT}
+ {1035712800 -32400 0 AKST}
+ {1049626800 -28800 1 AKDT}
+ {1067162400 -32400 0 AKST}
+ {1081076400 -28800 1 AKDT}
+ {1099216800 -32400 0 AKST}
+ {1112526000 -28800 1 AKDT}
+ {1130666400 -32400 0 AKST}
+ {1143975600 -28800 1 AKDT}
+ {1162116000 -32400 0 AKST}
+ {1173610800 -28800 1 AKDT}
+ {1194170400 -32400 0 AKST}
+ {1205060400 -28800 1 AKDT}
+ {1225620000 -32400 0 AKST}
+ {1236510000 -28800 1 AKDT}
+ {1257069600 -32400 0 AKST}
+ {1268564400 -28800 1 AKDT}
+ {1289124000 -32400 0 AKST}
+ {1300014000 -28800 1 AKDT}
+ {1320573600 -32400 0 AKST}
+ {1331463600 -28800 1 AKDT}
+ {1352023200 -32400 0 AKST}
+ {1362913200 -28800 1 AKDT}
+ {1383472800 -32400 0 AKST}
+ {1394362800 -28800 1 AKDT}
+ {1414922400 -32400 0 AKST}
+ {1425812400 -28800 1 AKDT}
+ {1446372000 -32400 0 AKST}
+ {1457866800 -28800 1 AKDT}
+ {1478426400 -32400 0 AKST}
+ {1489316400 -28800 1 AKDT}
+ {1509876000 -32400 0 AKST}
+ {1520766000 -28800 1 AKDT}
+ {1541325600 -32400 0 AKST}
+ {1552215600 -28800 1 AKDT}
+ {1572775200 -32400 0 AKST}
+ {1583665200 -28800 1 AKDT}
+ {1604224800 -32400 0 AKST}
+ {1615719600 -28800 1 AKDT}
+ {1636279200 -32400 0 AKST}
+ {1647169200 -28800 1 AKDT}
+ {1667728800 -32400 0 AKST}
+ {1678618800 -28800 1 AKDT}
+ {1699178400 -32400 0 AKST}
+ {1710068400 -28800 1 AKDT}
+ {1730628000 -32400 0 AKST}
+ {1741518000 -28800 1 AKDT}
+ {1762077600 -32400 0 AKST}
+ {1772967600 -28800 1 AKDT}
+ {1793527200 -32400 0 AKST}
+ {1805022000 -28800 1 AKDT}
+ {1825581600 -32400 0 AKST}
+ {1836471600 -28800 1 AKDT}
+ {1857031200 -32400 0 AKST}
+ {1867921200 -28800 1 AKDT}
+ {1888480800 -32400 0 AKST}
+ {1899370800 -28800 1 AKDT}
+ {1919930400 -32400 0 AKST}
+ {1930820400 -28800 1 AKDT}
+ {1951380000 -32400 0 AKST}
+ {1962874800 -28800 1 AKDT}
+ {1983434400 -32400 0 AKST}
+ {1994324400 -28800 1 AKDT}
+ {2014884000 -32400 0 AKST}
+ {2025774000 -28800 1 AKDT}
+ {2046333600 -32400 0 AKST}
+ {2057223600 -28800 1 AKDT}
+ {2077783200 -32400 0 AKST}
+ {2088673200 -28800 1 AKDT}
+ {2109232800 -32400 0 AKST}
+ {2120122800 -28800 1 AKDT}
+ {2140682400 -32400 0 AKST}
+ {2152177200 -28800 1 AKDT}
+ {2172736800 -32400 0 AKST}
+ {2183626800 -28800 1 AKDT}
+ {2204186400 -32400 0 AKST}
+ {2215076400 -28800 1 AKDT}
+ {2235636000 -32400 0 AKST}
+ {2246526000 -28800 1 AKDT}
+ {2267085600 -32400 0 AKST}
+ {2277975600 -28800 1 AKDT}
+ {2298535200 -32400 0 AKST}
+ {2309425200 -28800 1 AKDT}
+ {2329984800 -32400 0 AKST}
+ {2341479600 -28800 1 AKDT}
+ {2362039200 -32400 0 AKST}
+ {2372929200 -28800 1 AKDT}
+ {2393488800 -32400 0 AKST}
+ {2404378800 -28800 1 AKDT}
+ {2424938400 -32400 0 AKST}
+ {2435828400 -28800 1 AKDT}
+ {2456388000 -32400 0 AKST}
+ {2467278000 -28800 1 AKDT}
+ {2487837600 -32400 0 AKST}
+ {2499332400 -28800 1 AKDT}
+ {2519892000 -32400 0 AKST}
+ {2530782000 -28800 1 AKDT}
+ {2551341600 -32400 0 AKST}
+ {2562231600 -28800 1 AKDT}
+ {2582791200 -32400 0 AKST}
+ {2593681200 -28800 1 AKDT}
+ {2614240800 -32400 0 AKST}
+ {2625130800 -28800 1 AKDT}
+ {2645690400 -32400 0 AKST}
+ {2656580400 -28800 1 AKDT}
+ {2677140000 -32400 0 AKST}
+ {2688634800 -28800 1 AKDT}
+ {2709194400 -32400 0 AKST}
+ {2720084400 -28800 1 AKDT}
+ {2740644000 -32400 0 AKST}
+ {2751534000 -28800 1 AKDT}
+ {2772093600 -32400 0 AKST}
+ {2782983600 -28800 1 AKDT}
+ {2803543200 -32400 0 AKST}
+ {2814433200 -28800 1 AKDT}
+ {2834992800 -32400 0 AKST}
+ {2846487600 -28800 1 AKDT}
+ {2867047200 -32400 0 AKST}
+ {2877937200 -28800 1 AKDT}
+ {2898496800 -32400 0 AKST}
+ {2909386800 -28800 1 AKDT}
+ {2929946400 -32400 0 AKST}
+ {2940836400 -28800 1 AKDT}
+ {2961396000 -32400 0 AKST}
+ {2972286000 -28800 1 AKDT}
+ {2992845600 -32400 0 AKST}
+ {3003735600 -28800 1 AKDT}
+ {3024295200 -32400 0 AKST}
+ {3035790000 -28800 1 AKDT}
+ {3056349600 -32400 0 AKST}
+ {3067239600 -28800 1 AKDT}
+ {3087799200 -32400 0 AKST}
+ {3098689200 -28800 1 AKDT}
+ {3119248800 -32400 0 AKST}
+ {3130138800 -28800 1 AKDT}
+ {3150698400 -32400 0 AKST}
+ {3161588400 -28800 1 AKDT}
+ {3182148000 -32400 0 AKST}
+ {3193038000 -28800 1 AKDT}
+ {3213597600 -32400 0 AKST}
+ {3225092400 -28800 1 AKDT}
+ {3245652000 -32400 0 AKST}
+ {3256542000 -28800 1 AKDT}
+ {3277101600 -32400 0 AKST}
+ {3287991600 -28800 1 AKDT}
+ {3308551200 -32400 0 AKST}
+ {3319441200 -28800 1 AKDT}
+ {3340000800 -32400 0 AKST}
+ {3350890800 -28800 1 AKDT}
+ {3371450400 -32400 0 AKST}
+ {3382945200 -28800 1 AKDT}
+ {3403504800 -32400 0 AKST}
+ {3414394800 -28800 1 AKDT}
+ {3434954400 -32400 0 AKST}
+ {3445844400 -28800 1 AKDT}
+ {3466404000 -32400 0 AKST}
+ {3477294000 -28800 1 AKDT}
+ {3497853600 -32400 0 AKST}
+ {3508743600 -28800 1 AKDT}
+ {3529303200 -32400 0 AKST}
+ {3540193200 -28800 1 AKDT}
+ {3560752800 -32400 0 AKST}
+ {3572247600 -28800 1 AKDT}
+ {3592807200 -32400 0 AKST}
+ {3603697200 -28800 1 AKDT}
+ {3624256800 -32400 0 AKST}
+ {3635146800 -28800 1 AKDT}
+ {3655706400 -32400 0 AKST}
+ {3666596400 -28800 1 AKDT}
+ {3687156000 -32400 0 AKST}
+ {3698046000 -28800 1 AKDT}
+ {3718605600 -32400 0 AKST}
+ {3730100400 -28800 1 AKDT}
+ {3750660000 -32400 0 AKST}
+ {3761550000 -28800 1 AKDT}
+ {3782109600 -32400 0 AKST}
+ {3792999600 -28800 1 AKDT}
+ {3813559200 -32400 0 AKST}
+ {3824449200 -28800 1 AKDT}
+ {3845008800 -32400 0 AKST}
+ {3855898800 -28800 1 AKDT}
+ {3876458400 -32400 0 AKST}
+ {3887348400 -28800 1 AKDT}
+ {3907908000 -32400 0 AKST}
+ {3919402800 -28800 1 AKDT}
+ {3939962400 -32400 0 AKST}
+ {3950852400 -28800 1 AKDT}
+ {3971412000 -32400 0 AKST}
+ {3982302000 -28800 1 AKDT}
+ {4002861600 -32400 0 AKST}
+ {4013751600 -28800 1 AKDT}
+ {4034311200 -32400 0 AKST}
+ {4045201200 -28800 1 AKDT}
+ {4065760800 -32400 0 AKST}
+ {4076650800 -28800 1 AKDT}
+ {4097210400 -32400 0 AKST}
+}
diff --git a/library/tzdata/America/Kentucky/Louisville b/library/tzdata/America/Kentucky/Louisville
new file mode 100644
index 0000000..c2aa10c
--- /dev/null
+++ b/library/tzdata/America/Kentucky/Louisville
@@ -0,0 +1,314 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Kentucky/Louisville) {
+ {-9223372036854775808 -20582 0 LMT}
+ {-2717647200 -21600 0 CST}
+ {-1633276800 -18000 1 CDT}
+ {-1615136400 -21600 0 CST}
+ {-1601827200 -18000 1 CDT}
+ {-1583686800 -21600 0 CST}
+ {-1546279200 -21600 0 CST}
+ {-1535904000 -18000 1 CDT}
+ {-1525280400 -21600 0 CST}
+ {-905097600 -18000 1 CDT}
+ {-891795600 -21600 0 CST}
+ {-883591200 -21600 0 CST}
+ {-880214400 -18000 1 CWT}
+ {-769395600 -18000 1 CPT}
+ {-765392400 -21600 0 CST}
+ {-757360800 -21600 0 CST}
+ {-747244800 -18000 1 CDT}
+ {-744224400 -21600 0 CST}
+ {-715795200 -18000 1 CDT}
+ {-684349200 -18000 1 CDT}
+ {-652899600 -18000 1 CDT}
+ {-620845200 -18000 1 CDT}
+ {-608144400 -21600 0 CST}
+ {-589392000 -18000 1 CDT}
+ {-576090000 -21600 0 CST}
+ {-557942400 -18000 1 CDT}
+ {-544640400 -21600 0 CST}
+ {-526492800 -18000 1 CDT}
+ {-513190800 -21600 0 CST}
+ {-495043200 -18000 1 CDT}
+ {-481741200 -21600 0 CST}
+ {-463593600 -18000 1 CDT}
+ {-450291600 -21600 0 CST}
+ {-431539200 -18000 1 CDT}
+ {-415818000 -21600 0 CST}
+ {-400089600 -18000 1 CDT}
+ {-384368400 -21600 0 CST}
+ {-368640000 -18000 1 CDT}
+ {-352918800 -21600 0 CST}
+ {-337190400 -18000 1 CDT}
+ {-321469200 -21600 0 CST}
+ {-305740800 -18000 1 CDT}
+ {-289414800 -21600 0 CST}
+ {-273686400 -18000 1 CDT}
+ {-266432400 -18000 0 EST}
+ {-63140400 -18000 0 EST}
+ {-52938000 -14400 1 EDT}
+ {-37216800 -18000 0 EST}
+ {-21488400 -14400 1 EDT}
+ {-5767200 -18000 0 EST}
+ {9961200 -14400 1 EDT}
+ {25682400 -18000 0 EST}
+ {41410800 -14400 1 EDT}
+ {57736800 -18000 0 EST}
+ {73465200 -14400 1 EDT}
+ {89186400 -18000 0 EST}
+ {104914800 -14400 1 EDT}
+ {120636000 -18000 0 EST}
+ {126687600 -18000 1 CDT}
+ {152089200 -18000 0 EST}
+ {162370800 -14400 1 EDT}
+ {183535200 -18000 0 EST}
+ {199263600 -14400 1 EDT}
+ {215589600 -18000 0 EST}
+ {230713200 -14400 1 EDT}
+ {247039200 -18000 0 EST}
+ {262767600 -14400 1 EDT}
+ {278488800 -18000 0 EST}
+ {294217200 -14400 1 EDT}
+ {309938400 -18000 0 EST}
+ {325666800 -14400 1 EDT}
+ {341388000 -18000 0 EST}
+ {357116400 -14400 1 EDT}
+ {372837600 -18000 0 EST}
+ {388566000 -14400 1 EDT}
+ {404892000 -18000 0 EST}
+ {420015600 -14400 1 EDT}
+ {436341600 -18000 0 EST}
+ {452070000 -14400 1 EDT}
+ {467791200 -18000 0 EST}
+ {483519600 -14400 1 EDT}
+ {499240800 -18000 0 EST}
+ {514969200 -14400 1 EDT}
+ {530690400 -18000 0 EST}
+ {544604400 -14400 1 EDT}
+ {562140000 -18000 0 EST}
+ {576054000 -14400 1 EDT}
+ {594194400 -18000 0 EST}
+ {607503600 -14400 1 EDT}
+ {625644000 -18000 0 EST}
+ {638953200 -14400 1 EDT}
+ {657093600 -18000 0 EST}
+ {671007600 -14400 1 EDT}
+ {688543200 -18000 0 EST}
+ {702457200 -14400 1 EDT}
+ {719992800 -18000 0 EST}
+ {733906800 -14400 1 EDT}
+ {752047200 -18000 0 EST}
+ {765356400 -14400 1 EDT}
+ {783496800 -18000 0 EST}
+ {796806000 -14400 1 EDT}
+ {814946400 -18000 0 EST}
+ {828860400 -14400 1 EDT}
+ {846396000 -18000 0 EST}
+ {860310000 -14400 1 EDT}
+ {877845600 -18000 0 EST}
+ {891759600 -14400 1 EDT}
+ {909295200 -18000 0 EST}
+ {923209200 -14400 1 EDT}
+ {941349600 -18000 0 EST}
+ {954658800 -14400 1 EDT}
+ {972799200 -18000 0 EST}
+ {986108400 -14400 1 EDT}
+ {1004248800 -18000 0 EST}
+ {1018162800 -14400 1 EDT}
+ {1035698400 -18000 0 EST}
+ {1049612400 -14400 1 EDT}
+ {1067148000 -18000 0 EST}
+ {1081062000 -14400 1 EDT}
+ {1099202400 -18000 0 EST}
+ {1112511600 -14400 1 EDT}
+ {1130652000 -18000 0 EST}
+ {1143961200 -14400 1 EDT}
+ {1162101600 -18000 0 EST}
+ {1173596400 -14400 1 EDT}
+ {1194156000 -18000 0 EST}
+ {1205046000 -14400 1 EDT}
+ {1225605600 -18000 0 EST}
+ {1236495600 -14400 1 EDT}
+ {1257055200 -18000 0 EST}
+ {1268550000 -14400 1 EDT}
+ {1289109600 -18000 0 EST}
+ {1299999600 -14400 1 EDT}
+ {1320559200 -18000 0 EST}
+ {1331449200 -14400 1 EDT}
+ {1352008800 -18000 0 EST}
+ {1362898800 -14400 1 EDT}
+ {1383458400 -18000 0 EST}
+ {1394348400 -14400 1 EDT}
+ {1414908000 -18000 0 EST}
+ {1425798000 -14400 1 EDT}
+ {1446357600 -18000 0 EST}
+ {1457852400 -14400 1 EDT}
+ {1478412000 -18000 0 EST}
+ {1489302000 -14400 1 EDT}
+ {1509861600 -18000 0 EST}
+ {1520751600 -14400 1 EDT}
+ {1541311200 -18000 0 EST}
+ {1552201200 -14400 1 EDT}
+ {1572760800 -18000 0 EST}
+ {1583650800 -14400 1 EDT}
+ {1604210400 -18000 0 EST}
+ {1615705200 -14400 1 EDT}
+ {1636264800 -18000 0 EST}
+ {1647154800 -14400 1 EDT}
+ {1667714400 -18000 0 EST}
+ {1678604400 -14400 1 EDT}
+ {1699164000 -18000 0 EST}
+ {1710054000 -14400 1 EDT}
+ {1730613600 -18000 0 EST}
+ {1741503600 -14400 1 EDT}
+ {1762063200 -18000 0 EST}
+ {1772953200 -14400 1 EDT}
+ {1793512800 -18000 0 EST}
+ {1805007600 -14400 1 EDT}
+ {1825567200 -18000 0 EST}
+ {1836457200 -14400 1 EDT}
+ {1857016800 -18000 0 EST}
+ {1867906800 -14400 1 EDT}
+ {1888466400 -18000 0 EST}
+ {1899356400 -14400 1 EDT}
+ {1919916000 -18000 0 EST}
+ {1930806000 -14400 1 EDT}
+ {1951365600 -18000 0 EST}
+ {1962860400 -14400 1 EDT}
+ {1983420000 -18000 0 EST}
+ {1994310000 -14400 1 EDT}
+ {2014869600 -18000 0 EST}
+ {2025759600 -14400 1 EDT}
+ {2046319200 -18000 0 EST}
+ {2057209200 -14400 1 EDT}
+ {2077768800 -18000 0 EST}
+ {2088658800 -14400 1 EDT}
+ {2109218400 -18000 0 EST}
+ {2120108400 -14400 1 EDT}
+ {2140668000 -18000 0 EST}
+ {2152162800 -14400 1 EDT}
+ {2172722400 -18000 0 EST}
+ {2183612400 -14400 1 EDT}
+ {2204172000 -18000 0 EST}
+ {2215062000 -14400 1 EDT}
+ {2235621600 -18000 0 EST}
+ {2246511600 -14400 1 EDT}
+ {2267071200 -18000 0 EST}
+ {2277961200 -14400 1 EDT}
+ {2298520800 -18000 0 EST}
+ {2309410800 -14400 1 EDT}
+ {2329970400 -18000 0 EST}
+ {2341465200 -14400 1 EDT}
+ {2362024800 -18000 0 EST}
+ {2372914800 -14400 1 EDT}
+ {2393474400 -18000 0 EST}
+ {2404364400 -14400 1 EDT}
+ {2424924000 -18000 0 EST}
+ {2435814000 -14400 1 EDT}
+ {2456373600 -18000 0 EST}
+ {2467263600 -14400 1 EDT}
+ {2487823200 -18000 0 EST}
+ {2499318000 -14400 1 EDT}
+ {2519877600 -18000 0 EST}
+ {2530767600 -14400 1 EDT}
+ {2551327200 -18000 0 EST}
+ {2562217200 -14400 1 EDT}
+ {2582776800 -18000 0 EST}
+ {2593666800 -14400 1 EDT}
+ {2614226400 -18000 0 EST}
+ {2625116400 -14400 1 EDT}
+ {2645676000 -18000 0 EST}
+ {2656566000 -14400 1 EDT}
+ {2677125600 -18000 0 EST}
+ {2688620400 -14400 1 EDT}
+ {2709180000 -18000 0 EST}
+ {2720070000 -14400 1 EDT}
+ {2740629600 -18000 0 EST}
+ {2751519600 -14400 1 EDT}
+ {2772079200 -18000 0 EST}
+ {2782969200 -14400 1 EDT}
+ {2803528800 -18000 0 EST}
+ {2814418800 -14400 1 EDT}
+ {2834978400 -18000 0 EST}
+ {2846473200 -14400 1 EDT}
+ {2867032800 -18000 0 EST}
+ {2877922800 -14400 1 EDT}
+ {2898482400 -18000 0 EST}
+ {2909372400 -14400 1 EDT}
+ {2929932000 -18000 0 EST}
+ {2940822000 -14400 1 EDT}
+ {2961381600 -18000 0 EST}
+ {2972271600 -14400 1 EDT}
+ {2992831200 -18000 0 EST}
+ {3003721200 -14400 1 EDT}
+ {3024280800 -18000 0 EST}
+ {3035775600 -14400 1 EDT}
+ {3056335200 -18000 0 EST}
+ {3067225200 -14400 1 EDT}
+ {3087784800 -18000 0 EST}
+ {3098674800 -14400 1 EDT}
+ {3119234400 -18000 0 EST}
+ {3130124400 -14400 1 EDT}
+ {3150684000 -18000 0 EST}
+ {3161574000 -14400 1 EDT}
+ {3182133600 -18000 0 EST}
+ {3193023600 -14400 1 EDT}
+ {3213583200 -18000 0 EST}
+ {3225078000 -14400 1 EDT}
+ {3245637600 -18000 0 EST}
+ {3256527600 -14400 1 EDT}
+ {3277087200 -18000 0 EST}
+ {3287977200 -14400 1 EDT}
+ {3308536800 -18000 0 EST}
+ {3319426800 -14400 1 EDT}
+ {3339986400 -18000 0 EST}
+ {3350876400 -14400 1 EDT}
+ {3371436000 -18000 0 EST}
+ {3382930800 -14400 1 EDT}
+ {3403490400 -18000 0 EST}
+ {3414380400 -14400 1 EDT}
+ {3434940000 -18000 0 EST}
+ {3445830000 -14400 1 EDT}
+ {3466389600 -18000 0 EST}
+ {3477279600 -14400 1 EDT}
+ {3497839200 -18000 0 EST}
+ {3508729200 -14400 1 EDT}
+ {3529288800 -18000 0 EST}
+ {3540178800 -14400 1 EDT}
+ {3560738400 -18000 0 EST}
+ {3572233200 -14400 1 EDT}
+ {3592792800 -18000 0 EST}
+ {3603682800 -14400 1 EDT}
+ {3624242400 -18000 0 EST}
+ {3635132400 -14400 1 EDT}
+ {3655692000 -18000 0 EST}
+ {3666582000 -14400 1 EDT}
+ {3687141600 -18000 0 EST}
+ {3698031600 -14400 1 EDT}
+ {3718591200 -18000 0 EST}
+ {3730086000 -14400 1 EDT}
+ {3750645600 -18000 0 EST}
+ {3761535600 -14400 1 EDT}
+ {3782095200 -18000 0 EST}
+ {3792985200 -14400 1 EDT}
+ {3813544800 -18000 0 EST}
+ {3824434800 -14400 1 EDT}
+ {3844994400 -18000 0 EST}
+ {3855884400 -14400 1 EDT}
+ {3876444000 -18000 0 EST}
+ {3887334000 -14400 1 EDT}
+ {3907893600 -18000 0 EST}
+ {3919388400 -14400 1 EDT}
+ {3939948000 -18000 0 EST}
+ {3950838000 -14400 1 EDT}
+ {3971397600 -18000 0 EST}
+ {3982287600 -14400 1 EDT}
+ {4002847200 -18000 0 EST}
+ {4013737200 -14400 1 EDT}
+ {4034296800 -18000 0 EST}
+ {4045186800 -14400 1 EDT}
+ {4065746400 -18000 0 EST}
+ {4076636400 -14400 1 EDT}
+ {4097196000 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Kentucky/Monticello b/library/tzdata/America/Kentucky/Monticello
new file mode 100644
index 0000000..e523ecb
--- /dev/null
+++ b/library/tzdata/America/Kentucky/Monticello
@@ -0,0 +1,279 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Kentucky/Monticello) {
+ {-9223372036854775808 -20364 0 LMT}
+ {-2717647200 -21600 0 CST}
+ {-1633276800 -18000 1 CDT}
+ {-1615136400 -21600 0 CST}
+ {-1601827200 -18000 1 CDT}
+ {-1583686800 -21600 0 CST}
+ {-880214400 -18000 1 CWT}
+ {-769395600 -18000 1 CPT}
+ {-765392400 -21600 0 CST}
+ {-757360800 -21600 0 CST}
+ {-63136800 -21600 0 CST}
+ {-52934400 -18000 1 CDT}
+ {-37213200 -21600 0 CST}
+ {-21484800 -18000 1 CDT}
+ {-5763600 -21600 0 CST}
+ {9964800 -18000 1 CDT}
+ {25686000 -21600 0 CST}
+ {41414400 -18000 1 CDT}
+ {57740400 -21600 0 CST}
+ {73468800 -18000 1 CDT}
+ {89190000 -21600 0 CST}
+ {104918400 -18000 1 CDT}
+ {120639600 -21600 0 CST}
+ {126691200 -18000 1 CDT}
+ {152089200 -21600 0 CST}
+ {162374400 -18000 1 CDT}
+ {183538800 -21600 0 CST}
+ {199267200 -18000 1 CDT}
+ {215593200 -21600 0 CST}
+ {230716800 -18000 1 CDT}
+ {247042800 -21600 0 CST}
+ {262771200 -18000 1 CDT}
+ {278492400 -21600 0 CST}
+ {294220800 -18000 1 CDT}
+ {309942000 -21600 0 CST}
+ {325670400 -18000 1 CDT}
+ {341391600 -21600 0 CST}
+ {357120000 -18000 1 CDT}
+ {372841200 -21600 0 CST}
+ {388569600 -18000 1 CDT}
+ {404895600 -21600 0 CST}
+ {420019200 -18000 1 CDT}
+ {436345200 -21600 0 CST}
+ {452073600 -18000 1 CDT}
+ {467794800 -21600 0 CST}
+ {483523200 -18000 1 CDT}
+ {499244400 -21600 0 CST}
+ {514972800 -18000 1 CDT}
+ {530694000 -21600 0 CST}
+ {544608000 -18000 1 CDT}
+ {562143600 -21600 0 CST}
+ {576057600 -18000 1 CDT}
+ {594198000 -21600 0 CST}
+ {607507200 -18000 1 CDT}
+ {625647600 -21600 0 CST}
+ {638956800 -18000 1 CDT}
+ {657097200 -21600 0 CST}
+ {671011200 -18000 1 CDT}
+ {688546800 -21600 0 CST}
+ {702460800 -18000 1 CDT}
+ {719996400 -21600 0 CST}
+ {733910400 -18000 1 CDT}
+ {752050800 -21600 0 CST}
+ {765360000 -18000 1 CDT}
+ {783500400 -21600 0 CST}
+ {796809600 -18000 1 CDT}
+ {814950000 -21600 0 CST}
+ {828864000 -18000 1 CDT}
+ {846399600 -21600 0 CST}
+ {860313600 -18000 1 CDT}
+ {877849200 -21600 0 CST}
+ {891763200 -18000 1 CDT}
+ {909298800 -21600 0 CST}
+ {923212800 -18000 1 CDT}
+ {941353200 -21600 0 CST}
+ {954662400 -18000 1 CDT}
+ {972806400 -18000 0 EST}
+ {986108400 -14400 1 EDT}
+ {1004248800 -18000 0 EST}
+ {1018162800 -14400 1 EDT}
+ {1035698400 -18000 0 EST}
+ {1049612400 -14400 1 EDT}
+ {1067148000 -18000 0 EST}
+ {1081062000 -14400 1 EDT}
+ {1099202400 -18000 0 EST}
+ {1112511600 -14400 1 EDT}
+ {1130652000 -18000 0 EST}
+ {1143961200 -14400 1 EDT}
+ {1162101600 -18000 0 EST}
+ {1173596400 -14400 1 EDT}
+ {1194156000 -18000 0 EST}
+ {1205046000 -14400 1 EDT}
+ {1225605600 -18000 0 EST}
+ {1236495600 -14400 1 EDT}
+ {1257055200 -18000 0 EST}
+ {1268550000 -14400 1 EDT}
+ {1289109600 -18000 0 EST}
+ {1299999600 -14400 1 EDT}
+ {1320559200 -18000 0 EST}
+ {1331449200 -14400 1 EDT}
+ {1352008800 -18000 0 EST}
+ {1362898800 -14400 1 EDT}
+ {1383458400 -18000 0 EST}
+ {1394348400 -14400 1 EDT}
+ {1414908000 -18000 0 EST}
+ {1425798000 -14400 1 EDT}
+ {1446357600 -18000 0 EST}
+ {1457852400 -14400 1 EDT}
+ {1478412000 -18000 0 EST}
+ {1489302000 -14400 1 EDT}
+ {1509861600 -18000 0 EST}
+ {1520751600 -14400 1 EDT}
+ {1541311200 -18000 0 EST}
+ {1552201200 -14400 1 EDT}
+ {1572760800 -18000 0 EST}
+ {1583650800 -14400 1 EDT}
+ {1604210400 -18000 0 EST}
+ {1615705200 -14400 1 EDT}
+ {1636264800 -18000 0 EST}
+ {1647154800 -14400 1 EDT}
+ {1667714400 -18000 0 EST}
+ {1678604400 -14400 1 EDT}
+ {1699164000 -18000 0 EST}
+ {1710054000 -14400 1 EDT}
+ {1730613600 -18000 0 EST}
+ {1741503600 -14400 1 EDT}
+ {1762063200 -18000 0 EST}
+ {1772953200 -14400 1 EDT}
+ {1793512800 -18000 0 EST}
+ {1805007600 -14400 1 EDT}
+ {1825567200 -18000 0 EST}
+ {1836457200 -14400 1 EDT}
+ {1857016800 -18000 0 EST}
+ {1867906800 -14400 1 EDT}
+ {1888466400 -18000 0 EST}
+ {1899356400 -14400 1 EDT}
+ {1919916000 -18000 0 EST}
+ {1930806000 -14400 1 EDT}
+ {1951365600 -18000 0 EST}
+ {1962860400 -14400 1 EDT}
+ {1983420000 -18000 0 EST}
+ {1994310000 -14400 1 EDT}
+ {2014869600 -18000 0 EST}
+ {2025759600 -14400 1 EDT}
+ {2046319200 -18000 0 EST}
+ {2057209200 -14400 1 EDT}
+ {2077768800 -18000 0 EST}
+ {2088658800 -14400 1 EDT}
+ {2109218400 -18000 0 EST}
+ {2120108400 -14400 1 EDT}
+ {2140668000 -18000 0 EST}
+ {2152162800 -14400 1 EDT}
+ {2172722400 -18000 0 EST}
+ {2183612400 -14400 1 EDT}
+ {2204172000 -18000 0 EST}
+ {2215062000 -14400 1 EDT}
+ {2235621600 -18000 0 EST}
+ {2246511600 -14400 1 EDT}
+ {2267071200 -18000 0 EST}
+ {2277961200 -14400 1 EDT}
+ {2298520800 -18000 0 EST}
+ {2309410800 -14400 1 EDT}
+ {2329970400 -18000 0 EST}
+ {2341465200 -14400 1 EDT}
+ {2362024800 -18000 0 EST}
+ {2372914800 -14400 1 EDT}
+ {2393474400 -18000 0 EST}
+ {2404364400 -14400 1 EDT}
+ {2424924000 -18000 0 EST}
+ {2435814000 -14400 1 EDT}
+ {2456373600 -18000 0 EST}
+ {2467263600 -14400 1 EDT}
+ {2487823200 -18000 0 EST}
+ {2499318000 -14400 1 EDT}
+ {2519877600 -18000 0 EST}
+ {2530767600 -14400 1 EDT}
+ {2551327200 -18000 0 EST}
+ {2562217200 -14400 1 EDT}
+ {2582776800 -18000 0 EST}
+ {2593666800 -14400 1 EDT}
+ {2614226400 -18000 0 EST}
+ {2625116400 -14400 1 EDT}
+ {2645676000 -18000 0 EST}
+ {2656566000 -14400 1 EDT}
+ {2677125600 -18000 0 EST}
+ {2688620400 -14400 1 EDT}
+ {2709180000 -18000 0 EST}
+ {2720070000 -14400 1 EDT}
+ {2740629600 -18000 0 EST}
+ {2751519600 -14400 1 EDT}
+ {2772079200 -18000 0 EST}
+ {2782969200 -14400 1 EDT}
+ {2803528800 -18000 0 EST}
+ {2814418800 -14400 1 EDT}
+ {2834978400 -18000 0 EST}
+ {2846473200 -14400 1 EDT}
+ {2867032800 -18000 0 EST}
+ {2877922800 -14400 1 EDT}
+ {2898482400 -18000 0 EST}
+ {2909372400 -14400 1 EDT}
+ {2929932000 -18000 0 EST}
+ {2940822000 -14400 1 EDT}
+ {2961381600 -18000 0 EST}
+ {2972271600 -14400 1 EDT}
+ {2992831200 -18000 0 EST}
+ {3003721200 -14400 1 EDT}
+ {3024280800 -18000 0 EST}
+ {3035775600 -14400 1 EDT}
+ {3056335200 -18000 0 EST}
+ {3067225200 -14400 1 EDT}
+ {3087784800 -18000 0 EST}
+ {3098674800 -14400 1 EDT}
+ {3119234400 -18000 0 EST}
+ {3130124400 -14400 1 EDT}
+ {3150684000 -18000 0 EST}
+ {3161574000 -14400 1 EDT}
+ {3182133600 -18000 0 EST}
+ {3193023600 -14400 1 EDT}
+ {3213583200 -18000 0 EST}
+ {3225078000 -14400 1 EDT}
+ {3245637600 -18000 0 EST}
+ {3256527600 -14400 1 EDT}
+ {3277087200 -18000 0 EST}
+ {3287977200 -14400 1 EDT}
+ {3308536800 -18000 0 EST}
+ {3319426800 -14400 1 EDT}
+ {3339986400 -18000 0 EST}
+ {3350876400 -14400 1 EDT}
+ {3371436000 -18000 0 EST}
+ {3382930800 -14400 1 EDT}
+ {3403490400 -18000 0 EST}
+ {3414380400 -14400 1 EDT}
+ {3434940000 -18000 0 EST}
+ {3445830000 -14400 1 EDT}
+ {3466389600 -18000 0 EST}
+ {3477279600 -14400 1 EDT}
+ {3497839200 -18000 0 EST}
+ {3508729200 -14400 1 EDT}
+ {3529288800 -18000 0 EST}
+ {3540178800 -14400 1 EDT}
+ {3560738400 -18000 0 EST}
+ {3572233200 -14400 1 EDT}
+ {3592792800 -18000 0 EST}
+ {3603682800 -14400 1 EDT}
+ {3624242400 -18000 0 EST}
+ {3635132400 -14400 1 EDT}
+ {3655692000 -18000 0 EST}
+ {3666582000 -14400 1 EDT}
+ {3687141600 -18000 0 EST}
+ {3698031600 -14400 1 EDT}
+ {3718591200 -18000 0 EST}
+ {3730086000 -14400 1 EDT}
+ {3750645600 -18000 0 EST}
+ {3761535600 -14400 1 EDT}
+ {3782095200 -18000 0 EST}
+ {3792985200 -14400 1 EDT}
+ {3813544800 -18000 0 EST}
+ {3824434800 -14400 1 EDT}
+ {3844994400 -18000 0 EST}
+ {3855884400 -14400 1 EDT}
+ {3876444000 -18000 0 EST}
+ {3887334000 -14400 1 EDT}
+ {3907893600 -18000 0 EST}
+ {3919388400 -14400 1 EDT}
+ {3939948000 -18000 0 EST}
+ {3950838000 -14400 1 EDT}
+ {3971397600 -18000 0 EST}
+ {3982287600 -14400 1 EDT}
+ {4002847200 -18000 0 EST}
+ {4013737200 -14400 1 EDT}
+ {4034296800 -18000 0 EST}
+ {4045186800 -14400 1 EDT}
+ {4065746400 -18000 0 EST}
+ {4076636400 -14400 1 EDT}
+ {4097196000 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Knox_IN b/library/tzdata/America/Knox_IN
new file mode 100644
index 0000000..00d21c0
--- /dev/null
+++ b/library/tzdata/America/Knox_IN
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Indiana/Knox)]} {
+ LoadTimeZoneFile America/Indiana/Knox
+}
+set TZData(:America/Knox_IN) $TZData(:America/Indiana/Knox)
diff --git a/library/tzdata/America/Kralendijk b/library/tzdata/America/Kralendijk
new file mode 100644
index 0000000..8b6db86
--- /dev/null
+++ b/library/tzdata/America/Kralendijk
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Curacao)]} {
+ LoadTimeZoneFile America/Curacao
+}
+set TZData(:America/Kralendijk) $TZData(:America/Curacao)
diff --git a/library/tzdata/America/La_Paz b/library/tzdata/America/La_Paz
new file mode 100644
index 0000000..38ffbb0
--- /dev/null
+++ b/library/tzdata/America/La_Paz
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/La_Paz) {
+ {-9223372036854775808 -16356 0 LMT}
+ {-2524505244 -16356 0 CMT}
+ {-1205954844 -12756 1 BOST}
+ {-1192307244 -14400 0 BOT}
+}
diff --git a/library/tzdata/America/Lima b/library/tzdata/America/Lima
new file mode 100644
index 0000000..c6e6ac1
--- /dev/null
+++ b/library/tzdata/America/Lima
@@ -0,0 +1,16 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Lima) {
+ {-9223372036854775808 -18492 0 LMT}
+ {-2524503108 -18516 0 LMT}
+ {-1938538284 -14400 0 PEST}
+ {-1002052800 -18000 0 PET}
+ {-986756400 -14400 1 PEST}
+ {-971035200 -18000 0 PET}
+ {-955306800 -14400 1 PEST}
+ {-939585600 -18000 0 PET}
+ {512712000 -18000 0 PET}
+ {544248000 -18000 0 PET}
+ {638942400 -18000 0 PET}
+ {765172800 -18000 0 PET}
+}
diff --git a/library/tzdata/America/Los_Angeles b/library/tzdata/America/Los_Angeles
new file mode 100644
index 0000000..da6ca99
--- /dev/null
+++ b/library/tzdata/America/Los_Angeles
@@ -0,0 +1,317 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Los_Angeles) {
+ {-9223372036854775808 -28378 0 LMT}
+ {-2717640000 -28800 0 PST}
+ {-1633269600 -25200 1 PDT}
+ {-1615129200 -28800 0 PST}
+ {-1601820000 -25200 1 PDT}
+ {-1583679600 -28800 0 PST}
+ {-880207200 -25200 1 PWT}
+ {-769395600 -25200 1 PPT}
+ {-765385200 -28800 0 PST}
+ {-757353600 -28800 0 PST}
+ {-687967200 -25200 1 PDT}
+ {-662655600 -28800 0 PST}
+ {-620834400 -25200 1 PDT}
+ {-608137200 -28800 0 PST}
+ {-589384800 -25200 1 PDT}
+ {-576082800 -28800 0 PST}
+ {-557935200 -25200 1 PDT}
+ {-544633200 -28800 0 PST}
+ {-526485600 -25200 1 PDT}
+ {-513183600 -28800 0 PST}
+ {-495036000 -25200 1 PDT}
+ {-481734000 -28800 0 PST}
+ {-463586400 -25200 1 PDT}
+ {-450284400 -28800 0 PST}
+ {-431532000 -25200 1 PDT}
+ {-418230000 -28800 0 PST}
+ {-400082400 -25200 1 PDT}
+ {-386780400 -28800 0 PST}
+ {-368632800 -25200 1 PDT}
+ {-355330800 -28800 0 PST}
+ {-337183200 -25200 1 PDT}
+ {-323881200 -28800 0 PST}
+ {-305733600 -25200 1 PDT}
+ {-292431600 -28800 0 PST}
+ {-273679200 -25200 1 PDT}
+ {-260982000 -28800 0 PST}
+ {-242229600 -25200 1 PDT}
+ {-226508400 -28800 0 PST}
+ {-210780000 -25200 1 PDT}
+ {-195058800 -28800 0 PST}
+ {-179330400 -25200 1 PDT}
+ {-163609200 -28800 0 PST}
+ {-147880800 -25200 1 PDT}
+ {-131554800 -28800 0 PST}
+ {-116431200 -25200 1 PDT}
+ {-100105200 -28800 0 PST}
+ {-94665600 -28800 0 PST}
+ {-84376800 -25200 1 PDT}
+ {-68655600 -28800 0 PST}
+ {-52927200 -25200 1 PDT}
+ {-37206000 -28800 0 PST}
+ {-21477600 -25200 1 PDT}
+ {-5756400 -28800 0 PST}
+ {9972000 -25200 1 PDT}
+ {25693200 -28800 0 PST}
+ {41421600 -25200 1 PDT}
+ {57747600 -28800 0 PST}
+ {73476000 -25200 1 PDT}
+ {89197200 -28800 0 PST}
+ {104925600 -25200 1 PDT}
+ {120646800 -28800 0 PST}
+ {126698400 -25200 1 PDT}
+ {152096400 -28800 0 PST}
+ {162381600 -25200 1 PDT}
+ {183546000 -28800 0 PST}
+ {199274400 -25200 1 PDT}
+ {215600400 -28800 0 PST}
+ {230724000 -25200 1 PDT}
+ {247050000 -28800 0 PST}
+ {262778400 -25200 1 PDT}
+ {278499600 -28800 0 PST}
+ {294228000 -25200 1 PDT}
+ {309949200 -28800 0 PST}
+ {325677600 -25200 1 PDT}
+ {341398800 -28800 0 PST}
+ {357127200 -25200 1 PDT}
+ {372848400 -28800 0 PST}
+ {388576800 -25200 1 PDT}
+ {404902800 -28800 0 PST}
+ {420026400 -25200 1 PDT}
+ {436352400 -28800 0 PST}
+ {452080800 -25200 1 PDT}
+ {467802000 -28800 0 PST}
+ {483530400 -25200 1 PDT}
+ {499251600 -28800 0 PST}
+ {514980000 -25200 1 PDT}
+ {530701200 -28800 0 PST}
+ {544615200 -25200 1 PDT}
+ {562150800 -28800 0 PST}
+ {576064800 -25200 1 PDT}
+ {594205200 -28800 0 PST}
+ {607514400 -25200 1 PDT}
+ {625654800 -28800 0 PST}
+ {638964000 -25200 1 PDT}
+ {657104400 -28800 0 PST}
+ {671018400 -25200 1 PDT}
+ {688554000 -28800 0 PST}
+ {702468000 -25200 1 PDT}
+ {720003600 -28800 0 PST}
+ {733917600 -25200 1 PDT}
+ {752058000 -28800 0 PST}
+ {765367200 -25200 1 PDT}
+ {783507600 -28800 0 PST}
+ {796816800 -25200 1 PDT}
+ {814957200 -28800 0 PST}
+ {828871200 -25200 1 PDT}
+ {846406800 -28800 0 PST}
+ {860320800 -25200 1 PDT}
+ {877856400 -28800 0 PST}
+ {891770400 -25200 1 PDT}
+ {909306000 -28800 0 PST}
+ {923220000 -25200 1 PDT}
+ {941360400 -28800 0 PST}
+ {954669600 -25200 1 PDT}
+ {972810000 -28800 0 PST}
+ {986119200 -25200 1 PDT}
+ {1004259600 -28800 0 PST}
+ {1018173600 -25200 1 PDT}
+ {1035709200 -28800 0 PST}
+ {1049623200 -25200 1 PDT}
+ {1067158800 -28800 0 PST}
+ {1081072800 -25200 1 PDT}
+ {1099213200 -28800 0 PST}
+ {1112522400 -25200 1 PDT}
+ {1130662800 -28800 0 PST}
+ {1143972000 -25200 1 PDT}
+ {1162112400 -28800 0 PST}
+ {1173607200 -25200 1 PDT}
+ {1194166800 -28800 0 PST}
+ {1205056800 -25200 1 PDT}
+ {1225616400 -28800 0 PST}
+ {1236506400 -25200 1 PDT}
+ {1257066000 -28800 0 PST}
+ {1268560800 -25200 1 PDT}
+ {1289120400 -28800 0 PST}
+ {1300010400 -25200 1 PDT}
+ {1320570000 -28800 0 PST}
+ {1331460000 -25200 1 PDT}
+ {1352019600 -28800 0 PST}
+ {1362909600 -25200 1 PDT}
+ {1383469200 -28800 0 PST}
+ {1394359200 -25200 1 PDT}
+ {1414918800 -28800 0 PST}
+ {1425808800 -25200 1 PDT}
+ {1446368400 -28800 0 PST}
+ {1457863200 -25200 1 PDT}
+ {1478422800 -28800 0 PST}
+ {1489312800 -25200 1 PDT}
+ {1509872400 -28800 0 PST}
+ {1520762400 -25200 1 PDT}
+ {1541322000 -28800 0 PST}
+ {1552212000 -25200 1 PDT}
+ {1572771600 -28800 0 PST}
+ {1583661600 -25200 1 PDT}
+ {1604221200 -28800 0 PST}
+ {1615716000 -25200 1 PDT}
+ {1636275600 -28800 0 PST}
+ {1647165600 -25200 1 PDT}
+ {1667725200 -28800 0 PST}
+ {1678615200 -25200 1 PDT}
+ {1699174800 -28800 0 PST}
+ {1710064800 -25200 1 PDT}
+ {1730624400 -28800 0 PST}
+ {1741514400 -25200 1 PDT}
+ {1762074000 -28800 0 PST}
+ {1772964000 -25200 1 PDT}
+ {1793523600 -28800 0 PST}
+ {1805018400 -25200 1 PDT}
+ {1825578000 -28800 0 PST}
+ {1836468000 -25200 1 PDT}
+ {1857027600 -28800 0 PST}
+ {1867917600 -25200 1 PDT}
+ {1888477200 -28800 0 PST}
+ {1899367200 -25200 1 PDT}
+ {1919926800 -28800 0 PST}
+ {1930816800 -25200 1 PDT}
+ {1951376400 -28800 0 PST}
+ {1962871200 -25200 1 PDT}
+ {1983430800 -28800 0 PST}
+ {1994320800 -25200 1 PDT}
+ {2014880400 -28800 0 PST}
+ {2025770400 -25200 1 PDT}
+ {2046330000 -28800 0 PST}
+ {2057220000 -25200 1 PDT}
+ {2077779600 -28800 0 PST}
+ {2088669600 -25200 1 PDT}
+ {2109229200 -28800 0 PST}
+ {2120119200 -25200 1 PDT}
+ {2140678800 -28800 0 PST}
+ {2152173600 -25200 1 PDT}
+ {2172733200 -28800 0 PST}
+ {2183623200 -25200 1 PDT}
+ {2204182800 -28800 0 PST}
+ {2215072800 -25200 1 PDT}
+ {2235632400 -28800 0 PST}
+ {2246522400 -25200 1 PDT}
+ {2267082000 -28800 0 PST}
+ {2277972000 -25200 1 PDT}
+ {2298531600 -28800 0 PST}
+ {2309421600 -25200 1 PDT}
+ {2329981200 -28800 0 PST}
+ {2341476000 -25200 1 PDT}
+ {2362035600 -28800 0 PST}
+ {2372925600 -25200 1 PDT}
+ {2393485200 -28800 0 PST}
+ {2404375200 -25200 1 PDT}
+ {2424934800 -28800 0 PST}
+ {2435824800 -25200 1 PDT}
+ {2456384400 -28800 0 PST}
+ {2467274400 -25200 1 PDT}
+ {2487834000 -28800 0 PST}
+ {2499328800 -25200 1 PDT}
+ {2519888400 -28800 0 PST}
+ {2530778400 -25200 1 PDT}
+ {2551338000 -28800 0 PST}
+ {2562228000 -25200 1 PDT}
+ {2582787600 -28800 0 PST}
+ {2593677600 -25200 1 PDT}
+ {2614237200 -28800 0 PST}
+ {2625127200 -25200 1 PDT}
+ {2645686800 -28800 0 PST}
+ {2656576800 -25200 1 PDT}
+ {2677136400 -28800 0 PST}
+ {2688631200 -25200 1 PDT}
+ {2709190800 -28800 0 PST}
+ {2720080800 -25200 1 PDT}
+ {2740640400 -28800 0 PST}
+ {2751530400 -25200 1 PDT}
+ {2772090000 -28800 0 PST}
+ {2782980000 -25200 1 PDT}
+ {2803539600 -28800 0 PST}
+ {2814429600 -25200 1 PDT}
+ {2834989200 -28800 0 PST}
+ {2846484000 -25200 1 PDT}
+ {2867043600 -28800 0 PST}
+ {2877933600 -25200 1 PDT}
+ {2898493200 -28800 0 PST}
+ {2909383200 -25200 1 PDT}
+ {2929942800 -28800 0 PST}
+ {2940832800 -25200 1 PDT}
+ {2961392400 -28800 0 PST}
+ {2972282400 -25200 1 PDT}
+ {2992842000 -28800 0 PST}
+ {3003732000 -25200 1 PDT}
+ {3024291600 -28800 0 PST}
+ {3035786400 -25200 1 PDT}
+ {3056346000 -28800 0 PST}
+ {3067236000 -25200 1 PDT}
+ {3087795600 -28800 0 PST}
+ {3098685600 -25200 1 PDT}
+ {3119245200 -28800 0 PST}
+ {3130135200 -25200 1 PDT}
+ {3150694800 -28800 0 PST}
+ {3161584800 -25200 1 PDT}
+ {3182144400 -28800 0 PST}
+ {3193034400 -25200 1 PDT}
+ {3213594000 -28800 0 PST}
+ {3225088800 -25200 1 PDT}
+ {3245648400 -28800 0 PST}
+ {3256538400 -25200 1 PDT}
+ {3277098000 -28800 0 PST}
+ {3287988000 -25200 1 PDT}
+ {3308547600 -28800 0 PST}
+ {3319437600 -25200 1 PDT}
+ {3339997200 -28800 0 PST}
+ {3350887200 -25200 1 PDT}
+ {3371446800 -28800 0 PST}
+ {3382941600 -25200 1 PDT}
+ {3403501200 -28800 0 PST}
+ {3414391200 -25200 1 PDT}
+ {3434950800 -28800 0 PST}
+ {3445840800 -25200 1 PDT}
+ {3466400400 -28800 0 PST}
+ {3477290400 -25200 1 PDT}
+ {3497850000 -28800 0 PST}
+ {3508740000 -25200 1 PDT}
+ {3529299600 -28800 0 PST}
+ {3540189600 -25200 1 PDT}
+ {3560749200 -28800 0 PST}
+ {3572244000 -25200 1 PDT}
+ {3592803600 -28800 0 PST}
+ {3603693600 -25200 1 PDT}
+ {3624253200 -28800 0 PST}
+ {3635143200 -25200 1 PDT}
+ {3655702800 -28800 0 PST}
+ {3666592800 -25200 1 PDT}
+ {3687152400 -28800 0 PST}
+ {3698042400 -25200 1 PDT}
+ {3718602000 -28800 0 PST}
+ {3730096800 -25200 1 PDT}
+ {3750656400 -28800 0 PST}
+ {3761546400 -25200 1 PDT}
+ {3782106000 -28800 0 PST}
+ {3792996000 -25200 1 PDT}
+ {3813555600 -28800 0 PST}
+ {3824445600 -25200 1 PDT}
+ {3845005200 -28800 0 PST}
+ {3855895200 -25200 1 PDT}
+ {3876454800 -28800 0 PST}
+ {3887344800 -25200 1 PDT}
+ {3907904400 -28800 0 PST}
+ {3919399200 -25200 1 PDT}
+ {3939958800 -28800 0 PST}
+ {3950848800 -25200 1 PDT}
+ {3971408400 -28800 0 PST}
+ {3982298400 -25200 1 PDT}
+ {4002858000 -28800 0 PST}
+ {4013748000 -25200 1 PDT}
+ {4034307600 -28800 0 PST}
+ {4045197600 -25200 1 PDT}
+ {4065757200 -28800 0 PST}
+ {4076647200 -25200 1 PDT}
+ {4097206800 -28800 0 PST}
+}
diff --git a/library/tzdata/America/Louisville b/library/tzdata/America/Louisville
new file mode 100644
index 0000000..c5a3e1c
--- /dev/null
+++ b/library/tzdata/America/Louisville
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Kentucky/Louisville)]} {
+ LoadTimeZoneFile America/Kentucky/Louisville
+}
+set TZData(:America/Louisville) $TZData(:America/Kentucky/Louisville)
diff --git a/library/tzdata/America/Lower_Princes b/library/tzdata/America/Lower_Princes
new file mode 100644
index 0000000..94c9197
--- /dev/null
+++ b/library/tzdata/America/Lower_Princes
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Curacao)]} {
+ LoadTimeZoneFile America/Curacao
+}
+set TZData(:America/Lower_Princes) $TZData(:America/Curacao)
diff --git a/library/tzdata/America/Maceio b/library/tzdata/America/Maceio
new file mode 100644
index 0000000..333b878
--- /dev/null
+++ b/library/tzdata/America/Maceio
@@ -0,0 +1,52 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Maceio) {
+ {-9223372036854775808 -8572 0 LMT}
+ {-1767217028 -10800 0 BRT}
+ {-1206957600 -7200 1 BRST}
+ {-1191362400 -10800 0 BRT}
+ {-1175374800 -7200 1 BRST}
+ {-1159826400 -10800 0 BRT}
+ {-633819600 -7200 1 BRST}
+ {-622069200 -10800 0 BRT}
+ {-602283600 -7200 1 BRST}
+ {-591832800 -10800 0 BRT}
+ {-570747600 -7200 1 BRST}
+ {-560210400 -10800 0 BRT}
+ {-539125200 -7200 1 BRST}
+ {-531352800 -10800 0 BRT}
+ {-191365200 -7200 1 BRST}
+ {-184197600 -10800 0 BRT}
+ {-155163600 -7200 1 BRST}
+ {-150069600 -10800 0 BRT}
+ {-128898000 -7200 1 BRST}
+ {-121125600 -10800 0 BRT}
+ {-99954000 -7200 1 BRST}
+ {-89589600 -10800 0 BRT}
+ {-68418000 -7200 1 BRST}
+ {-57967200 -10800 0 BRT}
+ {499748400 -7200 1 BRST}
+ {511236000 -10800 0 BRT}
+ {530593200 -7200 1 BRST}
+ {540266400 -10800 0 BRT}
+ {562129200 -7200 1 BRST}
+ {571197600 -10800 0 BRT}
+ {592974000 -7200 1 BRST}
+ {602042400 -10800 0 BRT}
+ {624423600 -7200 1 BRST}
+ {634701600 -10800 0 BRT}
+ {653536800 -10800 0 BRT}
+ {813553200 -10800 0 BRT}
+ {813726000 -7200 1 BRST}
+ {824004000 -10800 0 BRT}
+ {841802400 -10800 0 BRT}
+ {938660400 -10800 0 BRT}
+ {938919600 -7200 1 BRST}
+ {951616800 -10800 0 BRT}
+ {970974000 -7200 1 BRST}
+ {972180000 -10800 0 BRT}
+ {1000350000 -10800 0 BRT}
+ {1003028400 -7200 1 BRST}
+ {1013911200 -10800 0 BRT}
+ {1033437600 -10800 0 BRT}
+}
diff --git a/library/tzdata/America/Managua b/library/tzdata/America/Managua
new file mode 100644
index 0000000..f729b8a
--- /dev/null
+++ b/library/tzdata/America/Managua
@@ -0,0 +1,21 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Managua) {
+ {-9223372036854775808 -20708 0 LMT}
+ {-2524500892 -20712 0 MMT}
+ {-1121105688 -21600 0 CST}
+ {105084000 -18000 0 EST}
+ {161758800 -21600 0 CST}
+ {290584800 -18000 1 CDT}
+ {299134800 -21600 0 CST}
+ {322034400 -18000 1 CDT}
+ {330584400 -21600 0 CST}
+ {694260000 -18000 0 EST}
+ {717310800 -21600 0 CST}
+ {725868000 -18000 0 EST}
+ {852094800 -21600 0 CST}
+ {1113112800 -18000 1 CDT}
+ {1128229200 -21600 0 CST}
+ {1146384000 -18000 1 CDT}
+ {1159682400 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Manaus b/library/tzdata/America/Manaus
new file mode 100644
index 0000000..058e0f7
--- /dev/null
+++ b/library/tzdata/America/Manaus
@@ -0,0 +1,39 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Manaus) {
+ {-9223372036854775808 -14404 0 LMT}
+ {-1767211196 -14400 0 AMT}
+ {-1206954000 -10800 1 AMST}
+ {-1191358800 -14400 0 AMT}
+ {-1175371200 -10800 1 AMST}
+ {-1159822800 -14400 0 AMT}
+ {-633816000 -10800 1 AMST}
+ {-622065600 -14400 0 AMT}
+ {-602280000 -10800 1 AMST}
+ {-591829200 -14400 0 AMT}
+ {-570744000 -10800 1 AMST}
+ {-560206800 -14400 0 AMT}
+ {-539121600 -10800 1 AMST}
+ {-531349200 -14400 0 AMT}
+ {-191361600 -10800 1 AMST}
+ {-184194000 -14400 0 AMT}
+ {-155160000 -10800 1 AMST}
+ {-150066000 -14400 0 AMT}
+ {-128894400 -10800 1 AMST}
+ {-121122000 -14400 0 AMT}
+ {-99950400 -10800 1 AMST}
+ {-89586000 -14400 0 AMT}
+ {-68414400 -10800 1 AMST}
+ {-57963600 -14400 0 AMT}
+ {499752000 -10800 1 AMST}
+ {511239600 -14400 0 AMT}
+ {530596800 -10800 1 AMST}
+ {540270000 -14400 0 AMT}
+ {562132800 -10800 1 AMST}
+ {571201200 -14400 0 AMT}
+ {590036400 -14400 0 AMT}
+ {749188800 -14400 0 AMT}
+ {750830400 -10800 1 AMST}
+ {761713200 -14400 0 AMT}
+ {780202800 -14400 0 AMT}
+}
diff --git a/library/tzdata/America/Marigot b/library/tzdata/America/Marigot
new file mode 100644
index 0000000..9f3f8f6
--- /dev/null
+++ b/library/tzdata/America/Marigot
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Guadeloupe)]} {
+ LoadTimeZoneFile America/Guadeloupe
+}
+set TZData(:America/Marigot) $TZData(:America/Guadeloupe)
diff --git a/library/tzdata/America/Martinique b/library/tzdata/America/Martinique
new file mode 100644
index 0000000..1f1b491
--- /dev/null
+++ b/library/tzdata/America/Martinique
@@ -0,0 +1,9 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Martinique) {
+ {-9223372036854775808 -14660 0 LMT}
+ {-2524506940 -14660 0 FFMT}
+ {-1851537340 -14400 0 AST}
+ {323841600 -10800 1 ADT}
+ {338958000 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Matamoros b/library/tzdata/America/Matamoros
new file mode 100644
index 0000000..2b98652
--- /dev/null
+++ b/library/tzdata/America/Matamoros
@@ -0,0 +1,219 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Matamoros) {
+ {-9223372036854775808 -24000 0 LMT}
+ {-1514743200 -21600 0 CST}
+ {568015200 -21600 0 CST}
+ {576057600 -18000 1 CDT}
+ {594198000 -21600 0 CST}
+ {599637600 -21600 0 CST}
+ {828864000 -18000 1 CDT}
+ {846399600 -21600 0 CST}
+ {860313600 -18000 1 CDT}
+ {877849200 -21600 0 CST}
+ {891763200 -18000 1 CDT}
+ {909298800 -21600 0 CST}
+ {923212800 -18000 1 CDT}
+ {941353200 -21600 0 CST}
+ {954662400 -18000 1 CDT}
+ {972802800 -21600 0 CST}
+ {989136000 -18000 1 CDT}
+ {1001833200 -21600 0 CST}
+ {1018166400 -18000 1 CDT}
+ {1035702000 -21600 0 CST}
+ {1049616000 -18000 1 CDT}
+ {1067151600 -21600 0 CST}
+ {1081065600 -18000 1 CDT}
+ {1099206000 -21600 0 CST}
+ {1112515200 -18000 1 CDT}
+ {1130655600 -21600 0 CST}
+ {1143964800 -18000 1 CDT}
+ {1162105200 -21600 0 CST}
+ {1175414400 -18000 1 CDT}
+ {1193554800 -21600 0 CST}
+ {1207468800 -18000 1 CDT}
+ {1225004400 -21600 0 CST}
+ {1238918400 -18000 1 CDT}
+ {1256454000 -21600 0 CST}
+ {1262325600 -21600 0 CST}
+ {1268553600 -18000 1 CDT}
+ {1289113200 -21600 0 CST}
+ {1300003200 -18000 1 CDT}
+ {1320562800 -21600 0 CST}
+ {1331452800 -18000 1 CDT}
+ {1352012400 -21600 0 CST}
+ {1362902400 -18000 1 CDT}
+ {1383462000 -21600 0 CST}
+ {1394352000 -18000 1 CDT}
+ {1414911600 -21600 0 CST}
+ {1425801600 -18000 1 CDT}
+ {1446361200 -21600 0 CST}
+ {1457856000 -18000 1 CDT}
+ {1478415600 -21600 0 CST}
+ {1489305600 -18000 1 CDT}
+ {1509865200 -21600 0 CST}
+ {1520755200 -18000 1 CDT}
+ {1541314800 -21600 0 CST}
+ {1552204800 -18000 1 CDT}
+ {1572764400 -21600 0 CST}
+ {1583654400 -18000 1 CDT}
+ {1604214000 -21600 0 CST}
+ {1615708800 -18000 1 CDT}
+ {1636268400 -21600 0 CST}
+ {1647158400 -18000 1 CDT}
+ {1667718000 -21600 0 CST}
+ {1678608000 -18000 1 CDT}
+ {1699167600 -21600 0 CST}
+ {1710057600 -18000 1 CDT}
+ {1730617200 -21600 0 CST}
+ {1741507200 -18000 1 CDT}
+ {1762066800 -21600 0 CST}
+ {1772956800 -18000 1 CDT}
+ {1793516400 -21600 0 CST}
+ {1805011200 -18000 1 CDT}
+ {1825570800 -21600 0 CST}
+ {1836460800 -18000 1 CDT}
+ {1857020400 -21600 0 CST}
+ {1867910400 -18000 1 CDT}
+ {1888470000 -21600 0 CST}
+ {1899360000 -18000 1 CDT}
+ {1919919600 -21600 0 CST}
+ {1930809600 -18000 1 CDT}
+ {1951369200 -21600 0 CST}
+ {1962864000 -18000 1 CDT}
+ {1983423600 -21600 0 CST}
+ {1994313600 -18000 1 CDT}
+ {2014873200 -21600 0 CST}
+ {2025763200 -18000 1 CDT}
+ {2046322800 -21600 0 CST}
+ {2057212800 -18000 1 CDT}
+ {2077772400 -21600 0 CST}
+ {2088662400 -18000 1 CDT}
+ {2109222000 -21600 0 CST}
+ {2120112000 -18000 1 CDT}
+ {2140671600 -21600 0 CST}
+ {2152166400 -18000 1 CDT}
+ {2172726000 -21600 0 CST}
+ {2183616000 -18000 1 CDT}
+ {2204175600 -21600 0 CST}
+ {2215065600 -18000 1 CDT}
+ {2235625200 -21600 0 CST}
+ {2246515200 -18000 1 CDT}
+ {2267074800 -21600 0 CST}
+ {2277964800 -18000 1 CDT}
+ {2298524400 -21600 0 CST}
+ {2309414400 -18000 1 CDT}
+ {2329974000 -21600 0 CST}
+ {2341468800 -18000 1 CDT}
+ {2362028400 -21600 0 CST}
+ {2372918400 -18000 1 CDT}
+ {2393478000 -21600 0 CST}
+ {2404368000 -18000 1 CDT}
+ {2424927600 -21600 0 CST}
+ {2435817600 -18000 1 CDT}
+ {2456377200 -21600 0 CST}
+ {2467267200 -18000 1 CDT}
+ {2487826800 -21600 0 CST}
+ {2499321600 -18000 1 CDT}
+ {2519881200 -21600 0 CST}
+ {2530771200 -18000 1 CDT}
+ {2551330800 -21600 0 CST}
+ {2562220800 -18000 1 CDT}
+ {2582780400 -21600 0 CST}
+ {2593670400 -18000 1 CDT}
+ {2614230000 -21600 0 CST}
+ {2625120000 -18000 1 CDT}
+ {2645679600 -21600 0 CST}
+ {2656569600 -18000 1 CDT}
+ {2677129200 -21600 0 CST}
+ {2688624000 -18000 1 CDT}
+ {2709183600 -21600 0 CST}
+ {2720073600 -18000 1 CDT}
+ {2740633200 -21600 0 CST}
+ {2751523200 -18000 1 CDT}
+ {2772082800 -21600 0 CST}
+ {2782972800 -18000 1 CDT}
+ {2803532400 -21600 0 CST}
+ {2814422400 -18000 1 CDT}
+ {2834982000 -21600 0 CST}
+ {2846476800 -18000 1 CDT}
+ {2867036400 -21600 0 CST}
+ {2877926400 -18000 1 CDT}
+ {2898486000 -21600 0 CST}
+ {2909376000 -18000 1 CDT}
+ {2929935600 -21600 0 CST}
+ {2940825600 -18000 1 CDT}
+ {2961385200 -21600 0 CST}
+ {2972275200 -18000 1 CDT}
+ {2992834800 -21600 0 CST}
+ {3003724800 -18000 1 CDT}
+ {3024284400 -21600 0 CST}
+ {3035779200 -18000 1 CDT}
+ {3056338800 -21600 0 CST}
+ {3067228800 -18000 1 CDT}
+ {3087788400 -21600 0 CST}
+ {3098678400 -18000 1 CDT}
+ {3119238000 -21600 0 CST}
+ {3130128000 -18000 1 CDT}
+ {3150687600 -21600 0 CST}
+ {3161577600 -18000 1 CDT}
+ {3182137200 -21600 0 CST}
+ {3193027200 -18000 1 CDT}
+ {3213586800 -21600 0 CST}
+ {3225081600 -18000 1 CDT}
+ {3245641200 -21600 0 CST}
+ {3256531200 -18000 1 CDT}
+ {3277090800 -21600 0 CST}
+ {3287980800 -18000 1 CDT}
+ {3308540400 -21600 0 CST}
+ {3319430400 -18000 1 CDT}
+ {3339990000 -21600 0 CST}
+ {3350880000 -18000 1 CDT}
+ {3371439600 -21600 0 CST}
+ {3382934400 -18000 1 CDT}
+ {3403494000 -21600 0 CST}
+ {3414384000 -18000 1 CDT}
+ {3434943600 -21600 0 CST}
+ {3445833600 -18000 1 CDT}
+ {3466393200 -21600 0 CST}
+ {3477283200 -18000 1 CDT}
+ {3497842800 -21600 0 CST}
+ {3508732800 -18000 1 CDT}
+ {3529292400 -21600 0 CST}
+ {3540182400 -18000 1 CDT}
+ {3560742000 -21600 0 CST}
+ {3572236800 -18000 1 CDT}
+ {3592796400 -21600 0 CST}
+ {3603686400 -18000 1 CDT}
+ {3624246000 -21600 0 CST}
+ {3635136000 -18000 1 CDT}
+ {3655695600 -21600 0 CST}
+ {3666585600 -18000 1 CDT}
+ {3687145200 -21600 0 CST}
+ {3698035200 -18000 1 CDT}
+ {3718594800 -21600 0 CST}
+ {3730089600 -18000 1 CDT}
+ {3750649200 -21600 0 CST}
+ {3761539200 -18000 1 CDT}
+ {3782098800 -21600 0 CST}
+ {3792988800 -18000 1 CDT}
+ {3813548400 -21600 0 CST}
+ {3824438400 -18000 1 CDT}
+ {3844998000 -21600 0 CST}
+ {3855888000 -18000 1 CDT}
+ {3876447600 -21600 0 CST}
+ {3887337600 -18000 1 CDT}
+ {3907897200 -21600 0 CST}
+ {3919392000 -18000 1 CDT}
+ {3939951600 -21600 0 CST}
+ {3950841600 -18000 1 CDT}
+ {3971401200 -21600 0 CST}
+ {3982291200 -18000 1 CDT}
+ {4002850800 -21600 0 CST}
+ {4013740800 -18000 1 CDT}
+ {4034300400 -21600 0 CST}
+ {4045190400 -18000 1 CDT}
+ {4065750000 -21600 0 CST}
+ {4076640000 -18000 1 CDT}
+ {4097199600 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Mazatlan b/library/tzdata/America/Mazatlan
new file mode 100644
index 0000000..e56d7d0
--- /dev/null
+++ b/library/tzdata/America/Mazatlan
@@ -0,0 +1,222 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Mazatlan) {
+ {-9223372036854775808 -25540 0 LMT}
+ {-1514739600 -25200 0 MST}
+ {-1343066400 -21600 0 CST}
+ {-1234807200 -25200 0 MST}
+ {-1220292000 -21600 0 CST}
+ {-1207159200 -25200 0 MST}
+ {-1191344400 -21600 0 CST}
+ {-873828000 -25200 0 MST}
+ {-661539600 -28800 0 PST}
+ {28800 -25200 0 MST}
+ {828867600 -21600 1 MDT}
+ {846403200 -25200 0 MST}
+ {860317200 -21600 1 MDT}
+ {877852800 -25200 0 MST}
+ {891766800 -21600 1 MDT}
+ {909302400 -25200 0 MST}
+ {923216400 -21600 1 MDT}
+ {941356800 -25200 0 MST}
+ {954666000 -21600 1 MDT}
+ {972806400 -25200 0 MST}
+ {989139600 -21600 1 MDT}
+ {1001836800 -25200 0 MST}
+ {1018170000 -21600 1 MDT}
+ {1035705600 -25200 0 MST}
+ {1049619600 -21600 1 MDT}
+ {1067155200 -25200 0 MST}
+ {1081069200 -21600 1 MDT}
+ {1099209600 -25200 0 MST}
+ {1112518800 -21600 1 MDT}
+ {1130659200 -25200 0 MST}
+ {1143968400 -21600 1 MDT}
+ {1162108800 -25200 0 MST}
+ {1175418000 -21600 1 MDT}
+ {1193558400 -25200 0 MST}
+ {1207472400 -21600 1 MDT}
+ {1225008000 -25200 0 MST}
+ {1238922000 -21600 1 MDT}
+ {1256457600 -25200 0 MST}
+ {1270371600 -21600 1 MDT}
+ {1288512000 -25200 0 MST}
+ {1301821200 -21600 1 MDT}
+ {1319961600 -25200 0 MST}
+ {1333270800 -21600 1 MDT}
+ {1351411200 -25200 0 MST}
+ {1365325200 -21600 1 MDT}
+ {1382860800 -25200 0 MST}
+ {1396774800 -21600 1 MDT}
+ {1414310400 -25200 0 MST}
+ {1428224400 -21600 1 MDT}
+ {1445760000 -25200 0 MST}
+ {1459674000 -21600 1 MDT}
+ {1477814400 -25200 0 MST}
+ {1491123600 -21600 1 MDT}
+ {1509264000 -25200 0 MST}
+ {1522573200 -21600 1 MDT}
+ {1540713600 -25200 0 MST}
+ {1554627600 -21600 1 MDT}
+ {1572163200 -25200 0 MST}
+ {1586077200 -21600 1 MDT}
+ {1603612800 -25200 0 MST}
+ {1617526800 -21600 1 MDT}
+ {1635667200 -25200 0 MST}
+ {1648976400 -21600 1 MDT}
+ {1667116800 -25200 0 MST}
+ {1680426000 -21600 1 MDT}
+ {1698566400 -25200 0 MST}
+ {1712480400 -21600 1 MDT}
+ {1730016000 -25200 0 MST}
+ {1743930000 -21600 1 MDT}
+ {1761465600 -25200 0 MST}
+ {1775379600 -21600 1 MDT}
+ {1792915200 -25200 0 MST}
+ {1806829200 -21600 1 MDT}
+ {1824969600 -25200 0 MST}
+ {1838278800 -21600 1 MDT}
+ {1856419200 -25200 0 MST}
+ {1869728400 -21600 1 MDT}
+ {1887868800 -25200 0 MST}
+ {1901782800 -21600 1 MDT}
+ {1919318400 -25200 0 MST}
+ {1933232400 -21600 1 MDT}
+ {1950768000 -25200 0 MST}
+ {1964682000 -21600 1 MDT}
+ {1982822400 -25200 0 MST}
+ {1996131600 -21600 1 MDT}
+ {2014272000 -25200 0 MST}
+ {2027581200 -21600 1 MDT}
+ {2045721600 -25200 0 MST}
+ {2059030800 -21600 1 MDT}
+ {2077171200 -25200 0 MST}
+ {2091085200 -21600 1 MDT}
+ {2108620800 -25200 0 MST}
+ {2122534800 -21600 1 MDT}
+ {2140070400 -25200 0 MST}
+ {2153984400 -21600 1 MDT}
+ {2172124800 -25200 0 MST}
+ {2185434000 -21600 1 MDT}
+ {2203574400 -25200 0 MST}
+ {2216883600 -21600 1 MDT}
+ {2235024000 -25200 0 MST}
+ {2248938000 -21600 1 MDT}
+ {2266473600 -25200 0 MST}
+ {2280387600 -21600 1 MDT}
+ {2297923200 -25200 0 MST}
+ {2311837200 -21600 1 MDT}
+ {2329372800 -25200 0 MST}
+ {2343286800 -21600 1 MDT}
+ {2361427200 -25200 0 MST}
+ {2374736400 -21600 1 MDT}
+ {2392876800 -25200 0 MST}
+ {2406186000 -21600 1 MDT}
+ {2424326400 -25200 0 MST}
+ {2438240400 -21600 1 MDT}
+ {2455776000 -25200 0 MST}
+ {2469690000 -21600 1 MDT}
+ {2487225600 -25200 0 MST}
+ {2501139600 -21600 1 MDT}
+ {2519280000 -25200 0 MST}
+ {2532589200 -21600 1 MDT}
+ {2550729600 -25200 0 MST}
+ {2564038800 -21600 1 MDT}
+ {2582179200 -25200 0 MST}
+ {2596093200 -21600 1 MDT}
+ {2613628800 -25200 0 MST}
+ {2627542800 -21600 1 MDT}
+ {2645078400 -25200 0 MST}
+ {2658992400 -21600 1 MDT}
+ {2676528000 -25200 0 MST}
+ {2690442000 -21600 1 MDT}
+ {2708582400 -25200 0 MST}
+ {2721891600 -21600 1 MDT}
+ {2740032000 -25200 0 MST}
+ {2753341200 -21600 1 MDT}
+ {2771481600 -25200 0 MST}
+ {2785395600 -21600 1 MDT}
+ {2802931200 -25200 0 MST}
+ {2816845200 -21600 1 MDT}
+ {2834380800 -25200 0 MST}
+ {2848294800 -21600 1 MDT}
+ {2866435200 -25200 0 MST}
+ {2879744400 -21600 1 MDT}
+ {2897884800 -25200 0 MST}
+ {2911194000 -21600 1 MDT}
+ {2929334400 -25200 0 MST}
+ {2942643600 -21600 1 MDT}
+ {2960784000 -25200 0 MST}
+ {2974698000 -21600 1 MDT}
+ {2992233600 -25200 0 MST}
+ {3006147600 -21600 1 MDT}
+ {3023683200 -25200 0 MST}
+ {3037597200 -21600 1 MDT}
+ {3055737600 -25200 0 MST}
+ {3069046800 -21600 1 MDT}
+ {3087187200 -25200 0 MST}
+ {3100496400 -21600 1 MDT}
+ {3118636800 -25200 0 MST}
+ {3132550800 -21600 1 MDT}
+ {3150086400 -25200 0 MST}
+ {3164000400 -21600 1 MDT}
+ {3181536000 -25200 0 MST}
+ {3195450000 -21600 1 MDT}
+ {3212985600 -25200 0 MST}
+ {3226899600 -21600 1 MDT}
+ {3245040000 -25200 0 MST}
+ {3258349200 -21600 1 MDT}
+ {3276489600 -25200 0 MST}
+ {3289798800 -21600 1 MDT}
+ {3307939200 -25200 0 MST}
+ {3321853200 -21600 1 MDT}
+ {3339388800 -25200 0 MST}
+ {3353302800 -21600 1 MDT}
+ {3370838400 -25200 0 MST}
+ {3384752400 -21600 1 MDT}
+ {3402892800 -25200 0 MST}
+ {3416202000 -21600 1 MDT}
+ {3434342400 -25200 0 MST}
+ {3447651600 -21600 1 MDT}
+ {3465792000 -25200 0 MST}
+ {3479706000 -21600 1 MDT}
+ {3497241600 -25200 0 MST}
+ {3511155600 -21600 1 MDT}
+ {3528691200 -25200 0 MST}
+ {3542605200 -21600 1 MDT}
+ {3560140800 -25200 0 MST}
+ {3574054800 -21600 1 MDT}
+ {3592195200 -25200 0 MST}
+ {3605504400 -21600 1 MDT}
+ {3623644800 -25200 0 MST}
+ {3636954000 -21600 1 MDT}
+ {3655094400 -25200 0 MST}
+ {3669008400 -21600 1 MDT}
+ {3686544000 -25200 0 MST}
+ {3700458000 -21600 1 MDT}
+ {3717993600 -25200 0 MST}
+ {3731907600 -21600 1 MDT}
+ {3750048000 -25200 0 MST}
+ {3763357200 -21600 1 MDT}
+ {3781497600 -25200 0 MST}
+ {3794806800 -21600 1 MDT}
+ {3812947200 -25200 0 MST}
+ {3826256400 -21600 1 MDT}
+ {3844396800 -25200 0 MST}
+ {3858310800 -21600 1 MDT}
+ {3875846400 -25200 0 MST}
+ {3889760400 -21600 1 MDT}
+ {3907296000 -25200 0 MST}
+ {3921210000 -21600 1 MDT}
+ {3939350400 -25200 0 MST}
+ {3952659600 -21600 1 MDT}
+ {3970800000 -25200 0 MST}
+ {3984109200 -21600 1 MDT}
+ {4002249600 -25200 0 MST}
+ {4016163600 -21600 1 MDT}
+ {4033699200 -25200 0 MST}
+ {4047613200 -21600 1 MDT}
+ {4065148800 -25200 0 MST}
+ {4079062800 -21600 1 MDT}
+ {4096598400 -25200 0 MST}
+}
diff --git a/library/tzdata/America/Mendoza b/library/tzdata/America/Mendoza
new file mode 100644
index 0000000..511d83e
--- /dev/null
+++ b/library/tzdata/America/Mendoza
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Argentina/Mendoza)]} {
+ LoadTimeZoneFile America/Argentina/Mendoza
+}
+set TZData(:America/Mendoza) $TZData(:America/Argentina/Mendoza)
diff --git a/library/tzdata/America/Menominee b/library/tzdata/America/Menominee
new file mode 100644
index 0000000..382aeda
--- /dev/null
+++ b/library/tzdata/America/Menominee
@@ -0,0 +1,274 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Menominee) {
+ {-9223372036854775808 -21027 0 LMT}
+ {-2659759773 -21600 0 CST}
+ {-1633276800 -18000 1 CDT}
+ {-1615136400 -21600 0 CST}
+ {-1601827200 -18000 1 CDT}
+ {-1583686800 -21600 0 CST}
+ {-880214400 -18000 1 CWT}
+ {-769395600 -18000 1 CPT}
+ {-765392400 -21600 0 CST}
+ {-757360800 -21600 0 CST}
+ {-747244800 -18000 1 CDT}
+ {-733942800 -21600 0 CST}
+ {-116438400 -18000 1 CDT}
+ {-100112400 -21600 0 CST}
+ {-21484800 -18000 0 EST}
+ {104914800 -21600 0 CST}
+ {104918400 -18000 1 CDT}
+ {120639600 -21600 0 CST}
+ {126691200 -18000 1 CDT}
+ {152089200 -21600 0 CST}
+ {162374400 -18000 1 CDT}
+ {183538800 -21600 0 CST}
+ {199267200 -18000 1 CDT}
+ {215593200 -21600 0 CST}
+ {230716800 -18000 1 CDT}
+ {247042800 -21600 0 CST}
+ {262771200 -18000 1 CDT}
+ {278492400 -21600 0 CST}
+ {294220800 -18000 1 CDT}
+ {309942000 -21600 0 CST}
+ {325670400 -18000 1 CDT}
+ {341391600 -21600 0 CST}
+ {357120000 -18000 1 CDT}
+ {372841200 -21600 0 CST}
+ {388569600 -18000 1 CDT}
+ {404895600 -21600 0 CST}
+ {420019200 -18000 1 CDT}
+ {436345200 -21600 0 CST}
+ {452073600 -18000 1 CDT}
+ {467794800 -21600 0 CST}
+ {483523200 -18000 1 CDT}
+ {499244400 -21600 0 CST}
+ {514972800 -18000 1 CDT}
+ {530694000 -21600 0 CST}
+ {544608000 -18000 1 CDT}
+ {562143600 -21600 0 CST}
+ {576057600 -18000 1 CDT}
+ {594198000 -21600 0 CST}
+ {607507200 -18000 1 CDT}
+ {625647600 -21600 0 CST}
+ {638956800 -18000 1 CDT}
+ {657097200 -21600 0 CST}
+ {671011200 -18000 1 CDT}
+ {688546800 -21600 0 CST}
+ {702460800 -18000 1 CDT}
+ {719996400 -21600 0 CST}
+ {733910400 -18000 1 CDT}
+ {752050800 -21600 0 CST}
+ {765360000 -18000 1 CDT}
+ {783500400 -21600 0 CST}
+ {796809600 -18000 1 CDT}
+ {814950000 -21600 0 CST}
+ {828864000 -18000 1 CDT}
+ {846399600 -21600 0 CST}
+ {860313600 -18000 1 CDT}
+ {877849200 -21600 0 CST}
+ {891763200 -18000 1 CDT}
+ {909298800 -21600 0 CST}
+ {923212800 -18000 1 CDT}
+ {941353200 -21600 0 CST}
+ {954662400 -18000 1 CDT}
+ {972802800 -21600 0 CST}
+ {986112000 -18000 1 CDT}
+ {1004252400 -21600 0 CST}
+ {1018166400 -18000 1 CDT}
+ {1035702000 -21600 0 CST}
+ {1049616000 -18000 1 CDT}
+ {1067151600 -21600 0 CST}
+ {1081065600 -18000 1 CDT}
+ {1099206000 -21600 0 CST}
+ {1112515200 -18000 1 CDT}
+ {1130655600 -21600 0 CST}
+ {1143964800 -18000 1 CDT}
+ {1162105200 -21600 0 CST}
+ {1173600000 -18000 1 CDT}
+ {1194159600 -21600 0 CST}
+ {1205049600 -18000 1 CDT}
+ {1225609200 -21600 0 CST}
+ {1236499200 -18000 1 CDT}
+ {1257058800 -21600 0 CST}
+ {1268553600 -18000 1 CDT}
+ {1289113200 -21600 0 CST}
+ {1300003200 -18000 1 CDT}
+ {1320562800 -21600 0 CST}
+ {1331452800 -18000 1 CDT}
+ {1352012400 -21600 0 CST}
+ {1362902400 -18000 1 CDT}
+ {1383462000 -21600 0 CST}
+ {1394352000 -18000 1 CDT}
+ {1414911600 -21600 0 CST}
+ {1425801600 -18000 1 CDT}
+ {1446361200 -21600 0 CST}
+ {1457856000 -18000 1 CDT}
+ {1478415600 -21600 0 CST}
+ {1489305600 -18000 1 CDT}
+ {1509865200 -21600 0 CST}
+ {1520755200 -18000 1 CDT}
+ {1541314800 -21600 0 CST}
+ {1552204800 -18000 1 CDT}
+ {1572764400 -21600 0 CST}
+ {1583654400 -18000 1 CDT}
+ {1604214000 -21600 0 CST}
+ {1615708800 -18000 1 CDT}
+ {1636268400 -21600 0 CST}
+ {1647158400 -18000 1 CDT}
+ {1667718000 -21600 0 CST}
+ {1678608000 -18000 1 CDT}
+ {1699167600 -21600 0 CST}
+ {1710057600 -18000 1 CDT}
+ {1730617200 -21600 0 CST}
+ {1741507200 -18000 1 CDT}
+ {1762066800 -21600 0 CST}
+ {1772956800 -18000 1 CDT}
+ {1793516400 -21600 0 CST}
+ {1805011200 -18000 1 CDT}
+ {1825570800 -21600 0 CST}
+ {1836460800 -18000 1 CDT}
+ {1857020400 -21600 0 CST}
+ {1867910400 -18000 1 CDT}
+ {1888470000 -21600 0 CST}
+ {1899360000 -18000 1 CDT}
+ {1919919600 -21600 0 CST}
+ {1930809600 -18000 1 CDT}
+ {1951369200 -21600 0 CST}
+ {1962864000 -18000 1 CDT}
+ {1983423600 -21600 0 CST}
+ {1994313600 -18000 1 CDT}
+ {2014873200 -21600 0 CST}
+ {2025763200 -18000 1 CDT}
+ {2046322800 -21600 0 CST}
+ {2057212800 -18000 1 CDT}
+ {2077772400 -21600 0 CST}
+ {2088662400 -18000 1 CDT}
+ {2109222000 -21600 0 CST}
+ {2120112000 -18000 1 CDT}
+ {2140671600 -21600 0 CST}
+ {2152166400 -18000 1 CDT}
+ {2172726000 -21600 0 CST}
+ {2183616000 -18000 1 CDT}
+ {2204175600 -21600 0 CST}
+ {2215065600 -18000 1 CDT}
+ {2235625200 -21600 0 CST}
+ {2246515200 -18000 1 CDT}
+ {2267074800 -21600 0 CST}
+ {2277964800 -18000 1 CDT}
+ {2298524400 -21600 0 CST}
+ {2309414400 -18000 1 CDT}
+ {2329974000 -21600 0 CST}
+ {2341468800 -18000 1 CDT}
+ {2362028400 -21600 0 CST}
+ {2372918400 -18000 1 CDT}
+ {2393478000 -21600 0 CST}
+ {2404368000 -18000 1 CDT}
+ {2424927600 -21600 0 CST}
+ {2435817600 -18000 1 CDT}
+ {2456377200 -21600 0 CST}
+ {2467267200 -18000 1 CDT}
+ {2487826800 -21600 0 CST}
+ {2499321600 -18000 1 CDT}
+ {2519881200 -21600 0 CST}
+ {2530771200 -18000 1 CDT}
+ {2551330800 -21600 0 CST}
+ {2562220800 -18000 1 CDT}
+ {2582780400 -21600 0 CST}
+ {2593670400 -18000 1 CDT}
+ {2614230000 -21600 0 CST}
+ {2625120000 -18000 1 CDT}
+ {2645679600 -21600 0 CST}
+ {2656569600 -18000 1 CDT}
+ {2677129200 -21600 0 CST}
+ {2688624000 -18000 1 CDT}
+ {2709183600 -21600 0 CST}
+ {2720073600 -18000 1 CDT}
+ {2740633200 -21600 0 CST}
+ {2751523200 -18000 1 CDT}
+ {2772082800 -21600 0 CST}
+ {2782972800 -18000 1 CDT}
+ {2803532400 -21600 0 CST}
+ {2814422400 -18000 1 CDT}
+ {2834982000 -21600 0 CST}
+ {2846476800 -18000 1 CDT}
+ {2867036400 -21600 0 CST}
+ {2877926400 -18000 1 CDT}
+ {2898486000 -21600 0 CST}
+ {2909376000 -18000 1 CDT}
+ {2929935600 -21600 0 CST}
+ {2940825600 -18000 1 CDT}
+ {2961385200 -21600 0 CST}
+ {2972275200 -18000 1 CDT}
+ {2992834800 -21600 0 CST}
+ {3003724800 -18000 1 CDT}
+ {3024284400 -21600 0 CST}
+ {3035779200 -18000 1 CDT}
+ {3056338800 -21600 0 CST}
+ {3067228800 -18000 1 CDT}
+ {3087788400 -21600 0 CST}
+ {3098678400 -18000 1 CDT}
+ {3119238000 -21600 0 CST}
+ {3130128000 -18000 1 CDT}
+ {3150687600 -21600 0 CST}
+ {3161577600 -18000 1 CDT}
+ {3182137200 -21600 0 CST}
+ {3193027200 -18000 1 CDT}
+ {3213586800 -21600 0 CST}
+ {3225081600 -18000 1 CDT}
+ {3245641200 -21600 0 CST}
+ {3256531200 -18000 1 CDT}
+ {3277090800 -21600 0 CST}
+ {3287980800 -18000 1 CDT}
+ {3308540400 -21600 0 CST}
+ {3319430400 -18000 1 CDT}
+ {3339990000 -21600 0 CST}
+ {3350880000 -18000 1 CDT}
+ {3371439600 -21600 0 CST}
+ {3382934400 -18000 1 CDT}
+ {3403494000 -21600 0 CST}
+ {3414384000 -18000 1 CDT}
+ {3434943600 -21600 0 CST}
+ {3445833600 -18000 1 CDT}
+ {3466393200 -21600 0 CST}
+ {3477283200 -18000 1 CDT}
+ {3497842800 -21600 0 CST}
+ {3508732800 -18000 1 CDT}
+ {3529292400 -21600 0 CST}
+ {3540182400 -18000 1 CDT}
+ {3560742000 -21600 0 CST}
+ {3572236800 -18000 1 CDT}
+ {3592796400 -21600 0 CST}
+ {3603686400 -18000 1 CDT}
+ {3624246000 -21600 0 CST}
+ {3635136000 -18000 1 CDT}
+ {3655695600 -21600 0 CST}
+ {3666585600 -18000 1 CDT}
+ {3687145200 -21600 0 CST}
+ {3698035200 -18000 1 CDT}
+ {3718594800 -21600 0 CST}
+ {3730089600 -18000 1 CDT}
+ {3750649200 -21600 0 CST}
+ {3761539200 -18000 1 CDT}
+ {3782098800 -21600 0 CST}
+ {3792988800 -18000 1 CDT}
+ {3813548400 -21600 0 CST}
+ {3824438400 -18000 1 CDT}
+ {3844998000 -21600 0 CST}
+ {3855888000 -18000 1 CDT}
+ {3876447600 -21600 0 CST}
+ {3887337600 -18000 1 CDT}
+ {3907897200 -21600 0 CST}
+ {3919392000 -18000 1 CDT}
+ {3939951600 -21600 0 CST}
+ {3950841600 -18000 1 CDT}
+ {3971401200 -21600 0 CST}
+ {3982291200 -18000 1 CDT}
+ {4002850800 -21600 0 CST}
+ {4013740800 -18000 1 CDT}
+ {4034300400 -21600 0 CST}
+ {4045190400 -18000 1 CDT}
+ {4065750000 -21600 0 CST}
+ {4076640000 -18000 1 CDT}
+ {4097199600 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Merida b/library/tzdata/America/Merida
new file mode 100644
index 0000000..ebf5927
--- /dev/null
+++ b/library/tzdata/America/Merida
@@ -0,0 +1,216 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Merida) {
+ {-9223372036854775808 -21508 0 LMT}
+ {-1514743200 -21600 0 CST}
+ {377935200 -18000 0 EST}
+ {407653200 -21600 0 CST}
+ {828864000 -18000 1 CDT}
+ {846399600 -21600 0 CST}
+ {860313600 -18000 1 CDT}
+ {877849200 -21600 0 CST}
+ {891763200 -18000 1 CDT}
+ {909298800 -21600 0 CST}
+ {923212800 -18000 1 CDT}
+ {941353200 -21600 0 CST}
+ {954662400 -18000 1 CDT}
+ {972802800 -21600 0 CST}
+ {989136000 -18000 1 CDT}
+ {1001833200 -21600 0 CST}
+ {1018166400 -18000 1 CDT}
+ {1035702000 -21600 0 CST}
+ {1049616000 -18000 1 CDT}
+ {1067151600 -21600 0 CST}
+ {1081065600 -18000 1 CDT}
+ {1099206000 -21600 0 CST}
+ {1112515200 -18000 1 CDT}
+ {1130655600 -21600 0 CST}
+ {1143964800 -18000 1 CDT}
+ {1162105200 -21600 0 CST}
+ {1175414400 -18000 1 CDT}
+ {1193554800 -21600 0 CST}
+ {1207468800 -18000 1 CDT}
+ {1225004400 -21600 0 CST}
+ {1238918400 -18000 1 CDT}
+ {1256454000 -21600 0 CST}
+ {1270368000 -18000 1 CDT}
+ {1288508400 -21600 0 CST}
+ {1301817600 -18000 1 CDT}
+ {1319958000 -21600 0 CST}
+ {1333267200 -18000 1 CDT}
+ {1351407600 -21600 0 CST}
+ {1365321600 -18000 1 CDT}
+ {1382857200 -21600 0 CST}
+ {1396771200 -18000 1 CDT}
+ {1414306800 -21600 0 CST}
+ {1428220800 -18000 1 CDT}
+ {1445756400 -21600 0 CST}
+ {1459670400 -18000 1 CDT}
+ {1477810800 -21600 0 CST}
+ {1491120000 -18000 1 CDT}
+ {1509260400 -21600 0 CST}
+ {1522569600 -18000 1 CDT}
+ {1540710000 -21600 0 CST}
+ {1554624000 -18000 1 CDT}
+ {1572159600 -21600 0 CST}
+ {1586073600 -18000 1 CDT}
+ {1603609200 -21600 0 CST}
+ {1617523200 -18000 1 CDT}
+ {1635663600 -21600 0 CST}
+ {1648972800 -18000 1 CDT}
+ {1667113200 -21600 0 CST}
+ {1680422400 -18000 1 CDT}
+ {1698562800 -21600 0 CST}
+ {1712476800 -18000 1 CDT}
+ {1730012400 -21600 0 CST}
+ {1743926400 -18000 1 CDT}
+ {1761462000 -21600 0 CST}
+ {1775376000 -18000 1 CDT}
+ {1792911600 -21600 0 CST}
+ {1806825600 -18000 1 CDT}
+ {1824966000 -21600 0 CST}
+ {1838275200 -18000 1 CDT}
+ {1856415600 -21600 0 CST}
+ {1869724800 -18000 1 CDT}
+ {1887865200 -21600 0 CST}
+ {1901779200 -18000 1 CDT}
+ {1919314800 -21600 0 CST}
+ {1933228800 -18000 1 CDT}
+ {1950764400 -21600 0 CST}
+ {1964678400 -18000 1 CDT}
+ {1982818800 -21600 0 CST}
+ {1996128000 -18000 1 CDT}
+ {2014268400 -21600 0 CST}
+ {2027577600 -18000 1 CDT}
+ {2045718000 -21600 0 CST}
+ {2059027200 -18000 1 CDT}
+ {2077167600 -21600 0 CST}
+ {2091081600 -18000 1 CDT}
+ {2108617200 -21600 0 CST}
+ {2122531200 -18000 1 CDT}
+ {2140066800 -21600 0 CST}
+ {2153980800 -18000 1 CDT}
+ {2172121200 -21600 0 CST}
+ {2185430400 -18000 1 CDT}
+ {2203570800 -21600 0 CST}
+ {2216880000 -18000 1 CDT}
+ {2235020400 -21600 0 CST}
+ {2248934400 -18000 1 CDT}
+ {2266470000 -21600 0 CST}
+ {2280384000 -18000 1 CDT}
+ {2297919600 -21600 0 CST}
+ {2311833600 -18000 1 CDT}
+ {2329369200 -21600 0 CST}
+ {2343283200 -18000 1 CDT}
+ {2361423600 -21600 0 CST}
+ {2374732800 -18000 1 CDT}
+ {2392873200 -21600 0 CST}
+ {2406182400 -18000 1 CDT}
+ {2424322800 -21600 0 CST}
+ {2438236800 -18000 1 CDT}
+ {2455772400 -21600 0 CST}
+ {2469686400 -18000 1 CDT}
+ {2487222000 -21600 0 CST}
+ {2501136000 -18000 1 CDT}
+ {2519276400 -21600 0 CST}
+ {2532585600 -18000 1 CDT}
+ {2550726000 -21600 0 CST}
+ {2564035200 -18000 1 CDT}
+ {2582175600 -21600 0 CST}
+ {2596089600 -18000 1 CDT}
+ {2613625200 -21600 0 CST}
+ {2627539200 -18000 1 CDT}
+ {2645074800 -21600 0 CST}
+ {2658988800 -18000 1 CDT}
+ {2676524400 -21600 0 CST}
+ {2690438400 -18000 1 CDT}
+ {2708578800 -21600 0 CST}
+ {2721888000 -18000 1 CDT}
+ {2740028400 -21600 0 CST}
+ {2753337600 -18000 1 CDT}
+ {2771478000 -21600 0 CST}
+ {2785392000 -18000 1 CDT}
+ {2802927600 -21600 0 CST}
+ {2816841600 -18000 1 CDT}
+ {2834377200 -21600 0 CST}
+ {2848291200 -18000 1 CDT}
+ {2866431600 -21600 0 CST}
+ {2879740800 -18000 1 CDT}
+ {2897881200 -21600 0 CST}
+ {2911190400 -18000 1 CDT}
+ {2929330800 -21600 0 CST}
+ {2942640000 -18000 1 CDT}
+ {2960780400 -21600 0 CST}
+ {2974694400 -18000 1 CDT}
+ {2992230000 -21600 0 CST}
+ {3006144000 -18000 1 CDT}
+ {3023679600 -21600 0 CST}
+ {3037593600 -18000 1 CDT}
+ {3055734000 -21600 0 CST}
+ {3069043200 -18000 1 CDT}
+ {3087183600 -21600 0 CST}
+ {3100492800 -18000 1 CDT}
+ {3118633200 -21600 0 CST}
+ {3132547200 -18000 1 CDT}
+ {3150082800 -21600 0 CST}
+ {3163996800 -18000 1 CDT}
+ {3181532400 -21600 0 CST}
+ {3195446400 -18000 1 CDT}
+ {3212982000 -21600 0 CST}
+ {3226896000 -18000 1 CDT}
+ {3245036400 -21600 0 CST}
+ {3258345600 -18000 1 CDT}
+ {3276486000 -21600 0 CST}
+ {3289795200 -18000 1 CDT}
+ {3307935600 -21600 0 CST}
+ {3321849600 -18000 1 CDT}
+ {3339385200 -21600 0 CST}
+ {3353299200 -18000 1 CDT}
+ {3370834800 -21600 0 CST}
+ {3384748800 -18000 1 CDT}
+ {3402889200 -21600 0 CST}
+ {3416198400 -18000 1 CDT}
+ {3434338800 -21600 0 CST}
+ {3447648000 -18000 1 CDT}
+ {3465788400 -21600 0 CST}
+ {3479702400 -18000 1 CDT}
+ {3497238000 -21600 0 CST}
+ {3511152000 -18000 1 CDT}
+ {3528687600 -21600 0 CST}
+ {3542601600 -18000 1 CDT}
+ {3560137200 -21600 0 CST}
+ {3574051200 -18000 1 CDT}
+ {3592191600 -21600 0 CST}
+ {3605500800 -18000 1 CDT}
+ {3623641200 -21600 0 CST}
+ {3636950400 -18000 1 CDT}
+ {3655090800 -21600 0 CST}
+ {3669004800 -18000 1 CDT}
+ {3686540400 -21600 0 CST}
+ {3700454400 -18000 1 CDT}
+ {3717990000 -21600 0 CST}
+ {3731904000 -18000 1 CDT}
+ {3750044400 -21600 0 CST}
+ {3763353600 -18000 1 CDT}
+ {3781494000 -21600 0 CST}
+ {3794803200 -18000 1 CDT}
+ {3812943600 -21600 0 CST}
+ {3826252800 -18000 1 CDT}
+ {3844393200 -21600 0 CST}
+ {3858307200 -18000 1 CDT}
+ {3875842800 -21600 0 CST}
+ {3889756800 -18000 1 CDT}
+ {3907292400 -21600 0 CST}
+ {3921206400 -18000 1 CDT}
+ {3939346800 -21600 0 CST}
+ {3952656000 -18000 1 CDT}
+ {3970796400 -21600 0 CST}
+ {3984105600 -18000 1 CDT}
+ {4002246000 -21600 0 CST}
+ {4016160000 -18000 1 CDT}
+ {4033695600 -21600 0 CST}
+ {4047609600 -18000 1 CDT}
+ {4065145200 -21600 0 CST}
+ {4079059200 -18000 1 CDT}
+ {4096594800 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Metlakatla b/library/tzdata/America/Metlakatla
new file mode 100644
index 0000000..19337bf
--- /dev/null
+++ b/library/tzdata/America/Metlakatla
@@ -0,0 +1,275 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Metlakatla) {
+ {-9223372036854775808 54822 0 LMT}
+ {-3225366822 -31578 0 LMT}
+ {-2188955622 -28800 0 PST}
+ {-883584000 -28800 0 PST}
+ {-880207200 -25200 1 PWT}
+ {-769395600 -25200 1 PPT}
+ {-765385200 -28800 0 PST}
+ {-757353600 -28800 0 PST}
+ {-31507200 -28800 0 PST}
+ {-21477600 -25200 1 PDT}
+ {-5756400 -28800 0 PST}
+ {9972000 -25200 1 PDT}
+ {25693200 -28800 0 PST}
+ {41421600 -25200 1 PDT}
+ {57747600 -28800 0 PST}
+ {73476000 -25200 1 PDT}
+ {89197200 -28800 0 PST}
+ {104925600 -25200 1 PDT}
+ {120646800 -28800 0 PST}
+ {126698400 -25200 1 PDT}
+ {152096400 -28800 0 PST}
+ {162381600 -25200 1 PDT}
+ {183546000 -28800 0 PST}
+ {199274400 -25200 1 PDT}
+ {215600400 -28800 0 PST}
+ {230724000 -25200 1 PDT}
+ {247050000 -28800 0 PST}
+ {262778400 -25200 1 PDT}
+ {278499600 -28800 0 PST}
+ {294228000 -25200 1 PDT}
+ {309949200 -28800 0 PST}
+ {325677600 -25200 1 PDT}
+ {341398800 -28800 0 PST}
+ {357127200 -25200 1 PDT}
+ {372848400 -28800 0 PST}
+ {388576800 -25200 1 PDT}
+ {404902800 -28800 0 PST}
+ {420026400 -25200 1 PDT}
+ {436356000 -28800 0 MeST}
+ {452080800 -25200 1 MeST}
+ {467802000 -28800 0 MeST}
+ {483530400 -25200 1 MeST}
+ {499251600 -28800 0 MeST}
+ {514980000 -25200 1 MeST}
+ {530701200 -28800 0 MeST}
+ {544615200 -25200 1 MeST}
+ {562150800 -28800 0 MeST}
+ {576064800 -25200 1 MeST}
+ {594205200 -28800 0 MeST}
+ {607514400 -25200 1 MeST}
+ {625654800 -28800 0 MeST}
+ {638964000 -25200 1 MeST}
+ {657104400 -28800 0 MeST}
+ {671018400 -25200 1 MeST}
+ {688554000 -28800 0 MeST}
+ {702468000 -25200 1 MeST}
+ {720003600 -28800 0 MeST}
+ {733917600 -25200 1 MeST}
+ {752058000 -28800 0 MeST}
+ {765367200 -25200 1 MeST}
+ {783507600 -28800 0 MeST}
+ {796816800 -25200 1 MeST}
+ {814957200 -28800 0 MeST}
+ {828871200 -25200 1 MeST}
+ {846406800 -28800 0 MeST}
+ {860320800 -25200 1 MeST}
+ {877856400 -28800 0 MeST}
+ {891770400 -25200 1 MeST}
+ {909306000 -28800 0 MeST}
+ {923220000 -25200 1 MeST}
+ {941360400 -28800 0 MeST}
+ {954669600 -25200 1 MeST}
+ {972810000 -28800 0 MeST}
+ {986119200 -25200 1 MeST}
+ {1004259600 -28800 0 MeST}
+ {1018173600 -25200 1 MeST}
+ {1035709200 -28800 0 MeST}
+ {1049623200 -25200 1 MeST}
+ {1067158800 -28800 0 MeST}
+ {1081072800 -25200 1 MeST}
+ {1099213200 -28800 0 MeST}
+ {1112522400 -25200 1 MeST}
+ {1130662800 -28800 0 MeST}
+ {1143972000 -25200 1 MeST}
+ {1162112400 -28800 0 MeST}
+ {1173607200 -25200 1 MeST}
+ {1194166800 -28800 0 MeST}
+ {1205056800 -25200 1 MeST}
+ {1225616400 -28800 0 MeST}
+ {1236506400 -25200 1 MeST}
+ {1257066000 -28800 0 MeST}
+ {1268560800 -25200 1 MeST}
+ {1289120400 -28800 0 MeST}
+ {1300010400 -25200 1 MeST}
+ {1320570000 -28800 0 MeST}
+ {1331460000 -25200 1 MeST}
+ {1352019600 -28800 0 MeST}
+ {1362909600 -25200 1 MeST}
+ {1383469200 -28800 0 MeST}
+ {1394359200 -25200 1 MeST}
+ {1414918800 -28800 0 MeST}
+ {1425808800 -25200 1 MeST}
+ {1446368400 -28800 0 MeST}
+ {1457863200 -25200 1 MeST}
+ {1478422800 -28800 0 MeST}
+ {1489312800 -25200 1 MeST}
+ {1509872400 -28800 0 MeST}
+ {1520762400 -25200 1 MeST}
+ {1541322000 -28800 0 MeST}
+ {1552212000 -25200 1 MeST}
+ {1572771600 -28800 0 MeST}
+ {1583661600 -25200 1 MeST}
+ {1604221200 -28800 0 MeST}
+ {1615716000 -25200 1 MeST}
+ {1636275600 -28800 0 MeST}
+ {1647165600 -25200 1 MeST}
+ {1667725200 -28800 0 MeST}
+ {1678615200 -25200 1 MeST}
+ {1699174800 -28800 0 MeST}
+ {1710064800 -25200 1 MeST}
+ {1730624400 -28800 0 MeST}
+ {1741514400 -25200 1 MeST}
+ {1762074000 -28800 0 MeST}
+ {1772964000 -25200 1 MeST}
+ {1793523600 -28800 0 MeST}
+ {1805018400 -25200 1 MeST}
+ {1825578000 -28800 0 MeST}
+ {1836468000 -25200 1 MeST}
+ {1857027600 -28800 0 MeST}
+ {1867917600 -25200 1 MeST}
+ {1888477200 -28800 0 MeST}
+ {1899367200 -25200 1 MeST}
+ {1919926800 -28800 0 MeST}
+ {1930816800 -25200 1 MeST}
+ {1951376400 -28800 0 MeST}
+ {1962871200 -25200 1 MeST}
+ {1983430800 -28800 0 MeST}
+ {1994320800 -25200 1 MeST}
+ {2014880400 -28800 0 MeST}
+ {2025770400 -25200 1 MeST}
+ {2046330000 -28800 0 MeST}
+ {2057220000 -25200 1 MeST}
+ {2077779600 -28800 0 MeST}
+ {2088669600 -25200 1 MeST}
+ {2109229200 -28800 0 MeST}
+ {2120119200 -25200 1 MeST}
+ {2140678800 -28800 0 MeST}
+ {2152173600 -25200 1 MeST}
+ {2172733200 -28800 0 MeST}
+ {2183623200 -25200 1 MeST}
+ {2204182800 -28800 0 MeST}
+ {2215072800 -25200 1 MeST}
+ {2235632400 -28800 0 MeST}
+ {2246522400 -25200 1 MeST}
+ {2267082000 -28800 0 MeST}
+ {2277972000 -25200 1 MeST}
+ {2298531600 -28800 0 MeST}
+ {2309421600 -25200 1 MeST}
+ {2329981200 -28800 0 MeST}
+ {2341476000 -25200 1 MeST}
+ {2362035600 -28800 0 MeST}
+ {2372925600 -25200 1 MeST}
+ {2393485200 -28800 0 MeST}
+ {2404375200 -25200 1 MeST}
+ {2424934800 -28800 0 MeST}
+ {2435824800 -25200 1 MeST}
+ {2456384400 -28800 0 MeST}
+ {2467274400 -25200 1 MeST}
+ {2487834000 -28800 0 MeST}
+ {2499328800 -25200 1 MeST}
+ {2519888400 -28800 0 MeST}
+ {2530778400 -25200 1 MeST}
+ {2551338000 -28800 0 MeST}
+ {2562228000 -25200 1 MeST}
+ {2582787600 -28800 0 MeST}
+ {2593677600 -25200 1 MeST}
+ {2614237200 -28800 0 MeST}
+ {2625127200 -25200 1 MeST}
+ {2645686800 -28800 0 MeST}
+ {2656576800 -25200 1 MeST}
+ {2677136400 -28800 0 MeST}
+ {2688631200 -25200 1 MeST}
+ {2709190800 -28800 0 MeST}
+ {2720080800 -25200 1 MeST}
+ {2740640400 -28800 0 MeST}
+ {2751530400 -25200 1 MeST}
+ {2772090000 -28800 0 MeST}
+ {2782980000 -25200 1 MeST}
+ {2803539600 -28800 0 MeST}
+ {2814429600 -25200 1 MeST}
+ {2834989200 -28800 0 MeST}
+ {2846484000 -25200 1 MeST}
+ {2867043600 -28800 0 MeST}
+ {2877933600 -25200 1 MeST}
+ {2898493200 -28800 0 MeST}
+ {2909383200 -25200 1 MeST}
+ {2929942800 -28800 0 MeST}
+ {2940832800 -25200 1 MeST}
+ {2961392400 -28800 0 MeST}
+ {2972282400 -25200 1 MeST}
+ {2992842000 -28800 0 MeST}
+ {3003732000 -25200 1 MeST}
+ {3024291600 -28800 0 MeST}
+ {3035786400 -25200 1 MeST}
+ {3056346000 -28800 0 MeST}
+ {3067236000 -25200 1 MeST}
+ {3087795600 -28800 0 MeST}
+ {3098685600 -25200 1 MeST}
+ {3119245200 -28800 0 MeST}
+ {3130135200 -25200 1 MeST}
+ {3150694800 -28800 0 MeST}
+ {3161584800 -25200 1 MeST}
+ {3182144400 -28800 0 MeST}
+ {3193034400 -25200 1 MeST}
+ {3213594000 -28800 0 MeST}
+ {3225088800 -25200 1 MeST}
+ {3245648400 -28800 0 MeST}
+ {3256538400 -25200 1 MeST}
+ {3277098000 -28800 0 MeST}
+ {3287988000 -25200 1 MeST}
+ {3308547600 -28800 0 MeST}
+ {3319437600 -25200 1 MeST}
+ {3339997200 -28800 0 MeST}
+ {3350887200 -25200 1 MeST}
+ {3371446800 -28800 0 MeST}
+ {3382941600 -25200 1 MeST}
+ {3403501200 -28800 0 MeST}
+ {3414391200 -25200 1 MeST}
+ {3434950800 -28800 0 MeST}
+ {3445840800 -25200 1 MeST}
+ {3466400400 -28800 0 MeST}
+ {3477290400 -25200 1 MeST}
+ {3497850000 -28800 0 MeST}
+ {3508740000 -25200 1 MeST}
+ {3529299600 -28800 0 MeST}
+ {3540189600 -25200 1 MeST}
+ {3560749200 -28800 0 MeST}
+ {3572244000 -25200 1 MeST}
+ {3592803600 -28800 0 MeST}
+ {3603693600 -25200 1 MeST}
+ {3624253200 -28800 0 MeST}
+ {3635143200 -25200 1 MeST}
+ {3655702800 -28800 0 MeST}
+ {3666592800 -25200 1 MeST}
+ {3687152400 -28800 0 MeST}
+ {3698042400 -25200 1 MeST}
+ {3718602000 -28800 0 MeST}
+ {3730096800 -25200 1 MeST}
+ {3750656400 -28800 0 MeST}
+ {3761546400 -25200 1 MeST}
+ {3782106000 -28800 0 MeST}
+ {3792996000 -25200 1 MeST}
+ {3813555600 -28800 0 MeST}
+ {3824445600 -25200 1 MeST}
+ {3845005200 -28800 0 MeST}
+ {3855895200 -25200 1 MeST}
+ {3876454800 -28800 0 MeST}
+ {3887344800 -25200 1 MeST}
+ {3907904400 -28800 0 MeST}
+ {3919399200 -25200 1 MeST}
+ {3939958800 -28800 0 MeST}
+ {3950848800 -25200 1 MeST}
+ {3971408400 -28800 0 MeST}
+ {3982298400 -25200 1 MeST}
+ {4002858000 -28800 0 MeST}
+ {4013748000 -25200 1 MeST}
+ {4034307600 -28800 0 MeST}
+ {4045197600 -25200 1 MeST}
+ {4065757200 -28800 0 MeST}
+ {4076647200 -25200 1 MeST}
+ {4097206800 -28800 0 MeST}
+}
diff --git a/library/tzdata/America/Mexico_City b/library/tzdata/America/Mexico_City
new file mode 100644
index 0000000..48462e4
--- /dev/null
+++ b/library/tzdata/America/Mexico_City
@@ -0,0 +1,228 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Mexico_City) {
+ {-9223372036854775808 -23796 0 LMT}
+ {-1514739600 -25200 0 MST}
+ {-1343066400 -21600 0 CST}
+ {-1234807200 -25200 0 MST}
+ {-1220292000 -21600 0 CST}
+ {-1207159200 -25200 0 MST}
+ {-1191344400 -21600 0 CST}
+ {-975261600 -18000 1 CDT}
+ {-963169200 -21600 0 CST}
+ {-917114400 -18000 1 CDT}
+ {-907354800 -21600 0 CST}
+ {-821901600 -18000 1 CWT}
+ {-810068400 -21600 0 CST}
+ {-627501600 -18000 1 CDT}
+ {-612990000 -21600 0 CST}
+ {828864000 -18000 1 CDT}
+ {846399600 -21600 0 CST}
+ {860313600 -18000 1 CDT}
+ {877849200 -21600 0 CST}
+ {891763200 -18000 1 CDT}
+ {909298800 -21600 0 CST}
+ {923212800 -18000 1 CDT}
+ {941353200 -21600 0 CST}
+ {954662400 -18000 1 CDT}
+ {972802800 -21600 0 CST}
+ {989136000 -18000 1 CDT}
+ {1001836800 -21600 0 CST}
+ {1014184800 -21600 0 CST}
+ {1018166400 -18000 1 CDT}
+ {1035702000 -21600 0 CST}
+ {1049616000 -18000 1 CDT}
+ {1067151600 -21600 0 CST}
+ {1081065600 -18000 1 CDT}
+ {1099206000 -21600 0 CST}
+ {1112515200 -18000 1 CDT}
+ {1130655600 -21600 0 CST}
+ {1143964800 -18000 1 CDT}
+ {1162105200 -21600 0 CST}
+ {1175414400 -18000 1 CDT}
+ {1193554800 -21600 0 CST}
+ {1207468800 -18000 1 CDT}
+ {1225004400 -21600 0 CST}
+ {1238918400 -18000 1 CDT}
+ {1256454000 -21600 0 CST}
+ {1270368000 -18000 1 CDT}
+ {1288508400 -21600 0 CST}
+ {1301817600 -18000 1 CDT}
+ {1319958000 -21600 0 CST}
+ {1333267200 -18000 1 CDT}
+ {1351407600 -21600 0 CST}
+ {1365321600 -18000 1 CDT}
+ {1382857200 -21600 0 CST}
+ {1396771200 -18000 1 CDT}
+ {1414306800 -21600 0 CST}
+ {1428220800 -18000 1 CDT}
+ {1445756400 -21600 0 CST}
+ {1459670400 -18000 1 CDT}
+ {1477810800 -21600 0 CST}
+ {1491120000 -18000 1 CDT}
+ {1509260400 -21600 0 CST}
+ {1522569600 -18000 1 CDT}
+ {1540710000 -21600 0 CST}
+ {1554624000 -18000 1 CDT}
+ {1572159600 -21600 0 CST}
+ {1586073600 -18000 1 CDT}
+ {1603609200 -21600 0 CST}
+ {1617523200 -18000 1 CDT}
+ {1635663600 -21600 0 CST}
+ {1648972800 -18000 1 CDT}
+ {1667113200 -21600 0 CST}
+ {1680422400 -18000 1 CDT}
+ {1698562800 -21600 0 CST}
+ {1712476800 -18000 1 CDT}
+ {1730012400 -21600 0 CST}
+ {1743926400 -18000 1 CDT}
+ {1761462000 -21600 0 CST}
+ {1775376000 -18000 1 CDT}
+ {1792911600 -21600 0 CST}
+ {1806825600 -18000 1 CDT}
+ {1824966000 -21600 0 CST}
+ {1838275200 -18000 1 CDT}
+ {1856415600 -21600 0 CST}
+ {1869724800 -18000 1 CDT}
+ {1887865200 -21600 0 CST}
+ {1901779200 -18000 1 CDT}
+ {1919314800 -21600 0 CST}
+ {1933228800 -18000 1 CDT}
+ {1950764400 -21600 0 CST}
+ {1964678400 -18000 1 CDT}
+ {1982818800 -21600 0 CST}
+ {1996128000 -18000 1 CDT}
+ {2014268400 -21600 0 CST}
+ {2027577600 -18000 1 CDT}
+ {2045718000 -21600 0 CST}
+ {2059027200 -18000 1 CDT}
+ {2077167600 -21600 0 CST}
+ {2091081600 -18000 1 CDT}
+ {2108617200 -21600 0 CST}
+ {2122531200 -18000 1 CDT}
+ {2140066800 -21600 0 CST}
+ {2153980800 -18000 1 CDT}
+ {2172121200 -21600 0 CST}
+ {2185430400 -18000 1 CDT}
+ {2203570800 -21600 0 CST}
+ {2216880000 -18000 1 CDT}
+ {2235020400 -21600 0 CST}
+ {2248934400 -18000 1 CDT}
+ {2266470000 -21600 0 CST}
+ {2280384000 -18000 1 CDT}
+ {2297919600 -21600 0 CST}
+ {2311833600 -18000 1 CDT}
+ {2329369200 -21600 0 CST}
+ {2343283200 -18000 1 CDT}
+ {2361423600 -21600 0 CST}
+ {2374732800 -18000 1 CDT}
+ {2392873200 -21600 0 CST}
+ {2406182400 -18000 1 CDT}
+ {2424322800 -21600 0 CST}
+ {2438236800 -18000 1 CDT}
+ {2455772400 -21600 0 CST}
+ {2469686400 -18000 1 CDT}
+ {2487222000 -21600 0 CST}
+ {2501136000 -18000 1 CDT}
+ {2519276400 -21600 0 CST}
+ {2532585600 -18000 1 CDT}
+ {2550726000 -21600 0 CST}
+ {2564035200 -18000 1 CDT}
+ {2582175600 -21600 0 CST}
+ {2596089600 -18000 1 CDT}
+ {2613625200 -21600 0 CST}
+ {2627539200 -18000 1 CDT}
+ {2645074800 -21600 0 CST}
+ {2658988800 -18000 1 CDT}
+ {2676524400 -21600 0 CST}
+ {2690438400 -18000 1 CDT}
+ {2708578800 -21600 0 CST}
+ {2721888000 -18000 1 CDT}
+ {2740028400 -21600 0 CST}
+ {2753337600 -18000 1 CDT}
+ {2771478000 -21600 0 CST}
+ {2785392000 -18000 1 CDT}
+ {2802927600 -21600 0 CST}
+ {2816841600 -18000 1 CDT}
+ {2834377200 -21600 0 CST}
+ {2848291200 -18000 1 CDT}
+ {2866431600 -21600 0 CST}
+ {2879740800 -18000 1 CDT}
+ {2897881200 -21600 0 CST}
+ {2911190400 -18000 1 CDT}
+ {2929330800 -21600 0 CST}
+ {2942640000 -18000 1 CDT}
+ {2960780400 -21600 0 CST}
+ {2974694400 -18000 1 CDT}
+ {2992230000 -21600 0 CST}
+ {3006144000 -18000 1 CDT}
+ {3023679600 -21600 0 CST}
+ {3037593600 -18000 1 CDT}
+ {3055734000 -21600 0 CST}
+ {3069043200 -18000 1 CDT}
+ {3087183600 -21600 0 CST}
+ {3100492800 -18000 1 CDT}
+ {3118633200 -21600 0 CST}
+ {3132547200 -18000 1 CDT}
+ {3150082800 -21600 0 CST}
+ {3163996800 -18000 1 CDT}
+ {3181532400 -21600 0 CST}
+ {3195446400 -18000 1 CDT}
+ {3212982000 -21600 0 CST}
+ {3226896000 -18000 1 CDT}
+ {3245036400 -21600 0 CST}
+ {3258345600 -18000 1 CDT}
+ {3276486000 -21600 0 CST}
+ {3289795200 -18000 1 CDT}
+ {3307935600 -21600 0 CST}
+ {3321849600 -18000 1 CDT}
+ {3339385200 -21600 0 CST}
+ {3353299200 -18000 1 CDT}
+ {3370834800 -21600 0 CST}
+ {3384748800 -18000 1 CDT}
+ {3402889200 -21600 0 CST}
+ {3416198400 -18000 1 CDT}
+ {3434338800 -21600 0 CST}
+ {3447648000 -18000 1 CDT}
+ {3465788400 -21600 0 CST}
+ {3479702400 -18000 1 CDT}
+ {3497238000 -21600 0 CST}
+ {3511152000 -18000 1 CDT}
+ {3528687600 -21600 0 CST}
+ {3542601600 -18000 1 CDT}
+ {3560137200 -21600 0 CST}
+ {3574051200 -18000 1 CDT}
+ {3592191600 -21600 0 CST}
+ {3605500800 -18000 1 CDT}
+ {3623641200 -21600 0 CST}
+ {3636950400 -18000 1 CDT}
+ {3655090800 -21600 0 CST}
+ {3669004800 -18000 1 CDT}
+ {3686540400 -21600 0 CST}
+ {3700454400 -18000 1 CDT}
+ {3717990000 -21600 0 CST}
+ {3731904000 -18000 1 CDT}
+ {3750044400 -21600 0 CST}
+ {3763353600 -18000 1 CDT}
+ {3781494000 -21600 0 CST}
+ {3794803200 -18000 1 CDT}
+ {3812943600 -21600 0 CST}
+ {3826252800 -18000 1 CDT}
+ {3844393200 -21600 0 CST}
+ {3858307200 -18000 1 CDT}
+ {3875842800 -21600 0 CST}
+ {3889756800 -18000 1 CDT}
+ {3907292400 -21600 0 CST}
+ {3921206400 -18000 1 CDT}
+ {3939346800 -21600 0 CST}
+ {3952656000 -18000 1 CDT}
+ {3970796400 -21600 0 CST}
+ {3984105600 -18000 1 CDT}
+ {4002246000 -21600 0 CST}
+ {4016160000 -18000 1 CDT}
+ {4033695600 -21600 0 CST}
+ {4047609600 -18000 1 CDT}
+ {4065145200 -21600 0 CST}
+ {4079059200 -18000 1 CDT}
+ {4096594800 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Miquelon b/library/tzdata/America/Miquelon
new file mode 100644
index 0000000..a7410f1
--- /dev/null
+++ b/library/tzdata/America/Miquelon
@@ -0,0 +1,234 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Miquelon) {
+ {-9223372036854775808 -13480 0 LMT}
+ {-1850328920 -14400 0 AST}
+ {326001600 -10800 0 PMST}
+ {536468400 -10800 0 PMST}
+ {544597200 -7200 1 PMDT}
+ {562132800 -10800 0 PMST}
+ {576046800 -7200 1 PMDT}
+ {594187200 -10800 0 PMST}
+ {607496400 -7200 1 PMDT}
+ {625636800 -10800 0 PMST}
+ {638946000 -7200 1 PMDT}
+ {657086400 -10800 0 PMST}
+ {671000400 -7200 1 PMDT}
+ {688536000 -10800 0 PMST}
+ {702450000 -7200 1 PMDT}
+ {719985600 -10800 0 PMST}
+ {733899600 -7200 1 PMDT}
+ {752040000 -10800 0 PMST}
+ {765349200 -7200 1 PMDT}
+ {783489600 -10800 0 PMST}
+ {796798800 -7200 1 PMDT}
+ {814939200 -10800 0 PMST}
+ {828853200 -7200 1 PMDT}
+ {846388800 -10800 0 PMST}
+ {860302800 -7200 1 PMDT}
+ {877838400 -10800 0 PMST}
+ {891752400 -7200 1 PMDT}
+ {909288000 -10800 0 PMST}
+ {923202000 -7200 1 PMDT}
+ {941342400 -10800 0 PMST}
+ {954651600 -7200 1 PMDT}
+ {972792000 -10800 0 PMST}
+ {986101200 -7200 1 PMDT}
+ {1004241600 -10800 0 PMST}
+ {1018155600 -7200 1 PMDT}
+ {1035691200 -10800 0 PMST}
+ {1049605200 -7200 1 PMDT}
+ {1067140800 -10800 0 PMST}
+ {1081054800 -7200 1 PMDT}
+ {1099195200 -10800 0 PMST}
+ {1112504400 -7200 1 PMDT}
+ {1130644800 -10800 0 PMST}
+ {1143954000 -7200 1 PMDT}
+ {1162094400 -10800 0 PMST}
+ {1173589200 -7200 1 PMDT}
+ {1194148800 -10800 0 PMST}
+ {1205038800 -7200 1 PMDT}
+ {1225598400 -10800 0 PMST}
+ {1236488400 -7200 1 PMDT}
+ {1257048000 -10800 0 PMST}
+ {1268542800 -7200 1 PMDT}
+ {1289102400 -10800 0 PMST}
+ {1299992400 -7200 1 PMDT}
+ {1320552000 -10800 0 PMST}
+ {1331442000 -7200 1 PMDT}
+ {1352001600 -10800 0 PMST}
+ {1362891600 -7200 1 PMDT}
+ {1383451200 -10800 0 PMST}
+ {1394341200 -7200 1 PMDT}
+ {1414900800 -10800 0 PMST}
+ {1425790800 -7200 1 PMDT}
+ {1446350400 -10800 0 PMST}
+ {1457845200 -7200 1 PMDT}
+ {1478404800 -10800 0 PMST}
+ {1489294800 -7200 1 PMDT}
+ {1509854400 -10800 0 PMST}
+ {1520744400 -7200 1 PMDT}
+ {1541304000 -10800 0 PMST}
+ {1552194000 -7200 1 PMDT}
+ {1572753600 -10800 0 PMST}
+ {1583643600 -7200 1 PMDT}
+ {1604203200 -10800 0 PMST}
+ {1615698000 -7200 1 PMDT}
+ {1636257600 -10800 0 PMST}
+ {1647147600 -7200 1 PMDT}
+ {1667707200 -10800 0 PMST}
+ {1678597200 -7200 1 PMDT}
+ {1699156800 -10800 0 PMST}
+ {1710046800 -7200 1 PMDT}
+ {1730606400 -10800 0 PMST}
+ {1741496400 -7200 1 PMDT}
+ {1762056000 -10800 0 PMST}
+ {1772946000 -7200 1 PMDT}
+ {1793505600 -10800 0 PMST}
+ {1805000400 -7200 1 PMDT}
+ {1825560000 -10800 0 PMST}
+ {1836450000 -7200 1 PMDT}
+ {1857009600 -10800 0 PMST}
+ {1867899600 -7200 1 PMDT}
+ {1888459200 -10800 0 PMST}
+ {1899349200 -7200 1 PMDT}
+ {1919908800 -10800 0 PMST}
+ {1930798800 -7200 1 PMDT}
+ {1951358400 -10800 0 PMST}
+ {1962853200 -7200 1 PMDT}
+ {1983412800 -10800 0 PMST}
+ {1994302800 -7200 1 PMDT}
+ {2014862400 -10800 0 PMST}
+ {2025752400 -7200 1 PMDT}
+ {2046312000 -10800 0 PMST}
+ {2057202000 -7200 1 PMDT}
+ {2077761600 -10800 0 PMST}
+ {2088651600 -7200 1 PMDT}
+ {2109211200 -10800 0 PMST}
+ {2120101200 -7200 1 PMDT}
+ {2140660800 -10800 0 PMST}
+ {2152155600 -7200 1 PMDT}
+ {2172715200 -10800 0 PMST}
+ {2183605200 -7200 1 PMDT}
+ {2204164800 -10800 0 PMST}
+ {2215054800 -7200 1 PMDT}
+ {2235614400 -10800 0 PMST}
+ {2246504400 -7200 1 PMDT}
+ {2267064000 -10800 0 PMST}
+ {2277954000 -7200 1 PMDT}
+ {2298513600 -10800 0 PMST}
+ {2309403600 -7200 1 PMDT}
+ {2329963200 -10800 0 PMST}
+ {2341458000 -7200 1 PMDT}
+ {2362017600 -10800 0 PMST}
+ {2372907600 -7200 1 PMDT}
+ {2393467200 -10800 0 PMST}
+ {2404357200 -7200 1 PMDT}
+ {2424916800 -10800 0 PMST}
+ {2435806800 -7200 1 PMDT}
+ {2456366400 -10800 0 PMST}
+ {2467256400 -7200 1 PMDT}
+ {2487816000 -10800 0 PMST}
+ {2499310800 -7200 1 PMDT}
+ {2519870400 -10800 0 PMST}
+ {2530760400 -7200 1 PMDT}
+ {2551320000 -10800 0 PMST}
+ {2562210000 -7200 1 PMDT}
+ {2582769600 -10800 0 PMST}
+ {2593659600 -7200 1 PMDT}
+ {2614219200 -10800 0 PMST}
+ {2625109200 -7200 1 PMDT}
+ {2645668800 -10800 0 PMST}
+ {2656558800 -7200 1 PMDT}
+ {2677118400 -10800 0 PMST}
+ {2688613200 -7200 1 PMDT}
+ {2709172800 -10800 0 PMST}
+ {2720062800 -7200 1 PMDT}
+ {2740622400 -10800 0 PMST}
+ {2751512400 -7200 1 PMDT}
+ {2772072000 -10800 0 PMST}
+ {2782962000 -7200 1 PMDT}
+ {2803521600 -10800 0 PMST}
+ {2814411600 -7200 1 PMDT}
+ {2834971200 -10800 0 PMST}
+ {2846466000 -7200 1 PMDT}
+ {2867025600 -10800 0 PMST}
+ {2877915600 -7200 1 PMDT}
+ {2898475200 -10800 0 PMST}
+ {2909365200 -7200 1 PMDT}
+ {2929924800 -10800 0 PMST}
+ {2940814800 -7200 1 PMDT}
+ {2961374400 -10800 0 PMST}
+ {2972264400 -7200 1 PMDT}
+ {2992824000 -10800 0 PMST}
+ {3003714000 -7200 1 PMDT}
+ {3024273600 -10800 0 PMST}
+ {3035768400 -7200 1 PMDT}
+ {3056328000 -10800 0 PMST}
+ {3067218000 -7200 1 PMDT}
+ {3087777600 -10800 0 PMST}
+ {3098667600 -7200 1 PMDT}
+ {3119227200 -10800 0 PMST}
+ {3130117200 -7200 1 PMDT}
+ {3150676800 -10800 0 PMST}
+ {3161566800 -7200 1 PMDT}
+ {3182126400 -10800 0 PMST}
+ {3193016400 -7200 1 PMDT}
+ {3213576000 -10800 0 PMST}
+ {3225070800 -7200 1 PMDT}
+ {3245630400 -10800 0 PMST}
+ {3256520400 -7200 1 PMDT}
+ {3277080000 -10800 0 PMST}
+ {3287970000 -7200 1 PMDT}
+ {3308529600 -10800 0 PMST}
+ {3319419600 -7200 1 PMDT}
+ {3339979200 -10800 0 PMST}
+ {3350869200 -7200 1 PMDT}
+ {3371428800 -10800 0 PMST}
+ {3382923600 -7200 1 PMDT}
+ {3403483200 -10800 0 PMST}
+ {3414373200 -7200 1 PMDT}
+ {3434932800 -10800 0 PMST}
+ {3445822800 -7200 1 PMDT}
+ {3466382400 -10800 0 PMST}
+ {3477272400 -7200 1 PMDT}
+ {3497832000 -10800 0 PMST}
+ {3508722000 -7200 1 PMDT}
+ {3529281600 -10800 0 PMST}
+ {3540171600 -7200 1 PMDT}
+ {3560731200 -10800 0 PMST}
+ {3572226000 -7200 1 PMDT}
+ {3592785600 -10800 0 PMST}
+ {3603675600 -7200 1 PMDT}
+ {3624235200 -10800 0 PMST}
+ {3635125200 -7200 1 PMDT}
+ {3655684800 -10800 0 PMST}
+ {3666574800 -7200 1 PMDT}
+ {3687134400 -10800 0 PMST}
+ {3698024400 -7200 1 PMDT}
+ {3718584000 -10800 0 PMST}
+ {3730078800 -7200 1 PMDT}
+ {3750638400 -10800 0 PMST}
+ {3761528400 -7200 1 PMDT}
+ {3782088000 -10800 0 PMST}
+ {3792978000 -7200 1 PMDT}
+ {3813537600 -10800 0 PMST}
+ {3824427600 -7200 1 PMDT}
+ {3844987200 -10800 0 PMST}
+ {3855877200 -7200 1 PMDT}
+ {3876436800 -10800 0 PMST}
+ {3887326800 -7200 1 PMDT}
+ {3907886400 -10800 0 PMST}
+ {3919381200 -7200 1 PMDT}
+ {3939940800 -10800 0 PMST}
+ {3950830800 -7200 1 PMDT}
+ {3971390400 -10800 0 PMST}
+ {3982280400 -7200 1 PMDT}
+ {4002840000 -10800 0 PMST}
+ {4013730000 -7200 1 PMDT}
+ {4034289600 -10800 0 PMST}
+ {4045179600 -7200 1 PMDT}
+ {4065739200 -10800 0 PMST}
+ {4076629200 -7200 1 PMDT}
+ {4097188800 -10800 0 PMST}
+}
diff --git a/library/tzdata/America/Moncton b/library/tzdata/America/Moncton
new file mode 100755
index 0000000..408e3a1
--- /dev/null
+++ b/library/tzdata/America/Moncton
@@ -0,0 +1,342 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Moncton) {
+ {-9223372036854775808 -15548 0 LMT}
+ {-2715882052 -18000 0 EST}
+ {-2131642800 -14400 0 AST}
+ {-1632074400 -10800 1 ADT}
+ {-1614798000 -14400 0 AST}
+ {-1167595200 -14400 0 AST}
+ {-1153681200 -10800 1 ADT}
+ {-1145822400 -14400 0 AST}
+ {-1122231600 -10800 1 ADT}
+ {-1114372800 -14400 0 AST}
+ {-1090782000 -10800 1 ADT}
+ {-1082923200 -14400 0 AST}
+ {-1059332400 -10800 1 ADT}
+ {-1051473600 -14400 0 AST}
+ {-1027882800 -10800 1 ADT}
+ {-1020024000 -14400 0 AST}
+ {-996433200 -10800 1 ADT}
+ {-988574400 -14400 0 AST}
+ {-965674800 -10800 1 ADT}
+ {-955396800 -14400 0 AST}
+ {-934743600 -10800 1 ADT}
+ {-923947200 -14400 0 AST}
+ {-904503600 -10800 1 ADT}
+ {-891892800 -14400 0 AST}
+ {-883598400 -14400 0 AST}
+ {-880221600 -10800 1 AWT}
+ {-769395600 -10800 1 APT}
+ {-765399600 -14400 0 AST}
+ {-757368000 -14400 0 AST}
+ {-747252000 -10800 1 ADT}
+ {-733950000 -14400 0 AST}
+ {-715802400 -10800 1 ADT}
+ {-702500400 -14400 0 AST}
+ {-684352800 -10800 1 ADT}
+ {-671050800 -14400 0 AST}
+ {-652903200 -10800 1 ADT}
+ {-639601200 -14400 0 AST}
+ {-620848800 -10800 1 ADT}
+ {-608151600 -14400 0 AST}
+ {-589399200 -10800 1 ADT}
+ {-576097200 -14400 0 AST}
+ {-557949600 -10800 1 ADT}
+ {-544647600 -14400 0 AST}
+ {-526500000 -10800 1 ADT}
+ {-513198000 -14400 0 AST}
+ {-495050400 -10800 1 ADT}
+ {-481748400 -14400 0 AST}
+ {-463600800 -10800 1 ADT}
+ {-450298800 -14400 0 AST}
+ {-431546400 -10800 1 ADT}
+ {-418244400 -14400 0 AST}
+ {-400096800 -10800 1 ADT}
+ {-384375600 -14400 0 AST}
+ {-368647200 -10800 1 ADT}
+ {-352926000 -14400 0 AST}
+ {-337197600 -10800 1 ADT}
+ {-321476400 -14400 0 AST}
+ {-305748000 -10800 1 ADT}
+ {-289422000 -14400 0 AST}
+ {-273693600 -10800 1 ADT}
+ {-257972400 -14400 0 AST}
+ {-242244000 -10800 1 ADT}
+ {-226522800 -14400 0 AST}
+ {-210794400 -10800 1 ADT}
+ {-195073200 -14400 0 AST}
+ {-179344800 -10800 1 ADT}
+ {-163623600 -14400 0 AST}
+ {-147895200 -10800 1 ADT}
+ {-131569200 -14400 0 AST}
+ {-116445600 -10800 1 ADT}
+ {-100119600 -14400 0 AST}
+ {-84391200 -10800 1 ADT}
+ {-68670000 -14400 0 AST}
+ {-52941600 -10800 1 ADT}
+ {-37220400 -14400 0 AST}
+ {-21492000 -10800 1 ADT}
+ {-5770800 -14400 0 AST}
+ {9957600 -10800 1 ADT}
+ {25678800 -14400 0 AST}
+ {41407200 -10800 1 ADT}
+ {57733200 -14400 0 AST}
+ {73461600 -10800 1 ADT}
+ {89182800 -14400 0 AST}
+ {94708800 -14400 0 AST}
+ {136360800 -10800 1 ADT}
+ {152082000 -14400 0 AST}
+ {167810400 -10800 1 ADT}
+ {183531600 -14400 0 AST}
+ {199260000 -10800 1 ADT}
+ {215586000 -14400 0 AST}
+ {230709600 -10800 1 ADT}
+ {247035600 -14400 0 AST}
+ {262764000 -10800 1 ADT}
+ {278485200 -14400 0 AST}
+ {294213600 -10800 1 ADT}
+ {309934800 -14400 0 AST}
+ {325663200 -10800 1 ADT}
+ {341384400 -14400 0 AST}
+ {357112800 -10800 1 ADT}
+ {372834000 -14400 0 AST}
+ {388562400 -10800 1 ADT}
+ {404888400 -14400 0 AST}
+ {420012000 -10800 1 ADT}
+ {436338000 -14400 0 AST}
+ {452066400 -10800 1 ADT}
+ {467787600 -14400 0 AST}
+ {483516000 -10800 1 ADT}
+ {499237200 -14400 0 AST}
+ {514965600 -10800 1 ADT}
+ {530686800 -14400 0 AST}
+ {544600800 -10800 1 ADT}
+ {562136400 -14400 0 AST}
+ {576050400 -10800 1 ADT}
+ {594190800 -14400 0 AST}
+ {607500000 -10800 1 ADT}
+ {625640400 -14400 0 AST}
+ {638949600 -10800 1 ADT}
+ {657090000 -14400 0 AST}
+ {671004000 -10800 1 ADT}
+ {688539600 -14400 0 AST}
+ {702453600 -10800 1 ADT}
+ {719989200 -14400 0 AST}
+ {725860800 -14400 0 AST}
+ {733896060 -10800 1 ADT}
+ {752036460 -14400 0 AST}
+ {765345660 -10800 1 ADT}
+ {783486060 -14400 0 AST}
+ {796795260 -10800 1 ADT}
+ {814935660 -14400 0 AST}
+ {828849660 -10800 1 ADT}
+ {846385260 -14400 0 AST}
+ {860299260 -10800 1 ADT}
+ {877834860 -14400 0 AST}
+ {891748860 -10800 1 ADT}
+ {909284460 -14400 0 AST}
+ {923198460 -10800 1 ADT}
+ {941338860 -14400 0 AST}
+ {954648060 -10800 1 ADT}
+ {972788460 -14400 0 AST}
+ {986097660 -10800 1 ADT}
+ {1004238060 -14400 0 AST}
+ {1018152060 -10800 1 ADT}
+ {1035687660 -14400 0 AST}
+ {1049601660 -10800 1 ADT}
+ {1067137260 -14400 0 AST}
+ {1081051260 -10800 1 ADT}
+ {1099191660 -14400 0 AST}
+ {1112500860 -10800 1 ADT}
+ {1130641260 -14400 0 AST}
+ {1143950460 -10800 1 ADT}
+ {1162090860 -14400 0 AST}
+ {1167624000 -14400 0 AST}
+ {1173592800 -10800 1 ADT}
+ {1194152400 -14400 0 AST}
+ {1205042400 -10800 1 ADT}
+ {1225602000 -14400 0 AST}
+ {1236492000 -10800 1 ADT}
+ {1257051600 -14400 0 AST}
+ {1268546400 -10800 1 ADT}
+ {1289106000 -14400 0 AST}
+ {1299996000 -10800 1 ADT}
+ {1320555600 -14400 0 AST}
+ {1331445600 -10800 1 ADT}
+ {1352005200 -14400 0 AST}
+ {1362895200 -10800 1 ADT}
+ {1383454800 -14400 0 AST}
+ {1394344800 -10800 1 ADT}
+ {1414904400 -14400 0 AST}
+ {1425794400 -10800 1 ADT}
+ {1446354000 -14400 0 AST}
+ {1457848800 -10800 1 ADT}
+ {1478408400 -14400 0 AST}
+ {1489298400 -10800 1 ADT}
+ {1509858000 -14400 0 AST}
+ {1520748000 -10800 1 ADT}
+ {1541307600 -14400 0 AST}
+ {1552197600 -10800 1 ADT}
+ {1572757200 -14400 0 AST}
+ {1583647200 -10800 1 ADT}
+ {1604206800 -14400 0 AST}
+ {1615701600 -10800 1 ADT}
+ {1636261200 -14400 0 AST}
+ {1647151200 -10800 1 ADT}
+ {1667710800 -14400 0 AST}
+ {1678600800 -10800 1 ADT}
+ {1699160400 -14400 0 AST}
+ {1710050400 -10800 1 ADT}
+ {1730610000 -14400 0 AST}
+ {1741500000 -10800 1 ADT}
+ {1762059600 -14400 0 AST}
+ {1772949600 -10800 1 ADT}
+ {1793509200 -14400 0 AST}
+ {1805004000 -10800 1 ADT}
+ {1825563600 -14400 0 AST}
+ {1836453600 -10800 1 ADT}
+ {1857013200 -14400 0 AST}
+ {1867903200 -10800 1 ADT}
+ {1888462800 -14400 0 AST}
+ {1899352800 -10800 1 ADT}
+ {1919912400 -14400 0 AST}
+ {1930802400 -10800 1 ADT}
+ {1951362000 -14400 0 AST}
+ {1962856800 -10800 1 ADT}
+ {1983416400 -14400 0 AST}
+ {1994306400 -10800 1 ADT}
+ {2014866000 -14400 0 AST}
+ {2025756000 -10800 1 ADT}
+ {2046315600 -14400 0 AST}
+ {2057205600 -10800 1 ADT}
+ {2077765200 -14400 0 AST}
+ {2088655200 -10800 1 ADT}
+ {2109214800 -14400 0 AST}
+ {2120104800 -10800 1 ADT}
+ {2140664400 -14400 0 AST}
+ {2152159200 -10800 1 ADT}
+ {2172718800 -14400 0 AST}
+ {2183608800 -10800 1 ADT}
+ {2204168400 -14400 0 AST}
+ {2215058400 -10800 1 ADT}
+ {2235618000 -14400 0 AST}
+ {2246508000 -10800 1 ADT}
+ {2267067600 -14400 0 AST}
+ {2277957600 -10800 1 ADT}
+ {2298517200 -14400 0 AST}
+ {2309407200 -10800 1 ADT}
+ {2329966800 -14400 0 AST}
+ {2341461600 -10800 1 ADT}
+ {2362021200 -14400 0 AST}
+ {2372911200 -10800 1 ADT}
+ {2393470800 -14400 0 AST}
+ {2404360800 -10800 1 ADT}
+ {2424920400 -14400 0 AST}
+ {2435810400 -10800 1 ADT}
+ {2456370000 -14400 0 AST}
+ {2467260000 -10800 1 ADT}
+ {2487819600 -14400 0 AST}
+ {2499314400 -10800 1 ADT}
+ {2519874000 -14400 0 AST}
+ {2530764000 -10800 1 ADT}
+ {2551323600 -14400 0 AST}
+ {2562213600 -10800 1 ADT}
+ {2582773200 -14400 0 AST}
+ {2593663200 -10800 1 ADT}
+ {2614222800 -14400 0 AST}
+ {2625112800 -10800 1 ADT}
+ {2645672400 -14400 0 AST}
+ {2656562400 -10800 1 ADT}
+ {2677122000 -14400 0 AST}
+ {2688616800 -10800 1 ADT}
+ {2709176400 -14400 0 AST}
+ {2720066400 -10800 1 ADT}
+ {2740626000 -14400 0 AST}
+ {2751516000 -10800 1 ADT}
+ {2772075600 -14400 0 AST}
+ {2782965600 -10800 1 ADT}
+ {2803525200 -14400 0 AST}
+ {2814415200 -10800 1 ADT}
+ {2834974800 -14400 0 AST}
+ {2846469600 -10800 1 ADT}
+ {2867029200 -14400 0 AST}
+ {2877919200 -10800 1 ADT}
+ {2898478800 -14400 0 AST}
+ {2909368800 -10800 1 ADT}
+ {2929928400 -14400 0 AST}
+ {2940818400 -10800 1 ADT}
+ {2961378000 -14400 0 AST}
+ {2972268000 -10800 1 ADT}
+ {2992827600 -14400 0 AST}
+ {3003717600 -10800 1 ADT}
+ {3024277200 -14400 0 AST}
+ {3035772000 -10800 1 ADT}
+ {3056331600 -14400 0 AST}
+ {3067221600 -10800 1 ADT}
+ {3087781200 -14400 0 AST}
+ {3098671200 -10800 1 ADT}
+ {3119230800 -14400 0 AST}
+ {3130120800 -10800 1 ADT}
+ {3150680400 -14400 0 AST}
+ {3161570400 -10800 1 ADT}
+ {3182130000 -14400 0 AST}
+ {3193020000 -10800 1 ADT}
+ {3213579600 -14400 0 AST}
+ {3225074400 -10800 1 ADT}
+ {3245634000 -14400 0 AST}
+ {3256524000 -10800 1 ADT}
+ {3277083600 -14400 0 AST}
+ {3287973600 -10800 1 ADT}
+ {3308533200 -14400 0 AST}
+ {3319423200 -10800 1 ADT}
+ {3339982800 -14400 0 AST}
+ {3350872800 -10800 1 ADT}
+ {3371432400 -14400 0 AST}
+ {3382927200 -10800 1 ADT}
+ {3403486800 -14400 0 AST}
+ {3414376800 -10800 1 ADT}
+ {3434936400 -14400 0 AST}
+ {3445826400 -10800 1 ADT}
+ {3466386000 -14400 0 AST}
+ {3477276000 -10800 1 ADT}
+ {3497835600 -14400 0 AST}
+ {3508725600 -10800 1 ADT}
+ {3529285200 -14400 0 AST}
+ {3540175200 -10800 1 ADT}
+ {3560734800 -14400 0 AST}
+ {3572229600 -10800 1 ADT}
+ {3592789200 -14400 0 AST}
+ {3603679200 -10800 1 ADT}
+ {3624238800 -14400 0 AST}
+ {3635128800 -10800 1 ADT}
+ {3655688400 -14400 0 AST}
+ {3666578400 -10800 1 ADT}
+ {3687138000 -14400 0 AST}
+ {3698028000 -10800 1 ADT}
+ {3718587600 -14400 0 AST}
+ {3730082400 -10800 1 ADT}
+ {3750642000 -14400 0 AST}
+ {3761532000 -10800 1 ADT}
+ {3782091600 -14400 0 AST}
+ {3792981600 -10800 1 ADT}
+ {3813541200 -14400 0 AST}
+ {3824431200 -10800 1 ADT}
+ {3844990800 -14400 0 AST}
+ {3855880800 -10800 1 ADT}
+ {3876440400 -14400 0 AST}
+ {3887330400 -10800 1 ADT}
+ {3907890000 -14400 0 AST}
+ {3919384800 -10800 1 ADT}
+ {3939944400 -14400 0 AST}
+ {3950834400 -10800 1 ADT}
+ {3971394000 -14400 0 AST}
+ {3982284000 -10800 1 ADT}
+ {4002843600 -14400 0 AST}
+ {4013733600 -10800 1 ADT}
+ {4034293200 -14400 0 AST}
+ {4045183200 -10800 1 ADT}
+ {4065742800 -14400 0 AST}
+ {4076632800 -10800 1 ADT}
+ {4097192400 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Monterrey b/library/tzdata/America/Monterrey
new file mode 100644
index 0000000..4135884
--- /dev/null
+++ b/library/tzdata/America/Monterrey
@@ -0,0 +1,218 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Monterrey) {
+ {-9223372036854775808 -24076 0 LMT}
+ {-1514743200 -21600 0 CST}
+ {568015200 -21600 0 CST}
+ {576057600 -18000 1 CDT}
+ {594198000 -21600 0 CST}
+ {599637600 -21600 0 CST}
+ {828864000 -18000 1 CDT}
+ {846399600 -21600 0 CST}
+ {860313600 -18000 1 CDT}
+ {877849200 -21600 0 CST}
+ {891763200 -18000 1 CDT}
+ {909298800 -21600 0 CST}
+ {923212800 -18000 1 CDT}
+ {941353200 -21600 0 CST}
+ {954662400 -18000 1 CDT}
+ {972802800 -21600 0 CST}
+ {989136000 -18000 1 CDT}
+ {1001833200 -21600 0 CST}
+ {1018166400 -18000 1 CDT}
+ {1035702000 -21600 0 CST}
+ {1049616000 -18000 1 CDT}
+ {1067151600 -21600 0 CST}
+ {1081065600 -18000 1 CDT}
+ {1099206000 -21600 0 CST}
+ {1112515200 -18000 1 CDT}
+ {1130655600 -21600 0 CST}
+ {1143964800 -18000 1 CDT}
+ {1162105200 -21600 0 CST}
+ {1175414400 -18000 1 CDT}
+ {1193554800 -21600 0 CST}
+ {1207468800 -18000 1 CDT}
+ {1225004400 -21600 0 CST}
+ {1238918400 -18000 1 CDT}
+ {1256454000 -21600 0 CST}
+ {1270368000 -18000 1 CDT}
+ {1288508400 -21600 0 CST}
+ {1301817600 -18000 1 CDT}
+ {1319958000 -21600 0 CST}
+ {1333267200 -18000 1 CDT}
+ {1351407600 -21600 0 CST}
+ {1365321600 -18000 1 CDT}
+ {1382857200 -21600 0 CST}
+ {1396771200 -18000 1 CDT}
+ {1414306800 -21600 0 CST}
+ {1428220800 -18000 1 CDT}
+ {1445756400 -21600 0 CST}
+ {1459670400 -18000 1 CDT}
+ {1477810800 -21600 0 CST}
+ {1491120000 -18000 1 CDT}
+ {1509260400 -21600 0 CST}
+ {1522569600 -18000 1 CDT}
+ {1540710000 -21600 0 CST}
+ {1554624000 -18000 1 CDT}
+ {1572159600 -21600 0 CST}
+ {1586073600 -18000 1 CDT}
+ {1603609200 -21600 0 CST}
+ {1617523200 -18000 1 CDT}
+ {1635663600 -21600 0 CST}
+ {1648972800 -18000 1 CDT}
+ {1667113200 -21600 0 CST}
+ {1680422400 -18000 1 CDT}
+ {1698562800 -21600 0 CST}
+ {1712476800 -18000 1 CDT}
+ {1730012400 -21600 0 CST}
+ {1743926400 -18000 1 CDT}
+ {1761462000 -21600 0 CST}
+ {1775376000 -18000 1 CDT}
+ {1792911600 -21600 0 CST}
+ {1806825600 -18000 1 CDT}
+ {1824966000 -21600 0 CST}
+ {1838275200 -18000 1 CDT}
+ {1856415600 -21600 0 CST}
+ {1869724800 -18000 1 CDT}
+ {1887865200 -21600 0 CST}
+ {1901779200 -18000 1 CDT}
+ {1919314800 -21600 0 CST}
+ {1933228800 -18000 1 CDT}
+ {1950764400 -21600 0 CST}
+ {1964678400 -18000 1 CDT}
+ {1982818800 -21600 0 CST}
+ {1996128000 -18000 1 CDT}
+ {2014268400 -21600 0 CST}
+ {2027577600 -18000 1 CDT}
+ {2045718000 -21600 0 CST}
+ {2059027200 -18000 1 CDT}
+ {2077167600 -21600 0 CST}
+ {2091081600 -18000 1 CDT}
+ {2108617200 -21600 0 CST}
+ {2122531200 -18000 1 CDT}
+ {2140066800 -21600 0 CST}
+ {2153980800 -18000 1 CDT}
+ {2172121200 -21600 0 CST}
+ {2185430400 -18000 1 CDT}
+ {2203570800 -21600 0 CST}
+ {2216880000 -18000 1 CDT}
+ {2235020400 -21600 0 CST}
+ {2248934400 -18000 1 CDT}
+ {2266470000 -21600 0 CST}
+ {2280384000 -18000 1 CDT}
+ {2297919600 -21600 0 CST}
+ {2311833600 -18000 1 CDT}
+ {2329369200 -21600 0 CST}
+ {2343283200 -18000 1 CDT}
+ {2361423600 -21600 0 CST}
+ {2374732800 -18000 1 CDT}
+ {2392873200 -21600 0 CST}
+ {2406182400 -18000 1 CDT}
+ {2424322800 -21600 0 CST}
+ {2438236800 -18000 1 CDT}
+ {2455772400 -21600 0 CST}
+ {2469686400 -18000 1 CDT}
+ {2487222000 -21600 0 CST}
+ {2501136000 -18000 1 CDT}
+ {2519276400 -21600 0 CST}
+ {2532585600 -18000 1 CDT}
+ {2550726000 -21600 0 CST}
+ {2564035200 -18000 1 CDT}
+ {2582175600 -21600 0 CST}
+ {2596089600 -18000 1 CDT}
+ {2613625200 -21600 0 CST}
+ {2627539200 -18000 1 CDT}
+ {2645074800 -21600 0 CST}
+ {2658988800 -18000 1 CDT}
+ {2676524400 -21600 0 CST}
+ {2690438400 -18000 1 CDT}
+ {2708578800 -21600 0 CST}
+ {2721888000 -18000 1 CDT}
+ {2740028400 -21600 0 CST}
+ {2753337600 -18000 1 CDT}
+ {2771478000 -21600 0 CST}
+ {2785392000 -18000 1 CDT}
+ {2802927600 -21600 0 CST}
+ {2816841600 -18000 1 CDT}
+ {2834377200 -21600 0 CST}
+ {2848291200 -18000 1 CDT}
+ {2866431600 -21600 0 CST}
+ {2879740800 -18000 1 CDT}
+ {2897881200 -21600 0 CST}
+ {2911190400 -18000 1 CDT}
+ {2929330800 -21600 0 CST}
+ {2942640000 -18000 1 CDT}
+ {2960780400 -21600 0 CST}
+ {2974694400 -18000 1 CDT}
+ {2992230000 -21600 0 CST}
+ {3006144000 -18000 1 CDT}
+ {3023679600 -21600 0 CST}
+ {3037593600 -18000 1 CDT}
+ {3055734000 -21600 0 CST}
+ {3069043200 -18000 1 CDT}
+ {3087183600 -21600 0 CST}
+ {3100492800 -18000 1 CDT}
+ {3118633200 -21600 0 CST}
+ {3132547200 -18000 1 CDT}
+ {3150082800 -21600 0 CST}
+ {3163996800 -18000 1 CDT}
+ {3181532400 -21600 0 CST}
+ {3195446400 -18000 1 CDT}
+ {3212982000 -21600 0 CST}
+ {3226896000 -18000 1 CDT}
+ {3245036400 -21600 0 CST}
+ {3258345600 -18000 1 CDT}
+ {3276486000 -21600 0 CST}
+ {3289795200 -18000 1 CDT}
+ {3307935600 -21600 0 CST}
+ {3321849600 -18000 1 CDT}
+ {3339385200 -21600 0 CST}
+ {3353299200 -18000 1 CDT}
+ {3370834800 -21600 0 CST}
+ {3384748800 -18000 1 CDT}
+ {3402889200 -21600 0 CST}
+ {3416198400 -18000 1 CDT}
+ {3434338800 -21600 0 CST}
+ {3447648000 -18000 1 CDT}
+ {3465788400 -21600 0 CST}
+ {3479702400 -18000 1 CDT}
+ {3497238000 -21600 0 CST}
+ {3511152000 -18000 1 CDT}
+ {3528687600 -21600 0 CST}
+ {3542601600 -18000 1 CDT}
+ {3560137200 -21600 0 CST}
+ {3574051200 -18000 1 CDT}
+ {3592191600 -21600 0 CST}
+ {3605500800 -18000 1 CDT}
+ {3623641200 -21600 0 CST}
+ {3636950400 -18000 1 CDT}
+ {3655090800 -21600 0 CST}
+ {3669004800 -18000 1 CDT}
+ {3686540400 -21600 0 CST}
+ {3700454400 -18000 1 CDT}
+ {3717990000 -21600 0 CST}
+ {3731904000 -18000 1 CDT}
+ {3750044400 -21600 0 CST}
+ {3763353600 -18000 1 CDT}
+ {3781494000 -21600 0 CST}
+ {3794803200 -18000 1 CDT}
+ {3812943600 -21600 0 CST}
+ {3826252800 -18000 1 CDT}
+ {3844393200 -21600 0 CST}
+ {3858307200 -18000 1 CDT}
+ {3875842800 -21600 0 CST}
+ {3889756800 -18000 1 CDT}
+ {3907292400 -21600 0 CST}
+ {3921206400 -18000 1 CDT}
+ {3939346800 -21600 0 CST}
+ {3952656000 -18000 1 CDT}
+ {3970796400 -21600 0 CST}
+ {3984105600 -18000 1 CDT}
+ {4002246000 -21600 0 CST}
+ {4016160000 -18000 1 CDT}
+ {4033695600 -21600 0 CST}
+ {4047609600 -18000 1 CDT}
+ {4065145200 -21600 0 CST}
+ {4079059200 -18000 1 CDT}
+ {4096594800 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Montevideo b/library/tzdata/America/Montevideo
new file mode 100644
index 0000000..aa469b9
--- /dev/null
+++ b/library/tzdata/America/Montevideo
@@ -0,0 +1,261 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Montevideo) {
+ {-9223372036854775808 -13484 0 LMT}
+ {-2256668116 -13484 0 MMT}
+ {-1567455316 -12600 0 UYT}
+ {-1459542600 -10800 1 UYHST}
+ {-1443819600 -12600 0 UYT}
+ {-1428006600 -10800 1 UYHST}
+ {-1412283600 -12600 0 UYT}
+ {-1396470600 -10800 1 UYHST}
+ {-1380747600 -12600 0 UYT}
+ {-1141590600 -10800 1 UYHST}
+ {-1128286800 -12600 0 UYT}
+ {-1110141000 -10800 1 UYHST}
+ {-1096837200 -12600 0 UYT}
+ {-1078691400 -10800 1 UYHST}
+ {-1065387600 -12600 0 UYT}
+ {-1046637000 -10800 1 UYHST}
+ {-1033938000 -12600 0 UYT}
+ {-1015187400 -10800 1 UYHST}
+ {-1002488400 -12600 0 UYT}
+ {-983737800 -10800 1 UYHST}
+ {-971038800 -12600 0 UYT}
+ {-952288200 -10800 1 UYHST}
+ {-938984400 -12600 0 UYT}
+ {-920838600 -10800 1 UYHST}
+ {-907534800 -12600 0 UYT}
+ {-896819400 -10800 1 UYHST}
+ {-853623000 -10800 0 UYT}
+ {-853621200 -7200 1 UYST}
+ {-845848800 -10800 0 UYT}
+ {-334789200 -7200 1 UYST}
+ {-319672800 -10800 0 UYT}
+ {-314226000 -7200 1 UYST}
+ {-309996000 -10800 0 UYT}
+ {-149720400 -7200 1 UYST}
+ {-134604000 -10800 0 UYT}
+ {-118270800 -7200 1 UYST}
+ {-100044000 -10800 0 UYT}
+ {-86821200 -7200 1 UYST}
+ {-68508000 -10800 0 UYT}
+ {-50446800 -9000 1 UYHST}
+ {-34119000 -10800 0 UYT}
+ {-18910800 -9000 1 UYHST}
+ {-2583000 -10800 0 UYT}
+ {12625200 -9000 1 UYHST}
+ {28953000 -10800 0 UYT}
+ {72932400 -7200 1 UYST}
+ {82692000 -10800 0 UYT}
+ {132116400 -9000 1 UYHST}
+ {156911400 -7200 1 UYST}
+ {212983200 -10800 0 UYT}
+ {250052400 -7200 1 UYST}
+ {260244000 -10800 0 UYT}
+ {307594800 -7200 1 UYST}
+ {325994400 -10800 0 UYT}
+ {566449200 -7200 1 UYST}
+ {574308000 -10800 0 UYT}
+ {597812400 -7200 1 UYST}
+ {605671200 -10800 0 UYT}
+ {625633200 -7200 1 UYST}
+ {636516000 -10800 0 UYT}
+ {656478000 -7200 1 UYST}
+ {667965600 -10800 0 UYT}
+ {688532400 -7200 1 UYST}
+ {699415200 -10800 0 UYT}
+ {719377200 -7200 1 UYST}
+ {730864800 -10800 0 UYT}
+ {1095562800 -7200 1 UYST}
+ {1111896000 -10800 0 UYT}
+ {1128834000 -7200 1 UYST}
+ {1142136000 -10800 0 UYT}
+ {1159678800 -7200 1 UYST}
+ {1173585600 -10800 0 UYT}
+ {1191733200 -7200 1 UYST}
+ {1205035200 -10800 0 UYT}
+ {1223182800 -7200 1 UYST}
+ {1236484800 -10800 0 UYT}
+ {1254632400 -7200 1 UYST}
+ {1268539200 -10800 0 UYT}
+ {1286082000 -7200 1 UYST}
+ {1299988800 -10800 0 UYT}
+ {1317531600 -7200 1 UYST}
+ {1331438400 -10800 0 UYT}
+ {1349586000 -7200 1 UYST}
+ {1362888000 -10800 0 UYT}
+ {1381035600 -7200 1 UYST}
+ {1394337600 -10800 0 UYT}
+ {1412485200 -7200 1 UYST}
+ {1425787200 -10800 0 UYT}
+ {1443934800 -7200 1 UYST}
+ {1457841600 -10800 0 UYT}
+ {1475384400 -7200 1 UYST}
+ {1489291200 -10800 0 UYT}
+ {1506834000 -7200 1 UYST}
+ {1520740800 -10800 0 UYT}
+ {1538888400 -7200 1 UYST}
+ {1552190400 -10800 0 UYT}
+ {1570338000 -7200 1 UYST}
+ {1583640000 -10800 0 UYT}
+ {1601787600 -7200 1 UYST}
+ {1615694400 -10800 0 UYT}
+ {1633237200 -7200 1 UYST}
+ {1647144000 -10800 0 UYT}
+ {1664686800 -7200 1 UYST}
+ {1678593600 -10800 0 UYT}
+ {1696136400 -7200 1 UYST}
+ {1710043200 -10800 0 UYT}
+ {1728190800 -7200 1 UYST}
+ {1741492800 -10800 0 UYT}
+ {1759640400 -7200 1 UYST}
+ {1772942400 -10800 0 UYT}
+ {1791090000 -7200 1 UYST}
+ {1804996800 -10800 0 UYT}
+ {1822539600 -7200 1 UYST}
+ {1836446400 -10800 0 UYT}
+ {1853989200 -7200 1 UYST}
+ {1867896000 -10800 0 UYT}
+ {1886043600 -7200 1 UYST}
+ {1899345600 -10800 0 UYT}
+ {1917493200 -7200 1 UYST}
+ {1930795200 -10800 0 UYT}
+ {1948942800 -7200 1 UYST}
+ {1962849600 -10800 0 UYT}
+ {1980392400 -7200 1 UYST}
+ {1994299200 -10800 0 UYT}
+ {2011842000 -7200 1 UYST}
+ {2025748800 -10800 0 UYT}
+ {2043291600 -7200 1 UYST}
+ {2057198400 -10800 0 UYT}
+ {2075346000 -7200 1 UYST}
+ {2088648000 -10800 0 UYT}
+ {2106795600 -7200 1 UYST}
+ {2120097600 -10800 0 UYT}
+ {2138245200 -7200 1 UYST}
+ {2152152000 -10800 0 UYT}
+ {2169694800 -7200 1 UYST}
+ {2183601600 -10800 0 UYT}
+ {2201144400 -7200 1 UYST}
+ {2215051200 -10800 0 UYT}
+ {2233198800 -7200 1 UYST}
+ {2246500800 -10800 0 UYT}
+ {2264648400 -7200 1 UYST}
+ {2277950400 -10800 0 UYT}
+ {2296098000 -7200 1 UYST}
+ {2309400000 -10800 0 UYT}
+ {2327547600 -7200 1 UYST}
+ {2341454400 -10800 0 UYT}
+ {2358997200 -7200 1 UYST}
+ {2372904000 -10800 0 UYT}
+ {2390446800 -7200 1 UYST}
+ {2404353600 -10800 0 UYT}
+ {2422501200 -7200 1 UYST}
+ {2435803200 -10800 0 UYT}
+ {2453950800 -7200 1 UYST}
+ {2467252800 -10800 0 UYT}
+ {2485400400 -7200 1 UYST}
+ {2499307200 -10800 0 UYT}
+ {2516850000 -7200 1 UYST}
+ {2530756800 -10800 0 UYT}
+ {2548299600 -7200 1 UYST}
+ {2562206400 -10800 0 UYT}
+ {2579749200 -7200 1 UYST}
+ {2593656000 -10800 0 UYT}
+ {2611803600 -7200 1 UYST}
+ {2625105600 -10800 0 UYT}
+ {2643253200 -7200 1 UYST}
+ {2656555200 -10800 0 UYT}
+ {2674702800 -7200 1 UYST}
+ {2688609600 -10800 0 UYT}
+ {2706152400 -7200 1 UYST}
+ {2720059200 -10800 0 UYT}
+ {2737602000 -7200 1 UYST}
+ {2751508800 -10800 0 UYT}
+ {2769656400 -7200 1 UYST}
+ {2782958400 -10800 0 UYT}
+ {2801106000 -7200 1 UYST}
+ {2814408000 -10800 0 UYT}
+ {2832555600 -7200 1 UYST}
+ {2846462400 -10800 0 UYT}
+ {2864005200 -7200 1 UYST}
+ {2877912000 -10800 0 UYT}
+ {2895454800 -7200 1 UYST}
+ {2909361600 -10800 0 UYT}
+ {2926904400 -7200 1 UYST}
+ {2940811200 -10800 0 UYT}
+ {2958958800 -7200 1 UYST}
+ {2972260800 -10800 0 UYT}
+ {2990408400 -7200 1 UYST}
+ {3003710400 -10800 0 UYT}
+ {3021858000 -7200 1 UYST}
+ {3035764800 -10800 0 UYT}
+ {3053307600 -7200 1 UYST}
+ {3067214400 -10800 0 UYT}
+ {3084757200 -7200 1 UYST}
+ {3098664000 -10800 0 UYT}
+ {3116811600 -7200 1 UYST}
+ {3130113600 -10800 0 UYT}
+ {3148261200 -7200 1 UYST}
+ {3161563200 -10800 0 UYT}
+ {3179710800 -7200 1 UYST}
+ {3193012800 -10800 0 UYT}
+ {3211160400 -7200 1 UYST}
+ {3225067200 -10800 0 UYT}
+ {3242610000 -7200 1 UYST}
+ {3256516800 -10800 0 UYT}
+ {3274059600 -7200 1 UYST}
+ {3287966400 -10800 0 UYT}
+ {3306114000 -7200 1 UYST}
+ {3319416000 -10800 0 UYT}
+ {3337563600 -7200 1 UYST}
+ {3350865600 -10800 0 UYT}
+ {3369013200 -7200 1 UYST}
+ {3382920000 -10800 0 UYT}
+ {3400462800 -7200 1 UYST}
+ {3414369600 -10800 0 UYT}
+ {3431912400 -7200 1 UYST}
+ {3445819200 -10800 0 UYT}
+ {3463362000 -7200 1 UYST}
+ {3477268800 -10800 0 UYT}
+ {3495416400 -7200 1 UYST}
+ {3508718400 -10800 0 UYT}
+ {3526866000 -7200 1 UYST}
+ {3540168000 -10800 0 UYT}
+ {3558315600 -7200 1 UYST}
+ {3572222400 -10800 0 UYT}
+ {3589765200 -7200 1 UYST}
+ {3603672000 -10800 0 UYT}
+ {3621214800 -7200 1 UYST}
+ {3635121600 -10800 0 UYT}
+ {3653269200 -7200 1 UYST}
+ {3666571200 -10800 0 UYT}
+ {3684718800 -7200 1 UYST}
+ {3698020800 -10800 0 UYT}
+ {3716168400 -7200 1 UYST}
+ {3730075200 -10800 0 UYT}
+ {3747618000 -7200 1 UYST}
+ {3761524800 -10800 0 UYT}
+ {3779067600 -7200 1 UYST}
+ {3792974400 -10800 0 UYT}
+ {3810517200 -7200 1 UYST}
+ {3824424000 -10800 0 UYT}
+ {3842571600 -7200 1 UYST}
+ {3855873600 -10800 0 UYT}
+ {3874021200 -7200 1 UYST}
+ {3887323200 -10800 0 UYT}
+ {3905470800 -7200 1 UYST}
+ {3919377600 -10800 0 UYT}
+ {3936920400 -7200 1 UYST}
+ {3950827200 -10800 0 UYT}
+ {3968370000 -7200 1 UYST}
+ {3982276800 -10800 0 UYT}
+ {4000424400 -7200 1 UYST}
+ {4013726400 -10800 0 UYT}
+ {4031874000 -7200 1 UYST}
+ {4045176000 -10800 0 UYT}
+ {4063323600 -7200 1 UYST}
+ {4076625600 -10800 0 UYT}
+ {4094773200 -7200 1 UYST}
+}
diff --git a/library/tzdata/America/Montreal b/library/tzdata/America/Montreal
new file mode 100644
index 0000000..b9535eb
--- /dev/null
+++ b/library/tzdata/America/Montreal
@@ -0,0 +1,366 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Montreal) {
+ {-9223372036854775808 -17656 0 LMT}
+ {-2713892744 -18000 0 EST}
+ {-1665334800 -14400 1 EDT}
+ {-1662753600 -18000 0 EST}
+ {-1640977200 -18000 0 EST}
+ {-1632070800 -14400 1 EDT}
+ {-1614794400 -18000 0 EST}
+ {-1609441200 -18000 0 EST}
+ {-1601742600 -14400 1 EDT}
+ {-1583775000 -18000 0 EST}
+ {-1567355400 -14400 1 EDT}
+ {-1554053400 -18000 0 EST}
+ {-1535907600 -14400 1 EDT}
+ {-1522603800 -18000 0 EST}
+ {-1504458000 -14400 1 EDT}
+ {-1491154200 -18000 0 EST}
+ {-1439830800 -14400 1 EDT}
+ {-1428255000 -18000 0 EST}
+ {-1409504400 -14400 1 EDT}
+ {-1396805400 -18000 0 EST}
+ {-1378054800 -14400 1 EDT}
+ {-1365355800 -18000 0 EST}
+ {-1346612400 -14400 1 EDT}
+ {-1333915200 -18000 0 EST}
+ {-1315162800 -14400 1 EDT}
+ {-1301860800 -18000 0 EST}
+ {-1283713200 -14400 1 EDT}
+ {-1270411200 -18000 0 EST}
+ {-1252263600 -14400 1 EDT}
+ {-1238961600 -18000 0 EST}
+ {-1220814000 -14400 1 EDT}
+ {-1207512000 -18000 0 EST}
+ {-1188759600 -14400 1 EDT}
+ {-1176062400 -18000 0 EST}
+ {-1157310000 -14400 1 EDT}
+ {-1144008000 -18000 0 EST}
+ {-1125860400 -14400 1 EDT}
+ {-1112558400 -18000 0 EST}
+ {-1094410800 -14400 1 EDT}
+ {-1081108800 -18000 0 EST}
+ {-1062961200 -14400 1 EDT}
+ {-1049659200 -18000 0 EST}
+ {-1031511600 -14400 1 EDT}
+ {-1018209600 -18000 0 EST}
+ {-1000062000 -14400 1 EDT}
+ {-986760000 -18000 0 EST}
+ {-968007600 -14400 1 EDT}
+ {-955310400 -18000 0 EST}
+ {-936558000 -14400 1 EDT}
+ {-880218000 -14400 0 EWT}
+ {-769395600 -14400 1 EPT}
+ {-765396000 -18000 0 EST}
+ {-757364400 -18000 0 EST}
+ {-747248400 -14400 1 EDT}
+ {-733946400 -18000 0 EST}
+ {-715798800 -14400 1 EDT}
+ {-702496800 -18000 0 EST}
+ {-684349200 -14400 1 EDT}
+ {-671047200 -18000 0 EST}
+ {-652899600 -14400 1 EDT}
+ {-636573600 -18000 0 EST}
+ {-620845200 -14400 1 EDT}
+ {-605124000 -18000 0 EST}
+ {-589395600 -14400 1 EDT}
+ {-576093600 -18000 0 EST}
+ {-557946000 -14400 1 EDT}
+ {-544644000 -18000 0 EST}
+ {-526496400 -14400 1 EDT}
+ {-513194400 -18000 0 EST}
+ {-495046800 -14400 1 EDT}
+ {-481744800 -18000 0 EST}
+ {-463597200 -14400 1 EDT}
+ {-450295200 -18000 0 EST}
+ {-431542800 -14400 1 EDT}
+ {-418240800 -18000 0 EST}
+ {-400093200 -14400 1 EDT}
+ {-384372000 -18000 0 EST}
+ {-368643600 -14400 1 EDT}
+ {-352922400 -18000 0 EST}
+ {-337194000 -14400 1 EDT}
+ {-321472800 -18000 0 EST}
+ {-305744400 -14400 1 EDT}
+ {-289418400 -18000 0 EST}
+ {-273690000 -14400 1 EDT}
+ {-257968800 -18000 0 EST}
+ {-242240400 -14400 1 EDT}
+ {-226519200 -18000 0 EST}
+ {-210790800 -14400 1 EDT}
+ {-195069600 -18000 0 EST}
+ {-179341200 -14400 1 EDT}
+ {-163620000 -18000 0 EST}
+ {-147891600 -14400 1 EDT}
+ {-131565600 -18000 0 EST}
+ {-116442000 -14400 1 EDT}
+ {-100116000 -18000 0 EST}
+ {-84387600 -14400 1 EDT}
+ {-68666400 -18000 0 EST}
+ {-52938000 -14400 1 EDT}
+ {-37216800 -18000 0 EST}
+ {-21488400 -14400 1 EDT}
+ {-5767200 -18000 0 EST}
+ {9961200 -14400 1 EDT}
+ {25682400 -18000 0 EST}
+ {41410800 -14400 1 EDT}
+ {57736800 -18000 0 EST}
+ {73465200 -14400 1 EDT}
+ {89186400 -18000 0 EST}
+ {104914800 -14400 1 EDT}
+ {120636000 -18000 0 EST}
+ {126248400 -18000 0 EST}
+ {136364400 -14400 1 EDT}
+ {152085600 -18000 0 EST}
+ {167814000 -14400 1 EDT}
+ {183535200 -18000 0 EST}
+ {199263600 -14400 1 EDT}
+ {215589600 -18000 0 EST}
+ {230713200 -14400 1 EDT}
+ {247039200 -18000 0 EST}
+ {262767600 -14400 1 EDT}
+ {278488800 -18000 0 EST}
+ {294217200 -14400 1 EDT}
+ {309938400 -18000 0 EST}
+ {325666800 -14400 1 EDT}
+ {341388000 -18000 0 EST}
+ {357116400 -14400 1 EDT}
+ {372837600 -18000 0 EST}
+ {388566000 -14400 1 EDT}
+ {404892000 -18000 0 EST}
+ {420015600 -14400 1 EDT}
+ {436341600 -18000 0 EST}
+ {452070000 -14400 1 EDT}
+ {467791200 -18000 0 EST}
+ {483519600 -14400 1 EDT}
+ {499240800 -18000 0 EST}
+ {514969200 -14400 1 EDT}
+ {530690400 -18000 0 EST}
+ {544604400 -14400 1 EDT}
+ {562140000 -18000 0 EST}
+ {576054000 -14400 1 EDT}
+ {594194400 -18000 0 EST}
+ {607503600 -14400 1 EDT}
+ {625644000 -18000 0 EST}
+ {638953200 -14400 1 EDT}
+ {657093600 -18000 0 EST}
+ {671007600 -14400 1 EDT}
+ {688543200 -18000 0 EST}
+ {702457200 -14400 1 EDT}
+ {719992800 -18000 0 EST}
+ {733906800 -14400 1 EDT}
+ {752047200 -18000 0 EST}
+ {765356400 -14400 1 EDT}
+ {783496800 -18000 0 EST}
+ {796806000 -14400 1 EDT}
+ {814946400 -18000 0 EST}
+ {828860400 -14400 1 EDT}
+ {846396000 -18000 0 EST}
+ {860310000 -14400 1 EDT}
+ {877845600 -18000 0 EST}
+ {891759600 -14400 1 EDT}
+ {909295200 -18000 0 EST}
+ {923209200 -14400 1 EDT}
+ {941349600 -18000 0 EST}
+ {954658800 -14400 1 EDT}
+ {972799200 -18000 0 EST}
+ {986108400 -14400 1 EDT}
+ {1004248800 -18000 0 EST}
+ {1018162800 -14400 1 EDT}
+ {1035698400 -18000 0 EST}
+ {1049612400 -14400 1 EDT}
+ {1067148000 -18000 0 EST}
+ {1081062000 -14400 1 EDT}
+ {1099202400 -18000 0 EST}
+ {1112511600 -14400 1 EDT}
+ {1130652000 -18000 0 EST}
+ {1143961200 -14400 1 EDT}
+ {1162101600 -18000 0 EST}
+ {1173596400 -14400 1 EDT}
+ {1194156000 -18000 0 EST}
+ {1205046000 -14400 1 EDT}
+ {1225605600 -18000 0 EST}
+ {1236495600 -14400 1 EDT}
+ {1257055200 -18000 0 EST}
+ {1268550000 -14400 1 EDT}
+ {1289109600 -18000 0 EST}
+ {1299999600 -14400 1 EDT}
+ {1320559200 -18000 0 EST}
+ {1331449200 -14400 1 EDT}
+ {1352008800 -18000 0 EST}
+ {1362898800 -14400 1 EDT}
+ {1383458400 -18000 0 EST}
+ {1394348400 -14400 1 EDT}
+ {1414908000 -18000 0 EST}
+ {1425798000 -14400 1 EDT}
+ {1446357600 -18000 0 EST}
+ {1457852400 -14400 1 EDT}
+ {1478412000 -18000 0 EST}
+ {1489302000 -14400 1 EDT}
+ {1509861600 -18000 0 EST}
+ {1520751600 -14400 1 EDT}
+ {1541311200 -18000 0 EST}
+ {1552201200 -14400 1 EDT}
+ {1572760800 -18000 0 EST}
+ {1583650800 -14400 1 EDT}
+ {1604210400 -18000 0 EST}
+ {1615705200 -14400 1 EDT}
+ {1636264800 -18000 0 EST}
+ {1647154800 -14400 1 EDT}
+ {1667714400 -18000 0 EST}
+ {1678604400 -14400 1 EDT}
+ {1699164000 -18000 0 EST}
+ {1710054000 -14400 1 EDT}
+ {1730613600 -18000 0 EST}
+ {1741503600 -14400 1 EDT}
+ {1762063200 -18000 0 EST}
+ {1772953200 -14400 1 EDT}
+ {1793512800 -18000 0 EST}
+ {1805007600 -14400 1 EDT}
+ {1825567200 -18000 0 EST}
+ {1836457200 -14400 1 EDT}
+ {1857016800 -18000 0 EST}
+ {1867906800 -14400 1 EDT}
+ {1888466400 -18000 0 EST}
+ {1899356400 -14400 1 EDT}
+ {1919916000 -18000 0 EST}
+ {1930806000 -14400 1 EDT}
+ {1951365600 -18000 0 EST}
+ {1962860400 -14400 1 EDT}
+ {1983420000 -18000 0 EST}
+ {1994310000 -14400 1 EDT}
+ {2014869600 -18000 0 EST}
+ {2025759600 -14400 1 EDT}
+ {2046319200 -18000 0 EST}
+ {2057209200 -14400 1 EDT}
+ {2077768800 -18000 0 EST}
+ {2088658800 -14400 1 EDT}
+ {2109218400 -18000 0 EST}
+ {2120108400 -14400 1 EDT}
+ {2140668000 -18000 0 EST}
+ {2152162800 -14400 1 EDT}
+ {2172722400 -18000 0 EST}
+ {2183612400 -14400 1 EDT}
+ {2204172000 -18000 0 EST}
+ {2215062000 -14400 1 EDT}
+ {2235621600 -18000 0 EST}
+ {2246511600 -14400 1 EDT}
+ {2267071200 -18000 0 EST}
+ {2277961200 -14400 1 EDT}
+ {2298520800 -18000 0 EST}
+ {2309410800 -14400 1 EDT}
+ {2329970400 -18000 0 EST}
+ {2341465200 -14400 1 EDT}
+ {2362024800 -18000 0 EST}
+ {2372914800 -14400 1 EDT}
+ {2393474400 -18000 0 EST}
+ {2404364400 -14400 1 EDT}
+ {2424924000 -18000 0 EST}
+ {2435814000 -14400 1 EDT}
+ {2456373600 -18000 0 EST}
+ {2467263600 -14400 1 EDT}
+ {2487823200 -18000 0 EST}
+ {2499318000 -14400 1 EDT}
+ {2519877600 -18000 0 EST}
+ {2530767600 -14400 1 EDT}
+ {2551327200 -18000 0 EST}
+ {2562217200 -14400 1 EDT}
+ {2582776800 -18000 0 EST}
+ {2593666800 -14400 1 EDT}
+ {2614226400 -18000 0 EST}
+ {2625116400 -14400 1 EDT}
+ {2645676000 -18000 0 EST}
+ {2656566000 -14400 1 EDT}
+ {2677125600 -18000 0 EST}
+ {2688620400 -14400 1 EDT}
+ {2709180000 -18000 0 EST}
+ {2720070000 -14400 1 EDT}
+ {2740629600 -18000 0 EST}
+ {2751519600 -14400 1 EDT}
+ {2772079200 -18000 0 EST}
+ {2782969200 -14400 1 EDT}
+ {2803528800 -18000 0 EST}
+ {2814418800 -14400 1 EDT}
+ {2834978400 -18000 0 EST}
+ {2846473200 -14400 1 EDT}
+ {2867032800 -18000 0 EST}
+ {2877922800 -14400 1 EDT}
+ {2898482400 -18000 0 EST}
+ {2909372400 -14400 1 EDT}
+ {2929932000 -18000 0 EST}
+ {2940822000 -14400 1 EDT}
+ {2961381600 -18000 0 EST}
+ {2972271600 -14400 1 EDT}
+ {2992831200 -18000 0 EST}
+ {3003721200 -14400 1 EDT}
+ {3024280800 -18000 0 EST}
+ {3035775600 -14400 1 EDT}
+ {3056335200 -18000 0 EST}
+ {3067225200 -14400 1 EDT}
+ {3087784800 -18000 0 EST}
+ {3098674800 -14400 1 EDT}
+ {3119234400 -18000 0 EST}
+ {3130124400 -14400 1 EDT}
+ {3150684000 -18000 0 EST}
+ {3161574000 -14400 1 EDT}
+ {3182133600 -18000 0 EST}
+ {3193023600 -14400 1 EDT}
+ {3213583200 -18000 0 EST}
+ {3225078000 -14400 1 EDT}
+ {3245637600 -18000 0 EST}
+ {3256527600 -14400 1 EDT}
+ {3277087200 -18000 0 EST}
+ {3287977200 -14400 1 EDT}
+ {3308536800 -18000 0 EST}
+ {3319426800 -14400 1 EDT}
+ {3339986400 -18000 0 EST}
+ {3350876400 -14400 1 EDT}
+ {3371436000 -18000 0 EST}
+ {3382930800 -14400 1 EDT}
+ {3403490400 -18000 0 EST}
+ {3414380400 -14400 1 EDT}
+ {3434940000 -18000 0 EST}
+ {3445830000 -14400 1 EDT}
+ {3466389600 -18000 0 EST}
+ {3477279600 -14400 1 EDT}
+ {3497839200 -18000 0 EST}
+ {3508729200 -14400 1 EDT}
+ {3529288800 -18000 0 EST}
+ {3540178800 -14400 1 EDT}
+ {3560738400 -18000 0 EST}
+ {3572233200 -14400 1 EDT}
+ {3592792800 -18000 0 EST}
+ {3603682800 -14400 1 EDT}
+ {3624242400 -18000 0 EST}
+ {3635132400 -14400 1 EDT}
+ {3655692000 -18000 0 EST}
+ {3666582000 -14400 1 EDT}
+ {3687141600 -18000 0 EST}
+ {3698031600 -14400 1 EDT}
+ {3718591200 -18000 0 EST}
+ {3730086000 -14400 1 EDT}
+ {3750645600 -18000 0 EST}
+ {3761535600 -14400 1 EDT}
+ {3782095200 -18000 0 EST}
+ {3792985200 -14400 1 EDT}
+ {3813544800 -18000 0 EST}
+ {3824434800 -14400 1 EDT}
+ {3844994400 -18000 0 EST}
+ {3855884400 -14400 1 EDT}
+ {3876444000 -18000 0 EST}
+ {3887334000 -14400 1 EDT}
+ {3907893600 -18000 0 EST}
+ {3919388400 -14400 1 EDT}
+ {3939948000 -18000 0 EST}
+ {3950838000 -14400 1 EDT}
+ {3971397600 -18000 0 EST}
+ {3982287600 -14400 1 EDT}
+ {4002847200 -18000 0 EST}
+ {4013737200 -14400 1 EDT}
+ {4034296800 -18000 0 EST}
+ {4045186800 -14400 1 EDT}
+ {4065746400 -18000 0 EST}
+ {4076636400 -14400 1 EDT}
+ {4097196000 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Montserrat b/library/tzdata/America/Montserrat
new file mode 100644
index 0000000..4d82766
--- /dev/null
+++ b/library/tzdata/America/Montserrat
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Montserrat) {
+ {-9223372036854775808 -14932 0 LMT}
+ {-1846266608 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Nassau b/library/tzdata/America/Nassau
new file mode 100644
index 0000000..06c5f06
--- /dev/null
+++ b/library/tzdata/America/Nassau
@@ -0,0 +1,279 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Nassau) {
+ {-9223372036854775808 -18564 0 LMT}
+ {-1825095036 -18000 0 EST}
+ {-179341200 -14400 1 EDT}
+ {-163620000 -18000 0 EST}
+ {-147891600 -14400 1 EDT}
+ {-131565600 -18000 0 EST}
+ {-116442000 -14400 1 EDT}
+ {-100116000 -18000 0 EST}
+ {-84387600 -14400 1 EDT}
+ {-68666400 -18000 0 EST}
+ {-52938000 -14400 1 EDT}
+ {-37216800 -18000 0 EST}
+ {-21488400 -14400 1 EDT}
+ {-5767200 -18000 0 EST}
+ {9961200 -14400 1 EDT}
+ {25682400 -18000 0 EST}
+ {41410800 -14400 1 EDT}
+ {57736800 -18000 0 EST}
+ {73465200 -14400 1 EDT}
+ {89186400 -18000 0 EST}
+ {104914800 -14400 1 EDT}
+ {120636000 -18000 0 EST}
+ {136364400 -14400 1 EDT}
+ {152085600 -18000 0 EST}
+ {167814000 -14400 1 EDT}
+ {183535200 -18000 0 EST}
+ {189320400 -18000 0 EST}
+ {199263600 -14400 1 EDT}
+ {215589600 -18000 0 EST}
+ {230713200 -14400 1 EDT}
+ {247039200 -18000 0 EST}
+ {262767600 -14400 1 EDT}
+ {278488800 -18000 0 EST}
+ {294217200 -14400 1 EDT}
+ {309938400 -18000 0 EST}
+ {325666800 -14400 1 EDT}
+ {341388000 -18000 0 EST}
+ {357116400 -14400 1 EDT}
+ {372837600 -18000 0 EST}
+ {388566000 -14400 1 EDT}
+ {404892000 -18000 0 EST}
+ {420015600 -14400 1 EDT}
+ {436341600 -18000 0 EST}
+ {452070000 -14400 1 EDT}
+ {467791200 -18000 0 EST}
+ {483519600 -14400 1 EDT}
+ {499240800 -18000 0 EST}
+ {514969200 -14400 1 EDT}
+ {530690400 -18000 0 EST}
+ {544604400 -14400 1 EDT}
+ {562140000 -18000 0 EST}
+ {576054000 -14400 1 EDT}
+ {594194400 -18000 0 EST}
+ {607503600 -14400 1 EDT}
+ {625644000 -18000 0 EST}
+ {638953200 -14400 1 EDT}
+ {657093600 -18000 0 EST}
+ {671007600 -14400 1 EDT}
+ {688543200 -18000 0 EST}
+ {702457200 -14400 1 EDT}
+ {719992800 -18000 0 EST}
+ {733906800 -14400 1 EDT}
+ {752047200 -18000 0 EST}
+ {765356400 -14400 1 EDT}
+ {783496800 -18000 0 EST}
+ {796806000 -14400 1 EDT}
+ {814946400 -18000 0 EST}
+ {828860400 -14400 1 EDT}
+ {846396000 -18000 0 EST}
+ {860310000 -14400 1 EDT}
+ {877845600 -18000 0 EST}
+ {891759600 -14400 1 EDT}
+ {909295200 -18000 0 EST}
+ {923209200 -14400 1 EDT}
+ {941349600 -18000 0 EST}
+ {954658800 -14400 1 EDT}
+ {972799200 -18000 0 EST}
+ {986108400 -14400 1 EDT}
+ {1004248800 -18000 0 EST}
+ {1018162800 -14400 1 EDT}
+ {1035698400 -18000 0 EST}
+ {1049612400 -14400 1 EDT}
+ {1067148000 -18000 0 EST}
+ {1081062000 -14400 1 EDT}
+ {1099202400 -18000 0 EST}
+ {1112511600 -14400 1 EDT}
+ {1130652000 -18000 0 EST}
+ {1143961200 -14400 1 EDT}
+ {1162101600 -18000 0 EST}
+ {1173596400 -14400 1 EDT}
+ {1194156000 -18000 0 EST}
+ {1205046000 -14400 1 EDT}
+ {1225605600 -18000 0 EST}
+ {1236495600 -14400 1 EDT}
+ {1257055200 -18000 0 EST}
+ {1268550000 -14400 1 EDT}
+ {1289109600 -18000 0 EST}
+ {1299999600 -14400 1 EDT}
+ {1320559200 -18000 0 EST}
+ {1331449200 -14400 1 EDT}
+ {1352008800 -18000 0 EST}
+ {1362898800 -14400 1 EDT}
+ {1383458400 -18000 0 EST}
+ {1394348400 -14400 1 EDT}
+ {1414908000 -18000 0 EST}
+ {1425798000 -14400 1 EDT}
+ {1446357600 -18000 0 EST}
+ {1457852400 -14400 1 EDT}
+ {1478412000 -18000 0 EST}
+ {1489302000 -14400 1 EDT}
+ {1509861600 -18000 0 EST}
+ {1520751600 -14400 1 EDT}
+ {1541311200 -18000 0 EST}
+ {1552201200 -14400 1 EDT}
+ {1572760800 -18000 0 EST}
+ {1583650800 -14400 1 EDT}
+ {1604210400 -18000 0 EST}
+ {1615705200 -14400 1 EDT}
+ {1636264800 -18000 0 EST}
+ {1647154800 -14400 1 EDT}
+ {1667714400 -18000 0 EST}
+ {1678604400 -14400 1 EDT}
+ {1699164000 -18000 0 EST}
+ {1710054000 -14400 1 EDT}
+ {1730613600 -18000 0 EST}
+ {1741503600 -14400 1 EDT}
+ {1762063200 -18000 0 EST}
+ {1772953200 -14400 1 EDT}
+ {1793512800 -18000 0 EST}
+ {1805007600 -14400 1 EDT}
+ {1825567200 -18000 0 EST}
+ {1836457200 -14400 1 EDT}
+ {1857016800 -18000 0 EST}
+ {1867906800 -14400 1 EDT}
+ {1888466400 -18000 0 EST}
+ {1899356400 -14400 1 EDT}
+ {1919916000 -18000 0 EST}
+ {1930806000 -14400 1 EDT}
+ {1951365600 -18000 0 EST}
+ {1962860400 -14400 1 EDT}
+ {1983420000 -18000 0 EST}
+ {1994310000 -14400 1 EDT}
+ {2014869600 -18000 0 EST}
+ {2025759600 -14400 1 EDT}
+ {2046319200 -18000 0 EST}
+ {2057209200 -14400 1 EDT}
+ {2077768800 -18000 0 EST}
+ {2088658800 -14400 1 EDT}
+ {2109218400 -18000 0 EST}
+ {2120108400 -14400 1 EDT}
+ {2140668000 -18000 0 EST}
+ {2152162800 -14400 1 EDT}
+ {2172722400 -18000 0 EST}
+ {2183612400 -14400 1 EDT}
+ {2204172000 -18000 0 EST}
+ {2215062000 -14400 1 EDT}
+ {2235621600 -18000 0 EST}
+ {2246511600 -14400 1 EDT}
+ {2267071200 -18000 0 EST}
+ {2277961200 -14400 1 EDT}
+ {2298520800 -18000 0 EST}
+ {2309410800 -14400 1 EDT}
+ {2329970400 -18000 0 EST}
+ {2341465200 -14400 1 EDT}
+ {2362024800 -18000 0 EST}
+ {2372914800 -14400 1 EDT}
+ {2393474400 -18000 0 EST}
+ {2404364400 -14400 1 EDT}
+ {2424924000 -18000 0 EST}
+ {2435814000 -14400 1 EDT}
+ {2456373600 -18000 0 EST}
+ {2467263600 -14400 1 EDT}
+ {2487823200 -18000 0 EST}
+ {2499318000 -14400 1 EDT}
+ {2519877600 -18000 0 EST}
+ {2530767600 -14400 1 EDT}
+ {2551327200 -18000 0 EST}
+ {2562217200 -14400 1 EDT}
+ {2582776800 -18000 0 EST}
+ {2593666800 -14400 1 EDT}
+ {2614226400 -18000 0 EST}
+ {2625116400 -14400 1 EDT}
+ {2645676000 -18000 0 EST}
+ {2656566000 -14400 1 EDT}
+ {2677125600 -18000 0 EST}
+ {2688620400 -14400 1 EDT}
+ {2709180000 -18000 0 EST}
+ {2720070000 -14400 1 EDT}
+ {2740629600 -18000 0 EST}
+ {2751519600 -14400 1 EDT}
+ {2772079200 -18000 0 EST}
+ {2782969200 -14400 1 EDT}
+ {2803528800 -18000 0 EST}
+ {2814418800 -14400 1 EDT}
+ {2834978400 -18000 0 EST}
+ {2846473200 -14400 1 EDT}
+ {2867032800 -18000 0 EST}
+ {2877922800 -14400 1 EDT}
+ {2898482400 -18000 0 EST}
+ {2909372400 -14400 1 EDT}
+ {2929932000 -18000 0 EST}
+ {2940822000 -14400 1 EDT}
+ {2961381600 -18000 0 EST}
+ {2972271600 -14400 1 EDT}
+ {2992831200 -18000 0 EST}
+ {3003721200 -14400 1 EDT}
+ {3024280800 -18000 0 EST}
+ {3035775600 -14400 1 EDT}
+ {3056335200 -18000 0 EST}
+ {3067225200 -14400 1 EDT}
+ {3087784800 -18000 0 EST}
+ {3098674800 -14400 1 EDT}
+ {3119234400 -18000 0 EST}
+ {3130124400 -14400 1 EDT}
+ {3150684000 -18000 0 EST}
+ {3161574000 -14400 1 EDT}
+ {3182133600 -18000 0 EST}
+ {3193023600 -14400 1 EDT}
+ {3213583200 -18000 0 EST}
+ {3225078000 -14400 1 EDT}
+ {3245637600 -18000 0 EST}
+ {3256527600 -14400 1 EDT}
+ {3277087200 -18000 0 EST}
+ {3287977200 -14400 1 EDT}
+ {3308536800 -18000 0 EST}
+ {3319426800 -14400 1 EDT}
+ {3339986400 -18000 0 EST}
+ {3350876400 -14400 1 EDT}
+ {3371436000 -18000 0 EST}
+ {3382930800 -14400 1 EDT}
+ {3403490400 -18000 0 EST}
+ {3414380400 -14400 1 EDT}
+ {3434940000 -18000 0 EST}
+ {3445830000 -14400 1 EDT}
+ {3466389600 -18000 0 EST}
+ {3477279600 -14400 1 EDT}
+ {3497839200 -18000 0 EST}
+ {3508729200 -14400 1 EDT}
+ {3529288800 -18000 0 EST}
+ {3540178800 -14400 1 EDT}
+ {3560738400 -18000 0 EST}
+ {3572233200 -14400 1 EDT}
+ {3592792800 -18000 0 EST}
+ {3603682800 -14400 1 EDT}
+ {3624242400 -18000 0 EST}
+ {3635132400 -14400 1 EDT}
+ {3655692000 -18000 0 EST}
+ {3666582000 -14400 1 EDT}
+ {3687141600 -18000 0 EST}
+ {3698031600 -14400 1 EDT}
+ {3718591200 -18000 0 EST}
+ {3730086000 -14400 1 EDT}
+ {3750645600 -18000 0 EST}
+ {3761535600 -14400 1 EDT}
+ {3782095200 -18000 0 EST}
+ {3792985200 -14400 1 EDT}
+ {3813544800 -18000 0 EST}
+ {3824434800 -14400 1 EDT}
+ {3844994400 -18000 0 EST}
+ {3855884400 -14400 1 EDT}
+ {3876444000 -18000 0 EST}
+ {3887334000 -14400 1 EDT}
+ {3907893600 -18000 0 EST}
+ {3919388400 -14400 1 EDT}
+ {3939948000 -18000 0 EST}
+ {3950838000 -14400 1 EDT}
+ {3971397600 -18000 0 EST}
+ {3982287600 -14400 1 EDT}
+ {4002847200 -18000 0 EST}
+ {4013737200 -14400 1 EDT}
+ {4034296800 -18000 0 EST}
+ {4045186800 -14400 1 EDT}
+ {4065746400 -18000 0 EST}
+ {4076636400 -14400 1 EDT}
+ {4097196000 -18000 0 EST}
+}
diff --git a/library/tzdata/America/New_York b/library/tzdata/America/New_York
new file mode 100644
index 0000000..72f2c96
--- /dev/null
+++ b/library/tzdata/America/New_York
@@ -0,0 +1,369 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/New_York) {
+ {-9223372036854775808 -17762 0 LMT}
+ {-2717650800 -18000 0 EST}
+ {-1633280400 -14400 1 EDT}
+ {-1615140000 -18000 0 EST}
+ {-1601830800 -14400 1 EDT}
+ {-1583690400 -18000 0 EST}
+ {-1577905200 -18000 0 EST}
+ {-1570381200 -14400 1 EDT}
+ {-1551636000 -18000 0 EST}
+ {-1536512400 -14400 1 EDT}
+ {-1523210400 -18000 0 EST}
+ {-1504458000 -14400 1 EDT}
+ {-1491760800 -18000 0 EST}
+ {-1473008400 -14400 1 EDT}
+ {-1459706400 -18000 0 EST}
+ {-1441558800 -14400 1 EDT}
+ {-1428256800 -18000 0 EST}
+ {-1410109200 -14400 1 EDT}
+ {-1396807200 -18000 0 EST}
+ {-1378659600 -14400 1 EDT}
+ {-1365357600 -18000 0 EST}
+ {-1347210000 -14400 1 EDT}
+ {-1333908000 -18000 0 EST}
+ {-1315155600 -14400 1 EDT}
+ {-1301853600 -18000 0 EST}
+ {-1283706000 -14400 1 EDT}
+ {-1270404000 -18000 0 EST}
+ {-1252256400 -14400 1 EDT}
+ {-1238954400 -18000 0 EST}
+ {-1220806800 -14400 1 EDT}
+ {-1207504800 -18000 0 EST}
+ {-1189357200 -14400 1 EDT}
+ {-1176055200 -18000 0 EST}
+ {-1157302800 -14400 1 EDT}
+ {-1144605600 -18000 0 EST}
+ {-1125853200 -14400 1 EDT}
+ {-1112551200 -18000 0 EST}
+ {-1094403600 -14400 1 EDT}
+ {-1081101600 -18000 0 EST}
+ {-1062954000 -14400 1 EDT}
+ {-1049652000 -18000 0 EST}
+ {-1031504400 -14400 1 EDT}
+ {-1018202400 -18000 0 EST}
+ {-1000054800 -14400 1 EDT}
+ {-986752800 -18000 0 EST}
+ {-968000400 -14400 1 EDT}
+ {-955303200 -18000 0 EST}
+ {-936550800 -14400 1 EDT}
+ {-923248800 -18000 0 EST}
+ {-905101200 -14400 1 EDT}
+ {-891799200 -18000 0 EST}
+ {-883594800 -18000 0 EST}
+ {-880218000 -14400 1 EWT}
+ {-769395600 -14400 1 EPT}
+ {-765396000 -18000 0 EST}
+ {-757364400 -18000 0 EST}
+ {-747248400 -14400 1 EDT}
+ {-733946400 -18000 0 EST}
+ {-715798800 -14400 1 EDT}
+ {-702496800 -18000 0 EST}
+ {-684349200 -14400 1 EDT}
+ {-671047200 -18000 0 EST}
+ {-652899600 -14400 1 EDT}
+ {-639597600 -18000 0 EST}
+ {-620845200 -14400 1 EDT}
+ {-608148000 -18000 0 EST}
+ {-589395600 -14400 1 EDT}
+ {-576093600 -18000 0 EST}
+ {-557946000 -14400 1 EDT}
+ {-544644000 -18000 0 EST}
+ {-526496400 -14400 1 EDT}
+ {-513194400 -18000 0 EST}
+ {-495046800 -14400 1 EDT}
+ {-481744800 -18000 0 EST}
+ {-463597200 -14400 1 EDT}
+ {-447271200 -18000 0 EST}
+ {-431542800 -14400 1 EDT}
+ {-415821600 -18000 0 EST}
+ {-400093200 -14400 1 EDT}
+ {-384372000 -18000 0 EST}
+ {-368643600 -14400 1 EDT}
+ {-352922400 -18000 0 EST}
+ {-337194000 -14400 1 EDT}
+ {-321472800 -18000 0 EST}
+ {-305744400 -14400 1 EDT}
+ {-289418400 -18000 0 EST}
+ {-273690000 -14400 1 EDT}
+ {-257968800 -18000 0 EST}
+ {-242240400 -14400 1 EDT}
+ {-226519200 -18000 0 EST}
+ {-210790800 -14400 1 EDT}
+ {-195069600 -18000 0 EST}
+ {-179341200 -14400 1 EDT}
+ {-163620000 -18000 0 EST}
+ {-147891600 -14400 1 EDT}
+ {-131565600 -18000 0 EST}
+ {-116442000 -14400 1 EDT}
+ {-100116000 -18000 0 EST}
+ {-94676400 -18000 0 EST}
+ {-84387600 -14400 1 EDT}
+ {-68666400 -18000 0 EST}
+ {-52938000 -14400 1 EDT}
+ {-37216800 -18000 0 EST}
+ {-21488400 -14400 1 EDT}
+ {-5767200 -18000 0 EST}
+ {9961200 -14400 1 EDT}
+ {25682400 -18000 0 EST}
+ {41410800 -14400 1 EDT}
+ {57736800 -18000 0 EST}
+ {73465200 -14400 1 EDT}
+ {89186400 -18000 0 EST}
+ {104914800 -14400 1 EDT}
+ {120636000 -18000 0 EST}
+ {126687600 -14400 1 EDT}
+ {152085600 -18000 0 EST}
+ {162370800 -14400 1 EDT}
+ {183535200 -18000 0 EST}
+ {199263600 -14400 1 EDT}
+ {215589600 -18000 0 EST}
+ {230713200 -14400 1 EDT}
+ {247039200 -18000 0 EST}
+ {262767600 -14400 1 EDT}
+ {278488800 -18000 0 EST}
+ {294217200 -14400 1 EDT}
+ {309938400 -18000 0 EST}
+ {325666800 -14400 1 EDT}
+ {341388000 -18000 0 EST}
+ {357116400 -14400 1 EDT}
+ {372837600 -18000 0 EST}
+ {388566000 -14400 1 EDT}
+ {404892000 -18000 0 EST}
+ {420015600 -14400 1 EDT}
+ {436341600 -18000 0 EST}
+ {452070000 -14400 1 EDT}
+ {467791200 -18000 0 EST}
+ {483519600 -14400 1 EDT}
+ {499240800 -18000 0 EST}
+ {514969200 -14400 1 EDT}
+ {530690400 -18000 0 EST}
+ {544604400 -14400 1 EDT}
+ {562140000 -18000 0 EST}
+ {576054000 -14400 1 EDT}
+ {594194400 -18000 0 EST}
+ {607503600 -14400 1 EDT}
+ {625644000 -18000 0 EST}
+ {638953200 -14400 1 EDT}
+ {657093600 -18000 0 EST}
+ {671007600 -14400 1 EDT}
+ {688543200 -18000 0 EST}
+ {702457200 -14400 1 EDT}
+ {719992800 -18000 0 EST}
+ {733906800 -14400 1 EDT}
+ {752047200 -18000 0 EST}
+ {765356400 -14400 1 EDT}
+ {783496800 -18000 0 EST}
+ {796806000 -14400 1 EDT}
+ {814946400 -18000 0 EST}
+ {828860400 -14400 1 EDT}
+ {846396000 -18000 0 EST}
+ {860310000 -14400 1 EDT}
+ {877845600 -18000 0 EST}
+ {891759600 -14400 1 EDT}
+ {909295200 -18000 0 EST}
+ {923209200 -14400 1 EDT}
+ {941349600 -18000 0 EST}
+ {954658800 -14400 1 EDT}
+ {972799200 -18000 0 EST}
+ {986108400 -14400 1 EDT}
+ {1004248800 -18000 0 EST}
+ {1018162800 -14400 1 EDT}
+ {1035698400 -18000 0 EST}
+ {1049612400 -14400 1 EDT}
+ {1067148000 -18000 0 EST}
+ {1081062000 -14400 1 EDT}
+ {1099202400 -18000 0 EST}
+ {1112511600 -14400 1 EDT}
+ {1130652000 -18000 0 EST}
+ {1143961200 -14400 1 EDT}
+ {1162101600 -18000 0 EST}
+ {1173596400 -14400 1 EDT}
+ {1194156000 -18000 0 EST}
+ {1205046000 -14400 1 EDT}
+ {1225605600 -18000 0 EST}
+ {1236495600 -14400 1 EDT}
+ {1257055200 -18000 0 EST}
+ {1268550000 -14400 1 EDT}
+ {1289109600 -18000 0 EST}
+ {1299999600 -14400 1 EDT}
+ {1320559200 -18000 0 EST}
+ {1331449200 -14400 1 EDT}
+ {1352008800 -18000 0 EST}
+ {1362898800 -14400 1 EDT}
+ {1383458400 -18000 0 EST}
+ {1394348400 -14400 1 EDT}
+ {1414908000 -18000 0 EST}
+ {1425798000 -14400 1 EDT}
+ {1446357600 -18000 0 EST}
+ {1457852400 -14400 1 EDT}
+ {1478412000 -18000 0 EST}
+ {1489302000 -14400 1 EDT}
+ {1509861600 -18000 0 EST}
+ {1520751600 -14400 1 EDT}
+ {1541311200 -18000 0 EST}
+ {1552201200 -14400 1 EDT}
+ {1572760800 -18000 0 EST}
+ {1583650800 -14400 1 EDT}
+ {1604210400 -18000 0 EST}
+ {1615705200 -14400 1 EDT}
+ {1636264800 -18000 0 EST}
+ {1647154800 -14400 1 EDT}
+ {1667714400 -18000 0 EST}
+ {1678604400 -14400 1 EDT}
+ {1699164000 -18000 0 EST}
+ {1710054000 -14400 1 EDT}
+ {1730613600 -18000 0 EST}
+ {1741503600 -14400 1 EDT}
+ {1762063200 -18000 0 EST}
+ {1772953200 -14400 1 EDT}
+ {1793512800 -18000 0 EST}
+ {1805007600 -14400 1 EDT}
+ {1825567200 -18000 0 EST}
+ {1836457200 -14400 1 EDT}
+ {1857016800 -18000 0 EST}
+ {1867906800 -14400 1 EDT}
+ {1888466400 -18000 0 EST}
+ {1899356400 -14400 1 EDT}
+ {1919916000 -18000 0 EST}
+ {1930806000 -14400 1 EDT}
+ {1951365600 -18000 0 EST}
+ {1962860400 -14400 1 EDT}
+ {1983420000 -18000 0 EST}
+ {1994310000 -14400 1 EDT}
+ {2014869600 -18000 0 EST}
+ {2025759600 -14400 1 EDT}
+ {2046319200 -18000 0 EST}
+ {2057209200 -14400 1 EDT}
+ {2077768800 -18000 0 EST}
+ {2088658800 -14400 1 EDT}
+ {2109218400 -18000 0 EST}
+ {2120108400 -14400 1 EDT}
+ {2140668000 -18000 0 EST}
+ {2152162800 -14400 1 EDT}
+ {2172722400 -18000 0 EST}
+ {2183612400 -14400 1 EDT}
+ {2204172000 -18000 0 EST}
+ {2215062000 -14400 1 EDT}
+ {2235621600 -18000 0 EST}
+ {2246511600 -14400 1 EDT}
+ {2267071200 -18000 0 EST}
+ {2277961200 -14400 1 EDT}
+ {2298520800 -18000 0 EST}
+ {2309410800 -14400 1 EDT}
+ {2329970400 -18000 0 EST}
+ {2341465200 -14400 1 EDT}
+ {2362024800 -18000 0 EST}
+ {2372914800 -14400 1 EDT}
+ {2393474400 -18000 0 EST}
+ {2404364400 -14400 1 EDT}
+ {2424924000 -18000 0 EST}
+ {2435814000 -14400 1 EDT}
+ {2456373600 -18000 0 EST}
+ {2467263600 -14400 1 EDT}
+ {2487823200 -18000 0 EST}
+ {2499318000 -14400 1 EDT}
+ {2519877600 -18000 0 EST}
+ {2530767600 -14400 1 EDT}
+ {2551327200 -18000 0 EST}
+ {2562217200 -14400 1 EDT}
+ {2582776800 -18000 0 EST}
+ {2593666800 -14400 1 EDT}
+ {2614226400 -18000 0 EST}
+ {2625116400 -14400 1 EDT}
+ {2645676000 -18000 0 EST}
+ {2656566000 -14400 1 EDT}
+ {2677125600 -18000 0 EST}
+ {2688620400 -14400 1 EDT}
+ {2709180000 -18000 0 EST}
+ {2720070000 -14400 1 EDT}
+ {2740629600 -18000 0 EST}
+ {2751519600 -14400 1 EDT}
+ {2772079200 -18000 0 EST}
+ {2782969200 -14400 1 EDT}
+ {2803528800 -18000 0 EST}
+ {2814418800 -14400 1 EDT}
+ {2834978400 -18000 0 EST}
+ {2846473200 -14400 1 EDT}
+ {2867032800 -18000 0 EST}
+ {2877922800 -14400 1 EDT}
+ {2898482400 -18000 0 EST}
+ {2909372400 -14400 1 EDT}
+ {2929932000 -18000 0 EST}
+ {2940822000 -14400 1 EDT}
+ {2961381600 -18000 0 EST}
+ {2972271600 -14400 1 EDT}
+ {2992831200 -18000 0 EST}
+ {3003721200 -14400 1 EDT}
+ {3024280800 -18000 0 EST}
+ {3035775600 -14400 1 EDT}
+ {3056335200 -18000 0 EST}
+ {3067225200 -14400 1 EDT}
+ {3087784800 -18000 0 EST}
+ {3098674800 -14400 1 EDT}
+ {3119234400 -18000 0 EST}
+ {3130124400 -14400 1 EDT}
+ {3150684000 -18000 0 EST}
+ {3161574000 -14400 1 EDT}
+ {3182133600 -18000 0 EST}
+ {3193023600 -14400 1 EDT}
+ {3213583200 -18000 0 EST}
+ {3225078000 -14400 1 EDT}
+ {3245637600 -18000 0 EST}
+ {3256527600 -14400 1 EDT}
+ {3277087200 -18000 0 EST}
+ {3287977200 -14400 1 EDT}
+ {3308536800 -18000 0 EST}
+ {3319426800 -14400 1 EDT}
+ {3339986400 -18000 0 EST}
+ {3350876400 -14400 1 EDT}
+ {3371436000 -18000 0 EST}
+ {3382930800 -14400 1 EDT}
+ {3403490400 -18000 0 EST}
+ {3414380400 -14400 1 EDT}
+ {3434940000 -18000 0 EST}
+ {3445830000 -14400 1 EDT}
+ {3466389600 -18000 0 EST}
+ {3477279600 -14400 1 EDT}
+ {3497839200 -18000 0 EST}
+ {3508729200 -14400 1 EDT}
+ {3529288800 -18000 0 EST}
+ {3540178800 -14400 1 EDT}
+ {3560738400 -18000 0 EST}
+ {3572233200 -14400 1 EDT}
+ {3592792800 -18000 0 EST}
+ {3603682800 -14400 1 EDT}
+ {3624242400 -18000 0 EST}
+ {3635132400 -14400 1 EDT}
+ {3655692000 -18000 0 EST}
+ {3666582000 -14400 1 EDT}
+ {3687141600 -18000 0 EST}
+ {3698031600 -14400 1 EDT}
+ {3718591200 -18000 0 EST}
+ {3730086000 -14400 1 EDT}
+ {3750645600 -18000 0 EST}
+ {3761535600 -14400 1 EDT}
+ {3782095200 -18000 0 EST}
+ {3792985200 -14400 1 EDT}
+ {3813544800 -18000 0 EST}
+ {3824434800 -14400 1 EDT}
+ {3844994400 -18000 0 EST}
+ {3855884400 -14400 1 EDT}
+ {3876444000 -18000 0 EST}
+ {3887334000 -14400 1 EDT}
+ {3907893600 -18000 0 EST}
+ {3919388400 -14400 1 EDT}
+ {3939948000 -18000 0 EST}
+ {3950838000 -14400 1 EDT}
+ {3971397600 -18000 0 EST}
+ {3982287600 -14400 1 EDT}
+ {4002847200 -18000 0 EST}
+ {4013737200 -14400 1 EDT}
+ {4034296800 -18000 0 EST}
+ {4045186800 -14400 1 EDT}
+ {4065746400 -18000 0 EST}
+ {4076636400 -14400 1 EDT}
+ {4097196000 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Nipigon b/library/tzdata/America/Nipigon
new file mode 100644
index 0000000..e98bb8c
--- /dev/null
+++ b/library/tzdata/America/Nipigon
@@ -0,0 +1,264 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Nipigon) {
+ {-9223372036854775808 -21184 0 LMT}
+ {-2366734016 -18000 0 EST}
+ {-1632070800 -14400 1 EDT}
+ {-1614794400 -18000 0 EST}
+ {-923252400 -14400 1 EDT}
+ {-880218000 -14400 0 EWT}
+ {-769395600 -14400 1 EPT}
+ {-765396000 -18000 0 EST}
+ {136364400 -14400 1 EDT}
+ {152085600 -18000 0 EST}
+ {167814000 -14400 1 EDT}
+ {183535200 -18000 0 EST}
+ {199263600 -14400 1 EDT}
+ {215589600 -18000 0 EST}
+ {230713200 -14400 1 EDT}
+ {247039200 -18000 0 EST}
+ {262767600 -14400 1 EDT}
+ {278488800 -18000 0 EST}
+ {294217200 -14400 1 EDT}
+ {309938400 -18000 0 EST}
+ {325666800 -14400 1 EDT}
+ {341388000 -18000 0 EST}
+ {357116400 -14400 1 EDT}
+ {372837600 -18000 0 EST}
+ {388566000 -14400 1 EDT}
+ {404892000 -18000 0 EST}
+ {420015600 -14400 1 EDT}
+ {436341600 -18000 0 EST}
+ {452070000 -14400 1 EDT}
+ {467791200 -18000 0 EST}
+ {483519600 -14400 1 EDT}
+ {499240800 -18000 0 EST}
+ {514969200 -14400 1 EDT}
+ {530690400 -18000 0 EST}
+ {544604400 -14400 1 EDT}
+ {562140000 -18000 0 EST}
+ {576054000 -14400 1 EDT}
+ {594194400 -18000 0 EST}
+ {607503600 -14400 1 EDT}
+ {625644000 -18000 0 EST}
+ {638953200 -14400 1 EDT}
+ {657093600 -18000 0 EST}
+ {671007600 -14400 1 EDT}
+ {688543200 -18000 0 EST}
+ {702457200 -14400 1 EDT}
+ {719992800 -18000 0 EST}
+ {733906800 -14400 1 EDT}
+ {752047200 -18000 0 EST}
+ {765356400 -14400 1 EDT}
+ {783496800 -18000 0 EST}
+ {796806000 -14400 1 EDT}
+ {814946400 -18000 0 EST}
+ {828860400 -14400 1 EDT}
+ {846396000 -18000 0 EST}
+ {860310000 -14400 1 EDT}
+ {877845600 -18000 0 EST}
+ {891759600 -14400 1 EDT}
+ {909295200 -18000 0 EST}
+ {923209200 -14400 1 EDT}
+ {941349600 -18000 0 EST}
+ {954658800 -14400 1 EDT}
+ {972799200 -18000 0 EST}
+ {986108400 -14400 1 EDT}
+ {1004248800 -18000 0 EST}
+ {1018162800 -14400 1 EDT}
+ {1035698400 -18000 0 EST}
+ {1049612400 -14400 1 EDT}
+ {1067148000 -18000 0 EST}
+ {1081062000 -14400 1 EDT}
+ {1099202400 -18000 0 EST}
+ {1112511600 -14400 1 EDT}
+ {1130652000 -18000 0 EST}
+ {1143961200 -14400 1 EDT}
+ {1162101600 -18000 0 EST}
+ {1173596400 -14400 1 EDT}
+ {1194156000 -18000 0 EST}
+ {1205046000 -14400 1 EDT}
+ {1225605600 -18000 0 EST}
+ {1236495600 -14400 1 EDT}
+ {1257055200 -18000 0 EST}
+ {1268550000 -14400 1 EDT}
+ {1289109600 -18000 0 EST}
+ {1299999600 -14400 1 EDT}
+ {1320559200 -18000 0 EST}
+ {1331449200 -14400 1 EDT}
+ {1352008800 -18000 0 EST}
+ {1362898800 -14400 1 EDT}
+ {1383458400 -18000 0 EST}
+ {1394348400 -14400 1 EDT}
+ {1414908000 -18000 0 EST}
+ {1425798000 -14400 1 EDT}
+ {1446357600 -18000 0 EST}
+ {1457852400 -14400 1 EDT}
+ {1478412000 -18000 0 EST}
+ {1489302000 -14400 1 EDT}
+ {1509861600 -18000 0 EST}
+ {1520751600 -14400 1 EDT}
+ {1541311200 -18000 0 EST}
+ {1552201200 -14400 1 EDT}
+ {1572760800 -18000 0 EST}
+ {1583650800 -14400 1 EDT}
+ {1604210400 -18000 0 EST}
+ {1615705200 -14400 1 EDT}
+ {1636264800 -18000 0 EST}
+ {1647154800 -14400 1 EDT}
+ {1667714400 -18000 0 EST}
+ {1678604400 -14400 1 EDT}
+ {1699164000 -18000 0 EST}
+ {1710054000 -14400 1 EDT}
+ {1730613600 -18000 0 EST}
+ {1741503600 -14400 1 EDT}
+ {1762063200 -18000 0 EST}
+ {1772953200 -14400 1 EDT}
+ {1793512800 -18000 0 EST}
+ {1805007600 -14400 1 EDT}
+ {1825567200 -18000 0 EST}
+ {1836457200 -14400 1 EDT}
+ {1857016800 -18000 0 EST}
+ {1867906800 -14400 1 EDT}
+ {1888466400 -18000 0 EST}
+ {1899356400 -14400 1 EDT}
+ {1919916000 -18000 0 EST}
+ {1930806000 -14400 1 EDT}
+ {1951365600 -18000 0 EST}
+ {1962860400 -14400 1 EDT}
+ {1983420000 -18000 0 EST}
+ {1994310000 -14400 1 EDT}
+ {2014869600 -18000 0 EST}
+ {2025759600 -14400 1 EDT}
+ {2046319200 -18000 0 EST}
+ {2057209200 -14400 1 EDT}
+ {2077768800 -18000 0 EST}
+ {2088658800 -14400 1 EDT}
+ {2109218400 -18000 0 EST}
+ {2120108400 -14400 1 EDT}
+ {2140668000 -18000 0 EST}
+ {2152162800 -14400 1 EDT}
+ {2172722400 -18000 0 EST}
+ {2183612400 -14400 1 EDT}
+ {2204172000 -18000 0 EST}
+ {2215062000 -14400 1 EDT}
+ {2235621600 -18000 0 EST}
+ {2246511600 -14400 1 EDT}
+ {2267071200 -18000 0 EST}
+ {2277961200 -14400 1 EDT}
+ {2298520800 -18000 0 EST}
+ {2309410800 -14400 1 EDT}
+ {2329970400 -18000 0 EST}
+ {2341465200 -14400 1 EDT}
+ {2362024800 -18000 0 EST}
+ {2372914800 -14400 1 EDT}
+ {2393474400 -18000 0 EST}
+ {2404364400 -14400 1 EDT}
+ {2424924000 -18000 0 EST}
+ {2435814000 -14400 1 EDT}
+ {2456373600 -18000 0 EST}
+ {2467263600 -14400 1 EDT}
+ {2487823200 -18000 0 EST}
+ {2499318000 -14400 1 EDT}
+ {2519877600 -18000 0 EST}
+ {2530767600 -14400 1 EDT}
+ {2551327200 -18000 0 EST}
+ {2562217200 -14400 1 EDT}
+ {2582776800 -18000 0 EST}
+ {2593666800 -14400 1 EDT}
+ {2614226400 -18000 0 EST}
+ {2625116400 -14400 1 EDT}
+ {2645676000 -18000 0 EST}
+ {2656566000 -14400 1 EDT}
+ {2677125600 -18000 0 EST}
+ {2688620400 -14400 1 EDT}
+ {2709180000 -18000 0 EST}
+ {2720070000 -14400 1 EDT}
+ {2740629600 -18000 0 EST}
+ {2751519600 -14400 1 EDT}
+ {2772079200 -18000 0 EST}
+ {2782969200 -14400 1 EDT}
+ {2803528800 -18000 0 EST}
+ {2814418800 -14400 1 EDT}
+ {2834978400 -18000 0 EST}
+ {2846473200 -14400 1 EDT}
+ {2867032800 -18000 0 EST}
+ {2877922800 -14400 1 EDT}
+ {2898482400 -18000 0 EST}
+ {2909372400 -14400 1 EDT}
+ {2929932000 -18000 0 EST}
+ {2940822000 -14400 1 EDT}
+ {2961381600 -18000 0 EST}
+ {2972271600 -14400 1 EDT}
+ {2992831200 -18000 0 EST}
+ {3003721200 -14400 1 EDT}
+ {3024280800 -18000 0 EST}
+ {3035775600 -14400 1 EDT}
+ {3056335200 -18000 0 EST}
+ {3067225200 -14400 1 EDT}
+ {3087784800 -18000 0 EST}
+ {3098674800 -14400 1 EDT}
+ {3119234400 -18000 0 EST}
+ {3130124400 -14400 1 EDT}
+ {3150684000 -18000 0 EST}
+ {3161574000 -14400 1 EDT}
+ {3182133600 -18000 0 EST}
+ {3193023600 -14400 1 EDT}
+ {3213583200 -18000 0 EST}
+ {3225078000 -14400 1 EDT}
+ {3245637600 -18000 0 EST}
+ {3256527600 -14400 1 EDT}
+ {3277087200 -18000 0 EST}
+ {3287977200 -14400 1 EDT}
+ {3308536800 -18000 0 EST}
+ {3319426800 -14400 1 EDT}
+ {3339986400 -18000 0 EST}
+ {3350876400 -14400 1 EDT}
+ {3371436000 -18000 0 EST}
+ {3382930800 -14400 1 EDT}
+ {3403490400 -18000 0 EST}
+ {3414380400 -14400 1 EDT}
+ {3434940000 -18000 0 EST}
+ {3445830000 -14400 1 EDT}
+ {3466389600 -18000 0 EST}
+ {3477279600 -14400 1 EDT}
+ {3497839200 -18000 0 EST}
+ {3508729200 -14400 1 EDT}
+ {3529288800 -18000 0 EST}
+ {3540178800 -14400 1 EDT}
+ {3560738400 -18000 0 EST}
+ {3572233200 -14400 1 EDT}
+ {3592792800 -18000 0 EST}
+ {3603682800 -14400 1 EDT}
+ {3624242400 -18000 0 EST}
+ {3635132400 -14400 1 EDT}
+ {3655692000 -18000 0 EST}
+ {3666582000 -14400 1 EDT}
+ {3687141600 -18000 0 EST}
+ {3698031600 -14400 1 EDT}
+ {3718591200 -18000 0 EST}
+ {3730086000 -14400 1 EDT}
+ {3750645600 -18000 0 EST}
+ {3761535600 -14400 1 EDT}
+ {3782095200 -18000 0 EST}
+ {3792985200 -14400 1 EDT}
+ {3813544800 -18000 0 EST}
+ {3824434800 -14400 1 EDT}
+ {3844994400 -18000 0 EST}
+ {3855884400 -14400 1 EDT}
+ {3876444000 -18000 0 EST}
+ {3887334000 -14400 1 EDT}
+ {3907893600 -18000 0 EST}
+ {3919388400 -14400 1 EDT}
+ {3939948000 -18000 0 EST}
+ {3950838000 -14400 1 EDT}
+ {3971397600 -18000 0 EST}
+ {3982287600 -14400 1 EDT}
+ {4002847200 -18000 0 EST}
+ {4013737200 -14400 1 EDT}
+ {4034296800 -18000 0 EST}
+ {4045186800 -14400 1 EDT}
+ {4065746400 -18000 0 EST}
+ {4076636400 -14400 1 EDT}
+ {4097196000 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Nome b/library/tzdata/America/Nome
new file mode 100644
index 0000000..c095b79
--- /dev/null
+++ b/library/tzdata/America/Nome
@@ -0,0 +1,276 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Nome) {
+ {-9223372036854775808 46701 0 LMT}
+ {-3225358701 -39698 0 LMT}
+ {-2188947502 -39600 0 NST}
+ {-883573200 -39600 0 NST}
+ {-880196400 -36000 1 NWT}
+ {-769395600 -36000 1 NPT}
+ {-765374400 -39600 0 NST}
+ {-757342800 -39600 0 NST}
+ {-86878800 -39600 0 BST}
+ {-31496400 -39600 0 BST}
+ {-21466800 -36000 1 BDT}
+ {-5745600 -39600 0 BST}
+ {9982800 -36000 1 BDT}
+ {25704000 -39600 0 BST}
+ {41432400 -36000 1 BDT}
+ {57758400 -39600 0 BST}
+ {73486800 -36000 1 BDT}
+ {89208000 -39600 0 BST}
+ {104936400 -36000 1 BDT}
+ {120657600 -39600 0 BST}
+ {126709200 -36000 1 BDT}
+ {152107200 -39600 0 BST}
+ {162392400 -36000 1 BDT}
+ {183556800 -39600 0 BST}
+ {199285200 -36000 1 BDT}
+ {215611200 -39600 0 BST}
+ {230734800 -36000 1 BDT}
+ {247060800 -39600 0 BST}
+ {262789200 -36000 1 BDT}
+ {278510400 -39600 0 BST}
+ {294238800 -36000 1 BDT}
+ {309960000 -39600 0 BST}
+ {325688400 -36000 1 BDT}
+ {341409600 -39600 0 BST}
+ {357138000 -36000 1 BDT}
+ {372859200 -39600 0 BST}
+ {388587600 -36000 1 BDT}
+ {404913600 -39600 0 BST}
+ {420037200 -36000 1 BDT}
+ {439030800 -32400 0 AKST}
+ {452084400 -28800 1 AKDT}
+ {467805600 -32400 0 AKST}
+ {483534000 -28800 1 AKDT}
+ {499255200 -32400 0 AKST}
+ {514983600 -28800 1 AKDT}
+ {530704800 -32400 0 AKST}
+ {544618800 -28800 1 AKDT}
+ {562154400 -32400 0 AKST}
+ {576068400 -28800 1 AKDT}
+ {594208800 -32400 0 AKST}
+ {607518000 -28800 1 AKDT}
+ {625658400 -32400 0 AKST}
+ {638967600 -28800 1 AKDT}
+ {657108000 -32400 0 AKST}
+ {671022000 -28800 1 AKDT}
+ {688557600 -32400 0 AKST}
+ {702471600 -28800 1 AKDT}
+ {720007200 -32400 0 AKST}
+ {733921200 -28800 1 AKDT}
+ {752061600 -32400 0 AKST}
+ {765370800 -28800 1 AKDT}
+ {783511200 -32400 0 AKST}
+ {796820400 -28800 1 AKDT}
+ {814960800 -32400 0 AKST}
+ {828874800 -28800 1 AKDT}
+ {846410400 -32400 0 AKST}
+ {860324400 -28800 1 AKDT}
+ {877860000 -32400 0 AKST}
+ {891774000 -28800 1 AKDT}
+ {909309600 -32400 0 AKST}
+ {923223600 -28800 1 AKDT}
+ {941364000 -32400 0 AKST}
+ {954673200 -28800 1 AKDT}
+ {972813600 -32400 0 AKST}
+ {986122800 -28800 1 AKDT}
+ {1004263200 -32400 0 AKST}
+ {1018177200 -28800 1 AKDT}
+ {1035712800 -32400 0 AKST}
+ {1049626800 -28800 1 AKDT}
+ {1067162400 -32400 0 AKST}
+ {1081076400 -28800 1 AKDT}
+ {1099216800 -32400 0 AKST}
+ {1112526000 -28800 1 AKDT}
+ {1130666400 -32400 0 AKST}
+ {1143975600 -28800 1 AKDT}
+ {1162116000 -32400 0 AKST}
+ {1173610800 -28800 1 AKDT}
+ {1194170400 -32400 0 AKST}
+ {1205060400 -28800 1 AKDT}
+ {1225620000 -32400 0 AKST}
+ {1236510000 -28800 1 AKDT}
+ {1257069600 -32400 0 AKST}
+ {1268564400 -28800 1 AKDT}
+ {1289124000 -32400 0 AKST}
+ {1300014000 -28800 1 AKDT}
+ {1320573600 -32400 0 AKST}
+ {1331463600 -28800 1 AKDT}
+ {1352023200 -32400 0 AKST}
+ {1362913200 -28800 1 AKDT}
+ {1383472800 -32400 0 AKST}
+ {1394362800 -28800 1 AKDT}
+ {1414922400 -32400 0 AKST}
+ {1425812400 -28800 1 AKDT}
+ {1446372000 -32400 0 AKST}
+ {1457866800 -28800 1 AKDT}
+ {1478426400 -32400 0 AKST}
+ {1489316400 -28800 1 AKDT}
+ {1509876000 -32400 0 AKST}
+ {1520766000 -28800 1 AKDT}
+ {1541325600 -32400 0 AKST}
+ {1552215600 -28800 1 AKDT}
+ {1572775200 -32400 0 AKST}
+ {1583665200 -28800 1 AKDT}
+ {1604224800 -32400 0 AKST}
+ {1615719600 -28800 1 AKDT}
+ {1636279200 -32400 0 AKST}
+ {1647169200 -28800 1 AKDT}
+ {1667728800 -32400 0 AKST}
+ {1678618800 -28800 1 AKDT}
+ {1699178400 -32400 0 AKST}
+ {1710068400 -28800 1 AKDT}
+ {1730628000 -32400 0 AKST}
+ {1741518000 -28800 1 AKDT}
+ {1762077600 -32400 0 AKST}
+ {1772967600 -28800 1 AKDT}
+ {1793527200 -32400 0 AKST}
+ {1805022000 -28800 1 AKDT}
+ {1825581600 -32400 0 AKST}
+ {1836471600 -28800 1 AKDT}
+ {1857031200 -32400 0 AKST}
+ {1867921200 -28800 1 AKDT}
+ {1888480800 -32400 0 AKST}
+ {1899370800 -28800 1 AKDT}
+ {1919930400 -32400 0 AKST}
+ {1930820400 -28800 1 AKDT}
+ {1951380000 -32400 0 AKST}
+ {1962874800 -28800 1 AKDT}
+ {1983434400 -32400 0 AKST}
+ {1994324400 -28800 1 AKDT}
+ {2014884000 -32400 0 AKST}
+ {2025774000 -28800 1 AKDT}
+ {2046333600 -32400 0 AKST}
+ {2057223600 -28800 1 AKDT}
+ {2077783200 -32400 0 AKST}
+ {2088673200 -28800 1 AKDT}
+ {2109232800 -32400 0 AKST}
+ {2120122800 -28800 1 AKDT}
+ {2140682400 -32400 0 AKST}
+ {2152177200 -28800 1 AKDT}
+ {2172736800 -32400 0 AKST}
+ {2183626800 -28800 1 AKDT}
+ {2204186400 -32400 0 AKST}
+ {2215076400 -28800 1 AKDT}
+ {2235636000 -32400 0 AKST}
+ {2246526000 -28800 1 AKDT}
+ {2267085600 -32400 0 AKST}
+ {2277975600 -28800 1 AKDT}
+ {2298535200 -32400 0 AKST}
+ {2309425200 -28800 1 AKDT}
+ {2329984800 -32400 0 AKST}
+ {2341479600 -28800 1 AKDT}
+ {2362039200 -32400 0 AKST}
+ {2372929200 -28800 1 AKDT}
+ {2393488800 -32400 0 AKST}
+ {2404378800 -28800 1 AKDT}
+ {2424938400 -32400 0 AKST}
+ {2435828400 -28800 1 AKDT}
+ {2456388000 -32400 0 AKST}
+ {2467278000 -28800 1 AKDT}
+ {2487837600 -32400 0 AKST}
+ {2499332400 -28800 1 AKDT}
+ {2519892000 -32400 0 AKST}
+ {2530782000 -28800 1 AKDT}
+ {2551341600 -32400 0 AKST}
+ {2562231600 -28800 1 AKDT}
+ {2582791200 -32400 0 AKST}
+ {2593681200 -28800 1 AKDT}
+ {2614240800 -32400 0 AKST}
+ {2625130800 -28800 1 AKDT}
+ {2645690400 -32400 0 AKST}
+ {2656580400 -28800 1 AKDT}
+ {2677140000 -32400 0 AKST}
+ {2688634800 -28800 1 AKDT}
+ {2709194400 -32400 0 AKST}
+ {2720084400 -28800 1 AKDT}
+ {2740644000 -32400 0 AKST}
+ {2751534000 -28800 1 AKDT}
+ {2772093600 -32400 0 AKST}
+ {2782983600 -28800 1 AKDT}
+ {2803543200 -32400 0 AKST}
+ {2814433200 -28800 1 AKDT}
+ {2834992800 -32400 0 AKST}
+ {2846487600 -28800 1 AKDT}
+ {2867047200 -32400 0 AKST}
+ {2877937200 -28800 1 AKDT}
+ {2898496800 -32400 0 AKST}
+ {2909386800 -28800 1 AKDT}
+ {2929946400 -32400 0 AKST}
+ {2940836400 -28800 1 AKDT}
+ {2961396000 -32400 0 AKST}
+ {2972286000 -28800 1 AKDT}
+ {2992845600 -32400 0 AKST}
+ {3003735600 -28800 1 AKDT}
+ {3024295200 -32400 0 AKST}
+ {3035790000 -28800 1 AKDT}
+ {3056349600 -32400 0 AKST}
+ {3067239600 -28800 1 AKDT}
+ {3087799200 -32400 0 AKST}
+ {3098689200 -28800 1 AKDT}
+ {3119248800 -32400 0 AKST}
+ {3130138800 -28800 1 AKDT}
+ {3150698400 -32400 0 AKST}
+ {3161588400 -28800 1 AKDT}
+ {3182148000 -32400 0 AKST}
+ {3193038000 -28800 1 AKDT}
+ {3213597600 -32400 0 AKST}
+ {3225092400 -28800 1 AKDT}
+ {3245652000 -32400 0 AKST}
+ {3256542000 -28800 1 AKDT}
+ {3277101600 -32400 0 AKST}
+ {3287991600 -28800 1 AKDT}
+ {3308551200 -32400 0 AKST}
+ {3319441200 -28800 1 AKDT}
+ {3340000800 -32400 0 AKST}
+ {3350890800 -28800 1 AKDT}
+ {3371450400 -32400 0 AKST}
+ {3382945200 -28800 1 AKDT}
+ {3403504800 -32400 0 AKST}
+ {3414394800 -28800 1 AKDT}
+ {3434954400 -32400 0 AKST}
+ {3445844400 -28800 1 AKDT}
+ {3466404000 -32400 0 AKST}
+ {3477294000 -28800 1 AKDT}
+ {3497853600 -32400 0 AKST}
+ {3508743600 -28800 1 AKDT}
+ {3529303200 -32400 0 AKST}
+ {3540193200 -28800 1 AKDT}
+ {3560752800 -32400 0 AKST}
+ {3572247600 -28800 1 AKDT}
+ {3592807200 -32400 0 AKST}
+ {3603697200 -28800 1 AKDT}
+ {3624256800 -32400 0 AKST}
+ {3635146800 -28800 1 AKDT}
+ {3655706400 -32400 0 AKST}
+ {3666596400 -28800 1 AKDT}
+ {3687156000 -32400 0 AKST}
+ {3698046000 -28800 1 AKDT}
+ {3718605600 -32400 0 AKST}
+ {3730100400 -28800 1 AKDT}
+ {3750660000 -32400 0 AKST}
+ {3761550000 -28800 1 AKDT}
+ {3782109600 -32400 0 AKST}
+ {3792999600 -28800 1 AKDT}
+ {3813559200 -32400 0 AKST}
+ {3824449200 -28800 1 AKDT}
+ {3845008800 -32400 0 AKST}
+ {3855898800 -28800 1 AKDT}
+ {3876458400 -32400 0 AKST}
+ {3887348400 -28800 1 AKDT}
+ {3907908000 -32400 0 AKST}
+ {3919402800 -28800 1 AKDT}
+ {3939962400 -32400 0 AKST}
+ {3950852400 -28800 1 AKDT}
+ {3971412000 -32400 0 AKST}
+ {3982302000 -28800 1 AKDT}
+ {4002861600 -32400 0 AKST}
+ {4013751600 -28800 1 AKDT}
+ {4034311200 -32400 0 AKST}
+ {4045201200 -28800 1 AKDT}
+ {4065760800 -32400 0 AKST}
+ {4076650800 -28800 1 AKDT}
+ {4097210400 -32400 0 AKST}
+}
diff --git a/library/tzdata/America/Noronha b/library/tzdata/America/Noronha
new file mode 100644
index 0000000..94d6f42
--- /dev/null
+++ b/library/tzdata/America/Noronha
@@ -0,0 +1,48 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Noronha) {
+ {-9223372036854775808 -7780 0 LMT}
+ {-1767217820 -7200 0 FNT}
+ {-1206961200 -3600 1 FNST}
+ {-1191366000 -7200 0 FNT}
+ {-1175378400 -3600 1 FNST}
+ {-1159830000 -7200 0 FNT}
+ {-633823200 -3600 1 FNST}
+ {-622072800 -7200 0 FNT}
+ {-602287200 -3600 1 FNST}
+ {-591836400 -7200 0 FNT}
+ {-570751200 -3600 1 FNST}
+ {-560214000 -7200 0 FNT}
+ {-539128800 -3600 1 FNST}
+ {-531356400 -7200 0 FNT}
+ {-191368800 -3600 1 FNST}
+ {-184201200 -7200 0 FNT}
+ {-155167200 -3600 1 FNST}
+ {-150073200 -7200 0 FNT}
+ {-128901600 -3600 1 FNST}
+ {-121129200 -7200 0 FNT}
+ {-99957600 -3600 1 FNST}
+ {-89593200 -7200 0 FNT}
+ {-68421600 -3600 1 FNST}
+ {-57970800 -7200 0 FNT}
+ {499744800 -3600 1 FNST}
+ {511232400 -7200 0 FNT}
+ {530589600 -3600 1 FNST}
+ {540262800 -7200 0 FNT}
+ {562125600 -3600 1 FNST}
+ {571194000 -7200 0 FNT}
+ {592970400 -3600 1 FNST}
+ {602038800 -7200 0 FNT}
+ {624420000 -3600 1 FNST}
+ {634698000 -7200 0 FNT}
+ {653533200 -7200 0 FNT}
+ {938656800 -7200 0 FNT}
+ {938916000 -3600 1 FNST}
+ {951613200 -7200 0 FNT}
+ {970970400 -3600 1 FNST}
+ {971571600 -7200 0 FNT}
+ {1000346400 -7200 0 FNT}
+ {1003024800 -3600 1 FNST}
+ {1013907600 -7200 0 FNT}
+ {1033434000 -7200 0 FNT}
+}
diff --git a/library/tzdata/America/North_Dakota/Beulah b/library/tzdata/America/North_Dakota/Beulah
new file mode 100644
index 0000000..95407c6
--- /dev/null
+++ b/library/tzdata/America/North_Dakota/Beulah
@@ -0,0 +1,279 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/North_Dakota/Beulah) {
+ {-9223372036854775808 -24427 0 LMT}
+ {-2717643600 -25200 0 MST}
+ {-1633273200 -21600 1 MDT}
+ {-1615132800 -25200 0 MST}
+ {-1601823600 -21600 1 MDT}
+ {-1583683200 -25200 0 MST}
+ {-880210800 -21600 1 MWT}
+ {-769395600 -21600 1 MPT}
+ {-765388800 -25200 0 MST}
+ {-84380400 -21600 1 MDT}
+ {-68659200 -25200 0 MST}
+ {-52930800 -21600 1 MDT}
+ {-37209600 -25200 0 MST}
+ {-21481200 -21600 1 MDT}
+ {-5760000 -25200 0 MST}
+ {9968400 -21600 1 MDT}
+ {25689600 -25200 0 MST}
+ {41418000 -21600 1 MDT}
+ {57744000 -25200 0 MST}
+ {73472400 -21600 1 MDT}
+ {89193600 -25200 0 MST}
+ {104922000 -21600 1 MDT}
+ {120643200 -25200 0 MST}
+ {126694800 -21600 1 MDT}
+ {152092800 -25200 0 MST}
+ {162378000 -21600 1 MDT}
+ {183542400 -25200 0 MST}
+ {199270800 -21600 1 MDT}
+ {215596800 -25200 0 MST}
+ {230720400 -21600 1 MDT}
+ {247046400 -25200 0 MST}
+ {262774800 -21600 1 MDT}
+ {278496000 -25200 0 MST}
+ {294224400 -21600 1 MDT}
+ {309945600 -25200 0 MST}
+ {325674000 -21600 1 MDT}
+ {341395200 -25200 0 MST}
+ {357123600 -21600 1 MDT}
+ {372844800 -25200 0 MST}
+ {388573200 -21600 1 MDT}
+ {404899200 -25200 0 MST}
+ {420022800 -21600 1 MDT}
+ {436348800 -25200 0 MST}
+ {452077200 -21600 1 MDT}
+ {467798400 -25200 0 MST}
+ {483526800 -21600 1 MDT}
+ {499248000 -25200 0 MST}
+ {514976400 -21600 1 MDT}
+ {530697600 -25200 0 MST}
+ {544611600 -21600 1 MDT}
+ {562147200 -25200 0 MST}
+ {576061200 -21600 1 MDT}
+ {594201600 -25200 0 MST}
+ {607510800 -21600 1 MDT}
+ {625651200 -25200 0 MST}
+ {638960400 -21600 1 MDT}
+ {657100800 -25200 0 MST}
+ {671014800 -21600 1 MDT}
+ {688550400 -25200 0 MST}
+ {702464400 -21600 1 MDT}
+ {720000000 -25200 0 MST}
+ {733914000 -21600 1 MDT}
+ {752054400 -25200 0 MST}
+ {765363600 -21600 1 MDT}
+ {783504000 -25200 0 MST}
+ {796813200 -21600 1 MDT}
+ {814953600 -25200 0 MST}
+ {828867600 -21600 1 MDT}
+ {846403200 -25200 0 MST}
+ {860317200 -21600 1 MDT}
+ {877852800 -25200 0 MST}
+ {891766800 -21600 1 MDT}
+ {909302400 -25200 0 MST}
+ {923216400 -21600 1 MDT}
+ {941356800 -25200 0 MST}
+ {954666000 -21600 1 MDT}
+ {972806400 -25200 0 MST}
+ {986115600 -21600 1 MDT}
+ {1004256000 -25200 0 MST}
+ {1018170000 -21600 1 MDT}
+ {1035705600 -25200 0 MST}
+ {1049619600 -21600 1 MDT}
+ {1067155200 -25200 0 MST}
+ {1081069200 -21600 1 MDT}
+ {1099209600 -25200 0 MST}
+ {1112518800 -21600 1 MDT}
+ {1130659200 -25200 0 MST}
+ {1143968400 -21600 1 MDT}
+ {1162108800 -25200 0 MST}
+ {1173603600 -21600 1 MDT}
+ {1194163200 -25200 0 MST}
+ {1205053200 -21600 1 MDT}
+ {1225612800 -25200 0 MST}
+ {1236502800 -21600 1 MDT}
+ {1257062400 -25200 0 MST}
+ {1268557200 -21600 1 MDT}
+ {1289120400 -21600 0 CST}
+ {1300003200 -18000 1 CDT}
+ {1320562800 -21600 0 CST}
+ {1331452800 -18000 1 CDT}
+ {1352012400 -21600 0 CST}
+ {1362902400 -18000 1 CDT}
+ {1383462000 -21600 0 CST}
+ {1394352000 -18000 1 CDT}
+ {1414911600 -21600 0 CST}
+ {1425801600 -18000 1 CDT}
+ {1446361200 -21600 0 CST}
+ {1457856000 -18000 1 CDT}
+ {1478415600 -21600 0 CST}
+ {1489305600 -18000 1 CDT}
+ {1509865200 -21600 0 CST}
+ {1520755200 -18000 1 CDT}
+ {1541314800 -21600 0 CST}
+ {1552204800 -18000 1 CDT}
+ {1572764400 -21600 0 CST}
+ {1583654400 -18000 1 CDT}
+ {1604214000 -21600 0 CST}
+ {1615708800 -18000 1 CDT}
+ {1636268400 -21600 0 CST}
+ {1647158400 -18000 1 CDT}
+ {1667718000 -21600 0 CST}
+ {1678608000 -18000 1 CDT}
+ {1699167600 -21600 0 CST}
+ {1710057600 -18000 1 CDT}
+ {1730617200 -21600 0 CST}
+ {1741507200 -18000 1 CDT}
+ {1762066800 -21600 0 CST}
+ {1772956800 -18000 1 CDT}
+ {1793516400 -21600 0 CST}
+ {1805011200 -18000 1 CDT}
+ {1825570800 -21600 0 CST}
+ {1836460800 -18000 1 CDT}
+ {1857020400 -21600 0 CST}
+ {1867910400 -18000 1 CDT}
+ {1888470000 -21600 0 CST}
+ {1899360000 -18000 1 CDT}
+ {1919919600 -21600 0 CST}
+ {1930809600 -18000 1 CDT}
+ {1951369200 -21600 0 CST}
+ {1962864000 -18000 1 CDT}
+ {1983423600 -21600 0 CST}
+ {1994313600 -18000 1 CDT}
+ {2014873200 -21600 0 CST}
+ {2025763200 -18000 1 CDT}
+ {2046322800 -21600 0 CST}
+ {2057212800 -18000 1 CDT}
+ {2077772400 -21600 0 CST}
+ {2088662400 -18000 1 CDT}
+ {2109222000 -21600 0 CST}
+ {2120112000 -18000 1 CDT}
+ {2140671600 -21600 0 CST}
+ {2152166400 -18000 1 CDT}
+ {2172726000 -21600 0 CST}
+ {2183616000 -18000 1 CDT}
+ {2204175600 -21600 0 CST}
+ {2215065600 -18000 1 CDT}
+ {2235625200 -21600 0 CST}
+ {2246515200 -18000 1 CDT}
+ {2267074800 -21600 0 CST}
+ {2277964800 -18000 1 CDT}
+ {2298524400 -21600 0 CST}
+ {2309414400 -18000 1 CDT}
+ {2329974000 -21600 0 CST}
+ {2341468800 -18000 1 CDT}
+ {2362028400 -21600 0 CST}
+ {2372918400 -18000 1 CDT}
+ {2393478000 -21600 0 CST}
+ {2404368000 -18000 1 CDT}
+ {2424927600 -21600 0 CST}
+ {2435817600 -18000 1 CDT}
+ {2456377200 -21600 0 CST}
+ {2467267200 -18000 1 CDT}
+ {2487826800 -21600 0 CST}
+ {2499321600 -18000 1 CDT}
+ {2519881200 -21600 0 CST}
+ {2530771200 -18000 1 CDT}
+ {2551330800 -21600 0 CST}
+ {2562220800 -18000 1 CDT}
+ {2582780400 -21600 0 CST}
+ {2593670400 -18000 1 CDT}
+ {2614230000 -21600 0 CST}
+ {2625120000 -18000 1 CDT}
+ {2645679600 -21600 0 CST}
+ {2656569600 -18000 1 CDT}
+ {2677129200 -21600 0 CST}
+ {2688624000 -18000 1 CDT}
+ {2709183600 -21600 0 CST}
+ {2720073600 -18000 1 CDT}
+ {2740633200 -21600 0 CST}
+ {2751523200 -18000 1 CDT}
+ {2772082800 -21600 0 CST}
+ {2782972800 -18000 1 CDT}
+ {2803532400 -21600 0 CST}
+ {2814422400 -18000 1 CDT}
+ {2834982000 -21600 0 CST}
+ {2846476800 -18000 1 CDT}
+ {2867036400 -21600 0 CST}
+ {2877926400 -18000 1 CDT}
+ {2898486000 -21600 0 CST}
+ {2909376000 -18000 1 CDT}
+ {2929935600 -21600 0 CST}
+ {2940825600 -18000 1 CDT}
+ {2961385200 -21600 0 CST}
+ {2972275200 -18000 1 CDT}
+ {2992834800 -21600 0 CST}
+ {3003724800 -18000 1 CDT}
+ {3024284400 -21600 0 CST}
+ {3035779200 -18000 1 CDT}
+ {3056338800 -21600 0 CST}
+ {3067228800 -18000 1 CDT}
+ {3087788400 -21600 0 CST}
+ {3098678400 -18000 1 CDT}
+ {3119238000 -21600 0 CST}
+ {3130128000 -18000 1 CDT}
+ {3150687600 -21600 0 CST}
+ {3161577600 -18000 1 CDT}
+ {3182137200 -21600 0 CST}
+ {3193027200 -18000 1 CDT}
+ {3213586800 -21600 0 CST}
+ {3225081600 -18000 1 CDT}
+ {3245641200 -21600 0 CST}
+ {3256531200 -18000 1 CDT}
+ {3277090800 -21600 0 CST}
+ {3287980800 -18000 1 CDT}
+ {3308540400 -21600 0 CST}
+ {3319430400 -18000 1 CDT}
+ {3339990000 -21600 0 CST}
+ {3350880000 -18000 1 CDT}
+ {3371439600 -21600 0 CST}
+ {3382934400 -18000 1 CDT}
+ {3403494000 -21600 0 CST}
+ {3414384000 -18000 1 CDT}
+ {3434943600 -21600 0 CST}
+ {3445833600 -18000 1 CDT}
+ {3466393200 -21600 0 CST}
+ {3477283200 -18000 1 CDT}
+ {3497842800 -21600 0 CST}
+ {3508732800 -18000 1 CDT}
+ {3529292400 -21600 0 CST}
+ {3540182400 -18000 1 CDT}
+ {3560742000 -21600 0 CST}
+ {3572236800 -18000 1 CDT}
+ {3592796400 -21600 0 CST}
+ {3603686400 -18000 1 CDT}
+ {3624246000 -21600 0 CST}
+ {3635136000 -18000 1 CDT}
+ {3655695600 -21600 0 CST}
+ {3666585600 -18000 1 CDT}
+ {3687145200 -21600 0 CST}
+ {3698035200 -18000 1 CDT}
+ {3718594800 -21600 0 CST}
+ {3730089600 -18000 1 CDT}
+ {3750649200 -21600 0 CST}
+ {3761539200 -18000 1 CDT}
+ {3782098800 -21600 0 CST}
+ {3792988800 -18000 1 CDT}
+ {3813548400 -21600 0 CST}
+ {3824438400 -18000 1 CDT}
+ {3844998000 -21600 0 CST}
+ {3855888000 -18000 1 CDT}
+ {3876447600 -21600 0 CST}
+ {3887337600 -18000 1 CDT}
+ {3907897200 -21600 0 CST}
+ {3919392000 -18000 1 CDT}
+ {3939951600 -21600 0 CST}
+ {3950841600 -18000 1 CDT}
+ {3971401200 -21600 0 CST}
+ {3982291200 -18000 1 CDT}
+ {4002850800 -21600 0 CST}
+ {4013740800 -18000 1 CDT}
+ {4034300400 -21600 0 CST}
+ {4045190400 -18000 1 CDT}
+ {4065750000 -21600 0 CST}
+ {4076640000 -18000 1 CDT}
+ {4097199600 -21600 0 CST}
+}
diff --git a/library/tzdata/America/North_Dakota/Center b/library/tzdata/America/North_Dakota/Center
new file mode 100644
index 0000000..30782f7
--- /dev/null
+++ b/library/tzdata/America/North_Dakota/Center
@@ -0,0 +1,279 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/North_Dakota/Center) {
+ {-9223372036854775808 -24312 0 LMT}
+ {-2717643600 -25200 0 MST}
+ {-1633273200 -21600 1 MDT}
+ {-1615132800 -25200 0 MST}
+ {-1601823600 -21600 1 MDT}
+ {-1583683200 -25200 0 MST}
+ {-880210800 -21600 1 MWT}
+ {-769395600 -21600 1 MPT}
+ {-765388800 -25200 0 MST}
+ {-84380400 -21600 1 MDT}
+ {-68659200 -25200 0 MST}
+ {-52930800 -21600 1 MDT}
+ {-37209600 -25200 0 MST}
+ {-21481200 -21600 1 MDT}
+ {-5760000 -25200 0 MST}
+ {9968400 -21600 1 MDT}
+ {25689600 -25200 0 MST}
+ {41418000 -21600 1 MDT}
+ {57744000 -25200 0 MST}
+ {73472400 -21600 1 MDT}
+ {89193600 -25200 0 MST}
+ {104922000 -21600 1 MDT}
+ {120643200 -25200 0 MST}
+ {126694800 -21600 1 MDT}
+ {152092800 -25200 0 MST}
+ {162378000 -21600 1 MDT}
+ {183542400 -25200 0 MST}
+ {199270800 -21600 1 MDT}
+ {215596800 -25200 0 MST}
+ {230720400 -21600 1 MDT}
+ {247046400 -25200 0 MST}
+ {262774800 -21600 1 MDT}
+ {278496000 -25200 0 MST}
+ {294224400 -21600 1 MDT}
+ {309945600 -25200 0 MST}
+ {325674000 -21600 1 MDT}
+ {341395200 -25200 0 MST}
+ {357123600 -21600 1 MDT}
+ {372844800 -25200 0 MST}
+ {388573200 -21600 1 MDT}
+ {404899200 -25200 0 MST}
+ {420022800 -21600 1 MDT}
+ {436348800 -25200 0 MST}
+ {452077200 -21600 1 MDT}
+ {467798400 -25200 0 MST}
+ {483526800 -21600 1 MDT}
+ {499248000 -25200 0 MST}
+ {514976400 -21600 1 MDT}
+ {530697600 -25200 0 MST}
+ {544611600 -21600 1 MDT}
+ {562147200 -25200 0 MST}
+ {576061200 -21600 1 MDT}
+ {594201600 -25200 0 MST}
+ {607510800 -21600 1 MDT}
+ {625651200 -25200 0 MST}
+ {638960400 -21600 1 MDT}
+ {657100800 -25200 0 MST}
+ {671014800 -21600 1 MDT}
+ {688550400 -25200 0 MST}
+ {702464400 -21600 1 MDT}
+ {720003600 -21600 0 CST}
+ {733910400 -18000 1 CDT}
+ {752050800 -21600 0 CST}
+ {765360000 -18000 1 CDT}
+ {783500400 -21600 0 CST}
+ {796809600 -18000 1 CDT}
+ {814950000 -21600 0 CST}
+ {828864000 -18000 1 CDT}
+ {846399600 -21600 0 CST}
+ {860313600 -18000 1 CDT}
+ {877849200 -21600 0 CST}
+ {891763200 -18000 1 CDT}
+ {909298800 -21600 0 CST}
+ {923212800 -18000 1 CDT}
+ {941353200 -21600 0 CST}
+ {954662400 -18000 1 CDT}
+ {972802800 -21600 0 CST}
+ {986112000 -18000 1 CDT}
+ {1004252400 -21600 0 CST}
+ {1018166400 -18000 1 CDT}
+ {1035702000 -21600 0 CST}
+ {1049616000 -18000 1 CDT}
+ {1067151600 -21600 0 CST}
+ {1081065600 -18000 1 CDT}
+ {1099206000 -21600 0 CST}
+ {1112515200 -18000 1 CDT}
+ {1130655600 -21600 0 CST}
+ {1143964800 -18000 1 CDT}
+ {1162105200 -21600 0 CST}
+ {1173600000 -18000 1 CDT}
+ {1194159600 -21600 0 CST}
+ {1205049600 -18000 1 CDT}
+ {1225609200 -21600 0 CST}
+ {1236499200 -18000 1 CDT}
+ {1257058800 -21600 0 CST}
+ {1268553600 -18000 1 CDT}
+ {1289113200 -21600 0 CST}
+ {1300003200 -18000 1 CDT}
+ {1320562800 -21600 0 CST}
+ {1331452800 -18000 1 CDT}
+ {1352012400 -21600 0 CST}
+ {1362902400 -18000 1 CDT}
+ {1383462000 -21600 0 CST}
+ {1394352000 -18000 1 CDT}
+ {1414911600 -21600 0 CST}
+ {1425801600 -18000 1 CDT}
+ {1446361200 -21600 0 CST}
+ {1457856000 -18000 1 CDT}
+ {1478415600 -21600 0 CST}
+ {1489305600 -18000 1 CDT}
+ {1509865200 -21600 0 CST}
+ {1520755200 -18000 1 CDT}
+ {1541314800 -21600 0 CST}
+ {1552204800 -18000 1 CDT}
+ {1572764400 -21600 0 CST}
+ {1583654400 -18000 1 CDT}
+ {1604214000 -21600 0 CST}
+ {1615708800 -18000 1 CDT}
+ {1636268400 -21600 0 CST}
+ {1647158400 -18000 1 CDT}
+ {1667718000 -21600 0 CST}
+ {1678608000 -18000 1 CDT}
+ {1699167600 -21600 0 CST}
+ {1710057600 -18000 1 CDT}
+ {1730617200 -21600 0 CST}
+ {1741507200 -18000 1 CDT}
+ {1762066800 -21600 0 CST}
+ {1772956800 -18000 1 CDT}
+ {1793516400 -21600 0 CST}
+ {1805011200 -18000 1 CDT}
+ {1825570800 -21600 0 CST}
+ {1836460800 -18000 1 CDT}
+ {1857020400 -21600 0 CST}
+ {1867910400 -18000 1 CDT}
+ {1888470000 -21600 0 CST}
+ {1899360000 -18000 1 CDT}
+ {1919919600 -21600 0 CST}
+ {1930809600 -18000 1 CDT}
+ {1951369200 -21600 0 CST}
+ {1962864000 -18000 1 CDT}
+ {1983423600 -21600 0 CST}
+ {1994313600 -18000 1 CDT}
+ {2014873200 -21600 0 CST}
+ {2025763200 -18000 1 CDT}
+ {2046322800 -21600 0 CST}
+ {2057212800 -18000 1 CDT}
+ {2077772400 -21600 0 CST}
+ {2088662400 -18000 1 CDT}
+ {2109222000 -21600 0 CST}
+ {2120112000 -18000 1 CDT}
+ {2140671600 -21600 0 CST}
+ {2152166400 -18000 1 CDT}
+ {2172726000 -21600 0 CST}
+ {2183616000 -18000 1 CDT}
+ {2204175600 -21600 0 CST}
+ {2215065600 -18000 1 CDT}
+ {2235625200 -21600 0 CST}
+ {2246515200 -18000 1 CDT}
+ {2267074800 -21600 0 CST}
+ {2277964800 -18000 1 CDT}
+ {2298524400 -21600 0 CST}
+ {2309414400 -18000 1 CDT}
+ {2329974000 -21600 0 CST}
+ {2341468800 -18000 1 CDT}
+ {2362028400 -21600 0 CST}
+ {2372918400 -18000 1 CDT}
+ {2393478000 -21600 0 CST}
+ {2404368000 -18000 1 CDT}
+ {2424927600 -21600 0 CST}
+ {2435817600 -18000 1 CDT}
+ {2456377200 -21600 0 CST}
+ {2467267200 -18000 1 CDT}
+ {2487826800 -21600 0 CST}
+ {2499321600 -18000 1 CDT}
+ {2519881200 -21600 0 CST}
+ {2530771200 -18000 1 CDT}
+ {2551330800 -21600 0 CST}
+ {2562220800 -18000 1 CDT}
+ {2582780400 -21600 0 CST}
+ {2593670400 -18000 1 CDT}
+ {2614230000 -21600 0 CST}
+ {2625120000 -18000 1 CDT}
+ {2645679600 -21600 0 CST}
+ {2656569600 -18000 1 CDT}
+ {2677129200 -21600 0 CST}
+ {2688624000 -18000 1 CDT}
+ {2709183600 -21600 0 CST}
+ {2720073600 -18000 1 CDT}
+ {2740633200 -21600 0 CST}
+ {2751523200 -18000 1 CDT}
+ {2772082800 -21600 0 CST}
+ {2782972800 -18000 1 CDT}
+ {2803532400 -21600 0 CST}
+ {2814422400 -18000 1 CDT}
+ {2834982000 -21600 0 CST}
+ {2846476800 -18000 1 CDT}
+ {2867036400 -21600 0 CST}
+ {2877926400 -18000 1 CDT}
+ {2898486000 -21600 0 CST}
+ {2909376000 -18000 1 CDT}
+ {2929935600 -21600 0 CST}
+ {2940825600 -18000 1 CDT}
+ {2961385200 -21600 0 CST}
+ {2972275200 -18000 1 CDT}
+ {2992834800 -21600 0 CST}
+ {3003724800 -18000 1 CDT}
+ {3024284400 -21600 0 CST}
+ {3035779200 -18000 1 CDT}
+ {3056338800 -21600 0 CST}
+ {3067228800 -18000 1 CDT}
+ {3087788400 -21600 0 CST}
+ {3098678400 -18000 1 CDT}
+ {3119238000 -21600 0 CST}
+ {3130128000 -18000 1 CDT}
+ {3150687600 -21600 0 CST}
+ {3161577600 -18000 1 CDT}
+ {3182137200 -21600 0 CST}
+ {3193027200 -18000 1 CDT}
+ {3213586800 -21600 0 CST}
+ {3225081600 -18000 1 CDT}
+ {3245641200 -21600 0 CST}
+ {3256531200 -18000 1 CDT}
+ {3277090800 -21600 0 CST}
+ {3287980800 -18000 1 CDT}
+ {3308540400 -21600 0 CST}
+ {3319430400 -18000 1 CDT}
+ {3339990000 -21600 0 CST}
+ {3350880000 -18000 1 CDT}
+ {3371439600 -21600 0 CST}
+ {3382934400 -18000 1 CDT}
+ {3403494000 -21600 0 CST}
+ {3414384000 -18000 1 CDT}
+ {3434943600 -21600 0 CST}
+ {3445833600 -18000 1 CDT}
+ {3466393200 -21600 0 CST}
+ {3477283200 -18000 1 CDT}
+ {3497842800 -21600 0 CST}
+ {3508732800 -18000 1 CDT}
+ {3529292400 -21600 0 CST}
+ {3540182400 -18000 1 CDT}
+ {3560742000 -21600 0 CST}
+ {3572236800 -18000 1 CDT}
+ {3592796400 -21600 0 CST}
+ {3603686400 -18000 1 CDT}
+ {3624246000 -21600 0 CST}
+ {3635136000 -18000 1 CDT}
+ {3655695600 -21600 0 CST}
+ {3666585600 -18000 1 CDT}
+ {3687145200 -21600 0 CST}
+ {3698035200 -18000 1 CDT}
+ {3718594800 -21600 0 CST}
+ {3730089600 -18000 1 CDT}
+ {3750649200 -21600 0 CST}
+ {3761539200 -18000 1 CDT}
+ {3782098800 -21600 0 CST}
+ {3792988800 -18000 1 CDT}
+ {3813548400 -21600 0 CST}
+ {3824438400 -18000 1 CDT}
+ {3844998000 -21600 0 CST}
+ {3855888000 -18000 1 CDT}
+ {3876447600 -21600 0 CST}
+ {3887337600 -18000 1 CDT}
+ {3907897200 -21600 0 CST}
+ {3919392000 -18000 1 CDT}
+ {3939951600 -21600 0 CST}
+ {3950841600 -18000 1 CDT}
+ {3971401200 -21600 0 CST}
+ {3982291200 -18000 1 CDT}
+ {4002850800 -21600 0 CST}
+ {4013740800 -18000 1 CDT}
+ {4034300400 -21600 0 CST}
+ {4045190400 -18000 1 CDT}
+ {4065750000 -21600 0 CST}
+ {4076640000 -18000 1 CDT}
+ {4097199600 -21600 0 CST}
+}
diff --git a/library/tzdata/America/North_Dakota/New_Salem b/library/tzdata/America/North_Dakota/New_Salem
new file mode 100755
index 0000000..5a9d229
--- /dev/null
+++ b/library/tzdata/America/North_Dakota/New_Salem
@@ -0,0 +1,279 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/North_Dakota/New_Salem) {
+ {-9223372036854775808 -24339 0 LMT}
+ {-2717643600 -25200 0 MST}
+ {-1633273200 -21600 1 MDT}
+ {-1615132800 -25200 0 MST}
+ {-1601823600 -21600 1 MDT}
+ {-1583683200 -25200 0 MST}
+ {-880210800 -21600 1 MWT}
+ {-769395600 -21600 1 MPT}
+ {-765388800 -25200 0 MST}
+ {-84380400 -21600 1 MDT}
+ {-68659200 -25200 0 MST}
+ {-52930800 -21600 1 MDT}
+ {-37209600 -25200 0 MST}
+ {-21481200 -21600 1 MDT}
+ {-5760000 -25200 0 MST}
+ {9968400 -21600 1 MDT}
+ {25689600 -25200 0 MST}
+ {41418000 -21600 1 MDT}
+ {57744000 -25200 0 MST}
+ {73472400 -21600 1 MDT}
+ {89193600 -25200 0 MST}
+ {104922000 -21600 1 MDT}
+ {120643200 -25200 0 MST}
+ {126694800 -21600 1 MDT}
+ {152092800 -25200 0 MST}
+ {162378000 -21600 1 MDT}
+ {183542400 -25200 0 MST}
+ {199270800 -21600 1 MDT}
+ {215596800 -25200 0 MST}
+ {230720400 -21600 1 MDT}
+ {247046400 -25200 0 MST}
+ {262774800 -21600 1 MDT}
+ {278496000 -25200 0 MST}
+ {294224400 -21600 1 MDT}
+ {309945600 -25200 0 MST}
+ {325674000 -21600 1 MDT}
+ {341395200 -25200 0 MST}
+ {357123600 -21600 1 MDT}
+ {372844800 -25200 0 MST}
+ {388573200 -21600 1 MDT}
+ {404899200 -25200 0 MST}
+ {420022800 -21600 1 MDT}
+ {436348800 -25200 0 MST}
+ {452077200 -21600 1 MDT}
+ {467798400 -25200 0 MST}
+ {483526800 -21600 1 MDT}
+ {499248000 -25200 0 MST}
+ {514976400 -21600 1 MDT}
+ {530697600 -25200 0 MST}
+ {544611600 -21600 1 MDT}
+ {562147200 -25200 0 MST}
+ {576061200 -21600 1 MDT}
+ {594201600 -25200 0 MST}
+ {607510800 -21600 1 MDT}
+ {625651200 -25200 0 MST}
+ {638960400 -21600 1 MDT}
+ {657100800 -25200 0 MST}
+ {671014800 -21600 1 MDT}
+ {688550400 -25200 0 MST}
+ {702464400 -21600 1 MDT}
+ {720000000 -25200 0 MST}
+ {733914000 -21600 1 MDT}
+ {752054400 -25200 0 MST}
+ {765363600 -21600 1 MDT}
+ {783504000 -25200 0 MST}
+ {796813200 -21600 1 MDT}
+ {814953600 -25200 0 MST}
+ {828867600 -21600 1 MDT}
+ {846403200 -25200 0 MST}
+ {860317200 -21600 1 MDT}
+ {877852800 -25200 0 MST}
+ {891766800 -21600 1 MDT}
+ {909302400 -25200 0 MST}
+ {923216400 -21600 1 MDT}
+ {941356800 -25200 0 MST}
+ {954666000 -21600 1 MDT}
+ {972806400 -25200 0 MST}
+ {986115600 -21600 1 MDT}
+ {1004256000 -25200 0 MST}
+ {1018170000 -21600 1 MDT}
+ {1035705600 -25200 0 MST}
+ {1049619600 -21600 1 MDT}
+ {1067158800 -21600 0 CST}
+ {1081065600 -18000 1 CDT}
+ {1099206000 -21600 0 CST}
+ {1112515200 -18000 1 CDT}
+ {1130655600 -21600 0 CST}
+ {1143964800 -18000 1 CDT}
+ {1162105200 -21600 0 CST}
+ {1173600000 -18000 1 CDT}
+ {1194159600 -21600 0 CST}
+ {1205049600 -18000 1 CDT}
+ {1225609200 -21600 0 CST}
+ {1236499200 -18000 1 CDT}
+ {1257058800 -21600 0 CST}
+ {1268553600 -18000 1 CDT}
+ {1289113200 -21600 0 CST}
+ {1300003200 -18000 1 CDT}
+ {1320562800 -21600 0 CST}
+ {1331452800 -18000 1 CDT}
+ {1352012400 -21600 0 CST}
+ {1362902400 -18000 1 CDT}
+ {1383462000 -21600 0 CST}
+ {1394352000 -18000 1 CDT}
+ {1414911600 -21600 0 CST}
+ {1425801600 -18000 1 CDT}
+ {1446361200 -21600 0 CST}
+ {1457856000 -18000 1 CDT}
+ {1478415600 -21600 0 CST}
+ {1489305600 -18000 1 CDT}
+ {1509865200 -21600 0 CST}
+ {1520755200 -18000 1 CDT}
+ {1541314800 -21600 0 CST}
+ {1552204800 -18000 1 CDT}
+ {1572764400 -21600 0 CST}
+ {1583654400 -18000 1 CDT}
+ {1604214000 -21600 0 CST}
+ {1615708800 -18000 1 CDT}
+ {1636268400 -21600 0 CST}
+ {1647158400 -18000 1 CDT}
+ {1667718000 -21600 0 CST}
+ {1678608000 -18000 1 CDT}
+ {1699167600 -21600 0 CST}
+ {1710057600 -18000 1 CDT}
+ {1730617200 -21600 0 CST}
+ {1741507200 -18000 1 CDT}
+ {1762066800 -21600 0 CST}
+ {1772956800 -18000 1 CDT}
+ {1793516400 -21600 0 CST}
+ {1805011200 -18000 1 CDT}
+ {1825570800 -21600 0 CST}
+ {1836460800 -18000 1 CDT}
+ {1857020400 -21600 0 CST}
+ {1867910400 -18000 1 CDT}
+ {1888470000 -21600 0 CST}
+ {1899360000 -18000 1 CDT}
+ {1919919600 -21600 0 CST}
+ {1930809600 -18000 1 CDT}
+ {1951369200 -21600 0 CST}
+ {1962864000 -18000 1 CDT}
+ {1983423600 -21600 0 CST}
+ {1994313600 -18000 1 CDT}
+ {2014873200 -21600 0 CST}
+ {2025763200 -18000 1 CDT}
+ {2046322800 -21600 0 CST}
+ {2057212800 -18000 1 CDT}
+ {2077772400 -21600 0 CST}
+ {2088662400 -18000 1 CDT}
+ {2109222000 -21600 0 CST}
+ {2120112000 -18000 1 CDT}
+ {2140671600 -21600 0 CST}
+ {2152166400 -18000 1 CDT}
+ {2172726000 -21600 0 CST}
+ {2183616000 -18000 1 CDT}
+ {2204175600 -21600 0 CST}
+ {2215065600 -18000 1 CDT}
+ {2235625200 -21600 0 CST}
+ {2246515200 -18000 1 CDT}
+ {2267074800 -21600 0 CST}
+ {2277964800 -18000 1 CDT}
+ {2298524400 -21600 0 CST}
+ {2309414400 -18000 1 CDT}
+ {2329974000 -21600 0 CST}
+ {2341468800 -18000 1 CDT}
+ {2362028400 -21600 0 CST}
+ {2372918400 -18000 1 CDT}
+ {2393478000 -21600 0 CST}
+ {2404368000 -18000 1 CDT}
+ {2424927600 -21600 0 CST}
+ {2435817600 -18000 1 CDT}
+ {2456377200 -21600 0 CST}
+ {2467267200 -18000 1 CDT}
+ {2487826800 -21600 0 CST}
+ {2499321600 -18000 1 CDT}
+ {2519881200 -21600 0 CST}
+ {2530771200 -18000 1 CDT}
+ {2551330800 -21600 0 CST}
+ {2562220800 -18000 1 CDT}
+ {2582780400 -21600 0 CST}
+ {2593670400 -18000 1 CDT}
+ {2614230000 -21600 0 CST}
+ {2625120000 -18000 1 CDT}
+ {2645679600 -21600 0 CST}
+ {2656569600 -18000 1 CDT}
+ {2677129200 -21600 0 CST}
+ {2688624000 -18000 1 CDT}
+ {2709183600 -21600 0 CST}
+ {2720073600 -18000 1 CDT}
+ {2740633200 -21600 0 CST}
+ {2751523200 -18000 1 CDT}
+ {2772082800 -21600 0 CST}
+ {2782972800 -18000 1 CDT}
+ {2803532400 -21600 0 CST}
+ {2814422400 -18000 1 CDT}
+ {2834982000 -21600 0 CST}
+ {2846476800 -18000 1 CDT}
+ {2867036400 -21600 0 CST}
+ {2877926400 -18000 1 CDT}
+ {2898486000 -21600 0 CST}
+ {2909376000 -18000 1 CDT}
+ {2929935600 -21600 0 CST}
+ {2940825600 -18000 1 CDT}
+ {2961385200 -21600 0 CST}
+ {2972275200 -18000 1 CDT}
+ {2992834800 -21600 0 CST}
+ {3003724800 -18000 1 CDT}
+ {3024284400 -21600 0 CST}
+ {3035779200 -18000 1 CDT}
+ {3056338800 -21600 0 CST}
+ {3067228800 -18000 1 CDT}
+ {3087788400 -21600 0 CST}
+ {3098678400 -18000 1 CDT}
+ {3119238000 -21600 0 CST}
+ {3130128000 -18000 1 CDT}
+ {3150687600 -21600 0 CST}
+ {3161577600 -18000 1 CDT}
+ {3182137200 -21600 0 CST}
+ {3193027200 -18000 1 CDT}
+ {3213586800 -21600 0 CST}
+ {3225081600 -18000 1 CDT}
+ {3245641200 -21600 0 CST}
+ {3256531200 -18000 1 CDT}
+ {3277090800 -21600 0 CST}
+ {3287980800 -18000 1 CDT}
+ {3308540400 -21600 0 CST}
+ {3319430400 -18000 1 CDT}
+ {3339990000 -21600 0 CST}
+ {3350880000 -18000 1 CDT}
+ {3371439600 -21600 0 CST}
+ {3382934400 -18000 1 CDT}
+ {3403494000 -21600 0 CST}
+ {3414384000 -18000 1 CDT}
+ {3434943600 -21600 0 CST}
+ {3445833600 -18000 1 CDT}
+ {3466393200 -21600 0 CST}
+ {3477283200 -18000 1 CDT}
+ {3497842800 -21600 0 CST}
+ {3508732800 -18000 1 CDT}
+ {3529292400 -21600 0 CST}
+ {3540182400 -18000 1 CDT}
+ {3560742000 -21600 0 CST}
+ {3572236800 -18000 1 CDT}
+ {3592796400 -21600 0 CST}
+ {3603686400 -18000 1 CDT}
+ {3624246000 -21600 0 CST}
+ {3635136000 -18000 1 CDT}
+ {3655695600 -21600 0 CST}
+ {3666585600 -18000 1 CDT}
+ {3687145200 -21600 0 CST}
+ {3698035200 -18000 1 CDT}
+ {3718594800 -21600 0 CST}
+ {3730089600 -18000 1 CDT}
+ {3750649200 -21600 0 CST}
+ {3761539200 -18000 1 CDT}
+ {3782098800 -21600 0 CST}
+ {3792988800 -18000 1 CDT}
+ {3813548400 -21600 0 CST}
+ {3824438400 -18000 1 CDT}
+ {3844998000 -21600 0 CST}
+ {3855888000 -18000 1 CDT}
+ {3876447600 -21600 0 CST}
+ {3887337600 -18000 1 CDT}
+ {3907897200 -21600 0 CST}
+ {3919392000 -18000 1 CDT}
+ {3939951600 -21600 0 CST}
+ {3950841600 -18000 1 CDT}
+ {3971401200 -21600 0 CST}
+ {3982291200 -18000 1 CDT}
+ {4002850800 -21600 0 CST}
+ {4013740800 -18000 1 CDT}
+ {4034300400 -21600 0 CST}
+ {4045190400 -18000 1 CDT}
+ {4065750000 -21600 0 CST}
+ {4076640000 -18000 1 CDT}
+ {4097199600 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Ojinaga b/library/tzdata/America/Ojinaga
new file mode 100644
index 0000000..1172708
--- /dev/null
+++ b/library/tzdata/America/Ojinaga
@@ -0,0 +1,222 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Ojinaga) {
+ {-9223372036854775808 -25060 0 LMT}
+ {-1514739600 -25200 0 MST}
+ {-1343066400 -21600 0 CST}
+ {-1234807200 -25200 0 MST}
+ {-1220292000 -21600 0 CST}
+ {-1207159200 -25200 0 MST}
+ {-1191344400 -21600 0 CST}
+ {820476000 -21600 0 CST}
+ {828864000 -18000 1 CDT}
+ {846399600 -21600 0 CST}
+ {860313600 -18000 1 CDT}
+ {877849200 -21600 0 CST}
+ {883634400 -21600 0 CST}
+ {891766800 -21600 0 MDT}
+ {909302400 -25200 0 MST}
+ {923216400 -21600 1 MDT}
+ {941356800 -25200 0 MST}
+ {954666000 -21600 1 MDT}
+ {972806400 -25200 0 MST}
+ {989139600 -21600 1 MDT}
+ {1001836800 -25200 0 MST}
+ {1018170000 -21600 1 MDT}
+ {1035705600 -25200 0 MST}
+ {1049619600 -21600 1 MDT}
+ {1067155200 -25200 0 MST}
+ {1081069200 -21600 1 MDT}
+ {1099209600 -25200 0 MST}
+ {1112518800 -21600 1 MDT}
+ {1130659200 -25200 0 MST}
+ {1143968400 -21600 1 MDT}
+ {1162108800 -25200 0 MST}
+ {1175418000 -21600 1 MDT}
+ {1193558400 -25200 0 MST}
+ {1207472400 -21600 1 MDT}
+ {1225008000 -25200 0 MST}
+ {1238922000 -21600 1 MDT}
+ {1256457600 -25200 0 MST}
+ {1262329200 -25200 0 MST}
+ {1268557200 -21600 1 MDT}
+ {1289116800 -25200 0 MST}
+ {1300006800 -21600 1 MDT}
+ {1320566400 -25200 0 MST}
+ {1331456400 -21600 1 MDT}
+ {1352016000 -25200 0 MST}
+ {1362906000 -21600 1 MDT}
+ {1383465600 -25200 0 MST}
+ {1394355600 -21600 1 MDT}
+ {1414915200 -25200 0 MST}
+ {1425805200 -21600 1 MDT}
+ {1446364800 -25200 0 MST}
+ {1457859600 -21600 1 MDT}
+ {1478419200 -25200 0 MST}
+ {1489309200 -21600 1 MDT}
+ {1509868800 -25200 0 MST}
+ {1520758800 -21600 1 MDT}
+ {1541318400 -25200 0 MST}
+ {1552208400 -21600 1 MDT}
+ {1572768000 -25200 0 MST}
+ {1583658000 -21600 1 MDT}
+ {1604217600 -25200 0 MST}
+ {1615712400 -21600 1 MDT}
+ {1636272000 -25200 0 MST}
+ {1647162000 -21600 1 MDT}
+ {1667721600 -25200 0 MST}
+ {1678611600 -21600 1 MDT}
+ {1699171200 -25200 0 MST}
+ {1710061200 -21600 1 MDT}
+ {1730620800 -25200 0 MST}
+ {1741510800 -21600 1 MDT}
+ {1762070400 -25200 0 MST}
+ {1772960400 -21600 1 MDT}
+ {1793520000 -25200 0 MST}
+ {1805014800 -21600 1 MDT}
+ {1825574400 -25200 0 MST}
+ {1836464400 -21600 1 MDT}
+ {1857024000 -25200 0 MST}
+ {1867914000 -21600 1 MDT}
+ {1888473600 -25200 0 MST}
+ {1899363600 -21600 1 MDT}
+ {1919923200 -25200 0 MST}
+ {1930813200 -21600 1 MDT}
+ {1951372800 -25200 0 MST}
+ {1962867600 -21600 1 MDT}
+ {1983427200 -25200 0 MST}
+ {1994317200 -21600 1 MDT}
+ {2014876800 -25200 0 MST}
+ {2025766800 -21600 1 MDT}
+ {2046326400 -25200 0 MST}
+ {2057216400 -21600 1 MDT}
+ {2077776000 -25200 0 MST}
+ {2088666000 -21600 1 MDT}
+ {2109225600 -25200 0 MST}
+ {2120115600 -21600 1 MDT}
+ {2140675200 -25200 0 MST}
+ {2152170000 -21600 1 MDT}
+ {2172729600 -25200 0 MST}
+ {2183619600 -21600 1 MDT}
+ {2204179200 -25200 0 MST}
+ {2215069200 -21600 1 MDT}
+ {2235628800 -25200 0 MST}
+ {2246518800 -21600 1 MDT}
+ {2267078400 -25200 0 MST}
+ {2277968400 -21600 1 MDT}
+ {2298528000 -25200 0 MST}
+ {2309418000 -21600 1 MDT}
+ {2329977600 -25200 0 MST}
+ {2341472400 -21600 1 MDT}
+ {2362032000 -25200 0 MST}
+ {2372922000 -21600 1 MDT}
+ {2393481600 -25200 0 MST}
+ {2404371600 -21600 1 MDT}
+ {2424931200 -25200 0 MST}
+ {2435821200 -21600 1 MDT}
+ {2456380800 -25200 0 MST}
+ {2467270800 -21600 1 MDT}
+ {2487830400 -25200 0 MST}
+ {2499325200 -21600 1 MDT}
+ {2519884800 -25200 0 MST}
+ {2530774800 -21600 1 MDT}
+ {2551334400 -25200 0 MST}
+ {2562224400 -21600 1 MDT}
+ {2582784000 -25200 0 MST}
+ {2593674000 -21600 1 MDT}
+ {2614233600 -25200 0 MST}
+ {2625123600 -21600 1 MDT}
+ {2645683200 -25200 0 MST}
+ {2656573200 -21600 1 MDT}
+ {2677132800 -25200 0 MST}
+ {2688627600 -21600 1 MDT}
+ {2709187200 -25200 0 MST}
+ {2720077200 -21600 1 MDT}
+ {2740636800 -25200 0 MST}
+ {2751526800 -21600 1 MDT}
+ {2772086400 -25200 0 MST}
+ {2782976400 -21600 1 MDT}
+ {2803536000 -25200 0 MST}
+ {2814426000 -21600 1 MDT}
+ {2834985600 -25200 0 MST}
+ {2846480400 -21600 1 MDT}
+ {2867040000 -25200 0 MST}
+ {2877930000 -21600 1 MDT}
+ {2898489600 -25200 0 MST}
+ {2909379600 -21600 1 MDT}
+ {2929939200 -25200 0 MST}
+ {2940829200 -21600 1 MDT}
+ {2961388800 -25200 0 MST}
+ {2972278800 -21600 1 MDT}
+ {2992838400 -25200 0 MST}
+ {3003728400 -21600 1 MDT}
+ {3024288000 -25200 0 MST}
+ {3035782800 -21600 1 MDT}
+ {3056342400 -25200 0 MST}
+ {3067232400 -21600 1 MDT}
+ {3087792000 -25200 0 MST}
+ {3098682000 -21600 1 MDT}
+ {3119241600 -25200 0 MST}
+ {3130131600 -21600 1 MDT}
+ {3150691200 -25200 0 MST}
+ {3161581200 -21600 1 MDT}
+ {3182140800 -25200 0 MST}
+ {3193030800 -21600 1 MDT}
+ {3213590400 -25200 0 MST}
+ {3225085200 -21600 1 MDT}
+ {3245644800 -25200 0 MST}
+ {3256534800 -21600 1 MDT}
+ {3277094400 -25200 0 MST}
+ {3287984400 -21600 1 MDT}
+ {3308544000 -25200 0 MST}
+ {3319434000 -21600 1 MDT}
+ {3339993600 -25200 0 MST}
+ {3350883600 -21600 1 MDT}
+ {3371443200 -25200 0 MST}
+ {3382938000 -21600 1 MDT}
+ {3403497600 -25200 0 MST}
+ {3414387600 -21600 1 MDT}
+ {3434947200 -25200 0 MST}
+ {3445837200 -21600 1 MDT}
+ {3466396800 -25200 0 MST}
+ {3477286800 -21600 1 MDT}
+ {3497846400 -25200 0 MST}
+ {3508736400 -21600 1 MDT}
+ {3529296000 -25200 0 MST}
+ {3540186000 -21600 1 MDT}
+ {3560745600 -25200 0 MST}
+ {3572240400 -21600 1 MDT}
+ {3592800000 -25200 0 MST}
+ {3603690000 -21600 1 MDT}
+ {3624249600 -25200 0 MST}
+ {3635139600 -21600 1 MDT}
+ {3655699200 -25200 0 MST}
+ {3666589200 -21600 1 MDT}
+ {3687148800 -25200 0 MST}
+ {3698038800 -21600 1 MDT}
+ {3718598400 -25200 0 MST}
+ {3730093200 -21600 1 MDT}
+ {3750652800 -25200 0 MST}
+ {3761542800 -21600 1 MDT}
+ {3782102400 -25200 0 MST}
+ {3792992400 -21600 1 MDT}
+ {3813552000 -25200 0 MST}
+ {3824442000 -21600 1 MDT}
+ {3845001600 -25200 0 MST}
+ {3855891600 -21600 1 MDT}
+ {3876451200 -25200 0 MST}
+ {3887341200 -21600 1 MDT}
+ {3907900800 -25200 0 MST}
+ {3919395600 -21600 1 MDT}
+ {3939955200 -25200 0 MST}
+ {3950845200 -21600 1 MDT}
+ {3971404800 -25200 0 MST}
+ {3982294800 -21600 1 MDT}
+ {4002854400 -25200 0 MST}
+ {4013744400 -21600 1 MDT}
+ {4034304000 -25200 0 MST}
+ {4045194000 -21600 1 MDT}
+ {4065753600 -25200 0 MST}
+ {4076643600 -21600 1 MDT}
+ {4097203200 -25200 0 MST}
+}
diff --git a/library/tzdata/America/Panama b/library/tzdata/America/Panama
new file mode 100644
index 0000000..3006785
--- /dev/null
+++ b/library/tzdata/America/Panama
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Panama) {
+ {-9223372036854775808 -19088 0 LMT}
+ {-2524502512 -19176 0 CMT}
+ {-1946918424 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Pangnirtung b/library/tzdata/America/Pangnirtung
new file mode 100644
index 0000000..640808e
--- /dev/null
+++ b/library/tzdata/America/Pangnirtung
@@ -0,0 +1,252 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Pangnirtung) {
+ {-9223372036854775808 0 0 zzz}
+ {-1546300800 -14400 0 AST}
+ {-880221600 -10800 1 AWT}
+ {-769395600 -10800 1 APT}
+ {-765399600 -14400 0 AST}
+ {-147902400 -7200 1 ADDT}
+ {-131572800 -14400 0 AST}
+ {325663200 -10800 1 ADT}
+ {341384400 -14400 0 AST}
+ {357112800 -10800 1 ADT}
+ {372834000 -14400 0 AST}
+ {388562400 -10800 1 ADT}
+ {404888400 -14400 0 AST}
+ {420012000 -10800 1 ADT}
+ {436338000 -14400 0 AST}
+ {452066400 -10800 1 ADT}
+ {467787600 -14400 0 AST}
+ {483516000 -10800 1 ADT}
+ {499237200 -14400 0 AST}
+ {514965600 -10800 1 ADT}
+ {530686800 -14400 0 AST}
+ {544600800 -10800 1 ADT}
+ {562136400 -14400 0 AST}
+ {576050400 -10800 1 ADT}
+ {594190800 -14400 0 AST}
+ {607500000 -10800 1 ADT}
+ {625640400 -14400 0 AST}
+ {638949600 -10800 1 ADT}
+ {657090000 -14400 0 AST}
+ {671004000 -10800 1 ADT}
+ {688539600 -14400 0 AST}
+ {702453600 -10800 1 ADT}
+ {719989200 -14400 0 AST}
+ {733903200 -10800 1 ADT}
+ {752043600 -14400 0 AST}
+ {765352800 -10800 1 ADT}
+ {783493200 -14400 0 AST}
+ {796802400 -18000 0 EST}
+ {796806000 -14400 1 EDT}
+ {814946400 -18000 0 EST}
+ {828860400 -14400 1 EDT}
+ {846396000 -18000 0 EST}
+ {860310000 -14400 1 EDT}
+ {877845600 -18000 0 EST}
+ {891759600 -14400 1 EDT}
+ {909295200 -18000 0 EST}
+ {923209200 -14400 1 EDT}
+ {941353200 -21600 0 CST}
+ {954662400 -18000 1 CDT}
+ {972806400 -18000 0 EST}
+ {986108400 -14400 1 EDT}
+ {1004248800 -18000 0 EST}
+ {1018162800 -14400 1 EDT}
+ {1035698400 -18000 0 EST}
+ {1049612400 -14400 1 EDT}
+ {1067148000 -18000 0 EST}
+ {1081062000 -14400 1 EDT}
+ {1099202400 -18000 0 EST}
+ {1112511600 -14400 1 EDT}
+ {1130652000 -18000 0 EST}
+ {1143961200 -14400 1 EDT}
+ {1162101600 -18000 0 EST}
+ {1173596400 -14400 1 EDT}
+ {1194156000 -18000 0 EST}
+ {1205046000 -14400 1 EDT}
+ {1225605600 -18000 0 EST}
+ {1236495600 -14400 1 EDT}
+ {1257055200 -18000 0 EST}
+ {1268550000 -14400 1 EDT}
+ {1289109600 -18000 0 EST}
+ {1299999600 -14400 1 EDT}
+ {1320559200 -18000 0 EST}
+ {1331449200 -14400 1 EDT}
+ {1352008800 -18000 0 EST}
+ {1362898800 -14400 1 EDT}
+ {1383458400 -18000 0 EST}
+ {1394348400 -14400 1 EDT}
+ {1414908000 -18000 0 EST}
+ {1425798000 -14400 1 EDT}
+ {1446357600 -18000 0 EST}
+ {1457852400 -14400 1 EDT}
+ {1478412000 -18000 0 EST}
+ {1489302000 -14400 1 EDT}
+ {1509861600 -18000 0 EST}
+ {1520751600 -14400 1 EDT}
+ {1541311200 -18000 0 EST}
+ {1552201200 -14400 1 EDT}
+ {1572760800 -18000 0 EST}
+ {1583650800 -14400 1 EDT}
+ {1604210400 -18000 0 EST}
+ {1615705200 -14400 1 EDT}
+ {1636264800 -18000 0 EST}
+ {1647154800 -14400 1 EDT}
+ {1667714400 -18000 0 EST}
+ {1678604400 -14400 1 EDT}
+ {1699164000 -18000 0 EST}
+ {1710054000 -14400 1 EDT}
+ {1730613600 -18000 0 EST}
+ {1741503600 -14400 1 EDT}
+ {1762063200 -18000 0 EST}
+ {1772953200 -14400 1 EDT}
+ {1793512800 -18000 0 EST}
+ {1805007600 -14400 1 EDT}
+ {1825567200 -18000 0 EST}
+ {1836457200 -14400 1 EDT}
+ {1857016800 -18000 0 EST}
+ {1867906800 -14400 1 EDT}
+ {1888466400 -18000 0 EST}
+ {1899356400 -14400 1 EDT}
+ {1919916000 -18000 0 EST}
+ {1930806000 -14400 1 EDT}
+ {1951365600 -18000 0 EST}
+ {1962860400 -14400 1 EDT}
+ {1983420000 -18000 0 EST}
+ {1994310000 -14400 1 EDT}
+ {2014869600 -18000 0 EST}
+ {2025759600 -14400 1 EDT}
+ {2046319200 -18000 0 EST}
+ {2057209200 -14400 1 EDT}
+ {2077768800 -18000 0 EST}
+ {2088658800 -14400 1 EDT}
+ {2109218400 -18000 0 EST}
+ {2120108400 -14400 1 EDT}
+ {2140668000 -18000 0 EST}
+ {2152162800 -14400 1 EDT}
+ {2172722400 -18000 0 EST}
+ {2183612400 -14400 1 EDT}
+ {2204172000 -18000 0 EST}
+ {2215062000 -14400 1 EDT}
+ {2235621600 -18000 0 EST}
+ {2246511600 -14400 1 EDT}
+ {2267071200 -18000 0 EST}
+ {2277961200 -14400 1 EDT}
+ {2298520800 -18000 0 EST}
+ {2309410800 -14400 1 EDT}
+ {2329970400 -18000 0 EST}
+ {2341465200 -14400 1 EDT}
+ {2362024800 -18000 0 EST}
+ {2372914800 -14400 1 EDT}
+ {2393474400 -18000 0 EST}
+ {2404364400 -14400 1 EDT}
+ {2424924000 -18000 0 EST}
+ {2435814000 -14400 1 EDT}
+ {2456373600 -18000 0 EST}
+ {2467263600 -14400 1 EDT}
+ {2487823200 -18000 0 EST}
+ {2499318000 -14400 1 EDT}
+ {2519877600 -18000 0 EST}
+ {2530767600 -14400 1 EDT}
+ {2551327200 -18000 0 EST}
+ {2562217200 -14400 1 EDT}
+ {2582776800 -18000 0 EST}
+ {2593666800 -14400 1 EDT}
+ {2614226400 -18000 0 EST}
+ {2625116400 -14400 1 EDT}
+ {2645676000 -18000 0 EST}
+ {2656566000 -14400 1 EDT}
+ {2677125600 -18000 0 EST}
+ {2688620400 -14400 1 EDT}
+ {2709180000 -18000 0 EST}
+ {2720070000 -14400 1 EDT}
+ {2740629600 -18000 0 EST}
+ {2751519600 -14400 1 EDT}
+ {2772079200 -18000 0 EST}
+ {2782969200 -14400 1 EDT}
+ {2803528800 -18000 0 EST}
+ {2814418800 -14400 1 EDT}
+ {2834978400 -18000 0 EST}
+ {2846473200 -14400 1 EDT}
+ {2867032800 -18000 0 EST}
+ {2877922800 -14400 1 EDT}
+ {2898482400 -18000 0 EST}
+ {2909372400 -14400 1 EDT}
+ {2929932000 -18000 0 EST}
+ {2940822000 -14400 1 EDT}
+ {2961381600 -18000 0 EST}
+ {2972271600 -14400 1 EDT}
+ {2992831200 -18000 0 EST}
+ {3003721200 -14400 1 EDT}
+ {3024280800 -18000 0 EST}
+ {3035775600 -14400 1 EDT}
+ {3056335200 -18000 0 EST}
+ {3067225200 -14400 1 EDT}
+ {3087784800 -18000 0 EST}
+ {3098674800 -14400 1 EDT}
+ {3119234400 -18000 0 EST}
+ {3130124400 -14400 1 EDT}
+ {3150684000 -18000 0 EST}
+ {3161574000 -14400 1 EDT}
+ {3182133600 -18000 0 EST}
+ {3193023600 -14400 1 EDT}
+ {3213583200 -18000 0 EST}
+ {3225078000 -14400 1 EDT}
+ {3245637600 -18000 0 EST}
+ {3256527600 -14400 1 EDT}
+ {3277087200 -18000 0 EST}
+ {3287977200 -14400 1 EDT}
+ {3308536800 -18000 0 EST}
+ {3319426800 -14400 1 EDT}
+ {3339986400 -18000 0 EST}
+ {3350876400 -14400 1 EDT}
+ {3371436000 -18000 0 EST}
+ {3382930800 -14400 1 EDT}
+ {3403490400 -18000 0 EST}
+ {3414380400 -14400 1 EDT}
+ {3434940000 -18000 0 EST}
+ {3445830000 -14400 1 EDT}
+ {3466389600 -18000 0 EST}
+ {3477279600 -14400 1 EDT}
+ {3497839200 -18000 0 EST}
+ {3508729200 -14400 1 EDT}
+ {3529288800 -18000 0 EST}
+ {3540178800 -14400 1 EDT}
+ {3560738400 -18000 0 EST}
+ {3572233200 -14400 1 EDT}
+ {3592792800 -18000 0 EST}
+ {3603682800 -14400 1 EDT}
+ {3624242400 -18000 0 EST}
+ {3635132400 -14400 1 EDT}
+ {3655692000 -18000 0 EST}
+ {3666582000 -14400 1 EDT}
+ {3687141600 -18000 0 EST}
+ {3698031600 -14400 1 EDT}
+ {3718591200 -18000 0 EST}
+ {3730086000 -14400 1 EDT}
+ {3750645600 -18000 0 EST}
+ {3761535600 -14400 1 EDT}
+ {3782095200 -18000 0 EST}
+ {3792985200 -14400 1 EDT}
+ {3813544800 -18000 0 EST}
+ {3824434800 -14400 1 EDT}
+ {3844994400 -18000 0 EST}
+ {3855884400 -14400 1 EDT}
+ {3876444000 -18000 0 EST}
+ {3887334000 -14400 1 EDT}
+ {3907893600 -18000 0 EST}
+ {3919388400 -14400 1 EDT}
+ {3939948000 -18000 0 EST}
+ {3950838000 -14400 1 EDT}
+ {3971397600 -18000 0 EST}
+ {3982287600 -14400 1 EDT}
+ {4002847200 -18000 0 EST}
+ {4013737200 -14400 1 EDT}
+ {4034296800 -18000 0 EST}
+ {4045186800 -14400 1 EDT}
+ {4065746400 -18000 0 EST}
+ {4076636400 -14400 1 EDT}
+ {4097196000 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Paramaribo b/library/tzdata/America/Paramaribo
new file mode 100644
index 0000000..d15f5c7
--- /dev/null
+++ b/library/tzdata/America/Paramaribo
@@ -0,0 +1,10 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Paramaribo) {
+ {-9223372036854775808 -13240 0 LMT}
+ {-1861906760 -13252 0 PMT}
+ {-1104524348 -13236 0 PMT}
+ {-765317964 -12600 0 NEGT}
+ {185686200 -12600 0 SRT}
+ {465449400 -10800 0 SRT}
+}
diff --git a/library/tzdata/America/Phoenix b/library/tzdata/America/Phoenix
new file mode 100644
index 0000000..3d37bb4
--- /dev/null
+++ b/library/tzdata/America/Phoenix
@@ -0,0 +1,17 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Phoenix) {
+ {-9223372036854775808 -26898 0 LMT}
+ {-2717643600 -25200 0 MST}
+ {-1633273200 -21600 1 MDT}
+ {-1615132800 -25200 0 MST}
+ {-1601823600 -21600 1 MDT}
+ {-1583683200 -25200 0 MST}
+ {-880210800 -21600 1 MWT}
+ {-820519140 -25200 0 MST}
+ {-796841940 -25200 0 MST}
+ {-94669200 -25200 0 MST}
+ {-84380400 -21600 1 MDT}
+ {-68659200 -25200 0 MST}
+ {-56221200 -25200 0 MST}
+}
diff --git a/library/tzdata/America/Port-au-Prince b/library/tzdata/America/Port-au-Prince
new file mode 100644
index 0000000..04ee62c
--- /dev/null
+++ b/library/tzdata/America/Port-au-Prince
@@ -0,0 +1,41 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Port-au-Prince) {
+ {-9223372036854775808 -17360 0 LMT}
+ {-2524504240 -17340 0 PPMT}
+ {-1670483460 -18000 0 EST}
+ {421218000 -14400 1 EDT}
+ {436334400 -18000 0 EST}
+ {452062800 -14400 1 EDT}
+ {467784000 -18000 0 EST}
+ {483512400 -14400 1 EDT}
+ {499233600 -18000 0 EST}
+ {514962000 -14400 1 EDT}
+ {530683200 -18000 0 EST}
+ {546411600 -14400 1 EDT}
+ {562132800 -18000 0 EST}
+ {576050400 -14400 1 EDT}
+ {594194400 -18000 0 EST}
+ {607500000 -14400 1 EDT}
+ {625644000 -18000 0 EST}
+ {638949600 -14400 1 EDT}
+ {657093600 -18000 0 EST}
+ {671004000 -14400 1 EDT}
+ {688543200 -18000 0 EST}
+ {702453600 -14400 1 EDT}
+ {719992800 -18000 0 EST}
+ {733903200 -14400 1 EDT}
+ {752047200 -18000 0 EST}
+ {765352800 -14400 1 EDT}
+ {783496800 -18000 0 EST}
+ {796802400 -14400 1 EDT}
+ {814946400 -18000 0 EST}
+ {828856800 -14400 1 EDT}
+ {846396000 -18000 0 EST}
+ {860306400 -14400 1 EDT}
+ {877845600 -18000 0 EST}
+ {1112504400 -14400 1 EDT}
+ {1130644800 -18000 0 EST}
+ {1143954000 -14400 1 EDT}
+ {1162094400 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Port_of_Spain b/library/tzdata/America/Port_of_Spain
new file mode 100644
index 0000000..c360c87
--- /dev/null
+++ b/library/tzdata/America/Port_of_Spain
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Port_of_Spain) {
+ {-9223372036854775808 -14764 0 LMT}
+ {-1825098836 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Porto_Acre b/library/tzdata/America/Porto_Acre
new file mode 100644
index 0000000..0626001
--- /dev/null
+++ b/library/tzdata/America/Porto_Acre
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Rio_Branco)]} {
+ LoadTimeZoneFile America/Rio_Branco
+}
+set TZData(:America/Porto_Acre) $TZData(:America/Rio_Branco)
diff --git a/library/tzdata/America/Porto_Velho b/library/tzdata/America/Porto_Velho
new file mode 100644
index 0000000..ce611d2
--- /dev/null
+++ b/library/tzdata/America/Porto_Velho
@@ -0,0 +1,35 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Porto_Velho) {
+ {-9223372036854775808 -15336 0 LMT}
+ {-1767210264 -14400 0 AMT}
+ {-1206954000 -10800 1 AMST}
+ {-1191358800 -14400 0 AMT}
+ {-1175371200 -10800 1 AMST}
+ {-1159822800 -14400 0 AMT}
+ {-633816000 -10800 1 AMST}
+ {-622065600 -14400 0 AMT}
+ {-602280000 -10800 1 AMST}
+ {-591829200 -14400 0 AMT}
+ {-570744000 -10800 1 AMST}
+ {-560206800 -14400 0 AMT}
+ {-539121600 -10800 1 AMST}
+ {-531349200 -14400 0 AMT}
+ {-191361600 -10800 1 AMST}
+ {-184194000 -14400 0 AMT}
+ {-155160000 -10800 1 AMST}
+ {-150066000 -14400 0 AMT}
+ {-128894400 -10800 1 AMST}
+ {-121122000 -14400 0 AMT}
+ {-99950400 -10800 1 AMST}
+ {-89586000 -14400 0 AMT}
+ {-68414400 -10800 1 AMST}
+ {-57963600 -14400 0 AMT}
+ {499752000 -10800 1 AMST}
+ {511239600 -14400 0 AMT}
+ {530596800 -10800 1 AMST}
+ {540270000 -14400 0 AMT}
+ {562132800 -10800 1 AMST}
+ {571201200 -14400 0 AMT}
+ {590036400 -14400 0 AMT}
+}
diff --git a/library/tzdata/America/Puerto_Rico b/library/tzdata/America/Puerto_Rico
new file mode 100644
index 0000000..0d5c9b4
--- /dev/null
+++ b/library/tzdata/America/Puerto_Rico
@@ -0,0 +1,10 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Puerto_Rico) {
+ {-9223372036854775808 -15865 0 LMT}
+ {-2233035335 -14400 0 AST}
+ {-873057600 -10800 0 AWT}
+ {-769395600 -10800 1 APT}
+ {-765399600 -14400 0 AST}
+ {-757368000 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Rainy_River b/library/tzdata/America/Rainy_River
new file mode 100644
index 0000000..331bac6
--- /dev/null
+++ b/library/tzdata/America/Rainy_River
@@ -0,0 +1,264 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Rainy_River) {
+ {-9223372036854775808 -22696 0 LMT}
+ {-2366732504 -21600 0 CST}
+ {-1632067200 -18000 1 CDT}
+ {-1614790800 -21600 0 CST}
+ {-923248800 -18000 1 CDT}
+ {-880214400 -18000 0 CWT}
+ {-769395600 -18000 1 CPT}
+ {-765392400 -21600 0 CST}
+ {136368000 -18000 1 CDT}
+ {152089200 -21600 0 CST}
+ {167817600 -18000 1 CDT}
+ {183538800 -21600 0 CST}
+ {199267200 -18000 1 CDT}
+ {215593200 -21600 0 CST}
+ {230716800 -18000 1 CDT}
+ {247042800 -21600 0 CST}
+ {262771200 -18000 1 CDT}
+ {278492400 -21600 0 CST}
+ {294220800 -18000 1 CDT}
+ {309942000 -21600 0 CST}
+ {325670400 -18000 1 CDT}
+ {341391600 -21600 0 CST}
+ {357120000 -18000 1 CDT}
+ {372841200 -21600 0 CST}
+ {388569600 -18000 1 CDT}
+ {404895600 -21600 0 CST}
+ {420019200 -18000 1 CDT}
+ {436345200 -21600 0 CST}
+ {452073600 -18000 1 CDT}
+ {467794800 -21600 0 CST}
+ {483523200 -18000 1 CDT}
+ {499244400 -21600 0 CST}
+ {514972800 -18000 1 CDT}
+ {530694000 -21600 0 CST}
+ {544608000 -18000 1 CDT}
+ {562143600 -21600 0 CST}
+ {576057600 -18000 1 CDT}
+ {594198000 -21600 0 CST}
+ {607507200 -18000 1 CDT}
+ {625647600 -21600 0 CST}
+ {638956800 -18000 1 CDT}
+ {657097200 -21600 0 CST}
+ {671011200 -18000 1 CDT}
+ {688546800 -21600 0 CST}
+ {702460800 -18000 1 CDT}
+ {719996400 -21600 0 CST}
+ {733910400 -18000 1 CDT}
+ {752050800 -21600 0 CST}
+ {765360000 -18000 1 CDT}
+ {783500400 -21600 0 CST}
+ {796809600 -18000 1 CDT}
+ {814950000 -21600 0 CST}
+ {828864000 -18000 1 CDT}
+ {846399600 -21600 0 CST}
+ {860313600 -18000 1 CDT}
+ {877849200 -21600 0 CST}
+ {891763200 -18000 1 CDT}
+ {909298800 -21600 0 CST}
+ {923212800 -18000 1 CDT}
+ {941353200 -21600 0 CST}
+ {954662400 -18000 1 CDT}
+ {972802800 -21600 0 CST}
+ {986112000 -18000 1 CDT}
+ {1004252400 -21600 0 CST}
+ {1018166400 -18000 1 CDT}
+ {1035702000 -21600 0 CST}
+ {1049616000 -18000 1 CDT}
+ {1067151600 -21600 0 CST}
+ {1081065600 -18000 1 CDT}
+ {1099206000 -21600 0 CST}
+ {1112515200 -18000 1 CDT}
+ {1130655600 -21600 0 CST}
+ {1143964800 -18000 1 CDT}
+ {1162105200 -21600 0 CST}
+ {1173600000 -18000 1 CDT}
+ {1194159600 -21600 0 CST}
+ {1205049600 -18000 1 CDT}
+ {1225609200 -21600 0 CST}
+ {1236499200 -18000 1 CDT}
+ {1257058800 -21600 0 CST}
+ {1268553600 -18000 1 CDT}
+ {1289113200 -21600 0 CST}
+ {1300003200 -18000 1 CDT}
+ {1320562800 -21600 0 CST}
+ {1331452800 -18000 1 CDT}
+ {1352012400 -21600 0 CST}
+ {1362902400 -18000 1 CDT}
+ {1383462000 -21600 0 CST}
+ {1394352000 -18000 1 CDT}
+ {1414911600 -21600 0 CST}
+ {1425801600 -18000 1 CDT}
+ {1446361200 -21600 0 CST}
+ {1457856000 -18000 1 CDT}
+ {1478415600 -21600 0 CST}
+ {1489305600 -18000 1 CDT}
+ {1509865200 -21600 0 CST}
+ {1520755200 -18000 1 CDT}
+ {1541314800 -21600 0 CST}
+ {1552204800 -18000 1 CDT}
+ {1572764400 -21600 0 CST}
+ {1583654400 -18000 1 CDT}
+ {1604214000 -21600 0 CST}
+ {1615708800 -18000 1 CDT}
+ {1636268400 -21600 0 CST}
+ {1647158400 -18000 1 CDT}
+ {1667718000 -21600 0 CST}
+ {1678608000 -18000 1 CDT}
+ {1699167600 -21600 0 CST}
+ {1710057600 -18000 1 CDT}
+ {1730617200 -21600 0 CST}
+ {1741507200 -18000 1 CDT}
+ {1762066800 -21600 0 CST}
+ {1772956800 -18000 1 CDT}
+ {1793516400 -21600 0 CST}
+ {1805011200 -18000 1 CDT}
+ {1825570800 -21600 0 CST}
+ {1836460800 -18000 1 CDT}
+ {1857020400 -21600 0 CST}
+ {1867910400 -18000 1 CDT}
+ {1888470000 -21600 0 CST}
+ {1899360000 -18000 1 CDT}
+ {1919919600 -21600 0 CST}
+ {1930809600 -18000 1 CDT}
+ {1951369200 -21600 0 CST}
+ {1962864000 -18000 1 CDT}
+ {1983423600 -21600 0 CST}
+ {1994313600 -18000 1 CDT}
+ {2014873200 -21600 0 CST}
+ {2025763200 -18000 1 CDT}
+ {2046322800 -21600 0 CST}
+ {2057212800 -18000 1 CDT}
+ {2077772400 -21600 0 CST}
+ {2088662400 -18000 1 CDT}
+ {2109222000 -21600 0 CST}
+ {2120112000 -18000 1 CDT}
+ {2140671600 -21600 0 CST}
+ {2152166400 -18000 1 CDT}
+ {2172726000 -21600 0 CST}
+ {2183616000 -18000 1 CDT}
+ {2204175600 -21600 0 CST}
+ {2215065600 -18000 1 CDT}
+ {2235625200 -21600 0 CST}
+ {2246515200 -18000 1 CDT}
+ {2267074800 -21600 0 CST}
+ {2277964800 -18000 1 CDT}
+ {2298524400 -21600 0 CST}
+ {2309414400 -18000 1 CDT}
+ {2329974000 -21600 0 CST}
+ {2341468800 -18000 1 CDT}
+ {2362028400 -21600 0 CST}
+ {2372918400 -18000 1 CDT}
+ {2393478000 -21600 0 CST}
+ {2404368000 -18000 1 CDT}
+ {2424927600 -21600 0 CST}
+ {2435817600 -18000 1 CDT}
+ {2456377200 -21600 0 CST}
+ {2467267200 -18000 1 CDT}
+ {2487826800 -21600 0 CST}
+ {2499321600 -18000 1 CDT}
+ {2519881200 -21600 0 CST}
+ {2530771200 -18000 1 CDT}
+ {2551330800 -21600 0 CST}
+ {2562220800 -18000 1 CDT}
+ {2582780400 -21600 0 CST}
+ {2593670400 -18000 1 CDT}
+ {2614230000 -21600 0 CST}
+ {2625120000 -18000 1 CDT}
+ {2645679600 -21600 0 CST}
+ {2656569600 -18000 1 CDT}
+ {2677129200 -21600 0 CST}
+ {2688624000 -18000 1 CDT}
+ {2709183600 -21600 0 CST}
+ {2720073600 -18000 1 CDT}
+ {2740633200 -21600 0 CST}
+ {2751523200 -18000 1 CDT}
+ {2772082800 -21600 0 CST}
+ {2782972800 -18000 1 CDT}
+ {2803532400 -21600 0 CST}
+ {2814422400 -18000 1 CDT}
+ {2834982000 -21600 0 CST}
+ {2846476800 -18000 1 CDT}
+ {2867036400 -21600 0 CST}
+ {2877926400 -18000 1 CDT}
+ {2898486000 -21600 0 CST}
+ {2909376000 -18000 1 CDT}
+ {2929935600 -21600 0 CST}
+ {2940825600 -18000 1 CDT}
+ {2961385200 -21600 0 CST}
+ {2972275200 -18000 1 CDT}
+ {2992834800 -21600 0 CST}
+ {3003724800 -18000 1 CDT}
+ {3024284400 -21600 0 CST}
+ {3035779200 -18000 1 CDT}
+ {3056338800 -21600 0 CST}
+ {3067228800 -18000 1 CDT}
+ {3087788400 -21600 0 CST}
+ {3098678400 -18000 1 CDT}
+ {3119238000 -21600 0 CST}
+ {3130128000 -18000 1 CDT}
+ {3150687600 -21600 0 CST}
+ {3161577600 -18000 1 CDT}
+ {3182137200 -21600 0 CST}
+ {3193027200 -18000 1 CDT}
+ {3213586800 -21600 0 CST}
+ {3225081600 -18000 1 CDT}
+ {3245641200 -21600 0 CST}
+ {3256531200 -18000 1 CDT}
+ {3277090800 -21600 0 CST}
+ {3287980800 -18000 1 CDT}
+ {3308540400 -21600 0 CST}
+ {3319430400 -18000 1 CDT}
+ {3339990000 -21600 0 CST}
+ {3350880000 -18000 1 CDT}
+ {3371439600 -21600 0 CST}
+ {3382934400 -18000 1 CDT}
+ {3403494000 -21600 0 CST}
+ {3414384000 -18000 1 CDT}
+ {3434943600 -21600 0 CST}
+ {3445833600 -18000 1 CDT}
+ {3466393200 -21600 0 CST}
+ {3477283200 -18000 1 CDT}
+ {3497842800 -21600 0 CST}
+ {3508732800 -18000 1 CDT}
+ {3529292400 -21600 0 CST}
+ {3540182400 -18000 1 CDT}
+ {3560742000 -21600 0 CST}
+ {3572236800 -18000 1 CDT}
+ {3592796400 -21600 0 CST}
+ {3603686400 -18000 1 CDT}
+ {3624246000 -21600 0 CST}
+ {3635136000 -18000 1 CDT}
+ {3655695600 -21600 0 CST}
+ {3666585600 -18000 1 CDT}
+ {3687145200 -21600 0 CST}
+ {3698035200 -18000 1 CDT}
+ {3718594800 -21600 0 CST}
+ {3730089600 -18000 1 CDT}
+ {3750649200 -21600 0 CST}
+ {3761539200 -18000 1 CDT}
+ {3782098800 -21600 0 CST}
+ {3792988800 -18000 1 CDT}
+ {3813548400 -21600 0 CST}
+ {3824438400 -18000 1 CDT}
+ {3844998000 -21600 0 CST}
+ {3855888000 -18000 1 CDT}
+ {3876447600 -21600 0 CST}
+ {3887337600 -18000 1 CDT}
+ {3907897200 -21600 0 CST}
+ {3919392000 -18000 1 CDT}
+ {3939951600 -21600 0 CST}
+ {3950841600 -18000 1 CDT}
+ {3971401200 -21600 0 CST}
+ {3982291200 -18000 1 CDT}
+ {4002850800 -21600 0 CST}
+ {4013740800 -18000 1 CDT}
+ {4034300400 -21600 0 CST}
+ {4045190400 -18000 1 CDT}
+ {4065750000 -21600 0 CST}
+ {4076640000 -18000 1 CDT}
+ {4097199600 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Rankin_Inlet b/library/tzdata/America/Rankin_Inlet
new file mode 100644
index 0000000..770ec5d
--- /dev/null
+++ b/library/tzdata/America/Rankin_Inlet
@@ -0,0 +1,248 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Rankin_Inlet) {
+ {-9223372036854775808 0 0 zzz}
+ {-410227200 -21600 0 CST}
+ {-147895200 -14400 1 CDDT}
+ {-131565600 -21600 0 CST}
+ {325670400 -18000 1 CDT}
+ {341391600 -21600 0 CST}
+ {357120000 -18000 1 CDT}
+ {372841200 -21600 0 CST}
+ {388569600 -18000 1 CDT}
+ {404895600 -21600 0 CST}
+ {420019200 -18000 1 CDT}
+ {436345200 -21600 0 CST}
+ {452073600 -18000 1 CDT}
+ {467794800 -21600 0 CST}
+ {483523200 -18000 1 CDT}
+ {499244400 -21600 0 CST}
+ {514972800 -18000 1 CDT}
+ {530694000 -21600 0 CST}
+ {544608000 -18000 1 CDT}
+ {562143600 -21600 0 CST}
+ {576057600 -18000 1 CDT}
+ {594198000 -21600 0 CST}
+ {607507200 -18000 1 CDT}
+ {625647600 -21600 0 CST}
+ {638956800 -18000 1 CDT}
+ {657097200 -21600 0 CST}
+ {671011200 -18000 1 CDT}
+ {688546800 -21600 0 CST}
+ {702460800 -18000 1 CDT}
+ {719996400 -21600 0 CST}
+ {733910400 -18000 1 CDT}
+ {752050800 -21600 0 CST}
+ {765360000 -18000 1 CDT}
+ {783500400 -21600 0 CST}
+ {796809600 -18000 1 CDT}
+ {814950000 -21600 0 CST}
+ {828864000 -18000 1 CDT}
+ {846399600 -21600 0 CST}
+ {860313600 -18000 1 CDT}
+ {877849200 -21600 0 CST}
+ {891763200 -18000 1 CDT}
+ {909298800 -21600 0 CST}
+ {923212800 -18000 1 CDT}
+ {941353200 -21600 0 CST}
+ {954662400 -18000 1 CDT}
+ {972806400 -18000 0 EST}
+ {986112000 -18000 0 CDT}
+ {1004252400 -21600 0 CST}
+ {1018166400 -18000 1 CDT}
+ {1035702000 -21600 0 CST}
+ {1049616000 -18000 1 CDT}
+ {1067151600 -21600 0 CST}
+ {1081065600 -18000 1 CDT}
+ {1099206000 -21600 0 CST}
+ {1112515200 -18000 1 CDT}
+ {1130655600 -21600 0 CST}
+ {1143964800 -18000 1 CDT}
+ {1162105200 -21600 0 CST}
+ {1173600000 -18000 1 CDT}
+ {1194159600 -21600 0 CST}
+ {1205049600 -18000 1 CDT}
+ {1225609200 -21600 0 CST}
+ {1236499200 -18000 1 CDT}
+ {1257058800 -21600 0 CST}
+ {1268553600 -18000 1 CDT}
+ {1289113200 -21600 0 CST}
+ {1300003200 -18000 1 CDT}
+ {1320562800 -21600 0 CST}
+ {1331452800 -18000 1 CDT}
+ {1352012400 -21600 0 CST}
+ {1362902400 -18000 1 CDT}
+ {1383462000 -21600 0 CST}
+ {1394352000 -18000 1 CDT}
+ {1414911600 -21600 0 CST}
+ {1425801600 -18000 1 CDT}
+ {1446361200 -21600 0 CST}
+ {1457856000 -18000 1 CDT}
+ {1478415600 -21600 0 CST}
+ {1489305600 -18000 1 CDT}
+ {1509865200 -21600 0 CST}
+ {1520755200 -18000 1 CDT}
+ {1541314800 -21600 0 CST}
+ {1552204800 -18000 1 CDT}
+ {1572764400 -21600 0 CST}
+ {1583654400 -18000 1 CDT}
+ {1604214000 -21600 0 CST}
+ {1615708800 -18000 1 CDT}
+ {1636268400 -21600 0 CST}
+ {1647158400 -18000 1 CDT}
+ {1667718000 -21600 0 CST}
+ {1678608000 -18000 1 CDT}
+ {1699167600 -21600 0 CST}
+ {1710057600 -18000 1 CDT}
+ {1730617200 -21600 0 CST}
+ {1741507200 -18000 1 CDT}
+ {1762066800 -21600 0 CST}
+ {1772956800 -18000 1 CDT}
+ {1793516400 -21600 0 CST}
+ {1805011200 -18000 1 CDT}
+ {1825570800 -21600 0 CST}
+ {1836460800 -18000 1 CDT}
+ {1857020400 -21600 0 CST}
+ {1867910400 -18000 1 CDT}
+ {1888470000 -21600 0 CST}
+ {1899360000 -18000 1 CDT}
+ {1919919600 -21600 0 CST}
+ {1930809600 -18000 1 CDT}
+ {1951369200 -21600 0 CST}
+ {1962864000 -18000 1 CDT}
+ {1983423600 -21600 0 CST}
+ {1994313600 -18000 1 CDT}
+ {2014873200 -21600 0 CST}
+ {2025763200 -18000 1 CDT}
+ {2046322800 -21600 0 CST}
+ {2057212800 -18000 1 CDT}
+ {2077772400 -21600 0 CST}
+ {2088662400 -18000 1 CDT}
+ {2109222000 -21600 0 CST}
+ {2120112000 -18000 1 CDT}
+ {2140671600 -21600 0 CST}
+ {2152166400 -18000 1 CDT}
+ {2172726000 -21600 0 CST}
+ {2183616000 -18000 1 CDT}
+ {2204175600 -21600 0 CST}
+ {2215065600 -18000 1 CDT}
+ {2235625200 -21600 0 CST}
+ {2246515200 -18000 1 CDT}
+ {2267074800 -21600 0 CST}
+ {2277964800 -18000 1 CDT}
+ {2298524400 -21600 0 CST}
+ {2309414400 -18000 1 CDT}
+ {2329974000 -21600 0 CST}
+ {2341468800 -18000 1 CDT}
+ {2362028400 -21600 0 CST}
+ {2372918400 -18000 1 CDT}
+ {2393478000 -21600 0 CST}
+ {2404368000 -18000 1 CDT}
+ {2424927600 -21600 0 CST}
+ {2435817600 -18000 1 CDT}
+ {2456377200 -21600 0 CST}
+ {2467267200 -18000 1 CDT}
+ {2487826800 -21600 0 CST}
+ {2499321600 -18000 1 CDT}
+ {2519881200 -21600 0 CST}
+ {2530771200 -18000 1 CDT}
+ {2551330800 -21600 0 CST}
+ {2562220800 -18000 1 CDT}
+ {2582780400 -21600 0 CST}
+ {2593670400 -18000 1 CDT}
+ {2614230000 -21600 0 CST}
+ {2625120000 -18000 1 CDT}
+ {2645679600 -21600 0 CST}
+ {2656569600 -18000 1 CDT}
+ {2677129200 -21600 0 CST}
+ {2688624000 -18000 1 CDT}
+ {2709183600 -21600 0 CST}
+ {2720073600 -18000 1 CDT}
+ {2740633200 -21600 0 CST}
+ {2751523200 -18000 1 CDT}
+ {2772082800 -21600 0 CST}
+ {2782972800 -18000 1 CDT}
+ {2803532400 -21600 0 CST}
+ {2814422400 -18000 1 CDT}
+ {2834982000 -21600 0 CST}
+ {2846476800 -18000 1 CDT}
+ {2867036400 -21600 0 CST}
+ {2877926400 -18000 1 CDT}
+ {2898486000 -21600 0 CST}
+ {2909376000 -18000 1 CDT}
+ {2929935600 -21600 0 CST}
+ {2940825600 -18000 1 CDT}
+ {2961385200 -21600 0 CST}
+ {2972275200 -18000 1 CDT}
+ {2992834800 -21600 0 CST}
+ {3003724800 -18000 1 CDT}
+ {3024284400 -21600 0 CST}
+ {3035779200 -18000 1 CDT}
+ {3056338800 -21600 0 CST}
+ {3067228800 -18000 1 CDT}
+ {3087788400 -21600 0 CST}
+ {3098678400 -18000 1 CDT}
+ {3119238000 -21600 0 CST}
+ {3130128000 -18000 1 CDT}
+ {3150687600 -21600 0 CST}
+ {3161577600 -18000 1 CDT}
+ {3182137200 -21600 0 CST}
+ {3193027200 -18000 1 CDT}
+ {3213586800 -21600 0 CST}
+ {3225081600 -18000 1 CDT}
+ {3245641200 -21600 0 CST}
+ {3256531200 -18000 1 CDT}
+ {3277090800 -21600 0 CST}
+ {3287980800 -18000 1 CDT}
+ {3308540400 -21600 0 CST}
+ {3319430400 -18000 1 CDT}
+ {3339990000 -21600 0 CST}
+ {3350880000 -18000 1 CDT}
+ {3371439600 -21600 0 CST}
+ {3382934400 -18000 1 CDT}
+ {3403494000 -21600 0 CST}
+ {3414384000 -18000 1 CDT}
+ {3434943600 -21600 0 CST}
+ {3445833600 -18000 1 CDT}
+ {3466393200 -21600 0 CST}
+ {3477283200 -18000 1 CDT}
+ {3497842800 -21600 0 CST}
+ {3508732800 -18000 1 CDT}
+ {3529292400 -21600 0 CST}
+ {3540182400 -18000 1 CDT}
+ {3560742000 -21600 0 CST}
+ {3572236800 -18000 1 CDT}
+ {3592796400 -21600 0 CST}
+ {3603686400 -18000 1 CDT}
+ {3624246000 -21600 0 CST}
+ {3635136000 -18000 1 CDT}
+ {3655695600 -21600 0 CST}
+ {3666585600 -18000 1 CDT}
+ {3687145200 -21600 0 CST}
+ {3698035200 -18000 1 CDT}
+ {3718594800 -21600 0 CST}
+ {3730089600 -18000 1 CDT}
+ {3750649200 -21600 0 CST}
+ {3761539200 -18000 1 CDT}
+ {3782098800 -21600 0 CST}
+ {3792988800 -18000 1 CDT}
+ {3813548400 -21600 0 CST}
+ {3824438400 -18000 1 CDT}
+ {3844998000 -21600 0 CST}
+ {3855888000 -18000 1 CDT}
+ {3876447600 -21600 0 CST}
+ {3887337600 -18000 1 CDT}
+ {3907897200 -21600 0 CST}
+ {3919392000 -18000 1 CDT}
+ {3939951600 -21600 0 CST}
+ {3950841600 -18000 1 CDT}
+ {3971401200 -21600 0 CST}
+ {3982291200 -18000 1 CDT}
+ {4002850800 -21600 0 CST}
+ {4013740800 -18000 1 CDT}
+ {4034300400 -21600 0 CST}
+ {4045190400 -18000 1 CDT}
+ {4065750000 -21600 0 CST}
+ {4076640000 -18000 1 CDT}
+ {4097199600 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Recife b/library/tzdata/America/Recife
new file mode 100644
index 0000000..f6ae00e
--- /dev/null
+++ b/library/tzdata/America/Recife
@@ -0,0 +1,48 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Recife) {
+ {-9223372036854775808 -8376 0 LMT}
+ {-1767217224 -10800 0 BRT}
+ {-1206957600 -7200 1 BRST}
+ {-1191362400 -10800 0 BRT}
+ {-1175374800 -7200 1 BRST}
+ {-1159826400 -10800 0 BRT}
+ {-633819600 -7200 1 BRST}
+ {-622069200 -10800 0 BRT}
+ {-602283600 -7200 1 BRST}
+ {-591832800 -10800 0 BRT}
+ {-570747600 -7200 1 BRST}
+ {-560210400 -10800 0 BRT}
+ {-539125200 -7200 1 BRST}
+ {-531352800 -10800 0 BRT}
+ {-191365200 -7200 1 BRST}
+ {-184197600 -10800 0 BRT}
+ {-155163600 -7200 1 BRST}
+ {-150069600 -10800 0 BRT}
+ {-128898000 -7200 1 BRST}
+ {-121125600 -10800 0 BRT}
+ {-99954000 -7200 1 BRST}
+ {-89589600 -10800 0 BRT}
+ {-68418000 -7200 1 BRST}
+ {-57967200 -10800 0 BRT}
+ {499748400 -7200 1 BRST}
+ {511236000 -10800 0 BRT}
+ {530593200 -7200 1 BRST}
+ {540266400 -10800 0 BRT}
+ {562129200 -7200 1 BRST}
+ {571197600 -10800 0 BRT}
+ {592974000 -7200 1 BRST}
+ {602042400 -10800 0 BRT}
+ {624423600 -7200 1 BRST}
+ {634701600 -10800 0 BRT}
+ {653536800 -10800 0 BRT}
+ {938660400 -10800 0 BRT}
+ {938919600 -7200 1 BRST}
+ {951616800 -10800 0 BRT}
+ {970974000 -7200 1 BRST}
+ {971575200 -10800 0 BRT}
+ {1000350000 -10800 0 BRT}
+ {1003028400 -7200 1 BRST}
+ {1013911200 -10800 0 BRT}
+ {1033437600 -10800 0 BRT}
+}
diff --git a/library/tzdata/America/Regina b/library/tzdata/America/Regina
new file mode 100644
index 0000000..2030d75
--- /dev/null
+++ b/library/tzdata/America/Regina
@@ -0,0 +1,58 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Regina) {
+ {-9223372036854775808 -25116 0 LMT}
+ {-2030202084 -25200 0 MST}
+ {-1632063600 -21600 1 MDT}
+ {-1614787200 -25200 0 MST}
+ {-1251651600 -21600 1 MDT}
+ {-1238349600 -25200 0 MST}
+ {-1220202000 -21600 1 MDT}
+ {-1206900000 -25200 0 MST}
+ {-1188752400 -21600 1 MDT}
+ {-1175450400 -25200 0 MST}
+ {-1156698000 -21600 1 MDT}
+ {-1144000800 -25200 0 MST}
+ {-1125248400 -21600 1 MDT}
+ {-1111946400 -25200 0 MST}
+ {-1032714000 -21600 1 MDT}
+ {-1016992800 -25200 0 MST}
+ {-1001264400 -21600 1 MDT}
+ {-986148000 -25200 0 MST}
+ {-969814800 -21600 1 MDT}
+ {-954093600 -25200 0 MST}
+ {-937760400 -21600 1 MDT}
+ {-922039200 -25200 0 MST}
+ {-906310800 -21600 1 MDT}
+ {-890589600 -25200 0 MST}
+ {-880210800 -21600 1 MWT}
+ {-769395600 -21600 1 MPT}
+ {-765388800 -25200 0 MST}
+ {-748450800 -21600 1 MDT}
+ {-732729600 -25200 0 MST}
+ {-715791600 -21600 1 MDT}
+ {-702489600 -25200 0 MST}
+ {-684342000 -21600 1 MDT}
+ {-671040000 -25200 0 MST}
+ {-652892400 -21600 1 MDT}
+ {-639590400 -25200 0 MST}
+ {-620838000 -21600 1 MDT}
+ {-608140800 -25200 0 MST}
+ {-589388400 -21600 1 MDT}
+ {-576086400 -25200 0 MST}
+ {-557938800 -21600 1 MDT}
+ {-544636800 -25200 0 MST}
+ {-526489200 -21600 1 MDT}
+ {-513187200 -25200 0 MST}
+ {-495039600 -21600 1 MDT}
+ {-481737600 -25200 0 MST}
+ {-463590000 -21600 1 MDT}
+ {-450288000 -25200 0 MST}
+ {-431535600 -21600 1 MDT}
+ {-418233600 -25200 0 MST}
+ {-400086000 -21600 1 MDT}
+ {-386784000 -25200 0 MST}
+ {-337186800 -21600 1 MDT}
+ {-321465600 -25200 0 MST}
+ {-305737200 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Resolute b/library/tzdata/America/Resolute
new file mode 100755
index 0000000..50ab9df
--- /dev/null
+++ b/library/tzdata/America/Resolute
@@ -0,0 +1,249 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Resolute) {
+ {-9223372036854775808 0 0 zzz}
+ {-704937600 -21600 0 CST}
+ {-147895200 -14400 1 CDDT}
+ {-131565600 -21600 0 CST}
+ {325670400 -18000 1 CDT}
+ {341391600 -21600 0 CST}
+ {357120000 -18000 1 CDT}
+ {372841200 -21600 0 CST}
+ {388569600 -18000 1 CDT}
+ {404895600 -21600 0 CST}
+ {420019200 -18000 1 CDT}
+ {436345200 -21600 0 CST}
+ {452073600 -18000 1 CDT}
+ {467794800 -21600 0 CST}
+ {483523200 -18000 1 CDT}
+ {499244400 -21600 0 CST}
+ {514972800 -18000 1 CDT}
+ {530694000 -21600 0 CST}
+ {544608000 -18000 1 CDT}
+ {562143600 -21600 0 CST}
+ {576057600 -18000 1 CDT}
+ {594198000 -21600 0 CST}
+ {607507200 -18000 1 CDT}
+ {625647600 -21600 0 CST}
+ {638956800 -18000 1 CDT}
+ {657097200 -21600 0 CST}
+ {671011200 -18000 1 CDT}
+ {688546800 -21600 0 CST}
+ {702460800 -18000 1 CDT}
+ {719996400 -21600 0 CST}
+ {733910400 -18000 1 CDT}
+ {752050800 -21600 0 CST}
+ {765360000 -18000 1 CDT}
+ {783500400 -21600 0 CST}
+ {796809600 -18000 1 CDT}
+ {814950000 -21600 0 CST}
+ {828864000 -18000 1 CDT}
+ {846399600 -21600 0 CST}
+ {860313600 -18000 1 CDT}
+ {877849200 -21600 0 CST}
+ {891763200 -18000 1 CDT}
+ {909298800 -21600 0 CST}
+ {923212800 -18000 1 CDT}
+ {941353200 -21600 0 CST}
+ {954662400 -18000 1 CDT}
+ {972806400 -18000 0 EST}
+ {986112000 -18000 0 CDT}
+ {1004252400 -21600 0 CST}
+ {1018166400 -18000 1 CDT}
+ {1035702000 -21600 0 CST}
+ {1049616000 -18000 1 CDT}
+ {1067151600 -21600 0 CST}
+ {1081065600 -18000 1 CDT}
+ {1099206000 -21600 0 CST}
+ {1112515200 -18000 1 CDT}
+ {1130655600 -21600 0 CST}
+ {1143964800 -18000 1 CDT}
+ {1162108800 -18000 0 EST}
+ {1162710000 -18000 0 EST}
+ {1173596400 -18000 0 CDT}
+ {1194159600 -18000 0 EST}
+ {1205046000 -18000 0 CDT}
+ {1225609200 -18000 0 EST}
+ {1236495600 -18000 0 CDT}
+ {1257058800 -18000 0 EST}
+ {1268550000 -18000 0 CDT}
+ {1289113200 -18000 0 EST}
+ {1299999600 -18000 0 CDT}
+ {1320562800 -18000 0 EST}
+ {1331449200 -18000 0 CDT}
+ {1352012400 -18000 0 EST}
+ {1362898800 -18000 0 CDT}
+ {1383462000 -18000 0 EST}
+ {1394348400 -18000 0 CDT}
+ {1414911600 -18000 0 EST}
+ {1425798000 -18000 0 CDT}
+ {1446361200 -18000 0 EST}
+ {1457852400 -18000 0 CDT}
+ {1478415600 -18000 0 EST}
+ {1489302000 -18000 0 CDT}
+ {1509865200 -18000 0 EST}
+ {1520751600 -18000 0 CDT}
+ {1541314800 -18000 0 EST}
+ {1552201200 -18000 0 CDT}
+ {1572764400 -18000 0 EST}
+ {1583650800 -18000 0 CDT}
+ {1604214000 -18000 0 EST}
+ {1615705200 -18000 0 CDT}
+ {1636268400 -18000 0 EST}
+ {1647154800 -18000 0 CDT}
+ {1667718000 -18000 0 EST}
+ {1678604400 -18000 0 CDT}
+ {1699167600 -18000 0 EST}
+ {1710054000 -18000 0 CDT}
+ {1730617200 -18000 0 EST}
+ {1741503600 -18000 0 CDT}
+ {1762066800 -18000 0 EST}
+ {1772953200 -18000 0 CDT}
+ {1793516400 -18000 0 EST}
+ {1805007600 -18000 0 CDT}
+ {1825570800 -18000 0 EST}
+ {1836457200 -18000 0 CDT}
+ {1857020400 -18000 0 EST}
+ {1867906800 -18000 0 CDT}
+ {1888470000 -18000 0 EST}
+ {1899356400 -18000 0 CDT}
+ {1919919600 -18000 0 EST}
+ {1930806000 -18000 0 CDT}
+ {1951369200 -18000 0 EST}
+ {1962860400 -18000 0 CDT}
+ {1983423600 -18000 0 EST}
+ {1994310000 -18000 0 CDT}
+ {2014873200 -18000 0 EST}
+ {2025759600 -18000 0 CDT}
+ {2046322800 -18000 0 EST}
+ {2057209200 -18000 0 CDT}
+ {2077772400 -18000 0 EST}
+ {2088658800 -18000 0 CDT}
+ {2109222000 -18000 0 EST}
+ {2120108400 -18000 0 CDT}
+ {2140671600 -18000 0 EST}
+ {2152162800 -18000 0 CDT}
+ {2172726000 -18000 0 EST}
+ {2183612400 -18000 0 CDT}
+ {2204175600 -18000 0 EST}
+ {2215062000 -18000 0 CDT}
+ {2235625200 -18000 0 EST}
+ {2246511600 -18000 0 CDT}
+ {2267074800 -18000 0 EST}
+ {2277961200 -18000 0 CDT}
+ {2298524400 -18000 0 EST}
+ {2309410800 -18000 0 CDT}
+ {2329974000 -18000 0 EST}
+ {2341465200 -18000 0 CDT}
+ {2362028400 -18000 0 EST}
+ {2372914800 -18000 0 CDT}
+ {2393478000 -18000 0 EST}
+ {2404364400 -18000 0 CDT}
+ {2424927600 -18000 0 EST}
+ {2435814000 -18000 0 CDT}
+ {2456377200 -18000 0 EST}
+ {2467263600 -18000 0 CDT}
+ {2487826800 -18000 0 EST}
+ {2499318000 -18000 0 CDT}
+ {2519881200 -18000 0 EST}
+ {2530767600 -18000 0 CDT}
+ {2551330800 -18000 0 EST}
+ {2562217200 -18000 0 CDT}
+ {2582780400 -18000 0 EST}
+ {2593666800 -18000 0 CDT}
+ {2614230000 -18000 0 EST}
+ {2625116400 -18000 0 CDT}
+ {2645679600 -18000 0 EST}
+ {2656566000 -18000 0 CDT}
+ {2677129200 -18000 0 EST}
+ {2688620400 -18000 0 CDT}
+ {2709183600 -18000 0 EST}
+ {2720070000 -18000 0 CDT}
+ {2740633200 -18000 0 EST}
+ {2751519600 -18000 0 CDT}
+ {2772082800 -18000 0 EST}
+ {2782969200 -18000 0 CDT}
+ {2803532400 -18000 0 EST}
+ {2814418800 -18000 0 CDT}
+ {2834982000 -18000 0 EST}
+ {2846473200 -18000 0 CDT}
+ {2867036400 -18000 0 EST}
+ {2877922800 -18000 0 CDT}
+ {2898486000 -18000 0 EST}
+ {2909372400 -18000 0 CDT}
+ {2929935600 -18000 0 EST}
+ {2940822000 -18000 0 CDT}
+ {2961385200 -18000 0 EST}
+ {2972271600 -18000 0 CDT}
+ {2992834800 -18000 0 EST}
+ {3003721200 -18000 0 CDT}
+ {3024284400 -18000 0 EST}
+ {3035775600 -18000 0 CDT}
+ {3056338800 -18000 0 EST}
+ {3067225200 -18000 0 CDT}
+ {3087788400 -18000 0 EST}
+ {3098674800 -18000 0 CDT}
+ {3119238000 -18000 0 EST}
+ {3130124400 -18000 0 CDT}
+ {3150687600 -18000 0 EST}
+ {3161574000 -18000 0 CDT}
+ {3182137200 -18000 0 EST}
+ {3193023600 -18000 0 CDT}
+ {3213586800 -18000 0 EST}
+ {3225078000 -18000 0 CDT}
+ {3245641200 -18000 0 EST}
+ {3256527600 -18000 0 CDT}
+ {3277090800 -18000 0 EST}
+ {3287977200 -18000 0 CDT}
+ {3308540400 -18000 0 EST}
+ {3319426800 -18000 0 CDT}
+ {3339990000 -18000 0 EST}
+ {3350876400 -18000 0 CDT}
+ {3371439600 -18000 0 EST}
+ {3382930800 -18000 0 CDT}
+ {3403494000 -18000 0 EST}
+ {3414380400 -18000 0 CDT}
+ {3434943600 -18000 0 EST}
+ {3445830000 -18000 0 CDT}
+ {3466393200 -18000 0 EST}
+ {3477279600 -18000 0 CDT}
+ {3497842800 -18000 0 EST}
+ {3508729200 -18000 0 CDT}
+ {3529292400 -18000 0 EST}
+ {3540178800 -18000 0 CDT}
+ {3560742000 -18000 0 EST}
+ {3572233200 -18000 0 CDT}
+ {3592796400 -18000 0 EST}
+ {3603682800 -18000 0 CDT}
+ {3624246000 -18000 0 EST}
+ {3635132400 -18000 0 CDT}
+ {3655695600 -18000 0 EST}
+ {3666582000 -18000 0 CDT}
+ {3687145200 -18000 0 EST}
+ {3698031600 -18000 0 CDT}
+ {3718594800 -18000 0 EST}
+ {3730086000 -18000 0 CDT}
+ {3750649200 -18000 0 EST}
+ {3761535600 -18000 0 CDT}
+ {3782098800 -18000 0 EST}
+ {3792985200 -18000 0 CDT}
+ {3813548400 -18000 0 EST}
+ {3824434800 -18000 0 CDT}
+ {3844998000 -18000 0 EST}
+ {3855884400 -18000 0 CDT}
+ {3876447600 -18000 0 EST}
+ {3887334000 -18000 0 CDT}
+ {3907897200 -18000 0 EST}
+ {3919388400 -18000 0 CDT}
+ {3939951600 -18000 0 EST}
+ {3950838000 -18000 0 CDT}
+ {3971401200 -18000 0 EST}
+ {3982287600 -18000 0 CDT}
+ {4002850800 -18000 0 EST}
+ {4013737200 -18000 0 CDT}
+ {4034300400 -18000 0 EST}
+ {4045186800 -18000 0 CDT}
+ {4065750000 -18000 0 EST}
+ {4076636400 -18000 0 CDT}
+ {4097199600 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Rio_Branco b/library/tzdata/America/Rio_Branco
new file mode 100644
index 0000000..20889cb
--- /dev/null
+++ b/library/tzdata/America/Rio_Branco
@@ -0,0 +1,36 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Rio_Branco) {
+ {-9223372036854775808 -16272 0 LMT}
+ {-1767209328 -18000 0 ACT}
+ {-1206950400 -14400 1 ACST}
+ {-1191355200 -18000 0 ACT}
+ {-1175367600 -14400 1 ACST}
+ {-1159819200 -18000 0 ACT}
+ {-633812400 -14400 1 ACST}
+ {-622062000 -18000 0 ACT}
+ {-602276400 -14400 1 ACST}
+ {-591825600 -18000 0 ACT}
+ {-570740400 -14400 1 ACST}
+ {-560203200 -18000 0 ACT}
+ {-539118000 -14400 1 ACST}
+ {-531345600 -18000 0 ACT}
+ {-191358000 -14400 1 ACST}
+ {-184190400 -18000 0 ACT}
+ {-155156400 -14400 1 ACST}
+ {-150062400 -18000 0 ACT}
+ {-128890800 -14400 1 ACST}
+ {-121118400 -18000 0 ACT}
+ {-99946800 -14400 1 ACST}
+ {-89582400 -18000 0 ACT}
+ {-68410800 -14400 1 ACST}
+ {-57960000 -18000 0 ACT}
+ {499755600 -14400 1 ACST}
+ {511243200 -18000 0 ACT}
+ {530600400 -14400 1 ACST}
+ {540273600 -18000 0 ACT}
+ {562136400 -14400 1 ACST}
+ {571204800 -18000 0 ACT}
+ {590040000 -18000 0 ACT}
+ {1214283600 -14400 0 AMT}
+}
diff --git a/library/tzdata/America/Rosario b/library/tzdata/America/Rosario
new file mode 100644
index 0000000..6687f88
--- /dev/null
+++ b/library/tzdata/America/Rosario
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Argentina/Cordoba)]} {
+ LoadTimeZoneFile America/Argentina/Cordoba
+}
+set TZData(:America/Rosario) $TZData(:America/Argentina/Cordoba)
diff --git a/library/tzdata/America/Santa_Isabel b/library/tzdata/America/Santa_Isabel
new file mode 100644
index 0000000..87cb5a8
--- /dev/null
+++ b/library/tzdata/America/Santa_Isabel
@@ -0,0 +1,284 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Santa_Isabel) {
+ {-9223372036854775808 -27568 0 LMT}
+ {-1514736000 -25200 0 MST}
+ {-1451667600 -28800 0 PST}
+ {-1343062800 -25200 0 MST}
+ {-1234803600 -28800 0 PST}
+ {-1222963200 -25200 1 PDT}
+ {-1207242000 -28800 0 PST}
+ {-873820800 -25200 1 PWT}
+ {-769395600 -25200 1 PPT}
+ {-761677200 -28800 0 PST}
+ {-686073600 -25200 1 PDT}
+ {-661539600 -28800 0 PST}
+ {-504892800 -28800 0 PST}
+ {-495036000 -25200 1 PDT}
+ {-481734000 -28800 0 PST}
+ {-463586400 -25200 1 PDT}
+ {-450284400 -28800 0 PST}
+ {-431532000 -25200 1 PDT}
+ {-418230000 -28800 0 PST}
+ {-400082400 -25200 1 PDT}
+ {-386780400 -28800 0 PST}
+ {-368632800 -25200 1 PDT}
+ {-355330800 -28800 0 PST}
+ {-337183200 -25200 1 PDT}
+ {-323881200 -28800 0 PST}
+ {-305733600 -25200 1 PDT}
+ {-292431600 -28800 0 PST}
+ {-283968000 -28800 0 PST}
+ {189331200 -28800 0 PST}
+ {199274400 -25200 1 PDT}
+ {215600400 -28800 0 PST}
+ {230724000 -25200 1 PDT}
+ {247050000 -28800 0 PST}
+ {262778400 -25200 1 PDT}
+ {278499600 -28800 0 PST}
+ {294228000 -25200 1 PDT}
+ {309949200 -28800 0 PST}
+ {325677600 -25200 1 PDT}
+ {341398800 -28800 0 PST}
+ {357127200 -25200 1 PDT}
+ {372848400 -28800 0 PST}
+ {388576800 -25200 1 PDT}
+ {404902800 -28800 0 PST}
+ {420026400 -25200 1 PDT}
+ {436352400 -28800 0 PST}
+ {452080800 -25200 1 PDT}
+ {467802000 -28800 0 PST}
+ {483530400 -25200 1 PDT}
+ {499251600 -28800 0 PST}
+ {514980000 -25200 1 PDT}
+ {530701200 -28800 0 PST}
+ {544615200 -25200 1 PDT}
+ {562150800 -28800 0 PST}
+ {576064800 -25200 1 PDT}
+ {594205200 -28800 0 PST}
+ {607514400 -25200 1 PDT}
+ {625654800 -28800 0 PST}
+ {638964000 -25200 1 PDT}
+ {657104400 -28800 0 PST}
+ {671018400 -25200 1 PDT}
+ {688554000 -28800 0 PST}
+ {702468000 -25200 1 PDT}
+ {720003600 -28800 0 PST}
+ {733917600 -25200 1 PDT}
+ {752058000 -28800 0 PST}
+ {765367200 -25200 1 PDT}
+ {783507600 -28800 0 PST}
+ {796816800 -25200 1 PDT}
+ {814957200 -28800 0 PST}
+ {820483200 -28800 0 PST}
+ {828871200 -25200 1 PDT}
+ {846406800 -28800 0 PST}
+ {860320800 -25200 1 PDT}
+ {877856400 -28800 0 PST}
+ {891770400 -25200 1 PDT}
+ {909306000 -28800 0 PST}
+ {923220000 -25200 1 PDT}
+ {941360400 -28800 0 PST}
+ {954669600 -25200 1 PDT}
+ {972810000 -28800 0 PST}
+ {978336000 -28800 0 PST}
+ {986119200 -25200 1 PDT}
+ {1004259600 -28800 0 PST}
+ {1014192000 -28800 0 PST}
+ {1018173600 -25200 1 PDT}
+ {1035709200 -28800 0 PST}
+ {1049623200 -25200 1 PDT}
+ {1067158800 -28800 0 PST}
+ {1081072800 -25200 1 PDT}
+ {1099213200 -28800 0 PST}
+ {1112522400 -25200 1 PDT}
+ {1130662800 -28800 0 PST}
+ {1143972000 -25200 1 PDT}
+ {1162112400 -28800 0 PST}
+ {1175421600 -25200 1 PDT}
+ {1193562000 -28800 0 PST}
+ {1207476000 -25200 1 PDT}
+ {1225011600 -28800 0 PST}
+ {1238925600 -25200 1 PDT}
+ {1256461200 -28800 0 PST}
+ {1270375200 -25200 1 PDT}
+ {1288515600 -28800 0 PST}
+ {1301824800 -25200 1 PDT}
+ {1319965200 -28800 0 PST}
+ {1333274400 -25200 1 PDT}
+ {1351414800 -28800 0 PST}
+ {1365328800 -25200 1 PDT}
+ {1382864400 -28800 0 PST}
+ {1396778400 -25200 1 PDT}
+ {1414314000 -28800 0 PST}
+ {1428228000 -25200 1 PDT}
+ {1445763600 -28800 0 PST}
+ {1459677600 -25200 1 PDT}
+ {1477818000 -28800 0 PST}
+ {1491127200 -25200 1 PDT}
+ {1509267600 -28800 0 PST}
+ {1522576800 -25200 1 PDT}
+ {1540717200 -28800 0 PST}
+ {1554631200 -25200 1 PDT}
+ {1572166800 -28800 0 PST}
+ {1586080800 -25200 1 PDT}
+ {1603616400 -28800 0 PST}
+ {1617530400 -25200 1 PDT}
+ {1635670800 -28800 0 PST}
+ {1648980000 -25200 1 PDT}
+ {1667120400 -28800 0 PST}
+ {1680429600 -25200 1 PDT}
+ {1698570000 -28800 0 PST}
+ {1712484000 -25200 1 PDT}
+ {1730019600 -28800 0 PST}
+ {1743933600 -25200 1 PDT}
+ {1761469200 -28800 0 PST}
+ {1775383200 -25200 1 PDT}
+ {1792918800 -28800 0 PST}
+ {1806832800 -25200 1 PDT}
+ {1824973200 -28800 0 PST}
+ {1838282400 -25200 1 PDT}
+ {1856422800 -28800 0 PST}
+ {1869732000 -25200 1 PDT}
+ {1887872400 -28800 0 PST}
+ {1901786400 -25200 1 PDT}
+ {1919322000 -28800 0 PST}
+ {1933236000 -25200 1 PDT}
+ {1950771600 -28800 0 PST}
+ {1964685600 -25200 1 PDT}
+ {1982826000 -28800 0 PST}
+ {1996135200 -25200 1 PDT}
+ {2014275600 -28800 0 PST}
+ {2027584800 -25200 1 PDT}
+ {2045725200 -28800 0 PST}
+ {2059034400 -25200 1 PDT}
+ {2077174800 -28800 0 PST}
+ {2091088800 -25200 1 PDT}
+ {2108624400 -28800 0 PST}
+ {2122538400 -25200 1 PDT}
+ {2140074000 -28800 0 PST}
+ {2153988000 -25200 1 PDT}
+ {2172128400 -28800 0 PST}
+ {2185437600 -25200 1 PDT}
+ {2203578000 -28800 0 PST}
+ {2216887200 -25200 1 PDT}
+ {2235027600 -28800 0 PST}
+ {2248941600 -25200 1 PDT}
+ {2266477200 -28800 0 PST}
+ {2280391200 -25200 1 PDT}
+ {2297926800 -28800 0 PST}
+ {2311840800 -25200 1 PDT}
+ {2329376400 -28800 0 PST}
+ {2343290400 -25200 1 PDT}
+ {2361430800 -28800 0 PST}
+ {2374740000 -25200 1 PDT}
+ {2392880400 -28800 0 PST}
+ {2406189600 -25200 1 PDT}
+ {2424330000 -28800 0 PST}
+ {2438244000 -25200 1 PDT}
+ {2455779600 -28800 0 PST}
+ {2469693600 -25200 1 PDT}
+ {2487229200 -28800 0 PST}
+ {2501143200 -25200 1 PDT}
+ {2519283600 -28800 0 PST}
+ {2532592800 -25200 1 PDT}
+ {2550733200 -28800 0 PST}
+ {2564042400 -25200 1 PDT}
+ {2582182800 -28800 0 PST}
+ {2596096800 -25200 1 PDT}
+ {2613632400 -28800 0 PST}
+ {2627546400 -25200 1 PDT}
+ {2645082000 -28800 0 PST}
+ {2658996000 -25200 1 PDT}
+ {2676531600 -28800 0 PST}
+ {2690445600 -25200 1 PDT}
+ {2708586000 -28800 0 PST}
+ {2721895200 -25200 1 PDT}
+ {2740035600 -28800 0 PST}
+ {2753344800 -25200 1 PDT}
+ {2771485200 -28800 0 PST}
+ {2785399200 -25200 1 PDT}
+ {2802934800 -28800 0 PST}
+ {2816848800 -25200 1 PDT}
+ {2834384400 -28800 0 PST}
+ {2848298400 -25200 1 PDT}
+ {2866438800 -28800 0 PST}
+ {2879748000 -25200 1 PDT}
+ {2897888400 -28800 0 PST}
+ {2911197600 -25200 1 PDT}
+ {2929338000 -28800 0 PST}
+ {2942647200 -25200 1 PDT}
+ {2960787600 -28800 0 PST}
+ {2974701600 -25200 1 PDT}
+ {2992237200 -28800 0 PST}
+ {3006151200 -25200 1 PDT}
+ {3023686800 -28800 0 PST}
+ {3037600800 -25200 1 PDT}
+ {3055741200 -28800 0 PST}
+ {3069050400 -25200 1 PDT}
+ {3087190800 -28800 0 PST}
+ {3100500000 -25200 1 PDT}
+ {3118640400 -28800 0 PST}
+ {3132554400 -25200 1 PDT}
+ {3150090000 -28800 0 PST}
+ {3164004000 -25200 1 PDT}
+ {3181539600 -28800 0 PST}
+ {3195453600 -25200 1 PDT}
+ {3212989200 -28800 0 PST}
+ {3226903200 -25200 1 PDT}
+ {3245043600 -28800 0 PST}
+ {3258352800 -25200 1 PDT}
+ {3276493200 -28800 0 PST}
+ {3289802400 -25200 1 PDT}
+ {3307942800 -28800 0 PST}
+ {3321856800 -25200 1 PDT}
+ {3339392400 -28800 0 PST}
+ {3353306400 -25200 1 PDT}
+ {3370842000 -28800 0 PST}
+ {3384756000 -25200 1 PDT}
+ {3402896400 -28800 0 PST}
+ {3416205600 -25200 1 PDT}
+ {3434346000 -28800 0 PST}
+ {3447655200 -25200 1 PDT}
+ {3465795600 -28800 0 PST}
+ {3479709600 -25200 1 PDT}
+ {3497245200 -28800 0 PST}
+ {3511159200 -25200 1 PDT}
+ {3528694800 -28800 0 PST}
+ {3542608800 -25200 1 PDT}
+ {3560144400 -28800 0 PST}
+ {3574058400 -25200 1 PDT}
+ {3592198800 -28800 0 PST}
+ {3605508000 -25200 1 PDT}
+ {3623648400 -28800 0 PST}
+ {3636957600 -25200 1 PDT}
+ {3655098000 -28800 0 PST}
+ {3669012000 -25200 1 PDT}
+ {3686547600 -28800 0 PST}
+ {3700461600 -25200 1 PDT}
+ {3717997200 -28800 0 PST}
+ {3731911200 -25200 1 PDT}
+ {3750051600 -28800 0 PST}
+ {3763360800 -25200 1 PDT}
+ {3781501200 -28800 0 PST}
+ {3794810400 -25200 1 PDT}
+ {3812950800 -28800 0 PST}
+ {3826260000 -25200 1 PDT}
+ {3844400400 -28800 0 PST}
+ {3858314400 -25200 1 PDT}
+ {3875850000 -28800 0 PST}
+ {3889764000 -25200 1 PDT}
+ {3907299600 -28800 0 PST}
+ {3921213600 -25200 1 PDT}
+ {3939354000 -28800 0 PST}
+ {3952663200 -25200 1 PDT}
+ {3970803600 -28800 0 PST}
+ {3984112800 -25200 1 PDT}
+ {4002253200 -28800 0 PST}
+ {4016167200 -25200 1 PDT}
+ {4033702800 -28800 0 PST}
+ {4047616800 -25200 1 PDT}
+ {4065152400 -28800 0 PST}
+ {4079066400 -25200 1 PDT}
+ {4096602000 -28800 0 PST}
+}
diff --git a/library/tzdata/America/Santarem b/library/tzdata/America/Santarem
new file mode 100644
index 0000000..b6e9264
--- /dev/null
+++ b/library/tzdata/America/Santarem
@@ -0,0 +1,36 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Santarem) {
+ {-9223372036854775808 -13128 0 LMT}
+ {-1767212472 -14400 0 AMT}
+ {-1206954000 -10800 1 AMST}
+ {-1191358800 -14400 0 AMT}
+ {-1175371200 -10800 1 AMST}
+ {-1159822800 -14400 0 AMT}
+ {-633816000 -10800 1 AMST}
+ {-622065600 -14400 0 AMT}
+ {-602280000 -10800 1 AMST}
+ {-591829200 -14400 0 AMT}
+ {-570744000 -10800 1 AMST}
+ {-560206800 -14400 0 AMT}
+ {-539121600 -10800 1 AMST}
+ {-531349200 -14400 0 AMT}
+ {-191361600 -10800 1 AMST}
+ {-184194000 -14400 0 AMT}
+ {-155160000 -10800 1 AMST}
+ {-150066000 -14400 0 AMT}
+ {-128894400 -10800 1 AMST}
+ {-121122000 -14400 0 AMT}
+ {-99950400 -10800 1 AMST}
+ {-89586000 -14400 0 AMT}
+ {-68414400 -10800 1 AMST}
+ {-57963600 -14400 0 AMT}
+ {499752000 -10800 1 AMST}
+ {511239600 -14400 0 AMT}
+ {530596800 -10800 1 AMST}
+ {540270000 -14400 0 AMT}
+ {562132800 -10800 1 AMST}
+ {571201200 -14400 0 AMT}
+ {590036400 -14400 0 AMT}
+ {1214280000 -10800 0 BRT}
+}
diff --git a/library/tzdata/America/Santiago b/library/tzdata/America/Santiago
new file mode 100644
index 0000000..c631bd1
--- /dev/null
+++ b/library/tzdata/America/Santiago
@@ -0,0 +1,291 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Santiago) {
+ {-9223372036854775808 -16966 0 LMT}
+ {-2524504634 -16966 0 SMT}
+ {-1893439034 -18000 0 CLT}
+ {-1688410800 -16966 0 SMT}
+ {-1619983034 -14400 0 CLT}
+ {-1593806400 -16966 0 SMT}
+ {-1335986234 -18000 0 CLT}
+ {-1335985200 -14400 1 CLST}
+ {-1317585600 -18000 0 CLT}
+ {-1304362800 -14400 1 CLST}
+ {-1286049600 -18000 0 CLT}
+ {-1272826800 -14400 1 CLST}
+ {-1254513600 -18000 0 CLT}
+ {-1241290800 -14400 1 CLST}
+ {-1222977600 -18000 0 CLT}
+ {-1209754800 -14400 1 CLST}
+ {-1191355200 -18000 0 CLT}
+ {-1178132400 -14400 1 CLST}
+ {-870552000 -18000 0 CLT}
+ {-865278000 -14400 1 CLST}
+ {-740520000 -14400 1 CLST}
+ {-736376400 -18000 0 CLT}
+ {-718056000 -18000 0 CLT}
+ {-713646000 -14400 0 CLT}
+ {-36619200 -10800 1 CLST}
+ {-23922000 -14400 0 CLT}
+ {-3355200 -10800 1 CLST}
+ {7527600 -14400 0 CLT}
+ {24465600 -10800 1 CLST}
+ {37767600 -14400 0 CLT}
+ {55915200 -10800 1 CLST}
+ {69217200 -14400 0 CLT}
+ {87969600 -10800 1 CLST}
+ {100666800 -14400 0 CLT}
+ {118209600 -10800 1 CLST}
+ {132116400 -14400 0 CLT}
+ {150868800 -10800 1 CLST}
+ {163566000 -14400 0 CLT}
+ {182318400 -10800 1 CLST}
+ {195620400 -14400 0 CLT}
+ {213768000 -10800 1 CLST}
+ {227070000 -14400 0 CLT}
+ {245217600 -10800 1 CLST}
+ {258519600 -14400 0 CLT}
+ {277272000 -10800 1 CLST}
+ {289969200 -14400 0 CLT}
+ {308721600 -10800 1 CLST}
+ {321418800 -14400 0 CLT}
+ {340171200 -10800 1 CLST}
+ {353473200 -14400 0 CLT}
+ {371620800 -10800 1 CLST}
+ {384922800 -14400 0 CLT}
+ {403070400 -10800 1 CLST}
+ {416372400 -14400 0 CLT}
+ {434520000 -10800 1 CLST}
+ {447822000 -14400 0 CLT}
+ {466574400 -10800 1 CLST}
+ {479271600 -14400 0 CLT}
+ {498024000 -10800 1 CLST}
+ {510721200 -14400 0 CLT}
+ {529473600 -10800 1 CLST}
+ {545194800 -14400 0 CLT}
+ {560923200 -10800 1 CLST}
+ {574225200 -14400 0 CLT}
+ {591768000 -10800 1 CLST}
+ {605674800 -14400 0 CLT}
+ {624427200 -10800 1 CLST}
+ {637729200 -14400 0 CLT}
+ {653457600 -10800 1 CLST}
+ {668574000 -14400 0 CLT}
+ {687326400 -10800 1 CLST}
+ {700628400 -14400 0 CLT}
+ {718776000 -10800 1 CLST}
+ {732078000 -14400 0 CLT}
+ {750225600 -10800 1 CLST}
+ {763527600 -14400 0 CLT}
+ {781675200 -10800 1 CLST}
+ {794977200 -14400 0 CLT}
+ {813729600 -10800 1 CLST}
+ {826426800 -14400 0 CLT}
+ {845179200 -10800 1 CLST}
+ {859690800 -14400 0 CLT}
+ {876628800 -10800 1 CLST}
+ {889930800 -14400 0 CLT}
+ {906868800 -10800 1 CLST}
+ {923194800 -14400 0 CLT}
+ {939528000 -10800 1 CLST}
+ {952830000 -14400 0 CLT}
+ {971582400 -10800 1 CLST}
+ {984279600 -14400 0 CLT}
+ {1003032000 -10800 1 CLST}
+ {1015729200 -14400 0 CLT}
+ {1034481600 -10800 1 CLST}
+ {1047178800 -14400 0 CLT}
+ {1065931200 -10800 1 CLST}
+ {1079233200 -14400 0 CLT}
+ {1097380800 -10800 1 CLST}
+ {1110682800 -14400 0 CLT}
+ {1128830400 -10800 1 CLST}
+ {1142132400 -14400 0 CLT}
+ {1160884800 -10800 1 CLST}
+ {1173582000 -14400 0 CLT}
+ {1192334400 -10800 1 CLST}
+ {1206846000 -14400 0 CLT}
+ {1223784000 -10800 1 CLST}
+ {1237086000 -14400 0 CLT}
+ {1255233600 -10800 1 CLST}
+ {1270350000 -14400 0 CLT}
+ {1286683200 -10800 1 CLST}
+ {1304823600 -14400 0 CLT}
+ {1313899200 -10800 1 CLST}
+ {1331434800 -14400 0 CLT}
+ {1350187200 -10800 1 CLST}
+ {1362884400 -14400 0 CLT}
+ {1381636800 -10800 1 CLST}
+ {1394334000 -14400 0 CLT}
+ {1413086400 -10800 1 CLST}
+ {1426388400 -14400 0 CLT}
+ {1444536000 -10800 1 CLST}
+ {1457838000 -14400 0 CLT}
+ {1475985600 -10800 1 CLST}
+ {1489287600 -14400 0 CLT}
+ {1508040000 -10800 1 CLST}
+ {1520737200 -14400 0 CLT}
+ {1539489600 -10800 1 CLST}
+ {1552186800 -14400 0 CLT}
+ {1570939200 -10800 1 CLST}
+ {1584241200 -14400 0 CLT}
+ {1602388800 -10800 1 CLST}
+ {1615690800 -14400 0 CLT}
+ {1633838400 -10800 1 CLST}
+ {1647140400 -14400 0 CLT}
+ {1665288000 -10800 1 CLST}
+ {1678590000 -14400 0 CLT}
+ {1697342400 -10800 1 CLST}
+ {1710039600 -14400 0 CLT}
+ {1728792000 -10800 1 CLST}
+ {1741489200 -14400 0 CLT}
+ {1760241600 -10800 1 CLST}
+ {1773543600 -14400 0 CLT}
+ {1791691200 -10800 1 CLST}
+ {1804993200 -14400 0 CLT}
+ {1823140800 -10800 1 CLST}
+ {1836442800 -14400 0 CLT}
+ {1855195200 -10800 1 CLST}
+ {1867892400 -14400 0 CLT}
+ {1886644800 -10800 1 CLST}
+ {1899342000 -14400 0 CLT}
+ {1918094400 -10800 1 CLST}
+ {1930791600 -14400 0 CLT}
+ {1949544000 -10800 1 CLST}
+ {1962846000 -14400 0 CLT}
+ {1980993600 -10800 1 CLST}
+ {1994295600 -14400 0 CLT}
+ {2012443200 -10800 1 CLST}
+ {2025745200 -14400 0 CLT}
+ {2044497600 -10800 1 CLST}
+ {2057194800 -14400 0 CLT}
+ {2075947200 -10800 1 CLST}
+ {2088644400 -14400 0 CLT}
+ {2107396800 -10800 1 CLST}
+ {2120698800 -14400 0 CLT}
+ {2138846400 -10800 1 CLST}
+ {2152148400 -14400 0 CLT}
+ {2170296000 -10800 1 CLST}
+ {2183598000 -14400 0 CLT}
+ {2201745600 -10800 1 CLST}
+ {2215047600 -14400 0 CLT}
+ {2233800000 -10800 1 CLST}
+ {2246497200 -14400 0 CLT}
+ {2265249600 -10800 1 CLST}
+ {2277946800 -14400 0 CLT}
+ {2296699200 -10800 1 CLST}
+ {2310001200 -14400 0 CLT}
+ {2328148800 -10800 1 CLST}
+ {2341450800 -14400 0 CLT}
+ {2359598400 -10800 1 CLST}
+ {2372900400 -14400 0 CLT}
+ {2391652800 -10800 1 CLST}
+ {2404350000 -14400 0 CLT}
+ {2423102400 -10800 1 CLST}
+ {2435799600 -14400 0 CLT}
+ {2454552000 -10800 1 CLST}
+ {2467854000 -14400 0 CLT}
+ {2486001600 -10800 1 CLST}
+ {2499303600 -14400 0 CLT}
+ {2517451200 -10800 1 CLST}
+ {2530753200 -14400 0 CLT}
+ {2548900800 -10800 1 CLST}
+ {2562202800 -14400 0 CLT}
+ {2580955200 -10800 1 CLST}
+ {2593652400 -14400 0 CLT}
+ {2612404800 -10800 1 CLST}
+ {2625102000 -14400 0 CLT}
+ {2643854400 -10800 1 CLST}
+ {2657156400 -14400 0 CLT}
+ {2675304000 -10800 1 CLST}
+ {2688606000 -14400 0 CLT}
+ {2706753600 -10800 1 CLST}
+ {2720055600 -14400 0 CLT}
+ {2738808000 -10800 1 CLST}
+ {2751505200 -14400 0 CLT}
+ {2770257600 -10800 1 CLST}
+ {2782954800 -14400 0 CLT}
+ {2801707200 -10800 1 CLST}
+ {2814404400 -14400 0 CLT}
+ {2833156800 -10800 1 CLST}
+ {2846458800 -14400 0 CLT}
+ {2864606400 -10800 1 CLST}
+ {2877908400 -14400 0 CLT}
+ {2896056000 -10800 1 CLST}
+ {2909358000 -14400 0 CLT}
+ {2928110400 -10800 1 CLST}
+ {2940807600 -14400 0 CLT}
+ {2959560000 -10800 1 CLST}
+ {2972257200 -14400 0 CLT}
+ {2991009600 -10800 1 CLST}
+ {3004311600 -14400 0 CLT}
+ {3022459200 -10800 1 CLST}
+ {3035761200 -14400 0 CLT}
+ {3053908800 -10800 1 CLST}
+ {3067210800 -14400 0 CLT}
+ {3085358400 -10800 1 CLST}
+ {3098660400 -14400 0 CLT}
+ {3117412800 -10800 1 CLST}
+ {3130110000 -14400 0 CLT}
+ {3148862400 -10800 1 CLST}
+ {3161559600 -14400 0 CLT}
+ {3180312000 -10800 1 CLST}
+ {3193614000 -14400 0 CLT}
+ {3211761600 -10800 1 CLST}
+ {3225063600 -14400 0 CLT}
+ {3243211200 -10800 1 CLST}
+ {3256513200 -14400 0 CLT}
+ {3275265600 -10800 1 CLST}
+ {3287962800 -14400 0 CLT}
+ {3306715200 -10800 1 CLST}
+ {3319412400 -14400 0 CLT}
+ {3338164800 -10800 1 CLST}
+ {3351466800 -14400 0 CLT}
+ {3369614400 -10800 1 CLST}
+ {3382916400 -14400 0 CLT}
+ {3401064000 -10800 1 CLST}
+ {3414366000 -14400 0 CLT}
+ {3432513600 -10800 1 CLST}
+ {3445815600 -14400 0 CLT}
+ {3464568000 -10800 1 CLST}
+ {3477265200 -14400 0 CLT}
+ {3496017600 -10800 1 CLST}
+ {3508714800 -14400 0 CLT}
+ {3527467200 -10800 1 CLST}
+ {3540769200 -14400 0 CLT}
+ {3558916800 -10800 1 CLST}
+ {3572218800 -14400 0 CLT}
+ {3590366400 -10800 1 CLST}
+ {3603668400 -14400 0 CLT}
+ {3622420800 -10800 1 CLST}
+ {3635118000 -14400 0 CLT}
+ {3653870400 -10800 1 CLST}
+ {3666567600 -14400 0 CLT}
+ {3685320000 -10800 1 CLST}
+ {3698017200 -14400 0 CLT}
+ {3716769600 -10800 1 CLST}
+ {3730071600 -14400 0 CLT}
+ {3748219200 -10800 1 CLST}
+ {3761521200 -14400 0 CLT}
+ {3779668800 -10800 1 CLST}
+ {3792970800 -14400 0 CLT}
+ {3811723200 -10800 1 CLST}
+ {3824420400 -14400 0 CLT}
+ {3843172800 -10800 1 CLST}
+ {3855870000 -14400 0 CLT}
+ {3874622400 -10800 1 CLST}
+ {3887924400 -14400 0 CLT}
+ {3906072000 -10800 1 CLST}
+ {3919374000 -14400 0 CLT}
+ {3937521600 -10800 1 CLST}
+ {3950823600 -14400 0 CLT}
+ {3968971200 -10800 1 CLST}
+ {3982273200 -14400 0 CLT}
+ {4001025600 -10800 1 CLST}
+ {4013722800 -14400 0 CLT}
+ {4032475200 -10800 1 CLST}
+ {4045172400 -14400 0 CLT}
+ {4063924800 -10800 1 CLST}
+ {4077226800 -14400 0 CLT}
+ {4095374400 -10800 1 CLST}
+}
diff --git a/library/tzdata/America/Santo_Domingo b/library/tzdata/America/Santo_Domingo
new file mode 100644
index 0000000..7706918
--- /dev/null
+++ b/library/tzdata/America/Santo_Domingo
@@ -0,0 +1,21 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Santo_Domingo) {
+ {-9223372036854775808 -16776 0 LMT}
+ {-2524504824 -16800 0 SDMT}
+ {-1159773600 -18000 0 EST}
+ {-100119600 -14400 1 EDT}
+ {-89668800 -18000 0 EST}
+ {-5770800 -16200 1 EHDT}
+ {4422600 -18000 0 EST}
+ {25678800 -16200 1 EHDT}
+ {33193800 -18000 0 EST}
+ {57733200 -16200 1 EHDT}
+ {64816200 -18000 0 EST}
+ {89182800 -16200 1 EHDT}
+ {96438600 -18000 0 EST}
+ {120632400 -16200 1 EHDT}
+ {127974600 -18000 0 EST}
+ {152082000 -14400 0 AST}
+ {975823200 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Sao_Paulo b/library/tzdata/America/Sao_Paulo
new file mode 100644
index 0000000..8d70063
--- /dev/null
+++ b/library/tzdata/America/Sao_Paulo
@@ -0,0 +1,258 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Sao_Paulo) {
+ {-9223372036854775808 -11188 0 LMT}
+ {-1767214412 -10800 0 BRT}
+ {-1206957600 -7200 1 BRST}
+ {-1191362400 -10800 0 BRT}
+ {-1175374800 -7200 1 BRST}
+ {-1159826400 -10800 0 BRT}
+ {-633819600 -7200 1 BRST}
+ {-622069200 -10800 0 BRT}
+ {-602283600 -7200 1 BRST}
+ {-591832800 -10800 0 BRT}
+ {-570747600 -7200 1 BRST}
+ {-560210400 -10800 0 BRT}
+ {-539125200 -7200 1 BRST}
+ {-531352800 -10800 0 BRT}
+ {-195429600 -7200 1 BRST}
+ {-189381600 -7200 0 BRT}
+ {-184197600 -10800 0 BRT}
+ {-155163600 -7200 1 BRST}
+ {-150069600 -10800 0 BRT}
+ {-128898000 -7200 1 BRST}
+ {-121125600 -10800 0 BRT}
+ {-99954000 -7200 1 BRST}
+ {-89589600 -10800 0 BRT}
+ {-68418000 -7200 1 BRST}
+ {-57967200 -10800 0 BRT}
+ {499748400 -7200 1 BRST}
+ {511236000 -10800 0 BRT}
+ {530593200 -7200 1 BRST}
+ {540266400 -10800 0 BRT}
+ {562129200 -7200 1 BRST}
+ {571197600 -10800 0 BRT}
+ {592974000 -7200 1 BRST}
+ {602042400 -10800 0 BRT}
+ {624423600 -7200 1 BRST}
+ {634701600 -10800 0 BRT}
+ {656478000 -7200 1 BRST}
+ {666756000 -10800 0 BRT}
+ {687927600 -7200 1 BRST}
+ {697600800 -10800 0 BRT}
+ {719982000 -7200 1 BRST}
+ {728445600 -10800 0 BRT}
+ {750826800 -7200 1 BRST}
+ {761709600 -10800 0 BRT}
+ {782276400 -7200 1 BRST}
+ {793159200 -10800 0 BRT}
+ {813726000 -7200 1 BRST}
+ {824004000 -10800 0 BRT}
+ {844570800 -7200 1 BRST}
+ {856058400 -10800 0 BRT}
+ {876106800 -7200 1 BRST}
+ {888717600 -10800 0 BRT}
+ {908074800 -7200 1 BRST}
+ {919562400 -10800 0 BRT}
+ {938919600 -7200 1 BRST}
+ {951616800 -10800 0 BRT}
+ {970974000 -7200 1 BRST}
+ {982461600 -10800 0 BRT}
+ {1003028400 -7200 1 BRST}
+ {1013911200 -10800 0 BRT}
+ {1036292400 -7200 1 BRST}
+ {1045360800 -10800 0 BRT}
+ {1066532400 -7200 1 BRST}
+ {1076810400 -10800 0 BRT}
+ {1099364400 -7200 1 BRST}
+ {1108864800 -10800 0 BRT}
+ {1129431600 -7200 1 BRST}
+ {1140314400 -10800 0 BRT}
+ {1162695600 -7200 1 BRST}
+ {1172368800 -10800 0 BRT}
+ {1192330800 -7200 1 BRST}
+ {1203213600 -10800 0 BRT}
+ {1224385200 -7200 1 BRST}
+ {1234663200 -10800 0 BRT}
+ {1255834800 -7200 1 BRST}
+ {1266717600 -10800 0 BRT}
+ {1287284400 -7200 1 BRST}
+ {1298167200 -10800 0 BRT}
+ {1318734000 -7200 1 BRST}
+ {1330221600 -10800 0 BRT}
+ {1350788400 -7200 1 BRST}
+ {1361066400 -10800 0 BRT}
+ {1382238000 -7200 1 BRST}
+ {1392516000 -10800 0 BRT}
+ {1413687600 -7200 1 BRST}
+ {1424570400 -10800 0 BRT}
+ {1445137200 -7200 1 BRST}
+ {1456020000 -10800 0 BRT}
+ {1476586800 -7200 1 BRST}
+ {1487469600 -10800 0 BRT}
+ {1508036400 -7200 1 BRST}
+ {1518919200 -10800 0 BRT}
+ {1540090800 -7200 1 BRST}
+ {1550368800 -10800 0 BRT}
+ {1571540400 -7200 1 BRST}
+ {1581818400 -10800 0 BRT}
+ {1602990000 -7200 1 BRST}
+ {1613872800 -10800 0 BRT}
+ {1634439600 -7200 1 BRST}
+ {1645322400 -10800 0 BRT}
+ {1665889200 -7200 1 BRST}
+ {1677376800 -10800 0 BRT}
+ {1697338800 -7200 1 BRST}
+ {1708221600 -10800 0 BRT}
+ {1729393200 -7200 1 BRST}
+ {1739671200 -10800 0 BRT}
+ {1760842800 -7200 1 BRST}
+ {1771725600 -10800 0 BRT}
+ {1792292400 -7200 1 BRST}
+ {1803175200 -10800 0 BRT}
+ {1823742000 -7200 1 BRST}
+ {1834624800 -10800 0 BRT}
+ {1855191600 -7200 1 BRST}
+ {1866074400 -10800 0 BRT}
+ {1887246000 -7200 1 BRST}
+ {1897524000 -10800 0 BRT}
+ {1918695600 -7200 1 BRST}
+ {1928973600 -10800 0 BRT}
+ {1950145200 -7200 1 BRST}
+ {1960423200 -10800 0 BRT}
+ {1981594800 -7200 1 BRST}
+ {1992477600 -10800 0 BRT}
+ {2013044400 -7200 1 BRST}
+ {2024532000 -10800 0 BRT}
+ {2044494000 -7200 1 BRST}
+ {2055376800 -10800 0 BRT}
+ {2076548400 -7200 1 BRST}
+ {2086826400 -10800 0 BRT}
+ {2107998000 -7200 1 BRST}
+ {2118880800 -10800 0 BRT}
+ {2139447600 -7200 1 BRST}
+ {2150330400 -10800 0 BRT}
+ {2170897200 -7200 1 BRST}
+ {2181780000 -10800 0 BRT}
+ {2202346800 -7200 1 BRST}
+ {2213229600 -10800 0 BRT}
+ {2234401200 -7200 1 BRST}
+ {2244679200 -10800 0 BRT}
+ {2265850800 -7200 1 BRST}
+ {2276128800 -10800 0 BRT}
+ {2297300400 -7200 1 BRST}
+ {2307578400 -10800 0 BRT}
+ {2328750000 -7200 1 BRST}
+ {2339632800 -10800 0 BRT}
+ {2360199600 -7200 1 BRST}
+ {2371082400 -10800 0 BRT}
+ {2391649200 -7200 1 BRST}
+ {2402532000 -10800 0 BRT}
+ {2423703600 -7200 1 BRST}
+ {2433981600 -10800 0 BRT}
+ {2455153200 -7200 1 BRST}
+ {2465431200 -10800 0 BRT}
+ {2486602800 -7200 1 BRST}
+ {2497485600 -10800 0 BRT}
+ {2518052400 -7200 1 BRST}
+ {2528935200 -10800 0 BRT}
+ {2549502000 -7200 1 BRST}
+ {2560384800 -10800 0 BRT}
+ {2580951600 -7200 1 BRST}
+ {2591834400 -10800 0 BRT}
+ {2613006000 -7200 1 BRST}
+ {2623284000 -10800 0 BRT}
+ {2644455600 -7200 1 BRST}
+ {2654733600 -10800 0 BRT}
+ {2675905200 -7200 1 BRST}
+ {2686788000 -10800 0 BRT}
+ {2707354800 -7200 1 BRST}
+ {2718237600 -10800 0 BRT}
+ {2738804400 -7200 1 BRST}
+ {2749687200 -10800 0 BRT}
+ {2770858800 -7200 1 BRST}
+ {2781136800 -10800 0 BRT}
+ {2802308400 -7200 1 BRST}
+ {2812586400 -10800 0 BRT}
+ {2833758000 -7200 1 BRST}
+ {2844036000 -10800 0 BRT}
+ {2865207600 -7200 1 BRST}
+ {2876090400 -10800 0 BRT}
+ {2896657200 -7200 1 BRST}
+ {2907540000 -10800 0 BRT}
+ {2928106800 -7200 1 BRST}
+ {2938989600 -10800 0 BRT}
+ {2960161200 -7200 1 BRST}
+ {2970439200 -10800 0 BRT}
+ {2991610800 -7200 1 BRST}
+ {3001888800 -10800 0 BRT}
+ {3023060400 -7200 1 BRST}
+ {3033943200 -10800 0 BRT}
+ {3054510000 -7200 1 BRST}
+ {3065392800 -10800 0 BRT}
+ {3085959600 -7200 1 BRST}
+ {3096842400 -10800 0 BRT}
+ {3118014000 -7200 1 BRST}
+ {3128292000 -10800 0 BRT}
+ {3149463600 -7200 1 BRST}
+ {3159741600 -10800 0 BRT}
+ {3180913200 -7200 1 BRST}
+ {3191191200 -10800 0 BRT}
+ {3212362800 -7200 1 BRST}
+ {3223245600 -10800 0 BRT}
+ {3243812400 -7200 1 BRST}
+ {3254695200 -10800 0 BRT}
+ {3275262000 -7200 1 BRST}
+ {3286144800 -10800 0 BRT}
+ {3307316400 -7200 1 BRST}
+ {3317594400 -10800 0 BRT}
+ {3338766000 -7200 1 BRST}
+ {3349044000 -10800 0 BRT}
+ {3370215600 -7200 1 BRST}
+ {3381098400 -10800 0 BRT}
+ {3401665200 -7200 1 BRST}
+ {3412548000 -10800 0 BRT}
+ {3433114800 -7200 1 BRST}
+ {3443997600 -10800 0 BRT}
+ {3464564400 -7200 1 BRST}
+ {3475447200 -10800 0 BRT}
+ {3496618800 -7200 1 BRST}
+ {3506896800 -10800 0 BRT}
+ {3528068400 -7200 1 BRST}
+ {3538346400 -10800 0 BRT}
+ {3559518000 -7200 1 BRST}
+ {3570400800 -10800 0 BRT}
+ {3590967600 -7200 1 BRST}
+ {3601850400 -10800 0 BRT}
+ {3622417200 -7200 1 BRST}
+ {3633300000 -10800 0 BRT}
+ {3654471600 -7200 1 BRST}
+ {3664749600 -10800 0 BRT}
+ {3685921200 -7200 1 BRST}
+ {3696199200 -10800 0 BRT}
+ {3717370800 -7200 1 BRST}
+ {3727648800 -10800 0 BRT}
+ {3748820400 -7200 1 BRST}
+ {3759703200 -10800 0 BRT}
+ {3780270000 -7200 1 BRST}
+ {3791152800 -10800 0 BRT}
+ {3811719600 -7200 1 BRST}
+ {3822602400 -10800 0 BRT}
+ {3843774000 -7200 1 BRST}
+ {3854052000 -10800 0 BRT}
+ {3875223600 -7200 1 BRST}
+ {3885501600 -10800 0 BRT}
+ {3906673200 -7200 1 BRST}
+ {3917556000 -10800 0 BRT}
+ {3938122800 -7200 1 BRST}
+ {3949005600 -10800 0 BRT}
+ {3969572400 -7200 1 BRST}
+ {3980455200 -10800 0 BRT}
+ {4001626800 -7200 1 BRST}
+ {4011904800 -10800 0 BRT}
+ {4033076400 -7200 1 BRST}
+ {4043354400 -10800 0 BRT}
+ {4064526000 -7200 1 BRST}
+ {4074804000 -10800 0 BRT}
+ {4095975600 -7200 1 BRST}
+}
diff --git a/library/tzdata/America/Scoresbysund b/library/tzdata/America/Scoresbysund
new file mode 100644
index 0000000..74a332c
--- /dev/null
+++ b/library/tzdata/America/Scoresbysund
@@ -0,0 +1,246 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Scoresbysund) {
+ {-9223372036854775808 -5272 0 LMT}
+ {-1686090728 -7200 0 CGT}
+ {323841600 -3600 0 CGST}
+ {338961600 -7200 0 CGT}
+ {354679200 0 0 EGST}
+ {370400400 -3600 0 EGT}
+ {386125200 0 1 EGST}
+ {401850000 -3600 0 EGT}
+ {417574800 0 1 EGST}
+ {433299600 -3600 0 EGT}
+ {449024400 0 1 EGST}
+ {465354000 -3600 0 EGT}
+ {481078800 0 1 EGST}
+ {496803600 -3600 0 EGT}
+ {512528400 0 1 EGST}
+ {528253200 -3600 0 EGT}
+ {543978000 0 1 EGST}
+ {559702800 -3600 0 EGT}
+ {575427600 0 1 EGST}
+ {591152400 -3600 0 EGT}
+ {606877200 0 1 EGST}
+ {622602000 -3600 0 EGT}
+ {638326800 0 1 EGST}
+ {654656400 -3600 0 EGT}
+ {670381200 0 1 EGST}
+ {686106000 -3600 0 EGT}
+ {701830800 0 1 EGST}
+ {717555600 -3600 0 EGT}
+ {733280400 0 1 EGST}
+ {749005200 -3600 0 EGT}
+ {764730000 0 1 EGST}
+ {780454800 -3600 0 EGT}
+ {796179600 0 1 EGST}
+ {811904400 -3600 0 EGT}
+ {828234000 0 1 EGST}
+ {846378000 -3600 0 EGT}
+ {859683600 0 1 EGST}
+ {877827600 -3600 0 EGT}
+ {891133200 0 1 EGST}
+ {909277200 -3600 0 EGT}
+ {922582800 0 1 EGST}
+ {941331600 -3600 0 EGT}
+ {954032400 0 1 EGST}
+ {972781200 -3600 0 EGT}
+ {985482000 0 1 EGST}
+ {1004230800 -3600 0 EGT}
+ {1017536400 0 1 EGST}
+ {1035680400 -3600 0 EGT}
+ {1048986000 0 1 EGST}
+ {1067130000 -3600 0 EGT}
+ {1080435600 0 1 EGST}
+ {1099184400 -3600 0 EGT}
+ {1111885200 0 1 EGST}
+ {1130634000 -3600 0 EGT}
+ {1143334800 0 1 EGST}
+ {1162083600 -3600 0 EGT}
+ {1174784400 0 1 EGST}
+ {1193533200 -3600 0 EGT}
+ {1206838800 0 1 EGST}
+ {1224982800 -3600 0 EGT}
+ {1238288400 0 1 EGST}
+ {1256432400 -3600 0 EGT}
+ {1269738000 0 1 EGST}
+ {1288486800 -3600 0 EGT}
+ {1301187600 0 1 EGST}
+ {1319936400 -3600 0 EGT}
+ {1332637200 0 1 EGST}
+ {1351386000 -3600 0 EGT}
+ {1364691600 0 1 EGST}
+ {1382835600 -3600 0 EGT}
+ {1396141200 0 1 EGST}
+ {1414285200 -3600 0 EGT}
+ {1427590800 0 1 EGST}
+ {1445734800 -3600 0 EGT}
+ {1459040400 0 1 EGST}
+ {1477789200 -3600 0 EGT}
+ {1490490000 0 1 EGST}
+ {1509238800 -3600 0 EGT}
+ {1521939600 0 1 EGST}
+ {1540688400 -3600 0 EGT}
+ {1553994000 0 1 EGST}
+ {1572138000 -3600 0 EGT}
+ {1585443600 0 1 EGST}
+ {1603587600 -3600 0 EGT}
+ {1616893200 0 1 EGST}
+ {1635642000 -3600 0 EGT}
+ {1648342800 0 1 EGST}
+ {1667091600 -3600 0 EGT}
+ {1679792400 0 1 EGST}
+ {1698541200 -3600 0 EGT}
+ {1711846800 0 1 EGST}
+ {1729990800 -3600 0 EGT}
+ {1743296400 0 1 EGST}
+ {1761440400 -3600 0 EGT}
+ {1774746000 0 1 EGST}
+ {1792890000 -3600 0 EGT}
+ {1806195600 0 1 EGST}
+ {1824944400 -3600 0 EGT}
+ {1837645200 0 1 EGST}
+ {1856394000 -3600 0 EGT}
+ {1869094800 0 1 EGST}
+ {1887843600 -3600 0 EGT}
+ {1901149200 0 1 EGST}
+ {1919293200 -3600 0 EGT}
+ {1932598800 0 1 EGST}
+ {1950742800 -3600 0 EGT}
+ {1964048400 0 1 EGST}
+ {1982797200 -3600 0 EGT}
+ {1995498000 0 1 EGST}
+ {2014246800 -3600 0 EGT}
+ {2026947600 0 1 EGST}
+ {2045696400 -3600 0 EGT}
+ {2058397200 0 1 EGST}
+ {2077146000 -3600 0 EGT}
+ {2090451600 0 1 EGST}
+ {2108595600 -3600 0 EGT}
+ {2121901200 0 1 EGST}
+ {2140045200 -3600 0 EGT}
+ {2153350800 0 1 EGST}
+ {2172099600 -3600 0 EGT}
+ {2184800400 0 1 EGST}
+ {2203549200 -3600 0 EGT}
+ {2216250000 0 1 EGST}
+ {2234998800 -3600 0 EGT}
+ {2248304400 0 1 EGST}
+ {2266448400 -3600 0 EGT}
+ {2279754000 0 1 EGST}
+ {2297898000 -3600 0 EGT}
+ {2311203600 0 1 EGST}
+ {2329347600 -3600 0 EGT}
+ {2342653200 0 1 EGST}
+ {2361402000 -3600 0 EGT}
+ {2374102800 0 1 EGST}
+ {2392851600 -3600 0 EGT}
+ {2405552400 0 1 EGST}
+ {2424301200 -3600 0 EGT}
+ {2437606800 0 1 EGST}
+ {2455750800 -3600 0 EGT}
+ {2469056400 0 1 EGST}
+ {2487200400 -3600 0 EGT}
+ {2500506000 0 1 EGST}
+ {2519254800 -3600 0 EGT}
+ {2531955600 0 1 EGST}
+ {2550704400 -3600 0 EGT}
+ {2563405200 0 1 EGST}
+ {2582154000 -3600 0 EGT}
+ {2595459600 0 1 EGST}
+ {2613603600 -3600 0 EGT}
+ {2626909200 0 1 EGST}
+ {2645053200 -3600 0 EGT}
+ {2658358800 0 1 EGST}
+ {2676502800 -3600 0 EGT}
+ {2689808400 0 1 EGST}
+ {2708557200 -3600 0 EGT}
+ {2721258000 0 1 EGST}
+ {2740006800 -3600 0 EGT}
+ {2752707600 0 1 EGST}
+ {2771456400 -3600 0 EGT}
+ {2784762000 0 1 EGST}
+ {2802906000 -3600 0 EGT}
+ {2816211600 0 1 EGST}
+ {2834355600 -3600 0 EGT}
+ {2847661200 0 1 EGST}
+ {2866410000 -3600 0 EGT}
+ {2879110800 0 1 EGST}
+ {2897859600 -3600 0 EGT}
+ {2910560400 0 1 EGST}
+ {2929309200 -3600 0 EGT}
+ {2942010000 0 1 EGST}
+ {2960758800 -3600 0 EGT}
+ {2974064400 0 1 EGST}
+ {2992208400 -3600 0 EGT}
+ {3005514000 0 1 EGST}
+ {3023658000 -3600 0 EGT}
+ {3036963600 0 1 EGST}
+ {3055712400 -3600 0 EGT}
+ {3068413200 0 1 EGST}
+ {3087162000 -3600 0 EGT}
+ {3099862800 0 1 EGST}
+ {3118611600 -3600 0 EGT}
+ {3131917200 0 1 EGST}
+ {3150061200 -3600 0 EGT}
+ {3163366800 0 1 EGST}
+ {3181510800 -3600 0 EGT}
+ {3194816400 0 1 EGST}
+ {3212960400 -3600 0 EGT}
+ {3226266000 0 1 EGST}
+ {3245014800 -3600 0 EGT}
+ {3257715600 0 1 EGST}
+ {3276464400 -3600 0 EGT}
+ {3289165200 0 1 EGST}
+ {3307914000 -3600 0 EGT}
+ {3321219600 0 1 EGST}
+ {3339363600 -3600 0 EGT}
+ {3352669200 0 1 EGST}
+ {3370813200 -3600 0 EGT}
+ {3384118800 0 1 EGST}
+ {3402867600 -3600 0 EGT}
+ {3415568400 0 1 EGST}
+ {3434317200 -3600 0 EGT}
+ {3447018000 0 1 EGST}
+ {3465766800 -3600 0 EGT}
+ {3479072400 0 1 EGST}
+ {3497216400 -3600 0 EGT}
+ {3510522000 0 1 EGST}
+ {3528666000 -3600 0 EGT}
+ {3541971600 0 1 EGST}
+ {3560115600 -3600 0 EGT}
+ {3573421200 0 1 EGST}
+ {3592170000 -3600 0 EGT}
+ {3604870800 0 1 EGST}
+ {3623619600 -3600 0 EGT}
+ {3636320400 0 1 EGST}
+ {3655069200 -3600 0 EGT}
+ {3668374800 0 1 EGST}
+ {3686518800 -3600 0 EGT}
+ {3699824400 0 1 EGST}
+ {3717968400 -3600 0 EGT}
+ {3731274000 0 1 EGST}
+ {3750022800 -3600 0 EGT}
+ {3762723600 0 1 EGST}
+ {3781472400 -3600 0 EGT}
+ {3794173200 0 1 EGST}
+ {3812922000 -3600 0 EGT}
+ {3825622800 0 1 EGST}
+ {3844371600 -3600 0 EGT}
+ {3857677200 0 1 EGST}
+ {3875821200 -3600 0 EGT}
+ {3889126800 0 1 EGST}
+ {3907270800 -3600 0 EGT}
+ {3920576400 0 1 EGST}
+ {3939325200 -3600 0 EGT}
+ {3952026000 0 1 EGST}
+ {3970774800 -3600 0 EGT}
+ {3983475600 0 1 EGST}
+ {4002224400 -3600 0 EGT}
+ {4015530000 0 1 EGST}
+ {4033674000 -3600 0 EGT}
+ {4046979600 0 1 EGST}
+ {4065123600 -3600 0 EGT}
+ {4078429200 0 1 EGST}
+ {4096573200 -3600 0 EGT}
+}
diff --git a/library/tzdata/America/Shiprock b/library/tzdata/America/Shiprock
new file mode 100644
index 0000000..995d25d
--- /dev/null
+++ b/library/tzdata/America/Shiprock
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Denver)]} {
+ LoadTimeZoneFile America/Denver
+}
+set TZData(:America/Shiprock) $TZData(:America/Denver)
diff --git a/library/tzdata/America/Sitka b/library/tzdata/America/Sitka
new file mode 100644
index 0000000..c096fc9
--- /dev/null
+++ b/library/tzdata/America/Sitka
@@ -0,0 +1,275 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Sitka) {
+ {-9223372036854775808 -53927 0 LMT}
+ {-3225258073 -32473 0 LMT}
+ {-2188954727 -28800 0 PST}
+ {-883584000 -28800 0 PST}
+ {-880207200 -25200 1 PWT}
+ {-769395600 -25200 1 PPT}
+ {-765385200 -28800 0 PST}
+ {-757353600 -28800 0 PST}
+ {-31507200 -28800 0 PST}
+ {-21477600 -25200 1 PDT}
+ {-5756400 -28800 0 PST}
+ {9972000 -25200 1 PDT}
+ {25693200 -28800 0 PST}
+ {41421600 -25200 1 PDT}
+ {57747600 -28800 0 PST}
+ {73476000 -25200 1 PDT}
+ {89197200 -28800 0 PST}
+ {104925600 -25200 1 PDT}
+ {120646800 -28800 0 PST}
+ {126698400 -25200 1 PDT}
+ {152096400 -28800 0 PST}
+ {162381600 -25200 1 PDT}
+ {183546000 -28800 0 PST}
+ {199274400 -25200 1 PDT}
+ {215600400 -28800 0 PST}
+ {230724000 -25200 1 PDT}
+ {247050000 -28800 0 PST}
+ {262778400 -25200 1 PDT}
+ {278499600 -28800 0 PST}
+ {294228000 -25200 1 PDT}
+ {309949200 -28800 0 PST}
+ {325677600 -25200 1 PDT}
+ {341398800 -28800 0 PST}
+ {357127200 -25200 1 PDT}
+ {372848400 -28800 0 PST}
+ {388576800 -25200 1 PDT}
+ {404902800 -28800 0 PST}
+ {420026400 -25200 1 PDT}
+ {439030800 -32400 0 AKST}
+ {452084400 -28800 1 AKDT}
+ {467805600 -32400 0 AKST}
+ {483534000 -28800 1 AKDT}
+ {499255200 -32400 0 AKST}
+ {514983600 -28800 1 AKDT}
+ {530704800 -32400 0 AKST}
+ {544618800 -28800 1 AKDT}
+ {562154400 -32400 0 AKST}
+ {576068400 -28800 1 AKDT}
+ {594208800 -32400 0 AKST}
+ {607518000 -28800 1 AKDT}
+ {625658400 -32400 0 AKST}
+ {638967600 -28800 1 AKDT}
+ {657108000 -32400 0 AKST}
+ {671022000 -28800 1 AKDT}
+ {688557600 -32400 0 AKST}
+ {702471600 -28800 1 AKDT}
+ {720007200 -32400 0 AKST}
+ {733921200 -28800 1 AKDT}
+ {752061600 -32400 0 AKST}
+ {765370800 -28800 1 AKDT}
+ {783511200 -32400 0 AKST}
+ {796820400 -28800 1 AKDT}
+ {814960800 -32400 0 AKST}
+ {828874800 -28800 1 AKDT}
+ {846410400 -32400 0 AKST}
+ {860324400 -28800 1 AKDT}
+ {877860000 -32400 0 AKST}
+ {891774000 -28800 1 AKDT}
+ {909309600 -32400 0 AKST}
+ {923223600 -28800 1 AKDT}
+ {941364000 -32400 0 AKST}
+ {954673200 -28800 1 AKDT}
+ {972813600 -32400 0 AKST}
+ {986122800 -28800 1 AKDT}
+ {1004263200 -32400 0 AKST}
+ {1018177200 -28800 1 AKDT}
+ {1035712800 -32400 0 AKST}
+ {1049626800 -28800 1 AKDT}
+ {1067162400 -32400 0 AKST}
+ {1081076400 -28800 1 AKDT}
+ {1099216800 -32400 0 AKST}
+ {1112526000 -28800 1 AKDT}
+ {1130666400 -32400 0 AKST}
+ {1143975600 -28800 1 AKDT}
+ {1162116000 -32400 0 AKST}
+ {1173610800 -28800 1 AKDT}
+ {1194170400 -32400 0 AKST}
+ {1205060400 -28800 1 AKDT}
+ {1225620000 -32400 0 AKST}
+ {1236510000 -28800 1 AKDT}
+ {1257069600 -32400 0 AKST}
+ {1268564400 -28800 1 AKDT}
+ {1289124000 -32400 0 AKST}
+ {1300014000 -28800 1 AKDT}
+ {1320573600 -32400 0 AKST}
+ {1331463600 -28800 1 AKDT}
+ {1352023200 -32400 0 AKST}
+ {1362913200 -28800 1 AKDT}
+ {1383472800 -32400 0 AKST}
+ {1394362800 -28800 1 AKDT}
+ {1414922400 -32400 0 AKST}
+ {1425812400 -28800 1 AKDT}
+ {1446372000 -32400 0 AKST}
+ {1457866800 -28800 1 AKDT}
+ {1478426400 -32400 0 AKST}
+ {1489316400 -28800 1 AKDT}
+ {1509876000 -32400 0 AKST}
+ {1520766000 -28800 1 AKDT}
+ {1541325600 -32400 0 AKST}
+ {1552215600 -28800 1 AKDT}
+ {1572775200 -32400 0 AKST}
+ {1583665200 -28800 1 AKDT}
+ {1604224800 -32400 0 AKST}
+ {1615719600 -28800 1 AKDT}
+ {1636279200 -32400 0 AKST}
+ {1647169200 -28800 1 AKDT}
+ {1667728800 -32400 0 AKST}
+ {1678618800 -28800 1 AKDT}
+ {1699178400 -32400 0 AKST}
+ {1710068400 -28800 1 AKDT}
+ {1730628000 -32400 0 AKST}
+ {1741518000 -28800 1 AKDT}
+ {1762077600 -32400 0 AKST}
+ {1772967600 -28800 1 AKDT}
+ {1793527200 -32400 0 AKST}
+ {1805022000 -28800 1 AKDT}
+ {1825581600 -32400 0 AKST}
+ {1836471600 -28800 1 AKDT}
+ {1857031200 -32400 0 AKST}
+ {1867921200 -28800 1 AKDT}
+ {1888480800 -32400 0 AKST}
+ {1899370800 -28800 1 AKDT}
+ {1919930400 -32400 0 AKST}
+ {1930820400 -28800 1 AKDT}
+ {1951380000 -32400 0 AKST}
+ {1962874800 -28800 1 AKDT}
+ {1983434400 -32400 0 AKST}
+ {1994324400 -28800 1 AKDT}
+ {2014884000 -32400 0 AKST}
+ {2025774000 -28800 1 AKDT}
+ {2046333600 -32400 0 AKST}
+ {2057223600 -28800 1 AKDT}
+ {2077783200 -32400 0 AKST}
+ {2088673200 -28800 1 AKDT}
+ {2109232800 -32400 0 AKST}
+ {2120122800 -28800 1 AKDT}
+ {2140682400 -32400 0 AKST}
+ {2152177200 -28800 1 AKDT}
+ {2172736800 -32400 0 AKST}
+ {2183626800 -28800 1 AKDT}
+ {2204186400 -32400 0 AKST}
+ {2215076400 -28800 1 AKDT}
+ {2235636000 -32400 0 AKST}
+ {2246526000 -28800 1 AKDT}
+ {2267085600 -32400 0 AKST}
+ {2277975600 -28800 1 AKDT}
+ {2298535200 -32400 0 AKST}
+ {2309425200 -28800 1 AKDT}
+ {2329984800 -32400 0 AKST}
+ {2341479600 -28800 1 AKDT}
+ {2362039200 -32400 0 AKST}
+ {2372929200 -28800 1 AKDT}
+ {2393488800 -32400 0 AKST}
+ {2404378800 -28800 1 AKDT}
+ {2424938400 -32400 0 AKST}
+ {2435828400 -28800 1 AKDT}
+ {2456388000 -32400 0 AKST}
+ {2467278000 -28800 1 AKDT}
+ {2487837600 -32400 0 AKST}
+ {2499332400 -28800 1 AKDT}
+ {2519892000 -32400 0 AKST}
+ {2530782000 -28800 1 AKDT}
+ {2551341600 -32400 0 AKST}
+ {2562231600 -28800 1 AKDT}
+ {2582791200 -32400 0 AKST}
+ {2593681200 -28800 1 AKDT}
+ {2614240800 -32400 0 AKST}
+ {2625130800 -28800 1 AKDT}
+ {2645690400 -32400 0 AKST}
+ {2656580400 -28800 1 AKDT}
+ {2677140000 -32400 0 AKST}
+ {2688634800 -28800 1 AKDT}
+ {2709194400 -32400 0 AKST}
+ {2720084400 -28800 1 AKDT}
+ {2740644000 -32400 0 AKST}
+ {2751534000 -28800 1 AKDT}
+ {2772093600 -32400 0 AKST}
+ {2782983600 -28800 1 AKDT}
+ {2803543200 -32400 0 AKST}
+ {2814433200 -28800 1 AKDT}
+ {2834992800 -32400 0 AKST}
+ {2846487600 -28800 1 AKDT}
+ {2867047200 -32400 0 AKST}
+ {2877937200 -28800 1 AKDT}
+ {2898496800 -32400 0 AKST}
+ {2909386800 -28800 1 AKDT}
+ {2929946400 -32400 0 AKST}
+ {2940836400 -28800 1 AKDT}
+ {2961396000 -32400 0 AKST}
+ {2972286000 -28800 1 AKDT}
+ {2992845600 -32400 0 AKST}
+ {3003735600 -28800 1 AKDT}
+ {3024295200 -32400 0 AKST}
+ {3035790000 -28800 1 AKDT}
+ {3056349600 -32400 0 AKST}
+ {3067239600 -28800 1 AKDT}
+ {3087799200 -32400 0 AKST}
+ {3098689200 -28800 1 AKDT}
+ {3119248800 -32400 0 AKST}
+ {3130138800 -28800 1 AKDT}
+ {3150698400 -32400 0 AKST}
+ {3161588400 -28800 1 AKDT}
+ {3182148000 -32400 0 AKST}
+ {3193038000 -28800 1 AKDT}
+ {3213597600 -32400 0 AKST}
+ {3225092400 -28800 1 AKDT}
+ {3245652000 -32400 0 AKST}
+ {3256542000 -28800 1 AKDT}
+ {3277101600 -32400 0 AKST}
+ {3287991600 -28800 1 AKDT}
+ {3308551200 -32400 0 AKST}
+ {3319441200 -28800 1 AKDT}
+ {3340000800 -32400 0 AKST}
+ {3350890800 -28800 1 AKDT}
+ {3371450400 -32400 0 AKST}
+ {3382945200 -28800 1 AKDT}
+ {3403504800 -32400 0 AKST}
+ {3414394800 -28800 1 AKDT}
+ {3434954400 -32400 0 AKST}
+ {3445844400 -28800 1 AKDT}
+ {3466404000 -32400 0 AKST}
+ {3477294000 -28800 1 AKDT}
+ {3497853600 -32400 0 AKST}
+ {3508743600 -28800 1 AKDT}
+ {3529303200 -32400 0 AKST}
+ {3540193200 -28800 1 AKDT}
+ {3560752800 -32400 0 AKST}
+ {3572247600 -28800 1 AKDT}
+ {3592807200 -32400 0 AKST}
+ {3603697200 -28800 1 AKDT}
+ {3624256800 -32400 0 AKST}
+ {3635146800 -28800 1 AKDT}
+ {3655706400 -32400 0 AKST}
+ {3666596400 -28800 1 AKDT}
+ {3687156000 -32400 0 AKST}
+ {3698046000 -28800 1 AKDT}
+ {3718605600 -32400 0 AKST}
+ {3730100400 -28800 1 AKDT}
+ {3750660000 -32400 0 AKST}
+ {3761550000 -28800 1 AKDT}
+ {3782109600 -32400 0 AKST}
+ {3792999600 -28800 1 AKDT}
+ {3813559200 -32400 0 AKST}
+ {3824449200 -28800 1 AKDT}
+ {3845008800 -32400 0 AKST}
+ {3855898800 -28800 1 AKDT}
+ {3876458400 -32400 0 AKST}
+ {3887348400 -28800 1 AKDT}
+ {3907908000 -32400 0 AKST}
+ {3919402800 -28800 1 AKDT}
+ {3939962400 -32400 0 AKST}
+ {3950852400 -28800 1 AKDT}
+ {3971412000 -32400 0 AKST}
+ {3982302000 -28800 1 AKDT}
+ {4002861600 -32400 0 AKST}
+ {4013751600 -28800 1 AKDT}
+ {4034311200 -32400 0 AKST}
+ {4045201200 -28800 1 AKDT}
+ {4065760800 -32400 0 AKST}
+ {4076650800 -28800 1 AKDT}
+ {4097210400 -32400 0 AKST}
+}
diff --git a/library/tzdata/America/St_Barthelemy b/library/tzdata/America/St_Barthelemy
new file mode 100644
index 0000000..25c114a
--- /dev/null
+++ b/library/tzdata/America/St_Barthelemy
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Guadeloupe)]} {
+ LoadTimeZoneFile America/Guadeloupe
+}
+set TZData(:America/St_Barthelemy) $TZData(:America/Guadeloupe)
diff --git a/library/tzdata/America/St_Johns b/library/tzdata/America/St_Johns
new file mode 100644
index 0000000..59f92bb
--- /dev/null
+++ b/library/tzdata/America/St_Johns
@@ -0,0 +1,371 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/St_Johns) {
+ {-9223372036854775808 -12652 0 LMT}
+ {-2713897748 -12652 0 NST}
+ {-1664130548 -9052 1 NDT}
+ {-1650137348 -12652 0 NST}
+ {-1640982548 -12652 0 NST}
+ {-1632076148 -9052 1 NDT}
+ {-1614799748 -12652 0 NST}
+ {-1609446548 -12652 0 NST}
+ {-1598650148 -9052 1 NDT}
+ {-1590100148 -12652 0 NST}
+ {-1567286948 -9052 1 NDT}
+ {-1551565748 -12652 0 NST}
+ {-1535837348 -9052 1 NDT}
+ {-1520116148 -12652 0 NST}
+ {-1503782948 -9052 1 NDT}
+ {-1488666548 -12652 0 NST}
+ {-1472333348 -9052 1 NDT}
+ {-1457216948 -12652 0 NST}
+ {-1440883748 -9052 1 NDT}
+ {-1425767348 -12652 0 NST}
+ {-1409434148 -9052 1 NDT}
+ {-1394317748 -12652 0 NST}
+ {-1377984548 -9052 1 NDT}
+ {-1362263348 -12652 0 NST}
+ {-1346534948 -9052 1 NDT}
+ {-1330813748 -12652 0 NST}
+ {-1314480548 -9052 1 NDT}
+ {-1299364148 -12652 0 NST}
+ {-1283030948 -9052 1 NDT}
+ {-1267914548 -12652 0 NST}
+ {-1251581348 -9052 1 NDT}
+ {-1236464948 -12652 0 NST}
+ {-1220131748 -9052 1 NDT}
+ {-1205015348 -12652 0 NST}
+ {-1188682148 -9052 1 NDT}
+ {-1172960948 -12652 0 NST}
+ {-1156627748 -9052 1 NDT}
+ {-1141511348 -12652 0 NST}
+ {-1125178148 -9052 1 NDT}
+ {-1110061748 -12652 0 NST}
+ {-1096921748 -12600 0 NST}
+ {-1093728600 -9000 1 NDT}
+ {-1078612200 -12600 0 NST}
+ {-1061670600 -9000 1 NDT}
+ {-1048973400 -12600 0 NST}
+ {-1030221000 -9000 1 NDT}
+ {-1017523800 -12600 0 NST}
+ {-998771400 -9000 1 NDT}
+ {-986074200 -12600 0 NST}
+ {-966717000 -9000 1 NDT}
+ {-954624600 -12600 0 NST}
+ {-935267400 -9000 1 NDT}
+ {-922570200 -12600 0 NST}
+ {-903817800 -9000 1 NDT}
+ {-891120600 -12600 0 NST}
+ {-872368200 -9000 0 NWT}
+ {-769395600 -9000 1 NPT}
+ {-765401400 -12600 0 NST}
+ {-757369800 -12600 0 NST}
+ {-746044200 -9000 1 NDT}
+ {-733347000 -12600 0 NST}
+ {-714594600 -9000 1 NDT}
+ {-701897400 -12600 0 NST}
+ {-683145000 -9000 1 NDT}
+ {-670447800 -12600 0 NST}
+ {-651695400 -9000 1 NDT}
+ {-638998200 -12600 0 NST}
+ {-619641000 -9000 1 NDT}
+ {-606943800 -12600 0 NST}
+ {-589401000 -9000 1 NDT}
+ {-576099000 -12600 0 NST}
+ {-557951400 -9000 1 NDT}
+ {-544649400 -12600 0 NST}
+ {-526501800 -9000 1 NDT}
+ {-513199800 -12600 0 NST}
+ {-495052200 -9000 1 NDT}
+ {-481750200 -12600 0 NST}
+ {-463602600 -9000 1 NDT}
+ {-450300600 -12600 0 NST}
+ {-431548200 -9000 1 NDT}
+ {-418246200 -12600 0 NST}
+ {-400098600 -9000 1 NDT}
+ {-386796600 -12600 0 NST}
+ {-368649000 -9000 1 NDT}
+ {-355347000 -12600 0 NST}
+ {-337199400 -9000 1 NDT}
+ {-323897400 -12600 0 NST}
+ {-305749800 -9000 1 NDT}
+ {-289423800 -12600 0 NST}
+ {-273695400 -9000 1 NDT}
+ {-257974200 -12600 0 NST}
+ {-242245800 -9000 1 NDT}
+ {-226524600 -12600 0 NST}
+ {-210796200 -9000 1 NDT}
+ {-195075000 -12600 0 NST}
+ {-179346600 -9000 1 NDT}
+ {-163625400 -12600 0 NST}
+ {-147897000 -9000 1 NDT}
+ {-131571000 -12600 0 NST}
+ {-116447400 -9000 1 NDT}
+ {-100121400 -12600 0 NST}
+ {-84393000 -9000 1 NDT}
+ {-68671800 -12600 0 NST}
+ {-52943400 -9000 1 NDT}
+ {-37222200 -12600 0 NST}
+ {-21493800 -9000 1 NDT}
+ {-5772600 -12600 0 NST}
+ {9955800 -9000 1 NDT}
+ {25677000 -12600 0 NST}
+ {41405400 -9000 1 NDT}
+ {57731400 -12600 0 NST}
+ {73459800 -9000 1 NDT}
+ {89181000 -12600 0 NST}
+ {104909400 -9000 1 NDT}
+ {120630600 -12600 0 NST}
+ {136359000 -9000 1 NDT}
+ {152080200 -12600 0 NST}
+ {167808600 -9000 1 NDT}
+ {183529800 -12600 0 NST}
+ {199258200 -9000 1 NDT}
+ {215584200 -12600 0 NST}
+ {230707800 -9000 1 NDT}
+ {247033800 -12600 0 NST}
+ {262762200 -9000 1 NDT}
+ {278483400 -12600 0 NST}
+ {294211800 -9000 1 NDT}
+ {309933000 -12600 0 NST}
+ {325661400 -9000 1 NDT}
+ {341382600 -12600 0 NST}
+ {357111000 -9000 1 NDT}
+ {372832200 -12600 0 NST}
+ {388560600 -9000 1 NDT}
+ {404886600 -12600 0 NST}
+ {420010200 -9000 1 NDT}
+ {436336200 -12600 0 NST}
+ {452064600 -9000 1 NDT}
+ {467785800 -12600 0 NST}
+ {483514200 -9000 1 NDT}
+ {499235400 -12600 0 NST}
+ {514963800 -9000 1 NDT}
+ {530685000 -12600 0 NST}
+ {544591860 -9000 1 NDT}
+ {562127460 -12600 0 NST}
+ {576041460 -5400 1 NDDT}
+ {594178260 -12600 0 NST}
+ {607491060 -9000 1 NDT}
+ {625631460 -12600 0 NST}
+ {638940660 -9000 1 NDT}
+ {657081060 -12600 0 NST}
+ {670995060 -9000 1 NDT}
+ {688530660 -12600 0 NST}
+ {702444660 -9000 1 NDT}
+ {719980260 -12600 0 NST}
+ {733894260 -9000 1 NDT}
+ {752034660 -12600 0 NST}
+ {765343860 -9000 1 NDT}
+ {783484260 -12600 0 NST}
+ {796793460 -9000 1 NDT}
+ {814933860 -12600 0 NST}
+ {828847860 -9000 1 NDT}
+ {846383460 -12600 0 NST}
+ {860297460 -9000 1 NDT}
+ {877833060 -12600 0 NST}
+ {891747060 -9000 1 NDT}
+ {909282660 -12600 0 NST}
+ {923196660 -9000 1 NDT}
+ {941337060 -12600 0 NST}
+ {954646260 -9000 1 NDT}
+ {972786660 -12600 0 NST}
+ {986095860 -9000 1 NDT}
+ {1004236260 -12600 0 NST}
+ {1018150260 -9000 1 NDT}
+ {1035685860 -12600 0 NST}
+ {1049599860 -9000 1 NDT}
+ {1067135460 -12600 0 NST}
+ {1081049460 -9000 1 NDT}
+ {1099189860 -12600 0 NST}
+ {1112499060 -9000 1 NDT}
+ {1130639460 -12600 0 NST}
+ {1143948660 -9000 1 NDT}
+ {1162089060 -12600 0 NST}
+ {1173583860 -9000 1 NDT}
+ {1194143460 -12600 0 NST}
+ {1205033460 -9000 1 NDT}
+ {1225593060 -12600 0 NST}
+ {1236483060 -9000 1 NDT}
+ {1257042660 -12600 0 NST}
+ {1268537460 -9000 1 NDT}
+ {1289097060 -12600 0 NST}
+ {1299987060 -9000 1 NDT}
+ {1320546660 -12600 0 NST}
+ {1331436660 -9000 1 NDT}
+ {1351996260 -12600 0 NST}
+ {1362886260 -9000 1 NDT}
+ {1383445860 -12600 0 NST}
+ {1394335860 -9000 1 NDT}
+ {1414895460 -12600 0 NST}
+ {1425785460 -9000 1 NDT}
+ {1446345060 -12600 0 NST}
+ {1457839860 -9000 1 NDT}
+ {1478399460 -12600 0 NST}
+ {1489289460 -9000 1 NDT}
+ {1509849060 -12600 0 NST}
+ {1520739060 -9000 1 NDT}
+ {1541298660 -12600 0 NST}
+ {1552188660 -9000 1 NDT}
+ {1572748260 -12600 0 NST}
+ {1583638260 -9000 1 NDT}
+ {1604197860 -12600 0 NST}
+ {1615692660 -9000 1 NDT}
+ {1636252260 -12600 0 NST}
+ {1647142260 -9000 1 NDT}
+ {1667701860 -12600 0 NST}
+ {1678591860 -9000 1 NDT}
+ {1699151460 -12600 0 NST}
+ {1710041460 -9000 1 NDT}
+ {1730601060 -12600 0 NST}
+ {1741491060 -9000 1 NDT}
+ {1762050660 -12600 0 NST}
+ {1772940660 -9000 1 NDT}
+ {1793500260 -12600 0 NST}
+ {1804995060 -9000 1 NDT}
+ {1825554660 -12600 0 NST}
+ {1836444660 -9000 1 NDT}
+ {1857004260 -12600 0 NST}
+ {1867894260 -9000 1 NDT}
+ {1888453860 -12600 0 NST}
+ {1899343860 -9000 1 NDT}
+ {1919903460 -12600 0 NST}
+ {1930793460 -9000 1 NDT}
+ {1951353060 -12600 0 NST}
+ {1962847860 -9000 1 NDT}
+ {1983407460 -12600 0 NST}
+ {1994297460 -9000 1 NDT}
+ {2014857060 -12600 0 NST}
+ {2025747060 -9000 1 NDT}
+ {2046306660 -12600 0 NST}
+ {2057196660 -9000 1 NDT}
+ {2077756260 -12600 0 NST}
+ {2088646260 -9000 1 NDT}
+ {2109205860 -12600 0 NST}
+ {2120095860 -9000 1 NDT}
+ {2140655460 -12600 0 NST}
+ {2152150260 -9000 1 NDT}
+ {2172709860 -12600 0 NST}
+ {2183599860 -9000 1 NDT}
+ {2204159460 -12600 0 NST}
+ {2215049460 -9000 1 NDT}
+ {2235609060 -12600 0 NST}
+ {2246499060 -9000 1 NDT}
+ {2267058660 -12600 0 NST}
+ {2277948660 -9000 1 NDT}
+ {2298508260 -12600 0 NST}
+ {2309398260 -9000 1 NDT}
+ {2329957860 -12600 0 NST}
+ {2341452660 -9000 1 NDT}
+ {2362012260 -12600 0 NST}
+ {2372902260 -9000 1 NDT}
+ {2393461860 -12600 0 NST}
+ {2404351860 -9000 1 NDT}
+ {2424911460 -12600 0 NST}
+ {2435801460 -9000 1 NDT}
+ {2456361060 -12600 0 NST}
+ {2467251060 -9000 1 NDT}
+ {2487810660 -12600 0 NST}
+ {2499305460 -9000 1 NDT}
+ {2519865060 -12600 0 NST}
+ {2530755060 -9000 1 NDT}
+ {2551314660 -12600 0 NST}
+ {2562204660 -9000 1 NDT}
+ {2582764260 -12600 0 NST}
+ {2593654260 -9000 1 NDT}
+ {2614213860 -12600 0 NST}
+ {2625103860 -9000 1 NDT}
+ {2645663460 -12600 0 NST}
+ {2656553460 -9000 1 NDT}
+ {2677113060 -12600 0 NST}
+ {2688607860 -9000 1 NDT}
+ {2709167460 -12600 0 NST}
+ {2720057460 -9000 1 NDT}
+ {2740617060 -12600 0 NST}
+ {2751507060 -9000 1 NDT}
+ {2772066660 -12600 0 NST}
+ {2782956660 -9000 1 NDT}
+ {2803516260 -12600 0 NST}
+ {2814406260 -9000 1 NDT}
+ {2834965860 -12600 0 NST}
+ {2846460660 -9000 1 NDT}
+ {2867020260 -12600 0 NST}
+ {2877910260 -9000 1 NDT}
+ {2898469860 -12600 0 NST}
+ {2909359860 -9000 1 NDT}
+ {2929919460 -12600 0 NST}
+ {2940809460 -9000 1 NDT}
+ {2961369060 -12600 0 NST}
+ {2972259060 -9000 1 NDT}
+ {2992818660 -12600 0 NST}
+ {3003708660 -9000 1 NDT}
+ {3024268260 -12600 0 NST}
+ {3035763060 -9000 1 NDT}
+ {3056322660 -12600 0 NST}
+ {3067212660 -9000 1 NDT}
+ {3087772260 -12600 0 NST}
+ {3098662260 -9000 1 NDT}
+ {3119221860 -12600 0 NST}
+ {3130111860 -9000 1 NDT}
+ {3150671460 -12600 0 NST}
+ {3161561460 -9000 1 NDT}
+ {3182121060 -12600 0 NST}
+ {3193011060 -9000 1 NDT}
+ {3213570660 -12600 0 NST}
+ {3225065460 -9000 1 NDT}
+ {3245625060 -12600 0 NST}
+ {3256515060 -9000 1 NDT}
+ {3277074660 -12600 0 NST}
+ {3287964660 -9000 1 NDT}
+ {3308524260 -12600 0 NST}
+ {3319414260 -9000 1 NDT}
+ {3339973860 -12600 0 NST}
+ {3350863860 -9000 1 NDT}
+ {3371423460 -12600 0 NST}
+ {3382918260 -9000 1 NDT}
+ {3403477860 -12600 0 NST}
+ {3414367860 -9000 1 NDT}
+ {3434927460 -12600 0 NST}
+ {3445817460 -9000 1 NDT}
+ {3466377060 -12600 0 NST}
+ {3477267060 -9000 1 NDT}
+ {3497826660 -12600 0 NST}
+ {3508716660 -9000 1 NDT}
+ {3529276260 -12600 0 NST}
+ {3540166260 -9000 1 NDT}
+ {3560725860 -12600 0 NST}
+ {3572220660 -9000 1 NDT}
+ {3592780260 -12600 0 NST}
+ {3603670260 -9000 1 NDT}
+ {3624229860 -12600 0 NST}
+ {3635119860 -9000 1 NDT}
+ {3655679460 -12600 0 NST}
+ {3666569460 -9000 1 NDT}
+ {3687129060 -12600 0 NST}
+ {3698019060 -9000 1 NDT}
+ {3718578660 -12600 0 NST}
+ {3730073460 -9000 1 NDT}
+ {3750633060 -12600 0 NST}
+ {3761523060 -9000 1 NDT}
+ {3782082660 -12600 0 NST}
+ {3792972660 -9000 1 NDT}
+ {3813532260 -12600 0 NST}
+ {3824422260 -9000 1 NDT}
+ {3844981860 -12600 0 NST}
+ {3855871860 -9000 1 NDT}
+ {3876431460 -12600 0 NST}
+ {3887321460 -9000 1 NDT}
+ {3907881060 -12600 0 NST}
+ {3919375860 -9000 1 NDT}
+ {3939935460 -12600 0 NST}
+ {3950825460 -9000 1 NDT}
+ {3971385060 -12600 0 NST}
+ {3982275060 -9000 1 NDT}
+ {4002834660 -12600 0 NST}
+ {4013724660 -9000 1 NDT}
+ {4034284260 -12600 0 NST}
+ {4045174260 -9000 1 NDT}
+ {4065733860 -12600 0 NST}
+ {4076623860 -9000 1 NDT}
+ {4097183460 -12600 0 NST}
+}
diff --git a/library/tzdata/America/St_Kitts b/library/tzdata/America/St_Kitts
new file mode 100644
index 0000000..bfd803b
--- /dev/null
+++ b/library/tzdata/America/St_Kitts
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/St_Kitts) {
+ {-9223372036854775808 -15052 0 LMT}
+ {-1825098548 -14400 0 AST}
+}
diff --git a/library/tzdata/America/St_Lucia b/library/tzdata/America/St_Lucia
new file mode 100644
index 0000000..c2767dd
--- /dev/null
+++ b/library/tzdata/America/St_Lucia
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/St_Lucia) {
+ {-9223372036854775808 -14640 0 LMT}
+ {-2524506960 -14640 0 CMT}
+ {-1830369360 -14400 0 AST}
+}
diff --git a/library/tzdata/America/St_Thomas b/library/tzdata/America/St_Thomas
new file mode 100644
index 0000000..bf93595
--- /dev/null
+++ b/library/tzdata/America/St_Thomas
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/St_Thomas) {
+ {-9223372036854775808 -15584 0 LMT}
+ {-1846266016 -14400 0 AST}
+}
diff --git a/library/tzdata/America/St_Vincent b/library/tzdata/America/St_Vincent
new file mode 100644
index 0000000..3a884c7
--- /dev/null
+++ b/library/tzdata/America/St_Vincent
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/St_Vincent) {
+ {-9223372036854775808 -14696 0 LMT}
+ {-2524506904 -14696 0 KMT}
+ {-1830369304 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Swift_Current b/library/tzdata/America/Swift_Current
new file mode 100644
index 0000000..dc4aa37
--- /dev/null
+++ b/library/tzdata/America/Swift_Current
@@ -0,0 +1,29 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Swift_Current) {
+ {-9223372036854775808 -25880 0 LMT}
+ {-2030201320 -25200 0 MST}
+ {-1632063600 -21600 1 MDT}
+ {-1614787200 -25200 0 MST}
+ {-880210800 -21600 1 MWT}
+ {-769395600 -21600 1 MPT}
+ {-765388800 -25200 0 MST}
+ {-747241200 -21600 0 MDT}
+ {-732729600 -25200 0 MST}
+ {-715791600 -21600 1 MDT}
+ {-702489600 -25200 0 MST}
+ {-684342000 -21600 1 MDT}
+ {-671040000 -25200 0 MST}
+ {-652892400 -21600 1 MDT}
+ {-639590400 -25200 0 MST}
+ {-631126800 -25200 0 MST}
+ {-400086000 -21600 1 MDT}
+ {-384364800 -25200 0 MST}
+ {-337186800 -21600 1 MDT}
+ {-321465600 -25200 0 MST}
+ {-305737200 -21600 1 MDT}
+ {-292435200 -25200 0 MST}
+ {-273682800 -21600 1 MDT}
+ {-260985600 -25200 0 MST}
+ {73472400 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Tegucigalpa b/library/tzdata/America/Tegucigalpa
new file mode 100644
index 0000000..050661e
--- /dev/null
+++ b/library/tzdata/America/Tegucigalpa
@@ -0,0 +1,12 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Tegucigalpa) {
+ {-9223372036854775808 -20932 0 LMT}
+ {-1538503868 -21600 0 CST}
+ {547020000 -18000 1 CDT}
+ {559717200 -21600 0 CST}
+ {578469600 -18000 1 CDT}
+ {591166800 -21600 0 CST}
+ {1146981600 -18000 1 CDT}
+ {1154926800 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Thule b/library/tzdata/America/Thule
new file mode 100644
index 0000000..0aaf9a1
--- /dev/null
+++ b/library/tzdata/America/Thule
@@ -0,0 +1,224 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Thule) {
+ {-9223372036854775808 -16508 0 LMT}
+ {-1686079492 -14400 0 AST}
+ {670399200 -10800 1 ADT}
+ {686120400 -14400 0 AST}
+ {701848800 -10800 1 ADT}
+ {717570000 -14400 0 AST}
+ {733903200 -10800 1 ADT}
+ {752043600 -14400 0 AST}
+ {765352800 -10800 1 ADT}
+ {783493200 -14400 0 AST}
+ {796802400 -10800 1 ADT}
+ {814942800 -14400 0 AST}
+ {828856800 -10800 1 ADT}
+ {846392400 -14400 0 AST}
+ {860306400 -10800 1 ADT}
+ {877842000 -14400 0 AST}
+ {891756000 -10800 1 ADT}
+ {909291600 -14400 0 AST}
+ {923205600 -10800 1 ADT}
+ {941346000 -14400 0 AST}
+ {954655200 -10800 1 ADT}
+ {972795600 -14400 0 AST}
+ {986104800 -10800 1 ADT}
+ {1004245200 -14400 0 AST}
+ {1018159200 -10800 1 ADT}
+ {1035694800 -14400 0 AST}
+ {1049608800 -10800 1 ADT}
+ {1067144400 -14400 0 AST}
+ {1081058400 -10800 1 ADT}
+ {1099198800 -14400 0 AST}
+ {1112508000 -10800 1 ADT}
+ {1130648400 -14400 0 AST}
+ {1143957600 -10800 1 ADT}
+ {1162098000 -14400 0 AST}
+ {1173592800 -10800 1 ADT}
+ {1194152400 -14400 0 AST}
+ {1205042400 -10800 1 ADT}
+ {1225602000 -14400 0 AST}
+ {1236492000 -10800 1 ADT}
+ {1257051600 -14400 0 AST}
+ {1268546400 -10800 1 ADT}
+ {1289106000 -14400 0 AST}
+ {1299996000 -10800 1 ADT}
+ {1320555600 -14400 0 AST}
+ {1331445600 -10800 1 ADT}
+ {1352005200 -14400 0 AST}
+ {1362895200 -10800 1 ADT}
+ {1383454800 -14400 0 AST}
+ {1394344800 -10800 1 ADT}
+ {1414904400 -14400 0 AST}
+ {1425794400 -10800 1 ADT}
+ {1446354000 -14400 0 AST}
+ {1457848800 -10800 1 ADT}
+ {1478408400 -14400 0 AST}
+ {1489298400 -10800 1 ADT}
+ {1509858000 -14400 0 AST}
+ {1520748000 -10800 1 ADT}
+ {1541307600 -14400 0 AST}
+ {1552197600 -10800 1 ADT}
+ {1572757200 -14400 0 AST}
+ {1583647200 -10800 1 ADT}
+ {1604206800 -14400 0 AST}
+ {1615701600 -10800 1 ADT}
+ {1636261200 -14400 0 AST}
+ {1647151200 -10800 1 ADT}
+ {1667710800 -14400 0 AST}
+ {1678600800 -10800 1 ADT}
+ {1699160400 -14400 0 AST}
+ {1710050400 -10800 1 ADT}
+ {1730610000 -14400 0 AST}
+ {1741500000 -10800 1 ADT}
+ {1762059600 -14400 0 AST}
+ {1772949600 -10800 1 ADT}
+ {1793509200 -14400 0 AST}
+ {1805004000 -10800 1 ADT}
+ {1825563600 -14400 0 AST}
+ {1836453600 -10800 1 ADT}
+ {1857013200 -14400 0 AST}
+ {1867903200 -10800 1 ADT}
+ {1888462800 -14400 0 AST}
+ {1899352800 -10800 1 ADT}
+ {1919912400 -14400 0 AST}
+ {1930802400 -10800 1 ADT}
+ {1951362000 -14400 0 AST}
+ {1962856800 -10800 1 ADT}
+ {1983416400 -14400 0 AST}
+ {1994306400 -10800 1 ADT}
+ {2014866000 -14400 0 AST}
+ {2025756000 -10800 1 ADT}
+ {2046315600 -14400 0 AST}
+ {2057205600 -10800 1 ADT}
+ {2077765200 -14400 0 AST}
+ {2088655200 -10800 1 ADT}
+ {2109214800 -14400 0 AST}
+ {2120104800 -10800 1 ADT}
+ {2140664400 -14400 0 AST}
+ {2152159200 -10800 1 ADT}
+ {2172718800 -14400 0 AST}
+ {2183608800 -10800 1 ADT}
+ {2204168400 -14400 0 AST}
+ {2215058400 -10800 1 ADT}
+ {2235618000 -14400 0 AST}
+ {2246508000 -10800 1 ADT}
+ {2267067600 -14400 0 AST}
+ {2277957600 -10800 1 ADT}
+ {2298517200 -14400 0 AST}
+ {2309407200 -10800 1 ADT}
+ {2329966800 -14400 0 AST}
+ {2341461600 -10800 1 ADT}
+ {2362021200 -14400 0 AST}
+ {2372911200 -10800 1 ADT}
+ {2393470800 -14400 0 AST}
+ {2404360800 -10800 1 ADT}
+ {2424920400 -14400 0 AST}
+ {2435810400 -10800 1 ADT}
+ {2456370000 -14400 0 AST}
+ {2467260000 -10800 1 ADT}
+ {2487819600 -14400 0 AST}
+ {2499314400 -10800 1 ADT}
+ {2519874000 -14400 0 AST}
+ {2530764000 -10800 1 ADT}
+ {2551323600 -14400 0 AST}
+ {2562213600 -10800 1 ADT}
+ {2582773200 -14400 0 AST}
+ {2593663200 -10800 1 ADT}
+ {2614222800 -14400 0 AST}
+ {2625112800 -10800 1 ADT}
+ {2645672400 -14400 0 AST}
+ {2656562400 -10800 1 ADT}
+ {2677122000 -14400 0 AST}
+ {2688616800 -10800 1 ADT}
+ {2709176400 -14400 0 AST}
+ {2720066400 -10800 1 ADT}
+ {2740626000 -14400 0 AST}
+ {2751516000 -10800 1 ADT}
+ {2772075600 -14400 0 AST}
+ {2782965600 -10800 1 ADT}
+ {2803525200 -14400 0 AST}
+ {2814415200 -10800 1 ADT}
+ {2834974800 -14400 0 AST}
+ {2846469600 -10800 1 ADT}
+ {2867029200 -14400 0 AST}
+ {2877919200 -10800 1 ADT}
+ {2898478800 -14400 0 AST}
+ {2909368800 -10800 1 ADT}
+ {2929928400 -14400 0 AST}
+ {2940818400 -10800 1 ADT}
+ {2961378000 -14400 0 AST}
+ {2972268000 -10800 1 ADT}
+ {2992827600 -14400 0 AST}
+ {3003717600 -10800 1 ADT}
+ {3024277200 -14400 0 AST}
+ {3035772000 -10800 1 ADT}
+ {3056331600 -14400 0 AST}
+ {3067221600 -10800 1 ADT}
+ {3087781200 -14400 0 AST}
+ {3098671200 -10800 1 ADT}
+ {3119230800 -14400 0 AST}
+ {3130120800 -10800 1 ADT}
+ {3150680400 -14400 0 AST}
+ {3161570400 -10800 1 ADT}
+ {3182130000 -14400 0 AST}
+ {3193020000 -10800 1 ADT}
+ {3213579600 -14400 0 AST}
+ {3225074400 -10800 1 ADT}
+ {3245634000 -14400 0 AST}
+ {3256524000 -10800 1 ADT}
+ {3277083600 -14400 0 AST}
+ {3287973600 -10800 1 ADT}
+ {3308533200 -14400 0 AST}
+ {3319423200 -10800 1 ADT}
+ {3339982800 -14400 0 AST}
+ {3350872800 -10800 1 ADT}
+ {3371432400 -14400 0 AST}
+ {3382927200 -10800 1 ADT}
+ {3403486800 -14400 0 AST}
+ {3414376800 -10800 1 ADT}
+ {3434936400 -14400 0 AST}
+ {3445826400 -10800 1 ADT}
+ {3466386000 -14400 0 AST}
+ {3477276000 -10800 1 ADT}
+ {3497835600 -14400 0 AST}
+ {3508725600 -10800 1 ADT}
+ {3529285200 -14400 0 AST}
+ {3540175200 -10800 1 ADT}
+ {3560734800 -14400 0 AST}
+ {3572229600 -10800 1 ADT}
+ {3592789200 -14400 0 AST}
+ {3603679200 -10800 1 ADT}
+ {3624238800 -14400 0 AST}
+ {3635128800 -10800 1 ADT}
+ {3655688400 -14400 0 AST}
+ {3666578400 -10800 1 ADT}
+ {3687138000 -14400 0 AST}
+ {3698028000 -10800 1 ADT}
+ {3718587600 -14400 0 AST}
+ {3730082400 -10800 1 ADT}
+ {3750642000 -14400 0 AST}
+ {3761532000 -10800 1 ADT}
+ {3782091600 -14400 0 AST}
+ {3792981600 -10800 1 ADT}
+ {3813541200 -14400 0 AST}
+ {3824431200 -10800 1 ADT}
+ {3844990800 -14400 0 AST}
+ {3855880800 -10800 1 ADT}
+ {3876440400 -14400 0 AST}
+ {3887330400 -10800 1 ADT}
+ {3907890000 -14400 0 AST}
+ {3919384800 -10800 1 ADT}
+ {3939944400 -14400 0 AST}
+ {3950834400 -10800 1 ADT}
+ {3971394000 -14400 0 AST}
+ {3982284000 -10800 1 ADT}
+ {4002843600 -14400 0 AST}
+ {4013733600 -10800 1 ADT}
+ {4034293200 -14400 0 AST}
+ {4045183200 -10800 1 ADT}
+ {4065742800 -14400 0 AST}
+ {4076632800 -10800 1 ADT}
+ {4097192400 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Thunder_Bay b/library/tzdata/America/Thunder_Bay
new file mode 100644
index 0000000..8a454be
--- /dev/null
+++ b/library/tzdata/America/Thunder_Bay
@@ -0,0 +1,272 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Thunder_Bay) {
+ {-9223372036854775808 -21420 0 LMT}
+ {-2366733780 -21600 0 CST}
+ {-1893434400 -18000 0 EST}
+ {-883594800 -18000 0 EST}
+ {-880218000 -14400 1 EWT}
+ {-769395600 -14400 1 EPT}
+ {-765396000 -18000 0 EST}
+ {18000 -18000 0 EST}
+ {9961200 -14400 1 EDT}
+ {25682400 -18000 0 EST}
+ {41410800 -14400 1 EDT}
+ {57736800 -18000 0 EST}
+ {73465200 -14400 1 EDT}
+ {89186400 -18000 0 EST}
+ {94712400 -18000 0 EST}
+ {126248400 -18000 0 EST}
+ {136364400 -14400 1 EDT}
+ {152085600 -18000 0 EST}
+ {167814000 -14400 1 EDT}
+ {183535200 -18000 0 EST}
+ {199263600 -14400 1 EDT}
+ {215589600 -18000 0 EST}
+ {230713200 -14400 1 EDT}
+ {247039200 -18000 0 EST}
+ {262767600 -14400 1 EDT}
+ {278488800 -18000 0 EST}
+ {294217200 -14400 1 EDT}
+ {309938400 -18000 0 EST}
+ {325666800 -14400 1 EDT}
+ {341388000 -18000 0 EST}
+ {357116400 -14400 1 EDT}
+ {372837600 -18000 0 EST}
+ {388566000 -14400 1 EDT}
+ {404892000 -18000 0 EST}
+ {420015600 -14400 1 EDT}
+ {436341600 -18000 0 EST}
+ {452070000 -14400 1 EDT}
+ {467791200 -18000 0 EST}
+ {483519600 -14400 1 EDT}
+ {499240800 -18000 0 EST}
+ {514969200 -14400 1 EDT}
+ {530690400 -18000 0 EST}
+ {544604400 -14400 1 EDT}
+ {562140000 -18000 0 EST}
+ {576054000 -14400 1 EDT}
+ {594194400 -18000 0 EST}
+ {607503600 -14400 1 EDT}
+ {625644000 -18000 0 EST}
+ {638953200 -14400 1 EDT}
+ {657093600 -18000 0 EST}
+ {671007600 -14400 1 EDT}
+ {688543200 -18000 0 EST}
+ {702457200 -14400 1 EDT}
+ {719992800 -18000 0 EST}
+ {733906800 -14400 1 EDT}
+ {752047200 -18000 0 EST}
+ {765356400 -14400 1 EDT}
+ {783496800 -18000 0 EST}
+ {796806000 -14400 1 EDT}
+ {814946400 -18000 0 EST}
+ {828860400 -14400 1 EDT}
+ {846396000 -18000 0 EST}
+ {860310000 -14400 1 EDT}
+ {877845600 -18000 0 EST}
+ {891759600 -14400 1 EDT}
+ {909295200 -18000 0 EST}
+ {923209200 -14400 1 EDT}
+ {941349600 -18000 0 EST}
+ {954658800 -14400 1 EDT}
+ {972799200 -18000 0 EST}
+ {986108400 -14400 1 EDT}
+ {1004248800 -18000 0 EST}
+ {1018162800 -14400 1 EDT}
+ {1035698400 -18000 0 EST}
+ {1049612400 -14400 1 EDT}
+ {1067148000 -18000 0 EST}
+ {1081062000 -14400 1 EDT}
+ {1099202400 -18000 0 EST}
+ {1112511600 -14400 1 EDT}
+ {1130652000 -18000 0 EST}
+ {1143961200 -14400 1 EDT}
+ {1162101600 -18000 0 EST}
+ {1173596400 -14400 1 EDT}
+ {1194156000 -18000 0 EST}
+ {1205046000 -14400 1 EDT}
+ {1225605600 -18000 0 EST}
+ {1236495600 -14400 1 EDT}
+ {1257055200 -18000 0 EST}
+ {1268550000 -14400 1 EDT}
+ {1289109600 -18000 0 EST}
+ {1299999600 -14400 1 EDT}
+ {1320559200 -18000 0 EST}
+ {1331449200 -14400 1 EDT}
+ {1352008800 -18000 0 EST}
+ {1362898800 -14400 1 EDT}
+ {1383458400 -18000 0 EST}
+ {1394348400 -14400 1 EDT}
+ {1414908000 -18000 0 EST}
+ {1425798000 -14400 1 EDT}
+ {1446357600 -18000 0 EST}
+ {1457852400 -14400 1 EDT}
+ {1478412000 -18000 0 EST}
+ {1489302000 -14400 1 EDT}
+ {1509861600 -18000 0 EST}
+ {1520751600 -14400 1 EDT}
+ {1541311200 -18000 0 EST}
+ {1552201200 -14400 1 EDT}
+ {1572760800 -18000 0 EST}
+ {1583650800 -14400 1 EDT}
+ {1604210400 -18000 0 EST}
+ {1615705200 -14400 1 EDT}
+ {1636264800 -18000 0 EST}
+ {1647154800 -14400 1 EDT}
+ {1667714400 -18000 0 EST}
+ {1678604400 -14400 1 EDT}
+ {1699164000 -18000 0 EST}
+ {1710054000 -14400 1 EDT}
+ {1730613600 -18000 0 EST}
+ {1741503600 -14400 1 EDT}
+ {1762063200 -18000 0 EST}
+ {1772953200 -14400 1 EDT}
+ {1793512800 -18000 0 EST}
+ {1805007600 -14400 1 EDT}
+ {1825567200 -18000 0 EST}
+ {1836457200 -14400 1 EDT}
+ {1857016800 -18000 0 EST}
+ {1867906800 -14400 1 EDT}
+ {1888466400 -18000 0 EST}
+ {1899356400 -14400 1 EDT}
+ {1919916000 -18000 0 EST}
+ {1930806000 -14400 1 EDT}
+ {1951365600 -18000 0 EST}
+ {1962860400 -14400 1 EDT}
+ {1983420000 -18000 0 EST}
+ {1994310000 -14400 1 EDT}
+ {2014869600 -18000 0 EST}
+ {2025759600 -14400 1 EDT}
+ {2046319200 -18000 0 EST}
+ {2057209200 -14400 1 EDT}
+ {2077768800 -18000 0 EST}
+ {2088658800 -14400 1 EDT}
+ {2109218400 -18000 0 EST}
+ {2120108400 -14400 1 EDT}
+ {2140668000 -18000 0 EST}
+ {2152162800 -14400 1 EDT}
+ {2172722400 -18000 0 EST}
+ {2183612400 -14400 1 EDT}
+ {2204172000 -18000 0 EST}
+ {2215062000 -14400 1 EDT}
+ {2235621600 -18000 0 EST}
+ {2246511600 -14400 1 EDT}
+ {2267071200 -18000 0 EST}
+ {2277961200 -14400 1 EDT}
+ {2298520800 -18000 0 EST}
+ {2309410800 -14400 1 EDT}
+ {2329970400 -18000 0 EST}
+ {2341465200 -14400 1 EDT}
+ {2362024800 -18000 0 EST}
+ {2372914800 -14400 1 EDT}
+ {2393474400 -18000 0 EST}
+ {2404364400 -14400 1 EDT}
+ {2424924000 -18000 0 EST}
+ {2435814000 -14400 1 EDT}
+ {2456373600 -18000 0 EST}
+ {2467263600 -14400 1 EDT}
+ {2487823200 -18000 0 EST}
+ {2499318000 -14400 1 EDT}
+ {2519877600 -18000 0 EST}
+ {2530767600 -14400 1 EDT}
+ {2551327200 -18000 0 EST}
+ {2562217200 -14400 1 EDT}
+ {2582776800 -18000 0 EST}
+ {2593666800 -14400 1 EDT}
+ {2614226400 -18000 0 EST}
+ {2625116400 -14400 1 EDT}
+ {2645676000 -18000 0 EST}
+ {2656566000 -14400 1 EDT}
+ {2677125600 -18000 0 EST}
+ {2688620400 -14400 1 EDT}
+ {2709180000 -18000 0 EST}
+ {2720070000 -14400 1 EDT}
+ {2740629600 -18000 0 EST}
+ {2751519600 -14400 1 EDT}
+ {2772079200 -18000 0 EST}
+ {2782969200 -14400 1 EDT}
+ {2803528800 -18000 0 EST}
+ {2814418800 -14400 1 EDT}
+ {2834978400 -18000 0 EST}
+ {2846473200 -14400 1 EDT}
+ {2867032800 -18000 0 EST}
+ {2877922800 -14400 1 EDT}
+ {2898482400 -18000 0 EST}
+ {2909372400 -14400 1 EDT}
+ {2929932000 -18000 0 EST}
+ {2940822000 -14400 1 EDT}
+ {2961381600 -18000 0 EST}
+ {2972271600 -14400 1 EDT}
+ {2992831200 -18000 0 EST}
+ {3003721200 -14400 1 EDT}
+ {3024280800 -18000 0 EST}
+ {3035775600 -14400 1 EDT}
+ {3056335200 -18000 0 EST}
+ {3067225200 -14400 1 EDT}
+ {3087784800 -18000 0 EST}
+ {3098674800 -14400 1 EDT}
+ {3119234400 -18000 0 EST}
+ {3130124400 -14400 1 EDT}
+ {3150684000 -18000 0 EST}
+ {3161574000 -14400 1 EDT}
+ {3182133600 -18000 0 EST}
+ {3193023600 -14400 1 EDT}
+ {3213583200 -18000 0 EST}
+ {3225078000 -14400 1 EDT}
+ {3245637600 -18000 0 EST}
+ {3256527600 -14400 1 EDT}
+ {3277087200 -18000 0 EST}
+ {3287977200 -14400 1 EDT}
+ {3308536800 -18000 0 EST}
+ {3319426800 -14400 1 EDT}
+ {3339986400 -18000 0 EST}
+ {3350876400 -14400 1 EDT}
+ {3371436000 -18000 0 EST}
+ {3382930800 -14400 1 EDT}
+ {3403490400 -18000 0 EST}
+ {3414380400 -14400 1 EDT}
+ {3434940000 -18000 0 EST}
+ {3445830000 -14400 1 EDT}
+ {3466389600 -18000 0 EST}
+ {3477279600 -14400 1 EDT}
+ {3497839200 -18000 0 EST}
+ {3508729200 -14400 1 EDT}
+ {3529288800 -18000 0 EST}
+ {3540178800 -14400 1 EDT}
+ {3560738400 -18000 0 EST}
+ {3572233200 -14400 1 EDT}
+ {3592792800 -18000 0 EST}
+ {3603682800 -14400 1 EDT}
+ {3624242400 -18000 0 EST}
+ {3635132400 -14400 1 EDT}
+ {3655692000 -18000 0 EST}
+ {3666582000 -14400 1 EDT}
+ {3687141600 -18000 0 EST}
+ {3698031600 -14400 1 EDT}
+ {3718591200 -18000 0 EST}
+ {3730086000 -14400 1 EDT}
+ {3750645600 -18000 0 EST}
+ {3761535600 -14400 1 EDT}
+ {3782095200 -18000 0 EST}
+ {3792985200 -14400 1 EDT}
+ {3813544800 -18000 0 EST}
+ {3824434800 -14400 1 EDT}
+ {3844994400 -18000 0 EST}
+ {3855884400 -14400 1 EDT}
+ {3876444000 -18000 0 EST}
+ {3887334000 -14400 1 EDT}
+ {3907893600 -18000 0 EST}
+ {3919388400 -14400 1 EDT}
+ {3939948000 -18000 0 EST}
+ {3950838000 -14400 1 EDT}
+ {3971397600 -18000 0 EST}
+ {3982287600 -14400 1 EDT}
+ {4002847200 -18000 0 EST}
+ {4013737200 -14400 1 EDT}
+ {4034296800 -18000 0 EST}
+ {4045186800 -14400 1 EDT}
+ {4065746400 -18000 0 EST}
+ {4076636400 -14400 1 EDT}
+ {4097196000 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Tijuana b/library/tzdata/America/Tijuana
new file mode 100644
index 0000000..6118cde
--- /dev/null
+++ b/library/tzdata/America/Tijuana
@@ -0,0 +1,285 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Tijuana) {
+ {-9223372036854775808 -28084 0 LMT}
+ {-1514736000 -25200 0 MST}
+ {-1451667600 -28800 0 PST}
+ {-1343062800 -25200 0 MST}
+ {-1234803600 -28800 0 PST}
+ {-1222963200 -25200 1 PDT}
+ {-1207242000 -28800 0 PST}
+ {-873820800 -25200 1 PWT}
+ {-769395600 -25200 1 PPT}
+ {-761677200 -28800 0 PST}
+ {-686073600 -25200 1 PDT}
+ {-661539600 -28800 0 PST}
+ {-504892800 -28800 0 PST}
+ {-495036000 -25200 1 PDT}
+ {-481734000 -28800 0 PST}
+ {-463586400 -25200 1 PDT}
+ {-450284400 -28800 0 PST}
+ {-431532000 -25200 1 PDT}
+ {-418230000 -28800 0 PST}
+ {-400082400 -25200 1 PDT}
+ {-386780400 -28800 0 PST}
+ {-368632800 -25200 1 PDT}
+ {-355330800 -28800 0 PST}
+ {-337183200 -25200 1 PDT}
+ {-323881200 -28800 0 PST}
+ {-305733600 -25200 1 PDT}
+ {-292431600 -28800 0 PST}
+ {-283968000 -28800 0 PST}
+ {189331200 -28800 0 PST}
+ {199274400 -25200 1 PDT}
+ {215600400 -28800 0 PST}
+ {230724000 -25200 1 PDT}
+ {247050000 -28800 0 PST}
+ {262778400 -25200 1 PDT}
+ {278499600 -28800 0 PST}
+ {294228000 -25200 1 PDT}
+ {309949200 -28800 0 PST}
+ {325677600 -25200 1 PDT}
+ {341398800 -28800 0 PST}
+ {357127200 -25200 1 PDT}
+ {372848400 -28800 0 PST}
+ {388576800 -25200 1 PDT}
+ {404902800 -28800 0 PST}
+ {420026400 -25200 1 PDT}
+ {436352400 -28800 0 PST}
+ {452080800 -25200 1 PDT}
+ {467802000 -28800 0 PST}
+ {483530400 -25200 1 PDT}
+ {499251600 -28800 0 PST}
+ {514980000 -25200 1 PDT}
+ {530701200 -28800 0 PST}
+ {544615200 -25200 1 PDT}
+ {562150800 -28800 0 PST}
+ {576064800 -25200 1 PDT}
+ {594205200 -28800 0 PST}
+ {607514400 -25200 1 PDT}
+ {625654800 -28800 0 PST}
+ {638964000 -25200 1 PDT}
+ {657104400 -28800 0 PST}
+ {671018400 -25200 1 PDT}
+ {688554000 -28800 0 PST}
+ {702468000 -25200 1 PDT}
+ {720003600 -28800 0 PST}
+ {733917600 -25200 1 PDT}
+ {752058000 -28800 0 PST}
+ {765367200 -25200 1 PDT}
+ {783507600 -28800 0 PST}
+ {796816800 -25200 1 PDT}
+ {814957200 -28800 0 PST}
+ {820483200 -28800 0 PST}
+ {828871200 -25200 1 PDT}
+ {846406800 -28800 0 PST}
+ {860320800 -25200 1 PDT}
+ {877856400 -28800 0 PST}
+ {891770400 -25200 1 PDT}
+ {909306000 -28800 0 PST}
+ {923220000 -25200 1 PDT}
+ {941360400 -28800 0 PST}
+ {954669600 -25200 1 PDT}
+ {972810000 -28800 0 PST}
+ {978336000 -28800 0 PST}
+ {986119200 -25200 1 PDT}
+ {1004259600 -28800 0 PST}
+ {1014192000 -28800 0 PST}
+ {1018173600 -25200 1 PDT}
+ {1035709200 -28800 0 PST}
+ {1049623200 -25200 1 PDT}
+ {1067158800 -28800 0 PST}
+ {1081072800 -25200 1 PDT}
+ {1099213200 -28800 0 PST}
+ {1112522400 -25200 1 PDT}
+ {1130662800 -28800 0 PST}
+ {1143972000 -25200 1 PDT}
+ {1162112400 -28800 0 PST}
+ {1175421600 -25200 1 PDT}
+ {1193562000 -28800 0 PST}
+ {1207476000 -25200 1 PDT}
+ {1225011600 -28800 0 PST}
+ {1238925600 -25200 1 PDT}
+ {1256461200 -28800 0 PST}
+ {1262332800 -28800 0 PST}
+ {1268560800 -25200 1 PDT}
+ {1289120400 -28800 0 PST}
+ {1300010400 -25200 1 PDT}
+ {1320570000 -28800 0 PST}
+ {1331460000 -25200 1 PDT}
+ {1352019600 -28800 0 PST}
+ {1362909600 -25200 1 PDT}
+ {1383469200 -28800 0 PST}
+ {1394359200 -25200 1 PDT}
+ {1414918800 -28800 0 PST}
+ {1425808800 -25200 1 PDT}
+ {1446368400 -28800 0 PST}
+ {1457863200 -25200 1 PDT}
+ {1478422800 -28800 0 PST}
+ {1489312800 -25200 1 PDT}
+ {1509872400 -28800 0 PST}
+ {1520762400 -25200 1 PDT}
+ {1541322000 -28800 0 PST}
+ {1552212000 -25200 1 PDT}
+ {1572771600 -28800 0 PST}
+ {1583661600 -25200 1 PDT}
+ {1604221200 -28800 0 PST}
+ {1615716000 -25200 1 PDT}
+ {1636275600 -28800 0 PST}
+ {1647165600 -25200 1 PDT}
+ {1667725200 -28800 0 PST}
+ {1678615200 -25200 1 PDT}
+ {1699174800 -28800 0 PST}
+ {1710064800 -25200 1 PDT}
+ {1730624400 -28800 0 PST}
+ {1741514400 -25200 1 PDT}
+ {1762074000 -28800 0 PST}
+ {1772964000 -25200 1 PDT}
+ {1793523600 -28800 0 PST}
+ {1805018400 -25200 1 PDT}
+ {1825578000 -28800 0 PST}
+ {1836468000 -25200 1 PDT}
+ {1857027600 -28800 0 PST}
+ {1867917600 -25200 1 PDT}
+ {1888477200 -28800 0 PST}
+ {1899367200 -25200 1 PDT}
+ {1919926800 -28800 0 PST}
+ {1930816800 -25200 1 PDT}
+ {1951376400 -28800 0 PST}
+ {1962871200 -25200 1 PDT}
+ {1983430800 -28800 0 PST}
+ {1994320800 -25200 1 PDT}
+ {2014880400 -28800 0 PST}
+ {2025770400 -25200 1 PDT}
+ {2046330000 -28800 0 PST}
+ {2057220000 -25200 1 PDT}
+ {2077779600 -28800 0 PST}
+ {2088669600 -25200 1 PDT}
+ {2109229200 -28800 0 PST}
+ {2120119200 -25200 1 PDT}
+ {2140678800 -28800 0 PST}
+ {2152173600 -25200 1 PDT}
+ {2172733200 -28800 0 PST}
+ {2183623200 -25200 1 PDT}
+ {2204182800 -28800 0 PST}
+ {2215072800 -25200 1 PDT}
+ {2235632400 -28800 0 PST}
+ {2246522400 -25200 1 PDT}
+ {2267082000 -28800 0 PST}
+ {2277972000 -25200 1 PDT}
+ {2298531600 -28800 0 PST}
+ {2309421600 -25200 1 PDT}
+ {2329981200 -28800 0 PST}
+ {2341476000 -25200 1 PDT}
+ {2362035600 -28800 0 PST}
+ {2372925600 -25200 1 PDT}
+ {2393485200 -28800 0 PST}
+ {2404375200 -25200 1 PDT}
+ {2424934800 -28800 0 PST}
+ {2435824800 -25200 1 PDT}
+ {2456384400 -28800 0 PST}
+ {2467274400 -25200 1 PDT}
+ {2487834000 -28800 0 PST}
+ {2499328800 -25200 1 PDT}
+ {2519888400 -28800 0 PST}
+ {2530778400 -25200 1 PDT}
+ {2551338000 -28800 0 PST}
+ {2562228000 -25200 1 PDT}
+ {2582787600 -28800 0 PST}
+ {2593677600 -25200 1 PDT}
+ {2614237200 -28800 0 PST}
+ {2625127200 -25200 1 PDT}
+ {2645686800 -28800 0 PST}
+ {2656576800 -25200 1 PDT}
+ {2677136400 -28800 0 PST}
+ {2688631200 -25200 1 PDT}
+ {2709190800 -28800 0 PST}
+ {2720080800 -25200 1 PDT}
+ {2740640400 -28800 0 PST}
+ {2751530400 -25200 1 PDT}
+ {2772090000 -28800 0 PST}
+ {2782980000 -25200 1 PDT}
+ {2803539600 -28800 0 PST}
+ {2814429600 -25200 1 PDT}
+ {2834989200 -28800 0 PST}
+ {2846484000 -25200 1 PDT}
+ {2867043600 -28800 0 PST}
+ {2877933600 -25200 1 PDT}
+ {2898493200 -28800 0 PST}
+ {2909383200 -25200 1 PDT}
+ {2929942800 -28800 0 PST}
+ {2940832800 -25200 1 PDT}
+ {2961392400 -28800 0 PST}
+ {2972282400 -25200 1 PDT}
+ {2992842000 -28800 0 PST}
+ {3003732000 -25200 1 PDT}
+ {3024291600 -28800 0 PST}
+ {3035786400 -25200 1 PDT}
+ {3056346000 -28800 0 PST}
+ {3067236000 -25200 1 PDT}
+ {3087795600 -28800 0 PST}
+ {3098685600 -25200 1 PDT}
+ {3119245200 -28800 0 PST}
+ {3130135200 -25200 1 PDT}
+ {3150694800 -28800 0 PST}
+ {3161584800 -25200 1 PDT}
+ {3182144400 -28800 0 PST}
+ {3193034400 -25200 1 PDT}
+ {3213594000 -28800 0 PST}
+ {3225088800 -25200 1 PDT}
+ {3245648400 -28800 0 PST}
+ {3256538400 -25200 1 PDT}
+ {3277098000 -28800 0 PST}
+ {3287988000 -25200 1 PDT}
+ {3308547600 -28800 0 PST}
+ {3319437600 -25200 1 PDT}
+ {3339997200 -28800 0 PST}
+ {3350887200 -25200 1 PDT}
+ {3371446800 -28800 0 PST}
+ {3382941600 -25200 1 PDT}
+ {3403501200 -28800 0 PST}
+ {3414391200 -25200 1 PDT}
+ {3434950800 -28800 0 PST}
+ {3445840800 -25200 1 PDT}
+ {3466400400 -28800 0 PST}
+ {3477290400 -25200 1 PDT}
+ {3497850000 -28800 0 PST}
+ {3508740000 -25200 1 PDT}
+ {3529299600 -28800 0 PST}
+ {3540189600 -25200 1 PDT}
+ {3560749200 -28800 0 PST}
+ {3572244000 -25200 1 PDT}
+ {3592803600 -28800 0 PST}
+ {3603693600 -25200 1 PDT}
+ {3624253200 -28800 0 PST}
+ {3635143200 -25200 1 PDT}
+ {3655702800 -28800 0 PST}
+ {3666592800 -25200 1 PDT}
+ {3687152400 -28800 0 PST}
+ {3698042400 -25200 1 PDT}
+ {3718602000 -28800 0 PST}
+ {3730096800 -25200 1 PDT}
+ {3750656400 -28800 0 PST}
+ {3761546400 -25200 1 PDT}
+ {3782106000 -28800 0 PST}
+ {3792996000 -25200 1 PDT}
+ {3813555600 -28800 0 PST}
+ {3824445600 -25200 1 PDT}
+ {3845005200 -28800 0 PST}
+ {3855895200 -25200 1 PDT}
+ {3876454800 -28800 0 PST}
+ {3887344800 -25200 1 PDT}
+ {3907904400 -28800 0 PST}
+ {3919399200 -25200 1 PDT}
+ {3939958800 -28800 0 PST}
+ {3950848800 -25200 1 PDT}
+ {3971408400 -28800 0 PST}
+ {3982298400 -25200 1 PDT}
+ {4002858000 -28800 0 PST}
+ {4013748000 -25200 1 PDT}
+ {4034307600 -28800 0 PST}
+ {4045197600 -25200 1 PDT}
+ {4065757200 -28800 0 PST}
+ {4076647200 -25200 1 PDT}
+ {4097206800 -28800 0 PST}
+}
diff --git a/library/tzdata/America/Toronto b/library/tzdata/America/Toronto
new file mode 100644
index 0000000..e4fc91a
--- /dev/null
+++ b/library/tzdata/America/Toronto
@@ -0,0 +1,365 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Toronto) {
+ {-9223372036854775808 -19052 0 LMT}
+ {-2366736148 -18000 0 EST}
+ {-1632070800 -14400 1 EDT}
+ {-1614794400 -18000 0 EST}
+ {-1609441200 -18000 0 EST}
+ {-1601753400 -14400 1 EDT}
+ {-1583697600 -18000 0 EST}
+ {-1567357200 -14400 1 EDT}
+ {-1554667200 -18000 0 EST}
+ {-1534698000 -14400 1 EDT}
+ {-1524074400 -18000 0 EST}
+ {-1503248400 -14400 1 EDT}
+ {-1492365600 -18000 0 EST}
+ {-1471798800 -14400 1 EDT}
+ {-1460916000 -18000 0 EST}
+ {-1440954000 -14400 1 EDT}
+ {-1428861600 -18000 0 EST}
+ {-1409504400 -14400 1 EDT}
+ {-1397412000 -18000 0 EST}
+ {-1378054800 -14400 1 EDT}
+ {-1365962400 -18000 0 EST}
+ {-1346605200 -14400 1 EDT}
+ {-1333908000 -18000 0 EST}
+ {-1315155600 -14400 1 EDT}
+ {-1301853600 -18000 0 EST}
+ {-1283706000 -14400 1 EDT}
+ {-1270404000 -18000 0 EST}
+ {-1252256400 -14400 1 EDT}
+ {-1238954400 -18000 0 EST}
+ {-1220806800 -14400 1 EDT}
+ {-1207504800 -18000 0 EST}
+ {-1188752400 -14400 1 EDT}
+ {-1176055200 -18000 0 EST}
+ {-1157302800 -14400 1 EDT}
+ {-1144000800 -18000 0 EST}
+ {-1125853200 -14400 1 EDT}
+ {-1112551200 -18000 0 EST}
+ {-1094403600 -14400 1 EDT}
+ {-1081101600 -18000 0 EST}
+ {-1062954000 -14400 1 EDT}
+ {-1049652000 -18000 0 EST}
+ {-1031504400 -14400 1 EDT}
+ {-1018202400 -18000 0 EST}
+ {-1000054800 -14400 1 EDT}
+ {-986752800 -18000 0 EST}
+ {-968000400 -14400 1 EDT}
+ {-955303200 -18000 0 EST}
+ {-936550800 -14400 1 EDT}
+ {-880218000 -14400 0 EWT}
+ {-769395600 -14400 1 EPT}
+ {-765396000 -18000 0 EST}
+ {-757364400 -18000 0 EST}
+ {-747248400 -14400 1 EDT}
+ {-733946400 -18000 0 EST}
+ {-715806000 -14400 1 EDT}
+ {-702504000 -18000 0 EST}
+ {-684356400 -14400 1 EDT}
+ {-671054400 -18000 0 EST}
+ {-652906800 -14400 1 EDT}
+ {-634161600 -18000 0 EST}
+ {-620845200 -14400 1 EDT}
+ {-602704800 -18000 0 EST}
+ {-589395600 -14400 1 EDT}
+ {-576093600 -18000 0 EST}
+ {-557946000 -14400 1 EDT}
+ {-544644000 -18000 0 EST}
+ {-526496400 -14400 1 EDT}
+ {-513194400 -18000 0 EST}
+ {-495046800 -14400 1 EDT}
+ {-481744800 -18000 0 EST}
+ {-463597200 -14400 1 EDT}
+ {-450295200 -18000 0 EST}
+ {-431542800 -14400 1 EDT}
+ {-418240800 -18000 0 EST}
+ {-400093200 -14400 1 EDT}
+ {-384372000 -18000 0 EST}
+ {-368643600 -14400 1 EDT}
+ {-352922400 -18000 0 EST}
+ {-337194000 -14400 1 EDT}
+ {-321472800 -18000 0 EST}
+ {-305744400 -14400 1 EDT}
+ {-289418400 -18000 0 EST}
+ {-273690000 -14400 1 EDT}
+ {-257968800 -18000 0 EST}
+ {-242240400 -14400 1 EDT}
+ {-226519200 -18000 0 EST}
+ {-210790800 -14400 1 EDT}
+ {-195069600 -18000 0 EST}
+ {-179341200 -14400 1 EDT}
+ {-163620000 -18000 0 EST}
+ {-147891600 -14400 1 EDT}
+ {-131565600 -18000 0 EST}
+ {-116442000 -14400 1 EDT}
+ {-100116000 -18000 0 EST}
+ {-84387600 -14400 1 EDT}
+ {-68666400 -18000 0 EST}
+ {-52938000 -14400 1 EDT}
+ {-37216800 -18000 0 EST}
+ {-21488400 -14400 1 EDT}
+ {-5767200 -18000 0 EST}
+ {9961200 -14400 1 EDT}
+ {25682400 -18000 0 EST}
+ {41410800 -14400 1 EDT}
+ {57736800 -18000 0 EST}
+ {73465200 -14400 1 EDT}
+ {89186400 -18000 0 EST}
+ {104914800 -14400 1 EDT}
+ {120636000 -18000 0 EST}
+ {126248400 -18000 0 EST}
+ {136364400 -14400 1 EDT}
+ {152085600 -18000 0 EST}
+ {167814000 -14400 1 EDT}
+ {183535200 -18000 0 EST}
+ {199263600 -14400 1 EDT}
+ {215589600 -18000 0 EST}
+ {230713200 -14400 1 EDT}
+ {247039200 -18000 0 EST}
+ {262767600 -14400 1 EDT}
+ {278488800 -18000 0 EST}
+ {294217200 -14400 1 EDT}
+ {309938400 -18000 0 EST}
+ {325666800 -14400 1 EDT}
+ {341388000 -18000 0 EST}
+ {357116400 -14400 1 EDT}
+ {372837600 -18000 0 EST}
+ {388566000 -14400 1 EDT}
+ {404892000 -18000 0 EST}
+ {420015600 -14400 1 EDT}
+ {436341600 -18000 0 EST}
+ {452070000 -14400 1 EDT}
+ {467791200 -18000 0 EST}
+ {483519600 -14400 1 EDT}
+ {499240800 -18000 0 EST}
+ {514969200 -14400 1 EDT}
+ {530690400 -18000 0 EST}
+ {544604400 -14400 1 EDT}
+ {562140000 -18000 0 EST}
+ {576054000 -14400 1 EDT}
+ {594194400 -18000 0 EST}
+ {607503600 -14400 1 EDT}
+ {625644000 -18000 0 EST}
+ {638953200 -14400 1 EDT}
+ {657093600 -18000 0 EST}
+ {671007600 -14400 1 EDT}
+ {688543200 -18000 0 EST}
+ {702457200 -14400 1 EDT}
+ {719992800 -18000 0 EST}
+ {733906800 -14400 1 EDT}
+ {752047200 -18000 0 EST}
+ {765356400 -14400 1 EDT}
+ {783496800 -18000 0 EST}
+ {796806000 -14400 1 EDT}
+ {814946400 -18000 0 EST}
+ {828860400 -14400 1 EDT}
+ {846396000 -18000 0 EST}
+ {860310000 -14400 1 EDT}
+ {877845600 -18000 0 EST}
+ {891759600 -14400 1 EDT}
+ {909295200 -18000 0 EST}
+ {923209200 -14400 1 EDT}
+ {941349600 -18000 0 EST}
+ {954658800 -14400 1 EDT}
+ {972799200 -18000 0 EST}
+ {986108400 -14400 1 EDT}
+ {1004248800 -18000 0 EST}
+ {1018162800 -14400 1 EDT}
+ {1035698400 -18000 0 EST}
+ {1049612400 -14400 1 EDT}
+ {1067148000 -18000 0 EST}
+ {1081062000 -14400 1 EDT}
+ {1099202400 -18000 0 EST}
+ {1112511600 -14400 1 EDT}
+ {1130652000 -18000 0 EST}
+ {1143961200 -14400 1 EDT}
+ {1162101600 -18000 0 EST}
+ {1173596400 -14400 1 EDT}
+ {1194156000 -18000 0 EST}
+ {1205046000 -14400 1 EDT}
+ {1225605600 -18000 0 EST}
+ {1236495600 -14400 1 EDT}
+ {1257055200 -18000 0 EST}
+ {1268550000 -14400 1 EDT}
+ {1289109600 -18000 0 EST}
+ {1299999600 -14400 1 EDT}
+ {1320559200 -18000 0 EST}
+ {1331449200 -14400 1 EDT}
+ {1352008800 -18000 0 EST}
+ {1362898800 -14400 1 EDT}
+ {1383458400 -18000 0 EST}
+ {1394348400 -14400 1 EDT}
+ {1414908000 -18000 0 EST}
+ {1425798000 -14400 1 EDT}
+ {1446357600 -18000 0 EST}
+ {1457852400 -14400 1 EDT}
+ {1478412000 -18000 0 EST}
+ {1489302000 -14400 1 EDT}
+ {1509861600 -18000 0 EST}
+ {1520751600 -14400 1 EDT}
+ {1541311200 -18000 0 EST}
+ {1552201200 -14400 1 EDT}
+ {1572760800 -18000 0 EST}
+ {1583650800 -14400 1 EDT}
+ {1604210400 -18000 0 EST}
+ {1615705200 -14400 1 EDT}
+ {1636264800 -18000 0 EST}
+ {1647154800 -14400 1 EDT}
+ {1667714400 -18000 0 EST}
+ {1678604400 -14400 1 EDT}
+ {1699164000 -18000 0 EST}
+ {1710054000 -14400 1 EDT}
+ {1730613600 -18000 0 EST}
+ {1741503600 -14400 1 EDT}
+ {1762063200 -18000 0 EST}
+ {1772953200 -14400 1 EDT}
+ {1793512800 -18000 0 EST}
+ {1805007600 -14400 1 EDT}
+ {1825567200 -18000 0 EST}
+ {1836457200 -14400 1 EDT}
+ {1857016800 -18000 0 EST}
+ {1867906800 -14400 1 EDT}
+ {1888466400 -18000 0 EST}
+ {1899356400 -14400 1 EDT}
+ {1919916000 -18000 0 EST}
+ {1930806000 -14400 1 EDT}
+ {1951365600 -18000 0 EST}
+ {1962860400 -14400 1 EDT}
+ {1983420000 -18000 0 EST}
+ {1994310000 -14400 1 EDT}
+ {2014869600 -18000 0 EST}
+ {2025759600 -14400 1 EDT}
+ {2046319200 -18000 0 EST}
+ {2057209200 -14400 1 EDT}
+ {2077768800 -18000 0 EST}
+ {2088658800 -14400 1 EDT}
+ {2109218400 -18000 0 EST}
+ {2120108400 -14400 1 EDT}
+ {2140668000 -18000 0 EST}
+ {2152162800 -14400 1 EDT}
+ {2172722400 -18000 0 EST}
+ {2183612400 -14400 1 EDT}
+ {2204172000 -18000 0 EST}
+ {2215062000 -14400 1 EDT}
+ {2235621600 -18000 0 EST}
+ {2246511600 -14400 1 EDT}
+ {2267071200 -18000 0 EST}
+ {2277961200 -14400 1 EDT}
+ {2298520800 -18000 0 EST}
+ {2309410800 -14400 1 EDT}
+ {2329970400 -18000 0 EST}
+ {2341465200 -14400 1 EDT}
+ {2362024800 -18000 0 EST}
+ {2372914800 -14400 1 EDT}
+ {2393474400 -18000 0 EST}
+ {2404364400 -14400 1 EDT}
+ {2424924000 -18000 0 EST}
+ {2435814000 -14400 1 EDT}
+ {2456373600 -18000 0 EST}
+ {2467263600 -14400 1 EDT}
+ {2487823200 -18000 0 EST}
+ {2499318000 -14400 1 EDT}
+ {2519877600 -18000 0 EST}
+ {2530767600 -14400 1 EDT}
+ {2551327200 -18000 0 EST}
+ {2562217200 -14400 1 EDT}
+ {2582776800 -18000 0 EST}
+ {2593666800 -14400 1 EDT}
+ {2614226400 -18000 0 EST}
+ {2625116400 -14400 1 EDT}
+ {2645676000 -18000 0 EST}
+ {2656566000 -14400 1 EDT}
+ {2677125600 -18000 0 EST}
+ {2688620400 -14400 1 EDT}
+ {2709180000 -18000 0 EST}
+ {2720070000 -14400 1 EDT}
+ {2740629600 -18000 0 EST}
+ {2751519600 -14400 1 EDT}
+ {2772079200 -18000 0 EST}
+ {2782969200 -14400 1 EDT}
+ {2803528800 -18000 0 EST}
+ {2814418800 -14400 1 EDT}
+ {2834978400 -18000 0 EST}
+ {2846473200 -14400 1 EDT}
+ {2867032800 -18000 0 EST}
+ {2877922800 -14400 1 EDT}
+ {2898482400 -18000 0 EST}
+ {2909372400 -14400 1 EDT}
+ {2929932000 -18000 0 EST}
+ {2940822000 -14400 1 EDT}
+ {2961381600 -18000 0 EST}
+ {2972271600 -14400 1 EDT}
+ {2992831200 -18000 0 EST}
+ {3003721200 -14400 1 EDT}
+ {3024280800 -18000 0 EST}
+ {3035775600 -14400 1 EDT}
+ {3056335200 -18000 0 EST}
+ {3067225200 -14400 1 EDT}
+ {3087784800 -18000 0 EST}
+ {3098674800 -14400 1 EDT}
+ {3119234400 -18000 0 EST}
+ {3130124400 -14400 1 EDT}
+ {3150684000 -18000 0 EST}
+ {3161574000 -14400 1 EDT}
+ {3182133600 -18000 0 EST}
+ {3193023600 -14400 1 EDT}
+ {3213583200 -18000 0 EST}
+ {3225078000 -14400 1 EDT}
+ {3245637600 -18000 0 EST}
+ {3256527600 -14400 1 EDT}
+ {3277087200 -18000 0 EST}
+ {3287977200 -14400 1 EDT}
+ {3308536800 -18000 0 EST}
+ {3319426800 -14400 1 EDT}
+ {3339986400 -18000 0 EST}
+ {3350876400 -14400 1 EDT}
+ {3371436000 -18000 0 EST}
+ {3382930800 -14400 1 EDT}
+ {3403490400 -18000 0 EST}
+ {3414380400 -14400 1 EDT}
+ {3434940000 -18000 0 EST}
+ {3445830000 -14400 1 EDT}
+ {3466389600 -18000 0 EST}
+ {3477279600 -14400 1 EDT}
+ {3497839200 -18000 0 EST}
+ {3508729200 -14400 1 EDT}
+ {3529288800 -18000 0 EST}
+ {3540178800 -14400 1 EDT}
+ {3560738400 -18000 0 EST}
+ {3572233200 -14400 1 EDT}
+ {3592792800 -18000 0 EST}
+ {3603682800 -14400 1 EDT}
+ {3624242400 -18000 0 EST}
+ {3635132400 -14400 1 EDT}
+ {3655692000 -18000 0 EST}
+ {3666582000 -14400 1 EDT}
+ {3687141600 -18000 0 EST}
+ {3698031600 -14400 1 EDT}
+ {3718591200 -18000 0 EST}
+ {3730086000 -14400 1 EDT}
+ {3750645600 -18000 0 EST}
+ {3761535600 -14400 1 EDT}
+ {3782095200 -18000 0 EST}
+ {3792985200 -14400 1 EDT}
+ {3813544800 -18000 0 EST}
+ {3824434800 -14400 1 EDT}
+ {3844994400 -18000 0 EST}
+ {3855884400 -14400 1 EDT}
+ {3876444000 -18000 0 EST}
+ {3887334000 -14400 1 EDT}
+ {3907893600 -18000 0 EST}
+ {3919388400 -14400 1 EDT}
+ {3939948000 -18000 0 EST}
+ {3950838000 -14400 1 EDT}
+ {3971397600 -18000 0 EST}
+ {3982287600 -14400 1 EDT}
+ {4002847200 -18000 0 EST}
+ {4013737200 -14400 1 EDT}
+ {4034296800 -18000 0 EST}
+ {4045186800 -14400 1 EDT}
+ {4065746400 -18000 0 EST}
+ {4076636400 -14400 1 EDT}
+ {4097196000 -18000 0 EST}
+}
diff --git a/library/tzdata/America/Tortola b/library/tzdata/America/Tortola
new file mode 100644
index 0000000..bf7f1fc
--- /dev/null
+++ b/library/tzdata/America/Tortola
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Tortola) {
+ {-9223372036854775808 -15508 0 LMT}
+ {-1846266092 -14400 0 AST}
+}
diff --git a/library/tzdata/America/Vancouver b/library/tzdata/America/Vancouver
new file mode 100644
index 0000000..b2e0415
--- /dev/null
+++ b/library/tzdata/America/Vancouver
@@ -0,0 +1,320 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Vancouver) {
+ {-9223372036854775808 -29548 0 LMT}
+ {-2713880852 -28800 0 PST}
+ {-1632060000 -25200 1 PDT}
+ {-1614783600 -28800 0 PST}
+ {-880207200 -25200 1 PWT}
+ {-769395600 -25200 1 PPT}
+ {-765385200 -28800 0 PST}
+ {-747237600 -25200 1 PDT}
+ {-732726000 -28800 0 PST}
+ {-715788000 -25200 1 PDT}
+ {-702486000 -28800 0 PST}
+ {-684338400 -25200 1 PDT}
+ {-671036400 -28800 0 PST}
+ {-652888800 -25200 1 PDT}
+ {-639586800 -28800 0 PST}
+ {-620834400 -25200 1 PDT}
+ {-608137200 -28800 0 PST}
+ {-589384800 -25200 1 PDT}
+ {-576082800 -28800 0 PST}
+ {-557935200 -25200 1 PDT}
+ {-544633200 -28800 0 PST}
+ {-526485600 -25200 1 PDT}
+ {-513183600 -28800 0 PST}
+ {-495036000 -25200 1 PDT}
+ {-481734000 -28800 0 PST}
+ {-463586400 -25200 1 PDT}
+ {-450284400 -28800 0 PST}
+ {-431532000 -25200 1 PDT}
+ {-418230000 -28800 0 PST}
+ {-400082400 -25200 1 PDT}
+ {-386780400 -28800 0 PST}
+ {-368632800 -25200 1 PDT}
+ {-355330800 -28800 0 PST}
+ {-337183200 -25200 1 PDT}
+ {-323881200 -28800 0 PST}
+ {-305733600 -25200 1 PDT}
+ {-292431600 -28800 0 PST}
+ {-273679200 -25200 1 PDT}
+ {-260982000 -28800 0 PST}
+ {-242229600 -25200 1 PDT}
+ {-226508400 -28800 0 PST}
+ {-210780000 -25200 1 PDT}
+ {-195058800 -28800 0 PST}
+ {-179330400 -25200 1 PDT}
+ {-163609200 -28800 0 PST}
+ {-147880800 -25200 1 PDT}
+ {-131554800 -28800 0 PST}
+ {-116431200 -25200 1 PDT}
+ {-100105200 -28800 0 PST}
+ {-84376800 -25200 1 PDT}
+ {-68655600 -28800 0 PST}
+ {-52927200 -25200 1 PDT}
+ {-37206000 -28800 0 PST}
+ {-21477600 -25200 1 PDT}
+ {-5756400 -28800 0 PST}
+ {9972000 -25200 1 PDT}
+ {25693200 -28800 0 PST}
+ {41421600 -25200 1 PDT}
+ {57747600 -28800 0 PST}
+ {73476000 -25200 1 PDT}
+ {89197200 -28800 0 PST}
+ {104925600 -25200 1 PDT}
+ {120646800 -28800 0 PST}
+ {136375200 -25200 1 PDT}
+ {152096400 -28800 0 PST}
+ {167824800 -25200 1 PDT}
+ {183546000 -28800 0 PST}
+ {199274400 -25200 1 PDT}
+ {215600400 -28800 0 PST}
+ {230724000 -25200 1 PDT}
+ {247050000 -28800 0 PST}
+ {262778400 -25200 1 PDT}
+ {278499600 -28800 0 PST}
+ {294228000 -25200 1 PDT}
+ {309949200 -28800 0 PST}
+ {325677600 -25200 1 PDT}
+ {341398800 -28800 0 PST}
+ {357127200 -25200 1 PDT}
+ {372848400 -28800 0 PST}
+ {388576800 -25200 1 PDT}
+ {404902800 -28800 0 PST}
+ {420026400 -25200 1 PDT}
+ {436352400 -28800 0 PST}
+ {452080800 -25200 1 PDT}
+ {467802000 -28800 0 PST}
+ {483530400 -25200 1 PDT}
+ {499251600 -28800 0 PST}
+ {514980000 -25200 1 PDT}
+ {530701200 -28800 0 PST}
+ {536486400 -28800 0 PST}
+ {544615200 -25200 1 PDT}
+ {562150800 -28800 0 PST}
+ {576064800 -25200 1 PDT}
+ {594205200 -28800 0 PST}
+ {607514400 -25200 1 PDT}
+ {625654800 -28800 0 PST}
+ {638964000 -25200 1 PDT}
+ {657104400 -28800 0 PST}
+ {671018400 -25200 1 PDT}
+ {688554000 -28800 0 PST}
+ {702468000 -25200 1 PDT}
+ {720003600 -28800 0 PST}
+ {733917600 -25200 1 PDT}
+ {752058000 -28800 0 PST}
+ {765367200 -25200 1 PDT}
+ {783507600 -28800 0 PST}
+ {796816800 -25200 1 PDT}
+ {814957200 -28800 0 PST}
+ {828871200 -25200 1 PDT}
+ {846406800 -28800 0 PST}
+ {860320800 -25200 1 PDT}
+ {877856400 -28800 0 PST}
+ {891770400 -25200 1 PDT}
+ {909306000 -28800 0 PST}
+ {923220000 -25200 1 PDT}
+ {941360400 -28800 0 PST}
+ {954669600 -25200 1 PDT}
+ {972810000 -28800 0 PST}
+ {986119200 -25200 1 PDT}
+ {1004259600 -28800 0 PST}
+ {1018173600 -25200 1 PDT}
+ {1035709200 -28800 0 PST}
+ {1049623200 -25200 1 PDT}
+ {1067158800 -28800 0 PST}
+ {1081072800 -25200 1 PDT}
+ {1099213200 -28800 0 PST}
+ {1112522400 -25200 1 PDT}
+ {1130662800 -28800 0 PST}
+ {1143972000 -25200 1 PDT}
+ {1162112400 -28800 0 PST}
+ {1173607200 -25200 1 PDT}
+ {1194166800 -28800 0 PST}
+ {1205056800 -25200 1 PDT}
+ {1225616400 -28800 0 PST}
+ {1236506400 -25200 1 PDT}
+ {1257066000 -28800 0 PST}
+ {1268560800 -25200 1 PDT}
+ {1289120400 -28800 0 PST}
+ {1300010400 -25200 1 PDT}
+ {1320570000 -28800 0 PST}
+ {1331460000 -25200 1 PDT}
+ {1352019600 -28800 0 PST}
+ {1362909600 -25200 1 PDT}
+ {1383469200 -28800 0 PST}
+ {1394359200 -25200 1 PDT}
+ {1414918800 -28800 0 PST}
+ {1425808800 -25200 1 PDT}
+ {1446368400 -28800 0 PST}
+ {1457863200 -25200 1 PDT}
+ {1478422800 -28800 0 PST}
+ {1489312800 -25200 1 PDT}
+ {1509872400 -28800 0 PST}
+ {1520762400 -25200 1 PDT}
+ {1541322000 -28800 0 PST}
+ {1552212000 -25200 1 PDT}
+ {1572771600 -28800 0 PST}
+ {1583661600 -25200 1 PDT}
+ {1604221200 -28800 0 PST}
+ {1615716000 -25200 1 PDT}
+ {1636275600 -28800 0 PST}
+ {1647165600 -25200 1 PDT}
+ {1667725200 -28800 0 PST}
+ {1678615200 -25200 1 PDT}
+ {1699174800 -28800 0 PST}
+ {1710064800 -25200 1 PDT}
+ {1730624400 -28800 0 PST}
+ {1741514400 -25200 1 PDT}
+ {1762074000 -28800 0 PST}
+ {1772964000 -25200 1 PDT}
+ {1793523600 -28800 0 PST}
+ {1805018400 -25200 1 PDT}
+ {1825578000 -28800 0 PST}
+ {1836468000 -25200 1 PDT}
+ {1857027600 -28800 0 PST}
+ {1867917600 -25200 1 PDT}
+ {1888477200 -28800 0 PST}
+ {1899367200 -25200 1 PDT}
+ {1919926800 -28800 0 PST}
+ {1930816800 -25200 1 PDT}
+ {1951376400 -28800 0 PST}
+ {1962871200 -25200 1 PDT}
+ {1983430800 -28800 0 PST}
+ {1994320800 -25200 1 PDT}
+ {2014880400 -28800 0 PST}
+ {2025770400 -25200 1 PDT}
+ {2046330000 -28800 0 PST}
+ {2057220000 -25200 1 PDT}
+ {2077779600 -28800 0 PST}
+ {2088669600 -25200 1 PDT}
+ {2109229200 -28800 0 PST}
+ {2120119200 -25200 1 PDT}
+ {2140678800 -28800 0 PST}
+ {2152173600 -25200 1 PDT}
+ {2172733200 -28800 0 PST}
+ {2183623200 -25200 1 PDT}
+ {2204182800 -28800 0 PST}
+ {2215072800 -25200 1 PDT}
+ {2235632400 -28800 0 PST}
+ {2246522400 -25200 1 PDT}
+ {2267082000 -28800 0 PST}
+ {2277972000 -25200 1 PDT}
+ {2298531600 -28800 0 PST}
+ {2309421600 -25200 1 PDT}
+ {2329981200 -28800 0 PST}
+ {2341476000 -25200 1 PDT}
+ {2362035600 -28800 0 PST}
+ {2372925600 -25200 1 PDT}
+ {2393485200 -28800 0 PST}
+ {2404375200 -25200 1 PDT}
+ {2424934800 -28800 0 PST}
+ {2435824800 -25200 1 PDT}
+ {2456384400 -28800 0 PST}
+ {2467274400 -25200 1 PDT}
+ {2487834000 -28800 0 PST}
+ {2499328800 -25200 1 PDT}
+ {2519888400 -28800 0 PST}
+ {2530778400 -25200 1 PDT}
+ {2551338000 -28800 0 PST}
+ {2562228000 -25200 1 PDT}
+ {2582787600 -28800 0 PST}
+ {2593677600 -25200 1 PDT}
+ {2614237200 -28800 0 PST}
+ {2625127200 -25200 1 PDT}
+ {2645686800 -28800 0 PST}
+ {2656576800 -25200 1 PDT}
+ {2677136400 -28800 0 PST}
+ {2688631200 -25200 1 PDT}
+ {2709190800 -28800 0 PST}
+ {2720080800 -25200 1 PDT}
+ {2740640400 -28800 0 PST}
+ {2751530400 -25200 1 PDT}
+ {2772090000 -28800 0 PST}
+ {2782980000 -25200 1 PDT}
+ {2803539600 -28800 0 PST}
+ {2814429600 -25200 1 PDT}
+ {2834989200 -28800 0 PST}
+ {2846484000 -25200 1 PDT}
+ {2867043600 -28800 0 PST}
+ {2877933600 -25200 1 PDT}
+ {2898493200 -28800 0 PST}
+ {2909383200 -25200 1 PDT}
+ {2929942800 -28800 0 PST}
+ {2940832800 -25200 1 PDT}
+ {2961392400 -28800 0 PST}
+ {2972282400 -25200 1 PDT}
+ {2992842000 -28800 0 PST}
+ {3003732000 -25200 1 PDT}
+ {3024291600 -28800 0 PST}
+ {3035786400 -25200 1 PDT}
+ {3056346000 -28800 0 PST}
+ {3067236000 -25200 1 PDT}
+ {3087795600 -28800 0 PST}
+ {3098685600 -25200 1 PDT}
+ {3119245200 -28800 0 PST}
+ {3130135200 -25200 1 PDT}
+ {3150694800 -28800 0 PST}
+ {3161584800 -25200 1 PDT}
+ {3182144400 -28800 0 PST}
+ {3193034400 -25200 1 PDT}
+ {3213594000 -28800 0 PST}
+ {3225088800 -25200 1 PDT}
+ {3245648400 -28800 0 PST}
+ {3256538400 -25200 1 PDT}
+ {3277098000 -28800 0 PST}
+ {3287988000 -25200 1 PDT}
+ {3308547600 -28800 0 PST}
+ {3319437600 -25200 1 PDT}
+ {3339997200 -28800 0 PST}
+ {3350887200 -25200 1 PDT}
+ {3371446800 -28800 0 PST}
+ {3382941600 -25200 1 PDT}
+ {3403501200 -28800 0 PST}
+ {3414391200 -25200 1 PDT}
+ {3434950800 -28800 0 PST}
+ {3445840800 -25200 1 PDT}
+ {3466400400 -28800 0 PST}
+ {3477290400 -25200 1 PDT}
+ {3497850000 -28800 0 PST}
+ {3508740000 -25200 1 PDT}
+ {3529299600 -28800 0 PST}
+ {3540189600 -25200 1 PDT}
+ {3560749200 -28800 0 PST}
+ {3572244000 -25200 1 PDT}
+ {3592803600 -28800 0 PST}
+ {3603693600 -25200 1 PDT}
+ {3624253200 -28800 0 PST}
+ {3635143200 -25200 1 PDT}
+ {3655702800 -28800 0 PST}
+ {3666592800 -25200 1 PDT}
+ {3687152400 -28800 0 PST}
+ {3698042400 -25200 1 PDT}
+ {3718602000 -28800 0 PST}
+ {3730096800 -25200 1 PDT}
+ {3750656400 -28800 0 PST}
+ {3761546400 -25200 1 PDT}
+ {3782106000 -28800 0 PST}
+ {3792996000 -25200 1 PDT}
+ {3813555600 -28800 0 PST}
+ {3824445600 -25200 1 PDT}
+ {3845005200 -28800 0 PST}
+ {3855895200 -25200 1 PDT}
+ {3876454800 -28800 0 PST}
+ {3887344800 -25200 1 PDT}
+ {3907904400 -28800 0 PST}
+ {3919399200 -25200 1 PDT}
+ {3939958800 -28800 0 PST}
+ {3950848800 -25200 1 PDT}
+ {3971408400 -28800 0 PST}
+ {3982298400 -25200 1 PDT}
+ {4002858000 -28800 0 PST}
+ {4013748000 -25200 1 PDT}
+ {4034307600 -28800 0 PST}
+ {4045197600 -25200 1 PDT}
+ {4065757200 -28800 0 PST}
+ {4076647200 -25200 1 PDT}
+ {4097206800 -28800 0 PST}
+}
diff --git a/library/tzdata/America/Virgin b/library/tzdata/America/Virgin
new file mode 100644
index 0000000..390d7c2
--- /dev/null
+++ b/library/tzdata/America/Virgin
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/St_Thomas)]} {
+ LoadTimeZoneFile America/St_Thomas
+}
+set TZData(:America/Virgin) $TZData(:America/St_Thomas)
diff --git a/library/tzdata/America/Whitehorse b/library/tzdata/America/Whitehorse
new file mode 100644
index 0000000..1d61093
--- /dev/null
+++ b/library/tzdata/America/Whitehorse
@@ -0,0 +1,256 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Whitehorse) {
+ {-9223372036854775808 -32412 0 LMT}
+ {-2188997988 -32400 0 YST}
+ {-1632056400 -28800 1 YDT}
+ {-1615125600 -32400 0 YST}
+ {-1596978000 -28800 1 YDT}
+ {-1583164800 -32400 0 YST}
+ {-880203600 -28800 1 YWT}
+ {-769395600 -28800 1 YPT}
+ {-765381600 -32400 0 YST}
+ {-147884400 -25200 1 YDDT}
+ {-131554800 -32400 0 YST}
+ {315561600 -28800 0 PST}
+ {325677600 -25200 1 PDT}
+ {341398800 -28800 0 PST}
+ {357127200 -25200 1 PDT}
+ {372848400 -28800 0 PST}
+ {388576800 -25200 1 PDT}
+ {404902800 -28800 0 PST}
+ {420026400 -25200 1 PDT}
+ {436352400 -28800 0 PST}
+ {452080800 -25200 1 PDT}
+ {467802000 -28800 0 PST}
+ {483530400 -25200 1 PDT}
+ {499251600 -28800 0 PST}
+ {514980000 -25200 1 PDT}
+ {530701200 -28800 0 PST}
+ {544615200 -25200 1 PDT}
+ {562150800 -28800 0 PST}
+ {576064800 -25200 1 PDT}
+ {594205200 -28800 0 PST}
+ {607514400 -25200 1 PDT}
+ {625654800 -28800 0 PST}
+ {638964000 -25200 1 PDT}
+ {657104400 -28800 0 PST}
+ {671018400 -25200 1 PDT}
+ {688554000 -28800 0 PST}
+ {702468000 -25200 1 PDT}
+ {720003600 -28800 0 PST}
+ {733917600 -25200 1 PDT}
+ {752058000 -28800 0 PST}
+ {765367200 -25200 1 PDT}
+ {783507600 -28800 0 PST}
+ {796816800 -25200 1 PDT}
+ {814957200 -28800 0 PST}
+ {828871200 -25200 1 PDT}
+ {846406800 -28800 0 PST}
+ {860320800 -25200 1 PDT}
+ {877856400 -28800 0 PST}
+ {891770400 -25200 1 PDT}
+ {909306000 -28800 0 PST}
+ {923220000 -25200 1 PDT}
+ {941360400 -28800 0 PST}
+ {954669600 -25200 1 PDT}
+ {972810000 -28800 0 PST}
+ {986119200 -25200 1 PDT}
+ {1004259600 -28800 0 PST}
+ {1018173600 -25200 1 PDT}
+ {1035709200 -28800 0 PST}
+ {1049623200 -25200 1 PDT}
+ {1067158800 -28800 0 PST}
+ {1081072800 -25200 1 PDT}
+ {1099213200 -28800 0 PST}
+ {1112522400 -25200 1 PDT}
+ {1130662800 -28800 0 PST}
+ {1143972000 -25200 1 PDT}
+ {1162112400 -28800 0 PST}
+ {1173607200 -25200 1 PDT}
+ {1194166800 -28800 0 PST}
+ {1205056800 -25200 1 PDT}
+ {1225616400 -28800 0 PST}
+ {1236506400 -25200 1 PDT}
+ {1257066000 -28800 0 PST}
+ {1268560800 -25200 1 PDT}
+ {1289120400 -28800 0 PST}
+ {1300010400 -25200 1 PDT}
+ {1320570000 -28800 0 PST}
+ {1331460000 -25200 1 PDT}
+ {1352019600 -28800 0 PST}
+ {1362909600 -25200 1 PDT}
+ {1383469200 -28800 0 PST}
+ {1394359200 -25200 1 PDT}
+ {1414918800 -28800 0 PST}
+ {1425808800 -25200 1 PDT}
+ {1446368400 -28800 0 PST}
+ {1457863200 -25200 1 PDT}
+ {1478422800 -28800 0 PST}
+ {1489312800 -25200 1 PDT}
+ {1509872400 -28800 0 PST}
+ {1520762400 -25200 1 PDT}
+ {1541322000 -28800 0 PST}
+ {1552212000 -25200 1 PDT}
+ {1572771600 -28800 0 PST}
+ {1583661600 -25200 1 PDT}
+ {1604221200 -28800 0 PST}
+ {1615716000 -25200 1 PDT}
+ {1636275600 -28800 0 PST}
+ {1647165600 -25200 1 PDT}
+ {1667725200 -28800 0 PST}
+ {1678615200 -25200 1 PDT}
+ {1699174800 -28800 0 PST}
+ {1710064800 -25200 1 PDT}
+ {1730624400 -28800 0 PST}
+ {1741514400 -25200 1 PDT}
+ {1762074000 -28800 0 PST}
+ {1772964000 -25200 1 PDT}
+ {1793523600 -28800 0 PST}
+ {1805018400 -25200 1 PDT}
+ {1825578000 -28800 0 PST}
+ {1836468000 -25200 1 PDT}
+ {1857027600 -28800 0 PST}
+ {1867917600 -25200 1 PDT}
+ {1888477200 -28800 0 PST}
+ {1899367200 -25200 1 PDT}
+ {1919926800 -28800 0 PST}
+ {1930816800 -25200 1 PDT}
+ {1951376400 -28800 0 PST}
+ {1962871200 -25200 1 PDT}
+ {1983430800 -28800 0 PST}
+ {1994320800 -25200 1 PDT}
+ {2014880400 -28800 0 PST}
+ {2025770400 -25200 1 PDT}
+ {2046330000 -28800 0 PST}
+ {2057220000 -25200 1 PDT}
+ {2077779600 -28800 0 PST}
+ {2088669600 -25200 1 PDT}
+ {2109229200 -28800 0 PST}
+ {2120119200 -25200 1 PDT}
+ {2140678800 -28800 0 PST}
+ {2152173600 -25200 1 PDT}
+ {2172733200 -28800 0 PST}
+ {2183623200 -25200 1 PDT}
+ {2204182800 -28800 0 PST}
+ {2215072800 -25200 1 PDT}
+ {2235632400 -28800 0 PST}
+ {2246522400 -25200 1 PDT}
+ {2267082000 -28800 0 PST}
+ {2277972000 -25200 1 PDT}
+ {2298531600 -28800 0 PST}
+ {2309421600 -25200 1 PDT}
+ {2329981200 -28800 0 PST}
+ {2341476000 -25200 1 PDT}
+ {2362035600 -28800 0 PST}
+ {2372925600 -25200 1 PDT}
+ {2393485200 -28800 0 PST}
+ {2404375200 -25200 1 PDT}
+ {2424934800 -28800 0 PST}
+ {2435824800 -25200 1 PDT}
+ {2456384400 -28800 0 PST}
+ {2467274400 -25200 1 PDT}
+ {2487834000 -28800 0 PST}
+ {2499328800 -25200 1 PDT}
+ {2519888400 -28800 0 PST}
+ {2530778400 -25200 1 PDT}
+ {2551338000 -28800 0 PST}
+ {2562228000 -25200 1 PDT}
+ {2582787600 -28800 0 PST}
+ {2593677600 -25200 1 PDT}
+ {2614237200 -28800 0 PST}
+ {2625127200 -25200 1 PDT}
+ {2645686800 -28800 0 PST}
+ {2656576800 -25200 1 PDT}
+ {2677136400 -28800 0 PST}
+ {2688631200 -25200 1 PDT}
+ {2709190800 -28800 0 PST}
+ {2720080800 -25200 1 PDT}
+ {2740640400 -28800 0 PST}
+ {2751530400 -25200 1 PDT}
+ {2772090000 -28800 0 PST}
+ {2782980000 -25200 1 PDT}
+ {2803539600 -28800 0 PST}
+ {2814429600 -25200 1 PDT}
+ {2834989200 -28800 0 PST}
+ {2846484000 -25200 1 PDT}
+ {2867043600 -28800 0 PST}
+ {2877933600 -25200 1 PDT}
+ {2898493200 -28800 0 PST}
+ {2909383200 -25200 1 PDT}
+ {2929942800 -28800 0 PST}
+ {2940832800 -25200 1 PDT}
+ {2961392400 -28800 0 PST}
+ {2972282400 -25200 1 PDT}
+ {2992842000 -28800 0 PST}
+ {3003732000 -25200 1 PDT}
+ {3024291600 -28800 0 PST}
+ {3035786400 -25200 1 PDT}
+ {3056346000 -28800 0 PST}
+ {3067236000 -25200 1 PDT}
+ {3087795600 -28800 0 PST}
+ {3098685600 -25200 1 PDT}
+ {3119245200 -28800 0 PST}
+ {3130135200 -25200 1 PDT}
+ {3150694800 -28800 0 PST}
+ {3161584800 -25200 1 PDT}
+ {3182144400 -28800 0 PST}
+ {3193034400 -25200 1 PDT}
+ {3213594000 -28800 0 PST}
+ {3225088800 -25200 1 PDT}
+ {3245648400 -28800 0 PST}
+ {3256538400 -25200 1 PDT}
+ {3277098000 -28800 0 PST}
+ {3287988000 -25200 1 PDT}
+ {3308547600 -28800 0 PST}
+ {3319437600 -25200 1 PDT}
+ {3339997200 -28800 0 PST}
+ {3350887200 -25200 1 PDT}
+ {3371446800 -28800 0 PST}
+ {3382941600 -25200 1 PDT}
+ {3403501200 -28800 0 PST}
+ {3414391200 -25200 1 PDT}
+ {3434950800 -28800 0 PST}
+ {3445840800 -25200 1 PDT}
+ {3466400400 -28800 0 PST}
+ {3477290400 -25200 1 PDT}
+ {3497850000 -28800 0 PST}
+ {3508740000 -25200 1 PDT}
+ {3529299600 -28800 0 PST}
+ {3540189600 -25200 1 PDT}
+ {3560749200 -28800 0 PST}
+ {3572244000 -25200 1 PDT}
+ {3592803600 -28800 0 PST}
+ {3603693600 -25200 1 PDT}
+ {3624253200 -28800 0 PST}
+ {3635143200 -25200 1 PDT}
+ {3655702800 -28800 0 PST}
+ {3666592800 -25200 1 PDT}
+ {3687152400 -28800 0 PST}
+ {3698042400 -25200 1 PDT}
+ {3718602000 -28800 0 PST}
+ {3730096800 -25200 1 PDT}
+ {3750656400 -28800 0 PST}
+ {3761546400 -25200 1 PDT}
+ {3782106000 -28800 0 PST}
+ {3792996000 -25200 1 PDT}
+ {3813555600 -28800 0 PST}
+ {3824445600 -25200 1 PDT}
+ {3845005200 -28800 0 PST}
+ {3855895200 -25200 1 PDT}
+ {3876454800 -28800 0 PST}
+ {3887344800 -25200 1 PDT}
+ {3907904400 -28800 0 PST}
+ {3919399200 -25200 1 PDT}
+ {3939958800 -28800 0 PST}
+ {3950848800 -25200 1 PDT}
+ {3971408400 -28800 0 PST}
+ {3982298400 -25200 1 PDT}
+ {4002858000 -28800 0 PST}
+ {4013748000 -25200 1 PDT}
+ {4034307600 -28800 0 PST}
+ {4045197600 -25200 1 PDT}
+ {4065757200 -28800 0 PST}
+ {4076647200 -25200 1 PDT}
+ {4097206800 -28800 0 PST}
+}
diff --git a/library/tzdata/America/Winnipeg b/library/tzdata/America/Winnipeg
new file mode 100644
index 0000000..7e6208a
--- /dev/null
+++ b/library/tzdata/America/Winnipeg
@@ -0,0 +1,316 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Winnipeg) {
+ {-9223372036854775808 -23316 0 LMT}
+ {-2602258284 -21600 0 CST}
+ {-1694368800 -18000 1 CDT}
+ {-1681671600 -21600 0 CST}
+ {-1632067200 -18000 1 CDT}
+ {-1614790800 -21600 0 CST}
+ {-1029686400 -18000 1 CDT}
+ {-1018198800 -21600 0 CST}
+ {-880214400 -18000 1 CWT}
+ {-769395600 -18000 1 CPT}
+ {-765392400 -21600 0 CST}
+ {-746035200 -18000 1 CDT}
+ {-732733200 -21600 0 CST}
+ {-715795200 -18000 1 CDT}
+ {-702493200 -21600 0 CST}
+ {-684345600 -18000 1 CDT}
+ {-671043600 -21600 0 CST}
+ {-652896000 -18000 1 CDT}
+ {-639594000 -21600 0 CST}
+ {-620755200 -18000 1 CDT}
+ {-607626000 -21600 0 CST}
+ {-589392000 -18000 1 CDT}
+ {-576090000 -21600 0 CST}
+ {-557942400 -18000 1 CDT}
+ {-544640400 -21600 0 CST}
+ {-526492800 -18000 1 CDT}
+ {-513190800 -21600 0 CST}
+ {-495043200 -18000 1 CDT}
+ {-481741200 -21600 0 CST}
+ {-463593600 -18000 1 CDT}
+ {-450291600 -21600 0 CST}
+ {-431539200 -18000 1 CDT}
+ {-418237200 -21600 0 CST}
+ {-400089600 -18000 1 CDT}
+ {-386787600 -21600 0 CST}
+ {-368640000 -18000 1 CDT}
+ {-355338000 -21600 0 CST}
+ {-337190400 -18000 1 CDT}
+ {-321469200 -21600 0 CST}
+ {-305740800 -18000 1 CDT}
+ {-292438800 -21600 0 CST}
+ {-210787200 -18000 1 CDT}
+ {-198090000 -21600 0 CST}
+ {-116438400 -18000 1 CDT}
+ {-100108800 -21600 0 CST}
+ {-84384000 -18000 1 CDT}
+ {-68659200 -21600 0 CST}
+ {-52934400 -18000 1 CDT}
+ {-37209600 -21600 0 CST}
+ {-21484800 -18000 1 CDT}
+ {-5760000 -21600 0 CST}
+ {9964800 -18000 1 CDT}
+ {25689600 -21600 0 CST}
+ {41414400 -18000 1 CDT}
+ {57744000 -21600 0 CST}
+ {73468800 -18000 1 CDT}
+ {89193600 -21600 0 CST}
+ {104918400 -18000 1 CDT}
+ {120643200 -21600 0 CST}
+ {136368000 -18000 1 CDT}
+ {152092800 -21600 0 CST}
+ {167817600 -18000 1 CDT}
+ {183542400 -21600 0 CST}
+ {199267200 -18000 1 CDT}
+ {215596800 -21600 0 CST}
+ {230716800 -18000 1 CDT}
+ {247046400 -21600 0 CST}
+ {262771200 -18000 1 CDT}
+ {278496000 -21600 0 CST}
+ {294220800 -18000 1 CDT}
+ {309945600 -21600 0 CST}
+ {325670400 -18000 1 CDT}
+ {341395200 -21600 0 CST}
+ {357120000 -18000 1 CDT}
+ {372844800 -21600 0 CST}
+ {388569600 -18000 1 CDT}
+ {404899200 -21600 0 CST}
+ {420019200 -18000 1 CDT}
+ {436348800 -21600 0 CST}
+ {452073600 -18000 1 CDT}
+ {467798400 -21600 0 CST}
+ {483523200 -18000 1 CDT}
+ {499248000 -21600 0 CST}
+ {514972800 -18000 1 CDT}
+ {530697600 -21600 0 CST}
+ {544608000 -18000 1 CDT}
+ {562147200 -21600 0 CST}
+ {576057600 -18000 1 CDT}
+ {594201600 -21600 0 CST}
+ {607507200 -18000 1 CDT}
+ {625651200 -21600 0 CST}
+ {638956800 -18000 1 CDT}
+ {657100800 -21600 0 CST}
+ {671011200 -18000 1 CDT}
+ {688550400 -21600 0 CST}
+ {702460800 -18000 1 CDT}
+ {720000000 -21600 0 CST}
+ {733910400 -18000 1 CDT}
+ {752054400 -21600 0 CST}
+ {765360000 -18000 1 CDT}
+ {783504000 -21600 0 CST}
+ {796809600 -18000 1 CDT}
+ {814953600 -21600 0 CST}
+ {828864000 -18000 1 CDT}
+ {846403200 -21600 0 CST}
+ {860313600 -18000 1 CDT}
+ {877852800 -21600 0 CST}
+ {891763200 -18000 1 CDT}
+ {909302400 -21600 0 CST}
+ {923212800 -18000 1 CDT}
+ {941356800 -21600 0 CST}
+ {954662400 -18000 1 CDT}
+ {972806400 -21600 0 CST}
+ {986112000 -18000 1 CDT}
+ {1004256000 -21600 0 CST}
+ {1018166400 -18000 1 CDT}
+ {1035705600 -21600 0 CST}
+ {1049616000 -18000 1 CDT}
+ {1067155200 -21600 0 CST}
+ {1081065600 -18000 1 CDT}
+ {1099209600 -21600 0 CST}
+ {1112515200 -18000 1 CDT}
+ {1130659200 -21600 0 CST}
+ {1136095200 -21600 0 CST}
+ {1143964800 -18000 1 CDT}
+ {1162105200 -21600 0 CST}
+ {1173600000 -18000 1 CDT}
+ {1194159600 -21600 0 CST}
+ {1205049600 -18000 1 CDT}
+ {1225609200 -21600 0 CST}
+ {1236499200 -18000 1 CDT}
+ {1257058800 -21600 0 CST}
+ {1268553600 -18000 1 CDT}
+ {1289113200 -21600 0 CST}
+ {1300003200 -18000 1 CDT}
+ {1320562800 -21600 0 CST}
+ {1331452800 -18000 1 CDT}
+ {1352012400 -21600 0 CST}
+ {1362902400 -18000 1 CDT}
+ {1383462000 -21600 0 CST}
+ {1394352000 -18000 1 CDT}
+ {1414911600 -21600 0 CST}
+ {1425801600 -18000 1 CDT}
+ {1446361200 -21600 0 CST}
+ {1457856000 -18000 1 CDT}
+ {1478415600 -21600 0 CST}
+ {1489305600 -18000 1 CDT}
+ {1509865200 -21600 0 CST}
+ {1520755200 -18000 1 CDT}
+ {1541314800 -21600 0 CST}
+ {1552204800 -18000 1 CDT}
+ {1572764400 -21600 0 CST}
+ {1583654400 -18000 1 CDT}
+ {1604214000 -21600 0 CST}
+ {1615708800 -18000 1 CDT}
+ {1636268400 -21600 0 CST}
+ {1647158400 -18000 1 CDT}
+ {1667718000 -21600 0 CST}
+ {1678608000 -18000 1 CDT}
+ {1699167600 -21600 0 CST}
+ {1710057600 -18000 1 CDT}
+ {1730617200 -21600 0 CST}
+ {1741507200 -18000 1 CDT}
+ {1762066800 -21600 0 CST}
+ {1772956800 -18000 1 CDT}
+ {1793516400 -21600 0 CST}
+ {1805011200 -18000 1 CDT}
+ {1825570800 -21600 0 CST}
+ {1836460800 -18000 1 CDT}
+ {1857020400 -21600 0 CST}
+ {1867910400 -18000 1 CDT}
+ {1888470000 -21600 0 CST}
+ {1899360000 -18000 1 CDT}
+ {1919919600 -21600 0 CST}
+ {1930809600 -18000 1 CDT}
+ {1951369200 -21600 0 CST}
+ {1962864000 -18000 1 CDT}
+ {1983423600 -21600 0 CST}
+ {1994313600 -18000 1 CDT}
+ {2014873200 -21600 0 CST}
+ {2025763200 -18000 1 CDT}
+ {2046322800 -21600 0 CST}
+ {2057212800 -18000 1 CDT}
+ {2077772400 -21600 0 CST}
+ {2088662400 -18000 1 CDT}
+ {2109222000 -21600 0 CST}
+ {2120112000 -18000 1 CDT}
+ {2140671600 -21600 0 CST}
+ {2152166400 -18000 1 CDT}
+ {2172726000 -21600 0 CST}
+ {2183616000 -18000 1 CDT}
+ {2204175600 -21600 0 CST}
+ {2215065600 -18000 1 CDT}
+ {2235625200 -21600 0 CST}
+ {2246515200 -18000 1 CDT}
+ {2267074800 -21600 0 CST}
+ {2277964800 -18000 1 CDT}
+ {2298524400 -21600 0 CST}
+ {2309414400 -18000 1 CDT}
+ {2329974000 -21600 0 CST}
+ {2341468800 -18000 1 CDT}
+ {2362028400 -21600 0 CST}
+ {2372918400 -18000 1 CDT}
+ {2393478000 -21600 0 CST}
+ {2404368000 -18000 1 CDT}
+ {2424927600 -21600 0 CST}
+ {2435817600 -18000 1 CDT}
+ {2456377200 -21600 0 CST}
+ {2467267200 -18000 1 CDT}
+ {2487826800 -21600 0 CST}
+ {2499321600 -18000 1 CDT}
+ {2519881200 -21600 0 CST}
+ {2530771200 -18000 1 CDT}
+ {2551330800 -21600 0 CST}
+ {2562220800 -18000 1 CDT}
+ {2582780400 -21600 0 CST}
+ {2593670400 -18000 1 CDT}
+ {2614230000 -21600 0 CST}
+ {2625120000 -18000 1 CDT}
+ {2645679600 -21600 0 CST}
+ {2656569600 -18000 1 CDT}
+ {2677129200 -21600 0 CST}
+ {2688624000 -18000 1 CDT}
+ {2709183600 -21600 0 CST}
+ {2720073600 -18000 1 CDT}
+ {2740633200 -21600 0 CST}
+ {2751523200 -18000 1 CDT}
+ {2772082800 -21600 0 CST}
+ {2782972800 -18000 1 CDT}
+ {2803532400 -21600 0 CST}
+ {2814422400 -18000 1 CDT}
+ {2834982000 -21600 0 CST}
+ {2846476800 -18000 1 CDT}
+ {2867036400 -21600 0 CST}
+ {2877926400 -18000 1 CDT}
+ {2898486000 -21600 0 CST}
+ {2909376000 -18000 1 CDT}
+ {2929935600 -21600 0 CST}
+ {2940825600 -18000 1 CDT}
+ {2961385200 -21600 0 CST}
+ {2972275200 -18000 1 CDT}
+ {2992834800 -21600 0 CST}
+ {3003724800 -18000 1 CDT}
+ {3024284400 -21600 0 CST}
+ {3035779200 -18000 1 CDT}
+ {3056338800 -21600 0 CST}
+ {3067228800 -18000 1 CDT}
+ {3087788400 -21600 0 CST}
+ {3098678400 -18000 1 CDT}
+ {3119238000 -21600 0 CST}
+ {3130128000 -18000 1 CDT}
+ {3150687600 -21600 0 CST}
+ {3161577600 -18000 1 CDT}
+ {3182137200 -21600 0 CST}
+ {3193027200 -18000 1 CDT}
+ {3213586800 -21600 0 CST}
+ {3225081600 -18000 1 CDT}
+ {3245641200 -21600 0 CST}
+ {3256531200 -18000 1 CDT}
+ {3277090800 -21600 0 CST}
+ {3287980800 -18000 1 CDT}
+ {3308540400 -21600 0 CST}
+ {3319430400 -18000 1 CDT}
+ {3339990000 -21600 0 CST}
+ {3350880000 -18000 1 CDT}
+ {3371439600 -21600 0 CST}
+ {3382934400 -18000 1 CDT}
+ {3403494000 -21600 0 CST}
+ {3414384000 -18000 1 CDT}
+ {3434943600 -21600 0 CST}
+ {3445833600 -18000 1 CDT}
+ {3466393200 -21600 0 CST}
+ {3477283200 -18000 1 CDT}
+ {3497842800 -21600 0 CST}
+ {3508732800 -18000 1 CDT}
+ {3529292400 -21600 0 CST}
+ {3540182400 -18000 1 CDT}
+ {3560742000 -21600 0 CST}
+ {3572236800 -18000 1 CDT}
+ {3592796400 -21600 0 CST}
+ {3603686400 -18000 1 CDT}
+ {3624246000 -21600 0 CST}
+ {3635136000 -18000 1 CDT}
+ {3655695600 -21600 0 CST}
+ {3666585600 -18000 1 CDT}
+ {3687145200 -21600 0 CST}
+ {3698035200 -18000 1 CDT}
+ {3718594800 -21600 0 CST}
+ {3730089600 -18000 1 CDT}
+ {3750649200 -21600 0 CST}
+ {3761539200 -18000 1 CDT}
+ {3782098800 -21600 0 CST}
+ {3792988800 -18000 1 CDT}
+ {3813548400 -21600 0 CST}
+ {3824438400 -18000 1 CDT}
+ {3844998000 -21600 0 CST}
+ {3855888000 -18000 1 CDT}
+ {3876447600 -21600 0 CST}
+ {3887337600 -18000 1 CDT}
+ {3907897200 -21600 0 CST}
+ {3919392000 -18000 1 CDT}
+ {3939951600 -21600 0 CST}
+ {3950841600 -18000 1 CDT}
+ {3971401200 -21600 0 CST}
+ {3982291200 -18000 1 CDT}
+ {4002850800 -21600 0 CST}
+ {4013740800 -18000 1 CDT}
+ {4034300400 -21600 0 CST}
+ {4045190400 -18000 1 CDT}
+ {4065750000 -21600 0 CST}
+ {4076640000 -18000 1 CDT}
+ {4097199600 -21600 0 CST}
+}
diff --git a/library/tzdata/America/Yakutat b/library/tzdata/America/Yakutat
new file mode 100644
index 0000000..a0420c5
--- /dev/null
+++ b/library/tzdata/America/Yakutat
@@ -0,0 +1,276 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Yakutat) {
+ {-9223372036854775808 52865 0 LMT}
+ {-3225364865 -33535 0 LMT}
+ {-2188953665 -32400 0 YST}
+ {-883580400 -32400 0 YST}
+ {-880203600 -28800 1 YWT}
+ {-769395600 -28800 1 YPT}
+ {-765381600 -32400 0 YST}
+ {-757350000 -32400 0 YST}
+ {-31503600 -32400 0 YST}
+ {-21474000 -28800 1 YDT}
+ {-5752800 -32400 0 YST}
+ {9975600 -28800 1 YDT}
+ {25696800 -32400 0 YST}
+ {41425200 -28800 1 YDT}
+ {57751200 -32400 0 YST}
+ {73479600 -28800 1 YDT}
+ {89200800 -32400 0 YST}
+ {104929200 -28800 1 YDT}
+ {120650400 -32400 0 YST}
+ {126702000 -28800 1 YDT}
+ {152100000 -32400 0 YST}
+ {162385200 -28800 1 YDT}
+ {183549600 -32400 0 YST}
+ {199278000 -28800 1 YDT}
+ {215604000 -32400 0 YST}
+ {230727600 -28800 1 YDT}
+ {247053600 -32400 0 YST}
+ {262782000 -28800 1 YDT}
+ {278503200 -32400 0 YST}
+ {294231600 -28800 1 YDT}
+ {309952800 -32400 0 YST}
+ {325681200 -28800 1 YDT}
+ {341402400 -32400 0 YST}
+ {357130800 -28800 1 YDT}
+ {372852000 -32400 0 YST}
+ {388580400 -28800 1 YDT}
+ {404906400 -32400 0 YST}
+ {420030000 -28800 1 YDT}
+ {436356000 -32400 0 YST}
+ {439030800 -32400 0 AKST}
+ {452084400 -28800 1 AKDT}
+ {467805600 -32400 0 AKST}
+ {483534000 -28800 1 AKDT}
+ {499255200 -32400 0 AKST}
+ {514983600 -28800 1 AKDT}
+ {530704800 -32400 0 AKST}
+ {544618800 -28800 1 AKDT}
+ {562154400 -32400 0 AKST}
+ {576068400 -28800 1 AKDT}
+ {594208800 -32400 0 AKST}
+ {607518000 -28800 1 AKDT}
+ {625658400 -32400 0 AKST}
+ {638967600 -28800 1 AKDT}
+ {657108000 -32400 0 AKST}
+ {671022000 -28800 1 AKDT}
+ {688557600 -32400 0 AKST}
+ {702471600 -28800 1 AKDT}
+ {720007200 -32400 0 AKST}
+ {733921200 -28800 1 AKDT}
+ {752061600 -32400 0 AKST}
+ {765370800 -28800 1 AKDT}
+ {783511200 -32400 0 AKST}
+ {796820400 -28800 1 AKDT}
+ {814960800 -32400 0 AKST}
+ {828874800 -28800 1 AKDT}
+ {846410400 -32400 0 AKST}
+ {860324400 -28800 1 AKDT}
+ {877860000 -32400 0 AKST}
+ {891774000 -28800 1 AKDT}
+ {909309600 -32400 0 AKST}
+ {923223600 -28800 1 AKDT}
+ {941364000 -32400 0 AKST}
+ {954673200 -28800 1 AKDT}
+ {972813600 -32400 0 AKST}
+ {986122800 -28800 1 AKDT}
+ {1004263200 -32400 0 AKST}
+ {1018177200 -28800 1 AKDT}
+ {1035712800 -32400 0 AKST}
+ {1049626800 -28800 1 AKDT}
+ {1067162400 -32400 0 AKST}
+ {1081076400 -28800 1 AKDT}
+ {1099216800 -32400 0 AKST}
+ {1112526000 -28800 1 AKDT}
+ {1130666400 -32400 0 AKST}
+ {1143975600 -28800 1 AKDT}
+ {1162116000 -32400 0 AKST}
+ {1173610800 -28800 1 AKDT}
+ {1194170400 -32400 0 AKST}
+ {1205060400 -28800 1 AKDT}
+ {1225620000 -32400 0 AKST}
+ {1236510000 -28800 1 AKDT}
+ {1257069600 -32400 0 AKST}
+ {1268564400 -28800 1 AKDT}
+ {1289124000 -32400 0 AKST}
+ {1300014000 -28800 1 AKDT}
+ {1320573600 -32400 0 AKST}
+ {1331463600 -28800 1 AKDT}
+ {1352023200 -32400 0 AKST}
+ {1362913200 -28800 1 AKDT}
+ {1383472800 -32400 0 AKST}
+ {1394362800 -28800 1 AKDT}
+ {1414922400 -32400 0 AKST}
+ {1425812400 -28800 1 AKDT}
+ {1446372000 -32400 0 AKST}
+ {1457866800 -28800 1 AKDT}
+ {1478426400 -32400 0 AKST}
+ {1489316400 -28800 1 AKDT}
+ {1509876000 -32400 0 AKST}
+ {1520766000 -28800 1 AKDT}
+ {1541325600 -32400 0 AKST}
+ {1552215600 -28800 1 AKDT}
+ {1572775200 -32400 0 AKST}
+ {1583665200 -28800 1 AKDT}
+ {1604224800 -32400 0 AKST}
+ {1615719600 -28800 1 AKDT}
+ {1636279200 -32400 0 AKST}
+ {1647169200 -28800 1 AKDT}
+ {1667728800 -32400 0 AKST}
+ {1678618800 -28800 1 AKDT}
+ {1699178400 -32400 0 AKST}
+ {1710068400 -28800 1 AKDT}
+ {1730628000 -32400 0 AKST}
+ {1741518000 -28800 1 AKDT}
+ {1762077600 -32400 0 AKST}
+ {1772967600 -28800 1 AKDT}
+ {1793527200 -32400 0 AKST}
+ {1805022000 -28800 1 AKDT}
+ {1825581600 -32400 0 AKST}
+ {1836471600 -28800 1 AKDT}
+ {1857031200 -32400 0 AKST}
+ {1867921200 -28800 1 AKDT}
+ {1888480800 -32400 0 AKST}
+ {1899370800 -28800 1 AKDT}
+ {1919930400 -32400 0 AKST}
+ {1930820400 -28800 1 AKDT}
+ {1951380000 -32400 0 AKST}
+ {1962874800 -28800 1 AKDT}
+ {1983434400 -32400 0 AKST}
+ {1994324400 -28800 1 AKDT}
+ {2014884000 -32400 0 AKST}
+ {2025774000 -28800 1 AKDT}
+ {2046333600 -32400 0 AKST}
+ {2057223600 -28800 1 AKDT}
+ {2077783200 -32400 0 AKST}
+ {2088673200 -28800 1 AKDT}
+ {2109232800 -32400 0 AKST}
+ {2120122800 -28800 1 AKDT}
+ {2140682400 -32400 0 AKST}
+ {2152177200 -28800 1 AKDT}
+ {2172736800 -32400 0 AKST}
+ {2183626800 -28800 1 AKDT}
+ {2204186400 -32400 0 AKST}
+ {2215076400 -28800 1 AKDT}
+ {2235636000 -32400 0 AKST}
+ {2246526000 -28800 1 AKDT}
+ {2267085600 -32400 0 AKST}
+ {2277975600 -28800 1 AKDT}
+ {2298535200 -32400 0 AKST}
+ {2309425200 -28800 1 AKDT}
+ {2329984800 -32400 0 AKST}
+ {2341479600 -28800 1 AKDT}
+ {2362039200 -32400 0 AKST}
+ {2372929200 -28800 1 AKDT}
+ {2393488800 -32400 0 AKST}
+ {2404378800 -28800 1 AKDT}
+ {2424938400 -32400 0 AKST}
+ {2435828400 -28800 1 AKDT}
+ {2456388000 -32400 0 AKST}
+ {2467278000 -28800 1 AKDT}
+ {2487837600 -32400 0 AKST}
+ {2499332400 -28800 1 AKDT}
+ {2519892000 -32400 0 AKST}
+ {2530782000 -28800 1 AKDT}
+ {2551341600 -32400 0 AKST}
+ {2562231600 -28800 1 AKDT}
+ {2582791200 -32400 0 AKST}
+ {2593681200 -28800 1 AKDT}
+ {2614240800 -32400 0 AKST}
+ {2625130800 -28800 1 AKDT}
+ {2645690400 -32400 0 AKST}
+ {2656580400 -28800 1 AKDT}
+ {2677140000 -32400 0 AKST}
+ {2688634800 -28800 1 AKDT}
+ {2709194400 -32400 0 AKST}
+ {2720084400 -28800 1 AKDT}
+ {2740644000 -32400 0 AKST}
+ {2751534000 -28800 1 AKDT}
+ {2772093600 -32400 0 AKST}
+ {2782983600 -28800 1 AKDT}
+ {2803543200 -32400 0 AKST}
+ {2814433200 -28800 1 AKDT}
+ {2834992800 -32400 0 AKST}
+ {2846487600 -28800 1 AKDT}
+ {2867047200 -32400 0 AKST}
+ {2877937200 -28800 1 AKDT}
+ {2898496800 -32400 0 AKST}
+ {2909386800 -28800 1 AKDT}
+ {2929946400 -32400 0 AKST}
+ {2940836400 -28800 1 AKDT}
+ {2961396000 -32400 0 AKST}
+ {2972286000 -28800 1 AKDT}
+ {2992845600 -32400 0 AKST}
+ {3003735600 -28800 1 AKDT}
+ {3024295200 -32400 0 AKST}
+ {3035790000 -28800 1 AKDT}
+ {3056349600 -32400 0 AKST}
+ {3067239600 -28800 1 AKDT}
+ {3087799200 -32400 0 AKST}
+ {3098689200 -28800 1 AKDT}
+ {3119248800 -32400 0 AKST}
+ {3130138800 -28800 1 AKDT}
+ {3150698400 -32400 0 AKST}
+ {3161588400 -28800 1 AKDT}
+ {3182148000 -32400 0 AKST}
+ {3193038000 -28800 1 AKDT}
+ {3213597600 -32400 0 AKST}
+ {3225092400 -28800 1 AKDT}
+ {3245652000 -32400 0 AKST}
+ {3256542000 -28800 1 AKDT}
+ {3277101600 -32400 0 AKST}
+ {3287991600 -28800 1 AKDT}
+ {3308551200 -32400 0 AKST}
+ {3319441200 -28800 1 AKDT}
+ {3340000800 -32400 0 AKST}
+ {3350890800 -28800 1 AKDT}
+ {3371450400 -32400 0 AKST}
+ {3382945200 -28800 1 AKDT}
+ {3403504800 -32400 0 AKST}
+ {3414394800 -28800 1 AKDT}
+ {3434954400 -32400 0 AKST}
+ {3445844400 -28800 1 AKDT}
+ {3466404000 -32400 0 AKST}
+ {3477294000 -28800 1 AKDT}
+ {3497853600 -32400 0 AKST}
+ {3508743600 -28800 1 AKDT}
+ {3529303200 -32400 0 AKST}
+ {3540193200 -28800 1 AKDT}
+ {3560752800 -32400 0 AKST}
+ {3572247600 -28800 1 AKDT}
+ {3592807200 -32400 0 AKST}
+ {3603697200 -28800 1 AKDT}
+ {3624256800 -32400 0 AKST}
+ {3635146800 -28800 1 AKDT}
+ {3655706400 -32400 0 AKST}
+ {3666596400 -28800 1 AKDT}
+ {3687156000 -32400 0 AKST}
+ {3698046000 -28800 1 AKDT}
+ {3718605600 -32400 0 AKST}
+ {3730100400 -28800 1 AKDT}
+ {3750660000 -32400 0 AKST}
+ {3761550000 -28800 1 AKDT}
+ {3782109600 -32400 0 AKST}
+ {3792999600 -28800 1 AKDT}
+ {3813559200 -32400 0 AKST}
+ {3824449200 -28800 1 AKDT}
+ {3845008800 -32400 0 AKST}
+ {3855898800 -28800 1 AKDT}
+ {3876458400 -32400 0 AKST}
+ {3887348400 -28800 1 AKDT}
+ {3907908000 -32400 0 AKST}
+ {3919402800 -28800 1 AKDT}
+ {3939962400 -32400 0 AKST}
+ {3950852400 -28800 1 AKDT}
+ {3971412000 -32400 0 AKST}
+ {3982302000 -28800 1 AKDT}
+ {4002861600 -32400 0 AKST}
+ {4013751600 -28800 1 AKDT}
+ {4034311200 -32400 0 AKST}
+ {4045201200 -28800 1 AKDT}
+ {4065760800 -32400 0 AKST}
+ {4076650800 -28800 1 AKDT}
+ {4097210400 -32400 0 AKST}
+}
diff --git a/library/tzdata/America/Yellowknife b/library/tzdata/America/Yellowknife
new file mode 100644
index 0000000..44ca658
--- /dev/null
+++ b/library/tzdata/America/Yellowknife
@@ -0,0 +1,252 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:America/Yellowknife) {
+ {-9223372036854775808 0 0 zzz}
+ {-1104537600 -25200 0 MST}
+ {-880210800 -21600 1 MWT}
+ {-769395600 -21600 1 MPT}
+ {-765388800 -25200 0 MST}
+ {-147891600 -18000 1 MDDT}
+ {-131562000 -25200 0 MST}
+ {315558000 -25200 0 MST}
+ {325674000 -21600 1 MDT}
+ {341395200 -25200 0 MST}
+ {357123600 -21600 1 MDT}
+ {372844800 -25200 0 MST}
+ {388573200 -21600 1 MDT}
+ {404899200 -25200 0 MST}
+ {420022800 -21600 1 MDT}
+ {436348800 -25200 0 MST}
+ {452077200 -21600 1 MDT}
+ {467798400 -25200 0 MST}
+ {483526800 -21600 1 MDT}
+ {499248000 -25200 0 MST}
+ {514976400 -21600 1 MDT}
+ {530697600 -25200 0 MST}
+ {544611600 -21600 1 MDT}
+ {562147200 -25200 0 MST}
+ {576061200 -21600 1 MDT}
+ {594201600 -25200 0 MST}
+ {607510800 -21600 1 MDT}
+ {625651200 -25200 0 MST}
+ {638960400 -21600 1 MDT}
+ {657100800 -25200 0 MST}
+ {671014800 -21600 1 MDT}
+ {688550400 -25200 0 MST}
+ {702464400 -21600 1 MDT}
+ {720000000 -25200 0 MST}
+ {733914000 -21600 1 MDT}
+ {752054400 -25200 0 MST}
+ {765363600 -21600 1 MDT}
+ {783504000 -25200 0 MST}
+ {796813200 -21600 1 MDT}
+ {814953600 -25200 0 MST}
+ {828867600 -21600 1 MDT}
+ {846403200 -25200 0 MST}
+ {860317200 -21600 1 MDT}
+ {877852800 -25200 0 MST}
+ {891766800 -21600 1 MDT}
+ {909302400 -25200 0 MST}
+ {923216400 -21600 1 MDT}
+ {941356800 -25200 0 MST}
+ {954666000 -21600 1 MDT}
+ {972806400 -25200 0 MST}
+ {986115600 -21600 1 MDT}
+ {1004256000 -25200 0 MST}
+ {1018170000 -21600 1 MDT}
+ {1035705600 -25200 0 MST}
+ {1049619600 -21600 1 MDT}
+ {1067155200 -25200 0 MST}
+ {1081069200 -21600 1 MDT}
+ {1099209600 -25200 0 MST}
+ {1112518800 -21600 1 MDT}
+ {1130659200 -25200 0 MST}
+ {1143968400 -21600 1 MDT}
+ {1162108800 -25200 0 MST}
+ {1173603600 -21600 1 MDT}
+ {1194163200 -25200 0 MST}
+ {1205053200 -21600 1 MDT}
+ {1225612800 -25200 0 MST}
+ {1236502800 -21600 1 MDT}
+ {1257062400 -25200 0 MST}
+ {1268557200 -21600 1 MDT}
+ {1289116800 -25200 0 MST}
+ {1300006800 -21600 1 MDT}
+ {1320566400 -25200 0 MST}
+ {1331456400 -21600 1 MDT}
+ {1352016000 -25200 0 MST}
+ {1362906000 -21600 1 MDT}
+ {1383465600 -25200 0 MST}
+ {1394355600 -21600 1 MDT}
+ {1414915200 -25200 0 MST}
+ {1425805200 -21600 1 MDT}
+ {1446364800 -25200 0 MST}
+ {1457859600 -21600 1 MDT}
+ {1478419200 -25200 0 MST}
+ {1489309200 -21600 1 MDT}
+ {1509868800 -25200 0 MST}
+ {1520758800 -21600 1 MDT}
+ {1541318400 -25200 0 MST}
+ {1552208400 -21600 1 MDT}
+ {1572768000 -25200 0 MST}
+ {1583658000 -21600 1 MDT}
+ {1604217600 -25200 0 MST}
+ {1615712400 -21600 1 MDT}
+ {1636272000 -25200 0 MST}
+ {1647162000 -21600 1 MDT}
+ {1667721600 -25200 0 MST}
+ {1678611600 -21600 1 MDT}
+ {1699171200 -25200 0 MST}
+ {1710061200 -21600 1 MDT}
+ {1730620800 -25200 0 MST}
+ {1741510800 -21600 1 MDT}
+ {1762070400 -25200 0 MST}
+ {1772960400 -21600 1 MDT}
+ {1793520000 -25200 0 MST}
+ {1805014800 -21600 1 MDT}
+ {1825574400 -25200 0 MST}
+ {1836464400 -21600 1 MDT}
+ {1857024000 -25200 0 MST}
+ {1867914000 -21600 1 MDT}
+ {1888473600 -25200 0 MST}
+ {1899363600 -21600 1 MDT}
+ {1919923200 -25200 0 MST}
+ {1930813200 -21600 1 MDT}
+ {1951372800 -25200 0 MST}
+ {1962867600 -21600 1 MDT}
+ {1983427200 -25200 0 MST}
+ {1994317200 -21600 1 MDT}
+ {2014876800 -25200 0 MST}
+ {2025766800 -21600 1 MDT}
+ {2046326400 -25200 0 MST}
+ {2057216400 -21600 1 MDT}
+ {2077776000 -25200 0 MST}
+ {2088666000 -21600 1 MDT}
+ {2109225600 -25200 0 MST}
+ {2120115600 -21600 1 MDT}
+ {2140675200 -25200 0 MST}
+ {2152170000 -21600 1 MDT}
+ {2172729600 -25200 0 MST}
+ {2183619600 -21600 1 MDT}
+ {2204179200 -25200 0 MST}
+ {2215069200 -21600 1 MDT}
+ {2235628800 -25200 0 MST}
+ {2246518800 -21600 1 MDT}
+ {2267078400 -25200 0 MST}
+ {2277968400 -21600 1 MDT}
+ {2298528000 -25200 0 MST}
+ {2309418000 -21600 1 MDT}
+ {2329977600 -25200 0 MST}
+ {2341472400 -21600 1 MDT}
+ {2362032000 -25200 0 MST}
+ {2372922000 -21600 1 MDT}
+ {2393481600 -25200 0 MST}
+ {2404371600 -21600 1 MDT}
+ {2424931200 -25200 0 MST}
+ {2435821200 -21600 1 MDT}
+ {2456380800 -25200 0 MST}
+ {2467270800 -21600 1 MDT}
+ {2487830400 -25200 0 MST}
+ {2499325200 -21600 1 MDT}
+ {2519884800 -25200 0 MST}
+ {2530774800 -21600 1 MDT}
+ {2551334400 -25200 0 MST}
+ {2562224400 -21600 1 MDT}
+ {2582784000 -25200 0 MST}
+ {2593674000 -21600 1 MDT}
+ {2614233600 -25200 0 MST}
+ {2625123600 -21600 1 MDT}
+ {2645683200 -25200 0 MST}
+ {2656573200 -21600 1 MDT}
+ {2677132800 -25200 0 MST}
+ {2688627600 -21600 1 MDT}
+ {2709187200 -25200 0 MST}
+ {2720077200 -21600 1 MDT}
+ {2740636800 -25200 0 MST}
+ {2751526800 -21600 1 MDT}
+ {2772086400 -25200 0 MST}
+ {2782976400 -21600 1 MDT}
+ {2803536000 -25200 0 MST}
+ {2814426000 -21600 1 MDT}
+ {2834985600 -25200 0 MST}
+ {2846480400 -21600 1 MDT}
+ {2867040000 -25200 0 MST}
+ {2877930000 -21600 1 MDT}
+ {2898489600 -25200 0 MST}
+ {2909379600 -21600 1 MDT}
+ {2929939200 -25200 0 MST}
+ {2940829200 -21600 1 MDT}
+ {2961388800 -25200 0 MST}
+ {2972278800 -21600 1 MDT}
+ {2992838400 -25200 0 MST}
+ {3003728400 -21600 1 MDT}
+ {3024288000 -25200 0 MST}
+ {3035782800 -21600 1 MDT}
+ {3056342400 -25200 0 MST}
+ {3067232400 -21600 1 MDT}
+ {3087792000 -25200 0 MST}
+ {3098682000 -21600 1 MDT}
+ {3119241600 -25200 0 MST}
+ {3130131600 -21600 1 MDT}
+ {3150691200 -25200 0 MST}
+ {3161581200 -21600 1 MDT}
+ {3182140800 -25200 0 MST}
+ {3193030800 -21600 1 MDT}
+ {3213590400 -25200 0 MST}
+ {3225085200 -21600 1 MDT}
+ {3245644800 -25200 0 MST}
+ {3256534800 -21600 1 MDT}
+ {3277094400 -25200 0 MST}
+ {3287984400 -21600 1 MDT}
+ {3308544000 -25200 0 MST}
+ {3319434000 -21600 1 MDT}
+ {3339993600 -25200 0 MST}
+ {3350883600 -21600 1 MDT}
+ {3371443200 -25200 0 MST}
+ {3382938000 -21600 1 MDT}
+ {3403497600 -25200 0 MST}
+ {3414387600 -21600 1 MDT}
+ {3434947200 -25200 0 MST}
+ {3445837200 -21600 1 MDT}
+ {3466396800 -25200 0 MST}
+ {3477286800 -21600 1 MDT}
+ {3497846400 -25200 0 MST}
+ {3508736400 -21600 1 MDT}
+ {3529296000 -25200 0 MST}
+ {3540186000 -21600 1 MDT}
+ {3560745600 -25200 0 MST}
+ {3572240400 -21600 1 MDT}
+ {3592800000 -25200 0 MST}
+ {3603690000 -21600 1 MDT}
+ {3624249600 -25200 0 MST}
+ {3635139600 -21600 1 MDT}
+ {3655699200 -25200 0 MST}
+ {3666589200 -21600 1 MDT}
+ {3687148800 -25200 0 MST}
+ {3698038800 -21600 1 MDT}
+ {3718598400 -25200 0 MST}
+ {3730093200 -21600 1 MDT}
+ {3750652800 -25200 0 MST}
+ {3761542800 -21600 1 MDT}
+ {3782102400 -25200 0 MST}
+ {3792992400 -21600 1 MDT}
+ {3813552000 -25200 0 MST}
+ {3824442000 -21600 1 MDT}
+ {3845001600 -25200 0 MST}
+ {3855891600 -21600 1 MDT}
+ {3876451200 -25200 0 MST}
+ {3887341200 -21600 1 MDT}
+ {3907900800 -25200 0 MST}
+ {3919395600 -21600 1 MDT}
+ {3939955200 -25200 0 MST}
+ {3950845200 -21600 1 MDT}
+ {3971404800 -25200 0 MST}
+ {3982294800 -21600 1 MDT}
+ {4002854400 -25200 0 MST}
+ {4013744400 -21600 1 MDT}
+ {4034304000 -25200 0 MST}
+ {4045194000 -21600 1 MDT}
+ {4065753600 -25200 0 MST}
+ {4076643600 -21600 1 MDT}
+ {4097203200 -25200 0 MST}
+}
diff --git a/library/tzdata/Antarctica/Casey b/library/tzdata/Antarctica/Casey
new file mode 100644
index 0000000..119d514
--- /dev/null
+++ b/library/tzdata/Antarctica/Casey
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Antarctica/Casey) {
+ {-9223372036854775808 0 0 zzz}
+ {-31536000 28800 0 WST}
+ {1255802400 39600 0 CAST}
+ {1267714800 28800 0 WST}
+}
diff --git a/library/tzdata/Antarctica/Davis b/library/tzdata/Antarctica/Davis
new file mode 100644
index 0000000..47aece9
--- /dev/null
+++ b/library/tzdata/Antarctica/Davis
@@ -0,0 +1,10 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Antarctica/Davis) {
+ {-9223372036854775808 0 0 zzz}
+ {-409190400 25200 0 DAVT}
+ {-163062000 0 0 zzz}
+ {-28857600 25200 0 DAVT}
+ {1255806000 18000 0 DAVT}
+ {1268251200 25200 0 DAVT}
+}
diff --git a/library/tzdata/Antarctica/DumontDUrville b/library/tzdata/Antarctica/DumontDUrville
new file mode 100644
index 0000000..41dc1e3
--- /dev/null
+++ b/library/tzdata/Antarctica/DumontDUrville
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Antarctica/DumontDUrville) {
+ {-9223372036854775808 0 0 zzz}
+ {-725846400 36000 0 PMT}
+ {-566992800 0 0 zzz}
+ {-415497600 36000 0 DDUT}
+}
diff --git a/library/tzdata/Antarctica/Macquarie b/library/tzdata/Antarctica/Macquarie
new file mode 100644
index 0000000..9877ee8
--- /dev/null
+++ b/library/tzdata/Antarctica/Macquarie
@@ -0,0 +1,102 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Antarctica/Macquarie) {
+ {-9223372036854775808 0 0 zzz}
+ {-1861920000 36000 0 EST}
+ {-1680508800 39600 1 EST}
+ {-1669892400 39600 0 EST}
+ {-1665392400 36000 0 EST}
+ {-883641600 39600 1 EST}
+ {-876128400 36000 0 EST}
+ {-860400000 39600 1 EST}
+ {-844678800 36000 0 EST}
+ {-828345600 39600 1 EST}
+ {-813229200 36000 0 EST}
+ {-94730400 36000 0 EST}
+ {-71136000 39600 1 EST}
+ {-55411200 36000 0 EST}
+ {-37267200 39600 1 EST}
+ {-25776000 36000 0 EST}
+ {-5817600 39600 1 EST}
+ {5673600 36000 0 EST}
+ {25632000 39600 1 EST}
+ {37728000 36000 0 EST}
+ {57686400 39600 1 EST}
+ {67968000 36000 0 EST}
+ {89136000 39600 1 EST}
+ {100022400 36000 0 EST}
+ {120585600 39600 1 EST}
+ {131472000 36000 0 EST}
+ {152035200 39600 1 EST}
+ {162921600 36000 0 EST}
+ {183484800 39600 1 EST}
+ {194976000 36000 0 EST}
+ {215539200 39600 1 EST}
+ {226425600 36000 0 EST}
+ {246988800 39600 1 EST}
+ {257875200 36000 0 EST}
+ {278438400 39600 1 EST}
+ {289324800 36000 0 EST}
+ {309888000 39600 1 EST}
+ {320774400 36000 0 EST}
+ {341337600 39600 1 EST}
+ {352224000 36000 0 EST}
+ {372787200 39600 1 EST}
+ {386092800 36000 0 EST}
+ {404841600 39600 1 EST}
+ {417542400 36000 0 EST}
+ {436291200 39600 1 EST}
+ {447177600 36000 0 EST}
+ {467740800 39600 1 EST}
+ {478627200 36000 0 EST}
+ {499190400 39600 1 EST}
+ {510076800 36000 0 EST}
+ {530035200 39600 1 EST}
+ {542736000 36000 0 EST}
+ {562089600 39600 1 EST}
+ {574790400 36000 0 EST}
+ {594144000 39600 1 EST}
+ {606240000 36000 0 EST}
+ {625593600 39600 1 EST}
+ {637689600 36000 0 EST}
+ {657043200 39600 1 EST}
+ {670348800 36000 0 EST}
+ {686678400 39600 1 EST}
+ {701798400 36000 0 EST}
+ {718128000 39600 1 EST}
+ {733248000 36000 0 EST}
+ {749577600 39600 1 EST}
+ {764697600 36000 0 EST}
+ {781027200 39600 1 EST}
+ {796147200 36000 0 EST}
+ {812476800 39600 1 EST}
+ {828201600 36000 0 EST}
+ {844531200 39600 1 EST}
+ {859651200 36000 0 EST}
+ {875980800 39600 1 EST}
+ {891100800 36000 0 EST}
+ {907430400 39600 1 EST}
+ {922550400 36000 0 EST}
+ {938880000 39600 1 EST}
+ {954000000 36000 0 EST}
+ {967305600 39600 1 EST}
+ {985449600 36000 0 EST}
+ {1002384000 39600 1 EST}
+ {1017504000 36000 0 EST}
+ {1033833600 39600 1 EST}
+ {1048953600 36000 0 EST}
+ {1065283200 39600 1 EST}
+ {1080403200 36000 0 EST}
+ {1096732800 39600 1 EST}
+ {1111852800 36000 0 EST}
+ {1128182400 39600 1 EST}
+ {1143907200 36000 0 EST}
+ {1159632000 39600 1 EST}
+ {1174752000 36000 0 EST}
+ {1191686400 39600 1 EST}
+ {1207411200 36000 0 EST}
+ {1223136000 39600 1 EST}
+ {1238860800 36000 0 EST}
+ {1254585600 39600 1 EST}
+ {1270310400 39600 0 MIST}
+}
diff --git a/library/tzdata/Antarctica/Mawson b/library/tzdata/Antarctica/Mawson
new file mode 100644
index 0000000..ba03ba1
--- /dev/null
+++ b/library/tzdata/Antarctica/Mawson
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Antarctica/Mawson) {
+ {-9223372036854775808 0 0 zzz}
+ {-501206400 21600 0 MAWT}
+ {1255809600 18000 0 MAWT}
+}
diff --git a/library/tzdata/Antarctica/McMurdo b/library/tzdata/Antarctica/McMurdo
new file mode 100644
index 0000000..670f7eb
--- /dev/null
+++ b/library/tzdata/Antarctica/McMurdo
@@ -0,0 +1,257 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Antarctica/McMurdo) {
+ {-9223372036854775808 0 0 zzz}
+ {-441849600 43200 0 NZST}
+ {152632800 46800 1 NZDT}
+ {162309600 43200 0 NZST}
+ {183477600 46800 1 NZDT}
+ {194968800 43200 0 NZST}
+ {215532000 46800 1 NZDT}
+ {226418400 43200 0 NZST}
+ {246981600 46800 1 NZDT}
+ {257868000 43200 0 NZST}
+ {278431200 46800 1 NZDT}
+ {289317600 43200 0 NZST}
+ {309880800 46800 1 NZDT}
+ {320767200 43200 0 NZST}
+ {341330400 46800 1 NZDT}
+ {352216800 43200 0 NZST}
+ {372780000 46800 1 NZDT}
+ {384271200 43200 0 NZST}
+ {404834400 46800 1 NZDT}
+ {415720800 43200 0 NZST}
+ {436284000 46800 1 NZDT}
+ {447170400 43200 0 NZST}
+ {467733600 46800 1 NZDT}
+ {478620000 43200 0 NZST}
+ {499183200 46800 1 NZDT}
+ {510069600 43200 0 NZST}
+ {530632800 46800 1 NZDT}
+ {541519200 43200 0 NZST}
+ {562082400 46800 1 NZDT}
+ {573573600 43200 0 NZST}
+ {594136800 46800 1 NZDT}
+ {605023200 43200 0 NZST}
+ {623772000 46800 1 NZDT}
+ {637682400 43200 0 NZST}
+ {655221600 46800 1 NZDT}
+ {669132000 43200 0 NZST}
+ {686671200 46800 1 NZDT}
+ {700581600 43200 0 NZST}
+ {718120800 46800 1 NZDT}
+ {732636000 43200 0 NZST}
+ {749570400 46800 1 NZDT}
+ {764085600 43200 0 NZST}
+ {781020000 46800 1 NZDT}
+ {795535200 43200 0 NZST}
+ {812469600 46800 1 NZDT}
+ {826984800 43200 0 NZST}
+ {844524000 46800 1 NZDT}
+ {858434400 43200 0 NZST}
+ {875973600 46800 1 NZDT}
+ {889884000 43200 0 NZST}
+ {907423200 46800 1 NZDT}
+ {921938400 43200 0 NZST}
+ {938872800 46800 1 NZDT}
+ {953388000 43200 0 NZST}
+ {970322400 46800 1 NZDT}
+ {984837600 43200 0 NZST}
+ {1002376800 46800 1 NZDT}
+ {1016287200 43200 0 NZST}
+ {1033826400 46800 1 NZDT}
+ {1047736800 43200 0 NZST}
+ {1065276000 46800 1 NZDT}
+ {1079791200 43200 0 NZST}
+ {1096725600 46800 1 NZDT}
+ {1111240800 43200 0 NZST}
+ {1128175200 46800 1 NZDT}
+ {1142690400 43200 0 NZST}
+ {1159624800 46800 1 NZDT}
+ {1174140000 43200 0 NZST}
+ {1191074400 46800 1 NZDT}
+ {1207404000 43200 0 NZST}
+ {1222524000 46800 1 NZDT}
+ {1238853600 43200 0 NZST}
+ {1253973600 46800 1 NZDT}
+ {1270303200 43200 0 NZST}
+ {1285423200 46800 1 NZDT}
+ {1301752800 43200 0 NZST}
+ {1316872800 46800 1 NZDT}
+ {1333202400 43200 0 NZST}
+ {1348927200 46800 1 NZDT}
+ {1365256800 43200 0 NZST}
+ {1380376800 46800 1 NZDT}
+ {1396706400 43200 0 NZST}
+ {1411826400 46800 1 NZDT}
+ {1428156000 43200 0 NZST}
+ {1443276000 46800 1 NZDT}
+ {1459605600 43200 0 NZST}
+ {1474725600 46800 1 NZDT}
+ {1491055200 43200 0 NZST}
+ {1506175200 46800 1 NZDT}
+ {1522504800 43200 0 NZST}
+ {1538229600 46800 1 NZDT}
+ {1554559200 43200 0 NZST}
+ {1569679200 46800 1 NZDT}
+ {1586008800 43200 0 NZST}
+ {1601128800 46800 1 NZDT}
+ {1617458400 43200 0 NZST}
+ {1632578400 46800 1 NZDT}
+ {1648908000 43200 0 NZST}
+ {1664028000 46800 1 NZDT}
+ {1680357600 43200 0 NZST}
+ {1695477600 46800 1 NZDT}
+ {1712412000 43200 0 NZST}
+ {1727532000 46800 1 NZDT}
+ {1743861600 43200 0 NZST}
+ {1758981600 46800 1 NZDT}
+ {1775311200 43200 0 NZST}
+ {1790431200 46800 1 NZDT}
+ {1806760800 43200 0 NZST}
+ {1821880800 46800 1 NZDT}
+ {1838210400 43200 0 NZST}
+ {1853330400 46800 1 NZDT}
+ {1869660000 43200 0 NZST}
+ {1885384800 46800 1 NZDT}
+ {1901714400 43200 0 NZST}
+ {1916834400 46800 1 NZDT}
+ {1933164000 43200 0 NZST}
+ {1948284000 46800 1 NZDT}
+ {1964613600 43200 0 NZST}
+ {1979733600 46800 1 NZDT}
+ {1996063200 43200 0 NZST}
+ {2011183200 46800 1 NZDT}
+ {2027512800 43200 0 NZST}
+ {2042632800 46800 1 NZDT}
+ {2058962400 43200 0 NZST}
+ {2074687200 46800 1 NZDT}
+ {2091016800 43200 0 NZST}
+ {2106136800 46800 1 NZDT}
+ {2122466400 43200 0 NZST}
+ {2137586400 46800 1 NZDT}
+ {2153916000 43200 0 NZST}
+ {2169036000 46800 1 NZDT}
+ {2185365600 43200 0 NZST}
+ {2200485600 46800 1 NZDT}
+ {2216815200 43200 0 NZST}
+ {2232540000 46800 1 NZDT}
+ {2248869600 43200 0 NZST}
+ {2263989600 46800 1 NZDT}
+ {2280319200 43200 0 NZST}
+ {2295439200 46800 1 NZDT}
+ {2311768800 43200 0 NZST}
+ {2326888800 46800 1 NZDT}
+ {2343218400 43200 0 NZST}
+ {2358338400 46800 1 NZDT}
+ {2374668000 43200 0 NZST}
+ {2389788000 46800 1 NZDT}
+ {2406117600 43200 0 NZST}
+ {2421842400 46800 1 NZDT}
+ {2438172000 43200 0 NZST}
+ {2453292000 46800 1 NZDT}
+ {2469621600 43200 0 NZST}
+ {2484741600 46800 1 NZDT}
+ {2501071200 43200 0 NZST}
+ {2516191200 46800 1 NZDT}
+ {2532520800 43200 0 NZST}
+ {2547640800 46800 1 NZDT}
+ {2563970400 43200 0 NZST}
+ {2579090400 46800 1 NZDT}
+ {2596024800 43200 0 NZST}
+ {2611144800 46800 1 NZDT}
+ {2627474400 43200 0 NZST}
+ {2642594400 46800 1 NZDT}
+ {2658924000 43200 0 NZST}
+ {2674044000 46800 1 NZDT}
+ {2690373600 43200 0 NZST}
+ {2705493600 46800 1 NZDT}
+ {2721823200 43200 0 NZST}
+ {2736943200 46800 1 NZDT}
+ {2753272800 43200 0 NZST}
+ {2768997600 46800 1 NZDT}
+ {2785327200 43200 0 NZST}
+ {2800447200 46800 1 NZDT}
+ {2816776800 43200 0 NZST}
+ {2831896800 46800 1 NZDT}
+ {2848226400 43200 0 NZST}
+ {2863346400 46800 1 NZDT}
+ {2879676000 43200 0 NZST}
+ {2894796000 46800 1 NZDT}
+ {2911125600 43200 0 NZST}
+ {2926245600 46800 1 NZDT}
+ {2942575200 43200 0 NZST}
+ {2958300000 46800 1 NZDT}
+ {2974629600 43200 0 NZST}
+ {2989749600 46800 1 NZDT}
+ {3006079200 43200 0 NZST}
+ {3021199200 46800 1 NZDT}
+ {3037528800 43200 0 NZST}
+ {3052648800 46800 1 NZDT}
+ {3068978400 43200 0 NZST}
+ {3084098400 46800 1 NZDT}
+ {3100428000 43200 0 NZST}
+ {3116152800 46800 1 NZDT}
+ {3132482400 43200 0 NZST}
+ {3147602400 46800 1 NZDT}
+ {3163932000 43200 0 NZST}
+ {3179052000 46800 1 NZDT}
+ {3195381600 43200 0 NZST}
+ {3210501600 46800 1 NZDT}
+ {3226831200 43200 0 NZST}
+ {3241951200 46800 1 NZDT}
+ {3258280800 43200 0 NZST}
+ {3273400800 46800 1 NZDT}
+ {3289730400 43200 0 NZST}
+ {3305455200 46800 1 NZDT}
+ {3321784800 43200 0 NZST}
+ {3336904800 46800 1 NZDT}
+ {3353234400 43200 0 NZST}
+ {3368354400 46800 1 NZDT}
+ {3384684000 43200 0 NZST}
+ {3399804000 46800 1 NZDT}
+ {3416133600 43200 0 NZST}
+ {3431253600 46800 1 NZDT}
+ {3447583200 43200 0 NZST}
+ {3462703200 46800 1 NZDT}
+ {3479637600 43200 0 NZST}
+ {3494757600 46800 1 NZDT}
+ {3511087200 43200 0 NZST}
+ {3526207200 46800 1 NZDT}
+ {3542536800 43200 0 NZST}
+ {3557656800 46800 1 NZDT}
+ {3573986400 43200 0 NZST}
+ {3589106400 46800 1 NZDT}
+ {3605436000 43200 0 NZST}
+ {3620556000 46800 1 NZDT}
+ {3636885600 43200 0 NZST}
+ {3652610400 46800 1 NZDT}
+ {3668940000 43200 0 NZST}
+ {3684060000 46800 1 NZDT}
+ {3700389600 43200 0 NZST}
+ {3715509600 46800 1 NZDT}
+ {3731839200 43200 0 NZST}
+ {3746959200 46800 1 NZDT}
+ {3763288800 43200 0 NZST}
+ {3778408800 46800 1 NZDT}
+ {3794738400 43200 0 NZST}
+ {3809858400 46800 1 NZDT}
+ {3826188000 43200 0 NZST}
+ {3841912800 46800 1 NZDT}
+ {3858242400 43200 0 NZST}
+ {3873362400 46800 1 NZDT}
+ {3889692000 43200 0 NZST}
+ {3904812000 46800 1 NZDT}
+ {3921141600 43200 0 NZST}
+ {3936261600 46800 1 NZDT}
+ {3952591200 43200 0 NZST}
+ {3967711200 46800 1 NZDT}
+ {3984040800 43200 0 NZST}
+ {3999765600 46800 1 NZDT}
+ {4016095200 43200 0 NZST}
+ {4031215200 46800 1 NZDT}
+ {4047544800 43200 0 NZST}
+ {4062664800 46800 1 NZDT}
+ {4078994400 43200 0 NZST}
+ {4094114400 46800 1 NZDT}
+}
diff --git a/library/tzdata/Antarctica/Palmer b/library/tzdata/Antarctica/Palmer
new file mode 100644
index 0000000..1e24754
--- /dev/null
+++ b/library/tzdata/Antarctica/Palmer
@@ -0,0 +1,254 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Antarctica/Palmer) {
+ {-9223372036854775808 0 0 zzz}
+ {-157766400 -14400 0 ART}
+ {-152654400 -14400 0 ART}
+ {-132955200 -10800 1 ARST}
+ {-121122000 -14400 0 ART}
+ {-101419200 -10800 1 ARST}
+ {-86821200 -14400 0 ART}
+ {-71092800 -10800 1 ARST}
+ {-54766800 -14400 0 ART}
+ {-39038400 -10800 1 ARST}
+ {-23317200 -14400 0 ART}
+ {-7588800 -10800 0 ART}
+ {128142000 -7200 1 ARST}
+ {136605600 -10800 0 ART}
+ {389070000 -14400 0 CLT}
+ {403070400 -10800 1 CLST}
+ {416372400 -14400 0 CLT}
+ {434520000 -10800 1 CLST}
+ {447822000 -14400 0 CLT}
+ {466574400 -10800 1 CLST}
+ {479271600 -14400 0 CLT}
+ {498024000 -10800 1 CLST}
+ {510721200 -14400 0 CLT}
+ {529473600 -10800 1 CLST}
+ {545194800 -14400 0 CLT}
+ {560923200 -10800 1 CLST}
+ {574225200 -14400 0 CLT}
+ {591768000 -10800 1 CLST}
+ {605674800 -14400 0 CLT}
+ {624427200 -10800 1 CLST}
+ {637729200 -14400 0 CLT}
+ {653457600 -10800 1 CLST}
+ {668574000 -14400 0 CLT}
+ {687326400 -10800 1 CLST}
+ {700628400 -14400 0 CLT}
+ {718776000 -10800 1 CLST}
+ {732078000 -14400 0 CLT}
+ {750225600 -10800 1 CLST}
+ {763527600 -14400 0 CLT}
+ {781675200 -10800 1 CLST}
+ {794977200 -14400 0 CLT}
+ {813729600 -10800 1 CLST}
+ {826426800 -14400 0 CLT}
+ {845179200 -10800 1 CLST}
+ {859690800 -14400 0 CLT}
+ {876628800 -10800 1 CLST}
+ {889930800 -14400 0 CLT}
+ {906868800 -10800 1 CLST}
+ {923194800 -14400 0 CLT}
+ {939528000 -10800 1 CLST}
+ {952830000 -14400 0 CLT}
+ {971582400 -10800 1 CLST}
+ {984279600 -14400 0 CLT}
+ {1003032000 -10800 1 CLST}
+ {1015729200 -14400 0 CLT}
+ {1034481600 -10800 1 CLST}
+ {1047178800 -14400 0 CLT}
+ {1065931200 -10800 1 CLST}
+ {1079233200 -14400 0 CLT}
+ {1097380800 -10800 1 CLST}
+ {1110682800 -14400 0 CLT}
+ {1128830400 -10800 1 CLST}
+ {1142132400 -14400 0 CLT}
+ {1160884800 -10800 1 CLST}
+ {1173582000 -14400 0 CLT}
+ {1192334400 -10800 1 CLST}
+ {1205031600 -14400 0 CLT}
+ {1223784000 -10800 1 CLST}
+ {1237086000 -14400 0 CLT}
+ {1255233600 -10800 1 CLST}
+ {1268535600 -14400 0 CLT}
+ {1286683200 -10800 1 CLST}
+ {1299985200 -14400 0 CLT}
+ {1318132800 -10800 1 CLST}
+ {1331434800 -14400 0 CLT}
+ {1350187200 -10800 1 CLST}
+ {1362884400 -14400 0 CLT}
+ {1381636800 -10800 1 CLST}
+ {1394334000 -14400 0 CLT}
+ {1413086400 -10800 1 CLST}
+ {1426388400 -14400 0 CLT}
+ {1444536000 -10800 1 CLST}
+ {1457838000 -14400 0 CLT}
+ {1475985600 -10800 1 CLST}
+ {1489287600 -14400 0 CLT}
+ {1508040000 -10800 1 CLST}
+ {1520737200 -14400 0 CLT}
+ {1539489600 -10800 1 CLST}
+ {1552186800 -14400 0 CLT}
+ {1570939200 -10800 1 CLST}
+ {1584241200 -14400 0 CLT}
+ {1602388800 -10800 1 CLST}
+ {1615690800 -14400 0 CLT}
+ {1633838400 -10800 1 CLST}
+ {1647140400 -14400 0 CLT}
+ {1665288000 -10800 1 CLST}
+ {1678590000 -14400 0 CLT}
+ {1697342400 -10800 1 CLST}
+ {1710039600 -14400 0 CLT}
+ {1728792000 -10800 1 CLST}
+ {1741489200 -14400 0 CLT}
+ {1760241600 -10800 1 CLST}
+ {1773543600 -14400 0 CLT}
+ {1791691200 -10800 1 CLST}
+ {1804993200 -14400 0 CLT}
+ {1823140800 -10800 1 CLST}
+ {1836442800 -14400 0 CLT}
+ {1855195200 -10800 1 CLST}
+ {1867892400 -14400 0 CLT}
+ {1886644800 -10800 1 CLST}
+ {1899342000 -14400 0 CLT}
+ {1918094400 -10800 1 CLST}
+ {1930791600 -14400 0 CLT}
+ {1949544000 -10800 1 CLST}
+ {1962846000 -14400 0 CLT}
+ {1980993600 -10800 1 CLST}
+ {1994295600 -14400 0 CLT}
+ {2012443200 -10800 1 CLST}
+ {2025745200 -14400 0 CLT}
+ {2044497600 -10800 1 CLST}
+ {2057194800 -14400 0 CLT}
+ {2075947200 -10800 1 CLST}
+ {2088644400 -14400 0 CLT}
+ {2107396800 -10800 1 CLST}
+ {2120698800 -14400 0 CLT}
+ {2138846400 -10800 1 CLST}
+ {2152148400 -14400 0 CLT}
+ {2170296000 -10800 1 CLST}
+ {2183598000 -14400 0 CLT}
+ {2201745600 -10800 1 CLST}
+ {2215047600 -14400 0 CLT}
+ {2233800000 -10800 1 CLST}
+ {2246497200 -14400 0 CLT}
+ {2265249600 -10800 1 CLST}
+ {2277946800 -14400 0 CLT}
+ {2296699200 -10800 1 CLST}
+ {2310001200 -14400 0 CLT}
+ {2328148800 -10800 1 CLST}
+ {2341450800 -14400 0 CLT}
+ {2359598400 -10800 1 CLST}
+ {2372900400 -14400 0 CLT}
+ {2391652800 -10800 1 CLST}
+ {2404350000 -14400 0 CLT}
+ {2423102400 -10800 1 CLST}
+ {2435799600 -14400 0 CLT}
+ {2454552000 -10800 1 CLST}
+ {2467854000 -14400 0 CLT}
+ {2486001600 -10800 1 CLST}
+ {2499303600 -14400 0 CLT}
+ {2517451200 -10800 1 CLST}
+ {2530753200 -14400 0 CLT}
+ {2548900800 -10800 1 CLST}
+ {2562202800 -14400 0 CLT}
+ {2580955200 -10800 1 CLST}
+ {2593652400 -14400 0 CLT}
+ {2612404800 -10800 1 CLST}
+ {2625102000 -14400 0 CLT}
+ {2643854400 -10800 1 CLST}
+ {2657156400 -14400 0 CLT}
+ {2675304000 -10800 1 CLST}
+ {2688606000 -14400 0 CLT}
+ {2706753600 -10800 1 CLST}
+ {2720055600 -14400 0 CLT}
+ {2738808000 -10800 1 CLST}
+ {2751505200 -14400 0 CLT}
+ {2770257600 -10800 1 CLST}
+ {2782954800 -14400 0 CLT}
+ {2801707200 -10800 1 CLST}
+ {2814404400 -14400 0 CLT}
+ {2833156800 -10800 1 CLST}
+ {2846458800 -14400 0 CLT}
+ {2864606400 -10800 1 CLST}
+ {2877908400 -14400 0 CLT}
+ {2896056000 -10800 1 CLST}
+ {2909358000 -14400 0 CLT}
+ {2928110400 -10800 1 CLST}
+ {2940807600 -14400 0 CLT}
+ {2959560000 -10800 1 CLST}
+ {2972257200 -14400 0 CLT}
+ {2991009600 -10800 1 CLST}
+ {3004311600 -14400 0 CLT}
+ {3022459200 -10800 1 CLST}
+ {3035761200 -14400 0 CLT}
+ {3053908800 -10800 1 CLST}
+ {3067210800 -14400 0 CLT}
+ {3085358400 -10800 1 CLST}
+ {3098660400 -14400 0 CLT}
+ {3117412800 -10800 1 CLST}
+ {3130110000 -14400 0 CLT}
+ {3148862400 -10800 1 CLST}
+ {3161559600 -14400 0 CLT}
+ {3180312000 -10800 1 CLST}
+ {3193614000 -14400 0 CLT}
+ {3211761600 -10800 1 CLST}
+ {3225063600 -14400 0 CLT}
+ {3243211200 -10800 1 CLST}
+ {3256513200 -14400 0 CLT}
+ {3275265600 -10800 1 CLST}
+ {3287962800 -14400 0 CLT}
+ {3306715200 -10800 1 CLST}
+ {3319412400 -14400 0 CLT}
+ {3338164800 -10800 1 CLST}
+ {3351466800 -14400 0 CLT}
+ {3369614400 -10800 1 CLST}
+ {3382916400 -14400 0 CLT}
+ {3401064000 -10800 1 CLST}
+ {3414366000 -14400 0 CLT}
+ {3432513600 -10800 1 CLST}
+ {3445815600 -14400 0 CLT}
+ {3464568000 -10800 1 CLST}
+ {3477265200 -14400 0 CLT}
+ {3496017600 -10800 1 CLST}
+ {3508714800 -14400 0 CLT}
+ {3527467200 -10800 1 CLST}
+ {3540769200 -14400 0 CLT}
+ {3558916800 -10800 1 CLST}
+ {3572218800 -14400 0 CLT}
+ {3590366400 -10800 1 CLST}
+ {3603668400 -14400 0 CLT}
+ {3622420800 -10800 1 CLST}
+ {3635118000 -14400 0 CLT}
+ {3653870400 -10800 1 CLST}
+ {3666567600 -14400 0 CLT}
+ {3685320000 -10800 1 CLST}
+ {3698017200 -14400 0 CLT}
+ {3716769600 -10800 1 CLST}
+ {3730071600 -14400 0 CLT}
+ {3748219200 -10800 1 CLST}
+ {3761521200 -14400 0 CLT}
+ {3779668800 -10800 1 CLST}
+ {3792970800 -14400 0 CLT}
+ {3811723200 -10800 1 CLST}
+ {3824420400 -14400 0 CLT}
+ {3843172800 -10800 1 CLST}
+ {3855870000 -14400 0 CLT}
+ {3874622400 -10800 1 CLST}
+ {3887924400 -14400 0 CLT}
+ {3906072000 -10800 1 CLST}
+ {3919374000 -14400 0 CLT}
+ {3937521600 -10800 1 CLST}
+ {3950823600 -14400 0 CLT}
+ {3968971200 -10800 1 CLST}
+ {3982273200 -14400 0 CLT}
+ {4001025600 -10800 1 CLST}
+ {4013722800 -14400 0 CLT}
+ {4032475200 -10800 1 CLST}
+ {4045172400 -14400 0 CLT}
+ {4063924800 -10800 1 CLST}
+ {4077226800 -14400 0 CLT}
+ {4095374400 -10800 1 CLST}
+}
diff --git a/library/tzdata/Antarctica/Rothera b/library/tzdata/Antarctica/Rothera
new file mode 100644
index 0000000..24d7f3e
--- /dev/null
+++ b/library/tzdata/Antarctica/Rothera
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Antarctica/Rothera) {
+ {-9223372036854775808 0 0 zzz}
+ {218246400 -10800 0 ROTT}
+}
diff --git a/library/tzdata/Antarctica/South_Pole b/library/tzdata/Antarctica/South_Pole
new file mode 100644
index 0000000..34d0db1
--- /dev/null
+++ b/library/tzdata/Antarctica/South_Pole
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Antarctica/McMurdo)]} {
+ LoadTimeZoneFile Antarctica/McMurdo
+}
+set TZData(:Antarctica/South_Pole) $TZData(:Antarctica/McMurdo)
diff --git a/library/tzdata/Antarctica/Syowa b/library/tzdata/Antarctica/Syowa
new file mode 100644
index 0000000..4d046b5
--- /dev/null
+++ b/library/tzdata/Antarctica/Syowa
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Antarctica/Syowa) {
+ {-9223372036854775808 0 0 zzz}
+ {-407808000 10800 0 SYOT}
+}
diff --git a/library/tzdata/Antarctica/Vostok b/library/tzdata/Antarctica/Vostok
new file mode 100644
index 0000000..f846f65
--- /dev/null
+++ b/library/tzdata/Antarctica/Vostok
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Antarctica/Vostok) {
+ {-9223372036854775808 0 0 zzz}
+ {-380073600 21600 0 VOST}
+}
diff --git a/library/tzdata/Arctic/Longyearbyen b/library/tzdata/Arctic/Longyearbyen
new file mode 100644
index 0000000..51f83dc
--- /dev/null
+++ b/library/tzdata/Arctic/Longyearbyen
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/Oslo)]} {
+ LoadTimeZoneFile Europe/Oslo
+}
+set TZData(:Arctic/Longyearbyen) $TZData(:Europe/Oslo)
diff --git a/library/tzdata/Asia/Aden b/library/tzdata/Asia/Aden
new file mode 100644
index 0000000..e939235
--- /dev/null
+++ b/library/tzdata/Asia/Aden
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Aden) {
+ {-9223372036854775808 10848 0 LMT}
+ {-631162848 10800 0 AST}
+}
diff --git a/library/tzdata/Asia/Almaty b/library/tzdata/Asia/Almaty
new file mode 100644
index 0000000..68dee29
--- /dev/null
+++ b/library/tzdata/Asia/Almaty
@@ -0,0 +1,56 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Almaty) {
+ {-9223372036854775808 18468 0 LMT}
+ {-1441170468 18000 0 ALMT}
+ {-1247547600 21600 0 ALMT}
+ {354909600 25200 1 ALMST}
+ {370717200 21600 0 ALMT}
+ {386445600 25200 1 ALMST}
+ {402253200 21600 0 ALMT}
+ {417981600 25200 1 ALMST}
+ {433789200 21600 0 ALMT}
+ {449604000 25200 1 ALMST}
+ {465336000 21600 0 ALMT}
+ {481060800 25200 1 ALMST}
+ {496785600 21600 0 ALMT}
+ {512510400 25200 1 ALMST}
+ {528235200 21600 0 ALMT}
+ {543960000 25200 1 ALMST}
+ {559684800 21600 0 ALMT}
+ {575409600 25200 1 ALMST}
+ {591134400 21600 0 ALMT}
+ {606859200 25200 1 ALMST}
+ {622584000 21600 0 ALMT}
+ {638308800 25200 1 ALMST}
+ {654638400 21600 0 ALMT}
+ {662666400 21600 0 ALMT}
+ {694202400 21600 0 ALMT}
+ {701802000 25200 1 ALMST}
+ {717523200 21600 0 ALMT}
+ {733262400 25200 1 ALMST}
+ {748987200 21600 0 ALMT}
+ {764712000 25200 1 ALMST}
+ {780436800 21600 0 ALMT}
+ {796161600 25200 1 ALMST}
+ {811886400 21600 0 ALMT}
+ {828216000 25200 1 ALMST}
+ {846360000 21600 0 ALMT}
+ {859665600 25200 1 ALMST}
+ {877809600 21600 0 ALMT}
+ {891115200 25200 1 ALMST}
+ {909259200 21600 0 ALMT}
+ {922564800 25200 1 ALMST}
+ {941313600 21600 0 ALMT}
+ {954014400 25200 1 ALMST}
+ {972763200 21600 0 ALMT}
+ {985464000 25200 1 ALMST}
+ {1004212800 21600 0 ALMT}
+ {1017518400 25200 1 ALMST}
+ {1035662400 21600 0 ALMT}
+ {1048968000 25200 1 ALMST}
+ {1067112000 21600 0 ALMT}
+ {1080417600 25200 1 ALMST}
+ {1099166400 21600 0 ALMT}
+ {1110823200 21600 0 ALMT}
+}
diff --git a/library/tzdata/Asia/Amman b/library/tzdata/Asia/Amman
new file mode 100644
index 0000000..bf30508
--- /dev/null
+++ b/library/tzdata/Asia/Amman
@@ -0,0 +1,248 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Amman) {
+ {-9223372036854775808 8624 0 LMT}
+ {-1230776624 7200 0 EET}
+ {108165600 10800 1 EEST}
+ {118270800 7200 0 EET}
+ {136591200 10800 1 EEST}
+ {149806800 7200 0 EET}
+ {168127200 10800 1 EEST}
+ {181342800 7200 0 EET}
+ {199749600 10800 1 EEST}
+ {215643600 7200 0 EET}
+ {231285600 10800 1 EEST}
+ {244501200 7200 0 EET}
+ {262735200 10800 1 EEST}
+ {275950800 7200 0 EET}
+ {481154400 10800 1 EEST}
+ {496962000 7200 0 EET}
+ {512949600 10800 1 EEST}
+ {528670800 7200 0 EET}
+ {544399200 10800 1 EEST}
+ {560120400 7200 0 EET}
+ {575848800 10800 1 EEST}
+ {592174800 7200 0 EET}
+ {610581600 10800 1 EEST}
+ {623624400 7200 0 EET}
+ {641167200 10800 1 EEST}
+ {655074000 7200 0 EET}
+ {671839200 10800 1 EEST}
+ {685918800 7200 0 EET}
+ {702856800 10800 1 EEST}
+ {717973200 7200 0 EET}
+ {733701600 10800 1 EEST}
+ {749422800 7200 0 EET}
+ {765151200 10800 1 EEST}
+ {779662800 7200 0 EET}
+ {797205600 10800 1 EEST}
+ {811116000 7200 0 EET}
+ {828655200 10800 1 EEST}
+ {843170400 7200 0 EET}
+ {860104800 10800 1 EEST}
+ {874620000 7200 0 EET}
+ {891554400 10800 1 EEST}
+ {906069600 7200 0 EET}
+ {930780000 10800 1 EEST}
+ {938124000 7200 0 EET}
+ {954367200 10800 1 EEST}
+ {970178400 7200 0 EET}
+ {985816800 10800 1 EEST}
+ {1001628000 7200 0 EET}
+ {1017352800 10800 1 EEST}
+ {1033077600 7200 0 EET}
+ {1048802400 10800 1 EEST}
+ {1066946400 7200 0 EET}
+ {1080252000 10800 1 EEST}
+ {1097791200 7200 0 EET}
+ {1112306400 10800 1 EEST}
+ {1128031200 7200 0 EET}
+ {1143756000 10800 1 EEST}
+ {1161900000 7200 0 EET}
+ {1175205600 10800 1 EEST}
+ {1193349600 7200 0 EET}
+ {1206655200 10800 1 EEST}
+ {1225404000 7200 0 EET}
+ {1238104800 10800 1 EEST}
+ {1256853600 7200 0 EET}
+ {1269554400 10800 1 EEST}
+ {1288303200 7200 0 EET}
+ {1301608800 10800 1 EEST}
+ {1319752800 7200 0 EET}
+ {1333058400 10800 1 EEST}
+ {1351202400 7200 0 EET}
+ {1364508000 10800 1 EEST}
+ {1382652000 7200 0 EET}
+ {1395957600 10800 1 EEST}
+ {1414706400 7200 0 EET}
+ {1427407200 10800 1 EEST}
+ {1446156000 7200 0 EET}
+ {1459461600 10800 1 EEST}
+ {1477605600 7200 0 EET}
+ {1490911200 10800 1 EEST}
+ {1509055200 7200 0 EET}
+ {1522360800 10800 1 EEST}
+ {1540504800 7200 0 EET}
+ {1553810400 10800 1 EEST}
+ {1571954400 7200 0 EET}
+ {1585260000 10800 1 EEST}
+ {1604008800 7200 0 EET}
+ {1616709600 10800 1 EEST}
+ {1635458400 7200 0 EET}
+ {1648764000 10800 1 EEST}
+ {1666908000 7200 0 EET}
+ {1680213600 10800 1 EEST}
+ {1698357600 7200 0 EET}
+ {1711663200 10800 1 EEST}
+ {1729807200 7200 0 EET}
+ {1743112800 10800 1 EEST}
+ {1761861600 7200 0 EET}
+ {1774562400 10800 1 EEST}
+ {1793311200 7200 0 EET}
+ {1806012000 10800 1 EEST}
+ {1824760800 7200 0 EET}
+ {1838066400 10800 1 EEST}
+ {1856210400 7200 0 EET}
+ {1869516000 10800 1 EEST}
+ {1887660000 7200 0 EET}
+ {1900965600 10800 1 EEST}
+ {1919109600 7200 0 EET}
+ {1932415200 10800 1 EEST}
+ {1951164000 7200 0 EET}
+ {1963864800 10800 1 EEST}
+ {1982613600 7200 0 EET}
+ {1995919200 10800 1 EEST}
+ {2014063200 7200 0 EET}
+ {2027368800 10800 1 EEST}
+ {2045512800 7200 0 EET}
+ {2058818400 10800 1 EEST}
+ {2076962400 7200 0 EET}
+ {2090268000 10800 1 EEST}
+ {2109016800 7200 0 EET}
+ {2121717600 10800 1 EEST}
+ {2140466400 7200 0 EET}
+ {2153167200 10800 1 EEST}
+ {2171916000 7200 0 EET}
+ {2185221600 10800 1 EEST}
+ {2203365600 7200 0 EET}
+ {2216671200 10800 1 EEST}
+ {2234815200 7200 0 EET}
+ {2248120800 10800 1 EEST}
+ {2266264800 7200 0 EET}
+ {2279570400 10800 1 EEST}
+ {2298319200 7200 0 EET}
+ {2311020000 10800 1 EEST}
+ {2329768800 7200 0 EET}
+ {2343074400 10800 1 EEST}
+ {2361218400 7200 0 EET}
+ {2374524000 10800 1 EEST}
+ {2392668000 7200 0 EET}
+ {2405973600 10800 1 EEST}
+ {2424117600 7200 0 EET}
+ {2437423200 10800 1 EEST}
+ {2455567200 7200 0 EET}
+ {2468872800 10800 1 EEST}
+ {2487621600 7200 0 EET}
+ {2500322400 10800 1 EEST}
+ {2519071200 7200 0 EET}
+ {2532376800 10800 1 EEST}
+ {2550520800 7200 0 EET}
+ {2563826400 10800 1 EEST}
+ {2581970400 7200 0 EET}
+ {2595276000 10800 1 EEST}
+ {2613420000 7200 0 EET}
+ {2626725600 10800 1 EEST}
+ {2645474400 7200 0 EET}
+ {2658175200 10800 1 EEST}
+ {2676924000 7200 0 EET}
+ {2689624800 10800 1 EEST}
+ {2708373600 7200 0 EET}
+ {2721679200 10800 1 EEST}
+ {2739823200 7200 0 EET}
+ {2753128800 10800 1 EEST}
+ {2771272800 7200 0 EET}
+ {2784578400 10800 1 EEST}
+ {2802722400 7200 0 EET}
+ {2816028000 10800 1 EEST}
+ {2834776800 7200 0 EET}
+ {2847477600 10800 1 EEST}
+ {2866226400 7200 0 EET}
+ {2879532000 10800 1 EEST}
+ {2897676000 7200 0 EET}
+ {2910981600 10800 1 EEST}
+ {2929125600 7200 0 EET}
+ {2942431200 10800 1 EEST}
+ {2960575200 7200 0 EET}
+ {2973880800 10800 1 EEST}
+ {2992629600 7200 0 EET}
+ {3005330400 10800 1 EEST}
+ {3024079200 7200 0 EET}
+ {3036780000 10800 1 EEST}
+ {3055528800 7200 0 EET}
+ {3068834400 10800 1 EEST}
+ {3086978400 7200 0 EET}
+ {3100284000 10800 1 EEST}
+ {3118428000 7200 0 EET}
+ {3131733600 10800 1 EEST}
+ {3149877600 7200 0 EET}
+ {3163183200 10800 1 EEST}
+ {3181932000 7200 0 EET}
+ {3194632800 10800 1 EEST}
+ {3213381600 7200 0 EET}
+ {3226687200 10800 1 EEST}
+ {3244831200 7200 0 EET}
+ {3258136800 10800 1 EEST}
+ {3276280800 7200 0 EET}
+ {3289586400 10800 1 EEST}
+ {3307730400 7200 0 EET}
+ {3321036000 10800 1 EEST}
+ {3339180000 7200 0 EET}
+ {3352485600 10800 1 EEST}
+ {3371234400 7200 0 EET}
+ {3383935200 10800 1 EEST}
+ {3402684000 7200 0 EET}
+ {3415989600 10800 1 EEST}
+ {3434133600 7200 0 EET}
+ {3447439200 10800 1 EEST}
+ {3465583200 7200 0 EET}
+ {3478888800 10800 1 EEST}
+ {3497032800 7200 0 EET}
+ {3510338400 10800 1 EEST}
+ {3529087200 7200 0 EET}
+ {3541788000 10800 1 EEST}
+ {3560536800 7200 0 EET}
+ {3573237600 10800 1 EEST}
+ {3591986400 7200 0 EET}
+ {3605292000 10800 1 EEST}
+ {3623436000 7200 0 EET}
+ {3636741600 10800 1 EEST}
+ {3654885600 7200 0 EET}
+ {3668191200 10800 1 EEST}
+ {3686335200 7200 0 EET}
+ {3699640800 10800 1 EEST}
+ {3718389600 7200 0 EET}
+ {3731090400 10800 1 EEST}
+ {3749839200 7200 0 EET}
+ {3763144800 10800 1 EEST}
+ {3781288800 7200 0 EET}
+ {3794594400 10800 1 EEST}
+ {3812738400 7200 0 EET}
+ {3826044000 10800 1 EEST}
+ {3844188000 7200 0 EET}
+ {3857493600 10800 1 EEST}
+ {3876242400 7200 0 EET}
+ {3888943200 10800 1 EEST}
+ {3907692000 7200 0 EET}
+ {3920392800 10800 1 EEST}
+ {3939141600 7200 0 EET}
+ {3952447200 10800 1 EEST}
+ {3970591200 7200 0 EET}
+ {3983896800 10800 1 EEST}
+ {4002040800 7200 0 EET}
+ {4015346400 10800 1 EEST}
+ {4033490400 7200 0 EET}
+ {4046796000 10800 1 EEST}
+ {4065544800 7200 0 EET}
+ {4078245600 10800 1 EEST}
+ {4096994400 7200 0 EET}
+}
diff --git a/library/tzdata/Asia/Anadyr b/library/tzdata/Asia/Anadyr
new file mode 100644
index 0000000..50ace50
--- /dev/null
+++ b/library/tzdata/Asia/Anadyr
@@ -0,0 +1,72 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Anadyr) {
+ {-9223372036854775808 42596 0 LMT}
+ {-1441194596 43200 0 ANAT}
+ {-1247572800 46800 0 ANAMMTT}
+ {354884400 50400 1 ANAST}
+ {370692000 46800 0 ANAT}
+ {386420400 43200 0 ANAMMTT}
+ {386424000 46800 1 ANAST}
+ {402231600 43200 0 ANAT}
+ {417960000 46800 1 ANAST}
+ {433767600 43200 0 ANAT}
+ {449582400 46800 1 ANAST}
+ {465314400 43200 0 ANAT}
+ {481039200 46800 1 ANAST}
+ {496764000 43200 0 ANAT}
+ {512488800 46800 1 ANAST}
+ {528213600 43200 0 ANAT}
+ {543938400 46800 1 ANAST}
+ {559663200 43200 0 ANAT}
+ {575388000 46800 1 ANAST}
+ {591112800 43200 0 ANAT}
+ {606837600 46800 1 ANAST}
+ {622562400 43200 0 ANAT}
+ {638287200 46800 1 ANAST}
+ {654616800 43200 0 ANAT}
+ {670341600 39600 0 ANAMMTT}
+ {670345200 43200 1 ANAST}
+ {686070000 39600 0 ANAT}
+ {695746800 43200 0 ANAMMTT}
+ {701780400 46800 1 ANAST}
+ {717501600 43200 0 ANAT}
+ {733240800 46800 1 ANAST}
+ {748965600 43200 0 ANAT}
+ {764690400 46800 1 ANAST}
+ {780415200 43200 0 ANAT}
+ {796140000 46800 1 ANAST}
+ {811864800 43200 0 ANAT}
+ {828194400 46800 1 ANAST}
+ {846338400 43200 0 ANAT}
+ {859644000 46800 1 ANAST}
+ {877788000 43200 0 ANAT}
+ {891093600 46800 1 ANAST}
+ {909237600 43200 0 ANAT}
+ {922543200 46800 1 ANAST}
+ {941292000 43200 0 ANAT}
+ {953992800 46800 1 ANAST}
+ {972741600 43200 0 ANAT}
+ {985442400 46800 1 ANAST}
+ {1004191200 43200 0 ANAT}
+ {1017496800 46800 1 ANAST}
+ {1035640800 43200 0 ANAT}
+ {1048946400 46800 1 ANAST}
+ {1067090400 43200 0 ANAT}
+ {1080396000 46800 1 ANAST}
+ {1099144800 43200 0 ANAT}
+ {1111845600 46800 1 ANAST}
+ {1130594400 43200 0 ANAT}
+ {1143295200 46800 1 ANAST}
+ {1162044000 43200 0 ANAT}
+ {1174744800 46800 1 ANAST}
+ {1193493600 43200 0 ANAT}
+ {1206799200 46800 1 ANAST}
+ {1224943200 43200 0 ANAT}
+ {1238248800 46800 1 ANAST}
+ {1256392800 43200 0 ANAT}
+ {1269698400 39600 0 ANAMMTT}
+ {1269702000 43200 1 ANAST}
+ {1288450800 39600 0 ANAT}
+ {1301151600 43200 0 ANAT}
+}
diff --git a/library/tzdata/Asia/Aqtau b/library/tzdata/Asia/Aqtau
new file mode 100644
index 0000000..11e89a2
--- /dev/null
+++ b/library/tzdata/Asia/Aqtau
@@ -0,0 +1,58 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Aqtau) {
+ {-9223372036854775808 12064 0 LMT}
+ {-1441164064 14400 0 FORT}
+ {-1247544000 18000 0 FORT}
+ {-220942800 18000 0 SHET}
+ {370724400 21600 0 SHET}
+ {386445600 18000 0 SHET}
+ {386449200 21600 1 SHEST}
+ {402256800 18000 0 SHET}
+ {417985200 21600 1 SHEST}
+ {433792800 18000 0 SHET}
+ {449607600 21600 1 SHEST}
+ {465339600 18000 0 SHET}
+ {481064400 21600 1 SHEST}
+ {496789200 18000 0 SHET}
+ {512514000 21600 1 SHEST}
+ {528238800 18000 0 SHET}
+ {543963600 21600 1 SHEST}
+ {559688400 18000 0 SHET}
+ {575413200 21600 1 SHEST}
+ {591138000 18000 0 SHET}
+ {606862800 21600 1 SHEST}
+ {622587600 18000 0 SHET}
+ {638312400 21600 1 SHEST}
+ {654642000 18000 0 SHET}
+ {662670000 18000 0 SHET}
+ {692823600 18000 0 AQTT}
+ {701805600 21600 1 AQTST}
+ {717526800 18000 0 AQTT}
+ {733266000 21600 1 AQTST}
+ {748990800 18000 0 AQTT}
+ {764715600 21600 1 AQTST}
+ {780440400 18000 0 AQTT}
+ {796165200 14400 0 AQTT}
+ {796168800 18000 1 AQTST}
+ {811893600 14400 0 AQTT}
+ {828223200 18000 1 AQTST}
+ {846367200 14400 0 AQTT}
+ {859672800 18000 1 AQTST}
+ {877816800 14400 0 AQTT}
+ {891122400 18000 1 AQTST}
+ {909266400 14400 0 AQTT}
+ {922572000 18000 1 AQTST}
+ {941320800 14400 0 AQTT}
+ {954021600 18000 1 AQTST}
+ {972770400 14400 0 AQTT}
+ {985471200 18000 1 AQTST}
+ {1004220000 14400 0 AQTT}
+ {1017525600 18000 1 AQTST}
+ {1035669600 14400 0 AQTT}
+ {1048975200 18000 1 AQTST}
+ {1067119200 14400 0 AQTT}
+ {1080424800 18000 1 AQTST}
+ {1099173600 14400 0 AQTT}
+ {1110830400 18000 0 AQTT}
+}
diff --git a/library/tzdata/Asia/Aqtobe b/library/tzdata/Asia/Aqtobe
new file mode 100644
index 0000000..c857491
--- /dev/null
+++ b/library/tzdata/Asia/Aqtobe
@@ -0,0 +1,57 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Aqtobe) {
+ {-9223372036854775808 13720 0 LMT}
+ {-1441165720 14400 0 AKTT}
+ {-1247544000 18000 0 AKTT}
+ {354913200 21600 1 AKTST}
+ {370720800 21600 0 AKTT}
+ {386445600 18000 0 AKTT}
+ {386449200 21600 1 AKTST}
+ {402256800 18000 0 AKTT}
+ {417985200 21600 1 AKTST}
+ {433792800 18000 0 AKTT}
+ {449607600 21600 1 AKTST}
+ {465339600 18000 0 AKTT}
+ {481064400 21600 1 AKTST}
+ {496789200 18000 0 AKTT}
+ {512514000 21600 1 AKTST}
+ {528238800 18000 0 AKTT}
+ {543963600 21600 1 AKTST}
+ {559688400 18000 0 AKTT}
+ {575413200 21600 1 AKTST}
+ {591138000 18000 0 AKTT}
+ {606862800 21600 1 AKTST}
+ {622587600 18000 0 AKTT}
+ {638312400 21600 1 AKTST}
+ {654642000 18000 0 AKTT}
+ {662670000 18000 0 AKTT}
+ {692823600 18000 0 AQTT}
+ {701805600 21600 1 AQTST}
+ {717526800 18000 0 AQTT}
+ {733266000 21600 1 AQTST}
+ {748990800 18000 0 AQTT}
+ {764715600 21600 1 AQTST}
+ {780440400 18000 0 AQTT}
+ {796165200 21600 1 AQTST}
+ {811890000 18000 0 AQTT}
+ {828219600 21600 1 AQTST}
+ {846363600 18000 0 AQTT}
+ {859669200 21600 1 AQTST}
+ {877813200 18000 0 AQTT}
+ {891118800 21600 1 AQTST}
+ {909262800 18000 0 AQTT}
+ {922568400 21600 1 AQTST}
+ {941317200 18000 0 AQTT}
+ {954018000 21600 1 AQTST}
+ {972766800 18000 0 AQTT}
+ {985467600 21600 1 AQTST}
+ {1004216400 18000 0 AQTT}
+ {1017522000 21600 1 AQTST}
+ {1035666000 18000 0 AQTT}
+ {1048971600 21600 1 AQTST}
+ {1067115600 18000 0 AQTT}
+ {1080421200 21600 1 AQTST}
+ {1099170000 18000 0 AQTT}
+ {1110826800 18000 0 AQTT}
+}
diff --git a/library/tzdata/Asia/Ashgabat b/library/tzdata/Asia/Ashgabat
new file mode 100644
index 0000000..64bdb3a
--- /dev/null
+++ b/library/tzdata/Asia/Ashgabat
@@ -0,0 +1,31 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Ashgabat) {
+ {-9223372036854775808 14012 0 LMT}
+ {-1441166012 14400 0 ASHT}
+ {-1247544000 18000 0 ASHT}
+ {354913200 21600 1 ASHST}
+ {370720800 18000 0 ASHT}
+ {386449200 21600 1 ASHST}
+ {402256800 18000 0 ASHT}
+ {417985200 21600 1 ASHST}
+ {433792800 18000 0 ASHT}
+ {449607600 21600 1 ASHST}
+ {465339600 18000 0 ASHT}
+ {481064400 21600 1 ASHST}
+ {496789200 18000 0 ASHT}
+ {512514000 21600 1 ASHST}
+ {528238800 18000 0 ASHT}
+ {543963600 21600 1 ASHST}
+ {559688400 18000 0 ASHT}
+ {575413200 21600 1 ASHST}
+ {591138000 18000 0 ASHT}
+ {606862800 21600 1 ASHST}
+ {622587600 18000 0 ASHT}
+ {638312400 21600 1 ASHST}
+ {654642000 18000 0 ASHT}
+ {670366800 14400 0 ASHT}
+ {670370400 18000 1 ASHST}
+ {686095200 14400 0 ASHT}
+ {695772000 18000 0 TMT}
+}
diff --git a/library/tzdata/Asia/Ashkhabad b/library/tzdata/Asia/Ashkhabad
new file mode 100644
index 0000000..3000c94
--- /dev/null
+++ b/library/tzdata/Asia/Ashkhabad
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Asia/Ashgabat)]} {
+ LoadTimeZoneFile Asia/Ashgabat
+}
+set TZData(:Asia/Ashkhabad) $TZData(:Asia/Ashgabat)
diff --git a/library/tzdata/Asia/Baghdad b/library/tzdata/Asia/Baghdad
new file mode 100644
index 0000000..c1058cb
--- /dev/null
+++ b/library/tzdata/Asia/Baghdad
@@ -0,0 +1,59 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Baghdad) {
+ {-9223372036854775808 10660 0 LMT}
+ {-2524532260 10656 0 BMT}
+ {-1641005856 10800 0 AST}
+ {389048400 14400 0 ADT}
+ {402264000 10800 0 AST}
+ {417906000 14400 1 ADT}
+ {433800000 10800 0 AST}
+ {449614800 14400 1 ADT}
+ {465422400 10800 0 AST}
+ {481150800 14400 1 ADT}
+ {496792800 10800 0 AST}
+ {512517600 14400 1 ADT}
+ {528242400 10800 0 AST}
+ {543967200 14400 1 ADT}
+ {559692000 10800 0 AST}
+ {575416800 14400 1 ADT}
+ {591141600 10800 0 AST}
+ {606866400 14400 1 ADT}
+ {622591200 10800 0 AST}
+ {638316000 14400 1 ADT}
+ {654645600 10800 0 AST}
+ {670464000 14400 1 ADT}
+ {686275200 10800 0 AST}
+ {702086400 14400 1 ADT}
+ {717897600 10800 0 AST}
+ {733622400 14400 1 ADT}
+ {749433600 10800 0 AST}
+ {765158400 14400 1 ADT}
+ {780969600 10800 0 AST}
+ {796694400 14400 1 ADT}
+ {812505600 10800 0 AST}
+ {828316800 14400 1 ADT}
+ {844128000 10800 0 AST}
+ {859852800 14400 1 ADT}
+ {875664000 10800 0 AST}
+ {891388800 14400 1 ADT}
+ {907200000 10800 0 AST}
+ {922924800 14400 1 ADT}
+ {938736000 10800 0 AST}
+ {954547200 14400 1 ADT}
+ {970358400 10800 0 AST}
+ {986083200 14400 1 ADT}
+ {1001894400 10800 0 AST}
+ {1017619200 14400 1 ADT}
+ {1033430400 10800 0 AST}
+ {1049155200 14400 1 ADT}
+ {1064966400 10800 0 AST}
+ {1080777600 14400 1 ADT}
+ {1096588800 10800 0 AST}
+ {1112313600 14400 1 ADT}
+ {1128124800 10800 0 AST}
+ {1143849600 14400 1 ADT}
+ {1159660800 10800 0 AST}
+ {1175385600 14400 1 ADT}
+ {1191196800 10800 0 AST}
+}
diff --git a/library/tzdata/Asia/Bahrain b/library/tzdata/Asia/Bahrain
new file mode 100644
index 0000000..d4b7d2c
--- /dev/null
+++ b/library/tzdata/Asia/Bahrain
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Bahrain) {
+ {-9223372036854775808 12140 0 LMT}
+ {-1577935340 14400 0 GST}
+ {76190400 10800 0 AST}
+}
diff --git a/library/tzdata/Asia/Baku b/library/tzdata/Asia/Baku
new file mode 100644
index 0000000..e50071b
--- /dev/null
+++ b/library/tzdata/Asia/Baku
@@ -0,0 +1,242 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Baku) {
+ {-9223372036854775808 11964 0 LMT}
+ {-1441163964 10800 0 BAKT}
+ {-405140400 14400 0 BAKT}
+ {354916800 18000 1 BAKST}
+ {370724400 14400 0 BAKT}
+ {386452800 18000 1 BAKST}
+ {402260400 14400 0 BAKT}
+ {417988800 18000 1 BAKST}
+ {433796400 14400 0 BAKT}
+ {449611200 18000 1 BAKST}
+ {465343200 14400 0 BAKT}
+ {481068000 18000 1 BAKST}
+ {496792800 14400 0 BAKT}
+ {512517600 18000 1 BAKST}
+ {528242400 14400 0 BAKT}
+ {543967200 18000 1 BAKST}
+ {559692000 14400 0 BAKT}
+ {575416800 18000 1 BAKST}
+ {591141600 14400 0 BAKT}
+ {606866400 18000 1 BAKST}
+ {622591200 14400 0 BAKT}
+ {638316000 18000 1 BAKST}
+ {654645600 14400 0 BAKT}
+ {670370400 14400 1 BAKST}
+ {683496000 14400 0 AZST}
+ {686098800 10800 0 AZT}
+ {701812800 14400 1 AZST}
+ {717537600 14400 0 AZT}
+ {820440000 14400 0 AZT}
+ {828234000 18000 1 AZST}
+ {846378000 14400 0 AZT}
+ {852062400 14400 0 AZT}
+ {859680000 18000 1 AZST}
+ {877824000 14400 0 AZT}
+ {891129600 18000 1 AZST}
+ {909273600 14400 0 AZT}
+ {922579200 18000 1 AZST}
+ {941328000 14400 0 AZT}
+ {954028800 18000 1 AZST}
+ {972777600 14400 0 AZT}
+ {985478400 18000 1 AZST}
+ {1004227200 14400 0 AZT}
+ {1017532800 18000 1 AZST}
+ {1035676800 14400 0 AZT}
+ {1048982400 18000 1 AZST}
+ {1067126400 14400 0 AZT}
+ {1080432000 18000 1 AZST}
+ {1099180800 14400 0 AZT}
+ {1111881600 18000 1 AZST}
+ {1130630400 14400 0 AZT}
+ {1143331200 18000 1 AZST}
+ {1162080000 14400 0 AZT}
+ {1174780800 18000 1 AZST}
+ {1193529600 14400 0 AZT}
+ {1206835200 18000 1 AZST}
+ {1224979200 14400 0 AZT}
+ {1238284800 18000 1 AZST}
+ {1256428800 14400 0 AZT}
+ {1269734400 18000 1 AZST}
+ {1288483200 14400 0 AZT}
+ {1301184000 18000 1 AZST}
+ {1319932800 14400 0 AZT}
+ {1332633600 18000 1 AZST}
+ {1351382400 14400 0 AZT}
+ {1364688000 18000 1 AZST}
+ {1382832000 14400 0 AZT}
+ {1396137600 18000 1 AZST}
+ {1414281600 14400 0 AZT}
+ {1427587200 18000 1 AZST}
+ {1445731200 14400 0 AZT}
+ {1459036800 18000 1 AZST}
+ {1477785600 14400 0 AZT}
+ {1490486400 18000 1 AZST}
+ {1509235200 14400 0 AZT}
+ {1521936000 18000 1 AZST}
+ {1540684800 14400 0 AZT}
+ {1553990400 18000 1 AZST}
+ {1572134400 14400 0 AZT}
+ {1585440000 18000 1 AZST}
+ {1603584000 14400 0 AZT}
+ {1616889600 18000 1 AZST}
+ {1635638400 14400 0 AZT}
+ {1648339200 18000 1 AZST}
+ {1667088000 14400 0 AZT}
+ {1679788800 18000 1 AZST}
+ {1698537600 14400 0 AZT}
+ {1711843200 18000 1 AZST}
+ {1729987200 14400 0 AZT}
+ {1743292800 18000 1 AZST}
+ {1761436800 14400 0 AZT}
+ {1774742400 18000 1 AZST}
+ {1792886400 14400 0 AZT}
+ {1806192000 18000 1 AZST}
+ {1824940800 14400 0 AZT}
+ {1837641600 18000 1 AZST}
+ {1856390400 14400 0 AZT}
+ {1869091200 18000 1 AZST}
+ {1887840000 14400 0 AZT}
+ {1901145600 18000 1 AZST}
+ {1919289600 14400 0 AZT}
+ {1932595200 18000 1 AZST}
+ {1950739200 14400 0 AZT}
+ {1964044800 18000 1 AZST}
+ {1982793600 14400 0 AZT}
+ {1995494400 18000 1 AZST}
+ {2014243200 14400 0 AZT}
+ {2026944000 18000 1 AZST}
+ {2045692800 14400 0 AZT}
+ {2058393600 18000 1 AZST}
+ {2077142400 14400 0 AZT}
+ {2090448000 18000 1 AZST}
+ {2108592000 14400 0 AZT}
+ {2121897600 18000 1 AZST}
+ {2140041600 14400 0 AZT}
+ {2153347200 18000 1 AZST}
+ {2172096000 14400 0 AZT}
+ {2184796800 18000 1 AZST}
+ {2203545600 14400 0 AZT}
+ {2216246400 18000 1 AZST}
+ {2234995200 14400 0 AZT}
+ {2248300800 18000 1 AZST}
+ {2266444800 14400 0 AZT}
+ {2279750400 18000 1 AZST}
+ {2297894400 14400 0 AZT}
+ {2311200000 18000 1 AZST}
+ {2329344000 14400 0 AZT}
+ {2342649600 18000 1 AZST}
+ {2361398400 14400 0 AZT}
+ {2374099200 18000 1 AZST}
+ {2392848000 14400 0 AZT}
+ {2405548800 18000 1 AZST}
+ {2424297600 14400 0 AZT}
+ {2437603200 18000 1 AZST}
+ {2455747200 14400 0 AZT}
+ {2469052800 18000 1 AZST}
+ {2487196800 14400 0 AZT}
+ {2500502400 18000 1 AZST}
+ {2519251200 14400 0 AZT}
+ {2531952000 18000 1 AZST}
+ {2550700800 14400 0 AZT}
+ {2563401600 18000 1 AZST}
+ {2582150400 14400 0 AZT}
+ {2595456000 18000 1 AZST}
+ {2613600000 14400 0 AZT}
+ {2626905600 18000 1 AZST}
+ {2645049600 14400 0 AZT}
+ {2658355200 18000 1 AZST}
+ {2676499200 14400 0 AZT}
+ {2689804800 18000 1 AZST}
+ {2708553600 14400 0 AZT}
+ {2721254400 18000 1 AZST}
+ {2740003200 14400 0 AZT}
+ {2752704000 18000 1 AZST}
+ {2771452800 14400 0 AZT}
+ {2784758400 18000 1 AZST}
+ {2802902400 14400 0 AZT}
+ {2816208000 18000 1 AZST}
+ {2834352000 14400 0 AZT}
+ {2847657600 18000 1 AZST}
+ {2866406400 14400 0 AZT}
+ {2879107200 18000 1 AZST}
+ {2897856000 14400 0 AZT}
+ {2910556800 18000 1 AZST}
+ {2929305600 14400 0 AZT}
+ {2942006400 18000 1 AZST}
+ {2960755200 14400 0 AZT}
+ {2974060800 18000 1 AZST}
+ {2992204800 14400 0 AZT}
+ {3005510400 18000 1 AZST}
+ {3023654400 14400 0 AZT}
+ {3036960000 18000 1 AZST}
+ {3055708800 14400 0 AZT}
+ {3068409600 18000 1 AZST}
+ {3087158400 14400 0 AZT}
+ {3099859200 18000 1 AZST}
+ {3118608000 14400 0 AZT}
+ {3131913600 18000 1 AZST}
+ {3150057600 14400 0 AZT}
+ {3163363200 18000 1 AZST}
+ {3181507200 14400 0 AZT}
+ {3194812800 18000 1 AZST}
+ {3212956800 14400 0 AZT}
+ {3226262400 18000 1 AZST}
+ {3245011200 14400 0 AZT}
+ {3257712000 18000 1 AZST}
+ {3276460800 14400 0 AZT}
+ {3289161600 18000 1 AZST}
+ {3307910400 14400 0 AZT}
+ {3321216000 18000 1 AZST}
+ {3339360000 14400 0 AZT}
+ {3352665600 18000 1 AZST}
+ {3370809600 14400 0 AZT}
+ {3384115200 18000 1 AZST}
+ {3402864000 14400 0 AZT}
+ {3415564800 18000 1 AZST}
+ {3434313600 14400 0 AZT}
+ {3447014400 18000 1 AZST}
+ {3465763200 14400 0 AZT}
+ {3479068800 18000 1 AZST}
+ {3497212800 14400 0 AZT}
+ {3510518400 18000 1 AZST}
+ {3528662400 14400 0 AZT}
+ {3541968000 18000 1 AZST}
+ {3560112000 14400 0 AZT}
+ {3573417600 18000 1 AZST}
+ {3592166400 14400 0 AZT}
+ {3604867200 18000 1 AZST}
+ {3623616000 14400 0 AZT}
+ {3636316800 18000 1 AZST}
+ {3655065600 14400 0 AZT}
+ {3668371200 18000 1 AZST}
+ {3686515200 14400 0 AZT}
+ {3699820800 18000 1 AZST}
+ {3717964800 14400 0 AZT}
+ {3731270400 18000 1 AZST}
+ {3750019200 14400 0 AZT}
+ {3762720000 18000 1 AZST}
+ {3781468800 14400 0 AZT}
+ {3794169600 18000 1 AZST}
+ {3812918400 14400 0 AZT}
+ {3825619200 18000 1 AZST}
+ {3844368000 14400 0 AZT}
+ {3857673600 18000 1 AZST}
+ {3875817600 14400 0 AZT}
+ {3889123200 18000 1 AZST}
+ {3907267200 14400 0 AZT}
+ {3920572800 18000 1 AZST}
+ {3939321600 14400 0 AZT}
+ {3952022400 18000 1 AZST}
+ {3970771200 14400 0 AZT}
+ {3983472000 18000 1 AZST}
+ {4002220800 14400 0 AZT}
+ {4015526400 18000 1 AZST}
+ {4033670400 14400 0 AZT}
+ {4046976000 18000 1 AZST}
+ {4065120000 14400 0 AZT}
+ {4078425600 18000 1 AZST}
+ {4096569600 14400 0 AZT}
+}
diff --git a/library/tzdata/Asia/Bangkok b/library/tzdata/Asia/Bangkok
new file mode 100644
index 0000000..6df7680
--- /dev/null
+++ b/library/tzdata/Asia/Bangkok
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Bangkok) {
+ {-9223372036854775808 24124 0 LMT}
+ {-2840164924 24124 0 BMT}
+ {-1570084924 25200 0 ICT}
+}
diff --git a/library/tzdata/Asia/Beirut b/library/tzdata/Asia/Beirut
new file mode 100644
index 0000000..ac0a64e
--- /dev/null
+++ b/library/tzdata/Asia/Beirut
@@ -0,0 +1,270 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Beirut) {
+ {-9223372036854775808 8520 0 LMT}
+ {-2840149320 7200 0 EET}
+ {-1570413600 10800 1 EEST}
+ {-1552186800 7200 0 EET}
+ {-1538359200 10800 1 EEST}
+ {-1522551600 7200 0 EET}
+ {-1507514400 10800 1 EEST}
+ {-1490583600 7200 0 EET}
+ {-1473645600 10800 1 EEST}
+ {-1460948400 7200 0 EET}
+ {-399866400 10800 1 EEST}
+ {-386650800 7200 0 EET}
+ {-368330400 10800 1 EEST}
+ {-355114800 7200 0 EET}
+ {-336794400 10800 1 EEST}
+ {-323578800 7200 0 EET}
+ {-305172000 10800 1 EEST}
+ {-291956400 7200 0 EET}
+ {-273636000 10800 1 EEST}
+ {-260420400 7200 0 EET}
+ {78012000 10800 1 EEST}
+ {86734800 7200 0 EET}
+ {105055200 10800 1 EEST}
+ {118270800 7200 0 EET}
+ {136591200 10800 1 EEST}
+ {149806800 7200 0 EET}
+ {168127200 10800 1 EEST}
+ {181342800 7200 0 EET}
+ {199749600 10800 1 EEST}
+ {212965200 7200 0 EET}
+ {231285600 10800 1 EEST}
+ {244501200 7200 0 EET}
+ {262735200 10800 1 EEST}
+ {275950800 7200 0 EET}
+ {452210400 10800 1 EEST}
+ {466722000 7200 0 EET}
+ {483746400 10800 1 EEST}
+ {498258000 7200 0 EET}
+ {515282400 10800 1 EEST}
+ {529794000 7200 0 EET}
+ {546818400 10800 1 EEST}
+ {561330000 7200 0 EET}
+ {581119200 10800 1 EEST}
+ {592952400 7200 0 EET}
+ {610754400 10800 1 EEST}
+ {624488400 7200 0 EET}
+ {641512800 10800 1 EEST}
+ {656024400 7200 0 EET}
+ {673048800 10800 1 EEST}
+ {687560400 7200 0 EET}
+ {704671200 10800 1 EEST}
+ {718146000 7200 0 EET}
+ {733269600 10800 1 EEST}
+ {748990800 7200 0 EET}
+ {764719200 10800 1 EEST}
+ {780440400 7200 0 EET}
+ {796168800 10800 1 EEST}
+ {811890000 7200 0 EET}
+ {828223200 10800 1 EEST}
+ {843944400 7200 0 EET}
+ {859672800 10800 1 EEST}
+ {875394000 7200 0 EET}
+ {891122400 10800 1 EEST}
+ {906843600 7200 0 EET}
+ {922572000 10800 1 EEST}
+ {941317200 7200 0 EET}
+ {954021600 10800 1 EEST}
+ {972766800 7200 0 EET}
+ {985471200 10800 1 EEST}
+ {1004216400 7200 0 EET}
+ {1017525600 10800 1 EEST}
+ {1035666000 7200 0 EET}
+ {1048975200 10800 1 EEST}
+ {1067115600 7200 0 EET}
+ {1080424800 10800 1 EEST}
+ {1099170000 7200 0 EET}
+ {1111874400 10800 1 EEST}
+ {1130619600 7200 0 EET}
+ {1143324000 10800 1 EEST}
+ {1162069200 7200 0 EET}
+ {1174773600 10800 1 EEST}
+ {1193518800 7200 0 EET}
+ {1206828000 10800 1 EEST}
+ {1224968400 7200 0 EET}
+ {1238277600 10800 1 EEST}
+ {1256418000 7200 0 EET}
+ {1269727200 10800 1 EEST}
+ {1288472400 7200 0 EET}
+ {1301176800 10800 1 EEST}
+ {1319922000 7200 0 EET}
+ {1332626400 10800 1 EEST}
+ {1351371600 7200 0 EET}
+ {1364680800 10800 1 EEST}
+ {1382821200 7200 0 EET}
+ {1396130400 10800 1 EEST}
+ {1414270800 7200 0 EET}
+ {1427580000 10800 1 EEST}
+ {1445720400 7200 0 EET}
+ {1459029600 10800 1 EEST}
+ {1477774800 7200 0 EET}
+ {1490479200 10800 1 EEST}
+ {1509224400 7200 0 EET}
+ {1521928800 10800 1 EEST}
+ {1540674000 7200 0 EET}
+ {1553983200 10800 1 EEST}
+ {1572123600 7200 0 EET}
+ {1585432800 10800 1 EEST}
+ {1603573200 7200 0 EET}
+ {1616882400 10800 1 EEST}
+ {1635627600 7200 0 EET}
+ {1648332000 10800 1 EEST}
+ {1667077200 7200 0 EET}
+ {1679781600 10800 1 EEST}
+ {1698526800 7200 0 EET}
+ {1711836000 10800 1 EEST}
+ {1729976400 7200 0 EET}
+ {1743285600 10800 1 EEST}
+ {1761426000 7200 0 EET}
+ {1774735200 10800 1 EEST}
+ {1792875600 7200 0 EET}
+ {1806184800 10800 1 EEST}
+ {1824930000 7200 0 EET}
+ {1837634400 10800 1 EEST}
+ {1856379600 7200 0 EET}
+ {1869084000 10800 1 EEST}
+ {1887829200 7200 0 EET}
+ {1901138400 10800 1 EEST}
+ {1919278800 7200 0 EET}
+ {1932588000 10800 1 EEST}
+ {1950728400 7200 0 EET}
+ {1964037600 10800 1 EEST}
+ {1982782800 7200 0 EET}
+ {1995487200 10800 1 EEST}
+ {2014232400 7200 0 EET}
+ {2026936800 10800 1 EEST}
+ {2045682000 7200 0 EET}
+ {2058386400 10800 1 EEST}
+ {2077131600 7200 0 EET}
+ {2090440800 10800 1 EEST}
+ {2108581200 7200 0 EET}
+ {2121890400 10800 1 EEST}
+ {2140030800 7200 0 EET}
+ {2153340000 10800 1 EEST}
+ {2172085200 7200 0 EET}
+ {2184789600 10800 1 EEST}
+ {2203534800 7200 0 EET}
+ {2216239200 10800 1 EEST}
+ {2234984400 7200 0 EET}
+ {2248293600 10800 1 EEST}
+ {2266434000 7200 0 EET}
+ {2279743200 10800 1 EEST}
+ {2297883600 7200 0 EET}
+ {2311192800 10800 1 EEST}
+ {2329333200 7200 0 EET}
+ {2342642400 10800 1 EEST}
+ {2361387600 7200 0 EET}
+ {2374092000 10800 1 EEST}
+ {2392837200 7200 0 EET}
+ {2405541600 10800 1 EEST}
+ {2424286800 7200 0 EET}
+ {2437596000 10800 1 EEST}
+ {2455736400 7200 0 EET}
+ {2469045600 10800 1 EEST}
+ {2487186000 7200 0 EET}
+ {2500495200 10800 1 EEST}
+ {2519240400 7200 0 EET}
+ {2531944800 10800 1 EEST}
+ {2550690000 7200 0 EET}
+ {2563394400 10800 1 EEST}
+ {2582139600 7200 0 EET}
+ {2595448800 10800 1 EEST}
+ {2613589200 7200 0 EET}
+ {2626898400 10800 1 EEST}
+ {2645038800 7200 0 EET}
+ {2658348000 10800 1 EEST}
+ {2676488400 7200 0 EET}
+ {2689797600 10800 1 EEST}
+ {2708542800 7200 0 EET}
+ {2721247200 10800 1 EEST}
+ {2739992400 7200 0 EET}
+ {2752696800 10800 1 EEST}
+ {2771442000 7200 0 EET}
+ {2784751200 10800 1 EEST}
+ {2802891600 7200 0 EET}
+ {2816200800 10800 1 EEST}
+ {2834341200 7200 0 EET}
+ {2847650400 10800 1 EEST}
+ {2866395600 7200 0 EET}
+ {2879100000 10800 1 EEST}
+ {2897845200 7200 0 EET}
+ {2910549600 10800 1 EEST}
+ {2929294800 7200 0 EET}
+ {2941999200 10800 1 EEST}
+ {2960744400 7200 0 EET}
+ {2974053600 10800 1 EEST}
+ {2992194000 7200 0 EET}
+ {3005503200 10800 1 EEST}
+ {3023643600 7200 0 EET}
+ {3036952800 10800 1 EEST}
+ {3055698000 7200 0 EET}
+ {3068402400 10800 1 EEST}
+ {3087147600 7200 0 EET}
+ {3099852000 10800 1 EEST}
+ {3118597200 7200 0 EET}
+ {3131906400 10800 1 EEST}
+ {3150046800 7200 0 EET}
+ {3163356000 10800 1 EEST}
+ {3181496400 7200 0 EET}
+ {3194805600 10800 1 EEST}
+ {3212946000 7200 0 EET}
+ {3226255200 10800 1 EEST}
+ {3245000400 7200 0 EET}
+ {3257704800 10800 1 EEST}
+ {3276450000 7200 0 EET}
+ {3289154400 10800 1 EEST}
+ {3307899600 7200 0 EET}
+ {3321208800 10800 1 EEST}
+ {3339349200 7200 0 EET}
+ {3352658400 10800 1 EEST}
+ {3370798800 7200 0 EET}
+ {3384108000 10800 1 EEST}
+ {3402853200 7200 0 EET}
+ {3415557600 10800 1 EEST}
+ {3434302800 7200 0 EET}
+ {3447007200 10800 1 EEST}
+ {3465752400 7200 0 EET}
+ {3479061600 10800 1 EEST}
+ {3497202000 7200 0 EET}
+ {3510511200 10800 1 EEST}
+ {3528651600 7200 0 EET}
+ {3541960800 10800 1 EEST}
+ {3560101200 7200 0 EET}
+ {3573410400 10800 1 EEST}
+ {3592155600 7200 0 EET}
+ {3604860000 10800 1 EEST}
+ {3623605200 7200 0 EET}
+ {3636309600 10800 1 EEST}
+ {3655054800 7200 0 EET}
+ {3668364000 10800 1 EEST}
+ {3686504400 7200 0 EET}
+ {3699813600 10800 1 EEST}
+ {3717954000 7200 0 EET}
+ {3731263200 10800 1 EEST}
+ {3750008400 7200 0 EET}
+ {3762712800 10800 1 EEST}
+ {3781458000 7200 0 EET}
+ {3794162400 10800 1 EEST}
+ {3812907600 7200 0 EET}
+ {3825612000 10800 1 EEST}
+ {3844357200 7200 0 EET}
+ {3857666400 10800 1 EEST}
+ {3875806800 7200 0 EET}
+ {3889116000 10800 1 EEST}
+ {3907256400 7200 0 EET}
+ {3920565600 10800 1 EEST}
+ {3939310800 7200 0 EET}
+ {3952015200 10800 1 EEST}
+ {3970760400 7200 0 EET}
+ {3983464800 10800 1 EEST}
+ {4002210000 7200 0 EET}
+ {4015519200 10800 1 EEST}
+ {4033659600 7200 0 EET}
+ {4046968800 10800 1 EEST}
+ {4065109200 7200 0 EET}
+ {4078418400 10800 1 EEST}
+ {4096558800 7200 0 EET}
+}
diff --git a/library/tzdata/Asia/Bishkek b/library/tzdata/Asia/Bishkek
new file mode 100644
index 0000000..6ba3896
--- /dev/null
+++ b/library/tzdata/Asia/Bishkek
@@ -0,0 +1,57 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Bishkek) {
+ {-9223372036854775808 17904 0 LMT}
+ {-1441169904 18000 0 FRUT}
+ {-1247547600 21600 0 FRUT}
+ {354909600 25200 1 FRUST}
+ {370717200 21600 0 FRUT}
+ {386445600 25200 1 FRUST}
+ {402253200 21600 0 FRUT}
+ {417981600 25200 1 FRUST}
+ {433789200 21600 0 FRUT}
+ {449604000 25200 1 FRUST}
+ {465336000 21600 0 FRUT}
+ {481060800 25200 1 FRUST}
+ {496785600 21600 0 FRUT}
+ {512510400 25200 1 FRUST}
+ {528235200 21600 0 FRUT}
+ {543960000 25200 1 FRUST}
+ {559684800 21600 0 FRUT}
+ {575409600 25200 1 FRUST}
+ {591134400 21600 0 FRUT}
+ {606859200 25200 1 FRUST}
+ {622584000 21600 0 FRUT}
+ {638308800 25200 1 FRUST}
+ {654638400 21600 0 FRUT}
+ {670363200 21600 1 FRUST}
+ {683582400 21600 0 KGT}
+ {703018800 21600 1 KGST}
+ {717530400 18000 0 KGT}
+ {734468400 21600 1 KGST}
+ {748980000 18000 0 KGT}
+ {765918000 21600 1 KGST}
+ {780429600 18000 0 KGT}
+ {797367600 21600 1 KGST}
+ {811879200 18000 0 KGT}
+ {828817200 21600 1 KGST}
+ {843933600 18000 0 KGT}
+ {859671000 21600 1 KGST}
+ {877811400 18000 0 KGT}
+ {891120600 21600 1 KGST}
+ {909261000 18000 0 KGT}
+ {922570200 21600 1 KGST}
+ {941315400 18000 0 KGT}
+ {954019800 21600 1 KGST}
+ {972765000 18000 0 KGT}
+ {985469400 21600 1 KGST}
+ {1004214600 18000 0 KGT}
+ {1017523800 21600 1 KGST}
+ {1035664200 18000 0 KGT}
+ {1048973400 21600 1 KGST}
+ {1067113800 18000 0 KGT}
+ {1080423000 21600 1 KGST}
+ {1099168200 18000 0 KGT}
+ {1111872600 21600 1 KGST}
+ {1123783200 21600 0 KGT}
+}
diff --git a/library/tzdata/Asia/Brunei b/library/tzdata/Asia/Brunei
new file mode 100644
index 0000000..63d380b
--- /dev/null
+++ b/library/tzdata/Asia/Brunei
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Brunei) {
+ {-9223372036854775808 27580 0 LMT}
+ {-1383464380 27000 0 BNT}
+ {-1167636600 28800 0 BNT}
+}
diff --git a/library/tzdata/Asia/Calcutta b/library/tzdata/Asia/Calcutta
new file mode 100644
index 0000000..7243ef8
--- /dev/null
+++ b/library/tzdata/Asia/Calcutta
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Asia/Kolkata)]} {
+ LoadTimeZoneFile Asia/Kolkata
+}
+set TZData(:Asia/Calcutta) $TZData(:Asia/Kolkata)
diff --git a/library/tzdata/Asia/Choibalsan b/library/tzdata/Asia/Choibalsan
new file mode 100644
index 0000000..3d42617
--- /dev/null
+++ b/library/tzdata/Asia/Choibalsan
@@ -0,0 +1,51 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Choibalsan) {
+ {-9223372036854775808 27480 0 LMT}
+ {-2032933080 25200 0 ULAT}
+ {252435600 28800 0 ULAT}
+ {417974400 36000 0 CHOST}
+ {433778400 32400 0 CHOT}
+ {449593200 36000 1 CHOST}
+ {465314400 32400 0 CHOT}
+ {481042800 36000 1 CHOST}
+ {496764000 32400 0 CHOT}
+ {512492400 36000 1 CHOST}
+ {528213600 32400 0 CHOT}
+ {543942000 36000 1 CHOST}
+ {559663200 32400 0 CHOT}
+ {575391600 36000 1 CHOST}
+ {591112800 32400 0 CHOT}
+ {606841200 36000 1 CHOST}
+ {622562400 32400 0 CHOT}
+ {638290800 36000 1 CHOST}
+ {654616800 32400 0 CHOT}
+ {670345200 36000 1 CHOST}
+ {686066400 32400 0 CHOT}
+ {701794800 36000 1 CHOST}
+ {717516000 32400 0 CHOT}
+ {733244400 36000 1 CHOST}
+ {748965600 32400 0 CHOT}
+ {764694000 36000 1 CHOST}
+ {780415200 32400 0 CHOT}
+ {796143600 36000 1 CHOST}
+ {811864800 32400 0 CHOT}
+ {828198000 36000 1 CHOST}
+ {843919200 32400 0 CHOT}
+ {859647600 36000 1 CHOST}
+ {875368800 32400 0 CHOT}
+ {891097200 36000 1 CHOST}
+ {906818400 32400 0 CHOT}
+ {988390800 36000 1 CHOST}
+ {1001692800 32400 0 CHOT}
+ {1017421200 36000 1 CHOST}
+ {1033142400 32400 0 CHOT}
+ {1048870800 36000 1 CHOST}
+ {1064592000 32400 0 CHOT}
+ {1080320400 36000 1 CHOST}
+ {1096041600 32400 0 CHOT}
+ {1111770000 36000 1 CHOST}
+ {1127491200 32400 0 CHOT}
+ {1143219600 36000 1 CHOST}
+ {1159545600 32400 0 CHOT}
+}
diff --git a/library/tzdata/Asia/Chongqing b/library/tzdata/Asia/Chongqing
new file mode 100644
index 0000000..eff3536
--- /dev/null
+++ b/library/tzdata/Asia/Chongqing
@@ -0,0 +1,19 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Chongqing) {
+ {-9223372036854775808 25580 0 LMT}
+ {-1325487980 25200 0 LONT}
+ {325962000 28800 0 CST}
+ {515520000 32400 1 CDT}
+ {527007600 28800 0 CST}
+ {545155200 32400 1 CDT}
+ {558457200 28800 0 CST}
+ {576604800 32400 1 CDT}
+ {589906800 28800 0 CST}
+ {608659200 32400 1 CDT}
+ {621961200 28800 0 CST}
+ {640108800 32400 1 CDT}
+ {653410800 28800 0 CST}
+ {671558400 32400 1 CDT}
+ {684860400 28800 0 CST}
+}
diff --git a/library/tzdata/Asia/Chungking b/library/tzdata/Asia/Chungking
new file mode 100644
index 0000000..f10d8a1
--- /dev/null
+++ b/library/tzdata/Asia/Chungking
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Asia/Chongqing)]} {
+ LoadTimeZoneFile Asia/Chongqing
+}
+set TZData(:Asia/Chungking) $TZData(:Asia/Chongqing)
diff --git a/library/tzdata/Asia/Colombo b/library/tzdata/Asia/Colombo
new file mode 100644
index 0000000..ca7bffc
--- /dev/null
+++ b/library/tzdata/Asia/Colombo
@@ -0,0 +1,13 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Colombo) {
+ {-9223372036854775808 19164 0 LMT}
+ {-2840159964 19172 0 MMT}
+ {-2019705572 19800 0 IST}
+ {-883287000 21600 1 IHST}
+ {-862639200 23400 1 IST}
+ {-764051400 19800 0 IST}
+ {832962600 23400 0 LKT}
+ {846266400 21600 0 LKT}
+ {1145039400 19800 0 IST}
+}
diff --git a/library/tzdata/Asia/Dacca b/library/tzdata/Asia/Dacca
new file mode 100644
index 0000000..b91d7fa
--- /dev/null
+++ b/library/tzdata/Asia/Dacca
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Asia/Dhaka)]} {
+ LoadTimeZoneFile Asia/Dhaka
+}
+set TZData(:Asia/Dacca) $TZData(:Asia/Dhaka)
diff --git a/library/tzdata/Asia/Damascus b/library/tzdata/Asia/Damascus
new file mode 100644
index 0000000..2ea1770
--- /dev/null
+++ b/library/tzdata/Asia/Damascus
@@ -0,0 +1,280 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Damascus) {
+ {-9223372036854775808 8712 0 LMT}
+ {-1577931912 7200 0 EET}
+ {-1568592000 10800 1 EEST}
+ {-1554080400 7200 0 EET}
+ {-1537142400 10800 1 EEST}
+ {-1522630800 7200 0 EET}
+ {-1505692800 10800 1 EEST}
+ {-1491181200 7200 0 EET}
+ {-1474243200 10800 1 EEST}
+ {-1459126800 7200 0 EET}
+ {-242265600 10800 1 EEST}
+ {-228877200 7200 0 EET}
+ {-210556800 10800 1 EEST}
+ {-197427600 7200 0 EET}
+ {-178934400 10800 1 EEST}
+ {-165718800 7200 0 EET}
+ {-147398400 10800 1 EEST}
+ {-134269200 7200 0 EET}
+ {-116467200 10800 1 EEST}
+ {-102646800 7200 0 EET}
+ {-84326400 10800 1 EEST}
+ {-71110800 7200 0 EET}
+ {-52704000 10800 1 EEST}
+ {-39488400 7200 0 EET}
+ {-21168000 10800 1 EEST}
+ {-7952400 7200 0 EET}
+ {10368000 10800 1 EEST}
+ {23583600 7200 0 EET}
+ {41904000 10800 1 EEST}
+ {55119600 7200 0 EET}
+ {73526400 10800 1 EEST}
+ {86742000 7200 0 EET}
+ {105062400 10800 1 EEST}
+ {118278000 7200 0 EET}
+ {136598400 10800 1 EEST}
+ {149814000 7200 0 EET}
+ {168134400 10800 1 EEST}
+ {181350000 7200 0 EET}
+ {199756800 10800 1 EEST}
+ {212972400 7200 0 EET}
+ {231292800 10800 1 EEST}
+ {241916400 7200 0 EET}
+ {262828800 10800 1 EEST}
+ {273452400 7200 0 EET}
+ {418694400 10800 1 EEST}
+ {433810800 7200 0 EET}
+ {450316800 10800 1 EEST}
+ {465433200 7200 0 EET}
+ {508896000 10800 1 EEST}
+ {529196400 7200 0 EET}
+ {541555200 10800 1 EEST}
+ {562633200 7200 0 EET}
+ {574387200 10800 1 EEST}
+ {594255600 7200 0 EET}
+ {607305600 10800 1 EEST}
+ {623199600 7200 0 EET}
+ {638928000 10800 1 EEST}
+ {654649200 7200 0 EET}
+ {670456800 10800 1 EEST}
+ {686264400 7200 0 EET}
+ {702684000 10800 1 EEST}
+ {717886800 7200 0 EET}
+ {733096800 10800 1 EEST}
+ {748904400 7200 0 EET}
+ {765151200 10800 1 EEST}
+ {780958800 7200 0 EET}
+ {796687200 10800 1 EEST}
+ {812494800 7200 0 EET}
+ {828309600 10800 1 EEST}
+ {844117200 7200 0 EET}
+ {859759200 10800 1 EEST}
+ {875653200 7200 0 EET}
+ {891208800 10800 1 EEST}
+ {907189200 7200 0 EET}
+ {922917600 10800 1 EEST}
+ {938725200 7200 0 EET}
+ {954540000 10800 1 EEST}
+ {970347600 7200 0 EET}
+ {986076000 10800 1 EEST}
+ {1001883600 7200 0 EET}
+ {1017612000 10800 1 EEST}
+ {1033419600 7200 0 EET}
+ {1049148000 10800 1 EEST}
+ {1064955600 7200 0 EET}
+ {1080770400 10800 1 EEST}
+ {1096578000 7200 0 EET}
+ {1112306400 10800 1 EEST}
+ {1128114000 7200 0 EET}
+ {1143842400 10800 1 EEST}
+ {1158872400 7200 0 EET}
+ {1175205600 10800 1 EEST}
+ {1193950800 7200 0 EET}
+ {1207260000 10800 1 EEST}
+ {1225486800 7200 0 EET}
+ {1238104800 10800 1 EEST}
+ {1256850000 7200 0 EET}
+ {1270159200 10800 1 EEST}
+ {1288299600 7200 0 EET}
+ {1301608800 10800 1 EEST}
+ {1319749200 7200 0 EET}
+ {1333663200 10800 1 EEST}
+ {1351198800 7200 0 EET}
+ {1365112800 10800 1 EEST}
+ {1382648400 7200 0 EET}
+ {1396562400 10800 1 EEST}
+ {1414702800 7200 0 EET}
+ {1428012000 10800 1 EEST}
+ {1446152400 7200 0 EET}
+ {1459461600 10800 1 EEST}
+ {1477602000 7200 0 EET}
+ {1491516000 10800 1 EEST}
+ {1509051600 7200 0 EET}
+ {1522965600 10800 1 EEST}
+ {1540501200 7200 0 EET}
+ {1554415200 10800 1 EEST}
+ {1571950800 7200 0 EET}
+ {1585864800 10800 1 EEST}
+ {1604005200 7200 0 EET}
+ {1617314400 10800 1 EEST}
+ {1635454800 7200 0 EET}
+ {1648764000 10800 1 EEST}
+ {1666904400 7200 0 EET}
+ {1680818400 10800 1 EEST}
+ {1698354000 7200 0 EET}
+ {1712268000 10800 1 EEST}
+ {1729803600 7200 0 EET}
+ {1743717600 10800 1 EEST}
+ {1761858000 7200 0 EET}
+ {1775167200 10800 1 EEST}
+ {1793307600 7200 0 EET}
+ {1806616800 10800 1 EEST}
+ {1824757200 7200 0 EET}
+ {1838671200 10800 1 EEST}
+ {1856206800 7200 0 EET}
+ {1870120800 10800 1 EEST}
+ {1887656400 7200 0 EET}
+ {1901570400 10800 1 EEST}
+ {1919106000 7200 0 EET}
+ {1933020000 10800 1 EEST}
+ {1951160400 7200 0 EET}
+ {1964469600 10800 1 EEST}
+ {1982610000 7200 0 EET}
+ {1995919200 10800 1 EEST}
+ {2014059600 7200 0 EET}
+ {2027973600 10800 1 EEST}
+ {2045509200 7200 0 EET}
+ {2059423200 10800 1 EEST}
+ {2076958800 7200 0 EET}
+ {2090872800 10800 1 EEST}
+ {2109013200 7200 0 EET}
+ {2122322400 10800 1 EEST}
+ {2140462800 7200 0 EET}
+ {2153772000 10800 1 EEST}
+ {2171912400 7200 0 EET}
+ {2185221600 10800 1 EEST}
+ {2203362000 7200 0 EET}
+ {2217276000 10800 1 EEST}
+ {2234811600 7200 0 EET}
+ {2248725600 10800 1 EEST}
+ {2266261200 7200 0 EET}
+ {2280175200 10800 1 EEST}
+ {2298315600 7200 0 EET}
+ {2311624800 10800 1 EEST}
+ {2329765200 7200 0 EET}
+ {2343074400 10800 1 EEST}
+ {2361214800 7200 0 EET}
+ {2375128800 10800 1 EEST}
+ {2392664400 7200 0 EET}
+ {2406578400 10800 1 EEST}
+ {2424114000 7200 0 EET}
+ {2438028000 10800 1 EEST}
+ {2455563600 7200 0 EET}
+ {2469477600 10800 1 EEST}
+ {2487618000 7200 0 EET}
+ {2500927200 10800 1 EEST}
+ {2519067600 7200 0 EET}
+ {2532376800 10800 1 EEST}
+ {2550517200 7200 0 EET}
+ {2564431200 10800 1 EEST}
+ {2581966800 7200 0 EET}
+ {2595880800 10800 1 EEST}
+ {2613416400 7200 0 EET}
+ {2627330400 10800 1 EEST}
+ {2645470800 7200 0 EET}
+ {2658780000 10800 1 EEST}
+ {2676920400 7200 0 EET}
+ {2690229600 10800 1 EEST}
+ {2708370000 7200 0 EET}
+ {2722284000 10800 1 EEST}
+ {2739819600 7200 0 EET}
+ {2753733600 10800 1 EEST}
+ {2771269200 7200 0 EET}
+ {2785183200 10800 1 EEST}
+ {2802718800 7200 0 EET}
+ {2816632800 10800 1 EEST}
+ {2834773200 7200 0 EET}
+ {2848082400 10800 1 EEST}
+ {2866222800 7200 0 EET}
+ {2879532000 10800 1 EEST}
+ {2897672400 7200 0 EET}
+ {2911586400 10800 1 EEST}
+ {2929122000 7200 0 EET}
+ {2943036000 10800 1 EEST}
+ {2960571600 7200 0 EET}
+ {2974485600 10800 1 EEST}
+ {2992626000 7200 0 EET}
+ {3005935200 10800 1 EEST}
+ {3024075600 7200 0 EET}
+ {3037384800 10800 1 EEST}
+ {3055525200 7200 0 EET}
+ {3068834400 10800 1 EEST}
+ {3086974800 7200 0 EET}
+ {3100888800 10800 1 EEST}
+ {3118424400 7200 0 EET}
+ {3132338400 10800 1 EEST}
+ {3149874000 7200 0 EET}
+ {3163788000 10800 1 EEST}
+ {3181928400 7200 0 EET}
+ {3195237600 10800 1 EEST}
+ {3213378000 7200 0 EET}
+ {3226687200 10800 1 EEST}
+ {3244827600 7200 0 EET}
+ {3258741600 10800 1 EEST}
+ {3276277200 7200 0 EET}
+ {3290191200 10800 1 EEST}
+ {3307726800 7200 0 EET}
+ {3321640800 10800 1 EEST}
+ {3339176400 7200 0 EET}
+ {3353090400 10800 1 EEST}
+ {3371230800 7200 0 EET}
+ {3384540000 10800 1 EEST}
+ {3402680400 7200 0 EET}
+ {3415989600 10800 1 EEST}
+ {3434130000 7200 0 EET}
+ {3448044000 10800 1 EEST}
+ {3465579600 7200 0 EET}
+ {3479493600 10800 1 EEST}
+ {3497029200 7200 0 EET}
+ {3510943200 10800 1 EEST}
+ {3529083600 7200 0 EET}
+ {3542392800 10800 1 EEST}
+ {3560533200 7200 0 EET}
+ {3573842400 10800 1 EEST}
+ {3591982800 7200 0 EET}
+ {3605896800 10800 1 EEST}
+ {3623432400 7200 0 EET}
+ {3637346400 10800 1 EEST}
+ {3654882000 7200 0 EET}
+ {3668796000 10800 1 EEST}
+ {3686331600 7200 0 EET}
+ {3700245600 10800 1 EEST}
+ {3718386000 7200 0 EET}
+ {3731695200 10800 1 EEST}
+ {3749835600 7200 0 EET}
+ {3763144800 10800 1 EEST}
+ {3781285200 7200 0 EET}
+ {3795199200 10800 1 EEST}
+ {3812734800 7200 0 EET}
+ {3826648800 10800 1 EEST}
+ {3844184400 7200 0 EET}
+ {3858098400 10800 1 EEST}
+ {3876238800 7200 0 EET}
+ {3889548000 10800 1 EEST}
+ {3907688400 7200 0 EET}
+ {3920997600 10800 1 EEST}
+ {3939138000 7200 0 EET}
+ {3952447200 10800 1 EEST}
+ {3970587600 7200 0 EET}
+ {3984501600 10800 1 EEST}
+ {4002037200 7200 0 EET}
+ {4015951200 10800 1 EEST}
+ {4033486800 7200 0 EET}
+ {4047400800 10800 1 EEST}
+ {4065541200 7200 0 EET}
+ {4078850400 10800 1 EEST}
+ {4096990800 7200 0 EET}
+}
diff --git a/library/tzdata/Asia/Dhaka b/library/tzdata/Asia/Dhaka
new file mode 100644
index 0000000..e0c270d
--- /dev/null
+++ b/library/tzdata/Asia/Dhaka
@@ -0,0 +1,14 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Dhaka) {
+ {-9223372036854775808 21700 0 LMT}
+ {-2524543300 21200 0 HMT}
+ {-891582800 23400 0 BURT}
+ {-872058600 19800 0 IST}
+ {-862637400 23400 0 BURT}
+ {-576138600 21600 0 DACT}
+ {38772000 21600 0 BDT}
+ {1230746400 21600 0 BDT}
+ {1245430800 25200 1 BDST}
+ {1262278740 21600 0 BDT}
+}
diff --git a/library/tzdata/Asia/Dili b/library/tzdata/Asia/Dili
new file mode 100644
index 0000000..36910fd
--- /dev/null
+++ b/library/tzdata/Asia/Dili
@@ -0,0 +1,10 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Dili) {
+ {-9223372036854775808 30140 0 LMT}
+ {-1830414140 28800 0 TLT}
+ {-879152400 32400 0 JST}
+ {-766054800 32400 0 TLT}
+ {199897200 28800 0 CIT}
+ {969120000 32400 0 TLT}
+}
diff --git a/library/tzdata/Asia/Dubai b/library/tzdata/Asia/Dubai
new file mode 100644
index 0000000..b8730e5
--- /dev/null
+++ b/library/tzdata/Asia/Dubai
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Dubai) {
+ {-9223372036854775808 13272 0 LMT}
+ {-1577936472 14400 0 GST}
+}
diff --git a/library/tzdata/Asia/Dushanbe b/library/tzdata/Asia/Dushanbe
new file mode 100644
index 0000000..59f8cb6
--- /dev/null
+++ b/library/tzdata/Asia/Dushanbe
@@ -0,0 +1,29 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Dushanbe) {
+ {-9223372036854775808 16512 0 LMT}
+ {-1441168512 18000 0 DUST}
+ {-1247547600 21600 0 DUST}
+ {354909600 25200 1 DUSST}
+ {370717200 21600 0 DUST}
+ {386445600 25200 1 DUSST}
+ {402253200 21600 0 DUST}
+ {417981600 25200 1 DUSST}
+ {433789200 21600 0 DUST}
+ {449604000 25200 1 DUSST}
+ {465336000 21600 0 DUST}
+ {481060800 25200 1 DUSST}
+ {496785600 21600 0 DUST}
+ {512510400 25200 1 DUSST}
+ {528235200 21600 0 DUST}
+ {543960000 25200 1 DUSST}
+ {559684800 21600 0 DUST}
+ {575409600 25200 1 DUSST}
+ {591134400 21600 0 DUST}
+ {606859200 25200 1 DUSST}
+ {622584000 21600 0 DUST}
+ {638308800 25200 1 DUSST}
+ {654638400 21600 0 DUST}
+ {670363200 21600 1 DUSST}
+ {684363600 18000 0 TJT}
+}
diff --git a/library/tzdata/Asia/Gaza b/library/tzdata/Asia/Gaza
new file mode 100644
index 0000000..f26221e
--- /dev/null
+++ b/library/tzdata/Asia/Gaza
@@ -0,0 +1,276 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Gaza) {
+ {-9223372036854775808 8272 0 LMT}
+ {-2185409872 7200 0 EET}
+ {-933645600 10800 1 EET}
+ {-857358000 7200 0 EET}
+ {-844300800 10800 1 EET}
+ {-825822000 7200 0 EET}
+ {-812685600 10800 1 EET}
+ {-794199600 7200 0 EET}
+ {-779853600 10800 1 EET}
+ {-762656400 7200 0 EET}
+ {-748310400 10800 1 EET}
+ {-731127600 7200 0 EET}
+ {-682653600 7200 0 EET}
+ {-399088800 10800 1 EEST}
+ {-386650800 7200 0 EET}
+ {-368330400 10800 1 EEST}
+ {-355114800 7200 0 EET}
+ {-336790800 10800 1 EEST}
+ {-323654400 7200 0 EET}
+ {-305168400 10800 1 EEST}
+ {-292032000 7200 0 EET}
+ {-273632400 10800 1 EEST}
+ {-260496000 7200 0 EET}
+ {-242096400 10800 1 EEST}
+ {-228960000 7200 0 EET}
+ {-210560400 10800 1 EEST}
+ {-197424000 7200 0 EET}
+ {-178938000 10800 1 EEST}
+ {-165801600 7200 0 EET}
+ {-147402000 10800 1 EEST}
+ {-134265600 7200 0 EET}
+ {-115866000 10800 1 EEST}
+ {-102643200 7200 0 EET}
+ {-84330000 10800 1 EEST}
+ {-81313200 10800 0 IST}
+ {142376400 10800 1 IDT}
+ {150843600 7200 0 IST}
+ {167176800 10800 1 IDT}
+ {178664400 7200 0 IST}
+ {482277600 10800 1 IDT}
+ {495579600 7200 0 IST}
+ {516751200 10800 1 IDT}
+ {526424400 7200 0 IST}
+ {545436000 10800 1 IDT}
+ {558478800 7200 0 IST}
+ {576540000 10800 1 IDT}
+ {589237200 7200 0 IST}
+ {609890400 10800 1 IDT}
+ {620773200 7200 0 IST}
+ {638316000 10800 1 IDT}
+ {651618000 7200 0 IST}
+ {669765600 10800 1 IDT}
+ {683672400 7200 0 IST}
+ {701820000 10800 1 IDT}
+ {715726800 7200 0 IST}
+ {733701600 10800 1 IDT}
+ {747176400 7200 0 IST}
+ {765151200 10800 1 IDT}
+ {778021200 7200 0 IST}
+ {796600800 10800 1 IDT}
+ {810075600 7200 0 IST}
+ {820447200 7200 0 EET}
+ {828655200 10800 1 EEST}
+ {843170400 7200 0 EET}
+ {860104800 10800 1 EEST}
+ {874620000 7200 0 EET}
+ {891554400 10800 1 EEST}
+ {906069600 7200 0 EET}
+ {915141600 7200 0 EET}
+ {924213600 10800 1 EEST}
+ {939934800 7200 0 EET}
+ {956268000 10800 1 EEST}
+ {971989200 7200 0 EET}
+ {987717600 10800 1 EEST}
+ {1003438800 7200 0 EET}
+ {1019167200 10800 1 EEST}
+ {1034888400 7200 0 EET}
+ {1050616800 10800 1 EEST}
+ {1066338000 7200 0 EET}
+ {1082066400 10800 1 EEST}
+ {1096581600 7200 0 EET}
+ {1113516000 10800 1 EEST}
+ {1128380400 7200 0 EET}
+ {1143842400 10800 1 EEST}
+ {1158872400 7200 0 EET}
+ {1175378400 10800 1 EEST}
+ {1189638000 7200 0 EET}
+ {1207000800 10800 1 EEST}
+ {1219964400 7200 0 EET}
+ {1238104800 10800 1 EEST}
+ {1252018800 7200 0 EET}
+ {1269640860 10800 1 EEST}
+ {1281474000 7200 0 EET}
+ {1283472000 7200 0 EET}
+ {1301090460 10800 1 EEST}
+ {1314918000 7200 0 EET}
+ {1333144860 10800 1 EEST}
+ {1346972400 7200 0 EET}
+ {1364594460 10800 1 EEST}
+ {1378422000 7200 0 EET}
+ {1396044060 10800 1 EEST}
+ {1409871600 7200 0 EET}
+ {1427493660 10800 1 EEST}
+ {1441321200 7200 0 EET}
+ {1458943260 10800 1 EEST}
+ {1472770800 7200 0 EET}
+ {1490392860 10800 1 EEST}
+ {1504220400 7200 0 EET}
+ {1522447260 10800 1 EEST}
+ {1536274800 7200 0 EET}
+ {1553896860 10800 1 EEST}
+ {1567724400 7200 0 EET}
+ {1585346460 10800 1 EEST}
+ {1599174000 7200 0 EET}
+ {1616796060 10800 1 EEST}
+ {1630623600 7200 0 EET}
+ {1648245660 10800 1 EEST}
+ {1662073200 7200 0 EET}
+ {1679695260 10800 1 EEST}
+ {1693522800 7200 0 EET}
+ {1711749660 10800 1 EEST}
+ {1725577200 7200 0 EET}
+ {1743199260 10800 1 EEST}
+ {1757026800 7200 0 EET}
+ {1774648860 10800 1 EEST}
+ {1788476400 7200 0 EET}
+ {1806098460 10800 1 EEST}
+ {1819926000 7200 0 EET}
+ {1837548060 10800 1 EEST}
+ {1851375600 7200 0 EET}
+ {1869602460 10800 1 EEST}
+ {1883430000 7200 0 EET}
+ {1901052060 10800 1 EEST}
+ {1914879600 7200 0 EET}
+ {1932501660 10800 1 EEST}
+ {1946329200 7200 0 EET}
+ {1963951260 10800 1 EEST}
+ {1977778800 7200 0 EET}
+ {1995400860 10800 1 EEST}
+ {2009228400 7200 0 EET}
+ {2026850460 10800 1 EEST}
+ {2040678000 7200 0 EET}
+ {2058904860 10800 1 EEST}
+ {2072732400 7200 0 EET}
+ {2090354460 10800 1 EEST}
+ {2104182000 7200 0 EET}
+ {2121804060 10800 1 EEST}
+ {2135631600 7200 0 EET}
+ {2153253660 10800 1 EEST}
+ {2167081200 7200 0 EET}
+ {2184703260 10800 1 EEST}
+ {2198530800 7200 0 EET}
+ {2216757660 10800 1 EEST}
+ {2230585200 7200 0 EET}
+ {2248207260 10800 1 EEST}
+ {2262034800 7200 0 EET}
+ {2279656860 10800 1 EEST}
+ {2293484400 7200 0 EET}
+ {2311106460 10800 1 EEST}
+ {2324934000 7200 0 EET}
+ {2342556060 10800 1 EEST}
+ {2356383600 7200 0 EET}
+ {2374005660 10800 1 EEST}
+ {2387833200 7200 0 EET}
+ {2406060060 10800 1 EEST}
+ {2419887600 7200 0 EET}
+ {2437509660 10800 1 EEST}
+ {2451337200 7200 0 EET}
+ {2468959260 10800 1 EEST}
+ {2482786800 7200 0 EET}
+ {2500408860 10800 1 EEST}
+ {2514236400 7200 0 EET}
+ {2531858460 10800 1 EEST}
+ {2545686000 7200 0 EET}
+ {2563308060 10800 1 EEST}
+ {2577135600 7200 0 EET}
+ {2595362460 10800 1 EEST}
+ {2609190000 7200 0 EET}
+ {2626812060 10800 1 EEST}
+ {2640639600 7200 0 EET}
+ {2658261660 10800 1 EEST}
+ {2672089200 7200 0 EET}
+ {2689711260 10800 1 EEST}
+ {2703538800 7200 0 EET}
+ {2721160860 10800 1 EEST}
+ {2734988400 7200 0 EET}
+ {2753215260 10800 1 EEST}
+ {2767042800 7200 0 EET}
+ {2784664860 10800 1 EEST}
+ {2798492400 7200 0 EET}
+ {2816114460 10800 1 EEST}
+ {2829942000 7200 0 EET}
+ {2847564060 10800 1 EEST}
+ {2861391600 7200 0 EET}
+ {2879013660 10800 1 EEST}
+ {2892841200 7200 0 EET}
+ {2910463260 10800 1 EEST}
+ {2924290800 7200 0 EET}
+ {2942517660 10800 1 EEST}
+ {2956345200 7200 0 EET}
+ {2973967260 10800 1 EEST}
+ {2987794800 7200 0 EET}
+ {3005416860 10800 1 EEST}
+ {3019244400 7200 0 EET}
+ {3036866460 10800 1 EEST}
+ {3050694000 7200 0 EET}
+ {3068316060 10800 1 EEST}
+ {3082143600 7200 0 EET}
+ {3100370460 10800 1 EEST}
+ {3114198000 7200 0 EET}
+ {3131820060 10800 1 EEST}
+ {3145647600 7200 0 EET}
+ {3163269660 10800 1 EEST}
+ {3177097200 7200 0 EET}
+ {3194719260 10800 1 EEST}
+ {3208546800 7200 0 EET}
+ {3226168860 10800 1 EEST}
+ {3239996400 7200 0 EET}
+ {3257618460 10800 1 EEST}
+ {3271446000 7200 0 EET}
+ {3289672860 10800 1 EEST}
+ {3303500400 7200 0 EET}
+ {3321122460 10800 1 EEST}
+ {3334950000 7200 0 EET}
+ {3352572060 10800 1 EEST}
+ {3366399600 7200 0 EET}
+ {3384021660 10800 1 EEST}
+ {3397849200 7200 0 EET}
+ {3415471260 10800 1 EEST}
+ {3429298800 7200 0 EET}
+ {3446920860 10800 1 EEST}
+ {3460748400 7200 0 EET}
+ {3478975260 10800 1 EEST}
+ {3492802800 7200 0 EET}
+ {3510424860 10800 1 EEST}
+ {3524252400 7200 0 EET}
+ {3541874460 10800 1 EEST}
+ {3555702000 7200 0 EET}
+ {3573324060 10800 1 EEST}
+ {3587151600 7200 0 EET}
+ {3604773660 10800 1 EEST}
+ {3618601200 7200 0 EET}
+ {3636828060 10800 1 EEST}
+ {3650655600 7200 0 EET}
+ {3668277660 10800 1 EEST}
+ {3682105200 7200 0 EET}
+ {3699727260 10800 1 EEST}
+ {3713554800 7200 0 EET}
+ {3731176860 10800 1 EEST}
+ {3745004400 7200 0 EET}
+ {3762626460 10800 1 EEST}
+ {3776454000 7200 0 EET}
+ {3794076060 10800 1 EEST}
+ {3807903600 7200 0 EET}
+ {3826130460 10800 1 EEST}
+ {3839958000 7200 0 EET}
+ {3857580060 10800 1 EEST}
+ {3871407600 7200 0 EET}
+ {3889029660 10800 1 EEST}
+ {3902857200 7200 0 EET}
+ {3920479260 10800 1 EEST}
+ {3934306800 7200 0 EET}
+ {3951928860 10800 1 EEST}
+ {3965756400 7200 0 EET}
+ {3983983260 10800 1 EEST}
+ {3997810800 7200 0 EET}
+ {4015432860 10800 1 EEST}
+ {4029260400 7200 0 EET}
+ {4046882460 10800 1 EEST}
+ {4060710000 7200 0 EET}
+ {4078332060 10800 1 EEST}
+ {4092159600 7200 0 EET}
+}
diff --git a/library/tzdata/Asia/Harbin b/library/tzdata/Asia/Harbin
new file mode 100644
index 0000000..0eb0c12
--- /dev/null
+++ b/library/tzdata/Asia/Harbin
@@ -0,0 +1,22 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Harbin) {
+ {-9223372036854775808 30404 0 LMT}
+ {-1325492804 30600 0 CHAT}
+ {-1194078600 28800 0 CST}
+ {-946800000 32400 0 CHAT}
+ {-115894800 30600 0 CHAT}
+ {325956600 28800 0 CST}
+ {515520000 32400 1 CDT}
+ {527007600 28800 0 CST}
+ {545155200 32400 1 CDT}
+ {558457200 28800 0 CST}
+ {576604800 32400 1 CDT}
+ {589906800 28800 0 CST}
+ {608659200 32400 1 CDT}
+ {621961200 28800 0 CST}
+ {640108800 32400 1 CDT}
+ {653410800 28800 0 CST}
+ {671558400 32400 1 CDT}
+ {684860400 28800 0 CST}
+}
diff --git a/library/tzdata/Asia/Ho_Chi_Minh b/library/tzdata/Asia/Ho_Chi_Minh
new file mode 100644
index 0000000..777c8db
--- /dev/null
+++ b/library/tzdata/Asia/Ho_Chi_Minh
@@ -0,0 +1,9 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Ho_Chi_Minh) {
+ {-9223372036854775808 25600 0 LMT}
+ {-2005974400 25580 0 SMT}
+ {-1855983920 25200 0 ICT}
+ {-1819954800 28800 0 ICT}
+ {-1220428800 25200 0 ICT}
+}
diff --git a/library/tzdata/Asia/Hong_Kong b/library/tzdata/Asia/Hong_Kong
new file mode 100644
index 0000000..928cde6
--- /dev/null
+++ b/library/tzdata/Asia/Hong_Kong
@@ -0,0 +1,75 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Hong_Kong) {
+ {-9223372036854775808 27396 0 LMT}
+ {-2056692996 28800 0 HKT}
+ {-907389000 32400 1 HKST}
+ {-891667800 28800 0 HKT}
+ {-884246400 32400 0 JST}
+ {-766746000 28800 0 HKT}
+ {-747981000 32400 1 HKST}
+ {-728544600 28800 0 HKT}
+ {-717049800 32400 1 HKST}
+ {-694503000 28800 0 HKT}
+ {-683785800 32400 1 HKST}
+ {-668064600 28800 0 HKT}
+ {-654755400 32400 1 HKST}
+ {-636615000 28800 0 HKT}
+ {-623305800 32400 1 HKST}
+ {-605165400 28800 0 HKT}
+ {-591856200 32400 1 HKST}
+ {-573715800 28800 0 HKT}
+ {-559801800 32400 1 HKST}
+ {-542352600 28800 0 HKT}
+ {-528352200 32400 1 HKST}
+ {-510211800 28800 0 HKT}
+ {-498112200 32400 1 HKST}
+ {-478762200 28800 0 HKT}
+ {-466662600 32400 1 HKST}
+ {-446707800 28800 0 HKT}
+ {-435213000 32400 1 HKST}
+ {-415258200 28800 0 HKT}
+ {-403158600 32400 1 HKST}
+ {-383808600 28800 0 HKT}
+ {-371709000 32400 1 HKST}
+ {-352359000 28800 0 HKT}
+ {-340259400 32400 1 HKST}
+ {-320909400 28800 0 HKT}
+ {-308809800 32400 1 HKST}
+ {-288855000 28800 0 HKT}
+ {-277360200 32400 1 HKST}
+ {-257405400 28800 0 HKT}
+ {-245910600 32400 1 HKST}
+ {-225955800 28800 0 HKT}
+ {-213856200 32400 1 HKST}
+ {-194506200 28800 0 HKT}
+ {-182406600 32400 1 HKST}
+ {-163056600 28800 0 HKT}
+ {-148537800 32400 1 HKST}
+ {-132816600 28800 0 HKT}
+ {-117088200 32400 1 HKST}
+ {-101367000 28800 0 HKT}
+ {-85638600 32400 1 HKST}
+ {-69312600 28800 0 HKT}
+ {-53584200 32400 1 HKST}
+ {-37863000 28800 0 HKT}
+ {-22134600 32400 1 HKST}
+ {-6413400 28800 0 HKT}
+ {9315000 32400 1 HKST}
+ {25036200 28800 0 HKT}
+ {40764600 32400 1 HKST}
+ {56485800 28800 0 HKT}
+ {72214200 32400 1 HKST}
+ {88540200 28800 0 HKT}
+ {104268600 32400 1 HKST}
+ {119989800 28800 0 HKT}
+ {126041400 32400 1 HKST}
+ {135714600 32400 1 HKST}
+ {151439400 28800 0 HKT}
+ {167167800 32400 1 HKST}
+ {182889000 28800 0 HKT}
+ {198617400 32400 1 HKST}
+ {214338600 28800 0 HKT}
+ {295385400 32400 1 HKST}
+ {309292200 28800 0 HKT}
+}
diff --git a/library/tzdata/Asia/Hovd b/library/tzdata/Asia/Hovd
new file mode 100644
index 0000000..2a87dab
--- /dev/null
+++ b/library/tzdata/Asia/Hovd
@@ -0,0 +1,51 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Hovd) {
+ {-9223372036854775808 21996 0 LMT}
+ {-2032927596 21600 0 HOVT}
+ {252439200 25200 0 HOVT}
+ {417978000 28800 1 HOVST}
+ {433785600 25200 0 HOVT}
+ {449600400 28800 1 HOVST}
+ {465321600 25200 0 HOVT}
+ {481050000 28800 1 HOVST}
+ {496771200 25200 0 HOVT}
+ {512499600 28800 1 HOVST}
+ {528220800 25200 0 HOVT}
+ {543949200 28800 1 HOVST}
+ {559670400 25200 0 HOVT}
+ {575398800 28800 1 HOVST}
+ {591120000 25200 0 HOVT}
+ {606848400 28800 1 HOVST}
+ {622569600 25200 0 HOVT}
+ {638298000 28800 1 HOVST}
+ {654624000 25200 0 HOVT}
+ {670352400 28800 1 HOVST}
+ {686073600 25200 0 HOVT}
+ {701802000 28800 1 HOVST}
+ {717523200 25200 0 HOVT}
+ {733251600 28800 1 HOVST}
+ {748972800 25200 0 HOVT}
+ {764701200 28800 1 HOVST}
+ {780422400 25200 0 HOVT}
+ {796150800 28800 1 HOVST}
+ {811872000 25200 0 HOVT}
+ {828205200 28800 1 HOVST}
+ {843926400 25200 0 HOVT}
+ {859654800 28800 1 HOVST}
+ {875376000 25200 0 HOVT}
+ {891104400 28800 1 HOVST}
+ {906825600 25200 0 HOVT}
+ {988398000 28800 1 HOVST}
+ {1001700000 25200 0 HOVT}
+ {1017428400 28800 1 HOVST}
+ {1033149600 25200 0 HOVT}
+ {1048878000 28800 1 HOVST}
+ {1064599200 25200 0 HOVT}
+ {1080327600 28800 1 HOVST}
+ {1096048800 25200 0 HOVT}
+ {1111777200 28800 1 HOVST}
+ {1127498400 25200 0 HOVT}
+ {1143226800 28800 1 HOVST}
+ {1159552800 25200 0 HOVT}
+}
diff --git a/library/tzdata/Asia/Irkutsk b/library/tzdata/Asia/Irkutsk
new file mode 100644
index 0000000..bca1dcc
--- /dev/null
+++ b/library/tzdata/Asia/Irkutsk
@@ -0,0 +1,71 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Irkutsk) {
+ {-9223372036854775808 25040 0 LMT}
+ {-2840165840 25040 0 IMT}
+ {-1575874640 25200 0 IRKT}
+ {-1247554800 28800 0 IRKMMTT}
+ {354902400 32400 1 IRKST}
+ {370710000 28800 0 IRKT}
+ {386438400 32400 1 IRKST}
+ {402246000 28800 0 IRKT}
+ {417974400 32400 1 IRKST}
+ {433782000 28800 0 IRKT}
+ {449596800 32400 1 IRKST}
+ {465328800 28800 0 IRKT}
+ {481053600 32400 1 IRKST}
+ {496778400 28800 0 IRKT}
+ {512503200 32400 1 IRKST}
+ {528228000 28800 0 IRKT}
+ {543952800 32400 1 IRKST}
+ {559677600 28800 0 IRKT}
+ {575402400 32400 1 IRKST}
+ {591127200 28800 0 IRKT}
+ {606852000 32400 1 IRKST}
+ {622576800 28800 0 IRKT}
+ {638301600 32400 1 IRKST}
+ {654631200 28800 0 IRKT}
+ {670356000 25200 0 IRKMMTT}
+ {670359600 28800 1 IRKST}
+ {686084400 25200 0 IRKT}
+ {695761200 28800 0 IRKMMTT}
+ {701794800 32400 1 IRKST}
+ {717516000 28800 0 IRKT}
+ {733255200 32400 1 IRKST}
+ {748980000 28800 0 IRKT}
+ {764704800 32400 1 IRKST}
+ {780429600 28800 0 IRKT}
+ {796154400 32400 1 IRKST}
+ {811879200 28800 0 IRKT}
+ {828208800 32400 1 IRKST}
+ {846352800 28800 0 IRKT}
+ {859658400 32400 1 IRKST}
+ {877802400 28800 0 IRKT}
+ {891108000 32400 1 IRKST}
+ {909252000 28800 0 IRKT}
+ {922557600 32400 1 IRKST}
+ {941306400 28800 0 IRKT}
+ {954007200 32400 1 IRKST}
+ {972756000 28800 0 IRKT}
+ {985456800 32400 1 IRKST}
+ {1004205600 28800 0 IRKT}
+ {1017511200 32400 1 IRKST}
+ {1035655200 28800 0 IRKT}
+ {1048960800 32400 1 IRKST}
+ {1067104800 28800 0 IRKT}
+ {1080410400 32400 1 IRKST}
+ {1099159200 28800 0 IRKT}
+ {1111860000 32400 1 IRKST}
+ {1130608800 28800 0 IRKT}
+ {1143309600 32400 1 IRKST}
+ {1162058400 28800 0 IRKT}
+ {1174759200 32400 1 IRKST}
+ {1193508000 28800 0 IRKT}
+ {1206813600 32400 1 IRKST}
+ {1224957600 28800 0 IRKT}
+ {1238263200 32400 1 IRKST}
+ {1256407200 28800 0 IRKT}
+ {1269712800 32400 1 IRKST}
+ {1288461600 28800 0 IRKT}
+ {1301162400 32400 0 IRKT}
+}
diff --git a/library/tzdata/Asia/Istanbul b/library/tzdata/Asia/Istanbul
new file mode 100644
index 0000000..85b3fc2
--- /dev/null
+++ b/library/tzdata/Asia/Istanbul
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/Istanbul)]} {
+ LoadTimeZoneFile Europe/Istanbul
+}
+set TZData(:Asia/Istanbul) $TZData(:Europe/Istanbul)
diff --git a/library/tzdata/Asia/Jakarta b/library/tzdata/Asia/Jakarta
new file mode 100644
index 0000000..27033e8
--- /dev/null
+++ b/library/tzdata/Asia/Jakarta
@@ -0,0 +1,13 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Jakarta) {
+ {-9223372036854775808 25632 0 LMT}
+ {-3231299232 25632 0 JMT}
+ {-1451719200 26400 0 JAVT}
+ {-1172906400 27000 0 WIT}
+ {-876641400 32400 0 JST}
+ {-766054800 27000 0 WIT}
+ {-683883000 28800 0 WIT}
+ {-620812800 27000 0 WIT}
+ {-189415800 25200 0 WIT}
+}
diff --git a/library/tzdata/Asia/Jayapura b/library/tzdata/Asia/Jayapura
new file mode 100644
index 0000000..893da8b
--- /dev/null
+++ b/library/tzdata/Asia/Jayapura
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Jayapura) {
+ {-9223372036854775808 33768 0 LMT}
+ {-1172913768 32400 0 EIT}
+ {-799491600 34200 0 CST}
+ {-189423000 32400 0 EIT}
+}
diff --git a/library/tzdata/Asia/Jerusalem b/library/tzdata/Asia/Jerusalem
new file mode 100644
index 0000000..48e213d
--- /dev/null
+++ b/library/tzdata/Asia/Jerusalem
@@ -0,0 +1,148 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Jerusalem) {
+ {-9223372036854775808 8456 0 LMT}
+ {-2840149256 8440 0 JMT}
+ {-1641003640 7200 0 IST}
+ {-933645600 10800 1 IDT}
+ {-857358000 7200 0 IST}
+ {-844300800 10800 1 IDT}
+ {-825822000 7200 0 IST}
+ {-812685600 10800 1 IDT}
+ {-794199600 7200 0 IST}
+ {-779853600 10800 1 IDT}
+ {-762656400 7200 0 IST}
+ {-748310400 10800 1 IDT}
+ {-731127600 7200 0 IST}
+ {-681962400 14400 1 IDDT}
+ {-673243200 10800 1 IDT}
+ {-667962000 7200 0 IST}
+ {-652327200 10800 1 IDT}
+ {-636426000 7200 0 IST}
+ {-622087200 10800 1 IDT}
+ {-608947200 7200 0 IST}
+ {-591847200 10800 1 IDT}
+ {-572486400 7200 0 IST}
+ {-558576000 10800 1 IDT}
+ {-542851200 7200 0 IST}
+ {-527731200 10800 1 IDT}
+ {-514425600 7200 0 IST}
+ {-490845600 10800 1 IDT}
+ {-482986800 7200 0 IST}
+ {-459475200 10800 1 IDT}
+ {-451537200 7200 0 IST}
+ {-428551200 10800 1 IDT}
+ {-418262400 7200 0 IST}
+ {-400032000 10800 1 IDT}
+ {-387428400 7200 0 IST}
+ {142380000 10800 1 IDT}
+ {150843600 7200 0 IST}
+ {167176800 10800 1 IDT}
+ {178664400 7200 0 IST}
+ {482277600 10800 1 IDT}
+ {495579600 7200 0 IST}
+ {516751200 10800 1 IDT}
+ {526424400 7200 0 IST}
+ {545436000 10800 1 IDT}
+ {558478800 7200 0 IST}
+ {576540000 10800 1 IDT}
+ {589237200 7200 0 IST}
+ {609890400 10800 1 IDT}
+ {620773200 7200 0 IST}
+ {638316000 10800 1 IDT}
+ {651618000 7200 0 IST}
+ {669765600 10800 1 IDT}
+ {683672400 7200 0 IST}
+ {701820000 10800 1 IDT}
+ {715726800 7200 0 IST}
+ {733701600 10800 1 IDT}
+ {747176400 7200 0 IST}
+ {765151200 10800 1 IDT}
+ {778021200 7200 0 IST}
+ {796600800 10800 1 IDT}
+ {810075600 7200 0 IST}
+ {826840800 10800 1 IDT}
+ {842821200 7200 0 IST}
+ {858895200 10800 1 IDT}
+ {874184400 7200 0 IST}
+ {890344800 10800 1 IDT}
+ {905029200 7200 0 IST}
+ {923011200 10800 1 IDT}
+ {936313200 7200 0 IST}
+ {955670400 10800 1 IDT}
+ {970783200 7200 0 IST}
+ {986770800 10800 1 IDT}
+ {1001282400 7200 0 IST}
+ {1017356400 10800 1 IDT}
+ {1033941600 7200 0 IST}
+ {1048806000 10800 1 IDT}
+ {1065132000 7200 0 IST}
+ {1081292400 10800 1 IDT}
+ {1095804000 7200 0 IST}
+ {1112313600 10800 1 IDT}
+ {1128812400 7200 0 IST}
+ {1143763200 10800 1 IDT}
+ {1159657200 7200 0 IST}
+ {1175212800 10800 1 IDT}
+ {1189897200 7200 0 IST}
+ {1206662400 10800 1 IDT}
+ {1223161200 7200 0 IST}
+ {1238112000 10800 1 IDT}
+ {1254006000 7200 0 IST}
+ {1269561600 10800 1 IDT}
+ {1284246000 7200 0 IST}
+ {1301616000 10800 1 IDT}
+ {1317510000 7200 0 IST}
+ {1333065600 10800 1 IDT}
+ {1348354800 7200 0 IST}
+ {1364515200 10800 1 IDT}
+ {1378594800 7200 0 IST}
+ {1395964800 10800 1 IDT}
+ {1411858800 7200 0 IST}
+ {1427414400 10800 1 IDT}
+ {1442703600 7200 0 IST}
+ {1459468800 10800 1 IDT}
+ {1475967600 7200 0 IST}
+ {1490918400 10800 1 IDT}
+ {1506207600 7200 0 IST}
+ {1522368000 10800 1 IDT}
+ {1537052400 7200 0 IST}
+ {1553817600 10800 1 IDT}
+ {1570316400 7200 0 IST}
+ {1585267200 10800 1 IDT}
+ {1601161200 7200 0 IST}
+ {1616716800 10800 1 IDT}
+ {1631401200 7200 0 IST}
+ {1648771200 10800 1 IDT}
+ {1664665200 7200 0 IST}
+ {1680220800 10800 1 IDT}
+ {1695510000 7200 0 IST}
+ {1711670400 10800 1 IDT}
+ {1728169200 7200 0 IST}
+ {1743120000 10800 1 IDT}
+ {1759014000 7200 0 IST}
+ {1774569600 10800 1 IDT}
+ {1789858800 7200 0 IST}
+ {1806019200 10800 1 IDT}
+ {1823122800 7200 0 IST}
+ {1838073600 10800 1 IDT}
+ {1853362800 7200 0 IST}
+ {1869523200 10800 1 IDT}
+ {1884207600 7200 0 IST}
+ {1900972800 10800 1 IDT}
+ {1917471600 7200 0 IST}
+ {1932422400 10800 1 IDT}
+ {1947711600 7200 0 IST}
+ {1963872000 10800 1 IDT}
+ {1978556400 7200 0 IST}
+ {1995926400 10800 1 IDT}
+ {2011820400 7200 0 IST}
+ {2027376000 10800 1 IDT}
+ {2042060400 7200 0 IST}
+ {2058825600 10800 1 IDT}
+ {2075324400 7200 0 IST}
+ {2090275200 10800 1 IDT}
+ {2106169200 7200 0 IST}
+ {2121724800 10800 1 IDT}
+ {2136409200 7200 0 IST}
+}
diff --git a/library/tzdata/Asia/Kabul b/library/tzdata/Asia/Kabul
new file mode 100644
index 0000000..33d7282
--- /dev/null
+++ b/library/tzdata/Asia/Kabul
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Kabul) {
+ {-9223372036854775808 16608 0 LMT}
+ {-2524538208 14400 0 AFT}
+ {-788932800 16200 0 AFT}
+}
diff --git a/library/tzdata/Asia/Kamchatka b/library/tzdata/Asia/Kamchatka
new file mode 100644
index 0000000..82abcfa
--- /dev/null
+++ b/library/tzdata/Asia/Kamchatka
@@ -0,0 +1,71 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Kamchatka) {
+ {-9223372036854775808 38076 0 LMT}
+ {-1487759676 39600 0 PETT}
+ {-1247569200 43200 0 PETMMTT}
+ {354888000 46800 1 PETST}
+ {370695600 43200 0 PETT}
+ {386424000 46800 1 PETST}
+ {402231600 43200 0 PETT}
+ {417960000 46800 1 PETST}
+ {433767600 43200 0 PETT}
+ {449582400 46800 1 PETST}
+ {465314400 43200 0 PETT}
+ {481039200 46800 1 PETST}
+ {496764000 43200 0 PETT}
+ {512488800 46800 1 PETST}
+ {528213600 43200 0 PETT}
+ {543938400 46800 1 PETST}
+ {559663200 43200 0 PETT}
+ {575388000 46800 1 PETST}
+ {591112800 43200 0 PETT}
+ {606837600 46800 1 PETST}
+ {622562400 43200 0 PETT}
+ {638287200 46800 1 PETST}
+ {654616800 43200 0 PETT}
+ {670341600 39600 0 PETMMTT}
+ {670345200 43200 1 PETST}
+ {686070000 39600 0 PETT}
+ {695746800 43200 0 PETMMTT}
+ {701780400 46800 1 PETST}
+ {717501600 43200 0 PETT}
+ {733240800 46800 1 PETST}
+ {748965600 43200 0 PETT}
+ {764690400 46800 1 PETST}
+ {780415200 43200 0 PETT}
+ {796140000 46800 1 PETST}
+ {811864800 43200 0 PETT}
+ {828194400 46800 1 PETST}
+ {846338400 43200 0 PETT}
+ {859644000 46800 1 PETST}
+ {877788000 43200 0 PETT}
+ {891093600 46800 1 PETST}
+ {909237600 43200 0 PETT}
+ {922543200 46800 1 PETST}
+ {941292000 43200 0 PETT}
+ {953992800 46800 1 PETST}
+ {972741600 43200 0 PETT}
+ {985442400 46800 1 PETST}
+ {1004191200 43200 0 PETT}
+ {1017496800 46800 1 PETST}
+ {1035640800 43200 0 PETT}
+ {1048946400 46800 1 PETST}
+ {1067090400 43200 0 PETT}
+ {1080396000 46800 1 PETST}
+ {1099144800 43200 0 PETT}
+ {1111845600 46800 1 PETST}
+ {1130594400 43200 0 PETT}
+ {1143295200 46800 1 PETST}
+ {1162044000 43200 0 PETT}
+ {1174744800 46800 1 PETST}
+ {1193493600 43200 0 PETT}
+ {1206799200 46800 1 PETST}
+ {1224943200 43200 0 PETT}
+ {1238248800 46800 1 PETST}
+ {1256392800 43200 0 PETT}
+ {1269698400 39600 0 PETMMTT}
+ {1269702000 43200 1 PETST}
+ {1288450800 39600 0 PETT}
+ {1301151600 43200 0 PETT}
+}
diff --git a/library/tzdata/Asia/Karachi b/library/tzdata/Asia/Karachi
new file mode 100644
index 0000000..3faa31e
--- /dev/null
+++ b/library/tzdata/Asia/Karachi
@@ -0,0 +1,16 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Karachi) {
+ {-9223372036854775808 16092 0 LMT}
+ {-1988166492 19800 0 IST}
+ {-862637400 23400 1 IST}
+ {-764145000 19800 0 IST}
+ {-576135000 18000 0 KART}
+ {38775600 18000 0 PKT}
+ {1018119660 21600 1 PKST}
+ {1033840860 18000 0 PKT}
+ {1212260400 21600 1 PKST}
+ {1225476000 18000 0 PKT}
+ {1239735600 21600 1 PKST}
+ {1257012000 18000 0 PKT}
+}
diff --git a/library/tzdata/Asia/Kashgar b/library/tzdata/Asia/Kashgar
new file mode 100644
index 0000000..2f64f42
--- /dev/null
+++ b/library/tzdata/Asia/Kashgar
@@ -0,0 +1,20 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Kashgar) {
+ {-9223372036854775808 18236 0 LMT}
+ {-1325480636 19800 0 KAST}
+ {-946791000 18000 0 KAST}
+ {325969200 28800 0 CST}
+ {515520000 32400 1 CDT}
+ {527007600 28800 0 CST}
+ {545155200 32400 1 CDT}
+ {558457200 28800 0 CST}
+ {576604800 32400 1 CDT}
+ {589906800 28800 0 CST}
+ {608659200 32400 1 CDT}
+ {621961200 28800 0 CST}
+ {640108800 32400 1 CDT}
+ {653410800 28800 0 CST}
+ {671558400 32400 1 CDT}
+ {684860400 28800 0 CST}
+}
diff --git a/library/tzdata/Asia/Kathmandu b/library/tzdata/Asia/Kathmandu
new file mode 100644
index 0000000..dbec1f0
--- /dev/null
+++ b/library/tzdata/Asia/Kathmandu
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Kathmandu) {
+ {-9223372036854775808 20476 0 LMT}
+ {-1577943676 19800 0 IST}
+ {504901800 20700 0 NPT}
+}
diff --git a/library/tzdata/Asia/Katmandu b/library/tzdata/Asia/Katmandu
new file mode 100644
index 0000000..2d6d060
--- /dev/null
+++ b/library/tzdata/Asia/Katmandu
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Asia/Kathmandu)]} {
+ LoadTimeZoneFile Asia/Kathmandu
+}
+set TZData(:Asia/Katmandu) $TZData(:Asia/Kathmandu)
diff --git a/library/tzdata/Asia/Kolkata b/library/tzdata/Asia/Kolkata
new file mode 100644
index 0000000..a87bf31
--- /dev/null
+++ b/library/tzdata/Asia/Kolkata
@@ -0,0 +1,10 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Kolkata) {
+ {-9223372036854775808 21208 0 LMT}
+ {-2840162008 21200 0 HMT}
+ {-891582800 23400 0 BURT}
+ {-872058600 19800 0 IST}
+ {-862637400 23400 1 IST}
+ {-764145000 19800 0 IST}
+}
diff --git a/library/tzdata/Asia/Krasnoyarsk b/library/tzdata/Asia/Krasnoyarsk
new file mode 100644
index 0000000..13dfeb5
--- /dev/null
+++ b/library/tzdata/Asia/Krasnoyarsk
@@ -0,0 +1,70 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Krasnoyarsk) {
+ {-9223372036854775808 22280 0 LMT}
+ {-1577513480 21600 0 KRAT}
+ {-1247551200 25200 0 KRAMMTT}
+ {354906000 28800 1 KRAST}
+ {370713600 25200 0 KRAT}
+ {386442000 28800 1 KRAST}
+ {402249600 25200 0 KRAT}
+ {417978000 28800 1 KRAST}
+ {433785600 25200 0 KRAT}
+ {449600400 28800 1 KRAST}
+ {465332400 25200 0 KRAT}
+ {481057200 28800 1 KRAST}
+ {496782000 25200 0 KRAT}
+ {512506800 28800 1 KRAST}
+ {528231600 25200 0 KRAT}
+ {543956400 28800 1 KRAST}
+ {559681200 25200 0 KRAT}
+ {575406000 28800 1 KRAST}
+ {591130800 25200 0 KRAT}
+ {606855600 28800 1 KRAST}
+ {622580400 25200 0 KRAT}
+ {638305200 28800 1 KRAST}
+ {654634800 25200 0 KRAT}
+ {670359600 21600 0 KRAMMTT}
+ {670363200 25200 1 KRAST}
+ {686088000 21600 0 KRAT}
+ {695764800 25200 0 KRAMMTT}
+ {701798400 28800 1 KRAST}
+ {717519600 25200 0 KRAT}
+ {733258800 28800 1 KRAST}
+ {748983600 25200 0 KRAT}
+ {764708400 28800 1 KRAST}
+ {780433200 25200 0 KRAT}
+ {796158000 28800 1 KRAST}
+ {811882800 25200 0 KRAT}
+ {828212400 28800 1 KRAST}
+ {846356400 25200 0 KRAT}
+ {859662000 28800 1 KRAST}
+ {877806000 25200 0 KRAT}
+ {891111600 28800 1 KRAST}
+ {909255600 25200 0 KRAT}
+ {922561200 28800 1 KRAST}
+ {941310000 25200 0 KRAT}
+ {954010800 28800 1 KRAST}
+ {972759600 25200 0 KRAT}
+ {985460400 28800 1 KRAST}
+ {1004209200 25200 0 KRAT}
+ {1017514800 28800 1 KRAST}
+ {1035658800 25200 0 KRAT}
+ {1048964400 28800 1 KRAST}
+ {1067108400 25200 0 KRAT}
+ {1080414000 28800 1 KRAST}
+ {1099162800 25200 0 KRAT}
+ {1111863600 28800 1 KRAST}
+ {1130612400 25200 0 KRAT}
+ {1143313200 28800 1 KRAST}
+ {1162062000 25200 0 KRAT}
+ {1174762800 28800 1 KRAST}
+ {1193511600 25200 0 KRAT}
+ {1206817200 28800 1 KRAST}
+ {1224961200 25200 0 KRAT}
+ {1238266800 28800 1 KRAST}
+ {1256410800 25200 0 KRAT}
+ {1269716400 28800 1 KRAST}
+ {1288465200 25200 0 KRAT}
+ {1301166000 28800 0 KRAT}
+}
diff --git a/library/tzdata/Asia/Kuala_Lumpur b/library/tzdata/Asia/Kuala_Lumpur
new file mode 100644
index 0000000..7a54bd6
--- /dev/null
+++ b/library/tzdata/Asia/Kuala_Lumpur
@@ -0,0 +1,13 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Kuala_Lumpur) {
+ {-9223372036854775808 24406 0 LMT}
+ {-2177477206 24925 0 SMT}
+ {-2038200925 25200 0 MALT}
+ {-1167634800 26400 1 MALST}
+ {-1073028000 26400 0 MALT}
+ {-894180000 27000 0 MALT}
+ {-879665400 32400 0 JST}
+ {-767005200 27000 0 MALT}
+ {378664200 28800 0 MYT}
+}
diff --git a/library/tzdata/Asia/Kuching b/library/tzdata/Asia/Kuching
new file mode 100644
index 0000000..0f9110c
--- /dev/null
+++ b/library/tzdata/Asia/Kuching
@@ -0,0 +1,24 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Kuching) {
+ {-9223372036854775808 26480 0 LMT}
+ {-1383463280 27000 0 BORT}
+ {-1167636600 28800 0 BORT}
+ {-1082448000 30000 1 BORTST}
+ {-1074586800 28800 0 BORT}
+ {-1050825600 30000 1 BORTST}
+ {-1042964400 28800 0 BORT}
+ {-1019289600 30000 1 BORTST}
+ {-1011428400 28800 0 BORT}
+ {-987753600 30000 1 BORTST}
+ {-979892400 28800 0 BORT}
+ {-956217600 30000 1 BORTST}
+ {-948356400 28800 0 BORT}
+ {-924595200 30000 1 BORTST}
+ {-916734000 28800 0 BORT}
+ {-893059200 30000 1 BORTST}
+ {-885198000 28800 0 BORT}
+ {-879667200 32400 0 JST}
+ {-767005200 28800 0 BORT}
+ {378662400 28800 0 MYT}
+}
diff --git a/library/tzdata/Asia/Kuwait b/library/tzdata/Asia/Kuwait
new file mode 100644
index 0000000..15d26db
--- /dev/null
+++ b/library/tzdata/Asia/Kuwait
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Kuwait) {
+ {-9223372036854775808 11516 0 LMT}
+ {-631163516 10800 0 AST}
+}
diff --git a/library/tzdata/Asia/Macao b/library/tzdata/Asia/Macao
new file mode 100644
index 0000000..6e972ff
--- /dev/null
+++ b/library/tzdata/Asia/Macao
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Asia/Macau)]} {
+ LoadTimeZoneFile Asia/Macau
+}
+set TZData(:Asia/Macao) $TZData(:Asia/Macau)
diff --git a/library/tzdata/Asia/Macau b/library/tzdata/Asia/Macau
new file mode 100644
index 0000000..9d4abfe
--- /dev/null
+++ b/library/tzdata/Asia/Macau
@@ -0,0 +1,46 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Macau) {
+ {-9223372036854775808 27260 0 LMT}
+ {-1830411260 28800 0 MOT}
+ {-277360200 32400 1 MOST}
+ {-257405400 28800 0 MOT}
+ {-245910600 32400 1 MOST}
+ {-225955800 28800 0 MOT}
+ {-214473600 32400 1 MOST}
+ {-194506200 28800 0 MOT}
+ {-182406600 32400 1 MOST}
+ {-163056600 28800 0 MOT}
+ {-150969600 32400 1 MOST}
+ {-131619600 28800 0 MOT}
+ {-117088200 32400 1 MOST}
+ {-101367000 28800 0 MOT}
+ {-85638600 32400 1 MOST}
+ {-69312600 28800 0 MOT}
+ {-53584200 32400 1 MOST}
+ {-37863000 28800 0 MOT}
+ {-22134600 32400 1 MOST}
+ {-6413400 28800 0 MOT}
+ {9315000 32400 1 MOST}
+ {25036200 28800 0 MOT}
+ {40764600 32400 1 MOST}
+ {56485800 28800 0 MOT}
+ {72201600 32400 1 MOST}
+ {87922800 28800 0 MOT}
+ {103651200 32400 1 MOST}
+ {119977200 28800 0 MOT}
+ {135705600 32400 1 MOST}
+ {151439400 28800 0 MOT}
+ {167167800 32400 1 MOST}
+ {182889000 28800 0 MOT}
+ {198617400 32400 1 MOST}
+ {214338600 28800 0 MOT}
+ {230067000 32400 1 MOST}
+ {245788200 28800 0 MOT}
+ {261504000 32400 1 MOST}
+ {277225200 28800 0 MOT}
+ {292953600 32400 1 MOST}
+ {309279600 28800 0 MOT}
+ {325008000 32400 1 MOST}
+ {340729200 28800 0 MOT}
+}
diff --git a/library/tzdata/Asia/Magadan b/library/tzdata/Asia/Magadan
new file mode 100644
index 0000000..62e01c5
--- /dev/null
+++ b/library/tzdata/Asia/Magadan
@@ -0,0 +1,70 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Magadan) {
+ {-9223372036854775808 36192 0 LMT}
+ {-1441188192 36000 0 MAGT}
+ {-1247565600 39600 0 MAGMMTT}
+ {354891600 43200 1 MAGST}
+ {370699200 39600 0 MAGT}
+ {386427600 43200 1 MAGST}
+ {402235200 39600 0 MAGT}
+ {417963600 43200 1 MAGST}
+ {433771200 39600 0 MAGT}
+ {449586000 43200 1 MAGST}
+ {465318000 39600 0 MAGT}
+ {481042800 43200 1 MAGST}
+ {496767600 39600 0 MAGT}
+ {512492400 43200 1 MAGST}
+ {528217200 39600 0 MAGT}
+ {543942000 43200 1 MAGST}
+ {559666800 39600 0 MAGT}
+ {575391600 43200 1 MAGST}
+ {591116400 39600 0 MAGT}
+ {606841200 43200 1 MAGST}
+ {622566000 39600 0 MAGT}
+ {638290800 43200 1 MAGST}
+ {654620400 39600 0 MAGT}
+ {670345200 36000 0 MAGMMTT}
+ {670348800 39600 1 MAGST}
+ {686073600 36000 0 MAGT}
+ {695750400 39600 0 MAGMMTT}
+ {701784000 43200 1 MAGST}
+ {717505200 39600 0 MAGT}
+ {733244400 43200 1 MAGST}
+ {748969200 39600 0 MAGT}
+ {764694000 43200 1 MAGST}
+ {780418800 39600 0 MAGT}
+ {796143600 43200 1 MAGST}
+ {811868400 39600 0 MAGT}
+ {828198000 43200 1 MAGST}
+ {846342000 39600 0 MAGT}
+ {859647600 43200 1 MAGST}
+ {877791600 39600 0 MAGT}
+ {891097200 43200 1 MAGST}
+ {909241200 39600 0 MAGT}
+ {922546800 43200 1 MAGST}
+ {941295600 39600 0 MAGT}
+ {953996400 43200 1 MAGST}
+ {972745200 39600 0 MAGT}
+ {985446000 43200 1 MAGST}
+ {1004194800 39600 0 MAGT}
+ {1017500400 43200 1 MAGST}
+ {1035644400 39600 0 MAGT}
+ {1048950000 43200 1 MAGST}
+ {1067094000 39600 0 MAGT}
+ {1080399600 43200 1 MAGST}
+ {1099148400 39600 0 MAGT}
+ {1111849200 43200 1 MAGST}
+ {1130598000 39600 0 MAGT}
+ {1143298800 43200 1 MAGST}
+ {1162047600 39600 0 MAGT}
+ {1174748400 43200 1 MAGST}
+ {1193497200 39600 0 MAGT}
+ {1206802800 43200 1 MAGST}
+ {1224946800 39600 0 MAGT}
+ {1238252400 43200 1 MAGST}
+ {1256396400 39600 0 MAGT}
+ {1269702000 43200 1 MAGST}
+ {1288450800 39600 0 MAGT}
+ {1301151600 43200 0 MAGT}
+}
diff --git a/library/tzdata/Asia/Makassar b/library/tzdata/Asia/Makassar
new file mode 100644
index 0000000..aa604b4
--- /dev/null
+++ b/library/tzdata/Asia/Makassar
@@ -0,0 +1,9 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Makassar) {
+ {-9223372036854775808 28656 0 LMT}
+ {-1577951856 28656 0 MMT}
+ {-1172908656 28800 0 CIT}
+ {-880272000 32400 0 JST}
+ {-766054800 28800 0 CIT}
+}
diff --git a/library/tzdata/Asia/Manila b/library/tzdata/Asia/Manila
new file mode 100644
index 0000000..9cc25e8
--- /dev/null
+++ b/library/tzdata/Asia/Manila
@@ -0,0 +1,15 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Manila) {
+ {-9223372036854775808 -57360 0 LMT}
+ {-3944621040 29040 0 LMT}
+ {-2229321840 28800 0 PHT}
+ {-1046678400 32400 1 PHST}
+ {-1038733200 28800 0 PHT}
+ {-873273600 32400 0 JST}
+ {-794221200 28800 0 PHT}
+ {-496224000 32400 1 PHST}
+ {-489315600 28800 0 PHT}
+ {259344000 32400 1 PHST}
+ {275151600 28800 0 PHT}
+}
diff --git a/library/tzdata/Asia/Muscat b/library/tzdata/Asia/Muscat
new file mode 100644
index 0000000..21b5873
--- /dev/null
+++ b/library/tzdata/Asia/Muscat
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Muscat) {
+ {-9223372036854775808 14060 0 LMT}
+ {-1577937260 14400 0 GST}
+}
diff --git a/library/tzdata/Asia/Nicosia b/library/tzdata/Asia/Nicosia
new file mode 100644
index 0000000..73a7b4c
--- /dev/null
+++ b/library/tzdata/Asia/Nicosia
@@ -0,0 +1,257 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Nicosia) {
+ {-9223372036854775808 8008 0 LMT}
+ {-1518920008 7200 0 EET}
+ {166572000 10800 1 EEST}
+ {182293200 7200 0 EET}
+ {200959200 10800 1 EEST}
+ {213829200 7200 0 EET}
+ {228866400 10800 1 EEST}
+ {243982800 7200 0 EET}
+ {260316000 10800 1 EEST}
+ {276123600 7200 0 EET}
+ {291765600 10800 1 EEST}
+ {307486800 7200 0 EET}
+ {323820000 10800 1 EEST}
+ {338936400 7200 0 EET}
+ {354664800 10800 1 EEST}
+ {370386000 7200 0 EET}
+ {386114400 10800 1 EEST}
+ {401835600 7200 0 EET}
+ {417564000 10800 1 EEST}
+ {433285200 7200 0 EET}
+ {449013600 10800 1 EEST}
+ {465339600 7200 0 EET}
+ {481068000 10800 1 EEST}
+ {496789200 7200 0 EET}
+ {512517600 10800 1 EEST}
+ {528238800 7200 0 EET}
+ {543967200 10800 1 EEST}
+ {559688400 7200 0 EET}
+ {575416800 10800 1 EEST}
+ {591138000 7200 0 EET}
+ {606866400 10800 1 EEST}
+ {622587600 7200 0 EET}
+ {638316000 10800 1 EEST}
+ {654642000 7200 0 EET}
+ {670370400 10800 1 EEST}
+ {686091600 7200 0 EET}
+ {701820000 10800 1 EEST}
+ {717541200 7200 0 EET}
+ {733269600 10800 1 EEST}
+ {748990800 7200 0 EET}
+ {764719200 10800 1 EEST}
+ {780440400 7200 0 EET}
+ {796168800 10800 1 EEST}
+ {811890000 7200 0 EET}
+ {828223200 10800 1 EEST}
+ {843944400 7200 0 EET}
+ {859672800 10800 1 EEST}
+ {875394000 7200 0 EET}
+ {891122400 10800 1 EEST}
+ {904597200 10800 0 EEST}
+ {909277200 7200 0 EET}
+ {922582800 10800 1 EEST}
+ {941331600 7200 0 EET}
+ {954032400 10800 1 EEST}
+ {972781200 7200 0 EET}
+ {985482000 10800 1 EEST}
+ {1004230800 7200 0 EET}
+ {1017536400 10800 1 EEST}
+ {1035680400 7200 0 EET}
+ {1048986000 10800 1 EEST}
+ {1067130000 7200 0 EET}
+ {1080435600 10800 1 EEST}
+ {1099184400 7200 0 EET}
+ {1111885200 10800 1 EEST}
+ {1130634000 7200 0 EET}
+ {1143334800 10800 1 EEST}
+ {1162083600 7200 0 EET}
+ {1174784400 10800 1 EEST}
+ {1193533200 7200 0 EET}
+ {1206838800 10800 1 EEST}
+ {1224982800 7200 0 EET}
+ {1238288400 10800 1 EEST}
+ {1256432400 7200 0 EET}
+ {1269738000 10800 1 EEST}
+ {1288486800 7200 0 EET}
+ {1301187600 10800 1 EEST}
+ {1319936400 7200 0 EET}
+ {1332637200 10800 1 EEST}
+ {1351386000 7200 0 EET}
+ {1364691600 10800 1 EEST}
+ {1382835600 7200 0 EET}
+ {1396141200 10800 1 EEST}
+ {1414285200 7200 0 EET}
+ {1427590800 10800 1 EEST}
+ {1445734800 7200 0 EET}
+ {1459040400 10800 1 EEST}
+ {1477789200 7200 0 EET}
+ {1490490000 10800 1 EEST}
+ {1509238800 7200 0 EET}
+ {1521939600 10800 1 EEST}
+ {1540688400 7200 0 EET}
+ {1553994000 10800 1 EEST}
+ {1572138000 7200 0 EET}
+ {1585443600 10800 1 EEST}
+ {1603587600 7200 0 EET}
+ {1616893200 10800 1 EEST}
+ {1635642000 7200 0 EET}
+ {1648342800 10800 1 EEST}
+ {1667091600 7200 0 EET}
+ {1679792400 10800 1 EEST}
+ {1698541200 7200 0 EET}
+ {1711846800 10800 1 EEST}
+ {1729990800 7200 0 EET}
+ {1743296400 10800 1 EEST}
+ {1761440400 7200 0 EET}
+ {1774746000 10800 1 EEST}
+ {1792890000 7200 0 EET}
+ {1806195600 10800 1 EEST}
+ {1824944400 7200 0 EET}
+ {1837645200 10800 1 EEST}
+ {1856394000 7200 0 EET}
+ {1869094800 10800 1 EEST}
+ {1887843600 7200 0 EET}
+ {1901149200 10800 1 EEST}
+ {1919293200 7200 0 EET}
+ {1932598800 10800 1 EEST}
+ {1950742800 7200 0 EET}
+ {1964048400 10800 1 EEST}
+ {1982797200 7200 0 EET}
+ {1995498000 10800 1 EEST}
+ {2014246800 7200 0 EET}
+ {2026947600 10800 1 EEST}
+ {2045696400 7200 0 EET}
+ {2058397200 10800 1 EEST}
+ {2077146000 7200 0 EET}
+ {2090451600 10800 1 EEST}
+ {2108595600 7200 0 EET}
+ {2121901200 10800 1 EEST}
+ {2140045200 7200 0 EET}
+ {2153350800 10800 1 EEST}
+ {2172099600 7200 0 EET}
+ {2184800400 10800 1 EEST}
+ {2203549200 7200 0 EET}
+ {2216250000 10800 1 EEST}
+ {2234998800 7200 0 EET}
+ {2248304400 10800 1 EEST}
+ {2266448400 7200 0 EET}
+ {2279754000 10800 1 EEST}
+ {2297898000 7200 0 EET}
+ {2311203600 10800 1 EEST}
+ {2329347600 7200 0 EET}
+ {2342653200 10800 1 EEST}
+ {2361402000 7200 0 EET}
+ {2374102800 10800 1 EEST}
+ {2392851600 7200 0 EET}
+ {2405552400 10800 1 EEST}
+ {2424301200 7200 0 EET}
+ {2437606800 10800 1 EEST}
+ {2455750800 7200 0 EET}
+ {2469056400 10800 1 EEST}
+ {2487200400 7200 0 EET}
+ {2500506000 10800 1 EEST}
+ {2519254800 7200 0 EET}
+ {2531955600 10800 1 EEST}
+ {2550704400 7200 0 EET}
+ {2563405200 10800 1 EEST}
+ {2582154000 7200 0 EET}
+ {2595459600 10800 1 EEST}
+ {2613603600 7200 0 EET}
+ {2626909200 10800 1 EEST}
+ {2645053200 7200 0 EET}
+ {2658358800 10800 1 EEST}
+ {2676502800 7200 0 EET}
+ {2689808400 10800 1 EEST}
+ {2708557200 7200 0 EET}
+ {2721258000 10800 1 EEST}
+ {2740006800 7200 0 EET}
+ {2752707600 10800 1 EEST}
+ {2771456400 7200 0 EET}
+ {2784762000 10800 1 EEST}
+ {2802906000 7200 0 EET}
+ {2816211600 10800 1 EEST}
+ {2834355600 7200 0 EET}
+ {2847661200 10800 1 EEST}
+ {2866410000 7200 0 EET}
+ {2879110800 10800 1 EEST}
+ {2897859600 7200 0 EET}
+ {2910560400 10800 1 EEST}
+ {2929309200 7200 0 EET}
+ {2942010000 10800 1 EEST}
+ {2960758800 7200 0 EET}
+ {2974064400 10800 1 EEST}
+ {2992208400 7200 0 EET}
+ {3005514000 10800 1 EEST}
+ {3023658000 7200 0 EET}
+ {3036963600 10800 1 EEST}
+ {3055712400 7200 0 EET}
+ {3068413200 10800 1 EEST}
+ {3087162000 7200 0 EET}
+ {3099862800 10800 1 EEST}
+ {3118611600 7200 0 EET}
+ {3131917200 10800 1 EEST}
+ {3150061200 7200 0 EET}
+ {3163366800 10800 1 EEST}
+ {3181510800 7200 0 EET}
+ {3194816400 10800 1 EEST}
+ {3212960400 7200 0 EET}
+ {3226266000 10800 1 EEST}
+ {3245014800 7200 0 EET}
+ {3257715600 10800 1 EEST}
+ {3276464400 7200 0 EET}
+ {3289165200 10800 1 EEST}
+ {3307914000 7200 0 EET}
+ {3321219600 10800 1 EEST}
+ {3339363600 7200 0 EET}
+ {3352669200 10800 1 EEST}
+ {3370813200 7200 0 EET}
+ {3384118800 10800 1 EEST}
+ {3402867600 7200 0 EET}
+ {3415568400 10800 1 EEST}
+ {3434317200 7200 0 EET}
+ {3447018000 10800 1 EEST}
+ {3465766800 7200 0 EET}
+ {3479072400 10800 1 EEST}
+ {3497216400 7200 0 EET}
+ {3510522000 10800 1 EEST}
+ {3528666000 7200 0 EET}
+ {3541971600 10800 1 EEST}
+ {3560115600 7200 0 EET}
+ {3573421200 10800 1 EEST}
+ {3592170000 7200 0 EET}
+ {3604870800 10800 1 EEST}
+ {3623619600 7200 0 EET}
+ {3636320400 10800 1 EEST}
+ {3655069200 7200 0 EET}
+ {3668374800 10800 1 EEST}
+ {3686518800 7200 0 EET}
+ {3699824400 10800 1 EEST}
+ {3717968400 7200 0 EET}
+ {3731274000 10800 1 EEST}
+ {3750022800 7200 0 EET}
+ {3762723600 10800 1 EEST}
+ {3781472400 7200 0 EET}
+ {3794173200 10800 1 EEST}
+ {3812922000 7200 0 EET}
+ {3825622800 10800 1 EEST}
+ {3844371600 7200 0 EET}
+ {3857677200 10800 1 EEST}
+ {3875821200 7200 0 EET}
+ {3889126800 10800 1 EEST}
+ {3907270800 7200 0 EET}
+ {3920576400 10800 1 EEST}
+ {3939325200 7200 0 EET}
+ {3952026000 10800 1 EEST}
+ {3970774800 7200 0 EET}
+ {3983475600 10800 1 EEST}
+ {4002224400 7200 0 EET}
+ {4015530000 10800 1 EEST}
+ {4033674000 7200 0 EET}
+ {4046979600 10800 1 EEST}
+ {4065123600 7200 0 EET}
+ {4078429200 10800 1 EEST}
+ {4096573200 7200 0 EET}
+}
diff --git a/library/tzdata/Asia/Novokuznetsk b/library/tzdata/Asia/Novokuznetsk
new file mode 100644
index 0000000..9cd45c0
--- /dev/null
+++ b/library/tzdata/Asia/Novokuznetsk
@@ -0,0 +1,71 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Novokuznetsk) {
+ {-9223372036854775808 20928 0 NMT}
+ {-1577512128 21600 0 KRAT}
+ {-1247551200 25200 0 KRAMMTT}
+ {354906000 28800 1 KRAST}
+ {370713600 25200 0 KRAT}
+ {386442000 28800 1 KRAST}
+ {402249600 25200 0 KRAT}
+ {417978000 28800 1 KRAST}
+ {433785600 25200 0 KRAT}
+ {449600400 28800 1 KRAST}
+ {465332400 25200 0 KRAT}
+ {481057200 28800 1 KRAST}
+ {496782000 25200 0 KRAT}
+ {512506800 28800 1 KRAST}
+ {528231600 25200 0 KRAT}
+ {543956400 28800 1 KRAST}
+ {559681200 25200 0 KRAT}
+ {575406000 28800 1 KRAST}
+ {591130800 25200 0 KRAT}
+ {606855600 28800 1 KRAST}
+ {622580400 25200 0 KRAT}
+ {638305200 28800 1 KRAST}
+ {654634800 25200 0 KRAT}
+ {670359600 21600 0 KRAMMTT}
+ {670363200 25200 1 KRAST}
+ {686088000 21600 0 KRAT}
+ {695764800 25200 0 KRAMMTT}
+ {701798400 28800 1 KRAST}
+ {717519600 25200 0 KRAT}
+ {733258800 28800 1 KRAST}
+ {748983600 25200 0 KRAT}
+ {764708400 28800 1 KRAST}
+ {780433200 25200 0 KRAT}
+ {796158000 28800 1 KRAST}
+ {811882800 25200 0 KRAT}
+ {828212400 28800 1 KRAST}
+ {846356400 25200 0 KRAT}
+ {859662000 28800 1 KRAST}
+ {877806000 25200 0 KRAT}
+ {891111600 28800 1 KRAST}
+ {909255600 25200 0 KRAT}
+ {922561200 28800 1 KRAST}
+ {941310000 25200 0 KRAT}
+ {954010800 28800 1 KRAST}
+ {972759600 25200 0 KRAT}
+ {985460400 28800 1 KRAST}
+ {1004209200 25200 0 KRAT}
+ {1017514800 28800 1 KRAST}
+ {1035658800 25200 0 KRAT}
+ {1048964400 28800 1 KRAST}
+ {1067108400 25200 0 KRAT}
+ {1080414000 28800 1 KRAST}
+ {1099162800 25200 0 KRAT}
+ {1111863600 28800 1 KRAST}
+ {1130612400 25200 0 KRAT}
+ {1143313200 28800 1 KRAST}
+ {1162062000 25200 0 KRAT}
+ {1174762800 28800 1 KRAST}
+ {1193511600 25200 0 KRAT}
+ {1206817200 28800 1 KRAST}
+ {1224961200 25200 0 KRAT}
+ {1238266800 28800 1 KRAST}
+ {1256410800 25200 0 KRAT}
+ {1269716400 21600 0 NOVMMTT}
+ {1269720000 25200 1 NOVST}
+ {1288468800 21600 0 NOVT}
+ {1301169600 25200 0 NOVT}
+}
diff --git a/library/tzdata/Asia/Novosibirsk b/library/tzdata/Asia/Novosibirsk
new file mode 100644
index 0000000..5032eec
--- /dev/null
+++ b/library/tzdata/Asia/Novosibirsk
@@ -0,0 +1,71 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Novosibirsk) {
+ {-9223372036854775808 19900 0 LMT}
+ {-1579476700 21600 0 NOVT}
+ {-1247551200 25200 0 NOVMMTT}
+ {354906000 28800 1 NOVST}
+ {370713600 25200 0 NOVT}
+ {386442000 28800 1 NOVST}
+ {402249600 25200 0 NOVT}
+ {417978000 28800 1 NOVST}
+ {433785600 25200 0 NOVT}
+ {449600400 28800 1 NOVST}
+ {465332400 25200 0 NOVT}
+ {481057200 28800 1 NOVST}
+ {496782000 25200 0 NOVT}
+ {512506800 28800 1 NOVST}
+ {528231600 25200 0 NOVT}
+ {543956400 28800 1 NOVST}
+ {559681200 25200 0 NOVT}
+ {575406000 28800 1 NOVST}
+ {591130800 25200 0 NOVT}
+ {606855600 28800 1 NOVST}
+ {622580400 25200 0 NOVT}
+ {638305200 28800 1 NOVST}
+ {654634800 25200 0 NOVT}
+ {670359600 21600 0 NOVMMTT}
+ {670363200 25200 1 NOVST}
+ {686088000 21600 0 NOVT}
+ {695764800 25200 0 NOVMMTT}
+ {701798400 28800 1 NOVST}
+ {717519600 25200 0 NOVT}
+ {733258800 28800 1 NOVST}
+ {738090000 25200 0 NOVST}
+ {748987200 21600 0 NOVT}
+ {764712000 25200 1 NOVST}
+ {780436800 21600 0 NOVT}
+ {796161600 25200 1 NOVST}
+ {811886400 21600 0 NOVT}
+ {828216000 25200 1 NOVST}
+ {846360000 21600 0 NOVT}
+ {859665600 25200 1 NOVST}
+ {877809600 21600 0 NOVT}
+ {891115200 25200 1 NOVST}
+ {909259200 21600 0 NOVT}
+ {922564800 25200 1 NOVST}
+ {941313600 21600 0 NOVT}
+ {954014400 25200 1 NOVST}
+ {972763200 21600 0 NOVT}
+ {985464000 25200 1 NOVST}
+ {1004212800 21600 0 NOVT}
+ {1017518400 25200 1 NOVST}
+ {1035662400 21600 0 NOVT}
+ {1048968000 25200 1 NOVST}
+ {1067112000 21600 0 NOVT}
+ {1080417600 25200 1 NOVST}
+ {1099166400 21600 0 NOVT}
+ {1111867200 25200 1 NOVST}
+ {1130616000 21600 0 NOVT}
+ {1143316800 25200 1 NOVST}
+ {1162065600 21600 0 NOVT}
+ {1174766400 25200 1 NOVST}
+ {1193515200 21600 0 NOVT}
+ {1206820800 25200 1 NOVST}
+ {1224964800 21600 0 NOVT}
+ {1238270400 25200 1 NOVST}
+ {1256414400 21600 0 NOVT}
+ {1269720000 25200 1 NOVST}
+ {1288468800 21600 0 NOVT}
+ {1301169600 25200 0 NOVT}
+}
diff --git a/library/tzdata/Asia/Omsk b/library/tzdata/Asia/Omsk
new file mode 100644
index 0000000..ca90d2e
--- /dev/null
+++ b/library/tzdata/Asia/Omsk
@@ -0,0 +1,70 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Omsk) {
+ {-9223372036854775808 17616 0 LMT}
+ {-1582088016 18000 0 OMST}
+ {-1247547600 21600 0 OMSMMTT}
+ {354909600 25200 1 OMSST}
+ {370717200 21600 0 OMST}
+ {386445600 25200 1 OMSST}
+ {402253200 21600 0 OMST}
+ {417981600 25200 1 OMSST}
+ {433789200 21600 0 OMST}
+ {449604000 25200 1 OMSST}
+ {465336000 21600 0 OMST}
+ {481060800 25200 1 OMSST}
+ {496785600 21600 0 OMST}
+ {512510400 25200 1 OMSST}
+ {528235200 21600 0 OMST}
+ {543960000 25200 1 OMSST}
+ {559684800 21600 0 OMST}
+ {575409600 25200 1 OMSST}
+ {591134400 21600 0 OMST}
+ {606859200 25200 1 OMSST}
+ {622584000 21600 0 OMST}
+ {638308800 25200 1 OMSST}
+ {654638400 21600 0 OMST}
+ {670363200 18000 0 OMSMMTT}
+ {670366800 21600 1 OMSST}
+ {686091600 18000 0 OMST}
+ {695768400 21600 0 OMSMMTT}
+ {701802000 25200 1 OMSST}
+ {717523200 21600 0 OMST}
+ {733262400 25200 1 OMSST}
+ {748987200 21600 0 OMST}
+ {764712000 25200 1 OMSST}
+ {780436800 21600 0 OMST}
+ {796161600 25200 1 OMSST}
+ {811886400 21600 0 OMST}
+ {828216000 25200 1 OMSST}
+ {846360000 21600 0 OMST}
+ {859665600 25200 1 OMSST}
+ {877809600 21600 0 OMST}
+ {891115200 25200 1 OMSST}
+ {909259200 21600 0 OMST}
+ {922564800 25200 1 OMSST}
+ {941313600 21600 0 OMST}
+ {954014400 25200 1 OMSST}
+ {972763200 21600 0 OMST}
+ {985464000 25200 1 OMSST}
+ {1004212800 21600 0 OMST}
+ {1017518400 25200 1 OMSST}
+ {1035662400 21600 0 OMST}
+ {1048968000 25200 1 OMSST}
+ {1067112000 21600 0 OMST}
+ {1080417600 25200 1 OMSST}
+ {1099166400 21600 0 OMST}
+ {1111867200 25200 1 OMSST}
+ {1130616000 21600 0 OMST}
+ {1143316800 25200 1 OMSST}
+ {1162065600 21600 0 OMST}
+ {1174766400 25200 1 OMSST}
+ {1193515200 21600 0 OMST}
+ {1206820800 25200 1 OMSST}
+ {1224964800 21600 0 OMST}
+ {1238270400 25200 1 OMSST}
+ {1256414400 21600 0 OMST}
+ {1269720000 25200 1 OMSST}
+ {1288468800 21600 0 OMST}
+ {1301169600 25200 0 OMST}
+}
diff --git a/library/tzdata/Asia/Oral b/library/tzdata/Asia/Oral
new file mode 100644
index 0000000..88b9a29
--- /dev/null
+++ b/library/tzdata/Asia/Oral
@@ -0,0 +1,58 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Oral) {
+ {-9223372036854775808 12324 0 LMT}
+ {-1441164324 14400 0 URAT}
+ {-1247544000 18000 0 URAT}
+ {354913200 21600 1 URAST}
+ {370720800 21600 0 URAT}
+ {386445600 18000 0 URAT}
+ {386449200 21600 1 URAST}
+ {402256800 18000 0 URAT}
+ {417985200 21600 1 URAST}
+ {433792800 18000 0 URAT}
+ {449607600 21600 1 URAST}
+ {465339600 18000 0 URAT}
+ {481064400 21600 1 URAST}
+ {496789200 18000 0 URAT}
+ {512514000 21600 1 URAST}
+ {528238800 18000 0 URAT}
+ {543963600 21600 1 URAST}
+ {559688400 18000 0 URAT}
+ {575413200 21600 1 URAST}
+ {591138000 18000 0 URAT}
+ {606862800 14400 0 URAT}
+ {606866400 18000 1 URAST}
+ {622591200 14400 0 URAT}
+ {638316000 18000 1 URAST}
+ {654645600 14400 0 URAT}
+ {662673600 14400 0 URAT}
+ {692827200 14400 0 ORAT}
+ {701809200 18000 1 ORAST}
+ {717530400 14400 0 ORAT}
+ {733269600 18000 1 ORAST}
+ {748994400 14400 0 ORAT}
+ {764719200 18000 1 ORAST}
+ {780444000 14400 0 ORAT}
+ {796168800 18000 1 ORAST}
+ {811893600 14400 0 ORAT}
+ {828223200 18000 1 ORAST}
+ {846367200 14400 0 ORAT}
+ {859672800 18000 1 ORAST}
+ {877816800 14400 0 ORAT}
+ {891122400 18000 1 ORAST}
+ {909266400 14400 0 ORAT}
+ {922572000 18000 1 ORAST}
+ {941320800 14400 0 ORAT}
+ {954021600 18000 1 ORAST}
+ {972770400 14400 0 ORAT}
+ {985471200 18000 1 ORAST}
+ {1004220000 14400 0 ORAT}
+ {1017525600 18000 1 ORAST}
+ {1035669600 14400 0 ORAT}
+ {1048975200 18000 1 ORAST}
+ {1067119200 14400 0 ORAT}
+ {1080424800 18000 1 ORAST}
+ {1099173600 14400 0 ORAT}
+ {1110830400 18000 0 ORAT}
+}
diff --git a/library/tzdata/Asia/Phnom_Penh b/library/tzdata/Asia/Phnom_Penh
new file mode 100644
index 0000000..4f28420
--- /dev/null
+++ b/library/tzdata/Asia/Phnom_Penh
@@ -0,0 +1,9 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Phnom_Penh) {
+ {-9223372036854775808 25180 0 LMT}
+ {-2005973980 25580 0 SMT}
+ {-1855983920 25200 0 ICT}
+ {-1819954800 28800 0 ICT}
+ {-1220428800 25200 0 ICT}
+}
diff --git a/library/tzdata/Asia/Pontianak b/library/tzdata/Asia/Pontianak
new file mode 100644
index 0000000..f3567dd
--- /dev/null
+++ b/library/tzdata/Asia/Pontianak
@@ -0,0 +1,13 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Pontianak) {
+ {-9223372036854775808 26240 0 LMT}
+ {-1946186240 26240 0 PMT}
+ {-1172906240 27000 0 WIT}
+ {-881220600 32400 0 JST}
+ {-766054800 27000 0 WIT}
+ {-683883000 28800 0 WIT}
+ {-620812800 27000 0 WIT}
+ {-189415800 28800 0 CIT}
+ {567964800 25200 0 WIT}
+}
diff --git a/library/tzdata/Asia/Pyongyang b/library/tzdata/Asia/Pyongyang
new file mode 100644
index 0000000..21c9a68
--- /dev/null
+++ b/library/tzdata/Asia/Pyongyang
@@ -0,0 +1,11 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Pyongyang) {
+ {-9223372036854775808 30180 0 LMT}
+ {-2524551780 30600 0 KST}
+ {-2053931400 32400 0 KST}
+ {-1325494800 30600 0 KST}
+ {-1199262600 32400 0 KST}
+ {-498128400 28800 0 KST}
+ {-264931200 32400 0 KST}
+}
diff --git a/library/tzdata/Asia/Qatar b/library/tzdata/Asia/Qatar
new file mode 100644
index 0000000..bfb4eb4
--- /dev/null
+++ b/library/tzdata/Asia/Qatar
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Qatar) {
+ {-9223372036854775808 12368 0 LMT}
+ {-1577935568 14400 0 GST}
+ {76190400 10800 0 AST}
+}
diff --git a/library/tzdata/Asia/Qyzylorda b/library/tzdata/Asia/Qyzylorda
new file mode 100644
index 0000000..16da574
--- /dev/null
+++ b/library/tzdata/Asia/Qyzylorda
@@ -0,0 +1,58 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Qyzylorda) {
+ {-9223372036854775808 15712 0 LMT}
+ {-1441167712 14400 0 KIZT}
+ {-1247544000 18000 0 KIZT}
+ {354913200 21600 1 KIZST}
+ {370720800 21600 0 KIZT}
+ {386445600 18000 0 KIZT}
+ {386449200 21600 1 KIZST}
+ {402256800 18000 0 KIZT}
+ {417985200 21600 1 KIZST}
+ {433792800 18000 0 KIZT}
+ {449607600 21600 1 KIZST}
+ {465339600 18000 0 KIZT}
+ {481064400 21600 1 KIZST}
+ {496789200 18000 0 KIZT}
+ {512514000 21600 1 KIZST}
+ {528238800 18000 0 KIZT}
+ {543963600 21600 1 KIZST}
+ {559688400 18000 0 KIZT}
+ {575413200 21600 1 KIZST}
+ {591138000 18000 0 KIZT}
+ {606862800 21600 1 KIZST}
+ {622587600 18000 0 KIZT}
+ {638312400 21600 1 KIZST}
+ {654642000 18000 0 KIZT}
+ {662670000 18000 0 KIZT}
+ {692823600 18000 0 QYZT}
+ {695768400 21600 0 QYZT}
+ {701802000 25200 1 QYZST}
+ {717523200 21600 0 QYZT}
+ {733262400 25200 1 QYZST}
+ {748987200 21600 0 QYZT}
+ {764712000 25200 1 QYZST}
+ {780436800 21600 0 QYZT}
+ {796161600 25200 1 QYZST}
+ {811886400 21600 0 QYZT}
+ {828216000 25200 1 QYZST}
+ {846360000 21600 0 QYZT}
+ {859665600 25200 1 QYZST}
+ {877809600 21600 0 QYZT}
+ {891115200 25200 1 QYZST}
+ {909259200 21600 0 QYZT}
+ {922564800 25200 1 QYZST}
+ {941313600 21600 0 QYZT}
+ {954014400 25200 1 QYZST}
+ {972763200 21600 0 QYZT}
+ {985464000 25200 1 QYZST}
+ {1004212800 21600 0 QYZT}
+ {1017518400 25200 1 QYZST}
+ {1035662400 21600 0 QYZT}
+ {1048968000 25200 1 QYZST}
+ {1067112000 21600 0 QYZT}
+ {1080417600 25200 1 QYZST}
+ {1099166400 21600 0 QYZT}
+ {1110823200 21600 0 QYZT}
+}
diff --git a/library/tzdata/Asia/Rangoon b/library/tzdata/Asia/Rangoon
new file mode 100644
index 0000000..2b8c4fa
--- /dev/null
+++ b/library/tzdata/Asia/Rangoon
@@ -0,0 +1,9 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Rangoon) {
+ {-9223372036854775808 23080 0 LMT}
+ {-2840163880 23076 0 RMT}
+ {-1577946276 23400 0 BURT}
+ {-873268200 32400 0 JST}
+ {-778410000 23400 0 MMT}
+}
diff --git a/library/tzdata/Asia/Riyadh b/library/tzdata/Asia/Riyadh
new file mode 100644
index 0000000..0ef28a9
--- /dev/null
+++ b/library/tzdata/Asia/Riyadh
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Riyadh) {
+ {-9223372036854775808 11212 0 LMT}
+ {-631163212 10800 0 AST}
+}
diff --git a/library/tzdata/Asia/Saigon b/library/tzdata/Asia/Saigon
new file mode 100644
index 0000000..1e42eed
--- /dev/null
+++ b/library/tzdata/Asia/Saigon
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Asia/Ho_Chi_Minh)]} {
+ LoadTimeZoneFile Asia/Ho_Chi_Minh
+}
+set TZData(:Asia/Saigon) $TZData(:Asia/Ho_Chi_Minh)
diff --git a/library/tzdata/Asia/Sakhalin b/library/tzdata/Asia/Sakhalin
new file mode 100644
index 0000000..0b29e82
--- /dev/null
+++ b/library/tzdata/Asia/Sakhalin
@@ -0,0 +1,72 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Sakhalin) {
+ {-9223372036854775808 34248 0 LMT}
+ {-2031039048 32400 0 CJT}
+ {-1009875600 32400 0 JST}
+ {-768560400 39600 0 SAKMMTT}
+ {354891600 43200 1 SAKST}
+ {370699200 39600 0 SAKT}
+ {386427600 43200 1 SAKST}
+ {402235200 39600 0 SAKT}
+ {417963600 43200 1 SAKST}
+ {433771200 39600 0 SAKT}
+ {449586000 43200 1 SAKST}
+ {465318000 39600 0 SAKT}
+ {481042800 43200 1 SAKST}
+ {496767600 39600 0 SAKT}
+ {512492400 43200 1 SAKST}
+ {528217200 39600 0 SAKT}
+ {543942000 43200 1 SAKST}
+ {559666800 39600 0 SAKT}
+ {575391600 43200 1 SAKST}
+ {591116400 39600 0 SAKT}
+ {606841200 43200 1 SAKST}
+ {622566000 39600 0 SAKT}
+ {638290800 43200 1 SAKST}
+ {654620400 39600 0 SAKT}
+ {670345200 36000 0 SAKMMTT}
+ {670348800 39600 1 SAKST}
+ {686073600 36000 0 SAKT}
+ {695750400 39600 0 SAKMMTT}
+ {701784000 43200 1 SAKST}
+ {717505200 39600 0 SAKT}
+ {733244400 43200 1 SAKST}
+ {748969200 39600 0 SAKT}
+ {764694000 43200 1 SAKST}
+ {780418800 39600 0 SAKT}
+ {796143600 43200 1 SAKST}
+ {811868400 39600 0 SAKT}
+ {828198000 43200 1 SAKST}
+ {846342000 39600 0 SAKT}
+ {859647600 36000 0 SAKMMTT}
+ {859651200 39600 1 SAKST}
+ {877795200 36000 0 SAKT}
+ {891100800 39600 1 SAKST}
+ {909244800 36000 0 SAKT}
+ {922550400 39600 1 SAKST}
+ {941299200 36000 0 SAKT}
+ {954000000 39600 1 SAKST}
+ {972748800 36000 0 SAKT}
+ {985449600 39600 1 SAKST}
+ {1004198400 36000 0 SAKT}
+ {1017504000 39600 1 SAKST}
+ {1035648000 36000 0 SAKT}
+ {1048953600 39600 1 SAKST}
+ {1067097600 36000 0 SAKT}
+ {1080403200 39600 1 SAKST}
+ {1099152000 36000 0 SAKT}
+ {1111852800 39600 1 SAKST}
+ {1130601600 36000 0 SAKT}
+ {1143302400 39600 1 SAKST}
+ {1162051200 36000 0 SAKT}
+ {1174752000 39600 1 SAKST}
+ {1193500800 36000 0 SAKT}
+ {1206806400 39600 1 SAKST}
+ {1224950400 36000 0 SAKT}
+ {1238256000 39600 1 SAKST}
+ {1256400000 36000 0 SAKT}
+ {1269705600 39600 1 SAKST}
+ {1288454400 36000 0 SAKT}
+ {1301155200 39600 0 SAKT}
+}
diff --git a/library/tzdata/Asia/Samarkand b/library/tzdata/Asia/Samarkand
new file mode 100644
index 0000000..6a1be11
--- /dev/null
+++ b/library/tzdata/Asia/Samarkand
@@ -0,0 +1,32 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Samarkand) {
+ {-9223372036854775808 16032 0 LMT}
+ {-1441168032 14400 0 SAMT}
+ {-1247544000 18000 0 SAMT}
+ {354913200 21600 1 SAMST}
+ {370720800 21600 0 TAST}
+ {386445600 18000 0 SAMT}
+ {386449200 21600 1 SAMST}
+ {402256800 18000 0 SAMT}
+ {417985200 21600 1 SAMST}
+ {433792800 18000 0 SAMT}
+ {449607600 21600 1 SAMST}
+ {465339600 18000 0 SAMT}
+ {481064400 21600 1 SAMST}
+ {496789200 18000 0 SAMT}
+ {512514000 21600 1 SAMST}
+ {528238800 18000 0 SAMT}
+ {543963600 21600 1 SAMST}
+ {559688400 18000 0 SAMT}
+ {575413200 21600 1 SAMST}
+ {591138000 18000 0 SAMT}
+ {606862800 21600 1 SAMST}
+ {622587600 18000 0 SAMT}
+ {638312400 21600 1 SAMST}
+ {654642000 18000 0 SAMT}
+ {670366800 21600 1 SAMST}
+ {683665200 21600 0 UZST}
+ {686091600 18000 0 UZT}
+ {694206000 18000 0 UZT}
+}
diff --git a/library/tzdata/Asia/Seoul b/library/tzdata/Asia/Seoul
new file mode 100644
index 0000000..9c83e30
--- /dev/null
+++ b/library/tzdata/Asia/Seoul
@@ -0,0 +1,18 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Seoul) {
+ {-9223372036854775808 30472 0 LMT}
+ {-2524552072 30600 0 KST}
+ {-2053931400 32400 0 KST}
+ {-1325494800 30600 0 KST}
+ {-1199262600 32400 0 KST}
+ {-498128400 28800 0 KST}
+ {-303984000 32400 1 KDT}
+ {-293533200 28800 0 KST}
+ {-264931200 30600 0 KST}
+ {-39515400 32400 0 KST}
+ {547570800 36000 1 KDT}
+ {560872800 32400 0 KST}
+ {579020400 36000 1 KDT}
+ {592322400 32400 0 KST}
+}
diff --git a/library/tzdata/Asia/Shanghai b/library/tzdata/Asia/Shanghai
new file mode 100644
index 0000000..aa7dc58
--- /dev/null
+++ b/library/tzdata/Asia/Shanghai
@@ -0,0 +1,23 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Shanghai) {
+ {-9223372036854775808 29152 0 LMT}
+ {-1325491552 28800 0 CST}
+ {-933494400 32400 1 CDT}
+ {-923130000 28800 0 CST}
+ {-908784000 32400 1 CDT}
+ {-891594000 28800 0 CST}
+ {-662716800 28800 0 CST}
+ {515520000 32400 1 CDT}
+ {527007600 28800 0 CST}
+ {545155200 32400 1 CDT}
+ {558457200 28800 0 CST}
+ {576604800 32400 1 CDT}
+ {589906800 28800 0 CST}
+ {608659200 32400 1 CDT}
+ {621961200 28800 0 CST}
+ {640108800 32400 1 CDT}
+ {653410800 28800 0 CST}
+ {671558400 32400 1 CDT}
+ {684860400 28800 0 CST}
+}
diff --git a/library/tzdata/Asia/Singapore b/library/tzdata/Asia/Singapore
new file mode 100644
index 0000000..e2f226e
--- /dev/null
+++ b/library/tzdata/Asia/Singapore
@@ -0,0 +1,14 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Singapore) {
+ {-9223372036854775808 24925 0 LMT}
+ {-2177477725 24925 0 SMT}
+ {-2038200925 25200 0 MALT}
+ {-1167634800 26400 1 MALST}
+ {-1073028000 26400 0 MALT}
+ {-894180000 27000 0 MALT}
+ {-879665400 32400 0 JST}
+ {-767005200 27000 0 MALT}
+ {-138785400 27000 0 SGT}
+ {378664200 28800 0 SGT}
+}
diff --git a/library/tzdata/Asia/Taipei b/library/tzdata/Asia/Taipei
new file mode 100644
index 0000000..a3c7ecf
--- /dev/null
+++ b/library/tzdata/Asia/Taipei
@@ -0,0 +1,46 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Taipei) {
+ {-9223372036854775808 29160 0 LMT}
+ {-2335248360 28800 0 CST}
+ {-778579200 32400 1 CDT}
+ {-765363600 28800 0 CST}
+ {-747043200 32400 1 CDT}
+ {-733827600 28800 0 CST}
+ {-715507200 32400 1 CDT}
+ {-702291600 28800 0 CST}
+ {-683884800 32400 1 CDT}
+ {-670669200 28800 0 CST}
+ {-652348800 32400 1 CDT}
+ {-639133200 28800 0 CST}
+ {-620812800 32400 1 CDT}
+ {-607597200 28800 0 CST}
+ {-589276800 32400 1 CDT}
+ {-576061200 28800 0 CST}
+ {-562924800 32400 1 CDT}
+ {-541760400 28800 0 CST}
+ {-528710400 32400 1 CDT}
+ {-510224400 28800 0 CST}
+ {-497174400 32400 1 CDT}
+ {-478688400 28800 0 CST}
+ {-465638400 32400 1 CDT}
+ {-449830800 28800 0 CST}
+ {-434016000 32400 1 CDT}
+ {-418208400 28800 0 CST}
+ {-402480000 32400 1 CDT}
+ {-386672400 28800 0 CST}
+ {-370944000 32400 1 CDT}
+ {-355136400 28800 0 CST}
+ {-339408000 32400 1 CDT}
+ {-323600400 28800 0 CST}
+ {-302515200 32400 1 CDT}
+ {-291978000 28800 0 CST}
+ {-270979200 32400 1 CDT}
+ {-260442000 28800 0 CST}
+ {133977600 32400 1 CDT}
+ {149785200 28800 0 CST}
+ {165513600 32400 1 CDT}
+ {181321200 28800 0 CST}
+ {299520000 32400 1 CDT}
+ {307465200 28800 0 CST}
+}
diff --git a/library/tzdata/Asia/Tashkent b/library/tzdata/Asia/Tashkent
new file mode 100644
index 0000000..fcee755
--- /dev/null
+++ b/library/tzdata/Asia/Tashkent
@@ -0,0 +1,32 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Tashkent) {
+ {-9223372036854775808 16632 0 LMT}
+ {-1441168632 18000 0 TAST}
+ {-1247547600 21600 0 TAST}
+ {354909600 25200 1 TASST}
+ {370717200 21600 0 TAST}
+ {386445600 25200 1 TASST}
+ {402253200 21600 0 TAST}
+ {417981600 25200 1 TASST}
+ {433789200 21600 0 TAST}
+ {449604000 25200 1 TASST}
+ {465336000 21600 0 TAST}
+ {481060800 25200 1 TASST}
+ {496785600 21600 0 TAST}
+ {512510400 25200 1 TASST}
+ {528235200 21600 0 TAST}
+ {543960000 25200 1 TASST}
+ {559684800 21600 0 TAST}
+ {575409600 25200 1 TASST}
+ {591134400 21600 0 TAST}
+ {606859200 25200 1 TASST}
+ {622584000 21600 0 TAST}
+ {638308800 25200 1 TASST}
+ {654638400 21600 0 TAST}
+ {670363200 18000 0 TAST}
+ {670366800 21600 1 TASST}
+ {683665200 21600 0 UZST}
+ {686091600 18000 0 UZT}
+ {694206000 18000 0 UZT}
+}
diff --git a/library/tzdata/Asia/Tbilisi b/library/tzdata/Asia/Tbilisi
new file mode 100644
index 0000000..a716917
--- /dev/null
+++ b/library/tzdata/Asia/Tbilisi
@@ -0,0 +1,60 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Tbilisi) {
+ {-9223372036854775808 10756 0 LMT}
+ {-2840151556 10756 0 TBMT}
+ {-1441162756 10800 0 TBIT}
+ {-405140400 14400 0 TBIT}
+ {354916800 18000 1 TBIST}
+ {370724400 14400 0 TBIT}
+ {386452800 18000 1 TBIST}
+ {402260400 14400 0 TBIT}
+ {417988800 18000 1 TBIST}
+ {433796400 14400 0 TBIT}
+ {449611200 18000 1 TBIST}
+ {465343200 14400 0 TBIT}
+ {481068000 18000 1 TBIST}
+ {496792800 14400 0 TBIT}
+ {512517600 18000 1 TBIST}
+ {528242400 14400 0 TBIT}
+ {543967200 18000 1 TBIST}
+ {559692000 14400 0 TBIT}
+ {575416800 18000 1 TBIST}
+ {591141600 14400 0 TBIT}
+ {606866400 18000 1 TBIST}
+ {622591200 14400 0 TBIT}
+ {638316000 18000 1 TBIST}
+ {654645600 14400 0 TBIT}
+ {670370400 14400 1 TBIST}
+ {671140800 14400 0 GEST}
+ {686098800 10800 0 GET}
+ {694213200 10800 0 GET}
+ {701816400 14400 1 GEST}
+ {717537600 10800 0 GET}
+ {733266000 14400 1 GEST}
+ {748987200 10800 0 GET}
+ {764715600 14400 1 GEST}
+ {780440400 14400 0 GET}
+ {796161600 18000 1 GEST}
+ {811882800 14400 0 GET}
+ {828216000 18000 1 GEST}
+ {846360000 18000 1 GEST}
+ {859662000 18000 0 GEST}
+ {877806000 14400 0 GET}
+ {891115200 18000 1 GEST}
+ {909255600 14400 0 GET}
+ {922564800 18000 1 GEST}
+ {941310000 14400 0 GET}
+ {954014400 18000 1 GEST}
+ {972759600 14400 0 GET}
+ {985464000 18000 1 GEST}
+ {1004209200 14400 0 GET}
+ {1017518400 18000 1 GEST}
+ {1035658800 14400 0 GET}
+ {1048968000 18000 1 GEST}
+ {1067108400 14400 0 GET}
+ {1080417600 18000 1 GEST}
+ {1088280000 14400 0 GEST}
+ {1099177200 10800 0 GET}
+ {1111878000 14400 0 GET}
+}
diff --git a/library/tzdata/Asia/Tehran b/library/tzdata/Asia/Tehran
new file mode 100644
index 0000000..7dca0ae
--- /dev/null
+++ b/library/tzdata/Asia/Tehran
@@ -0,0 +1,105 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Tehran) {
+ {-9223372036854775808 12344 0 LMT}
+ {-1704165944 12344 0 TMT}
+ {-757394744 12600 0 IRST}
+ {247177800 14400 0 IRST}
+ {259272000 18000 1 IRDT}
+ {277758000 14400 0 IRST}
+ {283982400 12600 0 IRST}
+ {290809800 16200 1 IRDT}
+ {306531000 12600 0 IRST}
+ {322432200 16200 1 IRDT}
+ {338499000 12600 0 IRST}
+ {673216200 16200 1 IRDT}
+ {685481400 12600 0 IRST}
+ {701209800 16200 1 IRDT}
+ {717103800 12600 0 IRST}
+ {732745800 16200 1 IRDT}
+ {748639800 12600 0 IRST}
+ {764281800 16200 1 IRDT}
+ {780175800 12600 0 IRST}
+ {795817800 16200 1 IRDT}
+ {811711800 12600 0 IRST}
+ {827353800 16200 1 IRDT}
+ {843247800 12600 0 IRST}
+ {858976200 16200 1 IRDT}
+ {874870200 12600 0 IRST}
+ {890512200 16200 1 IRDT}
+ {906406200 12600 0 IRST}
+ {922048200 16200 1 IRDT}
+ {937942200 12600 0 IRST}
+ {953584200 16200 1 IRDT}
+ {969478200 12600 0 IRST}
+ {985206600 16200 1 IRDT}
+ {1001100600 12600 0 IRST}
+ {1016742600 16200 1 IRDT}
+ {1032636600 12600 0 IRST}
+ {1048278600 16200 1 IRDT}
+ {1064172600 12600 0 IRST}
+ {1079814600 16200 1 IRDT}
+ {1095708600 12600 0 IRST}
+ {1111437000 16200 1 IRDT}
+ {1127331000 12600 0 IRST}
+ {1206045000 16200 1 IRDT}
+ {1221939000 12600 0 IRST}
+ {1237667400 16200 1 IRDT}
+ {1253561400 12600 0 IRST}
+ {1269203400 16200 1 IRDT}
+ {1285097400 12600 0 IRST}
+ {1300739400 16200 1 IRDT}
+ {1316633400 12600 0 IRST}
+ {1332275400 16200 1 IRDT}
+ {1348169400 12600 0 IRST}
+ {1363897800 16200 1 IRDT}
+ {1379791800 12600 0 IRST}
+ {1395433800 16200 1 IRDT}
+ {1411327800 12600 0 IRST}
+ {1426969800 16200 1 IRDT}
+ {1442863800 12600 0 IRST}
+ {1458505800 16200 1 IRDT}
+ {1474399800 12600 0 IRST}
+ {1490128200 16200 1 IRDT}
+ {1506022200 12600 0 IRST}
+ {1521664200 16200 1 IRDT}
+ {1537558200 12600 0 IRST}
+ {1553200200 16200 1 IRDT}
+ {1569094200 12600 0 IRST}
+ {1584736200 16200 1 IRDT}
+ {1600630200 12600 0 IRST}
+ {1616358600 16200 1 IRDT}
+ {1632252600 12600 0 IRST}
+ {1647894600 16200 1 IRDT}
+ {1663788600 12600 0 IRST}
+ {1679430600 16200 1 IRDT}
+ {1695324600 12600 0 IRST}
+ {1710966600 16200 1 IRDT}
+ {1726860600 12600 0 IRST}
+ {1742589000 16200 1 IRDT}
+ {1758483000 12600 0 IRST}
+ {1774125000 16200 1 IRDT}
+ {1790019000 12600 0 IRST}
+ {1805661000 16200 1 IRDT}
+ {1821555000 12600 0 IRST}
+ {1837197000 16200 1 IRDT}
+ {1853091000 12600 0 IRST}
+ {1868733000 16200 1 IRDT}
+ {1884627000 12600 0 IRST}
+ {1900355400 16200 1 IRDT}
+ {1916249400 12600 0 IRST}
+ {1931891400 16200 1 IRDT}
+ {1947785400 12600 0 IRST}
+ {1963427400 16200 1 IRDT}
+ {1979321400 12600 0 IRST}
+ {1994963400 16200 1 IRDT}
+ {2010857400 12600 0 IRST}
+ {2026585800 16200 1 IRDT}
+ {2042479800 12600 0 IRST}
+ {2058121800 16200 1 IRDT}
+ {2074015800 12600 0 IRST}
+ {2089657800 16200 1 IRDT}
+ {2105551800 12600 0 IRST}
+ {2121193800 16200 1 IRDT}
+ {2137087800 12600 0 IRST}
+}
diff --git a/library/tzdata/Asia/Tel_Aviv b/library/tzdata/Asia/Tel_Aviv
new file mode 100644
index 0000000..3e7278d
--- /dev/null
+++ b/library/tzdata/Asia/Tel_Aviv
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Asia/Jerusalem)]} {
+ LoadTimeZoneFile Asia/Jerusalem
+}
+set TZData(:Asia/Tel_Aviv) $TZData(:Asia/Jerusalem)
diff --git a/library/tzdata/Asia/Thimbu b/library/tzdata/Asia/Thimbu
new file mode 100644
index 0000000..94b0846
--- /dev/null
+++ b/library/tzdata/Asia/Thimbu
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Asia/Thimphu)]} {
+ LoadTimeZoneFile Asia/Thimphu
+}
+set TZData(:Asia/Thimbu) $TZData(:Asia/Thimphu)
diff --git a/library/tzdata/Asia/Thimphu b/library/tzdata/Asia/Thimphu
new file mode 100644
index 0000000..8c981de
--- /dev/null
+++ b/library/tzdata/Asia/Thimphu
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Thimphu) {
+ {-9223372036854775808 21516 0 LMT}
+ {-706341516 19800 0 IST}
+ {560025000 21600 0 BTT}
+}
diff --git a/library/tzdata/Asia/Tokyo b/library/tzdata/Asia/Tokyo
new file mode 100644
index 0000000..8d1ce11
--- /dev/null
+++ b/library/tzdata/Asia/Tokyo
@@ -0,0 +1,16 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Tokyo) {
+ {-9223372036854775808 33539 0 LMT}
+ {-2587712400 32400 0 JST}
+ {-2335251600 32400 0 CJT}
+ {-1009875600 32400 0 JST}
+ {-683794800 36000 1 JDT}
+ {-672393600 32400 0 JST}
+ {-654764400 36000 1 JDT}
+ {-640944000 32400 0 JST}
+ {-620290800 36000 1 JDT}
+ {-609494400 32400 0 JST}
+ {-588841200 36000 1 JDT}
+ {-578044800 32400 0 JST}
+}
diff --git a/library/tzdata/Asia/Ujung_Pandang b/library/tzdata/Asia/Ujung_Pandang
new file mode 100644
index 0000000..abe142e
--- /dev/null
+++ b/library/tzdata/Asia/Ujung_Pandang
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Asia/Makassar)]} {
+ LoadTimeZoneFile Asia/Makassar
+}
+set TZData(:Asia/Ujung_Pandang) $TZData(:Asia/Makassar)
diff --git a/library/tzdata/Asia/Ulaanbaatar b/library/tzdata/Asia/Ulaanbaatar
new file mode 100644
index 0000000..fef76ec
--- /dev/null
+++ b/library/tzdata/Asia/Ulaanbaatar
@@ -0,0 +1,51 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Ulaanbaatar) {
+ {-9223372036854775808 25652 0 LMT}
+ {-2032931252 25200 0 ULAT}
+ {252435600 28800 0 ULAT}
+ {417974400 32400 1 ULAST}
+ {433782000 28800 0 ULAT}
+ {449596800 32400 1 ULAST}
+ {465318000 28800 0 ULAT}
+ {481046400 32400 1 ULAST}
+ {496767600 28800 0 ULAT}
+ {512496000 32400 1 ULAST}
+ {528217200 28800 0 ULAT}
+ {543945600 32400 1 ULAST}
+ {559666800 28800 0 ULAT}
+ {575395200 32400 1 ULAST}
+ {591116400 28800 0 ULAT}
+ {606844800 32400 1 ULAST}
+ {622566000 28800 0 ULAT}
+ {638294400 32400 1 ULAST}
+ {654620400 28800 0 ULAT}
+ {670348800 32400 1 ULAST}
+ {686070000 28800 0 ULAT}
+ {701798400 32400 1 ULAST}
+ {717519600 28800 0 ULAT}
+ {733248000 32400 1 ULAST}
+ {748969200 28800 0 ULAT}
+ {764697600 32400 1 ULAST}
+ {780418800 28800 0 ULAT}
+ {796147200 32400 1 ULAST}
+ {811868400 28800 0 ULAT}
+ {828201600 32400 1 ULAST}
+ {843922800 28800 0 ULAT}
+ {859651200 32400 1 ULAST}
+ {875372400 28800 0 ULAT}
+ {891100800 32400 1 ULAST}
+ {906822000 28800 0 ULAT}
+ {988394400 32400 1 ULAST}
+ {1001696400 28800 0 ULAT}
+ {1017424800 32400 1 ULAST}
+ {1033146000 28800 0 ULAT}
+ {1048874400 32400 1 ULAST}
+ {1064595600 28800 0 ULAT}
+ {1080324000 32400 1 ULAST}
+ {1096045200 28800 0 ULAT}
+ {1111773600 32400 1 ULAST}
+ {1127494800 28800 0 ULAT}
+ {1143223200 32400 1 ULAST}
+ {1159549200 28800 0 ULAT}
+}
diff --git a/library/tzdata/Asia/Ulan_Bator b/library/tzdata/Asia/Ulan_Bator
new file mode 100644
index 0000000..3215ee7
--- /dev/null
+++ b/library/tzdata/Asia/Ulan_Bator
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Asia/Ulaanbaatar)]} {
+ LoadTimeZoneFile Asia/Ulaanbaatar
+}
+set TZData(:Asia/Ulan_Bator) $TZData(:Asia/Ulaanbaatar)
diff --git a/library/tzdata/Asia/Urumqi b/library/tzdata/Asia/Urumqi
new file mode 100644
index 0000000..93fc909
--- /dev/null
+++ b/library/tzdata/Asia/Urumqi
@@ -0,0 +1,19 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Urumqi) {
+ {-9223372036854775808 21020 0 LMT}
+ {-1325483420 21600 0 URUT}
+ {325965600 28800 0 CST}
+ {515520000 32400 1 CDT}
+ {527007600 28800 0 CST}
+ {545155200 32400 1 CDT}
+ {558457200 28800 0 CST}
+ {576604800 32400 1 CDT}
+ {589906800 28800 0 CST}
+ {608659200 32400 1 CDT}
+ {621961200 28800 0 CST}
+ {640108800 32400 1 CDT}
+ {653410800 28800 0 CST}
+ {671558400 32400 1 CDT}
+ {684860400 28800 0 CST}
+}
diff --git a/library/tzdata/Asia/Vientiane b/library/tzdata/Asia/Vientiane
new file mode 100644
index 0000000..18ade4d
--- /dev/null
+++ b/library/tzdata/Asia/Vientiane
@@ -0,0 +1,9 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Vientiane) {
+ {-9223372036854775808 24624 0 LMT}
+ {-2005973424 25580 0 SMT}
+ {-1855983920 25200 0 ICT}
+ {-1819954800 28800 0 ICT}
+ {-1220428800 25200 0 ICT}
+}
diff --git a/library/tzdata/Asia/Vladivostok b/library/tzdata/Asia/Vladivostok
new file mode 100644
index 0000000..54101a5
--- /dev/null
+++ b/library/tzdata/Asia/Vladivostok
@@ -0,0 +1,70 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Vladivostok) {
+ {-9223372036854775808 31664 0 LMT}
+ {-1487321264 32400 0 VLAT}
+ {-1247562000 36000 0 VLAMMTT}
+ {354895200 39600 1 VLAST}
+ {370702800 36000 0 VLAT}
+ {386431200 39600 1 VLAST}
+ {402238800 36000 0 VLAT}
+ {417967200 39600 1 VLAST}
+ {433774800 36000 0 VLAT}
+ {449589600 39600 1 VLAST}
+ {465321600 36000 0 VLAT}
+ {481046400 39600 1 VLAST}
+ {496771200 36000 0 VLAT}
+ {512496000 39600 1 VLAST}
+ {528220800 36000 0 VLAT}
+ {543945600 39600 1 VLAST}
+ {559670400 36000 0 VLAT}
+ {575395200 39600 1 VLAST}
+ {591120000 36000 0 VLAT}
+ {606844800 39600 1 VLAST}
+ {622569600 36000 0 VLAT}
+ {638294400 39600 1 VLAST}
+ {654624000 36000 0 VLAT}
+ {670348800 32400 0 VLAMMTST}
+ {670352400 36000 1 VLASST}
+ {686077200 32400 0 VLAST}
+ {695754000 36000 0 VLAMMTT}
+ {701787600 39600 1 VLAST}
+ {717508800 36000 0 VLAT}
+ {733248000 39600 1 VLAST}
+ {748972800 36000 0 VLAT}
+ {764697600 39600 1 VLAST}
+ {780422400 36000 0 VLAT}
+ {796147200 39600 1 VLAST}
+ {811872000 36000 0 VLAT}
+ {828201600 39600 1 VLAST}
+ {846345600 36000 0 VLAT}
+ {859651200 39600 1 VLAST}
+ {877795200 36000 0 VLAT}
+ {891100800 39600 1 VLAST}
+ {909244800 36000 0 VLAT}
+ {922550400 39600 1 VLAST}
+ {941299200 36000 0 VLAT}
+ {954000000 39600 1 VLAST}
+ {972748800 36000 0 VLAT}
+ {985449600 39600 1 VLAST}
+ {1004198400 36000 0 VLAT}
+ {1017504000 39600 1 VLAST}
+ {1035648000 36000 0 VLAT}
+ {1048953600 39600 1 VLAST}
+ {1067097600 36000 0 VLAT}
+ {1080403200 39600 1 VLAST}
+ {1099152000 36000 0 VLAT}
+ {1111852800 39600 1 VLAST}
+ {1130601600 36000 0 VLAT}
+ {1143302400 39600 1 VLAST}
+ {1162051200 36000 0 VLAT}
+ {1174752000 39600 1 VLAST}
+ {1193500800 36000 0 VLAT}
+ {1206806400 39600 1 VLAST}
+ {1224950400 36000 0 VLAT}
+ {1238256000 39600 1 VLAST}
+ {1256400000 36000 0 VLAT}
+ {1269705600 39600 1 VLAST}
+ {1288454400 36000 0 VLAT}
+ {1301155200 39600 0 VLAT}
+}
diff --git a/library/tzdata/Asia/Yakutsk b/library/tzdata/Asia/Yakutsk
new file mode 100644
index 0000000..5c32cc9
--- /dev/null
+++ b/library/tzdata/Asia/Yakutsk
@@ -0,0 +1,70 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Yakutsk) {
+ {-9223372036854775808 31120 0 LMT}
+ {-1579423120 28800 0 YAKT}
+ {-1247558400 32400 0 YAKMMTT}
+ {354898800 36000 1 YAKST}
+ {370706400 32400 0 YAKT}
+ {386434800 36000 1 YAKST}
+ {402242400 32400 0 YAKT}
+ {417970800 36000 1 YAKST}
+ {433778400 32400 0 YAKT}
+ {449593200 36000 1 YAKST}
+ {465325200 32400 0 YAKT}
+ {481050000 36000 1 YAKST}
+ {496774800 32400 0 YAKT}
+ {512499600 36000 1 YAKST}
+ {528224400 32400 0 YAKT}
+ {543949200 36000 1 YAKST}
+ {559674000 32400 0 YAKT}
+ {575398800 36000 1 YAKST}
+ {591123600 32400 0 YAKT}
+ {606848400 36000 1 YAKST}
+ {622573200 32400 0 YAKT}
+ {638298000 36000 1 YAKST}
+ {654627600 32400 0 YAKT}
+ {670352400 28800 0 YAKMMTT}
+ {670356000 32400 1 YAKST}
+ {686080800 28800 0 YAKT}
+ {695757600 32400 0 YAKMMTT}
+ {701791200 36000 1 YAKST}
+ {717512400 32400 0 YAKT}
+ {733251600 36000 1 YAKST}
+ {748976400 32400 0 YAKT}
+ {764701200 36000 1 YAKST}
+ {780426000 32400 0 YAKT}
+ {796150800 36000 1 YAKST}
+ {811875600 32400 0 YAKT}
+ {828205200 36000 1 YAKST}
+ {846349200 32400 0 YAKT}
+ {859654800 36000 1 YAKST}
+ {877798800 32400 0 YAKT}
+ {891104400 36000 1 YAKST}
+ {909248400 32400 0 YAKT}
+ {922554000 36000 1 YAKST}
+ {941302800 32400 0 YAKT}
+ {954003600 36000 1 YAKST}
+ {972752400 32400 0 YAKT}
+ {985453200 36000 1 YAKST}
+ {1004202000 32400 0 YAKT}
+ {1017507600 36000 1 YAKST}
+ {1035651600 32400 0 YAKT}
+ {1048957200 36000 1 YAKST}
+ {1067101200 32400 0 YAKT}
+ {1080406800 36000 1 YAKST}
+ {1099155600 32400 0 YAKT}
+ {1111856400 36000 1 YAKST}
+ {1130605200 32400 0 YAKT}
+ {1143306000 36000 1 YAKST}
+ {1162054800 32400 0 YAKT}
+ {1174755600 36000 1 YAKST}
+ {1193504400 32400 0 YAKT}
+ {1206810000 36000 1 YAKST}
+ {1224954000 32400 0 YAKT}
+ {1238259600 36000 1 YAKST}
+ {1256403600 32400 0 YAKT}
+ {1269709200 36000 1 YAKST}
+ {1288458000 32400 0 YAKT}
+ {1301158800 36000 0 YAKT}
+}
diff --git a/library/tzdata/Asia/Yekaterinburg b/library/tzdata/Asia/Yekaterinburg
new file mode 100644
index 0000000..2045496
--- /dev/null
+++ b/library/tzdata/Asia/Yekaterinburg
@@ -0,0 +1,70 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Yekaterinburg) {
+ {-9223372036854775808 14544 0 LMT}
+ {-1592611344 14400 0 SVET}
+ {-1247544000 18000 0 SVEMMTT}
+ {354913200 21600 1 SVEST}
+ {370720800 18000 0 SVET}
+ {386449200 21600 1 SVEST}
+ {402256800 18000 0 SVET}
+ {417985200 21600 1 SVEST}
+ {433792800 18000 0 SVET}
+ {449607600 21600 1 SVEST}
+ {465339600 18000 0 SVET}
+ {481064400 21600 1 SVEST}
+ {496789200 18000 0 SVET}
+ {512514000 21600 1 SVEST}
+ {528238800 18000 0 SVET}
+ {543963600 21600 1 SVEST}
+ {559688400 18000 0 SVET}
+ {575413200 21600 1 SVEST}
+ {591138000 18000 0 SVET}
+ {606862800 21600 1 SVEST}
+ {622587600 18000 0 SVET}
+ {638312400 21600 1 SVEST}
+ {654642000 18000 0 SVET}
+ {670366800 14400 0 SVEMMTT}
+ {670370400 18000 1 SVEST}
+ {686095200 14400 0 SVET}
+ {695772000 18000 0 YEKMMTT}
+ {701805600 21600 1 YEKST}
+ {717526800 18000 0 YEKT}
+ {733266000 21600 1 YEKST}
+ {748990800 18000 0 YEKT}
+ {764715600 21600 1 YEKST}
+ {780440400 18000 0 YEKT}
+ {796165200 21600 1 YEKST}
+ {811890000 18000 0 YEKT}
+ {828219600 21600 1 YEKST}
+ {846363600 18000 0 YEKT}
+ {859669200 21600 1 YEKST}
+ {877813200 18000 0 YEKT}
+ {891118800 21600 1 YEKST}
+ {909262800 18000 0 YEKT}
+ {922568400 21600 1 YEKST}
+ {941317200 18000 0 YEKT}
+ {954018000 21600 1 YEKST}
+ {972766800 18000 0 YEKT}
+ {985467600 21600 1 YEKST}
+ {1004216400 18000 0 YEKT}
+ {1017522000 21600 1 YEKST}
+ {1035666000 18000 0 YEKT}
+ {1048971600 21600 1 YEKST}
+ {1067115600 18000 0 YEKT}
+ {1080421200 21600 1 YEKST}
+ {1099170000 18000 0 YEKT}
+ {1111870800 21600 1 YEKST}
+ {1130619600 18000 0 YEKT}
+ {1143320400 21600 1 YEKST}
+ {1162069200 18000 0 YEKT}
+ {1174770000 21600 1 YEKST}
+ {1193518800 18000 0 YEKT}
+ {1206824400 21600 1 YEKST}
+ {1224968400 18000 0 YEKT}
+ {1238274000 21600 1 YEKST}
+ {1256418000 18000 0 YEKT}
+ {1269723600 21600 1 YEKST}
+ {1288472400 18000 0 YEKT}
+ {1301173200 21600 0 YEKT}
+}
diff --git a/library/tzdata/Asia/Yerevan b/library/tzdata/Asia/Yerevan
new file mode 100644
index 0000000..cd70b4f
--- /dev/null
+++ b/library/tzdata/Asia/Yerevan
@@ -0,0 +1,245 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Asia/Yerevan) {
+ {-9223372036854775808 10680 0 LMT}
+ {-1441162680 10800 0 YERT}
+ {-405140400 14400 0 YERT}
+ {354916800 18000 1 YERST}
+ {370724400 14400 0 YERT}
+ {386452800 18000 1 YERST}
+ {402260400 14400 0 YERT}
+ {417988800 18000 1 YERST}
+ {433796400 14400 0 YERT}
+ {449611200 18000 1 YERST}
+ {465343200 14400 0 YERT}
+ {481068000 18000 1 YERST}
+ {496792800 14400 0 YERT}
+ {512517600 18000 1 YERST}
+ {528242400 14400 0 YERT}
+ {543967200 18000 1 YERST}
+ {559692000 14400 0 YERT}
+ {575416800 18000 1 YERST}
+ {591141600 14400 0 YERT}
+ {606866400 18000 1 YERST}
+ {622591200 14400 0 YERT}
+ {638316000 18000 1 YERST}
+ {654645600 14400 0 YERT}
+ {670370400 14400 1 YERST}
+ {685569600 14400 0 AMST}
+ {686098800 10800 0 AMT}
+ {701812800 14400 1 AMST}
+ {717534000 10800 0 AMT}
+ {733273200 14400 1 AMST}
+ {748998000 10800 0 AMT}
+ {764722800 14400 1 AMST}
+ {780447600 10800 0 AMT}
+ {796172400 14400 1 AMST}
+ {811897200 14400 0 AMT}
+ {852062400 14400 0 AMT}
+ {859672800 18000 1 AMST}
+ {877816800 14400 0 AMT}
+ {891122400 18000 1 AMST}
+ {909266400 14400 0 AMT}
+ {922572000 18000 1 AMST}
+ {941320800 14400 0 AMT}
+ {954021600 18000 1 AMST}
+ {972770400 14400 0 AMT}
+ {985471200 18000 1 AMST}
+ {1004220000 14400 0 AMT}
+ {1017525600 18000 1 AMST}
+ {1035669600 14400 0 AMT}
+ {1048975200 18000 1 AMST}
+ {1067119200 14400 0 AMT}
+ {1080424800 18000 1 AMST}
+ {1099173600 14400 0 AMT}
+ {1111874400 18000 1 AMST}
+ {1130623200 14400 0 AMT}
+ {1143324000 18000 1 AMST}
+ {1162072800 14400 0 AMT}
+ {1174773600 18000 1 AMST}
+ {1193522400 14400 0 AMT}
+ {1206828000 18000 1 AMST}
+ {1224972000 14400 0 AMT}
+ {1238277600 18000 1 AMST}
+ {1256421600 14400 0 AMT}
+ {1269727200 18000 1 AMST}
+ {1288476000 14400 0 AMT}
+ {1301176800 18000 1 AMST}
+ {1319925600 14400 0 AMT}
+ {1332626400 18000 1 AMST}
+ {1351375200 14400 0 AMT}
+ {1364680800 18000 1 AMST}
+ {1382824800 14400 0 AMT}
+ {1396130400 18000 1 AMST}
+ {1414274400 14400 0 AMT}
+ {1427580000 18000 1 AMST}
+ {1445724000 14400 0 AMT}
+ {1459029600 18000 1 AMST}
+ {1477778400 14400 0 AMT}
+ {1490479200 18000 1 AMST}
+ {1509228000 14400 0 AMT}
+ {1521928800 18000 1 AMST}
+ {1540677600 14400 0 AMT}
+ {1553983200 18000 1 AMST}
+ {1572127200 14400 0 AMT}
+ {1585432800 18000 1 AMST}
+ {1603576800 14400 0 AMT}
+ {1616882400 18000 1 AMST}
+ {1635631200 14400 0 AMT}
+ {1648332000 18000 1 AMST}
+ {1667080800 14400 0 AMT}
+ {1679781600 18000 1 AMST}
+ {1698530400 14400 0 AMT}
+ {1711836000 18000 1 AMST}
+ {1729980000 14400 0 AMT}
+ {1743285600 18000 1 AMST}
+ {1761429600 14400 0 AMT}
+ {1774735200 18000 1 AMST}
+ {1792879200 14400 0 AMT}
+ {1806184800 18000 1 AMST}
+ {1824933600 14400 0 AMT}
+ {1837634400 18000 1 AMST}
+ {1856383200 14400 0 AMT}
+ {1869084000 18000 1 AMST}
+ {1887832800 14400 0 AMT}
+ {1901138400 18000 1 AMST}
+ {1919282400 14400 0 AMT}
+ {1932588000 18000 1 AMST}
+ {1950732000 14400 0 AMT}
+ {1964037600 18000 1 AMST}
+ {1982786400 14400 0 AMT}
+ {1995487200 18000 1 AMST}
+ {2014236000 14400 0 AMT}
+ {2026936800 18000 1 AMST}
+ {2045685600 14400 0 AMT}
+ {2058386400 18000 1 AMST}
+ {2077135200 14400 0 AMT}
+ {2090440800 18000 1 AMST}
+ {2108584800 14400 0 AMT}
+ {2121890400 18000 1 AMST}
+ {2140034400 14400 0 AMT}
+ {2153340000 18000 1 AMST}
+ {2172088800 14400 0 AMT}
+ {2184789600 18000 1 AMST}
+ {2203538400 14400 0 AMT}
+ {2216239200 18000 1 AMST}
+ {2234988000 14400 0 AMT}
+ {2248293600 18000 1 AMST}
+ {2266437600 14400 0 AMT}
+ {2279743200 18000 1 AMST}
+ {2297887200 14400 0 AMT}
+ {2311192800 18000 1 AMST}
+ {2329336800 14400 0 AMT}
+ {2342642400 18000 1 AMST}
+ {2361391200 14400 0 AMT}
+ {2374092000 18000 1 AMST}
+ {2392840800 14400 0 AMT}
+ {2405541600 18000 1 AMST}
+ {2424290400 14400 0 AMT}
+ {2437596000 18000 1 AMST}
+ {2455740000 14400 0 AMT}
+ {2469045600 18000 1 AMST}
+ {2487189600 14400 0 AMT}
+ {2500495200 18000 1 AMST}
+ {2519244000 14400 0 AMT}
+ {2531944800 18000 1 AMST}
+ {2550693600 14400 0 AMT}
+ {2563394400 18000 1 AMST}
+ {2582143200 14400 0 AMT}
+ {2595448800 18000 1 AMST}
+ {2613592800 14400 0 AMT}
+ {2626898400 18000 1 AMST}
+ {2645042400 14400 0 AMT}
+ {2658348000 18000 1 AMST}
+ {2676492000 14400 0 AMT}
+ {2689797600 18000 1 AMST}
+ {2708546400 14400 0 AMT}
+ {2721247200 18000 1 AMST}
+ {2739996000 14400 0 AMT}
+ {2752696800 18000 1 AMST}
+ {2771445600 14400 0 AMT}
+ {2784751200 18000 1 AMST}
+ {2802895200 14400 0 AMT}
+ {2816200800 18000 1 AMST}
+ {2834344800 14400 0 AMT}
+ {2847650400 18000 1 AMST}
+ {2866399200 14400 0 AMT}
+ {2879100000 18000 1 AMST}
+ {2897848800 14400 0 AMT}
+ {2910549600 18000 1 AMST}
+ {2929298400 14400 0 AMT}
+ {2941999200 18000 1 AMST}
+ {2960748000 14400 0 AMT}
+ {2974053600 18000 1 AMST}
+ {2992197600 14400 0 AMT}
+ {3005503200 18000 1 AMST}
+ {3023647200 14400 0 AMT}
+ {3036952800 18000 1 AMST}
+ {3055701600 14400 0 AMT}
+ {3068402400 18000 1 AMST}
+ {3087151200 14400 0 AMT}
+ {3099852000 18000 1 AMST}
+ {3118600800 14400 0 AMT}
+ {3131906400 18000 1 AMST}
+ {3150050400 14400 0 AMT}
+ {3163356000 18000 1 AMST}
+ {3181500000 14400 0 AMT}
+ {3194805600 18000 1 AMST}
+ {3212949600 14400 0 AMT}
+ {3226255200 18000 1 AMST}
+ {3245004000 14400 0 AMT}
+ {3257704800 18000 1 AMST}
+ {3276453600 14400 0 AMT}
+ {3289154400 18000 1 AMST}
+ {3307903200 14400 0 AMT}
+ {3321208800 18000 1 AMST}
+ {3339352800 14400 0 AMT}
+ {3352658400 18000 1 AMST}
+ {3370802400 14400 0 AMT}
+ {3384108000 18000 1 AMST}
+ {3402856800 14400 0 AMT}
+ {3415557600 18000 1 AMST}
+ {3434306400 14400 0 AMT}
+ {3447007200 18000 1 AMST}
+ {3465756000 14400 0 AMT}
+ {3479061600 18000 1 AMST}
+ {3497205600 14400 0 AMT}
+ {3510511200 18000 1 AMST}
+ {3528655200 14400 0 AMT}
+ {3541960800 18000 1 AMST}
+ {3560104800 14400 0 AMT}
+ {3573410400 18000 1 AMST}
+ {3592159200 14400 0 AMT}
+ {3604860000 18000 1 AMST}
+ {3623608800 14400 0 AMT}
+ {3636309600 18000 1 AMST}
+ {3655058400 14400 0 AMT}
+ {3668364000 18000 1 AMST}
+ {3686508000 14400 0 AMT}
+ {3699813600 18000 1 AMST}
+ {3717957600 14400 0 AMT}
+ {3731263200 18000 1 AMST}
+ {3750012000 14400 0 AMT}
+ {3762712800 18000 1 AMST}
+ {3781461600 14400 0 AMT}
+ {3794162400 18000 1 AMST}
+ {3812911200 14400 0 AMT}
+ {3825612000 18000 1 AMST}
+ {3844360800 14400 0 AMT}
+ {3857666400 18000 1 AMST}
+ {3875810400 14400 0 AMT}
+ {3889116000 18000 1 AMST}
+ {3907260000 14400 0 AMT}
+ {3920565600 18000 1 AMST}
+ {3939314400 14400 0 AMT}
+ {3952015200 18000 1 AMST}
+ {3970764000 14400 0 AMT}
+ {3983464800 18000 1 AMST}
+ {4002213600 14400 0 AMT}
+ {4015519200 18000 1 AMST}
+ {4033663200 14400 0 AMT}
+ {4046968800 18000 1 AMST}
+ {4065112800 14400 0 AMT}
+ {4078418400 18000 1 AMST}
+ {4096562400 14400 0 AMT}
+}
diff --git a/library/tzdata/Atlantic/Azores b/library/tzdata/Atlantic/Azores
new file mode 100644
index 0000000..c476191
--- /dev/null
+++ b/library/tzdata/Atlantic/Azores
@@ -0,0 +1,349 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Atlantic/Azores) {
+ {-9223372036854775808 -6160 0 LMT}
+ {-2713904240 -6872 0 HMT}
+ {-1849557928 -7200 0 AZOT}
+ {-1689548400 -3600 1 AZOST}
+ {-1677794400 -7200 0 AZOT}
+ {-1667430000 -3600 1 AZOST}
+ {-1647730800 -7200 0 AZOT}
+ {-1635807600 -3600 1 AZOST}
+ {-1616194800 -7200 0 AZOT}
+ {-1604358000 -3600 1 AZOST}
+ {-1584658800 -7200 0 AZOT}
+ {-1572735600 -3600 1 AZOST}
+ {-1553036400 -7200 0 AZOT}
+ {-1541199600 -3600 1 AZOST}
+ {-1521500400 -7200 0 AZOT}
+ {-1442444400 -3600 1 AZOST}
+ {-1426806000 -7200 0 AZOT}
+ {-1379286000 -3600 1 AZOST}
+ {-1364770800 -7200 0 AZOT}
+ {-1348441200 -3600 1 AZOST}
+ {-1333321200 -7200 0 AZOT}
+ {-1316386800 -3600 1 AZOST}
+ {-1301266800 -7200 0 AZOT}
+ {-1284332400 -3600 1 AZOST}
+ {-1269817200 -7200 0 AZOT}
+ {-1221433200 -3600 1 AZOST}
+ {-1206918000 -7200 0 AZOT}
+ {-1191193200 -3600 1 AZOST}
+ {-1175468400 -7200 0 AZOT}
+ {-1127689200 -3600 1 AZOST}
+ {-1111964400 -7200 0 AZOT}
+ {-1096844400 -3600 1 AZOST}
+ {-1080514800 -7200 0 AZOT}
+ {-1063580400 -3600 1 AZOST}
+ {-1049065200 -7200 0 AZOT}
+ {-1033340400 -3600 1 AZOST}
+ {-1017615600 -7200 0 AZOT}
+ {-1002495600 -3600 1 AZOST}
+ {-986166000 -7200 0 AZOT}
+ {-969231600 -3600 1 AZOST}
+ {-950482800 -7200 0 AZOT}
+ {-942015600 -3600 1 AZOST}
+ {-922662000 -7200 0 AZOT}
+ {-906937200 -3600 1 AZOST}
+ {-891126000 -7200 0 AZOT}
+ {-877302000 -3600 1 AZOST}
+ {-873676800 0 1 AZOMT}
+ {-864000000 -3600 1 AZOST}
+ {-857948400 -7200 0 AZOT}
+ {-845852400 -3600 1 AZOST}
+ {-842832000 0 1 AZOMT}
+ {-831340800 -3600 1 AZOST}
+ {-825894000 -7200 0 AZOT}
+ {-814402800 -3600 1 AZOST}
+ {-810777600 0 1 AZOMT}
+ {-799891200 -3600 1 AZOST}
+ {-794444400 -7200 0 AZOT}
+ {-782953200 -3600 1 AZOST}
+ {-779328000 0 1 AZOMT}
+ {-768441600 -3600 1 AZOST}
+ {-762994800 -7200 0 AZOT}
+ {-749084400 -3600 1 AZOST}
+ {-733359600 -7200 0 AZOT}
+ {-717624000 -3600 1 AZOST}
+ {-701899200 -7200 0 AZOT}
+ {-686174400 -3600 1 AZOST}
+ {-670449600 -7200 0 AZOT}
+ {-654724800 -3600 1 AZOST}
+ {-639000000 -7200 0 AZOT}
+ {-591825600 -3600 1 AZOST}
+ {-575496000 -7200 0 AZOT}
+ {-559771200 -3600 1 AZOST}
+ {-544046400 -7200 0 AZOT}
+ {-528321600 -3600 1 AZOST}
+ {-512596800 -7200 0 AZOT}
+ {-496872000 -3600 1 AZOST}
+ {-481147200 -7200 0 AZOT}
+ {-465422400 -3600 1 AZOST}
+ {-449697600 -7200 0 AZOT}
+ {-433972800 -3600 1 AZOST}
+ {-417643200 -7200 0 AZOT}
+ {-401918400 -3600 1 AZOST}
+ {-386193600 -7200 0 AZOT}
+ {-370468800 -3600 1 AZOST}
+ {-354744000 -7200 0 AZOT}
+ {-339019200 -3600 1 AZOST}
+ {-323294400 -7200 0 AZOT}
+ {-307569600 -3600 1 AZOST}
+ {-291844800 -7200 0 AZOT}
+ {-276120000 -3600 1 AZOST}
+ {-260395200 -7200 0 AZOT}
+ {-244670400 -3600 1 AZOST}
+ {-228340800 -7200 0 AZOT}
+ {-212616000 -3600 1 AZOST}
+ {-196891200 -7200 0 AZOT}
+ {-181166400 -3600 1 AZOST}
+ {-165441600 -7200 0 AZOT}
+ {-149716800 -3600 1 AZOST}
+ {-133992000 -7200 0 AZOT}
+ {-118267200 -3600 0 AZOT}
+ {228272400 0 1 AZOST}
+ {243997200 -3600 0 AZOT}
+ {260326800 0 1 AZOST}
+ {276051600 -3600 0 AZOT}
+ {291776400 0 1 AZOST}
+ {307504800 -3600 0 AZOT}
+ {323226000 0 1 AZOST}
+ {338954400 -3600 0 AZOT}
+ {354679200 0 1 AZOST}
+ {370404000 -3600 0 AZOT}
+ {386128800 0 1 AZOST}
+ {401853600 -3600 0 AZOT}
+ {417582000 0 1 AZOST}
+ {433303200 -3600 0 AZOT}
+ {449028000 0 1 AZOST}
+ {465357600 -3600 0 AZOT}
+ {481082400 0 1 AZOST}
+ {496807200 -3600 0 AZOT}
+ {512532000 0 1 AZOST}
+ {528256800 -3600 0 AZOT}
+ {543981600 0 1 AZOST}
+ {559706400 -3600 0 AZOT}
+ {575431200 0 1 AZOST}
+ {591156000 -3600 0 AZOT}
+ {606880800 0 1 AZOST}
+ {622605600 -3600 0 AZOT}
+ {638330400 0 1 AZOST}
+ {654660000 -3600 0 AZOT}
+ {670384800 0 1 AZOST}
+ {686109600 -3600 0 AZOT}
+ {701834400 0 1 AZOST}
+ {733280400 0 0 AZOST}
+ {749005200 -3600 0 AZOT}
+ {764730000 0 1 AZOST}
+ {780454800 -3600 0 AZOT}
+ {796179600 0 1 AZOST}
+ {811904400 -3600 0 AZOT}
+ {828234000 0 1 AZOST}
+ {846378000 -3600 0 AZOT}
+ {859683600 0 1 AZOST}
+ {877827600 -3600 0 AZOT}
+ {891133200 0 1 AZOST}
+ {909277200 -3600 0 AZOT}
+ {922582800 0 1 AZOST}
+ {941331600 -3600 0 AZOT}
+ {954032400 0 1 AZOST}
+ {972781200 -3600 0 AZOT}
+ {985482000 0 1 AZOST}
+ {1004230800 -3600 0 AZOT}
+ {1017536400 0 1 AZOST}
+ {1035680400 -3600 0 AZOT}
+ {1048986000 0 1 AZOST}
+ {1067130000 -3600 0 AZOT}
+ {1080435600 0 1 AZOST}
+ {1099184400 -3600 0 AZOT}
+ {1111885200 0 1 AZOST}
+ {1130634000 -3600 0 AZOT}
+ {1143334800 0 1 AZOST}
+ {1162083600 -3600 0 AZOT}
+ {1174784400 0 1 AZOST}
+ {1193533200 -3600 0 AZOT}
+ {1206838800 0 1 AZOST}
+ {1224982800 -3600 0 AZOT}
+ {1238288400 0 1 AZOST}
+ {1256432400 -3600 0 AZOT}
+ {1269738000 0 1 AZOST}
+ {1288486800 -3600 0 AZOT}
+ {1301187600 0 1 AZOST}
+ {1319936400 -3600 0 AZOT}
+ {1332637200 0 1 AZOST}
+ {1351386000 -3600 0 AZOT}
+ {1364691600 0 1 AZOST}
+ {1382835600 -3600 0 AZOT}
+ {1396141200 0 1 AZOST}
+ {1414285200 -3600 0 AZOT}
+ {1427590800 0 1 AZOST}
+ {1445734800 -3600 0 AZOT}
+ {1459040400 0 1 AZOST}
+ {1477789200 -3600 0 AZOT}
+ {1490490000 0 1 AZOST}
+ {1509238800 -3600 0 AZOT}
+ {1521939600 0 1 AZOST}
+ {1540688400 -3600 0 AZOT}
+ {1553994000 0 1 AZOST}
+ {1572138000 -3600 0 AZOT}
+ {1585443600 0 1 AZOST}
+ {1603587600 -3600 0 AZOT}
+ {1616893200 0 1 AZOST}
+ {1635642000 -3600 0 AZOT}
+ {1648342800 0 1 AZOST}
+ {1667091600 -3600 0 AZOT}
+ {1679792400 0 1 AZOST}
+ {1698541200 -3600 0 AZOT}
+ {1711846800 0 1 AZOST}
+ {1729990800 -3600 0 AZOT}
+ {1743296400 0 1 AZOST}
+ {1761440400 -3600 0 AZOT}
+ {1774746000 0 1 AZOST}
+ {1792890000 -3600 0 AZOT}
+ {1806195600 0 1 AZOST}
+ {1824944400 -3600 0 AZOT}
+ {1837645200 0 1 AZOST}
+ {1856394000 -3600 0 AZOT}
+ {1869094800 0 1 AZOST}
+ {1887843600 -3600 0 AZOT}
+ {1901149200 0 1 AZOST}
+ {1919293200 -3600 0 AZOT}
+ {1932598800 0 1 AZOST}
+ {1950742800 -3600 0 AZOT}
+ {1964048400 0 1 AZOST}
+ {1982797200 -3600 0 AZOT}
+ {1995498000 0 1 AZOST}
+ {2014246800 -3600 0 AZOT}
+ {2026947600 0 1 AZOST}
+ {2045696400 -3600 0 AZOT}
+ {2058397200 0 1 AZOST}
+ {2077146000 -3600 0 AZOT}
+ {2090451600 0 1 AZOST}
+ {2108595600 -3600 0 AZOT}
+ {2121901200 0 1 AZOST}
+ {2140045200 -3600 0 AZOT}
+ {2153350800 0 1 AZOST}
+ {2172099600 -3600 0 AZOT}
+ {2184800400 0 1 AZOST}
+ {2203549200 -3600 0 AZOT}
+ {2216250000 0 1 AZOST}
+ {2234998800 -3600 0 AZOT}
+ {2248304400 0 1 AZOST}
+ {2266448400 -3600 0 AZOT}
+ {2279754000 0 1 AZOST}
+ {2297898000 -3600 0 AZOT}
+ {2311203600 0 1 AZOST}
+ {2329347600 -3600 0 AZOT}
+ {2342653200 0 1 AZOST}
+ {2361402000 -3600 0 AZOT}
+ {2374102800 0 1 AZOST}
+ {2392851600 -3600 0 AZOT}
+ {2405552400 0 1 AZOST}
+ {2424301200 -3600 0 AZOT}
+ {2437606800 0 1 AZOST}
+ {2455750800 -3600 0 AZOT}
+ {2469056400 0 1 AZOST}
+ {2487200400 -3600 0 AZOT}
+ {2500506000 0 1 AZOST}
+ {2519254800 -3600 0 AZOT}
+ {2531955600 0 1 AZOST}
+ {2550704400 -3600 0 AZOT}
+ {2563405200 0 1 AZOST}
+ {2582154000 -3600 0 AZOT}
+ {2595459600 0 1 AZOST}
+ {2613603600 -3600 0 AZOT}
+ {2626909200 0 1 AZOST}
+ {2645053200 -3600 0 AZOT}
+ {2658358800 0 1 AZOST}
+ {2676502800 -3600 0 AZOT}
+ {2689808400 0 1 AZOST}
+ {2708557200 -3600 0 AZOT}
+ {2721258000 0 1 AZOST}
+ {2740006800 -3600 0 AZOT}
+ {2752707600 0 1 AZOST}
+ {2771456400 -3600 0 AZOT}
+ {2784762000 0 1 AZOST}
+ {2802906000 -3600 0 AZOT}
+ {2816211600 0 1 AZOST}
+ {2834355600 -3600 0 AZOT}
+ {2847661200 0 1 AZOST}
+ {2866410000 -3600 0 AZOT}
+ {2879110800 0 1 AZOST}
+ {2897859600 -3600 0 AZOT}
+ {2910560400 0 1 AZOST}
+ {2929309200 -3600 0 AZOT}
+ {2942010000 0 1 AZOST}
+ {2960758800 -3600 0 AZOT}
+ {2974064400 0 1 AZOST}
+ {2992208400 -3600 0 AZOT}
+ {3005514000 0 1 AZOST}
+ {3023658000 -3600 0 AZOT}
+ {3036963600 0 1 AZOST}
+ {3055712400 -3600 0 AZOT}
+ {3068413200 0 1 AZOST}
+ {3087162000 -3600 0 AZOT}
+ {3099862800 0 1 AZOST}
+ {3118611600 -3600 0 AZOT}
+ {3131917200 0 1 AZOST}
+ {3150061200 -3600 0 AZOT}
+ {3163366800 0 1 AZOST}
+ {3181510800 -3600 0 AZOT}
+ {3194816400 0 1 AZOST}
+ {3212960400 -3600 0 AZOT}
+ {3226266000 0 1 AZOST}
+ {3245014800 -3600 0 AZOT}
+ {3257715600 0 1 AZOST}
+ {3276464400 -3600 0 AZOT}
+ {3289165200 0 1 AZOST}
+ {3307914000 -3600 0 AZOT}
+ {3321219600 0 1 AZOST}
+ {3339363600 -3600 0 AZOT}
+ {3352669200 0 1 AZOST}
+ {3370813200 -3600 0 AZOT}
+ {3384118800 0 1 AZOST}
+ {3402867600 -3600 0 AZOT}
+ {3415568400 0 1 AZOST}
+ {3434317200 -3600 0 AZOT}
+ {3447018000 0 1 AZOST}
+ {3465766800 -3600 0 AZOT}
+ {3479072400 0 1 AZOST}
+ {3497216400 -3600 0 AZOT}
+ {3510522000 0 1 AZOST}
+ {3528666000 -3600 0 AZOT}
+ {3541971600 0 1 AZOST}
+ {3560115600 -3600 0 AZOT}
+ {3573421200 0 1 AZOST}
+ {3592170000 -3600 0 AZOT}
+ {3604870800 0 1 AZOST}
+ {3623619600 -3600 0 AZOT}
+ {3636320400 0 1 AZOST}
+ {3655069200 -3600 0 AZOT}
+ {3668374800 0 1 AZOST}
+ {3686518800 -3600 0 AZOT}
+ {3699824400 0 1 AZOST}
+ {3717968400 -3600 0 AZOT}
+ {3731274000 0 1 AZOST}
+ {3750022800 -3600 0 AZOT}
+ {3762723600 0 1 AZOST}
+ {3781472400 -3600 0 AZOT}
+ {3794173200 0 1 AZOST}
+ {3812922000 -3600 0 AZOT}
+ {3825622800 0 1 AZOST}
+ {3844371600 -3600 0 AZOT}
+ {3857677200 0 1 AZOST}
+ {3875821200 -3600 0 AZOT}
+ {3889126800 0 1 AZOST}
+ {3907270800 -3600 0 AZOT}
+ {3920576400 0 1 AZOST}
+ {3939325200 -3600 0 AZOT}
+ {3952026000 0 1 AZOST}
+ {3970774800 -3600 0 AZOT}
+ {3983475600 0 1 AZOST}
+ {4002224400 -3600 0 AZOT}
+ {4015530000 0 1 AZOST}
+ {4033674000 -3600 0 AZOT}
+ {4046979600 0 1 AZOST}
+ {4065123600 -3600 0 AZOT}
+ {4078429200 0 1 AZOST}
+ {4096573200 -3600 0 AZOT}
+}
diff --git a/library/tzdata/Atlantic/Bermuda b/library/tzdata/Atlantic/Bermuda
new file mode 100644
index 0000000..e8b165a
--- /dev/null
+++ b/library/tzdata/Atlantic/Bermuda
@@ -0,0 +1,259 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Atlantic/Bermuda) {
+ {-9223372036854775808 -15544 0 LMT}
+ {-1262281256 -14400 0 AST}
+ {136360800 -10800 0 ADT}
+ {152082000 -14400 0 AST}
+ {167810400 -10800 1 ADT}
+ {183531600 -14400 0 AST}
+ {189316800 -14400 0 AST}
+ {199260000 -10800 1 ADT}
+ {215586000 -14400 0 AST}
+ {230709600 -10800 1 ADT}
+ {247035600 -14400 0 AST}
+ {262764000 -10800 1 ADT}
+ {278485200 -14400 0 AST}
+ {294213600 -10800 1 ADT}
+ {309934800 -14400 0 AST}
+ {325663200 -10800 1 ADT}
+ {341384400 -14400 0 AST}
+ {357112800 -10800 1 ADT}
+ {372834000 -14400 0 AST}
+ {388562400 -10800 1 ADT}
+ {404888400 -14400 0 AST}
+ {420012000 -10800 1 ADT}
+ {436338000 -14400 0 AST}
+ {452066400 -10800 1 ADT}
+ {467787600 -14400 0 AST}
+ {483516000 -10800 1 ADT}
+ {499237200 -14400 0 AST}
+ {514965600 -10800 1 ADT}
+ {530686800 -14400 0 AST}
+ {544600800 -10800 1 ADT}
+ {562136400 -14400 0 AST}
+ {576050400 -10800 1 ADT}
+ {594190800 -14400 0 AST}
+ {607500000 -10800 1 ADT}
+ {625640400 -14400 0 AST}
+ {638949600 -10800 1 ADT}
+ {657090000 -14400 0 AST}
+ {671004000 -10800 1 ADT}
+ {688539600 -14400 0 AST}
+ {702453600 -10800 1 ADT}
+ {719989200 -14400 0 AST}
+ {733903200 -10800 1 ADT}
+ {752043600 -14400 0 AST}
+ {765352800 -10800 1 ADT}
+ {783493200 -14400 0 AST}
+ {796802400 -10800 1 ADT}
+ {814942800 -14400 0 AST}
+ {828856800 -10800 1 ADT}
+ {846392400 -14400 0 AST}
+ {860306400 -10800 1 ADT}
+ {877842000 -14400 0 AST}
+ {891756000 -10800 1 ADT}
+ {909291600 -14400 0 AST}
+ {923205600 -10800 1 ADT}
+ {941346000 -14400 0 AST}
+ {954655200 -10800 1 ADT}
+ {972795600 -14400 0 AST}
+ {986104800 -10800 1 ADT}
+ {1004245200 -14400 0 AST}
+ {1018159200 -10800 1 ADT}
+ {1035694800 -14400 0 AST}
+ {1049608800 -10800 1 ADT}
+ {1067144400 -14400 0 AST}
+ {1081058400 -10800 1 ADT}
+ {1099198800 -14400 0 AST}
+ {1112508000 -10800 1 ADT}
+ {1130648400 -14400 0 AST}
+ {1143957600 -10800 1 ADT}
+ {1162098000 -14400 0 AST}
+ {1173592800 -10800 1 ADT}
+ {1194152400 -14400 0 AST}
+ {1205042400 -10800 1 ADT}
+ {1225602000 -14400 0 AST}
+ {1236492000 -10800 1 ADT}
+ {1257051600 -14400 0 AST}
+ {1268546400 -10800 1 ADT}
+ {1289106000 -14400 0 AST}
+ {1299996000 -10800 1 ADT}
+ {1320555600 -14400 0 AST}
+ {1331445600 -10800 1 ADT}
+ {1352005200 -14400 0 AST}
+ {1362895200 -10800 1 ADT}
+ {1383454800 -14400 0 AST}
+ {1394344800 -10800 1 ADT}
+ {1414904400 -14400 0 AST}
+ {1425794400 -10800 1 ADT}
+ {1446354000 -14400 0 AST}
+ {1457848800 -10800 1 ADT}
+ {1478408400 -14400 0 AST}
+ {1489298400 -10800 1 ADT}
+ {1509858000 -14400 0 AST}
+ {1520748000 -10800 1 ADT}
+ {1541307600 -14400 0 AST}
+ {1552197600 -10800 1 ADT}
+ {1572757200 -14400 0 AST}
+ {1583647200 -10800 1 ADT}
+ {1604206800 -14400 0 AST}
+ {1615701600 -10800 1 ADT}
+ {1636261200 -14400 0 AST}
+ {1647151200 -10800 1 ADT}
+ {1667710800 -14400 0 AST}
+ {1678600800 -10800 1 ADT}
+ {1699160400 -14400 0 AST}
+ {1710050400 -10800 1 ADT}
+ {1730610000 -14400 0 AST}
+ {1741500000 -10800 1 ADT}
+ {1762059600 -14400 0 AST}
+ {1772949600 -10800 1 ADT}
+ {1793509200 -14400 0 AST}
+ {1805004000 -10800 1 ADT}
+ {1825563600 -14400 0 AST}
+ {1836453600 -10800 1 ADT}
+ {1857013200 -14400 0 AST}
+ {1867903200 -10800 1 ADT}
+ {1888462800 -14400 0 AST}
+ {1899352800 -10800 1 ADT}
+ {1919912400 -14400 0 AST}
+ {1930802400 -10800 1 ADT}
+ {1951362000 -14400 0 AST}
+ {1962856800 -10800 1 ADT}
+ {1983416400 -14400 0 AST}
+ {1994306400 -10800 1 ADT}
+ {2014866000 -14400 0 AST}
+ {2025756000 -10800 1 ADT}
+ {2046315600 -14400 0 AST}
+ {2057205600 -10800 1 ADT}
+ {2077765200 -14400 0 AST}
+ {2088655200 -10800 1 ADT}
+ {2109214800 -14400 0 AST}
+ {2120104800 -10800 1 ADT}
+ {2140664400 -14400 0 AST}
+ {2152159200 -10800 1 ADT}
+ {2172718800 -14400 0 AST}
+ {2183608800 -10800 1 ADT}
+ {2204168400 -14400 0 AST}
+ {2215058400 -10800 1 ADT}
+ {2235618000 -14400 0 AST}
+ {2246508000 -10800 1 ADT}
+ {2267067600 -14400 0 AST}
+ {2277957600 -10800 1 ADT}
+ {2298517200 -14400 0 AST}
+ {2309407200 -10800 1 ADT}
+ {2329966800 -14400 0 AST}
+ {2341461600 -10800 1 ADT}
+ {2362021200 -14400 0 AST}
+ {2372911200 -10800 1 ADT}
+ {2393470800 -14400 0 AST}
+ {2404360800 -10800 1 ADT}
+ {2424920400 -14400 0 AST}
+ {2435810400 -10800 1 ADT}
+ {2456370000 -14400 0 AST}
+ {2467260000 -10800 1 ADT}
+ {2487819600 -14400 0 AST}
+ {2499314400 -10800 1 ADT}
+ {2519874000 -14400 0 AST}
+ {2530764000 -10800 1 ADT}
+ {2551323600 -14400 0 AST}
+ {2562213600 -10800 1 ADT}
+ {2582773200 -14400 0 AST}
+ {2593663200 -10800 1 ADT}
+ {2614222800 -14400 0 AST}
+ {2625112800 -10800 1 ADT}
+ {2645672400 -14400 0 AST}
+ {2656562400 -10800 1 ADT}
+ {2677122000 -14400 0 AST}
+ {2688616800 -10800 1 ADT}
+ {2709176400 -14400 0 AST}
+ {2720066400 -10800 1 ADT}
+ {2740626000 -14400 0 AST}
+ {2751516000 -10800 1 ADT}
+ {2772075600 -14400 0 AST}
+ {2782965600 -10800 1 ADT}
+ {2803525200 -14400 0 AST}
+ {2814415200 -10800 1 ADT}
+ {2834974800 -14400 0 AST}
+ {2846469600 -10800 1 ADT}
+ {2867029200 -14400 0 AST}
+ {2877919200 -10800 1 ADT}
+ {2898478800 -14400 0 AST}
+ {2909368800 -10800 1 ADT}
+ {2929928400 -14400 0 AST}
+ {2940818400 -10800 1 ADT}
+ {2961378000 -14400 0 AST}
+ {2972268000 -10800 1 ADT}
+ {2992827600 -14400 0 AST}
+ {3003717600 -10800 1 ADT}
+ {3024277200 -14400 0 AST}
+ {3035772000 -10800 1 ADT}
+ {3056331600 -14400 0 AST}
+ {3067221600 -10800 1 ADT}
+ {3087781200 -14400 0 AST}
+ {3098671200 -10800 1 ADT}
+ {3119230800 -14400 0 AST}
+ {3130120800 -10800 1 ADT}
+ {3150680400 -14400 0 AST}
+ {3161570400 -10800 1 ADT}
+ {3182130000 -14400 0 AST}
+ {3193020000 -10800 1 ADT}
+ {3213579600 -14400 0 AST}
+ {3225074400 -10800 1 ADT}
+ {3245634000 -14400 0 AST}
+ {3256524000 -10800 1 ADT}
+ {3277083600 -14400 0 AST}
+ {3287973600 -10800 1 ADT}
+ {3308533200 -14400 0 AST}
+ {3319423200 -10800 1 ADT}
+ {3339982800 -14400 0 AST}
+ {3350872800 -10800 1 ADT}
+ {3371432400 -14400 0 AST}
+ {3382927200 -10800 1 ADT}
+ {3403486800 -14400 0 AST}
+ {3414376800 -10800 1 ADT}
+ {3434936400 -14400 0 AST}
+ {3445826400 -10800 1 ADT}
+ {3466386000 -14400 0 AST}
+ {3477276000 -10800 1 ADT}
+ {3497835600 -14400 0 AST}
+ {3508725600 -10800 1 ADT}
+ {3529285200 -14400 0 AST}
+ {3540175200 -10800 1 ADT}
+ {3560734800 -14400 0 AST}
+ {3572229600 -10800 1 ADT}
+ {3592789200 -14400 0 AST}
+ {3603679200 -10800 1 ADT}
+ {3624238800 -14400 0 AST}
+ {3635128800 -10800 1 ADT}
+ {3655688400 -14400 0 AST}
+ {3666578400 -10800 1 ADT}
+ {3687138000 -14400 0 AST}
+ {3698028000 -10800 1 ADT}
+ {3718587600 -14400 0 AST}
+ {3730082400 -10800 1 ADT}
+ {3750642000 -14400 0 AST}
+ {3761532000 -10800 1 ADT}
+ {3782091600 -14400 0 AST}
+ {3792981600 -10800 1 ADT}
+ {3813541200 -14400 0 AST}
+ {3824431200 -10800 1 ADT}
+ {3844990800 -14400 0 AST}
+ {3855880800 -10800 1 ADT}
+ {3876440400 -14400 0 AST}
+ {3887330400 -10800 1 ADT}
+ {3907890000 -14400 0 AST}
+ {3919384800 -10800 1 ADT}
+ {3939944400 -14400 0 AST}
+ {3950834400 -10800 1 ADT}
+ {3971394000 -14400 0 AST}
+ {3982284000 -10800 1 ADT}
+ {4002843600 -14400 0 AST}
+ {4013733600 -10800 1 ADT}
+ {4034293200 -14400 0 AST}
+ {4045183200 -10800 1 ADT}
+ {4065742800 -14400 0 AST}
+ {4076632800 -10800 1 ADT}
+ {4097192400 -14400 0 AST}
+}
diff --git a/library/tzdata/Atlantic/Canary b/library/tzdata/Atlantic/Canary
new file mode 100644
index 0000000..4b802c7
--- /dev/null
+++ b/library/tzdata/Atlantic/Canary
@@ -0,0 +1,248 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Atlantic/Canary) {
+ {-9223372036854775808 -3696 0 LMT}
+ {-1509663504 -3600 0 CANT}
+ {-733874400 0 0 WET}
+ {323827200 3600 1 WEST}
+ {338947200 3600 0 WEST}
+ {338950800 0 0 WET}
+ {354675600 3600 1 WEST}
+ {370400400 0 0 WET}
+ {386125200 3600 1 WEST}
+ {401850000 0 0 WET}
+ {417574800 3600 1 WEST}
+ {433299600 0 0 WET}
+ {449024400 3600 1 WEST}
+ {465354000 0 0 WET}
+ {481078800 3600 1 WEST}
+ {496803600 0 0 WET}
+ {512528400 3600 1 WEST}
+ {528253200 0 0 WET}
+ {543978000 3600 1 WEST}
+ {559702800 0 0 WET}
+ {575427600 3600 1 WEST}
+ {591152400 0 0 WET}
+ {606877200 3600 1 WEST}
+ {622602000 0 0 WET}
+ {638326800 3600 1 WEST}
+ {654656400 0 0 WET}
+ {670381200 3600 1 WEST}
+ {686106000 0 0 WET}
+ {701830800 3600 1 WEST}
+ {717555600 0 0 WET}
+ {733280400 3600 1 WEST}
+ {749005200 0 0 WET}
+ {764730000 3600 1 WEST}
+ {780454800 0 0 WET}
+ {796179600 3600 1 WEST}
+ {811904400 0 0 WET}
+ {828234000 3600 1 WEST}
+ {846378000 0 0 WET}
+ {859683600 3600 1 WEST}
+ {877827600 0 0 WET}
+ {891133200 3600 1 WEST}
+ {909277200 0 0 WET}
+ {922582800 3600 1 WEST}
+ {941331600 0 0 WET}
+ {954032400 3600 1 WEST}
+ {972781200 0 0 WET}
+ {985482000 3600 1 WEST}
+ {1004230800 0 0 WET}
+ {1017536400 3600 1 WEST}
+ {1035680400 0 0 WET}
+ {1048986000 3600 1 WEST}
+ {1067130000 0 0 WET}
+ {1080435600 3600 1 WEST}
+ {1099184400 0 0 WET}
+ {1111885200 3600 1 WEST}
+ {1130634000 0 0 WET}
+ {1143334800 3600 1 WEST}
+ {1162083600 0 0 WET}
+ {1174784400 3600 1 WEST}
+ {1193533200 0 0 WET}
+ {1206838800 3600 1 WEST}
+ {1224982800 0 0 WET}
+ {1238288400 3600 1 WEST}
+ {1256432400 0 0 WET}
+ {1269738000 3600 1 WEST}
+ {1288486800 0 0 WET}
+ {1301187600 3600 1 WEST}
+ {1319936400 0 0 WET}
+ {1332637200 3600 1 WEST}
+ {1351386000 0 0 WET}
+ {1364691600 3600 1 WEST}
+ {1382835600 0 0 WET}
+ {1396141200 3600 1 WEST}
+ {1414285200 0 0 WET}
+ {1427590800 3600 1 WEST}
+ {1445734800 0 0 WET}
+ {1459040400 3600 1 WEST}
+ {1477789200 0 0 WET}
+ {1490490000 3600 1 WEST}
+ {1509238800 0 0 WET}
+ {1521939600 3600 1 WEST}
+ {1540688400 0 0 WET}
+ {1553994000 3600 1 WEST}
+ {1572138000 0 0 WET}
+ {1585443600 3600 1 WEST}
+ {1603587600 0 0 WET}
+ {1616893200 3600 1 WEST}
+ {1635642000 0 0 WET}
+ {1648342800 3600 1 WEST}
+ {1667091600 0 0 WET}
+ {1679792400 3600 1 WEST}
+ {1698541200 0 0 WET}
+ {1711846800 3600 1 WEST}
+ {1729990800 0 0 WET}
+ {1743296400 3600 1 WEST}
+ {1761440400 0 0 WET}
+ {1774746000 3600 1 WEST}
+ {1792890000 0 0 WET}
+ {1806195600 3600 1 WEST}
+ {1824944400 0 0 WET}
+ {1837645200 3600 1 WEST}
+ {1856394000 0 0 WET}
+ {1869094800 3600 1 WEST}
+ {1887843600 0 0 WET}
+ {1901149200 3600 1 WEST}
+ {1919293200 0 0 WET}
+ {1932598800 3600 1 WEST}
+ {1950742800 0 0 WET}
+ {1964048400 3600 1 WEST}
+ {1982797200 0 0 WET}
+ {1995498000 3600 1 WEST}
+ {2014246800 0 0 WET}
+ {2026947600 3600 1 WEST}
+ {2045696400 0 0 WET}
+ {2058397200 3600 1 WEST}
+ {2077146000 0 0 WET}
+ {2090451600 3600 1 WEST}
+ {2108595600 0 0 WET}
+ {2121901200 3600 1 WEST}
+ {2140045200 0 0 WET}
+ {2153350800 3600 1 WEST}
+ {2172099600 0 0 WET}
+ {2184800400 3600 1 WEST}
+ {2203549200 0 0 WET}
+ {2216250000 3600 1 WEST}
+ {2234998800 0 0 WET}
+ {2248304400 3600 1 WEST}
+ {2266448400 0 0 WET}
+ {2279754000 3600 1 WEST}
+ {2297898000 0 0 WET}
+ {2311203600 3600 1 WEST}
+ {2329347600 0 0 WET}
+ {2342653200 3600 1 WEST}
+ {2361402000 0 0 WET}
+ {2374102800 3600 1 WEST}
+ {2392851600 0 0 WET}
+ {2405552400 3600 1 WEST}
+ {2424301200 0 0 WET}
+ {2437606800 3600 1 WEST}
+ {2455750800 0 0 WET}
+ {2469056400 3600 1 WEST}
+ {2487200400 0 0 WET}
+ {2500506000 3600 1 WEST}
+ {2519254800 0 0 WET}
+ {2531955600 3600 1 WEST}
+ {2550704400 0 0 WET}
+ {2563405200 3600 1 WEST}
+ {2582154000 0 0 WET}
+ {2595459600 3600 1 WEST}
+ {2613603600 0 0 WET}
+ {2626909200 3600 1 WEST}
+ {2645053200 0 0 WET}
+ {2658358800 3600 1 WEST}
+ {2676502800 0 0 WET}
+ {2689808400 3600 1 WEST}
+ {2708557200 0 0 WET}
+ {2721258000 3600 1 WEST}
+ {2740006800 0 0 WET}
+ {2752707600 3600 1 WEST}
+ {2771456400 0 0 WET}
+ {2784762000 3600 1 WEST}
+ {2802906000 0 0 WET}
+ {2816211600 3600 1 WEST}
+ {2834355600 0 0 WET}
+ {2847661200 3600 1 WEST}
+ {2866410000 0 0 WET}
+ {2879110800 3600 1 WEST}
+ {2897859600 0 0 WET}
+ {2910560400 3600 1 WEST}
+ {2929309200 0 0 WET}
+ {2942010000 3600 1 WEST}
+ {2960758800 0 0 WET}
+ {2974064400 3600 1 WEST}
+ {2992208400 0 0 WET}
+ {3005514000 3600 1 WEST}
+ {3023658000 0 0 WET}
+ {3036963600 3600 1 WEST}
+ {3055712400 0 0 WET}
+ {3068413200 3600 1 WEST}
+ {3087162000 0 0 WET}
+ {3099862800 3600 1 WEST}
+ {3118611600 0 0 WET}
+ {3131917200 3600 1 WEST}
+ {3150061200 0 0 WET}
+ {3163366800 3600 1 WEST}
+ {3181510800 0 0 WET}
+ {3194816400 3600 1 WEST}
+ {3212960400 0 0 WET}
+ {3226266000 3600 1 WEST}
+ {3245014800 0 0 WET}
+ {3257715600 3600 1 WEST}
+ {3276464400 0 0 WET}
+ {3289165200 3600 1 WEST}
+ {3307914000 0 0 WET}
+ {3321219600 3600 1 WEST}
+ {3339363600 0 0 WET}
+ {3352669200 3600 1 WEST}
+ {3370813200 0 0 WET}
+ {3384118800 3600 1 WEST}
+ {3402867600 0 0 WET}
+ {3415568400 3600 1 WEST}
+ {3434317200 0 0 WET}
+ {3447018000 3600 1 WEST}
+ {3465766800 0 0 WET}
+ {3479072400 3600 1 WEST}
+ {3497216400 0 0 WET}
+ {3510522000 3600 1 WEST}
+ {3528666000 0 0 WET}
+ {3541971600 3600 1 WEST}
+ {3560115600 0 0 WET}
+ {3573421200 3600 1 WEST}
+ {3592170000 0 0 WET}
+ {3604870800 3600 1 WEST}
+ {3623619600 0 0 WET}
+ {3636320400 3600 1 WEST}
+ {3655069200 0 0 WET}
+ {3668374800 3600 1 WEST}
+ {3686518800 0 0 WET}
+ {3699824400 3600 1 WEST}
+ {3717968400 0 0 WET}
+ {3731274000 3600 1 WEST}
+ {3750022800 0 0 WET}
+ {3762723600 3600 1 WEST}
+ {3781472400 0 0 WET}
+ {3794173200 3600 1 WEST}
+ {3812922000 0 0 WET}
+ {3825622800 3600 1 WEST}
+ {3844371600 0 0 WET}
+ {3857677200 3600 1 WEST}
+ {3875821200 0 0 WET}
+ {3889126800 3600 1 WEST}
+ {3907270800 0 0 WET}
+ {3920576400 3600 1 WEST}
+ {3939325200 0 0 WET}
+ {3952026000 3600 1 WEST}
+ {3970774800 0 0 WET}
+ {3983475600 3600 1 WEST}
+ {4002224400 0 0 WET}
+ {4015530000 3600 1 WEST}
+ {4033674000 0 0 WET}
+ {4046979600 3600 1 WEST}
+ {4065123600 0 0 WET}
+ {4078429200 3600 1 WEST}
+ {4096573200 0 0 WET}
+}
diff --git a/library/tzdata/Atlantic/Cape_Verde b/library/tzdata/Atlantic/Cape_Verde
new file mode 100644
index 0000000..f0bb79f
--- /dev/null
+++ b/library/tzdata/Atlantic/Cape_Verde
@@ -0,0 +1,9 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Atlantic/Cape_Verde) {
+ {-9223372036854775808 -5644 0 LMT}
+ {-1988144756 -7200 0 CVT}
+ {-862610400 -3600 1 CVST}
+ {-764118000 -7200 0 CVT}
+ {186120000 -3600 0 CVT}
+}
diff --git a/library/tzdata/Atlantic/Faeroe b/library/tzdata/Atlantic/Faeroe
new file mode 100644
index 0000000..4cafc34
--- /dev/null
+++ b/library/tzdata/Atlantic/Faeroe
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Atlantic/Faroe)]} {
+ LoadTimeZoneFile Atlantic/Faroe
+}
+set TZData(:Atlantic/Faeroe) $TZData(:Atlantic/Faroe)
diff --git a/library/tzdata/Atlantic/Faroe b/library/tzdata/Atlantic/Faroe
new file mode 100755
index 0000000..d2c314a
--- /dev/null
+++ b/library/tzdata/Atlantic/Faroe
@@ -0,0 +1,245 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Atlantic/Faroe) {
+ {-9223372036854775808 -1624 0 LMT}
+ {-1955748776 0 0 WET}
+ {347155200 0 0 WET}
+ {354675600 3600 1 WEST}
+ {370400400 0 0 WET}
+ {386125200 3600 1 WEST}
+ {401850000 0 0 WET}
+ {417574800 3600 1 WEST}
+ {433299600 0 0 WET}
+ {449024400 3600 1 WEST}
+ {465354000 0 0 WET}
+ {481078800 3600 1 WEST}
+ {496803600 0 0 WET}
+ {512528400 3600 1 WEST}
+ {528253200 0 0 WET}
+ {543978000 3600 1 WEST}
+ {559702800 0 0 WET}
+ {575427600 3600 1 WEST}
+ {591152400 0 0 WET}
+ {606877200 3600 1 WEST}
+ {622602000 0 0 WET}
+ {638326800 3600 1 WEST}
+ {654656400 0 0 WET}
+ {670381200 3600 1 WEST}
+ {686106000 0 0 WET}
+ {701830800 3600 1 WEST}
+ {717555600 0 0 WET}
+ {733280400 3600 1 WEST}
+ {749005200 0 0 WET}
+ {764730000 3600 1 WEST}
+ {780454800 0 0 WET}
+ {796179600 3600 1 WEST}
+ {811904400 0 0 WET}
+ {828234000 3600 1 WEST}
+ {846378000 0 0 WET}
+ {859683600 3600 1 WEST}
+ {877827600 0 0 WET}
+ {891133200 3600 1 WEST}
+ {909277200 0 0 WET}
+ {922582800 3600 1 WEST}
+ {941331600 0 0 WET}
+ {954032400 3600 1 WEST}
+ {972781200 0 0 WET}
+ {985482000 3600 1 WEST}
+ {1004230800 0 0 WET}
+ {1017536400 3600 1 WEST}
+ {1035680400 0 0 WET}
+ {1048986000 3600 1 WEST}
+ {1067130000 0 0 WET}
+ {1080435600 3600 1 WEST}
+ {1099184400 0 0 WET}
+ {1111885200 3600 1 WEST}
+ {1130634000 0 0 WET}
+ {1143334800 3600 1 WEST}
+ {1162083600 0 0 WET}
+ {1174784400 3600 1 WEST}
+ {1193533200 0 0 WET}
+ {1206838800 3600 1 WEST}
+ {1224982800 0 0 WET}
+ {1238288400 3600 1 WEST}
+ {1256432400 0 0 WET}
+ {1269738000 3600 1 WEST}
+ {1288486800 0 0 WET}
+ {1301187600 3600 1 WEST}
+ {1319936400 0 0 WET}
+ {1332637200 3600 1 WEST}
+ {1351386000 0 0 WET}
+ {1364691600 3600 1 WEST}
+ {1382835600 0 0 WET}
+ {1396141200 3600 1 WEST}
+ {1414285200 0 0 WET}
+ {1427590800 3600 1 WEST}
+ {1445734800 0 0 WET}
+ {1459040400 3600 1 WEST}
+ {1477789200 0 0 WET}
+ {1490490000 3600 1 WEST}
+ {1509238800 0 0 WET}
+ {1521939600 3600 1 WEST}
+ {1540688400 0 0 WET}
+ {1553994000 3600 1 WEST}
+ {1572138000 0 0 WET}
+ {1585443600 3600 1 WEST}
+ {1603587600 0 0 WET}
+ {1616893200 3600 1 WEST}
+ {1635642000 0 0 WET}
+ {1648342800 3600 1 WEST}
+ {1667091600 0 0 WET}
+ {1679792400 3600 1 WEST}
+ {1698541200 0 0 WET}
+ {1711846800 3600 1 WEST}
+ {1729990800 0 0 WET}
+ {1743296400 3600 1 WEST}
+ {1761440400 0 0 WET}
+ {1774746000 3600 1 WEST}
+ {1792890000 0 0 WET}
+ {1806195600 3600 1 WEST}
+ {1824944400 0 0 WET}
+ {1837645200 3600 1 WEST}
+ {1856394000 0 0 WET}
+ {1869094800 3600 1 WEST}
+ {1887843600 0 0 WET}
+ {1901149200 3600 1 WEST}
+ {1919293200 0 0 WET}
+ {1932598800 3600 1 WEST}
+ {1950742800 0 0 WET}
+ {1964048400 3600 1 WEST}
+ {1982797200 0 0 WET}
+ {1995498000 3600 1 WEST}
+ {2014246800 0 0 WET}
+ {2026947600 3600 1 WEST}
+ {2045696400 0 0 WET}
+ {2058397200 3600 1 WEST}
+ {2077146000 0 0 WET}
+ {2090451600 3600 1 WEST}
+ {2108595600 0 0 WET}
+ {2121901200 3600 1 WEST}
+ {2140045200 0 0 WET}
+ {2153350800 3600 1 WEST}
+ {2172099600 0 0 WET}
+ {2184800400 3600 1 WEST}
+ {2203549200 0 0 WET}
+ {2216250000 3600 1 WEST}
+ {2234998800 0 0 WET}
+ {2248304400 3600 1 WEST}
+ {2266448400 0 0 WET}
+ {2279754000 3600 1 WEST}
+ {2297898000 0 0 WET}
+ {2311203600 3600 1 WEST}
+ {2329347600 0 0 WET}
+ {2342653200 3600 1 WEST}
+ {2361402000 0 0 WET}
+ {2374102800 3600 1 WEST}
+ {2392851600 0 0 WET}
+ {2405552400 3600 1 WEST}
+ {2424301200 0 0 WET}
+ {2437606800 3600 1 WEST}
+ {2455750800 0 0 WET}
+ {2469056400 3600 1 WEST}
+ {2487200400 0 0 WET}
+ {2500506000 3600 1 WEST}
+ {2519254800 0 0 WET}
+ {2531955600 3600 1 WEST}
+ {2550704400 0 0 WET}
+ {2563405200 3600 1 WEST}
+ {2582154000 0 0 WET}
+ {2595459600 3600 1 WEST}
+ {2613603600 0 0 WET}
+ {2626909200 3600 1 WEST}
+ {2645053200 0 0 WET}
+ {2658358800 3600 1 WEST}
+ {2676502800 0 0 WET}
+ {2689808400 3600 1 WEST}
+ {2708557200 0 0 WET}
+ {2721258000 3600 1 WEST}
+ {2740006800 0 0 WET}
+ {2752707600 3600 1 WEST}
+ {2771456400 0 0 WET}
+ {2784762000 3600 1 WEST}
+ {2802906000 0 0 WET}
+ {2816211600 3600 1 WEST}
+ {2834355600 0 0 WET}
+ {2847661200 3600 1 WEST}
+ {2866410000 0 0 WET}
+ {2879110800 3600 1 WEST}
+ {2897859600 0 0 WET}
+ {2910560400 3600 1 WEST}
+ {2929309200 0 0 WET}
+ {2942010000 3600 1 WEST}
+ {2960758800 0 0 WET}
+ {2974064400 3600 1 WEST}
+ {2992208400 0 0 WET}
+ {3005514000 3600 1 WEST}
+ {3023658000 0 0 WET}
+ {3036963600 3600 1 WEST}
+ {3055712400 0 0 WET}
+ {3068413200 3600 1 WEST}
+ {3087162000 0 0 WET}
+ {3099862800 3600 1 WEST}
+ {3118611600 0 0 WET}
+ {3131917200 3600 1 WEST}
+ {3150061200 0 0 WET}
+ {3163366800 3600 1 WEST}
+ {3181510800 0 0 WET}
+ {3194816400 3600 1 WEST}
+ {3212960400 0 0 WET}
+ {3226266000 3600 1 WEST}
+ {3245014800 0 0 WET}
+ {3257715600 3600 1 WEST}
+ {3276464400 0 0 WET}
+ {3289165200 3600 1 WEST}
+ {3307914000 0 0 WET}
+ {3321219600 3600 1 WEST}
+ {3339363600 0 0 WET}
+ {3352669200 3600 1 WEST}
+ {3370813200 0 0 WET}
+ {3384118800 3600 1 WEST}
+ {3402867600 0 0 WET}
+ {3415568400 3600 1 WEST}
+ {3434317200 0 0 WET}
+ {3447018000 3600 1 WEST}
+ {3465766800 0 0 WET}
+ {3479072400 3600 1 WEST}
+ {3497216400 0 0 WET}
+ {3510522000 3600 1 WEST}
+ {3528666000 0 0 WET}
+ {3541971600 3600 1 WEST}
+ {3560115600 0 0 WET}
+ {3573421200 3600 1 WEST}
+ {3592170000 0 0 WET}
+ {3604870800 3600 1 WEST}
+ {3623619600 0 0 WET}
+ {3636320400 3600 1 WEST}
+ {3655069200 0 0 WET}
+ {3668374800 3600 1 WEST}
+ {3686518800 0 0 WET}
+ {3699824400 3600 1 WEST}
+ {3717968400 0 0 WET}
+ {3731274000 3600 1 WEST}
+ {3750022800 0 0 WET}
+ {3762723600 3600 1 WEST}
+ {3781472400 0 0 WET}
+ {3794173200 3600 1 WEST}
+ {3812922000 0 0 WET}
+ {3825622800 3600 1 WEST}
+ {3844371600 0 0 WET}
+ {3857677200 3600 1 WEST}
+ {3875821200 0 0 WET}
+ {3889126800 3600 1 WEST}
+ {3907270800 0 0 WET}
+ {3920576400 3600 1 WEST}
+ {3939325200 0 0 WET}
+ {3952026000 3600 1 WEST}
+ {3970774800 0 0 WET}
+ {3983475600 3600 1 WEST}
+ {4002224400 0 0 WET}
+ {4015530000 3600 1 WEST}
+ {4033674000 0 0 WET}
+ {4046979600 3600 1 WEST}
+ {4065123600 0 0 WET}
+ {4078429200 3600 1 WEST}
+ {4096573200 0 0 WET}
+}
diff --git a/library/tzdata/Atlantic/Jan_Mayen b/library/tzdata/Atlantic/Jan_Mayen
new file mode 100644
index 0000000..e592187
--- /dev/null
+++ b/library/tzdata/Atlantic/Jan_Mayen
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/Oslo)]} {
+ LoadTimeZoneFile Europe/Oslo
+}
+set TZData(:Atlantic/Jan_Mayen) $TZData(:Europe/Oslo)
diff --git a/library/tzdata/Atlantic/Madeira b/library/tzdata/Atlantic/Madeira
new file mode 100644
index 0000000..4960eeb
--- /dev/null
+++ b/library/tzdata/Atlantic/Madeira
@@ -0,0 +1,350 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Atlantic/Madeira) {
+ {-9223372036854775808 -4056 0 LMT}
+ {-2713906344 -4056 0 FMT}
+ {-1849560744 -3600 0 MADT}
+ {-1689552000 0 1 MADST}
+ {-1677798000 -3600 0 MADT}
+ {-1667433600 0 1 MADST}
+ {-1647734400 -3600 0 MADT}
+ {-1635811200 0 1 MADST}
+ {-1616198400 -3600 0 MADT}
+ {-1604361600 0 1 MADST}
+ {-1584662400 -3600 0 MADT}
+ {-1572739200 0 1 MADST}
+ {-1553040000 -3600 0 MADT}
+ {-1541203200 0 1 MADST}
+ {-1521504000 -3600 0 MADT}
+ {-1442448000 0 1 MADST}
+ {-1426809600 -3600 0 MADT}
+ {-1379289600 0 1 MADST}
+ {-1364774400 -3600 0 MADT}
+ {-1348444800 0 1 MADST}
+ {-1333324800 -3600 0 MADT}
+ {-1316390400 0 1 MADST}
+ {-1301270400 -3600 0 MADT}
+ {-1284336000 0 1 MADST}
+ {-1269820800 -3600 0 MADT}
+ {-1221436800 0 1 MADST}
+ {-1206921600 -3600 0 MADT}
+ {-1191196800 0 1 MADST}
+ {-1175472000 -3600 0 MADT}
+ {-1127692800 0 1 MADST}
+ {-1111968000 -3600 0 MADT}
+ {-1096848000 0 1 MADST}
+ {-1080518400 -3600 0 MADT}
+ {-1063584000 0 1 MADST}
+ {-1049068800 -3600 0 MADT}
+ {-1033344000 0 1 MADST}
+ {-1017619200 -3600 0 MADT}
+ {-1002499200 0 1 MADST}
+ {-986169600 -3600 0 MADT}
+ {-969235200 0 1 MADST}
+ {-950486400 -3600 0 MADT}
+ {-942019200 0 1 MADST}
+ {-922665600 -3600 0 MADT}
+ {-906940800 0 1 MADST}
+ {-891129600 -3600 0 MADT}
+ {-877305600 0 1 MADST}
+ {-873680400 3600 1 MADMT}
+ {-864003600 0 1 MADST}
+ {-857952000 -3600 0 MADT}
+ {-845856000 0 1 MADST}
+ {-842835600 3600 1 MADMT}
+ {-831344400 0 1 MADST}
+ {-825897600 -3600 0 MADT}
+ {-814406400 0 1 MADST}
+ {-810781200 3600 1 MADMT}
+ {-799894800 0 1 MADST}
+ {-794448000 -3600 0 MADT}
+ {-782956800 0 1 MADST}
+ {-779331600 3600 1 MADMT}
+ {-768445200 0 1 MADST}
+ {-762998400 -3600 0 MADT}
+ {-749088000 0 1 MADST}
+ {-733363200 -3600 0 MADT}
+ {-717627600 0 1 MADST}
+ {-701902800 -3600 0 MADT}
+ {-686178000 0 1 MADST}
+ {-670453200 -3600 0 MADT}
+ {-654728400 0 1 MADST}
+ {-639003600 -3600 0 MADT}
+ {-591829200 0 1 MADST}
+ {-575499600 -3600 0 MADT}
+ {-559774800 0 1 MADST}
+ {-544050000 -3600 0 MADT}
+ {-528325200 0 1 MADST}
+ {-512600400 -3600 0 MADT}
+ {-496875600 0 1 MADST}
+ {-481150800 -3600 0 MADT}
+ {-465426000 0 1 MADST}
+ {-449701200 -3600 0 MADT}
+ {-433976400 0 1 MADST}
+ {-417646800 -3600 0 MADT}
+ {-401922000 0 1 MADST}
+ {-386197200 -3600 0 MADT}
+ {-370472400 0 1 MADST}
+ {-354747600 -3600 0 MADT}
+ {-339022800 0 1 MADST}
+ {-323298000 -3600 0 MADT}
+ {-307573200 0 1 MADST}
+ {-291848400 -3600 0 MADT}
+ {-276123600 0 1 MADST}
+ {-260398800 -3600 0 MADT}
+ {-244674000 0 1 MADST}
+ {-228344400 -3600 0 MADT}
+ {-212619600 0 1 MADST}
+ {-196894800 -3600 0 MADT}
+ {-181170000 0 1 MADST}
+ {-165445200 -3600 0 MADT}
+ {-149720400 0 1 MADST}
+ {-133995600 -3600 0 MADT}
+ {-118270800 0 0 WET}
+ {228268800 3600 1 WEST}
+ {243993600 0 0 WET}
+ {260323200 3600 1 WEST}
+ {276048000 0 0 WET}
+ {291772800 3600 1 WEST}
+ {307501200 0 0 WET}
+ {323222400 3600 1 WEST}
+ {338950800 0 0 WET}
+ {354675600 3600 1 WEST}
+ {370400400 0 0 WET}
+ {386125200 3600 1 WEST}
+ {401850000 0 0 WET}
+ {417578400 3600 1 WEST}
+ {433299600 0 0 WET}
+ {449024400 3600 1 WEST}
+ {465354000 0 0 WET}
+ {481078800 3600 1 WEST}
+ {496803600 0 0 WET}
+ {512528400 3600 1 WEST}
+ {528253200 0 0 WET}
+ {543978000 3600 1 WEST}
+ {559702800 0 0 WET}
+ {575427600 3600 1 WEST}
+ {591152400 0 0 WET}
+ {606877200 3600 1 WEST}
+ {622602000 0 0 WET}
+ {638326800 3600 1 WEST}
+ {654656400 0 0 WET}
+ {670381200 3600 1 WEST}
+ {686106000 0 0 WET}
+ {701830800 3600 1 WEST}
+ {717555600 0 0 WET}
+ {733280400 3600 1 WEST}
+ {749005200 0 0 WET}
+ {764730000 3600 1 WEST}
+ {780454800 0 0 WET}
+ {796179600 3600 1 WEST}
+ {811904400 0 0 WET}
+ {828234000 3600 1 WEST}
+ {846378000 0 0 WET}
+ {859683600 3600 1 WEST}
+ {877827600 0 0 WET}
+ {891133200 3600 1 WEST}
+ {909277200 0 0 WET}
+ {922582800 3600 1 WEST}
+ {941331600 0 0 WET}
+ {954032400 3600 1 WEST}
+ {972781200 0 0 WET}
+ {985482000 3600 1 WEST}
+ {1004230800 0 0 WET}
+ {1017536400 3600 1 WEST}
+ {1035680400 0 0 WET}
+ {1048986000 3600 1 WEST}
+ {1067130000 0 0 WET}
+ {1080435600 3600 1 WEST}
+ {1099184400 0 0 WET}
+ {1111885200 3600 1 WEST}
+ {1130634000 0 0 WET}
+ {1143334800 3600 1 WEST}
+ {1162083600 0 0 WET}
+ {1174784400 3600 1 WEST}
+ {1193533200 0 0 WET}
+ {1206838800 3600 1 WEST}
+ {1224982800 0 0 WET}
+ {1238288400 3600 1 WEST}
+ {1256432400 0 0 WET}
+ {1269738000 3600 1 WEST}
+ {1288486800 0 0 WET}
+ {1301187600 3600 1 WEST}
+ {1319936400 0 0 WET}
+ {1332637200 3600 1 WEST}
+ {1351386000 0 0 WET}
+ {1364691600 3600 1 WEST}
+ {1382835600 0 0 WET}
+ {1396141200 3600 1 WEST}
+ {1414285200 0 0 WET}
+ {1427590800 3600 1 WEST}
+ {1445734800 0 0 WET}
+ {1459040400 3600 1 WEST}
+ {1477789200 0 0 WET}
+ {1490490000 3600 1 WEST}
+ {1509238800 0 0 WET}
+ {1521939600 3600 1 WEST}
+ {1540688400 0 0 WET}
+ {1553994000 3600 1 WEST}
+ {1572138000 0 0 WET}
+ {1585443600 3600 1 WEST}
+ {1603587600 0 0 WET}
+ {1616893200 3600 1 WEST}
+ {1635642000 0 0 WET}
+ {1648342800 3600 1 WEST}
+ {1667091600 0 0 WET}
+ {1679792400 3600 1 WEST}
+ {1698541200 0 0 WET}
+ {1711846800 3600 1 WEST}
+ {1729990800 0 0 WET}
+ {1743296400 3600 1 WEST}
+ {1761440400 0 0 WET}
+ {1774746000 3600 1 WEST}
+ {1792890000 0 0 WET}
+ {1806195600 3600 1 WEST}
+ {1824944400 0 0 WET}
+ {1837645200 3600 1 WEST}
+ {1856394000 0 0 WET}
+ {1869094800 3600 1 WEST}
+ {1887843600 0 0 WET}
+ {1901149200 3600 1 WEST}
+ {1919293200 0 0 WET}
+ {1932598800 3600 1 WEST}
+ {1950742800 0 0 WET}
+ {1964048400 3600 1 WEST}
+ {1982797200 0 0 WET}
+ {1995498000 3600 1 WEST}
+ {2014246800 0 0 WET}
+ {2026947600 3600 1 WEST}
+ {2045696400 0 0 WET}
+ {2058397200 3600 1 WEST}
+ {2077146000 0 0 WET}
+ {2090451600 3600 1 WEST}
+ {2108595600 0 0 WET}
+ {2121901200 3600 1 WEST}
+ {2140045200 0 0 WET}
+ {2153350800 3600 1 WEST}
+ {2172099600 0 0 WET}
+ {2184800400 3600 1 WEST}
+ {2203549200 0 0 WET}
+ {2216250000 3600 1 WEST}
+ {2234998800 0 0 WET}
+ {2248304400 3600 1 WEST}
+ {2266448400 0 0 WET}
+ {2279754000 3600 1 WEST}
+ {2297898000 0 0 WET}
+ {2311203600 3600 1 WEST}
+ {2329347600 0 0 WET}
+ {2342653200 3600 1 WEST}
+ {2361402000 0 0 WET}
+ {2374102800 3600 1 WEST}
+ {2392851600 0 0 WET}
+ {2405552400 3600 1 WEST}
+ {2424301200 0 0 WET}
+ {2437606800 3600 1 WEST}
+ {2455750800 0 0 WET}
+ {2469056400 3600 1 WEST}
+ {2487200400 0 0 WET}
+ {2500506000 3600 1 WEST}
+ {2519254800 0 0 WET}
+ {2531955600 3600 1 WEST}
+ {2550704400 0 0 WET}
+ {2563405200 3600 1 WEST}
+ {2582154000 0 0 WET}
+ {2595459600 3600 1 WEST}
+ {2613603600 0 0 WET}
+ {2626909200 3600 1 WEST}
+ {2645053200 0 0 WET}
+ {2658358800 3600 1 WEST}
+ {2676502800 0 0 WET}
+ {2689808400 3600 1 WEST}
+ {2708557200 0 0 WET}
+ {2721258000 3600 1 WEST}
+ {2740006800 0 0 WET}
+ {2752707600 3600 1 WEST}
+ {2771456400 0 0 WET}
+ {2784762000 3600 1 WEST}
+ {2802906000 0 0 WET}
+ {2816211600 3600 1 WEST}
+ {2834355600 0 0 WET}
+ {2847661200 3600 1 WEST}
+ {2866410000 0 0 WET}
+ {2879110800 3600 1 WEST}
+ {2897859600 0 0 WET}
+ {2910560400 3600 1 WEST}
+ {2929309200 0 0 WET}
+ {2942010000 3600 1 WEST}
+ {2960758800 0 0 WET}
+ {2974064400 3600 1 WEST}
+ {2992208400 0 0 WET}
+ {3005514000 3600 1 WEST}
+ {3023658000 0 0 WET}
+ {3036963600 3600 1 WEST}
+ {3055712400 0 0 WET}
+ {3068413200 3600 1 WEST}
+ {3087162000 0 0 WET}
+ {3099862800 3600 1 WEST}
+ {3118611600 0 0 WET}
+ {3131917200 3600 1 WEST}
+ {3150061200 0 0 WET}
+ {3163366800 3600 1 WEST}
+ {3181510800 0 0 WET}
+ {3194816400 3600 1 WEST}
+ {3212960400 0 0 WET}
+ {3226266000 3600 1 WEST}
+ {3245014800 0 0 WET}
+ {3257715600 3600 1 WEST}
+ {3276464400 0 0 WET}
+ {3289165200 3600 1 WEST}
+ {3307914000 0 0 WET}
+ {3321219600 3600 1 WEST}
+ {3339363600 0 0 WET}
+ {3352669200 3600 1 WEST}
+ {3370813200 0 0 WET}
+ {3384118800 3600 1 WEST}
+ {3402867600 0 0 WET}
+ {3415568400 3600 1 WEST}
+ {3434317200 0 0 WET}
+ {3447018000 3600 1 WEST}
+ {3465766800 0 0 WET}
+ {3479072400 3600 1 WEST}
+ {3497216400 0 0 WET}
+ {3510522000 3600 1 WEST}
+ {3528666000 0 0 WET}
+ {3541971600 3600 1 WEST}
+ {3560115600 0 0 WET}
+ {3573421200 3600 1 WEST}
+ {3592170000 0 0 WET}
+ {3604870800 3600 1 WEST}
+ {3623619600 0 0 WET}
+ {3636320400 3600 1 WEST}
+ {3655069200 0 0 WET}
+ {3668374800 3600 1 WEST}
+ {3686518800 0 0 WET}
+ {3699824400 3600 1 WEST}
+ {3717968400 0 0 WET}
+ {3731274000 3600 1 WEST}
+ {3750022800 0 0 WET}
+ {3762723600 3600 1 WEST}
+ {3781472400 0 0 WET}
+ {3794173200 3600 1 WEST}
+ {3812922000 0 0 WET}
+ {3825622800 3600 1 WEST}
+ {3844371600 0 0 WET}
+ {3857677200 3600 1 WEST}
+ {3875821200 0 0 WET}
+ {3889126800 3600 1 WEST}
+ {3907270800 0 0 WET}
+ {3920576400 3600 1 WEST}
+ {3939325200 0 0 WET}
+ {3952026000 3600 1 WEST}
+ {3970774800 0 0 WET}
+ {3983475600 3600 1 WEST}
+ {4002224400 0 0 WET}
+ {4015530000 3600 1 WEST}
+ {4033674000 0 0 WET}
+ {4046979600 3600 1 WEST}
+ {4065123600 0 0 WET}
+ {4078429200 3600 1 WEST}
+ {4096573200 0 0 WET}
+}
diff --git a/library/tzdata/Atlantic/Reykjavik b/library/tzdata/Atlantic/Reykjavik
new file mode 100644
index 0000000..f0248ad
--- /dev/null
+++ b/library/tzdata/Atlantic/Reykjavik
@@ -0,0 +1,70 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Atlantic/Reykjavik) {
+ {-9223372036854775808 -5244 0 LMT}
+ {-4197047556 -5268 0 RMT}
+ {-1956609132 -3600 0 IST}
+ {-1668211200 0 1 ISST}
+ {-1647212400 -3600 0 IST}
+ {-1636675200 0 1 ISST}
+ {-1613430000 -3600 0 IST}
+ {-968025600 0 1 ISST}
+ {-949615200 -3600 0 IST}
+ {-942008400 0 1 ISST}
+ {-920239200 -3600 0 IST}
+ {-909957600 0 1 ISST}
+ {-888789600 -3600 0 IST}
+ {-877903200 0 1 ISST}
+ {-857944800 -3600 0 IST}
+ {-846453600 0 1 ISST}
+ {-826495200 -3600 0 IST}
+ {-815004000 0 1 ISST}
+ {-795045600 -3600 0 IST}
+ {-783554400 0 1 ISST}
+ {-762991200 -3600 0 IST}
+ {-752104800 0 1 ISST}
+ {-731541600 -3600 0 IST}
+ {-717631200 0 1 ISST}
+ {-700092000 -3600 0 IST}
+ {-686181600 0 1 ISST}
+ {-668642400 -3600 0 IST}
+ {-654732000 0 1 ISST}
+ {-636588000 -3600 0 IST}
+ {-623282400 0 1 ISST}
+ {-605743200 -3600 0 IST}
+ {-591832800 0 1 ISST}
+ {-573688800 -3600 0 IST}
+ {-559778400 0 1 ISST}
+ {-542239200 -3600 0 IST}
+ {-528328800 0 1 ISST}
+ {-510789600 -3600 0 IST}
+ {-496879200 0 1 ISST}
+ {-479340000 -3600 0 IST}
+ {-465429600 0 1 ISST}
+ {-447890400 -3600 0 IST}
+ {-433980000 0 1 ISST}
+ {-415836000 -3600 0 IST}
+ {-401925600 0 1 ISST}
+ {-384386400 -3600 0 IST}
+ {-370476000 0 1 ISST}
+ {-352936800 -3600 0 IST}
+ {-339026400 0 1 ISST}
+ {-321487200 -3600 0 IST}
+ {-307576800 0 1 ISST}
+ {-290037600 -3600 0 IST}
+ {-276127200 0 1 ISST}
+ {-258588000 -3600 0 IST}
+ {-244677600 0 1 ISST}
+ {-226533600 -3600 0 IST}
+ {-212623200 0 1 ISST}
+ {-195084000 -3600 0 IST}
+ {-181173600 0 1 ISST}
+ {-163634400 -3600 0 IST}
+ {-149724000 0 1 ISST}
+ {-132184800 -3600 0 IST}
+ {-118274400 0 1 ISST}
+ {-100735200 -3600 0 IST}
+ {-86824800 0 1 ISST}
+ {-68680800 -3600 0 IST}
+ {-54770400 0 0 GMT}
+}
diff --git a/library/tzdata/Atlantic/South_Georgia b/library/tzdata/Atlantic/South_Georgia
new file mode 100644
index 0000000..cbfc826
--- /dev/null
+++ b/library/tzdata/Atlantic/South_Georgia
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Atlantic/South_Georgia) {
+ {-9223372036854775808 -8768 0 LMT}
+ {-2524512832 -7200 0 GST}
+}
diff --git a/library/tzdata/Atlantic/St_Helena b/library/tzdata/Atlantic/St_Helena
new file mode 100644
index 0000000..6d0c00d
--- /dev/null
+++ b/library/tzdata/Atlantic/St_Helena
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Atlantic/St_Helena) {
+ {-9223372036854775808 -1368 0 LMT}
+ {-2524520232 -1368 0 JMT}
+ {-599614632 0 0 GMT}
+}
diff --git a/library/tzdata/Atlantic/Stanley b/library/tzdata/Atlantic/Stanley
new file mode 100644
index 0000000..545b91c
--- /dev/null
+++ b/library/tzdata/Atlantic/Stanley
@@ -0,0 +1,252 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Atlantic/Stanley) {
+ {-9223372036854775808 -13884 0 LMT}
+ {-2524507716 -13884 0 SMT}
+ {-1824235716 -14400 0 FKT}
+ {-1018209600 -10800 1 FKST}
+ {-1003093200 -14400 0 FKT}
+ {-986760000 -10800 1 FKST}
+ {-971643600 -14400 0 FKT}
+ {-954705600 -10800 1 FKST}
+ {-939589200 -14400 0 FKT}
+ {-923256000 -10800 1 FKST}
+ {-908139600 -14400 0 FKT}
+ {-891806400 -10800 1 FKST}
+ {-876690000 -14400 0 FKT}
+ {-860356800 -10800 1 FKST}
+ {420606000 -7200 0 FKT}
+ {433303200 -7200 1 FKST}
+ {452052000 -10800 0 FKT}
+ {464151600 -7200 1 FKST}
+ {483501600 -10800 0 FKT}
+ {495597600 -14400 0 FKT}
+ {495604800 -10800 1 FKST}
+ {514350000 -14400 0 FKT}
+ {527054400 -10800 1 FKST}
+ {545799600 -14400 0 FKT}
+ {558504000 -10800 1 FKST}
+ {577249200 -14400 0 FKT}
+ {589953600 -10800 1 FKST}
+ {608698800 -14400 0 FKT}
+ {621403200 -10800 1 FKST}
+ {640753200 -14400 0 FKT}
+ {652852800 -10800 1 FKST}
+ {672202800 -14400 0 FKT}
+ {684907200 -10800 1 FKST}
+ {703652400 -14400 0 FKT}
+ {716356800 -10800 1 FKST}
+ {735102000 -14400 0 FKT}
+ {747806400 -10800 1 FKST}
+ {766551600 -14400 0 FKT}
+ {779256000 -10800 1 FKST}
+ {798001200 -14400 0 FKT}
+ {810705600 -10800 1 FKST}
+ {830055600 -14400 0 FKT}
+ {842760000 -10800 1 FKST}
+ {861505200 -14400 0 FKT}
+ {874209600 -10800 1 FKST}
+ {892954800 -14400 0 FKT}
+ {905659200 -10800 1 FKST}
+ {924404400 -14400 0 FKT}
+ {937108800 -10800 1 FKST}
+ {955854000 -14400 0 FKT}
+ {968558400 -10800 1 FKST}
+ {987310800 -14400 0 FKT}
+ {999410400 -10800 1 FKST}
+ {1019365200 -14400 0 FKT}
+ {1030860000 -10800 1 FKST}
+ {1050814800 -14400 0 FKT}
+ {1062914400 -10800 1 FKST}
+ {1082264400 -14400 0 FKT}
+ {1094364000 -10800 1 FKST}
+ {1113714000 -14400 0 FKT}
+ {1125813600 -10800 1 FKST}
+ {1145163600 -14400 0 FKT}
+ {1157263200 -10800 1 FKST}
+ {1176613200 -14400 0 FKT}
+ {1188712800 -10800 1 FKST}
+ {1208667600 -14400 0 FKT}
+ {1220767200 -10800 1 FKST}
+ {1240117200 -14400 0 FKT}
+ {1252216800 -10800 1 FKST}
+ {1271566800 -14400 0 FKT}
+ {1283666400 -10800 1 FKST}
+ {1315112400 -10800 1 FKST}
+ {1334466000 -14400 0 FKT}
+ {1346565600 -10800 1 FKST}
+ {1366520400 -14400 0 FKT}
+ {1378015200 -10800 1 FKST}
+ {1397970000 -14400 0 FKT}
+ {1410069600 -10800 1 FKST}
+ {1429419600 -14400 0 FKT}
+ {1441519200 -10800 1 FKST}
+ {1460869200 -14400 0 FKT}
+ {1472968800 -10800 1 FKST}
+ {1492318800 -14400 0 FKT}
+ {1504418400 -10800 1 FKST}
+ {1523768400 -14400 0 FKT}
+ {1535868000 -10800 1 FKST}
+ {1555822800 -14400 0 FKT}
+ {1567317600 -10800 1 FKST}
+ {1587272400 -14400 0 FKT}
+ {1599372000 -10800 1 FKST}
+ {1618722000 -14400 0 FKT}
+ {1630821600 -10800 1 FKST}
+ {1650171600 -14400 0 FKT}
+ {1662271200 -10800 1 FKST}
+ {1681621200 -14400 0 FKT}
+ {1693720800 -10800 1 FKST}
+ {1713675600 -14400 0 FKT}
+ {1725170400 -10800 1 FKST}
+ {1745125200 -14400 0 FKT}
+ {1757224800 -10800 1 FKST}
+ {1776574800 -14400 0 FKT}
+ {1788674400 -10800 1 FKST}
+ {1808024400 -14400 0 FKT}
+ {1820124000 -10800 1 FKST}
+ {1839474000 -14400 0 FKT}
+ {1851573600 -10800 1 FKST}
+ {1870923600 -14400 0 FKT}
+ {1883023200 -10800 1 FKST}
+ {1902978000 -14400 0 FKT}
+ {1914472800 -10800 1 FKST}
+ {1934427600 -14400 0 FKT}
+ {1946527200 -10800 1 FKST}
+ {1965877200 -14400 0 FKT}
+ {1977976800 -10800 1 FKST}
+ {1997326800 -14400 0 FKT}
+ {2009426400 -10800 1 FKST}
+ {2028776400 -14400 0 FKT}
+ {2040876000 -10800 1 FKST}
+ {2060226000 -14400 0 FKT}
+ {2072325600 -10800 1 FKST}
+ {2092280400 -14400 0 FKT}
+ {2104380000 -10800 1 FKST}
+ {2123730000 -14400 0 FKT}
+ {2135829600 -10800 1 FKST}
+ {2155179600 -14400 0 FKT}
+ {2167279200 -10800 1 FKST}
+ {2186629200 -14400 0 FKT}
+ {2198728800 -10800 1 FKST}
+ {2218078800 -14400 0 FKT}
+ {2230178400 -10800 1 FKST}
+ {2250133200 -14400 0 FKT}
+ {2261628000 -10800 1 FKST}
+ {2281582800 -14400 0 FKT}
+ {2293682400 -10800 1 FKST}
+ {2313032400 -14400 0 FKT}
+ {2325132000 -10800 1 FKST}
+ {2344482000 -14400 0 FKT}
+ {2356581600 -10800 1 FKST}
+ {2375931600 -14400 0 FKT}
+ {2388031200 -10800 1 FKST}
+ {2407381200 -14400 0 FKT}
+ {2419480800 -10800 1 FKST}
+ {2439435600 -14400 0 FKT}
+ {2450930400 -10800 1 FKST}
+ {2470885200 -14400 0 FKT}
+ {2482984800 -10800 1 FKST}
+ {2502334800 -14400 0 FKT}
+ {2514434400 -10800 1 FKST}
+ {2533784400 -14400 0 FKT}
+ {2545884000 -10800 1 FKST}
+ {2565234000 -14400 0 FKT}
+ {2577333600 -10800 1 FKST}
+ {2597288400 -14400 0 FKT}
+ {2608783200 -10800 1 FKST}
+ {2628738000 -14400 0 FKT}
+ {2640837600 -10800 1 FKST}
+ {2660187600 -14400 0 FKT}
+ {2672287200 -10800 1 FKST}
+ {2691637200 -14400 0 FKT}
+ {2703736800 -10800 1 FKST}
+ {2723086800 -14400 0 FKT}
+ {2735186400 -10800 1 FKST}
+ {2754536400 -14400 0 FKT}
+ {2766636000 -10800 1 FKST}
+ {2786590800 -14400 0 FKT}
+ {2798085600 -10800 1 FKST}
+ {2818040400 -14400 0 FKT}
+ {2830140000 -10800 1 FKST}
+ {2849490000 -14400 0 FKT}
+ {2861589600 -10800 1 FKST}
+ {2880939600 -14400 0 FKT}
+ {2893039200 -10800 1 FKST}
+ {2912389200 -14400 0 FKT}
+ {2924488800 -10800 1 FKST}
+ {2943838800 -14400 0 FKT}
+ {2955938400 -10800 1 FKST}
+ {2975893200 -14400 0 FKT}
+ {2987992800 -10800 1 FKST}
+ {3007342800 -14400 0 FKT}
+ {3019442400 -10800 1 FKST}
+ {3038792400 -14400 0 FKT}
+ {3050892000 -10800 1 FKST}
+ {3070242000 -14400 0 FKT}
+ {3082341600 -10800 1 FKST}
+ {3101691600 -14400 0 FKT}
+ {3113791200 -10800 1 FKST}
+ {3133746000 -14400 0 FKT}
+ {3145240800 -10800 1 FKST}
+ {3165195600 -14400 0 FKT}
+ {3177295200 -10800 1 FKST}
+ {3196645200 -14400 0 FKT}
+ {3208744800 -10800 1 FKST}
+ {3228094800 -14400 0 FKT}
+ {3240194400 -10800 1 FKST}
+ {3259544400 -14400 0 FKT}
+ {3271644000 -10800 1 FKST}
+ {3290994000 -14400 0 FKT}
+ {3303093600 -10800 1 FKST}
+ {3323048400 -14400 0 FKT}
+ {3334543200 -10800 1 FKST}
+ {3354498000 -14400 0 FKT}
+ {3366597600 -10800 1 FKST}
+ {3385947600 -14400 0 FKT}
+ {3398047200 -10800 1 FKST}
+ {3417397200 -14400 0 FKT}
+ {3429496800 -10800 1 FKST}
+ {3448846800 -14400 0 FKT}
+ {3460946400 -10800 1 FKST}
+ {3480901200 -14400 0 FKT}
+ {3492396000 -10800 1 FKST}
+ {3512350800 -14400 0 FKT}
+ {3524450400 -10800 1 FKST}
+ {3543800400 -14400 0 FKT}
+ {3555900000 -10800 1 FKST}
+ {3575250000 -14400 0 FKT}
+ {3587349600 -10800 1 FKST}
+ {3606699600 -14400 0 FKT}
+ {3618799200 -10800 1 FKST}
+ {3638149200 -14400 0 FKT}
+ {3650248800 -10800 1 FKST}
+ {3670203600 -14400 0 FKT}
+ {3681698400 -10800 1 FKST}
+ {3701653200 -14400 0 FKT}
+ {3713752800 -10800 1 FKST}
+ {3733102800 -14400 0 FKT}
+ {3745202400 -10800 1 FKST}
+ {3764552400 -14400 0 FKT}
+ {3776652000 -10800 1 FKST}
+ {3796002000 -14400 0 FKT}
+ {3808101600 -10800 1 FKST}
+ {3827451600 -14400 0 FKT}
+ {3839551200 -10800 1 FKST}
+ {3859506000 -14400 0 FKT}
+ {3871605600 -10800 1 FKST}
+ {3890955600 -14400 0 FKT}
+ {3903055200 -10800 1 FKST}
+ {3922405200 -14400 0 FKT}
+ {3934504800 -10800 1 FKST}
+ {3953854800 -14400 0 FKT}
+ {3965954400 -10800 1 FKST}
+ {3985304400 -14400 0 FKT}
+ {3997404000 -10800 1 FKST}
+ {4017358800 -14400 0 FKT}
+ {4028853600 -10800 1 FKST}
+ {4048808400 -14400 0 FKT}
+ {4060908000 -10800 1 FKST}
+ {4080258000 -14400 0 FKT}
+ {4092357600 -10800 1 FKST}
+}
diff --git a/library/tzdata/Australia/ACT b/library/tzdata/Australia/ACT
new file mode 100644
index 0000000..f7da281
--- /dev/null
+++ b/library/tzdata/Australia/ACT
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Australia/Sydney)]} {
+ LoadTimeZoneFile Australia/Sydney
+}
+set TZData(:Australia/ACT) $TZData(:Australia/Sydney)
diff --git a/library/tzdata/Australia/Adelaide b/library/tzdata/Australia/Adelaide
new file mode 100644
index 0000000..9abe192
--- /dev/null
+++ b/library/tzdata/Australia/Adelaide
@@ -0,0 +1,273 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Australia/Adelaide) {
+ {-9223372036854775808 33260 0 LMT}
+ {-2364110060 32400 0 CST}
+ {-2230189200 34200 0 CST}
+ {-1672565340 37800 1 CST}
+ {-1665390600 34200 0 CST}
+ {-883639800 37800 1 CST}
+ {-876126600 34200 0 CST}
+ {-860398200 37800 1 CST}
+ {-844677000 34200 0 CST}
+ {-828343800 37800 1 CST}
+ {-813227400 34200 0 CST}
+ {31501800 34200 0 CST}
+ {57688200 37800 1 CST}
+ {67969800 34200 0 CST}
+ {89137800 37800 1 CST}
+ {100024200 34200 0 CST}
+ {120587400 37800 1 CST}
+ {131473800 34200 0 CST}
+ {152037000 37800 1 CST}
+ {162923400 34200 0 CST}
+ {183486600 37800 1 CST}
+ {194977800 34200 0 CST}
+ {215541000 37800 1 CST}
+ {226427400 34200 0 CST}
+ {246990600 37800 1 CST}
+ {257877000 34200 0 CST}
+ {278440200 37800 1 CST}
+ {289326600 34200 0 CST}
+ {309889800 37800 1 CST}
+ {320776200 34200 0 CST}
+ {341339400 37800 1 CST}
+ {352225800 34200 0 CST}
+ {372789000 37800 1 CST}
+ {384280200 34200 0 CST}
+ {404843400 37800 1 CST}
+ {415729800 34200 0 CST}
+ {436293000 37800 1 CST}
+ {447179400 34200 0 CST}
+ {467742600 37800 1 CST}
+ {478629000 34200 0 CST}
+ {499192200 37800 1 CST}
+ {511288200 34200 0 CST}
+ {530037000 37800 1 CST}
+ {542737800 34200 0 CST}
+ {562091400 37800 1 CST}
+ {574792200 34200 0 CST}
+ {594145800 37800 1 CST}
+ {606241800 34200 0 CST}
+ {625595400 37800 1 CST}
+ {637691400 34200 0 CST}
+ {657045000 37800 1 CST}
+ {667931400 34200 0 CST}
+ {688494600 37800 1 CST}
+ {701195400 34200 0 CST}
+ {719944200 37800 1 CST}
+ {731435400 34200 0 CST}
+ {751998600 37800 1 CST}
+ {764094600 34200 0 CST}
+ {783448200 37800 1 CST}
+ {796149000 34200 0 CST}
+ {814897800 37800 1 CST}
+ {828203400 34200 0 CST}
+ {846347400 37800 1 CST}
+ {859653000 34200 0 CST}
+ {877797000 37800 1 CST}
+ {891102600 34200 0 CST}
+ {909246600 37800 1 CST}
+ {922552200 34200 0 CST}
+ {941301000 37800 1 CST}
+ {954001800 34200 0 CST}
+ {972750600 37800 1 CST}
+ {985451400 34200 0 CST}
+ {1004200200 37800 1 CST}
+ {1017505800 34200 0 CST}
+ {1035649800 37800 1 CST}
+ {1048955400 34200 0 CST}
+ {1067099400 37800 1 CST}
+ {1080405000 34200 0 CST}
+ {1099153800 37800 1 CST}
+ {1111854600 34200 0 CST}
+ {1130603400 37800 1 CST}
+ {1143909000 34200 0 CST}
+ {1162053000 37800 1 CST}
+ {1174753800 34200 0 CST}
+ {1193502600 37800 1 CST}
+ {1207413000 34200 0 CST}
+ {1223137800 37800 1 CST}
+ {1238862600 34200 0 CST}
+ {1254587400 37800 1 CST}
+ {1270312200 34200 0 CST}
+ {1286037000 37800 1 CST}
+ {1301761800 34200 0 CST}
+ {1317486600 37800 1 CST}
+ {1333211400 34200 0 CST}
+ {1349541000 37800 1 CST}
+ {1365265800 34200 0 CST}
+ {1380990600 37800 1 CST}
+ {1396715400 34200 0 CST}
+ {1412440200 37800 1 CST}
+ {1428165000 34200 0 CST}
+ {1443889800 37800 1 CST}
+ {1459614600 34200 0 CST}
+ {1475339400 37800 1 CST}
+ {1491064200 34200 0 CST}
+ {1506789000 37800 1 CST}
+ {1522513800 34200 0 CST}
+ {1538843400 37800 1 CST}
+ {1554568200 34200 0 CST}
+ {1570293000 37800 1 CST}
+ {1586017800 34200 0 CST}
+ {1601742600 37800 1 CST}
+ {1617467400 34200 0 CST}
+ {1633192200 37800 1 CST}
+ {1648917000 34200 0 CST}
+ {1664641800 37800 1 CST}
+ {1680366600 34200 0 CST}
+ {1696091400 37800 1 CST}
+ {1712421000 34200 0 CST}
+ {1728145800 37800 1 CST}
+ {1743870600 34200 0 CST}
+ {1759595400 37800 1 CST}
+ {1775320200 34200 0 CST}
+ {1791045000 37800 1 CST}
+ {1806769800 34200 0 CST}
+ {1822494600 37800 1 CST}
+ {1838219400 34200 0 CST}
+ {1853944200 37800 1 CST}
+ {1869669000 34200 0 CST}
+ {1885998600 37800 1 CST}
+ {1901723400 34200 0 CST}
+ {1917448200 37800 1 CST}
+ {1933173000 34200 0 CST}
+ {1948897800 37800 1 CST}
+ {1964622600 34200 0 CST}
+ {1980347400 37800 1 CST}
+ {1996072200 34200 0 CST}
+ {2011797000 37800 1 CST}
+ {2027521800 34200 0 CST}
+ {2043246600 37800 1 CST}
+ {2058971400 34200 0 CST}
+ {2075301000 37800 1 CST}
+ {2091025800 34200 0 CST}
+ {2106750600 37800 1 CST}
+ {2122475400 34200 0 CST}
+ {2138200200 37800 1 CST}
+ {2153925000 34200 0 CST}
+ {2169649800 37800 1 CST}
+ {2185374600 34200 0 CST}
+ {2201099400 37800 1 CST}
+ {2216824200 34200 0 CST}
+ {2233153800 37800 1 CST}
+ {2248878600 34200 0 CST}
+ {2264603400 37800 1 CST}
+ {2280328200 34200 0 CST}
+ {2296053000 37800 1 CST}
+ {2311777800 34200 0 CST}
+ {2327502600 37800 1 CST}
+ {2343227400 34200 0 CST}
+ {2358952200 37800 1 CST}
+ {2374677000 34200 0 CST}
+ {2390401800 37800 1 CST}
+ {2406126600 34200 0 CST}
+ {2422456200 37800 1 CST}
+ {2438181000 34200 0 CST}
+ {2453905800 37800 1 CST}
+ {2469630600 34200 0 CST}
+ {2485355400 37800 1 CST}
+ {2501080200 34200 0 CST}
+ {2516805000 37800 1 CST}
+ {2532529800 34200 0 CST}
+ {2548254600 37800 1 CST}
+ {2563979400 34200 0 CST}
+ {2579704200 37800 1 CST}
+ {2596033800 34200 0 CST}
+ {2611758600 37800 1 CST}
+ {2627483400 34200 0 CST}
+ {2643208200 37800 1 CST}
+ {2658933000 34200 0 CST}
+ {2674657800 37800 1 CST}
+ {2690382600 34200 0 CST}
+ {2706107400 37800 1 CST}
+ {2721832200 34200 0 CST}
+ {2737557000 37800 1 CST}
+ {2753281800 34200 0 CST}
+ {2769611400 37800 1 CST}
+ {2785336200 34200 0 CST}
+ {2801061000 37800 1 CST}
+ {2816785800 34200 0 CST}
+ {2832510600 37800 1 CST}
+ {2848235400 34200 0 CST}
+ {2863960200 37800 1 CST}
+ {2879685000 34200 0 CST}
+ {2895409800 37800 1 CST}
+ {2911134600 34200 0 CST}
+ {2926859400 37800 1 CST}
+ {2942584200 34200 0 CST}
+ {2958913800 37800 1 CST}
+ {2974638600 34200 0 CST}
+ {2990363400 37800 1 CST}
+ {3006088200 34200 0 CST}
+ {3021813000 37800 1 CST}
+ {3037537800 34200 0 CST}
+ {3053262600 37800 1 CST}
+ {3068987400 34200 0 CST}
+ {3084712200 37800 1 CST}
+ {3100437000 34200 0 CST}
+ {3116766600 37800 1 CST}
+ {3132491400 34200 0 CST}
+ {3148216200 37800 1 CST}
+ {3163941000 34200 0 CST}
+ {3179665800 37800 1 CST}
+ {3195390600 34200 0 CST}
+ {3211115400 37800 1 CST}
+ {3226840200 34200 0 CST}
+ {3242565000 37800 1 CST}
+ {3258289800 34200 0 CST}
+ {3274014600 37800 1 CST}
+ {3289739400 34200 0 CST}
+ {3306069000 37800 1 CST}
+ {3321793800 34200 0 CST}
+ {3337518600 37800 1 CST}
+ {3353243400 34200 0 CST}
+ {3368968200 37800 1 CST}
+ {3384693000 34200 0 CST}
+ {3400417800 37800 1 CST}
+ {3416142600 34200 0 CST}
+ {3431867400 37800 1 CST}
+ {3447592200 34200 0 CST}
+ {3463317000 37800 1 CST}
+ {3479646600 34200 0 CST}
+ {3495371400 37800 1 CST}
+ {3511096200 34200 0 CST}
+ {3526821000 37800 1 CST}
+ {3542545800 34200 0 CST}
+ {3558270600 37800 1 CST}
+ {3573995400 34200 0 CST}
+ {3589720200 37800 1 CST}
+ {3605445000 34200 0 CST}
+ {3621169800 37800 1 CST}
+ {3636894600 34200 0 CST}
+ {3653224200 37800 1 CST}
+ {3668949000 34200 0 CST}
+ {3684673800 37800 1 CST}
+ {3700398600 34200 0 CST}
+ {3716123400 37800 1 CST}
+ {3731848200 34200 0 CST}
+ {3747573000 37800 1 CST}
+ {3763297800 34200 0 CST}
+ {3779022600 37800 1 CST}
+ {3794747400 34200 0 CST}
+ {3810472200 37800 1 CST}
+ {3826197000 34200 0 CST}
+ {3842526600 37800 1 CST}
+ {3858251400 34200 0 CST}
+ {3873976200 37800 1 CST}
+ {3889701000 34200 0 CST}
+ {3905425800 37800 1 CST}
+ {3921150600 34200 0 CST}
+ {3936875400 37800 1 CST}
+ {3952600200 34200 0 CST}
+ {3968325000 37800 1 CST}
+ {3984049800 34200 0 CST}
+ {4000379400 37800 1 CST}
+ {4016104200 34200 0 CST}
+ {4031829000 37800 1 CST}
+ {4047553800 34200 0 CST}
+ {4063278600 37800 1 CST}
+ {4079003400 34200 0 CST}
+ {4094728200 37800 1 CST}
+}
diff --git a/library/tzdata/Australia/Brisbane b/library/tzdata/Australia/Brisbane
new file mode 100644
index 0000000..fe6d154
--- /dev/null
+++ b/library/tzdata/Australia/Brisbane
@@ -0,0 +1,23 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Australia/Brisbane) {
+ {-9223372036854775808 36728 0 LMT}
+ {-2366791928 36000 0 EST}
+ {-1672567140 39600 1 EST}
+ {-1665392400 36000 0 EST}
+ {-883641600 39600 1 EST}
+ {-876128400 36000 0 EST}
+ {-860400000 39600 1 EST}
+ {-844678800 36000 0 EST}
+ {-828345600 39600 1 EST}
+ {-813229200 36000 0 EST}
+ {31500000 36000 0 EST}
+ {57686400 39600 1 EST}
+ {67968000 36000 0 EST}
+ {625593600 39600 1 EST}
+ {636480000 36000 0 EST}
+ {657043200 39600 1 EST}
+ {667929600 36000 0 EST}
+ {688492800 39600 1 EST}
+ {699379200 36000 0 EST}
+}
diff --git a/library/tzdata/Australia/Broken_Hill b/library/tzdata/Australia/Broken_Hill
new file mode 100644
index 0000000..35cbb7e
--- /dev/null
+++ b/library/tzdata/Australia/Broken_Hill
@@ -0,0 +1,275 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Australia/Broken_Hill) {
+ {-9223372036854775808 33948 0 LMT}
+ {-2364110748 36000 0 EST}
+ {-2314951200 32400 0 CST}
+ {-2230189200 34200 0 CST}
+ {-1672565340 37800 1 CST}
+ {-1665390600 34200 0 CST}
+ {-883639800 37800 1 CST}
+ {-876126600 34200 0 CST}
+ {-860398200 37800 1 CST}
+ {-844677000 34200 0 CST}
+ {-828343800 37800 1 CST}
+ {-813227400 34200 0 CST}
+ {31501800 34200 0 CST}
+ {57688200 37800 1 CST}
+ {67969800 34200 0 CST}
+ {89137800 37800 1 CST}
+ {100024200 34200 0 CST}
+ {120587400 37800 1 CST}
+ {131473800 34200 0 CST}
+ {152037000 37800 1 CST}
+ {162923400 34200 0 CST}
+ {183486600 37800 1 CST}
+ {194977800 34200 0 CST}
+ {215541000 37800 1 CST}
+ {226427400 34200 0 CST}
+ {246990600 37800 1 CST}
+ {257877000 34200 0 CST}
+ {278440200 37800 1 CST}
+ {289326600 34200 0 CST}
+ {309889800 37800 1 CST}
+ {320776200 34200 0 CST}
+ {341339400 37800 1 CST}
+ {352225800 34200 0 CST}
+ {372789000 37800 1 CST}
+ {386699400 34200 0 CST}
+ {404843400 37800 1 CST}
+ {415729800 34200 0 CST}
+ {436293000 37800 1 CST}
+ {447179400 34200 0 CST}
+ {467742600 37800 1 CST}
+ {478629000 34200 0 CST}
+ {499192200 37800 1 CST}
+ {511288200 34200 0 CST}
+ {530037000 37800 1 CST}
+ {542737800 34200 0 CST}
+ {562091400 37800 1 CST}
+ {574792200 34200 0 CST}
+ {594145800 37800 1 CST}
+ {606241800 34200 0 CST}
+ {625595400 37800 1 CST}
+ {636481800 34200 0 CST}
+ {657045000 37800 1 CST}
+ {667931400 34200 0 CST}
+ {688494600 37800 1 CST}
+ {699381000 34200 0 CST}
+ {719944200 37800 1 CST}
+ {731435400 34200 0 CST}
+ {751998600 37800 1 CST}
+ {762885000 34200 0 CST}
+ {783448200 37800 1 CST}
+ {794334600 34200 0 CST}
+ {814897800 37800 1 CST}
+ {828203400 34200 0 CST}
+ {846347400 37800 1 CST}
+ {859653000 34200 0 CST}
+ {877797000 37800 1 CST}
+ {891102600 34200 0 CST}
+ {909246600 37800 1 CST}
+ {922552200 34200 0 CST}
+ {941301000 37800 1 CST}
+ {946647000 37800 0 CST}
+ {954001800 34200 0 CST}
+ {972750600 37800 1 CST}
+ {985451400 34200 0 CST}
+ {1004200200 37800 1 CST}
+ {1017505800 34200 0 CST}
+ {1035649800 37800 1 CST}
+ {1048955400 34200 0 CST}
+ {1067099400 37800 1 CST}
+ {1080405000 34200 0 CST}
+ {1099153800 37800 1 CST}
+ {1111854600 34200 0 CST}
+ {1130603400 37800 1 CST}
+ {1143909000 34200 0 CST}
+ {1162053000 37800 1 CST}
+ {1174753800 34200 0 CST}
+ {1193502600 37800 1 CST}
+ {1207413000 34200 0 CST}
+ {1223137800 37800 1 CST}
+ {1238862600 34200 0 CST}
+ {1254587400 37800 1 CST}
+ {1270312200 34200 0 CST}
+ {1286037000 37800 1 CST}
+ {1301761800 34200 0 CST}
+ {1317486600 37800 1 CST}
+ {1333211400 34200 0 CST}
+ {1349541000 37800 1 CST}
+ {1365265800 34200 0 CST}
+ {1380990600 37800 1 CST}
+ {1396715400 34200 0 CST}
+ {1412440200 37800 1 CST}
+ {1428165000 34200 0 CST}
+ {1443889800 37800 1 CST}
+ {1459614600 34200 0 CST}
+ {1475339400 37800 1 CST}
+ {1491064200 34200 0 CST}
+ {1506789000 37800 1 CST}
+ {1522513800 34200 0 CST}
+ {1538843400 37800 1 CST}
+ {1554568200 34200 0 CST}
+ {1570293000 37800 1 CST}
+ {1586017800 34200 0 CST}
+ {1601742600 37800 1 CST}
+ {1617467400 34200 0 CST}
+ {1633192200 37800 1 CST}
+ {1648917000 34200 0 CST}
+ {1664641800 37800 1 CST}
+ {1680366600 34200 0 CST}
+ {1696091400 37800 1 CST}
+ {1712421000 34200 0 CST}
+ {1728145800 37800 1 CST}
+ {1743870600 34200 0 CST}
+ {1759595400 37800 1 CST}
+ {1775320200 34200 0 CST}
+ {1791045000 37800 1 CST}
+ {1806769800 34200 0 CST}
+ {1822494600 37800 1 CST}
+ {1838219400 34200 0 CST}
+ {1853944200 37800 1 CST}
+ {1869669000 34200 0 CST}
+ {1885998600 37800 1 CST}
+ {1901723400 34200 0 CST}
+ {1917448200 37800 1 CST}
+ {1933173000 34200 0 CST}
+ {1948897800 37800 1 CST}
+ {1964622600 34200 0 CST}
+ {1980347400 37800 1 CST}
+ {1996072200 34200 0 CST}
+ {2011797000 37800 1 CST}
+ {2027521800 34200 0 CST}
+ {2043246600 37800 1 CST}
+ {2058971400 34200 0 CST}
+ {2075301000 37800 1 CST}
+ {2091025800 34200 0 CST}
+ {2106750600 37800 1 CST}
+ {2122475400 34200 0 CST}
+ {2138200200 37800 1 CST}
+ {2153925000 34200 0 CST}
+ {2169649800 37800 1 CST}
+ {2185374600 34200 0 CST}
+ {2201099400 37800 1 CST}
+ {2216824200 34200 0 CST}
+ {2233153800 37800 1 CST}
+ {2248878600 34200 0 CST}
+ {2264603400 37800 1 CST}
+ {2280328200 34200 0 CST}
+ {2296053000 37800 1 CST}
+ {2311777800 34200 0 CST}
+ {2327502600 37800 1 CST}
+ {2343227400 34200 0 CST}
+ {2358952200 37800 1 CST}
+ {2374677000 34200 0 CST}
+ {2390401800 37800 1 CST}
+ {2406126600 34200 0 CST}
+ {2422456200 37800 1 CST}
+ {2438181000 34200 0 CST}
+ {2453905800 37800 1 CST}
+ {2469630600 34200 0 CST}
+ {2485355400 37800 1 CST}
+ {2501080200 34200 0 CST}
+ {2516805000 37800 1 CST}
+ {2532529800 34200 0 CST}
+ {2548254600 37800 1 CST}
+ {2563979400 34200 0 CST}
+ {2579704200 37800 1 CST}
+ {2596033800 34200 0 CST}
+ {2611758600 37800 1 CST}
+ {2627483400 34200 0 CST}
+ {2643208200 37800 1 CST}
+ {2658933000 34200 0 CST}
+ {2674657800 37800 1 CST}
+ {2690382600 34200 0 CST}
+ {2706107400 37800 1 CST}
+ {2721832200 34200 0 CST}
+ {2737557000 37800 1 CST}
+ {2753281800 34200 0 CST}
+ {2769611400 37800 1 CST}
+ {2785336200 34200 0 CST}
+ {2801061000 37800 1 CST}
+ {2816785800 34200 0 CST}
+ {2832510600 37800 1 CST}
+ {2848235400 34200 0 CST}
+ {2863960200 37800 1 CST}
+ {2879685000 34200 0 CST}
+ {2895409800 37800 1 CST}
+ {2911134600 34200 0 CST}
+ {2926859400 37800 1 CST}
+ {2942584200 34200 0 CST}
+ {2958913800 37800 1 CST}
+ {2974638600 34200 0 CST}
+ {2990363400 37800 1 CST}
+ {3006088200 34200 0 CST}
+ {3021813000 37800 1 CST}
+ {3037537800 34200 0 CST}
+ {3053262600 37800 1 CST}
+ {3068987400 34200 0 CST}
+ {3084712200 37800 1 CST}
+ {3100437000 34200 0 CST}
+ {3116766600 37800 1 CST}
+ {3132491400 34200 0 CST}
+ {3148216200 37800 1 CST}
+ {3163941000 34200 0 CST}
+ {3179665800 37800 1 CST}
+ {3195390600 34200 0 CST}
+ {3211115400 37800 1 CST}
+ {3226840200 34200 0 CST}
+ {3242565000 37800 1 CST}
+ {3258289800 34200 0 CST}
+ {3274014600 37800 1 CST}
+ {3289739400 34200 0 CST}
+ {3306069000 37800 1 CST}
+ {3321793800 34200 0 CST}
+ {3337518600 37800 1 CST}
+ {3353243400 34200 0 CST}
+ {3368968200 37800 1 CST}
+ {3384693000 34200 0 CST}
+ {3400417800 37800 1 CST}
+ {3416142600 34200 0 CST}
+ {3431867400 37800 1 CST}
+ {3447592200 34200 0 CST}
+ {3463317000 37800 1 CST}
+ {3479646600 34200 0 CST}
+ {3495371400 37800 1 CST}
+ {3511096200 34200 0 CST}
+ {3526821000 37800 1 CST}
+ {3542545800 34200 0 CST}
+ {3558270600 37800 1 CST}
+ {3573995400 34200 0 CST}
+ {3589720200 37800 1 CST}
+ {3605445000 34200 0 CST}
+ {3621169800 37800 1 CST}
+ {3636894600 34200 0 CST}
+ {3653224200 37800 1 CST}
+ {3668949000 34200 0 CST}
+ {3684673800 37800 1 CST}
+ {3700398600 34200 0 CST}
+ {3716123400 37800 1 CST}
+ {3731848200 34200 0 CST}
+ {3747573000 37800 1 CST}
+ {3763297800 34200 0 CST}
+ {3779022600 37800 1 CST}
+ {3794747400 34200 0 CST}
+ {3810472200 37800 1 CST}
+ {3826197000 34200 0 CST}
+ {3842526600 37800 1 CST}
+ {3858251400 34200 0 CST}
+ {3873976200 37800 1 CST}
+ {3889701000 34200 0 CST}
+ {3905425800 37800 1 CST}
+ {3921150600 34200 0 CST}
+ {3936875400 37800 1 CST}
+ {3952600200 34200 0 CST}
+ {3968325000 37800 1 CST}
+ {3984049800 34200 0 CST}
+ {4000379400 37800 1 CST}
+ {4016104200 34200 0 CST}
+ {4031829000 37800 1 CST}
+ {4047553800 34200 0 CST}
+ {4063278600 37800 1 CST}
+ {4079003400 34200 0 CST}
+ {4094728200 37800 1 CST}
+}
diff --git a/library/tzdata/Australia/Canberra b/library/tzdata/Australia/Canberra
new file mode 100644
index 0000000..0b7b9ca
--- /dev/null
+++ b/library/tzdata/Australia/Canberra
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Australia/Sydney)]} {
+ LoadTimeZoneFile Australia/Sydney
+}
+set TZData(:Australia/Canberra) $TZData(:Australia/Sydney)
diff --git a/library/tzdata/Australia/Currie b/library/tzdata/Australia/Currie
new file mode 100644
index 0000000..ae6d1f0
--- /dev/null
+++ b/library/tzdata/Australia/Currie
@@ -0,0 +1,273 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Australia/Currie) {
+ {-9223372036854775808 34528 0 LMT}
+ {-2345794528 36000 0 EST}
+ {-1680508800 39600 1 EST}
+ {-1669892400 39600 0 EST}
+ {-1665392400 36000 0 EST}
+ {-883641600 39600 1 EST}
+ {-876128400 36000 0 EST}
+ {-860400000 39600 1 EST}
+ {-844678800 36000 0 EST}
+ {-828345600 39600 1 EST}
+ {-813229200 36000 0 EST}
+ {47138400 36000 0 EST}
+ {57686400 39600 1 EST}
+ {67968000 36000 0 EST}
+ {89136000 39600 1 EST}
+ {100022400 36000 0 EST}
+ {120585600 39600 1 EST}
+ {131472000 36000 0 EST}
+ {152035200 39600 1 EST}
+ {162921600 36000 0 EST}
+ {183484800 39600 1 EST}
+ {194976000 36000 0 EST}
+ {215539200 39600 1 EST}
+ {226425600 36000 0 EST}
+ {246988800 39600 1 EST}
+ {257875200 36000 0 EST}
+ {278438400 39600 1 EST}
+ {289324800 36000 0 EST}
+ {309888000 39600 1 EST}
+ {320774400 36000 0 EST}
+ {341337600 39600 1 EST}
+ {352224000 36000 0 EST}
+ {372787200 39600 1 EST}
+ {386092800 36000 0 EST}
+ {404841600 39600 1 EST}
+ {417542400 36000 0 EST}
+ {436291200 39600 1 EST}
+ {447177600 36000 0 EST}
+ {467740800 39600 1 EST}
+ {478627200 36000 0 EST}
+ {499190400 39600 1 EST}
+ {510076800 36000 0 EST}
+ {530035200 39600 1 EST}
+ {542736000 36000 0 EST}
+ {562089600 39600 1 EST}
+ {574790400 36000 0 EST}
+ {594144000 39600 1 EST}
+ {606240000 36000 0 EST}
+ {625593600 39600 1 EST}
+ {637689600 36000 0 EST}
+ {657043200 39600 1 EST}
+ {670348800 36000 0 EST}
+ {686678400 39600 1 EST}
+ {701798400 36000 0 EST}
+ {718128000 39600 1 EST}
+ {733248000 36000 0 EST}
+ {749577600 39600 1 EST}
+ {764697600 36000 0 EST}
+ {781027200 39600 1 EST}
+ {796147200 36000 0 EST}
+ {812476800 39600 1 EST}
+ {828201600 36000 0 EST}
+ {844531200 39600 1 EST}
+ {859651200 36000 0 EST}
+ {875980800 39600 1 EST}
+ {891100800 36000 0 EST}
+ {907430400 39600 1 EST}
+ {922550400 36000 0 EST}
+ {938880000 39600 1 EST}
+ {954000000 36000 0 EST}
+ {967305600 39600 1 EST}
+ {985449600 36000 0 EST}
+ {1002384000 39600 1 EST}
+ {1017504000 36000 0 EST}
+ {1033833600 39600 1 EST}
+ {1048953600 36000 0 EST}
+ {1065283200 39600 1 EST}
+ {1080403200 36000 0 EST}
+ {1096732800 39600 1 EST}
+ {1111852800 36000 0 EST}
+ {1128182400 39600 1 EST}
+ {1143907200 36000 0 EST}
+ {1159632000 39600 1 EST}
+ {1174752000 36000 0 EST}
+ {1191686400 39600 1 EST}
+ {1207411200 36000 0 EST}
+ {1223136000 39600 1 EST}
+ {1238860800 36000 0 EST}
+ {1254585600 39600 1 EST}
+ {1270310400 36000 0 EST}
+ {1286035200 39600 1 EST}
+ {1301760000 36000 0 EST}
+ {1317484800 39600 1 EST}
+ {1333209600 36000 0 EST}
+ {1349539200 39600 1 EST}
+ {1365264000 36000 0 EST}
+ {1380988800 39600 1 EST}
+ {1396713600 36000 0 EST}
+ {1412438400 39600 1 EST}
+ {1428163200 36000 0 EST}
+ {1443888000 39600 1 EST}
+ {1459612800 36000 0 EST}
+ {1475337600 39600 1 EST}
+ {1491062400 36000 0 EST}
+ {1506787200 39600 1 EST}
+ {1522512000 36000 0 EST}
+ {1538841600 39600 1 EST}
+ {1554566400 36000 0 EST}
+ {1570291200 39600 1 EST}
+ {1586016000 36000 0 EST}
+ {1601740800 39600 1 EST}
+ {1617465600 36000 0 EST}
+ {1633190400 39600 1 EST}
+ {1648915200 36000 0 EST}
+ {1664640000 39600 1 EST}
+ {1680364800 36000 0 EST}
+ {1696089600 39600 1 EST}
+ {1712419200 36000 0 EST}
+ {1728144000 39600 1 EST}
+ {1743868800 36000 0 EST}
+ {1759593600 39600 1 EST}
+ {1775318400 36000 0 EST}
+ {1791043200 39600 1 EST}
+ {1806768000 36000 0 EST}
+ {1822492800 39600 1 EST}
+ {1838217600 36000 0 EST}
+ {1853942400 39600 1 EST}
+ {1869667200 36000 0 EST}
+ {1885996800 39600 1 EST}
+ {1901721600 36000 0 EST}
+ {1917446400 39600 1 EST}
+ {1933171200 36000 0 EST}
+ {1948896000 39600 1 EST}
+ {1964620800 36000 0 EST}
+ {1980345600 39600 1 EST}
+ {1996070400 36000 0 EST}
+ {2011795200 39600 1 EST}
+ {2027520000 36000 0 EST}
+ {2043244800 39600 1 EST}
+ {2058969600 36000 0 EST}
+ {2075299200 39600 1 EST}
+ {2091024000 36000 0 EST}
+ {2106748800 39600 1 EST}
+ {2122473600 36000 0 EST}
+ {2138198400 39600 1 EST}
+ {2153923200 36000 0 EST}
+ {2169648000 39600 1 EST}
+ {2185372800 36000 0 EST}
+ {2201097600 39600 1 EST}
+ {2216822400 36000 0 EST}
+ {2233152000 39600 1 EST}
+ {2248876800 36000 0 EST}
+ {2264601600 39600 1 EST}
+ {2280326400 36000 0 EST}
+ {2296051200 39600 1 EST}
+ {2311776000 36000 0 EST}
+ {2327500800 39600 1 EST}
+ {2343225600 36000 0 EST}
+ {2358950400 39600 1 EST}
+ {2374675200 36000 0 EST}
+ {2390400000 39600 1 EST}
+ {2406124800 36000 0 EST}
+ {2422454400 39600 1 EST}
+ {2438179200 36000 0 EST}
+ {2453904000 39600 1 EST}
+ {2469628800 36000 0 EST}
+ {2485353600 39600 1 EST}
+ {2501078400 36000 0 EST}
+ {2516803200 39600 1 EST}
+ {2532528000 36000 0 EST}
+ {2548252800 39600 1 EST}
+ {2563977600 36000 0 EST}
+ {2579702400 39600 1 EST}
+ {2596032000 36000 0 EST}
+ {2611756800 39600 1 EST}
+ {2627481600 36000 0 EST}
+ {2643206400 39600 1 EST}
+ {2658931200 36000 0 EST}
+ {2674656000 39600 1 EST}
+ {2690380800 36000 0 EST}
+ {2706105600 39600 1 EST}
+ {2721830400 36000 0 EST}
+ {2737555200 39600 1 EST}
+ {2753280000 36000 0 EST}
+ {2769609600 39600 1 EST}
+ {2785334400 36000 0 EST}
+ {2801059200 39600 1 EST}
+ {2816784000 36000 0 EST}
+ {2832508800 39600 1 EST}
+ {2848233600 36000 0 EST}
+ {2863958400 39600 1 EST}
+ {2879683200 36000 0 EST}
+ {2895408000 39600 1 EST}
+ {2911132800 36000 0 EST}
+ {2926857600 39600 1 EST}
+ {2942582400 36000 0 EST}
+ {2958912000 39600 1 EST}
+ {2974636800 36000 0 EST}
+ {2990361600 39600 1 EST}
+ {3006086400 36000 0 EST}
+ {3021811200 39600 1 EST}
+ {3037536000 36000 0 EST}
+ {3053260800 39600 1 EST}
+ {3068985600 36000 0 EST}
+ {3084710400 39600 1 EST}
+ {3100435200 36000 0 EST}
+ {3116764800 39600 1 EST}
+ {3132489600 36000 0 EST}
+ {3148214400 39600 1 EST}
+ {3163939200 36000 0 EST}
+ {3179664000 39600 1 EST}
+ {3195388800 36000 0 EST}
+ {3211113600 39600 1 EST}
+ {3226838400 36000 0 EST}
+ {3242563200 39600 1 EST}
+ {3258288000 36000 0 EST}
+ {3274012800 39600 1 EST}
+ {3289737600 36000 0 EST}
+ {3306067200 39600 1 EST}
+ {3321792000 36000 0 EST}
+ {3337516800 39600 1 EST}
+ {3353241600 36000 0 EST}
+ {3368966400 39600 1 EST}
+ {3384691200 36000 0 EST}
+ {3400416000 39600 1 EST}
+ {3416140800 36000 0 EST}
+ {3431865600 39600 1 EST}
+ {3447590400 36000 0 EST}
+ {3463315200 39600 1 EST}
+ {3479644800 36000 0 EST}
+ {3495369600 39600 1 EST}
+ {3511094400 36000 0 EST}
+ {3526819200 39600 1 EST}
+ {3542544000 36000 0 EST}
+ {3558268800 39600 1 EST}
+ {3573993600 36000 0 EST}
+ {3589718400 39600 1 EST}
+ {3605443200 36000 0 EST}
+ {3621168000 39600 1 EST}
+ {3636892800 36000 0 EST}
+ {3653222400 39600 1 EST}
+ {3668947200 36000 0 EST}
+ {3684672000 39600 1 EST}
+ {3700396800 36000 0 EST}
+ {3716121600 39600 1 EST}
+ {3731846400 36000 0 EST}
+ {3747571200 39600 1 EST}
+ {3763296000 36000 0 EST}
+ {3779020800 39600 1 EST}
+ {3794745600 36000 0 EST}
+ {3810470400 39600 1 EST}
+ {3826195200 36000 0 EST}
+ {3842524800 39600 1 EST}
+ {3858249600 36000 0 EST}
+ {3873974400 39600 1 EST}
+ {3889699200 36000 0 EST}
+ {3905424000 39600 1 EST}
+ {3921148800 36000 0 EST}
+ {3936873600 39600 1 EST}
+ {3952598400 36000 0 EST}
+ {3968323200 39600 1 EST}
+ {3984048000 36000 0 EST}
+ {4000377600 39600 1 EST}
+ {4016102400 36000 0 EST}
+ {4031827200 39600 1 EST}
+ {4047552000 36000 0 EST}
+ {4063276800 39600 1 EST}
+ {4079001600 36000 0 EST}
+ {4094726400 39600 1 EST}
+}
diff --git a/library/tzdata/Australia/Darwin b/library/tzdata/Australia/Darwin
new file mode 100644
index 0000000..9be372d
--- /dev/null
+++ b/library/tzdata/Australia/Darwin
@@ -0,0 +1,15 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Australia/Darwin) {
+ {-9223372036854775808 31400 0 LMT}
+ {-2364108200 32400 0 CST}
+ {-2230189200 34200 0 CST}
+ {-1672565340 37800 1 CST}
+ {-1665390600 34200 0 CST}
+ {-883639800 37800 1 CST}
+ {-876126600 34200 0 CST}
+ {-860398200 37800 1 CST}
+ {-844677000 34200 0 CST}
+ {-828343800 37800 1 CST}
+ {-813227400 34200 0 CST}
+}
diff --git a/library/tzdata/Australia/Eucla b/library/tzdata/Australia/Eucla
new file mode 100755
index 0000000..0f8ed4d
--- /dev/null
+++ b/library/tzdata/Australia/Eucla
@@ -0,0 +1,25 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Australia/Eucla) {
+ {-9223372036854775808 30928 0 LMT}
+ {-2337928528 31500 0 CWST}
+ {-1672562640 35100 1 CWST}
+ {-1665387900 31500 0 CWST}
+ {-883637100 35100 1 CWST}
+ {-876123900 31500 0 CWST}
+ {-860395500 35100 1 CWST}
+ {-844674300 31500 0 CWST}
+ {-836473500 35100 0 CWST}
+ {152039700 35100 1 CWST}
+ {162926100 31500 0 CWST}
+ {436295700 35100 1 CWST}
+ {447182100 31500 0 CWST}
+ {690311700 35100 1 CWST}
+ {699383700 31500 0 CWST}
+ {1165079700 35100 1 CWST}
+ {1174756500 31500 0 CWST}
+ {1193505300 35100 1 CWST}
+ {1206810900 31500 0 CWST}
+ {1224954900 35100 1 CWST}
+ {1238260500 31500 0 CWST}
+}
diff --git a/library/tzdata/Australia/Hobart b/library/tzdata/Australia/Hobart
new file mode 100644
index 0000000..8f27110
--- /dev/null
+++ b/library/tzdata/Australia/Hobart
@@ -0,0 +1,281 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Australia/Hobart) {
+ {-9223372036854775808 35356 0 LMT}
+ {-2345795356 36000 0 EST}
+ {-1680508800 39600 1 EST}
+ {-1669892400 39600 0 EST}
+ {-1665392400 36000 0 EST}
+ {-883641600 39600 1 EST}
+ {-876128400 36000 0 EST}
+ {-860400000 39600 1 EST}
+ {-844678800 36000 0 EST}
+ {-828345600 39600 1 EST}
+ {-813229200 36000 0 EST}
+ {-94730400 36000 0 EST}
+ {-71136000 39600 1 EST}
+ {-55411200 36000 0 EST}
+ {-37267200 39600 1 EST}
+ {-25776000 36000 0 EST}
+ {-5817600 39600 1 EST}
+ {5673600 36000 0 EST}
+ {25632000 39600 1 EST}
+ {37728000 36000 0 EST}
+ {57686400 39600 1 EST}
+ {67968000 36000 0 EST}
+ {89136000 39600 1 EST}
+ {100022400 36000 0 EST}
+ {120585600 39600 1 EST}
+ {131472000 36000 0 EST}
+ {152035200 39600 1 EST}
+ {162921600 36000 0 EST}
+ {183484800 39600 1 EST}
+ {194976000 36000 0 EST}
+ {215539200 39600 1 EST}
+ {226425600 36000 0 EST}
+ {246988800 39600 1 EST}
+ {257875200 36000 0 EST}
+ {278438400 39600 1 EST}
+ {289324800 36000 0 EST}
+ {309888000 39600 1 EST}
+ {320774400 36000 0 EST}
+ {341337600 39600 1 EST}
+ {352224000 36000 0 EST}
+ {372787200 39600 1 EST}
+ {386092800 36000 0 EST}
+ {404841600 39600 1 EST}
+ {417542400 36000 0 EST}
+ {436291200 39600 1 EST}
+ {447177600 36000 0 EST}
+ {467740800 39600 1 EST}
+ {478627200 36000 0 EST}
+ {499190400 39600 1 EST}
+ {510076800 36000 0 EST}
+ {530035200 39600 1 EST}
+ {542736000 36000 0 EST}
+ {562089600 39600 1 EST}
+ {574790400 36000 0 EST}
+ {594144000 39600 1 EST}
+ {606240000 36000 0 EST}
+ {625593600 39600 1 EST}
+ {637689600 36000 0 EST}
+ {657043200 39600 1 EST}
+ {670348800 36000 0 EST}
+ {686678400 39600 1 EST}
+ {701798400 36000 0 EST}
+ {718128000 39600 1 EST}
+ {733248000 36000 0 EST}
+ {749577600 39600 1 EST}
+ {764697600 36000 0 EST}
+ {781027200 39600 1 EST}
+ {796147200 36000 0 EST}
+ {812476800 39600 1 EST}
+ {828201600 36000 0 EST}
+ {844531200 39600 1 EST}
+ {859651200 36000 0 EST}
+ {875980800 39600 1 EST}
+ {891100800 36000 0 EST}
+ {907430400 39600 1 EST}
+ {922550400 36000 0 EST}
+ {938880000 39600 1 EST}
+ {954000000 36000 0 EST}
+ {967305600 39600 1 EST}
+ {985449600 36000 0 EST}
+ {1002384000 39600 1 EST}
+ {1017504000 36000 0 EST}
+ {1033833600 39600 1 EST}
+ {1048953600 36000 0 EST}
+ {1065283200 39600 1 EST}
+ {1080403200 36000 0 EST}
+ {1096732800 39600 1 EST}
+ {1111852800 36000 0 EST}
+ {1128182400 39600 1 EST}
+ {1143907200 36000 0 EST}
+ {1159632000 39600 1 EST}
+ {1174752000 36000 0 EST}
+ {1191686400 39600 1 EST}
+ {1207411200 36000 0 EST}
+ {1223136000 39600 1 EST}
+ {1238860800 36000 0 EST}
+ {1254585600 39600 1 EST}
+ {1270310400 36000 0 EST}
+ {1286035200 39600 1 EST}
+ {1301760000 36000 0 EST}
+ {1317484800 39600 1 EST}
+ {1333209600 36000 0 EST}
+ {1349539200 39600 1 EST}
+ {1365264000 36000 0 EST}
+ {1380988800 39600 1 EST}
+ {1396713600 36000 0 EST}
+ {1412438400 39600 1 EST}
+ {1428163200 36000 0 EST}
+ {1443888000 39600 1 EST}
+ {1459612800 36000 0 EST}
+ {1475337600 39600 1 EST}
+ {1491062400 36000 0 EST}
+ {1506787200 39600 1 EST}
+ {1522512000 36000 0 EST}
+ {1538841600 39600 1 EST}
+ {1554566400 36000 0 EST}
+ {1570291200 39600 1 EST}
+ {1586016000 36000 0 EST}
+ {1601740800 39600 1 EST}
+ {1617465600 36000 0 EST}
+ {1633190400 39600 1 EST}
+ {1648915200 36000 0 EST}
+ {1664640000 39600 1 EST}
+ {1680364800 36000 0 EST}
+ {1696089600 39600 1 EST}
+ {1712419200 36000 0 EST}
+ {1728144000 39600 1 EST}
+ {1743868800 36000 0 EST}
+ {1759593600 39600 1 EST}
+ {1775318400 36000 0 EST}
+ {1791043200 39600 1 EST}
+ {1806768000 36000 0 EST}
+ {1822492800 39600 1 EST}
+ {1838217600 36000 0 EST}
+ {1853942400 39600 1 EST}
+ {1869667200 36000 0 EST}
+ {1885996800 39600 1 EST}
+ {1901721600 36000 0 EST}
+ {1917446400 39600 1 EST}
+ {1933171200 36000 0 EST}
+ {1948896000 39600 1 EST}
+ {1964620800 36000 0 EST}
+ {1980345600 39600 1 EST}
+ {1996070400 36000 0 EST}
+ {2011795200 39600 1 EST}
+ {2027520000 36000 0 EST}
+ {2043244800 39600 1 EST}
+ {2058969600 36000 0 EST}
+ {2075299200 39600 1 EST}
+ {2091024000 36000 0 EST}
+ {2106748800 39600 1 EST}
+ {2122473600 36000 0 EST}
+ {2138198400 39600 1 EST}
+ {2153923200 36000 0 EST}
+ {2169648000 39600 1 EST}
+ {2185372800 36000 0 EST}
+ {2201097600 39600 1 EST}
+ {2216822400 36000 0 EST}
+ {2233152000 39600 1 EST}
+ {2248876800 36000 0 EST}
+ {2264601600 39600 1 EST}
+ {2280326400 36000 0 EST}
+ {2296051200 39600 1 EST}
+ {2311776000 36000 0 EST}
+ {2327500800 39600 1 EST}
+ {2343225600 36000 0 EST}
+ {2358950400 39600 1 EST}
+ {2374675200 36000 0 EST}
+ {2390400000 39600 1 EST}
+ {2406124800 36000 0 EST}
+ {2422454400 39600 1 EST}
+ {2438179200 36000 0 EST}
+ {2453904000 39600 1 EST}
+ {2469628800 36000 0 EST}
+ {2485353600 39600 1 EST}
+ {2501078400 36000 0 EST}
+ {2516803200 39600 1 EST}
+ {2532528000 36000 0 EST}
+ {2548252800 39600 1 EST}
+ {2563977600 36000 0 EST}
+ {2579702400 39600 1 EST}
+ {2596032000 36000 0 EST}
+ {2611756800 39600 1 EST}
+ {2627481600 36000 0 EST}
+ {2643206400 39600 1 EST}
+ {2658931200 36000 0 EST}
+ {2674656000 39600 1 EST}
+ {2690380800 36000 0 EST}
+ {2706105600 39600 1 EST}
+ {2721830400 36000 0 EST}
+ {2737555200 39600 1 EST}
+ {2753280000 36000 0 EST}
+ {2769609600 39600 1 EST}
+ {2785334400 36000 0 EST}
+ {2801059200 39600 1 EST}
+ {2816784000 36000 0 EST}
+ {2832508800 39600 1 EST}
+ {2848233600 36000 0 EST}
+ {2863958400 39600 1 EST}
+ {2879683200 36000 0 EST}
+ {2895408000 39600 1 EST}
+ {2911132800 36000 0 EST}
+ {2926857600 39600 1 EST}
+ {2942582400 36000 0 EST}
+ {2958912000 39600 1 EST}
+ {2974636800 36000 0 EST}
+ {2990361600 39600 1 EST}
+ {3006086400 36000 0 EST}
+ {3021811200 39600 1 EST}
+ {3037536000 36000 0 EST}
+ {3053260800 39600 1 EST}
+ {3068985600 36000 0 EST}
+ {3084710400 39600 1 EST}
+ {3100435200 36000 0 EST}
+ {3116764800 39600 1 EST}
+ {3132489600 36000 0 EST}
+ {3148214400 39600 1 EST}
+ {3163939200 36000 0 EST}
+ {3179664000 39600 1 EST}
+ {3195388800 36000 0 EST}
+ {3211113600 39600 1 EST}
+ {3226838400 36000 0 EST}
+ {3242563200 39600 1 EST}
+ {3258288000 36000 0 EST}
+ {3274012800 39600 1 EST}
+ {3289737600 36000 0 EST}
+ {3306067200 39600 1 EST}
+ {3321792000 36000 0 EST}
+ {3337516800 39600 1 EST}
+ {3353241600 36000 0 EST}
+ {3368966400 39600 1 EST}
+ {3384691200 36000 0 EST}
+ {3400416000 39600 1 EST}
+ {3416140800 36000 0 EST}
+ {3431865600 39600 1 EST}
+ {3447590400 36000 0 EST}
+ {3463315200 39600 1 EST}
+ {3479644800 36000 0 EST}
+ {3495369600 39600 1 EST}
+ {3511094400 36000 0 EST}
+ {3526819200 39600 1 EST}
+ {3542544000 36000 0 EST}
+ {3558268800 39600 1 EST}
+ {3573993600 36000 0 EST}
+ {3589718400 39600 1 EST}
+ {3605443200 36000 0 EST}
+ {3621168000 39600 1 EST}
+ {3636892800 36000 0 EST}
+ {3653222400 39600 1 EST}
+ {3668947200 36000 0 EST}
+ {3684672000 39600 1 EST}
+ {3700396800 36000 0 EST}
+ {3716121600 39600 1 EST}
+ {3731846400 36000 0 EST}
+ {3747571200 39600 1 EST}
+ {3763296000 36000 0 EST}
+ {3779020800 39600 1 EST}
+ {3794745600 36000 0 EST}
+ {3810470400 39600 1 EST}
+ {3826195200 36000 0 EST}
+ {3842524800 39600 1 EST}
+ {3858249600 36000 0 EST}
+ {3873974400 39600 1 EST}
+ {3889699200 36000 0 EST}
+ {3905424000 39600 1 EST}
+ {3921148800 36000 0 EST}
+ {3936873600 39600 1 EST}
+ {3952598400 36000 0 EST}
+ {3968323200 39600 1 EST}
+ {3984048000 36000 0 EST}
+ {4000377600 39600 1 EST}
+ {4016102400 36000 0 EST}
+ {4031827200 39600 1 EST}
+ {4047552000 36000 0 EST}
+ {4063276800 39600 1 EST}
+ {4079001600 36000 0 EST}
+ {4094726400 39600 1 EST}
+}
diff --git a/library/tzdata/Australia/LHI b/library/tzdata/Australia/LHI
new file mode 100644
index 0000000..ddc79ce
--- /dev/null
+++ b/library/tzdata/Australia/LHI
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Australia/Lord_Howe)]} {
+ LoadTimeZoneFile Australia/Lord_Howe
+}
+set TZData(:Australia/LHI) $TZData(:Australia/Lord_Howe)
diff --git a/library/tzdata/Australia/Lindeman b/library/tzdata/Australia/Lindeman
new file mode 100644
index 0000000..de11c35
--- /dev/null
+++ b/library/tzdata/Australia/Lindeman
@@ -0,0 +1,28 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Australia/Lindeman) {
+ {-9223372036854775808 35756 0 LMT}
+ {-2366790956 36000 0 EST}
+ {-1672567140 39600 1 EST}
+ {-1665392400 36000 0 EST}
+ {-883641600 39600 1 EST}
+ {-876128400 36000 0 EST}
+ {-860400000 39600 1 EST}
+ {-844678800 36000 0 EST}
+ {-828345600 39600 1 EST}
+ {-813229200 36000 0 EST}
+ {31500000 36000 0 EST}
+ {57686400 39600 1 EST}
+ {67968000 36000 0 EST}
+ {625593600 39600 1 EST}
+ {636480000 36000 0 EST}
+ {657043200 39600 1 EST}
+ {667929600 36000 0 EST}
+ {688492800 39600 1 EST}
+ {699379200 36000 0 EST}
+ {709912800 36000 0 EST}
+ {719942400 39600 1 EST}
+ {731433600 36000 0 EST}
+ {751996800 39600 1 EST}
+ {762883200 36000 0 EST}
+}
diff --git a/library/tzdata/Australia/Lord_Howe b/library/tzdata/Australia/Lord_Howe
new file mode 100644
index 0000000..da094e5
--- /dev/null
+++ b/library/tzdata/Australia/Lord_Howe
@@ -0,0 +1,244 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Australia/Lord_Howe) {
+ {-9223372036854775808 38180 0 LMT}
+ {-2364114980 36000 0 EST}
+ {352216800 37800 0 LHST}
+ {372785400 41400 1 LHST}
+ {384273000 37800 0 LHST}
+ {404839800 41400 1 LHST}
+ {415722600 37800 0 LHST}
+ {436289400 41400 1 LHST}
+ {447172200 37800 0 LHST}
+ {467739000 41400 1 LHST}
+ {478621800 37800 0 LHST}
+ {499188600 39600 1 LHST}
+ {511282800 37800 0 LHST}
+ {530033400 39600 1 LHST}
+ {542732400 37800 0 LHST}
+ {562087800 39600 1 LHST}
+ {574786800 37800 0 LHST}
+ {594142200 39600 1 LHST}
+ {606236400 37800 0 LHST}
+ {625591800 39600 1 LHST}
+ {636476400 37800 0 LHST}
+ {657041400 39600 1 LHST}
+ {667926000 37800 0 LHST}
+ {688491000 39600 1 LHST}
+ {699375600 37800 0 LHST}
+ {719940600 39600 1 LHST}
+ {731430000 37800 0 LHST}
+ {751995000 39600 1 LHST}
+ {762879600 37800 0 LHST}
+ {783444600 39600 1 LHST}
+ {794329200 37800 0 LHST}
+ {814894200 39600 1 LHST}
+ {828198000 37800 0 LHST}
+ {846343800 39600 1 LHST}
+ {859647600 37800 0 LHST}
+ {877793400 39600 1 LHST}
+ {891097200 37800 0 LHST}
+ {909243000 39600 1 LHST}
+ {922546800 37800 0 LHST}
+ {941297400 39600 1 LHST}
+ {953996400 37800 0 LHST}
+ {967303800 39600 1 LHST}
+ {985446000 37800 0 LHST}
+ {1004196600 39600 1 LHST}
+ {1017500400 37800 0 LHST}
+ {1035646200 39600 1 LHST}
+ {1048950000 37800 0 LHST}
+ {1067095800 39600 1 LHST}
+ {1080399600 37800 0 LHST}
+ {1099150200 39600 1 LHST}
+ {1111849200 37800 0 LHST}
+ {1130599800 39600 1 LHST}
+ {1143903600 37800 0 LHST}
+ {1162049400 39600 1 LHST}
+ {1174748400 37800 0 LHST}
+ {1193499000 39600 1 LHST}
+ {1207407600 37800 0 LHST}
+ {1223134200 39600 1 LHST}
+ {1238857200 37800 0 LHST}
+ {1254583800 39600 1 LHST}
+ {1270306800 37800 0 LHST}
+ {1286033400 39600 1 LHST}
+ {1301756400 37800 0 LHST}
+ {1317483000 39600 1 LHST}
+ {1333206000 37800 0 LHST}
+ {1349537400 39600 1 LHST}
+ {1365260400 37800 0 LHST}
+ {1380987000 39600 1 LHST}
+ {1396710000 37800 0 LHST}
+ {1412436600 39600 1 LHST}
+ {1428159600 37800 0 LHST}
+ {1443886200 39600 1 LHST}
+ {1459609200 37800 0 LHST}
+ {1475335800 39600 1 LHST}
+ {1491058800 37800 0 LHST}
+ {1506785400 39600 1 LHST}
+ {1522508400 37800 0 LHST}
+ {1538839800 39600 1 LHST}
+ {1554562800 37800 0 LHST}
+ {1570289400 39600 1 LHST}
+ {1586012400 37800 0 LHST}
+ {1601739000 39600 1 LHST}
+ {1617462000 37800 0 LHST}
+ {1633188600 39600 1 LHST}
+ {1648911600 37800 0 LHST}
+ {1664638200 39600 1 LHST}
+ {1680361200 37800 0 LHST}
+ {1696087800 39600 1 LHST}
+ {1712415600 37800 0 LHST}
+ {1728142200 39600 1 LHST}
+ {1743865200 37800 0 LHST}
+ {1759591800 39600 1 LHST}
+ {1775314800 37800 0 LHST}
+ {1791041400 39600 1 LHST}
+ {1806764400 37800 0 LHST}
+ {1822491000 39600 1 LHST}
+ {1838214000 37800 0 LHST}
+ {1853940600 39600 1 LHST}
+ {1869663600 37800 0 LHST}
+ {1885995000 39600 1 LHST}
+ {1901718000 37800 0 LHST}
+ {1917444600 39600 1 LHST}
+ {1933167600 37800 0 LHST}
+ {1948894200 39600 1 LHST}
+ {1964617200 37800 0 LHST}
+ {1980343800 39600 1 LHST}
+ {1996066800 37800 0 LHST}
+ {2011793400 39600 1 LHST}
+ {2027516400 37800 0 LHST}
+ {2043243000 39600 1 LHST}
+ {2058966000 37800 0 LHST}
+ {2075297400 39600 1 LHST}
+ {2091020400 37800 0 LHST}
+ {2106747000 39600 1 LHST}
+ {2122470000 37800 0 LHST}
+ {2138196600 39600 1 LHST}
+ {2153919600 37800 0 LHST}
+ {2169646200 39600 1 LHST}
+ {2185369200 37800 0 LHST}
+ {2201095800 39600 1 LHST}
+ {2216818800 37800 0 LHST}
+ {2233150200 39600 1 LHST}
+ {2248873200 37800 0 LHST}
+ {2264599800 39600 1 LHST}
+ {2280322800 37800 0 LHST}
+ {2296049400 39600 1 LHST}
+ {2311772400 37800 0 LHST}
+ {2327499000 39600 1 LHST}
+ {2343222000 37800 0 LHST}
+ {2358948600 39600 1 LHST}
+ {2374671600 37800 0 LHST}
+ {2390398200 39600 1 LHST}
+ {2406121200 37800 0 LHST}
+ {2422452600 39600 1 LHST}
+ {2438175600 37800 0 LHST}
+ {2453902200 39600 1 LHST}
+ {2469625200 37800 0 LHST}
+ {2485351800 39600 1 LHST}
+ {2501074800 37800 0 LHST}
+ {2516801400 39600 1 LHST}
+ {2532524400 37800 0 LHST}
+ {2548251000 39600 1 LHST}
+ {2563974000 37800 0 LHST}
+ {2579700600 39600 1 LHST}
+ {2596028400 37800 0 LHST}
+ {2611755000 39600 1 LHST}
+ {2627478000 37800 0 LHST}
+ {2643204600 39600 1 LHST}
+ {2658927600 37800 0 LHST}
+ {2674654200 39600 1 LHST}
+ {2690377200 37800 0 LHST}
+ {2706103800 39600 1 LHST}
+ {2721826800 37800 0 LHST}
+ {2737553400 39600 1 LHST}
+ {2753276400 37800 0 LHST}
+ {2769607800 39600 1 LHST}
+ {2785330800 37800 0 LHST}
+ {2801057400 39600 1 LHST}
+ {2816780400 37800 0 LHST}
+ {2832507000 39600 1 LHST}
+ {2848230000 37800 0 LHST}
+ {2863956600 39600 1 LHST}
+ {2879679600 37800 0 LHST}
+ {2895406200 39600 1 LHST}
+ {2911129200 37800 0 LHST}
+ {2926855800 39600 1 LHST}
+ {2942578800 37800 0 LHST}
+ {2958910200 39600 1 LHST}
+ {2974633200 37800 0 LHST}
+ {2990359800 39600 1 LHST}
+ {3006082800 37800 0 LHST}
+ {3021809400 39600 1 LHST}
+ {3037532400 37800 0 LHST}
+ {3053259000 39600 1 LHST}
+ {3068982000 37800 0 LHST}
+ {3084708600 39600 1 LHST}
+ {3100431600 37800 0 LHST}
+ {3116763000 39600 1 LHST}
+ {3132486000 37800 0 LHST}
+ {3148212600 39600 1 LHST}
+ {3163935600 37800 0 LHST}
+ {3179662200 39600 1 LHST}
+ {3195385200 37800 0 LHST}
+ {3211111800 39600 1 LHST}
+ {3226834800 37800 0 LHST}
+ {3242561400 39600 1 LHST}
+ {3258284400 37800 0 LHST}
+ {3274011000 39600 1 LHST}
+ {3289734000 37800 0 LHST}
+ {3306065400 39600 1 LHST}
+ {3321788400 37800 0 LHST}
+ {3337515000 39600 1 LHST}
+ {3353238000 37800 0 LHST}
+ {3368964600 39600 1 LHST}
+ {3384687600 37800 0 LHST}
+ {3400414200 39600 1 LHST}
+ {3416137200 37800 0 LHST}
+ {3431863800 39600 1 LHST}
+ {3447586800 37800 0 LHST}
+ {3463313400 39600 1 LHST}
+ {3479641200 37800 0 LHST}
+ {3495367800 39600 1 LHST}
+ {3511090800 37800 0 LHST}
+ {3526817400 39600 1 LHST}
+ {3542540400 37800 0 LHST}
+ {3558267000 39600 1 LHST}
+ {3573990000 37800 0 LHST}
+ {3589716600 39600 1 LHST}
+ {3605439600 37800 0 LHST}
+ {3621166200 39600 1 LHST}
+ {3636889200 37800 0 LHST}
+ {3653220600 39600 1 LHST}
+ {3668943600 37800 0 LHST}
+ {3684670200 39600 1 LHST}
+ {3700393200 37800 0 LHST}
+ {3716119800 39600 1 LHST}
+ {3731842800 37800 0 LHST}
+ {3747569400 39600 1 LHST}
+ {3763292400 37800 0 LHST}
+ {3779019000 39600 1 LHST}
+ {3794742000 37800 0 LHST}
+ {3810468600 39600 1 LHST}
+ {3826191600 37800 0 LHST}
+ {3842523000 39600 1 LHST}
+ {3858246000 37800 0 LHST}
+ {3873972600 39600 1 LHST}
+ {3889695600 37800 0 LHST}
+ {3905422200 39600 1 LHST}
+ {3921145200 37800 0 LHST}
+ {3936871800 39600 1 LHST}
+ {3952594800 37800 0 LHST}
+ {3968321400 39600 1 LHST}
+ {3984044400 37800 0 LHST}
+ {4000375800 39600 1 LHST}
+ {4016098800 37800 0 LHST}
+ {4031825400 39600 1 LHST}
+ {4047548400 37800 0 LHST}
+ {4063275000 39600 1 LHST}
+ {4078998000 37800 0 LHST}
+ {4094724600 39600 1 LHST}
+}
diff --git a/library/tzdata/Australia/Melbourne b/library/tzdata/Australia/Melbourne
new file mode 100644
index 0000000..907b8b9
--- /dev/null
+++ b/library/tzdata/Australia/Melbourne
@@ -0,0 +1,272 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Australia/Melbourne) {
+ {-9223372036854775808 34792 0 LMT}
+ {-2364111592 36000 0 EST}
+ {-1672567140 39600 1 EST}
+ {-1665392400 36000 0 EST}
+ {-883641600 39600 1 EST}
+ {-876128400 36000 0 EST}
+ {-860400000 39600 1 EST}
+ {-844678800 36000 0 EST}
+ {-828345600 39600 1 EST}
+ {-813229200 36000 0 EST}
+ {31500000 36000 0 EST}
+ {57686400 39600 1 EST}
+ {67968000 36000 0 EST}
+ {89136000 39600 1 EST}
+ {100022400 36000 0 EST}
+ {120585600 39600 1 EST}
+ {131472000 36000 0 EST}
+ {152035200 39600 1 EST}
+ {162921600 36000 0 EST}
+ {183484800 39600 1 EST}
+ {194976000 36000 0 EST}
+ {215539200 39600 1 EST}
+ {226425600 36000 0 EST}
+ {246988800 39600 1 EST}
+ {257875200 36000 0 EST}
+ {278438400 39600 1 EST}
+ {289324800 36000 0 EST}
+ {309888000 39600 1 EST}
+ {320774400 36000 0 EST}
+ {341337600 39600 1 EST}
+ {352224000 36000 0 EST}
+ {372787200 39600 1 EST}
+ {384278400 36000 0 EST}
+ {404841600 39600 1 EST}
+ {415728000 36000 0 EST}
+ {436291200 39600 1 EST}
+ {447177600 36000 0 EST}
+ {467740800 39600 1 EST}
+ {478627200 36000 0 EST}
+ {499190400 39600 1 EST}
+ {511286400 36000 0 EST}
+ {530035200 39600 1 EST}
+ {542736000 36000 0 EST}
+ {561484800 39600 1 EST}
+ {574790400 36000 0 EST}
+ {594144000 39600 1 EST}
+ {606240000 36000 0 EST}
+ {625593600 39600 1 EST}
+ {637689600 36000 0 EST}
+ {657043200 39600 1 EST}
+ {667929600 36000 0 EST}
+ {688492800 39600 1 EST}
+ {699379200 36000 0 EST}
+ {719942400 39600 1 EST}
+ {731433600 36000 0 EST}
+ {751996800 39600 1 EST}
+ {762883200 36000 0 EST}
+ {783446400 39600 1 EST}
+ {796147200 36000 0 EST}
+ {814896000 39600 1 EST}
+ {828201600 36000 0 EST}
+ {846345600 39600 1 EST}
+ {859651200 36000 0 EST}
+ {877795200 39600 1 EST}
+ {891100800 36000 0 EST}
+ {909244800 39600 1 EST}
+ {922550400 36000 0 EST}
+ {941299200 39600 1 EST}
+ {954000000 36000 0 EST}
+ {967305600 39600 1 EST}
+ {985449600 36000 0 EST}
+ {1004198400 39600 1 EST}
+ {1017504000 36000 0 EST}
+ {1035648000 39600 1 EST}
+ {1048953600 36000 0 EST}
+ {1067097600 39600 1 EST}
+ {1080403200 36000 0 EST}
+ {1099152000 39600 1 EST}
+ {1111852800 36000 0 EST}
+ {1130601600 39600 1 EST}
+ {1143907200 36000 0 EST}
+ {1162051200 39600 1 EST}
+ {1174752000 36000 0 EST}
+ {1193500800 39600 1 EST}
+ {1207411200 36000 0 EST}
+ {1223136000 39600 1 EST}
+ {1238860800 36000 0 EST}
+ {1254585600 39600 1 EST}
+ {1270310400 36000 0 EST}
+ {1286035200 39600 1 EST}
+ {1301760000 36000 0 EST}
+ {1317484800 39600 1 EST}
+ {1333209600 36000 0 EST}
+ {1349539200 39600 1 EST}
+ {1365264000 36000 0 EST}
+ {1380988800 39600 1 EST}
+ {1396713600 36000 0 EST}
+ {1412438400 39600 1 EST}
+ {1428163200 36000 0 EST}
+ {1443888000 39600 1 EST}
+ {1459612800 36000 0 EST}
+ {1475337600 39600 1 EST}
+ {1491062400 36000 0 EST}
+ {1506787200 39600 1 EST}
+ {1522512000 36000 0 EST}
+ {1538841600 39600 1 EST}
+ {1554566400 36000 0 EST}
+ {1570291200 39600 1 EST}
+ {1586016000 36000 0 EST}
+ {1601740800 39600 1 EST}
+ {1617465600 36000 0 EST}
+ {1633190400 39600 1 EST}
+ {1648915200 36000 0 EST}
+ {1664640000 39600 1 EST}
+ {1680364800 36000 0 EST}
+ {1696089600 39600 1 EST}
+ {1712419200 36000 0 EST}
+ {1728144000 39600 1 EST}
+ {1743868800 36000 0 EST}
+ {1759593600 39600 1 EST}
+ {1775318400 36000 0 EST}
+ {1791043200 39600 1 EST}
+ {1806768000 36000 0 EST}
+ {1822492800 39600 1 EST}
+ {1838217600 36000 0 EST}
+ {1853942400 39600 1 EST}
+ {1869667200 36000 0 EST}
+ {1885996800 39600 1 EST}
+ {1901721600 36000 0 EST}
+ {1917446400 39600 1 EST}
+ {1933171200 36000 0 EST}
+ {1948896000 39600 1 EST}
+ {1964620800 36000 0 EST}
+ {1980345600 39600 1 EST}
+ {1996070400 36000 0 EST}
+ {2011795200 39600 1 EST}
+ {2027520000 36000 0 EST}
+ {2043244800 39600 1 EST}
+ {2058969600 36000 0 EST}
+ {2075299200 39600 1 EST}
+ {2091024000 36000 0 EST}
+ {2106748800 39600 1 EST}
+ {2122473600 36000 0 EST}
+ {2138198400 39600 1 EST}
+ {2153923200 36000 0 EST}
+ {2169648000 39600 1 EST}
+ {2185372800 36000 0 EST}
+ {2201097600 39600 1 EST}
+ {2216822400 36000 0 EST}
+ {2233152000 39600 1 EST}
+ {2248876800 36000 0 EST}
+ {2264601600 39600 1 EST}
+ {2280326400 36000 0 EST}
+ {2296051200 39600 1 EST}
+ {2311776000 36000 0 EST}
+ {2327500800 39600 1 EST}
+ {2343225600 36000 0 EST}
+ {2358950400 39600 1 EST}
+ {2374675200 36000 0 EST}
+ {2390400000 39600 1 EST}
+ {2406124800 36000 0 EST}
+ {2422454400 39600 1 EST}
+ {2438179200 36000 0 EST}
+ {2453904000 39600 1 EST}
+ {2469628800 36000 0 EST}
+ {2485353600 39600 1 EST}
+ {2501078400 36000 0 EST}
+ {2516803200 39600 1 EST}
+ {2532528000 36000 0 EST}
+ {2548252800 39600 1 EST}
+ {2563977600 36000 0 EST}
+ {2579702400 39600 1 EST}
+ {2596032000 36000 0 EST}
+ {2611756800 39600 1 EST}
+ {2627481600 36000 0 EST}
+ {2643206400 39600 1 EST}
+ {2658931200 36000 0 EST}
+ {2674656000 39600 1 EST}
+ {2690380800 36000 0 EST}
+ {2706105600 39600 1 EST}
+ {2721830400 36000 0 EST}
+ {2737555200 39600 1 EST}
+ {2753280000 36000 0 EST}
+ {2769609600 39600 1 EST}
+ {2785334400 36000 0 EST}
+ {2801059200 39600 1 EST}
+ {2816784000 36000 0 EST}
+ {2832508800 39600 1 EST}
+ {2848233600 36000 0 EST}
+ {2863958400 39600 1 EST}
+ {2879683200 36000 0 EST}
+ {2895408000 39600 1 EST}
+ {2911132800 36000 0 EST}
+ {2926857600 39600 1 EST}
+ {2942582400 36000 0 EST}
+ {2958912000 39600 1 EST}
+ {2974636800 36000 0 EST}
+ {2990361600 39600 1 EST}
+ {3006086400 36000 0 EST}
+ {3021811200 39600 1 EST}
+ {3037536000 36000 0 EST}
+ {3053260800 39600 1 EST}
+ {3068985600 36000 0 EST}
+ {3084710400 39600 1 EST}
+ {3100435200 36000 0 EST}
+ {3116764800 39600 1 EST}
+ {3132489600 36000 0 EST}
+ {3148214400 39600 1 EST}
+ {3163939200 36000 0 EST}
+ {3179664000 39600 1 EST}
+ {3195388800 36000 0 EST}
+ {3211113600 39600 1 EST}
+ {3226838400 36000 0 EST}
+ {3242563200 39600 1 EST}
+ {3258288000 36000 0 EST}
+ {3274012800 39600 1 EST}
+ {3289737600 36000 0 EST}
+ {3306067200 39600 1 EST}
+ {3321792000 36000 0 EST}
+ {3337516800 39600 1 EST}
+ {3353241600 36000 0 EST}
+ {3368966400 39600 1 EST}
+ {3384691200 36000 0 EST}
+ {3400416000 39600 1 EST}
+ {3416140800 36000 0 EST}
+ {3431865600 39600 1 EST}
+ {3447590400 36000 0 EST}
+ {3463315200 39600 1 EST}
+ {3479644800 36000 0 EST}
+ {3495369600 39600 1 EST}
+ {3511094400 36000 0 EST}
+ {3526819200 39600 1 EST}
+ {3542544000 36000 0 EST}
+ {3558268800 39600 1 EST}
+ {3573993600 36000 0 EST}
+ {3589718400 39600 1 EST}
+ {3605443200 36000 0 EST}
+ {3621168000 39600 1 EST}
+ {3636892800 36000 0 EST}
+ {3653222400 39600 1 EST}
+ {3668947200 36000 0 EST}
+ {3684672000 39600 1 EST}
+ {3700396800 36000 0 EST}
+ {3716121600 39600 1 EST}
+ {3731846400 36000 0 EST}
+ {3747571200 39600 1 EST}
+ {3763296000 36000 0 EST}
+ {3779020800 39600 1 EST}
+ {3794745600 36000 0 EST}
+ {3810470400 39600 1 EST}
+ {3826195200 36000 0 EST}
+ {3842524800 39600 1 EST}
+ {3858249600 36000 0 EST}
+ {3873974400 39600 1 EST}
+ {3889699200 36000 0 EST}
+ {3905424000 39600 1 EST}
+ {3921148800 36000 0 EST}
+ {3936873600 39600 1 EST}
+ {3952598400 36000 0 EST}
+ {3968323200 39600 1 EST}
+ {3984048000 36000 0 EST}
+ {4000377600 39600 1 EST}
+ {4016102400 36000 0 EST}
+ {4031827200 39600 1 EST}
+ {4047552000 36000 0 EST}
+ {4063276800 39600 1 EST}
+ {4079001600 36000 0 EST}
+ {4094726400 39600 1 EST}
+}
diff --git a/library/tzdata/Australia/NSW b/library/tzdata/Australia/NSW
new file mode 100644
index 0000000..905bdfe
--- /dev/null
+++ b/library/tzdata/Australia/NSW
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Australia/Sydney)]} {
+ LoadTimeZoneFile Australia/Sydney
+}
+set TZData(:Australia/NSW) $TZData(:Australia/Sydney)
diff --git a/library/tzdata/Australia/North b/library/tzdata/Australia/North
new file mode 100644
index 0000000..950c88c
--- /dev/null
+++ b/library/tzdata/Australia/North
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Australia/Darwin)]} {
+ LoadTimeZoneFile Australia/Darwin
+}
+set TZData(:Australia/North) $TZData(:Australia/Darwin)
diff --git a/library/tzdata/Australia/Perth b/library/tzdata/Australia/Perth
new file mode 100644
index 0000000..5d8f116
--- /dev/null
+++ b/library/tzdata/Australia/Perth
@@ -0,0 +1,25 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Australia/Perth) {
+ {-9223372036854775808 27804 0 LMT}
+ {-2337925404 28800 0 WST}
+ {-1672559940 32400 1 WST}
+ {-1665385200 28800 0 WST}
+ {-883634400 32400 1 WST}
+ {-876121200 28800 0 WST}
+ {-860392800 32400 1 WST}
+ {-844671600 28800 0 WST}
+ {-836470800 32400 0 WST}
+ {152042400 32400 1 WST}
+ {162928800 28800 0 WST}
+ {436298400 32400 1 WST}
+ {447184800 28800 0 WST}
+ {690314400 32400 1 WST}
+ {699386400 28800 0 WST}
+ {1165082400 32400 1 WST}
+ {1174759200 28800 0 WST}
+ {1193508000 32400 1 WST}
+ {1206813600 28800 0 WST}
+ {1224957600 32400 1 WST}
+ {1238263200 28800 0 WST}
+}
diff --git a/library/tzdata/Australia/Queensland b/library/tzdata/Australia/Queensland
new file mode 100644
index 0000000..6246e92
--- /dev/null
+++ b/library/tzdata/Australia/Queensland
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Australia/Brisbane)]} {
+ LoadTimeZoneFile Australia/Brisbane
+}
+set TZData(:Australia/Queensland) $TZData(:Australia/Brisbane)
diff --git a/library/tzdata/Australia/South b/library/tzdata/Australia/South
new file mode 100644
index 0000000..9c7dd95
--- /dev/null
+++ b/library/tzdata/Australia/South
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Australia/Adelaide)]} {
+ LoadTimeZoneFile Australia/Adelaide
+}
+set TZData(:Australia/South) $TZData(:Australia/Adelaide)
diff --git a/library/tzdata/Australia/Sydney b/library/tzdata/Australia/Sydney
new file mode 100644
index 0000000..84b1d14
--- /dev/null
+++ b/library/tzdata/Australia/Sydney
@@ -0,0 +1,272 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Australia/Sydney) {
+ {-9223372036854775808 36292 0 LMT}
+ {-2364113092 36000 0 EST}
+ {-1672567140 39600 1 EST}
+ {-1665392400 36000 0 EST}
+ {-883641600 39600 1 EST}
+ {-876128400 36000 0 EST}
+ {-860400000 39600 1 EST}
+ {-844678800 36000 0 EST}
+ {-828345600 39600 1 EST}
+ {-813229200 36000 0 EST}
+ {31500000 36000 0 EST}
+ {57686400 39600 1 EST}
+ {67968000 36000 0 EST}
+ {89136000 39600 1 EST}
+ {100022400 36000 0 EST}
+ {120585600 39600 1 EST}
+ {131472000 36000 0 EST}
+ {152035200 39600 1 EST}
+ {162921600 36000 0 EST}
+ {183484800 39600 1 EST}
+ {194976000 36000 0 EST}
+ {215539200 39600 1 EST}
+ {226425600 36000 0 EST}
+ {246988800 39600 1 EST}
+ {257875200 36000 0 EST}
+ {278438400 39600 1 EST}
+ {289324800 36000 0 EST}
+ {309888000 39600 1 EST}
+ {320774400 36000 0 EST}
+ {341337600 39600 1 EST}
+ {352224000 36000 0 EST}
+ {372787200 39600 1 EST}
+ {386697600 36000 0 EST}
+ {404841600 39600 1 EST}
+ {415728000 36000 0 EST}
+ {436291200 39600 1 EST}
+ {447177600 36000 0 EST}
+ {467740800 39600 1 EST}
+ {478627200 36000 0 EST}
+ {499190400 39600 1 EST}
+ {511286400 36000 0 EST}
+ {530035200 39600 1 EST}
+ {542736000 36000 0 EST}
+ {562089600 39600 1 EST}
+ {574790400 36000 0 EST}
+ {594144000 39600 1 EST}
+ {606240000 36000 0 EST}
+ {625593600 39600 1 EST}
+ {636480000 36000 0 EST}
+ {657043200 39600 1 EST}
+ {667929600 36000 0 EST}
+ {688492800 39600 1 EST}
+ {699379200 36000 0 EST}
+ {719942400 39600 1 EST}
+ {731433600 36000 0 EST}
+ {751996800 39600 1 EST}
+ {762883200 36000 0 EST}
+ {783446400 39600 1 EST}
+ {794332800 36000 0 EST}
+ {814896000 39600 1 EST}
+ {828201600 36000 0 EST}
+ {846345600 39600 1 EST}
+ {859651200 36000 0 EST}
+ {877795200 39600 1 EST}
+ {891100800 36000 0 EST}
+ {909244800 39600 1 EST}
+ {922550400 36000 0 EST}
+ {941299200 39600 1 EST}
+ {954000000 36000 0 EST}
+ {967305600 39600 1 EST}
+ {985449600 36000 0 EST}
+ {1004198400 39600 1 EST}
+ {1017504000 36000 0 EST}
+ {1035648000 39600 1 EST}
+ {1048953600 36000 0 EST}
+ {1067097600 39600 1 EST}
+ {1080403200 36000 0 EST}
+ {1099152000 39600 1 EST}
+ {1111852800 36000 0 EST}
+ {1130601600 39600 1 EST}
+ {1143907200 36000 0 EST}
+ {1162051200 39600 1 EST}
+ {1174752000 36000 0 EST}
+ {1193500800 39600 1 EST}
+ {1207411200 36000 0 EST}
+ {1223136000 39600 1 EST}
+ {1238860800 36000 0 EST}
+ {1254585600 39600 1 EST}
+ {1270310400 36000 0 EST}
+ {1286035200 39600 1 EST}
+ {1301760000 36000 0 EST}
+ {1317484800 39600 1 EST}
+ {1333209600 36000 0 EST}
+ {1349539200 39600 1 EST}
+ {1365264000 36000 0 EST}
+ {1380988800 39600 1 EST}
+ {1396713600 36000 0 EST}
+ {1412438400 39600 1 EST}
+ {1428163200 36000 0 EST}
+ {1443888000 39600 1 EST}
+ {1459612800 36000 0 EST}
+ {1475337600 39600 1 EST}
+ {1491062400 36000 0 EST}
+ {1506787200 39600 1 EST}
+ {1522512000 36000 0 EST}
+ {1538841600 39600 1 EST}
+ {1554566400 36000 0 EST}
+ {1570291200 39600 1 EST}
+ {1586016000 36000 0 EST}
+ {1601740800 39600 1 EST}
+ {1617465600 36000 0 EST}
+ {1633190400 39600 1 EST}
+ {1648915200 36000 0 EST}
+ {1664640000 39600 1 EST}
+ {1680364800 36000 0 EST}
+ {1696089600 39600 1 EST}
+ {1712419200 36000 0 EST}
+ {1728144000 39600 1 EST}
+ {1743868800 36000 0 EST}
+ {1759593600 39600 1 EST}
+ {1775318400 36000 0 EST}
+ {1791043200 39600 1 EST}
+ {1806768000 36000 0 EST}
+ {1822492800 39600 1 EST}
+ {1838217600 36000 0 EST}
+ {1853942400 39600 1 EST}
+ {1869667200 36000 0 EST}
+ {1885996800 39600 1 EST}
+ {1901721600 36000 0 EST}
+ {1917446400 39600 1 EST}
+ {1933171200 36000 0 EST}
+ {1948896000 39600 1 EST}
+ {1964620800 36000 0 EST}
+ {1980345600 39600 1 EST}
+ {1996070400 36000 0 EST}
+ {2011795200 39600 1 EST}
+ {2027520000 36000 0 EST}
+ {2043244800 39600 1 EST}
+ {2058969600 36000 0 EST}
+ {2075299200 39600 1 EST}
+ {2091024000 36000 0 EST}
+ {2106748800 39600 1 EST}
+ {2122473600 36000 0 EST}
+ {2138198400 39600 1 EST}
+ {2153923200 36000 0 EST}
+ {2169648000 39600 1 EST}
+ {2185372800 36000 0 EST}
+ {2201097600 39600 1 EST}
+ {2216822400 36000 0 EST}
+ {2233152000 39600 1 EST}
+ {2248876800 36000 0 EST}
+ {2264601600 39600 1 EST}
+ {2280326400 36000 0 EST}
+ {2296051200 39600 1 EST}
+ {2311776000 36000 0 EST}
+ {2327500800 39600 1 EST}
+ {2343225600 36000 0 EST}
+ {2358950400 39600 1 EST}
+ {2374675200 36000 0 EST}
+ {2390400000 39600 1 EST}
+ {2406124800 36000 0 EST}
+ {2422454400 39600 1 EST}
+ {2438179200 36000 0 EST}
+ {2453904000 39600 1 EST}
+ {2469628800 36000 0 EST}
+ {2485353600 39600 1 EST}
+ {2501078400 36000 0 EST}
+ {2516803200 39600 1 EST}
+ {2532528000 36000 0 EST}
+ {2548252800 39600 1 EST}
+ {2563977600 36000 0 EST}
+ {2579702400 39600 1 EST}
+ {2596032000 36000 0 EST}
+ {2611756800 39600 1 EST}
+ {2627481600 36000 0 EST}
+ {2643206400 39600 1 EST}
+ {2658931200 36000 0 EST}
+ {2674656000 39600 1 EST}
+ {2690380800 36000 0 EST}
+ {2706105600 39600 1 EST}
+ {2721830400 36000 0 EST}
+ {2737555200 39600 1 EST}
+ {2753280000 36000 0 EST}
+ {2769609600 39600 1 EST}
+ {2785334400 36000 0 EST}
+ {2801059200 39600 1 EST}
+ {2816784000 36000 0 EST}
+ {2832508800 39600 1 EST}
+ {2848233600 36000 0 EST}
+ {2863958400 39600 1 EST}
+ {2879683200 36000 0 EST}
+ {2895408000 39600 1 EST}
+ {2911132800 36000 0 EST}
+ {2926857600 39600 1 EST}
+ {2942582400 36000 0 EST}
+ {2958912000 39600 1 EST}
+ {2974636800 36000 0 EST}
+ {2990361600 39600 1 EST}
+ {3006086400 36000 0 EST}
+ {3021811200 39600 1 EST}
+ {3037536000 36000 0 EST}
+ {3053260800 39600 1 EST}
+ {3068985600 36000 0 EST}
+ {3084710400 39600 1 EST}
+ {3100435200 36000 0 EST}
+ {3116764800 39600 1 EST}
+ {3132489600 36000 0 EST}
+ {3148214400 39600 1 EST}
+ {3163939200 36000 0 EST}
+ {3179664000 39600 1 EST}
+ {3195388800 36000 0 EST}
+ {3211113600 39600 1 EST}
+ {3226838400 36000 0 EST}
+ {3242563200 39600 1 EST}
+ {3258288000 36000 0 EST}
+ {3274012800 39600 1 EST}
+ {3289737600 36000 0 EST}
+ {3306067200 39600 1 EST}
+ {3321792000 36000 0 EST}
+ {3337516800 39600 1 EST}
+ {3353241600 36000 0 EST}
+ {3368966400 39600 1 EST}
+ {3384691200 36000 0 EST}
+ {3400416000 39600 1 EST}
+ {3416140800 36000 0 EST}
+ {3431865600 39600 1 EST}
+ {3447590400 36000 0 EST}
+ {3463315200 39600 1 EST}
+ {3479644800 36000 0 EST}
+ {3495369600 39600 1 EST}
+ {3511094400 36000 0 EST}
+ {3526819200 39600 1 EST}
+ {3542544000 36000 0 EST}
+ {3558268800 39600 1 EST}
+ {3573993600 36000 0 EST}
+ {3589718400 39600 1 EST}
+ {3605443200 36000 0 EST}
+ {3621168000 39600 1 EST}
+ {3636892800 36000 0 EST}
+ {3653222400 39600 1 EST}
+ {3668947200 36000 0 EST}
+ {3684672000 39600 1 EST}
+ {3700396800 36000 0 EST}
+ {3716121600 39600 1 EST}
+ {3731846400 36000 0 EST}
+ {3747571200 39600 1 EST}
+ {3763296000 36000 0 EST}
+ {3779020800 39600 1 EST}
+ {3794745600 36000 0 EST}
+ {3810470400 39600 1 EST}
+ {3826195200 36000 0 EST}
+ {3842524800 39600 1 EST}
+ {3858249600 36000 0 EST}
+ {3873974400 39600 1 EST}
+ {3889699200 36000 0 EST}
+ {3905424000 39600 1 EST}
+ {3921148800 36000 0 EST}
+ {3936873600 39600 1 EST}
+ {3952598400 36000 0 EST}
+ {3968323200 39600 1 EST}
+ {3984048000 36000 0 EST}
+ {4000377600 39600 1 EST}
+ {4016102400 36000 0 EST}
+ {4031827200 39600 1 EST}
+ {4047552000 36000 0 EST}
+ {4063276800 39600 1 EST}
+ {4079001600 36000 0 EST}
+ {4094726400 39600 1 EST}
+}
diff --git a/library/tzdata/Australia/Tasmania b/library/tzdata/Australia/Tasmania
new file mode 100644
index 0000000..1849bde
--- /dev/null
+++ b/library/tzdata/Australia/Tasmania
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Australia/Hobart)]} {
+ LoadTimeZoneFile Australia/Hobart
+}
+set TZData(:Australia/Tasmania) $TZData(:Australia/Hobart)
diff --git a/library/tzdata/Australia/Victoria b/library/tzdata/Australia/Victoria
new file mode 100644
index 0000000..037bfeb
--- /dev/null
+++ b/library/tzdata/Australia/Victoria
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Australia/Melbourne)]} {
+ LoadTimeZoneFile Australia/Melbourne
+}
+set TZData(:Australia/Victoria) $TZData(:Australia/Melbourne)
diff --git a/library/tzdata/Australia/West b/library/tzdata/Australia/West
new file mode 100644
index 0000000..4689f7e
--- /dev/null
+++ b/library/tzdata/Australia/West
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Australia/Perth)]} {
+ LoadTimeZoneFile Australia/Perth
+}
+set TZData(:Australia/West) $TZData(:Australia/Perth)
diff --git a/library/tzdata/Australia/Yancowinna b/library/tzdata/Australia/Yancowinna
new file mode 100644
index 0000000..b7d668d
--- /dev/null
+++ b/library/tzdata/Australia/Yancowinna
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Australia/Broken_Hill)]} {
+ LoadTimeZoneFile Australia/Broken_Hill
+}
+set TZData(:Australia/Yancowinna) $TZData(:Australia/Broken_Hill)
diff --git a/library/tzdata/Brazil/Acre b/library/tzdata/Brazil/Acre
new file mode 100644
index 0000000..abb0b98
--- /dev/null
+++ b/library/tzdata/Brazil/Acre
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Rio_Branco)]} {
+ LoadTimeZoneFile America/Rio_Branco
+}
+set TZData(:Brazil/Acre) $TZData(:America/Rio_Branco)
diff --git a/library/tzdata/Brazil/DeNoronha b/library/tzdata/Brazil/DeNoronha
new file mode 100644
index 0000000..53accb4
--- /dev/null
+++ b/library/tzdata/Brazil/DeNoronha
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Noronha)]} {
+ LoadTimeZoneFile America/Noronha
+}
+set TZData(:Brazil/DeNoronha) $TZData(:America/Noronha)
diff --git a/library/tzdata/Brazil/East b/library/tzdata/Brazil/East
new file mode 100644
index 0000000..f684633
--- /dev/null
+++ b/library/tzdata/Brazil/East
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Sao_Paulo)]} {
+ LoadTimeZoneFile America/Sao_Paulo
+}
+set TZData(:Brazil/East) $TZData(:America/Sao_Paulo)
diff --git a/library/tzdata/Brazil/West b/library/tzdata/Brazil/West
new file mode 100644
index 0000000..67676d9
--- /dev/null
+++ b/library/tzdata/Brazil/West
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Manaus)]} {
+ LoadTimeZoneFile America/Manaus
+}
+set TZData(:Brazil/West) $TZData(:America/Manaus)
diff --git a/library/tzdata/CET b/library/tzdata/CET
new file mode 100644
index 0000000..b08750a
--- /dev/null
+++ b/library/tzdata/CET
@@ -0,0 +1,265 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:CET) {
+ {-9223372036854775808 3600 0 CET}
+ {-1693706400 7200 1 CEST}
+ {-1680483600 3600 0 CET}
+ {-1663455600 7200 1 CEST}
+ {-1650150000 3600 0 CET}
+ {-1632006000 7200 1 CEST}
+ {-1618700400 3600 0 CET}
+ {-938905200 7200 1 CEST}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-796777200 3600 0 CET}
+ {-781052400 7200 1 CEST}
+ {-766623600 3600 0 CET}
+ {228877200 7200 1 CEST}
+ {243997200 3600 0 CET}
+ {260326800 7200 1 CEST}
+ {276051600 3600 0 CET}
+ {291776400 7200 1 CEST}
+ {307501200 3600 0 CET}
+ {323830800 7200 1 CEST}
+ {338950800 3600 0 CET}
+ {354675600 7200 1 CEST}
+ {370400400 3600 0 CET}
+ {386125200 7200 1 CEST}
+ {401850000 3600 0 CET}
+ {417574800 7200 1 CEST}
+ {433299600 3600 0 CET}
+ {449024400 7200 1 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/CST6CDT b/library/tzdata/CST6CDT
new file mode 100644
index 0000000..11e45f0
--- /dev/null
+++ b/library/tzdata/CST6CDT
@@ -0,0 +1,278 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:CST6CDT) {
+ {-9223372036854775808 -21600 0 CST}
+ {-1633276800 -18000 1 CDT}
+ {-1615136400 -21600 0 CST}
+ {-1601827200 -18000 1 CDT}
+ {-1583686800 -21600 0 CST}
+ {-880214400 -18000 1 CWT}
+ {-769395600 -18000 1 CPT}
+ {-765392400 -21600 0 CST}
+ {-84384000 -18000 1 CDT}
+ {-68662800 -21600 0 CST}
+ {-52934400 -18000 1 CDT}
+ {-37213200 -21600 0 CST}
+ {-21484800 -18000 1 CDT}
+ {-5763600 -21600 0 CST}
+ {9964800 -18000 1 CDT}
+ {25686000 -21600 0 CST}
+ {41414400 -18000 1 CDT}
+ {57740400 -21600 0 CST}
+ {73468800 -18000 1 CDT}
+ {89190000 -21600 0 CST}
+ {104918400 -18000 1 CDT}
+ {120639600 -21600 0 CST}
+ {126691200 -18000 1 CDT}
+ {152089200 -21600 0 CST}
+ {162374400 -18000 1 CDT}
+ {183538800 -21600 0 CST}
+ {199267200 -18000 1 CDT}
+ {215593200 -21600 0 CST}
+ {230716800 -18000 1 CDT}
+ {247042800 -21600 0 CST}
+ {262771200 -18000 1 CDT}
+ {278492400 -21600 0 CST}
+ {294220800 -18000 1 CDT}
+ {309942000 -21600 0 CST}
+ {325670400 -18000 1 CDT}
+ {341391600 -21600 0 CST}
+ {357120000 -18000 1 CDT}
+ {372841200 -21600 0 CST}
+ {388569600 -18000 1 CDT}
+ {404895600 -21600 0 CST}
+ {420019200 -18000 1 CDT}
+ {436345200 -21600 0 CST}
+ {452073600 -18000 1 CDT}
+ {467794800 -21600 0 CST}
+ {483523200 -18000 1 CDT}
+ {499244400 -21600 0 CST}
+ {514972800 -18000 1 CDT}
+ {530694000 -21600 0 CST}
+ {544608000 -18000 1 CDT}
+ {562143600 -21600 0 CST}
+ {576057600 -18000 1 CDT}
+ {594198000 -21600 0 CST}
+ {607507200 -18000 1 CDT}
+ {625647600 -21600 0 CST}
+ {638956800 -18000 1 CDT}
+ {657097200 -21600 0 CST}
+ {671011200 -18000 1 CDT}
+ {688546800 -21600 0 CST}
+ {702460800 -18000 1 CDT}
+ {719996400 -21600 0 CST}
+ {733910400 -18000 1 CDT}
+ {752050800 -21600 0 CST}
+ {765360000 -18000 1 CDT}
+ {783500400 -21600 0 CST}
+ {796809600 -18000 1 CDT}
+ {814950000 -21600 0 CST}
+ {828864000 -18000 1 CDT}
+ {846399600 -21600 0 CST}
+ {860313600 -18000 1 CDT}
+ {877849200 -21600 0 CST}
+ {891763200 -18000 1 CDT}
+ {909298800 -21600 0 CST}
+ {923212800 -18000 1 CDT}
+ {941353200 -21600 0 CST}
+ {954662400 -18000 1 CDT}
+ {972802800 -21600 0 CST}
+ {986112000 -18000 1 CDT}
+ {1004252400 -21600 0 CST}
+ {1018166400 -18000 1 CDT}
+ {1035702000 -21600 0 CST}
+ {1049616000 -18000 1 CDT}
+ {1067151600 -21600 0 CST}
+ {1081065600 -18000 1 CDT}
+ {1099206000 -21600 0 CST}
+ {1112515200 -18000 1 CDT}
+ {1130655600 -21600 0 CST}
+ {1143964800 -18000 1 CDT}
+ {1162105200 -21600 0 CST}
+ {1173600000 -18000 1 CDT}
+ {1194159600 -21600 0 CST}
+ {1205049600 -18000 1 CDT}
+ {1225609200 -21600 0 CST}
+ {1236499200 -18000 1 CDT}
+ {1257058800 -21600 0 CST}
+ {1268553600 -18000 1 CDT}
+ {1289113200 -21600 0 CST}
+ {1300003200 -18000 1 CDT}
+ {1320562800 -21600 0 CST}
+ {1331452800 -18000 1 CDT}
+ {1352012400 -21600 0 CST}
+ {1362902400 -18000 1 CDT}
+ {1383462000 -21600 0 CST}
+ {1394352000 -18000 1 CDT}
+ {1414911600 -21600 0 CST}
+ {1425801600 -18000 1 CDT}
+ {1446361200 -21600 0 CST}
+ {1457856000 -18000 1 CDT}
+ {1478415600 -21600 0 CST}
+ {1489305600 -18000 1 CDT}
+ {1509865200 -21600 0 CST}
+ {1520755200 -18000 1 CDT}
+ {1541314800 -21600 0 CST}
+ {1552204800 -18000 1 CDT}
+ {1572764400 -21600 0 CST}
+ {1583654400 -18000 1 CDT}
+ {1604214000 -21600 0 CST}
+ {1615708800 -18000 1 CDT}
+ {1636268400 -21600 0 CST}
+ {1647158400 -18000 1 CDT}
+ {1667718000 -21600 0 CST}
+ {1678608000 -18000 1 CDT}
+ {1699167600 -21600 0 CST}
+ {1710057600 -18000 1 CDT}
+ {1730617200 -21600 0 CST}
+ {1741507200 -18000 1 CDT}
+ {1762066800 -21600 0 CST}
+ {1772956800 -18000 1 CDT}
+ {1793516400 -21600 0 CST}
+ {1805011200 -18000 1 CDT}
+ {1825570800 -21600 0 CST}
+ {1836460800 -18000 1 CDT}
+ {1857020400 -21600 0 CST}
+ {1867910400 -18000 1 CDT}
+ {1888470000 -21600 0 CST}
+ {1899360000 -18000 1 CDT}
+ {1919919600 -21600 0 CST}
+ {1930809600 -18000 1 CDT}
+ {1951369200 -21600 0 CST}
+ {1962864000 -18000 1 CDT}
+ {1983423600 -21600 0 CST}
+ {1994313600 -18000 1 CDT}
+ {2014873200 -21600 0 CST}
+ {2025763200 -18000 1 CDT}
+ {2046322800 -21600 0 CST}
+ {2057212800 -18000 1 CDT}
+ {2077772400 -21600 0 CST}
+ {2088662400 -18000 1 CDT}
+ {2109222000 -21600 0 CST}
+ {2120112000 -18000 1 CDT}
+ {2140671600 -21600 0 CST}
+ {2152166400 -18000 1 CDT}
+ {2172726000 -21600 0 CST}
+ {2183616000 -18000 1 CDT}
+ {2204175600 -21600 0 CST}
+ {2215065600 -18000 1 CDT}
+ {2235625200 -21600 0 CST}
+ {2246515200 -18000 1 CDT}
+ {2267074800 -21600 0 CST}
+ {2277964800 -18000 1 CDT}
+ {2298524400 -21600 0 CST}
+ {2309414400 -18000 1 CDT}
+ {2329974000 -21600 0 CST}
+ {2341468800 -18000 1 CDT}
+ {2362028400 -21600 0 CST}
+ {2372918400 -18000 1 CDT}
+ {2393478000 -21600 0 CST}
+ {2404368000 -18000 1 CDT}
+ {2424927600 -21600 0 CST}
+ {2435817600 -18000 1 CDT}
+ {2456377200 -21600 0 CST}
+ {2467267200 -18000 1 CDT}
+ {2487826800 -21600 0 CST}
+ {2499321600 -18000 1 CDT}
+ {2519881200 -21600 0 CST}
+ {2530771200 -18000 1 CDT}
+ {2551330800 -21600 0 CST}
+ {2562220800 -18000 1 CDT}
+ {2582780400 -21600 0 CST}
+ {2593670400 -18000 1 CDT}
+ {2614230000 -21600 0 CST}
+ {2625120000 -18000 1 CDT}
+ {2645679600 -21600 0 CST}
+ {2656569600 -18000 1 CDT}
+ {2677129200 -21600 0 CST}
+ {2688624000 -18000 1 CDT}
+ {2709183600 -21600 0 CST}
+ {2720073600 -18000 1 CDT}
+ {2740633200 -21600 0 CST}
+ {2751523200 -18000 1 CDT}
+ {2772082800 -21600 0 CST}
+ {2782972800 -18000 1 CDT}
+ {2803532400 -21600 0 CST}
+ {2814422400 -18000 1 CDT}
+ {2834982000 -21600 0 CST}
+ {2846476800 -18000 1 CDT}
+ {2867036400 -21600 0 CST}
+ {2877926400 -18000 1 CDT}
+ {2898486000 -21600 0 CST}
+ {2909376000 -18000 1 CDT}
+ {2929935600 -21600 0 CST}
+ {2940825600 -18000 1 CDT}
+ {2961385200 -21600 0 CST}
+ {2972275200 -18000 1 CDT}
+ {2992834800 -21600 0 CST}
+ {3003724800 -18000 1 CDT}
+ {3024284400 -21600 0 CST}
+ {3035779200 -18000 1 CDT}
+ {3056338800 -21600 0 CST}
+ {3067228800 -18000 1 CDT}
+ {3087788400 -21600 0 CST}
+ {3098678400 -18000 1 CDT}
+ {3119238000 -21600 0 CST}
+ {3130128000 -18000 1 CDT}
+ {3150687600 -21600 0 CST}
+ {3161577600 -18000 1 CDT}
+ {3182137200 -21600 0 CST}
+ {3193027200 -18000 1 CDT}
+ {3213586800 -21600 0 CST}
+ {3225081600 -18000 1 CDT}
+ {3245641200 -21600 0 CST}
+ {3256531200 -18000 1 CDT}
+ {3277090800 -21600 0 CST}
+ {3287980800 -18000 1 CDT}
+ {3308540400 -21600 0 CST}
+ {3319430400 -18000 1 CDT}
+ {3339990000 -21600 0 CST}
+ {3350880000 -18000 1 CDT}
+ {3371439600 -21600 0 CST}
+ {3382934400 -18000 1 CDT}
+ {3403494000 -21600 0 CST}
+ {3414384000 -18000 1 CDT}
+ {3434943600 -21600 0 CST}
+ {3445833600 -18000 1 CDT}
+ {3466393200 -21600 0 CST}
+ {3477283200 -18000 1 CDT}
+ {3497842800 -21600 0 CST}
+ {3508732800 -18000 1 CDT}
+ {3529292400 -21600 0 CST}
+ {3540182400 -18000 1 CDT}
+ {3560742000 -21600 0 CST}
+ {3572236800 -18000 1 CDT}
+ {3592796400 -21600 0 CST}
+ {3603686400 -18000 1 CDT}
+ {3624246000 -21600 0 CST}
+ {3635136000 -18000 1 CDT}
+ {3655695600 -21600 0 CST}
+ {3666585600 -18000 1 CDT}
+ {3687145200 -21600 0 CST}
+ {3698035200 -18000 1 CDT}
+ {3718594800 -21600 0 CST}
+ {3730089600 -18000 1 CDT}
+ {3750649200 -21600 0 CST}
+ {3761539200 -18000 1 CDT}
+ {3782098800 -21600 0 CST}
+ {3792988800 -18000 1 CDT}
+ {3813548400 -21600 0 CST}
+ {3824438400 -18000 1 CDT}
+ {3844998000 -21600 0 CST}
+ {3855888000 -18000 1 CDT}
+ {3876447600 -21600 0 CST}
+ {3887337600 -18000 1 CDT}
+ {3907897200 -21600 0 CST}
+ {3919392000 -18000 1 CDT}
+ {3939951600 -21600 0 CST}
+ {3950841600 -18000 1 CDT}
+ {3971401200 -21600 0 CST}
+ {3982291200 -18000 1 CDT}
+ {4002850800 -21600 0 CST}
+ {4013740800 -18000 1 CDT}
+ {4034300400 -21600 0 CST}
+ {4045190400 -18000 1 CDT}
+ {4065750000 -21600 0 CST}
+ {4076640000 -18000 1 CDT}
+ {4097199600 -21600 0 CST}
+}
diff --git a/library/tzdata/Canada/Atlantic b/library/tzdata/Canada/Atlantic
new file mode 100644
index 0000000..d1478d9
--- /dev/null
+++ b/library/tzdata/Canada/Atlantic
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Halifax)]} {
+ LoadTimeZoneFile America/Halifax
+}
+set TZData(:Canada/Atlantic) $TZData(:America/Halifax)
diff --git a/library/tzdata/Canada/Central b/library/tzdata/Canada/Central
new file mode 100644
index 0000000..b04bef9
--- /dev/null
+++ b/library/tzdata/Canada/Central
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Winnipeg)]} {
+ LoadTimeZoneFile America/Winnipeg
+}
+set TZData(:Canada/Central) $TZData(:America/Winnipeg)
diff --git a/library/tzdata/Canada/East-Saskatchewan b/library/tzdata/Canada/East-Saskatchewan
new file mode 100644
index 0000000..f7e500c
--- /dev/null
+++ b/library/tzdata/Canada/East-Saskatchewan
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Regina)]} {
+ LoadTimeZoneFile America/Regina
+}
+set TZData(:Canada/East-Saskatchewan) $TZData(:America/Regina)
diff --git a/library/tzdata/Canada/Eastern b/library/tzdata/Canada/Eastern
new file mode 100644
index 0000000..74528eb
--- /dev/null
+++ b/library/tzdata/Canada/Eastern
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Toronto)]} {
+ LoadTimeZoneFile America/Toronto
+}
+set TZData(:Canada/Eastern) $TZData(:America/Toronto)
diff --git a/library/tzdata/Canada/Mountain b/library/tzdata/Canada/Mountain
new file mode 100644
index 0000000..8c6458d
--- /dev/null
+++ b/library/tzdata/Canada/Mountain
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Edmonton)]} {
+ LoadTimeZoneFile America/Edmonton
+}
+set TZData(:Canada/Mountain) $TZData(:America/Edmonton)
diff --git a/library/tzdata/Canada/Newfoundland b/library/tzdata/Canada/Newfoundland
new file mode 100644
index 0000000..6904cde
--- /dev/null
+++ b/library/tzdata/Canada/Newfoundland
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/St_Johns)]} {
+ LoadTimeZoneFile America/St_Johns
+}
+set TZData(:Canada/Newfoundland) $TZData(:America/St_Johns)
diff --git a/library/tzdata/Canada/Pacific b/library/tzdata/Canada/Pacific
new file mode 100644
index 0000000..4d70342
--- /dev/null
+++ b/library/tzdata/Canada/Pacific
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Vancouver)]} {
+ LoadTimeZoneFile America/Vancouver
+}
+set TZData(:Canada/Pacific) $TZData(:America/Vancouver)
diff --git a/library/tzdata/Canada/Saskatchewan b/library/tzdata/Canada/Saskatchewan
new file mode 100644
index 0000000..cd56446
--- /dev/null
+++ b/library/tzdata/Canada/Saskatchewan
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Regina)]} {
+ LoadTimeZoneFile America/Regina
+}
+set TZData(:Canada/Saskatchewan) $TZData(:America/Regina)
diff --git a/library/tzdata/Canada/Yukon b/library/tzdata/Canada/Yukon
new file mode 100644
index 0000000..04b8368
--- /dev/null
+++ b/library/tzdata/Canada/Yukon
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Whitehorse)]} {
+ LoadTimeZoneFile America/Whitehorse
+}
+set TZData(:Canada/Yukon) $TZData(:America/Whitehorse)
diff --git a/library/tzdata/Chile/Continental b/library/tzdata/Chile/Continental
new file mode 100644
index 0000000..0f858a3
--- /dev/null
+++ b/library/tzdata/Chile/Continental
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Santiago)]} {
+ LoadTimeZoneFile America/Santiago
+}
+set TZData(:Chile/Continental) $TZData(:America/Santiago)
diff --git a/library/tzdata/Chile/EasterIsland b/library/tzdata/Chile/EasterIsland
new file mode 100644
index 0000000..4edc034
--- /dev/null
+++ b/library/tzdata/Chile/EasterIsland
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Pacific/Easter)]} {
+ LoadTimeZoneFile Pacific/Easter
+}
+set TZData(:Chile/EasterIsland) $TZData(:Pacific/Easter)
diff --git a/library/tzdata/Cuba b/library/tzdata/Cuba
new file mode 100644
index 0000000..17f7b45
--- /dev/null
+++ b/library/tzdata/Cuba
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Havana)]} {
+ LoadTimeZoneFile America/Havana
+}
+set TZData(:Cuba) $TZData(:America/Havana)
diff --git a/library/tzdata/EET b/library/tzdata/EET
new file mode 100644
index 0000000..e7c102a
--- /dev/null
+++ b/library/tzdata/EET
@@ -0,0 +1,251 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:EET) {
+ {-9223372036854775808 7200 0 EET}
+ {228877200 10800 1 EEST}
+ {243997200 7200 0 EET}
+ {260326800 10800 1 EEST}
+ {276051600 7200 0 EET}
+ {291776400 10800 1 EEST}
+ {307501200 7200 0 EET}
+ {323830800 10800 1 EEST}
+ {338950800 7200 0 EET}
+ {354675600 10800 1 EEST}
+ {370400400 7200 0 EET}
+ {386125200 10800 1 EEST}
+ {401850000 7200 0 EET}
+ {417574800 10800 1 EEST}
+ {433299600 7200 0 EET}
+ {449024400 10800 1 EEST}
+ {465354000 7200 0 EET}
+ {481078800 10800 1 EEST}
+ {496803600 7200 0 EET}
+ {512528400 10800 1 EEST}
+ {528253200 7200 0 EET}
+ {543978000 10800 1 EEST}
+ {559702800 7200 0 EET}
+ {575427600 10800 1 EEST}
+ {591152400 7200 0 EET}
+ {606877200 10800 1 EEST}
+ {622602000 7200 0 EET}
+ {638326800 10800 1 EEST}
+ {654656400 7200 0 EET}
+ {670381200 10800 1 EEST}
+ {686106000 7200 0 EET}
+ {701830800 10800 1 EEST}
+ {717555600 7200 0 EET}
+ {733280400 10800 1 EEST}
+ {749005200 7200 0 EET}
+ {764730000 10800 1 EEST}
+ {780454800 7200 0 EET}
+ {796179600 10800 1 EEST}
+ {811904400 7200 0 EET}
+ {828234000 10800 1 EEST}
+ {846378000 7200 0 EET}
+ {859683600 10800 1 EEST}
+ {877827600 7200 0 EET}
+ {891133200 10800 1 EEST}
+ {909277200 7200 0 EET}
+ {922582800 10800 1 EEST}
+ {941331600 7200 0 EET}
+ {954032400 10800 1 EEST}
+ {972781200 7200 0 EET}
+ {985482000 10800 1 EEST}
+ {1004230800 7200 0 EET}
+ {1017536400 10800 1 EEST}
+ {1035680400 7200 0 EET}
+ {1048986000 10800 1 EEST}
+ {1067130000 7200 0 EET}
+ {1080435600 10800 1 EEST}
+ {1099184400 7200 0 EET}
+ {1111885200 10800 1 EEST}
+ {1130634000 7200 0 EET}
+ {1143334800 10800 1 EEST}
+ {1162083600 7200 0 EET}
+ {1174784400 10800 1 EEST}
+ {1193533200 7200 0 EET}
+ {1206838800 10800 1 EEST}
+ {1224982800 7200 0 EET}
+ {1238288400 10800 1 EEST}
+ {1256432400 7200 0 EET}
+ {1269738000 10800 1 EEST}
+ {1288486800 7200 0 EET}
+ {1301187600 10800 1 EEST}
+ {1319936400 7200 0 EET}
+ {1332637200 10800 1 EEST}
+ {1351386000 7200 0 EET}
+ {1364691600 10800 1 EEST}
+ {1382835600 7200 0 EET}
+ {1396141200 10800 1 EEST}
+ {1414285200 7200 0 EET}
+ {1427590800 10800 1 EEST}
+ {1445734800 7200 0 EET}
+ {1459040400 10800 1 EEST}
+ {1477789200 7200 0 EET}
+ {1490490000 10800 1 EEST}
+ {1509238800 7200 0 EET}
+ {1521939600 10800 1 EEST}
+ {1540688400 7200 0 EET}
+ {1553994000 10800 1 EEST}
+ {1572138000 7200 0 EET}
+ {1585443600 10800 1 EEST}
+ {1603587600 7200 0 EET}
+ {1616893200 10800 1 EEST}
+ {1635642000 7200 0 EET}
+ {1648342800 10800 1 EEST}
+ {1667091600 7200 0 EET}
+ {1679792400 10800 1 EEST}
+ {1698541200 7200 0 EET}
+ {1711846800 10800 1 EEST}
+ {1729990800 7200 0 EET}
+ {1743296400 10800 1 EEST}
+ {1761440400 7200 0 EET}
+ {1774746000 10800 1 EEST}
+ {1792890000 7200 0 EET}
+ {1806195600 10800 1 EEST}
+ {1824944400 7200 0 EET}
+ {1837645200 10800 1 EEST}
+ {1856394000 7200 0 EET}
+ {1869094800 10800 1 EEST}
+ {1887843600 7200 0 EET}
+ {1901149200 10800 1 EEST}
+ {1919293200 7200 0 EET}
+ {1932598800 10800 1 EEST}
+ {1950742800 7200 0 EET}
+ {1964048400 10800 1 EEST}
+ {1982797200 7200 0 EET}
+ {1995498000 10800 1 EEST}
+ {2014246800 7200 0 EET}
+ {2026947600 10800 1 EEST}
+ {2045696400 7200 0 EET}
+ {2058397200 10800 1 EEST}
+ {2077146000 7200 0 EET}
+ {2090451600 10800 1 EEST}
+ {2108595600 7200 0 EET}
+ {2121901200 10800 1 EEST}
+ {2140045200 7200 0 EET}
+ {2153350800 10800 1 EEST}
+ {2172099600 7200 0 EET}
+ {2184800400 10800 1 EEST}
+ {2203549200 7200 0 EET}
+ {2216250000 10800 1 EEST}
+ {2234998800 7200 0 EET}
+ {2248304400 10800 1 EEST}
+ {2266448400 7200 0 EET}
+ {2279754000 10800 1 EEST}
+ {2297898000 7200 0 EET}
+ {2311203600 10800 1 EEST}
+ {2329347600 7200 0 EET}
+ {2342653200 10800 1 EEST}
+ {2361402000 7200 0 EET}
+ {2374102800 10800 1 EEST}
+ {2392851600 7200 0 EET}
+ {2405552400 10800 1 EEST}
+ {2424301200 7200 0 EET}
+ {2437606800 10800 1 EEST}
+ {2455750800 7200 0 EET}
+ {2469056400 10800 1 EEST}
+ {2487200400 7200 0 EET}
+ {2500506000 10800 1 EEST}
+ {2519254800 7200 0 EET}
+ {2531955600 10800 1 EEST}
+ {2550704400 7200 0 EET}
+ {2563405200 10800 1 EEST}
+ {2582154000 7200 0 EET}
+ {2595459600 10800 1 EEST}
+ {2613603600 7200 0 EET}
+ {2626909200 10800 1 EEST}
+ {2645053200 7200 0 EET}
+ {2658358800 10800 1 EEST}
+ {2676502800 7200 0 EET}
+ {2689808400 10800 1 EEST}
+ {2708557200 7200 0 EET}
+ {2721258000 10800 1 EEST}
+ {2740006800 7200 0 EET}
+ {2752707600 10800 1 EEST}
+ {2771456400 7200 0 EET}
+ {2784762000 10800 1 EEST}
+ {2802906000 7200 0 EET}
+ {2816211600 10800 1 EEST}
+ {2834355600 7200 0 EET}
+ {2847661200 10800 1 EEST}
+ {2866410000 7200 0 EET}
+ {2879110800 10800 1 EEST}
+ {2897859600 7200 0 EET}
+ {2910560400 10800 1 EEST}
+ {2929309200 7200 0 EET}
+ {2942010000 10800 1 EEST}
+ {2960758800 7200 0 EET}
+ {2974064400 10800 1 EEST}
+ {2992208400 7200 0 EET}
+ {3005514000 10800 1 EEST}
+ {3023658000 7200 0 EET}
+ {3036963600 10800 1 EEST}
+ {3055712400 7200 0 EET}
+ {3068413200 10800 1 EEST}
+ {3087162000 7200 0 EET}
+ {3099862800 10800 1 EEST}
+ {3118611600 7200 0 EET}
+ {3131917200 10800 1 EEST}
+ {3150061200 7200 0 EET}
+ {3163366800 10800 1 EEST}
+ {3181510800 7200 0 EET}
+ {3194816400 10800 1 EEST}
+ {3212960400 7200 0 EET}
+ {3226266000 10800 1 EEST}
+ {3245014800 7200 0 EET}
+ {3257715600 10800 1 EEST}
+ {3276464400 7200 0 EET}
+ {3289165200 10800 1 EEST}
+ {3307914000 7200 0 EET}
+ {3321219600 10800 1 EEST}
+ {3339363600 7200 0 EET}
+ {3352669200 10800 1 EEST}
+ {3370813200 7200 0 EET}
+ {3384118800 10800 1 EEST}
+ {3402867600 7200 0 EET}
+ {3415568400 10800 1 EEST}
+ {3434317200 7200 0 EET}
+ {3447018000 10800 1 EEST}
+ {3465766800 7200 0 EET}
+ {3479072400 10800 1 EEST}
+ {3497216400 7200 0 EET}
+ {3510522000 10800 1 EEST}
+ {3528666000 7200 0 EET}
+ {3541971600 10800 1 EEST}
+ {3560115600 7200 0 EET}
+ {3573421200 10800 1 EEST}
+ {3592170000 7200 0 EET}
+ {3604870800 10800 1 EEST}
+ {3623619600 7200 0 EET}
+ {3636320400 10800 1 EEST}
+ {3655069200 7200 0 EET}
+ {3668374800 10800 1 EEST}
+ {3686518800 7200 0 EET}
+ {3699824400 10800 1 EEST}
+ {3717968400 7200 0 EET}
+ {3731274000 10800 1 EEST}
+ {3750022800 7200 0 EET}
+ {3762723600 10800 1 EEST}
+ {3781472400 7200 0 EET}
+ {3794173200 10800 1 EEST}
+ {3812922000 7200 0 EET}
+ {3825622800 10800 1 EEST}
+ {3844371600 7200 0 EET}
+ {3857677200 10800 1 EEST}
+ {3875821200 7200 0 EET}
+ {3889126800 10800 1 EEST}
+ {3907270800 7200 0 EET}
+ {3920576400 10800 1 EEST}
+ {3939325200 7200 0 EET}
+ {3952026000 10800 1 EEST}
+ {3970774800 7200 0 EET}
+ {3983475600 10800 1 EEST}
+ {4002224400 7200 0 EET}
+ {4015530000 10800 1 EEST}
+ {4033674000 7200 0 EET}
+ {4046979600 10800 1 EEST}
+ {4065123600 7200 0 EET}
+ {4078429200 10800 1 EEST}
+ {4096573200 7200 0 EET}
+}
diff --git a/library/tzdata/EST b/library/tzdata/EST
new file mode 100644
index 0000000..72c5b17
--- /dev/null
+++ b/library/tzdata/EST
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:EST) {
+ {-9223372036854775808 -18000 0 EST}
+}
diff --git a/library/tzdata/EST5EDT b/library/tzdata/EST5EDT
new file mode 100644
index 0000000..968833e
--- /dev/null
+++ b/library/tzdata/EST5EDT
@@ -0,0 +1,278 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:EST5EDT) {
+ {-9223372036854775808 -18000 0 EST}
+ {-1633280400 -14400 1 EDT}
+ {-1615140000 -18000 0 EST}
+ {-1601830800 -14400 1 EDT}
+ {-1583690400 -18000 0 EST}
+ {-880218000 -14400 1 EWT}
+ {-769395600 -14400 1 EPT}
+ {-765396000 -18000 0 EST}
+ {-84387600 -14400 1 EDT}
+ {-68666400 -18000 0 EST}
+ {-52938000 -14400 1 EDT}
+ {-37216800 -18000 0 EST}
+ {-21488400 -14400 1 EDT}
+ {-5767200 -18000 0 EST}
+ {9961200 -14400 1 EDT}
+ {25682400 -18000 0 EST}
+ {41410800 -14400 1 EDT}
+ {57736800 -18000 0 EST}
+ {73465200 -14400 1 EDT}
+ {89186400 -18000 0 EST}
+ {104914800 -14400 1 EDT}
+ {120636000 -18000 0 EST}
+ {126687600 -14400 1 EDT}
+ {152085600 -18000 0 EST}
+ {162370800 -14400 1 EDT}
+ {183535200 -18000 0 EST}
+ {199263600 -14400 1 EDT}
+ {215589600 -18000 0 EST}
+ {230713200 -14400 1 EDT}
+ {247039200 -18000 0 EST}
+ {262767600 -14400 1 EDT}
+ {278488800 -18000 0 EST}
+ {294217200 -14400 1 EDT}
+ {309938400 -18000 0 EST}
+ {325666800 -14400 1 EDT}
+ {341388000 -18000 0 EST}
+ {357116400 -14400 1 EDT}
+ {372837600 -18000 0 EST}
+ {388566000 -14400 1 EDT}
+ {404892000 -18000 0 EST}
+ {420015600 -14400 1 EDT}
+ {436341600 -18000 0 EST}
+ {452070000 -14400 1 EDT}
+ {467791200 -18000 0 EST}
+ {483519600 -14400 1 EDT}
+ {499240800 -18000 0 EST}
+ {514969200 -14400 1 EDT}
+ {530690400 -18000 0 EST}
+ {544604400 -14400 1 EDT}
+ {562140000 -18000 0 EST}
+ {576054000 -14400 1 EDT}
+ {594194400 -18000 0 EST}
+ {607503600 -14400 1 EDT}
+ {625644000 -18000 0 EST}
+ {638953200 -14400 1 EDT}
+ {657093600 -18000 0 EST}
+ {671007600 -14400 1 EDT}
+ {688543200 -18000 0 EST}
+ {702457200 -14400 1 EDT}
+ {719992800 -18000 0 EST}
+ {733906800 -14400 1 EDT}
+ {752047200 -18000 0 EST}
+ {765356400 -14400 1 EDT}
+ {783496800 -18000 0 EST}
+ {796806000 -14400 1 EDT}
+ {814946400 -18000 0 EST}
+ {828860400 -14400 1 EDT}
+ {846396000 -18000 0 EST}
+ {860310000 -14400 1 EDT}
+ {877845600 -18000 0 EST}
+ {891759600 -14400 1 EDT}
+ {909295200 -18000 0 EST}
+ {923209200 -14400 1 EDT}
+ {941349600 -18000 0 EST}
+ {954658800 -14400 1 EDT}
+ {972799200 -18000 0 EST}
+ {986108400 -14400 1 EDT}
+ {1004248800 -18000 0 EST}
+ {1018162800 -14400 1 EDT}
+ {1035698400 -18000 0 EST}
+ {1049612400 -14400 1 EDT}
+ {1067148000 -18000 0 EST}
+ {1081062000 -14400 1 EDT}
+ {1099202400 -18000 0 EST}
+ {1112511600 -14400 1 EDT}
+ {1130652000 -18000 0 EST}
+ {1143961200 -14400 1 EDT}
+ {1162101600 -18000 0 EST}
+ {1173596400 -14400 1 EDT}
+ {1194156000 -18000 0 EST}
+ {1205046000 -14400 1 EDT}
+ {1225605600 -18000 0 EST}
+ {1236495600 -14400 1 EDT}
+ {1257055200 -18000 0 EST}
+ {1268550000 -14400 1 EDT}
+ {1289109600 -18000 0 EST}
+ {1299999600 -14400 1 EDT}
+ {1320559200 -18000 0 EST}
+ {1331449200 -14400 1 EDT}
+ {1352008800 -18000 0 EST}
+ {1362898800 -14400 1 EDT}
+ {1383458400 -18000 0 EST}
+ {1394348400 -14400 1 EDT}
+ {1414908000 -18000 0 EST}
+ {1425798000 -14400 1 EDT}
+ {1446357600 -18000 0 EST}
+ {1457852400 -14400 1 EDT}
+ {1478412000 -18000 0 EST}
+ {1489302000 -14400 1 EDT}
+ {1509861600 -18000 0 EST}
+ {1520751600 -14400 1 EDT}
+ {1541311200 -18000 0 EST}
+ {1552201200 -14400 1 EDT}
+ {1572760800 -18000 0 EST}
+ {1583650800 -14400 1 EDT}
+ {1604210400 -18000 0 EST}
+ {1615705200 -14400 1 EDT}
+ {1636264800 -18000 0 EST}
+ {1647154800 -14400 1 EDT}
+ {1667714400 -18000 0 EST}
+ {1678604400 -14400 1 EDT}
+ {1699164000 -18000 0 EST}
+ {1710054000 -14400 1 EDT}
+ {1730613600 -18000 0 EST}
+ {1741503600 -14400 1 EDT}
+ {1762063200 -18000 0 EST}
+ {1772953200 -14400 1 EDT}
+ {1793512800 -18000 0 EST}
+ {1805007600 -14400 1 EDT}
+ {1825567200 -18000 0 EST}
+ {1836457200 -14400 1 EDT}
+ {1857016800 -18000 0 EST}
+ {1867906800 -14400 1 EDT}
+ {1888466400 -18000 0 EST}
+ {1899356400 -14400 1 EDT}
+ {1919916000 -18000 0 EST}
+ {1930806000 -14400 1 EDT}
+ {1951365600 -18000 0 EST}
+ {1962860400 -14400 1 EDT}
+ {1983420000 -18000 0 EST}
+ {1994310000 -14400 1 EDT}
+ {2014869600 -18000 0 EST}
+ {2025759600 -14400 1 EDT}
+ {2046319200 -18000 0 EST}
+ {2057209200 -14400 1 EDT}
+ {2077768800 -18000 0 EST}
+ {2088658800 -14400 1 EDT}
+ {2109218400 -18000 0 EST}
+ {2120108400 -14400 1 EDT}
+ {2140668000 -18000 0 EST}
+ {2152162800 -14400 1 EDT}
+ {2172722400 -18000 0 EST}
+ {2183612400 -14400 1 EDT}
+ {2204172000 -18000 0 EST}
+ {2215062000 -14400 1 EDT}
+ {2235621600 -18000 0 EST}
+ {2246511600 -14400 1 EDT}
+ {2267071200 -18000 0 EST}
+ {2277961200 -14400 1 EDT}
+ {2298520800 -18000 0 EST}
+ {2309410800 -14400 1 EDT}
+ {2329970400 -18000 0 EST}
+ {2341465200 -14400 1 EDT}
+ {2362024800 -18000 0 EST}
+ {2372914800 -14400 1 EDT}
+ {2393474400 -18000 0 EST}
+ {2404364400 -14400 1 EDT}
+ {2424924000 -18000 0 EST}
+ {2435814000 -14400 1 EDT}
+ {2456373600 -18000 0 EST}
+ {2467263600 -14400 1 EDT}
+ {2487823200 -18000 0 EST}
+ {2499318000 -14400 1 EDT}
+ {2519877600 -18000 0 EST}
+ {2530767600 -14400 1 EDT}
+ {2551327200 -18000 0 EST}
+ {2562217200 -14400 1 EDT}
+ {2582776800 -18000 0 EST}
+ {2593666800 -14400 1 EDT}
+ {2614226400 -18000 0 EST}
+ {2625116400 -14400 1 EDT}
+ {2645676000 -18000 0 EST}
+ {2656566000 -14400 1 EDT}
+ {2677125600 -18000 0 EST}
+ {2688620400 -14400 1 EDT}
+ {2709180000 -18000 0 EST}
+ {2720070000 -14400 1 EDT}
+ {2740629600 -18000 0 EST}
+ {2751519600 -14400 1 EDT}
+ {2772079200 -18000 0 EST}
+ {2782969200 -14400 1 EDT}
+ {2803528800 -18000 0 EST}
+ {2814418800 -14400 1 EDT}
+ {2834978400 -18000 0 EST}
+ {2846473200 -14400 1 EDT}
+ {2867032800 -18000 0 EST}
+ {2877922800 -14400 1 EDT}
+ {2898482400 -18000 0 EST}
+ {2909372400 -14400 1 EDT}
+ {2929932000 -18000 0 EST}
+ {2940822000 -14400 1 EDT}
+ {2961381600 -18000 0 EST}
+ {2972271600 -14400 1 EDT}
+ {2992831200 -18000 0 EST}
+ {3003721200 -14400 1 EDT}
+ {3024280800 -18000 0 EST}
+ {3035775600 -14400 1 EDT}
+ {3056335200 -18000 0 EST}
+ {3067225200 -14400 1 EDT}
+ {3087784800 -18000 0 EST}
+ {3098674800 -14400 1 EDT}
+ {3119234400 -18000 0 EST}
+ {3130124400 -14400 1 EDT}
+ {3150684000 -18000 0 EST}
+ {3161574000 -14400 1 EDT}
+ {3182133600 -18000 0 EST}
+ {3193023600 -14400 1 EDT}
+ {3213583200 -18000 0 EST}
+ {3225078000 -14400 1 EDT}
+ {3245637600 -18000 0 EST}
+ {3256527600 -14400 1 EDT}
+ {3277087200 -18000 0 EST}
+ {3287977200 -14400 1 EDT}
+ {3308536800 -18000 0 EST}
+ {3319426800 -14400 1 EDT}
+ {3339986400 -18000 0 EST}
+ {3350876400 -14400 1 EDT}
+ {3371436000 -18000 0 EST}
+ {3382930800 -14400 1 EDT}
+ {3403490400 -18000 0 EST}
+ {3414380400 -14400 1 EDT}
+ {3434940000 -18000 0 EST}
+ {3445830000 -14400 1 EDT}
+ {3466389600 -18000 0 EST}
+ {3477279600 -14400 1 EDT}
+ {3497839200 -18000 0 EST}
+ {3508729200 -14400 1 EDT}
+ {3529288800 -18000 0 EST}
+ {3540178800 -14400 1 EDT}
+ {3560738400 -18000 0 EST}
+ {3572233200 -14400 1 EDT}
+ {3592792800 -18000 0 EST}
+ {3603682800 -14400 1 EDT}
+ {3624242400 -18000 0 EST}
+ {3635132400 -14400 1 EDT}
+ {3655692000 -18000 0 EST}
+ {3666582000 -14400 1 EDT}
+ {3687141600 -18000 0 EST}
+ {3698031600 -14400 1 EDT}
+ {3718591200 -18000 0 EST}
+ {3730086000 -14400 1 EDT}
+ {3750645600 -18000 0 EST}
+ {3761535600 -14400 1 EDT}
+ {3782095200 -18000 0 EST}
+ {3792985200 -14400 1 EDT}
+ {3813544800 -18000 0 EST}
+ {3824434800 -14400 1 EDT}
+ {3844994400 -18000 0 EST}
+ {3855884400 -14400 1 EDT}
+ {3876444000 -18000 0 EST}
+ {3887334000 -14400 1 EDT}
+ {3907893600 -18000 0 EST}
+ {3919388400 -14400 1 EDT}
+ {3939948000 -18000 0 EST}
+ {3950838000 -14400 1 EDT}
+ {3971397600 -18000 0 EST}
+ {3982287600 -14400 1 EDT}
+ {4002847200 -18000 0 EST}
+ {4013737200 -14400 1 EDT}
+ {4034296800 -18000 0 EST}
+ {4045186800 -14400 1 EDT}
+ {4065746400 -18000 0 EST}
+ {4076636400 -14400 1 EDT}
+ {4097196000 -18000 0 EST}
+}
diff --git a/library/tzdata/Egypt b/library/tzdata/Egypt
new file mode 100644
index 0000000..63341bc
--- /dev/null
+++ b/library/tzdata/Egypt
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Africa/Cairo)]} {
+ LoadTimeZoneFile Africa/Cairo
+}
+set TZData(:Egypt) $TZData(:Africa/Cairo)
diff --git a/library/tzdata/Eire b/library/tzdata/Eire
new file mode 100644
index 0000000..c86c91c
--- /dev/null
+++ b/library/tzdata/Eire
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/Dublin)]} {
+ LoadTimeZoneFile Europe/Dublin
+}
+set TZData(:Eire) $TZData(:Europe/Dublin)
diff --git a/library/tzdata/Etc/GMT b/library/tzdata/Etc/GMT
new file mode 100644
index 0000000..7454fd5
--- /dev/null
+++ b/library/tzdata/Etc/GMT
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT) {
+ {-9223372036854775808 0 0 GMT}
+}
diff --git a/library/tzdata/Etc/GMT+0 b/library/tzdata/Etc/GMT+0
new file mode 100644
index 0000000..017dee1
--- /dev/null
+++ b/library/tzdata/Etc/GMT+0
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Etc/GMT)]} {
+ LoadTimeZoneFile Etc/GMT
+}
+set TZData(:Etc/GMT+0) $TZData(:Etc/GMT)
diff --git a/library/tzdata/Etc/GMT+1 b/library/tzdata/Etc/GMT+1
new file mode 100644
index 0000000..12f97ba
--- /dev/null
+++ b/library/tzdata/Etc/GMT+1
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT+1) {
+ {-9223372036854775808 -3600 0 GMT+1}
+}
diff --git a/library/tzdata/Etc/GMT+10 b/library/tzdata/Etc/GMT+10
new file mode 100644
index 0000000..6ea50bb
--- /dev/null
+++ b/library/tzdata/Etc/GMT+10
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT+10) {
+ {-9223372036854775808 -36000 0 GMT+10}
+}
diff --git a/library/tzdata/Etc/GMT+11 b/library/tzdata/Etc/GMT+11
new file mode 100644
index 0000000..c91b169
--- /dev/null
+++ b/library/tzdata/Etc/GMT+11
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT+11) {
+ {-9223372036854775808 -39600 0 GMT+11}
+}
diff --git a/library/tzdata/Etc/GMT+12 b/library/tzdata/Etc/GMT+12
new file mode 100644
index 0000000..29a4cee
--- /dev/null
+++ b/library/tzdata/Etc/GMT+12
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT+12) {
+ {-9223372036854775808 -43200 0 GMT+12}
+}
diff --git a/library/tzdata/Etc/GMT+2 b/library/tzdata/Etc/GMT+2
new file mode 100644
index 0000000..8c6b526
--- /dev/null
+++ b/library/tzdata/Etc/GMT+2
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT+2) {
+ {-9223372036854775808 -7200 0 GMT+2}
+}
diff --git a/library/tzdata/Etc/GMT+3 b/library/tzdata/Etc/GMT+3
new file mode 100644
index 0000000..862571d
--- /dev/null
+++ b/library/tzdata/Etc/GMT+3
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT+3) {
+ {-9223372036854775808 -10800 0 GMT+3}
+}
diff --git a/library/tzdata/Etc/GMT+4 b/library/tzdata/Etc/GMT+4
new file mode 100644
index 0000000..a933bbc
--- /dev/null
+++ b/library/tzdata/Etc/GMT+4
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT+4) {
+ {-9223372036854775808 -14400 0 GMT+4}
+}
diff --git a/library/tzdata/Etc/GMT+5 b/library/tzdata/Etc/GMT+5
new file mode 100644
index 0000000..80cc25c
--- /dev/null
+++ b/library/tzdata/Etc/GMT+5
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT+5) {
+ {-9223372036854775808 -18000 0 GMT+5}
+}
diff --git a/library/tzdata/Etc/GMT+6 b/library/tzdata/Etc/GMT+6
new file mode 100644
index 0000000..bc57bd6
--- /dev/null
+++ b/library/tzdata/Etc/GMT+6
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT+6) {
+ {-9223372036854775808 -21600 0 GMT+6}
+}
diff --git a/library/tzdata/Etc/GMT+7 b/library/tzdata/Etc/GMT+7
new file mode 100644
index 0000000..d419eb9
--- /dev/null
+++ b/library/tzdata/Etc/GMT+7
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT+7) {
+ {-9223372036854775808 -25200 0 GMT+7}
+}
diff --git a/library/tzdata/Etc/GMT+8 b/library/tzdata/Etc/GMT+8
new file mode 100644
index 0000000..705ad40
--- /dev/null
+++ b/library/tzdata/Etc/GMT+8
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT+8) {
+ {-9223372036854775808 -28800 0 GMT+8}
+}
diff --git a/library/tzdata/Etc/GMT+9 b/library/tzdata/Etc/GMT+9
new file mode 100644
index 0000000..4086639
--- /dev/null
+++ b/library/tzdata/Etc/GMT+9
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT+9) {
+ {-9223372036854775808 -32400 0 GMT+9}
+}
diff --git a/library/tzdata/Etc/GMT-0 b/library/tzdata/Etc/GMT-0
new file mode 100644
index 0000000..d8913d5
--- /dev/null
+++ b/library/tzdata/Etc/GMT-0
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Etc/GMT)]} {
+ LoadTimeZoneFile Etc/GMT
+}
+set TZData(:Etc/GMT-0) $TZData(:Etc/GMT)
diff --git a/library/tzdata/Etc/GMT-1 b/library/tzdata/Etc/GMT-1
new file mode 100644
index 0000000..a44dd1f
--- /dev/null
+++ b/library/tzdata/Etc/GMT-1
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT-1) {
+ {-9223372036854775808 3600 0 GMT-1}
+}
diff --git a/library/tzdata/Etc/GMT-10 b/library/tzdata/Etc/GMT-10
new file mode 100644
index 0000000..1c50d01
--- /dev/null
+++ b/library/tzdata/Etc/GMT-10
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT-10) {
+ {-9223372036854775808 36000 0 GMT-10}
+}
diff --git a/library/tzdata/Etc/GMT-11 b/library/tzdata/Etc/GMT-11
new file mode 100644
index 0000000..d07710f
--- /dev/null
+++ b/library/tzdata/Etc/GMT-11
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT-11) {
+ {-9223372036854775808 39600 0 GMT-11}
+}
diff --git a/library/tzdata/Etc/GMT-12 b/library/tzdata/Etc/GMT-12
new file mode 100644
index 0000000..a23b98d
--- /dev/null
+++ b/library/tzdata/Etc/GMT-12
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT-12) {
+ {-9223372036854775808 43200 0 GMT-12}
+}
diff --git a/library/tzdata/Etc/GMT-13 b/library/tzdata/Etc/GMT-13
new file mode 100644
index 0000000..1a6700a
--- /dev/null
+++ b/library/tzdata/Etc/GMT-13
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT-13) {
+ {-9223372036854775808 46800 0 GMT-13}
+}
diff --git a/library/tzdata/Etc/GMT-14 b/library/tzdata/Etc/GMT-14
new file mode 100644
index 0000000..3707e21
--- /dev/null
+++ b/library/tzdata/Etc/GMT-14
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT-14) {
+ {-9223372036854775808 50400 0 GMT-14}
+}
diff --git a/library/tzdata/Etc/GMT-2 b/library/tzdata/Etc/GMT-2
new file mode 100644
index 0000000..f9dea16
--- /dev/null
+++ b/library/tzdata/Etc/GMT-2
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT-2) {
+ {-9223372036854775808 7200 0 GMT-2}
+}
diff --git a/library/tzdata/Etc/GMT-3 b/library/tzdata/Etc/GMT-3
new file mode 100644
index 0000000..99145b8
--- /dev/null
+++ b/library/tzdata/Etc/GMT-3
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT-3) {
+ {-9223372036854775808 10800 0 GMT-3}
+}
diff --git a/library/tzdata/Etc/GMT-4 b/library/tzdata/Etc/GMT-4
new file mode 100644
index 0000000..27b4fec
--- /dev/null
+++ b/library/tzdata/Etc/GMT-4
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT-4) {
+ {-9223372036854775808 14400 0 GMT-4}
+}
diff --git a/library/tzdata/Etc/GMT-5 b/library/tzdata/Etc/GMT-5
new file mode 100644
index 0000000..dbe3df7
--- /dev/null
+++ b/library/tzdata/Etc/GMT-5
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT-5) {
+ {-9223372036854775808 18000 0 GMT-5}
+}
diff --git a/library/tzdata/Etc/GMT-6 b/library/tzdata/Etc/GMT-6
new file mode 100644
index 0000000..414dbfa
--- /dev/null
+++ b/library/tzdata/Etc/GMT-6
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT-6) {
+ {-9223372036854775808 21600 0 GMT-6}
+}
diff --git a/library/tzdata/Etc/GMT-7 b/library/tzdata/Etc/GMT-7
new file mode 100644
index 0000000..2bd59db
--- /dev/null
+++ b/library/tzdata/Etc/GMT-7
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT-7) {
+ {-9223372036854775808 25200 0 GMT-7}
+}
diff --git a/library/tzdata/Etc/GMT-8 b/library/tzdata/Etc/GMT-8
new file mode 100644
index 0000000..7303721
--- /dev/null
+++ b/library/tzdata/Etc/GMT-8
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT-8) {
+ {-9223372036854775808 28800 0 GMT-8}
+}
diff --git a/library/tzdata/Etc/GMT-9 b/library/tzdata/Etc/GMT-9
new file mode 100644
index 0000000..46e6878
--- /dev/null
+++ b/library/tzdata/Etc/GMT-9
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/GMT-9) {
+ {-9223372036854775808 32400 0 GMT-9}
+}
diff --git a/library/tzdata/Etc/GMT0 b/library/tzdata/Etc/GMT0
new file mode 100644
index 0000000..dba1fe9
--- /dev/null
+++ b/library/tzdata/Etc/GMT0
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Etc/GMT)]} {
+ LoadTimeZoneFile Etc/GMT
+}
+set TZData(:Etc/GMT0) $TZData(:Etc/GMT)
diff --git a/library/tzdata/Etc/Greenwich b/library/tzdata/Etc/Greenwich
new file mode 100644
index 0000000..53acea0
--- /dev/null
+++ b/library/tzdata/Etc/Greenwich
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Etc/GMT)]} {
+ LoadTimeZoneFile Etc/GMT
+}
+set TZData(:Etc/Greenwich) $TZData(:Etc/GMT)
diff --git a/library/tzdata/Etc/UCT b/library/tzdata/Etc/UCT
new file mode 100644
index 0000000..f7d795e
--- /dev/null
+++ b/library/tzdata/Etc/UCT
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/UCT) {
+ {-9223372036854775808 0 0 UCT}
+}
diff --git a/library/tzdata/Etc/UTC b/library/tzdata/Etc/UTC
new file mode 100644
index 0000000..db5954b
--- /dev/null
+++ b/library/tzdata/Etc/UTC
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Etc/UTC) {
+ {-9223372036854775808 0 0 UTC}
+}
diff --git a/library/tzdata/Etc/Universal b/library/tzdata/Etc/Universal
new file mode 100644
index 0000000..a3b7547
--- /dev/null
+++ b/library/tzdata/Etc/Universal
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Etc/UTC)]} {
+ LoadTimeZoneFile Etc/UTC
+}
+set TZData(:Etc/Universal) $TZData(:Etc/UTC)
diff --git a/library/tzdata/Etc/Zulu b/library/tzdata/Etc/Zulu
new file mode 100644
index 0000000..f643db9
--- /dev/null
+++ b/library/tzdata/Etc/Zulu
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Etc/UTC)]} {
+ LoadTimeZoneFile Etc/UTC
+}
+set TZData(:Etc/Zulu) $TZData(:Etc/UTC)
diff --git a/library/tzdata/Europe/Amsterdam b/library/tzdata/Europe/Amsterdam
new file mode 100644
index 0000000..bd89127
--- /dev/null
+++ b/library/tzdata/Europe/Amsterdam
@@ -0,0 +1,310 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Amsterdam) {
+ {-9223372036854775808 1172 0 LMT}
+ {-4260212372 1172 0 AMT}
+ {-1693700372 4772 1 NST}
+ {-1680484772 1172 0 AMT}
+ {-1663453172 4772 1 NST}
+ {-1650147572 1172 0 AMT}
+ {-1633213172 4772 1 NST}
+ {-1617488372 1172 0 AMT}
+ {-1601158772 4772 1 NST}
+ {-1586038772 1172 0 AMT}
+ {-1569709172 4772 1 NST}
+ {-1554589172 1172 0 AMT}
+ {-1538259572 4772 1 NST}
+ {-1523139572 1172 0 AMT}
+ {-1507501172 4772 1 NST}
+ {-1490566772 1172 0 AMT}
+ {-1470176372 4772 1 NST}
+ {-1459117172 1172 0 AMT}
+ {-1443997172 4772 1 NST}
+ {-1427667572 1172 0 AMT}
+ {-1406672372 4772 1 NST}
+ {-1396217972 1172 0 AMT}
+ {-1376950772 4772 1 NST}
+ {-1364768372 1172 0 AMT}
+ {-1345414772 4772 1 NST}
+ {-1333318772 1172 0 AMT}
+ {-1313792372 4772 1 NST}
+ {-1301264372 1172 0 AMT}
+ {-1282256372 4772 1 NST}
+ {-1269814772 1172 0 AMT}
+ {-1250720372 4772 1 NST}
+ {-1238365172 1172 0 AMT}
+ {-1219184372 4772 1 NST}
+ {-1206915572 1172 0 AMT}
+ {-1186957172 4772 1 NST}
+ {-1175465972 1172 0 AMT}
+ {-1156025972 4772 1 NST}
+ {-1143411572 1172 0 AMT}
+ {-1124489972 4772 1 NST}
+ {-1111961972 1172 0 AMT}
+ {-1092953972 4772 1 NST}
+ {-1080512372 1172 0 AMT}
+ {-1061331572 4772 1 NST}
+ {-1049062772 1172 0 AMT}
+ {-1029190772 4772 1 NST}
+ {-1025741972 4800 0 NEST}
+ {-1017613200 1200 0 NET}
+ {-998259600 4800 1 NEST}
+ {-986163600 1200 0 NET}
+ {-966723600 4800 1 NEST}
+ {-954109200 1200 0 NET}
+ {-935022000 7200 0 CEST}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-796777200 3600 0 CET}
+ {-781052400 7200 0 CEST}
+ {-766623600 3600 0 CET}
+ {220921200 3600 0 CET}
+ {228877200 7200 1 CEST}
+ {243997200 3600 0 CET}
+ {260326800 7200 1 CEST}
+ {276051600 3600 0 CET}
+ {291776400 7200 1 CEST}
+ {307501200 3600 0 CET}
+ {323830800 7200 1 CEST}
+ {338950800 3600 0 CET}
+ {354675600 7200 1 CEST}
+ {370400400 3600 0 CET}
+ {386125200 7200 1 CEST}
+ {401850000 3600 0 CET}
+ {417574800 7200 1 CEST}
+ {433299600 3600 0 CET}
+ {449024400 7200 1 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Andorra b/library/tzdata/Europe/Andorra
new file mode 100644
index 0000000..89233fe
--- /dev/null
+++ b/library/tzdata/Europe/Andorra
@@ -0,0 +1,237 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Andorra) {
+ {-9223372036854775808 364 0 LMT}
+ {-2177453164 0 0 WET}
+ {-733881600 3600 0 CET}
+ {481078800 7200 0 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Athens b/library/tzdata/Europe/Athens
new file mode 100644
index 0000000..f8df408
--- /dev/null
+++ b/library/tzdata/Europe/Athens
@@ -0,0 +1,268 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Athens) {
+ {-9223372036854775808 5692 0 LMT}
+ {-2344642492 5692 0 AMT}
+ {-1686101632 7200 0 EET}
+ {-1182996000 10800 1 EEST}
+ {-1178161200 7200 0 EET}
+ {-906861600 10800 1 EEST}
+ {-904878000 7200 0 CEST}
+ {-857257200 3600 0 CET}
+ {-844477200 7200 1 CEST}
+ {-828237600 3600 0 CET}
+ {-812422800 7200 0 EET}
+ {-552362400 10800 1 EEST}
+ {-541652400 7200 0 EET}
+ {166485600 10800 1 EEST}
+ {186184800 7200 0 EET}
+ {198028800 10800 1 EEST}
+ {213753600 7200 0 EET}
+ {228873600 10800 1 EEST}
+ {244080000 7200 0 EET}
+ {260323200 10800 1 EEST}
+ {275446800 7200 0 EET}
+ {291798000 10800 1 EEST}
+ {307407600 7200 0 EET}
+ {323388000 10800 1 EEST}
+ {338936400 7200 0 EET}
+ {347148000 7200 0 EET}
+ {354675600 10800 1 EEST}
+ {370400400 7200 0 EET}
+ {386125200 10800 1 EEST}
+ {401850000 7200 0 EET}
+ {417574800 10800 1 EEST}
+ {433299600 7200 0 EET}
+ {449024400 10800 1 EEST}
+ {465354000 7200 0 EET}
+ {481078800 10800 1 EEST}
+ {496803600 7200 0 EET}
+ {512528400 10800 1 EEST}
+ {528253200 7200 0 EET}
+ {543978000 10800 1 EEST}
+ {559702800 7200 0 EET}
+ {575427600 10800 1 EEST}
+ {591152400 7200 0 EET}
+ {606877200 10800 1 EEST}
+ {622602000 7200 0 EET}
+ {638326800 10800 1 EEST}
+ {654656400 7200 0 EET}
+ {670381200 10800 1 EEST}
+ {686106000 7200 0 EET}
+ {701830800 10800 1 EEST}
+ {717555600 7200 0 EET}
+ {733280400 10800 1 EEST}
+ {749005200 7200 0 EET}
+ {764730000 10800 1 EEST}
+ {780454800 7200 0 EET}
+ {796179600 10800 1 EEST}
+ {811904400 7200 0 EET}
+ {828234000 10800 1 EEST}
+ {846378000 7200 0 EET}
+ {859683600 10800 1 EEST}
+ {877827600 7200 0 EET}
+ {891133200 10800 1 EEST}
+ {909277200 7200 0 EET}
+ {922582800 10800 1 EEST}
+ {941331600 7200 0 EET}
+ {954032400 10800 1 EEST}
+ {972781200 7200 0 EET}
+ {985482000 10800 1 EEST}
+ {1004230800 7200 0 EET}
+ {1017536400 10800 1 EEST}
+ {1035680400 7200 0 EET}
+ {1048986000 10800 1 EEST}
+ {1067130000 7200 0 EET}
+ {1080435600 10800 1 EEST}
+ {1099184400 7200 0 EET}
+ {1111885200 10800 1 EEST}
+ {1130634000 7200 0 EET}
+ {1143334800 10800 1 EEST}
+ {1162083600 7200 0 EET}
+ {1174784400 10800 1 EEST}
+ {1193533200 7200 0 EET}
+ {1206838800 10800 1 EEST}
+ {1224982800 7200 0 EET}
+ {1238288400 10800 1 EEST}
+ {1256432400 7200 0 EET}
+ {1269738000 10800 1 EEST}
+ {1288486800 7200 0 EET}
+ {1301187600 10800 1 EEST}
+ {1319936400 7200 0 EET}
+ {1332637200 10800 1 EEST}
+ {1351386000 7200 0 EET}
+ {1364691600 10800 1 EEST}
+ {1382835600 7200 0 EET}
+ {1396141200 10800 1 EEST}
+ {1414285200 7200 0 EET}
+ {1427590800 10800 1 EEST}
+ {1445734800 7200 0 EET}
+ {1459040400 10800 1 EEST}
+ {1477789200 7200 0 EET}
+ {1490490000 10800 1 EEST}
+ {1509238800 7200 0 EET}
+ {1521939600 10800 1 EEST}
+ {1540688400 7200 0 EET}
+ {1553994000 10800 1 EEST}
+ {1572138000 7200 0 EET}
+ {1585443600 10800 1 EEST}
+ {1603587600 7200 0 EET}
+ {1616893200 10800 1 EEST}
+ {1635642000 7200 0 EET}
+ {1648342800 10800 1 EEST}
+ {1667091600 7200 0 EET}
+ {1679792400 10800 1 EEST}
+ {1698541200 7200 0 EET}
+ {1711846800 10800 1 EEST}
+ {1729990800 7200 0 EET}
+ {1743296400 10800 1 EEST}
+ {1761440400 7200 0 EET}
+ {1774746000 10800 1 EEST}
+ {1792890000 7200 0 EET}
+ {1806195600 10800 1 EEST}
+ {1824944400 7200 0 EET}
+ {1837645200 10800 1 EEST}
+ {1856394000 7200 0 EET}
+ {1869094800 10800 1 EEST}
+ {1887843600 7200 0 EET}
+ {1901149200 10800 1 EEST}
+ {1919293200 7200 0 EET}
+ {1932598800 10800 1 EEST}
+ {1950742800 7200 0 EET}
+ {1964048400 10800 1 EEST}
+ {1982797200 7200 0 EET}
+ {1995498000 10800 1 EEST}
+ {2014246800 7200 0 EET}
+ {2026947600 10800 1 EEST}
+ {2045696400 7200 0 EET}
+ {2058397200 10800 1 EEST}
+ {2077146000 7200 0 EET}
+ {2090451600 10800 1 EEST}
+ {2108595600 7200 0 EET}
+ {2121901200 10800 1 EEST}
+ {2140045200 7200 0 EET}
+ {2153350800 10800 1 EEST}
+ {2172099600 7200 0 EET}
+ {2184800400 10800 1 EEST}
+ {2203549200 7200 0 EET}
+ {2216250000 10800 1 EEST}
+ {2234998800 7200 0 EET}
+ {2248304400 10800 1 EEST}
+ {2266448400 7200 0 EET}
+ {2279754000 10800 1 EEST}
+ {2297898000 7200 0 EET}
+ {2311203600 10800 1 EEST}
+ {2329347600 7200 0 EET}
+ {2342653200 10800 1 EEST}
+ {2361402000 7200 0 EET}
+ {2374102800 10800 1 EEST}
+ {2392851600 7200 0 EET}
+ {2405552400 10800 1 EEST}
+ {2424301200 7200 0 EET}
+ {2437606800 10800 1 EEST}
+ {2455750800 7200 0 EET}
+ {2469056400 10800 1 EEST}
+ {2487200400 7200 0 EET}
+ {2500506000 10800 1 EEST}
+ {2519254800 7200 0 EET}
+ {2531955600 10800 1 EEST}
+ {2550704400 7200 0 EET}
+ {2563405200 10800 1 EEST}
+ {2582154000 7200 0 EET}
+ {2595459600 10800 1 EEST}
+ {2613603600 7200 0 EET}
+ {2626909200 10800 1 EEST}
+ {2645053200 7200 0 EET}
+ {2658358800 10800 1 EEST}
+ {2676502800 7200 0 EET}
+ {2689808400 10800 1 EEST}
+ {2708557200 7200 0 EET}
+ {2721258000 10800 1 EEST}
+ {2740006800 7200 0 EET}
+ {2752707600 10800 1 EEST}
+ {2771456400 7200 0 EET}
+ {2784762000 10800 1 EEST}
+ {2802906000 7200 0 EET}
+ {2816211600 10800 1 EEST}
+ {2834355600 7200 0 EET}
+ {2847661200 10800 1 EEST}
+ {2866410000 7200 0 EET}
+ {2879110800 10800 1 EEST}
+ {2897859600 7200 0 EET}
+ {2910560400 10800 1 EEST}
+ {2929309200 7200 0 EET}
+ {2942010000 10800 1 EEST}
+ {2960758800 7200 0 EET}
+ {2974064400 10800 1 EEST}
+ {2992208400 7200 0 EET}
+ {3005514000 10800 1 EEST}
+ {3023658000 7200 0 EET}
+ {3036963600 10800 1 EEST}
+ {3055712400 7200 0 EET}
+ {3068413200 10800 1 EEST}
+ {3087162000 7200 0 EET}
+ {3099862800 10800 1 EEST}
+ {3118611600 7200 0 EET}
+ {3131917200 10800 1 EEST}
+ {3150061200 7200 0 EET}
+ {3163366800 10800 1 EEST}
+ {3181510800 7200 0 EET}
+ {3194816400 10800 1 EEST}
+ {3212960400 7200 0 EET}
+ {3226266000 10800 1 EEST}
+ {3245014800 7200 0 EET}
+ {3257715600 10800 1 EEST}
+ {3276464400 7200 0 EET}
+ {3289165200 10800 1 EEST}
+ {3307914000 7200 0 EET}
+ {3321219600 10800 1 EEST}
+ {3339363600 7200 0 EET}
+ {3352669200 10800 1 EEST}
+ {3370813200 7200 0 EET}
+ {3384118800 10800 1 EEST}
+ {3402867600 7200 0 EET}
+ {3415568400 10800 1 EEST}
+ {3434317200 7200 0 EET}
+ {3447018000 10800 1 EEST}
+ {3465766800 7200 0 EET}
+ {3479072400 10800 1 EEST}
+ {3497216400 7200 0 EET}
+ {3510522000 10800 1 EEST}
+ {3528666000 7200 0 EET}
+ {3541971600 10800 1 EEST}
+ {3560115600 7200 0 EET}
+ {3573421200 10800 1 EEST}
+ {3592170000 7200 0 EET}
+ {3604870800 10800 1 EEST}
+ {3623619600 7200 0 EET}
+ {3636320400 10800 1 EEST}
+ {3655069200 7200 0 EET}
+ {3668374800 10800 1 EEST}
+ {3686518800 7200 0 EET}
+ {3699824400 10800 1 EEST}
+ {3717968400 7200 0 EET}
+ {3731274000 10800 1 EEST}
+ {3750022800 7200 0 EET}
+ {3762723600 10800 1 EEST}
+ {3781472400 7200 0 EET}
+ {3794173200 10800 1 EEST}
+ {3812922000 7200 0 EET}
+ {3825622800 10800 1 EEST}
+ {3844371600 7200 0 EET}
+ {3857677200 10800 1 EEST}
+ {3875821200 7200 0 EET}
+ {3889126800 10800 1 EEST}
+ {3907270800 7200 0 EET}
+ {3920576400 10800 1 EEST}
+ {3939325200 7200 0 EET}
+ {3952026000 10800 1 EEST}
+ {3970774800 7200 0 EET}
+ {3983475600 10800 1 EEST}
+ {4002224400 7200 0 EET}
+ {4015530000 10800 1 EEST}
+ {4033674000 7200 0 EET}
+ {4046979600 10800 1 EEST}
+ {4065123600 7200 0 EET}
+ {4078429200 10800 1 EEST}
+ {4096573200 7200 0 EET}
+}
diff --git a/library/tzdata/Europe/Belfast b/library/tzdata/Europe/Belfast
new file mode 100644
index 0000000..51cd3ce
--- /dev/null
+++ b/library/tzdata/Europe/Belfast
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/London)]} {
+ LoadTimeZoneFile Europe/London
+}
+set TZData(:Europe/Belfast) $TZData(:Europe/London)
diff --git a/library/tzdata/Europe/Belgrade b/library/tzdata/Europe/Belgrade
new file mode 100644
index 0000000..b11f7b3
--- /dev/null
+++ b/library/tzdata/Europe/Belgrade
@@ -0,0 +1,250 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Belgrade) {
+ {-9223372036854775808 4920 0 LMT}
+ {-2713915320 3600 0 CET}
+ {-905824800 3600 0 CET}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-796777200 3600 0 CET}
+ {-788922000 3600 0 CET}
+ {-777942000 7200 1 CEST}
+ {-766623600 3600 0 CET}
+ {407199600 3600 0 CET}
+ {417574800 7200 1 CEST}
+ {433299600 3600 0 CET}
+ {449024400 7200 1 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Berlin b/library/tzdata/Europe/Berlin
new file mode 100644
index 0000000..5469cf6
--- /dev/null
+++ b/library/tzdata/Europe/Berlin
@@ -0,0 +1,274 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Berlin) {
+ {-9223372036854775808 3208 0 LMT}
+ {-2422054408 3600 0 CET}
+ {-1693706400 7200 1 CEST}
+ {-1680483600 3600 0 CET}
+ {-1663455600 7200 1 CEST}
+ {-1650150000 3600 0 CET}
+ {-1632006000 7200 1 CEST}
+ {-1618700400 3600 0 CET}
+ {-938905200 7200 1 CEST}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-796777200 3600 0 CET}
+ {-781052400 7200 1 CEST}
+ {-776559600 10800 0 CEMT}
+ {-765936000 7200 1 CEST}
+ {-761180400 3600 0 CET}
+ {-757386000 3600 0 CET}
+ {-748479600 7200 1 CEST}
+ {-733273200 3600 0 CET}
+ {-717631200 7200 1 CEST}
+ {-714610800 10800 1 CEMT}
+ {-710380800 7200 1 CEST}
+ {-701910000 3600 0 CET}
+ {-684975600 7200 1 CEST}
+ {-670460400 3600 0 CET}
+ {-654130800 7200 1 CEST}
+ {-639010800 3600 0 CET}
+ {315529200 3600 0 CET}
+ {323830800 7200 1 CEST}
+ {338950800 3600 0 CET}
+ {354675600 7200 1 CEST}
+ {370400400 3600 0 CET}
+ {386125200 7200 1 CEST}
+ {401850000 3600 0 CET}
+ {417574800 7200 1 CEST}
+ {433299600 3600 0 CET}
+ {449024400 7200 1 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Bratislava b/library/tzdata/Europe/Bratislava
new file mode 100644
index 0000000..d65ea5a
--- /dev/null
+++ b/library/tzdata/Europe/Bratislava
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/Prague)]} {
+ LoadTimeZoneFile Europe/Prague
+}
+set TZData(:Europe/Bratislava) $TZData(:Europe/Prague)
diff --git a/library/tzdata/Europe/Brussels b/library/tzdata/Europe/Brussels
new file mode 100644
index 0000000..3cb9b14
--- /dev/null
+++ b/library/tzdata/Europe/Brussels
@@ -0,0 +1,316 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Brussels) {
+ {-9223372036854775808 1050 0 LMT}
+ {-2840141850 1050 0 BMT}
+ {-2450953050 0 0 WET}
+ {-1740355200 3600 0 CET}
+ {-1693702800 7200 0 CEST}
+ {-1680483600 3600 0 CET}
+ {-1663455600 7200 1 CEST}
+ {-1650150000 3600 0 CET}
+ {-1632006000 7200 1 CEST}
+ {-1618700400 3600 0 CET}
+ {-1613826000 0 0 WET}
+ {-1604278800 3600 1 WEST}
+ {-1585530000 0 0 WET}
+ {-1574038800 3600 1 WEST}
+ {-1552266000 0 0 WET}
+ {-1539997200 3600 1 WEST}
+ {-1520557200 0 0 WET}
+ {-1507510800 3600 1 WEST}
+ {-1490576400 0 0 WET}
+ {-1473642000 3600 1 WEST}
+ {-1459126800 0 0 WET}
+ {-1444006800 3600 1 WEST}
+ {-1427677200 0 0 WET}
+ {-1411952400 3600 1 WEST}
+ {-1396227600 0 0 WET}
+ {-1379293200 3600 1 WEST}
+ {-1364778000 0 0 WET}
+ {-1348448400 3600 1 WEST}
+ {-1333328400 0 0 WET}
+ {-1316394000 3600 1 WEST}
+ {-1301263200 0 0 WET}
+ {-1284328800 3600 1 WEST}
+ {-1269813600 0 0 WET}
+ {-1253484000 3600 1 WEST}
+ {-1238364000 0 0 WET}
+ {-1221429600 3600 1 WEST}
+ {-1206914400 0 0 WET}
+ {-1191189600 3600 1 WEST}
+ {-1175464800 0 0 WET}
+ {-1160344800 3600 1 WEST}
+ {-1143410400 0 0 WET}
+ {-1127685600 3600 1 WEST}
+ {-1111960800 0 0 WET}
+ {-1096840800 3600 1 WEST}
+ {-1080511200 0 0 WET}
+ {-1063576800 3600 1 WEST}
+ {-1049061600 0 0 WET}
+ {-1033336800 3600 1 WEST}
+ {-1017612000 0 0 WET}
+ {-1002492000 3600 1 WEST}
+ {-986162400 0 0 WET}
+ {-969228000 3600 1 WEST}
+ {-950479200 0 0 WET}
+ {-942012000 3600 1 WEST}
+ {-934668000 7200 0 CEST}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-799290000 3600 0 CET}
+ {-798073200 3600 0 CET}
+ {-781052400 7200 1 CEST}
+ {-766623600 3600 0 CET}
+ {-745455600 7200 1 CEST}
+ {-733273200 3600 0 CET}
+ {220921200 3600 0 CET}
+ {228877200 7200 1 CEST}
+ {243997200 3600 0 CET}
+ {260326800 7200 1 CEST}
+ {276051600 3600 0 CET}
+ {291776400 7200 1 CEST}
+ {307501200 3600 0 CET}
+ {323830800 7200 1 CEST}
+ {338950800 3600 0 CET}
+ {354675600 7200 1 CEST}
+ {370400400 3600 0 CET}
+ {386125200 7200 1 CEST}
+ {401850000 3600 0 CET}
+ {417574800 7200 1 CEST}
+ {433299600 3600 0 CET}
+ {449024400 7200 1 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Bucharest b/library/tzdata/Europe/Bucharest
new file mode 100644
index 0000000..7b3bed4
--- /dev/null
+++ b/library/tzdata/Europe/Bucharest
@@ -0,0 +1,268 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Bucharest) {
+ {-9223372036854775808 6264 0 LMT}
+ {-2469404664 6264 0 BMT}
+ {-1213148664 7200 0 EET}
+ {-1187056800 10800 1 EEST}
+ {-1175479200 7200 0 EET}
+ {-1159754400 10800 1 EEST}
+ {-1144029600 7200 0 EET}
+ {-1127700000 10800 1 EEST}
+ {-1111975200 7200 0 EET}
+ {-1096250400 10800 1 EEST}
+ {-1080525600 7200 0 EET}
+ {-1064800800 10800 1 EEST}
+ {-1049076000 7200 0 EET}
+ {-1033351200 10800 1 EEST}
+ {-1017626400 7200 0 EET}
+ {-1001901600 10800 1 EEST}
+ {-986176800 7200 0 EET}
+ {-970452000 10800 1 EEST}
+ {-954727200 7200 0 EET}
+ {296604000 10800 1 EEST}
+ {307486800 7200 0 EET}
+ {323816400 10800 1 EEST}
+ {338940000 7200 0 EET}
+ {354672000 10800 0 EEST}
+ {370396800 7200 0 EET}
+ {386121600 10800 1 EEST}
+ {401846400 7200 0 EET}
+ {417571200 10800 1 EEST}
+ {433296000 7200 0 EET}
+ {449020800 10800 1 EEST}
+ {465350400 7200 0 EET}
+ {481075200 10800 1 EEST}
+ {496800000 7200 0 EET}
+ {512524800 10800 1 EEST}
+ {528249600 7200 0 EET}
+ {543974400 10800 1 EEST}
+ {559699200 7200 0 EET}
+ {575424000 10800 1 EEST}
+ {591148800 7200 0 EET}
+ {606873600 10800 1 EEST}
+ {622598400 7200 0 EET}
+ {638323200 10800 1 EEST}
+ {654652800 7200 0 EET}
+ {662680800 7200 0 EET}
+ {670370400 10800 1 EEST}
+ {686095200 7200 0 EET}
+ {701820000 10800 1 EEST}
+ {717544800 7200 0 EET}
+ {733269600 10800 1 EEST}
+ {748994400 7200 0 EET}
+ {757375200 7200 0 EET}
+ {764719200 10800 1 EEST}
+ {780440400 7200 0 EET}
+ {796168800 10800 1 EEST}
+ {811890000 7200 0 EET}
+ {828223200 10800 1 EEST}
+ {846363600 7200 0 EET}
+ {852069600 7200 0 EET}
+ {859683600 10800 1 EEST}
+ {877827600 7200 0 EET}
+ {891133200 10800 1 EEST}
+ {909277200 7200 0 EET}
+ {922582800 10800 1 EEST}
+ {941331600 7200 0 EET}
+ {954032400 10800 1 EEST}
+ {972781200 7200 0 EET}
+ {985482000 10800 1 EEST}
+ {1004230800 7200 0 EET}
+ {1017536400 10800 1 EEST}
+ {1035680400 7200 0 EET}
+ {1048986000 10800 1 EEST}
+ {1067130000 7200 0 EET}
+ {1080435600 10800 1 EEST}
+ {1099184400 7200 0 EET}
+ {1111885200 10800 1 EEST}
+ {1130634000 7200 0 EET}
+ {1143334800 10800 1 EEST}
+ {1162083600 7200 0 EET}
+ {1174784400 10800 1 EEST}
+ {1193533200 7200 0 EET}
+ {1206838800 10800 1 EEST}
+ {1224982800 7200 0 EET}
+ {1238288400 10800 1 EEST}
+ {1256432400 7200 0 EET}
+ {1269738000 10800 1 EEST}
+ {1288486800 7200 0 EET}
+ {1301187600 10800 1 EEST}
+ {1319936400 7200 0 EET}
+ {1332637200 10800 1 EEST}
+ {1351386000 7200 0 EET}
+ {1364691600 10800 1 EEST}
+ {1382835600 7200 0 EET}
+ {1396141200 10800 1 EEST}
+ {1414285200 7200 0 EET}
+ {1427590800 10800 1 EEST}
+ {1445734800 7200 0 EET}
+ {1459040400 10800 1 EEST}
+ {1477789200 7200 0 EET}
+ {1490490000 10800 1 EEST}
+ {1509238800 7200 0 EET}
+ {1521939600 10800 1 EEST}
+ {1540688400 7200 0 EET}
+ {1553994000 10800 1 EEST}
+ {1572138000 7200 0 EET}
+ {1585443600 10800 1 EEST}
+ {1603587600 7200 0 EET}
+ {1616893200 10800 1 EEST}
+ {1635642000 7200 0 EET}
+ {1648342800 10800 1 EEST}
+ {1667091600 7200 0 EET}
+ {1679792400 10800 1 EEST}
+ {1698541200 7200 0 EET}
+ {1711846800 10800 1 EEST}
+ {1729990800 7200 0 EET}
+ {1743296400 10800 1 EEST}
+ {1761440400 7200 0 EET}
+ {1774746000 10800 1 EEST}
+ {1792890000 7200 0 EET}
+ {1806195600 10800 1 EEST}
+ {1824944400 7200 0 EET}
+ {1837645200 10800 1 EEST}
+ {1856394000 7200 0 EET}
+ {1869094800 10800 1 EEST}
+ {1887843600 7200 0 EET}
+ {1901149200 10800 1 EEST}
+ {1919293200 7200 0 EET}
+ {1932598800 10800 1 EEST}
+ {1950742800 7200 0 EET}
+ {1964048400 10800 1 EEST}
+ {1982797200 7200 0 EET}
+ {1995498000 10800 1 EEST}
+ {2014246800 7200 0 EET}
+ {2026947600 10800 1 EEST}
+ {2045696400 7200 0 EET}
+ {2058397200 10800 1 EEST}
+ {2077146000 7200 0 EET}
+ {2090451600 10800 1 EEST}
+ {2108595600 7200 0 EET}
+ {2121901200 10800 1 EEST}
+ {2140045200 7200 0 EET}
+ {2153350800 10800 1 EEST}
+ {2172099600 7200 0 EET}
+ {2184800400 10800 1 EEST}
+ {2203549200 7200 0 EET}
+ {2216250000 10800 1 EEST}
+ {2234998800 7200 0 EET}
+ {2248304400 10800 1 EEST}
+ {2266448400 7200 0 EET}
+ {2279754000 10800 1 EEST}
+ {2297898000 7200 0 EET}
+ {2311203600 10800 1 EEST}
+ {2329347600 7200 0 EET}
+ {2342653200 10800 1 EEST}
+ {2361402000 7200 0 EET}
+ {2374102800 10800 1 EEST}
+ {2392851600 7200 0 EET}
+ {2405552400 10800 1 EEST}
+ {2424301200 7200 0 EET}
+ {2437606800 10800 1 EEST}
+ {2455750800 7200 0 EET}
+ {2469056400 10800 1 EEST}
+ {2487200400 7200 0 EET}
+ {2500506000 10800 1 EEST}
+ {2519254800 7200 0 EET}
+ {2531955600 10800 1 EEST}
+ {2550704400 7200 0 EET}
+ {2563405200 10800 1 EEST}
+ {2582154000 7200 0 EET}
+ {2595459600 10800 1 EEST}
+ {2613603600 7200 0 EET}
+ {2626909200 10800 1 EEST}
+ {2645053200 7200 0 EET}
+ {2658358800 10800 1 EEST}
+ {2676502800 7200 0 EET}
+ {2689808400 10800 1 EEST}
+ {2708557200 7200 0 EET}
+ {2721258000 10800 1 EEST}
+ {2740006800 7200 0 EET}
+ {2752707600 10800 1 EEST}
+ {2771456400 7200 0 EET}
+ {2784762000 10800 1 EEST}
+ {2802906000 7200 0 EET}
+ {2816211600 10800 1 EEST}
+ {2834355600 7200 0 EET}
+ {2847661200 10800 1 EEST}
+ {2866410000 7200 0 EET}
+ {2879110800 10800 1 EEST}
+ {2897859600 7200 0 EET}
+ {2910560400 10800 1 EEST}
+ {2929309200 7200 0 EET}
+ {2942010000 10800 1 EEST}
+ {2960758800 7200 0 EET}
+ {2974064400 10800 1 EEST}
+ {2992208400 7200 0 EET}
+ {3005514000 10800 1 EEST}
+ {3023658000 7200 0 EET}
+ {3036963600 10800 1 EEST}
+ {3055712400 7200 0 EET}
+ {3068413200 10800 1 EEST}
+ {3087162000 7200 0 EET}
+ {3099862800 10800 1 EEST}
+ {3118611600 7200 0 EET}
+ {3131917200 10800 1 EEST}
+ {3150061200 7200 0 EET}
+ {3163366800 10800 1 EEST}
+ {3181510800 7200 0 EET}
+ {3194816400 10800 1 EEST}
+ {3212960400 7200 0 EET}
+ {3226266000 10800 1 EEST}
+ {3245014800 7200 0 EET}
+ {3257715600 10800 1 EEST}
+ {3276464400 7200 0 EET}
+ {3289165200 10800 1 EEST}
+ {3307914000 7200 0 EET}
+ {3321219600 10800 1 EEST}
+ {3339363600 7200 0 EET}
+ {3352669200 10800 1 EEST}
+ {3370813200 7200 0 EET}
+ {3384118800 10800 1 EEST}
+ {3402867600 7200 0 EET}
+ {3415568400 10800 1 EEST}
+ {3434317200 7200 0 EET}
+ {3447018000 10800 1 EEST}
+ {3465766800 7200 0 EET}
+ {3479072400 10800 1 EEST}
+ {3497216400 7200 0 EET}
+ {3510522000 10800 1 EEST}
+ {3528666000 7200 0 EET}
+ {3541971600 10800 1 EEST}
+ {3560115600 7200 0 EET}
+ {3573421200 10800 1 EEST}
+ {3592170000 7200 0 EET}
+ {3604870800 10800 1 EEST}
+ {3623619600 7200 0 EET}
+ {3636320400 10800 1 EEST}
+ {3655069200 7200 0 EET}
+ {3668374800 10800 1 EEST}
+ {3686518800 7200 0 EET}
+ {3699824400 10800 1 EEST}
+ {3717968400 7200 0 EET}
+ {3731274000 10800 1 EEST}
+ {3750022800 7200 0 EET}
+ {3762723600 10800 1 EEST}
+ {3781472400 7200 0 EET}
+ {3794173200 10800 1 EEST}
+ {3812922000 7200 0 EET}
+ {3825622800 10800 1 EEST}
+ {3844371600 7200 0 EET}
+ {3857677200 10800 1 EEST}
+ {3875821200 7200 0 EET}
+ {3889126800 10800 1 EEST}
+ {3907270800 7200 0 EET}
+ {3920576400 10800 1 EEST}
+ {3939325200 7200 0 EET}
+ {3952026000 10800 1 EEST}
+ {3970774800 7200 0 EET}
+ {3983475600 10800 1 EEST}
+ {4002224400 7200 0 EET}
+ {4015530000 10800 1 EEST}
+ {4033674000 7200 0 EET}
+ {4046979600 10800 1 EEST}
+ {4065123600 7200 0 EET}
+ {4078429200 10800 1 EEST}
+ {4096573200 7200 0 EET}
+}
diff --git a/library/tzdata/Europe/Budapest b/library/tzdata/Europe/Budapest
new file mode 100644
index 0000000..fd41acc
--- /dev/null
+++ b/library/tzdata/Europe/Budapest
@@ -0,0 +1,284 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Budapest) {
+ {-9223372036854775808 4580 0 LMT}
+ {-2500938980 3600 0 CET}
+ {-1693706400 7200 1 CEST}
+ {-1680483600 3600 0 CET}
+ {-1663455600 7200 1 CEST}
+ {-1650150000 3600 0 CET}
+ {-1640998800 3600 0 CET}
+ {-1633212000 7200 1 CEST}
+ {-1617577200 3600 0 CET}
+ {-1600466400 7200 1 CEST}
+ {-1587250800 3600 0 CET}
+ {-1569708000 7200 1 CEST}
+ {-1554332400 3600 0 CET}
+ {-906937200 3600 0 CET}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-796777200 3600 0 CET}
+ {-788922000 3600 0 CET}
+ {-778471200 7200 1 CEST}
+ {-762487200 3600 0 CET}
+ {-749689200 7200 1 CEST}
+ {-733359600 3600 0 CET}
+ {-717634800 7200 1 CEST}
+ {-701910000 3600 0 CET}
+ {-686185200 7200 1 CEST}
+ {-670460400 3600 0 CET}
+ {-654130800 7200 1 CEST}
+ {-639010800 3600 0 CET}
+ {-621990000 7200 1 CEST}
+ {-605660400 3600 0 CET}
+ {-492656400 7200 1 CEST}
+ {-481168800 3600 0 CET}
+ {-461120400 7200 1 CEST}
+ {-449632800 3600 0 CET}
+ {-428547600 7200 1 CEST}
+ {-418269600 3600 0 CET}
+ {-397094400 7200 1 CEST}
+ {-386809200 3600 0 CET}
+ {323827200 7200 1 CEST}
+ {338950800 3600 0 CET}
+ {354675600 7200 1 CEST}
+ {370400400 3600 0 CET}
+ {386125200 7200 1 CEST}
+ {401850000 3600 0 CET}
+ {417574800 7200 1 CEST}
+ {433299600 3600 0 CET}
+ {449024400 7200 1 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Chisinau b/library/tzdata/Europe/Chisinau
new file mode 100644
index 0000000..4ef466b
--- /dev/null
+++ b/library/tzdata/Europe/Chisinau
@@ -0,0 +1,272 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Chisinau) {
+ {-9223372036854775808 6920 0 LMT}
+ {-2840147720 6900 0 CMT}
+ {-1637114100 6264 0 BMT}
+ {-1213148664 7200 0 EET}
+ {-1187056800 10800 1 EEST}
+ {-1175479200 7200 0 EET}
+ {-1159754400 10800 1 EEST}
+ {-1144029600 7200 0 EET}
+ {-1127700000 10800 1 EEST}
+ {-1111975200 7200 0 EET}
+ {-1096250400 10800 1 EEST}
+ {-1080525600 7200 0 EET}
+ {-1064800800 10800 1 EEST}
+ {-1049076000 7200 0 EET}
+ {-1033351200 10800 1 EEST}
+ {-1017626400 7200 0 EET}
+ {-1001901600 10800 1 EEST}
+ {-986176800 7200 0 EET}
+ {-970452000 10800 1 EEST}
+ {-954727200 7200 0 EET}
+ {-927165600 10800 1 EEST}
+ {-898138800 7200 0 CET}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-800154000 10800 0 MSD}
+ {354920400 14400 1 MSD}
+ {370728000 10800 0 MSK}
+ {386456400 14400 1 MSD}
+ {402264000 10800 0 MSK}
+ {417992400 14400 1 MSD}
+ {433800000 10800 0 MSK}
+ {449614800 14400 1 MSD}
+ {465346800 10800 0 MSK}
+ {481071600 14400 1 MSD}
+ {496796400 10800 0 MSK}
+ {512521200 14400 1 MSD}
+ {528246000 10800 0 MSK}
+ {543970800 14400 1 MSD}
+ {559695600 10800 0 MSK}
+ {575420400 14400 1 MSD}
+ {591145200 10800 0 MSK}
+ {606870000 14400 1 MSD}
+ {622594800 10800 0 MSK}
+ {631141200 10800 0 MSK}
+ {641941200 7200 0 EET}
+ {662680800 7200 0 EEMMTT}
+ {670377600 10800 1 EEST}
+ {686102400 7200 0 EET}
+ {694216800 7200 0 EET}
+ {701820000 10800 1 EEST}
+ {717541200 7200 0 EET}
+ {733269600 10800 1 EEST}
+ {748990800 7200 0 EET}
+ {764719200 10800 1 EEST}
+ {780440400 7200 0 EET}
+ {796168800 10800 1 EEST}
+ {811890000 7200 0 EET}
+ {828223200 10800 1 EEST}
+ {846363600 7200 0 EET}
+ {852069600 7200 0 EET}
+ {859683600 10800 1 EEST}
+ {877827600 7200 0 EET}
+ {891133200 10800 1 EEST}
+ {909277200 7200 0 EET}
+ {922582800 10800 1 EEST}
+ {941331600 7200 0 EET}
+ {954032400 10800 1 EEST}
+ {972781200 7200 0 EET}
+ {985482000 10800 1 EEST}
+ {1004230800 7200 0 EET}
+ {1017536400 10800 1 EEST}
+ {1035680400 7200 0 EET}
+ {1048986000 10800 1 EEST}
+ {1067130000 7200 0 EET}
+ {1080435600 10800 1 EEST}
+ {1099184400 7200 0 EET}
+ {1111885200 10800 1 EEST}
+ {1130634000 7200 0 EET}
+ {1143334800 10800 1 EEST}
+ {1162083600 7200 0 EET}
+ {1174784400 10800 1 EEST}
+ {1193533200 7200 0 EET}
+ {1206838800 10800 1 EEST}
+ {1224982800 7200 0 EET}
+ {1238288400 10800 1 EEST}
+ {1256432400 7200 0 EET}
+ {1269738000 10800 1 EEST}
+ {1288486800 7200 0 EET}
+ {1301187600 10800 1 EEST}
+ {1319936400 7200 0 EET}
+ {1332637200 10800 1 EEST}
+ {1351386000 7200 0 EET}
+ {1364691600 10800 1 EEST}
+ {1382835600 7200 0 EET}
+ {1396141200 10800 1 EEST}
+ {1414285200 7200 0 EET}
+ {1427590800 10800 1 EEST}
+ {1445734800 7200 0 EET}
+ {1459040400 10800 1 EEST}
+ {1477789200 7200 0 EET}
+ {1490490000 10800 1 EEST}
+ {1509238800 7200 0 EET}
+ {1521939600 10800 1 EEST}
+ {1540688400 7200 0 EET}
+ {1553994000 10800 1 EEST}
+ {1572138000 7200 0 EET}
+ {1585443600 10800 1 EEST}
+ {1603587600 7200 0 EET}
+ {1616893200 10800 1 EEST}
+ {1635642000 7200 0 EET}
+ {1648342800 10800 1 EEST}
+ {1667091600 7200 0 EET}
+ {1679792400 10800 1 EEST}
+ {1698541200 7200 0 EET}
+ {1711846800 10800 1 EEST}
+ {1729990800 7200 0 EET}
+ {1743296400 10800 1 EEST}
+ {1761440400 7200 0 EET}
+ {1774746000 10800 1 EEST}
+ {1792890000 7200 0 EET}
+ {1806195600 10800 1 EEST}
+ {1824944400 7200 0 EET}
+ {1837645200 10800 1 EEST}
+ {1856394000 7200 0 EET}
+ {1869094800 10800 1 EEST}
+ {1887843600 7200 0 EET}
+ {1901149200 10800 1 EEST}
+ {1919293200 7200 0 EET}
+ {1932598800 10800 1 EEST}
+ {1950742800 7200 0 EET}
+ {1964048400 10800 1 EEST}
+ {1982797200 7200 0 EET}
+ {1995498000 10800 1 EEST}
+ {2014246800 7200 0 EET}
+ {2026947600 10800 1 EEST}
+ {2045696400 7200 0 EET}
+ {2058397200 10800 1 EEST}
+ {2077146000 7200 0 EET}
+ {2090451600 10800 1 EEST}
+ {2108595600 7200 0 EET}
+ {2121901200 10800 1 EEST}
+ {2140045200 7200 0 EET}
+ {2153350800 10800 1 EEST}
+ {2172099600 7200 0 EET}
+ {2184800400 10800 1 EEST}
+ {2203549200 7200 0 EET}
+ {2216250000 10800 1 EEST}
+ {2234998800 7200 0 EET}
+ {2248304400 10800 1 EEST}
+ {2266448400 7200 0 EET}
+ {2279754000 10800 1 EEST}
+ {2297898000 7200 0 EET}
+ {2311203600 10800 1 EEST}
+ {2329347600 7200 0 EET}
+ {2342653200 10800 1 EEST}
+ {2361402000 7200 0 EET}
+ {2374102800 10800 1 EEST}
+ {2392851600 7200 0 EET}
+ {2405552400 10800 1 EEST}
+ {2424301200 7200 0 EET}
+ {2437606800 10800 1 EEST}
+ {2455750800 7200 0 EET}
+ {2469056400 10800 1 EEST}
+ {2487200400 7200 0 EET}
+ {2500506000 10800 1 EEST}
+ {2519254800 7200 0 EET}
+ {2531955600 10800 1 EEST}
+ {2550704400 7200 0 EET}
+ {2563405200 10800 1 EEST}
+ {2582154000 7200 0 EET}
+ {2595459600 10800 1 EEST}
+ {2613603600 7200 0 EET}
+ {2626909200 10800 1 EEST}
+ {2645053200 7200 0 EET}
+ {2658358800 10800 1 EEST}
+ {2676502800 7200 0 EET}
+ {2689808400 10800 1 EEST}
+ {2708557200 7200 0 EET}
+ {2721258000 10800 1 EEST}
+ {2740006800 7200 0 EET}
+ {2752707600 10800 1 EEST}
+ {2771456400 7200 0 EET}
+ {2784762000 10800 1 EEST}
+ {2802906000 7200 0 EET}
+ {2816211600 10800 1 EEST}
+ {2834355600 7200 0 EET}
+ {2847661200 10800 1 EEST}
+ {2866410000 7200 0 EET}
+ {2879110800 10800 1 EEST}
+ {2897859600 7200 0 EET}
+ {2910560400 10800 1 EEST}
+ {2929309200 7200 0 EET}
+ {2942010000 10800 1 EEST}
+ {2960758800 7200 0 EET}
+ {2974064400 10800 1 EEST}
+ {2992208400 7200 0 EET}
+ {3005514000 10800 1 EEST}
+ {3023658000 7200 0 EET}
+ {3036963600 10800 1 EEST}
+ {3055712400 7200 0 EET}
+ {3068413200 10800 1 EEST}
+ {3087162000 7200 0 EET}
+ {3099862800 10800 1 EEST}
+ {3118611600 7200 0 EET}
+ {3131917200 10800 1 EEST}
+ {3150061200 7200 0 EET}
+ {3163366800 10800 1 EEST}
+ {3181510800 7200 0 EET}
+ {3194816400 10800 1 EEST}
+ {3212960400 7200 0 EET}
+ {3226266000 10800 1 EEST}
+ {3245014800 7200 0 EET}
+ {3257715600 10800 1 EEST}
+ {3276464400 7200 0 EET}
+ {3289165200 10800 1 EEST}
+ {3307914000 7200 0 EET}
+ {3321219600 10800 1 EEST}
+ {3339363600 7200 0 EET}
+ {3352669200 10800 1 EEST}
+ {3370813200 7200 0 EET}
+ {3384118800 10800 1 EEST}
+ {3402867600 7200 0 EET}
+ {3415568400 10800 1 EEST}
+ {3434317200 7200 0 EET}
+ {3447018000 10800 1 EEST}
+ {3465766800 7200 0 EET}
+ {3479072400 10800 1 EEST}
+ {3497216400 7200 0 EET}
+ {3510522000 10800 1 EEST}
+ {3528666000 7200 0 EET}
+ {3541971600 10800 1 EEST}
+ {3560115600 7200 0 EET}
+ {3573421200 10800 1 EEST}
+ {3592170000 7200 0 EET}
+ {3604870800 10800 1 EEST}
+ {3623619600 7200 0 EET}
+ {3636320400 10800 1 EEST}
+ {3655069200 7200 0 EET}
+ {3668374800 10800 1 EEST}
+ {3686518800 7200 0 EET}
+ {3699824400 10800 1 EEST}
+ {3717968400 7200 0 EET}
+ {3731274000 10800 1 EEST}
+ {3750022800 7200 0 EET}
+ {3762723600 10800 1 EEST}
+ {3781472400 7200 0 EET}
+ {3794173200 10800 1 EEST}
+ {3812922000 7200 0 EET}
+ {3825622800 10800 1 EEST}
+ {3844371600 7200 0 EET}
+ {3857677200 10800 1 EEST}
+ {3875821200 7200 0 EET}
+ {3889126800 10800 1 EEST}
+ {3907270800 7200 0 EET}
+ {3920576400 10800 1 EEST}
+ {3939325200 7200 0 EET}
+ {3952026000 10800 1 EEST}
+ {3970774800 7200 0 EET}
+ {3983475600 10800 1 EEST}
+ {4002224400 7200 0 EET}
+ {4015530000 10800 1 EEST}
+ {4033674000 7200 0 EET}
+ {4046979600 10800 1 EEST}
+ {4065123600 7200 0 EET}
+ {4078429200 10800 1 EEST}
+ {4096573200 7200 0 EET}
+}
diff --git a/library/tzdata/Europe/Copenhagen b/library/tzdata/Europe/Copenhagen
new file mode 100644
index 0000000..c747e58
--- /dev/null
+++ b/library/tzdata/Europe/Copenhagen
@@ -0,0 +1,264 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Copenhagen) {
+ {-9223372036854775808 3020 0 LMT}
+ {-2524524620 3020 0 CMT}
+ {-2398294220 3600 0 CET}
+ {-1692496800 7200 1 CEST}
+ {-1680490800 3600 0 CET}
+ {-935110800 7200 1 CEST}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-796777200 3600 0 CET}
+ {-781052400 7200 0 CEST}
+ {-769388400 3600 0 CET}
+ {-747010800 7200 1 CEST}
+ {-736383600 3600 0 CET}
+ {-715215600 7200 1 CEST}
+ {-706748400 3600 0 CET}
+ {-683161200 7200 1 CEST}
+ {-675298800 3600 0 CET}
+ {315529200 3600 0 CET}
+ {323830800 7200 1 CEST}
+ {338950800 3600 0 CET}
+ {354675600 7200 1 CEST}
+ {370400400 3600 0 CET}
+ {386125200 7200 1 CEST}
+ {401850000 3600 0 CET}
+ {417574800 7200 1 CEST}
+ {433299600 3600 0 CET}
+ {449024400 7200 1 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Dublin b/library/tzdata/Europe/Dublin
new file mode 100644
index 0000000..4b43bc0
--- /dev/null
+++ b/library/tzdata/Europe/Dublin
@@ -0,0 +1,359 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Dublin) {
+ {-9223372036854775808 -1500 0 LMT}
+ {-2821649700 -1521 0 DMT}
+ {-1691962479 2079 1 IST}
+ {-1680471279 0 0 GMT}
+ {-1664143200 3600 1 BST}
+ {-1650146400 0 0 GMT}
+ {-1633903200 3600 1 BST}
+ {-1617487200 0 0 GMT}
+ {-1601848800 3600 1 BST}
+ {-1586037600 0 0 GMT}
+ {-1570399200 3600 1 BST}
+ {-1552168800 0 0 GMT}
+ {-1538344800 3600 1 BST}
+ {-1522533600 0 0 GMT}
+ {-1517011200 0 0 IST}
+ {-1507500000 3600 1 IST}
+ {-1490565600 0 0 IST}
+ {-1473631200 3600 1 IST}
+ {-1460930400 0 0 IST}
+ {-1442786400 3600 1 IST}
+ {-1428876000 0 0 IST}
+ {-1410732000 3600 1 IST}
+ {-1396216800 0 0 IST}
+ {-1379282400 3600 1 IST}
+ {-1364767200 0 0 IST}
+ {-1348437600 3600 1 IST}
+ {-1333317600 0 0 IST}
+ {-1315778400 3600 1 IST}
+ {-1301263200 0 0 IST}
+ {-1284328800 3600 1 IST}
+ {-1269813600 0 0 IST}
+ {-1253484000 3600 1 IST}
+ {-1238364000 0 0 IST}
+ {-1221429600 3600 1 IST}
+ {-1206914400 0 0 IST}
+ {-1189980000 3600 1 IST}
+ {-1175464800 0 0 IST}
+ {-1159135200 3600 1 IST}
+ {-1143410400 0 0 IST}
+ {-1126476000 3600 1 IST}
+ {-1111960800 0 0 IST}
+ {-1095631200 3600 1 IST}
+ {-1080511200 0 0 IST}
+ {-1063576800 3600 1 IST}
+ {-1049061600 0 0 IST}
+ {-1032127200 3600 1 IST}
+ {-1017612000 0 0 IST}
+ {-1001282400 3600 1 IST}
+ {-986162400 0 0 IST}
+ {-969228000 3600 1 IST}
+ {-950479200 0 0 IST}
+ {-942015600 3600 1 IST}
+ {-733359600 0 0 GMT}
+ {-719445600 3600 1 IST}
+ {-699490800 0 0 GMT}
+ {-684972000 3600 0 IST}
+ {-668037600 0 0 IST}
+ {-654732000 3600 1 IST}
+ {-636588000 0 0 IST}
+ {-622072800 3600 1 IST}
+ {-605743200 0 0 IST}
+ {-590623200 3600 1 IST}
+ {-574293600 0 0 IST}
+ {-558568800 3600 1 IST}
+ {-542239200 0 0 IST}
+ {-527119200 3600 1 IST}
+ {-512604000 0 0 IST}
+ {-496274400 3600 1 IST}
+ {-481154400 0 0 IST}
+ {-464220000 3600 1 IST}
+ {-449704800 0 0 IST}
+ {-432165600 3600 1 IST}
+ {-417650400 0 0 IST}
+ {-401320800 3600 1 IST}
+ {-386200800 0 0 IST}
+ {-369266400 3600 1 IST}
+ {-354751200 0 0 IST}
+ {-337816800 3600 1 IST}
+ {-323301600 0 0 IST}
+ {-306972000 3600 1 IST}
+ {-291852000 0 0 IST}
+ {-276732000 3600 1 IST}
+ {-257983200 0 0 IST}
+ {-245282400 3600 1 IST}
+ {-226533600 0 0 IST}
+ {-213228000 3600 1 IST}
+ {-195084000 0 0 IST}
+ {-182383200 3600 1 IST}
+ {-163634400 0 0 IST}
+ {-150933600 3600 1 IST}
+ {-132184800 0 0 IST}
+ {-119484000 3600 1 IST}
+ {-100735200 0 0 IST}
+ {-88034400 3600 1 IST}
+ {-68680800 0 0 IST}
+ {-59004000 3600 1 IST}
+ {-37238400 3600 0 IST}
+ {57722400 0 0 IST}
+ {69818400 3600 1 IST}
+ {89172000 0 0 IST}
+ {101268000 3600 1 IST}
+ {120621600 0 0 IST}
+ {132717600 3600 1 IST}
+ {152071200 0 0 IST}
+ {164167200 3600 1 IST}
+ {183520800 0 0 IST}
+ {196221600 3600 1 IST}
+ {214970400 0 0 IST}
+ {227671200 3600 1 IST}
+ {246420000 0 0 IST}
+ {259120800 3600 1 IST}
+ {278474400 0 0 IST}
+ {290570400 3600 1 IST}
+ {309924000 0 0 IST}
+ {322020000 3600 1 IST}
+ {341373600 0 0 IST}
+ {354675600 3600 1 IST}
+ {372819600 0 0 IST}
+ {386125200 3600 1 IST}
+ {404269200 0 0 IST}
+ {417574800 3600 1 IST}
+ {435718800 0 0 IST}
+ {449024400 3600 1 IST}
+ {467773200 0 0 IST}
+ {481078800 3600 1 IST}
+ {499222800 0 0 IST}
+ {512528400 3600 1 IST}
+ {530672400 0 0 IST}
+ {543978000 3600 1 IST}
+ {562122000 0 0 IST}
+ {575427600 3600 1 IST}
+ {593571600 0 0 IST}
+ {606877200 3600 1 IST}
+ {625626000 0 0 IST}
+ {638326800 3600 1 IST}
+ {657075600 0 0 IST}
+ {670381200 3600 1 IST}
+ {688525200 0 0 IST}
+ {701830800 3600 1 IST}
+ {719974800 0 0 IST}
+ {733280400 3600 1 IST}
+ {751424400 0 0 IST}
+ {764730000 3600 1 IST}
+ {782874000 0 0 IST}
+ {796179600 3600 1 IST}
+ {814323600 0 0 IST}
+ {820454400 0 0 GMT}
+ {828234000 3600 1 IST}
+ {846378000 0 0 GMT}
+ {859683600 3600 1 IST}
+ {877827600 0 0 GMT}
+ {891133200 3600 1 IST}
+ {909277200 0 0 GMT}
+ {922582800 3600 1 IST}
+ {941331600 0 0 GMT}
+ {954032400 3600 1 IST}
+ {972781200 0 0 GMT}
+ {985482000 3600 1 IST}
+ {1004230800 0 0 GMT}
+ {1017536400 3600 1 IST}
+ {1035680400 0 0 GMT}
+ {1048986000 3600 1 IST}
+ {1067130000 0 0 GMT}
+ {1080435600 3600 1 IST}
+ {1099184400 0 0 GMT}
+ {1111885200 3600 1 IST}
+ {1130634000 0 0 GMT}
+ {1143334800 3600 1 IST}
+ {1162083600 0 0 GMT}
+ {1174784400 3600 1 IST}
+ {1193533200 0 0 GMT}
+ {1206838800 3600 1 IST}
+ {1224982800 0 0 GMT}
+ {1238288400 3600 1 IST}
+ {1256432400 0 0 GMT}
+ {1269738000 3600 1 IST}
+ {1288486800 0 0 GMT}
+ {1301187600 3600 1 IST}
+ {1319936400 0 0 GMT}
+ {1332637200 3600 1 IST}
+ {1351386000 0 0 GMT}
+ {1364691600 3600 1 IST}
+ {1382835600 0 0 GMT}
+ {1396141200 3600 1 IST}
+ {1414285200 0 0 GMT}
+ {1427590800 3600 1 IST}
+ {1445734800 0 0 GMT}
+ {1459040400 3600 1 IST}
+ {1477789200 0 0 GMT}
+ {1490490000 3600 1 IST}
+ {1509238800 0 0 GMT}
+ {1521939600 3600 1 IST}
+ {1540688400 0 0 GMT}
+ {1553994000 3600 1 IST}
+ {1572138000 0 0 GMT}
+ {1585443600 3600 1 IST}
+ {1603587600 0 0 GMT}
+ {1616893200 3600 1 IST}
+ {1635642000 0 0 GMT}
+ {1648342800 3600 1 IST}
+ {1667091600 0 0 GMT}
+ {1679792400 3600 1 IST}
+ {1698541200 0 0 GMT}
+ {1711846800 3600 1 IST}
+ {1729990800 0 0 GMT}
+ {1743296400 3600 1 IST}
+ {1761440400 0 0 GMT}
+ {1774746000 3600 1 IST}
+ {1792890000 0 0 GMT}
+ {1806195600 3600 1 IST}
+ {1824944400 0 0 GMT}
+ {1837645200 3600 1 IST}
+ {1856394000 0 0 GMT}
+ {1869094800 3600 1 IST}
+ {1887843600 0 0 GMT}
+ {1901149200 3600 1 IST}
+ {1919293200 0 0 GMT}
+ {1932598800 3600 1 IST}
+ {1950742800 0 0 GMT}
+ {1964048400 3600 1 IST}
+ {1982797200 0 0 GMT}
+ {1995498000 3600 1 IST}
+ {2014246800 0 0 GMT}
+ {2026947600 3600 1 IST}
+ {2045696400 0 0 GMT}
+ {2058397200 3600 1 IST}
+ {2077146000 0 0 GMT}
+ {2090451600 3600 1 IST}
+ {2108595600 0 0 GMT}
+ {2121901200 3600 1 IST}
+ {2140045200 0 0 GMT}
+ {2153350800 3600 1 IST}
+ {2172099600 0 0 GMT}
+ {2184800400 3600 1 IST}
+ {2203549200 0 0 GMT}
+ {2216250000 3600 1 IST}
+ {2234998800 0 0 GMT}
+ {2248304400 3600 1 IST}
+ {2266448400 0 0 GMT}
+ {2279754000 3600 1 IST}
+ {2297898000 0 0 GMT}
+ {2311203600 3600 1 IST}
+ {2329347600 0 0 GMT}
+ {2342653200 3600 1 IST}
+ {2361402000 0 0 GMT}
+ {2374102800 3600 1 IST}
+ {2392851600 0 0 GMT}
+ {2405552400 3600 1 IST}
+ {2424301200 0 0 GMT}
+ {2437606800 3600 1 IST}
+ {2455750800 0 0 GMT}
+ {2469056400 3600 1 IST}
+ {2487200400 0 0 GMT}
+ {2500506000 3600 1 IST}
+ {2519254800 0 0 GMT}
+ {2531955600 3600 1 IST}
+ {2550704400 0 0 GMT}
+ {2563405200 3600 1 IST}
+ {2582154000 0 0 GMT}
+ {2595459600 3600 1 IST}
+ {2613603600 0 0 GMT}
+ {2626909200 3600 1 IST}
+ {2645053200 0 0 GMT}
+ {2658358800 3600 1 IST}
+ {2676502800 0 0 GMT}
+ {2689808400 3600 1 IST}
+ {2708557200 0 0 GMT}
+ {2721258000 3600 1 IST}
+ {2740006800 0 0 GMT}
+ {2752707600 3600 1 IST}
+ {2771456400 0 0 GMT}
+ {2784762000 3600 1 IST}
+ {2802906000 0 0 GMT}
+ {2816211600 3600 1 IST}
+ {2834355600 0 0 GMT}
+ {2847661200 3600 1 IST}
+ {2866410000 0 0 GMT}
+ {2879110800 3600 1 IST}
+ {2897859600 0 0 GMT}
+ {2910560400 3600 1 IST}
+ {2929309200 0 0 GMT}
+ {2942010000 3600 1 IST}
+ {2960758800 0 0 GMT}
+ {2974064400 3600 1 IST}
+ {2992208400 0 0 GMT}
+ {3005514000 3600 1 IST}
+ {3023658000 0 0 GMT}
+ {3036963600 3600 1 IST}
+ {3055712400 0 0 GMT}
+ {3068413200 3600 1 IST}
+ {3087162000 0 0 GMT}
+ {3099862800 3600 1 IST}
+ {3118611600 0 0 GMT}
+ {3131917200 3600 1 IST}
+ {3150061200 0 0 GMT}
+ {3163366800 3600 1 IST}
+ {3181510800 0 0 GMT}
+ {3194816400 3600 1 IST}
+ {3212960400 0 0 GMT}
+ {3226266000 3600 1 IST}
+ {3245014800 0 0 GMT}
+ {3257715600 3600 1 IST}
+ {3276464400 0 0 GMT}
+ {3289165200 3600 1 IST}
+ {3307914000 0 0 GMT}
+ {3321219600 3600 1 IST}
+ {3339363600 0 0 GMT}
+ {3352669200 3600 1 IST}
+ {3370813200 0 0 GMT}
+ {3384118800 3600 1 IST}
+ {3402867600 0 0 GMT}
+ {3415568400 3600 1 IST}
+ {3434317200 0 0 GMT}
+ {3447018000 3600 1 IST}
+ {3465766800 0 0 GMT}
+ {3479072400 3600 1 IST}
+ {3497216400 0 0 GMT}
+ {3510522000 3600 1 IST}
+ {3528666000 0 0 GMT}
+ {3541971600 3600 1 IST}
+ {3560115600 0 0 GMT}
+ {3573421200 3600 1 IST}
+ {3592170000 0 0 GMT}
+ {3604870800 3600 1 IST}
+ {3623619600 0 0 GMT}
+ {3636320400 3600 1 IST}
+ {3655069200 0 0 GMT}
+ {3668374800 3600 1 IST}
+ {3686518800 0 0 GMT}
+ {3699824400 3600 1 IST}
+ {3717968400 0 0 GMT}
+ {3731274000 3600 1 IST}
+ {3750022800 0 0 GMT}
+ {3762723600 3600 1 IST}
+ {3781472400 0 0 GMT}
+ {3794173200 3600 1 IST}
+ {3812922000 0 0 GMT}
+ {3825622800 3600 1 IST}
+ {3844371600 0 0 GMT}
+ {3857677200 3600 1 IST}
+ {3875821200 0 0 GMT}
+ {3889126800 3600 1 IST}
+ {3907270800 0 0 GMT}
+ {3920576400 3600 1 IST}
+ {3939325200 0 0 GMT}
+ {3952026000 3600 1 IST}
+ {3970774800 0 0 GMT}
+ {3983475600 3600 1 IST}
+ {4002224400 0 0 GMT}
+ {4015530000 3600 1 IST}
+ {4033674000 0 0 GMT}
+ {4046979600 3600 1 IST}
+ {4065123600 0 0 GMT}
+ {4078429200 3600 1 IST}
+ {4096573200 0 0 GMT}
+}
diff --git a/library/tzdata/Europe/Gibraltar b/library/tzdata/Europe/Gibraltar
new file mode 100644
index 0000000..de29c03
--- /dev/null
+++ b/library/tzdata/Europe/Gibraltar
@@ -0,0 +1,328 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Gibraltar) {
+ {-9223372036854775808 -1284 0 LMT}
+ {-2821649916 0 0 GMT}
+ {-1691964000 3600 1 BST}
+ {-1680472800 0 0 GMT}
+ {-1664143200 3600 1 BST}
+ {-1650146400 0 0 GMT}
+ {-1633903200 3600 1 BST}
+ {-1617487200 0 0 GMT}
+ {-1601848800 3600 1 BST}
+ {-1586037600 0 0 GMT}
+ {-1570399200 3600 1 BST}
+ {-1552168800 0 0 GMT}
+ {-1538344800 3600 1 BST}
+ {-1522533600 0 0 GMT}
+ {-1507500000 3600 1 BST}
+ {-1490565600 0 0 GMT}
+ {-1473631200 3600 1 BST}
+ {-1460930400 0 0 GMT}
+ {-1442786400 3600 1 BST}
+ {-1428876000 0 0 GMT}
+ {-1410732000 3600 1 BST}
+ {-1396216800 0 0 GMT}
+ {-1379282400 3600 1 BST}
+ {-1364767200 0 0 GMT}
+ {-1348437600 3600 1 BST}
+ {-1333317600 0 0 GMT}
+ {-1315778400 3600 1 BST}
+ {-1301263200 0 0 GMT}
+ {-1284328800 3600 1 BST}
+ {-1269813600 0 0 GMT}
+ {-1253484000 3600 1 BST}
+ {-1238364000 0 0 GMT}
+ {-1221429600 3600 1 BST}
+ {-1206914400 0 0 GMT}
+ {-1189980000 3600 1 BST}
+ {-1175464800 0 0 GMT}
+ {-1159135200 3600 1 BST}
+ {-1143410400 0 0 GMT}
+ {-1126476000 3600 1 BST}
+ {-1111960800 0 0 GMT}
+ {-1095631200 3600 1 BST}
+ {-1080511200 0 0 GMT}
+ {-1063576800 3600 1 BST}
+ {-1049061600 0 0 GMT}
+ {-1032127200 3600 1 BST}
+ {-1017612000 0 0 GMT}
+ {-1001282400 3600 1 BST}
+ {-986162400 0 0 GMT}
+ {-969228000 3600 1 BST}
+ {-950479200 0 0 GMT}
+ {-942012000 3600 1 BST}
+ {-904518000 7200 1 BDST}
+ {-896050800 3600 1 BST}
+ {-875487600 7200 1 BDST}
+ {-864601200 3600 1 BST}
+ {-844038000 7200 1 BDST}
+ {-832546800 3600 1 BST}
+ {-812588400 7200 1 BDST}
+ {-798073200 3600 1 BST}
+ {-781052400 7200 1 BDST}
+ {-772066800 3600 1 BST}
+ {-764805600 0 0 GMT}
+ {-748476000 3600 1 BST}
+ {-733356000 0 0 GMT}
+ {-719445600 3600 1 BST}
+ {-717030000 7200 1 BDST}
+ {-706748400 3600 1 BST}
+ {-699487200 0 0 GMT}
+ {-687996000 3600 1 BST}
+ {-668037600 0 0 GMT}
+ {-654732000 3600 1 BST}
+ {-636588000 0 0 GMT}
+ {-622072800 3600 1 BST}
+ {-605743200 0 0 GMT}
+ {-590623200 3600 1 BST}
+ {-574293600 0 0 GMT}
+ {-558568800 3600 1 BST}
+ {-542239200 0 0 GMT}
+ {-527119200 3600 1 BST}
+ {-512604000 0 0 GMT}
+ {-496274400 3600 1 BST}
+ {-481154400 0 0 GMT}
+ {-464220000 3600 1 BST}
+ {-449704800 0 0 GMT}
+ {-432165600 3600 1 BST}
+ {-417650400 0 0 GMT}
+ {-401320800 3600 0 CET}
+ {378687600 3600 0 CET}
+ {386125200 7200 1 CEST}
+ {401850000 3600 0 CET}
+ {417574800 7200 1 CEST}
+ {433299600 3600 0 CET}
+ {449024400 7200 1 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Guernsey b/library/tzdata/Europe/Guernsey
new file mode 100755
index 0000000..4372c64
--- /dev/null
+++ b/library/tzdata/Europe/Guernsey
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/London)]} {
+ LoadTimeZoneFile Europe/London
+}
+set TZData(:Europe/Guernsey) $TZData(:Europe/London)
diff --git a/library/tzdata/Europe/Helsinki b/library/tzdata/Europe/Helsinki
new file mode 100644
index 0000000..3abf790
--- /dev/null
+++ b/library/tzdata/Europe/Helsinki
@@ -0,0 +1,248 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Helsinki) {
+ {-9223372036854775808 5992 0 LMT}
+ {-2890258792 5992 0 HMT}
+ {-1535938792 7200 0 EET}
+ {-875671200 10800 1 EEST}
+ {-859863600 7200 0 EET}
+ {354672000 10800 1 EEST}
+ {370396800 7200 0 EET}
+ {386121600 10800 1 EEST}
+ {401846400 7200 0 EET}
+ {410220000 7200 0 EET}
+ {417574800 10800 1 EEST}
+ {433299600 7200 0 EET}
+ {449024400 10800 1 EEST}
+ {465354000 7200 0 EET}
+ {481078800 10800 1 EEST}
+ {496803600 7200 0 EET}
+ {512528400 10800 1 EEST}
+ {528253200 7200 0 EET}
+ {543978000 10800 1 EEST}
+ {559702800 7200 0 EET}
+ {575427600 10800 1 EEST}
+ {591152400 7200 0 EET}
+ {606877200 10800 1 EEST}
+ {622602000 7200 0 EET}
+ {638326800 10800 1 EEST}
+ {654656400 7200 0 EET}
+ {670381200 10800 1 EEST}
+ {686106000 7200 0 EET}
+ {701830800 10800 1 EEST}
+ {717555600 7200 0 EET}
+ {733280400 10800 1 EEST}
+ {749005200 7200 0 EET}
+ {764730000 10800 1 EEST}
+ {780454800 7200 0 EET}
+ {796179600 10800 1 EEST}
+ {811904400 7200 0 EET}
+ {828234000 10800 1 EEST}
+ {846378000 7200 0 EET}
+ {859683600 10800 1 EEST}
+ {877827600 7200 0 EET}
+ {891133200 10800 1 EEST}
+ {909277200 7200 0 EET}
+ {922582800 10800 1 EEST}
+ {941331600 7200 0 EET}
+ {954032400 10800 1 EEST}
+ {972781200 7200 0 EET}
+ {985482000 10800 1 EEST}
+ {1004230800 7200 0 EET}
+ {1017536400 10800 1 EEST}
+ {1035680400 7200 0 EET}
+ {1048986000 10800 1 EEST}
+ {1067130000 7200 0 EET}
+ {1080435600 10800 1 EEST}
+ {1099184400 7200 0 EET}
+ {1111885200 10800 1 EEST}
+ {1130634000 7200 0 EET}
+ {1143334800 10800 1 EEST}
+ {1162083600 7200 0 EET}
+ {1174784400 10800 1 EEST}
+ {1193533200 7200 0 EET}
+ {1206838800 10800 1 EEST}
+ {1224982800 7200 0 EET}
+ {1238288400 10800 1 EEST}
+ {1256432400 7200 0 EET}
+ {1269738000 10800 1 EEST}
+ {1288486800 7200 0 EET}
+ {1301187600 10800 1 EEST}
+ {1319936400 7200 0 EET}
+ {1332637200 10800 1 EEST}
+ {1351386000 7200 0 EET}
+ {1364691600 10800 1 EEST}
+ {1382835600 7200 0 EET}
+ {1396141200 10800 1 EEST}
+ {1414285200 7200 0 EET}
+ {1427590800 10800 1 EEST}
+ {1445734800 7200 0 EET}
+ {1459040400 10800 1 EEST}
+ {1477789200 7200 0 EET}
+ {1490490000 10800 1 EEST}
+ {1509238800 7200 0 EET}
+ {1521939600 10800 1 EEST}
+ {1540688400 7200 0 EET}
+ {1553994000 10800 1 EEST}
+ {1572138000 7200 0 EET}
+ {1585443600 10800 1 EEST}
+ {1603587600 7200 0 EET}
+ {1616893200 10800 1 EEST}
+ {1635642000 7200 0 EET}
+ {1648342800 10800 1 EEST}
+ {1667091600 7200 0 EET}
+ {1679792400 10800 1 EEST}
+ {1698541200 7200 0 EET}
+ {1711846800 10800 1 EEST}
+ {1729990800 7200 0 EET}
+ {1743296400 10800 1 EEST}
+ {1761440400 7200 0 EET}
+ {1774746000 10800 1 EEST}
+ {1792890000 7200 0 EET}
+ {1806195600 10800 1 EEST}
+ {1824944400 7200 0 EET}
+ {1837645200 10800 1 EEST}
+ {1856394000 7200 0 EET}
+ {1869094800 10800 1 EEST}
+ {1887843600 7200 0 EET}
+ {1901149200 10800 1 EEST}
+ {1919293200 7200 0 EET}
+ {1932598800 10800 1 EEST}
+ {1950742800 7200 0 EET}
+ {1964048400 10800 1 EEST}
+ {1982797200 7200 0 EET}
+ {1995498000 10800 1 EEST}
+ {2014246800 7200 0 EET}
+ {2026947600 10800 1 EEST}
+ {2045696400 7200 0 EET}
+ {2058397200 10800 1 EEST}
+ {2077146000 7200 0 EET}
+ {2090451600 10800 1 EEST}
+ {2108595600 7200 0 EET}
+ {2121901200 10800 1 EEST}
+ {2140045200 7200 0 EET}
+ {2153350800 10800 1 EEST}
+ {2172099600 7200 0 EET}
+ {2184800400 10800 1 EEST}
+ {2203549200 7200 0 EET}
+ {2216250000 10800 1 EEST}
+ {2234998800 7200 0 EET}
+ {2248304400 10800 1 EEST}
+ {2266448400 7200 0 EET}
+ {2279754000 10800 1 EEST}
+ {2297898000 7200 0 EET}
+ {2311203600 10800 1 EEST}
+ {2329347600 7200 0 EET}
+ {2342653200 10800 1 EEST}
+ {2361402000 7200 0 EET}
+ {2374102800 10800 1 EEST}
+ {2392851600 7200 0 EET}
+ {2405552400 10800 1 EEST}
+ {2424301200 7200 0 EET}
+ {2437606800 10800 1 EEST}
+ {2455750800 7200 0 EET}
+ {2469056400 10800 1 EEST}
+ {2487200400 7200 0 EET}
+ {2500506000 10800 1 EEST}
+ {2519254800 7200 0 EET}
+ {2531955600 10800 1 EEST}
+ {2550704400 7200 0 EET}
+ {2563405200 10800 1 EEST}
+ {2582154000 7200 0 EET}
+ {2595459600 10800 1 EEST}
+ {2613603600 7200 0 EET}
+ {2626909200 10800 1 EEST}
+ {2645053200 7200 0 EET}
+ {2658358800 10800 1 EEST}
+ {2676502800 7200 0 EET}
+ {2689808400 10800 1 EEST}
+ {2708557200 7200 0 EET}
+ {2721258000 10800 1 EEST}
+ {2740006800 7200 0 EET}
+ {2752707600 10800 1 EEST}
+ {2771456400 7200 0 EET}
+ {2784762000 10800 1 EEST}
+ {2802906000 7200 0 EET}
+ {2816211600 10800 1 EEST}
+ {2834355600 7200 0 EET}
+ {2847661200 10800 1 EEST}
+ {2866410000 7200 0 EET}
+ {2879110800 10800 1 EEST}
+ {2897859600 7200 0 EET}
+ {2910560400 10800 1 EEST}
+ {2929309200 7200 0 EET}
+ {2942010000 10800 1 EEST}
+ {2960758800 7200 0 EET}
+ {2974064400 10800 1 EEST}
+ {2992208400 7200 0 EET}
+ {3005514000 10800 1 EEST}
+ {3023658000 7200 0 EET}
+ {3036963600 10800 1 EEST}
+ {3055712400 7200 0 EET}
+ {3068413200 10800 1 EEST}
+ {3087162000 7200 0 EET}
+ {3099862800 10800 1 EEST}
+ {3118611600 7200 0 EET}
+ {3131917200 10800 1 EEST}
+ {3150061200 7200 0 EET}
+ {3163366800 10800 1 EEST}
+ {3181510800 7200 0 EET}
+ {3194816400 10800 1 EEST}
+ {3212960400 7200 0 EET}
+ {3226266000 10800 1 EEST}
+ {3245014800 7200 0 EET}
+ {3257715600 10800 1 EEST}
+ {3276464400 7200 0 EET}
+ {3289165200 10800 1 EEST}
+ {3307914000 7200 0 EET}
+ {3321219600 10800 1 EEST}
+ {3339363600 7200 0 EET}
+ {3352669200 10800 1 EEST}
+ {3370813200 7200 0 EET}
+ {3384118800 10800 1 EEST}
+ {3402867600 7200 0 EET}
+ {3415568400 10800 1 EEST}
+ {3434317200 7200 0 EET}
+ {3447018000 10800 1 EEST}
+ {3465766800 7200 0 EET}
+ {3479072400 10800 1 EEST}
+ {3497216400 7200 0 EET}
+ {3510522000 10800 1 EEST}
+ {3528666000 7200 0 EET}
+ {3541971600 10800 1 EEST}
+ {3560115600 7200 0 EET}
+ {3573421200 10800 1 EEST}
+ {3592170000 7200 0 EET}
+ {3604870800 10800 1 EEST}
+ {3623619600 7200 0 EET}
+ {3636320400 10800 1 EEST}
+ {3655069200 7200 0 EET}
+ {3668374800 10800 1 EEST}
+ {3686518800 7200 0 EET}
+ {3699824400 10800 1 EEST}
+ {3717968400 7200 0 EET}
+ {3731274000 10800 1 EEST}
+ {3750022800 7200 0 EET}
+ {3762723600 10800 1 EEST}
+ {3781472400 7200 0 EET}
+ {3794173200 10800 1 EEST}
+ {3812922000 7200 0 EET}
+ {3825622800 10800 1 EEST}
+ {3844371600 7200 0 EET}
+ {3857677200 10800 1 EEST}
+ {3875821200 7200 0 EET}
+ {3889126800 10800 1 EEST}
+ {3907270800 7200 0 EET}
+ {3920576400 10800 1 EEST}
+ {3939325200 7200 0 EET}
+ {3952026000 10800 1 EEST}
+ {3970774800 7200 0 EET}
+ {3983475600 10800 1 EEST}
+ {4002224400 7200 0 EET}
+ {4015530000 10800 1 EEST}
+ {4033674000 7200 0 EET}
+ {4046979600 10800 1 EEST}
+ {4065123600 7200 0 EET}
+ {4078429200 10800 1 EEST}
+ {4096573200 7200 0 EET}
+}
diff --git a/library/tzdata/Europe/Isle_of_Man b/library/tzdata/Europe/Isle_of_Man
new file mode 100755
index 0000000..870ac45
--- /dev/null
+++ b/library/tzdata/Europe/Isle_of_Man
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/London)]} {
+ LoadTimeZoneFile Europe/London
+}
+set TZData(:Europe/Isle_of_Man) $TZData(:Europe/London)
diff --git a/library/tzdata/Europe/Istanbul b/library/tzdata/Europe/Istanbul
new file mode 100644
index 0000000..7737d75
--- /dev/null
+++ b/library/tzdata/Europe/Istanbul
@@ -0,0 +1,304 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Istanbul) {
+ {-9223372036854775808 6952 0 LMT}
+ {-2840147752 7016 0 IMT}
+ {-1869875816 7200 0 EET}
+ {-1693706400 10800 1 EEST}
+ {-1680490800 7200 0 EET}
+ {-1570413600 10800 1 EEST}
+ {-1552186800 7200 0 EET}
+ {-1538359200 10800 1 EEST}
+ {-1522551600 7200 0 EET}
+ {-1507514400 10800 1 EEST}
+ {-1490583600 7200 0 EET}
+ {-1440208800 10800 1 EEST}
+ {-1428030000 7200 0 EET}
+ {-1409709600 10800 1 EEST}
+ {-1396494000 7200 0 EET}
+ {-931140000 10800 1 EEST}
+ {-922762800 7200 0 EET}
+ {-917834400 10800 1 EEST}
+ {-892436400 7200 0 EET}
+ {-875844000 10800 1 EEST}
+ {-857358000 7200 0 EET}
+ {-781063200 10800 1 EEST}
+ {-764737200 7200 0 EET}
+ {-744343200 10800 1 EEST}
+ {-733806000 7200 0 EET}
+ {-716436000 10800 1 EEST}
+ {-701924400 7200 0 EET}
+ {-684986400 10800 1 EEST}
+ {-670474800 7200 0 EET}
+ {-654141600 10800 1 EEST}
+ {-639025200 7200 0 EET}
+ {-621828000 10800 1 EEST}
+ {-606970800 7200 0 EET}
+ {-590032800 10800 1 EEST}
+ {-575434800 7200 0 EET}
+ {-235620000 10800 1 EEST}
+ {-228279600 7200 0 EET}
+ {-177732000 10800 1 EEST}
+ {-165726000 7200 0 EET}
+ {10533600 10800 1 EEST}
+ {23835600 7200 0 EET}
+ {41983200 10800 1 EEST}
+ {55285200 7200 0 EET}
+ {74037600 10800 1 EEST}
+ {87339600 7200 0 EET}
+ {107910000 10800 1 EEST}
+ {121219200 7200 0 EET}
+ {133920000 10800 1 EEST}
+ {152676000 7200 0 EET}
+ {165362400 10800 1 EEST}
+ {183502800 7200 0 EET}
+ {202428000 10800 1 EEST}
+ {215557200 7200 0 EET}
+ {228866400 10800 1 EEST}
+ {245797200 7200 0 EET}
+ {260316000 10800 1 EEST}
+ {277246800 14400 0 TRST}
+ {291769200 14400 1 TRST}
+ {308779200 10800 0 TRT}
+ {323827200 14400 1 TRST}
+ {340228800 10800 0 TRT}
+ {354672000 14400 1 TRST}
+ {371678400 10800 0 TRT}
+ {386121600 14400 1 TRST}
+ {403128000 10800 0 TRT}
+ {428446800 14400 1 TRST}
+ {433886400 10800 0 TRT}
+ {482792400 7200 0 EET}
+ {482796000 10800 1 EEST}
+ {496702800 7200 0 EET}
+ {512524800 10800 1 EEST}
+ {528249600 7200 0 EET}
+ {543974400 10800 1 EEST}
+ {559699200 7200 0 EET}
+ {575424000 10800 1 EEST}
+ {591148800 7200 0 EET}
+ {606873600 10800 1 EEST}
+ {622598400 7200 0 EET}
+ {638323200 10800 1 EEST}
+ {654652800 7200 0 EET}
+ {670374000 10800 1 EEST}
+ {686098800 7200 0 EET}
+ {701823600 10800 1 EEST}
+ {717548400 7200 0 EET}
+ {733273200 10800 1 EEST}
+ {748998000 7200 0 EET}
+ {764722800 10800 1 EEST}
+ {780447600 7200 0 EET}
+ {796172400 10800 1 EEST}
+ {811897200 7200 0 EET}
+ {828226800 10800 1 EEST}
+ {846370800 7200 0 EET}
+ {859676400 10800 1 EEST}
+ {877820400 7200 0 EET}
+ {891126000 10800 1 EEST}
+ {909270000 7200 0 EET}
+ {922575600 10800 1 EEST}
+ {941324400 7200 0 EET}
+ {954025200 10800 1 EEST}
+ {972774000 7200 0 EET}
+ {985474800 10800 1 EEST}
+ {1004223600 7200 0 EET}
+ {1017529200 10800 1 EEST}
+ {1035673200 7200 0 EET}
+ {1048978800 10800 1 EEST}
+ {1067122800 7200 0 EET}
+ {1080428400 10800 1 EEST}
+ {1099177200 7200 0 EET}
+ {1111878000 10800 1 EEST}
+ {1130626800 7200 0 EET}
+ {1143327600 10800 1 EEST}
+ {1162076400 7200 0 EET}
+ {1167602400 7200 0 EET}
+ {1174784400 10800 1 EEST}
+ {1193533200 7200 0 EET}
+ {1206838800 10800 1 EEST}
+ {1224982800 7200 0 EET}
+ {1238288400 10800 1 EEST}
+ {1256432400 7200 0 EET}
+ {1269738000 10800 1 EEST}
+ {1288486800 7200 0 EET}
+ {1301187600 7200 0 EET}
+ {1301274000 10800 0 EEST}
+ {1319936400 7200 0 EET}
+ {1332637200 10800 1 EEST}
+ {1351386000 7200 0 EET}
+ {1364691600 10800 1 EEST}
+ {1382835600 7200 0 EET}
+ {1396141200 10800 1 EEST}
+ {1414285200 7200 0 EET}
+ {1427590800 10800 1 EEST}
+ {1445734800 7200 0 EET}
+ {1459040400 10800 1 EEST}
+ {1477789200 7200 0 EET}
+ {1490490000 10800 1 EEST}
+ {1509238800 7200 0 EET}
+ {1521939600 10800 1 EEST}
+ {1540688400 7200 0 EET}
+ {1553994000 10800 1 EEST}
+ {1572138000 7200 0 EET}
+ {1585443600 10800 1 EEST}
+ {1603587600 7200 0 EET}
+ {1616893200 10800 1 EEST}
+ {1635642000 7200 0 EET}
+ {1648342800 10800 1 EEST}
+ {1667091600 7200 0 EET}
+ {1679792400 10800 1 EEST}
+ {1698541200 7200 0 EET}
+ {1711846800 10800 1 EEST}
+ {1729990800 7200 0 EET}
+ {1743296400 10800 1 EEST}
+ {1761440400 7200 0 EET}
+ {1774746000 10800 1 EEST}
+ {1792890000 7200 0 EET}
+ {1806195600 10800 1 EEST}
+ {1824944400 7200 0 EET}
+ {1837645200 10800 1 EEST}
+ {1856394000 7200 0 EET}
+ {1869094800 10800 1 EEST}
+ {1887843600 7200 0 EET}
+ {1901149200 10800 1 EEST}
+ {1919293200 7200 0 EET}
+ {1932598800 10800 1 EEST}
+ {1950742800 7200 0 EET}
+ {1964048400 10800 1 EEST}
+ {1982797200 7200 0 EET}
+ {1995498000 10800 1 EEST}
+ {2014246800 7200 0 EET}
+ {2026947600 10800 1 EEST}
+ {2045696400 7200 0 EET}
+ {2058397200 10800 1 EEST}
+ {2077146000 7200 0 EET}
+ {2090451600 10800 1 EEST}
+ {2108595600 7200 0 EET}
+ {2121901200 10800 1 EEST}
+ {2140045200 7200 0 EET}
+ {2153350800 10800 1 EEST}
+ {2172099600 7200 0 EET}
+ {2184800400 10800 1 EEST}
+ {2203549200 7200 0 EET}
+ {2216250000 10800 1 EEST}
+ {2234998800 7200 0 EET}
+ {2248304400 10800 1 EEST}
+ {2266448400 7200 0 EET}
+ {2279754000 10800 1 EEST}
+ {2297898000 7200 0 EET}
+ {2311203600 10800 1 EEST}
+ {2329347600 7200 0 EET}
+ {2342653200 10800 1 EEST}
+ {2361402000 7200 0 EET}
+ {2374102800 10800 1 EEST}
+ {2392851600 7200 0 EET}
+ {2405552400 10800 1 EEST}
+ {2424301200 7200 0 EET}
+ {2437606800 10800 1 EEST}
+ {2455750800 7200 0 EET}
+ {2469056400 10800 1 EEST}
+ {2487200400 7200 0 EET}
+ {2500506000 10800 1 EEST}
+ {2519254800 7200 0 EET}
+ {2531955600 10800 1 EEST}
+ {2550704400 7200 0 EET}
+ {2563405200 10800 1 EEST}
+ {2582154000 7200 0 EET}
+ {2595459600 10800 1 EEST}
+ {2613603600 7200 0 EET}
+ {2626909200 10800 1 EEST}
+ {2645053200 7200 0 EET}
+ {2658358800 10800 1 EEST}
+ {2676502800 7200 0 EET}
+ {2689808400 10800 1 EEST}
+ {2708557200 7200 0 EET}
+ {2721258000 10800 1 EEST}
+ {2740006800 7200 0 EET}
+ {2752707600 10800 1 EEST}
+ {2771456400 7200 0 EET}
+ {2784762000 10800 1 EEST}
+ {2802906000 7200 0 EET}
+ {2816211600 10800 1 EEST}
+ {2834355600 7200 0 EET}
+ {2847661200 10800 1 EEST}
+ {2866410000 7200 0 EET}
+ {2879110800 10800 1 EEST}
+ {2897859600 7200 0 EET}
+ {2910560400 10800 1 EEST}
+ {2929309200 7200 0 EET}
+ {2942010000 10800 1 EEST}
+ {2960758800 7200 0 EET}
+ {2974064400 10800 1 EEST}
+ {2992208400 7200 0 EET}
+ {3005514000 10800 1 EEST}
+ {3023658000 7200 0 EET}
+ {3036963600 10800 1 EEST}
+ {3055712400 7200 0 EET}
+ {3068413200 10800 1 EEST}
+ {3087162000 7200 0 EET}
+ {3099862800 10800 1 EEST}
+ {3118611600 7200 0 EET}
+ {3131917200 10800 1 EEST}
+ {3150061200 7200 0 EET}
+ {3163366800 10800 1 EEST}
+ {3181510800 7200 0 EET}
+ {3194816400 10800 1 EEST}
+ {3212960400 7200 0 EET}
+ {3226266000 10800 1 EEST}
+ {3245014800 7200 0 EET}
+ {3257715600 10800 1 EEST}
+ {3276464400 7200 0 EET}
+ {3289165200 10800 1 EEST}
+ {3307914000 7200 0 EET}
+ {3321219600 10800 1 EEST}
+ {3339363600 7200 0 EET}
+ {3352669200 10800 1 EEST}
+ {3370813200 7200 0 EET}
+ {3384118800 10800 1 EEST}
+ {3402867600 7200 0 EET}
+ {3415568400 10800 1 EEST}
+ {3434317200 7200 0 EET}
+ {3447018000 10800 1 EEST}
+ {3465766800 7200 0 EET}
+ {3479072400 10800 1 EEST}
+ {3497216400 7200 0 EET}
+ {3510522000 10800 1 EEST}
+ {3528666000 7200 0 EET}
+ {3541971600 10800 1 EEST}
+ {3560115600 7200 0 EET}
+ {3573421200 10800 1 EEST}
+ {3592170000 7200 0 EET}
+ {3604870800 10800 1 EEST}
+ {3623619600 7200 0 EET}
+ {3636320400 10800 1 EEST}
+ {3655069200 7200 0 EET}
+ {3668374800 10800 1 EEST}
+ {3686518800 7200 0 EET}
+ {3699824400 10800 1 EEST}
+ {3717968400 7200 0 EET}
+ {3731274000 10800 1 EEST}
+ {3750022800 7200 0 EET}
+ {3762723600 10800 1 EEST}
+ {3781472400 7200 0 EET}
+ {3794173200 10800 1 EEST}
+ {3812922000 7200 0 EET}
+ {3825622800 10800 1 EEST}
+ {3844371600 7200 0 EET}
+ {3857677200 10800 1 EEST}
+ {3875821200 7200 0 EET}
+ {3889126800 10800 1 EEST}
+ {3907270800 7200 0 EET}
+ {3920576400 10800 1 EEST}
+ {3939325200 7200 0 EET}
+ {3952026000 10800 1 EEST}
+ {3970774800 7200 0 EET}
+ {3983475600 10800 1 EEST}
+ {4002224400 7200 0 EET}
+ {4015530000 10800 1 EEST}
+ {4033674000 7200 0 EET}
+ {4046979600 10800 1 EEST}
+ {4065123600 7200 0 EET}
+ {4078429200 10800 1 EEST}
+ {4096573200 7200 0 EET}
+}
diff --git a/library/tzdata/Europe/Jersey b/library/tzdata/Europe/Jersey
new file mode 100755
index 0000000..e4da512
--- /dev/null
+++ b/library/tzdata/Europe/Jersey
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/London)]} {
+ LoadTimeZoneFile Europe/London
+}
+set TZData(:Europe/Jersey) $TZData(:Europe/London)
diff --git a/library/tzdata/Europe/Kaliningrad b/library/tzdata/Europe/Kaliningrad
new file mode 100644
index 0000000..02b45d4
--- /dev/null
+++ b/library/tzdata/Europe/Kaliningrad
@@ -0,0 +1,84 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Kaliningrad) {
+ {-9223372036854775808 4920 0 LMT}
+ {-2422056120 3600 0 CET}
+ {-1693706400 7200 1 CEST}
+ {-1680483600 3600 0 CET}
+ {-1663455600 7200 1 CEST}
+ {-1650150000 3600 0 CET}
+ {-1632006000 7200 1 CEST}
+ {-1618700400 3600 0 CET}
+ {-938905200 7200 1 CEST}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-796777200 3600 0 CET}
+ {-788922000 7200 0 CET}
+ {-778730400 10800 1 CEST}
+ {-762663600 7200 0 CET}
+ {-757389600 10800 0 MSD}
+ {354920400 14400 1 MSD}
+ {370728000 10800 0 MSK}
+ {386456400 14400 1 MSD}
+ {402264000 10800 0 MSK}
+ {417992400 14400 1 MSD}
+ {433800000 10800 0 MSK}
+ {449614800 14400 1 MSD}
+ {465346800 10800 0 MSK}
+ {481071600 14400 1 MSD}
+ {496796400 10800 0 MSK}
+ {512521200 14400 1 MSD}
+ {528246000 10800 0 MSK}
+ {543970800 14400 1 MSD}
+ {559695600 10800 0 MSK}
+ {575420400 14400 1 MSD}
+ {591145200 10800 0 MSK}
+ {606870000 14400 1 MSD}
+ {622594800 10800 0 MSK}
+ {638319600 14400 1 MSD}
+ {654649200 10800 0 MSK}
+ {670374000 7200 0 EEMMTT}
+ {670377600 10800 1 EEST}
+ {686102400 7200 0 EET}
+ {701816400 10800 1 EEST}
+ {717537600 7200 0 EET}
+ {733276800 10800 1 EEST}
+ {749001600 7200 0 EET}
+ {764726400 10800 1 EEST}
+ {780451200 7200 0 EET}
+ {796176000 10800 1 EEST}
+ {811900800 7200 0 EET}
+ {828230400 10800 1 EEST}
+ {846374400 7200 0 EET}
+ {859680000 10800 1 EEST}
+ {877824000 7200 0 EET}
+ {891129600 10800 1 EEST}
+ {909273600 7200 0 EET}
+ {922579200 10800 1 EEST}
+ {941328000 7200 0 EET}
+ {954028800 10800 1 EEST}
+ {972777600 7200 0 EET}
+ {985478400 10800 1 EEST}
+ {1004227200 7200 0 EET}
+ {1017532800 10800 1 EEST}
+ {1035676800 7200 0 EET}
+ {1048982400 10800 1 EEST}
+ {1067126400 7200 0 EET}
+ {1080432000 10800 1 EEST}
+ {1099180800 7200 0 EET}
+ {1111881600 10800 1 EEST}
+ {1130630400 7200 0 EET}
+ {1143331200 10800 1 EEST}
+ {1162080000 7200 0 EET}
+ {1174780800 10800 1 EEST}
+ {1193529600 7200 0 EET}
+ {1206835200 10800 1 EEST}
+ {1224979200 7200 0 EET}
+ {1238284800 10800 1 EEST}
+ {1256428800 7200 0 EET}
+ {1269734400 10800 1 EEST}
+ {1288483200 7200 0 EET}
+ {1301184000 10800 0 EET}
+}
diff --git a/library/tzdata/Europe/Kiev b/library/tzdata/Europe/Kiev
new file mode 100644
index 0000000..0206be7
--- /dev/null
+++ b/library/tzdata/Europe/Kiev
@@ -0,0 +1,251 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Kiev) {
+ {-9223372036854775808 7324 0 LMT}
+ {-2840148124 7324 0 KMT}
+ {-1441159324 7200 0 EET}
+ {-1247536800 10800 0 MSK}
+ {-892522800 3600 0 CET}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-825382800 10800 0 MSD}
+ {354920400 14400 1 MSD}
+ {370728000 10800 0 MSK}
+ {386456400 14400 1 MSD}
+ {402264000 10800 0 MSK}
+ {417992400 14400 1 MSD}
+ {433800000 10800 0 MSK}
+ {449614800 14400 1 MSD}
+ {465346800 10800 0 MSK}
+ {481071600 14400 1 MSD}
+ {496796400 10800 0 MSK}
+ {512521200 14400 1 MSD}
+ {528246000 10800 0 MSK}
+ {543970800 14400 1 MSD}
+ {559695600 10800 0 MSK}
+ {575420400 14400 1 MSD}
+ {591145200 10800 0 MSK}
+ {606870000 14400 1 MSD}
+ {622594800 10800 0 MSK}
+ {631141200 10800 0 MSK}
+ {646786800 7200 0 EET}
+ {694216800 7200 0 EET}
+ {701820000 10800 1 EEST}
+ {717541200 7200 0 EET}
+ {733269600 10800 1 EEST}
+ {748990800 7200 0 EET}
+ {764719200 10800 1 EEST}
+ {780440400 7200 0 EET}
+ {788911200 7200 0 EET}
+ {796179600 10800 1 EEST}
+ {811904400 7200 0 EET}
+ {828234000 10800 1 EEST}
+ {846378000 7200 0 EET}
+ {859683600 10800 1 EEST}
+ {877827600 7200 0 EET}
+ {891133200 10800 1 EEST}
+ {909277200 7200 0 EET}
+ {922582800 10800 1 EEST}
+ {941331600 7200 0 EET}
+ {954032400 10800 1 EEST}
+ {972781200 7200 0 EET}
+ {985482000 10800 1 EEST}
+ {1004230800 7200 0 EET}
+ {1017536400 10800 1 EEST}
+ {1035680400 7200 0 EET}
+ {1048986000 10800 1 EEST}
+ {1067130000 7200 0 EET}
+ {1080435600 10800 1 EEST}
+ {1099184400 7200 0 EET}
+ {1111885200 10800 1 EEST}
+ {1130634000 7200 0 EET}
+ {1143334800 10800 1 EEST}
+ {1162083600 7200 0 EET}
+ {1174784400 10800 1 EEST}
+ {1193533200 7200 0 EET}
+ {1206838800 10800 1 EEST}
+ {1224982800 7200 0 EET}
+ {1238288400 10800 1 EEST}
+ {1256432400 7200 0 EET}
+ {1269738000 10800 1 EEST}
+ {1288486800 7200 0 EET}
+ {1301187600 10800 1 EEST}
+ {1319936400 7200 0 EET}
+ {1332637200 10800 1 EEST}
+ {1351386000 7200 0 EET}
+ {1364691600 10800 1 EEST}
+ {1382835600 7200 0 EET}
+ {1396141200 10800 1 EEST}
+ {1414285200 7200 0 EET}
+ {1427590800 10800 1 EEST}
+ {1445734800 7200 0 EET}
+ {1459040400 10800 1 EEST}
+ {1477789200 7200 0 EET}
+ {1490490000 10800 1 EEST}
+ {1509238800 7200 0 EET}
+ {1521939600 10800 1 EEST}
+ {1540688400 7200 0 EET}
+ {1553994000 10800 1 EEST}
+ {1572138000 7200 0 EET}
+ {1585443600 10800 1 EEST}
+ {1603587600 7200 0 EET}
+ {1616893200 10800 1 EEST}
+ {1635642000 7200 0 EET}
+ {1648342800 10800 1 EEST}
+ {1667091600 7200 0 EET}
+ {1679792400 10800 1 EEST}
+ {1698541200 7200 0 EET}
+ {1711846800 10800 1 EEST}
+ {1729990800 7200 0 EET}
+ {1743296400 10800 1 EEST}
+ {1761440400 7200 0 EET}
+ {1774746000 10800 1 EEST}
+ {1792890000 7200 0 EET}
+ {1806195600 10800 1 EEST}
+ {1824944400 7200 0 EET}
+ {1837645200 10800 1 EEST}
+ {1856394000 7200 0 EET}
+ {1869094800 10800 1 EEST}
+ {1887843600 7200 0 EET}
+ {1901149200 10800 1 EEST}
+ {1919293200 7200 0 EET}
+ {1932598800 10800 1 EEST}
+ {1950742800 7200 0 EET}
+ {1964048400 10800 1 EEST}
+ {1982797200 7200 0 EET}
+ {1995498000 10800 1 EEST}
+ {2014246800 7200 0 EET}
+ {2026947600 10800 1 EEST}
+ {2045696400 7200 0 EET}
+ {2058397200 10800 1 EEST}
+ {2077146000 7200 0 EET}
+ {2090451600 10800 1 EEST}
+ {2108595600 7200 0 EET}
+ {2121901200 10800 1 EEST}
+ {2140045200 7200 0 EET}
+ {2153350800 10800 1 EEST}
+ {2172099600 7200 0 EET}
+ {2184800400 10800 1 EEST}
+ {2203549200 7200 0 EET}
+ {2216250000 10800 1 EEST}
+ {2234998800 7200 0 EET}
+ {2248304400 10800 1 EEST}
+ {2266448400 7200 0 EET}
+ {2279754000 10800 1 EEST}
+ {2297898000 7200 0 EET}
+ {2311203600 10800 1 EEST}
+ {2329347600 7200 0 EET}
+ {2342653200 10800 1 EEST}
+ {2361402000 7200 0 EET}
+ {2374102800 10800 1 EEST}
+ {2392851600 7200 0 EET}
+ {2405552400 10800 1 EEST}
+ {2424301200 7200 0 EET}
+ {2437606800 10800 1 EEST}
+ {2455750800 7200 0 EET}
+ {2469056400 10800 1 EEST}
+ {2487200400 7200 0 EET}
+ {2500506000 10800 1 EEST}
+ {2519254800 7200 0 EET}
+ {2531955600 10800 1 EEST}
+ {2550704400 7200 0 EET}
+ {2563405200 10800 1 EEST}
+ {2582154000 7200 0 EET}
+ {2595459600 10800 1 EEST}
+ {2613603600 7200 0 EET}
+ {2626909200 10800 1 EEST}
+ {2645053200 7200 0 EET}
+ {2658358800 10800 1 EEST}
+ {2676502800 7200 0 EET}
+ {2689808400 10800 1 EEST}
+ {2708557200 7200 0 EET}
+ {2721258000 10800 1 EEST}
+ {2740006800 7200 0 EET}
+ {2752707600 10800 1 EEST}
+ {2771456400 7200 0 EET}
+ {2784762000 10800 1 EEST}
+ {2802906000 7200 0 EET}
+ {2816211600 10800 1 EEST}
+ {2834355600 7200 0 EET}
+ {2847661200 10800 1 EEST}
+ {2866410000 7200 0 EET}
+ {2879110800 10800 1 EEST}
+ {2897859600 7200 0 EET}
+ {2910560400 10800 1 EEST}
+ {2929309200 7200 0 EET}
+ {2942010000 10800 1 EEST}
+ {2960758800 7200 0 EET}
+ {2974064400 10800 1 EEST}
+ {2992208400 7200 0 EET}
+ {3005514000 10800 1 EEST}
+ {3023658000 7200 0 EET}
+ {3036963600 10800 1 EEST}
+ {3055712400 7200 0 EET}
+ {3068413200 10800 1 EEST}
+ {3087162000 7200 0 EET}
+ {3099862800 10800 1 EEST}
+ {3118611600 7200 0 EET}
+ {3131917200 10800 1 EEST}
+ {3150061200 7200 0 EET}
+ {3163366800 10800 1 EEST}
+ {3181510800 7200 0 EET}
+ {3194816400 10800 1 EEST}
+ {3212960400 7200 0 EET}
+ {3226266000 10800 1 EEST}
+ {3245014800 7200 0 EET}
+ {3257715600 10800 1 EEST}
+ {3276464400 7200 0 EET}
+ {3289165200 10800 1 EEST}
+ {3307914000 7200 0 EET}
+ {3321219600 10800 1 EEST}
+ {3339363600 7200 0 EET}
+ {3352669200 10800 1 EEST}
+ {3370813200 7200 0 EET}
+ {3384118800 10800 1 EEST}
+ {3402867600 7200 0 EET}
+ {3415568400 10800 1 EEST}
+ {3434317200 7200 0 EET}
+ {3447018000 10800 1 EEST}
+ {3465766800 7200 0 EET}
+ {3479072400 10800 1 EEST}
+ {3497216400 7200 0 EET}
+ {3510522000 10800 1 EEST}
+ {3528666000 7200 0 EET}
+ {3541971600 10800 1 EEST}
+ {3560115600 7200 0 EET}
+ {3573421200 10800 1 EEST}
+ {3592170000 7200 0 EET}
+ {3604870800 10800 1 EEST}
+ {3623619600 7200 0 EET}
+ {3636320400 10800 1 EEST}
+ {3655069200 7200 0 EET}
+ {3668374800 10800 1 EEST}
+ {3686518800 7200 0 EET}
+ {3699824400 10800 1 EEST}
+ {3717968400 7200 0 EET}
+ {3731274000 10800 1 EEST}
+ {3750022800 7200 0 EET}
+ {3762723600 10800 1 EEST}
+ {3781472400 7200 0 EET}
+ {3794173200 10800 1 EEST}
+ {3812922000 7200 0 EET}
+ {3825622800 10800 1 EEST}
+ {3844371600 7200 0 EET}
+ {3857677200 10800 1 EEST}
+ {3875821200 7200 0 EET}
+ {3889126800 10800 1 EEST}
+ {3907270800 7200 0 EET}
+ {3920576400 10800 1 EEST}
+ {3939325200 7200 0 EET}
+ {3952026000 10800 1 EEST}
+ {3970774800 7200 0 EET}
+ {3983475600 10800 1 EEST}
+ {4002224400 7200 0 EET}
+ {4015530000 10800 1 EEST}
+ {4033674000 7200 0 EET}
+ {4046979600 10800 1 EEST}
+ {4065123600 7200 0 EET}
+ {4078429200 10800 1 EEST}
+ {4096573200 7200 0 EET}
+}
diff --git a/library/tzdata/Europe/Lisbon b/library/tzdata/Europe/Lisbon
new file mode 100644
index 0000000..79c688a
--- /dev/null
+++ b/library/tzdata/Europe/Lisbon
@@ -0,0 +1,351 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Lisbon) {
+ {-9223372036854775808 -2192 0 LMT}
+ {-2713908208 -2192 0 LMT}
+ {-1830381808 0 0 WET}
+ {-1689555600 3600 1 WEST}
+ {-1677801600 0 0 WET}
+ {-1667437200 3600 1 WEST}
+ {-1647738000 0 0 WET}
+ {-1635814800 3600 1 WEST}
+ {-1616202000 0 0 WET}
+ {-1604365200 3600 1 WEST}
+ {-1584666000 0 0 WET}
+ {-1572742800 3600 1 WEST}
+ {-1553043600 0 0 WET}
+ {-1541206800 3600 1 WEST}
+ {-1521507600 0 0 WET}
+ {-1442451600 3600 1 WEST}
+ {-1426813200 0 0 WET}
+ {-1379293200 3600 1 WEST}
+ {-1364778000 0 0 WET}
+ {-1348448400 3600 1 WEST}
+ {-1333328400 0 0 WET}
+ {-1316394000 3600 1 WEST}
+ {-1301274000 0 0 WET}
+ {-1284339600 3600 1 WEST}
+ {-1269824400 0 0 WET}
+ {-1221440400 3600 1 WEST}
+ {-1206925200 0 0 WET}
+ {-1191200400 3600 1 WEST}
+ {-1175475600 0 0 WET}
+ {-1127696400 3600 1 WEST}
+ {-1111971600 0 0 WET}
+ {-1096851600 3600 1 WEST}
+ {-1080522000 0 0 WET}
+ {-1063587600 3600 1 WEST}
+ {-1049072400 0 0 WET}
+ {-1033347600 3600 1 WEST}
+ {-1017622800 0 0 WET}
+ {-1002502800 3600 1 WEST}
+ {-986173200 0 0 WET}
+ {-969238800 3600 1 WEST}
+ {-950490000 0 0 WET}
+ {-942022800 3600 1 WEST}
+ {-922669200 0 0 WET}
+ {-906944400 3600 1 WEST}
+ {-891133200 0 0 WET}
+ {-877309200 3600 1 WEST}
+ {-873684000 7200 1 WEMT}
+ {-864007200 3600 1 WEST}
+ {-857955600 0 0 WET}
+ {-845859600 3600 1 WEST}
+ {-842839200 7200 1 WEMT}
+ {-831348000 3600 1 WEST}
+ {-825901200 0 0 WET}
+ {-814410000 3600 1 WEST}
+ {-810784800 7200 1 WEMT}
+ {-799898400 3600 1 WEST}
+ {-794451600 0 0 WET}
+ {-782960400 3600 1 WEST}
+ {-779335200 7200 1 WEMT}
+ {-768448800 3600 1 WEST}
+ {-763002000 0 0 WET}
+ {-749091600 3600 1 WEST}
+ {-733366800 0 0 WET}
+ {-717631200 3600 1 WEST}
+ {-701906400 0 0 WET}
+ {-686181600 3600 1 WEST}
+ {-670456800 0 0 WET}
+ {-654732000 3600 1 WEST}
+ {-639007200 0 0 WET}
+ {-591832800 3600 1 WEST}
+ {-575503200 0 0 WET}
+ {-559778400 3600 1 WEST}
+ {-544053600 0 0 WET}
+ {-528328800 3600 1 WEST}
+ {-512604000 0 0 WET}
+ {-496879200 3600 1 WEST}
+ {-481154400 0 0 WET}
+ {-465429600 3600 1 WEST}
+ {-449704800 0 0 WET}
+ {-433980000 3600 1 WEST}
+ {-417650400 0 0 WET}
+ {-401925600 3600 1 WEST}
+ {-386200800 0 0 WET}
+ {-370476000 3600 1 WEST}
+ {-354751200 0 0 WET}
+ {-339026400 3600 1 WEST}
+ {-323301600 0 0 WET}
+ {-307576800 3600 1 WEST}
+ {-291852000 0 0 WET}
+ {-276127200 3600 1 WEST}
+ {-260402400 0 0 WET}
+ {-244677600 3600 1 WEST}
+ {-228348000 0 0 WET}
+ {-212623200 3600 1 WEST}
+ {-196898400 0 0 WET}
+ {-181173600 3600 1 WEST}
+ {-165448800 0 0 WET}
+ {-149724000 3600 1 WEST}
+ {-133999200 0 0 WET}
+ {-118274400 3600 0 CET}
+ {212544000 0 0 WET}
+ {228268800 3600 1 WEST}
+ {243993600 0 0 WET}
+ {260323200 3600 1 WEST}
+ {276048000 0 0 WET}
+ {291772800 3600 1 WEST}
+ {307501200 0 0 WET}
+ {323222400 3600 1 WEST}
+ {338950800 0 0 WET}
+ {354675600 3600 1 WEST}
+ {370400400 0 0 WET}
+ {386125200 3600 1 WEST}
+ {401850000 0 0 WET}
+ {417578400 3600 1 WEST}
+ {433299600 0 0 WET}
+ {449024400 3600 1 WEST}
+ {465354000 0 0 WET}
+ {481078800 3600 1 WEST}
+ {496803600 0 0 WET}
+ {512528400 3600 1 WEST}
+ {528253200 0 0 WET}
+ {543978000 3600 1 WEST}
+ {559702800 0 0 WET}
+ {575427600 3600 1 WEST}
+ {591152400 0 0 WET}
+ {606877200 3600 1 WEST}
+ {622602000 0 0 WET}
+ {638326800 3600 1 WEST}
+ {654656400 0 0 WET}
+ {670381200 3600 1 WEST}
+ {686106000 0 0 WET}
+ {701830800 3600 1 WEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 3600 0 WEST}
+ {846378000 0 0 WET}
+ {859683600 3600 1 WEST}
+ {877827600 0 0 WET}
+ {891133200 3600 1 WEST}
+ {909277200 0 0 WET}
+ {922582800 3600 1 WEST}
+ {941331600 0 0 WET}
+ {954032400 3600 1 WEST}
+ {972781200 0 0 WET}
+ {985482000 3600 1 WEST}
+ {1004230800 0 0 WET}
+ {1017536400 3600 1 WEST}
+ {1035680400 0 0 WET}
+ {1048986000 3600 1 WEST}
+ {1067130000 0 0 WET}
+ {1080435600 3600 1 WEST}
+ {1099184400 0 0 WET}
+ {1111885200 3600 1 WEST}
+ {1130634000 0 0 WET}
+ {1143334800 3600 1 WEST}
+ {1162083600 0 0 WET}
+ {1174784400 3600 1 WEST}
+ {1193533200 0 0 WET}
+ {1206838800 3600 1 WEST}
+ {1224982800 0 0 WET}
+ {1238288400 3600 1 WEST}
+ {1256432400 0 0 WET}
+ {1269738000 3600 1 WEST}
+ {1288486800 0 0 WET}
+ {1301187600 3600 1 WEST}
+ {1319936400 0 0 WET}
+ {1332637200 3600 1 WEST}
+ {1351386000 0 0 WET}
+ {1364691600 3600 1 WEST}
+ {1382835600 0 0 WET}
+ {1396141200 3600 1 WEST}
+ {1414285200 0 0 WET}
+ {1427590800 3600 1 WEST}
+ {1445734800 0 0 WET}
+ {1459040400 3600 1 WEST}
+ {1477789200 0 0 WET}
+ {1490490000 3600 1 WEST}
+ {1509238800 0 0 WET}
+ {1521939600 3600 1 WEST}
+ {1540688400 0 0 WET}
+ {1553994000 3600 1 WEST}
+ {1572138000 0 0 WET}
+ {1585443600 3600 1 WEST}
+ {1603587600 0 0 WET}
+ {1616893200 3600 1 WEST}
+ {1635642000 0 0 WET}
+ {1648342800 3600 1 WEST}
+ {1667091600 0 0 WET}
+ {1679792400 3600 1 WEST}
+ {1698541200 0 0 WET}
+ {1711846800 3600 1 WEST}
+ {1729990800 0 0 WET}
+ {1743296400 3600 1 WEST}
+ {1761440400 0 0 WET}
+ {1774746000 3600 1 WEST}
+ {1792890000 0 0 WET}
+ {1806195600 3600 1 WEST}
+ {1824944400 0 0 WET}
+ {1837645200 3600 1 WEST}
+ {1856394000 0 0 WET}
+ {1869094800 3600 1 WEST}
+ {1887843600 0 0 WET}
+ {1901149200 3600 1 WEST}
+ {1919293200 0 0 WET}
+ {1932598800 3600 1 WEST}
+ {1950742800 0 0 WET}
+ {1964048400 3600 1 WEST}
+ {1982797200 0 0 WET}
+ {1995498000 3600 1 WEST}
+ {2014246800 0 0 WET}
+ {2026947600 3600 1 WEST}
+ {2045696400 0 0 WET}
+ {2058397200 3600 1 WEST}
+ {2077146000 0 0 WET}
+ {2090451600 3600 1 WEST}
+ {2108595600 0 0 WET}
+ {2121901200 3600 1 WEST}
+ {2140045200 0 0 WET}
+ {2153350800 3600 1 WEST}
+ {2172099600 0 0 WET}
+ {2184800400 3600 1 WEST}
+ {2203549200 0 0 WET}
+ {2216250000 3600 1 WEST}
+ {2234998800 0 0 WET}
+ {2248304400 3600 1 WEST}
+ {2266448400 0 0 WET}
+ {2279754000 3600 1 WEST}
+ {2297898000 0 0 WET}
+ {2311203600 3600 1 WEST}
+ {2329347600 0 0 WET}
+ {2342653200 3600 1 WEST}
+ {2361402000 0 0 WET}
+ {2374102800 3600 1 WEST}
+ {2392851600 0 0 WET}
+ {2405552400 3600 1 WEST}
+ {2424301200 0 0 WET}
+ {2437606800 3600 1 WEST}
+ {2455750800 0 0 WET}
+ {2469056400 3600 1 WEST}
+ {2487200400 0 0 WET}
+ {2500506000 3600 1 WEST}
+ {2519254800 0 0 WET}
+ {2531955600 3600 1 WEST}
+ {2550704400 0 0 WET}
+ {2563405200 3600 1 WEST}
+ {2582154000 0 0 WET}
+ {2595459600 3600 1 WEST}
+ {2613603600 0 0 WET}
+ {2626909200 3600 1 WEST}
+ {2645053200 0 0 WET}
+ {2658358800 3600 1 WEST}
+ {2676502800 0 0 WET}
+ {2689808400 3600 1 WEST}
+ {2708557200 0 0 WET}
+ {2721258000 3600 1 WEST}
+ {2740006800 0 0 WET}
+ {2752707600 3600 1 WEST}
+ {2771456400 0 0 WET}
+ {2784762000 3600 1 WEST}
+ {2802906000 0 0 WET}
+ {2816211600 3600 1 WEST}
+ {2834355600 0 0 WET}
+ {2847661200 3600 1 WEST}
+ {2866410000 0 0 WET}
+ {2879110800 3600 1 WEST}
+ {2897859600 0 0 WET}
+ {2910560400 3600 1 WEST}
+ {2929309200 0 0 WET}
+ {2942010000 3600 1 WEST}
+ {2960758800 0 0 WET}
+ {2974064400 3600 1 WEST}
+ {2992208400 0 0 WET}
+ {3005514000 3600 1 WEST}
+ {3023658000 0 0 WET}
+ {3036963600 3600 1 WEST}
+ {3055712400 0 0 WET}
+ {3068413200 3600 1 WEST}
+ {3087162000 0 0 WET}
+ {3099862800 3600 1 WEST}
+ {3118611600 0 0 WET}
+ {3131917200 3600 1 WEST}
+ {3150061200 0 0 WET}
+ {3163366800 3600 1 WEST}
+ {3181510800 0 0 WET}
+ {3194816400 3600 1 WEST}
+ {3212960400 0 0 WET}
+ {3226266000 3600 1 WEST}
+ {3245014800 0 0 WET}
+ {3257715600 3600 1 WEST}
+ {3276464400 0 0 WET}
+ {3289165200 3600 1 WEST}
+ {3307914000 0 0 WET}
+ {3321219600 3600 1 WEST}
+ {3339363600 0 0 WET}
+ {3352669200 3600 1 WEST}
+ {3370813200 0 0 WET}
+ {3384118800 3600 1 WEST}
+ {3402867600 0 0 WET}
+ {3415568400 3600 1 WEST}
+ {3434317200 0 0 WET}
+ {3447018000 3600 1 WEST}
+ {3465766800 0 0 WET}
+ {3479072400 3600 1 WEST}
+ {3497216400 0 0 WET}
+ {3510522000 3600 1 WEST}
+ {3528666000 0 0 WET}
+ {3541971600 3600 1 WEST}
+ {3560115600 0 0 WET}
+ {3573421200 3600 1 WEST}
+ {3592170000 0 0 WET}
+ {3604870800 3600 1 WEST}
+ {3623619600 0 0 WET}
+ {3636320400 3600 1 WEST}
+ {3655069200 0 0 WET}
+ {3668374800 3600 1 WEST}
+ {3686518800 0 0 WET}
+ {3699824400 3600 1 WEST}
+ {3717968400 0 0 WET}
+ {3731274000 3600 1 WEST}
+ {3750022800 0 0 WET}
+ {3762723600 3600 1 WEST}
+ {3781472400 0 0 WET}
+ {3794173200 3600 1 WEST}
+ {3812922000 0 0 WET}
+ {3825622800 3600 1 WEST}
+ {3844371600 0 0 WET}
+ {3857677200 3600 1 WEST}
+ {3875821200 0 0 WET}
+ {3889126800 3600 1 WEST}
+ {3907270800 0 0 WET}
+ {3920576400 3600 1 WEST}
+ {3939325200 0 0 WET}
+ {3952026000 3600 1 WEST}
+ {3970774800 0 0 WET}
+ {3983475600 3600 1 WEST}
+ {4002224400 0 0 WET}
+ {4015530000 3600 1 WEST}
+ {4033674000 0 0 WET}
+ {4046979600 3600 1 WEST}
+ {4065123600 0 0 WET}
+ {4078429200 3600 1 WEST}
+ {4096573200 0 0 WET}
+}
diff --git a/library/tzdata/Europe/Ljubljana b/library/tzdata/Europe/Ljubljana
new file mode 100644
index 0000000..42c7df4
--- /dev/null
+++ b/library/tzdata/Europe/Ljubljana
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/Belgrade)]} {
+ LoadTimeZoneFile Europe/Belgrade
+}
+set TZData(:Europe/Ljubljana) $TZData(:Europe/Belgrade)
diff --git a/library/tzdata/Europe/London b/library/tzdata/Europe/London
new file mode 100644
index 0000000..2014e00
--- /dev/null
+++ b/library/tzdata/Europe/London
@@ -0,0 +1,372 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/London) {
+ {-9223372036854775808 -75 0 LMT}
+ {-3852662325 0 0 GMT}
+ {-1691964000 3600 1 BST}
+ {-1680472800 0 0 GMT}
+ {-1664143200 3600 1 BST}
+ {-1650146400 0 0 GMT}
+ {-1633903200 3600 1 BST}
+ {-1617487200 0 0 GMT}
+ {-1601848800 3600 1 BST}
+ {-1586037600 0 0 GMT}
+ {-1570399200 3600 1 BST}
+ {-1552168800 0 0 GMT}
+ {-1538344800 3600 1 BST}
+ {-1522533600 0 0 GMT}
+ {-1507500000 3600 1 BST}
+ {-1490565600 0 0 GMT}
+ {-1473631200 3600 1 BST}
+ {-1460930400 0 0 GMT}
+ {-1442786400 3600 1 BST}
+ {-1428876000 0 0 GMT}
+ {-1410732000 3600 1 BST}
+ {-1396216800 0 0 GMT}
+ {-1379282400 3600 1 BST}
+ {-1364767200 0 0 GMT}
+ {-1348437600 3600 1 BST}
+ {-1333317600 0 0 GMT}
+ {-1315778400 3600 1 BST}
+ {-1301263200 0 0 GMT}
+ {-1284328800 3600 1 BST}
+ {-1269813600 0 0 GMT}
+ {-1253484000 3600 1 BST}
+ {-1238364000 0 0 GMT}
+ {-1221429600 3600 1 BST}
+ {-1206914400 0 0 GMT}
+ {-1189980000 3600 1 BST}
+ {-1175464800 0 0 GMT}
+ {-1159135200 3600 1 BST}
+ {-1143410400 0 0 GMT}
+ {-1126476000 3600 1 BST}
+ {-1111960800 0 0 GMT}
+ {-1095631200 3600 1 BST}
+ {-1080511200 0 0 GMT}
+ {-1063576800 3600 1 BST}
+ {-1049061600 0 0 GMT}
+ {-1032127200 3600 1 BST}
+ {-1017612000 0 0 GMT}
+ {-1001282400 3600 1 BST}
+ {-986162400 0 0 GMT}
+ {-969228000 3600 1 BST}
+ {-950479200 0 0 GMT}
+ {-942012000 3600 1 BST}
+ {-904518000 7200 1 BDST}
+ {-896050800 3600 1 BST}
+ {-875487600 7200 1 BDST}
+ {-864601200 3600 1 BST}
+ {-844038000 7200 1 BDST}
+ {-832546800 3600 1 BST}
+ {-812588400 7200 1 BDST}
+ {-798073200 3600 1 BST}
+ {-781052400 7200 1 BDST}
+ {-772066800 3600 1 BST}
+ {-764805600 0 0 GMT}
+ {-748476000 3600 1 BST}
+ {-733356000 0 0 GMT}
+ {-719445600 3600 1 BST}
+ {-717030000 7200 1 BDST}
+ {-706748400 3600 1 BST}
+ {-699487200 0 0 GMT}
+ {-687996000 3600 1 BST}
+ {-668037600 0 0 GMT}
+ {-654732000 3600 1 BST}
+ {-636588000 0 0 GMT}
+ {-622072800 3600 1 BST}
+ {-605743200 0 0 GMT}
+ {-590623200 3600 1 BST}
+ {-574293600 0 0 GMT}
+ {-558568800 3600 1 BST}
+ {-542239200 0 0 GMT}
+ {-527119200 3600 1 BST}
+ {-512604000 0 0 GMT}
+ {-496274400 3600 1 BST}
+ {-481154400 0 0 GMT}
+ {-464220000 3600 1 BST}
+ {-449704800 0 0 GMT}
+ {-432165600 3600 1 BST}
+ {-417650400 0 0 GMT}
+ {-401320800 3600 1 BST}
+ {-386200800 0 0 GMT}
+ {-369266400 3600 1 BST}
+ {-354751200 0 0 GMT}
+ {-337816800 3600 1 BST}
+ {-323301600 0 0 GMT}
+ {-306972000 3600 1 BST}
+ {-291852000 0 0 GMT}
+ {-276732000 3600 1 BST}
+ {-257983200 0 0 GMT}
+ {-245282400 3600 1 BST}
+ {-226533600 0 0 GMT}
+ {-213228000 3600 1 BST}
+ {-195084000 0 0 GMT}
+ {-182383200 3600 1 BST}
+ {-163634400 0 0 GMT}
+ {-150933600 3600 1 BST}
+ {-132184800 0 0 GMT}
+ {-119484000 3600 1 BST}
+ {-100735200 0 0 GMT}
+ {-88034400 3600 1 BST}
+ {-68680800 0 0 GMT}
+ {-59004000 3600 1 BST}
+ {-37238400 3600 0 BST}
+ {57722400 0 0 GMT}
+ {69818400 3600 1 BST}
+ {89172000 0 0 GMT}
+ {101268000 3600 1 BST}
+ {120621600 0 0 GMT}
+ {132717600 3600 1 BST}
+ {152071200 0 0 GMT}
+ {164167200 3600 1 BST}
+ {183520800 0 0 GMT}
+ {196221600 3600 1 BST}
+ {214970400 0 0 GMT}
+ {227671200 3600 1 BST}
+ {246420000 0 0 GMT}
+ {259120800 3600 1 BST}
+ {278474400 0 0 GMT}
+ {290570400 3600 1 BST}
+ {309924000 0 0 GMT}
+ {322020000 3600 1 BST}
+ {341373600 0 0 GMT}
+ {354675600 3600 1 BST}
+ {372819600 0 0 GMT}
+ {386125200 3600 1 BST}
+ {404269200 0 0 GMT}
+ {417574800 3600 1 BST}
+ {435718800 0 0 GMT}
+ {449024400 3600 1 BST}
+ {467773200 0 0 GMT}
+ {481078800 3600 1 BST}
+ {499222800 0 0 GMT}
+ {512528400 3600 1 BST}
+ {530672400 0 0 GMT}
+ {543978000 3600 1 BST}
+ {562122000 0 0 GMT}
+ {575427600 3600 1 BST}
+ {593571600 0 0 GMT}
+ {606877200 3600 1 BST}
+ {625626000 0 0 GMT}
+ {638326800 3600 1 BST}
+ {657075600 0 0 GMT}
+ {670381200 3600 1 BST}
+ {688525200 0 0 GMT}
+ {701830800 3600 1 BST}
+ {719974800 0 0 GMT}
+ {733280400 3600 1 BST}
+ {751424400 0 0 GMT}
+ {764730000 3600 1 BST}
+ {782874000 0 0 GMT}
+ {796179600 3600 1 BST}
+ {814323600 0 0 GMT}
+ {820454400 0 0 GMT}
+ {828234000 3600 1 BST}
+ {846378000 0 0 GMT}
+ {859683600 3600 1 BST}
+ {877827600 0 0 GMT}
+ {891133200 3600 1 BST}
+ {909277200 0 0 GMT}
+ {922582800 3600 1 BST}
+ {941331600 0 0 GMT}
+ {954032400 3600 1 BST}
+ {972781200 0 0 GMT}
+ {985482000 3600 1 BST}
+ {1004230800 0 0 GMT}
+ {1017536400 3600 1 BST}
+ {1035680400 0 0 GMT}
+ {1048986000 3600 1 BST}
+ {1067130000 0 0 GMT}
+ {1080435600 3600 1 BST}
+ {1099184400 0 0 GMT}
+ {1111885200 3600 1 BST}
+ {1130634000 0 0 GMT}
+ {1143334800 3600 1 BST}
+ {1162083600 0 0 GMT}
+ {1174784400 3600 1 BST}
+ {1193533200 0 0 GMT}
+ {1206838800 3600 1 BST}
+ {1224982800 0 0 GMT}
+ {1238288400 3600 1 BST}
+ {1256432400 0 0 GMT}
+ {1269738000 3600 1 BST}
+ {1288486800 0 0 GMT}
+ {1301187600 3600 1 BST}
+ {1319936400 0 0 GMT}
+ {1332637200 3600 1 BST}
+ {1351386000 0 0 GMT}
+ {1364691600 3600 1 BST}
+ {1382835600 0 0 GMT}
+ {1396141200 3600 1 BST}
+ {1414285200 0 0 GMT}
+ {1427590800 3600 1 BST}
+ {1445734800 0 0 GMT}
+ {1459040400 3600 1 BST}
+ {1477789200 0 0 GMT}
+ {1490490000 3600 1 BST}
+ {1509238800 0 0 GMT}
+ {1521939600 3600 1 BST}
+ {1540688400 0 0 GMT}
+ {1553994000 3600 1 BST}
+ {1572138000 0 0 GMT}
+ {1585443600 3600 1 BST}
+ {1603587600 0 0 GMT}
+ {1616893200 3600 1 BST}
+ {1635642000 0 0 GMT}
+ {1648342800 3600 1 BST}
+ {1667091600 0 0 GMT}
+ {1679792400 3600 1 BST}
+ {1698541200 0 0 GMT}
+ {1711846800 3600 1 BST}
+ {1729990800 0 0 GMT}
+ {1743296400 3600 1 BST}
+ {1761440400 0 0 GMT}
+ {1774746000 3600 1 BST}
+ {1792890000 0 0 GMT}
+ {1806195600 3600 1 BST}
+ {1824944400 0 0 GMT}
+ {1837645200 3600 1 BST}
+ {1856394000 0 0 GMT}
+ {1869094800 3600 1 BST}
+ {1887843600 0 0 GMT}
+ {1901149200 3600 1 BST}
+ {1919293200 0 0 GMT}
+ {1932598800 3600 1 BST}
+ {1950742800 0 0 GMT}
+ {1964048400 3600 1 BST}
+ {1982797200 0 0 GMT}
+ {1995498000 3600 1 BST}
+ {2014246800 0 0 GMT}
+ {2026947600 3600 1 BST}
+ {2045696400 0 0 GMT}
+ {2058397200 3600 1 BST}
+ {2077146000 0 0 GMT}
+ {2090451600 3600 1 BST}
+ {2108595600 0 0 GMT}
+ {2121901200 3600 1 BST}
+ {2140045200 0 0 GMT}
+ {2153350800 3600 1 BST}
+ {2172099600 0 0 GMT}
+ {2184800400 3600 1 BST}
+ {2203549200 0 0 GMT}
+ {2216250000 3600 1 BST}
+ {2234998800 0 0 GMT}
+ {2248304400 3600 1 BST}
+ {2266448400 0 0 GMT}
+ {2279754000 3600 1 BST}
+ {2297898000 0 0 GMT}
+ {2311203600 3600 1 BST}
+ {2329347600 0 0 GMT}
+ {2342653200 3600 1 BST}
+ {2361402000 0 0 GMT}
+ {2374102800 3600 1 BST}
+ {2392851600 0 0 GMT}
+ {2405552400 3600 1 BST}
+ {2424301200 0 0 GMT}
+ {2437606800 3600 1 BST}
+ {2455750800 0 0 GMT}
+ {2469056400 3600 1 BST}
+ {2487200400 0 0 GMT}
+ {2500506000 3600 1 BST}
+ {2519254800 0 0 GMT}
+ {2531955600 3600 1 BST}
+ {2550704400 0 0 GMT}
+ {2563405200 3600 1 BST}
+ {2582154000 0 0 GMT}
+ {2595459600 3600 1 BST}
+ {2613603600 0 0 GMT}
+ {2626909200 3600 1 BST}
+ {2645053200 0 0 GMT}
+ {2658358800 3600 1 BST}
+ {2676502800 0 0 GMT}
+ {2689808400 3600 1 BST}
+ {2708557200 0 0 GMT}
+ {2721258000 3600 1 BST}
+ {2740006800 0 0 GMT}
+ {2752707600 3600 1 BST}
+ {2771456400 0 0 GMT}
+ {2784762000 3600 1 BST}
+ {2802906000 0 0 GMT}
+ {2816211600 3600 1 BST}
+ {2834355600 0 0 GMT}
+ {2847661200 3600 1 BST}
+ {2866410000 0 0 GMT}
+ {2879110800 3600 1 BST}
+ {2897859600 0 0 GMT}
+ {2910560400 3600 1 BST}
+ {2929309200 0 0 GMT}
+ {2942010000 3600 1 BST}
+ {2960758800 0 0 GMT}
+ {2974064400 3600 1 BST}
+ {2992208400 0 0 GMT}
+ {3005514000 3600 1 BST}
+ {3023658000 0 0 GMT}
+ {3036963600 3600 1 BST}
+ {3055712400 0 0 GMT}
+ {3068413200 3600 1 BST}
+ {3087162000 0 0 GMT}
+ {3099862800 3600 1 BST}
+ {3118611600 0 0 GMT}
+ {3131917200 3600 1 BST}
+ {3150061200 0 0 GMT}
+ {3163366800 3600 1 BST}
+ {3181510800 0 0 GMT}
+ {3194816400 3600 1 BST}
+ {3212960400 0 0 GMT}
+ {3226266000 3600 1 BST}
+ {3245014800 0 0 GMT}
+ {3257715600 3600 1 BST}
+ {3276464400 0 0 GMT}
+ {3289165200 3600 1 BST}
+ {3307914000 0 0 GMT}
+ {3321219600 3600 1 BST}
+ {3339363600 0 0 GMT}
+ {3352669200 3600 1 BST}
+ {3370813200 0 0 GMT}
+ {3384118800 3600 1 BST}
+ {3402867600 0 0 GMT}
+ {3415568400 3600 1 BST}
+ {3434317200 0 0 GMT}
+ {3447018000 3600 1 BST}
+ {3465766800 0 0 GMT}
+ {3479072400 3600 1 BST}
+ {3497216400 0 0 GMT}
+ {3510522000 3600 1 BST}
+ {3528666000 0 0 GMT}
+ {3541971600 3600 1 BST}
+ {3560115600 0 0 GMT}
+ {3573421200 3600 1 BST}
+ {3592170000 0 0 GMT}
+ {3604870800 3600 1 BST}
+ {3623619600 0 0 GMT}
+ {3636320400 3600 1 BST}
+ {3655069200 0 0 GMT}
+ {3668374800 3600 1 BST}
+ {3686518800 0 0 GMT}
+ {3699824400 3600 1 BST}
+ {3717968400 0 0 GMT}
+ {3731274000 3600 1 BST}
+ {3750022800 0 0 GMT}
+ {3762723600 3600 1 BST}
+ {3781472400 0 0 GMT}
+ {3794173200 3600 1 BST}
+ {3812922000 0 0 GMT}
+ {3825622800 3600 1 BST}
+ {3844371600 0 0 GMT}
+ {3857677200 3600 1 BST}
+ {3875821200 0 0 GMT}
+ {3889126800 3600 1 BST}
+ {3907270800 0 0 GMT}
+ {3920576400 3600 1 BST}
+ {3939325200 0 0 GMT}
+ {3952026000 3600 1 BST}
+ {3970774800 0 0 GMT}
+ {3983475600 3600 1 BST}
+ {4002224400 0 0 GMT}
+ {4015530000 3600 1 BST}
+ {4033674000 0 0 GMT}
+ {4046979600 3600 1 BST}
+ {4065123600 0 0 GMT}
+ {4078429200 3600 1 BST}
+ {4096573200 0 0 GMT}
+}
diff --git a/library/tzdata/Europe/Luxembourg b/library/tzdata/Europe/Luxembourg
new file mode 100644
index 0000000..2a88c4b
--- /dev/null
+++ b/library/tzdata/Europe/Luxembourg
@@ -0,0 +1,313 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Luxembourg) {
+ {-9223372036854775808 1476 0 LMT}
+ {-2069713476 3600 0 CET}
+ {-1692496800 7200 1 CEST}
+ {-1680483600 3600 0 CET}
+ {-1662343200 7200 1 CEST}
+ {-1650157200 3600 0 CET}
+ {-1632006000 7200 1 CEST}
+ {-1618700400 3600 0 CET}
+ {-1612659600 0 0 WET}
+ {-1604278800 3600 1 WEST}
+ {-1585519200 0 0 WET}
+ {-1574038800 3600 1 WEST}
+ {-1552258800 0 0 WET}
+ {-1539997200 3600 1 WEST}
+ {-1520550000 0 0 WET}
+ {-1507510800 3600 1 WEST}
+ {-1490572800 0 0 WET}
+ {-1473642000 3600 1 WEST}
+ {-1459119600 0 0 WET}
+ {-1444006800 3600 1 WEST}
+ {-1427673600 0 0 WET}
+ {-1411866000 3600 1 WEST}
+ {-1396224000 0 0 WET}
+ {-1379293200 3600 1 WEST}
+ {-1364774400 0 0 WET}
+ {-1348448400 3600 1 WEST}
+ {-1333324800 0 0 WET}
+ {-1316394000 3600 1 WEST}
+ {-1301270400 0 0 WET}
+ {-1284339600 3600 1 WEST}
+ {-1269813600 0 0 WET}
+ {-1253484000 3600 1 WEST}
+ {-1238364000 0 0 WET}
+ {-1221429600 3600 1 WEST}
+ {-1206914400 0 0 WET}
+ {-1191189600 3600 1 WEST}
+ {-1175464800 0 0 WET}
+ {-1160344800 3600 1 WEST}
+ {-1143410400 0 0 WET}
+ {-1127685600 3600 1 WEST}
+ {-1111960800 0 0 WET}
+ {-1096840800 3600 1 WEST}
+ {-1080511200 0 0 WET}
+ {-1063576800 3600 1 WEST}
+ {-1049061600 0 0 WET}
+ {-1033336800 3600 1 WEST}
+ {-1017612000 0 0 WET}
+ {-1002492000 3600 1 WEST}
+ {-986162400 0 0 WET}
+ {-969228000 3600 1 WEST}
+ {-950479200 0 0 WET}
+ {-942012000 3600 1 WEST}
+ {-935186400 7200 0 WEST}
+ {-857257200 3600 0 WET}
+ {-844556400 7200 1 WEST}
+ {-828226800 3600 0 WET}
+ {-812502000 7200 1 WEST}
+ {-797983200 3600 0 CET}
+ {-781052400 7200 1 CEST}
+ {-766623600 3600 0 CET}
+ {-745455600 7200 1 CEST}
+ {-733273200 3600 0 CET}
+ {220921200 3600 0 CET}
+ {228877200 7200 1 CEST}
+ {243997200 3600 0 CET}
+ {260326800 7200 1 CEST}
+ {276051600 3600 0 CET}
+ {291776400 7200 1 CEST}
+ {307501200 3600 0 CET}
+ {323830800 7200 1 CEST}
+ {338950800 3600 0 CET}
+ {354675600 7200 1 CEST}
+ {370400400 3600 0 CET}
+ {386125200 7200 1 CEST}
+ {401850000 3600 0 CET}
+ {417574800 7200 1 CEST}
+ {433299600 3600 0 CET}
+ {449024400 7200 1 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Madrid b/library/tzdata/Europe/Madrid
new file mode 100644
index 0000000..50de14f
--- /dev/null
+++ b/library/tzdata/Europe/Madrid
@@ -0,0 +1,294 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Madrid) {
+ {-9223372036854775808 -884 0 LMT}
+ {-2177451916 0 0 WET}
+ {-1661734800 3600 1 WEST}
+ {-1648429200 0 0 WET}
+ {-1631926800 3600 1 WEST}
+ {-1616893200 0 0 WET}
+ {-1601254800 3600 1 WEST}
+ {-1585357200 0 0 WET}
+ {-1442451600 3600 1 WEST}
+ {-1427677200 0 0 WET}
+ {-1379293200 3600 1 WEST}
+ {-1364778000 0 0 WET}
+ {-1348448400 3600 1 WEST}
+ {-1333328400 0 0 WET}
+ {-1316394000 3600 1 WEST}
+ {-1301274000 0 0 WET}
+ {-1284339600 3600 1 WEST}
+ {-1269824400 0 0 WET}
+ {-1029114000 3600 1 WEST}
+ {-1017622800 0 0 WET}
+ {-1002848400 3600 1 WEST}
+ {-986173200 0 0 WET}
+ {-969238800 3600 1 WEST}
+ {-954118800 0 0 WET}
+ {-940208400 3600 1 WEST}
+ {-873079200 7200 1 WEMT}
+ {-862538400 3600 1 WEST}
+ {-842839200 7200 1 WEMT}
+ {-828237600 3600 1 WEST}
+ {-811389600 7200 1 WEMT}
+ {-796010400 3600 1 WEST}
+ {-779940000 7200 1 WEMT}
+ {-765421200 3600 1 WEST}
+ {-748490400 7200 1 WEMT}
+ {-733881600 3600 0 CET}
+ {-652327200 7200 1 CEST}
+ {-639190800 3600 0 CET}
+ {135122400 7200 1 CEST}
+ {150246000 3600 0 CET}
+ {167176800 7200 1 CEST}
+ {181695600 3600 0 CET}
+ {196812000 7200 1 CEST}
+ {212540400 3600 0 CET}
+ {228866400 7200 1 CEST}
+ {243990000 3600 0 CET}
+ {260402400 7200 1 CEST}
+ {276044400 3600 0 CET}
+ {283993200 3600 0 CET}
+ {291776400 7200 1 CEST}
+ {307501200 3600 0 CET}
+ {323830800 7200 1 CEST}
+ {338950800 3600 0 CET}
+ {354675600 7200 1 CEST}
+ {370400400 3600 0 CET}
+ {386125200 7200 1 CEST}
+ {401850000 3600 0 CET}
+ {417574800 7200 1 CEST}
+ {433299600 3600 0 CET}
+ {449024400 7200 1 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Malta b/library/tzdata/Europe/Malta
new file mode 100644
index 0000000..b84f68e
--- /dev/null
+++ b/library/tzdata/Europe/Malta
@@ -0,0 +1,299 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Malta) {
+ {-9223372036854775808 3484 0 LMT}
+ {-2403478684 3600 0 CET}
+ {-1690851600 7200 1 CEST}
+ {-1680483600 3600 0 CET}
+ {-1664758800 7200 1 CEST}
+ {-1649034000 3600 0 CET}
+ {-1635123600 7200 1 CEST}
+ {-1616979600 3600 0 CET}
+ {-1604278800 7200 1 CEST}
+ {-1585530000 3600 0 CET}
+ {-1571014800 7200 1 CEST}
+ {-1555290000 3600 0 CET}
+ {-932432400 7200 1 CEST}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-796777200 3600 0 CET}
+ {-781052400 7200 0 CEST}
+ {-766717200 3600 0 CET}
+ {-750898800 7200 1 CEST}
+ {-733359600 3600 0 CET}
+ {-719456400 7200 1 CEST}
+ {-701917200 3600 0 CET}
+ {-689209200 7200 1 CEST}
+ {-670460400 3600 0 CET}
+ {-114051600 7200 1 CEST}
+ {-103168800 3600 0 CET}
+ {-81997200 7200 1 CEST}
+ {-71719200 3600 0 CET}
+ {-50547600 7200 1 CEST}
+ {-40269600 3600 0 CET}
+ {-18493200 7200 1 CEST}
+ {-8215200 3600 0 CET}
+ {12956400 7200 1 CEST}
+ {23234400 3600 0 CET}
+ {43801200 7200 1 CEST}
+ {54687600 3600 0 CET}
+ {75855600 7200 1 CEST}
+ {86738400 3600 0 CET}
+ {102380400 7200 0 CEST}
+ {118105200 3600 0 CET}
+ {135730800 7200 1 CEST}
+ {148518000 3600 0 CET}
+ {167187600 7200 1 CEST}
+ {180489600 3600 0 CET}
+ {198637200 7200 1 CEST}
+ {211939200 3600 0 CET}
+ {230086800 7200 1 CEST}
+ {243388800 3600 0 CET}
+ {261536400 7200 1 CEST}
+ {274838400 3600 0 CET}
+ {292986000 7200 1 CEST}
+ {306288000 3600 0 CET}
+ {323312400 7200 1 CEST}
+ {338342400 3600 0 CET}
+ {347151600 3600 0 CET}
+ {354675600 7200 1 CEST}
+ {370400400 3600 0 CET}
+ {386125200 7200 1 CEST}
+ {401850000 3600 0 CET}
+ {417574800 7200 1 CEST}
+ {433299600 3600 0 CET}
+ {449024400 7200 1 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Mariehamn b/library/tzdata/Europe/Mariehamn
new file mode 100644
index 0000000..26d9177
--- /dev/null
+++ b/library/tzdata/Europe/Mariehamn
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/Helsinki)]} {
+ LoadTimeZoneFile Europe/Helsinki
+}
+set TZData(:Europe/Mariehamn) $TZData(:Europe/Helsinki)
diff --git a/library/tzdata/Europe/Minsk b/library/tzdata/Europe/Minsk
new file mode 100644
index 0000000..d7d9434
--- /dev/null
+++ b/library/tzdata/Europe/Minsk
@@ -0,0 +1,251 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Minsk) {
+ {-9223372036854775808 6616 0 LMT}
+ {-2840147416 6600 0 MMT}
+ {-1441158600 7200 0 EET}
+ {-1247536800 10800 0 MSK}
+ {-899780400 3600 0 CET}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-804646800 10800 0 MSD}
+ {354920400 14400 1 MSD}
+ {370728000 10800 0 MSK}
+ {386456400 14400 1 MSD}
+ {402264000 10800 0 MSK}
+ {417992400 14400 1 MSD}
+ {433800000 10800 0 MSK}
+ {449614800 14400 1 MSD}
+ {465346800 10800 0 MSK}
+ {481071600 14400 1 MSD}
+ {496796400 10800 0 MSK}
+ {512521200 14400 1 MSD}
+ {528246000 10800 0 MSK}
+ {543970800 14400 1 MSD}
+ {559695600 10800 0 MSK}
+ {575420400 14400 1 MSD}
+ {591145200 10800 0 MSK}
+ {606870000 14400 1 MSD}
+ {622594800 10800 0 MSK}
+ {631141200 10800 0 MSK}
+ {670374000 10800 1 EEST}
+ {686102400 7200 0 EET}
+ {701820000 10800 1 EEST}
+ {717544800 7200 0 EET}
+ {733276800 10800 1 EEST}
+ {749001600 7200 0 EET}
+ {764726400 10800 1 EEST}
+ {780451200 7200 0 EET}
+ {796176000 10800 1 EEST}
+ {811900800 7200 0 EET}
+ {828230400 10800 1 EEST}
+ {846374400 7200 0 EET}
+ {859680000 10800 1 EEST}
+ {877824000 7200 0 EET}
+ {891129600 10800 1 EEST}
+ {909273600 7200 0 EET}
+ {922579200 10800 1 EEST}
+ {941328000 7200 0 EET}
+ {954028800 10800 1 EEST}
+ {972777600 7200 0 EET}
+ {985478400 10800 1 EEST}
+ {1004227200 7200 0 EET}
+ {1017532800 10800 1 EEST}
+ {1035676800 7200 0 EET}
+ {1048982400 10800 1 EEST}
+ {1067126400 7200 0 EET}
+ {1080432000 10800 1 EEST}
+ {1099180800 7200 0 EET}
+ {1111881600 10800 1 EEST}
+ {1130630400 7200 0 EET}
+ {1143331200 10800 1 EEST}
+ {1162080000 7200 0 EET}
+ {1174780800 10800 1 EEST}
+ {1193529600 7200 0 EET}
+ {1206835200 10800 1 EEST}
+ {1224979200 7200 0 EET}
+ {1238284800 10800 1 EEST}
+ {1256428800 7200 0 EET}
+ {1269734400 10800 1 EEST}
+ {1288483200 7200 0 EET}
+ {1301184000 10800 1 EEST}
+ {1319932800 7200 0 EET}
+ {1332633600 10800 1 EEST}
+ {1351382400 7200 0 EET}
+ {1364688000 10800 1 EEST}
+ {1382832000 7200 0 EET}
+ {1396137600 10800 1 EEST}
+ {1414281600 7200 0 EET}
+ {1427587200 10800 1 EEST}
+ {1445731200 7200 0 EET}
+ {1459036800 10800 1 EEST}
+ {1477785600 7200 0 EET}
+ {1490486400 10800 1 EEST}
+ {1509235200 7200 0 EET}
+ {1521936000 10800 1 EEST}
+ {1540684800 7200 0 EET}
+ {1553990400 10800 1 EEST}
+ {1572134400 7200 0 EET}
+ {1585440000 10800 1 EEST}
+ {1603584000 7200 0 EET}
+ {1616889600 10800 1 EEST}
+ {1635638400 7200 0 EET}
+ {1648339200 10800 1 EEST}
+ {1667088000 7200 0 EET}
+ {1679788800 10800 1 EEST}
+ {1698537600 7200 0 EET}
+ {1711843200 10800 1 EEST}
+ {1729987200 7200 0 EET}
+ {1743292800 10800 1 EEST}
+ {1761436800 7200 0 EET}
+ {1774742400 10800 1 EEST}
+ {1792886400 7200 0 EET}
+ {1806192000 10800 1 EEST}
+ {1824940800 7200 0 EET}
+ {1837641600 10800 1 EEST}
+ {1856390400 7200 0 EET}
+ {1869091200 10800 1 EEST}
+ {1887840000 7200 0 EET}
+ {1901145600 10800 1 EEST}
+ {1919289600 7200 0 EET}
+ {1932595200 10800 1 EEST}
+ {1950739200 7200 0 EET}
+ {1964044800 10800 1 EEST}
+ {1982793600 7200 0 EET}
+ {1995494400 10800 1 EEST}
+ {2014243200 7200 0 EET}
+ {2026944000 10800 1 EEST}
+ {2045692800 7200 0 EET}
+ {2058393600 10800 1 EEST}
+ {2077142400 7200 0 EET}
+ {2090448000 10800 1 EEST}
+ {2108592000 7200 0 EET}
+ {2121897600 10800 1 EEST}
+ {2140041600 7200 0 EET}
+ {2153347200 10800 1 EEST}
+ {2172096000 7200 0 EET}
+ {2184796800 10800 1 EEST}
+ {2203545600 7200 0 EET}
+ {2216246400 10800 1 EEST}
+ {2234995200 7200 0 EET}
+ {2248300800 10800 1 EEST}
+ {2266444800 7200 0 EET}
+ {2279750400 10800 1 EEST}
+ {2297894400 7200 0 EET}
+ {2311200000 10800 1 EEST}
+ {2329344000 7200 0 EET}
+ {2342649600 10800 1 EEST}
+ {2361398400 7200 0 EET}
+ {2374099200 10800 1 EEST}
+ {2392848000 7200 0 EET}
+ {2405548800 10800 1 EEST}
+ {2424297600 7200 0 EET}
+ {2437603200 10800 1 EEST}
+ {2455747200 7200 0 EET}
+ {2469052800 10800 1 EEST}
+ {2487196800 7200 0 EET}
+ {2500502400 10800 1 EEST}
+ {2519251200 7200 0 EET}
+ {2531952000 10800 1 EEST}
+ {2550700800 7200 0 EET}
+ {2563401600 10800 1 EEST}
+ {2582150400 7200 0 EET}
+ {2595456000 10800 1 EEST}
+ {2613600000 7200 0 EET}
+ {2626905600 10800 1 EEST}
+ {2645049600 7200 0 EET}
+ {2658355200 10800 1 EEST}
+ {2676499200 7200 0 EET}
+ {2689804800 10800 1 EEST}
+ {2708553600 7200 0 EET}
+ {2721254400 10800 1 EEST}
+ {2740003200 7200 0 EET}
+ {2752704000 10800 1 EEST}
+ {2771452800 7200 0 EET}
+ {2784758400 10800 1 EEST}
+ {2802902400 7200 0 EET}
+ {2816208000 10800 1 EEST}
+ {2834352000 7200 0 EET}
+ {2847657600 10800 1 EEST}
+ {2866406400 7200 0 EET}
+ {2879107200 10800 1 EEST}
+ {2897856000 7200 0 EET}
+ {2910556800 10800 1 EEST}
+ {2929305600 7200 0 EET}
+ {2942006400 10800 1 EEST}
+ {2960755200 7200 0 EET}
+ {2974060800 10800 1 EEST}
+ {2992204800 7200 0 EET}
+ {3005510400 10800 1 EEST}
+ {3023654400 7200 0 EET}
+ {3036960000 10800 1 EEST}
+ {3055708800 7200 0 EET}
+ {3068409600 10800 1 EEST}
+ {3087158400 7200 0 EET}
+ {3099859200 10800 1 EEST}
+ {3118608000 7200 0 EET}
+ {3131913600 10800 1 EEST}
+ {3150057600 7200 0 EET}
+ {3163363200 10800 1 EEST}
+ {3181507200 7200 0 EET}
+ {3194812800 10800 1 EEST}
+ {3212956800 7200 0 EET}
+ {3226262400 10800 1 EEST}
+ {3245011200 7200 0 EET}
+ {3257712000 10800 1 EEST}
+ {3276460800 7200 0 EET}
+ {3289161600 10800 1 EEST}
+ {3307910400 7200 0 EET}
+ {3321216000 10800 1 EEST}
+ {3339360000 7200 0 EET}
+ {3352665600 10800 1 EEST}
+ {3370809600 7200 0 EET}
+ {3384115200 10800 1 EEST}
+ {3402864000 7200 0 EET}
+ {3415564800 10800 1 EEST}
+ {3434313600 7200 0 EET}
+ {3447014400 10800 1 EEST}
+ {3465763200 7200 0 EET}
+ {3479068800 10800 1 EEST}
+ {3497212800 7200 0 EET}
+ {3510518400 10800 1 EEST}
+ {3528662400 7200 0 EET}
+ {3541968000 10800 1 EEST}
+ {3560112000 7200 0 EET}
+ {3573417600 10800 1 EEST}
+ {3592166400 7200 0 EET}
+ {3604867200 10800 1 EEST}
+ {3623616000 7200 0 EET}
+ {3636316800 10800 1 EEST}
+ {3655065600 7200 0 EET}
+ {3668371200 10800 1 EEST}
+ {3686515200 7200 0 EET}
+ {3699820800 10800 1 EEST}
+ {3717964800 7200 0 EET}
+ {3731270400 10800 1 EEST}
+ {3750019200 7200 0 EET}
+ {3762720000 10800 1 EEST}
+ {3781468800 7200 0 EET}
+ {3794169600 10800 1 EEST}
+ {3812918400 7200 0 EET}
+ {3825619200 10800 1 EEST}
+ {3844368000 7200 0 EET}
+ {3857673600 10800 1 EEST}
+ {3875817600 7200 0 EET}
+ {3889123200 10800 1 EEST}
+ {3907267200 7200 0 EET}
+ {3920572800 10800 1 EEST}
+ {3939321600 7200 0 EET}
+ {3952022400 10800 1 EEST}
+ {3970771200 7200 0 EET}
+ {3983472000 10800 1 EEST}
+ {4002220800 7200 0 EET}
+ {4015526400 10800 1 EEST}
+ {4033670400 7200 0 EET}
+ {4046976000 10800 1 EEST}
+ {4065120000 7200 0 EET}
+ {4078425600 10800 1 EEST}
+ {4096569600 7200 0 EET}
+}
diff --git a/library/tzdata/Europe/Monaco b/library/tzdata/Europe/Monaco
new file mode 100644
index 0000000..f887b0b
--- /dev/null
+++ b/library/tzdata/Europe/Monaco
@@ -0,0 +1,315 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Monaco) {
+ {-9223372036854775808 1772 0 LMT}
+ {-2486680172 561 0 PMT}
+ {-1855958961 0 0 WET}
+ {-1689814800 3600 1 WEST}
+ {-1680397200 0 0 WET}
+ {-1665363600 3600 1 WEST}
+ {-1648342800 0 0 WET}
+ {-1635123600 3600 1 WEST}
+ {-1616893200 0 0 WET}
+ {-1604278800 3600 1 WEST}
+ {-1585443600 0 0 WET}
+ {-1574038800 3600 1 WEST}
+ {-1552266000 0 0 WET}
+ {-1539997200 3600 1 WEST}
+ {-1520557200 0 0 WET}
+ {-1507510800 3600 1 WEST}
+ {-1490576400 0 0 WET}
+ {-1470618000 3600 1 WEST}
+ {-1459126800 0 0 WET}
+ {-1444006800 3600 1 WEST}
+ {-1427677200 0 0 WET}
+ {-1411952400 3600 1 WEST}
+ {-1396227600 0 0 WET}
+ {-1379293200 3600 1 WEST}
+ {-1364778000 0 0 WET}
+ {-1348448400 3600 1 WEST}
+ {-1333328400 0 0 WET}
+ {-1316394000 3600 1 WEST}
+ {-1301274000 0 0 WET}
+ {-1284339600 3600 1 WEST}
+ {-1269824400 0 0 WET}
+ {-1253494800 3600 1 WEST}
+ {-1238374800 0 0 WET}
+ {-1221440400 3600 1 WEST}
+ {-1206925200 0 0 WET}
+ {-1191200400 3600 1 WEST}
+ {-1175475600 0 0 WET}
+ {-1160355600 3600 1 WEST}
+ {-1143421200 0 0 WET}
+ {-1127696400 3600 1 WEST}
+ {-1111971600 0 0 WET}
+ {-1096851600 3600 1 WEST}
+ {-1080522000 0 0 WET}
+ {-1063587600 3600 1 WEST}
+ {-1049072400 0 0 WET}
+ {-1033347600 3600 1 WEST}
+ {-1017622800 0 0 WET}
+ {-1002502800 3600 1 WEST}
+ {-986173200 0 0 WET}
+ {-969238800 3600 1 WEST}
+ {-950490000 0 0 WET}
+ {-942012000 3600 1 WEST}
+ {-904438800 7200 1 WEMT}
+ {-891136800 3600 1 WEST}
+ {-877827600 7200 1 WEMT}
+ {-857257200 3600 1 WEST}
+ {-844556400 7200 1 WEMT}
+ {-828226800 3600 1 WEST}
+ {-812502000 7200 1 WEMT}
+ {-796266000 3600 1 WEST}
+ {-781052400 7200 1 WEMT}
+ {-766616400 3600 0 CET}
+ {196819200 7200 1 CEST}
+ {212540400 3600 0 CET}
+ {220921200 3600 0 CET}
+ {228877200 7200 1 CEST}
+ {243997200 3600 0 CET}
+ {260326800 7200 1 CEST}
+ {276051600 3600 0 CET}
+ {291776400 7200 1 CEST}
+ {307501200 3600 0 CET}
+ {323830800 7200 1 CEST}
+ {338950800 3600 0 CET}
+ {354675600 7200 1 CEST}
+ {370400400 3600 0 CET}
+ {386125200 7200 1 CEST}
+ {401850000 3600 0 CET}
+ {417574800 7200 1 CEST}
+ {433299600 3600 0 CET}
+ {449024400 7200 1 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Moscow b/library/tzdata/Europe/Moscow
new file mode 100644
index 0000000..8f40741
--- /dev/null
+++ b/library/tzdata/Europe/Moscow
@@ -0,0 +1,83 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Moscow) {
+ {-9223372036854775808 9020 0 LMT}
+ {-2840149820 9000 0 MMT}
+ {-1688265000 9048 0 MMT}
+ {-1656819048 12648 1 MST}
+ {-1641353448 9048 0 MMT}
+ {-1627965048 16248 1 MDST}
+ {-1618716648 12648 1 MST}
+ {-1596429048 16248 1 MDST}
+ {-1593822648 14400 0 MSD}
+ {-1589860800 10800 0 MSK}
+ {-1542427200 14400 1 MSD}
+ {-1539493200 18000 1 MSD}
+ {-1525323600 14400 1 MSD}
+ {-1522728000 10800 0 MSK}
+ {-1491188400 7200 0 EET}
+ {-1247536800 10800 0 MSD}
+ {354920400 14400 1 MSD}
+ {370728000 10800 0 MSK}
+ {386456400 14400 1 MSD}
+ {402264000 10800 0 MSK}
+ {417992400 14400 1 MSD}
+ {433800000 10800 0 MSK}
+ {449614800 14400 1 MSD}
+ {465346800 10800 0 MSK}
+ {481071600 14400 1 MSD}
+ {496796400 10800 0 MSK}
+ {512521200 14400 1 MSD}
+ {528246000 10800 0 MSK}
+ {543970800 14400 1 MSD}
+ {559695600 10800 0 MSK}
+ {575420400 14400 1 MSD}
+ {591145200 10800 0 MSK}
+ {606870000 14400 1 MSD}
+ {622594800 10800 0 MSK}
+ {638319600 14400 1 MSD}
+ {654649200 10800 0 MSK}
+ {670374000 7200 0 EEMMTT}
+ {670377600 10800 1 EEST}
+ {686102400 7200 0 EET}
+ {695779200 10800 0 MSD}
+ {701812800 14400 1 MSD}
+ {717534000 10800 0 MSK}
+ {733273200 14400 1 MSD}
+ {748998000 10800 0 MSK}
+ {764722800 14400 1 MSD}
+ {780447600 10800 0 MSK}
+ {796172400 14400 1 MSD}
+ {811897200 10800 0 MSK}
+ {828226800 14400 1 MSD}
+ {846370800 10800 0 MSK}
+ {859676400 14400 1 MSD}
+ {877820400 10800 0 MSK}
+ {891126000 14400 1 MSD}
+ {909270000 10800 0 MSK}
+ {922575600 14400 1 MSD}
+ {941324400 10800 0 MSK}
+ {954025200 14400 1 MSD}
+ {972774000 10800 0 MSK}
+ {985474800 14400 1 MSD}
+ {1004223600 10800 0 MSK}
+ {1017529200 14400 1 MSD}
+ {1035673200 10800 0 MSK}
+ {1048978800 14400 1 MSD}
+ {1067122800 10800 0 MSK}
+ {1080428400 14400 1 MSD}
+ {1099177200 10800 0 MSK}
+ {1111878000 14400 1 MSD}
+ {1130626800 10800 0 MSK}
+ {1143327600 14400 1 MSD}
+ {1162076400 10800 0 MSK}
+ {1174777200 14400 1 MSD}
+ {1193526000 10800 0 MSK}
+ {1206831600 14400 1 MSD}
+ {1224975600 10800 0 MSK}
+ {1238281200 14400 1 MSD}
+ {1256425200 10800 0 MSK}
+ {1269730800 14400 1 MSD}
+ {1288479600 10800 0 MSK}
+ {1301180400 14400 0 MSK}
+}
diff --git a/library/tzdata/Europe/Nicosia b/library/tzdata/Europe/Nicosia
new file mode 100644
index 0000000..2d58355
--- /dev/null
+++ b/library/tzdata/Europe/Nicosia
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Asia/Nicosia)]} {
+ LoadTimeZoneFile Asia/Nicosia
+}
+set TZData(:Europe/Nicosia) $TZData(:Asia/Nicosia)
diff --git a/library/tzdata/Europe/Oslo b/library/tzdata/Europe/Oslo
new file mode 100644
index 0000000..6787c1e
--- /dev/null
+++ b/library/tzdata/Europe/Oslo
@@ -0,0 +1,271 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Oslo) {
+ {-9223372036854775808 2580 0 LMT}
+ {-2366757780 3600 0 CET}
+ {-1691884800 7200 1 CEST}
+ {-1680573600 3600 0 CET}
+ {-927511200 7200 0 CEST}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-796777200 3600 0 CET}
+ {-781052400 7200 0 CEST}
+ {-765327600 3600 0 CET}
+ {-340844400 7200 1 CEST}
+ {-324514800 3600 0 CET}
+ {-308790000 7200 1 CEST}
+ {-293065200 3600 0 CET}
+ {-277340400 7200 1 CEST}
+ {-261615600 3600 0 CET}
+ {-245890800 7200 1 CEST}
+ {-230166000 3600 0 CET}
+ {-214441200 7200 1 CEST}
+ {-198716400 3600 0 CET}
+ {-182991600 7200 1 CEST}
+ {-166662000 3600 0 CET}
+ {-147913200 7200 1 CEST}
+ {-135212400 3600 0 CET}
+ {315529200 3600 0 CET}
+ {323830800 7200 1 CEST}
+ {338950800 3600 0 CET}
+ {354675600 7200 1 CEST}
+ {370400400 3600 0 CET}
+ {386125200 7200 1 CEST}
+ {401850000 3600 0 CET}
+ {417574800 7200 1 CEST}
+ {433299600 3600 0 CET}
+ {449024400 7200 1 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Paris b/library/tzdata/Europe/Paris
new file mode 100644
index 0000000..4b22a09
--- /dev/null
+++ b/library/tzdata/Europe/Paris
@@ -0,0 +1,314 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Paris) {
+ {-9223372036854775808 561 0 LMT}
+ {-2486678901 561 0 PMT}
+ {-1855958901 0 0 WET}
+ {-1689814800 3600 1 WEST}
+ {-1680397200 0 0 WET}
+ {-1665363600 3600 1 WEST}
+ {-1648342800 0 0 WET}
+ {-1635123600 3600 1 WEST}
+ {-1616893200 0 0 WET}
+ {-1604278800 3600 1 WEST}
+ {-1585443600 0 0 WET}
+ {-1574038800 3600 1 WEST}
+ {-1552266000 0 0 WET}
+ {-1539997200 3600 1 WEST}
+ {-1520557200 0 0 WET}
+ {-1507510800 3600 1 WEST}
+ {-1490576400 0 0 WET}
+ {-1470618000 3600 1 WEST}
+ {-1459126800 0 0 WET}
+ {-1444006800 3600 1 WEST}
+ {-1427677200 0 0 WET}
+ {-1411952400 3600 1 WEST}
+ {-1396227600 0 0 WET}
+ {-1379293200 3600 1 WEST}
+ {-1364778000 0 0 WET}
+ {-1348448400 3600 1 WEST}
+ {-1333328400 0 0 WET}
+ {-1316394000 3600 1 WEST}
+ {-1301274000 0 0 WET}
+ {-1284339600 3600 1 WEST}
+ {-1269824400 0 0 WET}
+ {-1253494800 3600 1 WEST}
+ {-1238374800 0 0 WET}
+ {-1221440400 3600 1 WEST}
+ {-1206925200 0 0 WET}
+ {-1191200400 3600 1 WEST}
+ {-1175475600 0 0 WET}
+ {-1160355600 3600 1 WEST}
+ {-1143421200 0 0 WET}
+ {-1127696400 3600 1 WEST}
+ {-1111971600 0 0 WET}
+ {-1096851600 3600 1 WEST}
+ {-1080522000 0 0 WET}
+ {-1063587600 3600 1 WEST}
+ {-1049072400 0 0 WET}
+ {-1033347600 3600 1 WEST}
+ {-1017622800 0 0 WET}
+ {-1002502800 3600 1 WEST}
+ {-986173200 0 0 WET}
+ {-969238800 3600 1 WEST}
+ {-950490000 0 0 WET}
+ {-942012000 3600 1 WEST}
+ {-932436000 7200 0 CEST}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-800067600 7200 0 WEMT}
+ {-796266000 3600 1 WEST}
+ {-781052400 7200 1 WEMT}
+ {-766616400 3600 0 CET}
+ {196819200 7200 1 CEST}
+ {212540400 3600 0 CET}
+ {220921200 3600 0 CET}
+ {228877200 7200 1 CEST}
+ {243997200 3600 0 CET}
+ {260326800 7200 1 CEST}
+ {276051600 3600 0 CET}
+ {291776400 7200 1 CEST}
+ {307501200 3600 0 CET}
+ {323830800 7200 1 CEST}
+ {338950800 3600 0 CET}
+ {354675600 7200 1 CEST}
+ {370400400 3600 0 CET}
+ {386125200 7200 1 CEST}
+ {401850000 3600 0 CET}
+ {417574800 7200 1 CEST}
+ {433299600 3600 0 CET}
+ {449024400 7200 1 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Podgorica b/library/tzdata/Europe/Podgorica
new file mode 100755
index 0000000..f4f9066
--- /dev/null
+++ b/library/tzdata/Europe/Podgorica
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/Belgrade)]} {
+ LoadTimeZoneFile Europe/Belgrade
+}
+set TZData(:Europe/Podgorica) $TZData(:Europe/Belgrade)
diff --git a/library/tzdata/Europe/Prague b/library/tzdata/Europe/Prague
new file mode 100644
index 0000000..222b1ae
--- /dev/null
+++ b/library/tzdata/Europe/Prague
@@ -0,0 +1,272 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Prague) {
+ {-9223372036854775808 3464 0 LMT}
+ {-3786829064 3464 0 PMT}
+ {-2469401864 3600 0 CET}
+ {-1693706400 7200 1 CEST}
+ {-1680483600 3600 0 CET}
+ {-1663455600 7200 1 CEST}
+ {-1650150000 3600 0 CET}
+ {-1632006000 7200 1 CEST}
+ {-1618700400 3600 0 CET}
+ {-938905200 7200 1 CEST}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-798073200 3600 0 CET}
+ {-780534000 7200 1 CEST}
+ {-761180400 3600 0 CET}
+ {-746578800 7200 1 CEST}
+ {-733359600 3600 0 CET}
+ {-716425200 7200 1 CEST}
+ {-701910000 3600 0 CET}
+ {-684975600 7200 1 CEST}
+ {-670460400 3600 0 CET}
+ {-654217200 7200 1 CEST}
+ {-639010800 3600 0 CET}
+ {283993200 3600 0 CET}
+ {291776400 7200 1 CEST}
+ {307501200 3600 0 CET}
+ {323830800 7200 1 CEST}
+ {338950800 3600 0 CET}
+ {354675600 7200 1 CEST}
+ {370400400 3600 0 CET}
+ {386125200 7200 1 CEST}
+ {401850000 3600 0 CET}
+ {417574800 7200 1 CEST}
+ {433299600 3600 0 CET}
+ {449024400 7200 1 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Riga b/library/tzdata/Europe/Riga
new file mode 100644
index 0000000..9fad0f8
--- /dev/null
+++ b/library/tzdata/Europe/Riga
@@ -0,0 +1,258 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Riga) {
+ {-9223372036854775808 5784 0 LMT}
+ {-2840146584 5784 0 RMT}
+ {-1632008184 9384 1 LST}
+ {-1618702584 5784 0 RMT}
+ {-1601681784 9384 1 LST}
+ {-1597275384 5784 0 RMT}
+ {-1377308184 7200 0 EET}
+ {-928029600 10800 0 MSK}
+ {-899521200 3600 0 CET}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-796777200 3600 0 CET}
+ {-795834000 10800 0 MSD}
+ {354920400 14400 1 MSD}
+ {370728000 10800 0 MSK}
+ {386456400 14400 1 MSD}
+ {402264000 10800 0 MSK}
+ {417992400 14400 1 MSD}
+ {433800000 10800 0 MSK}
+ {449614800 14400 1 MSD}
+ {465346800 10800 0 MSK}
+ {481071600 14400 1 MSD}
+ {496796400 10800 0 MSK}
+ {512521200 14400 1 MSD}
+ {528246000 10800 0 MSK}
+ {543970800 14400 1 MSD}
+ {559695600 10800 0 MSK}
+ {575420400 14400 1 MSD}
+ {591145200 10800 0 MSK}
+ {606870000 10800 1 EEST}
+ {622598400 7200 0 EET}
+ {638323200 10800 1 EEST}
+ {654652800 7200 0 EET}
+ {670377600 10800 1 EEST}
+ {686102400 7200 0 EET}
+ {701827200 10800 1 EEST}
+ {717552000 7200 0 EET}
+ {733276800 10800 1 EEST}
+ {749001600 7200 0 EET}
+ {764726400 10800 1 EEST}
+ {780451200 7200 0 EET}
+ {796176000 10800 1 EEST}
+ {811900800 7200 0 EET}
+ {828230400 10800 1 EEST}
+ {843955200 7200 0 EET}
+ {853797600 7200 0 EET}
+ {859683600 10800 1 EEST}
+ {877827600 7200 0 EET}
+ {891133200 10800 1 EEST}
+ {909277200 7200 0 EET}
+ {922582800 10800 1 EEST}
+ {941331600 7200 0 EET}
+ {951775200 7200 0 EET}
+ {978386400 7200 0 EET}
+ {985482000 10800 1 EEST}
+ {1004230800 7200 0 EET}
+ {1017536400 10800 1 EEST}
+ {1035680400 7200 0 EET}
+ {1048986000 10800 1 EEST}
+ {1067130000 7200 0 EET}
+ {1080435600 10800 1 EEST}
+ {1099184400 7200 0 EET}
+ {1111885200 10800 1 EEST}
+ {1130634000 7200 0 EET}
+ {1143334800 10800 1 EEST}
+ {1162083600 7200 0 EET}
+ {1174784400 10800 1 EEST}
+ {1193533200 7200 0 EET}
+ {1206838800 10800 1 EEST}
+ {1224982800 7200 0 EET}
+ {1238288400 10800 1 EEST}
+ {1256432400 7200 0 EET}
+ {1269738000 10800 1 EEST}
+ {1288486800 7200 0 EET}
+ {1301187600 10800 1 EEST}
+ {1319936400 7200 0 EET}
+ {1332637200 10800 1 EEST}
+ {1351386000 7200 0 EET}
+ {1364691600 10800 1 EEST}
+ {1382835600 7200 0 EET}
+ {1396141200 10800 1 EEST}
+ {1414285200 7200 0 EET}
+ {1427590800 10800 1 EEST}
+ {1445734800 7200 0 EET}
+ {1459040400 10800 1 EEST}
+ {1477789200 7200 0 EET}
+ {1490490000 10800 1 EEST}
+ {1509238800 7200 0 EET}
+ {1521939600 10800 1 EEST}
+ {1540688400 7200 0 EET}
+ {1553994000 10800 1 EEST}
+ {1572138000 7200 0 EET}
+ {1585443600 10800 1 EEST}
+ {1603587600 7200 0 EET}
+ {1616893200 10800 1 EEST}
+ {1635642000 7200 0 EET}
+ {1648342800 10800 1 EEST}
+ {1667091600 7200 0 EET}
+ {1679792400 10800 1 EEST}
+ {1698541200 7200 0 EET}
+ {1711846800 10800 1 EEST}
+ {1729990800 7200 0 EET}
+ {1743296400 10800 1 EEST}
+ {1761440400 7200 0 EET}
+ {1774746000 10800 1 EEST}
+ {1792890000 7200 0 EET}
+ {1806195600 10800 1 EEST}
+ {1824944400 7200 0 EET}
+ {1837645200 10800 1 EEST}
+ {1856394000 7200 0 EET}
+ {1869094800 10800 1 EEST}
+ {1887843600 7200 0 EET}
+ {1901149200 10800 1 EEST}
+ {1919293200 7200 0 EET}
+ {1932598800 10800 1 EEST}
+ {1950742800 7200 0 EET}
+ {1964048400 10800 1 EEST}
+ {1982797200 7200 0 EET}
+ {1995498000 10800 1 EEST}
+ {2014246800 7200 0 EET}
+ {2026947600 10800 1 EEST}
+ {2045696400 7200 0 EET}
+ {2058397200 10800 1 EEST}
+ {2077146000 7200 0 EET}
+ {2090451600 10800 1 EEST}
+ {2108595600 7200 0 EET}
+ {2121901200 10800 1 EEST}
+ {2140045200 7200 0 EET}
+ {2153350800 10800 1 EEST}
+ {2172099600 7200 0 EET}
+ {2184800400 10800 1 EEST}
+ {2203549200 7200 0 EET}
+ {2216250000 10800 1 EEST}
+ {2234998800 7200 0 EET}
+ {2248304400 10800 1 EEST}
+ {2266448400 7200 0 EET}
+ {2279754000 10800 1 EEST}
+ {2297898000 7200 0 EET}
+ {2311203600 10800 1 EEST}
+ {2329347600 7200 0 EET}
+ {2342653200 10800 1 EEST}
+ {2361402000 7200 0 EET}
+ {2374102800 10800 1 EEST}
+ {2392851600 7200 0 EET}
+ {2405552400 10800 1 EEST}
+ {2424301200 7200 0 EET}
+ {2437606800 10800 1 EEST}
+ {2455750800 7200 0 EET}
+ {2469056400 10800 1 EEST}
+ {2487200400 7200 0 EET}
+ {2500506000 10800 1 EEST}
+ {2519254800 7200 0 EET}
+ {2531955600 10800 1 EEST}
+ {2550704400 7200 0 EET}
+ {2563405200 10800 1 EEST}
+ {2582154000 7200 0 EET}
+ {2595459600 10800 1 EEST}
+ {2613603600 7200 0 EET}
+ {2626909200 10800 1 EEST}
+ {2645053200 7200 0 EET}
+ {2658358800 10800 1 EEST}
+ {2676502800 7200 0 EET}
+ {2689808400 10800 1 EEST}
+ {2708557200 7200 0 EET}
+ {2721258000 10800 1 EEST}
+ {2740006800 7200 0 EET}
+ {2752707600 10800 1 EEST}
+ {2771456400 7200 0 EET}
+ {2784762000 10800 1 EEST}
+ {2802906000 7200 0 EET}
+ {2816211600 10800 1 EEST}
+ {2834355600 7200 0 EET}
+ {2847661200 10800 1 EEST}
+ {2866410000 7200 0 EET}
+ {2879110800 10800 1 EEST}
+ {2897859600 7200 0 EET}
+ {2910560400 10800 1 EEST}
+ {2929309200 7200 0 EET}
+ {2942010000 10800 1 EEST}
+ {2960758800 7200 0 EET}
+ {2974064400 10800 1 EEST}
+ {2992208400 7200 0 EET}
+ {3005514000 10800 1 EEST}
+ {3023658000 7200 0 EET}
+ {3036963600 10800 1 EEST}
+ {3055712400 7200 0 EET}
+ {3068413200 10800 1 EEST}
+ {3087162000 7200 0 EET}
+ {3099862800 10800 1 EEST}
+ {3118611600 7200 0 EET}
+ {3131917200 10800 1 EEST}
+ {3150061200 7200 0 EET}
+ {3163366800 10800 1 EEST}
+ {3181510800 7200 0 EET}
+ {3194816400 10800 1 EEST}
+ {3212960400 7200 0 EET}
+ {3226266000 10800 1 EEST}
+ {3245014800 7200 0 EET}
+ {3257715600 10800 1 EEST}
+ {3276464400 7200 0 EET}
+ {3289165200 10800 1 EEST}
+ {3307914000 7200 0 EET}
+ {3321219600 10800 1 EEST}
+ {3339363600 7200 0 EET}
+ {3352669200 10800 1 EEST}
+ {3370813200 7200 0 EET}
+ {3384118800 10800 1 EEST}
+ {3402867600 7200 0 EET}
+ {3415568400 10800 1 EEST}
+ {3434317200 7200 0 EET}
+ {3447018000 10800 1 EEST}
+ {3465766800 7200 0 EET}
+ {3479072400 10800 1 EEST}
+ {3497216400 7200 0 EET}
+ {3510522000 10800 1 EEST}
+ {3528666000 7200 0 EET}
+ {3541971600 10800 1 EEST}
+ {3560115600 7200 0 EET}
+ {3573421200 10800 1 EEST}
+ {3592170000 7200 0 EET}
+ {3604870800 10800 1 EEST}
+ {3623619600 7200 0 EET}
+ {3636320400 10800 1 EEST}
+ {3655069200 7200 0 EET}
+ {3668374800 10800 1 EEST}
+ {3686518800 7200 0 EET}
+ {3699824400 10800 1 EEST}
+ {3717968400 7200 0 EET}
+ {3731274000 10800 1 EEST}
+ {3750022800 7200 0 EET}
+ {3762723600 10800 1 EEST}
+ {3781472400 7200 0 EET}
+ {3794173200 10800 1 EEST}
+ {3812922000 7200 0 EET}
+ {3825622800 10800 1 EEST}
+ {3844371600 7200 0 EET}
+ {3857677200 10800 1 EEST}
+ {3875821200 7200 0 EET}
+ {3889126800 10800 1 EEST}
+ {3907270800 7200 0 EET}
+ {3920576400 10800 1 EEST}
+ {3939325200 7200 0 EET}
+ {3952026000 10800 1 EEST}
+ {3970774800 7200 0 EET}
+ {3983475600 10800 1 EEST}
+ {4002224400 7200 0 EET}
+ {4015530000 10800 1 EEST}
+ {4033674000 7200 0 EET}
+ {4046979600 10800 1 EEST}
+ {4065123600 7200 0 EET}
+ {4078429200 10800 1 EEST}
+ {4096573200 7200 0 EET}
+}
diff --git a/library/tzdata/Europe/Rome b/library/tzdata/Europe/Rome
new file mode 100644
index 0000000..64948b8
--- /dev/null
+++ b/library/tzdata/Europe/Rome
@@ -0,0 +1,301 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Rome) {
+ {-9223372036854775808 2996 0 LMT}
+ {-3259097396 2996 0 RMT}
+ {-2403564596 3600 0 CET}
+ {-1690851600 7200 1 CEST}
+ {-1680483600 3600 0 CET}
+ {-1664758800 7200 1 CEST}
+ {-1649034000 3600 0 CET}
+ {-1635123600 7200 1 CEST}
+ {-1616979600 3600 0 CET}
+ {-1604278800 7200 1 CEST}
+ {-1585530000 3600 0 CET}
+ {-1571014800 7200 1 CEST}
+ {-1555290000 3600 0 CET}
+ {-932432400 7200 1 CEST}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-804819600 3600 0 CET}
+ {-798080400 3600 0 CET}
+ {-781052400 7200 1 CEST}
+ {-766717200 3600 0 CET}
+ {-750898800 7200 1 CEST}
+ {-733359600 3600 0 CET}
+ {-719456400 7200 1 CEST}
+ {-701917200 3600 0 CET}
+ {-689209200 7200 1 CEST}
+ {-670460400 3600 0 CET}
+ {-114051600 7200 1 CEST}
+ {-103168800 3600 0 CET}
+ {-81997200 7200 1 CEST}
+ {-71719200 3600 0 CET}
+ {-50547600 7200 1 CEST}
+ {-40269600 3600 0 CET}
+ {-18493200 7200 1 CEST}
+ {-8215200 3600 0 CET}
+ {12956400 7200 1 CEST}
+ {23234400 3600 0 CET}
+ {43801200 7200 1 CEST}
+ {54687600 3600 0 CET}
+ {75855600 7200 1 CEST}
+ {86738400 3600 0 CET}
+ {107910000 7200 1 CEST}
+ {118188000 3600 0 CET}
+ {138754800 7200 1 CEST}
+ {149637600 3600 0 CET}
+ {170809200 7200 1 CEST}
+ {181090800 3600 0 CET}
+ {202258800 7200 1 CEST}
+ {212540400 3600 0 CET}
+ {233103600 7200 1 CEST}
+ {243990000 3600 0 CET}
+ {265158000 7200 1 CEST}
+ {276044400 3600 0 CET}
+ {296607600 7200 1 CEST}
+ {307494000 3600 0 CET}
+ {315529200 3600 0 CET}
+ {323830800 7200 1 CEST}
+ {338950800 3600 0 CET}
+ {354675600 7200 1 CEST}
+ {370400400 3600 0 CET}
+ {386125200 7200 1 CEST}
+ {401850000 3600 0 CET}
+ {417574800 7200 1 CEST}
+ {433299600 3600 0 CET}
+ {449024400 7200 1 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Samara b/library/tzdata/Europe/Samara
new file mode 100644
index 0000000..f2ac911
--- /dev/null
+++ b/library/tzdata/Europe/Samara
@@ -0,0 +1,73 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Samara) {
+ {-9223372036854775808 12036 0 LMT}
+ {-1593825636 10800 0 SAMT}
+ {-1247540400 14400 0 SAMT}
+ {-1102305600 14400 0 KUYMMTT}
+ {354916800 18000 1 KUYST}
+ {370724400 14400 0 KUYT}
+ {386452800 18000 1 KUYST}
+ {402260400 14400 0 KUYT}
+ {417988800 18000 1 KUYST}
+ {433796400 14400 0 KUYT}
+ {449611200 18000 1 KUYST}
+ {465343200 14400 0 KUYT}
+ {481068000 18000 1 KUYST}
+ {496792800 14400 0 KUYT}
+ {512517600 18000 1 KUYST}
+ {528242400 14400 0 KUYT}
+ {543967200 18000 1 KUYST}
+ {559692000 14400 0 KUYT}
+ {575416800 18000 1 KUYST}
+ {591141600 14400 0 KUYT}
+ {606866400 10800 0 KUYMMTT}
+ {606870000 14400 1 KUYST}
+ {622594800 10800 0 KUYT}
+ {638319600 14400 1 KUYST}
+ {654649200 10800 0 KUYT}
+ {670374000 7200 0 KUYMMTT}
+ {670377600 10800 1 KUYST}
+ {686102400 10800 0 KUYT}
+ {687916800 14400 0 SAMT}
+ {701809200 18000 1 SAMST}
+ {717530400 14400 0 SAMT}
+ {733269600 18000 1 SAMST}
+ {748994400 14400 0 SAMT}
+ {764719200 18000 1 SAMST}
+ {780444000 14400 0 SAMT}
+ {796168800 18000 1 SAMST}
+ {811893600 14400 0 SAMT}
+ {828223200 18000 1 SAMST}
+ {846367200 14400 0 SAMT}
+ {859672800 18000 1 SAMST}
+ {877816800 14400 0 SAMT}
+ {891122400 18000 1 SAMST}
+ {909266400 14400 0 SAMT}
+ {922572000 18000 1 SAMST}
+ {941320800 14400 0 SAMT}
+ {954021600 18000 1 SAMST}
+ {972770400 14400 0 SAMT}
+ {985471200 18000 1 SAMST}
+ {1004220000 14400 0 SAMT}
+ {1017525600 18000 1 SAMST}
+ {1035669600 14400 0 SAMT}
+ {1048975200 18000 1 SAMST}
+ {1067119200 14400 0 SAMT}
+ {1080424800 18000 1 SAMST}
+ {1099173600 14400 0 SAMT}
+ {1111874400 18000 1 SAMST}
+ {1130623200 14400 0 SAMT}
+ {1143324000 18000 1 SAMST}
+ {1162072800 14400 0 SAMT}
+ {1174773600 18000 1 SAMST}
+ {1193522400 14400 0 SAMT}
+ {1206828000 18000 1 SAMST}
+ {1224972000 14400 0 SAMT}
+ {1238277600 18000 1 SAMST}
+ {1256421600 14400 0 SAMT}
+ {1269727200 10800 0 SAMMMTT}
+ {1269730800 14400 1 SAMST}
+ {1288479600 10800 0 SAMT}
+ {1301180400 14400 0 SAMT}
+}
diff --git a/library/tzdata/Europe/San_Marino b/library/tzdata/Europe/San_Marino
new file mode 100644
index 0000000..927ad29
--- /dev/null
+++ b/library/tzdata/Europe/San_Marino
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/Rome)]} {
+ LoadTimeZoneFile Europe/Rome
+}
+set TZData(:Europe/San_Marino) $TZData(:Europe/Rome)
diff --git a/library/tzdata/Europe/Sarajevo b/library/tzdata/Europe/Sarajevo
new file mode 100644
index 0000000..1b14286
--- /dev/null
+++ b/library/tzdata/Europe/Sarajevo
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/Belgrade)]} {
+ LoadTimeZoneFile Europe/Belgrade
+}
+set TZData(:Europe/Sarajevo) $TZData(:Europe/Belgrade)
diff --git a/library/tzdata/Europe/Simferopol b/library/tzdata/Europe/Simferopol
new file mode 100644
index 0000000..9836560
--- /dev/null
+++ b/library/tzdata/Europe/Simferopol
@@ -0,0 +1,253 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Simferopol) {
+ {-9223372036854775808 8184 0 LMT}
+ {-2840148984 8160 0 SMT}
+ {-1441160160 7200 0 EET}
+ {-1247536800 10800 0 MSK}
+ {-888894000 3600 0 CET}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-811645200 10800 0 MSD}
+ {354920400 14400 1 MSD}
+ {370728000 10800 0 MSK}
+ {386456400 14400 1 MSD}
+ {402264000 10800 0 MSK}
+ {417992400 14400 1 MSD}
+ {433800000 10800 0 MSK}
+ {449614800 14400 1 MSD}
+ {465346800 10800 0 MSK}
+ {481071600 14400 1 MSD}
+ {496796400 10800 0 MSK}
+ {512521200 14400 1 MSD}
+ {528246000 10800 0 MSK}
+ {543970800 14400 1 MSD}
+ {559695600 10800 0 MSK}
+ {575420400 14400 1 MSD}
+ {591145200 10800 0 MSK}
+ {606870000 14400 1 MSD}
+ {622594800 10800 0 MSK}
+ {631141200 10800 0 MSK}
+ {646786800 7200 0 EET}
+ {694216800 7200 0 EET}
+ {701820000 10800 1 EEST}
+ {717541200 7200 0 EET}
+ {733269600 10800 1 EEST}
+ {748990800 7200 0 EET}
+ {764719200 10800 1 EEST}
+ {767743200 14400 0 MSD}
+ {780436800 10800 0 MSK}
+ {796165200 14400 1 MSD}
+ {811886400 10800 0 MSK}
+ {828219600 14400 1 MSD}
+ {828230400 14400 1 MSD}
+ {852066000 10800 0 MSK}
+ {859683600 10800 0 EEST}
+ {877827600 7200 0 EET}
+ {891133200 10800 1 EEST}
+ {909277200 7200 0 EET}
+ {922582800 10800 1 EEST}
+ {941331600 7200 0 EET}
+ {954032400 10800 1 EEST}
+ {972781200 7200 0 EET}
+ {985482000 10800 1 EEST}
+ {1004230800 7200 0 EET}
+ {1017536400 10800 1 EEST}
+ {1035680400 7200 0 EET}
+ {1048986000 10800 1 EEST}
+ {1067130000 7200 0 EET}
+ {1080435600 10800 1 EEST}
+ {1099184400 7200 0 EET}
+ {1111885200 10800 1 EEST}
+ {1130634000 7200 0 EET}
+ {1143334800 10800 1 EEST}
+ {1162083600 7200 0 EET}
+ {1174784400 10800 1 EEST}
+ {1193533200 7200 0 EET}
+ {1206838800 10800 1 EEST}
+ {1224982800 7200 0 EET}
+ {1238288400 10800 1 EEST}
+ {1256432400 7200 0 EET}
+ {1269738000 10800 1 EEST}
+ {1288486800 7200 0 EET}
+ {1301187600 10800 1 EEST}
+ {1319936400 7200 0 EET}
+ {1332637200 10800 1 EEST}
+ {1351386000 7200 0 EET}
+ {1364691600 10800 1 EEST}
+ {1382835600 7200 0 EET}
+ {1396141200 10800 1 EEST}
+ {1414285200 7200 0 EET}
+ {1427590800 10800 1 EEST}
+ {1445734800 7200 0 EET}
+ {1459040400 10800 1 EEST}
+ {1477789200 7200 0 EET}
+ {1490490000 10800 1 EEST}
+ {1509238800 7200 0 EET}
+ {1521939600 10800 1 EEST}
+ {1540688400 7200 0 EET}
+ {1553994000 10800 1 EEST}
+ {1572138000 7200 0 EET}
+ {1585443600 10800 1 EEST}
+ {1603587600 7200 0 EET}
+ {1616893200 10800 1 EEST}
+ {1635642000 7200 0 EET}
+ {1648342800 10800 1 EEST}
+ {1667091600 7200 0 EET}
+ {1679792400 10800 1 EEST}
+ {1698541200 7200 0 EET}
+ {1711846800 10800 1 EEST}
+ {1729990800 7200 0 EET}
+ {1743296400 10800 1 EEST}
+ {1761440400 7200 0 EET}
+ {1774746000 10800 1 EEST}
+ {1792890000 7200 0 EET}
+ {1806195600 10800 1 EEST}
+ {1824944400 7200 0 EET}
+ {1837645200 10800 1 EEST}
+ {1856394000 7200 0 EET}
+ {1869094800 10800 1 EEST}
+ {1887843600 7200 0 EET}
+ {1901149200 10800 1 EEST}
+ {1919293200 7200 0 EET}
+ {1932598800 10800 1 EEST}
+ {1950742800 7200 0 EET}
+ {1964048400 10800 1 EEST}
+ {1982797200 7200 0 EET}
+ {1995498000 10800 1 EEST}
+ {2014246800 7200 0 EET}
+ {2026947600 10800 1 EEST}
+ {2045696400 7200 0 EET}
+ {2058397200 10800 1 EEST}
+ {2077146000 7200 0 EET}
+ {2090451600 10800 1 EEST}
+ {2108595600 7200 0 EET}
+ {2121901200 10800 1 EEST}
+ {2140045200 7200 0 EET}
+ {2153350800 10800 1 EEST}
+ {2172099600 7200 0 EET}
+ {2184800400 10800 1 EEST}
+ {2203549200 7200 0 EET}
+ {2216250000 10800 1 EEST}
+ {2234998800 7200 0 EET}
+ {2248304400 10800 1 EEST}
+ {2266448400 7200 0 EET}
+ {2279754000 10800 1 EEST}
+ {2297898000 7200 0 EET}
+ {2311203600 10800 1 EEST}
+ {2329347600 7200 0 EET}
+ {2342653200 10800 1 EEST}
+ {2361402000 7200 0 EET}
+ {2374102800 10800 1 EEST}
+ {2392851600 7200 0 EET}
+ {2405552400 10800 1 EEST}
+ {2424301200 7200 0 EET}
+ {2437606800 10800 1 EEST}
+ {2455750800 7200 0 EET}
+ {2469056400 10800 1 EEST}
+ {2487200400 7200 0 EET}
+ {2500506000 10800 1 EEST}
+ {2519254800 7200 0 EET}
+ {2531955600 10800 1 EEST}
+ {2550704400 7200 0 EET}
+ {2563405200 10800 1 EEST}
+ {2582154000 7200 0 EET}
+ {2595459600 10800 1 EEST}
+ {2613603600 7200 0 EET}
+ {2626909200 10800 1 EEST}
+ {2645053200 7200 0 EET}
+ {2658358800 10800 1 EEST}
+ {2676502800 7200 0 EET}
+ {2689808400 10800 1 EEST}
+ {2708557200 7200 0 EET}
+ {2721258000 10800 1 EEST}
+ {2740006800 7200 0 EET}
+ {2752707600 10800 1 EEST}
+ {2771456400 7200 0 EET}
+ {2784762000 10800 1 EEST}
+ {2802906000 7200 0 EET}
+ {2816211600 10800 1 EEST}
+ {2834355600 7200 0 EET}
+ {2847661200 10800 1 EEST}
+ {2866410000 7200 0 EET}
+ {2879110800 10800 1 EEST}
+ {2897859600 7200 0 EET}
+ {2910560400 10800 1 EEST}
+ {2929309200 7200 0 EET}
+ {2942010000 10800 1 EEST}
+ {2960758800 7200 0 EET}
+ {2974064400 10800 1 EEST}
+ {2992208400 7200 0 EET}
+ {3005514000 10800 1 EEST}
+ {3023658000 7200 0 EET}
+ {3036963600 10800 1 EEST}
+ {3055712400 7200 0 EET}
+ {3068413200 10800 1 EEST}
+ {3087162000 7200 0 EET}
+ {3099862800 10800 1 EEST}
+ {3118611600 7200 0 EET}
+ {3131917200 10800 1 EEST}
+ {3150061200 7200 0 EET}
+ {3163366800 10800 1 EEST}
+ {3181510800 7200 0 EET}
+ {3194816400 10800 1 EEST}
+ {3212960400 7200 0 EET}
+ {3226266000 10800 1 EEST}
+ {3245014800 7200 0 EET}
+ {3257715600 10800 1 EEST}
+ {3276464400 7200 0 EET}
+ {3289165200 10800 1 EEST}
+ {3307914000 7200 0 EET}
+ {3321219600 10800 1 EEST}
+ {3339363600 7200 0 EET}
+ {3352669200 10800 1 EEST}
+ {3370813200 7200 0 EET}
+ {3384118800 10800 1 EEST}
+ {3402867600 7200 0 EET}
+ {3415568400 10800 1 EEST}
+ {3434317200 7200 0 EET}
+ {3447018000 10800 1 EEST}
+ {3465766800 7200 0 EET}
+ {3479072400 10800 1 EEST}
+ {3497216400 7200 0 EET}
+ {3510522000 10800 1 EEST}
+ {3528666000 7200 0 EET}
+ {3541971600 10800 1 EEST}
+ {3560115600 7200 0 EET}
+ {3573421200 10800 1 EEST}
+ {3592170000 7200 0 EET}
+ {3604870800 10800 1 EEST}
+ {3623619600 7200 0 EET}
+ {3636320400 10800 1 EEST}
+ {3655069200 7200 0 EET}
+ {3668374800 10800 1 EEST}
+ {3686518800 7200 0 EET}
+ {3699824400 10800 1 EEST}
+ {3717968400 7200 0 EET}
+ {3731274000 10800 1 EEST}
+ {3750022800 7200 0 EET}
+ {3762723600 10800 1 EEST}
+ {3781472400 7200 0 EET}
+ {3794173200 10800 1 EEST}
+ {3812922000 7200 0 EET}
+ {3825622800 10800 1 EEST}
+ {3844371600 7200 0 EET}
+ {3857677200 10800 1 EEST}
+ {3875821200 7200 0 EET}
+ {3889126800 10800 1 EEST}
+ {3907270800 7200 0 EET}
+ {3920576400 10800 1 EEST}
+ {3939325200 7200 0 EET}
+ {3952026000 10800 1 EEST}
+ {3970774800 7200 0 EET}
+ {3983475600 10800 1 EEST}
+ {4002224400 7200 0 EET}
+ {4015530000 10800 1 EEST}
+ {4033674000 7200 0 EET}
+ {4046979600 10800 1 EEST}
+ {4065123600 7200 0 EET}
+ {4078429200 10800 1 EEST}
+ {4096573200 7200 0 EET}
+}
diff --git a/library/tzdata/Europe/Skopje b/library/tzdata/Europe/Skopje
new file mode 100644
index 0000000..07eedbe
--- /dev/null
+++ b/library/tzdata/Europe/Skopje
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/Belgrade)]} {
+ LoadTimeZoneFile Europe/Belgrade
+}
+set TZData(:Europe/Skopje) $TZData(:Europe/Belgrade)
diff --git a/library/tzdata/Europe/Sofia b/library/tzdata/Europe/Sofia
new file mode 100644
index 0000000..8fd55f6
--- /dev/null
+++ b/library/tzdata/Europe/Sofia
@@ -0,0 +1,259 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Sofia) {
+ {-9223372036854775808 5596 0 LMT}
+ {-2840146396 7016 0 IMT}
+ {-2369527016 7200 0 EET}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-796777200 3600 0 CET}
+ {-788922000 3600 0 CET}
+ {-781048800 7200 0 EET}
+ {291762000 10800 0 EEST}
+ {307576800 7200 0 EET}
+ {323816400 10800 1 EEST}
+ {339026400 7200 0 EET}
+ {355266000 10800 1 EEST}
+ {370393200 7200 0 EET}
+ {386715600 10800 1 EEST}
+ {401842800 10800 0 EEST}
+ {401846400 7200 0 EET}
+ {417571200 10800 1 EEST}
+ {433296000 7200 0 EET}
+ {449020800 10800 1 EEST}
+ {465350400 7200 0 EET}
+ {481075200 10800 1 EEST}
+ {496800000 7200 0 EET}
+ {512524800 10800 1 EEST}
+ {528249600 7200 0 EET}
+ {543974400 10800 1 EEST}
+ {559699200 7200 0 EET}
+ {575424000 10800 1 EEST}
+ {591148800 7200 0 EET}
+ {606873600 10800 1 EEST}
+ {622598400 7200 0 EET}
+ {638323200 10800 1 EEST}
+ {654652800 7200 0 EET}
+ {662680800 7200 0 EET}
+ {670370400 10800 1 EEST}
+ {686091600 7200 0 EET}
+ {701820000 10800 1 EEST}
+ {717541200 7200 0 EET}
+ {733269600 10800 1 EEST}
+ {748990800 7200 0 EET}
+ {764719200 10800 1 EEST}
+ {780440400 7200 0 EET}
+ {796168800 10800 1 EEST}
+ {811890000 7200 0 EET}
+ {828223200 10800 1 EEST}
+ {846363600 7200 0 EET}
+ {852069600 7200 0 EET}
+ {859683600 10800 1 EEST}
+ {877827600 7200 0 EET}
+ {891133200 10800 1 EEST}
+ {909277200 7200 0 EET}
+ {922582800 10800 1 EEST}
+ {941331600 7200 0 EET}
+ {954032400 10800 1 EEST}
+ {972781200 7200 0 EET}
+ {985482000 10800 1 EEST}
+ {1004230800 7200 0 EET}
+ {1017536400 10800 1 EEST}
+ {1035680400 7200 0 EET}
+ {1048986000 10800 1 EEST}
+ {1067130000 7200 0 EET}
+ {1080435600 10800 1 EEST}
+ {1099184400 7200 0 EET}
+ {1111885200 10800 1 EEST}
+ {1130634000 7200 0 EET}
+ {1143334800 10800 1 EEST}
+ {1162083600 7200 0 EET}
+ {1174784400 10800 1 EEST}
+ {1193533200 7200 0 EET}
+ {1206838800 10800 1 EEST}
+ {1224982800 7200 0 EET}
+ {1238288400 10800 1 EEST}
+ {1256432400 7200 0 EET}
+ {1269738000 10800 1 EEST}
+ {1288486800 7200 0 EET}
+ {1301187600 10800 1 EEST}
+ {1319936400 7200 0 EET}
+ {1332637200 10800 1 EEST}
+ {1351386000 7200 0 EET}
+ {1364691600 10800 1 EEST}
+ {1382835600 7200 0 EET}
+ {1396141200 10800 1 EEST}
+ {1414285200 7200 0 EET}
+ {1427590800 10800 1 EEST}
+ {1445734800 7200 0 EET}
+ {1459040400 10800 1 EEST}
+ {1477789200 7200 0 EET}
+ {1490490000 10800 1 EEST}
+ {1509238800 7200 0 EET}
+ {1521939600 10800 1 EEST}
+ {1540688400 7200 0 EET}
+ {1553994000 10800 1 EEST}
+ {1572138000 7200 0 EET}
+ {1585443600 10800 1 EEST}
+ {1603587600 7200 0 EET}
+ {1616893200 10800 1 EEST}
+ {1635642000 7200 0 EET}
+ {1648342800 10800 1 EEST}
+ {1667091600 7200 0 EET}
+ {1679792400 10800 1 EEST}
+ {1698541200 7200 0 EET}
+ {1711846800 10800 1 EEST}
+ {1729990800 7200 0 EET}
+ {1743296400 10800 1 EEST}
+ {1761440400 7200 0 EET}
+ {1774746000 10800 1 EEST}
+ {1792890000 7200 0 EET}
+ {1806195600 10800 1 EEST}
+ {1824944400 7200 0 EET}
+ {1837645200 10800 1 EEST}
+ {1856394000 7200 0 EET}
+ {1869094800 10800 1 EEST}
+ {1887843600 7200 0 EET}
+ {1901149200 10800 1 EEST}
+ {1919293200 7200 0 EET}
+ {1932598800 10800 1 EEST}
+ {1950742800 7200 0 EET}
+ {1964048400 10800 1 EEST}
+ {1982797200 7200 0 EET}
+ {1995498000 10800 1 EEST}
+ {2014246800 7200 0 EET}
+ {2026947600 10800 1 EEST}
+ {2045696400 7200 0 EET}
+ {2058397200 10800 1 EEST}
+ {2077146000 7200 0 EET}
+ {2090451600 10800 1 EEST}
+ {2108595600 7200 0 EET}
+ {2121901200 10800 1 EEST}
+ {2140045200 7200 0 EET}
+ {2153350800 10800 1 EEST}
+ {2172099600 7200 0 EET}
+ {2184800400 10800 1 EEST}
+ {2203549200 7200 0 EET}
+ {2216250000 10800 1 EEST}
+ {2234998800 7200 0 EET}
+ {2248304400 10800 1 EEST}
+ {2266448400 7200 0 EET}
+ {2279754000 10800 1 EEST}
+ {2297898000 7200 0 EET}
+ {2311203600 10800 1 EEST}
+ {2329347600 7200 0 EET}
+ {2342653200 10800 1 EEST}
+ {2361402000 7200 0 EET}
+ {2374102800 10800 1 EEST}
+ {2392851600 7200 0 EET}
+ {2405552400 10800 1 EEST}
+ {2424301200 7200 0 EET}
+ {2437606800 10800 1 EEST}
+ {2455750800 7200 0 EET}
+ {2469056400 10800 1 EEST}
+ {2487200400 7200 0 EET}
+ {2500506000 10800 1 EEST}
+ {2519254800 7200 0 EET}
+ {2531955600 10800 1 EEST}
+ {2550704400 7200 0 EET}
+ {2563405200 10800 1 EEST}
+ {2582154000 7200 0 EET}
+ {2595459600 10800 1 EEST}
+ {2613603600 7200 0 EET}
+ {2626909200 10800 1 EEST}
+ {2645053200 7200 0 EET}
+ {2658358800 10800 1 EEST}
+ {2676502800 7200 0 EET}
+ {2689808400 10800 1 EEST}
+ {2708557200 7200 0 EET}
+ {2721258000 10800 1 EEST}
+ {2740006800 7200 0 EET}
+ {2752707600 10800 1 EEST}
+ {2771456400 7200 0 EET}
+ {2784762000 10800 1 EEST}
+ {2802906000 7200 0 EET}
+ {2816211600 10800 1 EEST}
+ {2834355600 7200 0 EET}
+ {2847661200 10800 1 EEST}
+ {2866410000 7200 0 EET}
+ {2879110800 10800 1 EEST}
+ {2897859600 7200 0 EET}
+ {2910560400 10800 1 EEST}
+ {2929309200 7200 0 EET}
+ {2942010000 10800 1 EEST}
+ {2960758800 7200 0 EET}
+ {2974064400 10800 1 EEST}
+ {2992208400 7200 0 EET}
+ {3005514000 10800 1 EEST}
+ {3023658000 7200 0 EET}
+ {3036963600 10800 1 EEST}
+ {3055712400 7200 0 EET}
+ {3068413200 10800 1 EEST}
+ {3087162000 7200 0 EET}
+ {3099862800 10800 1 EEST}
+ {3118611600 7200 0 EET}
+ {3131917200 10800 1 EEST}
+ {3150061200 7200 0 EET}
+ {3163366800 10800 1 EEST}
+ {3181510800 7200 0 EET}
+ {3194816400 10800 1 EEST}
+ {3212960400 7200 0 EET}
+ {3226266000 10800 1 EEST}
+ {3245014800 7200 0 EET}
+ {3257715600 10800 1 EEST}
+ {3276464400 7200 0 EET}
+ {3289165200 10800 1 EEST}
+ {3307914000 7200 0 EET}
+ {3321219600 10800 1 EEST}
+ {3339363600 7200 0 EET}
+ {3352669200 10800 1 EEST}
+ {3370813200 7200 0 EET}
+ {3384118800 10800 1 EEST}
+ {3402867600 7200 0 EET}
+ {3415568400 10800 1 EEST}
+ {3434317200 7200 0 EET}
+ {3447018000 10800 1 EEST}
+ {3465766800 7200 0 EET}
+ {3479072400 10800 1 EEST}
+ {3497216400 7200 0 EET}
+ {3510522000 10800 1 EEST}
+ {3528666000 7200 0 EET}
+ {3541971600 10800 1 EEST}
+ {3560115600 7200 0 EET}
+ {3573421200 10800 1 EEST}
+ {3592170000 7200 0 EET}
+ {3604870800 10800 1 EEST}
+ {3623619600 7200 0 EET}
+ {3636320400 10800 1 EEST}
+ {3655069200 7200 0 EET}
+ {3668374800 10800 1 EEST}
+ {3686518800 7200 0 EET}
+ {3699824400 10800 1 EEST}
+ {3717968400 7200 0 EET}
+ {3731274000 10800 1 EEST}
+ {3750022800 7200 0 EET}
+ {3762723600 10800 1 EEST}
+ {3781472400 7200 0 EET}
+ {3794173200 10800 1 EEST}
+ {3812922000 7200 0 EET}
+ {3825622800 10800 1 EEST}
+ {3844371600 7200 0 EET}
+ {3857677200 10800 1 EEST}
+ {3875821200 7200 0 EET}
+ {3889126800 10800 1 EEST}
+ {3907270800 7200 0 EET}
+ {3920576400 10800 1 EEST}
+ {3939325200 7200 0 EET}
+ {3952026000 10800 1 EEST}
+ {3970774800 7200 0 EET}
+ {3983475600 10800 1 EEST}
+ {4002224400 7200 0 EET}
+ {4015530000 10800 1 EEST}
+ {4033674000 7200 0 EET}
+ {4046979600 10800 1 EEST}
+ {4065123600 7200 0 EET}
+ {4078429200 10800 1 EEST}
+ {4096573200 7200 0 EET}
+}
diff --git a/library/tzdata/Europe/Stockholm b/library/tzdata/Europe/Stockholm
new file mode 100644
index 0000000..b74d327
--- /dev/null
+++ b/library/tzdata/Europe/Stockholm
@@ -0,0 +1,250 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Stockholm) {
+ {-9223372036854775808 4332 0 LMT}
+ {-2871681132 3614 0 SET}
+ {-2208992414 3600 0 CET}
+ {-1692496800 7200 1 CEST}
+ {-1680483600 3600 0 CET}
+ {315529200 3600 0 CET}
+ {323830800 7200 1 CEST}
+ {338950800 3600 0 CET}
+ {354675600 7200 1 CEST}
+ {370400400 3600 0 CET}
+ {386125200 7200 1 CEST}
+ {401850000 3600 0 CET}
+ {417574800 7200 1 CEST}
+ {433299600 3600 0 CET}
+ {449024400 7200 1 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Tallinn b/library/tzdata/Europe/Tallinn
new file mode 100644
index 0000000..17f14e6
--- /dev/null
+++ b/library/tzdata/Europe/Tallinn
@@ -0,0 +1,255 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Tallinn) {
+ {-9223372036854775808 5940 0 LMT}
+ {-2840146740 5940 0 TMT}
+ {-1638322740 3600 0 CET}
+ {-1632006000 7200 1 CEST}
+ {-1618700400 3600 0 CET}
+ {-1593824400 5940 0 TMT}
+ {-1535938740 7200 0 EET}
+ {-927943200 10800 0 MSK}
+ {-892954800 3600 0 CET}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-797648400 10800 0 MSD}
+ {354920400 14400 1 MSD}
+ {370728000 10800 0 MSK}
+ {386456400 14400 1 MSD}
+ {402264000 10800 0 MSK}
+ {417992400 14400 1 MSD}
+ {433800000 10800 0 MSK}
+ {449614800 14400 1 MSD}
+ {465346800 10800 0 MSK}
+ {481071600 14400 1 MSD}
+ {496796400 10800 0 MSK}
+ {512521200 14400 1 MSD}
+ {528246000 10800 0 MSK}
+ {543970800 14400 1 MSD}
+ {559695600 10800 0 MSK}
+ {575420400 14400 1 MSD}
+ {591145200 10800 0 MSK}
+ {606870000 10800 1 EEST}
+ {622598400 7200 0 EET}
+ {638323200 10800 1 EEST}
+ {654652800 7200 0 EET}
+ {670377600 10800 1 EEST}
+ {686102400 7200 0 EET}
+ {701827200 10800 1 EEST}
+ {717552000 7200 0 EET}
+ {733276800 10800 1 EEST}
+ {749001600 7200 0 EET}
+ {764726400 10800 1 EEST}
+ {780451200 7200 0 EET}
+ {796176000 10800 1 EEST}
+ {811900800 7200 0 EET}
+ {828230400 10800 1 EEST}
+ {846374400 7200 0 EET}
+ {859680000 10800 1 EEST}
+ {877824000 7200 0 EET}
+ {891129600 10800 1 EEST}
+ {906415200 10800 0 EEST}
+ {909277200 7200 0 EET}
+ {922582800 10800 1 EEST}
+ {941331600 7200 0 EET}
+ {941407200 7200 0 EET}
+ {1014242400 7200 0 EET}
+ {1017536400 10800 1 EEST}
+ {1035680400 7200 0 EET}
+ {1048986000 10800 1 EEST}
+ {1067130000 7200 0 EET}
+ {1080435600 10800 1 EEST}
+ {1099184400 7200 0 EET}
+ {1111885200 10800 1 EEST}
+ {1130634000 7200 0 EET}
+ {1143334800 10800 1 EEST}
+ {1162083600 7200 0 EET}
+ {1174784400 10800 1 EEST}
+ {1193533200 7200 0 EET}
+ {1206838800 10800 1 EEST}
+ {1224982800 7200 0 EET}
+ {1238288400 10800 1 EEST}
+ {1256432400 7200 0 EET}
+ {1269738000 10800 1 EEST}
+ {1288486800 7200 0 EET}
+ {1301187600 10800 1 EEST}
+ {1319936400 7200 0 EET}
+ {1332637200 10800 1 EEST}
+ {1351386000 7200 0 EET}
+ {1364691600 10800 1 EEST}
+ {1382835600 7200 0 EET}
+ {1396141200 10800 1 EEST}
+ {1414285200 7200 0 EET}
+ {1427590800 10800 1 EEST}
+ {1445734800 7200 0 EET}
+ {1459040400 10800 1 EEST}
+ {1477789200 7200 0 EET}
+ {1490490000 10800 1 EEST}
+ {1509238800 7200 0 EET}
+ {1521939600 10800 1 EEST}
+ {1540688400 7200 0 EET}
+ {1553994000 10800 1 EEST}
+ {1572138000 7200 0 EET}
+ {1585443600 10800 1 EEST}
+ {1603587600 7200 0 EET}
+ {1616893200 10800 1 EEST}
+ {1635642000 7200 0 EET}
+ {1648342800 10800 1 EEST}
+ {1667091600 7200 0 EET}
+ {1679792400 10800 1 EEST}
+ {1698541200 7200 0 EET}
+ {1711846800 10800 1 EEST}
+ {1729990800 7200 0 EET}
+ {1743296400 10800 1 EEST}
+ {1761440400 7200 0 EET}
+ {1774746000 10800 1 EEST}
+ {1792890000 7200 0 EET}
+ {1806195600 10800 1 EEST}
+ {1824944400 7200 0 EET}
+ {1837645200 10800 1 EEST}
+ {1856394000 7200 0 EET}
+ {1869094800 10800 1 EEST}
+ {1887843600 7200 0 EET}
+ {1901149200 10800 1 EEST}
+ {1919293200 7200 0 EET}
+ {1932598800 10800 1 EEST}
+ {1950742800 7200 0 EET}
+ {1964048400 10800 1 EEST}
+ {1982797200 7200 0 EET}
+ {1995498000 10800 1 EEST}
+ {2014246800 7200 0 EET}
+ {2026947600 10800 1 EEST}
+ {2045696400 7200 0 EET}
+ {2058397200 10800 1 EEST}
+ {2077146000 7200 0 EET}
+ {2090451600 10800 1 EEST}
+ {2108595600 7200 0 EET}
+ {2121901200 10800 1 EEST}
+ {2140045200 7200 0 EET}
+ {2153350800 10800 1 EEST}
+ {2172099600 7200 0 EET}
+ {2184800400 10800 1 EEST}
+ {2203549200 7200 0 EET}
+ {2216250000 10800 1 EEST}
+ {2234998800 7200 0 EET}
+ {2248304400 10800 1 EEST}
+ {2266448400 7200 0 EET}
+ {2279754000 10800 1 EEST}
+ {2297898000 7200 0 EET}
+ {2311203600 10800 1 EEST}
+ {2329347600 7200 0 EET}
+ {2342653200 10800 1 EEST}
+ {2361402000 7200 0 EET}
+ {2374102800 10800 1 EEST}
+ {2392851600 7200 0 EET}
+ {2405552400 10800 1 EEST}
+ {2424301200 7200 0 EET}
+ {2437606800 10800 1 EEST}
+ {2455750800 7200 0 EET}
+ {2469056400 10800 1 EEST}
+ {2487200400 7200 0 EET}
+ {2500506000 10800 1 EEST}
+ {2519254800 7200 0 EET}
+ {2531955600 10800 1 EEST}
+ {2550704400 7200 0 EET}
+ {2563405200 10800 1 EEST}
+ {2582154000 7200 0 EET}
+ {2595459600 10800 1 EEST}
+ {2613603600 7200 0 EET}
+ {2626909200 10800 1 EEST}
+ {2645053200 7200 0 EET}
+ {2658358800 10800 1 EEST}
+ {2676502800 7200 0 EET}
+ {2689808400 10800 1 EEST}
+ {2708557200 7200 0 EET}
+ {2721258000 10800 1 EEST}
+ {2740006800 7200 0 EET}
+ {2752707600 10800 1 EEST}
+ {2771456400 7200 0 EET}
+ {2784762000 10800 1 EEST}
+ {2802906000 7200 0 EET}
+ {2816211600 10800 1 EEST}
+ {2834355600 7200 0 EET}
+ {2847661200 10800 1 EEST}
+ {2866410000 7200 0 EET}
+ {2879110800 10800 1 EEST}
+ {2897859600 7200 0 EET}
+ {2910560400 10800 1 EEST}
+ {2929309200 7200 0 EET}
+ {2942010000 10800 1 EEST}
+ {2960758800 7200 0 EET}
+ {2974064400 10800 1 EEST}
+ {2992208400 7200 0 EET}
+ {3005514000 10800 1 EEST}
+ {3023658000 7200 0 EET}
+ {3036963600 10800 1 EEST}
+ {3055712400 7200 0 EET}
+ {3068413200 10800 1 EEST}
+ {3087162000 7200 0 EET}
+ {3099862800 10800 1 EEST}
+ {3118611600 7200 0 EET}
+ {3131917200 10800 1 EEST}
+ {3150061200 7200 0 EET}
+ {3163366800 10800 1 EEST}
+ {3181510800 7200 0 EET}
+ {3194816400 10800 1 EEST}
+ {3212960400 7200 0 EET}
+ {3226266000 10800 1 EEST}
+ {3245014800 7200 0 EET}
+ {3257715600 10800 1 EEST}
+ {3276464400 7200 0 EET}
+ {3289165200 10800 1 EEST}
+ {3307914000 7200 0 EET}
+ {3321219600 10800 1 EEST}
+ {3339363600 7200 0 EET}
+ {3352669200 10800 1 EEST}
+ {3370813200 7200 0 EET}
+ {3384118800 10800 1 EEST}
+ {3402867600 7200 0 EET}
+ {3415568400 10800 1 EEST}
+ {3434317200 7200 0 EET}
+ {3447018000 10800 1 EEST}
+ {3465766800 7200 0 EET}
+ {3479072400 10800 1 EEST}
+ {3497216400 7200 0 EET}
+ {3510522000 10800 1 EEST}
+ {3528666000 7200 0 EET}
+ {3541971600 10800 1 EEST}
+ {3560115600 7200 0 EET}
+ {3573421200 10800 1 EEST}
+ {3592170000 7200 0 EET}
+ {3604870800 10800 1 EEST}
+ {3623619600 7200 0 EET}
+ {3636320400 10800 1 EEST}
+ {3655069200 7200 0 EET}
+ {3668374800 10800 1 EEST}
+ {3686518800 7200 0 EET}
+ {3699824400 10800 1 EEST}
+ {3717968400 7200 0 EET}
+ {3731274000 10800 1 EEST}
+ {3750022800 7200 0 EET}
+ {3762723600 10800 1 EEST}
+ {3781472400 7200 0 EET}
+ {3794173200 10800 1 EEST}
+ {3812922000 7200 0 EET}
+ {3825622800 10800 1 EEST}
+ {3844371600 7200 0 EET}
+ {3857677200 10800 1 EEST}
+ {3875821200 7200 0 EET}
+ {3889126800 10800 1 EEST}
+ {3907270800 7200 0 EET}
+ {3920576400 10800 1 EEST}
+ {3939325200 7200 0 EET}
+ {3952026000 10800 1 EEST}
+ {3970774800 7200 0 EET}
+ {3983475600 10800 1 EEST}
+ {4002224400 7200 0 EET}
+ {4015530000 10800 1 EEST}
+ {4033674000 7200 0 EET}
+ {4046979600 10800 1 EEST}
+ {4065123600 7200 0 EET}
+ {4078429200 10800 1 EEST}
+ {4096573200 7200 0 EET}
+}
diff --git a/library/tzdata/Europe/Tirane b/library/tzdata/Europe/Tirane
new file mode 100644
index 0000000..14ace2e
--- /dev/null
+++ b/library/tzdata/Europe/Tirane
@@ -0,0 +1,263 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Tirane) {
+ {-9223372036854775808 4760 0 LMT}
+ {-1767230360 3600 0 CET}
+ {-932346000 7200 0 CEST}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-843519600 3600 0 CET}
+ {136854000 7200 1 CEST}
+ {149896800 3600 0 CET}
+ {168130800 7200 1 CEST}
+ {181432800 3600 0 CET}
+ {199839600 7200 1 CEST}
+ {213141600 3600 0 CET}
+ {231894000 7200 1 CEST}
+ {244591200 3600 0 CET}
+ {263257200 7200 1 CEST}
+ {276040800 3600 0 CET}
+ {294706800 7200 1 CEST}
+ {307490400 3600 0 CET}
+ {326156400 7200 1 CEST}
+ {339458400 3600 0 CET}
+ {357087600 7200 1 CEST}
+ {370389600 3600 0 CET}
+ {389142000 7200 1 CEST}
+ {402444000 3600 0 CET}
+ {419468400 7200 1 CEST}
+ {433807200 3600 0 CET}
+ {449622000 7200 1 CEST}
+ {457480800 7200 0 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Tiraspol b/library/tzdata/Europe/Tiraspol
new file mode 100644
index 0000000..ea8f671
--- /dev/null
+++ b/library/tzdata/Europe/Tiraspol
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/Chisinau)]} {
+ LoadTimeZoneFile Europe/Chisinau
+}
+set TZData(:Europe/Tiraspol) $TZData(:Europe/Chisinau)
diff --git a/library/tzdata/Europe/Uzhgorod b/library/tzdata/Europe/Uzhgorod
new file mode 100644
index 0000000..f6e580b
--- /dev/null
+++ b/library/tzdata/Europe/Uzhgorod
@@ -0,0 +1,254 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Uzhgorod) {
+ {-9223372036854775808 5352 0 LMT}
+ {-2500939752 3600 0 CET}
+ {-946774800 3600 0 CET}
+ {-938905200 7200 1 CEST}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-796870800 7200 1 CEST}
+ {-794714400 3600 0 CET}
+ {-773456400 10800 0 MSD}
+ {354920400 14400 1 MSD}
+ {370728000 10800 0 MSK}
+ {386456400 14400 1 MSD}
+ {402264000 10800 0 MSK}
+ {417992400 14400 1 MSD}
+ {433800000 10800 0 MSK}
+ {449614800 14400 1 MSD}
+ {465346800 10800 0 MSK}
+ {481071600 14400 1 MSD}
+ {496796400 10800 0 MSK}
+ {512521200 14400 1 MSD}
+ {528246000 10800 0 MSK}
+ {543970800 14400 1 MSD}
+ {559695600 10800 0 MSK}
+ {575420400 14400 1 MSD}
+ {591145200 10800 0 MSK}
+ {606870000 14400 1 MSD}
+ {622594800 10800 0 MSK}
+ {631141200 10800 0 MSK}
+ {646786800 3600 0 CET}
+ {670384800 7200 0 EET}
+ {694216800 7200 0 EET}
+ {701820000 10800 1 EEST}
+ {717541200 7200 0 EET}
+ {733269600 10800 1 EEST}
+ {748990800 7200 0 EET}
+ {764719200 10800 1 EEST}
+ {780440400 7200 0 EET}
+ {788911200 7200 0 EET}
+ {796179600 10800 1 EEST}
+ {811904400 7200 0 EET}
+ {828234000 10800 1 EEST}
+ {846378000 7200 0 EET}
+ {859683600 10800 1 EEST}
+ {877827600 7200 0 EET}
+ {891133200 10800 1 EEST}
+ {909277200 7200 0 EET}
+ {922582800 10800 1 EEST}
+ {941331600 7200 0 EET}
+ {954032400 10800 1 EEST}
+ {972781200 7200 0 EET}
+ {985482000 10800 1 EEST}
+ {1004230800 7200 0 EET}
+ {1017536400 10800 1 EEST}
+ {1035680400 7200 0 EET}
+ {1048986000 10800 1 EEST}
+ {1067130000 7200 0 EET}
+ {1080435600 10800 1 EEST}
+ {1099184400 7200 0 EET}
+ {1111885200 10800 1 EEST}
+ {1130634000 7200 0 EET}
+ {1143334800 10800 1 EEST}
+ {1162083600 7200 0 EET}
+ {1174784400 10800 1 EEST}
+ {1193533200 7200 0 EET}
+ {1206838800 10800 1 EEST}
+ {1224982800 7200 0 EET}
+ {1238288400 10800 1 EEST}
+ {1256432400 7200 0 EET}
+ {1269738000 10800 1 EEST}
+ {1288486800 7200 0 EET}
+ {1301187600 10800 1 EEST}
+ {1319936400 7200 0 EET}
+ {1332637200 10800 1 EEST}
+ {1351386000 7200 0 EET}
+ {1364691600 10800 1 EEST}
+ {1382835600 7200 0 EET}
+ {1396141200 10800 1 EEST}
+ {1414285200 7200 0 EET}
+ {1427590800 10800 1 EEST}
+ {1445734800 7200 0 EET}
+ {1459040400 10800 1 EEST}
+ {1477789200 7200 0 EET}
+ {1490490000 10800 1 EEST}
+ {1509238800 7200 0 EET}
+ {1521939600 10800 1 EEST}
+ {1540688400 7200 0 EET}
+ {1553994000 10800 1 EEST}
+ {1572138000 7200 0 EET}
+ {1585443600 10800 1 EEST}
+ {1603587600 7200 0 EET}
+ {1616893200 10800 1 EEST}
+ {1635642000 7200 0 EET}
+ {1648342800 10800 1 EEST}
+ {1667091600 7200 0 EET}
+ {1679792400 10800 1 EEST}
+ {1698541200 7200 0 EET}
+ {1711846800 10800 1 EEST}
+ {1729990800 7200 0 EET}
+ {1743296400 10800 1 EEST}
+ {1761440400 7200 0 EET}
+ {1774746000 10800 1 EEST}
+ {1792890000 7200 0 EET}
+ {1806195600 10800 1 EEST}
+ {1824944400 7200 0 EET}
+ {1837645200 10800 1 EEST}
+ {1856394000 7200 0 EET}
+ {1869094800 10800 1 EEST}
+ {1887843600 7200 0 EET}
+ {1901149200 10800 1 EEST}
+ {1919293200 7200 0 EET}
+ {1932598800 10800 1 EEST}
+ {1950742800 7200 0 EET}
+ {1964048400 10800 1 EEST}
+ {1982797200 7200 0 EET}
+ {1995498000 10800 1 EEST}
+ {2014246800 7200 0 EET}
+ {2026947600 10800 1 EEST}
+ {2045696400 7200 0 EET}
+ {2058397200 10800 1 EEST}
+ {2077146000 7200 0 EET}
+ {2090451600 10800 1 EEST}
+ {2108595600 7200 0 EET}
+ {2121901200 10800 1 EEST}
+ {2140045200 7200 0 EET}
+ {2153350800 10800 1 EEST}
+ {2172099600 7200 0 EET}
+ {2184800400 10800 1 EEST}
+ {2203549200 7200 0 EET}
+ {2216250000 10800 1 EEST}
+ {2234998800 7200 0 EET}
+ {2248304400 10800 1 EEST}
+ {2266448400 7200 0 EET}
+ {2279754000 10800 1 EEST}
+ {2297898000 7200 0 EET}
+ {2311203600 10800 1 EEST}
+ {2329347600 7200 0 EET}
+ {2342653200 10800 1 EEST}
+ {2361402000 7200 0 EET}
+ {2374102800 10800 1 EEST}
+ {2392851600 7200 0 EET}
+ {2405552400 10800 1 EEST}
+ {2424301200 7200 0 EET}
+ {2437606800 10800 1 EEST}
+ {2455750800 7200 0 EET}
+ {2469056400 10800 1 EEST}
+ {2487200400 7200 0 EET}
+ {2500506000 10800 1 EEST}
+ {2519254800 7200 0 EET}
+ {2531955600 10800 1 EEST}
+ {2550704400 7200 0 EET}
+ {2563405200 10800 1 EEST}
+ {2582154000 7200 0 EET}
+ {2595459600 10800 1 EEST}
+ {2613603600 7200 0 EET}
+ {2626909200 10800 1 EEST}
+ {2645053200 7200 0 EET}
+ {2658358800 10800 1 EEST}
+ {2676502800 7200 0 EET}
+ {2689808400 10800 1 EEST}
+ {2708557200 7200 0 EET}
+ {2721258000 10800 1 EEST}
+ {2740006800 7200 0 EET}
+ {2752707600 10800 1 EEST}
+ {2771456400 7200 0 EET}
+ {2784762000 10800 1 EEST}
+ {2802906000 7200 0 EET}
+ {2816211600 10800 1 EEST}
+ {2834355600 7200 0 EET}
+ {2847661200 10800 1 EEST}
+ {2866410000 7200 0 EET}
+ {2879110800 10800 1 EEST}
+ {2897859600 7200 0 EET}
+ {2910560400 10800 1 EEST}
+ {2929309200 7200 0 EET}
+ {2942010000 10800 1 EEST}
+ {2960758800 7200 0 EET}
+ {2974064400 10800 1 EEST}
+ {2992208400 7200 0 EET}
+ {3005514000 10800 1 EEST}
+ {3023658000 7200 0 EET}
+ {3036963600 10800 1 EEST}
+ {3055712400 7200 0 EET}
+ {3068413200 10800 1 EEST}
+ {3087162000 7200 0 EET}
+ {3099862800 10800 1 EEST}
+ {3118611600 7200 0 EET}
+ {3131917200 10800 1 EEST}
+ {3150061200 7200 0 EET}
+ {3163366800 10800 1 EEST}
+ {3181510800 7200 0 EET}
+ {3194816400 10800 1 EEST}
+ {3212960400 7200 0 EET}
+ {3226266000 10800 1 EEST}
+ {3245014800 7200 0 EET}
+ {3257715600 10800 1 EEST}
+ {3276464400 7200 0 EET}
+ {3289165200 10800 1 EEST}
+ {3307914000 7200 0 EET}
+ {3321219600 10800 1 EEST}
+ {3339363600 7200 0 EET}
+ {3352669200 10800 1 EEST}
+ {3370813200 7200 0 EET}
+ {3384118800 10800 1 EEST}
+ {3402867600 7200 0 EET}
+ {3415568400 10800 1 EEST}
+ {3434317200 7200 0 EET}
+ {3447018000 10800 1 EEST}
+ {3465766800 7200 0 EET}
+ {3479072400 10800 1 EEST}
+ {3497216400 7200 0 EET}
+ {3510522000 10800 1 EEST}
+ {3528666000 7200 0 EET}
+ {3541971600 10800 1 EEST}
+ {3560115600 7200 0 EET}
+ {3573421200 10800 1 EEST}
+ {3592170000 7200 0 EET}
+ {3604870800 10800 1 EEST}
+ {3623619600 7200 0 EET}
+ {3636320400 10800 1 EEST}
+ {3655069200 7200 0 EET}
+ {3668374800 10800 1 EEST}
+ {3686518800 7200 0 EET}
+ {3699824400 10800 1 EEST}
+ {3717968400 7200 0 EET}
+ {3731274000 10800 1 EEST}
+ {3750022800 7200 0 EET}
+ {3762723600 10800 1 EEST}
+ {3781472400 7200 0 EET}
+ {3794173200 10800 1 EEST}
+ {3812922000 7200 0 EET}
+ {3825622800 10800 1 EEST}
+ {3844371600 7200 0 EET}
+ {3857677200 10800 1 EEST}
+ {3875821200 7200 0 EET}
+ {3889126800 10800 1 EEST}
+ {3907270800 7200 0 EET}
+ {3920576400 10800 1 EEST}
+ {3939325200 7200 0 EET}
+ {3952026000 10800 1 EEST}
+ {3970774800 7200 0 EET}
+ {3983475600 10800 1 EEST}
+ {4002224400 7200 0 EET}
+ {4015530000 10800 1 EEST}
+ {4033674000 7200 0 EET}
+ {4046979600 10800 1 EEST}
+ {4065123600 7200 0 EET}
+ {4078429200 10800 1 EEST}
+ {4096573200 7200 0 EET}
+}
diff --git a/library/tzdata/Europe/Vaduz b/library/tzdata/Europe/Vaduz
new file mode 100644
index 0000000..3118331
--- /dev/null
+++ b/library/tzdata/Europe/Vaduz
@@ -0,0 +1,245 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Vaduz) {
+ {-9223372036854775808 2284 0 LMT}
+ {-2385247084 3600 0 CET}
+ {347151600 3600 0 CET}
+ {354675600 7200 1 CEST}
+ {370400400 3600 0 CET}
+ {386125200 7200 1 CEST}
+ {401850000 3600 0 CET}
+ {417574800 7200 1 CEST}
+ {433299600 3600 0 CET}
+ {449024400 7200 1 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Vatican b/library/tzdata/Europe/Vatican
new file mode 100644
index 0000000..fe50765
--- /dev/null
+++ b/library/tzdata/Europe/Vatican
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/Rome)]} {
+ LoadTimeZoneFile Europe/Rome
+}
+set TZData(:Europe/Vatican) $TZData(:Europe/Rome)
diff --git a/library/tzdata/Europe/Vienna b/library/tzdata/Europe/Vienna
new file mode 100644
index 0000000..41d744d
--- /dev/null
+++ b/library/tzdata/Europe/Vienna
@@ -0,0 +1,271 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Vienna) {
+ {-9223372036854775808 3920 0 LMT}
+ {-2422055120 3600 0 CET}
+ {-1693706400 7200 1 CEST}
+ {-1680483600 3600 0 CET}
+ {-1663455600 7200 1 CEST}
+ {-1650150000 3600 0 CET}
+ {-1632006000 7200 1 CEST}
+ {-1618700400 3600 0 CET}
+ {-1577926800 3600 0 CET}
+ {-1569711600 7200 1 CEST}
+ {-1555801200 3600 0 CET}
+ {-938905200 7200 0 CEST}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-796777200 3600 0 CET}
+ {-781052400 7200 1 CEST}
+ {-780188400 3600 0 CET}
+ {-757386000 3600 0 CET}
+ {-748479600 7200 1 CEST}
+ {-733359600 3600 0 CET}
+ {-717634800 7200 1 CEST}
+ {-701910000 3600 0 CET}
+ {-684975600 7200 1 CEST}
+ {-670460400 3600 0 CET}
+ {323823600 7200 1 CEST}
+ {338940000 3600 0 CET}
+ {347151600 3600 0 CET}
+ {354675600 7200 1 CEST}
+ {370400400 3600 0 CET}
+ {386125200 7200 1 CEST}
+ {401850000 3600 0 CET}
+ {417574800 7200 1 CEST}
+ {433299600 3600 0 CET}
+ {449024400 7200 1 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Vilnius b/library/tzdata/Europe/Vilnius
new file mode 100644
index 0000000..62d5d87
--- /dev/null
+++ b/library/tzdata/Europe/Vilnius
@@ -0,0 +1,251 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Vilnius) {
+ {-9223372036854775808 6076 0 LMT}
+ {-2840146876 5040 0 WMT}
+ {-1672536240 5736 0 KMT}
+ {-1585100136 3600 0 CET}
+ {-1561251600 7200 0 EET}
+ {-1553565600 3600 0 CET}
+ {-928198800 10800 0 MSK}
+ {-900126000 3600 0 CET}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-802141200 10800 0 MSD}
+ {354920400 14400 1 MSD}
+ {370728000 10800 0 MSK}
+ {386456400 14400 1 MSD}
+ {402264000 10800 0 MSK}
+ {417992400 14400 1 MSD}
+ {433800000 10800 0 MSK}
+ {449614800 14400 1 MSD}
+ {465346800 10800 0 MSK}
+ {481071600 14400 1 MSD}
+ {496796400 10800 0 MSK}
+ {512521200 14400 1 MSD}
+ {528246000 10800 0 MSK}
+ {543970800 14400 1 MSD}
+ {559695600 10800 0 MSK}
+ {575420400 14400 1 MSD}
+ {591145200 10800 0 MSK}
+ {606870000 14400 1 MSD}
+ {622594800 10800 0 MSK}
+ {638319600 14400 1 MSD}
+ {654649200 10800 0 MSK}
+ {670374000 10800 1 EEST}
+ {686102400 7200 0 EET}
+ {701827200 10800 1 EEST}
+ {717552000 7200 0 EET}
+ {733276800 10800 1 EEST}
+ {749001600 7200 0 EET}
+ {764726400 10800 1 EEST}
+ {780451200 7200 0 EET}
+ {796176000 10800 1 EEST}
+ {811900800 7200 0 EET}
+ {828230400 10800 1 EEST}
+ {846374400 7200 0 EET}
+ {859680000 10800 1 EEST}
+ {877824000 7200 0 EET}
+ {883605600 7200 0 EET}
+ {891133200 7200 0 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 7200 0 EET}
+ {1041372000 7200 0 EET}
+ {1048986000 10800 1 EEST}
+ {1067130000 7200 0 EET}
+ {1080435600 10800 1 EEST}
+ {1099184400 7200 0 EET}
+ {1111885200 10800 1 EEST}
+ {1130634000 7200 0 EET}
+ {1143334800 10800 1 EEST}
+ {1162083600 7200 0 EET}
+ {1174784400 10800 1 EEST}
+ {1193533200 7200 0 EET}
+ {1206838800 10800 1 EEST}
+ {1224982800 7200 0 EET}
+ {1238288400 10800 1 EEST}
+ {1256432400 7200 0 EET}
+ {1269738000 10800 1 EEST}
+ {1288486800 7200 0 EET}
+ {1301187600 10800 1 EEST}
+ {1319936400 7200 0 EET}
+ {1332637200 10800 1 EEST}
+ {1351386000 7200 0 EET}
+ {1364691600 10800 1 EEST}
+ {1382835600 7200 0 EET}
+ {1396141200 10800 1 EEST}
+ {1414285200 7200 0 EET}
+ {1427590800 10800 1 EEST}
+ {1445734800 7200 0 EET}
+ {1459040400 10800 1 EEST}
+ {1477789200 7200 0 EET}
+ {1490490000 10800 1 EEST}
+ {1509238800 7200 0 EET}
+ {1521939600 10800 1 EEST}
+ {1540688400 7200 0 EET}
+ {1553994000 10800 1 EEST}
+ {1572138000 7200 0 EET}
+ {1585443600 10800 1 EEST}
+ {1603587600 7200 0 EET}
+ {1616893200 10800 1 EEST}
+ {1635642000 7200 0 EET}
+ {1648342800 10800 1 EEST}
+ {1667091600 7200 0 EET}
+ {1679792400 10800 1 EEST}
+ {1698541200 7200 0 EET}
+ {1711846800 10800 1 EEST}
+ {1729990800 7200 0 EET}
+ {1743296400 10800 1 EEST}
+ {1761440400 7200 0 EET}
+ {1774746000 10800 1 EEST}
+ {1792890000 7200 0 EET}
+ {1806195600 10800 1 EEST}
+ {1824944400 7200 0 EET}
+ {1837645200 10800 1 EEST}
+ {1856394000 7200 0 EET}
+ {1869094800 10800 1 EEST}
+ {1887843600 7200 0 EET}
+ {1901149200 10800 1 EEST}
+ {1919293200 7200 0 EET}
+ {1932598800 10800 1 EEST}
+ {1950742800 7200 0 EET}
+ {1964048400 10800 1 EEST}
+ {1982797200 7200 0 EET}
+ {1995498000 10800 1 EEST}
+ {2014246800 7200 0 EET}
+ {2026947600 10800 1 EEST}
+ {2045696400 7200 0 EET}
+ {2058397200 10800 1 EEST}
+ {2077146000 7200 0 EET}
+ {2090451600 10800 1 EEST}
+ {2108595600 7200 0 EET}
+ {2121901200 10800 1 EEST}
+ {2140045200 7200 0 EET}
+ {2153350800 10800 1 EEST}
+ {2172099600 7200 0 EET}
+ {2184800400 10800 1 EEST}
+ {2203549200 7200 0 EET}
+ {2216250000 10800 1 EEST}
+ {2234998800 7200 0 EET}
+ {2248304400 10800 1 EEST}
+ {2266448400 7200 0 EET}
+ {2279754000 10800 1 EEST}
+ {2297898000 7200 0 EET}
+ {2311203600 10800 1 EEST}
+ {2329347600 7200 0 EET}
+ {2342653200 10800 1 EEST}
+ {2361402000 7200 0 EET}
+ {2374102800 10800 1 EEST}
+ {2392851600 7200 0 EET}
+ {2405552400 10800 1 EEST}
+ {2424301200 7200 0 EET}
+ {2437606800 10800 1 EEST}
+ {2455750800 7200 0 EET}
+ {2469056400 10800 1 EEST}
+ {2487200400 7200 0 EET}
+ {2500506000 10800 1 EEST}
+ {2519254800 7200 0 EET}
+ {2531955600 10800 1 EEST}
+ {2550704400 7200 0 EET}
+ {2563405200 10800 1 EEST}
+ {2582154000 7200 0 EET}
+ {2595459600 10800 1 EEST}
+ {2613603600 7200 0 EET}
+ {2626909200 10800 1 EEST}
+ {2645053200 7200 0 EET}
+ {2658358800 10800 1 EEST}
+ {2676502800 7200 0 EET}
+ {2689808400 10800 1 EEST}
+ {2708557200 7200 0 EET}
+ {2721258000 10800 1 EEST}
+ {2740006800 7200 0 EET}
+ {2752707600 10800 1 EEST}
+ {2771456400 7200 0 EET}
+ {2784762000 10800 1 EEST}
+ {2802906000 7200 0 EET}
+ {2816211600 10800 1 EEST}
+ {2834355600 7200 0 EET}
+ {2847661200 10800 1 EEST}
+ {2866410000 7200 0 EET}
+ {2879110800 10800 1 EEST}
+ {2897859600 7200 0 EET}
+ {2910560400 10800 1 EEST}
+ {2929309200 7200 0 EET}
+ {2942010000 10800 1 EEST}
+ {2960758800 7200 0 EET}
+ {2974064400 10800 1 EEST}
+ {2992208400 7200 0 EET}
+ {3005514000 10800 1 EEST}
+ {3023658000 7200 0 EET}
+ {3036963600 10800 1 EEST}
+ {3055712400 7200 0 EET}
+ {3068413200 10800 1 EEST}
+ {3087162000 7200 0 EET}
+ {3099862800 10800 1 EEST}
+ {3118611600 7200 0 EET}
+ {3131917200 10800 1 EEST}
+ {3150061200 7200 0 EET}
+ {3163366800 10800 1 EEST}
+ {3181510800 7200 0 EET}
+ {3194816400 10800 1 EEST}
+ {3212960400 7200 0 EET}
+ {3226266000 10800 1 EEST}
+ {3245014800 7200 0 EET}
+ {3257715600 10800 1 EEST}
+ {3276464400 7200 0 EET}
+ {3289165200 10800 1 EEST}
+ {3307914000 7200 0 EET}
+ {3321219600 10800 1 EEST}
+ {3339363600 7200 0 EET}
+ {3352669200 10800 1 EEST}
+ {3370813200 7200 0 EET}
+ {3384118800 10800 1 EEST}
+ {3402867600 7200 0 EET}
+ {3415568400 10800 1 EEST}
+ {3434317200 7200 0 EET}
+ {3447018000 10800 1 EEST}
+ {3465766800 7200 0 EET}
+ {3479072400 10800 1 EEST}
+ {3497216400 7200 0 EET}
+ {3510522000 10800 1 EEST}
+ {3528666000 7200 0 EET}
+ {3541971600 10800 1 EEST}
+ {3560115600 7200 0 EET}
+ {3573421200 10800 1 EEST}
+ {3592170000 7200 0 EET}
+ {3604870800 10800 1 EEST}
+ {3623619600 7200 0 EET}
+ {3636320400 10800 1 EEST}
+ {3655069200 7200 0 EET}
+ {3668374800 10800 1 EEST}
+ {3686518800 7200 0 EET}
+ {3699824400 10800 1 EEST}
+ {3717968400 7200 0 EET}
+ {3731274000 10800 1 EEST}
+ {3750022800 7200 0 EET}
+ {3762723600 10800 1 EEST}
+ {3781472400 7200 0 EET}
+ {3794173200 10800 1 EEST}
+ {3812922000 7200 0 EET}
+ {3825622800 10800 1 EEST}
+ {3844371600 7200 0 EET}
+ {3857677200 10800 1 EEST}
+ {3875821200 7200 0 EET}
+ {3889126800 10800 1 EEST}
+ {3907270800 7200 0 EET}
+ {3920576400 10800 1 EEST}
+ {3939325200 7200 0 EET}
+ {3952026000 10800 1 EEST}
+ {3970774800 7200 0 EET}
+ {3983475600 10800 1 EEST}
+ {4002224400 7200 0 EET}
+ {4015530000 10800 1 EEST}
+ {4033674000 7200 0 EET}
+ {4046979600 10800 1 EEST}
+ {4065123600 7200 0 EET}
+ {4078429200 10800 1 EEST}
+ {4096573200 7200 0 EET}
+}
diff --git a/library/tzdata/Europe/Volgograd b/library/tzdata/Europe/Volgograd
new file mode 100755
index 0000000..c3f148f
--- /dev/null
+++ b/library/tzdata/Europe/Volgograd
@@ -0,0 +1,70 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Volgograd) {
+ {-9223372036854775808 10660 0 LMT}
+ {-1577761060 10800 0 TSAT}
+ {-1411873200 10800 0 STAT}
+ {-1247540400 14400 0 STAT}
+ {-256881600 14400 0 VOLMMTT}
+ {354916800 18000 1 VOLST}
+ {370724400 14400 0 VOLT}
+ {386452800 18000 1 VOLST}
+ {402260400 14400 0 VOLT}
+ {417988800 18000 1 VOLST}
+ {433796400 14400 0 VOLT}
+ {449611200 18000 1 VOLST}
+ {465343200 14400 0 VOLT}
+ {481068000 18000 1 VOLST}
+ {496792800 14400 0 VOLT}
+ {512517600 18000 1 VOLST}
+ {528242400 14400 0 VOLT}
+ {543967200 18000 1 VOLST}
+ {559692000 14400 0 VOLT}
+ {575416800 18000 1 VOLST}
+ {591141600 14400 0 VOLT}
+ {606866400 10800 0 VOLMMTT}
+ {606870000 14400 1 VOLST}
+ {622594800 10800 0 VOLT}
+ {638319600 14400 1 VOLST}
+ {654649200 10800 0 VOLT}
+ {670374000 14400 0 VOLT}
+ {701820000 14400 0 VOLST}
+ {717534000 10800 0 VOLT}
+ {733273200 14400 1 VOLST}
+ {748998000 10800 0 VOLT}
+ {764722800 14400 1 VOLST}
+ {780447600 10800 0 VOLT}
+ {796172400 14400 1 VOLST}
+ {811897200 10800 0 VOLT}
+ {828226800 14400 1 VOLST}
+ {846370800 10800 0 VOLT}
+ {859676400 14400 1 VOLST}
+ {877820400 10800 0 VOLT}
+ {891126000 14400 1 VOLST}
+ {909270000 10800 0 VOLT}
+ {922575600 14400 1 VOLST}
+ {941324400 10800 0 VOLT}
+ {954025200 14400 1 VOLST}
+ {972774000 10800 0 VOLT}
+ {985474800 14400 1 VOLST}
+ {1004223600 10800 0 VOLT}
+ {1017529200 14400 1 VOLST}
+ {1035673200 10800 0 VOLT}
+ {1048978800 14400 1 VOLST}
+ {1067122800 10800 0 VOLT}
+ {1080428400 14400 1 VOLST}
+ {1099177200 10800 0 VOLT}
+ {1111878000 14400 1 VOLST}
+ {1130626800 10800 0 VOLT}
+ {1143327600 14400 1 VOLST}
+ {1162076400 10800 0 VOLT}
+ {1174777200 14400 1 VOLST}
+ {1193526000 10800 0 VOLT}
+ {1206831600 14400 1 VOLST}
+ {1224975600 10800 0 VOLT}
+ {1238281200 14400 1 VOLST}
+ {1256425200 10800 0 VOLT}
+ {1269730800 14400 1 VOLST}
+ {1288479600 10800 0 VOLT}
+ {1301180400 14400 0 VOLT}
+}
diff --git a/library/tzdata/Europe/Warsaw b/library/tzdata/Europe/Warsaw
new file mode 100644
index 0000000..6288a8a
--- /dev/null
+++ b/library/tzdata/Europe/Warsaw
@@ -0,0 +1,296 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Warsaw) {
+ {-9223372036854775808 5040 0 LMT}
+ {-2840145840 5040 0 WMT}
+ {-1717032240 3600 0 CET}
+ {-1693706400 7200 1 CEST}
+ {-1680483600 3600 0 CET}
+ {-1663455600 7200 1 CEST}
+ {-1650150000 3600 0 CET}
+ {-1632006000 7200 1 CEST}
+ {-1618696800 7200 0 EET}
+ {-1600473600 10800 1 EEST}
+ {-1587168000 7200 0 EET}
+ {-931734000 7200 0 CEST}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-812502000 7200 1 CEST}
+ {-796870800 7200 0 CEST}
+ {-796608000 3600 0 CET}
+ {-778726800 7200 1 CEST}
+ {-762660000 3600 0 CET}
+ {-748486800 7200 1 CEST}
+ {-733273200 3600 0 CET}
+ {-715215600 7200 1 CEST}
+ {-701910000 3600 0 CET}
+ {-684975600 7200 1 CEST}
+ {-670460400 3600 0 CET}
+ {-654130800 7200 1 CEST}
+ {-639010800 3600 0 CET}
+ {-397094400 7200 1 CEST}
+ {-386812800 3600 0 CET}
+ {-371088000 7200 1 CEST}
+ {-355363200 3600 0 CET}
+ {-334195200 7200 1 CEST}
+ {-323308800 3600 0 CET}
+ {-307584000 7200 1 CEST}
+ {-291859200 3600 0 CET}
+ {-271296000 7200 1 CEST}
+ {-260409600 3600 0 CET}
+ {-239846400 7200 1 CEST}
+ {-228960000 3600 0 CET}
+ {-208396800 7200 1 CEST}
+ {-197510400 3600 0 CET}
+ {-176342400 7200 1 CEST}
+ {-166060800 3600 0 CET}
+ {220921200 3600 0 CET}
+ {228873600 7200 1 CEST}
+ {243993600 3600 0 CET}
+ {260323200 7200 1 CEST}
+ {276048000 3600 0 CET}
+ {291772800 7200 1 CEST}
+ {307497600 3600 0 CET}
+ {323827200 7200 1 CEST}
+ {338947200 3600 0 CET}
+ {354672000 7200 1 CEST}
+ {370396800 3600 0 CET}
+ {386121600 7200 1 CEST}
+ {401846400 3600 0 CET}
+ {417571200 7200 1 CEST}
+ {433296000 3600 0 CET}
+ {449020800 7200 1 CEST}
+ {465350400 3600 0 CET}
+ {481075200 7200 1 CEST}
+ {496800000 3600 0 CET}
+ {512524800 7200 1 CEST}
+ {528249600 3600 0 CET}
+ {543974400 7200 1 CEST}
+ {559699200 3600 0 CET}
+ {567990000 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/Europe/Zagreb b/library/tzdata/Europe/Zagreb
new file mode 100644
index 0000000..46319a4
--- /dev/null
+++ b/library/tzdata/Europe/Zagreb
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/Belgrade)]} {
+ LoadTimeZoneFile Europe/Belgrade
+}
+set TZData(:Europe/Zagreb) $TZData(:Europe/Belgrade)
diff --git a/library/tzdata/Europe/Zaporozhye b/library/tzdata/Europe/Zaporozhye
new file mode 100644
index 0000000..01418cd
--- /dev/null
+++ b/library/tzdata/Europe/Zaporozhye
@@ -0,0 +1,252 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Zaporozhye) {
+ {-9223372036854775808 8440 0 LMT}
+ {-2840149240 8400 0 CUT}
+ {-1441160400 7200 0 EET}
+ {-1247536800 10800 0 MSK}
+ {-894769200 3600 0 CET}
+ {-857257200 3600 0 CET}
+ {-844556400 7200 1 CEST}
+ {-828226800 3600 0 CET}
+ {-826419600 10800 0 MSD}
+ {354920400 14400 1 MSD}
+ {370728000 10800 0 MSK}
+ {386456400 14400 1 MSD}
+ {402264000 10800 0 MSK}
+ {417992400 14400 1 MSD}
+ {433800000 10800 0 MSK}
+ {449614800 14400 1 MSD}
+ {465346800 10800 0 MSK}
+ {481071600 14400 1 MSD}
+ {496796400 10800 0 MSK}
+ {512521200 14400 1 MSD}
+ {528246000 10800 0 MSK}
+ {543970800 14400 1 MSD}
+ {559695600 10800 0 MSK}
+ {575420400 14400 1 MSD}
+ {591145200 10800 0 MSK}
+ {606870000 14400 1 MSD}
+ {622594800 10800 0 MSK}
+ {638319600 14400 1 MSD}
+ {654649200 10800 0 MSK}
+ {670374000 10800 0 EEST}
+ {686091600 7200 0 EET}
+ {701820000 10800 1 EEST}
+ {717541200 7200 0 EET}
+ {733269600 10800 1 EEST}
+ {748990800 7200 0 EET}
+ {764719200 10800 1 EEST}
+ {780440400 7200 0 EET}
+ {788911200 7200 0 EET}
+ {796179600 10800 1 EEST}
+ {811904400 7200 0 EET}
+ {828234000 10800 1 EEST}
+ {846378000 7200 0 EET}
+ {859683600 10800 1 EEST}
+ {877827600 7200 0 EET}
+ {891133200 10800 1 EEST}
+ {909277200 7200 0 EET}
+ {922582800 10800 1 EEST}
+ {941331600 7200 0 EET}
+ {954032400 10800 1 EEST}
+ {972781200 7200 0 EET}
+ {985482000 10800 1 EEST}
+ {1004230800 7200 0 EET}
+ {1017536400 10800 1 EEST}
+ {1035680400 7200 0 EET}
+ {1048986000 10800 1 EEST}
+ {1067130000 7200 0 EET}
+ {1080435600 10800 1 EEST}
+ {1099184400 7200 0 EET}
+ {1111885200 10800 1 EEST}
+ {1130634000 7200 0 EET}
+ {1143334800 10800 1 EEST}
+ {1162083600 7200 0 EET}
+ {1174784400 10800 1 EEST}
+ {1193533200 7200 0 EET}
+ {1206838800 10800 1 EEST}
+ {1224982800 7200 0 EET}
+ {1238288400 10800 1 EEST}
+ {1256432400 7200 0 EET}
+ {1269738000 10800 1 EEST}
+ {1288486800 7200 0 EET}
+ {1301187600 10800 1 EEST}
+ {1319936400 7200 0 EET}
+ {1332637200 10800 1 EEST}
+ {1351386000 7200 0 EET}
+ {1364691600 10800 1 EEST}
+ {1382835600 7200 0 EET}
+ {1396141200 10800 1 EEST}
+ {1414285200 7200 0 EET}
+ {1427590800 10800 1 EEST}
+ {1445734800 7200 0 EET}
+ {1459040400 10800 1 EEST}
+ {1477789200 7200 0 EET}
+ {1490490000 10800 1 EEST}
+ {1509238800 7200 0 EET}
+ {1521939600 10800 1 EEST}
+ {1540688400 7200 0 EET}
+ {1553994000 10800 1 EEST}
+ {1572138000 7200 0 EET}
+ {1585443600 10800 1 EEST}
+ {1603587600 7200 0 EET}
+ {1616893200 10800 1 EEST}
+ {1635642000 7200 0 EET}
+ {1648342800 10800 1 EEST}
+ {1667091600 7200 0 EET}
+ {1679792400 10800 1 EEST}
+ {1698541200 7200 0 EET}
+ {1711846800 10800 1 EEST}
+ {1729990800 7200 0 EET}
+ {1743296400 10800 1 EEST}
+ {1761440400 7200 0 EET}
+ {1774746000 10800 1 EEST}
+ {1792890000 7200 0 EET}
+ {1806195600 10800 1 EEST}
+ {1824944400 7200 0 EET}
+ {1837645200 10800 1 EEST}
+ {1856394000 7200 0 EET}
+ {1869094800 10800 1 EEST}
+ {1887843600 7200 0 EET}
+ {1901149200 10800 1 EEST}
+ {1919293200 7200 0 EET}
+ {1932598800 10800 1 EEST}
+ {1950742800 7200 0 EET}
+ {1964048400 10800 1 EEST}
+ {1982797200 7200 0 EET}
+ {1995498000 10800 1 EEST}
+ {2014246800 7200 0 EET}
+ {2026947600 10800 1 EEST}
+ {2045696400 7200 0 EET}
+ {2058397200 10800 1 EEST}
+ {2077146000 7200 0 EET}
+ {2090451600 10800 1 EEST}
+ {2108595600 7200 0 EET}
+ {2121901200 10800 1 EEST}
+ {2140045200 7200 0 EET}
+ {2153350800 10800 1 EEST}
+ {2172099600 7200 0 EET}
+ {2184800400 10800 1 EEST}
+ {2203549200 7200 0 EET}
+ {2216250000 10800 1 EEST}
+ {2234998800 7200 0 EET}
+ {2248304400 10800 1 EEST}
+ {2266448400 7200 0 EET}
+ {2279754000 10800 1 EEST}
+ {2297898000 7200 0 EET}
+ {2311203600 10800 1 EEST}
+ {2329347600 7200 0 EET}
+ {2342653200 10800 1 EEST}
+ {2361402000 7200 0 EET}
+ {2374102800 10800 1 EEST}
+ {2392851600 7200 0 EET}
+ {2405552400 10800 1 EEST}
+ {2424301200 7200 0 EET}
+ {2437606800 10800 1 EEST}
+ {2455750800 7200 0 EET}
+ {2469056400 10800 1 EEST}
+ {2487200400 7200 0 EET}
+ {2500506000 10800 1 EEST}
+ {2519254800 7200 0 EET}
+ {2531955600 10800 1 EEST}
+ {2550704400 7200 0 EET}
+ {2563405200 10800 1 EEST}
+ {2582154000 7200 0 EET}
+ {2595459600 10800 1 EEST}
+ {2613603600 7200 0 EET}
+ {2626909200 10800 1 EEST}
+ {2645053200 7200 0 EET}
+ {2658358800 10800 1 EEST}
+ {2676502800 7200 0 EET}
+ {2689808400 10800 1 EEST}
+ {2708557200 7200 0 EET}
+ {2721258000 10800 1 EEST}
+ {2740006800 7200 0 EET}
+ {2752707600 10800 1 EEST}
+ {2771456400 7200 0 EET}
+ {2784762000 10800 1 EEST}
+ {2802906000 7200 0 EET}
+ {2816211600 10800 1 EEST}
+ {2834355600 7200 0 EET}
+ {2847661200 10800 1 EEST}
+ {2866410000 7200 0 EET}
+ {2879110800 10800 1 EEST}
+ {2897859600 7200 0 EET}
+ {2910560400 10800 1 EEST}
+ {2929309200 7200 0 EET}
+ {2942010000 10800 1 EEST}
+ {2960758800 7200 0 EET}
+ {2974064400 10800 1 EEST}
+ {2992208400 7200 0 EET}
+ {3005514000 10800 1 EEST}
+ {3023658000 7200 0 EET}
+ {3036963600 10800 1 EEST}
+ {3055712400 7200 0 EET}
+ {3068413200 10800 1 EEST}
+ {3087162000 7200 0 EET}
+ {3099862800 10800 1 EEST}
+ {3118611600 7200 0 EET}
+ {3131917200 10800 1 EEST}
+ {3150061200 7200 0 EET}
+ {3163366800 10800 1 EEST}
+ {3181510800 7200 0 EET}
+ {3194816400 10800 1 EEST}
+ {3212960400 7200 0 EET}
+ {3226266000 10800 1 EEST}
+ {3245014800 7200 0 EET}
+ {3257715600 10800 1 EEST}
+ {3276464400 7200 0 EET}
+ {3289165200 10800 1 EEST}
+ {3307914000 7200 0 EET}
+ {3321219600 10800 1 EEST}
+ {3339363600 7200 0 EET}
+ {3352669200 10800 1 EEST}
+ {3370813200 7200 0 EET}
+ {3384118800 10800 1 EEST}
+ {3402867600 7200 0 EET}
+ {3415568400 10800 1 EEST}
+ {3434317200 7200 0 EET}
+ {3447018000 10800 1 EEST}
+ {3465766800 7200 0 EET}
+ {3479072400 10800 1 EEST}
+ {3497216400 7200 0 EET}
+ {3510522000 10800 1 EEST}
+ {3528666000 7200 0 EET}
+ {3541971600 10800 1 EEST}
+ {3560115600 7200 0 EET}
+ {3573421200 10800 1 EEST}
+ {3592170000 7200 0 EET}
+ {3604870800 10800 1 EEST}
+ {3623619600 7200 0 EET}
+ {3636320400 10800 1 EEST}
+ {3655069200 7200 0 EET}
+ {3668374800 10800 1 EEST}
+ {3686518800 7200 0 EET}
+ {3699824400 10800 1 EEST}
+ {3717968400 7200 0 EET}
+ {3731274000 10800 1 EEST}
+ {3750022800 7200 0 EET}
+ {3762723600 10800 1 EEST}
+ {3781472400 7200 0 EET}
+ {3794173200 10800 1 EEST}
+ {3812922000 7200 0 EET}
+ {3825622800 10800 1 EEST}
+ {3844371600 7200 0 EET}
+ {3857677200 10800 1 EEST}
+ {3875821200 7200 0 EET}
+ {3889126800 10800 1 EEST}
+ {3907270800 7200 0 EET}
+ {3920576400 10800 1 EEST}
+ {3939325200 7200 0 EET}
+ {3952026000 10800 1 EEST}
+ {3970774800 7200 0 EET}
+ {3983475600 10800 1 EEST}
+ {4002224400 7200 0 EET}
+ {4015530000 10800 1 EEST}
+ {4033674000 7200 0 EET}
+ {4046979600 10800 1 EEST}
+ {4065123600 7200 0 EET}
+ {4078429200 10800 1 EEST}
+ {4096573200 7200 0 EET}
+}
diff --git a/library/tzdata/Europe/Zurich b/library/tzdata/Europe/Zurich
new file mode 100644
index 0000000..33831c3
--- /dev/null
+++ b/library/tzdata/Europe/Zurich
@@ -0,0 +1,250 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Europe/Zurich) {
+ {-9223372036854775808 2048 0 LMT}
+ {-3827954048 1784 0 BMT}
+ {-2385246584 3600 0 CET}
+ {-904435200 7200 1 CEST}
+ {-891129600 3600 0 CET}
+ {-872985600 7200 1 CEST}
+ {-859680000 3600 0 CET}
+ {347151600 3600 0 CET}
+ {354675600 7200 1 CEST}
+ {370400400 3600 0 CET}
+ {386125200 7200 1 CEST}
+ {401850000 3600 0 CET}
+ {417574800 7200 1 CEST}
+ {433299600 3600 0 CET}
+ {449024400 7200 1 CEST}
+ {465354000 3600 0 CET}
+ {481078800 7200 1 CEST}
+ {496803600 3600 0 CET}
+ {512528400 7200 1 CEST}
+ {528253200 3600 0 CET}
+ {543978000 7200 1 CEST}
+ {559702800 3600 0 CET}
+ {575427600 7200 1 CEST}
+ {591152400 3600 0 CET}
+ {606877200 7200 1 CEST}
+ {622602000 3600 0 CET}
+ {638326800 7200 1 CEST}
+ {654656400 3600 0 CET}
+ {670381200 7200 1 CEST}
+ {686106000 3600 0 CET}
+ {701830800 7200 1 CEST}
+ {717555600 3600 0 CET}
+ {733280400 7200 1 CEST}
+ {749005200 3600 0 CET}
+ {764730000 7200 1 CEST}
+ {780454800 3600 0 CET}
+ {796179600 7200 1 CEST}
+ {811904400 3600 0 CET}
+ {828234000 7200 1 CEST}
+ {846378000 3600 0 CET}
+ {859683600 7200 1 CEST}
+ {877827600 3600 0 CET}
+ {891133200 7200 1 CEST}
+ {909277200 3600 0 CET}
+ {922582800 7200 1 CEST}
+ {941331600 3600 0 CET}
+ {954032400 7200 1 CEST}
+ {972781200 3600 0 CET}
+ {985482000 7200 1 CEST}
+ {1004230800 3600 0 CET}
+ {1017536400 7200 1 CEST}
+ {1035680400 3600 0 CET}
+ {1048986000 7200 1 CEST}
+ {1067130000 3600 0 CET}
+ {1080435600 7200 1 CEST}
+ {1099184400 3600 0 CET}
+ {1111885200 7200 1 CEST}
+ {1130634000 3600 0 CET}
+ {1143334800 7200 1 CEST}
+ {1162083600 3600 0 CET}
+ {1174784400 7200 1 CEST}
+ {1193533200 3600 0 CET}
+ {1206838800 7200 1 CEST}
+ {1224982800 3600 0 CET}
+ {1238288400 7200 1 CEST}
+ {1256432400 3600 0 CET}
+ {1269738000 7200 1 CEST}
+ {1288486800 3600 0 CET}
+ {1301187600 7200 1 CEST}
+ {1319936400 3600 0 CET}
+ {1332637200 7200 1 CEST}
+ {1351386000 3600 0 CET}
+ {1364691600 7200 1 CEST}
+ {1382835600 3600 0 CET}
+ {1396141200 7200 1 CEST}
+ {1414285200 3600 0 CET}
+ {1427590800 7200 1 CEST}
+ {1445734800 3600 0 CET}
+ {1459040400 7200 1 CEST}
+ {1477789200 3600 0 CET}
+ {1490490000 7200 1 CEST}
+ {1509238800 3600 0 CET}
+ {1521939600 7200 1 CEST}
+ {1540688400 3600 0 CET}
+ {1553994000 7200 1 CEST}
+ {1572138000 3600 0 CET}
+ {1585443600 7200 1 CEST}
+ {1603587600 3600 0 CET}
+ {1616893200 7200 1 CEST}
+ {1635642000 3600 0 CET}
+ {1648342800 7200 1 CEST}
+ {1667091600 3600 0 CET}
+ {1679792400 7200 1 CEST}
+ {1698541200 3600 0 CET}
+ {1711846800 7200 1 CEST}
+ {1729990800 3600 0 CET}
+ {1743296400 7200 1 CEST}
+ {1761440400 3600 0 CET}
+ {1774746000 7200 1 CEST}
+ {1792890000 3600 0 CET}
+ {1806195600 7200 1 CEST}
+ {1824944400 3600 0 CET}
+ {1837645200 7200 1 CEST}
+ {1856394000 3600 0 CET}
+ {1869094800 7200 1 CEST}
+ {1887843600 3600 0 CET}
+ {1901149200 7200 1 CEST}
+ {1919293200 3600 0 CET}
+ {1932598800 7200 1 CEST}
+ {1950742800 3600 0 CET}
+ {1964048400 7200 1 CEST}
+ {1982797200 3600 0 CET}
+ {1995498000 7200 1 CEST}
+ {2014246800 3600 0 CET}
+ {2026947600 7200 1 CEST}
+ {2045696400 3600 0 CET}
+ {2058397200 7200 1 CEST}
+ {2077146000 3600 0 CET}
+ {2090451600 7200 1 CEST}
+ {2108595600 3600 0 CET}
+ {2121901200 7200 1 CEST}
+ {2140045200 3600 0 CET}
+ {2153350800 7200 1 CEST}
+ {2172099600 3600 0 CET}
+ {2184800400 7200 1 CEST}
+ {2203549200 3600 0 CET}
+ {2216250000 7200 1 CEST}
+ {2234998800 3600 0 CET}
+ {2248304400 7200 1 CEST}
+ {2266448400 3600 0 CET}
+ {2279754000 7200 1 CEST}
+ {2297898000 3600 0 CET}
+ {2311203600 7200 1 CEST}
+ {2329347600 3600 0 CET}
+ {2342653200 7200 1 CEST}
+ {2361402000 3600 0 CET}
+ {2374102800 7200 1 CEST}
+ {2392851600 3600 0 CET}
+ {2405552400 7200 1 CEST}
+ {2424301200 3600 0 CET}
+ {2437606800 7200 1 CEST}
+ {2455750800 3600 0 CET}
+ {2469056400 7200 1 CEST}
+ {2487200400 3600 0 CET}
+ {2500506000 7200 1 CEST}
+ {2519254800 3600 0 CET}
+ {2531955600 7200 1 CEST}
+ {2550704400 3600 0 CET}
+ {2563405200 7200 1 CEST}
+ {2582154000 3600 0 CET}
+ {2595459600 7200 1 CEST}
+ {2613603600 3600 0 CET}
+ {2626909200 7200 1 CEST}
+ {2645053200 3600 0 CET}
+ {2658358800 7200 1 CEST}
+ {2676502800 3600 0 CET}
+ {2689808400 7200 1 CEST}
+ {2708557200 3600 0 CET}
+ {2721258000 7200 1 CEST}
+ {2740006800 3600 0 CET}
+ {2752707600 7200 1 CEST}
+ {2771456400 3600 0 CET}
+ {2784762000 7200 1 CEST}
+ {2802906000 3600 0 CET}
+ {2816211600 7200 1 CEST}
+ {2834355600 3600 0 CET}
+ {2847661200 7200 1 CEST}
+ {2866410000 3600 0 CET}
+ {2879110800 7200 1 CEST}
+ {2897859600 3600 0 CET}
+ {2910560400 7200 1 CEST}
+ {2929309200 3600 0 CET}
+ {2942010000 7200 1 CEST}
+ {2960758800 3600 0 CET}
+ {2974064400 7200 1 CEST}
+ {2992208400 3600 0 CET}
+ {3005514000 7200 1 CEST}
+ {3023658000 3600 0 CET}
+ {3036963600 7200 1 CEST}
+ {3055712400 3600 0 CET}
+ {3068413200 7200 1 CEST}
+ {3087162000 3600 0 CET}
+ {3099862800 7200 1 CEST}
+ {3118611600 3600 0 CET}
+ {3131917200 7200 1 CEST}
+ {3150061200 3600 0 CET}
+ {3163366800 7200 1 CEST}
+ {3181510800 3600 0 CET}
+ {3194816400 7200 1 CEST}
+ {3212960400 3600 0 CET}
+ {3226266000 7200 1 CEST}
+ {3245014800 3600 0 CET}
+ {3257715600 7200 1 CEST}
+ {3276464400 3600 0 CET}
+ {3289165200 7200 1 CEST}
+ {3307914000 3600 0 CET}
+ {3321219600 7200 1 CEST}
+ {3339363600 3600 0 CET}
+ {3352669200 7200 1 CEST}
+ {3370813200 3600 0 CET}
+ {3384118800 7200 1 CEST}
+ {3402867600 3600 0 CET}
+ {3415568400 7200 1 CEST}
+ {3434317200 3600 0 CET}
+ {3447018000 7200 1 CEST}
+ {3465766800 3600 0 CET}
+ {3479072400 7200 1 CEST}
+ {3497216400 3600 0 CET}
+ {3510522000 7200 1 CEST}
+ {3528666000 3600 0 CET}
+ {3541971600 7200 1 CEST}
+ {3560115600 3600 0 CET}
+ {3573421200 7200 1 CEST}
+ {3592170000 3600 0 CET}
+ {3604870800 7200 1 CEST}
+ {3623619600 3600 0 CET}
+ {3636320400 7200 1 CEST}
+ {3655069200 3600 0 CET}
+ {3668374800 7200 1 CEST}
+ {3686518800 3600 0 CET}
+ {3699824400 7200 1 CEST}
+ {3717968400 3600 0 CET}
+ {3731274000 7200 1 CEST}
+ {3750022800 3600 0 CET}
+ {3762723600 7200 1 CEST}
+ {3781472400 3600 0 CET}
+ {3794173200 7200 1 CEST}
+ {3812922000 3600 0 CET}
+ {3825622800 7200 1 CEST}
+ {3844371600 3600 0 CET}
+ {3857677200 7200 1 CEST}
+ {3875821200 3600 0 CET}
+ {3889126800 7200 1 CEST}
+ {3907270800 3600 0 CET}
+ {3920576400 7200 1 CEST}
+ {3939325200 3600 0 CET}
+ {3952026000 7200 1 CEST}
+ {3970774800 3600 0 CET}
+ {3983475600 7200 1 CEST}
+ {4002224400 3600 0 CET}
+ {4015530000 7200 1 CEST}
+ {4033674000 3600 0 CET}
+ {4046979600 7200 1 CEST}
+ {4065123600 3600 0 CET}
+ {4078429200 7200 1 CEST}
+ {4096573200 3600 0 CET}
+}
diff --git a/library/tzdata/GB b/library/tzdata/GB
new file mode 100644
index 0000000..72d77ee
--- /dev/null
+++ b/library/tzdata/GB
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/London)]} {
+ LoadTimeZoneFile Europe/London
+}
+set TZData(:GB) $TZData(:Europe/London)
diff --git a/library/tzdata/GB-Eire b/library/tzdata/GB-Eire
new file mode 100644
index 0000000..1622417
--- /dev/null
+++ b/library/tzdata/GB-Eire
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/London)]} {
+ LoadTimeZoneFile Europe/London
+}
+set TZData(:GB-Eire) $TZData(:Europe/London)
diff --git a/library/tzdata/GMT b/library/tzdata/GMT
new file mode 100644
index 0000000..4258564
--- /dev/null
+++ b/library/tzdata/GMT
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Etc/GMT)]} {
+ LoadTimeZoneFile Etc/GMT
+}
+set TZData(:GMT) $TZData(:Etc/GMT)
diff --git a/library/tzdata/GMT+0 b/library/tzdata/GMT+0
new file mode 100644
index 0000000..a1e8126
--- /dev/null
+++ b/library/tzdata/GMT+0
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Etc/GMT)]} {
+ LoadTimeZoneFile Etc/GMT
+}
+set TZData(:GMT+0) $TZData(:Etc/GMT)
diff --git a/library/tzdata/GMT-0 b/library/tzdata/GMT-0
new file mode 100644
index 0000000..04ccafe
--- /dev/null
+++ b/library/tzdata/GMT-0
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Etc/GMT)]} {
+ LoadTimeZoneFile Etc/GMT
+}
+set TZData(:GMT-0) $TZData(:Etc/GMT)
diff --git a/library/tzdata/GMT0 b/library/tzdata/GMT0
new file mode 100644
index 0000000..92e95a3
--- /dev/null
+++ b/library/tzdata/GMT0
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Etc/GMT)]} {
+ LoadTimeZoneFile Etc/GMT
+}
+set TZData(:GMT0) $TZData(:Etc/GMT)
diff --git a/library/tzdata/Greenwich b/library/tzdata/Greenwich
new file mode 100644
index 0000000..6115233
--- /dev/null
+++ b/library/tzdata/Greenwich
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Etc/GMT)]} {
+ LoadTimeZoneFile Etc/GMT
+}
+set TZData(:Greenwich) $TZData(:Etc/GMT)
diff --git a/library/tzdata/HST b/library/tzdata/HST
new file mode 100644
index 0000000..fea7f14
--- /dev/null
+++ b/library/tzdata/HST
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:HST) {
+ {-9223372036854775808 -36000 0 HST}
+}
diff --git a/library/tzdata/Hongkong b/library/tzdata/Hongkong
new file mode 100644
index 0000000..f9d4dac
--- /dev/null
+++ b/library/tzdata/Hongkong
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Asia/Hong_Kong)]} {
+ LoadTimeZoneFile Asia/Hong_Kong
+}
+set TZData(:Hongkong) $TZData(:Asia/Hong_Kong)
diff --git a/library/tzdata/Iceland b/library/tzdata/Iceland
new file mode 100644
index 0000000..eb3f3eb
--- /dev/null
+++ b/library/tzdata/Iceland
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Atlantic/Reykjavik)]} {
+ LoadTimeZoneFile Atlantic/Reykjavik
+}
+set TZData(:Iceland) $TZData(:Atlantic/Reykjavik)
diff --git a/library/tzdata/Indian/Antananarivo b/library/tzdata/Indian/Antananarivo
new file mode 100644
index 0000000..217715e
--- /dev/null
+++ b/library/tzdata/Indian/Antananarivo
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Indian/Antananarivo) {
+ {-9223372036854775808 11404 0 LMT}
+ {-1846293004 10800 0 EAT}
+ {-499924800 14400 1 EAST}
+ {-492062400 10800 0 EAT}
+}
diff --git a/library/tzdata/Indian/Chagos b/library/tzdata/Indian/Chagos
new file mode 100644
index 0000000..a5cec61
--- /dev/null
+++ b/library/tzdata/Indian/Chagos
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Indian/Chagos) {
+ {-9223372036854775808 17380 0 LMT}
+ {-1988167780 18000 0 IOT}
+ {820436400 21600 0 IOT}
+}
diff --git a/library/tzdata/Indian/Christmas b/library/tzdata/Indian/Christmas
new file mode 100644
index 0000000..c36e973
--- /dev/null
+++ b/library/tzdata/Indian/Christmas
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Indian/Christmas) {
+ {-9223372036854775808 25372 0 LMT}
+ {-2364102172 25200 0 CXT}
+}
diff --git a/library/tzdata/Indian/Cocos b/library/tzdata/Indian/Cocos
new file mode 100644
index 0000000..a63ae68
--- /dev/null
+++ b/library/tzdata/Indian/Cocos
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Indian/Cocos) {
+ {-9223372036854775808 23260 0 LMT}
+ {-2209012060 23400 0 CCT}
+}
diff --git a/library/tzdata/Indian/Comoro b/library/tzdata/Indian/Comoro
new file mode 100644
index 0000000..0b3c33a
--- /dev/null
+++ b/library/tzdata/Indian/Comoro
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Indian/Comoro) {
+ {-9223372036854775808 10384 0 LMT}
+ {-1846291984 10800 0 EAT}
+}
diff --git a/library/tzdata/Indian/Kerguelen b/library/tzdata/Indian/Kerguelen
new file mode 100644
index 0000000..b41b85a
--- /dev/null
+++ b/library/tzdata/Indian/Kerguelen
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Indian/Kerguelen) {
+ {-9223372036854775808 0 0 zzz}
+ {-631152000 18000 0 TFT}
+}
diff --git a/library/tzdata/Indian/Mahe b/library/tzdata/Indian/Mahe
new file mode 100644
index 0000000..c88a24b
--- /dev/null
+++ b/library/tzdata/Indian/Mahe
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Indian/Mahe) {
+ {-9223372036854775808 13308 0 LMT}
+ {-2006653308 14400 0 SCT}
+}
diff --git a/library/tzdata/Indian/Maldives b/library/tzdata/Indian/Maldives
new file mode 100644
index 0000000..2c2c739
--- /dev/null
+++ b/library/tzdata/Indian/Maldives
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Indian/Maldives) {
+ {-9223372036854775808 17640 0 LMT}
+ {-2840158440 17640 0 MMT}
+ {-315636840 18000 0 MVT}
+}
diff --git a/library/tzdata/Indian/Mauritius b/library/tzdata/Indian/Mauritius
new file mode 100644
index 0000000..a9c07eb
--- /dev/null
+++ b/library/tzdata/Indian/Mauritius
@@ -0,0 +1,10 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Indian/Mauritius) {
+ {-9223372036854775808 13800 0 LMT}
+ {-1988164200 14400 0 MUT}
+ {403041600 18000 1 MUST}
+ {417034800 14400 0 MUT}
+ {1224972000 18000 1 MUST}
+ {1238274000 14400 0 MUT}
+}
diff --git a/library/tzdata/Indian/Mayotte b/library/tzdata/Indian/Mayotte
new file mode 100644
index 0000000..0fe5f56
--- /dev/null
+++ b/library/tzdata/Indian/Mayotte
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Indian/Mayotte) {
+ {-9223372036854775808 10856 0 LMT}
+ {-1846292456 10800 0 EAT}
+}
diff --git a/library/tzdata/Indian/Reunion b/library/tzdata/Indian/Reunion
new file mode 100644
index 0000000..de2dd60
--- /dev/null
+++ b/library/tzdata/Indian/Reunion
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Indian/Reunion) {
+ {-9223372036854775808 13312 0 LMT}
+ {-1848886912 14400 0 RET}
+}
diff --git a/library/tzdata/Iran b/library/tzdata/Iran
new file mode 100644
index 0000000..e200b4d
--- /dev/null
+++ b/library/tzdata/Iran
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Asia/Tehran)]} {
+ LoadTimeZoneFile Asia/Tehran
+}
+set TZData(:Iran) $TZData(:Asia/Tehran)
diff --git a/library/tzdata/Israel b/library/tzdata/Israel
new file mode 100644
index 0000000..af521f5
--- /dev/null
+++ b/library/tzdata/Israel
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Asia/Jerusalem)]} {
+ LoadTimeZoneFile Asia/Jerusalem
+}
+set TZData(:Israel) $TZData(:Asia/Jerusalem)
diff --git a/library/tzdata/Jamaica b/library/tzdata/Jamaica
new file mode 100644
index 0000000..ddb5d45
--- /dev/null
+++ b/library/tzdata/Jamaica
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Jamaica)]} {
+ LoadTimeZoneFile America/Jamaica
+}
+set TZData(:Jamaica) $TZData(:America/Jamaica)
diff --git a/library/tzdata/Japan b/library/tzdata/Japan
new file mode 100644
index 0000000..428a79f
--- /dev/null
+++ b/library/tzdata/Japan
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Asia/Tokyo)]} {
+ LoadTimeZoneFile Asia/Tokyo
+}
+set TZData(:Japan) $TZData(:Asia/Tokyo)
diff --git a/library/tzdata/Kwajalein b/library/tzdata/Kwajalein
new file mode 100644
index 0000000..586db6d
--- /dev/null
+++ b/library/tzdata/Kwajalein
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Pacific/Kwajalein)]} {
+ LoadTimeZoneFile Pacific/Kwajalein
+}
+set TZData(:Kwajalein) $TZData(:Pacific/Kwajalein)
diff --git a/library/tzdata/Libya b/library/tzdata/Libya
new file mode 100644
index 0000000..6cd77e1
--- /dev/null
+++ b/library/tzdata/Libya
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Africa/Tripoli)]} {
+ LoadTimeZoneFile Africa/Tripoli
+}
+set TZData(:Libya) $TZData(:Africa/Tripoli)
diff --git a/library/tzdata/MET b/library/tzdata/MET
new file mode 100644
index 0000000..8789c97
--- /dev/null
+++ b/library/tzdata/MET
@@ -0,0 +1,265 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:MET) {
+ {-9223372036854775808 3600 0 MET}
+ {-1693706400 7200 1 MEST}
+ {-1680483600 3600 0 MET}
+ {-1663455600 7200 1 MEST}
+ {-1650150000 3600 0 MET}
+ {-1632006000 7200 1 MEST}
+ {-1618700400 3600 0 MET}
+ {-938905200 7200 1 MEST}
+ {-857257200 3600 0 MET}
+ {-844556400 7200 1 MEST}
+ {-828226800 3600 0 MET}
+ {-812502000 7200 1 MEST}
+ {-796777200 3600 0 MET}
+ {-781052400 7200 1 MEST}
+ {-766623600 3600 0 MET}
+ {228877200 7200 1 MEST}
+ {243997200 3600 0 MET}
+ {260326800 7200 1 MEST}
+ {276051600 3600 0 MET}
+ {291776400 7200 1 MEST}
+ {307501200 3600 0 MET}
+ {323830800 7200 1 MEST}
+ {338950800 3600 0 MET}
+ {354675600 7200 1 MEST}
+ {370400400 3600 0 MET}
+ {386125200 7200 1 MEST}
+ {401850000 3600 0 MET}
+ {417574800 7200 1 MEST}
+ {433299600 3600 0 MET}
+ {449024400 7200 1 MEST}
+ {465354000 3600 0 MET}
+ {481078800 7200 1 MEST}
+ {496803600 3600 0 MET}
+ {512528400 7200 1 MEST}
+ {528253200 3600 0 MET}
+ {543978000 7200 1 MEST}
+ {559702800 3600 0 MET}
+ {575427600 7200 1 MEST}
+ {591152400 3600 0 MET}
+ {606877200 7200 1 MEST}
+ {622602000 3600 0 MET}
+ {638326800 7200 1 MEST}
+ {654656400 3600 0 MET}
+ {670381200 7200 1 MEST}
+ {686106000 3600 0 MET}
+ {701830800 7200 1 MEST}
+ {717555600 3600 0 MET}
+ {733280400 7200 1 MEST}
+ {749005200 3600 0 MET}
+ {764730000 7200 1 MEST}
+ {780454800 3600 0 MET}
+ {796179600 7200 1 MEST}
+ {811904400 3600 0 MET}
+ {828234000 7200 1 MEST}
+ {846378000 3600 0 MET}
+ {859683600 7200 1 MEST}
+ {877827600 3600 0 MET}
+ {891133200 7200 1 MEST}
+ {909277200 3600 0 MET}
+ {922582800 7200 1 MEST}
+ {941331600 3600 0 MET}
+ {954032400 7200 1 MEST}
+ {972781200 3600 0 MET}
+ {985482000 7200 1 MEST}
+ {1004230800 3600 0 MET}
+ {1017536400 7200 1 MEST}
+ {1035680400 3600 0 MET}
+ {1048986000 7200 1 MEST}
+ {1067130000 3600 0 MET}
+ {1080435600 7200 1 MEST}
+ {1099184400 3600 0 MET}
+ {1111885200 7200 1 MEST}
+ {1130634000 3600 0 MET}
+ {1143334800 7200 1 MEST}
+ {1162083600 3600 0 MET}
+ {1174784400 7200 1 MEST}
+ {1193533200 3600 0 MET}
+ {1206838800 7200 1 MEST}
+ {1224982800 3600 0 MET}
+ {1238288400 7200 1 MEST}
+ {1256432400 3600 0 MET}
+ {1269738000 7200 1 MEST}
+ {1288486800 3600 0 MET}
+ {1301187600 7200 1 MEST}
+ {1319936400 3600 0 MET}
+ {1332637200 7200 1 MEST}
+ {1351386000 3600 0 MET}
+ {1364691600 7200 1 MEST}
+ {1382835600 3600 0 MET}
+ {1396141200 7200 1 MEST}
+ {1414285200 3600 0 MET}
+ {1427590800 7200 1 MEST}
+ {1445734800 3600 0 MET}
+ {1459040400 7200 1 MEST}
+ {1477789200 3600 0 MET}
+ {1490490000 7200 1 MEST}
+ {1509238800 3600 0 MET}
+ {1521939600 7200 1 MEST}
+ {1540688400 3600 0 MET}
+ {1553994000 7200 1 MEST}
+ {1572138000 3600 0 MET}
+ {1585443600 7200 1 MEST}
+ {1603587600 3600 0 MET}
+ {1616893200 7200 1 MEST}
+ {1635642000 3600 0 MET}
+ {1648342800 7200 1 MEST}
+ {1667091600 3600 0 MET}
+ {1679792400 7200 1 MEST}
+ {1698541200 3600 0 MET}
+ {1711846800 7200 1 MEST}
+ {1729990800 3600 0 MET}
+ {1743296400 7200 1 MEST}
+ {1761440400 3600 0 MET}
+ {1774746000 7200 1 MEST}
+ {1792890000 3600 0 MET}
+ {1806195600 7200 1 MEST}
+ {1824944400 3600 0 MET}
+ {1837645200 7200 1 MEST}
+ {1856394000 3600 0 MET}
+ {1869094800 7200 1 MEST}
+ {1887843600 3600 0 MET}
+ {1901149200 7200 1 MEST}
+ {1919293200 3600 0 MET}
+ {1932598800 7200 1 MEST}
+ {1950742800 3600 0 MET}
+ {1964048400 7200 1 MEST}
+ {1982797200 3600 0 MET}
+ {1995498000 7200 1 MEST}
+ {2014246800 3600 0 MET}
+ {2026947600 7200 1 MEST}
+ {2045696400 3600 0 MET}
+ {2058397200 7200 1 MEST}
+ {2077146000 3600 0 MET}
+ {2090451600 7200 1 MEST}
+ {2108595600 3600 0 MET}
+ {2121901200 7200 1 MEST}
+ {2140045200 3600 0 MET}
+ {2153350800 7200 1 MEST}
+ {2172099600 3600 0 MET}
+ {2184800400 7200 1 MEST}
+ {2203549200 3600 0 MET}
+ {2216250000 7200 1 MEST}
+ {2234998800 3600 0 MET}
+ {2248304400 7200 1 MEST}
+ {2266448400 3600 0 MET}
+ {2279754000 7200 1 MEST}
+ {2297898000 3600 0 MET}
+ {2311203600 7200 1 MEST}
+ {2329347600 3600 0 MET}
+ {2342653200 7200 1 MEST}
+ {2361402000 3600 0 MET}
+ {2374102800 7200 1 MEST}
+ {2392851600 3600 0 MET}
+ {2405552400 7200 1 MEST}
+ {2424301200 3600 0 MET}
+ {2437606800 7200 1 MEST}
+ {2455750800 3600 0 MET}
+ {2469056400 7200 1 MEST}
+ {2487200400 3600 0 MET}
+ {2500506000 7200 1 MEST}
+ {2519254800 3600 0 MET}
+ {2531955600 7200 1 MEST}
+ {2550704400 3600 0 MET}
+ {2563405200 7200 1 MEST}
+ {2582154000 3600 0 MET}
+ {2595459600 7200 1 MEST}
+ {2613603600 3600 0 MET}
+ {2626909200 7200 1 MEST}
+ {2645053200 3600 0 MET}
+ {2658358800 7200 1 MEST}
+ {2676502800 3600 0 MET}
+ {2689808400 7200 1 MEST}
+ {2708557200 3600 0 MET}
+ {2721258000 7200 1 MEST}
+ {2740006800 3600 0 MET}
+ {2752707600 7200 1 MEST}
+ {2771456400 3600 0 MET}
+ {2784762000 7200 1 MEST}
+ {2802906000 3600 0 MET}
+ {2816211600 7200 1 MEST}
+ {2834355600 3600 0 MET}
+ {2847661200 7200 1 MEST}
+ {2866410000 3600 0 MET}
+ {2879110800 7200 1 MEST}
+ {2897859600 3600 0 MET}
+ {2910560400 7200 1 MEST}
+ {2929309200 3600 0 MET}
+ {2942010000 7200 1 MEST}
+ {2960758800 3600 0 MET}
+ {2974064400 7200 1 MEST}
+ {2992208400 3600 0 MET}
+ {3005514000 7200 1 MEST}
+ {3023658000 3600 0 MET}
+ {3036963600 7200 1 MEST}
+ {3055712400 3600 0 MET}
+ {3068413200 7200 1 MEST}
+ {3087162000 3600 0 MET}
+ {3099862800 7200 1 MEST}
+ {3118611600 3600 0 MET}
+ {3131917200 7200 1 MEST}
+ {3150061200 3600 0 MET}
+ {3163366800 7200 1 MEST}
+ {3181510800 3600 0 MET}
+ {3194816400 7200 1 MEST}
+ {3212960400 3600 0 MET}
+ {3226266000 7200 1 MEST}
+ {3245014800 3600 0 MET}
+ {3257715600 7200 1 MEST}
+ {3276464400 3600 0 MET}
+ {3289165200 7200 1 MEST}
+ {3307914000 3600 0 MET}
+ {3321219600 7200 1 MEST}
+ {3339363600 3600 0 MET}
+ {3352669200 7200 1 MEST}
+ {3370813200 3600 0 MET}
+ {3384118800 7200 1 MEST}
+ {3402867600 3600 0 MET}
+ {3415568400 7200 1 MEST}
+ {3434317200 3600 0 MET}
+ {3447018000 7200 1 MEST}
+ {3465766800 3600 0 MET}
+ {3479072400 7200 1 MEST}
+ {3497216400 3600 0 MET}
+ {3510522000 7200 1 MEST}
+ {3528666000 3600 0 MET}
+ {3541971600 7200 1 MEST}
+ {3560115600 3600 0 MET}
+ {3573421200 7200 1 MEST}
+ {3592170000 3600 0 MET}
+ {3604870800 7200 1 MEST}
+ {3623619600 3600 0 MET}
+ {3636320400 7200 1 MEST}
+ {3655069200 3600 0 MET}
+ {3668374800 7200 1 MEST}
+ {3686518800 3600 0 MET}
+ {3699824400 7200 1 MEST}
+ {3717968400 3600 0 MET}
+ {3731274000 7200 1 MEST}
+ {3750022800 3600 0 MET}
+ {3762723600 7200 1 MEST}
+ {3781472400 3600 0 MET}
+ {3794173200 7200 1 MEST}
+ {3812922000 3600 0 MET}
+ {3825622800 7200 1 MEST}
+ {3844371600 3600 0 MET}
+ {3857677200 7200 1 MEST}
+ {3875821200 3600 0 MET}
+ {3889126800 7200 1 MEST}
+ {3907270800 3600 0 MET}
+ {3920576400 7200 1 MEST}
+ {3939325200 3600 0 MET}
+ {3952026000 7200 1 MEST}
+ {3970774800 3600 0 MET}
+ {3983475600 7200 1 MEST}
+ {4002224400 3600 0 MET}
+ {4015530000 7200 1 MEST}
+ {4033674000 3600 0 MET}
+ {4046979600 7200 1 MEST}
+ {4065123600 3600 0 MET}
+ {4078429200 7200 1 MEST}
+ {4096573200 3600 0 MET}
+}
diff --git a/library/tzdata/MST b/library/tzdata/MST
new file mode 100644
index 0000000..8c967ab
--- /dev/null
+++ b/library/tzdata/MST
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:MST) {
+ {-9223372036854775808 -25200 0 MST}
+}
diff --git a/library/tzdata/MST7MDT b/library/tzdata/MST7MDT
new file mode 100644
index 0000000..ff52048
--- /dev/null
+++ b/library/tzdata/MST7MDT
@@ -0,0 +1,278 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:MST7MDT) {
+ {-9223372036854775808 -25200 0 MST}
+ {-1633273200 -21600 1 MDT}
+ {-1615132800 -25200 0 MST}
+ {-1601823600 -21600 1 MDT}
+ {-1583683200 -25200 0 MST}
+ {-880210800 -21600 1 MWT}
+ {-769395600 -21600 1 MPT}
+ {-765388800 -25200 0 MST}
+ {-84380400 -21600 1 MDT}
+ {-68659200 -25200 0 MST}
+ {-52930800 -21600 1 MDT}
+ {-37209600 -25200 0 MST}
+ {-21481200 -21600 1 MDT}
+ {-5760000 -25200 0 MST}
+ {9968400 -21600 1 MDT}
+ {25689600 -25200 0 MST}
+ {41418000 -21600 1 MDT}
+ {57744000 -25200 0 MST}
+ {73472400 -21600 1 MDT}
+ {89193600 -25200 0 MST}
+ {104922000 -21600 1 MDT}
+ {120643200 -25200 0 MST}
+ {126694800 -21600 1 MDT}
+ {152092800 -25200 0 MST}
+ {162378000 -21600 1 MDT}
+ {183542400 -25200 0 MST}
+ {199270800 -21600 1 MDT}
+ {215596800 -25200 0 MST}
+ {230720400 -21600 1 MDT}
+ {247046400 -25200 0 MST}
+ {262774800 -21600 1 MDT}
+ {278496000 -25200 0 MST}
+ {294224400 -21600 1 MDT}
+ {309945600 -25200 0 MST}
+ {325674000 -21600 1 MDT}
+ {341395200 -25200 0 MST}
+ {357123600 -21600 1 MDT}
+ {372844800 -25200 0 MST}
+ {388573200 -21600 1 MDT}
+ {404899200 -25200 0 MST}
+ {420022800 -21600 1 MDT}
+ {436348800 -25200 0 MST}
+ {452077200 -21600 1 MDT}
+ {467798400 -25200 0 MST}
+ {483526800 -21600 1 MDT}
+ {499248000 -25200 0 MST}
+ {514976400 -21600 1 MDT}
+ {530697600 -25200 0 MST}
+ {544611600 -21600 1 MDT}
+ {562147200 -25200 0 MST}
+ {576061200 -21600 1 MDT}
+ {594201600 -25200 0 MST}
+ {607510800 -21600 1 MDT}
+ {625651200 -25200 0 MST}
+ {638960400 -21600 1 MDT}
+ {657100800 -25200 0 MST}
+ {671014800 -21600 1 MDT}
+ {688550400 -25200 0 MST}
+ {702464400 -21600 1 MDT}
+ {720000000 -25200 0 MST}
+ {733914000 -21600 1 MDT}
+ {752054400 -25200 0 MST}
+ {765363600 -21600 1 MDT}
+ {783504000 -25200 0 MST}
+ {796813200 -21600 1 MDT}
+ {814953600 -25200 0 MST}
+ {828867600 -21600 1 MDT}
+ {846403200 -25200 0 MST}
+ {860317200 -21600 1 MDT}
+ {877852800 -25200 0 MST}
+ {891766800 -21600 1 MDT}
+ {909302400 -25200 0 MST}
+ {923216400 -21600 1 MDT}
+ {941356800 -25200 0 MST}
+ {954666000 -21600 1 MDT}
+ {972806400 -25200 0 MST}
+ {986115600 -21600 1 MDT}
+ {1004256000 -25200 0 MST}
+ {1018170000 -21600 1 MDT}
+ {1035705600 -25200 0 MST}
+ {1049619600 -21600 1 MDT}
+ {1067155200 -25200 0 MST}
+ {1081069200 -21600 1 MDT}
+ {1099209600 -25200 0 MST}
+ {1112518800 -21600 1 MDT}
+ {1130659200 -25200 0 MST}
+ {1143968400 -21600 1 MDT}
+ {1162108800 -25200 0 MST}
+ {1173603600 -21600 1 MDT}
+ {1194163200 -25200 0 MST}
+ {1205053200 -21600 1 MDT}
+ {1225612800 -25200 0 MST}
+ {1236502800 -21600 1 MDT}
+ {1257062400 -25200 0 MST}
+ {1268557200 -21600 1 MDT}
+ {1289116800 -25200 0 MST}
+ {1300006800 -21600 1 MDT}
+ {1320566400 -25200 0 MST}
+ {1331456400 -21600 1 MDT}
+ {1352016000 -25200 0 MST}
+ {1362906000 -21600 1 MDT}
+ {1383465600 -25200 0 MST}
+ {1394355600 -21600 1 MDT}
+ {1414915200 -25200 0 MST}
+ {1425805200 -21600 1 MDT}
+ {1446364800 -25200 0 MST}
+ {1457859600 -21600 1 MDT}
+ {1478419200 -25200 0 MST}
+ {1489309200 -21600 1 MDT}
+ {1509868800 -25200 0 MST}
+ {1520758800 -21600 1 MDT}
+ {1541318400 -25200 0 MST}
+ {1552208400 -21600 1 MDT}
+ {1572768000 -25200 0 MST}
+ {1583658000 -21600 1 MDT}
+ {1604217600 -25200 0 MST}
+ {1615712400 -21600 1 MDT}
+ {1636272000 -25200 0 MST}
+ {1647162000 -21600 1 MDT}
+ {1667721600 -25200 0 MST}
+ {1678611600 -21600 1 MDT}
+ {1699171200 -25200 0 MST}
+ {1710061200 -21600 1 MDT}
+ {1730620800 -25200 0 MST}
+ {1741510800 -21600 1 MDT}
+ {1762070400 -25200 0 MST}
+ {1772960400 -21600 1 MDT}
+ {1793520000 -25200 0 MST}
+ {1805014800 -21600 1 MDT}
+ {1825574400 -25200 0 MST}
+ {1836464400 -21600 1 MDT}
+ {1857024000 -25200 0 MST}
+ {1867914000 -21600 1 MDT}
+ {1888473600 -25200 0 MST}
+ {1899363600 -21600 1 MDT}
+ {1919923200 -25200 0 MST}
+ {1930813200 -21600 1 MDT}
+ {1951372800 -25200 0 MST}
+ {1962867600 -21600 1 MDT}
+ {1983427200 -25200 0 MST}
+ {1994317200 -21600 1 MDT}
+ {2014876800 -25200 0 MST}
+ {2025766800 -21600 1 MDT}
+ {2046326400 -25200 0 MST}
+ {2057216400 -21600 1 MDT}
+ {2077776000 -25200 0 MST}
+ {2088666000 -21600 1 MDT}
+ {2109225600 -25200 0 MST}
+ {2120115600 -21600 1 MDT}
+ {2140675200 -25200 0 MST}
+ {2152170000 -21600 1 MDT}
+ {2172729600 -25200 0 MST}
+ {2183619600 -21600 1 MDT}
+ {2204179200 -25200 0 MST}
+ {2215069200 -21600 1 MDT}
+ {2235628800 -25200 0 MST}
+ {2246518800 -21600 1 MDT}
+ {2267078400 -25200 0 MST}
+ {2277968400 -21600 1 MDT}
+ {2298528000 -25200 0 MST}
+ {2309418000 -21600 1 MDT}
+ {2329977600 -25200 0 MST}
+ {2341472400 -21600 1 MDT}
+ {2362032000 -25200 0 MST}
+ {2372922000 -21600 1 MDT}
+ {2393481600 -25200 0 MST}
+ {2404371600 -21600 1 MDT}
+ {2424931200 -25200 0 MST}
+ {2435821200 -21600 1 MDT}
+ {2456380800 -25200 0 MST}
+ {2467270800 -21600 1 MDT}
+ {2487830400 -25200 0 MST}
+ {2499325200 -21600 1 MDT}
+ {2519884800 -25200 0 MST}
+ {2530774800 -21600 1 MDT}
+ {2551334400 -25200 0 MST}
+ {2562224400 -21600 1 MDT}
+ {2582784000 -25200 0 MST}
+ {2593674000 -21600 1 MDT}
+ {2614233600 -25200 0 MST}
+ {2625123600 -21600 1 MDT}
+ {2645683200 -25200 0 MST}
+ {2656573200 -21600 1 MDT}
+ {2677132800 -25200 0 MST}
+ {2688627600 -21600 1 MDT}
+ {2709187200 -25200 0 MST}
+ {2720077200 -21600 1 MDT}
+ {2740636800 -25200 0 MST}
+ {2751526800 -21600 1 MDT}
+ {2772086400 -25200 0 MST}
+ {2782976400 -21600 1 MDT}
+ {2803536000 -25200 0 MST}
+ {2814426000 -21600 1 MDT}
+ {2834985600 -25200 0 MST}
+ {2846480400 -21600 1 MDT}
+ {2867040000 -25200 0 MST}
+ {2877930000 -21600 1 MDT}
+ {2898489600 -25200 0 MST}
+ {2909379600 -21600 1 MDT}
+ {2929939200 -25200 0 MST}
+ {2940829200 -21600 1 MDT}
+ {2961388800 -25200 0 MST}
+ {2972278800 -21600 1 MDT}
+ {2992838400 -25200 0 MST}
+ {3003728400 -21600 1 MDT}
+ {3024288000 -25200 0 MST}
+ {3035782800 -21600 1 MDT}
+ {3056342400 -25200 0 MST}
+ {3067232400 -21600 1 MDT}
+ {3087792000 -25200 0 MST}
+ {3098682000 -21600 1 MDT}
+ {3119241600 -25200 0 MST}
+ {3130131600 -21600 1 MDT}
+ {3150691200 -25200 0 MST}
+ {3161581200 -21600 1 MDT}
+ {3182140800 -25200 0 MST}
+ {3193030800 -21600 1 MDT}
+ {3213590400 -25200 0 MST}
+ {3225085200 -21600 1 MDT}
+ {3245644800 -25200 0 MST}
+ {3256534800 -21600 1 MDT}
+ {3277094400 -25200 0 MST}
+ {3287984400 -21600 1 MDT}
+ {3308544000 -25200 0 MST}
+ {3319434000 -21600 1 MDT}
+ {3339993600 -25200 0 MST}
+ {3350883600 -21600 1 MDT}
+ {3371443200 -25200 0 MST}
+ {3382938000 -21600 1 MDT}
+ {3403497600 -25200 0 MST}
+ {3414387600 -21600 1 MDT}
+ {3434947200 -25200 0 MST}
+ {3445837200 -21600 1 MDT}
+ {3466396800 -25200 0 MST}
+ {3477286800 -21600 1 MDT}
+ {3497846400 -25200 0 MST}
+ {3508736400 -21600 1 MDT}
+ {3529296000 -25200 0 MST}
+ {3540186000 -21600 1 MDT}
+ {3560745600 -25200 0 MST}
+ {3572240400 -21600 1 MDT}
+ {3592800000 -25200 0 MST}
+ {3603690000 -21600 1 MDT}
+ {3624249600 -25200 0 MST}
+ {3635139600 -21600 1 MDT}
+ {3655699200 -25200 0 MST}
+ {3666589200 -21600 1 MDT}
+ {3687148800 -25200 0 MST}
+ {3698038800 -21600 1 MDT}
+ {3718598400 -25200 0 MST}
+ {3730093200 -21600 1 MDT}
+ {3750652800 -25200 0 MST}
+ {3761542800 -21600 1 MDT}
+ {3782102400 -25200 0 MST}
+ {3792992400 -21600 1 MDT}
+ {3813552000 -25200 0 MST}
+ {3824442000 -21600 1 MDT}
+ {3845001600 -25200 0 MST}
+ {3855891600 -21600 1 MDT}
+ {3876451200 -25200 0 MST}
+ {3887341200 -21600 1 MDT}
+ {3907900800 -25200 0 MST}
+ {3919395600 -21600 1 MDT}
+ {3939955200 -25200 0 MST}
+ {3950845200 -21600 1 MDT}
+ {3971404800 -25200 0 MST}
+ {3982294800 -21600 1 MDT}
+ {4002854400 -25200 0 MST}
+ {4013744400 -21600 1 MDT}
+ {4034304000 -25200 0 MST}
+ {4045194000 -21600 1 MDT}
+ {4065753600 -25200 0 MST}
+ {4076643600 -21600 1 MDT}
+ {4097203200 -25200 0 MST}
+}
diff --git a/library/tzdata/Mexico/BajaNorte b/library/tzdata/Mexico/BajaNorte
new file mode 100644
index 0000000..8f6f459
--- /dev/null
+++ b/library/tzdata/Mexico/BajaNorte
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Tijuana)]} {
+ LoadTimeZoneFile America/Tijuana
+}
+set TZData(:Mexico/BajaNorte) $TZData(:America/Tijuana)
diff --git a/library/tzdata/Mexico/BajaSur b/library/tzdata/Mexico/BajaSur
new file mode 100644
index 0000000..6d335a1
--- /dev/null
+++ b/library/tzdata/Mexico/BajaSur
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Mazatlan)]} {
+ LoadTimeZoneFile America/Mazatlan
+}
+set TZData(:Mexico/BajaSur) $TZData(:America/Mazatlan)
diff --git a/library/tzdata/Mexico/General b/library/tzdata/Mexico/General
new file mode 100644
index 0000000..0cac92f
--- /dev/null
+++ b/library/tzdata/Mexico/General
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Mexico_City)]} {
+ LoadTimeZoneFile America/Mexico_City
+}
+set TZData(:Mexico/General) $TZData(:America/Mexico_City)
diff --git a/library/tzdata/NZ b/library/tzdata/NZ
new file mode 100644
index 0000000..36d22a7
--- /dev/null
+++ b/library/tzdata/NZ
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Pacific/Auckland)]} {
+ LoadTimeZoneFile Pacific/Auckland
+}
+set TZData(:NZ) $TZData(:Pacific/Auckland)
diff --git a/library/tzdata/NZ-CHAT b/library/tzdata/NZ-CHAT
new file mode 100644
index 0000000..7f7c918
--- /dev/null
+++ b/library/tzdata/NZ-CHAT
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Pacific/Chatham)]} {
+ LoadTimeZoneFile Pacific/Chatham
+}
+set TZData(:NZ-CHAT) $TZData(:Pacific/Chatham)
diff --git a/library/tzdata/Navajo b/library/tzdata/Navajo
new file mode 100644
index 0000000..78cc2e2
--- /dev/null
+++ b/library/tzdata/Navajo
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Denver)]} {
+ LoadTimeZoneFile America/Denver
+}
+set TZData(:Navajo) $TZData(:America/Denver)
diff --git a/library/tzdata/PRC b/library/tzdata/PRC
new file mode 100644
index 0000000..1d8bb7c
--- /dev/null
+++ b/library/tzdata/PRC
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Asia/Shanghai)]} {
+ LoadTimeZoneFile Asia/Shanghai
+}
+set TZData(:PRC) $TZData(:Asia/Shanghai)
diff --git a/library/tzdata/PST8PDT b/library/tzdata/PST8PDT
new file mode 100644
index 0000000..87a94da
--- /dev/null
+++ b/library/tzdata/PST8PDT
@@ -0,0 +1,278 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:PST8PDT) {
+ {-9223372036854775808 -28800 0 PST}
+ {-1633269600 -25200 1 PDT}
+ {-1615129200 -28800 0 PST}
+ {-1601820000 -25200 1 PDT}
+ {-1583679600 -28800 0 PST}
+ {-880207200 -25200 1 PWT}
+ {-769395600 -25200 1 PPT}
+ {-765385200 -28800 0 PST}
+ {-84376800 -25200 1 PDT}
+ {-68655600 -28800 0 PST}
+ {-52927200 -25200 1 PDT}
+ {-37206000 -28800 0 PST}
+ {-21477600 -25200 1 PDT}
+ {-5756400 -28800 0 PST}
+ {9972000 -25200 1 PDT}
+ {25693200 -28800 0 PST}
+ {41421600 -25200 1 PDT}
+ {57747600 -28800 0 PST}
+ {73476000 -25200 1 PDT}
+ {89197200 -28800 0 PST}
+ {104925600 -25200 1 PDT}
+ {120646800 -28800 0 PST}
+ {126698400 -25200 1 PDT}
+ {152096400 -28800 0 PST}
+ {162381600 -25200 1 PDT}
+ {183546000 -28800 0 PST}
+ {199274400 -25200 1 PDT}
+ {215600400 -28800 0 PST}
+ {230724000 -25200 1 PDT}
+ {247050000 -28800 0 PST}
+ {262778400 -25200 1 PDT}
+ {278499600 -28800 0 PST}
+ {294228000 -25200 1 PDT}
+ {309949200 -28800 0 PST}
+ {325677600 -25200 1 PDT}
+ {341398800 -28800 0 PST}
+ {357127200 -25200 1 PDT}
+ {372848400 -28800 0 PST}
+ {388576800 -25200 1 PDT}
+ {404902800 -28800 0 PST}
+ {420026400 -25200 1 PDT}
+ {436352400 -28800 0 PST}
+ {452080800 -25200 1 PDT}
+ {467802000 -28800 0 PST}
+ {483530400 -25200 1 PDT}
+ {499251600 -28800 0 PST}
+ {514980000 -25200 1 PDT}
+ {530701200 -28800 0 PST}
+ {544615200 -25200 1 PDT}
+ {562150800 -28800 0 PST}
+ {576064800 -25200 1 PDT}
+ {594205200 -28800 0 PST}
+ {607514400 -25200 1 PDT}
+ {625654800 -28800 0 PST}
+ {638964000 -25200 1 PDT}
+ {657104400 -28800 0 PST}
+ {671018400 -25200 1 PDT}
+ {688554000 -28800 0 PST}
+ {702468000 -25200 1 PDT}
+ {720003600 -28800 0 PST}
+ {733917600 -25200 1 PDT}
+ {752058000 -28800 0 PST}
+ {765367200 -25200 1 PDT}
+ {783507600 -28800 0 PST}
+ {796816800 -25200 1 PDT}
+ {814957200 -28800 0 PST}
+ {828871200 -25200 1 PDT}
+ {846406800 -28800 0 PST}
+ {860320800 -25200 1 PDT}
+ {877856400 -28800 0 PST}
+ {891770400 -25200 1 PDT}
+ {909306000 -28800 0 PST}
+ {923220000 -25200 1 PDT}
+ {941360400 -28800 0 PST}
+ {954669600 -25200 1 PDT}
+ {972810000 -28800 0 PST}
+ {986119200 -25200 1 PDT}
+ {1004259600 -28800 0 PST}
+ {1018173600 -25200 1 PDT}
+ {1035709200 -28800 0 PST}
+ {1049623200 -25200 1 PDT}
+ {1067158800 -28800 0 PST}
+ {1081072800 -25200 1 PDT}
+ {1099213200 -28800 0 PST}
+ {1112522400 -25200 1 PDT}
+ {1130662800 -28800 0 PST}
+ {1143972000 -25200 1 PDT}
+ {1162112400 -28800 0 PST}
+ {1173607200 -25200 1 PDT}
+ {1194166800 -28800 0 PST}
+ {1205056800 -25200 1 PDT}
+ {1225616400 -28800 0 PST}
+ {1236506400 -25200 1 PDT}
+ {1257066000 -28800 0 PST}
+ {1268560800 -25200 1 PDT}
+ {1289120400 -28800 0 PST}
+ {1300010400 -25200 1 PDT}
+ {1320570000 -28800 0 PST}
+ {1331460000 -25200 1 PDT}
+ {1352019600 -28800 0 PST}
+ {1362909600 -25200 1 PDT}
+ {1383469200 -28800 0 PST}
+ {1394359200 -25200 1 PDT}
+ {1414918800 -28800 0 PST}
+ {1425808800 -25200 1 PDT}
+ {1446368400 -28800 0 PST}
+ {1457863200 -25200 1 PDT}
+ {1478422800 -28800 0 PST}
+ {1489312800 -25200 1 PDT}
+ {1509872400 -28800 0 PST}
+ {1520762400 -25200 1 PDT}
+ {1541322000 -28800 0 PST}
+ {1552212000 -25200 1 PDT}
+ {1572771600 -28800 0 PST}
+ {1583661600 -25200 1 PDT}
+ {1604221200 -28800 0 PST}
+ {1615716000 -25200 1 PDT}
+ {1636275600 -28800 0 PST}
+ {1647165600 -25200 1 PDT}
+ {1667725200 -28800 0 PST}
+ {1678615200 -25200 1 PDT}
+ {1699174800 -28800 0 PST}
+ {1710064800 -25200 1 PDT}
+ {1730624400 -28800 0 PST}
+ {1741514400 -25200 1 PDT}
+ {1762074000 -28800 0 PST}
+ {1772964000 -25200 1 PDT}
+ {1793523600 -28800 0 PST}
+ {1805018400 -25200 1 PDT}
+ {1825578000 -28800 0 PST}
+ {1836468000 -25200 1 PDT}
+ {1857027600 -28800 0 PST}
+ {1867917600 -25200 1 PDT}
+ {1888477200 -28800 0 PST}
+ {1899367200 -25200 1 PDT}
+ {1919926800 -28800 0 PST}
+ {1930816800 -25200 1 PDT}
+ {1951376400 -28800 0 PST}
+ {1962871200 -25200 1 PDT}
+ {1983430800 -28800 0 PST}
+ {1994320800 -25200 1 PDT}
+ {2014880400 -28800 0 PST}
+ {2025770400 -25200 1 PDT}
+ {2046330000 -28800 0 PST}
+ {2057220000 -25200 1 PDT}
+ {2077779600 -28800 0 PST}
+ {2088669600 -25200 1 PDT}
+ {2109229200 -28800 0 PST}
+ {2120119200 -25200 1 PDT}
+ {2140678800 -28800 0 PST}
+ {2152173600 -25200 1 PDT}
+ {2172733200 -28800 0 PST}
+ {2183623200 -25200 1 PDT}
+ {2204182800 -28800 0 PST}
+ {2215072800 -25200 1 PDT}
+ {2235632400 -28800 0 PST}
+ {2246522400 -25200 1 PDT}
+ {2267082000 -28800 0 PST}
+ {2277972000 -25200 1 PDT}
+ {2298531600 -28800 0 PST}
+ {2309421600 -25200 1 PDT}
+ {2329981200 -28800 0 PST}
+ {2341476000 -25200 1 PDT}
+ {2362035600 -28800 0 PST}
+ {2372925600 -25200 1 PDT}
+ {2393485200 -28800 0 PST}
+ {2404375200 -25200 1 PDT}
+ {2424934800 -28800 0 PST}
+ {2435824800 -25200 1 PDT}
+ {2456384400 -28800 0 PST}
+ {2467274400 -25200 1 PDT}
+ {2487834000 -28800 0 PST}
+ {2499328800 -25200 1 PDT}
+ {2519888400 -28800 0 PST}
+ {2530778400 -25200 1 PDT}
+ {2551338000 -28800 0 PST}
+ {2562228000 -25200 1 PDT}
+ {2582787600 -28800 0 PST}
+ {2593677600 -25200 1 PDT}
+ {2614237200 -28800 0 PST}
+ {2625127200 -25200 1 PDT}
+ {2645686800 -28800 0 PST}
+ {2656576800 -25200 1 PDT}
+ {2677136400 -28800 0 PST}
+ {2688631200 -25200 1 PDT}
+ {2709190800 -28800 0 PST}
+ {2720080800 -25200 1 PDT}
+ {2740640400 -28800 0 PST}
+ {2751530400 -25200 1 PDT}
+ {2772090000 -28800 0 PST}
+ {2782980000 -25200 1 PDT}
+ {2803539600 -28800 0 PST}
+ {2814429600 -25200 1 PDT}
+ {2834989200 -28800 0 PST}
+ {2846484000 -25200 1 PDT}
+ {2867043600 -28800 0 PST}
+ {2877933600 -25200 1 PDT}
+ {2898493200 -28800 0 PST}
+ {2909383200 -25200 1 PDT}
+ {2929942800 -28800 0 PST}
+ {2940832800 -25200 1 PDT}
+ {2961392400 -28800 0 PST}
+ {2972282400 -25200 1 PDT}
+ {2992842000 -28800 0 PST}
+ {3003732000 -25200 1 PDT}
+ {3024291600 -28800 0 PST}
+ {3035786400 -25200 1 PDT}
+ {3056346000 -28800 0 PST}
+ {3067236000 -25200 1 PDT}
+ {3087795600 -28800 0 PST}
+ {3098685600 -25200 1 PDT}
+ {3119245200 -28800 0 PST}
+ {3130135200 -25200 1 PDT}
+ {3150694800 -28800 0 PST}
+ {3161584800 -25200 1 PDT}
+ {3182144400 -28800 0 PST}
+ {3193034400 -25200 1 PDT}
+ {3213594000 -28800 0 PST}
+ {3225088800 -25200 1 PDT}
+ {3245648400 -28800 0 PST}
+ {3256538400 -25200 1 PDT}
+ {3277098000 -28800 0 PST}
+ {3287988000 -25200 1 PDT}
+ {3308547600 -28800 0 PST}
+ {3319437600 -25200 1 PDT}
+ {3339997200 -28800 0 PST}
+ {3350887200 -25200 1 PDT}
+ {3371446800 -28800 0 PST}
+ {3382941600 -25200 1 PDT}
+ {3403501200 -28800 0 PST}
+ {3414391200 -25200 1 PDT}
+ {3434950800 -28800 0 PST}
+ {3445840800 -25200 1 PDT}
+ {3466400400 -28800 0 PST}
+ {3477290400 -25200 1 PDT}
+ {3497850000 -28800 0 PST}
+ {3508740000 -25200 1 PDT}
+ {3529299600 -28800 0 PST}
+ {3540189600 -25200 1 PDT}
+ {3560749200 -28800 0 PST}
+ {3572244000 -25200 1 PDT}
+ {3592803600 -28800 0 PST}
+ {3603693600 -25200 1 PDT}
+ {3624253200 -28800 0 PST}
+ {3635143200 -25200 1 PDT}
+ {3655702800 -28800 0 PST}
+ {3666592800 -25200 1 PDT}
+ {3687152400 -28800 0 PST}
+ {3698042400 -25200 1 PDT}
+ {3718602000 -28800 0 PST}
+ {3730096800 -25200 1 PDT}
+ {3750656400 -28800 0 PST}
+ {3761546400 -25200 1 PDT}
+ {3782106000 -28800 0 PST}
+ {3792996000 -25200 1 PDT}
+ {3813555600 -28800 0 PST}
+ {3824445600 -25200 1 PDT}
+ {3845005200 -28800 0 PST}
+ {3855895200 -25200 1 PDT}
+ {3876454800 -28800 0 PST}
+ {3887344800 -25200 1 PDT}
+ {3907904400 -28800 0 PST}
+ {3919399200 -25200 1 PDT}
+ {3939958800 -28800 0 PST}
+ {3950848800 -25200 1 PDT}
+ {3971408400 -28800 0 PST}
+ {3982298400 -25200 1 PDT}
+ {4002858000 -28800 0 PST}
+ {4013748000 -25200 1 PDT}
+ {4034307600 -28800 0 PST}
+ {4045197600 -25200 1 PDT}
+ {4065757200 -28800 0 PST}
+ {4076647200 -25200 1 PDT}
+ {4097206800 -28800 0 PST}
+}
diff --git a/library/tzdata/Pacific/Apia b/library/tzdata/Pacific/Apia
new file mode 100644
index 0000000..25b047d
--- /dev/null
+++ b/library/tzdata/Pacific/Apia
@@ -0,0 +1,10 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Apia) {
+ {-9223372036854775808 45184 0 LMT}
+ {-2855737984 -41216 0 LMT}
+ {-1861878784 -41400 0 SAMT}
+ {-631110600 -39600 0 WST}
+ {1285498800 -36000 1 WSDT}
+ {1301752800 -39600 0 WST}
+}
diff --git a/library/tzdata/Pacific/Auckland b/library/tzdata/Pacific/Auckland
new file mode 100644
index 0000000..5f7e238
--- /dev/null
+++ b/library/tzdata/Pacific/Auckland
@@ -0,0 +1,285 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Auckland) {
+ {-9223372036854775808 41944 0 LMT}
+ {-3192435544 41400 0 NZMT}
+ {-1330335000 45000 1 NZST}
+ {-1320057000 41400 0 NZMT}
+ {-1300699800 43200 1 NZST}
+ {-1287396000 41400 0 NZMT}
+ {-1269250200 43200 1 NZST}
+ {-1255946400 41400 0 NZMT}
+ {-1237800600 43200 1 NZST}
+ {-1224496800 41400 0 NZMT}
+ {-1206351000 43200 1 NZST}
+ {-1192442400 41400 0 NZMT}
+ {-1174901400 43200 1 NZST}
+ {-1160992800 41400 0 NZMT}
+ {-1143451800 43200 1 NZST}
+ {-1125914400 41400 0 NZMT}
+ {-1112607000 43200 1 NZST}
+ {-1094464800 41400 0 NZMT}
+ {-1081157400 43200 1 NZST}
+ {-1063015200 41400 0 NZMT}
+ {-1049707800 43200 1 NZST}
+ {-1031565600 41400 0 NZMT}
+ {-1018258200 43200 1 NZST}
+ {-1000116000 41400 0 NZMT}
+ {-986808600 43200 1 NZST}
+ {-968061600 41400 0 NZMT}
+ {-955359000 43200 1 NZST}
+ {-936612000 41400 0 NZMT}
+ {-923304600 43200 1 NZST}
+ {-757425600 43200 0 NZST}
+ {152632800 46800 1 NZDT}
+ {162309600 43200 0 NZST}
+ {183477600 46800 1 NZDT}
+ {194968800 43200 0 NZST}
+ {215532000 46800 1 NZDT}
+ {226418400 43200 0 NZST}
+ {246981600 46800 1 NZDT}
+ {257868000 43200 0 NZST}
+ {278431200 46800 1 NZDT}
+ {289317600 43200 0 NZST}
+ {309880800 46800 1 NZDT}
+ {320767200 43200 0 NZST}
+ {341330400 46800 1 NZDT}
+ {352216800 43200 0 NZST}
+ {372780000 46800 1 NZDT}
+ {384271200 43200 0 NZST}
+ {404834400 46800 1 NZDT}
+ {415720800 43200 0 NZST}
+ {436284000 46800 1 NZDT}
+ {447170400 43200 0 NZST}
+ {467733600 46800 1 NZDT}
+ {478620000 43200 0 NZST}
+ {499183200 46800 1 NZDT}
+ {510069600 43200 0 NZST}
+ {530632800 46800 1 NZDT}
+ {541519200 43200 0 NZST}
+ {562082400 46800 1 NZDT}
+ {573573600 43200 0 NZST}
+ {594136800 46800 1 NZDT}
+ {605023200 43200 0 NZST}
+ {623772000 46800 1 NZDT}
+ {637682400 43200 0 NZST}
+ {655221600 46800 1 NZDT}
+ {669132000 43200 0 NZST}
+ {686671200 46800 1 NZDT}
+ {700581600 43200 0 NZST}
+ {718120800 46800 1 NZDT}
+ {732636000 43200 0 NZST}
+ {749570400 46800 1 NZDT}
+ {764085600 43200 0 NZST}
+ {781020000 46800 1 NZDT}
+ {795535200 43200 0 NZST}
+ {812469600 46800 1 NZDT}
+ {826984800 43200 0 NZST}
+ {844524000 46800 1 NZDT}
+ {858434400 43200 0 NZST}
+ {875973600 46800 1 NZDT}
+ {889884000 43200 0 NZST}
+ {907423200 46800 1 NZDT}
+ {921938400 43200 0 NZST}
+ {938872800 46800 1 NZDT}
+ {953388000 43200 0 NZST}
+ {970322400 46800 1 NZDT}
+ {984837600 43200 0 NZST}
+ {1002376800 46800 1 NZDT}
+ {1016287200 43200 0 NZST}
+ {1033826400 46800 1 NZDT}
+ {1047736800 43200 0 NZST}
+ {1065276000 46800 1 NZDT}
+ {1079791200 43200 0 NZST}
+ {1096725600 46800 1 NZDT}
+ {1111240800 43200 0 NZST}
+ {1128175200 46800 1 NZDT}
+ {1142690400 43200 0 NZST}
+ {1159624800 46800 1 NZDT}
+ {1174140000 43200 0 NZST}
+ {1191074400 46800 1 NZDT}
+ {1207404000 43200 0 NZST}
+ {1222524000 46800 1 NZDT}
+ {1238853600 43200 0 NZST}
+ {1253973600 46800 1 NZDT}
+ {1270303200 43200 0 NZST}
+ {1285423200 46800 1 NZDT}
+ {1301752800 43200 0 NZST}
+ {1316872800 46800 1 NZDT}
+ {1333202400 43200 0 NZST}
+ {1348927200 46800 1 NZDT}
+ {1365256800 43200 0 NZST}
+ {1380376800 46800 1 NZDT}
+ {1396706400 43200 0 NZST}
+ {1411826400 46800 1 NZDT}
+ {1428156000 43200 0 NZST}
+ {1443276000 46800 1 NZDT}
+ {1459605600 43200 0 NZST}
+ {1474725600 46800 1 NZDT}
+ {1491055200 43200 0 NZST}
+ {1506175200 46800 1 NZDT}
+ {1522504800 43200 0 NZST}
+ {1538229600 46800 1 NZDT}
+ {1554559200 43200 0 NZST}
+ {1569679200 46800 1 NZDT}
+ {1586008800 43200 0 NZST}
+ {1601128800 46800 1 NZDT}
+ {1617458400 43200 0 NZST}
+ {1632578400 46800 1 NZDT}
+ {1648908000 43200 0 NZST}
+ {1664028000 46800 1 NZDT}
+ {1680357600 43200 0 NZST}
+ {1695477600 46800 1 NZDT}
+ {1712412000 43200 0 NZST}
+ {1727532000 46800 1 NZDT}
+ {1743861600 43200 0 NZST}
+ {1758981600 46800 1 NZDT}
+ {1775311200 43200 0 NZST}
+ {1790431200 46800 1 NZDT}
+ {1806760800 43200 0 NZST}
+ {1821880800 46800 1 NZDT}
+ {1838210400 43200 0 NZST}
+ {1853330400 46800 1 NZDT}
+ {1869660000 43200 0 NZST}
+ {1885384800 46800 1 NZDT}
+ {1901714400 43200 0 NZST}
+ {1916834400 46800 1 NZDT}
+ {1933164000 43200 0 NZST}
+ {1948284000 46800 1 NZDT}
+ {1964613600 43200 0 NZST}
+ {1979733600 46800 1 NZDT}
+ {1996063200 43200 0 NZST}
+ {2011183200 46800 1 NZDT}
+ {2027512800 43200 0 NZST}
+ {2042632800 46800 1 NZDT}
+ {2058962400 43200 0 NZST}
+ {2074687200 46800 1 NZDT}
+ {2091016800 43200 0 NZST}
+ {2106136800 46800 1 NZDT}
+ {2122466400 43200 0 NZST}
+ {2137586400 46800 1 NZDT}
+ {2153916000 43200 0 NZST}
+ {2169036000 46800 1 NZDT}
+ {2185365600 43200 0 NZST}
+ {2200485600 46800 1 NZDT}
+ {2216815200 43200 0 NZST}
+ {2232540000 46800 1 NZDT}
+ {2248869600 43200 0 NZST}
+ {2263989600 46800 1 NZDT}
+ {2280319200 43200 0 NZST}
+ {2295439200 46800 1 NZDT}
+ {2311768800 43200 0 NZST}
+ {2326888800 46800 1 NZDT}
+ {2343218400 43200 0 NZST}
+ {2358338400 46800 1 NZDT}
+ {2374668000 43200 0 NZST}
+ {2389788000 46800 1 NZDT}
+ {2406117600 43200 0 NZST}
+ {2421842400 46800 1 NZDT}
+ {2438172000 43200 0 NZST}
+ {2453292000 46800 1 NZDT}
+ {2469621600 43200 0 NZST}
+ {2484741600 46800 1 NZDT}
+ {2501071200 43200 0 NZST}
+ {2516191200 46800 1 NZDT}
+ {2532520800 43200 0 NZST}
+ {2547640800 46800 1 NZDT}
+ {2563970400 43200 0 NZST}
+ {2579090400 46800 1 NZDT}
+ {2596024800 43200 0 NZST}
+ {2611144800 46800 1 NZDT}
+ {2627474400 43200 0 NZST}
+ {2642594400 46800 1 NZDT}
+ {2658924000 43200 0 NZST}
+ {2674044000 46800 1 NZDT}
+ {2690373600 43200 0 NZST}
+ {2705493600 46800 1 NZDT}
+ {2721823200 43200 0 NZST}
+ {2736943200 46800 1 NZDT}
+ {2753272800 43200 0 NZST}
+ {2768997600 46800 1 NZDT}
+ {2785327200 43200 0 NZST}
+ {2800447200 46800 1 NZDT}
+ {2816776800 43200 0 NZST}
+ {2831896800 46800 1 NZDT}
+ {2848226400 43200 0 NZST}
+ {2863346400 46800 1 NZDT}
+ {2879676000 43200 0 NZST}
+ {2894796000 46800 1 NZDT}
+ {2911125600 43200 0 NZST}
+ {2926245600 46800 1 NZDT}
+ {2942575200 43200 0 NZST}
+ {2958300000 46800 1 NZDT}
+ {2974629600 43200 0 NZST}
+ {2989749600 46800 1 NZDT}
+ {3006079200 43200 0 NZST}
+ {3021199200 46800 1 NZDT}
+ {3037528800 43200 0 NZST}
+ {3052648800 46800 1 NZDT}
+ {3068978400 43200 0 NZST}
+ {3084098400 46800 1 NZDT}
+ {3100428000 43200 0 NZST}
+ {3116152800 46800 1 NZDT}
+ {3132482400 43200 0 NZST}
+ {3147602400 46800 1 NZDT}
+ {3163932000 43200 0 NZST}
+ {3179052000 46800 1 NZDT}
+ {3195381600 43200 0 NZST}
+ {3210501600 46800 1 NZDT}
+ {3226831200 43200 0 NZST}
+ {3241951200 46800 1 NZDT}
+ {3258280800 43200 0 NZST}
+ {3273400800 46800 1 NZDT}
+ {3289730400 43200 0 NZST}
+ {3305455200 46800 1 NZDT}
+ {3321784800 43200 0 NZST}
+ {3336904800 46800 1 NZDT}
+ {3353234400 43200 0 NZST}
+ {3368354400 46800 1 NZDT}
+ {3384684000 43200 0 NZST}
+ {3399804000 46800 1 NZDT}
+ {3416133600 43200 0 NZST}
+ {3431253600 46800 1 NZDT}
+ {3447583200 43200 0 NZST}
+ {3462703200 46800 1 NZDT}
+ {3479637600 43200 0 NZST}
+ {3494757600 46800 1 NZDT}
+ {3511087200 43200 0 NZST}
+ {3526207200 46800 1 NZDT}
+ {3542536800 43200 0 NZST}
+ {3557656800 46800 1 NZDT}
+ {3573986400 43200 0 NZST}
+ {3589106400 46800 1 NZDT}
+ {3605436000 43200 0 NZST}
+ {3620556000 46800 1 NZDT}
+ {3636885600 43200 0 NZST}
+ {3652610400 46800 1 NZDT}
+ {3668940000 43200 0 NZST}
+ {3684060000 46800 1 NZDT}
+ {3700389600 43200 0 NZST}
+ {3715509600 46800 1 NZDT}
+ {3731839200 43200 0 NZST}
+ {3746959200 46800 1 NZDT}
+ {3763288800 43200 0 NZST}
+ {3778408800 46800 1 NZDT}
+ {3794738400 43200 0 NZST}
+ {3809858400 46800 1 NZDT}
+ {3826188000 43200 0 NZST}
+ {3841912800 46800 1 NZDT}
+ {3858242400 43200 0 NZST}
+ {3873362400 46800 1 NZDT}
+ {3889692000 43200 0 NZST}
+ {3904812000 46800 1 NZDT}
+ {3921141600 43200 0 NZST}
+ {3936261600 46800 1 NZDT}
+ {3952591200 43200 0 NZST}
+ {3967711200 46800 1 NZDT}
+ {3984040800 43200 0 NZST}
+ {3999765600 46800 1 NZDT}
+ {4016095200 43200 0 NZST}
+ {4031215200 46800 1 NZDT}
+ {4047544800 43200 0 NZST}
+ {4062664800 46800 1 NZDT}
+ {4078994400 43200 0 NZST}
+ {4094114400 46800 1 NZDT}
+}
diff --git a/library/tzdata/Pacific/Chatham b/library/tzdata/Pacific/Chatham
new file mode 100644
index 0000000..0ed2260
--- /dev/null
+++ b/library/tzdata/Pacific/Chatham
@@ -0,0 +1,257 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Chatham) {
+ {-9223372036854775808 44028 0 LMT}
+ {-410271228 45900 0 CHAST}
+ {152632800 49500 1 CHADT}
+ {162309600 45900 0 CHAST}
+ {183477600 49500 1 CHADT}
+ {194968800 45900 0 CHAST}
+ {215532000 49500 1 CHADT}
+ {226418400 45900 0 CHAST}
+ {246981600 49500 1 CHADT}
+ {257868000 45900 0 CHAST}
+ {278431200 49500 1 CHADT}
+ {289317600 45900 0 CHAST}
+ {309880800 49500 1 CHADT}
+ {320767200 45900 0 CHAST}
+ {341330400 49500 1 CHADT}
+ {352216800 45900 0 CHAST}
+ {372780000 49500 1 CHADT}
+ {384271200 45900 0 CHAST}
+ {404834400 49500 1 CHADT}
+ {415720800 45900 0 CHAST}
+ {436284000 49500 1 CHADT}
+ {447170400 45900 0 CHAST}
+ {467733600 49500 1 CHADT}
+ {478620000 45900 0 CHAST}
+ {499183200 49500 1 CHADT}
+ {510069600 45900 0 CHAST}
+ {530632800 49500 1 CHADT}
+ {541519200 45900 0 CHAST}
+ {562082400 49500 1 CHADT}
+ {573573600 45900 0 CHAST}
+ {594136800 49500 1 CHADT}
+ {605023200 45900 0 CHAST}
+ {623772000 49500 1 CHADT}
+ {637682400 45900 0 CHAST}
+ {655221600 49500 1 CHADT}
+ {669132000 45900 0 CHAST}
+ {686671200 49500 1 CHADT}
+ {700581600 45900 0 CHAST}
+ {718120800 49500 1 CHADT}
+ {732636000 45900 0 CHAST}
+ {749570400 49500 1 CHADT}
+ {764085600 45900 0 CHAST}
+ {781020000 49500 1 CHADT}
+ {795535200 45900 0 CHAST}
+ {812469600 49500 1 CHADT}
+ {826984800 45900 0 CHAST}
+ {844524000 49500 1 CHADT}
+ {858434400 45900 0 CHAST}
+ {875973600 49500 1 CHADT}
+ {889884000 45900 0 CHAST}
+ {907423200 49500 1 CHADT}
+ {921938400 45900 0 CHAST}
+ {938872800 49500 1 CHADT}
+ {953388000 45900 0 CHAST}
+ {970322400 49500 1 CHADT}
+ {984837600 45900 0 CHAST}
+ {1002376800 49500 1 CHADT}
+ {1016287200 45900 0 CHAST}
+ {1033826400 49500 1 CHADT}
+ {1047736800 45900 0 CHAST}
+ {1065276000 49500 1 CHADT}
+ {1079791200 45900 0 CHAST}
+ {1096725600 49500 1 CHADT}
+ {1111240800 45900 0 CHAST}
+ {1128175200 49500 1 CHADT}
+ {1142690400 45900 0 CHAST}
+ {1159624800 49500 1 CHADT}
+ {1174140000 45900 0 CHAST}
+ {1191074400 49500 1 CHADT}
+ {1207404000 45900 0 CHAST}
+ {1222524000 49500 1 CHADT}
+ {1238853600 45900 0 CHAST}
+ {1253973600 49500 1 CHADT}
+ {1270303200 45900 0 CHAST}
+ {1285423200 49500 1 CHADT}
+ {1301752800 45900 0 CHAST}
+ {1316872800 49500 1 CHADT}
+ {1333202400 45900 0 CHAST}
+ {1348927200 49500 1 CHADT}
+ {1365256800 45900 0 CHAST}
+ {1380376800 49500 1 CHADT}
+ {1396706400 45900 0 CHAST}
+ {1411826400 49500 1 CHADT}
+ {1428156000 45900 0 CHAST}
+ {1443276000 49500 1 CHADT}
+ {1459605600 45900 0 CHAST}
+ {1474725600 49500 1 CHADT}
+ {1491055200 45900 0 CHAST}
+ {1506175200 49500 1 CHADT}
+ {1522504800 45900 0 CHAST}
+ {1538229600 49500 1 CHADT}
+ {1554559200 45900 0 CHAST}
+ {1569679200 49500 1 CHADT}
+ {1586008800 45900 0 CHAST}
+ {1601128800 49500 1 CHADT}
+ {1617458400 45900 0 CHAST}
+ {1632578400 49500 1 CHADT}
+ {1648908000 45900 0 CHAST}
+ {1664028000 49500 1 CHADT}
+ {1680357600 45900 0 CHAST}
+ {1695477600 49500 1 CHADT}
+ {1712412000 45900 0 CHAST}
+ {1727532000 49500 1 CHADT}
+ {1743861600 45900 0 CHAST}
+ {1758981600 49500 1 CHADT}
+ {1775311200 45900 0 CHAST}
+ {1790431200 49500 1 CHADT}
+ {1806760800 45900 0 CHAST}
+ {1821880800 49500 1 CHADT}
+ {1838210400 45900 0 CHAST}
+ {1853330400 49500 1 CHADT}
+ {1869660000 45900 0 CHAST}
+ {1885384800 49500 1 CHADT}
+ {1901714400 45900 0 CHAST}
+ {1916834400 49500 1 CHADT}
+ {1933164000 45900 0 CHAST}
+ {1948284000 49500 1 CHADT}
+ {1964613600 45900 0 CHAST}
+ {1979733600 49500 1 CHADT}
+ {1996063200 45900 0 CHAST}
+ {2011183200 49500 1 CHADT}
+ {2027512800 45900 0 CHAST}
+ {2042632800 49500 1 CHADT}
+ {2058962400 45900 0 CHAST}
+ {2074687200 49500 1 CHADT}
+ {2091016800 45900 0 CHAST}
+ {2106136800 49500 1 CHADT}
+ {2122466400 45900 0 CHAST}
+ {2137586400 49500 1 CHADT}
+ {2153916000 45900 0 CHAST}
+ {2169036000 49500 1 CHADT}
+ {2185365600 45900 0 CHAST}
+ {2200485600 49500 1 CHADT}
+ {2216815200 45900 0 CHAST}
+ {2232540000 49500 1 CHADT}
+ {2248869600 45900 0 CHAST}
+ {2263989600 49500 1 CHADT}
+ {2280319200 45900 0 CHAST}
+ {2295439200 49500 1 CHADT}
+ {2311768800 45900 0 CHAST}
+ {2326888800 49500 1 CHADT}
+ {2343218400 45900 0 CHAST}
+ {2358338400 49500 1 CHADT}
+ {2374668000 45900 0 CHAST}
+ {2389788000 49500 1 CHADT}
+ {2406117600 45900 0 CHAST}
+ {2421842400 49500 1 CHADT}
+ {2438172000 45900 0 CHAST}
+ {2453292000 49500 1 CHADT}
+ {2469621600 45900 0 CHAST}
+ {2484741600 49500 1 CHADT}
+ {2501071200 45900 0 CHAST}
+ {2516191200 49500 1 CHADT}
+ {2532520800 45900 0 CHAST}
+ {2547640800 49500 1 CHADT}
+ {2563970400 45900 0 CHAST}
+ {2579090400 49500 1 CHADT}
+ {2596024800 45900 0 CHAST}
+ {2611144800 49500 1 CHADT}
+ {2627474400 45900 0 CHAST}
+ {2642594400 49500 1 CHADT}
+ {2658924000 45900 0 CHAST}
+ {2674044000 49500 1 CHADT}
+ {2690373600 45900 0 CHAST}
+ {2705493600 49500 1 CHADT}
+ {2721823200 45900 0 CHAST}
+ {2736943200 49500 1 CHADT}
+ {2753272800 45900 0 CHAST}
+ {2768997600 49500 1 CHADT}
+ {2785327200 45900 0 CHAST}
+ {2800447200 49500 1 CHADT}
+ {2816776800 45900 0 CHAST}
+ {2831896800 49500 1 CHADT}
+ {2848226400 45900 0 CHAST}
+ {2863346400 49500 1 CHADT}
+ {2879676000 45900 0 CHAST}
+ {2894796000 49500 1 CHADT}
+ {2911125600 45900 0 CHAST}
+ {2926245600 49500 1 CHADT}
+ {2942575200 45900 0 CHAST}
+ {2958300000 49500 1 CHADT}
+ {2974629600 45900 0 CHAST}
+ {2989749600 49500 1 CHADT}
+ {3006079200 45900 0 CHAST}
+ {3021199200 49500 1 CHADT}
+ {3037528800 45900 0 CHAST}
+ {3052648800 49500 1 CHADT}
+ {3068978400 45900 0 CHAST}
+ {3084098400 49500 1 CHADT}
+ {3100428000 45900 0 CHAST}
+ {3116152800 49500 1 CHADT}
+ {3132482400 45900 0 CHAST}
+ {3147602400 49500 1 CHADT}
+ {3163932000 45900 0 CHAST}
+ {3179052000 49500 1 CHADT}
+ {3195381600 45900 0 CHAST}
+ {3210501600 49500 1 CHADT}
+ {3226831200 45900 0 CHAST}
+ {3241951200 49500 1 CHADT}
+ {3258280800 45900 0 CHAST}
+ {3273400800 49500 1 CHADT}
+ {3289730400 45900 0 CHAST}
+ {3305455200 49500 1 CHADT}
+ {3321784800 45900 0 CHAST}
+ {3336904800 49500 1 CHADT}
+ {3353234400 45900 0 CHAST}
+ {3368354400 49500 1 CHADT}
+ {3384684000 45900 0 CHAST}
+ {3399804000 49500 1 CHADT}
+ {3416133600 45900 0 CHAST}
+ {3431253600 49500 1 CHADT}
+ {3447583200 45900 0 CHAST}
+ {3462703200 49500 1 CHADT}
+ {3479637600 45900 0 CHAST}
+ {3494757600 49500 1 CHADT}
+ {3511087200 45900 0 CHAST}
+ {3526207200 49500 1 CHADT}
+ {3542536800 45900 0 CHAST}
+ {3557656800 49500 1 CHADT}
+ {3573986400 45900 0 CHAST}
+ {3589106400 49500 1 CHADT}
+ {3605436000 45900 0 CHAST}
+ {3620556000 49500 1 CHADT}
+ {3636885600 45900 0 CHAST}
+ {3652610400 49500 1 CHADT}
+ {3668940000 45900 0 CHAST}
+ {3684060000 49500 1 CHADT}
+ {3700389600 45900 0 CHAST}
+ {3715509600 49500 1 CHADT}
+ {3731839200 45900 0 CHAST}
+ {3746959200 49500 1 CHADT}
+ {3763288800 45900 0 CHAST}
+ {3778408800 49500 1 CHADT}
+ {3794738400 45900 0 CHAST}
+ {3809858400 49500 1 CHADT}
+ {3826188000 45900 0 CHAST}
+ {3841912800 49500 1 CHADT}
+ {3858242400 45900 0 CHAST}
+ {3873362400 49500 1 CHADT}
+ {3889692000 45900 0 CHAST}
+ {3904812000 49500 1 CHADT}
+ {3921141600 45900 0 CHAST}
+ {3936261600 49500 1 CHADT}
+ {3952591200 45900 0 CHAST}
+ {3967711200 49500 1 CHADT}
+ {3984040800 45900 0 CHAST}
+ {3999765600 49500 1 CHADT}
+ {4016095200 45900 0 CHAST}
+ {4031215200 49500 1 CHADT}
+ {4047544800 45900 0 CHAST}
+ {4062664800 49500 1 CHADT}
+ {4078994400 45900 0 CHAST}
+ {4094114400 49500 1 CHADT}
+}
diff --git a/library/tzdata/Pacific/Chuuk b/library/tzdata/Pacific/Chuuk
new file mode 100644
index 0000000..70b14b2
--- /dev/null
+++ b/library/tzdata/Pacific/Chuuk
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Chuuk) {
+ {-9223372036854775808 36428 0 LMT}
+ {-2177489228 36000 0 CHUT}
+}
diff --git a/library/tzdata/Pacific/Easter b/library/tzdata/Pacific/Easter
new file mode 100644
index 0000000..f8e63a8
--- /dev/null
+++ b/library/tzdata/Pacific/Easter
@@ -0,0 +1,275 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Easter) {
+ {-9223372036854775808 -26264 0 LMT}
+ {-2524495336 -26248 0 EMT}
+ {-1178124152 -21600 0 EASST}
+ {-870552000 -25200 0 EAST}
+ {-865278000 -21600 1 EASST}
+ {-740520000 -21600 1 EASST}
+ {-736376400 -25200 0 EAST}
+ {-718056000 -25200 0 EAST}
+ {-36619200 -21600 1 EASST}
+ {-23922000 -25200 0 EAST}
+ {-3355200 -21600 1 EASST}
+ {7527600 -25200 0 EAST}
+ {24465600 -21600 1 EASST}
+ {37767600 -25200 0 EAST}
+ {55915200 -21600 1 EASST}
+ {69217200 -25200 0 EAST}
+ {87969600 -21600 1 EASST}
+ {100666800 -25200 0 EAST}
+ {118209600 -21600 1 EASST}
+ {132116400 -25200 0 EAST}
+ {150868800 -21600 1 EASST}
+ {163566000 -25200 0 EAST}
+ {182318400 -21600 1 EASST}
+ {195620400 -25200 0 EAST}
+ {213768000 -21600 1 EASST}
+ {227070000 -25200 0 EAST}
+ {245217600 -21600 1 EASST}
+ {258519600 -25200 0 EAST}
+ {277272000 -21600 1 EASST}
+ {289969200 -25200 0 EAST}
+ {308721600 -21600 1 EASST}
+ {321418800 -25200 0 EAST}
+ {340171200 -21600 1 EASST}
+ {353473200 -25200 0 EAST}
+ {371620800 -21600 1 EASST}
+ {384922800 -21600 0 EAST}
+ {403070400 -18000 1 EASST}
+ {416372400 -21600 0 EAST}
+ {434520000 -18000 1 EASST}
+ {447822000 -21600 0 EAST}
+ {466574400 -18000 1 EASST}
+ {479271600 -21600 0 EAST}
+ {498024000 -18000 1 EASST}
+ {510721200 -21600 0 EAST}
+ {529473600 -18000 1 EASST}
+ {545194800 -21600 0 EAST}
+ {560923200 -18000 1 EASST}
+ {574225200 -21600 0 EAST}
+ {591768000 -18000 1 EASST}
+ {605674800 -21600 0 EAST}
+ {624427200 -18000 1 EASST}
+ {637729200 -21600 0 EAST}
+ {653457600 -18000 1 EASST}
+ {668574000 -21600 0 EAST}
+ {687326400 -18000 1 EASST}
+ {700628400 -21600 0 EAST}
+ {718776000 -18000 1 EASST}
+ {732078000 -21600 0 EAST}
+ {750225600 -18000 1 EASST}
+ {763527600 -21600 0 EAST}
+ {781675200 -18000 1 EASST}
+ {794977200 -21600 0 EAST}
+ {813729600 -18000 1 EASST}
+ {826426800 -21600 0 EAST}
+ {845179200 -18000 1 EASST}
+ {859690800 -21600 0 EAST}
+ {876628800 -18000 1 EASST}
+ {889930800 -21600 0 EAST}
+ {906868800 -18000 1 EASST}
+ {923194800 -21600 0 EAST}
+ {939528000 -18000 1 EASST}
+ {952830000 -21600 0 EAST}
+ {971582400 -18000 1 EASST}
+ {984279600 -21600 0 EAST}
+ {1003032000 -18000 1 EASST}
+ {1015729200 -21600 0 EAST}
+ {1034481600 -18000 1 EASST}
+ {1047178800 -21600 0 EAST}
+ {1065931200 -18000 1 EASST}
+ {1079233200 -21600 0 EAST}
+ {1097380800 -18000 1 EASST}
+ {1110682800 -21600 0 EAST}
+ {1128830400 -18000 1 EASST}
+ {1142132400 -21600 0 EAST}
+ {1160884800 -18000 1 EASST}
+ {1173582000 -21600 0 EAST}
+ {1192334400 -18000 1 EASST}
+ {1206846000 -21600 0 EAST}
+ {1223784000 -18000 1 EASST}
+ {1237086000 -21600 0 EAST}
+ {1255233600 -18000 1 EASST}
+ {1270350000 -21600 0 EAST}
+ {1286683200 -18000 1 EASST}
+ {1304823600 -21600 0 EAST}
+ {1313899200 -18000 1 EASST}
+ {1331434800 -21600 0 EAST}
+ {1350187200 -18000 1 EASST}
+ {1362884400 -21600 0 EAST}
+ {1381636800 -18000 1 EASST}
+ {1394334000 -21600 0 EAST}
+ {1413086400 -18000 1 EASST}
+ {1426388400 -21600 0 EAST}
+ {1444536000 -18000 1 EASST}
+ {1457838000 -21600 0 EAST}
+ {1475985600 -18000 1 EASST}
+ {1489287600 -21600 0 EAST}
+ {1508040000 -18000 1 EASST}
+ {1520737200 -21600 0 EAST}
+ {1539489600 -18000 1 EASST}
+ {1552186800 -21600 0 EAST}
+ {1570939200 -18000 1 EASST}
+ {1584241200 -21600 0 EAST}
+ {1602388800 -18000 1 EASST}
+ {1615690800 -21600 0 EAST}
+ {1633838400 -18000 1 EASST}
+ {1647140400 -21600 0 EAST}
+ {1665288000 -18000 1 EASST}
+ {1678590000 -21600 0 EAST}
+ {1697342400 -18000 1 EASST}
+ {1710039600 -21600 0 EAST}
+ {1728792000 -18000 1 EASST}
+ {1741489200 -21600 0 EAST}
+ {1760241600 -18000 1 EASST}
+ {1773543600 -21600 0 EAST}
+ {1791691200 -18000 1 EASST}
+ {1804993200 -21600 0 EAST}
+ {1823140800 -18000 1 EASST}
+ {1836442800 -21600 0 EAST}
+ {1855195200 -18000 1 EASST}
+ {1867892400 -21600 0 EAST}
+ {1886644800 -18000 1 EASST}
+ {1899342000 -21600 0 EAST}
+ {1918094400 -18000 1 EASST}
+ {1930791600 -21600 0 EAST}
+ {1949544000 -18000 1 EASST}
+ {1962846000 -21600 0 EAST}
+ {1980993600 -18000 1 EASST}
+ {1994295600 -21600 0 EAST}
+ {2012443200 -18000 1 EASST}
+ {2025745200 -21600 0 EAST}
+ {2044497600 -18000 1 EASST}
+ {2057194800 -21600 0 EAST}
+ {2075947200 -18000 1 EASST}
+ {2088644400 -21600 0 EAST}
+ {2107396800 -18000 1 EASST}
+ {2120698800 -21600 0 EAST}
+ {2138846400 -18000 1 EASST}
+ {2152148400 -21600 0 EAST}
+ {2170296000 -18000 1 EASST}
+ {2183598000 -21600 0 EAST}
+ {2201745600 -18000 1 EASST}
+ {2215047600 -21600 0 EAST}
+ {2233800000 -18000 1 EASST}
+ {2246497200 -21600 0 EAST}
+ {2265249600 -18000 1 EASST}
+ {2277946800 -21600 0 EAST}
+ {2296699200 -18000 1 EASST}
+ {2310001200 -21600 0 EAST}
+ {2328148800 -18000 1 EASST}
+ {2341450800 -21600 0 EAST}
+ {2359598400 -18000 1 EASST}
+ {2372900400 -21600 0 EAST}
+ {2391652800 -18000 1 EASST}
+ {2404350000 -21600 0 EAST}
+ {2423102400 -18000 1 EASST}
+ {2435799600 -21600 0 EAST}
+ {2454552000 -18000 1 EASST}
+ {2467854000 -21600 0 EAST}
+ {2486001600 -18000 1 EASST}
+ {2499303600 -21600 0 EAST}
+ {2517451200 -18000 1 EASST}
+ {2530753200 -21600 0 EAST}
+ {2548900800 -18000 1 EASST}
+ {2562202800 -21600 0 EAST}
+ {2580955200 -18000 1 EASST}
+ {2593652400 -21600 0 EAST}
+ {2612404800 -18000 1 EASST}
+ {2625102000 -21600 0 EAST}
+ {2643854400 -18000 1 EASST}
+ {2657156400 -21600 0 EAST}
+ {2675304000 -18000 1 EASST}
+ {2688606000 -21600 0 EAST}
+ {2706753600 -18000 1 EASST}
+ {2720055600 -21600 0 EAST}
+ {2738808000 -18000 1 EASST}
+ {2751505200 -21600 0 EAST}
+ {2770257600 -18000 1 EASST}
+ {2782954800 -21600 0 EAST}
+ {2801707200 -18000 1 EASST}
+ {2814404400 -21600 0 EAST}
+ {2833156800 -18000 1 EASST}
+ {2846458800 -21600 0 EAST}
+ {2864606400 -18000 1 EASST}
+ {2877908400 -21600 0 EAST}
+ {2896056000 -18000 1 EASST}
+ {2909358000 -21600 0 EAST}
+ {2928110400 -18000 1 EASST}
+ {2940807600 -21600 0 EAST}
+ {2959560000 -18000 1 EASST}
+ {2972257200 -21600 0 EAST}
+ {2991009600 -18000 1 EASST}
+ {3004311600 -21600 0 EAST}
+ {3022459200 -18000 1 EASST}
+ {3035761200 -21600 0 EAST}
+ {3053908800 -18000 1 EASST}
+ {3067210800 -21600 0 EAST}
+ {3085358400 -18000 1 EASST}
+ {3098660400 -21600 0 EAST}
+ {3117412800 -18000 1 EASST}
+ {3130110000 -21600 0 EAST}
+ {3148862400 -18000 1 EASST}
+ {3161559600 -21600 0 EAST}
+ {3180312000 -18000 1 EASST}
+ {3193614000 -21600 0 EAST}
+ {3211761600 -18000 1 EASST}
+ {3225063600 -21600 0 EAST}
+ {3243211200 -18000 1 EASST}
+ {3256513200 -21600 0 EAST}
+ {3275265600 -18000 1 EASST}
+ {3287962800 -21600 0 EAST}
+ {3306715200 -18000 1 EASST}
+ {3319412400 -21600 0 EAST}
+ {3338164800 -18000 1 EASST}
+ {3351466800 -21600 0 EAST}
+ {3369614400 -18000 1 EASST}
+ {3382916400 -21600 0 EAST}
+ {3401064000 -18000 1 EASST}
+ {3414366000 -21600 0 EAST}
+ {3432513600 -18000 1 EASST}
+ {3445815600 -21600 0 EAST}
+ {3464568000 -18000 1 EASST}
+ {3477265200 -21600 0 EAST}
+ {3496017600 -18000 1 EASST}
+ {3508714800 -21600 0 EAST}
+ {3527467200 -18000 1 EASST}
+ {3540769200 -21600 0 EAST}
+ {3558916800 -18000 1 EASST}
+ {3572218800 -21600 0 EAST}
+ {3590366400 -18000 1 EASST}
+ {3603668400 -21600 0 EAST}
+ {3622420800 -18000 1 EASST}
+ {3635118000 -21600 0 EAST}
+ {3653870400 -18000 1 EASST}
+ {3666567600 -21600 0 EAST}
+ {3685320000 -18000 1 EASST}
+ {3698017200 -21600 0 EAST}
+ {3716769600 -18000 1 EASST}
+ {3730071600 -21600 0 EAST}
+ {3748219200 -18000 1 EASST}
+ {3761521200 -21600 0 EAST}
+ {3779668800 -18000 1 EASST}
+ {3792970800 -21600 0 EAST}
+ {3811723200 -18000 1 EASST}
+ {3824420400 -21600 0 EAST}
+ {3843172800 -18000 1 EASST}
+ {3855870000 -21600 0 EAST}
+ {3874622400 -18000 1 EASST}
+ {3887924400 -21600 0 EAST}
+ {3906072000 -18000 1 EASST}
+ {3919374000 -21600 0 EAST}
+ {3937521600 -18000 1 EASST}
+ {3950823600 -21600 0 EAST}
+ {3968971200 -18000 1 EASST}
+ {3982273200 -21600 0 EAST}
+ {4001025600 -18000 1 EASST}
+ {4013722800 -21600 0 EAST}
+ {4032475200 -18000 1 EASST}
+ {4045172400 -21600 0 EAST}
+ {4063924800 -18000 1 EASST}
+ {4077226800 -21600 0 EAST}
+ {4095374400 -18000 1 EASST}
+}
diff --git a/library/tzdata/Pacific/Efate b/library/tzdata/Pacific/Efate
new file mode 100644
index 0000000..18db6de
--- /dev/null
+++ b/library/tzdata/Pacific/Efate
@@ -0,0 +1,26 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Efate) {
+ {-9223372036854775808 40396 0 LMT}
+ {-1829387596 39600 0 VUT}
+ {433256400 43200 1 VUST}
+ {448977600 39600 0 VUT}
+ {467298000 43200 1 VUST}
+ {480427200 39600 0 VUT}
+ {496760400 43200 1 VUST}
+ {511876800 39600 0 VUT}
+ {528210000 43200 1 VUST}
+ {543931200 39600 0 VUT}
+ {559659600 43200 1 VUST}
+ {575380800 39600 0 VUT}
+ {591109200 43200 1 VUST}
+ {606830400 39600 0 VUT}
+ {622558800 43200 1 VUST}
+ {638280000 39600 0 VUT}
+ {654008400 43200 1 VUST}
+ {669729600 39600 0 VUT}
+ {686062800 43200 1 VUST}
+ {696340800 39600 0 VUT}
+ {719931600 43200 1 VUST}
+ {727790400 39600 0 VUT}
+}
diff --git a/library/tzdata/Pacific/Enderbury b/library/tzdata/Pacific/Enderbury
new file mode 100644
index 0000000..55784c4
--- /dev/null
+++ b/library/tzdata/Pacific/Enderbury
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Enderbury) {
+ {-9223372036854775808 -41060 0 LMT}
+ {-2177411740 -43200 0 PHOT}
+ {307627200 -39600 0 PHOT}
+ {788958000 46800 0 PHOT}
+}
diff --git a/library/tzdata/Pacific/Fakaofo b/library/tzdata/Pacific/Fakaofo
new file mode 100644
index 0000000..7420639
--- /dev/null
+++ b/library/tzdata/Pacific/Fakaofo
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Fakaofo) {
+ {-9223372036854775808 -41096 0 LMT}
+ {-2177411704 -36000 0 TKT}
+}
diff --git a/library/tzdata/Pacific/Fiji b/library/tzdata/Pacific/Fiji
new file mode 100644
index 0000000..3b7aabe
--- /dev/null
+++ b/library/tzdata/Pacific/Fiji
@@ -0,0 +1,14 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Fiji) {
+ {-9223372036854775808 42820 0 LMT}
+ {-1709985220 43200 0 FJT}
+ {909842400 46800 1 FJST}
+ {920124000 43200 0 FJT}
+ {941896800 46800 1 FJST}
+ {951573600 43200 0 FJT}
+ {1259416800 46800 1 FJST}
+ {1269698400 43200 0 FJT}
+ {1287842400 46800 1 FJST}
+ {1299333600 43200 0 FJT}
+}
diff --git a/library/tzdata/Pacific/Funafuti b/library/tzdata/Pacific/Funafuti
new file mode 100644
index 0000000..b94e4fb
--- /dev/null
+++ b/library/tzdata/Pacific/Funafuti
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Funafuti) {
+ {-9223372036854775808 43012 0 LMT}
+ {-2177495812 43200 0 TVT}
+}
diff --git a/library/tzdata/Pacific/Galapagos b/library/tzdata/Pacific/Galapagos
new file mode 100644
index 0000000..d8c80e8
--- /dev/null
+++ b/library/tzdata/Pacific/Galapagos
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Galapagos) {
+ {-9223372036854775808 -21504 0 LMT}
+ {-1230746496 -18000 0 ECT}
+ {504939600 -21600 0 GALT}
+}
diff --git a/library/tzdata/Pacific/Gambier b/library/tzdata/Pacific/Gambier
new file mode 100644
index 0000000..d69f99a
--- /dev/null
+++ b/library/tzdata/Pacific/Gambier
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Gambier) {
+ {-9223372036854775808 -32388 0 LMT}
+ {-1806678012 -32400 0 GAMT}
+}
diff --git a/library/tzdata/Pacific/Guadalcanal b/library/tzdata/Pacific/Guadalcanal
new file mode 100644
index 0000000..09a67dd
--- /dev/null
+++ b/library/tzdata/Pacific/Guadalcanal
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Guadalcanal) {
+ {-9223372036854775808 38388 0 LMT}
+ {-1806748788 39600 0 SBT}
+}
diff --git a/library/tzdata/Pacific/Guam b/library/tzdata/Pacific/Guam
new file mode 100644
index 0000000..79cca80
--- /dev/null
+++ b/library/tzdata/Pacific/Guam
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Guam) {
+ {-9223372036854775808 -51660 0 LMT}
+ {-3944626740 34740 0 LMT}
+ {-2177487540 36000 0 GST}
+ {977493600 36000 0 ChST}
+}
diff --git a/library/tzdata/Pacific/Honolulu b/library/tzdata/Pacific/Honolulu
new file mode 100644
index 0000000..e24b096
--- /dev/null
+++ b/library/tzdata/Pacific/Honolulu
@@ -0,0 +1,10 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Honolulu) {
+ {-9223372036854775808 -37886 0 LMT}
+ {-2334101314 -37800 0 HST}
+ {-1157283000 -34200 1 HDT}
+ {-1155436200 -37800 0 HST}
+ {-880198200 -34200 1 HDT}
+ {-712150200 -36000 0 HST}
+}
diff --git a/library/tzdata/Pacific/Johnston b/library/tzdata/Pacific/Johnston
new file mode 100644
index 0000000..7f9fee4
--- /dev/null
+++ b/library/tzdata/Pacific/Johnston
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Johnston) {
+ {-9223372036854775808 -36000 0 HST}
+}
diff --git a/library/tzdata/Pacific/Kiritimati b/library/tzdata/Pacific/Kiritimati
new file mode 100644
index 0000000..06b695b
--- /dev/null
+++ b/library/tzdata/Pacific/Kiritimati
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Kiritimati) {
+ {-9223372036854775808 -37760 0 LMT}
+ {-2177415040 -38400 0 LINT}
+ {307622400 -36000 0 LINT}
+ {788954400 50400 0 LINT}
+}
diff --git a/library/tzdata/Pacific/Kosrae b/library/tzdata/Pacific/Kosrae
new file mode 100644
index 0000000..a16b19d
--- /dev/null
+++ b/library/tzdata/Pacific/Kosrae
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Kosrae) {
+ {-9223372036854775808 39116 0 LMT}
+ {-2177491916 39600 0 KOST}
+ {-7988400 43200 0 KOST}
+ {915105600 39600 0 KOST}
+}
diff --git a/library/tzdata/Pacific/Kwajalein b/library/tzdata/Pacific/Kwajalein
new file mode 100644
index 0000000..8600b3b
--- /dev/null
+++ b/library/tzdata/Pacific/Kwajalein
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Kwajalein) {
+ {-9223372036854775808 40160 0 LMT}
+ {-2177492960 39600 0 MHT}
+ {-7988400 -43200 0 KWAT}
+ {745848000 43200 0 MHT}
+}
diff --git a/library/tzdata/Pacific/Majuro b/library/tzdata/Pacific/Majuro
new file mode 100644
index 0000000..468baab
--- /dev/null
+++ b/library/tzdata/Pacific/Majuro
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Majuro) {
+ {-9223372036854775808 41088 0 LMT}
+ {-2177493888 39600 0 MHT}
+ {-7988400 43200 0 MHT}
+}
diff --git a/library/tzdata/Pacific/Marquesas b/library/tzdata/Pacific/Marquesas
new file mode 100644
index 0000000..9bb508f
--- /dev/null
+++ b/library/tzdata/Pacific/Marquesas
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Marquesas) {
+ {-9223372036854775808 -33480 0 LMT}
+ {-1806676920 -34200 0 MART}
+}
diff --git a/library/tzdata/Pacific/Midway b/library/tzdata/Pacific/Midway
new file mode 100644
index 0000000..c07b030
--- /dev/null
+++ b/library/tzdata/Pacific/Midway
@@ -0,0 +1,10 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Midway) {
+ {-9223372036854775808 -42568 0 LMT}
+ {-2177410232 -39600 0 NST}
+ {-428504400 -36000 1 NDT}
+ {-420645600 -39600 0 NST}
+ {-86878800 -39600 0 BST}
+ {439038000 -39600 0 SST}
+}
diff --git a/library/tzdata/Pacific/Nauru b/library/tzdata/Pacific/Nauru
new file mode 100644
index 0000000..2da1e25
--- /dev/null
+++ b/library/tzdata/Pacific/Nauru
@@ -0,0 +1,9 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Nauru) {
+ {-9223372036854775808 40060 0 LMT}
+ {-1545131260 41400 0 NRT}
+ {-877347000 32400 0 JST}
+ {-800960400 41400 0 NRT}
+ {294323400 43200 0 NRT}
+}
diff --git a/library/tzdata/Pacific/Niue b/library/tzdata/Pacific/Niue
new file mode 100644
index 0000000..cf149fc
--- /dev/null
+++ b/library/tzdata/Pacific/Niue
@@ -0,0 +1,8 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Niue) {
+ {-9223372036854775808 -40780 0 LMT}
+ {-2177412020 -40800 0 NUT}
+ {-599575200 -41400 0 NUT}
+ {276089400 -39600 0 NUT}
+}
diff --git a/library/tzdata/Pacific/Norfolk b/library/tzdata/Pacific/Norfolk
new file mode 100644
index 0000000..a8fac15
--- /dev/null
+++ b/library/tzdata/Pacific/Norfolk
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Norfolk) {
+ {-9223372036854775808 40312 0 LMT}
+ {-2177493112 40320 0 NMT}
+ {-599656320 41400 0 NFT}
+}
diff --git a/library/tzdata/Pacific/Noumea b/library/tzdata/Pacific/Noumea
new file mode 100644
index 0000000..db1eeae
--- /dev/null
+++ b/library/tzdata/Pacific/Noumea
@@ -0,0 +1,12 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Noumea) {
+ {-9223372036854775808 39948 0 LMT}
+ {-1829387148 39600 0 NCT}
+ {250002000 43200 1 NCST}
+ {257342400 39600 0 NCT}
+ {281451600 43200 1 NCST}
+ {288878400 39600 0 NCT}
+ {849366000 43200 1 NCST}
+ {857228400 39600 0 NCT}
+}
diff --git a/library/tzdata/Pacific/Pago_Pago b/library/tzdata/Pacific/Pago_Pago
new file mode 100644
index 0000000..830f9ee
--- /dev/null
+++ b/library/tzdata/Pacific/Pago_Pago
@@ -0,0 +1,10 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Pago_Pago) {
+ {-9223372036854775808 45432 0 LMT}
+ {-2855738232 -40968 0 LMT}
+ {-1861879032 -41400 0 SAMT}
+ {-631110600 -39600 0 NST}
+ {-86878800 -39600 0 BST}
+ {439038000 -39600 0 SST}
+}
diff --git a/library/tzdata/Pacific/Palau b/library/tzdata/Pacific/Palau
new file mode 100644
index 0000000..ee0606d
--- /dev/null
+++ b/library/tzdata/Pacific/Palau
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Palau) {
+ {-9223372036854775808 32276 0 LMT}
+ {-2177485076 32400 0 PWT}
+}
diff --git a/library/tzdata/Pacific/Pitcairn b/library/tzdata/Pacific/Pitcairn
new file mode 100644
index 0000000..d62644e
--- /dev/null
+++ b/library/tzdata/Pacific/Pitcairn
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Pitcairn) {
+ {-9223372036854775808 -31220 0 LMT}
+ {-2177421580 -30600 0 PNT}
+ {893665800 -28800 0 PST}
+}
diff --git a/library/tzdata/Pacific/Pohnpei b/library/tzdata/Pacific/Pohnpei
new file mode 100644
index 0000000..58978da
--- /dev/null
+++ b/library/tzdata/Pacific/Pohnpei
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Pohnpei) {
+ {-9223372036854775808 37972 0 LMT}
+ {-2177490772 39600 0 PONT}
+}
diff --git a/library/tzdata/Pacific/Ponape b/library/tzdata/Pacific/Ponape
new file mode 100644
index 0000000..89644f7
--- /dev/null
+++ b/library/tzdata/Pacific/Ponape
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Pacific/Pohnpei)]} {
+ LoadTimeZoneFile Pacific/Pohnpei
+}
+set TZData(:Pacific/Ponape) $TZData(:Pacific/Pohnpei)
diff --git a/library/tzdata/Pacific/Port_Moresby b/library/tzdata/Pacific/Port_Moresby
new file mode 100644
index 0000000..65eb533
--- /dev/null
+++ b/library/tzdata/Pacific/Port_Moresby
@@ -0,0 +1,7 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Port_Moresby) {
+ {-9223372036854775808 35320 0 LMT}
+ {-2840176120 35312 0 PMMT}
+ {-2366790512 36000 0 PGT}
+}
diff --git a/library/tzdata/Pacific/Rarotonga b/library/tzdata/Pacific/Rarotonga
new file mode 100644
index 0000000..a4ecf8d
--- /dev/null
+++ b/library/tzdata/Pacific/Rarotonga
@@ -0,0 +1,32 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Rarotonga) {
+ {-9223372036854775808 -38344 0 LMT}
+ {-2177414456 -37800 0 CKT}
+ {279714600 -34200 0 CKHST}
+ {289387800 -36000 0 CKT}
+ {309952800 -34200 1 CKHST}
+ {320837400 -36000 0 CKT}
+ {341402400 -34200 1 CKHST}
+ {352287000 -36000 0 CKT}
+ {372852000 -34200 1 CKHST}
+ {384341400 -36000 0 CKT}
+ {404906400 -34200 1 CKHST}
+ {415791000 -36000 0 CKT}
+ {436356000 -34200 1 CKHST}
+ {447240600 -36000 0 CKT}
+ {467805600 -34200 1 CKHST}
+ {478690200 -36000 0 CKT}
+ {499255200 -34200 1 CKHST}
+ {510139800 -36000 0 CKT}
+ {530704800 -34200 1 CKHST}
+ {541589400 -36000 0 CKT}
+ {562154400 -34200 1 CKHST}
+ {573643800 -36000 0 CKT}
+ {594208800 -34200 1 CKHST}
+ {605093400 -36000 0 CKT}
+ {625658400 -34200 1 CKHST}
+ {636543000 -36000 0 CKT}
+ {657108000 -34200 1 CKHST}
+ {667992600 -36000 0 CKT}
+}
diff --git a/library/tzdata/Pacific/Saipan b/library/tzdata/Pacific/Saipan
new file mode 100644
index 0000000..b799298
--- /dev/null
+++ b/library/tzdata/Pacific/Saipan
@@ -0,0 +1,9 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Saipan) {
+ {-9223372036854775808 -51420 0 LMT}
+ {-3944626980 34980 0 LMT}
+ {-2177487780 32400 0 MPT}
+ {-7981200 36000 0 MPT}
+ {977493600 36000 0 ChST}
+}
diff --git a/library/tzdata/Pacific/Samoa b/library/tzdata/Pacific/Samoa
new file mode 100644
index 0000000..686eb34
--- /dev/null
+++ b/library/tzdata/Pacific/Samoa
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Pacific/Pago_Pago)]} {
+ LoadTimeZoneFile Pacific/Pago_Pago
+}
+set TZData(:Pacific/Samoa) $TZData(:Pacific/Pago_Pago)
diff --git a/library/tzdata/Pacific/Tahiti b/library/tzdata/Pacific/Tahiti
new file mode 100644
index 0000000..f739223
--- /dev/null
+++ b/library/tzdata/Pacific/Tahiti
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Tahiti) {
+ {-9223372036854775808 -35896 0 LMT}
+ {-1806674504 -36000 0 TAHT}
+}
diff --git a/library/tzdata/Pacific/Tarawa b/library/tzdata/Pacific/Tarawa
new file mode 100644
index 0000000..2dab5a2
--- /dev/null
+++ b/library/tzdata/Pacific/Tarawa
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Tarawa) {
+ {-9223372036854775808 41524 0 LMT}
+ {-2177494324 43200 0 GILT}
+}
diff --git a/library/tzdata/Pacific/Tongatapu b/library/tzdata/Pacific/Tongatapu
new file mode 100644
index 0000000..da9f857
--- /dev/null
+++ b/library/tzdata/Pacific/Tongatapu
@@ -0,0 +1,14 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Tongatapu) {
+ {-9223372036854775808 44360 0 LMT}
+ {-2177497160 44400 0 TOT}
+ {-915193200 46800 0 TOT}
+ {915102000 46800 0 TOT}
+ {939214800 50400 1 TOST}
+ {953384400 46800 0 TOT}
+ {973342800 50400 1 TOST}
+ {980596800 46800 0 TOT}
+ {1004792400 50400 1 TOST}
+ {1012046400 46800 0 TOT}
+}
diff --git a/library/tzdata/Pacific/Truk b/library/tzdata/Pacific/Truk
new file mode 100644
index 0000000..c9b1894
--- /dev/null
+++ b/library/tzdata/Pacific/Truk
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Pacific/Chuuk)]} {
+ LoadTimeZoneFile Pacific/Chuuk
+}
+set TZData(:Pacific/Truk) $TZData(:Pacific/Chuuk)
diff --git a/library/tzdata/Pacific/Wake b/library/tzdata/Pacific/Wake
new file mode 100644
index 0000000..5afedf5
--- /dev/null
+++ b/library/tzdata/Pacific/Wake
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Wake) {
+ {-9223372036854775808 39988 0 LMT}
+ {-2177492788 43200 0 WAKT}
+}
diff --git a/library/tzdata/Pacific/Wallis b/library/tzdata/Pacific/Wallis
new file mode 100644
index 0000000..7bdd964
--- /dev/null
+++ b/library/tzdata/Pacific/Wallis
@@ -0,0 +1,6 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:Pacific/Wallis) {
+ {-9223372036854775808 44120 0 LMT}
+ {-2177496920 43200 0 WFT}
+}
diff --git a/library/tzdata/Pacific/Yap b/library/tzdata/Pacific/Yap
new file mode 100644
index 0000000..4931030
--- /dev/null
+++ b/library/tzdata/Pacific/Yap
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Pacific/Chuuk)]} {
+ LoadTimeZoneFile Pacific/Chuuk
+}
+set TZData(:Pacific/Yap) $TZData(:Pacific/Chuuk)
diff --git a/library/tzdata/Poland b/library/tzdata/Poland
new file mode 100644
index 0000000..bd24028
--- /dev/null
+++ b/library/tzdata/Poland
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/Warsaw)]} {
+ LoadTimeZoneFile Europe/Warsaw
+}
+set TZData(:Poland) $TZData(:Europe/Warsaw)
diff --git a/library/tzdata/Portugal b/library/tzdata/Portugal
new file mode 100644
index 0000000..d1ffd9f
--- /dev/null
+++ b/library/tzdata/Portugal
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/Lisbon)]} {
+ LoadTimeZoneFile Europe/Lisbon
+}
+set TZData(:Portugal) $TZData(:Europe/Lisbon)
diff --git a/library/tzdata/ROC b/library/tzdata/ROC
new file mode 100644
index 0000000..5dd196d
--- /dev/null
+++ b/library/tzdata/ROC
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Asia/Taipei)]} {
+ LoadTimeZoneFile Asia/Taipei
+}
+set TZData(:ROC) $TZData(:Asia/Taipei)
diff --git a/library/tzdata/ROK b/library/tzdata/ROK
new file mode 100644
index 0000000..1162ce4
--- /dev/null
+++ b/library/tzdata/ROK
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Asia/Seoul)]} {
+ LoadTimeZoneFile Asia/Seoul
+}
+set TZData(:ROK) $TZData(:Asia/Seoul)
diff --git a/library/tzdata/Singapore b/library/tzdata/Singapore
new file mode 100644
index 0000000..1584b35
--- /dev/null
+++ b/library/tzdata/Singapore
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Asia/Singapore)]} {
+ LoadTimeZoneFile Asia/Singapore
+}
+set TZData(:Singapore) $TZData(:Asia/Singapore)
diff --git a/library/tzdata/SystemV/AST4 b/library/tzdata/SystemV/AST4
new file mode 100644
index 0000000..eced0d2
--- /dev/null
+++ b/library/tzdata/SystemV/AST4
@@ -0,0 +1,5 @@
+# created by ../tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Puerto_Rico)]} {
+ LoadTimeZoneFile America/Puerto_Rico
+}
+set TZData(:SystemV/AST4) $TZData(:America/Puerto_Rico)
diff --git a/library/tzdata/SystemV/AST4ADT b/library/tzdata/SystemV/AST4ADT
new file mode 100644
index 0000000..c24308f
--- /dev/null
+++ b/library/tzdata/SystemV/AST4ADT
@@ -0,0 +1,5 @@
+# created by ../tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Halifax)]} {
+ LoadTimeZoneFile America/Halifax
+}
+set TZData(:SystemV/AST4ADT) $TZData(:America/Halifax)
diff --git a/library/tzdata/SystemV/CST6 b/library/tzdata/SystemV/CST6
new file mode 100644
index 0000000..d46c015
--- /dev/null
+++ b/library/tzdata/SystemV/CST6
@@ -0,0 +1,5 @@
+# created by ../tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Regina)]} {
+ LoadTimeZoneFile America/Regina
+}
+set TZData(:SystemV/CST6) $TZData(:America/Regina)
diff --git a/library/tzdata/SystemV/CST6CDT b/library/tzdata/SystemV/CST6CDT
new file mode 100644
index 0000000..234af89
--- /dev/null
+++ b/library/tzdata/SystemV/CST6CDT
@@ -0,0 +1,5 @@
+# created by ../tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Chicago)]} {
+ LoadTimeZoneFile America/Chicago
+}
+set TZData(:SystemV/CST6CDT) $TZData(:America/Chicago)
diff --git a/library/tzdata/SystemV/EST5 b/library/tzdata/SystemV/EST5
new file mode 100644
index 0000000..52818c1
--- /dev/null
+++ b/library/tzdata/SystemV/EST5
@@ -0,0 +1,5 @@
+# created by ../tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Indianapolis)]} {
+ LoadTimeZoneFile America/Indianapolis
+}
+set TZData(:SystemV/EST5) $TZData(:America/Indianapolis)
diff --git a/library/tzdata/SystemV/EST5EDT b/library/tzdata/SystemV/EST5EDT
new file mode 100644
index 0000000..6cf2743
--- /dev/null
+++ b/library/tzdata/SystemV/EST5EDT
@@ -0,0 +1,5 @@
+# created by ../tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/New_York)]} {
+ LoadTimeZoneFile America/New_York
+}
+set TZData(:SystemV/EST5EDT) $TZData(:America/New_York)
diff --git a/library/tzdata/SystemV/HST10 b/library/tzdata/SystemV/HST10
new file mode 100644
index 0000000..a4316af
--- /dev/null
+++ b/library/tzdata/SystemV/HST10
@@ -0,0 +1,5 @@
+# created by ../tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Pacific/Honolulu)]} {
+ LoadTimeZoneFile Pacific/Honolulu
+}
+set TZData(:SystemV/HST10) $TZData(:Pacific/Honolulu)
diff --git a/library/tzdata/SystemV/MST7 b/library/tzdata/SystemV/MST7
new file mode 100644
index 0000000..e67a781
--- /dev/null
+++ b/library/tzdata/SystemV/MST7
@@ -0,0 +1,5 @@
+# created by ../tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Phoenix)]} {
+ LoadTimeZoneFile America/Phoenix
+}
+set TZData(:SystemV/MST7) $TZData(:America/Phoenix)
diff --git a/library/tzdata/SystemV/MST7MDT b/library/tzdata/SystemV/MST7MDT
new file mode 100644
index 0000000..fda5bf1
--- /dev/null
+++ b/library/tzdata/SystemV/MST7MDT
@@ -0,0 +1,5 @@
+# created by ../tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Denver)]} {
+ LoadTimeZoneFile America/Denver
+}
+set TZData(:SystemV/MST7MDT) $TZData(:America/Denver)
diff --git a/library/tzdata/SystemV/PST8 b/library/tzdata/SystemV/PST8
new file mode 100644
index 0000000..8e30bb8
--- /dev/null
+++ b/library/tzdata/SystemV/PST8
@@ -0,0 +1,5 @@
+# created by ../tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Pacific/Pitcairn)]} {
+ LoadTimeZoneFile Pacific/Pitcairn
+}
+set TZData(:SystemV/PST8) $TZData(:Pacific/Pitcairn)
diff --git a/library/tzdata/SystemV/PST8PDT b/library/tzdata/SystemV/PST8PDT
new file mode 100644
index 0000000..8281a9a
--- /dev/null
+++ b/library/tzdata/SystemV/PST8PDT
@@ -0,0 +1,5 @@
+# created by ../tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Los_Angeles)]} {
+ LoadTimeZoneFile America/Los_Angeles
+}
+set TZData(:SystemV/PST8PDT) $TZData(:America/Los_Angeles)
diff --git a/library/tzdata/SystemV/YST9 b/library/tzdata/SystemV/YST9
new file mode 100644
index 0000000..32d3717
--- /dev/null
+++ b/library/tzdata/SystemV/YST9
@@ -0,0 +1,5 @@
+# created by ../tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Pacific/Gambier)]} {
+ LoadTimeZoneFile Pacific/Gambier
+}
+set TZData(:SystemV/YST9) $TZData(:Pacific/Gambier)
diff --git a/library/tzdata/SystemV/YST9YDT b/library/tzdata/SystemV/YST9YDT
new file mode 100644
index 0000000..fba405f
--- /dev/null
+++ b/library/tzdata/SystemV/YST9YDT
@@ -0,0 +1,5 @@
+# created by ../tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Anchorage)]} {
+ LoadTimeZoneFile America/Anchorage
+}
+set TZData(:SystemV/YST9YDT) $TZData(:America/Anchorage)
diff --git a/library/tzdata/Turkey b/library/tzdata/Turkey
new file mode 100644
index 0000000..e20a7a5
--- /dev/null
+++ b/library/tzdata/Turkey
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/Istanbul)]} {
+ LoadTimeZoneFile Europe/Istanbul
+}
+set TZData(:Turkey) $TZData(:Europe/Istanbul)
diff --git a/library/tzdata/UCT b/library/tzdata/UCT
new file mode 100644
index 0000000..8449328
--- /dev/null
+++ b/library/tzdata/UCT
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Etc/UCT)]} {
+ LoadTimeZoneFile Etc/UCT
+}
+set TZData(:UCT) $TZData(:Etc/UCT)
diff --git a/library/tzdata/US/Alaska b/library/tzdata/US/Alaska
new file mode 100644
index 0000000..69a3899
--- /dev/null
+++ b/library/tzdata/US/Alaska
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Anchorage)]} {
+ LoadTimeZoneFile America/Anchorage
+}
+set TZData(:US/Alaska) $TZData(:America/Anchorage)
diff --git a/library/tzdata/US/Aleutian b/library/tzdata/US/Aleutian
new file mode 100644
index 0000000..024e70b
--- /dev/null
+++ b/library/tzdata/US/Aleutian
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Adak)]} {
+ LoadTimeZoneFile America/Adak
+}
+set TZData(:US/Aleutian) $TZData(:America/Adak)
diff --git a/library/tzdata/US/Arizona b/library/tzdata/US/Arizona
new file mode 100644
index 0000000..8eaa961
--- /dev/null
+++ b/library/tzdata/US/Arizona
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Phoenix)]} {
+ LoadTimeZoneFile America/Phoenix
+}
+set TZData(:US/Arizona) $TZData(:America/Phoenix)
diff --git a/library/tzdata/US/Central b/library/tzdata/US/Central
new file mode 100644
index 0000000..2aab66e
--- /dev/null
+++ b/library/tzdata/US/Central
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Chicago)]} {
+ LoadTimeZoneFile America/Chicago
+}
+set TZData(:US/Central) $TZData(:America/Chicago)
diff --git a/library/tzdata/US/East-Indiana b/library/tzdata/US/East-Indiana
new file mode 100644
index 0000000..2035a06
--- /dev/null
+++ b/library/tzdata/US/East-Indiana
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Indiana/Indianapolis)]} {
+ LoadTimeZoneFile America/Indiana/Indianapolis
+}
+set TZData(:US/East-Indiana) $TZData(:America/Indiana/Indianapolis)
diff --git a/library/tzdata/US/Eastern b/library/tzdata/US/Eastern
new file mode 100644
index 0000000..3cf2651
--- /dev/null
+++ b/library/tzdata/US/Eastern
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/New_York)]} {
+ LoadTimeZoneFile America/New_York
+}
+set TZData(:US/Eastern) $TZData(:America/New_York)
diff --git a/library/tzdata/US/Hawaii b/library/tzdata/US/Hawaii
new file mode 100644
index 0000000..6d1af65
--- /dev/null
+++ b/library/tzdata/US/Hawaii
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Pacific/Honolulu)]} {
+ LoadTimeZoneFile Pacific/Honolulu
+}
+set TZData(:US/Hawaii) $TZData(:Pacific/Honolulu)
diff --git a/library/tzdata/US/Indiana-Starke b/library/tzdata/US/Indiana-Starke
new file mode 100644
index 0000000..6ffe0e2
--- /dev/null
+++ b/library/tzdata/US/Indiana-Starke
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Indiana/Knox)]} {
+ LoadTimeZoneFile America/Indiana/Knox
+}
+set TZData(:US/Indiana-Starke) $TZData(:America/Indiana/Knox)
diff --git a/library/tzdata/US/Michigan b/library/tzdata/US/Michigan
new file mode 100644
index 0000000..b15035c
--- /dev/null
+++ b/library/tzdata/US/Michigan
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Detroit)]} {
+ LoadTimeZoneFile America/Detroit
+}
+set TZData(:US/Michigan) $TZData(:America/Detroit)
diff --git a/library/tzdata/US/Mountain b/library/tzdata/US/Mountain
new file mode 100644
index 0000000..b54235f
--- /dev/null
+++ b/library/tzdata/US/Mountain
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Denver)]} {
+ LoadTimeZoneFile America/Denver
+}
+set TZData(:US/Mountain) $TZData(:America/Denver)
diff --git a/library/tzdata/US/Pacific b/library/tzdata/US/Pacific
new file mode 100644
index 0000000..7232215
--- /dev/null
+++ b/library/tzdata/US/Pacific
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Los_Angeles)]} {
+ LoadTimeZoneFile America/Los_Angeles
+}
+set TZData(:US/Pacific) $TZData(:America/Los_Angeles)
diff --git a/library/tzdata/US/Pacific-New b/library/tzdata/US/Pacific-New
new file mode 100644
index 0000000..2eb30f8
--- /dev/null
+++ b/library/tzdata/US/Pacific-New
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(America/Los_Angeles)]} {
+ LoadTimeZoneFile America/Los_Angeles
+}
+set TZData(:US/Pacific-New) $TZData(:America/Los_Angeles)
diff --git a/library/tzdata/US/Samoa b/library/tzdata/US/Samoa
new file mode 100644
index 0000000..ad86b4f
--- /dev/null
+++ b/library/tzdata/US/Samoa
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Pacific/Pago_Pago)]} {
+ LoadTimeZoneFile Pacific/Pago_Pago
+}
+set TZData(:US/Samoa) $TZData(:Pacific/Pago_Pago)
diff --git a/library/tzdata/UTC b/library/tzdata/UTC
new file mode 100644
index 0000000..6d04d96
--- /dev/null
+++ b/library/tzdata/UTC
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Etc/UTC)]} {
+ LoadTimeZoneFile Etc/UTC
+}
+set TZData(:UTC) $TZData(:Etc/UTC)
diff --git a/library/tzdata/Universal b/library/tzdata/Universal
new file mode 100644
index 0000000..4a9ed5e
--- /dev/null
+++ b/library/tzdata/Universal
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Etc/UTC)]} {
+ LoadTimeZoneFile Etc/UTC
+}
+set TZData(:Universal) $TZData(:Etc/UTC)
diff --git a/library/tzdata/W-SU b/library/tzdata/W-SU
new file mode 100644
index 0000000..7e1f613
--- /dev/null
+++ b/library/tzdata/W-SU
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Europe/Moscow)]} {
+ LoadTimeZoneFile Europe/Moscow
+}
+set TZData(:W-SU) $TZData(:Europe/Moscow)
diff --git a/library/tzdata/WET b/library/tzdata/WET
new file mode 100644
index 0000000..60366a3
--- /dev/null
+++ b/library/tzdata/WET
@@ -0,0 +1,251 @@
+# created by tools/tclZIC.tcl - do not edit
+
+set TZData(:WET) {
+ {-9223372036854775808 0 0 WET}
+ {228877200 3600 1 WEST}
+ {243997200 0 0 WET}
+ {260326800 3600 1 WEST}
+ {276051600 0 0 WET}
+ {291776400 3600 1 WEST}
+ {307501200 0 0 WET}
+ {323830800 3600 1 WEST}
+ {338950800 0 0 WET}
+ {354675600 3600 1 WEST}
+ {370400400 0 0 WET}
+ {386125200 3600 1 WEST}
+ {401850000 0 0 WET}
+ {417574800 3600 1 WEST}
+ {433299600 0 0 WET}
+ {449024400 3600 1 WEST}
+ {465354000 0 0 WET}
+ {481078800 3600 1 WEST}
+ {496803600 0 0 WET}
+ {512528400 3600 1 WEST}
+ {528253200 0 0 WET}
+ {543978000 3600 1 WEST}
+ {559702800 0 0 WET}
+ {575427600 3600 1 WEST}
+ {591152400 0 0 WET}
+ {606877200 3600 1 WEST}
+ {622602000 0 0 WET}
+ {638326800 3600 1 WEST}
+ {654656400 0 0 WET}
+ {670381200 3600 1 WEST}
+ {686106000 0 0 WET}
+ {701830800 3600 1 WEST}
+ {717555600 0 0 WET}
+ {733280400 3600 1 WEST}
+ {749005200 0 0 WET}
+ {764730000 3600 1 WEST}
+ {780454800 0 0 WET}
+ {796179600 3600 1 WEST}
+ {811904400 0 0 WET}
+ {828234000 3600 1 WEST}
+ {846378000 0 0 WET}
+ {859683600 3600 1 WEST}
+ {877827600 0 0 WET}
+ {891133200 3600 1 WEST}
+ {909277200 0 0 WET}
+ {922582800 3600 1 WEST}
+ {941331600 0 0 WET}
+ {954032400 3600 1 WEST}
+ {972781200 0 0 WET}
+ {985482000 3600 1 WEST}
+ {1004230800 0 0 WET}
+ {1017536400 3600 1 WEST}
+ {1035680400 0 0 WET}
+ {1048986000 3600 1 WEST}
+ {1067130000 0 0 WET}
+ {1080435600 3600 1 WEST}
+ {1099184400 0 0 WET}
+ {1111885200 3600 1 WEST}
+ {1130634000 0 0 WET}
+ {1143334800 3600 1 WEST}
+ {1162083600 0 0 WET}
+ {1174784400 3600 1 WEST}
+ {1193533200 0 0 WET}
+ {1206838800 3600 1 WEST}
+ {1224982800 0 0 WET}
+ {1238288400 3600 1 WEST}
+ {1256432400 0 0 WET}
+ {1269738000 3600 1 WEST}
+ {1288486800 0 0 WET}
+ {1301187600 3600 1 WEST}
+ {1319936400 0 0 WET}
+ {1332637200 3600 1 WEST}
+ {1351386000 0 0 WET}
+ {1364691600 3600 1 WEST}
+ {1382835600 0 0 WET}
+ {1396141200 3600 1 WEST}
+ {1414285200 0 0 WET}
+ {1427590800 3600 1 WEST}
+ {1445734800 0 0 WET}
+ {1459040400 3600 1 WEST}
+ {1477789200 0 0 WET}
+ {1490490000 3600 1 WEST}
+ {1509238800 0 0 WET}
+ {1521939600 3600 1 WEST}
+ {1540688400 0 0 WET}
+ {1553994000 3600 1 WEST}
+ {1572138000 0 0 WET}
+ {1585443600 3600 1 WEST}
+ {1603587600 0 0 WET}
+ {1616893200 3600 1 WEST}
+ {1635642000 0 0 WET}
+ {1648342800 3600 1 WEST}
+ {1667091600 0 0 WET}
+ {1679792400 3600 1 WEST}
+ {1698541200 0 0 WET}
+ {1711846800 3600 1 WEST}
+ {1729990800 0 0 WET}
+ {1743296400 3600 1 WEST}
+ {1761440400 0 0 WET}
+ {1774746000 3600 1 WEST}
+ {1792890000 0 0 WET}
+ {1806195600 3600 1 WEST}
+ {1824944400 0 0 WET}
+ {1837645200 3600 1 WEST}
+ {1856394000 0 0 WET}
+ {1869094800 3600 1 WEST}
+ {1887843600 0 0 WET}
+ {1901149200 3600 1 WEST}
+ {1919293200 0 0 WET}
+ {1932598800 3600 1 WEST}
+ {1950742800 0 0 WET}
+ {1964048400 3600 1 WEST}
+ {1982797200 0 0 WET}
+ {1995498000 3600 1 WEST}
+ {2014246800 0 0 WET}
+ {2026947600 3600 1 WEST}
+ {2045696400 0 0 WET}
+ {2058397200 3600 1 WEST}
+ {2077146000 0 0 WET}
+ {2090451600 3600 1 WEST}
+ {2108595600 0 0 WET}
+ {2121901200 3600 1 WEST}
+ {2140045200 0 0 WET}
+ {2153350800 3600 1 WEST}
+ {2172099600 0 0 WET}
+ {2184800400 3600 1 WEST}
+ {2203549200 0 0 WET}
+ {2216250000 3600 1 WEST}
+ {2234998800 0 0 WET}
+ {2248304400 3600 1 WEST}
+ {2266448400 0 0 WET}
+ {2279754000 3600 1 WEST}
+ {2297898000 0 0 WET}
+ {2311203600 3600 1 WEST}
+ {2329347600 0 0 WET}
+ {2342653200 3600 1 WEST}
+ {2361402000 0 0 WET}
+ {2374102800 3600 1 WEST}
+ {2392851600 0 0 WET}
+ {2405552400 3600 1 WEST}
+ {2424301200 0 0 WET}
+ {2437606800 3600 1 WEST}
+ {2455750800 0 0 WET}
+ {2469056400 3600 1 WEST}
+ {2487200400 0 0 WET}
+ {2500506000 3600 1 WEST}
+ {2519254800 0 0 WET}
+ {2531955600 3600 1 WEST}
+ {2550704400 0 0 WET}
+ {2563405200 3600 1 WEST}
+ {2582154000 0 0 WET}
+ {2595459600 3600 1 WEST}
+ {2613603600 0 0 WET}
+ {2626909200 3600 1 WEST}
+ {2645053200 0 0 WET}
+ {2658358800 3600 1 WEST}
+ {2676502800 0 0 WET}
+ {2689808400 3600 1 WEST}
+ {2708557200 0 0 WET}
+ {2721258000 3600 1 WEST}
+ {2740006800 0 0 WET}
+ {2752707600 3600 1 WEST}
+ {2771456400 0 0 WET}
+ {2784762000 3600 1 WEST}
+ {2802906000 0 0 WET}
+ {2816211600 3600 1 WEST}
+ {2834355600 0 0 WET}
+ {2847661200 3600 1 WEST}
+ {2866410000 0 0 WET}
+ {2879110800 3600 1 WEST}
+ {2897859600 0 0 WET}
+ {2910560400 3600 1 WEST}
+ {2929309200 0 0 WET}
+ {2942010000 3600 1 WEST}
+ {2960758800 0 0 WET}
+ {2974064400 3600 1 WEST}
+ {2992208400 0 0 WET}
+ {3005514000 3600 1 WEST}
+ {3023658000 0 0 WET}
+ {3036963600 3600 1 WEST}
+ {3055712400 0 0 WET}
+ {3068413200 3600 1 WEST}
+ {3087162000 0 0 WET}
+ {3099862800 3600 1 WEST}
+ {3118611600 0 0 WET}
+ {3131917200 3600 1 WEST}
+ {3150061200 0 0 WET}
+ {3163366800 3600 1 WEST}
+ {3181510800 0 0 WET}
+ {3194816400 3600 1 WEST}
+ {3212960400 0 0 WET}
+ {3226266000 3600 1 WEST}
+ {3245014800 0 0 WET}
+ {3257715600 3600 1 WEST}
+ {3276464400 0 0 WET}
+ {3289165200 3600 1 WEST}
+ {3307914000 0 0 WET}
+ {3321219600 3600 1 WEST}
+ {3339363600 0 0 WET}
+ {3352669200 3600 1 WEST}
+ {3370813200 0 0 WET}
+ {3384118800 3600 1 WEST}
+ {3402867600 0 0 WET}
+ {3415568400 3600 1 WEST}
+ {3434317200 0 0 WET}
+ {3447018000 3600 1 WEST}
+ {3465766800 0 0 WET}
+ {3479072400 3600 1 WEST}
+ {3497216400 0 0 WET}
+ {3510522000 3600 1 WEST}
+ {3528666000 0 0 WET}
+ {3541971600 3600 1 WEST}
+ {3560115600 0 0 WET}
+ {3573421200 3600 1 WEST}
+ {3592170000 0 0 WET}
+ {3604870800 3600 1 WEST}
+ {3623619600 0 0 WET}
+ {3636320400 3600 1 WEST}
+ {3655069200 0 0 WET}
+ {3668374800 3600 1 WEST}
+ {3686518800 0 0 WET}
+ {3699824400 3600 1 WEST}
+ {3717968400 0 0 WET}
+ {3731274000 3600 1 WEST}
+ {3750022800 0 0 WET}
+ {3762723600 3600 1 WEST}
+ {3781472400 0 0 WET}
+ {3794173200 3600 1 WEST}
+ {3812922000 0 0 WET}
+ {3825622800 3600 1 WEST}
+ {3844371600 0 0 WET}
+ {3857677200 3600 1 WEST}
+ {3875821200 0 0 WET}
+ {3889126800 3600 1 WEST}
+ {3907270800 0 0 WET}
+ {3920576400 3600 1 WEST}
+ {3939325200 0 0 WET}
+ {3952026000 3600 1 WEST}
+ {3970774800 0 0 WET}
+ {3983475600 3600 1 WEST}
+ {4002224400 0 0 WET}
+ {4015530000 3600 1 WEST}
+ {4033674000 0 0 WET}
+ {4046979600 3600 1 WEST}
+ {4065123600 0 0 WET}
+ {4078429200 3600 1 WEST}
+ {4096573200 0 0 WET}
+}
diff --git a/library/tzdata/Zulu b/library/tzdata/Zulu
new file mode 100644
index 0000000..e9748e4
--- /dev/null
+++ b/library/tzdata/Zulu
@@ -0,0 +1,5 @@
+# created by tools/tclZIC.tcl - do not edit
+if {![info exists TZData(Etc/UTC)]} {
+ LoadTimeZoneFile Etc/UTC
+}
+set TZData(:Zulu) $TZData(:Etc/UTC)
diff --git a/library/word.tcl b/library/word.tcl
index c4f1683..16a4638 100644
--- a/library/word.tcl
+++ b/library/word.tcl
@@ -1,8 +1,8 @@
# word.tcl --
#
-# This file defines various procedures for computing word boundaries
-# in strings. This file is primarily needed so Tk text and entry
-# widgets behave properly for different platforms.
+# This file defines various procedures for computing word boundaries in
+# strings. This file is primarily needed so Tk text and entry widgets behave
+# properly for different platforms.
#
# Copyright (c) 1996 by Sun Microsystems, Inc.
# Copyright (c) 1998 by Scritpics Corporation.
@@ -11,120 +11,134 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# The following variables are used to determine which characters are
-# interpreted as white space.
+# interpreted as white space.
if {$::tcl_platform(platform) eq "windows"} {
# Windows style - any but a unicode space char
- set tcl_wordchars "\\S"
- set tcl_nonwordchars "\\s"
+ set ::tcl_wordchars {\S}
+ set ::tcl_nonwordchars {\s}
} else {
# Motif style - any unicode word char (number, letter, or underscore)
- set tcl_wordchars "\\w"
- set tcl_nonwordchars "\\W"
+ set ::tcl_wordchars {\w}
+ set ::tcl_nonwordchars {\W}
+}
+
+# Arrange for caches of the real matcher REs to be kept, which enables the REs
+# themselves to be cached for greater performance (and somewhat greater
+# clarity too).
+
+namespace eval ::tcl {
+ variable WordBreakRE
+ array set WordBreakRE {}
+
+ proc UpdateWordBreakREs args {
+ # Ignores the arguments
+ global tcl_wordchars tcl_nonwordchars
+ variable WordBreakRE
+
+ # To keep the RE strings short...
+ set letter $tcl_wordchars
+ set space $tcl_nonwordchars
+
+ set WordBreakRE(after) "$letter$space|$space$letter"
+ set WordBreakRE(before) "^.*($letter$space|$space$letter)"
+ set WordBreakRE(end) "$space*$letter+$space"
+ set WordBreakRE(next) "$letter*$space+$letter"
+ set WordBreakRE(previous) "$space*($letter+)$space*\$"
+ }
+
+ # Initialize the cache
+ UpdateWordBreakREs
+ trace add variable ::tcl_wordchars write ::tcl::UpdateWordBreakREs
+ trace add variable ::tcl_nonwordchars write ::tcl::UpdateWordBreakREs
}
# tcl_wordBreakAfter --
#
-# This procedure returns the index of the first word boundary
-# after the starting point in the given string, or -1 if there
-# are no more boundaries in the given string. The index returned refers
-# to the first character of the pair that comprises a boundary.
+# This procedure returns the index of the first word boundary after the
+# starting point in the given string, or -1 if there are no more boundaries in
+# the given string. The index returned refers to the first character of the
+# pair that comprises a boundary.
#
# Arguments:
# str - String to search.
# start - Index into string specifying starting point.
proc tcl_wordBreakAfter {str start} {
- global tcl_nonwordchars tcl_wordchars
- set str [string range $str $start end]
- if {[regexp -indices "$tcl_wordchars$tcl_nonwordchars|$tcl_nonwordchars$tcl_wordchars" $str result]} {
- return [expr {[lindex $result 1] + $start}]
- }
- return -1
+ variable ::tcl::WordBreakRE
+ set result {-1 -1}
+ regexp -indices -start $start $WordBreakRE(after) $str result
+ return [lindex $result 1]
}
# tcl_wordBreakBefore --
#
-# This procedure returns the index of the first word boundary
-# before the starting point in the given string, or -1 if there
-# are no more boundaries in the given string. The index returned
-# refers to the second character of the pair that comprises a boundary.
+# This procedure returns the index of the first word boundary before the
+# starting point in the given string, or -1 if there are no more boundaries in
+# the given string. The index returned refers to the second character of the
+# pair that comprises a boundary.
#
# Arguments:
# str - String to search.
# start - Index into string specifying starting point.
proc tcl_wordBreakBefore {str start} {
- global tcl_nonwordchars tcl_wordchars
- if {$start eq "end"} {
- set start [string length $str]
- }
- if {[regexp -indices "^.*($tcl_wordchars$tcl_nonwordchars|$tcl_nonwordchars$tcl_wordchars)" [string range $str 0 $start] result]} {
- return [lindex $result 1]
- }
- return -1
+ variable ::tcl::WordBreakRE
+ set result {-1 -1}
+ regexp -indices $WordBreakRE(before) [string range $str 0 $start] result
+ return [lindex $result 1]
}
# tcl_endOfWord --
#
-# This procedure returns the index of the first end-of-word location
-# after a starting index in the given string. An end-of-word location
-# is defined to be the first whitespace character following the first
-# non-whitespace character after the starting point. Returns -1 if
-# there are no more words after the starting point.
+# This procedure returns the index of the first end-of-word location after a
+# starting index in the given string. An end-of-word location is defined to be
+# the first whitespace character following the first non-whitespace character
+# after the starting point. Returns -1 if there are no more words after the
+# starting point.
#
# Arguments:
# str - String to search.
# start - Index into string specifying starting point.
proc tcl_endOfWord {str start} {
- global tcl_nonwordchars tcl_wordchars
- if {[regexp -indices "$tcl_nonwordchars*$tcl_wordchars+$tcl_nonwordchars" \
- [string range $str $start end] result]} {
- return [expr {[lindex $result 1] + $start}]
- }
- return -1
+ variable ::tcl::WordBreakRE
+ set result {-1 -1}
+ regexp -indices -start $start $WordBreakRE(end) $str result
+ return [lindex $result 1]
}
# tcl_startOfNextWord --
#
-# This procedure returns the index of the first start-of-word location
-# after a starting index in the given string. A start-of-word
-# location is defined to be a non-whitespace character following a
-# whitespace character. Returns -1 if there are no more start-of-word
-# locations after the starting point.
+# This procedure returns the index of the first start-of-word location after a
+# starting index in the given string. A start-of-word location is defined to
+# be a non-whitespace character following a whitespace character. Returns -1
+# if there are no more start-of-word locations after the starting point.
#
# Arguments:
# str - String to search.
# start - Index into string specifying starting point.
proc tcl_startOfNextWord {str start} {
- global tcl_nonwordchars tcl_wordchars
- if {[regexp -indices "$tcl_wordchars*$tcl_nonwordchars+$tcl_wordchars" \
- [string range $str $start end] result]} {
- return [expr {[lindex $result 1] + $start}]
- }
- return -1
+ variable ::tcl::WordBreakRE
+ set result {-1 -1}
+ regexp -indices -start $start $WordBreakRE(next) $str result
+ return [lindex $result 1]
}
# tcl_startOfPreviousWord --
#
-# This procedure returns the index of the first start-of-word location
-# before a starting index in the given string.
+# This procedure returns the index of the first start-of-word location before
+# a starting index in the given string.
#
# Arguments:
# str - String to search.
# start - Index into string specifying starting point.
proc tcl_startOfPreviousWord {str start} {
- global tcl_nonwordchars tcl_wordchars
- if {$start eq "end"} {
- set start [string length $str]
- }
- if {[regexp -indices \
- "$tcl_nonwordchars*($tcl_wordchars+)$tcl_nonwordchars*\$" \
- [string range $str 0 [expr {$start - 1}]] result word]} {
- return [lindex $word 0]
- }
- return -1
+ variable ::tcl::WordBreakRE
+ set word {-1 -1}
+ regexp -indices $WordBreakRE(previous) [string range $str 0 $start-1] \
+ result word
+ return [lindex $word 0]
}
diff --git a/libtommath/LICENSE b/libtommath/LICENSE
new file mode 100644
index 0000000..5baa792
--- /dev/null
+++ b/libtommath/LICENSE
@@ -0,0 +1,4 @@
+LibTomMath is hereby released into the Public Domain.
+
+-- Tom St Denis
+
diff --git a/libtommath/bn.ilg b/libtommath/bn.ilg
new file mode 100644
index 0000000..3c859f0
--- /dev/null
+++ b/libtommath/bn.ilg
@@ -0,0 +1,6 @@
+This is makeindex, version 2.14 [02-Oct-2002] (kpathsea + Thai support).
+Scanning input file bn.idx....done (79 entries accepted, 0 rejected).
+Sorting entries....done (511 comparisons).
+Generating output file bn.ind....done (82 lines written, 0 warnings).
+Output written in bn.ind.
+Transcript written in bn.ilg.
diff --git a/libtommath/bn.ind b/libtommath/bn.ind
new file mode 100644
index 0000000..e5f7d4a
--- /dev/null
+++ b/libtommath/bn.ind
@@ -0,0 +1,82 @@
+\begin{theindex}
+
+ \item mp\_add, \hyperpage{29}
+ \item mp\_add\_d, \hyperpage{52}
+ \item mp\_and, \hyperpage{29}
+ \item mp\_clear, \hyperpage{11}
+ \item mp\_clear\_multi, \hyperpage{12}
+ \item mp\_cmp, \hyperpage{24}
+ \item mp\_cmp\_d, \hyperpage{25}
+ \item mp\_cmp\_mag, \hyperpage{23}
+ \item mp\_div, \hyperpage{30}
+ \item mp\_div\_2, \hyperpage{26}
+ \item mp\_div\_2d, \hyperpage{28}
+ \item mp\_div\_d, \hyperpage{52}
+ \item mp\_dr\_reduce, \hyperpage{40}
+ \item mp\_dr\_setup, \hyperpage{40}
+ \item MP\_EQ, \hyperpage{22}
+ \item mp\_error\_to\_string, \hyperpage{10}
+ \item mp\_expt\_d, \hyperpage{43}
+ \item mp\_exptmod, \hyperpage{43}
+ \item mp\_exteuclid, \hyperpage{51}
+ \item mp\_gcd, \hyperpage{51}
+ \item mp\_get\_int, \hyperpage{20}
+ \item mp\_grow, \hyperpage{16}
+ \item MP\_GT, \hyperpage{22}
+ \item mp\_init, \hyperpage{11}
+ \item mp\_init\_copy, \hyperpage{13}
+ \item mp\_init\_multi, \hyperpage{12}
+ \item mp\_init\_set, \hyperpage{21}
+ \item mp\_init\_set\_int, \hyperpage{21}
+ \item mp\_init\_size, \hyperpage{14}
+ \item mp\_int, \hyperpage{10}
+ \item mp\_invmod, \hyperpage{52}
+ \item mp\_jacobi, \hyperpage{52}
+ \item mp\_lcm, \hyperpage{51}
+ \item mp\_lshd, \hyperpage{28}
+ \item MP\_LT, \hyperpage{22}
+ \item MP\_MEM, \hyperpage{9}
+ \item mp\_mod, \hyperpage{35}
+ \item mp\_mod\_d, \hyperpage{52}
+ \item mp\_montgomery\_calc\_normalization, \hyperpage{38}
+ \item mp\_montgomery\_reduce, \hyperpage{37}
+ \item mp\_montgomery\_setup, \hyperpage{37}
+ \item mp\_mul, \hyperpage{31}
+ \item mp\_mul\_2, \hyperpage{26}
+ \item mp\_mul\_2d, \hyperpage{28}
+ \item mp\_mul\_d, \hyperpage{52}
+ \item mp\_n\_root, \hyperpage{44}
+ \item mp\_neg, \hyperpage{29}
+ \item MP\_NO, \hyperpage{9}
+ \item MP\_OKAY, \hyperpage{9}
+ \item mp\_or, \hyperpage{29}
+ \item mp\_prime\_fermat, \hyperpage{45}
+ \item mp\_prime\_is\_divisible, \hyperpage{45}
+ \item mp\_prime\_is\_prime, \hyperpage{46}
+ \item mp\_prime\_miller\_rabin, \hyperpage{45}
+ \item mp\_prime\_next\_prime, \hyperpage{46}
+ \item mp\_prime\_rabin\_miller\_trials, \hyperpage{46}
+ \item mp\_prime\_random, \hyperpage{47}
+ \item mp\_prime\_random\_ex, \hyperpage{47}
+ \item mp\_radix\_size, \hyperpage{49}
+ \item mp\_read\_radix, \hyperpage{49}
+ \item mp\_read\_unsigned\_bin, \hyperpage{50}
+ \item mp\_reduce, \hyperpage{36}
+ \item mp\_reduce\_2k, \hyperpage{41}
+ \item mp\_reduce\_2k\_setup, \hyperpage{41}
+ \item mp\_reduce\_setup, \hyperpage{36}
+ \item mp\_rshd, \hyperpage{28}
+ \item mp\_set, \hyperpage{19}
+ \item mp\_set\_int, \hyperpage{20}
+ \item mp\_shrink, \hyperpage{15}
+ \item mp\_sqr, \hyperpage{33}
+ \item mp\_sub, \hyperpage{29}
+ \item mp\_sub\_d, \hyperpage{52}
+ \item mp\_to\_unsigned\_bin, \hyperpage{50}
+ \item mp\_toradix, \hyperpage{49}
+ \item mp\_unsigned\_bin\_size, \hyperpage{50}
+ \item MP\_VAL, \hyperpage{9}
+ \item mp\_xor, \hyperpage{29}
+ \item MP\_YES, \hyperpage{9}
+
+\end{theindex}
diff --git a/libtommath/bn.pdf b/libtommath/bn.pdf
new file mode 100644
index 0000000..392b649
--- /dev/null
+++ b/libtommath/bn.pdf
Binary files differ
diff --git a/libtommath/bn.tex b/libtommath/bn.tex
new file mode 100644
index 0000000..e8eb994
--- /dev/null
+++ b/libtommath/bn.tex
@@ -0,0 +1,1835 @@
+\documentclass[b5paper]{book}
+\usepackage{hyperref}
+\usepackage{makeidx}
+\usepackage{amssymb}
+\usepackage{color}
+\usepackage{alltt}
+\usepackage{graphicx}
+\usepackage{layout}
+\def\union{\cup}
+\def\intersect{\cap}
+\def\getsrandom{\stackrel{\rm R}{\gets}}
+\def\cross{\times}
+\def\cat{\hspace{0.5em} \| \hspace{0.5em}}
+\def\catn{$\|$}
+\def\divides{\hspace{0.3em} | \hspace{0.3em}}
+\def\nequiv{\not\equiv}
+\def\approx{\raisebox{0.2ex}{\mbox{\small $\sim$}}}
+\def\lcm{{\rm lcm}}
+\def\gcd{{\rm gcd}}
+\def\log{{\rm log}}
+\def\ord{{\rm ord}}
+\def\abs{{\mathit abs}}
+\def\rep{{\mathit rep}}
+\def\mod{{\mathit\ mod\ }}
+\renewcommand{\pmod}[1]{\ ({\rm mod\ }{#1})}
+\newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor}
+\newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil}
+\def\Or{{\rm\ or\ }}
+\def\And{{\rm\ and\ }}
+\def\iff{\hspace{1em}\Longleftrightarrow\hspace{1em}}
+\def\implies{\Rightarrow}
+\def\undefined{{\rm ``undefined"}}
+\def\Proof{\vspace{1ex}\noindent {\bf Proof:}\hspace{1em}}
+\let\oldphi\phi
+\def\phi{\varphi}
+\def\Pr{{\rm Pr}}
+\newcommand{\str}[1]{{\mathbf{#1}}}
+\def\F{{\mathbb F}}
+\def\N{{\mathbb N}}
+\def\Z{{\mathbb Z}}
+\def\R{{\mathbb R}}
+\def\C{{\mathbb C}}
+\def\Q{{\mathbb Q}}
+\definecolor{DGray}{gray}{0.5}
+\newcommand{\emailaddr}[1]{\mbox{$<${#1}$>$}}
+\def\twiddle{\raisebox{0.3ex}{\mbox{\tiny $\sim$}}}
+\def\gap{\vspace{0.5ex}}
+\makeindex
+\begin{document}
+\frontmatter
+\pagestyle{empty}
+\title{LibTomMath User Manual \\ v0.39}
+\author{Tom St Denis \\ tomstdenis@iahu.ca}
+\maketitle
+This text, the library and the accompanying textbook are all hereby placed in the public domain. This book has been
+formatted for B5 [176x250] paper using the \LaTeX{} {\em book} macro package.
+
+\vspace{10cm}
+
+\begin{flushright}Open Source. Open Academia. Open Minds.
+
+\mbox{ }
+
+Tom St Denis,
+
+Ontario, Canada
+\end{flushright}
+
+\tableofcontents
+\listoffigures
+\mainmatter
+\pagestyle{headings}
+\chapter{Introduction}
+\section{What is LibTomMath?}
+LibTomMath is a library of source code which provides a series of efficient and carefully written functions for manipulating
+large integer numbers. It was written in portable ISO C source code so that it will build on any platform with a conforming
+C compiler.
+
+In a nutshell the library was written from scratch with verbose comments to help instruct computer science students how
+to implement ``bignum'' math. However, the resulting code has proven to be very useful. It has been used by numerous
+universities, commercial and open source software developers. It has been used on a variety of platforms ranging from
+Linux and Windows based x86 to ARM based Gameboys and PPC based MacOS machines.
+
+\section{License}
+As of the v0.25 the library source code has been placed in the public domain with every new release. As of the v0.28
+release the textbook ``Implementing Multiple Precision Arithmetic'' has been placed in the public domain with every new
+release as well. This textbook is meant to compliment the project by providing a more solid walkthrough of the development
+algorithms used in the library.
+
+Since both\footnote{Note that the MPI files under mtest/ are copyrighted by Michael Fromberger. They are not required to use LibTomMath.} are in the
+public domain everyone is entitled to do with them as they see fit.
+
+\section{Building LibTomMath}
+
+LibTomMath is meant to be very ``GCC friendly'' as it comes with a makefile well suited for GCC. However, the library will
+also build in MSVC, Borland C out of the box. For any other ISO C compiler a makefile will have to be made by the end
+developer.
+
+\subsection{Static Libraries}
+To build as a static library for GCC issue the following
+\begin{alltt}
+make
+\end{alltt}
+
+command. This will build the library and archive the object files in ``libtommath.a''. Now you link against
+that and include ``tommath.h'' within your programs. Alternatively to build with MSVC issue the following
+\begin{alltt}
+nmake -f makefile.msvc
+\end{alltt}
+
+This will build the library and archive the object files in ``tommath.lib''. This has been tested with MSVC
+version 6.00 with service pack 5.
+
+\subsection{Shared Libraries}
+To build as a shared library for GCC issue the following
+\begin{alltt}
+make -f makefile.shared
+\end{alltt}
+This requires the ``libtool'' package (common on most Linux/BSD systems). It will build LibTomMath as both shared
+and static then install (by default) into /usr/lib as well as install the header files in /usr/include. The shared
+library (resource) will be called ``libtommath.la'' while the static library called ``libtommath.a''. Generally
+you use libtool to link your application against the shared object.
+
+There is limited support for making a ``DLL'' in windows via the ``makefile.cygwin\_dll'' makefile. It requires
+Cygwin to work with since it requires the auto-export/import functionality. The resulting DLL and import library
+``libtommath.dll.a'' can be used to link LibTomMath dynamically to any Windows program using Cygwin.
+
+\subsection{Testing}
+To build the library and the test harness type
+
+\begin{alltt}
+make test
+\end{alltt}
+
+This will build the library, ``test'' and ``mtest/mtest''. The ``test'' program will accept test vectors and verify the
+results. ``mtest/mtest'' will generate test vectors using the MPI library by Michael Fromberger\footnote{A copy of MPI
+is included in the package}. Simply pipe mtest into test using
+
+\begin{alltt}
+mtest/mtest | test
+\end{alltt}
+
+If you do not have a ``/dev/urandom'' style RNG source you will have to write your own PRNG and simply pipe that into
+mtest. For example, if your PRNG program is called ``myprng'' simply invoke
+
+\begin{alltt}
+myprng | mtest/mtest | test
+\end{alltt}
+
+This will output a row of numbers that are increasing. Each column is a different test (such as addition, multiplication, etc)
+that is being performed. The numbers represent how many times the test was invoked. If an error is detected the program
+will exit with a dump of the relevent numbers it was working with.
+
+\section{Build Configuration}
+LibTomMath can configured at build time in three phases we shall call ``depends'', ``tweaks'' and ``trims''.
+Each phase changes how the library is built and they are applied one after another respectively.
+
+To make the system more powerful you can tweak the build process. Classes are defined in the file
+``tommath\_superclass.h''. By default, the symbol ``LTM\_ALL'' shall be defined which simply
+instructs the system to build all of the functions. This is how LibTomMath used to be packaged. This will give you
+access to every function LibTomMath offers.
+
+However, there are cases where such a build is not optional. For instance, you want to perform RSA operations. You
+don't need the vast majority of the library to perform these operations. Aside from LTM\_ALL there is
+another pre--defined class ``SC\_RSA\_1'' which works in conjunction with the RSA from LibTomCrypt. Additional
+classes can be defined base on the need of the user.
+
+\subsection{Build Depends}
+In the file tommath\_class.h you will see a large list of C ``defines'' followed by a series of ``ifdefs''
+which further define symbols. All of the symbols (technically they're macros $\ldots$) represent a given C source
+file. For instance, BN\_MP\_ADD\_C represents the file ``bn\_mp\_add.c''. When a define has been enabled the
+function in the respective file will be compiled and linked into the library. Accordingly when the define
+is absent the file will not be compiled and not contribute any size to the library.
+
+You will also note that the header tommath\_class.h is actually recursively included (it includes itself twice).
+This is to help resolve as many dependencies as possible. In the last pass the symbol LTM\_LAST will be defined.
+This is useful for ``trims''.
+
+\subsection{Build Tweaks}
+A tweak is an algorithm ``alternative''. For example, to provide tradeoffs (usually between size and space).
+They can be enabled at any pass of the configuration phase.
+
+\begin{small}
+\begin{center}
+\begin{tabular}{|l|l|}
+\hline \textbf{Define} & \textbf{Purpose} \\
+\hline BN\_MP\_DIV\_SMALL & Enables a slower, smaller and equally \\
+ & functional mp\_div() function \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+
+\subsection{Build Trims}
+A trim is a manner of removing functionality from a function that is not required. For instance, to perform
+RSA cryptography you only require exponentiation with odd moduli so even moduli support can be safely removed.
+Build trims are meant to be defined on the last pass of the configuration which means they are to be defined
+only if LTM\_LAST has been defined.
+
+\subsubsection{Moduli Related}
+\begin{small}
+\begin{center}
+\begin{tabular}{|l|l|}
+\hline \textbf{Restriction} & \textbf{Undefine} \\
+\hline Exponentiation with odd moduli only & BN\_S\_MP\_EXPTMOD\_C \\
+ & BN\_MP\_REDUCE\_C \\
+ & BN\_MP\_REDUCE\_SETUP\_C \\
+ & BN\_S\_MP\_MUL\_HIGH\_DIGS\_C \\
+ & BN\_FAST\_S\_MP\_MUL\_HIGH\_DIGS\_C \\
+\hline Exponentiation with random odd moduli & (The above plus the following) \\
+ & BN\_MP\_REDUCE\_2K\_C \\
+ & BN\_MP\_REDUCE\_2K\_SETUP\_C \\
+ & BN\_MP\_REDUCE\_IS\_2K\_C \\
+ & BN\_MP\_DR\_IS\_MODULUS\_C \\
+ & BN\_MP\_DR\_REDUCE\_C \\
+ & BN\_MP\_DR\_SETUP\_C \\
+\hline Modular inverse odd moduli only & BN\_MP\_INVMOD\_SLOW\_C \\
+\hline Modular inverse (both, smaller/slower) & BN\_FAST\_MP\_INVMOD\_C \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+
+\subsubsection{Operand Size Related}
+\begin{small}
+\begin{center}
+\begin{tabular}{|l|l|}
+\hline \textbf{Restriction} & \textbf{Undefine} \\
+\hline Moduli $\le 2560$ bits & BN\_MP\_MONTGOMERY\_REDUCE\_C \\
+ & BN\_S\_MP\_MUL\_DIGS\_C \\
+ & BN\_S\_MP\_MUL\_HIGH\_DIGS\_C \\
+ & BN\_S\_MP\_SQR\_C \\
+\hline Polynomial Schmolynomial & BN\_MP\_KARATSUBA\_MUL\_C \\
+ & BN\_MP\_KARATSUBA\_SQR\_C \\
+ & BN\_MP\_TOOM\_MUL\_C \\
+ & BN\_MP\_TOOM\_SQR\_C \\
+
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+
+
+\section{Purpose of LibTomMath}
+Unlike GNU MP (GMP) Library, LIP, OpenSSL or various other commercial kits (Miracl), LibTomMath was not written with
+bleeding edge performance in mind. First and foremost LibTomMath was written to be entirely open. Not only is the
+source code public domain (unlike various other GPL/etc licensed code), not only is the code freely downloadable but the
+source code is also accessible for computer science students attempting to learn ``BigNum'' or multiple precision
+arithmetic techniques.
+
+LibTomMath was written to be an instructive collection of source code. This is why there are many comments, only one
+function per source file and often I use a ``middle-road'' approach where I don't cut corners for an extra 2\% speed
+increase.
+
+Source code alone cannot really teach how the algorithms work which is why I also wrote a textbook that accompanies
+the library (beat that!).
+
+So you may be thinking ``should I use LibTomMath?'' and the answer is a definite maybe. Let me tabulate what I think
+are the pros and cons of LibTomMath by comparing it to the math routines from GnuPG\footnote{GnuPG v1.2.3 versus LibTomMath v0.28}.
+
+\newpage\begin{figure}[here]
+\begin{small}
+\begin{center}
+\begin{tabular}{|l|c|c|l|}
+\hline \textbf{Criteria} & \textbf{Pro} & \textbf{Con} & \textbf{Notes} \\
+\hline Few lines of code per file & X & & GnuPG $ = 300.9$, LibTomMath $ = 71.97$ \\
+\hline Commented function prototypes & X && GnuPG function names are cryptic. \\
+\hline Speed && X & LibTomMath is slower. \\
+\hline Totally free & X & & GPL has unfavourable restrictions.\\
+\hline Large function base & X & & GnuPG is barebones. \\
+\hline Five modular reduction algorithms & X & & Faster modular exponentiation for a variety of moduli. \\
+\hline Portable & X & & GnuPG requires configuration to build. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{LibTomMath Valuation}
+\end{figure}
+
+It may seem odd to compare LibTomMath to GnuPG since the math in GnuPG is only a small portion of the entire application.
+However, LibTomMath was written with cryptography in mind. It provides essentially all of the functions a cryptosystem
+would require when working with large integers.
+
+So it may feel tempting to just rip the math code out of GnuPG (or GnuMP where it was taken from originally) in your
+own application but I think there are reasons not to. While LibTomMath is slower than libraries such as GnuMP it is
+not normally significantly slower. On x86 machines the difference is normally a factor of two when performing modular
+exponentiations. It depends largely on the processor, compiler and the moduli being used.
+
+Essentially the only time you wouldn't use LibTomMath is when blazing speed is the primary concern. However,
+on the other side of the coin LibTomMath offers you a totally free (public domain) well structured math library
+that is very flexible, complete and performs well in resource contrained environments. Fast RSA for example can
+be performed with as little as 8KB of ram for data (again depending on build options).
+
+\chapter{Getting Started with LibTomMath}
+\section{Building Programs}
+In order to use LibTomMath you must include ``tommath.h'' and link against the appropriate library file (typically
+libtommath.a). There is no library initialization required and the entire library is thread safe.
+
+\section{Return Codes}
+There are three possible return codes a function may return.
+
+\index{MP\_OKAY}\index{MP\_YES}\index{MP\_NO}\index{MP\_VAL}\index{MP\_MEM}
+\begin{figure}[here!]
+\begin{center}
+\begin{small}
+\begin{tabular}{|l|l|}
+\hline \textbf{Code} & \textbf{Meaning} \\
+\hline MP\_OKAY & The function succeeded. \\
+\hline MP\_VAL & The function input was invalid. \\
+\hline MP\_MEM & Heap memory exhausted. \\
+\hline &\\
+\hline MP\_YES & Response is yes. \\
+\hline MP\_NO & Response is no. \\
+\hline
+\end{tabular}
+\end{small}
+\end{center}
+\caption{Return Codes}
+\end{figure}
+
+The last two codes listed are not actually ``return'ed'' by a function. They are placed in an integer (the caller must
+provide the address of an integer it can store to) which the caller can access. To convert one of the three return codes
+to a string use the following function.
+
+\index{mp\_error\_to\_string}
+\begin{alltt}
+char *mp_error_to_string(int code);
+\end{alltt}
+
+This will return a pointer to a string which describes the given error code. It will not work for the return codes
+MP\_YES and MP\_NO.
+
+\section{Data Types}
+The basic ``multiple precision integer'' type is known as the ``mp\_int'' within LibTomMath. This data type is used to
+organize all of the data required to manipulate the integer it represents. Within LibTomMath it has been prototyped
+as the following.
+
+\index{mp\_int}
+\begin{alltt}
+typedef struct \{
+ int used, alloc, sign;
+ mp_digit *dp;
+\} mp_int;
+\end{alltt}
+
+Where ``mp\_digit'' is a data type that represents individual digits of the integer. By default, an mp\_digit is the
+ISO C ``unsigned long'' data type and each digit is $28-$bits long. The mp\_digit type can be configured to suit other
+platforms by defining the appropriate macros.
+
+All LTM functions that use the mp\_int type will expect a pointer to mp\_int structure. You must allocate memory to
+hold the structure itself by yourself (whether off stack or heap it doesn't matter). The very first thing that must be
+done to use an mp\_int is that it must be initialized.
+
+\section{Function Organization}
+
+The arithmetic functions of the library are all organized to have the same style prototype. That is source operands
+are passed on the left and the destination is on the right. For instance,
+
+\begin{alltt}
+mp_add(&a, &b, &c); /* c = a + b */
+mp_mul(&a, &a, &c); /* c = a * a */
+mp_div(&a, &b, &c, &d); /* c = [a/b], d = a mod b */
+\end{alltt}
+
+Another feature of the way the functions have been implemented is that source operands can be destination operands as well.
+For instance,
+
+\begin{alltt}
+mp_add(&a, &b, &b); /* b = a + b */
+mp_div(&a, &b, &a, &c); /* a = [a/b], c = a mod b */
+\end{alltt}
+
+This allows operands to be re-used which can make programming simpler.
+
+\section{Initialization}
+\subsection{Single Initialization}
+A single mp\_int can be initialized with the ``mp\_init'' function.
+
+\index{mp\_init}
+\begin{alltt}
+int mp_init (mp_int * a);
+\end{alltt}
+
+This function expects a pointer to an mp\_int structure and will initialize the members of the structure so the mp\_int
+represents the default integer which is zero. If the functions returns MP\_OKAY then the mp\_int is ready to be used
+by the other LibTomMath functions.
+
+\begin{small} \begin{alltt}
+int main(void)
+\{
+ mp_int number;
+ int result;
+
+ if ((result = mp_init(&number)) != MP_OKAY) \{
+ printf("Error initializing the number. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* use the number */
+
+ return EXIT_SUCCESS;
+\}
+\end{alltt} \end{small}
+
+\subsection{Single Free}
+When you are finished with an mp\_int it is ideal to return the heap it used back to the system. The following function
+provides this functionality.
+
+\index{mp\_clear}
+\begin{alltt}
+void mp_clear (mp_int * a);
+\end{alltt}
+
+The function expects a pointer to a previously initialized mp\_int structure and frees the heap it uses. It sets the
+pointer\footnote{The ``dp'' member.} within the mp\_int to \textbf{NULL} which is used to prevent double free situations.
+Is is legal to call mp\_clear() twice on the same mp\_int in a row.
+
+\begin{small} \begin{alltt}
+int main(void)
+\{
+ mp_int number;
+ int result;
+
+ if ((result = mp_init(&number)) != MP_OKAY) \{
+ printf("Error initializing the number. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* use the number */
+
+ /* We're done with it. */
+ mp_clear(&number);
+
+ return EXIT_SUCCESS;
+\}
+\end{alltt} \end{small}
+
+\subsection{Multiple Initializations}
+Certain algorithms require more than one large integer. In these instances it is ideal to initialize all of the mp\_int
+variables in an ``all or nothing'' fashion. That is, they are either all initialized successfully or they are all
+not initialized.
+
+The mp\_init\_multi() function provides this functionality.
+
+\index{mp\_init\_multi} \index{mp\_clear\_multi}
+\begin{alltt}
+int mp_init_multi(mp_int *mp, ...);
+\end{alltt}
+
+It accepts a \textbf{NULL} terminated list of pointers to mp\_int structures. It will attempt to initialize them all
+at once. If the function returns MP\_OKAY then all of the mp\_int variables are ready to use, otherwise none of them
+are available for use. A complementary mp\_clear\_multi() function allows multiple mp\_int variables to be free'd
+from the heap at the same time.
+
+\begin{small} \begin{alltt}
+int main(void)
+\{
+ mp_int num1, num2, num3;
+ int result;
+
+ if ((result = mp_init_multi(&num1,
+ &num2,
+ &num3, NULL)) != MP\_OKAY) \{
+ printf("Error initializing the numbers. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* use the numbers */
+
+ /* We're done with them. */
+ mp_clear_multi(&num1, &num2, &num3, NULL);
+
+ return EXIT_SUCCESS;
+\}
+\end{alltt} \end{small}
+
+\subsection{Other Initializers}
+To initialized and make a copy of an mp\_int the mp\_init\_copy() function has been provided.
+
+\index{mp\_init\_copy}
+\begin{alltt}
+int mp_init_copy (mp_int * a, mp_int * b);
+\end{alltt}
+
+This function will initialize $a$ and make it a copy of $b$ if all goes well.
+
+\begin{small} \begin{alltt}
+int main(void)
+\{
+ mp_int num1, num2;
+ int result;
+
+ /* initialize and do work on num1 ... */
+
+ /* We want a copy of num1 in num2 now */
+ if ((result = mp_init_copy(&num2, &num1)) != MP_OKAY) \{
+ printf("Error initializing the copy. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* now num2 is ready and contains a copy of num1 */
+
+ /* We're done with them. */
+ mp_clear_multi(&num1, &num2, NULL);
+
+ return EXIT_SUCCESS;
+\}
+\end{alltt} \end{small}
+
+Another less common initializer is mp\_init\_size() which allows the user to initialize an mp\_int with a given
+default number of digits. By default, all initializers allocate \textbf{MP\_PREC} digits. This function lets
+you override this behaviour.
+
+\index{mp\_init\_size}
+\begin{alltt}
+int mp_init_size (mp_int * a, int size);
+\end{alltt}
+
+The $size$ parameter must be greater than zero. If the function succeeds the mp\_int $a$ will be initialized
+to have $size$ digits (which are all initially zero).
+
+\begin{small} \begin{alltt}
+int main(void)
+\{
+ mp_int number;
+ int result;
+
+ /* we need a 60-digit number */
+ if ((result = mp_init_size(&number, 60)) != MP_OKAY) \{
+ printf("Error initializing the number. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* use the number */
+
+ return EXIT_SUCCESS;
+\}
+\end{alltt} \end{small}
+
+\section{Maintenance Functions}
+
+\subsection{Reducing Memory Usage}
+When an mp\_int is in a state where it won't be changed again\footnote{A Diffie-Hellman modulus for instance.} excess
+digits can be removed to return memory to the heap with the mp\_shrink() function.
+
+\index{mp\_shrink}
+\begin{alltt}
+int mp_shrink (mp_int * a);
+\end{alltt}
+
+This will remove excess digits of the mp\_int $a$. If the operation fails the mp\_int should be intact without the
+excess digits being removed. Note that you can use a shrunk mp\_int in further computations, however, such operations
+will require heap operations which can be slow. It is not ideal to shrink mp\_int variables that you will further
+modify in the system (unless you are seriously low on memory).
+
+\begin{small} \begin{alltt}
+int main(void)
+\{
+ mp_int number;
+ int result;
+
+ if ((result = mp_init(&number)) != MP_OKAY) \{
+ printf("Error initializing the number. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* use the number [e.g. pre-computation] */
+
+ /* We're done with it for now. */
+ if ((result = mp_shrink(&number)) != MP_OKAY) \{
+ printf("Error shrinking the number. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* use it .... */
+
+
+ /* we're done with it. */
+ mp_clear(&number);
+
+ return EXIT_SUCCESS;
+\}
+\end{alltt} \end{small}
+
+\subsection{Adding additional digits}
+
+Within the mp\_int structure are two parameters which control the limitations of the array of digits that represent
+the integer the mp\_int is meant to equal. The \textit{used} parameter dictates how many digits are significant, that is,
+contribute to the value of the mp\_int. The \textit{alloc} parameter dictates how many digits are currently available in
+the array. If you need to perform an operation that requires more digits you will have to mp\_grow() the mp\_int to
+your desired size.
+
+\index{mp\_grow}
+\begin{alltt}
+int mp_grow (mp_int * a, int size);
+\end{alltt}
+
+This will grow the array of digits of $a$ to $size$. If the \textit{alloc} parameter is already bigger than
+$size$ the function will not do anything.
+
+\begin{small} \begin{alltt}
+int main(void)
+\{
+ mp_int number;
+ int result;
+
+ if ((result = mp_init(&number)) != MP_OKAY) \{
+ printf("Error initializing the number. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* use the number */
+
+ /* We need to add 20 digits to the number */
+ if ((result = mp_grow(&number, number.alloc + 20)) != MP_OKAY) \{
+ printf("Error growing the number. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+
+ /* use the number */
+
+ /* we're done with it. */
+ mp_clear(&number);
+
+ return EXIT_SUCCESS;
+\}
+\end{alltt} \end{small}
+
+\chapter{Basic Operations}
+\section{Small Constants}
+Setting mp\_ints to small constants is a relatively common operation. To accomodate these instances there are two
+small constant assignment functions. The first function is used to set a single digit constant while the second sets
+an ISO C style ``unsigned long'' constant. The reason for both functions is efficiency. Setting a single digit is quick but the
+domain of a digit can change (it's always at least $0 \ldots 127$).
+
+\subsection{Single Digit}
+
+Setting a single digit can be accomplished with the following function.
+
+\index{mp\_set}
+\begin{alltt}
+void mp_set (mp_int * a, mp_digit b);
+\end{alltt}
+
+This will zero the contents of $a$ and make it represent an integer equal to the value of $b$. Note that this
+function has a return type of \textbf{void}. It cannot cause an error so it is safe to assume the function
+succeeded.
+
+\begin{small} \begin{alltt}
+int main(void)
+\{
+ mp_int number;
+ int result;
+
+ if ((result = mp_init(&number)) != MP_OKAY) \{
+ printf("Error initializing the number. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* set the number to 5 */
+ mp_set(&number, 5);
+
+ /* we're done with it. */
+ mp_clear(&number);
+
+ return EXIT_SUCCESS;
+\}
+\end{alltt} \end{small}
+
+\subsection{Long Constants}
+
+To set a constant that is the size of an ISO C ``unsigned long'' and larger than a single digit the following function
+can be used.
+
+\index{mp\_set\_int}
+\begin{alltt}
+int mp_set_int (mp_int * a, unsigned long b);
+\end{alltt}
+
+This will assign the value of the 32-bit variable $b$ to the mp\_int $a$. Unlike mp\_set() this function will always
+accept a 32-bit input regardless of the size of a single digit. However, since the value may span several digits
+this function can fail if it runs out of heap memory.
+
+To get the ``unsigned long'' copy of an mp\_int the following function can be used.
+
+\index{mp\_get\_int}
+\begin{alltt}
+unsigned long mp_get_int (mp_int * a);
+\end{alltt}
+
+This will return the 32 least significant bits of the mp\_int $a$.
+
+\begin{small} \begin{alltt}
+int main(void)
+\{
+ mp_int number;
+ int result;
+
+ if ((result = mp_init(&number)) != MP_OKAY) \{
+ printf("Error initializing the number. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* set the number to 654321 (note this is bigger than 127) */
+ if ((result = mp_set_int(&number, 654321)) != MP_OKAY) \{
+ printf("Error setting the value of the number. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ printf("number == \%lu", mp_get_int(&number));
+
+ /* we're done with it. */
+ mp_clear(&number);
+
+ return EXIT_SUCCESS;
+\}
+\end{alltt} \end{small}
+
+This should output the following if the program succeeds.
+
+\begin{alltt}
+number == 654321
+\end{alltt}
+
+\subsection{Initialize and Setting Constants}
+To both initialize and set small constants the following two functions are available.
+\index{mp\_init\_set} \index{mp\_init\_set\_int}
+\begin{alltt}
+int mp_init_set (mp_int * a, mp_digit b);
+int mp_init_set_int (mp_int * a, unsigned long b);
+\end{alltt}
+
+Both functions work like the previous counterparts except they first mp\_init $a$ before setting the values.
+
+\begin{alltt}
+int main(void)
+\{
+ mp_int number1, number2;
+ int result;
+
+ /* initialize and set a single digit */
+ if ((result = mp_init_set(&number1, 100)) != MP_OKAY) \{
+ printf("Error setting number1: \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* initialize and set a long */
+ if ((result = mp_init_set_int(&number2, 1023)) != MP_OKAY) \{
+ printf("Error setting number2: \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* display */
+ printf("Number1, Number2 == \%lu, \%lu",
+ mp_get_int(&number1), mp_get_int(&number2));
+
+ /* clear */
+ mp_clear_multi(&number1, &number2, NULL);
+
+ return EXIT_SUCCESS;
+\}
+\end{alltt}
+
+If this program succeeds it shall output.
+\begin{alltt}
+Number1, Number2 == 100, 1023
+\end{alltt}
+
+\section{Comparisons}
+
+Comparisons in LibTomMath are always performed in a ``left to right'' fashion. There are three possible return codes
+for any comparison.
+
+\index{MP\_GT} \index{MP\_EQ} \index{MP\_LT}
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{|c|c|}
+\hline \textbf{Result Code} & \textbf{Meaning} \\
+\hline MP\_GT & $a > b$ \\
+\hline MP\_EQ & $a = b$ \\
+\hline MP\_LT & $a < b$ \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Comparison Codes for $a, b$}
+\label{fig:CMP}
+\end{figure}
+
+In figure \ref{fig:CMP} two integers $a$ and $b$ are being compared. In this case $a$ is said to be ``to the left'' of
+$b$.
+
+\subsection{Unsigned comparison}
+
+An unsigned comparison considers only the digits themselves and not the associated \textit{sign} flag of the
+mp\_int structures. This is analogous to an absolute comparison. The function mp\_cmp\_mag() will compare two
+mp\_int variables based on their digits only.
+
+\index{mp\_cmp\_mag}
+\begin{alltt}
+int mp_cmp_mag(mp_int * a, mp_int * b);
+\end{alltt}
+This will compare $a$ to $b$ placing $a$ to the left of $b$. This function cannot fail and will return one of the
+three compare codes listed in figure \ref{fig:CMP}.
+
+\begin{small} \begin{alltt}
+int main(void)
+\{
+ mp_int number1, number2;
+ int result;
+
+ if ((result = mp_init_multi(&number1, &number2, NULL)) != MP_OKAY) \{
+ printf("Error initializing the numbers. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* set the number1 to 5 */
+ mp_set(&number1, 5);
+
+ /* set the number2 to -6 */
+ mp_set(&number2, 6);
+ if ((result = mp_neg(&number2, &number2)) != MP_OKAY) \{
+ printf("Error negating number2. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ switch(mp_cmp_mag(&number1, &number2)) \{
+ case MP_GT: printf("|number1| > |number2|"); break;
+ case MP_EQ: printf("|number1| = |number2|"); break;
+ case MP_LT: printf("|number1| < |number2|"); break;
+ \}
+
+ /* we're done with it. */
+ mp_clear_multi(&number1, &number2, NULL);
+
+ return EXIT_SUCCESS;
+\}
+\end{alltt} \end{small}
+
+If this program\footnote{This function uses the mp\_neg() function which is discussed in section \ref{sec:NEG}.} completes
+successfully it should print the following.
+
+\begin{alltt}
+|number1| < |number2|
+\end{alltt}
+
+This is because $\vert -6 \vert = 6$ and obviously $5 < 6$.
+
+\subsection{Signed comparison}
+
+To compare two mp\_int variables based on their signed value the mp\_cmp() function is provided.
+
+\index{mp\_cmp}
+\begin{alltt}
+int mp_cmp(mp_int * a, mp_int * b);
+\end{alltt}
+
+This will compare $a$ to the left of $b$. It will first compare the signs of the two mp\_int variables. If they
+differ it will return immediately based on their signs. If the signs are equal then it will compare the digits
+individually. This function will return one of the compare conditions codes listed in figure \ref{fig:CMP}.
+
+\begin{small} \begin{alltt}
+int main(void)
+\{
+ mp_int number1, number2;
+ int result;
+
+ if ((result = mp_init_multi(&number1, &number2, NULL)) != MP_OKAY) \{
+ printf("Error initializing the numbers. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* set the number1 to 5 */
+ mp_set(&number1, 5);
+
+ /* set the number2 to -6 */
+ mp_set(&number2, 6);
+ if ((result = mp_neg(&number2, &number2)) != MP_OKAY) \{
+ printf("Error negating number2. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ switch(mp_cmp(&number1, &number2)) \{
+ case MP_GT: printf("number1 > number2"); break;
+ case MP_EQ: printf("number1 = number2"); break;
+ case MP_LT: printf("number1 < number2"); break;
+ \}
+
+ /* we're done with it. */
+ mp_clear_multi(&number1, &number2, NULL);
+
+ return EXIT_SUCCESS;
+\}
+\end{alltt} \end{small}
+
+If this program\footnote{This function uses the mp\_neg() function which is discussed in section \ref{sec:NEG}.} completes
+successfully it should print the following.
+
+\begin{alltt}
+number1 > number2
+\end{alltt}
+
+\subsection{Single Digit}
+
+To compare a single digit against an mp\_int the following function has been provided.
+
+\index{mp\_cmp\_d}
+\begin{alltt}
+int mp_cmp_d(mp_int * a, mp_digit b);
+\end{alltt}
+
+This will compare $a$ to the left of $b$ using a signed comparison. Note that it will always treat $b$ as
+positive. This function is rather handy when you have to compare against small values such as $1$ (which often
+comes up in cryptography). The function cannot fail and will return one of the tree compare condition codes
+listed in figure \ref{fig:CMP}.
+
+
+\begin{small} \begin{alltt}
+int main(void)
+\{
+ mp_int number;
+ int result;
+
+ if ((result = mp_init(&number)) != MP_OKAY) \{
+ printf("Error initializing the number. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* set the number to 5 */
+ mp_set(&number, 5);
+
+ switch(mp_cmp_d(&number, 7)) \{
+ case MP_GT: printf("number > 7"); break;
+ case MP_EQ: printf("number = 7"); break;
+ case MP_LT: printf("number < 7"); break;
+ \}
+
+ /* we're done with it. */
+ mp_clear(&number);
+
+ return EXIT_SUCCESS;
+\}
+\end{alltt} \end{small}
+
+If this program functions properly it will print out the following.
+
+\begin{alltt}
+number < 7
+\end{alltt}
+
+\section{Logical Operations}
+
+Logical operations are operations that can be performed either with simple shifts or boolean operators such as
+AND, XOR and OR directly. These operations are very quick.
+
+\subsection{Multiplication by two}
+
+Multiplications and divisions by any power of two can be performed with quick logical shifts either left or
+right depending on the operation.
+
+When multiplying or dividing by two a special case routine can be used which are as follows.
+\index{mp\_mul\_2} \index{mp\_div\_2}
+\begin{alltt}
+int mp_mul_2(mp_int * a, mp_int * b);
+int mp_div_2(mp_int * a, mp_int * b);
+\end{alltt}
+
+The former will assign twice $a$ to $b$ while the latter will assign half $a$ to $b$. These functions are fast
+since the shift counts and maskes are hardcoded into the routines.
+
+\begin{small} \begin{alltt}
+int main(void)
+\{
+ mp_int number;
+ int result;
+
+ if ((result = mp_init(&number)) != MP_OKAY) \{
+ printf("Error initializing the number. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* set the number to 5 */
+ mp_set(&number, 5);
+
+ /* multiply by two */
+ if ((result = mp\_mul\_2(&number, &number)) != MP_OKAY) \{
+ printf("Error multiplying the number. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+ switch(mp_cmp_d(&number, 7)) \{
+ case MP_GT: printf("2*number > 7"); break;
+ case MP_EQ: printf("2*number = 7"); break;
+ case MP_LT: printf("2*number < 7"); break;
+ \}
+
+ /* now divide by two */
+ if ((result = mp\_div\_2(&number, &number)) != MP_OKAY) \{
+ printf("Error dividing the number. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+ switch(mp_cmp_d(&number, 7)) \{
+ case MP_GT: printf("2*number/2 > 7"); break;
+ case MP_EQ: printf("2*number/2 = 7"); break;
+ case MP_LT: printf("2*number/2 < 7"); break;
+ \}
+
+ /* we're done with it. */
+ mp_clear(&number);
+
+ return EXIT_SUCCESS;
+\}
+\end{alltt} \end{small}
+
+If this program is successful it will print out the following text.
+
+\begin{alltt}
+2*number > 7
+2*number/2 < 7
+\end{alltt}
+
+Since $10 > 7$ and $5 < 7$. To multiply by a power of two the following function can be used.
+
+\index{mp\_mul\_2d}
+\begin{alltt}
+int mp_mul_2d(mp_int * a, int b, mp_int * c);
+\end{alltt}
+
+This will multiply $a$ by $2^b$ and store the result in ``c''. If the value of $b$ is less than or equal to
+zero the function will copy $a$ to ``c'' without performing any further actions.
+
+To divide by a power of two use the following.
+
+\index{mp\_div\_2d}
+\begin{alltt}
+int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d);
+\end{alltt}
+Which will divide $a$ by $2^b$, store the quotient in ``c'' and the remainder in ``d'. If $b \le 0$ then the
+function simply copies $a$ over to ``c'' and zeroes $d$. The variable $d$ may be passed as a \textbf{NULL}
+value to signal that the remainder is not desired.
+
+\subsection{Polynomial Basis Operations}
+
+Strictly speaking the organization of the integers within the mp\_int structures is what is known as a
+``polynomial basis''. This simply means a field element is stored by divisions of a radix. For example, if
+$f(x) = \sum_{i=0}^{k} y_ix^k$ for any vector $\vec y$ then the array of digits in $\vec y$ are said to be
+the polynomial basis representation of $z$ if $f(\beta) = z$ for a given radix $\beta$.
+
+To multiply by the polynomial $g(x) = x$ all you have todo is shift the digits of the basis left one place. The
+following function provides this operation.
+
+\index{mp\_lshd}
+\begin{alltt}
+int mp_lshd (mp_int * a, int b);
+\end{alltt}
+
+This will multiply $a$ in place by $x^b$ which is equivalent to shifting the digits left $b$ places and inserting zeroes
+in the least significant digits. Similarly to divide by a power of $x$ the following function is provided.
+
+\index{mp\_rshd}
+\begin{alltt}
+void mp_rshd (mp_int * a, int b)
+\end{alltt}
+This will divide $a$ in place by $x^b$ and discard the remainder. This function cannot fail as it performs the operations
+in place and no new digits are required to complete it.
+
+\subsection{AND, OR and XOR Operations}
+
+While AND, OR and XOR operations are not typical ``bignum functions'' they can be useful in several instances. The
+three functions are prototyped as follows.
+
+\index{mp\_or} \index{mp\_and} \index{mp\_xor}
+\begin{alltt}
+int mp_or (mp_int * a, mp_int * b, mp_int * c);
+int mp_and (mp_int * a, mp_int * b, mp_int * c);
+int mp_xor (mp_int * a, mp_int * b, mp_int * c);
+\end{alltt}
+
+Which compute $c = a \odot b$ where $\odot$ is one of OR, AND or XOR.
+
+\section{Addition and Subtraction}
+
+To compute an addition or subtraction the following two functions can be used.
+
+\index{mp\_add} \index{mp\_sub}
+\begin{alltt}
+int mp_add (mp_int * a, mp_int * b, mp_int * c);
+int mp_sub (mp_int * a, mp_int * b, mp_int * c)
+\end{alltt}
+
+Which perform $c = a \odot b$ where $\odot$ is one of signed addition or subtraction. The operations are fully sign
+aware.
+
+\section{Sign Manipulation}
+\subsection{Negation}
+\label{sec:NEG}
+Simple integer negation can be performed with the following.
+
+\index{mp\_neg}
+\begin{alltt}
+int mp_neg (mp_int * a, mp_int * b);
+\end{alltt}
+
+Which assigns $-a$ to $b$.
+
+\subsection{Absolute}
+Simple integer absolutes can be performed with the following.
+
+\index{mp\_neg}
+\begin{alltt}
+int mp_abs (mp_int * a, mp_int * b);
+\end{alltt}
+
+Which assigns $\vert a \vert$ to $b$.
+
+\section{Integer Division and Remainder}
+To perform a complete and general integer division with remainder use the following function.
+
+\index{mp\_div}
+\begin{alltt}
+int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d);
+\end{alltt}
+
+This divides $a$ by $b$ and stores the quotient in $c$ and $d$. The signed quotient is computed such that
+$bc + d = a$. Note that either of $c$ or $d$ can be set to \textbf{NULL} if their value is not required. If
+$b$ is zero the function returns \textbf{MP\_VAL}.
+
+
+\chapter{Multiplication and Squaring}
+\section{Multiplication}
+A full signed integer multiplication can be performed with the following.
+\index{mp\_mul}
+\begin{alltt}
+int mp_mul (mp_int * a, mp_int * b, mp_int * c);
+\end{alltt}
+Which assigns the full signed product $ab$ to $c$. This function actually breaks into one of four cases which are
+specific multiplication routines optimized for given parameters. First there are the Toom-Cook multiplications which
+should only be used with very large inputs. This is followed by the Karatsuba multiplications which are for moderate
+sized inputs. Then followed by the Comba and baseline multipliers.
+
+Fortunately for the developer you don't really need to know this unless you really want to fine tune the system. mp\_mul()
+will determine on its own\footnote{Some tweaking may be required.} what routine to use automatically when it is called.
+
+\begin{alltt}
+int main(void)
+\{
+ mp_int number1, number2;
+ int result;
+
+ /* Initialize the numbers */
+ if ((result = mp_init_multi(&number1,
+ &number2, NULL)) != MP_OKAY) \{
+ printf("Error initializing the numbers. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* set the terms */
+ if ((result = mp_set_int(&number, 257)) != MP_OKAY) \{
+ printf("Error setting number1. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ if ((result = mp_set_int(&number2, 1023)) != MP_OKAY) \{
+ printf("Error setting number2. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* multiply them */
+ if ((result = mp_mul(&number1, &number2,
+ &number1)) != MP_OKAY) \{
+ printf("Error multiplying terms. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* display */
+ printf("number1 * number2 == \%lu", mp_get_int(&number1));
+
+ /* free terms and return */
+ mp_clear_multi(&number1, &number2, NULL);
+
+ return EXIT_SUCCESS;
+\}
+\end{alltt}
+
+If this program succeeds it shall output the following.
+
+\begin{alltt}
+number1 * number2 == 262911
+\end{alltt}
+
+\section{Squaring}
+Since squaring can be performed faster than multiplication it is performed it's own function instead of just using
+mp\_mul().
+
+\index{mp\_sqr}
+\begin{alltt}
+int mp_sqr (mp_int * a, mp_int * b);
+\end{alltt}
+
+Will square $a$ and store it in $b$. Like the case of multiplication there are four different squaring
+algorithms all which can be called from mp\_sqr(). It is ideal to use mp\_sqr over mp\_mul when squaring terms because
+of the speed difference.
+
+\section{Tuning Polynomial Basis Routines}
+
+Both of the Toom-Cook and Karatsuba multiplication algorithms are faster than the traditional $O(n^2)$ approach that
+the Comba and baseline algorithms use. At $O(n^{1.464973})$ and $O(n^{1.584962})$ running times respectively they require
+considerably less work. For example, a 10000-digit multiplication would take roughly 724,000 single precision
+multiplications with Toom-Cook or 100,000,000 single precision multiplications with the standard Comba (a factor
+of 138).
+
+So why not always use Karatsuba or Toom-Cook? The simple answer is that they have so much overhead that they're not
+actually faster than Comba until you hit distinct ``cutoff'' points. For Karatsuba with the default configuration,
+GCC 3.3.1 and an Athlon XP processor the cutoff point is roughly 110 digits (about 70 for the Intel P4). That is, at
+110 digits Karatsuba and Comba multiplications just about break even and for 110+ digits Karatsuba is faster.
+
+Toom-Cook has incredible overhead and is probably only useful for very large inputs. So far no known cutoff points
+exist and for the most part I just set the cutoff points very high to make sure they're not called.
+
+A demo program in the ``etc/'' directory of the project called ``tune.c'' can be used to find the cutoff points. This
+can be built with GCC as follows
+
+\begin{alltt}
+make XXX
+\end{alltt}
+Where ``XXX'' is one of the following entries from the table \ref{fig:tuning}.
+
+\begin{figure}[here]
+\begin{center}
+\begin{small}
+\begin{tabular}{|l|l|}
+\hline \textbf{Value of XXX} & \textbf{Meaning} \\
+\hline tune & Builds portable tuning application \\
+\hline tune86 & Builds x86 (pentium and up) program for COFF \\
+\hline tune86c & Builds x86 program for Cygwin \\
+\hline tune86l & Builds x86 program for Linux (ELF format) \\
+\hline
+\end{tabular}
+\end{small}
+\end{center}
+\caption{Build Names for Tuning Programs}
+\label{fig:tuning}
+\end{figure}
+
+When the program is running it will output a series of measurements for different cutoff points. It will first find
+good Karatsuba squaring and multiplication points. Then it proceeds to find Toom-Cook points. Note that the Toom-Cook
+tuning takes a very long time as the cutoff points are likely to be very high.
+
+\chapter{Modular Reduction}
+
+Modular reduction is process of taking the remainder of one quantity divided by another. Expressed
+as (\ref{eqn:mod}) the modular reduction is equivalent to the remainder of $b$ divided by $c$.
+
+\begin{equation}
+a \equiv b \mbox{ (mod }c\mbox{)}
+\label{eqn:mod}
+\end{equation}
+
+Of particular interest to cryptography are reductions where $b$ is limited to the range $0 \le b < c^2$ since particularly
+fast reduction algorithms can be written for the limited range.
+
+Note that one of the four optimized reduction algorithms are automatically chosen in the modular exponentiation
+algorithm mp\_exptmod when an appropriate modulus is detected.
+
+\section{Straight Division}
+In order to effect an arbitrary modular reduction the following algorithm is provided.
+
+\index{mp\_mod}
+\begin{alltt}
+int mp_mod(mp_int *a, mp_int *b, mp_int *c);
+\end{alltt}
+
+This reduces $a$ modulo $b$ and stores the result in $c$. The sign of $c$ shall agree with the sign
+of $b$. This algorithm accepts an input $a$ of any range and is not limited by $0 \le a < b^2$.
+
+\section{Barrett Reduction}
+
+Barrett reduction is a generic optimized reduction algorithm that requires pre--computation to achieve
+a decent speedup over straight division. First a $\mu$ value must be precomputed with the following function.
+
+\index{mp\_reduce\_setup}
+\begin{alltt}
+int mp_reduce_setup(mp_int *a, mp_int *b);
+\end{alltt}
+
+Given a modulus in $b$ this produces the required $\mu$ value in $a$. For any given modulus this only has to
+be computed once. Modular reduction can now be performed with the following.
+
+\index{mp\_reduce}
+\begin{alltt}
+int mp_reduce(mp_int *a, mp_int *b, mp_int *c);
+\end{alltt}
+
+This will reduce $a$ in place modulo $b$ with the precomputed $\mu$ value in $c$. $a$ must be in the range
+$0 \le a < b^2$.
+
+\begin{alltt}
+int main(void)
+\{
+ mp_int a, b, c, mu;
+ int result;
+
+ /* initialize a,b to desired values, mp_init mu,
+ * c and set c to 1...we want to compute a^3 mod b
+ */
+
+ /* get mu value */
+ if ((result = mp_reduce_setup(&mu, b)) != MP_OKAY) \{
+ printf("Error getting mu. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* square a to get c = a^2 */
+ if ((result = mp_sqr(&a, &c)) != MP_OKAY) \{
+ printf("Error squaring. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* now reduce `c' modulo b */
+ if ((result = mp_reduce(&c, &b, &mu)) != MP_OKAY) \{
+ printf("Error reducing. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* multiply a to get c = a^3 */
+ if ((result = mp_mul(&a, &c, &c)) != MP_OKAY) \{
+ printf("Error reducing. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* now reduce `c' modulo b */
+ if ((result = mp_reduce(&c, &b, &mu)) != MP_OKAY) \{
+ printf("Error reducing. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* c now equals a^3 mod b */
+
+ return EXIT_SUCCESS;
+\}
+\end{alltt}
+
+This program will calculate $a^3 \mbox{ mod }b$ if all the functions succeed.
+
+\section{Montgomery Reduction}
+
+Montgomery is a specialized reduction algorithm for any odd moduli. Like Barrett reduction a pre--computation
+step is required. This is accomplished with the following.
+
+\index{mp\_montgomery\_setup}
+\begin{alltt}
+int mp_montgomery_setup(mp_int *a, mp_digit *mp);
+\end{alltt}
+
+For the given odd moduli $a$ the precomputation value is placed in $mp$. The reduction is computed with the
+following.
+
+\index{mp\_montgomery\_reduce}
+\begin{alltt}
+int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
+\end{alltt}
+This reduces $a$ in place modulo $m$ with the pre--computed value $mp$. $a$ must be in the range
+$0 \le a < b^2$.
+
+Montgomery reduction is faster than Barrett reduction for moduli smaller than the ``comba'' limit. With the default
+setup for instance, the limit is $127$ digits ($3556$--bits). Note that this function is not limited to
+$127$ digits just that it falls back to a baseline algorithm after that point.
+
+An important observation is that this reduction does not return $a \mbox{ mod }m$ but $aR^{-1} \mbox{ mod }m$
+where $R = \beta^n$, $n$ is the n number of digits in $m$ and $\beta$ is radix used (default is $2^{28}$).
+
+To quickly calculate $R$ the following function was provided.
+
+\index{mp\_montgomery\_calc\_normalization}
+\begin{alltt}
+int mp_montgomery_calc_normalization(mp_int *a, mp_int *b);
+\end{alltt}
+Which calculates $a = R$ for the odd moduli $b$ without using multiplication or division.
+
+The normal modus operandi for Montgomery reductions is to normalize the integers before entering the system. For
+example, to calculate $a^3 \mbox { mod }b$ using Montgomery reduction the value of $a$ can be normalized by
+multiplying it by $R$. Consider the following code snippet.
+
+\begin{alltt}
+int main(void)
+\{
+ mp_int a, b, c, R;
+ mp_digit mp;
+ int result;
+
+ /* initialize a,b to desired values,
+ * mp_init R, c and set c to 1....
+ */
+
+ /* get normalization */
+ if ((result = mp_montgomery_calc_normalization(&R, b)) != MP_OKAY) \{
+ printf("Error getting norm. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* get mp value */
+ if ((result = mp_montgomery_setup(&c, &mp)) != MP_OKAY) \{
+ printf("Error setting up montgomery. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* normalize `a' so now a is equal to aR */
+ if ((result = mp_mulmod(&a, &R, &b, &a)) != MP_OKAY) \{
+ printf("Error computing aR. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* square a to get c = a^2R^2 */
+ if ((result = mp_sqr(&a, &c)) != MP_OKAY) \{
+ printf("Error squaring. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* now reduce `c' back down to c = a^2R^2 * R^-1 == a^2R */
+ if ((result = mp_montgomery_reduce(&c, &b, mp)) != MP_OKAY) \{
+ printf("Error reducing. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* multiply a to get c = a^3R^2 */
+ if ((result = mp_mul(&a, &c, &c)) != MP_OKAY) \{
+ printf("Error reducing. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* now reduce `c' back down to c = a^3R^2 * R^-1 == a^3R */
+ if ((result = mp_montgomery_reduce(&c, &b, mp)) != MP_OKAY) \{
+ printf("Error reducing. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* now reduce (again) `c' back down to c = a^3R * R^-1 == a^3 */
+ if ((result = mp_montgomery_reduce(&c, &b, mp)) != MP_OKAY) \{
+ printf("Error reducing. \%s",
+ mp_error_to_string(result));
+ return EXIT_FAILURE;
+ \}
+
+ /* c now equals a^3 mod b */
+
+ return EXIT_SUCCESS;
+\}
+\end{alltt}
+
+This particular example does not look too efficient but it demonstrates the point of the algorithm. By
+normalizing the inputs the reduced results are always of the form $aR$ for some variable $a$. This allows
+a single final reduction to correct for the normalization and the fast reduction used within the algorithm.
+
+For more details consider examining the file \textit{bn\_mp\_exptmod\_fast.c}.
+
+\section{Restricted Dimminished Radix}
+
+``Dimminished Radix'' reduction refers to reduction with respect to moduli that are ameniable to simple
+digit shifting and small multiplications. In this case the ``restricted'' variant refers to moduli of the
+form $\beta^k - p$ for some $k \ge 0$ and $0 < p < \beta$ where $\beta$ is the radix (default to $2^{28}$).
+
+As in the case of Montgomery reduction there is a pre--computation phase required for a given modulus.
+
+\index{mp\_dr\_setup}
+\begin{alltt}
+void mp_dr_setup(mp_int *a, mp_digit *d);
+\end{alltt}
+
+This computes the value required for the modulus $a$ and stores it in $d$. This function cannot fail
+and does not return any error codes. After the pre--computation a reduction can be performed with the
+following.
+
+\index{mp\_dr\_reduce}
+\begin{alltt}
+int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp);
+\end{alltt}
+
+This reduces $a$ in place modulo $b$ with the pre--computed value $mp$. $b$ must be of a restricted
+dimminished radix form and $a$ must be in the range $0 \le a < b^2$. Dimminished radix reductions are
+much faster than both Barrett and Montgomery reductions as they have a much lower asymtotic running time.
+
+Since the moduli are restricted this algorithm is not particularly useful for something like Rabin, RSA or
+BBS cryptographic purposes. This reduction algorithm is useful for Diffie-Hellman and ECC where fixed
+primes are acceptable.
+
+Note that unlike Montgomery reduction there is no normalization process. The result of this function is
+equal to the correct residue.
+
+\section{Unrestricted Dimminshed Radix}
+
+Unrestricted reductions work much like the restricted counterparts except in this case the moduli is of the
+form $2^k - p$ for $0 < p < \beta$. In this sense the unrestricted reductions are more flexible as they
+can be applied to a wider range of numbers.
+
+\index{mp\_reduce\_2k\_setup}
+\begin{alltt}
+int mp_reduce_2k_setup(mp_int *a, mp_digit *d);
+\end{alltt}
+
+This will compute the required $d$ value for the given moduli $a$.
+
+\index{mp\_reduce\_2k}
+\begin{alltt}
+int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);
+\end{alltt}
+
+This will reduce $a$ in place modulo $n$ with the pre--computed value $d$. From my experience this routine is
+slower than mp\_dr\_reduce but faster for most moduli sizes than the Montgomery reduction.
+
+\chapter{Exponentiation}
+\section{Single Digit Exponentiation}
+\index{mp\_expt\_d}
+\begin{alltt}
+int mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
+\end{alltt}
+This computes $c = a^b$ using a simple binary left-to-right algorithm. It is faster than repeated multiplications by
+$a$ for all values of $b$ greater than three.
+
+\section{Modular Exponentiation}
+\index{mp\_exptmod}
+\begin{alltt}
+int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
+\end{alltt}
+This computes $Y \equiv G^X \mbox{ (mod }P\mbox{)}$ using a variable width sliding window algorithm. This function
+will automatically detect the fastest modular reduction technique to use during the operation. For negative values of
+$X$ the operation is performed as $Y \equiv (G^{-1} \mbox{ mod }P)^{\vert X \vert} \mbox{ (mod }P\mbox{)}$ provided that
+$gcd(G, P) = 1$.
+
+This function is actually a shell around the two internal exponentiation functions. This routine will automatically
+detect when Barrett, Montgomery, Restricted and Unrestricted Dimminished Radix based exponentiation can be used. Generally
+moduli of the a ``restricted dimminished radix'' form lead to the fastest modular exponentiations. Followed by Montgomery
+and the other two algorithms.
+
+\section{Root Finding}
+\index{mp\_n\_root}
+\begin{alltt}
+int mp_n_root (mp_int * a, mp_digit b, mp_int * c)
+\end{alltt}
+This computes $c = a^{1/b}$ such that $c^b \le a$ and $(c+1)^b > a$. The implementation of this function is not
+ideal for values of $b$ greater than three. It will work but become very slow. So unless you are working with very small
+numbers (less than 1000 bits) I'd avoid $b > 3$ situations. Will return a positive root only for even roots and return
+a root with the sign of the input for odd roots. For example, performing $4^{1/2}$ will return $2$ whereas $(-8)^{1/3}$
+will return $-2$.
+
+This algorithm uses the ``Newton Approximation'' method and will converge on the correct root fairly quickly. Since
+the algorithm requires raising $a$ to the power of $b$ it is not ideal to attempt to find roots for large
+values of $b$. If particularly large roots are required then a factor method could be used instead. For example,
+$a^{1/16}$ is equivalent to $\left (a^{1/4} \right)^{1/4}$ or simply
+$\left ( \left ( \left ( a^{1/2} \right )^{1/2} \right )^{1/2} \right )^{1/2}$
+
+\chapter{Prime Numbers}
+\section{Trial Division}
+\index{mp\_prime\_is\_divisible}
+\begin{alltt}
+int mp_prime_is_divisible (mp_int * a, int *result)
+\end{alltt}
+This will attempt to evenly divide $a$ by a list of primes\footnote{Default is the first 256 primes.} and store the
+outcome in ``result''. That is if $result = 0$ then $a$ is not divisible by the primes, otherwise it is. Note that
+if the function does not return \textbf{MP\_OKAY} the value in ``result'' should be considered undefined\footnote{Currently
+the default is to set it to zero first.}.
+
+\section{Fermat Test}
+\index{mp\_prime\_fermat}
+\begin{alltt}
+int mp_prime_fermat (mp_int * a, mp_int * b, int *result)
+\end{alltt}
+Performs a Fermat primality test to the base $b$. That is it computes $b^a \mbox{ mod }a$ and tests whether the value is
+equal to $b$ or not. If the values are equal then $a$ is probably prime and $result$ is set to one. Otherwise $result$
+is set to zero.
+
+\section{Miller-Rabin Test}
+\index{mp\_prime\_miller\_rabin}
+\begin{alltt}
+int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
+\end{alltt}
+Performs a Miller-Rabin test to the base $b$ of $a$. This test is much stronger than the Fermat test and is very hard to
+fool (besides with Carmichael numbers). If $a$ passes the test (therefore is probably prime) $result$ is set to one.
+Otherwise $result$ is set to zero.
+
+Note that is suggested that you use the Miller-Rabin test instead of the Fermat test since all of the failures of
+Miller-Rabin are a subset of the failures of the Fermat test.
+
+\subsection{Required Number of Tests}
+Generally to ensure a number is very likely to be prime you have to perform the Miller-Rabin with at least a half-dozen
+or so unique bases. However, it has been proven that the probability of failure goes down as the size of the input goes up.
+This is why a simple function has been provided to help out.
+
+\index{mp\_prime\_rabin\_miller\_trials}
+\begin{alltt}
+int mp_prime_rabin_miller_trials(int size)
+\end{alltt}
+This returns the number of trials required for a $2^{-96}$ (or lower) probability of failure for a given ``size'' expressed
+in bits. This comes in handy specially since larger numbers are slower to test. For example, a 512-bit number would
+require ten tests whereas a 1024-bit number would only require four tests.
+
+You should always still perform a trial division before a Miller-Rabin test though.
+
+\section{Primality Testing}
+\index{mp\_prime\_is\_prime}
+\begin{alltt}
+int mp_prime_is_prime (mp_int * a, int t, int *result)
+\end{alltt}
+This will perform a trial division followed by $t$ rounds of Miller-Rabin tests on $a$ and store the result in $result$.
+If $a$ passes all of the tests $result$ is set to one, otherwise it is set to zero. Note that $t$ is bounded by
+$1 \le t < PRIME\_SIZE$ where $PRIME\_SIZE$ is the number of primes in the prime number table (by default this is $256$).
+
+\section{Next Prime}
+\index{mp\_prime\_next\_prime}
+\begin{alltt}
+int mp_prime_next_prime(mp_int *a, int t, int bbs_style)
+\end{alltt}
+This finds the next prime after $a$ that passes mp\_prime\_is\_prime() with $t$ tests. Set $bbs\_style$ to one if you
+want only the next prime congruent to $3 \mbox{ mod } 4$, otherwise set it to zero to find any next prime.
+
+\section{Random Primes}
+\index{mp\_prime\_random}
+\begin{alltt}
+int mp_prime_random(mp_int *a, int t, int size, int bbs,
+ ltm_prime_callback cb, void *dat)
+\end{alltt}
+This will find a prime greater than $256^{size}$ which can be ``bbs\_style'' or not depending on $bbs$ and must pass
+$t$ rounds of tests. The ``ltm\_prime\_callback'' is a typedef for
+
+\begin{alltt}
+typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);
+\end{alltt}
+
+Which is a function that must read $len$ bytes (and return the amount stored) into $dst$. The $dat$ variable is simply
+copied from the original input. It can be used to pass RNG context data to the callback. The function
+mp\_prime\_random() is more suitable for generating primes which must be secret (as in the case of RSA) since there
+is no skew on the least significant bits.
+
+\textit{Note:} As of v0.30 of the LibTomMath library this function has been deprecated. It is still available
+but users are encouraged to use the new mp\_prime\_random\_ex() function instead.
+
+\subsection{Extended Generation}
+\index{mp\_prime\_random\_ex}
+\begin{alltt}
+int mp_prime_random_ex(mp_int *a, int t,
+ int size, int flags,
+ ltm_prime_callback cb, void *dat);
+\end{alltt}
+This will generate a prime in $a$ using $t$ tests of the primality testing algorithms. The variable $size$
+specifies the bit length of the prime desired. The variable $flags$ specifies one of several options available
+(see fig. \ref{fig:primeopts}) which can be OR'ed together. The callback parameters are used as in
+mp\_prime\_random().
+
+\begin{figure}[here]
+\begin{center}
+\begin{small}
+\begin{tabular}{|r|l|}
+\hline \textbf{Flag} & \textbf{Meaning} \\
+\hline LTM\_PRIME\_BBS & Make the prime congruent to $3$ modulo $4$ \\
+\hline LTM\_PRIME\_SAFE & Make a prime $p$ such that $(p - 1)/2$ is also prime. \\
+ & This option implies LTM\_PRIME\_BBS as well. \\
+\hline LTM\_PRIME\_2MSB\_OFF & Makes sure that the bit adjacent to the most significant bit \\
+ & Is forced to zero. \\
+\hline LTM\_PRIME\_2MSB\_ON & Makes sure that the bit adjacent to the most significant bit \\
+ & Is forced to one. \\
+\hline
+\end{tabular}
+\end{small}
+\end{center}
+\caption{Primality Generation Options}
+\label{fig:primeopts}
+\end{figure}
+
+\chapter{Input and Output}
+\section{ASCII Conversions}
+\subsection{To ASCII}
+\index{mp\_toradix}
+\begin{alltt}
+int mp_toradix (mp_int * a, char *str, int radix);
+\end{alltt}
+This still store $a$ in ``str'' as a base-``radix'' string of ASCII chars. This function appends a NUL character
+to terminate the string. Valid values of ``radix'' line in the range $[2, 64]$. To determine the size (exact) required
+by the conversion before storing any data use the following function.
+
+\index{mp\_radix\_size}
+\begin{alltt}
+int mp_radix_size (mp_int * a, int radix, int *size)
+\end{alltt}
+This stores in ``size'' the number of characters (including space for the NUL terminator) required. Upon error this
+function returns an error code and ``size'' will be zero.
+
+\subsection{From ASCII}
+\index{mp\_read\_radix}
+\begin{alltt}
+int mp_read_radix (mp_int * a, char *str, int radix);
+\end{alltt}
+This will read the base-``radix'' NUL terminated string from ``str'' into $a$. It will stop reading when it reads a
+character it does not recognize (which happens to include th NUL char... imagine that...). A single leading $-$ sign
+can be used to denote a negative number.
+
+\section{Binary Conversions}
+
+Converting an mp\_int to and from binary is another keen idea.
+
+\index{mp\_unsigned\_bin\_size}
+\begin{alltt}
+int mp_unsigned_bin_size(mp_int *a);
+\end{alltt}
+
+This will return the number of bytes (octets) required to store the unsigned copy of the integer $a$.
+
+\index{mp\_to\_unsigned\_bin}
+\begin{alltt}
+int mp_to_unsigned_bin(mp_int *a, unsigned char *b);
+\end{alltt}
+This will store $a$ into the buffer $b$ in big--endian format. Fortunately this is exactly what DER (or is it ASN?)
+requires. It does not store the sign of the integer.
+
+\index{mp\_read\_unsigned\_bin}
+\begin{alltt}
+int mp_read_unsigned_bin(mp_int *a, unsigned char *b, int c);
+\end{alltt}
+This will read in an unsigned big--endian array of bytes (octets) from $b$ of length $c$ into $a$. The resulting
+integer $a$ will always be positive.
+
+For those who acknowledge the existence of negative numbers (heretic!) there are ``signed'' versions of the
+previous functions.
+
+\begin{alltt}
+int mp_signed_bin_size(mp_int *a);
+int mp_read_signed_bin(mp_int *a, unsigned char *b, int c);
+int mp_to_signed_bin(mp_int *a, unsigned char *b);
+\end{alltt}
+They operate essentially the same as the unsigned copies except they prefix the data with zero or non--zero
+byte depending on the sign. If the sign is zpos (e.g. not negative) the prefix is zero, otherwise the prefix
+is non--zero.
+
+\chapter{Algebraic Functions}
+\section{Extended Euclidean Algorithm}
+\index{mp\_exteuclid}
+\begin{alltt}
+int mp_exteuclid(mp_int *a, mp_int *b,
+ mp_int *U1, mp_int *U2, mp_int *U3);
+\end{alltt}
+
+This finds the triple U1/U2/U3 using the Extended Euclidean algorithm such that the following equation holds.
+
+\begin{equation}
+a \cdot U1 + b \cdot U2 = U3
+\end{equation}
+
+Any of the U1/U2/U3 paramters can be set to \textbf{NULL} if they are not desired.
+
+\section{Greatest Common Divisor}
+\index{mp\_gcd}
+\begin{alltt}
+int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
+\end{alltt}
+This will compute the greatest common divisor of $a$ and $b$ and store it in $c$.
+
+\section{Least Common Multiple}
+\index{mp\_lcm}
+\begin{alltt}
+int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
+\end{alltt}
+This will compute the least common multiple of $a$ and $b$ and store it in $c$.
+
+\section{Jacobi Symbol}
+\index{mp\_jacobi}
+\begin{alltt}
+int mp_jacobi (mp_int * a, mp_int * p, int *c)
+\end{alltt}
+This will compute the Jacobi symbol for $a$ with respect to $p$. If $p$ is prime this essentially computes the Legendre
+symbol. The result is stored in $c$ and can take on one of three values $\lbrace -1, 0, 1 \rbrace$. If $p$ is prime
+then the result will be $-1$ when $a$ is not a quadratic residue modulo $p$. The result will be $0$ if $a$ divides $p$
+and the result will be $1$ if $a$ is a quadratic residue modulo $p$.
+
+\section{Modular Inverse}
+\index{mp\_invmod}
+\begin{alltt}
+int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+\end{alltt}
+Computes the multiplicative inverse of $a$ modulo $b$ and stores the result in $c$ such that $ac \equiv 1 \mbox{ (mod }b\mbox{)}$.
+
+\section{Single Digit Functions}
+
+For those using small numbers (\textit{snicker snicker}) there are several ``helper'' functions
+
+\index{mp\_add\_d} \index{mp\_sub\_d} \index{mp\_mul\_d} \index{mp\_div\_d} \index{mp\_mod\_d}
+\begin{alltt}
+int mp_add_d(mp_int *a, mp_digit b, mp_int *c);
+int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);
+int mp_mul_d(mp_int *a, mp_digit b, mp_int *c);
+int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d);
+int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c);
+\end{alltt}
+
+These work like the full mp\_int capable variants except the second parameter $b$ is a mp\_digit. These
+functions fairly handy if you have to work with relatively small numbers since you will not have to allocate
+an entire mp\_int to store a number like $1$ or $2$.
+
+\input{bn.ind}
+
+\end{document}
diff --git a/libtommath/bn_error.c b/libtommath/bn_error.c
new file mode 100644
index 0000000..6393bb0
--- /dev/null
+++ b/libtommath/bn_error.c
@@ -0,0 +1,43 @@
+#include <tommath.h>
+#ifdef BN_ERROR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+static const struct {
+ int code;
+ char *msg;
+} msgs[] = {
+ { MP_OKAY, "Successful" },
+ { MP_MEM, "Out of heap" },
+ { MP_VAL, "Value out of range" }
+};
+
+/* return a char * string for a given code */
+char *mp_error_to_string(int code)
+{
+ int x;
+
+ /* scan the lookup table for the given message */
+ for (x = 0; x < (int)(sizeof(msgs) / sizeof(msgs[0])); x++) {
+ if (msgs[x].code == code) {
+ return msgs[x].msg;
+ }
+ }
+
+ /* generic reply for invalid code */
+ return "Invalid error code";
+}
+
+#endif
diff --git a/libtommath/bn_fast_mp_invmod.c b/libtommath/bn_fast_mp_invmod.c
new file mode 100644
index 0000000..fafd9dc
--- /dev/null
+++ b/libtommath/bn_fast_mp_invmod.c
@@ -0,0 +1,144 @@
+#include <tommath.h>
+#ifdef BN_FAST_MP_INVMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* computes the modular inverse via binary extended euclidean algorithm,
+ * that is c = 1/a mod b
+ *
+ * Based on slow invmod except this is optimized for the case where b is
+ * odd as per HAC Note 14.64 on pp. 610
+ */
+int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int x, y, u, v, B, D;
+ int res, neg;
+
+ /* 2. [modified] b must be odd */
+ if (mp_iseven (b) == 1) {
+ return MP_VAL;
+ }
+
+ /* init all our temps */
+ if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) {
+ return res;
+ }
+
+ /* x == modulus, y == value to invert */
+ if ((res = mp_copy (b, &x)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ /* we need y = |a| */
+ if ((res = mp_mod (a, b, &y)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+ if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ mp_set (&D, 1);
+
+top:
+ /* 4. while u is even do */
+ while (mp_iseven (&u) == 1) {
+ /* 4.1 u = u/2 */
+ if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ /* 4.2 if B is odd then */
+ if (mp_isodd (&B) == 1) {
+ if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ /* B = B/2 */
+ if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* 5. while v is even do */
+ while (mp_iseven (&v) == 1) {
+ /* 5.1 v = v/2 */
+ if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ /* 5.2 if D is odd then */
+ if (mp_isodd (&D) == 1) {
+ /* D = (D-x)/2 */
+ if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ /* D = D/2 */
+ if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* 6. if u >= v then */
+ if (mp_cmp (&u, &v) != MP_LT) {
+ /* u = u - v, B = B - D */
+ if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ } else {
+ /* v - v - u, D = D - B */
+ if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* if not zero goto step 4 */
+ if (mp_iszero (&u) == 0) {
+ goto top;
+ }
+
+ /* now a = C, b = D, gcd == g*v */
+
+ /* if v != 1 then there is no inverse */
+ if (mp_cmp_d (&v, 1) != MP_EQ) {
+ res = MP_VAL;
+ goto LBL_ERR;
+ }
+
+ /* b is now the inverse */
+ neg = a->sign;
+ while (D.sign == MP_NEG) {
+ if ((res = mp_add (&D, b, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ mp_exch (&D, c);
+ c->sign = neg;
+ res = MP_OKAY;
+
+LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL);
+ return res;
+}
+#endif
diff --git a/libtommath/bn_fast_mp_montgomery_reduce.c b/libtommath/bn_fast_mp_montgomery_reduce.c
new file mode 100644
index 0000000..e941dc2
--- /dev/null
+++ b/libtommath/bn_fast_mp_montgomery_reduce.c
@@ -0,0 +1,168 @@
+#include <tommath.h>
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction
+ *
+ * This is an optimized implementation of montgomery_reduce
+ * which uses the comba method to quickly calculate the columns of the
+ * reduction.
+ *
+ * Based on Algorithm 14.32 on pp.601 of HAC.
+*/
+int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+ int ix, res, olduse;
+ mp_word W[MP_WARRAY];
+
+ /* get old used count */
+ olduse = x->used;
+
+ /* grow a as required */
+ if (x->alloc < n->used + 1) {
+ if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* first we have to get the digits of the input into
+ * an array of double precision words W[...]
+ */
+ {
+ register mp_word *_W;
+ register mp_digit *tmpx;
+
+ /* alias for the W[] array */
+ _W = W;
+
+ /* alias for the digits of x*/
+ tmpx = x->dp;
+
+ /* copy the digits of a into W[0..a->used-1] */
+ for (ix = 0; ix < x->used; ix++) {
+ *_W++ = *tmpx++;
+ }
+
+ /* zero the high words of W[a->used..m->used*2] */
+ for (; ix < n->used * 2 + 1; ix++) {
+ *_W++ = 0;
+ }
+ }
+
+ /* now we proceed to zero successive digits
+ * from the least significant upwards
+ */
+ for (ix = 0; ix < n->used; ix++) {
+ /* mu = ai * m' mod b
+ *
+ * We avoid a double precision multiplication (which isn't required)
+ * by casting the value down to a mp_digit. Note this requires
+ * that W[ix-1] have the carry cleared (see after the inner loop)
+ */
+ register mp_digit mu;
+ mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);
+
+ /* a = a + mu * m * b**i
+ *
+ * This is computed in place and on the fly. The multiplication
+ * by b**i is handled by offseting which columns the results
+ * are added to.
+ *
+ * Note the comba method normally doesn't handle carries in the
+ * inner loop In this case we fix the carry from the previous
+ * column since the Montgomery reduction requires digits of the
+ * result (so far) [see above] to work. This is
+ * handled by fixing up one carry after the inner loop. The
+ * carry fixups are done in order so after these loops the
+ * first m->used words of W[] have the carries fixed
+ */
+ {
+ register int iy;
+ register mp_digit *tmpn;
+ register mp_word *_W;
+
+ /* alias for the digits of the modulus */
+ tmpn = n->dp;
+
+ /* Alias for the columns set by an offset of ix */
+ _W = W + ix;
+
+ /* inner loop */
+ for (iy = 0; iy < n->used; iy++) {
+ *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
+ }
+ }
+
+ /* now fix carry for next digit, W[ix+1] */
+ W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
+ }
+
+ /* now we have to propagate the carries and
+ * shift the words downward [all those least
+ * significant digits we zeroed].
+ */
+ {
+ register mp_digit *tmpx;
+ register mp_word *_W, *_W1;
+
+ /* nox fix rest of carries */
+
+ /* alias for current word */
+ _W1 = W + ix;
+
+ /* alias for next word, where the carry goes */
+ _W = W + ++ix;
+
+ for (; ix <= n->used * 2 + 1; ix++) {
+ *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
+ }
+
+ /* copy out, A = A/b**n
+ *
+ * The result is A/b**n but instead of converting from an
+ * array of mp_word to mp_digit than calling mp_rshd
+ * we just copy them in the right order
+ */
+
+ /* alias for destination word */
+ tmpx = x->dp;
+
+ /* alias for shifted double precision result */
+ _W = W + n->used;
+
+ for (ix = 0; ix < n->used + 1; ix++) {
+ *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
+ }
+
+ /* zero oldused digits, if the input a was larger than
+ * m->used+1 we'll have to clear the digits
+ */
+ for (; ix < olduse; ix++) {
+ *tmpx++ = 0;
+ }
+ }
+
+ /* set the max used and clamp */
+ x->used = n->used + 1;
+ mp_clamp (x);
+
+ /* if A >= m then A = A - m */
+ if (mp_cmp_mag (x, n) != MP_LT) {
+ return s_mp_sub (x, n, x);
+ }
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_fast_s_mp_mul_digs.c b/libtommath/bn_fast_s_mp_mul_digs.c
new file mode 100644
index 0000000..ab157b9
--- /dev/null
+++ b/libtommath/bn_fast_s_mp_mul_digs.c
@@ -0,0 +1,103 @@
+#include <tommath.h>
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* Fast (comba) multiplier
+ *
+ * This is the fast column-array [comba] multiplier. It is
+ * designed to compute the columns of the product first
+ * then handle the carries afterwards. This has the effect
+ * of making the nested loops that compute the columns very
+ * simple and schedulable on super-scalar processors.
+ *
+ * This has been modified to produce a variable number of
+ * digits of output so if say only a half-product is required
+ * you don't have to compute the upper half (a feature
+ * required for fast Barrett reduction).
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ *
+ */
+int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+ int olduse, res, pa, ix, iz;
+ mp_digit W[MP_WARRAY];
+ register mp_word _W;
+
+ /* grow the destination as required */
+ if (c->alloc < digs) {
+ if ((res = mp_grow (c, digs)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* number of output digits to produce */
+ pa = MIN(digs, a->used + b->used);
+
+ /* clear the carry */
+ _W = 0;
+ for (ix = 0; ix < pa; ix++) {
+ int tx, ty;
+ int iy;
+ mp_digit *tmpx, *tmpy;
+
+ /* get offsets into the two bignums */
+ ty = MIN(b->used-1, ix);
+ tx = ix - ty;
+
+ /* setup temp aliases */
+ tmpx = a->dp + tx;
+ tmpy = b->dp + ty;
+
+ /* this is the number of times the loop will iterrate, essentially
+ while (tx++ < a->used && ty-- >= 0) { ... }
+ */
+ iy = MIN(a->used-tx, ty+1);
+
+ /* execute loop */
+ for (iz = 0; iz < iy; ++iz) {
+ _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+
+ }
+
+ /* store term */
+ W[ix] = ((mp_digit)_W) & MP_MASK;
+
+ /* make next carry */
+ _W = _W >> ((mp_word)DIGIT_BIT);
+ }
+
+ /* setup dest */
+ olduse = c->used;
+ c->used = pa;
+
+ {
+ register mp_digit *tmpc;
+ tmpc = c->dp;
+ for (ix = 0; ix < pa+1; ix++) {
+ /* now extract the previous digit [below the carry] */
+ *tmpc++ = W[ix];
+ }
+
+ /* clear unused digits [that existed in the old copy of c] */
+ for (; ix < olduse; ix++) {
+ *tmpc++ = 0;
+ }
+ }
+ mp_clamp (c);
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_fast_s_mp_mul_high_digs.c b/libtommath/bn_fast_s_mp_mul_high_digs.c
new file mode 100644
index 0000000..ec9f58a
--- /dev/null
+++ b/libtommath/bn_fast_s_mp_mul_high_digs.c
@@ -0,0 +1,94 @@
+#include <tommath.h>
+#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* this is a modified version of fast_s_mul_digs that only produces
+ * output digits *above* digs. See the comments for fast_s_mul_digs
+ * to see how it works.
+ *
+ * This is used in the Barrett reduction since for one of the multiplications
+ * only the higher digits were needed. This essentially halves the work.
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ */
+int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+ int olduse, res, pa, ix, iz;
+ mp_digit W[MP_WARRAY];
+ mp_word _W;
+
+ /* grow the destination as required */
+ pa = a->used + b->used;
+ if (c->alloc < pa) {
+ if ((res = mp_grow (c, pa)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* number of output digits to produce */
+ pa = a->used + b->used;
+ _W = 0;
+ for (ix = digs; ix < pa; ix++) {
+ int tx, ty, iy;
+ mp_digit *tmpx, *tmpy;
+
+ /* get offsets into the two bignums */
+ ty = MIN(b->used-1, ix);
+ tx = ix - ty;
+
+ /* setup temp aliases */
+ tmpx = a->dp + tx;
+ tmpy = b->dp + ty;
+
+ /* this is the number of times the loop will iterrate, essentially its
+ while (tx++ < a->used && ty-- >= 0) { ... }
+ */
+ iy = MIN(a->used-tx, ty+1);
+
+ /* execute loop */
+ for (iz = 0; iz < iy; iz++) {
+ _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+ }
+
+ /* store term */
+ W[ix] = ((mp_digit)_W) & MP_MASK;
+
+ /* make next carry */
+ _W = _W >> ((mp_word)DIGIT_BIT);
+ }
+
+ /* setup dest */
+ olduse = c->used;
+ c->used = pa;
+
+ {
+ register mp_digit *tmpc;
+
+ tmpc = c->dp + digs;
+ for (ix = digs; ix < pa; ix++) {
+ /* now extract the previous digit [below the carry] */
+ *tmpc++ = W[ix];
+ }
+
+ /* clear unused digits [that existed in the old copy of c] */
+ for (; ix < olduse; ix++) {
+ *tmpc++ = 0;
+ }
+ }
+ mp_clamp (c);
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_fast_s_mp_sqr.c b/libtommath/bn_fast_s_mp_sqr.c
new file mode 100644
index 0000000..1abf24b
--- /dev/null
+++ b/libtommath/bn_fast_s_mp_sqr.c
@@ -0,0 +1,110 @@
+#include <tommath.h>
+#ifdef BN_FAST_S_MP_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* the jist of squaring...
+ * you do like mult except the offset of the tmpx [one that
+ * starts closer to zero] can't equal the offset of tmpy.
+ * So basically you set up iy like before then you min it with
+ * (ty-tx) so that it never happens. You double all those
+ * you add in the inner loop
+
+After that loop you do the squares and add them in.
+*/
+
+int fast_s_mp_sqr (mp_int * a, mp_int * b)
+{
+ int olduse, res, pa, ix, iz;
+ mp_digit W[MP_WARRAY], *tmpx;
+ mp_word W1;
+
+ /* grow the destination as required */
+ pa = a->used + a->used;
+ if (b->alloc < pa) {
+ if ((res = mp_grow (b, pa)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* number of output digits to produce */
+ W1 = 0;
+ for (ix = 0; ix < pa; ix++) {
+ int tx, ty, iy;
+ mp_word _W;
+ mp_digit *tmpy;
+
+ /* clear counter */
+ _W = 0;
+
+ /* get offsets into the two bignums */
+ ty = MIN(a->used-1, ix);
+ tx = ix - ty;
+
+ /* setup temp aliases */
+ tmpx = a->dp + tx;
+ tmpy = a->dp + ty;
+
+ /* this is the number of times the loop will iterrate, essentially
+ while (tx++ < a->used && ty-- >= 0) { ... }
+ */
+ iy = MIN(a->used-tx, ty+1);
+
+ /* now for squaring tx can never equal ty
+ * we halve the distance since they approach at a rate of 2x
+ * and we have to round because odd cases need to be executed
+ */
+ iy = MIN(iy, (ty-tx+1)>>1);
+
+ /* execute loop */
+ for (iz = 0; iz < iy; iz++) {
+ _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+ }
+
+ /* double the inner product and add carry */
+ _W = _W + _W + W1;
+
+ /* even columns have the square term in them */
+ if ((ix&1) == 0) {
+ _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
+ }
+
+ /* store it */
+ W[ix] = (mp_digit)(_W & MP_MASK);
+
+ /* make next carry */
+ W1 = _W >> ((mp_word)DIGIT_BIT);
+ }
+
+ /* setup dest */
+ olduse = b->used;
+ b->used = a->used+a->used;
+
+ {
+ mp_digit *tmpb;
+ tmpb = b->dp;
+ for (ix = 0; ix < pa; ix++) {
+ *tmpb++ = W[ix] & MP_MASK;
+ }
+
+ /* clear unused digits [that existed in the old copy of c] */
+ for (; ix < olduse; ix++) {
+ *tmpb++ = 0;
+ }
+ }
+ mp_clamp (b);
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_2expt.c b/libtommath/bn_mp_2expt.c
new file mode 100644
index 0000000..a32572d
--- /dev/null
+++ b/libtommath/bn_mp_2expt.c
@@ -0,0 +1,44 @@
+#include <tommath.h>
+#ifdef BN_MP_2EXPT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* computes a = 2**b
+ *
+ * Simple algorithm which zeroes the int, grows it then just sets one bit
+ * as required.
+ */
+int
+mp_2expt (mp_int * a, int b)
+{
+ int res;
+
+ /* zero a as per default */
+ mp_zero (a);
+
+ /* grow a to accomodate the single bit */
+ if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) {
+ return res;
+ }
+
+ /* set the used count of where the bit will go */
+ a->used = b / DIGIT_BIT + 1;
+
+ /* put the single bit in its place */
+ a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);
+
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_abs.c b/libtommath/bn_mp_abs.c
new file mode 100644
index 0000000..dc51884
--- /dev/null
+++ b/libtommath/bn_mp_abs.c
@@ -0,0 +1,39 @@
+#include <tommath.h>
+#ifdef BN_MP_ABS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* b = |a|
+ *
+ * Simple function copies the input and fixes the sign to positive
+ */
+int
+mp_abs (mp_int * a, mp_int * b)
+{
+ int res;
+
+ /* copy a to b */
+ if (a != b) {
+ if ((res = mp_copy (a, b)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* force the sign of b to positive */
+ b->sign = MP_ZPOS;
+
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_add.c b/libtommath/bn_mp_add.c
new file mode 100644
index 0000000..d9b8fa5
--- /dev/null
+++ b/libtommath/bn_mp_add.c
@@ -0,0 +1,49 @@
+#include <tommath.h>
+#ifdef BN_MP_ADD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* high level addition (handles signs) */
+int mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+ int sa, sb, res;
+
+ /* get sign of both inputs */
+ sa = a->sign;
+ sb = b->sign;
+
+ /* handle two cases, not four */
+ if (sa == sb) {
+ /* both positive or both negative */
+ /* add their magnitudes, copy the sign */
+ c->sign = sa;
+ res = s_mp_add (a, b, c);
+ } else {
+ /* one positive, the other negative */
+ /* subtract the one with the greater magnitude from */
+ /* the one of the lesser magnitude. The result gets */
+ /* the sign of the one with the greater magnitude. */
+ if (mp_cmp_mag (a, b) == MP_LT) {
+ c->sign = sb;
+ res = s_mp_sub (b, a, c);
+ } else {
+ c->sign = sa;
+ res = s_mp_sub (a, b, c);
+ }
+ }
+ return res;
+}
+
+#endif
diff --git a/libtommath/bn_mp_add_d.c b/libtommath/bn_mp_add_d.c
new file mode 100644
index 0000000..5281ad4
--- /dev/null
+++ b/libtommath/bn_mp_add_d.c
@@ -0,0 +1,109 @@
+#include <tommath.h>
+#ifdef BN_MP_ADD_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* single digit addition */
+int
+mp_add_d (mp_int * a, mp_digit b, mp_int * c)
+{
+ int res, ix, oldused;
+ mp_digit *tmpa, *tmpc, mu;
+
+ /* grow c as required */
+ if (c->alloc < a->used + 1) {
+ if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* if a is negative and |a| >= b, call c = |a| - b */
+ if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) {
+ /* temporarily fix sign of a */
+ a->sign = MP_ZPOS;
+
+ /* c = |a| - b */
+ res = mp_sub_d(a, b, c);
+
+ /* fix signs */
+ a->sign = MP_NEG;
+ c->sign = (c->used) ? MP_NEG : MP_ZPOS;
+
+ /* clamp */
+ mp_clamp(c);
+
+ return res;
+ }
+
+ /* old number of used digits in c */
+ oldused = c->used;
+
+ /* sign always positive */
+ c->sign = MP_ZPOS;
+
+ /* source alias */
+ tmpa = a->dp;
+
+ /* destination alias */
+ tmpc = c->dp;
+
+ /* if a is positive */
+ if (a->sign == MP_ZPOS) {
+ /* add digit, after this we're propagating
+ * the carry.
+ */
+ *tmpc = *tmpa++ + b;
+ mu = *tmpc >> DIGIT_BIT;
+ *tmpc++ &= MP_MASK;
+
+ /* now handle rest of the digits */
+ for (ix = 1; ix < a->used; ix++) {
+ *tmpc = *tmpa++ + mu;
+ mu = *tmpc >> DIGIT_BIT;
+ *tmpc++ &= MP_MASK;
+ }
+ /* set final carry */
+ ix++;
+ *tmpc++ = mu;
+
+ /* setup size */
+ c->used = a->used + 1;
+ } else {
+ /* a was negative and |a| < b */
+ c->used = 1;
+
+ /* the result is a single digit */
+ if (a->used == 1) {
+ *tmpc++ = b - a->dp[0];
+ } else {
+ *tmpc++ = b;
+ }
+
+ /* setup count so the clearing of oldused
+ * can fall through correctly
+ */
+ ix = 1;
+ }
+
+ /* now zero to oldused */
+ while (ix++ < oldused) {
+ *tmpc++ = 0;
+ }
+ mp_clamp(c);
+
+ return MP_OKAY;
+}
+
+#endif
diff --git a/libtommath/bn_mp_addmod.c b/libtommath/bn_mp_addmod.c
new file mode 100644
index 0000000..bff193f
--- /dev/null
+++ b/libtommath/bn_mp_addmod.c
@@ -0,0 +1,37 @@
+#include <tommath.h>
+#ifdef BN_MP_ADDMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* d = a + b (mod c) */
+int
+mp_addmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+ int res;
+ mp_int t;
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_add (a, b, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ res = mp_mod (&t, c, d);
+ mp_clear (&t);
+ return res;
+}
+#endif
diff --git a/libtommath/bn_mp_and.c b/libtommath/bn_mp_and.c
new file mode 100644
index 0000000..02bef18
--- /dev/null
+++ b/libtommath/bn_mp_and.c
@@ -0,0 +1,53 @@
+#include <tommath.h>
+#ifdef BN_MP_AND_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* AND two ints together */
+int
+mp_and (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res, ix, px;
+ mp_int t, *x;
+
+ if (a->used > b->used) {
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+ px = b->used;
+ x = b;
+ } else {
+ if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+ return res;
+ }
+ px = a->used;
+ x = a;
+ }
+
+ for (ix = 0; ix < px; ix++) {
+ t.dp[ix] &= x->dp[ix];
+ }
+
+ /* zero digits above the last from the smallest mp_int */
+ for (; ix < t.used; ix++) {
+ t.dp[ix] = 0;
+ }
+
+ mp_clamp (&t);
+ mp_exch (c, &t);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_clamp.c b/libtommath/bn_mp_clamp.c
new file mode 100644
index 0000000..74887bb
--- /dev/null
+++ b/libtommath/bn_mp_clamp.c
@@ -0,0 +1,40 @@
+#include <tommath.h>
+#ifdef BN_MP_CLAMP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* trim unused digits
+ *
+ * This is used to ensure that leading zero digits are
+ * trimed and the leading "used" digit will be non-zero
+ * Typically very fast. Also fixes the sign if there
+ * are no more leading digits
+ */
+void
+mp_clamp (mp_int * a)
+{
+ /* decrease used while the most significant digit is
+ * zero.
+ */
+ while (a->used > 0 && a->dp[a->used - 1] == 0) {
+ --(a->used);
+ }
+
+ /* reset the sign flag if used == 0 */
+ if (a->used == 0) {
+ a->sign = MP_ZPOS;
+ }
+}
+#endif
diff --git a/libtommath/bn_mp_clear.c b/libtommath/bn_mp_clear.c
new file mode 100644
index 0000000..bd07e76
--- /dev/null
+++ b/libtommath/bn_mp_clear.c
@@ -0,0 +1,40 @@
+#include <tommath.h>
+#ifdef BN_MP_CLEAR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* clear one (frees) */
+void
+mp_clear (mp_int * a)
+{
+ int i;
+
+ /* only do anything if a hasn't been freed previously */
+ if (a->dp != NULL) {
+ /* first zero the digits */
+ for (i = 0; i < a->used; i++) {
+ a->dp[i] = 0;
+ }
+
+ /* free ram */
+ XFREE(a->dp);
+
+ /* reset members to make debugging easier */
+ a->dp = NULL;
+ a->alloc = a->used = 0;
+ a->sign = MP_ZPOS;
+ }
+}
+#endif
diff --git a/libtommath/bn_mp_clear_multi.c b/libtommath/bn_mp_clear_multi.c
new file mode 100644
index 0000000..c3ad7a8
--- /dev/null
+++ b/libtommath/bn_mp_clear_multi.c
@@ -0,0 +1,30 @@
+#include <tommath.h>
+#ifdef BN_MP_CLEAR_MULTI_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+#include <stdarg.h>
+
+void mp_clear_multi(mp_int *mp, ...)
+{
+ mp_int* next_mp = mp;
+ va_list args;
+ va_start(args, mp);
+ while (next_mp != NULL) {
+ mp_clear(next_mp);
+ next_mp = va_arg(args, mp_int*);
+ }
+ va_end(args);
+}
+#endif
diff --git a/libtommath/bn_mp_cmp.c b/libtommath/bn_mp_cmp.c
new file mode 100644
index 0000000..b965d4b
--- /dev/null
+++ b/libtommath/bn_mp_cmp.c
@@ -0,0 +1,39 @@
+#include <tommath.h>
+#ifdef BN_MP_CMP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* compare two ints (signed)*/
+int
+mp_cmp (mp_int * a, mp_int * b)
+{
+ /* compare based on sign */
+ if (a->sign != b->sign) {
+ if (a->sign == MP_NEG) {
+ return MP_LT;
+ } else {
+ return MP_GT;
+ }
+ }
+
+ /* compare digits */
+ if (a->sign == MP_NEG) {
+ /* if negative compare opposite direction */
+ return mp_cmp_mag(b, a);
+ } else {
+ return mp_cmp_mag(a, b);
+ }
+}
+#endif
diff --git a/libtommath/bn_mp_cmp_d.c b/libtommath/bn_mp_cmp_d.c
new file mode 100644
index 0000000..a446bb4
--- /dev/null
+++ b/libtommath/bn_mp_cmp_d.c
@@ -0,0 +1,40 @@
+#include <tommath.h>
+#ifdef BN_MP_CMP_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* compare a digit */
+int mp_cmp_d(mp_int * a, mp_digit b)
+{
+ /* compare based on sign */
+ if (a->sign == MP_NEG) {
+ return MP_LT;
+ }
+
+ /* compare based on magnitude */
+ if (a->used > 1) {
+ return MP_GT;
+ }
+
+ /* compare the only digit of a to b */
+ if (a->dp[0] > b) {
+ return MP_GT;
+ } else if (a->dp[0] < b) {
+ return MP_LT;
+ } else {
+ return MP_EQ;
+ }
+}
+#endif
diff --git a/libtommath/bn_mp_cmp_mag.c b/libtommath/bn_mp_cmp_mag.c
new file mode 100644
index 0000000..3506d2b
--- /dev/null
+++ b/libtommath/bn_mp_cmp_mag.c
@@ -0,0 +1,51 @@
+#include <tommath.h>
+#ifdef BN_MP_CMP_MAG_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* compare maginitude of two ints (unsigned) */
+int mp_cmp_mag (mp_int * a, mp_int * b)
+{
+ int n;
+ mp_digit *tmpa, *tmpb;
+
+ /* compare based on # of non-zero digits */
+ if (a->used > b->used) {
+ return MP_GT;
+ }
+
+ if (a->used < b->used) {
+ return MP_LT;
+ }
+
+ /* alias for a */
+ tmpa = a->dp + (a->used - 1);
+
+ /* alias for b */
+ tmpb = b->dp + (a->used - 1);
+
+ /* compare based on digits */
+ for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
+ if (*tmpa > *tmpb) {
+ return MP_GT;
+ }
+
+ if (*tmpa < *tmpb) {
+ return MP_LT;
+ }
+ }
+ return MP_EQ;
+}
+#endif
diff --git a/libtommath/bn_mp_cnt_lsb.c b/libtommath/bn_mp_cnt_lsb.c
new file mode 100644
index 0000000..6447a1f
--- /dev/null
+++ b/libtommath/bn_mp_cnt_lsb.c
@@ -0,0 +1,49 @@
+#include <tommath.h>
+#ifdef BN_MP_CNT_LSB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+static const int lnz[16] = {
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+};
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+int mp_cnt_lsb(mp_int *a)
+{
+ int x;
+ mp_digit q, qq;
+
+ /* easy out */
+ if (mp_iszero(a) == 1) {
+ return 0;
+ }
+
+ /* scan lower digits until non-zero */
+ for (x = 0; x < a->used && a->dp[x] == 0; x++);
+ q = a->dp[x];
+ x *= DIGIT_BIT;
+
+ /* now scan this digit until a 1 is found */
+ if ((q & 1) == 0) {
+ do {
+ qq = q & 15;
+ x += lnz[qq];
+ q >>= 4;
+ } while (qq == 0);
+ }
+ return x;
+}
+
+#endif
diff --git a/libtommath/bn_mp_copy.c b/libtommath/bn_mp_copy.c
new file mode 100644
index 0000000..0de7565
--- /dev/null
+++ b/libtommath/bn_mp_copy.c
@@ -0,0 +1,64 @@
+#include <tommath.h>
+#ifdef BN_MP_COPY_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* copy, b = a */
+int
+mp_copy (mp_int * a, mp_int * b)
+{
+ int res, n;
+
+ /* if dst == src do nothing */
+ if (a == b) {
+ return MP_OKAY;
+ }
+
+ /* grow dest */
+ if (b->alloc < a->used) {
+ if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* zero b and copy the parameters over */
+ {
+ register mp_digit *tmpa, *tmpb;
+
+ /* pointer aliases */
+
+ /* source */
+ tmpa = a->dp;
+
+ /* destination */
+ tmpb = b->dp;
+
+ /* copy all the digits */
+ for (n = 0; n < a->used; n++) {
+ *tmpb++ = *tmpa++;
+ }
+
+ /* clear high digits */
+ for (; n < b->used; n++) {
+ *tmpb++ = 0;
+ }
+ }
+
+ /* copy used count and sign */
+ b->used = a->used;
+ b->sign = a->sign;
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_count_bits.c b/libtommath/bn_mp_count_bits.c
new file mode 100644
index 0000000..6c2d7ac
--- /dev/null
+++ b/libtommath/bn_mp_count_bits.c
@@ -0,0 +1,41 @@
+#include <tommath.h>
+#ifdef BN_MP_COUNT_BITS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* returns the number of bits in an int */
+int
+mp_count_bits (mp_int * a)
+{
+ int r;
+ mp_digit q;
+
+ /* shortcut */
+ if (a->used == 0) {
+ return 0;
+ }
+
+ /* get number of digits and add that */
+ r = (a->used - 1) * DIGIT_BIT;
+
+ /* take the last digit and count the bits in it */
+ q = a->dp[a->used - 1];
+ while (q > ((mp_digit) 0)) {
+ ++r;
+ q >>= ((mp_digit) 1);
+ }
+ return r;
+}
+#endif
diff --git a/libtommath/bn_mp_div.c b/libtommath/bn_mp_div.c
new file mode 100644
index 0000000..de4ca04
--- /dev/null
+++ b/libtommath/bn_mp_div.c
@@ -0,0 +1,288 @@
+#include <tommath.h>
+#ifdef BN_MP_DIV_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+#ifdef BN_MP_DIV_SMALL
+
+/* slower bit-bang division... also smaller */
+int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+ mp_int ta, tb, tq, q;
+ int res, n, n2;
+
+ /* is divisor zero ? */
+ if (mp_iszero (b) == 1) {
+ return MP_VAL;
+ }
+
+ /* if a < b then q=0, r = a */
+ if (mp_cmp_mag (a, b) == MP_LT) {
+ if (d != NULL) {
+ res = mp_copy (a, d);
+ } else {
+ res = MP_OKAY;
+ }
+ if (c != NULL) {
+ mp_zero (c);
+ }
+ return res;
+ }
+
+ /* init our temps */
+ if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) {
+ return res;
+ }
+
+
+ mp_set(&tq, 1);
+ n = mp_count_bits(a) - mp_count_bits(b);
+ if (((res = mp_abs(a, &ta)) != MP_OKAY) ||
+ ((res = mp_abs(b, &tb)) != MP_OKAY) ||
+ ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||
+ ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) {
+ goto LBL_ERR;
+ }
+
+ while (n-- >= 0) {
+ if (mp_cmp(&tb, &ta) != MP_GT) {
+ if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||
+ ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) {
+ goto LBL_ERR;
+ }
+ }
+ if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||
+ ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* now q == quotient and ta == remainder */
+ n = a->sign;
+ n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);
+ if (c != NULL) {
+ mp_exch(c, &q);
+ c->sign = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2;
+ }
+ if (d != NULL) {
+ mp_exch(d, &ta);
+ d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n;
+ }
+LBL_ERR:
+ mp_clear_multi(&ta, &tb, &tq, &q, NULL);
+ return res;
+}
+
+#else
+
+/* integer signed division.
+ * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
+ * HAC pp.598 Algorithm 14.20
+ *
+ * Note that the description in HAC is horribly
+ * incomplete. For example, it doesn't consider
+ * the case where digits are removed from 'x' in
+ * the inner loop. It also doesn't consider the
+ * case that y has fewer than three digits, etc..
+ *
+ * The overall algorithm is as described as
+ * 14.20 from HAC but fixed to treat these cases.
+*/
+int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+ mp_int q, x, y, t1, t2;
+ int res, n, t, i, norm, neg;
+
+ /* is divisor zero ? */
+ if (mp_iszero (b) == 1) {
+ return MP_VAL;
+ }
+
+ /* if a < b then q=0, r = a */
+ if (mp_cmp_mag (a, b) == MP_LT) {
+ if (d != NULL) {
+ res = mp_copy (a, d);
+ } else {
+ res = MP_OKAY;
+ }
+ if (c != NULL) {
+ mp_zero (c);
+ }
+ return res;
+ }
+
+ if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) {
+ return res;
+ }
+ q.used = a->used + 2;
+
+ if ((res = mp_init (&t1)) != MP_OKAY) {
+ goto LBL_Q;
+ }
+
+ if ((res = mp_init (&t2)) != MP_OKAY) {
+ goto LBL_T1;
+ }
+
+ if ((res = mp_init_copy (&x, a)) != MP_OKAY) {
+ goto LBL_T2;
+ }
+
+ if ((res = mp_init_copy (&y, b)) != MP_OKAY) {
+ goto LBL_X;
+ }
+
+ /* fix the sign */
+ neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+ x.sign = y.sign = MP_ZPOS;
+
+ /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
+ norm = mp_count_bits(&y) % DIGIT_BIT;
+ if (norm < (int)(DIGIT_BIT-1)) {
+ norm = (DIGIT_BIT-1) - norm;
+ if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+ if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+ } else {
+ norm = 0;
+ }
+
+ /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
+ n = x.used - 1;
+ t = y.used - 1;
+
+ /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
+ if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */
+ goto LBL_Y;
+ }
+
+ while (mp_cmp (&x, &y) != MP_LT) {
+ ++(q.dp[n - t]);
+ if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+ }
+
+ /* reset y by shifting it back down */
+ mp_rshd (&y, n - t);
+
+ /* step 3. for i from n down to (t + 1) */
+ for (i = n; i >= (t + 1); i--) {
+ if (i > x.used) {
+ continue;
+ }
+
+ /* step 3.1 if xi == yt then set q{i-t-1} to b-1,
+ * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
+ if (x.dp[i] == y.dp[t]) {
+ q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);
+ } else {
+ mp_word tmp;
+ tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
+ tmp |= ((mp_word) x.dp[i - 1]);
+ tmp /= ((mp_word) y.dp[t]);
+ if (tmp > (mp_word) MP_MASK)
+ tmp = MP_MASK;
+ q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK));
+ }
+
+ /* while (q{i-t-1} * (yt * b + y{t-1})) >
+ xi * b**2 + xi-1 * b + xi-2
+
+ do q{i-t-1} -= 1;
+ */
+ q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK;
+ do {
+ q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;
+
+ /* find left hand */
+ mp_zero (&t1);
+ t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
+ t1.dp[1] = y.dp[t];
+ t1.used = 2;
+ if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ /* find right hand */
+ t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
+ t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
+ t2.dp[2] = x.dp[i];
+ t2.used = 3;
+ } while (mp_cmp_mag(&t1, &t2) == MP_GT);
+
+ /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
+ if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
+ if (x.sign == MP_NEG) {
+ if ((res = mp_copy (&y, &t1)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+ if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+ if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK;
+ }
+ }
+
+ /* now q is the quotient and x is the remainder
+ * [which we have to normalize]
+ */
+
+ /* get sign before writing to c */
+ x.sign = x.used == 0 ? MP_ZPOS : a->sign;
+
+ if (c != NULL) {
+ mp_clamp (&q);
+ mp_exch (&q, c);
+ c->sign = neg;
+ }
+
+ if (d != NULL) {
+ mp_div_2d (&x, norm, &x, NULL);
+ mp_exch (&x, d);
+ }
+
+ res = MP_OKAY;
+
+LBL_Y:mp_clear (&y);
+LBL_X:mp_clear (&x);
+LBL_T2:mp_clear (&t2);
+LBL_T1:mp_clear (&t1);
+LBL_Q:mp_clear (&q);
+ return res;
+}
+
+#endif
+
+#endif
diff --git a/libtommath/bn_mp_div_2.c b/libtommath/bn_mp_div_2.c
new file mode 100644
index 0000000..186a959
--- /dev/null
+++ b/libtommath/bn_mp_div_2.c
@@ -0,0 +1,64 @@
+#include <tommath.h>
+#ifdef BN_MP_DIV_2_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* b = a/2 */
+int mp_div_2(mp_int * a, mp_int * b)
+{
+ int x, res, oldused;
+
+ /* copy */
+ if (b->alloc < a->used) {
+ if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ oldused = b->used;
+ b->used = a->used;
+ {
+ register mp_digit r, rr, *tmpa, *tmpb;
+
+ /* source alias */
+ tmpa = a->dp + b->used - 1;
+
+ /* dest alias */
+ tmpb = b->dp + b->used - 1;
+
+ /* carry */
+ r = 0;
+ for (x = b->used - 1; x >= 0; x--) {
+ /* get the carry for the next iteration */
+ rr = *tmpa & 1;
+
+ /* shift the current digit, add in carry and store */
+ *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
+
+ /* forward carry to next iteration */
+ r = rr;
+ }
+
+ /* zero excess digits */
+ tmpb = b->dp + b->used;
+ for (x = b->used; x < oldused; x++) {
+ *tmpb++ = 0;
+ }
+ }
+ b->sign = a->sign;
+ mp_clamp (b);
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_div_2d.c b/libtommath/bn_mp_div_2d.c
new file mode 100644
index 0000000..2f8d812
--- /dev/null
+++ b/libtommath/bn_mp_div_2d.c
@@ -0,0 +1,93 @@
+#include <tommath.h>
+#ifdef BN_MP_DIV_2D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* shift right by a certain bit count (store quotient in c, optional remainder in d) */
+int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
+{
+ mp_digit D, r, rr;
+ int x, res;
+ mp_int t;
+
+
+ /* if the shift count is <= 0 then we do no work */
+ if (b <= 0) {
+ res = mp_copy (a, c);
+ if (d != NULL) {
+ mp_zero (d);
+ }
+ return res;
+ }
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ /* get the remainder */
+ if (d != NULL) {
+ if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ }
+
+ /* copy */
+ if ((res = mp_copy (a, c)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+
+ /* shift by as many digits in the bit count */
+ if (b >= (int)DIGIT_BIT) {
+ mp_rshd (c, b / DIGIT_BIT);
+ }
+
+ /* shift any bit count < DIGIT_BIT */
+ D = (mp_digit) (b % DIGIT_BIT);
+ if (D != 0) {
+ register mp_digit *tmpc, mask, shift;
+
+ /* mask */
+ mask = (((mp_digit)1) << D) - 1;
+
+ /* shift for lsb */
+ shift = DIGIT_BIT - D;
+
+ /* alias */
+ tmpc = c->dp + (c->used - 1);
+
+ /* carry */
+ r = 0;
+ for (x = c->used - 1; x >= 0; x--) {
+ /* get the lower bits of this word in a temp */
+ rr = *tmpc & mask;
+
+ /* shift the current word and mix in the carry bits from the previous word */
+ *tmpc = (*tmpc >> D) | (r << shift);
+ --tmpc;
+
+ /* set the carry to the carry bits of the current word found above */
+ r = rr;
+ }
+ }
+ mp_clamp (c);
+ if (d != NULL) {
+ mp_exch (&t, d);
+ }
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_div_3.c b/libtommath/bn_mp_div_3.c
new file mode 100644
index 0000000..79a9816
--- /dev/null
+++ b/libtommath/bn_mp_div_3.c
@@ -0,0 +1,75 @@
+#include <tommath.h>
+#ifdef BN_MP_DIV_3_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* divide by three (based on routine from MPI and the GMP manual) */
+int
+mp_div_3 (mp_int * a, mp_int *c, mp_digit * d)
+{
+ mp_int q;
+ mp_word w, t;
+ mp_digit b;
+ int res, ix;
+
+ /* b = 2**DIGIT_BIT / 3 */
+ b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3);
+
+ if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
+ return res;
+ }
+
+ q.used = a->used;
+ q.sign = a->sign;
+ w = 0;
+ for (ix = a->used - 1; ix >= 0; ix--) {
+ w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
+
+ if (w >= 3) {
+ /* multiply w by [1/3] */
+ t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT);
+
+ /* now subtract 3 * [w/3] from w, to get the remainder */
+ w -= t+t+t;
+
+ /* fixup the remainder as required since
+ * the optimization is not exact.
+ */
+ while (w >= 3) {
+ t += 1;
+ w -= 3;
+ }
+ } else {
+ t = 0;
+ }
+ q.dp[ix] = (mp_digit)t;
+ }
+
+ /* [optional] store the remainder */
+ if (d != NULL) {
+ *d = (mp_digit)w;
+ }
+
+ /* [optional] store the quotient */
+ if (c != NULL) {
+ mp_clamp(&q);
+ mp_exch(&q, c);
+ }
+ mp_clear(&q);
+
+ return res;
+}
+
+#endif
diff --git a/libtommath/bn_mp_div_d.c b/libtommath/bn_mp_div_d.c
new file mode 100644
index 0000000..af18d0a
--- /dev/null
+++ b/libtommath/bn_mp_div_d.c
@@ -0,0 +1,110 @@
+#include <tommath.h>
+#ifdef BN_MP_DIV_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+static int s_is_power_of_two(mp_digit b, int *p)
+{
+ int x;
+
+ /* quick out - if (b & (b-1)) isn't zero, b isn't a power of two */
+ if ((b==0) || (b & (b-1))) {
+ return 0;
+ }
+ for (x = 1; x < DIGIT_BIT; x++) {
+ if (b == (((mp_digit)1)<<x)) {
+ *p = x;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* single digit division (based on routine from MPI) */
+int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
+{
+ mp_int q;
+ mp_word w;
+ mp_digit t;
+ int res, ix;
+
+ /* cannot divide by zero */
+ if (b == 0) {
+ return MP_VAL;
+ }
+
+ /* quick outs */
+ if (b == 1 || mp_iszero(a) == 1) {
+ if (d != NULL) {
+ *d = 0;
+ }
+ if (c != NULL) {
+ return mp_copy(a, c);
+ }
+ return MP_OKAY;
+ }
+
+ /* power of two ? */
+ if (s_is_power_of_two(b, &ix) == 1) {
+ if (d != NULL) {
+ *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1);
+ }
+ if (c != NULL) {
+ return mp_div_2d(a, ix, c, NULL);
+ }
+ return MP_OKAY;
+ }
+
+#ifdef BN_MP_DIV_3_C
+ /* three? */
+ if (b == 3) {
+ return mp_div_3(a, c, d);
+ }
+#endif
+
+ /* no easy answer [c'est la vie]. Just division */
+ if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
+ return res;
+ }
+
+ q.used = a->used;
+ q.sign = a->sign;
+ w = 0;
+ for (ix = a->used - 1; ix >= 0; ix--) {
+ w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
+
+ if (w >= b) {
+ t = (mp_digit)(w / b);
+ w -= ((mp_word)t) * ((mp_word)b);
+ } else {
+ t = 0;
+ }
+ q.dp[ix] = (mp_digit)t;
+ }
+
+ if (d != NULL) {
+ *d = (mp_digit)w;
+ }
+
+ if (c != NULL) {
+ mp_clamp(&q);
+ mp_exch(&q, c);
+ }
+ mp_clear(&q);
+
+ return res;
+}
+
+#endif
diff --git a/libtommath/bn_mp_dr_is_modulus.c b/libtommath/bn_mp_dr_is_modulus.c
new file mode 100644
index 0000000..8ad31dc
--- /dev/null
+++ b/libtommath/bn_mp_dr_is_modulus.c
@@ -0,0 +1,39 @@
+#include <tommath.h>
+#ifdef BN_MP_DR_IS_MODULUS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* determines if a number is a valid DR modulus */
+int mp_dr_is_modulus(mp_int *a)
+{
+ int ix;
+
+ /* must be at least two digits */
+ if (a->used < 2) {
+ return 0;
+ }
+
+ /* must be of the form b**k - a [a <= b] so all
+ * but the first digit must be equal to -1 (mod b).
+ */
+ for (ix = 1; ix < a->used; ix++) {
+ if (a->dp[ix] != MP_MASK) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+#endif
diff --git a/libtommath/bn_mp_dr_reduce.c b/libtommath/bn_mp_dr_reduce.c
new file mode 100644
index 0000000..8337591
--- /dev/null
+++ b/libtommath/bn_mp_dr_reduce.c
@@ -0,0 +1,90 @@
+#include <tommath.h>
+#ifdef BN_MP_DR_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
+ *
+ * Based on algorithm from the paper
+ *
+ * "Generating Efficient Primes for Discrete Log Cryptosystems"
+ * Chae Hoon Lim, Pil Joong Lee,
+ * POSTECH Information Research Laboratories
+ *
+ * The modulus must be of a special format [see manual]
+ *
+ * Has been modified to use algorithm 7.10 from the LTM book instead
+ *
+ * Input x must be in the range 0 <= x <= (n-1)**2
+ */
+int
+mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k)
+{
+ int err, i, m;
+ mp_word r;
+ mp_digit mu, *tmpx1, *tmpx2;
+
+ /* m = digits in modulus */
+ m = n->used;
+
+ /* ensure that "x" has at least 2m digits */
+ if (x->alloc < m + m) {
+ if ((err = mp_grow (x, m + m)) != MP_OKAY) {
+ return err;
+ }
+ }
+
+/* top of loop, this is where the code resumes if
+ * another reduction pass is required.
+ */
+top:
+ /* aliases for digits */
+ /* alias for lower half of x */
+ tmpx1 = x->dp;
+
+ /* alias for upper half of x, or x/B**m */
+ tmpx2 = x->dp + m;
+
+ /* set carry to zero */
+ mu = 0;
+
+ /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
+ for (i = 0; i < m; i++) {
+ r = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu;
+ *tmpx1++ = (mp_digit)(r & MP_MASK);
+ mu = (mp_digit)(r >> ((mp_word)DIGIT_BIT));
+ }
+
+ /* set final carry */
+ *tmpx1++ = mu;
+
+ /* zero words above m */
+ for (i = m + 1; i < x->used; i++) {
+ *tmpx1++ = 0;
+ }
+
+ /* clamp, sub and return */
+ mp_clamp (x);
+
+ /* if x >= n then subtract and reduce again
+ * Each successive "recursion" makes the input smaller and smaller.
+ */
+ if (mp_cmp_mag (x, n) != MP_LT) {
+ s_mp_sub(x, n, x);
+ goto top;
+ }
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_dr_setup.c b/libtommath/bn_mp_dr_setup.c
new file mode 100644
index 0000000..de00e2d
--- /dev/null
+++ b/libtommath/bn_mp_dr_setup.c
@@ -0,0 +1,28 @@
+#include <tommath.h>
+#ifdef BN_MP_DR_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* determines the setup value */
+void mp_dr_setup(mp_int *a, mp_digit *d)
+{
+ /* the casts are required if DIGIT_BIT is one less than
+ * the number of bits in a mp_digit [e.g. DIGIT_BIT==31]
+ */
+ *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) -
+ ((mp_word)a->dp[0]));
+}
+
+#endif
diff --git a/libtommath/bn_mp_exch.c b/libtommath/bn_mp_exch.c
new file mode 100644
index 0000000..b7bd186
--- /dev/null
+++ b/libtommath/bn_mp_exch.c
@@ -0,0 +1,30 @@
+#include <tommath.h>
+#ifdef BN_MP_EXCH_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* swap the elements of two integers, for cases where you can't simply swap the
+ * mp_int pointers around
+ */
+void
+mp_exch (mp_int * a, mp_int * b)
+{
+ mp_int t;
+
+ t = *a;
+ *a = *b;
+ *b = t;
+}
+#endif
diff --git a/libtommath/bn_mp_expt_d.c b/libtommath/bn_mp_expt_d.c
new file mode 100644
index 0000000..132f480
--- /dev/null
+++ b/libtommath/bn_mp_expt_d.c
@@ -0,0 +1,53 @@
+#include <tommath.h>
+#ifdef BN_MP_EXPT_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* calculate c = a**b using a square-multiply algorithm */
+int mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
+{
+ int res, x;
+ mp_int g;
+
+ if ((res = mp_init_copy (&g, a)) != MP_OKAY) {
+ return res;
+ }
+
+ /* set initial result */
+ mp_set (c, 1);
+
+ for (x = 0; x < (int) DIGIT_BIT; x++) {
+ /* square */
+ if ((res = mp_sqr (c, c)) != MP_OKAY) {
+ mp_clear (&g);
+ return res;
+ }
+
+ /* if the bit is set multiply */
+ if ((b & (mp_digit) (((mp_digit)1) << (DIGIT_BIT - 1))) != 0) {
+ if ((res = mp_mul (c, &g, c)) != MP_OKAY) {
+ mp_clear (&g);
+ return res;
+ }
+ }
+
+ /* shift to next bit */
+ b <<= 1;
+ }
+
+ mp_clear (&g);
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_exptmod.c b/libtommath/bn_mp_exptmod.c
new file mode 100644
index 0000000..b7d9fb7
--- /dev/null
+++ b/libtommath/bn_mp_exptmod.c
@@ -0,0 +1,108 @@
+#include <tommath.h>
+#ifdef BN_MP_EXPTMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+
+/* this is a shell function that calls either the normal or Montgomery
+ * exptmod functions. Originally the call to the montgomery code was
+ * embedded in the normal function but that wasted alot of stack space
+ * for nothing (since 99% of the time the Montgomery code would be called)
+ */
+int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
+{
+ int dr;
+
+ /* modulus P must be positive */
+ if (P->sign == MP_NEG) {
+ return MP_VAL;
+ }
+
+ /* if exponent X is negative we have to recurse */
+ if (X->sign == MP_NEG) {
+#ifdef BN_MP_INVMOD_C
+ mp_int tmpG, tmpX;
+ int err;
+
+ /* first compute 1/G mod P */
+ if ((err = mp_init(&tmpG)) != MP_OKAY) {
+ return err;
+ }
+ if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
+ mp_clear(&tmpG);
+ return err;
+ }
+
+ /* now get |X| */
+ if ((err = mp_init(&tmpX)) != MP_OKAY) {
+ mp_clear(&tmpG);
+ return err;
+ }
+ if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
+ mp_clear_multi(&tmpG, &tmpX, NULL);
+ return err;
+ }
+
+ /* and now compute (1/G)**|X| instead of G**X [X < 0] */
+ err = mp_exptmod(&tmpG, &tmpX, P, Y);
+ mp_clear_multi(&tmpG, &tmpX, NULL);
+ return err;
+#else
+ /* no invmod */
+ return MP_VAL;
+#endif
+ }
+
+/* modified diminished radix reduction */
+#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C)
+ if (mp_reduce_is_2k_l(P) == MP_YES) {
+ return s_mp_exptmod(G, X, P, Y, 1);
+ }
+#endif
+
+#ifdef BN_MP_DR_IS_MODULUS_C
+ /* is it a DR modulus? */
+ dr = mp_dr_is_modulus(P);
+#else
+ /* default to no */
+ dr = 0;
+#endif
+
+#ifdef BN_MP_REDUCE_IS_2K_C
+ /* if not, is it a unrestricted DR modulus? */
+ if (dr == 0) {
+ dr = mp_reduce_is_2k(P) << 1;
+ }
+#endif
+
+ /* if the modulus is odd or dr != 0 use the montgomery method */
+#ifdef BN_MP_EXPTMOD_FAST_C
+ if (mp_isodd (P) == 1 || dr != 0) {
+ return mp_exptmod_fast (G, X, P, Y, dr);
+ } else {
+#endif
+#ifdef BN_S_MP_EXPTMOD_C
+ /* otherwise use the generic Barrett reduction technique */
+ return s_mp_exptmod (G, X, P, Y, 0);
+#else
+ /* no exptmod for evens */
+ return MP_VAL;
+#endif
+#ifdef BN_MP_EXPTMOD_FAST_C
+ }
+#endif
+}
+
+#endif
diff --git a/libtommath/bn_mp_exptmod_fast.c b/libtommath/bn_mp_exptmod_fast.c
new file mode 100644
index 0000000..1902e79
--- /dev/null
+++ b/libtommath/bn_mp_exptmod_fast.c
@@ -0,0 +1,316 @@
+#include <tommath.h>
+#ifdef BN_MP_EXPTMOD_FAST_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
+ *
+ * Uses a left-to-right k-ary sliding window to compute the modular exponentiation.
+ * The value of k changes based on the size of the exponent.
+ *
+ * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
+ */
+
+#ifdef MP_LOW_MEM
+ #define TAB_SIZE 32
+#else
+ #define TAB_SIZE 256
+#endif
+
+int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+ mp_int M[TAB_SIZE], res;
+ mp_digit buf, mp;
+ int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+
+ /* use a pointer to the reduction algorithm. This allows us to use
+ * one of many reduction algorithms without modding the guts of
+ * the code with if statements everywhere.
+ */
+ int (*redux)(mp_int*,mp_int*,mp_digit);
+
+ /* find window size */
+ x = mp_count_bits (X);
+ if (x <= 7) {
+ winsize = 2;
+ } else if (x <= 36) {
+ winsize = 3;
+ } else if (x <= 140) {
+ winsize = 4;
+ } else if (x <= 450) {
+ winsize = 5;
+ } else if (x <= 1303) {
+ winsize = 6;
+ } else if (x <= 3529) {
+ winsize = 7;
+ } else {
+ winsize = 8;
+ }
+
+#ifdef MP_LOW_MEM
+ if (winsize > 5) {
+ winsize = 5;
+ }
+#endif
+
+ /* init M array */
+ /* init first cell */
+ if ((err = mp_init(&M[1])) != MP_OKAY) {
+ return err;
+ }
+
+ /* now init the second half of the array */
+ for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+ if ((err = mp_init(&M[x])) != MP_OKAY) {
+ for (y = 1<<(winsize-1); y < x; y++) {
+ mp_clear (&M[y]);
+ }
+ mp_clear(&M[1]);
+ return err;
+ }
+ }
+
+ /* determine and setup reduction code */
+ if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_SETUP_C
+ /* now setup montgomery */
+ if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
+ goto LBL_M;
+ }
+#else
+ err = MP_VAL;
+ goto LBL_M;
+#endif
+
+ /* automatically pick the comba one if available (saves quite a few calls/ifs) */
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+ if (((P->used * 2 + 1) < MP_WARRAY) &&
+ P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ redux = fast_mp_montgomery_reduce;
+ } else
+#endif
+ {
+#ifdef BN_MP_MONTGOMERY_REDUCE_C
+ /* use slower baseline Montgomery method */
+ redux = mp_montgomery_reduce;
+#else
+ err = MP_VAL;
+ goto LBL_M;
+#endif
+ }
+ } else if (redmode == 1) {
+#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)
+ /* setup DR reduction for moduli of the form B**k - b */
+ mp_dr_setup(P, &mp);
+ redux = mp_dr_reduce;
+#else
+ err = MP_VAL;
+ goto LBL_M;
+#endif
+ } else {
+#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)
+ /* setup DR reduction for moduli of the form 2**k - b */
+ if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
+ goto LBL_M;
+ }
+ redux = mp_reduce_2k;
+#else
+ err = MP_VAL;
+ goto LBL_M;
+#endif
+ }
+
+ /* setup result */
+ if ((err = mp_init (&res)) != MP_OKAY) {
+ goto LBL_M;
+ }
+
+ /* create M table
+ *
+
+ *
+ * The first half of the table is not computed though accept for M[0] and M[1]
+ */
+
+ if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+ /* now we need R mod m */
+ if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+#else
+ err = MP_VAL;
+ goto LBL_RES;
+#endif
+
+ /* now set M[1] to G * R mod m */
+ if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ } else {
+ mp_set(&res, 1);
+ if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
+ if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ for (x = 0; x < (winsize - 1); x++) {
+ if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* create upper table */
+ for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+ if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&M[x], P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* set initial mode and bit cnt */
+ mode = 0;
+ bitcnt = 1;
+ buf = 0;
+ digidx = X->used - 1;
+ bitcpy = 0;
+ bitbuf = 0;
+
+ for (;;) {
+ /* grab next digit as required */
+ if (--bitcnt == 0) {
+ /* if digidx == -1 we are out of digits so break */
+ if (digidx == -1) {
+ break;
+ }
+ /* read next digit and reset bitcnt */
+ buf = X->dp[digidx--];
+ bitcnt = (int)DIGIT_BIT;
+ }
+
+ /* grab the next msb from the exponent */
+ y = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
+ buf <<= (mp_digit)1;
+
+ /* if the bit is zero and mode == 0 then we ignore it
+ * These represent the leading zero bits before the first 1 bit
+ * in the exponent. Technically this opt is not required but it
+ * does lower the # of trivial squaring/reductions used
+ */
+ if (mode == 0 && y == 0) {
+ continue;
+ }
+
+ /* if the bit is zero and mode == 1 then we square */
+ if (mode == 1 && y == 0) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ continue;
+ }
+
+ /* else we add it to the window */
+ bitbuf |= (y << (winsize - ++bitcpy));
+ mode = 2;
+
+ if (bitcpy == winsize) {
+ /* ok window is filled so square as required and multiply */
+ /* square first */
+ for (x = 0; x < winsize; x++) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* then multiply */
+ if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ /* empty window and reset */
+ bitcpy = 0;
+ bitbuf = 0;
+ mode = 1;
+ }
+ }
+
+ /* if bits remain then square/multiply */
+ if (mode == 2 && bitcpy > 0) {
+ /* square then multiply if the bit is set */
+ for (x = 0; x < bitcpy; x++) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ /* get next bit of the window */
+ bitbuf <<= 1;
+ if ((bitbuf & (1 << winsize)) != 0) {
+ /* then multiply */
+ if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+ }
+ }
+
+ if (redmode == 0) {
+ /* fixup result if Montgomery reduction is used
+ * recall that any value in a Montgomery system is
+ * actually multiplied by R mod n. So we have
+ * to reduce one more time to cancel out the factor
+ * of R.
+ */
+ if ((err = redux(&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* swap res with Y */
+ mp_exch (&res, Y);
+ err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_M:
+ mp_clear(&M[1]);
+ for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+ mp_clear (&M[x]);
+ }
+ return err;
+}
+#endif
diff --git a/libtommath/bn_mp_exteuclid.c b/libtommath/bn_mp_exteuclid.c
new file mode 100644
index 0000000..2e69ce1
--- /dev/null
+++ b/libtommath/bn_mp_exteuclid.c
@@ -0,0 +1,78 @@
+#include <tommath.h>
+#ifdef BN_MP_EXTEUCLID_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* Extended euclidean algorithm of (a, b) produces
+ a*u1 + b*u2 = u3
+ */
+int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3)
+{
+ mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp;
+ int err;
+
+ if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) {
+ return err;
+ }
+
+ /* initialize, (u1,u2,u3) = (1,0,a) */
+ mp_set(&u1, 1);
+ if ((err = mp_copy(a, &u3)) != MP_OKAY) { goto _ERR; }
+
+ /* initialize, (v1,v2,v3) = (0,1,b) */
+ mp_set(&v2, 1);
+ if ((err = mp_copy(b, &v3)) != MP_OKAY) { goto _ERR; }
+
+ /* loop while v3 != 0 */
+ while (mp_iszero(&v3) == MP_NO) {
+ /* q = u3/v3 */
+ if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY) { goto _ERR; }
+
+ /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */
+ if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY) { goto _ERR; }
+
+ /* (u1,u2,u3) = (v1,v2,v3) */
+ if ((err = mp_copy(&v1, &u1)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_copy(&v2, &u2)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_copy(&v3, &u3)) != MP_OKAY) { goto _ERR; }
+
+ /* (v1,v2,v3) = (t1,t2,t3) */
+ if ((err = mp_copy(&t1, &v1)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_copy(&t2, &v2)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_copy(&t3, &v3)) != MP_OKAY) { goto _ERR; }
+ }
+
+ /* make sure U3 >= 0 */
+ if (u3.sign == MP_NEG) {
+ mp_neg(&u1, &u1);
+ mp_neg(&u2, &u2);
+ mp_neg(&u3, &u3);
+ }
+
+ /* copy result out */
+ if (U1 != NULL) { mp_exch(U1, &u1); }
+ if (U2 != NULL) { mp_exch(U2, &u2); }
+ if (U3 != NULL) { mp_exch(U3, &u3); }
+
+ err = MP_OKAY;
+_ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);
+ return err;
+}
+#endif
diff --git a/libtommath/bn_mp_fread.c b/libtommath/bn_mp_fread.c
new file mode 100644
index 0000000..44e1ea8
--- /dev/null
+++ b/libtommath/bn_mp_fread.c
@@ -0,0 +1,63 @@
+#include <tommath.h>
+#ifdef BN_MP_FREAD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* read a bigint from a file stream in ASCII */
+int mp_fread(mp_int *a, int radix, FILE *stream)
+{
+ int err, ch, neg, y;
+
+ /* clear a */
+ mp_zero(a);
+
+ /* if first digit is - then set negative */
+ ch = fgetc(stream);
+ if (ch == '-') {
+ neg = MP_NEG;
+ ch = fgetc(stream);
+ } else {
+ neg = MP_ZPOS;
+ }
+
+ for (;;) {
+ /* find y in the radix map */
+ for (y = 0; y < radix; y++) {
+ if (mp_s_rmap[y] == ch) {
+ break;
+ }
+ }
+ if (y == radix) {
+ break;
+ }
+
+ /* shift up and add */
+ if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) {
+ return err;
+ }
+ if ((err = mp_add_d(a, y, a)) != MP_OKAY) {
+ return err;
+ }
+
+ ch = fgetc(stream);
+ }
+ if (mp_cmp_d(a, 0) != MP_EQ) {
+ a->sign = neg;
+ }
+
+ return MP_OKAY;
+}
+
+#endif
diff --git a/libtommath/bn_mp_fwrite.c b/libtommath/bn_mp_fwrite.c
new file mode 100644
index 0000000..b0ec29e
--- /dev/null
+++ b/libtommath/bn_mp_fwrite.c
@@ -0,0 +1,48 @@
+#include <tommath.h>
+#ifdef BN_MP_FWRITE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+int mp_fwrite(mp_int *a, int radix, FILE *stream)
+{
+ char *buf;
+ int err, len, x;
+
+ if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) {
+ return err;
+ }
+
+ buf = OPT_CAST(char) XMALLOC (len);
+ if (buf == NULL) {
+ return MP_MEM;
+ }
+
+ if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) {
+ XFREE (buf);
+ return err;
+ }
+
+ for (x = 0; x < len; x++) {
+ if (fputc(buf[x], stream) == EOF) {
+ XFREE (buf);
+ return MP_VAL;
+ }
+ }
+
+ XFREE (buf);
+ return MP_OKAY;
+}
+
+#endif
diff --git a/libtommath/bn_mp_gcd.c b/libtommath/bn_mp_gcd.c
new file mode 100644
index 0000000..68cfa03
--- /dev/null
+++ b/libtommath/bn_mp_gcd.c
@@ -0,0 +1,101 @@
+#include <tommath.h>
+#ifdef BN_MP_GCD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* Greatest Common Divisor using the binary method */
+int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int u, v;
+ int k, u_lsb, v_lsb, res;
+
+ /* either zero than gcd is the largest */
+ if (mp_iszero (a) == MP_YES) {
+ return mp_abs (b, c);
+ }
+ if (mp_iszero (b) == MP_YES) {
+ return mp_abs (a, c);
+ }
+
+ /* get copies of a and b we can modify */
+ if ((res = mp_init_copy (&u, a)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_init_copy (&v, b)) != MP_OKAY) {
+ goto LBL_U;
+ }
+
+ /* must be positive for the remainder of the algorithm */
+ u.sign = v.sign = MP_ZPOS;
+
+ /* B1. Find the common power of two for u and v */
+ u_lsb = mp_cnt_lsb(&u);
+ v_lsb = mp_cnt_lsb(&v);
+ k = MIN(u_lsb, v_lsb);
+
+ if (k > 0) {
+ /* divide the power of two out */
+ if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) {
+ goto LBL_V;
+ }
+
+ if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) {
+ goto LBL_V;
+ }
+ }
+
+ /* divide any remaining factors of two out */
+ if (u_lsb != k) {
+ if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) {
+ goto LBL_V;
+ }
+ }
+
+ if (v_lsb != k) {
+ if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) {
+ goto LBL_V;
+ }
+ }
+
+ while (mp_iszero(&v) == 0) {
+ /* make sure v is the largest */
+ if (mp_cmp_mag(&u, &v) == MP_GT) {
+ /* swap u and v to make sure v is >= u */
+ mp_exch(&u, &v);
+ }
+
+ /* subtract smallest from largest */
+ if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) {
+ goto LBL_V;
+ }
+
+ /* Divide out all factors of two */
+ if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) {
+ goto LBL_V;
+ }
+ }
+
+ /* multiply by 2**k which we divided out at the beginning */
+ if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) {
+ goto LBL_V;
+ }
+ c->sign = MP_ZPOS;
+ res = MP_OKAY;
+LBL_V:mp_clear (&u);
+LBL_U:mp_clear (&v);
+ return res;
+}
+#endif
diff --git a/libtommath/bn_mp_get_int.c b/libtommath/bn_mp_get_int.c
new file mode 100644
index 0000000..762cb23
--- /dev/null
+++ b/libtommath/bn_mp_get_int.c
@@ -0,0 +1,41 @@
+#include <tommath.h>
+#ifdef BN_MP_GET_INT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* get the lower 32-bits of an mp_int */
+unsigned long mp_get_int(mp_int * a)
+{
+ int i;
+ unsigned long res;
+
+ if (a->used == 0) {
+ return 0;
+ }
+
+ /* get number of digits of the lsb we have to read */
+ i = MIN(a->used,(int)((sizeof(unsigned long)*CHAR_BIT+DIGIT_BIT-1)/DIGIT_BIT))-1;
+
+ /* get most significant digit of result */
+ res = DIGIT(a,i);
+
+ while (--i >= 0) {
+ res = (res << DIGIT_BIT) | DIGIT(a,i);
+ }
+
+ /* force result to 32-bits always so it is consistent on non 32-bit platforms */
+ return res & 0xFFFFFFFFUL;
+}
+#endif
diff --git a/libtommath/bn_mp_grow.c b/libtommath/bn_mp_grow.c
new file mode 100644
index 0000000..b5b2407
--- /dev/null
+++ b/libtommath/bn_mp_grow.c
@@ -0,0 +1,53 @@
+#include <tommath.h>
+#ifdef BN_MP_GROW_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* grow as required */
+int mp_grow (mp_int * a, int size)
+{
+ int i;
+ mp_digit *tmp;
+
+ /* if the alloc size is smaller alloc more ram */
+ if (a->alloc < size) {
+ /* ensure there are always at least MP_PREC digits extra on top */
+ size += (MP_PREC * 2) - (size % MP_PREC);
+
+ /* reallocate the array a->dp
+ *
+ * We store the return in a temporary variable
+ * in case the operation failed we don't want
+ * to overwrite the dp member of a.
+ */
+ tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size);
+ if (tmp == NULL) {
+ /* reallocation failed but "a" is still valid [can be freed] */
+ return MP_MEM;
+ }
+
+ /* reallocation succeeded so set a->dp */
+ a->dp = tmp;
+
+ /* zero excess digits */
+ i = a->alloc;
+ a->alloc = size;
+ for (; i < a->alloc; i++) {
+ a->dp[i] = 0;
+ }
+ }
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_init.c b/libtommath/bn_mp_init.c
new file mode 100644
index 0000000..ddb2d07
--- /dev/null
+++ b/libtommath/bn_mp_init.c
@@ -0,0 +1,42 @@
+#include <tommath.h>
+#ifdef BN_MP_INIT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* init a new mp_int */
+int mp_init (mp_int * a)
+{
+ int i;
+
+ /* allocate memory required and clear it */
+ a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC);
+ if (a->dp == NULL) {
+ return MP_MEM;
+ }
+
+ /* set the digits to zero */
+ for (i = 0; i < MP_PREC; i++) {
+ a->dp[i] = 0;
+ }
+
+ /* set the used to zero, allocated digits to the default precision
+ * and sign to positive */
+ a->used = 0;
+ a->alloc = MP_PREC;
+ a->sign = MP_ZPOS;
+
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_init_copy.c b/libtommath/bn_mp_init_copy.c
new file mode 100644
index 0000000..2410a9f
--- /dev/null
+++ b/libtommath/bn_mp_init_copy.c
@@ -0,0 +1,28 @@
+#include <tommath.h>
+#ifdef BN_MP_INIT_COPY_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* creates "a" then copies b into it */
+int mp_init_copy (mp_int * a, mp_int * b)
+{
+ int res;
+
+ if ((res = mp_init (a)) != MP_OKAY) {
+ return res;
+ }
+ return mp_copy (b, a);
+}
+#endif
diff --git a/libtommath/bn_mp_init_multi.c b/libtommath/bn_mp_init_multi.c
new file mode 100644
index 0000000..44e3fe6
--- /dev/null
+++ b/libtommath/bn_mp_init_multi.c
@@ -0,0 +1,55 @@
+#include <tommath.h>
+#ifdef BN_MP_INIT_MULTI_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+#include <stdarg.h>
+
+int mp_init_multi(mp_int *mp, ...)
+{
+ mp_err res = MP_OKAY; /* Assume ok until proven otherwise */
+ int n = 0; /* Number of ok inits */
+ mp_int* cur_arg = mp;
+ va_list args;
+
+ va_start(args, mp); /* init args to next argument from caller */
+ while (cur_arg != NULL) {
+ if (mp_init(cur_arg) != MP_OKAY) {
+ /* Oops - error! Back-track and mp_clear what we already
+ succeeded in init-ing, then return error.
+ */
+ va_list clean_args;
+
+ /* end the current list */
+ va_end(args);
+
+ /* now start cleaning up */
+ cur_arg = mp;
+ va_start(clean_args, mp);
+ while (n--) {
+ mp_clear(cur_arg);
+ cur_arg = va_arg(clean_args, mp_int*);
+ }
+ va_end(clean_args);
+ res = MP_MEM;
+ break;
+ }
+ n++;
+ cur_arg = va_arg(args, mp_int*);
+ }
+ va_end(args);
+ return res; /* Assumed ok, if error flagged above. */
+}
+
+#endif
diff --git a/libtommath/bn_mp_init_set.c b/libtommath/bn_mp_init_set.c
new file mode 100644
index 0000000..dc08867
--- /dev/null
+++ b/libtommath/bn_mp_init_set.c
@@ -0,0 +1,28 @@
+#include <tommath.h>
+#ifdef BN_MP_INIT_SET_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* initialize and set a digit */
+int mp_init_set (mp_int * a, mp_digit b)
+{
+ int err;
+ if ((err = mp_init(a)) != MP_OKAY) {
+ return err;
+ }
+ mp_set(a, b);
+ return err;
+}
+#endif
diff --git a/libtommath/bn_mp_init_set_int.c b/libtommath/bn_mp_init_set_int.c
new file mode 100644
index 0000000..56b27e0
--- /dev/null
+++ b/libtommath/bn_mp_init_set_int.c
@@ -0,0 +1,27 @@
+#include <tommath.h>
+#ifdef BN_MP_INIT_SET_INT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* initialize and set a digit */
+int mp_init_set_int (mp_int * a, unsigned long b)
+{
+ int err;
+ if ((err = mp_init(a)) != MP_OKAY) {
+ return err;
+ }
+ return mp_set_int(a, b);
+}
+#endif
diff --git a/libtommath/bn_mp_init_size.c b/libtommath/bn_mp_init_size.c
new file mode 100644
index 0000000..8ed2c2a
--- /dev/null
+++ b/libtommath/bn_mp_init_size.c
@@ -0,0 +1,44 @@
+#include <tommath.h>
+#ifdef BN_MP_INIT_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* init an mp_init for a given size */
+int mp_init_size (mp_int * a, int size)
+{
+ int x;
+
+ /* pad size so there are always extra digits */
+ size += (MP_PREC * 2) - (size % MP_PREC);
+
+ /* alloc mem */
+ a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size);
+ if (a->dp == NULL) {
+ return MP_MEM;
+ }
+
+ /* set the members */
+ a->used = 0;
+ a->alloc = size;
+ a->sign = MP_ZPOS;
+
+ /* zero the digits */
+ for (x = 0; x < size; x++) {
+ a->dp[x] = 0;
+ }
+
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_invmod.c b/libtommath/bn_mp_invmod.c
new file mode 100644
index 0000000..fdb6c88
--- /dev/null
+++ b/libtommath/bn_mp_invmod.c
@@ -0,0 +1,39 @@
+#include <tommath.h>
+#ifdef BN_MP_INVMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* hac 14.61, pp608 */
+int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+{
+ /* b cannot be negative */
+ if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+ return MP_VAL;
+ }
+
+#ifdef BN_FAST_MP_INVMOD_C
+ /* if the modulus is odd we can use a faster routine instead */
+ if (mp_isodd (b) == 1) {
+ return fast_mp_invmod (a, b, c);
+ }
+#endif
+
+#ifdef BN_MP_INVMOD_SLOW_C
+ return mp_invmod_slow(a, b, c);
+#endif
+
+ return MP_VAL;
+}
+#endif
diff --git a/libtommath/bn_mp_invmod_slow.c b/libtommath/bn_mp_invmod_slow.c
new file mode 100644
index 0000000..e079819
--- /dev/null
+++ b/libtommath/bn_mp_invmod_slow.c
@@ -0,0 +1,171 @@
+#include <tommath.h>
+#ifdef BN_MP_INVMOD_SLOW_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* hac 14.61, pp608 */
+int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int x, y, u, v, A, B, C, D;
+ int res;
+
+ /* b cannot be negative */
+ if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+ return MP_VAL;
+ }
+
+ /* init temps */
+ if ((res = mp_init_multi(&x, &y, &u, &v,
+ &A, &B, &C, &D, NULL)) != MP_OKAY) {
+ return res;
+ }
+
+ /* x = a, y = b */
+ if ((res = mp_mod(a, b, &x)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_copy (b, &y)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ /* 2. [modified] if x,y are both even then return an error! */
+ if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) {
+ res = MP_VAL;
+ goto LBL_ERR;
+ }
+
+ /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+ if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ mp_set (&A, 1);
+ mp_set (&D, 1);
+
+top:
+ /* 4. while u is even do */
+ while (mp_iseven (&u) == 1) {
+ /* 4.1 u = u/2 */
+ if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ /* 4.2 if A or B is odd then */
+ if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) {
+ /* A = (A+y)/2, B = (B-x)/2 */
+ if ((res = mp_add (&A, &y, &A)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ /* A = A/2, B = B/2 */
+ if ((res = mp_div_2 (&A, &A)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* 5. while v is even do */
+ while (mp_iseven (&v) == 1) {
+ /* 5.1 v = v/2 */
+ if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ /* 5.2 if C or D is odd then */
+ if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) {
+ /* C = (C+y)/2, D = (D-x)/2 */
+ if ((res = mp_add (&C, &y, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ /* C = C/2, D = D/2 */
+ if ((res = mp_div_2 (&C, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* 6. if u >= v then */
+ if (mp_cmp (&u, &v) != MP_LT) {
+ /* u = u - v, A = A - C, B = B - D */
+ if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ } else {
+ /* v - v - u, C = C - A, D = D - B */
+ if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* if not zero goto step 4 */
+ if (mp_iszero (&u) == 0)
+ goto top;
+
+ /* now a = C, b = D, gcd == g*v */
+
+ /* if v != 1 then there is no inverse */
+ if (mp_cmp_d (&v, 1) != MP_EQ) {
+ res = MP_VAL;
+ goto LBL_ERR;
+ }
+
+ /* if its too low */
+ while (mp_cmp_d(&C, 0) == MP_LT) {
+ if ((res = mp_add(&C, b, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* too big */
+ while (mp_cmp_mag(&C, b) != MP_LT) {
+ if ((res = mp_sub(&C, b, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* C is now the inverse */
+ mp_exch (&C, c);
+ res = MP_OKAY;
+LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL);
+ return res;
+}
+#endif
diff --git a/libtommath/bn_mp_is_square.c b/libtommath/bn_mp_is_square.c
new file mode 100644
index 0000000..926b449
--- /dev/null
+++ b/libtommath/bn_mp_is_square.c
@@ -0,0 +1,105 @@
+#include <tommath.h>
+#ifdef BN_MP_IS_SQUARE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* Check if remainders are possible squares - fast exclude non-squares */
+static const char rem_128[128] = {
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1
+};
+
+static const char rem_105[105] = {
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
+ 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1
+};
+
+/* Store non-zero to ret if arg is square, and zero if not */
+int mp_is_square(mp_int *arg,int *ret)
+{
+ int res;
+ mp_digit c;
+ mp_int t;
+ unsigned long r;
+
+ /* Default to Non-square :) */
+ *ret = MP_NO;
+
+ if (arg->sign == MP_NEG) {
+ return MP_VAL;
+ }
+
+ /* digits used? (TSD) */
+ if (arg->used == 0) {
+ return MP_OKAY;
+ }
+
+ /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */
+ if (rem_128[127 & DIGIT(arg,0)] == 1) {
+ return MP_OKAY;
+ }
+
+ /* Next check mod 105 (3*5*7) */
+ if ((res = mp_mod_d(arg,105,&c)) != MP_OKAY) {
+ return res;
+ }
+ if (rem_105[c] == 1) {
+ return MP_OKAY;
+ }
+
+
+ if ((res = mp_init_set_int(&t,11L*13L*17L*19L*23L*29L*31L)) != MP_OKAY) {
+ return res;
+ }
+ if ((res = mp_mod(arg,&t,&t)) != MP_OKAY) {
+ goto ERR;
+ }
+ r = mp_get_int(&t);
+ /* Check for other prime modules, note it's not an ERROR but we must
+ * free "t" so the easiest way is to goto ERR. We know that res
+ * is already equal to MP_OKAY from the mp_mod call
+ */
+ if ( (1L<<(r%11)) & 0x5C4L ) goto ERR;
+ if ( (1L<<(r%13)) & 0x9E4L ) goto ERR;
+ if ( (1L<<(r%17)) & 0x5CE8L ) goto ERR;
+ if ( (1L<<(r%19)) & 0x4F50CL ) goto ERR;
+ if ( (1L<<(r%23)) & 0x7ACCA0L ) goto ERR;
+ if ( (1L<<(r%29)) & 0xC2EDD0CL ) goto ERR;
+ if ( (1L<<(r%31)) & 0x6DE2B848L ) goto ERR;
+
+ /* Final check - is sqr(sqrt(arg)) == arg ? */
+ if ((res = mp_sqrt(arg,&t)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sqr(&t,&t)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ *ret = (mp_cmp_mag(&t,arg) == MP_EQ) ? MP_YES : MP_NO;
+ERR:mp_clear(&t);
+ return res;
+}
+#endif
diff --git a/libtommath/bn_mp_jacobi.c b/libtommath/bn_mp_jacobi.c
new file mode 100644
index 0000000..1644698
--- /dev/null
+++ b/libtommath/bn_mp_jacobi.c
@@ -0,0 +1,101 @@
+#include <tommath.h>
+#ifdef BN_MP_JACOBI_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* computes the jacobi c = (a | n) (or Legendre if n is prime)
+ * HAC pp. 73 Algorithm 2.149
+ */
+int mp_jacobi (mp_int * a, mp_int * p, int *c)
+{
+ mp_int a1, p1;
+ int k, s, r, res;
+ mp_digit residue;
+
+ /* if p <= 0 return MP_VAL */
+ if (mp_cmp_d(p, 0) != MP_GT) {
+ return MP_VAL;
+ }
+
+ /* step 1. if a == 0, return 0 */
+ if (mp_iszero (a) == 1) {
+ *c = 0;
+ return MP_OKAY;
+ }
+
+ /* step 2. if a == 1, return 1 */
+ if (mp_cmp_d (a, 1) == MP_EQ) {
+ *c = 1;
+ return MP_OKAY;
+ }
+
+ /* default */
+ s = 0;
+
+ /* step 3. write a = a1 * 2**k */
+ if ((res = mp_init_copy (&a1, a)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_init (&p1)) != MP_OKAY) {
+ goto LBL_A1;
+ }
+
+ /* divide out larger power of two */
+ k = mp_cnt_lsb(&a1);
+ if ((res = mp_div_2d(&a1, k, &a1, NULL)) != MP_OKAY) {
+ goto LBL_P1;
+ }
+
+ /* step 4. if e is even set s=1 */
+ if ((k & 1) == 0) {
+ s = 1;
+ } else {
+ /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
+ residue = p->dp[0] & 7;
+
+ if (residue == 1 || residue == 7) {
+ s = 1;
+ } else if (residue == 3 || residue == 5) {
+ s = -1;
+ }
+ }
+
+ /* step 5. if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
+ if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) {
+ s = -s;
+ }
+
+ /* if a1 == 1 we're done */
+ if (mp_cmp_d (&a1, 1) == MP_EQ) {
+ *c = s;
+ } else {
+ /* n1 = n mod a1 */
+ if ((res = mp_mod (p, &a1, &p1)) != MP_OKAY) {
+ goto LBL_P1;
+ }
+ if ((res = mp_jacobi (&p1, &a1, &r)) != MP_OKAY) {
+ goto LBL_P1;
+ }
+ *c = s * r;
+ }
+
+ /* done */
+ res = MP_OKAY;
+LBL_P1:mp_clear (&p1);
+LBL_A1:mp_clear (&a1);
+ return res;
+}
+#endif
diff --git a/libtommath/bn_mp_karatsuba_mul.c b/libtommath/bn_mp_karatsuba_mul.c
new file mode 100644
index 0000000..0d62b9b
--- /dev/null
+++ b/libtommath/bn_mp_karatsuba_mul.c
@@ -0,0 +1,163 @@
+#include <tommath.h>
+#ifdef BN_MP_KARATSUBA_MUL_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* c = |a| * |b| using Karatsuba Multiplication using
+ * three half size multiplications
+ *
+ * Let B represent the radix [e.g. 2**DIGIT_BIT] and
+ * let n represent half of the number of digits in
+ * the min(a,b)
+ *
+ * a = a1 * B**n + a0
+ * b = b1 * B**n + b0
+ *
+ * Then, a * b =>
+ a1b1 * B**2n + ((a1 + a0)(b1 + b0) - (a0b0 + a1b1)) * B + a0b0
+ *
+ * Note that a1b1 and a0b0 are used twice and only need to be
+ * computed once. So in total three half size (half # of
+ * digit) multiplications are performed, a0b0, a1b1 and
+ * (a1+b1)(a0+b0)
+ *
+ * Note that a multiplication of half the digits requires
+ * 1/4th the number of single precision multiplications so in
+ * total after one call 25% of the single precision multiplications
+ * are saved. Note also that the call to mp_mul can end up back
+ * in this function if the a0, a1, b0, or b1 are above the threshold.
+ * This is known as divide-and-conquer and leads to the famous
+ * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than
+ * the standard O(N**2) that the baseline/comba methods use.
+ * Generally though the overhead of this method doesn't pay off
+ * until a certain size (N ~ 80) is reached.
+ */
+int mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int x0, x1, y0, y1, t1, x0y0, x1y1;
+ int B, err;
+
+ /* default the return code to an error */
+ err = MP_MEM;
+
+ /* min # of digits */
+ B = MIN (a->used, b->used);
+
+ /* now divide in two */
+ B = B >> 1;
+
+ /* init copy all the temps */
+ if (mp_init_size (&x0, B) != MP_OKAY)
+ goto ERR;
+ if (mp_init_size (&x1, a->used - B) != MP_OKAY)
+ goto X0;
+ if (mp_init_size (&y0, B) != MP_OKAY)
+ goto X1;
+ if (mp_init_size (&y1, b->used - B) != MP_OKAY)
+ goto Y0;
+
+ /* init temps */
+ if (mp_init_size (&t1, B * 2) != MP_OKAY)
+ goto Y1;
+ if (mp_init_size (&x0y0, B * 2) != MP_OKAY)
+ goto T1;
+ if (mp_init_size (&x1y1, B * 2) != MP_OKAY)
+ goto X0Y0;
+
+ /* now shift the digits */
+ x0.used = y0.used = B;
+ x1.used = a->used - B;
+ y1.used = b->used - B;
+
+ {
+ register int x;
+ register mp_digit *tmpa, *tmpb, *tmpx, *tmpy;
+
+ /* we copy the digits directly instead of using higher level functions
+ * since we also need to shift the digits
+ */
+ tmpa = a->dp;
+ tmpb = b->dp;
+
+ tmpx = x0.dp;
+ tmpy = y0.dp;
+ for (x = 0; x < B; x++) {
+ *tmpx++ = *tmpa++;
+ *tmpy++ = *tmpb++;
+ }
+
+ tmpx = x1.dp;
+ for (x = B; x < a->used; x++) {
+ *tmpx++ = *tmpa++;
+ }
+
+ tmpy = y1.dp;
+ for (x = B; x < b->used; x++) {
+ *tmpy++ = *tmpb++;
+ }
+ }
+
+ /* only need to clamp the lower words since by definition the
+ * upper words x1/y1 must have a known number of digits
+ */
+ mp_clamp (&x0);
+ mp_clamp (&y0);
+
+ /* now calc the products x0y0 and x1y1 */
+ /* after this x0 is no longer required, free temp [x0==t2]! */
+ if (mp_mul (&x0, &y0, &x0y0) != MP_OKAY)
+ goto X1Y1; /* x0y0 = x0*y0 */
+ if (mp_mul (&x1, &y1, &x1y1) != MP_OKAY)
+ goto X1Y1; /* x1y1 = x1*y1 */
+
+ /* now calc x1+x0 and y1+y0 */
+ if (s_mp_add (&x1, &x0, &t1) != MP_OKAY)
+ goto X1Y1; /* t1 = x1 - x0 */
+ if (s_mp_add (&y1, &y0, &x0) != MP_OKAY)
+ goto X1Y1; /* t2 = y1 - y0 */
+ if (mp_mul (&t1, &x0, &t1) != MP_OKAY)
+ goto X1Y1; /* t1 = (x1 + x0) * (y1 + y0) */
+
+ /* add x0y0 */
+ if (mp_add (&x0y0, &x1y1, &x0) != MP_OKAY)
+ goto X1Y1; /* t2 = x0y0 + x1y1 */
+ if (s_mp_sub (&t1, &x0, &t1) != MP_OKAY)
+ goto X1Y1; /* t1 = (x1+x0)*(y1+y0) - (x1y1 + x0y0) */
+
+ /* shift by B */
+ if (mp_lshd (&t1, B) != MP_OKAY)
+ goto X1Y1; /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<<B */
+ if (mp_lshd (&x1y1, B * 2) != MP_OKAY)
+ goto X1Y1; /* x1y1 = x1y1 << 2*B */
+
+ if (mp_add (&x0y0, &t1, &t1) != MP_OKAY)
+ goto X1Y1; /* t1 = x0y0 + t1 */
+ if (mp_add (&t1, &x1y1, c) != MP_OKAY)
+ goto X1Y1; /* t1 = x0y0 + t1 + x1y1 */
+
+ /* Algorithm succeeded set the return code to MP_OKAY */
+ err = MP_OKAY;
+
+X1Y1:mp_clear (&x1y1);
+X0Y0:mp_clear (&x0y0);
+T1:mp_clear (&t1);
+Y1:mp_clear (&y1);
+Y0:mp_clear (&y0);
+X1:mp_clear (&x1);
+X0:mp_clear (&x0);
+ERR:
+ return err;
+}
+#endif
diff --git a/libtommath/bn_mp_karatsuba_sqr.c b/libtommath/bn_mp_karatsuba_sqr.c
new file mode 100644
index 0000000..829405a
--- /dev/null
+++ b/libtommath/bn_mp_karatsuba_sqr.c
@@ -0,0 +1,117 @@
+#include <tommath.h>
+#ifdef BN_MP_KARATSUBA_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* Karatsuba squaring, computes b = a*a using three
+ * half size squarings
+ *
+ * See comments of karatsuba_mul for details. It
+ * is essentially the same algorithm but merely
+ * tuned to perform recursive squarings.
+ */
+int mp_karatsuba_sqr (mp_int * a, mp_int * b)
+{
+ mp_int x0, x1, t1, t2, x0x0, x1x1;
+ int B, err;
+
+ err = MP_MEM;
+
+ /* min # of digits */
+ B = a->used;
+
+ /* now divide in two */
+ B = B >> 1;
+
+ /* init copy all the temps */
+ if (mp_init_size (&x0, B) != MP_OKAY)
+ goto ERR;
+ if (mp_init_size (&x1, a->used - B) != MP_OKAY)
+ goto X0;
+
+ /* init temps */
+ if (mp_init_size (&t1, a->used * 2) != MP_OKAY)
+ goto X1;
+ if (mp_init_size (&t2, a->used * 2) != MP_OKAY)
+ goto T1;
+ if (mp_init_size (&x0x0, B * 2) != MP_OKAY)
+ goto T2;
+ if (mp_init_size (&x1x1, (a->used - B) * 2) != MP_OKAY)
+ goto X0X0;
+
+ {
+ register int x;
+ register mp_digit *dst, *src;
+
+ src = a->dp;
+
+ /* now shift the digits */
+ dst = x0.dp;
+ for (x = 0; x < B; x++) {
+ *dst++ = *src++;
+ }
+
+ dst = x1.dp;
+ for (x = B; x < a->used; x++) {
+ *dst++ = *src++;
+ }
+ }
+
+ x0.used = B;
+ x1.used = a->used - B;
+
+ mp_clamp (&x0);
+
+ /* now calc the products x0*x0 and x1*x1 */
+ if (mp_sqr (&x0, &x0x0) != MP_OKAY)
+ goto X1X1; /* x0x0 = x0*x0 */
+ if (mp_sqr (&x1, &x1x1) != MP_OKAY)
+ goto X1X1; /* x1x1 = x1*x1 */
+
+ /* now calc (x1+x0)**2 */
+ if (s_mp_add (&x1, &x0, &t1) != MP_OKAY)
+ goto X1X1; /* t1 = x1 - x0 */
+ if (mp_sqr (&t1, &t1) != MP_OKAY)
+ goto X1X1; /* t1 = (x1 - x0) * (x1 - x0) */
+
+ /* add x0y0 */
+ if (s_mp_add (&x0x0, &x1x1, &t2) != MP_OKAY)
+ goto X1X1; /* t2 = x0x0 + x1x1 */
+ if (s_mp_sub (&t1, &t2, &t1) != MP_OKAY)
+ goto X1X1; /* t1 = (x1+x0)**2 - (x0x0 + x1x1) */
+
+ /* shift by B */
+ if (mp_lshd (&t1, B) != MP_OKAY)
+ goto X1X1; /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<<B */
+ if (mp_lshd (&x1x1, B * 2) != MP_OKAY)
+ goto X1X1; /* x1x1 = x1x1 << 2*B */
+
+ if (mp_add (&x0x0, &t1, &t1) != MP_OKAY)
+ goto X1X1; /* t1 = x0x0 + t1 */
+ if (mp_add (&t1, &x1x1, b) != MP_OKAY)
+ goto X1X1; /* t1 = x0x0 + t1 + x1x1 */
+
+ err = MP_OKAY;
+
+X1X1:mp_clear (&x1x1);
+X0X0:mp_clear (&x0x0);
+T2:mp_clear (&t2);
+T1:mp_clear (&t1);
+X1:mp_clear (&x1);
+X0:mp_clear (&x0);
+ERR:
+ return err;
+}
+#endif
diff --git a/libtommath/bn_mp_lcm.c b/libtommath/bn_mp_lcm.c
new file mode 100644
index 0000000..1d53921
--- /dev/null
+++ b/libtommath/bn_mp_lcm.c
@@ -0,0 +1,56 @@
+#include <tommath.h>
+#ifdef BN_MP_LCM_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* computes least common multiple as |a*b|/(a, b) */
+int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res;
+ mp_int t1, t2;
+
+
+ if ((res = mp_init_multi (&t1, &t2, NULL)) != MP_OKAY) {
+ return res;
+ }
+
+ /* t1 = get the GCD of the two inputs */
+ if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) {
+ goto LBL_T;
+ }
+
+ /* divide the smallest by the GCD */
+ if (mp_cmp_mag(a, b) == MP_LT) {
+ /* store quotient in t2 such that t2 * b is the LCM */
+ if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) {
+ goto LBL_T;
+ }
+ res = mp_mul(b, &t2, c);
+ } else {
+ /* store quotient in t2 such that t2 * a is the LCM */
+ if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) {
+ goto LBL_T;
+ }
+ res = mp_mul(a, &t2, c);
+ }
+
+ /* fix the sign to positive */
+ c->sign = MP_ZPOS;
+
+LBL_T:
+ mp_clear_multi (&t1, &t2, NULL);
+ return res;
+}
+#endif
diff --git a/libtommath/bn_mp_lshd.c b/libtommath/bn_mp_lshd.c
new file mode 100644
index 0000000..ce1e63b
--- /dev/null
+++ b/libtommath/bn_mp_lshd.c
@@ -0,0 +1,63 @@
+#include <tommath.h>
+#ifdef BN_MP_LSHD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* shift left a certain amount of digits */
+int mp_lshd (mp_int * a, int b)
+{
+ int x, res;
+
+ /* if its less than zero return */
+ if (b <= 0) {
+ return MP_OKAY;
+ }
+
+ /* grow to fit the new digits */
+ if (a->alloc < a->used + b) {
+ if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ {
+ register mp_digit *top, *bottom;
+
+ /* increment the used by the shift amount then copy upwards */
+ a->used += b;
+
+ /* top */
+ top = a->dp + a->used - 1;
+
+ /* base */
+ bottom = a->dp + a->used - 1 - b;
+
+ /* much like mp_rshd this is implemented using a sliding window
+ * except the window goes the otherway around. Copying from
+ * the bottom to the top. see bn_mp_rshd.c for more info.
+ */
+ for (x = a->used - 1; x >= b; x--) {
+ *top-- = *bottom--;
+ }
+
+ /* zero the lower digits */
+ top = a->dp;
+ for (x = 0; x < b; x++) {
+ *top++ = 0;
+ }
+ }
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_mod.c b/libtommath/bn_mp_mod.c
new file mode 100644
index 0000000..98e155e
--- /dev/null
+++ b/libtommath/bn_mp_mod.c
@@ -0,0 +1,44 @@
+#include <tommath.h>
+#ifdef BN_MP_MOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* c = a mod b, 0 <= c < b */
+int
+mp_mod (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int t;
+ int res;
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+
+ if (t.sign != b->sign) {
+ res = mp_add (b, &t, c);
+ } else {
+ res = MP_OKAY;
+ mp_exch (&t, c);
+ }
+
+ mp_clear (&t);
+ return res;
+}
+#endif
diff --git a/libtommath/bn_mp_mod_2d.c b/libtommath/bn_mp_mod_2d.c
new file mode 100644
index 0000000..25868cd
--- /dev/null
+++ b/libtommath/bn_mp_mod_2d.c
@@ -0,0 +1,51 @@
+#include <tommath.h>
+#ifdef BN_MP_MOD_2D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* calc a value mod 2**b */
+int
+mp_mod_2d (mp_int * a, int b, mp_int * c)
+{
+ int x, res;
+
+ /* if b is <= 0 then zero the int */
+ if (b <= 0) {
+ mp_zero (c);
+ return MP_OKAY;
+ }
+
+ /* if the modulus is larger than the value than return */
+ if (b >= (int) (a->used * DIGIT_BIT)) {
+ res = mp_copy (a, c);
+ return res;
+ }
+
+ /* copy */
+ if ((res = mp_copy (a, c)) != MP_OKAY) {
+ return res;
+ }
+
+ /* zero digits above the last digit of the modulus */
+ for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
+ c->dp[x] = 0;
+ }
+ /* clear the digit that is not completely outside/inside the modulus */
+ c->dp[b / DIGIT_BIT] &=
+ (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1));
+ mp_clamp (c);
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_mod_d.c b/libtommath/bn_mp_mod_d.c
new file mode 100644
index 0000000..f642ee8
--- /dev/null
+++ b/libtommath/bn_mp_mod_d.c
@@ -0,0 +1,23 @@
+#include <tommath.h>
+#ifdef BN_MP_MOD_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+int
+mp_mod_d (mp_int * a, mp_digit b, mp_digit * c)
+{
+ return mp_div_d(a, b, NULL, c);
+}
+#endif
diff --git a/libtommath/bn_mp_montgomery_calc_normalization.c b/libtommath/bn_mp_montgomery_calc_normalization.c
new file mode 100644
index 0000000..0748762
--- /dev/null
+++ b/libtommath/bn_mp_montgomery_calc_normalization.c
@@ -0,0 +1,55 @@
+#include <tommath.h>
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/*
+ * shifts with subtractions when the result is greater than b.
+ *
+ * The method is slightly modified to shift B unconditionally upto just under
+ * the leading bit of b. This saves alot of multiple precision shifting.
+ */
+int mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
+{
+ int x, bits, res;
+
+ /* how many bits of last digit does b use */
+ bits = mp_count_bits (b) % DIGIT_BIT;
+
+ if (b->used > 1) {
+ if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) {
+ return res;
+ }
+ } else {
+ mp_set(a, 1);
+ bits = 1;
+ }
+
+
+ /* now compute C = A * B mod b */
+ for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
+ if ((res = mp_mul_2 (a, a)) != MP_OKAY) {
+ return res;
+ }
+ if (mp_cmp_mag (a, b) != MP_LT) {
+ if ((res = s_mp_sub (a, b, a)) != MP_OKAY) {
+ return res;
+ }
+ }
+ }
+
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_montgomery_reduce.c b/libtommath/bn_mp_montgomery_reduce.c
new file mode 100644
index 0000000..bc6abb8
--- /dev/null
+++ b/libtommath/bn_mp_montgomery_reduce.c
@@ -0,0 +1,114 @@
+#include <tommath.h>
+#ifdef BN_MP_MONTGOMERY_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction */
+int
+mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+ int ix, res, digs;
+ mp_digit mu;
+
+ /* can the fast reduction [comba] method be used?
+ *
+ * Note that unlike in mul you're safely allowed *less*
+ * than the available columns [255 per default] since carries
+ * are fixed up in the inner loop.
+ */
+ digs = n->used * 2 + 1;
+ if ((digs < MP_WARRAY) &&
+ n->used <
+ (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ return fast_mp_montgomery_reduce (x, n, rho);
+ }
+
+ /* grow the input as required */
+ if (x->alloc < digs) {
+ if ((res = mp_grow (x, digs)) != MP_OKAY) {
+ return res;
+ }
+ }
+ x->used = digs;
+
+ for (ix = 0; ix < n->used; ix++) {
+ /* mu = ai * rho mod b
+ *
+ * The value of rho must be precalculated via
+ * montgomery_setup() such that
+ * it equals -1/n0 mod b this allows the
+ * following inner loop to reduce the
+ * input one digit at a time
+ */
+ mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK);
+
+ /* a = a + mu * m * b**i */
+ {
+ register int iy;
+ register mp_digit *tmpn, *tmpx, u;
+ register mp_word r;
+
+ /* alias for digits of the modulus */
+ tmpn = n->dp;
+
+ /* alias for the digits of x [the input] */
+ tmpx = x->dp + ix;
+
+ /* set the carry to zero */
+ u = 0;
+
+ /* Multiply and add in place */
+ for (iy = 0; iy < n->used; iy++) {
+ /* compute product and sum */
+ r = ((mp_word)mu) * ((mp_word)*tmpn++) +
+ ((mp_word) u) + ((mp_word) * tmpx);
+
+ /* get carry */
+ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+ /* fix digit */
+ *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK));
+ }
+ /* At this point the ix'th digit of x should be zero */
+
+
+ /* propagate carries upwards as required*/
+ while (u) {
+ *tmpx += u;
+ u = *tmpx >> DIGIT_BIT;
+ *tmpx++ &= MP_MASK;
+ }
+ }
+ }
+
+ /* at this point the n.used'th least
+ * significant digits of x are all zero
+ * which means we can shift x to the
+ * right by n.used digits and the
+ * residue is unchanged.
+ */
+
+ /* x = x/b**n.used */
+ mp_clamp(x);
+ mp_rshd (x, n->used);
+
+ /* if x >= n then x = x - n */
+ if (mp_cmp_mag (x, n) != MP_LT) {
+ return s_mp_sub (x, n, x);
+ }
+
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_montgomery_setup.c b/libtommath/bn_mp_montgomery_setup.c
new file mode 100644
index 0000000..b8e1887
--- /dev/null
+++ b/libtommath/bn_mp_montgomery_setup.c
@@ -0,0 +1,55 @@
+#include <tommath.h>
+#ifdef BN_MP_MONTGOMERY_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* setups the montgomery reduction stuff */
+int
+mp_montgomery_setup (mp_int * n, mp_digit * rho)
+{
+ mp_digit x, b;
+
+/* fast inversion mod 2**k
+ *
+ * Based on the fact that
+ *
+ * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n)
+ * => 2*X*A - X*X*A*A = 1
+ * => 2*(1) - (1) = 1
+ */
+ b = n->dp[0];
+
+ if ((b & 1) == 0) {
+ return MP_VAL;
+ }
+
+ x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
+ x *= 2 - b * x; /* here x*a==1 mod 2**8 */
+#if !defined(MP_8BIT)
+ x *= 2 - b * x; /* here x*a==1 mod 2**16 */
+#endif
+#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
+ x *= 2 - b * x; /* here x*a==1 mod 2**32 */
+#endif
+#ifdef MP_64BIT
+ x *= 2 - b * x; /* here x*a==1 mod 2**64 */
+#endif
+
+ /* rho = -1/m mod b */
+ *rho = (unsigned long)(((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK;
+
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_mul.c b/libtommath/bn_mp_mul.c
new file mode 100644
index 0000000..fc024be
--- /dev/null
+++ b/libtommath/bn_mp_mul.c
@@ -0,0 +1,62 @@
+#include <tommath.h>
+#ifdef BN_MP_MUL_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* high level multiplication (handles sign) */
+int mp_mul (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res, neg;
+ neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+
+ /* use Toom-Cook? */
+#ifdef BN_MP_TOOM_MUL_C
+ if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) {
+ res = mp_toom_mul(a, b, c);
+ } else
+#endif
+#ifdef BN_MP_KARATSUBA_MUL_C
+ /* use Karatsuba? */
+ if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) {
+ res = mp_karatsuba_mul (a, b, c);
+ } else
+#endif
+ {
+ /* can we use the fast multiplier?
+ *
+ * The fast multiplier can be used if the output will
+ * have less than MP_WARRAY digits and the number of
+ * digits won't affect carry propagation
+ */
+ int digs = a->used + b->used + 1;
+
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
+ if ((digs < MP_WARRAY) &&
+ MIN(a->used, b->used) <=
+ (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ res = fast_s_mp_mul_digs (a, b, c, digs);
+ } else
+#endif
+#ifdef BN_S_MP_MUL_DIGS_C
+ res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */
+#else
+ res = MP_VAL;
+#endif
+
+ }
+ c->sign = (c->used > 0) ? neg : MP_ZPOS;
+ return res;
+}
+#endif
diff --git a/libtommath/bn_mp_mul_2.c b/libtommath/bn_mp_mul_2.c
new file mode 100644
index 0000000..2ca6022
--- /dev/null
+++ b/libtommath/bn_mp_mul_2.c
@@ -0,0 +1,78 @@
+#include <tommath.h>
+#ifdef BN_MP_MUL_2_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* b = a*2 */
+int mp_mul_2(mp_int * a, mp_int * b)
+{
+ int x, res, oldused;
+
+ /* grow to accomodate result */
+ if (b->alloc < a->used + 1) {
+ if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ oldused = b->used;
+ b->used = a->used;
+
+ {
+ register mp_digit r, rr, *tmpa, *tmpb;
+
+ /* alias for source */
+ tmpa = a->dp;
+
+ /* alias for dest */
+ tmpb = b->dp;
+
+ /* carry */
+ r = 0;
+ for (x = 0; x < a->used; x++) {
+
+ /* get what will be the *next* carry bit from the
+ * MSB of the current digit
+ */
+ rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
+
+ /* now shift up this digit, add in the carry [from the previous] */
+ *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
+
+ /* copy the carry that would be from the source
+ * digit into the next iteration
+ */
+ r = rr;
+ }
+
+ /* new leading digit? */
+ if (r != 0) {
+ /* add a MSB which is always 1 at this point */
+ *tmpb = 1;
+ ++(b->used);
+ }
+
+ /* now zero any excess digits on the destination
+ * that we didn't write to
+ */
+ tmpb = b->dp + b->used;
+ for (x = b->used; x < oldused; x++) {
+ *tmpb++ = 0;
+ }
+ }
+ b->sign = a->sign;
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_mul_2d.c b/libtommath/bn_mp_mul_2d.c
new file mode 100644
index 0000000..cabff13
--- /dev/null
+++ b/libtommath/bn_mp_mul_2d.c
@@ -0,0 +1,81 @@
+#include <tommath.h>
+#ifdef BN_MP_MUL_2D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* shift left by a certain bit count */
+int mp_mul_2d (mp_int * a, int b, mp_int * c)
+{
+ mp_digit d;
+ int res;
+
+ /* copy */
+ if (a != c) {
+ if ((res = mp_copy (a, c)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) {
+ if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* shift by as many digits in the bit count */
+ if (b >= (int)DIGIT_BIT) {
+ if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* shift any bit count < DIGIT_BIT */
+ d = (mp_digit) (b % DIGIT_BIT);
+ if (d != 0) {
+ register mp_digit *tmpc, shift, mask, r, rr;
+ register int x;
+
+ /* bitmask for carries */
+ mask = (((mp_digit)1) << d) - 1;
+
+ /* shift for msbs */
+ shift = DIGIT_BIT - d;
+
+ /* alias */
+ tmpc = c->dp;
+
+ /* carry */
+ r = 0;
+ for (x = 0; x < c->used; x++) {
+ /* get the higher bits of the current word */
+ rr = (*tmpc >> shift) & mask;
+
+ /* shift the current word and OR in the carry */
+ *tmpc = ((*tmpc << d) | r) & MP_MASK;
+ ++tmpc;
+
+ /* set the carry to the carry bits of the current word */
+ r = rr;
+ }
+
+ /* set final carry */
+ if (r != 0) {
+ c->dp[(c->used)++] = r;
+ }
+ }
+ mp_clamp (c);
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_mul_d.c b/libtommath/bn_mp_mul_d.c
new file mode 100644
index 0000000..ba45a0c
--- /dev/null
+++ b/libtommath/bn_mp_mul_d.c
@@ -0,0 +1,75 @@
+#include <tommath.h>
+#ifdef BN_MP_MUL_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* multiply by a digit */
+int
+mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
+{
+ mp_digit u, *tmpa, *tmpc;
+ mp_word r;
+ int ix, res, olduse;
+
+ /* make sure c is big enough to hold a*b */
+ if (c->alloc < a->used + 1) {
+ if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* get the original destinations used count */
+ olduse = c->used;
+
+ /* set the sign */
+ c->sign = a->sign;
+
+ /* alias for a->dp [source] */
+ tmpa = a->dp;
+
+ /* alias for c->dp [dest] */
+ tmpc = c->dp;
+
+ /* zero carry */
+ u = 0;
+
+ /* compute columns */
+ for (ix = 0; ix < a->used; ix++) {
+ /* compute product and carry sum for this term */
+ r = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
+
+ /* mask off higher bits to get a single digit */
+ *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* send carry into next iteration */
+ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+ }
+
+ /* store final carry [if any] and increment ix offset */
+ *tmpc++ = u;
+ ++ix;
+
+ /* now zero digits above the top */
+ while (ix++ < olduse) {
+ *tmpc++ = 0;
+ }
+
+ /* set used count */
+ c->used = a->used + 1;
+ mp_clamp(c);
+
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_mulmod.c b/libtommath/bn_mp_mulmod.c
new file mode 100644
index 0000000..649b717
--- /dev/null
+++ b/libtommath/bn_mp_mulmod.c
@@ -0,0 +1,36 @@
+#include <tommath.h>
+#ifdef BN_MP_MULMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* d = a * b (mod c) */
+int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+ int res;
+ mp_int t;
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_mul (a, b, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ res = mp_mod (&t, c, d);
+ mp_clear (&t);
+ return res;
+}
+#endif
diff --git a/libtommath/bn_mp_n_root.c b/libtommath/bn_mp_n_root.c
new file mode 100644
index 0000000..b2700a8
--- /dev/null
+++ b/libtommath/bn_mp_n_root.c
@@ -0,0 +1,128 @@
+#include <tommath.h>
+#ifdef BN_MP_N_ROOT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* find the n'th root of an integer
+ *
+ * Result found such that (c)**b <= a and (c+1)**b > a
+ *
+ * This algorithm uses Newton's approximation
+ * x[i+1] = x[i] - f(x[i])/f'(x[i])
+ * which will find the root in log(N) time where
+ * each step involves a fair bit. This is not meant to
+ * find huge roots [square and cube, etc].
+ */
+int mp_n_root (mp_int * a, mp_digit b, mp_int * c)
+{
+ mp_int t1, t2, t3;
+ int res, neg;
+
+ /* input must be positive if b is even */
+ if ((b & 1) == 0 && a->sign == MP_NEG) {
+ return MP_VAL;
+ }
+
+ if ((res = mp_init (&t1)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_init (&t2)) != MP_OKAY) {
+ goto LBL_T1;
+ }
+
+ if ((res = mp_init (&t3)) != MP_OKAY) {
+ goto LBL_T2;
+ }
+
+ /* if a is negative fudge the sign but keep track */
+ neg = a->sign;
+ a->sign = MP_ZPOS;
+
+ /* t2 = 2 */
+ mp_set (&t2, 2);
+
+ do {
+ /* t1 = t2 */
+ if ((res = mp_copy (&t2, &t1)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */
+
+ /* t3 = t1**(b-1) */
+ if ((res = mp_expt_d (&t1, b - 1, &t3)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ /* numerator */
+ /* t2 = t1**b */
+ if ((res = mp_mul (&t3, &t1, &t2)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ /* t2 = t1**b - a */
+ if ((res = mp_sub (&t2, a, &t2)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ /* denominator */
+ /* t3 = t1**(b-1) * b */
+ if ((res = mp_mul_d (&t3, b, &t3)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ /* t3 = (t1**b - a)/(b * t1**(b-1)) */
+ if ((res = mp_div (&t2, &t3, &t3, NULL)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ if ((res = mp_sub (&t1, &t3, &t2)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+ } while (mp_cmp (&t1, &t2) != MP_EQ);
+
+ /* result can be off by a few so check */
+ for (;;) {
+ if ((res = mp_expt_d (&t1, b, &t2)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ if (mp_cmp (&t2, a) == MP_GT) {
+ if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+ } else {
+ break;
+ }
+ }
+
+ /* reset the sign of a first */
+ a->sign = neg;
+
+ /* set the result */
+ mp_exch (&t1, c);
+
+ /* set the sign of the result */
+ c->sign = neg;
+
+ res = MP_OKAY;
+
+LBL_T3:mp_clear (&t3);
+LBL_T2:mp_clear (&t2);
+LBL_T1:mp_clear (&t1);
+ return res;
+}
+#endif
diff --git a/libtommath/bn_mp_neg.c b/libtommath/bn_mp_neg.c
new file mode 100644
index 0000000..777b59b
--- /dev/null
+++ b/libtommath/bn_mp_neg.c
@@ -0,0 +1,36 @@
+#include <tommath.h>
+#ifdef BN_MP_NEG_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* b = -a */
+int mp_neg (mp_int * a, mp_int * b)
+{
+ int res;
+ if (a != b) {
+ if ((res = mp_copy (a, b)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ if (mp_iszero(b) != MP_YES) {
+ b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS;
+ } else {
+ b->sign = MP_ZPOS;
+ }
+
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_or.c b/libtommath/bn_mp_or.c
new file mode 100644
index 0000000..aa5b1bd
--- /dev/null
+++ b/libtommath/bn_mp_or.c
@@ -0,0 +1,46 @@
+#include <tommath.h>
+#ifdef BN_MP_OR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* OR two ints together */
+int mp_or (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res, ix, px;
+ mp_int t, *x;
+
+ if (a->used > b->used) {
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+ px = b->used;
+ x = b;
+ } else {
+ if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+ return res;
+ }
+ px = a->used;
+ x = a;
+ }
+
+ for (ix = 0; ix < px; ix++) {
+ t.dp[ix] |= x->dp[ix];
+ }
+ mp_clamp (&t);
+ mp_exch (c, &t);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_prime_fermat.c b/libtommath/bn_mp_prime_fermat.c
new file mode 100644
index 0000000..7b9b12e
--- /dev/null
+++ b/libtommath/bn_mp_prime_fermat.c
@@ -0,0 +1,58 @@
+#include <tommath.h>
+#ifdef BN_MP_PRIME_FERMAT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* performs one Fermat test.
+ *
+ * If "a" were prime then b**a == b (mod a) since the order of
+ * the multiplicative sub-group would be phi(a) = a-1. That means
+ * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a).
+ *
+ * Sets result to 1 if the congruence holds, or zero otherwise.
+ */
+int mp_prime_fermat (mp_int * a, mp_int * b, int *result)
+{
+ mp_int t;
+ int err;
+
+ /* default to composite */
+ *result = MP_NO;
+
+ /* ensure b > 1 */
+ if (mp_cmp_d(b, 1) != MP_GT) {
+ return MP_VAL;
+ }
+
+ /* init t */
+ if ((err = mp_init (&t)) != MP_OKAY) {
+ return err;
+ }
+
+ /* compute t = b**a mod a */
+ if ((err = mp_exptmod (b, a, a, &t)) != MP_OKAY) {
+ goto LBL_T;
+ }
+
+ /* is it equal to b? */
+ if (mp_cmp (&t, b) == MP_EQ) {
+ *result = MP_YES;
+ }
+
+ err = MP_OKAY;
+LBL_T:mp_clear (&t);
+ return err;
+}
+#endif
diff --git a/libtommath/bn_mp_prime_is_divisible.c b/libtommath/bn_mp_prime_is_divisible.c
new file mode 100644
index 0000000..710c967
--- /dev/null
+++ b/libtommath/bn_mp_prime_is_divisible.c
@@ -0,0 +1,46 @@
+#include <tommath.h>
+#ifdef BN_MP_PRIME_IS_DIVISIBLE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* determines if an integers is divisible by one
+ * of the first PRIME_SIZE primes or not
+ *
+ * sets result to 0 if not, 1 if yes
+ */
+int mp_prime_is_divisible (mp_int * a, int *result)
+{
+ int err, ix;
+ mp_digit res;
+
+ /* default to not */
+ *result = MP_NO;
+
+ for (ix = 0; ix < PRIME_SIZE; ix++) {
+ /* what is a mod LBL_prime_tab[ix] */
+ if ((err = mp_mod_d (a, ltm_prime_tab[ix], &res)) != MP_OKAY) {
+ return err;
+ }
+
+ /* is the residue zero? */
+ if (res == 0) {
+ *result = MP_YES;
+ return MP_OKAY;
+ }
+ }
+
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_prime_is_prime.c b/libtommath/bn_mp_prime_is_prime.c
new file mode 100644
index 0000000..ce225a3
--- /dev/null
+++ b/libtommath/bn_mp_prime_is_prime.c
@@ -0,0 +1,79 @@
+#include <tommath.h>
+#ifdef BN_MP_PRIME_IS_PRIME_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* performs a variable number of rounds of Miller-Rabin
+ *
+ * Probability of error after t rounds is no more than
+
+ *
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+int mp_prime_is_prime (mp_int * a, int t, int *result)
+{
+ mp_int b;
+ int ix, err, res;
+
+ /* default to no */
+ *result = MP_NO;
+
+ /* valid value of t? */
+ if (t <= 0 || t > PRIME_SIZE) {
+ return MP_VAL;
+ }
+
+ /* is the input equal to one of the primes in the table? */
+ for (ix = 0; ix < PRIME_SIZE; ix++) {
+ if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) {
+ *result = 1;
+ return MP_OKAY;
+ }
+ }
+
+ /* first perform trial division */
+ if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) {
+ return err;
+ }
+
+ /* return if it was trivially divisible */
+ if (res == MP_YES) {
+ return MP_OKAY;
+ }
+
+ /* now perform the miller-rabin rounds */
+ if ((err = mp_init (&b)) != MP_OKAY) {
+ return err;
+ }
+
+ for (ix = 0; ix < t; ix++) {
+ /* set the prime */
+ mp_set (&b, ltm_prime_tab[ix]);
+
+ if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) {
+ goto LBL_B;
+ }
+
+ if (res == MP_NO) {
+ goto LBL_B;
+ }
+ }
+
+ /* passed the test */
+ *result = MP_YES;
+LBL_B:mp_clear (&b);
+ return err;
+}
+#endif
diff --git a/libtommath/bn_mp_prime_miller_rabin.c b/libtommath/bn_mp_prime_miller_rabin.c
new file mode 100644
index 0000000..c5185b8
--- /dev/null
+++ b/libtommath/bn_mp_prime_miller_rabin.c
@@ -0,0 +1,99 @@
+#include <tommath.h>
+#ifdef BN_MP_PRIME_MILLER_RABIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* Miller-Rabin test of "a" to the base of "b" as described in
+ * HAC pp. 139 Algorithm 4.24
+ *
+ * Sets result to 0 if definitely composite or 1 if probably prime.
+ * Randomly the chance of error is no more than 1/4 and often
+ * very much lower.
+ */
+int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
+{
+ mp_int n1, y, r;
+ int s, j, err;
+
+ /* default */
+ *result = MP_NO;
+
+ /* ensure b > 1 */
+ if (mp_cmp_d(b, 1) != MP_GT) {
+ return MP_VAL;
+ }
+
+ /* get n1 = a - 1 */
+ if ((err = mp_init_copy (&n1, a)) != MP_OKAY) {
+ return err;
+ }
+ if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) {
+ goto LBL_N1;
+ }
+
+ /* set 2**s * r = n1 */
+ if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) {
+ goto LBL_N1;
+ }
+
+ /* count the number of least significant bits
+ * which are zero
+ */
+ s = mp_cnt_lsb(&r);
+
+ /* now divide n - 1 by 2**s */
+ if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) {
+ goto LBL_R;
+ }
+
+ /* compute y = b**r mod a */
+ if ((err = mp_init (&y)) != MP_OKAY) {
+ goto LBL_R;
+ }
+ if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ /* if y != 1 and y != n1 do */
+ if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) {
+ j = 1;
+ /* while j <= s-1 and y != n1 */
+ while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) {
+ if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ /* if y == 1 then composite */
+ if (mp_cmp_d (&y, 1) == MP_EQ) {
+ goto LBL_Y;
+ }
+
+ ++j;
+ }
+
+ /* if y != n1 then composite */
+ if (mp_cmp (&y, &n1) != MP_EQ) {
+ goto LBL_Y;
+ }
+ }
+
+ /* probably prime now */
+ *result = MP_YES;
+LBL_Y:mp_clear (&y);
+LBL_R:mp_clear (&r);
+LBL_N1:mp_clear (&n1);
+ return err;
+}
+#endif
diff --git a/libtommath/bn_mp_prime_next_prime.c b/libtommath/bn_mp_prime_next_prime.c
new file mode 100644
index 0000000..2433e8c
--- /dev/null
+++ b/libtommath/bn_mp_prime_next_prime.c
@@ -0,0 +1,166 @@
+#include <tommath.h>
+#ifdef BN_MP_PRIME_NEXT_PRIME_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* finds the next prime after the number "a" using "t" trials
+ * of Miller-Rabin.
+ *
+ * bbs_style = 1 means the prime must be congruent to 3 mod 4
+ */
+int mp_prime_next_prime(mp_int *a, int t, int bbs_style)
+{
+ int err, res, x, y;
+ mp_digit res_tab[PRIME_SIZE], step, kstep;
+ mp_int b;
+
+ /* ensure t is valid */
+ if (t <= 0 || t > PRIME_SIZE) {
+ return MP_VAL;
+ }
+
+ /* force positive */
+ a->sign = MP_ZPOS;
+
+ /* simple algo if a is less than the largest prime in the table */
+ if (mp_cmp_d(a, ltm_prime_tab[PRIME_SIZE-1]) == MP_LT) {
+ /* find which prime it is bigger than */
+ for (x = PRIME_SIZE - 2; x >= 0; x--) {
+ if (mp_cmp_d(a, ltm_prime_tab[x]) != MP_LT) {
+ if (bbs_style == 1) {
+ /* ok we found a prime smaller or
+ * equal [so the next is larger]
+ *
+ * however, the prime must be
+ * congruent to 3 mod 4
+ */
+ if ((ltm_prime_tab[x + 1] & 3) != 3) {
+ /* scan upwards for a prime congruent to 3 mod 4 */
+ for (y = x + 1; y < PRIME_SIZE; y++) {
+ if ((ltm_prime_tab[y] & 3) == 3) {
+ mp_set(a, ltm_prime_tab[y]);
+ return MP_OKAY;
+ }
+ }
+ }
+ } else {
+ mp_set(a, ltm_prime_tab[x + 1]);
+ return MP_OKAY;
+ }
+ }
+ }
+ /* at this point a maybe 1 */
+ if (mp_cmp_d(a, 1) == MP_EQ) {
+ mp_set(a, 2);
+ return MP_OKAY;
+ }
+ /* fall through to the sieve */
+ }
+
+ /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */
+ if (bbs_style == 1) {
+ kstep = 4;
+ } else {
+ kstep = 2;
+ }
+
+ /* at this point we will use a combination of a sieve and Miller-Rabin */
+
+ if (bbs_style == 1) {
+ /* if a mod 4 != 3 subtract the correct value to make it so */
+ if ((a->dp[0] & 3) != 3) {
+ if ((err = mp_sub_d(a, (a->dp[0] & 3) + 1, a)) != MP_OKAY) { return err; };
+ }
+ } else {
+ if (mp_iseven(a) == 1) {
+ /* force odd */
+ if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) {
+ return err;
+ }
+ }
+ }
+
+ /* generate the restable */
+ for (x = 1; x < PRIME_SIZE; x++) {
+ if ((err = mp_mod_d(a, ltm_prime_tab[x], res_tab + x)) != MP_OKAY) {
+ return err;
+ }
+ }
+
+ /* init temp used for Miller-Rabin Testing */
+ if ((err = mp_init(&b)) != MP_OKAY) {
+ return err;
+ }
+
+ for (;;) {
+ /* skip to the next non-trivially divisible candidate */
+ step = 0;
+ do {
+ /* y == 1 if any residue was zero [e.g. cannot be prime] */
+ y = 0;
+
+ /* increase step to next candidate */
+ step += kstep;
+
+ /* compute the new residue without using division */
+ for (x = 1; x < PRIME_SIZE; x++) {
+ /* add the step to each residue */
+ res_tab[x] += kstep;
+
+ /* subtract the modulus [instead of using division] */
+ if (res_tab[x] >= ltm_prime_tab[x]) {
+ res_tab[x] -= ltm_prime_tab[x];
+ }
+
+ /* set flag if zero */
+ if (res_tab[x] == 0) {
+ y = 1;
+ }
+ }
+ } while (y == 1 && step < ((((mp_digit)1)<<DIGIT_BIT) - kstep));
+
+ /* add the step */
+ if ((err = mp_add_d(a, step, a)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ /* if didn't pass sieve and step == MAX then skip test */
+ if (y == 1 && step >= ((((mp_digit)1)<<DIGIT_BIT) - kstep)) {
+ continue;
+ }
+
+ /* is this prime? */
+ for (x = 0; x < t; x++) {
+ mp_set(&b, ltm_prime_tab[x]);
+ if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if (res == MP_NO) {
+ break;
+ }
+ }
+
+ if (res == MP_YES) {
+ break;
+ }
+ }
+
+ err = MP_OKAY;
+LBL_ERR:
+ mp_clear(&b);
+ return err;
+}
+
+#endif
diff --git a/libtommath/bn_mp_prime_rabin_miller_trials.c b/libtommath/bn_mp_prime_rabin_miller_trials.c
new file mode 100644
index 0000000..e57a43c
--- /dev/null
+++ b/libtommath/bn_mp_prime_rabin_miller_trials.c
@@ -0,0 +1,48 @@
+#include <tommath.h>
+#ifdef BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+
+static const struct {
+ int k, t;
+} sizes[] = {
+{ 128, 28 },
+{ 256, 16 },
+{ 384, 10 },
+{ 512, 7 },
+{ 640, 6 },
+{ 768, 5 },
+{ 896, 4 },
+{ 1024, 4 }
+};
+
+/* returns # of RM trials required for a given bit size */
+int mp_prime_rabin_miller_trials(int size)
+{
+ int x;
+
+ for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) {
+ if (sizes[x].k == size) {
+ return sizes[x].t;
+ } else if (sizes[x].k > size) {
+ return (x == 0) ? sizes[0].t : sizes[x - 1].t;
+ }
+ }
+ return sizes[x-1].t + 1;
+}
+
+
+#endif
diff --git a/libtommath/bn_mp_prime_random_ex.c b/libtommath/bn_mp_prime_random_ex.c
new file mode 100644
index 0000000..a37477e
--- /dev/null
+++ b/libtommath/bn_mp_prime_random_ex.c
@@ -0,0 +1,121 @@
+#include <tommath.h>
+#ifdef BN_MP_PRIME_RANDOM_EX_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* makes a truly random prime of a given size (bits),
+ *
+ * Flags are as follows:
+ *
+ * LTM_PRIME_BBS - make prime congruent to 3 mod 4
+ * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
+ * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
+ * LTM_PRIME_2MSB_ON - make the 2nd highest bit one
+ *
+ * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ */
+
+/* This is possibly the mother of all prime generation functions, muahahahahaha! */
+int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat)
+{
+ unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb;
+ int res, err, bsize, maskOR_msb_offset;
+
+ /* sanity check the input */
+ if (size <= 1 || t <= 0) {
+ return MP_VAL;
+ }
+
+ /* LTM_PRIME_SAFE implies LTM_PRIME_BBS */
+ if (flags & LTM_PRIME_SAFE) {
+ flags |= LTM_PRIME_BBS;
+ }
+
+ /* calc the byte size */
+ bsize = (size>>3) + ((size&7)?1:0);
+
+ /* we need a buffer of bsize bytes */
+ tmp = OPT_CAST(unsigned char) XMALLOC(bsize);
+ if (tmp == NULL) {
+ return MP_MEM;
+ }
+
+ /* calc the maskAND value for the MSbyte*/
+ maskAND = ((size&7) == 0) ? 0xFF : (0xFF >> (8 - (size & 7)));
+
+ /* calc the maskOR_msb */
+ maskOR_msb = 0;
+ maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0;
+ if (flags & LTM_PRIME_2MSB_ON) {
+ maskOR_msb |= 0x80 >> ((9 - size) & 7);
+ }
+
+ /* get the maskOR_lsb */
+ maskOR_lsb = 1;
+ if (flags & LTM_PRIME_BBS) {
+ maskOR_lsb |= 3;
+ }
+
+ do {
+ /* read the bytes */
+ if (cb(tmp, bsize, dat) != bsize) {
+ err = MP_VAL;
+ goto error;
+ }
+
+ /* work over the MSbyte */
+ tmp[0] &= maskAND;
+ tmp[0] |= 1 << ((size - 1) & 7);
+
+ /* mix in the maskORs */
+ tmp[maskOR_msb_offset] |= maskOR_msb;
+ tmp[bsize-1] |= maskOR_lsb;
+
+ /* read it in */
+ if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY) { goto error; }
+
+ /* is it prime? */
+ if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; }
+ if (res == MP_NO) {
+ continue;
+ }
+
+ if (flags & LTM_PRIME_SAFE) {
+ /* see if (a-1)/2 is prime */
+ if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) { goto error; }
+ if ((err = mp_div_2(a, a)) != MP_OKAY) { goto error; }
+
+ /* is it prime? */
+ if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; }
+ }
+ } while (res == MP_NO);
+
+ if (flags & LTM_PRIME_SAFE) {
+ /* restore a to the original value */
+ if ((err = mp_mul_2(a, a)) != MP_OKAY) { goto error; }
+ if ((err = mp_add_d(a, 1, a)) != MP_OKAY) { goto error; }
+ }
+
+ err = MP_OKAY;
+error:
+ XFREE(tmp);
+ return err;
+}
+
+
+#endif
diff --git a/libtommath/bn_mp_radix_size.c b/libtommath/bn_mp_radix_size.c
new file mode 100644
index 0000000..40c4d04
--- /dev/null
+++ b/libtommath/bn_mp_radix_size.c
@@ -0,0 +1,83 @@
+#include <tommath.h>
+#ifdef BN_MP_RADIX_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* returns size of ASCII reprensentation */
+int mp_radix_size (mp_int * a, int radix, int *size)
+{
+ int res, digs;
+ mp_int t;
+ mp_digit d;
+
+ *size = 0;
+
+ /* special case for binary */
+ if (radix == 2) {
+ *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
+ return MP_OKAY;
+ }
+
+ /* make sure the radix is in range */
+ if (radix < 2 || radix > 64) {
+ return MP_VAL;
+ }
+
+ if (mp_iszero(a) == MP_YES) {
+ *size = 2;
+ return MP_OKAY;
+ }
+
+ /* digs is the digit count */
+ digs = 0;
+
+ /* if it's negative add one for the sign */
+ if (a->sign == MP_NEG) {
+ ++digs;
+ }
+
+ /* init a copy of the input */
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+
+ /* force temp to positive */
+ t.sign = MP_ZPOS;
+
+ /* fetch out all of the digits */
+ while (mp_iszero (&t) == MP_NO) {
+ if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ ++digs;
+ }
+ mp_clear (&t);
+
+ /*
+ * return digs + 1, the 1 is for the NULL byte that would be required.
+ * mp_toradix_n requires a minimum of 3 bytes, so never report less than
+ * that.
+ */
+
+ if ( digs >= 2 ) {
+ *size = digs + 1;
+ } else {
+ *size = 3;
+ }
+ return MP_OKAY;
+}
+
+#endif
diff --git a/libtommath/bn_mp_radix_smap.c b/libtommath/bn_mp_radix_smap.c
new file mode 100644
index 0000000..7aeb375
--- /dev/null
+++ b/libtommath/bn_mp_radix_smap.c
@@ -0,0 +1,20 @@
+#include <tommath.h>
+#ifdef BN_MP_RADIX_SMAP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* chars used in radix conversions */
+const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
+#endif
diff --git a/libtommath/bn_mp_rand.c b/libtommath/bn_mp_rand.c
new file mode 100644
index 0000000..17c1fbe
--- /dev/null
+++ b/libtommath/bn_mp_rand.c
@@ -0,0 +1,51 @@
+#include <tommath.h>
+#ifdef BN_MP_RAND_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* makes a pseudo-random int of a given size */
+int
+mp_rand (mp_int * a, int digits)
+{
+ int res;
+ mp_digit d;
+
+ mp_zero (a);
+ if (digits <= 0) {
+ return MP_OKAY;
+ }
+
+ /* first place a random non-zero digit */
+ do {
+ d = ((mp_digit) abs (rand ())) & MP_MASK;
+ } while (d == 0);
+
+ if ((res = mp_add_d (a, d, a)) != MP_OKAY) {
+ return res;
+ }
+
+ while (--digits > 0) {
+ if ((res = mp_lshd (a, 1)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_read_radix.c b/libtommath/bn_mp_read_radix.c
new file mode 100644
index 0000000..4b92589
--- /dev/null
+++ b/libtommath/bn_mp_read_radix.c
@@ -0,0 +1,88 @@
+#include <tommath.h>
+#ifdef BN_MP_READ_RADIX_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* read a string [ASCII] in a given radix */
+int mp_read_radix (mp_int * a, const char *str, int radix)
+{
+ int y, res, neg;
+ char ch;
+
+ /* zero the digit bignum */
+ mp_zero(a);
+
+ /* make sure the radix is ok */
+ if (radix < 2 || radix > 64) {
+ return MP_VAL;
+ }
+
+ /* if the leading digit is a
+ * minus set the sign to negative.
+ */
+ if (*str == '-') {
+ ++str;
+ neg = MP_NEG;
+ } else {
+ neg = MP_ZPOS;
+ }
+
+ /* set the integer to the default of zero */
+ mp_zero (a);
+
+ /* process each digit of the string */
+ while (*str) {
+ /* if the radix < 36 the conversion is case insensitive
+ * this allows numbers like 1AB and 1ab to represent the same value
+ * [e.g. in hex]
+ */
+ ch = (char) ((radix < 36) ? toupper ((unsigned char) *str) : *str);
+ for (y = 0; y < 64; y++) {
+ if (ch == mp_s_rmap[y]) {
+ break;
+ }
+ }
+
+ /* if the char was found in the map
+ * and is less than the given radix add it
+ * to the number, otherwise exit the loop.
+ */
+ if (y < radix) {
+ if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) {
+ return res;
+ }
+ if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) {
+ return res;
+ }
+ } else {
+ break;
+ }
+ ++str;
+ }
+
+ /* if an illegal character was found, fail. */
+
+ if ( *str != '\0' ) {
+ mp_zero( a );
+ return MP_VAL;
+ }
+
+ /* set the sign only if a != 0 */
+ if (mp_iszero(a) != 1) {
+ a->sign = neg;
+ }
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_read_signed_bin.c b/libtommath/bn_mp_read_signed_bin.c
new file mode 100644
index 0000000..3ee8556
--- /dev/null
+++ b/libtommath/bn_mp_read_signed_bin.c
@@ -0,0 +1,37 @@
+#include <tommath.h>
+#ifdef BN_MP_READ_SIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* read signed bin, big endian, first byte is 0==positive or 1==negative */
+int mp_read_signed_bin (mp_int * a, const unsigned char *b, int c)
+{
+ int res;
+
+ /* read magnitude */
+ if ((res = mp_read_unsigned_bin (a, b + 1, c - 1)) != MP_OKAY) {
+ return res;
+ }
+
+ /* first byte is 0 for positive, non-zero for negative */
+ if (b[0] == 0) {
+ a->sign = MP_ZPOS;
+ } else {
+ a->sign = MP_NEG;
+ }
+
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_read_unsigned_bin.c b/libtommath/bn_mp_read_unsigned_bin.c
new file mode 100644
index 0000000..caf5be0
--- /dev/null
+++ b/libtommath/bn_mp_read_unsigned_bin.c
@@ -0,0 +1,51 @@
+#include <tommath.h>
+#ifdef BN_MP_READ_UNSIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* reads a unsigned char array, assumes the msb is stored first [big endian] */
+int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c)
+{
+ int res;
+
+ /* make sure there are at least two digits */
+ if (a->alloc < 2) {
+ if ((res = mp_grow(a, 2)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* zero the int */
+ mp_zero (a);
+
+ /* read the bytes in */
+ while (c-- > 0) {
+ if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) {
+ return res;
+ }
+
+#ifndef MP_8BIT
+ a->dp[0] |= *b++;
+ a->used += 1;
+#else
+ a->dp[0] = (*b & MP_MASK);
+ a->dp[1] |= ((*b++ >> 7U) & 1);
+ a->used += 2;
+#endif
+ }
+ mp_clamp (a);
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_reduce.c b/libtommath/bn_mp_reduce.c
new file mode 100644
index 0000000..4375e4e
--- /dev/null
+++ b/libtommath/bn_mp_reduce.c
@@ -0,0 +1,96 @@
+#include <tommath.h>
+#ifdef BN_MP_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* reduces x mod m, assumes 0 < x < m**2, mu is
+ * precomputed via mp_reduce_setup.
+ * From HAC pp.604 Algorithm 14.42
+ */
+int mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
+{
+ mp_int q;
+ int res, um = m->used;
+
+ /* q = x */
+ if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
+ return res;
+ }
+
+ /* q1 = x / b**(k-1) */
+ mp_rshd (&q, um - 1);
+
+ /* according to HAC this optimization is ok */
+ if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
+ if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+ } else {
+#ifdef BN_S_MP_MUL_HIGH_DIGS_C
+ if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
+ if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+#else
+ {
+ res = MP_VAL;
+ goto CLEANUP;
+ }
+#endif
+ }
+
+ /* q3 = q2 / b**(k+1) */
+ mp_rshd (&q, um + 1);
+
+ /* x = x mod b**(k+1), quick (no division) */
+ if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+
+ /* q = q * m mod b**(k+1), quick (no division) */
+ if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+
+ /* x = x - q */
+ if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+
+ /* If x < 0, add b**(k+1) to it */
+ if (mp_cmp_d (x, 0) == MP_LT) {
+ mp_set (&q, 1);
+ if ((res = mp_lshd (&q, um + 1)) != MP_OKAY)
+ goto CLEANUP;
+ if ((res = mp_add (x, &q, x)) != MP_OKAY)
+ goto CLEANUP;
+ }
+
+ /* Back off if it's too big */
+ while (mp_cmp (x, m) != MP_LT) {
+ if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+ }
+
+CLEANUP:
+ mp_clear (&q);
+
+ return res;
+}
+#endif
diff --git a/libtommath/bn_mp_reduce_2k.c b/libtommath/bn_mp_reduce_2k.c
new file mode 100644
index 0000000..428f2ff
--- /dev/null
+++ b/libtommath/bn_mp_reduce_2k.c
@@ -0,0 +1,57 @@
+#include <tommath.h>
+#ifdef BN_MP_REDUCE_2K_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* reduces a modulo n where n is of the form 2**p - d */
+int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d)
+{
+ mp_int q;
+ int p, res;
+
+ if ((res = mp_init(&q)) != MP_OKAY) {
+ return res;
+ }
+
+ p = mp_count_bits(n);
+top:
+ /* q = a/2**p, a = a mod 2**p */
+ if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if (d != 1) {
+ /* q = q * d */
+ if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) {
+ goto ERR;
+ }
+ }
+
+ /* a = a + q */
+ if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if (mp_cmp_mag(a, n) != MP_LT) {
+ s_mp_sub(a, n, a);
+ goto top;
+ }
+
+ERR:
+ mp_clear(&q);
+ return res;
+}
+
+#endif
diff --git a/libtommath/bn_mp_reduce_2k_l.c b/libtommath/bn_mp_reduce_2k_l.c
new file mode 100644
index 0000000..8e52efa
--- /dev/null
+++ b/libtommath/bn_mp_reduce_2k_l.c
@@ -0,0 +1,58 @@
+#include <tommath.h>
+#ifdef BN_MP_REDUCE_2K_L_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* reduces a modulo n where n is of the form 2**p - d
+ This differs from reduce_2k since "d" can be larger
+ than a single digit.
+*/
+int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d)
+{
+ mp_int q;
+ int p, res;
+
+ if ((res = mp_init(&q)) != MP_OKAY) {
+ return res;
+ }
+
+ p = mp_count_bits(n);
+top:
+ /* q = a/2**p, a = a mod 2**p */
+ if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* q = q * d */
+ if ((res = mp_mul(&q, d, &q)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* a = a + q */
+ if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if (mp_cmp_mag(a, n) != MP_LT) {
+ s_mp_sub(a, n, a);
+ goto top;
+ }
+
+ERR:
+ mp_clear(&q);
+ return res;
+}
+
+#endif
diff --git a/libtommath/bn_mp_reduce_2k_setup.c b/libtommath/bn_mp_reduce_2k_setup.c
new file mode 100644
index 0000000..ac043f6
--- /dev/null
+++ b/libtommath/bn_mp_reduce_2k_setup.c
@@ -0,0 +1,43 @@
+#include <tommath.h>
+#ifdef BN_MP_REDUCE_2K_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* determines the setup value */
+int mp_reduce_2k_setup(mp_int *a, mp_digit *d)
+{
+ int res, p;
+ mp_int tmp;
+
+ if ((res = mp_init(&tmp)) != MP_OKAY) {
+ return res;
+ }
+
+ p = mp_count_bits(a);
+ if ((res = mp_2expt(&tmp, p)) != MP_OKAY) {
+ mp_clear(&tmp);
+ return res;
+ }
+
+ if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) {
+ mp_clear(&tmp);
+ return res;
+ }
+
+ *d = tmp.dp[0];
+ mp_clear(&tmp);
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_reduce_2k_setup_l.c b/libtommath/bn_mp_reduce_2k_setup_l.c
new file mode 100644
index 0000000..b59a1ed
--- /dev/null
+++ b/libtommath/bn_mp_reduce_2k_setup_l.c
@@ -0,0 +1,40 @@
+#include <tommath.h>
+#ifdef BN_MP_REDUCE_2K_SETUP_L_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* determines the setup value */
+int mp_reduce_2k_setup_l(mp_int *a, mp_int *d)
+{
+ int res;
+ mp_int tmp;
+
+ if ((res = mp_init(&tmp)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ERR:
+ mp_clear(&tmp);
+ return res;
+}
+#endif
diff --git a/libtommath/bn_mp_reduce_is_2k.c b/libtommath/bn_mp_reduce_is_2k.c
new file mode 100644
index 0000000..4655fcf
--- /dev/null
+++ b/libtommath/bn_mp_reduce_is_2k.c
@@ -0,0 +1,48 @@
+#include <tommath.h>
+#ifdef BN_MP_REDUCE_IS_2K_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* determines if mp_reduce_2k can be used */
+int mp_reduce_is_2k(mp_int *a)
+{
+ int ix, iy, iw;
+ mp_digit iz;
+
+ if (a->used == 0) {
+ return MP_NO;
+ } else if (a->used == 1) {
+ return MP_YES;
+ } else if (a->used > 1) {
+ iy = mp_count_bits(a);
+ iz = 1;
+ iw = 1;
+
+ /* Test every bit from the second digit up, must be 1 */
+ for (ix = DIGIT_BIT; ix < iy; ix++) {
+ if ((a->dp[iw] & iz) == 0) {
+ return MP_NO;
+ }
+ iz <<= 1;
+ if (iz > (mp_digit)MP_MASK) {
+ ++iw;
+ iz = 1;
+ }
+ }
+ }
+ return MP_YES;
+}
+
+#endif
diff --git a/libtommath/bn_mp_reduce_is_2k_l.c b/libtommath/bn_mp_reduce_is_2k_l.c
new file mode 100644
index 0000000..7b57865
--- /dev/null
+++ b/libtommath/bn_mp_reduce_is_2k_l.c
@@ -0,0 +1,40 @@
+#include <tommath.h>
+#ifdef BN_MP_REDUCE_IS_2K_L_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* determines if reduce_2k_l can be used */
+int mp_reduce_is_2k_l(mp_int *a)
+{
+ int ix, iy;
+
+ if (a->used == 0) {
+ return MP_NO;
+ } else if (a->used == 1) {
+ return MP_YES;
+ } else if (a->used > 1) {
+ /* if more than half of the digits are -1 we're sold */
+ for (iy = ix = 0; ix < a->used; ix++) {
+ if (a->dp[ix] == MP_MASK) {
+ ++iy;
+ }
+ }
+ return (iy >= (a->used/2)) ? MP_YES : MP_NO;
+
+ }
+ return MP_NO;
+}
+
+#endif
diff --git a/libtommath/bn_mp_reduce_setup.c b/libtommath/bn_mp_reduce_setup.c
new file mode 100644
index 0000000..d8cefd9
--- /dev/null
+++ b/libtommath/bn_mp_reduce_setup.c
@@ -0,0 +1,30 @@
+#include <tommath.h>
+#ifdef BN_MP_REDUCE_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* pre-calculate the value required for Barrett reduction
+ * For a given modulus "b" it calulates the value required in "a"
+ */
+int mp_reduce_setup (mp_int * a, mp_int * b)
+{
+ int res;
+
+ if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {
+ return res;
+ }
+ return mp_div (a, b, a, NULL);
+}
+#endif
diff --git a/libtommath/bn_mp_rshd.c b/libtommath/bn_mp_rshd.c
new file mode 100644
index 0000000..e6095b3
--- /dev/null
+++ b/libtommath/bn_mp_rshd.c
@@ -0,0 +1,68 @@
+#include <tommath.h>
+#ifdef BN_MP_RSHD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* shift right a certain amount of digits */
+void mp_rshd (mp_int * a, int b)
+{
+ int x;
+
+ /* if b <= 0 then ignore it */
+ if (b <= 0) {
+ return;
+ }
+
+ /* if b > used then simply zero it and return */
+ if (a->used <= b) {
+ mp_zero (a);
+ return;
+ }
+
+ {
+ register mp_digit *bottom, *top;
+
+ /* shift the digits down */
+
+ /* bottom */
+ bottom = a->dp;
+
+ /* top [offset into digits] */
+ top = a->dp + b;
+
+ /* this is implemented as a sliding window where
+ * the window is b-digits long and digits from
+ * the top of the window are copied to the bottom
+ *
+ * e.g.
+
+ b-2 | b-1 | b0 | b1 | b2 | ... | bb | ---->
+ /\ | ---->
+ \-------------------/ ---->
+ */
+ for (x = 0; x < (a->used - b); x++) {
+ *bottom++ = *top++;
+ }
+
+ /* zero the top digits */
+ for (; x < a->used; x++) {
+ *bottom++ = 0;
+ }
+ }
+
+ /* remove excess digits */
+ a->used -= b;
+}
+#endif
diff --git a/libtommath/bn_mp_set.c b/libtommath/bn_mp_set.c
new file mode 100644
index 0000000..c32fc42
--- /dev/null
+++ b/libtommath/bn_mp_set.c
@@ -0,0 +1,25 @@
+#include <tommath.h>
+#ifdef BN_MP_SET_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* set to a digit */
+void mp_set (mp_int * a, mp_digit b)
+{
+ mp_zero (a);
+ a->dp[0] = b & MP_MASK;
+ a->used = (a->dp[0] != 0) ? 1 : 0;
+}
+#endif
diff --git a/libtommath/bn_mp_set_int.c b/libtommath/bn_mp_set_int.c
new file mode 100644
index 0000000..b0fc344
--- /dev/null
+++ b/libtommath/bn_mp_set_int.c
@@ -0,0 +1,44 @@
+#include <tommath.h>
+#ifdef BN_MP_SET_INT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* set a 32-bit const */
+int mp_set_int (mp_int * a, unsigned long b)
+{
+ int x, res;
+
+ mp_zero (a);
+
+ /* set four bits at a time */
+ for (x = 0; x < 8; x++) {
+ /* shift the number up four bits */
+ if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) {
+ return res;
+ }
+
+ /* OR in the top four bits of the source */
+ a->dp[0] |= (b >> 28) & 15;
+
+ /* shift the source up to the next four bits */
+ b <<= 4;
+
+ /* ensure that digits are not clamped off */
+ a->used += 1;
+ }
+ mp_clamp (a);
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_shrink.c b/libtommath/bn_mp_shrink.c
new file mode 100644
index 0000000..bfdf93a
--- /dev/null
+++ b/libtommath/bn_mp_shrink.c
@@ -0,0 +1,36 @@
+#include <tommath.h>
+#ifdef BN_MP_SHRINK_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* shrink a bignum */
+int mp_shrink (mp_int * a)
+{
+ mp_digit *tmp;
+ int used = 1;
+
+ if(a->used > 0)
+ used = a->used;
+
+ if (a->alloc != used) {
+ if ((tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * used)) == NULL) {
+ return MP_MEM;
+ }
+ a->dp = tmp;
+ a->alloc = used;
+ }
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_signed_bin_size.c b/libtommath/bn_mp_signed_bin_size.c
new file mode 100644
index 0000000..8f88e76
--- /dev/null
+++ b/libtommath/bn_mp_signed_bin_size.c
@@ -0,0 +1,23 @@
+#include <tommath.h>
+#ifdef BN_MP_SIGNED_BIN_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* get the size for an signed equivalent */
+int mp_signed_bin_size (mp_int * a)
+{
+ return 1 + mp_unsigned_bin_size (a);
+}
+#endif
diff --git a/libtommath/bn_mp_sqr.c b/libtommath/bn_mp_sqr.c
new file mode 100644
index 0000000..3938537
--- /dev/null
+++ b/libtommath/bn_mp_sqr.c
@@ -0,0 +1,54 @@
+#include <tommath.h>
+#ifdef BN_MP_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* computes b = a*a */
+int
+mp_sqr (mp_int * a, mp_int * b)
+{
+ int res;
+
+#ifdef BN_MP_TOOM_SQR_C
+ /* use Toom-Cook? */
+ if (a->used >= TOOM_SQR_CUTOFF) {
+ res = mp_toom_sqr(a, b);
+ /* Karatsuba? */
+ } else
+#endif
+#ifdef BN_MP_KARATSUBA_SQR_C
+if (a->used >= KARATSUBA_SQR_CUTOFF) {
+ res = mp_karatsuba_sqr (a, b);
+ } else
+#endif
+ {
+#ifdef BN_FAST_S_MP_SQR_C
+ /* can we use the fast comba multiplier? */
+ if ((a->used * 2 + 1) < MP_WARRAY &&
+ a->used <
+ (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {
+ res = fast_s_mp_sqr (a, b);
+ } else
+#endif
+#ifdef BN_S_MP_SQR_C
+ res = s_mp_sqr (a, b);
+#else
+ res = MP_VAL;
+#endif
+ }
+ b->sign = MP_ZPOS;
+ return res;
+}
+#endif
diff --git a/libtommath/bn_mp_sqrmod.c b/libtommath/bn_mp_sqrmod.c
new file mode 100644
index 0000000..6f90772
--- /dev/null
+++ b/libtommath/bn_mp_sqrmod.c
@@ -0,0 +1,37 @@
+#include <tommath.h>
+#ifdef BN_MP_SQRMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* c = a * a (mod b) */
+int
+mp_sqrmod (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res;
+ mp_int t;
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_sqr (a, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ res = mp_mod (&t, b, c);
+ mp_clear (&t);
+ return res;
+}
+#endif
diff --git a/libtommath/bn_mp_sqrt.c b/libtommath/bn_mp_sqrt.c
new file mode 100644
index 0000000..016b8ba
--- /dev/null
+++ b/libtommath/bn_mp_sqrt.c
@@ -0,0 +1,142 @@
+#include <tommath.h>
+
+#ifdef BN_MP_SQRT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+#ifndef NO_FLOATING_POINT
+#include <math.h>
+#endif
+
+/* this function is less generic than mp_n_root, simpler and faster */
+int mp_sqrt(mp_int *arg, mp_int *ret)
+{
+ int res;
+ mp_int t1,t2;
+ int i, j, k;
+#ifndef NO_FLOATING_POINT
+ volatile double d;
+ mp_digit dig;
+#endif
+
+ /* must be positive */
+ if (arg->sign == MP_NEG) {
+ return MP_VAL;
+ }
+
+ /* easy out */
+ if (mp_iszero(arg) == MP_YES) {
+ mp_zero(ret);
+ return MP_OKAY;
+ }
+
+ i = (arg->used / 2) - 1;
+ j = 2 * i;
+ if ((res = mp_init_size(&t1, i+2)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_init(&t2)) != MP_OKAY) {
+ goto E2;
+ }
+
+ for (k = 0; k < i; ++k) {
+ t1.dp[k] = (mp_digit) 0;
+ }
+
+#ifndef NO_FLOATING_POINT
+
+ /* Estimate the square root using the hardware floating point unit. */
+
+ d = 0.0;
+ for (k = arg->used-1; k >= j; --k) {
+ d = ldexp(d, DIGIT_BIT) + (double) (arg->dp[k]);
+ }
+
+ /*
+ * At this point, d is the nearest floating point number to the most
+ * significant 1 or 2 mp_digits of arg. Extract its square root.
+ */
+
+ d = sqrt(d);
+
+ /* dig is the most significant mp_digit of the square root */
+
+ dig = (mp_digit) ldexp(d, -DIGIT_BIT);
+
+ /*
+ * If the most significant digit is nonzero, find the next digit down
+ * by subtracting DIGIT_BIT times thie most significant digit.
+ * Subtract one from the result so that our initial estimate is always
+ * low.
+ */
+
+ if (dig) {
+ t1.used = i+2;
+ d -= ldexp((double) dig, DIGIT_BIT);
+ if (d >= 1.0) {
+ t1.dp[i+1] = dig;
+ t1.dp[i] = ((mp_digit) d) - 1;
+ } else {
+ t1.dp[i+1] = dig-1;
+ t1.dp[i] = MP_DIGIT_MAX;
+ }
+ } else {
+ t1.used = i+1;
+ t1.dp[i] = ((mp_digit) d) - 1;
+ }
+
+#else
+
+ /* Estimate the square root as having 1 in the most significant place. */
+
+ t1.used = i + 2;
+ t1.dp[i+1] = (mp_digit) 1;
+ t1.dp[i] = (mp_digit) 0;
+
+#endif
+
+ /* t1 > 0 */
+ if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
+ goto E1;
+ }
+ if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
+ goto E1;
+ }
+ if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
+ goto E1;
+ }
+ /* And now t1 > sqrt(arg) */
+ do {
+ if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
+ goto E1;
+ }
+ if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
+ goto E1;
+ }
+ if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
+ goto E1;
+ }
+ /* t1 >= sqrt(arg) >= t2 at this point */
+ } while (mp_cmp_mag(&t1,&t2) == MP_GT);
+
+ mp_exch(&t1,ret);
+
+E1: mp_clear(&t2);
+E2: mp_clear(&t1);
+ return res;
+}
+
+#endif
diff --git a/libtommath/bn_mp_sub.c b/libtommath/bn_mp_sub.c
new file mode 100644
index 0000000..13cb43e
--- /dev/null
+++ b/libtommath/bn_mp_sub.c
@@ -0,0 +1,55 @@
+#include <tommath.h>
+#ifdef BN_MP_SUB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* high level subtraction (handles signs) */
+int
+mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+ int sa, sb, res;
+
+ sa = a->sign;
+ sb = b->sign;
+
+ if (sa != sb) {
+ /* subtract a negative from a positive, OR */
+ /* subtract a positive from a negative. */
+ /* In either case, ADD their magnitudes, */
+ /* and use the sign of the first number. */
+ c->sign = sa;
+ res = s_mp_add (a, b, c);
+ } else {
+ /* subtract a positive from a positive, OR */
+ /* subtract a negative from a negative. */
+ /* First, take the difference between their */
+ /* magnitudes, then... */
+ if (mp_cmp_mag (a, b) != MP_LT) {
+ /* Copy the sign from the first */
+ c->sign = sa;
+ /* The first has a larger or equal magnitude */
+ res = s_mp_sub (a, b, c);
+ } else {
+ /* The result has the *opposite* sign from */
+ /* the first number. */
+ c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
+ /* The second has a larger magnitude */
+ res = s_mp_sub (b, a, c);
+ }
+ }
+ return res;
+}
+
+#endif
diff --git a/libtommath/bn_mp_sub_d.c b/libtommath/bn_mp_sub_d.c
new file mode 100644
index 0000000..b1e4e3f
--- /dev/null
+++ b/libtommath/bn_mp_sub_d.c
@@ -0,0 +1,89 @@
+#include <tommath.h>
+#ifdef BN_MP_SUB_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* single digit subtraction */
+int
+mp_sub_d (mp_int * a, mp_digit b, mp_int * c)
+{
+ mp_digit *tmpa, *tmpc, mu;
+ int res, ix, oldused;
+
+ /* grow c as required */
+ if (c->alloc < a->used + 1) {
+ if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* if a is negative just do an unsigned
+ * addition [with fudged signs]
+ */
+ if (a->sign == MP_NEG) {
+ a->sign = MP_ZPOS;
+ res = mp_add_d(a, b, c);
+ a->sign = c->sign = MP_NEG;
+
+ /* clamp */
+ mp_clamp(c);
+
+ return res;
+ }
+
+ /* setup regs */
+ oldused = c->used;
+ tmpa = a->dp;
+ tmpc = c->dp;
+
+ /* if a <= b simply fix the single digit */
+ if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) {
+ if (a->used == 1) {
+ *tmpc++ = b - *tmpa;
+ } else {
+ *tmpc++ = b;
+ }
+ ix = 1;
+
+ /* negative/1digit */
+ c->sign = MP_NEG;
+ c->used = 1;
+ } else {
+ /* positive/size */
+ c->sign = MP_ZPOS;
+ c->used = a->used;
+
+ /* subtract first digit */
+ *tmpc = *tmpa++ - b;
+ mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
+ *tmpc++ &= MP_MASK;
+
+ /* handle rest of the digits */
+ for (ix = 1; ix < a->used; ix++) {
+ *tmpc = *tmpa++ - mu;
+ mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
+ *tmpc++ &= MP_MASK;
+ }
+ }
+
+ /* zero excess digits */
+ while (ix++ < oldused) {
+ *tmpc++ = 0;
+ }
+ mp_clamp(c);
+ return MP_OKAY;
+}
+
+#endif
diff --git a/libtommath/bn_mp_submod.c b/libtommath/bn_mp_submod.c
new file mode 100644
index 0000000..7461678
--- /dev/null
+++ b/libtommath/bn_mp_submod.c
@@ -0,0 +1,38 @@
+#include <tommath.h>
+#ifdef BN_MP_SUBMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* d = a - b (mod c) */
+int
+mp_submod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+ int res;
+ mp_int t;
+
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_sub (a, b, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ res = mp_mod (&t, c, d);
+ mp_clear (&t);
+ return res;
+}
+#endif
diff --git a/libtommath/bn_mp_to_signed_bin.c b/libtommath/bn_mp_to_signed_bin.c
new file mode 100644
index 0000000..7871921
--- /dev/null
+++ b/libtommath/bn_mp_to_signed_bin.c
@@ -0,0 +1,29 @@
+#include <tommath.h>
+#ifdef BN_MP_TO_SIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* store in signed [big endian] format */
+int mp_to_signed_bin (mp_int * a, unsigned char *b)
+{
+ int res;
+
+ if ((res = mp_to_unsigned_bin (a, b + 1)) != MP_OKAY) {
+ return res;
+ }
+ b[0] = (unsigned char) ((a->sign == MP_ZPOS) ? 0 : 1);
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_to_signed_bin_n.c b/libtommath/bn_mp_to_signed_bin_n.c
new file mode 100644
index 0000000..8da9961
--- /dev/null
+++ b/libtommath/bn_mp_to_signed_bin_n.c
@@ -0,0 +1,27 @@
+#include <tommath.h>
+#ifdef BN_MP_TO_SIGNED_BIN_N_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* store in signed [big endian] format */
+int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen)
+{
+ if (*outlen < (unsigned long)mp_signed_bin_size(a)) {
+ return MP_VAL;
+ }
+ *outlen = mp_signed_bin_size(a);
+ return mp_to_signed_bin(a, b);
+}
+#endif
diff --git a/libtommath/bn_mp_to_unsigned_bin.c b/libtommath/bn_mp_to_unsigned_bin.c
new file mode 100644
index 0000000..9496398
--- /dev/null
+++ b/libtommath/bn_mp_to_unsigned_bin.c
@@ -0,0 +1,44 @@
+#include <tommath.h>
+#ifdef BN_MP_TO_UNSIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* store in unsigned [big endian] format */
+int mp_to_unsigned_bin (mp_int * a, unsigned char *b)
+{
+ int x, res;
+ mp_int t;
+
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+
+ x = 0;
+ while (mp_iszero (&t) == 0) {
+#ifndef MP_8BIT
+ b[x++] = (unsigned char) (t.dp[0] & 255);
+#else
+ b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7));
+#endif
+ if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ }
+ bn_reverse (b, x);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_to_unsigned_bin_n.c b/libtommath/bn_mp_to_unsigned_bin_n.c
new file mode 100644
index 0000000..4f2a31d
--- /dev/null
+++ b/libtommath/bn_mp_to_unsigned_bin_n.c
@@ -0,0 +1,27 @@
+#include <tommath.h>
+#ifdef BN_MP_TO_UNSIGNED_BIN_N_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* store in unsigned [big endian] format */
+int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen)
+{
+ if (*outlen < (unsigned long)mp_unsigned_bin_size(a)) {
+ return MP_VAL;
+ }
+ *outlen = mp_unsigned_bin_size(a);
+ return mp_to_unsigned_bin(a, b);
+}
+#endif
diff --git a/libtommath/bn_mp_toom_mul.c b/libtommath/bn_mp_toom_mul.c
new file mode 100644
index 0000000..9daefbd
--- /dev/null
+++ b/libtommath/bn_mp_toom_mul.c
@@ -0,0 +1,280 @@
+#include <tommath.h>
+#ifdef BN_MP_TOOM_MUL_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* multiplication using the Toom-Cook 3-way algorithm
+ *
+ * Much more complicated than Karatsuba but has a lower
+ * asymptotic running time of O(N**1.464). This algorithm is
+ * only particularly useful on VERY large inputs
+ * (we're talking 1000s of digits here...).
+*/
+int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
+{
+ mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2;
+ int res, B;
+
+ /* init temps */
+ if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4,
+ &a0, &a1, &a2, &b0, &b1,
+ &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) {
+ return res;
+ }
+
+ /* B */
+ B = MIN(a->used, b->used) / 3;
+
+ /* a = a2 * B**2 + a1 * B + a0 */
+ if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_copy(a, &a1)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&a1, B);
+ mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
+
+ if ((res = mp_copy(a, &a2)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&a2, B*2);
+
+ /* b = b2 * B**2 + b1 * B + b0 */
+ if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_copy(b, &b1)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&b1, B);
+ mp_mod_2d(&b1, DIGIT_BIT * B, &b1);
+
+ if ((res = mp_copy(b, &b2)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&b2, B*2);
+
+ /* w0 = a0*b0 */
+ if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w4 = a2 * b2 */
+ if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */
+ if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */
+ if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+
+
+ /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */
+ if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* now solve the matrix
+
+ 0 0 0 0 1
+ 1 2 4 8 16
+ 1 1 1 1 1
+ 16 8 4 2 1
+ 1 0 0 0 0
+
+ using 12 subtractions, 4 shifts,
+ 2 small divisions and 1 small multiplication
+ */
+
+ /* r1 - r4 */
+ if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r0 */
+ if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1/2 */
+ if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3/2 */
+ if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r2 - r0 - r4 */
+ if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - r2 */
+ if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r2 */
+ if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - 8r0 */
+ if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - 8r4 */
+ if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* 3r2 - r1 - r3 */
+ if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - r2 */
+ if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r2 */
+ if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1/3 */
+ if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3/3 */
+ if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* at this point shift W[n] by B*n */
+ if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ERR:
+ mp_clear_multi(&w0, &w1, &w2, &w3, &w4,
+ &a0, &a1, &a2, &b0, &b1,
+ &b2, &tmp1, &tmp2, NULL);
+ return res;
+}
+
+#endif
diff --git a/libtommath/bn_mp_toom_sqr.c b/libtommath/bn_mp_toom_sqr.c
new file mode 100644
index 0000000..9e3f79c
--- /dev/null
+++ b/libtommath/bn_mp_toom_sqr.c
@@ -0,0 +1,222 @@
+#include <tommath.h>
+#ifdef BN_MP_TOOM_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* squaring using Toom-Cook 3-way algorithm */
+int
+mp_toom_sqr(mp_int *a, mp_int *b)
+{
+ mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2;
+ int res, B;
+
+ /* init temps */
+ if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) {
+ return res;
+ }
+
+ /* B */
+ B = a->used / 3;
+
+ /* a = a2 * B**2 + a1 * B + a0 */
+ if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_copy(a, &a1)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&a1, B);
+ mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
+
+ if ((res = mp_copy(a, &a2)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&a2, B*2);
+
+ /* w0 = a0*a0 */
+ if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w4 = a2 * a2 */
+ if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w1 = (a2 + 2(a1 + 2a0))**2 */
+ if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w3 = (a0 + 2(a1 + 2a2))**2 */
+ if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+
+
+ /* w2 = (a2 + a1 + a0)**2 */
+ if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* now solve the matrix
+
+ 0 0 0 0 1
+ 1 2 4 8 16
+ 1 1 1 1 1
+ 16 8 4 2 1
+ 1 0 0 0 0
+
+ using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication.
+ */
+
+ /* r1 - r4 */
+ if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r0 */
+ if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1/2 */
+ if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3/2 */
+ if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r2 - r0 - r4 */
+ if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - r2 */
+ if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r2 */
+ if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - 8r0 */
+ if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - 8r4 */
+ if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* 3r2 - r1 - r3 */
+ if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - r2 */
+ if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r2 */
+ if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1/3 */
+ if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3/3 */
+ if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* at this point shift W[n] by B*n */
+ if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ERR:
+ mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL);
+ return res;
+}
+
+#endif
diff --git a/libtommath/bn_mp_toradix.c b/libtommath/bn_mp_toradix.c
new file mode 100644
index 0000000..132743e
--- /dev/null
+++ b/libtommath/bn_mp_toradix.c
@@ -0,0 +1,71 @@
+#include <tommath.h>
+#ifdef BN_MP_TORADIX_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* stores a bignum as a ASCII string in a given radix (2..64) */
+int mp_toradix (mp_int * a, char *str, int radix)
+{
+ int res, digs;
+ mp_int t;
+ mp_digit d;
+ char *_s = str;
+
+ /* check range of the radix */
+ if (radix < 2 || radix > 64) {
+ return MP_VAL;
+ }
+
+ /* quick out if its zero */
+ if (mp_iszero(a) == 1) {
+ *str++ = '0';
+ *str = '\0';
+ return MP_OKAY;
+ }
+
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+
+ /* if it is negative output a - */
+ if (t.sign == MP_NEG) {
+ ++_s;
+ *str++ = '-';
+ t.sign = MP_ZPOS;
+ }
+
+ digs = 0;
+ while (mp_iszero (&t) == 0) {
+ if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ *str++ = mp_s_rmap[d];
+ ++digs;
+ }
+
+ /* reverse the digits of the string. In this case _s points
+ * to the first digit [exluding the sign] of the number]
+ */
+ bn_reverse ((unsigned char *)_s, digs);
+
+ /* append a NULL so the string is properly terminated */
+ *str = '\0';
+
+ mp_clear (&t);
+ return MP_OKAY;
+}
+
+#endif
diff --git a/libtommath/bn_mp_toradix_n.c b/libtommath/bn_mp_toradix_n.c
new file mode 100644
index 0000000..dedce71
--- /dev/null
+++ b/libtommath/bn_mp_toradix_n.c
@@ -0,0 +1,84 @@
+#include <tommath.h>
+#ifdef BN_MP_TORADIX_N_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* stores a bignum as a ASCII string in a given radix (2..64)
+ *
+ * Stores upto maxlen-1 chars and always a NULL byte
+ */
+int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen)
+{
+ int res, digs;
+ mp_int t;
+ mp_digit d;
+ char *_s = str;
+
+ /* check range of the maxlen, radix */
+ if (maxlen < 2 || radix < 2 || radix > 64) {
+ return MP_VAL;
+ }
+
+ /* quick out if its zero */
+ if (mp_iszero(a) == MP_YES) {
+ *str++ = '0';
+ *str = '\0';
+ return MP_OKAY;
+ }
+
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+
+ /* if it is negative output a - */
+ if (t.sign == MP_NEG) {
+ /* we have to reverse our digits later... but not the - sign!! */
+ ++_s;
+
+ /* store the flag and mark the number as positive */
+ *str++ = '-';
+ t.sign = MP_ZPOS;
+
+ /* subtract a char */
+ --maxlen;
+ }
+
+ digs = 0;
+ while (mp_iszero (&t) == 0) {
+ if (--maxlen < 1) {
+ /* no more room */
+ break;
+ }
+ if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ *str++ = mp_s_rmap[d];
+ ++digs;
+ }
+
+ /* reverse the digits of the string. In this case _s points
+ * to the first digit [exluding the sign] of the number
+ */
+ bn_reverse ((unsigned char *)_s, digs);
+
+ /* append a NULL so the string is properly terminated */
+ *str = '\0';
+
+ mp_clear (&t);
+ return MP_OKAY;
+}
+
+#endif
diff --git a/libtommath/bn_mp_unsigned_bin_size.c b/libtommath/bn_mp_unsigned_bin_size.c
new file mode 100644
index 0000000..58c18fb
--- /dev/null
+++ b/libtommath/bn_mp_unsigned_bin_size.c
@@ -0,0 +1,24 @@
+#include <tommath.h>
+#ifdef BN_MP_UNSIGNED_BIN_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* get the size for an unsigned equivalent */
+int mp_unsigned_bin_size (mp_int * a)
+{
+ int size = mp_count_bits (a);
+ return (size / 8 + ((size & 7) != 0 ? 1 : 0));
+}
+#endif
diff --git a/libtommath/bn_mp_xor.c b/libtommath/bn_mp_xor.c
new file mode 100644
index 0000000..432f42e
--- /dev/null
+++ b/libtommath/bn_mp_xor.c
@@ -0,0 +1,47 @@
+#include <tommath.h>
+#ifdef BN_MP_XOR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* XOR two ints together */
+int
+mp_xor (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res, ix, px;
+ mp_int t, *x;
+
+ if (a->used > b->used) {
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+ px = b->used;
+ x = b;
+ } else {
+ if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+ return res;
+ }
+ px = a->used;
+ x = a;
+ }
+
+ for (ix = 0; ix < px; ix++) {
+ t.dp[ix] ^= x->dp[ix];
+ }
+ mp_clamp (&t);
+ mp_exch (c, &t);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_mp_zero.c b/libtommath/bn_mp_zero.c
new file mode 100644
index 0000000..d697a60
--- /dev/null
+++ b/libtommath/bn_mp_zero.c
@@ -0,0 +1,32 @@
+#include <tommath.h>
+#ifdef BN_MP_ZERO_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* set to zero */
+void mp_zero (mp_int * a)
+{
+ int n;
+ mp_digit *tmp;
+
+ a->sign = MP_ZPOS;
+ a->used = 0;
+
+ tmp = a->dp;
+ for (n = 0; n < a->alloc; n++) {
+ *tmp++ = 0;
+ }
+}
+#endif
diff --git a/libtommath/bn_prime_tab.c b/libtommath/bn_prime_tab.c
new file mode 100644
index 0000000..c47c8bd
--- /dev/null
+++ b/libtommath/bn_prime_tab.c
@@ -0,0 +1,57 @@
+#include <tommath.h>
+#ifdef BN_PRIME_TAB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+const mp_digit ltm_prime_tab[] = {
+ 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
+ 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
+ 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
+ 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
+#ifndef MP_8BIT
+ 0x0083,
+ 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
+ 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
+ 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
+ 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
+
+ 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
+ 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
+ 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
+ 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
+ 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
+ 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
+ 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
+ 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
+
+ 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
+ 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
+ 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
+ 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
+ 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
+ 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
+ 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
+ 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
+
+ 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
+ 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
+ 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
+ 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
+ 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
+ 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
+ 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
+ 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
+#endif
+};
+#endif
diff --git a/libtommath/bn_reverse.c b/libtommath/bn_reverse.c
new file mode 100644
index 0000000..9d7fd29
--- /dev/null
+++ b/libtommath/bn_reverse.c
@@ -0,0 +1,35 @@
+#include <tommath.h>
+#ifdef BN_REVERSE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* reverse an array, used for radix code */
+void
+bn_reverse (unsigned char *s, int len)
+{
+ int ix, iy;
+ unsigned char t;
+
+ ix = 0;
+ iy = len - 1;
+ while (ix < iy) {
+ t = s[ix];
+ s[ix] = s[iy];
+ s[iy] = t;
+ ++ix;
+ --iy;
+ }
+}
+#endif
diff --git a/libtommath/bn_s_mp_add.c b/libtommath/bn_s_mp_add.c
new file mode 100644
index 0000000..7527bf8
--- /dev/null
+++ b/libtommath/bn_s_mp_add.c
@@ -0,0 +1,105 @@
+#include <tommath.h>
+#ifdef BN_S_MP_ADD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* low level addition, based on HAC pp.594, Algorithm 14.7 */
+int
+s_mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int *x;
+ int olduse, res, min, max;
+
+ /* find sizes, we let |a| <= |b| which means we have to sort
+ * them. "x" will point to the input with the most digits
+ */
+ if (a->used > b->used) {
+ min = b->used;
+ max = a->used;
+ x = a;
+ } else {
+ min = a->used;
+ max = b->used;
+ x = b;
+ }
+
+ /* init result */
+ if (c->alloc < max + 1) {
+ if ((res = mp_grow (c, max + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* get old used digit count and set new one */
+ olduse = c->used;
+ c->used = max + 1;
+
+ {
+ register mp_digit u, *tmpa, *tmpb, *tmpc;
+ register int i;
+
+ /* alias for digit pointers */
+
+ /* first input */
+ tmpa = a->dp;
+
+ /* second input */
+ tmpb = b->dp;
+
+ /* destination */
+ tmpc = c->dp;
+
+ /* zero the carry */
+ u = 0;
+ for (i = 0; i < min; i++) {
+ /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
+ *tmpc = *tmpa++ + *tmpb++ + u;
+
+ /* U = carry bit of T[i] */
+ u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+ /* take away carry bit from T[i] */
+ *tmpc++ &= MP_MASK;
+ }
+
+ /* now copy higher words if any, that is in A+B
+ * if A or B has more digits add those in
+ */
+ if (min != max) {
+ for (; i < max; i++) {
+ /* T[i] = X[i] + U */
+ *tmpc = x->dp[i] + u;
+
+ /* U = carry bit of T[i] */
+ u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+ /* take away carry bit from T[i] */
+ *tmpc++ &= MP_MASK;
+ }
+ }
+
+ /* add carry */
+ *tmpc++ = u;
+
+ /* clear digits above oldused */
+ for (i = c->used; i < olduse; i++) {
+ *tmpc++ = 0;
+ }
+ }
+
+ mp_clamp (c);
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_s_mp_exptmod.c b/libtommath/bn_s_mp_exptmod.c
new file mode 100644
index 0000000..ff6bd54
--- /dev/null
+++ b/libtommath/bn_s_mp_exptmod.c
@@ -0,0 +1,248 @@
+#include <tommath.h>
+#ifdef BN_S_MP_EXPTMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+#ifdef MP_LOW_MEM
+ #define TAB_SIZE 32
+#else
+ #define TAB_SIZE 256
+#endif
+
+int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+ mp_int M[TAB_SIZE], res, mu;
+ mp_digit buf;
+ int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+ int (*redux)(mp_int*,mp_int*,mp_int*);
+
+ /* find window size */
+ x = mp_count_bits (X);
+ if (x <= 7) {
+ winsize = 2;
+ } else if (x <= 36) {
+ winsize = 3;
+ } else if (x <= 140) {
+ winsize = 4;
+ } else if (x <= 450) {
+ winsize = 5;
+ } else if (x <= 1303) {
+ winsize = 6;
+ } else if (x <= 3529) {
+ winsize = 7;
+ } else {
+ winsize = 8;
+ }
+
+#ifdef MP_LOW_MEM
+ if (winsize > 5) {
+ winsize = 5;
+ }
+#endif
+
+ /* init M array */
+ /* init first cell */
+ if ((err = mp_init(&M[1])) != MP_OKAY) {
+ return err;
+ }
+
+ /* now init the second half of the array */
+ for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+ if ((err = mp_init(&M[x])) != MP_OKAY) {
+ for (y = 1<<(winsize-1); y < x; y++) {
+ mp_clear (&M[y]);
+ }
+ mp_clear(&M[1]);
+ return err;
+ }
+ }
+
+ /* create mu, used for Barrett reduction */
+ if ((err = mp_init (&mu)) != MP_OKAY) {
+ goto LBL_M;
+ }
+
+ if (redmode == 0) {
+ if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ redux = mp_reduce;
+ } else {
+ if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ redux = mp_reduce_2k_l;
+ }
+
+ /* create M table
+ *
+ * The M table contains powers of the base,
+ * e.g. M[x] = G**x mod P
+ *
+ * The first half of the table is not
+ * computed though accept for M[0] and M[1]
+ */
+ if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {
+ goto LBL_MU;
+ }
+
+ /* compute the value at M[1<<(winsize-1)] by squaring
+ * M[1] (winsize-1) times
+ */
+ if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+ goto LBL_MU;
+ }
+
+ for (x = 0; x < (winsize - 1); x++) {
+ /* square it */
+ if ((err = mp_sqr (&M[1 << (winsize - 1)],
+ &M[1 << (winsize - 1)])) != MP_OKAY) {
+ goto LBL_MU;
+ }
+
+ /* reduce modulo P */
+ if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ }
+
+ /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
+ * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
+ */
+ for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+ if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ if ((err = redux (&M[x], P, &mu)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ }
+
+ /* setup result */
+ if ((err = mp_init (&res)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ mp_set (&res, 1);
+
+ /* set initial mode and bit cnt */
+ mode = 0;
+ bitcnt = 1;
+ buf = 0;
+ digidx = X->used - 1;
+ bitcpy = 0;
+ bitbuf = 0;
+
+ for (;;) {
+ /* grab next digit as required */
+ if (--bitcnt == 0) {
+ /* if digidx == -1 we are out of digits */
+ if (digidx == -1) {
+ break;
+ }
+ /* read next digit and reset the bitcnt */
+ buf = X->dp[digidx--];
+ bitcnt = (int) DIGIT_BIT;
+ }
+
+ /* grab the next msb from the exponent */
+ y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
+ buf <<= (mp_digit)1;
+
+ /* if the bit is zero and mode == 0 then we ignore it
+ * These represent the leading zero bits before the first 1 bit
+ * in the exponent. Technically this opt is not required but it
+ * does lower the # of trivial squaring/reductions used
+ */
+ if (mode == 0 && y == 0) {
+ continue;
+ }
+
+ /* if the bit is zero and mode == 1 then we square */
+ if (mode == 1 && y == 0) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ continue;
+ }
+
+ /* else we add it to the window */
+ bitbuf |= (y << (winsize - ++bitcpy));
+ mode = 2;
+
+ if (bitcpy == winsize) {
+ /* ok window is filled so square as required and multiply */
+ /* square first */
+ for (x = 0; x < winsize; x++) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* then multiply */
+ if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ /* empty window and reset */
+ bitcpy = 0;
+ bitbuf = 0;
+ mode = 1;
+ }
+ }
+
+ /* if bits remain then square/multiply */
+ if (mode == 2 && bitcpy > 0) {
+ /* square then multiply if the bit is set */
+ for (x = 0; x < bitcpy; x++) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ bitbuf <<= 1;
+ if ((bitbuf & (1 << winsize)) != 0) {
+ /* then multiply */
+ if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+ }
+ }
+
+ mp_exch (&res, Y);
+ err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_MU:mp_clear (&mu);
+LBL_M:
+ mp_clear(&M[1]);
+ for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+ mp_clear (&M[x]);
+ }
+ return err;
+}
+#endif
diff --git a/libtommath/bn_s_mp_mul_digs.c b/libtommath/bn_s_mp_mul_digs.c
new file mode 100644
index 0000000..401f32e
--- /dev/null
+++ b/libtommath/bn_s_mp_mul_digs.c
@@ -0,0 +1,86 @@
+#include <tommath.h>
+#ifdef BN_S_MP_MUL_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* multiplies |a| * |b| and only computes upto digs digits of result
+ * HAC pp. 595, Algorithm 14.12 Modified so you can control how
+ * many digits of output are created.
+ */
+int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+ mp_int t;
+ int res, pa, pb, ix, iy;
+ mp_digit u;
+ mp_word r;
+ mp_digit tmpx, *tmpt, *tmpy;
+
+ /* can we use the fast multiplier? */
+ if (((digs) < MP_WARRAY) &&
+ MIN (a->used, b->used) <
+ (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ return fast_s_mp_mul_digs (a, b, c, digs);
+ }
+
+ if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
+ return res;
+ }
+ t.used = digs;
+
+ /* compute the digits of the product directly */
+ pa = a->used;
+ for (ix = 0; ix < pa; ix++) {
+ /* set the carry to zero */
+ u = 0;
+
+ /* limit ourselves to making digs digits of output */
+ pb = MIN (b->used, digs - ix);
+
+ /* setup some aliases */
+ /* copy of the digit from a used within the nested loop */
+ tmpx = a->dp[ix];
+
+ /* an alias for the destination shifted ix places */
+ tmpt = t.dp + ix;
+
+ /* an alias for the digits of b */
+ tmpy = b->dp;
+
+ /* compute the columns of the output and propagate the carry */
+ for (iy = 0; iy < pb; iy++) {
+ /* compute the column as a mp_word */
+ r = ((mp_word)*tmpt) +
+ ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+ ((mp_word) u);
+
+ /* the new column is the lower part of the result */
+ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* get the carry word from the result */
+ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+ }
+ /* set carry if it is placed below digs */
+ if (ix + iy < digs) {
+ *tmpt = u;
+ }
+ }
+
+ mp_clamp (&t);
+ mp_exch (&t, c);
+
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_s_mp_mul_high_digs.c b/libtommath/bn_s_mp_mul_high_digs.c
new file mode 100644
index 0000000..f4dca76
--- /dev/null
+++ b/libtommath/bn_s_mp_mul_high_digs.c
@@ -0,0 +1,77 @@
+#include <tommath.h>
+#ifdef BN_S_MP_MUL_HIGH_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* multiplies |a| * |b| and does not compute the lower digs digits
+ * [meant to get the higher part of the product]
+ */
+int
+s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+ mp_int t;
+ int res, pa, pb, ix, iy;
+ mp_digit u;
+ mp_word r;
+ mp_digit tmpx, *tmpt, *tmpy;
+
+ /* can we use the fast multiplier? */
+#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
+ if (((a->used + b->used + 1) < MP_WARRAY)
+ && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ return fast_s_mp_mul_high_digs (a, b, c, digs);
+ }
+#endif
+
+ if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ t.used = a->used + b->used + 1;
+
+ pa = a->used;
+ pb = b->used;
+ for (ix = 0; ix < pa; ix++) {
+ /* clear the carry */
+ u = 0;
+
+ /* left hand side of A[ix] * B[iy] */
+ tmpx = a->dp[ix];
+
+ /* alias to the address of where the digits will be stored */
+ tmpt = &(t.dp[digs]);
+
+ /* alias for where to read the right hand side from */
+ tmpy = b->dp + (digs - ix);
+
+ for (iy = digs - ix; iy < pb; iy++) {
+ /* calculate the double precision result */
+ r = ((mp_word)*tmpt) +
+ ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+ ((mp_word) u);
+
+ /* get the lower part */
+ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* carry the carry */
+ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+ }
+ *tmpt = u;
+ }
+ mp_clamp (&t);
+ mp_exch (&t, c);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_s_mp_sqr.c b/libtommath/bn_s_mp_sqr.c
new file mode 100644
index 0000000..464663f
--- /dev/null
+++ b/libtommath/bn_s_mp_sqr.c
@@ -0,0 +1,80 @@
+#include <tommath.h>
+#ifdef BN_S_MP_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
+int s_mp_sqr (mp_int * a, mp_int * b)
+{
+ mp_int t;
+ int res, ix, iy, pa;
+ mp_word r;
+ mp_digit u, tmpx, *tmpt;
+
+ pa = a->used;
+ if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
+ return res;
+ }
+
+ /* default used is maximum possible size */
+ t.used = 2*pa + 1;
+
+ for (ix = 0; ix < pa; ix++) {
+ /* first calculate the digit at 2*ix */
+ /* calculate double precision result */
+ r = ((mp_word) t.dp[2*ix]) +
+ ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
+
+ /* store lower part in result */
+ t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* get the carry */
+ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+ /* left hand side of A[ix] * A[iy] */
+ tmpx = a->dp[ix];
+
+ /* alias for where to store the results */
+ tmpt = t.dp + (2*ix + 1);
+
+ for (iy = ix + 1; iy < pa; iy++) {
+ /* first calculate the product */
+ r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
+
+ /* now calculate the double precision result, note we use
+ * addition instead of *2 since it's easier to optimize
+ */
+ r = ((mp_word) *tmpt) + r + r + ((mp_word) u);
+
+ /* store lower part */
+ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* get carry */
+ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+ }
+ /* propagate upwards */
+ while (u != ((mp_digit) 0)) {
+ r = ((mp_word) *tmpt) + ((mp_word) u);
+ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+ }
+ }
+
+ mp_clamp (&t);
+ mp_exch (&t, b);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
diff --git a/libtommath/bn_s_mp_sub.c b/libtommath/bn_s_mp_sub.c
new file mode 100644
index 0000000..328c9e5
--- /dev/null
+++ b/libtommath/bn_s_mp_sub.c
@@ -0,0 +1,85 @@
+#include <tommath.h>
+#ifdef BN_S_MP_SUB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
+int
+s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+ int olduse, res, min, max;
+
+ /* find sizes */
+ min = b->used;
+ max = a->used;
+
+ /* init result */
+ if (c->alloc < max) {
+ if ((res = mp_grow (c, max)) != MP_OKAY) {
+ return res;
+ }
+ }
+ olduse = c->used;
+ c->used = max;
+
+ {
+ register mp_digit u, *tmpa, *tmpb, *tmpc;
+ register int i;
+
+ /* alias for digit pointers */
+ tmpa = a->dp;
+ tmpb = b->dp;
+ tmpc = c->dp;
+
+ /* set carry to zero */
+ u = 0;
+ for (i = 0; i < min; i++) {
+ /* T[i] = A[i] - B[i] - U */
+ *tmpc = *tmpa++ - *tmpb++ - u;
+
+ /* U = carry bit of T[i]
+ * Note this saves performing an AND operation since
+ * if a carry does occur it will propagate all the way to the
+ * MSB. As a result a single shift is enough to get the carry
+ */
+ u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+ /* Clear carry from T[i] */
+ *tmpc++ &= MP_MASK;
+ }
+
+ /* now copy higher words if any, e.g. if A has more digits than B */
+ for (; i < max; i++) {
+ /* T[i] = A[i] - U */
+ *tmpc = *tmpa++ - u;
+
+ /* U = carry bit of T[i] */
+ u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+ /* Clear carry from T[i] */
+ *tmpc++ &= MP_MASK;
+ }
+
+ /* clear digits above used (since we may not have grown result above) */
+ for (i = c->used; i < olduse; i++) {
+ *tmpc++ = 0;
+ }
+ }
+
+ mp_clamp (c);
+ return MP_OKAY;
+}
+
+#endif
diff --git a/libtommath/bncore.c b/libtommath/bncore.c
new file mode 100644
index 0000000..eb95a2e
--- /dev/null
+++ b/libtommath/bncore.c
@@ -0,0 +1,32 @@
+#include <tommath.h>
+#ifdef BNCORE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* Known optimal configurations
+
+ CPU /Compiler /MUL CUTOFF/SQR CUTOFF
+-------------------------------------------------------------
+ Intel P4 Northwood /GCC v3.4.1 / 88/ 128/LTM 0.32 ;-)
+ AMD Athlon64 /GCC v3.4.4 / 80/ 120/LTM 0.35
+
+*/
+
+int KARATSUBA_MUL_CUTOFF = 80, /* Min. number of digits before Karatsuba multiplication is used. */
+ KARATSUBA_SQR_CUTOFF = 120, /* Min. number of digits before Karatsuba squaring is used. */
+
+ TOOM_MUL_CUTOFF = 350, /* no optimal values of these are known yet so set em high */
+ TOOM_SQR_CUTOFF = 400;
+#endif
diff --git a/libtommath/booker.pl b/libtommath/booker.pl
new file mode 100644
index 0000000..df8b30d
--- /dev/null
+++ b/libtommath/booker.pl
@@ -0,0 +1,265 @@
+#!/bin/perl
+#
+#Used to prepare the book "tommath.src" for LaTeX by pre-processing it into a .tex file
+#
+#Essentially you write the "tommath.src" as normal LaTex except where you want code snippets you put
+#
+#EXAM,file
+#
+#This preprocessor will then open "file" and insert it as a verbatim copy.
+#
+#Tom St Denis
+
+#get graphics type
+if (shift =~ /PDF/) {
+ $graph = "";
+} else {
+ $graph = ".ps";
+}
+
+open(IN,"<tommath.src") or die "Can't open source file";
+open(OUT,">tommath.tex") or die "Can't open destination file";
+
+print "Scanning for sections\n";
+$chapter = $section = $subsection = 0;
+$x = 0;
+while (<IN>) {
+ print ".";
+ if (!(++$x % 80)) { print "\n"; }
+ #update the headings
+ if (~($_ =~ /\*/)) {
+ if ($_ =~ /\\chapter{.+}/) {
+ ++$chapter;
+ $section = $subsection = 0;
+ } elsif ($_ =~ /\\section{.+}/) {
+ ++$section;
+ $subsection = 0;
+ } elsif ($_ =~ /\\subsection{.+}/) {
+ ++$subsection;
+ }
+ }
+
+ if ($_ =~ m/MARK/) {
+ @m = split(",",$_);
+ chomp(@m[1]);
+ $index1{@m[1]} = $chapter;
+ $index2{@m[1]} = $section;
+ $index3{@m[1]} = $subsection;
+ }
+}
+close(IN);
+
+open(IN,"<tommath.src") or die "Can't open source file";
+$readline = $wroteline = 0;
+$srcline = 0;
+
+while (<IN>) {
+ ++$readline;
+ ++$srcline;
+
+ if ($_ =~ m/MARK/) {
+ } elsif ($_ =~ m/EXAM/ || $_ =~ m/LIST/) {
+ if ($_ =~ m/EXAM/) {
+ $skipheader = 1;
+ } else {
+ $skipheader = 0;
+ }
+
+ # EXAM,file
+ chomp($_);
+ @m = split(",",$_);
+ open(SRC,"<$m[1]") or die "Error:$srcline:Can't open source file $m[1]";
+
+ print "$srcline:Inserting $m[1]:";
+
+ $line = 0;
+ $tmp = $m[1];
+ $tmp =~ s/_/"\\_"/ge;
+ print OUT "\\vspace{+3mm}\\begin{small}\n\\hspace{-5.1mm}{\\bf File}: $tmp\n\\vspace{-3mm}\n\\begin{alltt}\n";
+ $wroteline += 5;
+
+ if ($skipheader == 1) {
+ # scan till next end of comment, e.g. skip license
+ while (<SRC>) {
+ $text[$line++] = $_;
+ last if ($_ =~ /math\.libtomcrypt\.org/);
+ }
+ <SRC>;
+ }
+
+ $inline = 0;
+ while (<SRC>) {
+ next if ($_ =~ /\$Source/);
+ next if ($_ =~ /\$Revision/);
+ next if ($_ =~ /\$Date/);
+ $text[$line++] = $_;
+ ++$inline;
+ chomp($_);
+ $_ =~ s/\t/" "/ge;
+ $_ =~ s/{/"^{"/ge;
+ $_ =~ s/}/"^}"/ge;
+ $_ =~ s/\\/'\symbol{92}'/ge;
+ $_ =~ s/\^/"\\"/ge;
+
+ printf OUT ("%03d ", $line);
+ for ($x = 0; $x < length($_); $x++) {
+ print OUT chr(vec($_, $x, 8));
+ if ($x == 75) {
+ print OUT "\n ";
+ ++$wroteline;
+ }
+ }
+ print OUT "\n";
+ ++$wroteline;
+ }
+ $totlines = $line;
+ print OUT "\\end{alltt}\n\\end{small}\n";
+ close(SRC);
+ print "$inline lines\n";
+ $wroteline += 2;
+ } elsif ($_ =~ m/@\d+,.+@/) {
+ # line contains [number,text]
+ # e.g. @14,for (ix = 0)@
+ $txt = $_;
+ while ($txt =~ m/@\d+,.+@/) {
+ @m = split("@",$txt); # splits into text, one, two
+ @parms = split(",",$m[1]); # splits one,two into two elements
+
+ # now search from $parms[0] down for $parms[1]
+ $found1 = 0;
+ $found2 = 0;
+ for ($i = $parms[0]; $i < $totlines && $found1 == 0; $i++) {
+ if ($text[$i] =~ m/\Q$parms[1]\E/) {
+ $foundline1 = $i + 1;
+ $found1 = 1;
+ }
+ }
+
+ # now search backwards
+ for ($i = $parms[0] - 1; $i >= 0 && $found2 == 0; $i--) {
+ if ($text[$i] =~ m/\Q$parms[1]\E/) {
+ $foundline2 = $i + 1;
+ $found2 = 1;
+ }
+ }
+
+ # now use the closest match or the first if tied
+ if ($found1 == 1 && $found2 == 0) {
+ $found = 1;
+ $foundline = $foundline1;
+ } elsif ($found1 == 0 && $found2 == 1) {
+ $found = 1;
+ $foundline = $foundline2;
+ } elsif ($found1 == 1 && $found2 == 1) {
+ $found = 1;
+ if (($foundline1 - $parms[0]) <= ($parms[0] - $foundline2)) {
+ $foundline = $foundline1;
+ } else {
+ $foundline = $foundline2;
+ }
+ } else {
+ $found = 0;
+ }
+
+ # if found replace
+ if ($found == 1) {
+ $delta = $parms[0] - $foundline;
+ print "Found replacement tag for \"$parms[1]\" on line $srcline which refers to line $foundline (delta $delta)\n";
+ $_ =~ s/@\Q$m[1]\E@/$foundline/;
+ } else {
+ print "ERROR: The tag \"$parms[1]\" on line $srcline was not found in the most recently parsed source!\n";
+ }
+
+ # remake the rest of the line
+ $cnt = @m;
+ $txt = "";
+ for ($i = 2; $i < $cnt; $i++) {
+ $txt = $txt . $m[$i] . "@";
+ }
+ }
+ print OUT $_;
+ ++$wroteline;
+ } elsif ($_ =~ /~.+~/) {
+ # line contains a ~text~ pair used to refer to indexing :-)
+ $txt = $_;
+ while ($txt =~ /~.+~/) {
+ @m = split("~", $txt);
+
+ # word is the second position
+ $word = @m[1];
+ $a = $index1{$word};
+ $b = $index2{$word};
+ $c = $index3{$word};
+
+ # if chapter (a) is zero it wasn't found
+ if ($a == 0) {
+ print "ERROR: the tag \"$word\" on line $srcline was not found previously marked.\n";
+ } else {
+ # format the tag as x, x.y or x.y.z depending on the values
+ $str = $a;
+ $str = $str . ".$b" if ($b != 0);
+ $str = $str . ".$c" if ($c != 0);
+
+ if ($b == 0 && $c == 0) {
+ # its a chapter
+ if ($a <= 10) {
+ if ($a == 1) {
+ $str = "chapter one";
+ } elsif ($a == 2) {
+ $str = "chapter two";
+ } elsif ($a == 3) {
+ $str = "chapter three";
+ } elsif ($a == 4) {
+ $str = "chapter four";
+ } elsif ($a == 5) {
+ $str = "chapter five";
+ } elsif ($a == 6) {
+ $str = "chapter six";
+ } elsif ($a == 7) {
+ $str = "chapter seven";
+ } elsif ($a == 8) {
+ $str = "chapter eight";
+ } elsif ($a == 9) {
+ $str = "chapter nine";
+ } elsif ($a == 10) {
+ $str = "chapter ten";
+ }
+ } else {
+ $str = "chapter " . $str;
+ }
+ } else {
+ $str = "section " . $str if ($b != 0 && $c == 0);
+ $str = "sub-section " . $str if ($b != 0 && $c != 0);
+ }
+
+ #substitute
+ $_ =~ s/~\Q$word\E~/$str/;
+
+ print "Found replacement tag for marker \"$word\" on line $srcline which refers to $str\n";
+ }
+
+ # remake rest of the line
+ $cnt = @m;
+ $txt = "";
+ for ($i = 2; $i < $cnt; $i++) {
+ $txt = $txt . $m[$i] . "~";
+ }
+ }
+ print OUT $_;
+ ++$wroteline;
+ } elsif ($_ =~ m/FIGU/) {
+ # FIGU,file,caption
+ chomp($_);
+ @m = split(",", $_);
+ print OUT "\\begin{center}\n\\begin{figure}[here]\n\\includegraphics{pics/$m[1]$graph}\n";
+ print OUT "\\caption{$m[2]}\n\\label{pic:$m[1]}\n\\end{figure}\n\\end{center}\n";
+ $wroteline += 4;
+ } else {
+ print OUT $_;
+ ++$wroteline;
+ }
+}
+print "Read $readline lines, wrote $wroteline lines\n";
+
+close (OUT);
+close (IN);
diff --git a/libtommath/callgraph.txt b/libtommath/callgraph.txt
new file mode 100644
index 0000000..2efcf24
--- /dev/null
+++ b/libtommath/callgraph.txt
@@ -0,0 +1,11913 @@
+BN_PRIME_TAB_C
+
+
+BN_MP_SQRT_C
++--->BN_MP_N_ROOT_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_SET_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_EXPT_D_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_SQR_C
+| | | +--->BN_MP_TOOM_SQR_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_FAST_S_MP_SQR_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MUL_C
+| | | +--->BN_MP_TOOM_MUL_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| +--->BN_MP_MUL_C
+| | +--->BN_MP_TOOM_MUL_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_KARATSUBA_MUL_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_MUL_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CMP_C
+| | +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_SUB_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_ZERO_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_RSHD_C
++--->BN_MP_DIV_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_SET_C
+| +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_ABS_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_MUL_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_ADD_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_2_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_CMP_D_C
+
+
+BN_MP_EXCH_C
+
+
+BN_MP_IS_SQUARE_C
++--->BN_MP_MOD_D_C
+| +--->BN_MP_DIV_D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_SET_INT_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_SET_INT_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_MOD_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_GET_INT_C
++--->BN_MP_SQRT_C
+| +--->BN_MP_N_ROOT_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_SET_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_EXPT_D_C
+| | | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_SQR_C
+| | | | +--->BN_MP_TOOM_SQR_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_FAST_S_MP_SQR_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_MUL_C
+| | | +--->BN_MP_TOOM_MUL_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_ABS_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_CMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_SUB_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_2_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_SQR_C
+| +--->BN_MP_TOOM_SQR_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_KARATSUBA_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_SQR_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_CMP_MAG_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_NEG_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
+
+
+BN_MP_EXPTMOD_C
++--->BN_MP_INIT_C
++--->BN_MP_INVMOD_C
+| +--->BN_FAST_MP_INVMOD_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_MOD_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_COUNT_BITS_C
+| | | | +--->BN_MP_ABS_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2D_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_COPY_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_SET_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_CMP_D_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INVMOD_SLOW_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_COUNT_BITS_C
+| | | | +--->BN_MP_ABS_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2D_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_COPY_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_SET_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_CMP_D_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
++--->BN_MP_ABS_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_CLEAR_MULTI_C
++--->BN_MP_REDUCE_IS_2K_L_C
++--->BN_S_MP_EXPTMOD_C
+| +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_REDUCE_SETUP_C
+| | +--->BN_MP_2EXPT_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_DIV_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_SET_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_REDUCE_C
+| | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_C
+| | | +--->BN_MP_TOOM_MUL_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_S_MP_MUL_HIGH_DIGS_C
+| | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_MUL_DIGS_C
+| | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_D_C
+| | +--->BN_MP_SET_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_REDUCE_2K_SETUP_L_C
+| | +--->BN_MP_2EXPT_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_REDUCE_2K_L_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_MUL_C
+| | | +--->BN_MP_TOOM_MUL_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_MOD_C
+| | +--->BN_MP_DIV_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_SET_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_SQR_C
+| | +--->BN_MP_TOOM_SQR_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_KARATSUBA_SQR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | +--->BN_FAST_S_MP_SQR_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SQR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_MP_MUL_C
+| | +--->BN_MP_TOOM_MUL_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_KARATSUBA_MUL_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_MP_SET_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_DR_IS_MODULUS_C
++--->BN_MP_REDUCE_IS_2K_C
+| +--->BN_MP_REDUCE_2K_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_COUNT_BITS_C
++--->BN_MP_EXPTMOD_FAST_C
+| +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_MONTGOMERY_SETUP_C
+| +--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| +--->BN_MP_MONTGOMERY_REDUCE_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| +--->BN_MP_DR_SETUP_C
+| +--->BN_MP_DR_REDUCE_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| +--->BN_MP_REDUCE_2K_SETUP_C
+| | +--->BN_MP_2EXPT_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_REDUCE_2K_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+| | +--->BN_MP_2EXPT_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_SET_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_MULMOD_C
+| | +--->BN_MP_MUL_C
+| | | +--->BN_MP_TOOM_MUL_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_MOD_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2D_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_COPY_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_MP_SET_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_MOD_C
+| | +--->BN_MP_DIV_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_SQR_C
+| | +--->BN_MP_TOOM_SQR_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_KARATSUBA_SQR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | +--->BN_FAST_S_MP_SQR_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SQR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_MP_MUL_C
+| | +--->BN_MP_TOOM_MUL_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_KARATSUBA_MUL_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_MP_EXCH_C
+
+
+BN_MP_OR_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_ZERO_C
+
+
+BN_MP_GROW_C
+
+
+BN_MP_COUNT_BITS_C
+
+
+BN_MP_PRIME_FERMAT_C
++--->BN_MP_CMP_D_C
++--->BN_MP_INIT_C
++--->BN_MP_EXPTMOD_C
+| +--->BN_MP_INVMOD_C
+| | +--->BN_FAST_MP_INVMOD_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_SET_C
+| | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | +--->BN_MP_ABS_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2D_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_INIT_COPY_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INVMOD_SLOW_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_SET_C
+| | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | +--->BN_MP_ABS_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2D_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_INIT_COPY_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_ABS_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_REDUCE_IS_2K_L_C
+| +--->BN_S_MP_EXPTMOD_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_REDUCE_SETUP_C
+| | | +--->BN_MP_2EXPT_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2D_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_COPY_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_REDUCE_C
+| | | +--->BN_MP_INIT_COPY_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_S_MP_MUL_HIGH_DIGS_C
+| | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_REDUCE_2K_SETUP_L_C
+| | | +--->BN_MP_2EXPT_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_REDUCE_2K_L_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MOD_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2D_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_COPY_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_SQR_C
+| | | +--->BN_MP_TOOM_SQR_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | +--->BN_FAST_S_MP_SQR_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_MUL_C
+| | | +--->BN_MP_TOOM_MUL_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_SET_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_DR_IS_MODULUS_C
+| +--->BN_MP_REDUCE_IS_2K_C
+| | +--->BN_MP_REDUCE_2K_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_EXPTMOD_FAST_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_MONTGOMERY_SETUP_C
+| | +--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | +--->BN_MP_MONTGOMERY_REDUCE_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | +--->BN_MP_DR_SETUP_C
+| | +--->BN_MP_DR_REDUCE_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | +--->BN_MP_REDUCE_2K_SETUP_C
+| | | +--->BN_MP_2EXPT_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_REDUCE_2K_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+| | | +--->BN_MP_2EXPT_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MULMOD_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_SET_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2D_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_INIT_COPY_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_SET_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2D_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_COPY_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_SQR_C
+| | | +--->BN_MP_TOOM_SQR_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | +--->BN_FAST_S_MP_SQR_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_MUL_C
+| | | +--->BN_MP_TOOM_MUL_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
++--->BN_MP_CMP_C
+| +--->BN_MP_CMP_MAG_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_SUBMOD_C
++--->BN_MP_INIT_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
++--->BN_MP_MOD_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+
+
+BN_MP_MOD_2D_C
++--->BN_MP_ZERO_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_TORADIX_N_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_DIV_D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_DIV_3_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_CMP_C
++--->BN_MP_CMP_MAG_C
+
+
+BNCORE_C
+
+
+BN_MP_TORADIX_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_DIV_D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_DIV_3_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_ADD_D_C
++--->BN_MP_GROW_C
++--->BN_MP_SUB_D_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_DIV_3_C
++--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_FAST_S_MP_MUL_DIGS_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_SQRMOD_C
++--->BN_MP_INIT_C
++--->BN_MP_SQR_C
+| +--->BN_MP_TOOM_SQR_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_KARATSUBA_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_SQR_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
++--->BN_MP_MOD_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+
+
+BN_MP_INVMOD_C
++--->BN_FAST_MP_INVMOD_C
+| +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_MOD_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_DIV_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_SET_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_ABS_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_SET_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_DIV_2_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_C
+| | +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_CMP_D_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_INVMOD_SLOW_C
+| +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_MOD_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_DIV_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_SET_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_ABS_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_SET_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_DIV_2_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_C
+| | +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_CMP_D_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_CLEAR_C
+
+
+BN_MP_AND_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_MUL_D_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_FAST_MP_INVMOD_C
++--->BN_MP_INIT_MULTI_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_MOD_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_DIV_2_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_C
+| +--->BN_MP_CMP_MAG_C
++--->BN_MP_CMP_D_C
++--->BN_MP_ADD_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_FWRITE_C
++--->BN_MP_RADIX_SIZE_C
+| +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_DIV_D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_TORADIX_C
+| +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_DIV_D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_S_MP_SQR_C
++--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_N_ROOT_C
++--->BN_MP_INIT_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_EXPT_D_C
+| +--->BN_MP_INIT_COPY_C
+| +--->BN_MP_SQR_C
+| | +--->BN_MP_TOOM_SQR_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_KARATSUBA_SQR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_FAST_S_MP_SQR_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SQR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_MUL_C
+| | +--->BN_MP_TOOM_MUL_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_KARATSUBA_MUL_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
++--->BN_MP_MUL_C
+| +--->BN_MP_TOOM_MUL_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_KARATSUBA_MUL_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_ABS_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_INIT_COPY_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_CMP_C
+| +--->BN_MP_CMP_MAG_C
++--->BN_MP_SUB_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_ADD_D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+
+
+BN_MP_RADIX_SIZE_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_DIV_D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_DIV_3_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_READ_SIGNED_BIN_C
++--->BN_MP_READ_UNSIGNED_BIN_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
+
+
+BN_MP_PRIME_RANDOM_EX_C
++--->BN_MP_READ_UNSIGNED_BIN_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_PRIME_IS_PRIME_C
+| +--->BN_MP_CMP_D_C
+| +--->BN_MP_PRIME_IS_DIVISIBLE_C
+| | +--->BN_MP_MOD_D_C
+| | | +--->BN_MP_DIV_D_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_DIV_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_INIT_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_INIT_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_INIT_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_SET_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_PRIME_MILLER_RABIN_C
+| | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_SUB_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CNT_LSB_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXPTMOD_C
+| | | +--->BN_MP_INVMOD_C
+| | | | +--->BN_FAST_MP_INVMOD_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_MOD_C
+| | | | | | +--->BN_MP_DIV_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | | | +--->BN_MP_ABS_C
+| | | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_C
+| | | | | | | +--->BN_MP_SUB_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_ADD_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | | | +--->BN_MP_CLEAR_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CLEAR_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_INVMOD_SLOW_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_MOD_C
+| | | | | | +--->BN_MP_DIV_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | | | +--->BN_MP_ABS_C
+| | | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_C
+| | | | | | | +--->BN_MP_SUB_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_ADD_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | | | +--->BN_MP_CLEAR_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CLEAR_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_ABS_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_REDUCE_IS_2K_L_C
+| | | +--->BN_S_MP_EXPTMOD_C
+| | | | +--->BN_MP_COUNT_BITS_C
+| | | | +--->BN_MP_REDUCE_SETUP_C
+| | | | | +--->BN_MP_2EXPT_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_DIV_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_REDUCE_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_C
+| | | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_ADD_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_SUB_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_MP_EXCH_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_SUB_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_ADD_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_S_MP_MUL_HIGH_DIGS_C
+| | | | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_REDUCE_2K_SETUP_L_C
+| | | | | +--->BN_MP_2EXPT_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_REDUCE_2K_L_C
+| | | | | +--->BN_MP_MUL_C
+| | | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_ADD_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_SUB_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_MP_EXCH_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_SUB_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_ADD_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MOD_C
+| | | | | +--->BN_MP_DIV_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_SQR_C
+| | | | | +--->BN_MP_TOOM_SQR_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_FAST_S_MP_SQR_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SQR_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_MUL_C
+| | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_DR_IS_MODULUS_C
+| | | +--->BN_MP_REDUCE_IS_2K_C
+| | | | +--->BN_MP_REDUCE_2K_C
+| | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_EXPTMOD_FAST_C
+| | | | +--->BN_MP_COUNT_BITS_C
+| | | | +--->BN_MP_MONTGOMERY_SETUP_C
+| | | | +--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_MONTGOMERY_REDUCE_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_DR_SETUP_C
+| | | | +--->BN_MP_DR_REDUCE_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_REDUCE_2K_SETUP_C
+| | | | | +--->BN_MP_2EXPT_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_REDUCE_2K_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+| | | | | +--->BN_MP_2EXPT_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MULMOD_C
+| | | | | +--->BN_MP_MUL_C
+| | | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_ADD_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_SUB_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_MP_EXCH_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_SUB_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_ADD_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_MOD_C
+| | | | | | +--->BN_MP_DIV_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_C
+| | | | | | | +--->BN_MP_SUB_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_ADD_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_MOD_C
+| | | | | +--->BN_MP_DIV_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_SQR_C
+| | | | | +--->BN_MP_TOOM_SQR_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_FAST_S_MP_SQR_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SQR_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_MUL_C
+| | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_SQRMOD_C
+| | | +--->BN_MP_SQR_C
+| | | | +--->BN_MP_TOOM_SQR_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_FAST_S_MP_SQR_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | +--->BN_MP_ABS_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_SUB_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_ADD_D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_2_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_2_C
+| +--->BN_MP_GROW_C
++--->BN_MP_ADD_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
+
+
+BN_MP_KARATSUBA_SQR_C
++--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_SQR_C
+| +--->BN_MP_TOOM_SQR_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_SQR_C
+| | +--->BN_MP_GROW_C
+| +--->BN_S_MP_SQR_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
++--->BN_S_MP_ADD_C
+| +--->BN_MP_GROW_C
++--->BN_MP_LSHD_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_RSHD_C
+| | +--->BN_MP_ZERO_C
++--->BN_MP_ADD_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_INIT_COPY_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
+
+
+BN_MP_CLAMP_C
+
+
+BN_MP_TOOM_SQR_C
++--->BN_MP_INIT_MULTI_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_MOD_2D_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_RSHD_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_SQR_C
+| +--->BN_MP_KARATSUBA_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_SQR_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_MUL_2_C
+| +--->BN_MP_GROW_C
++--->BN_MP_ADD_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_2_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_2D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_LSHD_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_3_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_LSHD_C
+| +--->BN_MP_GROW_C
++--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_MOD_C
++--->BN_MP_INIT_C
++--->BN_MP_DIV_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_SET_C
+| +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_ABS_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_INIT_COPY_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_MUL_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
++--->BN_MP_ADD_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
+
+
+BN_MP_INIT_C
+
+
+BN_MP_TOOM_MUL_C
++--->BN_MP_INIT_MULTI_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_MOD_2D_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_RSHD_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_MUL_C
+| +--->BN_MP_KARATSUBA_MUL_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_MUL_2_C
+| +--->BN_MP_GROW_C
++--->BN_MP_ADD_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_2_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_2D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_LSHD_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_3_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_LSHD_C
+| +--->BN_MP_GROW_C
++--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_PRIME_IS_PRIME_C
++--->BN_MP_CMP_D_C
++--->BN_MP_PRIME_IS_DIVISIBLE_C
+| +--->BN_MP_MOD_D_C
+| | +--->BN_MP_DIV_D_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_INIT_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_INIT_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_PRIME_MILLER_RABIN_C
+| +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_SUB_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CNT_LSB_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_EXPTMOD_C
+| | +--->BN_MP_INVMOD_C
+| | | +--->BN_FAST_MP_INVMOD_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_MOD_C
+| | | | | +--->BN_MP_DIV_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | | +--->BN_MP_ABS_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | | +--->BN_MP_CLEAR_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_INVMOD_SLOW_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_MOD_C
+| | | | | +--->BN_MP_DIV_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | | +--->BN_MP_ABS_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | | +--->BN_MP_CLEAR_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_ABS_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_REDUCE_IS_2K_L_C
+| | +--->BN_S_MP_EXPTMOD_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_REDUCE_SETUP_C
+| | | | +--->BN_MP_2EXPT_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_REDUCE_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_C
+| | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_S_MP_MUL_HIGH_DIGS_C
+| | | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_REDUCE_2K_SETUP_L_C
+| | | | +--->BN_MP_2EXPT_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_REDUCE_2K_L_C
+| | | | +--->BN_MP_MUL_C
+| | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_SQR_C
+| | | | +--->BN_MP_TOOM_SQR_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_FAST_S_MP_SQR_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_DR_IS_MODULUS_C
+| | +--->BN_MP_REDUCE_IS_2K_C
+| | | +--->BN_MP_REDUCE_2K_C
+| | | | +--->BN_MP_COUNT_BITS_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_EXPTMOD_FAST_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_MONTGOMERY_SETUP_C
+| | | +--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_MONTGOMERY_REDUCE_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_DR_SETUP_C
+| | | +--->BN_MP_DR_REDUCE_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_REDUCE_2K_SETUP_C
+| | | | +--->BN_MP_2EXPT_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_REDUCE_2K_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+| | | | +--->BN_MP_2EXPT_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MULMOD_C
+| | | | +--->BN_MP_MUL_C
+| | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_MOD_C
+| | | | | +--->BN_MP_DIV_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_SQR_C
+| | | | +--->BN_MP_TOOM_SQR_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_FAST_S_MP_SQR_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_MP_CMP_C
+| | +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_SQRMOD_C
+| | +--->BN_MP_SQR_C
+| | | +--->BN_MP_TOOM_SQR_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_FAST_S_MP_SQR_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_COUNT_BITS_C
+| | | | +--->BN_MP_ABS_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_COPY_C
++--->BN_MP_GROW_C
+
+
+BN_S_MP_SUB_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_READ_UNSIGNED_BIN_C
++--->BN_MP_GROW_C
++--->BN_MP_ZERO_C
++--->BN_MP_MUL_2D_C
+| +--->BN_MP_COPY_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_EXPTMOD_FAST_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_INIT_C
++--->BN_MP_CLEAR_C
++--->BN_MP_MONTGOMERY_SETUP_C
++--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_RSHD_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
++--->BN_MP_MONTGOMERY_REDUCE_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_RSHD_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
++--->BN_MP_DR_SETUP_C
++--->BN_MP_DR_REDUCE_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
++--->BN_MP_REDUCE_2K_SETUP_C
+| +--->BN_MP_2EXPT_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_GROW_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_REDUCE_2K_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_MUL_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+| +--->BN_MP_2EXPT_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_SET_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_MUL_2_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_MULMOD_C
+| +--->BN_MP_MUL_C
+| | +--->BN_MP_TOOM_MUL_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_KARATSUBA_MUL_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_MP_MOD_C
+| | +--->BN_MP_DIV_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_SET_C
+| | | +--->BN_MP_ABS_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_MOD_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_SQR_C
+| +--->BN_MP_TOOM_SQR_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_KARATSUBA_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| +--->BN_FAST_S_MP_SQR_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
++--->BN_MP_MUL_C
+| +--->BN_MP_TOOM_MUL_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_KARATSUBA_MUL_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
++--->BN_MP_EXCH_C
+
+
+BN_MP_TO_UNSIGNED_BIN_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_DIV_2D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_SET_INT_C
++--->BN_MP_ZERO_C
++--->BN_MP_MUL_2D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_MOD_D_C
++--->BN_MP_DIV_D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_DIV_3_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_SQR_C
++--->BN_MP_TOOM_SQR_C
+| +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_RSHD_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_MUL_2_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_2_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_MUL_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_3_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_KARATSUBA_SQR_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| +--->BN_MP_ADD_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_CLEAR_C
++--->BN_FAST_S_MP_SQR_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_S_MP_SQR_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_MULMOD_C
++--->BN_MP_INIT_C
++--->BN_MP_MUL_C
+| +--->BN_MP_TOOM_MUL_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_KARATSUBA_MUL_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
++--->BN_MP_MOD_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+
+
+BN_MP_DIV_2D_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_ZERO_C
++--->BN_MP_INIT_C
++--->BN_MP_MOD_2D_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
++--->BN_MP_RSHD_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
+
+
+BN_S_MP_ADD_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_FAST_S_MP_SQR_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_S_MP_MUL_DIGS_C
++--->BN_FAST_S_MP_MUL_DIGS_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_XOR_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_RADIX_SMAP_C
+
+
+BN_MP_DR_IS_MODULUS_C
+
+
+BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_2EXPT_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_GROW_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_MUL_2_C
+| +--->BN_MP_GROW_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
+
+
+BN_MP_SUB_C
++--->BN_S_MP_ADD_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
+
+
+BN_MP_INIT_MULTI_C
++--->BN_MP_INIT_C
++--->BN_MP_CLEAR_C
+
+
+BN_S_MP_MUL_HIGH_DIGS_C
++--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_PRIME_NEXT_PRIME_C
++--->BN_MP_CMP_D_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_SUB_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_ADD_D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_MOD_D_C
+| +--->BN_MP_DIV_D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_C
++--->BN_MP_ADD_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_PRIME_MILLER_RABIN_C
+| +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_CNT_LSB_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_EXPTMOD_C
+| | +--->BN_MP_INVMOD_C
+| | | +--->BN_FAST_MP_INVMOD_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_MOD_C
+| | | | | +--->BN_MP_DIV_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | | +--->BN_MP_ABS_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | | +--->BN_MP_CLEAR_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_INVMOD_SLOW_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_MOD_C
+| | | | | +--->BN_MP_DIV_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | | +--->BN_MP_ABS_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | | +--->BN_MP_CLEAR_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_ABS_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_REDUCE_IS_2K_L_C
+| | +--->BN_S_MP_EXPTMOD_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_REDUCE_SETUP_C
+| | | | +--->BN_MP_2EXPT_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_REDUCE_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_C
+| | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_S_MP_MUL_HIGH_DIGS_C
+| | | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_REDUCE_2K_SETUP_L_C
+| | | | +--->BN_MP_2EXPT_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_REDUCE_2K_L_C
+| | | | +--->BN_MP_MUL_C
+| | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_SQR_C
+| | | | +--->BN_MP_TOOM_SQR_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_FAST_S_MP_SQR_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_DR_IS_MODULUS_C
+| | +--->BN_MP_REDUCE_IS_2K_C
+| | | +--->BN_MP_REDUCE_2K_C
+| | | | +--->BN_MP_COUNT_BITS_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_EXPTMOD_FAST_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_MONTGOMERY_SETUP_C
+| | | +--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_MONTGOMERY_REDUCE_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_DR_SETUP_C
+| | | +--->BN_MP_DR_REDUCE_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_REDUCE_2K_SETUP_C
+| | | | +--->BN_MP_2EXPT_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_REDUCE_2K_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+| | | | +--->BN_MP_2EXPT_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MULMOD_C
+| | | | +--->BN_MP_MUL_C
+| | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_MOD_C
+| | | | | +--->BN_MP_DIV_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_SQR_C
+| | | | +--->BN_MP_TOOM_SQR_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_FAST_S_MP_SQR_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_MP_CMP_C
+| | +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_SQRMOD_C
+| | +--->BN_MP_SQR_C
+| | | +--->BN_MP_TOOM_SQR_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_FAST_S_MP_SQR_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_COUNT_BITS_C
+| | | | +--->BN_MP_ABS_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_SIGNED_BIN_SIZE_C
++--->BN_MP_UNSIGNED_BIN_SIZE_C
+| +--->BN_MP_COUNT_BITS_C
+
+
+BN_MP_INVMOD_SLOW_C
++--->BN_MP_INIT_MULTI_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_MOD_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_DIV_2_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_ADD_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_C
+| +--->BN_MP_CMP_MAG_C
++--->BN_MP_CMP_D_C
++--->BN_MP_CMP_MAG_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_LCM_C
++--->BN_MP_INIT_MULTI_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_GCD_C
+| +--->BN_MP_ABS_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_CNT_LSB_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_EXCH_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_CMP_MAG_C
++--->BN_MP_DIV_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_SET_C
+| +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_ABS_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_INIT_COPY_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_MUL_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_MUL_C
+| +--->BN_MP_TOOM_MUL_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_KARATSUBA_MUL_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_REDUCE_2K_L_C
++--->BN_MP_INIT_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_DIV_2D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_MUL_C
+| +--->BN_MP_TOOM_MUL_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_KARATSUBA_MUL_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_S_MP_ADD_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
+
+
+BN_REVERSE_C
+
+
+BN_MP_PRIME_IS_DIVISIBLE_C
++--->BN_MP_MOD_D_C
+| +--->BN_MP_DIV_D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+
+
+BN_MP_SET_C
++--->BN_MP_ZERO_C
+
+
+BN_MP_GCD_C
++--->BN_MP_ABS_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_ZERO_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_CNT_LSB_C
++--->BN_MP_DIV_2D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_CMP_MAG_C
++--->BN_MP_EXCH_C
++--->BN_S_MP_SUB_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_2D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_REDUCE_2K_SETUP_L_C
++--->BN_MP_INIT_C
++--->BN_MP_2EXPT_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_GROW_C
++--->BN_MP_COUNT_BITS_C
++--->BN_S_MP_SUB_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_READ_RADIX_C
++--->BN_MP_ZERO_C
++--->BN_MP_MUL_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_ADD_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_SUB_D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
+
+
+BN_FAST_S_MP_MUL_HIGH_DIGS_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_FAST_MP_MONTGOMERY_REDUCE_C
++--->BN_MP_GROW_C
++--->BN_MP_RSHD_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+
+
+BN_MP_DIV_D_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_DIV_2D_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_DIV_3_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_REDUCE_2K_SETUP_C
++--->BN_MP_INIT_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_2EXPT_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_GROW_C
++--->BN_MP_CLEAR_C
++--->BN_S_MP_SUB_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
+
+
+BN_MP_INIT_SET_C
++--->BN_MP_INIT_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
+
+
+BN_MP_REDUCE_2K_C
++--->BN_MP_INIT_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_DIV_2D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_MUL_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_S_MP_ADD_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
+
+
+BN_ERROR_C
+
+
+BN_MP_EXPT_D_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_SQR_C
+| +--->BN_MP_TOOM_SQR_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_KARATSUBA_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_SQR_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
++--->BN_MP_MUL_C
+| +--->BN_MP_TOOM_MUL_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_KARATSUBA_MUL_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+
+
+BN_S_MP_EXPTMOD_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_INIT_C
++--->BN_MP_CLEAR_C
++--->BN_MP_REDUCE_SETUP_C
+| +--->BN_MP_2EXPT_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_REDUCE_C
+| +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_RSHD_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_MUL_C
+| | +--->BN_MP_TOOM_MUL_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_KARATSUBA_MUL_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_S_MP_MUL_HIGH_DIGS_C
+| | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_D_C
+| +--->BN_MP_SET_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_C
+| | +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_REDUCE_2K_SETUP_L_C
+| +--->BN_MP_2EXPT_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_GROW_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_REDUCE_2K_L_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_MUL_C
+| | +--->BN_MP_TOOM_MUL_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_KARATSUBA_MUL_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_MOD_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_SQR_C
+| +--->BN_MP_TOOM_SQR_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_KARATSUBA_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| +--->BN_FAST_S_MP_SQR_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
++--->BN_MP_MUL_C
+| +--->BN_MP_TOOM_MUL_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_KARATSUBA_MUL_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_EXCH_C
+
+
+BN_MP_ABS_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
+
+
+BN_MP_INIT_SET_INT_C
++--->BN_MP_INIT_C
++--->BN_MP_SET_INT_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
+
+
+BN_MP_SUB_D_C
++--->BN_MP_GROW_C
++--->BN_MP_ADD_D_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_TO_SIGNED_BIN_C
++--->BN_MP_TO_UNSIGNED_BIN_C
+| +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_DIV_2_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_REDUCE_IS_2K_C
++--->BN_MP_REDUCE_2K_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_MUL_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_COUNT_BITS_C
+
+
+BN_MP_INIT_SIZE_C
++--->BN_MP_INIT_C
+
+
+BN_MP_DIV_C
++--->BN_MP_CMP_MAG_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_ZERO_C
++--->BN_MP_INIT_MULTI_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_SET_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_ABS_C
++--->BN_MP_MUL_2D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_ADD_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_2D_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_INIT_C
++--->BN_MP_INIT_C
++--->BN_MP_INIT_COPY_C
++--->BN_MP_LSHD_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_RSHD_C
++--->BN_MP_RSHD_C
++--->BN_MP_MUL_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_CLEAR_C
+
+
+BN_MP_MONTGOMERY_REDUCE_C
++--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_RSHD_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
++--->BN_MP_RSHD_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+
+
+BN_MP_MUL_2_C
++--->BN_MP_GROW_C
+
+
+BN_MP_UNSIGNED_BIN_SIZE_C
++--->BN_MP_COUNT_BITS_C
+
+
+BN_MP_ADDMOD_C
++--->BN_MP_INIT_C
++--->BN_MP_ADD_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
++--->BN_MP_MOD_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+
+
+BN_MP_ADD_C
++--->BN_S_MP_ADD_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
+
+
+BN_MP_TO_SIGNED_BIN_N_C
++--->BN_MP_SIGNED_BIN_SIZE_C
+| +--->BN_MP_UNSIGNED_BIN_SIZE_C
+| | +--->BN_MP_COUNT_BITS_C
++--->BN_MP_TO_SIGNED_BIN_C
+| +--->BN_MP_TO_UNSIGNED_BIN_C
+| | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+
+
+BN_MP_REDUCE_IS_2K_L_C
+
+
+BN_MP_RAND_C
++--->BN_MP_ZERO_C
++--->BN_MP_ADD_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_SUB_D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_LSHD_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_RSHD_C
+
+
+BN_MP_CNT_LSB_C
+
+
+BN_MP_2EXPT_C
++--->BN_MP_ZERO_C
++--->BN_MP_GROW_C
+
+
+BN_MP_RSHD_C
++--->BN_MP_ZERO_C
+
+
+BN_MP_SHRINK_C
+
+
+BN_MP_TO_UNSIGNED_BIN_N_C
++--->BN_MP_UNSIGNED_BIN_SIZE_C
+| +--->BN_MP_COUNT_BITS_C
++--->BN_MP_TO_UNSIGNED_BIN_C
+| +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_REDUCE_C
++--->BN_MP_REDUCE_SETUP_C
+| +--->BN_MP_2EXPT_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_RSHD_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_MUL_C
+| +--->BN_MP_TOOM_MUL_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_KARATSUBA_MUL_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_S_MP_MUL_HIGH_DIGS_C
+| +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_MOD_2D_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_S_MP_MUL_DIGS_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_D_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_LSHD_C
+| +--->BN_MP_GROW_C
++--->BN_MP_ADD_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_C
+| +--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_MUL_2D_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_GROW_C
++--->BN_MP_LSHD_C
+| +--->BN_MP_RSHD_C
+| | +--->BN_MP_ZERO_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_GET_INT_C
+
+
+BN_MP_JACOBI_C
++--->BN_MP_CMP_D_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_CNT_LSB_C
++--->BN_MP_DIV_2D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_MOD_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_CLEAR_MULTI_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_MUL_C
++--->BN_MP_TOOM_MUL_C
+| +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_RSHD_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_MUL_2_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_2_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_MUL_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_3_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_KARATSUBA_MUL_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| +--->BN_MP_CLEAR_C
++--->BN_FAST_S_MP_MUL_DIGS_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_S_MP_MUL_DIGS_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_EXTEUCLID_C
++--->BN_MP_INIT_MULTI_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_DIV_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_ABS_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_INIT_COPY_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_MUL_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_MUL_C
+| +--->BN_MP_TOOM_MUL_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_KARATSUBA_MUL_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_NEG_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_DR_REDUCE_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+
+
+BN_MP_FREAD_C
++--->BN_MP_ZERO_C
++--->BN_MP_MUL_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_ADD_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_SUB_D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_D_C
+
+
+BN_MP_REDUCE_SETUP_C
++--->BN_MP_2EXPT_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_GROW_C
++--->BN_MP_DIV_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_SET_C
+| +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_ABS_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_INIT_COPY_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_MUL_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_MONTGOMERY_SETUP_C
+
+
+BN_MP_KARATSUBA_MUL_C
++--->BN_MP_MUL_C
+| +--->BN_MP_TOOM_MUL_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_ADD_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_LSHD_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_RSHD_C
+| | +--->BN_MP_ZERO_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_LSHD_C
++--->BN_MP_GROW_C
++--->BN_MP_RSHD_C
+| +--->BN_MP_ZERO_C
+
+
+BN_MP_PRIME_MILLER_RABIN_C
++--->BN_MP_CMP_D_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_SUB_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_ADD_D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CNT_LSB_C
++--->BN_MP_DIV_2D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_EXPTMOD_C
+| +--->BN_MP_INVMOD_C
+| | +--->BN_FAST_MP_INVMOD_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_SET_C
+| | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | +--->BN_MP_ABS_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INVMOD_SLOW_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_SET_C
+| | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | +--->BN_MP_ABS_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_ABS_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_REDUCE_IS_2K_L_C
+| +--->BN_S_MP_EXPTMOD_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_REDUCE_SETUP_C
+| | | +--->BN_MP_2EXPT_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_REDUCE_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_S_MP_MUL_HIGH_DIGS_C
+| | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_REDUCE_2K_SETUP_L_C
+| | | +--->BN_MP_2EXPT_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_REDUCE_2K_L_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MOD_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_SQR_C
+| | | +--->BN_MP_TOOM_SQR_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | +--->BN_FAST_S_MP_SQR_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_MUL_C
+| | | +--->BN_MP_TOOM_MUL_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_SET_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_DR_IS_MODULUS_C
+| +--->BN_MP_REDUCE_IS_2K_C
+| | +--->BN_MP_REDUCE_2K_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_EXPTMOD_FAST_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_MONTGOMERY_SETUP_C
+| | +--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | +--->BN_MP_MONTGOMERY_REDUCE_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | +--->BN_MP_DR_SETUP_C
+| | +--->BN_MP_DR_REDUCE_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | +--->BN_MP_REDUCE_2K_SETUP_C
+| | | +--->BN_MP_2EXPT_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_REDUCE_2K_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+| | | +--->BN_MP_2EXPT_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MULMOD_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_SET_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_SET_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_SQR_C
+| | | +--->BN_MP_TOOM_SQR_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | +--->BN_FAST_S_MP_SQR_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_MUL_C
+| | | +--->BN_MP_TOOM_MUL_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
++--->BN_MP_CMP_C
+| +--->BN_MP_CMP_MAG_C
++--->BN_MP_SQRMOD_C
+| +--->BN_MP_SQR_C
+| | +--->BN_MP_TOOM_SQR_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_KARATSUBA_SQR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_FAST_S_MP_SQR_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SQR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_MOD_C
+| | +--->BN_MP_DIV_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_SET_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_ABS_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_DR_SETUP_C
+
+
+BN_MP_CMP_MAG_C
+
+
diff --git a/libtommath/changes.txt b/libtommath/changes.txt
new file mode 100644
index 0000000..4fc0913
--- /dev/null
+++ b/libtommath/changes.txt
@@ -0,0 +1,403 @@
+July 23rd, 2010
+v0.42.0
+ -- Fix for mp_prime_next_prime() bug when checking generated prime
+ -- allow mp_shrink to shrink initialized, but empty MPI's
+ -- Added project and solution files for Visual Studio 2005 and Visual Studio 2008.
+
+March 10th, 2007
+v0.41 -- Wolfgang Ehrhardt suggested a quick fix to mp_div_d() which makes the detection of powers of two quicker.
+ -- [CRI] Added libtommath.dsp for Visual C++ users.
+
+December 24th, 2006
+v0.40 -- Updated makefile to properly support LIBNAME
+ -- Fixed bug in fast_s_mp_mul_high_digs() which overflowed (line 83), thanks Valgrind!
+
+April 4th, 2006
+v0.39 -- Jim Wigginton pointed out my Montgomery examples in figures 6.4 and 6.6 were off by one, k should be 9 not 8
+ -- Bruce Guenter suggested I use --tag=CC for libtool builds where the compiler may think it's C++.
+ -- "mm" from sci.crypt pointed out that my mp_gcd was sub-optimal (I also updated and corrected the book)
+ -- updated some of the @@ tags in tommath.src to reflect source changes.
+ -- updated email and url info in all source files
+
+Jan 26th, 2006
+v0.38 -- broken makefile.shared fixed
+ -- removed some carry stores that were not required [updated text]
+
+November 18th, 2005
+v0.37 -- [Don Porter] reported on a TCL list [HEY SEND ME BUGREPORTS ALREADY!!!] that mp_add_d() would compute -0 with some inputs. Fixed.
+ -- [rinick@gmail.com] reported the makefile.bcc was messed up. Fixed.
+ -- [Kevin Kenny] reported some issues with mp_toradix_n(). Now it doesn't require a min of 3 chars of output.
+ -- Made the make command renamable. Wee
+
+August 1st, 2005
+v0.36 -- LTM_PRIME_2MSB_ON was fixed and the "OFF" flag was removed.
+ -- [Peter LaDow] found a typo in the XREALLOC macro
+ -- [Peter LaDow] pointed out that mp_read_(un)signed_bin should have "const" on the input
+ -- Ported LTC patch to fix the prime_random_ex() function to get the bitsize correct [and the maskOR flags]
+ -- Kevin Kenny pointed out a stray //
+ -- David Hulton pointed out a typo in the textbook [mp_montgomery_setup() pseudo-code]
+ -- Neal Hamilton (Elliptic Semiconductor) pointed out that my Karatsuba notation was backwards and that I could use
+ unsigned operations in the routine.
+ -- Paul Schmidt pointed out a linking error in mp_exptmod() when BN_S_MP_EXPTMOD_C is undefined (and another for read_radix)
+ -- Updated makefiles to be way more flexible
+
+March 12th, 2005
+v0.35 -- Stupid XOR function missing line again... oops.
+ -- Fixed bug in invmod not handling negative inputs correctly [Wolfgang Ehrhardt]
+ -- Made exteuclid always give positive u3 output...[ Wolfgang Ehrhardt ]
+ -- [Wolfgang Ehrhardt] Suggested a fix for mp_reduce() which avoided underruns. ;-)
+ -- mp_rand() would emit one too many digits and it was possible to get a 0 out of it ... oops
+ -- Added montgomery to the testing to make sure it handles 1..10 digit moduli correctly
+ -- Fixed bug in comba that would lead to possible erroneous outputs when "pa < digs"
+ -- Fixed bug in mp_toradix_size for "0" [Kevin Kenny]
+ -- Updated chapters 1-5 of the textbook ;-) It now talks about the new comba code!
+
+February 12th, 2005
+v0.34 -- Fixed two more small errors in mp_prime_random_ex()
+ -- Fixed overflow in mp_mul_d() [Kevin Kenny]
+ -- Added mp_to_(un)signed_bin_n() functions which do bounds checking for ya [and report the size]
+ -- Added "large" diminished radix support. Speeds up things like DSA where the moduli is of the form 2^k - P for some P < 2^(k/2) or so
+ Actually is faster than Montgomery on my AMD64 (and probably much faster on a P4)
+ -- Updated the manual a bit
+ -- Ok so I haven't done the textbook work yet... My current freelance gig has landed me in France till the
+ end of Feb/05. Once I get back I'll have tons of free time and I plan to go to town on the book.
+ As of this release the API will freeze. At least until the book catches up with all the changes. I welcome
+ bug reports but new algorithms will have to wait.
+
+December 23rd, 2004
+v0.33 -- Fixed "small" variant for mp_div() which would munge with negative dividends...
+ -- Fixed bug in mp_prime_random_ex() which would set the most significant byte to zero when
+ no special flags were set
+ -- Fixed overflow [minor] bug in fast_s_mp_sqr()
+ -- Made the makefiles easier to configure the group/user that ltm will install as
+ -- Fixed "final carry" bug in comba multipliers. (Volkan Ceylan)
+ -- Matt Johnston pointed out a missing semi-colon in mp_exptmod
+
+October 29th, 2004
+v0.32 -- Added "makefile.shared" for shared object support
+ -- Added more to the build options/configs in the manual
+ -- Started the Depends framework, wrote dep.pl to scan deps and
+ produce "callgraph.txt" ;-)
+ -- Wrote SC_RSA_1 which will enable close to the minimum required to perform
+ RSA on 32-bit [or 64-bit] platforms with LibTomCrypt
+ -- Merged in the small/slower mp_div replacement. You can now toggle which
+ you want to use as your mp_div() at build time. Saves roughly 8KB or so.
+ -- Renamed a few files and changed some comments to make depends system work better.
+ (No changes to function names)
+ -- Merged in new Combas that perform 2 reads per inner loop instead of the older
+ 3reads/2writes per inner loop of the old code. Really though if you want speed
+ learn to use TomsFastMath ;-)
+
+August 9th, 2004
+v0.31 -- "profiled" builds now :-) new timings for Intel Northwoods
+ -- Added "pretty" build target
+ -- Update mp_init() to actually assign 0's instead of relying on calloc()
+ -- "Wolfgang Ehrhardt" <Wolfgang.Ehrhardt@munich.netsurf.de> found a bug in mp_mul() where if
+ you multiply a negative by zero you get negative zero as the result. Oops.
+ -- J Harper from PeerSec let me toy with his AMD64 and I got 60-bit digits working properly
+ [this also means that I fixed a bug where if sizeof(int) < sizeof(mp_digit) it would bug]
+
+April 11th, 2004
+v0.30 -- Added "mp_toradix_n" which stores upto "n-1" least significant digits of an mp_int
+ -- Johan Lindh sent a patch so MSVC wouldn't whine about redefining malloc [in weird dll modes]
+ -- Henrik Goldman spotted a missing OPT_CAST in mp_fwrite()
+ -- Tuned tommath.h so that when MP_LOW_MEM is defined MP_PREC shall be reduced.
+ [I also allow MP_PREC to be externally defined now]
+ -- Sped up mp_cnt_lsb() by using a 4x4 table [e.g. 4x speedup]
+ -- Added mp_prime_random_ex() which is a more versatile prime generator accurate to
+ exact bit lengths (unlike the deprecated but still available mp_prime_random() which
+ is only accurate to byte lengths). See the new LTM_PRIME_* flags ;-)
+ -- Alex Polushin contributed an optimized mp_sqrt() as well as mp_get_int() and mp_is_square().
+ I've cleaned them all up to be a little more consistent [along with one bug fix] for this release.
+ -- Added mp_init_set and mp_init_set_int to initialize and set small constants with one function
+ call.
+ -- Removed /etclib directory [um LibTomPoly deprecates this].
+ -- Fixed mp_mod() so the sign of the result agrees with the sign of the modulus.
+ ++ N.B. My semester is almost up so expect updates to the textbook to be posted to the libtomcrypt.org
+ website.
+
+Jan 25th, 2004
+v0.29 ++ Note: "Henrik" from the v0.28 changelog refers to Henrik Goldman ;-)
+ -- Added fix to mp_shrink to prevent a realloc when used == 0 [e.g. realloc zero bytes???]
+ -- Made the mp_prime_rabin_miller_trials() function internal table smaller and also
+ set the minimum number of tests to two (sounds a bit safer).
+ -- Added a mp_exteuclid() which computes the extended euclidean algorithm.
+ -- Fixed a memory leak in s_mp_exptmod() [called when Barrett reduction is to be used] which would arise
+ if a multiplication or subsequent reduction failed [would not free the temp result].
+ -- Made an API change to mp_radix_size(). It now returns an error code and stores the required size
+ through an "int star" passed to it.
+
+Dec 24th, 2003
+v0.28 -- Henrik Goldman suggested I add casts to the montomgery code [stores into mu...] so compilers wouldn't
+ spew [erroneous] diagnostics... fixed.
+ -- Henrik Goldman also spotted two typos. One in mp_radix_size() and another in mp_toradix().
+ -- Added fix to mp_shrink() to avoid a memory leak.
+ -- Added mp_prime_random() which requires a callback to make truly random primes of a given nature
+ (idea from chat with Niels Ferguson at Crypto'03)
+ -- Picked up a second wind. I'm filled with Gooo. Mission Gooo!
+ -- Removed divisions from mp_reduce_is_2k()
+ -- Sped up mp_div_d() [general case] to use only one division per digit instead of two.
+ -- Added the heap macros from LTC to LTM. Now you can easily [by editing four lines of tommath.h]
+ change the name of the heap functions used in LTM [also compatible with LTC via MPI mode]
+ -- Added bn_prime_rabin_miller_trials() which gives the number of Rabin-Miller trials to achieve
+ a failure rate of less than 2^-96
+ -- fixed bug in fast_mp_invmod(). The initial testing logic was wrong. An invalid input is not when
+ "a" and "b" are even it's when "b" is even [the algo is for odd moduli only].
+ -- Started a new manual [finally]. It is incomplete and will be finished as time goes on. I had to stop
+ adding full demos around half way in chapter three so I could at least get a good portion of the
+ manual done. If you really need help using the library you can always email me!
+ -- My Textbook is now included as part of the package [all Public Domain]
+
+Sept 19th, 2003
+v0.27 -- Removed changes.txt~ which was made by accident since "kate" decided it was
+ a good time to re-enable backups... [kde is fun!]
+ -- In mp_grow() "a->dp" is not overwritten by realloc call [re: memory leak]
+ Now if mp_grow() fails the mp_int is still valid and can be cleared via
+ mp_clear() to reclaim the memory.
+ -- Henrik Goldman found a buffer overflow bug in mp_add_d(). Fixed.
+ -- Cleaned up mp_mul_d() to be much easier to read and follow.
+
+Aug 29th, 2003
+v0.26 -- Fixed typo that caused warning with GCC 3.2
+ -- Martin Marcel noticed a bug in mp_neg() that allowed negative zeroes.
+ Also, Martin is the fellow who noted the bugs in mp_gcd() of 0.24/0.25.
+ -- Martin Marcel noticed an optimization [and slight bug] in mp_lcm().
+ -- Added fix to mp_read_unsigned_bin to prevent a buffer overflow.
+ -- Beefed up the comments in the baseline multipliers [and montgomery]
+ -- Added "mont" demo to the makefile.msvc in etc/
+ -- Optimized sign compares in mp_cmp from 4 to 2 cases.
+
+Aug 4th, 2003
+v0.25 -- Fix to mp_gcd again... oops (0,-a) == (-a, 0) == a
+ -- Fix to mp_clear which didn't reset the sign [Greg Rose]
+ -- Added mp_error_to_string() to convert return codes to strings. [Greg Rose]
+ -- Optimized fast_mp_invmod() to do the test for invalid inputs [both even]
+ first so temps don't have to be initialized if it's going to fail.
+ -- Optimized mp_gcd() by removing mp_div_2d calls for when one of the inputs
+ is odd.
+ -- Tons of new comments, some indentation fixups, etc.
+ -- mp_jacobi() returns MP_VAL if the modulus is less than or equal to zero.
+ -- fixed two typos in the header of each file :-)
+ -- LibTomMath is officially Public Domain [see LICENSE]
+
+July 15th, 2003
+v0.24 -- Optimized mp_add_d and mp_sub_d to not allocate temporary variables
+ -- Fixed mp_gcd() so the gcd of 0,0 is 0. Allows the gcd operation to be chained
+ e.g. (0,0,a) == a [instead of 1]
+ -- Should be one of the last release for a while. Working on LibTomMath book now.
+ -- optimized the pprime demo [/etc/pprime.c] to first make a huge table of single
+ digit primes then it reads them randomly instead of randomly choosing/testing single
+ digit primes.
+
+July 12th, 2003
+v0.23 -- Optimized mp_prime_next_prime() to not use mp_mod [via is_divisible()] in each
+ iteration. Instead now a smaller table is kept of the residues which can be updated
+ without division.
+ -- Fixed a bug in next_prime() where an input of zero would be treated as odd and
+ have two added to it [to move to the next odd].
+ -- fixed a bug in prime_fermat() and prime_miller_rabin() which allowed the base
+ to be negative, zero or one. Normally the test is only valid if the base is
+ greater than one.
+ -- changed the next_prime() prototype to accept a new parameter "bbs_style" which
+ will find the next prime congruent to 3 mod 4. The default [bbs_style==0] will
+ make primes which are either congruent to 1 or 3 mod 4.
+ -- fixed mp_read_unsigned_bin() so that it doesn't include both code for
+ the case DIGIT_BIT < 8 and >= 8
+ -- optimized div_d() to easy out on division by 1 [or if a == 0] and use
+ logical shifts if the divisor is a power of two.
+ -- the default DIGIT_BIT type was not int for non-default builds. Fixed.
+
+July 2nd, 2003
+v0.22 -- Fixed up mp_invmod so the result is properly in range now [was always congruent to the inverse...]
+ -- Fixed up s_mp_exptmod and mp_exptmod_fast so the lower half of the pre-computed table isn't allocated
+ which makes the algorithm use half as much ram.
+ -- Fixed the install script not to make the book :-) [which isn't included anyways]
+ -- added mp_cnt_lsb() which counts how many of the lsbs are zero
+ -- optimized mp_gcd() to use the new mp_cnt_lsb() to replace multiple divisions by two by a single division.
+ -- applied similar optimization to mp_prime_miller_rabin().
+ -- Fixed a bug in both mp_invmod() and fast_mp_invmod() which tested for odd
+ via "mp_iseven() == 0" which is not valid [since zero is not even either].
+
+June 19th, 2003
+v0.21 -- Fixed bug in mp_mul_d which would not handle sign correctly [would not always forward it]
+ -- Removed the #line lines from gen.pl [was in violation of ISO C]
+
+June 8th, 2003
+v0.20 -- Removed the book from the package. Added the TDCAL license document.
+ -- This release is officially pure-bred TDCAL again [last officially TDCAL based release was v0.16]
+
+June 6th, 2003
+v0.19 -- Fixed a bug in mp_montgomery_reduce() which was introduced when I tweaked mp_rshd() in the previous release.
+ Essentially the digits were not trimmed before the compare which cause a subtraction to occur all the time.
+ -- Fixed up etc/tune.c a bit to stop testing new cutoffs after 16 failures [to find more optimal points].
+ Brute force ho!
+
+
+May 29th, 2003
+v0.18 -- Fixed a bug in s_mp_sqr which would handle carries properly just not very elegantly.
+ (e.g. correct result, just bad looking code)
+ -- Fixed bug in mp_sqr which still had a 512 constant instead of MP_WARRAY
+ -- Added Toom-Cook multipliers [needs tuning!]
+ -- Added efficient divide by 3 algorithm mp_div_3
+ -- Re-wrote mp_div_d to be faster than calling mp_div
+ -- Added in a donated BCC makefile and a single page LTM poster (ahalhabsi@sbcglobal.net)
+ -- Added mp_reduce_2k which reduces an input modulo n = 2**p - k for any single digit k
+ -- Made the exptmod system be aware of the 2k reduction algorithms.
+ -- Rewrote mp_dr_reduce to be smaller, simpler and easier to understand.
+
+May 17th, 2003
+v0.17 -- Benjamin Goldberg submitted optimized mp_add and mp_sub routines. A new gen.pl as well
+ as several smaller suggestions. Thanks!
+ -- removed call to mp_cmp in inner loop of mp_div and put mp_cmp_mag in its place :-)
+ -- Fixed bug in mp_exptmod that would cause it to fail for odd moduli when DIGIT_BIT != 28
+ -- mp_exptmod now also returns errors if the modulus is negative and will handle negative exponents
+ -- mp_prime_is_prime will now return true if the input is one of the primes in the prime table
+ -- Damian M Gryski (dgryski@uwaterloo.ca) found a index out of bounds error in the
+ mp_fast_s_mp_mul_high_digs function which didn't come up before. (fixed)
+ -- Refactored the DR reduction code so there is only one function per file.
+ -- Fixed bug in the mp_mul() which would erroneously avoid the faster multiplier [comba] when it was
+ allowed. The bug would not cause the incorrect value to be produced just less efficient (fixed)
+ -- Fixed similar bug in the Montgomery reduction code.
+ -- Added tons of (mp_digit) casts so the 7/15/28/31 bit digit code will work flawlessly out of the box.
+ Also added limited support for 64-bit machines with a 60-bit digit. Both thanks to Tom Wu (tom@arcot.com)
+ -- Added new comments here and there, cleaned up some code [style stuff]
+ -- Fixed a lingering typo in mp_exptmod* that would set bitcnt to zero then one. Very silly stuff :-)
+ -- Fixed up mp_exptmod_fast so it would set "redux" to the comba Montgomery reduction if allowed. This
+ saves quite a few calls and if statements.
+ -- Added etc/mont.c a test of the Montgomery reduction [assuming all else works :-| ]
+ -- Fixed up etc/tune.c to use a wider test range [more appropriate] also added a x86 based addition which
+ uses RDTSC for high precision timing.
+ -- Updated demo/demo.c to remove MPI stuff [won't work anyways], made the tests run for 2 seconds each so its
+ not so insanely slow. Also made the output space delimited [and fixed up various errors]
+ -- Added logs directory, logs/graph.dem which will use gnuplot to make a series of PNG files
+ that go with the pre-made index.html. You have to build [via make timing] and run ltmtest first in the
+ root of the package.
+ -- Fixed a bug in mp_sub and mp_add where "-a - -a" or "-a + a" would produce -0 as the result [obviously invalid].
+ -- Fixed a bug in mp_rshd. If the count == a.used it should zero/return [instead of shifting]
+ -- Fixed a "off-by-one" bug in mp_mul2d. The initial size check on alloc would be off by one if the residue
+ shifting caused a carry.
+ -- Fixed a bug where s_mp_mul_digs() would not call the Comba based routine if allowed. This made Barrett reduction
+ slower than it had to be.
+
+Mar 29th, 2003
+v0.16 -- Sped up mp_div by making normalization one shift call
+ -- Sped up mp_mul_2d/mp_div_2d by aliasing pointers :-)
+ -- Cleaned up mp_gcd to use the macros for odd/even detection
+ -- Added comments here and there, mostly there but occasionally here too.
+
+Mar 22nd, 2003
+v0.15 -- Added series of prime testing routines to lib
+ -- Fixed up etc/tune.c
+ -- Added DR reduction algorithm
+ -- Beefed up the manual more.
+ -- Fixed up demo/demo.c so it doesn't have so many warnings and it does the full series of
+ tests
+ -- Added "pre-gen" directory which will hold a "gen.pl"'ed copy of the entire lib [done at
+ zipup time so its always the latest]
+ -- Added conditional casts for C++ users [boo!]
+
+Mar 15th, 2003
+v0.14 -- Tons of manual updates
+ -- cleaned up the directory
+ -- added MSVC makefiles
+ -- source changes [that I don't recall]
+ -- Fixed up the lshd/rshd code to use pointer aliasing
+ -- Fixed up the mul_2d and div_2d to not call rshd/lshd unless needed
+ -- Fixed up etc/tune.c a tad
+ -- fixed up demo/demo.c to output comma-delimited results of timing
+ also fixed up timing demo to use a finer granularity for various functions
+ -- fixed up demo/demo.c testing to pause during testing so my Duron won't catch on fire
+ [stays around 31-35C during testing :-)]
+
+Feb 13th, 2003
+v0.13 -- tons of minor speed-ups in low level add, sub, mul_2 and div_2 which propagate
+ to other functions like mp_invmod, mp_div, etc...
+ -- Sped up mp_exptmod_fast by using new code to find R mod m [e.g. B^n mod m]
+ -- minor fixes
+
+Jan 17th, 2003
+v0.12 -- re-wrote the majority of the makefile so its more portable and will
+ install via "make install" on most *nix platforms
+ -- Re-packaged all the source as seperate files. Means the library a single
+ file packagage any more. Instead of just adding "bn.c" you have to add
+ libtommath.a
+ -- Renamed "bn.h" to "tommath.h"
+ -- Changes to the manual to reflect all of this
+ -- Used GNU Indent to clean up the source
+
+Jan 15th, 2003
+v0.11 -- More subtle fixes
+ -- Moved to gentoo linux [hurrah!] so made *nix specific fixes to the make process
+ -- Sped up the montgomery reduction code quite a bit
+ -- fixed up demo so when building timing for the x86 it assumes ELF format now
+
+Jan 9th, 2003
+v0.10 -- Pekka Riikonen suggested fixes to the radix conversion code.
+ -- Added baseline montgomery and comba montgomery reductions, sped up exptmods
+ [to a point, see bn.h for MONTGOMERY_EXPT_CUTOFF]
+
+Jan 6th, 2003
+v0.09 -- Updated the manual to reflect recent changes. :-)
+ -- Added Jacobi function (mp_jacobi) to supplement the number theory side of the lib
+ -- Added a Mersenne prime finder demo in ./etc/mersenne.c
+
+Jan 2nd, 2003
+v0.08 -- Sped up the multipliers by moving the inner loop variables into a smaller scope
+ -- Corrected a bunch of small "warnings"
+ -- Added more comments
+ -- Made "mtest" be able to use /dev/random, /dev/urandom or stdin for RNG data
+ -- Corrected some bugs where error messages were potentially ignored
+ -- add etc/pprime.c program which makes numbers which are provably prime.
+
+Jan 1st, 2003
+v0.07 -- Removed alot of heap operations from core functions to speed them up
+ -- Added a root finding function [and mp_sqrt macro like from MPI]
+ -- Added more to manual
+
+Dec 31st, 2002
+v0.06 -- Sped up the s_mp_add, s_mp_sub which inturn sped up mp_invmod, mp_exptmod, etc...
+ -- Cleaned up the header a bit more
+
+Dec 30th, 2002
+v0.05 -- Builds with MSVC out of the box
+ -- Fixed a bug in mp_invmod w.r.t. even moduli
+ -- Made mp_toradix and mp_read_radix use char instead of unsigned char arrays
+ -- Fixed up exptmod to use fewer multiplications
+ -- Fixed up mp_init_size to use only one heap operation
+ -- Note there is a slight "off-by-one" bug in the library somewhere
+ without the padding (see the source for comment) the library
+ crashes in libtomcrypt. Anyways a reasonable workaround is to pad the
+ numbers which will always correct it since as the numbers grow the padding
+ will still be beyond the end of the number
+ -- Added more to the manual
+
+Dec 29th, 2002
+v0.04 -- Fixed a memory leak in mp_to_unsigned_bin
+ -- optimized invmod code
+ -- Fixed bug in mp_div
+ -- use exchange instead of copy for results
+ -- added a bit more to the manual
+
+Dec 27th, 2002
+v0.03 -- Sped up s_mp_mul_high_digs by not computing the carries of the lower digits
+ -- Fixed a bug where mp_set_int wouldn't zero the value first and set the used member.
+ -- fixed a bug in s_mp_mul_high_digs where the limit placed on the result digits was not calculated properly
+ -- fixed bugs in add/sub/mul/sqr_mod functions where if the modulus and dest were the same it wouldn't work
+ -- fixed a bug in mp_mod and mp_mod_d concerning negative inputs
+ -- mp_mul_d didn't preserve sign
+ -- Many many many many fixes
+ -- Works in LibTomCrypt now :-)
+ -- Added iterations to the timing demos... more accurate.
+ -- Tom needs a job.
+
+Dec 26th, 2002
+v0.02 -- Fixed a few "slips" in the manual. This is "LibTomMath" afterall :-)
+ -- Added mp_cmp_mag, mp_neg, mp_abs and mp_radix_size that were missing.
+ -- Sped up the fast [comba] multipliers more [yahoo!]
+
+Dec 25th,2002
+v0.01 -- Initial release. Gimme a break.
+ -- Todo list,
+ add details to manual [e.g. algorithms]
+ more comments in code
+ example programs
diff --git a/libtommath/demo/demo.c b/libtommath/demo/demo.c
new file mode 100644
index 0000000..e1f8a5e
--- /dev/null
+++ b/libtommath/demo/demo.c
@@ -0,0 +1,736 @@
+#include <time.h>
+
+#ifdef IOWNANATHLON
+#include <unistd.h>
+#define SLEEP sleep(4)
+#else
+#define SLEEP
+#endif
+
+#include "tommath.h"
+
+void ndraw(mp_int * a, char *name)
+{
+ char buf[16000];
+
+ printf("%s: ", name);
+ mp_toradix(a, buf, 10);
+ printf("%s\n", buf);
+}
+
+static void draw(mp_int * a)
+{
+ ndraw(a, "");
+}
+
+
+unsigned long lfsr = 0xAAAAAAAAUL;
+
+int lbit(void)
+{
+ if (lfsr & 0x80000000UL) {
+ lfsr = ((lfsr << 1) ^ 0x8000001BUL) & 0xFFFFFFFFUL;
+ return 1;
+ } else {
+ lfsr <<= 1;
+ return 0;
+ }
+}
+
+int myrng(unsigned char *dst, int len, void *dat)
+{
+ int x;
+
+ for (x = 0; x < len; x++)
+ dst[x] = rand() & 0xFF;
+ return len;
+}
+
+
+
+char cmd[4096], buf[4096];
+int main(void)
+{
+ mp_int a, b, c, d, e, f;
+ unsigned long expt_n, add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n,
+ gcd_n, lcm_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n, t;
+ unsigned rr;
+ int i, n, err, cnt, ix, old_kara_m, old_kara_s;
+ mp_digit mp;
+
+
+ mp_init(&a);
+ mp_init(&b);
+ mp_init(&c);
+ mp_init(&d);
+ mp_init(&e);
+ mp_init(&f);
+
+ srand(time(NULL));
+
+#if 0
+ // test montgomery
+ printf("Testing montgomery...\n");
+ for (i = 1; i < 10; i++) {
+ printf("Testing digit size: %d\n", i);
+ for (n = 0; n < 1000; n++) {
+ mp_rand(&a, i);
+ a.dp[0] |= 1;
+
+ // let's see if R is right
+ mp_montgomery_calc_normalization(&b, &a);
+ mp_montgomery_setup(&a, &mp);
+
+ // now test a random reduction
+ for (ix = 0; ix < 100; ix++) {
+ mp_rand(&c, 1 + abs(rand()) % (2*i));
+ mp_copy(&c, &d);
+ mp_copy(&c, &e);
+
+ mp_mod(&d, &a, &d);
+ mp_montgomery_reduce(&c, &a, mp);
+ mp_mulmod(&c, &b, &a, &c);
+
+ if (mp_cmp(&c, &d) != MP_EQ) {
+printf("d = e mod a, c = e MOD a\n");
+mp_todecimal(&a, buf); printf("a = %s\n", buf);
+mp_todecimal(&e, buf); printf("e = %s\n", buf);
+mp_todecimal(&d, buf); printf("d = %s\n", buf);
+mp_todecimal(&c, buf); printf("c = %s\n", buf);
+printf("compare no compare!\n"); exit(EXIT_FAILURE); }
+ }
+ }
+ }
+ printf("done\n");
+
+ // test mp_get_int
+ printf("Testing: mp_get_int\n");
+ for (i = 0; i < 1000; ++i) {
+ t = ((unsigned long) rand() * rand() + 1) & 0xFFFFFFFF;
+ mp_set_int(&a, t);
+ if (t != mp_get_int(&a)) {
+ printf("mp_get_int() bad result!\n");
+ return 1;
+ }
+ }
+ mp_set_int(&a, 0);
+ if (mp_get_int(&a) != 0) {
+ printf("mp_get_int() bad result!\n");
+ return 1;
+ }
+ mp_set_int(&a, 0xffffffff);
+ if (mp_get_int(&a) != 0xffffffff) {
+ printf("mp_get_int() bad result!\n");
+ return 1;
+ }
+ // test mp_sqrt
+ printf("Testing: mp_sqrt\n");
+ for (i = 0; i < 1000; ++i) {
+ printf("%6d\r", i);
+ fflush(stdout);
+ n = (rand() & 15) + 1;
+ mp_rand(&a, n);
+ if (mp_sqrt(&a, &b) != MP_OKAY) {
+ printf("mp_sqrt() error!\n");
+ return 1;
+ }
+ mp_n_root(&a, 2, &a);
+ if (mp_cmp_mag(&b, &a) != MP_EQ) {
+ printf("mp_sqrt() bad result!\n");
+ return 1;
+ }
+ }
+
+ printf("\nTesting: mp_is_square\n");
+ for (i = 0; i < 1000; ++i) {
+ printf("%6d\r", i);
+ fflush(stdout);
+
+ /* test mp_is_square false negatives */
+ n = (rand() & 7) + 1;
+ mp_rand(&a, n);
+ mp_sqr(&a, &a);
+ if (mp_is_square(&a, &n) != MP_OKAY) {
+ printf("fn:mp_is_square() error!\n");
+ return 1;
+ }
+ if (n == 0) {
+ printf("fn:mp_is_square() bad result!\n");
+ return 1;
+ }
+
+ /* test for false positives */
+ mp_add_d(&a, 1, &a);
+ if (mp_is_square(&a, &n) != MP_OKAY) {
+ printf("fp:mp_is_square() error!\n");
+ return 1;
+ }
+ if (n == 1) {
+ printf("fp:mp_is_square() bad result!\n");
+ return 1;
+ }
+
+ }
+ printf("\n\n");
+
+ /* test for size */
+ for (ix = 10; ix < 128; ix++) {
+ printf("Testing (not safe-prime): %9d bits \r", ix);
+ fflush(stdout);
+ err =
+ mp_prime_random_ex(&a, 8, ix,
+ (rand() & 1) ? LTM_PRIME_2MSB_OFF :
+ LTM_PRIME_2MSB_ON, myrng, NULL);
+ if (err != MP_OKAY) {
+ printf("failed with err code %d\n", err);
+ return EXIT_FAILURE;
+ }
+ if (mp_count_bits(&a) != ix) {
+ printf("Prime is %d not %d bits!!!\n", mp_count_bits(&a), ix);
+ return EXIT_FAILURE;
+ }
+ }
+
+ for (ix = 16; ix < 128; ix++) {
+ printf("Testing ( safe-prime): %9d bits \r", ix);
+ fflush(stdout);
+ err =
+ mp_prime_random_ex(&a, 8, ix,
+ ((rand() & 1) ? LTM_PRIME_2MSB_OFF :
+ LTM_PRIME_2MSB_ON) | LTM_PRIME_SAFE, myrng,
+ NULL);
+ if (err != MP_OKAY) {
+ printf("failed with err code %d\n", err);
+ return EXIT_FAILURE;
+ }
+ if (mp_count_bits(&a) != ix) {
+ printf("Prime is %d not %d bits!!!\n", mp_count_bits(&a), ix);
+ return EXIT_FAILURE;
+ }
+ /* let's see if it's really a safe prime */
+ mp_sub_d(&a, 1, &a);
+ mp_div_2(&a, &a);
+ mp_prime_is_prime(&a, 8, &cnt);
+ if (cnt != MP_YES) {
+ printf("sub is not prime!\n");
+ return EXIT_FAILURE;
+ }
+ }
+
+ printf("\n\n");
+
+ mp_read_radix(&a, "123456", 10);
+ mp_toradix_n(&a, buf, 10, 3);
+ printf("a == %s\n", buf);
+ mp_toradix_n(&a, buf, 10, 4);
+ printf("a == %s\n", buf);
+ mp_toradix_n(&a, buf, 10, 30);
+ printf("a == %s\n", buf);
+
+
+#if 0
+ for (;;) {
+ fgets(buf, sizeof(buf), stdin);
+ mp_read_radix(&a, buf, 10);
+ mp_prime_next_prime(&a, 5, 1);
+ mp_toradix(&a, buf, 10);
+ printf("%s, %lu\n", buf, a.dp[0] & 3);
+ }
+#endif
+
+ /* test mp_cnt_lsb */
+ printf("testing mp_cnt_lsb...\n");
+ mp_set(&a, 1);
+ for (ix = 0; ix < 1024; ix++) {
+ if (mp_cnt_lsb(&a) != ix) {
+ printf("Failed at %d, %d\n", ix, mp_cnt_lsb(&a));
+ return 0;
+ }
+ mp_mul_2(&a, &a);
+ }
+
+/* test mp_reduce_2k */
+ printf("Testing mp_reduce_2k...\n");
+ for (cnt = 3; cnt <= 128; ++cnt) {
+ mp_digit tmp;
+
+ mp_2expt(&a, cnt);
+ mp_sub_d(&a, 2, &a); /* a = 2**cnt - 2 */
+
+
+ printf("\nTesting %4d bits", cnt);
+ printf("(%d)", mp_reduce_is_2k(&a));
+ mp_reduce_2k_setup(&a, &tmp);
+ printf("(%d)", tmp);
+ for (ix = 0; ix < 1000; ix++) {
+ if (!(ix & 127)) {
+ printf(".");
+ fflush(stdout);
+ }
+ mp_rand(&b, (cnt / DIGIT_BIT + 1) * 2);
+ mp_copy(&c, &b);
+ mp_mod(&c, &a, &c);
+ mp_reduce_2k(&b, &a, 2);
+ if (mp_cmp(&c, &b)) {
+ printf("FAILED\n");
+ exit(0);
+ }
+ }
+ }
+
+/* test mp_div_3 */
+ printf("Testing mp_div_3...\n");
+ mp_set(&d, 3);
+ for (cnt = 0; cnt < 10000;) {
+ mp_digit r1, r2;
+
+ if (!(++cnt & 127))
+ printf("%9d\r", cnt);
+ mp_rand(&a, abs(rand()) % 128 + 1);
+ mp_div(&a, &d, &b, &e);
+ mp_div_3(&a, &c, &r2);
+
+ if (mp_cmp(&b, &c) || mp_cmp_d(&e, r2)) {
+ printf("\n\nmp_div_3 => Failure\n");
+ }
+ }
+ printf("\n\nPassed div_3 testing\n");
+
+/* test the DR reduction */
+ printf("testing mp_dr_reduce...\n");
+ for (cnt = 2; cnt < 32; cnt++) {
+ printf("%d digit modulus\n", cnt);
+ mp_grow(&a, cnt);
+ mp_zero(&a);
+ for (ix = 1; ix < cnt; ix++) {
+ a.dp[ix] = MP_MASK;
+ }
+ a.used = cnt;
+ a.dp[0] = 3;
+
+ mp_rand(&b, cnt - 1);
+ mp_copy(&b, &c);
+
+ rr = 0;
+ do {
+ if (!(rr & 127)) {
+ printf("%9lu\r", rr);
+ fflush(stdout);
+ }
+ mp_sqr(&b, &b);
+ mp_add_d(&b, 1, &b);
+ mp_copy(&b, &c);
+
+ mp_mod(&b, &a, &b);
+ mp_dr_reduce(&c, &a, (((mp_digit) 1) << DIGIT_BIT) - a.dp[0]);
+
+ if (mp_cmp(&b, &c) != MP_EQ) {
+ printf("Failed on trial %lu\n", rr);
+ exit(-1);
+
+ }
+ } while (++rr < 500);
+ printf("Passed DR test for %d digits\n", cnt);
+ }
+
+#endif
+
+/* test the mp_reduce_2k_l code */
+#if 0
+#if 0
+/* first load P with 2^1024 - 0x2A434 B9FDEC95 D8F9D550 FFFFFFFF FFFFFFFF */
+ mp_2expt(&a, 1024);
+ mp_read_radix(&b, "2A434B9FDEC95D8F9D550FFFFFFFFFFFFFFFF", 16);
+ mp_sub(&a, &b, &a);
+#elif 1
+/* p = 2^2048 - 0x1 00000000 00000000 00000000 00000000 4945DDBF 8EA2A91D 5776399B B83E188F */
+ mp_2expt(&a, 2048);
+ mp_read_radix(&b,
+ "1000000000000000000000000000000004945DDBF8EA2A91D5776399BB83E188F",
+ 16);
+ mp_sub(&a, &b, &a);
+#endif
+
+ mp_todecimal(&a, buf);
+ printf("p==%s\n", buf);
+/* now mp_reduce_is_2k_l() should return */
+ if (mp_reduce_is_2k_l(&a) != 1) {
+ printf("mp_reduce_is_2k_l() return 0, should be 1\n");
+ return EXIT_FAILURE;
+ }
+ mp_reduce_2k_setup_l(&a, &d);
+ /* now do a million square+1 to see if it varies */
+ mp_rand(&b, 64);
+ mp_mod(&b, &a, &b);
+ mp_copy(&b, &c);
+ printf("testing mp_reduce_2k_l...");
+ fflush(stdout);
+ for (cnt = 0; cnt < (1UL << 20); cnt++) {
+ mp_sqr(&b, &b);
+ mp_add_d(&b, 1, &b);
+ mp_reduce_2k_l(&b, &a, &d);
+ mp_sqr(&c, &c);
+ mp_add_d(&c, 1, &c);
+ mp_mod(&c, &a, &c);
+ if (mp_cmp(&b, &c) != MP_EQ) {
+ printf("mp_reduce_2k_l() failed at step %lu\n", cnt);
+ mp_tohex(&b, buf);
+ printf("b == %s\n", buf);
+ mp_tohex(&c, buf);
+ printf("c == %s\n", buf);
+ return EXIT_FAILURE;
+ }
+ }
+ printf("...Passed\n");
+#endif
+
+ div2_n = mul2_n = inv_n = expt_n = lcm_n = gcd_n = add_n =
+ sub_n = mul_n = div_n = sqr_n = mul2d_n = div2d_n = cnt = add_d_n =
+ sub_d_n = 0;
+
+ /* force KARA and TOOM to enable despite cutoffs */
+ KARATSUBA_SQR_CUTOFF = KARATSUBA_MUL_CUTOFF = 8;
+ TOOM_SQR_CUTOFF = TOOM_MUL_CUTOFF = 16;
+
+ for (;;) {
+ /* randomly clear and re-init one variable, this has the affect of triming the alloc space */
+ switch (abs(rand()) % 7) {
+ case 0:
+ mp_clear(&a);
+ mp_init(&a);
+ break;
+ case 1:
+ mp_clear(&b);
+ mp_init(&b);
+ break;
+ case 2:
+ mp_clear(&c);
+ mp_init(&c);
+ break;
+ case 3:
+ mp_clear(&d);
+ mp_init(&d);
+ break;
+ case 4:
+ mp_clear(&e);
+ mp_init(&e);
+ break;
+ case 5:
+ mp_clear(&f);
+ mp_init(&f);
+ break;
+ case 6:
+ break; /* don't clear any */
+ }
+
+
+ printf
+ ("%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu ",
+ add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n, gcd_n, lcm_n,
+ expt_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n);
+ fgets(cmd, 4095, stdin);
+ cmd[strlen(cmd) - 1] = 0;
+ printf("%s ]\r", cmd);
+ fflush(stdout);
+ if (!strcmp(cmd, "mul2d")) {
+ ++mul2d_n;
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&a, buf, 64);
+ fgets(buf, 4095, stdin);
+ sscanf(buf, "%d", &rr);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&b, buf, 64);
+
+ mp_mul_2d(&a, rr, &a);
+ a.sign = b.sign;
+ if (mp_cmp(&a, &b) != MP_EQ) {
+ printf("mul2d failed, rr == %d\n", rr);
+ draw(&a);
+ draw(&b);
+ return 0;
+ }
+ } else if (!strcmp(cmd, "div2d")) {
+ ++div2d_n;
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&a, buf, 64);
+ fgets(buf, 4095, stdin);
+ sscanf(buf, "%d", &rr);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&b, buf, 64);
+
+ mp_div_2d(&a, rr, &a, &e);
+ a.sign = b.sign;
+ if (a.used == b.used && a.used == 0) {
+ a.sign = b.sign = MP_ZPOS;
+ }
+ if (mp_cmp(&a, &b) != MP_EQ) {
+ printf("div2d failed, rr == %d\n", rr);
+ draw(&a);
+ draw(&b);
+ return 0;
+ }
+ } else if (!strcmp(cmd, "add")) {
+ ++add_n;
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&a, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&b, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&c, buf, 64);
+ mp_copy(&a, &d);
+ mp_add(&d, &b, &d);
+ if (mp_cmp(&c, &d) != MP_EQ) {
+ printf("add %lu failure!\n", add_n);
+ draw(&a);
+ draw(&b);
+ draw(&c);
+ draw(&d);
+ return 0;
+ }
+
+ /* test the sign/unsigned storage functions */
+
+ rr = mp_signed_bin_size(&c);
+ mp_to_signed_bin(&c, (unsigned char *) cmd);
+ memset(cmd + rr, rand() & 255, sizeof(cmd) - rr);
+ mp_read_signed_bin(&d, (unsigned char *) cmd, rr);
+ if (mp_cmp(&c, &d) != MP_EQ) {
+ printf("mp_signed_bin failure!\n");
+ draw(&c);
+ draw(&d);
+ return 0;
+ }
+
+
+ rr = mp_unsigned_bin_size(&c);
+ mp_to_unsigned_bin(&c, (unsigned char *) cmd);
+ memset(cmd + rr, rand() & 255, sizeof(cmd) - rr);
+ mp_read_unsigned_bin(&d, (unsigned char *) cmd, rr);
+ if (mp_cmp_mag(&c, &d) != MP_EQ) {
+ printf("mp_unsigned_bin failure!\n");
+ draw(&c);
+ draw(&d);
+ return 0;
+ }
+
+ } else if (!strcmp(cmd, "sub")) {
+ ++sub_n;
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&a, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&b, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&c, buf, 64);
+ mp_copy(&a, &d);
+ mp_sub(&d, &b, &d);
+ if (mp_cmp(&c, &d) != MP_EQ) {
+ printf("sub %lu failure!\n", sub_n);
+ draw(&a);
+ draw(&b);
+ draw(&c);
+ draw(&d);
+ return 0;
+ }
+ } else if (!strcmp(cmd, "mul")) {
+ ++mul_n;
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&a, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&b, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&c, buf, 64);
+ mp_copy(&a, &d);
+ mp_mul(&d, &b, &d);
+ if (mp_cmp(&c, &d) != MP_EQ) {
+ printf("mul %lu failure!\n", mul_n);
+ draw(&a);
+ draw(&b);
+ draw(&c);
+ draw(&d);
+ return 0;
+ }
+ } else if (!strcmp(cmd, "div")) {
+ ++div_n;
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&a, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&b, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&c, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&d, buf, 64);
+
+ mp_div(&a, &b, &e, &f);
+ if (mp_cmp(&c, &e) != MP_EQ || mp_cmp(&d, &f) != MP_EQ) {
+ printf("div %lu %d, %d, failure!\n", div_n, mp_cmp(&c, &e),
+ mp_cmp(&d, &f));
+ draw(&a);
+ draw(&b);
+ draw(&c);
+ draw(&d);
+ draw(&e);
+ draw(&f);
+ return 0;
+ }
+
+ } else if (!strcmp(cmd, "sqr")) {
+ ++sqr_n;
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&a, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&b, buf, 64);
+ mp_copy(&a, &c);
+ mp_sqr(&c, &c);
+ if (mp_cmp(&b, &c) != MP_EQ) {
+ printf("sqr %lu failure!\n", sqr_n);
+ draw(&a);
+ draw(&b);
+ draw(&c);
+ return 0;
+ }
+ } else if (!strcmp(cmd, "gcd")) {
+ ++gcd_n;
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&a, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&b, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&c, buf, 64);
+ mp_copy(&a, &d);
+ mp_gcd(&d, &b, &d);
+ d.sign = c.sign;
+ if (mp_cmp(&c, &d) != MP_EQ) {
+ printf("gcd %lu failure!\n", gcd_n);
+ draw(&a);
+ draw(&b);
+ draw(&c);
+ draw(&d);
+ return 0;
+ }
+ } else if (!strcmp(cmd, "lcm")) {
+ ++lcm_n;
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&a, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&b, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&c, buf, 64);
+ mp_copy(&a, &d);
+ mp_lcm(&d, &b, &d);
+ d.sign = c.sign;
+ if (mp_cmp(&c, &d) != MP_EQ) {
+ printf("lcm %lu failure!\n", lcm_n);
+ draw(&a);
+ draw(&b);
+ draw(&c);
+ draw(&d);
+ return 0;
+ }
+ } else if (!strcmp(cmd, "expt")) {
+ ++expt_n;
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&a, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&b, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&c, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&d, buf, 64);
+ mp_copy(&a, &e);
+ mp_exptmod(&e, &b, &c, &e);
+ if (mp_cmp(&d, &e) != MP_EQ) {
+ printf("expt %lu failure!\n", expt_n);
+ draw(&a);
+ draw(&b);
+ draw(&c);
+ draw(&d);
+ draw(&e);
+ return 0;
+ }
+ } else if (!strcmp(cmd, "invmod")) {
+ ++inv_n;
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&a, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&b, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&c, buf, 64);
+ mp_invmod(&a, &b, &d);
+ mp_mulmod(&d, &a, &b, &e);
+ if (mp_cmp_d(&e, 1) != MP_EQ) {
+ printf("inv [wrong value from MPI?!] failure\n");
+ draw(&a);
+ draw(&b);
+ draw(&c);
+ draw(&d);
+ mp_gcd(&a, &b, &e);
+ draw(&e);
+ return 0;
+ }
+
+ } else if (!strcmp(cmd, "div2")) {
+ ++div2_n;
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&a, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&b, buf, 64);
+ mp_div_2(&a, &c);
+ if (mp_cmp(&c, &b) != MP_EQ) {
+ printf("div_2 %lu failure\n", div2_n);
+ draw(&a);
+ draw(&b);
+ draw(&c);
+ return 0;
+ }
+ } else if (!strcmp(cmd, "mul2")) {
+ ++mul2_n;
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&a, buf, 64);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&b, buf, 64);
+ mp_mul_2(&a, &c);
+ if (mp_cmp(&c, &b) != MP_EQ) {
+ printf("mul_2 %lu failure\n", mul2_n);
+ draw(&a);
+ draw(&b);
+ draw(&c);
+ return 0;
+ }
+ } else if (!strcmp(cmd, "add_d")) {
+ ++add_d_n;
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&a, buf, 64);
+ fgets(buf, 4095, stdin);
+ sscanf(buf, "%d", &ix);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&b, buf, 64);
+ mp_add_d(&a, ix, &c);
+ if (mp_cmp(&b, &c) != MP_EQ) {
+ printf("add_d %lu failure\n", add_d_n);
+ draw(&a);
+ draw(&b);
+ draw(&c);
+ printf("d == %d\n", ix);
+ return 0;
+ }
+ } else if (!strcmp(cmd, "sub_d")) {
+ ++sub_d_n;
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&a, buf, 64);
+ fgets(buf, 4095, stdin);
+ sscanf(buf, "%d", &ix);
+ fgets(buf, 4095, stdin);
+ mp_read_radix(&b, buf, 64);
+ mp_sub_d(&a, ix, &c);
+ if (mp_cmp(&b, &c) != MP_EQ) {
+ printf("sub_d %lu failure\n", sub_d_n);
+ draw(&a);
+ draw(&b);
+ draw(&c);
+ printf("d == %d\n", ix);
+ return 0;
+ }
+ }
+ }
+ return 0;
+}
diff --git a/libtommath/demo/timing.c b/libtommath/demo/timing.c
new file mode 100644
index 0000000..bb3be52
--- /dev/null
+++ b/libtommath/demo/timing.c
@@ -0,0 +1,315 @@
+#include <tommath.h>
+#include <time.h>
+
+ulong64 _tt;
+
+#ifdef IOWNANATHLON
+#include <unistd.h>
+#define SLEEP sleep(4)
+#else
+#define SLEEP
+#endif
+
+
+void ndraw(mp_int * a, char *name)
+{
+ char buf[4096];
+
+ printf("%s: ", name);
+ mp_toradix(a, buf, 64);
+ printf("%s\n", buf);
+}
+
+static void draw(mp_int * a)
+{
+ ndraw(a, "");
+}
+
+
+unsigned long lfsr = 0xAAAAAAAAUL;
+
+int lbit(void)
+{
+ if (lfsr & 0x80000000UL) {
+ lfsr = ((lfsr << 1) ^ 0x8000001BUL) & 0xFFFFFFFFUL;
+ return 1;
+ } else {
+ lfsr <<= 1;
+ return 0;
+ }
+}
+
+/* RDTSC from Scott Duplichan */
+static ulong64 TIMFUNC(void)
+{
+#if defined __GNUC__
+#if defined(__i386__) || defined(__x86_64__)
+ unsigned long long a;
+ __asm__ __volatile__("rdtsc\nmovl %%eax,%0\nmovl %%edx,4+%0\n"::
+ "m"(a):"%eax", "%edx");
+ return a;
+#else /* gcc-IA64 version */
+ unsigned long result;
+ __asm__ __volatile__("mov %0=ar.itc":"=r"(result)::"memory");
+
+ while (__builtin_expect((int) result == -1, 0))
+ __asm__ __volatile__("mov %0=ar.itc":"=r"(result)::"memory");
+
+ return result;
+#endif
+
+ // Microsoft and Intel Windows compilers
+#elif defined _M_IX86
+ __asm rdtsc
+#elif defined _M_AMD64
+ return __rdtsc();
+#elif defined _M_IA64
+#if defined __INTEL_COMPILER
+#include <ia64intrin.h>
+#endif
+ return __getReg(3116);
+#else
+#error need rdtsc function for this build
+#endif
+}
+
+#define DO(x) x; x;
+//#define DO4(x) DO2(x); DO2(x);
+//#define DO8(x) DO4(x); DO4(x);
+//#define DO(x) DO8(x); DO8(x);
+
+int main(void)
+{
+ ulong64 tt, gg, CLK_PER_SEC;
+ FILE *log, *logb, *logc, *logd;
+ mp_int a, b, c, d, e, f;
+ int n, cnt, ix, old_kara_m, old_kara_s;
+ unsigned rr;
+
+ mp_init(&a);
+ mp_init(&b);
+ mp_init(&c);
+ mp_init(&d);
+ mp_init(&e);
+ mp_init(&f);
+
+ srand(time(NULL));
+
+
+ /* temp. turn off TOOM */
+ TOOM_MUL_CUTOFF = TOOM_SQR_CUTOFF = 100000;
+
+ CLK_PER_SEC = TIMFUNC();
+ sleep(1);
+ CLK_PER_SEC = TIMFUNC() - CLK_PER_SEC;
+
+ printf("CLK_PER_SEC == %llu\n", CLK_PER_SEC);
+ goto exptmod;
+ log = fopen("logs/add.log", "w");
+ for (cnt = 8; cnt <= 128; cnt += 8) {
+ SLEEP;
+ mp_rand(&a, cnt);
+ mp_rand(&b, cnt);
+ rr = 0;
+ tt = -1;
+ do {
+ gg = TIMFUNC();
+ DO(mp_add(&a, &b, &c));
+ gg = (TIMFUNC() - gg) >> 1;
+ if (tt > gg)
+ tt = gg;
+ } while (++rr < 100000);
+ printf("Adding\t\t%4d-bit => %9llu/sec, %9llu cycles\n",
+ mp_count_bits(&a), CLK_PER_SEC / tt, tt);
+ fprintf(log, "%d %9llu\n", cnt * DIGIT_BIT, tt);
+ fflush(log);
+ }
+ fclose(log);
+
+ log = fopen("logs/sub.log", "w");
+ for (cnt = 8; cnt <= 128; cnt += 8) {
+ SLEEP;
+ mp_rand(&a, cnt);
+ mp_rand(&b, cnt);
+ rr = 0;
+ tt = -1;
+ do {
+ gg = TIMFUNC();
+ DO(mp_sub(&a, &b, &c));
+ gg = (TIMFUNC() - gg) >> 1;
+ if (tt > gg)
+ tt = gg;
+ } while (++rr < 100000);
+
+ printf("Subtracting\t\t%4d-bit => %9llu/sec, %9llu cycles\n",
+ mp_count_bits(&a), CLK_PER_SEC / tt, tt);
+ fprintf(log, "%d %9llu\n", cnt * DIGIT_BIT, tt);
+ fflush(log);
+ }
+ fclose(log);
+
+ /* do mult/square twice, first without karatsuba and second with */
+ multtest:
+ old_kara_m = KARATSUBA_MUL_CUTOFF;
+ old_kara_s = KARATSUBA_SQR_CUTOFF;
+ for (ix = 0; ix < 2; ix++) {
+ printf("With%s Karatsuba\n", (ix == 0) ? "out" : "");
+
+ KARATSUBA_MUL_CUTOFF = (ix == 0) ? 9999 : old_kara_m;
+ KARATSUBA_SQR_CUTOFF = (ix == 0) ? 9999 : old_kara_s;
+
+ log = fopen((ix == 0) ? "logs/mult.log" : "logs/mult_kara.log", "w");
+ for (cnt = 4; cnt <= 10240 / DIGIT_BIT; cnt += 2) {
+ SLEEP;
+ mp_rand(&a, cnt);
+ mp_rand(&b, cnt);
+ rr = 0;
+ tt = -1;
+ do {
+ gg = TIMFUNC();
+ DO(mp_mul(&a, &b, &c));
+ gg = (TIMFUNC() - gg) >> 1;
+ if (tt > gg)
+ tt = gg;
+ } while (++rr < 100);
+ printf("Multiplying\t%4d-bit => %9llu/sec, %9llu cycles\n",
+ mp_count_bits(&a), CLK_PER_SEC / tt, tt);
+ fprintf(log, "%d %9llu\n", mp_count_bits(&a), tt);
+ fflush(log);
+ }
+ fclose(log);
+
+ log = fopen((ix == 0) ? "logs/sqr.log" : "logs/sqr_kara.log", "w");
+ for (cnt = 4; cnt <= 10240 / DIGIT_BIT; cnt += 2) {
+ SLEEP;
+ mp_rand(&a, cnt);
+ rr = 0;
+ tt = -1;
+ do {
+ gg = TIMFUNC();
+ DO(mp_sqr(&a, &b));
+ gg = (TIMFUNC() - gg) >> 1;
+ if (tt > gg)
+ tt = gg;
+ } while (++rr < 100);
+ printf("Squaring\t%4d-bit => %9llu/sec, %9llu cycles\n",
+ mp_count_bits(&a), CLK_PER_SEC / tt, tt);
+ fprintf(log, "%d %9llu\n", mp_count_bits(&a), tt);
+ fflush(log);
+ }
+ fclose(log);
+
+ }
+ exptmod:
+
+ {
+ char *primes[] = {
+ /* 2K large moduli */
+ "179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586239334100047359817950870678242457666208137217",
+ "32317006071311007300714876688669951960444102669715484032130345427524655138867890893197201411522913463688717960921898019494119559150490921095088152386448283120630877367300996091750197750389652106796057638384067568276792218642619756161838094338476170470581645852036305042887575891541065808607552399123930385521914333389668342420684974786564569494856176035326322058077805659331026192708460314150258592864177116725943603718461857357598351152301645904403697613233287231227125684710820209725157101726931323469678542580656697935045997268352998638099733077152121140120031150424541696791951097529546801429027668869927491725169",
+ "1044388881413152506691752710716624382579964249047383780384233483283953907971557456848826811934997558340890106714439262837987573438185793607263236087851365277945956976543709998340361590134383718314428070011855946226376318839397712745672334684344586617496807908705803704071284048740118609114467977783598029006686938976881787785946905630190260940599579453432823469303026696443059025015972399867714215541693835559885291486318237914434496734087811872639496475100189041349008417061675093668333850551032972088269550769983616369411933015213796825837188091833656751221318492846368125550225998300412344784862595674492194617023806505913245610825731835380087608622102834270197698202313169017678006675195485079921636419370285375124784014907159135459982790513399611551794271106831134090584272884279791554849782954323534517065223269061394905987693002122963395687782878948440616007412945674919823050571642377154816321380631045902916136926708342856440730447899971901781465763473223850267253059899795996090799469201774624817718449867455659250178329070473119433165550807568221846571746373296884912819520317457002440926616910874148385078411929804522981857338977648103126085902995208257421855249796721729039744118165938433694823325696642096892124547425283",
+ /* 2K moduli mersenne primes */
+ "6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151",
+ "531137992816767098689588206552468627329593117727031923199444138200403559860852242739162502265229285668889329486246501015346579337652707239409519978766587351943831270835393219031728127",
+ "10407932194664399081925240327364085538615262247266704805319112350403608059673360298012239441732324184842421613954281007791383566248323464908139906605677320762924129509389220345773183349661583550472959420547689811211693677147548478866962501384438260291732348885311160828538416585028255604666224831890918801847068222203140521026698435488732958028878050869736186900714720710555703168729087",
+ "1475979915214180235084898622737381736312066145333169775147771216478570297878078949377407337049389289382748507531496480477281264838760259191814463365330269540496961201113430156902396093989090226259326935025281409614983499388222831448598601834318536230923772641390209490231836446899608210795482963763094236630945410832793769905399982457186322944729636418890623372171723742105636440368218459649632948538696905872650486914434637457507280441823676813517852099348660847172579408422316678097670224011990280170474894487426924742108823536808485072502240519452587542875349976558572670229633962575212637477897785501552646522609988869914013540483809865681250419497686697771007",
+ "259117086013202627776246767922441530941818887553125427303974923161874019266586362086201209516800483406550695241733194177441689509238807017410377709597512042313066624082916353517952311186154862265604547691127595848775610568757931191017711408826252153849035830401185072116424747461823031471398340229288074545677907941037288235820705892351068433882986888616658650280927692080339605869308790500409503709875902119018371991620994002568935113136548829739112656797303241986517250116412703509705427773477972349821676443446668383119322540099648994051790241624056519054483690809616061625743042361721863339415852426431208737266591962061753535748892894599629195183082621860853400937932839420261866586142503251450773096274235376822938649407127700846077124211823080804139298087057504713825264571448379371125032081826126566649084251699453951887789613650248405739378594599444335231188280123660406262468609212150349937584782292237144339628858485938215738821232393687046160677362909315071",
+ "190797007524439073807468042969529173669356994749940177394741882673528979787005053706368049835514900244303495954950709725762186311224148828811920216904542206960744666169364221195289538436845390250168663932838805192055137154390912666527533007309292687539092257043362517857366624699975402375462954490293259233303137330643531556539739921926201438606439020075174723029056838272505051571967594608350063404495977660656269020823960825567012344189908927956646011998057988548630107637380993519826582389781888135705408653045219655801758081251164080554609057468028203308718724654081055323215860189611391296030471108443146745671967766308925858547271507311563765171008318248647110097614890313562856541784154881743146033909602737947385055355960331855614540900081456378659068370317267696980001187750995491090350108417050917991562167972281070161305972518044872048331306383715094854938415738549894606070722584737978176686422134354526989443028353644037187375385397838259511833166416134323695660367676897722287918773420968982326089026150031515424165462111337527431154890666327374921446276833564519776797633875503548665093914556482031482248883127023777039667707976559857333357013727342079099064400455741830654320379350833236245819348824064783585692924881021978332974949906122664421376034687815350484991",
+
+ /* DR moduli */
+ "14059105607947488696282932836518693308967803494693489478439861164411992439598399594747002144074658928593502845729752797260025831423419686528151609940203368612079",
+ "101745825697019260773923519755878567461315282017759829107608914364075275235254395622580447400994175578963163918967182013639660669771108475957692810857098847138903161308502419410142185759152435680068435915159402496058513611411688900243039",
+ "736335108039604595805923406147184530889923370574768772191969612422073040099331944991573923112581267542507986451953227192970402893063850485730703075899286013451337291468249027691733891486704001513279827771740183629161065194874727962517148100775228363421083691764065477590823919364012917984605619526140821797602431",
+ "38564998830736521417281865696453025806593491967131023221754800625044118265468851210705360385717536794615180260494208076605798671660719333199513807806252394423283413430106003596332513246682903994829528690198205120921557533726473585751382193953592127439965050261476810842071573684505878854588706623484573925925903505747545471088867712185004135201289273405614415899438276535626346098904241020877974002916168099951885406379295536200413493190419727789712076165162175783",
+ "542189391331696172661670440619180536749994166415993334151601745392193484590296600979602378676624808129613777993466242203025054573692562689251250471628358318743978285860720148446448885701001277560572526947619392551574490839286458454994488665744991822837769918095117129546414124448777033941223565831420390846864429504774477949153794689948747680362212954278693335653935890352619041936727463717926744868338358149568368643403037768649616778526013610493696186055899318268339432671541328195724261329606699831016666359440874843103020666106568222401047720269951530296879490444224546654729111504346660859907296364097126834834235287147",
+ "1487259134814709264092032648525971038895865645148901180585340454985524155135260217788758027400478312256339496385275012465661575576202252063145698732079880294664220579764848767704076761853197216563262660046602703973050798218246170835962005598561669706844469447435461092542265792444947706769615695252256130901271870341005768912974433684521436211263358097522726462083917939091760026658925757076733484173202927141441492573799914240222628795405623953109131594523623353044898339481494120112723445689647986475279242446083151413667587008191682564376412347964146113898565886683139407005941383669325997475076910488086663256335689181157957571445067490187939553165903773554290260531009121879044170766615232300936675369451260747671432073394867530820527479172464106442450727640226503746586340279816318821395210726268291535648506190714616083163403189943334431056876038286530365757187367147446004855912033137386225053275419626102417236133948503",
+ "1095121115716677802856811290392395128588168592409109494900178008967955253005183831872715423151551999734857184538199864469605657805519106717529655044054833197687459782636297255219742994736751541815269727940751860670268774903340296040006114013971309257028332849679096824800250742691718610670812374272414086863715763724622797509437062518082383056050144624962776302147890521249477060215148275163688301275847155316042279405557632639366066847442861422164832655874655824221577849928863023018366835675399949740429332468186340518172487073360822220449055340582568461568645259954873303616953776393853174845132081121976327462740354930744487429617202585015510744298530101547706821590188733515880733527449780963163909830077616357506845523215289297624086914545378511082534229620116563260168494523906566709418166011112754529766183554579321224940951177394088465596712620076240067370589036924024728375076210477267488679008016579588696191194060127319035195370137160936882402244399699172017835144537488486396906144217720028992863941288217185353914991583400421682751000603596655790990815525126154394344641336397793791497068253936771017031980867706707490224041075826337383538651825493679503771934836094655802776331664261631740148281763487765852746577808019633679",
+
+ /* generic unrestricted moduli */
+ "17933601194860113372237070562165128350027320072176844226673287945873370751245439587792371960615073855669274087805055507977323024886880985062002853331424203",
+ "2893527720709661239493896562339544088620375736490408468011883030469939904368086092336458298221245707898933583190713188177399401852627749210994595974791782790253946539043962213027074922559572312141181787434278708783207966459019479487",
+ "347743159439876626079252796797422223177535447388206607607181663903045907591201940478223621722118173270898487582987137708656414344685816179420855160986340457973820182883508387588163122354089264395604796675278966117567294812714812796820596564876450716066283126720010859041484786529056457896367683122960411136319",
+ "47266428956356393164697365098120418976400602706072312735924071745438532218237979333351774907308168340693326687317443721193266215155735814510792148768576498491199122744351399489453533553203833318691678263241941706256996197460424029012419012634671862283532342656309677173602509498417976091509154360039893165037637034737020327399910409885798185771003505320583967737293415979917317338985837385734747478364242020380416892056650841470869294527543597349250299539682430605173321029026555546832473048600327036845781970289288898317888427517364945316709081173840186150794397479045034008257793436817683392375274635794835245695887",
+ "436463808505957768574894870394349739623346440601945961161254440072143298152040105676491048248110146278752857839930515766167441407021501229924721335644557342265864606569000117714935185566842453630868849121480179691838399545644365571106757731317371758557990781880691336695584799313313687287468894148823761785582982549586183756806449017542622267874275103877481475534991201849912222670102069951687572917937634467778042874315463238062009202992087620963771759666448266532858079402669920025224220613419441069718482837399612644978839925207109870840278194042158748845445131729137117098529028886770063736487420613144045836803985635654192482395882603511950547826439092832800532152534003936926017612446606135655146445620623395788978726744728503058670046885876251527122350275750995227",
+ "11424167473351836398078306042624362277956429440521137061889702611766348760692206243140413411077394583180726863277012016602279290144126785129569474909173584789822341986742719230331946072730319555984484911716797058875905400999504305877245849119687509023232790273637466821052576859232452982061831009770786031785669030271542286603956118755585683996118896215213488875253101894663403069677745948305893849505434201763745232895780711972432011344857521691017896316861403206449421332243658855453435784006517202894181640562433575390821384210960117518650374602256601091379644034244332285065935413233557998331562749140202965844219336298970011513882564935538704289446968322281451907487362046511461221329799897350993370560697505809686438782036235372137015731304779072430260986460269894522159103008260495503005267165927542949439526272736586626709581721032189532726389643625590680105784844246152702670169304203783072275089194754889511973916207",
+ "1214855636816562637502584060163403830270705000634713483015101384881871978446801224798536155406895823305035467591632531067547890948695117172076954220727075688048751022421198712032848890056357845974246560748347918630050853933697792254955890439720297560693579400297062396904306270145886830719309296352765295712183040773146419022875165382778007040109957609739589875590885701126197906063620133954893216612678838507540777138437797705602453719559017633986486649523611975865005712371194067612263330335590526176087004421363598470302731349138773205901447704682181517904064735636518462452242791676541725292378925568296858010151852326316777511935037531017413910506921922450666933202278489024521263798482237150056835746454842662048692127173834433089016107854491097456725016327709663199738238442164843147132789153725513257167915555162094970853584447993125488607696008169807374736711297007473812256272245489405898470297178738029484459690836250560495461579533254473316340608217876781986188705928270735695752830825527963838355419762516246028680280988020401914551825487349990306976304093109384451438813251211051597392127491464898797406789175453067960072008590614886532333015881171367104445044718144312416815712216611576221546455968770801413440778423979",
+ NULL
+ };
+ log = fopen("logs/expt.log", "w");
+ logb = fopen("logs/expt_dr.log", "w");
+ logc = fopen("logs/expt_2k.log", "w");
+ logd = fopen("logs/expt_2kl.log", "w");
+ for (n = 0; primes[n]; n++) {
+ SLEEP;
+ mp_read_radix(&a, primes[n], 10);
+ mp_zero(&b);
+ for (rr = 0; rr < (unsigned) mp_count_bits(&a); rr++) {
+ mp_mul_2(&b, &b);
+ b.dp[0] |= lbit();
+ b.used += 1;
+ }
+ mp_sub_d(&a, 1, &c);
+ mp_mod(&b, &c, &b);
+ mp_set(&c, 3);
+ rr = 0;
+ tt = -1;
+ do {
+ gg = TIMFUNC();
+ DO(mp_exptmod(&c, &b, &a, &d));
+ gg = (TIMFUNC() - gg) >> 1;
+ if (tt > gg)
+ tt = gg;
+ } while (++rr < 10);
+ mp_sub_d(&a, 1, &e);
+ mp_sub(&e, &b, &b);
+ mp_exptmod(&c, &b, &a, &e); /* c^(p-1-b) mod a */
+ mp_mulmod(&e, &d, &a, &d); /* c^b * c^(p-1-b) == c^p-1 == 1 */
+ if (mp_cmp_d(&d, 1)) {
+ printf("Different (%d)!!!\n", mp_count_bits(&a));
+ draw(&d);
+ exit(0);
+ }
+ printf("Exponentiating\t%4d-bit => %9llu/sec, %9llu cycles\n",
+ mp_count_bits(&a), CLK_PER_SEC / tt, tt);
+ fprintf(n < 4 ? logd : (n < 9) ? logc : (n < 16) ? logb : log,
+ "%d %9llu\n", mp_count_bits(&a), tt);
+ }
+ }
+ fclose(log);
+ fclose(logb);
+ fclose(logc);
+ fclose(logd);
+
+ log = fopen("logs/invmod.log", "w");
+ for (cnt = 4; cnt <= 128; cnt += 4) {
+ SLEEP;
+ mp_rand(&a, cnt);
+ mp_rand(&b, cnt);
+
+ do {
+ mp_add_d(&b, 1, &b);
+ mp_gcd(&a, &b, &c);
+ } while (mp_cmp_d(&c, 1) != MP_EQ);
+
+ rr = 0;
+ tt = -1;
+ do {
+ gg = TIMFUNC();
+ DO(mp_invmod(&b, &a, &c));
+ gg = (TIMFUNC() - gg) >> 1;
+ if (tt > gg)
+ tt = gg;
+ } while (++rr < 1000);
+ mp_mulmod(&b, &c, &a, &d);
+ if (mp_cmp_d(&d, 1) != MP_EQ) {
+ printf("Failed to invert\n");
+ return 0;
+ }
+ printf("Inverting mod\t%4d-bit => %9llu/sec, %9llu cycles\n",
+ mp_count_bits(&a), CLK_PER_SEC / tt, tt);
+ fprintf(log, "%d %9llu\n", cnt * DIGIT_BIT, tt);
+ }
+ fclose(log);
+
+ return 0;
+}
diff --git a/libtommath/dep.pl b/libtommath/dep.pl
new file mode 100644
index 0000000..c39e27e
--- /dev/null
+++ b/libtommath/dep.pl
@@ -0,0 +1,123 @@
+#!/usr/bin/perl
+#
+# Walk through source, add labels and make classes
+#
+#use strict;
+
+my %deplist;
+
+#open class file and write preamble
+open(CLASS, ">tommath_class.h") or die "Couldn't open tommath_class.h for writing\n";
+print CLASS "#if !(defined(LTM1) && defined(LTM2) && defined(LTM3))\n#if defined(LTM2)\n#define LTM3\n#endif\n#if defined(LTM1)\n#define LTM2\n#endif\n#define LTM1\n\n#if defined(LTM_ALL)\n";
+
+foreach my $filename (glob "bn*.c") {
+ my $define = $filename;
+
+print "Processing $filename\n";
+
+ # convert filename to upper case so we can use it as a define
+ $define =~ tr/[a-z]/[A-Z]/;
+ $define =~ tr/\./_/;
+ print CLASS "#define $define\n";
+
+ # now copy text and apply #ifdef as required
+ my $apply = 0;
+ open(SRC, "<$filename");
+ open(OUT, ">tmp");
+
+ # first line will be the #ifdef
+ my $line = <SRC>;
+ if ($line =~ /include/) {
+ print OUT $line;
+ } else {
+ print OUT "#include <tommath.h>\n#ifdef $define\n$line";
+ $apply = 1;
+ }
+ while (<SRC>) {
+ if (!($_ =~ /tommath\.h/)) {
+ print OUT $_;
+ }
+ }
+ if ($apply == 1) {
+ print OUT "#endif\n";
+ }
+ close SRC;
+ close OUT;
+
+ unlink($filename);
+ rename("tmp", $filename);
+}
+print CLASS "#endif\n\n";
+
+# now do classes
+
+foreach my $filename (glob "bn*.c") {
+ open(SRC, "<$filename") or die "Can't open source file!\n";
+
+ # convert filename to upper case so we can use it as a define
+ $filename =~ tr/[a-z]/[A-Z]/;
+ $filename =~ tr/\./_/;
+
+ print CLASS "#if defined($filename)\n";
+ my $list = $filename;
+
+ # scan for mp_* and make classes
+ while (<SRC>) {
+ my $line = $_;
+ while ($line =~ m/(fast_)*(s_)*mp\_[a-z_0-9]*/) {
+ $line = $';
+ # now $& is the match, we want to skip over LTM keywords like
+ # mp_int, mp_word, mp_digit
+ if (!($& eq "mp_digit") && !($& eq "mp_word") && !($& eq "mp_int")) {
+ my $a = $&;
+ $a =~ tr/[a-z]/[A-Z]/;
+ $a = "BN_" . $a . "_C";
+ if (!($list =~ /$a/)) {
+ print CLASS " #define $a\n";
+ }
+ $list = $list . "," . $a;
+ }
+ }
+ }
+ @deplist{$filename} = $list;
+
+ print CLASS "#endif\n\n";
+ close SRC;
+}
+
+print CLASS "#ifdef LTM3\n#define LTM_LAST\n#endif\n#include <tommath_superclass.h>\n#include <tommath_class.h>\n#else\n#define LTM_LAST\n#endif\n";
+close CLASS;
+
+#now let's make a cool call graph...
+
+open(OUT,">callgraph.txt");
+$indent = 0;
+foreach (keys %deplist) {
+ $list = "";
+ draw_func(@deplist{$_});
+ print OUT "\n\n";
+}
+close(OUT);
+
+sub draw_func()
+{
+ my @funcs = split(",", $_[0]);
+ if ($list =~ /@funcs[0]/) {
+ return;
+ } else {
+ $list = $list . @funcs[0];
+ }
+ if ($indent == 0) { }
+ elsif ($indent >= 1) { print OUT "| " x ($indent - 1) . "+--->"; }
+ print OUT @funcs[0] . "\n";
+ shift @funcs;
+ my $temp = $list;
+ foreach my $i (@funcs) {
+ ++$indent;
+ draw_func(@deplist{$i});
+ --$indent;
+ }
+ $list = $temp;
+}
+
+
diff --git a/libtommath/etc/2kprime.1 b/libtommath/etc/2kprime.1
new file mode 100644
index 0000000..c41ded1
--- /dev/null
+++ b/libtommath/etc/2kprime.1
@@ -0,0 +1,2 @@
+256-bits (k = 36113) = 115792089237316195423570985008687907853269984665640564039457584007913129603823
+512-bits (k = 38117) = 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006045979
diff --git a/libtommath/etc/2kprime.c b/libtommath/etc/2kprime.c
new file mode 100644
index 0000000..67a2777
--- /dev/null
+++ b/libtommath/etc/2kprime.c
@@ -0,0 +1,75 @@
+/* Makes safe primes of a 2k nature */
+#include <tommath.h>
+#include <time.h>
+
+int sizes[] = {256, 512, 768, 1024, 1536, 2048, 3072, 4096};
+
+int main(void)
+{
+ char buf[2000];
+ int x, y;
+ mp_int q, p;
+ FILE *out;
+ clock_t t1;
+ mp_digit z;
+
+ mp_init_multi(&q, &p, NULL);
+
+ out = fopen("2kprime.1", "w");
+ for (x = 0; x < (int)(sizeof(sizes) / sizeof(sizes[0])); x++) {
+ top:
+ mp_2expt(&q, sizes[x]);
+ mp_add_d(&q, 3, &q);
+ z = -3;
+
+ t1 = clock();
+ for(;;) {
+ mp_sub_d(&q, 4, &q);
+ z += 4;
+
+ if (z > MP_MASK) {
+ printf("No primes of size %d found\n", sizes[x]);
+ break;
+ }
+
+ if (clock() - t1 > CLOCKS_PER_SEC) {
+ printf("."); fflush(stdout);
+// sleep((clock() - t1 + CLOCKS_PER_SEC/2)/CLOCKS_PER_SEC);
+ t1 = clock();
+ }
+
+ /* quick test on q */
+ mp_prime_is_prime(&q, 1, &y);
+ if (y == 0) {
+ continue;
+ }
+
+ /* find (q-1)/2 */
+ mp_sub_d(&q, 1, &p);
+ mp_div_2(&p, &p);
+ mp_prime_is_prime(&p, 3, &y);
+ if (y == 0) {
+ continue;
+ }
+
+ /* test on q */
+ mp_prime_is_prime(&q, 3, &y);
+ if (y == 0) {
+ continue;
+ }
+
+ break;
+ }
+
+ if (y == 0) {
+ ++sizes[x];
+ goto top;
+ }
+
+ mp_toradix(&q, buf, 10);
+ printf("\n\n%d-bits (k = %lu) = %s\n", sizes[x], z, buf);
+ fprintf(out, "%d-bits (k = %lu) = %s\n", sizes[x], z, buf); fflush(out);
+ }
+
+ return 0;
+}
diff --git a/libtommath/etc/drprime.c b/libtommath/etc/drprime.c
new file mode 100644
index 0000000..0d0fdb9
--- /dev/null
+++ b/libtommath/etc/drprime.c
@@ -0,0 +1,59 @@
+/* Makes safe primes of a DR nature */
+#include <tommath.h>
+
+int sizes[] = { 1+256/DIGIT_BIT, 1+512/DIGIT_BIT, 1+768/DIGIT_BIT, 1+1024/DIGIT_BIT, 1+2048/DIGIT_BIT, 1+4096/DIGIT_BIT };
+int main(void)
+{
+ int res, x, y;
+ char buf[4096];
+ FILE *out;
+ mp_int a, b;
+
+ mp_init(&a);
+ mp_init(&b);
+
+ out = fopen("drprimes.txt", "w");
+ for (x = 0; x < (int)(sizeof(sizes)/sizeof(sizes[0])); x++) {
+ top:
+ printf("Seeking a %d-bit safe prime\n", sizes[x] * DIGIT_BIT);
+ mp_grow(&a, sizes[x]);
+ mp_zero(&a);
+ for (y = 1; y < sizes[x]; y++) {
+ a.dp[y] = MP_MASK;
+ }
+
+ /* make a DR modulus */
+ a.dp[0] = -1;
+ a.used = sizes[x];
+
+ /* now loop */
+ res = 0;
+ for (;;) {
+ a.dp[0] += 4;
+ if (a.dp[0] >= MP_MASK) break;
+ mp_prime_is_prime(&a, 1, &res);
+ if (res == 0) continue;
+ printf("."); fflush(stdout);
+ mp_sub_d(&a, 1, &b);
+ mp_div_2(&b, &b);
+ mp_prime_is_prime(&b, 3, &res);
+ if (res == 0) continue;
+ mp_prime_is_prime(&a, 3, &res);
+ if (res == 1) break;
+ }
+
+ if (res != 1) {
+ printf("Error not DR modulus\n"); sizes[x] += 1; goto top;
+ } else {
+ mp_toradix(&a, buf, 10);
+ printf("\n\np == %s\n\n", buf);
+ fprintf(out, "%d-bit prime:\np == %s\n\n", mp_count_bits(&a), buf); fflush(out);
+ }
+ }
+ fclose(out);
+
+ mp_clear(&a);
+ mp_clear(&b);
+
+ return 0;
+}
diff --git a/libtommath/etc/drprimes.28 b/libtommath/etc/drprimes.28
new file mode 100644
index 0000000..9d438ad
--- /dev/null
+++ b/libtommath/etc/drprimes.28
@@ -0,0 +1,25 @@
+DR safe primes for 28-bit digits.
+
+224-bit prime:
+p == 26959946667150639794667015087019630673637144422540572481103341844143
+
+532-bit prime:
+p == 14059105607947488696282932836518693308967803494693489478439861164411992439598399594747002144074658928593502845729752797260025831423419686528151609940203368691747
+
+784-bit prime:
+p == 101745825697019260773923519755878567461315282017759829107608914364075275235254395622580447400994175578963163918967182013639660669771108475957692810857098847138903161308502419410142185759152435680068435915159402496058513611411688900243039
+
+1036-bit prime:
+p == 736335108039604595805923406147184530889923370574768772191969612422073040099331944991573923112581267542507986451953227192970402893063850485730703075899286013451337291468249027691733891486704001513279827771740183629161065194874727962517148100775228363421083691764065477590823919364012917984605619526140821798437127
+
+1540-bit prime:
+p == 38564998830736521417281865696453025806593491967131023221754800625044118265468851210705360385717536794615180260494208076605798671660719333199513807806252394423283413430106003596332513246682903994829528690198205120921557533726473585751382193953592127439965050261476810842071573684505878854588706623484573925925903505747545471088867712185004135201289273405614415899438276535626346098904241020877974002916168099951885406379295536200413493190419727789712076165162175783
+
+2072-bit prime:
+p == 542189391331696172661670440619180536749994166415993334151601745392193484590296600979602378676624808129613777993466242203025054573692562689251250471628358318743978285860720148446448885701001277560572526947619392551574490839286458454994488665744991822837769918095117129546414124448777033941223565831420390846864429504774477949153794689948747680362212954278693335653935890352619041936727463717926744868338358149568368643403037768649616778526013610493696186055899318268339432671541328195724261329606699831016666359440874843103020666106568222401047720269951530296879490444224546654729111504346660859907296364097126834834235287147
+
+3080-bit prime:
+p == 1487259134814709264092032648525971038895865645148901180585340454985524155135260217788758027400478312256339496385275012465661575576202252063145698732079880294664220579764848767704076761853197216563262660046602703973050798218246170835962005598561669706844469447435461092542265792444947706769615695252256130901271870341005768912974433684521436211263358097522726462083917939091760026658925757076733484173202927141441492573799914240222628795405623953109131594523623353044898339481494120112723445689647986475279242446083151413667587008191682564376412347964146113898565886683139407005941383669325997475076910488086663256335689181157957571445067490187939553165903773554290260531009121879044170766615232300936675369451260747671432073394867530820527479172464106442450727640226503746586340279816318821395210726268291535648506190714616083163403189943334431056876038286530365757187367147446004855912033137386225053275419626102417236133948503
+
+4116-bit prime:
+p == 1095121115716677802856811290392395128588168592409109494900178008967955253005183831872715423151551999734857184538199864469605657805519106717529655044054833197687459782636297255219742994736751541815269727940751860670268774903340296040006114013971309257028332849679096824800250742691718610670812374272414086863715763724622797509437062518082383056050144624962776302147890521249477060215148275163688301275847155316042279405557632639366066847442861422164832655874655824221577849928863023018366835675399949740429332468186340518172487073360822220449055340582568461568645259954873303616953776393853174845132081121976327462740354930744487429617202585015510744298530101547706821590188733515880733527449780963163909830077616357506845523215289297624086914545378511082534229620116563260168494523906566709418166011112754529766183554579321224940951177394088465596712620076240067370589036924024728375076210477267488679008016579588696191194060127319035195370137160936882402244399699172017835144537488486396906144217720028992863941288217185353914991583400421682751000603596655790990815525126154394344641336397793791497068253936771017031980867706707490224041075826337383538651825493679503771934836094655802776331664261631740148281763487765852746577808019633679
diff --git a/libtommath/etc/drprimes.txt b/libtommath/etc/drprimes.txt
new file mode 100644
index 0000000..7c97f67
--- /dev/null
+++ b/libtommath/etc/drprimes.txt
@@ -0,0 +1,9 @@
+300-bit prime:
+p == 2037035976334486086268445688409378161051468393665936250636140449354381298610415201576637819
+
+540-bit prime:
+p == 3599131035634557106248430806148785487095757694641533306480604458089470064537190296255232548883112685719936728506816716098566612844395439751206810991770626477344739
+
+780-bit prime:
+p == 6359114106063703798370219984742410466332205126109989319225557147754704702203399726411277962562135973685197744935448875852478791860694279747355800678568677946181447581781401213133886609947027230004277244697462656003655947791725966271167
+
diff --git a/libtommath/etc/makefile b/libtommath/etc/makefile
new file mode 100644
index 0000000..99154d8
--- /dev/null
+++ b/libtommath/etc/makefile
@@ -0,0 +1,50 @@
+CFLAGS += -Wall -W -Wshadow -O3 -fomit-frame-pointer -funroll-loops -I../
+
+# default lib name (requires install with root)
+# LIBNAME=-ltommath
+
+# libname when you can't install the lib with install
+LIBNAME=../libtommath.a
+
+#provable primes
+pprime: pprime.o
+ $(CC) pprime.o $(LIBNAME) -o pprime
+
+# portable [well requires clock()] tuning app
+tune: tune.o
+ $(CC) tune.o $(LIBNAME) -o tune
+
+# same app but using RDTSC for higher precision [requires 80586+], coff based gcc installs [e.g. ming, cygwin, djgpp]
+tune86: tune.c
+ nasm -f coff timer.asm
+ $(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o $(LIBNAME) -o tune86
+
+# for cygwin
+tune86c: tune.c
+ nasm -f gnuwin32 timer.asm
+ $(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o $(LIBNAME) -o tune86
+
+#make tune86 for linux or any ELF format
+tune86l: tune.c
+ nasm -f elf -DUSE_ELF timer.asm
+ $(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o $(LIBNAME) -o tune86l
+
+# spits out mersenne primes
+mersenne: mersenne.o
+ $(CC) mersenne.o $(LIBNAME) -o mersenne
+
+# fines DR safe primes for the given config
+drprime: drprime.o
+ $(CC) drprime.o $(LIBNAME) -o drprime
+
+# fines 2k safe primes for the given config
+2kprime: 2kprime.o
+ $(CC) 2kprime.o $(LIBNAME) -o 2kprime
+
+mont: mont.o
+ $(CC) mont.o $(LIBNAME) -o mont
+
+
+clean:
+ rm -f *.log *.o *.obj *.exe pprime tune mersenne drprime tune86 tune86l mont 2kprime pprime.dat \
+ *.da *.dyn *.dpi *~
diff --git a/libtommath/etc/makefile.icc b/libtommath/etc/makefile.icc
new file mode 100644
index 0000000..8a1ffff
--- /dev/null
+++ b/libtommath/etc/makefile.icc
@@ -0,0 +1,67 @@
+CC = icc
+
+CFLAGS += -I../
+
+# optimize for SPEED
+#
+# -mcpu= can be pentium, pentiumpro (covers PII through PIII) or pentium4
+# -ax? specifies make code specifically for ? but compatible with IA-32
+# -x? specifies compile solely for ? [not specifically IA-32 compatible]
+#
+# where ? is
+# K - PIII
+# W - first P4 [Williamette]
+# N - P4 Northwood
+# P - P4 Prescott
+# B - Blend of P4 and PM [mobile]
+#
+# Default to just generic max opts
+CFLAGS += -O3 -xP -ip
+
+# default lib name (requires install with root)
+# LIBNAME=-ltommath
+
+# libname when you can't install the lib with install
+LIBNAME=../libtommath.a
+
+#provable primes
+pprime: pprime.o
+ $(CC) pprime.o $(LIBNAME) -o pprime
+
+# portable [well requires clock()] tuning app
+tune: tune.o
+ $(CC) tune.o $(LIBNAME) -o tune
+
+# same app but using RDTSC for higher precision [requires 80586+], coff based gcc installs [e.g. ming, cygwin, djgpp]
+tune86: tune.c
+ nasm -f coff timer.asm
+ $(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o $(LIBNAME) -o tune86
+
+# for cygwin
+tune86c: tune.c
+ nasm -f gnuwin32 timer.asm
+ $(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o $(LIBNAME) -o tune86
+
+#make tune86 for linux or any ELF format
+tune86l: tune.c
+ nasm -f elf -DUSE_ELF timer.asm
+ $(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o $(LIBNAME) -o tune86l
+
+# spits out mersenne primes
+mersenne: mersenne.o
+ $(CC) mersenne.o $(LIBNAME) -o mersenne
+
+# fines DR safe primes for the given config
+drprime: drprime.o
+ $(CC) drprime.o $(LIBNAME) -o drprime
+
+# fines 2k safe primes for the given config
+2kprime: 2kprime.o
+ $(CC) 2kprime.o $(LIBNAME) -o 2kprime
+
+mont: mont.o
+ $(CC) mont.o $(LIBNAME) -o mont
+
+
+clean:
+ rm -f *.log *.o *.obj *.exe pprime tune mersenne drprime tune86 tune86l mont 2kprime pprime.dat *.il
diff --git a/libtommath/etc/makefile.msvc b/libtommath/etc/makefile.msvc
new file mode 100644
index 0000000..2833372
--- /dev/null
+++ b/libtommath/etc/makefile.msvc
@@ -0,0 +1,23 @@
+#MSVC Makefile
+#
+#Tom St Denis
+
+CFLAGS = /I../ /Ox /DWIN32 /W3
+
+pprime: pprime.obj
+ cl pprime.obj ../tommath.lib
+
+mersenne: mersenne.obj
+ cl mersenne.obj ../tommath.lib
+
+tune: tune.obj
+ cl tune.obj ../tommath.lib
+
+mont: mont.obj
+ cl mont.obj ../tommath.lib
+
+drprime: drprime.obj
+ cl drprime.obj ../tommath.lib
+
+2kprime: 2kprime.obj
+ cl 2kprime.obj ../tommath.lib
diff --git a/libtommath/etc/mersenne.c b/libtommath/etc/mersenne.c
new file mode 100644
index 0000000..28ac834
--- /dev/null
+++ b/libtommath/etc/mersenne.c
@@ -0,0 +1,140 @@
+/* Finds Mersenne primes using the Lucas-Lehmer test
+ *
+ * Tom St Denis, tomstdenis@gmail.com
+ */
+#include <time.h>
+#include <tommath.h>
+
+int
+is_mersenne (long s, int *pp)
+{
+ mp_int n, u;
+ int res, k;
+
+ *pp = 0;
+
+ if ((res = mp_init (&n)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_init (&u)) != MP_OKAY) {
+ goto LBL_N;
+ }
+
+ /* n = 2^s - 1 */
+ if ((res = mp_2expt(&n, s)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ if ((res = mp_sub_d (&n, 1, &n)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+
+ /* set u=4 */
+ mp_set (&u, 4);
+
+ /* for k=1 to s-2 do */
+ for (k = 1; k <= s - 2; k++) {
+ /* u = u^2 - 2 mod n */
+ if ((res = mp_sqr (&u, &u)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ if ((res = mp_sub_d (&u, 2, &u)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+
+ /* make sure u is positive */
+ while (u.sign == MP_NEG) {
+ if ((res = mp_add (&u, &n, &u)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ }
+
+ /* reduce */
+ if ((res = mp_reduce_2k (&u, &n, 1)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ }
+
+ /* if u == 0 then its prime */
+ if (mp_iszero (&u) == 1) {
+ mp_prime_is_prime(&n, 8, pp);
+ if (*pp != 1) printf("FAILURE\n");
+ }
+
+ res = MP_OKAY;
+LBL_MU:mp_clear (&u);
+LBL_N:mp_clear (&n);
+ return res;
+}
+
+/* square root of a long < 65536 */
+long
+i_sqrt (long x)
+{
+ long x1, x2;
+
+ x2 = 16;
+ do {
+ x1 = x2;
+ x2 = x1 - ((x1 * x1) - x) / (2 * x1);
+ } while (x1 != x2);
+
+ if (x1 * x1 > x) {
+ --x1;
+ }
+
+ return x1;
+}
+
+/* is the long prime by brute force */
+int
+isprime (long k)
+{
+ long y, z;
+
+ y = i_sqrt (k);
+ for (z = 2; z <= y; z++) {
+ if ((k % z) == 0)
+ return 0;
+ }
+ return 1;
+}
+
+
+int
+main (void)
+{
+ int pp;
+ long k;
+ clock_t tt;
+
+ k = 3;
+
+ for (;;) {
+ /* start time */
+ tt = clock ();
+
+ /* test if 2^k - 1 is prime */
+ if (is_mersenne (k, &pp) != MP_OKAY) {
+ printf ("Whoa error\n");
+ return -1;
+ }
+
+ if (pp == 1) {
+ /* count time */
+ tt = clock () - tt;
+
+ /* display if prime */
+ printf ("2^%-5ld - 1 is prime, test took %ld ticks\n", k, tt);
+ }
+
+ /* goto next odd exponent */
+ k += 2;
+
+ /* but make sure its prime */
+ while (isprime (k) == 0) {
+ k += 2;
+ }
+ }
+ return 0;
+}
diff --git a/libtommath/etc/mont.c b/libtommath/etc/mont.c
new file mode 100644
index 0000000..7839675
--- /dev/null
+++ b/libtommath/etc/mont.c
@@ -0,0 +1,41 @@
+/* tests the montgomery routines */
+#include <tommath.h>
+
+int main(void)
+{
+ mp_int modulus, R, p, pp;
+ mp_digit mp;
+ long x, y;
+
+ srand(time(NULL));
+ mp_init_multi(&modulus, &R, &p, &pp, NULL);
+
+ /* loop through various sizes */
+ for (x = 4; x < 256; x++) {
+ printf("DIGITS == %3ld...", x); fflush(stdout);
+
+ /* make up the odd modulus */
+ mp_rand(&modulus, x);
+ modulus.dp[0] |= 1;
+
+ /* now find the R value */
+ mp_montgomery_calc_normalization(&R, &modulus);
+ mp_montgomery_setup(&modulus, &mp);
+
+ /* now run through a bunch tests */
+ for (y = 0; y < 1000; y++) {
+ mp_rand(&p, x/2); /* p = random */
+ mp_mul(&p, &R, &pp); /* pp = R * p */
+ mp_montgomery_reduce(&pp, &modulus, mp);
+
+ /* should be equal to p */
+ if (mp_cmp(&pp, &p) != MP_EQ) {
+ printf("FAILURE!\n");
+ exit(-1);
+ }
+ }
+ printf("PASSED\n");
+ }
+
+ return 0;
+}
diff --git a/libtommath/etc/pprime.c b/libtommath/etc/pprime.c
new file mode 100644
index 0000000..955f19e
--- /dev/null
+++ b/libtommath/etc/pprime.c
@@ -0,0 +1,396 @@
+/* Generates provable primes
+ *
+ * See http://gmail.com:8080/papers/pp.pdf for more info.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://tom.gmail.com
+ */
+#include <time.h>
+#include "tommath.h"
+
+int n_prime;
+FILE *primes;
+
+/* fast square root */
+static mp_digit
+i_sqrt (mp_word x)
+{
+ mp_word x1, x2;
+
+ x2 = x;
+ do {
+ x1 = x2;
+ x2 = x1 - ((x1 * x1) - x) / (2 * x1);
+ } while (x1 != x2);
+
+ if (x1 * x1 > x) {
+ --x1;
+ }
+
+ return x1;
+}
+
+
+/* generates a prime digit */
+static void gen_prime (void)
+{
+ mp_digit r, x, y, next;
+ FILE *out;
+
+ out = fopen("pprime.dat", "wb");
+
+ /* write first set of primes */
+ r = 3; fwrite(&r, 1, sizeof(mp_digit), out);
+ r = 5; fwrite(&r, 1, sizeof(mp_digit), out);
+ r = 7; fwrite(&r, 1, sizeof(mp_digit), out);
+ r = 11; fwrite(&r, 1, sizeof(mp_digit), out);
+ r = 13; fwrite(&r, 1, sizeof(mp_digit), out);
+ r = 17; fwrite(&r, 1, sizeof(mp_digit), out);
+ r = 19; fwrite(&r, 1, sizeof(mp_digit), out);
+ r = 23; fwrite(&r, 1, sizeof(mp_digit), out);
+ r = 29; fwrite(&r, 1, sizeof(mp_digit), out);
+ r = 31; fwrite(&r, 1, sizeof(mp_digit), out);
+
+ /* get square root, since if 'r' is composite its factors must be < than this */
+ y = i_sqrt (r);
+ next = (y + 1) * (y + 1);
+
+ for (;;) {
+ do {
+ r += 2; /* next candidate */
+ r &= MP_MASK;
+ if (r < 31) break;
+
+ /* update sqrt ? */
+ if (next <= r) {
+ ++y;
+ next = (y + 1) * (y + 1);
+ }
+
+ /* loop if divisible by 3,5,7,11,13,17,19,23,29 */
+ if ((r % 3) == 0) {
+ x = 0;
+ continue;
+ }
+ if ((r % 5) == 0) {
+ x = 0;
+ continue;
+ }
+ if ((r % 7) == 0) {
+ x = 0;
+ continue;
+ }
+ if ((r % 11) == 0) {
+ x = 0;
+ continue;
+ }
+ if ((r % 13) == 0) {
+ x = 0;
+ continue;
+ }
+ if ((r % 17) == 0) {
+ x = 0;
+ continue;
+ }
+ if ((r % 19) == 0) {
+ x = 0;
+ continue;
+ }
+ if ((r % 23) == 0) {
+ x = 0;
+ continue;
+ }
+ if ((r % 29) == 0) {
+ x = 0;
+ continue;
+ }
+
+ /* now check if r is divisible by x + k={1,7,11,13,17,19,23,29} */
+ for (x = 30; x <= y; x += 30) {
+ if ((r % (x + 1)) == 0) {
+ x = 0;
+ break;
+ }
+ if ((r % (x + 7)) == 0) {
+ x = 0;
+ break;
+ }
+ if ((r % (x + 11)) == 0) {
+ x = 0;
+ break;
+ }
+ if ((r % (x + 13)) == 0) {
+ x = 0;
+ break;
+ }
+ if ((r % (x + 17)) == 0) {
+ x = 0;
+ break;
+ }
+ if ((r % (x + 19)) == 0) {
+ x = 0;
+ break;
+ }
+ if ((r % (x + 23)) == 0) {
+ x = 0;
+ break;
+ }
+ if ((r % (x + 29)) == 0) {
+ x = 0;
+ break;
+ }
+ }
+ } while (x == 0);
+ if (r > 31) { fwrite(&r, 1, sizeof(mp_digit), out); printf("%9d\r", r); fflush(stdout); }
+ if (r < 31) break;
+ }
+
+ fclose(out);
+}
+
+void load_tab(void)
+{
+ primes = fopen("pprime.dat", "rb");
+ if (primes == NULL) {
+ gen_prime();
+ primes = fopen("pprime.dat", "rb");
+ }
+ fseek(primes, 0, SEEK_END);
+ n_prime = ftell(primes) / sizeof(mp_digit);
+}
+
+mp_digit prime_digit(void)
+{
+ int n;
+ mp_digit d;
+
+ n = abs(rand()) % n_prime;
+ fseek(primes, n * sizeof(mp_digit), SEEK_SET);
+ fread(&d, 1, sizeof(mp_digit), primes);
+ return d;
+}
+
+
+/* makes a prime of at least k bits */
+int
+pprime (int k, int li, mp_int * p, mp_int * q)
+{
+ mp_int a, b, c, n, x, y, z, v;
+ int res, ii;
+ static const mp_digit bases[] = { 2, 3, 5, 7, 11, 13, 17, 19 };
+
+ /* single digit ? */
+ if (k <= (int) DIGIT_BIT) {
+ mp_set (p, prime_digit ());
+ return MP_OKAY;
+ }
+
+ if ((res = mp_init (&c)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_init (&v)) != MP_OKAY) {
+ goto LBL_C;
+ }
+
+ /* product of first 50 primes */
+ if ((res =
+ mp_read_radix (&v,
+ "19078266889580195013601891820992757757219839668357012055907516904309700014933909014729740190",
+ 10)) != MP_OKAY) {
+ goto LBL_V;
+ }
+
+ if ((res = mp_init (&a)) != MP_OKAY) {
+ goto LBL_V;
+ }
+
+ /* set the prime */
+ mp_set (&a, prime_digit ());
+
+ if ((res = mp_init (&b)) != MP_OKAY) {
+ goto LBL_A;
+ }
+
+ if ((res = mp_init (&n)) != MP_OKAY) {
+ goto LBL_B;
+ }
+
+ if ((res = mp_init (&x)) != MP_OKAY) {
+ goto LBL_N;
+ }
+
+ if ((res = mp_init (&y)) != MP_OKAY) {
+ goto LBL_X;
+ }
+
+ if ((res = mp_init (&z)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ /* now loop making the single digit */
+ while (mp_count_bits (&a) < k) {
+ fprintf (stderr, "prime has %4d bits left\r", k - mp_count_bits (&a));
+ fflush (stderr);
+ top:
+ mp_set (&b, prime_digit ());
+
+ /* now compute z = a * b * 2 */
+ if ((res = mp_mul (&a, &b, &z)) != MP_OKAY) { /* z = a * b */
+ goto LBL_Z;
+ }
+
+ if ((res = mp_copy (&z, &c)) != MP_OKAY) { /* c = a * b */
+ goto LBL_Z;
+ }
+
+ if ((res = mp_mul_2 (&z, &z)) != MP_OKAY) { /* z = 2 * a * b */
+ goto LBL_Z;
+ }
+
+ /* n = z + 1 */
+ if ((res = mp_add_d (&z, 1, &n)) != MP_OKAY) { /* n = z + 1 */
+ goto LBL_Z;
+ }
+
+ /* check (n, v) == 1 */
+ if ((res = mp_gcd (&n, &v, &y)) != MP_OKAY) { /* y = (n, v) */
+ goto LBL_Z;
+ }
+
+ if (mp_cmp_d (&y, 1) != MP_EQ)
+ goto top;
+
+ /* now try base x=bases[ii] */
+ for (ii = 0; ii < li; ii++) {
+ mp_set (&x, bases[ii]);
+
+ /* compute x^a mod n */
+ if ((res = mp_exptmod (&x, &a, &n, &y)) != MP_OKAY) { /* y = x^a mod n */
+ goto LBL_Z;
+ }
+
+ /* if y == 1 loop */
+ if (mp_cmp_d (&y, 1) == MP_EQ)
+ continue;
+
+ /* now x^2a mod n */
+ if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) { /* y = x^2a mod n */
+ goto LBL_Z;
+ }
+
+ if (mp_cmp_d (&y, 1) == MP_EQ)
+ continue;
+
+ /* compute x^b mod n */
+ if ((res = mp_exptmod (&x, &b, &n, &y)) != MP_OKAY) { /* y = x^b mod n */
+ goto LBL_Z;
+ }
+
+ /* if y == 1 loop */
+ if (mp_cmp_d (&y, 1) == MP_EQ)
+ continue;
+
+ /* now x^2b mod n */
+ if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) { /* y = x^2b mod n */
+ goto LBL_Z;
+ }
+
+ if (mp_cmp_d (&y, 1) == MP_EQ)
+ continue;
+
+ /* compute x^c mod n == x^ab mod n */
+ if ((res = mp_exptmod (&x, &c, &n, &y)) != MP_OKAY) { /* y = x^ab mod n */
+ goto LBL_Z;
+ }
+
+ /* if y == 1 loop */
+ if (mp_cmp_d (&y, 1) == MP_EQ)
+ continue;
+
+ /* now compute (x^c mod n)^2 */
+ if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) { /* y = x^2ab mod n */
+ goto LBL_Z;
+ }
+
+ /* y should be 1 */
+ if (mp_cmp_d (&y, 1) != MP_EQ)
+ continue;
+ break;
+ }
+
+ /* no bases worked? */
+ if (ii == li)
+ goto top;
+
+{
+ char buf[4096];
+
+ mp_toradix(&n, buf, 10);
+ printf("Certificate of primality for:\n%s\n\n", buf);
+ mp_toradix(&a, buf, 10);
+ printf("A == \n%s\n\n", buf);
+ mp_toradix(&b, buf, 10);
+ printf("B == \n%s\n\nG == %d\n", buf, bases[ii]);
+ printf("----------------------------------------------------------------\n");
+}
+
+ /* a = n */
+ mp_copy (&n, &a);
+ }
+
+ /* get q to be the order of the large prime subgroup */
+ mp_sub_d (&n, 1, q);
+ mp_div_2 (q, q);
+ mp_div (q, &b, q, NULL);
+
+ mp_exch (&n, p);
+
+ res = MP_OKAY;
+LBL_Z:mp_clear (&z);
+LBL_Y:mp_clear (&y);
+LBL_X:mp_clear (&x);
+LBL_N:mp_clear (&n);
+LBL_B:mp_clear (&b);
+LBL_A:mp_clear (&a);
+LBL_V:mp_clear (&v);
+LBL_C:mp_clear (&c);
+ return res;
+}
+
+
+int
+main (void)
+{
+ mp_int p, q;
+ char buf[4096];
+ int k, li;
+ clock_t t1;
+
+ srand (time (NULL));
+ load_tab();
+
+ printf ("Enter # of bits: \n");
+ fgets (buf, sizeof (buf), stdin);
+ sscanf (buf, "%d", &k);
+
+ printf ("Enter number of bases to try (1 to 8):\n");
+ fgets (buf, sizeof (buf), stdin);
+ sscanf (buf, "%d", &li);
+
+
+ mp_init (&p);
+ mp_init (&q);
+
+ t1 = clock ();
+ pprime (k, li, &p, &q);
+ t1 = clock () - t1;
+
+ printf ("\n\nTook %ld ticks, %d bits\n", t1, mp_count_bits (&p));
+
+ mp_toradix (&p, buf, 10);
+ printf ("P == %s\n", buf);
+ mp_toradix (&q, buf, 10);
+ printf ("Q == %s\n", buf);
+
+ return 0;
+}
diff --git a/libtommath/etc/prime.1024 b/libtommath/etc/prime.1024
new file mode 100644
index 0000000..5636e2d
--- /dev/null
+++ b/libtommath/etc/prime.1024
@@ -0,0 +1,414 @@
+Enter # of bits:
+Enter number of bases to try (1 to 8):
+Certificate of primality for:
+36360080703173363
+
+A ==
+89963569
+
+B ==
+202082249
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+4851595597739856136987139
+
+A ==
+36360080703173363
+
+B ==
+66715963
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+19550639734462621430325731591027
+
+A ==
+4851595597739856136987139
+
+B ==
+2014867
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+10409036141344317165691858509923818734539
+
+A ==
+19550639734462621430325731591027
+
+B ==
+266207047
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+1049829549988285012736475602118094726647504414203
+
+A ==
+10409036141344317165691858509923818734539
+
+B ==
+50428759
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+77194737385528288387712399596835459931920358844586615003
+
+A ==
+1049829549988285012736475602118094726647504414203
+
+B ==
+36765367
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+35663756695365208574443215955488689578374232732893628896541201763
+
+A ==
+77194737385528288387712399596835459931920358844586615003
+
+B ==
+230998627
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+16711831463502165169495622246023119698415848120292671294127567620396469803
+
+A ==
+35663756695365208574443215955488689578374232732893628896541201763
+
+B ==
+234297127
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+6163534781560285962890718925972249753147470953579266394395432475622345597103528739
+
+A ==
+16711831463502165169495622246023119698415848120292671294127567620396469803
+
+B ==
+184406323
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+814258256205243497704094951432575867360065658372158511036259934640748088306764553488803787
+
+A ==
+6163534781560285962890718925972249753147470953579266394395432475622345597103528739
+
+B ==
+66054487
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+176469695533271657902814176811660357049007467856432383037590673407330246967781451723764079581998187
+
+A ==
+814258256205243497704094951432575867360065658372158511036259934640748088306764553488803787
+
+B ==
+108362239
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+44924492859445516541759485198544012102424796403707253610035148063863073596051272171194806669756971406400419
+
+A ==
+176469695533271657902814176811660357049007467856432383037590673407330246967781451723764079581998187
+
+B ==
+127286707
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+20600996927219343383225424320134474929609459588323857796871086845924186191561749519858600696159932468024710985371059
+
+A ==
+44924492859445516541759485198544012102424796403707253610035148063863073596051272171194806669756971406400419
+
+B ==
+229284691
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+6295696427695493110141186605837397185848992307978456138112526915330347715236378041486547994708748840844217371233735072572979
+
+A ==
+20600996927219343383225424320134474929609459588323857796871086845924186191561749519858600696159932468024710985371059
+
+B ==
+152800771
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+3104984078042317488749073016454213579257792635142218294052134804187631661145261015102617582090263808696699966840735333252107678792123
+
+A ==
+6295696427695493110141186605837397185848992307978456138112526915330347715236378041486547994708748840844217371233735072572979
+
+B ==
+246595759
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+26405175827665701256325699315126705508919255051121452292124404943796947287968603975320562847910946802396632302209435206627913466015741799499
+
+A ==
+3104984078042317488749073016454213579257792635142218294052134804187631661145261015102617582090263808696699966840735333252107678792123
+
+B ==
+4252063
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+11122146237908413610034600609460545703591095894418599759742741406628055069007082998134905595800236452010905900391505454890446585211975124558601770163
+
+A ==
+26405175827665701256325699315126705508919255051121452292124404943796947287968603975320562847910946802396632302209435206627913466015741799499
+
+B ==
+210605419
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+1649861642047798890580354082088712649911849362201343649289384923147797960364736011515757482030049342943790127685185806092659832129486307035500638595572396187
+
+A ==
+11122146237908413610034600609460545703591095894418599759742741406628055069007082998134905595800236452010905900391505454890446585211975124558601770163
+
+B ==
+74170111
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+857983367126266717607389719637086684134462613006415859877666235955788392464081914127715967940968197765042399904117392707518175220864852816390004264107201177394565363
+
+A ==
+1649861642047798890580354082088712649911849362201343649289384923147797960364736011515757482030049342943790127685185806092659832129486307035500638595572396187
+
+B ==
+260016763
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+175995909353623703257072120479340610010337144085688850745292031336724691277374210929188442230237711063783727092685448718515661641054886101716698390145283196296702450566161283
+
+A ==
+857983367126266717607389719637086684134462613006415859877666235955788392464081914127715967940968197765042399904117392707518175220864852816390004264107201177394565363
+
+B ==
+102563707
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+48486002551155667224487059713350447239190772068092630563272168418880661006593537218144160068395218642353495339720640699721703003648144463556291315694787862009052641640656933232794283
+
+A ==
+175995909353623703257072120479340610010337144085688850745292031336724691277374210929188442230237711063783727092685448718515661641054886101716698390145283196296702450566161283
+
+B ==
+137747527
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+13156468011529105025061495011938518171328604045212410096476697450506055664012861932372156505805788068791146986282263016790631108386790291275939575123375304599622623328517354163964228279867403
+
+A ==
+48486002551155667224487059713350447239190772068092630563272168418880661006593537218144160068395218642353495339720640699721703003648144463556291315694787862009052641640656933232794283
+
+B ==
+135672847
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+6355194692790533601105154341731997464407930009404822926832136060319955058388106456084549316415200519472481147942263916585428906582726749131479465958107142228236909665306781538860053107680830113869123
+
+A ==
+13156468011529105025061495011938518171328604045212410096476697450506055664012861932372156505805788068791146986282263016790631108386790291275939575123375304599622623328517354163964228279867403
+
+B ==
+241523587
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+3157116676535430302794438027544146642863331358530722860333745617571010460905857862561870488000265751138954271040017454405707755458702044884023184574412221802502351503929935224995314581932097706874819348858083
+
+A ==
+6355194692790533601105154341731997464407930009404822926832136060319955058388106456084549316415200519472481147942263916585428906582726749131479465958107142228236909665306781538860053107680830113869123
+
+B ==
+248388667
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+390533129219992506725320633489467713907837370444962163378727819939092929448752905310115311180032249230394348337568973177802874166228132778126338883671958897238722734394783244237133367055422297736215754829839364158067
+
+A ==
+3157116676535430302794438027544146642863331358530722860333745617571010460905857862561870488000265751138954271040017454405707755458702044884023184574412221802502351503929935224995314581932097706874819348858083
+
+B ==
+61849651
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+48583654555070224891047847050732516652910250240135992225139515777200432486685999462997073444468380434359929499498804723793106565291183220444221080449740542884172281158126259373095216435009661050109711341419005972852770440739
+
+A ==
+390533129219992506725320633489467713907837370444962163378727819939092929448752905310115311180032249230394348337568973177802874166228132778126338883671958897238722734394783244237133367055422297736215754829839364158067
+
+B ==
+62201707
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+25733035251905120039135866524384525138869748427727001128764704499071378939227862068500633813538831598776578372709963673670934388213622433800015759585470542686333039614931682098922935087822950084908715298627996115185849260703525317419
+
+A ==
+48583654555070224891047847050732516652910250240135992225139515777200432486685999462997073444468380434359929499498804723793106565291183220444221080449740542884172281158126259373095216435009661050109711341419005972852770440739
+
+B ==
+264832231
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+2804594464939948901906623499531073917980499195397462605359913717827014360538186518540781517129548650937632008683280555602633122170458773895504894807182664540529077836857897972175530148107545939211339044386106111633510166695386323426241809387
+
+A ==
+25733035251905120039135866524384525138869748427727001128764704499071378939227862068500633813538831598776578372709963673670934388213622433800015759585470542686333039614931682098922935087822950084908715298627996115185849260703525317419
+
+B ==
+54494047
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+738136612083433720096707308165797114449914259256979340471077690416567237592465306112484843530074782721390528773594351482384711900456440808251196845265132086486672447136822046628407467459921823150600138073268385534588238548865012638209515923513516547
+
+A ==
+2804594464939948901906623499531073917980499195397462605359913717827014360538186518540781517129548650937632008683280555602633122170458773895504894807182664540529077836857897972175530148107545939211339044386106111633510166695386323426241809387
+
+B ==
+131594179
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+392847529056126766528615419937165193421166694172790666626558750047057558168124866940509180171236517681470100877687445134633784815352076138790217228749332398026714192707447855731679485746120589851992221508292976900578299504461333767437280988393026452846013683
+
+A ==
+738136612083433720096707308165797114449914259256979340471077690416567237592465306112484843530074782721390528773594351482384711900456440808251196845265132086486672447136822046628407467459921823150600138073268385534588238548865012638209515923513516547
+
+B ==
+266107603
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+168459393231883505975876919268398655632763956627405508859662408056221544310200546265681845397346956580604208064328814319465940958080244889692368602591598503944015835190587740756859842792554282496742843600573336023639256008687581291233481455395123454655488735304365627
+
+A ==
+392847529056126766528615419937165193421166694172790666626558750047057558168124866940509180171236517681470100877687445134633784815352076138790217228749332398026714192707447855731679485746120589851992221508292976900578299504461333767437280988393026452846013683
+
+B ==
+214408111
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+14865774288636941404884923981945833072113667565310054952177860608355263252462409554658728941191929400198053290113492910272458441655458514080123870132092365833472436407455910185221474386718838138135065780840839893113912689594815485706154461164071775481134379794909690501684643
+
+A ==
+168459393231883505975876919268398655632763956627405508859662408056221544310200546265681845397346956580604208064328814319465940958080244889692368602591598503944015835190587740756859842792554282496742843600573336023639256008687581291233481455395123454655488735304365627
+
+B ==
+44122723
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+1213301773203241614897109856134894783021668292000023984098824423682568173639394290886185366993108292039068940333907505157813934962357206131450244004178619265868614859794316361031904412926604138893775068853175215502104744339658944443630407632290152772487455298652998368296998719996019
+
+A ==
+14865774288636941404884923981945833072113667565310054952177860608355263252462409554658728941191929400198053290113492910272458441655458514080123870132092365833472436407455910185221474386718838138135065780840839893113912689594815485706154461164071775481134379794909690501684643
+
+B ==
+40808563
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+186935245989515158127969129347464851990429060640910951266513740972248428651109062997368144722015290092846666943896556191257222521203647606911446635194198213436423080005867489516421559330500722264446765608763224572386410155413161172707802334865729654109050873820610813855041667633843601286843
+
+A ==
+1213301773203241614897109856134894783021668292000023984098824423682568173639394290886185366993108292039068940333907505157813934962357206131450244004178619265868614859794316361031904412926604138893775068853175215502104744339658944443630407632290152772487455298652998368296998719996019
+
+B ==
+77035759
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+83142661079751490510739960019112406284111408348732592580459037404394946037094409915127399165633756159385609671956087845517678367844901424617866988187132480585966721962585586730693443536100138246516868613250009028187662080828012497191775172228832247706080044971423654632146928165751885302331924491683
+
+A ==
+186935245989515158127969129347464851990429060640910951266513740972248428651109062997368144722015290092846666943896556191257222521203647606911446635194198213436423080005867489516421559330500722264446765608763224572386410155413161172707802334865729654109050873820610813855041667633843601286843
+
+B ==
+222383587
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+3892354773803809855317742245039794448230625839512638747643814927766738642436392673485997449586432241626440927010641564064764336402368634186618250134234189066179771240232458249806850838490410473462391401438160528157981942499581634732706904411807195259620779379274017704050790865030808501633772117217899534443
+
+A ==
+83142661079751490510739960019112406284111408348732592580459037404394946037094409915127399165633756159385609671956087845517678367844901424617866988187132480585966721962585586730693443536100138246516868613250009028187662080828012497191775172228832247706080044971423654632146928165751885302331924491683
+
+B ==
+23407687
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+1663606652988091811284014366560171522582683318514519379924950390627250155440313691226744227787921928894551755219495501365555370027257568506349958010457682898612082048959464465369892842603765280317696116552850664773291371490339084156052244256635115997453399761029567033971998617303988376172539172702246575225837054723
+
+A ==
+3892354773803809855317742245039794448230625839512638747643814927766738642436392673485997449586432241626440927010641564064764336402368634186618250134234189066179771240232458249806850838490410473462391401438160528157981942499581634732706904411807195259620779379274017704050790865030808501633772117217899534443
+
+B ==
+213701827
+
+G == 2
+----------------------------------------------------------------
+
+
+Took 33057 ticks, 1048 bits
+P == 1663606652988091811284014366560171522582683318514519379924950390627250155440313691226744227787921928894551755219495501365555370027257568506349958010457682898612082048959464465369892842603765280317696116552850664773291371490339084156052244256635115997453399761029567033971998617303988376172539172702246575225837054723
+Q == 3892354773803809855317742245039794448230625839512638747643814927766738642436392673485997449586432241626440927010641564064764336402368634186618250134234189066179771240232458249806850838490410473462391401438160528157981942499581634732706904411807195259620779379274017704050790865030808501633772117217899534443
diff --git a/libtommath/etc/prime.512 b/libtommath/etc/prime.512
new file mode 100644
index 0000000..cb6ec30
--- /dev/null
+++ b/libtommath/etc/prime.512
@@ -0,0 +1,205 @@
+Enter # of bits:
+Enter number of bases to try (1 to 8):
+Certificate of primality for:
+85933926807634727
+
+A ==
+253758023
+
+B ==
+169322581
+
+G == 5
+----------------------------------------------------------------
+Certificate of primality for:
+23930198825086241462113799
+
+A ==
+85933926807634727
+
+B ==
+139236037
+
+G == 11
+----------------------------------------------------------------
+Certificate of primality for:
+6401844647261612602378676572510019
+
+A ==
+23930198825086241462113799
+
+B ==
+133760791
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+269731366027728777712034888684015329354259
+
+A ==
+6401844647261612602378676572510019
+
+B ==
+21066691
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+37942338209025571690075025099189467992329684223707
+
+A ==
+269731366027728777712034888684015329354259
+
+B ==
+70333567
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+15306904714258982484473490774101705363308327436988160248323
+
+A ==
+37942338209025571690075025099189467992329684223707
+
+B ==
+201712723
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+1616744757018513392810355191503853040357155275733333124624513530099
+
+A ==
+15306904714258982484473490774101705363308327436988160248323
+
+B ==
+52810963
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+464222094814208047161771036072622485188658077940154689939306386289983787983
+
+A ==
+1616744757018513392810355191503853040357155275733333124624513530099
+
+B ==
+143566909
+
+G == 5
+----------------------------------------------------------------
+Certificate of primality for:
+187429931674053784626487560729643601208757374994177258429930699354770049369025096447
+
+A ==
+464222094814208047161771036072622485188658077940154689939306386289983787983
+
+B ==
+201875281
+
+G == 5
+----------------------------------------------------------------
+Certificate of primality for:
+100579220846502621074093727119851331775052664444339632682598589456666938521976625305832917563
+
+A ==
+187429931674053784626487560729643601208757374994177258429930699354770049369025096447
+
+B ==
+268311523
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+1173616081309758475197022137833792133815753368965945885089720153370737965497134878651384030219765163
+
+A ==
+100579220846502621074093727119851331775052664444339632682598589456666938521976625305832917563
+
+B ==
+5834287
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+191456913489905913185935197655672585713573070349044195411728114905691721186574907738081340754373032735283623
+
+A ==
+1173616081309758475197022137833792133815753368965945885089720153370737965497134878651384030219765163
+
+B ==
+81567097
+
+G == 5
+----------------------------------------------------------------
+Certificate of primality for:
+57856530489201750164178576399448868489243874083056587683743345599898489554401618943240901541005080049321706789987519
+
+A ==
+191456913489905913185935197655672585713573070349044195411728114905691721186574907738081340754373032735283623
+
+B ==
+151095433
+
+G == 7
+----------------------------------------------------------------
+Certificate of primality for:
+13790529750452576698109671710773784949185621244122040804792403407272729038377767162233653248852099545134831722512085881814803
+
+A ==
+57856530489201750164178576399448868489243874083056587683743345599898489554401618943240901541005080049321706789987519
+
+B ==
+119178679
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+7075985989000817742677547821106534174334812111605018857703825637170140040509067704269696198231266351631132464035671858077052876058979
+
+A ==
+13790529750452576698109671710773784949185621244122040804792403407272729038377767162233653248852099545134831722512085881814803
+
+B ==
+256552363
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+1227273006232588072907488910282307435921226646895131225407452056677899411162892829564455154080310937471747140942360789623819327234258162420463
+
+A ==
+7075985989000817742677547821106534174334812111605018857703825637170140040509067704269696198231266351631132464035671858077052876058979
+
+B ==
+86720989
+
+G == 5
+----------------------------------------------------------------
+Certificate of primality for:
+446764896913554613686067036908702877942872355053329937790398156069936255759889884246832779737114032666318220500106499161852193765380831330106375235763
+
+A ==
+1227273006232588072907488910282307435921226646895131225407452056677899411162892829564455154080310937471747140942360789623819327234258162420463
+
+B ==
+182015287
+
+G == 2
+----------------------------------------------------------------
+Certificate of primality for:
+5290203010849586596974953717018896543907195901082056939587768479377028575911127944611236020459652034082251335583308070846379514569838984811187823420951275243
+
+A ==
+446764896913554613686067036908702877942872355053329937790398156069936255759889884246832779737114032666318220500106499161852193765380831330106375235763
+
+B ==
+5920567
+
+G == 2
+----------------------------------------------------------------
+
+
+Took 3454 ticks, 521 bits
+P == 5290203010849586596974953717018896543907195901082056939587768479377028575911127944611236020459652034082251335583308070846379514569838984811187823420951275243
+Q == 446764896913554613686067036908702877942872355053329937790398156069936255759889884246832779737114032666318220500106499161852193765380831330106375235763
diff --git a/libtommath/etc/timer.asm b/libtommath/etc/timer.asm
new file mode 100644
index 0000000..326a947
--- /dev/null
+++ b/libtommath/etc/timer.asm
@@ -0,0 +1,37 @@
+; x86 timer in NASM
+;
+; Tom St Denis, tomstdenis@iahu.ca
+[bits 32]
+[section .data]
+time dd 0, 0
+
+[section .text]
+
+%ifdef USE_ELF
+[global t_start]
+t_start:
+%else
+[global _t_start]
+_t_start:
+%endif
+ push edx
+ push eax
+ rdtsc
+ mov [time+0],edx
+ mov [time+4],eax
+ pop eax
+ pop edx
+ ret
+
+%ifdef USE_ELF
+[global t_read]
+t_read:
+%else
+[global _t_read]
+_t_read:
+%endif
+ rdtsc
+ sub eax,[time+4]
+ sbb edx,[time+0]
+ ret
+ \ No newline at end of file
diff --git a/libtommath/etc/tune.c b/libtommath/etc/tune.c
new file mode 100644
index 0000000..acb146f
--- /dev/null
+++ b/libtommath/etc/tune.c
@@ -0,0 +1,138 @@
+/* Tune the Karatsuba parameters
+ *
+ * Tom St Denis, tomstdenis@gmail.com
+ */
+#include <tommath.h>
+#include <time.h>
+
+/* how many times todo each size mult. Depends on your computer. For slow computers
+ * this can be low like 5 or 10. For fast [re: Athlon] should be 25 - 50 or so
+ */
+#define TIMES (1UL<<14UL)
+
+/* RDTSC from Scott Duplichan */
+static ulong64 TIMFUNC (void)
+ {
+ #if defined __GNUC__
+ #if defined(__i386__) || defined(__x86_64__)
+ unsigned long long a;
+ __asm__ __volatile__ ("rdtsc\nmovl %%eax,%0\nmovl %%edx,4+%0\n"::"m"(a):"%eax","%edx");
+ return a;
+ #else /* gcc-IA64 version */
+ unsigned long result;
+ __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory");
+ while (__builtin_expect ((int) result == -1, 0))
+ __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory");
+ return result;
+ #endif
+
+ // Microsoft and Intel Windows compilers
+ #elif defined _M_IX86
+ __asm rdtsc
+ #elif defined _M_AMD64
+ return __rdtsc ();
+ #elif defined _M_IA64
+ #if defined __INTEL_COMPILER
+ #include <ia64intrin.h>
+ #endif
+ return __getReg (3116);
+ #else
+ #error need rdtsc function for this build
+ #endif
+ }
+
+
+#ifndef X86_TIMER
+
+/* generic ISO C timer */
+ulong64 LBL_T;
+void t_start(void) { LBL_T = TIMFUNC(); }
+ulong64 t_read(void) { return TIMFUNC() - LBL_T; }
+
+#else
+extern void t_start(void);
+extern ulong64 t_read(void);
+#endif
+
+ulong64 time_mult(int size, int s)
+{
+ unsigned long x;
+ mp_int a, b, c;
+ ulong64 t1;
+
+ mp_init (&a);
+ mp_init (&b);
+ mp_init (&c);
+
+ mp_rand (&a, size);
+ mp_rand (&b, size);
+
+ if (s == 1) {
+ KARATSUBA_MUL_CUTOFF = size;
+ } else {
+ KARATSUBA_MUL_CUTOFF = 100000;
+ }
+
+ t_start();
+ for (x = 0; x < TIMES; x++) {
+ mp_mul(&a,&b,&c);
+ }
+ t1 = t_read();
+ mp_clear (&a);
+ mp_clear (&b);
+ mp_clear (&c);
+ return t1;
+}
+
+ulong64 time_sqr(int size, int s)
+{
+ unsigned long x;
+ mp_int a, b;
+ ulong64 t1;
+
+ mp_init (&a);
+ mp_init (&b);
+
+ mp_rand (&a, size);
+
+ if (s == 1) {
+ KARATSUBA_SQR_CUTOFF = size;
+ } else {
+ KARATSUBA_SQR_CUTOFF = 100000;
+ }
+
+ t_start();
+ for (x = 0; x < TIMES; x++) {
+ mp_sqr(&a,&b);
+ }
+ t1 = t_read();
+ mp_clear (&a);
+ mp_clear (&b);
+ return t1;
+}
+
+int
+main (void)
+{
+ ulong64 t1, t2;
+ int x, y;
+
+ for (x = 8; ; x += 2) {
+ t1 = time_mult(x, 0);
+ t2 = time_mult(x, 1);
+ printf("%d: %9llu %9llu, %9llu\n", x, t1, t2, t2 - t1);
+ if (t2 < t1) break;
+ }
+ y = x;
+
+ for (x = 8; ; x += 2) {
+ t1 = time_sqr(x, 0);
+ t2 = time_sqr(x, 1);
+ printf("%d: %9llu %9llu, %9llu\n", x, t1, t2, t2 - t1);
+ if (t2 < t1) break;
+ }
+ printf("KARATSUBA_MUL_CUTOFF = %d\n", y);
+ printf("KARATSUBA_SQR_CUTOFF = %d\n", x);
+
+ return 0;
+}
diff --git a/libtommath/gen.pl b/libtommath/gen.pl
new file mode 100644
index 0000000..7236591
--- /dev/null
+++ b/libtommath/gen.pl
@@ -0,0 +1,17 @@
+#!/usr/bin/perl -w
+#
+# Generates a "single file" you can use to quickly
+# add the whole source without any makefile troubles
+#
+use strict;
+
+open( OUT, ">mpi.c" ) or die "Couldn't open mpi.c for writing: $!";
+foreach my $filename (glob "bn*.c") {
+ open( SRC, "<$filename" ) or die "Couldn't open $filename for reading: $!";
+ print OUT "/* Start: $filename */\n";
+ print OUT while <SRC>;
+ print OUT "\n/* End: $filename */\n\n";
+ close SRC or die "Error closing $filename after reading: $!";
+}
+print OUT "\n/* EOF */\n";
+close OUT or die "Error closing mpi.c after writing: $!"; \ No newline at end of file
diff --git a/libtommath/logs/README b/libtommath/logs/README
new file mode 100644
index 0000000..965e7c8
--- /dev/null
+++ b/libtommath/logs/README
@@ -0,0 +1,13 @@
+To use the pretty graphs you have to first build/run the ltmtest from the root directory of the package.
+Todo this type
+
+make timing ; ltmtest
+
+in the root. It will run for a while [about ten minutes on most PCs] and produce a series of .log files in logs/.
+
+After doing that run "gnuplot graphs.dem" to make the PNGs. If you managed todo that all so far just open index.html to view
+them all :-)
+
+Have fun
+
+Tom \ No newline at end of file
diff --git a/libtommath/logs/add.log b/libtommath/logs/add.log
new file mode 100644
index 0000000..43503ac
--- /dev/null
+++ b/libtommath/logs/add.log
@@ -0,0 +1,16 @@
+480 87
+960 111
+1440 135
+1920 159
+2400 200
+2880 224
+3360 248
+3840 272
+4320 296
+4800 320
+5280 344
+5760 368
+6240 392
+6720 416
+7200 440
+7680 464
diff --git a/libtommath/logs/addsub.png b/libtommath/logs/addsub.png
new file mode 100644
index 0000000..441c7b2
--- /dev/null
+++ b/libtommath/logs/addsub.png
Binary files differ
diff --git a/libtommath/logs/expt.log b/libtommath/logs/expt.log
new file mode 100644
index 0000000..70932ab
--- /dev/null
+++ b/libtommath/logs/expt.log
@@ -0,0 +1,7 @@
+513 1435869
+769 3544970
+1025 7791638
+2049 46902238
+2561 85334899
+3073 141451412
+4097 308770310
diff --git a/libtommath/logs/expt.png b/libtommath/logs/expt.png
new file mode 100644
index 0000000..d779cc5
--- /dev/null
+++ b/libtommath/logs/expt.png
Binary files differ
diff --git a/libtommath/logs/expt_2k.log b/libtommath/logs/expt_2k.log
new file mode 100644
index 0000000..97d325f
--- /dev/null
+++ b/libtommath/logs/expt_2k.log
@@ -0,0 +1,5 @@
+607 2109225
+1279 10148314
+2203 34126877
+3217 82716424
+4253 161569606
diff --git a/libtommath/logs/expt_2kl.log b/libtommath/logs/expt_2kl.log
new file mode 100644
index 0000000..d9ad4be
--- /dev/null
+++ b/libtommath/logs/expt_2kl.log
@@ -0,0 +1,4 @@
+1024 7705271
+2048 34286851
+4096 165207491
+521 1618631
diff --git a/libtommath/logs/expt_dr.log b/libtommath/logs/expt_dr.log
new file mode 100644
index 0000000..c6bbe07
--- /dev/null
+++ b/libtommath/logs/expt_dr.log
@@ -0,0 +1,7 @@
+532 1928550
+784 3763908
+1036 7564221
+1540 16566059
+2072 32283784
+3080 79851565
+4116 157843530
diff --git a/libtommath/logs/graphs.dem b/libtommath/logs/graphs.dem
new file mode 100644
index 0000000..dfaf613
--- /dev/null
+++ b/libtommath/logs/graphs.dem
@@ -0,0 +1,17 @@
+set terminal png
+set size 1.75
+set ylabel "Cycles per Operation"
+set xlabel "Operand size (bits)"
+
+set output "addsub.png"
+plot 'add.log' smooth bezier title "Addition", 'sub.log' smooth bezier title "Subtraction"
+
+set output "mult.png"
+plot 'sqr.log' smooth bezier title "Squaring (without Karatsuba)", 'sqr_kara.log' smooth bezier title "Squaring (Karatsuba)", 'mult.log' smooth bezier title "Multiplication (without Karatsuba)", 'mult_kara.log' smooth bezier title "Multiplication (Karatsuba)"
+
+set output "expt.png"
+plot 'expt.log' smooth bezier title "Exptmod (Montgomery)", 'expt_dr.log' smooth bezier title "Exptmod (Dimminished Radix)", 'expt_2k.log' smooth bezier title "Exptmod (2k Reduction)"
+
+set output "invmod.png"
+plot 'invmod.log' smooth bezier title "Modular Inverse"
+
diff --git a/libtommath/logs/index.html b/libtommath/logs/index.html
new file mode 100644
index 0000000..8c1ed9d
--- /dev/null
+++ b/libtommath/logs/index.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<title>LibTomMath Log Plots</title>
+</head>
+<body>
+
+<h1>Addition and Subtraction</h1>
+<center><img src=addsub.png></center>
+<hr>
+
+<h1>Multipliers</h1>
+<center><img src=mult.png></center>
+<hr>
+
+<h1>Exptmod</h1>
+<center><img src=expt.png></center>
+<hr>
+
+<h1>Modular Inverse</h1>
+<center><img src=invmod.png></center>
+<hr>
+
+</body>
+</html>
diff --git a/libtommath/logs/invmod.log b/libtommath/logs/invmod.log
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libtommath/logs/invmod.log
diff --git a/libtommath/logs/invmod.png b/libtommath/logs/invmod.png
new file mode 100644
index 0000000..9dcd7d8
--- /dev/null
+++ b/libtommath/logs/invmod.png
Binary files differ
diff --git a/libtommath/logs/mult.log b/libtommath/logs/mult.log
new file mode 100644
index 0000000..33563fc
--- /dev/null
+++ b/libtommath/logs/mult.log
@@ -0,0 +1,84 @@
+271 555
+390 855
+508 1161
+631 1605
+749 2117
+871 2687
+991 3329
+1108 4084
+1231 4786
+1351 5624
+1470 6392
+1586 7364
+1710 8218
+1830 9255
+1951 10217
+2067 11461
+2191 12463
+2308 13677
+2430 14800
+2551 16232
+2671 17460
+2791 18899
+2902 20247
+3028 21902
+3151 23240
+3267 24927
+3391 26441
+3511 28277
+3631 29838
+3749 31751
+3869 33673
+3989 35431
+4111 37518
+4231 39426
+4349 41504
+4471 43567
+4591 45786
+4711 47876
+4831 50299
+4951 52427
+5071 54785
+5189 57241
+5307 59730
+5431 62194
+5551 64761
+5670 67322
+5789 70073
+5907 72663
+6030 75437
+6151 78242
+6268 81202
+6389 83948
+6509 86985
+6631 89903
+6747 93184
+6869 96044
+6991 99286
+7109 102395
+7229 105917
+7351 108940
+7470 112490
+7589 115702
+7711 119508
+7831 122632
+7951 126410
+8071 129808
+8190 133895
+8311 137146
+8431 141218
+8549 144732
+8667 149131
+8790 152462
+8911 156754
+9030 160479
+9149 165138
+9271 168601
+9391 173185
+9511 176988
+9627 181976
+9751 185539
+9870 190388
+9991 194335
+10110 199605
+10228 203298
diff --git a/libtommath/logs/mult.png b/libtommath/logs/mult.png
new file mode 100644
index 0000000..d22e8c8
--- /dev/null
+++ b/libtommath/logs/mult.png
Binary files differ
diff --git a/libtommath/logs/mult_kara.log b/libtommath/logs/mult_kara.log
new file mode 100644
index 0000000..7136c79
--- /dev/null
+++ b/libtommath/logs/mult_kara.log
@@ -0,0 +1,84 @@
+271 560
+391 870
+511 1159
+631 1605
+750 2111
+871 2737
+991 3361
+1111 4054
+1231 4778
+1351 5600
+1471 6404
+1591 7323
+1710 8255
+1831 9239
+1948 10257
+2070 11397
+2190 12531
+2308 13665
+2429 14870
+2550 16175
+2671 17539
+2787 18879
+2911 20350
+3031 21807
+3150 23415
+3270 24897
+3388 26567
+3511 28205
+3627 30076
+3751 31744
+3869 33657
+3991 35425
+4111 37522
+4229 39363
+4351 41503
+4470 43491
+4590 45827
+4711 47795
+4828 50166
+4951 52318
+5070 54911
+5191 57036
+5308 58237
+5431 60248
+5551 62678
+5671 64786
+5791 67294
+5908 69343
+6031 71607
+6151 74166
+6271 76590
+6391 78734
+6511 81175
+6631 83742
+6750 86403
+6868 88873
+6990 91150
+7110 94211
+7228 96922
+7351 99445
+7469 102216
+7589 104968
+7711 108113
+7827 110758
+7950 113714
+8071 116511
+8186 119643
+8310 122679
+8425 125581
+8551 128715
+8669 131778
+8788 135116
+8910 138138
+9031 141628
+9148 144754
+9268 148367
+9391 151551
+9511 155033
+9631 158652
+9751 162125
+9871 165248
+9988 168627
+10111 172427
+10231 176412
diff --git a/libtommath/logs/sqr.log b/libtommath/logs/sqr.log
new file mode 100644
index 0000000..cd29fc5
--- /dev/null
+++ b/libtommath/logs/sqr.log
@@ -0,0 +1,84 @@
+265 562
+389 882
+509 1207
+631 1572
+750 1990
+859 2433
+991 2894
+1109 3555
+1230 4228
+1350 5018
+1471 5805
+1591 6579
+1709 7415
+1829 8329
+1949 9225
+2071 10139
+2188 11239
+2309 12178
+2431 13212
+2551 14294
+2671 15551
+2791 16512
+2911 17718
+3030 18876
+3150 20259
+3270 21374
+3391 22650
+3511 23948
+3631 25493
+3750 26756
+3870 28225
+3989 29705
+4110 31409
+4230 32834
+4351 34327
+4471 35818
+4591 37636
+4711 39228
+4830 40868
+4949 42393
+5070 44541
+5191 46269
+5310 48162
+5429 49728
+5548 51985
+5671 53948
+5791 55885
+5910 57584
+6031 60082
+6150 62239
+6270 64309
+6390 66014
+6511 68766
+6631 71012
+6750 73172
+6871 74952
+6991 77909
+7111 80371
+7231 82666
+7351 84531
+7469 87698
+7589 90318
+7711 225384
+7830 232428
+7950 240009
+8070 246522
+8190 253662
+8310 260961
+8431 269253
+8549 275743
+8671 283769
+8789 290811
+8911 300034
+9030 306873
+9149 315085
+9270 323944
+9390 332390
+9508 337519
+9631 348986
+9749 356904
+9871 367013
+9989 373831
+10108 381033
+10230 393475
diff --git a/libtommath/logs/sqr_kara.log b/libtommath/logs/sqr_kara.log
new file mode 100644
index 0000000..06355a7
--- /dev/null
+++ b/libtommath/logs/sqr_kara.log
@@ -0,0 +1,84 @@
+271 560
+388 878
+511 1179
+629 1625
+751 1988
+871 2423
+989 2896
+1111 3561
+1231 4209
+1350 5015
+1470 5804
+1591 6556
+1709 7420
+1831 8263
+1951 9173
+2070 10153
+2191 11229
+2310 12167
+2431 13211
+2550 14309
+2671 15524
+2788 16525
+2910 17712
+3028 18822
+3148 20220
+3271 21343
+3391 22652
+3511 23944
+3630 25485
+3750 26778
+3868 28201
+3990 29653
+4111 31393
+4225 32841
+4350 34328
+4471 35786
+4590 37652
+4711 39245
+4830 40876
+4951 42433
+5068 44547
+5191 46321
+5311 48140
+5430 49727
+5550 52034
+5671 53954
+5791 55921
+5908 57597
+6031 60084
+6148 62226
+6270 64295
+6390 66045
+6511 68779
+6629 71003
+6751 73169
+6871 74992
+6991 77895
+7110 80376
+7231 82628
+7351 84468
+7470 87664
+7591 90284
+7711 91352
+7828 93995
+7950 96276
+8071 98691
+8190 101256
+8308 103631
+8431 105222
+8550 108343
+8671 110281
+8787 112764
+8911 115397
+9031 117690
+9151 120266
+9271 122715
+9391 124624
+9510 127937
+9630 130313
+9750 132914
+9871 136129
+9991 138517
+10108 141525
+10231 144225
diff --git a/libtommath/logs/sub.log b/libtommath/logs/sub.log
new file mode 100644
index 0000000..9f84fa2
--- /dev/null
+++ b/libtommath/logs/sub.log
@@ -0,0 +1,16 @@
+480 94
+960 116
+1440 140
+1920 164
+2400 205
+2880 229
+3360 253
+3840 277
+4320 299
+4800 321
+5280 345
+5760 371
+6240 395
+6720 419
+7200 441
+7680 465
diff --git a/libtommath/makefile b/libtommath/makefile
new file mode 100644
index 0000000..70de306
--- /dev/null
+++ b/libtommath/makefile
@@ -0,0 +1,186 @@
+#Makefile for GCC
+#
+#Tom St Denis
+
+#version of library
+VERSION=0.42.0
+
+CFLAGS += -I./ -Wall -W -Wshadow -Wsign-compare
+
+ifndef MAKE
+ MAKE=make
+endif
+
+ifndef IGNORE_SPEED
+
+#for speed
+CFLAGS += -O3 -funroll-loops
+
+#for size
+#CFLAGS += -Os
+
+#x86 optimizations [should be valid for any GCC install though]
+CFLAGS += -fomit-frame-pointer
+
+#debug
+#CFLAGS += -g3
+
+endif
+
+#install as this user
+ifndef INSTALL_GROUP
+ GROUP=wheel
+else
+ GROUP=$(INSTALL_GROUP)
+endif
+
+ifndef INSTALL_USER
+ USER=root
+else
+ USER=$(INSTALL_USER)
+endif
+
+#default files to install
+ifndef LIBNAME
+ LIBNAME=libtommath.a
+endif
+
+default: ${LIBNAME}
+
+HEADERS=tommath.h tommath_class.h tommath_superclass.h
+
+#LIBPATH-The directory for libtommath to be installed to.
+#INCPATH-The directory to install the header files for libtommath.
+#DATAPATH-The directory to install the pdf docs.
+DESTDIR=
+LIBPATH=/usr/lib
+INCPATH=/usr/include
+DATAPATH=/usr/share/doc/libtommath/pdf
+
+OBJECTS=bncore.o bn_mp_init.o bn_mp_clear.o bn_mp_exch.o bn_mp_grow.o bn_mp_shrink.o \
+bn_mp_clamp.o bn_mp_zero.o bn_mp_set.o bn_mp_set_int.o bn_mp_init_size.o bn_mp_copy.o \
+bn_mp_init_copy.o bn_mp_abs.o bn_mp_neg.o bn_mp_cmp_mag.o bn_mp_cmp.o bn_mp_cmp_d.o \
+bn_mp_rshd.o bn_mp_lshd.o bn_mp_mod_2d.o bn_mp_div_2d.o bn_mp_mul_2d.o bn_mp_div_2.o \
+bn_mp_mul_2.o bn_s_mp_add.o bn_s_mp_sub.o bn_fast_s_mp_mul_digs.o bn_s_mp_mul_digs.o \
+bn_fast_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs.o bn_fast_s_mp_sqr.o bn_s_mp_sqr.o \
+bn_mp_add.o bn_mp_sub.o bn_mp_karatsuba_mul.o bn_mp_mul.o bn_mp_karatsuba_sqr.o \
+bn_mp_sqr.o bn_mp_div.o bn_mp_mod.o bn_mp_add_d.o bn_mp_sub_d.o bn_mp_mul_d.o \
+bn_mp_div_d.o bn_mp_mod_d.o bn_mp_expt_d.o bn_mp_addmod.o bn_mp_submod.o \
+bn_mp_mulmod.o bn_mp_sqrmod.o bn_mp_gcd.o bn_mp_lcm.o bn_fast_mp_invmod.o bn_mp_invmod.o \
+bn_mp_reduce.o bn_mp_montgomery_setup.o bn_fast_mp_montgomery_reduce.o bn_mp_montgomery_reduce.o \
+bn_mp_exptmod_fast.o bn_mp_exptmod.o bn_mp_2expt.o bn_mp_n_root.o bn_mp_jacobi.o bn_reverse.o \
+bn_mp_count_bits.o bn_mp_read_unsigned_bin.o bn_mp_read_signed_bin.o bn_mp_to_unsigned_bin.o \
+bn_mp_to_signed_bin.o bn_mp_unsigned_bin_size.o bn_mp_signed_bin_size.o \
+bn_mp_xor.o bn_mp_and.o bn_mp_or.o bn_mp_rand.o bn_mp_montgomery_calc_normalization.o \
+bn_mp_prime_is_divisible.o bn_prime_tab.o bn_mp_prime_fermat.o bn_mp_prime_miller_rabin.o \
+bn_mp_prime_is_prime.o bn_mp_prime_next_prime.o bn_mp_dr_reduce.o \
+bn_mp_dr_is_modulus.o bn_mp_dr_setup.o bn_mp_reduce_setup.o \
+bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_div_3.o bn_s_mp_exptmod.o \
+bn_mp_reduce_2k.o bn_mp_reduce_is_2k.o bn_mp_reduce_2k_setup.o \
+bn_mp_reduce_2k_l.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_2k_setup_l.o \
+bn_mp_radix_smap.o bn_mp_read_radix.o bn_mp_toradix.o bn_mp_radix_size.o \
+bn_mp_fread.o bn_mp_fwrite.o bn_mp_cnt_lsb.o bn_error.o \
+bn_mp_init_multi.o bn_mp_clear_multi.o bn_mp_exteuclid.o bn_mp_toradix_n.o \
+bn_mp_prime_random_ex.o bn_mp_get_int.o bn_mp_sqrt.o bn_mp_is_square.o bn_mp_init_set.o \
+bn_mp_init_set_int.o bn_mp_invmod_slow.o bn_mp_prime_rabin_miller_trials.o \
+bn_mp_to_signed_bin_n.o bn_mp_to_unsigned_bin_n.o
+
+$(LIBNAME): $(OBJECTS)
+ $(AR) $(ARFLAGS) $@ $(OBJECTS)
+ ranlib $@
+
+#make a profiled library (takes a while!!!)
+#
+# This will build the library with profile generation
+# then run the test demo and rebuild the library.
+#
+# So far I've seen improvements in the MP math
+profiled:
+ make CFLAGS="$(CFLAGS) -fprofile-arcs -DTESTING" timing
+ ./ltmtest
+ rm -f *.a *.o ltmtest
+ make CFLAGS="$(CFLAGS) -fbranch-probabilities"
+
+#make a single object profiled library
+profiled_single:
+ perl gen.pl
+ $(CC) $(CFLAGS) -fprofile-arcs -DTESTING -c mpi.c -o mpi.o
+ $(CC) $(CFLAGS) -DTESTING -DTIMER demo/timing.c mpi.o -o ltmtest
+ ./ltmtest
+ rm -f *.o ltmtest
+ $(CC) $(CFLAGS) -fbranch-probabilities -DTESTING -c mpi.c -o mpi.o
+ $(AR) $(ARFLAGS) $(LIBNAME) mpi.o
+ ranlib $(LIBNAME)
+
+install: $(LIBNAME)
+ install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(LIBPATH)
+ install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(INCPATH)
+ install -g $(GROUP) -o $(USER) $(LIBNAME) $(DESTDIR)$(LIBPATH)
+ install -g $(GROUP) -o $(USER) $(HEADERS) $(DESTDIR)$(INCPATH)
+
+test: $(LIBNAME) demo/demo.o
+ $(CC) $(CFLAGS) demo/demo.o $(LIBNAME) -o test
+
+mtest: test
+ cd mtest ; $(CC) $(CFLAGS) mtest.c -o mtest
+
+timing: $(LIBNAME)
+ $(CC) $(CFLAGS) -DTIMER demo/timing.c $(LIBNAME) -o ltmtest
+
+# makes the LTM book DVI file, requires tetex, perl and makeindex [part of tetex I think]
+docdvi: tommath.src
+ cd pics ; MAKE=${MAKE} ${MAKE}
+ echo "hello" > tommath.ind
+ perl booker.pl
+ latex tommath > /dev/null
+ latex tommath > /dev/null
+ makeindex tommath
+ latex tommath > /dev/null
+
+# poster, makes the single page PDF poster
+poster: poster.tex
+ pdflatex poster
+ rm -f poster.aux poster.log
+
+# makes the LTM book PDF file, requires tetex, cleans up the LaTeX temp files
+docs: docdvi
+ dvipdf tommath
+ rm -f tommath.log tommath.aux tommath.dvi tommath.idx tommath.toc tommath.lof tommath.ind tommath.ilg
+ cd pics ; MAKE=${MAKE} ${MAKE} clean
+
+#LTM user manual
+mandvi: bn.tex
+ echo "hello" > bn.ind
+ latex bn > /dev/null
+ latex bn > /dev/null
+ makeindex bn
+ latex bn > /dev/null
+
+#LTM user manual [pdf]
+manual: mandvi
+ pdflatex bn >/dev/null
+ rm -f bn.aux bn.dvi bn.log bn.idx bn.lof bn.out bn.toc
+
+pretty:
+ perl pretty.build
+
+clean:
+ rm -f *.bat *.pdf *.o *.a *.obj *.lib *.exe *.dll etclib/*.o demo/demo.o test ltmtest mpitest mtest/mtest mtest/mtest.exe \
+ *.idx *.toc *.log *.aux *.dvi *.lof *.ind *.ilg *.ps *.log *.s mpi.c *.da *.dyn *.dpi tommath.tex `find . -type f | grep [~] | xargs` *.lo *.la
+ rm -rf .libs
+ cd etc ; MAKE=${MAKE} ${MAKE} clean
+ cd pics ; MAKE=${MAKE} ${MAKE} clean
+
+#zipup the project (take that!)
+no_oops: clean
+ cd .. ; cvs commit
+ echo Scanning for scratch/dirty files
+ find . -type f | grep -v CVS | xargs -n 1 bash mess.sh
+
+zipup: clean manual poster docs
+ perl gen.pl ; mv mpi.c pre_gen/ ; \
+ cd .. ; rm -rf ltm* libtommath-$(VERSION) ; mkdir libtommath-$(VERSION) ; \
+ cp -R ./libtommath/* ./libtommath-$(VERSION)/ ; \
+ tar -c libtommath-$(VERSION)/* | bzip2 -9vvc > ltm-$(VERSION).tar.bz2 ; \
+ zip -9 -r ltm-$(VERSION).zip libtommath-$(VERSION)/* ; \
+ mv -f ltm* ~ ; rm -rf libtommath-$(VERSION)
diff --git a/libtommath/makefile.bcc b/libtommath/makefile.bcc
new file mode 100644
index 0000000..67743d9
--- /dev/null
+++ b/libtommath/makefile.bcc
@@ -0,0 +1,44 @@
+#
+# Borland C++Builder Makefile (makefile.bcc)
+#
+
+
+LIB = tlib
+CC = bcc32
+CFLAGS = -c -O2 -I.
+
+OBJECTS=bncore.obj bn_mp_init.obj bn_mp_clear.obj bn_mp_exch.obj bn_mp_grow.obj bn_mp_shrink.obj \
+bn_mp_clamp.obj bn_mp_zero.obj bn_mp_set.obj bn_mp_set_int.obj bn_mp_init_size.obj bn_mp_copy.obj \
+bn_mp_init_copy.obj bn_mp_abs.obj bn_mp_neg.obj bn_mp_cmp_mag.obj bn_mp_cmp.obj bn_mp_cmp_d.obj \
+bn_mp_rshd.obj bn_mp_lshd.obj bn_mp_mod_2d.obj bn_mp_div_2d.obj bn_mp_mul_2d.obj bn_mp_div_2.obj \
+bn_mp_mul_2.obj bn_s_mp_add.obj bn_s_mp_sub.obj bn_fast_s_mp_mul_digs.obj bn_s_mp_mul_digs.obj \
+bn_fast_s_mp_mul_high_digs.obj bn_s_mp_mul_high_digs.obj bn_fast_s_mp_sqr.obj bn_s_mp_sqr.obj \
+bn_mp_add.obj bn_mp_sub.obj bn_mp_karatsuba_mul.obj bn_mp_mul.obj bn_mp_karatsuba_sqr.obj \
+bn_mp_sqr.obj bn_mp_div.obj bn_mp_mod.obj bn_mp_add_d.obj bn_mp_sub_d.obj bn_mp_mul_d.obj \
+bn_mp_div_d.obj bn_mp_mod_d.obj bn_mp_expt_d.obj bn_mp_addmod.obj bn_mp_submod.obj \
+bn_mp_mulmod.obj bn_mp_sqrmod.obj bn_mp_gcd.obj bn_mp_lcm.obj bn_fast_mp_invmod.obj bn_mp_invmod.obj \
+bn_mp_reduce.obj bn_mp_montgomery_setup.obj bn_fast_mp_montgomery_reduce.obj bn_mp_montgomery_reduce.obj \
+bn_mp_exptmod_fast.obj bn_mp_exptmod.obj bn_mp_2expt.obj bn_mp_n_root.obj bn_mp_jacobi.obj bn_reverse.obj \
+bn_mp_count_bits.obj bn_mp_read_unsigned_bin.obj bn_mp_read_signed_bin.obj bn_mp_to_unsigned_bin.obj \
+bn_mp_to_signed_bin.obj bn_mp_unsigned_bin_size.obj bn_mp_signed_bin_size.obj \
+bn_mp_xor.obj bn_mp_and.obj bn_mp_or.obj bn_mp_rand.obj bn_mp_montgomery_calc_normalization.obj \
+bn_mp_prime_is_divisible.obj bn_prime_tab.obj bn_mp_prime_fermat.obj bn_mp_prime_miller_rabin.obj \
+bn_mp_prime_is_prime.obj bn_mp_prime_next_prime.obj bn_mp_dr_reduce.obj \
+bn_mp_dr_is_modulus.obj bn_mp_dr_setup.obj bn_mp_reduce_setup.obj \
+bn_mp_toom_mul.obj bn_mp_toom_sqr.obj bn_mp_div_3.obj bn_s_mp_exptmod.obj \
+bn_mp_reduce_2k.obj bn_mp_reduce_is_2k.obj bn_mp_reduce_2k_setup.obj \
+bn_mp_reduce_2k_l.obj bn_mp_reduce_is_2k_l.obj bn_mp_reduce_2k_setup_l.obj \
+bn_mp_radix_smap.obj bn_mp_read_radix.obj bn_mp_toradix.obj bn_mp_radix_size.obj \
+bn_mp_fread.obj bn_mp_fwrite.obj bn_mp_cnt_lsb.obj bn_error.obj \
+bn_mp_init_multi.obj bn_mp_clear_multi.obj bn_mp_exteuclid.obj bn_mp_toradix_n.obj \
+bn_mp_prime_random_ex.obj bn_mp_get_int.obj bn_mp_sqrt.obj bn_mp_is_square.obj \
+bn_mp_init_set.obj bn_mp_init_set_int.obj bn_mp_invmod_slow.obj bn_mp_prime_rabin_miller_trials.obj \
+bn_mp_to_signed_bin_n.obj bn_mp_to_unsigned_bin_n.obj
+
+TARGET = libtommath.lib
+
+$(TARGET): $(OBJECTS)
+
+.c.obj:
+ $(CC) $(CFLAGS) $<
+ $(LIB) $(TARGET) -+$@
diff --git a/libtommath/makefile.cygwin_dll b/libtommath/makefile.cygwin_dll
new file mode 100644
index 0000000..85b10c7
--- /dev/null
+++ b/libtommath/makefile.cygwin_dll
@@ -0,0 +1,51 @@
+#Makefile for Cygwin-GCC
+#
+#This makefile will build a Windows DLL [doesn't require cygwin to run] in the file
+#libtommath.dll. The import library is in libtommath.dll.a. Remember to add
+#"-Wl,--enable-auto-import" to your client build to avoid the auto-import warnings
+#
+#Tom St Denis
+CFLAGS += -I./ -Wall -W -Wshadow -O3 -funroll-loops -mno-cygwin
+
+#x86 optimizations [should be valid for any GCC install though]
+CFLAGS += -fomit-frame-pointer
+
+default: windll
+
+OBJECTS=bncore.o bn_mp_init.o bn_mp_clear.o bn_mp_exch.o bn_mp_grow.o bn_mp_shrink.o \
+bn_mp_clamp.o bn_mp_zero.o bn_mp_set.o bn_mp_set_int.o bn_mp_init_size.o bn_mp_copy.o \
+bn_mp_init_copy.o bn_mp_abs.o bn_mp_neg.o bn_mp_cmp_mag.o bn_mp_cmp.o bn_mp_cmp_d.o \
+bn_mp_rshd.o bn_mp_lshd.o bn_mp_mod_2d.o bn_mp_div_2d.o bn_mp_mul_2d.o bn_mp_div_2.o \
+bn_mp_mul_2.o bn_s_mp_add.o bn_s_mp_sub.o bn_fast_s_mp_mul_digs.o bn_s_mp_mul_digs.o \
+bn_fast_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs.o bn_fast_s_mp_sqr.o bn_s_mp_sqr.o \
+bn_mp_add.o bn_mp_sub.o bn_mp_karatsuba_mul.o bn_mp_mul.o bn_mp_karatsuba_sqr.o \
+bn_mp_sqr.o bn_mp_div.o bn_mp_mod.o bn_mp_add_d.o bn_mp_sub_d.o bn_mp_mul_d.o \
+bn_mp_div_d.o bn_mp_mod_d.o bn_mp_expt_d.o bn_mp_addmod.o bn_mp_submod.o \
+bn_mp_mulmod.o bn_mp_sqrmod.o bn_mp_gcd.o bn_mp_lcm.o bn_fast_mp_invmod.o bn_mp_invmod.o \
+bn_mp_reduce.o bn_mp_montgomery_setup.o bn_fast_mp_montgomery_reduce.o bn_mp_montgomery_reduce.o \
+bn_mp_exptmod_fast.o bn_mp_exptmod.o bn_mp_2expt.o bn_mp_n_root.o bn_mp_jacobi.o bn_reverse.o \
+bn_mp_count_bits.o bn_mp_read_unsigned_bin.o bn_mp_read_signed_bin.o bn_mp_to_unsigned_bin.o \
+bn_mp_to_signed_bin.o bn_mp_unsigned_bin_size.o bn_mp_signed_bin_size.o \
+bn_mp_xor.o bn_mp_and.o bn_mp_or.o bn_mp_rand.o bn_mp_montgomery_calc_normalization.o \
+bn_mp_prime_is_divisible.o bn_prime_tab.o bn_mp_prime_fermat.o bn_mp_prime_miller_rabin.o \
+bn_mp_prime_is_prime.o bn_mp_prime_next_prime.o bn_mp_dr_reduce.o \
+bn_mp_dr_is_modulus.o bn_mp_dr_setup.o bn_mp_reduce_setup.o \
+bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_div_3.o bn_s_mp_exptmod.o \
+bn_mp_reduce_2k.o bn_mp_reduce_is_2k.o bn_mp_reduce_2k_setup.o \
+bn_mp_reduce_2k_l.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_2k_setup_l.o \
+bn_mp_radix_smap.o bn_mp_read_radix.o bn_mp_toradix.o bn_mp_radix_size.o \
+bn_mp_fread.o bn_mp_fwrite.o bn_mp_cnt_lsb.o bn_error.o \
+bn_mp_init_multi.o bn_mp_clear_multi.o bn_mp_exteuclid.o bn_mp_toradix_n.o \
+bn_mp_prime_random_ex.o bn_mp_get_int.o bn_mp_sqrt.o bn_mp_is_square.o bn_mp_init_set.o \
+bn_mp_init_set_int.o bn_mp_invmod_slow.o bn_mp_prime_rabin_miller_trials.o \
+bn_mp_to_signed_bin_n.o bn_mp_to_unsigned_bin_n.o
+
+# make a Windows DLL via Cygwin
+windll: $(OBJECTS)
+ gcc -mno-cygwin -mdll -o libtommath.dll -Wl,--out-implib=libtommath.dll.a -Wl,--export-all-symbols *.o
+ ranlib libtommath.dll.a
+
+# build the test program using the windows DLL
+test: $(OBJECTS) windll
+ gcc $(CFLAGS) demo/demo.c libtommath.dll.a -Wl,--enable-auto-import -o test -s
+ cd mtest ; $(CC) -O3 -fomit-frame-pointer -funroll-loops mtest.c -o mtest -s
diff --git a/libtommath/makefile.icc b/libtommath/makefile.icc
new file mode 100644
index 0000000..cf70ab0
--- /dev/null
+++ b/libtommath/makefile.icc
@@ -0,0 +1,116 @@
+#Makefile for ICC
+#
+#Tom St Denis
+CC=icc
+
+CFLAGS += -I./
+
+# optimize for SPEED
+#
+# -mcpu= can be pentium, pentiumpro (covers PII through PIII) or pentium4
+# -ax? specifies make code specifically for ? but compatible with IA-32
+# -x? specifies compile solely for ? [not specifically IA-32 compatible]
+#
+# where ? is
+# K - PIII
+# W - first P4 [Williamette]
+# N - P4 Northwood
+# P - P4 Prescott
+# B - Blend of P4 and PM [mobile]
+#
+# Default to just generic max opts
+CFLAGS += -O3 -xP -ip
+
+#install as this user
+USER=root
+GROUP=root
+
+default: libtommath.a
+
+#default files to install
+LIBNAME=libtommath.a
+HEADERS=tommath.h
+
+#LIBPATH-The directory for libtomcrypt to be installed to.
+#INCPATH-The directory to install the header files for libtommath.
+#DATAPATH-The directory to install the pdf docs.
+DESTDIR=
+LIBPATH=/usr/lib
+INCPATH=/usr/include
+DATAPATH=/usr/share/doc/libtommath/pdf
+
+OBJECTS=bncore.o bn_mp_init.o bn_mp_clear.o bn_mp_exch.o bn_mp_grow.o bn_mp_shrink.o \
+bn_mp_clamp.o bn_mp_zero.o bn_mp_set.o bn_mp_set_int.o bn_mp_init_size.o bn_mp_copy.o \
+bn_mp_init_copy.o bn_mp_abs.o bn_mp_neg.o bn_mp_cmp_mag.o bn_mp_cmp.o bn_mp_cmp_d.o \
+bn_mp_rshd.o bn_mp_lshd.o bn_mp_mod_2d.o bn_mp_div_2d.o bn_mp_mul_2d.o bn_mp_div_2.o \
+bn_mp_mul_2.o bn_s_mp_add.o bn_s_mp_sub.o bn_fast_s_mp_mul_digs.o bn_s_mp_mul_digs.o \
+bn_fast_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs.o bn_fast_s_mp_sqr.o bn_s_mp_sqr.o \
+bn_mp_add.o bn_mp_sub.o bn_mp_karatsuba_mul.o bn_mp_mul.o bn_mp_karatsuba_sqr.o \
+bn_mp_sqr.o bn_mp_div.o bn_mp_mod.o bn_mp_add_d.o bn_mp_sub_d.o bn_mp_mul_d.o \
+bn_mp_div_d.o bn_mp_mod_d.o bn_mp_expt_d.o bn_mp_addmod.o bn_mp_submod.o \
+bn_mp_mulmod.o bn_mp_sqrmod.o bn_mp_gcd.o bn_mp_lcm.o bn_fast_mp_invmod.o bn_mp_invmod.o \
+bn_mp_reduce.o bn_mp_montgomery_setup.o bn_fast_mp_montgomery_reduce.o bn_mp_montgomery_reduce.o \
+bn_mp_exptmod_fast.o bn_mp_exptmod.o bn_mp_2expt.o bn_mp_n_root.o bn_mp_jacobi.o bn_reverse.o \
+bn_mp_count_bits.o bn_mp_read_unsigned_bin.o bn_mp_read_signed_bin.o bn_mp_to_unsigned_bin.o \
+bn_mp_to_signed_bin.o bn_mp_unsigned_bin_size.o bn_mp_signed_bin_size.o \
+bn_mp_xor.o bn_mp_and.o bn_mp_or.o bn_mp_rand.o bn_mp_montgomery_calc_normalization.o \
+bn_mp_prime_is_divisible.o bn_prime_tab.o bn_mp_prime_fermat.o bn_mp_prime_miller_rabin.o \
+bn_mp_prime_is_prime.o bn_mp_prime_next_prime.o bn_mp_dr_reduce.o \
+bn_mp_dr_is_modulus.o bn_mp_dr_setup.o bn_mp_reduce_setup.o \
+bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_div_3.o bn_s_mp_exptmod.o \
+bn_mp_reduce_2k.o bn_mp_reduce_is_2k.o bn_mp_reduce_2k_setup.o \
+bn_mp_reduce_2k_l.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_2k_setup_l.o \
+bn_mp_radix_smap.o bn_mp_read_radix.o bn_mp_toradix.o bn_mp_radix_size.o \
+bn_mp_fread.o bn_mp_fwrite.o bn_mp_cnt_lsb.o bn_error.o \
+bn_mp_init_multi.o bn_mp_clear_multi.o bn_mp_exteuclid.o bn_mp_toradix_n.o \
+bn_mp_prime_random_ex.o bn_mp_get_int.o bn_mp_sqrt.o bn_mp_is_square.o bn_mp_init_set.o \
+bn_mp_init_set_int.o bn_mp_invmod_slow.o bn_mp_prime_rabin_miller_trials.o \
+bn_mp_to_signed_bin_n.o bn_mp_to_unsigned_bin_n.o
+
+libtommath.a: $(OBJECTS)
+ $(AR) $(ARFLAGS) libtommath.a $(OBJECTS)
+ ranlib libtommath.a
+
+#make a profiled library (takes a while!!!)
+#
+# This will build the library with profile generation
+# then run the test demo and rebuild the library.
+#
+# So far I've seen improvements in the MP math
+profiled:
+ make -f makefile.icc CFLAGS="$(CFLAGS) -prof_gen -DTESTING" timing
+ ./ltmtest
+ rm -f *.a *.o ltmtest
+ make -f makefile.icc CFLAGS="$(CFLAGS) -prof_use"
+
+#make a single object profiled library
+profiled_single:
+ perl gen.pl
+ $(CC) $(CFLAGS) -prof_gen -DTESTING -c mpi.c -o mpi.o
+ $(CC) $(CFLAGS) -DTESTING -DTIMER demo/demo.c mpi.o -o ltmtest
+ ./ltmtest
+ rm -f *.o ltmtest
+ $(CC) $(CFLAGS) -prof_use -ip -DTESTING -c mpi.c -o mpi.o
+ $(AR) $(ARFLAGS) libtommath.a mpi.o
+ ranlib libtommath.a
+
+install: libtommath.a
+ install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(LIBPATH)
+ install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(INCPATH)
+ install -g $(GROUP) -o $(USER) $(LIBNAME) $(DESTDIR)$(LIBPATH)
+ install -g $(GROUP) -o $(USER) $(HEADERS) $(DESTDIR)$(INCPATH)
+
+test: libtommath.a demo/demo.o
+ $(CC) demo/demo.o libtommath.a -o test
+
+mtest: test
+ cd mtest ; $(CC) $(CFLAGS) mtest.c -o mtest
+
+timing: libtommath.a
+ $(CC) $(CFLAGS) -DTIMER demo/timing.c libtommath.a -o ltmtest
+
+clean:
+ rm -f *.bat *.pdf *.o *.a *.obj *.lib *.exe *.dll etclib/*.o demo/demo.o test ltmtest mpitest mtest/mtest mtest/mtest.exe \
+ *.idx *.toc *.log *.aux *.dvi *.lof *.ind *.ilg *.ps *.log *.s mpi.c *.il etc/*.il *.dyn
+ cd etc ; make clean
+ cd pics ; make clean
diff --git a/libtommath/makefile.msvc b/libtommath/makefile.msvc
new file mode 100644
index 0000000..5edebec
--- /dev/null
+++ b/libtommath/makefile.msvc
@@ -0,0 +1,40 @@
+#MSVC Makefile
+#
+#Tom St Denis
+
+CFLAGS = /I. /Ox /DWIN32 /W3 /Fo$@
+
+default: library
+
+OBJECTS=bncore.obj bn_mp_init.obj bn_mp_clear.obj bn_mp_exch.obj bn_mp_grow.obj bn_mp_shrink.obj \
+bn_mp_clamp.obj bn_mp_zero.obj bn_mp_set.obj bn_mp_set_int.obj bn_mp_init_size.obj bn_mp_copy.obj \
+bn_mp_init_copy.obj bn_mp_abs.obj bn_mp_neg.obj bn_mp_cmp_mag.obj bn_mp_cmp.obj bn_mp_cmp_d.obj \
+bn_mp_rshd.obj bn_mp_lshd.obj bn_mp_mod_2d.obj bn_mp_div_2d.obj bn_mp_mul_2d.obj bn_mp_div_2.obj \
+bn_mp_mul_2.obj bn_s_mp_add.obj bn_s_mp_sub.obj bn_fast_s_mp_mul_digs.obj bn_s_mp_mul_digs.obj \
+bn_fast_s_mp_mul_high_digs.obj bn_s_mp_mul_high_digs.obj bn_fast_s_mp_sqr.obj bn_s_mp_sqr.obj \
+bn_mp_add.obj bn_mp_sub.obj bn_mp_karatsuba_mul.obj bn_mp_mul.obj bn_mp_karatsuba_sqr.obj \
+bn_mp_sqr.obj bn_mp_div.obj bn_mp_mod.obj bn_mp_add_d.obj bn_mp_sub_d.obj bn_mp_mul_d.obj \
+bn_mp_div_d.obj bn_mp_mod_d.obj bn_mp_expt_d.obj bn_mp_addmod.obj bn_mp_submod.obj \
+bn_mp_mulmod.obj bn_mp_sqrmod.obj bn_mp_gcd.obj bn_mp_lcm.obj bn_fast_mp_invmod.obj bn_mp_invmod.obj \
+bn_mp_reduce.obj bn_mp_montgomery_setup.obj bn_fast_mp_montgomery_reduce.obj bn_mp_montgomery_reduce.obj \
+bn_mp_exptmod_fast.obj bn_mp_exptmod.obj bn_mp_2expt.obj bn_mp_n_root.obj bn_mp_jacobi.obj bn_reverse.obj \
+bn_mp_count_bits.obj bn_mp_read_unsigned_bin.obj bn_mp_read_signed_bin.obj bn_mp_to_unsigned_bin.obj \
+bn_mp_to_signed_bin.obj bn_mp_unsigned_bin_size.obj bn_mp_signed_bin_size.obj \
+bn_mp_xor.obj bn_mp_and.obj bn_mp_or.obj bn_mp_rand.obj bn_mp_montgomery_calc_normalization.obj \
+bn_mp_prime_is_divisible.obj bn_prime_tab.obj bn_mp_prime_fermat.obj bn_mp_prime_miller_rabin.obj \
+bn_mp_prime_is_prime.obj bn_mp_prime_next_prime.obj bn_mp_dr_reduce.obj \
+bn_mp_dr_is_modulus.obj bn_mp_dr_setup.obj bn_mp_reduce_setup.obj \
+bn_mp_toom_mul.obj bn_mp_toom_sqr.obj bn_mp_div_3.obj bn_s_mp_exptmod.obj \
+bn_mp_reduce_2k.obj bn_mp_reduce_is_2k.obj bn_mp_reduce_2k_setup.obj \
+bn_mp_reduce_2k_l.obj bn_mp_reduce_is_2k_l.obj bn_mp_reduce_2k_setup_l.obj \
+bn_mp_radix_smap.obj bn_mp_read_radix.obj bn_mp_toradix.obj bn_mp_radix_size.obj \
+bn_mp_fread.obj bn_mp_fwrite.obj bn_mp_cnt_lsb.obj bn_error.obj \
+bn_mp_init_multi.obj bn_mp_clear_multi.obj bn_mp_exteuclid.obj bn_mp_toradix_n.obj \
+bn_mp_prime_random_ex.obj bn_mp_get_int.obj bn_mp_sqrt.obj bn_mp_is_square.obj \
+bn_mp_init_set.obj bn_mp_init_set_int.obj bn_mp_invmod_slow.obj bn_mp_prime_rabin_miller_trials.obj \
+bn_mp_to_signed_bin_n.obj bn_mp_to_unsigned_bin_n.obj
+
+HEADERS=tommath.h tommath_class.h tommath_superclass.h
+
+library: $(OBJECTS)
+ lib /out:tommath.lib $(OBJECTS)
diff --git a/libtommath/makefile.shared b/libtommath/makefile.shared
new file mode 100644
index 0000000..f17bbbd
--- /dev/null
+++ b/libtommath/makefile.shared
@@ -0,0 +1,102 @@
+#Makefile for GCC
+#
+#Tom St Denis
+VERSION=0:41
+
+CC = libtool --mode=compile --tag=CC gcc
+
+CFLAGS += -I./ -Wall -W -Wshadow -Wsign-compare
+
+ifndef IGNORE_SPEED
+
+#for speed
+CFLAGS += -O3 -funroll-loops
+
+#for size
+#CFLAGS += -Os
+
+#x86 optimizations [should be valid for any GCC install though]
+CFLAGS += -fomit-frame-pointer
+
+endif
+
+#install as this user
+ifndef INSTALL_GROUP
+ GROUP=wheel
+else
+ GROUP=$(INSTALL_GROUP)
+endif
+
+ifndef INSTALL_USER
+ USER=root
+else
+ USER=$(INSTALL_USER)
+endif
+
+default: libtommath.la
+
+#default files to install
+ifndef LIBNAME
+ LIBNAME=libtommath.la
+endif
+ifndef LIBNAME_S
+ LIBNAME_S=libtommath.a
+endif
+HEADERS=tommath.h tommath_class.h tommath_superclass.h
+
+#LIBPATH-The directory for libtommath to be installed to.
+#INCPATH-The directory to install the header files for libtommath.
+#DATAPATH-The directory to install the pdf docs.
+DESTDIR=
+LIBPATH=/usr/lib
+INCPATH=/usr/include
+DATAPATH=/usr/share/doc/libtommath/pdf
+
+OBJECTS=bncore.o bn_mp_init.o bn_mp_clear.o bn_mp_exch.o bn_mp_grow.o bn_mp_shrink.o \
+bn_mp_clamp.o bn_mp_zero.o bn_mp_set.o bn_mp_set_int.o bn_mp_init_size.o bn_mp_copy.o \
+bn_mp_init_copy.o bn_mp_abs.o bn_mp_neg.o bn_mp_cmp_mag.o bn_mp_cmp.o bn_mp_cmp_d.o \
+bn_mp_rshd.o bn_mp_lshd.o bn_mp_mod_2d.o bn_mp_div_2d.o bn_mp_mul_2d.o bn_mp_div_2.o \
+bn_mp_mul_2.o bn_s_mp_add.o bn_s_mp_sub.o bn_fast_s_mp_mul_digs.o bn_s_mp_mul_digs.o \
+bn_fast_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs.o bn_fast_s_mp_sqr.o bn_s_mp_sqr.o \
+bn_mp_add.o bn_mp_sub.o bn_mp_karatsuba_mul.o bn_mp_mul.o bn_mp_karatsuba_sqr.o \
+bn_mp_sqr.o bn_mp_div.o bn_mp_mod.o bn_mp_add_d.o bn_mp_sub_d.o bn_mp_mul_d.o \
+bn_mp_div_d.o bn_mp_mod_d.o bn_mp_expt_d.o bn_mp_addmod.o bn_mp_submod.o \
+bn_mp_mulmod.o bn_mp_sqrmod.o bn_mp_gcd.o bn_mp_lcm.o bn_fast_mp_invmod.o bn_mp_invmod.o \
+bn_mp_reduce.o bn_mp_montgomery_setup.o bn_fast_mp_montgomery_reduce.o bn_mp_montgomery_reduce.o \
+bn_mp_exptmod_fast.o bn_mp_exptmod.o bn_mp_2expt.o bn_mp_n_root.o bn_mp_jacobi.o bn_reverse.o \
+bn_mp_count_bits.o bn_mp_read_unsigned_bin.o bn_mp_read_signed_bin.o bn_mp_to_unsigned_bin.o \
+bn_mp_to_signed_bin.o bn_mp_unsigned_bin_size.o bn_mp_signed_bin_size.o \
+bn_mp_xor.o bn_mp_and.o bn_mp_or.o bn_mp_rand.o bn_mp_montgomery_calc_normalization.o \
+bn_mp_prime_is_divisible.o bn_prime_tab.o bn_mp_prime_fermat.o bn_mp_prime_miller_rabin.o \
+bn_mp_prime_is_prime.o bn_mp_prime_next_prime.o bn_mp_dr_reduce.o \
+bn_mp_dr_is_modulus.o bn_mp_dr_setup.o bn_mp_reduce_setup.o \
+bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_div_3.o bn_s_mp_exptmod.o \
+bn_mp_reduce_2k.o bn_mp_reduce_is_2k.o bn_mp_reduce_2k_setup.o \
+bn_mp_reduce_2k_l.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_2k_setup_l.o \
+bn_mp_radix_smap.o bn_mp_read_radix.o bn_mp_toradix.o bn_mp_radix_size.o \
+bn_mp_fread.o bn_mp_fwrite.o bn_mp_cnt_lsb.o bn_error.o \
+bn_mp_init_multi.o bn_mp_clear_multi.o bn_mp_exteuclid.o bn_mp_toradix_n.o \
+bn_mp_prime_random_ex.o bn_mp_get_int.o bn_mp_sqrt.o bn_mp_is_square.o bn_mp_init_set.o \
+bn_mp_init_set_int.o bn_mp_invmod_slow.o bn_mp_prime_rabin_miller_trials.o \
+bn_mp_to_signed_bin_n.o bn_mp_to_unsigned_bin_n.o
+
+objs: $(OBJECTS)
+
+$(LIBNAME): $(OBJECTS)
+ libtool --mode=link gcc *.lo -o $(LIBNAME) -rpath $(LIBPATH) -version-info $(VERSION)
+
+install: $(LIBNAME)
+ install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(LIBPATH)
+ libtool --mode=install install -c $(LIBNAME) $(DESTDIR)$(LIBPATH)/$(LIBNAME)
+ install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(INCPATH)
+ install -g $(GROUP) -o $(USER) $(HEADERS) $(DESTDIR)$(INCPATH)
+
+test: $(LIBNAME) demo/demo.o
+ gcc $(CFLAGS) -c demo/demo.c -o demo/demo.o
+ libtool --mode=link gcc -o test demo/demo.o $(LIBNAME_S)
+
+mtest: test
+ cd mtest ; gcc $(CFLAGS) mtest.c -o mtest
+
+timing: $(LIBNAME)
+ gcc $(CFLAGS) -DTIMER demo/timing.c $(LIBNAME_S) -o ltmtest
diff --git a/libtommath/mess.sh b/libtommath/mess.sh
new file mode 100644
index 0000000..bf639ce
--- /dev/null
+++ b/libtommath/mess.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+if cvs log $1 >/dev/null 2>/dev/null; then exit 0; else echo "$1 shouldn't be here" ; exit 1; fi
+
+
diff --git a/libtommath/mtest/logtab.h b/libtommath/mtest/logtab.h
new file mode 100644
index 0000000..addd3ab
--- /dev/null
+++ b/libtommath/mtest/logtab.h
@@ -0,0 +1,19 @@
+const float s_logv_2[] = {
+ 0.000000000, 0.000000000, 1.000000000, 0.630929754, /* 0 1 2 3 */
+ 0.500000000, 0.430676558, 0.386852807, 0.356207187, /* 4 5 6 7 */
+ 0.333333333, 0.315464877, 0.301029996, 0.289064826, /* 8 9 10 11 */
+ 0.278942946, 0.270238154, 0.262649535, 0.255958025, /* 12 13 14 15 */
+ 0.250000000, 0.244650542, 0.239812467, 0.235408913, /* 16 17 18 19 */
+ 0.231378213, 0.227670249, 0.224243824, 0.221064729, /* 20 21 22 23 */
+ 0.218104292, 0.215338279, 0.212746054, 0.210309918, /* 24 25 26 27 */
+ 0.208014598, 0.205846832, 0.203795047, 0.201849087, /* 28 29 30 31 */
+ 0.200000000, 0.198239863, 0.196561632, 0.194959022, /* 32 33 34 35 */
+ 0.193426404, 0.191958720, 0.190551412, 0.189200360, /* 36 37 38 39 */
+ 0.187901825, 0.186652411, 0.185449023, 0.184288833, /* 40 41 42 43 */
+ 0.183169251, 0.182087900, 0.181042597, 0.180031327, /* 44 45 46 47 */
+ 0.179052232, 0.178103594, 0.177183820, 0.176291434, /* 48 49 50 51 */
+ 0.175425064, 0.174583430, 0.173765343, 0.172969690, /* 52 53 54 55 */
+ 0.172195434, 0.171441601, 0.170707280, 0.169991616, /* 56 57 58 59 */
+ 0.169293808, 0.168613099, 0.167948779, 0.167300179, /* 60 61 62 63 */
+ 0.166666667
+};
diff --git a/libtommath/mtest/mpi-config.h b/libtommath/mtest/mpi-config.h
new file mode 100644
index 0000000..a347263
--- /dev/null
+++ b/libtommath/mtest/mpi-config.h
@@ -0,0 +1,85 @@
+/* Default configuration for MPI library */
+
+#ifndef MPI_CONFIG_H_
+#define MPI_CONFIG_H_
+
+/*
+ For boolean options,
+ 0 = no
+ 1 = yes
+
+ Other options are documented individually.
+
+ */
+
+#ifndef MP_IOFUNC
+#define MP_IOFUNC 0 /* include mp_print() ? */
+#endif
+
+#ifndef MP_MODARITH
+#define MP_MODARITH 1 /* include modular arithmetic ? */
+#endif
+
+#ifndef MP_NUMTH
+#define MP_NUMTH 1 /* include number theoretic functions? */
+#endif
+
+#ifndef MP_LOGTAB
+#define MP_LOGTAB 1 /* use table of logs instead of log()? */
+#endif
+
+#ifndef MP_MEMSET
+#define MP_MEMSET 1 /* use memset() to zero buffers? */
+#endif
+
+#ifndef MP_MEMCPY
+#define MP_MEMCPY 1 /* use memcpy() to copy buffers? */
+#endif
+
+#ifndef MP_CRYPTO
+#define MP_CRYPTO 1 /* erase memory on free? */
+#endif
+
+#ifndef MP_ARGCHK
+/*
+ 0 = no parameter checks
+ 1 = runtime checks, continue execution and return an error to caller
+ 2 = assertions; dump core on parameter errors
+ */
+#define MP_ARGCHK 2 /* how to check input arguments */
+#endif
+
+#ifndef MP_DEBUG
+#define MP_DEBUG 0 /* print diagnostic output? */
+#endif
+
+#ifndef MP_DEFPREC
+#define MP_DEFPREC 64 /* default precision, in digits */
+#endif
+
+#ifndef MP_MACRO
+#define MP_MACRO 1 /* use macros for frequent calls? */
+#endif
+
+#ifndef MP_SQUARE
+#define MP_SQUARE 1 /* use separate squaring code? */
+#endif
+
+#ifndef MP_PTAB_SIZE
+/*
+ When building mpprime.c, we build in a table of small prime
+ values to use for primality testing. The more you include,
+ the more space they take up. See primes.c for the possible
+ values (currently 16, 32, 64, 128, 256, and 6542)
+ */
+#define MP_PTAB_SIZE 128 /* how many built-in primes? */
+#endif
+
+#ifndef MP_COMPAT_MACROS
+#define MP_COMPAT_MACROS 1 /* define compatibility macros? */
+#endif
+
+#endif /* ifndef MPI_CONFIG_H_ */
+
+
+/* crc==3287762869, version==2, Sat Feb 02 06:43:53 2002 */
diff --git a/libtommath/mtest/mpi-types.h b/libtommath/mtest/mpi-types.h
new file mode 100644
index 0000000..42ccfc3
--- /dev/null
+++ b/libtommath/mtest/mpi-types.h
@@ -0,0 +1,15 @@
+/* Type definitions generated by 'types.pl' */
+typedef char mp_sign;
+typedef unsigned short mp_digit; /* 2 byte type */
+typedef unsigned int mp_word; /* 4 byte type */
+typedef unsigned int mp_size;
+typedef int mp_err;
+
+#define MP_DIGIT_BIT (CHAR_BIT*sizeof(mp_digit))
+#define MP_DIGIT_MAX USHRT_MAX
+#define MP_WORD_BIT (CHAR_BIT*sizeof(mp_word))
+#define MP_WORD_MAX UINT_MAX
+
+#define MP_DIGIT_SIZE 2
+#define DIGIT_FMT "%04X"
+#define RADIX (MP_DIGIT_MAX+1)
diff --git a/libtommath/mtest/mpi.c b/libtommath/mtest/mpi.c
new file mode 100644
index 0000000..5114bef
--- /dev/null
+++ b/libtommath/mtest/mpi.c
@@ -0,0 +1,3979 @@
+/*
+ mpi.c
+
+ by Michael J. Fromberger <sting@linguist.dartmouth.edu>
+ Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved
+
+ Arbitrary precision integer arithmetic library
+ */
+
+#include "mpi.h"
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#if MP_DEBUG
+#include <stdio.h>
+
+#define DIAG(T,V) {fprintf(stderr,T);mp_print(V,stderr);fputc('\n',stderr);}
+#else
+#define DIAG(T,V)
+#endif
+
+/*
+ If MP_LOGTAB is not defined, use the math library to compute the
+ logarithms on the fly. Otherwise, use the static table below.
+ Pick which works best for your system.
+ */
+#if MP_LOGTAB
+
+/* {{{ s_logv_2[] - log table for 2 in various bases */
+
+/*
+ A table of the logs of 2 for various bases (the 0 and 1 entries of
+ this table are meaningless and should not be referenced).
+
+ This table is used to compute output lengths for the mp_toradix()
+ function. Since a number n in radix r takes up about log_r(n)
+ digits, we estimate the output size by taking the least integer
+ greater than log_r(n), where:
+
+ log_r(n) = log_2(n) * log_r(2)
+
+ This table, therefore, is a table of log_r(2) for 2 <= r <= 36,
+ which are the output bases supported.
+ */
+
+#include "logtab.h"
+
+/* }}} */
+#define LOG_V_2(R) s_logv_2[(R)]
+
+#else
+
+#include <math.h>
+#define LOG_V_2(R) (log(2.0)/log(R))
+
+#endif
+
+/* Default precision for newly created mp_int's */
+static unsigned int s_mp_defprec = MP_DEFPREC;
+
+/* {{{ Digit arithmetic macros */
+
+/*
+ When adding and multiplying digits, the results can be larger than
+ can be contained in an mp_digit. Thus, an mp_word is used. These
+ macros mask off the upper and lower digits of the mp_word (the
+ mp_word may be more than 2 mp_digits wide, but we only concern
+ ourselves with the low-order 2 mp_digits)
+
+ If your mp_word DOES have more than 2 mp_digits, you need to
+ uncomment the first line, and comment out the second.
+ */
+
+/* #define CARRYOUT(W) (((W)>>DIGIT_BIT)&MP_DIGIT_MAX) */
+#define CARRYOUT(W) ((W)>>DIGIT_BIT)
+#define ACCUM(W) ((W)&MP_DIGIT_MAX)
+
+/* }}} */
+
+/* {{{ Comparison constants */
+
+#define MP_LT -1
+#define MP_EQ 0
+#define MP_GT 1
+
+/* }}} */
+
+/* {{{ Constant strings */
+
+/* Constant strings returned by mp_strerror() */
+static const char *mp_err_string[] = {
+ "unknown result code", /* say what? */
+ "boolean true", /* MP_OKAY, MP_YES */
+ "boolean false", /* MP_NO */
+ "out of memory", /* MP_MEM */
+ "argument out of range", /* MP_RANGE */
+ "invalid input parameter", /* MP_BADARG */
+ "result is undefined" /* MP_UNDEF */
+};
+
+/* Value to digit maps for radix conversion */
+
+/* s_dmap_1 - standard digits and letters */
+static const char *s_dmap_1 =
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
+
+#if 0
+/* s_dmap_2 - base64 ordering for digits */
+static const char *s_dmap_2 =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+#endif
+
+/* }}} */
+
+/* {{{ Static function declarations */
+
+/*
+ If MP_MACRO is false, these will be defined as actual functions;
+ otherwise, suitable macro definitions will be used. This works
+ around the fact that ANSI C89 doesn't support an 'inline' keyword
+ (although I hear C9x will ... about bloody time). At present, the
+ macro definitions are identical to the function bodies, but they'll
+ expand in place, instead of generating a function call.
+
+ I chose these particular functions to be made into macros because
+ some profiling showed they are called a lot on a typical workload,
+ and yet they are primarily housekeeping.
+ */
+#if MP_MACRO == 0
+ void s_mp_setz(mp_digit *dp, mp_size count); /* zero digits */
+ void s_mp_copy(mp_digit *sp, mp_digit *dp, mp_size count); /* copy */
+ void *s_mp_alloc(size_t nb, size_t ni); /* general allocator */
+ void s_mp_free(void *ptr); /* general free function */
+#else
+
+ /* Even if these are defined as macros, we need to respect the settings
+ of the MP_MEMSET and MP_MEMCPY configuration options...
+ */
+ #if MP_MEMSET == 0
+ #define s_mp_setz(dp, count) \
+ {int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=0;}
+ #else
+ #define s_mp_setz(dp, count) memset(dp, 0, (count) * sizeof(mp_digit))
+ #endif /* MP_MEMSET */
+
+ #if MP_MEMCPY == 0
+ #define s_mp_copy(sp, dp, count) \
+ {int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=(sp)[ix];}
+ #else
+ #define s_mp_copy(sp, dp, count) memcpy(dp, sp, (count) * sizeof(mp_digit))
+ #endif /* MP_MEMCPY */
+
+ #define s_mp_alloc(nb, ni) calloc(nb, ni)
+ #define s_mp_free(ptr) {if(ptr) free(ptr);}
+#endif /* MP_MACRO */
+
+mp_err s_mp_grow(mp_int *mp, mp_size min); /* increase allocated size */
+mp_err s_mp_pad(mp_int *mp, mp_size min); /* left pad with zeroes */
+
+void s_mp_clamp(mp_int *mp); /* clip leading zeroes */
+
+void s_mp_exch(mp_int *a, mp_int *b); /* swap a and b in place */
+
+mp_err s_mp_lshd(mp_int *mp, mp_size p); /* left-shift by p digits */
+void s_mp_rshd(mp_int *mp, mp_size p); /* right-shift by p digits */
+void s_mp_div_2d(mp_int *mp, mp_digit d); /* divide by 2^d in place */
+void s_mp_mod_2d(mp_int *mp, mp_digit d); /* modulo 2^d in place */
+mp_err s_mp_mul_2d(mp_int *mp, mp_digit d); /* multiply by 2^d in place*/
+void s_mp_div_2(mp_int *mp); /* divide by 2 in place */
+mp_err s_mp_mul_2(mp_int *mp); /* multiply by 2 in place */
+mp_digit s_mp_norm(mp_int *a, mp_int *b); /* normalize for division */
+mp_err s_mp_add_d(mp_int *mp, mp_digit d); /* unsigned digit addition */
+mp_err s_mp_sub_d(mp_int *mp, mp_digit d); /* unsigned digit subtract */
+mp_err s_mp_mul_d(mp_int *mp, mp_digit d); /* unsigned digit multiply */
+mp_err s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r);
+ /* unsigned digit divide */
+mp_err s_mp_reduce(mp_int *x, mp_int *m, mp_int *mu);
+ /* Barrett reduction */
+mp_err s_mp_add(mp_int *a, mp_int *b); /* magnitude addition */
+mp_err s_mp_sub(mp_int *a, mp_int *b); /* magnitude subtract */
+mp_err s_mp_mul(mp_int *a, mp_int *b); /* magnitude multiply */
+#if 0
+void s_mp_kmul(mp_digit *a, mp_digit *b, mp_digit *out, mp_size len);
+ /* multiply buffers in place */
+#endif
+#if MP_SQUARE
+mp_err s_mp_sqr(mp_int *a); /* magnitude square */
+#else
+#define s_mp_sqr(a) s_mp_mul(a, a)
+#endif
+mp_err s_mp_div(mp_int *a, mp_int *b); /* magnitude divide */
+mp_err s_mp_2expt(mp_int *a, mp_digit k); /* a = 2^k */
+int s_mp_cmp(mp_int *a, mp_int *b); /* magnitude comparison */
+int s_mp_cmp_d(mp_int *a, mp_digit d); /* magnitude digit compare */
+int s_mp_ispow2(mp_int *v); /* is v a power of 2? */
+int s_mp_ispow2d(mp_digit d); /* is d a power of 2? */
+
+int s_mp_tovalue(char ch, int r); /* convert ch to value */
+char s_mp_todigit(int val, int r, int low); /* convert val to digit */
+int s_mp_outlen(int bits, int r); /* output length in bytes */
+
+/* }}} */
+
+/* {{{ Default precision manipulation */
+
+unsigned int mp_get_prec(void)
+{
+ return s_mp_defprec;
+
+} /* end mp_get_prec() */
+
+void mp_set_prec(unsigned int prec)
+{
+ if(prec == 0)
+ s_mp_defprec = MP_DEFPREC;
+ else
+ s_mp_defprec = prec;
+
+} /* end mp_set_prec() */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ mp_init(mp) */
+
+/*
+ mp_init(mp)
+
+ Initialize a new zero-valued mp_int. Returns MP_OKAY if successful,
+ MP_MEM if memory could not be allocated for the structure.
+ */
+
+mp_err mp_init(mp_int *mp)
+{
+ return mp_init_size(mp, s_mp_defprec);
+
+} /* end mp_init() */
+
+/* }}} */
+
+/* {{{ mp_init_array(mp[], count) */
+
+mp_err mp_init_array(mp_int mp[], int count)
+{
+ mp_err res;
+ int pos;
+
+ ARGCHK(mp !=NULL && count > 0, MP_BADARG);
+
+ for(pos = 0; pos < count; ++pos) {
+ if((res = mp_init(&mp[pos])) != MP_OKAY)
+ goto CLEANUP;
+ }
+
+ return MP_OKAY;
+
+ CLEANUP:
+ while(--pos >= 0)
+ mp_clear(&mp[pos]);
+
+ return res;
+
+} /* end mp_init_array() */
+
+/* }}} */
+
+/* {{{ mp_init_size(mp, prec) */
+
+/*
+ mp_init_size(mp, prec)
+
+ Initialize a new zero-valued mp_int with at least the given
+ precision; returns MP_OKAY if successful, or MP_MEM if memory could
+ not be allocated for the structure.
+ */
+
+mp_err mp_init_size(mp_int *mp, mp_size prec)
+{
+ ARGCHK(mp != NULL && prec > 0, MP_BADARG);
+
+ if((DIGITS(mp) = s_mp_alloc(prec, sizeof(mp_digit))) == NULL)
+ return MP_MEM;
+
+ SIGN(mp) = MP_ZPOS;
+ USED(mp) = 1;
+ ALLOC(mp) = prec;
+
+ return MP_OKAY;
+
+} /* end mp_init_size() */
+
+/* }}} */
+
+/* {{{ mp_init_copy(mp, from) */
+
+/*
+ mp_init_copy(mp, from)
+
+ Initialize mp as an exact copy of from. Returns MP_OKAY if
+ successful, MP_MEM if memory could not be allocated for the new
+ structure.
+ */
+
+mp_err mp_init_copy(mp_int *mp, mp_int *from)
+{
+ ARGCHK(mp != NULL && from != NULL, MP_BADARG);
+
+ if(mp == from)
+ return MP_OKAY;
+
+ if((DIGITS(mp) = s_mp_alloc(USED(from), sizeof(mp_digit))) == NULL)
+ return MP_MEM;
+
+ s_mp_copy(DIGITS(from), DIGITS(mp), USED(from));
+ USED(mp) = USED(from);
+ ALLOC(mp) = USED(from);
+ SIGN(mp) = SIGN(from);
+
+ return MP_OKAY;
+
+} /* end mp_init_copy() */
+
+/* }}} */
+
+/* {{{ mp_copy(from, to) */
+
+/*
+ mp_copy(from, to)
+
+ Copies the mp_int 'from' to the mp_int 'to'. It is presumed that
+ 'to' has already been initialized (if not, use mp_init_copy()
+ instead). If 'from' and 'to' are identical, nothing happens.
+ */
+
+mp_err mp_copy(mp_int *from, mp_int *to)
+{
+ ARGCHK(from != NULL && to != NULL, MP_BADARG);
+
+ if(from == to)
+ return MP_OKAY;
+
+ { /* copy */
+ mp_digit *tmp;
+
+ /*
+ If the allocated buffer in 'to' already has enough space to hold
+ all the used digits of 'from', we'll re-use it to avoid hitting
+ the memory allocater more than necessary; otherwise, we'd have
+ to grow anyway, so we just allocate a hunk and make the copy as
+ usual
+ */
+ if(ALLOC(to) >= USED(from)) {
+ s_mp_setz(DIGITS(to) + USED(from), ALLOC(to) - USED(from));
+ s_mp_copy(DIGITS(from), DIGITS(to), USED(from));
+
+ } else {
+ if((tmp = s_mp_alloc(USED(from), sizeof(mp_digit))) == NULL)
+ return MP_MEM;
+
+ s_mp_copy(DIGITS(from), tmp, USED(from));
+
+ if(DIGITS(to) != NULL) {
+#if MP_CRYPTO
+ s_mp_setz(DIGITS(to), ALLOC(to));
+#endif
+ s_mp_free(DIGITS(to));
+ }
+
+ DIGITS(to) = tmp;
+ ALLOC(to) = USED(from);
+ }
+
+ /* Copy the precision and sign from the original */
+ USED(to) = USED(from);
+ SIGN(to) = SIGN(from);
+ } /* end copy */
+
+ return MP_OKAY;
+
+} /* end mp_copy() */
+
+/* }}} */
+
+/* {{{ mp_exch(mp1, mp2) */
+
+/*
+ mp_exch(mp1, mp2)
+
+ Exchange mp1 and mp2 without allocating any intermediate memory
+ (well, unless you count the stack space needed for this call and the
+ locals it creates...). This cannot fail.
+ */
+
+void mp_exch(mp_int *mp1, mp_int *mp2)
+{
+#if MP_ARGCHK == 2
+ assert(mp1 != NULL && mp2 != NULL);
+#else
+ if(mp1 == NULL || mp2 == NULL)
+ return;
+#endif
+
+ s_mp_exch(mp1, mp2);
+
+} /* end mp_exch() */
+
+/* }}} */
+
+/* {{{ mp_clear(mp) */
+
+/*
+ mp_clear(mp)
+
+ Release the storage used by an mp_int, and void its fields so that
+ if someone calls mp_clear() again for the same int later, we won't
+ get tollchocked.
+ */
+
+void mp_clear(mp_int *mp)
+{
+ if(mp == NULL)
+ return;
+
+ if(DIGITS(mp) != NULL) {
+#if MP_CRYPTO
+ s_mp_setz(DIGITS(mp), ALLOC(mp));
+#endif
+ s_mp_free(DIGITS(mp));
+ DIGITS(mp) = NULL;
+ }
+
+ USED(mp) = 0;
+ ALLOC(mp) = 0;
+
+} /* end mp_clear() */
+
+/* }}} */
+
+/* {{{ mp_clear_array(mp[], count) */
+
+void mp_clear_array(mp_int mp[], int count)
+{
+ ARGCHK(mp != NULL && count > 0, MP_BADARG);
+
+ while(--count >= 0)
+ mp_clear(&mp[count]);
+
+} /* end mp_clear_array() */
+
+/* }}} */
+
+/* {{{ mp_zero(mp) */
+
+/*
+ mp_zero(mp)
+
+ Set mp to zero. Does not change the allocated size of the structure,
+ and therefore cannot fail (except on a bad argument, which we ignore)
+ */
+void mp_zero(mp_int *mp)
+{
+ if(mp == NULL)
+ return;
+
+ s_mp_setz(DIGITS(mp), ALLOC(mp));
+ USED(mp) = 1;
+ SIGN(mp) = MP_ZPOS;
+
+} /* end mp_zero() */
+
+/* }}} */
+
+/* {{{ mp_set(mp, d) */
+
+void mp_set(mp_int *mp, mp_digit d)
+{
+ if(mp == NULL)
+ return;
+
+ mp_zero(mp);
+ DIGIT(mp, 0) = d;
+
+} /* end mp_set() */
+
+/* }}} */
+
+/* {{{ mp_set_int(mp, z) */
+
+mp_err mp_set_int(mp_int *mp, long z)
+{
+ int ix;
+ unsigned long v = abs(z);
+ mp_err res;
+
+ ARGCHK(mp != NULL, MP_BADARG);
+
+ mp_zero(mp);
+ if(z == 0)
+ return MP_OKAY; /* shortcut for zero */
+
+ for(ix = sizeof(long) - 1; ix >= 0; ix--) {
+
+ if((res = s_mp_mul_2d(mp, CHAR_BIT)) != MP_OKAY)
+ return res;
+
+ res = s_mp_add_d(mp,
+ (mp_digit)((v >> (ix * CHAR_BIT)) & UCHAR_MAX));
+ if(res != MP_OKAY)
+ return res;
+
+ }
+
+ if(z < 0)
+ SIGN(mp) = MP_NEG;
+
+ return MP_OKAY;
+
+} /* end mp_set_int() */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ Digit arithmetic */
+
+/* {{{ mp_add_d(a, d, b) */
+
+/*
+ mp_add_d(a, d, b)
+
+ Compute the sum b = a + d, for a single digit d. Respects the sign of
+ its primary addend (single digits are unsigned anyway).
+ */
+
+mp_err mp_add_d(mp_int *a, mp_digit d, mp_int *b)
+{
+ mp_err res = MP_OKAY;
+
+ ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+ if((res = mp_copy(a, b)) != MP_OKAY)
+ return res;
+
+ if(SIGN(b) == MP_ZPOS) {
+ res = s_mp_add_d(b, d);
+ } else if(s_mp_cmp_d(b, d) >= 0) {
+ res = s_mp_sub_d(b, d);
+ } else {
+ SIGN(b) = MP_ZPOS;
+
+ DIGIT(b, 0) = d - DIGIT(b, 0);
+ }
+
+ return res;
+
+} /* end mp_add_d() */
+
+/* }}} */
+
+/* {{{ mp_sub_d(a, d, b) */
+
+/*
+ mp_sub_d(a, d, b)
+
+ Compute the difference b = a - d, for a single digit d. Respects the
+ sign of its subtrahend (single digits are unsigned anyway).
+ */
+
+mp_err mp_sub_d(mp_int *a, mp_digit d, mp_int *b)
+{
+ mp_err res;
+
+ ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+ if((res = mp_copy(a, b)) != MP_OKAY)
+ return res;
+
+ if(SIGN(b) == MP_NEG) {
+ if((res = s_mp_add_d(b, d)) != MP_OKAY)
+ return res;
+
+ } else if(s_mp_cmp_d(b, d) >= 0) {
+ if((res = s_mp_sub_d(b, d)) != MP_OKAY)
+ return res;
+
+ } else {
+ mp_neg(b, b);
+
+ DIGIT(b, 0) = d - DIGIT(b, 0);
+ SIGN(b) = MP_NEG;
+ }
+
+ if(s_mp_cmp_d(b, 0) == 0)
+ SIGN(b) = MP_ZPOS;
+
+ return MP_OKAY;
+
+} /* end mp_sub_d() */
+
+/* }}} */
+
+/* {{{ mp_mul_d(a, d, b) */
+
+/*
+ mp_mul_d(a, d, b)
+
+ Compute the product b = a * d, for a single digit d. Respects the sign
+ of its multiplicand (single digits are unsigned anyway)
+ */
+
+mp_err mp_mul_d(mp_int *a, mp_digit d, mp_int *b)
+{
+ mp_err res;
+
+ ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+ if(d == 0) {
+ mp_zero(b);
+ return MP_OKAY;
+ }
+
+ if((res = mp_copy(a, b)) != MP_OKAY)
+ return res;
+
+ res = s_mp_mul_d(b, d);
+
+ return res;
+
+} /* end mp_mul_d() */
+
+/* }}} */
+
+/* {{{ mp_mul_2(a, c) */
+
+mp_err mp_mul_2(mp_int *a, mp_int *c)
+{
+ mp_err res;
+
+ ARGCHK(a != NULL && c != NULL, MP_BADARG);
+
+ if((res = mp_copy(a, c)) != MP_OKAY)
+ return res;
+
+ return s_mp_mul_2(c);
+
+} /* end mp_mul_2() */
+
+/* }}} */
+
+/* {{{ mp_div_d(a, d, q, r) */
+
+/*
+ mp_div_d(a, d, q, r)
+
+ Compute the quotient q = a / d and remainder r = a mod d, for a
+ single digit d. Respects the sign of its divisor (single digits are
+ unsigned anyway).
+ */
+
+mp_err mp_div_d(mp_int *a, mp_digit d, mp_int *q, mp_digit *r)
+{
+ mp_err res;
+ mp_digit rem;
+ int pow;
+
+ ARGCHK(a != NULL, MP_BADARG);
+
+ if(d == 0)
+ return MP_RANGE;
+
+ /* Shortcut for powers of two ... */
+ if((pow = s_mp_ispow2d(d)) >= 0) {
+ mp_digit mask;
+
+ mask = (1 << pow) - 1;
+ rem = DIGIT(a, 0) & mask;
+
+ if(q) {
+ mp_copy(a, q);
+ s_mp_div_2d(q, pow);
+ }
+
+ if(r)
+ *r = rem;
+
+ return MP_OKAY;
+ }
+
+ /*
+ If the quotient is actually going to be returned, we'll try to
+ avoid hitting the memory allocator by copying the dividend into it
+ and doing the division there. This can't be any _worse_ than
+ always copying, and will sometimes be better (since it won't make
+ another copy)
+
+ If it's not going to be returned, we need to allocate a temporary
+ to hold the quotient, which will just be discarded.
+ */
+ if(q) {
+ if((res = mp_copy(a, q)) != MP_OKAY)
+ return res;
+
+ res = s_mp_div_d(q, d, &rem);
+ if(s_mp_cmp_d(q, 0) == MP_EQ)
+ SIGN(q) = MP_ZPOS;
+
+ } else {
+ mp_int qp;
+
+ if((res = mp_init_copy(&qp, a)) != MP_OKAY)
+ return res;
+
+ res = s_mp_div_d(&qp, d, &rem);
+ if(s_mp_cmp_d(&qp, 0) == 0)
+ SIGN(&qp) = MP_ZPOS;
+
+ mp_clear(&qp);
+ }
+
+ if(r)
+ *r = rem;
+
+ return res;
+
+} /* end mp_div_d() */
+
+/* }}} */
+
+/* {{{ mp_div_2(a, c) */
+
+/*
+ mp_div_2(a, c)
+
+ Compute c = a / 2, disregarding the remainder.
+ */
+
+mp_err mp_div_2(mp_int *a, mp_int *c)
+{
+ mp_err res;
+
+ ARGCHK(a != NULL && c != NULL, MP_BADARG);
+
+ if((res = mp_copy(a, c)) != MP_OKAY)
+ return res;
+
+ s_mp_div_2(c);
+
+ return MP_OKAY;
+
+} /* end mp_div_2() */
+
+/* }}} */
+
+/* {{{ mp_expt_d(a, d, b) */
+
+mp_err mp_expt_d(mp_int *a, mp_digit d, mp_int *c)
+{
+ mp_int s, x;
+ mp_err res;
+
+ ARGCHK(a != NULL && c != NULL, MP_BADARG);
+
+ if((res = mp_init(&s)) != MP_OKAY)
+ return res;
+ if((res = mp_init_copy(&x, a)) != MP_OKAY)
+ goto X;
+
+ DIGIT(&s, 0) = 1;
+
+ while(d != 0) {
+ if(d & 1) {
+ if((res = s_mp_mul(&s, &x)) != MP_OKAY)
+ goto CLEANUP;
+ }
+
+ d >>= 1;
+
+ if((res = s_mp_sqr(&x)) != MP_OKAY)
+ goto CLEANUP;
+ }
+
+ s_mp_exch(&s, c);
+
+CLEANUP:
+ mp_clear(&x);
+X:
+ mp_clear(&s);
+
+ return res;
+
+} /* end mp_expt_d() */
+
+/* }}} */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ Full arithmetic */
+
+/* {{{ mp_abs(a, b) */
+
+/*
+ mp_abs(a, b)
+
+ Compute b = |a|. 'a' and 'b' may be identical.
+ */
+
+mp_err mp_abs(mp_int *a, mp_int *b)
+{
+ mp_err res;
+
+ ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+ if((res = mp_copy(a, b)) != MP_OKAY)
+ return res;
+
+ SIGN(b) = MP_ZPOS;
+
+ return MP_OKAY;
+
+} /* end mp_abs() */
+
+/* }}} */
+
+/* {{{ mp_neg(a, b) */
+
+/*
+ mp_neg(a, b)
+
+ Compute b = -a. 'a' and 'b' may be identical.
+ */
+
+mp_err mp_neg(mp_int *a, mp_int *b)
+{
+ mp_err res;
+
+ ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+ if((res = mp_copy(a, b)) != MP_OKAY)
+ return res;
+
+ if(s_mp_cmp_d(b, 0) == MP_EQ)
+ SIGN(b) = MP_ZPOS;
+ else
+ SIGN(b) = (SIGN(b) == MP_NEG) ? MP_ZPOS : MP_NEG;
+
+ return MP_OKAY;
+
+} /* end mp_neg() */
+
+/* }}} */
+
+/* {{{ mp_add(a, b, c) */
+
+/*
+ mp_add(a, b, c)
+
+ Compute c = a + b. All parameters may be identical.
+ */
+
+mp_err mp_add(mp_int *a, mp_int *b, mp_int *c)
+{
+ mp_err res;
+ int cmp;
+
+ ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+ if(SIGN(a) == SIGN(b)) { /* same sign: add values, keep sign */
+
+ /* Commutativity of addition lets us do this in either order,
+ so we avoid having to use a temporary even if the result
+ is supposed to replace the output
+ */
+ if(c == b) {
+ if((res = s_mp_add(c, a)) != MP_OKAY)
+ return res;
+ } else {
+ if(c != a && (res = mp_copy(a, c)) != MP_OKAY)
+ return res;
+
+ if((res = s_mp_add(c, b)) != MP_OKAY)
+ return res;
+ }
+
+ } else if((cmp = s_mp_cmp(a, b)) > 0) { /* different sign: a > b */
+
+ /* If the output is going to be clobbered, we will use a temporary
+ variable; otherwise, we'll do it without touching the memory
+ allocator at all, if possible
+ */
+ if(c == b) {
+ mp_int tmp;
+
+ if((res = mp_init_copy(&tmp, a)) != MP_OKAY)
+ return res;
+ if((res = s_mp_sub(&tmp, b)) != MP_OKAY) {
+ mp_clear(&tmp);
+ return res;
+ }
+
+ s_mp_exch(&tmp, c);
+ mp_clear(&tmp);
+
+ } else {
+
+ if(c != a && (res = mp_copy(a, c)) != MP_OKAY)
+ return res;
+ if((res = s_mp_sub(c, b)) != MP_OKAY)
+ return res;
+
+ }
+
+ } else if(cmp == 0) { /* different sign, a == b */
+
+ mp_zero(c);
+ return MP_OKAY;
+
+ } else { /* different sign: a < b */
+
+ /* See above... */
+ if(c == a) {
+ mp_int tmp;
+
+ if((res = mp_init_copy(&tmp, b)) != MP_OKAY)
+ return res;
+ if((res = s_mp_sub(&tmp, a)) != MP_OKAY) {
+ mp_clear(&tmp);
+ return res;
+ }
+
+ s_mp_exch(&tmp, c);
+ mp_clear(&tmp);
+
+ } else {
+
+ if(c != b && (res = mp_copy(b, c)) != MP_OKAY)
+ return res;
+ if((res = s_mp_sub(c, a)) != MP_OKAY)
+ return res;
+
+ }
+ }
+
+ if(USED(c) == 1 && DIGIT(c, 0) == 0)
+ SIGN(c) = MP_ZPOS;
+
+ return MP_OKAY;
+
+} /* end mp_add() */
+
+/* }}} */
+
+/* {{{ mp_sub(a, b, c) */
+
+/*
+ mp_sub(a, b, c)
+
+ Compute c = a - b. All parameters may be identical.
+ */
+
+mp_err mp_sub(mp_int *a, mp_int *b, mp_int *c)
+{
+ mp_err res;
+ int cmp;
+
+ ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+ if(SIGN(a) != SIGN(b)) {
+ if(c == a) {
+ if((res = s_mp_add(c, b)) != MP_OKAY)
+ return res;
+ } else {
+ if(c != b && ((res = mp_copy(b, c)) != MP_OKAY))
+ return res;
+ if((res = s_mp_add(c, a)) != MP_OKAY)
+ return res;
+ SIGN(c) = SIGN(a);
+ }
+
+ } else if((cmp = s_mp_cmp(a, b)) > 0) { /* Same sign, a > b */
+ if(c == b) {
+ mp_int tmp;
+
+ if((res = mp_init_copy(&tmp, a)) != MP_OKAY)
+ return res;
+ if((res = s_mp_sub(&tmp, b)) != MP_OKAY) {
+ mp_clear(&tmp);
+ return res;
+ }
+ s_mp_exch(&tmp, c);
+ mp_clear(&tmp);
+
+ } else {
+ if(c != a && ((res = mp_copy(a, c)) != MP_OKAY))
+ return res;
+
+ if((res = s_mp_sub(c, b)) != MP_OKAY)
+ return res;
+ }
+
+ } else if(cmp == 0) { /* Same sign, equal magnitude */
+ mp_zero(c);
+ return MP_OKAY;
+
+ } else { /* Same sign, b > a */
+ if(c == a) {
+ mp_int tmp;
+
+ if((res = mp_init_copy(&tmp, b)) != MP_OKAY)
+ return res;
+
+ if((res = s_mp_sub(&tmp, a)) != MP_OKAY) {
+ mp_clear(&tmp);
+ return res;
+ }
+ s_mp_exch(&tmp, c);
+ mp_clear(&tmp);
+
+ } else {
+ if(c != b && ((res = mp_copy(b, c)) != MP_OKAY))
+ return res;
+
+ if((res = s_mp_sub(c, a)) != MP_OKAY)
+ return res;
+ }
+
+ SIGN(c) = !SIGN(b);
+ }
+
+ if(USED(c) == 1 && DIGIT(c, 0) == 0)
+ SIGN(c) = MP_ZPOS;
+
+ return MP_OKAY;
+
+} /* end mp_sub() */
+
+/* }}} */
+
+/* {{{ mp_mul(a, b, c) */
+
+/*
+ mp_mul(a, b, c)
+
+ Compute c = a * b. All parameters may be identical.
+ */
+
+mp_err mp_mul(mp_int *a, mp_int *b, mp_int *c)
+{
+ mp_err res;
+ mp_sign sgn;
+
+ ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+ sgn = (SIGN(a) == SIGN(b)) ? MP_ZPOS : MP_NEG;
+
+ if(c == b) {
+ if((res = s_mp_mul(c, a)) != MP_OKAY)
+ return res;
+
+ } else {
+ if((res = mp_copy(a, c)) != MP_OKAY)
+ return res;
+
+ if((res = s_mp_mul(c, b)) != MP_OKAY)
+ return res;
+ }
+
+ if(sgn == MP_ZPOS || s_mp_cmp_d(c, 0) == MP_EQ)
+ SIGN(c) = MP_ZPOS;
+ else
+ SIGN(c) = sgn;
+
+ return MP_OKAY;
+
+} /* end mp_mul() */
+
+/* }}} */
+
+/* {{{ mp_mul_2d(a, d, c) */
+
+/*
+ mp_mul_2d(a, d, c)
+
+ Compute c = a * 2^d. a may be the same as c.
+ */
+
+mp_err mp_mul_2d(mp_int *a, mp_digit d, mp_int *c)
+{
+ mp_err res;
+
+ ARGCHK(a != NULL && c != NULL, MP_BADARG);
+
+ if((res = mp_copy(a, c)) != MP_OKAY)
+ return res;
+
+ if(d == 0)
+ return MP_OKAY;
+
+ return s_mp_mul_2d(c, d);
+
+} /* end mp_mul() */
+
+/* }}} */
+
+/* {{{ mp_sqr(a, b) */
+
+#if MP_SQUARE
+mp_err mp_sqr(mp_int *a, mp_int *b)
+{
+ mp_err res;
+
+ ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+ if((res = mp_copy(a, b)) != MP_OKAY)
+ return res;
+
+ if((res = s_mp_sqr(b)) != MP_OKAY)
+ return res;
+
+ SIGN(b) = MP_ZPOS;
+
+ return MP_OKAY;
+
+} /* end mp_sqr() */
+#endif
+
+/* }}} */
+
+/* {{{ mp_div(a, b, q, r) */
+
+/*
+ mp_div(a, b, q, r)
+
+ Compute q = a / b and r = a mod b. Input parameters may be re-used
+ as output parameters. If q or r is NULL, that portion of the
+ computation will be discarded (although it will still be computed)
+
+ Pay no attention to the hacker behind the curtain.
+ */
+
+mp_err mp_div(mp_int *a, mp_int *b, mp_int *q, mp_int *r)
+{
+ mp_err res;
+ mp_int qtmp, rtmp;
+ int cmp;
+
+ ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+ if(mp_cmp_z(b) == MP_EQ)
+ return MP_RANGE;
+
+ /* If a <= b, we can compute the solution without division, and
+ avoid any memory allocation
+ */
+ if((cmp = s_mp_cmp(a, b)) < 0) {
+ if(r) {
+ if((res = mp_copy(a, r)) != MP_OKAY)
+ return res;
+ }
+
+ if(q)
+ mp_zero(q);
+
+ return MP_OKAY;
+
+ } else if(cmp == 0) {
+
+ /* Set quotient to 1, with appropriate sign */
+ if(q) {
+ int qneg = (SIGN(a) != SIGN(b));
+
+ mp_set(q, 1);
+ if(qneg)
+ SIGN(q) = MP_NEG;
+ }
+
+ if(r)
+ mp_zero(r);
+
+ return MP_OKAY;
+ }
+
+ /* If we get here, it means we actually have to do some division */
+
+ /* Set up some temporaries... */
+ if((res = mp_init_copy(&qtmp, a)) != MP_OKAY)
+ return res;
+ if((res = mp_init_copy(&rtmp, b)) != MP_OKAY)
+ goto CLEANUP;
+
+ if((res = s_mp_div(&qtmp, &rtmp)) != MP_OKAY)
+ goto CLEANUP;
+
+ /* Compute the signs for the output */
+ SIGN(&rtmp) = SIGN(a); /* Sr = Sa */
+ if(SIGN(a) == SIGN(b))
+ SIGN(&qtmp) = MP_ZPOS; /* Sq = MP_ZPOS if Sa = Sb */
+ else
+ SIGN(&qtmp) = MP_NEG; /* Sq = MP_NEG if Sa != Sb */
+
+ if(s_mp_cmp_d(&qtmp, 0) == MP_EQ)
+ SIGN(&qtmp) = MP_ZPOS;
+ if(s_mp_cmp_d(&rtmp, 0) == MP_EQ)
+ SIGN(&rtmp) = MP_ZPOS;
+
+ /* Copy output, if it is needed */
+ if(q)
+ s_mp_exch(&qtmp, q);
+
+ if(r)
+ s_mp_exch(&rtmp, r);
+
+CLEANUP:
+ mp_clear(&rtmp);
+ mp_clear(&qtmp);
+
+ return res;
+
+} /* end mp_div() */
+
+/* }}} */
+
+/* {{{ mp_div_2d(a, d, q, r) */
+
+mp_err mp_div_2d(mp_int *a, mp_digit d, mp_int *q, mp_int *r)
+{
+ mp_err res;
+
+ ARGCHK(a != NULL, MP_BADARG);
+
+ if(q) {
+ if((res = mp_copy(a, q)) != MP_OKAY)
+ return res;
+
+ s_mp_div_2d(q, d);
+ }
+
+ if(r) {
+ if((res = mp_copy(a, r)) != MP_OKAY)
+ return res;
+
+ s_mp_mod_2d(r, d);
+ }
+
+ return MP_OKAY;
+
+} /* end mp_div_2d() */
+
+/* }}} */
+
+/* {{{ mp_expt(a, b, c) */
+
+/*
+ mp_expt(a, b, c)
+
+ Compute c = a ** b, that is, raise a to the b power. Uses a
+ standard iterative square-and-multiply technique.
+ */
+
+mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c)
+{
+ mp_int s, x;
+ mp_err res;
+ mp_digit d;
+ int dig, bit;
+
+ ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+ if(mp_cmp_z(b) < 0)
+ return MP_RANGE;
+
+ if((res = mp_init(&s)) != MP_OKAY)
+ return res;
+
+ mp_set(&s, 1);
+
+ if((res = mp_init_copy(&x, a)) != MP_OKAY)
+ goto X;
+
+ /* Loop over low-order digits in ascending order */
+ for(dig = 0; dig < (USED(b) - 1); dig++) {
+ d = DIGIT(b, dig);
+
+ /* Loop over bits of each non-maximal digit */
+ for(bit = 0; bit < DIGIT_BIT; bit++) {
+ if(d & 1) {
+ if((res = s_mp_mul(&s, &x)) != MP_OKAY)
+ goto CLEANUP;
+ }
+
+ d >>= 1;
+
+ if((res = s_mp_sqr(&x)) != MP_OKAY)
+ goto CLEANUP;
+ }
+ }
+
+ /* Consider now the last digit... */
+ d = DIGIT(b, dig);
+
+ while(d) {
+ if(d & 1) {
+ if((res = s_mp_mul(&s, &x)) != MP_OKAY)
+ goto CLEANUP;
+ }
+
+ d >>= 1;
+
+ if((res = s_mp_sqr(&x)) != MP_OKAY)
+ goto CLEANUP;
+ }
+
+ if(mp_iseven(b))
+ SIGN(&s) = SIGN(a);
+
+ res = mp_copy(&s, c);
+
+CLEANUP:
+ mp_clear(&x);
+X:
+ mp_clear(&s);
+
+ return res;
+
+} /* end mp_expt() */
+
+/* }}} */
+
+/* {{{ mp_2expt(a, k) */
+
+/* Compute a = 2^k */
+
+mp_err mp_2expt(mp_int *a, mp_digit k)
+{
+ ARGCHK(a != NULL, MP_BADARG);
+
+ return s_mp_2expt(a, k);
+
+} /* end mp_2expt() */
+
+/* }}} */
+
+/* {{{ mp_mod(a, m, c) */
+
+/*
+ mp_mod(a, m, c)
+
+ Compute c = a (mod m). Result will always be 0 <= c < m.
+ */
+
+mp_err mp_mod(mp_int *a, mp_int *m, mp_int *c)
+{
+ mp_err res;
+ int mag;
+
+ ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
+
+ if(SIGN(m) == MP_NEG)
+ return MP_RANGE;
+
+ /*
+ If |a| > m, we need to divide to get the remainder and take the
+ absolute value.
+
+ If |a| < m, we don't need to do any division, just copy and adjust
+ the sign (if a is negative).
+
+ If |a| == m, we can simply set the result to zero.
+
+ This order is intended to minimize the average path length of the
+ comparison chain on common workloads -- the most frequent cases are
+ that |a| != m, so we do those first.
+ */
+ if((mag = s_mp_cmp(a, m)) > 0) {
+ if((res = mp_div(a, m, NULL, c)) != MP_OKAY)
+ return res;
+
+ if(SIGN(c) == MP_NEG) {
+ if((res = mp_add(c, m, c)) != MP_OKAY)
+ return res;
+ }
+
+ } else if(mag < 0) {
+ if((res = mp_copy(a, c)) != MP_OKAY)
+ return res;
+
+ if(mp_cmp_z(a) < 0) {
+ if((res = mp_add(c, m, c)) != MP_OKAY)
+ return res;
+
+ }
+
+ } else {
+ mp_zero(c);
+
+ }
+
+ return MP_OKAY;
+
+} /* end mp_mod() */
+
+/* }}} */
+
+/* {{{ mp_mod_d(a, d, c) */
+
+/*
+ mp_mod_d(a, d, c)
+
+ Compute c = a (mod d). Result will always be 0 <= c < d
+ */
+mp_err mp_mod_d(mp_int *a, mp_digit d, mp_digit *c)
+{
+ mp_err res;
+ mp_digit rem;
+
+ ARGCHK(a != NULL && c != NULL, MP_BADARG);
+
+ if(s_mp_cmp_d(a, d) > 0) {
+ if((res = mp_div_d(a, d, NULL, &rem)) != MP_OKAY)
+ return res;
+
+ } else {
+ if(SIGN(a) == MP_NEG)
+ rem = d - DIGIT(a, 0);
+ else
+ rem = DIGIT(a, 0);
+ }
+
+ if(c)
+ *c = rem;
+
+ return MP_OKAY;
+
+} /* end mp_mod_d() */
+
+/* }}} */
+
+/* {{{ mp_sqrt(a, b) */
+
+/*
+ mp_sqrt(a, b)
+
+ Compute the integer square root of a, and store the result in b.
+ Uses an integer-arithmetic version of Newton's iterative linear
+ approximation technique to determine this value; the result has the
+ following two properties:
+
+ b^2 <= a
+ (b+1)^2 >= a
+
+ It is a range error to pass a negative value.
+ */
+mp_err mp_sqrt(mp_int *a, mp_int *b)
+{
+ mp_int x, t;
+ mp_err res;
+
+ ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+ /* Cannot take square root of a negative value */
+ if(SIGN(a) == MP_NEG)
+ return MP_RANGE;
+
+ /* Special cases for zero and one, trivial */
+ if(mp_cmp_d(a, 0) == MP_EQ || mp_cmp_d(a, 1) == MP_EQ)
+ return mp_copy(a, b);
+
+ /* Initialize the temporaries we'll use below */
+ if((res = mp_init_size(&t, USED(a))) != MP_OKAY)
+ return res;
+
+ /* Compute an initial guess for the iteration as a itself */
+ if((res = mp_init_copy(&x, a)) != MP_OKAY)
+ goto X;
+
+s_mp_rshd(&x, (USED(&x)/2)+1);
+mp_add_d(&x, 1, &x);
+
+ for(;;) {
+ /* t = (x * x) - a */
+ mp_copy(&x, &t); /* can't fail, t is big enough for original x */
+ if((res = mp_sqr(&t, &t)) != MP_OKAY ||
+ (res = mp_sub(&t, a, &t)) != MP_OKAY)
+ goto CLEANUP;
+
+ /* t = t / 2x */
+ s_mp_mul_2(&x);
+ if((res = mp_div(&t, &x, &t, NULL)) != MP_OKAY)
+ goto CLEANUP;
+ s_mp_div_2(&x);
+
+ /* Terminate the loop, if the quotient is zero */
+ if(mp_cmp_z(&t) == MP_EQ)
+ break;
+
+ /* x = x - t */
+ if((res = mp_sub(&x, &t, &x)) != MP_OKAY)
+ goto CLEANUP;
+
+ }
+
+ /* Copy result to output parameter */
+ mp_sub_d(&x, 1, &x);
+ s_mp_exch(&x, b);
+
+ CLEANUP:
+ mp_clear(&x);
+ X:
+ mp_clear(&t);
+
+ return res;
+
+} /* end mp_sqrt() */
+
+/* }}} */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ Modular arithmetic */
+
+#if MP_MODARITH
+/* {{{ mp_addmod(a, b, m, c) */
+
+/*
+ mp_addmod(a, b, m, c)
+
+ Compute c = (a + b) mod m
+ */
+
+mp_err mp_addmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c)
+{
+ mp_err res;
+
+ ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
+
+ if((res = mp_add(a, b, c)) != MP_OKAY)
+ return res;
+ if((res = mp_mod(c, m, c)) != MP_OKAY)
+ return res;
+
+ return MP_OKAY;
+
+}
+
+/* }}} */
+
+/* {{{ mp_submod(a, b, m, c) */
+
+/*
+ mp_submod(a, b, m, c)
+
+ Compute c = (a - b) mod m
+ */
+
+mp_err mp_submod(mp_int *a, mp_int *b, mp_int *m, mp_int *c)
+{
+ mp_err res;
+
+ ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
+
+ if((res = mp_sub(a, b, c)) != MP_OKAY)
+ return res;
+ if((res = mp_mod(c, m, c)) != MP_OKAY)
+ return res;
+
+ return MP_OKAY;
+
+}
+
+/* }}} */
+
+/* {{{ mp_mulmod(a, b, m, c) */
+
+/*
+ mp_mulmod(a, b, m, c)
+
+ Compute c = (a * b) mod m
+ */
+
+mp_err mp_mulmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c)
+{
+ mp_err res;
+
+ ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
+
+ if((res = mp_mul(a, b, c)) != MP_OKAY)
+ return res;
+ if((res = mp_mod(c, m, c)) != MP_OKAY)
+ return res;
+
+ return MP_OKAY;
+
+}
+
+/* }}} */
+
+/* {{{ mp_sqrmod(a, m, c) */
+
+#if MP_SQUARE
+mp_err mp_sqrmod(mp_int *a, mp_int *m, mp_int *c)
+{
+ mp_err res;
+
+ ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
+
+ if((res = mp_sqr(a, c)) != MP_OKAY)
+ return res;
+ if((res = mp_mod(c, m, c)) != MP_OKAY)
+ return res;
+
+ return MP_OKAY;
+
+} /* end mp_sqrmod() */
+#endif
+
+/* }}} */
+
+/* {{{ mp_exptmod(a, b, m, c) */
+
+/*
+ mp_exptmod(a, b, m, c)
+
+ Compute c = (a ** b) mod m. Uses a standard square-and-multiply
+ method with modular reductions at each step. (This is basically the
+ same code as mp_expt(), except for the addition of the reductions)
+
+ The modular reductions are done using Barrett's algorithm (see
+ s_mp_reduce() below for details)
+ */
+
+mp_err mp_exptmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c)
+{
+ mp_int s, x, mu;
+ mp_err res;
+ mp_digit d, *db = DIGITS(b);
+ mp_size ub = USED(b);
+ int dig, bit;
+
+ ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+ if(mp_cmp_z(b) < 0 || mp_cmp_z(m) <= 0)
+ return MP_RANGE;
+
+ if((res = mp_init(&s)) != MP_OKAY)
+ return res;
+ if((res = mp_init_copy(&x, a)) != MP_OKAY)
+ goto X;
+ if((res = mp_mod(&x, m, &x)) != MP_OKAY ||
+ (res = mp_init(&mu)) != MP_OKAY)
+ goto MU;
+
+ mp_set(&s, 1);
+
+ /* mu = b^2k / m */
+ s_mp_add_d(&mu, 1);
+ s_mp_lshd(&mu, 2 * USED(m));
+ if((res = mp_div(&mu, m, &mu, NULL)) != MP_OKAY)
+ goto CLEANUP;
+
+ /* Loop over digits of b in ascending order, except highest order */
+ for(dig = 0; dig < (ub - 1); dig++) {
+ d = *db++;
+
+ /* Loop over the bits of the lower-order digits */
+ for(bit = 0; bit < DIGIT_BIT; bit++) {
+ if(d & 1) {
+ if((res = s_mp_mul(&s, &x)) != MP_OKAY)
+ goto CLEANUP;
+ if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY)
+ goto CLEANUP;
+ }
+
+ d >>= 1;
+
+ if((res = s_mp_sqr(&x)) != MP_OKAY)
+ goto CLEANUP;
+ if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY)
+ goto CLEANUP;
+ }
+ }
+
+ /* Now do the last digit... */
+ d = *db;
+
+ while(d) {
+ if(d & 1) {
+ if((res = s_mp_mul(&s, &x)) != MP_OKAY)
+ goto CLEANUP;
+ if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY)
+ goto CLEANUP;
+ }
+
+ d >>= 1;
+
+ if((res = s_mp_sqr(&x)) != MP_OKAY)
+ goto CLEANUP;
+ if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY)
+ goto CLEANUP;
+ }
+
+ s_mp_exch(&s, c);
+
+ CLEANUP:
+ mp_clear(&mu);
+ MU:
+ mp_clear(&x);
+ X:
+ mp_clear(&s);
+
+ return res;
+
+} /* end mp_exptmod() */
+
+/* }}} */
+
+/* {{{ mp_exptmod_d(a, d, m, c) */
+
+mp_err mp_exptmod_d(mp_int *a, mp_digit d, mp_int *m, mp_int *c)
+{
+ mp_int s, x;
+ mp_err res;
+
+ ARGCHK(a != NULL && c != NULL, MP_BADARG);
+
+ if((res = mp_init(&s)) != MP_OKAY)
+ return res;
+ if((res = mp_init_copy(&x, a)) != MP_OKAY)
+ goto X;
+
+ mp_set(&s, 1);
+
+ while(d != 0) {
+ if(d & 1) {
+ if((res = s_mp_mul(&s, &x)) != MP_OKAY ||
+ (res = mp_mod(&s, m, &s)) != MP_OKAY)
+ goto CLEANUP;
+ }
+
+ d /= 2;
+
+ if((res = s_mp_sqr(&x)) != MP_OKAY ||
+ (res = mp_mod(&x, m, &x)) != MP_OKAY)
+ goto CLEANUP;
+ }
+
+ s_mp_exch(&s, c);
+
+CLEANUP:
+ mp_clear(&x);
+X:
+ mp_clear(&s);
+
+ return res;
+
+} /* end mp_exptmod_d() */
+
+/* }}} */
+#endif /* if MP_MODARITH */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ Comparison functions */
+
+/* {{{ mp_cmp_z(a) */
+
+/*
+ mp_cmp_z(a)
+
+ Compare a <=> 0. Returns <0 if a<0, 0 if a=0, >0 if a>0.
+ */
+
+int mp_cmp_z(mp_int *a)
+{
+ if(SIGN(a) == MP_NEG)
+ return MP_LT;
+ else if(USED(a) == 1 && DIGIT(a, 0) == 0)
+ return MP_EQ;
+ else
+ return MP_GT;
+
+} /* end mp_cmp_z() */
+
+/* }}} */
+
+/* {{{ mp_cmp_d(a, d) */
+
+/*
+ mp_cmp_d(a, d)
+
+ Compare a <=> d. Returns <0 if a<d, 0 if a=d, >0 if a>d
+ */
+
+int mp_cmp_d(mp_int *a, mp_digit d)
+{
+ ARGCHK(a != NULL, MP_EQ);
+
+ if(SIGN(a) == MP_NEG)
+ return MP_LT;
+
+ return s_mp_cmp_d(a, d);
+
+} /* end mp_cmp_d() */
+
+/* }}} */
+
+/* {{{ mp_cmp(a, b) */
+
+int mp_cmp(mp_int *a, mp_int *b)
+{
+ ARGCHK(a != NULL && b != NULL, MP_EQ);
+
+ if(SIGN(a) == SIGN(b)) {
+ int mag;
+
+ if((mag = s_mp_cmp(a, b)) == MP_EQ)
+ return MP_EQ;
+
+ if(SIGN(a) == MP_ZPOS)
+ return mag;
+ else
+ return -mag;
+
+ } else if(SIGN(a) == MP_ZPOS) {
+ return MP_GT;
+ } else {
+ return MP_LT;
+ }
+
+} /* end mp_cmp() */
+
+/* }}} */
+
+/* {{{ mp_cmp_mag(a, b) */
+
+/*
+ mp_cmp_mag(a, b)
+
+ Compares |a| <=> |b|, and returns an appropriate comparison result
+ */
+
+int mp_cmp_mag(mp_int *a, mp_int *b)
+{
+ ARGCHK(a != NULL && b != NULL, MP_EQ);
+
+ return s_mp_cmp(a, b);
+
+} /* end mp_cmp_mag() */
+
+/* }}} */
+
+/* {{{ mp_cmp_int(a, z) */
+
+/*
+ This just converts z to an mp_int, and uses the existing comparison
+ routines. This is sort of inefficient, but it's not clear to me how
+ frequently this wil get used anyway. For small positive constants,
+ you can always use mp_cmp_d(), and for zero, there is mp_cmp_z().
+ */
+int mp_cmp_int(mp_int *a, long z)
+{
+ mp_int tmp;
+ int out;
+
+ ARGCHK(a != NULL, MP_EQ);
+
+ mp_init(&tmp); mp_set_int(&tmp, z);
+ out = mp_cmp(a, &tmp);
+ mp_clear(&tmp);
+
+ return out;
+
+} /* end mp_cmp_int() */
+
+/* }}} */
+
+/* {{{ mp_isodd(a) */
+
+/*
+ mp_isodd(a)
+
+ Returns a true (non-zero) value if a is odd, false (zero) otherwise.
+ */
+int mp_isodd(mp_int *a)
+{
+ ARGCHK(a != NULL, 0);
+
+ return (DIGIT(a, 0) & 1);
+
+} /* end mp_isodd() */
+
+/* }}} */
+
+/* {{{ mp_iseven(a) */
+
+int mp_iseven(mp_int *a)
+{
+ return !mp_isodd(a);
+
+} /* end mp_iseven() */
+
+/* }}} */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ Number theoretic functions */
+
+#if MP_NUMTH
+/* {{{ mp_gcd(a, b, c) */
+
+/*
+ Like the old mp_gcd() function, except computes the GCD using the
+ binary algorithm due to Josef Stein in 1961 (via Knuth).
+ */
+mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c)
+{
+ mp_err res;
+ mp_int u, v, t;
+ mp_size k = 0;
+
+ ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+ if(mp_cmp_z(a) == MP_EQ && mp_cmp_z(b) == MP_EQ)
+ return MP_RANGE;
+ if(mp_cmp_z(a) == MP_EQ) {
+ return mp_copy(b, c);
+ } else if(mp_cmp_z(b) == MP_EQ) {
+ return mp_copy(a, c);
+ }
+
+ if((res = mp_init(&t)) != MP_OKAY)
+ return res;
+ if((res = mp_init_copy(&u, a)) != MP_OKAY)
+ goto U;
+ if((res = mp_init_copy(&v, b)) != MP_OKAY)
+ goto V;
+
+ SIGN(&u) = MP_ZPOS;
+ SIGN(&v) = MP_ZPOS;
+
+ /* Divide out common factors of 2 until at least 1 of a, b is even */
+ while(mp_iseven(&u) && mp_iseven(&v)) {
+ s_mp_div_2(&u);
+ s_mp_div_2(&v);
+ ++k;
+ }
+
+ /* Initialize t */
+ if(mp_isodd(&u)) {
+ if((res = mp_copy(&v, &t)) != MP_OKAY)
+ goto CLEANUP;
+
+ /* t = -v */
+ if(SIGN(&v) == MP_ZPOS)
+ SIGN(&t) = MP_NEG;
+ else
+ SIGN(&t) = MP_ZPOS;
+
+ } else {
+ if((res = mp_copy(&u, &t)) != MP_OKAY)
+ goto CLEANUP;
+
+ }
+
+ for(;;) {
+ while(mp_iseven(&t)) {
+ s_mp_div_2(&t);
+ }
+
+ if(mp_cmp_z(&t) == MP_GT) {
+ if((res = mp_copy(&t, &u)) != MP_OKAY)
+ goto CLEANUP;
+
+ } else {
+ if((res = mp_copy(&t, &v)) != MP_OKAY)
+ goto CLEANUP;
+
+ /* v = -t */
+ if(SIGN(&t) == MP_ZPOS)
+ SIGN(&v) = MP_NEG;
+ else
+ SIGN(&v) = MP_ZPOS;
+ }
+
+ if((res = mp_sub(&u, &v, &t)) != MP_OKAY)
+ goto CLEANUP;
+
+ if(s_mp_cmp_d(&t, 0) == MP_EQ)
+ break;
+ }
+
+ s_mp_2expt(&v, k); /* v = 2^k */
+ res = mp_mul(&u, &v, c); /* c = u * v */
+
+ CLEANUP:
+ mp_clear(&v);
+ V:
+ mp_clear(&u);
+ U:
+ mp_clear(&t);
+
+ return res;
+
+} /* end mp_bgcd() */
+
+/* }}} */
+
+/* {{{ mp_lcm(a, b, c) */
+
+/* We compute the least common multiple using the rule:
+
+ ab = [a, b](a, b)
+
+ ... by computing the product, and dividing out the gcd.
+ */
+
+mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c)
+{
+ mp_int gcd, prod;
+ mp_err res;
+
+ ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+ /* Set up temporaries */
+ if((res = mp_init(&gcd)) != MP_OKAY)
+ return res;
+ if((res = mp_init(&prod)) != MP_OKAY)
+ goto GCD;
+
+ if((res = mp_mul(a, b, &prod)) != MP_OKAY)
+ goto CLEANUP;
+ if((res = mp_gcd(a, b, &gcd)) != MP_OKAY)
+ goto CLEANUP;
+
+ res = mp_div(&prod, &gcd, c, NULL);
+
+ CLEANUP:
+ mp_clear(&prod);
+ GCD:
+ mp_clear(&gcd);
+
+ return res;
+
+} /* end mp_lcm() */
+
+/* }}} */
+
+/* {{{ mp_xgcd(a, b, g, x, y) */
+
+/*
+ mp_xgcd(a, b, g, x, y)
+
+ Compute g = (a, b) and values x and y satisfying Bezout's identity
+ (that is, ax + by = g). This uses the extended binary GCD algorithm
+ based on the Stein algorithm used for mp_gcd()
+ */
+
+mp_err mp_xgcd(mp_int *a, mp_int *b, mp_int *g, mp_int *x, mp_int *y)
+{
+ mp_int gx, xc, yc, u, v, A, B, C, D;
+ mp_int *clean[9];
+ mp_err res;
+ int last = -1;
+
+ if(mp_cmp_z(b) == 0)
+ return MP_RANGE;
+
+ /* Initialize all these variables we need */
+ if((res = mp_init(&u)) != MP_OKAY) goto CLEANUP;
+ clean[++last] = &u;
+ if((res = mp_init(&v)) != MP_OKAY) goto CLEANUP;
+ clean[++last] = &v;
+ if((res = mp_init(&gx)) != MP_OKAY) goto CLEANUP;
+ clean[++last] = &gx;
+ if((res = mp_init(&A)) != MP_OKAY) goto CLEANUP;
+ clean[++last] = &A;
+ if((res = mp_init(&B)) != MP_OKAY) goto CLEANUP;
+ clean[++last] = &B;
+ if((res = mp_init(&C)) != MP_OKAY) goto CLEANUP;
+ clean[++last] = &C;
+ if((res = mp_init(&D)) != MP_OKAY) goto CLEANUP;
+ clean[++last] = &D;
+ if((res = mp_init_copy(&xc, a)) != MP_OKAY) goto CLEANUP;
+ clean[++last] = &xc;
+ mp_abs(&xc, &xc);
+ if((res = mp_init_copy(&yc, b)) != MP_OKAY) goto CLEANUP;
+ clean[++last] = &yc;
+ mp_abs(&yc, &yc);
+
+ mp_set(&gx, 1);
+
+ /* Divide by two until at least one of them is even */
+ while(mp_iseven(&xc) && mp_iseven(&yc)) {
+ s_mp_div_2(&xc);
+ s_mp_div_2(&yc);
+ if((res = s_mp_mul_2(&gx)) != MP_OKAY)
+ goto CLEANUP;
+ }
+
+ mp_copy(&xc, &u);
+ mp_copy(&yc, &v);
+ mp_set(&A, 1); mp_set(&D, 1);
+
+ /* Loop through binary GCD algorithm */
+ for(;;) {
+ while(mp_iseven(&u)) {
+ s_mp_div_2(&u);
+
+ if(mp_iseven(&A) && mp_iseven(&B)) {
+ s_mp_div_2(&A); s_mp_div_2(&B);
+ } else {
+ if((res = mp_add(&A, &yc, &A)) != MP_OKAY) goto CLEANUP;
+ s_mp_div_2(&A);
+ if((res = mp_sub(&B, &xc, &B)) != MP_OKAY) goto CLEANUP;
+ s_mp_div_2(&B);
+ }
+ }
+
+ while(mp_iseven(&v)) {
+ s_mp_div_2(&v);
+
+ if(mp_iseven(&C) && mp_iseven(&D)) {
+ s_mp_div_2(&C); s_mp_div_2(&D);
+ } else {
+ if((res = mp_add(&C, &yc, &C)) != MP_OKAY) goto CLEANUP;
+ s_mp_div_2(&C);
+ if((res = mp_sub(&D, &xc, &D)) != MP_OKAY) goto CLEANUP;
+ s_mp_div_2(&D);
+ }
+ }
+
+ if(mp_cmp(&u, &v) >= 0) {
+ if((res = mp_sub(&u, &v, &u)) != MP_OKAY) goto CLEANUP;
+ if((res = mp_sub(&A, &C, &A)) != MP_OKAY) goto CLEANUP;
+ if((res = mp_sub(&B, &D, &B)) != MP_OKAY) goto CLEANUP;
+
+ } else {
+ if((res = mp_sub(&v, &u, &v)) != MP_OKAY) goto CLEANUP;
+ if((res = mp_sub(&C, &A, &C)) != MP_OKAY) goto CLEANUP;
+ if((res = mp_sub(&D, &B, &D)) != MP_OKAY) goto CLEANUP;
+
+ }
+
+ /* If we're done, copy results to output */
+ if(mp_cmp_z(&u) == 0) {
+ if(x)
+ if((res = mp_copy(&C, x)) != MP_OKAY) goto CLEANUP;
+
+ if(y)
+ if((res = mp_copy(&D, y)) != MP_OKAY) goto CLEANUP;
+
+ if(g)
+ if((res = mp_mul(&gx, &v, g)) != MP_OKAY) goto CLEANUP;
+
+ break;
+ }
+ }
+
+ CLEANUP:
+ while(last >= 0)
+ mp_clear(clean[last--]);
+
+ return res;
+
+} /* end mp_xgcd() */
+
+/* }}} */
+
+/* {{{ mp_invmod(a, m, c) */
+
+/*
+ mp_invmod(a, m, c)
+
+ Compute c = a^-1 (mod m), if there is an inverse for a (mod m).
+ This is equivalent to the question of whether (a, m) = 1. If not,
+ MP_UNDEF is returned, and there is no inverse.
+ */
+
+mp_err mp_invmod(mp_int *a, mp_int *m, mp_int *c)
+{
+ mp_int g, x;
+ mp_err res;
+
+ ARGCHK(a && m && c, MP_BADARG);
+
+ if(mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
+ return MP_RANGE;
+
+ if((res = mp_init(&g)) != MP_OKAY)
+ return res;
+ if((res = mp_init(&x)) != MP_OKAY)
+ goto X;
+
+ if((res = mp_xgcd(a, m, &g, &x, NULL)) != MP_OKAY)
+ goto CLEANUP;
+
+ if(mp_cmp_d(&g, 1) != MP_EQ) {
+ res = MP_UNDEF;
+ goto CLEANUP;
+ }
+
+ res = mp_mod(&x, m, c);
+ SIGN(c) = SIGN(a);
+
+CLEANUP:
+ mp_clear(&x);
+X:
+ mp_clear(&g);
+
+ return res;
+
+} /* end mp_invmod() */
+
+/* }}} */
+#endif /* if MP_NUMTH */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ mp_print(mp, ofp) */
+
+#if MP_IOFUNC
+/*
+ mp_print(mp, ofp)
+
+ Print a textual representation of the given mp_int on the output
+ stream 'ofp'. Output is generated using the internal radix.
+ */
+
+void mp_print(mp_int *mp, FILE *ofp)
+{
+ int ix;
+
+ if(mp == NULL || ofp == NULL)
+ return;
+
+ fputc((SIGN(mp) == MP_NEG) ? '-' : '+', ofp);
+
+ for(ix = USED(mp) - 1; ix >= 0; ix--) {
+ fprintf(ofp, DIGIT_FMT, DIGIT(mp, ix));
+ }
+
+} /* end mp_print() */
+
+#endif /* if MP_IOFUNC */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ More I/O Functions */
+
+/* {{{ mp_read_signed_bin(mp, str, len) */
+
+/*
+ mp_read_signed_bin(mp, str, len)
+
+ Read in a raw value (base 256) into the given mp_int
+ */
+
+mp_err mp_read_signed_bin(mp_int *mp, unsigned char *str, int len)
+{
+ mp_err res;
+
+ ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG);
+
+ if((res = mp_read_unsigned_bin(mp, str + 1, len - 1)) == MP_OKAY) {
+ /* Get sign from first byte */
+ if(str[0])
+ SIGN(mp) = MP_NEG;
+ else
+ SIGN(mp) = MP_ZPOS;
+ }
+
+ return res;
+
+} /* end mp_read_signed_bin() */
+
+/* }}} */
+
+/* {{{ mp_signed_bin_size(mp) */
+
+int mp_signed_bin_size(mp_int *mp)
+{
+ ARGCHK(mp != NULL, 0);
+
+ return mp_unsigned_bin_size(mp) + 1;
+
+} /* end mp_signed_bin_size() */
+
+/* }}} */
+
+/* {{{ mp_to_signed_bin(mp, str) */
+
+mp_err mp_to_signed_bin(mp_int *mp, unsigned char *str)
+{
+ ARGCHK(mp != NULL && str != NULL, MP_BADARG);
+
+ /* Caller responsible for allocating enough memory (use mp_raw_size(mp)) */
+ str[0] = (char)SIGN(mp);
+
+ return mp_to_unsigned_bin(mp, str + 1);
+
+} /* end mp_to_signed_bin() */
+
+/* }}} */
+
+/* {{{ mp_read_unsigned_bin(mp, str, len) */
+
+/*
+ mp_read_unsigned_bin(mp, str, len)
+
+ Read in an unsigned value (base 256) into the given mp_int
+ */
+
+mp_err mp_read_unsigned_bin(mp_int *mp, unsigned char *str, int len)
+{
+ int ix;
+ mp_err res;
+
+ ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG);
+
+ mp_zero(mp);
+
+ for(ix = 0; ix < len; ix++) {
+ if((res = s_mp_mul_2d(mp, CHAR_BIT)) != MP_OKAY)
+ return res;
+
+ if((res = mp_add_d(mp, str[ix], mp)) != MP_OKAY)
+ return res;
+ }
+
+ return MP_OKAY;
+
+} /* end mp_read_unsigned_bin() */
+
+/* }}} */
+
+/* {{{ mp_unsigned_bin_size(mp) */
+
+int mp_unsigned_bin_size(mp_int *mp)
+{
+ mp_digit topdig;
+ int count;
+
+ ARGCHK(mp != NULL, 0);
+
+ /* Special case for the value zero */
+ if(USED(mp) == 1 && DIGIT(mp, 0) == 0)
+ return 1;
+
+ count = (USED(mp) - 1) * sizeof(mp_digit);
+ topdig = DIGIT(mp, USED(mp) - 1);
+
+ while(topdig != 0) {
+ ++count;
+ topdig >>= CHAR_BIT;
+ }
+
+ return count;
+
+} /* end mp_unsigned_bin_size() */
+
+/* }}} */
+
+/* {{{ mp_to_unsigned_bin(mp, str) */
+
+mp_err mp_to_unsigned_bin(mp_int *mp, unsigned char *str)
+{
+ mp_digit *dp, *end, d;
+ unsigned char *spos;
+
+ ARGCHK(mp != NULL && str != NULL, MP_BADARG);
+
+ dp = DIGITS(mp);
+ end = dp + USED(mp) - 1;
+ spos = str;
+
+ /* Special case for zero, quick test */
+ if(dp == end && *dp == 0) {
+ *str = '\0';
+ return MP_OKAY;
+ }
+
+ /* Generate digits in reverse order */
+ while(dp < end) {
+ int ix;
+
+ d = *dp;
+ for(ix = 0; ix < sizeof(mp_digit); ++ix) {
+ *spos = d & UCHAR_MAX;
+ d >>= CHAR_BIT;
+ ++spos;
+ }
+
+ ++dp;
+ }
+
+ /* Now handle last digit specially, high order zeroes are not written */
+ d = *end;
+ while(d != 0) {
+ *spos = d & UCHAR_MAX;
+ d >>= CHAR_BIT;
+ ++spos;
+ }
+
+ /* Reverse everything to get digits in the correct order */
+ while(--spos > str) {
+ unsigned char t = *str;
+ *str = *spos;
+ *spos = t;
+
+ ++str;
+ }
+
+ return MP_OKAY;
+
+} /* end mp_to_unsigned_bin() */
+
+/* }}} */
+
+/* {{{ mp_count_bits(mp) */
+
+int mp_count_bits(mp_int *mp)
+{
+ int len;
+ mp_digit d;
+
+ ARGCHK(mp != NULL, MP_BADARG);
+
+ len = DIGIT_BIT * (USED(mp) - 1);
+ d = DIGIT(mp, USED(mp) - 1);
+
+ while(d != 0) {
+ ++len;
+ d >>= 1;
+ }
+
+ return len;
+
+} /* end mp_count_bits() */
+
+/* }}} */
+
+/* {{{ mp_read_radix(mp, str, radix) */
+
+/*
+ mp_read_radix(mp, str, radix)
+
+ Read an integer from the given string, and set mp to the resulting
+ value. The input is presumed to be in base 10. Leading non-digit
+ characters are ignored, and the function reads until a non-digit
+ character or the end of the string.
+ */
+
+mp_err mp_read_radix(mp_int *mp, unsigned char *str, int radix)
+{
+ int ix = 0, val = 0;
+ mp_err res;
+ mp_sign sig = MP_ZPOS;
+
+ ARGCHK(mp != NULL && str != NULL && radix >= 2 && radix <= MAX_RADIX,
+ MP_BADARG);
+
+ mp_zero(mp);
+
+ /* Skip leading non-digit characters until a digit or '-' or '+' */
+ while(str[ix] &&
+ (s_mp_tovalue(str[ix], radix) < 0) &&
+ str[ix] != '-' &&
+ str[ix] != '+') {
+ ++ix;
+ }
+
+ if(str[ix] == '-') {
+ sig = MP_NEG;
+ ++ix;
+ } else if(str[ix] == '+') {
+ sig = MP_ZPOS; /* this is the default anyway... */
+ ++ix;
+ }
+
+ while((val = s_mp_tovalue(str[ix], radix)) >= 0) {
+ if((res = s_mp_mul_d(mp, radix)) != MP_OKAY)
+ return res;
+ if((res = s_mp_add_d(mp, val)) != MP_OKAY)
+ return res;
+ ++ix;
+ }
+
+ if(s_mp_cmp_d(mp, 0) == MP_EQ)
+ SIGN(mp) = MP_ZPOS;
+ else
+ SIGN(mp) = sig;
+
+ return MP_OKAY;
+
+} /* end mp_read_radix() */
+
+/* }}} */
+
+/* {{{ mp_radix_size(mp, radix) */
+
+int mp_radix_size(mp_int *mp, int radix)
+{
+ int len;
+ ARGCHK(mp != NULL, 0);
+
+ len = s_mp_outlen(mp_count_bits(mp), radix) + 1; /* for NUL terminator */
+
+ if(mp_cmp_z(mp) < 0)
+ ++len; /* for sign */
+
+ return len;
+
+} /* end mp_radix_size() */
+
+/* }}} */
+
+/* {{{ mp_value_radix_size(num, qty, radix) */
+
+/* num = number of digits
+ qty = number of bits per digit
+ radix = target base
+
+ Return the number of digits in the specified radix that would be
+ needed to express 'num' digits of 'qty' bits each.
+ */
+int mp_value_radix_size(int num, int qty, int radix)
+{
+ ARGCHK(num >= 0 && qty > 0 && radix >= 2 && radix <= MAX_RADIX, 0);
+
+ return s_mp_outlen(num * qty, radix);
+
+} /* end mp_value_radix_size() */
+
+/* }}} */
+
+/* {{{ mp_toradix(mp, str, radix) */
+
+mp_err mp_toradix(mp_int *mp, unsigned char *str, int radix)
+{
+ int ix, pos = 0;
+
+ ARGCHK(mp != NULL && str != NULL, MP_BADARG);
+ ARGCHK(radix > 1 && radix <= MAX_RADIX, MP_RANGE);
+
+ if(mp_cmp_z(mp) == MP_EQ) {
+ str[0] = '0';
+ str[1] = '\0';
+ } else {
+ mp_err res;
+ mp_int tmp;
+ mp_sign sgn;
+ mp_digit rem, rdx = (mp_digit)radix;
+ char ch;
+
+ if((res = mp_init_copy(&tmp, mp)) != MP_OKAY)
+ return res;
+
+ /* Save sign for later, and take absolute value */
+ sgn = SIGN(&tmp); SIGN(&tmp) = MP_ZPOS;
+
+ /* Generate output digits in reverse order */
+ while(mp_cmp_z(&tmp) != 0) {
+ if((res = s_mp_div_d(&tmp, rdx, &rem)) != MP_OKAY) {
+ mp_clear(&tmp);
+ return res;
+ }
+
+ /* Generate digits, use capital letters */
+ ch = s_mp_todigit(rem, radix, 0);
+
+ str[pos++] = ch;
+ }
+
+ /* Add - sign if original value was negative */
+ if(sgn == MP_NEG)
+ str[pos++] = '-';
+
+ /* Add trailing NUL to end the string */
+ str[pos--] = '\0';
+
+ /* Reverse the digits and sign indicator */
+ ix = 0;
+ while(ix < pos) {
+ char tmp = str[ix];
+
+ str[ix] = str[pos];
+ str[pos] = tmp;
+ ++ix;
+ --pos;
+ }
+
+ mp_clear(&tmp);
+ }
+
+ return MP_OKAY;
+
+} /* end mp_toradix() */
+
+/* }}} */
+
+/* {{{ mp_char2value(ch, r) */
+
+int mp_char2value(char ch, int r)
+{
+ return s_mp_tovalue(ch, r);
+
+} /* end mp_tovalue() */
+
+/* }}} */
+
+/* }}} */
+
+/* {{{ mp_strerror(ec) */
+
+/*
+ mp_strerror(ec)
+
+ Return a string describing the meaning of error code 'ec'. The
+ string returned is allocated in static memory, so the caller should
+ not attempt to modify or free the memory associated with this
+ string.
+ */
+const char *mp_strerror(mp_err ec)
+{
+ int aec = (ec < 0) ? -ec : ec;
+
+ /* Code values are negative, so the senses of these comparisons
+ are accurate */
+ if(ec < MP_LAST_CODE || ec > MP_OKAY) {
+ return mp_err_string[0]; /* unknown error code */
+ } else {
+ return mp_err_string[aec + 1];
+ }
+
+} /* end mp_strerror() */
+
+/* }}} */
+
+/*========================================================================*/
+/*------------------------------------------------------------------------*/
+/* Static function definitions (internal use only) */
+
+/* {{{ Memory management */
+
+/* {{{ s_mp_grow(mp, min) */
+
+/* Make sure there are at least 'min' digits allocated to mp */
+mp_err s_mp_grow(mp_int *mp, mp_size min)
+{
+ if(min > ALLOC(mp)) {
+ mp_digit *tmp;
+
+ /* Set min to next nearest default precision block size */
+ min = ((min + (s_mp_defprec - 1)) / s_mp_defprec) * s_mp_defprec;
+
+ if((tmp = s_mp_alloc(min, sizeof(mp_digit))) == NULL)
+ return MP_MEM;
+
+ s_mp_copy(DIGITS(mp), tmp, USED(mp));
+
+#if MP_CRYPTO
+ s_mp_setz(DIGITS(mp), ALLOC(mp));
+#endif
+ s_mp_free(DIGITS(mp));
+ DIGITS(mp) = tmp;
+ ALLOC(mp) = min;
+ }
+
+ return MP_OKAY;
+
+} /* end s_mp_grow() */
+
+/* }}} */
+
+/* {{{ s_mp_pad(mp, min) */
+
+/* Make sure the used size of mp is at least 'min', growing if needed */
+mp_err s_mp_pad(mp_int *mp, mp_size min)
+{
+ if(min > USED(mp)) {
+ mp_err res;
+
+ /* Make sure there is room to increase precision */
+ if(min > ALLOC(mp) && (res = s_mp_grow(mp, min)) != MP_OKAY)
+ return res;
+
+ /* Increase precision; should already be 0-filled */
+ USED(mp) = min;
+ }
+
+ return MP_OKAY;
+
+} /* end s_mp_pad() */
+
+/* }}} */
+
+/* {{{ s_mp_setz(dp, count) */
+
+#if MP_MACRO == 0
+/* Set 'count' digits pointed to by dp to be zeroes */
+void s_mp_setz(mp_digit *dp, mp_size count)
+{
+#if MP_MEMSET == 0
+ int ix;
+
+ for(ix = 0; ix < count; ix++)
+ dp[ix] = 0;
+#else
+ memset(dp, 0, count * sizeof(mp_digit));
+#endif
+
+} /* end s_mp_setz() */
+#endif
+
+/* }}} */
+
+/* {{{ s_mp_copy(sp, dp, count) */
+
+#if MP_MACRO == 0
+/* Copy 'count' digits from sp to dp */
+void s_mp_copy(mp_digit *sp, mp_digit *dp, mp_size count)
+{
+#if MP_MEMCPY == 0
+ int ix;
+
+ for(ix = 0; ix < count; ix++)
+ dp[ix] = sp[ix];
+#else
+ memcpy(dp, sp, count * sizeof(mp_digit));
+#endif
+
+} /* end s_mp_copy() */
+#endif
+
+/* }}} */
+
+/* {{{ s_mp_alloc(nb, ni) */
+
+#if MP_MACRO == 0
+/* Allocate ni records of nb bytes each, and return a pointer to that */
+void *s_mp_alloc(size_t nb, size_t ni)
+{
+ return calloc(nb, ni);
+
+} /* end s_mp_alloc() */
+#endif
+
+/* }}} */
+
+/* {{{ s_mp_free(ptr) */
+
+#if MP_MACRO == 0
+/* Free the memory pointed to by ptr */
+void s_mp_free(void *ptr)
+{
+ if(ptr)
+ free(ptr);
+
+} /* end s_mp_free() */
+#endif
+
+/* }}} */
+
+/* {{{ s_mp_clamp(mp) */
+
+/* Remove leading zeroes from the given value */
+void s_mp_clamp(mp_int *mp)
+{
+ mp_size du = USED(mp);
+ mp_digit *zp = DIGITS(mp) + du - 1;
+
+ while(du > 1 && !*zp--)
+ --du;
+
+ USED(mp) = du;
+
+} /* end s_mp_clamp() */
+
+
+/* }}} */
+
+/* {{{ s_mp_exch(a, b) */
+
+/* Exchange the data for a and b; (b, a) = (a, b) */
+void s_mp_exch(mp_int *a, mp_int *b)
+{
+ mp_int tmp;
+
+ tmp = *a;
+ *a = *b;
+ *b = tmp;
+
+} /* end s_mp_exch() */
+
+/* }}} */
+
+/* }}} */
+
+/* {{{ Arithmetic helpers */
+
+/* {{{ s_mp_lshd(mp, p) */
+
+/*
+ Shift mp leftward by p digits, growing if needed, and zero-filling
+ the in-shifted digits at the right end. This is a convenient
+ alternative to multiplication by powers of the radix
+ */
+
+mp_err s_mp_lshd(mp_int *mp, mp_size p)
+{
+ mp_err res;
+ mp_size pos;
+ mp_digit *dp;
+ int ix;
+
+ if(p == 0)
+ return MP_OKAY;
+
+ if((res = s_mp_pad(mp, USED(mp) + p)) != MP_OKAY)
+ return res;
+
+ pos = USED(mp) - 1;
+ dp = DIGITS(mp);
+
+ /* Shift all the significant figures over as needed */
+ for(ix = pos - p; ix >= 0; ix--)
+ dp[ix + p] = dp[ix];
+
+ /* Fill the bottom digits with zeroes */
+ for(ix = 0; ix < p; ix++)
+ dp[ix] = 0;
+
+ return MP_OKAY;
+
+} /* end s_mp_lshd() */
+
+/* }}} */
+
+/* {{{ s_mp_rshd(mp, p) */
+
+/*
+ Shift mp rightward by p digits. Maintains the invariant that
+ digits above the precision are all zero. Digits shifted off the
+ end are lost. Cannot fail.
+ */
+
+void s_mp_rshd(mp_int *mp, mp_size p)
+{
+ mp_size ix;
+ mp_digit *dp;
+
+ if(p == 0)
+ return;
+
+ /* Shortcut when all digits are to be shifted off */
+ if(p >= USED(mp)) {
+ s_mp_setz(DIGITS(mp), ALLOC(mp));
+ USED(mp) = 1;
+ SIGN(mp) = MP_ZPOS;
+ return;
+ }
+
+ /* Shift all the significant figures over as needed */
+ dp = DIGITS(mp);
+ for(ix = p; ix < USED(mp); ix++)
+ dp[ix - p] = dp[ix];
+
+ /* Fill the top digits with zeroes */
+ ix -= p;
+ while(ix < USED(mp))
+ dp[ix++] = 0;
+
+ /* Strip off any leading zeroes */
+ s_mp_clamp(mp);
+
+} /* end s_mp_rshd() */
+
+/* }}} */
+
+/* {{{ s_mp_div_2(mp) */
+
+/* Divide by two -- take advantage of radix properties to do it fast */
+void s_mp_div_2(mp_int *mp)
+{
+ s_mp_div_2d(mp, 1);
+
+} /* end s_mp_div_2() */
+
+/* }}} */
+
+/* {{{ s_mp_mul_2(mp) */
+
+mp_err s_mp_mul_2(mp_int *mp)
+{
+ int ix;
+ mp_digit kin = 0, kout, *dp = DIGITS(mp);
+ mp_err res;
+
+ /* Shift digits leftward by 1 bit */
+ for(ix = 0; ix < USED(mp); ix++) {
+ kout = (dp[ix] >> (DIGIT_BIT - 1)) & 1;
+ dp[ix] = (dp[ix] << 1) | kin;
+
+ kin = kout;
+ }
+
+ /* Deal with rollover from last digit */
+ if(kin) {
+ if(ix >= ALLOC(mp)) {
+ if((res = s_mp_grow(mp, ALLOC(mp) + 1)) != MP_OKAY)
+ return res;
+ dp = DIGITS(mp);
+ }
+
+ dp[ix] = kin;
+ USED(mp) += 1;
+ }
+
+ return MP_OKAY;
+
+} /* end s_mp_mul_2() */
+
+/* }}} */
+
+/* {{{ s_mp_mod_2d(mp, d) */
+
+/*
+ Remainder the integer by 2^d, where d is a number of bits. This
+ amounts to a bitwise AND of the value, and does not require the full
+ division code
+ */
+void s_mp_mod_2d(mp_int *mp, mp_digit d)
+{
+ unsigned int ndig = (d / DIGIT_BIT), nbit = (d % DIGIT_BIT);
+ unsigned int ix;
+ mp_digit dmask, *dp = DIGITS(mp);
+
+ if(ndig >= USED(mp))
+ return;
+
+ /* Flush all the bits above 2^d in its digit */
+ dmask = (1 << nbit) - 1;
+ dp[ndig] &= dmask;
+
+ /* Flush all digits above the one with 2^d in it */
+ for(ix = ndig + 1; ix < USED(mp); ix++)
+ dp[ix] = 0;
+
+ s_mp_clamp(mp);
+
+} /* end s_mp_mod_2d() */
+
+/* }}} */
+
+/* {{{ s_mp_mul_2d(mp, d) */
+
+/*
+ Multiply by the integer 2^d, where d is a number of bits. This
+ amounts to a bitwise shift of the value, and does not require the
+ full multiplication code.
+ */
+mp_err s_mp_mul_2d(mp_int *mp, mp_digit d)
+{
+ mp_err res;
+ mp_digit save, next, mask, *dp;
+ mp_size used;
+ int ix;
+
+ if((res = s_mp_lshd(mp, d / DIGIT_BIT)) != MP_OKAY)
+ return res;
+
+ dp = DIGITS(mp); used = USED(mp);
+ d %= DIGIT_BIT;
+
+ mask = (1 << d) - 1;
+
+ /* If the shift requires another digit, make sure we've got one to
+ work with */
+ if((dp[used - 1] >> (DIGIT_BIT - d)) & mask) {
+ if((res = s_mp_grow(mp, used + 1)) != MP_OKAY)
+ return res;
+ dp = DIGITS(mp);
+ }
+
+ /* Do the shifting... */
+ save = 0;
+ for(ix = 0; ix < used; ix++) {
+ next = (dp[ix] >> (DIGIT_BIT - d)) & mask;
+ dp[ix] = (dp[ix] << d) | save;
+ save = next;
+ }
+
+ /* If, at this point, we have a nonzero carryout into the next
+ digit, we'll increase the size by one digit, and store it...
+ */
+ if(save) {
+ dp[used] = save;
+ USED(mp) += 1;
+ }
+
+ s_mp_clamp(mp);
+ return MP_OKAY;
+
+} /* end s_mp_mul_2d() */
+
+/* }}} */
+
+/* {{{ s_mp_div_2d(mp, d) */
+
+/*
+ Divide the integer by 2^d, where d is a number of bits. This
+ amounts to a bitwise shift of the value, and does not require the
+ full division code (used in Barrett reduction, see below)
+ */
+void s_mp_div_2d(mp_int *mp, mp_digit d)
+{
+ int ix;
+ mp_digit save, next, mask, *dp = DIGITS(mp);
+
+ s_mp_rshd(mp, d / DIGIT_BIT);
+ d %= DIGIT_BIT;
+
+ mask = (1 << d) - 1;
+
+ save = 0;
+ for(ix = USED(mp) - 1; ix >= 0; ix--) {
+ next = dp[ix] & mask;
+ dp[ix] = (dp[ix] >> d) | (save << (DIGIT_BIT - d));
+ save = next;
+ }
+
+ s_mp_clamp(mp);
+
+} /* end s_mp_div_2d() */
+
+/* }}} */
+
+/* {{{ s_mp_norm(a, b) */
+
+/*
+ s_mp_norm(a, b)
+
+ Normalize a and b for division, where b is the divisor. In order
+ that we might make good guesses for quotient digits, we want the
+ leading digit of b to be at least half the radix, which we
+ accomplish by multiplying a and b by a constant. This constant is
+ returned (so that it can be divided back out of the remainder at the
+ end of the division process).
+
+ We multiply by the smallest power of 2 that gives us a leading digit
+ at least half the radix. By choosing a power of 2, we simplify the
+ multiplication and division steps to simple shifts.
+ */
+mp_digit s_mp_norm(mp_int *a, mp_int *b)
+{
+ mp_digit t, d = 0;
+
+ t = DIGIT(b, USED(b) - 1);
+ while(t < (RADIX / 2)) {
+ t <<= 1;
+ ++d;
+ }
+
+ if(d != 0) {
+ s_mp_mul_2d(a, d);
+ s_mp_mul_2d(b, d);
+ }
+
+ return d;
+
+} /* end s_mp_norm() */
+
+/* }}} */
+
+/* }}} */
+
+/* {{{ Primitive digit arithmetic */
+
+/* {{{ s_mp_add_d(mp, d) */
+
+/* Add d to |mp| in place */
+mp_err s_mp_add_d(mp_int *mp, mp_digit d) /* unsigned digit addition */
+{
+ mp_word w, k = 0;
+ mp_size ix = 1, used = USED(mp);
+ mp_digit *dp = DIGITS(mp);
+
+ w = dp[0] + d;
+ dp[0] = ACCUM(w);
+ k = CARRYOUT(w);
+
+ while(ix < used && k) {
+ w = dp[ix] + k;
+ dp[ix] = ACCUM(w);
+ k = CARRYOUT(w);
+ ++ix;
+ }
+
+ if(k != 0) {
+ mp_err res;
+
+ if((res = s_mp_pad(mp, USED(mp) + 1)) != MP_OKAY)
+ return res;
+
+ DIGIT(mp, ix) = k;
+ }
+
+ return MP_OKAY;
+
+} /* end s_mp_add_d() */
+
+/* }}} */
+
+/* {{{ s_mp_sub_d(mp, d) */
+
+/* Subtract d from |mp| in place, assumes |mp| > d */
+mp_err s_mp_sub_d(mp_int *mp, mp_digit d) /* unsigned digit subtract */
+{
+ mp_word w, b = 0;
+ mp_size ix = 1, used = USED(mp);
+ mp_digit *dp = DIGITS(mp);
+
+ /* Compute initial subtraction */
+ w = (RADIX + dp[0]) - d;
+ b = CARRYOUT(w) ? 0 : 1;
+ dp[0] = ACCUM(w);
+
+ /* Propagate borrows leftward */
+ while(b && ix < used) {
+ w = (RADIX + dp[ix]) - b;
+ b = CARRYOUT(w) ? 0 : 1;
+ dp[ix] = ACCUM(w);
+ ++ix;
+ }
+
+ /* Remove leading zeroes */
+ s_mp_clamp(mp);
+
+ /* If we have a borrow out, it's a violation of the input invariant */
+ if(b)
+ return MP_RANGE;
+ else
+ return MP_OKAY;
+
+} /* end s_mp_sub_d() */
+
+/* }}} */
+
+/* {{{ s_mp_mul_d(a, d) */
+
+/* Compute a = a * d, single digit multiplication */
+mp_err s_mp_mul_d(mp_int *a, mp_digit d)
+{
+ mp_word w, k = 0;
+ mp_size ix, max;
+ mp_err res;
+ mp_digit *dp = DIGITS(a);
+
+ /*
+ Single-digit multiplication will increase the precision of the
+ output by at most one digit. However, we can detect when this
+ will happen -- if the high-order digit of a, times d, gives a
+ two-digit result, then the precision of the result will increase;
+ otherwise it won't. We use this fact to avoid calling s_mp_pad()
+ unless absolutely necessary.
+ */
+ max = USED(a);
+ w = dp[max - 1] * d;
+ if(CARRYOUT(w) != 0) {
+ if((res = s_mp_pad(a, max + 1)) != MP_OKAY)
+ return res;
+ dp = DIGITS(a);
+ }
+
+ for(ix = 0; ix < max; ix++) {
+ w = (dp[ix] * d) + k;
+ dp[ix] = ACCUM(w);
+ k = CARRYOUT(w);
+ }
+
+ /* If there is a precision increase, take care of it here; the above
+ test guarantees we have enough storage to do this safely.
+ */
+ if(k) {
+ dp[max] = k;
+ USED(a) = max + 1;
+ }
+
+ s_mp_clamp(a);
+
+ return MP_OKAY;
+
+} /* end s_mp_mul_d() */
+
+/* }}} */
+
+/* {{{ s_mp_div_d(mp, d, r) */
+
+/*
+ s_mp_div_d(mp, d, r)
+
+ Compute the quotient mp = mp / d and remainder r = mp mod d, for a
+ single digit d. If r is null, the remainder will be discarded.
+ */
+
+mp_err s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r)
+{
+ mp_word w = 0, t;
+ mp_int quot;
+ mp_err res;
+ mp_digit *dp = DIGITS(mp), *qp;
+ int ix;
+
+ if(d == 0)
+ return MP_RANGE;
+
+ /* Make room for the quotient */
+ if((res = mp_init_size(&quot, USED(mp))) != MP_OKAY)
+ return res;
+
+ USED(&quot) = USED(mp); /* so clamping will work below */
+ qp = DIGITS(&quot);
+
+ /* Divide without subtraction */
+ for(ix = USED(mp) - 1; ix >= 0; ix--) {
+ w = (w << DIGIT_BIT) | dp[ix];
+
+ if(w >= d) {
+ t = w / d;
+ w = w % d;
+ } else {
+ t = 0;
+ }
+
+ qp[ix] = t;
+ }
+
+ /* Deliver the remainder, if desired */
+ if(r)
+ *r = w;
+
+ s_mp_clamp(&quot);
+ mp_exch(&quot, mp);
+ mp_clear(&quot);
+
+ return MP_OKAY;
+
+} /* end s_mp_div_d() */
+
+/* }}} */
+
+/* }}} */
+
+/* {{{ Primitive full arithmetic */
+
+/* {{{ s_mp_add(a, b) */
+
+/* Compute a = |a| + |b| */
+mp_err s_mp_add(mp_int *a, mp_int *b) /* magnitude addition */
+{
+ mp_word w = 0;
+ mp_digit *pa, *pb;
+ mp_size ix, used = USED(b);
+ mp_err res;
+
+ /* Make sure a has enough precision for the output value */
+ if((used > USED(a)) && (res = s_mp_pad(a, used)) != MP_OKAY)
+ return res;
+
+ /*
+ Add up all digits up to the precision of b. If b had initially
+ the same precision as a, or greater, we took care of it by the
+ padding step above, so there is no problem. If b had initially
+ less precision, we'll have to make sure the carry out is duly
+ propagated upward among the higher-order digits of the sum.
+ */
+ pa = DIGITS(a);
+ pb = DIGITS(b);
+ for(ix = 0; ix < used; ++ix) {
+ w += *pa + *pb++;
+ *pa++ = ACCUM(w);
+ w = CARRYOUT(w);
+ }
+
+ /* If we run out of 'b' digits before we're actually done, make
+ sure the carries get propagated upward...
+ */
+ used = USED(a);
+ while(w && ix < used) {
+ w += *pa;
+ *pa++ = ACCUM(w);
+ w = CARRYOUT(w);
+ ++ix;
+ }
+
+ /* If there's an overall carry out, increase precision and include
+ it. We could have done this initially, but why touch the memory
+ allocator unless we're sure we have to?
+ */
+ if(w) {
+ if((res = s_mp_pad(a, used + 1)) != MP_OKAY)
+ return res;
+
+ DIGIT(a, ix) = w; /* pa may not be valid after s_mp_pad() call */
+ }
+
+ return MP_OKAY;
+
+} /* end s_mp_add() */
+
+/* }}} */
+
+/* {{{ s_mp_sub(a, b) */
+
+/* Compute a = |a| - |b|, assumes |a| >= |b| */
+mp_err s_mp_sub(mp_int *a, mp_int *b) /* magnitude subtract */
+{
+ mp_word w = 0;
+ mp_digit *pa, *pb;
+ mp_size ix, used = USED(b);
+
+ /*
+ Subtract and propagate borrow. Up to the precision of b, this
+ accounts for the digits of b; after that, we just make sure the
+ carries get to the right place. This saves having to pad b out to
+ the precision of a just to make the loops work right...
+ */
+ pa = DIGITS(a);
+ pb = DIGITS(b);
+
+ for(ix = 0; ix < used; ++ix) {
+ w = (RADIX + *pa) - w - *pb++;
+ *pa++ = ACCUM(w);
+ w = CARRYOUT(w) ? 0 : 1;
+ }
+
+ used = USED(a);
+ while(ix < used) {
+ w = RADIX + *pa - w;
+ *pa++ = ACCUM(w);
+ w = CARRYOUT(w) ? 0 : 1;
+ ++ix;
+ }
+
+ /* Clobber any leading zeroes we created */
+ s_mp_clamp(a);
+
+ /*
+ If there was a borrow out, then |b| > |a| in violation
+ of our input invariant. We've already done the work,
+ but we'll at least complain about it...
+ */
+ if(w)
+ return MP_RANGE;
+ else
+ return MP_OKAY;
+
+} /* end s_mp_sub() */
+
+/* }}} */
+
+mp_err s_mp_reduce(mp_int *x, mp_int *m, mp_int *mu)
+{
+ mp_int q;
+ mp_err res;
+ mp_size um = USED(m);
+
+ if((res = mp_init_copy(&q, x)) != MP_OKAY)
+ return res;
+
+ s_mp_rshd(&q, um - 1); /* q1 = x / b^(k-1) */
+ s_mp_mul(&q, mu); /* q2 = q1 * mu */
+ s_mp_rshd(&q, um + 1); /* q3 = q2 / b^(k+1) */
+
+ /* x = x mod b^(k+1), quick (no division) */
+ s_mp_mod_2d(x, (mp_digit)(DIGIT_BIT * (um + 1)));
+
+ /* q = q * m mod b^(k+1), quick (no division), uses the short multiplier */
+#ifndef SHRT_MUL
+ s_mp_mul(&q, m);
+ s_mp_mod_2d(&q, (mp_digit)(DIGIT_BIT * (um + 1)));
+#else
+ s_mp_mul_dig(&q, m, um + 1);
+#endif
+
+ /* x = x - q */
+ if((res = mp_sub(x, &q, x)) != MP_OKAY)
+ goto CLEANUP;
+
+ /* If x < 0, add b^(k+1) to it */
+ if(mp_cmp_z(x) < 0) {
+ mp_set(&q, 1);
+ if((res = s_mp_lshd(&q, um + 1)) != MP_OKAY)
+ goto CLEANUP;
+ if((res = mp_add(x, &q, x)) != MP_OKAY)
+ goto CLEANUP;
+ }
+
+ /* Back off if it's too big */
+ while(mp_cmp(x, m) >= 0) {
+ if((res = s_mp_sub(x, m)) != MP_OKAY)
+ break;
+ }
+
+ CLEANUP:
+ mp_clear(&q);
+
+ return res;
+
+} /* end s_mp_reduce() */
+
+
+
+/* {{{ s_mp_mul(a, b) */
+
+/* Compute a = |a| * |b| */
+mp_err s_mp_mul(mp_int *a, mp_int *b)
+{
+ mp_word w, k = 0;
+ mp_int tmp;
+ mp_err res;
+ mp_size ix, jx, ua = USED(a), ub = USED(b);
+ mp_digit *pa, *pb, *pt, *pbt;
+
+ if((res = mp_init_size(&tmp, ua + ub)) != MP_OKAY)
+ return res;
+
+ /* This has the effect of left-padding with zeroes... */
+ USED(&tmp) = ua + ub;
+
+ /* We're going to need the base value each iteration */
+ pbt = DIGITS(&tmp);
+
+ /* Outer loop: Digits of b */
+
+ pb = DIGITS(b);
+ for(ix = 0; ix < ub; ++ix, ++pb) {
+ if(*pb == 0)
+ continue;
+
+ /* Inner product: Digits of a */
+ pa = DIGITS(a);
+ for(jx = 0; jx < ua; ++jx, ++pa) {
+ pt = pbt + ix + jx;
+ w = *pb * *pa + k + *pt;
+ *pt = ACCUM(w);
+ k = CARRYOUT(w);
+ }
+
+ pbt[ix + jx] = k;
+ k = 0;
+ }
+
+ s_mp_clamp(&tmp);
+ s_mp_exch(&tmp, a);
+
+ mp_clear(&tmp);
+
+ return MP_OKAY;
+
+} /* end s_mp_mul() */
+
+/* }}} */
+
+/* {{{ s_mp_kmul(a, b, out, len) */
+
+#if 0
+void s_mp_kmul(mp_digit *a, mp_digit *b, mp_digit *out, mp_size len)
+{
+ mp_word w, k = 0;
+ mp_size ix, jx;
+ mp_digit *pa, *pt;
+
+ for(ix = 0; ix < len; ++ix, ++b) {
+ if(*b == 0)
+ continue;
+
+ pa = a;
+ for(jx = 0; jx < len; ++jx, ++pa) {
+ pt = out + ix + jx;
+ w = *b * *pa + k + *pt;
+ *pt = ACCUM(w);
+ k = CARRYOUT(w);
+ }
+
+ out[ix + jx] = k;
+ k = 0;
+ }
+
+} /* end s_mp_kmul() */
+#endif
+
+/* }}} */
+
+/* {{{ s_mp_sqr(a) */
+
+/*
+ Computes the square of a, in place. This can be done more
+ efficiently than a general multiplication, because many of the
+ computation steps are redundant when squaring. The inner product
+ step is a bit more complicated, but we save a fair number of
+ iterations of the multiplication loop.
+ */
+#if MP_SQUARE
+mp_err s_mp_sqr(mp_int *a)
+{
+ mp_word w, k = 0;
+ mp_int tmp;
+ mp_err res;
+ mp_size ix, jx, kx, used = USED(a);
+ mp_digit *pa1, *pa2, *pt, *pbt;
+
+ if((res = mp_init_size(&tmp, 2 * used)) != MP_OKAY)
+ return res;
+
+ /* Left-pad with zeroes */
+ USED(&tmp) = 2 * used;
+
+ /* We need the base value each time through the loop */
+ pbt = DIGITS(&tmp);
+
+ pa1 = DIGITS(a);
+ for(ix = 0; ix < used; ++ix, ++pa1) {
+ if(*pa1 == 0)
+ continue;
+
+ w = DIGIT(&tmp, ix + ix) + (*pa1 * *pa1);
+
+ pbt[ix + ix] = ACCUM(w);
+ k = CARRYOUT(w);
+
+ /*
+ The inner product is computed as:
+
+ (C, S) = t[i,j] + 2 a[i] a[j] + C
+
+ This can overflow what can be represented in an mp_word, and
+ since C arithmetic does not provide any way to check for
+ overflow, we have to check explicitly for overflow conditions
+ before they happen.
+ */
+ for(jx = ix + 1, pa2 = DIGITS(a) + jx; jx < used; ++jx, ++pa2) {
+ mp_word u = 0, v;
+
+ /* Store this in a temporary to avoid indirections later */
+ pt = pbt + ix + jx;
+
+ /* Compute the multiplicative step */
+ w = *pa1 * *pa2;
+
+ /* If w is more than half MP_WORD_MAX, the doubling will
+ overflow, and we need to record a carry out into the next
+ word */
+ u = (w >> (MP_WORD_BIT - 1)) & 1;
+
+ /* Double what we've got, overflow will be ignored as defined
+ for C arithmetic (we've already noted if it is to occur)
+ */
+ w *= 2;
+
+ /* Compute the additive step */
+ v = *pt + k;
+
+ /* If we do not already have an overflow carry, check to see
+ if the addition will cause one, and set the carry out if so
+ */
+ u |= ((MP_WORD_MAX - v) < w);
+
+ /* Add in the rest, again ignoring overflow */
+ w += v;
+
+ /* Set the i,j digit of the output */
+ *pt = ACCUM(w);
+
+ /* Save carry information for the next iteration of the loop.
+ This is why k must be an mp_word, instead of an mp_digit */
+ k = CARRYOUT(w) | (u << DIGIT_BIT);
+
+ } /* for(jx ...) */
+
+ /* Set the last digit in the cycle and reset the carry */
+ k = DIGIT(&tmp, ix + jx) + k;
+ pbt[ix + jx] = ACCUM(k);
+ k = CARRYOUT(k);
+
+ /* If we are carrying out, propagate the carry to the next digit
+ in the output. This may cascade, so we have to be somewhat
+ circumspect -- but we will have enough precision in the output
+ that we won't overflow
+ */
+ kx = 1;
+ while(k) {
+ k = pbt[ix + jx + kx] + 1;
+ pbt[ix + jx + kx] = ACCUM(k);
+ k = CARRYOUT(k);
+ ++kx;
+ }
+ } /* for(ix ...) */
+
+ s_mp_clamp(&tmp);
+ s_mp_exch(&tmp, a);
+
+ mp_clear(&tmp);
+
+ return MP_OKAY;
+
+} /* end s_mp_sqr() */
+#endif
+
+/* }}} */
+
+/* {{{ s_mp_div(a, b) */
+
+/*
+ s_mp_div(a, b)
+
+ Compute a = a / b and b = a mod b. Assumes b > a.
+ */
+
+mp_err s_mp_div(mp_int *a, mp_int *b)
+{
+ mp_int quot, rem, t;
+ mp_word q;
+ mp_err res;
+ mp_digit d;
+ int ix;
+
+ if(mp_cmp_z(b) == 0)
+ return MP_RANGE;
+
+ /* Shortcut if b is power of two */
+ if((ix = s_mp_ispow2(b)) >= 0) {
+ mp_copy(a, b); /* need this for remainder */
+ s_mp_div_2d(a, (mp_digit)ix);
+ s_mp_mod_2d(b, (mp_digit)ix);
+
+ return MP_OKAY;
+ }
+
+ /* Allocate space to store the quotient */
+ if((res = mp_init_size(&quot, USED(a))) != MP_OKAY)
+ return res;
+
+ /* A working temporary for division */
+ if((res = mp_init_size(&t, USED(a))) != MP_OKAY)
+ goto T;
+
+ /* Allocate space for the remainder */
+ if((res = mp_init_size(&rem, USED(a))) != MP_OKAY)
+ goto REM;
+
+ /* Normalize to optimize guessing */
+ d = s_mp_norm(a, b);
+
+ /* Perform the division itself...woo! */
+ ix = USED(a) - 1;
+
+ while(ix >= 0) {
+ /* Find a partial substring of a which is at least b */
+ while(s_mp_cmp(&rem, b) < 0 && ix >= 0) {
+ if((res = s_mp_lshd(&rem, 1)) != MP_OKAY)
+ goto CLEANUP;
+
+ if((res = s_mp_lshd(&quot, 1)) != MP_OKAY)
+ goto CLEANUP;
+
+ DIGIT(&rem, 0) = DIGIT(a, ix);
+ s_mp_clamp(&rem);
+ --ix;
+ }
+
+ /* If we didn't find one, we're finished dividing */
+ if(s_mp_cmp(&rem, b) < 0)
+ break;
+
+ /* Compute a guess for the next quotient digit */
+ q = DIGIT(&rem, USED(&rem) - 1);
+ if(q <= DIGIT(b, USED(b) - 1) && USED(&rem) > 1)
+ q = (q << DIGIT_BIT) | DIGIT(&rem, USED(&rem) - 2);
+
+ q /= DIGIT(b, USED(b) - 1);
+
+ /* The guess can be as much as RADIX + 1 */
+ if(q >= RADIX)
+ q = RADIX - 1;
+
+ /* See what that multiplies out to */
+ mp_copy(b, &t);
+ if((res = s_mp_mul_d(&t, q)) != MP_OKAY)
+ goto CLEANUP;
+
+ /*
+ If it's too big, back it off. We should not have to do this
+ more than once, or, in rare cases, twice. Knuth describes a
+ method by which this could be reduced to a maximum of once, but
+ I didn't implement that here.
+ */
+ while(s_mp_cmp(&t, &rem) > 0) {
+ --q;
+ s_mp_sub(&t, b);
+ }
+
+ /* At this point, q should be the right next digit */
+ if((res = s_mp_sub(&rem, &t)) != MP_OKAY)
+ goto CLEANUP;
+
+ /*
+ Include the digit in the quotient. We allocated enough memory
+ for any quotient we could ever possibly get, so we should not
+ have to check for failures here
+ */
+ DIGIT(&quot, 0) = q;
+ }
+
+ /* Denormalize remainder */
+ if(d != 0)
+ s_mp_div_2d(&rem, d);
+
+ s_mp_clamp(&quot);
+ s_mp_clamp(&rem);
+
+ /* Copy quotient back to output */
+ s_mp_exch(&quot, a);
+
+ /* Copy remainder back to output */
+ s_mp_exch(&rem, b);
+
+CLEANUP:
+ mp_clear(&rem);
+REM:
+ mp_clear(&t);
+T:
+ mp_clear(&quot);
+
+ return res;
+
+} /* end s_mp_div() */
+
+/* }}} */
+
+/* {{{ s_mp_2expt(a, k) */
+
+mp_err s_mp_2expt(mp_int *a, mp_digit k)
+{
+ mp_err res;
+ mp_size dig, bit;
+
+ dig = k / DIGIT_BIT;
+ bit = k % DIGIT_BIT;
+
+ mp_zero(a);
+ if((res = s_mp_pad(a, dig + 1)) != MP_OKAY)
+ return res;
+
+ DIGIT(a, dig) |= (1 << bit);
+
+ return MP_OKAY;
+
+} /* end s_mp_2expt() */
+
+/* }}} */
+
+
+/* }}} */
+
+/* }}} */
+
+/* {{{ Primitive comparisons */
+
+/* {{{ s_mp_cmp(a, b) */
+
+/* Compare |a| <=> |b|, return 0 if equal, <0 if a<b, >0 if a>b */
+int s_mp_cmp(mp_int *a, mp_int *b)
+{
+ mp_size ua = USED(a), ub = USED(b);
+
+ if(ua > ub)
+ return MP_GT;
+ else if(ua < ub)
+ return MP_LT;
+ else {
+ int ix = ua - 1;
+ mp_digit *ap = DIGITS(a) + ix, *bp = DIGITS(b) + ix;
+
+ while(ix >= 0) {
+ if(*ap > *bp)
+ return MP_GT;
+ else if(*ap < *bp)
+ return MP_LT;
+
+ --ap; --bp; --ix;
+ }
+
+ return MP_EQ;
+ }
+
+} /* end s_mp_cmp() */
+
+/* }}} */
+
+/* {{{ s_mp_cmp_d(a, d) */
+
+/* Compare |a| <=> d, return 0 if equal, <0 if a<d, >0 if a>d */
+int s_mp_cmp_d(mp_int *a, mp_digit d)
+{
+ mp_size ua = USED(a);
+ mp_digit *ap = DIGITS(a);
+
+ if(ua > 1)
+ return MP_GT;
+
+ if(*ap < d)
+ return MP_LT;
+ else if(*ap > d)
+ return MP_GT;
+ else
+ return MP_EQ;
+
+} /* end s_mp_cmp_d() */
+
+/* }}} */
+
+/* {{{ s_mp_ispow2(v) */
+
+/*
+ Returns -1 if the value is not a power of two; otherwise, it returns
+ k such that v = 2^k, i.e. lg(v).
+ */
+int s_mp_ispow2(mp_int *v)
+{
+ mp_digit d, *dp;
+ mp_size uv = USED(v);
+ int extra = 0, ix;
+
+ d = DIGIT(v, uv - 1); /* most significant digit of v */
+
+ while(d && ((d & 1) == 0)) {
+ d >>= 1;
+ ++extra;
+ }
+
+ if(d == 1) {
+ ix = uv - 2;
+ dp = DIGITS(v) + ix;
+
+ while(ix >= 0) {
+ if(*dp)
+ return -1; /* not a power of two */
+
+ --dp; --ix;
+ }
+
+ return ((uv - 1) * DIGIT_BIT) + extra;
+ }
+
+ return -1;
+
+} /* end s_mp_ispow2() */
+
+/* }}} */
+
+/* {{{ s_mp_ispow2d(d) */
+
+int s_mp_ispow2d(mp_digit d)
+{
+ int pow = 0;
+
+ while((d & 1) == 0) {
+ ++pow; d >>= 1;
+ }
+
+ if(d == 1)
+ return pow;
+
+ return -1;
+
+} /* end s_mp_ispow2d() */
+
+/* }}} */
+
+/* }}} */
+
+/* {{{ Primitive I/O helpers */
+
+/* {{{ s_mp_tovalue(ch, r) */
+
+/*
+ Convert the given character to its digit value, in the given radix.
+ If the given character is not understood in the given radix, -1 is
+ returned. Otherwise the digit's numeric value is returned.
+
+ The results will be odd if you use a radix < 2 or > 62, you are
+ expected to know what you're up to.
+ */
+int s_mp_tovalue(char ch, int r)
+{
+ int val, xch;
+
+ if(r > 36)
+ xch = ch;
+ else
+ xch = toupper(ch);
+
+ if(isdigit(xch))
+ val = xch - '0';
+ else if(isupper(xch))
+ val = xch - 'A' + 10;
+ else if(islower(xch))
+ val = xch - 'a' + 36;
+ else if(xch == '+')
+ val = 62;
+ else if(xch == '/')
+ val = 63;
+ else
+ return -1;
+
+ if(val < 0 || val >= r)
+ return -1;
+
+ return val;
+
+} /* end s_mp_tovalue() */
+
+/* }}} */
+
+/* {{{ s_mp_todigit(val, r, low) */
+
+/*
+ Convert val to a radix-r digit, if possible. If val is out of range
+ for r, returns zero. Otherwise, returns an ASCII character denoting
+ the value in the given radix.
+
+ The results may be odd if you use a radix < 2 or > 64, you are
+ expected to know what you're doing.
+ */
+
+char s_mp_todigit(int val, int r, int low)
+{
+ char ch;
+
+ if(val < 0 || val >= r)
+ return 0;
+
+ ch = s_dmap_1[val];
+
+ if(r <= 36 && low)
+ ch = tolower(ch);
+
+ return ch;
+
+} /* end s_mp_todigit() */
+
+/* }}} */
+
+/* {{{ s_mp_outlen(bits, radix) */
+
+/*
+ Return an estimate for how long a string is needed to hold a radix
+ r representation of a number with 'bits' significant bits.
+
+ Does not include space for a sign or a NUL terminator.
+ */
+int s_mp_outlen(int bits, int r)
+{
+ return (int)((double)bits * LOG_V_2(r));
+
+} /* end s_mp_outlen() */
+
+/* }}} */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* HERE THERE BE DRAGONS */
+/* crc==4242132123, version==2, Sat Feb 02 06:43:52 2002 */
diff --git a/libtommath/mtest/mpi.h b/libtommath/mtest/mpi.h
new file mode 100644
index 0000000..211421f
--- /dev/null
+++ b/libtommath/mtest/mpi.h
@@ -0,0 +1,225 @@
+/*
+ mpi.h
+
+ by Michael J. Fromberger <sting@linguist.dartmouth.edu>
+ Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved
+
+ Arbitrary precision integer arithmetic library
+ */
+
+#ifndef _H_MPI_
+#define _H_MPI_
+
+#include "mpi-config.h"
+
+#define MP_LT -1
+#define MP_EQ 0
+#define MP_GT 1
+
+#if MP_DEBUG
+#undef MP_IOFUNC
+#define MP_IOFUNC 1
+#endif
+
+#if MP_IOFUNC
+#include <stdio.h>
+#include <ctype.h>
+#endif
+
+#include <limits.h>
+
+#define MP_NEG 1
+#define MP_ZPOS 0
+
+/* Included for compatibility... */
+#define NEG MP_NEG
+#define ZPOS MP_ZPOS
+
+#define MP_OKAY 0 /* no error, all is well */
+#define MP_YES 0 /* yes (boolean result) */
+#define MP_NO -1 /* no (boolean result) */
+#define MP_MEM -2 /* out of memory */
+#define MP_RANGE -3 /* argument out of range */
+#define MP_BADARG -4 /* invalid parameter */
+#define MP_UNDEF -5 /* answer is undefined */
+#define MP_LAST_CODE MP_UNDEF
+
+#include "mpi-types.h"
+
+/* Included for compatibility... */
+#define DIGIT_BIT MP_DIGIT_BIT
+#define DIGIT_MAX MP_DIGIT_MAX
+
+/* Macros for accessing the mp_int internals */
+#define SIGN(MP) ((MP)->sign)
+#define USED(MP) ((MP)->used)
+#define ALLOC(MP) ((MP)->alloc)
+#define DIGITS(MP) ((MP)->dp)
+#define DIGIT(MP,N) (MP)->dp[(N)]
+
+#if MP_ARGCHK == 1
+#define ARGCHK(X,Y) {if(!(X)){return (Y);}}
+#elif MP_ARGCHK == 2
+#include <assert.h>
+#define ARGCHK(X,Y) assert(X)
+#else
+#define ARGCHK(X,Y) /* */
+#endif
+
+/* This defines the maximum I/O base (minimum is 2) */
+#define MAX_RADIX 64
+
+typedef struct {
+ mp_sign sign; /* sign of this quantity */
+ mp_size alloc; /* how many digits allocated */
+ mp_size used; /* how many digits used */
+ mp_digit *dp; /* the digits themselves */
+} mp_int;
+
+/*------------------------------------------------------------------------*/
+/* Default precision */
+
+unsigned int mp_get_prec(void);
+void mp_set_prec(unsigned int prec);
+
+/*------------------------------------------------------------------------*/
+/* Memory management */
+
+mp_err mp_init(mp_int *mp);
+mp_err mp_init_array(mp_int mp[], int count);
+mp_err mp_init_size(mp_int *mp, mp_size prec);
+mp_err mp_init_copy(mp_int *mp, mp_int *from);
+mp_err mp_copy(mp_int *from, mp_int *to);
+void mp_exch(mp_int *mp1, mp_int *mp2);
+void mp_clear(mp_int *mp);
+void mp_clear_array(mp_int mp[], int count);
+void mp_zero(mp_int *mp);
+void mp_set(mp_int *mp, mp_digit d);
+mp_err mp_set_int(mp_int *mp, long z);
+mp_err mp_shrink(mp_int *a);
+
+
+/*------------------------------------------------------------------------*/
+/* Single digit arithmetic */
+
+mp_err mp_add_d(mp_int *a, mp_digit d, mp_int *b);
+mp_err mp_sub_d(mp_int *a, mp_digit d, mp_int *b);
+mp_err mp_mul_d(mp_int *a, mp_digit d, mp_int *b);
+mp_err mp_mul_2(mp_int *a, mp_int *c);
+mp_err mp_div_d(mp_int *a, mp_digit d, mp_int *q, mp_digit *r);
+mp_err mp_div_2(mp_int *a, mp_int *c);
+mp_err mp_expt_d(mp_int *a, mp_digit d, mp_int *c);
+
+/*------------------------------------------------------------------------*/
+/* Sign manipulations */
+
+mp_err mp_abs(mp_int *a, mp_int *b);
+mp_err mp_neg(mp_int *a, mp_int *b);
+
+/*------------------------------------------------------------------------*/
+/* Full arithmetic */
+
+mp_err mp_add(mp_int *a, mp_int *b, mp_int *c);
+mp_err mp_sub(mp_int *a, mp_int *b, mp_int *c);
+mp_err mp_mul(mp_int *a, mp_int *b, mp_int *c);
+mp_err mp_mul_2d(mp_int *a, mp_digit d, mp_int *c);
+#if MP_SQUARE
+mp_err mp_sqr(mp_int *a, mp_int *b);
+#else
+#define mp_sqr(a, b) mp_mul(a, a, b)
+#endif
+mp_err mp_div(mp_int *a, mp_int *b, mp_int *q, mp_int *r);
+mp_err mp_div_2d(mp_int *a, mp_digit d, mp_int *q, mp_int *r);
+mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c);
+mp_err mp_2expt(mp_int *a, mp_digit k);
+mp_err mp_sqrt(mp_int *a, mp_int *b);
+
+/*------------------------------------------------------------------------*/
+/* Modular arithmetic */
+
+#if MP_MODARITH
+mp_err mp_mod(mp_int *a, mp_int *m, mp_int *c);
+mp_err mp_mod_d(mp_int *a, mp_digit d, mp_digit *c);
+mp_err mp_addmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
+mp_err mp_submod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
+mp_err mp_mulmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
+#if MP_SQUARE
+mp_err mp_sqrmod(mp_int *a, mp_int *m, mp_int *c);
+#else
+#define mp_sqrmod(a, m, c) mp_mulmod(a, a, m, c)
+#endif
+mp_err mp_exptmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
+mp_err mp_exptmod_d(mp_int *a, mp_digit d, mp_int *m, mp_int *c);
+#endif /* MP_MODARITH */
+
+/*------------------------------------------------------------------------*/
+/* Comparisons */
+
+int mp_cmp_z(mp_int *a);
+int mp_cmp_d(mp_int *a, mp_digit d);
+int mp_cmp(mp_int *a, mp_int *b);
+int mp_cmp_mag(mp_int *a, mp_int *b);
+int mp_cmp_int(mp_int *a, long z);
+int mp_isodd(mp_int *a);
+int mp_iseven(mp_int *a);
+
+/*------------------------------------------------------------------------*/
+/* Number theoretic */
+
+#if MP_NUMTH
+mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c);
+mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c);
+mp_err mp_xgcd(mp_int *a, mp_int *b, mp_int *g, mp_int *x, mp_int *y);
+mp_err mp_invmod(mp_int *a, mp_int *m, mp_int *c);
+#endif /* end MP_NUMTH */
+
+/*------------------------------------------------------------------------*/
+/* Input and output */
+
+#if MP_IOFUNC
+void mp_print(mp_int *mp, FILE *ofp);
+#endif /* end MP_IOFUNC */
+
+/*------------------------------------------------------------------------*/
+/* Base conversion */
+
+#define BITS 1
+#define BYTES CHAR_BIT
+
+mp_err mp_read_signed_bin(mp_int *mp, unsigned char *str, int len);
+int mp_signed_bin_size(mp_int *mp);
+mp_err mp_to_signed_bin(mp_int *mp, unsigned char *str);
+
+mp_err mp_read_unsigned_bin(mp_int *mp, unsigned char *str, int len);
+int mp_unsigned_bin_size(mp_int *mp);
+mp_err mp_to_unsigned_bin(mp_int *mp, unsigned char *str);
+
+int mp_count_bits(mp_int *mp);
+
+#if MP_COMPAT_MACROS
+#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
+#define mp_raw_size(mp) mp_signed_bin_size(mp)
+#define mp_toraw(mp, str) mp_to_signed_bin((mp), (str))
+#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
+#define mp_mag_size(mp) mp_unsigned_bin_size(mp)
+#define mp_tomag(mp, str) mp_to_unsigned_bin((mp), (str))
+#endif
+
+mp_err mp_read_radix(mp_int *mp, unsigned char *str, int radix);
+int mp_radix_size(mp_int *mp, int radix);
+int mp_value_radix_size(int num, int qty, int radix);
+mp_err mp_toradix(mp_int *mp, unsigned char *str, int radix);
+
+int mp_char2value(char ch, int r);
+
+#define mp_tobinary(M, S) mp_toradix((M), (S), 2)
+#define mp_tooctal(M, S) mp_toradix((M), (S), 8)
+#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
+#define mp_tohex(M, S) mp_toradix((M), (S), 16)
+
+/*------------------------------------------------------------------------*/
+/* Error strings */
+
+const char *mp_strerror(mp_err ec);
+
+#endif /* end _H_MPI_ */
diff --git a/libtommath/mtest/mtest.c b/libtommath/mtest/mtest.c
new file mode 100644
index 0000000..d46f456
--- /dev/null
+++ b/libtommath/mtest/mtest.c
@@ -0,0 +1,304 @@
+/* makes a bignum test harness with NUM tests per operation
+ *
+ * the output is made in the following format [one parameter per line]
+
+operation
+operand1
+operand2
+[... operandN]
+result1
+result2
+[... resultN]
+
+So for example "a * b mod n" would be
+
+mulmod
+a
+b
+n
+a*b mod n
+
+e.g. if a=3, b=4 n=11 then
+
+mulmod
+3
+4
+11
+1
+
+ */
+
+#ifdef MP_8BIT
+#define THE_MASK 127
+#else
+#define THE_MASK 32767
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include "mpi.c"
+
+FILE *rng;
+
+void rand_num(mp_int *a)
+{
+ int n, size;
+ unsigned char buf[2048];
+
+ size = 1 + ((fgetc(rng)<<8) + fgetc(rng)) % 101;
+ buf[0] = (fgetc(rng)&1)?1:0;
+ fread(buf+1, 1, size, rng);
+ while (buf[1] == 0) buf[1] = fgetc(rng);
+ mp_read_raw(a, buf, 1+size);
+}
+
+void rand_num2(mp_int *a)
+{
+ int n, size;
+ unsigned char buf[2048];
+
+ size = 10 + ((fgetc(rng)<<8) + fgetc(rng)) % 101;
+ buf[0] = (fgetc(rng)&1)?1:0;
+ fread(buf+1, 1, size, rng);
+ while (buf[1] == 0) buf[1] = fgetc(rng);
+ mp_read_raw(a, buf, 1+size);
+}
+
+#define mp_to64(a, b) mp_toradix(a, b, 64)
+
+int main(void)
+{
+ int n, tmp;
+ mp_int a, b, c, d, e;
+ clock_t t1;
+ char buf[4096];
+
+ mp_init(&a);
+ mp_init(&b);
+ mp_init(&c);
+ mp_init(&d);
+ mp_init(&e);
+
+
+ /* initial (2^n - 1)^2 testing, makes sure the comba multiplier works [it has the new carry code] */
+/*
+ mp_set(&a, 1);
+ for (n = 1; n < 8192; n++) {
+ mp_mul(&a, &a, &c);
+ printf("mul\n");
+ mp_to64(&a, buf);
+ printf("%s\n%s\n", buf, buf);
+ mp_to64(&c, buf);
+ printf("%s\n", buf);
+
+ mp_add_d(&a, 1, &a);
+ mp_mul_2(&a, &a);
+ mp_sub_d(&a, 1, &a);
+ }
+*/
+
+ rng = fopen("/dev/urandom", "rb");
+ if (rng == NULL) {
+ rng = fopen("/dev/random", "rb");
+ if (rng == NULL) {
+ fprintf(stderr, "\nWarning: stdin used as random source\n\n");
+ rng = stdin;
+ }
+ }
+
+ t1 = clock();
+ for (;;) {
+#if 0
+ if (clock() - t1 > CLOCKS_PER_SEC) {
+ sleep(2);
+ t1 = clock();
+ }
+#endif
+ n = fgetc(rng) % 15;
+
+ if (n == 0) {
+ /* add tests */
+ rand_num(&a);
+ rand_num(&b);
+ mp_add(&a, &b, &c);
+ printf("add\n");
+ mp_to64(&a, buf);
+ printf("%s\n", buf);
+ mp_to64(&b, buf);
+ printf("%s\n", buf);
+ mp_to64(&c, buf);
+ printf("%s\n", buf);
+ } else if (n == 1) {
+ /* sub tests */
+ rand_num(&a);
+ rand_num(&b);
+ mp_sub(&a, &b, &c);
+ printf("sub\n");
+ mp_to64(&a, buf);
+ printf("%s\n", buf);
+ mp_to64(&b, buf);
+ printf("%s\n", buf);
+ mp_to64(&c, buf);
+ printf("%s\n", buf);
+ } else if (n == 2) {
+ /* mul tests */
+ rand_num(&a);
+ rand_num(&b);
+ mp_mul(&a, &b, &c);
+ printf("mul\n");
+ mp_to64(&a, buf);
+ printf("%s\n", buf);
+ mp_to64(&b, buf);
+ printf("%s\n", buf);
+ mp_to64(&c, buf);
+ printf("%s\n", buf);
+ } else if (n == 3) {
+ /* div tests */
+ rand_num(&a);
+ rand_num(&b);
+ mp_div(&a, &b, &c, &d);
+ printf("div\n");
+ mp_to64(&a, buf);
+ printf("%s\n", buf);
+ mp_to64(&b, buf);
+ printf("%s\n", buf);
+ mp_to64(&c, buf);
+ printf("%s\n", buf);
+ mp_to64(&d, buf);
+ printf("%s\n", buf);
+ } else if (n == 4) {
+ /* sqr tests */
+ rand_num(&a);
+ mp_sqr(&a, &b);
+ printf("sqr\n");
+ mp_to64(&a, buf);
+ printf("%s\n", buf);
+ mp_to64(&b, buf);
+ printf("%s\n", buf);
+ } else if (n == 5) {
+ /* mul_2d test */
+ rand_num(&a);
+ mp_copy(&a, &b);
+ n = fgetc(rng) & 63;
+ mp_mul_2d(&b, n, &b);
+ mp_to64(&a, buf);
+ printf("mul2d\n");
+ printf("%s\n", buf);
+ printf("%d\n", n);
+ mp_to64(&b, buf);
+ printf("%s\n", buf);
+ } else if (n == 6) {
+ /* div_2d test */
+ rand_num(&a);
+ mp_copy(&a, &b);
+ n = fgetc(rng) & 63;
+ mp_div_2d(&b, n, &b, NULL);
+ mp_to64(&a, buf);
+ printf("div2d\n");
+ printf("%s\n", buf);
+ printf("%d\n", n);
+ mp_to64(&b, buf);
+ printf("%s\n", buf);
+ } else if (n == 7) {
+ /* gcd test */
+ rand_num(&a);
+ rand_num(&b);
+ a.sign = MP_ZPOS;
+ b.sign = MP_ZPOS;
+ mp_gcd(&a, &b, &c);
+ printf("gcd\n");
+ mp_to64(&a, buf);
+ printf("%s\n", buf);
+ mp_to64(&b, buf);
+ printf("%s\n", buf);
+ mp_to64(&c, buf);
+ printf("%s\n", buf);
+ } else if (n == 8) {
+ /* lcm test */
+ rand_num(&a);
+ rand_num(&b);
+ a.sign = MP_ZPOS;
+ b.sign = MP_ZPOS;
+ mp_lcm(&a, &b, &c);
+ printf("lcm\n");
+ mp_to64(&a, buf);
+ printf("%s\n", buf);
+ mp_to64(&b, buf);
+ printf("%s\n", buf);
+ mp_to64(&c, buf);
+ printf("%s\n", buf);
+ } else if (n == 9) {
+ /* exptmod test */
+ rand_num2(&a);
+ rand_num2(&b);
+ rand_num2(&c);
+// if (c.dp[0]&1) mp_add_d(&c, 1, &c);
+ a.sign = b.sign = c.sign = 0;
+ mp_exptmod(&a, &b, &c, &d);
+ printf("expt\n");
+ mp_to64(&a, buf);
+ printf("%s\n", buf);
+ mp_to64(&b, buf);
+ printf("%s\n", buf);
+ mp_to64(&c, buf);
+ printf("%s\n", buf);
+ mp_to64(&d, buf);
+ printf("%s\n", buf);
+ } else if (n == 10) {
+ /* invmod test */
+ rand_num2(&a);
+ rand_num2(&b);
+ b.sign = MP_ZPOS;
+ a.sign = MP_ZPOS;
+ mp_gcd(&a, &b, &c);
+ if (mp_cmp_d(&c, 1) != 0) continue;
+ if (mp_cmp_d(&b, 1) == 0) continue;
+ mp_invmod(&a, &b, &c);
+ printf("invmod\n");
+ mp_to64(&a, buf);
+ printf("%s\n", buf);
+ mp_to64(&b, buf);
+ printf("%s\n", buf);
+ mp_to64(&c, buf);
+ printf("%s\n", buf);
+ } else if (n == 11) {
+ rand_num(&a);
+ mp_mul_2(&a, &a);
+ mp_div_2(&a, &b);
+ printf("div2\n");
+ mp_to64(&a, buf);
+ printf("%s\n", buf);
+ mp_to64(&b, buf);
+ printf("%s\n", buf);
+ } else if (n == 12) {
+ rand_num2(&a);
+ mp_mul_2(&a, &b);
+ printf("mul2\n");
+ mp_to64(&a, buf);
+ printf("%s\n", buf);
+ mp_to64(&b, buf);
+ printf("%s\n", buf);
+ } else if (n == 13) {
+ rand_num2(&a);
+ tmp = abs(rand()) & THE_MASK;
+ mp_add_d(&a, tmp, &b);
+ printf("add_d\n");
+ mp_to64(&a, buf);
+ printf("%s\n%d\n", buf, tmp);
+ mp_to64(&b, buf);
+ printf("%s\n", buf);
+ } else if (n == 14) {
+ rand_num2(&a);
+ tmp = abs(rand()) & THE_MASK;
+ mp_sub_d(&a, tmp, &b);
+ printf("sub_d\n");
+ mp_to64(&a, buf);
+ printf("%s\n%d\n", buf, tmp);
+ mp_to64(&b, buf);
+ printf("%s\n", buf);
+ }
+ }
+ fclose(rng);
+ return 0;
+}
diff --git a/libtommath/pics/design_process.sxd b/libtommath/pics/design_process.sxd
new file mode 100644
index 0000000..7414dbb
--- /dev/null
+++ b/libtommath/pics/design_process.sxd
Binary files differ
diff --git a/libtommath/pics/design_process.tif b/libtommath/pics/design_process.tif
new file mode 100644
index 0000000..4a0c012
--- /dev/null
+++ b/libtommath/pics/design_process.tif
Binary files differ
diff --git a/libtommath/pics/expt_state.sxd b/libtommath/pics/expt_state.sxd
new file mode 100644
index 0000000..6518404
--- /dev/null
+++ b/libtommath/pics/expt_state.sxd
Binary files differ
diff --git a/libtommath/pics/expt_state.tif b/libtommath/pics/expt_state.tif
new file mode 100644
index 0000000..0aaee39
--- /dev/null
+++ b/libtommath/pics/expt_state.tif
Binary files differ
diff --git a/libtommath/pics/makefile b/libtommath/pics/makefile
new file mode 100644
index 0000000..3ecb02f
--- /dev/null
+++ b/libtommath/pics/makefile
@@ -0,0 +1,35 @@
+# makes the images... yeah
+
+default: pses
+
+design_process.ps: design_process.tif
+ tiff2ps -s -e design_process.tif > design_process.ps
+
+sliding_window.ps: sliding_window.tif
+ tiff2ps -s -e sliding_window.tif > sliding_window.ps
+
+expt_state.ps: expt_state.tif
+ tiff2ps -s -e expt_state.tif > expt_state.ps
+
+primality.ps: primality.tif
+ tiff2ps -s -e primality.tif > primality.ps
+
+design_process.pdf: design_process.ps
+ epstopdf design_process.ps
+
+sliding_window.pdf: sliding_window.ps
+ epstopdf sliding_window.ps
+
+expt_state.pdf: expt_state.ps
+ epstopdf expt_state.ps
+
+primality.pdf: primality.ps
+ epstopdf primality.ps
+
+
+pses: sliding_window.ps expt_state.ps primality.ps design_process.ps
+pdfes: sliding_window.pdf expt_state.pdf primality.pdf design_process.pdf
+
+clean:
+ rm -rf *.ps *.pdf .xvpics
+ \ No newline at end of file
diff --git a/libtommath/pics/primality.tif b/libtommath/pics/primality.tif
new file mode 100644
index 0000000..83aafe0
--- /dev/null
+++ b/libtommath/pics/primality.tif
Binary files differ
diff --git a/libtommath/pics/radix.sxd b/libtommath/pics/radix.sxd
new file mode 100644
index 0000000..b9eb9a0
--- /dev/null
+++ b/libtommath/pics/radix.sxd
Binary files differ
diff --git a/libtommath/pics/sliding_window.sxd b/libtommath/pics/sliding_window.sxd
new file mode 100644
index 0000000..91e7c0d
--- /dev/null
+++ b/libtommath/pics/sliding_window.sxd
Binary files differ
diff --git a/libtommath/pics/sliding_window.tif b/libtommath/pics/sliding_window.tif
new file mode 100644
index 0000000..bb4cb96
--- /dev/null
+++ b/libtommath/pics/sliding_window.tif
Binary files differ
diff --git a/libtommath/poster.out b/libtommath/poster.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libtommath/poster.out
diff --git a/libtommath/poster.pdf b/libtommath/poster.pdf
new file mode 100644
index 0000000..1f705cf
--- /dev/null
+++ b/libtommath/poster.pdf
Binary files differ
diff --git a/libtommath/poster.tex b/libtommath/poster.tex
new file mode 100644
index 0000000..e7388f4
--- /dev/null
+++ b/libtommath/poster.tex
@@ -0,0 +1,35 @@
+\documentclass[landscape,11pt]{article}
+\usepackage{amsmath, amssymb}
+\usepackage{hyperref}
+\begin{document}
+\hspace*{-3in}
+\begin{tabular}{llllll}
+$c = a + b$ & {\tt mp\_add(\&a, \&b, \&c)} & $b = 2a$ & {\tt mp\_mul\_2(\&a, \&b)} & \\
+$c = a - b$ & {\tt mp\_sub(\&a, \&b, \&c)} & $b = a/2$ & {\tt mp\_div\_2(\&a, \&b)} & \\
+$c = ab $ & {\tt mp\_mul(\&a, \&b, \&c)} & $c = 2^ba$ & {\tt mp\_mul\_2d(\&a, b, \&c)} \\
+$b = a^2 $ & {\tt mp\_sqr(\&a, \&b)} & $c = a/2^b, d = a \mod 2^b$ & {\tt mp\_div\_2d(\&a, b, \&c, \&d)} \\
+$c = \lfloor a/b \rfloor, d = a \mod b$ & {\tt mp\_div(\&a, \&b, \&c, \&d)} & $c = a \mod 2^b $ & {\tt mp\_mod\_2d(\&a, b, \&c)} \\
+ && \\
+$a = b $ & {\tt mp\_set\_int(\&a, b)} & $c = a \vee b$ & {\tt mp\_or(\&a, \&b, \&c)} \\
+$b = a $ & {\tt mp\_copy(\&a, \&b)} & $c = a \wedge b$ & {\tt mp\_and(\&a, \&b, \&c)} \\
+ && $c = a \oplus b$ & {\tt mp\_xor(\&a, \&b, \&c)} \\
+ & \\
+$b = -a $ & {\tt mp\_neg(\&a, \&b)} & $d = a + b \mod c$ & {\tt mp\_addmod(\&a, \&b, \&c, \&d)} \\
+$b = |a| $ & {\tt mp\_abs(\&a, \&b)} & $d = a - b \mod c$ & {\tt mp\_submod(\&a, \&b, \&c, \&d)} \\
+ && $d = ab \mod c$ & {\tt mp\_mulmod(\&a, \&b, \&c, \&d)} \\
+Compare $a$ and $b$ & {\tt mp\_cmp(\&a, \&b)} & $c = a^2 \mod b$ & {\tt mp\_sqrmod(\&a, \&b, \&c)} \\
+Is Zero? & {\tt mp\_iszero(\&a)} & $c = a^{-1} \mod b$ & {\tt mp\_invmod(\&a, \&b, \&c)} \\
+Is Even? & {\tt mp\_iseven(\&a)} & $d = a^b \mod c$ & {\tt mp\_exptmod(\&a, \&b, \&c, \&d)} \\
+Is Odd ? & {\tt mp\_isodd(\&a)} \\
+&\\
+$\vert \vert a \vert \vert$ & {\tt mp\_unsigned\_bin\_size(\&a)} & $res$ = 1 if $a$ prime to $t$ rounds? & {\tt mp\_prime\_is\_prime(\&a, t, \&res)} \\
+$buf \leftarrow a$ & {\tt mp\_to\_unsigned\_bin(\&a, buf)} & Next prime after $a$ to $t$ rounds. & {\tt mp\_prime\_next\_prime(\&a, t, bbs\_style)} \\
+$a \leftarrow buf[0..len-1]$ & {\tt mp\_read\_unsigned\_bin(\&a, buf, len)} \\
+&\\
+$b = \sqrt{a}$ & {\tt mp\_sqrt(\&a, \&b)} & $c = \mbox{gcd}(a, b)$ & {\tt mp\_gcd(\&a, \&b, \&c)} \\
+$c = a^{1/b}$ & {\tt mp\_n\_root(\&a, b, \&c)} & $c = \mbox{lcm}(a, b)$ & {\tt mp\_lcm(\&a, \&b, \&c)} \\
+&\\
+Greater Than & MP\_GT & Equal To & MP\_EQ \\
+Less Than & MP\_LT & Bits per digit & DIGIT\_BIT \\
+\end{tabular}
+\end{document}
diff --git a/libtommath/pre_gen/mpi.c b/libtommath/pre_gen/mpi.c
new file mode 100644
index 0000000..d2224c0
--- /dev/null
+++ b/libtommath/pre_gen/mpi.c
@@ -0,0 +1,9048 @@
+/* Start: bn_error.c */
+#include <tommath.h>
+#ifdef BN_ERROR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+static const struct {
+ int code;
+ char *msg;
+} msgs[] = {
+ { MP_OKAY, "Successful" },
+ { MP_MEM, "Out of heap" },
+ { MP_VAL, "Value out of range" }
+};
+
+/* return a char * string for a given code */
+char *mp_error_to_string(int code)
+{
+ int x;
+
+ /* scan the lookup table for the given message */
+ for (x = 0; x < (int)(sizeof(msgs) / sizeof(msgs[0])); x++) {
+ if (msgs[x].code == code) {
+ return msgs[x].msg;
+ }
+ }
+
+ /* generic reply for invalid code */
+ return "Invalid error code";
+}
+
+#endif
+
+/* End: bn_error.c */
+
+/* Start: bn_fast_mp_invmod.c */
+#include <tommath.h>
+#ifdef BN_FAST_MP_INVMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* computes the modular inverse via binary extended euclidean algorithm,
+ * that is c = 1/a mod b
+ *
+ * Based on slow invmod except this is optimized for the case where b is
+ * odd as per HAC Note 14.64 on pp. 610
+ */
+int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int x, y, u, v, B, D;
+ int res, neg;
+
+ /* 2. [modified] b must be odd */
+ if (mp_iseven (b) == 1) {
+ return MP_VAL;
+ }
+
+ /* init all our temps */
+ if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) {
+ return res;
+ }
+
+ /* x == modulus, y == value to invert */
+ if ((res = mp_copy (b, &x)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ /* we need y = |a| */
+ if ((res = mp_mod (a, b, &y)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+ if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ mp_set (&D, 1);
+
+top:
+ /* 4. while u is even do */
+ while (mp_iseven (&u) == 1) {
+ /* 4.1 u = u/2 */
+ if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ /* 4.2 if B is odd then */
+ if (mp_isodd (&B) == 1) {
+ if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ /* B = B/2 */
+ if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* 5. while v is even do */
+ while (mp_iseven (&v) == 1) {
+ /* 5.1 v = v/2 */
+ if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ /* 5.2 if D is odd then */
+ if (mp_isodd (&D) == 1) {
+ /* D = (D-x)/2 */
+ if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ /* D = D/2 */
+ if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* 6. if u >= v then */
+ if (mp_cmp (&u, &v) != MP_LT) {
+ /* u = u - v, B = B - D */
+ if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ } else {
+ /* v - v - u, D = D - B */
+ if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* if not zero goto step 4 */
+ if (mp_iszero (&u) == 0) {
+ goto top;
+ }
+
+ /* now a = C, b = D, gcd == g*v */
+
+ /* if v != 1 then there is no inverse */
+ if (mp_cmp_d (&v, 1) != MP_EQ) {
+ res = MP_VAL;
+ goto LBL_ERR;
+ }
+
+ /* b is now the inverse */
+ neg = a->sign;
+ while (D.sign == MP_NEG) {
+ if ((res = mp_add (&D, b, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ mp_exch (&D, c);
+ c->sign = neg;
+ res = MP_OKAY;
+
+LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL);
+ return res;
+}
+#endif
+
+/* End: bn_fast_mp_invmod.c */
+
+/* Start: bn_fast_mp_montgomery_reduce.c */
+#include <tommath.h>
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction
+ *
+ * This is an optimized implementation of montgomery_reduce
+ * which uses the comba method to quickly calculate the columns of the
+ * reduction.
+ *
+ * Based on Algorithm 14.32 on pp.601 of HAC.
+*/
+int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+ int ix, res, olduse;
+ mp_word W[MP_WARRAY];
+
+ /* get old used count */
+ olduse = x->used;
+
+ /* grow a as required */
+ if (x->alloc < n->used + 1) {
+ if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* first we have to get the digits of the input into
+ * an array of double precision words W[...]
+ */
+ {
+ register mp_word *_W;
+ register mp_digit *tmpx;
+
+ /* alias for the W[] array */
+ _W = W;
+
+ /* alias for the digits of x*/
+ tmpx = x->dp;
+
+ /* copy the digits of a into W[0..a->used-1] */
+ for (ix = 0; ix < x->used; ix++) {
+ *_W++ = *tmpx++;
+ }
+
+ /* zero the high words of W[a->used..m->used*2] */
+ for (; ix < n->used * 2 + 1; ix++) {
+ *_W++ = 0;
+ }
+ }
+
+ /* now we proceed to zero successive digits
+ * from the least significant upwards
+ */
+ for (ix = 0; ix < n->used; ix++) {
+ /* mu = ai * m' mod b
+ *
+ * We avoid a double precision multiplication (which isn't required)
+ * by casting the value down to a mp_digit. Note this requires
+ * that W[ix-1] have the carry cleared (see after the inner loop)
+ */
+ register mp_digit mu;
+ mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);
+
+ /* a = a + mu * m * b**i
+ *
+ * This is computed in place and on the fly. The multiplication
+ * by b**i is handled by offseting which columns the results
+ * are added to.
+ *
+ * Note the comba method normally doesn't handle carries in the
+ * inner loop In this case we fix the carry from the previous
+ * column since the Montgomery reduction requires digits of the
+ * result (so far) [see above] to work. This is
+ * handled by fixing up one carry after the inner loop. The
+ * carry fixups are done in order so after these loops the
+ * first m->used words of W[] have the carries fixed
+ */
+ {
+ register int iy;
+ register mp_digit *tmpn;
+ register mp_word *_W;
+
+ /* alias for the digits of the modulus */
+ tmpn = n->dp;
+
+ /* Alias for the columns set by an offset of ix */
+ _W = W + ix;
+
+ /* inner loop */
+ for (iy = 0; iy < n->used; iy++) {
+ *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
+ }
+ }
+
+ /* now fix carry for next digit, W[ix+1] */
+ W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
+ }
+
+ /* now we have to propagate the carries and
+ * shift the words downward [all those least
+ * significant digits we zeroed].
+ */
+ {
+ register mp_digit *tmpx;
+ register mp_word *_W, *_W1;
+
+ /* nox fix rest of carries */
+
+ /* alias for current word */
+ _W1 = W + ix;
+
+ /* alias for next word, where the carry goes */
+ _W = W + ++ix;
+
+ for (; ix <= n->used * 2 + 1; ix++) {
+ *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
+ }
+
+ /* copy out, A = A/b**n
+ *
+ * The result is A/b**n but instead of converting from an
+ * array of mp_word to mp_digit than calling mp_rshd
+ * we just copy them in the right order
+ */
+
+ /* alias for destination word */
+ tmpx = x->dp;
+
+ /* alias for shifted double precision result */
+ _W = W + n->used;
+
+ for (ix = 0; ix < n->used + 1; ix++) {
+ *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
+ }
+
+ /* zero oldused digits, if the input a was larger than
+ * m->used+1 we'll have to clear the digits
+ */
+ for (; ix < olduse; ix++) {
+ *tmpx++ = 0;
+ }
+ }
+
+ /* set the max used and clamp */
+ x->used = n->used + 1;
+ mp_clamp (x);
+
+ /* if A >= m then A = A - m */
+ if (mp_cmp_mag (x, n) != MP_LT) {
+ return s_mp_sub (x, n, x);
+ }
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_fast_mp_montgomery_reduce.c */
+
+/* Start: bn_fast_s_mp_mul_digs.c */
+#include <tommath.h>
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* Fast (comba) multiplier
+ *
+ * This is the fast column-array [comba] multiplier. It is
+ * designed to compute the columns of the product first
+ * then handle the carries afterwards. This has the effect
+ * of making the nested loops that compute the columns very
+ * simple and schedulable on super-scalar processors.
+ *
+ * This has been modified to produce a variable number of
+ * digits of output so if say only a half-product is required
+ * you don't have to compute the upper half (a feature
+ * required for fast Barrett reduction).
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ *
+ */
+int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+ int olduse, res, pa, ix, iz;
+ mp_digit W[MP_WARRAY];
+ register mp_word _W;
+
+ /* grow the destination as required */
+ if (c->alloc < digs) {
+ if ((res = mp_grow (c, digs)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* number of output digits to produce */
+ pa = MIN(digs, a->used + b->used);
+
+ /* clear the carry */
+ _W = 0;
+ for (ix = 0; ix < pa; ix++) {
+ int tx, ty;
+ int iy;
+ mp_digit *tmpx, *tmpy;
+
+ /* get offsets into the two bignums */
+ ty = MIN(b->used-1, ix);
+ tx = ix - ty;
+
+ /* setup temp aliases */
+ tmpx = a->dp + tx;
+ tmpy = b->dp + ty;
+
+ /* this is the number of times the loop will iterrate, essentially
+ while (tx++ < a->used && ty-- >= 0) { ... }
+ */
+ iy = MIN(a->used-tx, ty+1);
+
+ /* execute loop */
+ for (iz = 0; iz < iy; ++iz) {
+ _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+
+ }
+
+ /* store term */
+ W[ix] = ((mp_digit)_W) & MP_MASK;
+
+ /* make next carry */
+ _W = _W >> ((mp_word)DIGIT_BIT);
+ }
+
+ /* setup dest */
+ olduse = c->used;
+ c->used = pa;
+
+ {
+ register mp_digit *tmpc;
+ tmpc = c->dp;
+ for (ix = 0; ix < pa+1; ix++) {
+ /* now extract the previous digit [below the carry] */
+ *tmpc++ = W[ix];
+ }
+
+ /* clear unused digits [that existed in the old copy of c] */
+ for (; ix < olduse; ix++) {
+ *tmpc++ = 0;
+ }
+ }
+ mp_clamp (c);
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_fast_s_mp_mul_digs.c */
+
+/* Start: bn_fast_s_mp_mul_high_digs.c */
+#include <tommath.h>
+#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* this is a modified version of fast_s_mul_digs that only produces
+ * output digits *above* digs. See the comments for fast_s_mul_digs
+ * to see how it works.
+ *
+ * This is used in the Barrett reduction since for one of the multiplications
+ * only the higher digits were needed. This essentially halves the work.
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ */
+int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+ int olduse, res, pa, ix, iz;
+ mp_digit W[MP_WARRAY];
+ mp_word _W;
+
+ /* grow the destination as required */
+ pa = a->used + b->used;
+ if (c->alloc < pa) {
+ if ((res = mp_grow (c, pa)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* number of output digits to produce */
+ pa = a->used + b->used;
+ _W = 0;
+ for (ix = digs; ix < pa; ix++) {
+ int tx, ty, iy;
+ mp_digit *tmpx, *tmpy;
+
+ /* get offsets into the two bignums */
+ ty = MIN(b->used-1, ix);
+ tx = ix - ty;
+
+ /* setup temp aliases */
+ tmpx = a->dp + tx;
+ tmpy = b->dp + ty;
+
+ /* this is the number of times the loop will iterrate, essentially its
+ while (tx++ < a->used && ty-- >= 0) { ... }
+ */
+ iy = MIN(a->used-tx, ty+1);
+
+ /* execute loop */
+ for (iz = 0; iz < iy; iz++) {
+ _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+ }
+
+ /* store term */
+ W[ix] = ((mp_digit)_W) & MP_MASK;
+
+ /* make next carry */
+ _W = _W >> ((mp_word)DIGIT_BIT);
+ }
+
+ /* setup dest */
+ olduse = c->used;
+ c->used = pa;
+
+ {
+ register mp_digit *tmpc;
+
+ tmpc = c->dp + digs;
+ for (ix = digs; ix < pa; ix++) {
+ /* now extract the previous digit [below the carry] */
+ *tmpc++ = W[ix];
+ }
+
+ /* clear unused digits [that existed in the old copy of c] */
+ for (; ix < olduse; ix++) {
+ *tmpc++ = 0;
+ }
+ }
+ mp_clamp (c);
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_fast_s_mp_mul_high_digs.c */
+
+/* Start: bn_fast_s_mp_sqr.c */
+#include <tommath.h>
+#ifdef BN_FAST_S_MP_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* the jist of squaring...
+ * you do like mult except the offset of the tmpx [one that
+ * starts closer to zero] can't equal the offset of tmpy.
+ * So basically you set up iy like before then you min it with
+ * (ty-tx) so that it never happens. You double all those
+ * you add in the inner loop
+
+After that loop you do the squares and add them in.
+*/
+
+int fast_s_mp_sqr (mp_int * a, mp_int * b)
+{
+ int olduse, res, pa, ix, iz;
+ mp_digit W[MP_WARRAY], *tmpx;
+ mp_word W1;
+
+ /* grow the destination as required */
+ pa = a->used + a->used;
+ if (b->alloc < pa) {
+ if ((res = mp_grow (b, pa)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* number of output digits to produce */
+ W1 = 0;
+ for (ix = 0; ix < pa; ix++) {
+ int tx, ty, iy;
+ mp_word _W;
+ mp_digit *tmpy;
+
+ /* clear counter */
+ _W = 0;
+
+ /* get offsets into the two bignums */
+ ty = MIN(a->used-1, ix);
+ tx = ix - ty;
+
+ /* setup temp aliases */
+ tmpx = a->dp + tx;
+ tmpy = a->dp + ty;
+
+ /* this is the number of times the loop will iterrate, essentially
+ while (tx++ < a->used && ty-- >= 0) { ... }
+ */
+ iy = MIN(a->used-tx, ty+1);
+
+ /* now for squaring tx can never equal ty
+ * we halve the distance since they approach at a rate of 2x
+ * and we have to round because odd cases need to be executed
+ */
+ iy = MIN(iy, (ty-tx+1)>>1);
+
+ /* execute loop */
+ for (iz = 0; iz < iy; iz++) {
+ _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+ }
+
+ /* double the inner product and add carry */
+ _W = _W + _W + W1;
+
+ /* even columns have the square term in them */
+ if ((ix&1) == 0) {
+ _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
+ }
+
+ /* store it */
+ W[ix] = (mp_digit)(_W & MP_MASK);
+
+ /* make next carry */
+ W1 = _W >> ((mp_word)DIGIT_BIT);
+ }
+
+ /* setup dest */
+ olduse = b->used;
+ b->used = a->used+a->used;
+
+ {
+ mp_digit *tmpb;
+ tmpb = b->dp;
+ for (ix = 0; ix < pa; ix++) {
+ *tmpb++ = W[ix] & MP_MASK;
+ }
+
+ /* clear unused digits [that existed in the old copy of c] */
+ for (; ix < olduse; ix++) {
+ *tmpb++ = 0;
+ }
+ }
+ mp_clamp (b);
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_fast_s_mp_sqr.c */
+
+/* Start: bn_mp_2expt.c */
+#include <tommath.h>
+#ifdef BN_MP_2EXPT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* computes a = 2**b
+ *
+ * Simple algorithm which zeroes the int, grows it then just sets one bit
+ * as required.
+ */
+int
+mp_2expt (mp_int * a, int b)
+{
+ int res;
+
+ /* zero a as per default */
+ mp_zero (a);
+
+ /* grow a to accomodate the single bit */
+ if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) {
+ return res;
+ }
+
+ /* set the used count of where the bit will go */
+ a->used = b / DIGIT_BIT + 1;
+
+ /* put the single bit in its place */
+ a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);
+
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_2expt.c */
+
+/* Start: bn_mp_abs.c */
+#include <tommath.h>
+#ifdef BN_MP_ABS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* b = |a|
+ *
+ * Simple function copies the input and fixes the sign to positive
+ */
+int
+mp_abs (mp_int * a, mp_int * b)
+{
+ int res;
+
+ /* copy a to b */
+ if (a != b) {
+ if ((res = mp_copy (a, b)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* force the sign of b to positive */
+ b->sign = MP_ZPOS;
+
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_abs.c */
+
+/* Start: bn_mp_add.c */
+#include <tommath.h>
+#ifdef BN_MP_ADD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* high level addition (handles signs) */
+int mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+ int sa, sb, res;
+
+ /* get sign of both inputs */
+ sa = a->sign;
+ sb = b->sign;
+
+ /* handle two cases, not four */
+ if (sa == sb) {
+ /* both positive or both negative */
+ /* add their magnitudes, copy the sign */
+ c->sign = sa;
+ res = s_mp_add (a, b, c);
+ } else {
+ /* one positive, the other negative */
+ /* subtract the one with the greater magnitude from */
+ /* the one of the lesser magnitude. The result gets */
+ /* the sign of the one with the greater magnitude. */
+ if (mp_cmp_mag (a, b) == MP_LT) {
+ c->sign = sb;
+ res = s_mp_sub (b, a, c);
+ } else {
+ c->sign = sa;
+ res = s_mp_sub (a, b, c);
+ }
+ }
+ return res;
+}
+
+#endif
+
+/* End: bn_mp_add.c */
+
+/* Start: bn_mp_add_d.c */
+#include <tommath.h>
+#ifdef BN_MP_ADD_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* single digit addition */
+int
+mp_add_d (mp_int * a, mp_digit b, mp_int * c)
+{
+ int res, ix, oldused;
+ mp_digit *tmpa, *tmpc, mu;
+
+ /* grow c as required */
+ if (c->alloc < a->used + 1) {
+ if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* if a is negative and |a| >= b, call c = |a| - b */
+ if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) {
+ /* temporarily fix sign of a */
+ a->sign = MP_ZPOS;
+
+ /* c = |a| - b */
+ res = mp_sub_d(a, b, c);
+
+ /* fix sign */
+ a->sign = c->sign = MP_NEG;
+
+ /* clamp */
+ mp_clamp(c);
+
+ return res;
+ }
+
+ /* old number of used digits in c */
+ oldused = c->used;
+
+ /* sign always positive */
+ c->sign = MP_ZPOS;
+
+ /* source alias */
+ tmpa = a->dp;
+
+ /* destination alias */
+ tmpc = c->dp;
+
+ /* if a is positive */
+ if (a->sign == MP_ZPOS) {
+ /* add digit, after this we're propagating
+ * the carry.
+ */
+ *tmpc = *tmpa++ + b;
+ mu = *tmpc >> DIGIT_BIT;
+ *tmpc++ &= MP_MASK;
+
+ /* now handle rest of the digits */
+ for (ix = 1; ix < a->used; ix++) {
+ *tmpc = *tmpa++ + mu;
+ mu = *tmpc >> DIGIT_BIT;
+ *tmpc++ &= MP_MASK;
+ }
+ /* set final carry */
+ ix++;
+ *tmpc++ = mu;
+
+ /* setup size */
+ c->used = a->used + 1;
+ } else {
+ /* a was negative and |a| < b */
+ c->used = 1;
+
+ /* the result is a single digit */
+ if (a->used == 1) {
+ *tmpc++ = b - a->dp[0];
+ } else {
+ *tmpc++ = b;
+ }
+
+ /* setup count so the clearing of oldused
+ * can fall through correctly
+ */
+ ix = 1;
+ }
+
+ /* now zero to oldused */
+ while (ix++ < oldused) {
+ *tmpc++ = 0;
+ }
+ mp_clamp(c);
+
+ return MP_OKAY;
+}
+
+#endif
+
+/* End: bn_mp_add_d.c */
+
+/* Start: bn_mp_addmod.c */
+#include <tommath.h>
+#ifdef BN_MP_ADDMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* d = a + b (mod c) */
+int
+mp_addmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+ int res;
+ mp_int t;
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_add (a, b, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ res = mp_mod (&t, c, d);
+ mp_clear (&t);
+ return res;
+}
+#endif
+
+/* End: bn_mp_addmod.c */
+
+/* Start: bn_mp_and.c */
+#include <tommath.h>
+#ifdef BN_MP_AND_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* AND two ints together */
+int
+mp_and (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res, ix, px;
+ mp_int t, *x;
+
+ if (a->used > b->used) {
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+ px = b->used;
+ x = b;
+ } else {
+ if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+ return res;
+ }
+ px = a->used;
+ x = a;
+ }
+
+ for (ix = 0; ix < px; ix++) {
+ t.dp[ix] &= x->dp[ix];
+ }
+
+ /* zero digits above the last from the smallest mp_int */
+ for (; ix < t.used; ix++) {
+ t.dp[ix] = 0;
+ }
+
+ mp_clamp (&t);
+ mp_exch (c, &t);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_and.c */
+
+/* Start: bn_mp_clamp.c */
+#include <tommath.h>
+#ifdef BN_MP_CLAMP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* trim unused digits
+ *
+ * This is used to ensure that leading zero digits are
+ * trimed and the leading "used" digit will be non-zero
+ * Typically very fast. Also fixes the sign if there
+ * are no more leading digits
+ */
+void
+mp_clamp (mp_int * a)
+{
+ /* decrease used while the most significant digit is
+ * zero.
+ */
+ while (a->used > 0 && a->dp[a->used - 1] == 0) {
+ --(a->used);
+ }
+
+ /* reset the sign flag if used == 0 */
+ if (a->used == 0) {
+ a->sign = MP_ZPOS;
+ }
+}
+#endif
+
+/* End: bn_mp_clamp.c */
+
+/* Start: bn_mp_clear.c */
+#include <tommath.h>
+#ifdef BN_MP_CLEAR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* clear one (frees) */
+void
+mp_clear (mp_int * a)
+{
+ int i;
+
+ /* only do anything if a hasn't been freed previously */
+ if (a->dp != NULL) {
+ /* first zero the digits */
+ for (i = 0; i < a->used; i++) {
+ a->dp[i] = 0;
+ }
+
+ /* free ram */
+ XFREE(a->dp);
+
+ /* reset members to make debugging easier */
+ a->dp = NULL;
+ a->alloc = a->used = 0;
+ a->sign = MP_ZPOS;
+ }
+}
+#endif
+
+/* End: bn_mp_clear.c */
+
+/* Start: bn_mp_clear_multi.c */
+#include <tommath.h>
+#ifdef BN_MP_CLEAR_MULTI_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+#include <stdarg.h>
+
+void mp_clear_multi(mp_int *mp, ...)
+{
+ mp_int* next_mp = mp;
+ va_list args;
+ va_start(args, mp);
+ while (next_mp != NULL) {
+ mp_clear(next_mp);
+ next_mp = va_arg(args, mp_int*);
+ }
+ va_end(args);
+}
+#endif
+
+/* End: bn_mp_clear_multi.c */
+
+/* Start: bn_mp_cmp.c */
+#include <tommath.h>
+#ifdef BN_MP_CMP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* compare two ints (signed)*/
+int
+mp_cmp (mp_int * a, mp_int * b)
+{
+ /* compare based on sign */
+ if (a->sign != b->sign) {
+ if (a->sign == MP_NEG) {
+ return MP_LT;
+ } else {
+ return MP_GT;
+ }
+ }
+
+ /* compare digits */
+ if (a->sign == MP_NEG) {
+ /* if negative compare opposite direction */
+ return mp_cmp_mag(b, a);
+ } else {
+ return mp_cmp_mag(a, b);
+ }
+}
+#endif
+
+/* End: bn_mp_cmp.c */
+
+/* Start: bn_mp_cmp_d.c */
+#include <tommath.h>
+#ifdef BN_MP_CMP_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* compare a digit */
+int mp_cmp_d(mp_int * a, mp_digit b)
+{
+ /* compare based on sign */
+ if (a->sign == MP_NEG) {
+ return MP_LT;
+ }
+
+ /* compare based on magnitude */
+ if (a->used > 1) {
+ return MP_GT;
+ }
+
+ /* compare the only digit of a to b */
+ if (a->dp[0] > b) {
+ return MP_GT;
+ } else if (a->dp[0] < b) {
+ return MP_LT;
+ } else {
+ return MP_EQ;
+ }
+}
+#endif
+
+/* End: bn_mp_cmp_d.c */
+
+/* Start: bn_mp_cmp_mag.c */
+#include <tommath.h>
+#ifdef BN_MP_CMP_MAG_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* compare maginitude of two ints (unsigned) */
+int mp_cmp_mag (mp_int * a, mp_int * b)
+{
+ int n;
+ mp_digit *tmpa, *tmpb;
+
+ /* compare based on # of non-zero digits */
+ if (a->used > b->used) {
+ return MP_GT;
+ }
+
+ if (a->used < b->used) {
+ return MP_LT;
+ }
+
+ /* alias for a */
+ tmpa = a->dp + (a->used - 1);
+
+ /* alias for b */
+ tmpb = b->dp + (a->used - 1);
+
+ /* compare based on digits */
+ for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
+ if (*tmpa > *tmpb) {
+ return MP_GT;
+ }
+
+ if (*tmpa < *tmpb) {
+ return MP_LT;
+ }
+ }
+ return MP_EQ;
+}
+#endif
+
+/* End: bn_mp_cmp_mag.c */
+
+/* Start: bn_mp_cnt_lsb.c */
+#include <tommath.h>
+#ifdef BN_MP_CNT_LSB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+static const int lnz[16] = {
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+};
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+int mp_cnt_lsb(mp_int *a)
+{
+ int x;
+ mp_digit q, qq;
+
+ /* easy out */
+ if (mp_iszero(a) == 1) {
+ return 0;
+ }
+
+ /* scan lower digits until non-zero */
+ for (x = 0; x < a->used && a->dp[x] == 0; x++);
+ q = a->dp[x];
+ x *= DIGIT_BIT;
+
+ /* now scan this digit until a 1 is found */
+ if ((q & 1) == 0) {
+ do {
+ qq = q & 15;
+ x += lnz[qq];
+ q >>= 4;
+ } while (qq == 0);
+ }
+ return x;
+}
+
+#endif
+
+/* End: bn_mp_cnt_lsb.c */
+
+/* Start: bn_mp_copy.c */
+#include <tommath.h>
+#ifdef BN_MP_COPY_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* copy, b = a */
+int
+mp_copy (mp_int * a, mp_int * b)
+{
+ int res, n;
+
+ /* if dst == src do nothing */
+ if (a == b) {
+ return MP_OKAY;
+ }
+
+ /* grow dest */
+ if (b->alloc < a->used) {
+ if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* zero b and copy the parameters over */
+ {
+ register mp_digit *tmpa, *tmpb;
+
+ /* pointer aliases */
+
+ /* source */
+ tmpa = a->dp;
+
+ /* destination */
+ tmpb = b->dp;
+
+ /* copy all the digits */
+ for (n = 0; n < a->used; n++) {
+ *tmpb++ = *tmpa++;
+ }
+
+ /* clear high digits */
+ for (; n < b->used; n++) {
+ *tmpb++ = 0;
+ }
+ }
+
+ /* copy used count and sign */
+ b->used = a->used;
+ b->sign = a->sign;
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_copy.c */
+
+/* Start: bn_mp_count_bits.c */
+#include <tommath.h>
+#ifdef BN_MP_COUNT_BITS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* returns the number of bits in an int */
+int
+mp_count_bits (mp_int * a)
+{
+ int r;
+ mp_digit q;
+
+ /* shortcut */
+ if (a->used == 0) {
+ return 0;
+ }
+
+ /* get number of digits and add that */
+ r = (a->used - 1) * DIGIT_BIT;
+
+ /* take the last digit and count the bits in it */
+ q = a->dp[a->used - 1];
+ while (q > ((mp_digit) 0)) {
+ ++r;
+ q >>= ((mp_digit) 1);
+ }
+ return r;
+}
+#endif
+
+/* End: bn_mp_count_bits.c */
+
+/* Start: bn_mp_div.c */
+#include <tommath.h>
+#ifdef BN_MP_DIV_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+#ifdef BN_MP_DIV_SMALL
+
+/* slower bit-bang division... also smaller */
+int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+ mp_int ta, tb, tq, q;
+ int res, n, n2;
+
+ /* is divisor zero ? */
+ if (mp_iszero (b) == 1) {
+ return MP_VAL;
+ }
+
+ /* if a < b then q=0, r = a */
+ if (mp_cmp_mag (a, b) == MP_LT) {
+ if (d != NULL) {
+ res = mp_copy (a, d);
+ } else {
+ res = MP_OKAY;
+ }
+ if (c != NULL) {
+ mp_zero (c);
+ }
+ return res;
+ }
+
+ /* init our temps */
+ if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) {
+ return res;
+ }
+
+
+ mp_set(&tq, 1);
+ n = mp_count_bits(a) - mp_count_bits(b);
+ if (((res = mp_abs(a, &ta)) != MP_OKAY) ||
+ ((res = mp_abs(b, &tb)) != MP_OKAY) ||
+ ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||
+ ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) {
+ goto LBL_ERR;
+ }
+
+ while (n-- >= 0) {
+ if (mp_cmp(&tb, &ta) != MP_GT) {
+ if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||
+ ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) {
+ goto LBL_ERR;
+ }
+ }
+ if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||
+ ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* now q == quotient and ta == remainder */
+ n = a->sign;
+ n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);
+ if (c != NULL) {
+ mp_exch(c, &q);
+ c->sign = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2;
+ }
+ if (d != NULL) {
+ mp_exch(d, &ta);
+ d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n;
+ }
+LBL_ERR:
+ mp_clear_multi(&ta, &tb, &tq, &q, NULL);
+ return res;
+}
+
+#else
+
+/* integer signed division.
+ * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
+ * HAC pp.598 Algorithm 14.20
+ *
+ * Note that the description in HAC is horribly
+ * incomplete. For example, it doesn't consider
+ * the case where digits are removed from 'x' in
+ * the inner loop. It also doesn't consider the
+ * case that y has fewer than three digits, etc..
+ *
+ * The overall algorithm is as described as
+ * 14.20 from HAC but fixed to treat these cases.
+*/
+int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+ mp_int q, x, y, t1, t2;
+ int res, n, t, i, norm, neg;
+
+ /* is divisor zero ? */
+ if (mp_iszero (b) == 1) {
+ return MP_VAL;
+ }
+
+ /* if a < b then q=0, r = a */
+ if (mp_cmp_mag (a, b) == MP_LT) {
+ if (d != NULL) {
+ res = mp_copy (a, d);
+ } else {
+ res = MP_OKAY;
+ }
+ if (c != NULL) {
+ mp_zero (c);
+ }
+ return res;
+ }
+
+ if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) {
+ return res;
+ }
+ q.used = a->used + 2;
+
+ if ((res = mp_init (&t1)) != MP_OKAY) {
+ goto LBL_Q;
+ }
+
+ if ((res = mp_init (&t2)) != MP_OKAY) {
+ goto LBL_T1;
+ }
+
+ if ((res = mp_init_copy (&x, a)) != MP_OKAY) {
+ goto LBL_T2;
+ }
+
+ if ((res = mp_init_copy (&y, b)) != MP_OKAY) {
+ goto LBL_X;
+ }
+
+ /* fix the sign */
+ neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+ x.sign = y.sign = MP_ZPOS;
+
+ /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
+ norm = mp_count_bits(&y) % DIGIT_BIT;
+ if (norm < (int)(DIGIT_BIT-1)) {
+ norm = (DIGIT_BIT-1) - norm;
+ if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+ if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+ } else {
+ norm = 0;
+ }
+
+ /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
+ n = x.used - 1;
+ t = y.used - 1;
+
+ /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
+ if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */
+ goto LBL_Y;
+ }
+
+ while (mp_cmp (&x, &y) != MP_LT) {
+ ++(q.dp[n - t]);
+ if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+ }
+
+ /* reset y by shifting it back down */
+ mp_rshd (&y, n - t);
+
+ /* step 3. for i from n down to (t + 1) */
+ for (i = n; i >= (t + 1); i--) {
+ if (i > x.used) {
+ continue;
+ }
+
+ /* step 3.1 if xi == yt then set q{i-t-1} to b-1,
+ * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
+ if (x.dp[i] == y.dp[t]) {
+ q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);
+ } else {
+ mp_word tmp;
+ tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
+ tmp |= ((mp_word) x.dp[i - 1]);
+ tmp /= ((mp_word) y.dp[t]);
+ if (tmp > (mp_word) MP_MASK)
+ tmp = MP_MASK;
+ q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK));
+ }
+
+ /* while (q{i-t-1} * (yt * b + y{t-1})) >
+ xi * b**2 + xi-1 * b + xi-2
+
+ do q{i-t-1} -= 1;
+ */
+ q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK;
+ do {
+ q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;
+
+ /* find left hand */
+ mp_zero (&t1);
+ t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
+ t1.dp[1] = y.dp[t];
+ t1.used = 2;
+ if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ /* find right hand */
+ t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
+ t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
+ t2.dp[2] = x.dp[i];
+ t2.used = 3;
+ } while (mp_cmp_mag(&t1, &t2) == MP_GT);
+
+ /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
+ if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
+ if (x.sign == MP_NEG) {
+ if ((res = mp_copy (&y, &t1)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+ if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+ if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK;
+ }
+ }
+
+ /* now q is the quotient and x is the remainder
+ * [which we have to normalize]
+ */
+
+ /* get sign before writing to c */
+ x.sign = x.used == 0 ? MP_ZPOS : a->sign;
+
+ if (c != NULL) {
+ mp_clamp (&q);
+ mp_exch (&q, c);
+ c->sign = neg;
+ }
+
+ if (d != NULL) {
+ mp_div_2d (&x, norm, &x, NULL);
+ mp_exch (&x, d);
+ }
+
+ res = MP_OKAY;
+
+LBL_Y:mp_clear (&y);
+LBL_X:mp_clear (&x);
+LBL_T2:mp_clear (&t2);
+LBL_T1:mp_clear (&t1);
+LBL_Q:mp_clear (&q);
+ return res;
+}
+
+#endif
+
+#endif
+
+/* End: bn_mp_div.c */
+
+/* Start: bn_mp_div_2.c */
+#include <tommath.h>
+#ifdef BN_MP_DIV_2_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* b = a/2 */
+int mp_div_2(mp_int * a, mp_int * b)
+{
+ int x, res, oldused;
+
+ /* copy */
+ if (b->alloc < a->used) {
+ if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ oldused = b->used;
+ b->used = a->used;
+ {
+ register mp_digit r, rr, *tmpa, *tmpb;
+
+ /* source alias */
+ tmpa = a->dp + b->used - 1;
+
+ /* dest alias */
+ tmpb = b->dp + b->used - 1;
+
+ /* carry */
+ r = 0;
+ for (x = b->used - 1; x >= 0; x--) {
+ /* get the carry for the next iteration */
+ rr = *tmpa & 1;
+
+ /* shift the current digit, add in carry and store */
+ *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
+
+ /* forward carry to next iteration */
+ r = rr;
+ }
+
+ /* zero excess digits */
+ tmpb = b->dp + b->used;
+ for (x = b->used; x < oldused; x++) {
+ *tmpb++ = 0;
+ }
+ }
+ b->sign = a->sign;
+ mp_clamp (b);
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_div_2.c */
+
+/* Start: bn_mp_div_2d.c */
+#include <tommath.h>
+#ifdef BN_MP_DIV_2D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* shift right by a certain bit count (store quotient in c, optional remainder in d) */
+int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
+{
+ mp_digit D, r, rr;
+ int x, res;
+ mp_int t;
+
+
+ /* if the shift count is <= 0 then we do no work */
+ if (b <= 0) {
+ res = mp_copy (a, c);
+ if (d != NULL) {
+ mp_zero (d);
+ }
+ return res;
+ }
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ /* get the remainder */
+ if (d != NULL) {
+ if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ }
+
+ /* copy */
+ if ((res = mp_copy (a, c)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+
+ /* shift by as many digits in the bit count */
+ if (b >= (int)DIGIT_BIT) {
+ mp_rshd (c, b / DIGIT_BIT);
+ }
+
+ /* shift any bit count < DIGIT_BIT */
+ D = (mp_digit) (b % DIGIT_BIT);
+ if (D != 0) {
+ register mp_digit *tmpc, mask, shift;
+
+ /* mask */
+ mask = (((mp_digit)1) << D) - 1;
+
+ /* shift for lsb */
+ shift = DIGIT_BIT - D;
+
+ /* alias */
+ tmpc = c->dp + (c->used - 1);
+
+ /* carry */
+ r = 0;
+ for (x = c->used - 1; x >= 0; x--) {
+ /* get the lower bits of this word in a temp */
+ rr = *tmpc & mask;
+
+ /* shift the current word and mix in the carry bits from the previous word */
+ *tmpc = (*tmpc >> D) | (r << shift);
+ --tmpc;
+
+ /* set the carry to the carry bits of the current word found above */
+ r = rr;
+ }
+ }
+ mp_clamp (c);
+ if (d != NULL) {
+ mp_exch (&t, d);
+ }
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_div_2d.c */
+
+/* Start: bn_mp_div_3.c */
+#include <tommath.h>
+#ifdef BN_MP_DIV_3_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* divide by three (based on routine from MPI and the GMP manual) */
+int
+mp_div_3 (mp_int * a, mp_int *c, mp_digit * d)
+{
+ mp_int q;
+ mp_word w, t;
+ mp_digit b;
+ int res, ix;
+
+ /* b = 2**DIGIT_BIT / 3 */
+ b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3);
+
+ if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
+ return res;
+ }
+
+ q.used = a->used;
+ q.sign = a->sign;
+ w = 0;
+ for (ix = a->used - 1; ix >= 0; ix--) {
+ w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
+
+ if (w >= 3) {
+ /* multiply w by [1/3] */
+ t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT);
+
+ /* now subtract 3 * [w/3] from w, to get the remainder */
+ w -= t+t+t;
+
+ /* fixup the remainder as required since
+ * the optimization is not exact.
+ */
+ while (w >= 3) {
+ t += 1;
+ w -= 3;
+ }
+ } else {
+ t = 0;
+ }
+ q.dp[ix] = (mp_digit)t;
+ }
+
+ /* [optional] store the remainder */
+ if (d != NULL) {
+ *d = (mp_digit)w;
+ }
+
+ /* [optional] store the quotient */
+ if (c != NULL) {
+ mp_clamp(&q);
+ mp_exch(&q, c);
+ }
+ mp_clear(&q);
+
+ return res;
+}
+
+#endif
+
+/* End: bn_mp_div_3.c */
+
+/* Start: bn_mp_div_d.c */
+#include <tommath.h>
+#ifdef BN_MP_DIV_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+static int s_is_power_of_two(mp_digit b, int *p)
+{
+ int x;
+
+ /* fast return if no power of two */
+ if ((b==0) || (b & (b-1))) {
+ return 0;
+ }
+
+ for (x = 0; x < DIGIT_BIT; x++) {
+ if (b == (((mp_digit)1)<<x)) {
+ *p = x;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* single digit division (based on routine from MPI) */
+int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
+{
+ mp_int q;
+ mp_word w;
+ mp_digit t;
+ int res, ix;
+
+ /* cannot divide by zero */
+ if (b == 0) {
+ return MP_VAL;
+ }
+
+ /* quick outs */
+ if (b == 1 || mp_iszero(a) == 1) {
+ if (d != NULL) {
+ *d = 0;
+ }
+ if (c != NULL) {
+ return mp_copy(a, c);
+ }
+ return MP_OKAY;
+ }
+
+ /* power of two ? */
+ if (s_is_power_of_two(b, &ix) == 1) {
+ if (d != NULL) {
+ *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1);
+ }
+ if (c != NULL) {
+ return mp_div_2d(a, ix, c, NULL);
+ }
+ return MP_OKAY;
+ }
+
+#ifdef BN_MP_DIV_3_C
+ /* three? */
+ if (b == 3) {
+ return mp_div_3(a, c, d);
+ }
+#endif
+
+ /* no easy answer [c'est la vie]. Just division */
+ if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
+ return res;
+ }
+
+ q.used = a->used;
+ q.sign = a->sign;
+ w = 0;
+ for (ix = a->used - 1; ix >= 0; ix--) {
+ w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
+
+ if (w >= b) {
+ t = (mp_digit)(w / b);
+ w -= ((mp_word)t) * ((mp_word)b);
+ } else {
+ t = 0;
+ }
+ q.dp[ix] = (mp_digit)t;
+ }
+
+ if (d != NULL) {
+ *d = (mp_digit)w;
+ }
+
+ if (c != NULL) {
+ mp_clamp(&q);
+ mp_exch(&q, c);
+ }
+ mp_clear(&q);
+
+ return res;
+}
+
+#endif
+
+/* End: bn_mp_div_d.c */
+
+/* Start: bn_mp_dr_is_modulus.c */
+#include <tommath.h>
+#ifdef BN_MP_DR_IS_MODULUS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* determines if a number is a valid DR modulus */
+int mp_dr_is_modulus(mp_int *a)
+{
+ int ix;
+
+ /* must be at least two digits */
+ if (a->used < 2) {
+ return 0;
+ }
+
+ /* must be of the form b**k - a [a <= b] so all
+ * but the first digit must be equal to -1 (mod b).
+ */
+ for (ix = 1; ix < a->used; ix++) {
+ if (a->dp[ix] != MP_MASK) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+#endif
+
+/* End: bn_mp_dr_is_modulus.c */
+
+/* Start: bn_mp_dr_reduce.c */
+#include <tommath.h>
+#ifdef BN_MP_DR_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
+ *
+ * Based on algorithm from the paper
+ *
+ * "Generating Efficient Primes for Discrete Log Cryptosystems"
+ * Chae Hoon Lim, Pil Joong Lee,
+ * POSTECH Information Research Laboratories
+ *
+ * The modulus must be of a special format [see manual]
+ *
+ * Has been modified to use algorithm 7.10 from the LTM book instead
+ *
+ * Input x must be in the range 0 <= x <= (n-1)**2
+ */
+int
+mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k)
+{
+ int err, i, m;
+ mp_word r;
+ mp_digit mu, *tmpx1, *tmpx2;
+
+ /* m = digits in modulus */
+ m = n->used;
+
+ /* ensure that "x" has at least 2m digits */
+ if (x->alloc < m + m) {
+ if ((err = mp_grow (x, m + m)) != MP_OKAY) {
+ return err;
+ }
+ }
+
+/* top of loop, this is where the code resumes if
+ * another reduction pass is required.
+ */
+top:
+ /* aliases for digits */
+ /* alias for lower half of x */
+ tmpx1 = x->dp;
+
+ /* alias for upper half of x, or x/B**m */
+ tmpx2 = x->dp + m;
+
+ /* set carry to zero */
+ mu = 0;
+
+ /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
+ for (i = 0; i < m; i++) {
+ r = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu;
+ *tmpx1++ = (mp_digit)(r & MP_MASK);
+ mu = (mp_digit)(r >> ((mp_word)DIGIT_BIT));
+ }
+
+ /* set final carry */
+ *tmpx1++ = mu;
+
+ /* zero words above m */
+ for (i = m + 1; i < x->used; i++) {
+ *tmpx1++ = 0;
+ }
+
+ /* clamp, sub and return */
+ mp_clamp (x);
+
+ /* if x >= n then subtract and reduce again
+ * Each successive "recursion" makes the input smaller and smaller.
+ */
+ if (mp_cmp_mag (x, n) != MP_LT) {
+ s_mp_sub(x, n, x);
+ goto top;
+ }
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_dr_reduce.c */
+
+/* Start: bn_mp_dr_setup.c */
+#include <tommath.h>
+#ifdef BN_MP_DR_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* determines the setup value */
+void mp_dr_setup(mp_int *a, mp_digit *d)
+{
+ /* the casts are required if DIGIT_BIT is one less than
+ * the number of bits in a mp_digit [e.g. DIGIT_BIT==31]
+ */
+ *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) -
+ ((mp_word)a->dp[0]));
+}
+
+#endif
+
+/* End: bn_mp_dr_setup.c */
+
+/* Start: bn_mp_exch.c */
+#include <tommath.h>
+#ifdef BN_MP_EXCH_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* swap the elements of two integers, for cases where you can't simply swap the
+ * mp_int pointers around
+ */
+void
+mp_exch (mp_int * a, mp_int * b)
+{
+ mp_int t;
+
+ t = *a;
+ *a = *b;
+ *b = t;
+}
+#endif
+
+/* End: bn_mp_exch.c */
+
+/* Start: bn_mp_expt_d.c */
+#include <tommath.h>
+#ifdef BN_MP_EXPT_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* calculate c = a**b using a square-multiply algorithm */
+int mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
+{
+ int res, x;
+ mp_int g;
+
+ if ((res = mp_init_copy (&g, a)) != MP_OKAY) {
+ return res;
+ }
+
+ /* set initial result */
+ mp_set (c, 1);
+
+ for (x = 0; x < (int) DIGIT_BIT; x++) {
+ /* square */
+ if ((res = mp_sqr (c, c)) != MP_OKAY) {
+ mp_clear (&g);
+ return res;
+ }
+
+ /* if the bit is set multiply */
+ if ((b & (mp_digit) (((mp_digit)1) << (DIGIT_BIT - 1))) != 0) {
+ if ((res = mp_mul (c, &g, c)) != MP_OKAY) {
+ mp_clear (&g);
+ return res;
+ }
+ }
+
+ /* shift to next bit */
+ b <<= 1;
+ }
+
+ mp_clear (&g);
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_expt_d.c */
+
+/* Start: bn_mp_exptmod.c */
+#include <tommath.h>
+#ifdef BN_MP_EXPTMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+
+/* this is a shell function that calls either the normal or Montgomery
+ * exptmod functions. Originally the call to the montgomery code was
+ * embedded in the normal function but that wasted alot of stack space
+ * for nothing (since 99% of the time the Montgomery code would be called)
+ */
+int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
+{
+ int dr;
+
+ /* modulus P must be positive */
+ if (P->sign == MP_NEG) {
+ return MP_VAL;
+ }
+
+ /* if exponent X is negative we have to recurse */
+ if (X->sign == MP_NEG) {
+#ifdef BN_MP_INVMOD_C
+ mp_int tmpG, tmpX;
+ int err;
+
+ /* first compute 1/G mod P */
+ if ((err = mp_init(&tmpG)) != MP_OKAY) {
+ return err;
+ }
+ if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
+ mp_clear(&tmpG);
+ return err;
+ }
+
+ /* now get |X| */
+ if ((err = mp_init(&tmpX)) != MP_OKAY) {
+ mp_clear(&tmpG);
+ return err;
+ }
+ if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
+ mp_clear_multi(&tmpG, &tmpX, NULL);
+ return err;
+ }
+
+ /* and now compute (1/G)**|X| instead of G**X [X < 0] */
+ err = mp_exptmod(&tmpG, &tmpX, P, Y);
+ mp_clear_multi(&tmpG, &tmpX, NULL);
+ return err;
+#else
+ /* no invmod */
+ return MP_VAL;
+#endif
+ }
+
+/* modified diminished radix reduction */
+#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C)
+ if (mp_reduce_is_2k_l(P) == MP_YES) {
+ return s_mp_exptmod(G, X, P, Y, 1);
+ }
+#endif
+
+#ifdef BN_MP_DR_IS_MODULUS_C
+ /* is it a DR modulus? */
+ dr = mp_dr_is_modulus(P);
+#else
+ /* default to no */
+ dr = 0;
+#endif
+
+#ifdef BN_MP_REDUCE_IS_2K_C
+ /* if not, is it a unrestricted DR modulus? */
+ if (dr == 0) {
+ dr = mp_reduce_is_2k(P) << 1;
+ }
+#endif
+
+ /* if the modulus is odd or dr != 0 use the montgomery method */
+#ifdef BN_MP_EXPTMOD_FAST_C
+ if (mp_isodd (P) == 1 || dr != 0) {
+ return mp_exptmod_fast (G, X, P, Y, dr);
+ } else {
+#endif
+#ifdef BN_S_MP_EXPTMOD_C
+ /* otherwise use the generic Barrett reduction technique */
+ return s_mp_exptmod (G, X, P, Y, 0);
+#else
+ /* no exptmod for evens */
+ return MP_VAL;
+#endif
+#ifdef BN_MP_EXPTMOD_FAST_C
+ }
+#endif
+}
+
+#endif
+
+/* End: bn_mp_exptmod.c */
+
+/* Start: bn_mp_exptmod_fast.c */
+#include <tommath.h>
+#ifdef BN_MP_EXPTMOD_FAST_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
+ *
+ * Uses a left-to-right k-ary sliding window to compute the modular exponentiation.
+ * The value of k changes based on the size of the exponent.
+ *
+ * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
+ */
+
+#ifdef MP_LOW_MEM
+ #define TAB_SIZE 32
+#else
+ #define TAB_SIZE 256
+#endif
+
+int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+ mp_int M[TAB_SIZE], res;
+ mp_digit buf, mp;
+ int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+
+ /* use a pointer to the reduction algorithm. This allows us to use
+ * one of many reduction algorithms without modding the guts of
+ * the code with if statements everywhere.
+ */
+ int (*redux)(mp_int*,mp_int*,mp_digit);
+
+ /* find window size */
+ x = mp_count_bits (X);
+ if (x <= 7) {
+ winsize = 2;
+ } else if (x <= 36) {
+ winsize = 3;
+ } else if (x <= 140) {
+ winsize = 4;
+ } else if (x <= 450) {
+ winsize = 5;
+ } else if (x <= 1303) {
+ winsize = 6;
+ } else if (x <= 3529) {
+ winsize = 7;
+ } else {
+ winsize = 8;
+ }
+
+#ifdef MP_LOW_MEM
+ if (winsize > 5) {
+ winsize = 5;
+ }
+#endif
+
+ /* init M array */
+ /* init first cell */
+ if ((err = mp_init(&M[1])) != MP_OKAY) {
+ return err;
+ }
+
+ /* now init the second half of the array */
+ for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+ if ((err = mp_init(&M[x])) != MP_OKAY) {
+ for (y = 1<<(winsize-1); y < x; y++) {
+ mp_clear (&M[y]);
+ }
+ mp_clear(&M[1]);
+ return err;
+ }
+ }
+
+ /* determine and setup reduction code */
+ if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_SETUP_C
+ /* now setup montgomery */
+ if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
+ goto LBL_M;
+ }
+#else
+ err = MP_VAL;
+ goto LBL_M;
+#endif
+
+ /* automatically pick the comba one if available (saves quite a few calls/ifs) */
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+ if (((P->used * 2 + 1) < MP_WARRAY) &&
+ P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ redux = fast_mp_montgomery_reduce;
+ } else
+#endif
+ {
+#ifdef BN_MP_MONTGOMERY_REDUCE_C
+ /* use slower baseline Montgomery method */
+ redux = mp_montgomery_reduce;
+#else
+ err = MP_VAL;
+ goto LBL_M;
+#endif
+ }
+ } else if (redmode == 1) {
+#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)
+ /* setup DR reduction for moduli of the form B**k - b */
+ mp_dr_setup(P, &mp);
+ redux = mp_dr_reduce;
+#else
+ err = MP_VAL;
+ goto LBL_M;
+#endif
+ } else {
+#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)
+ /* setup DR reduction for moduli of the form 2**k - b */
+ if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
+ goto LBL_M;
+ }
+ redux = mp_reduce_2k;
+#else
+ err = MP_VAL;
+ goto LBL_M;
+#endif
+ }
+
+ /* setup result */
+ if ((err = mp_init (&res)) != MP_OKAY) {
+ goto LBL_M;
+ }
+
+ /* create M table
+ *
+
+ *
+ * The first half of the table is not computed though accept for M[0] and M[1]
+ */
+
+ if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+ /* now we need R mod m */
+ if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+#else
+ err = MP_VAL;
+ goto LBL_RES;
+#endif
+
+ /* now set M[1] to G * R mod m */
+ if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ } else {
+ mp_set(&res, 1);
+ if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
+ if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ for (x = 0; x < (winsize - 1); x++) {
+ if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* create upper table */
+ for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+ if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&M[x], P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* set initial mode and bit cnt */
+ mode = 0;
+ bitcnt = 1;
+ buf = 0;
+ digidx = X->used - 1;
+ bitcpy = 0;
+ bitbuf = 0;
+
+ for (;;) {
+ /* grab next digit as required */
+ if (--bitcnt == 0) {
+ /* if digidx == -1 we are out of digits so break */
+ if (digidx == -1) {
+ break;
+ }
+ /* read next digit and reset bitcnt */
+ buf = X->dp[digidx--];
+ bitcnt = (int)DIGIT_BIT;
+ }
+
+ /* grab the next msb from the exponent */
+ y = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
+ buf <<= (mp_digit)1;
+
+ /* if the bit is zero and mode == 0 then we ignore it
+ * These represent the leading zero bits before the first 1 bit
+ * in the exponent. Technically this opt is not required but it
+ * does lower the # of trivial squaring/reductions used
+ */
+ if (mode == 0 && y == 0) {
+ continue;
+ }
+
+ /* if the bit is zero and mode == 1 then we square */
+ if (mode == 1 && y == 0) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ continue;
+ }
+
+ /* else we add it to the window */
+ bitbuf |= (y << (winsize - ++bitcpy));
+ mode = 2;
+
+ if (bitcpy == winsize) {
+ /* ok window is filled so square as required and multiply */
+ /* square first */
+ for (x = 0; x < winsize; x++) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* then multiply */
+ if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ /* empty window and reset */
+ bitcpy = 0;
+ bitbuf = 0;
+ mode = 1;
+ }
+ }
+
+ /* if bits remain then square/multiply */
+ if (mode == 2 && bitcpy > 0) {
+ /* square then multiply if the bit is set */
+ for (x = 0; x < bitcpy; x++) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ /* get next bit of the window */
+ bitbuf <<= 1;
+ if ((bitbuf & (1 << winsize)) != 0) {
+ /* then multiply */
+ if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+ }
+ }
+
+ if (redmode == 0) {
+ /* fixup result if Montgomery reduction is used
+ * recall that any value in a Montgomery system is
+ * actually multiplied by R mod n. So we have
+ * to reduce one more time to cancel out the factor
+ * of R.
+ */
+ if ((err = redux(&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* swap res with Y */
+ mp_exch (&res, Y);
+ err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_M:
+ mp_clear(&M[1]);
+ for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+ mp_clear (&M[x]);
+ }
+ return err;
+}
+#endif
+
+/* End: bn_mp_exptmod_fast.c */
+
+/* Start: bn_mp_exteuclid.c */
+#include <tommath.h>
+#ifdef BN_MP_EXTEUCLID_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* Extended euclidean algorithm of (a, b) produces
+ a*u1 + b*u2 = u3
+ */
+int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3)
+{
+ mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp;
+ int err;
+
+ if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) {
+ return err;
+ }
+
+ /* initialize, (u1,u2,u3) = (1,0,a) */
+ mp_set(&u1, 1);
+ if ((err = mp_copy(a, &u3)) != MP_OKAY) { goto _ERR; }
+
+ /* initialize, (v1,v2,v3) = (0,1,b) */
+ mp_set(&v2, 1);
+ if ((err = mp_copy(b, &v3)) != MP_OKAY) { goto _ERR; }
+
+ /* loop while v3 != 0 */
+ while (mp_iszero(&v3) == MP_NO) {
+ /* q = u3/v3 */
+ if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY) { goto _ERR; }
+
+ /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */
+ if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY) { goto _ERR; }
+
+ /* (u1,u2,u3) = (v1,v2,v3) */
+ if ((err = mp_copy(&v1, &u1)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_copy(&v2, &u2)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_copy(&v3, &u3)) != MP_OKAY) { goto _ERR; }
+
+ /* (v1,v2,v3) = (t1,t2,t3) */
+ if ((err = mp_copy(&t1, &v1)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_copy(&t2, &v2)) != MP_OKAY) { goto _ERR; }
+ if ((err = mp_copy(&t3, &v3)) != MP_OKAY) { goto _ERR; }
+ }
+
+ /* make sure U3 >= 0 */
+ if (u3.sign == MP_NEG) {
+ mp_neg(&u1, &u1);
+ mp_neg(&u2, &u2);
+ mp_neg(&u3, &u3);
+ }
+
+ /* copy result out */
+ if (U1 != NULL) { mp_exch(U1, &u1); }
+ if (U2 != NULL) { mp_exch(U2, &u2); }
+ if (U3 != NULL) { mp_exch(U3, &u3); }
+
+ err = MP_OKAY;
+_ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);
+ return err;
+}
+#endif
+
+/* End: bn_mp_exteuclid.c */
+
+/* Start: bn_mp_fread.c */
+#include <tommath.h>
+#ifdef BN_MP_FREAD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* read a bigint from a file stream in ASCII */
+int mp_fread(mp_int *a, int radix, FILE *stream)
+{
+ int err, ch, neg, y;
+
+ /* clear a */
+ mp_zero(a);
+
+ /* if first digit is - then set negative */
+ ch = fgetc(stream);
+ if (ch == '-') {
+ neg = MP_NEG;
+ ch = fgetc(stream);
+ } else {
+ neg = MP_ZPOS;
+ }
+
+ for (;;) {
+ /* find y in the radix map */
+ for (y = 0; y < radix; y++) {
+ if (mp_s_rmap[y] == ch) {
+ break;
+ }
+ }
+ if (y == radix) {
+ break;
+ }
+
+ /* shift up and add */
+ if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) {
+ return err;
+ }
+ if ((err = mp_add_d(a, y, a)) != MP_OKAY) {
+ return err;
+ }
+
+ ch = fgetc(stream);
+ }
+ if (mp_cmp_d(a, 0) != MP_EQ) {
+ a->sign = neg;
+ }
+
+ return MP_OKAY;
+}
+
+#endif
+
+/* End: bn_mp_fread.c */
+
+/* Start: bn_mp_fwrite.c */
+#include <tommath.h>
+#ifdef BN_MP_FWRITE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+int mp_fwrite(mp_int *a, int radix, FILE *stream)
+{
+ char *buf;
+ int err, len, x;
+
+ if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) {
+ return err;
+ }
+
+ buf = OPT_CAST(char) XMALLOC (len);
+ if (buf == NULL) {
+ return MP_MEM;
+ }
+
+ if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) {
+ XFREE (buf);
+ return err;
+ }
+
+ for (x = 0; x < len; x++) {
+ if (fputc(buf[x], stream) == EOF) {
+ XFREE (buf);
+ return MP_VAL;
+ }
+ }
+
+ XFREE (buf);
+ return MP_OKAY;
+}
+
+#endif
+
+/* End: bn_mp_fwrite.c */
+
+/* Start: bn_mp_gcd.c */
+#include <tommath.h>
+#ifdef BN_MP_GCD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* Greatest Common Divisor using the binary method */
+int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int u, v;
+ int k, u_lsb, v_lsb, res;
+
+ /* either zero than gcd is the largest */
+ if (mp_iszero (a) == MP_YES) {
+ return mp_abs (b, c);
+ }
+ if (mp_iszero (b) == MP_YES) {
+ return mp_abs (a, c);
+ }
+
+ /* get copies of a and b we can modify */
+ if ((res = mp_init_copy (&u, a)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_init_copy (&v, b)) != MP_OKAY) {
+ goto LBL_U;
+ }
+
+ /* must be positive for the remainder of the algorithm */
+ u.sign = v.sign = MP_ZPOS;
+
+ /* B1. Find the common power of two for u and v */
+ u_lsb = mp_cnt_lsb(&u);
+ v_lsb = mp_cnt_lsb(&v);
+ k = MIN(u_lsb, v_lsb);
+
+ if (k > 0) {
+ /* divide the power of two out */
+ if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) {
+ goto LBL_V;
+ }
+
+ if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) {
+ goto LBL_V;
+ }
+ }
+
+ /* divide any remaining factors of two out */
+ if (u_lsb != k) {
+ if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) {
+ goto LBL_V;
+ }
+ }
+
+ if (v_lsb != k) {
+ if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) {
+ goto LBL_V;
+ }
+ }
+
+ while (mp_iszero(&v) == 0) {
+ /* make sure v is the largest */
+ if (mp_cmp_mag(&u, &v) == MP_GT) {
+ /* swap u and v to make sure v is >= u */
+ mp_exch(&u, &v);
+ }
+
+ /* subtract smallest from largest */
+ if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) {
+ goto LBL_V;
+ }
+
+ /* Divide out all factors of two */
+ if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) {
+ goto LBL_V;
+ }
+ }
+
+ /* multiply by 2**k which we divided out at the beginning */
+ if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) {
+ goto LBL_V;
+ }
+ c->sign = MP_ZPOS;
+ res = MP_OKAY;
+LBL_V:mp_clear (&u);
+LBL_U:mp_clear (&v);
+ return res;
+}
+#endif
+
+/* End: bn_mp_gcd.c */
+
+/* Start: bn_mp_get_int.c */
+#include <tommath.h>
+#ifdef BN_MP_GET_INT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* get the lower 32-bits of an mp_int */
+unsigned long mp_get_int(mp_int * a)
+{
+ int i;
+ unsigned long res;
+
+ if (a->used == 0) {
+ return 0;
+ }
+
+ /* get number of digits of the lsb we have to read */
+ i = MIN(a->used,(int)((sizeof(unsigned long)*CHAR_BIT+DIGIT_BIT-1)/DIGIT_BIT))-1;
+
+ /* get most significant digit of result */
+ res = DIGIT(a,i);
+
+ while (--i >= 0) {
+ res = (res << DIGIT_BIT) | DIGIT(a,i);
+ }
+
+ /* force result to 32-bits always so it is consistent on non 32-bit platforms */
+ return res & 0xFFFFFFFFUL;
+}
+#endif
+
+/* End: bn_mp_get_int.c */
+
+/* Start: bn_mp_grow.c */
+#include <tommath.h>
+#ifdef BN_MP_GROW_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* grow as required */
+int mp_grow (mp_int * a, int size)
+{
+ int i;
+ mp_digit *tmp;
+
+ /* if the alloc size is smaller alloc more ram */
+ if (a->alloc < size) {
+ /* ensure there are always at least MP_PREC digits extra on top */
+ size += (MP_PREC * 2) - (size % MP_PREC);
+
+ /* reallocate the array a->dp
+ *
+ * We store the return in a temporary variable
+ * in case the operation failed we don't want
+ * to overwrite the dp member of a.
+ */
+ tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size);
+ if (tmp == NULL) {
+ /* reallocation failed but "a" is still valid [can be freed] */
+ return MP_MEM;
+ }
+
+ /* reallocation succeeded so set a->dp */
+ a->dp = tmp;
+
+ /* zero excess digits */
+ i = a->alloc;
+ a->alloc = size;
+ for (; i < a->alloc; i++) {
+ a->dp[i] = 0;
+ }
+ }
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_grow.c */
+
+/* Start: bn_mp_init.c */
+#include <tommath.h>
+#ifdef BN_MP_INIT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* init a new mp_int */
+int mp_init (mp_int * a)
+{
+ int i;
+
+ /* allocate memory required and clear it */
+ a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC);
+ if (a->dp == NULL) {
+ return MP_MEM;
+ }
+
+ /* set the digits to zero */
+ for (i = 0; i < MP_PREC; i++) {
+ a->dp[i] = 0;
+ }
+
+ /* set the used to zero, allocated digits to the default precision
+ * and sign to positive */
+ a->used = 0;
+ a->alloc = MP_PREC;
+ a->sign = MP_ZPOS;
+
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_init.c */
+
+/* Start: bn_mp_init_copy.c */
+#include <tommath.h>
+#ifdef BN_MP_INIT_COPY_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* creates "a" then copies b into it */
+int mp_init_copy (mp_int * a, mp_int * b)
+{
+ int res;
+
+ if ((res = mp_init (a)) != MP_OKAY) {
+ return res;
+ }
+ return mp_copy (b, a);
+}
+#endif
+
+/* End: bn_mp_init_copy.c */
+
+/* Start: bn_mp_init_multi.c */
+#include <tommath.h>
+#ifdef BN_MP_INIT_MULTI_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+#include <stdarg.h>
+
+int mp_init_multi(mp_int *mp, ...)
+{
+ mp_err res = MP_OKAY; /* Assume ok until proven otherwise */
+ int n = 0; /* Number of ok inits */
+ mp_int* cur_arg = mp;
+ va_list args;
+
+ va_start(args, mp); /* init args to next argument from caller */
+ while (cur_arg != NULL) {
+ if (mp_init(cur_arg) != MP_OKAY) {
+ /* Oops - error! Back-track and mp_clear what we already
+ succeeded in init-ing, then return error.
+ */
+ va_list clean_args;
+
+ /* end the current list */
+ va_end(args);
+
+ /* now start cleaning up */
+ cur_arg = mp;
+ va_start(clean_args, mp);
+ while (n--) {
+ mp_clear(cur_arg);
+ cur_arg = va_arg(clean_args, mp_int*);
+ }
+ va_end(clean_args);
+ res = MP_MEM;
+ break;
+ }
+ n++;
+ cur_arg = va_arg(args, mp_int*);
+ }
+ va_end(args);
+ return res; /* Assumed ok, if error flagged above. */
+}
+
+#endif
+
+/* End: bn_mp_init_multi.c */
+
+/* Start: bn_mp_init_set.c */
+#include <tommath.h>
+#ifdef BN_MP_INIT_SET_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* initialize and set a digit */
+int mp_init_set (mp_int * a, mp_digit b)
+{
+ int err;
+ if ((err = mp_init(a)) != MP_OKAY) {
+ return err;
+ }
+ mp_set(a, b);
+ return err;
+}
+#endif
+
+/* End: bn_mp_init_set.c */
+
+/* Start: bn_mp_init_set_int.c */
+#include <tommath.h>
+#ifdef BN_MP_INIT_SET_INT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* initialize and set a digit */
+int mp_init_set_int (mp_int * a, unsigned long b)
+{
+ int err;
+ if ((err = mp_init(a)) != MP_OKAY) {
+ return err;
+ }
+ return mp_set_int(a, b);
+}
+#endif
+
+/* End: bn_mp_init_set_int.c */
+
+/* Start: bn_mp_init_size.c */
+#include <tommath.h>
+#ifdef BN_MP_INIT_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* init an mp_init for a given size */
+int mp_init_size (mp_int * a, int size)
+{
+ int x;
+
+ /* pad size so there are always extra digits */
+ size += (MP_PREC * 2) - (size % MP_PREC);
+
+ /* alloc mem */
+ a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size);
+ if (a->dp == NULL) {
+ return MP_MEM;
+ }
+
+ /* set the members */
+ a->used = 0;
+ a->alloc = size;
+ a->sign = MP_ZPOS;
+
+ /* zero the digits */
+ for (x = 0; x < size; x++) {
+ a->dp[x] = 0;
+ }
+
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_init_size.c */
+
+/* Start: bn_mp_invmod.c */
+#include <tommath.h>
+#ifdef BN_MP_INVMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* hac 14.61, pp608 */
+int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+{
+ /* b cannot be negative */
+ if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+ return MP_VAL;
+ }
+
+#ifdef BN_FAST_MP_INVMOD_C
+ /* if the modulus is odd we can use a faster routine instead */
+ if (mp_isodd (b) == 1) {
+ return fast_mp_invmod (a, b, c);
+ }
+#endif
+
+#ifdef BN_MP_INVMOD_SLOW_C
+ return mp_invmod_slow(a, b, c);
+#endif
+
+ return MP_VAL;
+}
+#endif
+
+/* End: bn_mp_invmod.c */
+
+/* Start: bn_mp_invmod_slow.c */
+#include <tommath.h>
+#ifdef BN_MP_INVMOD_SLOW_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* hac 14.61, pp608 */
+int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int x, y, u, v, A, B, C, D;
+ int res;
+
+ /* b cannot be negative */
+ if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+ return MP_VAL;
+ }
+
+ /* init temps */
+ if ((res = mp_init_multi(&x, &y, &u, &v,
+ &A, &B, &C, &D, NULL)) != MP_OKAY) {
+ return res;
+ }
+
+ /* x = a, y = b */
+ if ((res = mp_mod(a, b, &x)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_copy (b, &y)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ /* 2. [modified] if x,y are both even then return an error! */
+ if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) {
+ res = MP_VAL;
+ goto LBL_ERR;
+ }
+
+ /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+ if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ mp_set (&A, 1);
+ mp_set (&D, 1);
+
+top:
+ /* 4. while u is even do */
+ while (mp_iseven (&u) == 1) {
+ /* 4.1 u = u/2 */
+ if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ /* 4.2 if A or B is odd then */
+ if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) {
+ /* A = (A+y)/2, B = (B-x)/2 */
+ if ((res = mp_add (&A, &y, &A)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ /* A = A/2, B = B/2 */
+ if ((res = mp_div_2 (&A, &A)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* 5. while v is even do */
+ while (mp_iseven (&v) == 1) {
+ /* 5.1 v = v/2 */
+ if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ /* 5.2 if C or D is odd then */
+ if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) {
+ /* C = (C+y)/2, D = (D-x)/2 */
+ if ((res = mp_add (&C, &y, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ /* C = C/2, D = D/2 */
+ if ((res = mp_div_2 (&C, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* 6. if u >= v then */
+ if (mp_cmp (&u, &v) != MP_LT) {
+ /* u = u - v, A = A - C, B = B - D */
+ if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ } else {
+ /* v - v - u, C = C - A, D = D - B */
+ if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* if not zero goto step 4 */
+ if (mp_iszero (&u) == 0)
+ goto top;
+
+ /* now a = C, b = D, gcd == g*v */
+
+ /* if v != 1 then there is no inverse */
+ if (mp_cmp_d (&v, 1) != MP_EQ) {
+ res = MP_VAL;
+ goto LBL_ERR;
+ }
+
+ /* if its too low */
+ while (mp_cmp_d(&C, 0) == MP_LT) {
+ if ((res = mp_add(&C, b, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* too big */
+ while (mp_cmp_mag(&C, b) != MP_LT) {
+ if ((res = mp_sub(&C, b, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* C is now the inverse */
+ mp_exch (&C, c);
+ res = MP_OKAY;
+LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL);
+ return res;
+}
+#endif
+
+/* End: bn_mp_invmod_slow.c */
+
+/* Start: bn_mp_is_square.c */
+#include <tommath.h>
+#ifdef BN_MP_IS_SQUARE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* Check if remainders are possible squares - fast exclude non-squares */
+static const char rem_128[128] = {
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1
+};
+
+static const char rem_105[105] = {
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
+ 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1
+};
+
+/* Store non-zero to ret if arg is square, and zero if not */
+int mp_is_square(mp_int *arg,int *ret)
+{
+ int res;
+ mp_digit c;
+ mp_int t;
+ unsigned long r;
+
+ /* Default to Non-square :) */
+ *ret = MP_NO;
+
+ if (arg->sign == MP_NEG) {
+ return MP_VAL;
+ }
+
+ /* digits used? (TSD) */
+ if (arg->used == 0) {
+ return MP_OKAY;
+ }
+
+ /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */
+ if (rem_128[127 & DIGIT(arg,0)] == 1) {
+ return MP_OKAY;
+ }
+
+ /* Next check mod 105 (3*5*7) */
+ if ((res = mp_mod_d(arg,105,&c)) != MP_OKAY) {
+ return res;
+ }
+ if (rem_105[c] == 1) {
+ return MP_OKAY;
+ }
+
+
+ if ((res = mp_init_set_int(&t,11L*13L*17L*19L*23L*29L*31L)) != MP_OKAY) {
+ return res;
+ }
+ if ((res = mp_mod(arg,&t,&t)) != MP_OKAY) {
+ goto ERR;
+ }
+ r = mp_get_int(&t);
+ /* Check for other prime modules, note it's not an ERROR but we must
+ * free "t" so the easiest way is to goto ERR. We know that res
+ * is already equal to MP_OKAY from the mp_mod call
+ */
+ if ( (1L<<(r%11)) & 0x5C4L ) goto ERR;
+ if ( (1L<<(r%13)) & 0x9E4L ) goto ERR;
+ if ( (1L<<(r%17)) & 0x5CE8L ) goto ERR;
+ if ( (1L<<(r%19)) & 0x4F50CL ) goto ERR;
+ if ( (1L<<(r%23)) & 0x7ACCA0L ) goto ERR;
+ if ( (1L<<(r%29)) & 0xC2EDD0CL ) goto ERR;
+ if ( (1L<<(r%31)) & 0x6DE2B848L ) goto ERR;
+
+ /* Final check - is sqr(sqrt(arg)) == arg ? */
+ if ((res = mp_sqrt(arg,&t)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sqr(&t,&t)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ *ret = (mp_cmp_mag(&t,arg) == MP_EQ) ? MP_YES : MP_NO;
+ERR:mp_clear(&t);
+ return res;
+}
+#endif
+
+/* End: bn_mp_is_square.c */
+
+/* Start: bn_mp_jacobi.c */
+#include <tommath.h>
+#ifdef BN_MP_JACOBI_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* computes the jacobi c = (a | n) (or Legendre if n is prime)
+ * HAC pp. 73 Algorithm 2.149
+ */
+int mp_jacobi (mp_int * a, mp_int * p, int *c)
+{
+ mp_int a1, p1;
+ int k, s, r, res;
+ mp_digit residue;
+
+ /* if p <= 0 return MP_VAL */
+ if (mp_cmp_d(p, 0) != MP_GT) {
+ return MP_VAL;
+ }
+
+ /* step 1. if a == 0, return 0 */
+ if (mp_iszero (a) == 1) {
+ *c = 0;
+ return MP_OKAY;
+ }
+
+ /* step 2. if a == 1, return 1 */
+ if (mp_cmp_d (a, 1) == MP_EQ) {
+ *c = 1;
+ return MP_OKAY;
+ }
+
+ /* default */
+ s = 0;
+
+ /* step 3. write a = a1 * 2**k */
+ if ((res = mp_init_copy (&a1, a)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_init (&p1)) != MP_OKAY) {
+ goto LBL_A1;
+ }
+
+ /* divide out larger power of two */
+ k = mp_cnt_lsb(&a1);
+ if ((res = mp_div_2d(&a1, k, &a1, NULL)) != MP_OKAY) {
+ goto LBL_P1;
+ }
+
+ /* step 4. if e is even set s=1 */
+ if ((k & 1) == 0) {
+ s = 1;
+ } else {
+ /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
+ residue = p->dp[0] & 7;
+
+ if (residue == 1 || residue == 7) {
+ s = 1;
+ } else if (residue == 3 || residue == 5) {
+ s = -1;
+ }
+ }
+
+ /* step 5. if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
+ if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) {
+ s = -s;
+ }
+
+ /* if a1 == 1 we're done */
+ if (mp_cmp_d (&a1, 1) == MP_EQ) {
+ *c = s;
+ } else {
+ /* n1 = n mod a1 */
+ if ((res = mp_mod (p, &a1, &p1)) != MP_OKAY) {
+ goto LBL_P1;
+ }
+ if ((res = mp_jacobi (&p1, &a1, &r)) != MP_OKAY) {
+ goto LBL_P1;
+ }
+ *c = s * r;
+ }
+
+ /* done */
+ res = MP_OKAY;
+LBL_P1:mp_clear (&p1);
+LBL_A1:mp_clear (&a1);
+ return res;
+}
+#endif
+
+/* End: bn_mp_jacobi.c */
+
+/* Start: bn_mp_karatsuba_mul.c */
+#include <tommath.h>
+#ifdef BN_MP_KARATSUBA_MUL_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* c = |a| * |b| using Karatsuba Multiplication using
+ * three half size multiplications
+ *
+ * Let B represent the radix [e.g. 2**DIGIT_BIT] and
+ * let n represent half of the number of digits in
+ * the min(a,b)
+ *
+ * a = a1 * B**n + a0
+ * b = b1 * B**n + b0
+ *
+ * Then, a * b =>
+ a1b1 * B**2n + ((a1 + a0)(b1 + b0) - (a0b0 + a1b1)) * B + a0b0
+ *
+ * Note that a1b1 and a0b0 are used twice and only need to be
+ * computed once. So in total three half size (half # of
+ * digit) multiplications are performed, a0b0, a1b1 and
+ * (a1+b1)(a0+b0)
+ *
+ * Note that a multiplication of half the digits requires
+ * 1/4th the number of single precision multiplications so in
+ * total after one call 25% of the single precision multiplications
+ * are saved. Note also that the call to mp_mul can end up back
+ * in this function if the a0, a1, b0, or b1 are above the threshold.
+ * This is known as divide-and-conquer and leads to the famous
+ * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than
+ * the standard O(N**2) that the baseline/comba methods use.
+ * Generally though the overhead of this method doesn't pay off
+ * until a certain size (N ~ 80) is reached.
+ */
+int mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int x0, x1, y0, y1, t1, x0y0, x1y1;
+ int B, err;
+
+ /* default the return code to an error */
+ err = MP_MEM;
+
+ /* min # of digits */
+ B = MIN (a->used, b->used);
+
+ /* now divide in two */
+ B = B >> 1;
+
+ /* init copy all the temps */
+ if (mp_init_size (&x0, B) != MP_OKAY)
+ goto ERR;
+ if (mp_init_size (&x1, a->used - B) != MP_OKAY)
+ goto X0;
+ if (mp_init_size (&y0, B) != MP_OKAY)
+ goto X1;
+ if (mp_init_size (&y1, b->used - B) != MP_OKAY)
+ goto Y0;
+
+ /* init temps */
+ if (mp_init_size (&t1, B * 2) != MP_OKAY)
+ goto Y1;
+ if (mp_init_size (&x0y0, B * 2) != MP_OKAY)
+ goto T1;
+ if (mp_init_size (&x1y1, B * 2) != MP_OKAY)
+ goto X0Y0;
+
+ /* now shift the digits */
+ x0.used = y0.used = B;
+ x1.used = a->used - B;
+ y1.used = b->used - B;
+
+ {
+ register int x;
+ register mp_digit *tmpa, *tmpb, *tmpx, *tmpy;
+
+ /* we copy the digits directly instead of using higher level functions
+ * since we also need to shift the digits
+ */
+ tmpa = a->dp;
+ tmpb = b->dp;
+
+ tmpx = x0.dp;
+ tmpy = y0.dp;
+ for (x = 0; x < B; x++) {
+ *tmpx++ = *tmpa++;
+ *tmpy++ = *tmpb++;
+ }
+
+ tmpx = x1.dp;
+ for (x = B; x < a->used; x++) {
+ *tmpx++ = *tmpa++;
+ }
+
+ tmpy = y1.dp;
+ for (x = B; x < b->used; x++) {
+ *tmpy++ = *tmpb++;
+ }
+ }
+
+ /* only need to clamp the lower words since by definition the
+ * upper words x1/y1 must have a known number of digits
+ */
+ mp_clamp (&x0);
+ mp_clamp (&y0);
+
+ /* now calc the products x0y0 and x1y1 */
+ /* after this x0 is no longer required, free temp [x0==t2]! */
+ if (mp_mul (&x0, &y0, &x0y0) != MP_OKAY)
+ goto X1Y1; /* x0y0 = x0*y0 */
+ if (mp_mul (&x1, &y1, &x1y1) != MP_OKAY)
+ goto X1Y1; /* x1y1 = x1*y1 */
+
+ /* now calc x1+x0 and y1+y0 */
+ if (s_mp_add (&x1, &x0, &t1) != MP_OKAY)
+ goto X1Y1; /* t1 = x1 - x0 */
+ if (s_mp_add (&y1, &y0, &x0) != MP_OKAY)
+ goto X1Y1; /* t2 = y1 - y0 */
+ if (mp_mul (&t1, &x0, &t1) != MP_OKAY)
+ goto X1Y1; /* t1 = (x1 + x0) * (y1 + y0) */
+
+ /* add x0y0 */
+ if (mp_add (&x0y0, &x1y1, &x0) != MP_OKAY)
+ goto X1Y1; /* t2 = x0y0 + x1y1 */
+ if (s_mp_sub (&t1, &x0, &t1) != MP_OKAY)
+ goto X1Y1; /* t1 = (x1+x0)*(y1+y0) - (x1y1 + x0y0) */
+
+ /* shift by B */
+ if (mp_lshd (&t1, B) != MP_OKAY)
+ goto X1Y1; /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<<B */
+ if (mp_lshd (&x1y1, B * 2) != MP_OKAY)
+ goto X1Y1; /* x1y1 = x1y1 << 2*B */
+
+ if (mp_add (&x0y0, &t1, &t1) != MP_OKAY)
+ goto X1Y1; /* t1 = x0y0 + t1 */
+ if (mp_add (&t1, &x1y1, c) != MP_OKAY)
+ goto X1Y1; /* t1 = x0y0 + t1 + x1y1 */
+
+ /* Algorithm succeeded set the return code to MP_OKAY */
+ err = MP_OKAY;
+
+X1Y1:mp_clear (&x1y1);
+X0Y0:mp_clear (&x0y0);
+T1:mp_clear (&t1);
+Y1:mp_clear (&y1);
+Y0:mp_clear (&y0);
+X1:mp_clear (&x1);
+X0:mp_clear (&x0);
+ERR:
+ return err;
+}
+#endif
+
+/* End: bn_mp_karatsuba_mul.c */
+
+/* Start: bn_mp_karatsuba_sqr.c */
+#include <tommath.h>
+#ifdef BN_MP_KARATSUBA_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* Karatsuba squaring, computes b = a*a using three
+ * half size squarings
+ *
+ * See comments of karatsuba_mul for details. It
+ * is essentially the same algorithm but merely
+ * tuned to perform recursive squarings.
+ */
+int mp_karatsuba_sqr (mp_int * a, mp_int * b)
+{
+ mp_int x0, x1, t1, t2, x0x0, x1x1;
+ int B, err;
+
+ err = MP_MEM;
+
+ /* min # of digits */
+ B = a->used;
+
+ /* now divide in two */
+ B = B >> 1;
+
+ /* init copy all the temps */
+ if (mp_init_size (&x0, B) != MP_OKAY)
+ goto ERR;
+ if (mp_init_size (&x1, a->used - B) != MP_OKAY)
+ goto X0;
+
+ /* init temps */
+ if (mp_init_size (&t1, a->used * 2) != MP_OKAY)
+ goto X1;
+ if (mp_init_size (&t2, a->used * 2) != MP_OKAY)
+ goto T1;
+ if (mp_init_size (&x0x0, B * 2) != MP_OKAY)
+ goto T2;
+ if (mp_init_size (&x1x1, (a->used - B) * 2) != MP_OKAY)
+ goto X0X0;
+
+ {
+ register int x;
+ register mp_digit *dst, *src;
+
+ src = a->dp;
+
+ /* now shift the digits */
+ dst = x0.dp;
+ for (x = 0; x < B; x++) {
+ *dst++ = *src++;
+ }
+
+ dst = x1.dp;
+ for (x = B; x < a->used; x++) {
+ *dst++ = *src++;
+ }
+ }
+
+ x0.used = B;
+ x1.used = a->used - B;
+
+ mp_clamp (&x0);
+
+ /* now calc the products x0*x0 and x1*x1 */
+ if (mp_sqr (&x0, &x0x0) != MP_OKAY)
+ goto X1X1; /* x0x0 = x0*x0 */
+ if (mp_sqr (&x1, &x1x1) != MP_OKAY)
+ goto X1X1; /* x1x1 = x1*x1 */
+
+ /* now calc (x1+x0)**2 */
+ if (s_mp_add (&x1, &x0, &t1) != MP_OKAY)
+ goto X1X1; /* t1 = x1 - x0 */
+ if (mp_sqr (&t1, &t1) != MP_OKAY)
+ goto X1X1; /* t1 = (x1 - x0) * (x1 - x0) */
+
+ /* add x0y0 */
+ if (s_mp_add (&x0x0, &x1x1, &t2) != MP_OKAY)
+ goto X1X1; /* t2 = x0x0 + x1x1 */
+ if (s_mp_sub (&t1, &t2, &t1) != MP_OKAY)
+ goto X1X1; /* t1 = (x1+x0)**2 - (x0x0 + x1x1) */
+
+ /* shift by B */
+ if (mp_lshd (&t1, B) != MP_OKAY)
+ goto X1X1; /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<<B */
+ if (mp_lshd (&x1x1, B * 2) != MP_OKAY)
+ goto X1X1; /* x1x1 = x1x1 << 2*B */
+
+ if (mp_add (&x0x0, &t1, &t1) != MP_OKAY)
+ goto X1X1; /* t1 = x0x0 + t1 */
+ if (mp_add (&t1, &x1x1, b) != MP_OKAY)
+ goto X1X1; /* t1 = x0x0 + t1 + x1x1 */
+
+ err = MP_OKAY;
+
+X1X1:mp_clear (&x1x1);
+X0X0:mp_clear (&x0x0);
+T2:mp_clear (&t2);
+T1:mp_clear (&t1);
+X1:mp_clear (&x1);
+X0:mp_clear (&x0);
+ERR:
+ return err;
+}
+#endif
+
+/* End: bn_mp_karatsuba_sqr.c */
+
+/* Start: bn_mp_lcm.c */
+#include <tommath.h>
+#ifdef BN_MP_LCM_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* computes least common multiple as |a*b|/(a, b) */
+int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res;
+ mp_int t1, t2;
+
+
+ if ((res = mp_init_multi (&t1, &t2, NULL)) != MP_OKAY) {
+ return res;
+ }
+
+ /* t1 = get the GCD of the two inputs */
+ if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) {
+ goto LBL_T;
+ }
+
+ /* divide the smallest by the GCD */
+ if (mp_cmp_mag(a, b) == MP_LT) {
+ /* store quotient in t2 such that t2 * b is the LCM */
+ if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) {
+ goto LBL_T;
+ }
+ res = mp_mul(b, &t2, c);
+ } else {
+ /* store quotient in t2 such that t2 * a is the LCM */
+ if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) {
+ goto LBL_T;
+ }
+ res = mp_mul(a, &t2, c);
+ }
+
+ /* fix the sign to positive */
+ c->sign = MP_ZPOS;
+
+LBL_T:
+ mp_clear_multi (&t1, &t2, NULL);
+ return res;
+}
+#endif
+
+/* End: bn_mp_lcm.c */
+
+/* Start: bn_mp_lshd.c */
+#include <tommath.h>
+#ifdef BN_MP_LSHD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* shift left a certain amount of digits */
+int mp_lshd (mp_int * a, int b)
+{
+ int x, res;
+
+ /* if its less than zero return */
+ if (b <= 0) {
+ return MP_OKAY;
+ }
+
+ /* grow to fit the new digits */
+ if (a->alloc < a->used + b) {
+ if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ {
+ register mp_digit *top, *bottom;
+
+ /* increment the used by the shift amount then copy upwards */
+ a->used += b;
+
+ /* top */
+ top = a->dp + a->used - 1;
+
+ /* base */
+ bottom = a->dp + a->used - 1 - b;
+
+ /* much like mp_rshd this is implemented using a sliding window
+ * except the window goes the otherway around. Copying from
+ * the bottom to the top. see bn_mp_rshd.c for more info.
+ */
+ for (x = a->used - 1; x >= b; x--) {
+ *top-- = *bottom--;
+ }
+
+ /* zero the lower digits */
+ top = a->dp;
+ for (x = 0; x < b; x++) {
+ *top++ = 0;
+ }
+ }
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_lshd.c */
+
+/* Start: bn_mp_mod.c */
+#include <tommath.h>
+#ifdef BN_MP_MOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* c = a mod b, 0 <= c < b */
+int
+mp_mod (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int t;
+ int res;
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+
+ if (t.sign != b->sign) {
+ res = mp_add (b, &t, c);
+ } else {
+ res = MP_OKAY;
+ mp_exch (&t, c);
+ }
+
+ mp_clear (&t);
+ return res;
+}
+#endif
+
+/* End: bn_mp_mod.c */
+
+/* Start: bn_mp_mod_2d.c */
+#include <tommath.h>
+#ifdef BN_MP_MOD_2D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* calc a value mod 2**b */
+int
+mp_mod_2d (mp_int * a, int b, mp_int * c)
+{
+ int x, res;
+
+ /* if b is <= 0 then zero the int */
+ if (b <= 0) {
+ mp_zero (c);
+ return MP_OKAY;
+ }
+
+ /* if the modulus is larger than the value than return */
+ if (b >= (int) (a->used * DIGIT_BIT)) {
+ res = mp_copy (a, c);
+ return res;
+ }
+
+ /* copy */
+ if ((res = mp_copy (a, c)) != MP_OKAY) {
+ return res;
+ }
+
+ /* zero digits above the last digit of the modulus */
+ for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
+ c->dp[x] = 0;
+ }
+ /* clear the digit that is not completely outside/inside the modulus */
+ c->dp[b / DIGIT_BIT] &=
+ (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1));
+ mp_clamp (c);
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_mod_2d.c */
+
+/* Start: bn_mp_mod_d.c */
+#include <tommath.h>
+#ifdef BN_MP_MOD_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+int
+mp_mod_d (mp_int * a, mp_digit b, mp_digit * c)
+{
+ return mp_div_d(a, b, NULL, c);
+}
+#endif
+
+/* End: bn_mp_mod_d.c */
+
+/* Start: bn_mp_montgomery_calc_normalization.c */
+#include <tommath.h>
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/*
+ * shifts with subtractions when the result is greater than b.
+ *
+ * The method is slightly modified to shift B unconditionally upto just under
+ * the leading bit of b. This saves alot of multiple precision shifting.
+ */
+int mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
+{
+ int x, bits, res;
+
+ /* how many bits of last digit does b use */
+ bits = mp_count_bits (b) % DIGIT_BIT;
+
+ if (b->used > 1) {
+ if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) {
+ return res;
+ }
+ } else {
+ mp_set(a, 1);
+ bits = 1;
+ }
+
+
+ /* now compute C = A * B mod b */
+ for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
+ if ((res = mp_mul_2 (a, a)) != MP_OKAY) {
+ return res;
+ }
+ if (mp_cmp_mag (a, b) != MP_LT) {
+ if ((res = s_mp_sub (a, b, a)) != MP_OKAY) {
+ return res;
+ }
+ }
+ }
+
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_montgomery_calc_normalization.c */
+
+/* Start: bn_mp_montgomery_reduce.c */
+#include <tommath.h>
+#ifdef BN_MP_MONTGOMERY_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction */
+int
+mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+ int ix, res, digs;
+ mp_digit mu;
+
+ /* can the fast reduction [comba] method be used?
+ *
+ * Note that unlike in mul you're safely allowed *less*
+ * than the available columns [255 per default] since carries
+ * are fixed up in the inner loop.
+ */
+ digs = n->used * 2 + 1;
+ if ((digs < MP_WARRAY) &&
+ n->used <
+ (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ return fast_mp_montgomery_reduce (x, n, rho);
+ }
+
+ /* grow the input as required */
+ if (x->alloc < digs) {
+ if ((res = mp_grow (x, digs)) != MP_OKAY) {
+ return res;
+ }
+ }
+ x->used = digs;
+
+ for (ix = 0; ix < n->used; ix++) {
+ /* mu = ai * rho mod b
+ *
+ * The value of rho must be precalculated via
+ * montgomery_setup() such that
+ * it equals -1/n0 mod b this allows the
+ * following inner loop to reduce the
+ * input one digit at a time
+ */
+ mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK);
+
+ /* a = a + mu * m * b**i */
+ {
+ register int iy;
+ register mp_digit *tmpn, *tmpx, u;
+ register mp_word r;
+
+ /* alias for digits of the modulus */
+ tmpn = n->dp;
+
+ /* alias for the digits of x [the input] */
+ tmpx = x->dp + ix;
+
+ /* set the carry to zero */
+ u = 0;
+
+ /* Multiply and add in place */
+ for (iy = 0; iy < n->used; iy++) {
+ /* compute product and sum */
+ r = ((mp_word)mu) * ((mp_word)*tmpn++) +
+ ((mp_word) u) + ((mp_word) * tmpx);
+
+ /* get carry */
+ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+ /* fix digit */
+ *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK));
+ }
+ /* At this point the ix'th digit of x should be zero */
+
+
+ /* propagate carries upwards as required*/
+ while (u) {
+ *tmpx += u;
+ u = *tmpx >> DIGIT_BIT;
+ *tmpx++ &= MP_MASK;
+ }
+ }
+ }
+
+ /* at this point the n.used'th least
+ * significant digits of x are all zero
+ * which means we can shift x to the
+ * right by n.used digits and the
+ * residue is unchanged.
+ */
+
+ /* x = x/b**n.used */
+ mp_clamp(x);
+ mp_rshd (x, n->used);
+
+ /* if x >= n then x = x - n */
+ if (mp_cmp_mag (x, n) != MP_LT) {
+ return s_mp_sub (x, n, x);
+ }
+
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_montgomery_reduce.c */
+
+/* Start: bn_mp_montgomery_setup.c */
+#include <tommath.h>
+#ifdef BN_MP_MONTGOMERY_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* setups the montgomery reduction stuff */
+int
+mp_montgomery_setup (mp_int * n, mp_digit * rho)
+{
+ mp_digit x, b;
+
+/* fast inversion mod 2**k
+ *
+ * Based on the fact that
+ *
+ * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n)
+ * => 2*X*A - X*X*A*A = 1
+ * => 2*(1) - (1) = 1
+ */
+ b = n->dp[0];
+
+ if ((b & 1) == 0) {
+ return MP_VAL;
+ }
+
+ x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
+ x *= 2 - b * x; /* here x*a==1 mod 2**8 */
+#if !defined(MP_8BIT)
+ x *= 2 - b * x; /* here x*a==1 mod 2**16 */
+#endif
+#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
+ x *= 2 - b * x; /* here x*a==1 mod 2**32 */
+#endif
+#ifdef MP_64BIT
+ x *= 2 - b * x; /* here x*a==1 mod 2**64 */
+#endif
+
+ /* rho = -1/m mod b */
+ *rho = (unsigned long)(((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK;
+
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_montgomery_setup.c */
+
+/* Start: bn_mp_mul.c */
+#include <tommath.h>
+#ifdef BN_MP_MUL_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* high level multiplication (handles sign) */
+int mp_mul (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res, neg;
+ neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+
+ /* use Toom-Cook? */
+#ifdef BN_MP_TOOM_MUL_C
+ if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) {
+ res = mp_toom_mul(a, b, c);
+ } else
+#endif
+#ifdef BN_MP_KARATSUBA_MUL_C
+ /* use Karatsuba? */
+ if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) {
+ res = mp_karatsuba_mul (a, b, c);
+ } else
+#endif
+ {
+ /* can we use the fast multiplier?
+ *
+ * The fast multiplier can be used if the output will
+ * have less than MP_WARRAY digits and the number of
+ * digits won't affect carry propagation
+ */
+ int digs = a->used + b->used + 1;
+
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
+ if ((digs < MP_WARRAY) &&
+ MIN(a->used, b->used) <=
+ (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ res = fast_s_mp_mul_digs (a, b, c, digs);
+ } else
+#endif
+#ifdef BN_S_MP_MUL_DIGS_C
+ res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */
+#else
+ res = MP_VAL;
+#endif
+
+ }
+ c->sign = (c->used > 0) ? neg : MP_ZPOS;
+ return res;
+}
+#endif
+
+/* End: bn_mp_mul.c */
+
+/* Start: bn_mp_mul_2.c */
+#include <tommath.h>
+#ifdef BN_MP_MUL_2_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* b = a*2 */
+int mp_mul_2(mp_int * a, mp_int * b)
+{
+ int x, res, oldused;
+
+ /* grow to accomodate result */
+ if (b->alloc < a->used + 1) {
+ if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ oldused = b->used;
+ b->used = a->used;
+
+ {
+ register mp_digit r, rr, *tmpa, *tmpb;
+
+ /* alias for source */
+ tmpa = a->dp;
+
+ /* alias for dest */
+ tmpb = b->dp;
+
+ /* carry */
+ r = 0;
+ for (x = 0; x < a->used; x++) {
+
+ /* get what will be the *next* carry bit from the
+ * MSB of the current digit
+ */
+ rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
+
+ /* now shift up this digit, add in the carry [from the previous] */
+ *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
+
+ /* copy the carry that would be from the source
+ * digit into the next iteration
+ */
+ r = rr;
+ }
+
+ /* new leading digit? */
+ if (r != 0) {
+ /* add a MSB which is always 1 at this point */
+ *tmpb = 1;
+ ++(b->used);
+ }
+
+ /* now zero any excess digits on the destination
+ * that we didn't write to
+ */
+ tmpb = b->dp + b->used;
+ for (x = b->used; x < oldused; x++) {
+ *tmpb++ = 0;
+ }
+ }
+ b->sign = a->sign;
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_mul_2.c */
+
+/* Start: bn_mp_mul_2d.c */
+#include <tommath.h>
+#ifdef BN_MP_MUL_2D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* shift left by a certain bit count */
+int mp_mul_2d (mp_int * a, int b, mp_int * c)
+{
+ mp_digit d;
+ int res;
+
+ /* copy */
+ if (a != c) {
+ if ((res = mp_copy (a, c)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) {
+ if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* shift by as many digits in the bit count */
+ if (b >= (int)DIGIT_BIT) {
+ if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* shift any bit count < DIGIT_BIT */
+ d = (mp_digit) (b % DIGIT_BIT);
+ if (d != 0) {
+ register mp_digit *tmpc, shift, mask, r, rr;
+ register int x;
+
+ /* bitmask for carries */
+ mask = (((mp_digit)1) << d) - 1;
+
+ /* shift for msbs */
+ shift = DIGIT_BIT - d;
+
+ /* alias */
+ tmpc = c->dp;
+
+ /* carry */
+ r = 0;
+ for (x = 0; x < c->used; x++) {
+ /* get the higher bits of the current word */
+ rr = (*tmpc >> shift) & mask;
+
+ /* shift the current word and OR in the carry */
+ *tmpc = ((*tmpc << d) | r) & MP_MASK;
+ ++tmpc;
+
+ /* set the carry to the carry bits of the current word */
+ r = rr;
+ }
+
+ /* set final carry */
+ if (r != 0) {
+ c->dp[(c->used)++] = r;
+ }
+ }
+ mp_clamp (c);
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_mul_2d.c */
+
+/* Start: bn_mp_mul_d.c */
+#include <tommath.h>
+#ifdef BN_MP_MUL_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* multiply by a digit */
+int
+mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
+{
+ mp_digit u, *tmpa, *tmpc;
+ mp_word r;
+ int ix, res, olduse;
+
+ /* make sure c is big enough to hold a*b */
+ if (c->alloc < a->used + 1) {
+ if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* get the original destinations used count */
+ olduse = c->used;
+
+ /* set the sign */
+ c->sign = a->sign;
+
+ /* alias for a->dp [source] */
+ tmpa = a->dp;
+
+ /* alias for c->dp [dest] */
+ tmpc = c->dp;
+
+ /* zero carry */
+ u = 0;
+
+ /* compute columns */
+ for (ix = 0; ix < a->used; ix++) {
+ /* compute product and carry sum for this term */
+ r = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
+
+ /* mask off higher bits to get a single digit */
+ *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* send carry into next iteration */
+ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+ }
+
+ /* store final carry [if any] and increment ix offset */
+ *tmpc++ = u;
+ ++ix;
+
+ /* now zero digits above the top */
+ while (ix++ < olduse) {
+ *tmpc++ = 0;
+ }
+
+ /* set used count */
+ c->used = a->used + 1;
+ mp_clamp(c);
+
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_mul_d.c */
+
+/* Start: bn_mp_mulmod.c */
+#include <tommath.h>
+#ifdef BN_MP_MULMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* d = a * b (mod c) */
+int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+ int res;
+ mp_int t;
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_mul (a, b, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ res = mp_mod (&t, c, d);
+ mp_clear (&t);
+ return res;
+}
+#endif
+
+/* End: bn_mp_mulmod.c */
+
+/* Start: bn_mp_n_root.c */
+#include <tommath.h>
+#ifdef BN_MP_N_ROOT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* find the n'th root of an integer
+ *
+ * Result found such that (c)**b <= a and (c+1)**b > a
+ *
+ * This algorithm uses Newton's approximation
+ * x[i+1] = x[i] - f(x[i])/f'(x[i])
+ * which will find the root in log(N) time where
+ * each step involves a fair bit. This is not meant to
+ * find huge roots [square and cube, etc].
+ */
+int mp_n_root (mp_int * a, mp_digit b, mp_int * c)
+{
+ mp_int t1, t2, t3;
+ int res, neg;
+
+ /* input must be positive if b is even */
+ if ((b & 1) == 0 && a->sign == MP_NEG) {
+ return MP_VAL;
+ }
+
+ if ((res = mp_init (&t1)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_init (&t2)) != MP_OKAY) {
+ goto LBL_T1;
+ }
+
+ if ((res = mp_init (&t3)) != MP_OKAY) {
+ goto LBL_T2;
+ }
+
+ /* if a is negative fudge the sign but keep track */
+ neg = a->sign;
+ a->sign = MP_ZPOS;
+
+ /* t2 = 2 */
+ mp_set (&t2, 2);
+
+ do {
+ /* t1 = t2 */
+ if ((res = mp_copy (&t2, &t1)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */
+
+ /* t3 = t1**(b-1) */
+ if ((res = mp_expt_d (&t1, b - 1, &t3)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ /* numerator */
+ /* t2 = t1**b */
+ if ((res = mp_mul (&t3, &t1, &t2)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ /* t2 = t1**b - a */
+ if ((res = mp_sub (&t2, a, &t2)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ /* denominator */
+ /* t3 = t1**(b-1) * b */
+ if ((res = mp_mul_d (&t3, b, &t3)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ /* t3 = (t1**b - a)/(b * t1**(b-1)) */
+ if ((res = mp_div (&t2, &t3, &t3, NULL)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ if ((res = mp_sub (&t1, &t3, &t2)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+ } while (mp_cmp (&t1, &t2) != MP_EQ);
+
+ /* result can be off by a few so check */
+ for (;;) {
+ if ((res = mp_expt_d (&t1, b, &t2)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+
+ if (mp_cmp (&t2, a) == MP_GT) {
+ if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) {
+ goto LBL_T3;
+ }
+ } else {
+ break;
+ }
+ }
+
+ /* reset the sign of a first */
+ a->sign = neg;
+
+ /* set the result */
+ mp_exch (&t1, c);
+
+ /* set the sign of the result */
+ c->sign = neg;
+
+ res = MP_OKAY;
+
+LBL_T3:mp_clear (&t3);
+LBL_T2:mp_clear (&t2);
+LBL_T1:mp_clear (&t1);
+ return res;
+}
+#endif
+
+/* End: bn_mp_n_root.c */
+
+/* Start: bn_mp_neg.c */
+#include <tommath.h>
+#ifdef BN_MP_NEG_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* b = -a */
+int mp_neg (mp_int * a, mp_int * b)
+{
+ int res;
+ if (a != b) {
+ if ((res = mp_copy (a, b)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ if (mp_iszero(b) != MP_YES) {
+ b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS;
+ } else {
+ b->sign = MP_ZPOS;
+ }
+
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_neg.c */
+
+/* Start: bn_mp_or.c */
+#include <tommath.h>
+#ifdef BN_MP_OR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* OR two ints together */
+int mp_or (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res, ix, px;
+ mp_int t, *x;
+
+ if (a->used > b->used) {
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+ px = b->used;
+ x = b;
+ } else {
+ if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+ return res;
+ }
+ px = a->used;
+ x = a;
+ }
+
+ for (ix = 0; ix < px; ix++) {
+ t.dp[ix] |= x->dp[ix];
+ }
+ mp_clamp (&t);
+ mp_exch (c, &t);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_or.c */
+
+/* Start: bn_mp_prime_fermat.c */
+#include <tommath.h>
+#ifdef BN_MP_PRIME_FERMAT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* performs one Fermat test.
+ *
+ * If "a" were prime then b**a == b (mod a) since the order of
+ * the multiplicative sub-group would be phi(a) = a-1. That means
+ * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a).
+ *
+ * Sets result to 1 if the congruence holds, or zero otherwise.
+ */
+int mp_prime_fermat (mp_int * a, mp_int * b, int *result)
+{
+ mp_int t;
+ int err;
+
+ /* default to composite */
+ *result = MP_NO;
+
+ /* ensure b > 1 */
+ if (mp_cmp_d(b, 1) != MP_GT) {
+ return MP_VAL;
+ }
+
+ /* init t */
+ if ((err = mp_init (&t)) != MP_OKAY) {
+ return err;
+ }
+
+ /* compute t = b**a mod a */
+ if ((err = mp_exptmod (b, a, a, &t)) != MP_OKAY) {
+ goto LBL_T;
+ }
+
+ /* is it equal to b? */
+ if (mp_cmp (&t, b) == MP_EQ) {
+ *result = MP_YES;
+ }
+
+ err = MP_OKAY;
+LBL_T:mp_clear (&t);
+ return err;
+}
+#endif
+
+/* End: bn_mp_prime_fermat.c */
+
+/* Start: bn_mp_prime_is_divisible.c */
+#include <tommath.h>
+#ifdef BN_MP_PRIME_IS_DIVISIBLE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* determines if an integers is divisible by one
+ * of the first PRIME_SIZE primes or not
+ *
+ * sets result to 0 if not, 1 if yes
+ */
+int mp_prime_is_divisible (mp_int * a, int *result)
+{
+ int err, ix;
+ mp_digit res;
+
+ /* default to not */
+ *result = MP_NO;
+
+ for (ix = 0; ix < PRIME_SIZE; ix++) {
+ /* what is a mod LBL_prime_tab[ix] */
+ if ((err = mp_mod_d (a, ltm_prime_tab[ix], &res)) != MP_OKAY) {
+ return err;
+ }
+
+ /* is the residue zero? */
+ if (res == 0) {
+ *result = MP_YES;
+ return MP_OKAY;
+ }
+ }
+
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_prime_is_divisible.c */
+
+/* Start: bn_mp_prime_is_prime.c */
+#include <tommath.h>
+#ifdef BN_MP_PRIME_IS_PRIME_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* performs a variable number of rounds of Miller-Rabin
+ *
+ * Probability of error after t rounds is no more than
+
+ *
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+int mp_prime_is_prime (mp_int * a, int t, int *result)
+{
+ mp_int b;
+ int ix, err, res;
+
+ /* default to no */
+ *result = MP_NO;
+
+ /* valid value of t? */
+ if (t <= 0 || t > PRIME_SIZE) {
+ return MP_VAL;
+ }
+
+ /* is the input equal to one of the primes in the table? */
+ for (ix = 0; ix < PRIME_SIZE; ix++) {
+ if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) {
+ *result = 1;
+ return MP_OKAY;
+ }
+ }
+
+ /* first perform trial division */
+ if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) {
+ return err;
+ }
+
+ /* return if it was trivially divisible */
+ if (res == MP_YES) {
+ return MP_OKAY;
+ }
+
+ /* now perform the miller-rabin rounds */
+ if ((err = mp_init (&b)) != MP_OKAY) {
+ return err;
+ }
+
+ for (ix = 0; ix < t; ix++) {
+ /* set the prime */
+ mp_set (&b, ltm_prime_tab[ix]);
+
+ if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) {
+ goto LBL_B;
+ }
+
+ if (res == MP_NO) {
+ goto LBL_B;
+ }
+ }
+
+ /* passed the test */
+ *result = MP_YES;
+LBL_B:mp_clear (&b);
+ return err;
+}
+#endif
+
+/* End: bn_mp_prime_is_prime.c */
+
+/* Start: bn_mp_prime_miller_rabin.c */
+#include <tommath.h>
+#ifdef BN_MP_PRIME_MILLER_RABIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* Miller-Rabin test of "a" to the base of "b" as described in
+ * HAC pp. 139 Algorithm 4.24
+ *
+ * Sets result to 0 if definitely composite or 1 if probably prime.
+ * Randomly the chance of error is no more than 1/4 and often
+ * very much lower.
+ */
+int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
+{
+ mp_int n1, y, r;
+ int s, j, err;
+
+ /* default */
+ *result = MP_NO;
+
+ /* ensure b > 1 */
+ if (mp_cmp_d(b, 1) != MP_GT) {
+ return MP_VAL;
+ }
+
+ /* get n1 = a - 1 */
+ if ((err = mp_init_copy (&n1, a)) != MP_OKAY) {
+ return err;
+ }
+ if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) {
+ goto LBL_N1;
+ }
+
+ /* set 2**s * r = n1 */
+ if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) {
+ goto LBL_N1;
+ }
+
+ /* count the number of least significant bits
+ * which are zero
+ */
+ s = mp_cnt_lsb(&r);
+
+ /* now divide n - 1 by 2**s */
+ if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) {
+ goto LBL_R;
+ }
+
+ /* compute y = b**r mod a */
+ if ((err = mp_init (&y)) != MP_OKAY) {
+ goto LBL_R;
+ }
+ if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ /* if y != 1 and y != n1 do */
+ if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) {
+ j = 1;
+ /* while j <= s-1 and y != n1 */
+ while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) {
+ if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ /* if y == 1 then composite */
+ if (mp_cmp_d (&y, 1) == MP_EQ) {
+ goto LBL_Y;
+ }
+
+ ++j;
+ }
+
+ /* if y != n1 then composite */
+ if (mp_cmp (&y, &n1) != MP_EQ) {
+ goto LBL_Y;
+ }
+ }
+
+ /* probably prime now */
+ *result = MP_YES;
+LBL_Y:mp_clear (&y);
+LBL_R:mp_clear (&r);
+LBL_N1:mp_clear (&n1);
+ return err;
+}
+#endif
+
+/* End: bn_mp_prime_miller_rabin.c */
+
+/* Start: bn_mp_prime_next_prime.c */
+#include <tommath.h>
+#ifdef BN_MP_PRIME_NEXT_PRIME_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* finds the next prime after the number "a" using "t" trials
+ * of Miller-Rabin.
+ *
+ * bbs_style = 1 means the prime must be congruent to 3 mod 4
+ */
+int mp_prime_next_prime(mp_int *a, int t, int bbs_style)
+{
+ int err, res, x, y;
+ mp_digit res_tab[PRIME_SIZE], step, kstep;
+ mp_int b;
+
+ /* ensure t is valid */
+ if (t <= 0 || t > PRIME_SIZE) {
+ return MP_VAL;
+ }
+
+ /* force positive */
+ a->sign = MP_ZPOS;
+
+ /* simple algo if a is less than the largest prime in the table */
+ if (mp_cmp_d(a, ltm_prime_tab[PRIME_SIZE-1]) == MP_LT) {
+ /* find which prime it is bigger than */
+ for (x = PRIME_SIZE - 2; x >= 0; x--) {
+ if (mp_cmp_d(a, ltm_prime_tab[x]) != MP_LT) {
+ if (bbs_style == 1) {
+ /* ok we found a prime smaller or
+ * equal [so the next is larger]
+ *
+ * however, the prime must be
+ * congruent to 3 mod 4
+ */
+ if ((ltm_prime_tab[x + 1] & 3) != 3) {
+ /* scan upwards for a prime congruent to 3 mod 4 */
+ for (y = x + 1; y < PRIME_SIZE; y++) {
+ if ((ltm_prime_tab[y] & 3) == 3) {
+ mp_set(a, ltm_prime_tab[y]);
+ return MP_OKAY;
+ }
+ }
+ }
+ } else {
+ mp_set(a, ltm_prime_tab[x + 1]);
+ return MP_OKAY;
+ }
+ }
+ }
+ /* at this point a maybe 1 */
+ if (mp_cmp_d(a, 1) == MP_EQ) {
+ mp_set(a, 2);
+ return MP_OKAY;
+ }
+ /* fall through to the sieve */
+ }
+
+ /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */
+ if (bbs_style == 1) {
+ kstep = 4;
+ } else {
+ kstep = 2;
+ }
+
+ /* at this point we will use a combination of a sieve and Miller-Rabin */
+
+ if (bbs_style == 1) {
+ /* if a mod 4 != 3 subtract the correct value to make it so */
+ if ((a->dp[0] & 3) != 3) {
+ if ((err = mp_sub_d(a, (a->dp[0] & 3) + 1, a)) != MP_OKAY) { return err; };
+ }
+ } else {
+ if (mp_iseven(a) == 1) {
+ /* force odd */
+ if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) {
+ return err;
+ }
+ }
+ }
+
+ /* generate the restable */
+ for (x = 1; x < PRIME_SIZE; x++) {
+ if ((err = mp_mod_d(a, ltm_prime_tab[x], res_tab + x)) != MP_OKAY) {
+ return err;
+ }
+ }
+
+ /* init temp used for Miller-Rabin Testing */
+ if ((err = mp_init(&b)) != MP_OKAY) {
+ return err;
+ }
+
+ for (;;) {
+ /* skip to the next non-trivially divisible candidate */
+ step = 0;
+ do {
+ /* y == 1 if any residue was zero [e.g. cannot be prime] */
+ y = 0;
+
+ /* increase step to next candidate */
+ step += kstep;
+
+ /* compute the new residue without using division */
+ for (x = 1; x < PRIME_SIZE; x++) {
+ /* add the step to each residue */
+ res_tab[x] += kstep;
+
+ /* subtract the modulus [instead of using division] */
+ if (res_tab[x] >= ltm_prime_tab[x]) {
+ res_tab[x] -= ltm_prime_tab[x];
+ }
+
+ /* set flag if zero */
+ if (res_tab[x] == 0) {
+ y = 1;
+ }
+ }
+ } while (y == 1 && step < ((((mp_digit)1)<<DIGIT_BIT) - kstep));
+
+ /* add the step */
+ if ((err = mp_add_d(a, step, a)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ /* if didn't pass sieve and step == MAX then skip test */
+ if (y == 1 && step >= ((((mp_digit)1)<<DIGIT_BIT) - kstep)) {
+ continue;
+ }
+
+ /* is this prime? */
+ for (x = 0; x < t; x++) {
+ mp_set(&b, ltm_prime_tab[x]);
+ if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if (res == MP_NO) {
+ break;
+ }
+ }
+
+ if (res == MP_YES) {
+ break;
+ }
+ }
+
+ err = MP_OKAY;
+LBL_ERR:
+ mp_clear(&b);
+ return err;
+}
+
+#endif
+
+/* End: bn_mp_prime_next_prime.c */
+
+/* Start: bn_mp_prime_rabin_miller_trials.c */
+#include <tommath.h>
+#ifdef BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+
+static const struct {
+ int k, t;
+} sizes[] = {
+{ 128, 28 },
+{ 256, 16 },
+{ 384, 10 },
+{ 512, 7 },
+{ 640, 6 },
+{ 768, 5 },
+{ 896, 4 },
+{ 1024, 4 }
+};
+
+/* returns # of RM trials required for a given bit size */
+int mp_prime_rabin_miller_trials(int size)
+{
+ int x;
+
+ for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) {
+ if (sizes[x].k == size) {
+ return sizes[x].t;
+ } else if (sizes[x].k > size) {
+ return (x == 0) ? sizes[0].t : sizes[x - 1].t;
+ }
+ }
+ return sizes[x-1].t + 1;
+}
+
+
+#endif
+
+/* End: bn_mp_prime_rabin_miller_trials.c */
+
+/* Start: bn_mp_prime_random_ex.c */
+#include <tommath.h>
+#ifdef BN_MP_PRIME_RANDOM_EX_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* makes a truly random prime of a given size (bits),
+ *
+ * Flags are as follows:
+ *
+ * LTM_PRIME_BBS - make prime congruent to 3 mod 4
+ * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
+ * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
+ * LTM_PRIME_2MSB_ON - make the 2nd highest bit one
+ *
+ * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ */
+
+/* This is possibly the mother of all prime generation functions, muahahahahaha! */
+int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat)
+{
+ unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb;
+ int res, err, bsize, maskOR_msb_offset;
+
+ /* sanity check the input */
+ if (size <= 1 || t <= 0) {
+ return MP_VAL;
+ }
+
+ /* LTM_PRIME_SAFE implies LTM_PRIME_BBS */
+ if (flags & LTM_PRIME_SAFE) {
+ flags |= LTM_PRIME_BBS;
+ }
+
+ /* calc the byte size */
+ bsize = (size>>3) + ((size&7)?1:0);
+
+ /* we need a buffer of bsize bytes */
+ tmp = OPT_CAST(unsigned char) XMALLOC(bsize);
+ if (tmp == NULL) {
+ return MP_MEM;
+ }
+
+ /* calc the maskAND value for the MSbyte*/
+ maskAND = ((size&7) == 0) ? 0xFF : (0xFF >> (8 - (size & 7)));
+
+ /* calc the maskOR_msb */
+ maskOR_msb = 0;
+ maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0;
+ if (flags & LTM_PRIME_2MSB_ON) {
+ maskOR_msb |= 0x80 >> ((9 - size) & 7);
+ }
+
+ /* get the maskOR_lsb */
+ maskOR_lsb = 1;
+ if (flags & LTM_PRIME_BBS) {
+ maskOR_lsb |= 3;
+ }
+
+ do {
+ /* read the bytes */
+ if (cb(tmp, bsize, dat) != bsize) {
+ err = MP_VAL;
+ goto error;
+ }
+
+ /* work over the MSbyte */
+ tmp[0] &= maskAND;
+ tmp[0] |= 1 << ((size - 1) & 7);
+
+ /* mix in the maskORs */
+ tmp[maskOR_msb_offset] |= maskOR_msb;
+ tmp[bsize-1] |= maskOR_lsb;
+
+ /* read it in */
+ if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY) { goto error; }
+
+ /* is it prime? */
+ if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; }
+ if (res == MP_NO) {
+ continue;
+ }
+
+ if (flags & LTM_PRIME_SAFE) {
+ /* see if (a-1)/2 is prime */
+ if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) { goto error; }
+ if ((err = mp_div_2(a, a)) != MP_OKAY) { goto error; }
+
+ /* is it prime? */
+ if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; }
+ }
+ } while (res == MP_NO);
+
+ if (flags & LTM_PRIME_SAFE) {
+ /* restore a to the original value */
+ if ((err = mp_mul_2(a, a)) != MP_OKAY) { goto error; }
+ if ((err = mp_add_d(a, 1, a)) != MP_OKAY) { goto error; }
+ }
+
+ err = MP_OKAY;
+error:
+ XFREE(tmp);
+ return err;
+}
+
+
+#endif
+
+/* End: bn_mp_prime_random_ex.c */
+
+/* Start: bn_mp_radix_size.c */
+#include <tommath.h>
+#ifdef BN_MP_RADIX_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* returns size of ASCII reprensentation */
+int mp_radix_size (mp_int * a, int radix, int *size)
+{
+ int res, digs;
+ mp_int t;
+ mp_digit d;
+
+ *size = 0;
+
+ /* special case for binary */
+ if (radix == 2) {
+ *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
+ return MP_OKAY;
+ }
+
+ /* make sure the radix is in range */
+ if (radix < 2 || radix > 64) {
+ return MP_VAL;
+ }
+
+ if (mp_iszero(a) == MP_YES) {
+ *size = 2;
+ return MP_OKAY;
+ }
+
+ /* digs is the digit count */
+ digs = 0;
+
+ /* if it's negative add one for the sign */
+ if (a->sign == MP_NEG) {
+ ++digs;
+ }
+
+ /* init a copy of the input */
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+
+ /* force temp to positive */
+ t.sign = MP_ZPOS;
+
+ /* fetch out all of the digits */
+ while (mp_iszero (&t) == MP_NO) {
+ if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ ++digs;
+ }
+ mp_clear (&t);
+
+ /* return digs + 1, the 1 is for the NULL byte that would be required. */
+ *size = digs + 1;
+ return MP_OKAY;
+}
+
+#endif
+
+/* End: bn_mp_radix_size.c */
+
+/* Start: bn_mp_radix_smap.c */
+#include <tommath.h>
+#ifdef BN_MP_RADIX_SMAP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* chars used in radix conversions */
+const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
+#endif
+
+/* End: bn_mp_radix_smap.c */
+
+/* Start: bn_mp_rand.c */
+#include <tommath.h>
+#ifdef BN_MP_RAND_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* makes a pseudo-random int of a given size */
+int
+mp_rand (mp_int * a, int digits)
+{
+ int res;
+ mp_digit d;
+
+ mp_zero (a);
+ if (digits <= 0) {
+ return MP_OKAY;
+ }
+
+ /* first place a random non-zero digit */
+ do {
+ d = ((mp_digit) abs (rand ())) & MP_MASK;
+ } while (d == 0);
+
+ if ((res = mp_add_d (a, d, a)) != MP_OKAY) {
+ return res;
+ }
+
+ while (--digits > 0) {
+ if ((res = mp_lshd (a, 1)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_rand.c */
+
+/* Start: bn_mp_read_radix.c */
+#include <tommath.h>
+#ifdef BN_MP_READ_RADIX_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* read a string [ASCII] in a given radix */
+int mp_read_radix (mp_int * a, const char *str, int radix)
+{
+ int y, res, neg;
+ char ch;
+
+ /* zero the digit bignum */
+ mp_zero(a);
+
+ /* make sure the radix is ok */
+ if (radix < 2 || radix > 64) {
+ return MP_VAL;
+ }
+
+ /* if the leading digit is a
+ * minus set the sign to negative.
+ */
+ if (*str == '-') {
+ ++str;
+ neg = MP_NEG;
+ } else {
+ neg = MP_ZPOS;
+ }
+
+ /* set the integer to the default of zero */
+ mp_zero (a);
+
+ /* process each digit of the string */
+ while (*str) {
+ /* if the radix < 36 the conversion is case insensitive
+ * this allows numbers like 1AB and 1ab to represent the same value
+ * [e.g. in hex]
+ */
+ ch = (char) ((radix < 36) ? toupper (*str) : *str);
+ for (y = 0; y < 64; y++) {
+ if (ch == mp_s_rmap[y]) {
+ break;
+ }
+ }
+
+ /* if the char was found in the map
+ * and is less than the given radix add it
+ * to the number, otherwise exit the loop.
+ */
+ if (y < radix) {
+ if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) {
+ return res;
+ }
+ if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) {
+ return res;
+ }
+ } else {
+ break;
+ }
+ ++str;
+ }
+
+ /* set the sign only if a != 0 */
+ if (mp_iszero(a) != 1) {
+ a->sign = neg;
+ }
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_read_radix.c */
+
+/* Start: bn_mp_read_signed_bin.c */
+#include <tommath.h>
+#ifdef BN_MP_READ_SIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* read signed bin, big endian, first byte is 0==positive or 1==negative */
+int mp_read_signed_bin (mp_int * a, const unsigned char *b, int c)
+{
+ int res;
+
+ /* read magnitude */
+ if ((res = mp_read_unsigned_bin (a, b + 1, c - 1)) != MP_OKAY) {
+ return res;
+ }
+
+ /* first byte is 0 for positive, non-zero for negative */
+ if (b[0] == 0) {
+ a->sign = MP_ZPOS;
+ } else {
+ a->sign = MP_NEG;
+ }
+
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_read_signed_bin.c */
+
+/* Start: bn_mp_read_unsigned_bin.c */
+#include <tommath.h>
+#ifdef BN_MP_READ_UNSIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* reads a unsigned char array, assumes the msb is stored first [big endian] */
+int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c)
+{
+ int res;
+
+ /* make sure there are at least two digits */
+ if (a->alloc < 2) {
+ if ((res = mp_grow(a, 2)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* zero the int */
+ mp_zero (a);
+
+ /* read the bytes in */
+ while (c-- > 0) {
+ if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) {
+ return res;
+ }
+
+#ifndef MP_8BIT
+ a->dp[0] |= *b++;
+ a->used += 1;
+#else
+ a->dp[0] = (*b & MP_MASK);
+ a->dp[1] |= ((*b++ >> 7U) & 1);
+ a->used += 2;
+#endif
+ }
+ mp_clamp (a);
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_read_unsigned_bin.c */
+
+/* Start: bn_mp_reduce.c */
+#include <tommath.h>
+#ifdef BN_MP_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* reduces x mod m, assumes 0 < x < m**2, mu is
+ * precomputed via mp_reduce_setup.
+ * From HAC pp.604 Algorithm 14.42
+ */
+int mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
+{
+ mp_int q;
+ int res, um = m->used;
+
+ /* q = x */
+ if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
+ return res;
+ }
+
+ /* q1 = x / b**(k-1) */
+ mp_rshd (&q, um - 1);
+
+ /* according to HAC this optimization is ok */
+ if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
+ if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+ } else {
+#ifdef BN_S_MP_MUL_HIGH_DIGS_C
+ if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
+ if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+#else
+ {
+ res = MP_VAL;
+ goto CLEANUP;
+ }
+#endif
+ }
+
+ /* q3 = q2 / b**(k+1) */
+ mp_rshd (&q, um + 1);
+
+ /* x = x mod b**(k+1), quick (no division) */
+ if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+
+ /* q = q * m mod b**(k+1), quick (no division) */
+ if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+
+ /* x = x - q */
+ if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+
+ /* If x < 0, add b**(k+1) to it */
+ if (mp_cmp_d (x, 0) == MP_LT) {
+ mp_set (&q, 1);
+ if ((res = mp_lshd (&q, um + 1)) != MP_OKAY)
+ goto CLEANUP;
+ if ((res = mp_add (x, &q, x)) != MP_OKAY)
+ goto CLEANUP;
+ }
+
+ /* Back off if it's too big */
+ while (mp_cmp (x, m) != MP_LT) {
+ if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+ }
+
+CLEANUP:
+ mp_clear (&q);
+
+ return res;
+}
+#endif
+
+/* End: bn_mp_reduce.c */
+
+/* Start: bn_mp_reduce_2k.c */
+#include <tommath.h>
+#ifdef BN_MP_REDUCE_2K_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* reduces a modulo n where n is of the form 2**p - d */
+int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d)
+{
+ mp_int q;
+ int p, res;
+
+ if ((res = mp_init(&q)) != MP_OKAY) {
+ return res;
+ }
+
+ p = mp_count_bits(n);
+top:
+ /* q = a/2**p, a = a mod 2**p */
+ if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if (d != 1) {
+ /* q = q * d */
+ if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) {
+ goto ERR;
+ }
+ }
+
+ /* a = a + q */
+ if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if (mp_cmp_mag(a, n) != MP_LT) {
+ s_mp_sub(a, n, a);
+ goto top;
+ }
+
+ERR:
+ mp_clear(&q);
+ return res;
+}
+
+#endif
+
+/* End: bn_mp_reduce_2k.c */
+
+/* Start: bn_mp_reduce_2k_l.c */
+#include <tommath.h>
+#ifdef BN_MP_REDUCE_2K_L_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* reduces a modulo n where n is of the form 2**p - d
+ This differs from reduce_2k since "d" can be larger
+ than a single digit.
+*/
+int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d)
+{
+ mp_int q;
+ int p, res;
+
+ if ((res = mp_init(&q)) != MP_OKAY) {
+ return res;
+ }
+
+ p = mp_count_bits(n);
+top:
+ /* q = a/2**p, a = a mod 2**p */
+ if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* q = q * d */
+ if ((res = mp_mul(&q, d, &q)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* a = a + q */
+ if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if (mp_cmp_mag(a, n) != MP_LT) {
+ s_mp_sub(a, n, a);
+ goto top;
+ }
+
+ERR:
+ mp_clear(&q);
+ return res;
+}
+
+#endif
+
+/* End: bn_mp_reduce_2k_l.c */
+
+/* Start: bn_mp_reduce_2k_setup.c */
+#include <tommath.h>
+#ifdef BN_MP_REDUCE_2K_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* determines the setup value */
+int mp_reduce_2k_setup(mp_int *a, mp_digit *d)
+{
+ int res, p;
+ mp_int tmp;
+
+ if ((res = mp_init(&tmp)) != MP_OKAY) {
+ return res;
+ }
+
+ p = mp_count_bits(a);
+ if ((res = mp_2expt(&tmp, p)) != MP_OKAY) {
+ mp_clear(&tmp);
+ return res;
+ }
+
+ if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) {
+ mp_clear(&tmp);
+ return res;
+ }
+
+ *d = tmp.dp[0];
+ mp_clear(&tmp);
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_reduce_2k_setup.c */
+
+/* Start: bn_mp_reduce_2k_setup_l.c */
+#include <tommath.h>
+#ifdef BN_MP_REDUCE_2K_SETUP_L_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* determines the setup value */
+int mp_reduce_2k_setup_l(mp_int *a, mp_int *d)
+{
+ int res;
+ mp_int tmp;
+
+ if ((res = mp_init(&tmp)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ERR:
+ mp_clear(&tmp);
+ return res;
+}
+#endif
+
+/* End: bn_mp_reduce_2k_setup_l.c */
+
+/* Start: bn_mp_reduce_is_2k.c */
+#include <tommath.h>
+#ifdef BN_MP_REDUCE_IS_2K_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* determines if mp_reduce_2k can be used */
+int mp_reduce_is_2k(mp_int *a)
+{
+ int ix, iy, iw;
+ mp_digit iz;
+
+ if (a->used == 0) {
+ return MP_NO;
+ } else if (a->used == 1) {
+ return MP_YES;
+ } else if (a->used > 1) {
+ iy = mp_count_bits(a);
+ iz = 1;
+ iw = 1;
+
+ /* Test every bit from the second digit up, must be 1 */
+ for (ix = DIGIT_BIT; ix < iy; ix++) {
+ if ((a->dp[iw] & iz) == 0) {
+ return MP_NO;
+ }
+ iz <<= 1;
+ if (iz > (mp_digit)MP_MASK) {
+ ++iw;
+ iz = 1;
+ }
+ }
+ }
+ return MP_YES;
+}
+
+#endif
+
+/* End: bn_mp_reduce_is_2k.c */
+
+/* Start: bn_mp_reduce_is_2k_l.c */
+#include <tommath.h>
+#ifdef BN_MP_REDUCE_IS_2K_L_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* determines if reduce_2k_l can be used */
+int mp_reduce_is_2k_l(mp_int *a)
+{
+ int ix, iy;
+
+ if (a->used == 0) {
+ return MP_NO;
+ } else if (a->used == 1) {
+ return MP_YES;
+ } else if (a->used > 1) {
+ /* if more than half of the digits are -1 we're sold */
+ for (iy = ix = 0; ix < a->used; ix++) {
+ if (a->dp[ix] == MP_MASK) {
+ ++iy;
+ }
+ }
+ return (iy >= (a->used/2)) ? MP_YES : MP_NO;
+
+ }
+ return MP_NO;
+}
+
+#endif
+
+/* End: bn_mp_reduce_is_2k_l.c */
+
+/* Start: bn_mp_reduce_setup.c */
+#include <tommath.h>
+#ifdef BN_MP_REDUCE_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* pre-calculate the value required for Barrett reduction
+ * For a given modulus "b" it calulates the value required in "a"
+ */
+int mp_reduce_setup (mp_int * a, mp_int * b)
+{
+ int res;
+
+ if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {
+ return res;
+ }
+ return mp_div (a, b, a, NULL);
+}
+#endif
+
+/* End: bn_mp_reduce_setup.c */
+
+/* Start: bn_mp_rshd.c */
+#include <tommath.h>
+#ifdef BN_MP_RSHD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* shift right a certain amount of digits */
+void mp_rshd (mp_int * a, int b)
+{
+ int x;
+
+ /* if b <= 0 then ignore it */
+ if (b <= 0) {
+ return;
+ }
+
+ /* if b > used then simply zero it and return */
+ if (a->used <= b) {
+ mp_zero (a);
+ return;
+ }
+
+ {
+ register mp_digit *bottom, *top;
+
+ /* shift the digits down */
+
+ /* bottom */
+ bottom = a->dp;
+
+ /* top [offset into digits] */
+ top = a->dp + b;
+
+ /* this is implemented as a sliding window where
+ * the window is b-digits long and digits from
+ * the top of the window are copied to the bottom
+ *
+ * e.g.
+
+ b-2 | b-1 | b0 | b1 | b2 | ... | bb | ---->
+ /\ | ---->
+ \-------------------/ ---->
+ */
+ for (x = 0; x < (a->used - b); x++) {
+ *bottom++ = *top++;
+ }
+
+ /* zero the top digits */
+ for (; x < a->used; x++) {
+ *bottom++ = 0;
+ }
+ }
+
+ /* remove excess digits */
+ a->used -= b;
+}
+#endif
+
+/* End: bn_mp_rshd.c */
+
+/* Start: bn_mp_set.c */
+#include <tommath.h>
+#ifdef BN_MP_SET_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* set to a digit */
+void mp_set (mp_int * a, mp_digit b)
+{
+ mp_zero (a);
+ a->dp[0] = b & MP_MASK;
+ a->used = (a->dp[0] != 0) ? 1 : 0;
+}
+#endif
+
+/* End: bn_mp_set.c */
+
+/* Start: bn_mp_set_int.c */
+#include <tommath.h>
+#ifdef BN_MP_SET_INT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* set a 32-bit const */
+int mp_set_int (mp_int * a, unsigned long b)
+{
+ int x, res;
+
+ mp_zero (a);
+
+ /* set four bits at a time */
+ for (x = 0; x < 8; x++) {
+ /* shift the number up four bits */
+ if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) {
+ return res;
+ }
+
+ /* OR in the top four bits of the source */
+ a->dp[0] |= (b >> 28) & 15;
+
+ /* shift the source up to the next four bits */
+ b <<= 4;
+
+ /* ensure that digits are not clamped off */
+ a->used += 1;
+ }
+ mp_clamp (a);
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_set_int.c */
+
+/* Start: bn_mp_shrink.c */
+#include <tommath.h>
+#ifdef BN_MP_SHRINK_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* shrink a bignum */
+int mp_shrink (mp_int * a)
+{
+ mp_digit *tmp;
+ int used = 1;
+
+ if(a->used > 0)
+ used = a->used;
+
+ if (a->alloc != used) {
+ if ((tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * used)) == NULL) {
+ return MP_MEM;
+ }
+ a->dp = tmp;
+ a->alloc = used;
+ }
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_shrink.c */
+
+/* Start: bn_mp_signed_bin_size.c */
+#include <tommath.h>
+#ifdef BN_MP_SIGNED_BIN_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* get the size for an signed equivalent */
+int mp_signed_bin_size (mp_int * a)
+{
+ return 1 + mp_unsigned_bin_size (a);
+}
+#endif
+
+/* End: bn_mp_signed_bin_size.c */
+
+/* Start: bn_mp_sqr.c */
+#include <tommath.h>
+#ifdef BN_MP_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* computes b = a*a */
+int
+mp_sqr (mp_int * a, mp_int * b)
+{
+ int res;
+
+#ifdef BN_MP_TOOM_SQR_C
+ /* use Toom-Cook? */
+ if (a->used >= TOOM_SQR_CUTOFF) {
+ res = mp_toom_sqr(a, b);
+ /* Karatsuba? */
+ } else
+#endif
+#ifdef BN_MP_KARATSUBA_SQR_C
+if (a->used >= KARATSUBA_SQR_CUTOFF) {
+ res = mp_karatsuba_sqr (a, b);
+ } else
+#endif
+ {
+#ifdef BN_FAST_S_MP_SQR_C
+ /* can we use the fast comba multiplier? */
+ if ((a->used * 2 + 1) < MP_WARRAY &&
+ a->used <
+ (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {
+ res = fast_s_mp_sqr (a, b);
+ } else
+#endif
+#ifdef BN_S_MP_SQR_C
+ res = s_mp_sqr (a, b);
+#else
+ res = MP_VAL;
+#endif
+ }
+ b->sign = MP_ZPOS;
+ return res;
+}
+#endif
+
+/* End: bn_mp_sqr.c */
+
+/* Start: bn_mp_sqrmod.c */
+#include <tommath.h>
+#ifdef BN_MP_SQRMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* c = a * a (mod b) */
+int
+mp_sqrmod (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res;
+ mp_int t;
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_sqr (a, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ res = mp_mod (&t, b, c);
+ mp_clear (&t);
+ return res;
+}
+#endif
+
+/* End: bn_mp_sqrmod.c */
+
+/* Start: bn_mp_sqrt.c */
+#include <tommath.h>
+
+#ifdef BN_MP_SQRT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* this function is less generic than mp_n_root, simpler and faster */
+int mp_sqrt(mp_int *arg, mp_int *ret)
+{
+ int res;
+ mp_int t1,t2;
+
+ /* must be positive */
+ if (arg->sign == MP_NEG) {
+ return MP_VAL;
+ }
+
+ /* easy out */
+ if (mp_iszero(arg) == MP_YES) {
+ mp_zero(ret);
+ return MP_OKAY;
+ }
+
+ if ((res = mp_init_copy(&t1, arg)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_init(&t2)) != MP_OKAY) {
+ goto E2;
+ }
+
+ /* First approx. (not very bad for large arg) */
+ mp_rshd (&t1,t1.used/2);
+
+ /* t1 > 0 */
+ if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
+ goto E1;
+ }
+ if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
+ goto E1;
+ }
+ if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
+ goto E1;
+ }
+ /* And now t1 > sqrt(arg) */
+ do {
+ if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
+ goto E1;
+ }
+ if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
+ goto E1;
+ }
+ if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
+ goto E1;
+ }
+ /* t1 >= sqrt(arg) >= t2 at this point */
+ } while (mp_cmp_mag(&t1,&t2) == MP_GT);
+
+ mp_exch(&t1,ret);
+
+E1: mp_clear(&t2);
+E2: mp_clear(&t1);
+ return res;
+}
+
+#endif
+
+/* End: bn_mp_sqrt.c */
+
+/* Start: bn_mp_sub.c */
+#include <tommath.h>
+#ifdef BN_MP_SUB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* high level subtraction (handles signs) */
+int
+mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+ int sa, sb, res;
+
+ sa = a->sign;
+ sb = b->sign;
+
+ if (sa != sb) {
+ /* subtract a negative from a positive, OR */
+ /* subtract a positive from a negative. */
+ /* In either case, ADD their magnitudes, */
+ /* and use the sign of the first number. */
+ c->sign = sa;
+ res = s_mp_add (a, b, c);
+ } else {
+ /* subtract a positive from a positive, OR */
+ /* subtract a negative from a negative. */
+ /* First, take the difference between their */
+ /* magnitudes, then... */
+ if (mp_cmp_mag (a, b) != MP_LT) {
+ /* Copy the sign from the first */
+ c->sign = sa;
+ /* The first has a larger or equal magnitude */
+ res = s_mp_sub (a, b, c);
+ } else {
+ /* The result has the *opposite* sign from */
+ /* the first number. */
+ c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
+ /* The second has a larger magnitude */
+ res = s_mp_sub (b, a, c);
+ }
+ }
+ return res;
+}
+
+#endif
+
+/* End: bn_mp_sub.c */
+
+/* Start: bn_mp_sub_d.c */
+#include <tommath.h>
+#ifdef BN_MP_SUB_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* single digit subtraction */
+int
+mp_sub_d (mp_int * a, mp_digit b, mp_int * c)
+{
+ mp_digit *tmpa, *tmpc, mu;
+ int res, ix, oldused;
+
+ /* grow c as required */
+ if (c->alloc < a->used + 1) {
+ if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* if a is negative just do an unsigned
+ * addition [with fudged signs]
+ */
+ if (a->sign == MP_NEG) {
+ a->sign = MP_ZPOS;
+ res = mp_add_d(a, b, c);
+ a->sign = c->sign = MP_NEG;
+
+ /* clamp */
+ mp_clamp(c);
+
+ return res;
+ }
+
+ /* setup regs */
+ oldused = c->used;
+ tmpa = a->dp;
+ tmpc = c->dp;
+
+ /* if a <= b simply fix the single digit */
+ if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) {
+ if (a->used == 1) {
+ *tmpc++ = b - *tmpa;
+ } else {
+ *tmpc++ = b;
+ }
+ ix = 1;
+
+ /* negative/1digit */
+ c->sign = MP_NEG;
+ c->used = 1;
+ } else {
+ /* positive/size */
+ c->sign = MP_ZPOS;
+ c->used = a->used;
+
+ /* subtract first digit */
+ *tmpc = *tmpa++ - b;
+ mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
+ *tmpc++ &= MP_MASK;
+
+ /* handle rest of the digits */
+ for (ix = 1; ix < a->used; ix++) {
+ *tmpc = *tmpa++ - mu;
+ mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
+ *tmpc++ &= MP_MASK;
+ }
+ }
+
+ /* zero excess digits */
+ while (ix++ < oldused) {
+ *tmpc++ = 0;
+ }
+ mp_clamp(c);
+ return MP_OKAY;
+}
+
+#endif
+
+/* End: bn_mp_sub_d.c */
+
+/* Start: bn_mp_submod.c */
+#include <tommath.h>
+#ifdef BN_MP_SUBMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* d = a - b (mod c) */
+int
+mp_submod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+ int res;
+ mp_int t;
+
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_sub (a, b, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ res = mp_mod (&t, c, d);
+ mp_clear (&t);
+ return res;
+}
+#endif
+
+/* End: bn_mp_submod.c */
+
+/* Start: bn_mp_to_signed_bin.c */
+#include <tommath.h>
+#ifdef BN_MP_TO_SIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* store in signed [big endian] format */
+int mp_to_signed_bin (mp_int * a, unsigned char *b)
+{
+ int res;
+
+ if ((res = mp_to_unsigned_bin (a, b + 1)) != MP_OKAY) {
+ return res;
+ }
+ b[0] = (unsigned char) ((a->sign == MP_ZPOS) ? 0 : 1);
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_to_signed_bin.c */
+
+/* Start: bn_mp_to_signed_bin_n.c */
+#include <tommath.h>
+#ifdef BN_MP_TO_SIGNED_BIN_N_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* store in signed [big endian] format */
+int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen)
+{
+ if (*outlen < (unsigned long)mp_signed_bin_size(a)) {
+ return MP_VAL;
+ }
+ *outlen = mp_signed_bin_size(a);
+ return mp_to_signed_bin(a, b);
+}
+#endif
+
+/* End: bn_mp_to_signed_bin_n.c */
+
+/* Start: bn_mp_to_unsigned_bin.c */
+#include <tommath.h>
+#ifdef BN_MP_TO_UNSIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* store in unsigned [big endian] format */
+int mp_to_unsigned_bin (mp_int * a, unsigned char *b)
+{
+ int x, res;
+ mp_int t;
+
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+
+ x = 0;
+ while (mp_iszero (&t) == 0) {
+#ifndef MP_8BIT
+ b[x++] = (unsigned char) (t.dp[0] & 255);
+#else
+ b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7));
+#endif
+ if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ }
+ bn_reverse (b, x);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_to_unsigned_bin.c */
+
+/* Start: bn_mp_to_unsigned_bin_n.c */
+#include <tommath.h>
+#ifdef BN_MP_TO_UNSIGNED_BIN_N_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* store in unsigned [big endian] format */
+int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen)
+{
+ if (*outlen < (unsigned long)mp_unsigned_bin_size(a)) {
+ return MP_VAL;
+ }
+ *outlen = mp_unsigned_bin_size(a);
+ return mp_to_unsigned_bin(a, b);
+}
+#endif
+
+/* End: bn_mp_to_unsigned_bin_n.c */
+
+/* Start: bn_mp_toom_mul.c */
+#include <tommath.h>
+#ifdef BN_MP_TOOM_MUL_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* multiplication using the Toom-Cook 3-way algorithm
+ *
+ * Much more complicated than Karatsuba but has a lower
+ * asymptotic running time of O(N**1.464). This algorithm is
+ * only particularly useful on VERY large inputs
+ * (we're talking 1000s of digits here...).
+*/
+int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
+{
+ mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2;
+ int res, B;
+
+ /* init temps */
+ if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4,
+ &a0, &a1, &a2, &b0, &b1,
+ &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) {
+ return res;
+ }
+
+ /* B */
+ B = MIN(a->used, b->used) / 3;
+
+ /* a = a2 * B**2 + a1 * B + a0 */
+ if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_copy(a, &a1)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&a1, B);
+ mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
+
+ if ((res = mp_copy(a, &a2)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&a2, B*2);
+
+ /* b = b2 * B**2 + b1 * B + b0 */
+ if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_copy(b, &b1)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&b1, B);
+ mp_mod_2d(&b1, DIGIT_BIT * B, &b1);
+
+ if ((res = mp_copy(b, &b2)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&b2, B*2);
+
+ /* w0 = a0*b0 */
+ if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w4 = a2 * b2 */
+ if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */
+ if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */
+ if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+
+
+ /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */
+ if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* now solve the matrix
+
+ 0 0 0 0 1
+ 1 2 4 8 16
+ 1 1 1 1 1
+ 16 8 4 2 1
+ 1 0 0 0 0
+
+ using 12 subtractions, 4 shifts,
+ 2 small divisions and 1 small multiplication
+ */
+
+ /* r1 - r4 */
+ if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r0 */
+ if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1/2 */
+ if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3/2 */
+ if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r2 - r0 - r4 */
+ if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - r2 */
+ if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r2 */
+ if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - 8r0 */
+ if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - 8r4 */
+ if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* 3r2 - r1 - r3 */
+ if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - r2 */
+ if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r2 */
+ if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1/3 */
+ if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3/3 */
+ if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* at this point shift W[n] by B*n */
+ if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ERR:
+ mp_clear_multi(&w0, &w1, &w2, &w3, &w4,
+ &a0, &a1, &a2, &b0, &b1,
+ &b2, &tmp1, &tmp2, NULL);
+ return res;
+}
+
+#endif
+
+/* End: bn_mp_toom_mul.c */
+
+/* Start: bn_mp_toom_sqr.c */
+#include <tommath.h>
+#ifdef BN_MP_TOOM_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* squaring using Toom-Cook 3-way algorithm */
+int
+mp_toom_sqr(mp_int *a, mp_int *b)
+{
+ mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2;
+ int res, B;
+
+ /* init temps */
+ if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) {
+ return res;
+ }
+
+ /* B */
+ B = a->used / 3;
+
+ /* a = a2 * B**2 + a1 * B + a0 */
+ if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_copy(a, &a1)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&a1, B);
+ mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
+
+ if ((res = mp_copy(a, &a2)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&a2, B*2);
+
+ /* w0 = a0*a0 */
+ if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w4 = a2 * a2 */
+ if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w1 = (a2 + 2(a1 + 2a0))**2 */
+ if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w3 = (a0 + 2(a1 + 2a2))**2 */
+ if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+
+
+ /* w2 = (a2 + a1 + a0)**2 */
+ if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* now solve the matrix
+
+ 0 0 0 0 1
+ 1 2 4 8 16
+ 1 1 1 1 1
+ 16 8 4 2 1
+ 1 0 0 0 0
+
+ using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication.
+ */
+
+ /* r1 - r4 */
+ if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r0 */
+ if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1/2 */
+ if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3/2 */
+ if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r2 - r0 - r4 */
+ if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - r2 */
+ if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r2 */
+ if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - 8r0 */
+ if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - 8r4 */
+ if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* 3r2 - r1 - r3 */
+ if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - r2 */
+ if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r2 */
+ if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1/3 */
+ if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3/3 */
+ if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* at this point shift W[n] by B*n */
+ if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ERR:
+ mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL);
+ return res;
+}
+
+#endif
+
+/* End: bn_mp_toom_sqr.c */
+
+/* Start: bn_mp_toradix.c */
+#include <tommath.h>
+#ifdef BN_MP_TORADIX_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* stores a bignum as a ASCII string in a given radix (2..64) */
+int mp_toradix (mp_int * a, char *str, int radix)
+{
+ int res, digs;
+ mp_int t;
+ mp_digit d;
+ char *_s = str;
+
+ /* check range of the radix */
+ if (radix < 2 || radix > 64) {
+ return MP_VAL;
+ }
+
+ /* quick out if its zero */
+ if (mp_iszero(a) == 1) {
+ *str++ = '0';
+ *str = '\0';
+ return MP_OKAY;
+ }
+
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+
+ /* if it is negative output a - */
+ if (t.sign == MP_NEG) {
+ ++_s;
+ *str++ = '-';
+ t.sign = MP_ZPOS;
+ }
+
+ digs = 0;
+ while (mp_iszero (&t) == 0) {
+ if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ *str++ = mp_s_rmap[d];
+ ++digs;
+ }
+
+ /* reverse the digits of the string. In this case _s points
+ * to the first digit [exluding the sign] of the number]
+ */
+ bn_reverse ((unsigned char *)_s, digs);
+
+ /* append a NULL so the string is properly terminated */
+ *str = '\0';
+
+ mp_clear (&t);
+ return MP_OKAY;
+}
+
+#endif
+
+/* End: bn_mp_toradix.c */
+
+/* Start: bn_mp_toradix_n.c */
+#include <tommath.h>
+#ifdef BN_MP_TORADIX_N_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* stores a bignum as a ASCII string in a given radix (2..64)
+ *
+ * Stores upto maxlen-1 chars and always a NULL byte
+ */
+int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen)
+{
+ int res, digs;
+ mp_int t;
+ mp_digit d;
+ char *_s = str;
+
+ /* check range of the maxlen, radix */
+ if (maxlen < 2 || radix < 2 || radix > 64) {
+ return MP_VAL;
+ }
+
+ /* quick out if its zero */
+ if (mp_iszero(a) == MP_YES) {
+ *str++ = '0';
+ *str = '\0';
+ return MP_OKAY;
+ }
+
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+
+ /* if it is negative output a - */
+ if (t.sign == MP_NEG) {
+ /* we have to reverse our digits later... but not the - sign!! */
+ ++_s;
+
+ /* store the flag and mark the number as positive */
+ *str++ = '-';
+ t.sign = MP_ZPOS;
+
+ /* subtract a char */
+ --maxlen;
+ }
+
+ digs = 0;
+ while (mp_iszero (&t) == 0) {
+ if (--maxlen < 1) {
+ /* no more room */
+ break;
+ }
+ if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ *str++ = mp_s_rmap[d];
+ ++digs;
+ }
+
+ /* reverse the digits of the string. In this case _s points
+ * to the first digit [exluding the sign] of the number
+ */
+ bn_reverse ((unsigned char *)_s, digs);
+
+ /* append a NULL so the string is properly terminated */
+ *str = '\0';
+
+ mp_clear (&t);
+ return MP_OKAY;
+}
+
+#endif
+
+/* End: bn_mp_toradix_n.c */
+
+/* Start: bn_mp_unsigned_bin_size.c */
+#include <tommath.h>
+#ifdef BN_MP_UNSIGNED_BIN_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* get the size for an unsigned equivalent */
+int mp_unsigned_bin_size (mp_int * a)
+{
+ int size = mp_count_bits (a);
+ return (size / 8 + ((size & 7) != 0 ? 1 : 0));
+}
+#endif
+
+/* End: bn_mp_unsigned_bin_size.c */
+
+/* Start: bn_mp_xor.c */
+#include <tommath.h>
+#ifdef BN_MP_XOR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* XOR two ints together */
+int
+mp_xor (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res, ix, px;
+ mp_int t, *x;
+
+ if (a->used > b->used) {
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+ px = b->used;
+ x = b;
+ } else {
+ if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+ return res;
+ }
+ px = a->used;
+ x = a;
+ }
+
+ for (ix = 0; ix < px; ix++) {
+ t.dp[ix] ^= x->dp[ix];
+ }
+ mp_clamp (&t);
+ mp_exch (c, &t);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_xor.c */
+
+/* Start: bn_mp_zero.c */
+#include <tommath.h>
+#ifdef BN_MP_ZERO_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* set to zero */
+void mp_zero (mp_int * a)
+{
+ int n;
+ mp_digit *tmp;
+
+ a->sign = MP_ZPOS;
+ a->used = 0;
+
+ tmp = a->dp;
+ for (n = 0; n < a->alloc; n++) {
+ *tmp++ = 0;
+ }
+}
+#endif
+
+/* End: bn_mp_zero.c */
+
+/* Start: bn_prime_tab.c */
+#include <tommath.h>
+#ifdef BN_PRIME_TAB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+const mp_digit ltm_prime_tab[] = {
+ 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
+ 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
+ 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
+ 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
+#ifndef MP_8BIT
+ 0x0083,
+ 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
+ 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
+ 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
+ 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
+
+ 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
+ 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
+ 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
+ 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
+ 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
+ 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
+ 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
+ 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
+
+ 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
+ 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
+ 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
+ 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
+ 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
+ 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
+ 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
+ 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
+
+ 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
+ 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
+ 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
+ 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
+ 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
+ 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
+ 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
+ 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
+#endif
+};
+#endif
+
+/* End: bn_prime_tab.c */
+
+/* Start: bn_reverse.c */
+#include <tommath.h>
+#ifdef BN_REVERSE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* reverse an array, used for radix code */
+void
+bn_reverse (unsigned char *s, int len)
+{
+ int ix, iy;
+ unsigned char t;
+
+ ix = 0;
+ iy = len - 1;
+ while (ix < iy) {
+ t = s[ix];
+ s[ix] = s[iy];
+ s[iy] = t;
+ ++ix;
+ --iy;
+ }
+}
+#endif
+
+/* End: bn_reverse.c */
+
+/* Start: bn_s_mp_add.c */
+#include <tommath.h>
+#ifdef BN_S_MP_ADD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* low level addition, based on HAC pp.594, Algorithm 14.7 */
+int
+s_mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int *x;
+ int olduse, res, min, max;
+
+ /* find sizes, we let |a| <= |b| which means we have to sort
+ * them. "x" will point to the input with the most digits
+ */
+ if (a->used > b->used) {
+ min = b->used;
+ max = a->used;
+ x = a;
+ } else {
+ min = a->used;
+ max = b->used;
+ x = b;
+ }
+
+ /* init result */
+ if (c->alloc < max + 1) {
+ if ((res = mp_grow (c, max + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* get old used digit count and set new one */
+ olduse = c->used;
+ c->used = max + 1;
+
+ {
+ register mp_digit u, *tmpa, *tmpb, *tmpc;
+ register int i;
+
+ /* alias for digit pointers */
+
+ /* first input */
+ tmpa = a->dp;
+
+ /* second input */
+ tmpb = b->dp;
+
+ /* destination */
+ tmpc = c->dp;
+
+ /* zero the carry */
+ u = 0;
+ for (i = 0; i < min; i++) {
+ /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
+ *tmpc = *tmpa++ + *tmpb++ + u;
+
+ /* U = carry bit of T[i] */
+ u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+ /* take away carry bit from T[i] */
+ *tmpc++ &= MP_MASK;
+ }
+
+ /* now copy higher words if any, that is in A+B
+ * if A or B has more digits add those in
+ */
+ if (min != max) {
+ for (; i < max; i++) {
+ /* T[i] = X[i] + U */
+ *tmpc = x->dp[i] + u;
+
+ /* U = carry bit of T[i] */
+ u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+ /* take away carry bit from T[i] */
+ *tmpc++ &= MP_MASK;
+ }
+ }
+
+ /* add carry */
+ *tmpc++ = u;
+
+ /* clear digits above oldused */
+ for (i = c->used; i < olduse; i++) {
+ *tmpc++ = 0;
+ }
+ }
+
+ mp_clamp (c);
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_s_mp_add.c */
+
+/* Start: bn_s_mp_exptmod.c */
+#include <tommath.h>
+#ifdef BN_S_MP_EXPTMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+#ifdef MP_LOW_MEM
+ #define TAB_SIZE 32
+#else
+ #define TAB_SIZE 256
+#endif
+
+int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+ mp_int M[TAB_SIZE], res, mu;
+ mp_digit buf;
+ int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+ int (*redux)(mp_int*,mp_int*,mp_int*);
+
+ /* find window size */
+ x = mp_count_bits (X);
+ if (x <= 7) {
+ winsize = 2;
+ } else if (x <= 36) {
+ winsize = 3;
+ } else if (x <= 140) {
+ winsize = 4;
+ } else if (x <= 450) {
+ winsize = 5;
+ } else if (x <= 1303) {
+ winsize = 6;
+ } else if (x <= 3529) {
+ winsize = 7;
+ } else {
+ winsize = 8;
+ }
+
+#ifdef MP_LOW_MEM
+ if (winsize > 5) {
+ winsize = 5;
+ }
+#endif
+
+ /* init M array */
+ /* init first cell */
+ if ((err = mp_init(&M[1])) != MP_OKAY) {
+ return err;
+ }
+
+ /* now init the second half of the array */
+ for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+ if ((err = mp_init(&M[x])) != MP_OKAY) {
+ for (y = 1<<(winsize-1); y < x; y++) {
+ mp_clear (&M[y]);
+ }
+ mp_clear(&M[1]);
+ return err;
+ }
+ }
+
+ /* create mu, used for Barrett reduction */
+ if ((err = mp_init (&mu)) != MP_OKAY) {
+ goto LBL_M;
+ }
+
+ if (redmode == 0) {
+ if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ redux = mp_reduce;
+ } else {
+ if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ redux = mp_reduce_2k_l;
+ }
+
+ /* create M table
+ *
+ * The M table contains powers of the base,
+ * e.g. M[x] = G**x mod P
+ *
+ * The first half of the table is not
+ * computed though accept for M[0] and M[1]
+ */
+ if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {
+ goto LBL_MU;
+ }
+
+ /* compute the value at M[1<<(winsize-1)] by squaring
+ * M[1] (winsize-1) times
+ */
+ if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+ goto LBL_MU;
+ }
+
+ for (x = 0; x < (winsize - 1); x++) {
+ /* square it */
+ if ((err = mp_sqr (&M[1 << (winsize - 1)],
+ &M[1 << (winsize - 1)])) != MP_OKAY) {
+ goto LBL_MU;
+ }
+
+ /* reduce modulo P */
+ if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ }
+
+ /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
+ * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
+ */
+ for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+ if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ if ((err = redux (&M[x], P, &mu)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ }
+
+ /* setup result */
+ if ((err = mp_init (&res)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ mp_set (&res, 1);
+
+ /* set initial mode and bit cnt */
+ mode = 0;
+ bitcnt = 1;
+ buf = 0;
+ digidx = X->used - 1;
+ bitcpy = 0;
+ bitbuf = 0;
+
+ for (;;) {
+ /* grab next digit as required */
+ if (--bitcnt == 0) {
+ /* if digidx == -1 we are out of digits */
+ if (digidx == -1) {
+ break;
+ }
+ /* read next digit and reset the bitcnt */
+ buf = X->dp[digidx--];
+ bitcnt = (int) DIGIT_BIT;
+ }
+
+ /* grab the next msb from the exponent */
+ y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
+ buf <<= (mp_digit)1;
+
+ /* if the bit is zero and mode == 0 then we ignore it
+ * These represent the leading zero bits before the first 1 bit
+ * in the exponent. Technically this opt is not required but it
+ * does lower the # of trivial squaring/reductions used
+ */
+ if (mode == 0 && y == 0) {
+ continue;
+ }
+
+ /* if the bit is zero and mode == 1 then we square */
+ if (mode == 1 && y == 0) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ continue;
+ }
+
+ /* else we add it to the window */
+ bitbuf |= (y << (winsize - ++bitcpy));
+ mode = 2;
+
+ if (bitcpy == winsize) {
+ /* ok window is filled so square as required and multiply */
+ /* square first */
+ for (x = 0; x < winsize; x++) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* then multiply */
+ if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ /* empty window and reset */
+ bitcpy = 0;
+ bitbuf = 0;
+ mode = 1;
+ }
+ }
+
+ /* if bits remain then square/multiply */
+ if (mode == 2 && bitcpy > 0) {
+ /* square then multiply if the bit is set */
+ for (x = 0; x < bitcpy; x++) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ bitbuf <<= 1;
+ if ((bitbuf & (1 << winsize)) != 0) {
+ /* then multiply */
+ if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+ }
+ }
+
+ mp_exch (&res, Y);
+ err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_MU:mp_clear (&mu);
+LBL_M:
+ mp_clear(&M[1]);
+ for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+ mp_clear (&M[x]);
+ }
+ return err;
+}
+#endif
+
+/* End: bn_s_mp_exptmod.c */
+
+/* Start: bn_s_mp_mul_digs.c */
+#include <tommath.h>
+#ifdef BN_S_MP_MUL_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* multiplies |a| * |b| and only computes upto digs digits of result
+ * HAC pp. 595, Algorithm 14.12 Modified so you can control how
+ * many digits of output are created.
+ */
+int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+ mp_int t;
+ int res, pa, pb, ix, iy;
+ mp_digit u;
+ mp_word r;
+ mp_digit tmpx, *tmpt, *tmpy;
+
+ /* can we use the fast multiplier? */
+ if (((digs) < MP_WARRAY) &&
+ MIN (a->used, b->used) <
+ (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ return fast_s_mp_mul_digs (a, b, c, digs);
+ }
+
+ if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
+ return res;
+ }
+ t.used = digs;
+
+ /* compute the digits of the product directly */
+ pa = a->used;
+ for (ix = 0; ix < pa; ix++) {
+ /* set the carry to zero */
+ u = 0;
+
+ /* limit ourselves to making digs digits of output */
+ pb = MIN (b->used, digs - ix);
+
+ /* setup some aliases */
+ /* copy of the digit from a used within the nested loop */
+ tmpx = a->dp[ix];
+
+ /* an alias for the destination shifted ix places */
+ tmpt = t.dp + ix;
+
+ /* an alias for the digits of b */
+ tmpy = b->dp;
+
+ /* compute the columns of the output and propagate the carry */
+ for (iy = 0; iy < pb; iy++) {
+ /* compute the column as a mp_word */
+ r = ((mp_word)*tmpt) +
+ ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+ ((mp_word) u);
+
+ /* the new column is the lower part of the result */
+ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* get the carry word from the result */
+ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+ }
+ /* set carry if it is placed below digs */
+ if (ix + iy < digs) {
+ *tmpt = u;
+ }
+ }
+
+ mp_clamp (&t);
+ mp_exch (&t, c);
+
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_s_mp_mul_digs.c */
+
+/* Start: bn_s_mp_mul_high_digs.c */
+#include <tommath.h>
+#ifdef BN_S_MP_MUL_HIGH_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* multiplies |a| * |b| and does not compute the lower digs digits
+ * [meant to get the higher part of the product]
+ */
+int
+s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+ mp_int t;
+ int res, pa, pb, ix, iy;
+ mp_digit u;
+ mp_word r;
+ mp_digit tmpx, *tmpt, *tmpy;
+
+ /* can we use the fast multiplier? */
+#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
+ if (((a->used + b->used + 1) < MP_WARRAY)
+ && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ return fast_s_mp_mul_high_digs (a, b, c, digs);
+ }
+#endif
+
+ if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ t.used = a->used + b->used + 1;
+
+ pa = a->used;
+ pb = b->used;
+ for (ix = 0; ix < pa; ix++) {
+ /* clear the carry */
+ u = 0;
+
+ /* left hand side of A[ix] * B[iy] */
+ tmpx = a->dp[ix];
+
+ /* alias to the address of where the digits will be stored */
+ tmpt = &(t.dp[digs]);
+
+ /* alias for where to read the right hand side from */
+ tmpy = b->dp + (digs - ix);
+
+ for (iy = digs - ix; iy < pb; iy++) {
+ /* calculate the double precision result */
+ r = ((mp_word)*tmpt) +
+ ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+ ((mp_word) u);
+
+ /* get the lower part */
+ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* carry the carry */
+ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+ }
+ *tmpt = u;
+ }
+ mp_clamp (&t);
+ mp_exch (&t, c);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_s_mp_mul_high_digs.c */
+
+/* Start: bn_s_mp_sqr.c */
+#include <tommath.h>
+#ifdef BN_S_MP_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
+int s_mp_sqr (mp_int * a, mp_int * b)
+{
+ mp_int t;
+ int res, ix, iy, pa;
+ mp_word r;
+ mp_digit u, tmpx, *tmpt;
+
+ pa = a->used;
+ if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
+ return res;
+ }
+
+ /* default used is maximum possible size */
+ t.used = 2*pa + 1;
+
+ for (ix = 0; ix < pa; ix++) {
+ /* first calculate the digit at 2*ix */
+ /* calculate double precision result */
+ r = ((mp_word) t.dp[2*ix]) +
+ ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
+
+ /* store lower part in result */
+ t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* get the carry */
+ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+ /* left hand side of A[ix] * A[iy] */
+ tmpx = a->dp[ix];
+
+ /* alias for where to store the results */
+ tmpt = t.dp + (2*ix + 1);
+
+ for (iy = ix + 1; iy < pa; iy++) {
+ /* first calculate the product */
+ r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
+
+ /* now calculate the double precision result, note we use
+ * addition instead of *2 since it's easier to optimize
+ */
+ r = ((mp_word) *tmpt) + r + r + ((mp_word) u);
+
+ /* store lower part */
+ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* get carry */
+ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+ }
+ /* propagate upwards */
+ while (u != ((mp_digit) 0)) {
+ r = ((mp_word) *tmpt) + ((mp_word) u);
+ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+ }
+ }
+
+ mp_clamp (&t);
+ mp_exch (&t, b);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+#endif
+
+/* End: bn_s_mp_sqr.c */
+
+/* Start: bn_s_mp_sub.c */
+#include <tommath.h>
+#ifdef BN_S_MP_SUB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
+int
+s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+ int olduse, res, min, max;
+
+ /* find sizes */
+ min = b->used;
+ max = a->used;
+
+ /* init result */
+ if (c->alloc < max) {
+ if ((res = mp_grow (c, max)) != MP_OKAY) {
+ return res;
+ }
+ }
+ olduse = c->used;
+ c->used = max;
+
+ {
+ register mp_digit u, *tmpa, *tmpb, *tmpc;
+ register int i;
+
+ /* alias for digit pointers */
+ tmpa = a->dp;
+ tmpb = b->dp;
+ tmpc = c->dp;
+
+ /* set carry to zero */
+ u = 0;
+ for (i = 0; i < min; i++) {
+ /* T[i] = A[i] - B[i] - U */
+ *tmpc = *tmpa++ - *tmpb++ - u;
+
+ /* U = carry bit of T[i]
+ * Note this saves performing an AND operation since
+ * if a carry does occur it will propagate all the way to the
+ * MSB. As a result a single shift is enough to get the carry
+ */
+ u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+ /* Clear carry from T[i] */
+ *tmpc++ &= MP_MASK;
+ }
+
+ /* now copy higher words if any, e.g. if A has more digits than B */
+ for (; i < max; i++) {
+ /* T[i] = A[i] - U */
+ *tmpc = *tmpa++ - u;
+
+ /* U = carry bit of T[i] */
+ u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+ /* Clear carry from T[i] */
+ *tmpc++ &= MP_MASK;
+ }
+
+ /* clear digits above used (since we may not have grown result above) */
+ for (i = c->used; i < olduse; i++) {
+ *tmpc++ = 0;
+ }
+ }
+
+ mp_clamp (c);
+ return MP_OKAY;
+}
+
+#endif
+
+/* End: bn_s_mp_sub.c */
+
+/* Start: bncore.c */
+#include <tommath.h>
+#ifdef BNCORE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+
+/* Known optimal configurations
+
+ CPU /Compiler /MUL CUTOFF/SQR CUTOFF
+-------------------------------------------------------------
+ Intel P4 Northwood /GCC v3.4.1 / 88/ 128/LTM 0.32 ;-)
+ AMD Athlon64 /GCC v3.4.4 / 80/ 120/LTM 0.35
+
+*/
+
+int KARATSUBA_MUL_CUTOFF = 80, /* Min. number of digits before Karatsuba multiplication is used. */
+ KARATSUBA_SQR_CUTOFF = 120, /* Min. number of digits before Karatsuba squaring is used. */
+
+ TOOM_MUL_CUTOFF = 350, /* no optimal values of these are known yet so set em high */
+ TOOM_SQR_CUTOFF = 400;
+#endif
+
+/* End: bncore.c */
+
+
+/* EOF */
diff --git a/libtommath/pretty.build b/libtommath/pretty.build
new file mode 100644
index 0000000..a708b8a
--- /dev/null
+++ b/libtommath/pretty.build
@@ -0,0 +1,66 @@
+#!/bin/perl -w
+#
+# Cute little builder for perl
+# Total waste of development time...
+#
+# This will build all the object files and then the archive .a file
+# requires GCC, GNU make and a sense of humour.
+#
+# Tom St Denis
+use strict;
+
+my $count = 0;
+my $starttime = time;
+my $rate = 0;
+print "Scanning for source files...\n";
+foreach my $filename (glob "*.c") {
+ ++$count;
+}
+print "Source files to build: $count\nBuilding...\n";
+my $i = 0;
+my $lines = 0;
+my $filesbuilt = 0;
+foreach my $filename (glob "*.c") {
+ printf("Building %3.2f%%, ", (++$i/$count)*100.0);
+ if ($i % 4 == 0) { print "/, "; }
+ if ($i % 4 == 1) { print "-, "; }
+ if ($i % 4 == 2) { print "\\, "; }
+ if ($i % 4 == 3) { print "|, "; }
+ if ($rate > 0) {
+ my $tleft = ($count - $i) / $rate;
+ my $tsec = $tleft%60;
+ my $tmin = ($tleft/60)%60;
+ my $thour = ($tleft/3600)%60;
+ printf("%2d:%02d:%02d left, ", $thour, $tmin, $tsec);
+ }
+ my $cnt = ($i/$count)*30.0;
+ my $x = 0;
+ print "[";
+ for (; $x < $cnt; $x++) { print "#"; }
+ for (; $x < 30; $x++) { print " "; }
+ print "]\r";
+ my $tmp = $filename;
+ $tmp =~ s/\.c/".o"/ge;
+ if (open(SRC, "<$tmp")) {
+ close SRC;
+ } else {
+ !system("make $tmp > /dev/null 2>/dev/null") or die "\nERROR: Failed to make $tmp!!!\n";
+ open( SRC, "<$filename" ) or die "Couldn't open $filename for reading: $!";
+ ++$lines while (<SRC>);
+ close SRC or die "Error closing $filename after reading: $!";
+ ++$filesbuilt;
+ }
+
+ # update timer
+ if (time != $starttime) {
+ my $delay = time - $starttime;
+ $rate = $i/$delay;
+ }
+}
+
+# finish building the library
+printf("\nFinished building source (%d seconds, %3.2f files per second).\n", time - $starttime, $rate);
+print "Compiled approximately $filesbuilt files and $lines lines of code.\n";
+print "Doing final make (building archive...)\n";
+!system("make > /dev/null 2>/dev/null") or die "\nERROR: Failed to perform last make command!!!\n";
+print "done.\n"; \ No newline at end of file
diff --git a/libtommath/tombc/grammar.txt b/libtommath/tombc/grammar.txt
new file mode 100644
index 0000000..a780e75
--- /dev/null
+++ b/libtommath/tombc/grammar.txt
@@ -0,0 +1,35 @@
+program := program statement | statement | empty
+statement := { statement } |
+ identifier = numexpression; |
+ identifier[numexpression] = numexpression; |
+ function(expressionlist); |
+ for (identifer = numexpression; numexpression; identifier = numexpression) { statement } |
+ while (numexpression) { statement } |
+ if (numexpresion) { statement } elif |
+ break; |
+ continue;
+
+elif := else statement | empty
+function := abs | countbits | exptmod | jacobi | print | isprime | nextprime | issquare | readinteger | exit
+expressionlist := expressionlist, expression | expression
+
+// LR(1) !!!?
+expression := string | numexpression
+numexpression := cmpexpr && cmpexpr | cmpexpr \|\| cmpexpr | cmpexpr
+cmpexpr := boolexpr < boolexpr | boolexpr > boolexpr | boolexpr == boolexpr |
+ boolexpr <= boolexpr | boolexpr >= boolexpr | boolexpr
+boolexpr := shiftexpr & shiftexpr | shiftexpr ^ shiftexpr | shiftexpr \| shiftexpr | shiftexpr
+shiftexpr := addsubexpr << addsubexpr | addsubexpr >> addsubexpr | addsubexpr
+addsubexpr := mulexpr + mulexpr | mulexpr - mulexpr | mulexpr
+mulexpr := expr * expr | expr / expr | expr % expr | expr
+expr := -nexpr | nexpr
+nexpr := integer | identifier | ( numexpression ) | identifier[numexpression]
+
+identifier := identifer digits | identifier alpha | alpha
+alpha := a ... z | A ... Z
+integer := hexnumber | digits
+hexnumber := 0xhexdigits
+hexdigits := hexdigits hexdigit | hexdigit
+hexdigit := 0 ... 9 | a ... f | A ... F
+digits := digits digit | digit
+digit := 0 ... 9
diff --git a/libtommath/tommath.h b/libtommath/tommath.h
new file mode 100644
index 0000000..b706576
--- /dev/null
+++ b/libtommath/tommath.h
@@ -0,0 +1,579 @@
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+#ifndef BN_H_
+#define BN_H_
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+
+#include <tommath_class.h>
+
+#ifndef MIN
+ #define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+
+#ifndef MAX
+ #define MAX(x,y) ((x)>(y)?(x):(y))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+
+/* C++ compilers don't like assigning void * to mp_digit * */
+#define OPT_CAST(x) (x *)
+
+#else
+
+/* C on the other hand doesn't care */
+#define OPT_CAST(x)
+
+#endif
+
+
+/* detect 64-bit mode if possible */
+#if defined(__x86_64__)
+ #if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT))
+ #define MP_64BIT
+ #endif
+#endif
+
+/* some default configurations.
+ *
+ * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits
+ * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits
+ *
+ * At the very least a mp_digit must be able to hold 7 bits
+ * [any size beyond that is ok provided it doesn't overflow the data type]
+ */
+#ifdef MP_8BIT
+ typedef unsigned char mp_digit;
+ typedef unsigned short mp_word;
+#elif defined(MP_16BIT)
+ typedef unsigned short mp_digit;
+ typedef unsigned long mp_word;
+#elif defined(MP_64BIT)
+ /* for GCC only on supported platforms */
+#ifndef CRYPT
+ typedef unsigned long long ulong64;
+ typedef signed long long long64;
+#endif
+
+ typedef unsigned long mp_digit;
+ typedef unsigned long mp_word __attribute__ ((mode(TI)));
+
+ #define DIGIT_BIT 60
+#else
+ /* this is the default case, 28-bit digits */
+
+ /* this is to make porting into LibTomCrypt easier :-) */
+#ifndef CRYPT
+ #if defined(_MSC_VER) || defined(__BORLANDC__)
+ typedef unsigned __int64 ulong64;
+ typedef signed __int64 long64;
+ #else
+ typedef unsigned long long ulong64;
+ typedef signed long long long64;
+ #endif
+#endif
+
+ typedef unsigned long mp_digit;
+ typedef ulong64 mp_word;
+
+#ifdef MP_31BIT
+ /* this is an extension that uses 31-bit digits */
+ #define DIGIT_BIT 31
+#else
+ /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */
+ #define DIGIT_BIT 28
+ #define MP_28BIT
+#endif
+#endif
+
+/* define heap macros */
+#ifndef CRYPT
+ /* default to libc stuff */
+ #ifndef XMALLOC
+ #define XMALLOC malloc
+ #define XFREE free
+ #define XREALLOC realloc
+ #define XCALLOC calloc
+ #else
+ /* prototypes for our heap functions */
+ extern void *XMALLOC(size_t n);
+ extern void *XREALLOC(void *p, size_t n);
+ extern void *XCALLOC(size_t n, size_t s);
+ extern void XFREE(void *p);
+ #endif
+#endif
+
+
+/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */
+#ifndef DIGIT_BIT
+ #define DIGIT_BIT ((int)((CHAR_BIT * sizeof(mp_digit) - 1))) /* bits per digit */
+#endif
+
+#define MP_DIGIT_BIT DIGIT_BIT
+#define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
+#define MP_DIGIT_MAX MP_MASK
+
+/* equalities */
+#define MP_LT -1 /* less than */
+#define MP_EQ 0 /* equal to */
+#define MP_GT 1 /* greater than */
+
+#define MP_ZPOS 0 /* positive integer */
+#define MP_NEG 1 /* negative */
+
+#define MP_OKAY 0 /* ok result */
+#define MP_MEM -2 /* out of mem */
+#define MP_VAL -3 /* invalid input */
+#define MP_RANGE MP_VAL
+
+#define MP_YES 1 /* yes response */
+#define MP_NO 0 /* no response */
+
+/* Primality generation flags */
+#define LTM_PRIME_BBS 0x0001 /* BBS style prime */
+#define LTM_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */
+#define LTM_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */
+
+typedef int mp_err;
+
+/* you'll have to tune these... */
+extern int KARATSUBA_MUL_CUTOFF,
+ KARATSUBA_SQR_CUTOFF,
+ TOOM_MUL_CUTOFF,
+ TOOM_SQR_CUTOFF;
+
+/* define this to use lower memory usage routines (exptmods mostly) */
+/* #define MP_LOW_MEM */
+
+/* default precision */
+#ifndef MP_PREC
+ #ifndef MP_LOW_MEM
+ #define MP_PREC 32 /* default digits of precision */
+ #else
+ #define MP_PREC 8 /* default digits of precision */
+ #endif
+#endif
+
+/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
+#define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))
+
+/* the infamous mp_int structure */
+typedef struct {
+ int used, alloc, sign;
+ mp_digit *dp;
+} mp_int;
+
+/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
+typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);
+
+
+#define USED(m) ((m)->used)
+#define DIGIT(m,k) ((m)->dp[(k)])
+#define SIGN(m) ((m)->sign)
+
+/* error code to char* string */
+char *mp_error_to_string(int code);
+
+/* ---> init and deinit bignum functions <--- */
+/* init a bignum */
+int mp_init(mp_int *a);
+
+/* free a bignum */
+void mp_clear(mp_int *a);
+
+/* init a null terminated series of arguments */
+int mp_init_multi(mp_int *mp, ...);
+
+/* clear a null terminated series of arguments */
+void mp_clear_multi(mp_int *mp, ...);
+
+/* exchange two ints */
+void mp_exch(mp_int *a, mp_int *b);
+
+/* shrink ram required for a bignum */
+int mp_shrink(mp_int *a);
+
+/* grow an int to a given size */
+int mp_grow(mp_int *a, int size);
+
+/* init to a given number of digits */
+int mp_init_size(mp_int *a, int size);
+
+/* ---> Basic Manipulations <--- */
+#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
+#define mp_iseven(a) (((a)->used == 0 || (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
+#define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
+
+/* set to zero */
+void mp_zero(mp_int *a);
+
+/* set to a digit */
+void mp_set(mp_int *a, mp_digit b);
+
+/* set a 32-bit const */
+int mp_set_int(mp_int *a, unsigned long b);
+
+/* get a 32-bit value */
+unsigned long mp_get_int(mp_int * a);
+
+/* initialize and set a digit */
+int mp_init_set (mp_int * a, mp_digit b);
+
+/* initialize and set 32-bit value */
+int mp_init_set_int (mp_int * a, unsigned long b);
+
+/* copy, b = a */
+int mp_copy(mp_int *a, mp_int *b);
+
+/* inits and copies, a = b */
+int mp_init_copy(mp_int *a, mp_int *b);
+
+/* trim unused digits */
+void mp_clamp(mp_int *a);
+
+/* ---> digit manipulation <--- */
+
+/* right shift by "b" digits */
+void mp_rshd(mp_int *a, int b);
+
+/* left shift by "b" digits */
+int mp_lshd(mp_int *a, int b);
+
+/* c = a / 2**b */
+int mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d);
+
+/* b = a/2 */
+int mp_div_2(mp_int *a, mp_int *b);
+
+/* c = a * 2**b */
+int mp_mul_2d(mp_int *a, int b, mp_int *c);
+
+/* b = a*2 */
+int mp_mul_2(mp_int *a, mp_int *b);
+
+/* c = a mod 2**d */
+int mp_mod_2d(mp_int *a, int b, mp_int *c);
+
+/* computes a = 2**b */
+int mp_2expt(mp_int *a, int b);
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+int mp_cnt_lsb(mp_int *a);
+
+/* I Love Earth! */
+
+/* makes a pseudo-random int of a given size */
+int mp_rand(mp_int *a, int digits);
+
+/* ---> binary operations <--- */
+/* c = a XOR b */
+int mp_xor(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a OR b */
+int mp_or(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a AND b */
+int mp_and(mp_int *a, mp_int *b, mp_int *c);
+
+/* ---> Basic arithmetic <--- */
+
+/* b = -a */
+int mp_neg(mp_int *a, mp_int *b);
+
+/* b = |a| */
+int mp_abs(mp_int *a, mp_int *b);
+
+/* compare a to b */
+int mp_cmp(mp_int *a, mp_int *b);
+
+/* compare |a| to |b| */
+int mp_cmp_mag(mp_int *a, mp_int *b);
+
+/* c = a + b */
+int mp_add(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a - b */
+int mp_sub(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a * b */
+int mp_mul(mp_int *a, mp_int *b, mp_int *c);
+
+/* b = a*a */
+int mp_sqr(mp_int *a, mp_int *b);
+
+/* a/b => cb + d == a */
+int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* c = a mod b, 0 <= c < b */
+int mp_mod(mp_int *a, mp_int *b, mp_int *c);
+
+/* ---> single digit functions <--- */
+
+/* compare against a single digit */
+int mp_cmp_d(mp_int *a, mp_digit b);
+
+/* c = a + b */
+int mp_add_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a - b */
+int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a * b */
+int mp_mul_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* a/b => cb + d == a */
+int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d);
+
+/* a/3 => 3c + d == a */
+int mp_div_3(mp_int *a, mp_int *c, mp_digit *d);
+
+/* c = a**b */
+int mp_expt_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a mod b, 0 <= c < b */
+int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c);
+
+/* ---> number theory <--- */
+
+/* d = a + b (mod c) */
+int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* d = a - b (mod c) */
+int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* d = a * b (mod c) */
+int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* c = a * a (mod b) */
+int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = 1/a (mod b) */
+int mp_invmod(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = (a, b) */
+int mp_gcd(mp_int *a, mp_int *b, mp_int *c);
+
+/* produces value such that U1*a + U2*b = U3 */
+int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3);
+
+/* c = [a, b] or (a*b)/(a, b) */
+int mp_lcm(mp_int *a, mp_int *b, mp_int *c);
+
+/* finds one of the b'th root of a, such that |c|**b <= |a|
+ *
+ * returns error if a < 0 and b is even
+ */
+int mp_n_root(mp_int *a, mp_digit b, mp_int *c);
+
+/* special sqrt algo */
+int mp_sqrt(mp_int *arg, mp_int *ret);
+
+/* is number a square? */
+int mp_is_square(mp_int *arg, int *ret);
+
+/* computes the jacobi c = (a | n) (or Legendre if b is prime) */
+int mp_jacobi(mp_int *a, mp_int *n, int *c);
+
+/* used to setup the Barrett reduction for a given modulus b */
+int mp_reduce_setup(mp_int *a, mp_int *b);
+
+/* Barrett Reduction, computes a (mod b) with a precomputed value c
+ *
+ * Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely
+ * compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code].
+ */
+int mp_reduce(mp_int *a, mp_int *b, mp_int *c);
+
+/* setups the montgomery reduction */
+int mp_montgomery_setup(mp_int *a, mp_digit *mp);
+
+/* computes a = B**n mod b without division or multiplication useful for
+ * normalizing numbers in a Montgomery system.
+ */
+int mp_montgomery_calc_normalization(mp_int *a, mp_int *b);
+
+/* computes x/R == x (mod N) via Montgomery Reduction */
+int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
+
+/* returns 1 if a is a valid DR modulus */
+int mp_dr_is_modulus(mp_int *a);
+
+/* sets the value of "d" required for mp_dr_reduce */
+void mp_dr_setup(mp_int *a, mp_digit *d);
+
+/* reduces a modulo b using the Diminished Radix method */
+int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp);
+
+/* returns true if a can be reduced with mp_reduce_2k */
+int mp_reduce_is_2k(mp_int *a);
+
+/* determines k value for 2k reduction */
+int mp_reduce_2k_setup(mp_int *a, mp_digit *d);
+
+/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
+int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);
+
+/* returns true if a can be reduced with mp_reduce_2k_l */
+int mp_reduce_is_2k_l(mp_int *a);
+
+/* determines k value for 2k reduction */
+int mp_reduce_2k_setup_l(mp_int *a, mp_int *d);
+
+/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
+int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d);
+
+/* d = a**b (mod c) */
+int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* ---> Primes <--- */
+
+/* number of primes */
+#ifdef MP_8BIT
+ #define PRIME_SIZE 31
+#else
+ #define PRIME_SIZE 256
+#endif
+
+/* table of first PRIME_SIZE primes */
+extern const mp_digit ltm_prime_tab[];
+
+/* result=1 if a is divisible by one of the first PRIME_SIZE primes */
+int mp_prime_is_divisible(mp_int *a, int *result);
+
+/* performs one Fermat test of "a" using base "b".
+ * Sets result to 0 if composite or 1 if probable prime
+ */
+int mp_prime_fermat(mp_int *a, mp_int *b, int *result);
+
+/* performs one Miller-Rabin test of "a" using base "b".
+ * Sets result to 0 if composite or 1 if probable prime
+ */
+int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result);
+
+/* This gives [for a given bit size] the number of trials required
+ * such that Miller-Rabin gives a prob of failure lower than 2^-96
+ */
+int mp_prime_rabin_miller_trials(int size);
+
+/* performs t rounds of Miller-Rabin on "a" using the first
+ * t prime bases. Also performs an initial sieve of trial
+ * division. Determines if "a" is prime with probability
+ * of error no more than (1/4)**t.
+ *
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+int mp_prime_is_prime(mp_int *a, int t, int *result);
+
+/* finds the next prime after the number "a" using "t" trials
+ * of Miller-Rabin.
+ *
+ * bbs_style = 1 means the prime must be congruent to 3 mod 4
+ */
+int mp_prime_next_prime(mp_int *a, int t, int bbs_style);
+
+/* makes a truly random prime of a given size (bytes),
+ * call with bbs = 1 if you want it to be congruent to 3 mod 4
+ *
+ * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ * The prime generated will be larger than 2^(8*size).
+ */
+#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)
+
+/* makes a truly random prime of a given size (bits),
+ *
+ * Flags are as follows:
+ *
+ * LTM_PRIME_BBS - make prime congruent to 3 mod 4
+ * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
+ * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
+ * LTM_PRIME_2MSB_ON - make the 2nd highest bit one
+ *
+ * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ */
+int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat);
+
+/* ---> radix conversion <--- */
+int mp_count_bits(mp_int *a);
+
+int mp_unsigned_bin_size(mp_int *a);
+int mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c);
+int mp_to_unsigned_bin(mp_int *a, unsigned char *b);
+int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen);
+
+int mp_signed_bin_size(mp_int *a);
+int mp_read_signed_bin(mp_int *a, const unsigned char *b, int c);
+int mp_to_signed_bin(mp_int *a, unsigned char *b);
+int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen);
+
+int mp_read_radix(mp_int *a, const char *str, int radix);
+int mp_toradix(mp_int *a, char *str, int radix);
+int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen);
+int mp_radix_size(mp_int *a, int radix, int *size);
+
+int mp_fread(mp_int *a, int radix, FILE *stream);
+int mp_fwrite(mp_int *a, int radix, FILE *stream);
+
+#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
+#define mp_raw_size(mp) mp_signed_bin_size(mp)
+#define mp_toraw(mp, str) mp_to_signed_bin((mp), (str))
+#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
+#define mp_mag_size(mp) mp_unsigned_bin_size(mp)
+#define mp_tomag(mp, str) mp_to_unsigned_bin((mp), (str))
+
+#define mp_tobinary(M, S) mp_toradix((M), (S), 2)
+#define mp_tooctal(M, S) mp_toradix((M), (S), 8)
+#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
+#define mp_tohex(M, S) mp_toradix((M), (S), 16)
+
+/* lowlevel functions, do not call! */
+int s_mp_add(mp_int *a, mp_int *b, mp_int *c);
+int s_mp_sub(mp_int *a, mp_int *b, mp_int *c);
+#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)
+int fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int fast_s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int fast_s_mp_sqr(mp_int *a, mp_int *b);
+int s_mp_sqr(mp_int *a, mp_int *b);
+int mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c);
+int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c);
+int mp_karatsuba_sqr(mp_int *a, mp_int *b);
+int mp_toom_sqr(mp_int *a, mp_int *b);
+int fast_mp_invmod(mp_int *a, mp_int *b, mp_int *c);
+int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c);
+int fast_mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
+int mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int mode);
+int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int mode);
+void bn_reverse(unsigned char *s, int len);
+
+extern const char *mp_s_rmap;
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff --git a/libtommath/tommath.out b/libtommath/tommath.out
new file mode 100644
index 0000000..9f62617
--- /dev/null
+++ b/libtommath/tommath.out
@@ -0,0 +1,139 @@
+\BOOKMARK [0][-]{chapter.1}{Introduction}{}
+\BOOKMARK [1][-]{section.1.1}{Multiple Precision Arithmetic}{chapter.1}
+\BOOKMARK [2][-]{subsection.1.1.1}{What is Multiple Precision Arithmetic?}{section.1.1}
+\BOOKMARK [2][-]{subsection.1.1.2}{The Need for Multiple Precision Arithmetic}{section.1.1}
+\BOOKMARK [2][-]{subsection.1.1.3}{Benefits of Multiple Precision Arithmetic}{section.1.1}
+\BOOKMARK [1][-]{section.1.2}{Purpose of This Text}{chapter.1}
+\BOOKMARK [1][-]{section.1.3}{Discussion and Notation}{chapter.1}
+\BOOKMARK [2][-]{subsection.1.3.1}{Notation}{section.1.3}
+\BOOKMARK [2][-]{subsection.1.3.2}{Precision Notation}{section.1.3}
+\BOOKMARK [2][-]{subsection.1.3.3}{Algorithm Inputs and Outputs}{section.1.3}
+\BOOKMARK [2][-]{subsection.1.3.4}{Mathematical Expressions}{section.1.3}
+\BOOKMARK [2][-]{subsection.1.3.5}{Work Effort}{section.1.3}
+\BOOKMARK [1][-]{section.1.4}{Exercises}{chapter.1}
+\BOOKMARK [1][-]{section.1.5}{Introduction to LibTomMath}{chapter.1}
+\BOOKMARK [2][-]{subsection.1.5.1}{What is LibTomMath?}{section.1.5}
+\BOOKMARK [2][-]{subsection.1.5.2}{Goals of LibTomMath}{section.1.5}
+\BOOKMARK [1][-]{section.1.6}{Choice of LibTomMath}{chapter.1}
+\BOOKMARK [2][-]{subsection.1.6.1}{Code Base}{section.1.6}
+\BOOKMARK [2][-]{subsection.1.6.2}{API Simplicity}{section.1.6}
+\BOOKMARK [2][-]{subsection.1.6.3}{Optimizations}{section.1.6}
+\BOOKMARK [2][-]{subsection.1.6.4}{Portability and Stability}{section.1.6}
+\BOOKMARK [2][-]{subsection.1.6.5}{Choice}{section.1.6}
+\BOOKMARK [0][-]{chapter.2}{Getting Started}{}
+\BOOKMARK [1][-]{section.2.1}{Library Basics}{chapter.2}
+\BOOKMARK [1][-]{section.2.2}{What is a Multiple Precision Integer?}{chapter.2}
+\BOOKMARK [2][-]{subsection.2.2.1}{The mp\137int Structure}{section.2.2}
+\BOOKMARK [1][-]{section.2.3}{Argument Passing}{chapter.2}
+\BOOKMARK [1][-]{section.2.4}{Return Values}{chapter.2}
+\BOOKMARK [1][-]{section.2.5}{Initialization and Clearing}{chapter.2}
+\BOOKMARK [2][-]{subsection.2.5.1}{Initializing an mp\137int}{section.2.5}
+\BOOKMARK [2][-]{subsection.2.5.2}{Clearing an mp\137int}{section.2.5}
+\BOOKMARK [1][-]{section.2.6}{Maintenance Algorithms}{chapter.2}
+\BOOKMARK [2][-]{subsection.2.6.1}{Augmenting an mp\137int's Precision}{section.2.6}
+\BOOKMARK [2][-]{subsection.2.6.2}{Initializing Variable Precision mp\137ints}{section.2.6}
+\BOOKMARK [2][-]{subsection.2.6.3}{Multiple Integer Initializations and Clearings}{section.2.6}
+\BOOKMARK [2][-]{subsection.2.6.4}{Clamping Excess Digits}{section.2.6}
+\BOOKMARK [0][-]{chapter.3}{Basic Operations}{}
+\BOOKMARK [1][-]{section.3.1}{Introduction}{chapter.3}
+\BOOKMARK [1][-]{section.3.2}{Assigning Values to mp\137int Structures}{chapter.3}
+\BOOKMARK [2][-]{subsection.3.2.1}{Copying an mp\137int}{section.3.2}
+\BOOKMARK [2][-]{subsection.3.2.2}{Creating a Clone}{section.3.2}
+\BOOKMARK [1][-]{section.3.3}{Zeroing an Integer}{chapter.3}
+\BOOKMARK [1][-]{section.3.4}{Sign Manipulation}{chapter.3}
+\BOOKMARK [2][-]{subsection.3.4.1}{Absolute Value}{section.3.4}
+\BOOKMARK [2][-]{subsection.3.4.2}{Integer Negation}{section.3.4}
+\BOOKMARK [1][-]{section.3.5}{Small Constants}{chapter.3}
+\BOOKMARK [2][-]{subsection.3.5.1}{Setting Small Constants}{section.3.5}
+\BOOKMARK [2][-]{subsection.3.5.2}{Setting Large Constants}{section.3.5}
+\BOOKMARK [1][-]{section.3.6}{Comparisons}{chapter.3}
+\BOOKMARK [2][-]{subsection.3.6.1}{Unsigned Comparisions}{section.3.6}
+\BOOKMARK [2][-]{subsection.3.6.2}{Signed Comparisons}{section.3.6}
+\BOOKMARK [0][-]{chapter.4}{Basic Arithmetic}{}
+\BOOKMARK [1][-]{section.4.1}{Introduction}{chapter.4}
+\BOOKMARK [1][-]{section.4.2}{Addition and Subtraction}{chapter.4}
+\BOOKMARK [2][-]{subsection.4.2.1}{Low Level Addition}{section.4.2}
+\BOOKMARK [2][-]{subsection.4.2.2}{Low Level Subtraction}{section.4.2}
+\BOOKMARK [2][-]{subsection.4.2.3}{High Level Addition}{section.4.2}
+\BOOKMARK [2][-]{subsection.4.2.4}{High Level Subtraction}{section.4.2}
+\BOOKMARK [1][-]{section.4.3}{Bit and Digit Shifting}{chapter.4}
+\BOOKMARK [2][-]{subsection.4.3.1}{Multiplication by Two}{section.4.3}
+\BOOKMARK [2][-]{subsection.4.3.2}{Division by Two}{section.4.3}
+\BOOKMARK [1][-]{section.4.4}{Polynomial Basis Operations}{chapter.4}
+\BOOKMARK [2][-]{subsection.4.4.1}{Multiplication by x}{section.4.4}
+\BOOKMARK [2][-]{subsection.4.4.2}{Division by x}{section.4.4}
+\BOOKMARK [1][-]{section.4.5}{Powers of Two}{chapter.4}
+\BOOKMARK [2][-]{subsection.4.5.1}{Multiplication by Power of Two}{section.4.5}
+\BOOKMARK [2][-]{subsection.4.5.2}{Division by Power of Two}{section.4.5}
+\BOOKMARK [2][-]{subsection.4.5.3}{Remainder of Division by Power of Two}{section.4.5}
+\BOOKMARK [0][-]{chapter.5}{Multiplication and Squaring}{}
+\BOOKMARK [1][-]{section.5.1}{The Multipliers}{chapter.5}
+\BOOKMARK [1][-]{section.5.2}{Multiplication}{chapter.5}
+\BOOKMARK [2][-]{subsection.5.2.1}{The Baseline Multiplication}{section.5.2}
+\BOOKMARK [2][-]{subsection.5.2.2}{Faster Multiplication by the ``Comba'' Method}{section.5.2}
+\BOOKMARK [2][-]{subsection.5.2.3}{Polynomial Basis Multiplication}{section.5.2}
+\BOOKMARK [2][-]{subsection.5.2.4}{Karatsuba Multiplication}{section.5.2}
+\BOOKMARK [2][-]{subsection.5.2.5}{Toom-Cook 3-Way Multiplication}{section.5.2}
+\BOOKMARK [2][-]{subsection.5.2.6}{Signed Multiplication}{section.5.2}
+\BOOKMARK [1][-]{section.5.3}{Squaring}{chapter.5}
+\BOOKMARK [2][-]{subsection.5.3.1}{The Baseline Squaring Algorithm}{section.5.3}
+\BOOKMARK [2][-]{subsection.5.3.2}{Faster Squaring by the ``Comba'' Method}{section.5.3}
+\BOOKMARK [2][-]{subsection.5.3.3}{Polynomial Basis Squaring}{section.5.3}
+\BOOKMARK [2][-]{subsection.5.3.4}{Karatsuba Squaring}{section.5.3}
+\BOOKMARK [2][-]{subsection.5.3.5}{Toom-Cook Squaring}{section.5.3}
+\BOOKMARK [2][-]{subsection.5.3.6}{High Level Squaring}{section.5.3}
+\BOOKMARK [0][-]{chapter.6}{Modular Reduction}{}
+\BOOKMARK [1][-]{section.6.1}{Basics of Modular Reduction}{chapter.6}
+\BOOKMARK [1][-]{section.6.2}{The Barrett Reduction}{chapter.6}
+\BOOKMARK [2][-]{subsection.6.2.1}{Fixed Point Arithmetic}{section.6.2}
+\BOOKMARK [2][-]{subsection.6.2.2}{Choosing a Radix Point}{section.6.2}
+\BOOKMARK [2][-]{subsection.6.2.3}{Trimming the Quotient}{section.6.2}
+\BOOKMARK [2][-]{subsection.6.2.4}{Trimming the Residue}{section.6.2}
+\BOOKMARK [2][-]{subsection.6.2.5}{The Barrett Algorithm}{section.6.2}
+\BOOKMARK [2][-]{subsection.6.2.6}{The Barrett Setup Algorithm}{section.6.2}
+\BOOKMARK [1][-]{section.6.3}{The Montgomery Reduction}{chapter.6}
+\BOOKMARK [2][-]{subsection.6.3.1}{Digit Based Montgomery Reduction}{section.6.3}
+\BOOKMARK [2][-]{subsection.6.3.2}{Baseline Montgomery Reduction}{section.6.3}
+\BOOKMARK [2][-]{subsection.6.3.3}{Faster ``Comba'' Montgomery Reduction}{section.6.3}
+\BOOKMARK [2][-]{subsection.6.3.4}{Montgomery Setup}{section.6.3}
+\BOOKMARK [1][-]{section.6.4}{The Diminished Radix Algorithm}{chapter.6}
+\BOOKMARK [2][-]{subsection.6.4.1}{Choice of Moduli}{section.6.4}
+\BOOKMARK [2][-]{subsection.6.4.2}{Choice of k}{section.6.4}
+\BOOKMARK [2][-]{subsection.6.4.3}{Restricted Diminished Radix Reduction}{section.6.4}
+\BOOKMARK [2][-]{subsection.6.4.4}{Unrestricted Diminished Radix Reduction}{section.6.4}
+\BOOKMARK [1][-]{section.6.5}{Algorithm Comparison}{chapter.6}
+\BOOKMARK [0][-]{chapter.7}{Exponentiation}{}
+\BOOKMARK [1][-]{section.7.1}{Exponentiation Basics}{chapter.7}
+\BOOKMARK [2][-]{subsection.7.1.1}{Single Digit Exponentiation}{section.7.1}
+\BOOKMARK [1][-]{section.7.2}{k-ary Exponentiation}{chapter.7}
+\BOOKMARK [2][-]{subsection.7.2.1}{Optimal Values of k}{section.7.2}
+\BOOKMARK [2][-]{subsection.7.2.2}{Sliding-Window Exponentiation}{section.7.2}
+\BOOKMARK [1][-]{section.7.3}{Modular Exponentiation}{chapter.7}
+\BOOKMARK [2][-]{subsection.7.3.1}{Barrett Modular Exponentiation}{section.7.3}
+\BOOKMARK [1][-]{section.7.4}{Quick Power of Two}{chapter.7}
+\BOOKMARK [0][-]{chapter.8}{Higher Level Algorithms}{}
+\BOOKMARK [1][-]{section.8.1}{Integer Division with Remainder}{chapter.8}
+\BOOKMARK [2][-]{subsection.8.1.1}{Quotient Estimation}{section.8.1}
+\BOOKMARK [2][-]{subsection.8.1.2}{Normalized Integers}{section.8.1}
+\BOOKMARK [2][-]{subsection.8.1.3}{Radix- Division with Remainder}{section.8.1}
+\BOOKMARK [1][-]{section.8.2}{Single Digit Helpers}{chapter.8}
+\BOOKMARK [2][-]{subsection.8.2.1}{Single Digit Addition and Subtraction}{section.8.2}
+\BOOKMARK [2][-]{subsection.8.2.2}{Single Digit Multiplication}{section.8.2}
+\BOOKMARK [2][-]{subsection.8.2.3}{Single Digit Division}{section.8.2}
+\BOOKMARK [2][-]{subsection.8.2.4}{Single Digit Root Extraction}{section.8.2}
+\BOOKMARK [1][-]{section.8.3}{Random Number Generation}{chapter.8}
+\BOOKMARK [1][-]{section.8.4}{Formatted Representations}{chapter.8}
+\BOOKMARK [2][-]{subsection.8.4.1}{Reading Radix-n Input}{section.8.4}
+\BOOKMARK [2][-]{subsection.8.4.2}{Generating Radix-n Output}{section.8.4}
+\BOOKMARK [0][-]{chapter.9}{Number Theoretic Algorithms}{}
+\BOOKMARK [1][-]{section.9.1}{Greatest Common Divisor}{chapter.9}
+\BOOKMARK [2][-]{subsection.9.1.1}{Complete Greatest Common Divisor}{section.9.1}
+\BOOKMARK [1][-]{section.9.2}{Least Common Multiple}{chapter.9}
+\BOOKMARK [1][-]{section.9.3}{Jacobi Symbol Computation}{chapter.9}
+\BOOKMARK [2][-]{subsection.9.3.1}{Jacobi Symbol}{section.9.3}
+\BOOKMARK [1][-]{section.9.4}{Modular Inverse}{chapter.9}
+\BOOKMARK [2][-]{subsection.9.4.1}{General Case}{section.9.4}
+\BOOKMARK [1][-]{section.9.5}{Primality Tests}{chapter.9}
+\BOOKMARK [2][-]{subsection.9.5.1}{Trial Division}{section.9.5}
+\BOOKMARK [2][-]{subsection.9.5.2}{The Fermat Test}{section.9.5}
+\BOOKMARK [2][-]{subsection.9.5.3}{The Miller-Rabin Test}{section.9.5}
diff --git a/libtommath/tommath.pdf b/libtommath/tommath.pdf
new file mode 100644
index 0000000..c9571d8
--- /dev/null
+++ b/libtommath/tommath.pdf
Binary files differ
diff --git a/libtommath/tommath.src b/libtommath/tommath.src
new file mode 100644
index 0000000..4065822
--- /dev/null
+++ b/libtommath/tommath.src
@@ -0,0 +1,6350 @@
+\documentclass[b5paper]{book}
+\usepackage{hyperref}
+\usepackage{makeidx}
+\usepackage{amssymb}
+\usepackage{color}
+\usepackage{alltt}
+\usepackage{graphicx}
+\usepackage{layout}
+\def\union{\cup}
+\def\intersect{\cap}
+\def\getsrandom{\stackrel{\rm R}{\gets}}
+\def\cross{\times}
+\def\cat{\hspace{0.5em} \| \hspace{0.5em}}
+\def\catn{$\|$}
+\def\divides{\hspace{0.3em} | \hspace{0.3em}}
+\def\nequiv{\not\equiv}
+\def\approx{\raisebox{0.2ex}{\mbox{\small $\sim$}}}
+\def\lcm{{\rm lcm}}
+\def\gcd{{\rm gcd}}
+\def\log{{\rm log}}
+\def\ord{{\rm ord}}
+\def\abs{{\mathit abs}}
+\def\rep{{\mathit rep}}
+\def\mod{{\mathit\ mod\ }}
+\renewcommand{\pmod}[1]{\ ({\rm mod\ }{#1})}
+\newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor}
+\newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil}
+\def\Or{{\rm\ or\ }}
+\def\And{{\rm\ and\ }}
+\def\iff{\hspace{1em}\Longleftrightarrow\hspace{1em}}
+\def\implies{\Rightarrow}
+\def\undefined{{\rm ``undefined"}}
+\def\Proof{\vspace{1ex}\noindent {\bf Proof:}\hspace{1em}}
+\let\oldphi\phi
+\def\phi{\varphi}
+\def\Pr{{\rm Pr}}
+\newcommand{\str}[1]{{\mathbf{#1}}}
+\def\F{{\mathbb F}}
+\def\N{{\mathbb N}}
+\def\Z{{\mathbb Z}}
+\def\R{{\mathbb R}}
+\def\C{{\mathbb C}}
+\def\Q{{\mathbb Q}}
+\definecolor{DGray}{gray}{0.5}
+\newcommand{\emailaddr}[1]{\mbox{$<${#1}$>$}}
+\def\twiddle{\raisebox{0.3ex}{\mbox{\tiny $\sim$}}}
+\def\gap{\vspace{0.5ex}}
+\makeindex
+\begin{document}
+\frontmatter
+\pagestyle{empty}
+\title{Multi--Precision Math}
+\author{\mbox{
+%\begin{small}
+\begin{tabular}{c}
+Tom St Denis \\
+Algonquin College \\
+\\
+Mads Rasmussen \\
+Open Communications Security \\
+\\
+Greg Rose \\
+QUALCOMM Australia \\
+\end{tabular}
+%\end{small}
+}
+}
+\maketitle
+This text has been placed in the public domain. This text corresponds to the v0.39 release of the
+LibTomMath project.
+
+\begin{alltt}
+Tom St Denis
+111 Banning Rd
+Ottawa, Ontario
+K2L 1C3
+Canada
+
+Phone: 1-613-836-3160
+Email: tomstdenis@gmail.com
+\end{alltt}
+
+This text is formatted to the international B5 paper size of 176mm wide by 250mm tall using the \LaTeX{}
+{\em book} macro package and the Perl {\em booker} package.
+
+\tableofcontents
+\listoffigures
+\chapter*{Prefaces}
+When I tell people about my LibTom projects and that I release them as public domain they are often puzzled.
+They ask why I did it and especially why I continue to work on them for free. The best I can explain it is ``Because I can.''
+Which seems odd and perhaps too terse for adult conversation. I often qualify it with ``I am able, I am willing.'' which
+perhaps explains it better. I am the first to admit there is not anything that special with what I have done. Perhaps
+others can see that too and then we would have a society to be proud of. My LibTom projects are what I am doing to give
+back to society in the form of tools and knowledge that can help others in their endeavours.
+
+I started writing this book because it was the most logical task to further my goal of open academia. The LibTomMath source
+code itself was written to be easy to follow and learn from. There are times, however, where pure C source code does not
+explain the algorithms properly. Hence this book. The book literally starts with the foundation of the library and works
+itself outwards to the more complicated algorithms. The use of both pseudo--code and verbatim source code provides a duality
+of ``theory'' and ``practice'' that the computer science students of the world shall appreciate. I never deviate too far
+from relatively straightforward algebra and I hope that this book can be a valuable learning asset.
+
+This book and indeed much of the LibTom projects would not exist in their current form if it was not for a plethora
+of kind people donating their time, resources and kind words to help support my work. Writing a text of significant
+length (along with the source code) is a tiresome and lengthy process. Currently the LibTom project is four years old,
+comprises of literally thousands of users and over 100,000 lines of source code, TeX and other material. People like Mads and Greg
+were there at the beginning to encourage me to work well. It is amazing how timely validation from others can boost morale to
+continue the project. Definitely my parents were there for me by providing room and board during the many months of work in 2003.
+
+To my many friends whom I have met through the years I thank you for the good times and the words of encouragement. I hope I
+honour your kind gestures with this project.
+
+Open Source. Open Academia. Open Minds.
+
+\begin{flushright} Tom St Denis \end{flushright}
+
+\newpage
+I found the opportunity to work with Tom appealing for several reasons, not only could I broaden my own horizons, but also
+contribute to educate others facing the problem of having to handle big number mathematical calculations.
+
+This book is Tom's child and he has been caring and fostering the project ever since the beginning with a clear mind of
+how he wanted the project to turn out. I have helped by proofreading the text and we have had several discussions about
+the layout and language used.
+
+I hold a masters degree in cryptography from the University of Southern Denmark and have always been interested in the
+practical aspects of cryptography.
+
+Having worked in the security consultancy business for several years in S\~{a}o Paulo, Brazil, I have been in touch with a
+great deal of work in which multiple precision mathematics was needed. Understanding the possibilities for speeding up
+multiple precision calculations is often very important since we deal with outdated machine architecture where modular
+reductions, for example, become painfully slow.
+
+This text is for people who stop and wonder when first examining algorithms such as RSA for the first time and asks
+themselves, ``You tell me this is only secure for large numbers, fine; but how do you implement these numbers?''
+
+\begin{flushright}
+Mads Rasmussen
+
+S\~{a}o Paulo - SP
+
+Brazil
+\end{flushright}
+
+\newpage
+It's all because I broke my leg. That just happened to be at about the same time that Tom asked for someone to review the section of the book about
+Karatsuba multiplication. I was laid up, alone and immobile, and thought ``Why not?'' I vaguely knew what Karatsuba multiplication was, but not
+really, so I thought I could help, learn, and stop myself from watching daytime cable TV, all at once.
+
+At the time of writing this, I've still not met Tom or Mads in meatspace. I've been following Tom's progress since his first splash on the
+sci.crypt Usenet news group. I watched him go from a clueless newbie, to the cryptographic equivalent of a reformed smoker, to a real
+contributor to the field, over a period of about two years. I've been impressed with his obvious intelligence, and astounded by his productivity.
+Of course, he's young enough to be my own child, so he doesn't have my problems with staying awake.
+
+When I reviewed that single section of the book, in its very earliest form, I was very pleasantly surprised. So I decided to collaborate more fully,
+and at least review all of it, and perhaps write some bits too. There's still a long way to go with it, and I have watched a number of close
+friends go through the mill of publication, so I think that the way to go is longer than Tom thinks it is. Nevertheless, it's a good effort,
+and I'm pleased to be involved with it.
+
+\begin{flushright}
+Greg Rose, Sydney, Australia, June 2003.
+\end{flushright}
+
+\mainmatter
+\pagestyle{headings}
+\chapter{Introduction}
+\section{Multiple Precision Arithmetic}
+
+\subsection{What is Multiple Precision Arithmetic?}
+When we think of long-hand arithmetic such as addition or multiplication we rarely consider the fact that we instinctively
+raise or lower the precision of the numbers we are dealing with. For example, in decimal we almost immediate can
+reason that $7$ times $6$ is $42$. However, $42$ has two digits of precision as opposed to one digit we started with.
+Further multiplications of say $3$ result in a larger precision result $126$. In these few examples we have multiple
+precisions for the numbers we are working with. Despite the various levels of precision a single subset\footnote{With the occasional optimization.}
+ of algorithms can be designed to accomodate them.
+
+By way of comparison a fixed or single precision operation would lose precision on various operations. For example, in
+the decimal system with fixed precision $6 \cdot 7 = 2$.
+
+Essentially at the heart of computer based multiple precision arithmetic are the same long-hand algorithms taught in
+schools to manually add, subtract, multiply and divide.
+
+\subsection{The Need for Multiple Precision Arithmetic}
+The most prevalent need for multiple precision arithmetic, often referred to as ``bignum'' math, is within the implementation
+of public-key cryptography algorithms. Algorithms such as RSA \cite{RSAREF} and Diffie-Hellman \cite{DHREF} require
+integers of significant magnitude to resist known cryptanalytic attacks. For example, at the time of this writing a
+typical RSA modulus would be at least greater than $10^{309}$. However, modern programming languages such as ISO C \cite{ISOC} and
+Java \cite{JAVA} only provide instrinsic support for integers which are relatively small and single precision.
+
+\begin{figure}[!here]
+\begin{center}
+\begin{tabular}{|r|c|}
+\hline \textbf{Data Type} & \textbf{Range} \\
+\hline char & $-128 \ldots 127$ \\
+\hline short & $-32768 \ldots 32767$ \\
+\hline long & $-2147483648 \ldots 2147483647$ \\
+\hline long long & $-9223372036854775808 \ldots 9223372036854775807$ \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Typical Data Types for the C Programming Language}
+\label{fig:ISOC}
+\end{figure}
+
+The largest data type guaranteed to be provided by the ISO C programming
+language\footnote{As per the ISO C standard. However, each compiler vendor is allowed to augment the precision as they
+see fit.} can only represent values up to $10^{19}$ as shown in figure \ref{fig:ISOC}. On its own the C language is
+insufficient to accomodate the magnitude required for the problem at hand. An RSA modulus of magnitude $10^{19}$ could be
+trivially factored\footnote{A Pollard-Rho factoring would take only $2^{16}$ time.} on the average desktop computer,
+rendering any protocol based on the algorithm insecure. Multiple precision algorithms solve this very problem by
+extending the range of representable integers while using single precision data types.
+
+Most advancements in fast multiple precision arithmetic stem from the need for faster and more efficient cryptographic
+primitives. Faster modular reduction and exponentiation algorithms such as Barrett's algorithm, which have appeared in
+various cryptographic journals, can render algorithms such as RSA and Diffie-Hellman more efficient. In fact, several
+major companies such as RSA Security, Certicom and Entrust have built entire product lines on the implementation and
+deployment of efficient algorithms.
+
+However, cryptography is not the only field of study that can benefit from fast multiple precision integer routines.
+Another auxiliary use of multiple precision integers is high precision floating point data types.
+The basic IEEE \cite{IEEE} standard floating point type is made up of an integer mantissa $q$, an exponent $e$ and a sign bit $s$.
+Numbers are given in the form $n = q \cdot b^e \cdot -1^s$ where $b = 2$ is the most common base for IEEE. Since IEEE
+floating point is meant to be implemented in hardware the precision of the mantissa is often fairly small
+(\textit{23, 48 and 64 bits}). The mantissa is merely an integer and a multiple precision integer could be used to create
+a mantissa of much larger precision than hardware alone can efficiently support. This approach could be useful where
+scientific applications must minimize the total output error over long calculations.
+
+Yet another use for large integers is within arithmetic on polynomials of large characteristic (i.e. $GF(p)[x]$ for large $p$).
+In fact the library discussed within this text has already been used to form a polynomial basis library\footnote{See \url{http://poly.libtomcrypt.org} for more details.}.
+
+\subsection{Benefits of Multiple Precision Arithmetic}
+\index{precision}
+The benefit of multiple precision representations over single or fixed precision representations is that
+no precision is lost while representing the result of an operation which requires excess precision. For example,
+the product of two $n$-bit integers requires at least $2n$ bits of precision to be represented faithfully. A multiple
+precision algorithm would augment the precision of the destination to accomodate the result while a single precision system
+would truncate excess bits to maintain a fixed level of precision.
+
+It is possible to implement algorithms which require large integers with fixed precision algorithms. For example, elliptic
+curve cryptography (\textit{ECC}) is often implemented on smartcards by fixing the precision of the integers to the maximum
+size the system will ever need. Such an approach can lead to vastly simpler algorithms which can accomodate the
+integers required even if the host platform cannot natively accomodate them\footnote{For example, the average smartcard
+processor has an 8 bit accumulator.}. However, as efficient as such an approach may be, the resulting source code is not
+normally very flexible. It cannot, at runtime, accomodate inputs of higher magnitude than the designer anticipated.
+
+Multiple precision algorithms have the most overhead of any style of arithmetic. For the the most part the
+overhead can be kept to a minimum with careful planning, but overall, it is not well suited for most memory starved
+platforms. However, multiple precision algorithms do offer the most flexibility in terms of the magnitude of the
+inputs. That is, the same algorithms based on multiple precision integers can accomodate any reasonable size input
+without the designer's explicit forethought. This leads to lower cost of ownership for the code as it only has to
+be written and tested once.
+
+\section{Purpose of This Text}
+The purpose of this text is to instruct the reader regarding how to implement efficient multiple precision algorithms.
+That is to not only explain a limited subset of the core theory behind the algorithms but also the various ``house keeping''
+elements that are neglected by authors of other texts on the subject. Several well reknowned texts \cite{TAOCPV2,HAC}
+give considerably detailed explanations of the theoretical aspects of algorithms and often very little information
+regarding the practical implementation aspects.
+
+In most cases how an algorithm is explained and how it is actually implemented are two very different concepts. For
+example, the Handbook of Applied Cryptography (\textit{HAC}), algorithm 14.7 on page 594, gives a relatively simple
+algorithm for performing multiple precision integer addition. However, the description lacks any discussion concerning
+the fact that the two integer inputs may be of differing magnitudes. As a result the implementation is not as simple
+as the text would lead people to believe. Similarly the division routine (\textit{algorithm 14.20, pp. 598}) does not
+discuss how to handle sign or handle the dividend's decreasing magnitude in the main loop (\textit{step \#3}).
+
+Both texts also do not discuss several key optimal algorithms required such as ``Comba'' and Karatsuba multipliers
+and fast modular inversion, which we consider practical oversights. These optimal algorithms are vital to achieve
+any form of useful performance in non-trivial applications.
+
+To solve this problem the focus of this text is on the practical aspects of implementing a multiple precision integer
+package. As a case study the ``LibTomMath''\footnote{Available at \url{http://math.libtomcrypt.com}} package is used
+to demonstrate algorithms with real implementations\footnote{In the ISO C programming language.} that have been field
+tested and work very well. The LibTomMath library is freely available on the Internet for all uses and this text
+discusses a very large portion of the inner workings of the library.
+
+The algorithms that are presented will always include at least one ``pseudo-code'' description followed
+by the actual C source code that implements the algorithm. The pseudo-code can be used to implement the same
+algorithm in other programming languages as the reader sees fit.
+
+This text shall also serve as a walkthrough of the creation of multiple precision algorithms from scratch. Showing
+the reader how the algorithms fit together as well as where to start on various taskings.
+
+\section{Discussion and Notation}
+\subsection{Notation}
+A multiple precision integer of $n$-digits shall be denoted as $x = (x_{n-1}, \ldots, x_1, x_0)_{ \beta }$ and represent
+the integer $x \equiv \sum_{i=0}^{n-1} x_i\beta^i$. The elements of the array $x$ are said to be the radix $\beta$ digits
+of the integer. For example, $x = (1,2,3)_{10}$ would represent the integer
+$1\cdot 10^2 + 2\cdot10^1 + 3\cdot10^0 = 123$.
+
+\index{mp\_int}
+The term ``mp\_int'' shall refer to a composite structure which contains the digits of the integer it represents, as well
+as auxilary data required to manipulate the data. These additional members are discussed further in section
+\ref{sec:MPINT}. For the purposes of this text a ``multiple precision integer'' and an ``mp\_int'' are assumed to be
+synonymous. When an algorithm is specified to accept an mp\_int variable it is assumed the various auxliary data members
+are present as well. An expression of the type \textit{variablename.item} implies that it should evaluate to the
+member named ``item'' of the variable. For example, a string of characters may have a member ``length'' which would
+evaluate to the number of characters in the string. If the string $a$ equals ``hello'' then it follows that
+$a.length = 5$.
+
+For certain discussions more generic algorithms are presented to help the reader understand the final algorithm used
+to solve a given problem. When an algorithm is described as accepting an integer input it is assumed the input is
+a plain integer with no additional multiple-precision members. That is, algorithms that use integers as opposed to
+mp\_ints as inputs do not concern themselves with the housekeeping operations required such as memory management. These
+algorithms will be used to establish the relevant theory which will subsequently be used to describe a multiple
+precision algorithm to solve the same problem.
+
+\subsection{Precision Notation}
+The variable $\beta$ represents the radix of a single digit of a multiple precision integer and
+must be of the form $q^p$ for $q, p \in \Z^+$. A single precision variable must be able to represent integers in
+the range $0 \le x < q \beta$ while a double precision variable must be able to represent integers in the range
+$0 \le x < q \beta^2$. The extra radix-$q$ factor allows additions and subtractions to proceed without truncation of the
+carry. Since all modern computers are binary, it is assumed that $q$ is two.
+
+\index{mp\_digit} \index{mp\_word}
+Within the source code that will be presented for each algorithm, the data type \textbf{mp\_digit} will represent
+a single precision integer type, while, the data type \textbf{mp\_word} will represent a double precision integer type. In
+several algorithms (notably the Comba routines) temporary results will be stored in arrays of double precision mp\_words.
+For the purposes of this text $x_j$ will refer to the $j$'th digit of a single precision array and $\hat x_j$ will refer to
+the $j$'th digit of a double precision array. Whenever an expression is to be assigned to a double precision
+variable it is assumed that all single precision variables are promoted to double precision during the evaluation.
+Expressions that are assigned to a single precision variable are truncated to fit within the precision of a single
+precision data type.
+
+For example, if $\beta = 10^2$ a single precision data type may represent a value in the
+range $0 \le x < 10^3$, while a double precision data type may represent a value in the range $0 \le x < 10^5$. Let
+$a = 23$ and $b = 49$ represent two single precision variables. The single precision product shall be written
+as $c \leftarrow a \cdot b$ while the double precision product shall be written as $\hat c \leftarrow a \cdot b$.
+In this particular case, $\hat c = 1127$ and $c = 127$. The most significant digit of the product would not fit
+in a single precision data type and as a result $c \ne \hat c$.
+
+\subsection{Algorithm Inputs and Outputs}
+Within the algorithm descriptions all variables are assumed to be scalars of either single or double precision
+as indicated. The only exception to this rule is when variables have been indicated to be of type mp\_int. This
+distinction is important as scalars are often used as array indicies and various other counters.
+
+\subsection{Mathematical Expressions}
+The $\lfloor \mbox{ } \rfloor$ brackets imply an expression truncated to an integer not greater than the expression
+itself. For example, $\lfloor 5.7 \rfloor = 5$. Similarly the $\lceil \mbox{ } \rceil$ brackets imply an expression
+rounded to an integer not less than the expression itself. For example, $\lceil 5.1 \rceil = 6$. Typically when
+the $/$ division symbol is used the intention is to perform an integer division with truncation. For example,
+$5/2 = 2$ which will often be written as $\lfloor 5/2 \rfloor = 2$ for clarity. When an expression is written as a
+fraction a real value division is implied, for example ${5 \over 2} = 2.5$.
+
+The norm of a multiple precision integer, for example $\vert \vert x \vert \vert$, will be used to represent the number of digits in the representation
+of the integer. For example, $\vert \vert 123 \vert \vert = 3$ and $\vert \vert 79452 \vert \vert = 5$.
+
+\subsection{Work Effort}
+\index{big-Oh}
+To measure the efficiency of the specified algorithms, a modified big-Oh notation is used. In this system all
+single precision operations are considered to have the same cost\footnote{Except where explicitly noted.}.
+That is a single precision addition, multiplication and division are assumed to take the same time to
+complete. While this is generally not true in practice, it will simplify the discussions considerably.
+
+Some algorithms have slight advantages over others which is why some constants will not be removed in
+the notation. For example, a normal baseline multiplication (section \ref{sec:basemult}) requires $O(n^2)$ work while a
+baseline squaring (section \ref{sec:basesquare}) requires $O({{n^2 + n}\over 2})$ work. In standard big-Oh notation these
+would both be said to be equivalent to $O(n^2)$. However,
+in the context of the this text this is not the case as the magnitude of the inputs will typically be rather small. As a
+result small constant factors in the work effort will make an observable difference in algorithm efficiency.
+
+All of the algorithms presented in this text have a polynomial time work level. That is, of the form
+$O(n^k)$ for $n, k \in \Z^{+}$. This will help make useful comparisons in terms of the speed of the algorithms and how
+various optimizations will help pay off in the long run.
+
+\section{Exercises}
+Within the more advanced chapters a section will be set aside to give the reader some challenging exercises related to
+the discussion at hand. These exercises are not designed to be prize winning problems, but instead to be thought
+provoking. Wherever possible the problems are forward minded, stating problems that will be answered in subsequent
+chapters. The reader is encouraged to finish the exercises as they appear to get a better understanding of the
+subject material.
+
+That being said, the problems are designed to affirm knowledge of a particular subject matter. Students in particular
+are encouraged to verify they can answer the problems correctly before moving on.
+
+Similar to the exercises of \cite[pp. ix]{TAOCPV2} these exercises are given a scoring system based on the difficulty of
+the problem. However, unlike \cite{TAOCPV2} the problems do not get nearly as hard. The scoring of these
+exercises ranges from one (the easiest) to five (the hardest). The following table sumarizes the
+scoring system used.
+
+\begin{figure}[here]
+\begin{center}
+\begin{small}
+\begin{tabular}{|c|l|}
+\hline $\left [ 1 \right ]$ & An easy problem that should only take the reader a manner of \\
+ & minutes to solve. Usually does not involve much computer time \\
+ & to solve. \\
+\hline $\left [ 2 \right ]$ & An easy problem that involves a marginal amount of computer \\
+ & time usage. Usually requires a program to be written to \\
+ & solve the problem. \\
+\hline $\left [ 3 \right ]$ & A moderately hard problem that requires a non-trivial amount \\
+ & of work. Usually involves trivial research and development of \\
+ & new theory from the perspective of a student. \\
+\hline $\left [ 4 \right ]$ & A moderately hard problem that involves a non-trivial amount \\
+ & of work and research, the solution to which will demonstrate \\
+ & a higher mastery of the subject matter. \\
+\hline $\left [ 5 \right ]$ & A hard problem that involves concepts that are difficult for a \\
+ & novice to solve. Solutions to these problems will demonstrate a \\
+ & complete mastery of the given subject. \\
+\hline
+\end{tabular}
+\end{small}
+\end{center}
+\caption{Exercise Scoring System}
+\end{figure}
+
+Problems at the first level are meant to be simple questions that the reader can answer quickly without programming a solution or
+devising new theory. These problems are quick tests to see if the material is understood. Problems at the second level
+are also designed to be easy but will require a program or algorithm to be implemented to arrive at the answer. These
+two levels are essentially entry level questions.
+
+Problems at the third level are meant to be a bit more difficult than the first two levels. The answer is often
+fairly obvious but arriving at an exacting solution requires some thought and skill. These problems will almost always
+involve devising a new algorithm or implementing a variation of another algorithm previously presented. Readers who can
+answer these questions will feel comfortable with the concepts behind the topic at hand.
+
+Problems at the fourth level are meant to be similar to those of the level three questions except they will require
+additional research to be completed. The reader will most likely not know the answer right away, nor will the text provide
+the exact details of the answer until a subsequent chapter.
+
+Problems at the fifth level are meant to be the hardest
+problems relative to all the other problems in the chapter. People who can correctly answer fifth level problems have a
+mastery of the subject matter at hand.
+
+Often problems will be tied together. The purpose of this is to start a chain of thought that will be discussed in future chapters. The reader
+is encouraged to answer the follow-up problems and try to draw the relevance of problems.
+
+\section{Introduction to LibTomMath}
+
+\subsection{What is LibTomMath?}
+LibTomMath is a free and open source multiple precision integer library written entirely in portable ISO C. By portable it
+is meant that the library does not contain any code that is computer platform dependent or otherwise problematic to use on
+any given platform.
+
+The library has been successfully tested under numerous operating systems including Unix\footnote{All of these
+trademarks belong to their respective rightful owners.}, MacOS, Windows, Linux, PalmOS and on standalone hardware such
+as the Gameboy Advance. The library is designed to contain enough functionality to be able to develop applications such
+as public key cryptosystems and still maintain a relatively small footprint.
+
+\subsection{Goals of LibTomMath}
+
+Libraries which obtain the most efficiency are rarely written in a high level programming language such as C. However,
+even though this library is written entirely in ISO C, considerable care has been taken to optimize the algorithm implementations within the
+library. Specifically the code has been written to work well with the GNU C Compiler (\textit{GCC}) on both x86 and ARM
+processors. Wherever possible, highly efficient algorithms, such as Karatsuba multiplication, sliding window
+exponentiation and Montgomery reduction have been provided to make the library more efficient.
+
+Even with the nearly optimal and specialized algorithms that have been included the Application Programing Interface
+(\textit{API}) has been kept as simple as possible. Often generic place holder routines will make use of specialized
+algorithms automatically without the developer's specific attention. One such example is the generic multiplication
+algorithm \textbf{mp\_mul()} which will automatically use Toom--Cook, Karatsuba, Comba or baseline multiplication
+based on the magnitude of the inputs and the configuration of the library.
+
+Making LibTomMath as efficient as possible is not the only goal of the LibTomMath project. Ideally the library should
+be source compatible with another popular library which makes it more attractive for developers to use. In this case the
+MPI library was used as a API template for all the basic functions. MPI was chosen because it is another library that fits
+in the same niche as LibTomMath. Even though LibTomMath uses MPI as the template for the function names and argument
+passing conventions, it has been written from scratch by Tom St Denis.
+
+The project is also meant to act as a learning tool for students, the logic being that no easy-to-follow ``bignum''
+library exists which can be used to teach computer science students how to perform fast and reliable multiple precision
+integer arithmetic. To this end the source code has been given quite a few comments and algorithm discussion points.
+
+\section{Choice of LibTomMath}
+LibTomMath was chosen as the case study of this text not only because the author of both projects is one and the same but
+for more worthy reasons. Other libraries such as GMP \cite{GMP}, MPI \cite{MPI}, LIP \cite{LIP} and OpenSSL
+\cite{OPENSSL} have multiple precision integer arithmetic routines but would not be ideal for this text for
+reasons that will be explained in the following sub-sections.
+
+\subsection{Code Base}
+The LibTomMath code base is all portable ISO C source code. This means that there are no platform dependent conditional
+segments of code littered throughout the source. This clean and uncluttered approach to the library means that a
+developer can more readily discern the true intent of a given section of source code without trying to keep track of
+what conditional code will be used.
+
+The code base of LibTomMath is well organized. Each function is in its own separate source code file
+which allows the reader to find a given function very quickly. On average there are $76$ lines of code per source
+file which makes the source very easily to follow. By comparison MPI and LIP are single file projects making code tracing
+very hard. GMP has many conditional code segments which also hinder tracing.
+
+When compiled with GCC for the x86 processor and optimized for speed the entire library is approximately $100$KiB\footnote{The notation ``KiB'' means $2^{10}$ octets, similarly ``MiB'' means $2^{20}$ octets.}
+ which is fairly small compared to GMP (over $250$KiB). LibTomMath is slightly larger than MPI (which compiles to about
+$50$KiB) but LibTomMath is also much faster and more complete than MPI.
+
+\subsection{API Simplicity}
+LibTomMath is designed after the MPI library and shares the API design. Quite often programs that use MPI will build
+with LibTomMath without change. The function names correlate directly to the action they perform. Almost all of the
+functions share the same parameter passing convention. The learning curve is fairly shallow with the API provided
+which is an extremely valuable benefit for the student and developer alike.
+
+The LIP library is an example of a library with an API that is awkward to work with. LIP uses function names that are often ``compressed'' to
+illegible short hand. LibTomMath does not share this characteristic.
+
+The GMP library also does not return error codes. Instead it uses a POSIX.1 \cite{POSIX1} signal system where errors
+are signaled to the host application. This happens to be the fastest approach but definitely not the most versatile. In
+effect a math error (i.e. invalid input, heap error, etc) can cause a program to stop functioning which is definitely
+undersireable in many situations.
+
+\subsection{Optimizations}
+While LibTomMath is certainly not the fastest library (GMP often beats LibTomMath by a factor of two) it does
+feature a set of optimal algorithms for tasks such as modular reduction, exponentiation, multiplication and squaring. GMP
+and LIP also feature such optimizations while MPI only uses baseline algorithms with no optimizations. GMP lacks a few
+of the additional modular reduction optimizations that LibTomMath features\footnote{At the time of this writing GMP
+only had Barrett and Montgomery modular reduction algorithms.}.
+
+LibTomMath is almost always an order of magnitude faster than the MPI library at computationally expensive tasks such as modular
+exponentiation. In the grand scheme of ``bignum'' libraries LibTomMath is faster than the average library and usually
+slower than the best libraries such as GMP and OpenSSL by only a small factor.
+
+\subsection{Portability and Stability}
+LibTomMath will build ``out of the box'' on any platform equipped with a modern version of the GNU C Compiler
+(\textit{GCC}). This means that without changes the library will build without configuration or setting up any
+variables. LIP and MPI will build ``out of the box'' as well but have numerous known bugs. Most notably the author of
+MPI has recently stopped working on his library and LIP has long since been discontinued.
+
+GMP requires a configuration script to run and will not build out of the box. GMP and LibTomMath are still in active
+development and are very stable across a variety of platforms.
+
+\subsection{Choice}
+LibTomMath is a relatively compact, well documented, highly optimized and portable library which seems only natural for
+the case study of this text. Various source files from the LibTomMath project will be included within the text. However,
+the reader is encouraged to download their own copy of the library to actually be able to work with the library.
+
+\chapter{Getting Started}
+\section{Library Basics}
+The trick to writing any useful library of source code is to build a solid foundation and work outwards from it. First,
+a problem along with allowable solution parameters should be identified and analyzed. In this particular case the
+inability to accomodate multiple precision integers is the problem. Futhermore, the solution must be written
+as portable source code that is reasonably efficient across several different computer platforms.
+
+After a foundation is formed the remainder of the library can be designed and implemented in a hierarchical fashion.
+That is, to implement the lowest level dependencies first and work towards the most abstract functions last. For example,
+before implementing a modular exponentiation algorithm one would implement a modular reduction algorithm.
+By building outwards from a base foundation instead of using a parallel design methodology the resulting project is
+highly modular. Being highly modular is a desirable property of any project as it often means the resulting product
+has a small footprint and updates are easy to perform.
+
+Usually when I start a project I will begin with the header files. I define the data types I think I will need and
+prototype the initial functions that are not dependent on other functions (within the library). After I
+implement these base functions I prototype more dependent functions and implement them. The process repeats until
+I implement all of the functions I require. For example, in the case of LibTomMath I implemented functions such as
+mp\_init() well before I implemented mp\_mul() and even further before I implemented mp\_exptmod(). As an example as to
+why this design works note that the Karatsuba and Toom-Cook multipliers were written \textit{after} the
+dependent function mp\_exptmod() was written. Adding the new multiplication algorithms did not require changes to the
+mp\_exptmod() function itself and lowered the total cost of ownership (\textit{so to speak}) and of development
+for new algorithms. This methodology allows new algorithms to be tested in a complete framework with relative ease.
+
+FIGU,design_process,Design Flow of the First Few Original LibTomMath Functions.
+
+Only after the majority of the functions were in place did I pursue a less hierarchical approach to auditing and optimizing
+the source code. For example, one day I may audit the multipliers and the next day the polynomial basis functions.
+
+It only makes sense to begin the text with the preliminary data types and support algorithms required as well.
+This chapter discusses the core algorithms of the library which are the dependents for every other algorithm.
+
+\section{What is a Multiple Precision Integer?}
+Recall that most programming languages, in particular ISO C \cite{ISOC}, only have fixed precision data types that on their own cannot
+be used to represent values larger than their precision will allow. The purpose of multiple precision algorithms is
+to use fixed precision data types to create and manipulate multiple precision integers which may represent values
+that are very large.
+
+As a well known analogy, school children are taught how to form numbers larger than nine by prepending more radix ten digits. In the decimal system
+the largest single digit value is $9$. However, by concatenating digits together larger numbers may be represented. Newly prepended digits
+(\textit{to the left}) are said to be in a different power of ten column. That is, the number $123$ can be described as having a $1$ in the hundreds
+column, $2$ in the tens column and $3$ in the ones column. Or more formally $123 = 1 \cdot 10^2 + 2 \cdot 10^1 + 3 \cdot 10^0$. Computer based
+multiple precision arithmetic is essentially the same concept. Larger integers are represented by adjoining fixed
+precision computer words with the exception that a different radix is used.
+
+What most people probably do not think about explicitly are the various other attributes that describe a multiple precision
+integer. For example, the integer $154_{10}$ has two immediately obvious properties. First, the integer is positive,
+that is the sign of this particular integer is positive as opposed to negative. Second, the integer has three digits in
+its representation. There is an additional property that the integer posesses that does not concern pencil-and-paper
+arithmetic. The third property is how many digits placeholders are available to hold the integer.
+
+The human analogy of this third property is ensuring there is enough space on the paper to write the integer. For example,
+if one starts writing a large number too far to the right on a piece of paper they will have to erase it and move left.
+Similarly, computer algorithms must maintain strict control over memory usage to ensure that the digits of an integer
+will not exceed the allowed boundaries. These three properties make up what is known as a multiple precision
+integer or mp\_int for short.
+
+\subsection{The mp\_int Structure}
+\label{sec:MPINT}
+The mp\_int structure is the ISO C based manifestation of what represents a multiple precision integer. The ISO C standard does not provide for
+any such data type but it does provide for making composite data types known as structures. The following is the structure definition
+used within LibTomMath.
+
+\index{mp\_int}
+\begin{figure}[here]
+\begin{center}
+\begin{small}
+%\begin{verbatim}
+\begin{tabular}{|l|}
+\hline
+typedef struct \{ \\
+\hspace{3mm}int used, alloc, sign;\\
+\hspace{3mm}mp\_digit *dp;\\
+\} \textbf{mp\_int}; \\
+\hline
+\end{tabular}
+%\end{verbatim}
+\end{small}
+\caption{The mp\_int Structure}
+\label{fig:mpint}
+\end{center}
+\end{figure}
+
+The mp\_int structure (fig. \ref{fig:mpint}) can be broken down as follows.
+
+\begin{enumerate}
+\item The \textbf{used} parameter denotes how many digits of the array \textbf{dp} contain the digits used to represent
+a given integer. The \textbf{used} count must be positive (or zero) and may not exceed the \textbf{alloc} count.
+
+\item The \textbf{alloc} parameter denotes how
+many digits are available in the array to use by functions before it has to increase in size. When the \textbf{used} count
+of a result would exceed the \textbf{alloc} count all of the algorithms will automatically increase the size of the
+array to accommodate the precision of the result.
+
+\item The pointer \textbf{dp} points to a dynamically allocated array of digits that represent the given multiple
+precision integer. It is padded with $(\textbf{alloc} - \textbf{used})$ zero digits. The array is maintained in a least
+significant digit order. As a pencil and paper analogy the array is organized such that the right most digits are stored
+first starting at the location indexed by zero\footnote{In C all arrays begin at zero.} in the array. For example,
+if \textbf{dp} contains $\lbrace a, b, c, \ldots \rbrace$ where \textbf{dp}$_0 = a$, \textbf{dp}$_1 = b$, \textbf{dp}$_2 = c$, $\ldots$ then
+it would represent the integer $a + b\beta + c\beta^2 + \ldots$
+
+\index{MP\_ZPOS} \index{MP\_NEG}
+\item The \textbf{sign} parameter denotes the sign as either zero/positive (\textbf{MP\_ZPOS}) or negative (\textbf{MP\_NEG}).
+\end{enumerate}
+
+\subsubsection{Valid mp\_int Structures}
+Several rules are placed on the state of an mp\_int structure and are assumed to be followed for reasons of efficiency.
+The only exceptions are when the structure is passed to initialization functions such as mp\_init() and mp\_init\_copy().
+
+\begin{enumerate}
+\item The value of \textbf{alloc} may not be less than one. That is \textbf{dp} always points to a previously allocated
+array of digits.
+\item The value of \textbf{used} may not exceed \textbf{alloc} and must be greater than or equal to zero.
+\item The value of \textbf{used} implies the digit at index $(used - 1)$ of the \textbf{dp} array is non-zero. That is,
+leading zero digits in the most significant positions must be trimmed.
+ \begin{enumerate}
+ \item Digits in the \textbf{dp} array at and above the \textbf{used} location must be zero.
+ \end{enumerate}
+\item The value of \textbf{sign} must be \textbf{MP\_ZPOS} if \textbf{used} is zero;
+this represents the mp\_int value of zero.
+\end{enumerate}
+
+\section{Argument Passing}
+A convention of argument passing must be adopted early on in the development of any library. Making the function
+prototypes consistent will help eliminate many headaches in the future as the library grows to significant complexity.
+In LibTomMath the multiple precision integer functions accept parameters from left to right as pointers to mp\_int
+structures. That means that the source (input) operands are placed on the left and the destination (output) on the right.
+Consider the following examples.
+
+\begin{verbatim}
+ mp_mul(&a, &b, &c); /* c = a * b */
+ mp_add(&a, &b, &a); /* a = a + b */
+ mp_sqr(&a, &b); /* b = a * a */
+\end{verbatim}
+
+The left to right order is a fairly natural way to implement the functions since it lets the developer read aloud the
+functions and make sense of them. For example, the first function would read ``multiply a and b and store in c''.
+
+Certain libraries (\textit{LIP by Lenstra for instance}) accept parameters the other way around, to mimic the order
+of assignment expressions. That is, the destination (output) is on the left and arguments (inputs) are on the right. In
+truth, it is entirely a matter of preference. In the case of LibTomMath the convention from the MPI library has been
+adopted.
+
+Another very useful design consideration, provided for in LibTomMath, is whether to allow argument sources to also be a
+destination. For example, the second example (\textit{mp\_add}) adds $a$ to $b$ and stores in $a$. This is an important
+feature to implement since it allows the calling functions to cut down on the number of variables it must maintain.
+However, to implement this feature specific care has to be given to ensure the destination is not modified before the
+source is fully read.
+
+\section{Return Values}
+A well implemented application, no matter what its purpose, should trap as many runtime errors as possible and return them
+to the caller. By catching runtime errors a library can be guaranteed to prevent undefined behaviour. However, the end
+developer can still manage to cause a library to crash. For example, by passing an invalid pointer an application may
+fault by dereferencing memory not owned by the application.
+
+In the case of LibTomMath the only errors that are checked for are related to inappropriate inputs (division by zero for
+instance) and memory allocation errors. It will not check that the mp\_int passed to any function is valid nor
+will it check pointers for validity. Any function that can cause a runtime error will return an error code as an
+\textbf{int} data type with one of the following values (fig \ref{fig:errcodes}).
+
+\index{MP\_OKAY} \index{MP\_VAL} \index{MP\_MEM}
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{|l|l|}
+\hline \textbf{Value} & \textbf{Meaning} \\
+\hline \textbf{MP\_OKAY} & The function was successful \\
+\hline \textbf{MP\_VAL} & One of the input value(s) was invalid \\
+\hline \textbf{MP\_MEM} & The function ran out of heap memory \\
+\hline
+\end{tabular}
+\end{center}
+\caption{LibTomMath Error Codes}
+\label{fig:errcodes}
+\end{figure}
+
+When an error is detected within a function it should free any memory it allocated, often during the initialization of
+temporary mp\_ints, and return as soon as possible. The goal is to leave the system in the same state it was when the
+function was called. Error checking with this style of API is fairly simple.
+
+\begin{verbatim}
+ int err;
+ if ((err = mp_add(&a, &b, &c)) != MP_OKAY) {
+ printf("Error: %s\n", mp_error_to_string(err));
+ exit(EXIT_FAILURE);
+ }
+\end{verbatim}
+
+The GMP \cite{GMP} library uses C style \textit{signals} to flag errors which is of questionable use. Not all errors are fatal
+and it was not deemed ideal by the author of LibTomMath to force developers to have signal handlers for such cases.
+
+\section{Initialization and Clearing}
+The logical starting point when actually writing multiple precision integer functions is the initialization and
+clearing of the mp\_int structures. These two algorithms will be used by the majority of the higher level algorithms.
+
+Given the basic mp\_int structure an initialization routine must first allocate memory to hold the digits of
+the integer. Often it is optimal to allocate a sufficiently large pre-set number of digits even though
+the initial integer will represent zero. If only a single digit were allocated quite a few subsequent re-allocations
+would occur when operations are performed on the integers. There is a tradeoff between how many default digits to allocate
+and how many re-allocations are tolerable. Obviously allocating an excessive amount of digits initially will waste
+memory and become unmanageable.
+
+If the memory for the digits has been successfully allocated then the rest of the members of the structure must
+be initialized. Since the initial state of an mp\_int is to represent the zero integer, the allocated digits must be set
+to zero. The \textbf{used} count set to zero and \textbf{sign} set to \textbf{MP\_ZPOS}.
+
+\subsection{Initializing an mp\_int}
+An mp\_int is said to be initialized if it is set to a valid, preferably default, state such that all of the members of the
+structure are set to valid values. The mp\_init algorithm will perform such an action.
+
+\index{mp\_init}
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_init}. \\
+\textbf{Input}. An mp\_int $a$ \\
+\textbf{Output}. Allocate memory and initialize $a$ to a known valid mp\_int state. \\
+\hline \\
+1. Allocate memory for \textbf{MP\_PREC} digits. \\
+2. If the allocation failed return(\textit{MP\_MEM}) \\
+3. for $n$ from $0$ to $MP\_PREC - 1$ do \\
+\hspace{3mm}3.1 $a_n \leftarrow 0$\\
+4. $a.sign \leftarrow MP\_ZPOS$\\
+5. $a.used \leftarrow 0$\\
+6. $a.alloc \leftarrow MP\_PREC$\\
+7. Return(\textit{MP\_OKAY})\\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_init}
+\end{figure}
+
+\textbf{Algorithm mp\_init.}
+The purpose of this function is to initialize an mp\_int structure so that the rest of the library can properly
+manipulte it. It is assumed that the input may not have had any of its members previously initialized which is certainly
+a valid assumption if the input resides on the stack.
+
+Before any of the members such as \textbf{sign}, \textbf{used} or \textbf{alloc} are initialized the memory for
+the digits is allocated. If this fails the function returns before setting any of the other members. The \textbf{MP\_PREC}
+name represents a constant\footnote{Defined in the ``tommath.h'' header file within LibTomMath.}
+used to dictate the minimum precision of newly initialized mp\_int integers. Ideally, it is at least equal to the smallest
+precision number you'll be working with.
+
+Allocating a block of digits at first instead of a single digit has the benefit of lowering the number of usually slow
+heap operations later functions will have to perform in the future. If \textbf{MP\_PREC} is set correctly the slack
+memory and the number of heap operations will be trivial.
+
+Once the allocation has been made the digits have to be set to zero as well as the \textbf{used}, \textbf{sign} and
+\textbf{alloc} members initialized. This ensures that the mp\_int will always represent the default state of zero regardless
+of the original condition of the input.
+
+\textbf{Remark.}
+This function introduces the idiosyncrasy that all iterative loops, commonly initiated with the ``for'' keyword, iterate incrementally
+when the ``to'' keyword is placed between two expressions. For example, ``for $a$ from $b$ to $c$ do'' means that
+a subsequent expression (or body of expressions) are to be evaluated upto $c - b$ times so long as $b \le c$. In each
+iteration the variable $a$ is substituted for a new integer that lies inclusively between $b$ and $c$. If $b > c$ occured
+the loop would not iterate. By contrast if the ``downto'' keyword were used in place of ``to'' the loop would iterate
+decrementally.
+
+EXAM,bn_mp_init.c
+
+One immediate observation of this initializtion function is that it does not return a pointer to a mp\_int structure. It
+is assumed that the caller has already allocated memory for the mp\_int structure, typically on the application stack. The
+call to mp\_init() is used only to initialize the members of the structure to a known default state.
+
+Here we see (line @23,XMALLOC@) the memory allocation is performed first. This allows us to exit cleanly and quickly
+if there is an error. If the allocation fails the routine will return \textbf{MP\_MEM} to the caller to indicate there
+was a memory error. The function XMALLOC is what actually allocates the memory. Technically XMALLOC is not a function
+but a macro defined in ``tommath.h``. By default, XMALLOC will evaluate to malloc() which is the C library's built--in
+memory allocation routine.
+
+In order to assure the mp\_int is in a known state the digits must be set to zero. On most platforms this could have been
+accomplished by using calloc() instead of malloc(). However, to correctly initialize a integer type to a given value in a
+portable fashion you have to actually assign the value. The for loop (line @28,for@) performs this required
+operation.
+
+After the memory has been successfully initialized the remainder of the members are initialized
+(lines @29,used@ through @31,sign@) to their respective default states. At this point the algorithm has succeeded and
+a success code is returned to the calling function. If this function returns \textbf{MP\_OKAY} it is safe to assume the
+mp\_int structure has been properly initialized and is safe to use with other functions within the library.
+
+\subsection{Clearing an mp\_int}
+When an mp\_int is no longer required by the application, the memory that has been allocated for its digits must be
+returned to the application's memory pool with the mp\_clear algorithm.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_clear}. \\
+\textbf{Input}. An mp\_int $a$ \\
+\textbf{Output}. The memory for $a$ shall be deallocated. \\
+\hline \\
+1. If $a$ has been previously freed then return(\textit{MP\_OKAY}). \\
+2. for $n$ from 0 to $a.used - 1$ do \\
+\hspace{3mm}2.1 $a_n \leftarrow 0$ \\
+3. Free the memory allocated for the digits of $a$. \\
+4. $a.used \leftarrow 0$ \\
+5. $a.alloc \leftarrow 0$ \\
+6. $a.sign \leftarrow MP\_ZPOS$ \\
+7. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_clear}
+\end{figure}
+
+\textbf{Algorithm mp\_clear.}
+This algorithm accomplishes two goals. First, it clears the digits and the other mp\_int members. This ensures that
+if a developer accidentally re-uses a cleared structure it is less likely to cause problems. The second goal
+is to free the allocated memory.
+
+The logic behind the algorithm is extended by marking cleared mp\_int structures so that subsequent calls to this
+algorithm will not try to free the memory multiple times. Cleared mp\_ints are detectable by having a pre-defined invalid
+digit pointer \textbf{dp} setting.
+
+Once an mp\_int has been cleared the mp\_int structure is no longer in a valid state for any other algorithm
+with the exception of algorithms mp\_init, mp\_init\_copy, mp\_init\_size and mp\_clear.
+
+EXAM,bn_mp_clear.c
+
+The algorithm only operates on the mp\_int if it hasn't been previously cleared. The if statement (line @23,a->dp != NULL@)
+checks to see if the \textbf{dp} member is not \textbf{NULL}. If the mp\_int is a valid mp\_int then \textbf{dp} cannot be
+\textbf{NULL} in which case the if statement will evaluate to true.
+
+The digits of the mp\_int are cleared by the for loop (line @25,for@) which assigns a zero to every digit. Similar to mp\_init()
+the digits are assigned zero instead of using block memory operations (such as memset()) since this is more portable.
+
+The digits are deallocated off the heap via the XFREE macro. Similar to XMALLOC the XFREE macro actually evaluates to
+a standard C library function. In this case the free() function. Since free() only deallocates the memory the pointer
+still has to be reset to \textbf{NULL} manually (line @33,NULL@).
+
+Now that the digits have been cleared and deallocated the other members are set to their final values (lines @34,= 0@ and @35,ZPOS@).
+
+\section{Maintenance Algorithms}
+
+The previous sections describes how to initialize and clear an mp\_int structure. To further support operations
+that are to be performed on mp\_int structures (such as addition and multiplication) the dependent algorithms must be
+able to augment the precision of an mp\_int and
+initialize mp\_ints with differing initial conditions.
+
+These algorithms complete the set of low level algorithms required to work with mp\_int structures in the higher level
+algorithms such as addition, multiplication and modular exponentiation.
+
+\subsection{Augmenting an mp\_int's Precision}
+When storing a value in an mp\_int structure, a sufficient number of digits must be available to accomodate the entire
+result of an operation without loss of precision. Quite often the size of the array given by the \textbf{alloc} member
+is large enough to simply increase the \textbf{used} digit count. However, when the size of the array is too small it
+must be re-sized appropriately to accomodate the result. The mp\_grow algorithm will provide this functionality.
+
+\newpage\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_grow}. \\
+\textbf{Input}. An mp\_int $a$ and an integer $b$. \\
+\textbf{Output}. $a$ is expanded to accomodate $b$ digits. \\
+\hline \\
+1. if $a.alloc \ge b$ then return(\textit{MP\_OKAY}) \\
+2. $u \leftarrow b\mbox{ (mod }MP\_PREC\mbox{)}$ \\
+3. $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\
+4. Re-allocate the array of digits $a$ to size $v$ \\
+5. If the allocation failed then return(\textit{MP\_MEM}). \\
+6. for n from a.alloc to $v - 1$ do \\
+\hspace{+3mm}6.1 $a_n \leftarrow 0$ \\
+7. $a.alloc \leftarrow v$ \\
+8. Return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_grow}
+\end{figure}
+
+\textbf{Algorithm mp\_grow.}
+It is ideal to prevent re-allocations from being performed if they are not required (step one). This is useful to
+prevent mp\_ints from growing excessively in code that erroneously calls mp\_grow.
+
+The requested digit count is padded up to next multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} (steps two and three).
+This helps prevent many trivial reallocations that would grow an mp\_int by trivially small values.
+
+It is assumed that the reallocation (step four) leaves the lower $a.alloc$ digits of the mp\_int intact. This is much
+akin to how the \textit{realloc} function from the standard C library works. Since the newly allocated digits are
+assumed to contain undefined values they are initially set to zero.
+
+EXAM,bn_mp_grow.c
+
+A quick optimization is to first determine if a memory re-allocation is required at all. The if statement (line @24,alloc@) checks
+if the \textbf{alloc} member of the mp\_int is smaller than the requested digit count. If the count is not larger than \textbf{alloc}
+the function skips the re-allocation part thus saving time.
+
+When a re-allocation is performed it is turned into an optimal request to save time in the future. The requested digit count is
+padded upwards to 2nd multiple of \textbf{MP\_PREC} larger than \textbf{alloc} (line @25, size@). The XREALLOC function is used
+to re-allocate the memory. As per the other functions XREALLOC is actually a macro which evaluates to realloc by default. The realloc
+function leaves the base of the allocation intact which means the first \textbf{alloc} digits of the mp\_int are the same as before
+the re-allocation. All that is left is to clear the newly allocated digits and return.
+
+Note that the re-allocation result is actually stored in a temporary pointer $tmp$. This is to allow this function to return
+an error with a valid pointer. Earlier releases of the library stored the result of XREALLOC into the mp\_int $a$. That would
+result in a memory leak if XREALLOC ever failed.
+
+\subsection{Initializing Variable Precision mp\_ints}
+Occasionally the number of digits required will be known in advance of an initialization, based on, for example, the size
+of input mp\_ints to a given algorithm. The purpose of algorithm mp\_init\_size is similar to mp\_init except that it
+will allocate \textit{at least} a specified number of digits.
+
+\begin{figure}[here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_init\_size}. \\
+\textbf{Input}. An mp\_int $a$ and the requested number of digits $b$. \\
+\textbf{Output}. $a$ is initialized to hold at least $b$ digits. \\
+\hline \\
+1. $u \leftarrow b \mbox{ (mod }MP\_PREC\mbox{)}$ \\
+2. $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\
+3. Allocate $v$ digits. \\
+4. for $n$ from $0$ to $v - 1$ do \\
+\hspace{3mm}4.1 $a_n \leftarrow 0$ \\
+5. $a.sign \leftarrow MP\_ZPOS$\\
+6. $a.used \leftarrow 0$\\
+7. $a.alloc \leftarrow v$\\
+8. Return(\textit{MP\_OKAY})\\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_init\_size}
+\end{figure}
+
+\textbf{Algorithm mp\_init\_size.}
+This algorithm will initialize an mp\_int structure $a$ like algorithm mp\_init with the exception that the number of
+digits allocated can be controlled by the second input argument $b$. The input size is padded upwards so it is a
+multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} digits. This padding is used to prevent trivial
+allocations from becoming a bottleneck in the rest of the algorithms.
+
+Like algorithm mp\_init, the mp\_int structure is initialized to a default state representing the integer zero. This
+particular algorithm is useful if it is known ahead of time the approximate size of the input. If the approximation is
+correct no further memory re-allocations are required to work with the mp\_int.
+
+EXAM,bn_mp_init_size.c
+
+The number of digits $b$ requested is padded (line @22,MP_PREC@) by first augmenting it to the next multiple of
+\textbf{MP\_PREC} and then adding \textbf{MP\_PREC} to the result. If the memory can be successfully allocated the
+mp\_int is placed in a default state representing the integer zero. Otherwise, the error code \textbf{MP\_MEM} will be
+returned (line @27,return@).
+
+The digits are allocated and set to zero at the same time with the calloc() function (line @25,XCALLOC@). The
+\textbf{used} count is set to zero, the \textbf{alloc} count set to the padded digit count and the \textbf{sign} flag set
+to \textbf{MP\_ZPOS} to achieve a default valid mp\_int state (lines @29,used@, @30,alloc@ and @31,sign@). If the function
+returns succesfully then it is correct to assume that the mp\_int structure is in a valid state for the remainder of the
+functions to work with.
+
+\subsection{Multiple Integer Initializations and Clearings}
+Occasionally a function will require a series of mp\_int data types to be made available simultaneously.
+The purpose of algorithm mp\_init\_multi is to initialize a variable length array of mp\_int structures in a single
+statement. It is essentially a shortcut to multiple initializations.
+
+\newpage\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_init\_multi}. \\
+\textbf{Input}. Variable length array $V_k$ of mp\_int variables of length $k$. \\
+\textbf{Output}. The array is initialized such that each mp\_int of $V_k$ is ready to use. \\
+\hline \\
+1. for $n$ from 0 to $k - 1$ do \\
+\hspace{+3mm}1.1. Initialize the mp\_int $V_n$ (\textit{mp\_init}) \\
+\hspace{+3mm}1.2. If initialization failed then do \\
+\hspace{+6mm}1.2.1. for $j$ from $0$ to $n$ do \\
+\hspace{+9mm}1.2.1.1. Free the mp\_int $V_j$ (\textit{mp\_clear}) \\
+\hspace{+6mm}1.2.2. Return(\textit{MP\_MEM}) \\
+2. Return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_init\_multi}
+\end{figure}
+
+\textbf{Algorithm mp\_init\_multi.}
+The algorithm will initialize the array of mp\_int variables one at a time. If a runtime error has been detected
+(\textit{step 1.2}) all of the previously initialized variables are cleared. The goal is an ``all or nothing''
+initialization which allows for quick recovery from runtime errors.
+
+EXAM,bn_mp_init_multi.c
+
+This function intializes a variable length list of mp\_int structure pointers. However, instead of having the mp\_int
+structures in an actual C array they are simply passed as arguments to the function. This function makes use of the
+``...'' argument syntax of the C programming language. The list is terminated with a final \textbf{NULL} argument
+appended on the right.
+
+The function uses the ``stdarg.h'' \textit{va} functions to step portably through the arguments to the function. A count
+$n$ of succesfully initialized mp\_int structures is maintained (line @47,n++@) such that if a failure does occur,
+the algorithm can backtrack and free the previously initialized structures (lines @27,if@ to @46,}@).
+
+
+\subsection{Clamping Excess Digits}
+When a function anticipates a result will be $n$ digits it is simpler to assume this is true within the body of
+the function instead of checking during the computation. For example, a multiplication of a $i$ digit number by a
+$j$ digit produces a result of at most $i + j$ digits. It is entirely possible that the result is $i + j - 1$
+though, with no final carry into the last position. However, suppose the destination had to be first expanded
+(\textit{via mp\_grow}) to accomodate $i + j - 1$ digits than further expanded to accomodate the final carry.
+That would be a considerable waste of time since heap operations are relatively slow.
+
+The ideal solution is to always assume the result is $i + j$ and fix up the \textbf{used} count after the function
+terminates. This way a single heap operation (\textit{at most}) is required. However, if the result was not checked
+there would be an excess high order zero digit.
+
+For example, suppose the product of two integers was $x_n = (0x_{n-1}x_{n-2}...x_0)_{\beta}$. The leading zero digit
+will not contribute to the precision of the result. In fact, through subsequent operations more leading zero digits would
+accumulate to the point the size of the integer would be prohibitive. As a result even though the precision is very
+low the representation is excessively large.
+
+The mp\_clamp algorithm is designed to solve this very problem. It will trim high-order zeros by decrementing the
+\textbf{used} count until a non-zero most significant digit is found. Also in this system, zero is considered to be a
+positive number which means that if the \textbf{used} count is decremented to zero, the sign must be set to
+\textbf{MP\_ZPOS}.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_clamp}. \\
+\textbf{Input}. An mp\_int $a$ \\
+\textbf{Output}. Any excess leading zero digits of $a$ are removed \\
+\hline \\
+1. while $a.used > 0$ and $a_{a.used - 1} = 0$ do \\
+\hspace{+3mm}1.1 $a.used \leftarrow a.used - 1$ \\
+2. if $a.used = 0$ then do \\
+\hspace{+3mm}2.1 $a.sign \leftarrow MP\_ZPOS$ \\
+\hline \\
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_clamp}
+\end{figure}
+
+\textbf{Algorithm mp\_clamp.}
+As can be expected this algorithm is very simple. The loop on step one is expected to iterate only once or twice at
+the most. For example, this will happen in cases where there is not a carry to fill the last position. Step two fixes the sign for
+when all of the digits are zero to ensure that the mp\_int is valid at all times.
+
+EXAM,bn_mp_clamp.c
+
+Note on line @27,while@ how to test for the \textbf{used} count is made on the left of the \&\& operator. In the C programming
+language the terms to \&\& are evaluated left to right with a boolean short-circuit if any condition fails. This is
+important since if the \textbf{used} is zero the test on the right would fetch below the array. That is obviously
+undesirable. The parenthesis on line @28,a->used@ is used to make sure the \textbf{used} count is decremented and not
+the pointer ``a''.
+
+\section*{Exercises}
+\begin{tabular}{cl}
+$\left [ 1 \right ]$ & Discuss the relevance of the \textbf{used} member of the mp\_int structure. \\
+ & \\
+$\left [ 1 \right ]$ & Discuss the consequences of not using padding when performing allocations. \\
+ & \\
+$\left [ 2 \right ]$ & Estimate an ideal value for \textbf{MP\_PREC} when performing 1024-bit RSA \\
+ & encryption when $\beta = 2^{28}$. \\
+ & \\
+$\left [ 1 \right ]$ & Discuss the relevance of the algorithm mp\_clamp. What does it prevent? \\
+ & \\
+$\left [ 1 \right ]$ & Give an example of when the algorithm mp\_init\_copy might be useful. \\
+ & \\
+\end{tabular}
+
+
+%%%
+% CHAPTER FOUR
+%%%
+
+\chapter{Basic Operations}
+
+\section{Introduction}
+In the previous chapter a series of low level algorithms were established that dealt with initializing and maintaining
+mp\_int structures. This chapter will discuss another set of seemingly non-algebraic algorithms which will form the low
+level basis of the entire library. While these algorithm are relatively trivial it is important to understand how they
+work before proceeding since these algorithms will be used almost intrinsically in the following chapters.
+
+The algorithms in this chapter deal primarily with more ``programmer'' related tasks such as creating copies of
+mp\_int structures, assigning small values to mp\_int structures and comparisons of the values mp\_int structures
+represent.
+
+\section{Assigning Values to mp\_int Structures}
+\subsection{Copying an mp\_int}
+Assigning the value that a given mp\_int structure represents to another mp\_int structure shall be known as making
+a copy for the purposes of this text. The copy of the mp\_int will be a separate entity that represents the same
+value as the mp\_int it was copied from. The mp\_copy algorithm provides this functionality.
+
+\newpage\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_copy}. \\
+\textbf{Input}. An mp\_int $a$ and $b$. \\
+\textbf{Output}. Store a copy of $a$ in $b$. \\
+\hline \\
+1. If $b.alloc < a.used$ then grow $b$ to $a.used$ digits. (\textit{mp\_grow}) \\
+2. for $n$ from 0 to $a.used - 1$ do \\
+\hspace{3mm}2.1 $b_{n} \leftarrow a_{n}$ \\
+3. for $n$ from $a.used$ to $b.used - 1$ do \\
+\hspace{3mm}3.1 $b_{n} \leftarrow 0$ \\
+4. $b.used \leftarrow a.used$ \\
+5. $b.sign \leftarrow a.sign$ \\
+6. return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_copy}
+\end{figure}
+
+\textbf{Algorithm mp\_copy.}
+This algorithm copies the mp\_int $a$ such that upon succesful termination of the algorithm the mp\_int $b$ will
+represent the same integer as the mp\_int $a$. The mp\_int $b$ shall be a complete and distinct copy of the
+mp\_int $a$ meaing that the mp\_int $a$ can be modified and it shall not affect the value of the mp\_int $b$.
+
+If $b$ does not have enough room for the digits of $a$ it must first have its precision augmented via the mp\_grow
+algorithm. The digits of $a$ are copied over the digits of $b$ and any excess digits of $b$ are set to zero (step two
+and three). The \textbf{used} and \textbf{sign} members of $a$ are finally copied over the respective members of
+$b$.
+
+\textbf{Remark.} This algorithm also introduces a new idiosyncrasy that will be used throughout the rest of the
+text. The error return codes of other algorithms are not explicitly checked in the pseudo-code presented. For example, in
+step one of the mp\_copy algorithm the return of mp\_grow is not explicitly checked to ensure it succeeded. Text space is
+limited so it is assumed that if a algorithm fails it will clear all temporarily allocated mp\_ints and return
+the error code itself. However, the C code presented will demonstrate all of the error handling logic required to
+implement the pseudo-code.
+
+EXAM,bn_mp_copy.c
+
+Occasionally a dependent algorithm may copy an mp\_int effectively into itself such as when the input and output
+mp\_int structures passed to a function are one and the same. For this case it is optimal to return immediately without
+copying digits (line @24,a == b@).
+
+The mp\_int $b$ must have enough digits to accomodate the used digits of the mp\_int $a$. If $b.alloc$ is less than
+$a.used$ the algorithm mp\_grow is used to augment the precision of $b$ (lines @29,alloc@ to @33,}@). In order to
+simplify the inner loop that copies the digits from $a$ to $b$, two aliases $tmpa$ and $tmpb$ point directly at the digits
+of the mp\_ints $a$ and $b$ respectively. These aliases (lines @42,tmpa@ and @45,tmpb@) allow the compiler to access the digits without first dereferencing the
+mp\_int pointers and then subsequently the pointer to the digits.
+
+After the aliases are established the digits from $a$ are copied into $b$ (lines @48,for@ to @50,}@) and then the excess
+digits of $b$ are set to zero (lines @53,for@ to @55,}@). Both ``for'' loops make use of the pointer aliases and in
+fact the alias for $b$ is carried through into the second ``for'' loop to clear the excess digits. This optimization
+allows the alias to stay in a machine register fairly easy between the two loops.
+
+\textbf{Remarks.} The use of pointer aliases is an implementation methodology first introduced in this function that will
+be used considerably in other functions. Technically, a pointer alias is simply a short hand alias used to lower the
+number of pointer dereferencing operations required to access data. For example, a for loop may resemble
+
+\begin{alltt}
+for (x = 0; x < 100; x++) \{
+ a->num[4]->dp[x] = 0;
+\}
+\end{alltt}
+
+This could be re-written using aliases as
+
+\begin{alltt}
+mp_digit *tmpa;
+a = a->num[4]->dp;
+for (x = 0; x < 100; x++) \{
+ *a++ = 0;
+\}
+\end{alltt}
+
+In this case an alias is used to access the
+array of digits within an mp\_int structure directly. It may seem that a pointer alias is strictly not required
+as a compiler may optimize out the redundant pointer operations. However, there are two dominant reasons to use aliases.
+
+The first reason is that most compilers will not effectively optimize pointer arithmetic. For example, some optimizations
+may work for the Microsoft Visual C++ compiler (MSVC) and not for the GNU C Compiler (GCC). Also some optimizations may
+work for GCC and not MSVC. As such it is ideal to find a common ground for as many compilers as possible. Pointer
+aliases optimize the code considerably before the compiler even reads the source code which means the end compiled code
+stands a better chance of being faster.
+
+The second reason is that pointer aliases often can make an algorithm simpler to read. Consider the first ``for''
+loop of the function mp\_copy() re-written to not use pointer aliases.
+
+\begin{alltt}
+ /* copy all the digits */
+ for (n = 0; n < a->used; n++) \{
+ b->dp[n] = a->dp[n];
+ \}
+\end{alltt}
+
+Whether this code is harder to read depends strongly on the individual. However, it is quantifiably slightly more
+complicated as there are four variables within the statement instead of just two.
+
+\subsubsection{Nested Statements}
+Another commonly used technique in the source routines is that certain sections of code are nested. This is used in
+particular with the pointer aliases to highlight code phases. For example, a Comba multiplier (discussed in chapter six)
+will typically have three different phases. First the temporaries are initialized, then the columns calculated and
+finally the carries are propagated. In this example the middle column production phase will typically be nested as it
+uses temporary variables and aliases the most.
+
+The nesting also simplies the source code as variables that are nested are only valid for their scope. As a result
+the various temporary variables required do not propagate into other sections of code.
+
+
+\subsection{Creating a Clone}
+Another common operation is to make a local temporary copy of an mp\_int argument. To initialize an mp\_int
+and then copy another existing mp\_int into the newly intialized mp\_int will be known as creating a clone. This is
+useful within functions that need to modify an argument but do not wish to actually modify the original copy. The
+mp\_init\_copy algorithm has been designed to help perform this task.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_init\_copy}. \\
+\textbf{Input}. An mp\_int $a$ and $b$\\
+\textbf{Output}. $a$ is initialized to be a copy of $b$. \\
+\hline \\
+1. Init $a$. (\textit{mp\_init}) \\
+2. Copy $b$ to $a$. (\textit{mp\_copy}) \\
+3. Return the status of the copy operation. \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_init\_copy}
+\end{figure}
+
+\textbf{Algorithm mp\_init\_copy.}
+This algorithm will initialize an mp\_int variable and copy another previously initialized mp\_int variable into it. As
+such this algorithm will perform two operations in one step.
+
+EXAM,bn_mp_init_copy.c
+
+This will initialize \textbf{a} and make it a verbatim copy of the contents of \textbf{b}. Note that
+\textbf{a} will have its own memory allocated which means that \textbf{b} may be cleared after the call
+and \textbf{a} will be left intact.
+
+\section{Zeroing an Integer}
+Reseting an mp\_int to the default state is a common step in many algorithms. The mp\_zero algorithm will be the algorithm used to
+perform this task.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_zero}. \\
+\textbf{Input}. An mp\_int $a$ \\
+\textbf{Output}. Zero the contents of $a$ \\
+\hline \\
+1. $a.used \leftarrow 0$ \\
+2. $a.sign \leftarrow$ MP\_ZPOS \\
+3. for $n$ from 0 to $a.alloc - 1$ do \\
+\hspace{3mm}3.1 $a_n \leftarrow 0$ \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_zero}
+\end{figure}
+
+\textbf{Algorithm mp\_zero.}
+This algorithm simply resets a mp\_int to the default state.
+
+EXAM,bn_mp_zero.c
+
+After the function is completed, all of the digits are zeroed, the \textbf{used} count is zeroed and the
+\textbf{sign} variable is set to \textbf{MP\_ZPOS}.
+
+\section{Sign Manipulation}
+\subsection{Absolute Value}
+With the mp\_int representation of an integer, calculating the absolute value is trivial. The mp\_abs algorithm will compute
+the absolute value of an mp\_int.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_abs}. \\
+\textbf{Input}. An mp\_int $a$ \\
+\textbf{Output}. Computes $b = \vert a \vert$ \\
+\hline \\
+1. Copy $a$ to $b$. (\textit{mp\_copy}) \\
+2. If the copy failed return(\textit{MP\_MEM}). \\
+3. $b.sign \leftarrow MP\_ZPOS$ \\
+4. Return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_abs}
+\end{figure}
+
+\textbf{Algorithm mp\_abs.}
+This algorithm computes the absolute of an mp\_int input. First it copies $a$ over $b$. This is an example of an
+algorithm where the check in mp\_copy that determines if the source and destination are equal proves useful. This allows,
+for instance, the developer to pass the same mp\_int as the source and destination to this function without addition
+logic to handle it.
+
+EXAM,bn_mp_abs.c
+
+This fairly trivial algorithm first eliminates non--required duplications (line @27,a != b@) and then sets the
+\textbf{sign} flag to \textbf{MP\_ZPOS}.
+
+\subsection{Integer Negation}
+With the mp\_int representation of an integer, calculating the negation is also trivial. The mp\_neg algorithm will compute
+the negative of an mp\_int input.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_neg}. \\
+\textbf{Input}. An mp\_int $a$ \\
+\textbf{Output}. Computes $b = -a$ \\
+\hline \\
+1. Copy $a$ to $b$. (\textit{mp\_copy}) \\
+2. If the copy failed return(\textit{MP\_MEM}). \\
+3. If $a.used = 0$ then return(\textit{MP\_OKAY}). \\
+4. If $a.sign = MP\_ZPOS$ then do \\
+\hspace{3mm}4.1 $b.sign = MP\_NEG$. \\
+5. else do \\
+\hspace{3mm}5.1 $b.sign = MP\_ZPOS$. \\
+6. Return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_neg}
+\end{figure}
+
+\textbf{Algorithm mp\_neg.}
+This algorithm computes the negation of an input. First it copies $a$ over $b$. If $a$ has no used digits then
+the algorithm returns immediately. Otherwise it flips the sign flag and stores the result in $b$. Note that if
+$a$ had no digits then it must be positive by definition. Had step three been omitted then the algorithm would return
+zero as negative.
+
+EXAM,bn_mp_neg.c
+
+Like mp\_abs() this function avoids non--required duplications (line @21,a != b@) and then sets the sign. We
+have to make sure that only non--zero values get a \textbf{sign} of \textbf{MP\_NEG}. If the mp\_int is zero
+than the \textbf{sign} is hard--coded to \textbf{MP\_ZPOS}.
+
+\section{Small Constants}
+\subsection{Setting Small Constants}
+Often a mp\_int must be set to a relatively small value such as $1$ or $2$. For these cases the mp\_set algorithm is useful.
+
+\newpage\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_set}. \\
+\textbf{Input}. An mp\_int $a$ and a digit $b$ \\
+\textbf{Output}. Make $a$ equivalent to $b$ \\
+\hline \\
+1. Zero $a$ (\textit{mp\_zero}). \\
+2. $a_0 \leftarrow b \mbox{ (mod }\beta\mbox{)}$ \\
+3. $a.used \leftarrow \left \lbrace \begin{array}{ll}
+ 1 & \mbox{if }a_0 > 0 \\
+ 0 & \mbox{if }a_0 = 0
+ \end{array} \right .$ \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_set}
+\end{figure}
+
+\textbf{Algorithm mp\_set.}
+This algorithm sets a mp\_int to a small single digit value. Step number 1 ensures that the integer is reset to the default state. The
+single digit is set (\textit{modulo $\beta$}) and the \textbf{used} count is adjusted accordingly.
+
+EXAM,bn_mp_set.c
+
+First we zero (line @21,mp_zero@) the mp\_int to make sure that the other members are initialized for a
+small positive constant. mp\_zero() ensures that the \textbf{sign} is positive and the \textbf{used} count
+is zero. Next we set the digit and reduce it modulo $\beta$ (line @22,MP_MASK@). After this step we have to
+check if the resulting digit is zero or not. If it is not then we set the \textbf{used} count to one, otherwise
+to zero.
+
+We can quickly reduce modulo $\beta$ since it is of the form $2^k$ and a quick binary AND operation with
+$2^k - 1$ will perform the same operation.
+
+One important limitation of this function is that it will only set one digit. The size of a digit is not fixed, meaning source that uses
+this function should take that into account. Only trivially small constants can be set using this function.
+
+\subsection{Setting Large Constants}
+To overcome the limitations of the mp\_set algorithm the mp\_set\_int algorithm is ideal. It accepts a ``long''
+data type as input and will always treat it as a 32-bit integer.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_set\_int}. \\
+\textbf{Input}. An mp\_int $a$ and a ``long'' integer $b$ \\
+\textbf{Output}. Make $a$ equivalent to $b$ \\
+\hline \\
+1. Zero $a$ (\textit{mp\_zero}) \\
+2. for $n$ from 0 to 7 do \\
+\hspace{3mm}2.1 $a \leftarrow a \cdot 16$ (\textit{mp\_mul2d}) \\
+\hspace{3mm}2.2 $u \leftarrow \lfloor b / 2^{4(7 - n)} \rfloor \mbox{ (mod }16\mbox{)}$\\
+\hspace{3mm}2.3 $a_0 \leftarrow a_0 + u$ \\
+\hspace{3mm}2.4 $a.used \leftarrow a.used + 1$ \\
+3. Clamp excess used digits (\textit{mp\_clamp}) \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_set\_int}
+\end{figure}
+
+\textbf{Algorithm mp\_set\_int.}
+The algorithm performs eight iterations of a simple loop where in each iteration four bits from the source are added to the
+mp\_int. Step 2.1 will multiply the current result by sixteen making room for four more bits in the less significant positions. In step 2.2 the
+next four bits from the source are extracted and are added to the mp\_int. The \textbf{used} digit count is
+incremented to reflect the addition. The \textbf{used} digit counter is incremented since if any of the leading digits were zero the mp\_int would have
+zero digits used and the newly added four bits would be ignored.
+
+Excess zero digits are trimmed in steps 2.1 and 3 by using higher level algorithms mp\_mul2d and mp\_clamp.
+
+EXAM,bn_mp_set_int.c
+
+This function sets four bits of the number at a time to handle all practical \textbf{DIGIT\_BIT} sizes. The weird
+addition on line @38,a->used@ ensures that the newly added in bits are added to the number of digits. While it may not
+seem obvious as to why the digit counter does not grow exceedingly large it is because of the shift on line @27,mp_mul_2d@
+as well as the call to mp\_clamp() on line @40,mp_clamp@. Both functions will clamp excess leading digits which keeps
+the number of used digits low.
+
+\section{Comparisons}
+\subsection{Unsigned Comparisions}
+Comparing a multiple precision integer is performed with the exact same algorithm used to compare two decimal numbers. For example,
+to compare $1,234$ to $1,264$ the digits are extracted by their positions. That is we compare $1 \cdot 10^3 + 2 \cdot 10^2 + 3 \cdot 10^1 + 4 \cdot 10^0$
+to $1 \cdot 10^3 + 2 \cdot 10^2 + 6 \cdot 10^1 + 4 \cdot 10^0$ by comparing single digits at a time starting with the highest magnitude
+positions. If any leading digit of one integer is greater than a digit in the same position of another integer then obviously it must be greater.
+
+The first comparision routine that will be developed is the unsigned magnitude compare which will perform a comparison based on the digits of two
+mp\_int variables alone. It will ignore the sign of the two inputs. Such a function is useful when an absolute comparison is required or if the
+signs are known to agree in advance.
+
+To facilitate working with the results of the comparison functions three constants are required.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{|r|l|}
+\hline \textbf{Constant} & \textbf{Meaning} \\
+\hline \textbf{MP\_GT} & Greater Than \\
+\hline \textbf{MP\_EQ} & Equal To \\
+\hline \textbf{MP\_LT} & Less Than \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Comparison Return Codes}
+\end{figure}
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_cmp\_mag}. \\
+\textbf{Input}. Two mp\_ints $a$ and $b$. \\
+\textbf{Output}. Unsigned comparison results ($a$ to the left of $b$). \\
+\hline \\
+1. If $a.used > b.used$ then return(\textit{MP\_GT}) \\
+2. If $a.used < b.used$ then return(\textit{MP\_LT}) \\
+3. for n from $a.used - 1$ to 0 do \\
+\hspace{+3mm}3.1 if $a_n > b_n$ then return(\textit{MP\_GT}) \\
+\hspace{+3mm}3.2 if $a_n < b_n$ then return(\textit{MP\_LT}) \\
+4. Return(\textit{MP\_EQ}) \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_cmp\_mag}
+\end{figure}
+
+\textbf{Algorithm mp\_cmp\_mag.}
+By saying ``$a$ to the left of $b$'' it is meant that the comparison is with respect to $a$, that is if $a$ is greater than $b$ it will return
+\textbf{MP\_GT} and similar with respect to when $a = b$ and $a < b$. The first two steps compare the number of digits used in both $a$ and $b$.
+Obviously if the digit counts differ there would be an imaginary zero digit in the smaller number where the leading digit of the larger number is.
+If both have the same number of digits than the actual digits themselves must be compared starting at the leading digit.
+
+By step three both inputs must have the same number of digits so its safe to start from either $a.used - 1$ or $b.used - 1$ and count down to
+the zero'th digit. If after all of the digits have been compared, no difference is found, the algorithm returns \textbf{MP\_EQ}.
+
+EXAM,bn_mp_cmp_mag.c
+
+The two if statements (lines @24,if@ and @28,if@) compare the number of digits in the two inputs. These two are
+performed before all of the digits are compared since it is a very cheap test to perform and can potentially save
+considerable time. The implementation given is also not valid without those two statements. $b.alloc$ may be
+smaller than $a.used$, meaning that undefined values will be read from $b$ past the end of the array of digits.
+
+
+
+\subsection{Signed Comparisons}
+Comparing with sign considerations is also fairly critical in several routines (\textit{division for example}). Based on an unsigned magnitude
+comparison a trivial signed comparison algorithm can be written.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_cmp}. \\
+\textbf{Input}. Two mp\_ints $a$ and $b$ \\
+\textbf{Output}. Signed Comparison Results ($a$ to the left of $b$) \\
+\hline \\
+1. if $a.sign = MP\_NEG$ and $b.sign = MP\_ZPOS$ then return(\textit{MP\_LT}) \\
+2. if $a.sign = MP\_ZPOS$ and $b.sign = MP\_NEG$ then return(\textit{MP\_GT}) \\
+3. if $a.sign = MP\_NEG$ then \\
+\hspace{+3mm}3.1 Return the unsigned comparison of $b$ and $a$ (\textit{mp\_cmp\_mag}) \\
+4 Otherwise \\
+\hspace{+3mm}4.1 Return the unsigned comparison of $a$ and $b$ \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_cmp}
+\end{figure}
+
+\textbf{Algorithm mp\_cmp.}
+The first two steps compare the signs of the two inputs. If the signs do not agree then it can return right away with the appropriate
+comparison code. When the signs are equal the digits of the inputs must be compared to determine the correct result. In step
+three the unsigned comparision flips the order of the arguments since they are both negative. For instance, if $-a > -b$ then
+$\vert a \vert < \vert b \vert$. Step number four will compare the two when they are both positive.
+
+EXAM,bn_mp_cmp.c
+
+The two if statements (lines @22,if@ and @26,if@) perform the initial sign comparison. If the signs are not the equal then which ever
+has the positive sign is larger. The inputs are compared (line @30,if@) based on magnitudes. If the signs were both
+negative then the unsigned comparison is performed in the opposite direction (line @31,mp_cmp_mag@). Otherwise, the signs are assumed to
+be both positive and a forward direction unsigned comparison is performed.
+
+\section*{Exercises}
+\begin{tabular}{cl}
+$\left [ 2 \right ]$ & Modify algorithm mp\_set\_int to accept as input a variable length array of bits. \\
+ & \\
+$\left [ 3 \right ]$ & Give the probability that algorithm mp\_cmp\_mag will have to compare $k$ digits \\
+ & of two random digits (of equal magnitude) before a difference is found. \\
+ & \\
+$\left [ 1 \right ]$ & Suggest a simple method to speed up the implementation of mp\_cmp\_mag based \\
+ & on the observations made in the previous problem. \\
+ &
+\end{tabular}
+
+\chapter{Basic Arithmetic}
+\section{Introduction}
+At this point algorithms for initialization, clearing, zeroing, copying, comparing and setting small constants have been
+established. The next logical set of algorithms to develop are addition, subtraction and digit shifting algorithms. These
+algorithms make use of the lower level algorithms and are the cruicial building block for the multiplication algorithms. It is very important
+that these algorithms are highly optimized. On their own they are simple $O(n)$ algorithms but they can be called from higher level algorithms
+which easily places them at $O(n^2)$ or even $O(n^3)$ work levels.
+
+MARK,SHIFTS
+All of the algorithms within this chapter make use of the logical bit shift operations denoted by $<<$ and $>>$ for left and right
+logical shifts respectively. A logical shift is analogous to sliding the decimal point of radix-10 representations. For example, the real
+number $0.9345$ is equivalent to $93.45\%$ which is found by sliding the the decimal two places to the right (\textit{multiplying by $\beta^2 = 10^2$}).
+Algebraically a binary logical shift is equivalent to a division or multiplication by a power of two.
+For example, $a << k = a \cdot 2^k$ while $a >> k = \lfloor a/2^k \rfloor$.
+
+One significant difference between a logical shift and the way decimals are shifted is that digits below the zero'th position are removed
+from the number. For example, consider $1101_2 >> 1$ using decimal notation this would produce $110.1_2$. However, with a logical shift the
+result is $110_2$.
+
+\section{Addition and Subtraction}
+In common twos complement fixed precision arithmetic negative numbers are easily represented by subtraction from the modulus. For example, with 32-bit integers
+$a - b\mbox{ (mod }2^{32}\mbox{)}$ is the same as $a + (2^{32} - b) \mbox{ (mod }2^{32}\mbox{)}$ since $2^{32} \equiv 0 \mbox{ (mod }2^{32}\mbox{)}$.
+As a result subtraction can be performed with a trivial series of logical operations and an addition.
+
+However, in multiple precision arithmetic negative numbers are not represented in the same way. Instead a sign flag is used to keep track of the
+sign of the integer. As a result signed addition and subtraction are actually implemented as conditional usage of lower level addition or
+subtraction algorithms with the sign fixed up appropriately.
+
+The lower level algorithms will add or subtract integers without regard to the sign flag. That is they will add or subtract the magnitude of
+the integers respectively.
+
+\subsection{Low Level Addition}
+An unsigned addition of multiple precision integers is performed with the same long-hand algorithm used to add decimal numbers. That is to add the
+trailing digits first and propagate the resulting carry upwards. Since this is a lower level algorithm the name will have a ``s\_'' prefix.
+Historically that convention stems from the MPI library where ``s\_'' stood for static functions that were hidden from the developer entirely.
+
+\newpage
+\begin{figure}[!here]
+\begin{center}
+\begin{small}
+\begin{tabular}{l}
+\hline Algorithm \textbf{s\_mp\_add}. \\
+\textbf{Input}. Two mp\_ints $a$ and $b$ \\
+\textbf{Output}. The unsigned addition $c = \vert a \vert + \vert b \vert$. \\
+\hline \\
+1. if $a.used > b.used$ then \\
+\hspace{+3mm}1.1 $min \leftarrow b.used$ \\
+\hspace{+3mm}1.2 $max \leftarrow a.used$ \\
+\hspace{+3mm}1.3 $x \leftarrow a$ \\
+2. else \\
+\hspace{+3mm}2.1 $min \leftarrow a.used$ \\
+\hspace{+3mm}2.2 $max \leftarrow b.used$ \\
+\hspace{+3mm}2.3 $x \leftarrow b$ \\
+3. If $c.alloc < max + 1$ then grow $c$ to hold at least $max + 1$ digits (\textit{mp\_grow}) \\
+4. $oldused \leftarrow c.used$ \\
+5. $c.used \leftarrow max + 1$ \\
+6. $u \leftarrow 0$ \\
+7. for $n$ from $0$ to $min - 1$ do \\
+\hspace{+3mm}7.1 $c_n \leftarrow a_n + b_n + u$ \\
+\hspace{+3mm}7.2 $u \leftarrow c_n >> lg(\beta)$ \\
+\hspace{+3mm}7.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
+8. if $min \ne max$ then do \\
+\hspace{+3mm}8.1 for $n$ from $min$ to $max - 1$ do \\
+\hspace{+6mm}8.1.1 $c_n \leftarrow x_n + u$ \\
+\hspace{+6mm}8.1.2 $u \leftarrow c_n >> lg(\beta)$ \\
+\hspace{+6mm}8.1.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
+9. $c_{max} \leftarrow u$ \\
+10. if $olduse > max$ then \\
+\hspace{+3mm}10.1 for $n$ from $max + 1$ to $oldused - 1$ do \\
+\hspace{+6mm}10.1.1 $c_n \leftarrow 0$ \\
+11. Clamp excess digits in $c$. (\textit{mp\_clamp}) \\
+12. Return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{small}
+\end{center}
+\caption{Algorithm s\_mp\_add}
+\end{figure}
+
+\textbf{Algorithm s\_mp\_add.}
+This algorithm is loosely based on algorithm 14.7 of HAC \cite[pp. 594]{HAC} but has been extended to allow the inputs to have different magnitudes.
+Coincidentally the description of algorithm A in Knuth \cite[pp. 266]{TAOCPV2} shares the same deficiency as the algorithm from \cite{HAC}. Even the
+MIX pseudo machine code presented by Knuth \cite[pp. 266-267]{TAOCPV2} is incapable of handling inputs which are of different magnitudes.
+
+The first thing that has to be accomplished is to sort out which of the two inputs is the largest. The addition logic
+will simply add all of the smallest input to the largest input and store that first part of the result in the
+destination. Then it will apply a simpler addition loop to excess digits of the larger input.
+
+The first two steps will handle sorting the inputs such that $min$ and $max$ hold the digit counts of the two
+inputs. The variable $x$ will be an mp\_int alias for the largest input or the second input $b$ if they have the
+same number of digits. After the inputs are sorted the destination $c$ is grown as required to accomodate the sum
+of the two inputs. The original \textbf{used} count of $c$ is copied and set to the new used count.
+
+At this point the first addition loop will go through as many digit positions that both inputs have. The carry
+variable $\mu$ is set to zero outside the loop. Inside the loop an ``addition'' step requires three statements to produce
+one digit of the summand. First
+two digits from $a$ and $b$ are added together along with the carry $\mu$. The carry of this step is extracted and stored
+in $\mu$ and finally the digit of the result $c_n$ is truncated within the range $0 \le c_n < \beta$.
+
+Now all of the digit positions that both inputs have in common have been exhausted. If $min \ne max$ then $x$ is an alias
+for one of the inputs that has more digits. A simplified addition loop is then used to essentially copy the remaining digits
+and the carry to the destination.
+
+The final carry is stored in $c_{max}$ and digits above $max$ upto $oldused$ are zeroed which completes the addition.
+
+
+EXAM,bn_s_mp_add.c
+
+We first sort (lines @27,if@ to @35,}@) the inputs based on magnitude and determine the $min$ and $max$ variables.
+Note that $x$ is a pointer to an mp\_int assigned to the largest input, in effect it is a local alias. Next we
+grow the destination (@37,init@ to @42,}@) ensure that it can accomodate the result of the addition.
+
+Similar to the implementation of mp\_copy this function uses the braced code and local aliases coding style. The three aliases that are on
+lines @56,tmpa@, @59,tmpb@ and @62,tmpc@ represent the two inputs and destination variables respectively. These aliases are used to ensure the
+compiler does not have to dereference $a$, $b$ or $c$ (respectively) to access the digits of the respective mp\_int.
+
+The initial carry $u$ will be cleared (line @65,u = 0@), note that $u$ is of type mp\_digit which ensures type
+compatibility within the implementation. The initial addition (line @66,for@ to @75,}@) adds digits from
+both inputs until the smallest input runs out of digits. Similarly the conditional addition loop
+(line @81,for@ to @90,}@) adds the remaining digits from the larger of the two inputs. The addition is finished
+with the final carry being stored in $tmpc$ (line @94,tmpc++@). Note the ``++'' operator within the same expression.
+After line @94,tmpc++@, $tmpc$ will point to the $c.used$'th digit of the mp\_int $c$. This is useful
+for the next loop (line @97,for@ to @99,}@) which set any old upper digits to zero.
+
+\subsection{Low Level Subtraction}
+The low level unsigned subtraction algorithm is very similar to the low level unsigned addition algorithm. The principle difference is that the
+unsigned subtraction algorithm requires the result to be positive. That is when computing $a - b$ the condition $\vert a \vert \ge \vert b\vert$ must
+be met for this algorithm to function properly. Keep in mind this low level algorithm is not meant to be used in higher level algorithms directly.
+This algorithm as will be shown can be used to create functional signed addition and subtraction algorithms.
+
+MARK,GAMMA
+
+For this algorithm a new variable is required to make the description simpler. Recall from section 1.3.1 that a mp\_digit must be able to represent
+the range $0 \le x < 2\beta$ for the algorithms to work correctly. However, it is allowable that a mp\_digit represent a larger range of values. For
+this algorithm we will assume that the variable $\gamma$ represents the number of bits available in a
+mp\_digit (\textit{this implies $2^{\gamma} > \beta$}).
+
+For example, the default for LibTomMath is to use a ``unsigned long'' for the mp\_digit ``type'' while $\beta = 2^{28}$. In ISO C an ``unsigned long''
+data type must be able to represent $0 \le x < 2^{32}$ meaning that in this case $\gamma \ge 32$.
+
+\newpage\begin{figure}[!here]
+\begin{center}
+\begin{small}
+\begin{tabular}{l}
+\hline Algorithm \textbf{s\_mp\_sub}. \\
+\textbf{Input}. Two mp\_ints $a$ and $b$ ($\vert a \vert \ge \vert b \vert$) \\
+\textbf{Output}. The unsigned subtraction $c = \vert a \vert - \vert b \vert$. \\
+\hline \\
+1. $min \leftarrow b.used$ \\
+2. $max \leftarrow a.used$ \\
+3. If $c.alloc < max$ then grow $c$ to hold at least $max$ digits. (\textit{mp\_grow}) \\
+4. $oldused \leftarrow c.used$ \\
+5. $c.used \leftarrow max$ \\
+6. $u \leftarrow 0$ \\
+7. for $n$ from $0$ to $min - 1$ do \\
+\hspace{3mm}7.1 $c_n \leftarrow a_n - b_n - u$ \\
+\hspace{3mm}7.2 $u \leftarrow c_n >> (\gamma - 1)$ \\
+\hspace{3mm}7.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
+8. if $min < max$ then do \\
+\hspace{3mm}8.1 for $n$ from $min$ to $max - 1$ do \\
+\hspace{6mm}8.1.1 $c_n \leftarrow a_n - u$ \\
+\hspace{6mm}8.1.2 $u \leftarrow c_n >> (\gamma - 1)$ \\
+\hspace{6mm}8.1.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
+9. if $oldused > max$ then do \\
+\hspace{3mm}9.1 for $n$ from $max$ to $oldused - 1$ do \\
+\hspace{6mm}9.1.1 $c_n \leftarrow 0$ \\
+10. Clamp excess digits of $c$. (\textit{mp\_clamp}). \\
+11. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{small}
+\end{center}
+\caption{Algorithm s\_mp\_sub}
+\end{figure}
+
+\textbf{Algorithm s\_mp\_sub.}
+This algorithm performs the unsigned subtraction of two mp\_int variables under the restriction that the result must be positive. That is when
+passing variables $a$ and $b$ the condition that $\vert a \vert \ge \vert b \vert$ must be met for the algorithm to function correctly. This
+algorithm is loosely based on algorithm 14.9 \cite[pp. 595]{HAC} and is similar to algorithm S in \cite[pp. 267]{TAOCPV2} as well. As was the case
+of the algorithm s\_mp\_add both other references lack discussion concerning various practical details such as when the inputs differ in magnitude.
+
+The initial sorting of the inputs is trivial in this algorithm since $a$ is guaranteed to have at least the same magnitude of $b$. Steps 1 and 2
+set the $min$ and $max$ variables. Unlike the addition routine there is guaranteed to be no carry which means that the final result can be at
+most $max$ digits in length as opposed to $max + 1$. Similar to the addition algorithm the \textbf{used} count of $c$ is copied locally and
+set to the maximal count for the operation.
+
+The subtraction loop that begins on step seven is essentially the same as the addition loop of algorithm s\_mp\_add except single precision
+subtraction is used instead. Note the use of the $\gamma$ variable to extract the carry (\textit{also known as the borrow}) within the subtraction
+loops. Under the assumption that two's complement single precision arithmetic is used this will successfully extract the desired carry.
+
+For example, consider subtracting $0101_2$ from $0100_2$ where $\gamma = 4$ and $\beta = 2$. The least significant bit will force a carry upwards to
+the third bit which will be set to zero after the borrow. After the very first bit has been subtracted $4 - 1 \equiv 0011_2$ will remain, When the
+third bit of $0101_2$ is subtracted from the result it will cause another carry. In this case though the carry will be forced to propagate all the
+way to the most significant bit.
+
+Recall that $\beta < 2^{\gamma}$. This means that if a carry does occur just before the $lg(\beta)$'th bit it will propagate all the way to the most
+significant bit. Thus, the high order bits of the mp\_digit that are not part of the actual digit will either be all zero, or all one. All that
+is needed is a single zero or one bit for the carry. Therefore a single logical shift right by $\gamma - 1$ positions is sufficient to extract the
+carry. This method of carry extraction may seem awkward but the reason for it becomes apparent when the implementation is discussed.
+
+If $b$ has a smaller magnitude than $a$ then step 9 will force the carry and copy operation to propagate through the larger input $a$ into $c$. Step
+10 will ensure that any leading digits of $c$ above the $max$'th position are zeroed.
+
+EXAM,bn_s_mp_sub.c
+
+Like low level addition we ``sort'' the inputs. Except in this case the sorting is hardcoded
+(lines @24,min@ and @25,max@). In reality the $min$ and $max$ variables are only aliases and are only
+used to make the source code easier to read. Again the pointer alias optimization is used
+within this algorithm. The aliases $tmpa$, $tmpb$ and $tmpc$ are initialized
+(lines @42,tmpa@, @43,tmpb@ and @44,tmpc@) for $a$, $b$ and $c$ respectively.
+
+The first subtraction loop (lines @47,u = 0@ through @61,}@) subtract digits from both inputs until the smaller of
+the two inputs has been exhausted. As remarked earlier there is an implementation reason for using the ``awkward''
+method of extracting the carry (line @57, >>@). The traditional method for extracting the carry would be to shift
+by $lg(\beta)$ positions and logically AND the least significant bit. The AND operation is required because all of
+the bits above the $\lg(\beta)$'th bit will be set to one after a carry occurs from subtraction. This carry
+extraction requires two relatively cheap operations to extract the carry. The other method is to simply shift the
+most significant bit to the least significant bit thus extracting the carry with a single cheap operation. This
+optimization only works on twos compliment machines which is a safe assumption to make.
+
+If $a$ has a larger magnitude than $b$ an additional loop (lines @64,for@ through @73,}@) is required to propagate
+the carry through $a$ and copy the result to $c$.
+
+\subsection{High Level Addition}
+Now that both lower level addition and subtraction algorithms have been established an effective high level signed addition algorithm can be
+established. This high level addition algorithm will be what other algorithms and developers will use to perform addition of mp\_int data
+types.
+
+Recall from section 5.2 that an mp\_int represents an integer with an unsigned mantissa (\textit{the array of digits}) and a \textbf{sign}
+flag. A high level addition is actually performed as a series of eight separate cases which can be optimized down to three unique cases.
+
+\begin{figure}[!here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_add}. \\
+\textbf{Input}. Two mp\_ints $a$ and $b$ \\
+\textbf{Output}. The signed addition $c = a + b$. \\
+\hline \\
+1. if $a.sign = b.sign$ then do \\
+\hspace{3mm}1.1 $c.sign \leftarrow a.sign$ \\
+\hspace{3mm}1.2 $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add})\\
+2. else do \\
+\hspace{3mm}2.1 if $\vert a \vert < \vert b \vert$ then do (\textit{mp\_cmp\_mag}) \\
+\hspace{6mm}2.1.1 $c.sign \leftarrow b.sign$ \\
+\hspace{6mm}2.1.2 $c \leftarrow \vert b \vert - \vert a \vert$ (\textit{s\_mp\_sub}) \\
+\hspace{3mm}2.2 else do \\
+\hspace{6mm}2.2.1 $c.sign \leftarrow a.sign$ \\
+\hspace{6mm}2.2.2 $c \leftarrow \vert a \vert - \vert b \vert$ \\
+3. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_add}
+\end{figure}
+
+\textbf{Algorithm mp\_add.}
+This algorithm performs the signed addition of two mp\_int variables. There is no reference algorithm to draw upon from
+either \cite{TAOCPV2} or \cite{HAC} since they both only provide unsigned operations. The algorithm is fairly
+straightforward but restricted since subtraction can only produce positive results.
+
+\begin{figure}[here]
+\begin{small}
+\begin{center}
+\begin{tabular}{|c|c|c|c|c|}
+\hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert > \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\
+\hline $+$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\
+\hline $+$ & $+$ & No & $c = a + b$ & $a.sign$ \\
+\hline $-$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\
+\hline $-$ & $-$ & No & $c = a + b$ & $a.sign$ \\
+\hline &&&&\\
+
+\hline $+$ & $-$ & No & $c = b - a$ & $b.sign$ \\
+\hline $-$ & $+$ & No & $c = b - a$ & $b.sign$ \\
+
+\hline &&&&\\
+
+\hline $+$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\
+\hline $-$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\
+
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Addition Guide Chart}
+\label{fig:AddChart}
+\end{figure}
+
+Figure~\ref{fig:AddChart} lists all of the eight possible input combinations and is sorted to show that only three
+specific cases need to be handled. The return code of the unsigned operations at step 1.2, 2.1.2 and 2.2.2 are
+forwarded to step three to check for errors. This simplifies the description of the algorithm considerably and best
+follows how the implementation actually was achieved.
+
+Also note how the \textbf{sign} is set before the unsigned addition or subtraction is performed. Recall from the descriptions of algorithms
+s\_mp\_add and s\_mp\_sub that the mp\_clamp function is used at the end to trim excess digits. The mp\_clamp algorithm will set the \textbf{sign}
+to \textbf{MP\_ZPOS} when the \textbf{used} digit count reaches zero.
+
+For example, consider performing $-a + a$ with algorithm mp\_add. By the description of the algorithm the sign is set to \textbf{MP\_NEG} which would
+produce a result of $-0$. However, since the sign is set first then the unsigned addition is performed the subsequent usage of algorithm mp\_clamp
+within algorithm s\_mp\_add will force $-0$ to become $0$.
+
+EXAM,bn_mp_add.c
+
+The source code follows the algorithm fairly closely. The most notable new source code addition is the usage of the $res$ integer variable which
+is used to pass result of the unsigned operations forward. Unlike in the algorithm, the variable $res$ is merely returned as is without
+explicitly checking it and returning the constant \textbf{MP\_OKAY}. The observation is this algorithm will succeed or fail only if the lower
+level functions do so. Returning their return code is sufficient.
+
+\subsection{High Level Subtraction}
+The high level signed subtraction algorithm is essentially the same as the high level signed addition algorithm.
+
+\newpage\begin{figure}[!here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_sub}. \\
+\textbf{Input}. Two mp\_ints $a$ and $b$ \\
+\textbf{Output}. The signed subtraction $c = a - b$. \\
+\hline \\
+1. if $a.sign \ne b.sign$ then do \\
+\hspace{3mm}1.1 $c.sign \leftarrow a.sign$ \\
+\hspace{3mm}1.2 $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add}) \\
+2. else do \\
+\hspace{3mm}2.1 if $\vert a \vert \ge \vert b \vert$ then do (\textit{mp\_cmp\_mag}) \\
+\hspace{6mm}2.1.1 $c.sign \leftarrow a.sign$ \\
+\hspace{6mm}2.1.2 $c \leftarrow \vert a \vert - \vert b \vert$ (\textit{s\_mp\_sub}) \\
+\hspace{3mm}2.2 else do \\
+\hspace{6mm}2.2.1 $c.sign \leftarrow \left \lbrace \begin{array}{ll}
+ MP\_ZPOS & \mbox{if }a.sign = MP\_NEG \\
+ MP\_NEG & \mbox{otherwise} \\
+ \end{array} \right .$ \\
+\hspace{6mm}2.2.2 $c \leftarrow \vert b \vert - \vert a \vert$ \\
+3. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_sub}
+\end{figure}
+
+\textbf{Algorithm mp\_sub.}
+This algorithm performs the signed subtraction of two inputs. Similar to algorithm mp\_add there is no reference in either \cite{TAOCPV2} or
+\cite{HAC}. Also this algorithm is restricted by algorithm s\_mp\_sub. Chart \ref{fig:SubChart} lists the eight possible inputs and
+the operations required.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{|c|c|c|c|c|}
+\hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert \ge \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\
+\hline $+$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\
+\hline $+$ & $-$ & No & $c = a + b$ & $a.sign$ \\
+\hline $-$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\
+\hline $-$ & $+$ & No & $c = a + b$ & $a.sign$ \\
+\hline &&&& \\
+\hline $+$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\
+\hline $-$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\
+\hline &&&& \\
+\hline $+$ & $+$ & No & $c = b - a$ & $\mbox{opposite of }a.sign$ \\
+\hline $-$ & $-$ & No & $c = b - a$ & $\mbox{opposite of }a.sign$ \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Subtraction Guide Chart}
+\label{fig:SubChart}
+\end{figure}
+
+Similar to the case of algorithm mp\_add the \textbf{sign} is set first before the unsigned addition or subtraction. That is to prevent the
+algorithm from producing $-a - -a = -0$ as a result.
+
+EXAM,bn_mp_sub.c
+
+Much like the implementation of algorithm mp\_add the variable $res$ is used to catch the return code of the unsigned addition or subtraction operations
+and forward it to the end of the function. On line @38, != MP_LT@ the ``not equal to'' \textbf{MP\_LT} expression is used to emulate a
+``greater than or equal to'' comparison.
+
+\section{Bit and Digit Shifting}
+MARK,POLY
+It is quite common to think of a multiple precision integer as a polynomial in $x$, that is $y = f(\beta)$ where $f(x) = \sum_{i=0}^{n-1} a_i x^i$.
+This notation arises within discussion of Montgomery and Diminished Radix Reduction as well as Karatsuba multiplication and squaring.
+
+In order to facilitate operations on polynomials in $x$ as above a series of simple ``digit'' algorithms have to be established. That is to shift
+the digits left or right as well to shift individual bits of the digits left and right. It is important to note that not all ``shift'' operations
+are on radix-$\beta$ digits.
+
+\subsection{Multiplication by Two}
+
+In a binary system where the radix is a power of two multiplication by two not only arises often in other algorithms it is a fairly efficient
+operation to perform. A single precision logical shift left is sufficient to multiply a single digit by two.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_mul\_2}. \\
+\textbf{Input}. One mp\_int $a$ \\
+\textbf{Output}. $b = 2a$. \\
+\hline \\
+1. If $b.alloc < a.used + 1$ then grow $b$ to hold $a.used + 1$ digits. (\textit{mp\_grow}) \\
+2. $oldused \leftarrow b.used$ \\
+3. $b.used \leftarrow a.used$ \\
+4. $r \leftarrow 0$ \\
+5. for $n$ from 0 to $a.used - 1$ do \\
+\hspace{3mm}5.1 $rr \leftarrow a_n >> (lg(\beta) - 1)$ \\
+\hspace{3mm}5.2 $b_n \leftarrow (a_n << 1) + r \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{3mm}5.3 $r \leftarrow rr$ \\
+6. If $r \ne 0$ then do \\
+\hspace{3mm}6.1 $b_{n + 1} \leftarrow r$ \\
+\hspace{3mm}6.2 $b.used \leftarrow b.used + 1$ \\
+7. If $b.used < oldused - 1$ then do \\
+\hspace{3mm}7.1 for $n$ from $b.used$ to $oldused - 1$ do \\
+\hspace{6mm}7.1.1 $b_n \leftarrow 0$ \\
+8. $b.sign \leftarrow a.sign$ \\
+9. Return(\textit{MP\_OKAY}).\\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_mul\_2}
+\end{figure}
+
+\textbf{Algorithm mp\_mul\_2.}
+This algorithm will quickly multiply a mp\_int by two provided $\beta$ is a power of two. Neither \cite{TAOCPV2} nor \cite{HAC} describe such
+an algorithm despite the fact it arises often in other algorithms. The algorithm is setup much like the lower level algorithm s\_mp\_add since
+it is for all intents and purposes equivalent to the operation $b = \vert a \vert + \vert a \vert$.
+
+Step 1 and 2 grow the input as required to accomodate the maximum number of \textbf{used} digits in the result. The initial \textbf{used} count
+is set to $a.used$ at step 4. Only if there is a final carry will the \textbf{used} count require adjustment.
+
+Step 6 is an optimization implementation of the addition loop for this specific case. That is since the two values being added together
+are the same there is no need to perform two reads from the digits of $a$. Step 6.1 performs a single precision shift on the current digit $a_n$ to
+obtain what will be the carry for the next iteration. Step 6.2 calculates the $n$'th digit of the result as single precision shift of $a_n$ plus
+the previous carry. Recall from ~SHIFTS~ that $a_n << 1$ is equivalent to $a_n \cdot 2$. An iteration of the addition loop is finished with
+forwarding the carry to the next iteration.
+
+Step 7 takes care of any final carry by setting the $a.used$'th digit of the result to the carry and augmenting the \textbf{used} count of $b$.
+Step 8 clears any leading digits of $b$ in case it originally had a larger magnitude than $a$.
+
+EXAM,bn_mp_mul_2.c
+
+This implementation is essentially an optimized implementation of s\_mp\_add for the case of doubling an input. The only noteworthy difference
+is the use of the logical shift operator on line @52,<<@ to perform a single precision doubling.
+
+\subsection{Division by Two}
+A division by two can just as easily be accomplished with a logical shift right as multiplication by two can be with a logical shift left.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_div\_2}. \\
+\textbf{Input}. One mp\_int $a$ \\
+\textbf{Output}. $b = a/2$. \\
+\hline \\
+1. If $b.alloc < a.used$ then grow $b$ to hold $a.used$ digits. (\textit{mp\_grow}) \\
+2. If the reallocation failed return(\textit{MP\_MEM}). \\
+3. $oldused \leftarrow b.used$ \\
+4. $b.used \leftarrow a.used$ \\
+5. $r \leftarrow 0$ \\
+6. for $n$ from $b.used - 1$ to $0$ do \\
+\hspace{3mm}6.1 $rr \leftarrow a_n \mbox{ (mod }2\mbox{)}$\\
+\hspace{3mm}6.2 $b_n \leftarrow (a_n >> 1) + (r << (lg(\beta) - 1)) \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{3mm}6.3 $r \leftarrow rr$ \\
+7. If $b.used < oldused - 1$ then do \\
+\hspace{3mm}7.1 for $n$ from $b.used$ to $oldused - 1$ do \\
+\hspace{6mm}7.1.1 $b_n \leftarrow 0$ \\
+8. $b.sign \leftarrow a.sign$ \\
+9. Clamp excess digits of $b$. (\textit{mp\_clamp}) \\
+10. Return(\textit{MP\_OKAY}).\\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_div\_2}
+\end{figure}
+
+\textbf{Algorithm mp\_div\_2.}
+This algorithm will divide an mp\_int by two using logical shifts to the right. Like mp\_mul\_2 it uses a modified low level addition
+core as the basis of the algorithm. Unlike mp\_mul\_2 the shift operations work from the leading digit to the trailing digit. The algorithm
+could be written to work from the trailing digit to the leading digit however, it would have to stop one short of $a.used - 1$ digits to prevent
+reading past the end of the array of digits.
+
+Essentially the loop at step 6 is similar to that of mp\_mul\_2 except the logical shifts go in the opposite direction and the carry is at the
+least significant bit not the most significant bit.
+
+EXAM,bn_mp_div_2.c
+
+\section{Polynomial Basis Operations}
+Recall from ~POLY~ that any integer can be represented as a polynomial in $x$ as $y = f(\beta)$. Such a representation is also known as
+the polynomial basis \cite[pp. 48]{ROSE}. Given such a notation a multiplication or division by $x$ amounts to shifting whole digits a single
+place. The need for such operations arises in several other higher level algorithms such as Barrett and Montgomery reduction, integer
+division and Karatsuba multiplication.
+
+Converting from an array of digits to polynomial basis is very simple. Consider the integer $y \equiv (a_2, a_1, a_0)_{\beta}$ and recall that
+$y = \sum_{i=0}^{2} a_i \beta^i$. Simply replace $\beta$ with $x$ and the expression is in polynomial basis. For example, $f(x) = 8x + 9$ is the
+polynomial basis representation for $89$ using radix ten. That is, $f(10) = 8(10) + 9 = 89$.
+
+\subsection{Multiplication by $x$}
+
+Given a polynomial in $x$ such as $f(x) = a_n x^n + a_{n-1} x^{n-1} + ... + a_0$ multiplying by $x$ amounts to shifting the coefficients up one
+degree. In this case $f(x) \cdot x = a_n x^{n+1} + a_{n-1} x^n + ... + a_0 x$. From a scalar basis point of view multiplying by $x$ is equivalent to
+multiplying by the integer $\beta$.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_lshd}. \\
+\textbf{Input}. One mp\_int $a$ and an integer $b$ \\
+\textbf{Output}. $a \leftarrow a \cdot \beta^b$ (equivalent to multiplication by $x^b$). \\
+\hline \\
+1. If $b \le 0$ then return(\textit{MP\_OKAY}). \\
+2. If $a.alloc < a.used + b$ then grow $a$ to at least $a.used + b$ digits. (\textit{mp\_grow}). \\
+3. If the reallocation failed return(\textit{MP\_MEM}). \\
+4. $a.used \leftarrow a.used + b$ \\
+5. $i \leftarrow a.used - 1$ \\
+6. $j \leftarrow a.used - 1 - b$ \\
+7. for $n$ from $a.used - 1$ to $b$ do \\
+\hspace{3mm}7.1 $a_{i} \leftarrow a_{j}$ \\
+\hspace{3mm}7.2 $i \leftarrow i - 1$ \\
+\hspace{3mm}7.3 $j \leftarrow j - 1$ \\
+8. for $n$ from 0 to $b - 1$ do \\
+\hspace{3mm}8.1 $a_n \leftarrow 0$ \\
+9. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_lshd}
+\end{figure}
+
+\textbf{Algorithm mp\_lshd.}
+This algorithm multiplies an mp\_int by the $b$'th power of $x$. This is equivalent to multiplying by $\beta^b$. The algorithm differs
+from the other algorithms presented so far as it performs the operation in place instead storing the result in a separate location. The
+motivation behind this change is due to the way this function is typically used. Algorithms such as mp\_add store the result in an optionally
+different third mp\_int because the original inputs are often still required. Algorithm mp\_lshd (\textit{and similarly algorithm mp\_rshd}) is
+typically used on values where the original value is no longer required. The algorithm will return success immediately if
+$b \le 0$ since the rest of algorithm is only valid when $b > 0$.
+
+First the destination $a$ is grown as required to accomodate the result. The counters $i$ and $j$ are used to form a \textit{sliding window} over
+the digits of $a$ of length $b$. The head of the sliding window is at $i$ (\textit{the leading digit}) and the tail at $j$ (\textit{the trailing digit}).
+The loop on step 7 copies the digit from the tail to the head. In each iteration the window is moved down one digit. The last loop on
+step 8 sets the lower $b$ digits to zero.
+
+\newpage
+FIGU,sliding_window,Sliding Window Movement
+
+EXAM,bn_mp_lshd.c
+
+The if statement (line @24,if@) ensures that the $b$ variable is greater than zero since we do not interpret negative
+shift counts properly. The \textbf{used} count is incremented by $b$ before the copy loop begins. This elminates
+the need for an additional variable in the for loop. The variable $top$ (line @42,top@) is an alias
+for the leading digit while $bottom$ (line @45,bottom@) is an alias for the trailing edge. The aliases form a
+window of exactly $b$ digits over the input.
+
+\subsection{Division by $x$}
+
+Division by powers of $x$ is easily achieved by shifting the digits right and removing any that will end up to the right of the zero'th digit.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_rshd}. \\
+\textbf{Input}. One mp\_int $a$ and an integer $b$ \\
+\textbf{Output}. $a \leftarrow a / \beta^b$ (Divide by $x^b$). \\
+\hline \\
+1. If $b \le 0$ then return. \\
+2. If $a.used \le b$ then do \\
+\hspace{3mm}2.1 Zero $a$. (\textit{mp\_zero}). \\
+\hspace{3mm}2.2 Return. \\
+3. $i \leftarrow 0$ \\
+4. $j \leftarrow b$ \\
+5. for $n$ from 0 to $a.used - b - 1$ do \\
+\hspace{3mm}5.1 $a_i \leftarrow a_j$ \\
+\hspace{3mm}5.2 $i \leftarrow i + 1$ \\
+\hspace{3mm}5.3 $j \leftarrow j + 1$ \\
+6. for $n$ from $a.used - b$ to $a.used - 1$ do \\
+\hspace{3mm}6.1 $a_n \leftarrow 0$ \\
+7. $a.used \leftarrow a.used - b$ \\
+8. Return. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_rshd}
+\end{figure}
+
+\textbf{Algorithm mp\_rshd.}
+This algorithm divides the input in place by the $b$'th power of $x$. It is analogous to dividing by a $\beta^b$ but much quicker since
+it does not require single precision division. This algorithm does not actually return an error code as it cannot fail.
+
+If the input $b$ is less than one the algorithm quickly returns without performing any work. If the \textbf{used} count is less than or equal
+to the shift count $b$ then it will simply zero the input and return.
+
+After the trivial cases of inputs have been handled the sliding window is setup. Much like the case of algorithm mp\_lshd a sliding window that
+is $b$ digits wide is used to copy the digits. Unlike mp\_lshd the window slides in the opposite direction from the trailing to the leading digit.
+Also the digits are copied from the leading to the trailing edge.
+
+Once the window copy is complete the upper digits must be zeroed and the \textbf{used} count decremented.
+
+EXAM,bn_mp_rshd.c
+
+The only noteworthy element of this routine is the lack of a return type since it cannot fail. Like mp\_lshd() we
+form a sliding window except we copy in the other direction. After the window (line @59,for (;@) we then zero
+the upper digits of the input to make sure the result is correct.
+
+\section{Powers of Two}
+
+Now that algorithms for moving single bits as well as whole digits exist algorithms for moving the ``in between'' distances are required. For
+example, to quickly multiply by $2^k$ for any $k$ without using a full multiplier algorithm would prove useful. Instead of performing single
+shifts $k$ times to achieve a multiplication by $2^{\pm k}$ a mixture of whole digit shifting and partial digit shifting is employed.
+
+\subsection{Multiplication by Power of Two}
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_mul\_2d}. \\
+\textbf{Input}. One mp\_int $a$ and an integer $b$ \\
+\textbf{Output}. $c \leftarrow a \cdot 2^b$. \\
+\hline \\
+1. $c \leftarrow a$. (\textit{mp\_copy}) \\
+2. If $c.alloc < c.used + \lfloor b / lg(\beta) \rfloor + 2$ then grow $c$ accordingly. \\
+3. If the reallocation failed return(\textit{MP\_MEM}). \\
+4. If $b \ge lg(\beta)$ then \\
+\hspace{3mm}4.1 $c \leftarrow c \cdot \beta^{\lfloor b / lg(\beta) \rfloor}$ (\textit{mp\_lshd}). \\
+\hspace{3mm}4.2 If step 4.1 failed return(\textit{MP\_MEM}). \\
+5. $d \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
+6. If $d \ne 0$ then do \\
+\hspace{3mm}6.1 $mask \leftarrow 2^d$ \\
+\hspace{3mm}6.2 $r \leftarrow 0$ \\
+\hspace{3mm}6.3 for $n$ from $0$ to $c.used - 1$ do \\
+\hspace{6mm}6.3.1 $rr \leftarrow c_n >> (lg(\beta) - d) \mbox{ (mod }mask\mbox{)}$ \\
+\hspace{6mm}6.3.2 $c_n \leftarrow (c_n << d) + r \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{6mm}6.3.3 $r \leftarrow rr$ \\
+\hspace{3mm}6.4 If $r > 0$ then do \\
+\hspace{6mm}6.4.1 $c_{c.used} \leftarrow r$ \\
+\hspace{6mm}6.4.2 $c.used \leftarrow c.used + 1$ \\
+7. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_mul\_2d}
+\end{figure}
+
+\textbf{Algorithm mp\_mul\_2d.}
+This algorithm multiplies $a$ by $2^b$ and stores the result in $c$. The algorithm uses algorithm mp\_lshd and a derivative of algorithm mp\_mul\_2 to
+quickly compute the product.
+
+First the algorithm will multiply $a$ by $x^{\lfloor b / lg(\beta) \rfloor}$ which will ensure that the remainder multiplicand is less than
+$\beta$. For example, if $b = 37$ and $\beta = 2^{28}$ then this step will multiply by $x$ leaving a multiplication by $2^{37 - 28} = 2^{9}$
+left.
+
+After the digits have been shifted appropriately at most $lg(\beta) - 1$ shifts are left to perform. Step 5 calculates the number of remaining shifts
+required. If it is non-zero a modified shift loop is used to calculate the remaining product.
+Essentially the loop is a generic version of algorithm mp\_mul\_2 designed to handle any shift count in the range $1 \le x < lg(\beta)$. The $mask$
+variable is used to extract the upper $d$ bits to form the carry for the next iteration.
+
+This algorithm is loosely measured as a $O(2n)$ algorithm which means that if the input is $n$-digits that it takes $2n$ ``time'' to
+complete. It is possible to optimize this algorithm down to a $O(n)$ algorithm at a cost of making the algorithm slightly harder to follow.
+
+EXAM,bn_mp_mul_2d.c
+
+The shifting is performed in--place which means the first step (line @24,a != c@) is to copy the input to the
+destination. We avoid calling mp\_copy() by making sure the mp\_ints are different. The destination then
+has to be grown (line @31,grow@) to accomodate the result.
+
+If the shift count $b$ is larger than $lg(\beta)$ then a call to mp\_lshd() is used to handle all of the multiples
+of $lg(\beta)$. Leaving only a remaining shift of $lg(\beta) - 1$ or fewer bits left. Inside the actual shift
+loop (lines @45,if@ to @76,}@) we make use of pre--computed values $shift$ and $mask$. These are used to
+extract the carry bit(s) to pass into the next iteration of the loop. The $r$ and $rr$ variables form a
+chain between consecutive iterations to propagate the carry.
+
+\subsection{Division by Power of Two}
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_div\_2d}. \\
+\textbf{Input}. One mp\_int $a$ and an integer $b$ \\
+\textbf{Output}. $c \leftarrow \lfloor a / 2^b \rfloor, d \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\
+\hline \\
+1. If $b \le 0$ then do \\
+\hspace{3mm}1.1 $c \leftarrow a$ (\textit{mp\_copy}) \\
+\hspace{3mm}1.2 $d \leftarrow 0$ (\textit{mp\_zero}) \\
+\hspace{3mm}1.3 Return(\textit{MP\_OKAY}). \\
+2. $c \leftarrow a$ \\
+3. $d \leftarrow a \mbox{ (mod }2^b\mbox{)}$ (\textit{mp\_mod\_2d}) \\
+4. If $b \ge lg(\beta)$ then do \\
+\hspace{3mm}4.1 $c \leftarrow \lfloor c/\beta^{\lfloor b/lg(\beta) \rfloor} \rfloor$ (\textit{mp\_rshd}). \\
+5. $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
+6. If $k \ne 0$ then do \\
+\hspace{3mm}6.1 $mask \leftarrow 2^k$ \\
+\hspace{3mm}6.2 $r \leftarrow 0$ \\
+\hspace{3mm}6.3 for $n$ from $c.used - 1$ to $0$ do \\
+\hspace{6mm}6.3.1 $rr \leftarrow c_n \mbox{ (mod }mask\mbox{)}$ \\
+\hspace{6mm}6.3.2 $c_n \leftarrow (c_n >> k) + (r << (lg(\beta) - k))$ \\
+\hspace{6mm}6.3.3 $r \leftarrow rr$ \\
+7. Clamp excess digits of $c$. (\textit{mp\_clamp}) \\
+8. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_div\_2d}
+\end{figure}
+
+\textbf{Algorithm mp\_div\_2d.}
+This algorithm will divide an input $a$ by $2^b$ and produce the quotient and remainder. The algorithm is designed much like algorithm
+mp\_mul\_2d by first using whole digit shifts then single precision shifts. This algorithm will also produce the remainder of the division
+by using algorithm mp\_mod\_2d.
+
+EXAM,bn_mp_div_2d.c
+
+The implementation of algorithm mp\_div\_2d is slightly different than the algorithm specifies. The remainder $d$ may be optionally
+ignored by passing \textbf{NULL} as the pointer to the mp\_int variable. The temporary mp\_int variable $t$ is used to hold the
+result of the remainder operation until the end. This allows $d$ and $a$ to represent the same mp\_int without modifying $a$ before
+the quotient is obtained.
+
+The remainder of the source code is essentially the same as the source code for mp\_mul\_2d. The only significant difference is
+the direction of the shifts.
+
+\subsection{Remainder of Division by Power of Two}
+
+The last algorithm in the series of polynomial basis power of two algorithms is calculating the remainder of division by $2^b$. This
+algorithm benefits from the fact that in twos complement arithmetic $a \mbox{ (mod }2^b\mbox{)}$ is the same as $a$ AND $2^b - 1$.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_mod\_2d}. \\
+\textbf{Input}. One mp\_int $a$ and an integer $b$ \\
+\textbf{Output}. $c \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\
+\hline \\
+1. If $b \le 0$ then do \\
+\hspace{3mm}1.1 $c \leftarrow 0$ (\textit{mp\_zero}) \\
+\hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\
+2. If $b > a.used \cdot lg(\beta)$ then do \\
+\hspace{3mm}2.1 $c \leftarrow a$ (\textit{mp\_copy}) \\
+\hspace{3mm}2.2 Return the result of step 2.1. \\
+3. $c \leftarrow a$ \\
+4. If step 3 failed return(\textit{MP\_MEM}). \\
+5. for $n$ from $\lceil b / lg(\beta) \rceil$ to $c.used$ do \\
+\hspace{3mm}5.1 $c_n \leftarrow 0$ \\
+6. $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
+7. $c_{\lfloor b / lg(\beta) \rfloor} \leftarrow c_{\lfloor b / lg(\beta) \rfloor} \mbox{ (mod }2^{k}\mbox{)}$. \\
+8. Clamp excess digits of $c$. (\textit{mp\_clamp}) \\
+9. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_mod\_2d}
+\end{figure}
+
+\textbf{Algorithm mp\_mod\_2d.}
+This algorithm will quickly calculate the value of $a \mbox{ (mod }2^b\mbox{)}$. First if $b$ is less than or equal to zero the
+result is set to zero. If $b$ is greater than the number of bits in $a$ then it simply copies $a$ to $c$ and returns. Otherwise, $a$
+is copied to $b$, leading digits are removed and the remaining leading digit is trimed to the exact bit count.
+
+EXAM,bn_mp_mod_2d.c
+
+We first avoid cases of $b \le 0$ by simply mp\_zero()'ing the destination in such cases. Next if $2^b$ is larger
+than the input we just mp\_copy() the input and return right away. After this point we know we must actually
+perform some work to produce the remainder.
+
+Recalling that reducing modulo $2^k$ and a binary ``and'' with $2^k - 1$ are numerically equivalent we can quickly reduce
+the number. First we zero any digits above the last digit in $2^b$ (line @41,for@). Next we reduce the
+leading digit of both (line @45,&=@) and then mp\_clamp().
+
+\section*{Exercises}
+\begin{tabular}{cl}
+$\left [ 3 \right ] $ & Devise an algorithm that performs $a \cdot 2^b$ for generic values of $b$ \\
+ & in $O(n)$ time. \\
+ &\\
+$\left [ 3 \right ] $ & Devise an efficient algorithm to multiply by small low hamming \\
+ & weight values such as $3$, $5$ and $9$. Extend it to handle all values \\
+ & upto $64$ with a hamming weight less than three. \\
+ &\\
+$\left [ 2 \right ] $ & Modify the preceding algorithm to handle values of the form \\
+ & $2^k - 1$ as well. \\
+ &\\
+$\left [ 3 \right ] $ & Using only algorithms mp\_mul\_2, mp\_div\_2 and mp\_add create an \\
+ & algorithm to multiply two integers in roughly $O(2n^2)$ time for \\
+ & any $n$-bit input. Note that the time of addition is ignored in the \\
+ & calculation. \\
+ & \\
+$\left [ 5 \right ] $ & Improve the previous algorithm to have a working time of at most \\
+ & $O \left (2^{(k-1)}n + \left ({2n^2 \over k} \right ) \right )$ for an appropriate choice of $k$. Again ignore \\
+ & the cost of addition. \\
+ & \\
+$\left [ 2 \right ] $ & Devise a chart to find optimal values of $k$ for the previous problem \\
+ & for $n = 64 \ldots 1024$ in steps of $64$. \\
+ & \\
+$\left [ 2 \right ] $ & Using only algorithms mp\_abs and mp\_sub devise another method for \\
+ & calculating the result of a signed comparison. \\
+ &
+\end{tabular}
+
+\chapter{Multiplication and Squaring}
+\section{The Multipliers}
+For most number theoretic problems including certain public key cryptographic algorithms, the ``multipliers'' form the most important subset of
+algorithms of any multiple precision integer package. The set of multiplier algorithms include integer multiplication, squaring and modular reduction
+where in each of the algorithms single precision multiplication is the dominant operation performed. This chapter will discuss integer multiplication
+and squaring, leaving modular reductions for the subsequent chapter.
+
+The importance of the multiplier algorithms is for the most part driven by the fact that certain popular public key algorithms are based on modular
+exponentiation, that is computing $d \equiv a^b \mbox{ (mod }c\mbox{)}$ for some arbitrary choice of $a$, $b$, $c$ and $d$. During a modular
+exponentiation the majority\footnote{Roughly speaking a modular exponentiation will spend about 40\% of the time performing modular reductions,
+35\% of the time performing squaring and 25\% of the time performing multiplications.} of the processor time is spent performing single precision
+multiplications.
+
+For centuries general purpose multiplication has required a lengthly $O(n^2)$ process, whereby each digit of one multiplicand has to be multiplied
+against every digit of the other multiplicand. Traditional long-hand multiplication is based on this process; while the techniques can differ the
+overall algorithm used is essentially the same. Only ``recently'' have faster algorithms been studied. First Karatsuba multiplication was discovered in
+1962. This algorithm can multiply two numbers with considerably fewer single precision multiplications when compared to the long-hand approach.
+This technique led to the discovery of polynomial basis algorithms (\textit{good reference?}) and subquently Fourier Transform based solutions.
+
+\section{Multiplication}
+\subsection{The Baseline Multiplication}
+\label{sec:basemult}
+\index{baseline multiplication}
+Computing the product of two integers in software can be achieved using a trivial adaptation of the standard $O(n^2)$ long-hand multiplication
+algorithm that school children are taught. The algorithm is considered an $O(n^2)$ algorithm since for two $n$-digit inputs $n^2$ single precision
+multiplications are required. More specifically for a $m$ and $n$ digit input $m \cdot n$ single precision multiplications are required. To
+simplify most discussions, it will be assumed that the inputs have comparable number of digits.
+
+The ``baseline multiplication'' algorithm is designed to act as the ``catch-all'' algorithm, only to be used when the faster algorithms cannot be
+used. This algorithm does not use any particularly interesting optimizations and should ideally be avoided if possible. One important
+facet of this algorithm, is that it has been modified to only produce a certain amount of output digits as resolution. The importance of this
+modification will become evident during the discussion of Barrett modular reduction. Recall that for a $n$ and $m$ digit input the product
+will be at most $n + m$ digits. Therefore, this algorithm can be reduced to a full multiplier by having it produce $n + m$ digits of the product.
+
+Recall from ~GAMMA~ the definition of $\gamma$ as the number of bits in the type \textbf{mp\_digit}. We shall now extend the variable set to
+include $\alpha$ which shall represent the number of bits in the type \textbf{mp\_word}. This implies that $2^{\alpha} > 2 \cdot \beta^2$. The
+constant $\delta = 2^{\alpha - 2lg(\beta)}$ will represent the maximal weight of any column in a product (\textit{see ~COMBA~ for more information}).
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{s\_mp\_mul\_digs}. \\
+\textbf{Input}. mp\_int $a$, mp\_int $b$ and an integer $digs$ \\
+\textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\
+\hline \\
+1. If min$(a.used, b.used) < \delta$ then do \\
+\hspace{3mm}1.1 Calculate $c = \vert a \vert \cdot \vert b \vert$ by the Comba method (\textit{see algorithm~\ref{fig:COMBAMULT}}). \\
+\hspace{3mm}1.2 Return the result of step 1.1 \\
+\\
+Allocate and initialize a temporary mp\_int. \\
+2. Init $t$ to be of size $digs$ \\
+3. If step 2 failed return(\textit{MP\_MEM}). \\
+4. $t.used \leftarrow digs$ \\
+\\
+Compute the product. \\
+5. for $ix$ from $0$ to $a.used - 1$ do \\
+\hspace{3mm}5.1 $u \leftarrow 0$ \\
+\hspace{3mm}5.2 $pb \leftarrow \mbox{min}(b.used, digs - ix)$ \\
+\hspace{3mm}5.3 If $pb < 1$ then goto step 6. \\
+\hspace{3mm}5.4 for $iy$ from $0$ to $pb - 1$ do \\
+\hspace{6mm}5.4.1 $\hat r \leftarrow t_{iy + ix} + a_{ix} \cdot b_{iy} + u$ \\
+\hspace{6mm}5.4.2 $t_{iy + ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{6mm}5.4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
+\hspace{3mm}5.5 if $ix + pb < digs$ then do \\
+\hspace{6mm}5.5.1 $t_{ix + pb} \leftarrow u$ \\
+6. Clamp excess digits of $t$. \\
+7. Swap $c$ with $t$ \\
+8. Clear $t$ \\
+9. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm s\_mp\_mul\_digs}
+\end{figure}
+
+\textbf{Algorithm s\_mp\_mul\_digs.}
+This algorithm computes the unsigned product of two inputs $a$ and $b$, limited to an output precision of $digs$ digits. While it may seem
+a bit awkward to modify the function from its simple $O(n^2)$ description, the usefulness of partial multipliers will arise in a subsequent
+algorithm. The algorithm is loosely based on algorithm 14.12 from \cite[pp. 595]{HAC} and is similar to Algorithm M of Knuth \cite[pp. 268]{TAOCPV2}.
+Algorithm s\_mp\_mul\_digs differs from these cited references since it can produce a variable output precision regardless of the precision of the
+inputs.
+
+The first thing this algorithm checks for is whether a Comba multiplier can be used instead. If the minimum digit count of either
+input is less than $\delta$, then the Comba method may be used instead. After the Comba method is ruled out, the baseline algorithm begins. A
+temporary mp\_int variable $t$ is used to hold the intermediate result of the product. This allows the algorithm to be used to
+compute products when either $a = c$ or $b = c$ without overwriting the inputs.
+
+All of step 5 is the infamous $O(n^2)$ multiplication loop slightly modified to only produce upto $digs$ digits of output. The $pb$ variable
+is given the count of digits to read from $b$ inside the nested loop. If $pb \le 1$ then no more output digits can be produced and the algorithm
+will exit the loop. The best way to think of the loops are as a series of $pb \times 1$ multiplications. That is, in each pass of the
+innermost loop $a_{ix}$ is multiplied against $b$ and the result is added (\textit{with an appropriate shift}) to $t$.
+
+For example, consider multiplying $576$ by $241$. That is equivalent to computing $10^0(1)(576) + 10^1(4)(576) + 10^2(2)(576)$ which is best
+visualized in the following table.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{|c|c|c|c|c|c|l|}
+\hline && & 5 & 7 & 6 & \\
+\hline $\times$&& & 2 & 4 & 1 & \\
+\hline &&&&&&\\
+ && & 5 & 7 & 6 & $10^0(1)(576)$ \\
+ &2 & 3 & 6 & 1 & 6 & $10^1(4)(576) + 10^0(1)(576)$ \\
+ 1 & 3 & 8 & 8 & 1 & 6 & $10^2(2)(576) + 10^1(4)(576) + 10^0(1)(576)$ \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Long-Hand Multiplication Diagram}
+\end{figure}
+
+Each row of the product is added to the result after being shifted to the left (\textit{multiplied by a power of the radix}) by the appropriate
+count. That is in pass $ix$ of the inner loop the product is added starting at the $ix$'th digit of the reult.
+
+Step 5.4.1 introduces the hat symbol (\textit{e.g. $\hat r$}) which represents a double precision variable. The multiplication on that step
+is assumed to be a double wide output single precision multiplication. That is, two single precision variables are multiplied to produce a
+double precision result. The step is somewhat optimized from a long-hand multiplication algorithm because the carry from the addition in step
+5.4.1 is propagated through the nested loop. If the carry was not propagated immediately it would overflow the single precision digit
+$t_{ix+iy}$ and the result would be lost.
+
+At step 5.5 the nested loop is finished and any carry that was left over should be forwarded. The carry does not have to be added to the $ix+pb$'th
+digit since that digit is assumed to be zero at this point. However, if $ix + pb \ge digs$ the carry is not set as it would make the result
+exceed the precision requested.
+
+EXAM,bn_s_mp_mul_digs.c
+
+First we determine (line @30,if@) if the Comba method can be used first since it's faster. The conditions for
+sing the Comba routine are that min$(a.used, b.used) < \delta$ and the number of digits of output is less than
+\textbf{MP\_WARRAY}. This new constant is used to control the stack usage in the Comba routines. By default it is
+set to $\delta$ but can be reduced when memory is at a premium.
+
+If we cannot use the Comba method we proceed to setup the baseline routine. We allocate the the destination mp\_int
+$t$ (line @36,init@) to the exact size of the output to avoid further re--allocations. At this point we now
+begin the $O(n^2)$ loop.
+
+This implementation of multiplication has the caveat that it can be trimmed to only produce a variable number of
+digits as output. In each iteration of the outer loop the $pb$ variable is set (line @48,MIN@) to the maximum
+number of inner loop iterations.
+
+Inside the inner loop we calculate $\hat r$ as the mp\_word product of the two mp\_digits and the addition of the
+carry from the previous iteration. A particularly important observation is that most modern optimizing
+C compilers (GCC for instance) can recognize that a $N \times N \rightarrow 2N$ multiplication is all that
+is required for the product. In x86 terms for example, this means using the MUL instruction.
+
+Each digit of the product is stored in turn (line @68,tmpt@) and the carry propagated (line @71,>>@) to the
+next iteration.
+
+\subsection{Faster Multiplication by the ``Comba'' Method}
+MARK,COMBA
+
+One of the huge drawbacks of the ``baseline'' algorithms is that at the $O(n^2)$ level the carry must be
+computed and propagated upwards. This makes the nested loop very sequential and hard to unroll and implement
+in parallel. The ``Comba'' \cite{COMBA} method is named after little known (\textit{in cryptographic venues}) Paul G.
+Comba who described a method of implementing fast multipliers that do not require nested carry fixup operations. As an
+interesting aside it seems that Paul Barrett describes a similar technique in his 1986 paper \cite{BARRETT} written
+five years before.
+
+At the heart of the Comba technique is once again the long-hand algorithm. Except in this case a slight
+twist is placed on how the columns of the result are produced. In the standard long-hand algorithm rows of products
+are produced then added together to form the final result. In the baseline algorithm the columns are added together
+after each iteration to get the result instantaneously.
+
+In the Comba algorithm the columns of the result are produced entirely independently of each other. That is at
+the $O(n^2)$ level a simple multiplication and addition step is performed. The carries of the columns are propagated
+after the nested loop to reduce the amount of work requiored. Succintly the first step of the algorithm is to compute
+the product vector $\vec x$ as follows.
+
+\begin{equation}
+\vec x_n = \sum_{i+j = n} a_ib_j, \forall n \in \lbrace 0, 1, 2, \ldots, i + j \rbrace
+\end{equation}
+
+Where $\vec x_n$ is the $n'th$ column of the output vector. Consider the following example which computes the vector $\vec x$ for the multiplication
+of $576$ and $241$.
+
+\newpage\begin{figure}[here]
+\begin{small}
+\begin{center}
+\begin{tabular}{|c|c|c|c|c|c|}
+ \hline & & 5 & 7 & 6 & First Input\\
+ \hline $\times$ & & 2 & 4 & 1 & Second Input\\
+\hline & & $1 \cdot 5 = 5$ & $1 \cdot 7 = 7$ & $1 \cdot 6 = 6$ & First pass \\
+ & $4 \cdot 5 = 20$ & $4 \cdot 7+5=33$ & $4 \cdot 6+7=31$ & 6 & Second pass \\
+ $2 \cdot 5 = 10$ & $2 \cdot 7 + 20 = 34$ & $2 \cdot 6+33=45$ & 31 & 6 & Third pass \\
+\hline 10 & 34 & 45 & 31 & 6 & Final Result \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Comba Multiplication Diagram}
+\end{figure}
+
+At this point the vector $x = \left < 10, 34, 45, 31, 6 \right >$ is the result of the first step of the Comba multipler.
+Now the columns must be fixed by propagating the carry upwards. The resultant vector will have one extra dimension over the input vector which is
+congruent to adding a leading zero digit.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Comba Fixup}. \\
+\textbf{Input}. Vector $\vec x$ of dimension $k$ \\
+\textbf{Output}. Vector $\vec x$ such that the carries have been propagated. \\
+\hline \\
+1. for $n$ from $0$ to $k - 1$ do \\
+\hspace{3mm}1.1 $\vec x_{n+1} \leftarrow \vec x_{n+1} + \lfloor \vec x_{n}/\beta \rfloor$ \\
+\hspace{3mm}1.2 $\vec x_{n} \leftarrow \vec x_{n} \mbox{ (mod }\beta\mbox{)}$ \\
+2. Return($\vec x$). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm Comba Fixup}
+\end{figure}
+
+With that algorithm and $k = 5$ and $\beta = 10$ the following vector is produced $\vec x= \left < 1, 3, 8, 8, 1, 6 \right >$. In this case
+$241 \cdot 576$ is in fact $138816$ and the procedure succeeded. If the algorithm is correct and as will be demonstrated shortly more
+efficient than the baseline algorithm why not simply always use this algorithm?
+
+\subsubsection{Column Weight.}
+At the nested $O(n^2)$ level the Comba method adds the product of two single precision variables to each column of the output
+independently. A serious obstacle is if the carry is lost, due to lack of precision before the algorithm has a chance to fix
+the carries. For example, in the multiplication of two three-digit numbers the third column of output will be the sum of
+three single precision multiplications. If the precision of the accumulator for the output digits is less then $3 \cdot (\beta - 1)^2$ then
+an overflow can occur and the carry information will be lost. For any $m$ and $n$ digit inputs the maximum weight of any column is
+min$(m, n)$ which is fairly obvious.
+
+The maximum number of terms in any column of a product is known as the ``column weight'' and strictly governs when the algorithm can be used. Recall
+from earlier that a double precision type has $\alpha$ bits of resolution and a single precision digit has $lg(\beta)$ bits of precision. Given these
+two quantities we must not violate the following
+
+\begin{equation}
+k \cdot \left (\beta - 1 \right )^2 < 2^{\alpha}
+\end{equation}
+
+Which reduces to
+
+\begin{equation}
+k \cdot \left ( \beta^2 - 2\beta + 1 \right ) < 2^{\alpha}
+\end{equation}
+
+Let $\rho = lg(\beta)$ represent the number of bits in a single precision digit. By further re-arrangement of the equation the final solution is
+found.
+
+\begin{equation}
+k < {{2^{\alpha}} \over {\left (2^{2\rho} - 2^{\rho + 1} + 1 \right )}}
+\end{equation}
+
+The defaults for LibTomMath are $\beta = 2^{28}$ and $\alpha = 2^{64}$ which means that $k$ is bounded by $k < 257$. In this configuration
+the smaller input may not have more than $256$ digits if the Comba method is to be used. This is quite satisfactory for most applications since
+$256$ digits would allow for numbers in the range of $0 \le x < 2^{7168}$ which, is much larger than most public key cryptographic algorithms require.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{fast\_s\_mp\_mul\_digs}. \\
+\textbf{Input}. mp\_int $a$, mp\_int $b$ and an integer $digs$ \\
+\textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\
+\hline \\
+Place an array of \textbf{MP\_WARRAY} single precision digits named $W$ on the stack. \\
+1. If $c.alloc < digs$ then grow $c$ to $digs$ digits. (\textit{mp\_grow}) \\
+2. If step 1 failed return(\textit{MP\_MEM}).\\
+\\
+3. $pa \leftarrow \mbox{MIN}(digs, a.used + b.used)$ \\
+\\
+4. $\_ \hat W \leftarrow 0$ \\
+5. for $ix$ from 0 to $pa - 1$ do \\
+\hspace{3mm}5.1 $ty \leftarrow \mbox{MIN}(b.used - 1, ix)$ \\
+\hspace{3mm}5.2 $tx \leftarrow ix - ty$ \\
+\hspace{3mm}5.3 $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\
+\hspace{3mm}5.4 for $iz$ from 0 to $iy - 1$ do \\
+\hspace{6mm}5.4.1 $\_ \hat W \leftarrow \_ \hat W + a_{tx+iy}b_{ty-iy}$ \\
+\hspace{3mm}5.5 $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$\\
+\hspace{3mm}5.6 $\_ \hat W \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\
+\\
+6. $oldused \leftarrow c.used$ \\
+7. $c.used \leftarrow digs$ \\
+8. for $ix$ from $0$ to $pa$ do \\
+\hspace{3mm}8.1 $c_{ix} \leftarrow W_{ix}$ \\
+9. for $ix$ from $pa + 1$ to $oldused - 1$ do \\
+\hspace{3mm}9.1 $c_{ix} \leftarrow 0$ \\
+\\
+10. Clamp $c$. \\
+11. Return MP\_OKAY. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm fast\_s\_mp\_mul\_digs}
+\label{fig:COMBAMULT}
+\end{figure}
+
+\textbf{Algorithm fast\_s\_mp\_mul\_digs.}
+This algorithm performs the unsigned multiplication of $a$ and $b$ using the Comba method limited to $digs$ digits of precision.
+
+The outer loop of this algorithm is more complicated than that of the baseline multiplier. This is because on the inside of the
+loop we want to produce one column per pass. This allows the accumulator $\_ \hat W$ to be placed in CPU registers and
+reduce the memory bandwidth to two \textbf{mp\_digit} reads per iteration.
+
+The $ty$ variable is set to the minimum count of $ix$ or the number of digits in $b$. That way if $a$ has more digits than
+$b$ this will be limited to $b.used - 1$. The $tx$ variable is set to the to the distance past $b.used$ the variable
+$ix$ is. This is used for the immediately subsequent statement where we find $iy$.
+
+The variable $iy$ is the minimum digits we can read from either $a$ or $b$ before running out. Computing one column at a time
+means we have to scan one integer upwards and the other downwards. $a$ starts at $tx$ and $b$ starts at $ty$. In each
+pass we are producing the $ix$'th output column and we note that $tx + ty = ix$. As we move $tx$ upwards we have to
+move $ty$ downards so the equality remains valid. The $iy$ variable is the number of iterations until
+$tx \ge a.used$ or $ty < 0$ occurs.
+
+After every inner pass we store the lower half of the accumulator into $W_{ix}$ and then propagate the carry of the accumulator
+into the next round by dividing $\_ \hat W$ by $\beta$.
+
+To measure the benefits of the Comba method over the baseline method consider the number of operations that are required. If the
+cost in terms of time of a multiply and addition is $p$ and the cost of a carry propagation is $q$ then a baseline multiplication would require
+$O \left ((p + q)n^2 \right )$ time to multiply two $n$-digit numbers. The Comba method requires only $O(pn^2 + qn)$ time, however in practice,
+the speed increase is actually much more. With $O(n)$ space the algorithm can be reduced to $O(pn + qn)$ time by implementing the $n$ multiply
+and addition operations in the nested loop in parallel.
+
+EXAM,bn_fast_s_mp_mul_digs.c
+
+As per the pseudo--code we first calculate $pa$ (line @47,MIN@) as the number of digits to output. Next we begin the outer loop
+to produce the individual columns of the product. We use the two aliases $tmpx$ and $tmpy$ (lines @61,tmpx@, @62,tmpy@) to point
+inside the two multiplicands quickly.
+
+The inner loop (lines @70,for@ to @72,}@) of this implementation is where the tradeoff come into play. Originally this comba
+implementation was ``row--major'' which means it adds to each of the columns in each pass. After the outer loop it would then fix
+the carries. This was very fast except it had an annoying drawback. You had to read a mp\_word and two mp\_digits and write
+one mp\_word per iteration. On processors such as the Athlon XP and P4 this did not matter much since the cache bandwidth
+is very high and it can keep the ALU fed with data. It did, however, matter on older and embedded cpus where cache is often
+slower and also often doesn't exist. This new algorithm only performs two reads per iteration under the assumption that the
+compiler has aliased $\_ \hat W$ to a CPU register.
+
+After the inner loop we store the current accumulator in $W$ and shift $\_ \hat W$ (lines @75,W[ix]@, @78,>>@) to forward it as
+a carry for the next pass. After the outer loop we use the final carry (line @82,W[ix]@) as the last digit of the product.
+
+\subsection{Polynomial Basis Multiplication}
+To break the $O(n^2)$ barrier in multiplication requires a completely different look at integer multiplication. In the following algorithms
+the use of polynomial basis representation for two integers $a$ and $b$ as $f(x) = \sum_{i=0}^{n} a_i x^i$ and
+$g(x) = \sum_{i=0}^{n} b_i x^i$ respectively, is required. In this system both $f(x)$ and $g(x)$ have $n + 1$ terms and are of the $n$'th degree.
+
+The product $a \cdot b \equiv f(x)g(x)$ is the polynomial $W(x) = \sum_{i=0}^{2n} w_i x^i$. The coefficients $w_i$ will
+directly yield the desired product when $\beta$ is substituted for $x$. The direct solution to solve for the $2n + 1$ coefficients
+requires $O(n^2)$ time and would in practice be slower than the Comba technique.
+
+However, numerical analysis theory indicates that only $2n + 1$ distinct points in $W(x)$ are required to determine the values of the $2n + 1$ unknown
+coefficients. This means by finding $\zeta_y = W(y)$ for $2n + 1$ small values of $y$ the coefficients of $W(x)$ can be found with
+Gaussian elimination. This technique is also occasionally refered to as the \textit{interpolation technique} (\textit{references please...}) since in
+effect an interpolation based on $2n + 1$ points will yield a polynomial equivalent to $W(x)$.
+
+The coefficients of the polynomial $W(x)$ are unknown which makes finding $W(y)$ for any value of $y$ impossible. However, since
+$W(x) = f(x)g(x)$ the equivalent $\zeta_y = f(y) g(y)$ can be used in its place. The benefit of this technique stems from the
+fact that $f(y)$ and $g(y)$ are much smaller than either $a$ or $b$ respectively. As a result finding the $2n + 1$ relations required
+by multiplying $f(y)g(y)$ involves multiplying integers that are much smaller than either of the inputs.
+
+When picking points to gather relations there are always three obvious points to choose, $y = 0, 1$ and $ \infty$. The $\zeta_0$ term
+is simply the product $W(0) = w_0 = a_0 \cdot b_0$. The $\zeta_1$ term is the product
+$W(1) = \left (\sum_{i = 0}^{n} a_i \right ) \left (\sum_{i = 0}^{n} b_i \right )$. The third point $\zeta_{\infty}$ is less obvious but rather
+simple to explain. The $2n + 1$'th coefficient of $W(x)$ is numerically equivalent to the most significant column in an integer multiplication.
+The point at $\infty$ is used symbolically to represent the most significant column, that is $W(\infty) = w_{2n} = a_nb_n$. Note that the
+points at $y = 0$ and $\infty$ yield the coefficients $w_0$ and $w_{2n}$ directly.
+
+If more points are required they should be of small values and powers of two such as $2^q$ and the related \textit{mirror points}
+$\left (2^q \right )^{2n} \cdot \zeta_{2^{-q}}$ for small values of $q$. The term ``mirror point'' stems from the fact that
+$\left (2^q \right )^{2n} \cdot \zeta_{2^{-q}}$ can be calculated in the exact opposite fashion as $\zeta_{2^q}$. For
+example, when $n = 2$ and $q = 1$ then following two equations are equivalent to the point $\zeta_{2}$ and its mirror.
+
+\begin{eqnarray}
+\zeta_{2} = f(2)g(2) = (4a_2 + 2a_1 + a_0)(4b_2 + 2b_1 + b_0) \nonumber \\
+16 \cdot \zeta_{1 \over 2} = 4f({1\over 2}) \cdot 4g({1 \over 2}) = (a_2 + 2a_1 + 4a_0)(b_2 + 2b_1 + 4b_0)
+\end{eqnarray}
+
+Using such points will allow the values of $f(y)$ and $g(y)$ to be independently calculated using only left shifts. For example, when $n = 2$ the
+polynomial $f(2^q)$ is equal to $2^q((2^qa_2) + a_1) + a_0$. This technique of polynomial representation is known as Horner's method.
+
+As a general rule of the algorithm when the inputs are split into $n$ parts each there are $2n - 1$ multiplications. Each multiplication is of
+multiplicands that have $n$ times fewer digits than the inputs. The asymptotic running time of this algorithm is
+$O \left ( k^{lg_n(2n - 1)} \right )$ for $k$ digit inputs (\textit{assuming they have the same number of digits}). Figure~\ref{fig:exponent}
+summarizes the exponents for various values of $n$.
+
+\begin{figure}
+\begin{center}
+\begin{tabular}{|c|c|c|}
+\hline \textbf{Split into $n$ Parts} & \textbf{Exponent} & \textbf{Notes}\\
+\hline $2$ & $1.584962501$ & This is Karatsuba Multiplication. \\
+\hline $3$ & $1.464973520$ & This is Toom-Cook Multiplication. \\
+\hline $4$ & $1.403677461$ &\\
+\hline $5$ & $1.365212389$ &\\
+\hline $10$ & $1.278753601$ &\\
+\hline $100$ & $1.149426538$ &\\
+\hline $1000$ & $1.100270931$ &\\
+\hline $10000$ & $1.075252070$ &\\
+\hline
+\end{tabular}
+\end{center}
+\caption{Asymptotic Running Time of Polynomial Basis Multiplication}
+\label{fig:exponent}
+\end{figure}
+
+At first it may seem like a good idea to choose $n = 1000$ since the exponent is approximately $1.1$. However, the overhead
+of solving for the 2001 terms of $W(x)$ will certainly consume any savings the algorithm could offer for all but exceedingly large
+numbers.
+
+\subsubsection{Cutoff Point}
+The polynomial basis multiplication algorithms all require fewer single precision multiplications than a straight Comba approach. However,
+the algorithms incur an overhead (\textit{at the $O(n)$ work level}) since they require a system of equations to be solved. This makes the
+polynomial basis approach more costly to use with small inputs.
+
+Let $m$ represent the number of digits in the multiplicands (\textit{assume both multiplicands have the same number of digits}). There exists a
+point $y$ such that when $m < y$ the polynomial basis algorithms are more costly than Comba, when $m = y$ they are roughly the same cost and
+when $m > y$ the Comba methods are slower than the polynomial basis algorithms.
+
+The exact location of $y$ depends on several key architectural elements of the computer platform in question.
+
+\begin{enumerate}
+\item The ratio of clock cycles for single precision multiplication versus other simpler operations such as addition, shifting, etc. For example
+on the AMD Athlon the ratio is roughly $17 : 1$ while on the Intel P4 it is $29 : 1$. The higher the ratio in favour of multiplication the lower
+the cutoff point $y$ will be.
+
+\item The complexity of the linear system of equations (\textit{for the coefficients of $W(x)$}) is. Generally speaking as the number of splits
+grows the complexity grows substantially. Ideally solving the system will only involve addition, subtraction and shifting of integers. This
+directly reflects on the ratio previous mentioned.
+
+\item To a lesser extent memory bandwidth and function call overheads. Provided the values are in the processor cache this is less of an
+influence over the cutoff point.
+
+\end{enumerate}
+
+A clean cutoff point separation occurs when a point $y$ is found such that all of the cutoff point conditions are met. For example, if the point
+is too low then there will be values of $m$ such that $m > y$ and the Comba method is still faster. Finding the cutoff points is fairly simple when
+a high resolution timer is available.
+
+\subsection{Karatsuba Multiplication}
+Karatsuba \cite{KARA} multiplication when originally proposed in 1962 was among the first set of algorithms to break the $O(n^2)$ barrier for
+general purpose multiplication. Given two polynomial basis representations $f(x) = ax + b$ and $g(x) = cx + d$, Karatsuba proved with
+light algebra \cite{KARAP} that the following polynomial is equivalent to multiplication of the two integers the polynomials represent.
+
+\begin{equation}
+f(x) \cdot g(x) = acx^2 + ((a + b)(c + d) - (ac + bd))x + bd
+\end{equation}
+
+Using the observation that $ac$ and $bd$ could be re-used only three half sized multiplications would be required to produce the product. Applying
+this algorithm recursively, the work factor becomes $O(n^{lg(3)})$ which is substantially better than the work factor $O(n^2)$ of the Comba technique. It turns
+out what Karatsuba did not know or at least did not publish was that this is simply polynomial basis multiplication with the points
+$\zeta_0$, $\zeta_{\infty}$ and $\zeta_{1}$. Consider the resultant system of equations.
+
+\begin{center}
+\begin{tabular}{rcrcrcrc}
+$\zeta_{0}$ & $=$ & & & & & $w_0$ \\
+$\zeta_{1}$ & $=$ & $w_2$ & $+$ & $w_1$ & $+$ & $w_0$ \\
+$\zeta_{\infty}$ & $=$ & $w_2$ & & & & \\
+\end{tabular}
+\end{center}
+
+By adding the first and last equation to the equation in the middle the term $w_1$ can be isolated and all three coefficients solved for. The simplicity
+of this system of equations has made Karatsuba fairly popular. In fact the cutoff point is often fairly low\footnote{With LibTomMath 0.18 it is 70 and 109 digits for the Intel P4 and AMD Athlon respectively.}
+making it an ideal algorithm to speed up certain public key cryptosystems such as RSA and Diffie-Hellman.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_karatsuba\_mul}. \\
+\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\
+\textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert$ \\
+\hline \\
+1. Init the following mp\_int variables: $x0$, $x1$, $y0$, $y1$, $t1$, $x0y0$, $x1y1$.\\
+2. If step 2 failed then return(\textit{MP\_MEM}). \\
+\\
+Split the input. e.g. $a = x1 \cdot \beta^B + x0$ \\
+3. $B \leftarrow \mbox{min}(a.used, b.used)/2$ \\
+4. $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\
+5. $y0 \leftarrow b \mbox{ (mod }\beta^B\mbox{)}$ \\
+6. $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_rshd}) \\
+7. $y1 \leftarrow \lfloor b / \beta^B \rfloor$ \\
+\\
+Calculate the three products. \\
+8. $x0y0 \leftarrow x0 \cdot y0$ (\textit{mp\_mul}) \\
+9. $x1y1 \leftarrow x1 \cdot y1$ \\
+10. $t1 \leftarrow x1 + x0$ (\textit{mp\_add}) \\
+11. $x0 \leftarrow y1 + y0$ \\
+12. $t1 \leftarrow t1 \cdot x0$ \\
+\\
+Calculate the middle term. \\
+13. $x0 \leftarrow x0y0 + x1y1$ \\
+14. $t1 \leftarrow t1 - x0$ (\textit{s\_mp\_sub}) \\
+\\
+Calculate the final product. \\
+15. $t1 \leftarrow t1 \cdot \beta^B$ (\textit{mp\_lshd}) \\
+16. $x1y1 \leftarrow x1y1 \cdot \beta^{2B}$ \\
+17. $t1 \leftarrow x0y0 + t1$ \\
+18. $c \leftarrow t1 + x1y1$ \\
+19. Clear all of the temporary variables. \\
+20. Return(\textit{MP\_OKAY}).\\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_karatsuba\_mul}
+\end{figure}
+
+\textbf{Algorithm mp\_karatsuba\_mul.}
+This algorithm computes the unsigned product of two inputs using the Karatsuba multiplication algorithm. It is loosely based on the description
+from Knuth \cite[pp. 294-295]{TAOCPV2}.
+
+\index{radix point}
+In order to split the two inputs into their respective halves, a suitable \textit{radix point} must be chosen. The radix point chosen must
+be used for both of the inputs meaning that it must be smaller than the smallest input. Step 3 chooses the radix point $B$ as half of the
+smallest input \textbf{used} count. After the radix point is chosen the inputs are split into lower and upper halves. Step 4 and 5
+compute the lower halves. Step 6 and 7 computer the upper halves.
+
+After the halves have been computed the three intermediate half-size products must be computed. Step 8 and 9 compute the trivial products
+$x0 \cdot y0$ and $x1 \cdot y1$. The mp\_int $x0$ is used as a temporary variable after $x1 + x0$ has been computed. By using $x0$ instead
+of an additional temporary variable, the algorithm can avoid an addition memory allocation operation.
+
+The remaining steps 13 through 18 compute the Karatsuba polynomial through a variety of digit shifting and addition operations.
+
+EXAM,bn_mp_karatsuba_mul.c
+
+The new coding element in this routine, not seen in previous routines, is the usage of goto statements. The conventional
+wisdom is that goto statements should be avoided. This is generally true, however when every single function call can fail, it makes sense
+to handle error recovery with a single piece of code. Lines @61,if@ to @75,if@ handle initializing all of the temporary variables
+required. Note how each of the if statements goes to a different label in case of failure. This allows the routine to correctly free only
+the temporaries that have been successfully allocated so far.
+
+The temporary variables are all initialized using the mp\_init\_size routine since they are expected to be large. This saves the
+additional reallocation that would have been necessary. Also $x0$, $x1$, $y0$ and $y1$ have to be able to hold at least their respective
+number of digits for the next section of code.
+
+The first algebraic portion of the algorithm is to split the two inputs into their halves. However, instead of using mp\_mod\_2d and mp\_rshd
+to extract the halves, the respective code has been placed inline within the body of the function. To initialize the halves, the \textbf{used} and
+\textbf{sign} members are copied first. The first for loop on line @98,for@ copies the lower halves. Since they are both the same magnitude it
+is simpler to calculate both lower halves in a single loop. The for loop on lines @104,for@ and @109,for@ calculate the upper halves $x1$ and
+$y1$ respectively.
+
+By inlining the calculation of the halves, the Karatsuba multiplier has a slightly lower overhead and can be used for smaller magnitude inputs.
+
+When line @152,err@ is reached, the algorithm has completed succesfully. The ``error status'' variable $err$ is set to \textbf{MP\_OKAY} so that
+the same code that handles errors can be used to clear the temporary variables and return.
+
+\subsection{Toom-Cook $3$-Way Multiplication}
+Toom-Cook $3$-Way \cite{TOOM} multiplication is essentially the polynomial basis algorithm for $n = 2$ except that the points are
+chosen such that $\zeta$ is easy to compute and the resulting system of equations easy to reduce. Here, the points $\zeta_{0}$,
+$16 \cdot \zeta_{1 \over 2}$, $\zeta_1$, $\zeta_2$ and $\zeta_{\infty}$ make up the five required points to solve for the coefficients
+of the $W(x)$.
+
+With the five relations that Toom-Cook specifies, the following system of equations is formed.
+
+\begin{center}
+\begin{tabular}{rcrcrcrcrcr}
+$\zeta_0$ & $=$ & $0w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $1w_0$ \\
+$16 \cdot \zeta_{1 \over 2}$ & $=$ & $1w_4$ & $+$ & $2w_3$ & $+$ & $4w_2$ & $+$ & $8w_1$ & $+$ & $16w_0$ \\
+$\zeta_1$ & $=$ & $1w_4$ & $+$ & $1w_3$ & $+$ & $1w_2$ & $+$ & $1w_1$ & $+$ & $1w_0$ \\
+$\zeta_2$ & $=$ & $16w_4$ & $+$ & $8w_3$ & $+$ & $4w_2$ & $+$ & $2w_1$ & $+$ & $1w_0$ \\
+$\zeta_{\infty}$ & $=$ & $1w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $0w_0$ \\
+\end{tabular}
+\end{center}
+
+A trivial solution to this matrix requires $12$ subtractions, two multiplications by a small power of two, two divisions by a small power
+of two, two divisions by three and one multiplication by three. All of these $19$ sub-operations require less than quadratic time, meaning that
+the algorithm can be faster than a baseline multiplication. However, the greater complexity of this algorithm places the cutoff point
+(\textbf{TOOM\_MUL\_CUTOFF}) where Toom-Cook becomes more efficient much higher than the Karatsuba cutoff point.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_toom\_mul}. \\
+\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\
+\textbf{Output}. $c \leftarrow a \cdot b $ \\
+\hline \\
+Split $a$ and $b$ into three pieces. E.g. $a = a_2 \beta^{2k} + a_1 \beta^{k} + a_0$ \\
+1. $k \leftarrow \lfloor \mbox{min}(a.used, b.used) / 3 \rfloor$ \\
+2. $a_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\
+3. $a_1 \leftarrow \lfloor a / \beta^k \rfloor$, $a_1 \leftarrow a_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
+4. $a_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $a_2 \leftarrow a_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
+5. $b_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\
+6. $b_1 \leftarrow \lfloor a / \beta^k \rfloor$, $b_1 \leftarrow b_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
+7. $b_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $b_2 \leftarrow b_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
+\\
+Find the five equations for $w_0, w_1, ..., w_4$. \\
+8. $w_0 \leftarrow a_0 \cdot b_0$ \\
+9. $w_4 \leftarrow a_2 \cdot b_2$ \\
+10. $tmp_1 \leftarrow 2 \cdot a_0$, $tmp_1 \leftarrow a_1 + tmp_1$, $tmp_1 \leftarrow 2 \cdot tmp_1$, $tmp_1 \leftarrow tmp_1 + a_2$ \\
+11. $tmp_2 \leftarrow 2 \cdot b_0$, $tmp_2 \leftarrow b_1 + tmp_2$, $tmp_2 \leftarrow 2 \cdot tmp_2$, $tmp_2 \leftarrow tmp_2 + b_2$ \\
+12. $w_1 \leftarrow tmp_1 \cdot tmp_2$ \\
+13. $tmp_1 \leftarrow 2 \cdot a_2$, $tmp_1 \leftarrow a_1 + tmp_1$, $tmp_1 \leftarrow 2 \cdot tmp_1$, $tmp_1 \leftarrow tmp_1 + a_0$ \\
+14. $tmp_2 \leftarrow 2 \cdot b_2$, $tmp_2 \leftarrow b_1 + tmp_2$, $tmp_2 \leftarrow 2 \cdot tmp_2$, $tmp_2 \leftarrow tmp_2 + b_0$ \\
+15. $w_3 \leftarrow tmp_1 \cdot tmp_2$ \\
+16. $tmp_1 \leftarrow a_0 + a_1$, $tmp_1 \leftarrow tmp_1 + a_2$, $tmp_2 \leftarrow b_0 + b_1$, $tmp_2 \leftarrow tmp_2 + b_2$ \\
+17. $w_2 \leftarrow tmp_1 \cdot tmp_2$ \\
+\\
+Continued on the next page.\\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_toom\_mul}
+\end{figure}
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_toom\_mul} (continued). \\
+\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\
+\textbf{Output}. $c \leftarrow a \cdot b $ \\
+\hline \\
+Now solve the system of equations. \\
+18. $w_1 \leftarrow w_4 - w_1$, $w_3 \leftarrow w_3 - w_0$ \\
+19. $w_1 \leftarrow \lfloor w_1 / 2 \rfloor$, $w_3 \leftarrow \lfloor w_3 / 2 \rfloor$ \\
+20. $w_2 \leftarrow w_2 - w_0$, $w_2 \leftarrow w_2 - w_4$ \\
+21. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\
+22. $tmp_1 \leftarrow 8 \cdot w_0$, $w_1 \leftarrow w_1 - tmp_1$, $tmp_1 \leftarrow 8 \cdot w_4$, $w_3 \leftarrow w_3 - tmp_1$ \\
+23. $w_2 \leftarrow 3 \cdot w_2$, $w_2 \leftarrow w_2 - w_1$, $w_2 \leftarrow w_2 - w_3$ \\
+24. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\
+25. $w_1 \leftarrow \lfloor w_1 / 3 \rfloor, w_3 \leftarrow \lfloor w_3 / 3 \rfloor$ \\
+\\
+Now substitute $\beta^k$ for $x$ by shifting $w_0, w_1, ..., w_4$. \\
+26. for $n$ from $1$ to $4$ do \\
+\hspace{3mm}26.1 $w_n \leftarrow w_n \cdot \beta^{nk}$ \\
+27. $c \leftarrow w_0 + w_1$, $c \leftarrow c + w_2$, $c \leftarrow c + w_3$, $c \leftarrow c + w_4$ \\
+28. Return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_toom\_mul (continued)}
+\end{figure}
+
+\textbf{Algorithm mp\_toom\_mul.}
+This algorithm computes the product of two mp\_int variables $a$ and $b$ using the Toom-Cook approach. Compared to the Karatsuba multiplication, this
+algorithm has a lower asymptotic running time of approximately $O(n^{1.464})$ but at an obvious cost in overhead. In this
+description, several statements have been compounded to save space. The intention is that the statements are executed from left to right across
+any given step.
+
+The two inputs $a$ and $b$ are first split into three $k$-digit integers $a_0, a_1, a_2$ and $b_0, b_1, b_2$ respectively. From these smaller
+integers the coefficients of the polynomial basis representations $f(x)$ and $g(x)$ are known and can be used to find the relations required.
+
+The first two relations $w_0$ and $w_4$ are the points $\zeta_{0}$ and $\zeta_{\infty}$ respectively. The relation $w_1, w_2$ and $w_3$ correspond
+to the points $16 \cdot \zeta_{1 \over 2}, \zeta_{2}$ and $\zeta_{1}$ respectively. These are found using logical shifts to independently find
+$f(y)$ and $g(y)$ which significantly speeds up the algorithm.
+
+After the five relations $w_0, w_1, \ldots, w_4$ have been computed, the system they represent must be solved in order for the unknown coefficients
+$w_1, w_2$ and $w_3$ to be isolated. The steps 18 through 25 perform the system reduction required as previously described. Each step of
+the reduction represents the comparable matrix operation that would be performed had this been performed by pencil. For example, step 18 indicates
+that row $1$ must be subtracted from row $4$ and simultaneously row $0$ subtracted from row $3$.
+
+Once the coeffients have been isolated, the polynomial $W(x) = \sum_{i=0}^{2n} w_i x^i$ is known. By substituting $\beta^{k}$ for $x$, the integer
+result $a \cdot b$ is produced.
+
+EXAM,bn_mp_toom_mul.c
+
+The first obvious thing to note is that this algorithm is complicated. The complexity is worth it if you are multiplying very
+large numbers. For example, a 10,000 digit multiplication takes approximaly 99,282,205 fewer single precision multiplications with
+Toom--Cook than a Comba or baseline approach (this is a savings of more than 99$\%$). For most ``crypto'' sized numbers this
+algorithm is not practical as Karatsuba has a much lower cutoff point.
+
+First we split $a$ and $b$ into three roughly equal portions. This has been accomplished (lines @40,mod@ to @69,rshd@) with
+combinations of mp\_rshd() and mp\_mod\_2d() function calls. At this point $a = a2 \cdot \beta^2 + a1 \cdot \beta + a0$ and similiarly
+for $b$.
+
+Next we compute the five points $w0, w1, w2, w3$ and $w4$. Recall that $w0$ and $w4$ can be computed directly from the portions so
+we get those out of the way first (lines @72,mul@ and @77,mul@). Next we compute $w1, w2$ and $w3$ using Horners method.
+
+After this point we solve for the actual values of $w1, w2$ and $w3$ by reducing the $5 \times 5$ system which is relatively
+straight forward.
+
+\subsection{Signed Multiplication}
+Now that algorithms to handle multiplications of every useful dimensions have been developed, a rather simple finishing touch is required. So far all
+of the multiplication algorithms have been unsigned multiplications which leaves only a signed multiplication algorithm to be established.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_mul}. \\
+\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\
+\textbf{Output}. $c \leftarrow a \cdot b$ \\
+\hline \\
+1. If $a.sign = b.sign$ then \\
+\hspace{3mm}1.1 $sign = MP\_ZPOS$ \\
+2. else \\
+\hspace{3mm}2.1 $sign = MP\_ZNEG$ \\
+3. If min$(a.used, b.used) \ge TOOM\_MUL\_CUTOFF$ then \\
+\hspace{3mm}3.1 $c \leftarrow a \cdot b$ using algorithm mp\_toom\_mul \\
+4. else if min$(a.used, b.used) \ge KARATSUBA\_MUL\_CUTOFF$ then \\
+\hspace{3mm}4.1 $c \leftarrow a \cdot b$ using algorithm mp\_karatsuba\_mul \\
+5. else \\
+\hspace{3mm}5.1 $digs \leftarrow a.used + b.used + 1$ \\
+\hspace{3mm}5.2 If $digs < MP\_ARRAY$ and min$(a.used, b.used) \le \delta$ then \\
+\hspace{6mm}5.2.1 $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm fast\_s\_mp\_mul\_digs. \\
+\hspace{3mm}5.3 else \\
+\hspace{6mm}5.3.1 $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm s\_mp\_mul\_digs. \\
+6. $c.sign \leftarrow sign$ \\
+7. Return the result of the unsigned multiplication performed. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_mul}
+\end{figure}
+
+\textbf{Algorithm mp\_mul.}
+This algorithm performs the signed multiplication of two inputs. It will make use of any of the three unsigned multiplication algorithms
+available when the input is of appropriate size. The \textbf{sign} of the result is not set until the end of the algorithm since algorithm
+s\_mp\_mul\_digs will clear it.
+
+EXAM,bn_mp_mul.c
+
+The implementation is rather simplistic and is not particularly noteworthy. Line @22,?@ computes the sign of the result using the ``?''
+operator from the C programming language. Line @37,<<@ computes $\delta$ using the fact that $1 << k$ is equal to $2^k$.
+
+\section{Squaring}
+\label{sec:basesquare}
+
+Squaring is a special case of multiplication where both multiplicands are equal. At first it may seem like there is no significant optimization
+available but in fact there is. Consider the multiplication of $576$ against $241$. In total there will be nine single precision multiplications
+performed which are $1\cdot 6$, $1 \cdot 7$, $1 \cdot 5$, $4 \cdot 6$, $4 \cdot 7$, $4 \cdot 5$, $2 \cdot 6$, $2 \cdot 7$ and $2 \cdot 5$. Now consider
+the multiplication of $123$ against $123$. The nine products are $3 \cdot 3$, $3 \cdot 2$, $3 \cdot 1$, $2 \cdot 3$, $2 \cdot 2$, $2 \cdot 1$,
+$1 \cdot 3$, $1 \cdot 2$ and $1 \cdot 1$. On closer inspection some of the products are equivalent. For example, $3 \cdot 2 = 2 \cdot 3$
+and $3 \cdot 1 = 1 \cdot 3$.
+
+For any $n$-digit input, there are ${{\left (n^2 + n \right)}\over 2}$ possible unique single precision multiplications required compared to the $n^2$
+required for multiplication. The following diagram gives an example of the operations required.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{ccccc|c}
+&&1&2&3&\\
+$\times$ &&1&2&3&\\
+\hline && $3 \cdot 1$ & $3 \cdot 2$ & $3 \cdot 3$ & Row 0\\
+ & $2 \cdot 1$ & $2 \cdot 2$ & $2 \cdot 3$ && Row 1 \\
+ $1 \cdot 1$ & $1 \cdot 2$ & $1 \cdot 3$ &&& Row 2 \\
+\end{tabular}
+\end{center}
+\caption{Squaring Optimization Diagram}
+\end{figure}
+
+MARK,SQUARE
+Starting from zero and numbering the columns from right to left a very simple pattern becomes obvious. For the purposes of this discussion let $x$
+represent the number being squared. The first observation is that in row $k$ the $2k$'th column of the product has a $\left (x_k \right)^2$ term in it.
+
+The second observation is that every column $j$ in row $k$ where $j \ne 2k$ is part of a double product. Every non-square term of a column will
+appear twice hence the name ``double product''. Every odd column is made up entirely of double products. In fact every column is made up of double
+products and at most one square (\textit{see the exercise section}).
+
+The third and final observation is that for row $k$ the first unique non-square term, that is, one that hasn't already appeared in an earlier row,
+occurs at column $2k + 1$. For example, on row $1$ of the previous squaring, column one is part of the double product with column one from row zero.
+Column two of row one is a square and column three is the first unique column.
+
+\subsection{The Baseline Squaring Algorithm}
+The baseline squaring algorithm is meant to be a catch-all squaring algorithm. It will handle any of the input sizes that the faster routines
+will not handle.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{s\_mp\_sqr}. \\
+\textbf{Input}. mp\_int $a$ \\
+\textbf{Output}. $b \leftarrow a^2$ \\
+\hline \\
+1. Init a temporary mp\_int of at least $2 \cdot a.used +1$ digits. (\textit{mp\_init\_size}) \\
+2. If step 1 failed return(\textit{MP\_MEM}) \\
+3. $t.used \leftarrow 2 \cdot a.used + 1$ \\
+4. For $ix$ from 0 to $a.used - 1$ do \\
+\hspace{3mm}Calculate the square. \\
+\hspace{3mm}4.1 $\hat r \leftarrow t_{2ix} + \left (a_{ix} \right )^2$ \\
+\hspace{3mm}4.2 $t_{2ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{3mm}Calculate the double products after the square. \\
+\hspace{3mm}4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
+\hspace{3mm}4.4 For $iy$ from $ix + 1$ to $a.used - 1$ do \\
+\hspace{6mm}4.4.1 $\hat r \leftarrow 2 \cdot a_{ix}a_{iy} + t_{ix + iy} + u$ \\
+\hspace{6mm}4.4.2 $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{6mm}4.4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
+\hspace{3mm}Set the last carry. \\
+\hspace{3mm}4.5 While $u > 0$ do \\
+\hspace{6mm}4.5.1 $iy \leftarrow iy + 1$ \\
+\hspace{6mm}4.5.2 $\hat r \leftarrow t_{ix + iy} + u$ \\
+\hspace{6mm}4.5.3 $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{6mm}4.5.4 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
+5. Clamp excess digits of $t$. (\textit{mp\_clamp}) \\
+6. Exchange $b$ and $t$. \\
+7. Clear $t$ (\textit{mp\_clear}) \\
+8. Return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm s\_mp\_sqr}
+\end{figure}
+
+\textbf{Algorithm s\_mp\_sqr.}
+This algorithm computes the square of an input using the three observations on squaring. It is based fairly faithfully on algorithm 14.16 of HAC
+\cite[pp.596-597]{HAC}. Similar to algorithm s\_mp\_mul\_digs, a temporary mp\_int is allocated to hold the result of the squaring. This allows the
+destination mp\_int to be the same as the source mp\_int.
+
+The outer loop of this algorithm begins on step 4. It is best to think of the outer loop as walking down the rows of the partial results, while
+the inner loop computes the columns of the partial result. Step 4.1 and 4.2 compute the square term for each row, and step 4.3 and 4.4 propagate
+the carry and compute the double products.
+
+The requirement that a mp\_word be able to represent the range $0 \le x < 2 \beta^2$ arises from this
+very algorithm. The product $a_{ix}a_{iy}$ will lie in the range $0 \le x \le \beta^2 - 2\beta + 1$ which is obviously less than $\beta^2$ meaning that
+when it is multiplied by two, it can be properly represented by a mp\_word.
+
+Similar to algorithm s\_mp\_mul\_digs, after every pass of the inner loop, the destination is correctly set to the sum of all of the partial
+results calculated so far. This involves expensive carry propagation which will be eliminated in the next algorithm.
+
+EXAM,bn_s_mp_sqr.c
+
+Inside the outer loop (line @32,for@) the square term is calculated on line @35,r =@. The carry (line @42,>>@) has been
+extracted from the mp\_word accumulator using a right shift. Aliases for $a_{ix}$ and $t_{ix+iy}$ are initialized
+(lines @45,tmpx@ and @48,tmpt@) to simplify the inner loop. The doubling is performed using two
+additions (line @57,r + r@) since it is usually faster than shifting, if not at least as fast.
+
+The important observation is that the inner loop does not begin at $iy = 0$ like for multiplication. As such the inner loops
+get progressively shorter as the algorithm proceeds. This is what leads to the savings compared to using a multiplication to
+square a number.
+
+\subsection{Faster Squaring by the ``Comba'' Method}
+A major drawback to the baseline method is the requirement for single precision shifting inside the $O(n^2)$ nested loop. Squaring has an additional
+drawback that it must double the product inside the inner loop as well. As for multiplication, the Comba technique can be used to eliminate these
+performance hazards.
+
+The first obvious solution is to make an array of mp\_words which will hold all of the columns. This will indeed eliminate all of the carry
+propagation operations from the inner loop. However, the inner product must still be doubled $O(n^2)$ times. The solution stems from the simple fact
+that $2a + 2b + 2c = 2(a + b + c)$. That is the sum of all of the double products is equal to double the sum of all the products. For example,
+$ab + ba + ac + ca = 2ab + 2ac = 2(ab + ac)$.
+
+However, we cannot simply double all of the columns, since the squares appear only once per row. The most practical solution is to have two
+mp\_word arrays. One array will hold the squares and the other array will hold the double products. With both arrays the doubling and
+carry propagation can be moved to a $O(n)$ work level outside the $O(n^2)$ level. In this case, we have an even simpler solution in mind.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{fast\_s\_mp\_sqr}. \\
+\textbf{Input}. mp\_int $a$ \\
+\textbf{Output}. $b \leftarrow a^2$ \\
+\hline \\
+Place an array of \textbf{MP\_WARRAY} mp\_digits named $W$ on the stack. \\
+1. If $b.alloc < 2a.used + 1$ then grow $b$ to $2a.used + 1$ digits. (\textit{mp\_grow}). \\
+2. If step 1 failed return(\textit{MP\_MEM}). \\
+\\
+3. $pa \leftarrow 2 \cdot a.used$ \\
+4. $\hat W1 \leftarrow 0$ \\
+5. for $ix$ from $0$ to $pa - 1$ do \\
+\hspace{3mm}5.1 $\_ \hat W \leftarrow 0$ \\
+\hspace{3mm}5.2 $ty \leftarrow \mbox{MIN}(a.used - 1, ix)$ \\
+\hspace{3mm}5.3 $tx \leftarrow ix - ty$ \\
+\hspace{3mm}5.4 $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\
+\hspace{3mm}5.5 $iy \leftarrow \mbox{MIN}(iy, \lfloor \left (ty - tx + 1 \right )/2 \rfloor)$ \\
+\hspace{3mm}5.6 for $iz$ from $0$ to $iz - 1$ do \\
+\hspace{6mm}5.6.1 $\_ \hat W \leftarrow \_ \hat W + a_{tx + iz}a_{ty - iz}$ \\
+\hspace{3mm}5.7 $\_ \hat W \leftarrow 2 \cdot \_ \hat W + \hat W1$ \\
+\hspace{3mm}5.8 if $ix$ is even then \\
+\hspace{6mm}5.8.1 $\_ \hat W \leftarrow \_ \hat W + \left ( a_{\lfloor ix/2 \rfloor}\right )^2$ \\
+\hspace{3mm}5.9 $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$ \\
+\hspace{3mm}5.10 $\hat W1 \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\
+\\
+6. $oldused \leftarrow b.used$ \\
+7. $b.used \leftarrow 2 \cdot a.used$ \\
+8. for $ix$ from $0$ to $pa - 1$ do \\
+\hspace{3mm}8.1 $b_{ix} \leftarrow W_{ix}$ \\
+9. for $ix$ from $pa$ to $oldused - 1$ do \\
+\hspace{3mm}9.1 $b_{ix} \leftarrow 0$ \\
+10. Clamp excess digits from $b$. (\textit{mp\_clamp}) \\
+11. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm fast\_s\_mp\_sqr}
+\end{figure}
+
+\textbf{Algorithm fast\_s\_mp\_sqr.}
+This algorithm computes the square of an input using the Comba technique. It is designed to be a replacement for algorithm
+s\_mp\_sqr when the number of input digits is less than \textbf{MP\_WARRAY} and less than $\delta \over 2$.
+This algorithm is very similar to the Comba multiplier except with a few key differences we shall make note of.
+
+First, we have an accumulator and carry variables $\_ \hat W$ and $\hat W1$ respectively. This is because the inner loop
+products are to be doubled. If we had added the previous carry in we would be doubling too much. Next we perform an
+addition MIN condition on $iy$ (step 5.5) to prevent overlapping digits. For example, $a_3 \cdot a_5$ is equal
+$a_5 \cdot a_3$. Whereas in the multiplication case we would have $5 < a.used$ and $3 \ge 0$ is maintained since we double the sum
+of the products just outside the inner loop we have to avoid doing this. This is also a good thing since we perform
+fewer multiplications and the routine ends up being faster.
+
+Finally the last difference is the addition of the ``square'' term outside the inner loop (step 5.8). We add in the square
+only to even outputs and it is the square of the term at the $\lfloor ix / 2 \rfloor$ position.
+
+EXAM,bn_fast_s_mp_sqr.c
+
+This implementation is essentially a copy of Comba multiplication with the appropriate changes added to make it faster for
+the special case of squaring.
+
+\subsection{Polynomial Basis Squaring}
+The same algorithm that performs optimal polynomial basis multiplication can be used to perform polynomial basis squaring. The minor exception
+is that $\zeta_y = f(y)g(y)$ is actually equivalent to $\zeta_y = f(y)^2$ since $f(y) = g(y)$. Instead of performing $2n + 1$
+multiplications to find the $\zeta$ relations, squaring operations are performed instead.
+
+\subsection{Karatsuba Squaring}
+Let $f(x) = ax + b$ represent the polynomial basis representation of a number to square.
+Let $h(x) = \left ( f(x) \right )^2$ represent the square of the polynomial. The Karatsuba equation can be modified to square a
+number with the following equation.
+
+\begin{equation}
+h(x) = a^2x^2 + \left ((a + b)^2 - (a^2 + b^2) \right )x + b^2
+\end{equation}
+
+Upon closer inspection this equation only requires the calculation of three half-sized squares: $a^2$, $b^2$ and $(a + b)^2$. As in
+Karatsuba multiplication, this algorithm can be applied recursively on the input and will achieve an asymptotic running time of
+$O \left ( n^{lg(3)} \right )$.
+
+If the asymptotic times of Karatsuba squaring and multiplication are the same, why not simply use the multiplication algorithm
+instead? The answer to this arises from the cutoff point for squaring. As in multiplication there exists a cutoff point, at which the
+time required for a Comba based squaring and a Karatsuba based squaring meet. Due to the overhead inherent in the Karatsuba method, the cutoff
+point is fairly high. For example, on an AMD Athlon XP processor with $\beta = 2^{28}$, the cutoff point is around 127 digits.
+
+Consider squaring a 200 digit number with this technique. It will be split into two 100 digit halves which are subsequently squared.
+The 100 digit halves will not be squared using Karatsuba, but instead using the faster Comba based squaring algorithm. If Karatsuba multiplication
+were used instead, the 100 digit numbers would be squared with a slower Comba based multiplication.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_karatsuba\_sqr}. \\
+\textbf{Input}. mp\_int $a$ \\
+\textbf{Output}. $b \leftarrow a^2$ \\
+\hline \\
+1. Initialize the following temporary mp\_ints: $x0$, $x1$, $t1$, $t2$, $x0x0$ and $x1x1$. \\
+2. If any of the initializations on step 1 failed return(\textit{MP\_MEM}). \\
+\\
+Split the input. e.g. $a = x1\beta^B + x0$ \\
+3. $B \leftarrow \lfloor a.used / 2 \rfloor$ \\
+4. $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\
+5. $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_lshd}) \\
+\\
+Calculate the three squares. \\
+6. $x0x0 \leftarrow x0^2$ (\textit{mp\_sqr}) \\
+7. $x1x1 \leftarrow x1^2$ \\
+8. $t1 \leftarrow x1 + x0$ (\textit{s\_mp\_add}) \\
+9. $t1 \leftarrow t1^2$ \\
+\\
+Compute the middle term. \\
+10. $t2 \leftarrow x0x0 + x1x1$ (\textit{s\_mp\_add}) \\
+11. $t1 \leftarrow t1 - t2$ \\
+\\
+Compute final product. \\
+12. $t1 \leftarrow t1\beta^B$ (\textit{mp\_lshd}) \\
+13. $x1x1 \leftarrow x1x1\beta^{2B}$ \\
+14. $t1 \leftarrow t1 + x0x0$ \\
+15. $b \leftarrow t1 + x1x1$ \\
+16. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_karatsuba\_sqr}
+\end{figure}
+
+\textbf{Algorithm mp\_karatsuba\_sqr.}
+This algorithm computes the square of an input $a$ using the Karatsuba technique. This algorithm is very similar to the Karatsuba based
+multiplication algorithm with the exception that the three half-size multiplications have been replaced with three half-size squarings.
+
+The radix point for squaring is simply placed exactly in the middle of the digits when the input has an odd number of digits, otherwise it is
+placed just below the middle. Step 3, 4 and 5 compute the two halves required using $B$
+as the radix point. The first two squares in steps 6 and 7 are rather straightforward while the last square is of a more compact form.
+
+By expanding $\left (x1 + x0 \right )^2$, the $x1^2$ and $x0^2$ terms in the middle disappear, that is $(x0 - x1)^2 - (x1^2 + x0^2) = 2 \cdot x0 \cdot x1$.
+Now if $5n$ single precision additions and a squaring of $n$-digits is faster than multiplying two $n$-digit numbers and doubling then
+this method is faster. Assuming no further recursions occur, the difference can be estimated with the following inequality.
+
+Let $p$ represent the cost of a single precision addition and $q$ the cost of a single precision multiplication both in terms of time\footnote{Or
+machine clock cycles.}.
+
+\begin{equation}
+5pn +{{q(n^2 + n)} \over 2} \le pn + qn^2
+\end{equation}
+
+For example, on an AMD Athlon XP processor $p = {1 \over 3}$ and $q = 6$. This implies that the following inequality should hold.
+\begin{center}
+\begin{tabular}{rcl}
+${5n \over 3} + 3n^2 + 3n$ & $<$ & ${n \over 3} + 6n^2$ \\
+${5 \over 3} + 3n + 3$ & $<$ & ${1 \over 3} + 6n$ \\
+${13 \over 9}$ & $<$ & $n$ \\
+\end{tabular}
+\end{center}
+
+This results in a cutoff point around $n = 2$. As a consequence it is actually faster to compute the middle term the ``long way'' on processors
+where multiplication is substantially slower\footnote{On the Athlon there is a 1:17 ratio between clock cycles for addition and multiplication. On
+the Intel P4 processor this ratio is 1:29 making this method even more beneficial. The only common exception is the ARMv4 processor which has a
+ratio of 1:7. } than simpler operations such as addition.
+
+EXAM,bn_mp_karatsuba_sqr.c
+
+This implementation is largely based on the implementation of algorithm mp\_karatsuba\_mul. It uses the same inline style to copy and
+shift the input into the two halves. The loop from line @54,{@ to line @70,}@ has been modified since only one input exists. The \textbf{used}
+count of both $x0$ and $x1$ is fixed up and $x0$ is clamped before the calculations begin. At this point $x1$ and $x0$ are valid equivalents
+to the respective halves as if mp\_rshd and mp\_mod\_2d had been used.
+
+By inlining the copy and shift operations the cutoff point for Karatsuba multiplication can be lowered. On the Athlon the cutoff point
+is exactly at the point where Comba squaring can no longer be used (\textit{128 digits}). On slower processors such as the Intel P4
+it is actually below the Comba limit (\textit{at 110 digits}).
+
+This routine uses the same error trap coding style as mp\_karatsuba\_sqr. As the temporary variables are initialized errors are
+redirected to the error trap higher up. If the algorithm completes without error the error code is set to \textbf{MP\_OKAY} and
+mp\_clears are executed normally.
+
+\subsection{Toom-Cook Squaring}
+The Toom-Cook squaring algorithm mp\_toom\_sqr is heavily based on the algorithm mp\_toom\_mul with the exception that squarings are used
+instead of multiplication to find the five relations. The reader is encouraged to read the description of the latter algorithm and try to
+derive their own Toom-Cook squaring algorithm.
+
+\subsection{High Level Squaring}
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_sqr}. \\
+\textbf{Input}. mp\_int $a$ \\
+\textbf{Output}. $b \leftarrow a^2$ \\
+\hline \\
+1. If $a.used \ge TOOM\_SQR\_CUTOFF$ then \\
+\hspace{3mm}1.1 $b \leftarrow a^2$ using algorithm mp\_toom\_sqr \\
+2. else if $a.used \ge KARATSUBA\_SQR\_CUTOFF$ then \\
+\hspace{3mm}2.1 $b \leftarrow a^2$ using algorithm mp\_karatsuba\_sqr \\
+3. else \\
+\hspace{3mm}3.1 $digs \leftarrow a.used + b.used + 1$ \\
+\hspace{3mm}3.2 If $digs < MP\_ARRAY$ and $a.used \le \delta$ then \\
+\hspace{6mm}3.2.1 $b \leftarrow a^2$ using algorithm fast\_s\_mp\_sqr. \\
+\hspace{3mm}3.3 else \\
+\hspace{6mm}3.3.1 $b \leftarrow a^2$ using algorithm s\_mp\_sqr. \\
+4. $b.sign \leftarrow MP\_ZPOS$ \\
+5. Return the result of the unsigned squaring performed. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_sqr}
+\end{figure}
+
+\textbf{Algorithm mp\_sqr.}
+This algorithm computes the square of the input using one of four different algorithms. If the input is very large and has at least
+\textbf{TOOM\_SQR\_CUTOFF} or \textbf{KARATSUBA\_SQR\_CUTOFF} digits then either the Toom-Cook or the Karatsuba Squaring algorithm is used. If
+neither of the polynomial basis algorithms should be used then either the Comba or baseline algorithm is used.
+
+EXAM,bn_mp_sqr.c
+
+\section*{Exercises}
+\begin{tabular}{cl}
+$\left [ 3 \right ] $ & Devise an efficient algorithm for selection of the radix point to handle inputs \\
+ & that have different number of digits in Karatsuba multiplication. \\
+ & \\
+$\left [ 2 \right ] $ & In ~SQUARE~ the fact that every column of a squaring is made up \\
+ & of double products and at most one square is stated. Prove this statement. \\
+ & \\
+$\left [ 3 \right ] $ & Prove the equation for Karatsuba squaring. \\
+ & \\
+$\left [ 1 \right ] $ & Prove that Karatsuba squaring requires $O \left (n^{lg(3)} \right )$ time. \\
+ & \\
+$\left [ 2 \right ] $ & Determine the minimal ratio between addition and multiplication clock cycles \\
+ & required for equation $6.7$ to be true. \\
+ & \\
+$\left [ 3 \right ] $ & Implement a threaded version of Comba multiplication (and squaring) where you \\
+ & compute subsets of the columns in each thread. Determine a cutoff point where \\
+ & it is effective and add the logic to mp\_mul() and mp\_sqr(). \\
+ &\\
+$\left [ 4 \right ] $ & Same as the previous but also modify the Karatsuba and Toom-Cook. You must \\
+ & increase the throughput of mp\_exptmod() for random odd moduli in the range \\
+ & $512 \ldots 4096$ bits significantly ($> 2x$) to complete this challenge. \\
+ & \\
+\end{tabular}
+
+\chapter{Modular Reduction}
+MARK,REDUCTION
+\section{Basics of Modular Reduction}
+\index{modular residue}
+Modular reduction is an operation that arises quite often within public key cryptography algorithms and various number theoretic algorithms,
+such as factoring. Modular reduction algorithms are the third class of algorithms of the ``multipliers'' set. A number $a$ is said to be \textit{reduced}
+modulo another number $b$ by finding the remainder of the division $a/b$. Full integer division with remainder is a topic to be covered
+in~\ref{sec:division}.
+
+Modular reduction is equivalent to solving for $r$ in the following equation. $a = bq + r$ where $q = \lfloor a/b \rfloor$. The result
+$r$ is said to be ``congruent to $a$ modulo $b$'' which is also written as $r \equiv a \mbox{ (mod }b\mbox{)}$. In other vernacular $r$ is known as the
+``modular residue'' which leads to ``quadratic residue''\footnote{That's fancy talk for $b \equiv a^2 \mbox{ (mod }p\mbox{)}$.} and
+other forms of residues.
+
+Modular reductions are normally used to create either finite groups, rings or fields. The most common usage for performance driven modular reductions
+is in modular exponentiation algorithms. That is to compute $d = a^b \mbox{ (mod }c\mbox{)}$ as fast as possible. This operation is used in the
+RSA and Diffie-Hellman public key algorithms, for example. Modular multiplication and squaring also appears as a fundamental operation in
+elliptic curve cryptographic algorithms. As will be discussed in the subsequent chapter there exist fast algorithms for computing modular
+exponentiations without having to perform (\textit{in this example}) $b - 1$ multiplications. These algorithms will produce partial results in the
+range $0 \le x < c^2$ which can be taken advantage of to create several efficient algorithms. They have also been used to create redundancy check
+algorithms known as CRCs, error correction codes such as Reed-Solomon and solve a variety of number theoeretic problems.
+
+\section{The Barrett Reduction}
+The Barrett reduction algorithm \cite{BARRETT} was inspired by fast division algorithms which multiply by the reciprocal to emulate
+division. Barretts observation was that the residue $c$ of $a$ modulo $b$ is equal to
+
+\begin{equation}
+c = a - b \cdot \lfloor a/b \rfloor
+\end{equation}
+
+Since algorithms such as modular exponentiation would be using the same modulus extensively, typical DSP\footnote{It is worth noting that Barrett's paper
+targeted the DSP56K processor.} intuition would indicate the next step would be to replace $a/b$ by a multiplication by the reciprocal. However,
+DSP intuition on its own will not work as these numbers are considerably larger than the precision of common DSP floating point data types.
+It would take another common optimization to optimize the algorithm.
+
+\subsection{Fixed Point Arithmetic}
+The trick used to optimize the above equation is based on a technique of emulating floating point data types with fixed precision integers. Fixed
+point arithmetic would become very popular as it greatly optimize the ``3d-shooter'' genre of games in the mid 1990s when floating point units were
+fairly slow if not unavailable. The idea behind fixed point arithmetic is to take a normal $k$-bit integer data type and break it into $p$-bit
+integer and a $q$-bit fraction part (\textit{where $p+q = k$}).
+
+In this system a $k$-bit integer $n$ would actually represent $n/2^q$. For example, with $q = 4$ the integer $n = 37$ would actually represent the
+value $2.3125$. To multiply two fixed point numbers the integers are multiplied using traditional arithmetic and subsequently normalized by
+moving the implied decimal point back to where it should be. For example, with $q = 4$ to multiply the integers $9$ and $5$ they must be converted
+to fixed point first by multiplying by $2^q$. Let $a = 9(2^q)$ represent the fixed point representation of $9$ and $b = 5(2^q)$ represent the
+fixed point representation of $5$. The product $ab$ is equal to $45(2^{2q})$ which when normalized by dividing by $2^q$ produces $45(2^q)$.
+
+This technique became popular since a normal integer multiplication and logical shift right are the only required operations to perform a multiplication
+of two fixed point numbers. Using fixed point arithmetic, division can be easily approximated by multiplying by the reciprocal. If $2^q$ is
+equivalent to one than $2^q/b$ is equivalent to the fixed point approximation of $1/b$ using real arithmetic. Using this fact dividing an integer
+$a$ by another integer $b$ can be achieved with the following expression.
+
+\begin{equation}
+\lfloor a / b \rfloor \mbox{ }\approx\mbox{ } \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor
+\end{equation}
+
+The precision of the division is proportional to the value of $q$. If the divisor $b$ is used frequently as is the case with
+modular exponentiation pre-computing $2^q/b$ will allow a division to be performed with a multiplication and a right shift. Both operations
+are considerably faster than division on most processors.
+
+Consider dividing $19$ by $5$. The correct result is $\lfloor 19/5 \rfloor = 3$. With $q = 3$ the reciprocal is $\lfloor 2^q/5 \rfloor = 1$ which
+leads to a product of $19$ which when divided by $2^q$ produces $2$. However, with $q = 4$ the reciprocal is $\lfloor 2^q/5 \rfloor = 3$ and
+the result of the emulated division is $\lfloor 3 \cdot 19 / 2^q \rfloor = 3$ which is correct. The value of $2^q$ must be close to or ideally
+larger than the dividend. In effect if $a$ is the dividend then $q$ should allow $0 \le \lfloor a/2^q \rfloor \le 1$ in order for this approach
+to work correctly. Plugging this form of divison into the original equation the following modular residue equation arises.
+
+\begin{equation}
+c = a - b \cdot \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor
+\end{equation}
+
+Using the notation from \cite{BARRETT} the value of $\lfloor 2^q / b \rfloor$ will be represented by the $\mu$ symbol. Using the $\mu$
+variable also helps re-inforce the idea that it is meant to be computed once and re-used.
+
+\begin{equation}
+c = a - b \cdot \lfloor (a \cdot \mu)/2^q \rfloor
+\end{equation}
+
+Provided that $2^q \ge a$ this algorithm will produce a quotient that is either exactly correct or off by a value of one. In the context of Barrett
+reduction the value of $a$ is bound by $0 \le a \le (b - 1)^2$ meaning that $2^q \ge b^2$ is sufficient to ensure the reciprocal will have enough
+precision.
+
+Let $n$ represent the number of digits in $b$. This algorithm requires approximately $2n^2$ single precision multiplications to produce the quotient and
+another $n^2$ single precision multiplications to find the residue. In total $3n^2$ single precision multiplications are required to
+reduce the number.
+
+For example, if $b = 1179677$ and $q = 41$ ($2^q > b^2$), then the reciprocal $\mu$ is equal to $\lfloor 2^q / b \rfloor = 1864089$. Consider reducing
+$a = 180388626447$ modulo $b$ using the above reduction equation. The quotient using the new formula is $\lfloor (a \cdot \mu) / 2^q \rfloor = 152913$.
+By subtracting $152913b$ from $a$ the correct residue $a \equiv 677346 \mbox{ (mod }b\mbox{)}$ is found.
+
+\subsection{Choosing a Radix Point}
+Using the fixed point representation a modular reduction can be performed with $3n^2$ single precision multiplications. If that were the best
+that could be achieved a full division\footnote{A division requires approximately $O(2cn^2)$ single precision multiplications for a small value of $c$.
+See~\ref{sec:division} for further details.} might as well be used in its place. The key to optimizing the reduction is to reduce the precision of
+the initial multiplication that finds the quotient.
+
+Let $a$ represent the number of which the residue is sought. Let $b$ represent the modulus used to find the residue. Let $m$ represent
+the number of digits in $b$. For the purposes of this discussion we will assume that the number of digits in $a$ is $2m$, which is generally true if
+two $m$-digit numbers have been multiplied. Dividing $a$ by $b$ is the same as dividing a $2m$ digit integer by a $m$ digit integer. Digits below the
+$m - 1$'th digit of $a$ will contribute at most a value of $1$ to the quotient because $\beta^k < b$ for any $0 \le k \le m - 1$. Another way to
+express this is by re-writing $a$ as two parts. If $a' \equiv a \mbox{ (mod }b^m\mbox{)}$ and $a'' = a - a'$ then
+${a \over b} \equiv {{a' + a''} \over b}$ which is equivalent to ${a' \over b} + {a'' \over b}$. Since $a'$ is bound to be less than $b$ the quotient
+is bound by $0 \le {a' \over b} < 1$.
+
+Since the digits of $a'$ do not contribute much to the quotient the observation is that they might as well be zero. However, if the digits
+``might as well be zero'' they might as well not be there in the first place. Let $q_0 = \lfloor a/\beta^{m-1} \rfloor$ represent the input
+with the irrelevant digits trimmed. Now the modular reduction is trimmed to the almost equivalent equation
+
+\begin{equation}
+c = a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor
+\end{equation}
+
+Note that the original divisor $2^q$ has been replaced with $\beta^{m+1}$ where in this case $q$ is a multiple of $lg(\beta)$. Also note that the
+exponent on the divisor when added to the amount $q_0$ was shifted by equals $2m$. If the optimization had not been performed the divisor
+would have the exponent $2m$ so in the end the exponents do ``add up''. Using the above equation the quotient
+$\lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ can be off from the true quotient by at most two. The original fixed point quotient can be off
+by as much as one (\textit{provided the radix point is chosen suitably}) and now that the lower irrelevent digits have been trimmed the quotient
+can be off by an additional value of one for a total of at most two. This implies that
+$0 \le a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor < 3b$. By first subtracting $b$ times the quotient and then conditionally subtracting
+$b$ once or twice the residue is found.
+
+The quotient is now found using $(m + 1)(m) = m^2 + m$ single precision multiplications and the residue with an additional $m^2$ single
+precision multiplications, ignoring the subtractions required. In total $2m^2 + m$ single precision multiplications are required to find the residue.
+This is considerably faster than the original attempt.
+
+For example, let $\beta = 10$ represent the radix of the digits. Let $b = 9999$ represent the modulus which implies $m = 4$. Let $a = 99929878$
+represent the value of which the residue is desired. In this case $q = 8$ since $10^7 < 9999^2$ meaning that $\mu = \lfloor \beta^{q}/b \rfloor = 10001$.
+With the new observation the multiplicand for the quotient is equal to $q_0 = \lfloor a / \beta^{m - 1} \rfloor = 99929$. The quotient is then
+$\lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor = 9993$. Subtracting $9993b$ from $a$ and the correct residue $a \equiv 9871 \mbox{ (mod }b\mbox{)}$
+is found.
+
+\subsection{Trimming the Quotient}
+So far the reduction algorithm has been optimized from $3m^2$ single precision multiplications down to $2m^2 + m$ single precision multiplications. As
+it stands now the algorithm is already fairly fast compared to a full integer division algorithm. However, there is still room for
+optimization.
+
+After the first multiplication inside the quotient ($q_0 \cdot \mu$) the value is shifted right by $m + 1$ places effectively nullifying the lower
+half of the product. It would be nice to be able to remove those digits from the product to effectively cut down the number of single precision
+multiplications. If the number of digits in the modulus $m$ is far less than $\beta$ a full product is not required for the algorithm to work properly.
+In fact the lower $m - 2$ digits will not affect the upper half of the product at all and do not need to be computed.
+
+The value of $\mu$ is a $m$-digit number and $q_0$ is a $m + 1$ digit number. Using a full multiplier $(m + 1)(m) = m^2 + m$ single precision
+multiplications would be required. Using a multiplier that will only produce digits at and above the $m - 1$'th digit reduces the number
+of single precision multiplications to ${m^2 + m} \over 2$ single precision multiplications.
+
+\subsection{Trimming the Residue}
+After the quotient has been calculated it is used to reduce the input. As previously noted the algorithm is not exact and it can be off by a small
+multiple of the modulus, that is $0 \le a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor < 3b$. If $b$ is $m$ digits than the
+result of reduction equation is a value of at most $m + 1$ digits (\textit{provided $3 < \beta$}) implying that the upper $m - 1$ digits are
+implicitly zero.
+
+The next optimization arises from this very fact. Instead of computing $b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ using a full
+$O(m^2)$ multiplication algorithm only the lower $m+1$ digits of the product have to be computed. Similarly the value of $a$ can
+be reduced modulo $\beta^{m+1}$ before the multiple of $b$ is subtracted which simplifes the subtraction as well. A multiplication that produces
+only the lower $m+1$ digits requires ${m^2 + 3m - 2} \over 2$ single precision multiplications.
+
+With both optimizations in place the algorithm is the algorithm Barrett proposed. It requires $m^2 + 2m - 1$ single precision multiplications which
+is considerably faster than the straightforward $3m^2$ method.
+
+\subsection{The Barrett Algorithm}
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_reduce}. \\
+\textbf{Input}. mp\_int $a$, mp\_int $b$ and $\mu = \lfloor \beta^{2m}/b \rfloor, m = \lceil lg_{\beta}(b) \rceil, (0 \le a < b^2, b > 1)$ \\
+\textbf{Output}. $a \mbox{ (mod }b\mbox{)}$ \\
+\hline \\
+Let $m$ represent the number of digits in $b$. \\
+1. Make a copy of $a$ and store it in $q$. (\textit{mp\_init\_copy}) \\
+2. $q \leftarrow \lfloor q / \beta^{m - 1} \rfloor$ (\textit{mp\_rshd}) \\
+\\
+Produce the quotient. \\
+3. $q \leftarrow q \cdot \mu$ (\textit{note: only produce digits at or above $m-1$}) \\
+4. $q \leftarrow \lfloor q / \beta^{m + 1} \rfloor$ \\
+\\
+Subtract the multiple of modulus from the input. \\
+5. $a \leftarrow a \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{mp\_mod\_2d}) \\
+6. $q \leftarrow q \cdot b \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{s\_mp\_mul\_digs}) \\
+7. $a \leftarrow a - q$ (\textit{mp\_sub}) \\
+\\
+Add $\beta^{m+1}$ if a carry occured. \\
+8. If $a < 0$ then (\textit{mp\_cmp\_d}) \\
+\hspace{3mm}8.1 $q \leftarrow 1$ (\textit{mp\_set}) \\
+\hspace{3mm}8.2 $q \leftarrow q \cdot \beta^{m+1}$ (\textit{mp\_lshd}) \\
+\hspace{3mm}8.3 $a \leftarrow a + q$ \\
+\\
+Now subtract the modulus if the residue is too large (e.g. quotient too small). \\
+9. While $a \ge b$ do (\textit{mp\_cmp}) \\
+\hspace{3mm}9.1 $c \leftarrow a - b$ \\
+10. Clear $q$. \\
+11. Return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_reduce}
+\end{figure}
+
+\textbf{Algorithm mp\_reduce.}
+This algorithm will reduce the input $a$ modulo $b$ in place using the Barrett algorithm. It is loosely based on algorithm 14.42 of HAC
+\cite[pp. 602]{HAC} which is based on the paper from Paul Barrett \cite{BARRETT}. The algorithm has several restrictions and assumptions which must
+be adhered to for the algorithm to work.
+
+First the modulus $b$ is assumed to be positive and greater than one. If the modulus were less than or equal to one than subtracting
+a multiple of it would either accomplish nothing or actually enlarge the input. The input $a$ must be in the range $0 \le a < b^2$ in order
+for the quotient to have enough precision. If $a$ is the product of two numbers that were already reduced modulo $b$, this will not be a problem.
+Technically the algorithm will still work if $a \ge b^2$ but it will take much longer to finish. The value of $\mu$ is passed as an argument to this
+algorithm and is assumed to be calculated and stored before the algorithm is used.
+
+Recall that the multiplication for the quotient on step 3 must only produce digits at or above the $m-1$'th position. An algorithm called
+$s\_mp\_mul\_high\_digs$ which has not been presented is used to accomplish this task. The algorithm is based on $s\_mp\_mul\_digs$ except that
+instead of stopping at a given level of precision it starts at a given level of precision. This optimal algorithm can only be used if the number
+of digits in $b$ is very much smaller than $\beta$.
+
+While it is known that
+$a \ge b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ only the lower $m+1$ digits are being used to compute the residue, so an implied
+``borrow'' from the higher digits might leave a negative result. After the multiple of the modulus has been subtracted from $a$ the residue must be
+fixed up in case it is negative. The invariant $\beta^{m+1}$ must be added to the residue to make it positive again.
+
+The while loop at step 9 will subtract $b$ until the residue is less than $b$. If the algorithm is performed correctly this step is
+performed at most twice, and on average once. However, if $a \ge b^2$ than it will iterate substantially more times than it should.
+
+EXAM,bn_mp_reduce.c
+
+The first multiplication that determines the quotient can be performed by only producing the digits from $m - 1$ and up. This essentially halves
+the number of single precision multiplications required. However, the optimization is only safe if $\beta$ is much larger than the number of digits
+in the modulus. In the source code this is evaluated on lines @36,if@ to @44,}@ where algorithm s\_mp\_mul\_high\_digs is used when it is
+safe to do so.
+
+\subsection{The Barrett Setup Algorithm}
+In order to use algorithm mp\_reduce the value of $\mu$ must be calculated in advance. Ideally this value should be computed once and stored for
+future use so that the Barrett algorithm can be used without delay.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_reduce\_setup}. \\
+\textbf{Input}. mp\_int $a$ ($a > 1$) \\
+\textbf{Output}. $\mu \leftarrow \lfloor \beta^{2m}/a \rfloor$ \\
+\hline \\
+1. $\mu \leftarrow 2^{2 \cdot lg(\beta) \cdot m}$ (\textit{mp\_2expt}) \\
+2. $\mu \leftarrow \lfloor \mu / b \rfloor$ (\textit{mp\_div}) \\
+3. Return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_reduce\_setup}
+\end{figure}
+
+\textbf{Algorithm mp\_reduce\_setup.}
+This algorithm computes the reciprocal $\mu$ required for Barrett reduction. First $\beta^{2m}$ is calculated as $2^{2 \cdot lg(\beta) \cdot m}$ which
+is equivalent and much faster. The final value is computed by taking the integer quotient of $\lfloor \mu / b \rfloor$.
+
+EXAM,bn_mp_reduce_setup.c
+
+This simple routine calculates the reciprocal $\mu$ required by Barrett reduction. Note the extended usage of algorithm mp\_div where the variable
+which would received the remainder is passed as NULL. As will be discussed in~\ref{sec:division} the division routine allows both the quotient and the
+remainder to be passed as NULL meaning to ignore the value.
+
+\section{The Montgomery Reduction}
+Montgomery reduction\footnote{Thanks to Niels Ferguson for his insightful explanation of the algorithm.} \cite{MONT} is by far the most interesting
+form of reduction in common use. It computes a modular residue which is not actually equal to the residue of the input yet instead equal to a
+residue times a constant. However, as perplexing as this may sound the algorithm is relatively simple and very efficient.
+
+Throughout this entire section the variable $n$ will represent the modulus used to form the residue. As will be discussed shortly the value of
+$n$ must be odd. The variable $x$ will represent the quantity of which the residue is sought. Similar to the Barrett algorithm the input
+is restricted to $0 \le x < n^2$. To begin the description some simple number theory facts must be established.
+
+\textbf{Fact 1.} Adding $n$ to $x$ does not change the residue since in effect it adds one to the quotient $\lfloor x / n \rfloor$. Another way
+to explain this is that $n$ is (\textit{or multiples of $n$ are}) congruent to zero modulo $n$. Adding zero will not change the value of the residue.
+
+\textbf{Fact 2.} If $x$ is even then performing a division by two in $\Z$ is congruent to $x \cdot 2^{-1} \mbox{ (mod }n\mbox{)}$. Actually
+this is an application of the fact that if $x$ is evenly divisible by any $k \in \Z$ then division in $\Z$ will be congruent to
+multiplication by $k^{-1}$ modulo $n$.
+
+From these two simple facts the following simple algorithm can be derived.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Montgomery Reduction}. \\
+\textbf{Input}. Integer $x$, $n$ and $k$ \\
+\textbf{Output}. $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\
+\hline \\
+1. for $t$ from $1$ to $k$ do \\
+\hspace{3mm}1.1 If $x$ is odd then \\
+\hspace{6mm}1.1.1 $x \leftarrow x + n$ \\
+\hspace{3mm}1.2 $x \leftarrow x/2$ \\
+2. Return $x$. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm Montgomery Reduction}
+\end{figure}
+
+The algorithm reduces the input one bit at a time using the two congruencies stated previously. Inside the loop $n$, which is odd, is
+added to $x$ if $x$ is odd. This forces $x$ to be even which allows the division by two in $\Z$ to be congruent to a modular division by two. Since
+$x$ is assumed to be initially much larger than $n$ the addition of $n$ will contribute an insignificant magnitude to $x$. Let $r$ represent the
+final result of the Montgomery algorithm. If $k > lg(n)$ and $0 \le x < n^2$ then the final result is limited to
+$0 \le r < \lfloor x/2^k \rfloor + n$. As a result at most a single subtraction is required to get the residue desired.
+
+\begin{figure}[here]
+\begin{small}
+\begin{center}
+\begin{tabular}{|c|l|}
+\hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} \\
+\hline $1$ & $x + n = 5812$, $x/2 = 2906$ \\
+\hline $2$ & $x/2 = 1453$ \\
+\hline $3$ & $x + n = 1710$, $x/2 = 855$ \\
+\hline $4$ & $x + n = 1112$, $x/2 = 556$ \\
+\hline $5$ & $x/2 = 278$ \\
+\hline $6$ & $x/2 = 139$ \\
+\hline $7$ & $x + n = 396$, $x/2 = 198$ \\
+\hline $8$ & $x/2 = 99$ \\
+\hline $9$ & $x + n = 356$, $x/2 = 178$ \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Example of Montgomery Reduction (I)}
+\label{fig:MONT1}
+\end{figure}
+
+Consider the example in figure~\ref{fig:MONT1} which reduces $x = 5555$ modulo $n = 257$ when $k = 9$ (note $\beta^k = 512$ which is larger than $n$). The result of
+the algorithm $r = 178$ is congruent to the value of $2^{-9} \cdot 5555 \mbox{ (mod }257\mbox{)}$. When $r$ is multiplied by $2^9$ modulo $257$ the correct residue
+$r \equiv 158$ is produced.
+
+Let $k = \lfloor lg(n) \rfloor + 1$ represent the number of bits in $n$. The current algorithm requires $2k^2$ single precision shifts
+and $k^2$ single precision additions. At this rate the algorithm is most certainly slower than Barrett reduction and not terribly useful.
+Fortunately there exists an alternative representation of the algorithm.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Montgomery Reduction} (modified I). \\
+\textbf{Input}. Integer $x$, $n$ and $k$ ($2^k > n$) \\
+\textbf{Output}. $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\
+\hline \\
+1. for $t$ from $1$ to $k$ do \\
+\hspace{3mm}1.1 If the $t$'th bit of $x$ is one then \\
+\hspace{6mm}1.1.1 $x \leftarrow x + 2^tn$ \\
+2. Return $x/2^k$. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm Montgomery Reduction (modified I)}
+\end{figure}
+
+This algorithm is equivalent since $2^tn$ is a multiple of $n$ and the lower $k$ bits of $x$ are zero by step 2. The number of single
+precision shifts has now been reduced from $2k^2$ to $k^2 + k$ which is only a small improvement.
+
+\begin{figure}[here]
+\begin{small}
+\begin{center}
+\begin{tabular}{|c|l|r|}
+\hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} & \textbf{Result ($x$) in Binary} \\
+\hline -- & $5555$ & $1010110110011$ \\
+\hline $1$ & $x + 2^{0}n = 5812$ & $1011010110100$ \\
+\hline $2$ & $5812$ & $1011010110100$ \\
+\hline $3$ & $x + 2^{2}n = 6840$ & $1101010111000$ \\
+\hline $4$ & $x + 2^{3}n = 8896$ & $10001011000000$ \\
+\hline $5$ & $8896$ & $10001011000000$ \\
+\hline $6$ & $8896$ & $10001011000000$ \\
+\hline $7$ & $x + 2^{6}n = 25344$ & $110001100000000$ \\
+\hline $8$ & $25344$ & $110001100000000$ \\
+\hline $9$ & $x + 2^{7}n = 91136$ & $10110010000000000$ \\
+\hline -- & $x/2^k = 178$ & \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Example of Montgomery Reduction (II)}
+\label{fig:MONT2}
+\end{figure}
+
+Figure~\ref{fig:MONT2} demonstrates the modified algorithm reducing $x = 5555$ modulo $n = 257$ with $k = 9$.
+With this algorithm a single shift right at the end is the only right shift required to reduce the input instead of $k$ right shifts inside the
+loop. Note that for the iterations $t = 2, 5, 6$ and $8$ where the result $x$ is not changed. In those iterations the $t$'th bit of $x$ is
+zero and the appropriate multiple of $n$ does not need to be added to force the $t$'th bit of the result to zero.
+
+\subsection{Digit Based Montgomery Reduction}
+Instead of computing the reduction on a bit-by-bit basis it is actually much faster to compute it on digit-by-digit basis. Consider the
+previous algorithm re-written to compute the Montgomery reduction in this new fashion.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Montgomery Reduction} (modified II). \\
+\textbf{Input}. Integer $x$, $n$ and $k$ ($\beta^k > n$) \\
+\textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
+\hline \\
+1. for $t$ from $0$ to $k - 1$ do \\
+\hspace{3mm}1.1 $x \leftarrow x + \mu n \beta^t$ \\
+2. Return $x/\beta^k$. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm Montgomery Reduction (modified II)}
+\end{figure}
+
+The value $\mu n \beta^t$ is a multiple of the modulus $n$ meaning that it will not change the residue. If the first digit of
+the value $\mu n \beta^t$ equals the negative (modulo $\beta$) of the $t$'th digit of $x$ then the addition will result in a zero digit. This
+problem breaks down to solving the following congruency.
+
+\begin{center}
+\begin{tabular}{rcl}
+$x_t + \mu n_0$ & $\equiv$ & $0 \mbox{ (mod }\beta\mbox{)}$ \\
+$\mu n_0$ & $\equiv$ & $-x_t \mbox{ (mod }\beta\mbox{)}$ \\
+$\mu$ & $\equiv$ & $-x_t/n_0 \mbox{ (mod }\beta\mbox{)}$ \\
+\end{tabular}
+\end{center}
+
+In each iteration of the loop on step 1 a new value of $\mu$ must be calculated. The value of $-1/n_0 \mbox{ (mod }\beta\mbox{)}$ is used
+extensively in this algorithm and should be precomputed. Let $\rho$ represent the negative of the modular inverse of $n_0$ modulo $\beta$.
+
+For example, let $\beta = 10$ represent the radix. Let $n = 17$ represent the modulus which implies $k = 2$ and $\rho \equiv 7$. Let $x = 33$
+represent the value to reduce.
+
+\newpage\begin{figure}
+\begin{center}
+\begin{tabular}{|c|c|c|}
+\hline \textbf{Step ($t$)} & \textbf{Value of $x$} & \textbf{Value of $\mu$} \\
+\hline -- & $33$ & --\\
+\hline $0$ & $33 + \mu n = 50$ & $1$ \\
+\hline $1$ & $50 + \mu n \beta = 900$ & $5$ \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Example of Montgomery Reduction}
+\end{figure}
+
+The final result $900$ is then divided by $\beta^k$ to produce the final result $9$. The first observation is that $9 \nequiv x \mbox{ (mod }n\mbox{)}$
+which implies the result is not the modular residue of $x$ modulo $n$. However, recall that the residue is actually multiplied by $\beta^{-k}$ in
+the algorithm. To get the true residue the value must be multiplied by $\beta^k$. In this case $\beta^k \equiv 15 \mbox{ (mod }n\mbox{)}$ and
+the correct residue is $9 \cdot 15 \equiv 16 \mbox{ (mod }n\mbox{)}$.
+
+\subsection{Baseline Montgomery Reduction}
+The baseline Montgomery reduction algorithm will produce the residue for any size input. It is designed to be a catch-all algororithm for
+Montgomery reductions.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_montgomery\_reduce}. \\
+\textbf{Input}. mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\
+\hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\
+\textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
+\hline \\
+1. $digs \leftarrow 2n.used + 1$ \\
+2. If $digs < MP\_ARRAY$ and $m.used < \delta$ then \\
+\hspace{3mm}2.1 Use algorithm fast\_mp\_montgomery\_reduce instead. \\
+\\
+Setup $x$ for the reduction. \\
+3. If $x.alloc < digs$ then grow $x$ to $digs$ digits. \\
+4. $x.used \leftarrow digs$ \\
+\\
+Eliminate the lower $k$ digits. \\
+5. For $ix$ from $0$ to $k - 1$ do \\
+\hspace{3mm}5.1 $\mu \leftarrow x_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{3mm}5.2 $u \leftarrow 0$ \\
+\hspace{3mm}5.3 For $iy$ from $0$ to $k - 1$ do \\
+\hspace{6mm}5.3.1 $\hat r \leftarrow \mu n_{iy} + x_{ix + iy} + u$ \\
+\hspace{6mm}5.3.2 $x_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{6mm}5.3.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
+\hspace{3mm}5.4 While $u > 0$ do \\
+\hspace{6mm}5.4.1 $iy \leftarrow iy + 1$ \\
+\hspace{6mm}5.4.2 $x_{ix + iy} \leftarrow x_{ix + iy} + u$ \\
+\hspace{6mm}5.4.3 $u \leftarrow \lfloor x_{ix+iy} / \beta \rfloor$ \\
+\hspace{6mm}5.4.4 $x_{ix + iy} \leftarrow x_{ix+iy} \mbox{ (mod }\beta\mbox{)}$ \\
+\\
+Divide by $\beta^k$ and fix up as required. \\
+6. $x \leftarrow \lfloor x / \beta^k \rfloor$ \\
+7. If $x \ge n$ then \\
+\hspace{3mm}7.1 $x \leftarrow x - n$ \\
+8. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_montgomery\_reduce}
+\end{figure}
+
+\textbf{Algorithm mp\_montgomery\_reduce.}
+This algorithm reduces the input $x$ modulo $n$ in place using the Montgomery reduction algorithm. The algorithm is loosely based
+on algorithm 14.32 of \cite[pp.601]{HAC} except it merges the multiplication of $\mu n \beta^t$ with the addition in the inner loop. The
+restrictions on this algorithm are fairly easy to adapt to. First $0 \le x < n^2$ bounds the input to numbers in the same range as
+for the Barrett algorithm. Additionally if $n > 1$ and $n$ is odd there will exist a modular inverse $\rho$. $\rho$ must be calculated in
+advance of this algorithm. Finally the variable $k$ is fixed and a pseudonym for $n.used$.
+
+Step 2 decides whether a faster Montgomery algorithm can be used. It is based on the Comba technique meaning that there are limits on
+the size of the input. This algorithm is discussed in ~COMBARED~.
+
+Step 5 is the main reduction loop of the algorithm. The value of $\mu$ is calculated once per iteration in the outer loop. The inner loop
+calculates $x + \mu n \beta^{ix}$ by multiplying $\mu n$ and adding the result to $x$ shifted by $ix$ digits. Both the addition and
+multiplication are performed in the same loop to save time and memory. Step 5.4 will handle any additional carries that escape the inner loop.
+
+Using a quick inspection this algorithm requires $n$ single precision multiplications for the outer loop and $n^2$ single precision multiplications
+in the inner loop. In total $n^2 + n$ single precision multiplications which compares favourably to Barrett at $n^2 + 2n - 1$ single precision
+multiplications.
+
+EXAM,bn_mp_montgomery_reduce.c
+
+This is the baseline implementation of the Montgomery reduction algorithm. Lines @30,digs@ to @35,}@ determine if the Comba based
+routine can be used instead. Line @47,mu@ computes the value of $\mu$ for that particular iteration of the outer loop.
+
+The multiplication $\mu n \beta^{ix}$ is performed in one step in the inner loop. The alias $tmpx$ refers to the $ix$'th digit of $x$ and
+the alias $tmpn$ refers to the modulus $n$.
+
+\subsection{Faster ``Comba'' Montgomery Reduction}
+MARK,COMBARED
+
+The Montgomery reduction requires fewer single precision multiplications than a Barrett reduction, however it is much slower due to the serial
+nature of the inner loop. The Barrett reduction algorithm requires two slightly modified multipliers which can be implemented with the Comba
+technique. The Montgomery reduction algorithm cannot directly use the Comba technique to any significant advantage since the inner loop calculates
+a $k \times 1$ product $k$ times.
+
+The biggest obstacle is that at the $ix$'th iteration of the outer loop the value of $x_{ix}$ is required to calculate $\mu$. This means the
+carries from $0$ to $ix - 1$ must have been propagated upwards to form a valid $ix$'th digit. The solution as it turns out is very simple.
+Perform a Comba like multiplier and inside the outer loop just after the inner loop fix up the $ix + 1$'th digit by forwarding the carry.
+
+With this change in place the Montgomery reduction algorithm can be performed with a Comba style multiplication loop which substantially increases
+the speed of the algorithm.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{fast\_mp\_montgomery\_reduce}. \\
+\textbf{Input}. mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\
+\hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\
+\textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
+\hline \\
+Place an array of \textbf{MP\_WARRAY} mp\_word variables called $\hat W$ on the stack. \\
+1. if $x.alloc < n.used + 1$ then grow $x$ to $n.used + 1$ digits. \\
+Copy the digits of $x$ into the array $\hat W$ \\
+2. For $ix$ from $0$ to $x.used - 1$ do \\
+\hspace{3mm}2.1 $\hat W_{ix} \leftarrow x_{ix}$ \\
+3. For $ix$ from $x.used$ to $2n.used - 1$ do \\
+\hspace{3mm}3.1 $\hat W_{ix} \leftarrow 0$ \\
+Elimiate the lower $k$ digits. \\
+4. for $ix$ from $0$ to $n.used - 1$ do \\
+\hspace{3mm}4.1 $\mu \leftarrow \hat W_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{3mm}4.2 For $iy$ from $0$ to $n.used - 1$ do \\
+\hspace{6mm}4.2.1 $\hat W_{iy + ix} \leftarrow \hat W_{iy + ix} + \mu \cdot n_{iy}$ \\
+\hspace{3mm}4.3 $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\
+Propagate carries upwards. \\
+5. for $ix$ from $n.used$ to $2n.used + 1$ do \\
+\hspace{3mm}5.1 $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\
+Shift right and reduce modulo $\beta$ simultaneously. \\
+6. for $ix$ from $0$ to $n.used + 1$ do \\
+\hspace{3mm}6.1 $x_{ix} \leftarrow \hat W_{ix + n.used} \mbox{ (mod }\beta\mbox{)}$ \\
+Zero excess digits and fixup $x$. \\
+7. if $x.used > n.used + 1$ then do \\
+\hspace{3mm}7.1 for $ix$ from $n.used + 1$ to $x.used - 1$ do \\
+\hspace{6mm}7.1.1 $x_{ix} \leftarrow 0$ \\
+8. $x.used \leftarrow n.used + 1$ \\
+9. Clamp excessive digits of $x$. \\
+10. If $x \ge n$ then \\
+\hspace{3mm}10.1 $x \leftarrow x - n$ \\
+11. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm fast\_mp\_montgomery\_reduce}
+\end{figure}
+
+\textbf{Algorithm fast\_mp\_montgomery\_reduce.}
+This algorithm will compute the Montgomery reduction of $x$ modulo $n$ using the Comba technique. It is on most computer platforms significantly
+faster than algorithm mp\_montgomery\_reduce and algorithm mp\_reduce (\textit{Barrett reduction}). The algorithm has the same restrictions
+on the input as the baseline reduction algorithm. An additional two restrictions are imposed on this algorithm. The number of digits $k$ in the
+the modulus $n$ must not violate $MP\_WARRAY > 2k +1$ and $n < \delta$. When $\beta = 2^{28}$ this algorithm can be used to reduce modulo
+a modulus of at most $3,556$ bits in length.
+
+As in the other Comba reduction algorithms there is a $\hat W$ array which stores the columns of the product. It is initially filled with the
+contents of $x$ with the excess digits zeroed. The reduction loop is very similar the to the baseline loop at heart. The multiplication on step
+4.1 can be single precision only since $ab \mbox{ (mod }\beta\mbox{)} \equiv (a \mbox{ mod }\beta)(b \mbox{ mod }\beta)$. Some multipliers such
+as those on the ARM processors take a variable length time to complete depending on the number of bytes of result it must produce. By performing
+a single precision multiplication instead half the amount of time is spent.
+
+Also note that digit $\hat W_{ix}$ must have the carry from the $ix - 1$'th digit propagated upwards in order for this to work. That is what step
+4.3 will do. In effect over the $n.used$ iterations of the outer loop the $n.used$'th lower columns all have the their carries propagated forwards. Note
+how the upper bits of those same words are not reduced modulo $\beta$. This is because those values will be discarded shortly and there is no
+point.
+
+Step 5 will propagate the remainder of the carries upwards. On step 6 the columns are reduced modulo $\beta$ and shifted simultaneously as they are
+stored in the destination $x$.
+
+EXAM,bn_fast_mp_montgomery_reduce.c
+
+The $\hat W$ array is first filled with digits of $x$ on line @49,for@ then the rest of the digits are zeroed on line @54,for@. Both loops share
+the same alias variables to make the code easier to read.
+
+The value of $\mu$ is calculated in an interesting fashion. First the value $\hat W_{ix}$ is reduced modulo $\beta$ and cast to a mp\_digit. This
+forces the compiler to use a single precision multiplication and prevents any concerns about loss of precision. Line @101,>>@ fixes the carry
+for the next iteration of the loop by propagating the carry from $\hat W_{ix}$ to $\hat W_{ix+1}$.
+
+The for loop on line @113,for@ propagates the rest of the carries upwards through the columns. The for loop on line @126,for@ reduces the columns
+modulo $\beta$ and shifts them $k$ places at the same time. The alias $\_ \hat W$ actually refers to the array $\hat W$ starting at the $n.used$'th
+digit, that is $\_ \hat W_{t} = \hat W_{n.used + t}$.
+
+\subsection{Montgomery Setup}
+To calculate the variable $\rho$ a relatively simple algorithm will be required.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_montgomery\_setup}. \\
+\textbf{Input}. mp\_int $n$ ($n > 1$ and $(n, 2) = 1$) \\
+\textbf{Output}. $\rho \equiv -1/n_0 \mbox{ (mod }\beta\mbox{)}$ \\
+\hline \\
+1. $b \leftarrow n_0$ \\
+2. If $b$ is even return(\textit{MP\_VAL}) \\
+3. $x \leftarrow (((b + 2) \mbox{ AND } 4) << 1) + b$ \\
+4. for $k$ from 0 to $\lceil lg(lg(\beta)) \rceil - 2$ do \\
+\hspace{3mm}4.1 $x \leftarrow x \cdot (2 - bx)$ \\
+5. $\rho \leftarrow \beta - x \mbox{ (mod }\beta\mbox{)}$ \\
+6. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_montgomery\_setup}
+\end{figure}
+
+\textbf{Algorithm mp\_montgomery\_setup.}
+This algorithm will calculate the value of $\rho$ required within the Montgomery reduction algorithms. It uses a very interesting trick
+to calculate $1/n_0$ when $\beta$ is a power of two.
+
+EXAM,bn_mp_montgomery_setup.c
+
+This source code computes the value of $\rho$ required to perform Montgomery reduction. It has been modified to avoid performing excess
+multiplications when $\beta$ is not the default 28-bits.
+
+\section{The Diminished Radix Algorithm}
+The Diminished Radix method of modular reduction \cite{DRMET} is a fairly clever technique which can be more efficient than either the Barrett
+or Montgomery methods for certain forms of moduli. The technique is based on the following simple congruence.
+
+\begin{equation}
+(x \mbox{ mod } n) + k \lfloor x / n \rfloor \equiv x \mbox{ (mod }(n - k)\mbox{)}
+\end{equation}
+
+This observation was used in the MMB \cite{MMB} block cipher to create a diffusion primitive. It used the fact that if $n = 2^{31}$ and $k=1$ that
+then a x86 multiplier could produce the 62-bit product and use the ``shrd'' instruction to perform a double-precision right shift. The proof
+of the above equation is very simple. First write $x$ in the product form.
+
+\begin{equation}
+x = qn + r
+\end{equation}
+
+Now reduce both sides modulo $(n - k)$.
+
+\begin{equation}
+x \equiv qk + r \mbox{ (mod }(n-k)\mbox{)}
+\end{equation}
+
+The variable $n$ reduces modulo $n - k$ to $k$. By putting $q = \lfloor x/n \rfloor$ and $r = x \mbox{ mod } n$
+into the equation the original congruence is reproduced, thus concluding the proof. The following algorithm is based on this observation.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Diminished Radix Reduction}. \\
+\textbf{Input}. Integer $x$, $n$, $k$ \\
+\textbf{Output}. $x \mbox{ mod } (n - k)$ \\
+\hline \\
+1. $q \leftarrow \lfloor x / n \rfloor$ \\
+2. $q \leftarrow k \cdot q$ \\
+3. $x \leftarrow x \mbox{ (mod }n\mbox{)}$ \\
+4. $x \leftarrow x + q$ \\
+5. If $x \ge (n - k)$ then \\
+\hspace{3mm}5.1 $x \leftarrow x - (n - k)$ \\
+\hspace{3mm}5.2 Goto step 1. \\
+6. Return $x$ \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm Diminished Radix Reduction}
+\label{fig:DR}
+\end{figure}
+
+This algorithm will reduce $x$ modulo $n - k$ and return the residue. If $0 \le x < (n - k)^2$ then the algorithm will loop almost always
+once or twice and occasionally three times. For simplicity sake the value of $x$ is bounded by the following simple polynomial.
+
+\begin{equation}
+0 \le x < n^2 + k^2 - 2nk
+\end{equation}
+
+The true bound is $0 \le x < (n - k - 1)^2$ but this has quite a few more terms. The value of $q$ after step 1 is bounded by the following.
+
+\begin{equation}
+q < n - 2k - k^2/n
+\end{equation}
+
+Since $k^2$ is going to be considerably smaller than $n$ that term will always be zero. The value of $x$ after step 3 is bounded trivially as
+$0 \le x < n$. By step four the sum $x + q$ is bounded by
+
+\begin{equation}
+0 \le q + x < (k + 1)n - 2k^2 - 1
+\end{equation}
+
+With a second pass $q$ will be loosely bounded by $0 \le q < k^2$ after step 2 while $x$ will still be loosely bounded by $0 \le x < n$ after step 3. After the second pass it is highly unlike that the
+sum in step 4 will exceed $n - k$. In practice fewer than three passes of the algorithm are required to reduce virtually every input in the
+range $0 \le x < (n - k - 1)^2$.
+
+\begin{figure}
+\begin{small}
+\begin{center}
+\begin{tabular}{|l|}
+\hline
+$x = 123456789, n = 256, k = 3$ \\
+\hline $q \leftarrow \lfloor x/n \rfloor = 482253$ \\
+$q \leftarrow q*k = 1446759$ \\
+$x \leftarrow x \mbox{ mod } n = 21$ \\
+$x \leftarrow x + q = 1446780$ \\
+$x \leftarrow x - (n - k) = 1446527$ \\
+\hline
+$q \leftarrow \lfloor x/n \rfloor = 5650$ \\
+$q \leftarrow q*k = 16950$ \\
+$x \leftarrow x \mbox{ mod } n = 127$ \\
+$x \leftarrow x + q = 17077$ \\
+$x \leftarrow x - (n - k) = 16824$ \\
+\hline
+$q \leftarrow \lfloor x/n \rfloor = 65$ \\
+$q \leftarrow q*k = 195$ \\
+$x \leftarrow x \mbox{ mod } n = 184$ \\
+$x \leftarrow x + q = 379$ \\
+$x \leftarrow x - (n - k) = 126$ \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Example Diminished Radix Reduction}
+\label{fig:EXDR}
+\end{figure}
+
+Figure~\ref{fig:EXDR} demonstrates the reduction of $x = 123456789$ modulo $n - k = 253$ when $n = 256$ and $k = 3$. Note that even while $x$
+is considerably larger than $(n - k - 1)^2 = 63504$ the algorithm still converges on the modular residue exceedingly fast. In this case only
+three passes were required to find the residue $x \equiv 126$.
+
+
+\subsection{Choice of Moduli}
+On the surface this algorithm looks like a very expensive algorithm. It requires a couple of subtractions followed by multiplication and other
+modular reductions. The usefulness of this algorithm becomes exceedingly clear when an appropriate modulus is chosen.
+
+Division in general is a very expensive operation to perform. The one exception is when the division is by a power of the radix of representation used.
+Division by ten for example is simple for pencil and paper mathematics since it amounts to shifting the decimal place to the right. Similarly division
+by two (\textit{or powers of two}) is very simple for binary computers to perform. It would therefore seem logical to choose $n$ of the form $2^p$
+which would imply that $\lfloor x / n \rfloor$ is a simple shift of $x$ right $p$ bits.
+
+However, there is one operation related to division of power of twos that is even faster than this. If $n = \beta^p$ then the division may be
+performed by moving whole digits to the right $p$ places. In practice division by $\beta^p$ is much faster than division by $2^p$ for any $p$.
+Also with the choice of $n = \beta^p$ reducing $x$ modulo $n$ merely requires zeroing the digits above the $p-1$'th digit of $x$.
+
+Throughout the next section the term ``restricted modulus'' will refer to a modulus of the form $\beta^p - k$ whereas the term ``unrestricted
+modulus'' will refer to a modulus of the form $2^p - k$. The word ``restricted'' in this case refers to the fact that it is based on the
+$2^p$ logic except $p$ must be a multiple of $lg(\beta)$.
+
+\subsection{Choice of $k$}
+Now that division and reduction (\textit{step 1 and 3 of figure~\ref{fig:DR}}) have been optimized to simple digit operations the multiplication by $k$
+in step 2 is the most expensive operation. Fortunately the choice of $k$ is not terribly limited. For all intents and purposes it might
+as well be a single digit. The smaller the value of $k$ is the faster the algorithm will be.
+
+\subsection{Restricted Diminished Radix Reduction}
+The restricted Diminished Radix algorithm can quickly reduce an input modulo a modulus of the form $n = \beta^p - k$. This algorithm can reduce
+an input $x$ within the range $0 \le x < n^2$ using only a couple passes of the algorithm demonstrated in figure~\ref{fig:DR}. The implementation
+of this algorithm has been optimized to avoid additional overhead associated with a division by $\beta^p$, the multiplication by $k$ or the addition
+of $x$ and $q$. The resulting algorithm is very efficient and can lead to substantial improvements over Barrett and Montgomery reduction when modular
+exponentiations are performed.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_dr\_reduce}. \\
+\textbf{Input}. mp\_int $x$, $n$ and a mp\_digit $k = \beta - n_0$ \\
+\hspace{11.5mm}($0 \le x < n^2$, $n > 1$, $0 < k < \beta$) \\
+\textbf{Output}. $x \mbox{ mod } n$ \\
+\hline \\
+1. $m \leftarrow n.used$ \\
+2. If $x.alloc < 2m$ then grow $x$ to $2m$ digits. \\
+3. $\mu \leftarrow 0$ \\
+4. for $i$ from $0$ to $m - 1$ do \\
+\hspace{3mm}4.1 $\hat r \leftarrow k \cdot x_{m+i} + x_{i} + \mu$ \\
+\hspace{3mm}4.2 $x_{i} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{3mm}4.3 $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\
+5. $x_{m} \leftarrow \mu$ \\
+6. for $i$ from $m + 1$ to $x.used - 1$ do \\
+\hspace{3mm}6.1 $x_{i} \leftarrow 0$ \\
+7. Clamp excess digits of $x$. \\
+8. If $x \ge n$ then \\
+\hspace{3mm}8.1 $x \leftarrow x - n$ \\
+\hspace{3mm}8.2 Goto step 3. \\
+9. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_dr\_reduce}
+\end{figure}
+
+\textbf{Algorithm mp\_dr\_reduce.}
+This algorithm will perform the Dimished Radix reduction of $x$ modulo $n$. It has similar restrictions to that of the Barrett reduction
+with the addition that $n$ must be of the form $n = \beta^m - k$ where $0 < k <\beta$.
+
+This algorithm essentially implements the pseudo-code in figure~\ref{fig:DR} except with a slight optimization. The division by $\beta^m$, multiplication by $k$
+and addition of $x \mbox{ mod }\beta^m$ are all performed simultaneously inside the loop on step 4. The division by $\beta^m$ is emulated by accessing
+the term at the $m+i$'th position which is subsequently multiplied by $k$ and added to the term at the $i$'th position. After the loop the $m$'th
+digit is set to the carry and the upper digits are zeroed. Steps 5 and 6 emulate the reduction modulo $\beta^m$ that should have happend to
+$x$ before the addition of the multiple of the upper half.
+
+At step 8 if $x$ is still larger than $n$ another pass of the algorithm is required. First $n$ is subtracted from $x$ and then the algorithm resumes
+at step 3.
+
+EXAM,bn_mp_dr_reduce.c
+
+The first step is to grow $x$ as required to $2m$ digits since the reduction is performed in place on $x$. The label on line @49,top:@ is where
+the algorithm will resume if further reduction passes are required. In theory it could be placed at the top of the function however, the size of
+the modulus and question of whether $x$ is large enough are invariant after the first pass meaning that it would be a waste of time.
+
+The aliases $tmpx1$ and $tmpx2$ refer to the digits of $x$ where the latter is offset by $m$ digits. By reading digits from $x$ offset by $m$ digits
+a division by $\beta^m$ can be simulated virtually for free. The loop on line @61,for@ performs the bulk of the work (\textit{corresponds to step 4 of algorithm 7.11})
+in this algorithm.
+
+By line @68,mu@ the pointer $tmpx1$ points to the $m$'th digit of $x$ which is where the final carry will be placed. Similarly by line @71,for@ the
+same pointer will point to the $m+1$'th digit where the zeroes will be placed.
+
+Since the algorithm is only valid if both $x$ and $n$ are greater than zero an unsigned comparison suffices to determine if another pass is required.
+With the same logic at line @82,sub@ the value of $x$ is known to be greater than or equal to $n$ meaning that an unsigned subtraction can be used
+as well. Since the destination of the subtraction is the larger of the inputs the call to algorithm s\_mp\_sub cannot fail and the return code
+does not need to be checked.
+
+\subsubsection{Setup}
+To setup the restricted Diminished Radix algorithm the value $k = \beta - n_0$ is required. This algorithm is not really complicated but provided for
+completeness.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_dr\_setup}. \\
+\textbf{Input}. mp\_int $n$ \\
+\textbf{Output}. $k = \beta - n_0$ \\
+\hline \\
+1. $k \leftarrow \beta - n_0$ \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_dr\_setup}
+\end{figure}
+
+EXAM,bn_mp_dr_setup.c
+
+\subsubsection{Modulus Detection}
+Another algorithm which will be useful is the ability to detect a restricted Diminished Radix modulus. An integer is said to be
+of restricted Diminished Radix form if all of the digits are equal to $\beta - 1$ except the trailing digit which may be any value.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_dr\_is\_modulus}. \\
+\textbf{Input}. mp\_int $n$ \\
+\textbf{Output}. $1$ if $n$ is in D.R form, $0$ otherwise \\
+\hline
+1. If $n.used < 2$ then return($0$). \\
+2. for $ix$ from $1$ to $n.used - 1$ do \\
+\hspace{3mm}2.1 If $n_{ix} \ne \beta - 1$ return($0$). \\
+3. Return($1$). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_dr\_is\_modulus}
+\end{figure}
+
+\textbf{Algorithm mp\_dr\_is\_modulus.}
+This algorithm determines if a value is in Diminished Radix form. Step 1 rejects obvious cases where fewer than two digits are
+in the mp\_int. Step 2 tests all but the first digit to see if they are equal to $\beta - 1$. If the algorithm manages to get to
+step 3 then $n$ must be of Diminished Radix form.
+
+EXAM,bn_mp_dr_is_modulus.c
+
+\subsection{Unrestricted Diminished Radix Reduction}
+The unrestricted Diminished Radix algorithm allows modular reductions to be performed when the modulus is of the form $2^p - k$. This algorithm
+is a straightforward adaptation of algorithm~\ref{fig:DR}.
+
+In general the restricted Diminished Radix reduction algorithm is much faster since it has considerably lower overhead. However, this new
+algorithm is much faster than either Montgomery or Barrett reduction when the moduli are of the appropriate form.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_reduce\_2k}. \\
+\textbf{Input}. mp\_int $a$ and $n$. mp\_digit $k$ \\
+\hspace{11.5mm}($a \ge 0$, $n > 1$, $0 < k < \beta$, $n + k$ is a power of two) \\
+\textbf{Output}. $a \mbox{ (mod }n\mbox{)}$ \\
+\hline
+1. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\
+2. While $a \ge n$ do \\
+\hspace{3mm}2.1 $q \leftarrow \lfloor a / 2^p \rfloor$ (\textit{mp\_div\_2d}) \\
+\hspace{3mm}2.2 $a \leftarrow a \mbox{ (mod }2^p\mbox{)}$ (\textit{mp\_mod\_2d}) \\
+\hspace{3mm}2.3 $q \leftarrow q \cdot k$ (\textit{mp\_mul\_d}) \\
+\hspace{3mm}2.4 $a \leftarrow a - q$ (\textit{s\_mp\_sub}) \\
+\hspace{3mm}2.5 If $a \ge n$ then do \\
+\hspace{6mm}2.5.1 $a \leftarrow a - n$ \\
+3. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_reduce\_2k}
+\end{figure}
+
+\textbf{Algorithm mp\_reduce\_2k.}
+This algorithm quickly reduces an input $a$ modulo an unrestricted Diminished Radix modulus $n$. Division by $2^p$ is emulated with a right
+shift which makes the algorithm fairly inexpensive to use.
+
+EXAM,bn_mp_reduce_2k.c
+
+The algorithm mp\_count\_bits calculates the number of bits in an mp\_int which is used to find the initial value of $p$. The call to mp\_div\_2d
+on line @31,mp_div_2d@ calculates both the quotient $q$ and the remainder $a$ required. By doing both in a single function call the code size
+is kept fairly small. The multiplication by $k$ is only performed if $k > 1$. This allows reductions modulo $2^p - 1$ to be performed without
+any multiplications.
+
+The unsigned s\_mp\_add, mp\_cmp\_mag and s\_mp\_sub are used in place of their full sign counterparts since the inputs are only valid if they are
+positive. By using the unsigned versions the overhead is kept to a minimum.
+
+\subsubsection{Unrestricted Setup}
+To setup this reduction algorithm the value of $k = 2^p - n$ is required.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_reduce\_2k\_setup}. \\
+\textbf{Input}. mp\_int $n$ \\
+\textbf{Output}. $k = 2^p - n$ \\
+\hline
+1. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\
+2. $x \leftarrow 2^p$ (\textit{mp\_2expt}) \\
+3. $x \leftarrow x - n$ (\textit{mp\_sub}) \\
+4. $k \leftarrow x_0$ \\
+5. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_reduce\_2k\_setup}
+\end{figure}
+
+\textbf{Algorithm mp\_reduce\_2k\_setup.}
+This algorithm computes the value of $k$ required for the algorithm mp\_reduce\_2k. By making a temporary variable $x$ equal to $2^p$ a subtraction
+is sufficient to solve for $k$. Alternatively if $n$ has more than one digit the value of $k$ is simply $\beta - n_0$.
+
+EXAM,bn_mp_reduce_2k_setup.c
+
+\subsubsection{Unrestricted Detection}
+An integer $n$ is a valid unrestricted Diminished Radix modulus if either of the following are true.
+
+\begin{enumerate}
+\item The number has only one digit.
+\item The number has more than one digit and every bit from the $\beta$'th to the most significant is one.
+\end{enumerate}
+
+If either condition is true than there is a power of two $2^p$ such that $0 < 2^p - n < \beta$. If the input is only
+one digit than it will always be of the correct form. Otherwise all of the bits above the first digit must be one. This arises from the fact
+that there will be value of $k$ that when added to the modulus causes a carry in the first digit which propagates all the way to the most
+significant bit. The resulting sum will be a power of two.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_reduce\_is\_2k}. \\
+\textbf{Input}. mp\_int $n$ \\
+\textbf{Output}. $1$ if of proper form, $0$ otherwise \\
+\hline
+1. If $n.used = 0$ then return($0$). \\
+2. If $n.used = 1$ then return($1$). \\
+3. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\
+4. for $x$ from $lg(\beta)$ to $p$ do \\
+\hspace{3mm}4.1 If the ($x \mbox{ mod }lg(\beta)$)'th bit of the $\lfloor x / lg(\beta) \rfloor$ of $n$ is zero then return($0$). \\
+5. Return($1$). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_reduce\_is\_2k}
+\end{figure}
+
+\textbf{Algorithm mp\_reduce\_is\_2k.}
+This algorithm quickly determines if a modulus is of the form required for algorithm mp\_reduce\_2k to function properly.
+
+EXAM,bn_mp_reduce_is_2k.c
+
+
+
+\section{Algorithm Comparison}
+So far three very different algorithms for modular reduction have been discussed. Each of the algorithms have their own strengths and weaknesses
+that makes having such a selection very useful. The following table sumarizes the three algorithms along with comparisons of work factors. Since
+all three algorithms have the restriction that $0 \le x < n^2$ and $n > 1$ those limitations are not included in the table.
+
+\begin{center}
+\begin{small}
+\begin{tabular}{|c|c|c|c|c|c|}
+\hline \textbf{Method} & \textbf{Work Required} & \textbf{Limitations} & \textbf{$m = 8$} & \textbf{$m = 32$} & \textbf{$m = 64$} \\
+\hline Barrett & $m^2 + 2m - 1$ & None & $79$ & $1087$ & $4223$ \\
+\hline Montgomery & $m^2 + m$ & $n$ must be odd & $72$ & $1056$ & $4160$ \\
+\hline D.R. & $2m$ & $n = \beta^m - k$ & $16$ & $64$ & $128$ \\
+\hline
+\end{tabular}
+\end{small}
+\end{center}
+
+In theory Montgomery and Barrett reductions would require roughly the same amount of time to complete. However, in practice since Montgomery
+reduction can be written as a single function with the Comba technique it is much faster. Barrett reduction suffers from the overhead of
+calling the half precision multipliers, addition and division by $\beta$ algorithms.
+
+For almost every cryptographic algorithm Montgomery reduction is the algorithm of choice. The one set of algorithms where Diminished Radix reduction truly
+shines are based on the discrete logarithm problem such as Diffie-Hellman \cite{DH} and ElGamal \cite{ELGAMAL}. In these algorithms
+primes of the form $\beta^m - k$ can be found and shared amongst users. These primes will allow the Diminished Radix algorithm to be used in
+modular exponentiation to greatly speed up the operation.
+
+
+
+\section*{Exercises}
+\begin{tabular}{cl}
+$\left [ 3 \right ]$ & Prove that the ``trick'' in algorithm mp\_montgomery\_setup actually \\
+ & calculates the correct value of $\rho$. \\
+ & \\
+$\left [ 2 \right ]$ & Devise an algorithm to reduce modulo $n + k$ for small $k$ quickly. \\
+ & \\
+$\left [ 4 \right ]$ & Prove that the pseudo-code algorithm ``Diminished Radix Reduction'' \\
+ & (\textit{figure~\ref{fig:DR}}) terminates. Also prove the probability that it will \\
+ & terminate within $1 \le k \le 10$ iterations. \\
+ & \\
+\end{tabular}
+
+
+\chapter{Exponentiation}
+Exponentiation is the operation of raising one variable to the power of another, for example, $a^b$. A variant of exponentiation, computed
+in a finite field or ring, is called modular exponentiation. This latter style of operation is typically used in public key
+cryptosystems such as RSA and Diffie-Hellman. The ability to quickly compute modular exponentiations is of great benefit to any
+such cryptosystem and many methods have been sought to speed it up.
+
+\section{Exponentiation Basics}
+A trivial algorithm would simply multiply $a$ against itself $b - 1$ times to compute the exponentiation desired. However, as $b$ grows in size
+the number of multiplications becomes prohibitive. Imagine what would happen if $b$ $\approx$ $2^{1024}$ as is the case when computing an RSA signature
+with a $1024$-bit key. Such a calculation could never be completed as it would take simply far too long.
+
+Fortunately there is a very simple algorithm based on the laws of exponents. Recall that $lg_a(a^b) = b$ and that $lg_a(a^ba^c) = b + c$ which
+are two trivial relationships between the base and the exponent. Let $b_i$ represent the $i$'th bit of $b$ starting from the least
+significant bit. If $b$ is a $k$-bit integer than the following equation is true.
+
+\begin{equation}
+a^b = \prod_{i=0}^{k-1} a^{2^i \cdot b_i}
+\end{equation}
+
+By taking the base $a$ logarithm of both sides of the equation the following equation is the result.
+
+\begin{equation}
+b = \sum_{i=0}^{k-1}2^i \cdot b_i
+\end{equation}
+
+The term $a^{2^i}$ can be found from the $i - 1$'th term by squaring the term since $\left ( a^{2^i} \right )^2$ is equal to
+$a^{2^{i+1}}$. This observation forms the basis of essentially all fast exponentiation algorithms. It requires $k$ squarings and on average
+$k \over 2$ multiplications to compute the result. This is indeed quite an improvement over simply multiplying by $a$ a total of $b-1$ times.
+
+While this current method is a considerable speed up there are further improvements to be made. For example, the $a^{2^i}$ term does not need to
+be computed in an auxilary variable. Consider the following equivalent algorithm.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Left to Right Exponentiation}. \\
+\textbf{Input}. Integer $a$, $b$ and $k$ \\
+\textbf{Output}. $c = a^b$ \\
+\hline \\
+1. $c \leftarrow 1$ \\
+2. for $i$ from $k - 1$ to $0$ do \\
+\hspace{3mm}2.1 $c \leftarrow c^2$ \\
+\hspace{3mm}2.2 $c \leftarrow c \cdot a^{b_i}$ \\
+3. Return $c$. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Left to Right Exponentiation}
+\label{fig:LTOR}
+\end{figure}
+
+This algorithm starts from the most significant bit and works towards the least significant bit. When the $i$'th bit of $b$ is set $a$ is
+multiplied against the current product. In each iteration the product is squared which doubles the exponent of the individual terms of the
+product.
+
+For example, let $b = 101100_2 \equiv 44_{10}$. The following chart demonstrates the actions of the algorithm.
+
+\newpage\begin{figure}
+\begin{center}
+\begin{tabular}{|c|c|}
+\hline \textbf{Value of $i$} & \textbf{Value of $c$} \\
+\hline - & $1$ \\
+\hline $5$ & $a$ \\
+\hline $4$ & $a^2$ \\
+\hline $3$ & $a^4 \cdot a$ \\
+\hline $2$ & $a^8 \cdot a^2 \cdot a$ \\
+\hline $1$ & $a^{16} \cdot a^4 \cdot a^2$ \\
+\hline $0$ & $a^{32} \cdot a^8 \cdot a^4$ \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Example of Left to Right Exponentiation}
+\end{figure}
+
+When the product $a^{32} \cdot a^8 \cdot a^4$ is simplified it is equal $a^{44}$ which is the desired exponentiation. This particular algorithm is
+called ``Left to Right'' because it reads the exponent in that order. All of the exponentiation algorithms that will be presented are of this nature.
+
+\subsection{Single Digit Exponentiation}
+The first algorithm in the series of exponentiation algorithms will be an unbounded algorithm where the exponent is a single digit. It is intended
+to be used when a small power of an input is required (\textit{e.g. $a^5$}). It is faster than simply multiplying $b - 1$ times for all values of
+$b$ that are greater than three.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_expt\_d}. \\
+\textbf{Input}. mp\_int $a$ and mp\_digit $b$ \\
+\textbf{Output}. $c = a^b$ \\
+\hline \\
+1. $g \leftarrow a$ (\textit{mp\_init\_copy}) \\
+2. $c \leftarrow 1$ (\textit{mp\_set}) \\
+3. for $x$ from 1 to $lg(\beta)$ do \\
+\hspace{3mm}3.1 $c \leftarrow c^2$ (\textit{mp\_sqr}) \\
+\hspace{3mm}3.2 If $b$ AND $2^{lg(\beta) - 1} \ne 0$ then \\
+\hspace{6mm}3.2.1 $c \leftarrow c \cdot g$ (\textit{mp\_mul}) \\
+\hspace{3mm}3.3 $b \leftarrow b << 1$ \\
+4. Clear $g$. \\
+5. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_expt\_d}
+\end{figure}
+
+\textbf{Algorithm mp\_expt\_d.}
+This algorithm computes the value of $a$ raised to the power of a single digit $b$. It uses the left to right exponentiation algorithm to
+quickly compute the exponentiation. It is loosely based on algorithm 14.79 of HAC \cite[pp. 615]{HAC} with the difference that the
+exponent is a fixed width.
+
+A copy of $a$ is made first to allow destination variable $c$ be the same as the source variable $a$. The result is set to the initial value of
+$1$ in the subsequent step.
+
+Inside the loop the exponent is read from the most significant bit first down to the least significant bit. First $c$ is invariably squared
+on step 3.1. In the following step if the most significant bit of $b$ is one the copy of $a$ is multiplied against $c$. The value
+of $b$ is shifted left one bit to make the next bit down from the most signficant bit the new most significant bit. In effect each
+iteration of the loop moves the bits of the exponent $b$ upwards to the most significant location.
+
+EXAM,bn_mp_expt_d.c
+
+Line @29,mp_set@ sets the initial value of the result to $1$. Next the loop on line @31,for@ steps through each bit of the exponent starting from
+the most significant down towards the least significant. The invariant squaring operation placed on line @333,mp_sqr@ is performed first. After
+the squaring the result $c$ is multiplied by the base $g$ if and only if the most significant bit of the exponent is set. The shift on line
+@47,<<@ moves all of the bits of the exponent upwards towards the most significant location.
+
+\section{$k$-ary Exponentiation}
+When calculating an exponentiation the most time consuming bottleneck is the multiplications which are in general a small factor
+slower than squaring. Recall from the previous algorithm that $b_{i}$ refers to the $i$'th bit of the exponent $b$. Suppose instead it referred to
+the $i$'th $k$-bit digit of the exponent of $b$. For $k = 1$ the definitions are synonymous and for $k > 1$ algorithm~\ref{fig:KARY}
+computes the same exponentiation. A group of $k$ bits from the exponent is called a \textit{window}. That is it is a small window on only a
+portion of the entire exponent. Consider the following modification to the basic left to right exponentiation algorithm.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{$k$-ary Exponentiation}. \\
+\textbf{Input}. Integer $a$, $b$, $k$ and $t$ \\
+\textbf{Output}. $c = a^b$ \\
+\hline \\
+1. $c \leftarrow 1$ \\
+2. for $i$ from $t - 1$ to $0$ do \\
+\hspace{3mm}2.1 $c \leftarrow c^{2^k} $ \\
+\hspace{3mm}2.2 Extract the $i$'th $k$-bit word from $b$ and store it in $g$. \\
+\hspace{3mm}2.3 $c \leftarrow c \cdot a^g$ \\
+3. Return $c$. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{$k$-ary Exponentiation}
+\label{fig:KARY}
+\end{figure}
+
+The squaring on step 2.1 can be calculated by squaring the value $c$ successively $k$ times. If the values of $a^g$ for $0 < g < 2^k$ have been
+precomputed this algorithm requires only $t$ multiplications and $tk$ squarings. The table can be generated with $2^{k - 1} - 1$ squarings and
+$2^{k - 1} + 1$ multiplications. This algorithm assumes that the number of bits in the exponent is evenly divisible by $k$.
+However, when it is not the remaining $0 < x \le k - 1$ bits can be handled with algorithm~\ref{fig:LTOR}.
+
+Suppose $k = 4$ and $t = 100$. This modified algorithm will require $109$ multiplications and $408$ squarings to compute the exponentiation. The
+original algorithm would on average have required $200$ multiplications and $400$ squrings to compute the same value. The total number of squarings
+has increased slightly but the number of multiplications has nearly halved.
+
+\subsection{Optimal Values of $k$}
+An optimal value of $k$ will minimize $2^{k} + \lceil n / k \rceil + n - 1$ for a fixed number of bits in the exponent $n$. The simplest
+approach is to brute force search amongst the values $k = 2, 3, \ldots, 8$ for the lowest result. Table~\ref{fig:OPTK} lists optimal values of $k$
+for various exponent sizes and compares the number of multiplication and squarings required against algorithm~\ref{fig:LTOR}.
+
+\begin{figure}[here]
+\begin{center}
+\begin{small}
+\begin{tabular}{|c|c|c|c|c|c|}
+\hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:LTOR}} \\
+\hline $16$ & $2$ & $27$ & $24$ \\
+\hline $32$ & $3$ & $49$ & $48$ \\
+\hline $64$ & $3$ & $92$ & $96$ \\
+\hline $128$ & $4$ & $175$ & $192$ \\
+\hline $256$ & $4$ & $335$ & $384$ \\
+\hline $512$ & $5$ & $645$ & $768$ \\
+\hline $1024$ & $6$ & $1257$ & $1536$ \\
+\hline $2048$ & $6$ & $2452$ & $3072$ \\
+\hline $4096$ & $7$ & $4808$ & $6144$ \\
+\hline
+\end{tabular}
+\end{small}
+\end{center}
+\caption{Optimal Values of $k$ for $k$-ary Exponentiation}
+\label{fig:OPTK}
+\end{figure}
+
+\subsection{Sliding-Window Exponentiation}
+A simple modification to the previous algorithm is only generate the upper half of the table in the range $2^{k-1} \le g < 2^k$. Essentially
+this is a table for all values of $g$ where the most significant bit of $g$ is a one. However, in order for this to be allowed in the
+algorithm values of $g$ in the range $0 \le g < 2^{k-1}$ must be avoided.
+
+Table~\ref{fig:OPTK2} lists optimal values of $k$ for various exponent sizes and compares the work required against algorithm~\ref{fig:KARY}.
+
+\begin{figure}[here]
+\begin{center}
+\begin{small}
+\begin{tabular}{|c|c|c|c|c|c|}
+\hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:KARY}} \\
+\hline $16$ & $3$ & $24$ & $27$ \\
+\hline $32$ & $3$ & $45$ & $49$ \\
+\hline $64$ & $4$ & $87$ & $92$ \\
+\hline $128$ & $4$ & $167$ & $175$ \\
+\hline $256$ & $5$ & $322$ & $335$ \\
+\hline $512$ & $6$ & $628$ & $645$ \\
+\hline $1024$ & $6$ & $1225$ & $1257$ \\
+\hline $2048$ & $7$ & $2403$ & $2452$ \\
+\hline $4096$ & $8$ & $4735$ & $4808$ \\
+\hline
+\end{tabular}
+\end{small}
+\end{center}
+\caption{Optimal Values of $k$ for Sliding Window Exponentiation}
+\label{fig:OPTK2}
+\end{figure}
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Sliding Window $k$-ary Exponentiation}. \\
+\textbf{Input}. Integer $a$, $b$, $k$ and $t$ \\
+\textbf{Output}. $c = a^b$ \\
+\hline \\
+1. $c \leftarrow 1$ \\
+2. for $i$ from $t - 1$ to $0$ do \\
+\hspace{3mm}2.1 If the $i$'th bit of $b$ is a zero then \\
+\hspace{6mm}2.1.1 $c \leftarrow c^2$ \\
+\hspace{3mm}2.2 else do \\
+\hspace{6mm}2.2.1 $c \leftarrow c^{2^k}$ \\
+\hspace{6mm}2.2.2 Extract the $k$ bits from $(b_{i}b_{i-1}\ldots b_{i-(k-1)})$ and store it in $g$. \\
+\hspace{6mm}2.2.3 $c \leftarrow c \cdot a^g$ \\
+\hspace{6mm}2.2.4 $i \leftarrow i - k$ \\
+3. Return $c$. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Sliding Window $k$-ary Exponentiation}
+\end{figure}
+
+Similar to the previous algorithm this algorithm must have a special handler when fewer than $k$ bits are left in the exponent. While this
+algorithm requires the same number of squarings it can potentially have fewer multiplications. The pre-computed table $a^g$ is also half
+the size as the previous table.
+
+Consider the exponent $b = 111101011001000_2 \equiv 31432_{10}$ with $k = 3$ using both algorithms. The first algorithm will divide the exponent up as
+the following five $3$-bit words $b \equiv \left ( 111, 101, 011, 001, 000 \right )_{2}$. The second algorithm will break the
+exponent as $b \equiv \left ( 111, 101, 0, 110, 0, 100, 0 \right )_{2}$. The single digit $0$ in the second representation are where
+a single squaring took place instead of a squaring and multiplication. In total the first method requires $10$ multiplications and $18$
+squarings. The second method requires $8$ multiplications and $18$ squarings.
+
+In general the sliding window method is never slower than the generic $k$-ary method and often it is slightly faster.
+
+\section{Modular Exponentiation}
+
+Modular exponentiation is essentially computing the power of a base within a finite field or ring. For example, computing
+$d \equiv a^b \mbox{ (mod }c\mbox{)}$ is a modular exponentiation. Instead of first computing $a^b$ and then reducing it
+modulo $c$ the intermediate result is reduced modulo $c$ after every squaring or multiplication operation.
+
+This guarantees that any intermediate result is bounded by $0 \le d \le c^2 - 2c + 1$ and can be reduced modulo $c$ quickly using
+one of the algorithms presented in ~REDUCTION~.
+
+Before the actual modular exponentiation algorithm can be written a wrapper algorithm must be written first. This algorithm
+will allow the exponent $b$ to be negative which is computed as $c \equiv \left (1 / a \right )^{\vert b \vert} \mbox{(mod }d\mbox{)}$. The
+value of $(1/a) \mbox{ mod }c$ is computed using the modular inverse (\textit{see \ref{sec;modinv}}). If no inverse exists the algorithm
+terminates with an error.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_exptmod}. \\
+\textbf{Input}. mp\_int $a$, $b$ and $c$ \\
+\textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
+\hline \\
+1. If $c.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\
+2. If $b.sign = MP\_NEG$ then \\
+\hspace{3mm}2.1 $g' \leftarrow g^{-1} \mbox{ (mod }c\mbox{)}$ \\
+\hspace{3mm}2.2 $x' \leftarrow \vert x \vert$ \\
+\hspace{3mm}2.3 Compute $d \equiv g'^{x'} \mbox{ (mod }c\mbox{)}$ via recursion. \\
+3. if $p$ is odd \textbf{OR} $p$ is a D.R. modulus then \\
+\hspace{3mm}3.1 Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm mp\_exptmod\_fast. \\
+4. else \\
+\hspace{3mm}4.1 Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm s\_mp\_exptmod. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_exptmod}
+\end{figure}
+
+\textbf{Algorithm mp\_exptmod.}
+The first algorithm which actually performs modular exponentiation is algorithm s\_mp\_exptmod. It is a sliding window $k$-ary algorithm
+which uses Barrett reduction to reduce the product modulo $p$. The second algorithm mp\_exptmod\_fast performs the same operation
+except it uses either Montgomery or Diminished Radix reduction. The two latter reduction algorithms are clumped in the same exponentiation
+algorithm since their arguments are essentially the same (\textit{two mp\_ints and one mp\_digit}).
+
+EXAM,bn_mp_exptmod.c
+
+In order to keep the algorithms in a known state the first step on line @29,if@ is to reject any negative modulus as input. If the exponent is
+negative the algorithm tries to perform a modular exponentiation with the modular inverse of the base $G$. The temporary variable $tmpG$ is assigned
+the modular inverse of $G$ and $tmpX$ is assigned the absolute value of $X$. The algorithm will recuse with these new values with a positive
+exponent.
+
+If the exponent is positive the algorithm resumes the exponentiation. Line @63,dr_@ determines if the modulus is of the restricted Diminished Radix
+form. If it is not line @65,reduce@ attempts to determine if it is of a unrestricted Diminished Radix form. The integer $dr$ will take on one
+of three values.
+
+\begin{enumerate}
+\item $dr = 0$ means that the modulus is not of either restricted or unrestricted Diminished Radix form.
+\item $dr = 1$ means that the modulus is of restricted Diminished Radix form.
+\item $dr = 2$ means that the modulus is of unrestricted Diminished Radix form.
+\end{enumerate}
+
+Line @69,if@ determines if the fast modular exponentiation algorithm can be used. It is allowed if $dr \ne 0$ or if the modulus is odd. Otherwise,
+the slower s\_mp\_exptmod algorithm is used which uses Barrett reduction.
+
+\subsection{Barrett Modular Exponentiation}
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{s\_mp\_exptmod}. \\
+\textbf{Input}. mp\_int $a$, $b$ and $c$ \\
+\textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
+\hline \\
+1. $k \leftarrow lg(x)$ \\
+2. $winsize \leftarrow \left \lbrace \begin{array}{ll}
+ 2 & \mbox{if }k \le 7 \\
+ 3 & \mbox{if }7 < k \le 36 \\
+ 4 & \mbox{if }36 < k \le 140 \\
+ 5 & \mbox{if }140 < k \le 450 \\
+ 6 & \mbox{if }450 < k \le 1303 \\
+ 7 & \mbox{if }1303 < k \le 3529 \\
+ 8 & \mbox{if }3529 < k \\
+ \end{array} \right .$ \\
+3. Initialize $2^{winsize}$ mp\_ints in an array named $M$ and one mp\_int named $\mu$ \\
+4. Calculate the $\mu$ required for Barrett Reduction (\textit{mp\_reduce\_setup}). \\
+5. $M_1 \leftarrow g \mbox{ (mod }p\mbox{)}$ \\
+\\
+Setup the table of small powers of $g$. First find $g^{2^{winsize}}$ and then all multiples of it. \\
+6. $k \leftarrow 2^{winsize - 1}$ \\
+7. $M_{k} \leftarrow M_1$ \\
+8. for $ix$ from 0 to $winsize - 2$ do \\
+\hspace{3mm}8.1 $M_k \leftarrow \left ( M_k \right )^2$ (\textit{mp\_sqr}) \\
+\hspace{3mm}8.2 $M_k \leftarrow M_k \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\
+9. for $ix$ from $2^{winsize - 1} + 1$ to $2^{winsize} - 1$ do \\
+\hspace{3mm}9.1 $M_{ix} \leftarrow M_{ix - 1} \cdot M_{1}$ (\textit{mp\_mul}) \\
+\hspace{3mm}9.2 $M_{ix} \leftarrow M_{ix} \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\
+10. $res \leftarrow 1$ \\
+\\
+Start Sliding Window. \\
+11. $mode \leftarrow 0, bitcnt \leftarrow 1, buf \leftarrow 0, digidx \leftarrow x.used - 1, bitcpy \leftarrow 0, bitbuf \leftarrow 0$ \\
+12. Loop \\
+\hspace{3mm}12.1 $bitcnt \leftarrow bitcnt - 1$ \\
+\hspace{3mm}12.2 If $bitcnt = 0$ then do \\
+\hspace{6mm}12.2.1 If $digidx = -1$ goto step 13. \\
+\hspace{6mm}12.2.2 $buf \leftarrow x_{digidx}$ \\
+\hspace{6mm}12.2.3 $digidx \leftarrow digidx - 1$ \\
+\hspace{6mm}12.2.4 $bitcnt \leftarrow lg(\beta)$ \\
+Continued on next page. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm s\_mp\_exptmod}
+\end{figure}
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{s\_mp\_exptmod} (\textit{continued}). \\
+\textbf{Input}. mp\_int $a$, $b$ and $c$ \\
+\textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
+\hline \\
+\hspace{3mm}12.3 $y \leftarrow (buf >> (lg(\beta) - 1))$ AND $1$ \\
+\hspace{3mm}12.4 $buf \leftarrow buf << 1$ \\
+\hspace{3mm}12.5 if $mode = 0$ and $y = 0$ then goto step 12. \\
+\hspace{3mm}12.6 if $mode = 1$ and $y = 0$ then do \\
+\hspace{6mm}12.6.1 $res \leftarrow res^2$ \\
+\hspace{6mm}12.6.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
+\hspace{6mm}12.6.3 Goto step 12. \\
+\hspace{3mm}12.7 $bitcpy \leftarrow bitcpy + 1$ \\
+\hspace{3mm}12.8 $bitbuf \leftarrow bitbuf + (y << (winsize - bitcpy))$ \\
+\hspace{3mm}12.9 $mode \leftarrow 2$ \\
+\hspace{3mm}12.10 If $bitcpy = winsize$ then do \\
+\hspace{6mm}Window is full so perform the squarings and single multiplication. \\
+\hspace{6mm}12.10.1 for $ix$ from $0$ to $winsize -1$ do \\
+\hspace{9mm}12.10.1.1 $res \leftarrow res^2$ \\
+\hspace{9mm}12.10.1.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
+\hspace{6mm}12.10.2 $res \leftarrow res \cdot M_{bitbuf}$ \\
+\hspace{6mm}12.10.3 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
+\hspace{6mm}Reset the window. \\
+\hspace{6mm}12.10.4 $bitcpy \leftarrow 0, bitbuf \leftarrow 0, mode \leftarrow 1$ \\
+\\
+No more windows left. Check for residual bits of exponent. \\
+13. If $mode = 2$ and $bitcpy > 0$ then do \\
+\hspace{3mm}13.1 for $ix$ form $0$ to $bitcpy - 1$ do \\
+\hspace{6mm}13.1.1 $res \leftarrow res^2$ \\
+\hspace{6mm}13.1.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
+\hspace{6mm}13.1.3 $bitbuf \leftarrow bitbuf << 1$ \\
+\hspace{6mm}13.1.4 If $bitbuf$ AND $2^{winsize} \ne 0$ then do \\
+\hspace{9mm}13.1.4.1 $res \leftarrow res \cdot M_{1}$ \\
+\hspace{9mm}13.1.4.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
+14. $y \leftarrow res$ \\
+15. Clear $res$, $mu$ and the $M$ array. \\
+16. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm s\_mp\_exptmod (continued)}
+\end{figure}
+
+\textbf{Algorithm s\_mp\_exptmod.}
+This algorithm computes the $x$'th power of $g$ modulo $p$ and stores the result in $y$. It takes advantage of the Barrett reduction
+algorithm to keep the product small throughout the algorithm.
+
+The first two steps determine the optimal window size based on the number of bits in the exponent. The larger the exponent the
+larger the window size becomes. After a window size $winsize$ has been chosen an array of $2^{winsize}$ mp\_int variables is allocated. This
+table will hold the values of $g^x \mbox{ (mod }p\mbox{)}$ for $2^{winsize - 1} \le x < 2^{winsize}$.
+
+After the table is allocated the first power of $g$ is found. Since $g \ge p$ is allowed it must be first reduced modulo $p$ to make
+the rest of the algorithm more efficient. The first element of the table at $2^{winsize - 1}$ is found by squaring $M_1$ successively $winsize - 2$
+times. The rest of the table elements are found by multiplying the previous element by $M_1$ modulo $p$.
+
+Now that the table is available the sliding window may begin. The following list describes the functions of all the variables in the window.
+\begin{enumerate}
+\item The variable $mode$ dictates how the bits of the exponent are interpreted.
+\begin{enumerate}
+ \item When $mode = 0$ the bits are ignored since no non-zero bit of the exponent has been seen yet. For example, if the exponent were simply
+ $1$ then there would be $lg(\beta) - 1$ zero bits before the first non-zero bit. In this case bits are ignored until a non-zero bit is found.
+ \item When $mode = 1$ a non-zero bit has been seen before and a new $winsize$-bit window has not been formed yet. In this mode leading $0$ bits
+ are read and a single squaring is performed. If a non-zero bit is read a new window is created.
+ \item When $mode = 2$ the algorithm is in the middle of forming a window and new bits are appended to the window from the most significant bit
+ downwards.
+\end{enumerate}
+\item The variable $bitcnt$ indicates how many bits are left in the current digit of the exponent left to be read. When it reaches zero a new digit
+ is fetched from the exponent.
+\item The variable $buf$ holds the currently read digit of the exponent.
+\item The variable $digidx$ is an index into the exponents digits. It starts at the leading digit $x.used - 1$ and moves towards the trailing digit.
+\item The variable $bitcpy$ indicates how many bits are in the currently formed window. When it reaches $winsize$ the window is flushed and
+ the appropriate operations performed.
+\item The variable $bitbuf$ holds the current bits of the window being formed.
+\end{enumerate}
+
+All of step 12 is the window processing loop. It will iterate while there are digits available form the exponent to read. The first step
+inside this loop is to extract a new digit if no more bits are available in the current digit. If there are no bits left a new digit is
+read and if there are no digits left than the loop terminates.
+
+After a digit is made available step 12.3 will extract the most significant bit of the current digit and move all other bits in the digit
+upwards. In effect the digit is read from most significant bit to least significant bit and since the digits are read from leading to
+trailing edges the entire exponent is read from most significant bit to least significant bit.
+
+At step 12.5 if the $mode$ and currently extracted bit $y$ are both zero the bit is ignored and the next bit is read. This prevents the
+algorithm from having to perform trivial squaring and reduction operations before the first non-zero bit is read. Step 12.6 and 12.7-10 handle
+the two cases of $mode = 1$ and $mode = 2$ respectively.
+
+FIGU,expt_state,Sliding Window State Diagram
+
+By step 13 there are no more digits left in the exponent. However, there may be partial bits in the window left. If $mode = 2$ then
+a Left-to-Right algorithm is used to process the remaining few bits.
+
+EXAM,bn_s_mp_exptmod.c
+
+Lines @31,if@ through @45,}@ determine the optimal window size based on the length of the exponent in bits. The window divisions are sorted
+from smallest to greatest so that in each \textbf{if} statement only one condition must be tested. For example, by the \textbf{if} statement
+on line @37,if@ the value of $x$ is already known to be greater than $140$.
+
+The conditional piece of code beginning on line @42,ifdef@ allows the window size to be restricted to five bits. This logic is used to ensure
+the table of precomputed powers of $G$ remains relatively small.
+
+The for loop on line @60,for@ initializes the $M$ array while lines @71,mp_init@ and @75,mp_reduce@ through @85,}@ initialize the reduction
+function that will be used for this modulus.
+
+-- More later.
+
+\section{Quick Power of Two}
+Calculating $b = 2^a$ can be performed much quicker than with any of the previous algorithms. Recall that a logical shift left $m << k$ is
+equivalent to $m \cdot 2^k$. By this logic when $m = 1$ a quick power of two can be achieved.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_2expt}. \\
+\textbf{Input}. integer $b$ \\
+\textbf{Output}. $a \leftarrow 2^b$ \\
+\hline \\
+1. $a \leftarrow 0$ \\
+2. If $a.alloc < \lfloor b / lg(\beta) \rfloor + 1$ then grow $a$ appropriately. \\
+3. $a.used \leftarrow \lfloor b / lg(\beta) \rfloor + 1$ \\
+4. $a_{\lfloor b / lg(\beta) \rfloor} \leftarrow 1 << (b \mbox{ mod } lg(\beta))$ \\
+5. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_2expt}
+\end{figure}
+
+\textbf{Algorithm mp\_2expt.}
+
+EXAM,bn_mp_2expt.c
+
+\chapter{Higher Level Algorithms}
+
+This chapter discusses the various higher level algorithms that are required to complete a well rounded multiple precision integer package. These
+routines are less performance oriented than the algorithms of chapters five, six and seven but are no less important.
+
+The first section describes a method of integer division with remainder that is universally well known. It provides the signed division logic
+for the package. The subsequent section discusses a set of algorithms which allow a single digit to be the 2nd operand for a variety of operations.
+These algorithms serve mostly to simplify other algorithms where small constants are required. The last two sections discuss how to manipulate
+various representations of integers. For example, converting from an mp\_int to a string of character.
+
+\section{Integer Division with Remainder}
+\label{sec:division}
+
+Integer division aside from modular exponentiation is the most intensive algorithm to compute. Like addition, subtraction and multiplication
+the basis of this algorithm is the long-hand division algorithm taught to school children. Throughout this discussion several common variables
+will be used. Let $x$ represent the divisor and $y$ represent the dividend. Let $q$ represent the integer quotient $\lfloor y / x \rfloor$ and
+let $r$ represent the remainder $r = y - x \lfloor y / x \rfloor$. The following simple algorithm will be used to start the discussion.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Radix-$\beta$ Integer Division}. \\
+\textbf{Input}. integer $x$ and $y$ \\
+\textbf{Output}. $q = \lfloor y/x\rfloor, r = y - xq$ \\
+\hline \\
+1. $q \leftarrow 0$ \\
+2. $n \leftarrow \vert \vert y \vert \vert - \vert \vert x \vert \vert$ \\
+3. for $t$ from $n$ down to $0$ do \\
+\hspace{3mm}3.1 Maximize $k$ such that $kx\beta^t$ is less than or equal to $y$ and $(k + 1)x\beta^t$ is greater. \\
+\hspace{3mm}3.2 $q \leftarrow q + k\beta^t$ \\
+\hspace{3mm}3.3 $y \leftarrow y - kx\beta^t$ \\
+4. $r \leftarrow y$ \\
+5. Return($q, r$) \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm Radix-$\beta$ Integer Division}
+\label{fig:raddiv}
+\end{figure}
+
+As children we are taught this very simple algorithm for the case of $\beta = 10$. Almost instinctively several optimizations are taught for which
+their reason of existing are never explained. For this example let $y = 5471$ represent the dividend and $x = 23$ represent the divisor.
+
+To find the first digit of the quotient the value of $k$ must be maximized such that $kx\beta^t$ is less than or equal to $y$ and
+simultaneously $(k + 1)x\beta^t$ is greater than $y$. Implicitly $k$ is the maximum value the $t$'th digit of the quotient may have. The habitual method
+used to find the maximum is to ``eyeball'' the two numbers, typically only the leading digits and quickly estimate a quotient. By only using leading
+digits a much simpler division may be used to form an educated guess at what the value must be. In this case $k = \lfloor 54/23\rfloor = 2$ quickly
+arises as a possible solution. Indeed $2x\beta^2 = 4600$ is less than $y = 5471$ and simultaneously $(k + 1)x\beta^2 = 6900$ is larger than $y$.
+As a result $k\beta^2$ is added to the quotient which now equals $q = 200$ and $4600$ is subtracted from $y$ to give a remainder of $y = 841$.
+
+Again this process is repeated to produce the quotient digit $k = 3$ which makes the quotient $q = 200 + 3\beta = 230$ and the remainder
+$y = 841 - 3x\beta = 181$. Finally the last iteration of the loop produces $k = 7$ which leads to the quotient $q = 230 + 7 = 237$ and the
+remainder $y = 181 - 7x = 20$. The final quotient and remainder found are $q = 237$ and $r = y = 20$ which are indeed correct since
+$237 \cdot 23 + 20 = 5471$ is true.
+
+\subsection{Quotient Estimation}
+\label{sec:divest}
+As alluded to earlier the quotient digit $k$ can be estimated from only the leading digits of both the divisor and dividend. When $p$ leading
+digits are used from both the divisor and dividend to form an estimation the accuracy of the estimation rises as $p$ grows. Technically
+speaking the estimation is based on assuming the lower $\vert \vert y \vert \vert - p$ and $\vert \vert x \vert \vert - p$ lower digits of the
+dividend and divisor are zero.
+
+The value of the estimation may off by a few values in either direction and in general is fairly correct. A simplification \cite[pp. 271]{TAOCPV2}
+of the estimation technique is to use $t + 1$ digits of the dividend and $t$ digits of the divisor, in particularly when $t = 1$. The estimate
+using this technique is never too small. For the following proof let $t = \vert \vert y \vert \vert - 1$ and $s = \vert \vert x \vert \vert - 1$
+represent the most significant digits of the dividend and divisor respectively.
+
+\textbf{Proof.}\textit{ The quotient $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ is greater than or equal to
+$k = \lfloor y / (x \cdot \beta^{\vert \vert y \vert \vert - \vert \vert x \vert \vert - 1}) \rfloor$. }
+The first obvious case is when $\hat k = \beta - 1$ in which case the proof is concluded since the real quotient cannot be larger. For all other
+cases $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ and $\hat k x_s \ge y_t\beta + y_{t-1} - x_s + 1$. The latter portion of the inequalility
+$-x_s + 1$ arises from the fact that a truncated integer division will give the same quotient for at most $x_s - 1$ values. Next a series of
+inequalities will prove the hypothesis.
+
+\begin{equation}
+y - \hat k x \le y - \hat k x_s\beta^s
+\end{equation}
+
+This is trivially true since $x \ge x_s\beta^s$. Next we replace $\hat kx_s\beta^s$ by the previous inequality for $\hat kx_s$.
+
+\begin{equation}
+y - \hat k x \le y_t\beta^t + \ldots + y_0 - (y_t\beta^t + y_{t-1}\beta^{t-1} - x_s\beta^t + \beta^s)
+\end{equation}
+
+By simplifying the previous inequality the following inequality is formed.
+
+\begin{equation}
+y - \hat k x \le y_{t-2}\beta^{t-2} + \ldots + y_0 + x_s\beta^s - \beta^s
+\end{equation}
+
+Subsequently,
+
+\begin{equation}
+y_{t-2}\beta^{t-2} + \ldots + y_0 + x_s\beta^s - \beta^s < x_s\beta^s \le x
+\end{equation}
+
+Which proves that $y - \hat kx \le x$ and by consequence $\hat k \ge k$ which concludes the proof. \textbf{QED}
+
+
+\subsection{Normalized Integers}
+For the purposes of division a normalized input is when the divisors leading digit $x_n$ is greater than or equal to $\beta / 2$. By multiplying both
+$x$ and $y$ by $j = \lfloor (\beta / 2) / x_n \rfloor$ the quotient remains unchanged and the remainder is simply $j$ times the original
+remainder. The purpose of normalization is to ensure the leading digit of the divisor is sufficiently large such that the estimated quotient will
+lie in the domain of a single digit. Consider the maximum dividend $(\beta - 1) \cdot \beta + (\beta - 1)$ and the minimum divisor $\beta / 2$.
+
+\begin{equation}
+{{\beta^2 - 1} \over { \beta / 2}} \le 2\beta - {2 \over \beta}
+\end{equation}
+
+At most the quotient approaches $2\beta$, however, in practice this will not occur since that would imply the previous quotient digit was too small.
+
+\subsection{Radix-$\beta$ Division with Remainder}
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_div}. \\
+\textbf{Input}. mp\_int $a, b$ \\
+\textbf{Output}. $c = \lfloor a/b \rfloor$, $d = a - bc$ \\
+\hline \\
+1. If $b = 0$ return(\textit{MP\_VAL}). \\
+2. If $\vert a \vert < \vert b \vert$ then do \\
+\hspace{3mm}2.1 $d \leftarrow a$ \\
+\hspace{3mm}2.2 $c \leftarrow 0$ \\
+\hspace{3mm}2.3 Return(\textit{MP\_OKAY}). \\
+\\
+Setup the quotient to receive the digits. \\
+3. Grow $q$ to $a.used + 2$ digits. \\
+4. $q \leftarrow 0$ \\
+5. $x \leftarrow \vert a \vert , y \leftarrow \vert b \vert$ \\
+6. $sign \leftarrow \left \lbrace \begin{array}{ll}
+ MP\_ZPOS & \mbox{if }a.sign = b.sign \\
+ MP\_NEG & \mbox{otherwise} \\
+ \end{array} \right .$ \\
+\\
+Normalize the inputs such that the leading digit of $y$ is greater than or equal to $\beta / 2$. \\
+7. $norm \leftarrow (lg(\beta) - 1) - (\lceil lg(y) \rceil \mbox{ (mod }lg(\beta)\mbox{)})$ \\
+8. $x \leftarrow x \cdot 2^{norm}, y \leftarrow y \cdot 2^{norm}$ \\
+\\
+Find the leading digit of the quotient. \\
+9. $n \leftarrow x.used - 1, t \leftarrow y.used - 1$ \\
+10. $y \leftarrow y \cdot \beta^{n - t}$ \\
+11. While ($x \ge y$) do \\
+\hspace{3mm}11.1 $q_{n - t} \leftarrow q_{n - t} + 1$ \\
+\hspace{3mm}11.2 $x \leftarrow x - y$ \\
+12. $y \leftarrow \lfloor y / \beta^{n-t} \rfloor$ \\
+\\
+Continued on the next page. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_div}
+\end{figure}
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_div} (continued). \\
+\textbf{Input}. mp\_int $a, b$ \\
+\textbf{Output}. $c = \lfloor a/b \rfloor$, $d = a - bc$ \\
+\hline \\
+Now find the remainder fo the digits. \\
+13. for $i$ from $n$ down to $(t + 1)$ do \\
+\hspace{3mm}13.1 If $i > x.used$ then jump to the next iteration of this loop. \\
+\hspace{3mm}13.2 If $x_{i} = y_{t}$ then \\
+\hspace{6mm}13.2.1 $q_{i - t - 1} \leftarrow \beta - 1$ \\
+\hspace{3mm}13.3 else \\
+\hspace{6mm}13.3.1 $\hat r \leftarrow x_{i} \cdot \beta + x_{i - 1}$ \\
+\hspace{6mm}13.3.2 $\hat r \leftarrow \lfloor \hat r / y_{t} \rfloor$ \\
+\hspace{6mm}13.3.3 $q_{i - t - 1} \leftarrow \hat r$ \\
+\hspace{3mm}13.4 $q_{i - t - 1} \leftarrow q_{i - t - 1} + 1$ \\
+\\
+Fixup quotient estimation. \\
+\hspace{3mm}13.5 Loop \\
+\hspace{6mm}13.5.1 $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\
+\hspace{6mm}13.5.2 t$1 \leftarrow 0$ \\
+\hspace{6mm}13.5.3 t$1_0 \leftarrow y_{t - 1}, $ t$1_1 \leftarrow y_t,$ t$1.used \leftarrow 2$ \\
+\hspace{6mm}13.5.4 $t1 \leftarrow t1 \cdot q_{i - t - 1}$ \\
+\hspace{6mm}13.5.5 t$2_0 \leftarrow x_{i - 2}, $ t$2_1 \leftarrow x_{i - 1}, $ t$2_2 \leftarrow x_i, $ t$2.used \leftarrow 3$ \\
+\hspace{6mm}13.5.6 If $\vert t1 \vert > \vert t2 \vert$ then goto step 13.5. \\
+\hspace{3mm}13.6 t$1 \leftarrow y \cdot q_{i - t - 1}$ \\
+\hspace{3mm}13.7 t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\
+\hspace{3mm}13.8 $x \leftarrow x - $ t$1$ \\
+\hspace{3mm}13.9 If $x.sign = MP\_NEG$ then \\
+\hspace{6mm}13.10 t$1 \leftarrow y$ \\
+\hspace{6mm}13.11 t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\
+\hspace{6mm}13.12 $x \leftarrow x + $ t$1$ \\
+\hspace{6mm}13.13 $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\
+\\
+Finalize the result. \\
+14. Clamp excess digits of $q$ \\
+15. $c \leftarrow q, c.sign \leftarrow sign$ \\
+16. $x.sign \leftarrow a.sign$ \\
+17. $d \leftarrow \lfloor x / 2^{norm} \rfloor$ \\
+18. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_div (continued)}
+\end{figure}
+\textbf{Algorithm mp\_div.}
+This algorithm will calculate quotient and remainder from an integer division given a dividend and divisor. The algorithm is a signed
+division and will produce a fully qualified quotient and remainder.
+
+First the divisor $b$ must be non-zero which is enforced in step one. If the divisor is larger than the dividend than the quotient is implicitly
+zero and the remainder is the dividend.
+
+After the first two trivial cases of inputs are handled the variable $q$ is setup to receive the digits of the quotient. Two unsigned copies of the
+divisor $y$ and dividend $x$ are made as well. The core of the division algorithm is an unsigned division and will only work if the values are
+positive. Now the two values $x$ and $y$ must be normalized such that the leading digit of $y$ is greater than or equal to $\beta / 2$.
+This is performed by shifting both to the left by enough bits to get the desired normalization.
+
+At this point the division algorithm can begin producing digits of the quotient. Recall that maximum value of the estimation used is
+$2\beta - {2 \over \beta}$ which means that a digit of the quotient must be first produced by another means. In this case $y$ is shifted
+to the left (\textit{step ten}) so that it has the same number of digits as $x$. The loop on step eleven will subtract multiples of the
+shifted copy of $y$ until $x$ is smaller. Since the leading digit of $y$ is greater than or equal to $\beta/2$ this loop will iterate at most two
+times to produce the desired leading digit of the quotient.
+
+Now the remainder of the digits can be produced. The equation $\hat q = \lfloor {{x_i \beta + x_{i-1}}\over y_t} \rfloor$ is used to fairly
+accurately approximate the true quotient digit. The estimation can in theory produce an estimation as high as $2\beta - {2 \over \beta}$ but by
+induction the upper quotient digit is correct (\textit{as established on step eleven}) and the estimate must be less than $\beta$.
+
+Recall from section~\ref{sec:divest} that the estimation is never too low but may be too high. The next step of the estimation process is
+to refine the estimation. The loop on step 13.5 uses $x_i\beta^2 + x_{i-1}\beta + x_{i-2}$ and $q_{i - t - 1}(y_t\beta + y_{t-1})$ as a higher
+order approximation to adjust the quotient digit.
+
+After both phases of estimation the quotient digit may still be off by a value of one\footnote{This is similar to the error introduced
+by optimizing Barrett reduction.}. Steps 13.6 and 13.7 subtract the multiple of the divisor from the dividend (\textit{Similar to step 3.3 of
+algorithm~\ref{fig:raddiv}} and then subsequently add a multiple of the divisor if the quotient was too large.
+
+Now that the quotient has been determine finializing the result is a matter of clamping the quotient, fixing the sizes and de-normalizing the
+remainder. An important aspect of this algorithm seemingly overlooked in other descriptions such as that of Algorithm 14.20 HAC \cite[pp. 598]{HAC}
+is that when the estimations are being made (\textit{inside the loop on step 13.5}) that the digits $y_{t-1}$, $x_{i-2}$ and $x_{i-1}$ may lie
+outside their respective boundaries. For example, if $t = 0$ or $i \le 1$ then the digits would be undefined. In those cases the digits should
+respectively be replaced with a zero.
+
+EXAM,bn_mp_div.c
+
+The implementation of this algorithm differs slightly from the pseudo code presented previously. In this algorithm either of the quotient $c$ or
+remainder $d$ may be passed as a \textbf{NULL} pointer which indicates their value is not desired. For example, the C code to call the division
+algorithm with only the quotient is
+
+\begin{verbatim}
+mp_div(&a, &b, &c, NULL); /* c = [a/b] */
+\end{verbatim}
+
+Lines @108,if@ and @113,if@ handle the two trivial cases of inputs which are division by zero and dividend smaller than the divisor
+respectively. After the two trivial cases all of the temporary variables are initialized. Line @147,neg@ determines the sign of
+the quotient and line @148,sign@ ensures that both $x$ and $y$ are positive.
+
+The number of bits in the leading digit is calculated on line @151,norm@. Implictly an mp\_int with $r$ digits will require $lg(\beta)(r-1) + k$ bits
+of precision which when reduced modulo $lg(\beta)$ produces the value of $k$. In this case $k$ is the number of bits in the leading digit which is
+exactly what is required. For the algorithm to operate $k$ must equal $lg(\beta) - 1$ and when it does not the inputs must be normalized by shifting
+them to the left by $lg(\beta) - 1 - k$ bits.
+
+Throughout the variables $n$ and $t$ will represent the highest digit of $x$ and $y$ respectively. These are first used to produce the
+leading digit of the quotient. The loop beginning on line @184,for@ will produce the remainder of the quotient digits.
+
+The conditional ``continue'' on line @186,continue@ is used to prevent the algorithm from reading past the leading edge of $x$ which can occur when the
+algorithm eliminates multiple non-zero digits in a single iteration. This ensures that $x_i$ is always non-zero since by definition the digits
+above the $i$'th position $x$ must be zero in order for the quotient to be precise\footnote{Precise as far as integer division is concerned.}.
+
+Lines @214,t1@, @216,t1@ and @222,t2@ through @225,t2@ manually construct the high accuracy estimations by setting the digits of the two mp\_int
+variables directly.
+
+\section{Single Digit Helpers}
+
+This section briefly describes a series of single digit helper algorithms which come in handy when working with small constants. All of
+the helper functions assume the single digit input is positive and will treat them as such.
+
+\subsection{Single Digit Addition and Subtraction}
+
+Both addition and subtraction are performed by ``cheating'' and using mp\_set followed by the higher level addition or subtraction
+algorithms. As a result these algorithms are subtantially simpler with a slight cost in performance.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_add\_d}. \\
+\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\
+\textbf{Output}. $c = a + b$ \\
+\hline \\
+1. $t \leftarrow b$ (\textit{mp\_set}) \\
+2. $c \leftarrow a + t$ \\
+3. Return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_add\_d}
+\end{figure}
+
+\textbf{Algorithm mp\_add\_d.}
+This algorithm initiates a temporary mp\_int with the value of the single digit and uses algorithm mp\_add to add the two values together.
+
+EXAM,bn_mp_add_d.c
+
+Clever use of the letter 't'.
+
+\subsubsection{Subtraction}
+The single digit subtraction algorithm mp\_sub\_d is essentially the same except it uses mp\_sub to subtract the digit from the mp\_int.
+
+\subsection{Single Digit Multiplication}
+Single digit multiplication arises enough in division and radix conversion that it ought to be implement as a special case of the baseline
+multiplication algorithm. Essentially this algorithm is a modified version of algorithm s\_mp\_mul\_digs where one of the multiplicands
+only has one digit.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_mul\_d}. \\
+\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\
+\textbf{Output}. $c = ab$ \\
+\hline \\
+1. $pa \leftarrow a.used$ \\
+2. Grow $c$ to at least $pa + 1$ digits. \\
+3. $oldused \leftarrow c.used$ \\
+4. $c.used \leftarrow pa + 1$ \\
+5. $c.sign \leftarrow a.sign$ \\
+6. $\mu \leftarrow 0$ \\
+7. for $ix$ from $0$ to $pa - 1$ do \\
+\hspace{3mm}7.1 $\hat r \leftarrow \mu + a_{ix}b$ \\
+\hspace{3mm}7.2 $c_{ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{3mm}7.3 $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\
+8. $c_{pa} \leftarrow \mu$ \\
+9. for $ix$ from $pa + 1$ to $oldused$ do \\
+\hspace{3mm}9.1 $c_{ix} \leftarrow 0$ \\
+10. Clamp excess digits of $c$. \\
+11. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_mul\_d}
+\end{figure}
+\textbf{Algorithm mp\_mul\_d.}
+This algorithm quickly multiplies an mp\_int by a small single digit value. It is specially tailored to the job and has a minimal of overhead.
+Unlike the full multiplication algorithms this algorithm does not require any significnat temporary storage or memory allocations.
+
+EXAM,bn_mp_mul_d.c
+
+In this implementation the destination $c$ may point to the same mp\_int as the source $a$ since the result is written after the digit is
+read from the source. This function uses pointer aliases $tmpa$ and $tmpc$ for the digits of $a$ and $c$ respectively.
+
+\subsection{Single Digit Division}
+Like the single digit multiplication algorithm, single digit division is also a fairly common algorithm used in radix conversion. Since the
+divisor is only a single digit a specialized variant of the division algorithm can be used to compute the quotient.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_div\_d}. \\
+\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\
+\textbf{Output}. $c = \lfloor a / b \rfloor, d = a - cb$ \\
+\hline \\
+1. If $b = 0$ then return(\textit{MP\_VAL}).\\
+2. If $b = 3$ then use algorithm mp\_div\_3 instead. \\
+3. Init $q$ to $a.used$ digits. \\
+4. $q.used \leftarrow a.used$ \\
+5. $q.sign \leftarrow a.sign$ \\
+6. $\hat w \leftarrow 0$ \\
+7. for $ix$ from $a.used - 1$ down to $0$ do \\
+\hspace{3mm}7.1 $\hat w \leftarrow \hat w \beta + a_{ix}$ \\
+\hspace{3mm}7.2 If $\hat w \ge b$ then \\
+\hspace{6mm}7.2.1 $t \leftarrow \lfloor \hat w / b \rfloor$ \\
+\hspace{6mm}7.2.2 $\hat w \leftarrow \hat w \mbox{ (mod }b\mbox{)}$ \\
+\hspace{3mm}7.3 else\\
+\hspace{6mm}7.3.1 $t \leftarrow 0$ \\
+\hspace{3mm}7.4 $q_{ix} \leftarrow t$ \\
+8. $d \leftarrow \hat w$ \\
+9. Clamp excess digits of $q$. \\
+10. $c \leftarrow q$ \\
+11. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_div\_d}
+\end{figure}
+\textbf{Algorithm mp\_div\_d.}
+This algorithm divides the mp\_int $a$ by the single mp\_digit $b$ using an optimized approach. Essentially in every iteration of the
+algorithm another digit of the dividend is reduced and another digit of quotient produced. Provided $b < \beta$ the value of $\hat w$
+after step 7.1 will be limited such that $0 \le \lfloor \hat w / b \rfloor < \beta$.
+
+If the divisor $b$ is equal to three a variant of this algorithm is used which is called mp\_div\_3. It replaces the division by three with
+a multiplication by $\lfloor \beta / 3 \rfloor$ and the appropriate shift and residual fixup. In essence it is much like the Barrett reduction
+from chapter seven.
+
+EXAM,bn_mp_div_d.c
+
+Like the implementation of algorithm mp\_div this algorithm allows either of the quotient or remainder to be passed as a \textbf{NULL} pointer to
+indicate the respective value is not required. This allows a trivial single digit modular reduction algorithm, mp\_mod\_d to be created.
+
+The division and remainder on lines @44,/@ and @45,%@ can be replaced often by a single division on most processors. For example, the 32-bit x86 based
+processors can divide a 64-bit quantity by a 32-bit quantity and produce the quotient and remainder simultaneously. Unfortunately the GCC
+compiler does not recognize that optimization and will actually produce two function calls to find the quotient and remainder respectively.
+
+\subsection{Single Digit Root Extraction}
+
+Finding the $n$'th root of an integer is fairly easy as far as numerical analysis is concerned. Algorithms such as the Newton-Raphson approximation
+(\ref{eqn:newton}) series will converge very quickly to a root for any continuous function $f(x)$.
+
+\begin{equation}
+x_{i+1} = x_i - {f(x_i) \over f'(x_i)}
+\label{eqn:newton}
+\end{equation}
+
+In this case the $n$'th root is desired and $f(x) = x^n - a$ where $a$ is the integer of which the root is desired. The derivative of $f(x)$ is
+simply $f'(x) = nx^{n - 1}$. Of particular importance is that this algorithm will be used over the integers not over the a more continuous domain
+such as the real numbers. As a result the root found can be above the true root by few and must be manually adjusted. Ideally at the end of the
+algorithm the $n$'th root $b$ of an integer $a$ is desired such that $b^n \le a$.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_n\_root}. \\
+\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\
+\textbf{Output}. $c^b \le a$ \\
+\hline \\
+1. If $b$ is even and $a.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\
+2. $sign \leftarrow a.sign$ \\
+3. $a.sign \leftarrow MP\_ZPOS$ \\
+4. t$2 \leftarrow 2$ \\
+5. Loop \\
+\hspace{3mm}5.1 t$1 \leftarrow $ t$2$ \\
+\hspace{3mm}5.2 t$3 \leftarrow $ t$1^{b - 1}$ \\
+\hspace{3mm}5.3 t$2 \leftarrow $ t$3 $ $\cdot$ t$1$ \\
+\hspace{3mm}5.4 t$2 \leftarrow $ t$2 - a$ \\
+\hspace{3mm}5.5 t$3 \leftarrow $ t$3 \cdot b$ \\
+\hspace{3mm}5.6 t$3 \leftarrow \lfloor $t$2 / $t$3 \rfloor$ \\
+\hspace{3mm}5.7 t$2 \leftarrow $ t$1 - $ t$3$ \\
+\hspace{3mm}5.8 If t$1 \ne $ t$2$ then goto step 5. \\
+6. Loop \\
+\hspace{3mm}6.1 t$2 \leftarrow $ t$1^b$ \\
+\hspace{3mm}6.2 If t$2 > a$ then \\
+\hspace{6mm}6.2.1 t$1 \leftarrow $ t$1 - 1$ \\
+\hspace{6mm}6.2.2 Goto step 6. \\
+7. $a.sign \leftarrow sign$ \\
+8. $c \leftarrow $ t$1$ \\
+9. $c.sign \leftarrow sign$ \\
+10. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_n\_root}
+\end{figure}
+\textbf{Algorithm mp\_n\_root.}
+This algorithm finds the integer $n$'th root of an input using the Newton-Raphson approach. It is partially optimized based on the observation
+that the numerator of ${f(x) \over f'(x)}$ can be derived from a partial denominator. That is at first the denominator is calculated by finding
+$x^{b - 1}$. This value can then be multiplied by $x$ and have $a$ subtracted from it to find the numerator. This saves a total of $b - 1$
+multiplications by t$1$ inside the loop.
+
+The initial value of the approximation is t$2 = 2$ which allows the algorithm to start with very small values and quickly converge on the
+root. Ideally this algorithm is meant to find the $n$'th root of an input where $n$ is bounded by $2 \le n \le 5$.
+
+EXAM,bn_mp_n_root.c
+
+\section{Random Number Generation}
+
+Random numbers come up in a variety of activities from public key cryptography to simple simulations and various randomized algorithms. Pollard-Rho
+factoring for example, can make use of random values as starting points to find factors of a composite integer. In this case the algorithm presented
+is solely for simulations and not intended for cryptographic use.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_rand}. \\
+\textbf{Input}. An integer $b$ \\
+\textbf{Output}. A pseudo-random number of $b$ digits \\
+\hline \\
+1. $a \leftarrow 0$ \\
+2. If $b \le 0$ return(\textit{MP\_OKAY}) \\
+3. Pick a non-zero random digit $d$. \\
+4. $a \leftarrow a + d$ \\
+5. for $ix$ from 1 to $d - 1$ do \\
+\hspace{3mm}5.1 $a \leftarrow a \cdot \beta$ \\
+\hspace{3mm}5.2 Pick a random digit $d$. \\
+\hspace{3mm}5.3 $a \leftarrow a + d$ \\
+6. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_rand}
+\end{figure}
+\textbf{Algorithm mp\_rand.}
+This algorithm produces a pseudo-random integer of $b$ digits. By ensuring that the first digit is non-zero the algorithm also guarantees that the
+final result has at least $b$ digits. It relies heavily on a third-part random number generator which should ideally generate uniformly all of
+the integers from $0$ to $\beta - 1$.
+
+EXAM,bn_mp_rand.c
+
+\section{Formatted Representations}
+The ability to emit a radix-$n$ textual representation of an integer is useful for interacting with human parties. For example, the ability to
+be given a string of characters such as ``114585'' and turn it into the radix-$\beta$ equivalent would make it easier to enter numbers
+into a program.
+
+\subsection{Reading Radix-n Input}
+For the purposes of this text we will assume that a simple lower ASCII map (\ref{fig:ASC}) is used for the values of from $0$ to $63$ to
+printable characters. For example, when the character ``N'' is read it represents the integer $23$. The first $16$ characters of the
+map are for the common representations up to hexadecimal. After that they match the ``base64'' encoding scheme which are suitable chosen
+such that they are printable. While outputting as base64 may not be too helpful for human operators it does allow communication via non binary
+mediums.
+
+\newpage\begin{figure}[here]
+\begin{center}
+\begin{tabular}{cc|cc|cc|cc}
+\hline \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} \\
+\hline
+0 & 0 & 1 & 1 & 2 & 2 & 3 & 3 \\
+4 & 4 & 5 & 5 & 6 & 6 & 7 & 7 \\
+8 & 8 & 9 & 9 & 10 & A & 11 & B \\
+12 & C & 13 & D & 14 & E & 15 & F \\
+16 & G & 17 & H & 18 & I & 19 & J \\
+20 & K & 21 & L & 22 & M & 23 & N \\
+24 & O & 25 & P & 26 & Q & 27 & R \\
+28 & S & 29 & T & 30 & U & 31 & V \\
+32 & W & 33 & X & 34 & Y & 35 & Z \\
+36 & a & 37 & b & 38 & c & 39 & d \\
+40 & e & 41 & f & 42 & g & 43 & h \\
+44 & i & 45 & j & 46 & k & 47 & l \\
+48 & m & 49 & n & 50 & o & 51 & p \\
+52 & q & 53 & r & 54 & s & 55 & t \\
+56 & u & 57 & v & 58 & w & 59 & x \\
+60 & y & 61 & z & 62 & $+$ & 63 & $/$ \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Lower ASCII Map}
+\label{fig:ASC}
+\end{figure}
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_read\_radix}. \\
+\textbf{Input}. A string $str$ of length $sn$ and radix $r$. \\
+\textbf{Output}. The radix-$\beta$ equivalent mp\_int. \\
+\hline \\
+1. If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\
+2. $ix \leftarrow 0$ \\
+3. If $str_0 =$ ``-'' then do \\
+\hspace{3mm}3.1 $ix \leftarrow ix + 1$ \\
+\hspace{3mm}3.2 $sign \leftarrow MP\_NEG$ \\
+4. else \\
+\hspace{3mm}4.1 $sign \leftarrow MP\_ZPOS$ \\
+5. $a \leftarrow 0$ \\
+6. for $iy$ from $ix$ to $sn - 1$ do \\
+\hspace{3mm}6.1 Let $y$ denote the position in the map of $str_{iy}$. \\
+\hspace{3mm}6.2 If $str_{iy}$ is not in the map or $y \ge r$ then goto step 7. \\
+\hspace{3mm}6.3 $a \leftarrow a \cdot r$ \\
+\hspace{3mm}6.4 $a \leftarrow a + y$ \\
+7. If $a \ne 0$ then $a.sign \leftarrow sign$ \\
+8. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_read\_radix}
+\end{figure}
+\textbf{Algorithm mp\_read\_radix.}
+This algorithm will read an ASCII string and produce the radix-$\beta$ mp\_int representation of the same integer. A minus symbol ``-'' may precede the
+string to indicate the value is negative, otherwise it is assumed to be positive. The algorithm will read up to $sn$ characters from the input
+and will stop when it reads a character it cannot map the algorithm stops reading characters from the string. This allows numbers to be embedded
+as part of larger input without any significant problem.
+
+EXAM,bn_mp_read_radix.c
+
+\subsection{Generating Radix-$n$ Output}
+Generating radix-$n$ output is fairly trivial with a division and remainder algorithm.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_toradix}. \\
+\textbf{Input}. A mp\_int $a$ and an integer $r$\\
+\textbf{Output}. The radix-$r$ representation of $a$ \\
+\hline \\
+1. If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\
+2. If $a = 0$ then $str = $ ``$0$'' and return(\textit{MP\_OKAY}). \\
+3. $t \leftarrow a$ \\
+4. $str \leftarrow$ ``'' \\
+5. if $t.sign = MP\_NEG$ then \\
+\hspace{3mm}5.1 $str \leftarrow str + $ ``-'' \\
+\hspace{3mm}5.2 $t.sign = MP\_ZPOS$ \\
+6. While ($t \ne 0$) do \\
+\hspace{3mm}6.1 $d \leftarrow t \mbox{ (mod }r\mbox{)}$ \\
+\hspace{3mm}6.2 $t \leftarrow \lfloor t / r \rfloor$ \\
+\hspace{3mm}6.3 Look up $d$ in the map and store the equivalent character in $y$. \\
+\hspace{3mm}6.4 $str \leftarrow str + y$ \\
+7. If $str_0 = $``$-$'' then \\
+\hspace{3mm}7.1 Reverse the digits $str_1, str_2, \ldots str_n$. \\
+8. Otherwise \\
+\hspace{3mm}8.1 Reverse the digits $str_0, str_1, \ldots str_n$. \\
+9. Return(\textit{MP\_OKAY}).\\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_toradix}
+\end{figure}
+\textbf{Algorithm mp\_toradix.}
+This algorithm computes the radix-$r$ representation of an mp\_int $a$. The ``digits'' of the representation are extracted by reducing
+successive powers of $\lfloor a / r^k \rfloor$ the input modulo $r$ until $r^k > a$. Note that instead of actually dividing by $r^k$ in
+each iteration the quotient $\lfloor a / r \rfloor$ is saved for the next iteration. As a result a series of trivial $n \times 1$ divisions
+are required instead of a series of $n \times k$ divisions. One design flaw of this approach is that the digits are produced in the reverse order
+(see~\ref{fig:mpradix}). To remedy this flaw the digits must be swapped or simply ``reversed''.
+
+\begin{figure}
+\begin{center}
+\begin{tabular}{|c|c|c|}
+\hline \textbf{Value of $a$} & \textbf{Value of $d$} & \textbf{Value of $str$} \\
+\hline $1234$ & -- & -- \\
+\hline $123$ & $4$ & ``4'' \\
+\hline $12$ & $3$ & ``43'' \\
+\hline $1$ & $2$ & ``432'' \\
+\hline $0$ & $1$ & ``4321'' \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Example of Algorithm mp\_toradix.}
+\label{fig:mpradix}
+\end{figure}
+
+EXAM,bn_mp_toradix.c
+
+\chapter{Number Theoretic Algorithms}
+This chapter discusses several fundamental number theoretic algorithms such as the greatest common divisor, least common multiple and Jacobi
+symbol computation. These algorithms arise as essential components in several key cryptographic algorithms such as the RSA public key algorithm and
+various Sieve based factoring algorithms.
+
+\section{Greatest Common Divisor}
+The greatest common divisor of two integers $a$ and $b$, often denoted as $(a, b)$ is the largest integer $k$ that is a proper divisor of
+both $a$ and $b$. That is, $k$ is the largest integer such that $0 \equiv a \mbox{ (mod }k\mbox{)}$ and $0 \equiv b \mbox{ (mod }k\mbox{)}$ occur
+simultaneously.
+
+The most common approach (cite) is to reduce one input modulo another. That is if $a$ and $b$ are divisible by some integer $k$ and if $qa + r = b$ then
+$r$ is also divisible by $k$. The reduction pattern follows $\left < a , b \right > \rightarrow \left < b, a \mbox{ mod } b \right >$.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Greatest Common Divisor (I)}. \\
+\textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\
+\textbf{Output}. The greatest common divisor $(a, b)$. \\
+\hline \\
+1. While ($b > 0$) do \\
+\hspace{3mm}1.1 $r \leftarrow a \mbox{ (mod }b\mbox{)}$ \\
+\hspace{3mm}1.2 $a \leftarrow b$ \\
+\hspace{3mm}1.3 $b \leftarrow r$ \\
+2. Return($a$). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm Greatest Common Divisor (I)}
+\label{fig:gcd1}
+\end{figure}
+
+This algorithm will quickly converge on the greatest common divisor since the residue $r$ tends diminish rapidly. However, divisions are
+relatively expensive operations to perform and should ideally be avoided. There is another approach based on a similar relationship of
+greatest common divisors. The faster approach is based on the observation that if $k$ divides both $a$ and $b$ it will also divide $a - b$.
+In particular, we would like $a - b$ to decrease in magnitude which implies that $b \ge a$.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Greatest Common Divisor (II)}. \\
+\textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\
+\textbf{Output}. The greatest common divisor $(a, b)$. \\
+\hline \\
+1. While ($b > 0$) do \\
+\hspace{3mm}1.1 Swap $a$ and $b$ such that $a$ is the smallest of the two. \\
+\hspace{3mm}1.2 $b \leftarrow b - a$ \\
+2. Return($a$). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm Greatest Common Divisor (II)}
+\label{fig:gcd2}
+\end{figure}
+
+\textbf{Proof} \textit{Algorithm~\ref{fig:gcd2} will return the greatest common divisor of $a$ and $b$.}
+The algorithm in figure~\ref{fig:gcd2} will eventually terminate since $b \ge a$ the subtraction in step 1.2 will be a value less than $b$. In other
+words in every iteration that tuple $\left < a, b \right >$ decrease in magnitude until eventually $a = b$. Since both $a$ and $b$ are always
+divisible by the greatest common divisor (\textit{until the last iteration}) and in the last iteration of the algorithm $b = 0$, therefore, in the
+second to last iteration of the algorithm $b = a$ and clearly $(a, a) = a$ which concludes the proof. \textbf{QED}.
+
+As a matter of practicality algorithm \ref{fig:gcd1} decreases far too slowly to be useful. Specially if $b$ is much larger than $a$ such that
+$b - a$ is still very much larger than $a$. A simple addition to the algorithm is to divide $b - a$ by a power of some integer $p$ which does
+not divide the greatest common divisor but will divide $b - a$. In this case ${b - a} \over p$ is also an integer and still divisible by
+the greatest common divisor.
+
+However, instead of factoring $b - a$ to find a suitable value of $p$ the powers of $p$ can be removed from $a$ and $b$ that are in common first.
+Then inside the loop whenever $b - a$ is divisible by some power of $p$ it can be safely removed.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Greatest Common Divisor (III)}. \\
+\textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\
+\textbf{Output}. The greatest common divisor $(a, b)$. \\
+\hline \\
+1. $k \leftarrow 0$ \\
+2. While $a$ and $b$ are both divisible by $p$ do \\
+\hspace{3mm}2.1 $a \leftarrow \lfloor a / p \rfloor$ \\
+\hspace{3mm}2.2 $b \leftarrow \lfloor b / p \rfloor$ \\
+\hspace{3mm}2.3 $k \leftarrow k + 1$ \\
+3. While $a$ is divisible by $p$ do \\
+\hspace{3mm}3.1 $a \leftarrow \lfloor a / p \rfloor$ \\
+4. While $b$ is divisible by $p$ do \\
+\hspace{3mm}4.1 $b \leftarrow \lfloor b / p \rfloor$ \\
+5. While ($b > 0$) do \\
+\hspace{3mm}5.1 Swap $a$ and $b$ such that $a$ is the smallest of the two. \\
+\hspace{3mm}5.2 $b \leftarrow b - a$ \\
+\hspace{3mm}5.3 While $b$ is divisible by $p$ do \\
+\hspace{6mm}5.3.1 $b \leftarrow \lfloor b / p \rfloor$ \\
+6. Return($a \cdot p^k$). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm Greatest Common Divisor (III)}
+\label{fig:gcd3}
+\end{figure}
+
+This algorithm is based on the first except it removes powers of $p$ first and inside the main loop to ensure the tuple $\left < a, b \right >$
+decreases more rapidly. The first loop on step two removes powers of $p$ that are in common. A count, $k$, is kept which will present a common
+divisor of $p^k$. After step two the remaining common divisor of $a$ and $b$ cannot be divisible by $p$. This means that $p$ can be safely
+divided out of the difference $b - a$ so long as the division leaves no remainder.
+
+In particular the value of $p$ should be chosen such that the division on step 5.3.1 occur often. It also helps that division by $p$ be easy
+to compute. The ideal choice of $p$ is two since division by two amounts to a right logical shift. Another important observation is that by
+step five both $a$ and $b$ are odd. Therefore, the diffrence $b - a$ must be even which means that each iteration removes one bit from the
+largest of the pair.
+
+\subsection{Complete Greatest Common Divisor}
+The algorithms presented so far cannot handle inputs which are zero or negative. The following algorithm can handle all input cases properly
+and will produce the greatest common divisor.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_gcd}. \\
+\textbf{Input}. mp\_int $a$ and $b$ \\
+\textbf{Output}. The greatest common divisor $c = (a, b)$. \\
+\hline \\
+1. If $a = 0$ then \\
+\hspace{3mm}1.1 $c \leftarrow \vert b \vert $ \\
+\hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\
+2. If $b = 0$ then \\
+\hspace{3mm}2.1 $c \leftarrow \vert a \vert $ \\
+\hspace{3mm}2.2 Return(\textit{MP\_OKAY}). \\
+3. $u \leftarrow \vert a \vert, v \leftarrow \vert b \vert$ \\
+4. $k \leftarrow 0$ \\
+5. While $u.used > 0$ and $v.used > 0$ and $u_0 \equiv v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
+\hspace{3mm}5.1 $k \leftarrow k + 1$ \\
+\hspace{3mm}5.2 $u \leftarrow \lfloor u / 2 \rfloor$ \\
+\hspace{3mm}5.3 $v \leftarrow \lfloor v / 2 \rfloor$ \\
+6. While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
+\hspace{3mm}6.1 $u \leftarrow \lfloor u / 2 \rfloor$ \\
+7. While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
+\hspace{3mm}7.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\
+8. While $v.used > 0$ \\
+\hspace{3mm}8.1 If $\vert u \vert > \vert v \vert$ then \\
+\hspace{6mm}8.1.1 Swap $u$ and $v$. \\
+\hspace{3mm}8.2 $v \leftarrow \vert v \vert - \vert u \vert$ \\
+\hspace{3mm}8.3 While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
+\hspace{6mm}8.3.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\
+9. $c \leftarrow u \cdot 2^k$ \\
+10. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_gcd}
+\end{figure}
+\textbf{Algorithm mp\_gcd.}
+This algorithm will produce the greatest common divisor of two mp\_ints $a$ and $b$. The algorithm was originally based on Algorithm B of
+Knuth \cite[pp. 338]{TAOCPV2} but has been modified to be simpler to explain. In theory it achieves the same asymptotic working time as
+Algorithm B and in practice this appears to be true.
+
+The first two steps handle the cases where either one of or both inputs are zero. If either input is zero the greatest common divisor is the
+largest input or zero if they are both zero. If the inputs are not trivial than $u$ and $v$ are assigned the absolute values of
+$a$ and $b$ respectively and the algorithm will proceed to reduce the pair.
+
+Step five will divide out any common factors of two and keep track of the count in the variable $k$. After this step, two is no longer a
+factor of the remaining greatest common divisor between $u$ and $v$ and can be safely evenly divided out of either whenever they are even. Step
+six and seven ensure that the $u$ and $v$ respectively have no more factors of two. At most only one of the while--loops will iterate since
+they cannot both be even.
+
+By step eight both of $u$ and $v$ are odd which is required for the inner logic. First the pair are swapped such that $v$ is equal to
+or greater than $u$. This ensures that the subtraction on step 8.2 will always produce a positive and even result. Step 8.3 removes any
+factors of two from the difference $u$ to ensure that in the next iteration of the loop both are once again odd.
+
+After $v = 0$ occurs the variable $u$ has the greatest common divisor of the pair $\left < u, v \right >$ just after step six. The result
+must be adjusted by multiplying by the common factors of two ($2^k$) removed earlier.
+
+EXAM,bn_mp_gcd.c
+
+This function makes use of the macros mp\_iszero and mp\_iseven. The former evaluates to $1$ if the input mp\_int is equivalent to the
+integer zero otherwise it evaluates to $0$. The latter evaluates to $1$ if the input mp\_int represents a non-zero even integer otherwise
+it evaluates to $0$. Note that just because mp\_iseven may evaluate to $0$ does not mean the input is odd, it could also be zero. The three
+trivial cases of inputs are handled on lines @23,zero@ through @29,}@. After those lines the inputs are assumed to be non-zero.
+
+Lines @32,if@ and @36,if@ make local copies $u$ and $v$ of the inputs $a$ and $b$ respectively. At this point the common factors of two
+must be divided out of the two inputs. The block starting at line @43,common@ removes common factors of two by first counting the number of trailing
+zero bits in both. The local integer $k$ is used to keep track of how many factors of $2$ are pulled out of both values. It is assumed that
+the number of factors will not exceed the maximum value of a C ``int'' data type\footnote{Strictly speaking no array in C may have more than
+entries than are accessible by an ``int'' so this is not a limitation.}.
+
+At this point there are no more common factors of two in the two values. The divisions by a power of two on lines @60,div_2d@ and @67,div_2d@ remove
+any independent factors of two such that both $u$ and $v$ are guaranteed to be an odd integer before hitting the main body of the algorithm. The while loop
+on line @72, while@ performs the reduction of the pair until $v$ is equal to zero. The unsigned comparison and subtraction algorithms are used in
+place of the full signed routines since both values are guaranteed to be positive and the result of the subtraction is guaranteed to be non-negative.
+
+\section{Least Common Multiple}
+The least common multiple of a pair of integers is their product divided by their greatest common divisor. For two integers $a$ and $b$ the
+least common multiple is normally denoted as $[ a, b ]$ and numerically equivalent to ${ab} \over {(a, b)}$. For example, if $a = 2 \cdot 2 \cdot 3 = 12$
+and $b = 2 \cdot 3 \cdot 3 \cdot 7 = 126$ the least common multiple is ${126 \over {(12, 126)}} = {126 \over 6} = 21$.
+
+The least common multiple arises often in coding theory as well as number theory. If two functions have periods of $a$ and $b$ respectively they will
+collide, that is be in synchronous states, after only $[ a, b ]$ iterations. This is why, for example, random number generators based on
+Linear Feedback Shift Registers (LFSR) tend to use registers with periods which are co-prime (\textit{e.g. the greatest common divisor is one.}).
+Similarly in number theory if a composite $n$ has two prime factors $p$ and $q$ then maximal order of any unit of $\Z/n\Z$ will be $[ p - 1, q - 1] $.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_lcm}. \\
+\textbf{Input}. mp\_int $a$ and $b$ \\
+\textbf{Output}. The least common multiple $c = [a, b]$. \\
+\hline \\
+1. $c \leftarrow (a, b)$ \\
+2. $t \leftarrow a \cdot b$ \\
+3. $c \leftarrow \lfloor t / c \rfloor$ \\
+4. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_lcm}
+\end{figure}
+\textbf{Algorithm mp\_lcm.}
+This algorithm computes the least common multiple of two mp\_int inputs $a$ and $b$. It computes the least common multiple directly by
+dividing the product of the two inputs by their greatest common divisor.
+
+EXAM,bn_mp_lcm.c
+
+\section{Jacobi Symbol Computation}
+To explain the Jacobi Symbol we shall first discuss the Legendre function\footnote{Arrg. What is the name of this?} off which the Jacobi symbol is
+defined. The Legendre function computes whether or not an integer $a$ is a quadratic residue modulo an odd prime $p$. Numerically it is
+equivalent to equation \ref{eqn:legendre}.
+
+\textit{-- Tom, don't be an ass, cite your source here...!}
+
+\begin{equation}
+a^{(p-1)/2} \equiv \begin{array}{rl}
+ -1 & \mbox{if }a\mbox{ is a quadratic non-residue.} \\
+ 0 & \mbox{if }a\mbox{ divides }p\mbox{.} \\
+ 1 & \mbox{if }a\mbox{ is a quadratic residue}.
+ \end{array} \mbox{ (mod }p\mbox{)}
+\label{eqn:legendre}
+\end{equation}
+
+\textbf{Proof.} \textit{Equation \ref{eqn:legendre} correctly identifies the residue status of an integer $a$ modulo a prime $p$.}
+An integer $a$ is a quadratic residue if the following equation has a solution.
+
+\begin{equation}
+x^2 \equiv a \mbox{ (mod }p\mbox{)}
+\label{eqn:root}
+\end{equation}
+
+Consider the following equation.
+
+\begin{equation}
+0 \equiv x^{p-1} - 1 \equiv \left \lbrace \left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \right \rbrace + \left ( a^{(p-1)/2} - 1 \right ) \mbox{ (mod }p\mbox{)}
+\label{eqn:rooti}
+\end{equation}
+
+Whether equation \ref{eqn:root} has a solution or not equation \ref{eqn:rooti} is always true. If $a^{(p-1)/2} - 1 \equiv 0 \mbox{ (mod }p\mbox{)}$
+then the quantity in the braces must be zero. By reduction,
+
+\begin{eqnarray}
+\left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \equiv 0 \nonumber \\
+\left (x^2 \right )^{(p-1)/2} \equiv a^{(p-1)/2} \nonumber \\
+x^2 \equiv a \mbox{ (mod }p\mbox{)}
+\end{eqnarray}
+
+As a result there must be a solution to the quadratic equation and in turn $a$ must be a quadratic residue. If $a$ does not divide $p$ and $a$
+is not a quadratic residue then the only other value $a^{(p-1)/2}$ may be congruent to is $-1$ since
+\begin{equation}
+0 \equiv a^{p - 1} - 1 \equiv (a^{(p-1)/2} + 1)(a^{(p-1)/2} - 1) \mbox{ (mod }p\mbox{)}
+\end{equation}
+One of the terms on the right hand side must be zero. \textbf{QED}
+
+\subsection{Jacobi Symbol}
+The Jacobi symbol is a generalization of the Legendre function for any odd non prime moduli $p$ greater than 2. If $p = \prod_{i=0}^n p_i$ then
+the Jacobi symbol $\left ( { a \over p } \right )$ is equal to the following equation.
+
+\begin{equation}
+\left ( { a \over p } \right ) = \left ( { a \over p_0} \right ) \left ( { a \over p_1} \right ) \ldots \left ( { a \over p_n} \right )
+\end{equation}
+
+By inspection if $p$ is prime the Jacobi symbol is equivalent to the Legendre function. The following facts\footnote{See HAC \cite[pp. 72-74]{HAC} for
+further details.} will be used to derive an efficient Jacobi symbol algorithm. Where $p$ is an odd integer greater than two and $a, b \in \Z$ the
+following are true.
+
+\begin{enumerate}
+\item $\left ( { a \over p} \right )$ equals $-1$, $0$ or $1$.
+\item $\left ( { ab \over p} \right ) = \left ( { a \over p} \right )\left ( { b \over p} \right )$.
+\item If $a \equiv b$ then $\left ( { a \over p} \right ) = \left ( { b \over p} \right )$.
+\item $\left ( { 2 \over p} \right )$ equals $1$ if $p \equiv 1$ or $7 \mbox{ (mod }8\mbox{)}$. Otherwise, it equals $-1$.
+\item $\left ( { a \over p} \right ) \equiv \left ( { p \over a} \right ) \cdot (-1)^{(p-1)(a-1)/4}$. More specifically
+$\left ( { a \over p} \right ) = \left ( { p \over a} \right )$ if $p \equiv a \equiv 1 \mbox{ (mod }4\mbox{)}$.
+\end{enumerate}
+
+Using these facts if $a = 2^k \cdot a'$ then
+
+\begin{eqnarray}
+\left ( { a \over p } \right ) = \left ( {{2^k} \over p } \right ) \left ( {a' \over p} \right ) \nonumber \\
+ = \left ( {2 \over p } \right )^k \left ( {a' \over p} \right )
+\label{eqn:jacobi}
+\end{eqnarray}
+
+By fact five,
+
+\begin{equation}
+\left ( { a \over p } \right ) = \left ( { p \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4}
+\end{equation}
+
+Subsequently by fact three since $p \equiv (p \mbox{ mod }a) \mbox{ (mod }a\mbox{)}$ then
+
+\begin{equation}
+\left ( { a \over p } \right ) = \left ( { {p \mbox{ mod } a} \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4}
+\end{equation}
+
+By putting both observations into equation \ref{eqn:jacobi} the following simplified equation is formed.
+
+\begin{equation}
+\left ( { a \over p } \right ) = \left ( {2 \over p } \right )^k \left ( {{p\mbox{ mod }a'} \over a'} \right ) \cdot (-1)^{(p-1)(a'-1)/4}
+\end{equation}
+
+The value of $\left ( {{p \mbox{ mod }a'} \over a'} \right )$ can be found by using the same equation recursively. The value of
+$\left ( {2 \over p } \right )^k$ equals $1$ if $k$ is even otherwise it equals $\left ( {2 \over p } \right )$. Using this approach the
+factors of $p$ do not have to be known. Furthermore, if $(a, p) = 1$ then the algorithm will terminate when the recursion requests the
+Jacobi symbol computation of $\left ( {1 \over a'} \right )$ which is simply $1$.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_jacobi}. \\
+\textbf{Input}. mp\_int $a$ and $p$, $a \ge 0$, $p \ge 3$, $p \equiv 1 \mbox{ (mod }2\mbox{)}$ \\
+\textbf{Output}. The Jacobi symbol $c = \left ( {a \over p } \right )$. \\
+\hline \\
+1. If $a = 0$ then \\
+\hspace{3mm}1.1 $c \leftarrow 0$ \\
+\hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\
+2. If $a = 1$ then \\
+\hspace{3mm}2.1 $c \leftarrow 1$ \\
+\hspace{3mm}2.2 Return(\textit{MP\_OKAY}). \\
+3. $a' \leftarrow a$ \\
+4. $k \leftarrow 0$ \\
+5. While $a'.used > 0$ and $a'_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
+\hspace{3mm}5.1 $k \leftarrow k + 1$ \\
+\hspace{3mm}5.2 $a' \leftarrow \lfloor a' / 2 \rfloor$ \\
+6. If $k \equiv 0 \mbox{ (mod }2\mbox{)}$ then \\
+\hspace{3mm}6.1 $s \leftarrow 1$ \\
+7. else \\
+\hspace{3mm}7.1 $r \leftarrow p_0 \mbox{ (mod }8\mbox{)}$ \\
+\hspace{3mm}7.2 If $r = 1$ or $r = 7$ then \\
+\hspace{6mm}7.2.1 $s \leftarrow 1$ \\
+\hspace{3mm}7.3 else \\
+\hspace{6mm}7.3.1 $s \leftarrow -1$ \\
+8. If $p_0 \equiv a'_0 \equiv 3 \mbox{ (mod }4\mbox{)}$ then \\
+\hspace{3mm}8.1 $s \leftarrow -s$ \\
+9. If $a' \ne 1$ then \\
+\hspace{3mm}9.1 $p' \leftarrow p \mbox{ (mod }a'\mbox{)}$ \\
+\hspace{3mm}9.2 $s \leftarrow s \cdot \mbox{mp\_jacobi}(p', a')$ \\
+10. $c \leftarrow s$ \\
+11. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_jacobi}
+\end{figure}
+\textbf{Algorithm mp\_jacobi.}
+This algorithm computes the Jacobi symbol for an arbitrary positive integer $a$ with respect to an odd integer $p$ greater than three. The algorithm
+is based on algorithm 2.149 of HAC \cite[pp. 73]{HAC}.
+
+Step numbers one and two handle the trivial cases of $a = 0$ and $a = 1$ respectively. Step five determines the number of two factors in the
+input $a$. If $k$ is even than the term $\left ( { 2 \over p } \right )^k$ must always evaluate to one. If $k$ is odd than the term evaluates to one
+if $p_0$ is congruent to one or seven modulo eight, otherwise it evaluates to $-1$. After the the $\left ( { 2 \over p } \right )^k$ term is handled
+the $(-1)^{(p-1)(a'-1)/4}$ is computed and multiplied against the current product $s$. The latter term evaluates to one if both $p$ and $a'$
+are congruent to one modulo four, otherwise it evaluates to negative one.
+
+By step nine if $a'$ does not equal one a recursion is required. Step 9.1 computes $p' \equiv p \mbox{ (mod }a'\mbox{)}$ and will recurse to compute
+$\left ( {p' \over a'} \right )$ which is multiplied against the current Jacobi product.
+
+EXAM,bn_mp_jacobi.c
+
+As a matter of practicality the variable $a'$ as per the pseudo-code is reprensented by the variable $a1$ since the $'$ symbol is not valid for a C
+variable name character.
+
+The two simple cases of $a = 0$ and $a = 1$ are handled at the very beginning to simplify the algorithm. If the input is non-trivial the algorithm
+has to proceed compute the Jacobi. The variable $s$ is used to hold the current Jacobi product. Note that $s$ is merely a C ``int'' data type since
+the values it may obtain are merely $-1$, $0$ and $1$.
+
+After a local copy of $a$ is made all of the factors of two are divided out and the total stored in $k$. Technically only the least significant
+bit of $k$ is required, however, it makes the algorithm simpler to follow to perform an addition. In practice an exclusive-or and addition have the same
+processor requirements and neither is faster than the other.
+
+Line @59, if@ through @70, }@ determines the value of $\left ( { 2 \over p } \right )^k$. If the least significant bit of $k$ is zero than
+$k$ is even and the value is one. Otherwise, the value of $s$ depends on which residue class $p$ belongs to modulo eight. The value of
+$(-1)^{(p-1)(a'-1)/4}$ is compute and multiplied against $s$ on lines @73, if@ through @75, }@.
+
+Finally, if $a1$ does not equal one the algorithm must recurse and compute $\left ( {p' \over a'} \right )$.
+
+\textit{-- Comment about default $s$ and such...}
+
+\section{Modular Inverse}
+\label{sec:modinv}
+The modular inverse of a number actually refers to the modular multiplicative inverse. Essentially for any integer $a$ such that $(a, p) = 1$ there
+exist another integer $b$ such that $ab \equiv 1 \mbox{ (mod }p\mbox{)}$. The integer $b$ is called the multiplicative inverse of $a$ which is
+denoted as $b = a^{-1}$. Technically speaking modular inversion is a well defined operation for any finite ring or field not just for rings and
+fields of integers. However, the former will be the matter of discussion.
+
+The simplest approach is to compute the algebraic inverse of the input. That is to compute $b \equiv a^{\Phi(p) - 1}$. If $\Phi(p)$ is the
+order of the multiplicative subgroup modulo $p$ then $b$ must be the multiplicative inverse of $a$. The proof of which is trivial.
+
+\begin{equation}
+ab \equiv a \left (a^{\Phi(p) - 1} \right ) \equiv a^{\Phi(p)} \equiv a^0 \equiv 1 \mbox{ (mod }p\mbox{)}
+\end{equation}
+
+However, as simple as this approach may be it has two serious flaws. It requires that the value of $\Phi(p)$ be known which if $p$ is composite
+requires all of the prime factors. This approach also is very slow as the size of $p$ grows.
+
+A simpler approach is based on the observation that solving for the multiplicative inverse is equivalent to solving the linear
+Diophantine\footnote{See LeVeque \cite[pp. 40-43]{LeVeque} for more information.} equation.
+
+\begin{equation}
+ab + pq = 1
+\end{equation}
+
+Where $a$, $b$, $p$ and $q$ are all integers. If such a pair of integers $ \left < b, q \right >$ exist than $b$ is the multiplicative inverse of
+$a$ modulo $p$. The extended Euclidean algorithm (Knuth \cite[pp. 342]{TAOCPV2}) can be used to solve such equations provided $(a, p) = 1$.
+However, instead of using that algorithm directly a variant known as the binary Extended Euclidean algorithm will be used in its place. The
+binary approach is very similar to the binary greatest common divisor algorithm except it will produce a full solution to the Diophantine
+equation.
+
+\subsection{General Case}
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_invmod}. \\
+\textbf{Input}. mp\_int $a$ and $b$, $(a, b) = 1$, $p \ge 2$, $0 < a < p$. \\
+\textbf{Output}. The modular inverse $c \equiv a^{-1} \mbox{ (mod }b\mbox{)}$. \\
+\hline \\
+1. If $b \le 0$ then return(\textit{MP\_VAL}). \\
+2. If $b_0 \equiv 1 \mbox{ (mod }2\mbox{)}$ then use algorithm fast\_mp\_invmod. \\
+3. $x \leftarrow \vert a \vert, y \leftarrow b$ \\
+4. If $x_0 \equiv y_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ then return(\textit{MP\_VAL}). \\
+5. $B \leftarrow 0, C \leftarrow 0, A \leftarrow 1, D \leftarrow 1$ \\
+6. While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
+\hspace{3mm}6.1 $u \leftarrow \lfloor u / 2 \rfloor$ \\
+\hspace{3mm}6.2 If ($A.used > 0$ and $A_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) or ($B.used > 0$ and $B_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) then \\
+\hspace{6mm}6.2.1 $A \leftarrow A + y$ \\
+\hspace{6mm}6.2.2 $B \leftarrow B - x$ \\
+\hspace{3mm}6.3 $A \leftarrow \lfloor A / 2 \rfloor$ \\
+\hspace{3mm}6.4 $B \leftarrow \lfloor B / 2 \rfloor$ \\
+7. While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
+\hspace{3mm}7.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\
+\hspace{3mm}7.2 If ($C.used > 0$ and $C_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) or ($D.used > 0$ and $D_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) then \\
+\hspace{6mm}7.2.1 $C \leftarrow C + y$ \\
+\hspace{6mm}7.2.2 $D \leftarrow D - x$ \\
+\hspace{3mm}7.3 $C \leftarrow \lfloor C / 2 \rfloor$ \\
+\hspace{3mm}7.4 $D \leftarrow \lfloor D / 2 \rfloor$ \\
+8. If $u \ge v$ then \\
+\hspace{3mm}8.1 $u \leftarrow u - v$ \\
+\hspace{3mm}8.2 $A \leftarrow A - C$ \\
+\hspace{3mm}8.3 $B \leftarrow B - D$ \\
+9. else \\
+\hspace{3mm}9.1 $v \leftarrow v - u$ \\
+\hspace{3mm}9.2 $C \leftarrow C - A$ \\
+\hspace{3mm}9.3 $D \leftarrow D - B$ \\
+10. If $u \ne 0$ goto step 6. \\
+11. If $v \ne 1$ return(\textit{MP\_VAL}). \\
+12. While $C \le 0$ do \\
+\hspace{3mm}12.1 $C \leftarrow C + b$ \\
+13. While $C \ge b$ do \\
+\hspace{3mm}13.1 $C \leftarrow C - b$ \\
+14. $c \leftarrow C$ \\
+15. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\end{figure}
+\textbf{Algorithm mp\_invmod.}
+This algorithm computes the modular multiplicative inverse of an integer $a$ modulo an integer $b$. This algorithm is a variation of the
+extended binary Euclidean algorithm from HAC \cite[pp. 608]{HAC}. It has been modified to only compute the modular inverse and not a complete
+Diophantine solution.
+
+If $b \le 0$ than the modulus is invalid and MP\_VAL is returned. Similarly if both $a$ and $b$ are even then there cannot be a multiplicative
+inverse for $a$ and the error is reported.
+
+The astute reader will observe that steps seven through nine are very similar to the binary greatest common divisor algorithm mp\_gcd. In this case
+the other variables to the Diophantine equation are solved. The algorithm terminates when $u = 0$ in which case the solution is
+
+\begin{equation}
+Ca + Db = v
+\end{equation}
+
+If $v$, the greatest common divisor of $a$ and $b$ is not equal to one then the algorithm will report an error as no inverse exists. Otherwise, $C$
+is the modular inverse of $a$. The actual value of $C$ is congruent to, but not necessarily equal to, the ideal modular inverse which should lie
+within $1 \le a^{-1} < b$. Step numbers twelve and thirteen adjust the inverse until it is in range. If the original input $a$ is within $0 < a < p$
+then only a couple of additions or subtractions will be required to adjust the inverse.
+
+EXAM,bn_mp_invmod.c
+
+\subsubsection{Odd Moduli}
+
+When the modulus $b$ is odd the variables $A$ and $C$ are fixed and are not required to compute the inverse. In particular by attempting to solve
+the Diophantine $Cb + Da = 1$ only $B$ and $D$ are required to find the inverse of $a$.
+
+The algorithm fast\_mp\_invmod is a direct adaptation of algorithm mp\_invmod with all all steps involving either $A$ or $C$ removed. This
+optimization will halve the time required to compute the modular inverse.
+
+\section{Primality Tests}
+
+A non-zero integer $a$ is said to be prime if it is not divisible by any other integer excluding one and itself. For example, $a = 7$ is prime
+since the integers $2 \ldots 6$ do not evenly divide $a$. By contrast, $a = 6$ is not prime since $a = 6 = 2 \cdot 3$.
+
+Prime numbers arise in cryptography considerably as they allow finite fields to be formed. The ability to determine whether an integer is prime or
+not quickly has been a viable subject in cryptography and number theory for considerable time. The algorithms that will be presented are all
+probablistic algorithms in that when they report an integer is composite it must be composite. However, when the algorithms report an integer is
+prime the algorithm may be incorrect.
+
+As will be discussed it is possible to limit the probability of error so well that for practical purposes the probablity of error might as
+well be zero. For the purposes of these discussions let $n$ represent the candidate integer of which the primality is in question.
+
+\subsection{Trial Division}
+
+Trial division means to attempt to evenly divide a candidate integer by small prime integers. If the candidate can be evenly divided it obviously
+cannot be prime. By dividing by all primes $1 < p \le \sqrt{n}$ this test can actually prove whether an integer is prime. However, such a test
+would require a prohibitive amount of time as $n$ grows.
+
+Instead of dividing by every prime, a smaller, more mangeable set of primes may be used instead. By performing trial division with only a subset
+of the primes less than $\sqrt{n} + 1$ the algorithm cannot prove if a candidate is prime. However, often it can prove a candidate is not prime.
+
+The benefit of this test is that trial division by small values is fairly efficient. Specially compared to the other algorithms that will be
+discussed shortly. The probability that this approach correctly identifies a composite candidate when tested with all primes upto $q$ is given by
+$1 - {1.12 \over ln(q)}$. The graph (\ref{pic:primality}, will be added later) demonstrates the probability of success for the range
+$3 \le q \le 100$.
+
+At approximately $q = 30$ the gain of performing further tests diminishes fairly quickly. At $q = 90$ further testing is generally not going to
+be of any practical use. In the case of LibTomMath the default limit $q = 256$ was chosen since it is not too high and will eliminate
+approximately $80\%$ of all candidate integers. The constant \textbf{PRIME\_SIZE} is equal to the number of primes in the test base. The
+array \_\_prime\_tab is an array of the first \textbf{PRIME\_SIZE} prime numbers.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_prime\_is\_divisible}. \\
+\textbf{Input}. mp\_int $a$ \\
+\textbf{Output}. $c = 1$ if $n$ is divisible by a small prime, otherwise $c = 0$. \\
+\hline \\
+1. for $ix$ from $0$ to $PRIME\_SIZE$ do \\
+\hspace{3mm}1.1 $d \leftarrow n \mbox{ (mod }\_\_prime\_tab_{ix}\mbox{)}$ \\
+\hspace{3mm}1.2 If $d = 0$ then \\
+\hspace{6mm}1.2.1 $c \leftarrow 1$ \\
+\hspace{6mm}1.2.2 Return(\textit{MP\_OKAY}). \\
+2. $c \leftarrow 0$ \\
+3. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_prime\_is\_divisible}
+\end{figure}
+\textbf{Algorithm mp\_prime\_is\_divisible.}
+This algorithm attempts to determine if a candidate integer $n$ is composite by performing trial divisions.
+
+EXAM,bn_mp_prime_is_divisible.c
+
+The algorithm defaults to a return of $0$ in case an error occurs. The values in the prime table are all specified to be in the range of a
+mp\_digit. The table \_\_prime\_tab is defined in the following file.
+
+EXAM,bn_prime_tab.c
+
+Note that there are two possible tables. When an mp\_digit is 7-bits long only the primes upto $127$ may be included, otherwise the primes
+upto $1619$ are used. Note that the value of \textbf{PRIME\_SIZE} is a constant dependent on the size of a mp\_digit.
+
+\subsection{The Fermat Test}
+The Fermat test is probably one the oldest tests to have a non-trivial probability of success. It is based on the fact that if $n$ is in
+fact prime then $a^{n} \equiv a \mbox{ (mod }n\mbox{)}$ for all $0 < a < n$. The reason being that if $n$ is prime than the order of
+the multiplicative sub group is $n - 1$. Any base $a$ must have an order which divides $n - 1$ and as such $a^n$ is equivalent to
+$a^1 = a$.
+
+If $n$ is composite then any given base $a$ does not have to have a period which divides $n - 1$. In which case
+it is possible that $a^n \nequiv a \mbox{ (mod }n\mbox{)}$. However, this test is not absolute as it is possible that the order
+of a base will divide $n - 1$ which would then be reported as prime. Such a base yields what is known as a Fermat pseudo-prime. Several
+integers known as Carmichael numbers will be a pseudo-prime to all valid bases. Fortunately such numbers are extremely rare as $n$ grows
+in size.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_prime\_fermat}. \\
+\textbf{Input}. mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$. \\
+\textbf{Output}. $c = 1$ if $b^a \equiv b \mbox{ (mod }a\mbox{)}$, otherwise $c = 0$. \\
+\hline \\
+1. $t \leftarrow b^a \mbox{ (mod }a\mbox{)}$ \\
+2. If $t = b$ then \\
+\hspace{3mm}2.1 $c = 1$ \\
+3. else \\
+\hspace{3mm}3.1 $c = 0$ \\
+4. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_prime\_fermat}
+\end{figure}
+\textbf{Algorithm mp\_prime\_fermat.}
+This algorithm determines whether an mp\_int $a$ is a Fermat prime to the base $b$ or not. It uses a single modular exponentiation to
+determine the result.
+
+EXAM,bn_mp_prime_fermat.c
+
+\subsection{The Miller-Rabin Test}
+The Miller-Rabin (citation) test is another primality test which has tighter error bounds than the Fermat test specifically with sequentially chosen
+candidate integers. The algorithm is based on the observation that if $n - 1 = 2^kr$ and if $b^r \nequiv \pm 1$ then after upto $k - 1$ squarings the
+value must be equal to $-1$. The squarings are stopped as soon as $-1$ is observed. If the value of $1$ is observed first it means that
+some value not congruent to $\pm 1$ when squared equals one which cannot occur if $n$ is prime.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_prime\_miller\_rabin}. \\
+\textbf{Input}. mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$. \\
+\textbf{Output}. $c = 1$ if $a$ is a Miller-Rabin prime to the base $a$, otherwise $c = 0$. \\
+\hline
+1. $a' \leftarrow a - 1$ \\
+2. $r \leftarrow n1$ \\
+3. $c \leftarrow 0, s \leftarrow 0$ \\
+4. While $r.used > 0$ and $r_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
+\hspace{3mm}4.1 $s \leftarrow s + 1$ \\
+\hspace{3mm}4.2 $r \leftarrow \lfloor r / 2 \rfloor$ \\
+5. $y \leftarrow b^r \mbox{ (mod }a\mbox{)}$ \\
+6. If $y \nequiv \pm 1$ then \\
+\hspace{3mm}6.1 $j \leftarrow 1$ \\
+\hspace{3mm}6.2 While $j \le (s - 1)$ and $y \nequiv a'$ \\
+\hspace{6mm}6.2.1 $y \leftarrow y^2 \mbox{ (mod }a\mbox{)}$ \\
+\hspace{6mm}6.2.2 If $y = 1$ then goto step 8. \\
+\hspace{6mm}6.2.3 $j \leftarrow j + 1$ \\
+\hspace{3mm}6.3 If $y \nequiv a'$ goto step 8. \\
+7. $c \leftarrow 1$\\
+8. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_prime\_miller\_rabin}
+\end{figure}
+\textbf{Algorithm mp\_prime\_miller\_rabin.}
+This algorithm performs one trial round of the Miller-Rabin algorithm to the base $b$. It will set $c = 1$ if the algorithm cannot determine
+if $b$ is composite or $c = 0$ if $b$ is provably composite. The values of $s$ and $r$ are computed such that $a' = a - 1 = 2^sr$.
+
+If the value $y \equiv b^r$ is congruent to $\pm 1$ then the algorithm cannot prove if $a$ is composite or not. Otherwise, the algorithm will
+square $y$ upto $s - 1$ times stopping only when $y \equiv -1$. If $y^2 \equiv 1$ and $y \nequiv \pm 1$ then the algorithm can report that $a$
+is provably composite. If the algorithm performs $s - 1$ squarings and $y \nequiv -1$ then $a$ is provably composite. If $a$ is not provably
+composite then it is \textit{probably} prime.
+
+EXAM,bn_mp_prime_miller_rabin.c
+
+
+
+
+\backmatter
+\appendix
+\begin{thebibliography}{ABCDEF}
+\bibitem[1]{TAOCPV2}
+Donald Knuth, \textit{The Art of Computer Programming}, Third Edition, Volume Two, Seminumerical Algorithms, Addison-Wesley, 1998
+
+\bibitem[2]{HAC}
+A. Menezes, P. van Oorschot, S. Vanstone, \textit{Handbook of Applied Cryptography}, CRC Press, 1996
+
+\bibitem[3]{ROSE}
+Michael Rosing, \textit{Implementing Elliptic Curve Cryptography}, Manning Publications, 1999
+
+\bibitem[4]{COMBA}
+Paul G. Comba, \textit{Exponentiation Cryptosystems on the IBM PC}. IBM Systems Journal 29(4): 526-538 (1990)
+
+\bibitem[5]{KARA}
+A. Karatsuba, Doklay Akad. Nauk SSSR 145 (1962), pp.293-294
+
+\bibitem[6]{KARAP}
+Andre Weimerskirch and Christof Paar, \textit{Generalizations of the Karatsuba Algorithm for Polynomial Multiplication}, Submitted to Design, Codes and Cryptography, March 2002
+
+\bibitem[7]{BARRETT}
+Paul Barrett, \textit{Implementing the Rivest Shamir and Adleman Public Key Encryption Algorithm on a Standard Digital Signal Processor}, Advances in Cryptology, Crypto '86, Springer-Verlag.
+
+\bibitem[8]{MONT}
+P.L.Montgomery. \textit{Modular multiplication without trial division}. Mathematics of Computation, 44(170):519-521, April 1985.
+
+\bibitem[9]{DRMET}
+Chae Hoon Lim and Pil Joong Lee, \textit{Generating Efficient Primes for Discrete Log Cryptosystems}, POSTECH Information Research Laboratories
+
+\bibitem[10]{MMB}
+J. Daemen and R. Govaerts and J. Vandewalle, \textit{Block ciphers based on Modular Arithmetic}, State and {P}rogress in the {R}esearch of {C}ryptography, 1993, pp. 80-89
+
+\bibitem[11]{RSAREF}
+R.L. Rivest, A. Shamir, L. Adleman, \textit{A Method for Obtaining Digital Signatures and Public-Key Cryptosystems}
+
+\bibitem[12]{DHREF}
+Whitfield Diffie, Martin E. Hellman, \textit{New Directions in Cryptography}, IEEE Transactions on Information Theory, 1976
+
+\bibitem[13]{IEEE}
+IEEE Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Std 754-1985)
+
+\bibitem[14]{GMP}
+GNU Multiple Precision (GMP), \url{http://www.swox.com/gmp/}
+
+\bibitem[15]{MPI}
+Multiple Precision Integer Library (MPI), Michael Fromberger, \url{http://thayer.dartmouth.edu/~sting/mpi/}
+
+\bibitem[16]{OPENSSL}
+OpenSSL Cryptographic Toolkit, \url{http://openssl.org}
+
+\bibitem[17]{LIP}
+Large Integer Package, \url{http://home.hetnet.nl/~ecstr/LIP.zip}
+
+\bibitem[18]{ISOC}
+JTC1/SC22/WG14, ISO/IEC 9899:1999, ``A draft rationale for the C99 standard.''
+
+\bibitem[19]{JAVA}
+The Sun Java Website, \url{http://java.sun.com/}
+
+\end{thebibliography}
+
+\input{tommath.ind}
+
+\end{document}
diff --git a/libtommath/tommath.tex b/libtommath/tommath.tex
new file mode 100644
index 0000000..c79a537
--- /dev/null
+++ b/libtommath/tommath.tex
@@ -0,0 +1,6691 @@
+\documentclass[b5paper]{book}
+\usepackage{hyperref}
+\usepackage{makeidx}
+\usepackage{amssymb}
+\usepackage{color}
+\usepackage{alltt}
+\usepackage{graphicx}
+\usepackage{layout}
+\def\union{\cup}
+\def\intersect{\cap}
+\def\getsrandom{\stackrel{\rm R}{\gets}}
+\def\cross{\times}
+\def\cat{\hspace{0.5em} \| \hspace{0.5em}}
+\def\catn{$\|$}
+\def\divides{\hspace{0.3em} | \hspace{0.3em}}
+\def\nequiv{\not\equiv}
+\def\approx{\raisebox{0.2ex}{\mbox{\small $\sim$}}}
+\def\lcm{{\rm lcm}}
+\def\gcd{{\rm gcd}}
+\def\log{{\rm log}}
+\def\ord{{\rm ord}}
+\def\abs{{\mathit abs}}
+\def\rep{{\mathit rep}}
+\def\mod{{\mathit\ mod\ }}
+\renewcommand{\pmod}[1]{\ ({\rm mod\ }{#1})}
+\newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor}
+\newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil}
+\def\Or{{\rm\ or\ }}
+\def\And{{\rm\ and\ }}
+\def\iff{\hspace{1em}\Longleftrightarrow\hspace{1em}}
+\def\implies{\Rightarrow}
+\def\undefined{{\rm ``undefined"}}
+\def\Proof{\vspace{1ex}\noindent {\bf Proof:}\hspace{1em}}
+\let\oldphi\phi
+\def\phi{\varphi}
+\def\Pr{{\rm Pr}}
+\newcommand{\str}[1]{{\mathbf{#1}}}
+\def\F{{\mathbb F}}
+\def\N{{\mathbb N}}
+\def\Z{{\mathbb Z}}
+\def\R{{\mathbb R}}
+\def\C{{\mathbb C}}
+\def\Q{{\mathbb Q}}
+\definecolor{DGray}{gray}{0.5}
+\newcommand{\emailaddr}[1]{\mbox{$<${#1}$>$}}
+\def\twiddle{\raisebox{0.3ex}{\mbox{\tiny $\sim$}}}
+\def\gap{\vspace{0.5ex}}
+\makeindex
+\begin{document}
+\frontmatter
+\pagestyle{empty}
+\title{Multi--Precision Math}
+\author{\mbox{
+%\begin{small}
+\begin{tabular}{c}
+Tom St Denis \\
+Algonquin College \\
+\\
+Mads Rasmussen \\
+Open Communications Security \\
+\\
+Greg Rose \\
+QUALCOMM Australia \\
+\end{tabular}
+%\end{small}
+}
+}
+\maketitle
+This text has been placed in the public domain. This text corresponds to the v0.39 release of the
+LibTomMath project.
+
+\begin{alltt}
+Tom St Denis
+111 Banning Rd
+Ottawa, Ontario
+K2L 1C3
+Canada
+
+Phone: 1-613-836-3160
+Email: tomstdenis@gmail.com
+\end{alltt}
+
+This text is formatted to the international B5 paper size of 176mm wide by 250mm tall using the \LaTeX{}
+{\em book} macro package and the Perl {\em booker} package.
+
+\tableofcontents
+\listoffigures
+\chapter*{Prefaces}
+When I tell people about my LibTom projects and that I release them as public domain they are often puzzled.
+They ask why I did it and especially why I continue to work on them for free. The best I can explain it is ``Because I can.''
+Which seems odd and perhaps too terse for adult conversation. I often qualify it with ``I am able, I am willing.'' which
+perhaps explains it better. I am the first to admit there is not anything that special with what I have done. Perhaps
+others can see that too and then we would have a society to be proud of. My LibTom projects are what I am doing to give
+back to society in the form of tools and knowledge that can help others in their endeavours.
+
+I started writing this book because it was the most logical task to further my goal of open academia. The LibTomMath source
+code itself was written to be easy to follow and learn from. There are times, however, where pure C source code does not
+explain the algorithms properly. Hence this book. The book literally starts with the foundation of the library and works
+itself outwards to the more complicated algorithms. The use of both pseudo--code and verbatim source code provides a duality
+of ``theory'' and ``practice'' that the computer science students of the world shall appreciate. I never deviate too far
+from relatively straightforward algebra and I hope that this book can be a valuable learning asset.
+
+This book and indeed much of the LibTom projects would not exist in their current form if it was not for a plethora
+of kind people donating their time, resources and kind words to help support my work. Writing a text of significant
+length (along with the source code) is a tiresome and lengthy process. Currently the LibTom project is four years old,
+comprises of literally thousands of users and over 100,000 lines of source code, TeX and other material. People like Mads and Greg
+were there at the beginning to encourage me to work well. It is amazing how timely validation from others can boost morale to
+continue the project. Definitely my parents were there for me by providing room and board during the many months of work in 2003.
+
+To my many friends whom I have met through the years I thank you for the good times and the words of encouragement. I hope I
+honour your kind gestures with this project.
+
+Open Source. Open Academia. Open Minds.
+
+\begin{flushright} Tom St Denis \end{flushright}
+
+\newpage
+I found the opportunity to work with Tom appealing for several reasons, not only could I broaden my own horizons, but also
+contribute to educate others facing the problem of having to handle big number mathematical calculations.
+
+This book is Tom's child and he has been caring and fostering the project ever since the beginning with a clear mind of
+how he wanted the project to turn out. I have helped by proofreading the text and we have had several discussions about
+the layout and language used.
+
+I hold a masters degree in cryptography from the University of Southern Denmark and have always been interested in the
+practical aspects of cryptography.
+
+Having worked in the security consultancy business for several years in S\~{a}o Paulo, Brazil, I have been in touch with a
+great deal of work in which multiple precision mathematics was needed. Understanding the possibilities for speeding up
+multiple precision calculations is often very important since we deal with outdated machine architecture where modular
+reductions, for example, become painfully slow.
+
+This text is for people who stop and wonder when first examining algorithms such as RSA for the first time and asks
+themselves, ``You tell me this is only secure for large numbers, fine; but how do you implement these numbers?''
+
+\begin{flushright}
+Mads Rasmussen
+
+S\~{a}o Paulo - SP
+
+Brazil
+\end{flushright}
+
+\newpage
+It's all because I broke my leg. That just happened to be at about the same time that Tom asked for someone to review the section of the book about
+Karatsuba multiplication. I was laid up, alone and immobile, and thought ``Why not?'' I vaguely knew what Karatsuba multiplication was, but not
+really, so I thought I could help, learn, and stop myself from watching daytime cable TV, all at once.
+
+At the time of writing this, I've still not met Tom or Mads in meatspace. I've been following Tom's progress since his first splash on the
+sci.crypt Usenet news group. I watched him go from a clueless newbie, to the cryptographic equivalent of a reformed smoker, to a real
+contributor to the field, over a period of about two years. I've been impressed with his obvious intelligence, and astounded by his productivity.
+Of course, he's young enough to be my own child, so he doesn't have my problems with staying awake.
+
+When I reviewed that single section of the book, in its very earliest form, I was very pleasantly surprised. So I decided to collaborate more fully,
+and at least review all of it, and perhaps write some bits too. There's still a long way to go with it, and I have watched a number of close
+friends go through the mill of publication, so I think that the way to go is longer than Tom thinks it is. Nevertheless, it's a good effort,
+and I'm pleased to be involved with it.
+
+\begin{flushright}
+Greg Rose, Sydney, Australia, June 2003.
+\end{flushright}
+
+\mainmatter
+\pagestyle{headings}
+\chapter{Introduction}
+\section{Multiple Precision Arithmetic}
+
+\subsection{What is Multiple Precision Arithmetic?}
+When we think of long-hand arithmetic such as addition or multiplication we rarely consider the fact that we instinctively
+raise or lower the precision of the numbers we are dealing with. For example, in decimal we almost immediate can
+reason that $7$ times $6$ is $42$. However, $42$ has two digits of precision as opposed to one digit we started with.
+Further multiplications of say $3$ result in a larger precision result $126$. In these few examples we have multiple
+precisions for the numbers we are working with. Despite the various levels of precision a single subset\footnote{With the occasional optimization.}
+ of algorithms can be designed to accomodate them.
+
+By way of comparison a fixed or single precision operation would lose precision on various operations. For example, in
+the decimal system with fixed precision $6 \cdot 7 = 2$.
+
+Essentially at the heart of computer based multiple precision arithmetic are the same long-hand algorithms taught in
+schools to manually add, subtract, multiply and divide.
+
+\subsection{The Need for Multiple Precision Arithmetic}
+The most prevalent need for multiple precision arithmetic, often referred to as ``bignum'' math, is within the implementation
+of public-key cryptography algorithms. Algorithms such as RSA \cite{RSAREF} and Diffie-Hellman \cite{DHREF} require
+integers of significant magnitude to resist known cryptanalytic attacks. For example, at the time of this writing a
+typical RSA modulus would be at least greater than $10^{309}$. However, modern programming languages such as ISO C \cite{ISOC} and
+Java \cite{JAVA} only provide instrinsic support for integers which are relatively small and single precision.
+
+\begin{figure}[!here]
+\begin{center}
+\begin{tabular}{|r|c|}
+\hline \textbf{Data Type} & \textbf{Range} \\
+\hline char & $-128 \ldots 127$ \\
+\hline short & $-32768 \ldots 32767$ \\
+\hline long & $-2147483648 \ldots 2147483647$ \\
+\hline long long & $-9223372036854775808 \ldots 9223372036854775807$ \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Typical Data Types for the C Programming Language}
+\label{fig:ISOC}
+\end{figure}
+
+The largest data type guaranteed to be provided by the ISO C programming
+language\footnote{As per the ISO C standard. However, each compiler vendor is allowed to augment the precision as they
+see fit.} can only represent values up to $10^{19}$ as shown in figure \ref{fig:ISOC}. On its own the C language is
+insufficient to accomodate the magnitude required for the problem at hand. An RSA modulus of magnitude $10^{19}$ could be
+trivially factored\footnote{A Pollard-Rho factoring would take only $2^{16}$ time.} on the average desktop computer,
+rendering any protocol based on the algorithm insecure. Multiple precision algorithms solve this very problem by
+extending the range of representable integers while using single precision data types.
+
+Most advancements in fast multiple precision arithmetic stem from the need for faster and more efficient cryptographic
+primitives. Faster modular reduction and exponentiation algorithms such as Barrett's algorithm, which have appeared in
+various cryptographic journals, can render algorithms such as RSA and Diffie-Hellman more efficient. In fact, several
+major companies such as RSA Security, Certicom and Entrust have built entire product lines on the implementation and
+deployment of efficient algorithms.
+
+However, cryptography is not the only field of study that can benefit from fast multiple precision integer routines.
+Another auxiliary use of multiple precision integers is high precision floating point data types.
+The basic IEEE \cite{IEEE} standard floating point type is made up of an integer mantissa $q$, an exponent $e$ and a sign bit $s$.
+Numbers are given in the form $n = q \cdot b^e \cdot -1^s$ where $b = 2$ is the most common base for IEEE. Since IEEE
+floating point is meant to be implemented in hardware the precision of the mantissa is often fairly small
+(\textit{23, 48 and 64 bits}). The mantissa is merely an integer and a multiple precision integer could be used to create
+a mantissa of much larger precision than hardware alone can efficiently support. This approach could be useful where
+scientific applications must minimize the total output error over long calculations.
+
+Yet another use for large integers is within arithmetic on polynomials of large characteristic (i.e. $GF(p)[x]$ for large $p$).
+In fact the library discussed within this text has already been used to form a polynomial basis library\footnote{See \url{http://poly.libtomcrypt.org} for more details.}.
+
+\subsection{Benefits of Multiple Precision Arithmetic}
+\index{precision}
+The benefit of multiple precision representations over single or fixed precision representations is that
+no precision is lost while representing the result of an operation which requires excess precision. For example,
+the product of two $n$-bit integers requires at least $2n$ bits of precision to be represented faithfully. A multiple
+precision algorithm would augment the precision of the destination to accomodate the result while a single precision system
+would truncate excess bits to maintain a fixed level of precision.
+
+It is possible to implement algorithms which require large integers with fixed precision algorithms. For example, elliptic
+curve cryptography (\textit{ECC}) is often implemented on smartcards by fixing the precision of the integers to the maximum
+size the system will ever need. Such an approach can lead to vastly simpler algorithms which can accomodate the
+integers required even if the host platform cannot natively accomodate them\footnote{For example, the average smartcard
+processor has an 8 bit accumulator.}. However, as efficient as such an approach may be, the resulting source code is not
+normally very flexible. It cannot, at runtime, accomodate inputs of higher magnitude than the designer anticipated.
+
+Multiple precision algorithms have the most overhead of any style of arithmetic. For the the most part the
+overhead can be kept to a minimum with careful planning, but overall, it is not well suited for most memory starved
+platforms. However, multiple precision algorithms do offer the most flexibility in terms of the magnitude of the
+inputs. That is, the same algorithms based on multiple precision integers can accomodate any reasonable size input
+without the designer's explicit forethought. This leads to lower cost of ownership for the code as it only has to
+be written and tested once.
+
+\section{Purpose of This Text}
+The purpose of this text is to instruct the reader regarding how to implement efficient multiple precision algorithms.
+That is to not only explain a limited subset of the core theory behind the algorithms but also the various ``house keeping''
+elements that are neglected by authors of other texts on the subject. Several well reknowned texts \cite{TAOCPV2,HAC}
+give considerably detailed explanations of the theoretical aspects of algorithms and often very little information
+regarding the practical implementation aspects.
+
+In most cases how an algorithm is explained and how it is actually implemented are two very different concepts. For
+example, the Handbook of Applied Cryptography (\textit{HAC}), algorithm 14.7 on page 594, gives a relatively simple
+algorithm for performing multiple precision integer addition. However, the description lacks any discussion concerning
+the fact that the two integer inputs may be of differing magnitudes. As a result the implementation is not as simple
+as the text would lead people to believe. Similarly the division routine (\textit{algorithm 14.20, pp. 598}) does not
+discuss how to handle sign or handle the dividend's decreasing magnitude in the main loop (\textit{step \#3}).
+
+Both texts also do not discuss several key optimal algorithms required such as ``Comba'' and Karatsuba multipliers
+and fast modular inversion, which we consider practical oversights. These optimal algorithms are vital to achieve
+any form of useful performance in non-trivial applications.
+
+To solve this problem the focus of this text is on the practical aspects of implementing a multiple precision integer
+package. As a case study the ``LibTomMath''\footnote{Available at \url{http://math.libtomcrypt.com}} package is used
+to demonstrate algorithms with real implementations\footnote{In the ISO C programming language.} that have been field
+tested and work very well. The LibTomMath library is freely available on the Internet for all uses and this text
+discusses a very large portion of the inner workings of the library.
+
+The algorithms that are presented will always include at least one ``pseudo-code'' description followed
+by the actual C source code that implements the algorithm. The pseudo-code can be used to implement the same
+algorithm in other programming languages as the reader sees fit.
+
+This text shall also serve as a walkthrough of the creation of multiple precision algorithms from scratch. Showing
+the reader how the algorithms fit together as well as where to start on various taskings.
+
+\section{Discussion and Notation}
+\subsection{Notation}
+A multiple precision integer of $n$-digits shall be denoted as $x = (x_{n-1}, \ldots, x_1, x_0)_{ \beta }$ and represent
+the integer $x \equiv \sum_{i=0}^{n-1} x_i\beta^i$. The elements of the array $x$ are said to be the radix $\beta$ digits
+of the integer. For example, $x = (1,2,3)_{10}$ would represent the integer
+$1\cdot 10^2 + 2\cdot10^1 + 3\cdot10^0 = 123$.
+
+\index{mp\_int}
+The term ``mp\_int'' shall refer to a composite structure which contains the digits of the integer it represents, as well
+as auxilary data required to manipulate the data. These additional members are discussed further in section
+\ref{sec:MPINT}. For the purposes of this text a ``multiple precision integer'' and an ``mp\_int'' are assumed to be
+synonymous. When an algorithm is specified to accept an mp\_int variable it is assumed the various auxliary data members
+are present as well. An expression of the type \textit{variablename.item} implies that it should evaluate to the
+member named ``item'' of the variable. For example, a string of characters may have a member ``length'' which would
+evaluate to the number of characters in the string. If the string $a$ equals ``hello'' then it follows that
+$a.length = 5$.
+
+For certain discussions more generic algorithms are presented to help the reader understand the final algorithm used
+to solve a given problem. When an algorithm is described as accepting an integer input it is assumed the input is
+a plain integer with no additional multiple-precision members. That is, algorithms that use integers as opposed to
+mp\_ints as inputs do not concern themselves with the housekeeping operations required such as memory management. These
+algorithms will be used to establish the relevant theory which will subsequently be used to describe a multiple
+precision algorithm to solve the same problem.
+
+\subsection{Precision Notation}
+The variable $\beta$ represents the radix of a single digit of a multiple precision integer and
+must be of the form $q^p$ for $q, p \in \Z^+$. A single precision variable must be able to represent integers in
+the range $0 \le x < q \beta$ while a double precision variable must be able to represent integers in the range
+$0 \le x < q \beta^2$. The extra radix-$q$ factor allows additions and subtractions to proceed without truncation of the
+carry. Since all modern computers are binary, it is assumed that $q$ is two.
+
+\index{mp\_digit} \index{mp\_word}
+Within the source code that will be presented for each algorithm, the data type \textbf{mp\_digit} will represent
+a single precision integer type, while, the data type \textbf{mp\_word} will represent a double precision integer type. In
+several algorithms (notably the Comba routines) temporary results will be stored in arrays of double precision mp\_words.
+For the purposes of this text $x_j$ will refer to the $j$'th digit of a single precision array and $\hat x_j$ will refer to
+the $j$'th digit of a double precision array. Whenever an expression is to be assigned to a double precision
+variable it is assumed that all single precision variables are promoted to double precision during the evaluation.
+Expressions that are assigned to a single precision variable are truncated to fit within the precision of a single
+precision data type.
+
+For example, if $\beta = 10^2$ a single precision data type may represent a value in the
+range $0 \le x < 10^3$, while a double precision data type may represent a value in the range $0 \le x < 10^5$. Let
+$a = 23$ and $b = 49$ represent two single precision variables. The single precision product shall be written
+as $c \leftarrow a \cdot b$ while the double precision product shall be written as $\hat c \leftarrow a \cdot b$.
+In this particular case, $\hat c = 1127$ and $c = 127$. The most significant digit of the product would not fit
+in a single precision data type and as a result $c \ne \hat c$.
+
+\subsection{Algorithm Inputs and Outputs}
+Within the algorithm descriptions all variables are assumed to be scalars of either single or double precision
+as indicated. The only exception to this rule is when variables have been indicated to be of type mp\_int. This
+distinction is important as scalars are often used as array indicies and various other counters.
+
+\subsection{Mathematical Expressions}
+The $\lfloor \mbox{ } \rfloor$ brackets imply an expression truncated to an integer not greater than the expression
+itself. For example, $\lfloor 5.7 \rfloor = 5$. Similarly the $\lceil \mbox{ } \rceil$ brackets imply an expression
+rounded to an integer not less than the expression itself. For example, $\lceil 5.1 \rceil = 6$. Typically when
+the $/$ division symbol is used the intention is to perform an integer division with truncation. For example,
+$5/2 = 2$ which will often be written as $\lfloor 5/2 \rfloor = 2$ for clarity. When an expression is written as a
+fraction a real value division is implied, for example ${5 \over 2} = 2.5$.
+
+The norm of a multiple precision integer, for example $\vert \vert x \vert \vert$, will be used to represent the number of digits in the representation
+of the integer. For example, $\vert \vert 123 \vert \vert = 3$ and $\vert \vert 79452 \vert \vert = 5$.
+
+\subsection{Work Effort}
+\index{big-Oh}
+To measure the efficiency of the specified algorithms, a modified big-Oh notation is used. In this system all
+single precision operations are considered to have the same cost\footnote{Except where explicitly noted.}.
+That is a single precision addition, multiplication and division are assumed to take the same time to
+complete. While this is generally not true in practice, it will simplify the discussions considerably.
+
+Some algorithms have slight advantages over others which is why some constants will not be removed in
+the notation. For example, a normal baseline multiplication (section \ref{sec:basemult}) requires $O(n^2)$ work while a
+baseline squaring (section \ref{sec:basesquare}) requires $O({{n^2 + n}\over 2})$ work. In standard big-Oh notation these
+would both be said to be equivalent to $O(n^2)$. However,
+in the context of the this text this is not the case as the magnitude of the inputs will typically be rather small. As a
+result small constant factors in the work effort will make an observable difference in algorithm efficiency.
+
+All of the algorithms presented in this text have a polynomial time work level. That is, of the form
+$O(n^k)$ for $n, k \in \Z^{+}$. This will help make useful comparisons in terms of the speed of the algorithms and how
+various optimizations will help pay off in the long run.
+
+\section{Exercises}
+Within the more advanced chapters a section will be set aside to give the reader some challenging exercises related to
+the discussion at hand. These exercises are not designed to be prize winning problems, but instead to be thought
+provoking. Wherever possible the problems are forward minded, stating problems that will be answered in subsequent
+chapters. The reader is encouraged to finish the exercises as they appear to get a better understanding of the
+subject material.
+
+That being said, the problems are designed to affirm knowledge of a particular subject matter. Students in particular
+are encouraged to verify they can answer the problems correctly before moving on.
+
+Similar to the exercises of \cite[pp. ix]{TAOCPV2} these exercises are given a scoring system based on the difficulty of
+the problem. However, unlike \cite{TAOCPV2} the problems do not get nearly as hard. The scoring of these
+exercises ranges from one (the easiest) to five (the hardest). The following table sumarizes the
+scoring system used.
+
+\begin{figure}[here]
+\begin{center}
+\begin{small}
+\begin{tabular}{|c|l|}
+\hline $\left [ 1 \right ]$ & An easy problem that should only take the reader a manner of \\
+ & minutes to solve. Usually does not involve much computer time \\
+ & to solve. \\
+\hline $\left [ 2 \right ]$ & An easy problem that involves a marginal amount of computer \\
+ & time usage. Usually requires a program to be written to \\
+ & solve the problem. \\
+\hline $\left [ 3 \right ]$ & A moderately hard problem that requires a non-trivial amount \\
+ & of work. Usually involves trivial research and development of \\
+ & new theory from the perspective of a student. \\
+\hline $\left [ 4 \right ]$ & A moderately hard problem that involves a non-trivial amount \\
+ & of work and research, the solution to which will demonstrate \\
+ & a higher mastery of the subject matter. \\
+\hline $\left [ 5 \right ]$ & A hard problem that involves concepts that are difficult for a \\
+ & novice to solve. Solutions to these problems will demonstrate a \\
+ & complete mastery of the given subject. \\
+\hline
+\end{tabular}
+\end{small}
+\end{center}
+\caption{Exercise Scoring System}
+\end{figure}
+
+Problems at the first level are meant to be simple questions that the reader can answer quickly without programming a solution or
+devising new theory. These problems are quick tests to see if the material is understood. Problems at the second level
+are also designed to be easy but will require a program or algorithm to be implemented to arrive at the answer. These
+two levels are essentially entry level questions.
+
+Problems at the third level are meant to be a bit more difficult than the first two levels. The answer is often
+fairly obvious but arriving at an exacting solution requires some thought and skill. These problems will almost always
+involve devising a new algorithm or implementing a variation of another algorithm previously presented. Readers who can
+answer these questions will feel comfortable with the concepts behind the topic at hand.
+
+Problems at the fourth level are meant to be similar to those of the level three questions except they will require
+additional research to be completed. The reader will most likely not know the answer right away, nor will the text provide
+the exact details of the answer until a subsequent chapter.
+
+Problems at the fifth level are meant to be the hardest
+problems relative to all the other problems in the chapter. People who can correctly answer fifth level problems have a
+mastery of the subject matter at hand.
+
+Often problems will be tied together. The purpose of this is to start a chain of thought that will be discussed in future chapters. The reader
+is encouraged to answer the follow-up problems and try to draw the relevance of problems.
+
+\section{Introduction to LibTomMath}
+
+\subsection{What is LibTomMath?}
+LibTomMath is a free and open source multiple precision integer library written entirely in portable ISO C. By portable it
+is meant that the library does not contain any code that is computer platform dependent or otherwise problematic to use on
+any given platform.
+
+The library has been successfully tested under numerous operating systems including Unix\footnote{All of these
+trademarks belong to their respective rightful owners.}, MacOS, Windows, Linux, PalmOS and on standalone hardware such
+as the Gameboy Advance. The library is designed to contain enough functionality to be able to develop applications such
+as public key cryptosystems and still maintain a relatively small footprint.
+
+\subsection{Goals of LibTomMath}
+
+Libraries which obtain the most efficiency are rarely written in a high level programming language such as C. However,
+even though this library is written entirely in ISO C, considerable care has been taken to optimize the algorithm implementations within the
+library. Specifically the code has been written to work well with the GNU C Compiler (\textit{GCC}) on both x86 and ARM
+processors. Wherever possible, highly efficient algorithms, such as Karatsuba multiplication, sliding window
+exponentiation and Montgomery reduction have been provided to make the library more efficient.
+
+Even with the nearly optimal and specialized algorithms that have been included the Application Programing Interface
+(\textit{API}) has been kept as simple as possible. Often generic place holder routines will make use of specialized
+algorithms automatically without the developer's specific attention. One such example is the generic multiplication
+algorithm \textbf{mp\_mul()} which will automatically use Toom--Cook, Karatsuba, Comba or baseline multiplication
+based on the magnitude of the inputs and the configuration of the library.
+
+Making LibTomMath as efficient as possible is not the only goal of the LibTomMath project. Ideally the library should
+be source compatible with another popular library which makes it more attractive for developers to use. In this case the
+MPI library was used as a API template for all the basic functions. MPI was chosen because it is another library that fits
+in the same niche as LibTomMath. Even though LibTomMath uses MPI as the template for the function names and argument
+passing conventions, it has been written from scratch by Tom St Denis.
+
+The project is also meant to act as a learning tool for students, the logic being that no easy-to-follow ``bignum''
+library exists which can be used to teach computer science students how to perform fast and reliable multiple precision
+integer arithmetic. To this end the source code has been given quite a few comments and algorithm discussion points.
+
+\section{Choice of LibTomMath}
+LibTomMath was chosen as the case study of this text not only because the author of both projects is one and the same but
+for more worthy reasons. Other libraries such as GMP \cite{GMP}, MPI \cite{MPI}, LIP \cite{LIP} and OpenSSL
+\cite{OPENSSL} have multiple precision integer arithmetic routines but would not be ideal for this text for
+reasons that will be explained in the following sub-sections.
+
+\subsection{Code Base}
+The LibTomMath code base is all portable ISO C source code. This means that there are no platform dependent conditional
+segments of code littered throughout the source. This clean and uncluttered approach to the library means that a
+developer can more readily discern the true intent of a given section of source code without trying to keep track of
+what conditional code will be used.
+
+The code base of LibTomMath is well organized. Each function is in its own separate source code file
+which allows the reader to find a given function very quickly. On average there are $76$ lines of code per source
+file which makes the source very easily to follow. By comparison MPI and LIP are single file projects making code tracing
+very hard. GMP has many conditional code segments which also hinder tracing.
+
+When compiled with GCC for the x86 processor and optimized for speed the entire library is approximately $100$KiB\footnote{The notation ``KiB'' means $2^{10}$ octets, similarly ``MiB'' means $2^{20}$ octets.}
+ which is fairly small compared to GMP (over $250$KiB). LibTomMath is slightly larger than MPI (which compiles to about
+$50$KiB) but LibTomMath is also much faster and more complete than MPI.
+
+\subsection{API Simplicity}
+LibTomMath is designed after the MPI library and shares the API design. Quite often programs that use MPI will build
+with LibTomMath without change. The function names correlate directly to the action they perform. Almost all of the
+functions share the same parameter passing convention. The learning curve is fairly shallow with the API provided
+which is an extremely valuable benefit for the student and developer alike.
+
+The LIP library is an example of a library with an API that is awkward to work with. LIP uses function names that are often ``compressed'' to
+illegible short hand. LibTomMath does not share this characteristic.
+
+The GMP library also does not return error codes. Instead it uses a POSIX.1 \cite{POSIX1} signal system where errors
+are signaled to the host application. This happens to be the fastest approach but definitely not the most versatile. In
+effect a math error (i.e. invalid input, heap error, etc) can cause a program to stop functioning which is definitely
+undersireable in many situations.
+
+\subsection{Optimizations}
+While LibTomMath is certainly not the fastest library (GMP often beats LibTomMath by a factor of two) it does
+feature a set of optimal algorithms for tasks such as modular reduction, exponentiation, multiplication and squaring. GMP
+and LIP also feature such optimizations while MPI only uses baseline algorithms with no optimizations. GMP lacks a few
+of the additional modular reduction optimizations that LibTomMath features\footnote{At the time of this writing GMP
+only had Barrett and Montgomery modular reduction algorithms.}.
+
+LibTomMath is almost always an order of magnitude faster than the MPI library at computationally expensive tasks such as modular
+exponentiation. In the grand scheme of ``bignum'' libraries LibTomMath is faster than the average library and usually
+slower than the best libraries such as GMP and OpenSSL by only a small factor.
+
+\subsection{Portability and Stability}
+LibTomMath will build ``out of the box'' on any platform equipped with a modern version of the GNU C Compiler
+(\textit{GCC}). This means that without changes the library will build without configuration or setting up any
+variables. LIP and MPI will build ``out of the box'' as well but have numerous known bugs. Most notably the author of
+MPI has recently stopped working on his library and LIP has long since been discontinued.
+
+GMP requires a configuration script to run and will not build out of the box. GMP and LibTomMath are still in active
+development and are very stable across a variety of platforms.
+
+\subsection{Choice}
+LibTomMath is a relatively compact, well documented, highly optimized and portable library which seems only natural for
+the case study of this text. Various source files from the LibTomMath project will be included within the text. However,
+the reader is encouraged to download their own copy of the library to actually be able to work with the library.
+
+\chapter{Getting Started}
+\section{Library Basics}
+The trick to writing any useful library of source code is to build a solid foundation and work outwards from it. First,
+a problem along with allowable solution parameters should be identified and analyzed. In this particular case the
+inability to accomodate multiple precision integers is the problem. Futhermore, the solution must be written
+as portable source code that is reasonably efficient across several different computer platforms.
+
+After a foundation is formed the remainder of the library can be designed and implemented in a hierarchical fashion.
+That is, to implement the lowest level dependencies first and work towards the most abstract functions last. For example,
+before implementing a modular exponentiation algorithm one would implement a modular reduction algorithm.
+By building outwards from a base foundation instead of using a parallel design methodology the resulting project is
+highly modular. Being highly modular is a desirable property of any project as it often means the resulting product
+has a small footprint and updates are easy to perform.
+
+Usually when I start a project I will begin with the header files. I define the data types I think I will need and
+prototype the initial functions that are not dependent on other functions (within the library). After I
+implement these base functions I prototype more dependent functions and implement them. The process repeats until
+I implement all of the functions I require. For example, in the case of LibTomMath I implemented functions such as
+mp\_init() well before I implemented mp\_mul() and even further before I implemented mp\_exptmod(). As an example as to
+why this design works note that the Karatsuba and Toom-Cook multipliers were written \textit{after} the
+dependent function mp\_exptmod() was written. Adding the new multiplication algorithms did not require changes to the
+mp\_exptmod() function itself and lowered the total cost of ownership (\textit{so to speak}) and of development
+for new algorithms. This methodology allows new algorithms to be tested in a complete framework with relative ease.
+
+\begin{center}
+\begin{figure}[here]
+\includegraphics{pics/design_process.ps}
+\caption{Design Flow of the First Few Original LibTomMath Functions.}
+\label{pic:design_process}
+\end{figure}
+\end{center}
+
+Only after the majority of the functions were in place did I pursue a less hierarchical approach to auditing and optimizing
+the source code. For example, one day I may audit the multipliers and the next day the polynomial basis functions.
+
+It only makes sense to begin the text with the preliminary data types and support algorithms required as well.
+This chapter discusses the core algorithms of the library which are the dependents for every other algorithm.
+
+\section{What is a Multiple Precision Integer?}
+Recall that most programming languages, in particular ISO C \cite{ISOC}, only have fixed precision data types that on their own cannot
+be used to represent values larger than their precision will allow. The purpose of multiple precision algorithms is
+to use fixed precision data types to create and manipulate multiple precision integers which may represent values
+that are very large.
+
+As a well known analogy, school children are taught how to form numbers larger than nine by prepending more radix ten digits. In the decimal system
+the largest single digit value is $9$. However, by concatenating digits together larger numbers may be represented. Newly prepended digits
+(\textit{to the left}) are said to be in a different power of ten column. That is, the number $123$ can be described as having a $1$ in the hundreds
+column, $2$ in the tens column and $3$ in the ones column. Or more formally $123 = 1 \cdot 10^2 + 2 \cdot 10^1 + 3 \cdot 10^0$. Computer based
+multiple precision arithmetic is essentially the same concept. Larger integers are represented by adjoining fixed
+precision computer words with the exception that a different radix is used.
+
+What most people probably do not think about explicitly are the various other attributes that describe a multiple precision
+integer. For example, the integer $154_{10}$ has two immediately obvious properties. First, the integer is positive,
+that is the sign of this particular integer is positive as opposed to negative. Second, the integer has three digits in
+its representation. There is an additional property that the integer posesses that does not concern pencil-and-paper
+arithmetic. The third property is how many digits placeholders are available to hold the integer.
+
+The human analogy of this third property is ensuring there is enough space on the paper to write the integer. For example,
+if one starts writing a large number too far to the right on a piece of paper they will have to erase it and move left.
+Similarly, computer algorithms must maintain strict control over memory usage to ensure that the digits of an integer
+will not exceed the allowed boundaries. These three properties make up what is known as a multiple precision
+integer or mp\_int for short.
+
+\subsection{The mp\_int Structure}
+\label{sec:MPINT}
+The mp\_int structure is the ISO C based manifestation of what represents a multiple precision integer. The ISO C standard does not provide for
+any such data type but it does provide for making composite data types known as structures. The following is the structure definition
+used within LibTomMath.
+
+\index{mp\_int}
+\begin{figure}[here]
+\begin{center}
+\begin{small}
+%\begin{verbatim}
+\begin{tabular}{|l|}
+\hline
+typedef struct \{ \\
+\hspace{3mm}int used, alloc, sign;\\
+\hspace{3mm}mp\_digit *dp;\\
+\} \textbf{mp\_int}; \\
+\hline
+\end{tabular}
+%\end{verbatim}
+\end{small}
+\caption{The mp\_int Structure}
+\label{fig:mpint}
+\end{center}
+\end{figure}
+
+The mp\_int structure (fig. \ref{fig:mpint}) can be broken down as follows.
+
+\begin{enumerate}
+\item The \textbf{used} parameter denotes how many digits of the array \textbf{dp} contain the digits used to represent
+a given integer. The \textbf{used} count must be positive (or zero) and may not exceed the \textbf{alloc} count.
+
+\item The \textbf{alloc} parameter denotes how
+many digits are available in the array to use by functions before it has to increase in size. When the \textbf{used} count
+of a result would exceed the \textbf{alloc} count all of the algorithms will automatically increase the size of the
+array to accommodate the precision of the result.
+
+\item The pointer \textbf{dp} points to a dynamically allocated array of digits that represent the given multiple
+precision integer. It is padded with $(\textbf{alloc} - \textbf{used})$ zero digits. The array is maintained in a least
+significant digit order. As a pencil and paper analogy the array is organized such that the right most digits are stored
+first starting at the location indexed by zero\footnote{In C all arrays begin at zero.} in the array. For example,
+if \textbf{dp} contains $\lbrace a, b, c, \ldots \rbrace$ where \textbf{dp}$_0 = a$, \textbf{dp}$_1 = b$, \textbf{dp}$_2 = c$, $\ldots$ then
+it would represent the integer $a + b\beta + c\beta^2 + \ldots$
+
+\index{MP\_ZPOS} \index{MP\_NEG}
+\item The \textbf{sign} parameter denotes the sign as either zero/positive (\textbf{MP\_ZPOS}) or negative (\textbf{MP\_NEG}).
+\end{enumerate}
+
+\subsubsection{Valid mp\_int Structures}
+Several rules are placed on the state of an mp\_int structure and are assumed to be followed for reasons of efficiency.
+The only exceptions are when the structure is passed to initialization functions such as mp\_init() and mp\_init\_copy().
+
+\begin{enumerate}
+\item The value of \textbf{alloc} may not be less than one. That is \textbf{dp} always points to a previously allocated
+array of digits.
+\item The value of \textbf{used} may not exceed \textbf{alloc} and must be greater than or equal to zero.
+\item The value of \textbf{used} implies the digit at index $(used - 1)$ of the \textbf{dp} array is non-zero. That is,
+leading zero digits in the most significant positions must be trimmed.
+ \begin{enumerate}
+ \item Digits in the \textbf{dp} array at and above the \textbf{used} location must be zero.
+ \end{enumerate}
+\item The value of \textbf{sign} must be \textbf{MP\_ZPOS} if \textbf{used} is zero;
+this represents the mp\_int value of zero.
+\end{enumerate}
+
+\section{Argument Passing}
+A convention of argument passing must be adopted early on in the development of any library. Making the function
+prototypes consistent will help eliminate many headaches in the future as the library grows to significant complexity.
+In LibTomMath the multiple precision integer functions accept parameters from left to right as pointers to mp\_int
+structures. That means that the source (input) operands are placed on the left and the destination (output) on the right.
+Consider the following examples.
+
+\begin{verbatim}
+ mp_mul(&a, &b, &c); /* c = a * b */
+ mp_add(&a, &b, &a); /* a = a + b */
+ mp_sqr(&a, &b); /* b = a * a */
+\end{verbatim}
+
+The left to right order is a fairly natural way to implement the functions since it lets the developer read aloud the
+functions and make sense of them. For example, the first function would read ``multiply a and b and store in c''.
+
+Certain libraries (\textit{LIP by Lenstra for instance}) accept parameters the other way around, to mimic the order
+of assignment expressions. That is, the destination (output) is on the left and arguments (inputs) are on the right. In
+truth, it is entirely a matter of preference. In the case of LibTomMath the convention from the MPI library has been
+adopted.
+
+Another very useful design consideration, provided for in LibTomMath, is whether to allow argument sources to also be a
+destination. For example, the second example (\textit{mp\_add}) adds $a$ to $b$ and stores in $a$. This is an important
+feature to implement since it allows the calling functions to cut down on the number of variables it must maintain.
+However, to implement this feature specific care has to be given to ensure the destination is not modified before the
+source is fully read.
+
+\section{Return Values}
+A well implemented application, no matter what its purpose, should trap as many runtime errors as possible and return them
+to the caller. By catching runtime errors a library can be guaranteed to prevent undefined behaviour. However, the end
+developer can still manage to cause a library to crash. For example, by passing an invalid pointer an application may
+fault by dereferencing memory not owned by the application.
+
+In the case of LibTomMath the only errors that are checked for are related to inappropriate inputs (division by zero for
+instance) and memory allocation errors. It will not check that the mp\_int passed to any function is valid nor
+will it check pointers for validity. Any function that can cause a runtime error will return an error code as an
+\textbf{int} data type with one of the following values (fig \ref{fig:errcodes}).
+
+\index{MP\_OKAY} \index{MP\_VAL} \index{MP\_MEM}
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{|l|l|}
+\hline \textbf{Value} & \textbf{Meaning} \\
+\hline \textbf{MP\_OKAY} & The function was successful \\
+\hline \textbf{MP\_VAL} & One of the input value(s) was invalid \\
+\hline \textbf{MP\_MEM} & The function ran out of heap memory \\
+\hline
+\end{tabular}
+\end{center}
+\caption{LibTomMath Error Codes}
+\label{fig:errcodes}
+\end{figure}
+
+When an error is detected within a function it should free any memory it allocated, often during the initialization of
+temporary mp\_ints, and return as soon as possible. The goal is to leave the system in the same state it was when the
+function was called. Error checking with this style of API is fairly simple.
+
+\begin{verbatim}
+ int err;
+ if ((err = mp_add(&a, &b, &c)) != MP_OKAY) {
+ printf("Error: %s\n", mp_error_to_string(err));
+ exit(EXIT_FAILURE);
+ }
+\end{verbatim}
+
+The GMP \cite{GMP} library uses C style \textit{signals} to flag errors which is of questionable use. Not all errors are fatal
+and it was not deemed ideal by the author of LibTomMath to force developers to have signal handlers for such cases.
+
+\section{Initialization and Clearing}
+The logical starting point when actually writing multiple precision integer functions is the initialization and
+clearing of the mp\_int structures. These two algorithms will be used by the majority of the higher level algorithms.
+
+Given the basic mp\_int structure an initialization routine must first allocate memory to hold the digits of
+the integer. Often it is optimal to allocate a sufficiently large pre-set number of digits even though
+the initial integer will represent zero. If only a single digit were allocated quite a few subsequent re-allocations
+would occur when operations are performed on the integers. There is a tradeoff between how many default digits to allocate
+and how many re-allocations are tolerable. Obviously allocating an excessive amount of digits initially will waste
+memory and become unmanageable.
+
+If the memory for the digits has been successfully allocated then the rest of the members of the structure must
+be initialized. Since the initial state of an mp\_int is to represent the zero integer, the allocated digits must be set
+to zero. The \textbf{used} count set to zero and \textbf{sign} set to \textbf{MP\_ZPOS}.
+
+\subsection{Initializing an mp\_int}
+An mp\_int is said to be initialized if it is set to a valid, preferably default, state such that all of the members of the
+structure are set to valid values. The mp\_init algorithm will perform such an action.
+
+\index{mp\_init}
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_init}. \\
+\textbf{Input}. An mp\_int $a$ \\
+\textbf{Output}. Allocate memory and initialize $a$ to a known valid mp\_int state. \\
+\hline \\
+1. Allocate memory for \textbf{MP\_PREC} digits. \\
+2. If the allocation failed return(\textit{MP\_MEM}) \\
+3. for $n$ from $0$ to $MP\_PREC - 1$ do \\
+\hspace{3mm}3.1 $a_n \leftarrow 0$\\
+4. $a.sign \leftarrow MP\_ZPOS$\\
+5. $a.used \leftarrow 0$\\
+6. $a.alloc \leftarrow MP\_PREC$\\
+7. Return(\textit{MP\_OKAY})\\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_init}
+\end{figure}
+
+\textbf{Algorithm mp\_init.}
+The purpose of this function is to initialize an mp\_int structure so that the rest of the library can properly
+manipulte it. It is assumed that the input may not have had any of its members previously initialized which is certainly
+a valid assumption if the input resides on the stack.
+
+Before any of the members such as \textbf{sign}, \textbf{used} or \textbf{alloc} are initialized the memory for
+the digits is allocated. If this fails the function returns before setting any of the other members. The \textbf{MP\_PREC}
+name represents a constant\footnote{Defined in the ``tommath.h'' header file within LibTomMath.}
+used to dictate the minimum precision of newly initialized mp\_int integers. Ideally, it is at least equal to the smallest
+precision number you'll be working with.
+
+Allocating a block of digits at first instead of a single digit has the benefit of lowering the number of usually slow
+heap operations later functions will have to perform in the future. If \textbf{MP\_PREC} is set correctly the slack
+memory and the number of heap operations will be trivial.
+
+Once the allocation has been made the digits have to be set to zero as well as the \textbf{used}, \textbf{sign} and
+\textbf{alloc} members initialized. This ensures that the mp\_int will always represent the default state of zero regardless
+of the original condition of the input.
+
+\textbf{Remark.}
+This function introduces the idiosyncrasy that all iterative loops, commonly initiated with the ``for'' keyword, iterate incrementally
+when the ``to'' keyword is placed between two expressions. For example, ``for $a$ from $b$ to $c$ do'' means that
+a subsequent expression (or body of expressions) are to be evaluated upto $c - b$ times so long as $b \le c$. In each
+iteration the variable $a$ is substituted for a new integer that lies inclusively between $b$ and $c$. If $b > c$ occured
+the loop would not iterate. By contrast if the ``downto'' keyword were used in place of ``to'' the loop would iterate
+decrementally.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_init.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+One immediate observation of this initializtion function is that it does not return a pointer to a mp\_int structure. It
+is assumed that the caller has already allocated memory for the mp\_int structure, typically on the application stack. The
+call to mp\_init() is used only to initialize the members of the structure to a known default state.
+
+Here we see (line 24) the memory allocation is performed first. This allows us to exit cleanly and quickly
+if there is an error. If the allocation fails the routine will return \textbf{MP\_MEM} to the caller to indicate there
+was a memory error. The function XMALLOC is what actually allocates the memory. Technically XMALLOC is not a function
+but a macro defined in ``tommath.h``. By default, XMALLOC will evaluate to malloc() which is the C library's built--in
+memory allocation routine.
+
+In order to assure the mp\_int is in a known state the digits must be set to zero. On most platforms this could have been
+accomplished by using calloc() instead of malloc(). However, to correctly initialize a integer type to a given value in a
+portable fashion you have to actually assign the value. The for loop (line 30) performs this required
+operation.
+
+After the memory has been successfully initialized the remainder of the members are initialized
+(lines 34 through 35) to their respective default states. At this point the algorithm has succeeded and
+a success code is returned to the calling function. If this function returns \textbf{MP\_OKAY} it is safe to assume the
+mp\_int structure has been properly initialized and is safe to use with other functions within the library.
+
+\subsection{Clearing an mp\_int}
+When an mp\_int is no longer required by the application, the memory that has been allocated for its digits must be
+returned to the application's memory pool with the mp\_clear algorithm.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_clear}. \\
+\textbf{Input}. An mp\_int $a$ \\
+\textbf{Output}. The memory for $a$ shall be deallocated. \\
+\hline \\
+1. If $a$ has been previously freed then return(\textit{MP\_OKAY}). \\
+2. for $n$ from 0 to $a.used - 1$ do \\
+\hspace{3mm}2.1 $a_n \leftarrow 0$ \\
+3. Free the memory allocated for the digits of $a$. \\
+4. $a.used \leftarrow 0$ \\
+5. $a.alloc \leftarrow 0$ \\
+6. $a.sign \leftarrow MP\_ZPOS$ \\
+7. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_clear}
+\end{figure}
+
+\textbf{Algorithm mp\_clear.}
+This algorithm accomplishes two goals. First, it clears the digits and the other mp\_int members. This ensures that
+if a developer accidentally re-uses a cleared structure it is less likely to cause problems. The second goal
+is to free the allocated memory.
+
+The logic behind the algorithm is extended by marking cleared mp\_int structures so that subsequent calls to this
+algorithm will not try to free the memory multiple times. Cleared mp\_ints are detectable by having a pre-defined invalid
+digit pointer \textbf{dp} setting.
+
+Once an mp\_int has been cleared the mp\_int structure is no longer in a valid state for any other algorithm
+with the exception of algorithms mp\_init, mp\_init\_copy, mp\_init\_size and mp\_clear.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_clear.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+The algorithm only operates on the mp\_int if it hasn't been previously cleared. The if statement (line 25)
+checks to see if the \textbf{dp} member is not \textbf{NULL}. If the mp\_int is a valid mp\_int then \textbf{dp} cannot be
+\textbf{NULL} in which case the if statement will evaluate to true.
+
+The digits of the mp\_int are cleared by the for loop (line 27) which assigns a zero to every digit. Similar to mp\_init()
+the digits are assigned zero instead of using block memory operations (such as memset()) since this is more portable.
+
+The digits are deallocated off the heap via the XFREE macro. Similar to XMALLOC the XFREE macro actually evaluates to
+a standard C library function. In this case the free() function. Since free() only deallocates the memory the pointer
+still has to be reset to \textbf{NULL} manually (line 35).
+
+Now that the digits have been cleared and deallocated the other members are set to their final values (lines 36 and 37).
+
+\section{Maintenance Algorithms}
+
+The previous sections describes how to initialize and clear an mp\_int structure. To further support operations
+that are to be performed on mp\_int structures (such as addition and multiplication) the dependent algorithms must be
+able to augment the precision of an mp\_int and
+initialize mp\_ints with differing initial conditions.
+
+These algorithms complete the set of low level algorithms required to work with mp\_int structures in the higher level
+algorithms such as addition, multiplication and modular exponentiation.
+
+\subsection{Augmenting an mp\_int's Precision}
+When storing a value in an mp\_int structure, a sufficient number of digits must be available to accomodate the entire
+result of an operation without loss of precision. Quite often the size of the array given by the \textbf{alloc} member
+is large enough to simply increase the \textbf{used} digit count. However, when the size of the array is too small it
+must be re-sized appropriately to accomodate the result. The mp\_grow algorithm will provide this functionality.
+
+\newpage\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_grow}. \\
+\textbf{Input}. An mp\_int $a$ and an integer $b$. \\
+\textbf{Output}. $a$ is expanded to accomodate $b$ digits. \\
+\hline \\
+1. if $a.alloc \ge b$ then return(\textit{MP\_OKAY}) \\
+2. $u \leftarrow b\mbox{ (mod }MP\_PREC\mbox{)}$ \\
+3. $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\
+4. Re-allocate the array of digits $a$ to size $v$ \\
+5. If the allocation failed then return(\textit{MP\_MEM}). \\
+6. for n from a.alloc to $v - 1$ do \\
+\hspace{+3mm}6.1 $a_n \leftarrow 0$ \\
+7. $a.alloc \leftarrow v$ \\
+8. Return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_grow}
+\end{figure}
+
+\textbf{Algorithm mp\_grow.}
+It is ideal to prevent re-allocations from being performed if they are not required (step one). This is useful to
+prevent mp\_ints from growing excessively in code that erroneously calls mp\_grow.
+
+The requested digit count is padded up to next multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} (steps two and three).
+This helps prevent many trivial reallocations that would grow an mp\_int by trivially small values.
+
+It is assumed that the reallocation (step four) leaves the lower $a.alloc$ digits of the mp\_int intact. This is much
+akin to how the \textit{realloc} function from the standard C library works. Since the newly allocated digits are
+assumed to contain undefined values they are initially set to zero.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_grow.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+A quick optimization is to first determine if a memory re-allocation is required at all. The if statement (line 24) checks
+if the \textbf{alloc} member of the mp\_int is smaller than the requested digit count. If the count is not larger than \textbf{alloc}
+the function skips the re-allocation part thus saving time.
+
+When a re-allocation is performed it is turned into an optimal request to save time in the future. The requested digit count is
+padded upwards to 2nd multiple of \textbf{MP\_PREC} larger than \textbf{alloc} (line 25). The XREALLOC function is used
+to re-allocate the memory. As per the other functions XREALLOC is actually a macro which evaluates to realloc by default. The realloc
+function leaves the base of the allocation intact which means the first \textbf{alloc} digits of the mp\_int are the same as before
+the re-allocation. All that is left is to clear the newly allocated digits and return.
+
+Note that the re-allocation result is actually stored in a temporary pointer $tmp$. This is to allow this function to return
+an error with a valid pointer. Earlier releases of the library stored the result of XREALLOC into the mp\_int $a$. That would
+result in a memory leak if XREALLOC ever failed.
+
+\subsection{Initializing Variable Precision mp\_ints}
+Occasionally the number of digits required will be known in advance of an initialization, based on, for example, the size
+of input mp\_ints to a given algorithm. The purpose of algorithm mp\_init\_size is similar to mp\_init except that it
+will allocate \textit{at least} a specified number of digits.
+
+\begin{figure}[here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_init\_size}. \\
+\textbf{Input}. An mp\_int $a$ and the requested number of digits $b$. \\
+\textbf{Output}. $a$ is initialized to hold at least $b$ digits. \\
+\hline \\
+1. $u \leftarrow b \mbox{ (mod }MP\_PREC\mbox{)}$ \\
+2. $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\
+3. Allocate $v$ digits. \\
+4. for $n$ from $0$ to $v - 1$ do \\
+\hspace{3mm}4.1 $a_n \leftarrow 0$ \\
+5. $a.sign \leftarrow MP\_ZPOS$\\
+6. $a.used \leftarrow 0$\\
+7. $a.alloc \leftarrow v$\\
+8. Return(\textit{MP\_OKAY})\\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_init\_size}
+\end{figure}
+
+\textbf{Algorithm mp\_init\_size.}
+This algorithm will initialize an mp\_int structure $a$ like algorithm mp\_init with the exception that the number of
+digits allocated can be controlled by the second input argument $b$. The input size is padded upwards so it is a
+multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} digits. This padding is used to prevent trivial
+allocations from becoming a bottleneck in the rest of the algorithms.
+
+Like algorithm mp\_init, the mp\_int structure is initialized to a default state representing the integer zero. This
+particular algorithm is useful if it is known ahead of time the approximate size of the input. If the approximation is
+correct no further memory re-allocations are required to work with the mp\_int.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_init\_size.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+The number of digits $b$ requested is padded (line 24) by first augmenting it to the next multiple of
+\textbf{MP\_PREC} and then adding \textbf{MP\_PREC} to the result. If the memory can be successfully allocated the
+mp\_int is placed in a default state representing the integer zero. Otherwise, the error code \textbf{MP\_MEM} will be
+returned (line 29).
+
+The digits are allocated and set to zero at the same time with the calloc() function (line @25,XCALLOC@). The
+\textbf{used} count is set to zero, the \textbf{alloc} count set to the padded digit count and the \textbf{sign} flag set
+to \textbf{MP\_ZPOS} to achieve a default valid mp\_int state (lines 33, 34 and 35). If the function
+returns succesfully then it is correct to assume that the mp\_int structure is in a valid state for the remainder of the
+functions to work with.
+
+\subsection{Multiple Integer Initializations and Clearings}
+Occasionally a function will require a series of mp\_int data types to be made available simultaneously.
+The purpose of algorithm mp\_init\_multi is to initialize a variable length array of mp\_int structures in a single
+statement. It is essentially a shortcut to multiple initializations.
+
+\newpage\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_init\_multi}. \\
+\textbf{Input}. Variable length array $V_k$ of mp\_int variables of length $k$. \\
+\textbf{Output}. The array is initialized such that each mp\_int of $V_k$ is ready to use. \\
+\hline \\
+1. for $n$ from 0 to $k - 1$ do \\
+\hspace{+3mm}1.1. Initialize the mp\_int $V_n$ (\textit{mp\_init}) \\
+\hspace{+3mm}1.2. If initialization failed then do \\
+\hspace{+6mm}1.2.1. for $j$ from $0$ to $n$ do \\
+\hspace{+9mm}1.2.1.1. Free the mp\_int $V_j$ (\textit{mp\_clear}) \\
+\hspace{+6mm}1.2.2. Return(\textit{MP\_MEM}) \\
+2. Return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_init\_multi}
+\end{figure}
+
+\textbf{Algorithm mp\_init\_multi.}
+The algorithm will initialize the array of mp\_int variables one at a time. If a runtime error has been detected
+(\textit{step 1.2}) all of the previously initialized variables are cleared. The goal is an ``all or nothing''
+initialization which allows for quick recovery from runtime errors.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_init\_multi.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+This function intializes a variable length list of mp\_int structure pointers. However, instead of having the mp\_int
+structures in an actual C array they are simply passed as arguments to the function. This function makes use of the
+``...'' argument syntax of the C programming language. The list is terminated with a final \textbf{NULL} argument
+appended on the right.
+
+The function uses the ``stdarg.h'' \textit{va} functions to step portably through the arguments to the function. A count
+$n$ of succesfully initialized mp\_int structures is maintained (line 48) such that if a failure does occur,
+the algorithm can backtrack and free the previously initialized structures (lines 28 to 47).
+
+
+\subsection{Clamping Excess Digits}
+When a function anticipates a result will be $n$ digits it is simpler to assume this is true within the body of
+the function instead of checking during the computation. For example, a multiplication of a $i$ digit number by a
+$j$ digit produces a result of at most $i + j$ digits. It is entirely possible that the result is $i + j - 1$
+though, with no final carry into the last position. However, suppose the destination had to be first expanded
+(\textit{via mp\_grow}) to accomodate $i + j - 1$ digits than further expanded to accomodate the final carry.
+That would be a considerable waste of time since heap operations are relatively slow.
+
+The ideal solution is to always assume the result is $i + j$ and fix up the \textbf{used} count after the function
+terminates. This way a single heap operation (\textit{at most}) is required. However, if the result was not checked
+there would be an excess high order zero digit.
+
+For example, suppose the product of two integers was $x_n = (0x_{n-1}x_{n-2}...x_0)_{\beta}$. The leading zero digit
+will not contribute to the precision of the result. In fact, through subsequent operations more leading zero digits would
+accumulate to the point the size of the integer would be prohibitive. As a result even though the precision is very
+low the representation is excessively large.
+
+The mp\_clamp algorithm is designed to solve this very problem. It will trim high-order zeros by decrementing the
+\textbf{used} count until a non-zero most significant digit is found. Also in this system, zero is considered to be a
+positive number which means that if the \textbf{used} count is decremented to zero, the sign must be set to
+\textbf{MP\_ZPOS}.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_clamp}. \\
+\textbf{Input}. An mp\_int $a$ \\
+\textbf{Output}. Any excess leading zero digits of $a$ are removed \\
+\hline \\
+1. while $a.used > 0$ and $a_{a.used - 1} = 0$ do \\
+\hspace{+3mm}1.1 $a.used \leftarrow a.used - 1$ \\
+2. if $a.used = 0$ then do \\
+\hspace{+3mm}2.1 $a.sign \leftarrow MP\_ZPOS$ \\
+\hline \\
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_clamp}
+\end{figure}
+
+\textbf{Algorithm mp\_clamp.}
+As can be expected this algorithm is very simple. The loop on step one is expected to iterate only once or twice at
+the most. For example, this will happen in cases where there is not a carry to fill the last position. Step two fixes the sign for
+when all of the digits are zero to ensure that the mp\_int is valid at all times.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_clamp.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+Note on line 28 how to test for the \textbf{used} count is made on the left of the \&\& operator. In the C programming
+language the terms to \&\& are evaluated left to right with a boolean short-circuit if any condition fails. This is
+important since if the \textbf{used} is zero the test on the right would fetch below the array. That is obviously
+undesirable. The parenthesis on line 31 is used to make sure the \textbf{used} count is decremented and not
+the pointer ``a''.
+
+\section*{Exercises}
+\begin{tabular}{cl}
+$\left [ 1 \right ]$ & Discuss the relevance of the \textbf{used} member of the mp\_int structure. \\
+ & \\
+$\left [ 1 \right ]$ & Discuss the consequences of not using padding when performing allocations. \\
+ & \\
+$\left [ 2 \right ]$ & Estimate an ideal value for \textbf{MP\_PREC} when performing 1024-bit RSA \\
+ & encryption when $\beta = 2^{28}$. \\
+ & \\
+$\left [ 1 \right ]$ & Discuss the relevance of the algorithm mp\_clamp. What does it prevent? \\
+ & \\
+$\left [ 1 \right ]$ & Give an example of when the algorithm mp\_init\_copy might be useful. \\
+ & \\
+\end{tabular}
+
+
+%%%
+% CHAPTER FOUR
+%%%
+
+\chapter{Basic Operations}
+
+\section{Introduction}
+In the previous chapter a series of low level algorithms were established that dealt with initializing and maintaining
+mp\_int structures. This chapter will discuss another set of seemingly non-algebraic algorithms which will form the low
+level basis of the entire library. While these algorithm are relatively trivial it is important to understand how they
+work before proceeding since these algorithms will be used almost intrinsically in the following chapters.
+
+The algorithms in this chapter deal primarily with more ``programmer'' related tasks such as creating copies of
+mp\_int structures, assigning small values to mp\_int structures and comparisons of the values mp\_int structures
+represent.
+
+\section{Assigning Values to mp\_int Structures}
+\subsection{Copying an mp\_int}
+Assigning the value that a given mp\_int structure represents to another mp\_int structure shall be known as making
+a copy for the purposes of this text. The copy of the mp\_int will be a separate entity that represents the same
+value as the mp\_int it was copied from. The mp\_copy algorithm provides this functionality.
+
+\newpage\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_copy}. \\
+\textbf{Input}. An mp\_int $a$ and $b$. \\
+\textbf{Output}. Store a copy of $a$ in $b$. \\
+\hline \\
+1. If $b.alloc < a.used$ then grow $b$ to $a.used$ digits. (\textit{mp\_grow}) \\
+2. for $n$ from 0 to $a.used - 1$ do \\
+\hspace{3mm}2.1 $b_{n} \leftarrow a_{n}$ \\
+3. for $n$ from $a.used$ to $b.used - 1$ do \\
+\hspace{3mm}3.1 $b_{n} \leftarrow 0$ \\
+4. $b.used \leftarrow a.used$ \\
+5. $b.sign \leftarrow a.sign$ \\
+6. return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_copy}
+\end{figure}
+
+\textbf{Algorithm mp\_copy.}
+This algorithm copies the mp\_int $a$ such that upon succesful termination of the algorithm the mp\_int $b$ will
+represent the same integer as the mp\_int $a$. The mp\_int $b$ shall be a complete and distinct copy of the
+mp\_int $a$ meaing that the mp\_int $a$ can be modified and it shall not affect the value of the mp\_int $b$.
+
+If $b$ does not have enough room for the digits of $a$ it must first have its precision augmented via the mp\_grow
+algorithm. The digits of $a$ are copied over the digits of $b$ and any excess digits of $b$ are set to zero (step two
+and three). The \textbf{used} and \textbf{sign} members of $a$ are finally copied over the respective members of
+$b$.
+
+\textbf{Remark.} This algorithm also introduces a new idiosyncrasy that will be used throughout the rest of the
+text. The error return codes of other algorithms are not explicitly checked in the pseudo-code presented. For example, in
+step one of the mp\_copy algorithm the return of mp\_grow is not explicitly checked to ensure it succeeded. Text space is
+limited so it is assumed that if a algorithm fails it will clear all temporarily allocated mp\_ints and return
+the error code itself. However, the C code presented will demonstrate all of the error handling logic required to
+implement the pseudo-code.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_copy.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+Occasionally a dependent algorithm may copy an mp\_int effectively into itself such as when the input and output
+mp\_int structures passed to a function are one and the same. For this case it is optimal to return immediately without
+copying digits (line 25).
+
+The mp\_int $b$ must have enough digits to accomodate the used digits of the mp\_int $a$. If $b.alloc$ is less than
+$a.used$ the algorithm mp\_grow is used to augment the precision of $b$ (lines 30 to 33). In order to
+simplify the inner loop that copies the digits from $a$ to $b$, two aliases $tmpa$ and $tmpb$ point directly at the digits
+of the mp\_ints $a$ and $b$ respectively. These aliases (lines 43 and 46) allow the compiler to access the digits without first dereferencing the
+mp\_int pointers and then subsequently the pointer to the digits.
+
+After the aliases are established the digits from $a$ are copied into $b$ (lines 49 to 51) and then the excess
+digits of $b$ are set to zero (lines 54 to 56). Both ``for'' loops make use of the pointer aliases and in
+fact the alias for $b$ is carried through into the second ``for'' loop to clear the excess digits. This optimization
+allows the alias to stay in a machine register fairly easy between the two loops.
+
+\textbf{Remarks.} The use of pointer aliases is an implementation methodology first introduced in this function that will
+be used considerably in other functions. Technically, a pointer alias is simply a short hand alias used to lower the
+number of pointer dereferencing operations required to access data. For example, a for loop may resemble
+
+\begin{alltt}
+for (x = 0; x < 100; x++) \{
+ a->num[4]->dp[x] = 0;
+\}
+\end{alltt}
+
+This could be re-written using aliases as
+
+\begin{alltt}
+mp_digit *tmpa;
+a = a->num[4]->dp;
+for (x = 0; x < 100; x++) \{
+ *a++ = 0;
+\}
+\end{alltt}
+
+In this case an alias is used to access the
+array of digits within an mp\_int structure directly. It may seem that a pointer alias is strictly not required
+as a compiler may optimize out the redundant pointer operations. However, there are two dominant reasons to use aliases.
+
+The first reason is that most compilers will not effectively optimize pointer arithmetic. For example, some optimizations
+may work for the Microsoft Visual C++ compiler (MSVC) and not for the GNU C Compiler (GCC). Also some optimizations may
+work for GCC and not MSVC. As such it is ideal to find a common ground for as many compilers as possible. Pointer
+aliases optimize the code considerably before the compiler even reads the source code which means the end compiled code
+stands a better chance of being faster.
+
+The second reason is that pointer aliases often can make an algorithm simpler to read. Consider the first ``for''
+loop of the function mp\_copy() re-written to not use pointer aliases.
+
+\begin{alltt}
+ /* copy all the digits */
+ for (n = 0; n < a->used; n++) \{
+ b->dp[n] = a->dp[n];
+ \}
+\end{alltt}
+
+Whether this code is harder to read depends strongly on the individual. However, it is quantifiably slightly more
+complicated as there are four variables within the statement instead of just two.
+
+\subsubsection{Nested Statements}
+Another commonly used technique in the source routines is that certain sections of code are nested. This is used in
+particular with the pointer aliases to highlight code phases. For example, a Comba multiplier (discussed in chapter six)
+will typically have three different phases. First the temporaries are initialized, then the columns calculated and
+finally the carries are propagated. In this example the middle column production phase will typically be nested as it
+uses temporary variables and aliases the most.
+
+The nesting also simplies the source code as variables that are nested are only valid for their scope. As a result
+the various temporary variables required do not propagate into other sections of code.
+
+
+\subsection{Creating a Clone}
+Another common operation is to make a local temporary copy of an mp\_int argument. To initialize an mp\_int
+and then copy another existing mp\_int into the newly intialized mp\_int will be known as creating a clone. This is
+useful within functions that need to modify an argument but do not wish to actually modify the original copy. The
+mp\_init\_copy algorithm has been designed to help perform this task.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_init\_copy}. \\
+\textbf{Input}. An mp\_int $a$ and $b$\\
+\textbf{Output}. $a$ is initialized to be a copy of $b$. \\
+\hline \\
+1. Init $a$. (\textit{mp\_init}) \\
+2. Copy $b$ to $a$. (\textit{mp\_copy}) \\
+3. Return the status of the copy operation. \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_init\_copy}
+\end{figure}
+
+\textbf{Algorithm mp\_init\_copy.}
+This algorithm will initialize an mp\_int variable and copy another previously initialized mp\_int variable into it. As
+such this algorithm will perform two operations in one step.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_init\_copy.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+This will initialize \textbf{a} and make it a verbatim copy of the contents of \textbf{b}. Note that
+\textbf{a} will have its own memory allocated which means that \textbf{b} may be cleared after the call
+and \textbf{a} will be left intact.
+
+\section{Zeroing an Integer}
+Reseting an mp\_int to the default state is a common step in many algorithms. The mp\_zero algorithm will be the algorithm used to
+perform this task.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_zero}. \\
+\textbf{Input}. An mp\_int $a$ \\
+\textbf{Output}. Zero the contents of $a$ \\
+\hline \\
+1. $a.used \leftarrow 0$ \\
+2. $a.sign \leftarrow$ MP\_ZPOS \\
+3. for $n$ from 0 to $a.alloc - 1$ do \\
+\hspace{3mm}3.1 $a_n \leftarrow 0$ \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_zero}
+\end{figure}
+
+\textbf{Algorithm mp\_zero.}
+This algorithm simply resets a mp\_int to the default state.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_zero.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+After the function is completed, all of the digits are zeroed, the \textbf{used} count is zeroed and the
+\textbf{sign} variable is set to \textbf{MP\_ZPOS}.
+
+\section{Sign Manipulation}
+\subsection{Absolute Value}
+With the mp\_int representation of an integer, calculating the absolute value is trivial. The mp\_abs algorithm will compute
+the absolute value of an mp\_int.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_abs}. \\
+\textbf{Input}. An mp\_int $a$ \\
+\textbf{Output}. Computes $b = \vert a \vert$ \\
+\hline \\
+1. Copy $a$ to $b$. (\textit{mp\_copy}) \\
+2. If the copy failed return(\textit{MP\_MEM}). \\
+3. $b.sign \leftarrow MP\_ZPOS$ \\
+4. Return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_abs}
+\end{figure}
+
+\textbf{Algorithm mp\_abs.}
+This algorithm computes the absolute of an mp\_int input. First it copies $a$ over $b$. This is an example of an
+algorithm where the check in mp\_copy that determines if the source and destination are equal proves useful. This allows,
+for instance, the developer to pass the same mp\_int as the source and destination to this function without addition
+logic to handle it.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_abs.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+This fairly trivial algorithm first eliminates non--required duplications (line 28) and then sets the
+\textbf{sign} flag to \textbf{MP\_ZPOS}.
+
+\subsection{Integer Negation}
+With the mp\_int representation of an integer, calculating the negation is also trivial. The mp\_neg algorithm will compute
+the negative of an mp\_int input.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_neg}. \\
+\textbf{Input}. An mp\_int $a$ \\
+\textbf{Output}. Computes $b = -a$ \\
+\hline \\
+1. Copy $a$ to $b$. (\textit{mp\_copy}) \\
+2. If the copy failed return(\textit{MP\_MEM}). \\
+3. If $a.used = 0$ then return(\textit{MP\_OKAY}). \\
+4. If $a.sign = MP\_ZPOS$ then do \\
+\hspace{3mm}4.1 $b.sign = MP\_NEG$. \\
+5. else do \\
+\hspace{3mm}5.1 $b.sign = MP\_ZPOS$. \\
+6. Return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_neg}
+\end{figure}
+
+\textbf{Algorithm mp\_neg.}
+This algorithm computes the negation of an input. First it copies $a$ over $b$. If $a$ has no used digits then
+the algorithm returns immediately. Otherwise it flips the sign flag and stores the result in $b$. Note that if
+$a$ had no digits then it must be positive by definition. Had step three been omitted then the algorithm would return
+zero as negative.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_neg.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+Like mp\_abs() this function avoids non--required duplications (line 22) and then sets the sign. We
+have to make sure that only non--zero values get a \textbf{sign} of \textbf{MP\_NEG}. If the mp\_int is zero
+than the \textbf{sign} is hard--coded to \textbf{MP\_ZPOS}.
+
+\section{Small Constants}
+\subsection{Setting Small Constants}
+Often a mp\_int must be set to a relatively small value such as $1$ or $2$. For these cases the mp\_set algorithm is useful.
+
+\newpage\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_set}. \\
+\textbf{Input}. An mp\_int $a$ and a digit $b$ \\
+\textbf{Output}. Make $a$ equivalent to $b$ \\
+\hline \\
+1. Zero $a$ (\textit{mp\_zero}). \\
+2. $a_0 \leftarrow b \mbox{ (mod }\beta\mbox{)}$ \\
+3. $a.used \leftarrow \left \lbrace \begin{array}{ll}
+ 1 & \mbox{if }a_0 > 0 \\
+ 0 & \mbox{if }a_0 = 0
+ \end{array} \right .$ \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_set}
+\end{figure}
+
+\textbf{Algorithm mp\_set.}
+This algorithm sets a mp\_int to a small single digit value. Step number 1 ensures that the integer is reset to the default state. The
+single digit is set (\textit{modulo $\beta$}) and the \textbf{used} count is adjusted accordingly.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_set.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+First we zero (line 21) the mp\_int to make sure that the other members are initialized for a
+small positive constant. mp\_zero() ensures that the \textbf{sign} is positive and the \textbf{used} count
+is zero. Next we set the digit and reduce it modulo $\beta$ (line 22). After this step we have to
+check if the resulting digit is zero or not. If it is not then we set the \textbf{used} count to one, otherwise
+to zero.
+
+We can quickly reduce modulo $\beta$ since it is of the form $2^k$ and a quick binary AND operation with
+$2^k - 1$ will perform the same operation.
+
+One important limitation of this function is that it will only set one digit. The size of a digit is not fixed, meaning source that uses
+this function should take that into account. Only trivially small constants can be set using this function.
+
+\subsection{Setting Large Constants}
+To overcome the limitations of the mp\_set algorithm the mp\_set\_int algorithm is ideal. It accepts a ``long''
+data type as input and will always treat it as a 32-bit integer.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_set\_int}. \\
+\textbf{Input}. An mp\_int $a$ and a ``long'' integer $b$ \\
+\textbf{Output}. Make $a$ equivalent to $b$ \\
+\hline \\
+1. Zero $a$ (\textit{mp\_zero}) \\
+2. for $n$ from 0 to 7 do \\
+\hspace{3mm}2.1 $a \leftarrow a \cdot 16$ (\textit{mp\_mul2d}) \\
+\hspace{3mm}2.2 $u \leftarrow \lfloor b / 2^{4(7 - n)} \rfloor \mbox{ (mod }16\mbox{)}$\\
+\hspace{3mm}2.3 $a_0 \leftarrow a_0 + u$ \\
+\hspace{3mm}2.4 $a.used \leftarrow a.used + 1$ \\
+3. Clamp excess used digits (\textit{mp\_clamp}) \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_set\_int}
+\end{figure}
+
+\textbf{Algorithm mp\_set\_int.}
+The algorithm performs eight iterations of a simple loop where in each iteration four bits from the source are added to the
+mp\_int. Step 2.1 will multiply the current result by sixteen making room for four more bits in the less significant positions. In step 2.2 the
+next four bits from the source are extracted and are added to the mp\_int. The \textbf{used} digit count is
+incremented to reflect the addition. The \textbf{used} digit counter is incremented since if any of the leading digits were zero the mp\_int would have
+zero digits used and the newly added four bits would be ignored.
+
+Excess zero digits are trimmed in steps 2.1 and 3 by using higher level algorithms mp\_mul2d and mp\_clamp.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_set\_int.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+This function sets four bits of the number at a time to handle all practical \textbf{DIGIT\_BIT} sizes. The weird
+addition on line 39 ensures that the newly added in bits are added to the number of digits. While it may not
+seem obvious as to why the digit counter does not grow exceedingly large it is because of the shift on line 28
+as well as the call to mp\_clamp() on line 41. Both functions will clamp excess leading digits which keeps
+the number of used digits low.
+
+\section{Comparisons}
+\subsection{Unsigned Comparisions}
+Comparing a multiple precision integer is performed with the exact same algorithm used to compare two decimal numbers. For example,
+to compare $1,234$ to $1,264$ the digits are extracted by their positions. That is we compare $1 \cdot 10^3 + 2 \cdot 10^2 + 3 \cdot 10^1 + 4 \cdot 10^0$
+to $1 \cdot 10^3 + 2 \cdot 10^2 + 6 \cdot 10^1 + 4 \cdot 10^0$ by comparing single digits at a time starting with the highest magnitude
+positions. If any leading digit of one integer is greater than a digit in the same position of another integer then obviously it must be greater.
+
+The first comparision routine that will be developed is the unsigned magnitude compare which will perform a comparison based on the digits of two
+mp\_int variables alone. It will ignore the sign of the two inputs. Such a function is useful when an absolute comparison is required or if the
+signs are known to agree in advance.
+
+To facilitate working with the results of the comparison functions three constants are required.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{|r|l|}
+\hline \textbf{Constant} & \textbf{Meaning} \\
+\hline \textbf{MP\_GT} & Greater Than \\
+\hline \textbf{MP\_EQ} & Equal To \\
+\hline \textbf{MP\_LT} & Less Than \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Comparison Return Codes}
+\end{figure}
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_cmp\_mag}. \\
+\textbf{Input}. Two mp\_ints $a$ and $b$. \\
+\textbf{Output}. Unsigned comparison results ($a$ to the left of $b$). \\
+\hline \\
+1. If $a.used > b.used$ then return(\textit{MP\_GT}) \\
+2. If $a.used < b.used$ then return(\textit{MP\_LT}) \\
+3. for n from $a.used - 1$ to 0 do \\
+\hspace{+3mm}3.1 if $a_n > b_n$ then return(\textit{MP\_GT}) \\
+\hspace{+3mm}3.2 if $a_n < b_n$ then return(\textit{MP\_LT}) \\
+4. Return(\textit{MP\_EQ}) \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_cmp\_mag}
+\end{figure}
+
+\textbf{Algorithm mp\_cmp\_mag.}
+By saying ``$a$ to the left of $b$'' it is meant that the comparison is with respect to $a$, that is if $a$ is greater than $b$ it will return
+\textbf{MP\_GT} and similar with respect to when $a = b$ and $a < b$. The first two steps compare the number of digits used in both $a$ and $b$.
+Obviously if the digit counts differ there would be an imaginary zero digit in the smaller number where the leading digit of the larger number is.
+If both have the same number of digits than the actual digits themselves must be compared starting at the leading digit.
+
+By step three both inputs must have the same number of digits so its safe to start from either $a.used - 1$ or $b.used - 1$ and count down to
+the zero'th digit. If after all of the digits have been compared, no difference is found, the algorithm returns \textbf{MP\_EQ}.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_cmp\_mag.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+The two if statements (lines 25 and 29) compare the number of digits in the two inputs. These two are
+performed before all of the digits are compared since it is a very cheap test to perform and can potentially save
+considerable time. The implementation given is also not valid without those two statements. $b.alloc$ may be
+smaller than $a.used$, meaning that undefined values will be read from $b$ past the end of the array of digits.
+
+
+
+\subsection{Signed Comparisons}
+Comparing with sign considerations is also fairly critical in several routines (\textit{division for example}). Based on an unsigned magnitude
+comparison a trivial signed comparison algorithm can be written.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_cmp}. \\
+\textbf{Input}. Two mp\_ints $a$ and $b$ \\
+\textbf{Output}. Signed Comparison Results ($a$ to the left of $b$) \\
+\hline \\
+1. if $a.sign = MP\_NEG$ and $b.sign = MP\_ZPOS$ then return(\textit{MP\_LT}) \\
+2. if $a.sign = MP\_ZPOS$ and $b.sign = MP\_NEG$ then return(\textit{MP\_GT}) \\
+3. if $a.sign = MP\_NEG$ then \\
+\hspace{+3mm}3.1 Return the unsigned comparison of $b$ and $a$ (\textit{mp\_cmp\_mag}) \\
+4 Otherwise \\
+\hspace{+3mm}4.1 Return the unsigned comparison of $a$ and $b$ \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_cmp}
+\end{figure}
+
+\textbf{Algorithm mp\_cmp.}
+The first two steps compare the signs of the two inputs. If the signs do not agree then it can return right away with the appropriate
+comparison code. When the signs are equal the digits of the inputs must be compared to determine the correct result. In step
+three the unsigned comparision flips the order of the arguments since they are both negative. For instance, if $-a > -b$ then
+$\vert a \vert < \vert b \vert$. Step number four will compare the two when they are both positive.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_cmp.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+The two if statements (lines 23 and 24) perform the initial sign comparison. If the signs are not the equal then which ever
+has the positive sign is larger. The inputs are compared (line 32) based on magnitudes. If the signs were both
+negative then the unsigned comparison is performed in the opposite direction (line 34). Otherwise, the signs are assumed to
+be both positive and a forward direction unsigned comparison is performed.
+
+\section*{Exercises}
+\begin{tabular}{cl}
+$\left [ 2 \right ]$ & Modify algorithm mp\_set\_int to accept as input a variable length array of bits. \\
+ & \\
+$\left [ 3 \right ]$ & Give the probability that algorithm mp\_cmp\_mag will have to compare $k$ digits \\
+ & of two random digits (of equal magnitude) before a difference is found. \\
+ & \\
+$\left [ 1 \right ]$ & Suggest a simple method to speed up the implementation of mp\_cmp\_mag based \\
+ & on the observations made in the previous problem. \\
+ &
+\end{tabular}
+
+\chapter{Basic Arithmetic}
+\section{Introduction}
+At this point algorithms for initialization, clearing, zeroing, copying, comparing and setting small constants have been
+established. The next logical set of algorithms to develop are addition, subtraction and digit shifting algorithms. These
+algorithms make use of the lower level algorithms and are the cruicial building block for the multiplication algorithms. It is very important
+that these algorithms are highly optimized. On their own they are simple $O(n)$ algorithms but they can be called from higher level algorithms
+which easily places them at $O(n^2)$ or even $O(n^3)$ work levels.
+
+All of the algorithms within this chapter make use of the logical bit shift operations denoted by $<<$ and $>>$ for left and right
+logical shifts respectively. A logical shift is analogous to sliding the decimal point of radix-10 representations. For example, the real
+number $0.9345$ is equivalent to $93.45\%$ which is found by sliding the the decimal two places to the right (\textit{multiplying by $\beta^2 = 10^2$}).
+Algebraically a binary logical shift is equivalent to a division or multiplication by a power of two.
+For example, $a << k = a \cdot 2^k$ while $a >> k = \lfloor a/2^k \rfloor$.
+
+One significant difference between a logical shift and the way decimals are shifted is that digits below the zero'th position are removed
+from the number. For example, consider $1101_2 >> 1$ using decimal notation this would produce $110.1_2$. However, with a logical shift the
+result is $110_2$.
+
+\section{Addition and Subtraction}
+In common twos complement fixed precision arithmetic negative numbers are easily represented by subtraction from the modulus. For example, with 32-bit integers
+$a - b\mbox{ (mod }2^{32}\mbox{)}$ is the same as $a + (2^{32} - b) \mbox{ (mod }2^{32}\mbox{)}$ since $2^{32} \equiv 0 \mbox{ (mod }2^{32}\mbox{)}$.
+As a result subtraction can be performed with a trivial series of logical operations and an addition.
+
+However, in multiple precision arithmetic negative numbers are not represented in the same way. Instead a sign flag is used to keep track of the
+sign of the integer. As a result signed addition and subtraction are actually implemented as conditional usage of lower level addition or
+subtraction algorithms with the sign fixed up appropriately.
+
+The lower level algorithms will add or subtract integers without regard to the sign flag. That is they will add or subtract the magnitude of
+the integers respectively.
+
+\subsection{Low Level Addition}
+An unsigned addition of multiple precision integers is performed with the same long-hand algorithm used to add decimal numbers. That is to add the
+trailing digits first and propagate the resulting carry upwards. Since this is a lower level algorithm the name will have a ``s\_'' prefix.
+Historically that convention stems from the MPI library where ``s\_'' stood for static functions that were hidden from the developer entirely.
+
+\newpage
+\begin{figure}[!here]
+\begin{center}
+\begin{small}
+\begin{tabular}{l}
+\hline Algorithm \textbf{s\_mp\_add}. \\
+\textbf{Input}. Two mp\_ints $a$ and $b$ \\
+\textbf{Output}. The unsigned addition $c = \vert a \vert + \vert b \vert$. \\
+\hline \\
+1. if $a.used > b.used$ then \\
+\hspace{+3mm}1.1 $min \leftarrow b.used$ \\
+\hspace{+3mm}1.2 $max \leftarrow a.used$ \\
+\hspace{+3mm}1.3 $x \leftarrow a$ \\
+2. else \\
+\hspace{+3mm}2.1 $min \leftarrow a.used$ \\
+\hspace{+3mm}2.2 $max \leftarrow b.used$ \\
+\hspace{+3mm}2.3 $x \leftarrow b$ \\
+3. If $c.alloc < max + 1$ then grow $c$ to hold at least $max + 1$ digits (\textit{mp\_grow}) \\
+4. $oldused \leftarrow c.used$ \\
+5. $c.used \leftarrow max + 1$ \\
+6. $u \leftarrow 0$ \\
+7. for $n$ from $0$ to $min - 1$ do \\
+\hspace{+3mm}7.1 $c_n \leftarrow a_n + b_n + u$ \\
+\hspace{+3mm}7.2 $u \leftarrow c_n >> lg(\beta)$ \\
+\hspace{+3mm}7.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
+8. if $min \ne max$ then do \\
+\hspace{+3mm}8.1 for $n$ from $min$ to $max - 1$ do \\
+\hspace{+6mm}8.1.1 $c_n \leftarrow x_n + u$ \\
+\hspace{+6mm}8.1.2 $u \leftarrow c_n >> lg(\beta)$ \\
+\hspace{+6mm}8.1.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
+9. $c_{max} \leftarrow u$ \\
+10. if $olduse > max$ then \\
+\hspace{+3mm}10.1 for $n$ from $max + 1$ to $oldused - 1$ do \\
+\hspace{+6mm}10.1.1 $c_n \leftarrow 0$ \\
+11. Clamp excess digits in $c$. (\textit{mp\_clamp}) \\
+12. Return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{small}
+\end{center}
+\caption{Algorithm s\_mp\_add}
+\end{figure}
+
+\textbf{Algorithm s\_mp\_add.}
+This algorithm is loosely based on algorithm 14.7 of HAC \cite[pp. 594]{HAC} but has been extended to allow the inputs to have different magnitudes.
+Coincidentally the description of algorithm A in Knuth \cite[pp. 266]{TAOCPV2} shares the same deficiency as the algorithm from \cite{HAC}. Even the
+MIX pseudo machine code presented by Knuth \cite[pp. 266-267]{TAOCPV2} is incapable of handling inputs which are of different magnitudes.
+
+The first thing that has to be accomplished is to sort out which of the two inputs is the largest. The addition logic
+will simply add all of the smallest input to the largest input and store that first part of the result in the
+destination. Then it will apply a simpler addition loop to excess digits of the larger input.
+
+The first two steps will handle sorting the inputs such that $min$ and $max$ hold the digit counts of the two
+inputs. The variable $x$ will be an mp\_int alias for the largest input or the second input $b$ if they have the
+same number of digits. After the inputs are sorted the destination $c$ is grown as required to accomodate the sum
+of the two inputs. The original \textbf{used} count of $c$ is copied and set to the new used count.
+
+At this point the first addition loop will go through as many digit positions that both inputs have. The carry
+variable $\mu$ is set to zero outside the loop. Inside the loop an ``addition'' step requires three statements to produce
+one digit of the summand. First
+two digits from $a$ and $b$ are added together along with the carry $\mu$. The carry of this step is extracted and stored
+in $\mu$ and finally the digit of the result $c_n$ is truncated within the range $0 \le c_n < \beta$.
+
+Now all of the digit positions that both inputs have in common have been exhausted. If $min \ne max$ then $x$ is an alias
+for one of the inputs that has more digits. A simplified addition loop is then used to essentially copy the remaining digits
+and the carry to the destination.
+
+The final carry is stored in $c_{max}$ and digits above $max$ upto $oldused$ are zeroed which completes the addition.
+
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_s\_mp\_add.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+We first sort (lines 28 to 36) the inputs based on magnitude and determine the $min$ and $max$ variables.
+Note that $x$ is a pointer to an mp\_int assigned to the largest input, in effect it is a local alias. Next we
+grow the destination (38 to 42) ensure that it can accomodate the result of the addition.
+
+Similar to the implementation of mp\_copy this function uses the braced code and local aliases coding style. The three aliases that are on
+lines 56, 59 and 62 represent the two inputs and destination variables respectively. These aliases are used to ensure the
+compiler does not have to dereference $a$, $b$ or $c$ (respectively) to access the digits of the respective mp\_int.
+
+The initial carry $u$ will be cleared (line 65), note that $u$ is of type mp\_digit which ensures type
+compatibility within the implementation. The initial addition (line 66 to 75) adds digits from
+both inputs until the smallest input runs out of digits. Similarly the conditional addition loop
+(line 81 to 90) adds the remaining digits from the larger of the two inputs. The addition is finished
+with the final carry being stored in $tmpc$ (line 94). Note the ``++'' operator within the same expression.
+After line 94, $tmpc$ will point to the $c.used$'th digit of the mp\_int $c$. This is useful
+for the next loop (line 97 to 99) which set any old upper digits to zero.
+
+\subsection{Low Level Subtraction}
+The low level unsigned subtraction algorithm is very similar to the low level unsigned addition algorithm. The principle difference is that the
+unsigned subtraction algorithm requires the result to be positive. That is when computing $a - b$ the condition $\vert a \vert \ge \vert b\vert$ must
+be met for this algorithm to function properly. Keep in mind this low level algorithm is not meant to be used in higher level algorithms directly.
+This algorithm as will be shown can be used to create functional signed addition and subtraction algorithms.
+
+
+For this algorithm a new variable is required to make the description simpler. Recall from section 1.3.1 that a mp\_digit must be able to represent
+the range $0 \le x < 2\beta$ for the algorithms to work correctly. However, it is allowable that a mp\_digit represent a larger range of values. For
+this algorithm we will assume that the variable $\gamma$ represents the number of bits available in a
+mp\_digit (\textit{this implies $2^{\gamma} > \beta$}).
+
+For example, the default for LibTomMath is to use a ``unsigned long'' for the mp\_digit ``type'' while $\beta = 2^{28}$. In ISO C an ``unsigned long''
+data type must be able to represent $0 \le x < 2^{32}$ meaning that in this case $\gamma \ge 32$.
+
+\newpage\begin{figure}[!here]
+\begin{center}
+\begin{small}
+\begin{tabular}{l}
+\hline Algorithm \textbf{s\_mp\_sub}. \\
+\textbf{Input}. Two mp\_ints $a$ and $b$ ($\vert a \vert \ge \vert b \vert$) \\
+\textbf{Output}. The unsigned subtraction $c = \vert a \vert - \vert b \vert$. \\
+\hline \\
+1. $min \leftarrow b.used$ \\
+2. $max \leftarrow a.used$ \\
+3. If $c.alloc < max$ then grow $c$ to hold at least $max$ digits. (\textit{mp\_grow}) \\
+4. $oldused \leftarrow c.used$ \\
+5. $c.used \leftarrow max$ \\
+6. $u \leftarrow 0$ \\
+7. for $n$ from $0$ to $min - 1$ do \\
+\hspace{3mm}7.1 $c_n \leftarrow a_n - b_n - u$ \\
+\hspace{3mm}7.2 $u \leftarrow c_n >> (\gamma - 1)$ \\
+\hspace{3mm}7.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
+8. if $min < max$ then do \\
+\hspace{3mm}8.1 for $n$ from $min$ to $max - 1$ do \\
+\hspace{6mm}8.1.1 $c_n \leftarrow a_n - u$ \\
+\hspace{6mm}8.1.2 $u \leftarrow c_n >> (\gamma - 1)$ \\
+\hspace{6mm}8.1.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
+9. if $oldused > max$ then do \\
+\hspace{3mm}9.1 for $n$ from $max$ to $oldused - 1$ do \\
+\hspace{6mm}9.1.1 $c_n \leftarrow 0$ \\
+10. Clamp excess digits of $c$. (\textit{mp\_clamp}). \\
+11. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{small}
+\end{center}
+\caption{Algorithm s\_mp\_sub}
+\end{figure}
+
+\textbf{Algorithm s\_mp\_sub.}
+This algorithm performs the unsigned subtraction of two mp\_int variables under the restriction that the result must be positive. That is when
+passing variables $a$ and $b$ the condition that $\vert a \vert \ge \vert b \vert$ must be met for the algorithm to function correctly. This
+algorithm is loosely based on algorithm 14.9 \cite[pp. 595]{HAC} and is similar to algorithm S in \cite[pp. 267]{TAOCPV2} as well. As was the case
+of the algorithm s\_mp\_add both other references lack discussion concerning various practical details such as when the inputs differ in magnitude.
+
+The initial sorting of the inputs is trivial in this algorithm since $a$ is guaranteed to have at least the same magnitude of $b$. Steps 1 and 2
+set the $min$ and $max$ variables. Unlike the addition routine there is guaranteed to be no carry which means that the final result can be at
+most $max$ digits in length as opposed to $max + 1$. Similar to the addition algorithm the \textbf{used} count of $c$ is copied locally and
+set to the maximal count for the operation.
+
+The subtraction loop that begins on step seven is essentially the same as the addition loop of algorithm s\_mp\_add except single precision
+subtraction is used instead. Note the use of the $\gamma$ variable to extract the carry (\textit{also known as the borrow}) within the subtraction
+loops. Under the assumption that two's complement single precision arithmetic is used this will successfully extract the desired carry.
+
+For example, consider subtracting $0101_2$ from $0100_2$ where $\gamma = 4$ and $\beta = 2$. The least significant bit will force a carry upwards to
+the third bit which will be set to zero after the borrow. After the very first bit has been subtracted $4 - 1 \equiv 0011_2$ will remain, When the
+third bit of $0101_2$ is subtracted from the result it will cause another carry. In this case though the carry will be forced to propagate all the
+way to the most significant bit.
+
+Recall that $\beta < 2^{\gamma}$. This means that if a carry does occur just before the $lg(\beta)$'th bit it will propagate all the way to the most
+significant bit. Thus, the high order bits of the mp\_digit that are not part of the actual digit will either be all zero, or all one. All that
+is needed is a single zero or one bit for the carry. Therefore a single logical shift right by $\gamma - 1$ positions is sufficient to extract the
+carry. This method of carry extraction may seem awkward but the reason for it becomes apparent when the implementation is discussed.
+
+If $b$ has a smaller magnitude than $a$ then step 9 will force the carry and copy operation to propagate through the larger input $a$ into $c$. Step
+10 will ensure that any leading digits of $c$ above the $max$'th position are zeroed.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_s\_mp\_sub.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+Like low level addition we ``sort'' the inputs. Except in this case the sorting is hardcoded
+(lines 25 and 26). In reality the $min$ and $max$ variables are only aliases and are only
+used to make the source code easier to read. Again the pointer alias optimization is used
+within this algorithm. The aliases $tmpa$, $tmpb$ and $tmpc$ are initialized
+(lines 42, 43 and 44) for $a$, $b$ and $c$ respectively.
+
+The first subtraction loop (lines 47 through 61) subtract digits from both inputs until the smaller of
+the two inputs has been exhausted. As remarked earlier there is an implementation reason for using the ``awkward''
+method of extracting the carry (line 57). The traditional method for extracting the carry would be to shift
+by $lg(\beta)$ positions and logically AND the least significant bit. The AND operation is required because all of
+the bits above the $\lg(\beta)$'th bit will be set to one after a carry occurs from subtraction. This carry
+extraction requires two relatively cheap operations to extract the carry. The other method is to simply shift the
+most significant bit to the least significant bit thus extracting the carry with a single cheap operation. This
+optimization only works on twos compliment machines which is a safe assumption to make.
+
+If $a$ has a larger magnitude than $b$ an additional loop (lines 64 through 73) is required to propagate
+the carry through $a$ and copy the result to $c$.
+
+\subsection{High Level Addition}
+Now that both lower level addition and subtraction algorithms have been established an effective high level signed addition algorithm can be
+established. This high level addition algorithm will be what other algorithms and developers will use to perform addition of mp\_int data
+types.
+
+Recall from section 5.2 that an mp\_int represents an integer with an unsigned mantissa (\textit{the array of digits}) and a \textbf{sign}
+flag. A high level addition is actually performed as a series of eight separate cases which can be optimized down to three unique cases.
+
+\begin{figure}[!here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_add}. \\
+\textbf{Input}. Two mp\_ints $a$ and $b$ \\
+\textbf{Output}. The signed addition $c = a + b$. \\
+\hline \\
+1. if $a.sign = b.sign$ then do \\
+\hspace{3mm}1.1 $c.sign \leftarrow a.sign$ \\
+\hspace{3mm}1.2 $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add})\\
+2. else do \\
+\hspace{3mm}2.1 if $\vert a \vert < \vert b \vert$ then do (\textit{mp\_cmp\_mag}) \\
+\hspace{6mm}2.1.1 $c.sign \leftarrow b.sign$ \\
+\hspace{6mm}2.1.2 $c \leftarrow \vert b \vert - \vert a \vert$ (\textit{s\_mp\_sub}) \\
+\hspace{3mm}2.2 else do \\
+\hspace{6mm}2.2.1 $c.sign \leftarrow a.sign$ \\
+\hspace{6mm}2.2.2 $c \leftarrow \vert a \vert - \vert b \vert$ \\
+3. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_add}
+\end{figure}
+
+\textbf{Algorithm mp\_add.}
+This algorithm performs the signed addition of two mp\_int variables. There is no reference algorithm to draw upon from
+either \cite{TAOCPV2} or \cite{HAC} since they both only provide unsigned operations. The algorithm is fairly
+straightforward but restricted since subtraction can only produce positive results.
+
+\begin{figure}[here]
+\begin{small}
+\begin{center}
+\begin{tabular}{|c|c|c|c|c|}
+\hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert > \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\
+\hline $+$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\
+\hline $+$ & $+$ & No & $c = a + b$ & $a.sign$ \\
+\hline $-$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\
+\hline $-$ & $-$ & No & $c = a + b$ & $a.sign$ \\
+\hline &&&&\\
+
+\hline $+$ & $-$ & No & $c = b - a$ & $b.sign$ \\
+\hline $-$ & $+$ & No & $c = b - a$ & $b.sign$ \\
+
+\hline &&&&\\
+
+\hline $+$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\
+\hline $-$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\
+
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Addition Guide Chart}
+\label{fig:AddChart}
+\end{figure}
+
+Figure~\ref{fig:AddChart} lists all of the eight possible input combinations and is sorted to show that only three
+specific cases need to be handled. The return code of the unsigned operations at step 1.2, 2.1.2 and 2.2.2 are
+forwarded to step three to check for errors. This simplifies the description of the algorithm considerably and best
+follows how the implementation actually was achieved.
+
+Also note how the \textbf{sign} is set before the unsigned addition or subtraction is performed. Recall from the descriptions of algorithms
+s\_mp\_add and s\_mp\_sub that the mp\_clamp function is used at the end to trim excess digits. The mp\_clamp algorithm will set the \textbf{sign}
+to \textbf{MP\_ZPOS} when the \textbf{used} digit count reaches zero.
+
+For example, consider performing $-a + a$ with algorithm mp\_add. By the description of the algorithm the sign is set to \textbf{MP\_NEG} which would
+produce a result of $-0$. However, since the sign is set first then the unsigned addition is performed the subsequent usage of algorithm mp\_clamp
+within algorithm s\_mp\_add will force $-0$ to become $0$.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_add.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+The source code follows the algorithm fairly closely. The most notable new source code addition is the usage of the $res$ integer variable which
+is used to pass result of the unsigned operations forward. Unlike in the algorithm, the variable $res$ is merely returned as is without
+explicitly checking it and returning the constant \textbf{MP\_OKAY}. The observation is this algorithm will succeed or fail only if the lower
+level functions do so. Returning their return code is sufficient.
+
+\subsection{High Level Subtraction}
+The high level signed subtraction algorithm is essentially the same as the high level signed addition algorithm.
+
+\newpage\begin{figure}[!here]
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_sub}. \\
+\textbf{Input}. Two mp\_ints $a$ and $b$ \\
+\textbf{Output}. The signed subtraction $c = a - b$. \\
+\hline \\
+1. if $a.sign \ne b.sign$ then do \\
+\hspace{3mm}1.1 $c.sign \leftarrow a.sign$ \\
+\hspace{3mm}1.2 $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add}) \\
+2. else do \\
+\hspace{3mm}2.1 if $\vert a \vert \ge \vert b \vert$ then do (\textit{mp\_cmp\_mag}) \\
+\hspace{6mm}2.1.1 $c.sign \leftarrow a.sign$ \\
+\hspace{6mm}2.1.2 $c \leftarrow \vert a \vert - \vert b \vert$ (\textit{s\_mp\_sub}) \\
+\hspace{3mm}2.2 else do \\
+\hspace{6mm}2.2.1 $c.sign \leftarrow \left \lbrace \begin{array}{ll}
+ MP\_ZPOS & \mbox{if }a.sign = MP\_NEG \\
+ MP\_NEG & \mbox{otherwise} \\
+ \end{array} \right .$ \\
+\hspace{6mm}2.2.2 $c \leftarrow \vert b \vert - \vert a \vert$ \\
+3. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Algorithm mp\_sub}
+\end{figure}
+
+\textbf{Algorithm mp\_sub.}
+This algorithm performs the signed subtraction of two inputs. Similar to algorithm mp\_add there is no reference in either \cite{TAOCPV2} or
+\cite{HAC}. Also this algorithm is restricted by algorithm s\_mp\_sub. Chart \ref{fig:SubChart} lists the eight possible inputs and
+the operations required.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{|c|c|c|c|c|}
+\hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert \ge \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\
+\hline $+$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\
+\hline $+$ & $-$ & No & $c = a + b$ & $a.sign$ \\
+\hline $-$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\
+\hline $-$ & $+$ & No & $c = a + b$ & $a.sign$ \\
+\hline &&&& \\
+\hline $+$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\
+\hline $-$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\
+\hline &&&& \\
+\hline $+$ & $+$ & No & $c = b - a$ & $\mbox{opposite of }a.sign$ \\
+\hline $-$ & $-$ & No & $c = b - a$ & $\mbox{opposite of }a.sign$ \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Subtraction Guide Chart}
+\label{fig:SubChart}
+\end{figure}
+
+Similar to the case of algorithm mp\_add the \textbf{sign} is set first before the unsigned addition or subtraction. That is to prevent the
+algorithm from producing $-a - -a = -0$ as a result.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_sub.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+Much like the implementation of algorithm mp\_add the variable $res$ is used to catch the return code of the unsigned addition or subtraction operations
+and forward it to the end of the function. On line 39 the ``not equal to'' \textbf{MP\_LT} expression is used to emulate a
+``greater than or equal to'' comparison.
+
+\section{Bit and Digit Shifting}
+It is quite common to think of a multiple precision integer as a polynomial in $x$, that is $y = f(\beta)$ where $f(x) = \sum_{i=0}^{n-1} a_i x^i$.
+This notation arises within discussion of Montgomery and Diminished Radix Reduction as well as Karatsuba multiplication and squaring.
+
+In order to facilitate operations on polynomials in $x$ as above a series of simple ``digit'' algorithms have to be established. That is to shift
+the digits left or right as well to shift individual bits of the digits left and right. It is important to note that not all ``shift'' operations
+are on radix-$\beta$ digits.
+
+\subsection{Multiplication by Two}
+
+In a binary system where the radix is a power of two multiplication by two not only arises often in other algorithms it is a fairly efficient
+operation to perform. A single precision logical shift left is sufficient to multiply a single digit by two.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_mul\_2}. \\
+\textbf{Input}. One mp\_int $a$ \\
+\textbf{Output}. $b = 2a$. \\
+\hline \\
+1. If $b.alloc < a.used + 1$ then grow $b$ to hold $a.used + 1$ digits. (\textit{mp\_grow}) \\
+2. $oldused \leftarrow b.used$ \\
+3. $b.used \leftarrow a.used$ \\
+4. $r \leftarrow 0$ \\
+5. for $n$ from 0 to $a.used - 1$ do \\
+\hspace{3mm}5.1 $rr \leftarrow a_n >> (lg(\beta) - 1)$ \\
+\hspace{3mm}5.2 $b_n \leftarrow (a_n << 1) + r \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{3mm}5.3 $r \leftarrow rr$ \\
+6. If $r \ne 0$ then do \\
+\hspace{3mm}6.1 $b_{n + 1} \leftarrow r$ \\
+\hspace{3mm}6.2 $b.used \leftarrow b.used + 1$ \\
+7. If $b.used < oldused - 1$ then do \\
+\hspace{3mm}7.1 for $n$ from $b.used$ to $oldused - 1$ do \\
+\hspace{6mm}7.1.1 $b_n \leftarrow 0$ \\
+8. $b.sign \leftarrow a.sign$ \\
+9. Return(\textit{MP\_OKAY}).\\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_mul\_2}
+\end{figure}
+
+\textbf{Algorithm mp\_mul\_2.}
+This algorithm will quickly multiply a mp\_int by two provided $\beta$ is a power of two. Neither \cite{TAOCPV2} nor \cite{HAC} describe such
+an algorithm despite the fact it arises often in other algorithms. The algorithm is setup much like the lower level algorithm s\_mp\_add since
+it is for all intents and purposes equivalent to the operation $b = \vert a \vert + \vert a \vert$.
+
+Step 1 and 2 grow the input as required to accomodate the maximum number of \textbf{used} digits in the result. The initial \textbf{used} count
+is set to $a.used$ at step 4. Only if there is a final carry will the \textbf{used} count require adjustment.
+
+Step 6 is an optimization implementation of the addition loop for this specific case. That is since the two values being added together
+are the same there is no need to perform two reads from the digits of $a$. Step 6.1 performs a single precision shift on the current digit $a_n$ to
+obtain what will be the carry for the next iteration. Step 6.2 calculates the $n$'th digit of the result as single precision shift of $a_n$ plus
+the previous carry. Recall from section 4.1 that $a_n << 1$ is equivalent to $a_n \cdot 2$. An iteration of the addition loop is finished with
+forwarding the carry to the next iteration.
+
+Step 7 takes care of any final carry by setting the $a.used$'th digit of the result to the carry and augmenting the \textbf{used} count of $b$.
+Step 8 clears any leading digits of $b$ in case it originally had a larger magnitude than $a$.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_mul\_2.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+This implementation is essentially an optimized implementation of s\_mp\_add for the case of doubling an input. The only noteworthy difference
+is the use of the logical shift operator on line 52 to perform a single precision doubling.
+
+\subsection{Division by Two}
+A division by two can just as easily be accomplished with a logical shift right as multiplication by two can be with a logical shift left.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_div\_2}. \\
+\textbf{Input}. One mp\_int $a$ \\
+\textbf{Output}. $b = a/2$. \\
+\hline \\
+1. If $b.alloc < a.used$ then grow $b$ to hold $a.used$ digits. (\textit{mp\_grow}) \\
+2. If the reallocation failed return(\textit{MP\_MEM}). \\
+3. $oldused \leftarrow b.used$ \\
+4. $b.used \leftarrow a.used$ \\
+5. $r \leftarrow 0$ \\
+6. for $n$ from $b.used - 1$ to $0$ do \\
+\hspace{3mm}6.1 $rr \leftarrow a_n \mbox{ (mod }2\mbox{)}$\\
+\hspace{3mm}6.2 $b_n \leftarrow (a_n >> 1) + (r << (lg(\beta) - 1)) \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{3mm}6.3 $r \leftarrow rr$ \\
+7. If $b.used < oldused - 1$ then do \\
+\hspace{3mm}7.1 for $n$ from $b.used$ to $oldused - 1$ do \\
+\hspace{6mm}7.1.1 $b_n \leftarrow 0$ \\
+8. $b.sign \leftarrow a.sign$ \\
+9. Clamp excess digits of $b$. (\textit{mp\_clamp}) \\
+10. Return(\textit{MP\_OKAY}).\\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_div\_2}
+\end{figure}
+
+\textbf{Algorithm mp\_div\_2.}
+This algorithm will divide an mp\_int by two using logical shifts to the right. Like mp\_mul\_2 it uses a modified low level addition
+core as the basis of the algorithm. Unlike mp\_mul\_2 the shift operations work from the leading digit to the trailing digit. The algorithm
+could be written to work from the trailing digit to the leading digit however, it would have to stop one short of $a.used - 1$ digits to prevent
+reading past the end of the array of digits.
+
+Essentially the loop at step 6 is similar to that of mp\_mul\_2 except the logical shifts go in the opposite direction and the carry is at the
+least significant bit not the most significant bit.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_div\_2.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+\section{Polynomial Basis Operations}
+Recall from section 4.3 that any integer can be represented as a polynomial in $x$ as $y = f(\beta)$. Such a representation is also known as
+the polynomial basis \cite[pp. 48]{ROSE}. Given such a notation a multiplication or division by $x$ amounts to shifting whole digits a single
+place. The need for such operations arises in several other higher level algorithms such as Barrett and Montgomery reduction, integer
+division and Karatsuba multiplication.
+
+Converting from an array of digits to polynomial basis is very simple. Consider the integer $y \equiv (a_2, a_1, a_0)_{\beta}$ and recall that
+$y = \sum_{i=0}^{2} a_i \beta^i$. Simply replace $\beta$ with $x$ and the expression is in polynomial basis. For example, $f(x) = 8x + 9$ is the
+polynomial basis representation for $89$ using radix ten. That is, $f(10) = 8(10) + 9 = 89$.
+
+\subsection{Multiplication by $x$}
+
+Given a polynomial in $x$ such as $f(x) = a_n x^n + a_{n-1} x^{n-1} + ... + a_0$ multiplying by $x$ amounts to shifting the coefficients up one
+degree. In this case $f(x) \cdot x = a_n x^{n+1} + a_{n-1} x^n + ... + a_0 x$. From a scalar basis point of view multiplying by $x$ is equivalent to
+multiplying by the integer $\beta$.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_lshd}. \\
+\textbf{Input}. One mp\_int $a$ and an integer $b$ \\
+\textbf{Output}. $a \leftarrow a \cdot \beta^b$ (equivalent to multiplication by $x^b$). \\
+\hline \\
+1. If $b \le 0$ then return(\textit{MP\_OKAY}). \\
+2. If $a.alloc < a.used + b$ then grow $a$ to at least $a.used + b$ digits. (\textit{mp\_grow}). \\
+3. If the reallocation failed return(\textit{MP\_MEM}). \\
+4. $a.used \leftarrow a.used + b$ \\
+5. $i \leftarrow a.used - 1$ \\
+6. $j \leftarrow a.used - 1 - b$ \\
+7. for $n$ from $a.used - 1$ to $b$ do \\
+\hspace{3mm}7.1 $a_{i} \leftarrow a_{j}$ \\
+\hspace{3mm}7.2 $i \leftarrow i - 1$ \\
+\hspace{3mm}7.3 $j \leftarrow j - 1$ \\
+8. for $n$ from 0 to $b - 1$ do \\
+\hspace{3mm}8.1 $a_n \leftarrow 0$ \\
+9. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_lshd}
+\end{figure}
+
+\textbf{Algorithm mp\_lshd.}
+This algorithm multiplies an mp\_int by the $b$'th power of $x$. This is equivalent to multiplying by $\beta^b$. The algorithm differs
+from the other algorithms presented so far as it performs the operation in place instead storing the result in a separate location. The
+motivation behind this change is due to the way this function is typically used. Algorithms such as mp\_add store the result in an optionally
+different third mp\_int because the original inputs are often still required. Algorithm mp\_lshd (\textit{and similarly algorithm mp\_rshd}) is
+typically used on values where the original value is no longer required. The algorithm will return success immediately if
+$b \le 0$ since the rest of algorithm is only valid when $b > 0$.
+
+First the destination $a$ is grown as required to accomodate the result. The counters $i$ and $j$ are used to form a \textit{sliding window} over
+the digits of $a$ of length $b$. The head of the sliding window is at $i$ (\textit{the leading digit}) and the tail at $j$ (\textit{the trailing digit}).
+The loop on step 7 copies the digit from the tail to the head. In each iteration the window is moved down one digit. The last loop on
+step 8 sets the lower $b$ digits to zero.
+
+\newpage
+\begin{center}
+\begin{figure}[here]
+\includegraphics{pics/sliding_window.ps}
+\caption{Sliding Window Movement}
+\label{pic:sliding_window}
+\end{figure}
+\end{center}
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_lshd.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+The if statement (line 24) ensures that the $b$ variable is greater than zero since we do not interpret negative
+shift counts properly. The \textbf{used} count is incremented by $b$ before the copy loop begins. This elminates
+the need for an additional variable in the for loop. The variable $top$ (line 42) is an alias
+for the leading digit while $bottom$ (line 45) is an alias for the trailing edge. The aliases form a
+window of exactly $b$ digits over the input.
+
+\subsection{Division by $x$}
+
+Division by powers of $x$ is easily achieved by shifting the digits right and removing any that will end up to the right of the zero'th digit.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_rshd}. \\
+\textbf{Input}. One mp\_int $a$ and an integer $b$ \\
+\textbf{Output}. $a \leftarrow a / \beta^b$ (Divide by $x^b$). \\
+\hline \\
+1. If $b \le 0$ then return. \\
+2. If $a.used \le b$ then do \\
+\hspace{3mm}2.1 Zero $a$. (\textit{mp\_zero}). \\
+\hspace{3mm}2.2 Return. \\
+3. $i \leftarrow 0$ \\
+4. $j \leftarrow b$ \\
+5. for $n$ from 0 to $a.used - b - 1$ do \\
+\hspace{3mm}5.1 $a_i \leftarrow a_j$ \\
+\hspace{3mm}5.2 $i \leftarrow i + 1$ \\
+\hspace{3mm}5.3 $j \leftarrow j + 1$ \\
+6. for $n$ from $a.used - b$ to $a.used - 1$ do \\
+\hspace{3mm}6.1 $a_n \leftarrow 0$ \\
+7. $a.used \leftarrow a.used - b$ \\
+8. Return. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_rshd}
+\end{figure}
+
+\textbf{Algorithm mp\_rshd.}
+This algorithm divides the input in place by the $b$'th power of $x$. It is analogous to dividing by a $\beta^b$ but much quicker since
+it does not require single precision division. This algorithm does not actually return an error code as it cannot fail.
+
+If the input $b$ is less than one the algorithm quickly returns without performing any work. If the \textbf{used} count is less than or equal
+to the shift count $b$ then it will simply zero the input and return.
+
+After the trivial cases of inputs have been handled the sliding window is setup. Much like the case of algorithm mp\_lshd a sliding window that
+is $b$ digits wide is used to copy the digits. Unlike mp\_lshd the window slides in the opposite direction from the trailing to the leading digit.
+Also the digits are copied from the leading to the trailing edge.
+
+Once the window copy is complete the upper digits must be zeroed and the \textbf{used} count decremented.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_rshd.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+The only noteworthy element of this routine is the lack of a return type since it cannot fail. Like mp\_lshd() we
+form a sliding window except we copy in the other direction. After the window (line 60) we then zero
+the upper digits of the input to make sure the result is correct.
+
+\section{Powers of Two}
+
+Now that algorithms for moving single bits as well as whole digits exist algorithms for moving the ``in between'' distances are required. For
+example, to quickly multiply by $2^k$ for any $k$ without using a full multiplier algorithm would prove useful. Instead of performing single
+shifts $k$ times to achieve a multiplication by $2^{\pm k}$ a mixture of whole digit shifting and partial digit shifting is employed.
+
+\subsection{Multiplication by Power of Two}
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_mul\_2d}. \\
+\textbf{Input}. One mp\_int $a$ and an integer $b$ \\
+\textbf{Output}. $c \leftarrow a \cdot 2^b$. \\
+\hline \\
+1. $c \leftarrow a$. (\textit{mp\_copy}) \\
+2. If $c.alloc < c.used + \lfloor b / lg(\beta) \rfloor + 2$ then grow $c$ accordingly. \\
+3. If the reallocation failed return(\textit{MP\_MEM}). \\
+4. If $b \ge lg(\beta)$ then \\
+\hspace{3mm}4.1 $c \leftarrow c \cdot \beta^{\lfloor b / lg(\beta) \rfloor}$ (\textit{mp\_lshd}). \\
+\hspace{3mm}4.2 If step 4.1 failed return(\textit{MP\_MEM}). \\
+5. $d \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
+6. If $d \ne 0$ then do \\
+\hspace{3mm}6.1 $mask \leftarrow 2^d$ \\
+\hspace{3mm}6.2 $r \leftarrow 0$ \\
+\hspace{3mm}6.3 for $n$ from $0$ to $c.used - 1$ do \\
+\hspace{6mm}6.3.1 $rr \leftarrow c_n >> (lg(\beta) - d) \mbox{ (mod }mask\mbox{)}$ \\
+\hspace{6mm}6.3.2 $c_n \leftarrow (c_n << d) + r \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{6mm}6.3.3 $r \leftarrow rr$ \\
+\hspace{3mm}6.4 If $r > 0$ then do \\
+\hspace{6mm}6.4.1 $c_{c.used} \leftarrow r$ \\
+\hspace{6mm}6.4.2 $c.used \leftarrow c.used + 1$ \\
+7. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_mul\_2d}
+\end{figure}
+
+\textbf{Algorithm mp\_mul\_2d.}
+This algorithm multiplies $a$ by $2^b$ and stores the result in $c$. The algorithm uses algorithm mp\_lshd and a derivative of algorithm mp\_mul\_2 to
+quickly compute the product.
+
+First the algorithm will multiply $a$ by $x^{\lfloor b / lg(\beta) \rfloor}$ which will ensure that the remainder multiplicand is less than
+$\beta$. For example, if $b = 37$ and $\beta = 2^{28}$ then this step will multiply by $x$ leaving a multiplication by $2^{37 - 28} = 2^{9}$
+left.
+
+After the digits have been shifted appropriately at most $lg(\beta) - 1$ shifts are left to perform. Step 5 calculates the number of remaining shifts
+required. If it is non-zero a modified shift loop is used to calculate the remaining product.
+Essentially the loop is a generic version of algorithm mp\_mul\_2 designed to handle any shift count in the range $1 \le x < lg(\beta)$. The $mask$
+variable is used to extract the upper $d$ bits to form the carry for the next iteration.
+
+This algorithm is loosely measured as a $O(2n)$ algorithm which means that if the input is $n$-digits that it takes $2n$ ``time'' to
+complete. It is possible to optimize this algorithm down to a $O(n)$ algorithm at a cost of making the algorithm slightly harder to follow.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_mul\_2d.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+The shifting is performed in--place which means the first step (line 25) is to copy the input to the
+destination. We avoid calling mp\_copy() by making sure the mp\_ints are different. The destination then
+has to be grown (line 32) to accomodate the result.
+
+If the shift count $b$ is larger than $lg(\beta)$ then a call to mp\_lshd() is used to handle all of the multiples
+of $lg(\beta)$. Leaving only a remaining shift of $lg(\beta) - 1$ or fewer bits left. Inside the actual shift
+loop (lines 46 to 76) we make use of pre--computed values $shift$ and $mask$. These are used to
+extract the carry bit(s) to pass into the next iteration of the loop. The $r$ and $rr$ variables form a
+chain between consecutive iterations to propagate the carry.
+
+\subsection{Division by Power of Two}
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_div\_2d}. \\
+\textbf{Input}. One mp\_int $a$ and an integer $b$ \\
+\textbf{Output}. $c \leftarrow \lfloor a / 2^b \rfloor, d \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\
+\hline \\
+1. If $b \le 0$ then do \\
+\hspace{3mm}1.1 $c \leftarrow a$ (\textit{mp\_copy}) \\
+\hspace{3mm}1.2 $d \leftarrow 0$ (\textit{mp\_zero}) \\
+\hspace{3mm}1.3 Return(\textit{MP\_OKAY}). \\
+2. $c \leftarrow a$ \\
+3. $d \leftarrow a \mbox{ (mod }2^b\mbox{)}$ (\textit{mp\_mod\_2d}) \\
+4. If $b \ge lg(\beta)$ then do \\
+\hspace{3mm}4.1 $c \leftarrow \lfloor c/\beta^{\lfloor b/lg(\beta) \rfloor} \rfloor$ (\textit{mp\_rshd}). \\
+5. $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
+6. If $k \ne 0$ then do \\
+\hspace{3mm}6.1 $mask \leftarrow 2^k$ \\
+\hspace{3mm}6.2 $r \leftarrow 0$ \\
+\hspace{3mm}6.3 for $n$ from $c.used - 1$ to $0$ do \\
+\hspace{6mm}6.3.1 $rr \leftarrow c_n \mbox{ (mod }mask\mbox{)}$ \\
+\hspace{6mm}6.3.2 $c_n \leftarrow (c_n >> k) + (r << (lg(\beta) - k))$ \\
+\hspace{6mm}6.3.3 $r \leftarrow rr$ \\
+7. Clamp excess digits of $c$. (\textit{mp\_clamp}) \\
+8. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_div\_2d}
+\end{figure}
+
+\textbf{Algorithm mp\_div\_2d.}
+This algorithm will divide an input $a$ by $2^b$ and produce the quotient and remainder. The algorithm is designed much like algorithm
+mp\_mul\_2d by first using whole digit shifts then single precision shifts. This algorithm will also produce the remainder of the division
+by using algorithm mp\_mod\_2d.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_div\_2d.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+The implementation of algorithm mp\_div\_2d is slightly different than the algorithm specifies. The remainder $d$ may be optionally
+ignored by passing \textbf{NULL} as the pointer to the mp\_int variable. The temporary mp\_int variable $t$ is used to hold the
+result of the remainder operation until the end. This allows $d$ and $a$ to represent the same mp\_int without modifying $a$ before
+the quotient is obtained.
+
+The remainder of the source code is essentially the same as the source code for mp\_mul\_2d. The only significant difference is
+the direction of the shifts.
+
+\subsection{Remainder of Division by Power of Two}
+
+The last algorithm in the series of polynomial basis power of two algorithms is calculating the remainder of division by $2^b$. This
+algorithm benefits from the fact that in twos complement arithmetic $a \mbox{ (mod }2^b\mbox{)}$ is the same as $a$ AND $2^b - 1$.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_mod\_2d}. \\
+\textbf{Input}. One mp\_int $a$ and an integer $b$ \\
+\textbf{Output}. $c \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\
+\hline \\
+1. If $b \le 0$ then do \\
+\hspace{3mm}1.1 $c \leftarrow 0$ (\textit{mp\_zero}) \\
+\hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\
+2. If $b > a.used \cdot lg(\beta)$ then do \\
+\hspace{3mm}2.1 $c \leftarrow a$ (\textit{mp\_copy}) \\
+\hspace{3mm}2.2 Return the result of step 2.1. \\
+3. $c \leftarrow a$ \\
+4. If step 3 failed return(\textit{MP\_MEM}). \\
+5. for $n$ from $\lceil b / lg(\beta) \rceil$ to $c.used$ do \\
+\hspace{3mm}5.1 $c_n \leftarrow 0$ \\
+6. $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
+7. $c_{\lfloor b / lg(\beta) \rfloor} \leftarrow c_{\lfloor b / lg(\beta) \rfloor} \mbox{ (mod }2^{k}\mbox{)}$. \\
+8. Clamp excess digits of $c$. (\textit{mp\_clamp}) \\
+9. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_mod\_2d}
+\end{figure}
+
+\textbf{Algorithm mp\_mod\_2d.}
+This algorithm will quickly calculate the value of $a \mbox{ (mod }2^b\mbox{)}$. First if $b$ is less than or equal to zero the
+result is set to zero. If $b$ is greater than the number of bits in $a$ then it simply copies $a$ to $c$ and returns. Otherwise, $a$
+is copied to $b$, leading digits are removed and the remaining leading digit is trimed to the exact bit count.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_mod\_2d.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+We first avoid cases of $b \le 0$ by simply mp\_zero()'ing the destination in such cases. Next if $2^b$ is larger
+than the input we just mp\_copy() the input and return right away. After this point we know we must actually
+perform some work to produce the remainder.
+
+Recalling that reducing modulo $2^k$ and a binary ``and'' with $2^k - 1$ are numerically equivalent we can quickly reduce
+the number. First we zero any digits above the last digit in $2^b$ (line 42). Next we reduce the
+leading digit of both (line 46) and then mp\_clamp().
+
+\section*{Exercises}
+\begin{tabular}{cl}
+$\left [ 3 \right ] $ & Devise an algorithm that performs $a \cdot 2^b$ for generic values of $b$ \\
+ & in $O(n)$ time. \\
+ &\\
+$\left [ 3 \right ] $ & Devise an efficient algorithm to multiply by small low hamming \\
+ & weight values such as $3$, $5$ and $9$. Extend it to handle all values \\
+ & upto $64$ with a hamming weight less than three. \\
+ &\\
+$\left [ 2 \right ] $ & Modify the preceding algorithm to handle values of the form \\
+ & $2^k - 1$ as well. \\
+ &\\
+$\left [ 3 \right ] $ & Using only algorithms mp\_mul\_2, mp\_div\_2 and mp\_add create an \\
+ & algorithm to multiply two integers in roughly $O(2n^2)$ time for \\
+ & any $n$-bit input. Note that the time of addition is ignored in the \\
+ & calculation. \\
+ & \\
+$\left [ 5 \right ] $ & Improve the previous algorithm to have a working time of at most \\
+ & $O \left (2^{(k-1)}n + \left ({2n^2 \over k} \right ) \right )$ for an appropriate choice of $k$. Again ignore \\
+ & the cost of addition. \\
+ & \\
+$\left [ 2 \right ] $ & Devise a chart to find optimal values of $k$ for the previous problem \\
+ & for $n = 64 \ldots 1024$ in steps of $64$. \\
+ & \\
+$\left [ 2 \right ] $ & Using only algorithms mp\_abs and mp\_sub devise another method for \\
+ & calculating the result of a signed comparison. \\
+ &
+\end{tabular}
+
+\chapter{Multiplication and Squaring}
+\section{The Multipliers}
+For most number theoretic problems including certain public key cryptographic algorithms, the ``multipliers'' form the most important subset of
+algorithms of any multiple precision integer package. The set of multiplier algorithms include integer multiplication, squaring and modular reduction
+where in each of the algorithms single precision multiplication is the dominant operation performed. This chapter will discuss integer multiplication
+and squaring, leaving modular reductions for the subsequent chapter.
+
+The importance of the multiplier algorithms is for the most part driven by the fact that certain popular public key algorithms are based on modular
+exponentiation, that is computing $d \equiv a^b \mbox{ (mod }c\mbox{)}$ for some arbitrary choice of $a$, $b$, $c$ and $d$. During a modular
+exponentiation the majority\footnote{Roughly speaking a modular exponentiation will spend about 40\% of the time performing modular reductions,
+35\% of the time performing squaring and 25\% of the time performing multiplications.} of the processor time is spent performing single precision
+multiplications.
+
+For centuries general purpose multiplication has required a lengthly $O(n^2)$ process, whereby each digit of one multiplicand has to be multiplied
+against every digit of the other multiplicand. Traditional long-hand multiplication is based on this process; while the techniques can differ the
+overall algorithm used is essentially the same. Only ``recently'' have faster algorithms been studied. First Karatsuba multiplication was discovered in
+1962. This algorithm can multiply two numbers with considerably fewer single precision multiplications when compared to the long-hand approach.
+This technique led to the discovery of polynomial basis algorithms (\textit{good reference?}) and subquently Fourier Transform based solutions.
+
+\section{Multiplication}
+\subsection{The Baseline Multiplication}
+\label{sec:basemult}
+\index{baseline multiplication}
+Computing the product of two integers in software can be achieved using a trivial adaptation of the standard $O(n^2)$ long-hand multiplication
+algorithm that school children are taught. The algorithm is considered an $O(n^2)$ algorithm since for two $n$-digit inputs $n^2$ single precision
+multiplications are required. More specifically for a $m$ and $n$ digit input $m \cdot n$ single precision multiplications are required. To
+simplify most discussions, it will be assumed that the inputs have comparable number of digits.
+
+The ``baseline multiplication'' algorithm is designed to act as the ``catch-all'' algorithm, only to be used when the faster algorithms cannot be
+used. This algorithm does not use any particularly interesting optimizations and should ideally be avoided if possible. One important
+facet of this algorithm, is that it has been modified to only produce a certain amount of output digits as resolution. The importance of this
+modification will become evident during the discussion of Barrett modular reduction. Recall that for a $n$ and $m$ digit input the product
+will be at most $n + m$ digits. Therefore, this algorithm can be reduced to a full multiplier by having it produce $n + m$ digits of the product.
+
+Recall from sub-section 4.2.2 the definition of $\gamma$ as the number of bits in the type \textbf{mp\_digit}. We shall now extend the variable set to
+include $\alpha$ which shall represent the number of bits in the type \textbf{mp\_word}. This implies that $2^{\alpha} > 2 \cdot \beta^2$. The
+constant $\delta = 2^{\alpha - 2lg(\beta)}$ will represent the maximal weight of any column in a product (\textit{see sub-section 5.2.2 for more information}).
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{s\_mp\_mul\_digs}. \\
+\textbf{Input}. mp\_int $a$, mp\_int $b$ and an integer $digs$ \\
+\textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\
+\hline \\
+1. If min$(a.used, b.used) < \delta$ then do \\
+\hspace{3mm}1.1 Calculate $c = \vert a \vert \cdot \vert b \vert$ by the Comba method (\textit{see algorithm~\ref{fig:COMBAMULT}}). \\
+\hspace{3mm}1.2 Return the result of step 1.1 \\
+\\
+Allocate and initialize a temporary mp\_int. \\
+2. Init $t$ to be of size $digs$ \\
+3. If step 2 failed return(\textit{MP\_MEM}). \\
+4. $t.used \leftarrow digs$ \\
+\\
+Compute the product. \\
+5. for $ix$ from $0$ to $a.used - 1$ do \\
+\hspace{3mm}5.1 $u \leftarrow 0$ \\
+\hspace{3mm}5.2 $pb \leftarrow \mbox{min}(b.used, digs - ix)$ \\
+\hspace{3mm}5.3 If $pb < 1$ then goto step 6. \\
+\hspace{3mm}5.4 for $iy$ from $0$ to $pb - 1$ do \\
+\hspace{6mm}5.4.1 $\hat r \leftarrow t_{iy + ix} + a_{ix} \cdot b_{iy} + u$ \\
+\hspace{6mm}5.4.2 $t_{iy + ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{6mm}5.4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
+\hspace{3mm}5.5 if $ix + pb < digs$ then do \\
+\hspace{6mm}5.5.1 $t_{ix + pb} \leftarrow u$ \\
+6. Clamp excess digits of $t$. \\
+7. Swap $c$ with $t$ \\
+8. Clear $t$ \\
+9. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm s\_mp\_mul\_digs}
+\end{figure}
+
+\textbf{Algorithm s\_mp\_mul\_digs.}
+This algorithm computes the unsigned product of two inputs $a$ and $b$, limited to an output precision of $digs$ digits. While it may seem
+a bit awkward to modify the function from its simple $O(n^2)$ description, the usefulness of partial multipliers will arise in a subsequent
+algorithm. The algorithm is loosely based on algorithm 14.12 from \cite[pp. 595]{HAC} and is similar to Algorithm M of Knuth \cite[pp. 268]{TAOCPV2}.
+Algorithm s\_mp\_mul\_digs differs from these cited references since it can produce a variable output precision regardless of the precision of the
+inputs.
+
+The first thing this algorithm checks for is whether a Comba multiplier can be used instead. If the minimum digit count of either
+input is less than $\delta$, then the Comba method may be used instead. After the Comba method is ruled out, the baseline algorithm begins. A
+temporary mp\_int variable $t$ is used to hold the intermediate result of the product. This allows the algorithm to be used to
+compute products when either $a = c$ or $b = c$ without overwriting the inputs.
+
+All of step 5 is the infamous $O(n^2)$ multiplication loop slightly modified to only produce upto $digs$ digits of output. The $pb$ variable
+is given the count of digits to read from $b$ inside the nested loop. If $pb \le 1$ then no more output digits can be produced and the algorithm
+will exit the loop. The best way to think of the loops are as a series of $pb \times 1$ multiplications. That is, in each pass of the
+innermost loop $a_{ix}$ is multiplied against $b$ and the result is added (\textit{with an appropriate shift}) to $t$.
+
+For example, consider multiplying $576$ by $241$. That is equivalent to computing $10^0(1)(576) + 10^1(4)(576) + 10^2(2)(576)$ which is best
+visualized in the following table.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{|c|c|c|c|c|c|l|}
+\hline && & 5 & 7 & 6 & \\
+\hline $\times$&& & 2 & 4 & 1 & \\
+\hline &&&&&&\\
+ && & 5 & 7 & 6 & $10^0(1)(576)$ \\
+ &2 & 3 & 6 & 1 & 6 & $10^1(4)(576) + 10^0(1)(576)$ \\
+ 1 & 3 & 8 & 8 & 1 & 6 & $10^2(2)(576) + 10^1(4)(576) + 10^0(1)(576)$ \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Long-Hand Multiplication Diagram}
+\end{figure}
+
+Each row of the product is added to the result after being shifted to the left (\textit{multiplied by a power of the radix}) by the appropriate
+count. That is in pass $ix$ of the inner loop the product is added starting at the $ix$'th digit of the reult.
+
+Step 5.4.1 introduces the hat symbol (\textit{e.g. $\hat r$}) which represents a double precision variable. The multiplication on that step
+is assumed to be a double wide output single precision multiplication. That is, two single precision variables are multiplied to produce a
+double precision result. The step is somewhat optimized from a long-hand multiplication algorithm because the carry from the addition in step
+5.4.1 is propagated through the nested loop. If the carry was not propagated immediately it would overflow the single precision digit
+$t_{ix+iy}$ and the result would be lost.
+
+At step 5.5 the nested loop is finished and any carry that was left over should be forwarded. The carry does not have to be added to the $ix+pb$'th
+digit since that digit is assumed to be zero at this point. However, if $ix + pb \ge digs$ the carry is not set as it would make the result
+exceed the precision requested.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_s\_mp\_mul\_digs.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+First we determine (line 31) if the Comba method can be used first since it's faster. The conditions for
+sing the Comba routine are that min$(a.used, b.used) < \delta$ and the number of digits of output is less than
+\textbf{MP\_WARRAY}. This new constant is used to control the stack usage in the Comba routines. By default it is
+set to $\delta$ but can be reduced when memory is at a premium.
+
+If we cannot use the Comba method we proceed to setup the baseline routine. We allocate the the destination mp\_int
+$t$ (line 37) to the exact size of the output to avoid further re--allocations. At this point we now
+begin the $O(n^2)$ loop.
+
+This implementation of multiplication has the caveat that it can be trimmed to only produce a variable number of
+digits as output. In each iteration of the outer loop the $pb$ variable is set (line 49) to the maximum
+number of inner loop iterations.
+
+Inside the inner loop we calculate $\hat r$ as the mp\_word product of the two mp\_digits and the addition of the
+carry from the previous iteration. A particularly important observation is that most modern optimizing
+C compilers (GCC for instance) can recognize that a $N \times N \rightarrow 2N$ multiplication is all that
+is required for the product. In x86 terms for example, this means using the MUL instruction.
+
+Each digit of the product is stored in turn (line 69) and the carry propagated (line 72) to the
+next iteration.
+
+\subsection{Faster Multiplication by the ``Comba'' Method}
+
+One of the huge drawbacks of the ``baseline'' algorithms is that at the $O(n^2)$ level the carry must be
+computed and propagated upwards. This makes the nested loop very sequential and hard to unroll and implement
+in parallel. The ``Comba'' \cite{COMBA} method is named after little known (\textit{in cryptographic venues}) Paul G.
+Comba who described a method of implementing fast multipliers that do not require nested carry fixup operations. As an
+interesting aside it seems that Paul Barrett describes a similar technique in his 1986 paper \cite{BARRETT} written
+five years before.
+
+At the heart of the Comba technique is once again the long-hand algorithm. Except in this case a slight
+twist is placed on how the columns of the result are produced. In the standard long-hand algorithm rows of products
+are produced then added together to form the final result. In the baseline algorithm the columns are added together
+after each iteration to get the result instantaneously.
+
+In the Comba algorithm the columns of the result are produced entirely independently of each other. That is at
+the $O(n^2)$ level a simple multiplication and addition step is performed. The carries of the columns are propagated
+after the nested loop to reduce the amount of work requiored. Succintly the first step of the algorithm is to compute
+the product vector $\vec x$ as follows.
+
+\begin{equation}
+\vec x_n = \sum_{i+j = n} a_ib_j, \forall n \in \lbrace 0, 1, 2, \ldots, i + j \rbrace
+\end{equation}
+
+Where $\vec x_n$ is the $n'th$ column of the output vector. Consider the following example which computes the vector $\vec x$ for the multiplication
+of $576$ and $241$.
+
+\newpage\begin{figure}[here]
+\begin{small}
+\begin{center}
+\begin{tabular}{|c|c|c|c|c|c|}
+ \hline & & 5 & 7 & 6 & First Input\\
+ \hline $\times$ & & 2 & 4 & 1 & Second Input\\
+\hline & & $1 \cdot 5 = 5$ & $1 \cdot 7 = 7$ & $1 \cdot 6 = 6$ & First pass \\
+ & $4 \cdot 5 = 20$ & $4 \cdot 7+5=33$ & $4 \cdot 6+7=31$ & 6 & Second pass \\
+ $2 \cdot 5 = 10$ & $2 \cdot 7 + 20 = 34$ & $2 \cdot 6+33=45$ & 31 & 6 & Third pass \\
+\hline 10 & 34 & 45 & 31 & 6 & Final Result \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Comba Multiplication Diagram}
+\end{figure}
+
+At this point the vector $x = \left < 10, 34, 45, 31, 6 \right >$ is the result of the first step of the Comba multipler.
+Now the columns must be fixed by propagating the carry upwards. The resultant vector will have one extra dimension over the input vector which is
+congruent to adding a leading zero digit.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Comba Fixup}. \\
+\textbf{Input}. Vector $\vec x$ of dimension $k$ \\
+\textbf{Output}. Vector $\vec x$ such that the carries have been propagated. \\
+\hline \\
+1. for $n$ from $0$ to $k - 1$ do \\
+\hspace{3mm}1.1 $\vec x_{n+1} \leftarrow \vec x_{n+1} + \lfloor \vec x_{n}/\beta \rfloor$ \\
+\hspace{3mm}1.2 $\vec x_{n} \leftarrow \vec x_{n} \mbox{ (mod }\beta\mbox{)}$ \\
+2. Return($\vec x$). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm Comba Fixup}
+\end{figure}
+
+With that algorithm and $k = 5$ and $\beta = 10$ the following vector is produced $\vec x= \left < 1, 3, 8, 8, 1, 6 \right >$. In this case
+$241 \cdot 576$ is in fact $138816$ and the procedure succeeded. If the algorithm is correct and as will be demonstrated shortly more
+efficient than the baseline algorithm why not simply always use this algorithm?
+
+\subsubsection{Column Weight.}
+At the nested $O(n^2)$ level the Comba method adds the product of two single precision variables to each column of the output
+independently. A serious obstacle is if the carry is lost, due to lack of precision before the algorithm has a chance to fix
+the carries. For example, in the multiplication of two three-digit numbers the third column of output will be the sum of
+three single precision multiplications. If the precision of the accumulator for the output digits is less then $3 \cdot (\beta - 1)^2$ then
+an overflow can occur and the carry information will be lost. For any $m$ and $n$ digit inputs the maximum weight of any column is
+min$(m, n)$ which is fairly obvious.
+
+The maximum number of terms in any column of a product is known as the ``column weight'' and strictly governs when the algorithm can be used. Recall
+from earlier that a double precision type has $\alpha$ bits of resolution and a single precision digit has $lg(\beta)$ bits of precision. Given these
+two quantities we must not violate the following
+
+\begin{equation}
+k \cdot \left (\beta - 1 \right )^2 < 2^{\alpha}
+\end{equation}
+
+Which reduces to
+
+\begin{equation}
+k \cdot \left ( \beta^2 - 2\beta + 1 \right ) < 2^{\alpha}
+\end{equation}
+
+Let $\rho = lg(\beta)$ represent the number of bits in a single precision digit. By further re-arrangement of the equation the final solution is
+found.
+
+\begin{equation}
+k < {{2^{\alpha}} \over {\left (2^{2\rho} - 2^{\rho + 1} + 1 \right )}}
+\end{equation}
+
+The defaults for LibTomMath are $\beta = 2^{28}$ and $\alpha = 2^{64}$ which means that $k$ is bounded by $k < 257$. In this configuration
+the smaller input may not have more than $256$ digits if the Comba method is to be used. This is quite satisfactory for most applications since
+$256$ digits would allow for numbers in the range of $0 \le x < 2^{7168}$ which, is much larger than most public key cryptographic algorithms require.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{fast\_s\_mp\_mul\_digs}. \\
+\textbf{Input}. mp\_int $a$, mp\_int $b$ and an integer $digs$ \\
+\textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\
+\hline \\
+Place an array of \textbf{MP\_WARRAY} single precision digits named $W$ on the stack. \\
+1. If $c.alloc < digs$ then grow $c$ to $digs$ digits. (\textit{mp\_grow}) \\
+2. If step 1 failed return(\textit{MP\_MEM}).\\
+\\
+3. $pa \leftarrow \mbox{MIN}(digs, a.used + b.used)$ \\
+\\
+4. $\_ \hat W \leftarrow 0$ \\
+5. for $ix$ from 0 to $pa - 1$ do \\
+\hspace{3mm}5.1 $ty \leftarrow \mbox{MIN}(b.used - 1, ix)$ \\
+\hspace{3mm}5.2 $tx \leftarrow ix - ty$ \\
+\hspace{3mm}5.3 $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\
+\hspace{3mm}5.4 for $iz$ from 0 to $iy - 1$ do \\
+\hspace{6mm}5.4.1 $\_ \hat W \leftarrow \_ \hat W + a_{tx+iy}b_{ty-iy}$ \\
+\hspace{3mm}5.5 $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$\\
+\hspace{3mm}5.6 $\_ \hat W \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\
+\\
+6. $oldused \leftarrow c.used$ \\
+7. $c.used \leftarrow digs$ \\
+8. for $ix$ from $0$ to $pa$ do \\
+\hspace{3mm}8.1 $c_{ix} \leftarrow W_{ix}$ \\
+9. for $ix$ from $pa + 1$ to $oldused - 1$ do \\
+\hspace{3mm}9.1 $c_{ix} \leftarrow 0$ \\
+\\
+10. Clamp $c$. \\
+11. Return MP\_OKAY. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm fast\_s\_mp\_mul\_digs}
+\label{fig:COMBAMULT}
+\end{figure}
+
+\textbf{Algorithm fast\_s\_mp\_mul\_digs.}
+This algorithm performs the unsigned multiplication of $a$ and $b$ using the Comba method limited to $digs$ digits of precision.
+
+The outer loop of this algorithm is more complicated than that of the baseline multiplier. This is because on the inside of the
+loop we want to produce one column per pass. This allows the accumulator $\_ \hat W$ to be placed in CPU registers and
+reduce the memory bandwidth to two \textbf{mp\_digit} reads per iteration.
+
+The $ty$ variable is set to the minimum count of $ix$ or the number of digits in $b$. That way if $a$ has more digits than
+$b$ this will be limited to $b.used - 1$. The $tx$ variable is set to the to the distance past $b.used$ the variable
+$ix$ is. This is used for the immediately subsequent statement where we find $iy$.
+
+The variable $iy$ is the minimum digits we can read from either $a$ or $b$ before running out. Computing one column at a time
+means we have to scan one integer upwards and the other downwards. $a$ starts at $tx$ and $b$ starts at $ty$. In each
+pass we are producing the $ix$'th output column and we note that $tx + ty = ix$. As we move $tx$ upwards we have to
+move $ty$ downards so the equality remains valid. The $iy$ variable is the number of iterations until
+$tx \ge a.used$ or $ty < 0$ occurs.
+
+After every inner pass we store the lower half of the accumulator into $W_{ix}$ and then propagate the carry of the accumulator
+into the next round by dividing $\_ \hat W$ by $\beta$.
+
+To measure the benefits of the Comba method over the baseline method consider the number of operations that are required. If the
+cost in terms of time of a multiply and addition is $p$ and the cost of a carry propagation is $q$ then a baseline multiplication would require
+$O \left ((p + q)n^2 \right )$ time to multiply two $n$-digit numbers. The Comba method requires only $O(pn^2 + qn)$ time, however in practice,
+the speed increase is actually much more. With $O(n)$ space the algorithm can be reduced to $O(pn + qn)$ time by implementing the $n$ multiply
+and addition operations in the nested loop in parallel.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_fast\_s\_mp\_mul\_digs.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+As per the pseudo--code we first calculate $pa$ (line 48) as the number of digits to output. Next we begin the outer loop
+to produce the individual columns of the product. We use the two aliases $tmpx$ and $tmpy$ (lines 62, 63) to point
+inside the two multiplicands quickly.
+
+The inner loop (lines 71 to 74) of this implementation is where the tradeoff come into play. Originally this comba
+implementation was ``row--major'' which means it adds to each of the columns in each pass. After the outer loop it would then fix
+the carries. This was very fast except it had an annoying drawback. You had to read a mp\_word and two mp\_digits and write
+one mp\_word per iteration. On processors such as the Athlon XP and P4 this did not matter much since the cache bandwidth
+is very high and it can keep the ALU fed with data. It did, however, matter on older and embedded cpus where cache is often
+slower and also often doesn't exist. This new algorithm only performs two reads per iteration under the assumption that the
+compiler has aliased $\_ \hat W$ to a CPU register.
+
+After the inner loop we store the current accumulator in $W$ and shift $\_ \hat W$ (lines 77, 80) to forward it as
+a carry for the next pass. After the outer loop we use the final carry (line 77) as the last digit of the product.
+
+\subsection{Polynomial Basis Multiplication}
+To break the $O(n^2)$ barrier in multiplication requires a completely different look at integer multiplication. In the following algorithms
+the use of polynomial basis representation for two integers $a$ and $b$ as $f(x) = \sum_{i=0}^{n} a_i x^i$ and
+$g(x) = \sum_{i=0}^{n} b_i x^i$ respectively, is required. In this system both $f(x)$ and $g(x)$ have $n + 1$ terms and are of the $n$'th degree.
+
+The product $a \cdot b \equiv f(x)g(x)$ is the polynomial $W(x) = \sum_{i=0}^{2n} w_i x^i$. The coefficients $w_i$ will
+directly yield the desired product when $\beta$ is substituted for $x$. The direct solution to solve for the $2n + 1$ coefficients
+requires $O(n^2)$ time and would in practice be slower than the Comba technique.
+
+However, numerical analysis theory indicates that only $2n + 1$ distinct points in $W(x)$ are required to determine the values of the $2n + 1$ unknown
+coefficients. This means by finding $\zeta_y = W(y)$ for $2n + 1$ small values of $y$ the coefficients of $W(x)$ can be found with
+Gaussian elimination. This technique is also occasionally refered to as the \textit{interpolation technique} (\textit{references please...}) since in
+effect an interpolation based on $2n + 1$ points will yield a polynomial equivalent to $W(x)$.
+
+The coefficients of the polynomial $W(x)$ are unknown which makes finding $W(y)$ for any value of $y$ impossible. However, since
+$W(x) = f(x)g(x)$ the equivalent $\zeta_y = f(y) g(y)$ can be used in its place. The benefit of this technique stems from the
+fact that $f(y)$ and $g(y)$ are much smaller than either $a$ or $b$ respectively. As a result finding the $2n + 1$ relations required
+by multiplying $f(y)g(y)$ involves multiplying integers that are much smaller than either of the inputs.
+
+When picking points to gather relations there are always three obvious points to choose, $y = 0, 1$ and $ \infty$. The $\zeta_0$ term
+is simply the product $W(0) = w_0 = a_0 \cdot b_0$. The $\zeta_1$ term is the product
+$W(1) = \left (\sum_{i = 0}^{n} a_i \right ) \left (\sum_{i = 0}^{n} b_i \right )$. The third point $\zeta_{\infty}$ is less obvious but rather
+simple to explain. The $2n + 1$'th coefficient of $W(x)$ is numerically equivalent to the most significant column in an integer multiplication.
+The point at $\infty$ is used symbolically to represent the most significant column, that is $W(\infty) = w_{2n} = a_nb_n$. Note that the
+points at $y = 0$ and $\infty$ yield the coefficients $w_0$ and $w_{2n}$ directly.
+
+If more points are required they should be of small values and powers of two such as $2^q$ and the related \textit{mirror points}
+$\left (2^q \right )^{2n} \cdot \zeta_{2^{-q}}$ for small values of $q$. The term ``mirror point'' stems from the fact that
+$\left (2^q \right )^{2n} \cdot \zeta_{2^{-q}}$ can be calculated in the exact opposite fashion as $\zeta_{2^q}$. For
+example, when $n = 2$ and $q = 1$ then following two equations are equivalent to the point $\zeta_{2}$ and its mirror.
+
+\begin{eqnarray}
+\zeta_{2} = f(2)g(2) = (4a_2 + 2a_1 + a_0)(4b_2 + 2b_1 + b_0) \nonumber \\
+16 \cdot \zeta_{1 \over 2} = 4f({1\over 2}) \cdot 4g({1 \over 2}) = (a_2 + 2a_1 + 4a_0)(b_2 + 2b_1 + 4b_0)
+\end{eqnarray}
+
+Using such points will allow the values of $f(y)$ and $g(y)$ to be independently calculated using only left shifts. For example, when $n = 2$ the
+polynomial $f(2^q)$ is equal to $2^q((2^qa_2) + a_1) + a_0$. This technique of polynomial representation is known as Horner's method.
+
+As a general rule of the algorithm when the inputs are split into $n$ parts each there are $2n - 1$ multiplications. Each multiplication is of
+multiplicands that have $n$ times fewer digits than the inputs. The asymptotic running time of this algorithm is
+$O \left ( k^{lg_n(2n - 1)} \right )$ for $k$ digit inputs (\textit{assuming they have the same number of digits}). Figure~\ref{fig:exponent}
+summarizes the exponents for various values of $n$.
+
+\begin{figure}
+\begin{center}
+\begin{tabular}{|c|c|c|}
+\hline \textbf{Split into $n$ Parts} & \textbf{Exponent} & \textbf{Notes}\\
+\hline $2$ & $1.584962501$ & This is Karatsuba Multiplication. \\
+\hline $3$ & $1.464973520$ & This is Toom-Cook Multiplication. \\
+\hline $4$ & $1.403677461$ &\\
+\hline $5$ & $1.365212389$ &\\
+\hline $10$ & $1.278753601$ &\\
+\hline $100$ & $1.149426538$ &\\
+\hline $1000$ & $1.100270931$ &\\
+\hline $10000$ & $1.075252070$ &\\
+\hline
+\end{tabular}
+\end{center}
+\caption{Asymptotic Running Time of Polynomial Basis Multiplication}
+\label{fig:exponent}
+\end{figure}
+
+At first it may seem like a good idea to choose $n = 1000$ since the exponent is approximately $1.1$. However, the overhead
+of solving for the 2001 terms of $W(x)$ will certainly consume any savings the algorithm could offer for all but exceedingly large
+numbers.
+
+\subsubsection{Cutoff Point}
+The polynomial basis multiplication algorithms all require fewer single precision multiplications than a straight Comba approach. However,
+the algorithms incur an overhead (\textit{at the $O(n)$ work level}) since they require a system of equations to be solved. This makes the
+polynomial basis approach more costly to use with small inputs.
+
+Let $m$ represent the number of digits in the multiplicands (\textit{assume both multiplicands have the same number of digits}). There exists a
+point $y$ such that when $m < y$ the polynomial basis algorithms are more costly than Comba, when $m = y$ they are roughly the same cost and
+when $m > y$ the Comba methods are slower than the polynomial basis algorithms.
+
+The exact location of $y$ depends on several key architectural elements of the computer platform in question.
+
+\begin{enumerate}
+\item The ratio of clock cycles for single precision multiplication versus other simpler operations such as addition, shifting, etc. For example
+on the AMD Athlon the ratio is roughly $17 : 1$ while on the Intel P4 it is $29 : 1$. The higher the ratio in favour of multiplication the lower
+the cutoff point $y$ will be.
+
+\item The complexity of the linear system of equations (\textit{for the coefficients of $W(x)$}) is. Generally speaking as the number of splits
+grows the complexity grows substantially. Ideally solving the system will only involve addition, subtraction and shifting of integers. This
+directly reflects on the ratio previous mentioned.
+
+\item To a lesser extent memory bandwidth and function call overheads. Provided the values are in the processor cache this is less of an
+influence over the cutoff point.
+
+\end{enumerate}
+
+A clean cutoff point separation occurs when a point $y$ is found such that all of the cutoff point conditions are met. For example, if the point
+is too low then there will be values of $m$ such that $m > y$ and the Comba method is still faster. Finding the cutoff points is fairly simple when
+a high resolution timer is available.
+
+\subsection{Karatsuba Multiplication}
+Karatsuba \cite{KARA} multiplication when originally proposed in 1962 was among the first set of algorithms to break the $O(n^2)$ barrier for
+general purpose multiplication. Given two polynomial basis representations $f(x) = ax + b$ and $g(x) = cx + d$, Karatsuba proved with
+light algebra \cite{KARAP} that the following polynomial is equivalent to multiplication of the two integers the polynomials represent.
+
+\begin{equation}
+f(x) \cdot g(x) = acx^2 + ((a + b)(c + d) - (ac + bd))x + bd
+\end{equation}
+
+Using the observation that $ac$ and $bd$ could be re-used only three half sized multiplications would be required to produce the product. Applying
+this algorithm recursively, the work factor becomes $O(n^{lg(3)})$ which is substantially better than the work factor $O(n^2)$ of the Comba technique. It turns
+out what Karatsuba did not know or at least did not publish was that this is simply polynomial basis multiplication with the points
+$\zeta_0$, $\zeta_{\infty}$ and $\zeta_{1}$. Consider the resultant system of equations.
+
+\begin{center}
+\begin{tabular}{rcrcrcrc}
+$\zeta_{0}$ & $=$ & & & & & $w_0$ \\
+$\zeta_{1}$ & $=$ & $w_2$ & $+$ & $w_1$ & $+$ & $w_0$ \\
+$\zeta_{\infty}$ & $=$ & $w_2$ & & & & \\
+\end{tabular}
+\end{center}
+
+By adding the first and last equation to the equation in the middle the term $w_1$ can be isolated and all three coefficients solved for. The simplicity
+of this system of equations has made Karatsuba fairly popular. In fact the cutoff point is often fairly low\footnote{With LibTomMath 0.18 it is 70 and 109 digits for the Intel P4 and AMD Athlon respectively.}
+making it an ideal algorithm to speed up certain public key cryptosystems such as RSA and Diffie-Hellman.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_karatsuba\_mul}. \\
+\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\
+\textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert$ \\
+\hline \\
+1. Init the following mp\_int variables: $x0$, $x1$, $y0$, $y1$, $t1$, $x0y0$, $x1y1$.\\
+2. If step 2 failed then return(\textit{MP\_MEM}). \\
+\\
+Split the input. e.g. $a = x1 \cdot \beta^B + x0$ \\
+3. $B \leftarrow \mbox{min}(a.used, b.used)/2$ \\
+4. $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\
+5. $y0 \leftarrow b \mbox{ (mod }\beta^B\mbox{)}$ \\
+6. $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_rshd}) \\
+7. $y1 \leftarrow \lfloor b / \beta^B \rfloor$ \\
+\\
+Calculate the three products. \\
+8. $x0y0 \leftarrow x0 \cdot y0$ (\textit{mp\_mul}) \\
+9. $x1y1 \leftarrow x1 \cdot y1$ \\
+10. $t1 \leftarrow x1 + x0$ (\textit{mp\_add}) \\
+11. $x0 \leftarrow y1 + y0$ \\
+12. $t1 \leftarrow t1 \cdot x0$ \\
+\\
+Calculate the middle term. \\
+13. $x0 \leftarrow x0y0 + x1y1$ \\
+14. $t1 \leftarrow t1 - x0$ (\textit{s\_mp\_sub}) \\
+\\
+Calculate the final product. \\
+15. $t1 \leftarrow t1 \cdot \beta^B$ (\textit{mp\_lshd}) \\
+16. $x1y1 \leftarrow x1y1 \cdot \beta^{2B}$ \\
+17. $t1 \leftarrow x0y0 + t1$ \\
+18. $c \leftarrow t1 + x1y1$ \\
+19. Clear all of the temporary variables. \\
+20. Return(\textit{MP\_OKAY}).\\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_karatsuba\_mul}
+\end{figure}
+
+\textbf{Algorithm mp\_karatsuba\_mul.}
+This algorithm computes the unsigned product of two inputs using the Karatsuba multiplication algorithm. It is loosely based on the description
+from Knuth \cite[pp. 294-295]{TAOCPV2}.
+
+\index{radix point}
+In order to split the two inputs into their respective halves, a suitable \textit{radix point} must be chosen. The radix point chosen must
+be used for both of the inputs meaning that it must be smaller than the smallest input. Step 3 chooses the radix point $B$ as half of the
+smallest input \textbf{used} count. After the radix point is chosen the inputs are split into lower and upper halves. Step 4 and 5
+compute the lower halves. Step 6 and 7 computer the upper halves.
+
+After the halves have been computed the three intermediate half-size products must be computed. Step 8 and 9 compute the trivial products
+$x0 \cdot y0$ and $x1 \cdot y1$. The mp\_int $x0$ is used as a temporary variable after $x1 + x0$ has been computed. By using $x0$ instead
+of an additional temporary variable, the algorithm can avoid an addition memory allocation operation.
+
+The remaining steps 13 through 18 compute the Karatsuba polynomial through a variety of digit shifting and addition operations.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_karatsuba\_mul.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+The new coding element in this routine, not seen in previous routines, is the usage of goto statements. The conventional
+wisdom is that goto statements should be avoided. This is generally true, however when every single function call can fail, it makes sense
+to handle error recovery with a single piece of code. Lines 62 to 76 handle initializing all of the temporary variables
+required. Note how each of the if statements goes to a different label in case of failure. This allows the routine to correctly free only
+the temporaries that have been successfully allocated so far.
+
+The temporary variables are all initialized using the mp\_init\_size routine since they are expected to be large. This saves the
+additional reallocation that would have been necessary. Also $x0$, $x1$, $y0$ and $y1$ have to be able to hold at least their respective
+number of digits for the next section of code.
+
+The first algebraic portion of the algorithm is to split the two inputs into their halves. However, instead of using mp\_mod\_2d and mp\_rshd
+to extract the halves, the respective code has been placed inline within the body of the function. To initialize the halves, the \textbf{used} and
+\textbf{sign} members are copied first. The first for loop on line 96 copies the lower halves. Since they are both the same magnitude it
+is simpler to calculate both lower halves in a single loop. The for loop on lines 102 and 107 calculate the upper halves $x1$ and
+$y1$ respectively.
+
+By inlining the calculation of the halves, the Karatsuba multiplier has a slightly lower overhead and can be used for smaller magnitude inputs.
+
+When line 151 is reached, the algorithm has completed succesfully. The ``error status'' variable $err$ is set to \textbf{MP\_OKAY} so that
+the same code that handles errors can be used to clear the temporary variables and return.
+
+\subsection{Toom-Cook $3$-Way Multiplication}
+Toom-Cook $3$-Way \cite{TOOM} multiplication is essentially the polynomial basis algorithm for $n = 2$ except that the points are
+chosen such that $\zeta$ is easy to compute and the resulting system of equations easy to reduce. Here, the points $\zeta_{0}$,
+$16 \cdot \zeta_{1 \over 2}$, $\zeta_1$, $\zeta_2$ and $\zeta_{\infty}$ make up the five required points to solve for the coefficients
+of the $W(x)$.
+
+With the five relations that Toom-Cook specifies, the following system of equations is formed.
+
+\begin{center}
+\begin{tabular}{rcrcrcrcrcr}
+$\zeta_0$ & $=$ & $0w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $1w_0$ \\
+$16 \cdot \zeta_{1 \over 2}$ & $=$ & $1w_4$ & $+$ & $2w_3$ & $+$ & $4w_2$ & $+$ & $8w_1$ & $+$ & $16w_0$ \\
+$\zeta_1$ & $=$ & $1w_4$ & $+$ & $1w_3$ & $+$ & $1w_2$ & $+$ & $1w_1$ & $+$ & $1w_0$ \\
+$\zeta_2$ & $=$ & $16w_4$ & $+$ & $8w_3$ & $+$ & $4w_2$ & $+$ & $2w_1$ & $+$ & $1w_0$ \\
+$\zeta_{\infty}$ & $=$ & $1w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $0w_0$ \\
+\end{tabular}
+\end{center}
+
+A trivial solution to this matrix requires $12$ subtractions, two multiplications by a small power of two, two divisions by a small power
+of two, two divisions by three and one multiplication by three. All of these $19$ sub-operations require less than quadratic time, meaning that
+the algorithm can be faster than a baseline multiplication. However, the greater complexity of this algorithm places the cutoff point
+(\textbf{TOOM\_MUL\_CUTOFF}) where Toom-Cook becomes more efficient much higher than the Karatsuba cutoff point.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_toom\_mul}. \\
+\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\
+\textbf{Output}. $c \leftarrow a \cdot b $ \\
+\hline \\
+Split $a$ and $b$ into three pieces. E.g. $a = a_2 \beta^{2k} + a_1 \beta^{k} + a_0$ \\
+1. $k \leftarrow \lfloor \mbox{min}(a.used, b.used) / 3 \rfloor$ \\
+2. $a_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\
+3. $a_1 \leftarrow \lfloor a / \beta^k \rfloor$, $a_1 \leftarrow a_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
+4. $a_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $a_2 \leftarrow a_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
+5. $b_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\
+6. $b_1 \leftarrow \lfloor a / \beta^k \rfloor$, $b_1 \leftarrow b_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
+7. $b_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $b_2 \leftarrow b_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
+\\
+Find the five equations for $w_0, w_1, ..., w_4$. \\
+8. $w_0 \leftarrow a_0 \cdot b_0$ \\
+9. $w_4 \leftarrow a_2 \cdot b_2$ \\
+10. $tmp_1 \leftarrow 2 \cdot a_0$, $tmp_1 \leftarrow a_1 + tmp_1$, $tmp_1 \leftarrow 2 \cdot tmp_1$, $tmp_1 \leftarrow tmp_1 + a_2$ \\
+11. $tmp_2 \leftarrow 2 \cdot b_0$, $tmp_2 \leftarrow b_1 + tmp_2$, $tmp_2 \leftarrow 2 \cdot tmp_2$, $tmp_2 \leftarrow tmp_2 + b_2$ \\
+12. $w_1 \leftarrow tmp_1 \cdot tmp_2$ \\
+13. $tmp_1 \leftarrow 2 \cdot a_2$, $tmp_1 \leftarrow a_1 + tmp_1$, $tmp_1 \leftarrow 2 \cdot tmp_1$, $tmp_1 \leftarrow tmp_1 + a_0$ \\
+14. $tmp_2 \leftarrow 2 \cdot b_2$, $tmp_2 \leftarrow b_1 + tmp_2$, $tmp_2 \leftarrow 2 \cdot tmp_2$, $tmp_2 \leftarrow tmp_2 + b_0$ \\
+15. $w_3 \leftarrow tmp_1 \cdot tmp_2$ \\
+16. $tmp_1 \leftarrow a_0 + a_1$, $tmp_1 \leftarrow tmp_1 + a_2$, $tmp_2 \leftarrow b_0 + b_1$, $tmp_2 \leftarrow tmp_2 + b_2$ \\
+17. $w_2 \leftarrow tmp_1 \cdot tmp_2$ \\
+\\
+Continued on the next page.\\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_toom\_mul}
+\end{figure}
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_toom\_mul} (continued). \\
+\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\
+\textbf{Output}. $c \leftarrow a \cdot b $ \\
+\hline \\
+Now solve the system of equations. \\
+18. $w_1 \leftarrow w_4 - w_1$, $w_3 \leftarrow w_3 - w_0$ \\
+19. $w_1 \leftarrow \lfloor w_1 / 2 \rfloor$, $w_3 \leftarrow \lfloor w_3 / 2 \rfloor$ \\
+20. $w_2 \leftarrow w_2 - w_0$, $w_2 \leftarrow w_2 - w_4$ \\
+21. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\
+22. $tmp_1 \leftarrow 8 \cdot w_0$, $w_1 \leftarrow w_1 - tmp_1$, $tmp_1 \leftarrow 8 \cdot w_4$, $w_3 \leftarrow w_3 - tmp_1$ \\
+23. $w_2 \leftarrow 3 \cdot w_2$, $w_2 \leftarrow w_2 - w_1$, $w_2 \leftarrow w_2 - w_3$ \\
+24. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\
+25. $w_1 \leftarrow \lfloor w_1 / 3 \rfloor, w_3 \leftarrow \lfloor w_3 / 3 \rfloor$ \\
+\\
+Now substitute $\beta^k$ for $x$ by shifting $w_0, w_1, ..., w_4$. \\
+26. for $n$ from $1$ to $4$ do \\
+\hspace{3mm}26.1 $w_n \leftarrow w_n \cdot \beta^{nk}$ \\
+27. $c \leftarrow w_0 + w_1$, $c \leftarrow c + w_2$, $c \leftarrow c + w_3$, $c \leftarrow c + w_4$ \\
+28. Return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_toom\_mul (continued)}
+\end{figure}
+
+\textbf{Algorithm mp\_toom\_mul.}
+This algorithm computes the product of two mp\_int variables $a$ and $b$ using the Toom-Cook approach. Compared to the Karatsuba multiplication, this
+algorithm has a lower asymptotic running time of approximately $O(n^{1.464})$ but at an obvious cost in overhead. In this
+description, several statements have been compounded to save space. The intention is that the statements are executed from left to right across
+any given step.
+
+The two inputs $a$ and $b$ are first split into three $k$-digit integers $a_0, a_1, a_2$ and $b_0, b_1, b_2$ respectively. From these smaller
+integers the coefficients of the polynomial basis representations $f(x)$ and $g(x)$ are known and can be used to find the relations required.
+
+The first two relations $w_0$ and $w_4$ are the points $\zeta_{0}$ and $\zeta_{\infty}$ respectively. The relation $w_1, w_2$ and $w_3$ correspond
+to the points $16 \cdot \zeta_{1 \over 2}, \zeta_{2}$ and $\zeta_{1}$ respectively. These are found using logical shifts to independently find
+$f(y)$ and $g(y)$ which significantly speeds up the algorithm.
+
+After the five relations $w_0, w_1, \ldots, w_4$ have been computed, the system they represent must be solved in order for the unknown coefficients
+$w_1, w_2$ and $w_3$ to be isolated. The steps 18 through 25 perform the system reduction required as previously described. Each step of
+the reduction represents the comparable matrix operation that would be performed had this been performed by pencil. For example, step 18 indicates
+that row $1$ must be subtracted from row $4$ and simultaneously row $0$ subtracted from row $3$.
+
+Once the coeffients have been isolated, the polynomial $W(x) = \sum_{i=0}^{2n} w_i x^i$ is known. By substituting $\beta^{k}$ for $x$, the integer
+result $a \cdot b$ is produced.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_toom\_mul.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+The first obvious thing to note is that this algorithm is complicated. The complexity is worth it if you are multiplying very
+large numbers. For example, a 10,000 digit multiplication takes approximaly 99,282,205 fewer single precision multiplications with
+Toom--Cook than a Comba or baseline approach (this is a savings of more than 99$\%$). For most ``crypto'' sized numbers this
+algorithm is not practical as Karatsuba has a much lower cutoff point.
+
+First we split $a$ and $b$ into three roughly equal portions. This has been accomplished (lines 41 to 70) with
+combinations of mp\_rshd() and mp\_mod\_2d() function calls. At this point $a = a2 \cdot \beta^2 + a1 \cdot \beta + a0$ and similiarly
+for $b$.
+
+Next we compute the five points $w0, w1, w2, w3$ and $w4$. Recall that $w0$ and $w4$ can be computed directly from the portions so
+we get those out of the way first (lines 73 and 78). Next we compute $w1, w2$ and $w3$ using Horners method.
+
+After this point we solve for the actual values of $w1, w2$ and $w3$ by reducing the $5 \times 5$ system which is relatively
+straight forward.
+
+\subsection{Signed Multiplication}
+Now that algorithms to handle multiplications of every useful dimensions have been developed, a rather simple finishing touch is required. So far all
+of the multiplication algorithms have been unsigned multiplications which leaves only a signed multiplication algorithm to be established.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_mul}. \\
+\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\
+\textbf{Output}. $c \leftarrow a \cdot b$ \\
+\hline \\
+1. If $a.sign = b.sign$ then \\
+\hspace{3mm}1.1 $sign = MP\_ZPOS$ \\
+2. else \\
+\hspace{3mm}2.1 $sign = MP\_ZNEG$ \\
+3. If min$(a.used, b.used) \ge TOOM\_MUL\_CUTOFF$ then \\
+\hspace{3mm}3.1 $c \leftarrow a \cdot b$ using algorithm mp\_toom\_mul \\
+4. else if min$(a.used, b.used) \ge KARATSUBA\_MUL\_CUTOFF$ then \\
+\hspace{3mm}4.1 $c \leftarrow a \cdot b$ using algorithm mp\_karatsuba\_mul \\
+5. else \\
+\hspace{3mm}5.1 $digs \leftarrow a.used + b.used + 1$ \\
+\hspace{3mm}5.2 If $digs < MP\_ARRAY$ and min$(a.used, b.used) \le \delta$ then \\
+\hspace{6mm}5.2.1 $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm fast\_s\_mp\_mul\_digs. \\
+\hspace{3mm}5.3 else \\
+\hspace{6mm}5.3.1 $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm s\_mp\_mul\_digs. \\
+6. $c.sign \leftarrow sign$ \\
+7. Return the result of the unsigned multiplication performed. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_mul}
+\end{figure}
+
+\textbf{Algorithm mp\_mul.}
+This algorithm performs the signed multiplication of two inputs. It will make use of any of the three unsigned multiplication algorithms
+available when the input is of appropriate size. The \textbf{sign} of the result is not set until the end of the algorithm since algorithm
+s\_mp\_mul\_digs will clear it.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_mul.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+The implementation is rather simplistic and is not particularly noteworthy. Line 22 computes the sign of the result using the ``?''
+operator from the C programming language. Line 48 computes $\delta$ using the fact that $1 << k$ is equal to $2^k$.
+
+\section{Squaring}
+\label{sec:basesquare}
+
+Squaring is a special case of multiplication where both multiplicands are equal. At first it may seem like there is no significant optimization
+available but in fact there is. Consider the multiplication of $576$ against $241$. In total there will be nine single precision multiplications
+performed which are $1\cdot 6$, $1 \cdot 7$, $1 \cdot 5$, $4 \cdot 6$, $4 \cdot 7$, $4 \cdot 5$, $2 \cdot 6$, $2 \cdot 7$ and $2 \cdot 5$. Now consider
+the multiplication of $123$ against $123$. The nine products are $3 \cdot 3$, $3 \cdot 2$, $3 \cdot 1$, $2 \cdot 3$, $2 \cdot 2$, $2 \cdot 1$,
+$1 \cdot 3$, $1 \cdot 2$ and $1 \cdot 1$. On closer inspection some of the products are equivalent. For example, $3 \cdot 2 = 2 \cdot 3$
+and $3 \cdot 1 = 1 \cdot 3$.
+
+For any $n$-digit input, there are ${{\left (n^2 + n \right)}\over 2}$ possible unique single precision multiplications required compared to the $n^2$
+required for multiplication. The following diagram gives an example of the operations required.
+
+\begin{figure}[here]
+\begin{center}
+\begin{tabular}{ccccc|c}
+&&1&2&3&\\
+$\times$ &&1&2&3&\\
+\hline && $3 \cdot 1$ & $3 \cdot 2$ & $3 \cdot 3$ & Row 0\\
+ & $2 \cdot 1$ & $2 \cdot 2$ & $2 \cdot 3$ && Row 1 \\
+ $1 \cdot 1$ & $1 \cdot 2$ & $1 \cdot 3$ &&& Row 2 \\
+\end{tabular}
+\end{center}
+\caption{Squaring Optimization Diagram}
+\end{figure}
+
+Starting from zero and numbering the columns from right to left a very simple pattern becomes obvious. For the purposes of this discussion let $x$
+represent the number being squared. The first observation is that in row $k$ the $2k$'th column of the product has a $\left (x_k \right)^2$ term in it.
+
+The second observation is that every column $j$ in row $k$ where $j \ne 2k$ is part of a double product. Every non-square term of a column will
+appear twice hence the name ``double product''. Every odd column is made up entirely of double products. In fact every column is made up of double
+products and at most one square (\textit{see the exercise section}).
+
+The third and final observation is that for row $k$ the first unique non-square term, that is, one that hasn't already appeared in an earlier row,
+occurs at column $2k + 1$. For example, on row $1$ of the previous squaring, column one is part of the double product with column one from row zero.
+Column two of row one is a square and column three is the first unique column.
+
+\subsection{The Baseline Squaring Algorithm}
+The baseline squaring algorithm is meant to be a catch-all squaring algorithm. It will handle any of the input sizes that the faster routines
+will not handle.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{s\_mp\_sqr}. \\
+\textbf{Input}. mp\_int $a$ \\
+\textbf{Output}. $b \leftarrow a^2$ \\
+\hline \\
+1. Init a temporary mp\_int of at least $2 \cdot a.used +1$ digits. (\textit{mp\_init\_size}) \\
+2. If step 1 failed return(\textit{MP\_MEM}) \\
+3. $t.used \leftarrow 2 \cdot a.used + 1$ \\
+4. For $ix$ from 0 to $a.used - 1$ do \\
+\hspace{3mm}Calculate the square. \\
+\hspace{3mm}4.1 $\hat r \leftarrow t_{2ix} + \left (a_{ix} \right )^2$ \\
+\hspace{3mm}4.2 $t_{2ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{3mm}Calculate the double products after the square. \\
+\hspace{3mm}4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
+\hspace{3mm}4.4 For $iy$ from $ix + 1$ to $a.used - 1$ do \\
+\hspace{6mm}4.4.1 $\hat r \leftarrow 2 \cdot a_{ix}a_{iy} + t_{ix + iy} + u$ \\
+\hspace{6mm}4.4.2 $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{6mm}4.4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
+\hspace{3mm}Set the last carry. \\
+\hspace{3mm}4.5 While $u > 0$ do \\
+\hspace{6mm}4.5.1 $iy \leftarrow iy + 1$ \\
+\hspace{6mm}4.5.2 $\hat r \leftarrow t_{ix + iy} + u$ \\
+\hspace{6mm}4.5.3 $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{6mm}4.5.4 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
+5. Clamp excess digits of $t$. (\textit{mp\_clamp}) \\
+6. Exchange $b$ and $t$. \\
+7. Clear $t$ (\textit{mp\_clear}) \\
+8. Return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm s\_mp\_sqr}
+\end{figure}
+
+\textbf{Algorithm s\_mp\_sqr.}
+This algorithm computes the square of an input using the three observations on squaring. It is based fairly faithfully on algorithm 14.16 of HAC
+\cite[pp.596-597]{HAC}. Similar to algorithm s\_mp\_mul\_digs, a temporary mp\_int is allocated to hold the result of the squaring. This allows the
+destination mp\_int to be the same as the source mp\_int.
+
+The outer loop of this algorithm begins on step 4. It is best to think of the outer loop as walking down the rows of the partial results, while
+the inner loop computes the columns of the partial result. Step 4.1 and 4.2 compute the square term for each row, and step 4.3 and 4.4 propagate
+the carry and compute the double products.
+
+The requirement that a mp\_word be able to represent the range $0 \le x < 2 \beta^2$ arises from this
+very algorithm. The product $a_{ix}a_{iy}$ will lie in the range $0 \le x \le \beta^2 - 2\beta + 1$ which is obviously less than $\beta^2$ meaning that
+when it is multiplied by two, it can be properly represented by a mp\_word.
+
+Similar to algorithm s\_mp\_mul\_digs, after every pass of the inner loop, the destination is correctly set to the sum of all of the partial
+results calculated so far. This involves expensive carry propagation which will be eliminated in the next algorithm.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_s\_mp\_sqr.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+Inside the outer loop (line 34) the square term is calculated on line 37. The carry (line 44) has been
+extracted from the mp\_word accumulator using a right shift. Aliases for $a_{ix}$ and $t_{ix+iy}$ are initialized
+(lines 47 and 50) to simplify the inner loop. The doubling is performed using two
+additions (line 59) since it is usually faster than shifting, if not at least as fast.
+
+The important observation is that the inner loop does not begin at $iy = 0$ like for multiplication. As such the inner loops
+get progressively shorter as the algorithm proceeds. This is what leads to the savings compared to using a multiplication to
+square a number.
+
+\subsection{Faster Squaring by the ``Comba'' Method}
+A major drawback to the baseline method is the requirement for single precision shifting inside the $O(n^2)$ nested loop. Squaring has an additional
+drawback that it must double the product inside the inner loop as well. As for multiplication, the Comba technique can be used to eliminate these
+performance hazards.
+
+The first obvious solution is to make an array of mp\_words which will hold all of the columns. This will indeed eliminate all of the carry
+propagation operations from the inner loop. However, the inner product must still be doubled $O(n^2)$ times. The solution stems from the simple fact
+that $2a + 2b + 2c = 2(a + b + c)$. That is the sum of all of the double products is equal to double the sum of all the products. For example,
+$ab + ba + ac + ca = 2ab + 2ac = 2(ab + ac)$.
+
+However, we cannot simply double all of the columns, since the squares appear only once per row. The most practical solution is to have two
+mp\_word arrays. One array will hold the squares and the other array will hold the double products. With both arrays the doubling and
+carry propagation can be moved to a $O(n)$ work level outside the $O(n^2)$ level. In this case, we have an even simpler solution in mind.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{fast\_s\_mp\_sqr}. \\
+\textbf{Input}. mp\_int $a$ \\
+\textbf{Output}. $b \leftarrow a^2$ \\
+\hline \\
+Place an array of \textbf{MP\_WARRAY} mp\_digits named $W$ on the stack. \\
+1. If $b.alloc < 2a.used + 1$ then grow $b$ to $2a.used + 1$ digits. (\textit{mp\_grow}). \\
+2. If step 1 failed return(\textit{MP\_MEM}). \\
+\\
+3. $pa \leftarrow 2 \cdot a.used$ \\
+4. $\hat W1 \leftarrow 0$ \\
+5. for $ix$ from $0$ to $pa - 1$ do \\
+\hspace{3mm}5.1 $\_ \hat W \leftarrow 0$ \\
+\hspace{3mm}5.2 $ty \leftarrow \mbox{MIN}(a.used - 1, ix)$ \\
+\hspace{3mm}5.3 $tx \leftarrow ix - ty$ \\
+\hspace{3mm}5.4 $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\
+\hspace{3mm}5.5 $iy \leftarrow \mbox{MIN}(iy, \lfloor \left (ty - tx + 1 \right )/2 \rfloor)$ \\
+\hspace{3mm}5.6 for $iz$ from $0$ to $iz - 1$ do \\
+\hspace{6mm}5.6.1 $\_ \hat W \leftarrow \_ \hat W + a_{tx + iz}a_{ty - iz}$ \\
+\hspace{3mm}5.7 $\_ \hat W \leftarrow 2 \cdot \_ \hat W + \hat W1$ \\
+\hspace{3mm}5.8 if $ix$ is even then \\
+\hspace{6mm}5.8.1 $\_ \hat W \leftarrow \_ \hat W + \left ( a_{\lfloor ix/2 \rfloor}\right )^2$ \\
+\hspace{3mm}5.9 $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$ \\
+\hspace{3mm}5.10 $\hat W1 \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\
+\\
+6. $oldused \leftarrow b.used$ \\
+7. $b.used \leftarrow 2 \cdot a.used$ \\
+8. for $ix$ from $0$ to $pa - 1$ do \\
+\hspace{3mm}8.1 $b_{ix} \leftarrow W_{ix}$ \\
+9. for $ix$ from $pa$ to $oldused - 1$ do \\
+\hspace{3mm}9.1 $b_{ix} \leftarrow 0$ \\
+10. Clamp excess digits from $b$. (\textit{mp\_clamp}) \\
+11. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm fast\_s\_mp\_sqr}
+\end{figure}
+
+\textbf{Algorithm fast\_s\_mp\_sqr.}
+This algorithm computes the square of an input using the Comba technique. It is designed to be a replacement for algorithm
+s\_mp\_sqr when the number of input digits is less than \textbf{MP\_WARRAY} and less than $\delta \over 2$.
+This algorithm is very similar to the Comba multiplier except with a few key differences we shall make note of.
+
+First, we have an accumulator and carry variables $\_ \hat W$ and $\hat W1$ respectively. This is because the inner loop
+products are to be doubled. If we had added the previous carry in we would be doubling too much. Next we perform an
+addition MIN condition on $iy$ (step 5.5) to prevent overlapping digits. For example, $a_3 \cdot a_5$ is equal
+$a_5 \cdot a_3$. Whereas in the multiplication case we would have $5 < a.used$ and $3 \ge 0$ is maintained since we double the sum
+of the products just outside the inner loop we have to avoid doing this. This is also a good thing since we perform
+fewer multiplications and the routine ends up being faster.
+
+Finally the last difference is the addition of the ``square'' term outside the inner loop (step 5.8). We add in the square
+only to even outputs and it is the square of the term at the $\lfloor ix / 2 \rfloor$ position.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_fast\_s\_mp\_sqr.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+This implementation is essentially a copy of Comba multiplication with the appropriate changes added to make it faster for
+the special case of squaring.
+
+\subsection{Polynomial Basis Squaring}
+The same algorithm that performs optimal polynomial basis multiplication can be used to perform polynomial basis squaring. The minor exception
+is that $\zeta_y = f(y)g(y)$ is actually equivalent to $\zeta_y = f(y)^2$ since $f(y) = g(y)$. Instead of performing $2n + 1$
+multiplications to find the $\zeta$ relations, squaring operations are performed instead.
+
+\subsection{Karatsuba Squaring}
+Let $f(x) = ax + b$ represent the polynomial basis representation of a number to square.
+Let $h(x) = \left ( f(x) \right )^2$ represent the square of the polynomial. The Karatsuba equation can be modified to square a
+number with the following equation.
+
+\begin{equation}
+h(x) = a^2x^2 + \left ((a + b)^2 - (a^2 + b^2) \right )x + b^2
+\end{equation}
+
+Upon closer inspection this equation only requires the calculation of three half-sized squares: $a^2$, $b^2$ and $(a + b)^2$. As in
+Karatsuba multiplication, this algorithm can be applied recursively on the input and will achieve an asymptotic running time of
+$O \left ( n^{lg(3)} \right )$.
+
+If the asymptotic times of Karatsuba squaring and multiplication are the same, why not simply use the multiplication algorithm
+instead? The answer to this arises from the cutoff point for squaring. As in multiplication there exists a cutoff point, at which the
+time required for a Comba based squaring and a Karatsuba based squaring meet. Due to the overhead inherent in the Karatsuba method, the cutoff
+point is fairly high. For example, on an AMD Athlon XP processor with $\beta = 2^{28}$, the cutoff point is around 127 digits.
+
+Consider squaring a 200 digit number with this technique. It will be split into two 100 digit halves which are subsequently squared.
+The 100 digit halves will not be squared using Karatsuba, but instead using the faster Comba based squaring algorithm. If Karatsuba multiplication
+were used instead, the 100 digit numbers would be squared with a slower Comba based multiplication.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_karatsuba\_sqr}. \\
+\textbf{Input}. mp\_int $a$ \\
+\textbf{Output}. $b \leftarrow a^2$ \\
+\hline \\
+1. Initialize the following temporary mp\_ints: $x0$, $x1$, $t1$, $t2$, $x0x0$ and $x1x1$. \\
+2. If any of the initializations on step 1 failed return(\textit{MP\_MEM}). \\
+\\
+Split the input. e.g. $a = x1\beta^B + x0$ \\
+3. $B \leftarrow \lfloor a.used / 2 \rfloor$ \\
+4. $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\
+5. $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_lshd}) \\
+\\
+Calculate the three squares. \\
+6. $x0x0 \leftarrow x0^2$ (\textit{mp\_sqr}) \\
+7. $x1x1 \leftarrow x1^2$ \\
+8. $t1 \leftarrow x1 + x0$ (\textit{s\_mp\_add}) \\
+9. $t1 \leftarrow t1^2$ \\
+\\
+Compute the middle term. \\
+10. $t2 \leftarrow x0x0 + x1x1$ (\textit{s\_mp\_add}) \\
+11. $t1 \leftarrow t1 - t2$ \\
+\\
+Compute final product. \\
+12. $t1 \leftarrow t1\beta^B$ (\textit{mp\_lshd}) \\
+13. $x1x1 \leftarrow x1x1\beta^{2B}$ \\
+14. $t1 \leftarrow t1 + x0x0$ \\
+15. $b \leftarrow t1 + x1x1$ \\
+16. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_karatsuba\_sqr}
+\end{figure}
+
+\textbf{Algorithm mp\_karatsuba\_sqr.}
+This algorithm computes the square of an input $a$ using the Karatsuba technique. This algorithm is very similar to the Karatsuba based
+multiplication algorithm with the exception that the three half-size multiplications have been replaced with three half-size squarings.
+
+The radix point for squaring is simply placed exactly in the middle of the digits when the input has an odd number of digits, otherwise it is
+placed just below the middle. Step 3, 4 and 5 compute the two halves required using $B$
+as the radix point. The first two squares in steps 6 and 7 are rather straightforward while the last square is of a more compact form.
+
+By expanding $\left (x1 + x0 \right )^2$, the $x1^2$ and $x0^2$ terms in the middle disappear, that is $(x0 - x1)^2 - (x1^2 + x0^2) = 2 \cdot x0 \cdot x1$.
+Now if $5n$ single precision additions and a squaring of $n$-digits is faster than multiplying two $n$-digit numbers and doubling then
+this method is faster. Assuming no further recursions occur, the difference can be estimated with the following inequality.
+
+Let $p$ represent the cost of a single precision addition and $q$ the cost of a single precision multiplication both in terms of time\footnote{Or
+machine clock cycles.}.
+
+\begin{equation}
+5pn +{{q(n^2 + n)} \over 2} \le pn + qn^2
+\end{equation}
+
+For example, on an AMD Athlon XP processor $p = {1 \over 3}$ and $q = 6$. This implies that the following inequality should hold.
+\begin{center}
+\begin{tabular}{rcl}
+${5n \over 3} + 3n^2 + 3n$ & $<$ & ${n \over 3} + 6n^2$ \\
+${5 \over 3} + 3n + 3$ & $<$ & ${1 \over 3} + 6n$ \\
+${13 \over 9}$ & $<$ & $n$ \\
+\end{tabular}
+\end{center}
+
+This results in a cutoff point around $n = 2$. As a consequence it is actually faster to compute the middle term the ``long way'' on processors
+where multiplication is substantially slower\footnote{On the Athlon there is a 1:17 ratio between clock cycles for addition and multiplication. On
+the Intel P4 processor this ratio is 1:29 making this method even more beneficial. The only common exception is the ARMv4 processor which has a
+ratio of 1:7. } than simpler operations such as addition.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_karatsuba\_sqr.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+This implementation is largely based on the implementation of algorithm mp\_karatsuba\_mul. It uses the same inline style to copy and
+shift the input into the two halves. The loop from line 54 to line 70 has been modified since only one input exists. The \textbf{used}
+count of both $x0$ and $x1$ is fixed up and $x0$ is clamped before the calculations begin. At this point $x1$ and $x0$ are valid equivalents
+to the respective halves as if mp\_rshd and mp\_mod\_2d had been used.
+
+By inlining the copy and shift operations the cutoff point for Karatsuba multiplication can be lowered. On the Athlon the cutoff point
+is exactly at the point where Comba squaring can no longer be used (\textit{128 digits}). On slower processors such as the Intel P4
+it is actually below the Comba limit (\textit{at 110 digits}).
+
+This routine uses the same error trap coding style as mp\_karatsuba\_sqr. As the temporary variables are initialized errors are
+redirected to the error trap higher up. If the algorithm completes without error the error code is set to \textbf{MP\_OKAY} and
+mp\_clears are executed normally.
+
+\subsection{Toom-Cook Squaring}
+The Toom-Cook squaring algorithm mp\_toom\_sqr is heavily based on the algorithm mp\_toom\_mul with the exception that squarings are used
+instead of multiplication to find the five relations. The reader is encouraged to read the description of the latter algorithm and try to
+derive their own Toom-Cook squaring algorithm.
+
+\subsection{High Level Squaring}
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_sqr}. \\
+\textbf{Input}. mp\_int $a$ \\
+\textbf{Output}. $b \leftarrow a^2$ \\
+\hline \\
+1. If $a.used \ge TOOM\_SQR\_CUTOFF$ then \\
+\hspace{3mm}1.1 $b \leftarrow a^2$ using algorithm mp\_toom\_sqr \\
+2. else if $a.used \ge KARATSUBA\_SQR\_CUTOFF$ then \\
+\hspace{3mm}2.1 $b \leftarrow a^2$ using algorithm mp\_karatsuba\_sqr \\
+3. else \\
+\hspace{3mm}3.1 $digs \leftarrow a.used + b.used + 1$ \\
+\hspace{3mm}3.2 If $digs < MP\_ARRAY$ and $a.used \le \delta$ then \\
+\hspace{6mm}3.2.1 $b \leftarrow a^2$ using algorithm fast\_s\_mp\_sqr. \\
+\hspace{3mm}3.3 else \\
+\hspace{6mm}3.3.1 $b \leftarrow a^2$ using algorithm s\_mp\_sqr. \\
+4. $b.sign \leftarrow MP\_ZPOS$ \\
+5. Return the result of the unsigned squaring performed. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_sqr}
+\end{figure}
+
+\textbf{Algorithm mp\_sqr.}
+This algorithm computes the square of the input using one of four different algorithms. If the input is very large and has at least
+\textbf{TOOM\_SQR\_CUTOFF} or \textbf{KARATSUBA\_SQR\_CUTOFF} digits then either the Toom-Cook or the Karatsuba Squaring algorithm is used. If
+neither of the polynomial basis algorithms should be used then either the Comba or baseline algorithm is used.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_sqr.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+\section*{Exercises}
+\begin{tabular}{cl}
+$\left [ 3 \right ] $ & Devise an efficient algorithm for selection of the radix point to handle inputs \\
+ & that have different number of digits in Karatsuba multiplication. \\
+ & \\
+$\left [ 2 \right ] $ & In section 5.3 the fact that every column of a squaring is made up \\
+ & of double products and at most one square is stated. Prove this statement. \\
+ & \\
+$\left [ 3 \right ] $ & Prove the equation for Karatsuba squaring. \\
+ & \\
+$\left [ 1 \right ] $ & Prove that Karatsuba squaring requires $O \left (n^{lg(3)} \right )$ time. \\
+ & \\
+$\left [ 2 \right ] $ & Determine the minimal ratio between addition and multiplication clock cycles \\
+ & required for equation $6.7$ to be true. \\
+ & \\
+$\left [ 3 \right ] $ & Implement a threaded version of Comba multiplication (and squaring) where you \\
+ & compute subsets of the columns in each thread. Determine a cutoff point where \\
+ & it is effective and add the logic to mp\_mul() and mp\_sqr(). \\
+ &\\
+$\left [ 4 \right ] $ & Same as the previous but also modify the Karatsuba and Toom-Cook. You must \\
+ & increase the throughput of mp\_exptmod() for random odd moduli in the range \\
+ & $512 \ldots 4096$ bits significantly ($> 2x$) to complete this challenge. \\
+ & \\
+\end{tabular}
+
+\chapter{Modular Reduction}
+\section{Basics of Modular Reduction}
+\index{modular residue}
+Modular reduction is an operation that arises quite often within public key cryptography algorithms and various number theoretic algorithms,
+such as factoring. Modular reduction algorithms are the third class of algorithms of the ``multipliers'' set. A number $a$ is said to be \textit{reduced}
+modulo another number $b$ by finding the remainder of the division $a/b$. Full integer division with remainder is a topic to be covered
+in~\ref{sec:division}.
+
+Modular reduction is equivalent to solving for $r$ in the following equation. $a = bq + r$ where $q = \lfloor a/b \rfloor$. The result
+$r$ is said to be ``congruent to $a$ modulo $b$'' which is also written as $r \equiv a \mbox{ (mod }b\mbox{)}$. In other vernacular $r$ is known as the
+``modular residue'' which leads to ``quadratic residue''\footnote{That's fancy talk for $b \equiv a^2 \mbox{ (mod }p\mbox{)}$.} and
+other forms of residues.
+
+Modular reductions are normally used to create either finite groups, rings or fields. The most common usage for performance driven modular reductions
+is in modular exponentiation algorithms. That is to compute $d = a^b \mbox{ (mod }c\mbox{)}$ as fast as possible. This operation is used in the
+RSA and Diffie-Hellman public key algorithms, for example. Modular multiplication and squaring also appears as a fundamental operation in
+elliptic curve cryptographic algorithms. As will be discussed in the subsequent chapter there exist fast algorithms for computing modular
+exponentiations without having to perform (\textit{in this example}) $b - 1$ multiplications. These algorithms will produce partial results in the
+range $0 \le x < c^2$ which can be taken advantage of to create several efficient algorithms. They have also been used to create redundancy check
+algorithms known as CRCs, error correction codes such as Reed-Solomon and solve a variety of number theoeretic problems.
+
+\section{The Barrett Reduction}
+The Barrett reduction algorithm \cite{BARRETT} was inspired by fast division algorithms which multiply by the reciprocal to emulate
+division. Barretts observation was that the residue $c$ of $a$ modulo $b$ is equal to
+
+\begin{equation}
+c = a - b \cdot \lfloor a/b \rfloor
+\end{equation}
+
+Since algorithms such as modular exponentiation would be using the same modulus extensively, typical DSP\footnote{It is worth noting that Barrett's paper
+targeted the DSP56K processor.} intuition would indicate the next step would be to replace $a/b$ by a multiplication by the reciprocal. However,
+DSP intuition on its own will not work as these numbers are considerably larger than the precision of common DSP floating point data types.
+It would take another common optimization to optimize the algorithm.
+
+\subsection{Fixed Point Arithmetic}
+The trick used to optimize the above equation is based on a technique of emulating floating point data types with fixed precision integers. Fixed
+point arithmetic would become very popular as it greatly optimize the ``3d-shooter'' genre of games in the mid 1990s when floating point units were
+fairly slow if not unavailable. The idea behind fixed point arithmetic is to take a normal $k$-bit integer data type and break it into $p$-bit
+integer and a $q$-bit fraction part (\textit{where $p+q = k$}).
+
+In this system a $k$-bit integer $n$ would actually represent $n/2^q$. For example, with $q = 4$ the integer $n = 37$ would actually represent the
+value $2.3125$. To multiply two fixed point numbers the integers are multiplied using traditional arithmetic and subsequently normalized by
+moving the implied decimal point back to where it should be. For example, with $q = 4$ to multiply the integers $9$ and $5$ they must be converted
+to fixed point first by multiplying by $2^q$. Let $a = 9(2^q)$ represent the fixed point representation of $9$ and $b = 5(2^q)$ represent the
+fixed point representation of $5$. The product $ab$ is equal to $45(2^{2q})$ which when normalized by dividing by $2^q$ produces $45(2^q)$.
+
+This technique became popular since a normal integer multiplication and logical shift right are the only required operations to perform a multiplication
+of two fixed point numbers. Using fixed point arithmetic, division can be easily approximated by multiplying by the reciprocal. If $2^q$ is
+equivalent to one than $2^q/b$ is equivalent to the fixed point approximation of $1/b$ using real arithmetic. Using this fact dividing an integer
+$a$ by another integer $b$ can be achieved with the following expression.
+
+\begin{equation}
+\lfloor a / b \rfloor \mbox{ }\approx\mbox{ } \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor
+\end{equation}
+
+The precision of the division is proportional to the value of $q$. If the divisor $b$ is used frequently as is the case with
+modular exponentiation pre-computing $2^q/b$ will allow a division to be performed with a multiplication and a right shift. Both operations
+are considerably faster than division on most processors.
+
+Consider dividing $19$ by $5$. The correct result is $\lfloor 19/5 \rfloor = 3$. With $q = 3$ the reciprocal is $\lfloor 2^q/5 \rfloor = 1$ which
+leads to a product of $19$ which when divided by $2^q$ produces $2$. However, with $q = 4$ the reciprocal is $\lfloor 2^q/5 \rfloor = 3$ and
+the result of the emulated division is $\lfloor 3 \cdot 19 / 2^q \rfloor = 3$ which is correct. The value of $2^q$ must be close to or ideally
+larger than the dividend. In effect if $a$ is the dividend then $q$ should allow $0 \le \lfloor a/2^q \rfloor \le 1$ in order for this approach
+to work correctly. Plugging this form of divison into the original equation the following modular residue equation arises.
+
+\begin{equation}
+c = a - b \cdot \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor
+\end{equation}
+
+Using the notation from \cite{BARRETT} the value of $\lfloor 2^q / b \rfloor$ will be represented by the $\mu$ symbol. Using the $\mu$
+variable also helps re-inforce the idea that it is meant to be computed once and re-used.
+
+\begin{equation}
+c = a - b \cdot \lfloor (a \cdot \mu)/2^q \rfloor
+\end{equation}
+
+Provided that $2^q \ge a$ this algorithm will produce a quotient that is either exactly correct or off by a value of one. In the context of Barrett
+reduction the value of $a$ is bound by $0 \le a \le (b - 1)^2$ meaning that $2^q \ge b^2$ is sufficient to ensure the reciprocal will have enough
+precision.
+
+Let $n$ represent the number of digits in $b$. This algorithm requires approximately $2n^2$ single precision multiplications to produce the quotient and
+another $n^2$ single precision multiplications to find the residue. In total $3n^2$ single precision multiplications are required to
+reduce the number.
+
+For example, if $b = 1179677$ and $q = 41$ ($2^q > b^2$), then the reciprocal $\mu$ is equal to $\lfloor 2^q / b \rfloor = 1864089$. Consider reducing
+$a = 180388626447$ modulo $b$ using the above reduction equation. The quotient using the new formula is $\lfloor (a \cdot \mu) / 2^q \rfloor = 152913$.
+By subtracting $152913b$ from $a$ the correct residue $a \equiv 677346 \mbox{ (mod }b\mbox{)}$ is found.
+
+\subsection{Choosing a Radix Point}
+Using the fixed point representation a modular reduction can be performed with $3n^2$ single precision multiplications. If that were the best
+that could be achieved a full division\footnote{A division requires approximately $O(2cn^2)$ single precision multiplications for a small value of $c$.
+See~\ref{sec:division} for further details.} might as well be used in its place. The key to optimizing the reduction is to reduce the precision of
+the initial multiplication that finds the quotient.
+
+Let $a$ represent the number of which the residue is sought. Let $b$ represent the modulus used to find the residue. Let $m$ represent
+the number of digits in $b$. For the purposes of this discussion we will assume that the number of digits in $a$ is $2m$, which is generally true if
+two $m$-digit numbers have been multiplied. Dividing $a$ by $b$ is the same as dividing a $2m$ digit integer by a $m$ digit integer. Digits below the
+$m - 1$'th digit of $a$ will contribute at most a value of $1$ to the quotient because $\beta^k < b$ for any $0 \le k \le m - 1$. Another way to
+express this is by re-writing $a$ as two parts. If $a' \equiv a \mbox{ (mod }b^m\mbox{)}$ and $a'' = a - a'$ then
+${a \over b} \equiv {{a' + a''} \over b}$ which is equivalent to ${a' \over b} + {a'' \over b}$. Since $a'$ is bound to be less than $b$ the quotient
+is bound by $0 \le {a' \over b} < 1$.
+
+Since the digits of $a'$ do not contribute much to the quotient the observation is that they might as well be zero. However, if the digits
+``might as well be zero'' they might as well not be there in the first place. Let $q_0 = \lfloor a/\beta^{m-1} \rfloor$ represent the input
+with the irrelevant digits trimmed. Now the modular reduction is trimmed to the almost equivalent equation
+
+\begin{equation}
+c = a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor
+\end{equation}
+
+Note that the original divisor $2^q$ has been replaced with $\beta^{m+1}$ where in this case $q$ is a multiple of $lg(\beta)$. Also note that the
+exponent on the divisor when added to the amount $q_0$ was shifted by equals $2m$. If the optimization had not been performed the divisor
+would have the exponent $2m$ so in the end the exponents do ``add up''. Using the above equation the quotient
+$\lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ can be off from the true quotient by at most two. The original fixed point quotient can be off
+by as much as one (\textit{provided the radix point is chosen suitably}) and now that the lower irrelevent digits have been trimmed the quotient
+can be off by an additional value of one for a total of at most two. This implies that
+$0 \le a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor < 3b$. By first subtracting $b$ times the quotient and then conditionally subtracting
+$b$ once or twice the residue is found.
+
+The quotient is now found using $(m + 1)(m) = m^2 + m$ single precision multiplications and the residue with an additional $m^2$ single
+precision multiplications, ignoring the subtractions required. In total $2m^2 + m$ single precision multiplications are required to find the residue.
+This is considerably faster than the original attempt.
+
+For example, let $\beta = 10$ represent the radix of the digits. Let $b = 9999$ represent the modulus which implies $m = 4$. Let $a = 99929878$
+represent the value of which the residue is desired. In this case $q = 8$ since $10^7 < 9999^2$ meaning that $\mu = \lfloor \beta^{q}/b \rfloor = 10001$.
+With the new observation the multiplicand for the quotient is equal to $q_0 = \lfloor a / \beta^{m - 1} \rfloor = 99929$. The quotient is then
+$\lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor = 9993$. Subtracting $9993b$ from $a$ and the correct residue $a \equiv 9871 \mbox{ (mod }b\mbox{)}$
+is found.
+
+\subsection{Trimming the Quotient}
+So far the reduction algorithm has been optimized from $3m^2$ single precision multiplications down to $2m^2 + m$ single precision multiplications. As
+it stands now the algorithm is already fairly fast compared to a full integer division algorithm. However, there is still room for
+optimization.
+
+After the first multiplication inside the quotient ($q_0 \cdot \mu$) the value is shifted right by $m + 1$ places effectively nullifying the lower
+half of the product. It would be nice to be able to remove those digits from the product to effectively cut down the number of single precision
+multiplications. If the number of digits in the modulus $m$ is far less than $\beta$ a full product is not required for the algorithm to work properly.
+In fact the lower $m - 2$ digits will not affect the upper half of the product at all and do not need to be computed.
+
+The value of $\mu$ is a $m$-digit number and $q_0$ is a $m + 1$ digit number. Using a full multiplier $(m + 1)(m) = m^2 + m$ single precision
+multiplications would be required. Using a multiplier that will only produce digits at and above the $m - 1$'th digit reduces the number
+of single precision multiplications to ${m^2 + m} \over 2$ single precision multiplications.
+
+\subsection{Trimming the Residue}
+After the quotient has been calculated it is used to reduce the input. As previously noted the algorithm is not exact and it can be off by a small
+multiple of the modulus, that is $0 \le a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor < 3b$. If $b$ is $m$ digits than the
+result of reduction equation is a value of at most $m + 1$ digits (\textit{provided $3 < \beta$}) implying that the upper $m - 1$ digits are
+implicitly zero.
+
+The next optimization arises from this very fact. Instead of computing $b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ using a full
+$O(m^2)$ multiplication algorithm only the lower $m+1$ digits of the product have to be computed. Similarly the value of $a$ can
+be reduced modulo $\beta^{m+1}$ before the multiple of $b$ is subtracted which simplifes the subtraction as well. A multiplication that produces
+only the lower $m+1$ digits requires ${m^2 + 3m - 2} \over 2$ single precision multiplications.
+
+With both optimizations in place the algorithm is the algorithm Barrett proposed. It requires $m^2 + 2m - 1$ single precision multiplications which
+is considerably faster than the straightforward $3m^2$ method.
+
+\subsection{The Barrett Algorithm}
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_reduce}. \\
+\textbf{Input}. mp\_int $a$, mp\_int $b$ and $\mu = \lfloor \beta^{2m}/b \rfloor, m = \lceil lg_{\beta}(b) \rceil, (0 \le a < b^2, b > 1)$ \\
+\textbf{Output}. $a \mbox{ (mod }b\mbox{)}$ \\
+\hline \\
+Let $m$ represent the number of digits in $b$. \\
+1. Make a copy of $a$ and store it in $q$. (\textit{mp\_init\_copy}) \\
+2. $q \leftarrow \lfloor q / \beta^{m - 1} \rfloor$ (\textit{mp\_rshd}) \\
+\\
+Produce the quotient. \\
+3. $q \leftarrow q \cdot \mu$ (\textit{note: only produce digits at or above $m-1$}) \\
+4. $q \leftarrow \lfloor q / \beta^{m + 1} \rfloor$ \\
+\\
+Subtract the multiple of modulus from the input. \\
+5. $a \leftarrow a \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{mp\_mod\_2d}) \\
+6. $q \leftarrow q \cdot b \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{s\_mp\_mul\_digs}) \\
+7. $a \leftarrow a - q$ (\textit{mp\_sub}) \\
+\\
+Add $\beta^{m+1}$ if a carry occured. \\
+8. If $a < 0$ then (\textit{mp\_cmp\_d}) \\
+\hspace{3mm}8.1 $q \leftarrow 1$ (\textit{mp\_set}) \\
+\hspace{3mm}8.2 $q \leftarrow q \cdot \beta^{m+1}$ (\textit{mp\_lshd}) \\
+\hspace{3mm}8.3 $a \leftarrow a + q$ \\
+\\
+Now subtract the modulus if the residue is too large (e.g. quotient too small). \\
+9. While $a \ge b$ do (\textit{mp\_cmp}) \\
+\hspace{3mm}9.1 $c \leftarrow a - b$ \\
+10. Clear $q$. \\
+11. Return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_reduce}
+\end{figure}
+
+\textbf{Algorithm mp\_reduce.}
+This algorithm will reduce the input $a$ modulo $b$ in place using the Barrett algorithm. It is loosely based on algorithm 14.42 of HAC
+\cite[pp. 602]{HAC} which is based on the paper from Paul Barrett \cite{BARRETT}. The algorithm has several restrictions and assumptions which must
+be adhered to for the algorithm to work.
+
+First the modulus $b$ is assumed to be positive and greater than one. If the modulus were less than or equal to one than subtracting
+a multiple of it would either accomplish nothing or actually enlarge the input. The input $a$ must be in the range $0 \le a < b^2$ in order
+for the quotient to have enough precision. If $a$ is the product of two numbers that were already reduced modulo $b$, this will not be a problem.
+Technically the algorithm will still work if $a \ge b^2$ but it will take much longer to finish. The value of $\mu$ is passed as an argument to this
+algorithm and is assumed to be calculated and stored before the algorithm is used.
+
+Recall that the multiplication for the quotient on step 3 must only produce digits at or above the $m-1$'th position. An algorithm called
+$s\_mp\_mul\_high\_digs$ which has not been presented is used to accomplish this task. The algorithm is based on $s\_mp\_mul\_digs$ except that
+instead of stopping at a given level of precision it starts at a given level of precision. This optimal algorithm can only be used if the number
+of digits in $b$ is very much smaller than $\beta$.
+
+While it is known that
+$a \ge b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ only the lower $m+1$ digits are being used to compute the residue, so an implied
+``borrow'' from the higher digits might leave a negative result. After the multiple of the modulus has been subtracted from $a$ the residue must be
+fixed up in case it is negative. The invariant $\beta^{m+1}$ must be added to the residue to make it positive again.
+
+The while loop at step 9 will subtract $b$ until the residue is less than $b$. If the algorithm is performed correctly this step is
+performed at most twice, and on average once. However, if $a \ge b^2$ than it will iterate substantially more times than it should.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_reduce.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+The first multiplication that determines the quotient can be performed by only producing the digits from $m - 1$ and up. This essentially halves
+the number of single precision multiplications required. However, the optimization is only safe if $\beta$ is much larger than the number of digits
+in the modulus. In the source code this is evaluated on lines 36 to 44 where algorithm s\_mp\_mul\_high\_digs is used when it is
+safe to do so.
+
+\subsection{The Barrett Setup Algorithm}
+In order to use algorithm mp\_reduce the value of $\mu$ must be calculated in advance. Ideally this value should be computed once and stored for
+future use so that the Barrett algorithm can be used without delay.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_reduce\_setup}. \\
+\textbf{Input}. mp\_int $a$ ($a > 1$) \\
+\textbf{Output}. $\mu \leftarrow \lfloor \beta^{2m}/a \rfloor$ \\
+\hline \\
+1. $\mu \leftarrow 2^{2 \cdot lg(\beta) \cdot m}$ (\textit{mp\_2expt}) \\
+2. $\mu \leftarrow \lfloor \mu / b \rfloor$ (\textit{mp\_div}) \\
+3. Return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_reduce\_setup}
+\end{figure}
+
+\textbf{Algorithm mp\_reduce\_setup.}
+This algorithm computes the reciprocal $\mu$ required for Barrett reduction. First $\beta^{2m}$ is calculated as $2^{2 \cdot lg(\beta) \cdot m}$ which
+is equivalent and much faster. The final value is computed by taking the integer quotient of $\lfloor \mu / b \rfloor$.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_setup.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+This simple routine calculates the reciprocal $\mu$ required by Barrett reduction. Note the extended usage of algorithm mp\_div where the variable
+which would received the remainder is passed as NULL. As will be discussed in~\ref{sec:division} the division routine allows both the quotient and the
+remainder to be passed as NULL meaning to ignore the value.
+
+\section{The Montgomery Reduction}
+Montgomery reduction\footnote{Thanks to Niels Ferguson for his insightful explanation of the algorithm.} \cite{MONT} is by far the most interesting
+form of reduction in common use. It computes a modular residue which is not actually equal to the residue of the input yet instead equal to a
+residue times a constant. However, as perplexing as this may sound the algorithm is relatively simple and very efficient.
+
+Throughout this entire section the variable $n$ will represent the modulus used to form the residue. As will be discussed shortly the value of
+$n$ must be odd. The variable $x$ will represent the quantity of which the residue is sought. Similar to the Barrett algorithm the input
+is restricted to $0 \le x < n^2$. To begin the description some simple number theory facts must be established.
+
+\textbf{Fact 1.} Adding $n$ to $x$ does not change the residue since in effect it adds one to the quotient $\lfloor x / n \rfloor$. Another way
+to explain this is that $n$ is (\textit{or multiples of $n$ are}) congruent to zero modulo $n$. Adding zero will not change the value of the residue.
+
+\textbf{Fact 2.} If $x$ is even then performing a division by two in $\Z$ is congruent to $x \cdot 2^{-1} \mbox{ (mod }n\mbox{)}$. Actually
+this is an application of the fact that if $x$ is evenly divisible by any $k \in \Z$ then division in $\Z$ will be congruent to
+multiplication by $k^{-1}$ modulo $n$.
+
+From these two simple facts the following simple algorithm can be derived.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Montgomery Reduction}. \\
+\textbf{Input}. Integer $x$, $n$ and $k$ \\
+\textbf{Output}. $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\
+\hline \\
+1. for $t$ from $1$ to $k$ do \\
+\hspace{3mm}1.1 If $x$ is odd then \\
+\hspace{6mm}1.1.1 $x \leftarrow x + n$ \\
+\hspace{3mm}1.2 $x \leftarrow x/2$ \\
+2. Return $x$. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm Montgomery Reduction}
+\end{figure}
+
+The algorithm reduces the input one bit at a time using the two congruencies stated previously. Inside the loop $n$, which is odd, is
+added to $x$ if $x$ is odd. This forces $x$ to be even which allows the division by two in $\Z$ to be congruent to a modular division by two. Since
+$x$ is assumed to be initially much larger than $n$ the addition of $n$ will contribute an insignificant magnitude to $x$. Let $r$ represent the
+final result of the Montgomery algorithm. If $k > lg(n)$ and $0 \le x < n^2$ then the final result is limited to
+$0 \le r < \lfloor x/2^k \rfloor + n$. As a result at most a single subtraction is required to get the residue desired.
+
+\begin{figure}[here]
+\begin{small}
+\begin{center}
+\begin{tabular}{|c|l|}
+\hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} \\
+\hline $1$ & $x + n = 5812$, $x/2 = 2906$ \\
+\hline $2$ & $x/2 = 1453$ \\
+\hline $3$ & $x + n = 1710$, $x/2 = 855$ \\
+\hline $4$ & $x + n = 1112$, $x/2 = 556$ \\
+\hline $5$ & $x/2 = 278$ \\
+\hline $6$ & $x/2 = 139$ \\
+\hline $7$ & $x + n = 396$, $x/2 = 198$ \\
+\hline $8$ & $x/2 = 99$ \\
+\hline $9$ & $x + n = 356$, $x/2 = 178$ \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Example of Montgomery Reduction (I)}
+\label{fig:MONT1}
+\end{figure}
+
+Consider the example in figure~\ref{fig:MONT1} which reduces $x = 5555$ modulo $n = 257$ when $k = 9$ (note $\beta^k = 512$ which is larger than $n$). The result of
+the algorithm $r = 178$ is congruent to the value of $2^{-9} \cdot 5555 \mbox{ (mod }257\mbox{)}$. When $r$ is multiplied by $2^9$ modulo $257$ the correct residue
+$r \equiv 158$ is produced.
+
+Let $k = \lfloor lg(n) \rfloor + 1$ represent the number of bits in $n$. The current algorithm requires $2k^2$ single precision shifts
+and $k^2$ single precision additions. At this rate the algorithm is most certainly slower than Barrett reduction and not terribly useful.
+Fortunately there exists an alternative representation of the algorithm.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Montgomery Reduction} (modified I). \\
+\textbf{Input}. Integer $x$, $n$ and $k$ ($2^k > n$) \\
+\textbf{Output}. $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\
+\hline \\
+1. for $t$ from $1$ to $k$ do \\
+\hspace{3mm}1.1 If the $t$'th bit of $x$ is one then \\
+\hspace{6mm}1.1.1 $x \leftarrow x + 2^tn$ \\
+2. Return $x/2^k$. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm Montgomery Reduction (modified I)}
+\end{figure}
+
+This algorithm is equivalent since $2^tn$ is a multiple of $n$ and the lower $k$ bits of $x$ are zero by step 2. The number of single
+precision shifts has now been reduced from $2k^2$ to $k^2 + k$ which is only a small improvement.
+
+\begin{figure}[here]
+\begin{small}
+\begin{center}
+\begin{tabular}{|c|l|r|}
+\hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} & \textbf{Result ($x$) in Binary} \\
+\hline -- & $5555$ & $1010110110011$ \\
+\hline $1$ & $x + 2^{0}n = 5812$ & $1011010110100$ \\
+\hline $2$ & $5812$ & $1011010110100$ \\
+\hline $3$ & $x + 2^{2}n = 6840$ & $1101010111000$ \\
+\hline $4$ & $x + 2^{3}n = 8896$ & $10001011000000$ \\
+\hline $5$ & $8896$ & $10001011000000$ \\
+\hline $6$ & $8896$ & $10001011000000$ \\
+\hline $7$ & $x + 2^{6}n = 25344$ & $110001100000000$ \\
+\hline $8$ & $25344$ & $110001100000000$ \\
+\hline $9$ & $x + 2^{7}n = 91136$ & $10110010000000000$ \\
+\hline -- & $x/2^k = 178$ & \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Example of Montgomery Reduction (II)}
+\label{fig:MONT2}
+\end{figure}
+
+Figure~\ref{fig:MONT2} demonstrates the modified algorithm reducing $x = 5555$ modulo $n = 257$ with $k = 9$.
+With this algorithm a single shift right at the end is the only right shift required to reduce the input instead of $k$ right shifts inside the
+loop. Note that for the iterations $t = 2, 5, 6$ and $8$ where the result $x$ is not changed. In those iterations the $t$'th bit of $x$ is
+zero and the appropriate multiple of $n$ does not need to be added to force the $t$'th bit of the result to zero.
+
+\subsection{Digit Based Montgomery Reduction}
+Instead of computing the reduction on a bit-by-bit basis it is actually much faster to compute it on digit-by-digit basis. Consider the
+previous algorithm re-written to compute the Montgomery reduction in this new fashion.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Montgomery Reduction} (modified II). \\
+\textbf{Input}. Integer $x$, $n$ and $k$ ($\beta^k > n$) \\
+\textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
+\hline \\
+1. for $t$ from $0$ to $k - 1$ do \\
+\hspace{3mm}1.1 $x \leftarrow x + \mu n \beta^t$ \\
+2. Return $x/\beta^k$. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm Montgomery Reduction (modified II)}
+\end{figure}
+
+The value $\mu n \beta^t$ is a multiple of the modulus $n$ meaning that it will not change the residue. If the first digit of
+the value $\mu n \beta^t$ equals the negative (modulo $\beta$) of the $t$'th digit of $x$ then the addition will result in a zero digit. This
+problem breaks down to solving the following congruency.
+
+\begin{center}
+\begin{tabular}{rcl}
+$x_t + \mu n_0$ & $\equiv$ & $0 \mbox{ (mod }\beta\mbox{)}$ \\
+$\mu n_0$ & $\equiv$ & $-x_t \mbox{ (mod }\beta\mbox{)}$ \\
+$\mu$ & $\equiv$ & $-x_t/n_0 \mbox{ (mod }\beta\mbox{)}$ \\
+\end{tabular}
+\end{center}
+
+In each iteration of the loop on step 1 a new value of $\mu$ must be calculated. The value of $-1/n_0 \mbox{ (mod }\beta\mbox{)}$ is used
+extensively in this algorithm and should be precomputed. Let $\rho$ represent the negative of the modular inverse of $n_0$ modulo $\beta$.
+
+For example, let $\beta = 10$ represent the radix. Let $n = 17$ represent the modulus which implies $k = 2$ and $\rho \equiv 7$. Let $x = 33$
+represent the value to reduce.
+
+\newpage\begin{figure}
+\begin{center}
+\begin{tabular}{|c|c|c|}
+\hline \textbf{Step ($t$)} & \textbf{Value of $x$} & \textbf{Value of $\mu$} \\
+\hline -- & $33$ & --\\
+\hline $0$ & $33 + \mu n = 50$ & $1$ \\
+\hline $1$ & $50 + \mu n \beta = 900$ & $5$ \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Example of Montgomery Reduction}
+\end{figure}
+
+The final result $900$ is then divided by $\beta^k$ to produce the final result $9$. The first observation is that $9 \nequiv x \mbox{ (mod }n\mbox{)}$
+which implies the result is not the modular residue of $x$ modulo $n$. However, recall that the residue is actually multiplied by $\beta^{-k}$ in
+the algorithm. To get the true residue the value must be multiplied by $\beta^k$. In this case $\beta^k \equiv 15 \mbox{ (mod }n\mbox{)}$ and
+the correct residue is $9 \cdot 15 \equiv 16 \mbox{ (mod }n\mbox{)}$.
+
+\subsection{Baseline Montgomery Reduction}
+The baseline Montgomery reduction algorithm will produce the residue for any size input. It is designed to be a catch-all algororithm for
+Montgomery reductions.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_montgomery\_reduce}. \\
+\textbf{Input}. mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\
+\hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\
+\textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
+\hline \\
+1. $digs \leftarrow 2n.used + 1$ \\
+2. If $digs < MP\_ARRAY$ and $m.used < \delta$ then \\
+\hspace{3mm}2.1 Use algorithm fast\_mp\_montgomery\_reduce instead. \\
+\\
+Setup $x$ for the reduction. \\
+3. If $x.alloc < digs$ then grow $x$ to $digs$ digits. \\
+4. $x.used \leftarrow digs$ \\
+\\
+Eliminate the lower $k$ digits. \\
+5. For $ix$ from $0$ to $k - 1$ do \\
+\hspace{3mm}5.1 $\mu \leftarrow x_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{3mm}5.2 $u \leftarrow 0$ \\
+\hspace{3mm}5.3 For $iy$ from $0$ to $k - 1$ do \\
+\hspace{6mm}5.3.1 $\hat r \leftarrow \mu n_{iy} + x_{ix + iy} + u$ \\
+\hspace{6mm}5.3.2 $x_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{6mm}5.3.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
+\hspace{3mm}5.4 While $u > 0$ do \\
+\hspace{6mm}5.4.1 $iy \leftarrow iy + 1$ \\
+\hspace{6mm}5.4.2 $x_{ix + iy} \leftarrow x_{ix + iy} + u$ \\
+\hspace{6mm}5.4.3 $u \leftarrow \lfloor x_{ix+iy} / \beta \rfloor$ \\
+\hspace{6mm}5.4.4 $x_{ix + iy} \leftarrow x_{ix+iy} \mbox{ (mod }\beta\mbox{)}$ \\
+\\
+Divide by $\beta^k$ and fix up as required. \\
+6. $x \leftarrow \lfloor x / \beta^k \rfloor$ \\
+7. If $x \ge n$ then \\
+\hspace{3mm}7.1 $x \leftarrow x - n$ \\
+8. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_montgomery\_reduce}
+\end{figure}
+
+\textbf{Algorithm mp\_montgomery\_reduce.}
+This algorithm reduces the input $x$ modulo $n$ in place using the Montgomery reduction algorithm. The algorithm is loosely based
+on algorithm 14.32 of \cite[pp.601]{HAC} except it merges the multiplication of $\mu n \beta^t$ with the addition in the inner loop. The
+restrictions on this algorithm are fairly easy to adapt to. First $0 \le x < n^2$ bounds the input to numbers in the same range as
+for the Barrett algorithm. Additionally if $n > 1$ and $n$ is odd there will exist a modular inverse $\rho$. $\rho$ must be calculated in
+advance of this algorithm. Finally the variable $k$ is fixed and a pseudonym for $n.used$.
+
+Step 2 decides whether a faster Montgomery algorithm can be used. It is based on the Comba technique meaning that there are limits on
+the size of the input. This algorithm is discussed in sub-section 6.3.3.
+
+Step 5 is the main reduction loop of the algorithm. The value of $\mu$ is calculated once per iteration in the outer loop. The inner loop
+calculates $x + \mu n \beta^{ix}$ by multiplying $\mu n$ and adding the result to $x$ shifted by $ix$ digits. Both the addition and
+multiplication are performed in the same loop to save time and memory. Step 5.4 will handle any additional carries that escape the inner loop.
+
+Using a quick inspection this algorithm requires $n$ single precision multiplications for the outer loop and $n^2$ single precision multiplications
+in the inner loop. In total $n^2 + n$ single precision multiplications which compares favourably to Barrett at $n^2 + 2n - 1$ single precision
+multiplications.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_montgomery\_reduce.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+This is the baseline implementation of the Montgomery reduction algorithm. Lines 31 to 36 determine if the Comba based
+routine can be used instead. Line 47 computes the value of $\mu$ for that particular iteration of the outer loop.
+
+The multiplication $\mu n \beta^{ix}$ is performed in one step in the inner loop. The alias $tmpx$ refers to the $ix$'th digit of $x$ and
+the alias $tmpn$ refers to the modulus $n$.
+
+\subsection{Faster ``Comba'' Montgomery Reduction}
+
+The Montgomery reduction requires fewer single precision multiplications than a Barrett reduction, however it is much slower due to the serial
+nature of the inner loop. The Barrett reduction algorithm requires two slightly modified multipliers which can be implemented with the Comba
+technique. The Montgomery reduction algorithm cannot directly use the Comba technique to any significant advantage since the inner loop calculates
+a $k \times 1$ product $k$ times.
+
+The biggest obstacle is that at the $ix$'th iteration of the outer loop the value of $x_{ix}$ is required to calculate $\mu$. This means the
+carries from $0$ to $ix - 1$ must have been propagated upwards to form a valid $ix$'th digit. The solution as it turns out is very simple.
+Perform a Comba like multiplier and inside the outer loop just after the inner loop fix up the $ix + 1$'th digit by forwarding the carry.
+
+With this change in place the Montgomery reduction algorithm can be performed with a Comba style multiplication loop which substantially increases
+the speed of the algorithm.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{fast\_mp\_montgomery\_reduce}. \\
+\textbf{Input}. mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\
+\hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\
+\textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
+\hline \\
+Place an array of \textbf{MP\_WARRAY} mp\_word variables called $\hat W$ on the stack. \\
+1. if $x.alloc < n.used + 1$ then grow $x$ to $n.used + 1$ digits. \\
+Copy the digits of $x$ into the array $\hat W$ \\
+2. For $ix$ from $0$ to $x.used - 1$ do \\
+\hspace{3mm}2.1 $\hat W_{ix} \leftarrow x_{ix}$ \\
+3. For $ix$ from $x.used$ to $2n.used - 1$ do \\
+\hspace{3mm}3.1 $\hat W_{ix} \leftarrow 0$ \\
+Elimiate the lower $k$ digits. \\
+4. for $ix$ from $0$ to $n.used - 1$ do \\
+\hspace{3mm}4.1 $\mu \leftarrow \hat W_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{3mm}4.2 For $iy$ from $0$ to $n.used - 1$ do \\
+\hspace{6mm}4.2.1 $\hat W_{iy + ix} \leftarrow \hat W_{iy + ix} + \mu \cdot n_{iy}$ \\
+\hspace{3mm}4.3 $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\
+Propagate carries upwards. \\
+5. for $ix$ from $n.used$ to $2n.used + 1$ do \\
+\hspace{3mm}5.1 $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\
+Shift right and reduce modulo $\beta$ simultaneously. \\
+6. for $ix$ from $0$ to $n.used + 1$ do \\
+\hspace{3mm}6.1 $x_{ix} \leftarrow \hat W_{ix + n.used} \mbox{ (mod }\beta\mbox{)}$ \\
+Zero excess digits and fixup $x$. \\
+7. if $x.used > n.used + 1$ then do \\
+\hspace{3mm}7.1 for $ix$ from $n.used + 1$ to $x.used - 1$ do \\
+\hspace{6mm}7.1.1 $x_{ix} \leftarrow 0$ \\
+8. $x.used \leftarrow n.used + 1$ \\
+9. Clamp excessive digits of $x$. \\
+10. If $x \ge n$ then \\
+\hspace{3mm}10.1 $x \leftarrow x - n$ \\
+11. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm fast\_mp\_montgomery\_reduce}
+\end{figure}
+
+\textbf{Algorithm fast\_mp\_montgomery\_reduce.}
+This algorithm will compute the Montgomery reduction of $x$ modulo $n$ using the Comba technique. It is on most computer platforms significantly
+faster than algorithm mp\_montgomery\_reduce and algorithm mp\_reduce (\textit{Barrett reduction}). The algorithm has the same restrictions
+on the input as the baseline reduction algorithm. An additional two restrictions are imposed on this algorithm. The number of digits $k$ in the
+the modulus $n$ must not violate $MP\_WARRAY > 2k +1$ and $n < \delta$. When $\beta = 2^{28}$ this algorithm can be used to reduce modulo
+a modulus of at most $3,556$ bits in length.
+
+As in the other Comba reduction algorithms there is a $\hat W$ array which stores the columns of the product. It is initially filled with the
+contents of $x$ with the excess digits zeroed. The reduction loop is very similar the to the baseline loop at heart. The multiplication on step
+4.1 can be single precision only since $ab \mbox{ (mod }\beta\mbox{)} \equiv (a \mbox{ mod }\beta)(b \mbox{ mod }\beta)$. Some multipliers such
+as those on the ARM processors take a variable length time to complete depending on the number of bytes of result it must produce. By performing
+a single precision multiplication instead half the amount of time is spent.
+
+Also note that digit $\hat W_{ix}$ must have the carry from the $ix - 1$'th digit propagated upwards in order for this to work. That is what step
+4.3 will do. In effect over the $n.used$ iterations of the outer loop the $n.used$'th lower columns all have the their carries propagated forwards. Note
+how the upper bits of those same words are not reduced modulo $\beta$. This is because those values will be discarded shortly and there is no
+point.
+
+Step 5 will propagate the remainder of the carries upwards. On step 6 the columns are reduced modulo $\beta$ and shifted simultaneously as they are
+stored in the destination $x$.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_fast\_mp\_montgomery\_reduce.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+The $\hat W$ array is first filled with digits of $x$ on line 48 then the rest of the digits are zeroed on line 55. Both loops share
+the same alias variables to make the code easier to read.
+
+The value of $\mu$ is calculated in an interesting fashion. First the value $\hat W_{ix}$ is reduced modulo $\beta$ and cast to a mp\_digit. This
+forces the compiler to use a single precision multiplication and prevents any concerns about loss of precision. Line 110 fixes the carry
+for the next iteration of the loop by propagating the carry from $\hat W_{ix}$ to $\hat W_{ix+1}$.
+
+The for loop on line 109 propagates the rest of the carries upwards through the columns. The for loop on line 126 reduces the columns
+modulo $\beta$ and shifts them $k$ places at the same time. The alias $\_ \hat W$ actually refers to the array $\hat W$ starting at the $n.used$'th
+digit, that is $\_ \hat W_{t} = \hat W_{n.used + t}$.
+
+\subsection{Montgomery Setup}
+To calculate the variable $\rho$ a relatively simple algorithm will be required.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_montgomery\_setup}. \\
+\textbf{Input}. mp\_int $n$ ($n > 1$ and $(n, 2) = 1$) \\
+\textbf{Output}. $\rho \equiv -1/n_0 \mbox{ (mod }\beta\mbox{)}$ \\
+\hline \\
+1. $b \leftarrow n_0$ \\
+2. If $b$ is even return(\textit{MP\_VAL}) \\
+3. $x \leftarrow (((b + 2) \mbox{ AND } 4) << 1) + b$ \\
+4. for $k$ from 0 to $\lceil lg(lg(\beta)) \rceil - 2$ do \\
+\hspace{3mm}4.1 $x \leftarrow x \cdot (2 - bx)$ \\
+5. $\rho \leftarrow \beta - x \mbox{ (mod }\beta\mbox{)}$ \\
+6. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_montgomery\_setup}
+\end{figure}
+
+\textbf{Algorithm mp\_montgomery\_setup.}
+This algorithm will calculate the value of $\rho$ required within the Montgomery reduction algorithms. It uses a very interesting trick
+to calculate $1/n_0$ when $\beta$ is a power of two.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_montgomery\_setup.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+This source code computes the value of $\rho$ required to perform Montgomery reduction. It has been modified to avoid performing excess
+multiplications when $\beta$ is not the default 28-bits.
+
+\section{The Diminished Radix Algorithm}
+The Diminished Radix method of modular reduction \cite{DRMET} is a fairly clever technique which can be more efficient than either the Barrett
+or Montgomery methods for certain forms of moduli. The technique is based on the following simple congruence.
+
+\begin{equation}
+(x \mbox{ mod } n) + k \lfloor x / n \rfloor \equiv x \mbox{ (mod }(n - k)\mbox{)}
+\end{equation}
+
+This observation was used in the MMB \cite{MMB} block cipher to create a diffusion primitive. It used the fact that if $n = 2^{31}$ and $k=1$ that
+then a x86 multiplier could produce the 62-bit product and use the ``shrd'' instruction to perform a double-precision right shift. The proof
+of the above equation is very simple. First write $x$ in the product form.
+
+\begin{equation}
+x = qn + r
+\end{equation}
+
+Now reduce both sides modulo $(n - k)$.
+
+\begin{equation}
+x \equiv qk + r \mbox{ (mod }(n-k)\mbox{)}
+\end{equation}
+
+The variable $n$ reduces modulo $n - k$ to $k$. By putting $q = \lfloor x/n \rfloor$ and $r = x \mbox{ mod } n$
+into the equation the original congruence is reproduced, thus concluding the proof. The following algorithm is based on this observation.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Diminished Radix Reduction}. \\
+\textbf{Input}. Integer $x$, $n$, $k$ \\
+\textbf{Output}. $x \mbox{ mod } (n - k)$ \\
+\hline \\
+1. $q \leftarrow \lfloor x / n \rfloor$ \\
+2. $q \leftarrow k \cdot q$ \\
+3. $x \leftarrow x \mbox{ (mod }n\mbox{)}$ \\
+4. $x \leftarrow x + q$ \\
+5. If $x \ge (n - k)$ then \\
+\hspace{3mm}5.1 $x \leftarrow x - (n - k)$ \\
+\hspace{3mm}5.2 Goto step 1. \\
+6. Return $x$ \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm Diminished Radix Reduction}
+\label{fig:DR}
+\end{figure}
+
+This algorithm will reduce $x$ modulo $n - k$ and return the residue. If $0 \le x < (n - k)^2$ then the algorithm will loop almost always
+once or twice and occasionally three times. For simplicity sake the value of $x$ is bounded by the following simple polynomial.
+
+\begin{equation}
+0 \le x < n^2 + k^2 - 2nk
+\end{equation}
+
+The true bound is $0 \le x < (n - k - 1)^2$ but this has quite a few more terms. The value of $q$ after step 1 is bounded by the following.
+
+\begin{equation}
+q < n - 2k - k^2/n
+\end{equation}
+
+Since $k^2$ is going to be considerably smaller than $n$ that term will always be zero. The value of $x$ after step 3 is bounded trivially as
+$0 \le x < n$. By step four the sum $x + q$ is bounded by
+
+\begin{equation}
+0 \le q + x < (k + 1)n - 2k^2 - 1
+\end{equation}
+
+With a second pass $q$ will be loosely bounded by $0 \le q < k^2$ after step 2 while $x$ will still be loosely bounded by $0 \le x < n$ after step 3. After the second pass it is highly unlike that the
+sum in step 4 will exceed $n - k$. In practice fewer than three passes of the algorithm are required to reduce virtually every input in the
+range $0 \le x < (n - k - 1)^2$.
+
+\begin{figure}
+\begin{small}
+\begin{center}
+\begin{tabular}{|l|}
+\hline
+$x = 123456789, n = 256, k = 3$ \\
+\hline $q \leftarrow \lfloor x/n \rfloor = 482253$ \\
+$q \leftarrow q*k = 1446759$ \\
+$x \leftarrow x \mbox{ mod } n = 21$ \\
+$x \leftarrow x + q = 1446780$ \\
+$x \leftarrow x - (n - k) = 1446527$ \\
+\hline
+$q \leftarrow \lfloor x/n \rfloor = 5650$ \\
+$q \leftarrow q*k = 16950$ \\
+$x \leftarrow x \mbox{ mod } n = 127$ \\
+$x \leftarrow x + q = 17077$ \\
+$x \leftarrow x - (n - k) = 16824$ \\
+\hline
+$q \leftarrow \lfloor x/n \rfloor = 65$ \\
+$q \leftarrow q*k = 195$ \\
+$x \leftarrow x \mbox{ mod } n = 184$ \\
+$x \leftarrow x + q = 379$ \\
+$x \leftarrow x - (n - k) = 126$ \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Example Diminished Radix Reduction}
+\label{fig:EXDR}
+\end{figure}
+
+Figure~\ref{fig:EXDR} demonstrates the reduction of $x = 123456789$ modulo $n - k = 253$ when $n = 256$ and $k = 3$. Note that even while $x$
+is considerably larger than $(n - k - 1)^2 = 63504$ the algorithm still converges on the modular residue exceedingly fast. In this case only
+three passes were required to find the residue $x \equiv 126$.
+
+
+\subsection{Choice of Moduli}
+On the surface this algorithm looks like a very expensive algorithm. It requires a couple of subtractions followed by multiplication and other
+modular reductions. The usefulness of this algorithm becomes exceedingly clear when an appropriate modulus is chosen.
+
+Division in general is a very expensive operation to perform. The one exception is when the division is by a power of the radix of representation used.
+Division by ten for example is simple for pencil and paper mathematics since it amounts to shifting the decimal place to the right. Similarly division
+by two (\textit{or powers of two}) is very simple for binary computers to perform. It would therefore seem logical to choose $n$ of the form $2^p$
+which would imply that $\lfloor x / n \rfloor$ is a simple shift of $x$ right $p$ bits.
+
+However, there is one operation related to division of power of twos that is even faster than this. If $n = \beta^p$ then the division may be
+performed by moving whole digits to the right $p$ places. In practice division by $\beta^p$ is much faster than division by $2^p$ for any $p$.
+Also with the choice of $n = \beta^p$ reducing $x$ modulo $n$ merely requires zeroing the digits above the $p-1$'th digit of $x$.
+
+Throughout the next section the term ``restricted modulus'' will refer to a modulus of the form $\beta^p - k$ whereas the term ``unrestricted
+modulus'' will refer to a modulus of the form $2^p - k$. The word ``restricted'' in this case refers to the fact that it is based on the
+$2^p$ logic except $p$ must be a multiple of $lg(\beta)$.
+
+\subsection{Choice of $k$}
+Now that division and reduction (\textit{step 1 and 3 of figure~\ref{fig:DR}}) have been optimized to simple digit operations the multiplication by $k$
+in step 2 is the most expensive operation. Fortunately the choice of $k$ is not terribly limited. For all intents and purposes it might
+as well be a single digit. The smaller the value of $k$ is the faster the algorithm will be.
+
+\subsection{Restricted Diminished Radix Reduction}
+The restricted Diminished Radix algorithm can quickly reduce an input modulo a modulus of the form $n = \beta^p - k$. This algorithm can reduce
+an input $x$ within the range $0 \le x < n^2$ using only a couple passes of the algorithm demonstrated in figure~\ref{fig:DR}. The implementation
+of this algorithm has been optimized to avoid additional overhead associated with a division by $\beta^p$, the multiplication by $k$ or the addition
+of $x$ and $q$. The resulting algorithm is very efficient and can lead to substantial improvements over Barrett and Montgomery reduction when modular
+exponentiations are performed.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_dr\_reduce}. \\
+\textbf{Input}. mp\_int $x$, $n$ and a mp\_digit $k = \beta - n_0$ \\
+\hspace{11.5mm}($0 \le x < n^2$, $n > 1$, $0 < k < \beta$) \\
+\textbf{Output}. $x \mbox{ mod } n$ \\
+\hline \\
+1. $m \leftarrow n.used$ \\
+2. If $x.alloc < 2m$ then grow $x$ to $2m$ digits. \\
+3. $\mu \leftarrow 0$ \\
+4. for $i$ from $0$ to $m - 1$ do \\
+\hspace{3mm}4.1 $\hat r \leftarrow k \cdot x_{m+i} + x_{i} + \mu$ \\
+\hspace{3mm}4.2 $x_{i} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{3mm}4.3 $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\
+5. $x_{m} \leftarrow \mu$ \\
+6. for $i$ from $m + 1$ to $x.used - 1$ do \\
+\hspace{3mm}6.1 $x_{i} \leftarrow 0$ \\
+7. Clamp excess digits of $x$. \\
+8. If $x \ge n$ then \\
+\hspace{3mm}8.1 $x \leftarrow x - n$ \\
+\hspace{3mm}8.2 Goto step 3. \\
+9. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_dr\_reduce}
+\end{figure}
+
+\textbf{Algorithm mp\_dr\_reduce.}
+This algorithm will perform the Dimished Radix reduction of $x$ modulo $n$. It has similar restrictions to that of the Barrett reduction
+with the addition that $n$ must be of the form $n = \beta^m - k$ where $0 < k <\beta$.
+
+This algorithm essentially implements the pseudo-code in figure~\ref{fig:DR} except with a slight optimization. The division by $\beta^m$, multiplication by $k$
+and addition of $x \mbox{ mod }\beta^m$ are all performed simultaneously inside the loop on step 4. The division by $\beta^m$ is emulated by accessing
+the term at the $m+i$'th position which is subsequently multiplied by $k$ and added to the term at the $i$'th position. After the loop the $m$'th
+digit is set to the carry and the upper digits are zeroed. Steps 5 and 6 emulate the reduction modulo $\beta^m$ that should have happend to
+$x$ before the addition of the multiple of the upper half.
+
+At step 8 if $x$ is still larger than $n$ another pass of the algorithm is required. First $n$ is subtracted from $x$ and then the algorithm resumes
+at step 3.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_dr\_reduce.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+The first step is to grow $x$ as required to $2m$ digits since the reduction is performed in place on $x$. The label on line 52 is where
+the algorithm will resume if further reduction passes are required. In theory it could be placed at the top of the function however, the size of
+the modulus and question of whether $x$ is large enough are invariant after the first pass meaning that it would be a waste of time.
+
+The aliases $tmpx1$ and $tmpx2$ refer to the digits of $x$ where the latter is offset by $m$ digits. By reading digits from $x$ offset by $m$ digits
+a division by $\beta^m$ can be simulated virtually for free. The loop on line 64 performs the bulk of the work (\textit{corresponds to step 4 of algorithm 7.11})
+in this algorithm.
+
+By line 67 the pointer $tmpx1$ points to the $m$'th digit of $x$ which is where the final carry will be placed. Similarly by line 74 the
+same pointer will point to the $m+1$'th digit where the zeroes will be placed.
+
+Since the algorithm is only valid if both $x$ and $n$ are greater than zero an unsigned comparison suffices to determine if another pass is required.
+With the same logic at line 81 the value of $x$ is known to be greater than or equal to $n$ meaning that an unsigned subtraction can be used
+as well. Since the destination of the subtraction is the larger of the inputs the call to algorithm s\_mp\_sub cannot fail and the return code
+does not need to be checked.
+
+\subsubsection{Setup}
+To setup the restricted Diminished Radix algorithm the value $k = \beta - n_0$ is required. This algorithm is not really complicated but provided for
+completeness.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_dr\_setup}. \\
+\textbf{Input}. mp\_int $n$ \\
+\textbf{Output}. $k = \beta - n_0$ \\
+\hline \\
+1. $k \leftarrow \beta - n_0$ \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_dr\_setup}
+\end{figure}
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_dr\_setup.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+\subsubsection{Modulus Detection}
+Another algorithm which will be useful is the ability to detect a restricted Diminished Radix modulus. An integer is said to be
+of restricted Diminished Radix form if all of the digits are equal to $\beta - 1$ except the trailing digit which may be any value.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_dr\_is\_modulus}. \\
+\textbf{Input}. mp\_int $n$ \\
+\textbf{Output}. $1$ if $n$ is in D.R form, $0$ otherwise \\
+\hline
+1. If $n.used < 2$ then return($0$). \\
+2. for $ix$ from $1$ to $n.used - 1$ do \\
+\hspace{3mm}2.1 If $n_{ix} \ne \beta - 1$ return($0$). \\
+3. Return($1$). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_dr\_is\_modulus}
+\end{figure}
+
+\textbf{Algorithm mp\_dr\_is\_modulus.}
+This algorithm determines if a value is in Diminished Radix form. Step 1 rejects obvious cases where fewer than two digits are
+in the mp\_int. Step 2 tests all but the first digit to see if they are equal to $\beta - 1$. If the algorithm manages to get to
+step 3 then $n$ must be of Diminished Radix form.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_dr\_is\_modulus.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+\subsection{Unrestricted Diminished Radix Reduction}
+The unrestricted Diminished Radix algorithm allows modular reductions to be performed when the modulus is of the form $2^p - k$. This algorithm
+is a straightforward adaptation of algorithm~\ref{fig:DR}.
+
+In general the restricted Diminished Radix reduction algorithm is much faster since it has considerably lower overhead. However, this new
+algorithm is much faster than either Montgomery or Barrett reduction when the moduli are of the appropriate form.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_reduce\_2k}. \\
+\textbf{Input}. mp\_int $a$ and $n$. mp\_digit $k$ \\
+\hspace{11.5mm}($a \ge 0$, $n > 1$, $0 < k < \beta$, $n + k$ is a power of two) \\
+\textbf{Output}. $a \mbox{ (mod }n\mbox{)}$ \\
+\hline
+1. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\
+2. While $a \ge n$ do \\
+\hspace{3mm}2.1 $q \leftarrow \lfloor a / 2^p \rfloor$ (\textit{mp\_div\_2d}) \\
+\hspace{3mm}2.2 $a \leftarrow a \mbox{ (mod }2^p\mbox{)}$ (\textit{mp\_mod\_2d}) \\
+\hspace{3mm}2.3 $q \leftarrow q \cdot k$ (\textit{mp\_mul\_d}) \\
+\hspace{3mm}2.4 $a \leftarrow a - q$ (\textit{s\_mp\_sub}) \\
+\hspace{3mm}2.5 If $a \ge n$ then do \\
+\hspace{6mm}2.5.1 $a \leftarrow a - n$ \\
+3. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_reduce\_2k}
+\end{figure}
+
+\textbf{Algorithm mp\_reduce\_2k.}
+This algorithm quickly reduces an input $a$ modulo an unrestricted Diminished Radix modulus $n$. Division by $2^p$ is emulated with a right
+shift which makes the algorithm fairly inexpensive to use.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_2k.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+The algorithm mp\_count\_bits calculates the number of bits in an mp\_int which is used to find the initial value of $p$. The call to mp\_div\_2d
+on line 31 calculates both the quotient $q$ and the remainder $a$ required. By doing both in a single function call the code size
+is kept fairly small. The multiplication by $k$ is only performed if $k > 1$. This allows reductions modulo $2^p - 1$ to be performed without
+any multiplications.
+
+The unsigned s\_mp\_add, mp\_cmp\_mag and s\_mp\_sub are used in place of their full sign counterparts since the inputs are only valid if they are
+positive. By using the unsigned versions the overhead is kept to a minimum.
+
+\subsubsection{Unrestricted Setup}
+To setup this reduction algorithm the value of $k = 2^p - n$ is required.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_reduce\_2k\_setup}. \\
+\textbf{Input}. mp\_int $n$ \\
+\textbf{Output}. $k = 2^p - n$ \\
+\hline
+1. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\
+2. $x \leftarrow 2^p$ (\textit{mp\_2expt}) \\
+3. $x \leftarrow x - n$ (\textit{mp\_sub}) \\
+4. $k \leftarrow x_0$ \\
+5. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_reduce\_2k\_setup}
+\end{figure}
+
+\textbf{Algorithm mp\_reduce\_2k\_setup.}
+This algorithm computes the value of $k$ required for the algorithm mp\_reduce\_2k. By making a temporary variable $x$ equal to $2^p$ a subtraction
+is sufficient to solve for $k$. Alternatively if $n$ has more than one digit the value of $k$ is simply $\beta - n_0$.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_2k\_setup.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+\subsubsection{Unrestricted Detection}
+An integer $n$ is a valid unrestricted Diminished Radix modulus if either of the following are true.
+
+\begin{enumerate}
+\item The number has only one digit.
+\item The number has more than one digit and every bit from the $\beta$'th to the most significant is one.
+\end{enumerate}
+
+If either condition is true than there is a power of two $2^p$ such that $0 < 2^p - n < \beta$. If the input is only
+one digit than it will always be of the correct form. Otherwise all of the bits above the first digit must be one. This arises from the fact
+that there will be value of $k$ that when added to the modulus causes a carry in the first digit which propagates all the way to the most
+significant bit. The resulting sum will be a power of two.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_reduce\_is\_2k}. \\
+\textbf{Input}. mp\_int $n$ \\
+\textbf{Output}. $1$ if of proper form, $0$ otherwise \\
+\hline
+1. If $n.used = 0$ then return($0$). \\
+2. If $n.used = 1$ then return($1$). \\
+3. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\
+4. for $x$ from $lg(\beta)$ to $p$ do \\
+\hspace{3mm}4.1 If the ($x \mbox{ mod }lg(\beta)$)'th bit of the $\lfloor x / lg(\beta) \rfloor$ of $n$ is zero then return($0$). \\
+5. Return($1$). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_reduce\_is\_2k}
+\end{figure}
+
+\textbf{Algorithm mp\_reduce\_is\_2k.}
+This algorithm quickly determines if a modulus is of the form required for algorithm mp\_reduce\_2k to function properly.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_is\_2k.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+
+
+\section{Algorithm Comparison}
+So far three very different algorithms for modular reduction have been discussed. Each of the algorithms have their own strengths and weaknesses
+that makes having such a selection very useful. The following table sumarizes the three algorithms along with comparisons of work factors. Since
+all three algorithms have the restriction that $0 \le x < n^2$ and $n > 1$ those limitations are not included in the table.
+
+\begin{center}
+\begin{small}
+\begin{tabular}{|c|c|c|c|c|c|}
+\hline \textbf{Method} & \textbf{Work Required} & \textbf{Limitations} & \textbf{$m = 8$} & \textbf{$m = 32$} & \textbf{$m = 64$} \\
+\hline Barrett & $m^2 + 2m - 1$ & None & $79$ & $1087$ & $4223$ \\
+\hline Montgomery & $m^2 + m$ & $n$ must be odd & $72$ & $1056$ & $4160$ \\
+\hline D.R. & $2m$ & $n = \beta^m - k$ & $16$ & $64$ & $128$ \\
+\hline
+\end{tabular}
+\end{small}
+\end{center}
+
+In theory Montgomery and Barrett reductions would require roughly the same amount of time to complete. However, in practice since Montgomery
+reduction can be written as a single function with the Comba technique it is much faster. Barrett reduction suffers from the overhead of
+calling the half precision multipliers, addition and division by $\beta$ algorithms.
+
+For almost every cryptographic algorithm Montgomery reduction is the algorithm of choice. The one set of algorithms where Diminished Radix reduction truly
+shines are based on the discrete logarithm problem such as Diffie-Hellman \cite{DH} and ElGamal \cite{ELGAMAL}. In these algorithms
+primes of the form $\beta^m - k$ can be found and shared amongst users. These primes will allow the Diminished Radix algorithm to be used in
+modular exponentiation to greatly speed up the operation.
+
+
+
+\section*{Exercises}
+\begin{tabular}{cl}
+$\left [ 3 \right ]$ & Prove that the ``trick'' in algorithm mp\_montgomery\_setup actually \\
+ & calculates the correct value of $\rho$. \\
+ & \\
+$\left [ 2 \right ]$ & Devise an algorithm to reduce modulo $n + k$ for small $k$ quickly. \\
+ & \\
+$\left [ 4 \right ]$ & Prove that the pseudo-code algorithm ``Diminished Radix Reduction'' \\
+ & (\textit{figure~\ref{fig:DR}}) terminates. Also prove the probability that it will \\
+ & terminate within $1 \le k \le 10$ iterations. \\
+ & \\
+\end{tabular}
+
+
+\chapter{Exponentiation}
+Exponentiation is the operation of raising one variable to the power of another, for example, $a^b$. A variant of exponentiation, computed
+in a finite field or ring, is called modular exponentiation. This latter style of operation is typically used in public key
+cryptosystems such as RSA and Diffie-Hellman. The ability to quickly compute modular exponentiations is of great benefit to any
+such cryptosystem and many methods have been sought to speed it up.
+
+\section{Exponentiation Basics}
+A trivial algorithm would simply multiply $a$ against itself $b - 1$ times to compute the exponentiation desired. However, as $b$ grows in size
+the number of multiplications becomes prohibitive. Imagine what would happen if $b$ $\approx$ $2^{1024}$ as is the case when computing an RSA signature
+with a $1024$-bit key. Such a calculation could never be completed as it would take simply far too long.
+
+Fortunately there is a very simple algorithm based on the laws of exponents. Recall that $lg_a(a^b) = b$ and that $lg_a(a^ba^c) = b + c$ which
+are two trivial relationships between the base and the exponent. Let $b_i$ represent the $i$'th bit of $b$ starting from the least
+significant bit. If $b$ is a $k$-bit integer than the following equation is true.
+
+\begin{equation}
+a^b = \prod_{i=0}^{k-1} a^{2^i \cdot b_i}
+\end{equation}
+
+By taking the base $a$ logarithm of both sides of the equation the following equation is the result.
+
+\begin{equation}
+b = \sum_{i=0}^{k-1}2^i \cdot b_i
+\end{equation}
+
+The term $a^{2^i}$ can be found from the $i - 1$'th term by squaring the term since $\left ( a^{2^i} \right )^2$ is equal to
+$a^{2^{i+1}}$. This observation forms the basis of essentially all fast exponentiation algorithms. It requires $k$ squarings and on average
+$k \over 2$ multiplications to compute the result. This is indeed quite an improvement over simply multiplying by $a$ a total of $b-1$ times.
+
+While this current method is a considerable speed up there are further improvements to be made. For example, the $a^{2^i}$ term does not need to
+be computed in an auxilary variable. Consider the following equivalent algorithm.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Left to Right Exponentiation}. \\
+\textbf{Input}. Integer $a$, $b$ and $k$ \\
+\textbf{Output}. $c = a^b$ \\
+\hline \\
+1. $c \leftarrow 1$ \\
+2. for $i$ from $k - 1$ to $0$ do \\
+\hspace{3mm}2.1 $c \leftarrow c^2$ \\
+\hspace{3mm}2.2 $c \leftarrow c \cdot a^{b_i}$ \\
+3. Return $c$. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Left to Right Exponentiation}
+\label{fig:LTOR}
+\end{figure}
+
+This algorithm starts from the most significant bit and works towards the least significant bit. When the $i$'th bit of $b$ is set $a$ is
+multiplied against the current product. In each iteration the product is squared which doubles the exponent of the individual terms of the
+product.
+
+For example, let $b = 101100_2 \equiv 44_{10}$. The following chart demonstrates the actions of the algorithm.
+
+\newpage\begin{figure}
+\begin{center}
+\begin{tabular}{|c|c|}
+\hline \textbf{Value of $i$} & \textbf{Value of $c$} \\
+\hline - & $1$ \\
+\hline $5$ & $a$ \\
+\hline $4$ & $a^2$ \\
+\hline $3$ & $a^4 \cdot a$ \\
+\hline $2$ & $a^8 \cdot a^2 \cdot a$ \\
+\hline $1$ & $a^{16} \cdot a^4 \cdot a^2$ \\
+\hline $0$ & $a^{32} \cdot a^8 \cdot a^4$ \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Example of Left to Right Exponentiation}
+\end{figure}
+
+When the product $a^{32} \cdot a^8 \cdot a^4$ is simplified it is equal $a^{44}$ which is the desired exponentiation. This particular algorithm is
+called ``Left to Right'' because it reads the exponent in that order. All of the exponentiation algorithms that will be presented are of this nature.
+
+\subsection{Single Digit Exponentiation}
+The first algorithm in the series of exponentiation algorithms will be an unbounded algorithm where the exponent is a single digit. It is intended
+to be used when a small power of an input is required (\textit{e.g. $a^5$}). It is faster than simply multiplying $b - 1$ times for all values of
+$b$ that are greater than three.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_expt\_d}. \\
+\textbf{Input}. mp\_int $a$ and mp\_digit $b$ \\
+\textbf{Output}. $c = a^b$ \\
+\hline \\
+1. $g \leftarrow a$ (\textit{mp\_init\_copy}) \\
+2. $c \leftarrow 1$ (\textit{mp\_set}) \\
+3. for $x$ from 1 to $lg(\beta)$ do \\
+\hspace{3mm}3.1 $c \leftarrow c^2$ (\textit{mp\_sqr}) \\
+\hspace{3mm}3.2 If $b$ AND $2^{lg(\beta) - 1} \ne 0$ then \\
+\hspace{6mm}3.2.1 $c \leftarrow c \cdot g$ (\textit{mp\_mul}) \\
+\hspace{3mm}3.3 $b \leftarrow b << 1$ \\
+4. Clear $g$. \\
+5. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_expt\_d}
+\end{figure}
+
+\textbf{Algorithm mp\_expt\_d.}
+This algorithm computes the value of $a$ raised to the power of a single digit $b$. It uses the left to right exponentiation algorithm to
+quickly compute the exponentiation. It is loosely based on algorithm 14.79 of HAC \cite[pp. 615]{HAC} with the difference that the
+exponent is a fixed width.
+
+A copy of $a$ is made first to allow destination variable $c$ be the same as the source variable $a$. The result is set to the initial value of
+$1$ in the subsequent step.
+
+Inside the loop the exponent is read from the most significant bit first down to the least significant bit. First $c$ is invariably squared
+on step 3.1. In the following step if the most significant bit of $b$ is one the copy of $a$ is multiplied against $c$. The value
+of $b$ is shifted left one bit to make the next bit down from the most signficant bit the new most significant bit. In effect each
+iteration of the loop moves the bits of the exponent $b$ upwards to the most significant location.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_expt\_d.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+Line 29 sets the initial value of the result to $1$. Next the loop on line 31 steps through each bit of the exponent starting from
+the most significant down towards the least significant. The invariant squaring operation placed on line 33 is performed first. After
+the squaring the result $c$ is multiplied by the base $g$ if and only if the most significant bit of the exponent is set. The shift on line
+47 moves all of the bits of the exponent upwards towards the most significant location.
+
+\section{$k$-ary Exponentiation}
+When calculating an exponentiation the most time consuming bottleneck is the multiplications which are in general a small factor
+slower than squaring. Recall from the previous algorithm that $b_{i}$ refers to the $i$'th bit of the exponent $b$. Suppose instead it referred to
+the $i$'th $k$-bit digit of the exponent of $b$. For $k = 1$ the definitions are synonymous and for $k > 1$ algorithm~\ref{fig:KARY}
+computes the same exponentiation. A group of $k$ bits from the exponent is called a \textit{window}. That is it is a small window on only a
+portion of the entire exponent. Consider the following modification to the basic left to right exponentiation algorithm.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{$k$-ary Exponentiation}. \\
+\textbf{Input}. Integer $a$, $b$, $k$ and $t$ \\
+\textbf{Output}. $c = a^b$ \\
+\hline \\
+1. $c \leftarrow 1$ \\
+2. for $i$ from $t - 1$ to $0$ do \\
+\hspace{3mm}2.1 $c \leftarrow c^{2^k} $ \\
+\hspace{3mm}2.2 Extract the $i$'th $k$-bit word from $b$ and store it in $g$. \\
+\hspace{3mm}2.3 $c \leftarrow c \cdot a^g$ \\
+3. Return $c$. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{$k$-ary Exponentiation}
+\label{fig:KARY}
+\end{figure}
+
+The squaring on step 2.1 can be calculated by squaring the value $c$ successively $k$ times. If the values of $a^g$ for $0 < g < 2^k$ have been
+precomputed this algorithm requires only $t$ multiplications and $tk$ squarings. The table can be generated with $2^{k - 1} - 1$ squarings and
+$2^{k - 1} + 1$ multiplications. This algorithm assumes that the number of bits in the exponent is evenly divisible by $k$.
+However, when it is not the remaining $0 < x \le k - 1$ bits can be handled with algorithm~\ref{fig:LTOR}.
+
+Suppose $k = 4$ and $t = 100$. This modified algorithm will require $109$ multiplications and $408$ squarings to compute the exponentiation. The
+original algorithm would on average have required $200$ multiplications and $400$ squrings to compute the same value. The total number of squarings
+has increased slightly but the number of multiplications has nearly halved.
+
+\subsection{Optimal Values of $k$}
+An optimal value of $k$ will minimize $2^{k} + \lceil n / k \rceil + n - 1$ for a fixed number of bits in the exponent $n$. The simplest
+approach is to brute force search amongst the values $k = 2, 3, \ldots, 8$ for the lowest result. Table~\ref{fig:OPTK} lists optimal values of $k$
+for various exponent sizes and compares the number of multiplication and squarings required against algorithm~\ref{fig:LTOR}.
+
+\begin{figure}[here]
+\begin{center}
+\begin{small}
+\begin{tabular}{|c|c|c|c|c|c|}
+\hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:LTOR}} \\
+\hline $16$ & $2$ & $27$ & $24$ \\
+\hline $32$ & $3$ & $49$ & $48$ \\
+\hline $64$ & $3$ & $92$ & $96$ \\
+\hline $128$ & $4$ & $175$ & $192$ \\
+\hline $256$ & $4$ & $335$ & $384$ \\
+\hline $512$ & $5$ & $645$ & $768$ \\
+\hline $1024$ & $6$ & $1257$ & $1536$ \\
+\hline $2048$ & $6$ & $2452$ & $3072$ \\
+\hline $4096$ & $7$ & $4808$ & $6144$ \\
+\hline
+\end{tabular}
+\end{small}
+\end{center}
+\caption{Optimal Values of $k$ for $k$-ary Exponentiation}
+\label{fig:OPTK}
+\end{figure}
+
+\subsection{Sliding-Window Exponentiation}
+A simple modification to the previous algorithm is only generate the upper half of the table in the range $2^{k-1} \le g < 2^k$. Essentially
+this is a table for all values of $g$ where the most significant bit of $g$ is a one. However, in order for this to be allowed in the
+algorithm values of $g$ in the range $0 \le g < 2^{k-1}$ must be avoided.
+
+Table~\ref{fig:OPTK2} lists optimal values of $k$ for various exponent sizes and compares the work required against algorithm~\ref{fig:KARY}.
+
+\begin{figure}[here]
+\begin{center}
+\begin{small}
+\begin{tabular}{|c|c|c|c|c|c|}
+\hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:KARY}} \\
+\hline $16$ & $3$ & $24$ & $27$ \\
+\hline $32$ & $3$ & $45$ & $49$ \\
+\hline $64$ & $4$ & $87$ & $92$ \\
+\hline $128$ & $4$ & $167$ & $175$ \\
+\hline $256$ & $5$ & $322$ & $335$ \\
+\hline $512$ & $6$ & $628$ & $645$ \\
+\hline $1024$ & $6$ & $1225$ & $1257$ \\
+\hline $2048$ & $7$ & $2403$ & $2452$ \\
+\hline $4096$ & $8$ & $4735$ & $4808$ \\
+\hline
+\end{tabular}
+\end{small}
+\end{center}
+\caption{Optimal Values of $k$ for Sliding Window Exponentiation}
+\label{fig:OPTK2}
+\end{figure}
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Sliding Window $k$-ary Exponentiation}. \\
+\textbf{Input}. Integer $a$, $b$, $k$ and $t$ \\
+\textbf{Output}. $c = a^b$ \\
+\hline \\
+1. $c \leftarrow 1$ \\
+2. for $i$ from $t - 1$ to $0$ do \\
+\hspace{3mm}2.1 If the $i$'th bit of $b$ is a zero then \\
+\hspace{6mm}2.1.1 $c \leftarrow c^2$ \\
+\hspace{3mm}2.2 else do \\
+\hspace{6mm}2.2.1 $c \leftarrow c^{2^k}$ \\
+\hspace{6mm}2.2.2 Extract the $k$ bits from $(b_{i}b_{i-1}\ldots b_{i-(k-1)})$ and store it in $g$. \\
+\hspace{6mm}2.2.3 $c \leftarrow c \cdot a^g$ \\
+\hspace{6mm}2.2.4 $i \leftarrow i - k$ \\
+3. Return $c$. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Sliding Window $k$-ary Exponentiation}
+\end{figure}
+
+Similar to the previous algorithm this algorithm must have a special handler when fewer than $k$ bits are left in the exponent. While this
+algorithm requires the same number of squarings it can potentially have fewer multiplications. The pre-computed table $a^g$ is also half
+the size as the previous table.
+
+Consider the exponent $b = 111101011001000_2 \equiv 31432_{10}$ with $k = 3$ using both algorithms. The first algorithm will divide the exponent up as
+the following five $3$-bit words $b \equiv \left ( 111, 101, 011, 001, 000 \right )_{2}$. The second algorithm will break the
+exponent as $b \equiv \left ( 111, 101, 0, 110, 0, 100, 0 \right )_{2}$. The single digit $0$ in the second representation are where
+a single squaring took place instead of a squaring and multiplication. In total the first method requires $10$ multiplications and $18$
+squarings. The second method requires $8$ multiplications and $18$ squarings.
+
+In general the sliding window method is never slower than the generic $k$-ary method and often it is slightly faster.
+
+\section{Modular Exponentiation}
+
+Modular exponentiation is essentially computing the power of a base within a finite field or ring. For example, computing
+$d \equiv a^b \mbox{ (mod }c\mbox{)}$ is a modular exponentiation. Instead of first computing $a^b$ and then reducing it
+modulo $c$ the intermediate result is reduced modulo $c$ after every squaring or multiplication operation.
+
+This guarantees that any intermediate result is bounded by $0 \le d \le c^2 - 2c + 1$ and can be reduced modulo $c$ quickly using
+one of the algorithms presented in chapter six.
+
+Before the actual modular exponentiation algorithm can be written a wrapper algorithm must be written first. This algorithm
+will allow the exponent $b$ to be negative which is computed as $c \equiv \left (1 / a \right )^{\vert b \vert} \mbox{(mod }d\mbox{)}$. The
+value of $(1/a) \mbox{ mod }c$ is computed using the modular inverse (\textit{see \ref{sec;modinv}}). If no inverse exists the algorithm
+terminates with an error.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_exptmod}. \\
+\textbf{Input}. mp\_int $a$, $b$ and $c$ \\
+\textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
+\hline \\
+1. If $c.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\
+2. If $b.sign = MP\_NEG$ then \\
+\hspace{3mm}2.1 $g' \leftarrow g^{-1} \mbox{ (mod }c\mbox{)}$ \\
+\hspace{3mm}2.2 $x' \leftarrow \vert x \vert$ \\
+\hspace{3mm}2.3 Compute $d \equiv g'^{x'} \mbox{ (mod }c\mbox{)}$ via recursion. \\
+3. if $p$ is odd \textbf{OR} $p$ is a D.R. modulus then \\
+\hspace{3mm}3.1 Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm mp\_exptmod\_fast. \\
+4. else \\
+\hspace{3mm}4.1 Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm s\_mp\_exptmod. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_exptmod}
+\end{figure}
+
+\textbf{Algorithm mp\_exptmod.}
+The first algorithm which actually performs modular exponentiation is algorithm s\_mp\_exptmod. It is a sliding window $k$-ary algorithm
+which uses Barrett reduction to reduce the product modulo $p$. The second algorithm mp\_exptmod\_fast performs the same operation
+except it uses either Montgomery or Diminished Radix reduction. The two latter reduction algorithms are clumped in the same exponentiation
+algorithm since their arguments are essentially the same (\textit{two mp\_ints and one mp\_digit}).
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_exptmod.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+In order to keep the algorithms in a known state the first step on line 29 is to reject any negative modulus as input. If the exponent is
+negative the algorithm tries to perform a modular exponentiation with the modular inverse of the base $G$. The temporary variable $tmpG$ is assigned
+the modular inverse of $G$ and $tmpX$ is assigned the absolute value of $X$. The algorithm will recuse with these new values with a positive
+exponent.
+
+If the exponent is positive the algorithm resumes the exponentiation. Line 77 determines if the modulus is of the restricted Diminished Radix
+form. If it is not line 70 attempts to determine if it is of a unrestricted Diminished Radix form. The integer $dr$ will take on one
+of three values.
+
+\begin{enumerate}
+\item $dr = 0$ means that the modulus is not of either restricted or unrestricted Diminished Radix form.
+\item $dr = 1$ means that the modulus is of restricted Diminished Radix form.
+\item $dr = 2$ means that the modulus is of unrestricted Diminished Radix form.
+\end{enumerate}
+
+Line 69 determines if the fast modular exponentiation algorithm can be used. It is allowed if $dr \ne 0$ or if the modulus is odd. Otherwise,
+the slower s\_mp\_exptmod algorithm is used which uses Barrett reduction.
+
+\subsection{Barrett Modular Exponentiation}
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{s\_mp\_exptmod}. \\
+\textbf{Input}. mp\_int $a$, $b$ and $c$ \\
+\textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
+\hline \\
+1. $k \leftarrow lg(x)$ \\
+2. $winsize \leftarrow \left \lbrace \begin{array}{ll}
+ 2 & \mbox{if }k \le 7 \\
+ 3 & \mbox{if }7 < k \le 36 \\
+ 4 & \mbox{if }36 < k \le 140 \\
+ 5 & \mbox{if }140 < k \le 450 \\
+ 6 & \mbox{if }450 < k \le 1303 \\
+ 7 & \mbox{if }1303 < k \le 3529 \\
+ 8 & \mbox{if }3529 < k \\
+ \end{array} \right .$ \\
+3. Initialize $2^{winsize}$ mp\_ints in an array named $M$ and one mp\_int named $\mu$ \\
+4. Calculate the $\mu$ required for Barrett Reduction (\textit{mp\_reduce\_setup}). \\
+5. $M_1 \leftarrow g \mbox{ (mod }p\mbox{)}$ \\
+\\
+Setup the table of small powers of $g$. First find $g^{2^{winsize}}$ and then all multiples of it. \\
+6. $k \leftarrow 2^{winsize - 1}$ \\
+7. $M_{k} \leftarrow M_1$ \\
+8. for $ix$ from 0 to $winsize - 2$ do \\
+\hspace{3mm}8.1 $M_k \leftarrow \left ( M_k \right )^2$ (\textit{mp\_sqr}) \\
+\hspace{3mm}8.2 $M_k \leftarrow M_k \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\
+9. for $ix$ from $2^{winsize - 1} + 1$ to $2^{winsize} - 1$ do \\
+\hspace{3mm}9.1 $M_{ix} \leftarrow M_{ix - 1} \cdot M_{1}$ (\textit{mp\_mul}) \\
+\hspace{3mm}9.2 $M_{ix} \leftarrow M_{ix} \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\
+10. $res \leftarrow 1$ \\
+\\
+Start Sliding Window. \\
+11. $mode \leftarrow 0, bitcnt \leftarrow 1, buf \leftarrow 0, digidx \leftarrow x.used - 1, bitcpy \leftarrow 0, bitbuf \leftarrow 0$ \\
+12. Loop \\
+\hspace{3mm}12.1 $bitcnt \leftarrow bitcnt - 1$ \\
+\hspace{3mm}12.2 If $bitcnt = 0$ then do \\
+\hspace{6mm}12.2.1 If $digidx = -1$ goto step 13. \\
+\hspace{6mm}12.2.2 $buf \leftarrow x_{digidx}$ \\
+\hspace{6mm}12.2.3 $digidx \leftarrow digidx - 1$ \\
+\hspace{6mm}12.2.4 $bitcnt \leftarrow lg(\beta)$ \\
+Continued on next page. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm s\_mp\_exptmod}
+\end{figure}
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{s\_mp\_exptmod} (\textit{continued}). \\
+\textbf{Input}. mp\_int $a$, $b$ and $c$ \\
+\textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
+\hline \\
+\hspace{3mm}12.3 $y \leftarrow (buf >> (lg(\beta) - 1))$ AND $1$ \\
+\hspace{3mm}12.4 $buf \leftarrow buf << 1$ \\
+\hspace{3mm}12.5 if $mode = 0$ and $y = 0$ then goto step 12. \\
+\hspace{3mm}12.6 if $mode = 1$ and $y = 0$ then do \\
+\hspace{6mm}12.6.1 $res \leftarrow res^2$ \\
+\hspace{6mm}12.6.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
+\hspace{6mm}12.6.3 Goto step 12. \\
+\hspace{3mm}12.7 $bitcpy \leftarrow bitcpy + 1$ \\
+\hspace{3mm}12.8 $bitbuf \leftarrow bitbuf + (y << (winsize - bitcpy))$ \\
+\hspace{3mm}12.9 $mode \leftarrow 2$ \\
+\hspace{3mm}12.10 If $bitcpy = winsize$ then do \\
+\hspace{6mm}Window is full so perform the squarings and single multiplication. \\
+\hspace{6mm}12.10.1 for $ix$ from $0$ to $winsize -1$ do \\
+\hspace{9mm}12.10.1.1 $res \leftarrow res^2$ \\
+\hspace{9mm}12.10.1.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
+\hspace{6mm}12.10.2 $res \leftarrow res \cdot M_{bitbuf}$ \\
+\hspace{6mm}12.10.3 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
+\hspace{6mm}Reset the window. \\
+\hspace{6mm}12.10.4 $bitcpy \leftarrow 0, bitbuf \leftarrow 0, mode \leftarrow 1$ \\
+\\
+No more windows left. Check for residual bits of exponent. \\
+13. If $mode = 2$ and $bitcpy > 0$ then do \\
+\hspace{3mm}13.1 for $ix$ form $0$ to $bitcpy - 1$ do \\
+\hspace{6mm}13.1.1 $res \leftarrow res^2$ \\
+\hspace{6mm}13.1.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
+\hspace{6mm}13.1.3 $bitbuf \leftarrow bitbuf << 1$ \\
+\hspace{6mm}13.1.4 If $bitbuf$ AND $2^{winsize} \ne 0$ then do \\
+\hspace{9mm}13.1.4.1 $res \leftarrow res \cdot M_{1}$ \\
+\hspace{9mm}13.1.4.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
+14. $y \leftarrow res$ \\
+15. Clear $res$, $mu$ and the $M$ array. \\
+16. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm s\_mp\_exptmod (continued)}
+\end{figure}
+
+\textbf{Algorithm s\_mp\_exptmod.}
+This algorithm computes the $x$'th power of $g$ modulo $p$ and stores the result in $y$. It takes advantage of the Barrett reduction
+algorithm to keep the product small throughout the algorithm.
+
+The first two steps determine the optimal window size based on the number of bits in the exponent. The larger the exponent the
+larger the window size becomes. After a window size $winsize$ has been chosen an array of $2^{winsize}$ mp\_int variables is allocated. This
+table will hold the values of $g^x \mbox{ (mod }p\mbox{)}$ for $2^{winsize - 1} \le x < 2^{winsize}$.
+
+After the table is allocated the first power of $g$ is found. Since $g \ge p$ is allowed it must be first reduced modulo $p$ to make
+the rest of the algorithm more efficient. The first element of the table at $2^{winsize - 1}$ is found by squaring $M_1$ successively $winsize - 2$
+times. The rest of the table elements are found by multiplying the previous element by $M_1$ modulo $p$.
+
+Now that the table is available the sliding window may begin. The following list describes the functions of all the variables in the window.
+\begin{enumerate}
+\item The variable $mode$ dictates how the bits of the exponent are interpreted.
+\begin{enumerate}
+ \item When $mode = 0$ the bits are ignored since no non-zero bit of the exponent has been seen yet. For example, if the exponent were simply
+ $1$ then there would be $lg(\beta) - 1$ zero bits before the first non-zero bit. In this case bits are ignored until a non-zero bit is found.
+ \item When $mode = 1$ a non-zero bit has been seen before and a new $winsize$-bit window has not been formed yet. In this mode leading $0$ bits
+ are read and a single squaring is performed. If a non-zero bit is read a new window is created.
+ \item When $mode = 2$ the algorithm is in the middle of forming a window and new bits are appended to the window from the most significant bit
+ downwards.
+\end{enumerate}
+\item The variable $bitcnt$ indicates how many bits are left in the current digit of the exponent left to be read. When it reaches zero a new digit
+ is fetched from the exponent.
+\item The variable $buf$ holds the currently read digit of the exponent.
+\item The variable $digidx$ is an index into the exponents digits. It starts at the leading digit $x.used - 1$ and moves towards the trailing digit.
+\item The variable $bitcpy$ indicates how many bits are in the currently formed window. When it reaches $winsize$ the window is flushed and
+ the appropriate operations performed.
+\item The variable $bitbuf$ holds the current bits of the window being formed.
+\end{enumerate}
+
+All of step 12 is the window processing loop. It will iterate while there are digits available form the exponent to read. The first step
+inside this loop is to extract a new digit if no more bits are available in the current digit. If there are no bits left a new digit is
+read and if there are no digits left than the loop terminates.
+
+After a digit is made available step 12.3 will extract the most significant bit of the current digit and move all other bits in the digit
+upwards. In effect the digit is read from most significant bit to least significant bit and since the digits are read from leading to
+trailing edges the entire exponent is read from most significant bit to least significant bit.
+
+At step 12.5 if the $mode$ and currently extracted bit $y$ are both zero the bit is ignored and the next bit is read. This prevents the
+algorithm from having to perform trivial squaring and reduction operations before the first non-zero bit is read. Step 12.6 and 12.7-10 handle
+the two cases of $mode = 1$ and $mode = 2$ respectively.
+
+\begin{center}
+\begin{figure}[here]
+\includegraphics{pics/expt_state.ps}
+\caption{Sliding Window State Diagram}
+\label{pic:expt_state}
+\end{figure}
+\end{center}
+
+By step 13 there are no more digits left in the exponent. However, there may be partial bits in the window left. If $mode = 2$ then
+a Left-to-Right algorithm is used to process the remaining few bits.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_s\_mp\_exptmod.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+Lines 32 through 46 determine the optimal window size based on the length of the exponent in bits. The window divisions are sorted
+from smallest to greatest so that in each \textbf{if} statement only one condition must be tested. For example, by the \textbf{if} statement
+on line 38 the value of $x$ is already known to be greater than $140$.
+
+The conditional piece of code beginning on line 48 allows the window size to be restricted to five bits. This logic is used to ensure
+the table of precomputed powers of $G$ remains relatively small.
+
+The for loop on line 61 initializes the $M$ array while lines 72 and 77 through 86 initialize the reduction
+function that will be used for this modulus.
+
+-- More later.
+
+\section{Quick Power of Two}
+Calculating $b = 2^a$ can be performed much quicker than with any of the previous algorithms. Recall that a logical shift left $m << k$ is
+equivalent to $m \cdot 2^k$. By this logic when $m = 1$ a quick power of two can be achieved.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_2expt}. \\
+\textbf{Input}. integer $b$ \\
+\textbf{Output}. $a \leftarrow 2^b$ \\
+\hline \\
+1. $a \leftarrow 0$ \\
+2. If $a.alloc < \lfloor b / lg(\beta) \rfloor + 1$ then grow $a$ appropriately. \\
+3. $a.used \leftarrow \lfloor b / lg(\beta) \rfloor + 1$ \\
+4. $a_{\lfloor b / lg(\beta) \rfloor} \leftarrow 1 << (b \mbox{ mod } lg(\beta))$ \\
+5. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_2expt}
+\end{figure}
+
+\textbf{Algorithm mp\_2expt.}
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_2expt.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+\chapter{Higher Level Algorithms}
+
+This chapter discusses the various higher level algorithms that are required to complete a well rounded multiple precision integer package. These
+routines are less performance oriented than the algorithms of chapters five, six and seven but are no less important.
+
+The first section describes a method of integer division with remainder that is universally well known. It provides the signed division logic
+for the package. The subsequent section discusses a set of algorithms which allow a single digit to be the 2nd operand for a variety of operations.
+These algorithms serve mostly to simplify other algorithms where small constants are required. The last two sections discuss how to manipulate
+various representations of integers. For example, converting from an mp\_int to a string of character.
+
+\section{Integer Division with Remainder}
+\label{sec:division}
+
+Integer division aside from modular exponentiation is the most intensive algorithm to compute. Like addition, subtraction and multiplication
+the basis of this algorithm is the long-hand division algorithm taught to school children. Throughout this discussion several common variables
+will be used. Let $x$ represent the divisor and $y$ represent the dividend. Let $q$ represent the integer quotient $\lfloor y / x \rfloor$ and
+let $r$ represent the remainder $r = y - x \lfloor y / x \rfloor$. The following simple algorithm will be used to start the discussion.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Radix-$\beta$ Integer Division}. \\
+\textbf{Input}. integer $x$ and $y$ \\
+\textbf{Output}. $q = \lfloor y/x\rfloor, r = y - xq$ \\
+\hline \\
+1. $q \leftarrow 0$ \\
+2. $n \leftarrow \vert \vert y \vert \vert - \vert \vert x \vert \vert$ \\
+3. for $t$ from $n$ down to $0$ do \\
+\hspace{3mm}3.1 Maximize $k$ such that $kx\beta^t$ is less than or equal to $y$ and $(k + 1)x\beta^t$ is greater. \\
+\hspace{3mm}3.2 $q \leftarrow q + k\beta^t$ \\
+\hspace{3mm}3.3 $y \leftarrow y - kx\beta^t$ \\
+4. $r \leftarrow y$ \\
+5. Return($q, r$) \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm Radix-$\beta$ Integer Division}
+\label{fig:raddiv}
+\end{figure}
+
+As children we are taught this very simple algorithm for the case of $\beta = 10$. Almost instinctively several optimizations are taught for which
+their reason of existing are never explained. For this example let $y = 5471$ represent the dividend and $x = 23$ represent the divisor.
+
+To find the first digit of the quotient the value of $k$ must be maximized such that $kx\beta^t$ is less than or equal to $y$ and
+simultaneously $(k + 1)x\beta^t$ is greater than $y$. Implicitly $k$ is the maximum value the $t$'th digit of the quotient may have. The habitual method
+used to find the maximum is to ``eyeball'' the two numbers, typically only the leading digits and quickly estimate a quotient. By only using leading
+digits a much simpler division may be used to form an educated guess at what the value must be. In this case $k = \lfloor 54/23\rfloor = 2$ quickly
+arises as a possible solution. Indeed $2x\beta^2 = 4600$ is less than $y = 5471$ and simultaneously $(k + 1)x\beta^2 = 6900$ is larger than $y$.
+As a result $k\beta^2$ is added to the quotient which now equals $q = 200$ and $4600$ is subtracted from $y$ to give a remainder of $y = 841$.
+
+Again this process is repeated to produce the quotient digit $k = 3$ which makes the quotient $q = 200 + 3\beta = 230$ and the remainder
+$y = 841 - 3x\beta = 181$. Finally the last iteration of the loop produces $k = 7$ which leads to the quotient $q = 230 + 7 = 237$ and the
+remainder $y = 181 - 7x = 20$. The final quotient and remainder found are $q = 237$ and $r = y = 20$ which are indeed correct since
+$237 \cdot 23 + 20 = 5471$ is true.
+
+\subsection{Quotient Estimation}
+\label{sec:divest}
+As alluded to earlier the quotient digit $k$ can be estimated from only the leading digits of both the divisor and dividend. When $p$ leading
+digits are used from both the divisor and dividend to form an estimation the accuracy of the estimation rises as $p$ grows. Technically
+speaking the estimation is based on assuming the lower $\vert \vert y \vert \vert - p$ and $\vert \vert x \vert \vert - p$ lower digits of the
+dividend and divisor are zero.
+
+The value of the estimation may off by a few values in either direction and in general is fairly correct. A simplification \cite[pp. 271]{TAOCPV2}
+of the estimation technique is to use $t + 1$ digits of the dividend and $t$ digits of the divisor, in particularly when $t = 1$. The estimate
+using this technique is never too small. For the following proof let $t = \vert \vert y \vert \vert - 1$ and $s = \vert \vert x \vert \vert - 1$
+represent the most significant digits of the dividend and divisor respectively.
+
+\textbf{Proof.}\textit{ The quotient $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ is greater than or equal to
+$k = \lfloor y / (x \cdot \beta^{\vert \vert y \vert \vert - \vert \vert x \vert \vert - 1}) \rfloor$. }
+The first obvious case is when $\hat k = \beta - 1$ in which case the proof is concluded since the real quotient cannot be larger. For all other
+cases $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ and $\hat k x_s \ge y_t\beta + y_{t-1} - x_s + 1$. The latter portion of the inequalility
+$-x_s + 1$ arises from the fact that a truncated integer division will give the same quotient for at most $x_s - 1$ values. Next a series of
+inequalities will prove the hypothesis.
+
+\begin{equation}
+y - \hat k x \le y - \hat k x_s\beta^s
+\end{equation}
+
+This is trivially true since $x \ge x_s\beta^s$. Next we replace $\hat kx_s\beta^s$ by the previous inequality for $\hat kx_s$.
+
+\begin{equation}
+y - \hat k x \le y_t\beta^t + \ldots + y_0 - (y_t\beta^t + y_{t-1}\beta^{t-1} - x_s\beta^t + \beta^s)
+\end{equation}
+
+By simplifying the previous inequality the following inequality is formed.
+
+\begin{equation}
+y - \hat k x \le y_{t-2}\beta^{t-2} + \ldots + y_0 + x_s\beta^s - \beta^s
+\end{equation}
+
+Subsequently,
+
+\begin{equation}
+y_{t-2}\beta^{t-2} + \ldots + y_0 + x_s\beta^s - \beta^s < x_s\beta^s \le x
+\end{equation}
+
+Which proves that $y - \hat kx \le x$ and by consequence $\hat k \ge k$ which concludes the proof. \textbf{QED}
+
+
+\subsection{Normalized Integers}
+For the purposes of division a normalized input is when the divisors leading digit $x_n$ is greater than or equal to $\beta / 2$. By multiplying both
+$x$ and $y$ by $j = \lfloor (\beta / 2) / x_n \rfloor$ the quotient remains unchanged and the remainder is simply $j$ times the original
+remainder. The purpose of normalization is to ensure the leading digit of the divisor is sufficiently large such that the estimated quotient will
+lie in the domain of a single digit. Consider the maximum dividend $(\beta - 1) \cdot \beta + (\beta - 1)$ and the minimum divisor $\beta / 2$.
+
+\begin{equation}
+{{\beta^2 - 1} \over { \beta / 2}} \le 2\beta - {2 \over \beta}
+\end{equation}
+
+At most the quotient approaches $2\beta$, however, in practice this will not occur since that would imply the previous quotient digit was too small.
+
+\subsection{Radix-$\beta$ Division with Remainder}
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_div}. \\
+\textbf{Input}. mp\_int $a, b$ \\
+\textbf{Output}. $c = \lfloor a/b \rfloor$, $d = a - bc$ \\
+\hline \\
+1. If $b = 0$ return(\textit{MP\_VAL}). \\
+2. If $\vert a \vert < \vert b \vert$ then do \\
+\hspace{3mm}2.1 $d \leftarrow a$ \\
+\hspace{3mm}2.2 $c \leftarrow 0$ \\
+\hspace{3mm}2.3 Return(\textit{MP\_OKAY}). \\
+\\
+Setup the quotient to receive the digits. \\
+3. Grow $q$ to $a.used + 2$ digits. \\
+4. $q \leftarrow 0$ \\
+5. $x \leftarrow \vert a \vert , y \leftarrow \vert b \vert$ \\
+6. $sign \leftarrow \left \lbrace \begin{array}{ll}
+ MP\_ZPOS & \mbox{if }a.sign = b.sign \\
+ MP\_NEG & \mbox{otherwise} \\
+ \end{array} \right .$ \\
+\\
+Normalize the inputs such that the leading digit of $y$ is greater than or equal to $\beta / 2$. \\
+7. $norm \leftarrow (lg(\beta) - 1) - (\lceil lg(y) \rceil \mbox{ (mod }lg(\beta)\mbox{)})$ \\
+8. $x \leftarrow x \cdot 2^{norm}, y \leftarrow y \cdot 2^{norm}$ \\
+\\
+Find the leading digit of the quotient. \\
+9. $n \leftarrow x.used - 1, t \leftarrow y.used - 1$ \\
+10. $y \leftarrow y \cdot \beta^{n - t}$ \\
+11. While ($x \ge y$) do \\
+\hspace{3mm}11.1 $q_{n - t} \leftarrow q_{n - t} + 1$ \\
+\hspace{3mm}11.2 $x \leftarrow x - y$ \\
+12. $y \leftarrow \lfloor y / \beta^{n-t} \rfloor$ \\
+\\
+Continued on the next page. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_div}
+\end{figure}
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_div} (continued). \\
+\textbf{Input}. mp\_int $a, b$ \\
+\textbf{Output}. $c = \lfloor a/b \rfloor$, $d = a - bc$ \\
+\hline \\
+Now find the remainder fo the digits. \\
+13. for $i$ from $n$ down to $(t + 1)$ do \\
+\hspace{3mm}13.1 If $i > x.used$ then jump to the next iteration of this loop. \\
+\hspace{3mm}13.2 If $x_{i} = y_{t}$ then \\
+\hspace{6mm}13.2.1 $q_{i - t - 1} \leftarrow \beta - 1$ \\
+\hspace{3mm}13.3 else \\
+\hspace{6mm}13.3.1 $\hat r \leftarrow x_{i} \cdot \beta + x_{i - 1}$ \\
+\hspace{6mm}13.3.2 $\hat r \leftarrow \lfloor \hat r / y_{t} \rfloor$ \\
+\hspace{6mm}13.3.3 $q_{i - t - 1} \leftarrow \hat r$ \\
+\hspace{3mm}13.4 $q_{i - t - 1} \leftarrow q_{i - t - 1} + 1$ \\
+\\
+Fixup quotient estimation. \\
+\hspace{3mm}13.5 Loop \\
+\hspace{6mm}13.5.1 $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\
+\hspace{6mm}13.5.2 t$1 \leftarrow 0$ \\
+\hspace{6mm}13.5.3 t$1_0 \leftarrow y_{t - 1}, $ t$1_1 \leftarrow y_t,$ t$1.used \leftarrow 2$ \\
+\hspace{6mm}13.5.4 $t1 \leftarrow t1 \cdot q_{i - t - 1}$ \\
+\hspace{6mm}13.5.5 t$2_0 \leftarrow x_{i - 2}, $ t$2_1 \leftarrow x_{i - 1}, $ t$2_2 \leftarrow x_i, $ t$2.used \leftarrow 3$ \\
+\hspace{6mm}13.5.6 If $\vert t1 \vert > \vert t2 \vert$ then goto step 13.5. \\
+\hspace{3mm}13.6 t$1 \leftarrow y \cdot q_{i - t - 1}$ \\
+\hspace{3mm}13.7 t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\
+\hspace{3mm}13.8 $x \leftarrow x - $ t$1$ \\
+\hspace{3mm}13.9 If $x.sign = MP\_NEG$ then \\
+\hspace{6mm}13.10 t$1 \leftarrow y$ \\
+\hspace{6mm}13.11 t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\
+\hspace{6mm}13.12 $x \leftarrow x + $ t$1$ \\
+\hspace{6mm}13.13 $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\
+\\
+Finalize the result. \\
+14. Clamp excess digits of $q$ \\
+15. $c \leftarrow q, c.sign \leftarrow sign$ \\
+16. $x.sign \leftarrow a.sign$ \\
+17. $d \leftarrow \lfloor x / 2^{norm} \rfloor$ \\
+18. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_div (continued)}
+\end{figure}
+\textbf{Algorithm mp\_div.}
+This algorithm will calculate quotient and remainder from an integer division given a dividend and divisor. The algorithm is a signed
+division and will produce a fully qualified quotient and remainder.
+
+First the divisor $b$ must be non-zero which is enforced in step one. If the divisor is larger than the dividend than the quotient is implicitly
+zero and the remainder is the dividend.
+
+After the first two trivial cases of inputs are handled the variable $q$ is setup to receive the digits of the quotient. Two unsigned copies of the
+divisor $y$ and dividend $x$ are made as well. The core of the division algorithm is an unsigned division and will only work if the values are
+positive. Now the two values $x$ and $y$ must be normalized such that the leading digit of $y$ is greater than or equal to $\beta / 2$.
+This is performed by shifting both to the left by enough bits to get the desired normalization.
+
+At this point the division algorithm can begin producing digits of the quotient. Recall that maximum value of the estimation used is
+$2\beta - {2 \over \beta}$ which means that a digit of the quotient must be first produced by another means. In this case $y$ is shifted
+to the left (\textit{step ten}) so that it has the same number of digits as $x$. The loop on step eleven will subtract multiples of the
+shifted copy of $y$ until $x$ is smaller. Since the leading digit of $y$ is greater than or equal to $\beta/2$ this loop will iterate at most two
+times to produce the desired leading digit of the quotient.
+
+Now the remainder of the digits can be produced. The equation $\hat q = \lfloor {{x_i \beta + x_{i-1}}\over y_t} \rfloor$ is used to fairly
+accurately approximate the true quotient digit. The estimation can in theory produce an estimation as high as $2\beta - {2 \over \beta}$ but by
+induction the upper quotient digit is correct (\textit{as established on step eleven}) and the estimate must be less than $\beta$.
+
+Recall from section~\ref{sec:divest} that the estimation is never too low but may be too high. The next step of the estimation process is
+to refine the estimation. The loop on step 13.5 uses $x_i\beta^2 + x_{i-1}\beta + x_{i-2}$ and $q_{i - t - 1}(y_t\beta + y_{t-1})$ as a higher
+order approximation to adjust the quotient digit.
+
+After both phases of estimation the quotient digit may still be off by a value of one\footnote{This is similar to the error introduced
+by optimizing Barrett reduction.}. Steps 13.6 and 13.7 subtract the multiple of the divisor from the dividend (\textit{Similar to step 3.3 of
+algorithm~\ref{fig:raddiv}} and then subsequently add a multiple of the divisor if the quotient was too large.
+
+Now that the quotient has been determine finializing the result is a matter of clamping the quotient, fixing the sizes and de-normalizing the
+remainder. An important aspect of this algorithm seemingly overlooked in other descriptions such as that of Algorithm 14.20 HAC \cite[pp. 598]{HAC}
+is that when the estimations are being made (\textit{inside the loop on step 13.5}) that the digits $y_{t-1}$, $x_{i-2}$ and $x_{i-1}$ may lie
+outside their respective boundaries. For example, if $t = 0$ or $i \le 1$ then the digits would be undefined. In those cases the digits should
+respectively be replaced with a zero.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_div.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+The implementation of this algorithm differs slightly from the pseudo code presented previously. In this algorithm either of the quotient $c$ or
+remainder $d$ may be passed as a \textbf{NULL} pointer which indicates their value is not desired. For example, the C code to call the division
+algorithm with only the quotient is
+
+\begin{verbatim}
+mp_div(&a, &b, &c, NULL); /* c = [a/b] */
+\end{verbatim}
+
+Lines 109 and 113 handle the two trivial cases of inputs which are division by zero and dividend smaller than the divisor
+respectively. After the two trivial cases all of the temporary variables are initialized. Line 148 determines the sign of
+the quotient and line 148 ensures that both $x$ and $y$ are positive.
+
+The number of bits in the leading digit is calculated on line 151. Implictly an mp\_int with $r$ digits will require $lg(\beta)(r-1) + k$ bits
+of precision which when reduced modulo $lg(\beta)$ produces the value of $k$. In this case $k$ is the number of bits in the leading digit which is
+exactly what is required. For the algorithm to operate $k$ must equal $lg(\beta) - 1$ and when it does not the inputs must be normalized by shifting
+them to the left by $lg(\beta) - 1 - k$ bits.
+
+Throughout the variables $n$ and $t$ will represent the highest digit of $x$ and $y$ respectively. These are first used to produce the
+leading digit of the quotient. The loop beginning on line 184 will produce the remainder of the quotient digits.
+
+The conditional ``continue'' on line 187 is used to prevent the algorithm from reading past the leading edge of $x$ which can occur when the
+algorithm eliminates multiple non-zero digits in a single iteration. This ensures that $x_i$ is always non-zero since by definition the digits
+above the $i$'th position $x$ must be zero in order for the quotient to be precise\footnote{Precise as far as integer division is concerned.}.
+
+Lines 214, 216 and 223 through 225 manually construct the high accuracy estimations by setting the digits of the two mp\_int
+variables directly.
+
+\section{Single Digit Helpers}
+
+This section briefly describes a series of single digit helper algorithms which come in handy when working with small constants. All of
+the helper functions assume the single digit input is positive and will treat them as such.
+
+\subsection{Single Digit Addition and Subtraction}
+
+Both addition and subtraction are performed by ``cheating'' and using mp\_set followed by the higher level addition or subtraction
+algorithms. As a result these algorithms are subtantially simpler with a slight cost in performance.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_add\_d}. \\
+\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\
+\textbf{Output}. $c = a + b$ \\
+\hline \\
+1. $t \leftarrow b$ (\textit{mp\_set}) \\
+2. $c \leftarrow a + t$ \\
+3. Return(\textit{MP\_OKAY}) \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_add\_d}
+\end{figure}
+
+\textbf{Algorithm mp\_add\_d.}
+This algorithm initiates a temporary mp\_int with the value of the single digit and uses algorithm mp\_add to add the two values together.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_add\_d.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+Clever use of the letter 't'.
+
+\subsubsection{Subtraction}
+The single digit subtraction algorithm mp\_sub\_d is essentially the same except it uses mp\_sub to subtract the digit from the mp\_int.
+
+\subsection{Single Digit Multiplication}
+Single digit multiplication arises enough in division and radix conversion that it ought to be implement as a special case of the baseline
+multiplication algorithm. Essentially this algorithm is a modified version of algorithm s\_mp\_mul\_digs where one of the multiplicands
+only has one digit.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_mul\_d}. \\
+\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\
+\textbf{Output}. $c = ab$ \\
+\hline \\
+1. $pa \leftarrow a.used$ \\
+2. Grow $c$ to at least $pa + 1$ digits. \\
+3. $oldused \leftarrow c.used$ \\
+4. $c.used \leftarrow pa + 1$ \\
+5. $c.sign \leftarrow a.sign$ \\
+6. $\mu \leftarrow 0$ \\
+7. for $ix$ from $0$ to $pa - 1$ do \\
+\hspace{3mm}7.1 $\hat r \leftarrow \mu + a_{ix}b$ \\
+\hspace{3mm}7.2 $c_{ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
+\hspace{3mm}7.3 $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\
+8. $c_{pa} \leftarrow \mu$ \\
+9. for $ix$ from $pa + 1$ to $oldused$ do \\
+\hspace{3mm}9.1 $c_{ix} \leftarrow 0$ \\
+10. Clamp excess digits of $c$. \\
+11. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_mul\_d}
+\end{figure}
+\textbf{Algorithm mp\_mul\_d.}
+This algorithm quickly multiplies an mp\_int by a small single digit value. It is specially tailored to the job and has a minimal of overhead.
+Unlike the full multiplication algorithms this algorithm does not require any significnat temporary storage or memory allocations.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_mul\_d.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+In this implementation the destination $c$ may point to the same mp\_int as the source $a$ since the result is written after the digit is
+read from the source. This function uses pointer aliases $tmpa$ and $tmpc$ for the digits of $a$ and $c$ respectively.
+
+\subsection{Single Digit Division}
+Like the single digit multiplication algorithm, single digit division is also a fairly common algorithm used in radix conversion. Since the
+divisor is only a single digit a specialized variant of the division algorithm can be used to compute the quotient.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_div\_d}. \\
+\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\
+\textbf{Output}. $c = \lfloor a / b \rfloor, d = a - cb$ \\
+\hline \\
+1. If $b = 0$ then return(\textit{MP\_VAL}).\\
+2. If $b = 3$ then use algorithm mp\_div\_3 instead. \\
+3. Init $q$ to $a.used$ digits. \\
+4. $q.used \leftarrow a.used$ \\
+5. $q.sign \leftarrow a.sign$ \\
+6. $\hat w \leftarrow 0$ \\
+7. for $ix$ from $a.used - 1$ down to $0$ do \\
+\hspace{3mm}7.1 $\hat w \leftarrow \hat w \beta + a_{ix}$ \\
+\hspace{3mm}7.2 If $\hat w \ge b$ then \\
+\hspace{6mm}7.2.1 $t \leftarrow \lfloor \hat w / b \rfloor$ \\
+\hspace{6mm}7.2.2 $\hat w \leftarrow \hat w \mbox{ (mod }b\mbox{)}$ \\
+\hspace{3mm}7.3 else\\
+\hspace{6mm}7.3.1 $t \leftarrow 0$ \\
+\hspace{3mm}7.4 $q_{ix} \leftarrow t$ \\
+8. $d \leftarrow \hat w$ \\
+9. Clamp excess digits of $q$. \\
+10. $c \leftarrow q$ \\
+11. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_div\_d}
+\end{figure}
+\textbf{Algorithm mp\_div\_d.}
+This algorithm divides the mp\_int $a$ by the single mp\_digit $b$ using an optimized approach. Essentially in every iteration of the
+algorithm another digit of the dividend is reduced and another digit of quotient produced. Provided $b < \beta$ the value of $\hat w$
+after step 7.1 will be limited such that $0 \le \lfloor \hat w / b \rfloor < \beta$.
+
+If the divisor $b$ is equal to three a variant of this algorithm is used which is called mp\_div\_3. It replaces the division by three with
+a multiplication by $\lfloor \beta / 3 \rfloor$ and the appropriate shift and residual fixup. In essence it is much like the Barrett reduction
+from chapter seven.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_div\_d.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+Like the implementation of algorithm mp\_div this algorithm allows either of the quotient or remainder to be passed as a \textbf{NULL} pointer to
+indicate the respective value is not required. This allows a trivial single digit modular reduction algorithm, mp\_mod\_d to be created.
+
+The division and remainder on lines 44 and @45,%@ can be replaced often by a single division on most processors. For example, the 32-bit x86 based
+processors can divide a 64-bit quantity by a 32-bit quantity and produce the quotient and remainder simultaneously. Unfortunately the GCC
+compiler does not recognize that optimization and will actually produce two function calls to find the quotient and remainder respectively.
+
+\subsection{Single Digit Root Extraction}
+
+Finding the $n$'th root of an integer is fairly easy as far as numerical analysis is concerned. Algorithms such as the Newton-Raphson approximation
+(\ref{eqn:newton}) series will converge very quickly to a root for any continuous function $f(x)$.
+
+\begin{equation}
+x_{i+1} = x_i - {f(x_i) \over f'(x_i)}
+\label{eqn:newton}
+\end{equation}
+
+In this case the $n$'th root is desired and $f(x) = x^n - a$ where $a$ is the integer of which the root is desired. The derivative of $f(x)$ is
+simply $f'(x) = nx^{n - 1}$. Of particular importance is that this algorithm will be used over the integers not over the a more continuous domain
+such as the real numbers. As a result the root found can be above the true root by few and must be manually adjusted. Ideally at the end of the
+algorithm the $n$'th root $b$ of an integer $a$ is desired such that $b^n \le a$.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_n\_root}. \\
+\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\
+\textbf{Output}. $c^b \le a$ \\
+\hline \\
+1. If $b$ is even and $a.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\
+2. $sign \leftarrow a.sign$ \\
+3. $a.sign \leftarrow MP\_ZPOS$ \\
+4. t$2 \leftarrow 2$ \\
+5. Loop \\
+\hspace{3mm}5.1 t$1 \leftarrow $ t$2$ \\
+\hspace{3mm}5.2 t$3 \leftarrow $ t$1^{b - 1}$ \\
+\hspace{3mm}5.3 t$2 \leftarrow $ t$3 $ $\cdot$ t$1$ \\
+\hspace{3mm}5.4 t$2 \leftarrow $ t$2 - a$ \\
+\hspace{3mm}5.5 t$3 \leftarrow $ t$3 \cdot b$ \\
+\hspace{3mm}5.6 t$3 \leftarrow \lfloor $t$2 / $t$3 \rfloor$ \\
+\hspace{3mm}5.7 t$2 \leftarrow $ t$1 - $ t$3$ \\
+\hspace{3mm}5.8 If t$1 \ne $ t$2$ then goto step 5. \\
+6. Loop \\
+\hspace{3mm}6.1 t$2 \leftarrow $ t$1^b$ \\
+\hspace{3mm}6.2 If t$2 > a$ then \\
+\hspace{6mm}6.2.1 t$1 \leftarrow $ t$1 - 1$ \\
+\hspace{6mm}6.2.2 Goto step 6. \\
+7. $a.sign \leftarrow sign$ \\
+8. $c \leftarrow $ t$1$ \\
+9. $c.sign \leftarrow sign$ \\
+10. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_n\_root}
+\end{figure}
+\textbf{Algorithm mp\_n\_root.}
+This algorithm finds the integer $n$'th root of an input using the Newton-Raphson approach. It is partially optimized based on the observation
+that the numerator of ${f(x) \over f'(x)}$ can be derived from a partial denominator. That is at first the denominator is calculated by finding
+$x^{b - 1}$. This value can then be multiplied by $x$ and have $a$ subtracted from it to find the numerator. This saves a total of $b - 1$
+multiplications by t$1$ inside the loop.
+
+The initial value of the approximation is t$2 = 2$ which allows the algorithm to start with very small values and quickly converge on the
+root. Ideally this algorithm is meant to find the $n$'th root of an input where $n$ is bounded by $2 \le n \le 5$.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_n\_root.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+\section{Random Number Generation}
+
+Random numbers come up in a variety of activities from public key cryptography to simple simulations and various randomized algorithms. Pollard-Rho
+factoring for example, can make use of random values as starting points to find factors of a composite integer. In this case the algorithm presented
+is solely for simulations and not intended for cryptographic use.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_rand}. \\
+\textbf{Input}. An integer $b$ \\
+\textbf{Output}. A pseudo-random number of $b$ digits \\
+\hline \\
+1. $a \leftarrow 0$ \\
+2. If $b \le 0$ return(\textit{MP\_OKAY}) \\
+3. Pick a non-zero random digit $d$. \\
+4. $a \leftarrow a + d$ \\
+5. for $ix$ from 1 to $d - 1$ do \\
+\hspace{3mm}5.1 $a \leftarrow a \cdot \beta$ \\
+\hspace{3mm}5.2 Pick a random digit $d$. \\
+\hspace{3mm}5.3 $a \leftarrow a + d$ \\
+6. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_rand}
+\end{figure}
+\textbf{Algorithm mp\_rand.}
+This algorithm produces a pseudo-random integer of $b$ digits. By ensuring that the first digit is non-zero the algorithm also guarantees that the
+final result has at least $b$ digits. It relies heavily on a third-part random number generator which should ideally generate uniformly all of
+the integers from $0$ to $\beta - 1$.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_rand.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+\section{Formatted Representations}
+The ability to emit a radix-$n$ textual representation of an integer is useful for interacting with human parties. For example, the ability to
+be given a string of characters such as ``114585'' and turn it into the radix-$\beta$ equivalent would make it easier to enter numbers
+into a program.
+
+\subsection{Reading Radix-n Input}
+For the purposes of this text we will assume that a simple lower ASCII map (\ref{fig:ASC}) is used for the values of from $0$ to $63$ to
+printable characters. For example, when the character ``N'' is read it represents the integer $23$. The first $16$ characters of the
+map are for the common representations up to hexadecimal. After that they match the ``base64'' encoding scheme which are suitable chosen
+such that they are printable. While outputting as base64 may not be too helpful for human operators it does allow communication via non binary
+mediums.
+
+\newpage\begin{figure}[here]
+\begin{center}
+\begin{tabular}{cc|cc|cc|cc}
+\hline \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} \\
+\hline
+0 & 0 & 1 & 1 & 2 & 2 & 3 & 3 \\
+4 & 4 & 5 & 5 & 6 & 6 & 7 & 7 \\
+8 & 8 & 9 & 9 & 10 & A & 11 & B \\
+12 & C & 13 & D & 14 & E & 15 & F \\
+16 & G & 17 & H & 18 & I & 19 & J \\
+20 & K & 21 & L & 22 & M & 23 & N \\
+24 & O & 25 & P & 26 & Q & 27 & R \\
+28 & S & 29 & T & 30 & U & 31 & V \\
+32 & W & 33 & X & 34 & Y & 35 & Z \\
+36 & a & 37 & b & 38 & c & 39 & d \\
+40 & e & 41 & f & 42 & g & 43 & h \\
+44 & i & 45 & j & 46 & k & 47 & l \\
+48 & m & 49 & n & 50 & o & 51 & p \\
+52 & q & 53 & r & 54 & s & 55 & t \\
+56 & u & 57 & v & 58 & w & 59 & x \\
+60 & y & 61 & z & 62 & $+$ & 63 & $/$ \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Lower ASCII Map}
+\label{fig:ASC}
+\end{figure}
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_read\_radix}. \\
+\textbf{Input}. A string $str$ of length $sn$ and radix $r$. \\
+\textbf{Output}. The radix-$\beta$ equivalent mp\_int. \\
+\hline \\
+1. If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\
+2. $ix \leftarrow 0$ \\
+3. If $str_0 =$ ``-'' then do \\
+\hspace{3mm}3.1 $ix \leftarrow ix + 1$ \\
+\hspace{3mm}3.2 $sign \leftarrow MP\_NEG$ \\
+4. else \\
+\hspace{3mm}4.1 $sign \leftarrow MP\_ZPOS$ \\
+5. $a \leftarrow 0$ \\
+6. for $iy$ from $ix$ to $sn - 1$ do \\
+\hspace{3mm}6.1 Let $y$ denote the position in the map of $str_{iy}$. \\
+\hspace{3mm}6.2 If $str_{iy}$ is not in the map or $y \ge r$ then goto step 7. \\
+\hspace{3mm}6.3 $a \leftarrow a \cdot r$ \\
+\hspace{3mm}6.4 $a \leftarrow a + y$ \\
+7. If $a \ne 0$ then $a.sign \leftarrow sign$ \\
+8. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_read\_radix}
+\end{figure}
+\textbf{Algorithm mp\_read\_radix.}
+This algorithm will read an ASCII string and produce the radix-$\beta$ mp\_int representation of the same integer. A minus symbol ``-'' may precede the
+string to indicate the value is negative, otherwise it is assumed to be positive. The algorithm will read up to $sn$ characters from the input
+and will stop when it reads a character it cannot map the algorithm stops reading characters from the string. This allows numbers to be embedded
+as part of larger input without any significant problem.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_read\_radix.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+\subsection{Generating Radix-$n$ Output}
+Generating radix-$n$ output is fairly trivial with a division and remainder algorithm.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_toradix}. \\
+\textbf{Input}. A mp\_int $a$ and an integer $r$\\
+\textbf{Output}. The radix-$r$ representation of $a$ \\
+\hline \\
+1. If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\
+2. If $a = 0$ then $str = $ ``$0$'' and return(\textit{MP\_OKAY}). \\
+3. $t \leftarrow a$ \\
+4. $str \leftarrow$ ``'' \\
+5. if $t.sign = MP\_NEG$ then \\
+\hspace{3mm}5.1 $str \leftarrow str + $ ``-'' \\
+\hspace{3mm}5.2 $t.sign = MP\_ZPOS$ \\
+6. While ($t \ne 0$) do \\
+\hspace{3mm}6.1 $d \leftarrow t \mbox{ (mod }r\mbox{)}$ \\
+\hspace{3mm}6.2 $t \leftarrow \lfloor t / r \rfloor$ \\
+\hspace{3mm}6.3 Look up $d$ in the map and store the equivalent character in $y$. \\
+\hspace{3mm}6.4 $str \leftarrow str + y$ \\
+7. If $str_0 = $``$-$'' then \\
+\hspace{3mm}7.1 Reverse the digits $str_1, str_2, \ldots str_n$. \\
+8. Otherwise \\
+\hspace{3mm}8.1 Reverse the digits $str_0, str_1, \ldots str_n$. \\
+9. Return(\textit{MP\_OKAY}).\\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_toradix}
+\end{figure}
+\textbf{Algorithm mp\_toradix.}
+This algorithm computes the radix-$r$ representation of an mp\_int $a$. The ``digits'' of the representation are extracted by reducing
+successive powers of $\lfloor a / r^k \rfloor$ the input modulo $r$ until $r^k > a$. Note that instead of actually dividing by $r^k$ in
+each iteration the quotient $\lfloor a / r \rfloor$ is saved for the next iteration. As a result a series of trivial $n \times 1$ divisions
+are required instead of a series of $n \times k$ divisions. One design flaw of this approach is that the digits are produced in the reverse order
+(see~\ref{fig:mpradix}). To remedy this flaw the digits must be swapped or simply ``reversed''.
+
+\begin{figure}
+\begin{center}
+\begin{tabular}{|c|c|c|}
+\hline \textbf{Value of $a$} & \textbf{Value of $d$} & \textbf{Value of $str$} \\
+\hline $1234$ & -- & -- \\
+\hline $123$ & $4$ & ``4'' \\
+\hline $12$ & $3$ & ``43'' \\
+\hline $1$ & $2$ & ``432'' \\
+\hline $0$ & $1$ & ``4321'' \\
+\hline
+\end{tabular}
+\end{center}
+\caption{Example of Algorithm mp\_toradix.}
+\label{fig:mpradix}
+\end{figure}
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_toradix.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+\chapter{Number Theoretic Algorithms}
+This chapter discusses several fundamental number theoretic algorithms such as the greatest common divisor, least common multiple and Jacobi
+symbol computation. These algorithms arise as essential components in several key cryptographic algorithms such as the RSA public key algorithm and
+various Sieve based factoring algorithms.
+
+\section{Greatest Common Divisor}
+The greatest common divisor of two integers $a$ and $b$, often denoted as $(a, b)$ is the largest integer $k$ that is a proper divisor of
+both $a$ and $b$. That is, $k$ is the largest integer such that $0 \equiv a \mbox{ (mod }k\mbox{)}$ and $0 \equiv b \mbox{ (mod }k\mbox{)}$ occur
+simultaneously.
+
+The most common approach (cite) is to reduce one input modulo another. That is if $a$ and $b$ are divisible by some integer $k$ and if $qa + r = b$ then
+$r$ is also divisible by $k$. The reduction pattern follows $\left < a , b \right > \rightarrow \left < b, a \mbox{ mod } b \right >$.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Greatest Common Divisor (I)}. \\
+\textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\
+\textbf{Output}. The greatest common divisor $(a, b)$. \\
+\hline \\
+1. While ($b > 0$) do \\
+\hspace{3mm}1.1 $r \leftarrow a \mbox{ (mod }b\mbox{)}$ \\
+\hspace{3mm}1.2 $a \leftarrow b$ \\
+\hspace{3mm}1.3 $b \leftarrow r$ \\
+2. Return($a$). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm Greatest Common Divisor (I)}
+\label{fig:gcd1}
+\end{figure}
+
+This algorithm will quickly converge on the greatest common divisor since the residue $r$ tends diminish rapidly. However, divisions are
+relatively expensive operations to perform and should ideally be avoided. There is another approach based on a similar relationship of
+greatest common divisors. The faster approach is based on the observation that if $k$ divides both $a$ and $b$ it will also divide $a - b$.
+In particular, we would like $a - b$ to decrease in magnitude which implies that $b \ge a$.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Greatest Common Divisor (II)}. \\
+\textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\
+\textbf{Output}. The greatest common divisor $(a, b)$. \\
+\hline \\
+1. While ($b > 0$) do \\
+\hspace{3mm}1.1 Swap $a$ and $b$ such that $a$ is the smallest of the two. \\
+\hspace{3mm}1.2 $b \leftarrow b - a$ \\
+2. Return($a$). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm Greatest Common Divisor (II)}
+\label{fig:gcd2}
+\end{figure}
+
+\textbf{Proof} \textit{Algorithm~\ref{fig:gcd2} will return the greatest common divisor of $a$ and $b$.}
+The algorithm in figure~\ref{fig:gcd2} will eventually terminate since $b \ge a$ the subtraction in step 1.2 will be a value less than $b$. In other
+words in every iteration that tuple $\left < a, b \right >$ decrease in magnitude until eventually $a = b$. Since both $a$ and $b$ are always
+divisible by the greatest common divisor (\textit{until the last iteration}) and in the last iteration of the algorithm $b = 0$, therefore, in the
+second to last iteration of the algorithm $b = a$ and clearly $(a, a) = a$ which concludes the proof. \textbf{QED}.
+
+As a matter of practicality algorithm \ref{fig:gcd1} decreases far too slowly to be useful. Specially if $b$ is much larger than $a$ such that
+$b - a$ is still very much larger than $a$. A simple addition to the algorithm is to divide $b - a$ by a power of some integer $p$ which does
+not divide the greatest common divisor but will divide $b - a$. In this case ${b - a} \over p$ is also an integer and still divisible by
+the greatest common divisor.
+
+However, instead of factoring $b - a$ to find a suitable value of $p$ the powers of $p$ can be removed from $a$ and $b$ that are in common first.
+Then inside the loop whenever $b - a$ is divisible by some power of $p$ it can be safely removed.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{Greatest Common Divisor (III)}. \\
+\textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\
+\textbf{Output}. The greatest common divisor $(a, b)$. \\
+\hline \\
+1. $k \leftarrow 0$ \\
+2. While $a$ and $b$ are both divisible by $p$ do \\
+\hspace{3mm}2.1 $a \leftarrow \lfloor a / p \rfloor$ \\
+\hspace{3mm}2.2 $b \leftarrow \lfloor b / p \rfloor$ \\
+\hspace{3mm}2.3 $k \leftarrow k + 1$ \\
+3. While $a$ is divisible by $p$ do \\
+\hspace{3mm}3.1 $a \leftarrow \lfloor a / p \rfloor$ \\
+4. While $b$ is divisible by $p$ do \\
+\hspace{3mm}4.1 $b \leftarrow \lfloor b / p \rfloor$ \\
+5. While ($b > 0$) do \\
+\hspace{3mm}5.1 Swap $a$ and $b$ such that $a$ is the smallest of the two. \\
+\hspace{3mm}5.2 $b \leftarrow b - a$ \\
+\hspace{3mm}5.3 While $b$ is divisible by $p$ do \\
+\hspace{6mm}5.3.1 $b \leftarrow \lfloor b / p \rfloor$ \\
+6. Return($a \cdot p^k$). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm Greatest Common Divisor (III)}
+\label{fig:gcd3}
+\end{figure}
+
+This algorithm is based on the first except it removes powers of $p$ first and inside the main loop to ensure the tuple $\left < a, b \right >$
+decreases more rapidly. The first loop on step two removes powers of $p$ that are in common. A count, $k$, is kept which will present a common
+divisor of $p^k$. After step two the remaining common divisor of $a$ and $b$ cannot be divisible by $p$. This means that $p$ can be safely
+divided out of the difference $b - a$ so long as the division leaves no remainder.
+
+In particular the value of $p$ should be chosen such that the division on step 5.3.1 occur often. It also helps that division by $p$ be easy
+to compute. The ideal choice of $p$ is two since division by two amounts to a right logical shift. Another important observation is that by
+step five both $a$ and $b$ are odd. Therefore, the diffrence $b - a$ must be even which means that each iteration removes one bit from the
+largest of the pair.
+
+\subsection{Complete Greatest Common Divisor}
+The algorithms presented so far cannot handle inputs which are zero or negative. The following algorithm can handle all input cases properly
+and will produce the greatest common divisor.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_gcd}. \\
+\textbf{Input}. mp\_int $a$ and $b$ \\
+\textbf{Output}. The greatest common divisor $c = (a, b)$. \\
+\hline \\
+1. If $a = 0$ then \\
+\hspace{3mm}1.1 $c \leftarrow \vert b \vert $ \\
+\hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\
+2. If $b = 0$ then \\
+\hspace{3mm}2.1 $c \leftarrow \vert a \vert $ \\
+\hspace{3mm}2.2 Return(\textit{MP\_OKAY}). \\
+3. $u \leftarrow \vert a \vert, v \leftarrow \vert b \vert$ \\
+4. $k \leftarrow 0$ \\
+5. While $u.used > 0$ and $v.used > 0$ and $u_0 \equiv v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
+\hspace{3mm}5.1 $k \leftarrow k + 1$ \\
+\hspace{3mm}5.2 $u \leftarrow \lfloor u / 2 \rfloor$ \\
+\hspace{3mm}5.3 $v \leftarrow \lfloor v / 2 \rfloor$ \\
+6. While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
+\hspace{3mm}6.1 $u \leftarrow \lfloor u / 2 \rfloor$ \\
+7. While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
+\hspace{3mm}7.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\
+8. While $v.used > 0$ \\
+\hspace{3mm}8.1 If $\vert u \vert > \vert v \vert$ then \\
+\hspace{6mm}8.1.1 Swap $u$ and $v$. \\
+\hspace{3mm}8.2 $v \leftarrow \vert v \vert - \vert u \vert$ \\
+\hspace{3mm}8.3 While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
+\hspace{6mm}8.3.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\
+9. $c \leftarrow u \cdot 2^k$ \\
+10. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_gcd}
+\end{figure}
+\textbf{Algorithm mp\_gcd.}
+This algorithm will produce the greatest common divisor of two mp\_ints $a$ and $b$. The algorithm was originally based on Algorithm B of
+Knuth \cite[pp. 338]{TAOCPV2} but has been modified to be simpler to explain. In theory it achieves the same asymptotic working time as
+Algorithm B and in practice this appears to be true.
+
+The first two steps handle the cases where either one of or both inputs are zero. If either input is zero the greatest common divisor is the
+largest input or zero if they are both zero. If the inputs are not trivial than $u$ and $v$ are assigned the absolute values of
+$a$ and $b$ respectively and the algorithm will proceed to reduce the pair.
+
+Step five will divide out any common factors of two and keep track of the count in the variable $k$. After this step, two is no longer a
+factor of the remaining greatest common divisor between $u$ and $v$ and can be safely evenly divided out of either whenever they are even. Step
+six and seven ensure that the $u$ and $v$ respectively have no more factors of two. At most only one of the while--loops will iterate since
+they cannot both be even.
+
+By step eight both of $u$ and $v$ are odd which is required for the inner logic. First the pair are swapped such that $v$ is equal to
+or greater than $u$. This ensures that the subtraction on step 8.2 will always produce a positive and even result. Step 8.3 removes any
+factors of two from the difference $u$ to ensure that in the next iteration of the loop both are once again odd.
+
+After $v = 0$ occurs the variable $u$ has the greatest common divisor of the pair $\left < u, v \right >$ just after step six. The result
+must be adjusted by multiplying by the common factors of two ($2^k$) removed earlier.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_gcd.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+This function makes use of the macros mp\_iszero and mp\_iseven. The former evaluates to $1$ if the input mp\_int is equivalent to the
+integer zero otherwise it evaluates to $0$. The latter evaluates to $1$ if the input mp\_int represents a non-zero even integer otherwise
+it evaluates to $0$. Note that just because mp\_iseven may evaluate to $0$ does not mean the input is odd, it could also be zero. The three
+trivial cases of inputs are handled on lines 24 through 30. After those lines the inputs are assumed to be non-zero.
+
+Lines 32 and 37 make local copies $u$ and $v$ of the inputs $a$ and $b$ respectively. At this point the common factors of two
+must be divided out of the two inputs. The block starting at line 44 removes common factors of two by first counting the number of trailing
+zero bits in both. The local integer $k$ is used to keep track of how many factors of $2$ are pulled out of both values. It is assumed that
+the number of factors will not exceed the maximum value of a C ``int'' data type\footnote{Strictly speaking no array in C may have more than
+entries than are accessible by an ``int'' so this is not a limitation.}.
+
+At this point there are no more common factors of two in the two values. The divisions by a power of two on lines 62 and 68 remove
+any independent factors of two such that both $u$ and $v$ are guaranteed to be an odd integer before hitting the main body of the algorithm. The while loop
+on line 73 performs the reduction of the pair until $v$ is equal to zero. The unsigned comparison and subtraction algorithms are used in
+place of the full signed routines since both values are guaranteed to be positive and the result of the subtraction is guaranteed to be non-negative.
+
+\section{Least Common Multiple}
+The least common multiple of a pair of integers is their product divided by their greatest common divisor. For two integers $a$ and $b$ the
+least common multiple is normally denoted as $[ a, b ]$ and numerically equivalent to ${ab} \over {(a, b)}$. For example, if $a = 2 \cdot 2 \cdot 3 = 12$
+and $b = 2 \cdot 3 \cdot 3 \cdot 7 = 126$ the least common multiple is ${126 \over {(12, 126)}} = {126 \over 6} = 21$.
+
+The least common multiple arises often in coding theory as well as number theory. If two functions have periods of $a$ and $b$ respectively they will
+collide, that is be in synchronous states, after only $[ a, b ]$ iterations. This is why, for example, random number generators based on
+Linear Feedback Shift Registers (LFSR) tend to use registers with periods which are co-prime (\textit{e.g. the greatest common divisor is one.}).
+Similarly in number theory if a composite $n$ has two prime factors $p$ and $q$ then maximal order of any unit of $\Z/n\Z$ will be $[ p - 1, q - 1] $.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_lcm}. \\
+\textbf{Input}. mp\_int $a$ and $b$ \\
+\textbf{Output}. The least common multiple $c = [a, b]$. \\
+\hline \\
+1. $c \leftarrow (a, b)$ \\
+2. $t \leftarrow a \cdot b$ \\
+3. $c \leftarrow \lfloor t / c \rfloor$ \\
+4. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_lcm}
+\end{figure}
+\textbf{Algorithm mp\_lcm.}
+This algorithm computes the least common multiple of two mp\_int inputs $a$ and $b$. It computes the least common multiple directly by
+dividing the product of the two inputs by their greatest common divisor.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_lcm.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+\section{Jacobi Symbol Computation}
+To explain the Jacobi Symbol we shall first discuss the Legendre function\footnote{Arrg. What is the name of this?} off which the Jacobi symbol is
+defined. The Legendre function computes whether or not an integer $a$ is a quadratic residue modulo an odd prime $p$. Numerically it is
+equivalent to equation \ref{eqn:legendre}.
+
+\textit{-- Tom, don't be an ass, cite your source here...!}
+
+\begin{equation}
+a^{(p-1)/2} \equiv \begin{array}{rl}
+ -1 & \mbox{if }a\mbox{ is a quadratic non-residue.} \\
+ 0 & \mbox{if }a\mbox{ divides }p\mbox{.} \\
+ 1 & \mbox{if }a\mbox{ is a quadratic residue}.
+ \end{array} \mbox{ (mod }p\mbox{)}
+\label{eqn:legendre}
+\end{equation}
+
+\textbf{Proof.} \textit{Equation \ref{eqn:legendre} correctly identifies the residue status of an integer $a$ modulo a prime $p$.}
+An integer $a$ is a quadratic residue if the following equation has a solution.
+
+\begin{equation}
+x^2 \equiv a \mbox{ (mod }p\mbox{)}
+\label{eqn:root}
+\end{equation}
+
+Consider the following equation.
+
+\begin{equation}
+0 \equiv x^{p-1} - 1 \equiv \left \lbrace \left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \right \rbrace + \left ( a^{(p-1)/2} - 1 \right ) \mbox{ (mod }p\mbox{)}
+\label{eqn:rooti}
+\end{equation}
+
+Whether equation \ref{eqn:root} has a solution or not equation \ref{eqn:rooti} is always true. If $a^{(p-1)/2} - 1 \equiv 0 \mbox{ (mod }p\mbox{)}$
+then the quantity in the braces must be zero. By reduction,
+
+\begin{eqnarray}
+\left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \equiv 0 \nonumber \\
+\left (x^2 \right )^{(p-1)/2} \equiv a^{(p-1)/2} \nonumber \\
+x^2 \equiv a \mbox{ (mod }p\mbox{)}
+\end{eqnarray}
+
+As a result there must be a solution to the quadratic equation and in turn $a$ must be a quadratic residue. If $a$ does not divide $p$ and $a$
+is not a quadratic residue then the only other value $a^{(p-1)/2}$ may be congruent to is $-1$ since
+\begin{equation}
+0 \equiv a^{p - 1} - 1 \equiv (a^{(p-1)/2} + 1)(a^{(p-1)/2} - 1) \mbox{ (mod }p\mbox{)}
+\end{equation}
+One of the terms on the right hand side must be zero. \textbf{QED}
+
+\subsection{Jacobi Symbol}
+The Jacobi symbol is a generalization of the Legendre function for any odd non prime moduli $p$ greater than 2. If $p = \prod_{i=0}^n p_i$ then
+the Jacobi symbol $\left ( { a \over p } \right )$ is equal to the following equation.
+
+\begin{equation}
+\left ( { a \over p } \right ) = \left ( { a \over p_0} \right ) \left ( { a \over p_1} \right ) \ldots \left ( { a \over p_n} \right )
+\end{equation}
+
+By inspection if $p$ is prime the Jacobi symbol is equivalent to the Legendre function. The following facts\footnote{See HAC \cite[pp. 72-74]{HAC} for
+further details.} will be used to derive an efficient Jacobi symbol algorithm. Where $p$ is an odd integer greater than two and $a, b \in \Z$ the
+following are true.
+
+\begin{enumerate}
+\item $\left ( { a \over p} \right )$ equals $-1$, $0$ or $1$.
+\item $\left ( { ab \over p} \right ) = \left ( { a \over p} \right )\left ( { b \over p} \right )$.
+\item If $a \equiv b$ then $\left ( { a \over p} \right ) = \left ( { b \over p} \right )$.
+\item $\left ( { 2 \over p} \right )$ equals $1$ if $p \equiv 1$ or $7 \mbox{ (mod }8\mbox{)}$. Otherwise, it equals $-1$.
+\item $\left ( { a \over p} \right ) \equiv \left ( { p \over a} \right ) \cdot (-1)^{(p-1)(a-1)/4}$. More specifically
+$\left ( { a \over p} \right ) = \left ( { p \over a} \right )$ if $p \equiv a \equiv 1 \mbox{ (mod }4\mbox{)}$.
+\end{enumerate}
+
+Using these facts if $a = 2^k \cdot a'$ then
+
+\begin{eqnarray}
+\left ( { a \over p } \right ) = \left ( {{2^k} \over p } \right ) \left ( {a' \over p} \right ) \nonumber \\
+ = \left ( {2 \over p } \right )^k \left ( {a' \over p} \right )
+\label{eqn:jacobi}
+\end{eqnarray}
+
+By fact five,
+
+\begin{equation}
+\left ( { a \over p } \right ) = \left ( { p \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4}
+\end{equation}
+
+Subsequently by fact three since $p \equiv (p \mbox{ mod }a) \mbox{ (mod }a\mbox{)}$ then
+
+\begin{equation}
+\left ( { a \over p } \right ) = \left ( { {p \mbox{ mod } a} \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4}
+\end{equation}
+
+By putting both observations into equation \ref{eqn:jacobi} the following simplified equation is formed.
+
+\begin{equation}
+\left ( { a \over p } \right ) = \left ( {2 \over p } \right )^k \left ( {{p\mbox{ mod }a'} \over a'} \right ) \cdot (-1)^{(p-1)(a'-1)/4}
+\end{equation}
+
+The value of $\left ( {{p \mbox{ mod }a'} \over a'} \right )$ can be found by using the same equation recursively. The value of
+$\left ( {2 \over p } \right )^k$ equals $1$ if $k$ is even otherwise it equals $\left ( {2 \over p } \right )$. Using this approach the
+factors of $p$ do not have to be known. Furthermore, if $(a, p) = 1$ then the algorithm will terminate when the recursion requests the
+Jacobi symbol computation of $\left ( {1 \over a'} \right )$ which is simply $1$.
+
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_jacobi}. \\
+\textbf{Input}. mp\_int $a$ and $p$, $a \ge 0$, $p \ge 3$, $p \equiv 1 \mbox{ (mod }2\mbox{)}$ \\
+\textbf{Output}. The Jacobi symbol $c = \left ( {a \over p } \right )$. \\
+\hline \\
+1. If $a = 0$ then \\
+\hspace{3mm}1.1 $c \leftarrow 0$ \\
+\hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\
+2. If $a = 1$ then \\
+\hspace{3mm}2.1 $c \leftarrow 1$ \\
+\hspace{3mm}2.2 Return(\textit{MP\_OKAY}). \\
+3. $a' \leftarrow a$ \\
+4. $k \leftarrow 0$ \\
+5. While $a'.used > 0$ and $a'_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
+\hspace{3mm}5.1 $k \leftarrow k + 1$ \\
+\hspace{3mm}5.2 $a' \leftarrow \lfloor a' / 2 \rfloor$ \\
+6. If $k \equiv 0 \mbox{ (mod }2\mbox{)}$ then \\
+\hspace{3mm}6.1 $s \leftarrow 1$ \\
+7. else \\
+\hspace{3mm}7.1 $r \leftarrow p_0 \mbox{ (mod }8\mbox{)}$ \\
+\hspace{3mm}7.2 If $r = 1$ or $r = 7$ then \\
+\hspace{6mm}7.2.1 $s \leftarrow 1$ \\
+\hspace{3mm}7.3 else \\
+\hspace{6mm}7.3.1 $s \leftarrow -1$ \\
+8. If $p_0 \equiv a'_0 \equiv 3 \mbox{ (mod }4\mbox{)}$ then \\
+\hspace{3mm}8.1 $s \leftarrow -s$ \\
+9. If $a' \ne 1$ then \\
+\hspace{3mm}9.1 $p' \leftarrow p \mbox{ (mod }a'\mbox{)}$ \\
+\hspace{3mm}9.2 $s \leftarrow s \cdot \mbox{mp\_jacobi}(p', a')$ \\
+10. $c \leftarrow s$ \\
+11. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_jacobi}
+\end{figure}
+\textbf{Algorithm mp\_jacobi.}
+This algorithm computes the Jacobi symbol for an arbitrary positive integer $a$ with respect to an odd integer $p$ greater than three. The algorithm
+is based on algorithm 2.149 of HAC \cite[pp. 73]{HAC}.
+
+Step numbers one and two handle the trivial cases of $a = 0$ and $a = 1$ respectively. Step five determines the number of two factors in the
+input $a$. If $k$ is even than the term $\left ( { 2 \over p } \right )^k$ must always evaluate to one. If $k$ is odd than the term evaluates to one
+if $p_0$ is congruent to one or seven modulo eight, otherwise it evaluates to $-1$. After the the $\left ( { 2 \over p } \right )^k$ term is handled
+the $(-1)^{(p-1)(a'-1)/4}$ is computed and multiplied against the current product $s$. The latter term evaluates to one if both $p$ and $a'$
+are congruent to one modulo four, otherwise it evaluates to negative one.
+
+By step nine if $a'$ does not equal one a recursion is required. Step 9.1 computes $p' \equiv p \mbox{ (mod }a'\mbox{)}$ and will recurse to compute
+$\left ( {p' \over a'} \right )$ which is multiplied against the current Jacobi product.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_jacobi.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+As a matter of practicality the variable $a'$ as per the pseudo-code is reprensented by the variable $a1$ since the $'$ symbol is not valid for a C
+variable name character.
+
+The two simple cases of $a = 0$ and $a = 1$ are handled at the very beginning to simplify the algorithm. If the input is non-trivial the algorithm
+has to proceed compute the Jacobi. The variable $s$ is used to hold the current Jacobi product. Note that $s$ is merely a C ``int'' data type since
+the values it may obtain are merely $-1$, $0$ and $1$.
+
+After a local copy of $a$ is made all of the factors of two are divided out and the total stored in $k$. Technically only the least significant
+bit of $k$ is required, however, it makes the algorithm simpler to follow to perform an addition. In practice an exclusive-or and addition have the same
+processor requirements and neither is faster than the other.
+
+Line 58 through 71 determines the value of $\left ( { 2 \over p } \right )^k$. If the least significant bit of $k$ is zero than
+$k$ is even and the value is one. Otherwise, the value of $s$ depends on which residue class $p$ belongs to modulo eight. The value of
+$(-1)^{(p-1)(a'-1)/4}$ is compute and multiplied against $s$ on lines 71 through 74.
+
+Finally, if $a1$ does not equal one the algorithm must recurse and compute $\left ( {p' \over a'} \right )$.
+
+\textit{-- Comment about default $s$ and such...}
+
+\section{Modular Inverse}
+\label{sec:modinv}
+The modular inverse of a number actually refers to the modular multiplicative inverse. Essentially for any integer $a$ such that $(a, p) = 1$ there
+exist another integer $b$ such that $ab \equiv 1 \mbox{ (mod }p\mbox{)}$. The integer $b$ is called the multiplicative inverse of $a$ which is
+denoted as $b = a^{-1}$. Technically speaking modular inversion is a well defined operation for any finite ring or field not just for rings and
+fields of integers. However, the former will be the matter of discussion.
+
+The simplest approach is to compute the algebraic inverse of the input. That is to compute $b \equiv a^{\Phi(p) - 1}$. If $\Phi(p)$ is the
+order of the multiplicative subgroup modulo $p$ then $b$ must be the multiplicative inverse of $a$. The proof of which is trivial.
+
+\begin{equation}
+ab \equiv a \left (a^{\Phi(p) - 1} \right ) \equiv a^{\Phi(p)} \equiv a^0 \equiv 1 \mbox{ (mod }p\mbox{)}
+\end{equation}
+
+However, as simple as this approach may be it has two serious flaws. It requires that the value of $\Phi(p)$ be known which if $p$ is composite
+requires all of the prime factors. This approach also is very slow as the size of $p$ grows.
+
+A simpler approach is based on the observation that solving for the multiplicative inverse is equivalent to solving the linear
+Diophantine\footnote{See LeVeque \cite[pp. 40-43]{LeVeque} for more information.} equation.
+
+\begin{equation}
+ab + pq = 1
+\end{equation}
+
+Where $a$, $b$, $p$ and $q$ are all integers. If such a pair of integers $ \left < b, q \right >$ exist than $b$ is the multiplicative inverse of
+$a$ modulo $p$. The extended Euclidean algorithm (Knuth \cite[pp. 342]{TAOCPV2}) can be used to solve such equations provided $(a, p) = 1$.
+However, instead of using that algorithm directly a variant known as the binary Extended Euclidean algorithm will be used in its place. The
+binary approach is very similar to the binary greatest common divisor algorithm except it will produce a full solution to the Diophantine
+equation.
+
+\subsection{General Case}
+\newpage\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_invmod}. \\
+\textbf{Input}. mp\_int $a$ and $b$, $(a, b) = 1$, $p \ge 2$, $0 < a < p$. \\
+\textbf{Output}. The modular inverse $c \equiv a^{-1} \mbox{ (mod }b\mbox{)}$. \\
+\hline \\
+1. If $b \le 0$ then return(\textit{MP\_VAL}). \\
+2. If $b_0 \equiv 1 \mbox{ (mod }2\mbox{)}$ then use algorithm fast\_mp\_invmod. \\
+3. $x \leftarrow \vert a \vert, y \leftarrow b$ \\
+4. If $x_0 \equiv y_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ then return(\textit{MP\_VAL}). \\
+5. $B \leftarrow 0, C \leftarrow 0, A \leftarrow 1, D \leftarrow 1$ \\
+6. While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
+\hspace{3mm}6.1 $u \leftarrow \lfloor u / 2 \rfloor$ \\
+\hspace{3mm}6.2 If ($A.used > 0$ and $A_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) or ($B.used > 0$ and $B_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) then \\
+\hspace{6mm}6.2.1 $A \leftarrow A + y$ \\
+\hspace{6mm}6.2.2 $B \leftarrow B - x$ \\
+\hspace{3mm}6.3 $A \leftarrow \lfloor A / 2 \rfloor$ \\
+\hspace{3mm}6.4 $B \leftarrow \lfloor B / 2 \rfloor$ \\
+7. While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
+\hspace{3mm}7.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\
+\hspace{3mm}7.2 If ($C.used > 0$ and $C_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) or ($D.used > 0$ and $D_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) then \\
+\hspace{6mm}7.2.1 $C \leftarrow C + y$ \\
+\hspace{6mm}7.2.2 $D \leftarrow D - x$ \\
+\hspace{3mm}7.3 $C \leftarrow \lfloor C / 2 \rfloor$ \\
+\hspace{3mm}7.4 $D \leftarrow \lfloor D / 2 \rfloor$ \\
+8. If $u \ge v$ then \\
+\hspace{3mm}8.1 $u \leftarrow u - v$ \\
+\hspace{3mm}8.2 $A \leftarrow A - C$ \\
+\hspace{3mm}8.3 $B \leftarrow B - D$ \\
+9. else \\
+\hspace{3mm}9.1 $v \leftarrow v - u$ \\
+\hspace{3mm}9.2 $C \leftarrow C - A$ \\
+\hspace{3mm}9.3 $D \leftarrow D - B$ \\
+10. If $u \ne 0$ goto step 6. \\
+11. If $v \ne 1$ return(\textit{MP\_VAL}). \\
+12. While $C \le 0$ do \\
+\hspace{3mm}12.1 $C \leftarrow C + b$ \\
+13. While $C \ge b$ do \\
+\hspace{3mm}13.1 $C \leftarrow C - b$ \\
+14. $c \leftarrow C$ \\
+15. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\end{figure}
+\textbf{Algorithm mp\_invmod.}
+This algorithm computes the modular multiplicative inverse of an integer $a$ modulo an integer $b$. This algorithm is a variation of the
+extended binary Euclidean algorithm from HAC \cite[pp. 608]{HAC}. It has been modified to only compute the modular inverse and not a complete
+Diophantine solution.
+
+If $b \le 0$ than the modulus is invalid and MP\_VAL is returned. Similarly if both $a$ and $b$ are even then there cannot be a multiplicative
+inverse for $a$ and the error is reported.
+
+The astute reader will observe that steps seven through nine are very similar to the binary greatest common divisor algorithm mp\_gcd. In this case
+the other variables to the Diophantine equation are solved. The algorithm terminates when $u = 0$ in which case the solution is
+
+\begin{equation}
+Ca + Db = v
+\end{equation}
+
+If $v$, the greatest common divisor of $a$ and $b$ is not equal to one then the algorithm will report an error as no inverse exists. Otherwise, $C$
+is the modular inverse of $a$. The actual value of $C$ is congruent to, but not necessarily equal to, the ideal modular inverse which should lie
+within $1 \le a^{-1} < b$. Step numbers twelve and thirteen adjust the inverse until it is in range. If the original input $a$ is within $0 < a < p$
+then only a couple of additions or subtractions will be required to adjust the inverse.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_invmod.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+\subsubsection{Odd Moduli}
+
+When the modulus $b$ is odd the variables $A$ and $C$ are fixed and are not required to compute the inverse. In particular by attempting to solve
+the Diophantine $Cb + Da = 1$ only $B$ and $D$ are required to find the inverse of $a$.
+
+The algorithm fast\_mp\_invmod is a direct adaptation of algorithm mp\_invmod with all all steps involving either $A$ or $C$ removed. This
+optimization will halve the time required to compute the modular inverse.
+
+\section{Primality Tests}
+
+A non-zero integer $a$ is said to be prime if it is not divisible by any other integer excluding one and itself. For example, $a = 7$ is prime
+since the integers $2 \ldots 6$ do not evenly divide $a$. By contrast, $a = 6$ is not prime since $a = 6 = 2 \cdot 3$.
+
+Prime numbers arise in cryptography considerably as they allow finite fields to be formed. The ability to determine whether an integer is prime or
+not quickly has been a viable subject in cryptography and number theory for considerable time. The algorithms that will be presented are all
+probablistic algorithms in that when they report an integer is composite it must be composite. However, when the algorithms report an integer is
+prime the algorithm may be incorrect.
+
+As will be discussed it is possible to limit the probability of error so well that for practical purposes the probablity of error might as
+well be zero. For the purposes of these discussions let $n$ represent the candidate integer of which the primality is in question.
+
+\subsection{Trial Division}
+
+Trial division means to attempt to evenly divide a candidate integer by small prime integers. If the candidate can be evenly divided it obviously
+cannot be prime. By dividing by all primes $1 < p \le \sqrt{n}$ this test can actually prove whether an integer is prime. However, such a test
+would require a prohibitive amount of time as $n$ grows.
+
+Instead of dividing by every prime, a smaller, more mangeable set of primes may be used instead. By performing trial division with only a subset
+of the primes less than $\sqrt{n} + 1$ the algorithm cannot prove if a candidate is prime. However, often it can prove a candidate is not prime.
+
+The benefit of this test is that trial division by small values is fairly efficient. Specially compared to the other algorithms that will be
+discussed shortly. The probability that this approach correctly identifies a composite candidate when tested with all primes upto $q$ is given by
+$1 - {1.12 \over ln(q)}$. The graph (\ref{pic:primality}, will be added later) demonstrates the probability of success for the range
+$3 \le q \le 100$.
+
+At approximately $q = 30$ the gain of performing further tests diminishes fairly quickly. At $q = 90$ further testing is generally not going to
+be of any practical use. In the case of LibTomMath the default limit $q = 256$ was chosen since it is not too high and will eliminate
+approximately $80\%$ of all candidate integers. The constant \textbf{PRIME\_SIZE} is equal to the number of primes in the test base. The
+array \_\_prime\_tab is an array of the first \textbf{PRIME\_SIZE} prime numbers.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_prime\_is\_divisible}. \\
+\textbf{Input}. mp\_int $a$ \\
+\textbf{Output}. $c = 1$ if $n$ is divisible by a small prime, otherwise $c = 0$. \\
+\hline \\
+1. for $ix$ from $0$ to $PRIME\_SIZE$ do \\
+\hspace{3mm}1.1 $d \leftarrow n \mbox{ (mod }\_\_prime\_tab_{ix}\mbox{)}$ \\
+\hspace{3mm}1.2 If $d = 0$ then \\
+\hspace{6mm}1.2.1 $c \leftarrow 1$ \\
+\hspace{6mm}1.2.2 Return(\textit{MP\_OKAY}). \\
+2. $c \leftarrow 0$ \\
+3. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_prime\_is\_divisible}
+\end{figure}
+\textbf{Algorithm mp\_prime\_is\_divisible.}
+This algorithm attempts to determine if a candidate integer $n$ is composite by performing trial divisions.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_prime\_is\_divisible.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+The algorithm defaults to a return of $0$ in case an error occurs. The values in the prime table are all specified to be in the range of a
+mp\_digit. The table \_\_prime\_tab is defined in the following file.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_prime\_tab.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+Note that there are two possible tables. When an mp\_digit is 7-bits long only the primes upto $127$ may be included, otherwise the primes
+upto $1619$ are used. Note that the value of \textbf{PRIME\_SIZE} is a constant dependent on the size of a mp\_digit.
+
+\subsection{The Fermat Test}
+The Fermat test is probably one the oldest tests to have a non-trivial probability of success. It is based on the fact that if $n$ is in
+fact prime then $a^{n} \equiv a \mbox{ (mod }n\mbox{)}$ for all $0 < a < n$. The reason being that if $n$ is prime than the order of
+the multiplicative sub group is $n - 1$. Any base $a$ must have an order which divides $n - 1$ and as such $a^n$ is equivalent to
+$a^1 = a$.
+
+If $n$ is composite then any given base $a$ does not have to have a period which divides $n - 1$. In which case
+it is possible that $a^n \nequiv a \mbox{ (mod }n\mbox{)}$. However, this test is not absolute as it is possible that the order
+of a base will divide $n - 1$ which would then be reported as prime. Such a base yields what is known as a Fermat pseudo-prime. Several
+integers known as Carmichael numbers will be a pseudo-prime to all valid bases. Fortunately such numbers are extremely rare as $n$ grows
+in size.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_prime\_fermat}. \\
+\textbf{Input}. mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$. \\
+\textbf{Output}. $c = 1$ if $b^a \equiv b \mbox{ (mod }a\mbox{)}$, otherwise $c = 0$. \\
+\hline \\
+1. $t \leftarrow b^a \mbox{ (mod }a\mbox{)}$ \\
+2. If $t = b$ then \\
+\hspace{3mm}2.1 $c = 1$ \\
+3. else \\
+\hspace{3mm}3.1 $c = 0$ \\
+4. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_prime\_fermat}
+\end{figure}
+\textbf{Algorithm mp\_prime\_fermat.}
+This algorithm determines whether an mp\_int $a$ is a Fermat prime to the base $b$ or not. It uses a single modular exponentiation to
+determine the result.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_prime\_fermat.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+\subsection{The Miller-Rabin Test}
+The Miller-Rabin (citation) test is another primality test which has tighter error bounds than the Fermat test specifically with sequentially chosen
+candidate integers. The algorithm is based on the observation that if $n - 1 = 2^kr$ and if $b^r \nequiv \pm 1$ then after upto $k - 1$ squarings the
+value must be equal to $-1$. The squarings are stopped as soon as $-1$ is observed. If the value of $1$ is observed first it means that
+some value not congruent to $\pm 1$ when squared equals one which cannot occur if $n$ is prime.
+
+\begin{figure}[!here]
+\begin{small}
+\begin{center}
+\begin{tabular}{l}
+\hline Algorithm \textbf{mp\_prime\_miller\_rabin}. \\
+\textbf{Input}. mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$. \\
+\textbf{Output}. $c = 1$ if $a$ is a Miller-Rabin prime to the base $a$, otherwise $c = 0$. \\
+\hline
+1. $a' \leftarrow a - 1$ \\
+2. $r \leftarrow n1$ \\
+3. $c \leftarrow 0, s \leftarrow 0$ \\
+4. While $r.used > 0$ and $r_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
+\hspace{3mm}4.1 $s \leftarrow s + 1$ \\
+\hspace{3mm}4.2 $r \leftarrow \lfloor r / 2 \rfloor$ \\
+5. $y \leftarrow b^r \mbox{ (mod }a\mbox{)}$ \\
+6. If $y \nequiv \pm 1$ then \\
+\hspace{3mm}6.1 $j \leftarrow 1$ \\
+\hspace{3mm}6.2 While $j \le (s - 1)$ and $y \nequiv a'$ \\
+\hspace{6mm}6.2.1 $y \leftarrow y^2 \mbox{ (mod }a\mbox{)}$ \\
+\hspace{6mm}6.2.2 If $y = 1$ then goto step 8. \\
+\hspace{6mm}6.2.3 $j \leftarrow j + 1$ \\
+\hspace{3mm}6.3 If $y \nequiv a'$ goto step 8. \\
+7. $c \leftarrow 1$\\
+8. Return(\textit{MP\_OKAY}). \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+\caption{Algorithm mp\_prime\_miller\_rabin}
+\end{figure}
+\textbf{Algorithm mp\_prime\_miller\_rabin.}
+This algorithm performs one trial round of the Miller-Rabin algorithm to the base $b$. It will set $c = 1$ if the algorithm cannot determine
+if $b$ is composite or $c = 0$ if $b$ is provably composite. The values of $s$ and $r$ are computed such that $a' = a - 1 = 2^sr$.
+
+If the value $y \equiv b^r$ is congruent to $\pm 1$ then the algorithm cannot prove if $a$ is composite or not. Otherwise, the algorithm will
+square $y$ upto $s - 1$ times stopping only when $y \equiv -1$. If $y^2 \equiv 1$ and $y \nequiv \pm 1$ then the algorithm can report that $a$
+is provably composite. If the algorithm performs $s - 1$ squarings and $y \nequiv -1$ then $a$ is provably composite. If $a$ is not provably
+composite then it is \textit{probably} prime.
+
+\vspace{+3mm}\begin{small}
+\hspace{-5.1mm}{\bf File}: bn\_mp\_prime\_miller\_rabin.c
+\vspace{-3mm}
+\begin{alltt}
+\end{alltt}
+\end{small}
+
+
+
+
+\backmatter
+\appendix
+\begin{thebibliography}{ABCDEF}
+\bibitem[1]{TAOCPV2}
+Donald Knuth, \textit{The Art of Computer Programming}, Third Edition, Volume Two, Seminumerical Algorithms, Addison-Wesley, 1998
+
+\bibitem[2]{HAC}
+A. Menezes, P. van Oorschot, S. Vanstone, \textit{Handbook of Applied Cryptography}, CRC Press, 1996
+
+\bibitem[3]{ROSE}
+Michael Rosing, \textit{Implementing Elliptic Curve Cryptography}, Manning Publications, 1999
+
+\bibitem[4]{COMBA}
+Paul G. Comba, \textit{Exponentiation Cryptosystems on the IBM PC}. IBM Systems Journal 29(4): 526-538 (1990)
+
+\bibitem[5]{KARA}
+A. Karatsuba, Doklay Akad. Nauk SSSR 145 (1962), pp.293-294
+
+\bibitem[6]{KARAP}
+Andre Weimerskirch and Christof Paar, \textit{Generalizations of the Karatsuba Algorithm for Polynomial Multiplication}, Submitted to Design, Codes and Cryptography, March 2002
+
+\bibitem[7]{BARRETT}
+Paul Barrett, \textit{Implementing the Rivest Shamir and Adleman Public Key Encryption Algorithm on a Standard Digital Signal Processor}, Advances in Cryptology, Crypto '86, Springer-Verlag.
+
+\bibitem[8]{MONT}
+P.L.Montgomery. \textit{Modular multiplication without trial division}. Mathematics of Computation, 44(170):519-521, April 1985.
+
+\bibitem[9]{DRMET}
+Chae Hoon Lim and Pil Joong Lee, \textit{Generating Efficient Primes for Discrete Log Cryptosystems}, POSTECH Information Research Laboratories
+
+\bibitem[10]{MMB}
+J. Daemen and R. Govaerts and J. Vandewalle, \textit{Block ciphers based on Modular Arithmetic}, State and {P}rogress in the {R}esearch of {C}ryptography, 1993, pp. 80-89
+
+\bibitem[11]{RSAREF}
+R.L. Rivest, A. Shamir, L. Adleman, \textit{A Method for Obtaining Digital Signatures and Public-Key Cryptosystems}
+
+\bibitem[12]{DHREF}
+Whitfield Diffie, Martin E. Hellman, \textit{New Directions in Cryptography}, IEEE Transactions on Information Theory, 1976
+
+\bibitem[13]{IEEE}
+IEEE Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Std 754-1985)
+
+\bibitem[14]{GMP}
+GNU Multiple Precision (GMP), \url{http://www.swox.com/gmp/}
+
+\bibitem[15]{MPI}
+Multiple Precision Integer Library (MPI), Michael Fromberger, \url{http://thayer.dartmouth.edu/~sting/mpi/}
+
+\bibitem[16]{OPENSSL}
+OpenSSL Cryptographic Toolkit, \url{http://openssl.org}
+
+\bibitem[17]{LIP}
+Large Integer Package, \url{http://home.hetnet.nl/~ecstr/LIP.zip}
+
+\bibitem[18]{ISOC}
+JTC1/SC22/WG14, ISO/IEC 9899:1999, ``A draft rationale for the C99 standard.''
+
+\bibitem[19]{JAVA}
+The Sun Java Website, \url{http://java.sun.com/}
+
+\end{thebibliography}
+
+\input{tommath.ind}
+
+\end{document}
diff --git a/libtommath/tommath_class.h b/libtommath/tommath_class.h
new file mode 100644
index 0000000..b9cc902
--- /dev/null
+++ b/libtommath/tommath_class.h
@@ -0,0 +1,995 @@
+#if !(defined(LTM1) && defined(LTM2) && defined(LTM3))
+#if defined(LTM2)
+#define LTM3
+#endif
+#if defined(LTM1)
+#define LTM2
+#endif
+#define LTM1
+
+#if defined(LTM_ALL)
+#define BN_ERROR_C
+#define BN_FAST_MP_INVMOD_C
+#define BN_FAST_MP_MONTGOMERY_REDUCE_C
+#define BN_FAST_S_MP_MUL_DIGS_C
+#define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+#define BN_FAST_S_MP_SQR_C
+#define BN_MP_2EXPT_C
+#define BN_MP_ABS_C
+#define BN_MP_ADD_C
+#define BN_MP_ADD_D_C
+#define BN_MP_ADDMOD_C
+#define BN_MP_AND_C
+#define BN_MP_CLAMP_C
+#define BN_MP_CLEAR_C
+#define BN_MP_CLEAR_MULTI_C
+#define BN_MP_CMP_C
+#define BN_MP_CMP_D_C
+#define BN_MP_CMP_MAG_C
+#define BN_MP_CNT_LSB_C
+#define BN_MP_COPY_C
+#define BN_MP_COUNT_BITS_C
+#define BN_MP_DIV_C
+#define BN_MP_DIV_2_C
+#define BN_MP_DIV_2D_C
+#define BN_MP_DIV_3_C
+#define BN_MP_DIV_D_C
+#define BN_MP_DR_IS_MODULUS_C
+#define BN_MP_DR_REDUCE_C
+#define BN_MP_DR_SETUP_C
+#define BN_MP_EXCH_C
+#define BN_MP_EXPT_D_C
+#define BN_MP_EXPTMOD_C
+#define BN_MP_EXPTMOD_FAST_C
+#define BN_MP_EXTEUCLID_C
+#define BN_MP_FREAD_C
+#define BN_MP_FWRITE_C
+#define BN_MP_GCD_C
+#define BN_MP_GET_INT_C
+#define BN_MP_GROW_C
+#define BN_MP_INIT_C
+#define BN_MP_INIT_COPY_C
+#define BN_MP_INIT_MULTI_C
+#define BN_MP_INIT_SET_C
+#define BN_MP_INIT_SET_INT_C
+#define BN_MP_INIT_SIZE_C
+#define BN_MP_INVMOD_C
+#define BN_MP_INVMOD_SLOW_C
+#define BN_MP_IS_SQUARE_C
+#define BN_MP_JACOBI_C
+#define BN_MP_KARATSUBA_MUL_C
+#define BN_MP_KARATSUBA_SQR_C
+#define BN_MP_LCM_C
+#define BN_MP_LSHD_C
+#define BN_MP_MOD_C
+#define BN_MP_MOD_2D_C
+#define BN_MP_MOD_D_C
+#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+#define BN_MP_MONTGOMERY_REDUCE_C
+#define BN_MP_MONTGOMERY_SETUP_C
+#define BN_MP_MUL_C
+#define BN_MP_MUL_2_C
+#define BN_MP_MUL_2D_C
+#define BN_MP_MUL_D_C
+#define BN_MP_MULMOD_C
+#define BN_MP_N_ROOT_C
+#define BN_MP_NEG_C
+#define BN_MP_OR_C
+#define BN_MP_PRIME_FERMAT_C
+#define BN_MP_PRIME_IS_DIVISIBLE_C
+#define BN_MP_PRIME_IS_PRIME_C
+#define BN_MP_PRIME_MILLER_RABIN_C
+#define BN_MP_PRIME_NEXT_PRIME_C
+#define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+#define BN_MP_PRIME_RANDOM_EX_C
+#define BN_MP_RADIX_SIZE_C
+#define BN_MP_RADIX_SMAP_C
+#define BN_MP_RAND_C
+#define BN_MP_READ_RADIX_C
+#define BN_MP_READ_SIGNED_BIN_C
+#define BN_MP_READ_UNSIGNED_BIN_C
+#define BN_MP_REDUCE_C
+#define BN_MP_REDUCE_2K_C
+#define BN_MP_REDUCE_2K_L_C
+#define BN_MP_REDUCE_2K_SETUP_C
+#define BN_MP_REDUCE_2K_SETUP_L_C
+#define BN_MP_REDUCE_IS_2K_C
+#define BN_MP_REDUCE_IS_2K_L_C
+#define BN_MP_REDUCE_SETUP_C
+#define BN_MP_RSHD_C
+#define BN_MP_SET_C
+#define BN_MP_SET_INT_C
+#define BN_MP_SHRINK_C
+#define BN_MP_SIGNED_BIN_SIZE_C
+#define BN_MP_SQR_C
+#define BN_MP_SQRMOD_C
+#define BN_MP_SQRT_C
+#define BN_MP_SUB_C
+#define BN_MP_SUB_D_C
+#define BN_MP_SUBMOD_C
+#define BN_MP_TO_SIGNED_BIN_C
+#define BN_MP_TO_SIGNED_BIN_N_C
+#define BN_MP_TO_UNSIGNED_BIN_C
+#define BN_MP_TO_UNSIGNED_BIN_N_C
+#define BN_MP_TOOM_MUL_C
+#define BN_MP_TOOM_SQR_C
+#define BN_MP_TORADIX_C
+#define BN_MP_TORADIX_N_C
+#define BN_MP_UNSIGNED_BIN_SIZE_C
+#define BN_MP_XOR_C
+#define BN_MP_ZERO_C
+#define BN_PRIME_TAB_C
+#define BN_REVERSE_C
+#define BN_S_MP_ADD_C
+#define BN_S_MP_EXPTMOD_C
+#define BN_S_MP_MUL_DIGS_C
+#define BN_S_MP_MUL_HIGH_DIGS_C
+#define BN_S_MP_SQR_C
+#define BN_S_MP_SUB_C
+#define BNCORE_C
+#endif
+
+#if defined(BN_ERROR_C)
+ #define BN_MP_ERROR_TO_STRING_C
+#endif
+
+#if defined(BN_FAST_MP_INVMOD_C)
+ #define BN_MP_ISEVEN_C
+ #define BN_MP_INIT_MULTI_C
+ #define BN_MP_COPY_C
+ #define BN_MP_MOD_C
+ #define BN_MP_SET_C
+ #define BN_MP_DIV_2_C
+ #define BN_MP_ISODD_C
+ #define BN_MP_SUB_C
+ #define BN_MP_CMP_C
+ #define BN_MP_ISZERO_C
+ #define BN_MP_CMP_D_C
+ #define BN_MP_ADD_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_FAST_MP_MONTGOMERY_REDUCE_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_RSHD_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_FAST_S_MP_MUL_DIGS_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_FAST_S_MP_SQR_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_2EXPT_C)
+ #define BN_MP_ZERO_C
+ #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_ABS_C)
+ #define BN_MP_COPY_C
+#endif
+
+#if defined(BN_MP_ADD_C)
+ #define BN_S_MP_ADD_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_ADD_D_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_SUB_D_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_ADDMOD_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_ADD_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_AND_C)
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_CLAMP_C)
+#endif
+
+#if defined(BN_MP_CLEAR_C)
+#endif
+
+#if defined(BN_MP_CLEAR_MULTI_C)
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_CMP_C)
+ #define BN_MP_CMP_MAG_C
+#endif
+
+#if defined(BN_MP_CMP_D_C)
+#endif
+
+#if defined(BN_MP_CMP_MAG_C)
+#endif
+
+#if defined(BN_MP_CNT_LSB_C)
+ #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_COPY_C)
+ #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_COUNT_BITS_C)
+#endif
+
+#if defined(BN_MP_DIV_C)
+ #define BN_MP_ISZERO_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_MP_COPY_C
+ #define BN_MP_ZERO_C
+ #define BN_MP_INIT_MULTI_C
+ #define BN_MP_SET_C
+ #define BN_MP_COUNT_BITS_C
+ #define BN_MP_ABS_C
+ #define BN_MP_MUL_2D_C
+ #define BN_MP_CMP_C
+ #define BN_MP_SUB_C
+ #define BN_MP_ADD_C
+ #define BN_MP_DIV_2D_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_MULTI_C
+ #define BN_MP_INIT_SIZE_C
+ #define BN_MP_INIT_C
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_LSHD_C
+ #define BN_MP_RSHD_C
+ #define BN_MP_MUL_D_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DIV_2_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_DIV_2D_C)
+ #define BN_MP_COPY_C
+ #define BN_MP_ZERO_C
+ #define BN_MP_INIT_C
+ #define BN_MP_MOD_2D_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_RSHD_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_DIV_3_C)
+ #define BN_MP_INIT_SIZE_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DIV_D_C)
+ #define BN_MP_ISZERO_C
+ #define BN_MP_COPY_C
+ #define BN_MP_DIV_2D_C
+ #define BN_MP_DIV_3_C
+ #define BN_MP_INIT_SIZE_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DR_IS_MODULUS_C)
+#endif
+
+#if defined(BN_MP_DR_REDUCE_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_DR_SETUP_C)
+#endif
+
+#if defined(BN_MP_EXCH_C)
+#endif
+
+#if defined(BN_MP_EXPT_D_C)
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_SET_C
+ #define BN_MP_SQR_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_MUL_C
+#endif
+
+#if defined(BN_MP_EXPTMOD_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_INVMOD_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_ABS_C
+ #define BN_MP_CLEAR_MULTI_C
+ #define BN_MP_REDUCE_IS_2K_L_C
+ #define BN_S_MP_EXPTMOD_C
+ #define BN_MP_DR_IS_MODULUS_C
+ #define BN_MP_REDUCE_IS_2K_C
+ #define BN_MP_ISODD_C
+ #define BN_MP_EXPTMOD_FAST_C
+#endif
+
+#if defined(BN_MP_EXPTMOD_FAST_C)
+ #define BN_MP_COUNT_BITS_C
+ #define BN_MP_INIT_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_MONTGOMERY_SETUP_C
+ #define BN_FAST_MP_MONTGOMERY_REDUCE_C
+ #define BN_MP_MONTGOMERY_REDUCE_C
+ #define BN_MP_DR_SETUP_C
+ #define BN_MP_DR_REDUCE_C
+ #define BN_MP_REDUCE_2K_SETUP_C
+ #define BN_MP_REDUCE_2K_C
+ #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+ #define BN_MP_MULMOD_C
+ #define BN_MP_SET_C
+ #define BN_MP_MOD_C
+ #define BN_MP_COPY_C
+ #define BN_MP_SQR_C
+ #define BN_MP_MUL_C
+ #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_EXTEUCLID_C)
+ #define BN_MP_INIT_MULTI_C
+ #define BN_MP_SET_C
+ #define BN_MP_COPY_C
+ #define BN_MP_ISZERO_C
+ #define BN_MP_DIV_C
+ #define BN_MP_MUL_C
+ #define BN_MP_SUB_C
+ #define BN_MP_NEG_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_FREAD_C)
+ #define BN_MP_ZERO_C
+ #define BN_MP_S_RMAP_C
+ #define BN_MP_MUL_D_C
+ #define BN_MP_ADD_D_C
+ #define BN_MP_CMP_D_C
+#endif
+
+#if defined(BN_MP_FWRITE_C)
+ #define BN_MP_RADIX_SIZE_C
+ #define BN_MP_TORADIX_C
+#endif
+
+#if defined(BN_MP_GCD_C)
+ #define BN_MP_ISZERO_C
+ #define BN_MP_ABS_C
+ #define BN_MP_ZERO_C
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_CNT_LSB_C
+ #define BN_MP_DIV_2D_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_MP_EXCH_C
+ #define BN_S_MP_SUB_C
+ #define BN_MP_MUL_2D_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_GET_INT_C)
+#endif
+
+#if defined(BN_MP_GROW_C)
+#endif
+
+#if defined(BN_MP_INIT_C)
+#endif
+
+#if defined(BN_MP_INIT_COPY_C)
+ #define BN_MP_COPY_C
+#endif
+
+#if defined(BN_MP_INIT_MULTI_C)
+ #define BN_MP_ERR_C
+ #define BN_MP_INIT_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_INIT_SET_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_SET_C
+#endif
+
+#if defined(BN_MP_INIT_SET_INT_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_SET_INT_C
+#endif
+
+#if defined(BN_MP_INIT_SIZE_C)
+ #define BN_MP_INIT_C
+#endif
+
+#if defined(BN_MP_INVMOD_C)
+ #define BN_MP_ISZERO_C
+ #define BN_MP_ISODD_C
+ #define BN_FAST_MP_INVMOD_C
+ #define BN_MP_INVMOD_SLOW_C
+#endif
+
+#if defined(BN_MP_INVMOD_SLOW_C)
+ #define BN_MP_ISZERO_C
+ #define BN_MP_INIT_MULTI_C
+ #define BN_MP_MOD_C
+ #define BN_MP_COPY_C
+ #define BN_MP_ISEVEN_C
+ #define BN_MP_SET_C
+ #define BN_MP_DIV_2_C
+ #define BN_MP_ISODD_C
+ #define BN_MP_ADD_C
+ #define BN_MP_SUB_C
+ #define BN_MP_CMP_C
+ #define BN_MP_CMP_D_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_IS_SQUARE_C)
+ #define BN_MP_MOD_D_C
+ #define BN_MP_INIT_SET_INT_C
+ #define BN_MP_MOD_C
+ #define BN_MP_GET_INT_C
+ #define BN_MP_SQRT_C
+ #define BN_MP_SQR_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_JACOBI_C)
+ #define BN_MP_CMP_D_C
+ #define BN_MP_ISZERO_C
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_CNT_LSB_C
+ #define BN_MP_DIV_2D_C
+ #define BN_MP_MOD_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_KARATSUBA_MUL_C)
+ #define BN_MP_MUL_C
+ #define BN_MP_INIT_SIZE_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_SUB_C
+ #define BN_MP_ADD_C
+ #define BN_MP_LSHD_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_KARATSUBA_SQR_C)
+ #define BN_MP_INIT_SIZE_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_SQR_C
+ #define BN_MP_SUB_C
+ #define BN_S_MP_ADD_C
+ #define BN_MP_LSHD_C
+ #define BN_MP_ADD_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_LCM_C)
+ #define BN_MP_INIT_MULTI_C
+ #define BN_MP_GCD_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_MP_DIV_C
+ #define BN_MP_MUL_C
+ #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_LSHD_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_RSHD_C
+#endif
+
+#if defined(BN_MP_MOD_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_DIV_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_ADD_C
+ #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_MOD_2D_C)
+ #define BN_MP_ZERO_C
+ #define BN_MP_COPY_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MOD_D_C)
+ #define BN_MP_DIV_D_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_CALC_NORMALIZATION_C)
+ #define BN_MP_COUNT_BITS_C
+ #define BN_MP_2EXPT_C
+ #define BN_MP_SET_C
+ #define BN_MP_MUL_2_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_REDUCE_C)
+ #define BN_FAST_MP_MONTGOMERY_REDUCE_C
+ #define BN_MP_GROW_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_RSHD_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_SETUP_C)
+#endif
+
+#if defined(BN_MP_MUL_C)
+ #define BN_MP_TOOM_MUL_C
+ #define BN_MP_KARATSUBA_MUL_C
+ #define BN_FAST_S_MP_MUL_DIGS_C
+ #define BN_S_MP_MUL_C
+ #define BN_S_MP_MUL_DIGS_C
+#endif
+
+#if defined(BN_MP_MUL_2_C)
+ #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_MUL_2D_C)
+ #define BN_MP_COPY_C
+ #define BN_MP_GROW_C
+ #define BN_MP_LSHD_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MUL_D_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MULMOD_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_MUL_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_N_ROOT_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_SET_C
+ #define BN_MP_COPY_C
+ #define BN_MP_EXPT_D_C
+ #define BN_MP_MUL_C
+ #define BN_MP_SUB_C
+ #define BN_MP_MUL_D_C
+ #define BN_MP_DIV_C
+ #define BN_MP_CMP_C
+ #define BN_MP_SUB_D_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_NEG_C)
+ #define BN_MP_COPY_C
+ #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_OR_C)
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_FERMAT_C)
+ #define BN_MP_CMP_D_C
+ #define BN_MP_INIT_C
+ #define BN_MP_EXPTMOD_C
+ #define BN_MP_CMP_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_IS_DIVISIBLE_C)
+ #define BN_MP_MOD_D_C
+#endif
+
+#if defined(BN_MP_PRIME_IS_PRIME_C)
+ #define BN_MP_CMP_D_C
+ #define BN_MP_PRIME_IS_DIVISIBLE_C
+ #define BN_MP_INIT_C
+ #define BN_MP_SET_C
+ #define BN_MP_PRIME_MILLER_RABIN_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_MILLER_RABIN_C)
+ #define BN_MP_CMP_D_C
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_SUB_D_C
+ #define BN_MP_CNT_LSB_C
+ #define BN_MP_DIV_2D_C
+ #define BN_MP_EXPTMOD_C
+ #define BN_MP_CMP_C
+ #define BN_MP_SQRMOD_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_NEXT_PRIME_C)
+ #define BN_MP_CMP_D_C
+ #define BN_MP_SET_C
+ #define BN_MP_SUB_D_C
+ #define BN_MP_ISEVEN_C
+ #define BN_MP_MOD_D_C
+ #define BN_MP_INIT_C
+ #define BN_MP_ADD_D_C
+ #define BN_MP_PRIME_MILLER_RABIN_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_RABIN_MILLER_TRIALS_C)
+#endif
+
+#if defined(BN_MP_PRIME_RANDOM_EX_C)
+ #define BN_MP_READ_UNSIGNED_BIN_C
+ #define BN_MP_PRIME_IS_PRIME_C
+ #define BN_MP_SUB_D_C
+ #define BN_MP_DIV_2_C
+ #define BN_MP_MUL_2_C
+ #define BN_MP_ADD_D_C
+#endif
+
+#if defined(BN_MP_RADIX_SIZE_C)
+ #define BN_MP_COUNT_BITS_C
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_ISZERO_C
+ #define BN_MP_DIV_D_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_RADIX_SMAP_C)
+ #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_RAND_C)
+ #define BN_MP_ZERO_C
+ #define BN_MP_ADD_D_C
+ #define BN_MP_LSHD_C
+#endif
+
+#if defined(BN_MP_READ_RADIX_C)
+ #define BN_MP_ZERO_C
+ #define BN_MP_S_RMAP_C
+ #define BN_MP_RADIX_SMAP_C
+ #define BN_MP_MUL_D_C
+ #define BN_MP_ADD_D_C
+ #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_READ_SIGNED_BIN_C)
+ #define BN_MP_READ_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_READ_UNSIGNED_BIN_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_ZERO_C
+ #define BN_MP_MUL_2D_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_REDUCE_C)
+ #define BN_MP_REDUCE_SETUP_C
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_RSHD_C
+ #define BN_MP_MUL_C
+ #define BN_S_MP_MUL_HIGH_DIGS_C
+ #define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+ #define BN_MP_MOD_2D_C
+ #define BN_S_MP_MUL_DIGS_C
+ #define BN_MP_SUB_C
+ #define BN_MP_CMP_D_C
+ #define BN_MP_SET_C
+ #define BN_MP_LSHD_C
+ #define BN_MP_ADD_C
+ #define BN_MP_CMP_C
+ #define BN_S_MP_SUB_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_COUNT_BITS_C
+ #define BN_MP_DIV_2D_C
+ #define BN_MP_MUL_D_C
+ #define BN_S_MP_ADD_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_S_MP_SUB_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_L_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_COUNT_BITS_C
+ #define BN_MP_DIV_2D_C
+ #define BN_MP_MUL_C
+ #define BN_S_MP_ADD_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_S_MP_SUB_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_SETUP_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_COUNT_BITS_C
+ #define BN_MP_2EXPT_C
+ #define BN_MP_CLEAR_C
+ #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_SETUP_L_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_2EXPT_C
+ #define BN_MP_COUNT_BITS_C
+ #define BN_S_MP_SUB_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_IS_2K_C)
+ #define BN_MP_REDUCE_2K_C
+ #define BN_MP_COUNT_BITS_C
+#endif
+
+#if defined(BN_MP_REDUCE_IS_2K_L_C)
+#endif
+
+#if defined(BN_MP_REDUCE_SETUP_C)
+ #define BN_MP_2EXPT_C
+ #define BN_MP_DIV_C
+#endif
+
+#if defined(BN_MP_RSHD_C)
+ #define BN_MP_ZERO_C
+#endif
+
+#if defined(BN_MP_SET_C)
+ #define BN_MP_ZERO_C
+#endif
+
+#if defined(BN_MP_SET_INT_C)
+ #define BN_MP_ZERO_C
+ #define BN_MP_MUL_2D_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_SHRINK_C)
+#endif
+
+#if defined(BN_MP_SIGNED_BIN_SIZE_C)
+ #define BN_MP_UNSIGNED_BIN_SIZE_C
+#endif
+
+#if defined(BN_MP_SQR_C)
+ #define BN_MP_TOOM_SQR_C
+ #define BN_MP_KARATSUBA_SQR_C
+ #define BN_FAST_S_MP_SQR_C
+ #define BN_S_MP_SQR_C
+#endif
+
+#if defined(BN_MP_SQRMOD_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_SQR_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_SQRT_C)
+ #define BN_MP_N_ROOT_C
+ #define BN_MP_ISZERO_C
+ #define BN_MP_ZERO_C
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_RSHD_C
+ #define BN_MP_DIV_C
+ #define BN_MP_ADD_C
+ #define BN_MP_DIV_2_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_SUB_C)
+ #define BN_S_MP_ADD_C
+ #define BN_MP_CMP_MAG_C
+ #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_SUB_D_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_ADD_D_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_SUBMOD_C)
+ #define BN_MP_INIT_C
+ #define BN_MP_SUB_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_TO_SIGNED_BIN_C)
+ #define BN_MP_TO_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_TO_SIGNED_BIN_N_C)
+ #define BN_MP_SIGNED_BIN_SIZE_C
+ #define BN_MP_TO_SIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_TO_UNSIGNED_BIN_C)
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_ISZERO_C
+ #define BN_MP_DIV_2D_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_TO_UNSIGNED_BIN_N_C)
+ #define BN_MP_UNSIGNED_BIN_SIZE_C
+ #define BN_MP_TO_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_TOOM_MUL_C)
+ #define BN_MP_INIT_MULTI_C
+ #define BN_MP_MOD_2D_C
+ #define BN_MP_COPY_C
+ #define BN_MP_RSHD_C
+ #define BN_MP_MUL_C
+ #define BN_MP_MUL_2_C
+ #define BN_MP_ADD_C
+ #define BN_MP_SUB_C
+ #define BN_MP_DIV_2_C
+ #define BN_MP_MUL_2D_C
+ #define BN_MP_MUL_D_C
+ #define BN_MP_DIV_3_C
+ #define BN_MP_LSHD_C
+ #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_TOOM_SQR_C)
+ #define BN_MP_INIT_MULTI_C
+ #define BN_MP_MOD_2D_C
+ #define BN_MP_COPY_C
+ #define BN_MP_RSHD_C
+ #define BN_MP_SQR_C
+ #define BN_MP_MUL_2_C
+ #define BN_MP_ADD_C
+ #define BN_MP_SUB_C
+ #define BN_MP_DIV_2_C
+ #define BN_MP_MUL_2D_C
+ #define BN_MP_MUL_D_C
+ #define BN_MP_DIV_3_C
+ #define BN_MP_LSHD_C
+ #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_TORADIX_C)
+ #define BN_MP_ISZERO_C
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_DIV_D_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_TORADIX_N_C)
+ #define BN_MP_ISZERO_C
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_DIV_D_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_UNSIGNED_BIN_SIZE_C)
+ #define BN_MP_COUNT_BITS_C
+#endif
+
+#if defined(BN_MP_XOR_C)
+ #define BN_MP_INIT_COPY_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_ZERO_C)
+#endif
+
+#if defined(BN_PRIME_TAB_C)
+#endif
+
+#if defined(BN_REVERSE_C)
+#endif
+
+#if defined(BN_S_MP_ADD_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_S_MP_EXPTMOD_C)
+ #define BN_MP_COUNT_BITS_C
+ #define BN_MP_INIT_C
+ #define BN_MP_CLEAR_C
+ #define BN_MP_REDUCE_SETUP_C
+ #define BN_MP_REDUCE_C
+ #define BN_MP_REDUCE_2K_SETUP_L_C
+ #define BN_MP_REDUCE_2K_L_C
+ #define BN_MP_MOD_C
+ #define BN_MP_COPY_C
+ #define BN_MP_SQR_C
+ #define BN_MP_MUL_C
+ #define BN_MP_SET_C
+ #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_S_MP_MUL_DIGS_C)
+ #define BN_FAST_S_MP_MUL_DIGS_C
+ #define BN_MP_INIT_SIZE_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_MUL_HIGH_DIGS_C)
+ #define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+ #define BN_MP_INIT_SIZE_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_SQR_C)
+ #define BN_MP_INIT_SIZE_C
+ #define BN_MP_CLAMP_C
+ #define BN_MP_EXCH_C
+ #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_SUB_C)
+ #define BN_MP_GROW_C
+ #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BNCORE_C)
+#endif
+
+#ifdef LTM3
+#define LTM_LAST
+#endif
+#include <tommath_superclass.h>
+#include <tommath_class.h>
+#else
+#define LTM_LAST
+#endif
diff --git a/libtommath/tommath_superclass.h b/libtommath/tommath_superclass.h
new file mode 100644
index 0000000..e3926df
--- /dev/null
+++ b/libtommath/tommath_superclass.h
@@ -0,0 +1,72 @@
+/* super class file for PK algos */
+
+/* default ... include all MPI */
+#define LTM_ALL
+
+/* RSA only (does not support DH/DSA/ECC) */
+/* #define SC_RSA_1 */
+
+/* For reference.... On an Athlon64 optimizing for speed...
+
+ LTM's mpi.o with all functions [striped] is 142KiB in size.
+
+*/
+
+/* Works for RSA only, mpi.o is 68KiB */
+#ifdef SC_RSA_1
+ #define BN_MP_SHRINK_C
+ #define BN_MP_LCM_C
+ #define BN_MP_PRIME_RANDOM_EX_C
+ #define BN_MP_INVMOD_C
+ #define BN_MP_GCD_C
+ #define BN_MP_MOD_C
+ #define BN_MP_MULMOD_C
+ #define BN_MP_ADDMOD_C
+ #define BN_MP_EXPTMOD_C
+ #define BN_MP_SET_INT_C
+ #define BN_MP_INIT_MULTI_C
+ #define BN_MP_CLEAR_MULTI_C
+ #define BN_MP_UNSIGNED_BIN_SIZE_C
+ #define BN_MP_TO_UNSIGNED_BIN_C
+ #define BN_MP_MOD_D_C
+ #define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+ #define BN_REVERSE_C
+ #define BN_PRIME_TAB_C
+
+ /* other modifiers */
+ #define BN_MP_DIV_SMALL /* Slower division, not critical */
+
+ /* here we are on the last pass so we turn things off. The functions classes are still there
+ * but we remove them specifically from the build. This also invokes tweaks in functions
+ * like removing support for even moduli, etc...
+ */
+#ifdef LTM_LAST
+ #undef BN_MP_TOOM_MUL_C
+ #undef BN_MP_TOOM_SQR_C
+ #undef BN_MP_KARATSUBA_MUL_C
+ #undef BN_MP_KARATSUBA_SQR_C
+ #undef BN_MP_REDUCE_C
+ #undef BN_MP_REDUCE_SETUP_C
+ #undef BN_MP_DR_IS_MODULUS_C
+ #undef BN_MP_DR_SETUP_C
+ #undef BN_MP_DR_REDUCE_C
+ #undef BN_MP_REDUCE_IS_2K_C
+ #undef BN_MP_REDUCE_2K_SETUP_C
+ #undef BN_MP_REDUCE_2K_C
+ #undef BN_S_MP_EXPTMOD_C
+ #undef BN_MP_DIV_3_C
+ #undef BN_S_MP_MUL_HIGH_DIGS_C
+ #undef BN_FAST_S_MP_MUL_HIGH_DIGS_C
+ #undef BN_FAST_MP_INVMOD_C
+
+ /* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold
+ * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines]
+ * which means roughly speaking you can handle upto 2536-bit RSA keys with these defined without
+ * trouble.
+ */
+ #undef BN_S_MP_MUL_DIGS_C
+ #undef BN_S_MP_SQR_C
+ #undef BN_MP_MONTGOMERY_REDUCE_C
+#endif
+
+#endif
diff --git a/license.terms b/license.terms
index f1dcaa5..d44f069 100644
--- a/license.terms
+++ b/license.terms
@@ -34,7 +34,7 @@ Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
are acquiring the software on behalf of the Department of Defense, the
software shall be classified as "Commercial Computer Software" and the
Government shall have only "Restricted Rights" as defined in Clause
-252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
+252.227-7013 (b) (3) of DFARs. Notwithstanding the foregoing, the
authors grant the U.S. Government and others acting in its behalf
permission to use and distribute the software in accordance with the
terms specified in this license.
diff --git a/mac/AppleScript.html b/mac/AppleScript.html
deleted file mode 100644
index 32b2e9f..0000000
--- a/mac/AppleScript.html
+++ /dev/null
@@ -1,312 +0,0 @@
-<HTML>
-
-<HEAD>
-
-<TITLE>tclOSAScript -- OSA</TITLE>
-
-</HEAD>
-
-<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#FF0000" ALINK="#00FF00">
-
-<H2 ALIGN="CENTER">TclAppleScript Extension Command</H2>
-
-<H3>NAME</H3>
-<DL>
-<DT>
-AppleScript - Communicate with the AppleScript OSA component to run
- AppleScripts from Tcl.
-</DL>
-<H3>SYNOPSIS</H3>
-<DL><DT>
-<B>AppleScript <A NAME="compile">compile</A> </B><I>?-flag value?</I> <I>scriptData1
- ?ScriptData2 ...?</I><I>componentName</I>
-<BR>
-<B>AppleScript <A NAME="decompile">decompile</A></B> <I>scriptName</I>
-<BR>
-<B>AppleScript <A NAME="delete">delete</A> </B><I>what scriptName</I>
-<BR>
-<B>AppleScript <A NAME="execute">execute</A> </B><I>?flags value?</I> <I>scriptData1
- ?scriptData2 ...?</I>
-<BR>
-<B>AppleScript <A NAME="info">info</A> </B><I>what</I>
-<BR>
-<B>AppleScript <A NAME="load">load</A></B> <I>?flag value? fileName</I>
-<BR>
-<B>AppleScript <A NAME="run">run</A></B> <I>?flag value?</I>
- <I>scriptName</I>
-<BR>
-<B>AppleScript <A NAME="store">store</A></B> <I>?flag value? scriptName fileName</I>
-<BR>
-</DL>
-
-<H3>DESCRIPTION</H3>
-<DL>
-<DT>
-
-
-This command is used to communicate with the AppleScript OSA component.
-You can <A HREF="#compile"><B>compile</B></A> scripts, <A
-HREF="#run"><B>run</B></A> compiled scripts, <A
-HREF="#execute"><B>execute</B></A> script data (i.e. compile and run at a
-blow). You can get script data from a compiled script (<A
-HREF="#decompile"><B>decompile</B></A> it), and you can <A
-HREF="#load"><B>load</B></A> a compiled script from the scpt resource of a
-file, or <A HREF="store"><B>store</B></A> one to a scpt resource. You can
-also get <A HREF="#info"><B>info</B></A> on the currently available scripts
-and contexts. It has the general form
-
-<DL>
-<DT>
-<P>
-<I>AppleScript option ?arg arg ...?</I>
-<P>
-</DL>
-The possible sub-commands are:
-<P>
-<DL>
- <DT>
- <I>AppleScript</I> <A NAME="compile"><B>compile</A> </B><I>?-flag value?</I> <I>scriptData1
- ?ScriptData2 ...?</I>
- <BR>
-
- <DD>
- The scriptData
- elements are concatenated (with a space between each), and
- sent to AppleScript
- for compilation. There is no limitation on the size of
- the scriptData, beyond the available memory of the Wish interpreter.
- <P>
- If the compilation is successful, then the command will return a token
- that you can pass to the <A HREF="#run">"run"</A> subcommand. If the
- compilation fails, then the return value will be the error message from
- AppleScript, and the pertinent line of code, with an "_" to indicate
- the place where it thinks the error occured.
- <P>
- The
- compilation is controlled by flag value pairs. The available flags
- are:
- <P>
- <DL>
- <DT>
- <A NAME="first compile switch"><B>-augment Boolean</B></A>
- <DD>
- To be used in concert with the <A HREF="#-context">-context</A> flag.
- If augment is yes,
- then the scriptData augments the handlers and data already in the
- script context. If augment is no, then the scriptData replaces the
- data and handlers already in the context. The default is yes.
- <P>
- <!-- I'm leaving this flag out for now, since I can't seem to get the
- AE manager to obey it. Even when I hard code the value, applications
- still switch to the foreground. Oh, well...
-
- <DT>
- <B>-canswitch Boolean </B>
- <DD>
- If yes, then applications activated by the code in scriptData will
- be allowed to switch to the foreground. If no, then they will use
- the notification manager to indicate they need attention (this
- usually means they blink the Finder icon, and put a check in the
- application's entry in the Finder menu).
- -->
-
- <DT>
- <B><A NAME="-context">-context</A> Boolean</B>
- <DD>
- This flag causes the code given in the scriptData to be compiled
- into a "context". In AppleScript, this is the equivalent of creating an Tcl
- Namespace. The command in this case returns the name of the context as
- the its result, rather than a compiled script name.
- <P>
- You can store data and procedures (aka
- handlers) in a script context. Then later, you can
- run other scripts in this context, and they will see all the data and
- handlers that were set up with this command. You do this by passing the
- name of this context to the -context flag of the run or execute subcommands.
- <P>
- Unlike the straight compile command, the code compiled into a
- script context is run immediatly, when it is compiled, to set up the context.
- <DT>
- <P>
- <B>-name string</B>
- <DD>
- Use <I>string</I> as the name of the script or script context. If there is
- already a script
- of this name, it will be discarded. The same is true with script
- contexts, unless the <I>-augment</I> flag is true. If no name is provided, then a
- unique name will be created for you.
- <DT>
- <P>
- <B>-parent contextName </B>
- <DD>
- This flag is also to be used in conjunction with the <A HREF="#-context">-context</A> flag.
- <I>contextName</I> must be the name of a compiled script context. Then
- the new script context will inherit the data and handlers from the
- parent context.
- </DL>
- <P>
- <DT>
- <I>AppleScript</I> <B><A NAME="decompile">decompile</A></B> <I>scriptName</I>
- <BR>
- <DD>
- This decompiles the script data compiled into the script scriptName,
- and returns the source code.
- <P>
- <DT>
- <I>AppleScript</I> <B><A NAME="delete">delete</A> </B><I>what scriptName</I>
- <BR>
- <DD>
- This deletes contexts or script data. The allowed values for "what" are:
- <P>
- <DL>
- <DT>
- <P>
- <B>context</B>
- <DD>
- This deletes the context scriptName,
- and frees up all the resources associated with it.
- <DT>
- <P>
- <B>script</B>
- <DD>
- This deletes the script data compiled into the script scriptName,
- and frees up all the resources associated with it.
- </DL>
- <P>
- <DT>
- <I>AppleScript</I> <B><A NAME="execute">execute</A> </B><I>?flags value?</I> <I>scriptData1
- ?scriptData2 ...?</I>
- <BR>
- <DD>
- This compiles and runs the script in scriptData (concatenating first), and
- returns the results of the script execution. It is the same as doing
- <I>compile</I> and then <I>run</I>, except that the compiled script is
- immediately discarded.
- <P>
- <DT>
- <I>AppleScript</I> <B><A NAME="info">info</A> </B><I>what</I>
- <DD>
- This gives info on the connection. The allowed values for "what" are:
- <P>
- <DL>
- <DT>
- <P>
- <B>contexts </B> <I>?pattern?</I>
- <DD>
- This gives the list of the script contexts that have been.
- If <I>pattern</I> is given, it only reports the contexts
- that match this pattern.
- <DT>
- <!-- <P>
- <B>language</B>
- <DD>
- Returns the language of this OSA component
- <DT>
- -->
- <P>
- <B>scripts</B> <I>?pattern?</I>
- <DD>
- This returns a list of the scripts that have been compiled in the
- current connection. If <I>pattern</I> is given, it only reports the
- script names that match this pattern.
- </DL>
- <P>
- <DT>
- <I>AppleScript</I> <B><A NAME="load">load</A></B> <I>?flag value? fileName</I>
- <DD>
- This loads compiled script data from a resource of type 'scpt' in the
- file fileName, and returns a token for the script data. As with the
- <I>compile</I> command, the script is not actually executed. Note that all
- scripts compiled with Apple's "Script Editor" are stored as script
- contexts. However, unlike with the "<I>compile -context</I>" command, the <I>load</I>
- command does not run these scripts automatically. If you want to set up
- the handlers contained in the loaded script, you must run it manually.
- <P>
- <I>load</I> takes the following flags:
- <P>
- <DL>
- <DT>
- <B>-rsrcname string</B>
- <DD>
- load a named resource of type 'scpt' using the rsrcname
- flag.
- <DT>
- <P>
- <B>-rsrcid integer</B>
- <DD>
- load a resource by number with the rsrcid flag.
- </DL>
- <DD>
- <P>
- If neither the <I>rsrcname</I> nor the <I>rsrcid</I> flag is provided, then the load
- command defaults to -rsrcid = 128. This is the resource in which
- Apple's Script Editor puts the script data when it writes out a
- compiled script.
- <P>
- <DT>
- <I>AppleScript</I> <B><A NAME="run">run</A></B> <I>?flag value?</I> <I>scriptName</I>
- <DD>
- This runs the script which was previously compiled into <I>scriptName</I>. If the script
- runs successfully, the command returns the return value for this command,
- coerced to a text string.
- If there is an error in
- the script execution, then it returns the error result from the
- scripting component. It accepts the following flag:
-
- <DL>
- <DT>
- <P>
- <B>-context contextName</B>
- <DD>
- <I>contextName</I> must be a context created by a previous call to <I>compile</I> with
- the -<I>context</I> flag set. This flag causes the code given in the
- <I>scriptData</I> to be run in this "context". It will see all the data and
- handlers that were set up previously.
- <!-- <DT>
- <B>-canswitch Boolean </B>
- <DD>
- If yes, then applications activated by the code
- in scriptData will be allowed to switch to the foreground. If no, then
- they will use the notification manager to indicate they need attention
- (this usually means they blink the Finder icon, and put a check in the
- application's entry in the Finder menu). -->
- </DL>
- <P>
- <DT>
- <I>AppleScript </I> <B> <A NAME="store">store</A></B> <I>?flag value? scriptName fileName</I>
- <DD>
- This stores a compiled script or script context into a resource of type 'scpt' in the
- file fileName.
- <P>
- store takes the following flags:
- <P>
- <DL>
- <DT>
- <B>-rsrcname string</B>
- <DD>
- store to a named resource of type 'scpt' using the rsrcname
- flag.
- <DT>
- <P>
- <B>-rsrcid integer</B>
- <DD>
- store to a numbered resource with the rsrcid flag.
- </DL>
- <P>
- <DD>
- If neither the rsrcname nor the rsrcid flag is provided, then the load
- command defaults to -rsrcid = 128. Apple's Script Editor can read in files written by
- tclOSAScript with this setting of the <I>-rsrcid</I> flag.
-</DL>
-</DL>
-<H2>Notes:</H2>
-
-The AppleScript command is a stopgap command to fill the place of exec
- on the Mac. It is not a supported command, and will likely change
- as we broaden it to allow communication with other OSA languages.
-<H2>See Also:</H2>
-
-
-</BODY>
-
-</HTML>
diff --git a/mac/Background.doc b/mac/Background.doc
deleted file mode 100644
index 8fe4a27..0000000
--- a/mac/Background.doc
+++ /dev/null
@@ -1,90 +0,0 @@
-Notes about the Background Only application template
-====================================================
-
-We have included sample code and project files for making a Background-Only
- application (BOA) in Tcl. This could be used for server processes (like the
-Tcl Web-Server).
-
-Files:
-------
-
-* BOA_TclShells.¼ - This is the project file.
-* tclMacBOAAppInit.c - This is the AppInit file for the BOA App.
-* tclMacBOAMain - This is a replacement for the Tcl_Main for BOA's.
-
-Caveat:
--------
-
-This is an unsupported addition to MacTcl. The main feature that will certainly
-change is how we handle AppleEvents. Currently, all the AppleEvent handling is
-done on the Tk side, which is not really right. Also, there is no way to
-register your own AppleEvent handlers, which is obviously something that would be
-useful in a BOA App. We will address these issues in Tcl8.1. If you need to
-register your own AppleEvent Handlers in the meantime, be aware that your code
-will probably break in Tcl8.1.
-
-I will also improve the basic code here based on feedback that I recieve. This
-is to be considered a first cut only at writing a BOA in Tcl.
-
-Introduction:
--------------
-
-This project makes a double-clickable BOA application. It obviously needs
-some Tcl code to get it started. It will look for this code first in a
-'TEXT' resource in the application shell whose name is "bgScript.tcl". If
-it does not find any such resource, it will look for a file called
-bgScript.tcl in the application's folder. Otherwise it will quit with an
-error.
-
-It creates three files in the application folder to store stdin, stdout &
-stderr. They are imaginatively called temp.in, temp.out & temp.err. They
-will be opened append, so you do not need to erase them after each use of
-the BOA.
-
-The app does understand the "quit", and the "doScript" AppleEvents, so you can
-kill it with the former, and instruct it with the latter. It also has an
-aete, so you can target it with Apple's "Script Editor".
-
-For more information on Macintosh BOA's, see the Apple TechNote: 1070.
-
-Notifications:
---------------
-
-BOA's are not supposed to have direct contact with the outside world. They
-are, however, allowed to go through the Notification Manager to post
-alerts. To this end, I have added a Tcl command called "bgnotify" to the
-shell, that simply posts a notification through the notification manager.
-
-To use it, say:
-
-bgnotify "Hi, there little buddy"
-
-It will make the system beep, and pop up an annoying message box with the
-text of the first argument to the command. While the message is up, Tcl
-is yielding processor time, but not processing any events.
-
-Errors:
--------
-
-Usually a Tcl background application will have some startup code, opening
-up a server socket, or whatever, and at the end of this, will use the
-vwait command to kick off the event loop. If an error occurs in the
-startup code, it will kill the application, and a notification of the error
-will be posted through the Notification Manager.
-
-If an error occurs in the event handling code after the
-vwait, the error message will be written to the file temp.err. However,
-if you would like to have these errors post a notification as well, just
-define a proc called bgerror that takes one argument, the error message,
-and passes that off to "bgnotify", thusly:
-
-proc bgerror {mssg} {
- bgnotify "A background error has occured\n $mssg"
-}
-
-Support:
---------
-
-If you have any questions, contact me at:
-
-jim.ingham@eng.sun.com
diff --git a/mac/MW_TclAppleScriptHeader.h b/mac/MW_TclAppleScriptHeader.h
deleted file mode 100755
index 6ce3853..0000000
--- a/mac/MW_TclAppleScriptHeader.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#if __POWERPC__
-#include "MW_TclAppleScriptHeaderPPC"
-#elif __CFM68K__
-#include "MW_TclAppleScriptHeaderCFM68K"
-#else
-#include "MW_TclAppleScriptHeader68K"
-#endif
diff --git a/mac/MW_TclAppleScriptHeader.pch b/mac/MW_TclAppleScriptHeader.pch
deleted file mode 100644
index 2f13605..0000000
--- a/mac/MW_TclAppleScriptHeader.pch
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * MW_TclAppleScriptHeader.pch --
- *
- * This file is the source for a pre-compilied header that gets used
- * for TclAppleScript. This make compilies go a bit
- * faster. This file is only intended to be used in the MetroWerks
- * CodeWarrior environment. It essentially acts as a place to set
- * compiler flags. See MetroWerks documention for more details.
- *
- * Copyright (c) 1995-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-/*
- * To use the compilied header you need to set the "Prefix file" in
- * the "C/C++ Language" preference panel to point to the created
- * compilied header. The name of the header depends on the
- * architecture we are compiling for (see the code below). For
- * example, for a 68k app the prefix file should be: MW_TclHeader68K.
- */
-
-#if __POWERPC__
-#pragma precompile_target "MW_TclAppleScriptHeaderPPC"
-#elif __CFM68K__
-#pragma precompile_target "MW_TclAppleScriptHeaderCFM68K"
-#else
-#pragma precompile_target "MW_TclAppleScriptHeader68K"
-#endif
-
-#include "tclMacCommonPch.h"
-
-#define USE_TCL_STUBS
diff --git a/mac/MW_TclBuildLibHeader.h b/mac/MW_TclBuildLibHeader.h
deleted file mode 100644
index f6a6f61..0000000
--- a/mac/MW_TclBuildLibHeader.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#if __POWERPC__
-#include "MW_TclBuildLibHeaderPPC"
-#elif __CFM68K__
-#include "MW_TclBuildLibHeaderCFM68K"
-#else
-#include "MW_TclBuildLibHeader68K"
-#endif
diff --git a/mac/MW_TclBuildLibHeader.pch b/mac/MW_TclBuildLibHeader.pch
deleted file mode 100644
index 9503153..0000000
--- a/mac/MW_TclBuildLibHeader.pch
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * MW_TclBuildLibHeader.pch --
- *
- * This file is the source for a pre-compilied header that gets used
- * for all files in the Tcl projects. This make compilies go a bit
- * faster. This file is only intended to be used in the MetroWerks
- * CodeWarrior environment. It essentially acts as a place to set
- * compiler flags. See MetroWerks documention for more details.
- *
- * Copyright (c) 1995-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-/*
- * To use the compilied header you need to set the "Prefix file" in
- * the "C/C++ Language" preference panel to point to the created
- * compilied header. The name of the header depends on the
- * architecture we are compiling for (see the code below). For
- * example, for a 68k app the prefix file should be: MW_TclHeader68K.
- */
-#if __POWERPC__
-#pragma precompile_target "MW_TclBuildLibHeaderPPC"
-#elif __CFM68K__
-#pragma precompile_target "MW_TclBuildLibHeaderCFM68K"
-#else
-#pragma precompile_target "MW_TclBuildLibHeader68K"
-#endif
-
-#define BUILD_tcl 1
-
-#include "MW_TclHeaderCommon.h"
diff --git a/mac/MW_TclHeader.h b/mac/MW_TclHeader.h
deleted file mode 100755
index 43a9029..0000000
--- a/mac/MW_TclHeader.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#if __POWERPC__
-#include "MW_TclHeaderPPC"
-#elif __CFM68K__
-#include "MW_TclHeaderCFM68K"
-#else
-#include "MW_TclHeader68K"
-#endif
diff --git a/mac/MW_TclHeader.pch b/mac/MW_TclHeader.pch
deleted file mode 100644
index 6e547d4..0000000
--- a/mac/MW_TclHeader.pch
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * MW_TclHeader.pch --
- *
- * This file is the source for a pre-compilied header that gets used
- * for all files in the Tcl projects. This make compilies go a bit
- * faster. This file is only intended to be used in the MetroWerks
- * CodeWarrior environment. It essentially acts as a place to set
- * compiler flags. See MetroWerks documention for more details.
- *
- * Copyright (c) 1995-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-/*
- * To use the compilied header you need to set the "Prefix file" in
- * the "C/C++ Language" preference panel to point to the created
- * compilied header. The name of the header depends on the
- * architecture we are compiling for (see the code below). For
- * example, for a 68k app the prefix file should be: MW_TclHeader68K.
- */
-#if __POWERPC__
-#pragma precompile_target "MW_TclHeaderPPC"
-#elif __CFM68K__
-#pragma precompile_target "MW_TclHeaderCFM68K"
-#else
-#pragma precompile_target "MW_TclHeader68K"
-#endif
-
-#include "MW_TclHeaderCommon.h"
diff --git a/mac/MW_TclHeaderCommon.h b/mac/MW_TclHeaderCommon.h
deleted file mode 100644
index 59a57d6..0000000
--- a/mac/MW_TclHeaderCommon.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * MW_TclHeaderCommon.h --
- *
- * Common includes for precompiled headers
- *
- * Copyright (c) 1998 by Scriptics Corporation.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#pragma once
-
-#include "tclMacCommonPch.h"
-
-/*
- * Place any includes below that will are needed by the majority of the
- * and is OK to be in any file in the system.
- */
-
-#include "tcl.h"
-
-#ifdef BUILD_tcl
-# undef TCL_STORAGE_CLASS
-# define TCL_STORAGE_CLASS DLLEXPORT
-#endif
-#include "tclMac.h"
-#undef TCL_STORAGE_CLASS
-#define TCL_STORAGE_CLASS DLLIMPORT
-
-#include "tclInt.h"
-
-
-#if PRAGMA_IMPORT
-#pragma import on
-#endif
-
-#include <MoreFiles.h>
-#include <MoreFilesExtras.h>
-#include <FSpCompat.h>
-#include <FileCopy.h>
-#include <FullPath.h>
-#include <IterateDirectory.h>
-#include <MoreDesktopMgr.h>
-#include <DirectoryCopy.h>
-#include <Search.h>
-
-#ifdef PRAGMA_IMPORT_OFF
-#pragma import off
-#elif PRAGMA_IMPORT
-#pragma import reset
-#endif
diff --git a/mac/MW_TclStaticHeader.h b/mac/MW_TclStaticHeader.h
deleted file mode 100644
index 0c1abc2..0000000
--- a/mac/MW_TclStaticHeader.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#if __POWERPC__
-#include "MW_TclStaticHeaderPPC"
-#elif __CFM68K__
-#include "MW_TclStaticHeaderCFM68K"
-#else
-#include "MW_TclStaticHeader68K"
-#endif
diff --git a/mac/MW_TclStaticHeader.pch b/mac/MW_TclStaticHeader.pch
deleted file mode 100644
index 06496a0..0000000
--- a/mac/MW_TclStaticHeader.pch
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * MW_TclStaticHeader.pch --
- *
- * This file is the source for a pre-compilied header that gets used
- * for all files in the Tcl projects. This make compilies go a bit
- * faster. This file is only intended to be used in the MetroWerks
- * CodeWarrior environment. It essentially acts as a place to set
- * compiler flags. See MetroWerks documention for more details.
- *
- * Copyright (c) 1995-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-/*
- * To use the compilied header you need to set the "Prefix file" in
- * the "C/C++ Language" preference panel to point to the created
- * compilied header. The name of the header depends on the
- * architecture we are compiling for (see the code below). For
- * example, for a 68k app the prefix file should be: MW_TclHeader68K.
- */
-#if __POWERPC__
-#pragma precompile_target "MW_TclStaticHeaderPPC"
-#elif __CFM68K__
-#pragma precompile_target "MW_TclStaticHeaderCFM68K"
-#else
-#pragma precompile_target "MW_TclStaticHeader68K"
-#endif
-
-#define STATIC_BUILD 1
-
-#include "MW_TclHeaderCommon.h"
diff --git a/mac/MW_TclTestHeader.h b/mac/MW_TclTestHeader.h
deleted file mode 100755
index c47bb97..0000000
--- a/mac/MW_TclTestHeader.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#if __POWERPC__
-#include "MW_TclTestHeaderPPC"
-#elif __CFM68K__
-#include "MW_TclTestHeaderCFM68K"
-#else
-#include "MW_TclTestHeader68K"
-#endif
diff --git a/mac/MW_TclTestHeader.pch b/mac/MW_TclTestHeader.pch
deleted file mode 100755
index eae2d48..0000000
--- a/mac/MW_TclTestHeader.pch
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * MW_TclTestHeader.pch --
- *
- * This file is the source for a pre-compilied header that gets used
- * for all files in the Tcl projects. This make compilies go a bit
- * faster. This file is only intended to be used in the MetroWerks
- * CodeWarrior environment. It essentially acts as a place to set
- * compiler flags. See MetroWerks documention for more details.
- *
- * Copyright (c) 1995-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-/*
- * To use the compilied header you need to set the "Prefix file" in
- * the "C/C++ Language" preference panel to point to the created
- * compilied header. The name of the header depends on the
- * architecture we are compiling for (see the code below). For
- * example, for a 68k app the prefix file should be: MW_TclHeader68K.
- */
-#if __POWERPC__
-#pragma precompile_target "MW_TclTestHeaderPPC"
-#elif __CFM68K__
-#pragma precompile_target "MW_TclTestHeaderCFM68K"
-#else
-#pragma precompile_target "MW_TclTestHeader68K"
-#endif
-
-#define BUILD_tcl 1
-
-#define STATIC_BUILD 1
-
-#define TCL_DEBUG 1
-
-#define TCL_THREADS 1
-
-#include "MW_TclHeaderCommon.h"
diff --git a/mac/README b/mac/README
deleted file mode 100644
index 7841056..0000000
--- a/mac/README
+++ /dev/null
@@ -1,79 +0,0 @@
-Tcl 8.4 for Macintosh
-
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-Note that Tcl on Mac OS Classic is no longer supported and likely no longer
-compiles, the last release known to work is 8.4.2. The 'mac' source
-directory and all other Mac Classic code have been removed from Tk 8.5.
-
-The Mac OS X port of Tcl can be found in the 'macosx' source directory.
-
-The information and URLs below are known to be outdated and incorrect.
-
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-1. Introduction
----------------
-
-This is the README file for the Macintosh version of the Tcl
-scripting language. The home page for the Mac/Tcl info is
- http://www.tcl.tk/software/mac/
-
-A summary of what's new in this release is at
- http://www.tcl.tk/software/tcltk/8.4.html
-
-A summary of Macintosh-specific features is at
- http://www.tcl.tk/software/mac/features.html
-
-2. The Distribution
--------------------
-
-Macintosh Tcl is distributed in three different forms. This should
-make it easier to only download what you need. Substitute <version>
-with the version you wish to use. The packages are as follows:
-
-mactk<version>.sea.hqx
-
- This distribution is a "binary" only release. It contains an
- installer program that will install a 68k, PowerPC, or Fat
- version of the "Tcl Shell" and "Wish" applications. In addition,
- it installs the Tcl & Tk libraries in the Extensions folder inside
- your System Folder.
-
-mactcltk-full-<version>.sea.hqx
-
- This release contains the full release of Tcl and Tk for the
- Macintosh plus the More Files packages which Macintosh Tcl and Tk
- rely on.
-
-mactcl-source-<version>.sea.hqx
-
- This release contains the complete source for Tcl. In
- addition, Metrowerks CodeWarrior libraries and project files
- are included. However, you must already have the More Files
- package to compile this code.
-
-The "html" subdirectory contains reference documentation in
-in the HTML format. You may also find these pages at:
-
- http://www.tcl.tk/man/
-
-3. Compiling Tcl
-----------------
-
-In order to compile Macintosh Tcl you must have the
-following items:
-
- CodeWarrior Pro 5+
- Mac Tcl (sources)
- More Files 1.4.9
-
-The included project files should work fine. However, for
-current release notes please check this page:
-
- http://www.tcl.tk/doc/howto/compile.html#mac
-
-If you have comments or Bug reports, please use the SourceForge
-Bug tracker to report them:
-
- http://tcl.sourceforge.net/
diff --git a/mac/bugs.doc b/mac/bugs.doc
deleted file mode 100644
index fe4bb00..0000000
--- a/mac/bugs.doc
+++ /dev/null
@@ -1,42 +0,0 @@
-Known bug list for Tcl 8.0 for Macintosh
-
-by Ray Johnson
-Sun Microsystems Laboratories
-rjohnson@eng.sun.com
-
-This was a new feature as of Tcl7.6b1 and as such I'll started with
-a clean slate. I currently know of no reproducable bugs. I often
-get vague reports - but nothing I've been able to confirm. Let
-me know what bugs you find!
-
-The Macintosh version of Tcl passes most all tests in the Tcl
-test suite. Slower Macs may fail some tests in event.test whose
-timing constraints are too tight. If other tests fail please report
-them.
-
-Ray
-
-Known bugs in the current release.
-
-* With the socket code you can't use the "localhost" host name. This
- is actually a known bug in Apple's MacTcp stack. However, you can
- use [info hostname] whereever you would have used "localhost" to
- achive the same effect.
-
-* Most socket bugs have been fixed. We do have a couple of test cases
- that will hang the Mac, however, and we are still working on them.
- If you find additional test cases that show crashes please let us
- know!
-
-* In Tcl 8.2, the new Regexp code seems to be more deeply recursive than
-the older version in Tcl8.0. As a result, I have had to increase the Stack
-size of Tcl to 1Meg. If you are not doing regexps with many subexpressions,
-this is probably more stack than you will need. You can relink with the
-stack set to 512K, and you will be fine for most purposes.
-* This regexp problem is fixed in Tcl8.3. If you are going to do complex
-regexp's, it is probably a good idea to keep the stack size big. But normal
-regexps will not cause crashes.
-
-* The "clock scan -base" command does not work. The epoch is wrong.
-* The file mtime command does not work when setting the time, it is off
-by 4 years.
diff --git a/mac/libmoto.doc b/mac/libmoto.doc
deleted file mode 100644
index 54d7b95..0000000
--- a/mac/libmoto.doc
+++ /dev/null
@@ -1,37 +0,0 @@
-Notes about the use of libmoto
-------------------------------
-
-First of all, libmoto is not required! If you don't have it, you
-can simply remove the library reference from the project file and
-everything should compile just fine.
-
-The libmoto library replaces certain functions in the MathLib and
-ANSI libraries. Motorola has optimized the functions in the library
-to run very fast on the PowerPC. As I said above, you don't need
-this library, but it does make things faster.
-
-Obtaining Libmoto:
-
- For more information about Libmoto and how to doanload
- it, visit the following URL:
-
- http://www.mot.com/SPS/PowerPC/library/fact_sheet/libmoto.html
-
- You will need to register for the library. However, the
- library is free and you can use it in any commercial product
- you might have.
-
-Installing Libmoto:
-
- Just follow the instructions provided by the Motorola
- README file. You need to make sure that the Libmoto
- library is before the ANSI and MathLib libraries in
- link order. Also, you will get several warnings stateing
- that certain functions have already been defined in
- Libmoto. (These can safely be ignored.)
-
-Finally, you can thank Kate Stewart of Motorola for twisting my
-arm at the Tcl/Tk Conference to provide some support for Libmoto.
-
-Ray Johnson
-
diff --git a/mac/morefiles.doc b/mac/morefiles.doc
deleted file mode 100644
index 9704373..0000000
--- a/mac/morefiles.doc
+++ /dev/null
@@ -1,72 +0,0 @@
-Notes about MoreFiles, dnr.c & other non-Tcl source files
----------------------------------------------------------
-
-The Macintosh distribution uses several source files that don't
-actually ship with Tcl. This sometimes causes problems or confusion
-to developers. This document should help clear up a few things.
-
-dnr.c
------
-
-We have found a way to work around some bugs in dnr.c that
-Apple has never fixed even though we sent in numerous bug reports.
-The file tclMacDNR.c simply set's some #pragma's and the includes
-the Apple dnr.c file. This should work the problems that many of
-you have reported with dnr.c.
-
-More Files
-----------
-
-Macintosh Tcl/Tk also uses Jim Luther's very useful package called
-More Files. More Files fixes many of the broken or underfunctional
-parts of the file system.
-
-More Files can be found on the MetroWerks CD and Developer CD from
-Apple. You can also down load the latest version from:
-
- ftp://members.aol.com/JumpLong/
-
-The package can also be found at the home of Tcl/Tk for the mac:
-
- ftp://ftp.sunlabs.com/pub/tcl/mac/
-
-I used to just link the More Files library in the Tcl projects.
-However, this caused problems when libraries wern't matched correctly.
-I'm now including the files in the Tcl project directly. This
-solves the problem of missmatched libraries - but may not always
-compile.
-
-If you get a compiliation error in MoreFiles you need to contact
-Jim Luther. His email address:
-
- JumpLong@aol.com
-
-The version of More Files that we use with Tcl/Tk is 1.4.3. Early
-version may work as well..
-
-Unfortunantly, there is one bug in his library (in 1.4.3). The bug is
-in the function FSpGetFullPath found in the file FullPath.c. After
-the call to PBGetCatInfoSync you need to change the line:
-
- if ( result == noErr )
-
- to:
-
- if ( (result == noErr) || (result == fnfErr) )
-
-
-The latest version of More Files is 1.4.6. Unfortunantly, this
-version has a bug that keeps it from working with shared libraries
-right out of the box. If you want to use 1.4.6 you can but you will
-need to make the following fix:
-
- In the file "Opimization.h" in the More Files package you
- need to remove the line "#pragma internal on". And in the
- file "OptimazationEnd.h" you need to remove the line
- "#pragma internal reset".
-
-Note: the version of MoreFile downloaded from the Sun Tcl/Tk site
-will have the fix included. (If you want you can send email to
-Jim Luther suggesting that he use Tcl for regression testing!)
-
-Ray Johnson
diff --git a/mac/porting.notes b/mac/porting.notes
deleted file mode 100644
index 191a44e..0000000
--- a/mac/porting.notes
+++ /dev/null
@@ -1,21 +0,0 @@
-Porting Notes
--------------
-
-Currently, the Macintosh version Tcl only compilies with the
-CodeWarrior C compilier from MetroWerks. It should be straight
-forward to port the Tcl source to MPW.
-
-Tcl on the Mac no longer requires the use of GUSI. It should now
-be easier to port Tcl/Tk to other compiliers such as Symantic C
-and MPW C.
-
-If you attempt to port Tcl to other Macintosh compiliers please
-let me know. I would be glad to help with advice and encouragement.
-If your efforts are succesfull I wold also be interested in puting
-those changes into the core distribution. Furthermore, please feel
-free to send me any notes you might make about your porting
-experience so I may include them in this file for others to reference.
-
-Ray Johnson
-ray.johnson@eng.sun.com
-
diff --git a/mac/tclMac.h b/mac/tclMac.h
deleted file mode 100644
index 7b4bbb6..0000000
--- a/mac/tclMac.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * tclMac.h --
- *
- * Declarations of Macintosh specific public variables and procedures.
- *
- * Copyright (c) 1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#ifndef _TCLMAC
-#define _TCLMAC
-
-#ifndef _TCL
-# include "tcl.h"
-#endif
-#include <Types.h>
-#include <Files.h>
-#include <Events.h>
-
-typedef int (*Tcl_MacConvertEventPtr) _ANSI_ARGS_((EventRecord *eventPtr));
-
-#include "tclPlatDecls.h"
-
-#endif /* _TCLMAC */
diff --git a/mac/tclMacAETE.r b/mac/tclMacAETE.r
deleted file mode 100644
index 9a93f59..0000000
--- a/mac/tclMacAETE.r
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * tclMacAETE.r --
- *
- * This file creates the Apple Event Terminology resources
- * for use Tcl and Tk. It is not used in the Simple Tcl shell
- * since SIOUX does not support AppleEvents. An example of its
- * use in Tcl is the TclBGOnly project. And it is used in all the
- * Tk Shells.
- *
- * Copyright (c) 1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#define SystemSevenOrLater 1
-
-#include <Types.r>
-#include <SysTypes.r>
-#include <AEUserTermTypes.r>
-
-/*
- * The following resources defines the Apple Events that Tk can be
- * sent from Apple Script.
- */
-
-resource 'aete' (0, "Wish Suite") {
- 0x01, 0x00, english, roman,
- {
- "Required Suite",
- "Events that every application should support",
- 'reqd', 1, 1,
- {},
- {},
- {},
- {},
-
- "Wish Suite", "Events for the Wish application", 'WIsH', 1, 1,
- {
- "do script", "Execute a Tcl script", 'misc', 'dosc',
- 'TEXT', "Result", replyOptional, singleItem,
- notEnumerated, reserved, reserved, reserved, reserved,
- reserved, reserved, reserved, reserved, reserved,
- reserved, reserved, reserved, reserved,
- 'TEXT', "Script to execute", directParamRequired,
- singleItem, notEnumerated, changesState, reserved,
- reserved, reserved, reserved, reserved, reserved,
- reserved, reserved, reserved, reserved, reserved,
- reserved,
- {},
- },
- {},
- {},
- {},
- }
-};
diff --git a/mac/tclMacAlloc.c b/mac/tclMacAlloc.c
deleted file mode 100644
index d620554..0000000
--- a/mac/tclMacAlloc.c
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * tclMacAlloc.c --
- *
- * This is a very fast storage allocator. It allocates blocks of a
- * small number of different sizes, and keeps free lists of each size.
- * Blocks that don't exactly fit are passed up to the next larger size.
- * Blocks over a certain size are directly allocated by calling NewPtr.
- *
- * Copyright (c) 1983 Regents of the University of California.
- * Copyright (c) 1996-1997 Sun Microsystems, Inc.
- *
- * Portions contributed by Chris Kingsley, Jack Jansen and Ray Johnson
- *.
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include "tclInt.h"
-#include "tclMacInt.h"
-#include <Memory.h>
-#include <Gestalt.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-/*
- * Flags that are used by ConfigureMemory to define how the allocator
- * should work. They can be or'd together.
- */
-#define MEMORY_ALL_SYS 1 /* All memory should come from the system
-heap. */
-#define MEMORY_DONT_USE_TEMPMEM 2 /* Don't use temporary memory but system memory. */
-
-/*
- * Amount of space to leave in the application heap for the Toolbox to work.
- */
-
-#define TOOLBOX_SPACE (512 * 1024)
-
-static int memoryFlags = 0;
-static Handle toolGuardHandle = NULL;
- /* This handle must be around so that we don't
- * have NewGWorld failures. This handle is
- * purgeable. Before we allocate any blocks,
- * we see if this handle is still around.
- * If it is not, then we try to get it again.
- * If we can get it, we lock it and try
- * to do the normal allocation, unlocking on
- * the way out. If we can't, we go to the
- * system heap directly. */
-
-static int tclUseMemTracking = 0; /* Are we tracking memory allocations?
- * On recent versions of the MacOS this
- * is no longer necessary, as we can use
- * temporary memory which is freed by the
- * OS after a quit or crash. */
-
-static size_t tclExtraHdlSize = 0; /* Size of extra memory allocated at the start
- * of each block when using memory tracking
- * ( == 0 otherwise) */
-
-/*
- * The following typedef and variable are used to keep track of memory
- * blocks that are allocated directly from the System Heap. These chunks
- * of memory must always be freed - even if we crash.
- */
-
-typedef struct listEl {
- Handle memoryHandle;
- struct listEl * next;
- struct listEl * prec;
-} ListEl;
-
-static ListEl * systemMemory = NULL;
-static ListEl * appMemory = NULL;
-
-/*
- * Prototypes for functions used only in this file.
- */
-
-static pascal void CleanUpExitProc _ANSI_ARGS_((void));
-void ConfigureMemory _ANSI_ARGS_((int flags));
-void FreeAllMemory _ANSI_ARGS_((void));
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpSysRealloc --
- *
- * This function reallocates a chunk of system memory. If the
- * chunk is already big enough to hold the new block, then no
- * allocation happens.
- *
- * Results:
- * Returns a pointer to the newly allocated block.
- *
- * Side effects:
- * May copy the contents of the original block to the new block
- * and deallocate the original block.
- *
- *----------------------------------------------------------------------
- */
-
-VOID *
-TclpSysRealloc(
- VOID *oldPtr, /* Original block */
- unsigned int size) /* New size of block. */
-{
- Handle hand;
- void *newPtr;
- int maxsize;
- OSErr err;
-
- if (tclUseMemTracking) {
- hand = ((ListEl *) ((Ptr) oldPtr - tclExtraHdlSize))->memoryHandle;
- } else {
- hand = RecoverHandle((Ptr) oldPtr);
- }
- maxsize = GetHandleSize(hand) - sizeof(Handle);
- if (maxsize < size) {
- HUnlock(hand);
- SetHandleSize(hand,size + tclExtraHdlSize);
- err = MemError();
- HLock(hand);
- if(err==noErr){
- newPtr=(*hand + tclExtraHdlSize);
- } else {
- newPtr = TclpSysAlloc(size, 1);
- if(newPtr!=NULL) {
- memmove(newPtr, oldPtr, maxsize);
- TclpSysFree(oldPtr);
- }
- }
- } else {
- newPtr = oldPtr;
- }
- return newPtr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpSysAlloc --
- *
- * Allocate a new block of memory free from the System.
- *
- * Results:
- * Returns a pointer to a new block of memory.
- *
- * Side effects:
- * May obtain memory from app or sys space. Info is added to
- * overhead lists etc.
- *
- *----------------------------------------------------------------------
- */
-
-VOID *
-TclpSysAlloc(
- long size, /* Size of block to allocate. */
- int isBin) /* Is this a bin allocation? */
-{
- Handle hand = NULL;
- ListEl * newMemoryRecord;
- int isSysMem = 0;
- static int initialized=0;
-
- if (!initialized) {
- long response = 0;
- OSErr err = noErr;
- int useTempMem = 0;
-
- /* Check if we can use temporary memory */
- initialized=1;
- err = Gestalt(gestaltOSAttr, &response);
- if (err == noErr) {
- useTempMem = response & (1 << gestaltRealTempMemory);
- }
- tclUseMemTracking = !useTempMem || (memoryFlags & MEMORY_DONT_USE_TEMPMEM);
- if(tclUseMemTracking) {
- tclExtraHdlSize = sizeof(ListEl);
- /*
- * We are allocating memory directly from the system
- * heap. We need to install an exit handle
- * to ensure the memory is cleaned up.
- */
- TclMacInstallExitToShellPatch(CleanUpExitProc);
- }
- }
-
- if (!(memoryFlags & MEMORY_ALL_SYS)) {
-
- /*
- * If the guard handle has been purged, throw it away and try
- * to allocate it again.
- */
-
- if ((toolGuardHandle != NULL) && (*toolGuardHandle == NULL)) {
- DisposeHandle(toolGuardHandle);
- toolGuardHandle = NULL;
- }
-
- /*
- * If we have never allocated the guard handle, or it was purged
- * and thrown away, then try to allocate it again.
- */
-
- if (toolGuardHandle == NULL) {
- toolGuardHandle = NewHandle(TOOLBOX_SPACE);
- if (toolGuardHandle != NULL) {
- HLock(toolGuardHandle);
- HPurge(toolGuardHandle);
- }
- }
-
- /*
- * If we got the handle, lock it and do our allocation.
- */
-
- if (toolGuardHandle != NULL) {
- HLock(toolGuardHandle);
- hand = NewHandle(size + tclExtraHdlSize);
- HUnlock(toolGuardHandle);
- }
- }
- if (hand == NULL) {
- /*
- * Ran out of memory in application space. Lets try to get
- * more memory from system. Otherwise, we return NULL to
- * denote failure.
- */
- if(!tclUseMemTracking) {
- /* Use Temporary Memory instead of System Heap when available */
- OSErr err;
- isBin = 1; /* always HLockHi TempMemHandles */
- hand = TempNewHandle(size + tclExtraHdlSize,&err);
- if(err!=noErr) { hand=NULL; }
- } else {
- /* Use system heap when tracking memory */
- isSysMem=1;
- isBin = 0;
- hand = NewHandleSys(size + tclExtraHdlSize);
- }
- }
- if (hand == NULL) {
- return NULL;
- }
- if (isBin) {
- HLockHi(hand);
- } else {
- HLock(hand);
- }
- if(tclUseMemTracking) {
- /* Only need to do this when tracking memory */
- newMemoryRecord = (ListEl *) *hand;
- newMemoryRecord->memoryHandle = hand;
- newMemoryRecord->prec = NULL;
- if(isSysMem) {
- newMemoryRecord->next = systemMemory;
- systemMemory = newMemoryRecord;
- } else {
- newMemoryRecord->next = appMemory;
- appMemory = newMemoryRecord;
- }
- if(newMemoryRecord->next!=NULL) {
- newMemoryRecord->next->prec=newMemoryRecord;
- }
- }
-
- return (*hand + tclExtraHdlSize);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpSysFree --
- *
- * Free memory that we allocated back to the system.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Memory is freed.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpSysFree(
- void * ptr) /* Free this system memory. */
-{
- if(tclUseMemTracking) {
- /* Only need to do this when tracking memory */
- ListEl *memRecord;
-
- memRecord = (ListEl *) ((Ptr) ptr - tclExtraHdlSize);
- /* Remove current record from linked list */
- if(memRecord->next!=NULL) {
- memRecord->next->prec=memRecord->prec;
- }
- if(memRecord->prec!=NULL) {
- memRecord->prec->next=memRecord->next;
- }
- if(memRecord==appMemory) {
- appMemory=memRecord->next;
- } else if(memRecord==systemMemory) {
- systemMemory=memRecord->next;
- }
- DisposeHandle(memRecord->memoryHandle);
- } else {
- DisposeHandle(RecoverHandle((Ptr) ptr));
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * CleanUpExitProc --
- *
- * This procedure is invoked as an exit handler when ExitToShell
- * is called. It removes any memory that was allocated directly
- * from the system heap. This must be called when the application
- * quits or the memory will never be freed.
- *
- * Results:
- * None.
- *
- * Side effects:
- * May free memory in the system heap.
- *
- *----------------------------------------------------------------------
- */
-
-static pascal void
-CleanUpExitProc()
-{
- ListEl * memRecord;
-
- if(tclUseMemTracking) {
- /* Only need to do this when tracking memory */
- while (systemMemory != NULL) {
- memRecord = systemMemory;
- systemMemory = memRecord->next;
- DisposeHandle(memRecord->memoryHandle);
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * FreeAllMemory --
- *
- * This procedure frees all memory blocks allocated by the memory
- * sub-system. Make sure you don't have any code that references
- * any malloced data!
- *
- * Results:
- * None.
- *
- * Side effects:
- * Frees all memory allocated by TclpAlloc.
- *
- *----------------------------------------------------------------------
- */
-
-void
-FreeAllMemory()
-{
- ListEl * memRecord;
-
- if(tclUseMemTracking) {
- /* Only need to do this when tracking memory */
- while (systemMemory != NULL) {
- memRecord = systemMemory;
- systemMemory = memRecord->next;
- DisposeHandle(memRecord->memoryHandle);
- }
- while (appMemory != NULL) {
- memRecord = appMemory;
- appMemory = memRecord->next;
- DisposeHandle(memRecord->memoryHandle);
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ConfigureMemory --
- *
- * This procedure sets certain flags in this file that control
- * how memory is allocated and managed. This call must be made
- * before any call to TclpAlloc is made.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Certain state will be changed.
- *
- *----------------------------------------------------------------------
- */
-
-void
-ConfigureMemory(
- int flags) /* Flags that control memory alloc scheme. */
-{
- memoryFlags = flags;
-}
diff --git a/mac/tclMacAppInit.c b/mac/tclMacAppInit.c
deleted file mode 100644
index 2a8eb76..0000000
--- a/mac/tclMacAppInit.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * tclMacAppInit.c --
- *
- * Provides a version of the Tcl_AppInit procedure for the example shell.
- *
- * Copyright (c) 1993-1994 Lockheed Missle & Space Company, AI Center
- * Copyright (c) 1995-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include "tcl.h"
-#include "tclInt.h"
-#include "tclPort.h"
-#include "tclMac.h"
-#include "tclMacInt.h"
-
-#if defined(THINK_C)
-# include <console.h>
-#elif defined(__MWERKS__)
-# include <SIOUX.h>
-EXTERN short InstallConsole _ANSI_ARGS_((short fd));
-#endif
-
-#ifdef TCL_TEST
-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));
-#endif /* TCL_TEST */
-
-/*
- * Forward declarations for procedures defined later in this file:
- */
-
-static int MacintoshInit _ANSI_ARGS_((void));
-
-/*
- *----------------------------------------------------------------------
- *
- * main --
- *
- * Main program for tclsh. This file can be used as a prototype
- * for other applications using the Tcl library.
- *
- * Results:
- * None. This procedure never returns (it exits the process when
- * it's done.
- *
- * Side effects:
- * This procedure initializes the Macintosh world and then
- * calls Tcl_Main. Tcl_Main will never return except to exit.
- *
- *----------------------------------------------------------------------
- */
-
-void
-main(
- int argc, /* Number of arguments. */
- char **argv) /* Array of argument strings. */
-{
- char *newArgv[2];
-
- if (MacintoshInit() != TCL_OK) {
- Tcl_Exit(1);
- }
-
- argc = 1;
- newArgv[0] = "tclsh";
- newArgv[1] = NULL;
- Tcl_Main(argc, newArgv, Tcl_AppInit);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * 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(
- Tcl_Interp *interp) /* Interpreter for application. */
-{
- if (Tcl_Init(interp) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
-#ifdef TCL_TEST
- 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;
- }
- 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.
- * Each call would loo like this:
- *
- * Tcl_CreateCommand(interp, "tclName", CFuncCmd, NULL, NULL);
- */
-
- /*
- * Specify a user-specific startup script to invoke if the application
- * is run interactively. On the Mac we can specifiy either a TEXT resource
- * which contains the script or the more UNIX like file location
- * may also used. (I highly recommend using the resource method.)
- */
-
- Tcl_SetVar(interp, "tcl_rcRsrcName", "tclshrc", TCL_GLOBAL_ONLY);
- /* Tcl_SetVar(interp, "tcl_rcFileName", "~/.tclshrc", TCL_GLOBAL_ONLY); */
-
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * MacintoshInit --
- *
- * This procedure calls initalization routines to set up a simple
- * console on a Macintosh. This is necessary as the Mac doesn't
- * have a stdout & stderr by default.
- *
- * Results:
- * Returns TCL_OK if everything went fine. If it didn't the
- * application should probably fail.
- *
- * Side effects:
- * Inits the appropiate console package.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-MacintoshInit()
-{
-#if GENERATING68K && !GENERATINGCFM
- SetApplLimit(GetApplLimit() - (TCL_MAC_68K_STACK_GROWTH));
-#endif
- MaxApplZone();
-
-#if defined(THINK_C)
-
- /* Set options for Think C console package */
- /* The console package calls the Mac init calls */
- console_options.pause_atexit = 0;
- console_options.title = "\pTcl Interpreter";
-
-#elif defined(__MWERKS__)
-
- /* Set options for CodeWarrior SIOUX package */
- SIOUXSettings.autocloseonquit = true;
- SIOUXSettings.showstatusline = true;
- SIOUXSettings.asktosaveonclose = false;
- SIOUXSettings.wasteusetempmemory = true;
- InstallConsole(0);
- SIOUXSetTitle("\pTcl Interpreter");
-
-#elif defined(applec)
-
- /* Init packages used by MPW SIOW package */
- InitGraf((Ptr)&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
- InitCursor();
-
-#endif
-
- Tcl_MacSetEventProc((Tcl_MacConvertEventPtr) SIOUXHandleOneEvent);
-
- /* No problems with initialization */
- return TCL_OK;
-}
diff --git a/mac/tclMacApplication.r b/mac/tclMacApplication.r
deleted file mode 100644
index 0d51b2d..0000000
--- a/mac/tclMacApplication.r
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * tclMacApplication.r --
- *
- * This file creates resources for use Tcl Shell application.
- * It should be viewed as an example of how to create a new
- * Tcl application using the shared Tcl libraries.
- *
- * Copyright (c) 1996-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include <Types.r>
-#include <SysTypes.r>
-
-/*
- * The folowing include and defines help construct
- * the version string for Tcl.
- */
-
-#define RC_INVOKED
-#include "tcl.h"
-
-#if (TCL_RELEASE_LEVEL == 0)
-# define RELEASE_LEVEL alpha
-#elif (TCL_RELEASE_LEVEL == 1)
-# define RELEASE_LEVEL beta
-#elif (TCL_RELEASE_LEVEL == 2)
-# define RELEASE_LEVEL final
-#endif
-
-#if (TCL_RELEASE_LEVEL == 2)
-# define MINOR_VERSION (TCL_MINOR_VERSION * 16) + TCL_RELEASE_SERIAL
-# define RELEASE_CODE 0x00
-#else
-# define MINOR_VERSION TCL_MINOR_VERSION * 16
-# define RELEASE_CODE TCL_RELEASE_SERIAL
-#endif
-
-resource 'vers' (1) {
- TCL_MAJOR_VERSION, MINOR_VERSION,
- RELEASE_LEVEL, RELEASE_CODE, verUS,
- TCL_PATCH_LEVEL,
- TCL_PATCH_LEVEL ", by Ray Johnson & Jim Ingham" "\n" "© 2001 Tcl Core Team"
-};
-
-resource 'vers' (2) {
- TCL_MAJOR_VERSION, MINOR_VERSION,
- RELEASE_LEVEL, RELEASE_CODE, verUS,
- TCL_PATCH_LEVEL,
- "Tcl Shell " TCL_PATCH_LEVEL " © 1993-2001"
-};
-
-#define TCL_APP_CREATOR 'Tcl '
-
-type TCL_APP_CREATOR as 'STR ';
-resource TCL_APP_CREATOR (0, purgeable) {
- "Tcl Shell " TCL_PATCH_LEVEL " © 1993-2001"
-};
-
-/*
- * The 'kind' resource works with a 'BNDL' in Macintosh Easy Open
- * to affect the text the Finder displays in the "kind" column and
- * file info dialog. This information will be applied to all files
- * with the listed creator and type.
- */
-
-resource 'kind' (128, "Tcl kind", purgeable) {
- TCL_APP_CREATOR,
- 0, /* region = USA */
- {
- 'APPL', "Tcl Shell",
- }
-};
-
-/*
- * The following resource is used when creating the 'env' variable in
- * the Macintosh environment. The creation mechanisim looks for the
- * 'STR#' resource named "Tcl Environment Variables" rather than a
- * specific resource number. (In other words, feel free to change the
- * resource id if it conflicts with your application.) Each string in
- * the resource must be of the form "KEYWORD=SOME STRING". See Tcl
- * documentation for futher information about the env variable.
- *
- * A good example of something you may want to set is: "TCL_LIBRARY=My
- * disk:etc."
- */
-
-resource 'STR#' (128, "Tcl Environment Variables") {
- {
- /*
- "SCHEDULE_NAME=Agent Controller Schedule",
- "SCHEDULE_PATH=Lozoya:System Folder:Tcl Lib:Tcl-Scheduler"
- */
- };
-};
-
-data 'alis' (1000, "Library Folder") {
- $"0000 0000 00BA 0002 0001 012F 0000 0000" /* .....†...../.... */
- $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */
- $"0000 0000 0000 985C FB00 4244 0000 0000" /* ......ò\š.BD.... */
- $"0002 1328 5375 7070 6F72 7420 4C69 6272" /* ...(Support Libr */
- $"6172 6965 7329 0000 0000 0000 0000 0000" /* aries).......... */
- $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */
- $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */
- $"0000 0076 8504 B617 A796 003D 0027 025B" /* ...vÖ..ßñ.=.'.[ */
- $"01E4 0001 0001 0000 0000 0000 0000 0000" /* .”.............. */
- $"0000 0000 0000 0000 0001 2F00 0002 0015" /* ........../..... */
- $"2F3A 2853 7570 706F 7274 204C 6962 7261" /* /:(Support Libra */
- $"7269 6573 2900 FFFF 0000" /* ries)... */
-};
-
diff --git a/mac/tclMacBOAAppInit.c b/mac/tclMacBOAAppInit.c
deleted file mode 100644
index 2a48fd0..0000000
--- a/mac/tclMacBOAAppInit.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * tclMacBOAAppInit.c --
- *
- * Provides a version of the Tcl_AppInit procedure for a
- * Macintosh Background Only Application.
- *
- * Copyright (c) 1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include "tcl.h"
-#include "tclInt.h"
-#include "tclPort.h"
-#include "tclMac.h"
-#include "tclMacInt.h"
-#include <Fonts.h>
-#include <Windows.h>
-#include <Dialogs.h>
-#include <Menus.h>
-#include <Aliases.h>
-#include <LowMem.h>
-
-#include <AppleEvents.h>
-#include <SegLoad.h>
-#include <ToolUtils.h>
-
-#if defined(THINK_C)
-# include <console.h>
-#elif defined(__MWERKS__)
-# include <SIOUX.h>
-short InstallConsole _ANSI_ARGS_((short fd));
-#endif
-
-void TkMacInitAppleEvents(Tcl_Interp *interp);
-int HandleHighLevelEvents(EventRecord *eventPtr);
-
-#ifdef TCL_TEST
-EXTERN int TclObjTest_Init _ANSI_ARGS_((Tcl_Interp *interp));
-EXTERN int Tcltest_Init _ANSI_ARGS_((Tcl_Interp *interp));
-#endif /* TCL_TEST */
-
-/*
- * Forward declarations for procedures defined later in this file:
- */
-
-static int MacintoshInit _ANSI_ARGS_((void));
-
-/*
- *----------------------------------------------------------------------
- *
- * main --
- *
- * Main program for tclsh. This file can be used as a prototype
- * for other applications using the Tcl library.
- *
- * Results:
- * None. This procedure never returns (it exits the process when
- * it's done.
- *
- * Side effects:
- * This procedure initializes the Macintosh world and then
- * calls Tcl_Main. Tcl_Main will never return except to exit.
- *
- *----------------------------------------------------------------------
- */
-
-void
-main(
- int argc, /* Number of arguments. */
- char **argv) /* Array of argument strings. */
-{
- char *newArgv[3];
-
- if (MacintoshInit() != TCL_OK) {
- Tcl_Exit(1);
- }
-
- argc = 2;
- newArgv[0] = "tclsh";
- newArgv[1] = "bgScript.tcl";
- newArgv[2] = NULL;
- Tcl_Main(argc, newArgv, Tcl_AppInit);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * 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(
- Tcl_Interp *interp) /* Interpreter for application. */
-{
- Tcl_Channel tempChan;
-
- if (Tcl_Init(interp) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
-#ifdef TCL_TEST
- 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;
- }
-#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.
- * Each call would loo like this:
- *
- * Tcl_CreateCommand(interp, "tclName", CFuncCmd, NULL, NULL);
- */
-
- /*
- * Specify a user-specific startup script to invoke if the application
- * is run interactively. On the Mac we can specifiy either a TEXT resource
- * which contains the script or the more UNIX like file location
- * may also used. (I highly recommend using the resource method.)
- */
-
- Tcl_SetVar(interp, "tcl_rcRsrcName", "tclshrc", TCL_GLOBAL_ONLY);
-
- /* Tcl_SetVar(interp, "tcl_rcFileName", "~/.tclshrc", TCL_GLOBAL_ONLY); */
-
- /*
- * We have to support at least the quit Apple Event.
- */
-
- TkMacInitAppleEvents(interp);
-
- /*
- * Open a file channel to put stderr, stdin, stdout...
- */
-
- tempChan = Tcl_OpenFileChannel(interp, ":temp.in", "a+", 0);
- Tcl_SetStdChannel(tempChan,TCL_STDIN);
- Tcl_RegisterChannel(interp, tempChan);
- Tcl_SetChannelOption(NULL, tempChan, "-translation", "cr");
- Tcl_SetChannelOption(NULL, tempChan, "-buffering", "line");
-
- tempChan = Tcl_OpenFileChannel(interp, ":temp.out", "a+", 0);
- Tcl_SetStdChannel(tempChan,TCL_STDOUT);
- Tcl_RegisterChannel(interp, tempChan);
- Tcl_SetChannelOption(NULL, tempChan, "-translation", "cr");
- Tcl_SetChannelOption(NULL, tempChan, "-buffering", "line");
-
- tempChan = Tcl_OpenFileChannel(interp, ":temp.err", "a+", 0);
- Tcl_SetStdChannel(tempChan,TCL_STDERR);
- Tcl_RegisterChannel(interp, tempChan);
- Tcl_SetChannelOption(NULL, tempChan, "-translation", "cr");
- Tcl_SetChannelOption(NULL, tempChan, "-buffering", "none");
-
-
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * MacintoshInit --
- *
- * This procedure calls initalization routines to set up a simple
- * console on a Macintosh. This is necessary as the Mac doesn't
- * have a stdout & stderr by default.
- *
- * Results:
- * Returns TCL_OK if everything went fine. If it didn't the
- * application should probably fail.
- *
- * Side effects:
- * Inits the appropiate console package.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-MacintoshInit()
-{
- THz theZone = GetZone();
- SysEnvRec sys;
-
-
- /*
- * There is a bug in systems earlier that 7.5.5, where a second BOA will
- * get a corrupted heap. This is the fix from TechNote 1070
- */
-
- SysEnvirons(1, &sys);
-
- if (sys.systemVersion < 0x0755)
- {
- if ( LMGetHeapEnd() != theZone->bkLim) {
- LMSetHeapEnd(theZone->bkLim);
- }
- }
-
-#if GENERATING68K && !GENERATINGCFM
- SetApplLimit(GetApplLimit() - (TCL_MAC_68K_STACK_GROWTH));
-#endif
- MaxApplZone();
-
- InitGraf((Ptr)&qd.thePort);
-
- /* No problems with initialization */
- Tcl_MacSetEventProc(HandleHighLevelEvents);
-
- return TCL_OK;
-}
-
-int
-HandleHighLevelEvents(
- EventRecord *eventPtr)
-{
- int eventFound = false;
-
- if (eventPtr->what == kHighLevelEvent) {
- AEProcessAppleEvent(eventPtr);
- eventFound = true;
- } else if (eventPtr->what == nullEvent) {
- eventFound = true;
- }
- return eventFound;
-}
diff --git a/mac/tclMacBOAMain.c b/mac/tclMacBOAMain.c
deleted file mode 100644
index d981a2a..0000000
--- a/mac/tclMacBOAMain.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * tclMacBGMain.c --
- *
- * Main program for Macintosh Background Only Application shells.
- *
- * Copyright (c) 1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include "tcl.h"
-#include "tclInt.h"
-#include "tclMacInt.h"
-#include <Resources.h>
-#include <Notification.h>
-#include <Strings.h>
-
-/*
- * This variable is used to get out of the modal loop of the
- * notification manager.
- */
-
-int NotificationIsDone = 0;
-
-/*
- * The following code ensures that tclLink.c is linked whenever
- * Tcl is linked. Without this code there's no reference to the
- * code in that file from anywhere in Tcl, so it may not be
- * linked into the application.
- */
-
-EXTERN int Tcl_LinkVar();
-int (*tclDummyLinkVarPtr)() = Tcl_LinkVar;
-
-/*
- * Declarations for various library procedures and variables (don't want
- * to include tclPort.h here, because people might copy this file out of
- * the Tcl source directory to make their own modified versions).
- * Note: "exit" should really be declared here, but there's no way to
- * declare it without causing conflicts with other definitions elsewher
- * on some systems, so it's better just to leave it out.
- */
-
-extern int isatty _ANSI_ARGS_((int fd));
-extern char * strcpy _ANSI_ARGS_((char *dst, CONST char *src));
-
-static Tcl_Interp *interp; /* Interpreter for application. */
-
-/*
- * Forward references for procedures defined later in this file:
- */
-
-void TclMacDoNotification(char *mssg);
-void TclMacNotificationResponse(NMRecPtr nmRec);
-int Tcl_MacBGNotifyObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv);
-
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_Main --
- *
- * Main program for tclsh and most other Tcl-based applications.
- *
- * Results:
- * None. This procedure never returns (it exits the process when
- * it's done.
- *
- * Side effects:
- * This procedure initializes the Tk world and then starts
- * interpreting commands; almost anything could happen, depending
- * on the script being interpreted.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tcl_Main(argc, argv, appInitProc)
- int argc; /* Number of arguments. */
- char **argv; /* Array of argument strings. */
- Tcl_AppInitProc *appInitProc;
- /* Application-specific initialization
- * procedure to call after most
- * initialization but before starting to
- * execute commands. */
-{
- Tcl_Obj *prompt1NamePtr = NULL;
- Tcl_Obj *prompt2NamePtr = NULL;
- Tcl_Obj *commandPtr = NULL;
- char buffer[1000], *args, *fileName;
- int code, tty;
- int exitCode = 0;
-
- Tcl_FindExecutable(argv[0]);
- interp = Tcl_CreateInterp();
- Tcl_InitMemory(interp);
-
- /*
- * Make command-line arguments available in the Tcl variables "argc"
- * and "argv". If the first argument doesn't start with a "-" then
- * strip it off and use it as the name of a script file to process.
- */
-
- fileName = NULL;
- if ((argc > 1) && (argv[1][0] != '-')) {
- fileName = argv[1];
- argc--;
- argv++;
- }
- args = Tcl_Merge(argc-1, argv+1);
- Tcl_SetVar(interp, "argv", args, TCL_GLOBAL_ONLY);
- ckfree(args);
- TclFormatInt(buffer, argc-1);
- Tcl_SetVar(interp, "argc", buffer, TCL_GLOBAL_ONLY);
- Tcl_SetVar(interp, "argv0", (fileName != NULL) ? fileName : argv[0],
- TCL_GLOBAL_ONLY);
-
- /*
- * Set the "tcl_interactive" variable.
- */
-
- tty = isatty(0);
- Tcl_SetVar(interp, "tcl_interactive",
- ((fileName == NULL) && tty) ? "1" : "0", TCL_GLOBAL_ONLY);
-
- /*
- * Invoke application-specific initialization.
- */
-
- if ((*appInitProc)(interp) != TCL_OK) {
- Tcl_DString errStr;
-
- Tcl_DStringInit(&errStr);
- Tcl_DStringAppend(&errStr,
- "application-specific initialization failed: \n", -1);
- Tcl_DStringAppend(&errStr, Tcl_GetStringResult(interp), -1);
- Tcl_DStringAppend(&errStr, "\n", 1);
- TclMacDoNotification(Tcl_DStringValue(&errStr));
- Tcl_DStringFree(&errStr);
- goto done;
- }
-
- /*
- * Install the BGNotify command:
- */
-
- if ( Tcl_CreateObjCommand(interp, "bgnotify", Tcl_MacBGNotifyObjCmd, NULL,
- (Tcl_CmdDeleteProc *) NULL) == NULL) {
- goto done;
- }
-
- /*
- * If a script file was specified then just source that file
- * and quit. In this Mac BG Application version, we will try the
- * resource fork first, then the file system second...
- */
-
- if (fileName != NULL) {
- Str255 resName;
- Handle resource;
-
- strcpy((char *) resName + 1, fileName);
- resName[0] = strlen(fileName);
- resource = GetNamedResource('TEXT',resName);
- if (resource != NULL) {
- code = Tcl_MacEvalResource(interp, fileName, -1, NULL);
- } else {
- code = Tcl_EvalFile(interp, fileName);
- }
-
- if (code != TCL_OK) {
- Tcl_DString errStr;
-
- Tcl_DStringInit(&errStr);
- Tcl_DStringAppend(&errStr, " Error sourcing resource or file: ", -1);
- Tcl_DStringAppend(&errStr, fileName, -1);
- Tcl_DStringAppend(&errStr, "\n\nError was: ", -1);
- Tcl_DStringAppend(&errStr, Tcl_GetStringResult(interp), -1);
- TclMacDoNotification(Tcl_DStringValue(&errStr));
- Tcl_DStringFree(&errStr);
- }
- goto done;
- }
-
-
- /*
- * Rather than calling exit, invoke the "exit" command so that
- * users can replace "exit" with some other command to do additional
- * cleanup on exit. The Tcl_Eval call should never return.
- */
-
- done:
- if (commandPtr != NULL) {
- Tcl_DecrRefCount(commandPtr);
- }
- if (prompt1NamePtr != NULL) {
- Tcl_DecrRefCount(prompt1NamePtr);
- }
- if (prompt2NamePtr != NULL) {
- Tcl_DecrRefCount(prompt2NamePtr);
- }
- sprintf(buffer, "exit %d", exitCode);
- Tcl_Eval(interp, buffer);
-}
-
-/*----------------------------------------------------------------------
- *
- * TclMacDoNotification --
- *
- * This posts an error message using the Notification manager.
- *
- * Results:
- * Post a Notification Manager dialog.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-void
-TclMacDoNotification(mssg)
- char *mssg;
-{
- NMRec errorNot;
- EventRecord *theEvent = NULL;
- OSErr err;
- char *ptr;
-
- errorNot.qType = nmType;
- errorNot.nmMark = 0;
- errorNot.nmIcon = 0;
- errorNot.nmSound = (Handle) -1;
-
- for ( ptr = mssg; *ptr != '\0'; ptr++) {
- if (*ptr == '\n') {
- *ptr = '\r';
- }
- }
-
- c2pstr(mssg);
- errorNot.nmStr = (StringPtr) mssg;
-
- errorNot.nmResp = NewNMProc(TclMacNotificationResponse);
- errorNot.nmRefCon = SetCurrentA5();
-
- NotificationIsDone = 0;
-
- /*
- * Cycle while waiting for the user to click on the
- * notification box. Don't take any events off the event queue,
- * since we want Tcl to do this but we want to block till the notification
- * has been handled...
- */
-
- err = NMInstall(&errorNot);
- if (err == noErr) {
- while (!NotificationIsDone) {
- WaitNextEvent(0, theEvent, 20, NULL);
- }
- NMRemove(&errorNot);
- }
-
- p2cstr((unsigned char *) mssg);
-}
-
-void
-TclMacNotificationResponse(nmRec)
- NMRecPtr nmRec;
-{
- int curA5;
-
- curA5 = SetCurrentA5();
- SetA5(nmRec->nmRefCon);
-
- NotificationIsDone = 1;
-
- SetA5(curA5);
-
-}
-
-int
-Tcl_MacBGNotifyObjCmd(clientData, interp, objc, objv)
- ClientData clientData;
- Tcl_Interp *interp;
- int objc;
- Tcl_Obj **objv;
-{
- Tcl_Obj *resultPtr;
-
- resultPtr = Tcl_GetObjResult(interp);
-
- if ( objc != 2 ) {
- Tcl_WrongNumArgs(interp, 1, objv, "message");
- return TCL_ERROR;
- }
-
- TclMacDoNotification(Tcl_GetString(objv[1]));
- return TCL_OK;
-
-}
-
diff --git a/mac/tclMacChan.c b/mac/tclMacChan.c
deleted file mode 100644
index 31eb111..0000000
--- a/mac/tclMacChan.c
+++ /dev/null
@@ -1,1273 +0,0 @@
-/*
- * tclMacChan.c
- *
- * Channel drivers for Macintosh channels for the
- * console fds.
- *
- * Copyright (c) 1996-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include "tclInt.h"
-#include "tclPort.h"
-#include "tclMacInt.h"
-#include <Aliases.h>
-#include <Errors.h>
-#include <Files.h>
-#include <Gestalt.h>
-#include <Processes.h>
-#include <Strings.h>
-#include <FSpCompat.h>
-#include <MoreFiles.h>
-#include <MoreFilesExtras.h>
-#include "tclIO.h"
-
-#ifdef __MSL__
-#include <unix.mac.h>
-#define TCL_FILE_CREATOR (__getcreator(0))
-#else
-#define TCL_FILE_CREATOR 'MPW '
-#endif
-
-/*
- * This structure describes per-instance state of a
- * macintosh file based channel.
- */
-
-typedef struct FileState {
- short fileRef; /* Macintosh file reference number. */
- Tcl_Channel fileChan; /* Pointer to the channel for this file. */
- int watchMask; /* OR'ed set of flags indicating which events
- * are being watched. */
- int appendMode; /* Flag to tell if in O_APPEND mode or not. */
- int volumeRef; /* Flag to tell if in O_APPEND mode or not. */
- int pending; /* 1 if message is pending on queue. */
- struct FileState *nextPtr; /* Pointer to next registered file. */
-} FileState;
-
-typedef struct ThreadSpecificData {
- int initialized; /* True after the thread initializes */
- FileState *firstFilePtr; /* the head of the list of files managed
- * that are being watched for file events. */
- Tcl_Channel stdinChannel;
- Tcl_Channel stdoutChannel; /* Note - these seem unused */
- Tcl_Channel stderrChannel;
-} ThreadSpecificData;
-
-static Tcl_ThreadDataKey dataKey;
-
-/*
- * The following structure is what is added to the Tcl event queue when
- * file events are generated.
- */
-
-typedef struct FileEvent {
- Tcl_Event header; /* Information that is standard for
- * all events. */
- FileState *infoPtr; /* Pointer to file info structure. Note
- * that we still have to verify that the
- * file exists before dereferencing this
- * pointer. */
-} FileEvent;
-
-
-/*
- * Static routines for this file:
- */
-
-static int CommonGetHandle _ANSI_ARGS_((ClientData instanceData,
- int direction, ClientData *handlePtr));
-static void CommonWatch _ANSI_ARGS_((ClientData instanceData,
- int mask));
-static int FileBlockMode _ANSI_ARGS_((ClientData instanceData,
- int mode));
-static void FileChannelExitHandler _ANSI_ARGS_((
- ClientData clientData));
-static void FileCheckProc _ANSI_ARGS_((ClientData clientData,
- int flags));
-static int FileClose _ANSI_ARGS_((ClientData instanceData,
- Tcl_Interp *interp));
-static int FileEventProc _ANSI_ARGS_((Tcl_Event *evPtr,
- int flags));
-static ThreadSpecificData *FileInit _ANSI_ARGS_((void));
-static int FileInput _ANSI_ARGS_((ClientData instanceData,
- char *buf, int toRead, int *errorCode));
-static int FileOutput _ANSI_ARGS_((ClientData instanceData,
- CONST char *buf, int toWrite, int *errorCode));
-static int FileSeek _ANSI_ARGS_((ClientData instanceData,
- long offset, int mode, int *errorCode));
-static void FileSetupProc _ANSI_ARGS_((ClientData clientData,
- int flags));
-static void FileThreadActionProc _ANSI_ARGS_ ((
- ClientData instanceData, int action));
-static Tcl_Channel OpenFileChannel _ANSI_ARGS_((CONST char *fileName,
- int mode, int permissions, int *errorCodePtr));
-static int StdIOBlockMode _ANSI_ARGS_((ClientData instanceData,
- int mode));
-static int StdIOClose _ANSI_ARGS_((ClientData instanceData,
- Tcl_Interp *interp));
-static int StdIOInput _ANSI_ARGS_((ClientData instanceData,
- char *buf, int toRead, int *errorCode));
-static int StdIOOutput _ANSI_ARGS_((ClientData instanceData,
- CONST char *buf, int toWrite, int *errorCode));
-static int StdIOSeek _ANSI_ARGS_((ClientData instanceData,
- long offset, int mode, int *errorCode));
-static int StdReady _ANSI_ARGS_((ClientData instanceData,
- int mask));
-
-/*
- * This structure describes the channel type structure for file based IO:
- */
-
-static Tcl_ChannelType consoleChannelType = {
- "file", /* Type name. */
- TCL_CHANNEL_VERSION_4, /* v4 channel */
- StdIOClose, /* Close proc. */
- StdIOInput, /* Input proc. */
- StdIOOutput, /* Output proc. */
- StdIOSeek, /* Seek proc. */
- NULL, /* Set option proc. */
- NULL, /* Get option proc. */
- CommonWatch, /* Initialize notifier. */
- CommonGetHandle /* Get OS handles out of channel. */
- NULL, /* close2proc. */
- StdIOBlockMode, /* Set blocking/nonblocking mode.*/
- NULL, /* flush proc. */
- NULL, /* handler proc. */
- NULL, /* wide seek proc. */
- NULL, /* thread actions */
-};
-
-/*
- * This variable describes the channel type structure for file based IO.
- */
-
-static Tcl_ChannelType fileChannelType = {
- "file", /* Type name. */
- TCL_CHANNEL_VERSION_4, /* v4 channel */
- FileClose, /* Close proc. */
- FileInput, /* Input proc. */
- FileOutput, /* Output proc. */
- FileSeek, /* Seek proc. */
- NULL, /* Set option proc. */
- NULL, /* Get option proc. */
- CommonWatch, /* Initialize notifier. */
- CommonGetHandle /* Get OS handles out of channel. */
- NULL, /* close2proc. */
- FileBlockMode, /* Set blocking/nonblocking mode.*/
- NULL, /* flush proc. */
- NULL, /* handler proc. */
- NULL, /* wide seek proc. */
- FileThreadActionProc, /* thread actions */
-};
-
-
-/*
- * Hack to allow Mac Tk to override the TclGetStdChannels function.
- */
-
-typedef void (*TclGetStdChannelsProc) _ANSI_ARGS_((Tcl_Channel *stdinPtr,
- Tcl_Channel *stdoutPtr, Tcl_Channel *stderrPtr));
-
-TclGetStdChannelsProc getStdChannelsProc = NULL;
-
-
-/*
- *----------------------------------------------------------------------
- *
- * FileInit --
- *
- * This function initializes the file channel event source.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Creates a new event source.
- *
- *----------------------------------------------------------------------
- */
-
-static ThreadSpecificData *
-FileInit()
-{
- ThreadSpecificData *tsdPtr =
- (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
- if (tsdPtr == NULL) {
- tsdPtr = TCL_TSD_INIT(&dataKey);
- tsdPtr->firstFilePtr = NULL;
- Tcl_CreateEventSource(FileSetupProc, FileCheckProc, NULL);
- Tcl_CreateThreadExitHandler(FileChannelExitHandler, NULL);
- }
- return tsdPtr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * FileChannelExitHandler --
- *
- * This function is called to cleanup the channel driver before
- * Tcl is unloaded.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Destroys the communication window.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-FileChannelExitHandler(
- ClientData clientData) /* Old window proc */
-{
- Tcl_DeleteEventSource(FileSetupProc, FileCheckProc, NULL);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * FileSetupProc --
- *
- * This procedure is invoked before Tcl_DoOneEvent blocks waiting
- * for an event.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Adjusts the block time if needed.
- *
- *----------------------------------------------------------------------
- */
-
-void
-FileSetupProc(
- ClientData data, /* Not used. */
- int flags) /* Event flags as passed to Tcl_DoOneEvent. */
-{
- FileState *infoPtr;
- Tcl_Time blockTime = { 0, 0 };
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
- if (!(flags & TCL_FILE_EVENTS)) {
- return;
- }
-
- /*
- * Check to see if there is a ready file. If so, poll.
- */
-
- for (infoPtr = tsdPtr->firstFilePtr; infoPtr != NULL;
- infoPtr = infoPtr->nextPtr) {
- if (infoPtr->watchMask) {
- Tcl_SetMaxBlockTime(&blockTime);
- break;
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * FileCheckProc --
- *
- * This procedure is called by Tcl_DoOneEvent to check the file
- * event source for events.
- *
- * Results:
- * None.
- *
- * Side effects:
- * May queue an event.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-FileCheckProc(
- ClientData data, /* Not used. */
- int flags) /* Event flags as passed to Tcl_DoOneEvent. */
-{
- FileEvent *evPtr;
- FileState *infoPtr;
- int sentMsg = 0;
- Tcl_Time blockTime = { 0, 0 };
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
- if (!(flags & TCL_FILE_EVENTS)) {
- return;
- }
-
- /*
- * Queue events for any ready files that don't already have events
- * queued (caused by persistent states that won't generate WinSock
- * events).
- */
-
- for (infoPtr = tsdPtr->firstFilePtr; infoPtr != NULL;
- infoPtr = infoPtr->nextPtr) {
- if (infoPtr->watchMask && !infoPtr->pending) {
- infoPtr->pending = 1;
- evPtr = (FileEvent *) ckalloc(sizeof(FileEvent));
- evPtr->header.proc = FileEventProc;
- evPtr->infoPtr = infoPtr;
- Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL);
- }
- }
-}
-
-/*----------------------------------------------------------------------
- *
- * FileEventProc --
- *
- * This function is invoked by Tcl_ServiceEvent when a file event
- * reaches the front of the event queue. This procedure invokes
- * Tcl_NotifyChannel on the file.
- *
- * Results:
- * Returns 1 if the event was handled, meaning it should be removed
- * from the queue. Returns 0 if the event was not handled, meaning
- * it should stay on the queue. The only time the event isn't
- * handled is if the TCL_FILE_EVENTS flag bit isn't set.
- *
- * Side effects:
- * Whatever the notifier callback does.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-FileEventProc(
- Tcl_Event *evPtr, /* Event to service. */
- int flags) /* Flags that indicate what events to
- * handle, such as TCL_FILE_EVENTS. */
-{
- FileEvent *fileEvPtr = (FileEvent *)evPtr;
- FileState *infoPtr;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
- if (!(flags & TCL_FILE_EVENTS)) {
- return 0;
- }
-
- /*
- * Search through the list of watched files for the one whose handle
- * matches the event. We do this rather than simply dereferencing
- * the handle in the event so that files can be deleted while the
- * event is in the queue.
- */
-
- for (infoPtr = tsdPtr->firstFilePtr; infoPtr != NULL;
- infoPtr = infoPtr->nextPtr) {
- if (fileEvPtr->infoPtr == infoPtr) {
- infoPtr->pending = 0;
- Tcl_NotifyChannel(infoPtr->fileChan, infoPtr->watchMask);
- break;
- }
- }
- return 1;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * StdIOBlockMode --
- *
- * Set blocking or non-blocking mode on channel.
- *
- * Results:
- * 0 if successful, errno when failed.
- *
- * Side effects:
- * Sets the device into blocking or non-blocking mode.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-StdIOBlockMode(
- ClientData instanceData, /* Unused. */
- int mode) /* The mode to set. */
-{
- /*
- * Do not allow putting stdin, stdout or stderr into nonblocking mode.
- */
-
- if (mode == TCL_MODE_NONBLOCKING) {
- return EFAULT;
- }
-
- return 0;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * StdIOClose --
- *
- * Closes the IO channel.
- *
- * Results:
- * 0 if successful, the value of errno if failed.
- *
- * Side effects:
- * Closes the physical channel
- *
- *----------------------------------------------------------------------
- */
-
-static int
-StdIOClose(
- ClientData instanceData, /* Unused. */
- Tcl_Interp *interp) /* Unused. */
-{
- int fd, errorCode = 0;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
- /*
- * Invalidate the stdio cache if necessary. Note that we assume that
- * the stdio file and channel pointers will become invalid at the same
- * time.
- * Do not close standard channels while in thread-exit.
- */
-
- fd = (int) ((FileState*)instanceData)->fileRef;
- if (!TclInThreadExit()) {
- if (fd == 0) {
- tsdPtr->stdinChannel = NULL;
- } else if (fd == 1) {
- tsdPtr->stdoutChannel = NULL;
- } else if (fd == 2) {
- tsdPtr->stderrChannel = NULL;
- } else {
- panic("recieved invalid std file");
- }
-
- if (close(fd) < 0) {
- errorCode = errno;
- }
- }
- return errorCode;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * CommonGetHandle --
- *
- * Called from Tcl_GetChannelHandle to retrieve OS handles from inside
- * a file based channel.
- *
- * Results:
- * The appropriate handle or NULL if not present.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-CommonGetHandle(
- ClientData instanceData, /* The file state. */
- int direction, /* Which handle to retrieve? */
- ClientData *handlePtr)
-{
- if ((direction == TCL_READABLE) || (direction == TCL_WRITABLE)) {
- *handlePtr = (ClientData) ((FileState*)instanceData)->fileRef;
- return TCL_OK;
- }
- return TCL_ERROR;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * StdIOInput --
- *
- * Reads input from the IO channel into the buffer given. Returns
- * count of how many bytes were actually read, and an error indication.
- *
- * Results:
- * A count of how many bytes were read is returned and an error
- * indication is returned in an output argument.
- *
- * Side effects:
- * Reads input from the actual channel.
- *
- *----------------------------------------------------------------------
- */
-
-int
-StdIOInput(
- ClientData instanceData, /* Unused. */
- char *buf, /* Where to store data read. */
- int bufSize, /* How much space is available
- * in the buffer? */
- int *errorCode) /* Where to store error code. */
-{
- int fd;
- int bytesRead; /* How many bytes were read? */
-
- *errorCode = 0;
- errno = 0;
- fd = (int) ((FileState*)instanceData)->fileRef;
- bytesRead = read(fd, buf, (size_t) bufSize);
- if (bytesRead > -1) {
- return bytesRead;
- }
- *errorCode = errno;
- return -1;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * StdIOOutput--
- *
- * Writes the given output on the IO channel. Returns count of how
- * many characters were actually written, and an error indication.
- *
- * Results:
- * A count of how many characters were written is returned and an
- * error indication is returned in an output argument.
- *
- * Side effects:
- * Writes output on the actual channel.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-StdIOOutput(
- ClientData instanceData, /* Unused. */
- CONST char *buf, /* The data buffer. */
- int toWrite, /* How many bytes to write? */
- int *errorCode) /* Where to store error code. */
-{
- int written;
- int fd;
-
- *errorCode = 0;
- errno = 0;
- fd = (int) ((FileState*)instanceData)->fileRef;
- written = write(fd, (void*)buf, (size_t) toWrite);
- if (written > -1) {
- return written;
- }
- *errorCode = errno;
- return -1;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * StdIOSeek --
- *
- * Seeks on an IO channel. Returns the new position.
- *
- * Results:
- * -1 if failed, the new position if successful. If failed, it
- * also sets *errorCodePtr to the error code.
- *
- * Side effects:
- * Moves the location at which the channel will be accessed in
- * future operations.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-StdIOSeek(
- ClientData instanceData, /* Unused. */
- long offset, /* Offset to seek to. */
- int mode, /* Relative to where should we seek? */
- int *errorCodePtr) /* To store error code. */
-{
- int newLoc;
- int fd;
-
- *errorCodePtr = 0;
- fd = (int) ((FileState*)instanceData)->fileRef;
- newLoc = lseek(fd, offset, mode);
- if (newLoc > -1) {
- return newLoc;
- }
- *errorCodePtr = errno;
- return -1;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_PidObjCmd --
- *
- * This procedure is invoked to process the "pid" Tcl command.
- * See the user documentation for details on what it does.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * See the user documentation.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
-int
-Tcl_PidObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST *objv; /* Argument strings. */
-{
- ProcessSerialNumber psn;
- char buf[20];
- Tcl_Channel chan;
- Tcl_Obj *resultPtr;
-
- if (objc > 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "?channelId?");
- return TCL_ERROR;
- }
- if (objc == 1) {
- resultPtr = Tcl_GetObjResult(interp);
- GetCurrentProcess(&psn);
- sprintf(buf, "0x%08x%08x", psn.highLongOfPSN, psn.lowLongOfPSN);
- Tcl_SetStringObj(resultPtr, buf, -1);
- } else {
- chan = Tcl_GetChannel(interp, Tcl_GetString(objv[1]),
- NULL);
- if (chan == (Tcl_Channel) NULL) {
- return TCL_ERROR;
- }
- /*
- * We can't create pipelines on the Mac so
- * this will always return an empty list.
- */
- }
-
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpGetDefaultStdChannel --
- *
- * Constructs a channel for the specified standard OS handle.
- *
- * Results:
- * Returns the specified default standard channel, or NULL.
- *
- * Side effects:
- * May cause the creation of a standard channel and the underlying
- * file.
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_Channel
-TclpGetDefaultStdChannel(
- int type) /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR. */
-{
- Tcl_Channel channel = NULL;
- int fd = 0; /* Initializations needed to prevent */
- int mode = 0; /* compiler warning (used before set). */
- char *bufMode = NULL;
- char channelName[16 + TCL_INTEGER_SPACE];
- int channelPermissions;
- FileState *fileState;
-
- /*
- * If the channels were not created yet, create them now and
- * store them in the static variables.
- */
-
- switch (type) {
- case TCL_STDIN:
- fd = 0;
- channelPermissions = TCL_READABLE;
- bufMode = "line";
- break;
- case TCL_STDOUT:
- fd = 1;
- channelPermissions = TCL_WRITABLE;
- bufMode = "line";
- break;
- case TCL_STDERR:
- fd = 2;
- channelPermissions = TCL_WRITABLE;
- bufMode = "none";
- break;
- default:
- panic("TclGetDefaultStdChannel: Unexpected channel type");
- break;
- }
-
- sprintf(channelName, "console%d", (int) fd);
- fileState = (FileState *) ckalloc((unsigned) sizeof(FileState));
- channel = Tcl_CreateChannel(&consoleChannelType, channelName,
- (ClientData) fileState, channelPermissions);
- fileState->fileChan = channel;
- fileState->fileRef = fd;
-
- /*
- * Set up the normal channel options for stdio handles.
- */
-
- Tcl_SetChannelOption(NULL, channel, "-translation", "cr");
- Tcl_SetChannelOption(NULL, channel, "-buffering", bufMode);
-
- return channel;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpOpenFileChannel --
- *
- * Open a File based channel on MacOS systems.
- *
- * Results:
- * The new channel or NULL. If NULL, the output argument
- * errorCodePtr is set to a POSIX error.
- *
- * Side effects:
- * May open the channel and may cause creation of a file on the
- * file system.
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_Channel
-TclpOpenFileChannel(
- Tcl_Interp *interp, /* Interpreter for error reporting;
- * can be NULL. */
- Tcl_Obj *pathPtr, /* Name of file to open. */
- int mode, /* POSIX open mode. */
- int permissions) /* If the open involves creating a
- * file, with what modes to create
- * it? */
-{
- Tcl_Channel chan;
- CONST char *native;
- int errorCode;
-
- native = Tcl_FSGetNativePath(pathPtr);
- if (native == NULL) {
- return NULL;
- }
- chan = OpenFileChannel(native, mode, permissions, &errorCode);
-
- if (chan == NULL) {
- Tcl_SetErrno(errorCode);
- if (interp != (Tcl_Interp *) NULL) {
- Tcl_AppendResult(interp, "couldn't open \"",
- Tcl_GetString(pathPtr), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
- }
- return NULL;
- }
-
- return chan;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * OpenFileChannel--
- *
- * Opens a Macintosh file and creates a Tcl channel to control it.
- *
- * Results:
- * A Tcl channel.
- *
- * Side effects:
- * Will open a Macintosh file.
- *
- *----------------------------------------------------------------------
- */
-
-static Tcl_Channel
-OpenFileChannel(
- CONST char *fileName, /* Name of file to open (native). */
- int mode, /* Mode for opening file. */
- int permissions, /* If the open involves creating a
- * file, with what modes to create
- * it? */
- int *errorCodePtr) /* Where to store error code. */
-{
- int channelPermissions;
- Tcl_Channel chan;
- char macPermision;
- FSSpec fileSpec;
- OSErr err;
- short fileRef;
- FileState *fileState;
- char channelName[16 + TCL_INTEGER_SPACE];
- ThreadSpecificData *tsdPtr;
-
- tsdPtr = FileInit();
-
- /*
- * Note we use fsRdWrShPerm instead of fsRdWrPerm which allows shared
- * writes on a file. This isn't common on a mac but is common with
- * Windows and UNIX and the feature is used by Tcl.
- */
-
- switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) {
- case O_RDWR:
- channelPermissions = (TCL_READABLE | TCL_WRITABLE);
- macPermision = fsRdWrShPerm;
- break;
- case O_WRONLY:
- /*
- * Mac's fsRdPerm permission actually defaults to fsRdWrPerm because
- * the Mac OS doesn't realy support write only access. We explicitly
- * set the permission fsRdWrShPerm so that we can have shared write
- * access.
- */
- channelPermissions = TCL_WRITABLE;
- macPermision = fsRdWrShPerm;
- break;
- case O_RDONLY:
- default:
- channelPermissions = TCL_READABLE;
- macPermision = fsRdPerm;
- break;
- }
-
- err = FSpLocationFromPath(strlen(fileName), fileName, &fileSpec);
- if ((err != noErr) && (err != fnfErr)) {
- *errorCodePtr = errno = TclMacOSErrorToPosixError(err);
- Tcl_SetErrno(errno);
- return NULL;
- }
-
- if ((err == fnfErr) && (mode & O_CREAT)) {
- err = HCreate(fileSpec.vRefNum, fileSpec.parID, fileSpec.name, TCL_FILE_CREATOR, 'TEXT');
- if (err != noErr) {
- *errorCodePtr = errno = TclMacOSErrorToPosixError(err);
- Tcl_SetErrno(errno);
- return NULL;
- }
- } else if ((mode & O_CREAT) && (mode & O_EXCL)) {
- *errorCodePtr = errno = EEXIST;
- Tcl_SetErrno(errno);
- return NULL;
- }
-
- err = HOpenDF(fileSpec.vRefNum, fileSpec.parID, fileSpec.name, macPermision, &fileRef);
- if (err != noErr) {
- *errorCodePtr = errno = TclMacOSErrorToPosixError(err);
- Tcl_SetErrno(errno);
- return NULL;
- }
-
- if (mode & O_TRUNC) {
- SetEOF(fileRef, 0);
- }
-
- sprintf(channelName, "file%d", (int) fileRef);
- fileState = (FileState *) ckalloc((unsigned) sizeof(FileState));
- chan = Tcl_CreateChannel(&fileChannelType, channelName,
- (ClientData) fileState, channelPermissions);
- if (chan == (Tcl_Channel) NULL) {
- *errorCodePtr = errno = EFAULT;
- Tcl_SetErrno(errno);
- FSClose(fileRef);
- ckfree((char *) fileState);
- return NULL;
- }
-
- fileState->fileChan = chan;
- fileState->nextPtr = tsdPtr->firstFilePtr;
- tsdPtr->firstFilePtr = fileState;
- fileState->volumeRef = fileSpec.vRefNum;
- fileState->fileRef = fileRef;
- fileState->pending = 0;
- fileState->watchMask = 0;
- if (mode & O_APPEND) {
- fileState->appendMode = true;
- } else {
- fileState->appendMode = false;
- }
-
- if ((mode & O_APPEND) || (mode & O_APPEND)) {
- if (Tcl_Seek(chan, 0, SEEK_END) < 0) {
- *errorCodePtr = errno = EFAULT;
- Tcl_SetErrno(errno);
- Tcl_Close(NULL, chan);
- FSClose(fileRef);
- ckfree((char *) fileState);
- return NULL;
- }
- }
-
- return chan;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_MakeFileChannel --
- *
- * Makes a Tcl_Channel from an existing OS level file handle.
- *
- * Results:
- * The Tcl_Channel created around the preexisting OS level file handle.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_Channel
-Tcl_MakeFileChannel(handle, mode)
- ClientData handle; /* OS level handle. */
- int mode; /* ORed combination of TCL_READABLE and
- * TCL_WRITABLE to indicate file mode. */
-{
- /*
- * Not implemented yet.
- */
-
- return NULL;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * FileBlockMode --
- *
- * Set blocking or non-blocking mode on channel. Macintosh files
- * can never really be set to blocking or non-blocking modes.
- * However, we don't generate an error - we just return success.
- *
- * Results:
- * 0 if successful, errno when failed.
- *
- * Side effects:
- * Sets the device into blocking or non-blocking mode.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-FileBlockMode(
- ClientData instanceData, /* Unused. */
- int mode) /* The mode to set. */
-{
- return 0;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * FileClose --
- *
- * Closes the IO channel.
- *
- * Results:
- * 0 if successful, the value of errno if failed.
- *
- * Side effects:
- * Closes the physical channel
- *
- *----------------------------------------------------------------------
- */
-
-static int
-FileClose(
- ClientData instanceData, /* Unused. */
- Tcl_Interp *interp) /* Unused. */
-{
- FileState *fileState = (FileState *) instanceData;
- int errorCode = 0;
- OSErr err;
-
- err = FSClose(fileState->fileRef);
- FlushVol(NULL, fileState->volumeRef);
- if (err != noErr) {
- errorCode = errno = TclMacOSErrorToPosixError(err);
- panic("error during file close");
- }
-
- ckfree((char *) fileState);
- Tcl_SetErrno(errorCode);
- return errorCode;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * FileInput --
- *
- * Reads input from the IO channel into the buffer given. Returns
- * count of how many bytes were actually read, and an error indication.
- *
- * Results:
- * A count of how many bytes were read is returned and an error
- * indication is returned in an output argument.
- *
- * Side effects:
- * Reads input from the actual channel.
- *
- *----------------------------------------------------------------------
- */
-
-int
-FileInput(
- ClientData instanceData, /* Unused. */
- char *buffer, /* Where to store data read. */
- int bufSize, /* How much space is available
- * in the buffer? */
- int *errorCodePtr) /* Where to store error code. */
-{
- FileState *fileState = (FileState *) instanceData;
- OSErr err;
- long length = bufSize;
-
- *errorCodePtr = 0;
- errno = 0;
- err = FSRead(fileState->fileRef, &length, buffer);
- if ((err == noErr) || (err == eofErr)) {
- return length;
- } else {
- switch (err) {
- case ioErr:
- *errorCodePtr = errno = EIO;
- case afpAccessDenied:
- *errorCodePtr = errno = EACCES;
- default:
- *errorCodePtr = errno = EINVAL;
- }
- return -1;
- }
- *errorCodePtr = errno;
- return -1;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * FileOutput--
- *
- * Writes the given output on the IO channel. Returns count of how
- * many characters were actually written, and an error indication.
- *
- * Results:
- * A count of how many characters were written is returned and an
- * error indication is returned in an output argument.
- *
- * Side effects:
- * Writes output on the actual channel.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-FileOutput(
- ClientData instanceData, /* Unused. */
- CONST char *buffer, /* The data buffer. */
- int toWrite, /* How many bytes to write? */
- int *errorCodePtr) /* Where to store error code. */
-{
- FileState *fileState = (FileState *) instanceData;
- long length = toWrite;
- OSErr err;
-
- *errorCodePtr = 0;
- errno = 0;
-
- if (fileState->appendMode == true) {
- FileSeek(instanceData, 0, SEEK_END, errorCodePtr);
- *errorCodePtr = 0;
- }
-
- err = FSWrite(fileState->fileRef, &length, buffer);
- if (err == noErr) {
- err = FlushFile(fileState->fileRef);
- } else {
- *errorCodePtr = errno = TclMacOSErrorToPosixError(err);
- return -1;
- }
- return length;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * FileSeek --
- *
- * Seeks on an IO channel. Returns the new position.
- *
- * Results:
- * -1 if failed, the new position if successful. If failed, it
- * also sets *errorCodePtr to the error code.
- *
- * Side effects:
- * Moves the location at which the channel will be accessed in
- * future operations.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-FileSeek(
- ClientData instanceData, /* Unused. */
- long offset, /* Offset to seek to. */
- int mode, /* Relative to where should we seek? */
- int *errorCodePtr) /* To store error code. */
-{
- FileState *fileState = (FileState *) instanceData;
- IOParam pb;
- OSErr err;
-
- *errorCodePtr = 0;
- pb.ioCompletion = NULL;
- pb.ioRefNum = fileState->fileRef;
- if (mode == SEEK_SET) {
- pb.ioPosMode = fsFromStart;
- } else if (mode == SEEK_END) {
- pb.ioPosMode = fsFromLEOF;
- } else if (mode == SEEK_CUR) {
- err = PBGetFPosSync((ParmBlkPtr) &pb);
- if (pb.ioResult == noErr) {
- if (offset == 0) {
- return pb.ioPosOffset;
- }
- offset += pb.ioPosOffset;
- }
- pb.ioPosMode = fsFromStart;
- }
- pb.ioPosOffset = offset;
- err = PBSetFPosSync((ParmBlkPtr) &pb);
- if (pb.ioResult == noErr){
- return pb.ioPosOffset;
- } else if (pb.ioResult == eofErr) {
- long currentEOF, newEOF;
- long buffer, i, length;
-
- err = PBGetEOFSync((ParmBlkPtr) &pb);
- currentEOF = (long) pb.ioMisc;
- if (mode == SEEK_SET) {
- newEOF = offset;
- } else if (mode == SEEK_END) {
- newEOF = offset + currentEOF;
- } else if (mode == SEEK_CUR) {
- err = PBGetFPosSync((ParmBlkPtr) &pb);
- newEOF = offset + pb.ioPosOffset;
- }
-
- /*
- * Write 0's to the new EOF.
- */
- pb.ioPosOffset = 0;
- pb.ioPosMode = fsFromLEOF;
- err = PBGetFPosSync((ParmBlkPtr) &pb);
- length = 1;
- buffer = 0;
- for (i = 0; i < (newEOF - currentEOF); i++) {
- err = FSWrite(fileState->fileRef, &length, &buffer);
- }
- err = PBGetFPosSync((ParmBlkPtr) &pb);
- if (pb.ioResult == noErr){
- return pb.ioPosOffset;
- }
- }
- *errorCodePtr = errno = TclMacOSErrorToPosixError(err);
- return -1;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * CommonWatch --
- *
- * Initialize the notifier to watch handles from this channel.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-CommonWatch(
- ClientData instanceData, /* The file state. */
- int mask) /* Events of interest; an OR-ed
- * combination of TCL_READABLE,
- * TCL_WRITABLE and TCL_EXCEPTION. */
-{
- FileState *infoPtr = (FileState *) instanceData;
- Tcl_Time blockTime = { 0, 0 };
-
- infoPtr->watchMask = mask;
- if (infoPtr->watchMask) {
- Tcl_SetMaxBlockTime(&blockTime);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * FileThreadActionProc --
- *
- * Insert or remove any thread local refs to this channel.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Changes thread local list of valid channels.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-FileThreadActionProc (instanceData, action)
- ClientData instanceData;
- int action;
-{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- FileState *infoPtr = (FileState *) instanceData;
-
- if (action == TCL_CHANNEL_THREAD_INSERT) {
- infoPtr->nextPtr = tsdPtr->firstFilePtr;
- tsdPtr->firstFilePtr = infoPtr;
- } else {
- FileState **nextPtrPtr;
- int removed = 0;
-
- for (nextPtrPtr = &(tsdPtr->firstFilePtr); (*nextPtrPtr) != NULL;
- nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {
- if ((*nextPtrPtr) == infoPtr) {
- (*nextPtrPtr) = infoPtr->nextPtr;
- removed = 1;
- break;
- }
- }
-
- /*
- * This could happen if the channel was created in one thread
- * and then moved to another without updating the thread
- * local data in each thread.
- */
-
- if (!removed) {
- panic("file info ptr not on thread channel list");
- }
- }
-}
diff --git a/mac/tclMacCommonPch.h b/mac/tclMacCommonPch.h
deleted file mode 100755
index a183f36..0000000
--- a/mac/tclMacCommonPch.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * tclMacCommonPch.h --
- *
- * Macintosh Tcl must be compiled with certain compiler options to
- * ensure that it will work correctly. The following pragmas are
- * used to ensure that those options are set correctly. An error
- * will occur at compile time if they are not set correctly.
- *
- * Copyright (c) 1998 by Scriptics Corporation.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#if !__option(enumsalwaysint)
-#error Tcl requires the Metrowerks setting "Enums always ints".
-#endif
-
-
-#if !defined(__POWERPC__)
-#if !__option(far_data)
-#error Tcl requires the Metrowerks setting "Far data".
-#endif
-#endif
-
-
-#if !defined(__POWERPC__)
-#if !__option(fourbyteints)
-#error Tcl requires the Metrowerks setting "4 byte ints".
-#endif
-#endif
-
-
-#if !defined(__POWERPC__)
-#if !__option(IEEEdoubles)
-#error Tcl requires the Metrowerks setting "8 byte doubles".
-#endif
-#endif
-
-
-/*
-* The define is used most everywhere to tell Tcl (or any Tcl
-* extensions) that we are compiling for the Macintosh platform.
-*/
-
-
-#define MAC_TCL
-
-
-/*
-* Define the following symbol if you want
-* comprehensive debugging turned on.
-*/
-
-
-/* #define TCL_DEBUG */
-
-
-#ifdef TCL_DEBUG
-# define TCL_MEM_DEBUG
-# define TCL_TEST
-#endif
-
-
-/*
-* for Metrowerks Pro 6 MSL
-*/
-
-#include <UseDLLPrefix.h>
diff --git a/mac/tclMacDNR.c b/mac/tclMacDNR.c
deleted file mode 100644
index 3631b01..0000000
--- a/mac/tclMacDNR.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * tclMacDNR.c
- *
- * This file actually just includes the file "dnr.c" provided by
- * Apple Computer and redistributed by MetroWerks (and other compiler
- * vendors.) Unfortunantly, despite various bug reports, dnr.c uses
- * C++ style comments and will not compile under the "ANSI Strict"
- * mode that the rest of Tcl compiles under. Furthermore, the Apple
- * license prohibits me from redistributing a corrected version of
- * dnr.c. This file uses a pragma to turn off the Strict ANSI option
- * and then includes the dnr.c file.
- *
- * Copyright (c) 1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#pragma ANSI_strict off
-#include <dnr.c>
-#pragma ANSI_strict reset
diff --git a/mac/tclMacEnv.c b/mac/tclMacEnv.c
deleted file mode 100644
index 9680790..0000000
--- a/mac/tclMacEnv.c
+++ /dev/null
@@ -1,534 +0,0 @@
-/*
- * tclMacEnv.c --
- *
- * Implements the "environment" on a Macintosh.
- *
- * Copyright (c) 1995-1996 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include <Gestalt.h>
-#include <Folders.h>
-#include <TextUtils.h>
-#include <Resources.h>
-#include <string.h>
-
-#include "tcl.h"
-#include "tclInt.h"
-#include "tclMacInt.h"
-#include "tclPort.h"
-
-#define kMaxEnvStringSize 255
-#define kMaxEnvVarSize 100
-#define kLoginnameTag "LOGIN="
-#define kUsernameTag "USER="
-#define kDefaultDirTag "HOME="
-
-/*
- * The following specifies a text file where additional environment variables
- * can be set. The file must reside in the preferences folder. If the file
- * doesn't exist NO error will occur. Commet out the difinition if you do
- * NOT want to use an environment variables file.
- */
-#define kPrefsFile "Tcl Environment Variables"
-
-/*
- * The following specifies the Name of a 'STR#' resource in the application
- * where additional environment variables may be set. If the resource doesn't
- * exist no errors will occur. Commet it out if you don't want it.
- */
-#define REZ_ENV "\pTcl Environment Variables"
-
-/* Globals */
-char **environ = NULL;
-
-/*
- * Declarations for local procedures defined in this file:
- */
-static char ** RezRCVariables _ANSI_ARGS_((void));
-static char ** FileRCVariables _ANSI_ARGS_((void));
-static char ** PathVariables _ANSI_ARGS_((void));
-static char ** SystemVariables _ANSI_ARGS_((void));
-static char * MakeFolderEnvVar _ANSI_ARGS_((char * prefixTag,
- long whichFolder));
-static char * GetUserName _ANSI_ARGS_((void));
-
-/*
- *----------------------------------------------------------------------
- *
- * RezRCVariables --
- *
- * Creates environment variables from the applications resource fork.
- * The function looks for the 'STR#' resource with the name defined
- * in the #define REZ_ENV. If the define is not defined this code
- * will not be included. If the resource doesn't exist or no strings
- * reside in the resource nothing will happen.
- *
- * Results:
- * ptr to value on success, NULL if error.
- *
- * Side effects:
- * Memory is allocated and returned to the caller.
- *
- *----------------------------------------------------------------------
- */
-
-#ifdef REZ_ENV
-static char **
-RezRCVariables()
-{
- Handle envStrs = NULL;
- char** rezEnv = NULL;
- short int numStrs;
-
- envStrs = GetNamedResource('STR#', REZ_ENV);
- if (envStrs == NULL) return NULL;
- numStrs = *((short *) (*envStrs));
-
- rezEnv = (char **) ckalloc((numStrs + 1) * sizeof(char *));
-
- if (envStrs != NULL) {
- ResType theType;
- Str255 theName;
- short theID, index = 1;
- int i = 0;
- char* string;
-
- GetResInfo(envStrs, &theID, &theType, theName);
- for(;;) {
- GetIndString(theName, theID, index++);
- if (theName[0] == '\0') break;
- string = (char *) ckalloc(theName[0] + 2);
- strncpy(string, (char *) theName + 1, theName[0]);
- string[theName[0]] = '\0';
- rezEnv[i++] = string;
- }
- ReleaseResource(envStrs);
-
- rezEnv[i] = NULL;
- return rezEnv;
- }
-
- return NULL;
-}
-#endif
-
-/*
- *----------------------------------------------------------------------
- *
- * FileRCVariables --
- *
- * Creates environment variables from a file in the system preferences
- * folder. The function looks for a file in the preferences folder
- * a name defined in the #define kPrefsFile. If the define is not
- * defined this code will not be included. If the resource doesn't exist or
- * no strings reside in the resource nothing will happen.
- *
- * Results:
- * ptr to value on success, NULL if error.
- *
- * Side effects:
- * Memory is allocated and returned to the caller.
- *
- *----------------------------------------------------------------------
- */
-
-#ifdef kPrefsFile
-static char **
-FileRCVariables()
-{
- char *prefsFolder = NULL;
- char *tempPtr = NULL;
- char **fileEnv = NULL;
- FILE *thePrefsFile = NULL;
- int i;
- FSSpec prefDir;
- OSErr err;
- Handle theString = NULL;
- Tcl_Channel chan;
- int size;
- Tcl_DString lineRead;
-
- err = FSpFindFolder(kOnSystemDisk, kPreferencesFolderType,
- kDontCreateFolder, &prefDir);
- if (err != noErr) {
- return NULL;
- }
- err = FSpPathFromLocation(&prefDir, &size, &theString);
- if (err != noErr) {
- return NULL;
- }
- (void) Munger(theString, size, NULL, 0, kPrefsFile, strlen(kPrefsFile));
-
- HLock(theString);
- chan = Tcl_OpenFileChannel(NULL, *theString, "r", 0);
- HUnlock(theString);
- DisposeHandle(theString);
- if (chan == NULL) {
- return NULL;
- }
-
- /*
- * We found a env file. Let start parsing it.
- */
- fileEnv = (char **) ckalloc((kMaxEnvVarSize + 1) * sizeof(char *));
-
- i = 0;
- Tcl_DStringInit(&lineRead);
- while (Tcl_Gets(chan, &lineRead) != -1) {
- /*
- * First strip off new line char
- */
- if (lineRead.string[lineRead.length-1] == '\n') {
- lineRead.string[lineRead.length-1] = '\0';
- }
- if (lineRead.string[0] == '\0' || lineRead.string[0] == '#') {
- /*
- * skip empty lines or commented lines
- */
- Tcl_DStringSetLength(&lineRead, 0);
- continue;
- }
-
- tempPtr = (char *) ckalloc(lineRead.length + 1);
- strcpy(tempPtr, lineRead.string);
- fileEnv[i++] = tempPtr;
- Tcl_DStringSetLength(&lineRead, 0);
- }
-
- fileEnv[i] = NULL;
- Tcl_Close(NULL, chan);
- Tcl_DStringFree(&lineRead);
-
- return fileEnv;
-}
-#endif
-
-/*
- *----------------------------------------------------------------------
- *
- * MakeFolderEnvVar --
- *
- * This function creates "environment" variable by taking a prefix and
- * appending a folder path to a directory. The directory is specified
- * by a integer value acceptable by the FindFolder function.
- *
- * Results:
- * The function returns an *allocated* string. If the folder doesn't
- * exist the return string is still allocated and just contains the
- * given prefix.
- *
- * Side effects:
- * Memory is allocated and returned to the caller.
- *
- *----------------------------------------------------------------------
- */
-
-static char *
-MakeFolderEnvVar(
- char * prefixTag, /* Prefix added before result. */
- long whichFolder) /* Constant for FSpFindFolder. */
-{
- char * thePath = NULL;
- char * result = NULL;
- OSErr theErr = noErr;
- Handle theString = NULL;
- FSSpec theFolder;
- int size;
- Tcl_DString pathStr;
- Tcl_DString tagPathStr;
-
- Tcl_DStringInit(&pathStr);
- theErr = FSpFindFolder(kOnSystemDisk, whichFolder,
- kDontCreateFolder, &theFolder);
- if (theErr == noErr) {
- theErr = FSpPathFromLocation(&theFolder, &size, &theString);
-
- HLock(theString);
- tclPlatform = TCL_PLATFORM_MAC;
- Tcl_DStringAppend(&pathStr, *theString, -1);
- HUnlock(theString);
- DisposeHandle(theString);
-
- Tcl_DStringInit(&tagPathStr);
- Tcl_DStringAppend(&tagPathStr, prefixTag, strlen(prefixTag));
- Tcl_DStringAppend(&tagPathStr, pathStr.string, pathStr.length);
- Tcl_DStringFree(&pathStr);
-
- /*
- * Make sure the path ends with a ':'
- */
- if (tagPathStr.string[tagPathStr.length - 1] != ':') {
- Tcl_DStringAppend(&tagPathStr, ":", 1);
- }
-
- /*
- * Don't free tagPathStr - rather make sure it's allocated
- * and return it as the result.
- */
- if (tagPathStr.string == tagPathStr.staticSpace) {
- result = (char *) ckalloc(tagPathStr.length + 1);
- strcpy(result, tagPathStr.string);
- } else {
- result = tagPathStr.string;
- }
- } else {
- result = (char *) ckalloc(strlen(prefixTag) + 1);
- strcpy(result, prefixTag);
- }
-
- return result;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * PathVariables --
- *
- * Creates environment variables from the system call FSpFindFolder.
- * The function generates environment variables for many of the
- * commonly used paths on the Macintosh.
- *
- * Results:
- * ptr to value on success, NULL if error.
- *
- * Side effects:
- * Memory is allocated and returned to the caller.
- *
- *----------------------------------------------------------------------
- */
-
-static char **
-PathVariables()
-{
- int i = 0;
- char **sysEnv;
- char *thePath = NULL;
-
- sysEnv = (char **) ckalloc((12) * sizeof(char *));
-
- sysEnv[i++] = MakeFolderEnvVar("PREF_FOLDER=", kPreferencesFolderType);
- sysEnv[i++] = MakeFolderEnvVar("SYS_FOLDER=", kSystemFolderType);
- sysEnv[i++] = MakeFolderEnvVar("TEMP=", kTemporaryFolderType);
- sysEnv[i++] = MakeFolderEnvVar("APPLE_M_FOLDER=", kAppleMenuFolderType);
- sysEnv[i++] = MakeFolderEnvVar("CP_FOLDER=", kControlPanelFolderType);
- sysEnv[i++] = MakeFolderEnvVar("DESK_FOLDER=", kDesktopFolderType);
- sysEnv[i++] = MakeFolderEnvVar("EXT_FOLDER=", kExtensionFolderType);
- sysEnv[i++] = MakeFolderEnvVar("PRINT_MON_FOLDER=",
- kPrintMonitorDocsFolderType);
- sysEnv[i++] = MakeFolderEnvVar("SHARED_TRASH_FOLDER=",
- kWhereToEmptyTrashFolderType);
- sysEnv[i++] = MakeFolderEnvVar("TRASH_FOLDER=", kTrashFolderType);
- sysEnv[i++] = MakeFolderEnvVar("START_UP_FOLDER=", kStartupFolderType);
- sysEnv[i++] = NULL;
-
- return sysEnv;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * SystemVariables --
- *
- * Creates environment variables from various Mac system calls.
- *
- * Results:
- * ptr to value on success, NULL if error.
- *
- * Side effects:
- * Memory is allocated and returned to the caller.
- *
- *----------------------------------------------------------------------
- */
-
-static char **
-SystemVariables()
-{
- int i = 0;
- char ** sysEnv;
- char * thePath = NULL;
- Handle theString = NULL;
- FSSpec currentDir;
- int size;
-
- sysEnv = (char **) ckalloc((4) * sizeof(char *));
-
- /*
- * Get user name from chooser. It will be assigned to both
- * the USER and LOGIN environment variables.
- */
- thePath = GetUserName();
- if (thePath != NULL) {
- sysEnv[i] = (char *) ckalloc(strlen(kLoginnameTag) + strlen(thePath) + 1);
- strcpy(sysEnv[i], kLoginnameTag);
- strcpy(sysEnv[i]+strlen(kLoginnameTag), thePath);
- i++;
- sysEnv[i] = (char *) ckalloc(strlen(kUsernameTag) + strlen(thePath) + 1);
- strcpy(sysEnv[i], kUsernameTag);
- strcpy(sysEnv[i]+strlen(kUsernameTag), thePath);
- i++;
- }
-
- /*
- * Get 'home' directory
- */
-#ifdef kDefaultDirTag
- FSpGetDefaultDir(&currentDir);
- FSpPathFromLocation(&currentDir, &size, &theString);
- HLock(theString);
- sysEnv[i] = (char *) ckalloc(strlen(kDefaultDirTag) + size + 4);
- strcpy(sysEnv[i], kDefaultDirTag);
- strncpy(sysEnv[i]+strlen(kDefaultDirTag) , *theString, size);
- if (sysEnv[i][strlen(kDefaultDirTag) + size - 1] != ':') {
- sysEnv[i][strlen(kDefaultDirTag) + size] = ':';
- sysEnv[i][strlen(kDefaultDirTag) + size + 1] = '\0';
- } else {
- sysEnv[i][strlen(kDefaultDirTag) + size] = '\0';
- }
- HUnlock(theString);
- DisposeHandle(theString);
- i++;
-#endif
-
- sysEnv[i++] = NULL;
- return sysEnv;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclMacCreateEnv --
- *
- * This function allocates and populates the global "environ"
- * variable. Entries are in traditional Unix format but variables
- * are, hopefully, a bit more relevant for the Macintosh.
- *
- * Results:
- * The number of elements in the newly created environ array.
- *
- * Side effects:
- * Memory is allocated and pointed too by the environ variable.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclMacCreateEnv()
-{
- char ** sysEnv = NULL;
- char ** pathEnv = NULL;
- char ** fileEnv = NULL;
- char ** rezEnv = NULL;
- int count = 0;
- int i, j;
-
- sysEnv = SystemVariables();
- if (sysEnv != NULL) {
- for (i = 0; sysEnv[i] != NULL; count++, i++) {
- /* Empty Loop */
- }
- }
-
- pathEnv = PathVariables();
- if (pathEnv != NULL) {
- for (i = 0; pathEnv[i] != NULL; count++, i++) {
- /* Empty Loop */
- }
- }
-
-#ifdef kPrefsFile
- fileEnv = FileRCVariables();
- if (fileEnv != NULL) {
- for (i = 0; fileEnv[i] != NULL; count++, i++) {
- /* Empty Loop */
- }
- }
-#endif
-
-#ifdef REZ_ENV
- rezEnv = RezRCVariables();
- if (rezEnv != NULL) {
- for (i = 0; rezEnv[i] != NULL; count++, i++) {
- /* Empty Loop */
- }
- }
-#endif
-
- /*
- * Create environ variable
- */
- environ = (char **) ckalloc((count + 1) * sizeof(char *));
- j = 0;
-
- if (sysEnv != NULL) {
- for (i = 0; sysEnv[i] != NULL;)
- environ[j++] = sysEnv[i++];
- ckfree((char *) sysEnv);
- }
-
- if (pathEnv != NULL) {
- for (i = 0; pathEnv[i] != NULL;)
- environ[j++] = pathEnv[i++];
- ckfree((char *) pathEnv);
- }
-
-#ifdef kPrefsFile
- if (fileEnv != NULL) {
- for (i = 0; fileEnv[i] != NULL;)
- environ[j++] = fileEnv[i++];
- ckfree((char *) fileEnv);
- }
-#endif
-
-#ifdef REZ_ENV
- if (rezEnv != NULL) {
- for (i = 0; rezEnv[i] != NULL;)
- environ[j++] = rezEnv[i++];
- ckfree((char *) rezEnv);
- }
-#endif
-
- environ[j] = NULL;
- return j;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * GetUserName --
- *
- * Get the user login name.
- *
- * Results:
- * ptr to static string, NULL if error.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static char *
-GetUserName()
-{
- static char buf[33];
- short refnum;
- Handle h;
-
- refnum = CurResFile();
- UseResFile(0);
- h = GetResource('STR ', -16096);
- UseResFile(refnum);
- if (h == NULL) {
- return NULL;
- }
-
- HLock(h);
- strncpy(buf, (*h)+1, **h);
- buf[**h] = '\0';
- HUnlock(h);
- ReleaseResource(h);
- return(buf[0] ? buf : NULL);
-}
diff --git a/mac/tclMacExit.c b/mac/tclMacExit.c
deleted file mode 100644
index b71a12e..0000000
--- a/mac/tclMacExit.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * tclMacExit.c --
- *
- * This file contains routines that deal with cleaning up various state
- * when Tcl/Tk applications quit. Unfortunantly, not all state is cleaned
- * up by the process when an application quites or crashes. Also you
- * need to do different things depending on wether you are running as
- * 68k code, PowerPC, or a code resource. The Exit handler code was
- * adapted from code posted on alt.sources.mac by Dave Nebinger.
- *
- * Copyright (c) 1995 Dave Nebinger.
- * Copyright (c) 1995-1996 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include "tclInt.h"
-#include "tclMacInt.h"
-#include <SegLoad.h>
-#include <Traps.h>
-#include <Processes.h>
-
-/*
- * Various typedefs and defines needed to patch ExitToShell.
- */
-
-enum {
- uppExitToShellProcInfo = kPascalStackBased
-};
-
-#if GENERATINGCFM
-typedef UniversalProcPtr ExitToShellUPP;
-
-#define CallExitToShellProc(userRoutine) \
- CallUniversalProc((UniversalProcPtr)(userRoutine),uppExitToShellProcInfo)
-#define NewExitToShellProc(userRoutine) \
- (ExitToShellUPP)NewRoutineDescriptor((ProcPtr)(userRoutine), \
- uppExitToShellProcInfo, GetCurrentArchitecture())
-
-#else
-typedef ExitToShellProcPtr ExitToShellUPP;
-
-#define CallExitToShellProc(userRoutine) \
- (*(userRoutine))()
-#define NewExitToShellProc(userRoutine) \
- (ExitToShellUPP)(userRoutine)
-#endif
-
-#define DisposeExitToShellProc(userRoutine) \
- DisposeRoutineDescriptor(userRoutine)
-
-#if defined(powerc)||defined(__powerc)
-#pragma options align=mac68k
-#endif
-struct ExitToShellUPPList{
- struct ExitToShellUPPList* nextProc;
- ExitToShellUPP userProc;
-};
-#if defined(powerc)||defined(__powerc)
-#pragma options align=reset
-#endif
-
-typedef struct ExitToShellDataStruct ExitToShellDataRec,* ExitToShellDataPtr,** ExitToShellDataHdl;
-
-typedef struct ExitToShellUPPList ExitToShellUPPList,* ExitToShellUPPListPtr,** ExitToShellUPPHdl;
-
-#if defined(powerc)||defined(__powerc)
-#pragma options align=mac68k
-#endif
-struct ExitToShellDataStruct{
- unsigned long a5;
- ExitToShellUPPList* userProcs;
- ExitToShellUPP oldProc;
-};
-#if defined(powerc)||defined(__powerc)
-#pragma options align=reset
-#endif
-
-/*
- * Static globals used within this file.
- */
-static ExitToShellDataPtr gExitToShellData = (ExitToShellDataPtr) NULL;
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TclPlatformExit --
- *
- * This procedure implements the Macintosh specific exit routine.
- * We explicitly callthe ExitHandler function to do various clean
- * up.
- *
- * Results:
- * None.
- *
- * Side effects:
- * We exit the process.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpExit(
- int status) /* Ignored. */
-{
- TclMacExitHandler();
-
-/*
- * If we are using the Metrowerks Standard Library, then we will call its exit so that it
- * will get a chance to clean up temp files, and so forth. It always calls the standard
- * ExitToShell, so the Tcl handlers will also get called.
- *
- * If you have another exit, make sure that it does not patch ExitToShell, and does
- * call it. If so, it will probably work as well.
- *
- */
-
-#ifdef __MSL__
- exit(status);
-#else
- ExitToShell();
-#endif
-
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclMacExitHandler --
- *
- * This procedure is invoked after Tcl at the last possible moment
- * to clean up any state Tcl has left around that may cause other
- * applications to crash. For example, this function can be used
- * as the termination routine for CFM applications.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Various cleanup occurs.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclMacExitHandler()
-{
- ExitToShellUPPListPtr curProc;
-
- /*
- * Loop through all installed Exit handlers
- * and call them. Always make sure we are in
- * a clean state in case we are recursivly called.
- */
- if ((gExitToShellData) != NULL && (gExitToShellData->userProcs != NULL)){
-
- /*
- * Call the installed exit to shell routines.
- */
- curProc = gExitToShellData->userProcs;
- do {
- gExitToShellData->userProcs = curProc->nextProc;
- CallExitToShellProc(curProc->userProc);
- DisposeExitToShellProc(curProc->userProc);
- DisposePtr((Ptr) curProc);
- curProc = gExitToShellData->userProcs;
- } while (curProc != (ExitToShellUPPListPtr) NULL);
- }
-
- return;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclMacInstallExitToShellPatch --
- *
- * This procedure installs a way to clean up state at the latest
- * possible moment before we exit. These are things that must
- * be cleaned up or the system will crash. The exact way in which
- * this is implemented depends on the architecture in which we are
- * running. For 68k applications we patch the ExitToShell call.
- * For PowerPC applications we just create a list of procs to call.
- * The function ExitHandler should be installed in the Code
- * Fragments terminiation routine.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Installs the new routine.
- *
- *----------------------------------------------------------------------
- */
-
-OSErr
-TclMacInstallExitToShellPatch(
- ExitToShellProcPtr newProc) /* Function pointer. */
-{
- ExitToShellUPP exitHandler;
- ExitToShellUPPListPtr listPtr;
-
- if (gExitToShellData == (ExitToShellDataPtr) NULL){
- TclMacInitExitToShell(true);
- }
-
- /*
- * Add the passed in function pointer to the list of functions
- * to be called when ExitToShell is called.
- */
- exitHandler = NewExitToShellProc(newProc);
- listPtr = (ExitToShellUPPListPtr) NewPtrClear(sizeof(ExitToShellUPPList));
- listPtr->userProc = exitHandler;
- listPtr->nextProc = gExitToShellData->userProcs;
- gExitToShellData->userProcs = listPtr;
-
- return noErr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ExitToShellPatchRoutine --
- *
- * This procedure is invoked when someone calls ExitToShell for
- * this application. This function performs some last miniute
- * clean up and then calls the real ExitToShell routine.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Various cleanup occurs.
- *
- *----------------------------------------------------------------------
- */
-
-static pascal void
-ExitToShellPatchRoutine()
-{
- ExitToShellUPP oldETS;
- long oldA5;
-
- /*
- * Set up our A5 world. This allows us to have
- * access to our global variables in the 68k world.
- */
- oldA5 = SetCurrentA5();
- SetA5(gExitToShellData->a5);
-
- /*
- * Call the function that invokes all
- * of the handlers.
- */
- TclMacExitHandler();
-
- /*
- * Call the origional ExitToShell routine.
- */
- oldETS = gExitToShellData->oldProc;
- DisposePtr((Ptr) gExitToShellData);
- SetA5(oldA5);
- CallExitToShellProc(oldETS);
- return;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclMacInitExitToShell --
- *
- * This procedure initializes the ExitToShell clean up machanism.
- * Generally, this is handled automatically when users make a call
- * to InstallExitToShellPatch. However, it can be called
- * explicitly at startup time to turn off the patching mechanism.
- * This can be used by code resources which could be removed from
- * the application before ExitToShell is called.
- *
- * Note, if we are running from CFM code we never install the
- * patch. Instead, the function ExitHandler should be installed
- * as the terminiation routine for the code fragment.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Creates global state.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclMacInitExitToShell(
- int usePatch) /* True if on 68k. */
-{
- if (gExitToShellData == (ExitToShellDataPtr) NULL){
-#if GENERATINGCFM
- gExitToShellData = (ExitToShellDataPtr)
- NewPtr(sizeof(ExitToShellDataRec));
- gExitToShellData->a5 = SetCurrentA5();
- gExitToShellData->userProcs = (ExitToShellUPPList*) NULL;
-#else
- ExitToShellUPP oldExitToShell, newExitToShellPatch;
- short exitToShellTrap;
-
- /*
- * Initialize patch mechanism.
- */
-
- gExitToShellData = (ExitToShellDataPtr) NewPtr(sizeof(ExitToShellDataRec));
- gExitToShellData->a5 = SetCurrentA5();
- gExitToShellData->userProcs = (ExitToShellUPPList*) NULL;
-
- /*
- * Save state needed to call origional ExitToShell routine. Install
- * the new ExitToShell code in it's place.
- */
- if (usePatch) {
- exitToShellTrap = _ExitToShell & 0x3ff;
- newExitToShellPatch = NewExitToShellProc(ExitToShellPatchRoutine);
- oldExitToShell = (ExitToShellUPP)
- NGetTrapAddress(exitToShellTrap, ToolTrap);
- NSetTrapAddress((UniversalProcPtr) newExitToShellPatch,
- exitToShellTrap, ToolTrap);
- gExitToShellData->oldProc = oldExitToShell;
- }
-#endif
- }
-}
diff --git a/mac/tclMacFCmd.c b/mac/tclMacFCmd.c
deleted file mode 100644
index fddffce..0000000
--- a/mac/tclMacFCmd.c
+++ /dev/null
@@ -1,1650 +0,0 @@
-/*
- * tclMacFCmd.c --
- *
- * Implements the Macintosh specific portions of the file manipulation
- * subcommands of the "file" command.
- *
- * Copyright (c) 1996-1998 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include "tclInt.h"
-#include "tclMac.h"
-#include "tclMacInt.h"
-#include "tclPort.h"
-#include <FSpCompat.h>
-#include <MoreFilesExtras.h>
-#include <Strings.h>
-#include <Errors.h>
-#include <FileCopy.h>
-#include <DirectoryCopy.h>
-#include <Script.h>
-#include <string.h>
-#include <Finder.h>
-#include <Aliases.h>
-
-/*
- * Callback for the file attributes code.
- */
-
-static int GetFileFinderAttributes _ANSI_ARGS_((Tcl_Interp *interp,
- int objIndex, Tcl_Obj *fileName,
- Tcl_Obj **attributePtrPtr));
-static int GetFileReadOnly _ANSI_ARGS_((Tcl_Interp *interp,
- int objIndex, Tcl_Obj *fileName,
- Tcl_Obj **readOnlyPtrPtr));
-static int SetFileFinderAttributes _ANSI_ARGS_((Tcl_Interp *interp,
- int objIndex, Tcl_Obj *fileName,
- Tcl_Obj *attributePtr));
-static int SetFileReadOnly _ANSI_ARGS_((Tcl_Interp *interp,
- int objIndex, Tcl_Obj *fileName,
- Tcl_Obj *readOnlyPtr));
-
-/*
- * These are indeces into the tclpFileAttrsStrings table below.
- */
-
-#define MAC_CREATOR_ATTRIBUTE 0
-#define MAC_HIDDEN_ATTRIBUTE 1
-#define MAC_READONLY_ATTRIBUTE 2
-#define MAC_TYPE_ATTRIBUTE 3
-
-/*
- * Global variables for the file attributes code.
- */
-
-CONST char *tclpFileAttrStrings[] = {"-creator", "-hidden", "-readonly",
- "-type", (char *) NULL};
-CONST TclFileAttrProcs tclpFileAttrProcs[] = {
- {GetFileFinderAttributes, SetFileFinderAttributes},
- {GetFileFinderAttributes, SetFileFinderAttributes},
- {GetFileReadOnly, SetFileReadOnly},
- {GetFileFinderAttributes, SetFileFinderAttributes}};
-
-/*
- * File specific static data
- */
-
-static long startSeed = 248923489;
-
-/*
- * Prototypes for procedure only used in this file
- */
-
-static pascal Boolean CopyErrHandler _ANSI_ARGS_((OSErr error,
- short failedOperation,
- short srcVRefNum, long srcDirID,
- ConstStr255Param srcName, short dstVRefNum,
- long dstDirID,ConstStr255Param dstName));
-static int DoCopyDirectory _ANSI_ARGS_((CONST char *src,
- CONST char *dst, Tcl_DString *errorPtr));
-static int DoCopyFile _ANSI_ARGS_((CONST char *src,
- CONST char *dst));
-static int DoCreateDirectory _ANSI_ARGS_((CONST char *path));
-static int DoRemoveDirectory _ANSI_ARGS_((CONST char *path,
- int recursive, Tcl_DString *errorPtr));
-static int DoRenameFile _ANSI_ARGS_((CONST char *src,
- CONST char *dst));
-OSErr FSpGetFLockCompat _ANSI_ARGS_((const FSSpec *specPtr,
- Boolean *lockedPtr));
-static OSErr GetFileSpecs _ANSI_ARGS_((CONST char *path,
- FSSpec *pathSpecPtr, FSSpec *dirSpecPtr,
- Boolean *pathExistsPtr,
- Boolean *pathIsDirectoryPtr));
-static OSErr MoveRename _ANSI_ARGS_((const FSSpec *srcSpecPtr,
- const FSSpec *dstSpecPtr, StringPtr copyName));
-static int Pstrequal _ANSI_ARGS_((ConstStr255Param stringA,
- ConstStr255Param stringB));
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclpObjRenameFile, DoRenameFile --
- *
- * Changes the name of an existing file or directory, from src to dst.
- * If src and dst refer to the same file or directory, does nothing
- * and returns success. Otherwise if dst already exists, it will be
- * deleted and replaced by src subject to the following conditions:
- * If src is a directory, dst may be an empty directory.
- * If src is a file, dst may be a file.
- * In any other situation where dst already exists, the rename will
- * fail.
- *
- * Results:
- * If the directory was successfully created, returns TCL_OK.
- * Otherwise the return value is TCL_ERROR and errno is set to
- * indicate the error. Some possible values for errno are:
- *
- * EACCES: src or dst parent directory can't be read and/or written.
- * EEXIST: dst is a non-empty directory.
- * EINVAL: src is a root directory or dst is a subdirectory of src.
- * EISDIR: dst is a directory, but src is not.
- * ENOENT: src doesn't exist. src or dst is "".
- * ENOTDIR: src is a directory, but dst is not.
- * EXDEV: src and dst are on different filesystems.
- *
- * Side effects:
- * The implementation of rename may allow cross-filesystem renames,
- * but the caller should be prepared to emulate it with copy and
- * delete if errno is EXDEV.
- *
- *---------------------------------------------------------------------------
- */
-
-int
-TclpObjRenameFile(srcPathPtr, destPathPtr)
- Tcl_Obj *srcPathPtr;
- Tcl_Obj *destPathPtr;
-{
- return DoRenameFile(Tcl_FSGetNativePath(srcPathPtr),
- Tcl_FSGetNativePath(destPathPtr));
-}
-
-static int
-DoRenameFile(
- CONST char *src, /* Pathname of file or dir to be renamed
- * (native). */
- CONST char *dst) /* New pathname of file or directory
- * (native). */
-{
- FSSpec srcFileSpec, dstFileSpec, dstDirSpec;
- OSErr err;
- long srcID, dummy;
- Boolean srcIsDirectory, dstIsDirectory, dstExists, dstLocked;
-
- err = FSpLLocationFromPath(strlen(src), src, &srcFileSpec);
- if (err == noErr) {
- FSpGetDirectoryID(&srcFileSpec, &srcID, &srcIsDirectory);
- }
- if (err == noErr) {
- err = GetFileSpecs(dst, &dstFileSpec, &dstDirSpec, &dstExists,
- &dstIsDirectory);
- }
- if (err == noErr) {
- if (dstExists == 0) {
- err = MoveRename(&srcFileSpec, &dstDirSpec, dstFileSpec.name);
- goto end;
- }
- err = FSpGetFLockCompat(&dstFileSpec, &dstLocked);
- if (dstLocked) {
- FSpRstFLockCompat(&dstFileSpec);
- }
- }
- if (err == noErr) {
- if (srcIsDirectory) {
- if (dstIsDirectory) {
- /*
- * The following call will remove an empty directory. If it
- * fails, it's because it wasn't empty.
- */
-
- if (DoRemoveDirectory(dst, 0, NULL) != TCL_OK) {
- return TCL_ERROR;
- }
-
- /*
- * Now that that empty directory is gone, we can try
- * renaming src. If that fails, we'll put this empty
- * directory back, for completeness.
- */
-
- err = MoveRename(&srcFileSpec, &dstDirSpec, dstFileSpec.name);
- if (err != noErr) {
- FSpDirCreateCompat(&dstFileSpec, smSystemScript, &dummy);
- if (dstLocked) {
- FSpSetFLockCompat(&dstFileSpec);
- }
- }
- } else {
- errno = ENOTDIR;
- return TCL_ERROR;
- }
- } else {
- if (dstIsDirectory) {
- errno = EISDIR;
- return TCL_ERROR;
- } else {
- /*
- * Overwrite existing file by:
- *
- * 1. Rename existing file to temp name.
- * 2. Rename old file to new name.
- * 3. If success, delete temp file. If failure,
- * put temp file back to old name.
- */
-
- Str31 tmpName;
- FSSpec tmpFileSpec;
-
- err = GenerateUniqueName(dstFileSpec.vRefNum, &startSeed,
- dstFileSpec.parID, dstFileSpec.parID, tmpName);
- if (err == noErr) {
- err = FSpRenameCompat(&dstFileSpec, tmpName);
- }
- if (err == noErr) {
- err = FSMakeFSSpecCompat(dstFileSpec.vRefNum,
- dstFileSpec.parID, tmpName, &tmpFileSpec);
- }
- if (err == noErr) {
- err = MoveRename(&srcFileSpec, &dstDirSpec,
- dstFileSpec.name);
- }
- if (err == noErr) {
- FSpDeleteCompat(&tmpFileSpec);
- } else {
- FSpDeleteCompat(&dstFileSpec);
- FSpRenameCompat(&tmpFileSpec, dstFileSpec.name);
- if (dstLocked) {
- FSpSetFLockCompat(&dstFileSpec);
- }
- }
- }
- }
- }
-
- end:
- if (err != noErr) {
- errno = TclMacOSErrorToPosixError(err);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
- *--------------------------------------------------------------------------
- *
- * MoveRename --
- *
- * Helper function for TclpRenameFile. Renames a file or directory
- * into the same directory or another directory. The target name
- * must not already exist in the destination directory.
- *
- * Don't use FSpMoveRenameCompat because it doesn't work with
- * directories or with locked files.
- *
- * Results:
- * Returns a mac error indicating the cause of the failure.
- *
- * Side effects:
- * Creates a temp file in the target directory to handle a rename
- * between directories.
- *
- *--------------------------------------------------------------------------
- */
-
-static OSErr
-MoveRename(
- const FSSpec *srcFileSpecPtr, /* Source object. */
- const FSSpec *dstDirSpecPtr, /* Destination directory. */
- StringPtr copyName) /* New name for object in destination
- * directory. */
-{
- OSErr err;
- long srcID, dstID;
- Boolean srcIsDir, dstIsDir;
- Str31 tmpName;
- FSSpec dstFileSpec, srcDirSpec, tmpSrcFileSpec, tmpDstFileSpec;
- Boolean locked;
-
- if (srcFileSpecPtr->parID == 1) {
- /*
- * Trying to rename a volume.
- */
-
- return badMovErr;
- }
- if (srcFileSpecPtr->vRefNum != dstDirSpecPtr->vRefNum) {
- /*
- * Renaming across volumes.
- */
-
- return diffVolErr;
- }
- err = FSpGetFLockCompat(srcFileSpecPtr, &locked);
- if (locked) {
- FSpRstFLockCompat(srcFileSpecPtr);
- }
- if (err == noErr) {
- err = FSpGetDirectoryID(dstDirSpecPtr, &dstID, &dstIsDir);
- }
- if (err == noErr) {
- if (srcFileSpecPtr->parID == dstID) {
- /*
- * Renaming object within directory.
- */
-
- err = FSpRenameCompat(srcFileSpecPtr, copyName);
- goto done;
- }
- if (Pstrequal(srcFileSpecPtr->name, copyName)) {
- /*
- * Moving object to another directory (under same name).
- */
-
- err = FSpCatMoveCompat(srcFileSpecPtr, dstDirSpecPtr);
- goto done;
- }
- err = FSpGetDirectoryID(srcFileSpecPtr, &srcID, &srcIsDir);
- }
- if (err == noErr) {
- /*
- * Fullblown: rename source object to temp name, move temp to
- * dest directory, and rename temp to target.
- */
-
- err = GenerateUniqueName(srcFileSpecPtr->vRefNum, &startSeed,
- srcFileSpecPtr->parID, dstID, tmpName);
- FSMakeFSSpecCompat(srcFileSpecPtr->vRefNum, srcFileSpecPtr->parID,
- tmpName, &tmpSrcFileSpec);
- FSMakeFSSpecCompat(dstDirSpecPtr->vRefNum, dstID, tmpName,
- &tmpDstFileSpec);
- }
- if (err == noErr) {
- err = FSpRenameCompat(srcFileSpecPtr, tmpName);
- }
- if (err == noErr) {
- err = FSpCatMoveCompat(&tmpSrcFileSpec, dstDirSpecPtr);
- if (err == noErr) {
- err = FSpRenameCompat(&tmpDstFileSpec, copyName);
- if (err == noErr) {
- goto done;
- }
- FSMakeFSSpecCompat(srcFileSpecPtr->vRefNum, srcFileSpecPtr->parID,
- NULL, &srcDirSpec);
- FSpCatMoveCompat(&tmpDstFileSpec, &srcDirSpec);
- }
- FSpRenameCompat(&tmpSrcFileSpec, srcFileSpecPtr->name);
- }
-
- done:
- if (locked != false) {
- if (err == noErr) {
- FSMakeFSSpecCompat(dstDirSpecPtr->vRefNum,
- dstID, copyName, &dstFileSpec);
- FSpSetFLockCompat(&dstFileSpec);
- } else {
- FSpSetFLockCompat(srcFileSpecPtr);
- }
- }
- return err;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclpObjCopyFile, DoCopyFile --
- *
- * Copy a single file (not a directory). If dst already exists and
- * is not a directory, it is removed.
- *
- * Results:
- * If the file was successfully copied, returns TCL_OK. Otherwise
- * the return value is TCL_ERROR and errno is set to indicate the
- * error. Some possible values for errno are:
- *
- * EACCES: src or dst parent directory can't be read and/or written.
- * EISDIR: src or dst is a directory.
- * ENOENT: src doesn't exist. src or dst is "".
- *
- * Side effects:
- * This procedure will also copy symbolic links, block, and
- * character devices, and fifos. For symbolic links, the links
- * themselves will be copied and not what they point to. For the
- * other special file types, the directory entry will be copied and
- * not the contents of the device that it refers to.
- *
- *---------------------------------------------------------------------------
- */
-
-int
-TclpObjCopyFile(srcPathPtr, destPathPtr)
- Tcl_Obj *srcPathPtr;
- Tcl_Obj *destPathPtr;
-{
- return DoCopyFile(Tcl_FSGetNativePath(srcPathPtr),
- Tcl_FSGetNativePath(destPathPtr));
-}
-
-static int
-DoCopyFile(
- CONST char *src, /* Pathname of file to be copied (native). */
- CONST char *dst) /* Pathname of file to copy to (native). */
-{
- OSErr err, dstErr;
- Boolean dstExists, dstIsDirectory, dstLocked;
- FSSpec srcFileSpec, dstFileSpec, dstDirSpec, tmpFileSpec;
- Str31 tmpName;
-
- err = FSpLLocationFromPath(strlen(src), src, &srcFileSpec);
- if (err == noErr) {
- err = GetFileSpecs(dst, &dstFileSpec, &dstDirSpec, &dstExists,
- &dstIsDirectory);
- }
- if (dstExists) {
- if (dstIsDirectory) {
- errno = EISDIR;
- return TCL_ERROR;
- }
- err = FSpGetFLockCompat(&dstFileSpec, &dstLocked);
- if (dstLocked) {
- FSpRstFLockCompat(&dstFileSpec);
- }
-
- /*
- * Backup dest file.
- */
-
- dstErr = GenerateUniqueName(dstFileSpec.vRefNum, &startSeed, dstFileSpec.parID,
- dstFileSpec.parID, tmpName);
- if (dstErr == noErr) {
- dstErr = FSpRenameCompat(&dstFileSpec, tmpName);
- }
- }
- if (err == noErr) {
- err = FSpFileCopy(&srcFileSpec, &dstDirSpec,
- (StringPtr) dstFileSpec.name, NULL, 0, true);
- }
- if ((dstExists != false) && (dstErr == noErr)) {
- FSMakeFSSpecCompat(dstFileSpec.vRefNum, dstFileSpec.parID,
- tmpName, &tmpFileSpec);
- if (err == noErr) {
- /*
- * Delete backup file.
- */
-
- FSpDeleteCompat(&tmpFileSpec);
- } else {
-
- /*
- * Restore backup file.
- */
-
- FSpDeleteCompat(&dstFileSpec);
- FSpRenameCompat(&tmpFileSpec, dstFileSpec.name);
- if (dstLocked) {
- FSpSetFLockCompat(&dstFileSpec);
- }
- }
- }
-
- if (err != noErr) {
- errno = TclMacOSErrorToPosixError(err);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclpObjDeleteFile, TclpDeleteFile --
- *
- * Removes a single file (not a directory).
- *
- * Results:
- * If the file was successfully deleted, returns TCL_OK. Otherwise
- * the return value is TCL_ERROR and errno is set to indicate the
- * error. Some possible values for errno are:
- *
- * EACCES: a parent directory can't be read and/or written.
- * EISDIR: path is a directory.
- * ENOENT: path doesn't exist or is "".
- *
- * Side effects:
- * The file is deleted, even if it is read-only.
- *
- *---------------------------------------------------------------------------
- */
-
-int
-TclpObjDeleteFile(pathPtr)
- Tcl_Obj *pathPtr;
-{
- return TclpDeleteFile(Tcl_FSGetNativePath(pathPtr));
-}
-
-int
-TclpDeleteFile(
- CONST char *path) /* Pathname of file to be removed (native). */
-{
- OSErr err;
- FSSpec fileSpec;
- Boolean isDirectory;
- long dirID;
-
- err = FSpLLocationFromPath(strlen(path), path, &fileSpec);
- if (err == noErr) {
- /*
- * Since FSpDeleteCompat will delete an empty directory, make sure
- * that this isn't a directory first.
- */
-
- FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
- if (isDirectory == true) {
- errno = EISDIR;
- return TCL_ERROR;
- }
- }
- err = FSpDeleteCompat(&fileSpec);
- if (err == fLckdErr) {
- FSpRstFLockCompat(&fileSpec);
- err = FSpDeleteCompat(&fileSpec);
- if (err != noErr) {
- FSpSetFLockCompat(&fileSpec);
- }
- }
- if (err != noErr) {
- errno = TclMacOSErrorToPosixError(err);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclpObjCreateDirectory, DoCreateDirectory --
- *
- * Creates the specified directory. All parent directories of the
- * specified directory must already exist. The directory is
- * automatically created with permissions so that user can access
- * the new directory and create new files or subdirectories in it.
- *
- * Results:
- * If the directory was successfully created, returns TCL_OK.
- * Otherwise the return value is TCL_ERROR and errno is set to
- * indicate the error. Some possible values for errno are:
- *
- * EACCES: a parent directory can't be read and/or written.
- * EEXIST: path already exists.
- * ENOENT: a parent directory doesn't exist.
- *
- * Side effects:
- * A directory is created with the current umask, except that
- * permission for u+rwx will always be added.
- *
- *---------------------------------------------------------------------------
- */
-
-int
-TclpObjCreateDirectory(pathPtr)
- Tcl_Obj *pathPtr;
-{
- return DoCreateDirectory(Tcl_FSGetNativePath(pathPtr));
-}
-
-static int
-DoCreateDirectory(
- CONST char *path) /* Pathname of directory to create (native). */
-{
- OSErr err;
- FSSpec dirSpec;
- long outDirID;
-
- err = FSpLocationFromPath(strlen(path), path, &dirSpec);
- if (err == noErr) {
- err = dupFNErr; /* EEXIST. */
- } else if (err == fnfErr) {
- err = FSpDirCreateCompat(&dirSpec, smSystemScript, &outDirID);
- }
-
- if (err != noErr) {
- errno = TclMacOSErrorToPosixError(err);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclpObjCopyDirectory, DoCopyDirectory --
- *
- * Recursively copies a directory. The target directory dst must
- * not already exist. Note that this function does not merge two
- * directory hierarchies, even if the target directory is an an
- * empty directory.
- *
- * Results:
- * If the directory was successfully copied, returns TCL_OK.
- * Otherwise the return value is TCL_ERROR, errno is set to indicate
- * the error, and the pathname of the file that caused the error
- * is stored in errorPtr. See TclpCreateDirectory and TclpCopyFile
- * for a description of possible values for errno.
- *
- * Side effects:
- * An exact copy of the directory hierarchy src will be created
- * with the name dst. If an error occurs, the error will
- * be returned immediately, and remaining files will not be
- * processed.
- *
- *---------------------------------------------------------------------------
- */
-
-int
-TclpObjCopyDirectory(srcPathPtr, destPathPtr, errorPtr)
- Tcl_Obj *srcPathPtr;
- Tcl_Obj *destPathPtr;
- Tcl_Obj **errorPtr;
-{
- Tcl_DString ds;
- int ret;
- ret = DoCopyDirectory(Tcl_FSGetNativePath(srcPathPtr),
- Tcl_FSGetNativePath(destPathPtr), &ds);
- if (ret != TCL_OK) {
- *errorPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1);
- Tcl_DStringFree(&ds);
- Tcl_IncrRefCount(*errorPtr);
- }
- return ret;
-}
-
-static int
-DoCopyDirectory(
- CONST char *src, /* Pathname of directory to be copied
- * (Native). */
- CONST char *dst, /* Pathname of target directory (Native). */
- Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free
- * DString filled with UTF-8 name of file
- * causing error. */
-{
- OSErr err, saveErr;
- long srcID, tmpDirID;
- FSSpec srcFileSpec, dstFileSpec, dstDirSpec, tmpDirSpec, tmpFileSpec;
- Boolean srcIsDirectory, srcLocked;
- Boolean dstIsDirectory, dstExists;
- Str31 tmpName;
-
- err = FSpLocationFromPath(strlen(src), src, &srcFileSpec);
- if (err == noErr) {
- err = FSpGetDirectoryID(&srcFileSpec, &srcID, &srcIsDirectory);
- }
- if (err == noErr) {
- if (srcIsDirectory == false) {
- err = afpObjectTypeErr; /* ENOTDIR. */
- }
- }
- if (err == noErr) {
- err = GetFileSpecs(dst, &dstFileSpec, &dstDirSpec, &dstExists,
- &dstIsDirectory);
- }
- if (dstExists) {
- if (dstIsDirectory == false) {
- err = afpObjectTypeErr; /* ENOTDIR. */
- } else {
- err = dupFNErr; /* EEXIST. */
- }
- }
- if (err != noErr) {
- goto done;
- }
- if ((srcFileSpec.vRefNum == dstFileSpec.vRefNum) &&
- (srcFileSpec.parID == dstFileSpec.parID) &&
- (Pstrequal(srcFileSpec.name, dstFileSpec.name) != 0)) {
- /*
- * Copying on top of self. No-op.
- */
-
- goto done;
- }
-
- /*
- * This algorthm will work making a copy of the source directory in
- * the current directory with a new name, in a new directory with the
- * same name, and in a new directory with a new name:
- *
- * 1. Make dstDir/tmpDir.
- * 2. Copy srcDir/src to dstDir/tmpDir/src
- * 3. Rename dstDir/tmpDir/src to dstDir/tmpDir/dst (if necessary).
- * 4. CatMove dstDir/tmpDir/dst to dstDir/dst.
- * 5. Remove dstDir/tmpDir.
- */
-
- err = FSpGetFLockCompat(&srcFileSpec, &srcLocked);
- if (srcLocked) {
- FSpRstFLockCompat(&srcFileSpec);
- }
- if (err == noErr) {
- err = GenerateUniqueName(dstFileSpec.vRefNum, &startSeed, dstFileSpec.parID,
- dstFileSpec.parID, tmpName);
- }
- if (err == noErr) {
- FSMakeFSSpecCompat(dstFileSpec.vRefNum, dstFileSpec.parID,
- tmpName, &tmpDirSpec);
- err = FSpDirCreateCompat(&tmpDirSpec, smSystemScript, &tmpDirID);
- }
- if (err == noErr) {
- err = FSpDirectoryCopy(&srcFileSpec, &tmpDirSpec, NULL, NULL, 0, true,
- CopyErrHandler);
- }
-
- /*
- * Even if the Copy failed, Rename/Move whatever did get copied to the
- * appropriate final destination, if possible.
- */
-
- saveErr = err;
- err = noErr;
- if (Pstrequal(srcFileSpec.name, dstFileSpec.name) == 0) {
- err = FSMakeFSSpecCompat(tmpDirSpec.vRefNum, tmpDirID,
- srcFileSpec.name, &tmpFileSpec);
- if (err == noErr) {
- err = FSpRenameCompat(&tmpFileSpec, dstFileSpec.name);
- }
- }
- if (err == noErr) {
- err = FSMakeFSSpecCompat(tmpDirSpec.vRefNum, tmpDirID,
- dstFileSpec.name, &tmpFileSpec);
- }
- if (err == noErr) {
- err = FSpCatMoveCompat(&tmpFileSpec, &dstDirSpec);
- }
- if (err == noErr) {
- if (srcLocked) {
- FSpSetFLockCompat(&dstFileSpec);
- }
- }
-
- FSpDeleteCompat(&tmpDirSpec);
-
- if (saveErr != noErr) {
- err = saveErr;
- }
-
- done:
- if (err != noErr) {
- errno = TclMacOSErrorToPosixError(err);
- if (errorPtr != NULL) {
- Tcl_ExternalToUtfDString(NULL, dst, -1, errorPtr);
- }
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * CopyErrHandler --
- *
- * This procedure is called from the MoreFiles procedure
- * FSpDirectoryCopy whenever an error occurs.
- *
- * Results:
- * False if the condition should not be considered an error, true
- * otherwise.
- *
- * Side effects:
- * Since FSpDirectoryCopy() is called only after removing any
- * existing target directories, there shouldn't be any errors.
- *
- *----------------------------------------------------------------------
- */
-
-static pascal Boolean
-CopyErrHandler(
- OSErr error, /* Error that occured */
- short failedOperation, /* operation that caused the error */
- short srcVRefNum, /* volume ref number of source */
- long srcDirID, /* directory id of source */
- ConstStr255Param srcName, /* name of source */
- short dstVRefNum, /* volume ref number of dst */
- long dstDirID, /* directory id of dst */
- ConstStr255Param dstName) /* name of dst directory */
-{
- return true;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclpObjRemoveDirectory, DoRemoveDirectory --
- *
- * Removes directory (and its contents, if the recursive flag is set).
- *
- * Results:
- * If the directory was successfully removed, returns TCL_OK.
- * Otherwise the return value is TCL_ERROR, errno is set to indicate
- * the error, and the pathname of the file that caused the error
- * is stored in errorPtr. Some possible values for errno are:
- *
- * EACCES: path directory can't be read and/or written.
- * EEXIST: path is a non-empty directory.
- * EINVAL: path is a root directory.
- * ENOENT: path doesn't exist or is "".
- * ENOTDIR: path is not a directory.
- *
- * Side effects:
- * Directory removed. If an error occurs, the error will be returned
- * immediately, and remaining files will not be deleted.
- *
- *---------------------------------------------------------------------------
- */
-
-int
-TclpObjRemoveDirectory(pathPtr, recursive, errorPtr)
- Tcl_Obj *pathPtr;
- int recursive;
- Tcl_Obj **errorPtr;
-{
- Tcl_DString ds;
- int ret;
- ret = DoRemoveDirectory(Tcl_FSGetNativePath(pathPtr),recursive, &ds);
- if (ret != TCL_OK) {
- *errorPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1);
- Tcl_DStringFree(&ds);
- Tcl_IncrRefCount(*errorPtr);
- }
- return ret;
-}
-
-static int
-DoRemoveDirectory(
- CONST char *path, /* Pathname of directory to be removed
- * (native). */
- int recursive, /* If non-zero, removes directories that
- * are nonempty. Otherwise, will only remove
- * empty directories. */
- Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free
- * DString filled with UTF-8 name of file
- * causing error. */
-{
- OSErr err;
- FSSpec fileSpec;
- long dirID;
- int locked;
- Boolean isDirectory;
- CInfoPBRec pb;
- Str255 fileName;
-
-
- locked = 0;
- err = FSpLocationFromPath(strlen(path), path, &fileSpec);
- if (err != noErr) {
- goto done;
- }
-
- /*
- * Since FSpDeleteCompat will delete a file, make sure this isn't
- * a file first.
- */
-
- isDirectory = 1;
- FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
- if (isDirectory == 0) {
- errno = ENOTDIR;
- return TCL_ERROR;
- }
-
- err = FSpDeleteCompat(&fileSpec);
- if (err == fLckdErr) {
- locked = 1;
- FSpRstFLockCompat(&fileSpec);
- err = FSpDeleteCompat(&fileSpec);
- }
- if (err == noErr) {
- return TCL_OK;
- }
- if (err != fBsyErr) {
- goto done;
- }
-
- if (recursive == 0) {
- /*
- * fBsyErr means one of three things: file busy, directory not empty,
- * or working directory control block open. Determine if directory
- * is empty. If directory is not empty, return EEXIST.
- */
-
- pb.hFileInfo.ioVRefNum = fileSpec.vRefNum;
- pb.hFileInfo.ioDirID = dirID;
- pb.hFileInfo.ioNamePtr = (StringPtr) fileName;
- pb.hFileInfo.ioFDirIndex = 1;
- if (PBGetCatInfoSync(&pb) == noErr) {
- err = dupFNErr; /* EEXIST */
- goto done;
- }
- }
-
- /*
- * DeleteDirectory removes a directory and all its contents, including
- * any locked files. There is no interface to get the name of the
- * file that caused the error, if an error occurs deleting this tree,
- * unless we rewrite DeleteDirectory ourselves.
- */
-
- err = DeleteDirectory(fileSpec.vRefNum, dirID, NULL);
-
- done:
- if (err != noErr) {
- if (errorPtr != NULL) {
- Tcl_UtfToExternalDString(NULL, path, -1, errorPtr);
- }
- if (locked) {
- FSpSetFLockCompat(&fileSpec);
- }
- errno = TclMacOSErrorToPosixError(err);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * GetFileSpecs --
- *
- * Gets FSSpecs for the specified path and its parent directory.
- *
- * Results:
- * The return value is noErr if there was no error getting FSSpecs,
- * otherwise it is an error describing the problem. Fills buffers
- * with information, as above.
- *
- * Side effects:
- * None.
- *
- *---------------------------------------------------------------------------
- */
-
-static OSErr
-GetFileSpecs(
- CONST char *path, /* The path to query. */
- FSSpec *pathSpecPtr, /* Filled with information about path. */
- FSSpec *dirSpecPtr, /* Filled with information about path's
- * parent directory. */
- Boolean *pathExistsPtr, /* Set to true if path actually exists,
- * false if it doesn't or there was an
- * error reading the specified path. */
- Boolean *pathIsDirectoryPtr)/* Set to true if path is itself a directory,
- * otherwise false. */
-{
- CONST char *dirName;
- OSErr err;
- int argc;
- CONST char **argv;
- long d;
- Tcl_DString buffer;
-
- *pathExistsPtr = false;
- *pathIsDirectoryPtr = false;
-
- Tcl_DStringInit(&buffer);
- Tcl_SplitPath(path, &argc, &argv);
- if (argc == 1) {
- dirName = ":";
- } else {
- dirName = Tcl_JoinPath(argc - 1, argv, &buffer);
- }
- err = FSpLocationFromPath(strlen(dirName), dirName, dirSpecPtr);
- Tcl_DStringFree(&buffer);
- ckfree((char *) argv);
-
- if (err == noErr) {
- err = FSpLocationFromPath(strlen(path), path, pathSpecPtr);
- if (err == noErr) {
- *pathExistsPtr = true;
- err = FSpGetDirectoryID(pathSpecPtr, &d, pathIsDirectoryPtr);
- } else if (err == fnfErr) {
- err = noErr;
- }
- }
- return err;
-}
-
-/*
- *-------------------------------------------------------------------------
- *
- * FSpGetFLockCompat --
- *
- * Determines if there exists a software lock on the specified
- * file. The software lock could prevent the file from being
- * renamed or moved.
- *
- * Results:
- * Standard macintosh error code.
- *
- * Side effects:
- * None.
- *
- *
- *-------------------------------------------------------------------------
- */
-
-OSErr
-FSpGetFLockCompat(
- const FSSpec *specPtr, /* File to query. */
- Boolean *lockedPtr) /* Set to true if file is locked, false
- * if it isn't or there was an error reading
- * specified file. */
-{
- CInfoPBRec pb;
- OSErr err;
-
- pb.hFileInfo.ioVRefNum = specPtr->vRefNum;
- pb.hFileInfo.ioDirID = specPtr->parID;
- pb.hFileInfo.ioNamePtr = (StringPtr) specPtr->name;
- pb.hFileInfo.ioFDirIndex = 0;
-
- err = PBGetCatInfoSync(&pb);
- if ((err == noErr) && (pb.hFileInfo.ioFlAttrib & 0x01)) {
- *lockedPtr = true;
- } else {
- *lockedPtr = false;
- }
- return err;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Pstrequal --
- *
- * Pascal string compare.
- *
- * Results:
- * Returns 1 if strings equal, 0 otherwise.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-Pstrequal (
- ConstStr255Param stringA, /* Pascal string A */
- ConstStr255Param stringB) /* Pascal string B */
-{
- int i, len;
-
- len = *stringA;
- for (i = 0; i <= len; i++) {
- if (*stringA++ != *stringB++) {
- return 0;
- }
- }
- return 1;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * GetFileFinderAttributes --
- *
- * Returns a Tcl_Obj containing the value of a file attribute
- * which is part of the FInfo record. Which attribute is controlled
- * by objIndex.
- *
- * Results:
- * Returns a standard TCL error. If the return value is TCL_OK,
- * the new creator or file type object is put into attributePtrPtr.
- * The object will have ref count 0. If there is an error,
- * attributePtrPtr is not touched.
- *
- * Side effects:
- * A new object is allocated if the file is valid.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-GetFileFinderAttributes(
- Tcl_Interp *interp, /* The interp to report errors with. */
- int objIndex, /* The index of the attribute option. */
- Tcl_Obj *fileName, /* The name of the file (UTF-8). */
- Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */
-{
- OSErr err;
- FSSpec fileSpec;
- FInfo finfo;
- CONST char *native;
-
- native=Tcl_FSGetNativePath(fileName);
- err = FSpLLocationFromPath(strlen(native),
- native, &fileSpec);
-
- if (err == noErr) {
- err = FSpGetFInfo(&fileSpec, &finfo);
- }
-
- if (err == noErr) {
- switch (objIndex) {
- case MAC_CREATOR_ATTRIBUTE:
- *attributePtrPtr = Tcl_NewOSTypeObj(finfo.fdCreator);
- break;
- case MAC_HIDDEN_ATTRIBUTE:
- *attributePtrPtr = Tcl_NewBooleanObj(finfo.fdFlags
- & kIsInvisible);
- break;
- case MAC_TYPE_ATTRIBUTE:
- *attributePtrPtr = Tcl_NewOSTypeObj(finfo.fdType);
- break;
- }
- } else if (err == fnfErr) {
- long dirID;
- Boolean isDirectory = 0;
-
- err = FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
- if ((err == noErr) && isDirectory) {
- if (objIndex == MAC_HIDDEN_ATTRIBUTE) {
- *attributePtrPtr = Tcl_NewBooleanObj(0);
- } else {
- *attributePtrPtr = Tcl_NewOSTypeObj('Fldr');
- }
- }
- }
-
- if (err != noErr) {
- errno = TclMacOSErrorToPosixError(err);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "could not read \"", Tcl_GetString(fileName), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * GetFileReadOnly --
- *
- * Returns a Tcl_Obj containing a Boolean value indicating whether
- * or not the file is read-only. The object will have ref count 0.
- * This procedure just checks the Finder attributes; it does not
- * check AppleShare sharing attributes.
- *
- * Results:
- * Returns a standard TCL error. If the return value is TCL_OK,
- * the new creator type object is put into readOnlyPtrPtr.
- * If there is an error, readOnlyPtrPtr is not touched.
- *
- * Side effects:
- * A new object is allocated if the file is valid.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-GetFileReadOnly(
- Tcl_Interp *interp, /* The interp to report errors with. */
- int objIndex, /* The index of the attribute. */
- Tcl_Obj *fileName, /* The name of the file (UTF-8). */
- Tcl_Obj **readOnlyPtrPtr) /* A pointer to return the object with. */
-{
- OSErr err;
- FSSpec fileSpec;
- CInfoPBRec paramBlock;
- CONST char *native;
-
- native=Tcl_FSGetNativePath(fileName);
- err = FSpLLocationFromPath(strlen(native),
- native, &fileSpec);
-
- if (err == noErr) {
- if (err == noErr) {
- paramBlock.hFileInfo.ioCompletion = NULL;
- paramBlock.hFileInfo.ioNamePtr = fileSpec.name;
- paramBlock.hFileInfo.ioVRefNum = fileSpec.vRefNum;
- paramBlock.hFileInfo.ioFDirIndex = 0;
- paramBlock.hFileInfo.ioDirID = fileSpec.parID;
- err = PBGetCatInfo(&paramBlock, 0);
- if (err == noErr) {
-
- /*
- * For some unknown reason, the Mac does not give
- * symbols for the bits in the ioFlAttrib field.
- * 1 -> locked.
- */
-
- *readOnlyPtrPtr = Tcl_NewBooleanObj(
- paramBlock.hFileInfo.ioFlAttrib & 1);
- }
- }
- }
- if (err != noErr) {
- errno = TclMacOSErrorToPosixError(err);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "could not read \"", Tcl_GetString(fileName), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * SetFileFinderAttributes --
- *
- * Sets the file to the creator or file type given by attributePtr.
- * objIndex determines whether the creator or file type is set.
- *
- * Results:
- * Returns a standard TCL error.
- *
- * Side effects:
- * The file's attribute is set.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-SetFileFinderAttributes(
- Tcl_Interp *interp, /* The interp to report errors with. */
- int objIndex, /* The index of the attribute. */
- Tcl_Obj *fileName, /* The name of the file (UTF-8). */
- Tcl_Obj *attributePtr) /* The command line object. */
-{
- OSErr err;
- FSSpec fileSpec;
- FInfo finfo;
- CONST char *native;
-
- native=Tcl_FSGetNativePath(fileName);
- err = FSpLLocationFromPath(strlen(native),
- native, &fileSpec);
-
- if (err == noErr) {
- err = FSpGetFInfo(&fileSpec, &finfo);
- }
-
- if (err == noErr) {
- switch (objIndex) {
- case MAC_CREATOR_ATTRIBUTE:
- if (Tcl_GetOSTypeFromObj(interp, attributePtr,
- &finfo.fdCreator) != TCL_OK) {
- return TCL_ERROR;
- }
- break;
- case MAC_HIDDEN_ATTRIBUTE: {
- int hidden;
-
- if (Tcl_GetBooleanFromObj(interp, attributePtr, &hidden)
- != TCL_OK) {
- return TCL_ERROR;
- }
- if (hidden) {
- finfo.fdFlags |= kIsInvisible;
- } else {
- finfo.fdFlags &= ~kIsInvisible;
- }
- break;
- }
- case MAC_TYPE_ATTRIBUTE:
- if (Tcl_GetOSTypeFromObj(interp, attributePtr,
- &finfo.fdType) != TCL_OK) {
- return TCL_ERROR;
- }
- break;
- }
- err = FSpSetFInfo(&fileSpec, &finfo);
- } else if (err == fnfErr) {
- long dirID;
- Boolean isDirectory = 0;
-
- err = FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
- if ((err == noErr) && isDirectory) {
- Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);
- Tcl_AppendStringsToObj(resultPtr, "cannot set ",
- tclpFileAttrStrings[objIndex], ": \"",
- Tcl_GetString(fileName), "\" is a directory", (char *) NULL);
- return TCL_ERROR;
- }
- }
-
- if (err != noErr) {
- errno = TclMacOSErrorToPosixError(err);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "could not read \"", Tcl_GetString(fileName), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * SetFileReadOnly --
- *
- * Sets the file to be read-only according to the Boolean value
- * given by hiddenPtr.
- *
- * Results:
- * Returns a standard TCL error.
- *
- * Side effects:
- * The file's attribute is set.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-SetFileReadOnly(
- Tcl_Interp *interp, /* The interp to report errors with. */
- int objIndex, /* The index of the attribute. */
- Tcl_Obj *fileName, /* The name of the file (UTF-8). */
- Tcl_Obj *readOnlyPtr) /* The command line object. */
-{
- OSErr err;
- FSSpec fileSpec;
- HParamBlockRec paramBlock;
- int hidden;
- CONST char *native;
-
- native=Tcl_FSGetNativePath(fileName);
- err = FSpLLocationFromPath(strlen(native),
- native, &fileSpec);
-
- if (err == noErr) {
- if (Tcl_GetBooleanFromObj(interp, readOnlyPtr, &hidden) != TCL_OK) {
- return TCL_ERROR;
- }
-
- paramBlock.fileParam.ioCompletion = NULL;
- paramBlock.fileParam.ioNamePtr = fileSpec.name;
- paramBlock.fileParam.ioVRefNum = fileSpec.vRefNum;
- paramBlock.fileParam.ioDirID = fileSpec.parID;
- if (hidden) {
- err = PBHSetFLock(&paramBlock, 0);
- } else {
- err = PBHRstFLock(&paramBlock, 0);
- }
- }
-
- if (err == fnfErr) {
- long dirID;
- Boolean isDirectory = 0;
- err = FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
- if ((err == noErr) && isDirectory) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "cannot set a directory to read-only when File Sharing is turned off",
- (char *) NULL);
- return TCL_ERROR;
- } else {
- err = fnfErr;
- }
- }
-
- if (err != noErr) {
- errno = TclMacOSErrorToPosixError(err);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "could not read \"", Tcl_GetString(fileName), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclpObjListVolumes --
- *
- * Lists the currently mounted volumes
- *
- * Results:
- * The list of volumes.
- *
- * Side effects:
- * None
- *
- *---------------------------------------------------------------------------
- */
-Tcl_Obj*
-TclpObjListVolumes(void)
-{
- HParamBlockRec pb;
- Str255 name;
- OSErr theError = noErr;
- Tcl_Obj *resultPtr, *elemPtr;
- short volIndex = 1;
- Tcl_DString dstr;
-
- resultPtr = Tcl_NewObj();
-
- /*
- * We use two facts:
- * 1) The Mac volumes are enumerated by the ioVolIndex parameter of
- * the HParamBlockRec. They run through the integers contiguously,
- * starting at 1.
- * 2) PBHGetVInfoSync returns an error when you ask for a volume index
- * that does not exist.
- *
- */
-
- while ( 1 ) {
- pb.volumeParam.ioNamePtr = (StringPtr) &name;
- pb.volumeParam.ioVolIndex = volIndex;
-
- theError = PBHGetVInfoSync(&pb);
-
- if ( theError != noErr ) {
- break;
- }
-
- Tcl_ExternalToUtfDString(NULL, (CONST char *)&name[1], name[0], &dstr);
- elemPtr = Tcl_NewStringObj(Tcl_DStringValue(&dstr),
- Tcl_DStringLength(&dstr));
- Tcl_AppendToObj(elemPtr, ":", 1);
- Tcl_ListObjAppendElement(NULL, resultPtr, elemPtr);
-
- Tcl_DStringFree(&dstr);
-
- volIndex++;
- }
-
- Tcl_IncrRefCount(resultPtr);
- return resultPtr;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclpObjNormalizePath --
- *
- * This function scans through a path specification and replaces
- * it, in place, with a normalized version. On MacOS, this means
- * resolving all aliases present in the path and replacing the head of
- * pathPtr with the absolute case-sensitive path to the last file or
- * directory that could be validated in the path.
- *
- * Results:
- * The new 'nextCheckpoint' value, giving as far as we could
- * understand in the path.
- *
- * Side effects:
- * The pathPtr string, which must contain a valid path, is
- * possibly modified in place.
- *
- *---------------------------------------------------------------------------
- */
-
-int
-TclpObjNormalizePath(interp, pathPtr, nextCheckpoint)
- Tcl_Interp *interp;
- Tcl_Obj *pathPtr;
- int nextCheckpoint;
-{
- #define MAXMACFILENAMELEN 31 /* assumed to be < sizeof(StrFileName) */
-
- StrFileName fileName;
- StringPtr fileNamePtr;
- int fileNameLen,newPathLen;
- Handle newPathHandle;
- OSErr err;
- short vRefNum;
- long dirID;
- Boolean isDirectory;
- Boolean wasAlias=FALSE;
- FSSpec fileSpec, lastFileSpec;
-
- Tcl_DString nativeds;
-
- char cur;
- int firstCheckpoint=nextCheckpoint, lastCheckpoint;
- int origPathLen;
- char *path = Tcl_GetStringFromObj(pathPtr,&origPathLen);
-
- {
- int currDirValid=0;
- /*
- * check if substring to first ':' after initial
- * nextCheckpoint is a valid relative or absolute
- * path to a directory, if not we return without
- * normalizing anything
- */
-
- while (1) {
- cur = path[nextCheckpoint];
- if (cur == ':' || cur == 0) {
- if (cur == ':') {
- /* jump over separator */
- nextCheckpoint++; cur = path[nextCheckpoint];
- }
- Tcl_UtfToExternalDString(NULL,path,nextCheckpoint,&nativeds);
- err = FSpLLocationFromPath(Tcl_DStringLength(&nativeds),
- Tcl_DStringValue(&nativeds),
- &fileSpec);
- Tcl_DStringFree(&nativeds);
- if (err == noErr) {
- lastFileSpec=fileSpec;
- err = ResolveAliasFile(&fileSpec, true, &isDirectory,
- &wasAlias);
- if (err == noErr) {
- err = FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
- currDirValid = ((err == noErr) && isDirectory);
- vRefNum = fileSpec.vRefNum;
- }
- }
- break;
- }
- nextCheckpoint++;
- }
-
- if(!currDirValid) {
- /* can't determine root dir, bail out */
- return firstCheckpoint;
- }
- }
-
- /*
- * Now vRefNum and dirID point to a valid
- * directory, so walk the rest of the path
- * ( code adapted from FSpLocationFromPath() )
- */
-
- lastCheckpoint=nextCheckpoint;
- while (1) {
- cur = path[nextCheckpoint];
- if (cur == ':' || cur == 0) {
- fileNameLen=nextCheckpoint-lastCheckpoint;
- fileNamePtr=fileName;
- if(fileNameLen==0) {
- if (cur == ':') {
- /*
- * special case for empty dirname i.e. encountered
- * a '::' path component: get parent dir of currDir
- */
- fileName[0]=2;
- strcpy((char *) fileName + 1, "::");
- lastCheckpoint--;
- } else {
- /*
- * empty filename, i.e. want FSSpec for currDir
- */
- fileNamePtr=NULL;
- }
- } else {
- Tcl_UtfToExternalDString(NULL,&path[lastCheckpoint],
- fileNameLen,&nativeds);
- fileNameLen=Tcl_DStringLength(&nativeds);
- if(fileNameLen > MAXMACFILENAMELEN) {
- err = bdNamErr;
- } else {
- fileName[0]=fileNameLen;
- strncpy((char *) fileName + 1, Tcl_DStringValue(&nativeds),
- fileNameLen);
- }
- Tcl_DStringFree(&nativeds);
- }
- if(err == noErr)
- err=FSMakeFSSpecCompat(vRefNum, dirID, fileNamePtr, &fileSpec);
- if(err != noErr) {
- if(err != fnfErr) {
- /*
- * this can occur if trying to get parent of a root
- * volume via '::' or when using an illegal
- * filename; revert to last checkpoint and stop
- * processing path further
- */
- err=FSMakeFSSpecCompat(vRefNum, dirID, NULL, &fileSpec);
- if(err != noErr) {
- /* should never happen, bail out */
- return firstCheckpoint;
- }
- nextCheckpoint=lastCheckpoint;
- cur = path[lastCheckpoint];
- }
- break; /* arrived at nonexistent file or dir */
- } else {
- /* fileSpec could point to an alias, resolve it */
- lastFileSpec=fileSpec;
- err = ResolveAliasFile(&fileSpec, true, &isDirectory,
- &wasAlias);
- if (err != noErr || !isDirectory) {
- break; /* fileSpec doesn't point to a dir */
- }
- }
- if (cur == 0) break; /* arrived at end of path */
-
- /* fileSpec points to possibly nonexisting subdirectory; validate */
- err = FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
- if (err != noErr || !isDirectory) {
- break; /* fileSpec doesn't point to existing dir */
- }
- vRefNum = fileSpec.vRefNum;
-
- /* found a new valid subdir in path, continue processing path */
- lastCheckpoint=nextCheckpoint+1;
- }
- wasAlias=FALSE;
- nextCheckpoint++;
- }
-
- if (wasAlias)
- fileSpec=lastFileSpec;
-
- /*
- * fileSpec now points to a possibly nonexisting file or dir
- * inside a valid dir; get full path name to it
- */
-
- err=FSpPathFromLocation(&fileSpec, &newPathLen, &newPathHandle);
- if(err != noErr) {
- return firstCheckpoint; /* should not see any errors here, bail out */
- }
-
- HLock(newPathHandle);
- Tcl_ExternalToUtfDString(NULL,*newPathHandle,newPathLen,&nativeds);
- if (cur != 0) {
- /* not at end, append remaining path */
- if ( newPathLen==0 || (*(*newPathHandle+(newPathLen-1))!=':' && path[nextCheckpoint] !=':')) {
- Tcl_DStringAppend(&nativeds, ":" , 1);
- }
- Tcl_DStringAppend(&nativeds, &path[nextCheckpoint],
- strlen(&path[nextCheckpoint]));
- }
- DisposeHandle(newPathHandle);
-
- fileNameLen=Tcl_DStringLength(&nativeds);
- Tcl_SetStringObj(pathPtr,Tcl_DStringValue(&nativeds),fileNameLen);
- Tcl_DStringFree(&nativeds);
-
- return nextCheckpoint+(fileNameLen-origPathLen);
-}
-
diff --git a/mac/tclMacFile.c b/mac/tclMacFile.c
deleted file mode 100644
index 168b087..0000000
--- a/mac/tclMacFile.c
+++ /dev/null
@@ -1,1348 +0,0 @@
-/*
- * tclMacFile.c --
- *
- * This file implements the channel drivers for Macintosh
- * files. It also comtains Macintosh version of other Tcl
- * functions that deal with the file system.
- *
- * Copyright (c) 1995-1998 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-/*
- * Note: This code eventually needs to support async I/O. In doing this
- * we will need to keep track of all current async I/O. If exit to shell
- * is called - we shouldn't exit until all asyc I/O completes.
- */
-
-#include "tclInt.h"
-#include "tclPort.h"
-#include "tclMacInt.h"
-#include <Aliases.h>
-#include <Resources.h>
-#include <Files.h>
-#include <Errors.h>
-#include <Processes.h>
-#include <Strings.h>
-#include <Types.h>
-#include <MoreFiles.h>
-#include <MoreFilesExtras.h>
-#include <FSpCompat.h>
-
-static int NativeMatchType(Tcl_Obj *tempName, Tcl_GlobTypeData *types,
- HFileInfo fileInfo, OSType okType, OSType okCreator);
-static OSErr FspLocationFromFsPath _ANSI_ARGS_((Tcl_Obj *pathPtr,
- FSSpec* specPtr));
-static OSErr FspLLocationFromFsPath _ANSI_ARGS_((Tcl_Obj *pathPtr,
- FSSpec* specPtr));
-
-static OSErr CreateAliasFile _ANSI_ARGS_((FSSpec *theAliasFile, FSSpec *targetFile));
-
-static OSErr
-FspLocationFromFsPath(pathPtr, specPtr)
- Tcl_Obj *pathPtr;
- FSSpec* specPtr;
-{
- CONST char *native = Tcl_FSGetNativePath(pathPtr);
- return FSpLocationFromPath(strlen(native), native, specPtr);
-}
-
-static OSErr
-FspLLocationFromFsPath(pathPtr, specPtr)
- Tcl_Obj *pathPtr;
- FSSpec* specPtr;
-{
- CONST char *native = Tcl_FSGetNativePath(pathPtr);
- return FSpLLocationFromPath(strlen(native), native, specPtr);
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpFindExecutable --
- *
- * This procedure computes the absolute path name of the current
- * application, given its argv[0] value. However, this
- * implementation doesn't need the argv[0] value. NULL
- * may be passed in its place.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The variable tclExecutableName gets filled in with the file
- * name for the application, if we figured it out. If we couldn't
- * figure it out, Tcl_FindExecutable is set to NULL.
- *
- *----------------------------------------------------------------------
- */
-
-char *
-TclpFindExecutable(
- CONST char *argv0) /* The value of the application's argv[0]. */
-{
- ProcessSerialNumber psn;
- ProcessInfoRec info;
- Str63 appName;
- FSSpec fileSpec;
- int pathLength;
- Handle pathName = NULL;
- OSErr err;
- Tcl_DString ds;
-
- TclInitSubsystems(argv0);
-
- GetCurrentProcess(&psn);
- info.processInfoLength = sizeof(ProcessInfoRec);
- info.processName = appName;
- info.processAppSpec = &fileSpec;
- GetProcessInformation(&psn, &info);
-
- if (tclExecutableName != NULL) {
- ckfree(tclExecutableName);
- tclExecutableName = NULL;
- }
-
- err = FSpPathFromLocation(&fileSpec, &pathLength, &pathName);
- HLock(pathName);
- Tcl_ExternalToUtfDString(NULL, *pathName, pathLength, &ds);
- HUnlock(pathName);
- DisposeHandle(pathName);
-
- tclExecutableName = (char *) ckalloc((unsigned)
- (Tcl_DStringLength(&ds) + 1));
- strcpy(tclExecutableName, Tcl_DStringValue(&ds));
- Tcl_DStringFree(&ds);
- return tclExecutableName;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpMatchInDirectory --
- *
- * This routine is used by the globbing code to search a
- * directory for all files which match a given pattern.
- *
- * Results:
- *
- * The return value is a standard Tcl result indicating whether an
- * error occurred in globbing. Errors are left in interp, good
- * results are lappended to resultPtr (which must be a valid object)
- *
- * Side effects:
- * None.
- *
- *---------------------------------------------------------------------- */
-
-int
-TclpMatchInDirectory(interp, resultPtr, pathPtr, pattern, types)
- Tcl_Interp *interp; /* Interpreter to receive errors. */
- Tcl_Obj *resultPtr; /* List object to lappend results. */
- Tcl_Obj *pathPtr; /* Contains path to directory to search. */
- CONST char *pattern; /* Pattern to match against. NULL or empty
- * means pathPtr is actually a single file
- * to check. */
- Tcl_GlobTypeData *types; /* Object containing list of acceptable types.
- * May be NULL. In particular the directory
- * flag is very important. */
-{
- OSType okType = 0;
- OSType okCreator = 0;
- Tcl_Obj *fileNamePtr;
-
- fileNamePtr = Tcl_FSGetTranslatedPath(interp, pathPtr);
- if (fileNamePtr == NULL) {
- return TCL_ERROR;
- }
-
- if (types != NULL) {
- if (types->macType != NULL) {
- Tcl_GetOSTypeFromObj(NULL, types->macType, &okType);
- }
- if (types->macCreator != NULL) {
- Tcl_GetOSTypeFromObj(NULL, types->macCreator, &okCreator);
- }
- }
-
- if (pattern == NULL || (*pattern == '\0')) {
- /* Match a single file directly */
- Tcl_StatBuf buf;
- CInfoPBRec paramBlock;
- FSSpec fileSpec;
-
- if (TclpObjLstat(fileNamePtr, &buf) != 0) {
- /* File doesn't exist */
- Tcl_DecrRefCount(fileNamePtr);
- return TCL_OK;
- }
-
- if (FspLLocationFromFsPath(fileNamePtr, &fileSpec) == noErr) {
- paramBlock.hFileInfo.ioCompletion = NULL;
- paramBlock.hFileInfo.ioNamePtr = fileSpec.name;
- paramBlock.hFileInfo.ioVRefNum = fileSpec.vRefNum;
- paramBlock.hFileInfo.ioFDirIndex = 0;
- paramBlock.hFileInfo.ioDirID = fileSpec.parID;
-
- PBGetCatInfo(&paramBlock, 0);
- }
-
- if (NativeMatchType(fileNamePtr, types, paramBlock.hFileInfo,
- okType, okCreator)) {
- int fnameLen;
- char *fname = Tcl_GetStringFromObj(pathPtr,&fnameLen);
- if ((fnameLen > 1) && (strchr(fname+1, ':') == NULL)) {
- Tcl_ListObjAppendElement(interp, resultPtr,
- Tcl_NewStringObj(fname+1, fnameLen-1));
- } else {
- Tcl_ListObjAppendElement(interp, resultPtr, pathPtr);
- }
- }
- Tcl_DecrRefCount(fileNamePtr);
- return TCL_OK;
- } else {
- char *fname;
- int fnameLen, result = TCL_OK;
- int baseLength;
- CInfoPBRec pb;
- OSErr err;
- FSSpec dirSpec;
- Boolean isDirectory;
- long dirID;
- short itemIndex;
- Str255 fileName;
- Tcl_DString fileString;
- Tcl_DString dsOrig;
-
- Tcl_DStringInit(&dsOrig);
- Tcl_DStringAppend(&dsOrig, Tcl_GetString(fileNamePtr), -1);
- baseLength = Tcl_DStringLength(&dsOrig);
-
- /*
- * Make sure that the directory part of the name really is a
- * directory.
- */
-
- Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&dsOrig),
- Tcl_DStringLength(&dsOrig), &fileString);
-
- err = FSpLocationFromPath(Tcl_DStringLength(&fileString),
- Tcl_DStringValue(&fileString), &dirSpec);
- Tcl_DStringFree(&fileString);
- if (err == noErr) {
- err = FSpGetDirectoryID(&dirSpec, &dirID, &isDirectory);
- }
-
- if ((err != noErr) || !isDirectory) {
- /*
- * Check if we had a relative path (unix style relative path
- * compatibility for glob)
- */
- Tcl_DStringFree(&dsOrig);
- Tcl_DStringAppend(&dsOrig, ":", 1);
- Tcl_DStringAppend(&dsOrig, Tcl_GetString(fileNamePtr), -1);
- baseLength = Tcl_DStringLength(&dsOrig);
-
- Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&dsOrig),
- Tcl_DStringLength(&dsOrig), &fileString);
-
- err = FSpLocationFromPath(Tcl_DStringLength(&fileString),
- Tcl_DStringValue(&fileString), &dirSpec);
- Tcl_DStringFree(&fileString);
- if (err == noErr) {
- err = FSpGetDirectoryID(&dirSpec, &dirID, &isDirectory);
- }
-
- if ((err != noErr) || !isDirectory) {
- Tcl_DStringFree(&dsOrig);
- Tcl_DecrRefCount(fileNamePtr);
- return TCL_OK;
- }
- }
-
- /* Make sure we have a trailing directory delimiter */
- if (Tcl_DStringValue(&dsOrig)[baseLength-1] != ':') {
- Tcl_DStringAppend(&dsOrig, ":", 1);
- baseLength++;
- }
-
- /*
- * Now open the directory for reading and iterate over the contents.
- */
-
- pb.hFileInfo.ioVRefNum = dirSpec.vRefNum;
- pb.hFileInfo.ioDirID = dirID;
- pb.hFileInfo.ioNamePtr = (StringPtr) fileName;
- pb.hFileInfo.ioFDirIndex = itemIndex = 1;
-
- while (1) {
- pb.hFileInfo.ioFDirIndex = itemIndex;
- pb.hFileInfo.ioDirID = dirID;
- err = PBGetCatInfoSync(&pb);
- if (err != noErr) {
- break;
- }
-
- /*
- * Now check to see if the file matches.
- */
-
- Tcl_ExternalToUtfDString(NULL, (char *) fileName + 1, fileName[0],
- &fileString);
- if (Tcl_StringMatch(Tcl_DStringValue(&fileString), pattern)) {
- Tcl_Obj *tempName;
- Tcl_DStringSetLength(&dsOrig, baseLength);
- Tcl_DStringAppend(&dsOrig, Tcl_DStringValue(&fileString), -1);
- fname = Tcl_DStringValue(&dsOrig);
- fnameLen = Tcl_DStringLength(&dsOrig);
-
- /*
- * We use this tempName in calls to check the file's
- * type below. We may also use it for the result.
- */
- tempName = Tcl_NewStringObj(fname, fnameLen);
- Tcl_IncrRefCount(tempName);
-
- /* Is the type acceptable? */
- if (NativeMatchType(tempName, types, pb.hFileInfo,
- okType, okCreator)) {
- if ((fnameLen > 1) && (strchr(fname+1, ':') == NULL)) {
- Tcl_ListObjAppendElement(interp, resultPtr,
- Tcl_NewStringObj(fname+1, fnameLen-1));
- } else {
- Tcl_ListObjAppendElement(interp, resultPtr, tempName);
- }
- }
- /*
- * This will free the object, unless it was inserted in
- * the result list above.
- */
- Tcl_DecrRefCount(tempName);
- }
- Tcl_DStringFree(&fileString);
- itemIndex++;
- }
-
- Tcl_DStringFree(&dsOrig);
- Tcl_DecrRefCount(fileNamePtr);
- return result;
- }
-}
-
-static int
-NativeMatchType(
- Tcl_Obj *tempName, /* Path to check */
- Tcl_GlobTypeData *types, /* Type description to match against */
- HFileInfo fileInfo, /* MacOS file info */
- OSType okType, /* Acceptable MacOS type, or zero */
- OSType okCreator) /* Acceptable MacOS creator, or zero */
-{
- if (types == NULL) {
- /* If invisible, don't return the file */
- if (fileInfo.ioFlFndrInfo.fdFlags & kIsInvisible) {
- return 0;
- }
- } else {
- Tcl_StatBuf buf;
-
- if (fileInfo.ioFlFndrInfo.fdFlags & kIsInvisible) {
- /* If invisible */
- if ((types->perm == 0) ||
- !(types->perm & TCL_GLOB_PERM_HIDDEN)) {
- return 0;
- }
- } else {
- /* Visible */
- if (types->perm & TCL_GLOB_PERM_HIDDEN) {
- return 0;
- }
- }
- if (types->perm != 0) {
- if (
- ((types->perm & TCL_GLOB_PERM_RONLY) &&
- !(fileInfo.ioFlAttrib & 1)) ||
- ((types->perm & TCL_GLOB_PERM_R) &&
- (TclpObjAccess(tempName, R_OK) != 0)) ||
- ((types->perm & TCL_GLOB_PERM_W) &&
- (TclpObjAccess(tempName, W_OK) != 0)) ||
- ((types->perm & TCL_GLOB_PERM_X) &&
- (TclpObjAccess(tempName, X_OK) != 0))
- ) {
- return 0;
- }
- }
- if (types->type != 0) {
- if (TclpObjStat(tempName, &buf) != 0) {
- /* Posix error occurred */
- return 0;
- }
- /*
- * In order bcdpfls as in 'find -t'
- */
- if (
- ((types->type & TCL_GLOB_TYPE_BLOCK) &&
- S_ISBLK(buf.st_mode)) ||
- ((types->type & TCL_GLOB_TYPE_CHAR) &&
- S_ISCHR(buf.st_mode)) ||
- ((types->type & TCL_GLOB_TYPE_DIR) &&
- S_ISDIR(buf.st_mode)) ||
- ((types->type & TCL_GLOB_TYPE_PIPE) &&
- S_ISFIFO(buf.st_mode)) ||
- ((types->type & TCL_GLOB_TYPE_FILE) &&
- S_ISREG(buf.st_mode))
-#ifdef S_ISSOCK
- || ((types->type & TCL_GLOB_TYPE_SOCK) &&
- S_ISSOCK(buf.st_mode))
-#endif
- ) {
- /* Do nothing -- this file is ok */
- } else {
- int typeOk = 0;
-#ifdef S_ISLNK
- if (types->type & TCL_GLOB_TYPE_LINK) {
- if (TclpObjLstat(tempName, &buf) == 0) {
- if (S_ISLNK(buf.st_mode)) {
- typeOk = 1;
- }
- }
- }
-#endif
- if (typeOk == 0) {
- return 0;
- }
- }
- }
- if (((okType != 0) && (okType !=
- fileInfo.ioFlFndrInfo.fdType)) ||
- ((okCreator != 0) && (okCreator !=
- fileInfo.ioFlFndrInfo.fdCreator))) {
- return 0;
- }
- }
- return 1;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpObjAccess --
- *
- * This function replaces the library version of access().
- *
- * Results:
- * See access documentation.
- *
- * Side effects:
- * See access documentation.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclpObjAccess(pathPtr, mode)
- Tcl_Obj *pathPtr;
- int mode;
-{
- HFileInfo fpb;
- HVolumeParam vpb;
- OSErr err;
- FSSpec fileSpec;
- Boolean isDirectory;
- long dirID;
- int full_mode = 0;
-
- err = FspLLocationFromFsPath(pathPtr, &fileSpec);
-
- if (err != noErr) {
- errno = TclMacOSErrorToPosixError(err);
- return -1;
- }
-
- /*
- * Fill the fpb & vpb struct up with info about file or directory.
- */
- FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
- vpb.ioVRefNum = fpb.ioVRefNum = fileSpec.vRefNum;
- vpb.ioNamePtr = fpb.ioNamePtr = fileSpec.name;
- if (isDirectory) {
- fpb.ioDirID = fileSpec.parID;
- } else {
- fpb.ioDirID = dirID;
- }
-
- fpb.ioFDirIndex = 0;
- err = PBGetCatInfoSync((CInfoPBPtr)&fpb);
- if (err == noErr) {
- vpb.ioVolIndex = 0;
- err = PBHGetVInfoSync((HParmBlkPtr)&vpb);
- if (err == noErr) {
- /*
- * Use the Volume Info & File Info to determine
- * access information. If we have got this far
- * we know the directory is searchable or the file
- * exists. (We have F_OK)
- */
-
- /*
- * Check to see if the volume is hardware or
- * software locked. If so we arn't W_OK.
- */
- if (mode & W_OK) {
- if ((vpb.ioVAtrb & 0x0080) || (vpb.ioVAtrb & 0x8000)) {
- errno = EROFS;
- return -1;
- }
- if (fpb.ioFlAttrib & 0x01) {
- errno = EACCES;
- return -1;
- }
- }
-
- /*
- * Directories are always searchable and executable. But only
- * files of type 'APPL' are executable.
- */
- if (!(fpb.ioFlAttrib & 0x10) && (mode & X_OK)
- && (fpb.ioFlFndrInfo.fdType != 'APPL')) {
- return -1;
- }
- }
- }
-
- if (err != noErr) {
- errno = TclMacOSErrorToPosixError(err);
- return -1;
- }
-
- return 0;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpObjChdir --
- *
- * This function replaces the library version of chdir().
- *
- * Results:
- * See chdir() documentation.
- *
- * Side effects:
- * See chdir() documentation. Also the cache maintained used by
- * Tcl_FSGetCwd() is deallocated and set to NULL.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclpObjChdir(pathPtr)
- Tcl_Obj *pathPtr;
-{
- FSSpec spec;
- OSErr err;
- Boolean isFolder;
- long dirID;
-
- err = FspLocationFromFsPath(pathPtr, &spec);
-
- if (err != noErr) {
- errno = ENOENT;
- return -1;
- }
-
- err = FSpGetDirectoryID(&spec, &dirID, &isFolder);
- if (err != noErr) {
- errno = ENOENT;
- return -1;
- }
-
- if (isFolder != true) {
- errno = ENOTDIR;
- return -1;
- }
-
- err = FSpSetDefaultDir(&spec);
- if (err != noErr) {
- switch (err) {
- case afpAccessDenied:
- errno = EACCES;
- break;
- default:
- errno = ENOENT;
- }
- return -1;
- }
-
- return 0;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpObjGetCwd --
- *
- * This function replaces the library version of getcwd().
- *
- * Results:
- * The result is a pointer to a string specifying the current
- * directory, or NULL if the current directory could not be
- * determined. If NULL is returned, an error message is left in the
- * interp's result. Storage for the result string is allocated in
- * bufferPtr; the caller must call Tcl_DStringFree() when the result
- * is no longer needed.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_Obj*
-TclpObjGetCwd(interp)
- Tcl_Interp *interp;
-{
- Tcl_DString ds;
- if (TclpGetCwd(interp, &ds) != NULL) {
- Tcl_Obj *cwdPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1);
- Tcl_IncrRefCount(cwdPtr);
- Tcl_DStringFree(&ds);
- return cwdPtr;
- } else {
- return NULL;
- }
-}
-
-CONST char *
-TclpGetCwd(
- Tcl_Interp *interp, /* If non-NULL, used for error reporting. */
- Tcl_DString *bufferPtr) /* Uninitialized or free DString filled
- * with name of current directory. */
-{
- FSSpec theSpec;
- int length;
- Handle pathHandle = NULL;
-
- if (FSpGetDefaultDir(&theSpec) != noErr) {
- if (interp != NULL) {
- Tcl_SetResult(interp, "error getting working directory name",
- TCL_STATIC);
- }
- return NULL;
- }
- if (FSpPathFromLocation(&theSpec, &length, &pathHandle) != noErr) {
- if (interp != NULL) {
- Tcl_SetResult(interp, "error getting working directory name",
- TCL_STATIC);
- }
- return NULL;
- }
- HLock(pathHandle);
- Tcl_ExternalToUtfDString(NULL, *pathHandle, length, bufferPtr);
- HUnlock(pathHandle);
- DisposeHandle(pathHandle);
-
- return Tcl_DStringValue(bufferPtr);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpReadlink --
- *
- * This function replaces the library version of readlink().
- *
- * Results:
- * The result is a pointer to a string specifying the contents
- * of the symbolic link given by 'path', or NULL if the symbolic
- * link could not be read. Storage for the result string is
- * allocated in bufferPtr; the caller must call Tcl_DStringFree()
- * when the result is no longer needed.
- *
- * Side effects:
- * See readlink() documentation.
- *
- *---------------------------------------------------------------------------
- */
-
-char *
-TclpReadlink(
- CONST char *path, /* Path of file to readlink (UTF-8). */
- Tcl_DString *linkPtr) /* Uninitialized or free DString filled
- * with contents of link (UTF-8). */
-{
- HFileInfo fpb;
- OSErr err;
- FSSpec fileSpec;
- Boolean isDirectory;
- Boolean wasAlias;
- long dirID;
- char fileName[257];
- char *end;
- Handle theString = NULL;
- int pathSize;
- Tcl_DString ds;
-
- Tcl_UtfToExternalDString(NULL, path, -1, &ds);
-
- /*
- * Remove ending colons if they exist.
- */
-
- while ((Tcl_DStringLength(&ds) != 0)
- && (Tcl_DStringValue(&ds)[Tcl_DStringLength(&ds) - 1] == ':')) {
- Tcl_DStringSetLength(&ds, Tcl_DStringLength(&ds) - 1);
- }
-
- end = strrchr(Tcl_DStringValue(&ds), ':');
- if (end == NULL ) {
- strcpy(fileName + 1, Tcl_DStringValue(&ds));
- } else {
- strcpy(fileName + 1, end + 1);
- Tcl_DStringSetLength(&ds, end + 1 - Tcl_DStringValue(&ds));
- }
- fileName[0] = (char) strlen(fileName + 1);
-
- /*
- * Create the file spec for the directory of the file
- * we want to look at.
- */
-
- if (end != NULL) {
- err = FSpLocationFromPath(Tcl_DStringLength(&ds),
- Tcl_DStringValue(&ds), &fileSpec);
- if (err != noErr) {
- Tcl_DStringFree(&ds);
- errno = EINVAL;
- return NULL;
- }
- } else {
- FSMakeFSSpecCompat(0, 0, NULL, &fileSpec);
- }
- Tcl_DStringFree(&ds);
-
- /*
- * Fill the fpb struct up with info about file or directory.
- */
-
- FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
- fpb.ioVRefNum = fileSpec.vRefNum;
- fpb.ioDirID = dirID;
- fpb.ioNamePtr = (StringPtr) fileName;
-
- fpb.ioFDirIndex = 0;
- err = PBGetCatInfoSync((CInfoPBPtr)&fpb);
- if (err != noErr) {
- errno = TclMacOSErrorToPosixError(err);
- return NULL;
- } else {
- if (fpb.ioFlAttrib & 0x10) {
- errno = EINVAL;
- return NULL;
- } else {
- if (fpb.ioFlFndrInfo.fdFlags & 0x8000) {
- /*
- * The file is a link!
- */
- } else {
- errno = EINVAL;
- return NULL;
- }
- }
- }
-
- /*
- * If we are here it's really a link - now find out
- * where it points to.
- */
- err = FSMakeFSSpecCompat(fileSpec.vRefNum, dirID, (StringPtr) fileName,
- &fileSpec);
- if (err == noErr) {
- err = ResolveAliasFile(&fileSpec, true, &isDirectory, &wasAlias);
- }
- if ((err == fnfErr) || wasAlias) {
- err = FSpPathFromLocation(&fileSpec, &pathSize, &theString);
- if (err != noErr) {
- DisposeHandle(theString);
- errno = ENAMETOOLONG;
- return NULL;
- }
- } else {
- errno = EINVAL;
- return NULL;
- }
-
- Tcl_ExternalToUtfDString(NULL, *theString, pathSize, linkPtr);
- DisposeHandle(theString);
-
- return Tcl_DStringValue(linkPtr);
-}
-
-static int
-TclpObjStatAlias _ANSI_ARGS_((Tcl_Obj *pathPtr, Tcl_StatBuf *bufPtr,
- Boolean resolveLink));
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpObjLstat --
- *
- * This function replaces the library version of lstat().
- *
- * Results:
- * See lstat() documentation.
- *
- * Side effects:
- * See lstat() documentation.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclpObjLstat(pathPtr, buf)
- Tcl_Obj *pathPtr;
- Tcl_StatBuf *buf;
-{
- return TclpObjStatAlias(pathPtr, buf, FALSE);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpObjStat --
- *
- * This function replaces the library version of stat().
- *
- * Results:
- * See stat() documentation.
- *
- * Side effects:
- * See stat() documentation.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclpObjStat(pathPtr, bufPtr)
- Tcl_Obj *pathPtr;
- Tcl_StatBuf *bufPtr;
-{
- return TclpObjStatAlias(pathPtr, bufPtr, TRUE);
-}
-
-
-static int
-TclpObjStatAlias (Tcl_Obj *pathPtr, Tcl_StatBuf *bufPtr, Boolean resolveLink)
-{
- HFileInfo fpb;
- HVolumeParam vpb;
- OSErr err;
- FSSpec fileSpec;
- Boolean isDirectory;
- long dirID;
-
- if (resolveLink)
- err = FspLocationFromFsPath(pathPtr, &fileSpec);
- else
- err = FspLLocationFromFsPath(pathPtr, &fileSpec);
-
- if (err != noErr) {
- errno = TclMacOSErrorToPosixError(err);
- return -1;
- }
-
- /*
- * Fill the fpb & vpb struct up with info about file or directory.
- */
-
- FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
- vpb.ioVRefNum = fpb.ioVRefNum = fileSpec.vRefNum;
- vpb.ioNamePtr = fpb.ioNamePtr = fileSpec.name;
- if (isDirectory) {
- fpb.ioDirID = fileSpec.parID;
- } else {
- fpb.ioDirID = dirID;
- }
-
- fpb.ioFDirIndex = 0;
- err = PBGetCatInfoSync((CInfoPBPtr)&fpb);
- if (err == noErr) {
- vpb.ioVolIndex = 0;
- err = PBHGetVInfoSync((HParmBlkPtr)&vpb);
- if (err == noErr && bufPtr != NULL) {
- /*
- * Files are always readable by everyone.
- */
-
- bufPtr->st_mode = S_IRUSR | S_IRGRP | S_IROTH;
-
- /*
- * Use the Volume Info & File Info to fill out stat buf.
- */
- if (fpb.ioFlAttrib & 0x10) {
- bufPtr->st_mode |= S_IFDIR;
- bufPtr->st_nlink = 2;
- } else {
- bufPtr->st_nlink = 1;
- if (fpb.ioFlFndrInfo.fdFlags & 0x8000) {
- bufPtr->st_mode |= S_IFLNK;
- } else {
- bufPtr->st_mode |= S_IFREG;
- }
- }
- if ((fpb.ioFlAttrib & 0x10) || (fpb.ioFlFndrInfo.fdType == 'APPL')) {
- /*
- * Directories and applications are executable by everyone.
- */
-
- bufPtr->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH;
- }
- if ((fpb.ioFlAttrib & 0x01) == 0){
- /*
- * If not locked, then everyone has write acces.
- */
-
- bufPtr->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
- }
- bufPtr->st_ino = fpb.ioDirID;
- bufPtr->st_dev = fpb.ioVRefNum;
- bufPtr->st_uid = -1;
- bufPtr->st_gid = -1;
- bufPtr->st_rdev = 0;
- bufPtr->st_size = fpb.ioFlLgLen;
- bufPtr->st_blksize = vpb.ioVAlBlkSiz;
- bufPtr->st_blocks = (bufPtr->st_size + bufPtr->st_blksize - 1)
- / bufPtr->st_blksize;
-
- /*
- * The times returned by the Mac file system are in the
- * local time zone. We convert them to GMT so that the
- * epoch starts from GMT. This is also consistent with
- * what is returned from "clock seconds".
- */
-
- bufPtr->st_atime = bufPtr->st_mtime = fpb.ioFlMdDat
- - TclpGetGMTOffset() + tcl_mac_epoch_offset;
- bufPtr->st_ctime = fpb.ioFlCrDat - TclpGetGMTOffset()
- + tcl_mac_epoch_offset;
- }
- }
-
- if (err != noErr) {
- errno = TclMacOSErrorToPosixError(err);
- }
-
- return (err == noErr ? 0 : -1);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_WaitPid --
- *
- * Fakes a call to wait pid.
- *
- * Results:
- * Always returns -1.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_Pid
-Tcl_WaitPid(
- Tcl_Pid pid,
- int *statPtr,
- int options)
-{
- return (Tcl_Pid) -1;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclMacFOpenHack --
- *
- * This function replaces fopen. It supports paths with alises.
- * Note, remember to undefine the fopen macro!
- *
- * Results:
- * See fopen documentation.
- *
- * Side effects:
- * See fopen documentation.
- *
- *----------------------------------------------------------------------
- */
-
-#undef fopen
-FILE *
-TclMacFOpenHack(
- CONST char *path,
- CONST char *mode)
-{
- OSErr err;
- FSSpec fileSpec;
- Handle pathString = NULL;
- int size;
- FILE * f;
-
- err = FSpLocationFromPath(strlen(path), path, &fileSpec);
- if ((err != noErr) && (err != fnfErr)) {
- return NULL;
- }
- err = FSpPathFromLocation(&fileSpec, &size, &pathString);
- if ((err != noErr) && (err != fnfErr)) {
- return NULL;
- }
-
- HLock(pathString);
- f = fopen(*pathString, mode);
- HUnlock(pathString);
- DisposeHandle(pathString);
- return f;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclpGetUserHome --
- *
- * This function takes the specified user name and finds their
- * home directory.
- *
- * Results:
- * The result is a pointer to a string specifying the user's home
- * directory, or NULL if the user's home directory could not be
- * determined. Storage for the result string is allocated in
- * bufferPtr; the caller must call Tcl_DStringFree() when the result
- * is no longer needed.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-char *
-TclpGetUserHome(name, bufferPtr)
- CONST char *name; /* User name for desired home directory. */
- Tcl_DString *bufferPtr; /* Uninitialized or free DString filled
- * with name of user's home directory. */
-{
- return NULL;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclMacOSErrorToPosixError --
- *
- * Given a Macintosh OSErr return the appropiate POSIX error.
- *
- * Results:
- * A Posix error.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclMacOSErrorToPosixError(
- int error) /* A Macintosh error. */
-{
- switch (error) {
- case noErr:
- return 0;
- case bdNamErr:
- return ENAMETOOLONG;
- case afpObjectTypeErr:
- return ENOTDIR;
- case fnfErr:
- case dirNFErr:
- return ENOENT;
- case dupFNErr:
- return EEXIST;
- case dirFulErr:
- case dskFulErr:
- return ENOSPC;
- case fBsyErr:
- return EBUSY;
- case tmfoErr:
- return ENFILE;
- case fLckdErr:
- case permErr:
- case afpAccessDenied:
- return EACCES;
- case wPrErr:
- case vLckdErr:
- return EROFS;
- case badMovErr:
- return EINVAL;
- case diffVolErr:
- return EXDEV;
- default:
- return EINVAL;
- }
-}
-
-int
-TclMacChmod(
- CONST char *path,
- int mode)
-{
- HParamBlockRec hpb;
- OSErr err;
- Str255 pathName;
- strcpy((char *) pathName + 1, path);
- pathName[0] = strlen(path);
- hpb.fileParam.ioNamePtr = pathName;
- hpb.fileParam.ioVRefNum = 0;
- hpb.fileParam.ioDirID = 0;
-
- if (mode & 0200) {
- err = PBHRstFLockSync(&hpb);
- } else {
- err = PBHSetFLockSync(&hpb);
- }
-
- if (err != noErr) {
- errno = TclMacOSErrorToPosixError(err);
- return -1;
- }
-
- return 0;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpTempFileName --
- *
- * This function returns a unique filename.
- *
- * Results:
- * Returns a valid Tcl_Obj* with refCount 0, or NULL on failure.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_Obj*
-TclpTempFileName()
-{
- char fileName[L_tmpnam];
-
- if (tmpnam(fileName) == NULL) { /* INTL: Native. */
- return NULL;
- }
-
- return TclpNativeToNormalized((ClientData) fileName);
-}
-
-#ifdef S_IFLNK
-
-Tcl_Obj*
-TclpObjLink(pathPtr, toPtr, linkAction)
- Tcl_Obj *pathPtr;
- Tcl_Obj *toPtr;
- int linkAction;
-{
- Tcl_Obj* link = NULL;
-
- if (toPtr != NULL) {
- if (TclpObjAccess(pathPtr, F_OK) != -1) {
- /* src exists */
- errno = EEXIST;
- return NULL;
- }
- if (TclpObjAccess(toPtr, F_OK) == -1) {
- /* target doesn't exist */
- errno = ENOENT;
- return NULL;
- }
-
- if (linkAction & TCL_CREATE_SYMBOLIC_LINK) {
- /* Needs to create a new link */
- FSSpec spec;
- FSSpec linkSpec;
- OSErr err;
- CONST char *path;
-
- err = FspLocationFromFsPath(toPtr, &spec);
- if (err != noErr) {
- errno = ENOENT;
- return NULL;
- }
-
- path = Tcl_FSGetNativePath(pathPtr);
- err = FSpLocationFromPath(strlen(path), path, &linkSpec);
- if (err == noErr) {
- err = dupFNErr; /* EEXIST. */
- } else {
- err = CreateAliasFile(&linkSpec, &spec);
- }
- if (err != noErr) {
- errno = TclMacOSErrorToPosixError(err);
- return NULL;
- }
- return toPtr;
- } else {
- errno = ENODEV;
- return NULL;
- }
- } else {
- Tcl_DString ds;
- Tcl_Obj *transPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
- if (transPtr == NULL) {
- return NULL;
- }
- if (TclpReadlink(Tcl_GetString(transPtr), &ds) != NULL) {
- link = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1);
- Tcl_IncrRefCount(link);
- Tcl_DStringFree(&ds);
- }
- Tcl_DecrRefCount(transPtr);
- }
- return link;
-}
-
-#endif
-
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclpFilesystemPathType --
- *
- * This function is part of the native filesystem support, and
- * returns the path type of the given path. Right now it simply
- * returns NULL. In the future it could return specific path
- * types, like 'HFS', 'HFS+', 'nfs', 'samba', 'FAT32', etc.
- *
- * Results:
- * NULL at present.
- *
- * Side effects:
- * None.
- *
- *---------------------------------------------------------------------------
- */
-Tcl_Obj*
-TclpFilesystemPathType(pathObjPtr)
- Tcl_Obj* pathObjPtr;
-{
- /* All native paths are of the same type */
- return NULL;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclpUtime --
- *
- * Set the modification date for a file.
- *
- * Results:
- * 0 on success, -1 on error.
- *
- * Side effects:
- * None.
- *
- *---------------------------------------------------------------------------
- */
-int
-TclpUtime(pathPtr, tval)
- Tcl_Obj *pathPtr; /* File to modify */
- struct utimbuf *tval; /* New modification date structure */
-{
- long gmt_offset=TclpGetGMTOffset();
- struct utimbuf local_tval;
- local_tval.actime=tval->actime+gmt_offset;
- local_tval.modtime=tval->modtime+gmt_offset;
- return utime(Tcl_FSGetNativePath(Tcl_FSGetNormalizedPath(NULL,pathPtr)),
- &local_tval);
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * CreateAliasFile --
- *
- * Creates an alias file located at aliasDest referring to the targetFile.
- *
- * Results:
- * 0 on success, OS error code on error.
- *
- * Side effects:
- * None.
- *
- *---------------------------------------------------------------------------
- */
-static OSErr
-CreateAliasFile(FSSpec *theAliasFile, FSSpec *targetFile)
-{
- CInfoPBRec cat;
- FInfo fndrInfo;
- AliasHandle theAlias;
- short saveRef, rsrc = -1;
- OSErr err;
-
- saveRef = CurResFile();
- /* set up the Finder information record for the alias file */
- cat.dirInfo.ioNamePtr = targetFile->name;
- cat.dirInfo.ioVRefNum = targetFile->vRefNum;
- cat.dirInfo.ioFDirIndex = 0;
- cat.dirInfo.ioDrDirID = targetFile->parID;
- err = PBGetCatInfoSync(&cat);
- if (err != noErr) goto bail;
- if ((cat.dirInfo.ioFlAttrib & 16) == 0) {
- /* file alias */
- switch (cat.hFileInfo.ioFlFndrInfo.fdType) {
- case 'APPL': fndrInfo.fdType = kApplicationAliasType; break;
- case 'APPC': fndrInfo.fdType = kApplicationCPAliasType; break;
- case 'APPD': fndrInfo.fdType = kApplicationDAAliasType; break;
- default: fndrInfo.fdType = cat.hFileInfo.ioFlFndrInfo.fdType; break;
- }
- fndrInfo.fdCreator = cat.hFileInfo.ioFlFndrInfo.fdCreator;
- } else {
- /* folder alias */
- fndrInfo.fdType = kContainerFolderAliasType;
- fndrInfo.fdCreator = 'MACS';
- }
- fndrInfo.fdFlags = kIsAlias;
- fndrInfo.fdLocation.v = 0;
- fndrInfo.fdLocation.h = 0;
- fndrInfo.fdFldr = 0;
- /* create new file and set the file information */
- FSpCreateResFile( theAliasFile, fndrInfo.fdCreator, fndrInfo.fdType, smSystemScript);
- if ((err = ResError()) != noErr) goto bail;
- err = FSpSetFInfo( theAliasFile, &fndrInfo);
- if (err != noErr) goto bail;
- /* save the alias resource */
- rsrc = FSpOpenResFile(theAliasFile, fsRdWrPerm);
- if (rsrc == -1) { err = ResError(); goto bail; }
- UseResFile(rsrc);
- err = NewAlias(theAliasFile, targetFile, &theAlias);
- if (err != noErr) goto bail;
- AddResource((Handle) theAlias, rAliasType, 0, theAliasFile->name);
- if ((err = ResError()) != noErr) goto bail;
- CloseResFile(rsrc);
- rsrc = -1;
- /* done */
- bail:
- if (rsrc != -1) CloseResFile(rsrc);
- UseResFile(saveRef);
- return err;
-}
diff --git a/mac/tclMacInit.c b/mac/tclMacInit.c
deleted file mode 100644
index fd7f1af..0000000
--- a/mac/tclMacInit.c
+++ /dev/null
@@ -1,805 +0,0 @@
-/*
- * tclMacInit.c --
- *
- * Contains the Mac-specific interpreter initialization functions.
- *
- * Copyright (c) 1995-1998 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include <AppleEvents.h>
-#include <AEDataModel.h>
-#include <AEObjects.h>
-#include <AEPackObject.h>
-#include <AERegistry.h>
-#include <Files.h>
-#include <Folders.h>
-#include <Gestalt.h>
-#include <TextUtils.h>
-#include <Resources.h>
-#include <Strings.h>
-#include "tclInt.h"
-#include "tclMacInt.h"
-#include "tclPort.h"
-#include "tclInitScript.h"
-
-/*
- * The following string is the startup script executed in new
- * interpreters. It looks on the library path and in the resource fork for
- * a script "init.tcl" that is compatible with this version of Tcl. The
- * init.tcl script does all of the real work of initialization.
- */
-
-static char initCmd[] = "if {[info proc tclInit]==\"\"} {\n\
-proc tclInit {} {\n\
-global tcl_pkgPath env\n\
-proc sourcePath {file} {\n\
- foreach i $::auto_path {\n\
- set init [file join $i $file.tcl]\n\
- if {[catch {uplevel #0 [list source $init]}] == 0} {\n\
- return\n\
- }\n\
- }\n\
- if {[catch {uplevel #0 [list source -rsrc $file]}] == 0} {\n\
- return\n\
- }\n\
- rename sourcePath {}\n\
- set msg \"Can't find $file resource or a usable $file.tcl file\"\n\
- append msg \" in the following directories:\"\n\
- append msg \" $::auto_path\"\n\
- append msg \" perhaps you need to install Tcl or set your\"\n\
- append msg \" TCL_LIBRARY environment variable?\"\n\
- error $msg\n\
-}\n\
-if {[info exists env(EXT_FOLDER)]} {\n\
- lappend tcl_pkgPath [file join $env(EXT_FOLDER) {Tool Command Language}]\n\
-}\n\
-if {[info exists tcl_pkgPath] == 0} {\n\
- set tcl_pkgPath {no extension folder}\n\
-}\n\
-sourcePath init\n\
-sourcePath auto\n\
-sourcePath package\n\
-sourcePath history\n\
-sourcePath word\n\
-sourcePath parray\n\
-rename sourcePath {}\n\
-} }\n\
-tclInit";
-
-/*
- * The following structures are used to map the script/language codes of a
- * font to the name that should be passed to Tcl_GetEncoding() to obtain
- * the encoding for that font. The set of numeric constants is fixed and
- * defined by Apple.
- */
-
-typedef struct Map {
- int numKey;
- char *strKey;
-} Map;
-
-static Map scriptMap[] = {
- {smRoman, "macRoman"},
- {smJapanese, "macJapan"},
- {smTradChinese, "macChinese"},
- {smKorean, "macKorean"},
- {smArabic, "macArabic"},
- {smHebrew, "macHebrew"},
- {smGreek, "macGreek"},
- {smCyrillic, "macCyrillic"},
- {smRSymbol, "macRSymbol"},
- {smDevanagari, "macDevanagari"},
- {smGurmukhi, "macGurmukhi"},
- {smGujarati, "macGujarati"},
- {smOriya, "macOriya"},
- {smBengali, "macBengali"},
- {smTamil, "macTamil"},
- {smTelugu, "macTelugu"},
- {smKannada, "macKannada"},
- {smMalayalam, "macMalayalam"},
- {smSinhalese, "macSinhalese"},
- {smBurmese, "macBurmese"},
- {smKhmer, "macKhmer"},
- {smThai, "macThailand"},
- {smLaotian, "macLaos"},
- {smGeorgian, "macGeorgia"},
- {smArmenian, "macArmenia"},
- {smSimpChinese, "macSimpChinese"},
- {smTibetan, "macTIbet"},
- {smMongolian, "macMongolia"},
- {smGeez, "macEthiopia"},
- {smEastEurRoman, "macCentEuro"},
- {smVietnamese, "macVietnam"},
- {smExtArabic, "macSindhi"},
- {NULL, NULL}
-};
-
-static Map romanMap[] = {
- {langCroatian, "macCroatian"},
- {langSlovenian, "macCroatian"},
- {langIcelandic, "macIceland"},
- {langRomanian, "macRomania"},
- {langTurkish, "macTurkish"},
- {langGreek, "macGreek"},
- {NULL, NULL}
-};
-
-static Map cyrillicMap[] = {
- {langUkrainian, "macUkraine"},
- {langBulgarian, "macBulgaria"},
- {NULL, NULL}
-};
-
-static int GetFinderFont(int *finderID);
-
-/* Used to store the encoding used for binary files */
-static Tcl_Encoding binaryEncoding = NULL;
-/* Has the basic library path encoding issue been fixed */
-static int libraryPathEncodingFixed = 0;
-
-
-/*
- *----------------------------------------------------------------------
- *
- * GetFinderFont --
- *
- * Gets the "views" font of the Macintosh Finder
- *
- * Results:
- * Standard Tcl result, and sets finderID to the font family
- * id for the current finder font.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-static int
-GetFinderFont(int *finderID)
-{
- OSErr err = noErr;
- OSType finderPrefs, viewFont = 'vfnt';
- DescType returnType;
- Size returnSize;
- long result, sys8Mask = 0x0800;
- static AppleEvent outgoingAevt = {typeNull, NULL};
- AppleEvent returnAevt;
- AEAddressDesc fndrAddress;
- AEDesc nullContainer = {typeNull, NULL},
- tempDesc = {typeNull, NULL},
- tempDesc2 = {typeNull, NULL},
- finalDesc = {typeNull, NULL};
- const OSType finderSignature = 'MACS';
-
-
- if (outgoingAevt.descriptorType == typeNull) {
- if ((Gestalt(gestaltSystemVersion, &result) != noErr)
- || (result >= sys8Mask)) {
- finderPrefs = 'pfrp';
- } else {
- finderPrefs = 'pvwp';
- }
-
- AECreateDesc(typeApplSignature, &finderSignature,
- sizeof(finderSignature), &fndrAddress);
-
- err = AECreateAppleEvent(kAECoreSuite, kAEGetData, &fndrAddress,
- kAutoGenerateReturnID, kAnyTransactionID, &outgoingAevt);
-
- AEDisposeDesc(&fndrAddress);
-
- /*
- * The structure is:
- * the property view font ('vfnt')
- * of the property view preferences ('pvwp')
- * of the Null Container (i.e. the Finder itself).
- */
-
- AECreateDesc(typeType, &finderPrefs, sizeof(finderPrefs), &tempDesc);
- err = CreateObjSpecifier(typeType, &nullContainer, formPropertyID,
- &tempDesc, true, &tempDesc2);
- AECreateDesc(typeType, &viewFont, sizeof(viewFont), &tempDesc);
- err = CreateObjSpecifier(typeType, &tempDesc2, formPropertyID,
- &tempDesc, true, &finalDesc);
-
- AEPutKeyDesc(&outgoingAevt, keyDirectObject, &finalDesc);
- AEDisposeDesc(&finalDesc);
- }
-
- err = AESend(&outgoingAevt, &returnAevt, kAEWaitReply, kAEHighPriority,
- kAEDefaultTimeout, NULL, NULL);
- if (err == noErr) {
- err = AEGetKeyPtr(&returnAevt, keyDirectObject, typeInteger,
- &returnType, (void *) finderID, sizeof(int), &returnSize);
- if (err == noErr) {
- return TCL_OK;
- }
- }
- return TCL_ERROR;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclMacGetFontEncoding --
- *
- * Determine the encoding of the specified font. The encoding
- * can be used to convert bytes from UTF-8 into the encoding of
- * that font.
- *
- * Results:
- * The return value is a string that specifies the font's encoding
- * and that can be passed to Tcl_GetEncoding() to construct the
- * encoding. If the font's encoding could not be identified, NULL
- * is returned.
- *
- * Side effects:
- * None.
- *
- *---------------------------------------------------------------------------
- */
-
-char *
-TclMacGetFontEncoding(
- int fontId)
-{
- int script, lang;
- char *name;
- Map *mapPtr;
-
- script = FontToScript(fontId);
- lang = GetScriptVariable(script, smScriptLang);
- name = NULL;
- if (script == smRoman) {
- for (mapPtr = romanMap; mapPtr->strKey != NULL; mapPtr++) {
- if (mapPtr->numKey == lang) {
- name = mapPtr->strKey;
- break;
- }
- }
- } else if (script == smCyrillic) {
- for (mapPtr = cyrillicMap; mapPtr->strKey != NULL; mapPtr++) {
- if (mapPtr->numKey == lang) {
- name = mapPtr->strKey;
- break;
- }
- }
- }
- if (name == NULL) {
- for (mapPtr = scriptMap; mapPtr->strKey != NULL; mapPtr++) {
- if (mapPtr->numKey == script) {
- name = mapPtr->strKey;
- break;
- }
- }
- }
- return name;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclpInitPlatform --
- *
- * Initialize all the platform-dependant things like signals and
- * floating-point error handling.
- *
- * Called at process initialization time.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *---------------------------------------------------------------------------
- */
-
-void
-TclpInitPlatform()
-{
- tclPlatform = TCL_PLATFORM_MAC;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclpInitLibraryPath --
- *
- * Initialize the library path at startup. We have a minor
- * metacircular problem that we don't know the encoding of the
- * operating system but we may need to talk to operating system
- * to find the library directories so that we know how to talk to
- * the operating system.
- *
- * We do not know the encoding of the operating system.
- * We do know that the encoding is some multibyte encoding.
- * In that multibyte encoding, the characters 0..127 are equivalent
- * to ascii.
- *
- * So although we don't know the encoding, it's safe:
- * to look for the last colon character in a path in the encoding.
- * to append an ascii string to a path.
- * to pass those strings back to the operating system.
- *
- * But any strings that we remembered before we knew the encoding of
- * the operating system must be translated to UTF-8 once we know the
- * encoding so that the rest of Tcl can use those strings.
- *
- * This call sets the library path to strings in the unknown native
- * encoding. TclpSetInitialEncodings() will translate the library
- * path from the native encoding to UTF-8 as soon as it determines
- * what the native encoding actually is.
- *
- * Called at process initialization time.
- *
- * Results:
- * Return 1, indicating that the UTF may be dirty and require "cleanup"
- * after encodings are initialized.
- *
- * Side effects:
- * None.
- *
- *---------------------------------------------------------------------------
- */
-
-int
-TclpInitLibraryPath(argv0)
- CONST char *argv0; /* Name of executable from argv[0] to main().
- * Not used because we can determine the name
- * by querying the module handle. */
-{
- Tcl_Obj *objPtr, *pathPtr;
- CONST char *str;
- Tcl_DString ds;
-
- TclMacCreateEnv();
-
- pathPtr = Tcl_NewObj();
-
- /*
- * Look for the library relative to default encoding dir.
- */
-
- str = Tcl_GetDefaultEncodingDir();
- if ((str != NULL) && (str[0] != '\0')) {
- objPtr = Tcl_NewStringObj(str, -1);
- Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
- }
-
- str = TclGetEnv("TCL_LIBRARY", &ds);
- if ((str != NULL) && (str[0] != '\0')) {
- /*
- * If TCL_LIBRARY is set, search there.
- */
-
- objPtr = Tcl_NewStringObj(str, Tcl_DStringLength(&ds));
- Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
- Tcl_DStringFree(&ds);
- }
-
- objPtr = TclGetLibraryPath();
- if (objPtr != NULL) {
- Tcl_ListObjAppendList(NULL, pathPtr, objPtr);
- }
-
- /*
- * lappend path [file join $env(EXT_FOLDER) \
- * "Tool Command Language" "tcl[info version]"
- */
-
- str = TclGetEnv("EXT_FOLDER", &ds);
- if ((str != NULL) && (str[0] != '\0')) {
- Tcl_DString libPath, path;
- CONST char *argv[3];
-
- argv[0] = str;
- argv[1] = "Tool Command Language";
- Tcl_DStringInit(&libPath);
- Tcl_DStringAppend(&libPath, "tcl", -1);
- argv[2] = Tcl_DStringAppend(&libPath, TCL_VERSION, -1);
- Tcl_DStringInit(&path);
- str = Tcl_JoinPath(3, argv, &path);
- objPtr = Tcl_NewStringObj(str, Tcl_DStringLength(&path));
- Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
- Tcl_DStringFree(&ds);
- Tcl_DStringFree(&libPath);
- Tcl_DStringFree(&path);
- }
- TclSetLibraryPath(pathPtr);
-
- return 1; /* 1 indicates that pathPtr may be dirty utf (needs cleaning) */
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclpSetInitialEncodings --
- *
- * Based on the locale, determine the encoding of the operating
- * system and the default encoding for newly opened files.
- *
- * Called at process initialization time, and part way through
- * startup, we verify that the initial encodings were correctly
- * setup. Depending on Tcl's environment, there may not have been
- * enough information first time through (above).
- *
- * Results:
- * None.
- *
- * Side effects:
- * The Tcl library path is converted from native encoding to UTF-8,
- * on the first call, and the encodings may be changed on first or
- * second call.
- *
- *---------------------------------------------------------------------------
- */
-
-void
-TclpSetInitialEncodings()
-{
- CONST char *encoding;
- Tcl_Obj *pathPtr;
- int fontId, err;
-
- fontId = 0;
- GetFinderFont(&fontId);
- encoding = TclMacGetFontEncoding(fontId);
- if (encoding == NULL) {
- encoding = "macRoman";
- }
-
- err = Tcl_SetSystemEncoding(NULL, encoding);
-
- if (err == TCL_OK && libraryPathEncodingFixed == 0) {
-
- /*
- * Until the system encoding was actually set, the library path was
- * actually in the native multi-byte encoding, and not really UTF-8
- * as advertised. We cheated as follows:
- *
- * 1. It was safe to allow the Tcl_SetSystemEncoding() call to
- * append the ASCII chars that make up the encoding's filename to
- * the names (in the native encoding) of directories in the library
- * path, since all Unix multi-byte encodings have ASCII in the
- * beginning.
- *
- * 2. To open the encoding file, the native bytes in the file name
- * were passed to the OS, without translating from UTF-8 to native,
- * because the name was already in the native encoding.
- *
- * Now that the system encoding was actually successfully set,
- * translate all the names in the library path to UTF-8. That way,
- * next time we search the library path, we'll translate the names
- * from UTF-8 to the system encoding which will be the native
- * encoding.
- */
-
- pathPtr = TclGetLibraryPath();
- if (pathPtr != NULL) {
- int i, objc;
- Tcl_Obj **objv;
-
- objc = 0;
- Tcl_ListObjGetElements(NULL, pathPtr, &objc, &objv);
- for (i = 0; i < objc; i++) {
- int length;
- char *string;
- Tcl_DString ds;
-
- string = Tcl_GetStringFromObj(objv[i], &length);
- Tcl_ExternalToUtfDString(NULL, string, length, &ds);
- Tcl_SetStringObj(objv[i], Tcl_DStringValue(&ds),
- Tcl_DStringLength(&ds));
- Tcl_DStringFree(&ds);
- }
- Tcl_InvalidateStringRep(pathPtr);
- }
- libraryPathEncodingFixed = 1;
- }
-
- /* This is only ever called from the startup thread */
- if (binaryEncoding == NULL) {
- /*
- * Keep the iso8859-1 encoding preloaded. The IO package uses
- * it for gets on a binary channel.
- */
- binaryEncoding = Tcl_GetEncoding(NULL, "iso8859-1");
- }
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * TclpSetVariables --
- *
- * Performs platform-specific interpreter initialization related to
- * the tcl_library and tcl_platform variables, and other platform-
- * specific things.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Sets "tcl_library" and "tcl_platform" Tcl variables.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpSetVariables(interp)
- Tcl_Interp *interp;
-{
- long int gestaltResult;
- int minor, major, objc;
- Tcl_Obj **objv;
- char versStr[2 * TCL_INTEGER_SPACE];
- CONST char *str;
- Tcl_Obj *pathPtr;
- Tcl_DString ds;
-
- str = "no library";
- pathPtr = TclGetLibraryPath();
- if (pathPtr != NULL) {
- objc = 0;
- Tcl_ListObjGetElements(NULL, pathPtr, &objc, &objv);
- if (objc > 0) {
- str = Tcl_GetStringFromObj(objv[0], NULL);
- }
- }
- Tcl_SetVar(interp, "tcl_library", str, TCL_GLOBAL_ONLY);
-
- if (pathPtr != NULL) {
- Tcl_SetVar2Ex(interp, "tcl_pkgPath", NULL, pathPtr, TCL_GLOBAL_ONLY);
- }
-
- Tcl_SetVar2(interp, "tcl_platform", "platform", "macintosh",
- TCL_GLOBAL_ONLY);
- Tcl_SetVar2(interp, "tcl_platform", "os", "MacOS", TCL_GLOBAL_ONLY);
- Gestalt(gestaltSystemVersion, &gestaltResult);
- major = (gestaltResult & 0x0000FF00) >> 8;
- minor = (gestaltResult & 0x000000F0) >> 4;
- sprintf(versStr, "%d.%d", major, minor);
- Tcl_SetVar2(interp, "tcl_platform", "osVersion", versStr, TCL_GLOBAL_ONLY);
-#if GENERATINGPOWERPC
- Tcl_SetVar2(interp, "tcl_platform", "machine", "ppc", TCL_GLOBAL_ONLY);
-#else
- Tcl_SetVar2(interp, "tcl_platform", "machine", "68k", TCL_GLOBAL_ONLY);
-#endif
-
- /*
- * Copy USER or LOGIN environment variable into tcl_platform(user)
- * These are set by SystemVariables in tclMacEnv.c
- */
-
- Tcl_DStringInit(&ds);
- str = TclGetEnv("USER", &ds);
- if (str == NULL) {
- str = TclGetEnv("LOGIN", &ds);
- if (str == NULL) {
- str = "";
- }
- }
- Tcl_SetVar2(interp, "tcl_platform", "user", str, TCL_GLOBAL_ONLY);
- Tcl_DStringFree(&ds);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpCheckStackSpace --
- *
- * On a 68K Mac, we can detect if we are about to blow the stack.
- * Called before an evaluation can happen when nesting depth is
- * checked.
- *
- * Results:
- * 1 if there is enough stack space to continue; 0 if not.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclpCheckStackSpace()
-{
- return StackSpace() > TCL_MAC_STACK_THRESHOLD;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpFindVariable --
- *
- * Locate the entry in environ for a given name. On Unix and Macthis
- * routine is case sensitive, on Windows this matches mixed case.
- *
- * Results:
- * The return value is the index in environ of an entry with the
- * name "name", or -1 if there is no such entry. The integer at
- * *lengthPtr is filled in with the length of name (if a matching
- * entry is found) or the length of the environ array (if no matching
- * entry is found).
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclpFindVariable(name, lengthPtr)
- CONST char *name; /* Name of desired environment variable
- * (native). */
- int *lengthPtr; /* Used to return length of name (for
- * successful searches) or number of non-NULL
- * entries in environ (for unsuccessful
- * searches). */
-{
- int i, result = -1;
- register CONST char *env, *p1, *p2;
- Tcl_DString envString;
-
- Tcl_DStringInit(&envString);
- for (i = 0, env = environ[i]; env != NULL; i++, env = environ[i]) {
- p1 = Tcl_ExternalToUtfDString(NULL, env, -1, &envString);
- p2 = name;
-
- for (; *p2 == *p1; p1++, p2++) {
- /* NULL loop body. */
- }
- if ((*p1 == '=') && (*p2 == '\0')) {
- *lengthPtr = p2 - name;
- result = i;
- goto done;
- }
-
- Tcl_DStringFree(&envString);
- }
-
- *lengthPtr = i;
-
- done:
- Tcl_DStringFree(&envString);
- return result;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_Init --
- *
- * This procedure is typically invoked by Tcl_AppInit procedures
- * to perform additional initialization for a Tcl interpreter,
- * such as sourcing the "init.tcl" script.
- *
- * Results:
- * Returns a standard Tcl completion code and sets the interp's result
- * if there is an error.
- *
- * Side effects:
- * Depends on what's in the init.tcl script.
- *
- *----------------------------------------------------------------------
- */
-
-int
-Tcl_Init(
- Tcl_Interp *interp) /* Interpreter to initialize. */
-{
- Tcl_Obj *pathPtr;
-
- if (tclPreInitScript != NULL) {
- if (Tcl_Eval(interp, tclPreInitScript) == TCL_ERROR) {
- return (TCL_ERROR);
- };
- }
-
- /*
- * For Macintosh applications the Init function may be contained in
- * the application resources. If it exists we use it - otherwise we
- * look in the tcl_library directory. Ditto for the history command.
- */
-
- pathPtr = TclGetLibraryPath();
- if (pathPtr == NULL) {
- pathPtr = Tcl_NewObj();
- }
- Tcl_IncrRefCount(pathPtr);
- Tcl_SetVar2Ex(interp, "auto_path", NULL, pathPtr, TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(pathPtr);
- return Tcl_Eval(interp, initCmd);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_SourceRCFile --
- *
- * This procedure is typically invoked by Tcl_Main or Tk_Main
- * procedure to source an application specific rc file into the
- * interpreter at startup time. This will either source a file
- * in the "tcl_rcFileName" variable or a TEXT resource in the
- * "tcl_rcRsrcName" variable.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Depends on what's in the rc script.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tcl_SourceRCFile(
- Tcl_Interp *interp) /* Interpreter to source rc file into. */
-{
- Tcl_DString temp;
- CONST char *fileName;
- Tcl_Channel errChannel;
- Handle h;
-
- fileName = Tcl_GetVar(interp, "tcl_rcFileName", TCL_GLOBAL_ONLY);
-
- if (fileName != NULL) {
- Tcl_Channel c;
- CONST char *fullName;
-
- Tcl_DStringInit(&temp);
- fullName = Tcl_TranslateFileName(interp, fileName, &temp);
- if (fullName == NULL) {
- /*
- * Couldn't translate the file name (e.g. it referred to a
- * bogus user or there was no HOME environment variable).
- * Just do nothing.
- */
- } else {
-
- /*
- * Test for the existence of the rc file before trying to read it.
- */
-
- c = Tcl_OpenFileChannel(NULL, fullName, "r", 0);
- if (c != (Tcl_Channel) NULL) {
- Tcl_Close(NULL, c);
- if (Tcl_EvalFile(interp, fullName) != TCL_OK) {
- errChannel = Tcl_GetStdChannel(TCL_STDERR);
- if (errChannel) {
- Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
- Tcl_WriteChars(errChannel, "\n", 1);
- }
- }
- }
- }
- Tcl_DStringFree(&temp);
- }
-
- fileName = Tcl_GetVar(interp, "tcl_rcRsrcName", TCL_GLOBAL_ONLY);
-
- if (fileName != NULL) {
- Str255 rezName;
- Tcl_DString ds;
- Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
- strcpy((char *) rezName + 1, Tcl_DStringValue(&ds));
- rezName[0] = (unsigned) Tcl_DStringLength(&ds);
- h = GetNamedResource('TEXT', rezName);
- Tcl_DStringFree(&ds);
- if (h != NULL) {
- if (Tcl_MacEvalResource(interp, fileName, 0, NULL) != TCL_OK) {
- errChannel = Tcl_GetStdChannel(TCL_STDERR);
- if (errChannel) {
- Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
- Tcl_WriteChars(errChannel, "\n", 1);
- }
- }
- Tcl_ResetResult(interp);
- ReleaseResource(h);
- }
- }
-}
diff --git a/mac/tclMacInt.h b/mac/tclMacInt.h
deleted file mode 100644
index 9e18889..0000000
--- a/mac/tclMacInt.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * tclMacInt.h --
- *
- * Declarations of Macintosh specific shared variables and procedures.
- *
- * Copyright (c) 1996-1998 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#ifndef _TCLMACINT
-#define _TCLMACINT
-
-#ifndef _TCLINT
-#include "tclInt.h"
-#endif
-#ifndef _TCLPORT
-#include "tclPort.h"
-#endif
-
-#include <Events.h>
-#include <Files.h>
-
-/*
- * Defines to control stack behavior.
- *
- * The Tcl8.2 regexp code is highly recursive for patterns with many
- * subexpressions. So we have to increase the stack space to accomodate.
- * 512 K is good enough for ordinary work, but you need 768 to pass the Tcl
- * regexp testsuite.
- *
- * For the PPC, you need to set the stack space in the Project file.
- *
- */
-
-#ifdef TCL_TEST
-# define TCL_MAC_68K_STACK_GROWTH (768*1024)
-#else
-# define TCL_MAC_68K_STACK_GROWTH (512*1024)
-#endif
-
-#define TCL_MAC_STACK_THRESHOLD 16384
-
-#ifdef BUILD_tcl
-# undef TCL_STORAGE_CLASS
-# define TCL_STORAGE_CLASS DLLEXPORT
-#endif
-
-/*
- * This flag is passed to TclMacRegisterResourceFork
- * by a file (usually a library) whose resource fork
- * should not be closed by the resource command.
- */
-
-#define TCL_RESOURCE_DONT_CLOSE 2
-
-/*
- * Typedefs used by Macintosh parts of Tcl.
- */
-
-/*
- * Prototypes of Mac only internal functions.
- */
-
-EXTERN char * TclMacGetFontEncoding _ANSI_ARGS_((int fontId));
-EXTERN int TclMacHaveThreads _ANSI_ARGS_((void));
-EXTERN long TclpGetGMTOffset _ANSI_ARGS_((void));
-
-# undef TCL_STORAGE_CLASS
-# define TCL_STORAGE_CLASS DLLIMPORT
-
-#include "tclIntPlatDecls.h"
-
-#endif /* _TCLMACINT */
diff --git a/mac/tclMacInterupt.c b/mac/tclMacInterupt.c
deleted file mode 100644
index 008be31..0000000
--- a/mac/tclMacInterupt.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * tclMacInterupt.c --
- *
- * This file contains routines that deal with the Macintosh's low level
- * time manager. This code provides a better resolution timer than what
- * can be provided by WaitNextEvent.
- *
- * Copyright (c) 1996 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include "tclInt.h"
-#include "tclMacInt.h"
-#include <LowMem.h>
-#include <Processes.h>
-#include <Timer.h>
-
-/*
- * Data structure for timer tasks.
- */
-typedef struct TMInfo {
- TMTask tmTask;
- ProcessSerialNumber psn;
- Point lastPoint;
- Point newPoint;
- long currentA5;
- long ourA5;
- int installed;
-} TMInfo;
-
-/*
- * Globals used within this file.
- */
-
-static TimerUPP sleepTimerProc = NULL;
-static int interuptsInited = false;
-static ProcessSerialNumber applicationPSN;
-#define MAX_TIMER_ARRAY_SIZE 16
-static TMInfo timerInfoArray[MAX_TIMER_ARRAY_SIZE];
-static int topTimerElement = 0;
-
-/*
- * Prototypes for procedures that are referenced only in this file:
- */
-
-#if !GENERATINGCFM
-static TMInfo * GetTMInfo(void) ONEWORDINLINE(0x2E89); /* MOVE.L A1,(SP) */
-#endif
-static void SleepTimerProc _ANSI_ARGS_((void));
-static pascal void CleanUpExitProc _ANSI_ARGS_((void));
-static void InitInteruptSystem _ANSI_ARGS_((void));
-
-/*
- *----------------------------------------------------------------------
- *
- * InitInteruptSystem --
- *
- * Does various initialization for the functions used in this
- * file. Sets up Universial Pricedure Pointers, installs a trap
- * patch for ExitToShell, etc.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Various initialization.
- *
- *----------------------------------------------------------------------
- */
-
-void
-InitInteruptSystem()
-{
- int i;
-
- sleepTimerProc = NewTimerProc(SleepTimerProc);
- GetCurrentProcess(&applicationPSN);
- for (i = 0; i < MAX_TIMER_ARRAY_SIZE; i++) {
- timerInfoArray[i].installed = false;
- }
-
- /*
- * Install the ExitToShell patch. We use this patch instead
- * of the Tcl exit mechanism because we need to ensure that
- * these routines are cleaned up even if we crash or are forced
- * to quit. There are some circumstances when the Tcl exit
- * handlers may not fire.
- */
-
- TclMacInstallExitToShellPatch(CleanUpExitProc);
- interuptsInited = true;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclMacStartTimer --
- *
- * Install a Time Manager task to wake our process up in the
- * future. The process should get a NULL event after ms
- * milliseconds.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Schedules our process to wake up.
- *
- *----------------------------------------------------------------------
- */
-
-void *
-TclMacStartTimer(
- long ms) /* Milliseconds. */
-{
- TMInfo *timerInfoPtr;
-
- if (!interuptsInited) {
- InitInteruptSystem();
- }
-
- /*
- * Obtain a pointer for the timer. We only allocate up
- * to MAX_TIMER_ARRAY_SIZE timers. If we are past that
- * max we return NULL.
- */
- if (topTimerElement < MAX_TIMER_ARRAY_SIZE) {
- timerInfoPtr = &timerInfoArray[topTimerElement];
- topTimerElement++;
- } else {
- return NULL;
- }
-
- /*
- * Install timer to wake process in ms milliseconds.
- */
- timerInfoPtr->tmTask.tmAddr = sleepTimerProc;
- timerInfoPtr->tmTask.tmWakeUp = 0;
- timerInfoPtr->tmTask.tmReserved = 0;
- timerInfoPtr->psn = applicationPSN;
- timerInfoPtr->installed = true;
-
- InsTime((QElemPtr) timerInfoPtr);
- PrimeTime((QElemPtr) timerInfoPtr, (long) ms);
-
- return (void *) timerInfoPtr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclMacRemoveTimer --
- *
- * Remove the timer event from the Time Manager.
- *
- * Results:
- * None.
- *
- * Side effects:
- * A scheduled timer would be removed.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclMacRemoveTimer(
- void * timerToken) /* Token got from start timer. */
-{
- TMInfo *timerInfoPtr = (TMInfo *) timerToken;
-
- if (timerInfoPtr == NULL) {
- return;
- }
-
- RmvTime((QElemPtr) timerInfoPtr);
- timerInfoPtr->installed = false;
- topTimerElement--;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclMacTimerExpired --
- *
- * Check to see if the installed timer has expired.
- *
- * Results:
- * True if timer has expired, false otherwise.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclMacTimerExpired(
- void * timerToken) /* Our token again. */
-{
- TMInfo *timerInfoPtr = (TMInfo *) timerToken;
-
- if ((timerInfoPtr == NULL) ||
- !(timerInfoPtr->tmTask.qType & kTMTaskActive)) {
- return true;
- } else {
- return false;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * SleepTimerProc --
- *
- * Time proc is called by the is a callback routine placed in the
- * system by Tcl_Sleep. The routine is called at interupt time
- * and threrfor can not move or allocate memory. This call will
- * schedule our process to wake up the next time the process gets
- * around to consider running it.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Schedules our process to wake up.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-SleepTimerProc()
-{
- /*
- * In CFM code we can access our code directly. In 68k code that
- * isn't based on CFM we must do a glorious hack. The function
- * GetTMInfo is an inline assembler call that moves the pointer
- * at A1 to the top of the stack. The Time Manager keeps the TMTask
- * info record there before calling this call back. In order for
- * this to work the infoPtr argument must be the *last* item on the
- * stack. If we "piggyback" our data to the TMTask info record we
- * can get access to the information we need. While this is really
- * ugly - it's the way Apple recomends it be done - go figure...
- */
-
-#if GENERATINGCFM
- WakeUpProcess(&applicationPSN);
-#else
- TMInfo * infoPtr;
-
- infoPtr = GetTMInfo();
- WakeUpProcess(&infoPtr->psn);
-#endif
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * CleanUpExitProc --
- *
- * This procedure is invoked as an exit handler when ExitToShell
- * is called. It removes the system level timer handler if it
- * is installed. This must be called or the Mac OS will more than
- * likely crash.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static pascal void
-CleanUpExitProc()
-{
- int i;
-
- for (i = 0; i < MAX_TIMER_ARRAY_SIZE; i++) {
- if (timerInfoArray[i].installed) {
- RmvTime((QElemPtr) &timerInfoArray[i]);
- timerInfoArray[i].installed = false;
- }
- }
-}
diff --git a/mac/tclMacLibrary.c b/mac/tclMacLibrary.c
deleted file mode 100644
index 7db83c5..0000000
--- a/mac/tclMacLibrary.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * tclMacLibrary.c --
- *
- * This file should be included in Tcl extensions that want to
- * automatically open their resource forks when the code is linked.
- * These routines should not be exported but should be compiled
- * locally by each fragment. Many thanks to Jay Lieske
- * <lieske@princeton.edu> who provide an initial version of this
- * file.
- *
- * Copyright (c) 1996 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-/*
- * Here is another place that we are using the old routine names...
- */
-
-#include <CodeFragments.h>
-#include <Errors.h>
-#include <Resources.h>
-#include <Strings.h>
-#include "tclMacInt.h"
-
-#if defined(TCL_REGISTER_LIBRARY) && defined(USE_TCL_STUBS)
-#error "Can't use TCL_REGISTER_LIBRARY and USE_TCL_STUBS at the same time!"
-/*
- * Can't register a library with Tcl when using stubs in the current
- * implementation, since Tcl_InitStubs hasn't been called yet
- * when OpenLibraryResource is executing.
- */
-#endif
-
-/*
- * These function are not currently defined in any header file. The
- * only place they should be used is in the Initialization and
- * Termination entry points for a code fragment. The prototypes
- * are included here to avoid compile errors.
- */
-
-OSErr TclMacInitializeFragment _ANSI_ARGS_((
- struct CFragInitBlock* initBlkPtr));
-void TclMacTerminateFragment _ANSI_ARGS_((void));
-
-/*
- * Static functions in this file.
- */
-
-static OSErr OpenLibraryResource _ANSI_ARGS_((
- struct CFragInitBlock* initBlkPtr));
-static void CloseLibraryResource _ANSI_ARGS_((void));
-
-/*
- * The refnum of the opened resource fork.
- */
-static short ourResFile = kResFileNotOpened;
-
-/*
- * This is the resource token for the our resource file.
- * It stores the name we registered with the resource facility.
- * We only need to use this if we are actually registering ourselves.
- */
-
-#ifdef TCL_REGISTER_LIBRARY
-static Tcl_Obj *ourResToken;
-#endif
-
-/*
- *----------------------------------------------------------------------
- *
- * TclMacInitializeFragment --
- *
- * Called by MacOS CFM when the shared library is loaded. All this
- * function really does is give Tcl a chance to open and register
- * the resource fork of the library.
- *
- * Results:
- * MacOS error code if loading should be canceled.
- *
- * Side effects:
- * Opens the resource fork of the shared library file.
- *
- *----------------------------------------------------------------------
- */
-
-OSErr
-TclMacInitializeFragment(
- struct CFragInitBlock* initBlkPtr) /* Pointer to our library. */
-{
- OSErr err = noErr;
-
-#ifdef __MWERKS__
- {
- extern OSErr __initialize( CFragInitBlock* initBlkPtr);
- err = __initialize((CFragInitBlock *) initBlkPtr);
- }
-#endif
- if (err == noErr)
- err = OpenLibraryResource( initBlkPtr);
- return err;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclMacTerminateFragment --
- *
- * Called by MacOS CFM when the shared library is unloaded.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The resource fork of the code fragment is closed.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclMacTerminateFragment()
-{
- CloseLibraryResource();
-
-#ifdef __MWERKS__
- {
- extern void __terminate(void);
- __terminate();
- }
-#endif
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * OpenLibraryResource --
- *
- * This routine can be called by a MacOS fragment's initialiation
- * function to open the resource fork of the file.
- * Call it with the same data passed to the initialization function.
- * If the fragment loading should fail if the resource fork can't
- * be opened, then the initialization function can pass on this
- * return value.
- *
- * If you #define TCL_REGISTER_RESOURCE before compiling this resource,
- * then your library will register its open resource fork with the
- * resource command.
- *
- * Results:
- * It returns noErr on success and a MacOS error code on failure.
- *
- * Side effects:
- * The resource fork of the code fragment is opened read-only and
- * is installed at the head of the resource chain.
- *
- *----------------------------------------------------------------------
- */
-
-static OSErr
-OpenLibraryResource(
- struct CFragInitBlock* initBlkPtr)
-{
- /*
- * The 3.0 version of the Universal headers changed CFragInitBlock
- * to an opaque pointer type. CFragSystem7InitBlock is now the
- * real pointer.
- */
-
-#if !defined(UNIVERSAL_INTERFACES_VERSION) || (UNIVERSAL_INTERFACES_VERSION < 0x0300)
- struct CFragInitBlock *realInitBlkPtr = initBlkPtr;
-#else
- CFragSystem7InitBlock *realInitBlkPtr = (CFragSystem7InitBlock *) initBlkPtr;
-#endif
- FSSpec* fileSpec = NULL;
- OSErr err = noErr;
-
-
- if (realInitBlkPtr->fragLocator.where == kDataForkCFragLocator) {
- fileSpec = realInitBlkPtr->fragLocator.u.onDisk.fileSpec;
- } else if (realInitBlkPtr->fragLocator.where == kResourceCFragLocator) {
- fileSpec = realInitBlkPtr->fragLocator.u.inSegs.fileSpec;
- } else {
- err = resFNotFound;
- }
-
- /*
- * Open the resource fork for this library in read-only mode.
- * This will make it the current res file, ahead of the
- * application's own resources.
- */
-
- if (fileSpec != NULL) {
- ourResFile = FSpOpenResFile(fileSpec, fsRdPerm);
- if (ourResFile == kResFileNotOpened) {
- err = ResError();
- } else {
-#ifdef TCL_REGISTER_LIBRARY
- ourResToken = Tcl_NewObj();
- Tcl_IncrRefCount(ourResToken);
- p2cstr(realInitBlkPtr->libName);
- Tcl_SetStringObj(ourResToken, (char *) realInitBlkPtr->libName, -1);
- c2pstr((char *) realInitBlkPtr->libName);
- TclMacRegisterResourceFork(ourResFile, ourResToken,
- TCL_RESOURCE_DONT_CLOSE);
-#endif
- SetResFileAttrs(ourResFile, mapReadOnly);
- }
- }
-
- return err;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * CloseLibraryResource --
- *
- * This routine should be called by a MacOS fragment's termination
- * function to close the resource fork of the file
- * that was opened with OpenLibraryResource.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The resource fork of the code fragment is closed.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-CloseLibraryResource()
-{
- if (ourResFile != kResFileNotOpened) {
-#ifdef TCL_REGISTER_LIBRARY
- int length;
- TclMacUnRegisterResourceFork(
- Tcl_GetStringFromObj(ourResToken, &length),
- NULL);
- Tcl_DecrRefCount(ourResToken);
-#endif
- CloseResFile(ourResFile);
- ourResFile = kResFileNotOpened;
- }
-}
diff --git a/mac/tclMacLibrary.r b/mac/tclMacLibrary.r
deleted file mode 100644
index 9c17a71..0000000
--- a/mac/tclMacLibrary.r
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * tclMacLibrary.r --
- *
- * This file creates resources used by the Tcl shared library.
- * Many thanks go to "Jay Lieske, Jr." <lieske@princeton.edu> who
- * wrote the initial version of this file.
- *
- * Copyright (c) 1996-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include <Types.r>
-#include <SysTypes.r>
-
-/*
- * The folowing include and defines help construct
- * the version string for Tcl.
- */
-
-#define RC_INVOKED
-#include "tcl.h"
-
-#if (TCL_RELEASE_LEVEL == 0)
-# define RELEASE_LEVEL alpha
-#elif (TCL_RELEASE_LEVEL == 1)
-# define RELEASE_LEVEL beta
-#elif (TCL_RELEASE_LEVEL == 2)
-# define RELEASE_LEVEL final
-#endif
-
-#if (TCL_RELEASE_LEVEL == 2)
-# define MINOR_VERSION (TCL_MINOR_VERSION * 16) + TCL_RELEASE_SERIAL
-# define RELEASE_CODE 0x00
-#else
-# define MINOR_VERSION TCL_MINOR_VERSION * 16
-# define RELEASE_CODE TCL_RELEASE_SERIAL
-#endif
-
-resource 'vers' (1) {
- TCL_MAJOR_VERSION, MINOR_VERSION,
- RELEASE_LEVEL, RELEASE_CODE, verUS,
- TCL_PATCH_LEVEL,
- TCL_PATCH_LEVEL ", by Ray Johnson & Jim Ingham" "\n" "© 2001 Tcl Core Team"
-};
-
-resource 'vers' (2) {
- TCL_MAJOR_VERSION, MINOR_VERSION,
- RELEASE_LEVEL, RELEASE_CODE, verUS,
- TCL_PATCH_LEVEL,
- "Tcl Library " TCL_PATCH_LEVEL " © 1993-2001"
-};
-
-/*
- * Currently the creator for all Tcl/Tk libraries and extensions
- * should be 'TclL'. This will allow those extension and libraries
- * to use the common icon for Tcl extensions. However, this signature
- * still needs to be approved by the signature police at Apple and may
- * change.
- */
-#define TCL_CREATOR 'TclL'
-#define TCL_LIBRARY_RESOURCES 2000
-
-/*
- * The 'BNDL' resource is the primary link between a file's
- * creator/type and its icon. This resource acts for all Tcl shared
- * libraries; other libraries will not need one and ought to use
- * custom icons rather than new file types for a different appearance.
- */
-
-resource 'BNDL' (TCL_LIBRARY_RESOURCES, "Tcl bundle", purgeable)
-{
- TCL_CREATOR,
- 0,
- { /* array TypeArray: 2 elements */
- /* [1] */
- 'FREF',
- { /* array IDArray: 1 elements */
- /* [1] */
- 0, TCL_LIBRARY_RESOURCES
- },
- /* [2] */
- 'ICN#',
- { /* array IDArray: 1 elements */
- /* [1] */
- 0, TCL_LIBRARY_RESOURCES
- }
- }
-};
-
-resource 'FREF' (TCL_LIBRARY_RESOURCES, purgeable)
-{
- 'shlb', 0, ""
-};
-
-type TCL_CREATOR as 'STR ';
-resource TCL_CREATOR (0, purgeable) {
- "Tcl Library " TCL_PATCH_LEVEL " © 1993-2001"
-};
-
-/*
- * The 'kind' resource works with a 'BNDL' in Macintosh Easy Open
- * to affect the text the Finder displays in the "kind" column and
- * file info dialog. This information will be applied to all files
- * with the listed creator and type.
- */
-
-resource 'kind' (TCL_LIBRARY_RESOURCES, "Tcl kind", purgeable) {
- TCL_CREATOR,
- 0, /* region = USA */
- {
- 'shlb', "Tcl Library"
- }
-};
-
-
-/*
- * The -16397 string will be displayed by Finder when a user
- * tries to open the shared library. The string should
- * give the user a little detail about the library's capabilities
- * and enough information to install the library in the correct location.
- * A similar string should be placed in all shared libraries.
- */
-resource 'STR ' (-16397, purgeable) {
- "Tcl Library\n\n"
- "This is the core library needed to run Tool Command Language programs. "
- "To work properly, it should be placed in the ŒTool Command Language¹ folder "
- "within the Extensions folder."
-};
-
-/*
- * The following are icons for the shared library.
- */
-
-data 'icl4' (2000, "Tcl Shared Library", purgeable) {
- $"0FFF FFFF FFFF FFFF FFFF FFFF FFFF 0000"
- $"F000 0000 0000 0000 0000 0000 000C F000"
- $"F0CC CFFF CCCC CCC6 66CC CCCC CCCC F000"
- $"F0CC CFFF FFFF FF66 F6CC CCCC CCCC F000"
- $"F0CC CFFF 2000 0D66 6CCC CCCC CCCC F000"
- $"F0CC CFFF 0202 056F 6E5C CCCC CCCC F000"
- $"F0CC CFFF 2020 C666 F66F CCCC CCCC F000"
- $"F0CC CFFF 0200 B66F 666B FCCC CCCC F000"
- $"F0FC CFFF B020 55F6 6F52 BFCC CCCC F000"
- $"FF0F 0CCC FB02 5665 66D0 2FCC CCCC F0F0"
- $"F00F 0CCC CFB0 BF55 F6CF FFCC CCCC FFCF"
- $"000F 0CCC CCFB 06C9 66CC CCCC CCCC F0CF"
- $"000F 0CCC CCCF 56C6 6CCC CCCC CCCC CCCF"
- $"000F 0CCC CCCC 6FC6 FCCC CCCC CCCC CCCF"
- $"000F 0CCC CCCC 65C5 65CC CCCC CCCC CCCF"
- $"000F 0CCC CCCC 55D6 57CC CCCC CCCC CCCF"
- $"000F 0CCC CCCC 65CF 6CCC CCCC CCCC CCCF"
- $"000F 0CCC CCCC 5AC6 6CFF CCCC CCCC CCCF"
- $"000F 0CCC CCCC 65C5 6CF0 FCCC CCCC CCCF"
- $"000F 0CCC CCCC CECF CCF0 0FCC CCCC CCCF"
- $"000F 0CCC CCCC C5C6 CCCF 20FC CCCC FCCF"
- $"F00F 0CCC CCCF FFD5 CCCC F20F CCCC FFCF"
- $"FF0F 0CCC CCCF 20CF CCCC F020 FCCC F0F0"
- $"F0F0 CCCC CCCF B2C2 FFFF 0002 0FFC F000"
- $"F00C CCCC CCCC FBC0 2000 0020 2FFC F000"
- $"F0CC CCCC CCCC CFCB 0202 0202 0FFC F000"
- $"F0CC CCCC CCCC CCCF B020 2020 2FFC F000"
- $"F0CC CCCC CCCC CCDC FBBB BBBB BFFC F000"
- $"F0CC CCCC CCCC CCCC CFFF FFFF FFFC F000"
- $"F0CC CCCC CCCC CCCC CCCC CCCC CFFC F000"
- $"FCCC CCCC CCCC CCCC CCCC CCCC CCCC F000"
- $"0FFF FFFF FFFF FFFF FFFF FFFF FFFF 0000"
-};
-
-data 'ICN#' (2000, "Tcl Shared Library", purgeable) {
- $"7FFF FFF0 8000 0008 8701 C008 87FF C008"
- $"8703 8008 8707 E008 8707 F008 870F F808"
- $"A78F EC08 D0CF C40A 906F DC0D 1035 C009"
- $"101D 8001 100D 8001 100D C001 100D C001"
- $"100D 8001 100D B001 100D A801 1005 2401"
- $"1005 1209 901D 090D D011 088A A018 F068"
- $"800C 0068 8005 0068 8001 8068 8000 FFE8"
- $"8000 7FE8 8000 0068 8000 0008 7FFF FFF0"
- $"7FFF FFF0 FFFF FFF8 FFFF FFF8 FFFF FFF8"
- $"FFFF FFF8 FFFF FFF8 FFFF FFF8 FFFF FFF8"
- $"FFFF FFF8 DFFF FFFA 9FFF FFFF 1FFF FFFF"
- $"1FFF FFFF 1FFF FFFF 1FFF FFFF 1FFF FFFF"
- $"1FFF FFFF 1FFF FFFF 1FFF FFFF 1FFF FFFF"
- $"1FFF FFFF 9FFF FFFF DFFF FFFA FFFF FFF8"
- $"FFFF FFF8 FFFF FFF8 FFFF FFF8 FFFF FFF8"
- $"FFFF FFF8 FFFF FFF8 FFFF FFF8 7FFF FFF0"
-};
-
-data 'ics#' (2000, "Tcl Shared Library", purgeable) {
- $"FFFE B582 BB82 B3C2 BFA2 43C3 4381 4381"
- $"4381 4763 4392 856E 838E 81AE 811E FFFE"
- $"FFFE FFFE FFFE FFFE FFFE FFFF 7FFF 7FFF"
- $"7FFF 7FFF 7FFF FFFE FFFE FFFE FFFE FFFE"
-};
-
-data 'ics4' (2000, "Tcl Shared Library", purgeable) {
- $"FFFF FFFF FFFF FFF0 FCFF DED5 6CCC CCF0"
- $"FCFF C0D6 ECCC CCF0 FCFF 2056 65DC CCF0"
- $"FDFE D256 6DAC CCFF FFCC DDDE 5DDC CCEF"
- $"0FCC CD67 5CCC CCCF 0FCC CC5D 6CCC CCCF"
- $"0FCC CC5D 5CCC CCCF 0FCC CCD5 5CCC CCCF"
- $"FFCC CFFD CCFF CCFF FCCC CF2D DF20 FCFC"
- $"FCCC CCFD D202 FEF0 FCCC CC0D 2020 FEF0"
- $"FCCC CCCD FBBB FEF0 FFFF FFFF FFFF FFE0"
-};
-
diff --git a/mac/tclMacLoad.c b/mac/tclMacLoad.c
deleted file mode 100644
index 81bfe60..0000000
--- a/mac/tclMacLoad.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * tclMacLoad.c --
- *
- * This procedure provides a version of the TclLoadFile for use
- * on the Macintosh. This procedure will only work with systems
- * that use the Code Fragment Manager.
- *
- * Copyright (c) 1995-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include <CodeFragments.h>
-#include <Errors.h>
-#include <Resources.h>
-#include <Strings.h>
-#include <FSpCompat.h>
-
-/*
- * Seems that the 3.0.1 Universal headers leave this define out. So we
- * define it here...
- */
-
-#ifndef fragNoErr
- #define fragNoErr noErr
-#endif
-
-#include "tclPort.h"
-#include "tclInt.h"
-#include "tclMacInt.h"
-
-#if GENERATINGPOWERPC
- #define OUR_ARCH_TYPE kPowerPCCFragArch
-#else
- #define OUR_ARCH_TYPE kMotorola68KCFragArch
-#endif
-
-/*
- * The following data structure defines the structure of a code fragment
- * resource. We can cast the resource to be of this type to access
- * any fields we need to see.
- */
-struct CfrgHeader {
- long res1;
- long res2;
- long version;
- long res3;
- long res4;
- long filler1;
- long filler2;
- long itemCount;
- char arrayStart; /* Array of externalItems begins here. */
-};
-typedef struct CfrgHeader CfrgHeader, *CfrgHeaderPtr, **CfrgHeaderPtrHand;
-
-/*
- * The below structure defines a cfrag item within the cfrag resource.
- */
-struct CfrgItem {
- OSType archType;
- long updateLevel;
- long currVersion;
- long oldDefVersion;
- long appStackSize;
- short appSubFolder;
- char usage;
- char location;
- long codeOffset;
- long codeLength;
- long res1;
- long res2;
- short itemSize;
- Str255 name; /* This is actually variable sized. */
-};
-typedef struct CfrgItem CfrgItem;
-
-/*
- * On MacOS, old shared libraries which contain many code fragments
- * cannot, it seems, be loaded in one go. We need to look provide
- * the name of a code fragment while we load. Since with the
- * separation of the 'load' and 'findsymbol' be do not necessarily
- * know a symbol name at load time, we have to store some further
- * information in a structure like this so we can ensure we load
- * properly in 'findsymbol' if the first attempts didn't work.
- */
-typedef struct TclMacLoadInfo {
- int loaded;
- CFragConnectionID connID;
- FSSpec fileSpec;
-} TclMacLoadInfo;
-
-static int TryToLoad(Tcl_Interp *interp, TclMacLoadInfo *loadInfo, Tcl_Obj *pathPtr,
- CONST char *sym /* native */);
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpDlopen --
- *
- * This procedure is called to carry out dynamic loading of binary
- * code for the Macintosh. This implementation is based on the
- * Code Fragment Manager & will not work on other systems.
- *
- * Results:
- * The result is TCL_ERROR, and an error message is left in
- * the interp's result.
- *
- * Side effects:
- * New binary code is loaded.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Obj *pathPtr; /* Name of the file containing the desired
- * code (UTF-8). */
- Tcl_LoadHandle *loadHandle; /* Filled with token for dynamically loaded
- * file which will be passed back to
- * (*unloadProcPtr)() to unload the file. */
- Tcl_FSUnloadFileProc **unloadProcPtr;
- /* Filled with address of Tcl_FSUnloadFileProc
- * function which should be used for
- * this file. */
-{
- OSErr err;
- FSSpec fileSpec;
- CONST char *native;
- TclMacLoadInfo *loadInfo;
-
- native = Tcl_FSGetNativePath(pathPtr);
- err = FSpLocationFromPath(strlen(native), native, &fileSpec);
-
- if (err != noErr) {
- Tcl_SetResult(interp, "could not locate shared library", TCL_STATIC);
- return TCL_ERROR;
- }
-
- loadInfo = (TclMacLoadInfo *) ckalloc(sizeof(TclMacLoadInfo));
- loadInfo->loaded = 0;
- loadInfo->fileSpec = fileSpec;
- loadInfo->connID = NULL;
-
- if (TryToLoad(interp, loadInfo, pathPtr, NULL) != TCL_OK) {
- ckfree((char*) loadInfo);
- return TCL_ERROR;
- }
-
- *loadHandle = (Tcl_LoadHandle)loadInfo;
- *unloadProcPtr = &TclpUnloadFile;
- return TCL_OK;
-}
-
-/*
- * See the comments about 'struct TclMacLoadInfo' above. This
- * function ensures the appropriate library or symbol is
- * loaded.
- */
-static int
-TryToLoad(Tcl_Interp *interp, TclMacLoadInfo *loadInfo, Tcl_Obj *pathPtr,
- CONST char *sym /* native */)
-{
- OSErr err;
- CFragConnectionID connID;
- Ptr dummy;
- short fragFileRef, saveFileRef;
- Handle fragResource;
- UInt32 offset = 0;
- UInt32 length = kCFragGoesToEOF;
- Str255 errName;
- StringPtr fragName=NULL;
-
- if (loadInfo->loaded == 1) {
- return TCL_OK;
- }
-
- /*
- * See if this fragment has a 'cfrg' resource. It will tell us where
- * to look for the fragment in the file. If it doesn't exist we will
- * assume we have a ppc frag using the whole data fork. If it does
- * exist we find the frag that matches the one we are looking for and
- * get the offset and size from the resource.
- */
-
- saveFileRef = CurResFile();
- SetResLoad(false);
- fragFileRef = FSpOpenResFile(&loadInfo->fileSpec, fsRdPerm);
- SetResLoad(true);
- if (fragFileRef != -1) {
- if (sym != NULL) {
- UseResFile(fragFileRef);
- fragResource = Get1Resource(kCFragResourceType, kCFragResourceID);
- HLock(fragResource);
- if (ResError() == noErr) {
- CfrgItem* srcItem;
- long itemCount, index;
- Ptr itemStart;
-
- itemCount = (*(CfrgHeaderPtrHand)fragResource)->itemCount;
- itemStart = &(*(CfrgHeaderPtrHand)fragResource)->arrayStart;
- for (index = 0; index < itemCount;
- index++, itemStart += srcItem->itemSize) {
- srcItem = (CfrgItem*)itemStart;
- if (srcItem->archType != OUR_ARCH_TYPE) continue;
- if (!strncasecmp(sym, (char *) srcItem->name + 1,
- strlen(sym))) {
- offset = srcItem->codeOffset;
- length = srcItem->codeLength;
- fragName=srcItem->name;
- }
- }
- }
- }
- /*
- * Close the resource file. If the extension wants to reopen the
- * resource fork it should use the tclMacLibrary.c file during it's
- * construction.
- */
- HUnlock(fragResource);
- ReleaseResource(fragResource);
- CloseResFile(fragFileRef);
- UseResFile(saveFileRef);
- if (sym == NULL) {
- /* We just return */
- return TCL_OK;
- }
- }
-
- /*
- * Now we can attempt to load the fragment using the offset & length
- * obtained from the resource. We don't worry about the main entry point
- * as we are going to search for specific entry points passed to us.
- */
-
- err = GetDiskFragment(&loadInfo->fileSpec, offset, length, fragName,
- kLoadCFrag, &connID, &dummy, errName);
-
- if (err != fragNoErr) {
- p2cstr(errName);
- if(pathPtr) {
- Tcl_AppendResult(interp, "couldn't load file \"",
- Tcl_GetString(pathPtr),
- "\": ", errName, (char *) NULL);
- } else if(sym) {
- Tcl_AppendResult(interp, "couldn't load library \"",
- sym,
- "\": ", errName, (char *) NULL);
- }
- return TCL_ERROR;
- }
-
- loadInfo->connID = connID;
- loadInfo->loaded = 1;
-
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpFindSymbol --
- *
- * Looks up a symbol, by name, through a handle associated with
- * a previously loaded piece of code (shared library).
- *
- * Results:
- * Returns a pointer to the function associated with 'symbol' if
- * it is found. Otherwise returns NULL and may leave an error
- * message in the interp's result.
- *
- *----------------------------------------------------------------------
- */
-Tcl_PackageInitProc*
-TclpFindSymbol(interp, loadHandle, symbol)
- Tcl_Interp *interp;
- Tcl_LoadHandle loadHandle;
- CONST char *symbol;
-{
- Tcl_DString ds;
- Tcl_PackageInitProc *proc=NULL;
- TclMacLoadInfo *loadInfo = (TclMacLoadInfo *)loadHandle;
- Str255 symbolName;
- CFragSymbolClass symClass;
- OSErr err;
-
- if (loadInfo->loaded == 0) {
- int res;
- /*
- * First thing we must do is infer the package name from the
- * sym variable. We do this by removing the '_Init'.
- */
- Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
- Tcl_DStringSetLength(&ds, Tcl_DStringLength(&ds) - 5);
- res = TryToLoad(interp, loadInfo, NULL, Tcl_DStringValue(&ds));
- Tcl_DStringFree(&ds);
- if (res != TCL_OK) {
- return NULL;
- }
- }
-
- Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
- strcpy((char *) symbolName + 1, Tcl_DStringValue(&ds));
- symbolName[0] = (unsigned) Tcl_DStringLength(&ds);
- err = FindSymbol(loadInfo->connID, symbolName, (Ptr *) &proc, &symClass);
- Tcl_DStringFree(&ds);
- if (err != fragNoErr || symClass == kDataCFragSymbol) {
- Tcl_SetResult(interp,
- "could not find Initialization routine in library",
- TCL_STATIC);
- return NULL;
- }
- return proc;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpUnloadFile --
- *
- * Unloads a dynamically loaded binary code file from memory.
- * Code pointers in the formerly loaded file are no longer valid
- * after calling this function.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Does nothing. Can anything be done?
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpUnloadFile(loadHandle)
- Tcl_LoadHandle loadHandle; /* loadHandle returned by a previous call
- * to TclpDlopen(). The loadHandle is
- * a token that represents the loaded
- * file. */
-{
- TclMacLoadInfo *loadInfo = (TclMacLoadInfo *)loadHandle;
- if (loadInfo->loaded) {
- CloseConnection((CFragConnectionID*) &(loadInfo->connID));
- }
- ckfree((char*)loadInfo);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclGuessPackageName --
- *
- * If the "load" command is invoked without providing a package
- * name, this procedure is invoked to try to figure it out.
- *
- * Results:
- * Always returns 0 to indicate that we couldn't figure out a
- * package name; generic code will then try to guess the package
- * from the file name. A return value of 1 would have meant that
- * we figured out the package name and put it in bufPtr.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclGuessPackageName(
- CONST char *fileName, /* Name of file containing package (already
- * translated to local form if needed). */
- Tcl_DString *bufPtr) /* Initialized empty dstring. Append
- * package name to this if possible. */
-{
- return 0;
-}
diff --git a/mac/tclMacMath.h b/mac/tclMacMath.h
deleted file mode 100644
index 0361d79..0000000
--- a/mac/tclMacMath.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * tclMacMath.h --
- *
- * This file is necessary because of Metrowerks CodeWarrior Pro 1
- * on the Macintosh. With 8-byte doubles turned on, the definitions of
- * sin, cos, acos, etc., are screwed up. They are fine as long as
- * they are used as function calls, but if the function pointers
- * are passed around and used, they will crash hard on the 68K.
- *
- * Copyright (c) 1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#ifndef _TCLMACMATH
-#define _TCLMACMATH
-
-#include <math.h>
-
-#if defined(__MWERKS__) && !defined(__POWERPC__)
-#if __option(IEEEdoubles)
-
-# ifdef cos
-# undef cos
-# define cos cosd
-# endif
-
-# ifdef sin
-# undef sin
-# define sin sind
-# endif
-
-# ifdef tan
-# undef tan
-# define tan tand
-# endif
-
-# ifdef acos
-# undef acos
-# define acos acosd
-# endif
-
-# ifdef asin
-# undef asin
-# define asin asind
-# endif
-
-# ifdef atan
-# undef atan
-# define atan atand
-# endif
-
-# ifdef cosh
-# undef cosh
-# define cosh coshd
-# endif
-
-# ifdef sinh
-# undef sinh
-# define sinh sinhd
-# endif
-
-# ifdef tanh
-# undef tanh
-# define tanh tanhd
-# endif
-
-# ifdef exp
-# undef exp
-# define exp expd
-# endif
-
-# ifdef ldexp
-# undef ldexp
-# define ldexp ldexpd
-# endif
-
-# ifdef log
-# undef log
-# define log logd
-# endif
-
-# ifdef log10
-# undef log10
-# define log10 log10d
-# endif
-
-# ifdef fabs
-# undef fabs
-# define fabs fabsd
-# endif
-
-# ifdef sqrt
-# undef sqrt
-# define sqrt sqrtd
-# endif
-
-# ifdef fmod
-# undef fmod
-# define fmod fmodd
-# endif
-
-# ifdef atan2
-# undef atan2
-# define atan2 atan2d
-# endif
-
-# ifdef frexp
-# undef frexp
-# define frexp frexpd
-# endif
-
-# ifdef modf
-# undef modf
-# define modf modfd
-# endif
-
-# ifdef pow
-# undef pow
-# define pow powd
-# endif
-
-# ifdef ceil
-# undef ceil
-# define ceil ceild
-# endif
-
-# ifdef floor
-# undef floor
-# define floor floord
-# endif
-#endif
-#endif
-
-#if (defined(THINK_C))
-#pragma export on
-double hypotd(double x, double y);
-#define hypot hypotd
-#pragma export reset
-#endif
-
-#endif /* _TCLMACMATH */
diff --git a/mac/tclMacNotify.c b/mac/tclMacNotify.c
deleted file mode 100644
index dae468a..0000000
--- a/mac/tclMacNotify.c
+++ /dev/null
@@ -1,579 +0,0 @@
-/*
- * tclMacNotify.c --
- *
- * This file contains Macintosh-specific procedures for the notifier,
- * which is the lowest-level part of the Tcl event loop. This file
- * works together with ../generic/tclNotify.c.
- *
- * The Mac notifier only polls for system and OS events, so it is process
- * wide, rather than thread specific. However, this means that the convert
- * event proc will have to arbitrate which events go to which threads.
- *
- * Copyright (c) 1995-1996 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include "tclInt.h"
-#include "tclPort.h"
-#include "tclMac.h"
-#include "tclMacInt.h"
-#include <signal.h>
-#include <Events.h>
-#include <LowMem.h>
-#include <Processes.h>
-#include <Timer.h>
-#include <Threads.h>
-
-
-/*
- * This is necessary to work around a bug in Apple's Universal header files
- * for the CFM68K libraries.
- */
-
-#ifdef __CFM68K__
-#undef GetEventQueue
-extern pascal QHdrPtr GetEventQueue(void)
- THREEWORDINLINE(0x2EBC, 0x0000, 0x014A);
-#pragma import list GetEventQueue
-#define GetEvQHdr() GetEventQueue()
-#endif
-
-/*
- * Need this for replacing Tcl_SetTimer and Tcl_WaitForEvent defined
- * in THIS file with ones defined in the stub table.
- */
-
-extern TclStubs tclStubs;
-extern Tcl_NotifierProcs tclOriginalNotifier;
-
-/*
- * The follwing static indicates whether this module has been initialized.
- */
-
-static int initialized = 0;
-
-/*
- * The following structure contains the state information for the
- * notifier module.
- */
-
-static struct {
- int timerActive; /* 1 if timer is running. */
- Tcl_Time timer; /* Time when next timer event is expected. */
- int flags; /* OR'ed set of flags defined below. */
- Point lastMousePosition; /* Last known mouse location. */
- RgnHandle utilityRgn; /* Region used as the mouse region for
- * WaitNextEvent and the update region when
- * checking for events. */
- Tcl_MacConvertEventPtr eventProcPtr;
- /* This pointer holds the address of the
- * function that will handle all incoming
- * Macintosh events. */
-} notifier;
-
-/*
- * The following defines are used in the flags field of the notifier struct.
- */
-
-#define NOTIFY_IDLE (1<<1) /* Tcl_ServiceIdle should be called. */
-#define NOTIFY_TIMER (1<<2) /* Tcl_ServiceTimer should be called. */
-
-/*
- * Prototypes for procedures that are referenced only in this file:
- */
-
-static int HandleMacEvents _ANSI_ARGS_((void));
-static void InitNotifier _ANSI_ARGS_((void));
-static void NotifierExitHandler _ANSI_ARGS_((
- ClientData clientData));
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_InitNotifier --
- *
- * Initializes the platform specific notifier state. There is no thread
- * specific platform notifier on the Mac, so this really doesn't do
- * anything. However, we need to return the ThreadID, since the generic
- * notifier hands this back to us in AlertThread.
- *
- * Results:
- * Returns the threadID for this thread.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-ClientData
-Tcl_InitNotifier()
-{
-
-#ifdef TCL_THREADS
- ThreadID curThread;
- if (TclMacHaveThreads()) {
- GetCurrentThread(&curThread);
- return (ClientData) curThread;
- } else {
- return NULL;
- }
-#else
- return NULL;
-#endif
-
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_FinalizeNotifier --
- *
- * This function is called to cleanup the notifier state before
- * a thread is terminated. There is no platform thread specific
- * notifier, so this does nothing.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tcl_FinalizeNotifier(clientData)
- ClientData clientData; /* Pointer to notifier data. */
-{
- /* Nothing to do on the Mac */
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_AlertNotifier --
- *
- * Wake up the specified notifier from any thread. This routine
- * is called by the platform independent notifier code whenever
- * the Tcl_ThreadAlert routine is called. This routine is
- * guaranteed not to be called on a given notifier after
- * Tcl_FinalizeNotifier is called for that notifier.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Calls YieldToThread from this thread.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tcl_AlertNotifier(clientData)
- ClientData clientData; /* Pointer to thread data. */
-{
-
-#ifdef TCL_THREADS
- if (TclMacHaveThreads()) {
- YieldToThread((ThreadID) clientData);
- }
-#endif
-
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * InitNotifier --
- *
- * Initializes the notifier structure. Note - this function is never
- * used.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Creates a new exit handler.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-InitNotifier(void)
-{
- initialized = 1;
- memset(&notifier, 0, sizeof(notifier));
- Tcl_CreateExitHandler(NotifierExitHandler, NULL);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * NotifierExitHandler --
- *
- * This function is called to cleanup the notifier state before
- * Tcl is unloaded. This function is never used, since InitNotifier
- * isn't either.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-NotifierExitHandler(
- ClientData clientData) /* Not used. */
-{
- initialized = 0;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * HandleMacEvents --
- *
- * This function checks for events from the Macintosh event queue.
- *
- * Results:
- * Returns 1 if event found, 0 otherwise.
- *
- * Side effects:
- * Pulls events off of the Mac event queue and then calls
- * convertEventProc.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-HandleMacEvents(void)
-{
- EventRecord theEvent;
- int eventFound = 0, needsUpdate = 0;
- Point currentMouse;
- WindowRef windowRef;
- Rect mouseRect;
-
- /*
- * Check for mouse moved events. These events aren't placed on the
- * system event queue unless we call WaitNextEvent.
- */
-
- GetGlobalMouseTcl(&currentMouse);
- if ((notifier.eventProcPtr != NULL) &&
- !EqualPt(currentMouse, notifier.lastMousePosition)) {
- notifier.lastMousePosition = currentMouse;
- theEvent.what = nullEvent;
- if ((*notifier.eventProcPtr)(&theEvent) == true) {
- eventFound = 1;
- }
- }
-
- /*
- * Check for update events. Since update events aren't generated
- * until we call GetNextEvent, we may need to force a call to
- * GetNextEvent, even if the queue is empty.
- */
-
- for (windowRef = FrontWindow(); windowRef != NULL;
- windowRef = GetNextWindow(windowRef)) {
- GetWindowUpdateRgn(windowRef, notifier.utilityRgn);
- if (!EmptyRgn(notifier.utilityRgn)) {
- needsUpdate = 1;
- break;
- }
- }
-
- /*
- * Process events from the OS event queue.
- */
-
- while (needsUpdate || (GetEvQHdr()->qHead != NULL)) {
- GetGlobalMouseTcl(&currentMouse);
- SetRect(&mouseRect, currentMouse.h, currentMouse.v,
- currentMouse.h + 1, currentMouse.v + 1);
- RectRgn(notifier.utilityRgn, &mouseRect);
-
- WaitNextEvent(everyEvent, &theEvent, 5, notifier.utilityRgn);
- needsUpdate = 0;
- if ((notifier.eventProcPtr != NULL)
- && ((*notifier.eventProcPtr)(&theEvent) == true)) {
- eventFound = 1;
- }
- }
-
- return eventFound;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_SetTimer --
- *
- * This procedure sets the current notifier timer value. The
- * notifier will ensure that Tcl_ServiceAll() is called after
- * the specified interval, even if no events have occurred.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Replaces any previous timer.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tcl_SetTimer(
- Tcl_Time *timePtr) /* New value for interval timer. */
-{
- /*
- * Allow the notifier to be hooked. This may not make sense
- * on the Mac, but mirrors the UNIX hook.
- */
-
- if (tclStubs.tcl_SetTimer != tclOriginalNotifier.setTimerProc) {
- tclStubs.tcl_SetTimer(timePtr);
- return;
- }
-
- if (!timePtr) {
- notifier.timerActive = 0;
- } else {
- /*
- * Compute when the timer should fire.
- */
-
- Tcl_GetTime(&notifier.timer);
- notifier.timer.sec += timePtr->sec;
- notifier.timer.usec += timePtr->usec;
- if (notifier.timer.usec >= 1000000) {
- notifier.timer.usec -= 1000000;
- notifier.timer.sec += 1;
- }
- notifier.timerActive = 1;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_ServiceModeHook --
- *
- * This function is invoked whenever the service mode changes.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tcl_ServiceModeHook(mode)
- int mode; /* Either TCL_SERVICE_ALL, or
- * TCL_SERVICE_NONE. */
-{
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_WaitForEvent --
- *
- * This function is called by Tcl_DoOneEvent to wait for new
- * events on the message queue. If the block time is 0, then
- * Tcl_WaitForEvent just polls the event queue without blocking.
- *
- * Results:
- * Always returns 0.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-Tcl_WaitForEvent(
- Tcl_Time *timePtr) /* Maximum block time. */
-{
- int found;
- EventRecord macEvent;
- long sleepTime = 5;
- long ms;
- Point currentMouse;
- void * timerToken;
- Rect mouseRect;
-
- /*
- * Allow the notifier to be hooked. This may not make
- * sense on the Mac, but mirrors the UNIX hook.
- */
-
- if (tclStubs.tcl_WaitForEvent != tclOriginalNotifier.waitForEventProc) {
- return tclStubs.tcl_WaitForEvent(timePtr);
- }
-
- /*
- * Compute the next timeout value.
- */
-
- if (!timePtr) {
- ms = INT_MAX;
- } else {
- ms = (timePtr->sec * 1000) + (timePtr->usec / 1000);
- }
- timerToken = TclMacStartTimer((long) ms);
-
- /*
- * Poll the Mac event sources. This loop repeats until something
- * happens: a timeout, a socket event, mouse motion, or some other
- * window event. Note that we don't call WaitNextEvent if another
- * event is found to avoid context switches. This effectively gives
- * events coming in via WaitNextEvent a slightly lower priority.
- */
-
- found = 0;
- if (notifier.utilityRgn == NULL) {
- notifier.utilityRgn = NewRgn();
- }
-
- while (!found) {
- /*
- * Check for generated and queued events.
- */
-
- if (HandleMacEvents()) {
- found = 1;
- }
-
- /*
- * Check for time out.
- */
-
- if (!found && TclMacTimerExpired(timerToken)) {
- found = 1;
- }
-
- /*
- * Check for window events. We may receive a NULL event for
- * various reasons. 1) the timer has expired, 2) a mouse moved
- * event is occuring or 3) the os is giving us time for idle
- * events. Note that we aren't sharing the processor very
- * well here. We really ought to do a better job of calling
- * WaitNextEvent for time slicing purposes.
- */
-
- if (!found) {
- /*
- * Set up mouse region so we will wake if the mouse is moved.
- * We do this by defining the smallest possible region around
- * the current mouse position.
- */
-
- GetGlobalMouseTcl(&currentMouse);
- SetRect(&mouseRect, currentMouse.h, currentMouse.v,
- currentMouse.h + 1, currentMouse.v + 1);
- RectRgn(notifier.utilityRgn, &mouseRect);
-
- WaitNextEvent(everyEvent, &macEvent, sleepTime,
- notifier.utilityRgn);
-
- if (notifier.eventProcPtr != NULL) {
- if ((*notifier.eventProcPtr)(&macEvent) == true) {
- found = 1;
- }
- }
- }
- }
- TclMacRemoveTimer(timerToken);
-
- /*
- * Yield time to nay other thread at this point. If we find that the
- * apps thrash too switching between threads, we can put a timer here,
- * and only yield when the timer fires.
- */
-
- if (TclMacHaveThreads()) {
- YieldToAnyThread();
- }
-
- return 0;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_Sleep --
- *
- * Delay execution for the specified number of milliseconds. This
- * is not a very good call to make. It will block the system -
- * you will not even be able to switch applications.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Time passes.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tcl_Sleep(
- int ms) /* Number of milliseconds to sleep. */
-{
- EventRecord dummy;
- void *timerToken;
-
- if (ms <= 0) {
- return;
- }
-
- timerToken = TclMacStartTimer((long) ms);
- while (1) {
- WaitNextEvent(0, &dummy, (ms / 16.66) + 1, NULL);
- if (TclMacHaveThreads()) {
- YieldToAnyThread();
- }
- if (TclMacTimerExpired(timerToken)) {
- break;
- }
- }
- TclMacRemoveTimer(timerToken);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_MacSetEventProc --
- *
- * This function sets the event handling procedure for the
- * application. This function will be passed all incoming Mac
- * events. This function usually controls the console or some
- * other entity like Tk.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Changes the event handling function.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tcl_MacSetEventProc(
- Tcl_MacConvertEventPtr procPtr)
-{
- notifier.eventProcPtr = procPtr;
-}
diff --git a/mac/tclMacOSA.c b/mac/tclMacOSA.c
deleted file mode 100644
index 6bcef6e..0000000
--- a/mac/tclMacOSA.c
+++ /dev/null
@@ -1,2956 +0,0 @@
-/*
- * tclMacOSA.c --
- *
- * This contains the initialization routines, and the implementation of
- * the OSA and Component commands. These commands allow you to connect
- * with the AppleScript or any other OSA component to compile and execute
- * scripts.
- *
- * Copyright (c) 1996 Lucent Technologies and Jim Ingham
- * Copyright (c) 1997 Sun Microsystems, Inc.
- *
- * See the file "License Terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#define MAC_TCL
-
-#include <Aliases.h>
-#include <string.h>
-#include <AppleEvents.h>
-#include <AppleScript.h>
-#include <OSA.h>
-#include <OSAGeneric.h>
-#include <Script.h>
-
-#include <FullPath.h>
-#include <components.h>
-
-#include <resources.h>
-#include <FSpCompat.h>
-/*
- * The following two Includes are from the More Files package.
- */
-#include <MoreFiles.h>
-#include <FullPath.h>
-
-#include "tcl.h"
-#include "tclInt.h"
-
-/*
- * I need this only for the call to FspGetFullPath,
- * I'm really not poking my nose where it does not belong!
- */
-#include "tclMacInt.h"
-
-/*
- * Data structures used by the OSA code.
- */
-typedef struct tclOSAScript {
- OSAID scriptID;
- OSType languageID;
- long modeFlags;
-} tclOSAScript;
-
-typedef struct tclOSAContext {
- OSAID contextID;
-} tclOSAContext;
-
-typedef struct tclOSAComponent {
- char *theName;
- ComponentInstance theComponent; /* The OSA Component represented */
- long componentFlags;
- OSType languageID;
- char *languageName;
- Tcl_HashTable contextTable; /* Hash Table linking the context names & ID's */
- Tcl_HashTable scriptTable;
- Tcl_Interp *theInterp;
- OSAActiveUPP defActiveProc;
- long defRefCon;
-} tclOSAComponent;
-
-/*
- * Prototypes for static procedures.
- */
-
-static pascal OSErr TclOSAActiveProc _ANSI_ARGS_((long refCon));
-static int TclOSACompileCmd _ANSI_ARGS_((Tcl_Interp *interp,
- tclOSAComponent *OSAComponent, int argc,
- CONST char **argv));
-static int tclOSADecompileCmd _ANSI_ARGS_((Tcl_Interp * Interp,
- tclOSAComponent *OSAComponent, int argc,
- CONST char **argv));
-static int tclOSADeleteCmd _ANSI_ARGS_((Tcl_Interp *interp,
- tclOSAComponent *OSAComponent, int argc,
- CONST char **argv));
-static int tclOSAExecuteCmd _ANSI_ARGS_((Tcl_Interp *interp,
- tclOSAComponent *OSAComponent, int argc,
- CONST char **argv));
-static int tclOSAInfoCmd _ANSI_ARGS_((Tcl_Interp *interp,
- tclOSAComponent *OSAComponent, int argc,
- CONST char **argv));
-static int tclOSALoadCmd _ANSI_ARGS_((Tcl_Interp *interp,
- tclOSAComponent *OSAComponent, int argc,
- CONST char **argv));
-static int tclOSARunCmd _ANSI_ARGS_((Tcl_Interp *interp,
- tclOSAComponent *OSAComponent, int argc,
- CONST char **argv));
-static int tclOSAStoreCmd _ANSI_ARGS_((Tcl_Interp *interp,
- tclOSAComponent *OSAComponent, int argc,
- CONST char **argv));
-static void GetRawDataFromDescriptor _ANSI_ARGS_((AEDesc *theDesc,
- Ptr destPtr, Size destMaxSize, Size *actSize));
-static OSErr GetCStringFromDescriptor _ANSI_ARGS_((
- AEDesc *sourceDesc, char *resultStr,
- Size resultMaxSize,Size *resultSize));
-static int Tcl_OSAComponentCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static void getSortedHashKeys _ANSI_ARGS_((Tcl_HashTable *theTable,
- CONST char *pattern, Tcl_DString *theResult));
-static int ASCIICompareProc _ANSI_ARGS_((const void *first,
- const void *second));
-static int Tcl_OSACmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static void tclOSAClose _ANSI_ARGS_((ClientData clientData));
-/*static void tclOSACloseAll _ANSI_ARGS_((ClientData clientData));*/
-static tclOSAComponent *tclOSAMakeNewComponent _ANSI_ARGS_((Tcl_Interp *interp,
- char *cmdName, char *languageName,
- OSType scriptSubtype, long componentFlags));
-static int prepareScriptData _ANSI_ARGS_((int argc, CONST char **argv,
- Tcl_DString *scrptData ,AEDesc *scrptDesc));
-static void tclOSAResultFromID _ANSI_ARGS_((Tcl_Interp *interp,
- ComponentInstance theComponent, OSAID resultID));
-static void tclOSAASError _ANSI_ARGS_((Tcl_Interp * interp,
- ComponentInstance theComponent, char *scriptSource));
-static int tclOSAGetContextID _ANSI_ARGS_((tclOSAComponent *theComponent,
- CONST char *contextName, OSAID *theContext));
-static void tclOSAAddContext _ANSI_ARGS_((tclOSAComponent *theComponent,
- char *contextName, const OSAID theContext));
-static int tclOSAMakeContext _ANSI_ARGS_((tclOSAComponent *theComponent,
- CONST char *contextName, OSAID *theContext));
-static int tclOSADeleteContext _ANSI_ARGS_((tclOSAComponent *theComponent,
- CONST char *contextName));
-static int tclOSALoad _ANSI_ARGS_((Tcl_Interp *interp,
- tclOSAComponent *theComponent, CONST char *resourceName,
- int resourceNumber, CONST char *fileName,OSAID *resultID));
-static int tclOSAStore _ANSI_ARGS_((Tcl_Interp *interp,
- tclOSAComponent *theComponent, CONST char *resourceName,
- int resourceNumber, CONST char *scriptName, CONST char *fileName));
-static int tclOSAAddScript _ANSI_ARGS_((tclOSAComponent *theComponent,
- char *scriptName, long modeFlags, OSAID scriptID));
-static int tclOSAGetScriptID _ANSI_ARGS_((tclOSAComponent *theComponent,
- CONST char *scriptName, OSAID *scriptID));
-static tclOSAScript * tclOSAGetScript _ANSI_ARGS_((tclOSAComponent *theComponent,
- CONST char *scriptName));
-static int tclOSADeleteScript _ANSI_ARGS_((tclOSAComponent *theComponent,
- CONST char *scriptName,char *errMsg));
-
-/*
- * "export" is a MetroWerks specific pragma. It flags the linker that
- * any symbols that are defined when this pragma is on will be exported
- * to shared libraries that link with this library.
- */
-
-
-#pragma export on
-int Tclapplescript_Init( Tcl_Interp *interp );
-#pragma export reset
-
-/*
- *----------------------------------------------------------------------
- *
- * Tclapplescript_Init --
- *
- * Initializes the the OSA command which opens connections to
- * OSA components, creates the AppleScript command, which opens an
- * instance of the AppleScript component,and constructs the table of
- * available languages.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side Effects:
- * Opens one connection to the AppleScript component, if
- * available. Also builds up a table of available OSA languages,
- * and creates the OSA command.
- *
- *----------------------------------------------------------------------
- */
-
-int
-Tclapplescript_Init(
- Tcl_Interp *interp) /* Tcl interpreter. */
-{
- char *errMsg = NULL;
- OSErr myErr = noErr;
- Boolean gotAppleScript = false;
- Boolean GotOneOSALanguage = false;
- ComponentDescription compDescr = {
- kOSAComponentType,
- (OSType) 0,
- (OSType) 0,
- (long) 0,
- (long) 0
- }, *foundComp;
- Component curComponent = (Component) 0;
- ComponentInstance curOpenComponent;
- Tcl_HashTable *ComponentTable;
- Tcl_HashTable *LanguagesTable;
- Tcl_HashEntry *hashEntry;
- int newPtr;
- AEDesc componentName = { typeNull, NULL };
- char nameStr[32];
- Size nameLen;
- long appleScriptFlags;
-
- /*
- * Perform the required stubs magic...
- */
-
- if (!Tcl_InitStubs(interp, "8.2", 0)) {
- return TCL_ERROR;
- }
-
- /*
- * Here We Will Get The Available Osa Languages, Since They Can Only Be
- * Registered At Startup... If You Dynamically Load Components, This
- * Will Fail, But This Is Not A Common Thing To Do.
- */
-
- LanguagesTable = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
-
- if (LanguagesTable == NULL) {
- panic("Memory Error Allocating Languages Hash Table");
- }
-
- Tcl_SetAssocData(interp, "OSAScript_LangTable", NULL, LanguagesTable);
- Tcl_InitHashTable(LanguagesTable, TCL_STRING_KEYS);
-
-
- while ((curComponent = FindNextComponent(curComponent, &compDescr)) != 0) {
- int nbytes = sizeof(ComponentDescription);
- foundComp = (ComponentDescription *)
- ckalloc(sizeof(ComponentDescription));
- myErr = GetComponentInfo(curComponent, foundComp, NULL, NULL, NULL);
- if (foundComp->componentSubType ==
- kOSAGenericScriptingComponentSubtype) {
- /* Skip the generic component */
- ckfree((char *) foundComp);
- } else {
- GotOneOSALanguage = true;
-
- /*
- * This is gross: looks like I have to open the component just
- * to get its name!!! GetComponentInfo is supposed to return
- * the name, but AppleScript always returns an empty string.
- */
-
- curOpenComponent = OpenComponent(curComponent);
- if (curOpenComponent == NULL) {
- Tcl_AppendResult(interp,"Error opening component",
- (char *) NULL);
- return TCL_ERROR;
- }
-
- myErr = OSAScriptingComponentName(curOpenComponent,&componentName);
- if (myErr == noErr) {
- myErr = GetCStringFromDescriptor(&componentName,
- nameStr, 31, &nameLen);
- AEDisposeDesc(&componentName);
- }
- CloseComponent(curOpenComponent);
-
- if (myErr == noErr) {
- hashEntry = Tcl_CreateHashEntry(LanguagesTable,
- nameStr, &newPtr);
- Tcl_SetHashValue(hashEntry, (ClientData) foundComp);
- } else {
- Tcl_AppendResult(interp,"Error getting componentName.",
- (char *) NULL);
- return TCL_ERROR;
- }
-
- /*
- * Make sure AppleScript is loaded, otherwise we will
- * not bother to make the AppleScript command.
- */
- if (foundComp->componentSubType == kAppleScriptSubtype) {
- appleScriptFlags = foundComp->componentFlags;
- gotAppleScript = true;
- }
- }
- }
-
- /*
- * Create the OSA command.
- */
-
- if (!GotOneOSALanguage) {
- Tcl_AppendResult(interp,"Could not find any OSA languages",
- (char *) NULL);
- return TCL_ERROR;
- }
-
- /*
- * Create the Component Assoc Data & put it in the interpreter.
- */
-
- ComponentTable = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
-
- if (ComponentTable == NULL) {
- panic("Memory Error Allocating Hash Table");
- }
-
- Tcl_SetAssocData(interp, "OSAScript_CompTable", NULL, ComponentTable);
-
- Tcl_InitHashTable(ComponentTable, TCL_STRING_KEYS);
-
- /*
- * The OSA command is not currently supported.
- Tcl_CreateCommand(interp, "OSA", Tcl_OSACmd, (ClientData) NULL,
- (Tcl_CmdDeleteProc *) NULL);
- */
-
- /*
- * Open up one AppleScript component, with a default context
- * and tie it to the AppleScript command.
- * If the user just wants single-threaded AppleScript execution
- * this should be enough.
- *
- */
-
- if (gotAppleScript) {
- if (tclOSAMakeNewComponent(interp, "AppleScript",
- "AppleScript English", kAppleScriptSubtype,
- appleScriptFlags) == NULL ) {
- return TCL_ERROR;
- }
- }
-
- return Tcl_PkgProvide(interp, "OSAConnect", "1.0");
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_OSACmd --
- *
- * This is the command that provides the interface to the OSA
- * component manager. The subcommands are: close: close a component,
- * info: get info on components open, and open: get a new connection
- * with the Scripting Component
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * Depends on the subcommand, see the user documentation
- * for more details.
- *
- *----------------------------------------------------------------------
- */
-
-int
-Tcl_OSACmd(
- ClientData clientData,
- Tcl_Interp *interp,
- int argc,
- CONST char **argv)
-{
- static unsigned short componentCmdIndex = 0;
- char autoName[32];
- char c;
- int length;
- Tcl_HashTable *ComponentTable = NULL;
-
-
- if (argc == 1) {
- Tcl_AppendResult(interp, "Wrong # of arguments, should be \"",
- argv[0], " option\"", (char *) NULL);
- return TCL_ERROR;
- }
-
- c = *argv[1];
- length = strlen(argv[1]);
-
- /*
- * Query out the Component Table, since most of these commands use it...
- */
-
- ComponentTable = (Tcl_HashTable *) Tcl_GetAssocData(interp,
- "OSAScript_CompTable", (Tcl_InterpDeleteProc **) NULL);
-
- if (ComponentTable == NULL) {
- Tcl_AppendResult(interp, "Error, could not get the Component Table",
- " from the Associated data.", (char *) NULL);
- return TCL_ERROR;
- }
-
- if (c == 'c' && strncmp(argv[1],"close",length) == 0) {
- Tcl_HashEntry *hashEntry;
- if (argc != 3) {
- Tcl_AppendResult(interp, "Wrong # of arguments, should be \"",
- argv[0], " ",argv[1], " componentName\"",
- (char *) NULL);
- return TCL_ERROR;
- }
-
- if ((hashEntry = Tcl_FindHashEntry(ComponentTable,argv[2])) == NULL) {
- Tcl_AppendResult(interp, "Component \"", argv[2], "\" not found",
- (char *) NULL);
- return TCL_ERROR;
- } else {
- Tcl_DeleteCommand(interp,argv[2]);
- return TCL_OK;
- }
- } else if (c == 'o' && strncmp(argv[1],"open",length) == 0) {
- /*
- * Default language is AppleScript.
- */
- OSType scriptSubtype = kAppleScriptSubtype;
- char *languageName = "AppleScript English";
- char *errMsg = NULL;
- ComponentDescription *theCD;
-
- argv += 2;
- argc -= 2;
-
- while (argc > 0 ) {
- if (*argv[0] == '-') {
- c = *(argv[0] + 1);
- if (c == 'l' && strcmp(argv[0] + 1, "language") == 0) {
- if (argc == 1) {
- Tcl_AppendResult(interp,
- "Error - no language provided for the -language switch",
- (char *) NULL);
- return TCL_ERROR;
- } else {
- Tcl_HashEntry *hashEntry;
- Tcl_HashSearch search;
- Boolean gotIt = false;
- Tcl_HashTable *LanguagesTable;
-
- /*
- * Look up the language in the languages table
- * Do a simple strstr match, so AppleScript
- * will match "AppleScript English"...
- */
-
- LanguagesTable = Tcl_GetAssocData(interp,
- "OSAScript_LangTable",
- (Tcl_InterpDeleteProc **) NULL);
-
- for (hashEntry =
- Tcl_FirstHashEntry(LanguagesTable, &search);
- hashEntry != NULL;
- hashEntry = Tcl_NextHashEntry(&search)) {
- languageName = Tcl_GetHashKey(LanguagesTable,
- hashEntry);
- if (strstr(languageName,argv[1]) != NULL) {
- theCD = (ComponentDescription *)
- Tcl_GetHashValue(hashEntry);
- gotIt = true;
- break;
- }
- }
- if (!gotIt) {
- Tcl_AppendResult(interp,
- "Error, could not find the language \"",
- argv[1],
- "\" in the list of known languages.",
- (char *) NULL);
- return TCL_ERROR;
- }
- }
- }
- argc -= 2;
- argv += 2;
- } else {
- Tcl_AppendResult(interp, "Expected a flag, but got ",
- argv[0], (char *) NULL);
- return TCL_ERROR;
- }
- }
-
- sprintf(autoName, "OSAComponent%-d", componentCmdIndex++);
- if (tclOSAMakeNewComponent(interp, autoName, languageName,
- theCD->componentSubType, theCD->componentFlags) == NULL ) {
- return TCL_ERROR;
- } else {
- Tcl_SetResult(interp,autoName,TCL_VOLATILE);
- return TCL_OK;
- }
-
- } else if (c == 'i' && strncmp(argv[1],"info",length) == 0) {
- if (argc == 2) {
- Tcl_AppendResult(interp, "Wrong # of arguments, should be \"",
- argv[0], " ", argv[1], " what\"",
- (char *) NULL);
- return TCL_ERROR;
- }
-
- c = *argv[2];
- length = strlen(argv[2]);
-
- if (c == 'c' && strncmp(argv[2], "components", length) == 0) {
- Tcl_DString theResult;
-
- Tcl_DStringInit(&theResult);
-
- if (argc == 3) {
- getSortedHashKeys(ComponentTable,(char *) NULL, &theResult);
- } else if (argc == 4) {
- getSortedHashKeys(ComponentTable, argv[3], &theResult);
- } else {
- Tcl_AppendResult(interp, "Error: wrong # of arguments",
- ", should be \"", argv[0], " ", argv[1], " ",
- argv[2], " ?pattern?\".", (char *) NULL);
- return TCL_ERROR;
- }
- Tcl_DStringResult(interp, &theResult);
- return TCL_OK;
- } else if (c == 'l' && strncmp(argv[2],"languages",length) == 0) {
- Tcl_DString theResult;
- Tcl_HashTable *LanguagesTable;
-
- Tcl_DStringInit(&theResult);
- LanguagesTable = Tcl_GetAssocData(interp,
- "OSAScript_LangTable", (Tcl_InterpDeleteProc **) NULL);
-
- if (argc == 3) {
- getSortedHashKeys(LanguagesTable, (char *) NULL, &theResult);
- } else if (argc == 4) {
- getSortedHashKeys(LanguagesTable, argv[3], &theResult);
- } else {
- Tcl_AppendResult(interp, "Error: wrong # of arguments",
- ", should be \"", argv[0], " ", argv[1], " ",
- argv[2], " ?pattern?\".", (char *) NULL);
- return TCL_ERROR;
- }
- Tcl_DStringResult(interp,&theResult);
- return TCL_OK;
- } else {
- Tcl_AppendResult(interp, "Unknown option: ", argv[2],
- " for OSA info, should be one of",
- " \"components\" or \"languages\"",
- (char *) NULL);
- return TCL_ERROR;
- }
- } else {
- Tcl_AppendResult(interp, "Unknown option: ", argv[1],
- ", should be one of \"open\", \"close\" or \"info\".",
- (char *) NULL);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_OSAComponentCmd --
- *
- * This is the command that provides the interface with an OSA
- * component. The sub commands are:
- * - compile ? -context context? scriptData
- * compiles the script data, returns the ScriptID
- * - decompile ? -context context? scriptData
- * decompiles the script data, source code
- * - execute ?-context context? scriptData
- * compiles and runs script data
- * - info what: get component info
- * - load ?-flags values? fileName
- * loads & compiles script data from fileName
- * - run scriptId ?options?
- * executes the compiled script
- *
- * Results:
- * A standard Tcl result
- *
- * Side Effects:
- * Depends on the subcommand, see the user documentation
- * for more details.
- *
- *----------------------------------------------------------------------
- */
-
-int
-Tcl_OSAComponentCmd(
- ClientData clientData,
- Tcl_Interp *interp,
- int argc,
- CONST char **argv)
-{
- int length;
- char c;
-
- tclOSAComponent *OSAComponent = (tclOSAComponent *) clientData;
-
- if (argc == 1) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " option ?arg ...?\"",
- (char *) NULL);
- return TCL_ERROR;
- }
-
- c = *argv[1];
- length = strlen(argv[1]);
- if (c == 'c' && strncmp(argv[1], "compile", length) == 0) {
- return TclOSACompileCmd(interp, OSAComponent, argc, argv);
- } else if (c == 'l' && strncmp(argv[1], "load", length) == 0) {
- return tclOSALoadCmd(interp, OSAComponent, argc, argv);
- } else if (c == 'e' && strncmp(argv[1], "execute", length) == 0) {
- return tclOSAExecuteCmd(interp, OSAComponent, argc, argv);
- } else if (c == 'i' && strncmp(argv[1], "info", length) == 0) {
- return tclOSAInfoCmd(interp, OSAComponent, argc, argv);
- } else if (c == 'd' && strncmp(argv[1], "decompile", length) == 0) {
- return tclOSADecompileCmd(interp, OSAComponent, argc, argv);
- } else if (c == 'd' && strncmp(argv[1], "delete", length) == 0) {
- return tclOSADeleteCmd(interp, OSAComponent, argc, argv);
- } else if (c == 'r' && strncmp(argv[1], "run", length) == 0) {
- return tclOSARunCmd(interp, OSAComponent, argc, argv);
- } else if (c == 's' && strncmp(argv[1], "store", length) == 0) {
- return tclOSAStoreCmd(interp, OSAComponent, argc, argv);
- } else {
- Tcl_AppendResult(interp,"bad option \"", argv[1],
- "\": should be compile, decompile, delete, ",
- "execute, info, load, run or store",
- (char *) NULL);
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclOSACompileCmd --
- *
- * This is the compile subcommand for the component command.
- *
- * Results:
- * A standard Tcl result
- *
- * Side Effects:
- * Compiles the script data either into a script or a script
- * context. Adds the script to the component's script or context
- * table. Sets interp's result to the name of the new script or
- * context.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-TclOSACompileCmd(
- Tcl_Interp *interp,
- tclOSAComponent *OSAComponent,
- int argc,
- CONST char **argv)
-{
- int tclError = TCL_OK;
- int augment = 1;
- int makeContext = 0;
- char c;
- char autoName[16];
- char buffer[32];
- char *resultName;
- Boolean makeNewContext = false;
- Tcl_DString scrptData;
- AEDesc scrptDesc = { typeNull, NULL };
- long modeFlags = kOSAModeCanInteract;
- OSAID resultID = kOSANullScript;
- OSAID contextID = kOSANullScript;
- OSAID parentID = kOSANullScript;
- OSAError osaErr = noErr;
-
- if (!(OSAComponent->componentFlags && kOSASupportsCompiling)) {
- Tcl_AppendResult(interp,
- "OSA component does not support compiling",
- (char *) NULL);
- return TCL_ERROR;
- }
-
- /*
- * This signals that we should make up a name, which is the
- * default behavior:
- */
-
- autoName[0] = '\0';
- resultName = NULL;
-
- if (argc == 2) {
- numArgs:
- Tcl_AppendResult(interp,
- "wrong # args: should be \"", argv[0], " ", argv[1],
- " ?options? code\"",(char *) NULL);
- return TCL_ERROR;
- }
-
- argv += 2;
- argc -= 2;
-
- /*
- * Do the argument parsing.
- */
-
- while (argc > 0) {
-
- if (*argv[0] == '-') {
- c = *(argv[0] + 1);
-
- /*
- * "--" is the only switch that has no value, stops processing
- */
-
- if (c == '-' && *(argv[0] + 2) == '\0') {
- argv += 1;
- argc--;
- break;
- }
-
- /*
- * So we can check here a switch with no value.
- */
-
- if (argc == 1) {
- Tcl_AppendResult(interp,
- "no value given for switch: ",
- argv[0], (char *) NULL);
- return TCL_ERROR;
- }
-
- if (c == 'c' && strcmp(argv[0] + 1, "context") == 0) {
- if (Tcl_GetBoolean(interp, argv[1], &makeContext) != TCL_OK) {
- return TCL_ERROR;
- }
- } else if (c == 'a' && strcmp(argv[0] + 1, "augment") == 0) {
- /*
- * Augment the current context which implies making a context.
- */
-
- if (Tcl_GetBoolean(interp, argv[1], &augment) != TCL_OK) {
- return TCL_ERROR;
- }
- makeContext = 1;
- } else if (c == 'n' && strcmp(argv[0] + 1, "name") == 0) {
- strncpy(autoName, argv[1], 15);
- autoName[15] = '\0';
- resultName = autoName;
- } else if (c == 'p' && strcmp(argv[0] + 1,"parent") == 0) {
- /*
- * Since this implies we are compiling into a context,
- * set makeContext here
- */
- if (tclOSAGetContextID(OSAComponent,
- argv[1], &parentID) != TCL_OK) {
- Tcl_AppendResult(interp, "context not found \"",
- argv[1], "\"", (char *) NULL);
- return TCL_ERROR;
- }
- makeContext = 1;
- } else {
- Tcl_AppendResult(interp, "bad option \"", argv[0],
- "\": should be -augment, -context, -name or -parent",
- (char *) NULL);
- return TCL_ERROR;
- }
- argv += 2;
- argc -= 2;
-
- } else {
- break;
- }
- }
-
- /*
- * Make sure we have some data left...
- */
- if (argc == 0) {
- goto numArgs;
- }
-
- /*
- * Now if we are making a context, see if it is a new one...
- * There are three options here:
- * 1) There was no name provided, so we autoName it
- * 2) There was a name, then check and see if it already exists
- * a) If yes, then makeNewContext is false
- * b) Otherwise we are making a new context
- */
-
- if (makeContext) {
- modeFlags |= kOSAModeCompileIntoContext;
- if (resultName == NULL) {
- /*
- * Auto name the new context.
- */
- resultName = autoName;
- resultID = kOSANullScript;
- makeNewContext = true;
- } else if (tclOSAGetContextID(OSAComponent,
- resultName, &resultID) == TCL_OK) {
- } else {
- makeNewContext = true;
- }
-
- /*
- * Deal with the augment now...
- */
- if (augment && !makeNewContext) {
- modeFlags |= kOSAModeAugmentContext;
- }
- } else if (resultName == NULL) {
- resultName = autoName; /* Auto name the script */
- }
-
- /*
- * Ok, now we have the options, so we can compile the script data.
- */
-
- if (prepareScriptData(argc, argv, &scrptData, &scrptDesc) == TCL_ERROR) {
- Tcl_DStringResult(interp, &scrptData);
- AEDisposeDesc(&scrptDesc);
- return TCL_ERROR;
- }
-
- /*
- * If we want to use a parent context, we have to make the context
- * by hand. Note, parentID is only specified when you make a new context.
- */
-
- if (parentID != kOSANullScript && makeNewContext) {
- AEDesc contextDesc = { typeNull, NULL };
-
- osaErr = OSAMakeContext(OSAComponent->theComponent,
- &contextDesc, parentID, &resultID);
- modeFlags |= kOSAModeAugmentContext;
- }
-
- osaErr = OSACompile(OSAComponent->theComponent, &scrptDesc,
- modeFlags, &resultID);
- if (osaErr == noErr) {
-
- if (makeContext) {
- /*
- * For the compiled context to be active, you need to run
- * the code that is in the context.
- */
- OSAID activateID;
-
- osaErr = OSAExecute(OSAComponent->theComponent, resultID,
- resultID, kOSAModeCanInteract, &activateID);
- OSADispose(OSAComponent->theComponent, activateID);
-
- if (osaErr == noErr) {
- if (makeNewContext) {
- /*
- * If we have compiled into a context,
- * this is added to the context table
- */
-
- tclOSAAddContext(OSAComponent, resultName, resultID);
- }
-
- Tcl_SetResult(interp, resultName, TCL_VOLATILE);
- tclError = TCL_OK;
- }
- } else {
- /*
- * For a script, we return the script name.
- */
- tclOSAAddScript(OSAComponent, resultName, modeFlags, resultID);
- Tcl_SetResult(interp, resultName, TCL_VOLATILE);
- tclError = TCL_OK;
- }
- }
-
- /*
- * This catches the error either from the original compile,
- * or from the execute in case makeContext == true
- */
-
- if (osaErr == errOSAScriptError) {
- OSADispose(OSAComponent->theComponent, resultID);
- tclOSAASError(interp, OSAComponent->theComponent,
- Tcl_DStringValue(&scrptData));
- tclError = TCL_ERROR;
- } else if (osaErr != noErr) {
- sprintf(buffer, "Error #%-6ld compiling script", osaErr);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- tclError = TCL_ERROR;
- }
-
- Tcl_DStringFree(&scrptData);
- AEDisposeDesc(&scrptDesc);
-
- return tclError;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tclOSADecompileCmd --
- *
- * This implements the Decompile subcommand of the component command
- *
- * Results:
- * A standard Tcl result.
- *
- * Side Effects:
- * Decompiles the script, and sets interp's result to the
- * decompiled script data.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-tclOSADecompileCmd(
- Tcl_Interp * interp,
- tclOSAComponent *OSAComponent,
- int argc,
- CONST char **argv)
-{
- AEDesc resultingSourceData = { typeChar, NULL };
- OSAID scriptID;
- Boolean isContext;
- long result;
- OSErr sysErr = noErr;
-
- if (argc == 2) {
- Tcl_AppendResult(interp, "Wrong # of arguments, should be \"",
- argv[0], " ",argv[1], " scriptName \"", (char *) NULL );
- return TCL_ERROR;
- }
-
- if (!(OSAComponent->componentFlags && kOSASupportsGetSource)) {
- Tcl_AppendResult(interp,
- "Error, this component does not support get source",
- (char *) NULL);
- return TCL_ERROR;
- }
-
- if (tclOSAGetScriptID(OSAComponent, argv[2], &scriptID) == TCL_OK) {
- isContext = false;
- } else if (tclOSAGetContextID(OSAComponent, argv[2], &scriptID)
- == TCL_OK ) {
- isContext = true;
- } else {
- Tcl_AppendResult(interp, "Could not find script \"",
- argv[2], "\"", (char *) NULL);
- return TCL_ERROR;
- }
-
- OSAGetScriptInfo(OSAComponent->theComponent, scriptID,
- kOSACanGetSource, &result);
-
- sysErr = OSAGetSource(OSAComponent->theComponent,
- scriptID, typeChar, &resultingSourceData);
-
- if (sysErr == noErr) {
- Tcl_DString theResult;
- Tcl_DStringInit(&theResult);
-
- Tcl_DStringAppend(&theResult, *resultingSourceData.dataHandle,
- GetHandleSize(resultingSourceData.dataHandle));
- Tcl_DStringResult(interp, &theResult);
- AEDisposeDesc(&resultingSourceData);
- return TCL_OK;
- } else {
- Tcl_AppendResult(interp, "Error getting source data", (char *) NULL);
- AEDisposeDesc(&resultingSourceData);
- return TCL_ERROR;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tclOSADeleteCmd --
- *
- * This implements the Delete subcommand of the Component command.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side Effects:
- * Deletes a script from the script list of the given component.
- * Removes all references to the script, and frees the memory
- * associated with it.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-tclOSADeleteCmd(
- Tcl_Interp *interp,
- tclOSAComponent *OSAComponent,
- int argc,
- CONST char **argv)
-{
- char c,*errMsg = NULL;
- int length;
-
- if (argc < 4) {
- Tcl_AppendResult(interp, "Wrong # of arguments, should be \"",
- argv[0], " ", argv[1], " what scriptName", (char *) NULL);
- return TCL_ERROR;
- }
-
- c = *argv[2];
- length = strlen(argv[2]);
- if (c == 'c' && strncmp(argv[2], "context", length) == 0) {
- if (strcmp(argv[3], "global") == 0) {
- Tcl_AppendResult(interp, "You cannot delete the global context",
- (char *) NULL);
- return TCL_ERROR;
- } else if (tclOSADeleteContext(OSAComponent, argv[3]) != TCL_OK) {
- Tcl_AppendResult(interp, "Error deleting script \"", argv[2],
- "\": ", errMsg, (char *) NULL);
- ckfree(errMsg);
- return TCL_ERROR;
- }
- } else if (c == 's' && strncmp(argv[2], "script", length) == 0) {
- if (tclOSADeleteScript(OSAComponent, argv[3], errMsg) != TCL_OK) {
- Tcl_AppendResult(interp, "Error deleting script \"", argv[3],
- "\": ", errMsg, (char *) NULL);
- ckfree(errMsg);
- return TCL_ERROR;
- }
- } else {
- Tcl_AppendResult(interp,"Unknown value ", argv[2],
- " should be one of ",
- "\"context\" or \"script\".",
- (char *) NULL );
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tclOSAExecuteCmd --
- *
- * This implements the execute subcommand of the component command.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * Executes the given script data, and sets interp's result to
- * the OSA component's return value.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-tclOSAExecuteCmd(
- Tcl_Interp *interp,
- tclOSAComponent *OSAComponent,
- int argc,
- CONST char **argv)
-{
- int tclError = TCL_OK, resID = 128;
- char c,buffer[32],
- *contextName = NULL,*scriptName = NULL, *resName = NULL;
- Boolean makeNewContext = false,makeContext = false;
- AEDesc scrptDesc = { typeNull, NULL };
- long modeFlags = kOSAModeCanInteract;
- OSAID resultID = kOSANullScript,
- contextID = kOSANullScript,
- parentID = kOSANullScript;
- Tcl_DString scrptData;
- OSAError osaErr = noErr;
- OSErr sysErr = noErr;
-
- if (argc == 2) {
- Tcl_AppendResult(interp,
- "Error, no script data for \"", argv[0],
- " run\"", (char *) NULL);
- return TCL_ERROR;
- }
-
- argv += 2;
- argc -= 2;
-
- /*
- * Set the context to the global context by default.
- * Then parse the argument list for switches
- */
- tclOSAGetContextID(OSAComponent, "global", &contextID);
-
- while (argc > 0) {
-
- if (*argv[0] == '-') {
- c = *(argv[0] + 1);
-
- /*
- * "--" is the only switch that has no value.
- */
-
- if (c == '-' && *(argv[0] + 2) == '\0') {
- argv += 1;
- argc--;
- break;
- }
-
- /*
- * So we can check here for a switch with no value.
- */
-
- if (argc == 1) {
- Tcl_AppendResult(interp,
- "Error, no value given for switch ",
- argv[0], (char *) NULL);
- return TCL_ERROR;
- }
-
- if (c == 'c' && strcmp(argv[0] + 1, "context") == 0) {
- if (tclOSAGetContextID(OSAComponent,
- argv[1], &contextID) == TCL_OK) {
- } else {
- Tcl_AppendResult(interp, "Script context \"",
- argv[1], "\" not found", (char *) NULL);
- return TCL_ERROR;
- }
- } else {
- Tcl_AppendResult(interp, "Error, invalid switch ", argv[0],
- " should be \"-context\"", (char *) NULL);
- return TCL_ERROR;
- }
-
- argv += 2;
- argc -= 2;
- } else {
- break;
- }
- }
-
- if (argc == 0) {
- Tcl_AppendResult(interp, "Error, no script data", (char *) NULL);
- return TCL_ERROR;
- }
-
- if (prepareScriptData(argc, argv, &scrptData, &scrptDesc) == TCL_ERROR) {
- Tcl_DStringResult(interp, &scrptData);
- AEDisposeDesc(&scrptDesc);
- return TCL_ERROR;
- }
- /*
- * Now try to compile and run, but check to make sure the
- * component supports the one shot deal
- */
- if (OSAComponent->componentFlags && kOSASupportsConvenience) {
- osaErr = OSACompileExecute(OSAComponent->theComponent,
- &scrptDesc, contextID, modeFlags, &resultID);
- } else {
- /*
- * If not, we have to do this ourselves
- */
- if (OSAComponent->componentFlags && kOSASupportsCompiling) {
- OSAID compiledID = kOSANullScript;
- osaErr = OSACompile(OSAComponent->theComponent, &scrptDesc,
- modeFlags, &compiledID);
- if (osaErr == noErr) {
- osaErr = OSAExecute(OSAComponent->theComponent, compiledID,
- contextID, modeFlags, &resultID);
- }
- OSADispose(OSAComponent->theComponent, compiledID);
- } else {
- /*
- * The scripting component had better be able to load text data...
- */
- OSAID loadedID = kOSANullScript;
-
- scrptDesc.descriptorType = OSAComponent->languageID;
- osaErr = OSALoad(OSAComponent->theComponent, &scrptDesc,
- modeFlags, &loadedID);
- if (osaErr == noErr) {
- OSAExecute(OSAComponent->theComponent, loadedID,
- contextID, modeFlags, &resultID);
- }
- OSADispose(OSAComponent->theComponent, loadedID);
- }
- }
- if (osaErr == errOSAScriptError) {
- tclOSAASError(interp, OSAComponent->theComponent,
- Tcl_DStringValue(&scrptData));
- tclError = TCL_ERROR;
- } else if (osaErr != noErr) {
- sprintf(buffer, "Error #%-6ld compiling script", osaErr);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- tclError = TCL_ERROR;
- } else {
- tclOSAResultFromID(interp, OSAComponent->theComponent, resultID);
- osaErr = OSADispose(OSAComponent->theComponent, resultID);
- tclError = TCL_OK;
- }
-
- Tcl_DStringFree(&scrptData);
- AEDisposeDesc(&scrptDesc);
-
- return tclError;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tclOSAInfoCmd --
- *
- * This implements the Info subcommand of the component command
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * Info on scripts and contexts. See the user documentation for details.
- *
- *----------------------------------------------------------------------
- */
-static int
-tclOSAInfoCmd(
- Tcl_Interp *interp,
- tclOSAComponent *OSAComponent,
- int argc,
- CONST char **argv)
-{
- char c;
- int length;
- Tcl_DString theResult;
-
- if (argc == 2) {
- Tcl_AppendResult(interp, "Wrong # of arguments, should be \"",
- argv[0], " ", argv[1], " what \"", (char *) NULL );
- return TCL_ERROR;
- }
-
- c = *argv[2];
- length = strlen(argv[2]);
- if (c == 's' && strncmp(argv[2], "scripts", length) == 0) {
- Tcl_DStringInit(&theResult);
- if (argc == 3) {
- getSortedHashKeys(&OSAComponent->scriptTable, (char *) NULL,
- &theResult);
- } else if (argc == 4) {
- getSortedHashKeys(&OSAComponent->scriptTable, argv[3], &theResult);
- } else {
- Tcl_AppendResult(interp, "Error: wrong # of arguments,",
- " should be \"", argv[0], " ", argv[1], " ",
- argv[2], " ?pattern?", (char *) NULL);
- return TCL_ERROR;
- }
- Tcl_DStringResult(interp, &theResult);
- return TCL_OK;
- } else if (c == 'c' && strncmp(argv[2], "contexts", length) == 0) {
- Tcl_DStringInit(&theResult);
- if (argc == 3) {
- getSortedHashKeys(&OSAComponent->contextTable, (char *) NULL,
- &theResult);
- } else if (argc == 4) {
- getSortedHashKeys(&OSAComponent->contextTable,
- argv[3], &theResult);
- } else {
- Tcl_AppendResult(interp, "Error: wrong # of arguments for ,",
- " should be \"", argv[0], " ", argv[1], " ",
- argv[2], " ?pattern?", (char *) NULL);
- return TCL_ERROR;
- }
- Tcl_DStringResult(interp, &theResult);
- return TCL_OK;
- } else if (c == 'l' && strncmp(argv[2], "language", length) == 0) {
- Tcl_SetResult(interp, OSAComponent->languageName, TCL_STATIC);
- return TCL_OK;
- } else {
- Tcl_AppendResult(interp, "Unknown argument \"", argv[2],
- "\" for \"", argv[0], " info \", should be one of ",
- "\"scripts\" \"language\", or \"contexts\"",
- (char *) NULL);
- return TCL_ERROR;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tclOSALoadCmd --
- *
- * This is the load subcommand for the Component Command
- *
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * Loads script data from the given file, creates a new context
- * for it, and sets interp's result to the name of the new context.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-tclOSALoadCmd(
- Tcl_Interp *interp,
- tclOSAComponent *OSAComponent,
- int argc,
- CONST char **argv)
-{
- int tclError = TCL_OK, resID = 128;
- char c, autoName[24],
- *contextName = NULL, *scriptName = NULL;
- CONST char *resName = NULL;
- Boolean makeNewContext = false, makeContext = false;
- AEDesc scrptDesc = { typeNull, NULL };
- long modeFlags = kOSAModeCanInteract;
- OSAID resultID = kOSANullScript,
- contextID = kOSANullScript,
- parentID = kOSANullScript;
- OSAError osaErr = noErr;
- OSErr sysErr = noErr;
- long scptInfo;
-
- autoName[0] = '\0';
- scriptName = autoName;
- contextName = autoName;
-
- if (argc == 2) {
- Tcl_AppendResult(interp,
- "Error, no data for \"", argv[0], " ", argv[1],
- "\"", (char *) NULL);
- return TCL_ERROR;
- }
-
- argv += 2;
- argc -= 2;
-
- /*
- * Do the argument parsing.
- */
-
- while (argc > 0) {
-
- if (*argv[0] == '-') {
- c = *(argv[0] + 1);
-
- /*
- * "--" is the only switch that has no value.
- */
-
- if (c == '-' && *(argv[0] + 2) == '\0') {
- argv += 1;
- argc--;
- break;
- }
-
- /*
- * So we can check here a switch with no value.
- */
-
- if (argc == 1) {
- Tcl_AppendResult(interp, "Error, no value given for switch ",
- argv[0], (char *) NULL);
- return TCL_ERROR;
- }
-
- if (c == 'r' && strcmp(argv[0] + 1, "rsrcname") == 0) {
- resName = argv[1];
- } else if (c == 'r' && strcmp(argv[0] + 1, "rsrcid") == 0) {
- if (Tcl_GetInt(interp, argv[1], &resID) != TCL_OK) {
- Tcl_AppendResult(interp,
- "Error getting resource ID", (char *) NULL);
- return TCL_ERROR;
- }
- } else {
- Tcl_AppendResult(interp, "Error, invalid switch ", argv[0],
- " should be \"--\", \"-rsrcname\" or \"-rsrcid\"",
- (char *) NULL);
- return TCL_ERROR;
- }
-
- argv += 2;
- argc -= 2;
- } else {
- break;
- }
- }
- /*
- * Ok, now we have the options, so we can load the resource,
- */
- if (argc == 0) {
- Tcl_AppendResult(interp, "Error, no filename given", (char *) NULL);
- return TCL_ERROR;
- }
-
- if (tclOSALoad(interp, OSAComponent, resName, resID,
- argv[0], &resultID) != TCL_OK) {
- Tcl_AppendResult(interp, "Error in load command", (char *) NULL);
- return TCL_ERROR;
- }
-
- /*
- * Now find out whether we have a script, or a script context.
- */
-
- OSAGetScriptInfo(OSAComponent->theComponent, resultID,
- kOSAScriptIsTypeScriptContext, &scptInfo);
-
- if (scptInfo) {
- autoName[0] = '\0';
- tclOSAAddContext(OSAComponent, autoName, resultID);
-
- Tcl_SetResult(interp, autoName, TCL_VOLATILE);
- } else {
- /*
- * For a script, we return the script name
- */
- autoName[0] = '\0';
- tclOSAAddScript(OSAComponent, autoName, kOSAModeCanInteract, resultID);
- Tcl_SetResult(interp, autoName, TCL_VOLATILE);
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tclOSARunCmd --
- *
- * This implements the run subcommand of the component command
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * Runs the given compiled script, and returns the OSA
- * component's result.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-tclOSARunCmd(
- Tcl_Interp *interp,
- tclOSAComponent *OSAComponent,
- int argc,
- CONST char **argv)
-{
- int tclError = TCL_OK,
- resID = 128;
- char c, *contextName = NULL,
- *scriptName = NULL,
- *resName = NULL;
- AEDesc scrptDesc = { typeNull, NULL };
- long modeFlags = kOSAModeCanInteract;
- OSAID resultID = kOSANullScript,
- contextID = kOSANullScript,
- parentID = kOSANullScript;
- OSAError osaErr = noErr;
- OSErr sysErr = noErr;
- CONST char *componentName = argv[0];
- OSAID scriptID;
-
- if (argc == 2) {
- Tcl_AppendResult(interp, "Wrong # of arguments, should be \"",
- argv[0], " ", argv[1], " scriptName", (char *) NULL);
- return TCL_ERROR;
- }
-
- /*
- * Set the context to the global context for this component,
- * as a default
- */
- if (tclOSAGetContextID(OSAComponent, "global", &contextID) != TCL_OK) {
- Tcl_AppendResult(interp,
- "Could not find the global context for component ",
- OSAComponent->theName, (char *) NULL );
- return TCL_ERROR;
- }
-
- /*
- * Now parse the argument list for switches
- */
- argv += 2;
- argc -= 2;
-
- while (argc > 0) {
- if (*argv[0] == '-') {
- c = *(argv[0] + 1);
- /*
- * "--" is the only switch that has no value
- */
- if (c == '-' && *(argv[0] + 2) == '\0') {
- argv += 1;
- argc--;
- break;
- }
-
- /*
- * So we can check here for a switch with no value.
- */
- if (argc == 1) {
- Tcl_AppendResult(interp, "Error, no value given for switch ",
- argv[0], (char *) NULL);
- return TCL_ERROR;
- }
-
- if (c == 'c' && strcmp(argv[0] + 1, "context") == 0) {
- if (argc == 1) {
- Tcl_AppendResult(interp,
- "Error - no context provided for the -context switch",
- (char *) NULL);
- return TCL_ERROR;
- } else if (tclOSAGetContextID(OSAComponent,
- argv[1], &contextID) == TCL_OK) {
- } else {
- Tcl_AppendResult(interp, "Script context \"", argv[1],
- "\" not found", (char *) NULL);
- return TCL_ERROR;
- }
- } else {
- Tcl_AppendResult(interp, "Error, invalid switch ", argv[0],
- " for ", componentName,
- " should be \"-context\"", (char *) NULL);
- return TCL_ERROR;
- }
- argv += 2;
- argc -= 2;
- } else {
- break;
- }
- }
-
- if (tclOSAGetScriptID(OSAComponent, argv[0], &scriptID) != TCL_OK) {
- if (tclOSAGetContextID(OSAComponent, argv[0], &scriptID) != TCL_OK) {
- Tcl_AppendResult(interp, "Could not find script \"",
- argv[2], "\"", (char *) NULL);
- return TCL_ERROR;
- }
- }
-
- sysErr = OSAExecute(OSAComponent->theComponent,
- scriptID, contextID, modeFlags, &resultID);
-
- if (sysErr == errOSAScriptError) {
- tclOSAASError(interp, OSAComponent->theComponent, (char *) NULL);
- tclError = TCL_ERROR;
- } else if (sysErr != noErr) {
- char buffer[32];
- sprintf(buffer, "Error #%6.6d encountered in run", sysErr);
- Tcl_SetResult(interp, buffer, TCL_VOLATILE);
- tclError = TCL_ERROR;
- } else {
- tclOSAResultFromID(interp, OSAComponent->theComponent, resultID );
- }
- OSADispose(OSAComponent->theComponent, resultID);
-
- return tclError;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tclOSAStoreCmd --
- *
- * This implements the store subcommand of the component command
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * Runs the given compiled script, and returns the OSA
- * component's result.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-tclOSAStoreCmd(
- Tcl_Interp *interp,
- tclOSAComponent *OSAComponent,
- int argc,
- CONST char **argv)
-{
- int tclError = TCL_OK, resID = 128;
- char c, *contextName = NULL, *scriptName = NULL;
- CONST char *resName = NULL;
- Boolean makeNewContext = false, makeContext = false;
- AEDesc scrptDesc = { typeNull, NULL };
- long modeFlags = kOSAModeCanInteract;
- OSAID resultID = kOSANullScript,
- contextID = kOSANullScript,
- parentID = kOSANullScript;
- OSAError osaErr = noErr;
- OSErr sysErr = noErr;
-
- if (argc == 2) {
- Tcl_AppendResult(interp, "Error, no data for \"", argv[0],
- " ",argv[1], "\"", (char *) NULL);
- return TCL_ERROR;
- }
-
- argv += 2;
- argc -= 2;
-
- /*
- * Do the argument parsing
- */
-
- while (argc > 0) {
- if (*argv[0] == '-') {
- c = *(argv[0] + 1);
-
- /*
- * "--" is the only switch that has no value
- */
- if (c == '-' && *(argv[0] + 2) == '\0') {
- argv += 1;
- argc--;
- break;
- }
-
- /*
- * So we can check here a switch with no value.
- */
- if (argc == 1) {
- Tcl_AppendResult(interp,
- "Error, no value given for switch ",
- argv[0], (char *) NULL);
- return TCL_ERROR;
- }
-
- if (c == 'r' && strcmp(argv[0] + 1, "rsrcname") == 0) {
- resName = argv[1];
- } else if (c == 'r' && strcmp(argv[0] + 1, "rsrcid") == 0) {
- if (Tcl_GetInt(interp, argv[1], &resID) != TCL_OK) {
- Tcl_AppendResult(interp,
- "Error getting resource ID", (char *) NULL);
- return TCL_ERROR;
- }
- } else {
- Tcl_AppendResult(interp, "Error, invalid switch ", argv[0],
- " should be \"--\", \"-rsrcname\" or \"-rsrcid\"",
- (char *) NULL);
- return TCL_ERROR;
- }
-
- argv += 2;
- argc -= 2;
- } else {
- break;
- }
- }
- /*
- * Ok, now we have the options, so we can load the resource,
- */
- if (argc != 2) {
- Tcl_AppendResult(interp, "Error, wrong # of arguments, should be ",
- argv[0], " ", argv[1], "?option flag? scriptName fileName",
- (char *) NULL);
- return TCL_ERROR;
- }
-
- if (tclOSAStore(interp, OSAComponent, resName, resID,
- argv[0], argv[1]) != TCL_OK) {
- Tcl_AppendResult(interp, "Error in load command", (char *) NULL);
- return TCL_ERROR;
- } else {
- Tcl_ResetResult(interp);
- tclError = TCL_OK;
- }
-
- return tclError;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tclOSAMakeNewComponent --
- *
- * Makes a command cmdName to represent a new connection to the
- * OSA component with componentSubType scriptSubtype.
- *
- * Results:
- * Returns the tclOSAComponent structure for the connection.
- *
- * Side Effects:
- * Adds a new element to the component table. If there is an
- * error, then the result of the Tcl interpreter interp is set
- * to an appropriate error message.
- *
- *----------------------------------------------------------------------
- */
-
-tclOSAComponent *
-tclOSAMakeNewComponent(
- Tcl_Interp *interp,
- char *cmdName,
- char *languageName,
- OSType scriptSubtype,
- long componentFlags)
-{
- char buffer[32];
- AEDesc resultingName = {typeNull, NULL};
- AEDesc nullDesc = {typeNull, NULL };
- OSAID globalContext;
- char global[] = "global";
- int nbytes;
- ComponentDescription requestedComponent = {
- kOSAComponentType,
- (OSType) 0,
- (OSType) 0,
- (long int) 0,
- (long int) 0
- };
- Tcl_HashTable *ComponentTable;
- Component foundComponent = NULL;
- OSAActiveUPP myActiveProcUPP;
-
- tclOSAComponent *newComponent;
- Tcl_HashEntry *hashEntry;
- int newPtr;
-
- requestedComponent.componentSubType = scriptSubtype;
- nbytes = sizeof(tclOSAComponent);
- newComponent = (tclOSAComponent *) ckalloc(sizeof(tclOSAComponent));
- if (newComponent == NULL) {
- goto CleanUp;
- }
-
- foundComponent = FindNextComponent(0, &requestedComponent);
- if (foundComponent == 0) {
- Tcl_AppendResult(interp,
- "Could not find component of requested type", (char *) NULL);
- goto CleanUp;
- }
-
- newComponent->theComponent = OpenComponent(foundComponent);
-
- if (newComponent->theComponent == NULL) {
- Tcl_AppendResult(interp,
- "Could not open component of the requested type",
- (char *) NULL);
- goto CleanUp;
- }
-
- newComponent->languageName = (char *) ckalloc(strlen(languageName) + 1);
- strcpy(newComponent->languageName,languageName);
-
- newComponent->componentFlags = componentFlags;
-
- newComponent->theInterp = interp;
-
- Tcl_InitHashTable(&newComponent->contextTable, TCL_STRING_KEYS);
- Tcl_InitHashTable(&newComponent->scriptTable, TCL_STRING_KEYS);
-
- if (tclOSAMakeContext(newComponent, global, &globalContext) != TCL_OK) {
- sprintf(buffer, "%-6.6ld", globalContext);
- Tcl_AppendResult(interp, "Error ", buffer, " making ", global,
- " context.", (char *) NULL);
- goto CleanUp;
- }
-
- newComponent->languageID = scriptSubtype;
-
- newComponent->theName = (char *) ckalloc(strlen(cmdName) + 1 );
- strcpy(newComponent->theName, cmdName);
-
- Tcl_CreateCommand(interp, newComponent->theName, Tcl_OSAComponentCmd,
- (ClientData) newComponent, tclOSAClose);
-
- /*
- * Register the new component with the component table
- */
-
- ComponentTable = (Tcl_HashTable *) Tcl_GetAssocData(interp,
- "OSAScript_CompTable", (Tcl_InterpDeleteProc **) NULL);
-
- if (ComponentTable == NULL) {
- Tcl_AppendResult(interp, "Error, could not get the Component Table",
- " from the Associated data.", (char *) NULL);
- return (tclOSAComponent *) NULL;
- }
-
- hashEntry = Tcl_CreateHashEntry(ComponentTable,
- newComponent->theName, &newPtr);
- Tcl_SetHashValue(hashEntry, (ClientData) newComponent);
-
- /*
- * Set the active proc to call Tcl_DoOneEvent() while idle
- */
- if (OSAGetActiveProc(newComponent->theComponent,
- &newComponent->defActiveProc, &newComponent->defRefCon) != noErr ) {
- /* TODO -- clean up here... */
- }
-
- myActiveProcUPP = NewOSAActiveUPP(TclOSAActiveProc);
- OSASetActiveProc(newComponent->theComponent,
- myActiveProcUPP, (long) newComponent);
- return newComponent;
-
- CleanUp:
-
- ckfree((char *) newComponent);
- return (tclOSAComponent *) NULL;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tclOSAClose --
- *
- * This procedure closes the connection to an OSA component, and
- * deletes all the script and context data associated with it.
- * It is the command deletion callback for the component's command.
- *
- * Results:
- * None
- *
- * Side effects:
- * Closes the connection, and releases all the script data.
- *
- *----------------------------------------------------------------------
- */
-
-void
-tclOSAClose(
- ClientData clientData)
-{
- tclOSAComponent *theComponent = (tclOSAComponent *) clientData;
- Tcl_HashEntry *hashEntry;
- Tcl_HashSearch search;
- tclOSAScript *theScript;
- Tcl_HashTable *ComponentTable;
-
- /*
- * Delete the context and script tables
- * the memory for the language name, and
- * the hash entry.
- */
-
- for (hashEntry = Tcl_FirstHashEntry(&theComponent->scriptTable, &search);
- hashEntry != NULL;
- hashEntry = Tcl_NextHashEntry(&search)) {
-
- theScript = (tclOSAScript *) Tcl_GetHashValue(hashEntry);
- OSADispose(theComponent->theComponent, theScript->scriptID);
- ckfree((char *) theScript);
- Tcl_DeleteHashEntry(hashEntry);
- }
-
- for (hashEntry = Tcl_FirstHashEntry(&theComponent->contextTable, &search);
- hashEntry != NULL;
- hashEntry = Tcl_NextHashEntry(&search)) {
-
- Tcl_DeleteHashEntry(hashEntry);
- }
-
- ckfree(theComponent->languageName);
- ckfree(theComponent->theName);
-
- /*
- * Finally close the component
- */
-
- CloseComponent(theComponent->theComponent);
-
- ComponentTable = (Tcl_HashTable *)
- Tcl_GetAssocData(theComponent->theInterp,
- "OSAScript_CompTable", (Tcl_InterpDeleteProc **) NULL);
-
- if (ComponentTable == NULL) {
- panic("Error, could not get the Component Table from the Associated data.");
- }
-
- hashEntry = Tcl_FindHashEntry(ComponentTable, theComponent->theName);
- if (hashEntry != NULL) {
- Tcl_DeleteHashEntry(hashEntry);
- }
-
- ckfree((char *) theComponent);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tclOSAGetContextID --
- *
- * This returns the context ID, given the component name.
- *
- * Results:
- * A context ID
- *
- * Side effects:
- * None
- *
- *----------------------------------------------------------------------
- */
-
-static int
-tclOSAGetContextID(
- tclOSAComponent *theComponent,
- CONST char *contextName,
- OSAID *theContext)
-{
- Tcl_HashEntry *hashEntry;
- tclOSAContext *contextStruct;
-
- if ((hashEntry = Tcl_FindHashEntry(&theComponent->contextTable,
- contextName)) == NULL ) {
- return TCL_ERROR;
- } else {
- contextStruct = (tclOSAContext *) Tcl_GetHashValue(hashEntry);
- *theContext = contextStruct->contextID;
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tclOSAAddContext --
- *
- * This adds the context ID, with the name contextName. If the
- * name is passed in as a NULL string, space is malloc'ed for the
- * string and a new name is made up, if the string is empty, you
- * must have allocated enough space ( 24 characters is fine) for
- * the name, which is made up and passed out.
- *
- * Results:
- * Nothing
- *
- * Side effects:
- * Adds the script context to the component's context table.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-tclOSAAddContext(
- tclOSAComponent *theComponent,
- char *contextName,
- const OSAID theContext)
-{
- static unsigned short contextIndex = 0;
- tclOSAContext *contextStruct;
- Tcl_HashEntry *hashEntry;
- int newPtr;
-
- if (contextName == NULL) {
- contextName = ckalloc(16 + TCL_INTEGER_SPACE);
- sprintf(contextName, "OSAContext%d", contextIndex++);
- } else if (*contextName == '\0') {
- sprintf(contextName, "OSAContext%d", contextIndex++);
- }
-
- hashEntry = Tcl_CreateHashEntry(&theComponent->contextTable,
- contextName, &newPtr);
-
- contextStruct = (tclOSAContext *) ckalloc(sizeof(tclOSAContext));
- contextStruct->contextID = theContext;
- Tcl_SetHashValue(hashEntry,(ClientData) contextStruct);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tclOSADeleteContext --
- *
- * This deletes the context struct, with the name contextName.
- *
- * Results:
- * A normal Tcl result
- *
- * Side effects:
- * Removes the script context to the component's context table,
- * and deletes the data associated with it.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-tclOSADeleteContext(
- tclOSAComponent *theComponent,
- CONST char *contextName)
-{
- Tcl_HashEntry *hashEntry;
- tclOSAContext *contextStruct;
-
- hashEntry = Tcl_FindHashEntry(&theComponent->contextTable, contextName);
- if (hashEntry == NULL) {
- return TCL_ERROR;
- }
- /*
- * Dispose of the script context data
- */
- contextStruct = (tclOSAContext *) Tcl_GetHashValue(hashEntry);
- OSADispose(theComponent->theComponent,contextStruct->contextID);
- /*
- * Then the hash entry
- */
- ckfree((char *) contextStruct);
- Tcl_DeleteHashEntry(hashEntry);
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tclOSAMakeContext --
- *
- * This makes the context with name contextName, and returns the ID.
- *
- * Results:
- * A standard Tcl result
- *
- * Side effects:
- * Makes a new context, adds it to the context table, and returns
- * the new contextID in the variable theContext.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-tclOSAMakeContext(
- tclOSAComponent *theComponent,
- CONST char *contextName,
- OSAID *theContext)
-{
- AEDesc contextNameDesc = {typeNull, NULL};
- OSAError osaErr = noErr;
-
- AECreateDesc(typeChar, contextName, strlen(contextName), &contextNameDesc);
- osaErr = OSAMakeContext(theComponent->theComponent, &contextNameDesc,
- kOSANullScript, theContext);
-
- AEDisposeDesc(&contextNameDesc);
-
- if (osaErr == noErr) {
- char name[24];
- strncpy(name, contextName, 23);
- name[23] = '\0';
- tclOSAAddContext(theComponent, name, *theContext);
- } else {
- *theContext = (OSAID) osaErr;
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tclOSAStore --
- *
- * This stores a script resource from the file named in fileName.
- *
- * Most of this routine is caged from the Tcl Source, from the
- * Tcl_MacSourceCmd routine. This is good, since it ensures this
- * follows the same convention for looking up files as Tcl.
- *
- * Returns
- * A standard Tcl result.
- *
- * Side Effects:
- * The given script data is stored in the file fileName.
- *
- *----------------------------------------------------------------------
- */
-
-int
-tclOSAStore(
- Tcl_Interp *interp,
- tclOSAComponent *theComponent,
- CONST char *resourceName,
- int resourceNumber,
- CONST char *scriptName,
- CONST char *fileName)
-{
- Handle resHandle;
- Str255 rezName;
- int result = TCL_OK;
- short saveRef, fileRef = -1;
- char idStr[16 + TCL_INTEGER_SPACE];
- FSSpec fileSpec;
- Tcl_DString ds, buffer;
- CONST char *nativeName;
- OSErr myErr = noErr;
- OSAID scriptID;
- Size scriptSize;
- AEDesc scriptData;
-
- /*
- * First extract the script data
- */
-
- if (tclOSAGetScriptID(theComponent, scriptName, &scriptID) != TCL_OK ) {
- if (tclOSAGetContextID(theComponent, scriptName, &scriptID)
- != TCL_OK) {
- Tcl_AppendResult(interp, "Error getting script ",
- scriptName, (char *) NULL);
- return TCL_ERROR;
- }
- }
-
- myErr = OSAStore(theComponent->theComponent, scriptID,
- typeOSAGenericStorage, kOSAModeNull, &scriptData);
- if (myErr != noErr) {
- sprintf(idStr, "%d", myErr);
- Tcl_AppendResult(interp, "Error #", idStr,
- " storing script ", scriptName, (char *) NULL);
- return TCL_ERROR;
- }
-
- /*
- * Now try to open the output file
- */
-
- saveRef = CurResFile();
-
- if (fileName != NULL) {
- OSErr err;
-
- if (Tcl_TranslateFileName(interp, fileName, &buffer) == NULL) {
- return TCL_ERROR;
- }
- nativeName = Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&buffer),
- Tcl_DStringLength(&buffer), &ds);
- err = FSpLocationFromPath(strlen(nativeName), nativeName, &fileSpec);
-
- Tcl_DStringFree(&ds);
- Tcl_DStringFree(&buffer);
- if ((err != noErr) && (err != fnfErr)) {
- Tcl_AppendResult(interp,
- "Error getting a location for the file: \"",
- fileName, "\".", NULL);
- return TCL_ERROR;
- }
-
- FSpCreateResFileCompatTcl(&fileSpec,
- 'WiSH', 'osas', smSystemScript);
- myErr = ResError();
-
- if ((myErr != noErr) && (myErr != dupFNErr)) {
- sprintf(idStr, "%d", myErr);
- Tcl_AppendResult(interp, "Error #", idStr,
- " creating new resource file ", fileName, (char *) NULL);
- result = TCL_ERROR;
- goto rezEvalCleanUp;
- }
-
- fileRef = FSpOpenResFileCompatTcl(&fileSpec, fsRdWrPerm);
- if (fileRef == -1) {
- Tcl_AppendResult(interp, "Error reading the file: \"",
- fileName, "\".", NULL);
- result = TCL_ERROR;
- goto rezEvalCleanUp;
- }
- UseResFile(fileRef);
- } else {
- /*
- * The default behavior will search through all open resource files.
- * This may not be the behavior you desire. If you want the behavior
- * of this call to *only* search the application resource fork, you
- * must call UseResFile at this point to set it to the application
- * file. This means you must have already obtained the application's
- * fileRef when the application started up.
- */
- }
-
- /*
- * Load the resource by name
- */
- if (resourceName != NULL) {
- strcpy((char *) rezName + 1, resourceName);
- rezName[0] = strlen(resourceName);
- resHandle = Get1NamedResource('scpt', rezName);
- myErr = ResError();
- if (resHandle == NULL) {
- /*
- * These signify either the resource or the resource
- * type were not found
- */
- if (myErr == resNotFound || myErr == noErr) {
- short uniqueID;
- while ((uniqueID = Unique1ID('scpt') ) < 128) {}
- AddResource(scriptData.dataHandle, 'scpt', uniqueID, rezName);
- WriteResource(resHandle);
- result = TCL_OK;
- goto rezEvalCleanUp;
- } else {
- /*
- * This means there was some other error, for now
- * I just bag out.
- */
- sprintf(idStr, "%d", myErr);
- Tcl_AppendResult(interp, "Error #", idStr,
- " opening scpt resource named ", resourceName,
- " in file ", fileName, (char *) NULL);
- result = TCL_ERROR;
- goto rezEvalCleanUp;
- }
- }
- /*
- * Or ID
- */
- } else {
- resHandle = Get1Resource('scpt', resourceNumber);
- rezName[0] = 0;
- rezName[1] = '\0';
- myErr = ResError();
- if (resHandle == NULL) {
- /*
- * These signify either the resource or the resource
- * type were not found
- */
- if (myErr == resNotFound || myErr == noErr) {
- AddResource(scriptData.dataHandle, 'scpt',
- resourceNumber, rezName);
- WriteResource(resHandle);
- result = TCL_OK;
- goto rezEvalCleanUp;
- } else {
- /*
- * This means there was some other error, for now
- * I just bag out */
- sprintf(idStr, "%d", myErr);
- Tcl_AppendResult(interp, "Error #", idStr,
- " opening scpt resource named ", resourceName,
- " in file ", fileName,(char *) NULL);
- result = TCL_ERROR;
- goto rezEvalCleanUp;
- }
- }
- }
-
- /*
- * We get to here if the resource exists
- * we just copy into it...
- */
-
- scriptSize = GetHandleSize(scriptData.dataHandle);
- SetHandleSize(resHandle, scriptSize);
- HLock(scriptData.dataHandle);
- HLock(resHandle);
- BlockMove(*scriptData.dataHandle, *resHandle,scriptSize);
- HUnlock(scriptData.dataHandle);
- HUnlock(resHandle);
- ChangedResource(resHandle);
- WriteResource(resHandle);
- result = TCL_OK;
- goto rezEvalCleanUp;
-
- rezEvalError:
- sprintf(idStr, "ID=%d", resourceNumber);
- Tcl_AppendResult(interp, "The resource \"",
- (resourceName != NULL ? resourceName : idStr),
- "\" could not be loaded from ",
- (fileName != NULL ? fileName : "application"),
- ".", NULL);
-
- rezEvalCleanUp:
- if (fileRef != -1) {
- CloseResFile(fileRef);
- }
-
- UseResFile(saveRef);
-
- return result;
-}
-
-/*----------------------------------------------------------------------
- *
- * tclOSALoad --
- *
- * This loads a script resource from the file named in fileName.
- * Most of this routine is caged from the Tcl Source, from the
- * Tcl_MacSourceCmd routine. This is good, since it ensures this
- * follows the same convention for looking up files as Tcl.
- *
- * Returns
- * A standard Tcl result.
- *
- * Side Effects:
- * A new script element is created from the data in the file.
- * The script ID is passed out in the variable resultID.
- *
- *----------------------------------------------------------------------
- */
-
-int
-tclOSALoad(
- Tcl_Interp *interp,
- tclOSAComponent *theComponent,
- CONST char *resourceName,
- int resourceNumber,
- CONST char *fileName,
- OSAID *resultID)
-{
- Handle sourceData;
- Str255 rezName;
- int result = TCL_OK;
- short saveRef, fileRef = -1;
- char idStr[16 + TCL_INTEGER_SPACE];
- FSSpec fileSpec;
- Tcl_DString ds, buffer;
- CONST char *nativeName;
-
- saveRef = CurResFile();
-
- if (fileName != NULL) {
- OSErr err;
-
- if (Tcl_TranslateFileName(interp, fileName, &buffer) == NULL) {
- return TCL_ERROR;
- }
- nativeName = Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&buffer),
- Tcl_DStringLength(&buffer), &ds);
- err = FSpLocationFromPath(strlen(nativeName), nativeName, &fileSpec);
- Tcl_DStringFree(&ds);
- Tcl_DStringFree(&buffer);
- if (err != noErr) {
- Tcl_AppendResult(interp, "Error finding the file: \"",
- fileName, "\".", NULL);
- return TCL_ERROR;
- }
-
- fileRef = FSpOpenResFileCompatTcl(&fileSpec, fsRdPerm);
- if (fileRef == -1) {
- Tcl_AppendResult(interp, "Error reading the file: \"",
- fileName, "\".", NULL);
- return TCL_ERROR;
- }
- UseResFile(fileRef);
- } else {
- /*
- * The default behavior will search through all open resource files.
- * This may not be the behavior you desire. If you want the behavior
- * of this call to *only* search the application resource fork, you
- * must call UseResFile at this point to set it to the application
- * file. This means you must have already obtained the application's
- * fileRef when the application started up.
- */
- }
-
- /*
- * Load the resource by name or ID
- */
- if (resourceName != NULL) {
- strcpy((char *) rezName + 1, resourceName);
- rezName[0] = strlen(resourceName);
- sourceData = GetNamedResource('scpt', rezName);
- } else {
- sourceData = GetResource('scpt', (short) resourceNumber);
- }
-
- if (sourceData == NULL) {
- result = TCL_ERROR;
- } else {
- AEDesc scriptDesc;
- OSAError osaErr;
-
- scriptDesc.descriptorType = typeOSAGenericStorage;
- scriptDesc.dataHandle = sourceData;
-
- osaErr = OSALoad(theComponent->theComponent, &scriptDesc,
- kOSAModeNull, resultID);
-
- ReleaseResource(sourceData);
-
- if (osaErr != noErr) {
- result = TCL_ERROR;
- goto rezEvalError;
- }
-
- goto rezEvalCleanUp;
- }
-
- rezEvalError:
- sprintf(idStr, "ID=%d", resourceNumber);
- Tcl_AppendResult(interp, "The resource \"",
- (resourceName != NULL ? resourceName : idStr),
- "\" could not be loaded from ",
- (fileName != NULL ? fileName : "application"),
- ".", NULL);
-
- rezEvalCleanUp:
- if (fileRef != -1) {
- CloseResFile(fileRef);
- }
-
- UseResFile(saveRef);
-
- return result;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tclOSAGetScriptID --
- *
- * This returns the context ID, gibven the component name.
- *
- * Results:
- * A standard Tcl result
- *
- * Side effects:
- * Passes out the script ID in the variable scriptID.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-tclOSAGetScriptID(
- tclOSAComponent *theComponent,
- CONST char *scriptName,
- OSAID *scriptID)
-{
- tclOSAScript *theScript;
-
- theScript = tclOSAGetScript(theComponent, scriptName);
- if (theScript == NULL) {
- return TCL_ERROR;
- }
-
- *scriptID = theScript->scriptID;
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tclOSAAddScript --
- *
- * This adds a script to theComponent's script table, with the
- * given name & ID.
- *
- * Results:
- * A standard Tcl result
- *
- * Side effects:
- * Adds an element to the component's script table.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-tclOSAAddScript(
- tclOSAComponent *theComponent,
- char *scriptName,
- long modeFlags,
- OSAID scriptID)
-{
- Tcl_HashEntry *hashEntry;
- int newPtr;
- static int scriptIndex = 0;
- tclOSAScript *theScript;
-
- if (*scriptName == '\0') {
- sprintf(scriptName, "OSAScript%d", scriptIndex++);
- }
-
- hashEntry = Tcl_CreateHashEntry(&theComponent->scriptTable,
- scriptName, &newPtr);
- if (newPtr == 0) {
- theScript = (tclOSAScript *) Tcl_GetHashValue(hashEntry);
- OSADispose(theComponent->theComponent, theScript->scriptID);
- } else {
- theScript = (tclOSAScript *) ckalloc(sizeof(tclOSAScript));
- if (theScript == NULL) {
- return TCL_ERROR;
- }
- }
-
- theScript->scriptID = scriptID;
- theScript->languageID = theComponent->languageID;
- theScript->modeFlags = modeFlags;
-
- Tcl_SetHashValue(hashEntry,(ClientData) theScript);
-
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tclOSAGetScriptID --
- *
- * This returns the script structure, given the component and script name.
- *
- * Results:
- * A pointer to the script structure.
- *
- * Side effects:
- * None
- *
- *----------------------------------------------------------------------
- */
-
-static tclOSAScript *
-tclOSAGetScript(
- tclOSAComponent *theComponent,
- CONST char *scriptName)
-{
- Tcl_HashEntry *hashEntry;
-
- hashEntry = Tcl_FindHashEntry(&theComponent->scriptTable, scriptName);
- if (hashEntry == NULL) {
- return NULL;
- }
-
- return (tclOSAScript *) Tcl_GetHashValue(hashEntry);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tclOSADeleteScript --
- *
- * This deletes the script given by scriptName.
- *
- * Results:
- * A standard Tcl result
- *
- * Side effects:
- * Deletes the script from the script table, and frees up the
- * resources associated with it. If there is an error, then
- * space for the error message is malloc'ed, and passed out in
- * the variable errMsg.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-tclOSADeleteScript(
- tclOSAComponent *theComponent,
- CONST char *scriptName,
- char *errMsg)
-{
- Tcl_HashEntry *hashEntry;
- tclOSAScript *scriptPtr;
-
- hashEntry = Tcl_FindHashEntry(&theComponent->scriptTable, scriptName);
- if (hashEntry == NULL) {
- errMsg = ckalloc(17);
- strcpy(errMsg,"Script not found");
- return TCL_ERROR;
- }
-
- scriptPtr = (tclOSAScript *) Tcl_GetHashValue(hashEntry);
- OSADispose(theComponent->theComponent, scriptPtr->scriptID);
- ckfree((char *) scriptPtr);
- Tcl_DeleteHashEntry(hashEntry);
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclOSAActiveProc --
- *
- * This is passed to each component. It is run periodically
- * during script compilation and script execution. It in turn
- * calls Tcl_DoOneEvent to process the event queue. We also call
- * the default Active proc which will let the user cancel the script
- * by hitting Command-.
- *
- * Results:
- * A standard MacOS system error
- *
- * Side effects:
- * Any Tcl code may run while calling Tcl_DoOneEvent.
- *
- *----------------------------------------------------------------------
- */
-
-static pascal OSErr
-TclOSAActiveProc(
- long refCon)
-{
- tclOSAComponent *theComponent = (tclOSAComponent *) refCon;
-
- Tcl_DoOneEvent(TCL_DONT_WAIT);
- InvokeOSAActiveUPP(theComponent->defRefCon, theComponent->defActiveProc);
-
- return noErr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ASCIICompareProc --
- *
- * Trivial ascii compare for use with qsort.
- *
- * Results:
- * strcmp of the two input strings
- *
- * Side effects:
- * None
- *
- *----------------------------------------------------------------------
- */
-static int
-ASCIICompareProc(const void *first,const void *second)
-{
- int order;
-
- char *firstString = *((char **) first);
- char *secondString = *((char **) second);
-
- order = strcmp(firstString, secondString);
-
- return order;
-}
-
-#define REALLOC_INCR 30
-/*
- *----------------------------------------------------------------------
- *
- * getSortedHashKeys --
- *
- * returns an alphabetically sorted list of the keys of the hash
- * theTable which match the string "pattern" in the DString
- * theResult. pattern == NULL matches all.
- *
- * Results:
- * None
- *
- * Side effects:
- * ReInitializes the DString theResult, then copies the names of
- * the matching keys into the string as list elements.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-getSortedHashKeys(
- Tcl_HashTable *theTable,
- CONST char *pattern,
- Tcl_DString *theResult)
-{
- Tcl_HashSearch search;
- Tcl_HashEntry *hPtr;
- Boolean compare = true;
- char *keyPtr;
- static char **resultArgv = NULL;
- static int totSize = 0;
- int totElem = 0, i;
-
- if (pattern == NULL || *pattern == '\0' ||
- (*pattern == '*' && *(pattern + 1) == '\0')) {
- compare = false;
- }
-
- for (hPtr = Tcl_FirstHashEntry(theTable,&search), totElem = 0;
- hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
-
- keyPtr = (char *) Tcl_GetHashKey(theTable, hPtr);
- if (!compare || Tcl_StringMatch(keyPtr, pattern)) {
- totElem++;
- if (totElem >= totSize) {
- totSize += REALLOC_INCR;
- resultArgv = (char **) ckrealloc((char *) resultArgv,
- totSize * sizeof(char *));
- }
- resultArgv[totElem - 1] = keyPtr;
- }
- }
-
- Tcl_DStringInit(theResult);
- if (totElem == 1) {
- Tcl_DStringAppendElement(theResult, resultArgv[0]);
- } else if (totElem > 1) {
- qsort((VOID *) resultArgv, (size_t) totElem, sizeof (char *),
- ASCIICompareProc);
-
- for (i = 0; i < totElem; i++) {
- Tcl_DStringAppendElement(theResult, resultArgv[i]);
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * prepareScriptData --
- *
- * Massages the input data in the argv array, concating the
- * elements, with a " " between each, and replacing \n with \r,
- * and \\n with " ". Puts the result in the the DString scrptData,
- * and copies the result to the AEdesc scrptDesc.
- *
- * Results:
- * Standard Tcl result
- *
- * Side effects:
- * Creates a new Handle (with AECreateDesc) for the script data.
- * Stores the script in scrptData, or the error message if there
- * is an error creating the descriptor.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-prepareScriptData(
- int argc,
- CONST char **argv,
- Tcl_DString *scrptData,
- AEDesc *scrptDesc)
-{
- char * ptr;
- int i;
- char buffer[7];
- OSErr sysErr = noErr;
- Tcl_DString encodedText;
-
- Tcl_DStringInit(scrptData);
-
- for (i = 0; i < argc; i++) {
- Tcl_DStringAppend(scrptData, argv[i], -1);
- Tcl_DStringAppend(scrptData, " ", 1);
- }
-
- /*
- * First replace the \n's with \r's in the script argument
- * Also replace "\\n" with " ".
- */
-
- for (ptr = scrptData->string; *ptr != '\0'; ptr++) {
- if (*ptr == '\n') {
- *ptr = '\r';
- } else if (*ptr == '\\') {
- if (*(ptr + 1) == '\n') {
- *ptr = ' ';
- *(ptr + 1) = ' ';
- }
- }
- }
-
- Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(scrptData),
- Tcl_DStringLength(scrptData), &encodedText);
- sysErr = AECreateDesc(typeChar, Tcl_DStringValue(&encodedText),
- Tcl_DStringLength(&encodedText), scrptDesc);
- Tcl_DStringFree(&encodedText);
-
- if (sysErr != noErr) {
- sprintf(buffer, "%6d", sysErr);
- Tcl_DStringFree(scrptData);
- Tcl_DStringAppend(scrptData, "Error #", 7);
- Tcl_DStringAppend(scrptData, buffer, -1);
- Tcl_DStringAppend(scrptData, " creating Script Data Descriptor.", 33);
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tclOSAResultFromID --
- *
- * Gets a human readable version of the result from the script ID
- * and returns it in the result of the interpreter interp
- *
- * Results:
- * None
- *
- * Side effects:
- * Sets the result of interp to the human readable version of resultID.
- *
- *
- *----------------------------------------------------------------------
- */
-
-void
-tclOSAResultFromID(
- Tcl_Interp *interp,
- ComponentInstance theComponent,
- OSAID resultID )
-{
- OSErr myErr = noErr;
- AEDesc resultDesc;
- Tcl_DString resultStr;
-
- Tcl_DStringInit(&resultStr);
-
- myErr = OSADisplay(theComponent, resultID, typeChar,
- kOSAModeNull, &resultDesc);
- Tcl_DStringAppend(&resultStr, (char *) *resultDesc.dataHandle,
- GetHandleSize(resultDesc.dataHandle));
- Tcl_DStringResult(interp,&resultStr);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * tclOSAASError --
- *
- * Gets the error message from the AppleScript component, and adds
- * it to interp's result. If the script data is known, will point
- * out the offending bit of code. This MUST BE A NULL TERMINATED
- * C-STRING, not a typeChar.
- *
- * Results:
- * None
- *
- * Side effects:
- * Sets the result of interp to error, plus the relevant portion
- * of the script.
- *
- *----------------------------------------------------------------------
- */
-
-void
-tclOSAASError(
- Tcl_Interp * interp,
- ComponentInstance theComponent,
- char *scriptData )
-{
- OSErr myErr = noErr;
- AEDesc errResult,errLimits;
- Tcl_DString errStr;
- DescType returnType;
- Size returnSize;
- short srcStart,srcEnd;
- char buffer[16];
-
- Tcl_DStringInit(&errStr);
- Tcl_DStringAppend(&errStr, "An AppleScript error was encountered.\n", -1);
-
- OSAScriptError(theComponent, kOSAErrorNumber,
- typeShortInteger, &errResult);
-
- sprintf(buffer, "Error #%-6.6d\n", (short int) **errResult.dataHandle);
-
- AEDisposeDesc(&errResult);
-
- Tcl_DStringAppend(&errStr,buffer, 15);
-
- OSAScriptError(theComponent, kOSAErrorMessage, typeChar, &errResult);
- Tcl_DStringAppend(&errStr, (char *) *errResult.dataHandle,
- GetHandleSize(errResult.dataHandle));
- AEDisposeDesc(&errResult);
-
- if (scriptData != NULL) {
- int lowerB, upperB;
-
- myErr = OSAScriptError(theComponent, kOSAErrorRange,
- typeOSAErrorRange, &errResult);
-
- myErr = AECoerceDesc(&errResult, typeAERecord, &errLimits);
- myErr = AEGetKeyPtr(&errLimits, keyOSASourceStart,
- typeShortInteger, &returnType, &srcStart,
- sizeof(short int), &returnSize);
- myErr = AEGetKeyPtr(&errLimits, keyOSASourceEnd, typeShortInteger,
- &returnType, &srcEnd, sizeof(short int), &returnSize);
- AEDisposeDesc(&errResult);
- AEDisposeDesc(&errLimits);
-
- Tcl_DStringAppend(&errStr, "\nThe offending bit of code was:\n\t", -1);
- /*
- * Get the full line on which the error occured:
- */
- for (lowerB = srcStart; lowerB > 0; lowerB--) {
- if (*(scriptData + lowerB ) == '\r') {
- lowerB++;
- break;
- }
- }
-
- for (upperB = srcEnd; *(scriptData + upperB) != '\0'; upperB++) {
- if (*(scriptData + upperB) == '\r') {
- break;
- }
- }
-
- Tcl_DStringAppend(&errStr, scriptData+lowerB, srcStart - lowerB);
- Tcl_DStringAppend(&errStr, "_", 1);
- Tcl_DStringAppend(&errStr, scriptData+srcStart, upperB - srcStart);
- }
-
- Tcl_DStringResult(interp,&errStr);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * GetRawDataFromDescriptor --
- *
- * Get the data from a descriptor.
- *
- * Results:
- * None
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-GetRawDataFromDescriptor(
- AEDesc *theDesc,
- Ptr destPtr,
- Size destMaxSize,
- Size *actSize)
- {
- Size copySize;
-
- if (theDesc->dataHandle) {
- HLock((Handle)theDesc->dataHandle);
- *actSize = GetHandleSize((Handle)theDesc->dataHandle);
- copySize = *actSize < destMaxSize ? *actSize : destMaxSize;
- BlockMove(*theDesc->dataHandle, destPtr, copySize);
- HUnlock((Handle)theDesc->dataHandle);
- } else {
- *actSize = 0;
- }
-
- }
-
-/*
- *----------------------------------------------------------------------
- *
- * GetRawDataFromDescriptor --
- *
- * Get the data from a descriptor. Assume it's a C string.
- *
- * Results:
- * None
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static OSErr
-GetCStringFromDescriptor(
- AEDesc *sourceDesc,
- char *resultStr,
- Size resultMaxSize,
- Size *resultSize)
-{
- OSErr err;
- AEDesc resultDesc;
-
- resultDesc.dataHandle = nil;
-
- err = AECoerceDesc(sourceDesc, typeChar, &resultDesc);
-
- if (!err) {
- GetRawDataFromDescriptor(&resultDesc, (Ptr) resultStr,
- resultMaxSize - 1, resultSize);
- resultStr[*resultSize] = 0;
- } else {
- err = errAECoercionFail;
- }
-
- if (resultDesc.dataHandle) {
- AEDisposeDesc(&resultDesc);
- }
-
- return err;
-}
diff --git a/mac/tclMacOSA.r b/mac/tclMacOSA.r
deleted file mode 100644
index bcb2a94..0000000
--- a/mac/tclMacOSA.r
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * tkMacOSA.r --
- *
- * This file creates resources used by the AppleScript package.
- *
- * Copyright (c) 1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include <Types.r>
-#include <SysTypes.r>
-
-/*
- * The folowing include and defines help construct
- * the version string for Tcl.
- */
-
-#define SCRIPT_MAJOR_VERSION 1 /* Major number */
-#define SCRIPT_MINOR_VERSION 1 /* Minor number */
-#define SCRIPT_RELEASE_SERIAL 0 /* Really minor number! */
-#define RELEASE_LEVEL final /* alpha, beta, or final */
-#define SCRIPT_VERSION "1.1"
-#define SCRIPT_PATCH_LEVEL "1.1.0"
-#define FINAL 1 /* Change to 1 if final version. */
-
-#if FINAL
-# define MINOR_VERSION (SCRIPT_MINOR_VERSION * 16) + SCRIPT_RELEASE_SERIAL
-# define RELEASE_CODE 0x00
-#else
-# define MINOR_VERSION SCRIPT_MINOR_VERSION * 16
-# define RELEASE_CODE SCRIPT_RELEASE_SERIAL
-#endif
-
-#define RELEASE_CODE 0x00
-
-resource 'vers' (1) {
- SCRIPT_MAJOR_VERSION, MINOR_VERSION,
- RELEASE_LEVEL, RELEASE_CODE, verUS,
- SCRIPT_PATCH_LEVEL,
- SCRIPT_PATCH_LEVEL ", by Jim Ingham © Cygnus Solutions" "\n" "© 2001 Tcl Core Team"
-};
-
-resource 'vers' (2) {
- SCRIPT_MAJOR_VERSION, MINOR_VERSION,
- RELEASE_LEVEL, RELEASE_CODE, verUS,
- SCRIPT_PATCH_LEVEL,
- "Tclapplescript " SCRIPT_PATCH_LEVEL " © 1996-2001"
-};
-
-/*
- * The -16397 string will be displayed by Finder when a user
- * tries to open the shared library. The string should
- * give the user a little detail about the library's capabilities
- * and enough information to install the library in the correct location.
- * A similar string should be placed in all shared libraries.
- */
-resource 'STR ' (-16397, purgeable) {
- "TclAppleScript Library\n\n"
- "This library provides the ability to run AppleScript "
- " commands from Tcl/Tk programs. To work properly, it "
- "should be placed in the ŒTool Command Language¹ folder "
- "within the Extensions folder."
-};
-
-
-/*
- * We now load the Tk library into the resource fork of the library.
- */
-
-data 'TEXT' (4000,"pkgIndex",purgeable, preload) {
- "# Tcl package index file, version 1.0\n"
- "package ifneeded Tclapplescript 1.1 [list tclPkgSetup $dir Tclapplescript 1.1 {{Tclapplescript"
- ".shlb load AppleScript}}]\n"
-};
diff --git a/mac/tclMacPanic.c b/mac/tclMacPanic.c
deleted file mode 100644
index f39c4ea..0000000
--- a/mac/tclMacPanic.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * tclMacPanic.c --
- *
- * Source code for the "Tcl_Panic" library procedure used in "Simple
- * Shell"; other Mac applications will probably call Tcl_SetPanicProc
- * to set a more robust application-specific panic procedure.
- *
- * Copyright (c) 1993-1994 Lockheed Missle & Space Company, AI Center
- * Copyright (c) 1995-1996 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-
-#include <Events.h>
-#include <Controls.h>
-#include <ControlDefinitions.h>
-#include <Windows.h>
-#include <TextEdit.h>
-#include <Fonts.h>
-#include <Dialogs.h>
-#include <Icons.h>
-#include <Sound.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "tclInt.h"
-#include "tclMacInt.h"
-
-/*
- * constants for panic dialog
- */
-#define PANICHEIGHT 150 /* Height of dialog */
-#define PANICWIDTH 350 /* Width of dialog */
-#define PANIC_BUTTON_RECT {125, 260, 145, 335} /* Rect for button. */
-#define PANIC_ICON_RECT {10, 20, 42, 52} /* Rect for icon. */
-#define PANIC_TEXT_RECT {10, 65, 140, 330} /* Rect for text. */
-#define ENTERCODE (0x03)
-#define RETURNCODE (0x0D)
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpPanic --
- *
- * Displays panic info, then aborts
- *
- * Results:
- * None.
- *
- * Side effects:
- * The process dies, entering the debugger if possible.
- *
- *----------------------------------------------------------------------
- */
-
- /* VARARGS ARGSUSED */
-void
-TclpPanic TCL_VARARGS_DEF(CONST char *, format)
-{
- va_list varg;
- char msg[256];
- WindowRef macWinPtr, foundWinPtr;
- Rect macRect;
- Rect buttonRect = PANIC_BUTTON_RECT;
- Rect iconRect = PANIC_ICON_RECT;
- Rect textRect = PANIC_TEXT_RECT;
- ControlHandle okButtonHandle;
- EventRecord event;
- Handle stopIconHandle;
- int part;
- Boolean done = false;
-
- va_start(varg, format);
- vsprintf(msg, format, varg);
- va_end(varg);
-
- /*
- * Put up an alert without using the Resource Manager (there may
- * be no resources to load). Use the Window and Control Managers instead.
- * We want the window centered on the main monitor. The following
- * should be tested with multiple monitors. Look and see if there is a way
- * not using qd.screenBits.
- */
-
- macRect.top = (qd.screenBits.bounds.top + qd.screenBits.bounds.bottom)
- / 2 - (PANICHEIGHT / 2);
- macRect.bottom = (qd.screenBits.bounds.top + qd.screenBits.bounds.bottom)
- / 2 + (PANICHEIGHT / 2);
- macRect.left = (qd.screenBits.bounds.left + qd.screenBits.bounds.right)
- / 2 - (PANICWIDTH / 2);
- macRect.right = (qd.screenBits.bounds.left + qd.screenBits.bounds.right)
- / 2 + (PANICWIDTH / 2);
-
- macWinPtr = NewWindow(NULL, &macRect, "\p", true, dBoxProc, (WindowRef) -1,
- false, 0);
- if (macWinPtr == NULL) {
- goto exitNow;
- }
-
- okButtonHandle = NewControl(macWinPtr, &buttonRect, "\pOK", true,
- 0, 0, 1, pushButProc, 0);
- if (okButtonHandle == NULL) {
- CloseWindow(macWinPtr);
- goto exitNow;
- }
-
- SelectWindow(macWinPtr);
- SetCursor(&qd.arrow);
- stopIconHandle = GetIcon(kStopIcon);
-
- while (!done) {
- if (WaitNextEvent(mDownMask | keyDownMask | updateMask,
- &event, 0, NULL)) {
- switch(event.what) {
- case mouseDown:
- part = FindWindow(event.where, &foundWinPtr);
-
- if ((foundWinPtr != macWinPtr) || (part != inContent)) {
- SysBeep(1);
- } else {
- SetPortWindowPort(macWinPtr);
- GlobalToLocal(&event.where);
- part = FindControl(event.where, macWinPtr,
- &okButtonHandle);
-
- if ((kControlButtonPart == part) &&
- (TrackControl(okButtonHandle,
- event.where, NULL))) {
- done = true;
- }
- }
- break;
- case keyDown:
- switch (event.message & charCodeMask) {
- case ENTERCODE:
- case RETURNCODE:
- HiliteControl(okButtonHandle, 1);
- HiliteControl(okButtonHandle, 0);
- done = true;
- }
- break;
- case updateEvt:
- SetPortWindowPort(macWinPtr);
- TextFont(systemFont);
-
- BeginUpdate(macWinPtr);
- if (stopIconHandle != NULL) {
- PlotIcon(&iconRect, stopIconHandle);
- }
- TETextBox(msg, strlen(msg), &textRect, teFlushDefault);
- DrawControls(macWinPtr);
- EndUpdate(macWinPtr);
- }
- }
- }
-
- CloseWindow(macWinPtr);
-
- exitNow:
-#ifdef TCL_DEBUG
- Debugger();
-#else
- abort();
-#endif
-}
-
diff --git a/mac/tclMacPort.h b/mac/tclMacPort.h
deleted file mode 100644
index f427899..0000000
--- a/mac/tclMacPort.h
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * tclMacPort.h --
- *
- * This header file handles porting issues that occur because of
- * differences between the Mac and Unix. It should be the only
- * file that contains #ifdefs to handle different flavors of OS.
- *
- * Copyright (c) 1995-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-
-#ifndef _MACPORT
-#define _MACPORT
-
-#ifndef _TCLINT
-# include "tclInt.h"
-#endif
-
-/*
- *---------------------------------------------------------------------------
- * The following sets of #includes and #ifdefs are required to get Tcl to
- * compile on the macintosh.
- *---------------------------------------------------------------------------
- */
-
-#include "tclErrno.h"
-
-#ifndef EOVERFLOW
-# ifdef EFBIG
-# define EOVERFLOW EFBIG /* The object couldn't fit in the datatype */
-# else /* !EFBIG */
-# define EOVERFLOW EINVAL /* Better than nothing! */
-# endif /* EFBIG */
-#endif /* !EOVERFLOW */
-
-#include <float.h>
-
-#ifdef THINK_C
- /*
- * The Symantic C code has not been tested
- * and probably will not work.
- */
-# include <pascal.h>
-# include <posix.h>
-# include <string.h>
-# include <fcntl.h>
-# include <pwd.h>
-# include <sys/param.h>
-# include <sys/types.h>
-# include <sys/stat.h>
-# include <unistd.h>
-#elif defined(__MWERKS__)
-# include <time.h>
-# include <unistd.h>
-# include <utime.h>
-# include <fcntl.h>
-# include <stat.h>
-
-#if __MSL__ < 0x6000
-# define isatty(arg) 1
-
-/*
- * Defines used by access function. This function is provided
- * by Mac Tcl as the function TclpAccess.
- */
-
-# define F_OK 0 /* test for existence of file */
-# define X_OK 0x01 /* test for execute or search permission */
-# define W_OK 0x02 /* test for write permission */
-# define R_OK 0x04 /* test for read permission */
-#endif
-
-#endif /* __MWERKS__ */
-
-#if defined(S_IFBLK) && !defined(S_ISLNK)
-#define S_ISLNK(m) (((m)&(S_IFMT)) == (S_IFLNK))
-#endif
-
-/*
- * Many signals are not supported on the Mac and are thus not defined in
- * <signal.h>. They are defined here so that Tcl will compile with less
- * modification.
- */
-
-#ifndef SIGQUIT
-#define SIGQUIT 300
-#endif
-
-#ifndef SIGPIPE
-#define SIGPIPE 13
-#endif
-
-#ifndef SIGHUP
-#define SIGHUP 100
-#endif
-
-/*
- * waitpid doesn't work on a Mac - the following makes
- * Tcl compile without errors. These would normally
- * be defined in sys/wait.h on UNIX systems.
- */
-
-#define WAIT_STATUS_TYPE int
-#define WNOHANG 1
-#define WIFSTOPPED(stat) (1)
-#define WIFSIGNALED(stat) (1)
-#define WIFEXITED(stat) (1)
-#define WIFSTOPSIG(stat) (1)
-#define WIFTERMSIG(stat) (1)
-#define WIFEXITSTATUS(stat) (1)
-#define WEXITSTATUS(stat) (1)
-#define WTERMSIG(status) (1)
-#define WSTOPSIG(status) (1)
-
-#ifdef BUILD_tcl
-# undef TCL_STORAGE_CLASS
-# define TCL_STORAGE_CLASS DLLEXPORT
-#endif
-
-/*
- * Make sure that MAXPATHLEN is defined.
- */
-
-#ifndef MAXPATHLEN
-# ifdef PATH_MAX
-# define MAXPATHLEN PATH_MAX
-# else
-# define MAXPATHLEN 2048
-# endif
-#endif
-
-/*
- * Define "NBBY" (number of bits per byte) if it's not already defined.
- */
-
-#ifndef NBBY
-# define NBBY 8
-#endif
-
-/*
- * These functions always return dummy values on Mac.
- */
-#ifndef geteuid
-# define geteuid() 1
-#endif
-#ifndef getpid
-# define getpid() -1
-#endif
-
-/*
- * Variables provided by the C library.
- */
-
-extern char **environ;
-
-/*
- *---------------------------------------------------------------------------
- * The following macros and declarations represent the interface between
- * generic and mac-specific parts of Tcl. Some of the macros may override
- * functions declared in tclInt.h.
- *---------------------------------------------------------------------------
- */
-
-/*
- * The default platform eol translation on Mac is TCL_TRANSLATE_CR:
- */
-
-#define TCL_PLATFORM_TRANSLATION TCL_TRANSLATE_CR
-
-/*
- * Declare dynamic loading extension macro.
- */
-
-#define TCL_SHLIB_EXT ".shlb"
-
-/*
- * The following define is defined as a workaround on the mac. It claims that
- * struct tm has the timezone string in it, which is not true. However,
- * the code that works around this fact does not compile on the Mac, since
- * it relies on the fact that time.h has a "timezone" variable, which the
- * Metrowerks time.h does not have...
- *
- * The Mac timezone stuff is implemented via the TclpGetTZName() routine in
- * tclMacTime.c
- *
- */
-
-#define HAVE_TM_ZONE
-
-
-/*
- * If we're using the Metrowerks MSL, we need to convert time_t values from
- * the mac epoch to the msl epoch (== unix epoch) by adding the offset from
- * <time.mac.h> to mac time_t values, as MSL is using its epoch for file
- * access routines such as stat or utime
- */
-
-#ifdef __MSL__
-#include <time.mac.h>
-#ifdef _mac_msl_epoch_offset_
-#define tcl_mac_epoch_offset _mac_msl_epoch_offset_
-#define TCL_MAC_USE_MSL_EPOCH /* flag for TclDate.c */
-#else
-#define tcl_mac_epoch_offset 0L
-#endif
-#else
-#define tcl_mac_epoch_offset 0L
-#endif
-
-/*
- * The following macros have trivial definitions, allowing generic code to
- * address platform-specific issues.
- */
-
-#define TclpGetPid(pid) ((unsigned long) (pid))
-#define TclSetSystemEnv(a,b)
-#define tzset()
-
-char *TclpFindExecutable(const char *argv0);
-int TclpFindVariable(CONST char *name, int *lengthPtr);
-
-#define fopen(path, mode) TclMacFOpenHack(path, mode)
-#define readlink(fileName, buffer, size) TclMacReadlink(fileName, buffer, size)
-#ifdef TCL_TEST
-#define chmod(path, mode) TclMacChmod(path, mode)
-#endif
-
-/*
- * Prototypes needed for compatability
- */
-
-/* EXTERN int strncasecmp _ANSI_ARGS_((CONST char *s1,
- CONST char *s2, size_t n)); */
-
-/*
- * These definitions force putenv & company to use the version
- * supplied with Tcl.
- */
-#ifndef putenv
-# define unsetenv TclUnsetEnv
-# define putenv Tcl_PutEnv
-# define setenv TclSetEnv
-void TclSetEnv(CONST char *name, CONST char *value);
-/* int Tcl_PutEnv(CONST char *string); */
-void TclUnsetEnv(CONST char *name);
-#endif
-
-/*
- * Platform specific mutex definition used by memory allocators.
- * These are all no-ops on the Macintosh, since the threads are
- * all cooperative.
- */
-
-#ifdef TCL_THREADS
-typedef int TclpMutex;
-#define TclpMutexInit(a)
-#define TclpMutexLock(a)
-#define TclpMutexUnlock(a)
-#else
-typedef int TclpMutex;
-#define TclpMutexInit(a)
-#define TclpMutexLock(a)
-#define TclpMutexUnlock(a)
-#endif /* TCL_THREADS */
-
-typedef pascal void (*ExitToShellProcPtr)(void);
-
-#include "tclMac.h" // contains #include "tclPlatDecls.h"
-#include "tclIntPlatDecls.h"
-
-# undef TCL_STORAGE_CLASS
-# define TCL_STORAGE_CLASS DLLIMPORT
-
-#endif /* _MACPORT */
diff --git a/mac/tclMacProjects.sea.hqx b/mac/tclMacProjects.sea.hqx
deleted file mode 100644
index 178f9d6..0000000
--- a/mac/tclMacProjects.sea.hqx
+++ /dev/null
@@ -1,3759 +0,0 @@
-(This file must be converted with BinHex 4.0)
-:%R4ME%eKBe"bEfTPBh4c,R0PB3""8&"-BA9cG#!!!!%Z[J!"NlA,LP0dG@CQ5A3
-J+'-T-6Nj0bda16Ni)%&XB@4ND@iJ8hPcG'9YFb`J5@jM,L`JD(4dF$S[,hH3!bj
-KE'&NC'PZFhPc,Q0[E5p6G(9QCNPd,`d+'J!&%!!",Vi!N!0b!!%!N!0bca`0TD9
-5CA0PFRCPC+@P!+@3"!%!!$i!4,GD)G+jbMBk!*!0$Jc@!*!$e!!Q*!F!!5hU!!*
-dBfa0B@03FQpUC@0dF`!!#f3#@3&G![-$"J(!rj!%!Klrq2r`bd!!!)!!N!3",JZ
-PN!3"!!!i!%5fm8lcY[&2-`#3!h)!!5fN!*!$FJ!)#A-!!!%`!#BL)3!",(3!!Ld
-q)%*eD@aN!!!A8J"&!#)"8`*#!F$rN!3$([rirr$,4!!!J!#3"k@3"!%!!$B!4,3
-GFA1i)pb!!*!$e!!",)d!N!28!!CX5!!!!BS!*L!l!!%V!`!),6iJG'0X!!#-6J"
-p!"!"f3(d!F$rN!3#([rirr$,3!!!J!#3"k@3"!%!!%!!J,B'`L+hF!IL!!!"-!!
-!)5`!!!%`!"#N(J!#@aS!!"mq!*!%$`"#6d&I9'0X8fKPE'ac,Xq!!!"!XNe08(*
-$9dP&!3$rN!3!N!U!F!#3"N,"e'PFK"b(4aK@[R1qJ(P@i%H83GqET6BT*14UHT,
-eK$hlfi9(H0B6dI!$U#L1N8h0Cq2k3TGqDC@Vm@q&Q`J@9lZrhZCT8r+TZ$)k8++
-`8fpXhmSZf!"JIDUP)VGk*fJIQeXaYV@6!j!!8jZi&[XVa+YZ4J!'$$#05VZ6LBN
-H%K++"cX0PA2T`+8mhb"PQqPfA-PJN!#P,fj)deA`mk95kQPPLSmUV*&SQfY6VS9
-+[h9UI2`FS"#!A#9'H'3E"PX[YZR"kNXXmL6'lU[,'Pb9M!+dP0,06aAeV!lIhTT
-+G0K+l0RbT6mX(&T'mabLP"a2NrJ*qG`+IS*'mKCHZY*5NQ+PEIE"&E1`,F*H0VJ
-(ZB(BYiLJmIJDpU*#meb#JPqY!1q)-RE&EB&8#2YD$k'@eV119U'f6HR%q%B&KVZ
-+Xh#p99K4kd'DkQ!6-jIVe6qH@U)JNYGb0TBUGXF4b*T@S*!!ec@'8C3cS8cSXP%
-V'NDMlL!B@G'%1(5*4l)pKZ3S&lCArdL%*&6H6pVcd'"j-$L*Hh#RlGaLJe@#YQ)
-iq'Q)J5JdA*+e0ljlXI)3KVmY8i2FB6MBrPq(M#[qjC+%3DL9E$2)K90Qr20HB53
-cjUQjK2'"jSCpme@6YT*@0(Q,+P1hEZ3b1@ZjcDB60jph83pRb5X%Sk@fQJV@Z2i
-K&)$`9$+8Y"TDdef4l30NZU@ZUAY&C)Urhd"%ff&(P`-JEBT-fbqDP%@VHGNFFR'
-L*Blb4R0GQV9BjQ'pYTf2UZ#%fM063U0PQGdLrl1Qrc108I,)#!pCjX([LC!!fCp
-[8+4QR@Z0(P3SjDmGN`b(RMDR-f*dX(96bf0V&U*)+C+9'ljS'&c#rp-*)B2AmeZ
-E&1!39hic*VHTLp[bY5XjZ%-PCE)V8*Qi#EMB#LNYBJr'&XhKrVrNQK!c$+k&KUA
-keiV"cKUC[kL1pAAhL2d0&AUQNV'imp#25d1K4Sm@imRTD[RB2XfiFJ(`@'CrKEY
-$4eKCJ!A%kmj`#L)*jR6)*15r8&&S@+FX-jPF-kl(SrhD'G2)bYIrj*0SlJMZGYK
-ZpFd$j*T#`0beN!"mhRqZh6,T2q"hI@f3!+"(,SCA0%pSU2c@#EYS@0Thh9Bml"5
-l4k5$eA-RqfHqU!plEV"[pGQ"H98*rBLXEe)NjDJ"+d3TlbN3,Z0Pdh!V-HEib4C
-#TKZ05*KJhEaM,(`,V$&0N!$!YJlr22fi"VE'[-LeTF9E51c91,G4mBSH(U4+fE3
-j#QJNH[YPVMm"G-c5A&kFfE(CPDHVfB"-`1N19a#`-h4-3F!)Br'[Gm6K*ak8LEi
-@!K8bjB1*iQ!2KJNIj*YLZ!hRP"dZemV-c"#fj&h+%-)FTU&Z-RLl4ZF0,[IXX9I
-RJ,qPYL0kS5`JfSqUJ@Ad[1HKYiLGh*Lc[a)8%RL)!pV5Th0S08qjr"S8apHRq54
-dX#`ZX",N3!AEi1"FR1TrrI%q8+2Fq+`,aQQD#k$!L(4k#*XVb1ErG!QpY5$6SY@
-d83ePf"GfB)@q[Bmrk(Pd8NqdT`-b*)'P",BcRi3!im(I)d0PSJa82iTKGHm,krb
-ir*Z3!*iJZUXH5X3Mhrpam#lXmY$FmH"9fASdSAM+hE(QdmPZYeXcVX&JU$V!00p
-H0HbI"0[5lJ&eBKYfX!+a3B)!3I-B&fr[f-fS6T@ilrP8fp)KlJli*KPTbM5*SjI
-Bp8S$)LP$JPX+`J*+Qh+B2XhI`9XcbAREbp!!r29CCbK)$kXqqq"#C@[-T'$e!HE
-C"qSB!dMC(Z9bK-5rpmIi+))YXqL'b'[8Y&&-MEXDQh`+)HD[!'kULh!Sl6Me1TB
-NBfTI*Bpra%@iK*pp*l1KE)fQkV6GD!pl424(R-`3XLpNb6"[Ci,bE%R`&(#I$,(
-G'`pGrblMK,CiJ[-9RemS9(b9315)XpdRhPck45XmEklB*YQHQ#qYG5V`aB#lN@K
-4UjhrPULm'LSG"*dq@1kS03fSJ6lF56dU4Gd92DAAl0GECdq#A(T3pB&UC"!N3m4
-VdH(1Fh5E!P1GP9FcXe$Ed1p`R06QMhNl6hlm61`JV8NQ[(V!($6bbfV#b"EaS)6
-5VDV!VPfCC45lFGc-YJ9)E[$"4G6,GkJ,HJ8KlR8%j*T,T(ZD8cZecZ-60@dS8aR
-h'M08'Kpdi-#120URl([H(#1qE`!$6b0U"Fj[J2F*pG1B`(KGaf3QF$*d9j!!"X@
-fPGM&4,5K9GI$bM`Q-+d2Nmlp)J$#GcU&JX8Ea5cp&$K3F&#)+96Tf'C193lK2A!
-c'R&&Acq5J,94KS3AAUB#2Nh#M#61jH[H+#@Sb))2-5rB-SbMSbemZf(eC6aLV-*
-%F6PSG(cNU*GZkQReYb2-5GCfUVce[iY0X4"T)aJcP52fAmaB94K&[P9P09Y6dZN
-e00S-GlL3!#aX"6P@,RZ!p1LSC6B!NFT0E)5ei!(#Dl1qAK[U'J8HpbPRd$RdhAJ
-cR*HR0LQV`$,)iQ,aC`$a46RhUZ9RiCbE*0&&(QGpC655UUcb1$Z!D!XGZPYR+q,
-E2[l4*l@3!(VfJHR4hl-5KBbX$LDLc$MK0GdpN!$+@ridD@EajBq&6rq)Q@DK&%j
-K,I!Jhd1A,i4Vb$D9YHUhPmAJZfq"3)(kQjZQI*-HfNc*S-RkZH5A4QACbEAl+Uk
-h&[m[8))UAFeBJVc64BaQdk00%N"lrDUd!D(A'3,!N!"4NIlfkaD0RDT82GD"9kL
-"6*GB8kpd3N4`SdQk&RcE$,'VU$mFD-d)3"RG5ThL&P'iZd!lD9C$9G12@U[l6*V
-A6RK#j'DC`M2Kc3a9T&bJGKqKm#i$+Q@#kj!!F'dq90UYjPC"6Kcj!jqk@VBqZIh
-N"K2QNNCH5V3EcY69@HZB(Sh$$-Lir3RUPGf,`Xmk81a"bF!'c8-r+eS*C%34@mZ
-PZP"Z)'9c$)-59'ePaa[V*mBk1FX84f-bBVCG&S-dB(d%YJaS5L)#AN#IH#q21Hh
-kc$RE`,(Pf*`3"J)Zf$CT+5e-+ERZ%KGFZCihV+P2qI5k*PhJ98SAecDc(Ub)I[5
-#Vr8LpT!!i%bEZNVmC!EDPjq!U8R2!A-qDhN`rLV"iEF#l'D$`AqdYY2[a0AR"Ne
-b5m1qE(U!qM&)SHapc$lTCQPT$X%$qMhTJ8EBFQA$e1)TT9!N0P"m'8-p0a5h8`@
-ccr6KA@l2-e-3``!iBic*0*3(Z!m[H#3#qj6EMe2QX1A4D6-53j1HkBPV-q-24@a
-"b)$*eTG*UKN8+4,KkN)5U"%cY"diF2HI#[jrTJ*[*NZ"PAZ"B@94MHDmZ'(-[(8
-$+l@`68[pqhRjF)U$m[dadi(G$CRL-X$UX#D3!2F6M'6rB-#20A#X991hMS+-*S+
-B%5F%YIfaYG9D`U(FN!!GYk8km`)rX%HVE-SMIXZGZfk92Zb9JFKY5Cd`Up[1dBH
-rKlXHf#MZ6*[GbhEX[G30`G1rPK3`)A"`0d-[,"Q&9PBjm8q"TH'J'UGG`H"U3b(
-IC%RXa&Ti4UF4QF`hM0LL4V42VGK5NM*TPZ%Q6GcD&eeR84UN6@8'cTBeDmp9SUj
-RP9I%A#3Y1KN)b6MFKENMFHcPl)FDNj(F8jm`qTV3LLK`j#f%U!!99jIPYU13!%a
-+8#daH881[H'l6kcZ91#6a01ljIA,(Hrr+qFB1cLHPTB*1riNa)kaBGb!9)TQ[IQ
-$DVUhS*(+lKAdek,Mr8QT#IaA%#qq!S%qCrEhQidQFZPE#V1p(ZC6`4LY!c*dUE1
-QmM9JNTh2bpTG$k0-m3``UBCH9rB#0$GRBqFAa1bHaP#qUiV&PXI#l(i+3L+2Ve1
-)BQlLR0KQ"J#r4l*fAEF1U`$CL@dikV!1QN6QiQ&FNI(VeVSkQFd)drG'98E%@dY
-pT3bIr2K38'dLG#-P552[pakjcH0dKEMfCl'imC'fU`jAQQqKbbRj[l0aNXmr$[A
-18i28&9NmC(hKSc0jBP1MB&U`f,Bq04!jeXPELr,XV*RXLNbNbrJcVE[FP4RF`f(
-,4PHXpUe!%dNpCDRQ+Nql$P5V3f5CF8%HMbE"h#K1'qljV#bSYJMH8%-YR1)Jr)6
-mkdPmb8r2PH[8A&9J0)!`#hm@IUN',)dmV)2G&cL%!VfA,+Ra,q8,Q0de6Kr1Ne5
-l9fe*GA5e+(@ZLG*"K-h2bq`4C-+E+m#e#1G!,%p13RIPJ5C5eYHKf+JTYJ&rjNV
-CY*X$Ak+8QFNGk`U&VCa39K[p4i,[@&Aer#iQ%AHUc2e+-*U2,FK%[rfrd+I3hC3
-[lDBU)3[`F!CICC!!*Jbmae9JllV!$88%jQ$8!R&TZM4`iI#H#!+db`Fe11'T"UI
-C(IVDJ-4+C3Z"6*lp&VKKD6DrHb[QrcDD8(0!q`dL++Ir(8dhh*CXpYFSelRi!4`
-LU6P`MFA@mX0CRS4F4G'SaV9Q%&B$+!+eCSmk5ef'Yl,9AV19X$NcY(%$[G"Y4Rr
-k@rrM1R,P(H3rFpq"h@D)--rE-+K`J-hBk-j(cd&ekU"A#B4#L9lh0*AAdEdPS*0
-B[BhD1QFTD+V5hbB2SVN*!S`HQKG5YN[-JUf+#e[Z$HdeBDahibjlZ3Nm1e)r6-F
-dXVfLm%me*2G`3AZ&!h9ZYpV,V$H*'QY2%k(BRRpXa$J'H1c@[b-ra6pLJ%fjVa3
-19)QNHTr'6"0cEUpFVP)fc8P(K")CTXSLccLmLkRV)4f-Z(c2q-E6F'JMbpEr+Y[
-,!kLIePjSP2[%-SScFpYf!h-$ZCJ2PBeE"Q$Q3IjYa(ld2Tj%R@i+3p*-H@R-edJ
-(5&AqSr#kdilSISdh'I8+0I"a*NHZ#1d3[M8p(&*+J',UP*,8Z&1!Q%kJqJaXHkR
-0+NZKC`ACSC5F2&*NUjQPCq8jGUKSlG"9f5$p&Zq[NrMbX&$!Hf$jQQM5UY%5!h0
-H#blD1$Z8h%[AMe#L)YYH'q5m%*cZMEL'`VF`N!!Hj6"a%QBV&l#D#LK'*9NKeB3
-NT3hQ4R%c#N@4Q!18R#1X6&'%406jVQRR6[@BU))-+V$8-"VFT&U3!!3%ZZdQSMr
-TmR3*V`%CKPQk&8%'E&h-Tb46R&*"b(DBr#m0a*VE%Gp9FE-YIYF(aE)[601l,XK
-)XhKLl-'A`"'UAN6hkZB@@&S0kH$1C$E@FXNKGB,aL)6S!b1hVG8#kG3604AdCUJ
-e#R+U"*%3SPjZ1RCM%Qa4[KP,Mci8bb(J5P2c33r0,GQJI`(NfMPl%S-iQK(N+h3
-h&PRG*B02A!!iKI,m!B&!2Umibm(HJdT)V998H*)&#jl-F6f'(b@T(FpC&f1q[e#
-eDH`[PPpilM+CV$NR$1IG+XpX0VG9m*6)K`3LlVV,"kG%*m8ij4K%cK1!1*LaR@C
-f0,8KLN%TVNQ!p2MdMbQ',J8Kq#i1'Z5lGbA@I"Fq+KY!hHUp&C-)-U['9%"8EK6
-VGe3dP-VkZi,qG'U3!2f5&&!)Tm)b[)S#C6Gp`Feh&)&0hY@$"m8IdqdU8Mh&X1P
-$kdP6K,cGrlf6"8PebC9YaTRjiV[5KL+6L5X(!Q!hpK+!P0()%VV,IdiFH'mV&9k
-XLcJib'#9FjCpUk#LF)U+6"8$AA@BS*6qf1dCIhK"rV`m(5aIRZ-U'HELMi4BG*q
-!#Xr8j'Cb1Y(CSTY'DQDQ9@FH%0efcDYHZ,$bq4X8JjfSFA)-E!Xp',FkZ1NhK32
-MSY"(b@pGJRTDR+HV0*CJ!d4CVi@m[A$m#5"$L4,N,#dGa9i@U,)a"VTp,p#)k)L
-k8%-U8(+BV*')2LreL*b1)%iCXB3rbGI#-GA")Q!IBMPDSj!!dA$R3rp0&Le"`-J
-("XCfT8i'C6[5V+B3'QlG&pQKBB[[!h!S`1C)LYkXl#2QT"[r%Arb)qRcC6*`5r!
-kS#PLI`-)aa1L+$*BEa)RqTAGpe-jQ2eZ9MMm#MfLdN2YId[Q$l+-9IbqUZ31#EC
-(l`MAp5`V(29c-pPVGN0fapQ!`PkFGT6QADT"JiaeVQ&R3,3(c2aidmXDCD,6f,N
-d(AAk0qCjaS#(8$FeM(%ES4$YdKa(!TL5Th,qZr6AHkCRjXPl+j(ZbR*P$N`HQ5T
-J88#$FGUdXR`B,G8l+bBXlTK()[[c4M'D5X''Rjh)f*E56FlH&ia[!j38"CZL33m
-CN@"+)hLRCXjDLDlT2!VkQ"N@+a!ES9N"qSAQ@'G6!b2*aA5SSGHcbiL`ZmXRFCK
-!$D0dj@&#NeY4qI2r6F)#N!!B#-,JfBXq5f$G+2mk6XBR2XYS,kfQQP$SQP1"8eS
-9FpeB2BFSY54FK1-9YqH3!2!PY*K[Xr$HkPR8+qJkCdK%G3a6@$F)EB%4Z!5I@1R
-%'MDUbEe3VhE6I*`0VK9+SPb+V@`2KbL,q)'mhlZNJ%`5RVK2Q#3!!rN4Ck-)ej[
-Z%jQ0FepC8qm@RTRNFcH@VMSAbI0r[Xk6pk3D8-i2e4&,Ia2lR*j$clBb(M1RdQA
-CC4K[-$J(AV5TaQP"4Ar,4F&UB$f4#kim6#!K8HpNA[$'`4b0iG,Q!PT'+I(LKK*
-D2!cHl0%KT'6$(TbHE9(jZ*p%qF3(+RCp[Qrm'BA(ml9(F%LXBHZ(DNXchNAVpQQ
-XE@H*3(1Jb%l5l5cTFEXV+J#aI&#,LQiml2hjX3HffH&AV3MJ9rkG@2Y-aJ01UTa
-rqVFiHrZ6Gp0U[lX(442LXh9%[paqqY%dkJ3iPH"VEF@kK#adN!#@cDSh3'LMZ8A
-'(,6"4$(H[#l$NYk+3q$YKN9$9NR1ejJ6G8j9%5Pq,PSA2TSPr`*H&PjAHL1J"Z(
-K2QAR4Sff%eb8"$iETR,+TL+lF@cVNKP6Q!ZJr9'h[hTaSq!+SQIaB+bD"+6V'L,
-!V-aZ$!Hmfh(eJ9`Ua5'E,#)bGi32!eadACE!CBBY#4&+FGahJj&'%P(pe%8'(9b
-M%M6a*8H4+Sk("H3lpP6DFV8mN6jk&JV"0M@rkhMaJNm)e%N6jC!!8CSp'0C*p5d
-XZmUIU5SQIi-A8-q'0Ab!CTrKa`Z3!$I#G!+fSTVXT*)Ui6[RHif%9r+-ZCRm($A
-'DEF0f-ZVC6iDZJ93,09XU+TEDV3ZfbpYI@[PB2BKHdia+e3!GG*`bB*-+VJfpNY
-m[,N3i#deR(p,A[L(C$Jd'Ic+EDh18Zq"jIKLGNildLSNFUidB-P)e3FV64Tjc#)
-U&H25QYI!-i*'`fb((aTHPT80dM3U3h$C+HJUK&rSphAmA5KD6UI'TFq!k4cbk`a
-YfIN!,a3hK@MmZ'NX)8cR8qCk-q#BG)eR4Z6mM&%XBR$2!kU8L@U[fAF*9SF"R+R
-R40M1mCfXI(kd4QA(ld$j66c5LVAU0KNPV(0m9[q$i!j35faRT,mqN!!RR,c)[48
-j$%0!H@IbK&BVH8TqS'*BB%Y6hI6lc*R%Y19R-!#J(`kG*dp94ELNbr*$T5VSEhh
-9HbqX+'Rl+5BCiRk%2j)"6Jq&XkQ&96$da3YV#bRGrJ2clF8jFHjHrL")Bh$IPPI
-T6bd90&'[2c![3NLFZDRplq+*T[r1[(DRL1,eiEG"ESa19AeRIT!!p8-Z!ie[NDB
-HpCYhjqM-Uck&f4rd-&Si*N"4!3Dii-9d0H-M'C*lMMQJ)KkB`PGqUN*V-CN3lB!
-NLP5PfQJ+[cdH,eZ)ADh@$Hr@VYI0N!"69[q+(,VX%JpdhQJ-@UHbjIPG*b2Xjk0
-DH&I5YfZpaf!Q(-6S2'[IES5@X8#EBZ!8F@(YaF@0Q(A,+ah"!ZHDr-*2p$XfXkR
-QS%rT4)Ic*X%&(Z$1rmI[V1d`&e$@AK3LP'HDP03!4G0@TBEMTqbHeb'U#9*9mGH
-pBr6EZ$@FQIpC,MkLRNpB2elHKh$KPl`5pFM&kCdKIEVY))0GGX,X5-Ll1,-dfr"
-,q,JQA#i((VQbFlqq+H@2BKF-Kip8bl[%KcK%684+-d()EJAc(&%Gk*IK4UbNh3*
-h[#9NPm4AbH-%*Z9d+`TFpRA$j!8HX%EIri`,PRcXYTp*+Cq)ElSfc2&IRUa+edq
-@MSLU@+l#j`H-(YrbM8,`"Z8@MCVh%AG!e19"*D1-1Pcj'#+"3,0(`q%C@,20QK`
-YhU*prPL21,Jj4E0D`CQbeYMAb-*C)U3SjP4`30cSrY1U`l@IATb+m3Q4,@hFMIZ
-!USPPf9Z$,fKj*eAeb0h1$`KFm5iRJ)4,HN`Y"BfT+TKal6p31P(4Al)TiC[da&H
-!T"L@f,NmiYG[AT[fQJ'P4a2mPh(6%X"C9$"eA,)8CYZdE+GPdJHlj(4Ehj-"Al&
-kF&rN,U@pR@bFD[DDJA6BX9D$Iee[NCcN`Ma#XLrSMGTP$+,KR1H9"QV85TF8M*V
-#Y+HN(Q*'1,e08TDFJN90mf3TmBf#LJJQ$ST)T#[AGNUa$%0,j(mZb,c%2Fa#-pj
-Fp1EkaaK"U5S!N@+-#CS&MHUFT'X(limlR3KU,&c1KP@mQ*C*RMZrY-6%4-jpceM
-*E3eVHRXfA`"0PTA5C"GjABqEj*9D"Mqfj$Pf5AQ8VTd+VaZK0C,AjfYPqhB16,L
-H%M#lY(,pKC%6'l(l+aZ8e-TVZiUP)6c"+P2-'f`#KefmfdY45EJd4aUp+rGHqk%
-#(d*6+8ic15PkSX4Kj8d(m--e#Z2d!TN9l)M4P8ZK%%E$*kTFBMaepNi-PY"cEbE
-5@QH8*UcJ[jfM$E3AGS%q1*MV9l$FeKD@QMB48L8p@CQ())i9p[rNUebCEm!Yhb3
-lZ9ESm3G[$*Q6K6chFR'L9`5mHjHR[-e8%YGUce[ar@pYGqc1NYYCil-hj`$+9Bl
-jH4RXZ#9M@YlH1f1@%m)9E,0IZ0+DP3!3%rbUi`kdC5!-6"eGCQZf,(&d+'eM5EM
-`flh*-1"Ml!YFLf3KkGcicL(554Vmc[c86XffSf!9L&X#-%$"qpeih8$*8Hb#9`I
-3b`6PlA!2*(DUEMqUcQmr+%9GXc*4RYA[SNi[6m*l-5Pfbk@a9`38drlYK45ceYB
-NqUPS,X@+NI-Dj&mDHD)YjCqZJSre+q!#@RL5cX`K3ahmI!@G-XaLZ,,qLj,'jDc
-!2Qp+HD%k2d8"bID[6l[LL'E`U0",qB1SPVY*DNYDkJrc(3qqBDc@bG21`hAKMd@
-Lp-E$3d0Z4lBhkX-0P"V")([8mcCJbL9QaVLrM4[9h#k"pd&VF4rUMLmA*$+jbVp
-K,JA&-UHj-TeKQd[RKZ041)@eq[,Ma38&Y(AhAQqY[af[@11MF1`H6V@aZ@e$+I%
-h"KC3`d5#*)R%#Yk)@#Rjl#mNfbIZBMfVHZeV14cp'q-8,$fe$U`fqf+`PeX3[Fr
-P&G*G!fHUl5H2K!(U25DMX$Ed)+0kjCRKRi,&*1AfXlIjE(r)BbV)jE9C*'NMFbF
-Q3+lTbi%dPFK@44EMkA3i+!G'0G0L0+k(Fmm,-GD%LCI*CiS("Bjr!Mer6SUH+EP
-mepA'BPKR5#M2XH(A%'!+cj6Z$3"lmE[c8kBd"0hNkZSLNB)m4ECLAGV"EVM$X$@
-j)0R3F@Z$8jQ,C0N8(a3kbq2,@HPcPrAB#LbR'mZ8Q5X-e%2)XU`+bpYM@q0Ee)p
-3!8HfJ*fM45#D0kcCQ+M@r5`MShZ4YphA$d'aMBP`S*E$hRlA%MTQmTq2YaValdd
-l$6JP0b6*"CpQEad+!4%C6FG6RK+0A8i[459Bi*!!Bmr''aqp''GBbG@&4U,5`F1
-,pfREV48KqC1'6UBT"Dd-U'%N@6c,&P2[284AHS$&**TSV4"V"9I#-`8D$8j`Ij,
-"f4mSID(lY5@l#2HdPkDhbL1Nam%EL#E6@PMaXZCU2hdclm%H+)eJFKB!61[Q+QL
-"2(qb%LV&6jD4'89L38@LCYq+YC!!R[)-88l$ZS'&[Z"!(hBSQ"M2BU@+6F,BmK(
-bZK#4#@D`QC!!&Akm&IhVV)5($)l(-%,J5ANJB!S"DkSVLYkk40jmkST-#2lpTbJ
-2hfFe')M1E3YPrEM9kETI3ZaVK&,)"DQ14FX4)6D)%X(89Ze[5ZFVZ-1NXAID$*L
-c,!A@I[CGMhE8+PTkJZC,BmQ`R"6bbKJB!RDYV[qNKFCEe[ZDm$-6)0NMQcT*cIe
-iX[*NSe[904PicU9mbp%ZrIRSkY*`j+Z!S0LFI5DEMj!!Ta9M+-6VLpc4Pb5*[BV
-1l[9lp&IF@1qr-*C3QI!PkXF(+*)"K'l&qQbp`4#4Jp`24@ELXH$,pU,fI*XBfdd
-KhBCDTiL!(iKU#C4UT4MLb*,10U2r)S!)(E2X12G%&2X8,iX3VF"!99epAB`Yl&I
-Tk'%TPeDX-Li,B%4hIphIlcfafKaflmFVLpS2J`8[JcaZ3lTMqXE5c28*jU4$H[B
-"iG!BBQ-K*k%'mif-#jLRqf3,pp#8`EJY@Km)h*KMiV#5QK9J$Gkec%aY"h[Qd@E
-ED!CRMP6KkbTd1I#ZBLr9fZL6dC!!")#[5(!AU2f+ZFc')DPZ245mArZQdUT5a"q
-q-XBM-Yk(bhedR(ViCmX'`%I1V)Ge0[BEPTc@-b3eZDd9SMVF3TSU+T&R+4!B4"e
-9%SY-1)`@jkHFY(e#5li!K&@aQ5$e-URJ9a)!e'"2(3[(RD59G)Lcil+A4X`Jj1)
-!1K(T-VNlcH-'r#cB"N1[9FE4Mj9SlN1fF+cA'mb$MT9DaU,YR,qJd3+kHep2F1R
-&%3jE9,Lp3XrEH9F(ID2IXph3YUR"fD2ipbdC#43XDcr!Z&'VhFc'TcN-`8&4e&S
-B5I5KZ92PK!h@JQ'lbMNcC84riDQ6G-paKX0Mek-1PUjm`+@3"!%!!%3!%,JMfUZ
-i)pUV!!!"LJ!!1aJ!!!%`!"3h*J!$lbd!!"Nr!*!%$`"#6d&I9'0X8fKPE'ac,Xq
-!,RKYE!!"0cC849K83eG*43%!rj!%!*!+J!#3#3%k!*!$0`#3"!m!3X(9#he9rJK
-eEik-8V@kZdUV2E5CM[,Q!QPqceI`p4Mi%Ir,pA,iSf5%CNQ6JE&I4Gf(b46X!%,
-"e3qeE'il$r6I&A"ADfRMa1#5dEk6cNSf[XQ!TmiKlIrJQhrjCrdk19B[NbM#Yb+
-G@RAa!kLGZ(1MD9kqS9ApeVSdPap3d`N1Br2+I"Q*J@!+rL"ETEVKLPZ&Yp38NEN
-D*9c)B*3B#cBVKMePJqq+N54CZF6kC8ebd)VTreliJRK9)+flaCX@,8MC[(98m+D
-Bc1NQ-BS8$+DZjFk2`-1AHq9iKPS-c(i)#8mpp!$DeeM!ZU3RYlKqEf*m,E#q3jj
-%C1GS)Z'G+ZA!Em)8MHeh",ZcUVb5T!"q@Y963YbCK%RNrDZ@KZ)@C2($kP*bifB
-YUiYiqFrb+FE'@4A!ekR862BZ-&RM&93LAqX,M4m5Vf44"c-Eh1LaQi0[@lA%XaQ
-LS,#(*RrYhRjS@09-1'4CBTe4aQe98m"I5MQ6,MXa93&DKE[qbNmV!NI,"[h!(hV
-'4(R3[KDKJT4Uq-(eeZ+YLcdfF1"TVibCijf+VAddTYiDF`0FF`4-5K9&88eB$"R
-8&B&3NIkPPd9QZSCD(G3)18pAV,`)XDmr0+5B5)+kBVe,26(eAK[#@(I`YLAPl&S
-5H6*Fj6VF+$-3aCr%%Y*EMYC,#iKCpem535(irl4I&jqYaM*f0YcR%)!b&S)f"de
-#8`3TH#qUY(["SQlKIqV0NR'fIbJFQlNIE@!H(-UkfT[P@lGic0X$lPRkLY`VAkk
-b@1am!KK8YrhM5(b5$c84(kjdb8')k9$R"j)#)IDN[i(HTURph-I*JZV-@T,+,Tm
-U&0d+(3kp-6jZAJ853LEXAE4Z5D@A&1X@rM#SZUCqe[9RKEQ)8Ul(R6m5MT3P6L5
-)h3'f$ef!--fq@+TNbVH)dITkR3P#@)Y"ePPHBl8br$624dXMb[l59L3fk4Qie[f
-1VEbYK8F5L`M6mcScBqmED4"C6%'rpaZ4l0IJp1pAJc'4K'2KCicl2Y1bQLlGFBc
-A9@rm+RPV9QZpMG[GTY)YPm&K[M+[X,2%JG,-QBheqIjlEc2#b5pBA'QN32kXT1m
-3,5&a0Uh,@*!!K3#F!+qT+!@5Aj(r`Ic1EZ@YrJ98FUk'(q+a,hr'IHJEm5(6BVF
-XE-Tm@lX0SiJpa+aadrc36+K9*cKi1p3F1KBq"EH%Le-#XTVaQlBD"L+(U),2h9-
-h31$Y%4elh[HiJAY3@@-aHeB+!e1Ua-9K'ZXPc03)3bH`j!`h*8c1iX5q!bJl3D8
-0DRdj-F)hGDIMCQjP,SVhU&XT,E[Qd8(BQ%JJEJ23M5-5HBD*+X[QG'Q2M*5rZIS
-bT[e)!QBqT!,Mc1G'lIJm40hD!-5AAl'15EHX9-qZm'd58i23'iTDN!"XAKAV(rM
-ikQJ'jS!U9fa0JJ-cRT[PjY#r-Q8I+$m8-`L!3RpDekGN#RA)h-(fAM%bMGr$L*2
-)rQk4jkMX#Z%@!,9+8JfGq5K+heHYZ5S6eZGce!)TU4m5Yq01Yh,ek(2&TL8cipK
-Va1-X)"P*2V-Sp%h`hBmkS)@V-ZFljqJ#S2$J3$Yec@G`Tc4TA8k6X(&M3PeAPjM
-NRGUC%*hHeqkpP4rc5S2K%p5kDCIVki,@#YhL+1DMG&!5Q*XiKq%0"b@1[&V2d!M
-NTC!!MrTh6qR$`8N%C4EP[HY)k(p@8m`aN!#[c9m1hp,-m+e(`Sl,+VBX$$FEklI
-qhQ9bV!)P`i83j%S[&R[PrU*HlSaP92SUU6Per$,e5),i[$3j@!J)YRpeZBIa5@1
--eYE3l@jPT5@SFfdrce-S0qFJ4P8dl8Q,(U$PkH8"C%H"b!6JHH4GbN''1$M%1bc
-@d[Y5Y6pCqFFDjLfYYH[VI%Si4@BLXl'$-DS`qcXA*RFkCNSJji"93Fa5K(Z6,3)
-j0DCSa3YI+$PAbR60j*qQ*jF([YIEH!3Z*i&"H88L&4M-J08k,c3YC[BK(E)MT31
-8KU%DFp#R0)mXp9S5[&MJ8ZSVb@8#*Da%AHQP$PP&RdhipKp3!`h"JhilM2RIb#Z
-#+@9j#1fMlqd9D5lcHc,$8iMhNmKVARZ5qAeY)Q"dCD9ECRjj,@DNqD4IFNLl,P8
-dD2i8*NB$ajP!M4kLEGq@r4"f98YPe&++bAYd(&e'$46*($L835HQ5l`4BYiDAaZ
-p!r+)Gk98+P6lbX`4ZP!%mZ%Rq984*&-4IM,SF"QLCdkKed[-a@PZkKK9BZQLC0h
-&K4CTl!I!pX4q'(9Mm@T,diA60Ki*%iL24pq@LS*U6(#HkN,PJ`35q!NIl5Yb`2D
-M`*!!X2(RB#`eJDI'`Fa6cPaSi62IZ@B+F#L[ADmM"3JPiRe'cej"X19P@'TPhBH
-%*e5d+5[&P2LA"Z%"d(@@+MrXM#)D92qP@D*(faN5R-G&BB0MHeUGLphC+NBS2JV
-FMDU0&p!pdNYNj-+X$%lD@486G411QS'mbDhmm)Tcp'#ZeiQCD'Zb*2eZHbAahG)
--EM`D43Z,[VmppYkTX4HVI`p3a,J@1Mkkj3[laNe,h6l,,@$cY2QSNp93cC3,+f5
-bMBlbib@Bj5eHJ5GS+Shqh#M9@&1#kCl-M"6rkmd6J'1"([[2$9ZaUYj5j2b!6F*
-AT*KNI6-@i9QB(LfD8k1!K4*"DUCpm+MReY&SV(fAk)m4S+X[q3SVr6!&9&Ul-mF
-VPC%,e("H&Hqf3BJG@qJ'Vi2r59k+aVLUT@)CAp5FG&c"AlLM)JJqc&FmL-B%#"$
-%*4MbKe[kVmI,"3@de`f4fTh2ABUMBlN#8q,6D#aG9AX*hi&G'riZ&b8NkAk'#1P
-lZ"p%PH2&*S`DQ&&)&YehPQC6"D)M4(J)*9!9r93Rqb$P9'`MY+EhE1(b(Ah,@Sf
-C(Lid3R!@364@LJSLFI,aS32DZii!U&CpDb)Hr!%6())3*[&2j@(R[,P'-P)L0pf
-b@HkAF0!FJRX32`[E&Nq`*e$LH9@$A'%F3D@YGIKVAB2HB,4NTRVN@A%4'ZM2D0-
-@ZEp5@TNkKT2H*!0CbUU2clZp5X"DZNpL$(Xkaa5@Z+&(1Yff-rG2ip&MMIX14r&
-m6VpPc*ZE0J)GA'L*V9`NM0q6%!QG$p[A)MbFiNQ-M@e[6FVq[5!QME2IVHjL,A4
-r'VcQUk4hp4Vcq4e906aPpelE3lEm5A$(+6D9'lkRFfm6"VPjUrD3!!eVNUH"4H`
-hmV(,4dp22ShQp&LV9pmI'qD@`4-r[A+3!"a4894-hH31RJ'cmmSkSIc[fk10-kM
-3*GQHc2E)L*CaGj%f'$+*0%l`M[+83GBL%22c'h'6C&'))845S*ZaEqV-AdjG`H`
-Dp2f@Ue*IJ0A)'qrZSGUTTMe-klYBYeZeMj3Mfm,)$dA0f&905YJY4db-a-JfZXP
-1[+EN6Dmka"f0$4!Xmj5$[HG"fL!2@D*AI&,dVm@"Gd#)fXV"B49qq+GDG+0XD!P
-C@bVq9NK30Nra*JR1G`*25B*kJSZk`"iMm14V0G"Y$P%%jbNBdd[AF1fCD+a5I%'
-TE#SUD9pqmQMIRIXL%"MZdI#$dMRC`8I)'5lBF+ieF[P!qXkRcE$N(Pj!2(&0Q+T
-RTiT[m)[CcdC`dJ'503Yq%6pjcTVp-&#i'FKdBbJilqfQ'XqSS8G"@-#Qh*hpB2q
-!Q,M364iaEB5)mG1f@e'L`@5bc4+Qd2V`BVM&a&)HJp1m)804d-hbdlF22Jm5ZM9
-H"JbFLl5F#j2TJA8hRTGRXfe-qVBcHBYdYeSIUGIbL6bA(1lSm"!@'Rp!8`%mF%K
-XMA29RLa"Lk!HNX%I+mK`CAbP9Q5fUD$#*@JH`E@TB,rdMZ'IfPAii,F+kD%BcMA
-cri@*[Nl*cI66@&@*f@*%K4X@8!jeRjLbjjqX05@cif`BKXS1+l`RG`QdR38ji6$
-Dm@5XUl[j)01GJFZBVKK`B1MlhHB8pFl4ZfdY5j5NQ*P5VEZrCF(pq2fVF"pTJm,
-B,2N2$RGAiK&(DCT*IQD2UcpApd*!VEeIkRe1)P4iMbKMr!Z-h1I[hPeBqYm'G6X
-ffP-"HccL,0Lf4DT+6m*(8f3a@3HH,$ZMDL8fPU+JU@lVmAmZMSB&0rlm,*JFd`H
-#&5ilC,CK*E(12e%kjRSN0-)pV)rB&9qQl[a@BBDj(YAaf)JD2cFKrA!LNID`mbP
-@mlj%I8[C)@%IVf(B3[(H2#![ShDC)R"Vm%M9erEm[A0[!*YHXA0C@BM*1khZaZ#
-rqYJ-C'%(@lrC)qiJh`BYU%1K!c%JVb0i2QRq0qCh"A@Q)"LeXQAQ4"m41Ac[Gl"
-Ic&Phm*R!acV%A0%+6)`pFqSqm5E*lF%(EKCM!ldM5Sr)kM`VVp2q-'jeF'RjL,3
-Z"jD&RaAZ8Q%lfTIl4-&"2&Nk#VjhrXCV@lD,92F%LP)#EBJf-e43DDVqA4,SQLp
-jJBZm*TpTUcQ@A9a5@Pa@2"5R!L6kaS'[GKYA65ERdmRPIej6d)cAl&C"%ZhmFcd
-452Li1)EUC#,MRiVCp383#F3Ej@)%H'SchbpUq3HRR)cMD#+2a!b,mX+K[',Y30Y
-AkcA%(JFA"hP6lQdmBbpR%J25$X40dKPPM3Ba1%0&[)P$G)"8"imm4D5bDG$&T&B
-eCa)3@fTC-D"l+EqFKQZkFS"2icra6!b&a-DK,Jb,ZFN&)aFH!MZDfhhH)4A2FDK
-$CT8)f+PZ`(iG@[1-pMG8"H4+-a5$AP5DikaSX@+1FHHp(cQpQqijKl6mr#N'VkT
-J"@KFkUF4U,fS-QAL8fkc$$#facNA[[Y"YHA[L(#@XDV#qEm5U6b89!2'6rq0,jP
-c3IiL@%PU,,'*5a2X'"AQdla%U@Qd4D`!hk**6$#MCCd,kUH[80T1,`Ze"`JVmA[
-GCB5pU`pX4KNC!G)DP2e"+1%HhiS&C&9"'3m59N5eZEb*`L3*ca1+aYFT2#ml(US
-C*iPNqc8RKRC#P!a)UjJI&44KJhm,NLL*QC2MZe[8%,1V8pVUhhE*+pDEa#GA!qA
-JC!`9mGC`cNBZ&!4'Mf65XECD!6jRP*k8mIVJ@!)j*&e-,-0*6pL4XCFEMmFS!4S
-mQfZj!cfNj'kjY*6dA*!!L',Jmi-URMEM&S*lL[`HZVbfGJVMek,QY!hDRa0%Y4%
-rH`ccSZT0Ylal-Z8K"fk@Xm)0H#!K-EDAq0k,Q)iDd2B%lj!!FKRM,5C[DY-hlkU
-F[T!!5j)")eq!`XHb-J,8lp5+jI)iqLXi-jbpllG[f*V*+*T1"FHJIpQ!bf+*KSa
-"*+$9NkD(kVN3fpQ!6[MZ0@QqA1#SiRqSj+ZK#(+245VJFSUp&cVli%DY16l`N30
-K0e"apf[Xkpq9a%#QcemN-A!h-H@mQr+adZqDQU(R*G(PFjCpr*($JIA#KB9F@RZ
-![!G)P,[b1,JEKB9hj5'6,IUGNc4hPB8lqH6IpE+F6-GGaX"#6B-f81c2R@-S8er
-`5%'CRf8YcaD%#mR'"YLj-6L%NMa*3!N,@@P*`MT"TKmcX8R,-0RDk"FECZ5M@*(
-A1Q$&&jX)%!Ajf[ZH@05C9`5A6baIC'*$B1&0KCL2ihEprR-#*BbmZUMPN@*34YP
-rRUBG#&Y',36IAXAlII'!'i`B5T*ACjlGj-P3qUjVG+KA@6K@j-JNM!&kV0XXP9h
-%PV"C"d+6D*5X`PBSA%QQRdaS,F3ZS3PE[MV!X6@EqMpeFZ-BQmPBEQmZQ[b1@lU
-`-,8"[Id-Q$mmQUA1-)06!4@V`9PZ,+a[p(82N!$lq+8NeaZbbQ6rV8JCRFcJ*K4
-5%2+ij'!+-1`a#UTBiEb(XE3+M9ra2)D*&%bfYUYJS&%Z3XKq2aMeh5R49M)!8(J
-%mMDUN!!f-XiC+&r5EJZcc!fPrNAdVE2)Mcb9EdH(0P!miV-%&FUp#bTZ,hHcbb$
-l(Up"#*Pb'$l+dN0!%%LmP3$pfLq,b"G%+252EM,PTfK)U$ffR%amJq`aP)aVC%N
-dQ,lm%%HMjZZQ1kc82V3bP6E%,$$X)69$R3c#b(i)PbibXCbGH0'!j%*D#E9qDU3
-qV`!aG4AkkPr['ah&`q6Zm8a&Hh46Rpjp9CZ+([d$EK1&M9P#83l@I[k+K`bN0KS
-bH@kGD&92k45BZX31jFd(PCce9CH`4&B[R(5H[aEZPMieY(DN!!RN'`5[,XF41&2
-li[S&fG(`-3e%L(-&lKI-D@0K'+-+64I36Hc01%0&5Y`khQVdJaiN4KbZlDSET+A
-'IT'2'2plQ)['Z&hq5I#1BRVRq2CNNIVpia+A2h%UU$ejXI8``Ec(lr%iE'')ClT
-lr-r5B@9B+,L`Z%jL6[DG%%5e3I*"M+SGkL!PjS!#CSFUBD4+e6[I5+TX)CiF@HX
-GcUFIb8&`6qhfp-iVR&'*'B!Cf4j&L6k$K!d"-0`6(jmRD,@dAV5Z$BN6dQHFlG`
-XiA%biFfbGA3Q@'TE8fbThYF#G#@cZABN6i@HPBFfG%QA5NV$'j`(CBiYcTik&Rl
-a-qXTm'`j5083%laY*NA-Y2UN'EfrIRfjZ[``YmG"GVCNapici`4d*5Y"RPeCNDd
-MT-,edHGme#*b"D"B3jE,6dkUGMA"f2M2NGBbm)qi*TP"eB**)GlNHf(Mj1&J2-+
-CK!AK-CT9`&JP-CX9q8VQC825,1!9"H@+EBHXSXqaJ(f0$[(X@CffkkaHF&SPXkN
-D@,FC1i,Qe564jfrNFB+`C4!2&T4p(k%)JHDBIh8$@D[S,"fKIXAG,VQ@$-hEQ0G
-+jqj5l`3%0C)BD"Q26ieYEpUj5j(lqP#aHXS8Ci-CBS5qQ$mbh8BaDC&UijJaXUQ
-@BqN$SA6L9PhX6&-f9$YCTh(NU[hIH(JLj(Z`['bc&#&Y3e8Y4Aj8b#6*9TCPlJX
-bi6!Gdac3"15kZ!&6%SqdBEhTjJTq)B[`C['GqEP)P&+P0RL[&P9"&FH6Y3(5%XD
-5I$%KXeB#[rl"EMZN0p[AGl3*DB3PdmZCd(Pd$KplPmL+LIjflj`!(C%rhEXQ(R@
-B4fK1X)5f[B0mej9-jhKZ9KLLUX(JQ,Bm6[$Pp3r#3PFU@-*S6Vp!Hb4jp*8b69-
-&d$CT&)0&A21FZTKL4'Ld"rTDMcR%KA8V0V9#!mGf8GkPL(M"JV`[GFN6*@iU@&h
-(PKSp`a3dXZYGF(Sh*[`lU6[2lYIk`[8EYp&h@6**9p'LZ5H'+j&,SN@EpVQG2Nh
--iYMriq1'&9-JeP#&%%jcI"q@#Uc"ZRBANj,l!$665af0"VIE5`08lV!3RD8"*iL
-LDqF5`iM-Kdr%'e3*HZ26kL+NLXDHG26a(#LV9mkr`+b&qX2r*`,ippjljAE`q&a
-#qd)*)+Bm!lfpB#d`hFpB!`b(C4G@!@f)Ih9QIG86CJ+*0ZJTLD+"@CHJFfkck!B
-ZJlq#T+8*`1NmD+9e`-4ZdXlBMV8Fj"p0N!#9@1UN[XKVK,aI#DaGq2eMSDZV9Ma
-K%$LBRP`51e%HfEq+UmjF0#1jJZaKl2Tp3@S'QEHIa0kmN!"P!5#AZ)#%VZGNSbU
-G$TGeb)Q5[r4U0dJL-P-!jZ(bVF5i'!B)h5)2f'!fF@eV,F2"@'h31X,%2Z%4TTM
-#!JTbL4l[jY3#hF-P`%GHelH$3p#YHG-3F-e6Yfh5mb&f$IGhRIGlK4LdAVfR4Nd
-*5MiRZfB#Z0rCJ6McJpQS`*Kr,mlMC4qUEi0I3[JpN9S`GAC$PLceq5JCj[bZ5N6
-m"ek#4ilr5U#0,c(#LcL5SFN3I#H*pN6-HRrXH-pa,6,446Dap1AE-'%A(F8+YIM
-62$Y%kiZ@`5*f!2Zf$[YBQ)8qj0RIE4*%kH`0Jp(HSf$T`TZRP$[(M)e95"U!+h2
-R69flG,%Y!J054UL#MCEpF0ZSR[lG%3+aSdELDXhDXSp36`DiRLL5djAXkb)ZpBl
-BBA+I&MUKaTIk1NGP3B8YqqS"D@(#$i,emBNNBakq[UUHDl2JDZmpq&!hCGp9--#
-VZ"TEM[C,b+CQhhZdUCrM5(#'')-b4"6"K3AT-Pk$E$kkd#92IG9FPr1Rj1!E0mf
-XYi)j5,9fH8`LpiMJPK+jeT!!QU[Q!cCEZA-KjBb(G+C[U"3fLD!G2-&&Ql)Z[hL
-d2+Y%`ciGN6NYK%j*M'+%Z)"Aji25Bd%4$KqUF*8&K$Fce!a)Z)GS*+RdNi(iQ)i
-PcV+X8-iS!%UU!rlCi1r3MR-Mk!+cRM$QJk1UI(GIb(kiKHM-fS1h,Pj$`TVfmUR
-$a1-PdhA24TkXl,8Z(P1NpH+V+i6ij6m[mIh8qZ(-U*lrlV-9)%4Kq@BfE,Y8aPU
-#NBKiMi!P$JX0d63+mfUKLj!!q1*E$V)(lcRDXFCikZbE"M0jbfMQZDCMPA6@bfj
-%KE#cE34@%[YAAV*b1C'IB86#4+FK"+kGrU!q,ba"SHIXe))X-S4I5idbV3ZMmT!
-!rFhR'3'D2rqAPkI36@f8bY9r)6-5#f-`0lm6l-@A8e#N5kQSf(+4)NmT#Fp)C8S
-IM,38Jr#JpA!m'`Q5TLb+dIlHcZercL2N(c4TT*DIhPTfKULSQ(QaCYFFUK!VMdf
-6fBD"-4%0r)A'82fA94d!C#9FIPr'C0--R'45LdB#UcliP-kVr`lkRVdlK4i84D!
-B+I26"#Ek)@-dXDEd(%#M`jRU0H)3hCk53!NX([eLSaeeHRJZEf%GAJKe0Yl#NjD
-p#100'rCb$rX&@Q4cU+B&KQ,2ZST[PjID@mIM[9N`raEQ-RMPfFfJ`Hp!8e`@3+@
-3"!%!!%%!J,5KU6Uh66Z#!!!K,!!!@-F!!!%`!"%p$3!"iq3!!"e+!*!%$`"8Bfa
-KF("XCA0MFQP`G#l2J!!!3,*069"b3eG*43%!rj!%!*!+J(!!N!C#`G6%@f`GLi0
-)4DkN[b4RC2,[p#G'&Ba5`H5melD4TILkXNc(dUD4AADeYh`"ae8f(MfSk)LA3PP
-1c[3#,a2j``qGXElqPTKk3KGX'TDk!hVB4Ff`[h*lLUD'L`+BN6c+ph@'P!&+HQC
--r)R0'I*m-,@$l!'[Q8GFUd@%2X2,T"Lj"'+11`*Pc2PXHmZMq,k0rdC$J%*!aGk
-V-6Z`A**1B`f)kF9I0hGA"S9eM5UU&Q0DH&Nce%$r6!CET+h4Ij+E*AKY)T4rN!!
-eeR69mlA95SVK,X6LPP3-CEEURhK&'T1aXj4@*5k&L*3eldG'S6jC&9E10a(FPQQ
-mKqIrX93df1k#Zb4FkJU8eN&Jm[+fM`+19c'+,b8P2)XA80L+X%#62HeHbH!&`TT
-k,1mMj*HCmA!qY+j18l4Sj8`$D"&6-N,Pq*YIlAa3$HJp'#hFE["N-$K#*FR2%2q
-5[N9Vi3+dQ&$A)-KC%B'e[PPB$k6*+f+Qb6bH%bAYARAL+02j[aX%p8j%jDD@[FU
-+(0q"3dhB0PqX'Fhq,4qVi*G1RrlF1&NGh3H[CM$D8!!I0VHGIf#5E)MjG#k1R,d
-#@hZ!1erY&#"A9lb[6r2ZR&'[lHrT25rGd`e@GdhCrqpN[jiDMdMSValBrm`'"*!
-!LZSPm5meDEVi*LSbYb(b#K(ZMSjadYT)j4Ue,hHQK(XLGM%i6JV)#`2$Ik#q,0+
-E5-%YL2[&X4Cbqm,r5b6JAL`P)MYH+USBi-`1G*B!c8mQmq@PGI)D0*2-aqP"hLi
-FXPr)e!ZZVA%ka)V+FDTJBL#(4K!+pa+5pSC)9K$#TeJVpNrF-H@+*B[ffalK+R3
-dB1(B9QYQId@H"rAq&TE2V!2A1cDFdMJ`PHBjD0bk0EKHHU#CBr(j@aq[!8U%XBU
-ZlSDp1X9E"2TTT'eAdJ61[5B*I,4@QKA%YY*qfaJab4Gk-,k6N@Vre+JLI*qh623
-4`RM&*d1pac@LC*B-YU6CNID4fFFpA&)fU'$[G&G)q1lLPjK`@5Vp9N`4PM#lCNS
-Pd&Mb@SD6d%'YX'2[db,DT`MAr@805'5%bY9&)S-1elM)C@c#AS(FDlPQYJ#X$6H
-2CK33[!+fC)UEhS)*&*p$&EXbjDp5mU3+m5Yiq@fNMBJ*I[M6*110iP)qUGj$hZI
-88Q)JF`1&@A2'6p(5K46d3`Nb!M'0S%YTkKj4A3`TlTJfl+Eb6X!+)rdVX'41@Ub
-NSHcZY)Bq@`hDPBjqUBR9@FRmBdUdJZP)h@rEaa3!KEaaQYX1LAEYSkdDj[IZ!+b
-'b#VLf)qF1a[1k2KPC!dl4PZH4q+b)00d!HTkfL@Z2UMI5,9JBl%,ejmh$NDer$L
-FhBi*KU!2EN*9JE%MTp5Ze`MMD'*M)ZC$T5%P4,8kX#Qj%Q[`QX#H8,2bHhA'Z')
-N)CJkRc)LpFb"p,%i4RfiQ-+C6`-pCVU&P+bQH*)L5J`(EcMUTYrXi0ZaFh9lf#q
-VA()+5MjeP*[$@TYJIm-!$CHIRRHi8jEc3m52b0H%&Q9b[aRQQd8B`[5mjJdIK9c
-,p!P%dC*9!#aZ@[2`UaZV+R8##YiBMkGMh&bMqT8rl&#"+BV2GV48c``8G+Vq$A%
-imGd1b&AV[-MJTdb0i*dmlCCGIp,X*Mb06c-4%GZeQPlGm99jZe%l)@[+e23iTBV
-id+$454R"TT`UHbKAfN*HFLSmY8a26pQp$dXKQ2b"9"er"%(#Ri-!#VM`EjHBC+,
-I(+U2M1XEFaE)$q"[,VBpp%b,,Tb1'CY8$Td,eMaia%'YFMB@J$Z1Ml`KrT!!!R*
-0T!V*(U',df0@T-S"-!Z[ieD*k%N&9G'-SM6AXXBZqdZdNYIDi!Q)[)`TN`D#(G$
-llHDEG-`AffqpE%d$+%*jK`!ETm[P6mcEbQ8EZVJPK-eK2FNl1(rcf-8F[j[LVl1
-YT9j+CdBZ'*JDVSZ(d#JRelLN'-S3-qBe[ql[mdD'qIJYVLMBrhlH#QCEKB"SamP
-VB8e84Uaji3"Sia4aAeHZKVkZQ9Bqb'k*9bi9(0$H5a[bG3q-G0U$h*&*j0S+eD*
-fYDAqKXISJ%dNMbp*!9fL`cH$#YdCT!+b!pE+C%)kqbY$1,"iKhm0I1UhrMm["I9
-1RY5`*d!1h#eY)$VI@QX@4e3&p#D+FaHT[FUllBTS4LUkPKBlS""HFM#00)$ZAN)
-XrK0j)G2Ad0L#23Mcj+TPEY,iBP$!aqMJj#m)['%RT*-&#43'e&qbdIQ!+%*L`Zp
-%(lQIB(m$jj[2leU4bGMcIL8)kHH2b3U*!R,-1j5dGR%S@4C0)#F-1BL@I6!qUU0
-Jp3AmBBmYlF,JIcBS9pi8RdEF'%TkkFjKNc#faNlP4M`RBq5'APV@!SB3kh!TY,U
-Hk0S)EmI*f5@*,Jm9-#Jh#G,&1Gq1F)'Tf#hP!2p$Y%Z"&-YPZI"AKJZTm*D3!"V
-q0(-mK8PLKRKLkmD9rX,K%15EI1(G@-53!#QK9)+Jj4#'%U$V6c`L)!*1pKp*ZJf
-S(+,Q$[`*BADjZ+!a*(fPZ-PN5r2H@IApm@'N"TRQ08UBHRSD-m2p'523!rf0SPM
-C05DB`,N*-R84-L+K+R98-2DZr5'i%'')1l@PEAk+K(1J9SSSGAlE&i36L$k&6CQ
-&-M"Eccq,1L#3!24I428,eE)'GTLcSPc3,YL+YZ@PSQC0lck3!+FbDRXQ,Ul)b&E
-PFXb6!AmDF+V94'ImM&88ki,ipGa0@i6qSD,0)F")Pk&0fT50bU-PSQiaVBD%P2,
-XcA4mI!%Q-r#BhNE+"9m`(iRpPPlU3`IFH8$1J#f6PLBCf-qHeYL+C@,TH@P@TPQ
-Uh'"8ENi"eNjCP`Ph0#Ze$PVqc9pjYLj(Q6qZLU9ZIAVE1fE%TD`E2I3P4k$qI#C
-m+ef62J6h0VADr$b*,A"X05%SCBF"68V)T4r9Mhd"aDjh0i4mXX"bT29d3kDaCHR
-D#cp2HrqhbH&D16U%P[UF8M3@@'`8*qjHUV#GAmP`r$S8LF4q5`8i$a08PmI+ImL
-&%N0GD$`%HB%qcILq9jd93H0dF*hB!i4iKR"%6p$eTk39hZ0@d8c+2ZIreDFNi!B
-P+35eMle`YZV$K@PXFIm[`81CBk-c#AJ"KiMbdch8kmfP,HQr,P3lB@TT[pE0GZ,
-!D,(afA),PkMKRM34PBN`lE,S-Nqh$ZQL!`@XBTiT[(i)MLBbqf4b!GZjVf68i0S
-@!pLJAZdS,6$eS,5qX$f0$@f&aS8ahPXl-2**i*b&J1+h*YBYFB2Y9*8L#@q)9Ld
-!ap+lkXXXmK!N"$ELVBj%)J-`&X#j#,S+!!e+Z#&pqQ*2!iAC`CTqi@b[2-SL4,I
--ca2`"c8B'X0S9hYmX)2Rbe"MN5NQclrR*8A-4E(YNfd'Zrf8aJ2!e,0,imlMHB)
-8U"PEPkmNLSI!*pk4+b@lGMKKc'llU&6-i@BbCPeLLF9@(QfX*T8r#TG(4+G)ZCB
-RU[)P6FTR849TMNdT0mcpXGFrYI&pR9(mh4qBbT+,eAFXTK'R$N`Fd*hSCRSH*D+
-YQN1X[T,QMf`@,"GS$*YT8@jX`&CZPaCdH`jI-@RAAdRVP289qmICQ#8#,XMhJQ6
-)[G1!j5V(',Z@JYhbqb9Te%qhSq+G5lNP8K8Vf+2qYmrN6Sp*MHF1RVXqY(0e6%5
-9b0`R$%I8ZTr6,IYm*U+(PGlH[bcG8U6f1*!!Zm*B)$NbrBK"5`m%l6eAN!"'bD-
-@BB`B,lQ1EdS@T14,)8E,$TpJeaH,PTUcqYcpE6#fPbjRk@Cpmc&,Gr%*QHc($qF
-38S@fAAJ"AeiSkpR5kq5Nfm"*KZ#*lkAifcDYS8Uh-lAFk3@,8J$p!hlS,6rE[%5
-Lql"AV#(l#LhI#!X(3Afe39Bqk4HaZmDZ'5GYR`V5Im(Y6jUhVaYBc-B8l`ME!8T
-Mrcld&L,F0hjbND[XlMN1A+6REPb1%YY@fHq8kTq434f$#c&5jd4(L[4(R0SULX(
-"Q$**jAB4ck1KVV68`hdPTHlah)B8rjG,R13#fdRdB(ce1EI`'r(#I3J'%-j0Yr@
-L)9rkmPb&Yl$i&6bk%dQSRJI5ASr$[GJ&GQbM(ieCZpf+4&84$,PN%#1e#%#mZJR
-!dHFHSLJ!D5r[cb@1C@mQC-N#-jlIf8Aq`r0')&PPI980MNYQcm@I!28J$5EM-)1
-pbc@F`RkF&Rml&#3B+#qFK5Kmdi9U86SA(Ef2H"c2YcI580bA2IHi$Ke-,F2A0Kc
-)-Ie63bTlfrq"IiH"qCJ`U6Sk19%RTj(qedHXlDCP(9I[!(5-+2,2Cfb*#P3(Cc0
-hdJkEl#Z$1mSN1JkeiGMc3Qf#cbUAIdB"i)#K&mAaH[Ype#(B`p-G%-VrL%%MqcK
-pT0I!AaMd1fNPpQC4M+-dZ2lAb)`9U5dZcD0G2phM%rLlbUJR@p23RUAAm(pkdJc
-U@E+c,+@$jR353k8c+ZZfkhPQc)HHFHdrqXJ@h4#jP3k))pd-([YPBVc@P)H`,+a
-SK4,*Mimj1G#)Af,F((bEKP[UriFD,iTrei*[eD$F"P2Z(`KqhiCCe1bhT48*@TU
-XqQH*hZINRPa38YVjfkfMUDXj(@),9Ci8ShqSaU1hMF*5"-("DeSeCK2kqr96[US
-ThB5i+@*%21%6fkK5TJ"FM5IRqdECL,Qk[$fAJ0CK1480q#*"qEp+aI$8SrU&FPB
-01pjkbDiiFIeSZM6Yl4a3!*jec&(bhpcVM8EUr)'Hrl@rH*d[h#Cfb@2KbljiP@M
-1bENG6PViS0HKi13((!DSE+!R3dl$8pMT6$56IbU+(#CrflmAJ1+I3[G!j'C6U)p
-XlMRG[a2&S6FF5[-hJ[4MB&0!fBblLh'THH,)qI&ri%AkEl+NeCH'lrjjjpPF,mS
-CNPfjE(!KV,aejI%hKDrZhECfdQJb%ZEZQA5aMl,[90S")Y4F"31AL!0E8I8)'ek
-UM%*FUST`C-9-iTT'(6Si1Z$(-NEAk8@Req!PGa)5VcAiKZiJA6ehUCjlIFdb0`H
-PEBeP25!E`eqL3CcRE$S$13C%4Sm6@M0JlpE(#YP!HDDa9La6T*cCaS(#JAeBDp1
-Pfc-RbCQKchqm8ecEYUIJ,'&lEM%`G-eQ*N@K8I@ciH3M`X9h)#i"[5iire8!Iq,
-'lU!+i)fhaKr2V0*,i1Kl53lf6`'fZ!-N+SII$SM*X0US00#NB3N!64Cq+EP345i
-Xq`-EFYM35Gl)qkEjekZQK!,IN!!Q&Cbe9'c'&`Sh8kb1kllV%mXD(ZQlBRRMG'&
-$dqAdl!+4V`hBK,fZ(A0K&+BRAB9Z@q%Re+f`QmMG0KH9hd6[8%*`9SH93Y!DfQ8
-A+H4fVkVR[Xd8Zq1![fEHQE@pemQS'([GNNT%lTZF3hT!YdKHH9V*2Kb)[KP6ldM
-APDqJ(Z*DTR0VRbP'e*pEj8Y$*ZD4Q%%2M*(Se#QVVib3!1KG`r"FlY9lTF(bM%P
-Vpq'`Hj!!Br8Cbb*LdZ#B8ZR,NB8aXqj#I&JMQK(lID3ABY4Q10Cc'i&8LV@LUa4
-9[i(1[5SZq(QmSph5SBc1j'A@lC3%2UqC1*EE4,If+[#C%amlk2JM[me[PaC$6P`
-9e,1rmN[B9'lji0332bZlce,'R&i%KVSCqfL)3pLA[*-F#5jT"`)3IR,dHM%V2YU
-T`qf-ZjXee-M4Y)pR1pIS5AA-#U0l)fQF+f[DY840[)N9Cj-Mk5RBK8&T0[V`k!F
-TRZDj#R+2*Y0(kD[,U$3MJ2G$-DVQpL-Ha"$G$"04HMCI"pCC(QefGQF0QE8$CDb
-HAXY1H2&,GEU8bXl1mCYRMK[iUiV3jZfC$+!Uf@`4rm-%[kQ%`FD%NP@ki#,9!"e
-bfKi2iZU&1#Q#&i260@Idp!GjIjcdkIF3"ZX)#+F9!!Zr(q1NfX[Lf(#PK+ja2@4
-&EI&mZU`'Kd281Ra'hX[KE,Sp4V#($0Hhh3ik"0dXX!q!lL-YC4r$Ha@NXZb!fHF
-R9FVDV&-%UUr09lK[hjlV"k6VGmDDfMQpjSCCIRC1q2B@F`$AXK`VrE@kNP`VB(4
-XhLLT9B4qBS4Sa"-HFGiH26Z"TX,9[rIDJ)F-"`DmaCHD'jNb*(C1HkRT!QfDGCf
-8)-fl+X58kV[[l)Z%"'XJTM(5R&+,%D'k4EP0CKCCYY1b`l8Eb`BjC4@"5%1"BiD
-RdLV3hI88bJ1@%0PJK(5YqLFA(eYSq&UEk-$3qR-*6d6b%jcF!8XZN58NBE`PGi[
-9-[Tj(JZZ5NT$IK)AlV$5LkK4d4k&K1DYQdfcRU%'@6mh@AU5$&UZV9'Pkickq&`
-U*eDB&"T4eU1jXq'Ce4q!N!"CB,P[DcrRB4Fq1,bCh4PiHhBLQq0+Vr)V5jaf!0R
-rMqBp9#PDYKV`Jc*CGahpreNB2&A4B3V"%GYId`P2&jjl-T!!LhcipmJJHUU0l%!
-K6e#p[jJ4k9EaeSSAkmKRKNBYQ'MCr2`Cj9)P2U'EmlM5'U6PY3UT5k*4i$jQk3Y
-jMC)B%MN6'8FY-qXfi#qLkKIlS26F9L6P4@fU'0bAb'6Bhrb3!%%rH'&[*ij!b,F
-!R&&p)1cFdd%TR*!!S'''c(&h59,DLaEdb(Kf@cLb(JXH)`5LMrCG'!"bZJ09-R*
-+bBSqp01rGh`DN!$)T)lJb&N2ZX--K8D'aI5kmVej`+2a[#N$R0HBHpmB5Y"hr"Q
-mBYqM(KKT`fHN5MQ2Rl[NDkBT@P'&"Z-cV"Gi4!Fr#"f@d`JGcLd4fRUk@YF$D@0
-9qm$&"EY-&NSdDJ!"5B5P`U2q5Q#eA')!3&+"*EKPM,2ID*%9A96al3QHRXpC*ZI
-+&5N+#jNB$6!,*`[a6La0(E1`BQM'cF(ilQME%XmI*8F)',)L0kRcq&1X5r14KP,
-a8##DecE&Njl40$R4M*YcE(Cd!,9PDH[LJqjhq)50)%E)(Ta*pBJpIpcA#5$X$dU
-edqJFS(BSH'D2@)(jE*L68eEd2DM%kQMkh6q3!)FB[TkqelG*9mM-LNd+Njp'@6@
-9G'Bf6E690UfY&Rhl5$X6Gd6Kd`KP,Y3IK3Cf81'a5hU!NL(P0C0`E"@#16iV1Bc
-C$b@IEf'A5ZT0kD(!2Pr0@ZRpThBU14[c4+Iq5I#,3+1@ZQ,YAQdd4*J(iZfFI!`
-UT!NL[,Phh9Z-Zriq%UC1AI!da,1BlibB%#(4GM1V[L3YQ'fG)i*B$UDbBRU9c"T
-mV+UZPBCHI6$&CLeXDTdJcFm$jCTHJ"!-a6GF`R2jYX!mej9QDL3A%#2FbmMi#99
-5(5H2Q!3h@1ZD8!4aICXfJlLU"@HXUMKbp-[A9#G"TVF@%U2$YAh9-#0i"19pCT6
-MRCb-ml8"e*keaR%%4i6GiYPI29c@pH1VL#NT0jlNa8ZRYrbq[bJ(U#(da@[RkJQ
-(Ma,bIf"#-i*K@5b)VU4,QGQdhRRk41SG-UPbN96NDp"%kdmL5YpJaFGU"eBUVpZ
-9Drdq5dqhiSeFCq1fG,46amR6D002-F2LPHM+!CpBjX%rRMFUXH`!#pUd*5"9&GB
-EX9@F,D1[K#K*#X*,M$39b*Eq52k[Pk3QEU%KLjZjD4%ESA(@M1q#eK1qaP0FpPH
-`2j)p10-Z%(k&5f(!mC3hIUA[e-SkbNTcfJjk2-TqPB1bUqqkI[6erFSQi$ADYG,
-&CN4hm%H(T3fhVNMaY'DEf$bBi(Sr5kTacDkTIpDD,Vmq8NP2$2SjqNPj9V8cm9"
-j4SkV)F$a8KY"'(%FP%8$F3GpppZ*UHicK2m4`jr1"HI[PC,d3NZ!mL"c'U"1b!"
-eVSaY)YDj(@PSC$99f1Lj9Rqf+J@&8%D4cC08KIGfS'MeURYYpQrpXI(JK24,9pJ
-432aeKL@a8MC182eYU)aX%1)E+3)9ULU6HqFDhT+3!2b9Rpa#h0"lHB4R&hCGD!5
-LaiqMEmc2-(VQ2@P#X"%daQ`15cQG#FM,U'EbPG!VpX90kHNe%6U#+!!F'F+RTj%
-M9Zc*(R4&8C%9%Ra,-M4,6Kp*l[0VX6'CM0Z6USJ&rfqYR#pCGHY&bL4$RRGG`Vp
-aL$AE'GG"S4lXK`2V*$5lm&Ib4V*jFN1HM[hfNcS"8`G"4H@TZV`QTp3hpecGrqa
-dDZU[c28ADS6U9BNp03XZ$bfVU*kXV*!!i1Y8p!6Tfhfrb0jjHXJ5E2!AAQE9kCQ
-N"VZKmC&YdjSTA0bM06e60M'0@L-b@&kec6T,K3JI(Xdj+Tm"eaCir#+bYAXVHI3
-h2R)'9Bfq-D95lcb@I"XQG!-KCq6(meN%$GP#,K2-L['Kfl8,XRQ)B23f(GA)Er,
-PDpB-[)rPKbCRa-,XLmL6KQeN[2(8ZrVGFT3epD8dR%6bSNb8A#!FqA9$Ej-H4kT
-K5aT,BTXS*1jThXB-pqZ*EFU3!'A`6@GY5SM0j$@RQ6K6p6aNi%0$G6J"GVMm6pD
-pe)Rcd8j*)he-UPb"IM#6B3l%$+kcUrePhi%d!(9X#CRh5"G%Eqcbake0'l%&eFp
-J34h(1[#BlQ+kB!I@JDDD8ZV8B6IVM"@UG,QGdijH$F1k2+9M`EI!&(`$L[3+#'D
-I6crX*",#1*@FPfL-Ha-UU$IC[bY[GXIDUiJ2*4"bec[i+Q"IqF!@km0qqm3-9%`
-KiTqkI1r`2-SP+Z0hM(A#dfNQ2b5@!`a9jN"CB#V$GpF'iBNJ$b+C!fTEkYjmicM
-rYec+r4&Lf!m,k$[*34Uf-A+U%a[ikSUFX"-IRH6XpVV$"6!KG1l2@qLk)!*"R&J
-IB%Hja1pTAfQ5Pbp51[Qam(UJ%jP(mYAe#D"[1D-'4K9LIq#mVfphA`EehQhEGIK
-1eI$Qm4ce`0Fd$MLp-LBC@#8qSZVKi,Z8A!8Z'4P%rh5[kk0Nj#FBU$N!k2U%3A3
-rPfhC0kU!4c1Gq+ZkLb+-T(##&-VecNUl*Y[1fl#[MB-#qNMaZ1m,"*J*GII3Z2N
-TVQl!KQ9QqJhP$KfSX%pRNbMa+e1,UE$(ck@[ZJ8$edP@R!AF#S@4PPF0'&'(GjD
-5`pA+cU#KY$c*hDS@dr94!e+3!%AND-0+I(5M`4UXq+05I&TAcS`d&U8B6G1LEEV
-Lm&dkPd+V-)8)$eM8[hpd(Q$,5r![+PRd6AhA3bUClF-XX8QBleEQ$9-'!9,85F&
-%9(M[BdJI%2"Tb24A$D,*,6DlXjqUQ`C-&A9B1'2hUJZf"K2(5i%6I!Qq+#G%V!9
-GII"-MJbcb1l5@F5A4HlQTQB)B*bk2$J`+Dm&S`bd,hM+3XFdf!d0'A1a@eq*,XM
-K,SEeI%m[-cT*)1QZPIV089RcTl@,(3ehcDK*D81+4bICrVlXVrkklL&&h5'K$'j
-fPq!KqU*4([+0lQDSCmTaS)[k-r9iharrb5)3PALLGQHUI%fa%2VP0#3*j+r2hiZ
-PRcLa%-#V`"KlGJK4lN3AB)G!jG``3%(-#015IH+('kKR1hi+AV&[`&"X#0EU0Iq
-FF!4BpU0@kl9UZG-hrd(CY&2iU`[l@50Z5pCUA!#r[HFKYjp'%Lh[i0S)jH#*pTY
-NTM-0N!"ei&+M,&!F0RSY6P'q&+5BY2!kL(VJJM4feLS"3rSiG@QGceS'am-!L",
-FHeda9p*8V#SeNF!`#Y0qYMJ*,hZa-Y`+k"kjQe(,RT90@kp,`m[EA9HD*+16Mep
-J2A9`6%3eASH2LEIKMckf6RlR-kN3r[I0PYqaFK$R8l)dR!"S3N#Kp!Z6(KZK[Pd
-HA+a3kKfPGH(j21FPZ4MXPp("NPaMD@qc%p9@3GkZ-3pjPp+ilSNN%&PL@TFh&90
-T!!LFTUfJZeiVfV#q42TkX2r+TQhIl[-P9!8T+l"a3,1fh-aTAmi6Xabd,&jIEYf
-T%ZQ+C-$)INQ'JGJ&SHMJG8p1,jY52DDqEX-2KER!8B96+V"%Jd+*[YkKkJqDFQ'
-S'q[&ejGJJHlZcaiLIS-X9Kr++R9XX`VMX[qc61f1SJ!@R%qpG%HDSZ9HPcUC6G#
-&'(Gp%cC3FqJ-2Y*$@baMifc#4G'%p2Eq#%a[i)&#f`YG%ebGML"32##J3GhXXPP
-c,EXKUpL1'R"p!Br`-SGaQ[KaBAF!K4#PN!3"!!"&!"#i)pUKZ#2DS3!!1aJ!!'r
-F!!!"-!!9liJ!!U4E!!!@V!#3"!m!9'0XBA"`E'9cBh*TF(3Zci!ZH'eX!!"c`94
-&@&4$9dP&!3$rN!3!N!U!!*!(3X(8iXXZp(-krTf8IY"Piq#rik,"FeHi09PXX+H
-qVbNSXImj5m86%'83J!02008HiH%4L*(c)IEi3[$9Kb@DaNZ9#L-cE+j"D*)*rmG
-r(q0I)pYVB36,65&C4R80PLm1C2mB3lkV%ia3d$05+DF9T9(2i%Pp,R',&KYJ5,8
-pj#*e3YhJ#L0Mf&4Gp4Q%0'T!3ILQ#B-T-jY5j`%ZRqjkrfZ1lfpfq)`E8jjB-8p
-ISm4Ip*,XqE2XPr#qY-K8-r#P[N'(59M%(GA+I*(6##2)`q5bS5'#JAp@46CK9(I
-[J4*chDR4c-YSr*[Y3J3i$8me-aQrJN4@'NZA+hXiDl3flG[-G[8UNf&h,Gr29Nf
-*K`L3!1l%$bUl9K+i(`bpEC[Mc`LKjCmB,L'X1ipjTEqf,FM!f$$p6C4,@h+EMJb
-i$U$6@S'459-K3`pQi0bmDcVRLSfIJJNp-aDhkif2D1!4@Kqm!)h*lqP4eQZ98EU
-"*QmTNdd++&fjfqPL'3p'*DG&GZ"CKf!T%V$`ki1X#eSjLD&&'D`F3PMM'rJ'@@'
-hF5Z05'cp%DmQ4a+l*-&T964*"V)AeUpmCpR2h1%mSMF(q+-'Ti6G#E5R4q%"a1i
-D*-E0Kbeqc&YI!p[e,ZcFpEm'9D+(Iq#bHE5T,AD2@Xf#%arVJ@EGdqDc5""D%EN
-c(ep%!9*"`h@iM,Xl*I5MPpEe%Z*phC%ffD%B4%k4l'BBAf16e1jp!qCLJ+9i6b3
-6qj(%hGb3!+SI*rHid3rN8#ClH%eLG%ST1Xh(&`Ii$pi%ZTSN2S""dEL2,3)Z9JU
-9UA51mhqh,DYD$X+#`[qZqXC"Rd$ejC@MU`eaG1M'1IJ9@!@,rN9MPA'-PA8$Y8#
-ILi$`@eSpYb1LN4"D-b'IJd'5@'#hEA&MhaZ4'SSLLISbddS##T[rd+Jk5L0T$A%
-"m$UC#S1fCHaED)hNjNf$bCA,04m83Dl+!!TfDN*CY0LDdmQZAf'ArmUG98lIBhC
-JEJ9&HpR"2LN-dLSe01V"E3I*&pl-3m2eh1Sb)Dd'[lH0HC6QI(@d1d25#"8U+#F
-#(#&2b'L**[Tqr9JcJ1a-$NL1$I96Ae+'Cpp8'PPmAk1C&LId&i[[c,$H%$MYZK)
-`,k3U-+'U5KHCY)`"8'fQIL&'jIljFj4jK'hiEI#8q9-Kd4p#`"*TUcZiBUeG'Cd
-NB&c[VBQmb3i!1la(*QINT5i15"bR2PmV0$(`V`0#RIY[KB&'pp#8[Aqpi%$&8dR
-D*bpI#c9b0#Y+!Xll+k6'`EXZM2ac"H+j2drQiC!!%QeT1N!*`Ci6C#krmAPl)6p
-4LND96"hB8%["-3Rhl[-,0lA6[QRh((GX0BqXCCYm9GcT4J&kV*-Dp201bp(fP5E
-p6kpAMfJ-HBVI"![-U6qbp%j!IA`UM++9Ml#HEJRZeAC6`SDI#KlFf`4Vm5$F&UL
-P&H1K`LHqaZHh6@m(GA$ID,)KNfD-QA0*jNj5$K8Bmd3L9rpd%"9A(('RQ[kq%6b
-1dLiEc1cqK#i2XfTrI5)JU"+!S$$HM'rr#1A2j*)N%jh&D@M0rL@cQ#"3hBr#SI-
-6J$Tb3N0"`NE#'JQKY2F'r!)aGYq-pL-4MGfA0J$L`c03iRf4"1T'd!c9%er2XIi
-qIq"e30JjT#J$FNpb820IS9-4BdN3AR@Je6GVeFh@9T0+pll%L-DXVI%#X)NVS2R
-`ZqJ$6+*EAVNXK#bb4cCk+8aD3d''l2@(FYR8IR&fV%3V8JMG[%b'!*01'CJ(F+l
-m)U5MQZ,(@T)Y4NhmqPL`qfS0EHl@32U5NreY-X8MYIANPeG0AU%hf!eMD"Lh,S6
-6&6$#,!`NAJlG`rGVL5+DZIX3G&1*JrX3bTq5'iB4MGjGFe#fD'UP2(D4J'lS+@R
-3DRcPqN,$SRch"Da[Hb6!GXM+*"bQa@0`dl#GFhLZ!%la1,TF'Dh[&TC-mTAm+D"
-R"18K+KYe@kB[Y$hBp$#41T1mlJFb83q'BH&H@Tc3KhBN(D2T&K*aD&RBhe)q0c5
-k1FqPSp)EF4Tk%Df4IZ)BG!fMCQ954TRK19d2U@&,mkGd'rdqdP&ZYlD#(9rAeYX
-`Z&0FM&`f!24EG6SdJSiD`0,%eqcV9r6!LJYMpqDqP6MT$S'UGaMU[&43JC3f1Q'
-LidP%2VjJb64$'@2&"(N3Vfj!1Qe$*VS@jdFharZpFE*!!IcM6aecDZ+@lE@!iLN
-K,a6fZH*m[,lH'r`91Rk2aBr(0X1VYGXe,9mN&,1U2Gb,C2Sk"L11F*'@`"@!jh+
-M9kJ8%a1eJK"$8rR%lCC9F5mPC4!4S!+VTh-d8J2$G,ifVAC9HqECdXm$*r0%GBc
-IFA!AJ3)ej1%Ri4"MQic0kl2CmDYDA4i(6)Qdp3hEmB)M+i3R,3d(Ghd%Pb+FS%2
-qjbDFB5N!aYrKY#f&HSGBAYJhY@hJR8mHTr!RjNdA$C5&eXla1B[rEUk`)Nb&Xqj
-)55Eh5UN1!"dQrN3B)D5)H"ZqZKr1[-Y@Dr+6*F!4BJ&3@9Cc$-*9jlT&8+-A&a#
-KCd'&2hN1Nl@VpZei(a+SF3CA3%L(H8q3!2Dd2eQ@(k$5GA#C@[[ER9(#@C9(*%c
-1k0&(fSKdSHk%CE1ZCA1J*BR2'AIadGCkF@5rikr(SY9RT8TIP0XiU8)3ZPk*UU3
-BTP9hh1#+J[RRG`QjJpZT*NYMSYLr1T,PmQC3dIe5[p&X9QbGKm+b6["0YafcQ)!
-(4q@cK28qNcQ9H&[F*Gb@Aecf`YV'2ri#qC-cB!A4+X20U1D5EekA[De!%Bf-MDj
-0HrU,dFPk`1,C#eUX[LeE1GrL0fMhYRF4$#YH1FQA1E'JiQj3Mh8F$j(9)Na[mhb
-4QiP%MC@L6`r"lDlVR*3a*H$%c2pC'P,@fjUK'62LN!")-VlCR+TjM2`"9RYc3Ie
-[jUDX3r5@b-&lHD[CjK6*dD4iP5Q%fr'L[`-%6"[&I)+f49&4`ALCj4B)*"KFK!1
-Vj4rLJ"!ESPadE0YI3,eERRVe*M%TfP,#i6r)-!lEpeMk9,0fq!'8)EJ$1!D+X*p
-qAdHkQE0cJM@UiC`R%kI,QMr+QM''45)$Krph*,(*3Ia8P'IT@"T!HHK3GJqEd4"
-N(+lTKJCcpXJHh`"a&J,QTE(C8jQ4Yf#V$&"Z0I"2!fl8rZ13!#c1ehJqV-U)3d%
--BSS9hPS!M9Q5LcUE$N8"l66hK3U'RGKm&l&TDm*&1!P4PQlYbDGN$1BqZaG"a8r
-53MTS[0c1TK3X)aX#DR6SM!-Z2,a&iGCQJ'@$V9#C`dfZk4G()[aadj!!-KHem-B
-GIPI(2FSZHQb9e#5AC,Dl1$9re8`k+(&"r@VFl0&f54V$F%c6E6"(BZ!hC6k'PQi
-4H$Vq@MSH*AXT(b)(e$*MN!"-XpT9D,G25SQ$EGiA[)Q@f`3@"m6jPfhe+lUKEh2
-Y)h`@4fX1AGG'""&h@ec3hPU)bVd%C#&D86D6%[YlF0&E@YL*mbFGQN"6BRK!kl#
-hpRUBleqM8H3qVh+hjXhDEm@9h!1IZaN2I4`#FZca*TAKqYCDiBIq@kJGd'd1XP&
-!-jd'FG%p69L@Xd"F"%jUYkQ#%l(9arp$2H#3!#i!1Re*28BDFk"c25"dJE[TU`F
-BjMYRk-D'(Ca'q0#NeIX5GUQY#V&XDpc!4PdZe,G&l55m6krmC3'M(0eLG`c-$Ze
-ZTVA+8SYS+$BBSDI[S4SV`k[0A8A"CGkT-CGGd61Ke8"jr8PTTaEM6K$iRh0e[&b
-,@f5[1h)2GAd1%"DqjAY&!bRp+T9R*P#+c6(DR"&)cdQrhZFVXciH4XZcfU&@NCX
-6AcR0P+ciJHcXjHm0dj-C6bC'`@RbcEca&5*CFpc#,C3-Ra$lP&#kl1XZ(k`9Gf8
-dRGl0!5&kKqbb4K5YDp2CAq('HX0[Y3RK9H8U%rf"V0M&'V#SYlm5&(MI1N`*!cU
-"`*QBrr-#-Q3'556pfD`2'cXcKhHYdLS@+0&keRBQe35"SRF-Lma8[h1j3Z+ipqa
-P%Y8LfXZYF`18ABfV&iBJNQbZ1'iidA1(RI2G666a,YZAlSULp%Ta%9QrLFHEMC4
-r9QRp)UrH&K5l(Yd1A52XQ-S&GB#aBe"d[i"[kSbIaS*c$QciLr-K-FKQ`Ukb6Mm
-Rca!c2M##l6$epilpM3dA`la2IR,!jX-jI#E2$X$Nk&BG+m)YXB$TdV2"PfeBfCM
-EqKEP*U*(MaQ(aUJ&lMDDh+Z&pZJKTbc*)&'6,L5Q`9VaRc-G)Y"Be!T!MB5#!T-
-T1bIAqL4!GI4V!3&V*6blm!23(S#emQAqC`4pMQrmQmTHf!`HS9dc9NfPiQ6[bqr
-@bS[)GK#H['m*XImbD[IJYK"r-cCCVVMal5$Ae()BVMbr-CVX-BC4FpHP)lJD"ED
-@apUBLqT9KA`Y6Nlq,mh@AE@'FdB-0bNDR5ek$rjJH0ajj64MLH%PG")VYPFVf,J
-6rVaYfVYLi&f`)'IjK2HcK+,9HEfFQ,I*ZM8Y4'c9QiSI-eqZr'TY`9m'A+I(ZEe
-T30+hjpa9l!Z[*`M'Em#I,dQEYCKZrM4pdhlY2YTXDcbBJRqebDk@RP'`J(FkGc&
-Zq1JY[b-3[-RV6,4T,PqVV*+QejcB1hMLri(+L$pM4#h"QfIaj%+XFK$AB69a(TC
-*Ef``*#EkVlck%85ck`bdGd9r'FDBfFi'"fKmdTeUaIH%A8+(qCaBAAFkV%2PNl#
-B+*)+I!KX"Am'1M(3lTS'CmEPI@bj@S"#CicPA`K4lJ&)NJ*X3c2(DV02*0#"e&Y
-!l9pTj2@I(4Fr6hk-F&01-aRq(qYrrj!!6bESB'035kQRdGR)idH,$`m-9&-qRj-
-mli$QcAU18AfJiSrB[`D@[6pPpX[6)k`NMmmKU,k"#G@F6me!"KIY0aDdBd'EJ"0
-)dpb#M4YPGLhNXQKImTdABHacR$jU2HUVmAG,XI2rhmDG#$d!!c3fUCI3Jc8)p)k
-!P`AK$45Hq$"SchXaBpf'b0H(F!YFKJS9j#(@ZfA"keKF3CdZP(lTfLTA-djYSU9
-[[-pB6YaXq,9Y8+qL"N(qpMmlM%EfeLV*Ip-I1paKGXkK$5*'X6k-*fp+bpp#,&%
-TG)llUX8XX01qq9k@P(FEb@[-"S1Y+K1'%!fh6P0pV(`q&CiEllV3`R0lN8*Z,Ac
-$p%BE408dhJT4`iB@a50-P"m08#FVkV`[q@#[l1p@bmfl'L&C!rrH10&)*arB`AR
-f2Gd!mE*&!KDXEF)hXX@bPejHcFSLQm%UJ1D9+,&c!RUDiDFk6NlUF%NYEF&6pl-
-Q!#+,E#6L)h@-j'MpAl#UK(G'l0k8h+A@hSF95mZI9GerZ6NPApph,[IlmSXIR%6
-"ScBe5Ief(VmJmFj&hIV9r1ML"+3-+1fDF$b2brIN3QBU0Q(L$KUBeE8XcNm'+a6
-A%rM5[i%jcr80UK`hX@Vj[,"0*1)4KVrE,#4M*qPEZ2+#(iRP3d2V`C@8"m,Br+T
-C'LH1j"0X-"DI&%B-XC3mk&qd9[dR'K2[0eea9J-Y"()Xh"0l(`jKH#DK@0Aah)U
-iKCCaF,bZhp0!)MULqpV6pM4S+fHf)&rfJV(G0``"$&8%a1"NaRKZYd9MZihm2fL
-)dp`CpE#UE"f26MX1JK`L[i"TS%UeEJ(Qma2(ikKLU34&T@YXQ%c8fL+,if,*"dL
-4KIR"kd(N09IST6d-f-,DX[QLN!$05TM%'XPScN'+F'8q#CXXPPGc"jPE94VCR&C
-P&NqQM1Y&I@8R#dR6cP$8fb5))mQk6lCb&qB,pcAU6eZ66rFX'm4UZHam[hM4HSh
-SURSNNm3A92)+NlGQSchm5EdM!j!!4E*p[lU%,p8K&H4cE@rkrQ&#l`HmaVE,k[K
-3YV!Vq6`(pfDJ2RYbJf9NSQl*!2XKd03K'B[b6#PYdlp!fTr[e(eqUdDLF5(&Ip2
-&'0)V##"rfa1,0F2ilYN30mr`@PFACp)K6k,d4pJq)YVBI0@DcRcJcZ(3+4S@J-L
-')2Z5qKZIKD[VDAKG9eU0$`h6"jC,(KcZf(bpdBIBqBKTbY8eN!$Ar,6SFHT5"3U
-TZ59d[(H2Z&#UIpIBfRIj0I#Z+3aiB1"K9(q-GNU+bpBMfk0b8Z"DQ"(V8abXNMR
-5f@ppHP22Zq)JM'p#LBjjiC+VYG)l0l9&m,DED,la$4J-dQ8k-S'3!(04AfXG1-&
-!NdJf@%BbpNZ88NQF[i"qfrh%e99SrQDIk!%KXiAF[rITj&9((f+K)PXN!6QMUkF
-lGeUiYH999$pjCkm9$kGU&PDaK%Ur3kLAfeY[&#Bb*ld4RhhH"IIVIZA#$6X6YfI
-jN!!&b9DTcU48-6(6N!!iD+`Z+VZK(CNNhk$Pk3H%+VEd(JZIj9*JX8a+0m6hld4
-eKBNUcJ""3CUcY&9%fPFC+2FT[*dRD[D[b8E-#h0P@m'9'`2a-@RD14(*T01N30*
-pqjG&iI*fAYr!AYfZCr"RYKmIMY4+%J+0,DQMi8I3kNil'%L68[Mp[$Q($&-VbTY
-q"SD8jrU+1r8#UUIjJdJT*mP%0I*8["AF98SA(E$RXXhR+kf5@0Je$4TI#klk-IM
-*iS4'(BRG(@*cGdQ"4p"QE@%SHSB9b!3HPq"l60fE1SK8'G-0G82[I#h6mEpb!Z)
-QcK`fVVR598F*VV'3!2ME,6I5-GfPJZSNB#iEP46Z'F%BlC[DHrbXZp"+kESk(3Z
-IAC*3b3H6DmdK"HZSI[VH0XdeRm1UDB#+ZbhI%)mIcfiL(3!M,EP(1ITD2L(Kep@
-N)+H)"3P3d!66L$pBeLZ3!)i4BL6QbC,EKIITd$p,FlK-'bbe)%T#4CYfjr2X$*8
-&(RNCP#9*!$Nrp`6L@ZD-cS[,#d+-2$p@(5#YH'cMQaLQa1PMb*8aTIbhcHP"#,H
-#d0QY*aK`AV[MM@-)B(YF5bR,Ra[pV&#dmlS[T3mS-8Hkf8,3kB#eUh(+e(#9EBZ
-A6[iPr0I#ie'lla+i`(mVPI0R(q4VcibXjl[1H`[k'KMrkN[aB5T9Fhmp$jTQi,U
-ALGaa0FmUHr9G&!qY`&rkQTJV*'hd4fK8Z0iFCp@keR!JKiHKJ%raGIB0DQ9'k@r
-q$lq[1Yk'5cliEd'4GFqFJ6j@a'CQkRA(3I8#kEFQ3dGlVTjNZ[IeGNC,DS-L((b
-)1r6![lTk8r80Up5)bV)R!8eREC(4AdU*`C+Z$IPd93+FP#MPJ8RD5,(P[BH)cR!
-p&(CJANqR+GNGkT(SS#0Zd1(R'De4E#2[#1M*j#HV4NVD)P@,!F[PpAKIZ*&8YQ3
-cb48ZMbDM!,YmraJpLq0@&DaalYqa8RGSL1pf+Xj+)XrAYpiLN@@1PGpk+65Mf'K
-eKRA[3JX#SXklC)[4ScJSeR6ca)T2fD)[kXjr`9r`0+Y"8Uqk6V3,A`LA%a!N4(3
-4C%pYM,dLb%H$`3[afBalFd#'[JKdC3XMN!$,(95KFcN9JY08heDX-Ti`'&6a4df
-IQl!UGjhVCba)E!($03!'e$j4aJ8kZaS(L!Phf[jI#pN8)m!"0"QBYb`bEl0Y3[p
-IT[l[V0@$)2c"2daCrF6epKEc8,%0dI@E-6De3NQ9h&QN)XlY0N54p+CZk%DVkpa
-aE8TpN!!FB6q!XMLJ`ak!cQFl!%BHQA8P$!8pe56DEG,jGKCb(V`K"1'q+I-%lk3
-K8(Y0P*!!`5elB-m`@D-qqK9#mAVB`FQC#N*33d1[pjV!)ch@)1j4aDd%()LKaLZ
-!j5*2+SY0hb8IT$$F,3Ef'X+BD"&)RmIDejh3T&bb%qFaMS#PN!3"!!!r!)#dSD1
-fZ#0piJ!!@-F!!,L#!!!"-!!21mF!"@Tj!!")3`#3"!m!9'0X6'PLFQ&bD@9c,Xq
-!!!"!XNe08(*$9dP&!3$rN!3!N!U!F!#3"N,"e-&U[TX*XY+6YAlamJKQZS(1"N"
-RGSJ$2JY`9L(8jLldKr!KEIrqiA('+SKEH-lJ$H6Qc3@D!XhKHQI4#BF(daA$k@%
-2#p(X2K%3Q'$XQ$qZhfVM%3e2p,jHD'c30qqe,**l(R6PcR!EVjM&DSifaEX"KH&
-LJEqqU90djX11RPmaIed$1D$AmHL("J"3%I*34XlaiDb2Xrj69NfEL5Rfq@8YDYd
-MeFHl`eJh!*PF-UP9r#YL!4SXfU9Jpcr+E8MRQieA!+KA4*F!JJc9p!ehJpYm4*p
-dR'[NMa2"l@+dYr%T,CGA$YM9icaH,*BKjjJ09'6)"M)l&6Q2,pLqPkDhFUZGA)L
-3!-Kcbk5S19rY6Pd1j'J[5FYjrJ)'#(aB1GqI!aB8CAdNrf)0VIY(qIr#K#P[hDT
-ki!eDcJb!bLe@Bfl*&FB1NB`GSa@`'JYTi%$RjkaC)8&VI[!+TiL#d(DL8V-@++r
-FeP#C[FNhV4ji4X`R640d5b%Hd-ZXj48$`CA+R-UGV5P#$fDB9ZC+T0cUY8cJJ"%
-f,"MX&ibNh--&Nd)FD3RJRS`#JVS,RP2prBi$HrYffUcUlZ@elRa!YQ0F#'BKLjU
-F68q"X&eJ5E3P56rJ3-#i!&$1G[D3!-S#kF[2f+r((*K*%eiAPPX('bl#69TVVYq
-lGKP-#j&&eq!9jRF`"ff5QhfBXRJaHL&CX1R3'G1B10LkIT3Z$h`8Kq*)U1-Y%FE
-8aRq&-d3m-mZ69ScTTJ$f"6i@,qcHrU[(KA!5cKAQKk1mpXI%28&)hjM8!95Gm!(
-#6m0TmM9T@cd8d@V[NfbL$%ed(,TL)YDd*2@qPr$ep(fqGj,906[`l+IbcJlqSCE
-Jh3`ibU45QK!B2#BhF#[IT*ZRHrXVbVE!eK&+l@bMmqh"&ZdJE-kSAPH9mae,Tq1
-6T$IjL0*d0Q[p(Kc&"!r@dTISYipJG*!!ES+Hjh[i)0p'IB(@2XmcXN*9#9[iTS3
-d)1T5CkE$jqmpGD'iB*Df#)J%S$D&T"ra,S%e@bTBfq!UZ"I0N`Z"`EQl+adRLC6
-ZFSF)4fbN99H4+*!!14PH29'6*9iI0,,4#6cNj!#,Uj`l+2rVbLjKjIQYh`HkNde
-*BkD`93jSrb5GG&iIR$V,"q@1*QNY$03d9P4K4M&aL+cFl#hhGR!ZZN1qbF8Q!Fp
-F9db!%iHBKT!!LmYI#4ePU'8&M(R[%ZMa0kD*ClHheDMS9X!$$6(NjMZ'PYY-XH`
-1&p[pN5i#PXeF9`KmZSb(S)6fPm"KD'FH&-ZM$RBG(B%KI@%(AM'Y8N`B&"LUI9q
-+%ja5CR9(mqhT2erEk$0dlMJZbCNM$Z3P8RL9Pre`qK%kDrCXDk&HE'lh,D4!bHp
-@%Iik)SCi!dF$el"!9-[lF5JfqQDpr3rKFLkJCNk91*p81Mjm'%#rGP9b2U3`8hN
-,@)Yl'M)Cp0qSQp9N)XdB,NC&V2@k[hqHP0p$,(85I6XX-XV1qHTV[9XiJ9f-1!q
-r&Y2ai9(-EV`9aH)JjN@Qk3-ISfJk"ZQ#KbCUM8Ed90+DTq2cN6m!fKRll"#6NDp
-3B*2SfRN'3QA3A2%BMrMJHXVL-3`QX6cBLR34P(F[T[Pd@)36UYc!KG2k0PI+e(U
-LPV2)ZqZr[e`6YHeFN4P!SmR35Pi4MK0f6*MTk8E%DrNR`FA#UPhKkL9bMNcJhp*
-!9LX6h2l4Pq0Npl$G[MSj@(Mj@af4+e"%U896`,8rk9P[Y0*'Km,K5UL$+ci)P)Q
-65XM2[f[!pel$mdIFjJ0@+pYplRqeKCbb8E0[dh6'Zh)j$69#*4G'Y`PD0p+V806
-f1F!11lC`Cf6k5T*rH[3*cDKjdVHXL8(GACq'0NT+CMHkB,"(86RjH%HRc-ebSSN
-)l-l+fBT5NIP8J-10p@`fPbq9STmUq0)88fL0F0qbclkY@@VcTj!!"D*dAUL9H"9
-0`U)NdY'&Gib2*Vl2@KBKP%ji(3EdA6AHeXhF'V6LP3KL,ZFX&dJ8VeX&PZh-VbD
-BL$HR)0,d)L-0I4F%6lNi8ph+fjS'm(rqk%ScG(#c-53N2)E2S1*!fl#Yl8C%UGd
-mMH%0)(4k3Y"qSN%Ja+DX&FeCe&-6$IU1i#lY9,!D8U#Y!rr[+43EVZ6J28i4"qL
-++di[8C%pR()6$k,lJ4')ke25(fSl#iH[pN[T)ee@cZ(fiKF'``TFkBXk4%6HPe)
-,(iE8AQSK-q`Bm'34k*@685#Kh3!50BCG4Mace(#SX3(5AK2%r2RLZ1qaN9ZF5+Q
-MFcUCSfPQ#,$,3(3ED-[T)1!X$4*ZlpIT4`Ei9''"`NaSSQJ+2PQ*V&H9kkrSE'"
-hefPf@aXZKJb+-22"0KP1FZB-`hAcb)Z'iZSbP+%$qY4r9(l26pFZ&`kX[H4EYX)
-e$ZFAX1"5)I13!0+6@LhYbFG$Xfr5mf&`IQIjQHA+0ld39-d2XK%h%`mBQ[DGHRD
--9!AZLTM+X(Z4"H63f2Z[BER3@FALXpchkUd'V8QI[@V#3BY!j5JfH1IPQPII!(G
-#$d-VQZZ%dMRVmKQDr1U)&P8RePYQ2%''ca&U9P(SkH&EPPT8U+,2S#BfZCmp*mj
-!PFVHR"GjC9lI&AhNBl*1jESS1%Yc[YeB-B%%Uf'qD0md38!'fX&PD%#aDMlEQ0*
-mQp&4d%P*,H!XD`+&UJ(UXAQ!ec-6X2Z@F9MHZ)FGSi!UqiYla"ZIriPjN!"fqc)
-DFGZkp%*aPmSjX4Pq6[XI6Y)9,CE-#-*`UD`"JK*)Mce642!i8[8Xp"1d+e0V(J(
-0(2J@ZDfqELISmE0d,5@k0k@mFqEDd(c@Te(jke"eUBmRr`CrbAL09Z'6dih$D!,
-Up8Ae6[+kcDpp06#QEDZ18pC%Ad38,FXVR1kUEZDiKVlA[16DVQP+1@qDB6T8UY&
-BmpE9Pm1,Q-Y-VTBaD5[G2ipf,LT'GClL0B-V(r)m@#T0k%IQ0Fp4!m5)C5X-$A6
-&QQf-CCkM)R!kU$&48E1Ak,T%`hiTbfC4+R%H[&PYcZ1Mb4LDHAB3DefL[$K23eX
-CG+J0*(CaBNDkT`2kEiXi"5620Uq63D`A'+m31@@B9UbPb++m0M2jfraD5"UAd+i
-UN4+[!I%B6AVZDFqM#N-`4KP(VXPjc8NFFEihGPH+J8`-$*!!,h23*,8M*`a,298
-p`@iL2c)[XJbir*ACEX1k2F(Bde+1jUUf1[l4B5q+JD4mY)i+[86#2X"TrX!h[5L
-Ka4diMf!!j3"F$2Cce5`r-6qZqK%eP'U8ilZbVQM'hYlNqX#HP`r(KQ#LF9iff'q
-a$ZQ&CrTmeMUR"GG#`8NmjIkS2YXT&0!C9a'pPkQ@l%5Tdb4ULb4GM)(VKQ8RJ*'
-"`*G2QF6Z)6kU0GGj5eJ+U5-D4MT#C9amqJ46K"UhqE*+YkpD8%L48i69HI91ZrC
-j%&eYkjYqRQ[[)CmfkHSSEd,RXLSDA"X9Ekh-CkXf9#,+VG9)2(,ipb@@cDC&EKS
-CK-M$Ki-Qq$[)kMZZSkGE6KJ6phlai,LLaC1X`SDA2!RPC!Bf`GF,2MahEkhLF**
-1@V'Bdd6NA8e(A@95&-HlNrZ'il$L2kE`@RIXGiU*4`-PLeiK[lqSh4eI1Gi`rJ$
-2AJElR*V!&r5+aD54UQN0$X2Vq`NP%IIf8IjERD6!Yc9CdMH$6jbGpB9SYT-BJY@
-lcjLkA#Dhdq0(Tj@A2A9arr%DM%)TX'fUdlUAbhB@-Ceh2e63A2'8!Lmr[8L@UZM
-8%edSpmZm$)S3kl1UbLKDHb(22`Y"50dP`Ua00j6$@hmGH'Nr-FR1jicN"VP8BPH
-,a'jZ2C-L3N59Q"Jkf[k2-)TGV,N#)VNC9r%a80ri''p$V5!5NFBKb,UkG5@m&4a
-jkkYXlP)QQCpG*eGpY166K$0[N!#2[r3+d&h!)NN-U``'!EbQT',dVeYcm'1"VTq
-k@&b4j*heI9fEpZS*h@Jk,m+dFLZPFCHE1(K2+)+I4q(C+1+dAB8p$e4FN!#''**
-)N@J8'FSjT!&M,I15&%4HV9`bFkCJdkI++KkLFAXk6Njd-TN`YiCUH63Qc,CTDm9
-)!`EaF5aV&Q2*%pSck$fALEbh0*AUG$b$mb#eX6DP6c6-hbk1,`FDE,GD@36qM4j
-bG,c+!(I(1PARBCp[8G4(UeVeB!Y%5+fQDS0*b@SBHI2bJ[X*SlkKkqXFPfeV'AR
-rD`[0M'H)(a$APST1Lk`Bk&p&Ta[1(ThSk-GpIMZTNXC)T0Y,V@p2M0QjbX41[48
-[rj4-m`5F-"`9NfTFjKRFQlljSrj6!fYPDH2+!lHM2QSFBlqFZEDm'ff-LeC&&kH
-@6Apa5l*h-F'a$G$q*@`H8!@i#-`@iK4ADl%ECd*4J#EbX#)R+(`mHh(R4f6h8#@
-qTaMcdZ*5'UiFbVXf3FFEd$Ie&YZYTT*ZFV&C+e`G+"TBeiJ9eNPI(k1#TIJCYqR
-X%l21GDp1p0)6a*dLHQ#21)H@TC01%%9-P@j2r"-+jAiT'1LUEG8FI4-&ab[X-D-
-TS4c@@je!8Hq$%Q-LH24kd@M58#ZdIhMee`Df(Z(I8!`JIQ9Br-[+%SX[K1(12US
-#62U@Yj1)$V@d-G)#i[Td[jdT4BK-,C5KB2BA#[Q8!ekF4TX95HI8L&X#pARRRc)
-ZF8*BplB0Ercb2UcP`'YP29IkA@3l"DA3VrEJrM&B,fi+)L8"KT12JL'([Q`0FrS
-6@+mZ'0FGi1NIhIhDm%UY-38b,,3HBQChpTJfCN,lk4h9LCKR%q1[)3j)3@9*3fJ
-&+0VXGY!ZE#$4e+cQ5KEf%Kq"0BJXlB%[6DKmU2YaH-GDpq8$)Cf'$YB)36i1JcU
-SPL1r"-T2)pE(85[eT#T%L&K49C5G(kZZlY"AS#2K5EM$K32m!Ff66jJ5rh5+Ui3
-fHC+P,#XGa*!!T50pX)'%4k[iK'M)8L`2K'JRf,9aqV2+SmcUX5QYUkBB@(NRB"8
-m-3LLC[a!R+qaQjHA2@br`Qk*a9a"kSjmjEmF"%0V6"PHe*C'K#f#1hRJAi#4q#M
-QQ61Z9+!@)I#5Zpal"U*hQlGV)Ll-Z'aI3d5le!V9c6)BC8+mmaJG9GJqM1S[#ZL
-8(1@![M[+aMeLZ`ANM08f8F1L3-6$%d&p(5QlRp*$,!-a$'!Ze!TP$")`&fjBj!U
-UYZ8p3HiQGTb0Mi*F''E&#j(qkJC`T!3N)iS0*!B4!M4AY2[MraIAPlH(JUQDR5S
-)``p1lq"24US#j3F#5)T8lUmAhdG6aT(E69[[@XaJAqRhdG[3Fq)H@N#C"dB,IkH
-3!1hb5kf)dQZ4HARGSiAETbr`3(,$M&,Gj,fXE+L%+&XrQ'BjXk#9kED@EMTb(+a
-%&,Hd1QM@5FcHTmZA[Yb8B&0F*QjS8hP)JHU!e$FDpi2&1%@,SJ'@*K9pGiY!AQ`
-0kiUdX8(XC$,b%B&%[LIAMlQ4ZX&m4aA%`he8QJqqajhU*,UE`3ZZ44B5cKCK5YA
-I2Nd'B$`X4FfZK0,4Pc#)&leXL1PcMJF2U+[!XRQTLhLqXP4e$JfB%Z[k"lqQTEm
--0H2f#Kfhkl(R393SC`$C6aBX`%lP'42"4!8&l*(#rh)UiKJK@mKL[R0T5SAFJi@
-*!S5dRh3jMCZiij-F0#,!PX5jfcT#l09dSZ(S9KD22-1fhMIX3J$SmQ[0m60"h!F
-NDU96EPi,JR`JEdi!$CbT4Ea2cV-(ElZlKJfqSdCC"NK5H`q1"(5m+A42KmEG#-V
-c!%"$*@iU-ei*S%Ak,0M%mXShKKR)NmIBHjYU),&92RZ*Z)C-k,)9#E#4-mS!l5Z
-kQ[GQel3$FHN%ql0AX90r+[iEeIj5!R2Y8PeE2!a5m"9JqVI6P+k2NYJQpqfqLcT
--Z(4fmMqrr$Y0N!"m!I*5"'8bM1A'RTRNfE%#eIB#DG#1m8`me!HG'TY+p,3JF)r
-1i&IUjZ(f8+$)RNSX"[S+QBNV(JlQYec(EYmHUc#950L$8KaX[!f(fY,9#S8bf4k
-1V,#R+$h!EA2Df#-qbakIVU4q$-0UNdHf[L1JDY%R3Y#p"Fq6BQ"60L5UZZ9h8jL
-IV))%cSKmHB0`5GFjTN*C-AZ,V0R9R4(aKamfccKqD3+qmdfpEB'he-@X%kAXer`
-2+p)3Q'RVjI&E2l@"YeVmF2QDJQ[LN!"Qfk*b!Q[-NP'e*h$QA@MpGcM',6Bi@EQ
-2Gq@Ql-'M$p3B4kmLlRBjLXY0HM)1aP1+Jr['YiIaDT&0Y"6b3,mF`2lcG0RI8G'
-qQiI3rXhaTVK9(fPKGA)YP8iMGI@Ph-4GpPBelX$pB,-ramNRB-Fa`2FAhM#T5mG
-lG$2JAQ8(2jJjCqQ3!2Se$(,dQK$PI)@8ALd-N85HLpjT43QkHR-8E#+&ibr8[*E
-9Epka(+iD%!cK5)J1M`*C##)HRC0feS0'b-%!GD4X$c4+'HrjJe1c5S86LMpGS2P
-e(dXPRK#&d+fQrj'[qi*pQ5$TU)m+ZlPjH"CFRQd,lq%45Xiq1iT(%kP6bLTfaYf
-$I+UKB%G"J&94ipS'$(b[*'@*FaZ0jRFNZZ[%XF9jJkSQ(A+X4EfKD+iVafLB'i-
-e%UT6X)!JdSQ$EB-F8'KZ"bNa5j-kG'GU)[-,-c(j,265-86k4UfJ$Ka3KDQ@1YT
-)CGj"rq4mp86Y#*!!TK%%ai#ABVD,Fd6mJ`A9EFQSrVN#jkM)6T,6AjVHR*TLSd$
-GG!L,P3lC9T,M6K$DrC4D1)PcUFi2b4@JD&*L-H'EEII0mb"%N!$%SJ1Fq'NR6CD
-Zm10R5h8TYRQf2#8Vcrb9'3h$*"1S3*%V$d023KqADc&ES`XTK0%B,iJX5QEh,Ad
-fYR9faC(caZ%5U,[d5+G9DlIHPPE''VpX5'3[UPjmBAcEIX)A&3pZVZ1%bF'3!%@
-T"+ZK@*-606P44I)5VaieF-0q@rE*'rS-10`!(rE*,RFe3Q2AA@[YG&!"V6TD6PS
-hX46(#HS)MPH6"3&L'II`!T&NTRd2f+f5`)-PiLh!#6Z#"C6r(G@'f+e!*VeCJd-
-8ReaBV+L0jFEljDQq3RXJ'HA`CZif%9F,pG+LCIjKRpp[5+J%!da4Xr(4hNR+am9
-Mm*qh"KcMSqNEm(XYq&h-f8MSI6&N3ClS`*HZdXe0,lcfP9+E)QIeq#m2cRk"PUL
-')'rD4kNRTM@jYq[[P#-G83Ack$p8(32-Al@ed0aL2$9FR*d1H-#K4P1kPBHX`04
-VEqDK(PZ,1(aYiXPR)@G+'ENhZN#15-Y*e2'KJ2EfdACKa9ENC!HiA'AVQ2k14LH
-+M2bN8Re5F2(G-*9h!55CJMAcK8($f$##GGMM)1YS@D6-5c)k)q@4*#8&dS!G+q4
-%p)8P5$36i("K@#ClZPcq$YQlCfEfI`bTGR1-(RR*I`A($X!6RVkNA3T[dYRedK4
-9E49)VK%%-Y0Kk5q(JRM)0CQNEk%F%%K9ZDBq4E$XmF!5p'cF2DKf!"5LPiGYPXG
-8K#64ZC3SIQ31,b'*m&rR6,Ph+Y[-Zb*+d*!!rmRj%#jMZ&HmGMd35,6A5CMq"jU
-#`+e[*1PXf3KT6(3(piP'$'V*GKdr'iDU(+Mq!9E[I6YKde"hD`0hBRL`h+i`KT@
-Ea30b(NiLa&QbHmDbaM6aUS03'Y('ipd9$24FCYr0k#5+T[Z'MX[P2cB4F*kN5R`
-T5VKmeL`$R#j%qYkXDc)@EU5#+&m"![drY,dT(qd&S[Q'@eK4jN9eCS5RLKMQhED
-J,f35q96G8pp6Ld4Ee6VTf-E%+9QCrT@QQ-,XFC)ePH%)#N1UF+Nbb2'6c(Kd+L@
-X1ZE4,Me,1F95k*cGP%V*iU%bXK'Yh8DSRNjYQq'ljeqQj(UI*DRbH',GJh,*E!i
-L@)FdFTY-Y!5bFc9F300&)9iHj)bba`E(TVEdCSP22VHp4%RR`0IiI0R9V@XI&e6
-i3d+1Y1&,8Y%SHXQdH[+52rX+0MdM,SIL`458U3Y4`YZSf2ca06ER%I2jXGD+8F6
-ChKa"f9Nr3)QSDT!!lXA-NMkh*"X-1jmeHm%%(VQKHr00l[U+SX1BjTDF'fB4dp-
-'ZXEK"IqPPk4NfI3H,`PZ'Iahbm,91EVrM)p1jD6rJD5jBU-IYZSi*GqD@6Kr!fG
-F("J3MSV%Vh6FJ0$-05&'!@"U5#,9NV[QRZG5+`&TS-Y*mjReAh#jXXNGB5r`["!
-F1BLrl%,R1`JXA0Mp31K[C&I6EaiSHZ2A0a@DH+fHDDh3BG9LUN%kU+K5bL!iS)@
-CjSVP((Q2N!#iaENkkE$fU*SNr,VN*#kIJff6UMTERIc'!pkSQjMjGJk5ZBR&k%G
-&SakX9TDkM!&eS&X,CPJ-e*3+*i-fq3IFj,k$Y*1mRAJ`pfkV34KSk9XffrkpQVZ
-Y($5di%4E6VYbHiVG@@-&$'ZjYc@JDI6"Ip3haB(`aG*Ki+Jm)"0%d$UZCrNHlb`
-JZ2p-rRpK1pe!cY%P0&pIRE5SZF1I3"+`5lRDJ$kPf$[1B%@f+NS@iMA6#Y8iVjI
-D4Xl[fD*8@H&AY3(KDIm4rPJJGjMDp&fPd3YVVfAD1J`Vm&!0rlX$U5+9`3f8ESd
--`46Z(9,&3h!L3m9f,k%0T-k9AZXGF`NA&)6Y9i9De()N!A@Li[bQL,K)X@-)@6U
-I&d#Gk,*Mk,q$EPr2F'9h3YKpDI#p$eYU)LrifTCNF`ECY9VU[f%r"fm)QmjCK3G
-qGeJEdk[KVV`r8hXjm%%Q@S#U`RcN"Sf"+0jiGBRCr)"QCJ,hF*)GT$rJ`Y-%I*[
-ZN5AZ2)KMm(V)c6$!LY+Db[hP3UT0H8VUDFN!!ZhK#TTrp6B%%X`2*bi2,ie3SAh
-F"J)JC"28CPb*DZD1bUm055qN2B2YC2AJPkfSe$0E`LY+ja`q@K*f`lPh3aZiII(
-p34AS3T9!MYpY9NCjNV*H[6a-16NAd9@lS#5FQbL-#*mDFk8j8TX4eFC[#+cQXBA
-c0L6hc1L!KD,hqJ0f`Bh8P#SbU1%(12@QI!KPijVcb5$0a)qLSBAMYcpkPGHKGep
-Ch+h4+A[mL4'Zc#2%UK"A6rdNbD8ir3PiU"FYG)T-KNMRf6UVdYd5Xl31EjF[4*r
-dX-4+ef6[AU6q&TV"`5dQZbpI`daaLT1ch8hV-XUfd2*9*bap3#CVGbehEEZ1*Vd
-i6R$jVRjRGTbaUEH-ZXdI,1jmeGIUQT6E4(G4dCI#"3R"ZFKfbi8J``fefqBMBV,
-!50ALD)i8@!X,@B,R+MMBNjHV`BXZi1USEfbQq"G(VSNQlNVhDcmGbjfbl5d6b!E
-F1CVj"IX[+LRk+qq1)H`,'Sr&)M$&Epm,*UZPCdQ0Pc`Z@0qSYl8,R!h9GIJTk8K
-,60,jRDcf2VmhGmGK54ZrNIYM2RdGiLV!Vc+J@RNQXQ3eC9e2XEdIk8DAL0hD2"5
-ZB34"TjBZC01FHl0dE#fm"0rqGZla'"ih`@c43AJdN!$VV13$BAd(Nj!!EX!aRi%
-h,)*9GhkQG+IJLe$fVkKPdUl[4i%2a%q@6(!8-PE`lm2B%CAaj'8H2BS#em65NVr
-4Kce#`iA)cJ++!2C6Ypc*N!!!DqK3)e!B2HAET1Sa`&i'DQ8pVRL!MGbD)86m*1+
-A2AKAm1i42Le6$0Kl8i8+BLX2AbLaihc&8(EZ6G4l9[6V0ikpYV`34+L())fD,K`
-QTaa-`iFfD$NRE)93ZXMT9+%h!FeGI`dTNXbhF&UCJ,#k%iN[Ce-PBDj)AD@KAD1
-(P*B08i#!`FZSFhG!k-8U$`&@F[eXcq!rcJeH#2l[Y1dc,H%U,M&PbdSR-E*'P$k
-l6qlb0pEe+3LM5Sck-%AiZAGC)!1Ma+d4#YKV@+JDIh9!Pf'a@CrdVr-5E"1#iX(
-NT&[65!@L%3X)A)'A3l$2Ej)$LYZK5F*G0jb%LImF@#[Me1dLXY(a`4$H9&j31+H
-pe&Kk0Ja$RAQh&!l"!8qU&aINNX0-+NHDhm&JZK%cHZ',CB5@BNDHT1,d(K("HBS
-c$Tkr)FEC5`VNSdBj[fa1l-,!-Am`QYqGjA+1+keL'MGipVDGQS&G%A!5`$YlrET
-CXi`FQSTTC%VJAZYG0LbC,biI'lr12#TbVd-[$"HTa$e@crk0"%hDMj!!YSM!3[Q
-)U-BkLf6d88r"6b6dQ!(C&-$mMDD0mRqbQ-HM9+'I9%FFQB!+`5C5AZX)pLl&@(9
-&BL1A*QcdRaJ*QQh"Ujk@k0Kb9j!!'KD3!,"mcFA*bYj"dEFB"k-h20LE5f'&E$Y
-DIfAfb&*LlF305V`iBmJ#JHU0lG984+%,kGH$kq%c2(9lXI%LE1`D!G`Rc(Ub+rH
-jH[KYVTL4Aqq$U`JIEL2cXT8#-98TM0[4JfcABKZ@$"$V%[#EqU84$efe-+k0rLc
-cP(H6),eGSkG-P+&dpIZq4Cq1LAm&YKUSLjN,Mlea[r"r45,K*+if4fAlZ'KhS,Q
-"-hlAI1+VbCG+K[8-@a0qD5M5YG`3cL85`A@5[B"+T@'4HPM(lk3q64SVDDrM83d
-G(Qb++#h!ZGUHR%R$53&Y(@TT4I1jr$KMd"$$q(Q3!0Z+l4'8*5*6+(AIreF[qM'
-3!!9'&I8-$RL)k*&10b"&4AM-p`B6UHE5!b4QJZS%`AZ!S-6p3rNPD#-"9Qj43F&
-AE"MV)'h`H!B3qi`644jl,6Fi5A)RBpAKQVVkRk[96SGdqb[f2UX1CKZ2Cri2[eS
-%`jJGMJ0,RID+[MdShTR2#LEQCM0V*[$M"`kRr#S5K1,LG+93Xdr2MIRa$DCD'Kk
-dBi#lV0KUHA!P(Q[&*#6AjGMSmpNFTN$b(F56Z"bR`+fF`rRGCCK(4"F&0aQpLHi
-9X8U[r#AmID6C5bjA1@4pBEk@5Q#$F#CYN!#XY"!FQ`MNYHhU2eUUVKr[X-#aFQI
-(8BS'5[hV$"PQ69QZ+$`9-+L1[T2X%[ahU(`4U8$9Z5)X*SGGJqBJ'[R+a0E"p&3
-fqBf0JiHXplJCMVI*R`AVp&V83hYeV1J*[AD!030q%9VbFU1B-%$UGBV0rUX4K"B
-4SFShN!#5B+HEe-LdJ1I0P-bkG4P6AMH6i-k#aTTAIh(`&[jN'c+$@freN3U-Aji
-ef'r)99PL$M1ZcpAPh98iHe*H2H55FPL06EX94kmb!rb%1pEVh#PYL+qR@`qj1BY
-'F4A9X1)ZSF@Hijahc(*3aCDFT3"3V*S35&hk*(%G*qNSER%#a6L-l,!0,fEr!Kj
-'6)(mF$,[Z*&#fR*S+T-@9AQF6%mF6+FG1k"[5"M&pr5SjP)%-q,MNrGFerN@,&L
-+c'kCAIiP!PBBC"eQ-4`J`(J0YI[fN5Gqm'!*%BAJh*TIpJUZ@He9bhRBHG$'-IY
-iI)lFY-aF`aEaYkh1RY1B`!Dj,G-Zq0f-ZQ(E534kN3"ViYJEfAq-9A-LVT!!+Yj
-AZ[AimZ!6-JB!#0Zb&49C95mUb,*TAd,p2ICFmN9AHAD9K*-r*N'6"JqC"HNmQZP
-FNr&Z+#i4Bl6[kSRXQXMhHB5%M0ce8ejVB[FS4SNkSmGN5JqMhIE+%BN23AlqFh0
-+#erXKJ1`jD5M-8EKM@C(hQpVH9-3d[&!eJ`rBJe5qr+kSmAU!,jQ8*LN&`P4A,L
-8m*IFCNq(fNIdApe`U6Fh5R(*hLZS![a"q6iKiP)HFCih'Br`VP,@*r`@JFKd22H
-ei#QE'1M%j%#`a)X8f3UVl*3+ee+UPU#qUI99k6Hr[a5[4iR`+[L@K)G2Pd9FK-*
-qT4BFNbCSQ,T0Q6aS2ZG8VXU8jE'mq5CTUT69hVkj4#)N-XQYdZ'HpajP,pZahjm
-k8Hl0'ekhSP,%arrKJmR6%LU%+PcfXHk'MfDI*Ea4S*!!89$[BS+I,8b(#ZE+"83
-JUEUhpRV`*)5`[b!pYFZ[a"-h-"*KNcU,'&p4RP6iHm3(Ua8$M&1kqdXAJr"XmmP
-LfV'IRCD,d,@1PPK5T532#M-6[hXKfj-2!F43NUJ,,Np,,maMEL4(*h6NAD-Q3I!
-mhGrSFpYpfq6J3m+efE@`[LR1)ZK$"pUmVDMYRckMQ!`SPTlC+F`p!jF'[UbV2jL
-`55dPJfP6m'BVj"XlE8hqb)PB3!5`BQqAp-8*E2prMFDD4&Zj#p#AR)CdDJJQQre
-DI3DBS(E9[k-K2AVX@DH5pqI6%mQ6Y&&IkQB4kaVpk8rIaAh@8KS3A`19@ibb$P2
-I`3$NN!"de$!eX0+6Q1k2#%(PPRa'Ij*CZ#VDRYPjK5&DLZRCTp-`bK`ke0cMRaV
-&T39E$[d$cE"($TYJiQhA-DYBj$RZ((Q1d%AIX1N')FGB&0N,!*LPRTXSb5(Si6R
-+"QSi@CVA9dd(#%!X'%j'9V6(f`Qip%dN-cK-h0Ga"Ldp2Ej`H+!jYhS9Z)d0M"!
-Be2#L9%&aFG&Ha66SMeB*4(FCGN$r1R"phah@V+m%3%-IUBFiG6ZC)8`mralD)5'
-k%*Amk"RCB'RL88JL'N6N!2d`ElBMTUCPjb$ZKi8M"B54LNZU[4qi3(`m6Apq$3b
-6fq5'@[+@%a&XMq)0L4[aB!D`QUH0C0b@jJ'Vr"P9NkR#0H@CDEUj)MFG2EeUF)E
-K!*'QQ4l(I,D9#ER6!@Jpp1)a0Ke8!ech,(&)lfTK$`r8k[j28pA'VJ'Blc-IB3P
-!SaT*8$HNpQiiCm*f[q[BPTb6fN5P2*@6j1+J("!e([SGIH,Q-fdi)4)3c95diIV
-981!324bEaLXJcYdl4RDeh`dql*EZm"%*Db)8[+[$)RkI'a8U(rSrEpFqB-Y)fZa
-ee*TU,NN%%3i2!kpa(f)AQP$3`Eh!J!9jc%!-N!"([J4Kc9qjRCh%eem&LD9)j2`
-#l!br$f6)Z2ap3,4lRIiCiVJU8LDF&!4!RT'pkrhj2#,`N!!i[,G&J(!TB,#qLRC
-#eRafJfH+&QX&!6YZ5))LCPLI,LG,IG9bYFJP[e`P1Mm3q4pT&jfL"FbGRLib3ZY
--&dJJS-fHcZ@j!Bc1Q2SFe,EkB4G8RcPeM4Fq%mB%M#qN(c$p1B1UZbaqMMl*+0K
-1kA4YVh`4&DYK+a*BMfUkVl+#h3!C!*GINITm*c*eVp33fYD22CQ9`GBiTHQ!QlH
-fif-0$cK96lUc)ZIqfpHJNpU4)e+#SHj'i[d!a&1BCc'CP#M"INQc3[1hHfr9L4@
-46P98+4[9m1D15FFZRNjDa553!,(aG6[Q(3BZY2i!)1&VJK2k`,`RHQ03I+AJedM
-eLfq&a'laqp`TkB#mJM851FUMj'2XkKl&0&dGb+"bA-E'bm[*iCeCYBLA"q0$$Tb
-'9&p8pEpJP2$MlLhi)DRmmj51j[XC-!RpfU#qkB,+bT@0[HNMU*,Kj,2Li813!2T
-%e4[8#KU1a+Hc@(6Ra2IM9kf0[l5GjphLdK&b-(,pc'U$S,CA`GV'J+#bP-c9%Y9
-8m3Edp9V0PSJhY3q",)PFA15iR!rhT(dhN!"aq!ehqIiKAKbHf`KmaVN%kC!!@VJ
-j12Q)X3[rkEQ[jP@jPU*MHIH-!GblddHCIKmhqJQ$"mimeGRZK`Q!F-Z*d,G5qje
-MG,1jA0Ab,Mb622%Te@T`&!,*fI3Zaq)l9!QJ2&2IEfFiarlf#N9C&9BBX#94c@F
-ZkE8eLC+@d"k"%6hp0FKfN44cC,lj`k@Eb3Mpml&mJiSQApVYHEA8EmQQL2AImbk
-C%8pe)(3ah#[U2aZE@`mEf)mZ31Ub5,P8&*c@F8prq#ra2!Mlj%SL'4Gh8lZI@2&
-rfKAA$"MrFmB%lA#&q3U&LB4U'KYEd4#arMhU6f*p4pX*eh4+%l(i6rNe(US`C(0
-UUM[d&2l68`jLr(0Dmp+SL%pm!JAbZr-Y0QHpB5PrbF'6+"[hpUHi*mbmq(YpIb(
-iB(r"*pf86AUZ-!l)V$HAl',dpB[biK4XhPiIjeL!5F39C-K"Vlh%H0YNG5@r1(+
-G,N)iGfhN'@3U8KNN-i+$E%A$DNf,$-9iY$!#JXXB9%0f(UlRSJk)YaU3!)9Q-9l
-m!fYq(q6f3KeHlAT9l1Nb1)&rMiMRj&8bBT(jp)#G2A$ab1Fp`PB)aT`D1("f1S6
-26c!6r6aRcr9f5kP@43340EDIJ(,)EBRUZ$bFB)Bp$DHrl'!hQ%Y-8mmSfIAML3m
-IEFL@-m8b)9pah0(ieY1bIBEqVcVNKYQ0+$Ap*8BdPJD+BeNI$!pU@Bj8P"`Pf2E
-QT5K*@Kb#Gr58CV@JmK2YA9$2Ifi-JQ-SHpUa,L*j)3l5J#iE"%33)#@jmFZeDfG
-5ZKdH'[Y+PIb18DRh@)K!($648I6KkdBF%kccR[drlc513fX%5V0'I8fedac*a'R
-kDTmjjJcTbpfMm4AHT6D4PqYYL`F!rH[k0)9b$baE3G1b3MrY6$$l@bQIQdqV9#!
-dFcf!)EF%VL12F'fJJYZfXZYQhZbBA&P6mj+R'GCL'dSf1-%0FRm*Ml+ImF'HHPN
-PrEP3K,+MJ0Pef+f*pS-$AH8-S2P#Sqda)Df$@rQh%Kl3EJ6QQdG"*bF9ZjU[Xhi
--ZMVIe`aD+P`me228S,XK((,kN!!0H9LGMKXBG,)(X2cNCad'D3#[jiG*hb$eNm,
-1CEkGjB@XqbSS+kaTKJ@qNm&*lJUr5QYDh$PHJ0I''f*JM)Kmlq#kPEZ*Hi'+d`2
-MqF"4+p9Rq8l6+*RE4!@AVi@3!1`8rVjR3)SG,l(6$a82Rl,e8hl8&B(XpI#M)cM
--8lFZi+MCVAc[*,"BIQ2,Qhk#B&qZA%)9FKqUXYk@Qp!TNJX!,lGd$mNUlD0UfpP
-Adh"381Y!63!r$fP0Mq)&B"rP-&@rf*@bDH9G8IFbp!he3()LEmFj[`'DrLm-Zlm
-+lai03DpBX9b8RaUCSQerK"cdG@2'[SC5"0&AL)$DaAJ9r9hhQSX)1A612C($fMR
-CiP(GZC'LTDmZf%q%lJeZ$kS5VjNKdY6dX10dUEX5-0q&`@G-DUJ8f&aNYXp[FHc
-1lJ(HBlPX!F@Vrm(X%0T5fm[0&(c*5ldY1[(X'k24LEl#LaFf%EA((pN(hIreK#2
-35Rj2#FV*[$b(1XLqNJ8+1QXR'@lrBkXLD&))e*ci0B6M'Q(QUcd3)1S6Ic&T"5G
-PPl8UpC,qJ@HSBURlieK45*h&QccXmf2fl*`[h*cfpi`M%5Cc%Mfa+N8KaMYjjI!
-q-Z9-$V!SaLTM[ZIf3IFFIV0AJqH+YNYV+aQ'j&GlmY5jS"""@9(qkjiHE%J0LC!
-!MSZ09P$I(41NerEN(RQpNC4JGLr[M$,EikU`T-UMk**Mm!4!SBPA6qilBe-"Mq-
-AqG2I+V908X6!FMT)T9dd0UPG!9#!*YXLDiC3'%6%T2ZVL[!eY)c'5*eQ"kM"9iq
-!KXP-BmMdp*EFRcD&r5SZT[IM%1JqJbP!2S1H4QJA``#p`92C!f$BEkqai'23eTS
-%"D6c%X6b@cG5)e@hf-*9PbR1qhMeLVS)9RFRGR!L4NF%`dd+bS[5ir,FMEppf(!
-ap!5qAYDjMHmhHRdLi'@%c+5-`,%YEP1rEBrmh"YQqAa)S3Ij#c1UJj+jKMASeMa
-8UcBYIj%ADYrmimbFjNdf-!c`D'3H4K!8H1Y5r@B(C"'l#k0XEMaimf-NUG[T$Vh
-$h[`pDl[3e!Vl'#C@K@h!#&[XB[4f03E-lBfJQf('f$`'$4q"ZYMSj(Q@F3Z3!-#
-&!aq2hpXI@T(@ENr!9Q2-CYDdU,1qS&`CeGdlPX,(DS!cJr#GPP3H4R8#[cQSIcm
-q,QqPHb`SlK8%c'"L8LJ3dH&e'bHRNFaZC*6j(V1SSD5'bjKSp81G))Pd,0ViS-j
-rlM2*'PmMKKj!`Irl"M1fBmS9mJ[SRDGCeVQH9pZfH@q3!&,+pq2Cae6KPVYCC8V
-jCJRL`j()%Ndp!H*&i)Th$12"j1HSG,TkeA%cL11j9!Br3NV-%0Na'`(AIdh'@,@
-M#0lk"RFYiUh,jkc`Uef(M)q#T!%bpGFKeb()L[fY)-F#`SL)X$Vlei`BUE5,VIq
-dJ[GZNmddYYkKjH"T(H%*KJ+Bd'S3ARUHV&CVeBrrkcNUlEKV*XVNLSqC5M*b!T'
-0#6mfji82iRk*JI#C$e0E%(9X,H98ePL2EVHeiilFCp,hCFIAcqQD,d'&R2BcQ8(
-k4""3jhN`UN!Aim8DXa,#hUJK9XiAPU0cXPG-AB5#mbcr6lZ82CB51ir$41b4eE,
-A1@c"1Tp(r@rKS@-I,4F1a`5,`E'3!('ir5`8AFb8#"qCSc@E")X[ejVr$Xp8bR(
-J!Q3Fa#H+0+$T5#Dq@*Je4DY@M0,j,Sd`XX5LT+Jl(ccmG-aXlc,U[1dSMNLDT,'
-&i4QES@EKU,c*ciYcq4(i&eY`2e8[(p,US+fUSRd(#D`UNYXHJB!XHLIJ5q@'NrN
-4rQUI9I6$h3T"8jrDj-+kdG2M%*HR06IbE,GfC2GB*h0`UmMm$2MTLji!Lrj+INZ
-&),G`!R!D,bb*XP`1aj9l`99a*&qR36bLT+c&LYBF-FX"@D"UPJ$)0URXSc#mNp1
-CGHTKL'AXq$'0Y$PaJQ[a8,9F9X6Bb4m8UTVI*lVK2lh0pdhISkc2i)qkS1U@**[
-E(2bfV40k`cblEG)4EY6"[r"c[JcK3@4T%I1'bNP2`rCfe"8XimbQ%pTe+kB-cH5
-mK'5%)H01SA(5Uiq$,VjZHL#Clr9181&b(AeejpS[X-+QVE5k&c8SGPrqFAA8a*0
-a8-1I5PPMT*Fb!K(d1#QCFq)Ba%9'e@T*Q8r"`0b!$kJcXAR@+&%%C6H0A$Q&GBA
-'0QjD,YAB2`'Uhcec-1)!5NqedJ-VLq4K+i8mi"GbEpr"VYUJFS0FY`k1BlaYpiG
-UNmUaDPcY1bdNMrPCP"3DYT!!AUAATp[Tbb,4C`fC5BE`5q'U'irZmP-ej&Q'!$Z
-6eH'b!X18[LJec'G8+E#J)CP)rj[,U"8i@Ap3ic`&kTCdRq84F&T!9,#d%qPc`F5
-XdZ3I'8TQ#F'bk'94RU9ZckA"U%ALP)HC@6FHreBRLAi6UM4UT'M+4q0Zpm$+k`b
-0MJ9KV[U5iS1'+NJTUcJHMDaFMbVAhIfeU@&G6@!dj*)YZr2Fe-2`8fPQ`D9Rr,-
-83Gi),&08RI#P9#2ef54kSP6JCFd*rCae(5Ke-Z(mi1#!VpULVpFN@-!,0ShSq1@
-&,M+MiqkHXL1C9QjUFIP%aYVQU2(#U#4ZRTaE5P'-mX(dh[8G1@Rc5jD2Idh$3j&
-k"X&-lM1!rR$%-qIr(IaG$pRMZ%K!hU2AqN@dZ[EV*-3[4bP2ch0F)!5Qj2$DDi[
-rT*dr@8I1CPRQea-"(4VZCpp86brNpLl2NETkcJBESXPjXXFI%(*2Q'jJSUUAkD(
-V(k9#[LR3U$iYZ`+@*lU6h9epSA2QE#!AKb!LNrleHq+DC@k1iI+Y#(-4Xb[L@aR
-kPThIX!9`eU[*Af6LRd%aC8+G)*ap[$FU0p-G(M"f858V2)afR-)$lEM84f[%!QI
-U4eNE361!ch555m1b(dD0N`!ZBRl,6UmJ2YVaKIJAT8,q'-V[+b2QSH58kCl0A#,
-EZAiqG590(llL,)`ZFXX+AYZ+#kjEQe$'AC@KE([-$G"(l[i3)2XE+FRXkTe2rXN
-N-0Mq)3AIHKTPDed,A5jH0k+LaRRiZ%@Y!MS!CJ3TElZ3!+%D#X4q$CFQNX-I6mZ
-(rqqYZ2eC!m8P@pmBdNG86Z-`"I)5!`-YNPPr"C6D%AmB`),k)ErhGhN#!@S6Kh6
-2H*KPGmZVNI'c0!aKS+!$(3+K+h1P+(M"3+h@UqLbI&Lec3`(qB!$YKJYL`4V51l
-kB[eYJF!fa'A46TLqRjJIcmcd!jTN[&+[GD6U+D@FhCp9DpVj5($JaQ)*H3T0P`)
-FeAQ'$Mqk`KCfAlVfe$pT9"2(rV13!+1-1jCIN!"'Ch"hYUU29-Edf%(UeTp)QZ"
-ZPSQ28*mVZ2[,cDSpXMd'$PmbJ(H-j1Kqh*eKjlR"c450H$3rM%+X-0i9%BBl$8'
-cBE%L+PV#E'AXB4&eS++1Tj-4EJEF4$rA5Vm@A5D,92[ULe2T+6B4E*8c8Mb!kf!
-)V+9cqeHRaFUT!6+fYGY8MGS,NH!5KIG%pVCP'm`SAZ`,$#Zfj#650m!LNZcUqM0
-+#CJLI4-&*Gr+!(cl"+@-28j2fZ0T)RKHj&FJ1+YMNC[h`jD9J32`!a#ATDQUc`i
-M3B'1LPX@H`FYSI-'i4q%arj!S+2"BXGeV&1UHP3'6I-Phmh@9kpI0ESXl,PE$hX
-)iAeb(CBCGRA"SCiKSP@0)&eGQU2l2iJcka1AEMCV)9*"X$E2iC&5MHT8)5'EY,!
-caJ$dN4RBL!IZHVmi`9MV0%-*m-eTh3N6&TXC-kqT`qGQpLJTQ+q91FbRFYkjqPK
-6#jjYjGiHSG#G`$@8D[UqQ[Spp6JV6l5FTL1bAlm@lILq5+&IJ9G-!51,1l`Gb+G
-,6&jLem!B0$+e4ZBcV-k24IYpLHQcAafk8K'aV*XFq6R'*(``()rIHRh[NTZ$rPc
-iB0(D'e6'jbECIfbZkJ(QUNj3TGT'[#h2ajST4eQI1!dm4l)iS#lB91pfLch!CC,
-bUB`TJA$N)-i6$224eG)@jIYS#22VU(F`%LCi"TAM0F-RHElQH#pB+C+E'D"T6Xl
-mGK+Y9VQm-MMMhJ$eJ!JePf)VLp'4(k5a!H[(015-h`TLAC!!qNf2ah3mF93%qCm
-!YRG#kXfrQhCUA&f&XA"k8Gm39XKie+XV)aJf3#VSCqLAKZ)6J&9-8ch[)!%Q@k*
-eF)15X6"[CJ#YQA*fh%MkXj2(lGT[8(`RP-lG6EicfF`2hcc2%*+Hfa%3jd"'JX(
-E[B@3!(V1BiRRKJ&D8hkGDKC,p%6bi$q&$,Q`@i+hBib6Y*(cG#!2V5"N06ZH'"E
-!+ef[L-KZV6l(kqH!0#lL0,6,"Nl1kdd`,`V!#N$)@mDfj,4*%HSIQ3KVch$daK"
-q&`9bqCaS4K5AGJ@iaLQcqNdIESam-B-8$9Zj%ciG4b1q*llb[M`e3%X)QB)24S8
-V1ZceULkb(3Yl1q'R!Pc20iCr4K(mR$`Ka!602NDSRGKLDh+QHqdZC%4lSKmTr38
-Uf+jLZ6a8M&Q9'Q29Qq+-1d*Q4hM0j&X&RSBZd`NbD)4Y-Kerf#&&%9Ri#Hf!iVl
-ZcGa4j4KC3BL,TA`h@0UG#kZl39Spr*5F+Z+GMD8e*MU[jZT%KZ08&MTIrhTp&('
-UA2H'59aSr,$&D8%-AH)#(B8'1Je9)Gf)5AH99MpCf5EAK,Pm+IZhaj5Cjh(b1Jk
-peI+V(+R@+ZC*IBL",[A4d%#HF1K-ZRr%-8JM3INlVdMIhD,m$iq!iZb$G0NEJqX
-@!LBibiB3q1CaS,22Vr#&,#45[!flm9!CF(a*MI"a9IrhR+RpBS%TlbpL,`1qUIB
-YbPKFIRb"9q001b69Z'5[Hlaq3Ec5!c!MA40AMSa23EcH!Cca@rr3M6BJP"TX,AC
-`$VmNZFPrhq0H!6GL@q$9EYPp1ND`#lK+3-##0aMPMNQrik+Kk*!!GDhSbELhC2i
-lmdAU-6$-*&KBkP4X(1INKVcI,2Kpm,cH1)q4Pq*!-jlP`-q1Hc&f)IV)jjq6pS'
-[lBIf[Y'#GCHRiU`qG%!hQlH'J-5I3Zd6-`6CS2T+8a!-Ta3X6IGLHTC2a@1Tcf)
-jcmA8+,jdc1c9[#2B4!ME'l1Q68%6-mIl')I"9mI92Qhm!H4qX2E4I#-r$MLX5p`
-K"kKS[DLjFY@dR[iiDd53!1"48P%(l6-BSXP%Zr(GrZK1Jlp+$aHP#Cdp"Cc&*Rp
-TXh*MQi9P[CPG0&1dT&Jm0j!!Qm1"6"LTD+V,(IaYE'VC%+2h0Z&AqB!8j*6"&'K
-VLSd`HAe'rSPh%L[QU%Ppei,'HEb-+,VmD3#49"FK3lPCQC2&q,NhKBkp9NUQh@,
-Aml+@2kI'*DdhiMe8a!YAF&8ZP8kS#KR"KdU[e`+k5BjT%`Kip9eJ*qbCp@c%%rM
-ERh$N(QSNa'!LZUZA)bkJ)N`QmK6a%`8eq`NqlbkJY3p,(hc(Ur(V[VE0H!IV%jm
-923N(`X+)C3dlRTjk[Di,G"FXN[qUHdR8d`C%LMN5m%)&XQ(F'TpbFDU8U2BI%m1
-8,&F3p*jrU0#q5RPYRk%j-p)+mIbFF0f,j%QL%SC6qdIrmG@c5jEc+A%M9[[FlX!
-X&GdJMJ+1U'R5F&[KG1&l&+Z,iDKhYEJVLel!ejDTaadaV3)d4,3SqaT5fBT)iCD
-rR1Nf&GI#m@T[GdSJ&Cm3jc#Y`jTlHAeZXPG&b@*S,m2kBNqpV2K5Jh'R$YFh"Y2
-9K,-PDG#9B-DH+j!!T*4fac0*b!c&3adJhAeY9L2l+R`#i'@')aL1&P3b%5f0CTb
-*dQ8f#Y+!KFrAA#%e9E%eBQDl5dkNHMi["'"C'A`UmV5h(A#LK`9ppZ6l6U!C9(i
-I3HXP,8"R&1@Nr(cfbBqYaGKQj$&'"KlTq,`JcV4NaS%LXTH0hh%(T[AkceBa0XX
-ICp9NB,3$AdQj'%#k21b%'D-'@"$MlfMlF9d+kSq)$VbdfSA(P"[eQ-M4!1Jkc81
-f-kBc2!A@r1FY,EYL,(CZef-j'9*JjJQ[#F`Xfq6X-q6VQ84dBGYj+*PVh@N&[b"
-m!Yb[AS4['TmDGQRGLa)$EMmb+d"Z`,A#[-+($f)c&p30D+294lIfZaP9,GQ6bP9
-VDZDVEq[RFa9$AaP-T#CMKNN*V'M$k3AYkK)#[dCI@8J""ADkjh(mKNbC)T,h-l#
-jXMUi+D&2$(@RZ-pdpVdbp'G'jF)BGVe%)QlI&mN0V"4-4mC!F2QrTU5)!Lpd)1)
-!(S@NNDk3!,bJpE3hD1H'Je`Q$+4reCBhBZ)ihliFeU"m6f48MpiKm(2p5CJm*SY
-LC%Xe`[hQa!ZK@Da+#pj1Tfeqe#bce8V'[h9AfV4!GKUN'BE$AkAeq@9r)S2)!Bf
-M,Ia,H8S55pjDmh6+ddfh)&iYDm-1GMYH#&j"%f,e53V4%kAhq2+MK`k"I@'EJ`p
-"K*pea8*TlE48GM`T'5e'&"D%TY(N853EYpjq`89*Q1+$2A4YX`X2l*GMZK$eSA4
-H`IUQZM9T8GAmeGD&$U-e,9M0B3!@ECQjj-rB,55m'h-d"S!da`*lqA8Vj0["rp8
-TC64E0)bK[cC8h&@bDY0F`-NeaYK#[80Y298&q`a(K`PCaSHC,jX"1L)(lMAaU(d
-FNrHMe8LNE%Zb9*4aD'XEIL#THjj(Y3(jH5YJKf8!Gj&VA41,9a)pdb*``mF`SR)
-j2MYFe39[4H(p9R&3me8&r55B+FHkk@MB3BP#bfPYBXbV3b9hT6)4f%"6QrQ%3("
-E'NH,@lA*jR4EH$mAm*hJq'5)ZC9*ciH(ReH[#a`[ai0rf,UpjNQN@ZAXUlZiZ`5
-A`ehdUk8BU[IEi'kFaLN)f-cmcb+UC1T0er#!hike[m&95MF,A2$Q@ra&EQ+9HKD
-j'Uf66bCZ4b!NhHb,3q"edT@icIkl$c8-88C-HEZlY3j'cFmR`hHIS)Z2d`hDaK!
-I9!j$IU%9YQQPZ,fK"TBUQ$jQBe-iL6HSHjEZIHr'XE*VQidM)[[h''RXj"&a@,J
-bG-i&0HT+kFcfd$2*(0fG&@#qYGKZcp)LR+TUCc5%cVjRrIFjKLF*)8Aem4(aQhE
-hMpE*EQf99EN)@jY,b-iiZIK34KM)qRcNkAk3!2Y9+&%TqKcC63G,1BC0kl@k9SC
-#f2p6[rV*1rU*0F11j1&NFBN59XXeT,aX*(`G8AJ$H`RF%Y9-5RdJKLk9`&Ab2Mq
-RN!#2#E4bGB2ic%I8p6N6@Vk5GYR#ME!PZa`0RG(II!lc'Q!82*&1K@r3!-5)fj0
-6"[e4b1Le`aIl+pYkb2063#mHrM2!d$1#A@`6!X&r+kb*F5TUm)ab,HS3ST3iGlR
-J%Ei!-SpG6fB![L%Y$Z[Z@biqYA3'hS`FjqG#iiRCN!#)EGSS[%p3Z,2eieMe4lZ
-4$a0PF8XN0"qCFkiUT'%PDHerL4Da5QX2,TMIc@H&bq,rFLK3)#QcSV6"2LJDK@+
-'GaFUP#QmE@feA6XYKrNHA[LeK8TADeFl!U"LDQXr&d%qJ3GLU*2PVBSe8ZAL[!K
-Pe"BDA'mQEj-EiThV`1SUcC`-laqV%V5aj3IV#$frY23"MclAMdZRPi2`6EpVT+b
-3!*!!J5k1f@"H#hKAhhdUaX1"LU!L2!V-Jq@+4%`,0R"B[')Q+Z1%XBY(KCI!jdG
-iTAY)qR"pkZITN4JUm$pHaIRZ"*U&$Fa"ISRqJkJ"4C[f(1`#['&F+4Nq"'h"idh
-kPF(5BbUjk8T4CV[I@G*SL#Alm61)X3GS!LVHf-YT44h96dreUJTPfp(4JVk+jTp
-,jIeXrK2A@PTPXC!!q"KM6MjZS9r"XLUh&(aYHJ'jEP#LGhFl[LZM-`TEU%cUB9c
-2KCK(QPP*r`f5ArY#QSSQI@IcL3VK5AfAVm!2e`SAe%YrQ#4Yp&#$d60$VJT'3H3
-8+8'"Ub#DR+Z1a3jL&6m#VeijFE1afD1SR&4kJZHk-Q+ikI#iH&Fk#F6MUQ`L4rV
-p8p'f0i0$&!46"S&lHUF6Aj8&FJ22m%akdieVN!!r4BDF##fNACEK8eIfNFS@FRb
-!Z0i4T9!894SjmlGabH`kL8VeNAY!@3S6R4J5JRXJ`YM9K`&F0pS#&!'UATdf4+X
-5HN%QP!'8FR1U0FM*@lUGM6#B`X$+a06JF%-hZ`PX@Y1b[Fl&X5cUhr9Y0ZihfAq
-@&HDM#mMKPPp%YY-B3M&A11c5JD+"*`8F6F4k*QU0!5@59A&Gplm3EjCBVS`j%p6
-ji6mj0rAS(Z16Zhk6'I%5RqVHKB8`&Da`IM#%"`SA"-1`blUD*6#T%1JFTkUIh[C
-ErrqrKjej,@dI8Y'liFD3!'U3!'2$5HcfR0@5ASiJb(m`##J$N!#3!)S#"'!Eld5
-Yp5a$J`KHlrB4Xj(Q4DfNJZi-2Y#'ce4"f8S@4kj6P[K,L('"XfHd-U3-qYV3KCD
-pb3Z3!'Ue35p8-cbf`2kN3(d2-0!E-*DkAT05YPTmP@UL52!rK*ZAiYIL-Lc$9[$
-)4#p$$Y##%&,`GU"8J3(k1*SZ+TV$+H`QcF49m)4AJCa%3EQ5&1pdh%RiC%%+-D2
-99$kc,2hb'JYpN!!JcmSfjM5q9bFG811dTZe-S[#hqHRD(VS'r$MNqCRe)aLZEE*
-MirM)366CD2'(5EPm-5b[c6&pUBh`XC0JEbM$l)kd&m`XX1+mrC@mRK6'YE%kNiU
-+qRAF'Rb-!DX'Sh@@9MD9q(9B(CJh[[3F3R"8b,@SIr&c8XR`lSAVMb+DqCNV,cE
-&)RY3RAD'ApXSZ5G6hJ-NMj)&#Kbmh#Ar*h9M1rfS,[mEBbfAEC+EIIH&XQjk-XZ
-EI9p*"NTkh8CC(hPZBb#9,p,@4Ni@eEEZqN!Ncf6k23j[*STT$bEjQJ`20D0T"TT
-k$GU-8`lSZZ-JHepEDdqkr1)Ne9!erE8(@al4VaXcm&4UbKXVq9r`dZmZKip)8f0
-ZJ$eVdV-fEm9DCL(h,ffKia!eMVGBG3Qjqb,d+%C2D5jflqj@-0`HQF("l1)i%Pa
-!ZR"T@DXUB"fS`bA02SG1jAqil4`XB1,1%59cB`AMMRK9kF$%+CD3!'"GSV4m9Gb
-Q)5r"2(2PkZ4`*Bd,Zlp6'SUE4klDpJ!dG5&cj2`#1HFb4bKq4r,EJ,q4Ld3+[-E
-q@,KQS#PGB)I2+6i(25JJk-dqI[40PjGMb,e9BU8PjY-S!RXNF(T@a*8UlI!0Ul)
-Ma!M#!FeR(-rr9@Ge8rT8cR&X6"30CMN'biqZJL8R6ek662a'19-6h5Vl6f5RE0i
-6IPc4C`mkcI#q6VjTbRKq"3I)8+-EXPL8D4V"AjIhECrTd#Hr*['PH[mIHcAk'@X
-2-0*cT&afh,f0&MjRJN$6q&YFB6LLDSp,09e@h('dKc(meGDcZJr4GFcYR-r`,i8
-[LBl(%bQmFQL&HGGND1bGV)fS6!cQAS(Zah(A858MNPK!Ce5'E%CDma$FRj@CrMq
-lMRN%d`Z%!IhVr1el(8N9rfe46jj-$DTZr(TCKd'mM#%DGBBAJ8(e3VedLmIcTjk
-Z8QrhX0#GK$4"XDQh0j*E%bT+rHS%$@h5K'*QP,@Um#iVXTrpQmQ5b41VMDi$0%H
-4&*XIpAJfI'$%(10+mDb064"5PG43jZ34ZJE3QT!!X@edA0+A1+,SHLc#!N,"pJ-
-dJl%F[68l3fNPV+[Ah[0)iIX8BeiDf6hb1PeaeSI%2%B#Si,R6ACS1h%KPiCb$`K
-KTp&bXbrb(S5S(&f"FMr"A8kk!c'BdIV$Bbfqr#8)SBcZQEIJ2GY[)$bBYG[cNrl
-!D!Vl8lK3QH)*XqXJF(I'RSc,!rkCB$S4qKKd5X4CdFP2Nq%GF4)K,)N*0%&p+DI
-A%qd@5Ge5j@r!'Xq`42F-8"I81+@#a6(QC5LCVa`TN@hiRd#j"j5Y',1D3E6DAl*
-ZQ3G*80FRH!0@29L3!&iQb3PLcCGVE-e0T!Li##m[%(J[qZP[QJ!3aD)HQX19mF"
-IT!B0[eQeZV5aP#ZCKE823S'R8PXqKf2T5%B0V0V$5+QCLHZ[`eU"hrX'LqN%i5d
-Iqp)ISCkM#ail$CbB*5i"kAhKf8F2FpSqB,JS61('1mRp0dCBKqMAr,YlDqK1pH'
-PQ@+#b2F9hNM1d9"!eUM"[jH*SfJ5qEET2fUJ(NU)$bkh!NZ,lAb)!)d$1iZXYd2
-#VI5HHhJ![2UiYB+bJ[Qhl,$#emcI@e3F!lFT0U)ED#*QliSf%$"&AD$e![cj[qM
-"eqIQi2Z8rMcaQI&*"Fal#(0ZRq*Z8BhD&d!cHlh&*K)Dr8Ld$RkV(Y)IU%c6A6J
-S12UB51T!![5ml*Jjpa@peRUVSP2IH!#PN!3"!!"$!"#i)pScZ#2D-`!!Ep`!!0`
-F!!!"-!!6bAi!#akj!!!LZ3#3"!m!9'0X6'PLFQ&bD@9c,Xq!,RKYE!!"m0j849K
-83eG*43%!rj!%!*!+J!#3#3'D!*!$E!#3"!m!3X(9$qA8,*!!8NT&S"6e"mU%bYA
-[Y1QHX&BMjQ2ahc,$m!MIA$$R'`VL@F"A4pDH)kaKa""@D8%C'RA`LF4NCHCM(6(
-Cq'LiNaR8%2m4p5Z`YAR`Bm)BX@"bF6THhaG330G5!cVEkD69VGF%!%,"e+8,`$l
-pV*PjG4R`R3eDNISlN!"qd5Cb#i8Y,r$"DB[+lC9*bYc66$Hfr%NFkmV#h6!AlFl
-I!kibBp(9a4[JB@kG4rjYTq6[59V*FIMU"U(hK'fhLKAZEF1IEe2q(,JM$YPAKbY
-#Q`*%JlAK&88iXK3%UiN*lP&92Z#bBBX2HCBblr(MfqPG1-q9%CN%eSJjfpmq6CL
-cJrLiE(e"lcq!6`fH8*J#hXRbA+jKUI)aZI#TUI6*$pe*[bbq,)FYLHHYJfB&+Z[
-'bm'kJ6qFPM-+3Y"dI"6DAe12-,5F[`Sfr6Q%80,PQc`!'2(P6ERC-lc$BH$@qS%
-X4EjGh*Q[bEc`)*dR)'H%qDdkHkh%1'C$KDk*b$dDV*`REjF9$fElUrKQ[d&4$eE
-B%&PpdQ'6JkG@Z+aH(rj`3JKS+8DDhiIFI@&eR5)a%ZHmAX4T8,ha$0kdZhIQkTb
-b3QRT-EqC`N1BXCLl2RDd+@a+3mUTf,)MU-i,"MG($8NR!iHQTJ6kajfB`!Pa18$
-FNKerI)QK("6Nc*Sr2V95UFK-&UMEJIVAlpRf#ZlpMc,+BabY2jcSDQl"[(0d$XK
-Q#@UR0UrIMcN`5Y9@YC!!j0AaK*V(Da&CY[4r%!l-P+q-(!lSV9bf4b3%pFF-YHK
-h2i2EDmQ&@9cBBjJa15JP`Sh)e$NrLZX"iNlTj[r#+@8@eAaqebY%eE!,eL9l(%r
-r,,BLm-Ma9(Q01$URIdJ,DAM6hP#$Z#*d'ECGKQ[6)KX4Z,-kEqh&cUN6ZT!!3rX
-bB3XeEXR6@,"SMY2l!9#R&3RkJXGEJL`"1!YS%XLU"`Fr9HaAbk[$Vb'G4H"kLrY
-k40H5f(ck0[aKZaYYGCJGfileS(0+6Gk+E-R0LXG,K41`4J0HGJKY,(S)8`"Vmj2
-hYhR$[@dI((9RcB!-NiM!Q"aU80ASqd8mM!MCDfDj$A%['4,$*f4pZ+%F8fIe0N4
-GG-FKCTSI3l8j1%F)d`lmAQ"@DYUkp*d%N86G#ek8*RR%9qh(ah%4RcdF)-`fk!-
-%5eaMlm9Tq2qr"YUC)N4SP,-86l)U5'#4Vb3D[ilbJFe(0X0+3$M4T0Eb1'kIhdX
-hA0P1[IKS1!QEN!!eb6,pF`8b"i[Bh6K5BJhP"V'Pqf!2N!#291e%d6`U+@i"[!9
-63m+N9hF9P,jV6!&@"9QDkcC%189ld"!)HKEEDkqr9NGB95+LTeY@%%&aI-M4)YK
-NlqYc)ZY)iqmVmF`+9$+eLhPp!Vai668U0#h28k`[JV@T,$I`X[k*F0[e4ebCX`8
-pSH8@L0`"iL9fQlKjU-pNE2*F12FAkL0KAk#8P3@$de-E#YV`c9[KaMbTke@0YaP
-VM#c6P%T&&+*$LI,4MCMXcaXm(JKq0AJ@2jqALJDL('F-*G!FdkE)RRZjRRJVabN
-dqKA4D2U["iR,!!i%0ED4Yp'M23qe`&2%jM)UMJS,2c"e81J8[kb&`E0'&cdJ'0r
-$A6ET5D9)J-K%$kN1TV3J(kiT03iJq5B6AER+mj!!VLlE"Ge6M$#Rmie5,)eeZV(
-UdCllh0)&"G0J!1aE!@'PQ!0dCDG-Q9Dm8NX3rkZaN!!ATJIpX-38ClaVFMd+,hI
-"bl*R@Fa94QFU4D9ejhYU9!18U`pY6VHITrYJQ@,9A+Y9qXlAS-`3bX[-BS*9ecA
-0!LLN@'3,eE3k5e2d#51bDjr$5!"IaFI$ecBQ3l85emcTdLpR@@ILlQG0fQF-q`B
-2-X18!58)f)PCr%5,-QllXmYj")2JbIrBJV'Ip&a2"NdAFpX$`,kUk)mG6iU`A"V
-q-8ehJ&,llIBR#DaRch$)[!fmb0[cI*L[86EC'Z+Z3)(`9Y18IiZ"aU("k$q+&0Y
-2(`1M6[i$m(T,GVM+L4cQcY*Vlh8X[1p#@QN6m*rHi56c96Y`f9E4$V"*K*iSK%I
-04rVr%2A+JP"Ql!U8,6eLL@19Z2%A8JQHRYe0b498D%b@bDi+dafFkC1TbZH99E,
-`mRHkPjFAS+F29LZTZNhQEr6`5NY+&BdmhIc8"p%q!aU$c$K[NY2+4mb#+29KXCi
-Y&pbeh%i3IZH&Dc)1!54"mZ8l2BlL#HB*1MZ*AT%#Ma1,SN[DAQ8fQ%IahNL8IZC
-8T+eDpA*#lbIi#3MJG)1"SfS)pFU"UZ@Q#,FEdrZ@R4Fm-[)UALb,jc8AE189`hJ
--"YTji6Zp*4-ELAA,)bbmIEKrBV)D$`VE%%pDap[SNeG%HPZUV"(1V'PB)PqjNE4
-'"5H(5X84!9mB!0jj)kUk,cU%LA%[Z4pSkP1JhR*&iL'f#U!,F,frAaMGb`XfiA8
-!f#jF1C`5Yb`kYTD%+9EGKijM9mh4Mc&`2,,8H"+dVLjll&%prQdUYT+2)h5JmEa
-A%+me'e`r1`M[hArd`6A%ANA,a#,ED*5NF!9M%MAi8%Z3!*)UEFT4p-TpJe0!S0M
-9HIIlhIk-mXE8@84X%!SSANf`%'kq)HILTdk"b#!B8he#UdCL%S6L9I6rFiM!F@#
-`LhF06SJ'b`&0#4SVj9p6m#h+dLN"S-E+#NQK(YccYqN6F`d[fpNIRa4Z%a1T8l@
-*l(pe*p!KXK65SI'c2maSbN`GPk['iX*IHT2IZ-rArrS"S)H[H1b8)[%mB!+2e*)
-0ZjQc3MGl`+MCT1AFqTkF0bhkH'K@aAHC#Aj12K@'`9[48l#U&)FI3Q%Q4SY9hZ5
-D266mJMT5mZF#jd)S9d!c'j5`I3*$D5')fj*@J+)Z4Y@9#DD1`'434a2dB*XGf(U
-&5CYU,eMpEE$qE3d`SPmEZp'9NbNhY9,YBc(LmN1@Ql#iT9LVbLrS"MN[&&0-+@i
-"'id`DMc#jA!LQC9SIlfTimGY)Elq8#AL41jLe-9adhmNMmVIfZl60$Y,&5f@X!!
-,S1Ei[XAR,"j5iL1qheVA`-[YFHiXGqLj6JQShhhkU63iHj,HNUi@dE-6M+RKHGL
-l8(c0H%59DLbB9kVZhU(5)4ZllqRlJqm@f2"rehpYEV)h&X[&LmMa@5jJeED1LRG
-"F0Hq8j9q[&%md@Nf$I08-Hle[)j@Kk@8K5@X5DQV%(VJ+1@ES2S&bhBrq1[BQ8(
-'"I%XkHSrYP&PShSe,jme$pm'NT4$9Hk(lk[%#pk$m6+a)dhQLjBVXcbTh6FrJfj
-HT0FYPf##pYd93ZJ8L6-e[bMeJj!!IjjM3Yj"VJ+lpkA$Ur1!3crK0Fq"V1ipj+B
-HK396h!e4bL(!YIX['jc6N!$dj6Ip81k2Ulk5caLrJXk%T,cN-L#-+QN("1GYd2A
-AT88T$)UGT,`eYiqL4&ErK-985YMP"mA5)Q(LP`Ec9ikChK9NI8+JMYd$aDdZk,q
-TcF+1pl`mNb!D2JpA",!PUI+h0aZ2m(88X`(d!#9FZF+,Rr6+%c0C@lp8a+J&%!5
-c1G"QEc2-KC),21m3p*R)c5d*3rU&m-58Za,(NXZ4GeXLR+9Mf'504LFUd0)-p1a
-2#BD66)@-aNAXd[LiI6qBUp5P2S#M`cRNX"k`GrAIdqfh8,iU6r40TlHad-`'+#!
-,Y5UJRZfKI`G$TB+0*kh#FA,&@b(r(lJ[E",*,cMJ3jS(rD3eb#`3`h!8E@Vp(9N
-0@-AHq$G((SXXIBble91Jj"IFBKpTQmAB1kQE3,$-RIV+33JBTA`0VfiJR*!!%kZ
-fS)bph`*da+0`f34UkN83lYU1)Ja&EHhaEYlG'jP*ST@MB!)mcEXQ')FXl$dDKIp
-H0)TSSI*l[S"l()D8@r@-5RjZRMj'lcfl"f8"@Z-bUkqr4I@8mZ9BNQ!8-C`"D%*
-lhi%3#a&l2`R"`A'@XddRXYNUq,9QMGFVS#Xi-lrcf6)(Nb%JVK92a!XNKMF#E,N
-V"Q%"Xchk0*i`)G,8N!$G3IRR&ffECI9F`eaQ&f$ABbLTKhGBjM1r43R''d*+c*1
-F38MSR1e(ki+m5MQ9'GN1"G0e'2bj96%r95`*QaSE[SHH*TU"hfJF'bjMYG,L&qY
-JThHkaer)S'NIBhmJeVd&)H$8J!$KhU+*UQ+Ci2K9I&2"5hB"(,l-q`P)61ciJ82
-"#(TF!&5!J`KIPpddXMC!*l$Ehc00HXhL,hCqG'cIe$#1I!m'Uj4["SqTp29$ae(
-4ErB&,bPKA,!8dS49a8K%#U4'&fH)j%HCb-b&rmA2N4XlpA!Q$!cpedr4hdfjGd!
-`-X9q#IT'rjeaI'T23EaAYi#b1c5`hqXSD@k[98lIZ`c0c-Sd+L@GEe9$VX*dIk&
-4,dPdd$dAme@Z+L1UD%3l1R)(&Q3B'rSK2lU&3%U$IXBm-SR#3q2mJah,DB'NZD)
-YNYJ@k#cZ''VXT$V"E`jH9NS2Pm&@S'h)8d-BHeU(%18dej4*VCBm1[H[laT(%09
-H)UKJM[#eK@RlUZHa'fm(Kq-c*mh"D'ApZ4EU1#M,+*EPF*Yqli&ClpA#0)&a`MQ
-DSP$98Q4"9&%Q-6!mr(kXF8643'F)l6FB4T!!bMRTb92R3'(@(8$i#3FdTS%fUU&
-U[Uh2`jT$(4(KjINdGDi6Dl'T#,Y+#iNr,"j,9FC6*#PUA'D,&02UTFk5qS[B$fX
-8[[`FPU%3*1&GGLdXFcq3!!8$AF"08GlKUVL08'MP6X@3!'+lkZY)l$LBXC!!$+l
-"i8%UY39-ICVm`V6a@4'`Ci$P)eedifadR$FA*qi41E#F[VD*j1[M%d`'4k%d'N2
-a@$ljQ3`V!cS*2e`%ia+PG5Ei%*JHIQB[K!i@B10+-Q&pG4I&@(h3)0CJb5jie+*
-iFZHcCSaXqA28+ANd+X(3F!2VRZ'AkcDP[jbV[(D%Q32NQp@K6@9E&E10QqpSSH$
-(6KL[4lKCe&a(YJPl$$NimDh1U%Q6C1TSCYh-r%UemDdCA1C`R-NjP&`Iff0JT$-
-5BQLXK0+m69Bre[Epp"e44kNiT"&-aV%+#-3Z4`Up4Qq8Sp[1NhaB6fIA+piSb"3
-qQTbir@dbTeP*fmNbJRhV2k$APS+`@18'mdGHl6jM)()pZA"SVAEqXh)S-hY46S,
-5E@KLSpaak3#8rKUf1NfXLINfhci((r#A'UJP!$GU"a)LPmA)XF9c*'-VeF#Vf8h
-6jVCcmXP8Dh)F`X1MjIUHD0FLfK%06S9lbKmGGI&P'BZ"B$CBB-RZaPDNY+J8P'`
-)P!85Ub#4[8YB$MQI@,L#LhBHSh@PRIH&Nb6lP,[(E,'6,K3hL0lbRQ*-#k,3LCU
-3!"D+K)5dZJailX69dL&kJ2A06KcMDPKS"qf+YfiG#+!F#E[$N!"KEDM3V5p!(#+
-[hF-fleVfGZ2TSQ'6!ZJN*UY8ANp"%[-hVRL(3"Bkl@P-%,NA`q`8"r#&(Sl%1*f
-*Yk@QRD2q%l["XGa&dJ#DF[-)c!KV,rp-TdQd9&rejN)MpLeZJ)+ZF#TIDLV5*UH
-2,MS!C"34Aai622T@!LrHG'ZK!fejY'fQCTM@(fmaj1rhKMAK4CkDbe#U[83V1XV
-(VlAHJDmNl$Z`d#B4L)!c8QZBSX0"#fBcX64@dYi8V0%jp@$Ea)E5[`0LFDUVc,h
-50lpIT4'I(k(d'-dKL@AddVlG*6fkmk8228qc$r9[b)TLMc!FrX-V'IMDJNbU`K"
-pqR$p&Bq`rd+h,d(i,Z1jXdph0pN[+$dq-KbiTPI5S9TRa@%&l"J8[VM1B"&j*Ee
-(Z8Gjd3p*36eb!BJ`i1i)Q"qaGc3r`e@MT(SaG-be)6(kr,@@(),'+aXY86feIdK
-6LmKMRiSY*6%Rh`[8[#[[aB-Eiq)49@b&,@LPf'*bE5U6YJCIMSqhRjG*220%1#m
-#M)ZN434@Cj)8iIEE6#X0LjK21mY'&6,PD8Hl!hDTJeNqiAAZm-Qr"Z8@JF59P@9
-PdIHRr)+9@HcTK[)r6mDP,5S1F*@i%l)8-N"e$L8e,SfA@JPEmDSUK`RSKfk*3)N
-pLr'``VEQ3'q[mLhFRBIb2F'r#!#TbIij*Y1cQk+N1-kXF4Cfi*9@0iUZAb@T2lX
-QB44IKeb+"jfSh"5Q2aerh8Rk@krQp5'eKRQ)0$eaeBH'iDG21H`A`U+P*6(L4Gk
-j)L#%8NhiG)-GdI0mX&QG+LTjY"&"fSQSJVh$pX'*bfiU[&2r'kB#N!!-f1YH#+b
-&bdp*PU,T@$fQK&AL25'4G[kVXAA04U*101F!3Tcmb8Tk4r[32E,lmJ"k[EMLii*
-"I)EC!q0TDS@A!Yq*hFd%'aXGU%V$'BVfMdHS%"cNi-eIAkKd(GTZUkB!*k!@%5B
-&!ie(0[5EFp6GSD$TaLqR1RdZ%'f"LEFq9jl#5BSrjfI)TA&C!f0G[B%N)Ck0k-#
-V+&UJf$4eIi,fLRdBS#e2CPIFJVR,@ZXiaN"aKSAYH+TRi[XaH[V9VlNf-UIC-ei
-pfAdKXQ"cdH$dTA(bH&UGher5)6M!l[,lh-8*"``r&Zba2XLHU8lNm'()#hK%GYG
-eYf,2p&NX)qfi-d19CMpGfQi89+0p)icDXFr#I&3NY!M3%(Pdr2AifG4ALGj`6De
-*EC@Klm!"jQQp+fY#$aLc@`L&+@UI(EpA(*RMfGY@hX4Y`La'R&5K9Lj6VQ@jp#r
-@p)Z9C&[9$aM`K,m-"peJ,MqUL(,ja$3m208mmFMr*#lD@pHhI'G6pAk+@T@8dCK
-C4!+[Y#@RLGqN3'VJKe3V3,mAc!803L!FQ')f"`V4DY3c"rV)044LqDmBhq#A$p-
--B"0HlmC-%'#f#4BfhDaI!YSdBEjQfd*&ZQlDcH9QA2BU(5md,&V[0%&(b*LHJbH
-rM846XlS+"N6q+a`YM3R[DXAF@$d5`h(Drm8ZXqITPPU6jk&J-T%GVY(&%`CHf38
-H5`FFJG`Km+LmT'6ekKGS[XXJdNc0!P680LBmXQ8D#02jF)CcCEdaMhr54$U18j,
-9,RYkGM%%8I'caJTa!F6!2CaLj9,3[h(IHEf(KpYY3A4!9TAV4AhAkH,6r#j+b0E
-!r*`EG5KjGKGMBrLcECJFKE$VUh`1M$#L8%MJ19ahU48$DkGRPZADAR#hMBCb$MC
-`DNR24QF2fd0UZeEQMY"6SQJblG+(QA3+*`YUAU#D!LTTGA*!f8qlF`)jFEX'Q'D
-V4hkTkDS0$T1INi``CYl5#Y2kCh)+HXb()4Q*aJDbBP*f[-U&jI8A%B$2`LVb&Fi
-IGiZii1i#TA6G5Lj+m3P51Y+Y9Kbd"5TM35%A+fdLY-X!r5Dd*9"JJdBqGk8)X2"
-![*PZ$q6Xr"@ki`rbh8(8qp"GK'[G"Ah+fcQZ((p9R&!FJR$"a""P0rVVG#Z86%-
-iK,3&b(JUE%1AjR4Z9Ga$4dUKqGjFe)5ACGX!i&[Ha$FmB0Z5qb"L+ZdRBi'@K8G
-6B*9QXrFk63a%Hi-4GXFSB-K-L$R`[KCDGKZAC4!HC#LBEH'U-`RlFh415pUCZBR
-33jkG(*R`IfCJ,Qf52EXL9TrXi0j6%+K@@5&ik)&$*VD[2Le3h#$*$d1*cZjkUI`
-M64Q&dS+D[kY4if#"KR9-m*UbCcd,,IG'Dl&qLj,6Ui%3D2E+HQUb!q&F'[2j"9`
-dFR0-A)p)kpQ,f8D-6Iai*,PBGEU@IN)P%0'8S*i(ip+*q)r`$A)`ja"HXTlb%Re
-MhVS[V$!K1TPh3IrU&f%Fl53''VNA@XdU$KpYQm1*lfpa15(dB$eM[d(!!rU,cpP
-4F+B6E+LD5fN`@c#$!JGh"m"$Xdp#C1rk4X[V&HAck-2k)m&bj6"GZqjXYFN#Vcp
-3G-jXF9RR'PS2CFPQ`BPANdL',k0iXZ,@!0fbI+F"E@SbD)3b)TDG`L1lYMGL,"H
-Z(3dHIf`IIG)#LJc3(4`QLdBMe$bQ61+aq$hG!-(k@)VCQ8pE)cSp-j*%5qh%D@m
-TiYc)1hX0Dc)r"QZjYQL,GF9#2HU#j`hQLHahfK&3`R-$Z!M3DPHQdC2Vk)Sqc,m
-QMJ*U%!hZ2E6@`qmS"H`iIq@KJib01KF(!DI0186$Hb!R(6MZ`H)#4Fk4mS-`9``
-D#`*ZB52AfRd*j`j4[(kE`P1)kL[H,'M)0D5aDXDf3q,L'ljIhXdfVR6GR9q@NAi
-NNf5N'Q23&q`S9PG9SXEZ"HbRMU@&!Pj`BSQ1JQU)*QLj9ai!YL20RN*hZHG@4FD
-RV-8T%1ck2Q*[FXQ@PPTCUN3H-j6J'm8bBQNCZ9*%ICcqr$-A(ii-Tmi(9la0i!a
-T2GI$X6a%*,[Hle#'M-ljS*!!HHf+A)p[mD`F*rjY3!)@!Nd!-(j"2HQbKH&#ePH
-m9$1'mUA'lTbPNc9JJcm5BQ2rZX,X8DXci'[jNlc!-H*2P8SHrHLLlKNAY'$aXDB
-,M9m0[P%9hlii5Hc#,"DpiiU2i)kq"-A2UHkD"KTlSiUSGIe"'dpMK`3ai8c8jpm
-*9210TC!!"38K##-3"P-N`!0"qKVkV,MF,X#085c%%(,$(Gji(ND*P@)C[ejC,'-
-CE-a#Vij%[*hmK'3c9#G8`QaPF'[Y9[(("#i-Ma8T2CKN%V-'*eY*G*)f!b(F&6)
-CVTK(@'&Aj(G2fKMmarFiUh0B0B,p[hJC`M!SZEli'+"j`)*A4$UHI5UAk5BKT+'
-6)%9EETZI4"J88F!))M#P6fX!UJV'cI5GhJMp!HIS)S1a6#rlUkRcQjZiZJG(NB!
-TXS,TVQ2i0C'eQK3%rhmQS3UdpSeYBCNLRKpIdJi2fH)SR&GamS*,3ZZaF%UHDf`
-S",lL#28QmhX%#h3[-qqCZ5,M),3qR"jf"[fG6hbkel0JL93!j0b#Y5q@H(m6BFK
-eMXG,,*Z@Pj92db(!'r1mmaq268YSV$d9FmBa45%-ePKb3'BBRD9Xl)BJ&U280aj
-e@mr[R`CC!j80)UNbiBRGb(eLeLmfZ#[G#TdcFqCr9eJ99mG&l!JL1A-r#5*Ea+4
-[)A,crH-,1q+!bkrb`Ee,i-aK4BULK42G1',!iq$XJHGKD@AC&C5(85[kpCp`)8[
-%PACEIMl@f9SHeIF4VXIKlA!L1'a%4LALVm*K9A*5!%&UVpl$i&1XbraK#12rTSi
-MkfjRNB)HC-qcRSZ%eS#p4U204B"b%Gkc*q"iHSdXEPaAHjhhakU#-9PZMGkK%e3
-#iGD'[A"jj1NbH8[(+SHiN8ih$rC%!1X$#ji(Gh0QP8qX-Z6K(FF(`B1A1%3)j%,
-TVa5TLXdN&SXe)@rGV94%1E&HQQS'J@pfrC*BhVYX+l"DBlFqB(2qcd8b2*V60di
-ARYBl4S$ZfNMY-TDFmf3Fr'-GKlZY#MR-`ZbZPki"Z9A"b0!jlC&`H&L6Y9CGK4'
-kjb,ZqhTrX&l&lR%ef[FGcfa-6E!XRhBh)*NUMd4bT"#EN!$$$%XMj3'8&Iq5YLb
-)8R[9996B9c-RP[GaX6KKAAU6SBQFD*@NkN6`)lYhq-GDU(q9Fe(9Pq2a+pC0'1+
-06Yj#b8iKXlF`9YeX!j3X`9N5Dl#FB9RY5QTQQdc@i)ca&0T[5+@,3NJM,0!chZJ
-aekKVD9'r2k0AlNAX@cS9fZ*$++(I$Id6"'$&pFcjR'SE@5U([jfUJbCbeQ[QTrk
-`qNX!0)fSq!C&8NjIcaL1-T394XZr(IXPNmbjfY)5I0iSPeY$93hG15mHZRZYIqp
-pT@VQ%bK1+U'&Z+GlSmG,+-)R@h`DC3jS0D&jT6BJDJQ%KBq$C)rMKcHRDF&+TUG
-jY8S"11YR$RBfIqLFVej!'e6)&'prA5d1NrA@)ddaLB`-ZAj1THRFhK35ppcMqDr
-3*)h)'VG+("IXYVG)UIT&Pm'KEP+mYTm-6"8l0VfkK!C)R)I3+96r+@eRQPbZ!V@
-m$,1C1YV*hN`q2CDa4C)1"hD&4j&9q+32YTEbJPD&6)9J`Ue4rlNLHQh%1!UM5`Z
-b2bmj%"+9ZUPTf%r0-GT[T+`+ll%b1[GH$BI[GaGCXeNVYHApL4MMk`GrjkYMckL
-P'"G[DF8"1(,3AE4hdTcVU['UF63VQkE5,YjfjQ+A+N&HFZX&l5BB3UbhP93C(Vh
-Q!*!!P'XcVSrJ)2MDhI#+,Pp6Z9EYT5e&D#A6P4BfHJ0XPEU3!+4d(CqjfEe+5[T
-E$%BiC0E5B6e@Hm3)KhM"'6[S3(9a"H1,)j9NG@Y5`r&,Q4BPADRA")8``@UF#2K
-6a8d,-PkGm)k+HVlLKD4+c8Lq@3T"IlRTM3aDZT[P,CUMmA![VNA,p'Q-[hTdqEV
-NUkQj-MqIKqrDX9m[6qm(kR`)#U$RaD')[`aMQiNX6@[c6HaLUKXlce+R@*mqJaj
-a[ZL6X*++!kqHjY$8#m3KF)qq-Z%"S1`b#$d!B0Qb%dFAc"K*fc4l9B9"q4!ajjC
-*N!$C%Z$&q`$!k*PB5G5S1cE!"r6-N`,!PD8HcCeaj%KHCYlFK)!GK95q)EXVC*p
-m4iRqhk@c01&8eZ*GfCD'-mXE-Laak#pBHRP@%mVY%LiiI4V3r*("(ASB(TX,r!A
-rQG0-4QEqpP@-DIT983QpQleJFd+Y4B85A&l8YC+qEmmQ3RY!-rb!2$@[9+3!TPG
-C""jS,A4`66j(0Y8$(6iD8h(cFa1p5B#m0"mpBpM24RK@(H0ZB&Y&jZS1d-Xh#Qq
-h`0)!5Q&$"NP%hESGQ0Cq*&hfVhFppB$fM3A9h6p%SArADeZ"[Q(@Z1(F)d`X&8B
-mPUrQB'3Ch(JCmJDpRI60hNk)H%5A5lY-eT%DbFJ%p@ULHCGLG59l%l5V1+l1YL"
-Vj5BD-8N,Pa[*jJca%cPh-K#6'TYepeH''2QMDFZ0M(BKdH&#Bf5I*15LX%C60UE
-JJlYAd52ELYYkFNHD)0`aFiQ)clNNN5$9@2Jk*E'JX@FDTRjVcj1YUr&qD%mK"dl
-Mp-'L[)P8UC@QkG&cDKpriLT'lckbP*N(60(`@CSM2F68mBFBL-jb2d@9ZNDK2-#
-&X@VHM50K5[$YU6lS+@0225)&3P3-N5P6@QH)cfC$1*j*UT!!F*1-!'BV4@f2`16
-$j*'jcG@#4aim5Gm0ce%23bS*LR3JpQ`k8chbi+Q*"01)NP(ZDPf'0D4a!*!!M`P
-Te!bFCaSCe8CGT'P*j((JdqJ)"4Z#,m*b,3@ZlRejJLN,AY(&D@pNK*b)T)jaBH#
-RDHrFPd,LcX$Q,phmlEm%Rm1&pJN&DKK`%@9Yp4j$F,VmY[#4J$CQmCq#(HR"k,@
-hY[p-QcmjCNG0HIHL'@qr4qdB[qa%B1-JA%mh@8QYB8EJa'B'(ECTB0iilEcTR"B
-AEQ-Db0KeApNCaZ*Sr'HaQlBF%8Hja9%(&[jU#kR`BkA09MVLC`2NZ+U2c(8@fBQ
-2(%Sl!fl$'Y@*ejT*q4CS@`mbj*D)dkMV4U9"jSfbF(4lPX1'-QGUfX9[@$E822`
-fqJV4'jLp+b`QLY(8SD2FEYY%'pkj04C(Y,(lLaYeD6P$"('c[Q8i,e#ES51*ieN
-aP'mY[1YHq,TEj4irq5AK,`$eHCV-E(cHJ8FbAmiq$BkKPe3@mqKN8BI-`h2+`qS
-,qA,h#KL5KMjeKT&9bqCPC#jaD*j9jNPhFbC@"li36rAb)MXAdcHCZqUUlJ2CBb"
-mm&8rKbrf'T9ka[*YrK!SLr"DD(%SF@EVi#4AaD!#eFrlH!-40Vmi8,5kGdlG,9&
-rrSEPPCLe[)YTA$di$`9f#*,8lGjVTIUrQ51qmDX#HYA)lV1Z)Ck5+UL"NQR@NJq
-85d0)U[k#pYadbJjk+eb4'&Z'1)V+@jSk&*BKCB2N[cB@BR#Z1+Hdd2c)PY3P#ae
-SemSHr)3El'i[XZ'Im2a[hEHIAUb*ZK!#,b3HRAiNYcGjjRN0ZRXQqjVmaNc--bH
-ErBVXUG3a9TP@B(ed3Sh'm9(pB1Cahmacr8miCG)KI9JJE@hXL!'fpcHSA!94Df"
-[p)%%Q4++f34B&Q)VS+Y'[rMHYDF-),b6Bk@al-'P!3@VaCk%%6066eQZ$Hh2Y0%
-pi&FRe84GmhSeD$mRKN"L!KCYJE$$SRFjG,"Z!+@3"!%!!$`!J,5Ka+Qh@5'%!!#
-iJJ!"$Xd!!!%`!!a)XJ!%(XF!!$*4!*!%$`"8Bfa6D'9XE(-Zci!!!%#b68e3FN0
-A588"!2q3"!#3#S"`!*!'3X(9(r(GKeJVd0rI0G5c(rZ&qH)39'X#pD,Sp#64@B"
-*bj!!1bA*X!$h45M4#Upl&elcXXe$8r50`$F,#8T0bhNTqfT0rL[CBY+KBXcEc!,
-Z`4$@J)cf`Fje)0&(kI#)6XYRq%PhJXF2j4diff0bZ"TT)VeBVc3(V!p"+2m[*kT
-(G0P8pM`XcRGR`KC,+Bp,F1#DET4jDY#QFi'(bYf6*$IA8H39Ga!d,3a(#4KF2*+
-C0j@d#IYb#M1b`Sh'1'e8lfM'f,%#,b&BmLbhU6Mf6M6)lJrZiH[l'Tf$QV-elZE
-i@TVM0@N35!T6cLPR+3#Qc-i)b%ISaffjhM("ZCYC#SFA!YN0f!+H#E*@rp@FQGK
-mka`bQV0-b6`GK0#hed13!1F8I`Y4p6&m!*hZ4Ia9d&04CQQ1`Rjr)PKS956c8,T
-a`2#ZTP4NaAF'@XHCF2I#IE)%MYYam9a(#HSX02'%lpj#$q+YMAU[3Y"0ZENldLK
-&5NDa+6$lQf#MP1Ipqd#$%Ie"*"`)1NP&c%6$Tep'`Lk`J5f1+DN1j3kGi3kjFHk
-5*bSccReA`5VfdmU%UcMp+5E6,mMd,l6U'E(P%#r5SlSSm,H0qJ*&DGMNqRXS4I1
-)#Mr9cR"lYfl4ZTiDX#9q6flM$IRLJCl"`P$4l!RLIYNjGCN[rLL1fkcf`EelDC*
-"PEVhM'2T*2%3E-0Ec3m61,T)!J*rr6@Kb8Ur94Ycr(&DX#)cemR[([)@-P`+3XT
-'9IHIEFKKcL%VlAhP+jq!4,k,$9dA8ihdZ"AjGB33[YK*aAjiqTT590NCR`TDR58
-qH8R[c)5NJmC'eBBSV4DY&hNCj*!!4BijPPl4mIFYcj,G[BlU4jilZ'FNN8SkmcK
-KMjkJ#5kiGkeijh8,b,q2h[Lh0UbUA9D3!$*iD'3#jhV(2)`qqbHYDmRreC6c3Xe
-KPJI"cL9+XF4VSeDRk0P%C+5XV!26a!#fm&49QkZ"V'm#&ZY&SITUXGhQCFUNf[h
--m+BJRE+eI-9DM0IpY,c(EE(+JedXl2,+@8*N#V+NAf4YPHLdZ*)f8$LDJe13!&b
-T@8F1'dmmiSfFB!Ue"QRp6kI@-a0[EcJJLke(j`I9d(Y1M9EM(A4X&Ej2FbZML(K
-CV(j@"HEa*iKC)e6f[Gp4JFprT!aL[3Re-$Q#0MSQd'Z$$Nk-6$J@[b(0d,Gari6
-FVdP&8eA%Zkr%rf@(VcbPkYRKGaZfMFGDDI@+GTKfSJf!SldiNS(VYQU@ABXJMP3
-61V[bF$9mdRAQ6@B@[rS98G"`1DddBj!!hZ%e+hq6M&-I@S918Vdp[LFGf#i+2ST
-&SLp+3&,G9JhLDqiDlarUI#mbCJC$c5DYFGd[Cqmkh)@Gmmql(ha65-b!kNH!#ZN
-P!'p,J+(*,UF5fBN2M9i1R$ArU[B0IC)PRQ`@*c@ZP&B1EHAJVAV"h,bZiCke*F+
-)!MGBHlr0iIFd,D&6S(,lL`lpfN6Nre%!&Z'-p1qMEEX8JHYm+IF$2h&ZPk`U8F#
-SN@jSH3(KMm#"1+)5AS'!8bZLXJ*D$9VB[")A1CiEZp0V$c#L2S%!4'El`HUqX%a
-PdC9IS2)5iU"9C4lC0bFp+!JLBCRcdj)A5@TJqb2qfN[RdHJXZ)-T8FP[&S5ekm2
-QZp#PI[TdjN"US@@XBQZ&P-f8[$q@G@-UH-iaU[&iJhcYR@A%T80A)SGY93Q#C+3
-Q8hJZ$YDAL%4,Tm8`GBr`X(-Z3-ZB(Cp-SSX-c-T'I@dUI@NhlX(qSXb#08r$HTp
-IQ"IS$lYQ@0Q0r0%[bRNm+pR%[$mmDq3#@2rX(Z`09jEUV#fAX5Ej,-j0%lNhr'`
--HSKi%N'5c6F5c24cjP4e-$'X&@'N#F0k8`-X[0lM2-hDL'3@3MqF**j&emF,J$V
-D[!#,#MriKb,D!ElY%UNHZkMJS,qkGeX)`AVk3bLTlPbU90mF5%%d)($mBCD(ihS
-@[YaPBcQ91h+'V3X,AXB2"#[FQHIZ-T@''H+aBUp*-+8rHP2JUD4-MP6J"mE*Ij4
-)Aj`+T-dl4NQNHmRh)BZl[D)FQ@"(F5-IHGdQ0b+F,5fX1UD@a#(CfhDlJlcrpVh
-T8LMSfpl#JVl)*p!6'0bkN!#+li8Iqq(%PB[NfHH)M(K3`pa'P5bk'BD$I#,lp!@
-5+FQ"Y#J-lP%%+PBa''hR@iE3-E2F'mq-FbmB0liUhF4"j3[UXj0b5%1jJ-3$mCP
-(hG99NaJE2U+NYbjVMA40V+BBUq8eI(cTA$DZJI-DPYp$5Z(fc5qrr5KP#,pAYZZ
-lV0GZJ@iBa[pkGB0NST@[YP3P)!h$IlHd(LE`Iqj$9rQhXM!'f158*3rrYSmKeFD
-GIqH$fX%IRjjeSQFEeaq0ac2H"fC!b)CSikCY9lY91JB@eqIS@Fh4M$5E`05q%48
-QHCZ'9GJqE'*'15m)-TQ1Zhr'A9ch14S[bC3NID0&#r2+B!hF[f%a5C(,fVV,"iH
-SbC%PG%2K$#1mbPR`A8DN[1lTrlf"RSVX*f9&41K4EQl#$B[1Q*U(J(-B1%6!KUf
-QH(mHa5R5EUZ'**,35cH[SM*`)i0(K"b',,`&rAdXQ`ja!0MHVJ$G#F#@%hA5EQ9
-#8%%h!rVN0F)LIA6Lr1C@(QCkAeEUJ@E59MAhrckb6j6VI1k*3iL,!hFIDI8dHAE
-Jea(#!+EY8E`r!eNLF,eIKEXeX),YX%U&bQdqJZ(-F)$QmC+l0U@jF[Y1KAGYEk`
-G8eCmkN'd(I[KpVdaA,I6B0k(hRhP2HIYMVGT4-rifRKeUB8Y)hX%#[er59`D,q&
-N5$D*CM!8$GUSpKhEX@'Y-GT'd@DcijbpbGd!eCFH,8krK`lL-RY)95m#+(efM[8
-mamGiVGQGI5-c#,M!M42CZr9lY`b,Fp16p#X)S%#`K"0*P4c[iZUi@lQq'!2Pl#f
-19FKZr-E+[5HcF#[cS5*m1HiJIHQA3Q'HC$FPj)93Xi`R"`"C6F2eA0@"JT1e85h
-dI-*"j8kZm'5,MT&6$+bc6[cHa36M&%%+%cVEN!$+2G$kSb2pR"5KCB[[GV4@l11
-N8Pra-DYr(UPZ3+69C&+KrI2ael0MefV3!iQ,VTaJ-e+P)Y1iD`cE!`Y"Ck8Q)Ij
-`+(C#h[BZ%"D23NUC',F,i!%4U@6PdVmV%jdCUaM8B`RU66BX`Y-`5"15d1%mb1A
-H"Z2Sj'16-FcfbJEpU[HZpbI&`Z3RN!#`+$LFFZ0)4iI*B`mQF0@Q)J2hVeQhH(%
-i",PqR)%"CE846[@F3'J2"T!!C95Ii"4ZNe,-aJ3aG',r+DPJh-#kaKEj[4-r89E
-E"1d3G84a#dENhh-Gi(GBi(DCV83ie"!(4GiCf2L6Zmhr$l9'+l(J5)6K4miNX85
-VA,KKmf2cErPCFI6A!mJ"2ee5#,HVCBjY9IFJKf$BiQ[HiEU2R-er`aRf$+31&S$
-Ya,Xi"d#i(f-kYaE)cdZrHeh(h@I8mAVEbEZq+&r!r%ARK8'2(-!TATI9r$C6iN(
-5Za5PL5b[Lc@L88*K8eNYBEi&I`24R%H%MS+I-BU))TKFpTjepG"B`LlS52El2U%
-RI9fRh`26PUMPqDcK8%rhKk-!1SrPVHmdRPHCS$#0j6#B6YFh+KP931LZX+)'BFd
-L49`SJ*I`r-%k,[FiNE3GZ&9iU(9XJ!)f@!SR@XbQ`9DCL'3XCYm5m!a*2KRP9k+
-aNR*Q+G6(XV8K*l9KA!0kL@MYr#6Tc+b)V'r%'CVe#Z[ar,rUX0p()JS8'T)-FD0
-PAYZS'@h1)LL"FV'@b)j%PrbbD3&dpVC@UJfXrAdaH*r3RAdq-qI8ch3m$*Uci8$
-+,I1E!&5f$VZN1!ME-IC'Y8KeTKdJ8aN,2$N2m+c&FVM,bNmhITmqc9IdXYef(S-
-%I#$e&@)X"-5L[r%RF'qba%)K)Xc@P31ifT`AUA%rRf&LS'9C%`Z`QfTRJk%cP(L
-XpNBVUI%GKjYHPSCA$P'!iF!QQ"CE!a"Kb4Gdf9@PEF2XH%QjZi@[U"G"[+CLbTC
-2pC'&-3i@!)AcB5UNQY!)$2X8VJEkSNE%ZB5I&U*,AhY$PVMV2%8i0d3k2i#PTF#
-(Sk4GXGHY[*A@AdKe2E-68YJaD*&10)G@L9,*jH!(f&*&iXVcIj(R'T8P#&Aad&V
-F(jcY8`E2+-8FVr0b8YPh`m4`c&FM4)@q,jemlq00k&!DQ9&EpYaE#E#0,[2`%Z&
-0*G43MLMqNNX0%bYl8P`("DB48YfGG@8SMr)S*IPN%rC+MAD)$65DNDPBcmr+R(2
-V0cf,6Rce$H)J1j!!PBF$mkVblA(@U&V9*CUEL+PD-L0p%'D5H+QD"JL$H@laIU(
-mF"XeJhMY2-JjaAr)l0#MJcMJZP)4lIiMr"KqpFPTCC!!A()DYrrf1,1bQc'YG'Y
-q*fJp5[K4)q%B014PfiPk4iX`*hVjQ(V[)M[kFPR4l&@CjLY#%`Y"*jNpKS")[bb
-C1TNbP`%TRXK!Z%RjGE[F"iNADi1`X2S`U$`HP&6lM+Fif!Ae@YCZjT'-hd580QE
-`EZbLJ"KG54H+L6-q)V"#i&p3)i"%+S,+[2$U!EF'$UBC)'1V4RXch#r1SjbNEET
-QD%amC8B"#iDBS1+U$095BRANa)C&-U41kU6UQJ6l4fib(!a#-*HVLGFkiPqEJCT
-`LfT0l!fNf3ZKT4JY2*FRah3e0X1YUJNQ`d+TaBNVA8SS#(ra1frB+i-9@lE%pX[
-F[R"*ra)35(imh+aSY$J+#AKCZUiRahCp`lm`&[XKUKQ&`H,m1hFB`jiDE16q[83
-0GCpf&,@A[a'04"60JIF&KB(Z(Q!A,CdV3,!Lc'Hj+XKbCSjBIBKZ2fcq%Kqb+8X
-IJVL*P'Y#9ISZJk6ASiDL+i(&)d@0iXBL%J'GNdJKIcU(qXPFR"mLkElk)c-R+K6
-1aYpla*eML6YXd`2N#BQa+$pZkH8,j%M$eDKGq)GD3!Rer9H,0i$+42DC`'L#jX8
-IQXf)1,EX@%RIq&cVV4B+&YXAFQF5k8G)Fc#TqeNm-3GY-k1pfG+$2Pabe`jr+("
-,c#ZHf[NSkIM5fq3#("9bf+@1bN@I*ME'FKJep`c2XPPJ#lA`AL%S2S0CU&8dL+6
-N5dC'9&H'%XXQCHD5a9IN*kP8acArm%kZrGPm%V@5MjE3Yp4pjl89NL&&DT!!bU3
-ADY1[A-e`L)iqIkbV+NZ3!-`KLFK2@*9!VKUUX+9aK(SeSiNF8"R!#kZbVTC%iqX
-KLpM&`0SH%(E0c[8+iIM9b0eDTNI",@+e5`+@cLYl0[P!kGF&Yh`HR$pVjRb4#[A
-ab"aLLXbCqTY4)*Mak3UMRFIiVL'jJTQ1#h1D3%S%bEfMP3EDjjRBQ[l@FeH3!$9
-QDEAYZ%`3"$Q*6YK)CI#+Cd)H(N6Ka"1dM(Yr"0PC424%*Qc+h,NZ"MMhGQ9V"D@
-4!r&(rD@GY@q#VVZAEY6KJp61XDh4mbNXF0(M(9PpH$-2`)CRS@,@+k&1T*ej*8K
-pkA16J#r[J-J[)&Y&K@-hcK)@X#)0HJ5f+(aB,ZmNY[AS!6pedJhVG8%fQM*F0j-
-1%,N1jQKU,IEb0&Xr`eVeY@5l"Z@U*0q6+DSD6eLG3"'!eBBPM9d@GB93*D8c&hX
-*Yifm[XCXGJHPe#9l`hZHr4p1*NlEABLq5M3ph)SlG%8E5f0Li##[,f&SUUBZa#Z
-,*f8&ajU(f(e3+[#(9Uqf-j!!iih,E%2)Fl0b9CLSJl"`+Sm,Y-i5ZH6MkYEkKKZ
-Z%ephme@&V",!V3+Vfrleq,DB,1U%M4*kc2!j`BFqANiFfTNdEeDe6RQ)Z"b)I9`
-XI&&F[fKU4ZIZT3$aLeGjc!erA'%4dJ%I*6#m`kZd!B$M"G)@$q1eJ#RU"phe2(Y
-DAUS)D'-HH#&5#l)*2@!aN6'AHMX)lkBI)e5X&qJ(qKS@1mYf0YIZ4l$`Q!3fP%p
-hNKr5(!d'FqFl2RIT%f("rE&)"&ReH(pI0E3S$)82TYJRQ9(Y1++FN`2HG6DMTm8
-qI"#NLf5)"YHR!!c6ZKb!-Y`NKe"UbG$&'e$K'RIKV"HkQ4jV`!TNQb[lIDSL,MB
-F[8'Fka+kG,0"XEiZ$hq`Kf#!ZpY+d@G6#mr$9(P9CKA,"6Fp%eL4m*)iA46Mq['
-Ti39QCKL8!JCA8AfUSX5pFl&dX"iYf#l5%d+rklHpja9QZ8iH0HFhk#p8'P(NqcZ
-PhC9h`L)Tq3ba5DqX30B))(SBTQ84[qbr5i2d6,F,&JX$jXfS5QYhprDAFP%L699
-LjJ[9(MJ"Q4ZH[C`@GDd4V&0K-`"XDlE,#54e#1--Q31PGjkcABc!*906VqX0V6#
-C#-c[PMD&5SDEJLQcS`,i61X4KMj#rjrm9NlS+"28XI"3SQ6'Xb""jrN-q#C,m4G
-)F9$G+0QPMe-P@`[`Q`YhKBJV"6*$MM"Fkkm34RCFhbj*qr#G'(ZZ[ck6cXLb3)2
-2FVAS$jZID2&3a',dDRGd9+,1jXj!$Pre9jaX1)E0hcJh!Ea8L$kf%2AibjKSYUd
-0h8NF0XXr,HQJJUeEBYGHYT(f!UB8!5faZUV0-418G6ekF*5X5aGXlkDA8-SYV96
-1)cF*B[@aIrb0c#3pc6%$lRC&p#ALSJG`8fH5aITjaY&Db%*Y8Q4+lrVHTF`e+mG
-J3eJ!%Rm&08&Z%"idD(Kb(c[d!GF)%e)Ifi[P)0rcArF%-UG-'PXc9U5(-M'J`EK
-4CqN9F0XVH%kd)*c1)lh!8lhqcC6J+TR(5Vi[rDGk5$`DTQZ4QclL9f1HS,RK`5-
-C#$MND2DY@DK+9IXDGPDq64fk+L5r$jc(K)3%-Ka8&R#p#AX9&irbDRM5)!&`XK!
-U@Ne-dd1MAB('8+$(QcV!bpFL"+DUb+hf2Fa,)dCI$XF)&kb`lS2jh3JL3%Z4(lp
-cI)IDUCpAV@!$1!G(YQQA8%58,C!!)2eV"!4dYV0FQq%UVU,h*$lLC-G-83rJV8K
-l-jBBf%Gp$E"P2RZJdq!ic0I+K"Z4aceXh&UR3SEkQPCc1GCjCQ2!"iX1,f0H!Hf
-&C1ZI&e-*VYNVCaq,3(YUGA+CBaVMjE0[kIaN10*'13BeLY0*9NMABMB2UITf(AE
-3+P&Vmr!Ipp1#RH6C[6bX23)[fl'MBqi8F1TSj@JQFhAYKlBE2ZJ0AXelCi9TelK
-6+G`q0IJM-ZRMhCUX!FJm0C**KQb680ZH"Nq)Ji[aKU*`T(6#l@SSTJq%+ki[6d9
-M[Uf4DidRlLLZ69[["3diQ*hZ-fq,l&9M%2iPk&&JUjkCB`iEYjbe*l#H0b['Zj@
-#5Me)DE68`k0D4BiLR5rhIijA2MMYKEhM#PlQ3Sd3JkMK3""j-S0&)41`&!Aj1pi
-HQM9"ckR&IXiLXREUGCQ@)5e$XRbHYPeJlM##T"04Kf+)KBQa-iU6&,SKV'jc4QU
-!6+"EAciXJ"jeE2V&4Sc4qMZ2"G(ijhT*EbGQ&T!!)*0eGG%6qFY(R#EPcrAfpfU
-U,3U-ee$edL9)YVrlTc$5jpm)SEldkIaV[-a6iXq6!dLMl%NCeK4Hf94ZA,CN@VY
-CE3mAqe1b@lG@PNV,1RCQB8eMF4,*B`"F5*qh$A23MM%6'2j8Sd`V6LFhR2%+@pp
-A1Q*APbLI-rc,[fhcLk9'leU1Eja1djNqTp4b15aGF`2&LS9D`UXUEIKYj9XM"D-
-blrSUj29R!JaCkZRUVJa,lD[)@-eE(,SDTaHBPFNmBe&)ma'GPlKG2IK,48X6SfP
-G"I+CShM!(HJR@VDErULca0-6Ae4N5SAP[j)0%Yb5dAVPld-eDCZ[JkaEQfF"425
-!0q-d2-!k,qAI41r#eJGJBd`GHie`%epJ(UdD)(jUqe&XE[@DiYMk5R!AiUYLZP&
-jE&CTVI9b`$N+SF6h8amQG3#m4i3k'[TU%pK6+,0j5bJU(Z[LAI0r"b#Jk*iG+1H
-YA9'H5KKB$#SSPU`jdDEM"'Q"r5SQjX@[)G+DlGl"1rP5Njpj4Td#k4T%m(!L4@M
-0Tpe3Sl&f+SSeP%[2!C,d)!XH!@(ZeI%ZfVYfDG0M)SekrXVD@J`e#cm#5HG`@4d
-p1&Q4fqi11GVAr5X[HP0bdU$!5E#a#BdfLXlkZ1SV"q8'I'6qjD3JZI,LlPbHP5N
-rX@C2*H4)+lKE3M[%rDC2GpZY6f`fYU#8a-b'pN%$al"d+9$LeTHbX)d0(djPVl+
-EEbK@B(a!$PedGf35iQm[MhBqG+iUdLThLR#IHU#R`SPENkSU0D@V$KbPPp@jV+H
-I9pfMj6edd9r4$#'N6J3dRRC&ij`dUmXN&6T)p1H()lMY#UJkD6J"6[T@CXXBccL
-l$BQCcXCapCSCQQmKcfIDB@,FdmFN2q9$@%HPFMI-qSCa80k&(ML42813!$G@&1J
-%aAdfcBIMQ5,8i#a"&BadB0%&UVKM%8*lpAapP)+eN9(Z1@%2fM8PJLATp9Bp`1Y
-d#`DR[,N-*T,`0J)dmqiJ6H8JBeJIM!k@CSMqRN%h2&`BX%J*a2lSVE(bb8%,"p-
-UDY!P-5EcQi3Hj3fMF*%DR2B"h#-2p1MH"qQEFC!!9%Icj'F3(S$,"I(qCFfD5V5
-Xb(hM)LeRTaa1jqr[HR2'TrCVP@,kN!$!@f'8(BC)r40d`ZFHqE5qbfbXCe,R6-4
-F*rJ2a&KSiGl-"%9q1k"J6@5L`RAb-3Fhi`GUiIa`TJ'JAPb9B#E5Ni%D-RKX'`T
-([2)amID2Hlc`4fq4a!PkmA&SjI*l!ipP(iIMN8,&eQb[b-rFIcEUC,M$U&,jV[q
-RS1ScZD3T2+6HCfSkR#KX-aKjH5N*-M"q#5'P&hRHH9NaSh*ImlYMr,mjF2Nc+`@
-P*X1D!Qc)59EbYm*#-&,Sd8JP$fa@1LK[q585Q!N[%4mc%AG'ELQ)@h4"`J9Pd0"
-1&P6rC+Gl*Nd'RH42066iH+ET,p3j9#2N)[T0[qB1Jl0QMXi3VS'2XhQCKf[F9ar
-pB8M9ZN0a*#kZh$,&p4eq68U#hkd(m#Y*KL@VTJp[!aQ3!&ahL`S+qB"#Qj5em%3
-d8'p+V'hV[6%$i24+&9$DbM-XdPe26r-)rU*I9`mkUBGr*k10$H$mVEaBR%kVKcp
-2T34f)2KX'IY([@S,+5EDDC+)dYiaFJFC1NR0-8ekqIN2,`LmZ1Y``b+m@NeGbF4
-VLr"(E$ScUR241-,8iq8V,HrSXjCN@hJ[r*r,1[liei8"eI#&VAJ1($QM-($,6`V
-m56SbI0F@4SkL!XGM-)$cfC)`QVTYdbYapS)hl%$LEbXE,BUq[1'Kc*dX&rcP'85
--b"@CD6+ifHZJXU%LQYJ@e3qCcfT(dTXS'N-SY[Z$Y,CGNiR@emPTZTJiJP5rr*p
-j#Y%06HijFYrZ((N4X[CZY0Er5N&4#1Ur%DcX&9IpMqTC@`[I(#G396)PFG+I8j*
-biI$$qcTZQ4*aP8K'h10J)9YTaQApKLRR49!$c@%VpKSNfMHVjG'[j)Q!d@*%PaG
-B#db5URPiDTbA0,lNDAAP6XjK%,`a2DIhl,U0TL-%HE4SV16#ql5bV9+r*rX!qE#
-(m@Q[dL&r`pc8m2h*+A-C($V'Imb$j0I#U0-V46+*5r1Vj%N"!SG-H`[3Dj0j8SJ
-GT1rJrLm6h2)TG5X-6#)BU6@1RIZ9QUIVd#)`BYTXN!"lcr0B3l&KZ@Q%,hI$beE
-lCIr6Q*0d%2`BN5L99D('10`SbR)k2A``Bb$jPmrS(ZU))$MNIPU&BGBV-bERCaX
-3[KY(P3dJqRP6fej`K8%q9'1fQD#Gf"@Sk'k%+8aci'aLGYrF`L&pe$cTiES&R[V
-Y9,cLa5p42HPYFfcdZ1J*IU"6"h2-LLB4ibIlLM-+jbh`'"mRc4aTc*JQhm,a-jZ
-kPi-#QRp!CaQEih!eqKTDLJKlKLBam`8V6)`cHjYjB2!pHUV(RqV&"r2'Al1Gh([
-5hU%BRP$m,IU8DEP1!bL*R[5S@Y$Lb!eP#!MHj0UjkRH(-$,1Glk*))$2GqjBkeV
-eUDr`+iIPaKr(G6p2,lYJ6*%"i!pbkQ5E+a!3!`Q%I8dDf!&i8(VblV8c*AIZl&P
-BL-'!-iaRl"YCLAP6"eYP2Z3rY19"lp[$h,rqR*ZY&GI@8P3k)A0$D%9UX9Tq309
-TZ%IK2['0P--j1bD`MjFM@cbDJhD$*X*6q$f'`L"'"+0N#`4C(X-M$mp[BZE,HAP
-6#!(h9NShIT[Jdb5HVb4qQT)KMN*9AFBZpA0+AFT5PRHfZ"-C38)RF8T,IGCqA1L
-PAGkI0!Dk,eNE$UqPU&kERp!2jhX+8(L'cQ[NC1lk@,Q-(LL,bih%8YD!*8*LP*8
-mh[5"ic+Y@3BC@!D0`@5j[[0pPQrARETV%qp'R0II(P#cS$T0FY,N[mV2jH'b363
-GU2ZEH*hmE3&QM4C+qmCX#2R[dd[9[9pGmNHARJa$9)R(rdHUqX*%epFrQBEl6Z8
-E%h*dc*ANML,efcc*a"5jicR$"4S&pl)ledh),jQ4G#&qpYCUlB40+4'&$Ddi!+S
--I@'k#C[j9#F!I4J8*elSFF'0MIAF"0++"T%U9RfCU"U*kDEd0@-G3[$FrE+A[2P
-Ql"IAAjq*a)B8LC1R#De$30,AjJa*A$m`8[b("$Vr9j!!h(j-4X"Z6j'*"@#dJ"9
-)AR(cRfTe@1cBG@m6Ai8B5'pCi,D6HdcdpJ+$iLaHTrT'J%2l"cdcDH"`QV#U'p+
-m88$NU043+F#6"lC(+Q8hiYi!K5C)P%%[%6ppehJ%e8LYR@NGp*@P,%-,`1HSZPc
-(&*+6YJ!'Hf`@R`c[R1N)XTK4hB%@mSJJ`LKZ0Tf+6l'5YhSFC&*)Ibec[CLKY*U
-VZI9ea8lPG0P"4Rbd!*bX0*IM1`9!Y2$UPqSNX"Ur`(GXf1Q,`IPrlND06HTMkD*
-DBDQ%5L$RlC'QLZDlTTTrAQedXV@%fDRQ'0cT2V3NL'hrUQ*0QJYl[q0()pG0-H2
-,21i#506El-4KVTP[Mf"aURGkZcDSqlVF-,XEj5VpN!$TU)mfM'G%qUZSkVa4Xcf
-MaFN',)9ZUJB'$JNmCG69HC*GXfdLH%'ZaCNeBmd`m-HZeSL8mSSApb"i"[h56jG
-,j9JS-HKk@BIZip(jXF,RV)dZYp6JDJab&YV5)HSJJ!Pq#h2N$2M5%!+Dhjp6e`(
-'hrK4iDIS*Kr`6R,Je&SX1LY)$[*0TLrB5fhS36"VM#Q&-MMK5YBbk'eLNXh3E"$
-6qP,QV4ilV8R0U[lc,$LaE&d@"F'l8Ci"5cAHSqQNMEA,+8[mch[hD-X3km9DU@X
-D6+KHECr,8FQhPT!!ArkeRBh%q"AiF32qH5(VYpIUA011%@T-@CXefaAQc"ZpC$c
-ac[EY(#-d-f,,QX22Pf"Iikha`F5@ThRd200VA+5cSMhKU%9$rMp%qMY3S2a*R5k
-am*-f*V@E08U&-+$UdiDbbBl2N!$2*[-8#V*iBXkE46Kl(3*m*0S3&Z68-3Hm5`i
-8JcPfehQQar#HGD$e@q!cirlTqH6&G5M3BkqrLcd`erB3"$F@G"dZF1QVq[@Vi5U
-U&JTDT*!!-GpmCflG94U0S6$q6DfmI0&CJ)+NcTmi2hkb1mYr"XJ*G%!-BICP$db
-6dGBSf'beEYA0m-0@@UBrmm&$"ik%'4TGdd&NBj[aJQLBLXlEIr0k4Nj+N9iMEfN
-QJf0K,XLI"21PC()M2,#pJmI)D-L%,Ti,qfVXi80[XLSB@k9e$PNBj5R*8K%S[k`
-0fAGMVH#-E'LINSQ#2c(q32ZJ&*E*KFd0K)K(TD@eaPCk#e10P9i#[XM)9XHP@GM
-e9PA&#-*M2IQjS%p3Z1B'@1P$ia-HIH&Eh6[aI9SGIfT!`BXlpUrUL'aH*)JiG-9
-H($`!3Q1T(`(e!cMU#5ec6%)!a5b%l9qrE@D!q-50-+LR,a18amcBDa+@`epQmE0
-Zdpi@NNVhT4T"b,@E'G*k62',@G!,*+bcl19`kD@0(GD+1c6AH0F`+5%BVFCe5&T
-kBA*EjFR[j"FRPr4V$MQZiXIYK%AM-6BKi&6TieZ4ckGP19Ra`@lY'FhI'Y)-`ai
-6qrr(`E8H,8bebG9RLNRB,Gi3h4Ebial,3L058bDAIXXXkV*Q69IIQ6lIJ[I2139
-A`-I)#)"A@ZUUIX&S12*2A!8NUpa"q0T!-a`%Ed3Q`%iRB)09((b[86rHiE30N!$
-c`L"IGef#h!kB5TQdA6QFpQhkcb0AKMAV1GFlUC+USFUqH2CYNal,(aK35MjId)I
-kA1jkJ2E*FI9ZcbIU2QKQRi9-EIUP%10VUkchHSG@qB@PZ!8eR8CXS3M2b"`KJZ+
-3!1HfEk-MV-9b1'$@ZN0b4fd(HXPjQ(lRjr)U@hFFX03UkD`0eq[kQ@AEEk2aA+@
-eh&&4F!P3RB8-4'26TRmIBmiPhJUHLMq,laqe52El43h+q4TSA2MSLP'qacFKKBq
-rBG#i&R3$HK305I'22U`)eBDCB8M%kbZb`,'1Vaa[p%9KP-5cRP#km6%mNRRZJh[
-flr#$$!&Xc!,i#QRB)d2d!RF`5hRD+ddYfjPrL2ARYm9iGl6cZ$YR4iG6c-R9dI)
-%M4X'$8YBP-mRX9Lh#$(BF'MP-r,"F#DAJPp%#"iKEMjF!ck8*rU4M#ElBkH96Fh
-E8ZH46d+qBDRT#l-AU9fZ9`-6BZVRMZQ8Qk2lYM&HLN6dp!C"dVUMN!!QNFXfd+B
-%mrc#PE@Tc8CcN41hj0S+9`[0E%mf9f+5p4DVT+-p[Sa6#ZaNE233(&N#"*R`0'G
-Hik*5A2Imblk@rNXY0"j8VX'f5T,Zl10%l"S6#qPD('a#*(1C"QL+q#aa(#3&2I1
-e2NUYF!Mmd1*#c+Q9I4ad24GS5Gc,*DKieI68mE3NN!!CF8&i!Dp&+DdA(Y'T0Na
-pXB38X[Rb@NQ3!0S#((Nd8LZ"Cr21'+2bJb%!Zlm4BTGaq(NjQQjTXf%,Li8`$BY
-+JS,T'pq0KXT,f6i1LE3"jG(!H4AQ*8mPlKj9"X(5(Q"ZEqpcPP(mGMEqdjZBc3e
-R0J"%qhKQI[m9JbX$@LH)&-9P"A6)!69!eH29f(ak&jbl%0-ASq(5SlK)aJ5A)2`
-AXP2m6BR%6Y&B8-[c0!R,r$!KUQ'XPR-H56cj'eEmUP'8'K+iiEH`pqCPiX`)2h3
-a,5P+rYT6+QD!8h"0)9Lqj9*)#0"(*+,F&,1@ee%@1%Sj5fbM-EQ)6"#YA2%Mm3V
-(!Ni$CKr%krXqHP[E%ilbE4mj@C1Z)r[D98GVG$mb'"HMd@UX,LD29)dI*B#4'"&
-&Yrd5'1F#Gq@65*!!GTep5+DGU2pHeKj3#ID$0!C%8R+8XL6NIN%1EQ%Zj5AD&c"
-jKj+M96qR5[Fb+A*$)GdV-)L8q''bq5X)0NE$ZdkRE0hXhGMMU9`d8-b#i,6XMJ6
-aBQqq$Kqr#TbGQraBj[qjX'+AF)@ZcQ0GTSJbPJUk'*)jZc-cMUacj0#Sb!S%1PH
-Lr!,VlfD6Ii8P(T)TfQA*8La&Y!)V*05bZRRNLQQ!RFcVH,Bbl(4DDfPAEABpBZE
-#ih`'&3mJ9Hc#P[!(01p(hpAaPcJ),Pa*YBMC!a@JNE-,i"dm91NlM*JFTemMKLY
-@J2,rj0e$UkQNfmeF$Qr8'CYZqDGSUGP968SBZqNP2dU*FH5KqKl8Sbi0c1f[#FX
-Y9&3e(AUaIF,NAVk(AANbcla)RaA4c$hkDKVNr[CmJ3C,1IUffSFkeQR0AkNQLm@
-Ua[PLZ"5c"$(BeTba5Z)$`AlcF35YA+,RIE"0Tf%aQL'G5Kp0#-SZq3XjQpYKqrU
-Z'"22-MIUZAiDIJVG&S%6k`A$Y"AMXDXIVH1&e)K)1(V3L'IZIDXr8f5E"1EQIF,
-j8*V"NR+lP)eZS,mF@`V9Em"C'mA6UIr!5q""CjAIAUTD+MG8T9-Vq4TB@h3G6%5
-+h"@1rFa(4Sh4d%FDIML)5CNC-Q4*GAf1jZAB)2!YDH%Z$@"GHcI&@H)UL%XDhq)
-DLLIQHMQ48p3LB*E`1iII6q9XSM)P1f',9+F%'#!YqX'R$NbY0!Y,`RA+PKXZHUC
-VJ#6K'PUJKb3"1bPBR*p%mmk4EYR,fb-UEBr19Ibk1Yr2akNAp9SF39e3UZ0$mLF
-22rr13m`4f%NK11T4Y2lCfJB4RPPD1fPI2eq-KL0@X4!,B!B-EdMR!HM13MNXqcM
-QZqi*VTc5L,GVL@G9Q+CVH&)UPZ)Ce6'rYZCHc,pI('a&&p0lQbq!6P4`'jmYM69
-)hjpSLj!!mZU3!%ehhppUG%*-0rK'Ur+cP'Bj8b"LYIM@Ur0fVTJ@AXXhr*aiSB0
-1I2`jABm-HI"&lRr9j,Ybr1Q$NXU`4Mq8aeFP*!8lkKKKT!0)2TqUji2JcLeNp`N
-)mH!DQ#4ha,2d$"ZNi&qL'c[NS-Z6m5iljR,lQKG9)0eckbeMlJS0I0jk(fZjYU*
-8b[&jHN4`SGHbiTA)6"Va%$9eACU-rNl"mHRiG)&pT!9&q"3V&1[ed21e4VVBfJ(
-#da0MPYIPr'PIB,p@$SEcHj&-DKK",N5F2hZ5Zck#RVlP2dTAA'rd#['!Sp(mEDj
-i2VYcLrh5M*F*8k9NZeSY8`f%CK)@&23B1-QPlqfJ'!eQ`UCEf%MPC"a-`Zr40Ua
-2Q$@Li9-'TERGjcQ)hAiTPbA'P--j,fDlZ5Vf)Kq#r8mhXcbrmZMrA-UkDjf'T3f
-%i+X&DchhkaYa5[Y2r%''J)5C"`di'5K-9ZP)AULV[a-l+[4YV,)FJbL4r2R6FlH
-ZXB48!B"kGe9Pf,2C%0f&)Il8-KD!1rp`j[XGF4@)6@2c[KN$%p2,EpZ1aFc8P[U
-Rd(Q"ah!4d"5XDN'"5X0lkQ[@3Z1L6l6d16$6l5+hpU+%8+fcIr$2d%XbAA2l*!L
-Y20b,j#F*Y-QIS*2D&@lcRIA&M%RMcJS9QR*1j1R3KP*ICpVB$bd#X+Mj5%UGVH6
-%C9D&4M*'Y"Dpami+-6dkcb&q@m&m6#G*dHXm"jmN5BlbRXJIcQr8i6Vd"F0ALjd
-rhH6F5a!DD"q`biRb%[GFlPRJ4(H%@kZZ"fhlrQGZSk9Il#krXF#KLRZeXac`0Vp
-Jk'QI-AS)E,aj(Uf#26R3$NNFl*ZFe0kNElF+)jeZ-rBdLA$fKA2h*UL62)-ARMm
-(`LL#IZ1`Z*TpQ2IaiFMkN!#$[9kABhY,RD)A+JNRQi8`A98p9iNL5f4!,,h4-4'
-r8dcTM-I8ScB9U-m%6C[A"L(D6!EQ+(5`)k9d+r*h[GiqD5CX"KaAIXL[%2!Kr$!
-kc52EKr$#9(l,NdI@P%8(p8X59bNC,2f0B$EZf!)Y!CH,bRc$0iGD+P9@0h-RF84
-*aaMC,35rD0-af)DTA9hZ,HhY"EC+RdBei`+M2ZjP)c+qUG6bLaZ$6+ZT'[6j$F8
-V-NiK$CA*6fVGeLqkHEC@JIC36A`cNqL+&8'N3dKQ`h'MQPB'*P",GXA(VX($Mb9
-aGP1`J$r2rUH58QkeN!"I"#)T#KIPBdDGjPmJFkJ-QAI583`eBMUkdl1!M,8QEh5
-KD,@QMq'HNS&9+1)cRRCj("dlZ@bM,bk8)TLT&+KA4)YLC)0Z3k$KU"F"0RQGl[X
-jcjMqB(pP3qH1MIf6ZjbP8!$JbT+qIpaN*)2H0d&[D!HKR+JSUZ8Yrh&)1@N#q5f
-aYV'SpE-MEDfk8CI+E-b0-k2iQ15afA`884+49(pS6A!Hm+q6!d9`QXBN"Uc1H(,
-ARCmF8*P!$cm(lK$lG8HILL%'-JpZ#`J9cpdF1C*HXerSGRXB*`PLLD[F8YX&0aG
-R$Vpm+Fic,VlUr3Yd9TY2Xf0*jYQFUTM)5V88kHr8Z&ipciSh1[)S'ihH5+$UmrV
-H5@C`P(S$-a3SY,a#DVT'5q$CJ,,Z!fK9[`2Dj8pIf6!9I5Pc!!H%T`DI'k*mE#I
-Jl(*LDDaBK3KC*cN#9@#l,+F&1I#!b#k5MF"MKjdlcf2SXa&UG*M@XX@PQ!&qR[+
-TADfDK6T!`%-%phZHf5L@[6m#Rb!YQT`A#!A5Q`L08aMBT(09dGSQ[QE&jr24Zhp
-Nr)&h3rP[&qGi)80bdq")5*6T3qk0pkDqYYVQl9'hFi![4I-l&Q+9cpM3KkSh8"%
-hrd@XBd1CddAr&hB2J*Dj*r)0-I&FD@b3!0&N,V8cQPCZ,cZbd0remh+Kr`-p%XV
-VGr6kV$Tb(6X`kbj`15mY$3"j+"*VV#B4*f''eE`#2bFFfr-#eb@&"N'&XP-bd34
-1&8!-J*6,02r!P5+C*bNiBJ4NqGD9iL-)ZXaMN!"TB3JG9G9U$,4@BYf1Lr'(&P)
-3-XqS!ai0YFSKT"1'C5HP'IYk6L!%a%e!rqbKX2`+!`RH-aYBi%J`c6ehpJDKAT!
-!A`R3@!JhPI3I('q2&Ld`dc#@bfVQAMpl%MFC--)b0j6THbUGU@!TF4cNB#"Cd8@
-M`fh8m8X)[5iGqYcm,SZhLPaqK-"q[qpeNaA[Gfmbmb!a!%&B(klUL()Ld9ar"mG
-E1UC&QFDE!XZ@&N6cKB@28$G93mJZp$!3Ik+KPeSL*XdF"hCC@&HVmem+%%hAD''
-&4*Flq+Lq5VSSepP(h5QYQ6"&!C3DkHmThZk[`K%IiIABqSb#GkDr)4pH6Z40'#)
-Jh#f9H1QLTYK)FA318MU''X,q[0SUHK4F1p*pKG![k(8D'ei68Q-(+kK*e04Q+pH
-eK0$$U5DQj0!`)bZZBLmU+4pf-8RpUH(m0%f5q[*hkidPG-NSek1QR%RK4M`r*Pf
-Mk)Z%bl8pSd!,AH,j8(dQLLcihDYl4pF56cP)m9R9,J[(j[[N,V@@2BZ84RGci*[
-m5IC9a586IUSTB$9kbRpACJMAQi9qN8'FHi+i!#RI5RB%9TEY['(fM+M"&-Z-)b&
-K8RTpdVebHX%`rPf+aKF,(B'lBHA(E%FpcC&De&f8U8YH[2-6jVlRIVTPELq1FS9
-4,JkR!Lr*S"1G1H52[Q*X%YhR3qi8CFCNKFhC*$)MC+aNP4B&L0f&cfPY@fMQI3J
-N!63',SBNkMf##G6eXSmZ9C8#*!D'J$%SpIIm4fAVqXFMX$1IUQ(3U[ilVBP"dFf
-Y&R9k'jF@M$!fI-GMkjk5UU6f0V13!28ZN!#`K%cK1fHcpa%c'-)N*3(*PKE%f@A
-!$e-aD[6,lqX8jB`KXGNcZ4&cN@NE,1HrVpZ0kU5HJ8ED*QlqI%p4R%$)TbcpV2)
-([)9hPD9@1Ia2$bpk&)"i44h*1X8mfTeiqclLLcRYAh%bJ#deaBE2(0r8BUdfQe4
-(VU"8*@J65-VRX4cPVi9PADfAEfY8BpZa#H+3!+@3"!%!!%!!%,JMfVZi)pUl!!$
-F(!!",&d!!!%`!"$kD3!'SDi!!"cR!*!%$`"8Bfa6D'9XE(-Zci!ZH'eX!!%h0P4
-&@&4$9dP&!3$rN!3!N!U!!*!*!6S!N!-h!*!%$`"#`G8,I9Aq#(9[MSa5YEUl5UX
-pY*Q1mZC@MAl29r$e'2J4rm[eF[LMC)4Jl&H"X@*aBC!!jGX&-%,"e0*&TEMEM'a
-Ap)XDl+*0iq00A"9P3fJ*)FB3UC!!TepBrSpBCMc#ckdj0m'"Lm60!02&ifLCTr8
-a+"T`hr)YJNiAa@28a4a"+lhPV[!FA8-p%VJCZ*+X,i2ea3QDM5aiBR,`A!!`+"T
-[R*-l,1@FSqjqr8PU`,B-fbR1'QZ-9FV6d0lI`IrS&KbhRXCrqIkVmhJBVX%GK0p
-mNAUT1jfjI-$!!pJHdTAiqd'$a`KbQ9KQ)L9dl6A-[Q6Pcc@&51F(l0kP!a8,TkY
-8YB%hBrGEJ#'KH%S@ZKFTQ[,VEIciK#P-69@fNFm0eCrVHU-d`@F-QpT9D!ZlZF%
-aMN1c@4KZmqVrTM5G'Ul'MjA[FbRL[DUV2Yp+Y$mjR-ib"#Zm-C3'&CQjF-Q9`Am
-%429Tk8mp`)Ph&N)e([fZpk%YA`Xp[ABec)&kIVciX5(&)2`V4h*ckeQFGXjqLak
-R5C!!XHL@)"6qI2-Kc'GaE'F#@A([T0q2Y1H'$2feM@@l!rFK6d[L1`BZpUYp@KB
-T10jjXIbHQRbYZM-Z1@j-(J'j#[rfQAf#4Dbj#bH3!$GG'0XcBAFaFa6Jl(M&jK4
-LI6*N"*VP2&YDb26LM[Q4$'-Va"b(fA8eQ&"+B9a!a,TrGT%3AeDNhF4#RjhfHf8
-de!"lMY$[C2-ahX1QA--49D!TN!"!@11j95Y$$@JZQArN+$,qC"@6S+APebb3!$m
-V&Y*)#XL`&'XmRb-Y[DE@!["R39LUF@-FjEYGQDA!EN'qR*HTSF8RlY-Y*bNCGUe
-)rTX939pR+"0IBAq9eL#VQcj9PL(S%(L9F03$bX`@Nj1S-Z(m-Ph#M4P*)a&`qM"
-22&4[q$8RGl$*l-qBqJ(EhcE6Ib-h,EGa(L@3!'P+(N2LcU[*!"-a9FTV8E$4N!$
-1(1P,8IS'Vh852crEYkB0)hB(ZF4Tb,SRPAi5CNe8N!"jh&!@QN+V!-"8lREclHa
-U1@mb6!@&T*5MDrL`rVPSl&#lNBYIb!9S)#9J[@L!r5$#E5h[,I[5`S2aEj*I[K[
-Ck2KcrCdH6q)#PbdZ9PlP2r+SYdKKKK6DG`L'p0'fLXV9L(RqCG"`CIj63PCUZGL
-rI0ia[caIb(Rd4TTb-)PS("1mPC[jcJEUA2*"99Z(LJ2K6k,UYHb9-BdY4+9)R6E
-C-IEdiREl1h2J6EQF!QB5jB52E&rmbXZ*FVidVY"mTKV%mYac#!E*r13!XMLhJ40
-JHmk2rd4V!kTJTEIl4X5*FiJPBS-AYYe1YH03cHF*m[FTpT(EIB1-#6X08,3b0&d
-[YKA&mlNiXDfNRd+fSlr-m+m64E(&#8-eqK+JkBiL#d@Z&,8D"#A@&)M42qrBqR#
-ee$j2DAT%,bf)IqU-MRJ1*'0'LYY6cE(lCJA2JYP)&R*+qr"Tmc32L@hEMfJfmbG
-[Z0SJC3DHLaNSqlh!bf9EQJqU(kf1RiA%$1++F@5,S!KC@b,NXe*B*#IcSV5VCUF
-0+5dMLeH%er@-'V4CH-Tj*ak@HZ98MBZFB)3J!D)eDr5d"qpffpm)"QDd#1LJPk`
-qTYk*pi!dSI%J!B0%H6(fCZGP2Np0HicFd+G*%41XV'X5JQ@`pYNh'Q[FJ[R-Vl6
-d1K0-$MM3H958i"fle8b`AUj2G"DYceiLAr98(jRkh0BGY1G3P[r*c1emqRqFYmh
-hd3ChD#m,rM0HYE,*icdiL(SUHZa&qm!0MlDKS5ELif44GPAGfpEc[kh9k`F2p$-
-TFjBaU,D8ETkSF,hqQ$P4XEU88236KM*k*I)1am8S`24qeb[63Kld'3BB$m'DP,K
-G*-PUV!)VP%[LM&5D3,EphQS(r(UkIbPTeEqG`134R`Lc8JfmDSE,bhU*+34ZNEp
-![2@0H-a#[1%LFJVkf!J(QN,"P[XX4!`mlI2e$'R*Kej$i+9Rdhi4)kSBc+F$YVD
-95AdZL,mJa`ijS!j#)2pmL[lCIm%2QiGbMK1GIBl`lf-d[%(e8NlIaIVNG2XY9I`
-r6&9X2kEmU$k,$AJ0`-c!bIED2QYCr*CT6,5BQkl8dB8P-&lpU6lBYEhiH[[5FL2
-AhaKIMhj1DdmF&+8G1rFaHFd[M,4KK68YSHrJdf@j42``r84Nfq0k"TrH$eJk1RR
-F`6$3@a9@1eA`AhXl"U&MlJNPcelaib!!X+ZG9NkGi*LYqaq9L(rf2(YFKhDcamE
-3pd)Z&[5PYH!3T0P5E+E1S8N4kE8cMMXD4Feja#@VGNC#LK53!'Sbp[R1KXTrY*H
-(aiHj8q[FhkmCBFBCRCbGQP,EBq6IU(3dcTeh#R!1j3BMK@PMKBI$eB3H`1("B1T
-$Zq)V`GN&RjNC8@)269$ade5JTJ#c*6IhkATMT9[,Y@irJr0i2bZ0h#T02FQ42+e
-rF*!!P606R,I`32"*IkhmjB6j89Z%r#e24Bm#NB8i3I4YX2DU65`JK#[j49m!Tb'
-#C#,KJAJL41i8SIrlX6LbMMjeaIQAf-DTI*c"2GEG1`(lXI(elDV$mYV28VcBEcZ
-Nd@-cadT!3"rHF*DA)ThbDP6ahja&V90&'NbQ0U*(M1AMYa6r#ZVeFc1lj#TME$S
-[TYK!iU1Rmr"3[EJE62ECb0VEBHLCr3[@!9NND,U@-CCF,FIp$XL421qf&Z"Q1Za
-3(hK2-@Ki%XM"$SRQk%mf(Gic6D*-l&8HRc"J6jir,dZ8TNi8V)ipheIS*`513h&
-Zr4)b9f06&-QE`,MB3h$(r-lGIrdSKaeGYiQB5mbYbhiLLKZL$bXC%M*kN9mPpXZ
-2U[D+A[,GBHkP4[Ai+h,841fQ1hPVHPrlHpjFUaDfeAFH0Nqr6k"6Q@TTaY0U%'P
-i$&#)%B%!4(*d#"rMUDY#KSBaXM4ZbIrea!pj8r[`ih5eGh(EZB*(%Ecj+`+LU4e
-@pbdD(A,IrfDC'6jFAUhP`Dk''bq"`0@3!2'UT2%B%j!!Lh`MACF'S$(I'*1P!F2
-$Qr)*8MlS"(Vl-[dX8M+$"BZf5e6)DKiZcHrD)i42j,RN'bl8QjcA[`b6effTJpr
-GdpDD9R"Z5[Y0"a6$FUTQ8f,BN!#,YV1hCQ$eTDEMACAX8`XSJdB$266P%2J8p3U
-cJJJh(EVf+9(Nh*4J-99eU4d6*Ya"'FE10miEXZNI#eD$rfM!R&DLVNGmr#@$[X'
-XCP#`p[rT#`rS'6ZMT4aj`rhEeVkV95#3!)FHK"V4T3VL!kMGR1!+XD)%*,3#Qp(
-cqN`hXp,0DrCG8R5ffF,GG``r%!1%4H(-lY[S%HFb%0(ckcEH$mD9VPcm2K3X43j
-,56qmZpKf')D8XQ68aKq+haZS'Kp%S&pj+ep51Rfp1S2$b`@C[Qp%%Tf0P6e-GHL
-IYL6h,$5*1kY*[I44cL5Q'CR03dZ'UZaEk6"El@Ld8[im[ihdkQ82NYce'ddY2M3
-DrcPh[RZ@0[LdhZkId(X8U5`THChbi5UHTNrPb`Y'FSp2!Ufd0)TE@LmVG'#mQSY
-cHM&f&jHiBa3h%qNDcAQM#lC#D@1KY$RdSpIEe!UE@U[5Db9Ypa3B#6(2ICPbED9
-Z+m[mp1$K[B2-MT!!rhp0Z&qA&4p1XC0r6e4DajG1&DfFirY-("LN"0&AQQ*'YIN
-09SHhf&a[R)`l9*Rqd*,j&+3@Nh[i+(PfIF+i02`,"aGI*XBl-4h-CAS%3EUq#Fq
-EH-q`AJaKEK[D#1m6k1C2eQ&Req1e0RYS4S&BbeSHYr$H`1e82'Bm1d!B+BM2Mh,
-UU#GkPS-HZAUrFR2HJ3F0#EKaT8S)Z2K!-T!!1ZV+j%3$&r02,+JE$QfGlpEVQjA
-!RM[E*r"fa`Ma@%,XY!c636A5@4M(61-HI9,(eYBMIc4NYr&qE'3aA!dNkhrB`I-
-"&lYPqBUGE&'@CJFMMCm6+N'AdRiCqf0(Krc%MTNE`@0Q5B[JYf6E,%+kapcN6(p
-CXdKKriRBc[YkKS'QYRXqr4cF(C6kh53M@-D3!$RGU41"FdmDd$j*L$K)%#6N[Fe
-E333L$$djTVZ!XSVRIA89TYA#fhd044KCiDfU#!X4*UNR!FEU5jZT1P$%&J+`[&F
-&[G4E0mc$6X8LDDD45i9a+,Z#F!bq+qDV%(1(31TVq41R-QD9rQYZE6TZ4'X"['G
-pZXe"pkJd0@Q'rVA!)XSh#pp*Ye&))3eh94+L$qN%''l3PAbX8HjKCV5c0kj$"-U
-%&&3,k)[@'k#90L$i%M3P,,2Y0HCUMPT$'@l@mVQ0mUQJb3F)h4cHVP#iZ%S(JFp
-V+%HCD6))+jTYkR4dNbaQa3k,Uq`!l@fc1[HI1j0lS03R!8CN4aC2$RCG8ZeJmUh
-+(-SICRFCmdES,@),Y6YIeA!)Sl*#@cJ-#[6G,TP2L#fDE[Ua$Pe'Vk56)!#K(@-
-rLbcV8*!!`bDU"A$QG!jYc1hkYL)!4M"*aETbIlfdKjkT9h!4X)2E)FY'!2PUY2k
-M2+hpq8$Z891lB2dF6S[#63P#Si'4%Cqb,9r1$&cXLkd9'iGU[B[cp%`V#AJc[89
-NN!!m#P'D3[Q3!$LdXJ&aB`-,DTKh6!C@,fh%Ulfb!bEXDL$`,,V1F1B6K4)d+B+
-bi,8TlchY-4JfJ$1!X8pURN'P'mIl(+j+HX8!GRdp@B!,UR!I@k$M`10kG,fV1HY
-`KiL!DqS%8C(%3+CdJ(cm16ErKkNPGTJfeFEjHBjUNiK"p[DNG#(I055!bQc#`Y&
-TY`RkMqHBKPS+a'8%9pcbjH0TMK%R8jkFLJXUS5Q-d+$'+XhYF42dmc8Tl",M#IV
-`kC&-BmJ(PKjj!4Ed'q3B&HhV$liq&6J6Bb%(j3R3I3L0DLJ1dr1*[I60-+m!Aba
-1h#K4UmjR@l@P!(Ai#JVKVB&3+,S9ME6k0P#miH'ARGH'`pilLI9&&+jIE45'"9!
-U&r$$[4i+NqT%5IT"bT291cC1Rj!!cFqBLUAP)e9)Efm09Yh[*'NK#V4T6mTYNH[
-Kid0RR[P%K`@bmM'fPkk9#DRNB[DA00-iBjKH4Y3&BE44,0PN)ZmJ(fZe$#G`d[9
-j,I&i$"rm10H6Vak!-RF4b5#YhX"-eE)e6!UE54&jH8FHFj%Em$9Mj)`V,(8cEkG
-6Q!8)"YIlEGPX30Y#L)020K*YQ'XI[`K!i-Yekpm'Em9Bpb&p1XlV1cfXkc08cD#
-8Dqh3GKE5U3SY5U`DZF988BZ2,8$P[hITmA)M)qpV()%AC@8R+@bjFmQD"4dEA!K
-6N!#)"GNcPQ!Ea65X6Jh[kpDF&jM9Z5NL46qp-I!9BDm%*pG'L!i4#[@&l1k$&`!
-5,E4meC)KXI1*[L#SqVlXSGq08NYf6j[*(GZa[@m'h0(KiRG*j1jB!Q8hkp0f8TU
-16BeFq4lJ#-,Fj4I$,-6C)Gq#P*Y#PrCCB[qIF(M(4Gk*L'$Dj"Kk&h%F-,TZQTG
-6+TQA2lH[@*80DAIQDc@5mQf[X8*R8SjU*SR(MGE0(IT+22XjRYHRYZhFFj6VJ*3
-XSMhKj6J+0hB!J6A4RPfa,dLAbh!)JeRmY*f$YZTQY(rQ"#SDeKP%rr3UNXCf1Nj
-l)R%(B9ThBEae3aD%9BU@$JemikpMlN!,[epU5L%NH4M+KQV#!(*["`T5MN4H,`E
-6Eh)YKhQmS+QP0PLREIi)(GSbjC!!+$hS*kC5i&E*b[m9,3TX0BM!JD#X+Ta!b8$
-$%#j0'Amlpa@M1mK`3LD+JUdDUmVl#EIk'9iB5!p+PZ1)NDBk[,FL*5)+cFRlbdL
-@*AIG*D!i("%hZD[)2FmXeeQcFVG2T98`D(ih*[Jq3mkSTmS)RYU&%VS'`6flY@%
-plfcZXGMKU+%kmR1J@0P0p!&pa%$4KMY@EHYkBh[+HD[5pB9-+NQhk,jTLrqIFB#
-8%446'GeqjG*'c$6BJSq)MEV[i*Nh1hQ9`E)%QeT0&hkp-q**#C3'6MG5SU!!qDH
-PFh!$*)(q#N2i1!`HfKZQ+QV1AmASjR"$jJ0*l51X98J1V-,`I4DMJjV$T"N+$U'
-4Z'KGKV@+r%,'IKJTbf"-##"q95$l'%Pk[l@[1p*d&2,XXmVP5Rp8QS'`XS6Ae%4
-FiYEY!jPTN!"ZA,*FdMpY&(m*KdJf[iKEY`'IJidPC-"Di9G3fVc[eED[J`CBI#R
-Q-eq5rj`)MR16)J(m0DQUc&k([45p!-TBr9cB!XCV#I4bZNqITYaZ%"-5PQSZF1L
-G1f+E'*+P$%PqTcT+i(T"PGj-eI@*h+fNGjk+X,+`ji)#VVSVp%"Q4`Fa$FN-++k
-BNiq-,Dfhp[VZfbX(dS[l*X([V!fjc4Ha-USb*AXm[GX!G$Z8L-+-ihMXQ,)[!kb
-+FL-@)fkUR"3[Pl0Q@405Z$mkIb@Da+cmm5dKRrk0U"l-)EEG6V#6%,aYq8jUEd1
-c2[6d$QS)24!e6I'rZaf-#QfVUmeB@Pb'FKGcDIa03@lM8eX[G5I4RZ%-TUUKr$r
-8Na#DlUd@3qfmBKl$r4e+jdmfa`0"8$k[eGhl5IUB#2a%U-qGbNd)I38[)cPLk&G
-'Xi3YK*6-2d5i&XrGR#9S3b(1aH!cRr#`dTdTlp@--c)*pR!iI'421*)f*0*`0Ap
-J@`qUT,M[MR2kiRdc+"l(QL0iA[caYbi$bKq29RILaq@A'&rJ2IH2`Zp&c9YUZ(k
-j+a+bFT&fE-KrE9'KBVPS'CE2PlXQM!*ErXU60["D*Kb9e98Y4G,rPCX"Ce)%&m%
-q1pjr@-0PK8jSY-PQ-6NF"M1E%-D%4VUBZ4b4!`L8#5A9&BjG18&1brMRcVY8e[Y
-q-U,f`p@I,A-rLac)Yrk*JTAQVB#%iIleX!fUlYBQmBm3Xb#`'+L0+2Vdb2""f6d
-"QSBQ)Si%d8`Y228*LaE-rDrrj2-!'iKG,-6r`8BZqT&23*Z)S9h1$rAMX1$h2eQ
-MHMBD'I)#N6Hk4*S[kZ@`**Bla9YHG94k5"d9P-lU$KAK20TV6T!!!JC1h5Dd@M*
-je!0pAM0A`"frX[9K6VpI"A3q"G)XbmmDLX2B0ZP#6qX+Uk*U6jdlLGU`ERB4rkd
-IDedYh8-4VfjT*mj`lDbr#FFjm0h!L#9Pci2lZ%pd%!39fST,em"fMRTbqNK8T9+
-"6Y,N*KU5HeX013hY`$aimV[BMkDrBXSkNFeBc(#NIU$a%rNGr!M+kF&X[DCThXX
-SHH(c%hD#*EbXeLDlpa"3@G0QDAam'08Z5Jf@h(G#jR-"1D@0#9+[C0iVQe"''Qp
-#G@kT4%fc*h(ibjAY`#$qerB%9T!!hbF,cal4,V'U%dCL5V`kbD'CLYZN0kmJ$V,
-'r44IIZMbG1KhRMHV&dTUkJK'@X-dS")I,#BYL*!!HmL20US*+3KD"`-V$BDlp#E
-2Qrpj%TVD"&0m&FQ*k'P3b8UBU&*Q$FRG)"9)rP&iApDf0SZfqXmJl+Iiij+PDD*
-rPTlVL$T`@G(AP+RAX6T)26bZM$40l*Q8-l,0elkhelp&TT3GaG+&9PX9%X89Z%D
-fpeSYHpXl0mb%"aiFL"A-Eb`qp3er9"!!)hFikGqKKI*(*(H3!*R[M%pqP5pIPcP
-8cX9!*6*rpR%hECB`d(J`T*cbNRB[[1A@TTP`lFQc#Ej"eVV3#*`$,jD*T4m08(m
-V5Z8p&@rH"hUZJ*5li!S6$mH803Q$ERJi6iDR`%$Y9FqV,36f3E*9,K(pC+-i+'(
-1#*-*!(5cCIk'eV$V1l'1b5B&mQ![9iGIk"&4V%-Z'ZB(ieSGJN*"S3,$qd'A8!S
-(Ek#5KQrpG9BN$)FJYcFVkCa!M2550)&p&p)p'lc!F9Np2`N98SM$P#IbJc%cmR1
-`mTY%XlE%m@N3,BBB#a'PEk&((%4HRVVPk%Im,F5Kfi9m%D'EL)m[(ahjXRR@aT`
-Y62eJ"BmPHX2qM`Li!CcESF@$eF$1DqHUjB$UheM1-FIlA+CidPQ,Hi&pq"PP*E1
-GJ0JH#4%,j3&Jd6[@6k"+PVkIaA9Shb&&eEI@i[rMYHefN!$qqph2,$PXBE+QlU$
-FD[&D1A5S2a(b'!F%*ZM86NQXG%@p3eG8dj`Xj-Z!6c88qDmR2hEG2('UmG-6Xc6
-HEclFTiL)bk@%S`Pf!TcjF'-ECaY1ISa#[QUhXj9GX)dR,mRrY-E%kpq*NjZ-See
-K'F8NJZA#HlA+mNMX52(b-S-a@Y5$J3q3!2VUTF0ai!FpN!#G'JPFKXL4YU0icm6
-$@L`GU*k'MLhL3r6q4A`,#1dPE$kVZ(bDpBHP9DPch%X4@9p!Tp1kd3!99+&AX6e
-64p2)dM+#NeJaBd3-2eh1J6r)f,bL*`N@$4(MFirKd!`qPSI8JME`IPEMirVF1UV
-3Q`!Be)[-2D1ea-6deXT2AZmUe+rCESGBCk0P6Hl92V)EF5FC&mU2&!'h#E))l6-
-ecRL8B$RL%C1Sp-[9X-IQR1X4Fi1Z8e6pd#9iXDLeAL9Z8hLTB8R"H[+X(`p"PCj
-%)Crp,f(A"YP#pBQ9K`(43Up0E!,8Ym*BKAeE0$8"rY,0Aj!!#Kp#5%JU,ZK$5Gj
-A[3N4``VQjkmJ-+C2!'MXSBKHbEU+MpRh9I"k(5$MM)aa"8ba)`1I5i"130!hm-c
-rQrQClRJ-EDJD)331F"AHr(k4P(1hJh02BrNh-B%62Jd8bXXcQjpTI2*c49$NZP&
-P(8FREhlF8HTZ2JAN@E#B5eG%SU,q)p6qqa"BU)$aqPfU5BXIiVe9K%NeYadfUN,
-2ceGpIJSiT-#R,HD%pJTTG9E8Pa5Sb4if'%dVlq-JT0$"AKX($P`kYCJ!154($61
-AJRDJMIU!pP#+'rAVkPDK,224f5S"kYi##XL@RU*e$3j2F80*SI(rjb)`LcTbVG1
-HQr,'H`$LSbeh6GpJ98cH!R**!F(TUcSmpkV'9Vk$aGQNXh&U"ek,&&e*!)%,SRd
-#`U&b@a$J28CH(GPU%!T,D6HUCBYr&CR*P)rKb!`NR)$B+%fRQ)Fe658RFLIR8Y9
-FVFSZFC,2ZbHMXIb2rS2#LETKc(6jmc1eZ+XB,&GIJF&Qlmk(a6X'hBk&PDA,24"
-UhMPA@aiJiF%FKBPI[(lFK2-66-Aj!82N4NYk5!kq@TDM59Y[fjm*Q%F*Pf4K9kc
-fB,1"rDKCY3k+H9mSqhSp*hG3'TpK2"ULCUdCJ5qq*Ta'!c0EfH3Hj,LelZMa%@-
-*4*!!LlVlEhMQQlR`D4%""e[MG(MHfDNhBG5S1(jY5C&dqe%YMTc%*&#PJ`*FJZ+
-`MK2((l5Z'[94d)LLX1G&@PjR%AHhjMh@H"9A'Tr+2FbkVV+deM08p6RE8Sl$62q
-"+B@02AKH"6RMhdf(cG-hA#KD@c-IjBY[Vkj9f6+Y8`bV8(QNMS58d%fD1$jjC"r
-!TRACafmrA[)G8Q9jSb,D`Bp$f#YbUKAELT'K,dUch)EF1,N3%XKXPZR,rm-D@Pe
-Q(qla9d"N$D!&Bb#!Y0*8kc-8+Hf)1`%5%aKcP9'(ClXqKViUq)r9RkH9f@FY1!R
-XfRRDU)A&RdmZLVp525#FYjYp%Tk1e65ESF*JhVIlC[[J&0LJKlbfB!mEK3%lFbe
-Z`3&P@$hfERG6bVRN)@E2)@@HmXB)rmX9mim&8$aRk,0iBEM6[1TA8hCpV"PGbIe
-Y`%(S"VfcUV`&S'qQ((HMT""-bqPe[YcUNjj8ZUCA5CKHSRVI5+"%i,!SQBQ$ff+
-lP6&cN!#dKbcMBebi-TXIa5hKUBEB`p3#$J`J"$rE[Ibj5K&p8!FrX-IFQp(SM4%
-5aPrE1j,K$!R&cp+&[H`LGYRp[Tp&hkFK#lj30+-)F3+&0d211[j+dl+T`2*2&HN
-6X$VhK-GppdS-aHIlK+*Rl@`BKk!,k2P2NA*UL&3D%VZld$SSCK&VF6$)a2IUa,H
-`-N#DZh1QJKI1!bc-ilPX"0E4Z1R[GK`4Z',!6m[B"9qh$5Pl$%@f0B@V63PNjN2
-CXqe8bVQRXd35PS3a5-a,I2Na`T'#3!i))Bp0%43!TC!%!3!!-!"!!*!*!3l0!*!
-'!6!!!)0Rrj!%!*!+TC!%!3!!03!!Y[&1mlEa6[-!!!%`!!%YG!#3!p3!"E`U!*!
-15@0[EJd!!GZmD@0[ENe"3e0"!*!2J!#3#3(Q!*!$J!#3"!m!3X(8iHr%)(JHNZX
-l)T0$PMe1&X9%h,U"-`j,RCS+U(NFRSIR`'$MA4ifZ1eNp(bc"k[8Tf29`V5Ebi-
-dlUp1aif&(6j6c4PRTLP1eK5a-h2EPVY&cfClKmZkIGS2aXQ*%PIPjC5M%Hph@9&
-a(ZfDKkIUBkh$)JJi(L3&)ZG6@!#PN!3"!!!`!%!!N!N",)d!N!I8!!#,Z2q3"!#
-3#U@3"!%!!$8!!,GD)G+h@L(6!*!$e!!",Si!N!0b!!@JdJ#3$NPMEfi0!!(EMfP
-MEfj0380633#3$i!!N!N"jJ#3!i-!N!32!%,"e(hUjNKc6hS*X&!ZqFG%dkqC`#&
-3,a$2e2#THbFLNpi5*Z4VJD@If`"I'V#EIfh'MSlG""q1a88iE&-14)Qqr-Mh6Z)
-ZSeCSpTee"5pRNpe,5q3Re3-HYimLk883BP`hF8paMJYi,IjQFS4aSC!!3[jdX&9
-S8p#SmYla(hQ@e-dU3+@3"!%!!$!!3!#3#3%YT!#3"h)!!&"[rj!%!*!+h0)!!!%
-!!!'253!"MNN!!!4X!*$cI!!"!*!&D3"M!(d!R`3#6dX!N!Fp!'!!miKF9'KPFQ8
-JDA-JEQpd)'9ZEh9RD#"bEfpY)'pZ)0*H-0-JG'mJBfpZG'PZG@8J9@j6G(9QCQP
-ZCbiJ)%&Z)'&NC'PdD@pZB@`JAM%JBRPdCA-JBA*P)'jPC@4PC#i!N!05!!%!N!9
-Y!'B!J3#L"!*25`#3"33!5!"R!31)-P0[FR*j,#"LGA3JB5"NDA0V)(*PE'&dC@3
-JCA*bEh)J+&i`+5"SBA-JEf0MGA*bC@3Z!*!$6!!#!*!&-3"R!%8!V33%8A9TG!#
-3"3S!8!!F!4#)'P9Z8h4eCQCTEQFJGf&c)(0eBf0PFh0QG@`K!*!&#!!1!#J!,U!
-#!!%!N!0p384$8J-!!(i08`U6K!'ME3$X#h)$Y,)b+b[M@dhH@qpUpkCZ*YH!-3"
-!!`#3!lUe$)!!#@NUrZ!"94)XqdV)@`lMjA1kK9'1XMr2MrqZ)$NhV"Vi%FU'0AQ
-'BU0RDr#XAMm&lZ`,`,#T"L)i6&Fq[H[,VD-C!m8F@8XE1!X!N!0D!!%!N!9G!(!
-!F3#X"!*25`#3"dS!93%6L$T6Eh*bH5iJ)%PZFh4KE'aKG'P[EL"MB@iJEfjXH5"
-LC5"`CA*QEh*YC@3JEfiJ5%C6)(C[E(9YCA-Z!*!$EJ!"!*!&D!"k!(`!YJ3#6dX
-!N!G)!&i"*BK18fpYC5"TG'9YFb"hCA*P)(0VDA"`C@3JBQ9MBA9cC5"dD'9j)'&
-bC5"ZEh3JFh9`F'pbG'9N)'*j)(4SDA-JFf9XCLePH(4bB@0dEh)Z!*!$@J!"!*!
-&A3"`!(%!V!3#6dX!N!G+!&8"%iJk9'KP)'CTE'8JdPi`db"YBANJBQ8JC'&YB@G
-PC#iJ)&"XC@&cC5"eFf8JDA3JGfPdD#"MBA9dD@pZ,J#3!bJ!!3#3"D3!M3#i!0%
-%#%0[ER4TER9P!*!*RJ&H`!)$k!#3!p4"4%05!`!"%Je6#TXN!$Z+L)S9caE3Fka
-%E"$e,$pr2qcARErRlXi-TeMBB58U@)999@,P[r%%XDS&#l*P1diJqC!!(`&8**M
-k0Eb&Tph&fGe0dXKkNVep(bj$h-@Aak8,&[Q01&G2PI8,*$a+MT*"[ZKdYI"dDK@
-D)Mi&jNl(,(@,TA1"CHpm&"bi0FV-TR9!6`FK$%aAP&QFVF'lCA-L&paq$(JIm$a
-!SNrM'Ub)p-`20hNS80Z-b('VTjc&BeY4ZFc0eZQ"Uj3hhmRl$1Rr92r*E3#3"$S
-!!3#3"9!!@3"N!*-%!Np,!*!&!`"%!%J!k)JC9'KTFb"KFQ0SDACP)'Pc)'4KE@&
-RC@3Z)!#3"%J!!3#3"8F!@J"E!*3%!Np,!*!&!J"&!$%!k)JR@@pe)'KKGQ8JC@j
-dCA*PC#"KEL"TEQ0[FR*PBh3JF'&cFhG[FQ3Z!*!%$!!S!#J!YJ%F"!&993#3!``
-!)!!)!+)"(!##998!N!--!')!NJ$`!CJ!K999!*!$$!!S!#J!G3%m!)G993#3!``
-!4J#Q!,S"eJ#'998!N!--!#!!#!#L!4`!J&99!*!$$!!S!#J!VJ&1!,9993#3!`i
-!+!!S!-)"T!#)998S#J#3!``!+!!S!*3"%J)!998!N!--!#J!+!#0!4F#!999!*!
-$$!Y9EP0dG@CQ)'&c1J#3!`J()'C[E'4PFJ!!"$0"4%05!`!'G`e9$8-L%K(QAQi
-3C#dC4'Vb4#3,%&QVTLBRYcf,M1"fjmK*Yc06mTPrGlr[fiSm'pr-Yl9!NYA1l-R
-N5GLq1j-4NZ9@j)QXb1mIN6q6RmQmfGCf%8N@%l)h,FNL+%$L"rp1@BD49%3iU!X
-lH1)RGL%XdS$Y8-@K&RB5AKr2MQN-Tdqr@5Tb%b2*lEeNEa2deYr0KTa,b#P((lQ
-rdKDbpHCeqFBN#8XTDGMHT"F9Nj*A@5m3r1$*iF)A(Ra+`bCSd@*%bYh0[UE$mLb
-8Z8NZL1FKb4cpaH#,'S2Z2"A0G593mh5B(ilNbH!U(HDq*03V2L&LN!#Glm-GLj)
-350pE&JffVadV0j9c-)PcYTmmT-U'cCf2[lLr"Zb,Dr,j*UQJ&eL!@HMeXIT'U5K
-XK+Zi)G(%4'NH4P'P*SBS*l2%Ke)*Td69NE&*%bSLi2'$"P$iBJ#e%QfCd)!P0"&
-UFSY0QF0BUD3IT`bXGDL,fZ$B!U8fSh08@--BYZrp*)$#,J2%1@+BZ'k&r-qa*h(
-XSZeGPi*0bi'TkX2@JbVR0)ahG0E&J(3EJ`[@YV@,-D*-cb(Q-Y`6mPcZfjMcBMp
-"cGLljK3Rb&aVTMai@-PP[RfUT+62k1U0klXYd-Kcq8@f`RZ!4-@X%K,E)89)*H!
-)2HGQk+!L4L(61rDKE[-93T%lT4&h#Yj6*Gq@)$NpfZfT-bIQ[*a$ZHi9U@$-fpT
-GbR)EqIHh6JN-ELhIr*F2iT-R9S%)rHb*!9X*2'JQcVG5aT+bk)"66"T!8Hh@RKi
-MNZDb1RCPrpLBBZE'f'*+5Z1k(+rRjMiNk%bc`$2Y2dPbk)d[lP"05[[rh(fm5+9
-i5KpCGN!BDPI(P8iGH))aB&$'@AMak[HhZkICP"IAk`20U"30ED$cl3ANPB5bhE"
-dKJq'UT!!'MJ$K%Ef[#TaY#Qi5[JiZdp@*Ek(V6S2"5LGMGP9XcSTH`kX!)Q$@e`
-Lj!Hc!YeF"G@qBdCpV(kpX(EYJl32qi0AAhd*'kUV,i&`%M,25lL3!)9HJTA-Hq-
-JNiRVb1C`%N0V@&,9LJXedG30VZTedYBKmQ8[pD@$C2LX$T!!US[$LD0[BBPS9ak
-e"Bi4i"NpQ[B5,S$!l!aZkDY"[CV-MSM(ZdcHrYqi$lHRmXQ0Uj1Q&hdZmV+6dc$
-Q@CReZ"0&fVV&S"Ua`C3d8JpM+h9[1peJ#QP[H2ESABrbfDQ9EXl,)rR"Y(aV,(D
-K,&e(qXHCLJYTG`ceq9R+jqIUrhj)D3VcIeGqcX4Q-IlfpqABR&9R,NpTEKEkTP6
-FE&CkmZ##0U6Epj,8cI&CH25LN[RmcjI[Q)F-e2@eAFBV*qph(["`34I,9E@$fDI
-YZ+ZVJh8&%Tl"cXY,fjl%2ZKNB,XDjI@RH3*a"UE`8,`*ALRF`jGi-!Gh[Rked&R
-$@pIN$J#3!aJ!0!#3!r-"AJ!"!3!"!*!&!qJ!N!18!*!$2!!&"#"[CL!()'PdC@e
-c,J46G'p`'dPdC@ec)(*PE@&TEQPZCb"dEb"9EP0dG@CQ1JY9EP0dG@CQD@jR1J!
-!"b*"4%05!`!-3`jG#kZ#*$lU%1prGjb%8-8Ke%4U9$M4)k"mV`1cHE"X35+++e)
-@+mTLVcDH@@K*2-mfY,@Gq([e)E3@F+Y3`CU6#q4l%rB@IfqViqmTMVm(#i0NeC)
-kXl[86Qa45-+m*-Y)P`SKT2Fr)CeBA(YZrId!$HEQ0$%"*$3M04p9j!kQI8Mr1XJ
-2KmNe8STE4UDQIi,S@Rhe[I@qarqjqdZ#CYHDLRYFmcXRh'Fqe)[)rKRQcr8Z)jY
-$mqMAB4Z*`8GNQ$3LNF,eb%X++LNJ[Q-))Z%`N@8J`NC%+3H8XKIX1QSI*qQMdQD
-IpGLhEpjV%lmY1l+5fDcpH'C-jhq['[`3jSrETKXX9fHMKlcNER4riBTCqG'#)HT
-h9+c"*XN$@Cl+I(h)QjMblcphCF`KE5hCkEmEJ'dKrURKM#aIRB*N3e24C0KHQ)T
-l$%Br@CYXcVBTrfSiNkeV5'3-b4AlqD@&QA@GlC-5"V-KqeISpU@)!9VF#TrPGVe
-3`$j(GLp+(M+%)bJKr&Sfl6c(iZ1Y!9iHNp3EPSIpCePFTPi6XLqMR56Ea[SbUjG
-DGG,V$qpI@A3Hj0jCf4[JHkF,BhCr0'i62[6hH)6PrqmTD$jIpH[T![HreCf6"(c
-N`HmpTrP+(EbH[''!b&!IJmY(HX)"[R"cV$$bkT!!BFkfqZ%`*Q+HH1mQpFh)rJ@
-qePkBpb0ELS5`[FqP*d'Lda$-8qj%Tj%SG+&FF'&0$-QD@&h34--"6@3i6E!+&5C
-N6k*#4QZTHTiUAUNT`YdPZGKX@*2jFEfX5HRlGNQ6`Y[fJLBRhkjk5j-GMr1P!HB
-l[3'Qm)HHJ"HPEDQ!T2NIX`%2j1DEYFhii,)JXp(b1Mbrp)q9Zl25JF%)$&*Jm!+
-$kJjf`(I`)SH&YIF)dciHP@*rMBUa4$IDcXH3!-q&V(Q`BSJadb$'CXSYUpXb)Mq
-,Xi0GD)T&6U4-SpFIe6rLf`lAZj!!4!fm'%+q8%hL1133Cp,eVX%T8F2L###cAI$
-mL&00G&-%Cd*2iB%iCf`MfF-jf!FJ1%J4[MVRbX'20Z1CcLbH@N1)6)kDFS+SqQb
-1EX+TQJDrTfh#kJ*5aM-q0k+Q%VF[a'CXI#96N@%'546j5+F6eCZ`Y)TX2A,NUk)
-B-Ej,R0VL%(mE&PXrq-#p#2e$Mh`2m[mZZU6[&E)M(T+mmZ5*C[*Naii8P6'D6(c
-bha3TS[J5ABK&@0UBMc(1MV#HAk%1$dlX0f$d-%mhXhTHI(EKj`HhGF*SlVcm3"f
-0R8KeA4MGl##9e5FlJEb)E"IQpI`h[mJ1R[b#0H)%!d,9%Uh1GmIjmI'(P'YJ%Xl
-MTk6lU'PlpV!H4GrmYK0%M4LGSRTmK3Gb$BLAff+Tl2CbF&6Y![$@m5BA+)6!`8@
-ee[Q9(MN+4[41XU3cmMk'DQ'S6h&HI"C4IqZm$K%CM(`cNh-UZ['2M!%2")E[(Qe
-ki1c3Sd5C@fSUeH@m*6B09&BcS)f1L@L#PQ*+KA6-TD%G95+1T&jmbi%QIa"&$XC
-A8%pjZ(#6lN3Mjf1EiJUFd@m[mhpEDRiY`BBack+-$RSC#LEPF![d"pU$S5L'jPl
-JNJjCi#!A!`%J-IrFfDFJj'I2C[Bd0UCE2jZlIl&[h22GqrIq+,l2YIaTXma5M'B
-r@GG*k@i'TkPPB`@qB46N'fV8i#e-mqY#FQQhm,*pdPaSPhIj$G'iC,9Ub5XUlPr
-MUJ4eJF&a@NLbIaHiI1&RqABj*aPfCDA)c9$b&Q1&B+d6")mEj`"hp!LF[E!INQr
-i$5f+0$%85TjqUk*%EUa+@q*c!aF,QlbR+TRT&K*AHmBm`H+'b@!Ybe[DD%JNC+Y
-K,rT32-h-5[2H&`Vq&@3lX4p3qFD#JN-be"TjPN2HL'*jq3e('@KA62r,S8m@)G*
-`Y9bQVCUKQ*,F46fP#De(dpG(,*GddTH@hAh9Cmq89@fhA6q[&HaSDHi-`A&rBc"
-SL*VAklaba4[#Y3N[eaKF#TAbf#jhZMBU6rSp`@$*6JDqIde3IqrP2-(&8*'2lGS
-HTLKVm%m-dEa@`90(@8HSq#r2kiERdSZ#C9dhN3qf5G9@i9,MEQj4F)61!R+`NF*
-EQ#T+d!MBVHi6(K1%BpVk5r4F!%DirSj!pl[YiQ83Vp(a)p)(#6++Y%mhNNJ2e#*
-CJ3JADBr0GlNJA$EL+aRZ3114C2lUKK@1Nj`-Cd`A*&$Smk@bIplmk&rjj*%N!V4
-E+8QIVZ9DXkIkqYr-K5K(p'2[p%4qhlC$P5dE9Uqbd&iR9pd`'&Kc0*!!U["1F`I
-#QD4#UF6[J,+V(BCCFebM0LLP5'&(NU-8pp2f1U[GXf#3!0bTkLKeI+$XpBE#8R'
-ID@5dE+#fMGY9GNqZYN`D+Xf6iI+JTG!R)B'`%6K'3j9)bMeQTe#4CN8`4!JVG%2
-hqIS((dfBili2!*!$'JB!J!#3!`-f,M!28h4eCQC*G#"648%J0Li`!*!$$JB!J!#
-3!`-f,M!$0Li`!*!$&3"8!'3!L`''!!%"!*!("%X!N!3B!$`!3!#`!CJ!!3%!N!F
-""`#3"J%L384$8J-!!iS08`UE*!"rKN@`h6Nj%l$&$Pe,6NmGf`%9!pZaqYJ-9[A
-12LLS@(eX`@kXkXE!2f0r925rrfq2mhC@'FEU!!ZC03eF9Shd`Bj'pkj6'Z`%Xr-
-S&0c&iM*#YY5j)-Pc#j!!hfq#GS,Td84dcbPjXa2G[-RZ+i@%-ma,@ZUD8SSG#ci
-IQp0r"2"krMRUbY2UD[qIAfl(Ujrp3rrlNCBP!VJcDU1#E9E"5#Dm4DYXM&@eAPX
-qBTZhKHeK&AhF&mE5@NbNP,3#F4p-ISc$ekiEjSHQ'HT6frC0h3qk%'KDJ#F%b!#
-F!%bpqLd!rZS*!a&r!2#LFZ%#%"b#J!'#BQ!Y1)Z43BcI$%,N%MVLkQ15c,dSF4p
--hh6j4F3VE-XB!*!$Gd&%3e)$!!#!$9-,@b!$!kCJ`kTUXc#`!5*LB$G,XGYCPD!
-JBX-HkYR!Q&8a#f-UZ[HR8k`+#iPMb,ELGpB!8LMpiEh!JNUia8#RBdJbMUrCpbB
-L$VrTa[llf*mk9dmSTT%&(C'kJKQiSm8DVUKU*k42-JV[4Fi&!*!$6!!#!*!&#!!
-d!"S"'iJE8'aPBA0P)'PZFf9bG#"NDA0V)&i`)(GTG'Jk!*!'#`!,!#X!+k!#"%X
-!N!8G!$3!,3%BL!*H-3#3!cS!!3#3"6B!K`"+!-%%!Np,!*!&!J"&!#m"2iJCAM!
-JBA"`C@&bFb"dEb"LC5"NB@eKCf9N,NX!N!1U384$8J-!!,B0@`Y6-!0hFbeQ"Z`
-CdmT9aMFdilke99E'2fp2lp9kYqiprq)E'J!!m!d!!1Jf$3!!#l)Y'i'Pq!GfCr[
-jjDdYFp0@cGpCf*-4E6ZY!bFUCeRCbDlbH0Gh4)AJ8X4rJKJ8[N3-RI0#5DL'!59
-#J#kS$Yl9"F#6K4bJ',6dJeNIl`L5Cd'q)0q+c@'mi[eVN`@PK4)VLVPbh1Hj`Y*
-8H1AaB3%!N!--!#J!+!"r!A!%Ve99!!!"!*!$J!!Ird!!)!)J!#)%N!!!*JR)!#)
-6j!!L)!)!)N!"!##(i)!K$r"!)K``)#3Cra!S'SS)-M++*#BbmM*10!Bj*QAd-K*
-P&#3)Cr`)"($!%!)ri#!"!B"!!)E!J!"!!3!!)!)!!"2N!!!*b!!!"*!!!!!#)!!
-!!8!!N!1!!*!(J!!Irm!!2rrJ!$rrm!!rrrJ!2rrm!$rrrJ!rrrm!2rrrJ$rrrm!
-rrrrJ2rrrm$rrrrJrrrrm2rrrrRrrN!-rrrrq(rrrr!rrrrJ(rrr`!rrri!(rrm!
-!rrq!!(rr!!!rrJ!!(r`!!!ri!!!(m!!!!q!!!!(!!*!$J!#3"`%!"rrq!!J!J`!
-*J3+!#N)#3!L%!L!*#!)3#p!$q!JJ!!J)3!!)#)!!#!N!!!J+!!!)$!!!#!J!!!J
-)!IJ)#!2m#!J($!J)"Rr)#!DJL!J-S)J)$!')#!d"L!JCI3J)'8F)#"Rr#!JF-!J
-)$rJ)#!"J#!J"X!J)!!!)#!!!#!rrrrJ(rri!$rrr!!rrri!2rrr!$rrri!rrrr!
-2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ
-2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ
-2rrri$rrrq!!!!3!(rri!#!#$!!Z"!S!)3J*!#B3#)!K)!K!,N!!$q!JJ!!J)3!!
-)#)!!#!N!!!J+!!!)$!!!#!J!!!J)!IJ)#!2m#!J($!J)"Rr)#!DJL!J-S)J)$!'
-)#!d"L!JCI3J)'8F)#"Rr#!JF-!J)$rJ)#!"J#!J"X!J)!!!)#!!!#!rrrrJ(rri
-!$rrr!!rrri!2rrr!$rrri!rrrr!2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrr
-i$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrr
-i$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!!!!3!(rri!#!#$!!Z"!S!+3J*
-!#N3#)!T)!K!+8!2i##!!#!K!!!J)J!!)#3!!#!S!!!J-!!!)#!!!#!J"q!J)!r`
-)#!F-#!J'ImJ)"U#)#!bJL!J-!BJ)$3')#"Pp#!JC4`J)'Im)#"``#!J2q!J)!'!
-)#!'`#!J!!!J)!!!)$rrrq!IrrJ!2rrm!$rrrJ!rrrm!2rrrJ$rrrm!rrrrJ2rrr
-i$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrr
-i$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrr
-i!!!"!*!$J!!!!8!!!!)J!!!%N!!!!!R)!!!6j!!!)!)!!%!"!!#(i)!"$r"!!K`
-`)!3Cra!)'SS)%M++*#BbmM*10!Bj*QAd-K*P&#3)Cr`)"($!%!)ri#!"!B"!!)E
-!J!"!!3!!)!)!!"2N!!!*b!!!"*!!!!!#)!!!!8!!N!1!!*!(J!!!!F!!!!2J!!!
-(m!!!$rJ!!"rm!!!rrJ!!Irm!!2rrJ!(rrm!$rrrJ"rrrm!rrrrJIrrrm2rrrrRr
-rN!-rrrrq(rrrr!rrrrJ(rrr`!rrri!(rrm!!rrq!!(rr!!!rrJ!!(r`!!!ri!!!
-(m!!!!q!!!!(!!*!$J!#3#!G"8&"-!*!'"e0PCc)!!3#3"!G6C@Fc!!*r!*!$"e0
-PCdi!!rm!N!-(39"36!#3"KaKGA0d!*!$!8P$6L-!N!@%4P*&4J#3"B3!N!-d399
-c-J#3!`&*3diM!!-!N!1!!!%!J3!#!))!!`#$4P*&4J!$!*!$J!!"!)%!!J##!!-
-!J`#3!b!IU5!a16N`,6Ni)%&XB@4ND@iJ8hPcG'9YFb`J5@jM,J#3"eG"4%05!`!
-"!3e6!Yc@"T2hdNE0440Y!,6j0bkmfddECX*X[UX,hi6GX0[NhAE9eA9K!!NiTBM
-rG!Ak'M5Q0Klla*eVf8k#LE$6%2V!XqJ!D*!!aElq",i'!!!%!*!4J3#3(S%!r`#
-3()%!9#[r!*!DJ3"8re3Vr`#3')%!92q3!e3Vr`#3&S%!92q3"93Vr`#3&)%!pID
-3!e6fN!3Vr`#3%S%!pID3"2MfN!8Vr`#3%)%!pIEfJC!'9[IfpL[r!*!1J3$ep[E
-prj!'r&EfN!-Vr`#3$)%!pIEf9[prpj!%JIrhpT!%+rm!N!U"!2AfN!2mrIG@Ij!
-&Uj!$IrEf+rm!N!L"!&6fN!6rIrCr+Rm!N!089(p@+rC8+rm!N!D"!&6rpT!$9[r
-iphmUI`#3!e48UrFVp[p8+rm!N!5"!&6rrrD3!rcppeC8+P53"AqVprEfrrp8+rm
-!!)%!92q3!e6ip[prpRmUN!989(prprK8rj!$92Mr!!$r+e6rrrEf9[rhphmUJC!
-%V&5V9[D3!rrr92Mr!*!%rbY8rrEfr2hf9UXUJID3!i&rrrIfN!2r92Mr!*!'rbY
-8p[EprIG@Uk[rN!CrprD3!e6ir`#3#2mVp[C@rRrhN!6rJIH3"2D3!rIir`#3#[m
-Vp[C@rIq3"S(fN!Ahq2m!N!cr+rD3"[q"pj!$pT!$prMr!*!1rb[fN!2rrrMrrrM
-fN!2hq2m!N"$r+rD3!rIhq2H3!rEhq2m!N",r+rD3"&6fN!2hq2m!N"6r+e6rN!9
-8q2m!N"Er+e6rN!08q2m!N"Mr+e6r92Mr!*!DrbY8q2m!N"crq2m!N"lr!*!a3Ej
-"4%05!`#)P""9$@99%3!K9Hj'RckIP9+A1THPQ3[p@HHXJkd919ilR0"ecjZZ,P[
-Y"Nk#VV#Y"GcclQX-A$KHA-'"#b!1j!a($*R6`fd),X3[m6M2QjaRL1F40-C6ipF
-JAjmh-ES33mJFfrVqqr`qEAmG!b'AerIr14e@0K)4!J'3""%"N!-43Ji!A32IQ[E
-j"hUL-`Km2d5"rJbZdI4iYUQE[`3Tm6XAhiZ&e28rqjHmNSQ(K@lSkfQ#6r`iVi5
-1%R'3!"ppNiMDBVVe&PPM2LpJ(+*"mm&3LHU40Ie0Ta2I!E(6NmKV1Sd&"12cP@Q
-J+GX')Y9EJeDr$H6H,`GrpKGRmP13!#bEXSf"1qIEaTUh[$@iaYbd'mYIm@8%bje
-mf8Q[*dT#jjHGTGF6*F&@[Y`*SR$2XV1Gr`B3[)iqlT-J)#BF!mrN18-Q*db"*Xq
-Iq-$d9ZHrJBj8$b*c9I013I3G00mrlfl2%H2BSK"2V[aQr(XLJ*m3IS+Y18,qdhm
-2IfTqeKB%XFVLV!J0LIqCqZ[NN!"M++XipJ#IGMNVq'*Ia'@Zre0pE#iIbXiNQ11
-4SC&2Ba+$fJQ#RIM'!GA82c-"bfc"+$+J6QE-GGQH%Vl1l5")aN45M)YY`T4rCDT
-3TH)rIjhk+cA-f04IfF3j$*[aXfAd#Ne&V[$T8Iedj)V%bPk-l4X6hfMqFD3[fLH
-#H8,PN@r2lqBNJi0@pqIGL4`4AIQImFqaqFqaqFp&X11(k5,@e[)$GB"[2AT(3"d
-`@mceeeYLZT9(L*@rFMQMYKmqBGlUiUmUp-GEIrM%PDe(j4`8,PBaG9H$6N`HFKc
-+EC!!qr1l1q*%0'hYYpjL69*@L-TL(@Jkc3ET@%K,bNjT*8+Ta0chAIBL3ZcDBCm
-eU4edkBrm4iR3f818(5LU1JkJXC(AY0Z",GUp@%D3!-QBE2[,'f+d'b4Jr)GXZ4,
-jimk$3im+-C9HAbM8cpIjYh3HK-S#%2[#D,IjrSdE6ldY2$!)Mcc3&(-QCGFq%-%
-lDdBrd"3Rlp8(*jUN!'8I"PX@-MqJFJ0Vl#C(elVC6UrXUXk3!0qXrNM1PM@b[rS
-8b2jq'c(081e*Q1rD,,#CSSebGZ)lIp`X[#!lKa,q@25H[Ce!m)r0)U6jkFYc9-m
-i%*3SNq61qEJX3iP5fer+bKaGJ3&RU&R&Yd(&F5QbFT,BJ$pkMJ6C$d4"`"Hq[*5
-,FpMPSG@fiFhr)"DKJN',eRi%H8ePa*Uh#2'5&M&XV3-&8hmBJZH9#,CQpr`'&F(
-"MV5eAJUqL*41(T!!Ye"%5B'E)JT"'T%IQeS6D6,Z'e1TV-L!N!#4!G&CFk+l0Dr
-*+#IY6e*dQqqhLI43jrD%L#AE!S,)fp(1Jkh#E(VrXrD!HHLpqZZ(c#D6UIkcZ8H
-PPf&(*V4(!LD6f@3IRi@QRYRPp&Nqf`3KYL!Yj*!!a,5*[c5EfJ-ThlMqk&f@KQF
-c[6A24N)[raKECdbGMkT8*4iL`eQ$P+dBX#'Uae4&&M'aa5qU"kT6cAR0KjYbQiU
-XL"b9LM)SQPZDEFeh)j2M[jSdeE1UCmPMaT5F9'6)&0kj1&%h5pM(UB+HY$Kpq!R
-&r'5FcA0L845jkTK2'QUc$1CEJf[bQMjX["HIDBdR1aGrZaJN[+MT,6$@)C0`ciP
-ZBf!#i(Cec9-!YKY2I*UVqRVMT$aQ2b2,qNXG,V[I'+S('8qILIHTUc%#TYb-P&8
-b[5b2R8R2X)Fa"5Sar9hRiZ+06qeG+aV(q'IT8hY9UXE$TVc'[UIfLQLMUA2aVXe
-!r$Pc@NKJ-3F(c-JDbPY5KjqUcKNrZ-B@0beZRR[iZG#8,GlRHXV9I,dTVrNQ)SR
-JCbj8r%AR$2-e!hXRqU$NqDC&UNI`8if+HE2U4E"8dmqq-9Y&mkm03lqkqGGJDac
-)Dbj9,F*N)reSfGL3!0MB%#3*[d%%$Eemq!*q[Y#bIS'Ipl5XmpR3hrcV8r9pBPM
-B"TUIT!`9LiA!&@GSIq"8Yh*ML+VVejLE(cG1VA%eEm@f2h3%l5d6$cGrBE69aU$
-JBFFLeH010CN"-ZkRc'NLp-CIJXK+ACF#a4QbNRCC+4X*3"G3++%XAh0HifMcaeD
-H05Q5c8p6&U*))ZTf96q9X0!,9202'l*F$-6r,MK*c)mX4C!!RSH#a!'5QR2%pUU
-jITZ`V4&HFhh0XEDpILTGIA12a6E4UalpUpF5BZ02k9rT6qq`E$eL`f5Vf(L&rT9
-HZGkb&5$R(DrC!V2S3-KFVh0KiF2"bp[%aU[dVr6UcCDYafcZbJFI1AVcj8fSUZI
-fr6fUeEmI&#'EEfi["Vj`JMePK!+)DHXq#fAiQkYEN6f()YP4r9&lT!Y)cTpFLL[
-Rh5C#B`00(jVIfc(30-hmfI*MBelcHmZ2E3YSd6Lbp9K+mZBMK`HDlMCr(fac`IE
-DBEIjqmYIk`PXr)$qPAl`q*'YVmdk"P6kj-J03!bIXd#YE'i[Rr"aC2T(fq6)2Te
-SDDiHb1ECpiA9$XS1Skbli4S!GJ10NdkG,N,CeL)*iY9!I8PmQdMZfbD3!$d0%M)
-b5#R#'QqAXf1kpKE''#4'H3JjIdQ)$f0Yr[rPl(BcYYdKhfj3%,)NNi654&YNY,*
-kb-$-+&LX,848PKd`eb3+B1e"Dj!!MU!UQG&UTL@Kd(aX9T`ZX3AEiq8bAe8`[hB
-Gc#F9c)G@CeBp3`EHG%CKjXr`c14F9A(car5aMUN+9B90c5KiJb,Bp%eT8UL&ZUN
-"L`$!d'rUK9('+*'-@mRF35i'10l5,Tkf109'rh5,A8De@8'C0mlKRpmR3RBHr2C
-jLG#YfUrTMZ8EJp04A"[GB'k$Se*)bM*Y&bQh)%[&4krYQkcVpRNCQS@%D[2(&2@
-b*US$0Ia@*jVS3QfVNX3@ZSb"%pdaRRdEp5M93eQAD#KAQ2p"$NET'[G*QqfTN!!
-%8(D++2lTk'G0T2(m'P5JM9Pb8Q14A@XdMFBe!0XEdf2Ym4ia!X80Bc&P68*p&A,
-HiQ%dCR4L&-fjaF8k4,ID-E$N8AY#$MSpRdY9N6T@J8,%L*rcB*)eh36+0cV$)K"
-439&#6-5-+XYR+&,8j%E%La6D"Pb#TKki0$Q80mc"`(A@+-6'0&FQKqMkV2YJU(l
-$iA'C-Uj"dNrLF!81Z0%mAIcSq9Q#60-q5ch3I(1+'P'NYJidPe,60H#I*D$%m92
-G8+UEXQaq8@@,+iBMXq+f)$+P&0RMFClj$NHPj*l!hX"6JmdhVHPV,ReU#!Ac`dY
-+8$$2j8Aa@Pi8#c&2HqhT$P`,T#MEIVV$FU,EZ9FDLP*8BL9mX2K4)l+$[$3"0ip
-LMSaKiV)YcT9Ilk!YUCe()i0ld%*3l3eMQeRTf1kPF@5Qj1pcdp%p)M)ifSe$CPZ
-CZ4i!5V&#JAaVT-!d`4#Yi)LD'++$P4!GD%b`5cVCTGUT9cIDiPe#3TH3!,9j`jd
--aX95TNDUYNPPY922,@iZYEI-b'Yqh"iP!)"8f[a&p5qXAN,qd65+,+H(,X+959Y
-FqF+q@AQ"P8c!r`T-#0R4MA!dJN'*6E,$q%TY6''+kb4'Q*ZDf16EUcpkC9,)+2!
-3`#U+AmN@VEm!)Q*!%[$+AZ2aJeQL#i)5*+Kp09'mQ*e#F2%daGZcjAA1VR)%9h2
-"ZH*(@X'%+"-,jJiiThbT&%qQhDV2V1VKJCXUp3!82YBre2QmPCQVDMp9p64p)69
-VNhBkKZNJQql56MX`lC@QcaK%E-+dQddE4+c%Y)p0'd43"QD9)A!3H,[rCUNa$l*
-P)CBI[$8)%Q-KJ(ebij!!Df1ca,iK-F8"N!"d!1kl#akJkPFCE'A(8'N"XTl9,4&
-,EFpH!I!VLTm@%2L'*dS,(S"Sf6J&!NNV`#""!-mXiI6CJM&!(A*2`@BU9YA#$QF
-"6(AK5#'1m1-JMYP-ZDTaIR#YiQ!,J%"CC3&"Ta9A%@Li!!GUHA9l'4YYIbHlS-5
-4@e!#0p'Ya-,%,S#iC5$'e82NCH1lY6&Fm3NQUP$dp+LUT1-&+HDd!"TFqkEM5"d
-jQNQ&#hc2!NdMlf3A&G+bqCZ1h+*#bPJ#-6-0lQ4MTXkqYUCE`&$d$VP[(3"j29"
-8P#F#VXrCDf4,(B#M@MB%lq@ZK-1S,2DL'BP2UfBJSUU+0T*j#,rGSh0S,YZf%EM
-e4&e+mSl,GeL3!&@q-qD4(CSk)XbMmDCr@AH(46H"V4AEm#2lRkL$`*hF[E!%"*'
-[k2V"51mJTNX)K'K#d5iRRHRYNBjAiG+QfJqRQbjF&4ZKCQ6$EF*VMh)(00AK6C[
-m-ArqPFM3p,kFV3i`1pY*(#'jVi`*QYTA"[8Be"FLTFaBT,)i@q#UjmU+iZ+kK1E
-j3aNSb2)AU8SLK#C3"+'aZ!'99ij3hFX9d3%aHjZr"!0PB"pSb#dUbK&&j14CClK
-JHmQqRU,#jRRF841LUjqhp458K)%r343iU2lfX@UVFdEdLePaK4Rl*8FPU`5)4%h
-[aMQC),P&cF$XNLH*U'4D9!LRJE5!j*B)-NmJ6iJV"(M[mcCpJd"mS&9#6SRmCBb
-l)jEX#cC9Y'CENf!X-ZF@f[#cUENTZSM!-9@*[4eQmCUU+-q2a5998BikQZXHa%3
-&&ML5kq11L&i!4Sl)N!$KLZQZR1T)Ri6+FbkSl)!*&6Nf1V#NcMU`T-UFYPC0fk!
-U(f3m&cCpNk(U'HefmZ$PEM!YAR+9Q'j!-dbBhN"$626K`#JBeI6#e#3b!&`1,,P
-U(9JmM'Qr`m8V,[q"J$&MM@[*eA*H4qh#hF'Q2&b-,[!5`)j6('##Fk46*T!!&Dp
-G$[%Q'NbIZTBm5S$)#6eL(SFE4-M,TlVT1)c8CFllGc34NkJBM4NA&rple4T-,,N
-bi#Vd'TJ)A)2B'894j9EY`VY!)5LhN!!UeH@G-pDqASNYl5Qm@,),Ri@0D9'%db8
-,R49SU'TL`R[#U&VM!JU,(kfC+&kV(J+BJ!+ZDkfDLMKclRB["cmY3(%D$F(Ba5[
-D-H(Pdmra+RAaSfSflHE6Y@cDRbED[B4Lp$`!eY0FK3QJGKlS8P3BL4'$df#f(!J
-3!`*bd`("Ab#Uk89d3(LAP'Lk8`H"fX#5NMFY"-`3H@+SY2$[MGlU(J4LEq%QU,+
-1M"""-qN3QQjl#kDZ5P1&a66Pp(i1!45`*dFMmVka8)#D$-5#CJ+Z`J8pKCY5iXX
-YdP804c6G18PM[!E6L%T#GC1dY@+0TPXK52#Q4f6SiFB$2&Y!e2E!FCj8dS*$T*`
-pq$Q+J`dF2"UfFc,bNNG4a0qd"UqA($$R)M##Q4#C+#hF4-!DSZbSRP43k-G29#)
-9G1f0jTRkQSXJDXSjc%NP82[AG**3!)dLC$'U'Q"1@@C#XcI01%N1fkhC01`mQ$G
-)`hBUe04b4+HqCP&KG,+U,GIP,B5,)+V%bAf%#-b()UpG*hE(pLUMc3&6ccQ(+Ue
-flU+L&qE5F8YEVK#&d@Z3!-e4X!c6cee,bp-)'#ke!+$[!KP[LJP)bqmQ!k8,i-V
-@8h#&JSp,f*1FL-PI++r+rFVa,+U3!%A2SCK+A5TlDl"Skk(VV%)#k-T+p9&MHJY
-NU8ZN%Lm+ZQH'$5S*j$Tkl6&5-B,e(K3R4`RmjX%kD8q%[CLaXj1QPB%SB10&d&&
-LdNFTJYU*m+!@5*+DH!&3E!8J@V`&PmLpTB@M*kkJQ5A%HijHTmmdm2BV-@iB!&8
-3hB6NfkpSZM(`*+#q1k!q9(5"e43iSN56U@JZ98+a&@e-&lkaVqd2hjM6cma3Bqd
-TD,$f&-dXjiSjC,"@,fd+SQe`!+H'9BXqLR5#4a*DLhc,a+6,afD+0aX+*j!!mBT
-XF5TN81biZ!#*`2GDji`Y(i,!*`cZJ0aCPS18aN"l4m"Arkc6(qd3UZ!KZm2Sae$
-Yk3MP4EfS[*ILilC[`ZZb8*CcQp'QCDkbVc4kLAQi)r#pD"$-&ILilI5k,($DMZb
-@Ya--L51G-rj3HU*E8J@2M)6Ne!c`N6GGj6M-+54h@dAe*ClC(1fFkdJ,AEdYB4X
-609m1*XaB!,$mj4bRQV+j!2b[VDlC"r)*$ZH!q!bc6TKM[Z#Vkj!!hJ9$p9EAT-Z
-8$`*diBj24!J*HKEGXeG9"2GPDNU[GCSF!&jbjAX)[!raUfch8-)L$0BPcV9L%"+
-Kf,MT!Mm5!M1U,8al-Hh$)LK#H1Q0GSP3`*UE9(F&V"(AUbj4aS99q,Z%Geh#kAZ
-9K2UMDIY8SDXRTH&DG9GS*E)B[VF$"Ab$r1D2NDNkFFq%5$Uk3KG[ml4d"ECM$pq
-)J[KJ6`,aQemp,mV%,IHNKG5L`T%@h*AAKkXVF(c-j!5CZ9$Z[L%YQ5mm4RpYc0j
-k`hRih3hAPYP(hMJ[6J[E'hYl)rfhLh&M!+pppj`(IE%##MiJpbIJP(hiNrZU1Zm
-LNk"#9FU'SfAeBTi49`%AbbL)YM#94&fX(GPUXfaMpld-9m[Sl2P1Rf1qXb@fDkK
-%b(qFLma&BV0`Y`%eZ3aS2ZLF#rC)V(4rCXSC90ka[11Tjl()122l-rZaU#150KE
-,lFD$F!i3#rkI$*N@QfmlQB&&B14iHYCY@*MbmSJKN!#4FMb2&R9C@0&#X2pJ6%F
-6L'+M0hT"(%35X*ESKG"q!,lHL#[Q8hG&IhQ#-Y0M)0Pd"8jMZCXUB)Sb$"b)4'r
-!kZaLNEC*lRi'KHAAhVApX-FFGF8pcZ'SDjr(UFDRbeQ"U5ki6)KB"Dj0'Q%1aL#
-C-N3*+D*cak9'8#YAjC,J@i05KI9#RGf()b,Qiqk$P&%q66)'-C``YhLFSZL1fF+
-qkq+2C6pHcZE'l#[cZ[eVi6,-c@-ic$cmC"i!MFV!AL@CBKk4D,UL2i[L4QF8Rf#
-HGp)P)9J88b*'M61j+q"rS3j*R6j!)"eZqN#1JfhTljD0M'!B4DBK9+2fQ&hU(cL
-X5%KAJBr2kAea,+DZ(SY&TH'b-4`C5`,&1%a&(pc4J*`QGlq"*U"SZB'Da3$ma!K
-q2J8B1@iFUBj&ADTTpP#e)%2Ed53m-,3@jTU5e![!86q5`m!T!T0i13SMI2Qc@%M
-cQIB#[j!!Ek!'Y`H#SQqm,&T0jm8fA0,M#0LpeD&BU$T)SZPeSJR14IFQT#X36&6
-eA%55SqJA`p@r!'X&XCciJ$-dF)B@cU#@YP$YY`rML[(UU,eLD$1FDdS46"D*D28
-Yle#L-8Pm"6mq,9`m2lkfdKA5*U2Bj+hdLJFk++KF&Sq#T@FePJVKiBcEZ&*kU[Z
-NJ*ZJJ%[4k89'V4rNrP)%C56HJ&R%Hp!-3f)cS9E([1V0)S$LYF5NCZbDjXGJ!0j
-%(BTP2mr33l(#!,MRb4@NZCU8DVT9MMX6P)PSmm"phHmFRZdk#8H-b3QR6qfjUck
-f5kf1Z+Tlp%8)%,lE'S4ENeVe1"VDGpG1c4)J*d6K[,q9*`C"4T+0SS`hb"6QG$F
-19DJHI`I-UUdBq&@&A-![9M1F+QX3E-1UH@"V8Eh!$hk&aZb#(p(Khh#RM@SFVM+
-1%0Q!VXAeMr"V2GTVe4XQV$CjAD*35BYhb+PZ(T&"39KiJDZ"Lq-L8',CGG`*84+
-*-X$Z'D#,Q[L'Ak4$r08Y5(cJa58M)**jf$8Y#S5R1-*UIN98p4AIV%qr@DMi"Bl
-LX"C&+4PEe6YdD"irp!+rdS$FfYA9[!VfL3eL0kh'I[Fla,+9)YJBUSeTJhqhhS$
-i*VGbC6h!)i%ENl'-E9*Y)dGe5MK%L45N6@mZGp-2)D%UC3-N3BLV!!Qc4Cr`,ZV
-bLEaC9-6H15JPpfSDN4*HPA`K*IILT%Xhb'IViT3Y-@+,NpNL!G#F[5VP+dUUL!E
-@#l2LpLJ4(fLi26%V$QFNIh4)p4-3PDqFNT,&PC*V**TH0i-jR61AkM-iT+`L93L
-[6K-lA3$@cCJ!)[+kkP0@*)@M#j[I(`2aY[RY@I(S)Y5Q)9@aIBSIJ6L@+'&f9ca
-@SCr%PRCe!4elD"B)L$Im*4Qcq@JV!$$6`S,J3d6ii!NiT%3RkM"PGB3Tke0*@Bm
-ZCmU+5JTTqK3JIEeH2DCh*H88cPFUTm3(e)G8Il+hD"RISUCmi5HN02Z"F'9YEm"
-KHhR++VJ@VpS-bYS1!ACN1M6rE0AUfEi`A$f2AK1Z(JR`0TJV,aBj+DRNG6J#m!b
--BmBGU@I58i58r*!!#Qdb4mR4,$,a`Udm5Gf),6!j!FFap5rpI#)T6GLh'!-+8V%
-K%GcN8R@NGjBl1L3#@A4JE,p`p1CX5K1YNhpkIr3+-Jf*M&[$QqdmDdPZ&$iXTV"
-!SQBN%P0IB`'jVMG['S(UiiVQ3p4$f648S"m3)e0GlNeH4ep1*,T*p-M#2UKfei3
-LSX@5&QK[ZhCQj&+XeGEAkRpeL8T9*dCZ30k6@ac2M1*ci+62H`15iiR)T8JI+TC
-EGhM0Rmffj-c&pEj*8qiLZYKMdermHEFjlh@3!%!QqdFcNF93MkV%CeVmHNPX%e3
-km(S*A,X3m92hbR&lLc3P%H0q-4HJM9UD`X%518l(H,0paqM[ZH1DPYMZ`#YNCc(
-Q(hVNZ2EJ6$P1%3I(0BQ`9dY*$PPfP4V0UDRpd[&@kBL9CcQ@E)@B&PhFAY'qU'4
-ckk+5Kl!jN!#Rj#L)9#"$PY35)`K266`Lf[3'b9r4L`k@f40Y4q(8ZNK9[$m3FfM
-Cm[jp)@Ic-MDEJUfe-P["ii`YD@"6"`d*'C(5%4XNm0iSSNIhi6pl0(U%,bJ4kXV
-SdG(Hr&'Dc-JjFja2*Ke(l6l(%53L$HLc!8a1kjJp*bY$#PCIHp'4r@Bp*C2hpj!
-!Fm[ZcqS$I3**3lRKAq`I1Q@Hf0dlf0rC0pMGeYFEi5krA-MaV!YRQ*!!f+U%[-5
-%6,6e6daqCk*ciUaH$!8LJ&&HYR#cKBm[cNZ"c#M3U855[DTJVcVCK)DbaSNdM+J
-m,b)`!TZ8(5qL%j[&FM4pfSeZq8CUCYSZ8XA#QMkSH1VkKb+6Sa1485&'2%-TQFI
-6-qA8R&cl"HI"P12Tm(#@MjpC5QJ@@FZ`A9iJq,BKLDYhcl4Bb(5@XZFJ-0U$#SM
-!UGHi`'i0hpT9UU6JPP'5Z'C($9aU5e$C3e@U,b3!iaddDe@0))rPJM@E-MX1@bK
-a1JQ8a&hH$AAeN!0(*M@p3lcB89faPN&X4CMB@Llf%lVZ"'88,1$J9"-AI9N[qR$
-FILm$C@TTm3B+@K&#9(P9ME[V%b$`6aKR`qPmpfF@0"Mf"')fFX8Y'X&Qfk@Y8c#
-&b%[iZ@+-0Mer1,klhY+MZJ4h`S!cY#I`cPR4dX-ViXF,U4$pk@$h+4K-IeX[4ae
-Cmf8F+03M,dZ&NrT%hG"[4F6i$5Q+10SPHQ8MDc2lcHrhPDR,l$el!h5%6%0LfZH
-6Q)VZ)l9e)+["''Jij,c*FBL1r1JX9ACL)d-)P4hbSbFkpIE,Lh"Z1"@d-ISaC"k
-S%`2C%[!LE38")%,'2p6G1GKr9VZPqmch"kJ3pj1U#Pq(UPCDaiMqEB8E@+DGK&U
-MjLb"KKfT+kB$@4K*ekQDkja41JG4-QabSMSUP0M`iVl1'EYf(Bj$PG'f[kJYK!*
-)5(1[dZdDj1FSd&FY3kBF[ji5Lqi421K4`ZX@%%dd&2J3+G-FVr%A+aep6hq'TY1
-8Sfrh6%I)@G%HII-IhJmH$99QHj-1$L0TUMU*aQYp!00qq!"9%*YT8-rih1#pR0(
-dPXhh@5(FI0,*@E'JSLG1bB8GV`(iqF)dD(+$XEl&,BPbfRLNYKL1B-2,F1b"NEJ
-d5DjY3h$[P@qdAB5JQ@Sh06paB4G38$Yhm'Kr"K&qM#+m4pKP554ca5"KmdELA%`
-Th2SJ4K,"0j!!3&"j#"Q"8,kULG3%TYG42-$`%YH3!1%G#+MGGPm2("B,lX8@e0`
-i@L6"&A8pFDlDebJVieB3Y!E18SF4kQ*Q*!!ljm0)c[CfpNBQfLVE#NAA,KL,4er
-Tla'1E8)MUGiqpXkNDYI!E35dF""S&i#9ph[LpK'j691A3&F*qU,V"d5BFTZf#Cq
-%b!mN405SI#hk!QdK&8!S,IS(2kq%JZ$0""5'0U1hr-*`13lhp3j1R'SET@1G%pr
-"dH'TrYcdc*6Fc(4C!k216-R-6Fdm``@U#3bf6-,P%Mr*Q*Ub3*&S)2S1%Gk5-Dm
-Te`$JApEd4VicfMdi53X&3Q5XF$5F4S8HL$6#82KG'M,h$YhHhcRChbF&0lL!"F@
-i90$l6@6U&CrJq*[e+D(CY2JX2I##lmfC-d1m!"1aEF6#,aKR!4hZXVGNmDMd5bT
-%!KXTbM1Kb"B8&r@'3(pTX$Xbe'Y!30U`8c)-J'39,k+3!+KJ5&IS1dri10,EeMX
-a'AE35NPAr46PZqYjK4KeC)P1*cQ"G6E2-f'!50ASX[8EEqZ'J-&Z6@mRhhLaqIj
-[N!$C*%H!J'3kZqXGlMHTS*C-b+p'9UipY1H[21LK5Z(ZCA!c3l&5JHD$'i&'BiX
-6k2l-Nf0aJ&*[5d()q+F'+#,PaYQ[FA'jDVFf3[faQ)RF9Nk(Ll2bLN,kG-liPHL
-++em$#'JSlrU#1pMeGZAe3$IkGi1Lm`HpU-+h#EHYc1Y5IHMdIFm&9eNTBSiMBY!
-jKAU,AX&8BCYkcrCh5X'UK%F(LZb#"UVbpG9'dC8ICDZf8l@S0kGM10MEfFH2&9&
-5*4iB66e&aGYH4DFG&J+XM5SCf9dk&aIUNDUlSYp#H&92r-ek5YMP!0$"LdJ*26X
-[%"H*+9lF8Q)EC1`8&40`ER)4JF4FEa9bR%KeY6fF'4HqqCRMf0-cF5bk1k`)4Y5
-p#1@JQ8*A)E1JXhQq39PiI3b)3I%4$9h5*1Zb$DrPU&f,%LU9Y`L-r2A'MVM4fh!
-S4hU9J9H(CIIR&QafP+VG4!e(SYla%NFrmFP,@Al1HM)@f[DU2*9[X8T1B$lp&[C
-jQqF$)2C5Kba-56fNS-)RSIaLA1$Y3IBqSQ`F4C+qD*a#aFZ,aP'U`)3q+,1+%de
-!1AjRSUG1paZ6%mkc-Y[Z-,pJLLG3)L5QN!#9DZq*4eqM6GURV&0d%!639JNiP#e
-l"#lfk#Y0A!cb6)hKB[-%A$&B88b!#,pq$bN1bZIJf%iH"FZNLaQSmc88a5MkB9C
-4A(CKT@8m$VD4F15NMQq3!!9fE`qpAXQC1hJbjCd5NXUYJ8AQ,"p9hL)6iqQ*@k0
-aRjU1RQ2Sp("8pR63"D%HYdc4pKU20VL8kPA"&,$4S!!pf+,8!)'b62fNZ&'eZ[i
-6FR#-@!i,+k(M*j!!eQ#f0,aVS9ka9%em205Yq4c8`[l1XpfR4V8UT3!e"IFJYHQ
-X[)l!",[1m4)9+hECFHKT@RLX"($"YHUhJ`PdQ2AdNGRm"6IrXrD)V[I'2c+'pQe
-a8L"3p"P3i9%p$1H4d'i5[c*KTQjZCVpm,`QRkL#k3fhql*-MA+Mhm*MU,-5L1bj
-*&#G'kXJa19bN0$Rh-NcJ'3j))1X&"3JjT$mM05J#02'KB5*%%c--%d'DD$4-H'P
-L(KH1ETk3!'cXQH@ADij`FTAP(4j*(N8NA6V9UCNBZVfhFc6bZ9kChb"PUSNF8ii
-bUm+9HAm*8fC9Q$,lp-UmrkB15CRq5XVdVe+CIP,QM("P$NU#H#0LG9@bb@hLjXY
-@(kN4jM9S-#m$mcXF-2GX-3$QP`FR*NF48TN@p*8pUB&AR5Bb+jIk9G0%bp4X9fk
-DIP!c-3DJIdm!%e-0Cr-L)#bie2I%i-i)pa`"iS83&9Mm&j))qVb!0`jE1-XQibT
-BE2''E+TqN!"XlfaXQ56kDDRD*N#VAKm-V[C2ST(GLfUqZh2h"!2*898(rDbELLJ
-9,ccbfKd,HH5Y4-&2Lf%HH5LL(cK-N6Il@,DK+[G3B@2P$4XL#k"`VC8+$KDmk`f
-QFe8UhVicS6%SVNK[2Vbc$&4[KG3`5+cMKBA(ZJj94b'T,laUBSLf-%56U+B+&H"
-&PQR`J1#)Z9PPHpU4EGr0`6!A-VD'2h%p6Ff#,TVbSb%[IX%V54f4,ZP+HX%#9RX
-,YSbA%K!h1)lM1MFh(`5@QbbaqDb*8H%B$+pSl91X`15Gh8R0m*kiT"DY-8%YI`Z
-e-*hdpdiDi&K%cdidi8Q)'SN-4r9%4@6)l`H`,8Z[8'JA@lA03$H+G*T#mISmVTV
-50QkMN[TaNH%'IpPhMKZ0&h+GG"8c""5a1JX459+0ZHP5!Epe$-UMcBa4X5`"8XB
-hQMTd[h%XY+-#YJK,)+B$!bq-ZA-4XK@E1RV3"4G%64Rp64eN%YX%#CI!Ih@pJT`
-aa-JCHS18'VNN#NdK5C3%*KP%m@V&0m!ER33#-d,'N!#@N!#KVl#MK$MN,%HP[A+
-e5VX(9G'SeFp!X"+JA+(I#*Ul(USH8@&03Cea"I,DLJ9A-Yb9))*M)5@!)J"!CHZ
-*aj*5d#Ne8M9*SJDd6@8'jNPBkaXB&HK!%T&,5kYDhm$(*Rbm8Gj"cIbB"'`SA!I
-rm%"imaq!4$P01Rj"#bl3m3YDV'U3!1RTTd*a89+XC"F0aeC+6FV+E($mf%3-KUE
-NGrZ(9Y#5C0G'FHdi[cCU9@X0*FLZ8XGD*)+B*2jA965T9c2)F1@d$eFTH0d+"#p
-5#JD`X9VENBP0DX8QZC,mR!cLCQ)VQ0KNR)[pQTSQpH!qM)*"qdbB4kY`$dI4!%"
-*JYA#a`52-i9l+V2KNL*L-!#S2b@&-rL8A65&LeVj492m)Z8P8G(+,[(%+J'$dJ9
-IIi4HKJ'LPH'`pEYSC08AlC`HIY%(fSdB`$h@c+jaH[JeIPa$48'5LBl'+[40U'G
-Qdi38N!!1p3raeK)6S0B')l99L5)bmCQJ+4D-&1L9A+8AKL,cirkKX"*c[93`[QS
-92&S4VS+&r*,95[reZfaUeCF9bq'AIFc9EDKr@E)6'lV!S%3a&G6!h#r5a!(K1*Y
-M(hmekK2rFp+2K0e$NDTB"-1j'He`k!J4Q,DfI3S*11a45[Jp@M8kG%!9Xd@Z4+T
-',id1aBJYb0N%CkZ3!"+)lklD6BaqBYapDII3p,0j"(Dfb&8f0c+c&!P'9YV'&%J
-G%2Z&c4hTE4M-%[i&(M4re9i[GpVPLC!!rZHNm+ITNb'"FPF4'!pd",S#Ji(4`-Q
-!-E!RF$N`,p!8Q"ji2h"(B'1J0&!B5SBmSIE3TT!!+D3*h4[+#Kd)eB@q#VdBQKf
-U$pd4fKJU$48'Nm(aB%H`+cJB(!hDJqR"Sm'&`GTJ3h"QF'j`Dh#R0q49Ha2H6Gj
-"lkMAlNhh([A@H"GiArI1m-laAZ[Gl0hPpVY(h$Vh,,IC[GZGi8ja@paAhBqi&lR
-VhAHiRh6[m[Pp`ckGEjD[clIEGpjh`(ICYm$Ai*[TQq[EkYYCjLZE+NZ8fFS1Pl@
-9R5ilAlDrV+TXH9PefHbbqV*TC6HAh9Hfbarb9rK(r1hq(Il$ISGrYrrN9+(i"ra
-8M6iE%f9f0Mc%KrPXq"SI1YM`Th`iaSBAqE#($ErL3jN0(q($&MDmN`qpE&K03pm
-Z0UcP`meXq#)IhX5'Ar,Kh@ciVhci"4ZqaBF0E0M-Kl9Xf-5(#pQ`N3q2XH%52Na
-M`m9mH)i0AqI$%fbiL!mlfI"Y2R5aiFriF!FErT)2@pP`0Km1Xq%,I1KR`qNdG*H
-`iIrQ`iIBF!BI2Xk'rmD(FpR`2rK`*KYq`SF[B,N92aC5kQkD)J838`0R@-L'A-A
-ZBfc)PHT1Bd1Z4[FjKDKD,LUI-8J)k`hJ0h`iaPjb"EPlf*!!4i&ECU+UY+)U'!0
-AK&Z`)BmLlc1-rDIk,AJhXUZ1FBBlf(!q(ll2f1[`Xi#ccfELH(4iAe5)Hj%c,&G
--r5ZIXV!Mh*Lm+@c))m+ESEMJ+'H2++BZmLQABZS$2N8+q!NTM`Z4&3a,1)0H!G`
--[AS&m-J1NJ+QkC8AI**YGaNIAXZ'cr(K((E`(rP`"K[bJ"9mR3fjq3BA+&#B4bJ
-%,f2j(Rk@FiBp#UA8FBBXaC&MI1Sd%mN$5l#0$EN4"JmVM'8CCpr''(M!$UjNL(1
-&"09Xq#`IKYM`EfNBfSRP2qX4#ch!KLrai6@+DekLDd,[+DB@mLPP!(L%6p8UTVl
-&TfS88r2je"l&e(rbU5b'eXrjeIFbKZrLj`TRD'--A2QK``a4(M%K'f-r3NE2f8N
-"Ib$ceaYe++UimYpS+P#LQ*V"TcDcBa5C4rM8YBSTESk"paA(lZ46qJ$!83qmU'$
-J84pBVTML35CJ88`em+PFYVfMA%L-$Dr`BB30Mr"K(aYHiX0CE&M(KcSfr*J24pM
-`+Kp'fI!$'SSL0Vc-Ke[BN!"(1dH0KJ[jm(UQJLp*qB5Xd"H!h'6%#f`iM`qAXH%
-hqA!q'riR(k+,'[%q+bMfB[&2V)JaXJ&99aP-Q963jl-A92#dX3'*FV%"AEQ*(5"
-$d,%Ahm*JR!d)%68E8$AURASrmQcNNJ5Fj)P[fcNimb`Pl#@ATE#%dj58+N5*N!#
-mGNU%b!'BQ4b!ZH@Nm,CTNe'2`h0L0(JqZ-"VN[i&Cr2&L,F("cY%J"qYjNIMk"6
-['Zh4k@+"-!Z0Q)BH1kH*h5*GR"HA4D0i%F16BLD5)4c!FTV)&FI%#6&(I),"FY(
-!*kH*qF0MiNj5,"De@"c&iX[B!AaHM+AMXbb@Ldp6l$`qcE'6q#b*RF$RpGKZI(i
-@dq$c3Xb"crq1pH(c(l($q(`5km+R2VB$RmpLfr#C'@[(jrXa'CmjX4&m2Sa0i9-
-BUm#R11E(jl%B[+c95%,T0LXf,B&lqdk+N!"1#qiY#m`&@2FkYP`(YqfD`-eLIZ$
-$`,@"RB'YJFf"dY"+84hb"8T##&LL+E3b8!2!,aTU%3fKP4KD4,ei$UUi4X`9'`2
-ca@C4,,B!K23(21Kc5!lS`'3,Z!"-QJ2j!8hJZ8"ei(`J"U!bM3[i!XM#!6``$iX
-M&$La1)S&+C'##5Qa#JY5ib%X8V!iKX8j,&l$JY4BKm9T,(j+J41,+eL3!"S[B@(
-#!Pd-"TCLm6%@T-DV@(4Jm3%@#5aU+("LF4',&Lb@Bj(%iL8X3PJX4'5@B2'h@$b
-$a9GBh)I&GbP`BM%ILjZ`3*HEiJiXjQ(a)4EIT-#*a50Bc-$L@eM-aQ)"&SeBr!D
-,@LcH`S)8X!J,8X$Ec)LqB%EdMpb)rSNEdGhFL2k&'p'eh)LZi8Ed"$HL"lJ4hFq
-0D$-hSYpb)lU2'p'[Z4%pa)hSB@j%TGb)rX#0k&IFL*lK4[3eEN3lp8B8p#,Kb-r
-JeZj6MiQ[5blVS5d+`eVZV+!1"[MJ&5HDpcJqMB[k#4GeSej8D!C%,@HLhQHLPLP
-%(A-Q)-V-"lIb35Yqf[(6JamNY(,+-4Y%lZ,Eq$EIaU0m'b9m'p[j0JVij8AmFTA
-fmX1i[*PGrZrXmJj-@YMN[l(*BIj"JNeNDD1i#AQ(@j!!I'BV%MK9SkYUS2VB*Bj
-b#)QmJS5Uj58Nd1UBT)H2G(a1ReQ6KXrS+ITi*JdI-df*'Mk`d8GFTQ0LkmX@cYc
-cXS@rp%XIVS`2UGXh@JCA1M2iBL-jUI'$,dS(4"@1TqN(H0AfXZ9l&QF+&r"rRI[
-j`Z2X`DZPB$T-%lFm!@Bbm(USUTSCkVmb3feNKVUB'@S$-p6Cc&"rb3ae1M28Rh0
-$IBiEkJaZU2r!$I@IZD'qa`heapa3jh*$[BXEkKhF82r)$I9kEUKriSEkhcb+Eq*
-4I$12i[r,ShJMMq+Y2)Vr&irL*eN8Rd!drF'ZU4a*d@H&H2fSFaYI(('ZT-@ArqK
--dU+f'TRH(JMC`XAqPBYpR)[p#a2ViadK#8AA*8K-car")T%+3#B3+hNh&P&lP,N
-h8I)%'h9h)KdT1%E1Rkh-%B3bHJE1`39prM[Ri)lq#"*demU1fV*CP1&lEI5FU3m
-GYIQ-dkJB3GFpIHLiai6N-4hLX-l#&chY&NVUMXl0(d&LH$KH&ab$!pJbkQJk*&5
-02&(kE"Tk"AFb2eBGJ[#dD+jj69()RR,GKh&06j'hVFF[#ZECFJYU%rl4)qPVRfM
-Q5G1e)TeH*0&[4`,'BqCkUPM-DjcHrG0L,DrN&L`50YfLJZRYL`TQNaUT1YHlU&*
-@T%HQa`P9)bF!b4QI48,0HEN*U2&DC!+3!(-SUEF)"*!!(c@Kql&BK4cmed3V%T!
-!bF%lXC!!(IU%D3`dN!"FaTV`+SN%b'V6ZjbiJfj[H')U2#DM9G&C3p6[3E3K%pc
-[[$I"ZQf)H9[HT`l[d&P--,&fTX@q"3kZKekYbKI'H2dKqdkmfS%Z*,ebk,'k+SX
-F-VY-,LckGIdhrV-ZqX[h-kENQH(rIRChjN-J80X-"L12j5Lkkd*d*+Q,-(SJMEk
-M,@h(6jZPlLU3!$LeG3+G[lhUDUh$`-m(4e[Vd(e60!FGVP$RL0qZbqq@(HM@"4e
-PmBRcqGfa)QR$hmV1cNM2cRjjachSi1Z'HdiHcmM16%[00**riq"qUI0@l9@H$48
-rAbRqlm)N#dQBP1#%NTp`pY49XUGe([c2"mmI,iGTL,Jidil1J`Z86*8fa6R&kJT
-XkIcG&"Lq4EVVH&C@6LUl4N+UTBpB`e(AXJj*DYChH!)N9Nimr*2@eMTNa5$KkhB
-0SA+L1mG23`N9C8G+G)J6)SRC,"hPRC(id6&%Gf9@5Ibd"9VaYJd3Vj11AUIidGp
-Cr1KeLrqAKr6L#m4kL-HV`Q,T'1qS"4dTj+p)p(iQHNC"G,e%cbJi,"d,&dS&"K,
-lI53DRCl%4f+C(+KT&VA26iKDZ4p1K5ZI0iX&Ub(3!9'LYBiqB'V&JpQQT'f@A,0
-LC1"iV#G",bkC5iHPC*jk-66%G9155bm81m+c9TY%,9XXSm@Yj*VA5%Y#MaeD`!p
-4eh%@L4fCY,LQm$b5ha44`FXQDr&`U`9iI09)*cSdJlYUNB,Cb+Xjmr0JNkjLD0q
-REkJj1U#NT+04e0Up*Jcia"5kJe`3D43,IU44U5BEH40T2TK'l0a35MEQ8a,a'L-
-p6'@RqC`@V8*pKe[i88%)8*T&+"8b*U0ML*ccNFcN4ZHJj%iVPZAMmA&)[1N`DhL
-'lq)5**AIAXHFlKq#@9SdB%'QF!6+jae@5Sb2&U25@%N2DQ&GJ,&U(dlL'A*Q5NT
-1LR`K9qj05aqmN!#9fCpV2*JqQBkAH8ZA%S[Z)b(H3#Q`G+QfA(VMM9l$ZVpE-G*
-Qe$$e)8Q1fUE[XUqGh"q3!"#JA&AZS+lIfcY%lA5`C2'1i%QjLGZT8N(@2Mjh3G'
-dZ#JTHKPAG!ZkQ&[(PEfCG6@a(0dG),%[G6!JMT)JKH*,p"d2@YFTe&kb!V8r4*Q
-e61epA1fl&'VIaGfI$@V29kKpPelYX[3302m'+$cer2'8MQhbQ3X(-V262pSJjDX
-++9Q3!*4"*P0hb$9`j4l(`qjQ5JNEYTIQ5mK59b&'RR!+L+efaDNcQ5P+b5a,5-d
-69fNcNpCKmkjf$L3k4eT[id8$3"d1V%5Y3CiS#KRXFP#[!!P3BQ,SH&Hl-+UQ8aF
-V(6mD8UQBN!#9*)3#"R8jT4Fc61El,*P[Q%#!)@'C@`D8d,N$)F&8iGHVSZ3j548
-P6c*9Y1K9)623GRh8`5lfKfeL"cT`iLL[GQNIZp6i0lR8%!88N!#BXUBqlqE1q3U
-9YmGKqQU1S"4*-EV+S$3)5L1R3%PPmTX*6H)#XJ%[+V[,Sm*E2m%l[Z9*KJcGjQQ
-VJRCd,1JPTbKdM4XeRq-GF)p6*8#AVU"+UR5"SBS5J`k4hffA"X2jh5K3ND3H`%c
-SiTc`lKKjN8+2A[A+P"JqJ%FlqT9Gr['XiLEK*cIPmUV2Re6VUdmaFYh9*`lei0$
-*eMT5KZaJ(Bfh5L+qI[Nk0U`A-X*958@9Ile"M4QL48+h%T!!)@A2Ca&D8MA+A!2
-p$,QNS4"Q+TmK6NGJTPEUc,D'$*&9aBU-BG&",bSIecIrC,rk4MXHdUKm)@Z83b2
-Fia`HHiPbdUU'`%e--"VrqJB"KP1a+!G5&dXJU[kBi3&l*##r,Rc6US8V8&5&DAQ
-iNK69d'D&DQ"Bj9r-,QJ2QeMmlIQ'aeF+E9*(rM#Tq@5Z6RpN#44aHf`3lV0TP%`
-'R6`qd'SQJaMSTSS'"N[UYr(UD59RiP1&#bR!8XFbhcBbK0+S)6JZ`KU#84b"%J2
-(U$')kLR+#ccDFY+`AIk!6fhAZ+d[@9m&`eId`,2q8TiSjcB#*TN+1U8!Ji++"9i
-@F0X"b%AP&KkFef#6(GaX$["Z9R9KL%P"f,)LNbAhLYDD&88(SMKB[iJRqr2[2V,
-F)JF86&%bjjBD*AM+NdPMdbPb`j&-Efe2$&e%1T1*Y5hA6&VX*BN*Z6r-*-p,P4S
-[T0GT8B-+9FG))@G,q3X+,N`KUX2P+d3ec"9#fapAGSj)#'N(%26E1KkSp+CGSVq
-@NSDU@JbA%ZL"4&%E+6$S,bqD@IlP4I2SFR2H6li[48249M*[UA2jpZ`rIc%FMVC
-SU)bfQ+j%@m4@B%+E'0V[-q0T+3pYI66[U&'UFDj&UFBrUe&a*YrE5+,i%0!XfER
-0-2Mk[BE"eeC@,[,RUX1+I)"d8T(rKhRAU9ab[TY')U6L@9%!QDqVU'D&XD',fM5
-95Z'ZYVK%T`@Qd,5"mp494A(H&4BBG&j[dS)0KK@TdX9PkXV&G1%AUdfp[YV822f
-8e)Qc%[3U-CGAeFj0eeHek#CY[DZp4mHPSkY(1"jBS$B8b4)"XTfk+@fCAT84D[H
-L`kSCfapT&hL-ZRIkSIcZM!J9`qhRb196$KU-GAZASVKE*aRXpU[DJ,41B[ZfjT8
-Ki586MQRdKA4XF2UK9*0Z0C%P$bK%XZ*cqjK@*!ZBZiVd)T8*h282Q99@0P*h@3d
-!JM*p!),3M'49$#r1YKpY9e3b8L@arD61,%G45E6`LJ-A8N96XSXB#CKbd'2'"kP
-c4`Vm*6BC(3+LmF+,$5Vb`AbjI6Q[U'4qe6VTXUrI9dj9GEZb5T!!*@3"FSdU3#j
-PmBdQA,r5c)%%J3BY"**)"U6D'#B1REj80VqLDa@ZB,`l-A*2KaYB)%diMZ@-@j-
--R29dAU31c*bK+mpHqfbNkVPMH8r+F#AcTPAZYS"AG'Y`B%DJ4#Gd!+TEfcUQfYd
-cUM6G*p&ek,A,TeHP&ZZ#mjGc9R4a,,',p[EN9kMiRhb@QTm')&S13RfHm+i,T-H
-JpJ"Fl5KVki&,Eh5E@pH"VUDKp[R(5$N05(L988&Jr9G)b04@CJ2ap+Y$FXXTG*r
-if1*YlZR(6UkmpPP%NjGG&HfmQ2$L-6hS8)k-2(8VM#U+4jZV$3mc03$+h)M819%
-*p!$b#8hhrX"lMB,qH)(SeMS8j@3HDMQX)h0pKff8H!2'9a9qIEX!dF-[0AcXJe*
-LeLdqeP3qcj[+KBUQ-LGe+*V+'BUQFU'fU4b8b"-6$pmiLQiSE1Jh#@TkV2PCS+S
-"JXrK"eh5THP*j4HSj5cEdBD@-h-ccXJ(Fc26M*QTkCNC@ErI8*)&+l+J%1Vb%-T
-dmD'kl4b'ILZ[SLDTLJS$ZhM9j8Id460mY%6(TceDm-0!XKhQK(XG&ArjBF9I1#"
-U%,Y2DY)45D)kV)KB*&8GIr-VT+-mbk#&AkF21[l1LbFU&lPrYQX9'hYZa9G3pfS
-dV+p40Yr+Qjaiq(UASB)0UqBI,YQS''a@$+k4M[jT,2bSSH)ZILKFe(DK'2J9!ip
-#E$%*L'ZVld"22RpXIQ!@,F+VG#6Ii#Vm"C&iGi#)e@VR#IG4B1r!NEi6hAKUqMh
-iS@%&Ef3N%'M1)@JPH0"#iJY4cB*5Kjk8)+Rj3XkCl*2(cf6+pZ-AXN"`)N*6DPE
-QmC69!`5Id"pBZT5G#!m3(!bk[M5miIZVE9+&rX$#p3'$(TK$)XTVT2l+AVQCL53
-i1l346SQ8m4!i*1$h(l@S!q@pQ+Pi`36FS`Aqq4BS5Z)`8p8L20Da%!mD$b0q-c,
-bMR#8$D!ADe#dVJEB1%!m$2'QE3SR@@cE0bB,l@3Rl`Te"MTiFe(Q(FLE5)U%!M5
-%)V!DA@hQVNKPP%A*(hc(0fF,fa`5T@QlT@(G2&"$i9Sb-'+)Nr*Q&+($&8-3d3G
-@8`[)V!'HT4!LJ%',kM2F[$6DL6YNIhih*fT,%c0j`jfMVChm3QVf6RdLU&ZCqB5
-)rQ9K)AA++UV#*MGMdULF+QU4!NI4$UimRMaCqr+F4#SS1Ra#HfA"9Vj*2FZ8G,a
-J*dHN`J#DN!!T'KV5P3SaG&)C4Kb#ZYj8&#AUmJTZ,F&QHp2US1Z+#MN1V#!21*a
-N4Jp*eT)SHAFKQR,*%%T5a4qb9N5U-*!!5"3N[(%$#FmS9LpbYiF9ZC%QhNQ0IcA
-6RN,41-)b&-Xe8MSfLH0fkY6'6k5j969HU%*mSNj2%,fVAX'X*0V@Vc))DJ(MbN3
-R42fl,0((BPADUK$C%16#,f&NSB`9NldF0ACrC2(2MmVdSej0TCi0)M31'jMc9m5
-XIiJ%-Lf3!094B@hK'5#5Dd!dM%"3LG5U*8`V!I52K"GUZ"#Q!UkDm!Bj2k`Z2k+
-)R2I3i*0e+b#Xk6GA8EjC86@k[CLUd8+rBU"@$)55F*!!U#RAG$GFdBX,G#Y@Y,j
-j,@CTQpH'$4G*64J`,#l`Dl60l`*Aj5TY4@LUdPH98EUH9kZ[qfUH#(4+bL,N$Dl
-G'ZU8[jLjqY"4)NbUf84d"B'Q-N'i[)KJMb2!jQl@%LAeei$BUqNfA++UV8b3!+K
-mHAPJS3%Ke3(&&KAAU"D&AA2hDNFA&mLV,",d@h[jPh-9e@JK5m4F5*8l1p5L80R
-5X!$eFS)+erj9&QND6GhUL"5p@2kf`T9AC+p8e6#e&heBcRDl9U$!UA+feX&HGLQ
-f0PbT'(5Y,UbJG!@4F@mBfUlV3NqTI'A9[&Tf%BM[#BA6QIcb'fh#UlZBZ24Z[r#
-fCqX-i&581T6(G@%&@9KNM2e2*H+BV&ke-C3Ab9*#DriJ,dNPZY8$fBUL2c`59ad
-!bJpii8&)pIi+#+JH1YjDm`TB+5YJ4@68$51ldKpmScbJQNeGr,e#RG98ZX5kVPf
-IM66jaJ@1"$lb5mT($T@*(UQ"J%iS@hN(eKf"QijZ2E60r89$PXMd*Yba8+YE$Y8
-F!H(r56NJGBPQL*C@1Rj"S+YY'r`*(k0+68H%"*diUL!)Fa9+V,TE&iPA296GU6F
-5qqiE,#0K*#diRC4AU'l@9m%Sd2G222br2L4AQ0pZ3iAFq[-j)(TZ&KSXKQN5JfS
--Q'Y@`@B8p%RR$K`b%A%6VmGPhJ4RcDYaBY[H"*!!ZC,leZS1A[U+h[,r+RfklS'
-VeTN,UGP%&MPjd*lpS0k[E"0j&@5RTabrN!"q"Y2C"XHbX-eXIAqp0e1Xhmc@rd1
-E55eh-kRDc4K!)b#fHq,KadT"N!$edN*6PeqAL#6UfL2dq+',rr5Z@5`P02"!E%`
-!E3rBVY+IPi3reFE"(B*SLh01G'mSXMPRZ#I(G5Sq$0R6Z(irA8q,F'6cPHJQT#N
-&`P''F24h4IM#li)`P,YaTU6FM62A4lNEcrmjPEY"KJ$PEY4)bYfS@9rPFS6rE-T
-G$i6ek#ESFTCK`UpPB'+PDrQPpi4Gq[IXdT`c'hMKBeIrTKHZ4b'M[p$djbNZ1%*
-rTd4Sd`d53T,1ekHi#%IVce%JV`pDUeD@fNVG%(BHI#3M*r["#aQCZAT*ADRT[cG
-QJR&S-&ASRB%mA@`$IFL-#V@2$Um41cc"&2HF)`k[ACkeKTceLD3Z#qV#QC'KZ$N
-A2CGIMMRVZq@e('DEZ'H$LVCCCc*cde0q(qD'V5IhM8XAEFHI8P&CP4``NC3hjXa
--Kirala#T3rpIAV[#,I0VShLD'@A4)I,3853qDq(5M3M-23j([`I,LF%(+3VT)@q
-cV1LbD5J!d!C*$Y6m$d2!3l"+X`ihq)AYKrK6YZ+5U25FV*`(-e2+Nl9+89[+%AA
-3D&bK+&idH2QMELXii%TrU)"a@#+j4Y1%*cM(S[B5-(`#)RAFFFeLJp`,CmS4+CR
-2$6CTLSM-Qr+1RlRY`8T&N!!mmI!6ipbChDFJ2C86Y,kV$&RDLbJ+b"dI3AHTV(l
-CFYIE)"M!LIh!U(,kFqf,rbUArEmDbQIIHk)bX[FAVJqbPRH9f1ki*rYXCQjQ#U`
-U05FM-h9r1M"(f9P1J8aAY2jCVNJ0[i,!D[bK(A$L!J!m61Dr3RFD)K63&DqXb)T
-6%EfDS96mRkT*CFA@+SbHq&06bd0NDVd3HAi&TD%"$id8T)")P2im"'41@T!!!%9
-&38%GR(Mi[LaU"Z$b`+U$9#SVAPFXkYIPL#S[51P&SB[bJaBGq2+1Tf9RCHBkdmp
-R'dU6X+M5&f(&",`-d%-iLRY,9E`$6LK-6Bmhj3ijH$`!$jK0XTSD@!`!kF%Peh9
-"C1L#T+p6@3be06Kf21["ilmrNjfEJkl#pkm51qP31`kKhpbF$232YNTqBa$X!f!
-rQ([Qr!9lqLS`Zk""(%Ci0#)J6XP[`d$`CdpJiH&LGP!KNlY+#AaR%@i-6&DjSZk
-"U*b$k4XS5e41r($r94j)eHXEA"H%*9[D9%iJA5p6HG#JhTHlHpi'X))r"Z)L(KH
-)2bI#+rq`S5l,1r(I-Hr%(c#%H9b(B6aBVQ')p61-"cI--"lF%-0iX"c$U"`&Qmp
-TSk$`Ea!&LS)B!!!`!d&%3e)$!&D`$e8,,#N!+Qec[jGh@9G%A&BL)U)9%G(8M((
--'%IIppepbI2,b%c06%(1,4J"`S*QTXqlZ`)LRXh8'M1RF4c(DFbDaM'RS(%FTm`
-m[aV(2$HH1b8cN!-MT19qRJ9F2(I6I2r[ZVl[ZmlcAGF&'ab""%%3"%'3!%L+C%3
-VeYA9r@Ep8rTj4l$i&@M"-f#1`jb'k3V$B8*K,X0dJZPlX-ec+UE*63K"8H6*hDG
-bXi0(@j,U0%2kK5(Mmp@lkQ3M%$f1re)YTPmRYG-mdLbM0RSCIdmp3"mRcG'+T$c
-k)1P6EE6d@f0-Y*R29'FB*G'2m6qSMp"h5BZdE#QGPL3Yd"kAPKU24QIaa@ST68p
-k3hYDqV2a9(3CIdfGBRLM$r+TDJ&05jUYQD6"aZRS&qVi2HUrkHkNJ9UPG)D'*0f
-[h5NpB2`cqL`IT"kPQU5l003$id6d-@j93icbk$raSHTYG%G5X(CFDU#8T)He2G*
-$a[24qrK`GB4a+[SjIUpkNKj-'URYPqBD1G&lq6IUEKU@0%UVPh*TIY*#lC!!0-m
-i('hKN@SR)c`kUSirSbE6[j)kDcZNCZU6p(GYXr4()bJkJGqZCP#rT,pUldKr-r+
-M-rP2DRpMBr6Vr(GU%rdPUDr@+1fLRNNrehk8AMAHMVl!HkZI'cHMEr![e@rT0dR
-GYB[5*iBl1TEr9pe#rdKkAdZ6)UK(dSGDM25$X5QkPIG58qPbdUelY-qN!FCAd5[
-j1E@EX5*k&Ap#rCkH61UL,CGH0VC&Im6rSqkNCj-kD0ZPVG3qk4AY6DQMm9EdDYj
-9$6@14'rJep@eG#8T6&XMVD1V5CHd,k4VaYI4khQEkL*RdRP0Pa+0qk,MH,aU0j4
-S"lGC9-QQ*A(0)YR3p$#8rJE*0)i1d10dJQj3R9%ReifV1e$hH0f*1M*lDJ[c!NA
-'Q1*PmZKa"e4lmBc4ZVEDV'X56,3jML2Z'UGVc`GdVE4BefTKXQ!HJ4N0T!NG#cV
-(`93#-f1-bcjk4Uh,E[!mPch!4l[XXV!(1*!!ii6eF#`KF)AX9$!I%(DFX'2BhKQ
-eZZD"C+03Ya6UfMKCef52VTQ,*52k$Vl-mXI%P8%a34&T33Q@2dVfVpbaPZEi$@j
-,3r+H&bbhfHmmLH!mEP%cSL`*jjSb,9rp'1-1HLGQ[f9$C[+TrCC'LeYV,EFmGhL
-,l958B'TVbScj-HB8XVcRQ,#`$HlRPZ9Pdl,l-S)XQI%@06E'hC5Tr+p!RGV*qBd
-E0bd'pqMF8#f'a@-a*,Z(d&0%G'JHXKM-@MbUc51ZqJSHc@2Sh+0D22%'#Da(e3`
-2j!Y1b-%3M+Laj-%!aXQiG#"aRGM$$8I&FJVhX"eL-B8E,VB8dd#a3CUKBKAZFGJ
-p6#"R#U*RKl5UC6MMUMlQH$'Y9NXrchSH&k3QHMKbF8jFi9aeSNmQeh8,0j&!@VJ
-U"P`BX0KK9@jb*6)'-R%e[S,4`EQV3J!h+6D"9VR&TCQiNPLahH63J!TP,'+hHTk
-YB&,Y1&GXJN89+cK#fC)3Ee'iKH&F6LB%DkYFU%69kL@b!CKGGVq'Z,BIaV6hbe"
-iSF9X+A6CcB9N-8YFZ"V@86@"8I&[0e-KmP*,S3dp)(QK3qc5a8EX9bf&NQBZ9*d
-3B5Dfh9iSHLS1a4kc)PJj*)&$%C)Nj-aLT0S+Ui4,BTQiUR8Va)!&qhLeHPAm6!U
-L*YCK&L*9SCTr498Sb!X9aQ8afrbDJ95Lm#fD-%SE)a!q8@N`!JmS!MNe4P)`F-d
-9,mijJc!8&NJVk'H`8RCJJhVH,d#FqrZL609i*KFLVQK8)B('5cf#&C6VIRDffbQ
-1aq[Pp'rQ@X@UGU(GGBY4TDh39,9C+JUc3KZrI*5fJG3,SpS983P!CS-N44-Bb5`
-`kV9#k)-"JB-8Xf)c#aB3#cQG+R+l@a)lmCY#0X"Z-PaF8Ca-[-)9KqBA*pC4l!c
-TAkG0UC!!cpC401b1&lZ!mc-+P"fb9E'bSTaRbl"m9SAFke9EQIS-(FVf#`HLf[(
-+i)!b&SXNqUJpV%Z5DVI!9Ja!MH[Si)d"&P9--VRLr828$X%QfF4!#B8-BXCPNCJ
-Xa5kKCNJ5Yc#V#,'1mibR#Lq@J!iQS3d@FrSAB4JQ3f1Xm*!!5S93PdhX9e!cE@!
-9H-ldU0,*8E'D)l3#Ji3QHLa8k#&cS6l!6+)$i#rd@$#`L)(`S+,%#Mf+6E#+UJF
-fp3SlCP[K@1hBSYUa4@L*J30e)C6*%I)Ff1k`#CN!CE-JfL@a%M1-(f9ehLp11(6
-')U3*'4AU++L9(K5[Kid9b,R2b8BZ*d-jl%)2Qa#+#U['3jL*6"*c8Kji3Sp*BTl
-3"$J")H$U*C0($4-(j!(H!hIRB4X%a6dUSb%1&#IM8+qc(F+B&$3,lR1bNCm*'BI
-J8[`4KH84CH"`XKe#e(Qa2-(PBJX6lprZJ'T-*dHSAa'UBNJ%QYK4I)@+b+$Bb[$
-aINj&V)2-46jmUN#l(qmNprG9IM)1IimQQViV1DM9M@m)KqQ`cd$IjBjVbJMDN!$
-C'Z[qbKd4&2@1HX9R4!ADV+X1Qq"4dHrXZ$3"Zq"SVr"5a,i1BeB[G+*pF-DXk8"
-I3(ma6,#ZIIp*J9E6!)1AU*VMUVBU"CdM-+Q#`FY(UYU10KJh$$+V&IeMh!Q@mY#
-J+T@KaRY((GGD*!P+[,IHBEbh(*dG-*PBjk`kB19m*5VjpFd4qE'C#HZEd2$-$)T
-3%kZli'c[Z+3Q0lTM-cGASB@Xfb'V(cVGaF"iEbE'mHM2KTQVDmXAUApjDl8VbKd
-&8VL$)Rb*-5P+d-*Kc2%@D(0ba-#BFaVbDM$'Lq5FpC!!Ge(9hJT@%prUN4U4[cN
-Lb"*cDq*Lf0BjMGKQKqQ'VHQUYM9DI@,VNI(DI"(VpLR)&N2XqX"aDb*m1*N"dC(
-S$")$if2#Z%H"pV%C*N[A[ST@Y6HKjjYR#ja$)eQ"a'INEfj+hKPNLG$b'5P"riq
-2JRmGc&CGfpC(G@l2C,b*'8'CQpf0JYQHc`Lmh[Ki+rJM`1Z%k3Vq#&AERURD$V-
-YcKe4#6ZM,"Rfr16$qN53!+Tp8U$iH*(MZLp!I$`F5`a%"l5H$6HqSk[U6%kEU2+
-#GlDP`$QlNTfhjFHkGqBhlib)bY`Fa%3CXiq"*3k59X0Nk&VbBM9aHfC9J3h3di)
-bh8GM-f1D0QIL25JM2h2c-3LHl64QGcC#,)k*TH'U'K%6P0Q8A29eca)6#ZSi+JD
-hmL1B9&G66'Z81lQ4!HEX5'0f#$5C9D"0+i3T-N+J8-JZQ(#B4L1NG@*,D3VHSei
-*LJK+m!@TPZ!eECYMSQ!hVG&K6'Y&abi'aV5V'+1b6ZX'dpm)`EH2N!$,"HG$ZSj
-Yh8YLhCF%bQNMaJ+8dfSFaK42J6DP4!b-+6PB'ppITZb(NBb3!,jBZbG-G-%c)Ed
-Hl'Qc61LA@UCNLV[DL8d*0DC`jTkQ)$e6%Y""HUBJ260mA41%qlLQ+IfCDpS)30f
-i&DDji&C)T*!!q&+Tie0G9DY1,61Q&V&9TfCKe4(S`"p-2@k%",GFY8BUd)D@q&H
-GHYbrkNbBAM$GB@l(1HVP8&2"Xd-RiQpD*RYUHf0U(iFa&38ep5HBhXC3V$2dH-'
-!SG+,F"K6KaY6Jl(rY3*Y1X40Vc@'3UfKJ,UKi3AAKNDfA'hkIQ2kF@0SSc'dpHU
-',mCAaNNVkr6`PT9eHU[$Q!iiRQiA!f-kbQ8kI2PdP-[drXE3d1UUQpL8(l0c4e4
--%'TaFe464Qb%)#lErbikLf"'kGVV(94RIJREF6iM2cN+A`l+RFe4b8&Z`@deh[$
-Uer+[6T!!f$IUM6I1'N0R'd-""N-M&6j#i5X8(Uc`AbMm2`Tr9Z%r+Abr`[qUm2F
-8RX1`II$kTr!5KIpFiFmSh+l`@)8rc,Lr9hLc`MFU2&lKQa5q@1&1*V%E#mq`m5k
-&rd2KPBa29[K#d3EQ"8`SfLXZKGY8mEVTB'GC#Kr-a)(lGB8IB(Y1-Y46#RmEE3Z
-&$m(l)C0lJDda6q(h+Vb0(53UI+h#rkl`q3VIS[!3KIGN,I`4E"c0dV0(%DpcZjR
-'AS9(XT@Q+IbL`[-8IPhKhc*"lCL+53Tr3H&r8rKaTNUM`Kp4H*V#Ie6i#B9rTr"
-I-Y3CTKa@6DjDVjB0VM"&XIN*KEqLm$mVr*,#PbTmS-,raA4UBk5rMHRd)91S31&
-&,,8+5bF+Sjh#cbRm,BA2C%Y+6)-%KAr##L"Ei4d8EPAi6S8(&(j8i5UMb(5&peG
-i9jCJP1AMM1jp@GUQ+,b6`JH`ihZCVU$qJi`klbVm)CD'KpNDKeLDda@q9q'V&,j
-%i@MbI+c`'`Vr4Z'pf@,$fImCTNS$)`d5Xje"c$T'eUX+Ame+#i[GBRTJl9HV3'3
-$Sq#2,*&h-pB[&,j5i5mceLf-q[XBiF!k@q%G&Iie9'I&%`jC$(TL@6R0B8`@*RS
-9+im(&&k[m1F9(UE`,eN#)-+Qm,-+(k68289FLVCd#SmdA8kGIETAkf"ck*'C$Ad
-E8dUkVTja[1HZB)r6e5lRpS5jT9f@6crlLAY3EG[k@I[lCBc-HRREiU2G,pB8fT9
-hFc[[Q1mpYh*+CBq)JAPKDclBehrMm1cf@aH9pli3%SL2QecIThP8@EF9Vjej2fe
-)dG9eFdlpP$NL[F2f*FFq[ePR063ekI!c8I-+ERdflB8I0Ydcj[U'hqlj5p2$Mh9
-mk`qhrIc(1iV2klrHqmHJEjjqm[Xhr[RIf!H@AI[k[C0rIHI"4rrcdG,IrqEEZf5
-EiaH(rT@mm1#!VkEqqm1BZdGI@I[TmlplrD&(ARRcZcqpq[E3FBRhrA,hhcF2HqU
-*9AqqmapElMp`kBZ2RrYErVf22lYc`BN[EjLZ+8hZPfJ8,dUBH)kj#-jS%AcCSM!
-a-"Ce`aLqE&%(Q"l'd-'UYRN(A,IN@1RiGk@[$k)*(0+Lb,&NM)Y'31D3!),%lr+
-B%#ckAEUaD!4H"C!!,haA9Y&"GVPS$MV),VmlBRb(E'aSX+T&e--8`@3,*iGF"YY
-Vc!ARDd`9qG4h&ih[l%D0CG*-#6RKjCV859SYAI-M3+Q[ma1#-QKV8%6q&a%*34&
-X,-4pi*LdR41I2jjKNF2iEMik0@*J,$CMM(aUX3NQakM"eC8D0,TV4,iFU@V00pA
-,cFI',[$D*!SXEMB@TcQ-aH[4[`N6CY4FRN6SqHCM%fQq6%4D1f2aG+0QCV@%Dj!
-!i(pjB'de`62)@&TSe!aqBX+A#TphMUAeaP)dj*H@S3rD,R8CGp&DhjH5T3R'dNc
-MVY5*YHA1953r,LV'r5Zd(*IfQdK"q"[M5bG$'8$+d[PLB#`&G#hYJ[k3!!*Y5Cj
-a9d8$mbl@`%5R%DfpeTI3l+Z-r#frJQC,YSe9Xb8SZ58SY5ARa-"BdJ&M&rTpB(S
-EGqfUd)aAD"CDF#QNpHZSC*q@am4H%jB-E0Rd@&$S-"EN&9aE81VEC"%(aJ),cP!
-,&TbY'"X,MN!*%'S"@N%,-SblaVp5K&Be6-4HTl(JR((A6)Grr@l!ifd$"5`Um0(
-NaUL)r4CfG%N-GVSMSTVF-Hc!FUa+CepjLbXNRDZ3!*3Iml1NB"GHD4EJl5I5)JE
-)b0"(IPPV,1L2,P)8H86A,Qi6(5mZ9QMfFi*$GhjEkkYdrSY6fVq'fEq'fBKdSiY
-LLZbYDfrh%Kd[$eDGpSY-3XH@p0ML&eJKrTb[q)UcDUSm1Ci!,fUER`ccm1Bp,kk
-D$20@#M*%SU8iEbX-2K5m6D,M*d1#i!!C@ZLDrk[S@Nd-XC,CQ0FHh5N`D*CH@#i
-kIQ+XBd+kqPI`,l!MY[PR8hTq`*KIVQ[IMLc3V2$T9N#L&5l0'UTUq5K1+qUV&9A
-#L[TU4E@`iYA0ZJX[lEembl8C[[l&,9IZ-1DM$Xj(-Fl[VQXriMh#'Pfa,TbJ&Fl
-35MlV$SE"5j-edVqZG3D6rXU%kAaaT13,*@-K8RX6E`9@N!$8LQc"#P@XH2@ciJh
-*#Z#fiJZA&CA8LTc+#RGUlBTP*GrLUdVYLbbqK8Mc3U4jiIX`lq*b+li"@B2&kPj
-ZpL)I['Y`eG*HhZ$P&LmAZR6eGM"9[jY8[*PBF,8c15-S+S)16q#),)IYBhZGX4a
-@*ZEiR`AeQM)h@j,cm8dP)MECR4p4EXQd(,1m%l9VCdc6KD#U6bH6VY,LDdIedZ1
-rb6"d44fEp(9TEXm+ph-VfIeMDe!9XBljhqV#',E+9Fe0-HB'-qLI1mYKc*eHS(d
-$p$HPZUCC98hVjZ9iRj@mr!K'kldm&E(3beHVfSd5,`r(9BpCAYjiRfdI1@LhFDM
-`0#k(R63hR0jVcZP8bA2-1H'98UkC'cGZf#HbqUJ%apJ5-HUL`hF,!h"4f+2F60Y
-4Pah'+!$1+2qAaNilla-j-@L@M*`r1FeG89(mS5R6AH@3!0SU'+T9''%-Sr%L*aG
-S`c!BKZpRYYShrAZkMNdQ&I"K$[pHBaJq%!a$NfAB4TKiAB[(Uhpm!NbfUTfI#r-
-qM"fQ4(8k8jMJfbG4ZKVH*lS)9J#!$d-p(6C)eqcp+r4Vra,E99m9"cQ-&(bq5)&
-M6GQKDk'9AYl9bcZT@Q)0c"bBpM!+$0c[U-q01UjUcJjH$MrPA1lPPe8YmkUUfBE
-!c&(2fc,rCm"l2Le)e!K,HCIUqL'%q2NXIVlla,YF+AY[GcQd22kCdAZrZ!4ES2A
-Hri94Pq,PJq'DMBF[1M3[6PqY1(feaHNX"bk9IQCdVcMYlRXk21Y'DTe4+(Z+!q2
--Br*'ebiV1Q!Um"iXIEVXUC,(XKr*HM6pFF[Kh%-jHqYh0qcCprcqNkHH1re#jEr
-2r[2-RFG[+rr6dGmI1b&&l8K1#'VHh0LdmI@-Gc,c@cG&a,KMdlEXq[(#QpXqfVi
-cI1`-EermpZD0X&PYekjfDrpXBZMeX#[SAlTmkpb!,NpfHk*VarD[[2bI$XpfHUE
-c[flrBjqrpre,rpreqq[RArEkSFH(RrchrArdr(R[9l[rj[-[Sj2Hr8@lAdrqjFc
-IIK"kj4A,aiQcTdfC1[f0erjXQ9'hk,[&5jFXL*`hIq(FkjF6EedkeqA*!8pd(0c
-ej3lrH@$)rF&hK!bYZFYD4rp6'UL+`kA(hAGN`jUeklpHpdAUCbZr@[lpLP@VhlT
-lUjm)BqABbSM!0E[0H6jqf+IIm&RS2c`UCIL$$iedMVMRh[2[$4adGha,'[cdYjB
-dq1P[2M6iG0ClPMRMDI!(AaTm-fTBbX2$(aVji)Kl"pmcm1j",@J`bDq`qQHmL*q
-iGME4Re6RljfHb+mPEbHI(hq42em"i6irbHGA*p(BIe@lM3NN5lrbVf9UI"%J`B6
-+QLIKPmCb0&kM56IaX3LBN!"-RDZS06'k9IaFGD,-CC4N-38`hFY-BbL24P-Y,D-
-L62ib83(ZpML)ZmQHTM*kLNVS-FUQ4bL,(U9d6!fcd'(+T8183hZTRRC6!qfKII3
-mlDH6Z,[L146h#jLAqfrF4r42h*Yf*afRfkLFrS5ja,qRBjKBKS++SKf86!N84-f
-dQ4UTL6E5kj4"le!QjH0'Zdd836(NTPK+SbfdLhkN#r3QED12D$[Y4+Rr[`KiQbl
-5Yh36mpV#U+k0VY&9kNEYk9P+T&#k$Z`9mU-[d@@k4HGS!(@K*m(d"(@PMQ"pK9k
-Qre!(E1P%ce"RqKIG6RqN2[4hkNYrSIld1qT(IkA2k8[U46p3$rU3!$kKrp,lp!r
-U56qRh[3UGDII-)CSc,kLGqNAe)jq6C2TPc56INXI3)mV@19Mr'E60*T#8fNk[8'
-[dCpT"Rk,k$YD6%YT#5fJ5*T(mfNKcBAQPj'#@p$k(00h!26Y5)1Kmm[3p6rd!!f
-KqbQBlU!3'NSeG"GCU8lj[`m#+QCA1-K&1XA4IA5%0Y!D@N[Vk@YD4ep3+Re'+qN
-V@NlId`TD4D[T,GVD!J6qA`5-"`(FG+@4R@cNT2-86m2S8rS'f&RN4cp-SbL&KY1
-$p"#0"0-)ZSIZ"HYl0*!!"Y(Gf2*5)2!6rHdP38!`4&2Ga%$J8qM`(Xh"Ed)3q!0
-q%`H"Ek$Y-1Ml-$3@qMi)IHm&#0`$EHq'[K-&!6,@m6Y8flMJG3MQ'K(bPV2!44L
-G`m)()Y4QX0"1"&-F#aG%1*JY`Q1$4FKfLT!!EN+`T'YX8-N#fj!!(Xr#C"BL@CJ
-V`Z0(@'$(MrGRB4B,)d5`P,+JX,#D"DX)KpH`d)@&%"&b%eL)CQ'*#(Xc4DM[)m,
-Z2"E1L0"J&Z&%*a'NXb+NcKEK+lEjUd%L,%pRB58,&eRSaF)L%Ei[BS&YrVk4K9!
-@2Q'"L9Le@)3hfl2!%[EQjb*XBkTX+fGK1`X4)Rc%52N4)mTf4[VYM(cE@H+hGfD
-KK`MKM#MKp5b`!JYRL3r[c3)MF6K60-V&`Q84GR4PJDQ9c!k5`ePiQB@I@'!N5'C
--#5B@@#)6f)BJPZ`J4TUJ15``GB-Bk$6[&k&a[JK0TePJfjTB!63aj6BbdQr-BS%
-aE@4-'fqb`)Tcih34-SkcN!$+!P-dJi&A"Q2+B)4qTeQ%r+-X-#$,pk-BD1EhC'%
-+#`aS@XYBB)4VCD$3bTC[hFS#+kV@[Lb`cDf-P+d-@$Fa%QpbXm"8fF3)YiQ"a5C
-@Y*Z'La$"LLf#JA8%+lB)"XSa,0Na$&aL'$PL'2RF!4BB@Gd-V0fXXVPC*A5c",[
-lXF")idjKJ9AD@%E3@!X,$&"L@@*L'8M&XNS9biSfPUNBqaS,E(-D+q#d"KBBZG0
-fX,#,KA-XX%U5aXL4aUTPfK!4YM#PYl#NEQ&*hF)+D8Xh&KMKYV"Nla,,m&d@i@N
-XZjKAf#@NDVYkb94E+&0rQ(D&XP&D+"FZKh%Ab[*0Q!r351pE+"F(B#S,j6&(#q8
-m$*DY+C5,qK6+*4d+j82E#ZAG10MG!fC%SGa`$!B#'VS8bR[+BF#`"m+I6i!"m[R
-EBAV#c)5C!C05+1mR,"U3!1A#5&N1R*,PNM4ChKdYbmrhPqApdfAj4*JXUd@bV'6
-)XYjCPZq,Jh(,mK'6,'m!``CXA1Z&k5(,kl0J9X)XPZ@[JIbkQbar!8'THE,mfAi
-B#([VXLb(Mj!!jDKd'!L+kLl,1bl+FR+U,!H9`4b"!5+S6CDE&9RH$%&01'K&Cj0
-9PL1JC%3cc%qb(0-H"XTZk3S$j5jdJ*NXbeRR22,TH)rm*jG(rRfj4ck"cSPq(YQ
-eh52VPchb+S,"!G8@bj4G,-YZQ(E&XUFrc)KL19!+d`rQY@,C["AQ!Nb2BRR-l'+
-jGP5aA03"CNLaA&"B,"qF85`rA9mXPi3AbpPGLZ9(MX0!B&CHXCbZ`-b%'9iX2ei
-#FlPB2R`'jL)-0ZB@`C6$""I,Kl$3S4d`@1a3CjMHaA*1*FaUQ$DB2M!3PJ-&pqE
-#5$$BX"H(HaFAbrA,BAE"32(k16$cLqAG8'Jh&QT)+CEh4"6,*j'`NpK`mRdB,(U
-+B"B9bmp"NHFJr(3C$!5IKS)[R),T@5aAGLq@cd,aIiB@bfI#LZ8lSH$a"TK2LZA
-Ec$")f'hlBD"%Z3N''mS(&mY(Qi[P%p(&XZ5#Z3N68L`V5+4b&3E%GZb$@3H$MDi
-!$)MSJR"A2-bjBMQZY9Lq,keB2J,PMX`YPMId,CEAG#Z@eqE!J-"VSF"k&0JA8$B
-9KCJ+iCqP&X[,)Ial,2jpHaJ3B3819m&3@8#Q5N!k`I3-b)'iJ$`Z,5#E!IhQ9TL
-DJ$aQ)mcmJ*bh$bB$TJG-5%!H$FE4R`INfJ$-6CM*!APC,Fa+Q0N"Z3M#$`"a!%*
--%'BD%C!!#qB'C1pV!IRJQS$m9'T!cZSIN!!IE3[)k9-#XJ9#$Zf!53R)$GN"qIP
-5Q#%"qH64J(`+R4F'"q4+-0eT#XJU&(8FJjNCN!"Gkf%J3#q(k3`c-L$(V3kJ-X*
-J`j()J,`"'cEd#mKVHJINp8K3+K#Ir33c25"[KH*EV3(jc48"1H&-3'l1JpN1dbH
-!*`#J!5ZX&,U`G"d9eG1ir5iq$R0EF2%'Xd"j,6kLU0V+VCLd@AK86-IRim4X6Dd
-edK8DQA@@mR*SA"NB#lcf&'k+ifZmL5Pdf*a$biT8@bQC6bND0r!9"Pqkqr)m6)$
-1+iLr2j6#McH3!-8VAFmV!bGC625S)Q4%-QE9PYQH$VViD9q-1*r*J8l`*Xj%)fi
-E&CGMGV0ICLKN6S#c#Cb&akqRTqV*9+R'Vk1F0A5i6)hI5Xql+Eh--E&dqT25AGM
-T(&qejkl("k9+Re'KepZK1d8YGp&6Q1fC6DZD+6H2(Ld6-h22P0!H%q%k2b6MXZR
-3[K$(0,Eh)d0FaK$TU'AdZfPhmB-1cFMefY[ji,$ZBPm@&`pTL5V`hF#dEHY(GEb
-r9NBPARSk@h9UjC4HJPBTT4p4E9Q8hU`kbbLGprBRE69E0Phd$+&Pfah"H(S4Ek-
-b[21i9#IrJ)T1UFiX+X,N&Fh2C,XM@1cY*26TiJhV4(8P1C4RSR((UJSH*rZmB5P
-dEdNF1dRh19R[E8XK5dNfQB[`aP@06aFESP+cUDb)$TV8@hP8j+8X%ceI5RY0H-&
-U8I#pr&[mRDd#,+UJiDES&(Jl42l2bq6ENC18LF$jP!PMD9%Q&4cM0rL8#3qT,T-
-59LBPV%bb@CQ8SN`kq*C*BA@CA"&PX[eQGC&-CN@5,BV%dE*)1JYeiVeKRImh,*)
-f&)QjN@UcD9`ZlPiG[p[-*P$9JPSAP6Cm0H+G9p$[q5JU,e)((+Ikj94C4)Ij9FT
-ZS)-jG$L9ZD2"STkk4$@YUDLQ%$K%YGh!T(MFrYE9Djmp(PAJ1a5+p45Hk30[@mq
-IU91Yd#R+R2Dc&+rpQ9be)Pi[+CZ!bYPHRM*4I*JS%palA%6M[$k&9IQ5*q%P#C1
-F0)lpj$*1cKkKV'`U-"(ZfcY8kUUZ'!bdl9lE,",qFl6`Ri*XhEcfZD$ST2L`Z65
-XC$APPG#i)Tp9QVhA8kM1QB9,4B&M`S0!q-L#@c@$DAHp3Yib1T!!+cBG3'RkJ[*
-Fi9qAB,CGUMGd,X$ChJe2V2-Amq!AZAfTA@b(AT%0fbP[6AAL)iA#REfKN@6*UUF
-!GeE)9Dp(i$'Y@EQq1#eLK')[mFRQ)NDiVPVU+mPVHUQe&rG3H,R3h&+NAD"!598
-plBLUE-((RcZckA3flFQQA(a)bUC5h$'TX"8`9q@bBZp,i`GY2S0@Rm&bRm&aRd&
-@Y5$G@544F8Q9e`l&iSG,0e*aGP81l%GGR""PDUa'e45F&bJYem)PV5KEYEPS6,D
-r&('K954CG'X+VM-fEbB&XKeD"9+l)eJj[ipUc95X9LN9MPY!+JBiaJedZ'&'%0I
-[,6F0ekqAi*0XV@p0U"AYKbKmXbV1Uml+Eb%V2jbH5mY+bCY&HFGT@4CcZr1&dL(
-LYCK3aNHU-9V'*kKMTJP%PrUV([!QAh`*1VKKU%5+0fIj(Zcheccie63DYm1RKG-
-'3BUphLFP+lI'fE1U%8LiC8+%Uk0apKL9jG+M*F+plLQPJlP89%)(c95QqJX$j#8
-'V[j03e0p!'dm$Y!fE6)Q(EEJr0@PRjj8qQQrp$-YTCpfK9P+d)aV3CX'I`Bb+Il
-R+66-'Gj!P@Bk@8,IiS&XCQV)SLB[0AMTd%ANJR5)pk8lDqR3$NV&U)3DDZPN,9A
-@1TLVQ-98&Ge2a(F8eZdT[U+`lY`#@`daaYN&YU'$'6+k`"CLqC@fG(r4LcLaTGV
-Yr8U-[XHAF&aRFSQfp4JqLiTU'I%(#FAprZdDr0[%b)QDF+KSUdqG&[@Z6N[I4iH
-mkQAiNE0dS*C+&AUXK%Tj9dC#kbLrB(6RLkp5j+qG9A9h[ZTXR1r6CRj113+``@e
-pd%"Y1dfjkI4d,TP+k'PcPCTq2lHi'T!!aN-1i'8fjY*D[EJPqe,p"ASXTpT*iR'
-+eBc%h+3IS1iUF9AYkqD,PJU2mS(5qG&m#CQVmba`IScCp8Bl848M5ij5hQUI()d
-GBiDeS01`%S@+Mi01&GJ)88I2)fXfMIG'm%#iSlkUaZ,PTF4&HGi**-+4Va(,c5Z
-4+'rjT+HK,(20UK5jTmpT()qVpLi6FcV`FRQqq$cQ3dj9Cc5LG4-hJ8paa8H9mT6
-Uh'5)hqZ@m9l9Z'#4+Y`rPqEMDd*Q5)ADe[h5afi6jCYSiaP+A8%rPP&U%IhG4+R
-VDDfAi[*)VD@M*VV65j8PG,)Hp8p8bU1eiL#ZPYE@8ZSqHZ-B"9A5aPV+Vb@h(fV
-E!EVkLREcB[(9@26k!a8XHQN!qA$4Z`"8U1LG%eq64Dq$q*4-)1'XlAKr1L8FVKK
-PBP614VT@'#pk!N6I&9q6@EGrPFK-mIQC`@qI!QG0,jqkp[pAD1hr4k%f##eiNFc
-a0EdUjK0TqFQ+jYf1QlT1UpTAh960LeYD[-d`p[[X,@BHJ4@c)F)F%dkM91#[6dq
-3!-@G%BU%@l)NTfLYPIM"GUlr&F%jGfcc1hb@XKc',I$+pC+L#9UYAMpiPdk!,r&
-H5a'lafZP(8c9YFr3[[SUS'S(-9rQ)'B@(6aANDLf&YaUU1r'FcVU!ZV$I'aS2fP
-bRI0)0#QZF5r,UeXQI*mrRjU8(VIJ6mjQ8lD*LXj333Q0,N(,c5%iCM%fmHdKXfS
-NURHkejNb0N+e9"qdUTMY0H'"DV+9jV+UkX@XR#kU9SVj3Z0#GHh8,PA,bX!8Ida
-$R2keYVVXDfe9Ae9lp#KQLkISfQC-hFR0!4#ZIS[4m1"XPG(Ni#ISI1+(&@pl!5m
-k+LAZ%mD9("'@Tl1`NS@,,24LBC%)haHaF*D&4J6Yqe!GB-UkQ'jT@U&U+rUViZj
-9EG9L(6H#BV"2GEkeQZ1Z@GYE2AL8`rP@-)mU9*aEMh!$Gp*ZM4E4pZCCR0RI[)M
-R#EcCAYMqh)9,3*!!E(mc"2eYH@+4EH8kV[q)jEIeB@'i#"pPLm12MQ'a8PAl+%2
-9$PK9qdF3SAhdVQlrD$B%IM3AcdRBVQJ(!"2EXhAlpNT)aAdEf,NGmje`Sk*fB,*
-Uhhi1c0XlBq[f(N#&UlDG1@"blNcPN@L)lZb1E6YRL@dl"q[fm(T`KLrARH%*20b
-MD1'pJCb-TbD%,q,K!38AP-3$'U)X3%9G&LJY+N5hlkL&P"d@)@@(5mH9*YCGM2A
-+9AYb'64)hSFYb5iZlQY2$YIYb@N#'bEXbm,q*'`da#3[&J4)-!N4#@Ge,F%&-EQ
-U&P5NDd(T+ZiSdS,Qk2BJT0iH9!0YQl0dHr0qE'dqaTpcf*T[BJUBV6Q&Rh$B0Zr
-JKad-F*E03#2JUK$D1&RA'N'bCGe9He-@"$5GeV8QV&+l!ffDQi+RU3p3[B'+!mm
-Jm'`dkrD0A86[G[5Q)bNEDlLP9V'phN&XH"hb4MHJY@h5R4RK()rFd$+FZMe$E-Q
-iA8HcA,#p8kVEhcN+h$[`Bk04rc-hkPSQ!$C[Z'V2R)'66%"e(ZDPjD-KNSI#bMq
-Ufr2MF*+r$EeQdEZJfr*C1[*l!MG&i%DKC`8e@N&RVE9HYlHka(#VX*N#C`HZVqM
-ee(%Y5j!!Ga-$qNhP20aKhj5!XdeZhElTCG(VKGlRSJG&mZ,%*5faA%54MJYDBPG
-%QJ#HL-kL**d4Rl-#MCL2ia(L)#D,(F3FC`Fafh4R6#-QRbMf'!'!-3#Q')#Z-fD
-ZU$afG`"BGlTZG`0dRHieIQ`'`0TY%8GGG+HlRm"UlZRJ5K()B0dHD`ClV)@aili
-KPce@*$Bf3U$Mr@J"6V'I#maVIN``0UHCG(YDJqJG4fm(H0*fLD&6GkE0%QTUD80
-dqaDKe4CSYH8)J'T,Z%MrPM!G9lCBYlIZh$+CijCqEFX)-I%@VJ[3q52Q$)l$%c8
-Z,!G0E@m6#le%Z,K0K'pV"I'q&Gi(RmC8,6"II,9%jedaVe3AAfF@1V3EZ0A$Jb-
-1Re-B,+DDkMDY'jFG0NaFaPEl1YeQlbp%fB4!Zdf8V`fe`6B%25GUlIN5(JlGcYY
-e@la`FTMDU0Y#+d8hY-[AcXI1m$U3!$2lFphfL"RH5FYDSpZb1[-kKrCS$ee,amh
-6T4Y9Cqi-2JpmKlE"Z8,ER"*GbeQ13Ar9ZGI$&cBSfZkMZQdhUbblHk!l3Y5c"RL
-VJf@U[F%0E4VJelei!@fBM-llURe21HLpCjZ`0iAY"+BplGCac"BeCDJff3db1H9
-f2!V2#I"dd'fHrX"S(Y`[G1"f95X'43i)HTAUYN!r!@Q"erK#m*T6GDIj!XI$9Cc
-Q([a3VD+03Dj3"-p6LlRXbp"m+EUUfSTB05h#4-iLj#8&H($+-U6Vi!add,4i'RF
-EeGj8YC*`2)i+b0(`&GPG"*QcTr"$$YXMamAJ%6II$B,Pi9&@d'6d4NaH%+k@TeX
-iZ1cT-`%YkFah2ei#M2Bi2N2J`5V*+!j,AedlI!DlPQ1QJS!"jq%Ch#K8l,P&)%-
-Z*SrRSVD22SCC#m&#dd0EGIXK!Cq(,JJVUXkKhVSY4j5M,@He+2UF0KcPp-'L16-
-C@P3rqpjFS2G+31rG)G"lfrKQKlChX@kVAbi3pEZ%r2TqZV0q$UZKpB#f[$6-LZJ
-LA-&ZiB4f)c21JbYXb16c(,D'&!#QE8m%#YLfCcK3fMj8kRe1ATHPD2X(klD6E8,
-bbIFj@Q%RJhAE+3DITd6@UMd(PreF215G9Qh2#6hYTq'ME+I4KR*STbrUfZP"UL9
-2YEe`5QakJ@Rh3Np9'i0XYa)eD`amd&R-`Kd$Ara2e,!aI96Y6"Jkje6YcJ[SS05
-10qLfimbr(TqKfiq24"*Z-qZffjJHYiQm4#XhkEEb8)%Slmi3JhAY6ihBM`TlY&Q
-JMZ*6URQNDMXfA!$bL@cGGZ+8+-36AA@E*$)m6@T%9`#m6HSXMU5"ZUDL5@VZVGU
-8VB*&ZDVE(#c[FJ9BU"GS&pSRCN#`#ilEG8k8[@X+FiJZNAATH!5''91-pFr4fD8
-kieTjH+RL[#q0Kq24(8H+4051S%6-+e6RKVim('@fBC!!EPXM()bf"ZfFY5)VYke
-Gai*E,,N@V5%c@NRVd@Baiakk,blUYLpB1bL9Y5P5SG)i9*!!cc#aI4aUjr*fD1d
-FCDfICKED#iIerAbKl)TXIJJUV-THab["hNF4hjc(+DV051'4$Ll(fH5HF#1f3*c
-B1NjN$6CcS3!@FbXEe!L#MYQ)QSZb'c0IGqD&L)D50MS06i9$&KJ)%h92GbjEbD2
-JFCE0aUHl-Mi-EDJ$YA`K8!GUG+GT"%-9c'8SlfZkGK![``&-a5q&K`QJCT9KUR-
-!RjUI3U++RDU@MH@+YkV14clJ#e%"Xd!,$qEf2iVRGAMJFG1RS0-C6`F#!(QJh5'
-dPJkK@HI*!GaR#lrBJ'DRh+SkpjeP%Tj('db'H4iZT"!ZiL6F5#%JpC4!B0,i#`#
-TbT[Ll8Leh@N5%ZlXJ0IeH09jfck@)GlQpXI*V0U9)hmhFJ&plk*qfRkI)Ic[-EJ
-!!q9eSNB4hqh81!!BEJRq#FmR`-h"BDV0F8a84FG-%9cV4AEKQU,Ep*'L'lGDYae
-Kl[K)*)##Y@[Aj`V%HV3a[XB0Y)fUE9ffJ*TeZ)9k*F$L&'le9EA81!HZH"BfZr[
-@p-2[mS`CdXS+Xhc'M"XGDfTU"PP$V0D"6ZG8Uh@)X1Lr)IV"mf$[(ALM&8`e9QX
-`3`krF6l8DMd(4(b`04M)N!$je[&r)6@I6R$mMIqNKTe'KJJKLd*B$,''Y'1pTG@
-)EaEAe$a3`e3B!K3dZhqZdaRLG!kXi"JiTH8B'qkZ%D,[UDQjafkh$kPC+)*!,I$
-h'11pLqhXEh$0r8jVc4$r%S1'3X*`Ch!&dphIER4#`0de)l"pF%d&q[k4cZ#DJ8k
-VN`Ppf#PS&9)c,HbFe6NA%Thf%B`XGl`@HRQi'&FK8[alr'SZB2[mbh`RYJd88U$
-m``*p$a3%i[l[a1JKG"qShVP3p,kT'-kYk!ak@$"&9LeA3Dc"GbbaAPKqde&9&#M
-ep"lRHi8pfI'16P,M!1Q#X1HNeekqjiG,mCFZa8Ykr+AZGl#rpm2#`JB-[4b@q%I
-TR5Zhhp2aqX""Rl-JZ6[1NAD1l(M2b'($T+dX**r[fL8XV223i-X$VPdIf1&@fp9
-ZYhTh[A,pNl!`UAR+$e1Q5-N`S3p23IJGJR3Kc1Um+Ze%H$)86iVGpRE%AIp(rlf
-p9i"c66!$pprqZB,FRpl`eJMXM98hZLIpGXKVm4m-LVr4+IipK+XhRl"qE,eae@Q
-pmF1hTdCDjpjB"H#imD(6H[-pqbclC2Xm+iSib@TGB,A1XIlDrZRPP(01P&pHHHa
-$9b6P!FR9mm-KG`qj@rV`0a@G[bFqmdV`S2k*9r&629HZ5j0l$T*5T4U8ceT45(m
-G)MdV"8PEZjbAVSNbq&CBQehDBRr@6[krfb5Z&UNjK0QmmD'KciD'GR[Lh-[SGPh
-je`'*eb@(X1Y#TG43IrJ`Y&GScm6VV`,p9ZJRLCmN5Npm+Dhi33e)dk3Nb"XRCGV
-#L066E9IDK(`!!"`4384$8J-!,[%293eP44%!-@AZ3lpYEjBjAm,,$2Q'N!#6[)3
-jadbbiC%d4b8Z@4,R-T+a4!RFI-R8C"2*NMA'019kF$%aK'JKKKBXPd-$TDIaq3`
-X8+XHJ3'@`a8[0r*mV29i15)8T)MPYPb[f04prRl[Zf3*PR,[kAhq!4ZQ*q9"%!4
-!%!#L!4IRm4'G$LmqA-KF8)PNK!'qrQI6#bh1aZi@2YRY$6j1PIakU[aLI1'41jh
-[rIf,p4#*3eUE'RPf1QaCD(,k902TFL3G1!DH1-f%9(bZ(jeRSipam@1B@&8)ca,
-l@K4#KqjM"FhS[%2lm&%YIL6%$lq[$HiadFdM1B##IR)i1IK19aFh(#8A*#XScD"
-+5+5F10cV-!jCIK@ZH*QhAMX5qZq#8!%jU8C[qH#CpDP@ERNR%&Ul0d5Z3pehHhX
-G'GH2l`fdq9BkPBelDLhcZErlar5hm8,hMmr[jp[lR(pfD)06rH5H+b($6`24R%"
-6fC39Ie99C-IPPpbp(M6hSfECJHp"9V$K`0h9cJVVU0'UF$Q,AT1KX&pTNN("C"P
-HVI&U['*&IV`q1a$+jEhEii)Tk$QM")IDp)RY9STGB@d6`m1-M$)#4rd11'bKN[8
-l`ME9AlpML+ZQihYmX8"-hG#NK0YpCP0qh0[iN4cK#8p#&[KR(U%T%Y@`LPKC1Im
--4D(XhDC)lel2DR@$NUBQ'V++&4MAaR4SlZB4)5@9#DhmXj'`48dJD@A9"T'mLkN
-Q`eBbP`3MNjTJ)"91(56-r0SESjcIEAS$)J@QmVT9'CmhqXcK(RMVJmN+DMJ'Tla
-FUj[PJ$)R)'keH$9aHIQAIE&*DIMrH1'8RRA&NediCr@9qklNPUdZJ*YFU!r[k"q
-E&9,(fq,YKZ31ZYGbYI0C(cV#mRJU+I3jrk6e@U4P2IfHD8cI#ZIh!Qce1E80DD`
-H*,%kker`QG80kK@6hC2`pSE0fX6Tc9a!d8X*51Y@(K[4A(C-bfSl%RdDDphP[G9
-+P)TIpXP)h,@VHe-4II$"CF5F-`5+2$4*2)+[)ZT&XLmXAKUZ"$krq0*)F9TpU6i
-jP0m'*kJ+CX,%@c*6`Dbfqkc)DPU2PCqa8USbUD61PU%a3("NT%HG2I*0$KaA5)d
-KYGVVL)p&2DD#!dX$S68&[AYArAUi3Ndp,iFF40!jKdG3+k)@0A9e5G@N-&)4&F)
-9eZhI&K4GLJB`f&Fmq0b+ja8fU1cFLUZ98S[AD(AQreA@kPe[3[pkm6&X6mA'RhV
-EI&C[Tqr`I4G88rh$Xr+4SUP)4V54PT&N"4))'9a'-G3bJP6!&kQf&f%f'U%%p3'
-&0U,NiQJ#9Y$&FcQZVG#e!pq%+`!mB53e(&1$J6C[+I4P+3*6rA12I!Jb%S3N[VC
-#14"ji0G$&DVI6)PU$R%PdF!5+K$*%q5QNe*JDQAcAP*%eApICR1D!6P6ECjUVe8
-effp(hM[be,$2T#k)YiCl`hX[Yh1N8pAeeB)%9+[M-LP8CfP%QQD*!5RC3-J$SYl
-fYNRT#%2&80ZX,%q-Z6"ie%mI!JqJ)j35$SCd``5AZlLB8U"da)Up4Q%Fb35@3"#
-)88"Lr$X$BerEmR`bb%JQ&"V!4*d*J5Q2GpFKQHH%N4J`mClqH*1k[pImR"B*T[*
-RR51C*T[((`C`mS*YGYiN'[`F,T4QB[SDkIe'5NeD#L2hpY@C-'3Rfdah[a,4lbE
-%33N-5F5E6!"+h*!!4N'+"F2rfPIRlLmHSL[Id3pa"BNpRX"209e+06SEBI4Y-!T
-)*-EKISCaf8E9Ai%Fh[d5*Z"GfNRDA!chFL3lHE$la`$'9QaNkijq@N`(M'6MPMS
-FV3@VXZ)M9+e*YB(e9'T`bfp@',F@)UddZ+9ZKA(,aC8ZA+I(e[K"'Jlfi@$bZ21
-$0$TSF'kTD8#([G#fj49em)1ddkM3"SX44*Q3!""Nq"a5JcYp-pkEH5KX"VTVYLh
-K&L5N!V`['JYEB6L189US0UD2m#`0D1lI3+$D@"p'%UYqNK61CjeBb)A&[5F@F[q
-MB*NDE,PNFHdIE,R4mXR6MT4JF6hY-"qCliFkq,@*-ika`CBpP[pB2pM5E(QRlSf
-a#XYre,da(&cl"2dGHq,1JP9[M'HPr-eGU[8VK'2JY3&-+jXl@)@IN6'lakaD!3E
-0a[V"'CEH,Umh8ES)U5hRRa3)2S0EHq0HVjA5ZYK816RSfY8fa"2RKpJf9e-#%B*
-KqGC1G5EUp@R%K4&DU0U4'8Z!IDQP'rp9RI&Cb'b89MZ6dGND9e1$cPCX@fDmXGZ
-jXIN8+MGH2hV,a[IUrcpl9BZ!A%[*Za05S!0$YD4`[U,2HGYmNieeCl8PPF[rZ-6
-%QC'1B8%Qd,F(L+b*Qr1#Tq`EebcXfRMX9!FQ1DCEZp#bXCQQdFjj+JT9#LL$'mr
-N+Ui###e`fiVXDUZ`me[Yd@hkU6rGfj3NB%"m'ilSlYDf)pa8%5Hh'&ANeI+"IJa
-ZU)U@91b'STJ'Ypb'3*Uj9U!aQ$4E#ZFS'1#3!)dmZ,A3hCpZ5H%S'F2K*pJNFK3
-2kciTR&jX'a05P8LGF`dFE9mLiIN[A4KZI2mCBY2Rh1HQ)BB#,U&dRk8L6BcdH"G
-)k8EciNPf39QkB*3(pd[,)#kF-2'TIT!!&X"e&*0IZP,h@6J"0ddC,J-@`@CQQQT
-T!kRke(cHAAS6Sp0d5'S1J+`iC5Yph00[)&35%Lf&1Kd*LN)RPVmAYL36,5F4'&"
-!fi#Vc%+5AdC&rNIS+,EF&Xf"%GQ[dj'cJaLd4*(Z*%Fm'Lmc$Xq0AL6@9F&LXlL
-`a5PUGT82Mh-b9"+`HBM5`ApmKS'K1Pj0V!N8Tqc1eQJ63dTlPH[!Y3q3!'J!%R*
-c[Xd-qI*GEdrekb9K,P+A5ilb4R5j"X2KR9(hHp)c*Q'q,iVQ'i&%VUpe&`hK(8d
-m-!66dS(1-pX%da*IfKC*,Q"N`X5!q)[kf`9d0*Q%q"K!J12NrXQLNcHcl6Z)Ree
-Dh[)#$+T+,%$S,VKM$i,&Ye9B5'DVMTNY%D82CT(*krjD9cGkl'!@K,h&$q)UZUH
-lXh923A'bRUT%-ia)(N2S`DILp@*kCM%-XqMh0$8'G(q%-"b,qr'bH+3%UQ(+-rU
-'%NB@D+rI6"#qJ*UmA+T4!9"DY,)S0(2rbS3EG$@IHNfqMS%Vbhie'9Bd&NGMQ5A
-r)GY%a059A8D#C`S!AS'3!)Y*2bdU1[2kKCpI1K#JT8f(,@Q,EH-35)fYTLk2NPS
-S,He&9cREPHfRT8Xh,IY`-ZBVmclZbimqq[0,(Q'J*YVMdi44SAB1C)jd22kT1QH
-9BfdQr5h+E(lYESIDHIc55'a9`GVAk'r4DpGNhPh`T50$`EC3UQXXh$P3iqk29LF
-V,$HMkekZ'`SXJ,1ZirJPVI!,ee+Z5qN,@bN5,R(GATXaeVfiHh'[,D2%T*lI(q2
-*3HGk-0R8Yha1MKk)+"$J6UKRk"HhE$lSSFf(5N#i4TA9k83(VbMMA$*&I"F*,[1
-3!(J9YpN2)3G#d`NHX[0+K%CpFRkr3K1G!00XFG*a&*Cf'jhKEUFcB1TL+0DReE`
-cemG(Eh&HR8c&3&j`9"SfTe@UR"#S%N5FX-bhJF3j)6UB5%h)1)bG&b6'X89J0ad
-G-(A%`m9-r-YTi!Kql2ID1)PM0[l8-"U9UYkLKdT2i-mL`V5*C[YjN@KrcP6r3S$
-6U3+P%RT'rAEUZ'NS0EkK![Zm+14a'18QCcM$PX*9Q@2f,8&+EUQl@K`!b8+E-q$
-'))Q"d48BG!DS#IfjcNX*I`%Tdh9bD-`[Eq"bGLfU+LE@b6c9VQ)KN!#RRKMm1aK
-%Ak@UA&QU%SaFGSCTqESF'@,pICPKSh2i1PGd#'B&dmC*-"%3+"0!eXeeAbD)'cl
-Y3Y-56&BjL%8[%@A9kH)h6QMNVL#I(&BMeR`Xp(f6&Z0b2YVi1U-Q'B(K(AM%k93
-(qSdmp&iH*h$!'I9R#@9#QlhCZReJ-$DC1#(i1h34+',pp`TBa0JcE3"C4-G!N!!
-S!8%#B"R')TY(PJJGk)rb8+YK`#&T`1FP!cjhK[dGI24l4Gi36C6&YT)#,33-'hq
-H6kINd)-EG!G,0Y3rNF+'EY$Id0r4KPkpdJheBb2(eqGL8qImjcB9SNKA[("-k0d
-!FXU2"0GAhTAp[ETkDS-hCVrPrDG5Ap9`LiZ)Zf)M-ZD9A#rPYi,K-&q4RkkSP3h
-j&KFPGh@kaBjS3MVd4KBl8K8@e`JlU(--"@F9C!MEXSaMUQ!PdG`h!S3FX4aH%H0
-0"S485L(N-03bM4f%#RP[KqH6+#pr&8$cAIHZ$kprc%eeE-SXqbmFlF+469m%238
-4i[hkpB2[emZMP8,'G'T8M4&!ZlA9!Rj#Ajh6kDUjGC51MD[dh868h08bBjbN$UN
-DkFeAMr"#RXGITJ#SDZR3Ci0K0jp*QpBSPE0G&16eT52HfPKTbCq)b&dkR8FS4,"
-CbUj9'c),JrGX0YR6@p'93b4*qQ'3!-)$r@![ih-@'Dk"'JTM3C2bJR&c+5H5(`i
-mG)SjRmmY',hPI9FCiZYQ[ch[0HhRVJ)&KRHfDbKdlbYR(2T9!Iqp[ej6ULTFF@r
-0pD8AK6lq)LA99,*!$3AD$#ifh5k!+f8)G%+U5qC+GZ$P)!*`P,Z-HCbkQZB,ARi
-r`NjNIXIAr"YcD&1(E&Hi%5jDIU1kJ*VARqYm(%liAGi&8*A0fYZEiDCmd-B#E5,
-bHYiQKq+e616EjE2GFBiUaV'T9Z2lpIIRRq24K(3i[PkQMh)N--V4YAQJ8'PaAmS
-HL+%E'4llkK8K$S%kUU6%`B3+AcQZ&XCjG#KP(f,,([c*+b(G340H8%3)9&@ACiI
-'qDSVaG0i(Q8(Z0iia"ejRhkcX*!!!deVmaLU3"9X2K[%lc5SP`,eh#qUCrN29-p
-bK!ij5e36Jiec53dP`!ec,&pr!XB(A8cU51LUA3UKP%""L'db[5U3!)LFPcS9m[I
-p%hi1"0(b9X3h6I*kDaH"qiidQCVcer6U&qHb!T5&&EH*KNT14Daf5K$GN9E,$FY
-,QbNXchbjmK+@pqbPS`IBdBZ-V0i1E&+C2K1TdV1SC'V6bqGTF'jL63%0Am5'rlq
-21ea@+U`Faj%l(,@F%K90kmhFNQDeda)S'6qBPmGp*UmFMAhIcN-$&m5M0100bF4
-j8RdQL2lc'$9-5LNNQX0jl-VhCAEFmRlcGDlc%39'fq+!f+'4",6b"p`e9VYXjjG
-*YB[Ze(I#L!'Ce9k'(Q%cL#249ViIC*4pPq)`"(EQ@NSc,Q,*)J-TNb)T,,`b+A[
-6i9"0)LN&TjbDcZ84XkNJlYHXlLh`l&,0F-RYcTUC1C!!V[dYpMdTM'!jNM(AUL%
-@NZU)Tl3ferCiUrEmA!G3l9T[k*iVQH`c,0a6NqD)#SDMNG!pVfehK)-dLETGRHe
-Ykp[p5%IKq%6Rc)DLR(k2jf44cXa-ZrZ!HdF'5db@'d`S"&QjZ`'*%VK,bGRHF4[
-RC6P3!p9RK312"mZ@I9L%4dc8cY2[,[Yd+3m+TUeF4YSbTTU2IqL0q3*FIZ##qPN
-cA-Fqfa%HL1cBUdCf1)V@qIbEpUkk-"a4+qr,R29GM"HeUYJ1-(*j,E0DH'a5m*Q
-MbP$%QK89!R$2RpYlB-mM(f*5[fN,&c`#820*eAVk"L4'j"I``-ELap@&&$a,X)&
-ERN6p6+MLCmeB6YG3(@6JI,dp&kJ)pjF!jrFbcT[f)%BIhB+EZ9JJm)Z9j)*cpmF
-Eeq"MHGV5DS6CYGl6#A#fCYQLeb0peXK5E!l'h(hD*4)#00!UelP`FF($$jiaS*d
-M*F'lrERXbBl#!dAD('5#V8J,jdj+N!$rk[l(AL`jQChY55FdaBE&`[1jr#d56Kj
-*d0G3)$'&9$Zm%N[llYcFSZbFd3-dNTMC[eSRP@ER&18Hc8R2034q+j+CAd+"[(&
-jr,$N'(9`*!+AF-9()%P)3,Pfh!3RSLH'4ePd!26eY1#bQbZdZI(h8$@,'AD#p@'
-BSbHEEDP6A$*)Lf'58RK030UhF$FIJ-@C$eecSj,q#M(MBTk&a!+B4E1eeHc$)eC
-FVG@`MjhL4jqiS&fX'0-fXSpaFF#`Z-!RINa2dDX*j+&Tq,I-A,QjJ"hif985Z)L
-F8JL%-2@XBHX)5f$X+bV8Jq&93BLY%&**(R195aIpXf,KIE[aFY"V0L[-CJ86+jK
-BSC-91P(iJc62BqPj46hTlHj#YZXR$9XMTBX)3C%BQXmRe0ja"FQKTm2Q2pc++C`
-eJMBa`"eC'rG1),!qcqrEX1&@hK4J!UeVEpcrHXeC+eGI[p"VAf@'d3TP2+"YFfA
-&`hP+B59EA-X@4l"BH,h'9iHPADXki3L2C-a6@5*`2im(*[DV2+qbK+hbCXhV04"
-eQ&,8QUEk4IC#aThUKTGk3+MCR6Qb!@LrAmhJ3JQbIeqkV6YGfjYcp-$0lEP(M88
--VZYljZHQrmLHRTd$H+m-jaQDqY+"MNNNq)#Jb!G`Q5QeCfFSRa+DfXTYMZb%'[N
-E-aE4DMAbTN-UM-lMDYL#E@UbZ(BiiKVmY-+X4b`1LiYYq1i8R!9U6#US'ZNMI$1
-IZ1lGNQ%+IKV*f9!bb&TeL'1Na(EZ2*UaHb9hbf"ELdG"a&"-+*lX*F@626k$NY8
-qjBAM$-+MU($Nr[1XSH,$cdH['5mELdJ+bR8'4BYX,PDd5$d8V3q[9lJV@"Dm-43
-,[4Uk&0SAI#K5crl')QDm-RdbZGj8q`LZLBF,3TDIa$JHUr(h08JUK1BiMla+bf$
-6lA!kqLAbrZ9,Nj4'DedTJd4I`e5rU(3mdLT0!bB#Ba)b-#%@5DlDUdiCQMH%T#'
-F840rQFG$!8`l#+DkFKqFdrLX4Q2HLm"SK$b3!2K%c)4VrZ)bjDGVIMqATX,M-"e
-p$Ehj8rhCad66`%1r'C)C#Hhk*(KY*C8P9r2aNXU%S6*3A&PG-TLV`NLNH(TFarZ
-@*'KmFRImUQ!!q'`!(J9A*[3fS0S!MZ#D(`E!(cLdRQeGD+9E0r3@a&6VXC3f8la
-%X)qfKQh()KTHDV$Y0-,@["DeAGbbDYhYf,*UI'Td0f(,k!'%QkJj@JTSLC8#66,
-NR0rTNcmHiT!!di#[d%294*8,Mr`J4J-'P*frl"L5[APLm989L(Kk%3p"A)QTA5B
-)(r%4eHje,lX9,Y(BfIP)L8%8%Dp!c')%-YE96$0@3c#B3k8l(%Q48j9L&m[,3ph
-X`[rF9G9-lXMq%B3#CLNrMT&djh'$L+B`%Bfk$55-B4$$RA"#U%b-JGJPQCD($iV
-1C%S5+K"-mkA1FC[$Z+RB[HY)5X6-2MNlZeGEG1!jch-(MKTk3`JRid@&-bIe$b3
-LpY#MXH6UK2"30YJ[UHV$pGLSlFbK[BJU4PDE("#N40Fa9ChG6b6"D3kjYUa(Ej'
-YiaM#jePhBref&+,QB9Xidf[#ePIM@R[Si)8T&!r5d$G[5XU-aA!a8`S5Cm8[T3d
-`2)ClC@CQGhC4)Dk3!&-dbDAZR-4TmcbqMm[QHBJaprDG0KKfFhTfh,6EU&h*IZ5
-9#&2-X2[%%(XNi5)5dNdIB4h+)KMp,Gabq@EHa3@mc$b'Kd(,S(j!(h8)63dSRc3
-Nh!65bdUfiM'*#-[4l-Q-SKdP9(mXh2KK'l@D'L`Nr$Ap'bCd('D"6'%(`(8'U')
-6Zk#[G@FJp)QS#e'[#ijQT"GdC`b25Y)I+KDj-pfC-!0Eq33pHNS$@YmE4`T06bL
-XIG&Qp-8E"4Y2'+G4N!$M6EffH"JrS@MeiENd[GM9+3BQ(m@)5A3j%TllI$hr3-F
-!`!Qmkh)[Yd"jc*FlZ6XUi00GPDM"*A`##[($L-N!!APa$b-Q'i@TH!+%61,(bY4
-P08h*c%D!GqNVMFFD(C-Z2*!!kE-N&F-##9dp)mR$$)3-BF-p0+6+j649,XGe5mJ
-0Qj5,"diIJ8!qmBp&21(EbLeRPa$#i!@%JE$D*5Xm`%KT96X*l'I4`-#"K4iSd+h
-'Bmd8I)-+'1E9G#K0M`[G$56c@l4!-SQm*RHrSGPT%(NC-NPiPRY9p1,mQA,HBrN
-lRP6KPVrVk"(",`$15EirQFjlZ!f[!Gk&ea5hi"APjZ6R009PiBfCQ4cL*+P+-N'
-)aibR"U3bdbNeT"mAfbp(F`l-*r6YBS)f"N!aJAimASCAM0*p6+@I(qM(jR1%)C8
-K2IrLX+f['@TGP!h91%!mZ'(#C)3HY[H%mJ3i)CG"J2`8VYIB3,qRe85J1!)h$6k
-mRk!jm&ZUk'Z)EP*0KZEpDc-cf6m#2-5'm$`@Q#%ehiPCXfL-jK8E)h(BC!C"863
-3dJ#3!(f-MQZ)k9'4+f0V@1!G@cR$'Q*i914)3qkQ9*3*kU[CamaNZEkCe25&-hd
-'-hPhD62CQj)-V@C6XCN-cdLKJ,mAYfTQkG(*QD-C'HN(CQEqlf61C,Yi$AEP@E6
-dq'61I!1UP&j#L#iYfEh5*DTaMl@[J5e"BmViA2E4R++V,0NT,DREV@I[$'XiFeS
-i@l3[!6'iJ*I!B`XY,9SbiRfl&mr-j"E&RcX*lM2aM25P4c0QdTFZ!4-ZT4h4N!#
-SKCY&$54j@1hSEN"iQd`TACD`faffbfAFl9P[[5!IjRC2L(hX&$rb2%fU[8P"d+!
-Ek9&%%K82""XmVN@0"1DBHbQ1IhL"d$&b5V6mFN%m*UCUGbZD&4pjeXQYr#A2lAN
-mfU4'FK15F+4TY44BhVR'S@fqaZ%,iZQbPcbVe!iehc!&'l4,HTNdRK+@2V2e3V6
-&@L15R-"3)K`9M468D#pHbUk53191D3'@lL`qCX[G,1eVp64Z1acI(&9-NH)V5La
-am&I$N!!r'0#&kGX-"E3Ic5d5%4lSUGe*SE))kd)J"S8bKZB1p#0`GX`3rQ9!1cC
-Jd$N'ThQ,IT!!T9LjYFULEkY8I&UPiT+KJX3,28C[P`5a1*eM,2K%`Bq-8-'548(
-UHMA4NN-@NPM-BKFGkkHhmE"Ia&@3!$[RVK,#Y4'ipH@F1AG[I0["PK38ZaM*m&Q
-@8,ViZK0h8-"FU"Z0dB(qdJ'rhp"4X&5`UjF(UiDlXJBN"!f%eT6"Y46'[fj4I4e
-!CEqh`iZ+@IN(3Yi)rU8&`Lk55!$cpeUT#e2L!X31&B%pNIfFKBLdHq5(d[iapl+
-GKp'KUUL-S9)`j@HI5rQV"'k@L*HB9J1MfQLL%-P`f0ca9a5XfH8Q+pca'S4$QUF
-bl6GS$kYrHI0601,-8aHfEH(K!i*[)3mRLD`&,%85D1@Q0%D@aP6K58$X9NHk+"6
-`,2j9KYVjC+Q!482)!"'!X!'PN!!hDN`"(S`["FS'ie-SK1+Y30P'J$@8T+N@iM'
-1j6F-h'(M%AFr&N3mK0iK6`V"YiN!MJG[jQ&HKQDRQUa!U%+C*3FGT#aYdJe2SMX
-0&`D*3%8S&6UCN!##)FPPL)A(J'B)#MJBkPl#'pQRKVfk94-*FY,f`LKmBplDiAZ
-LEM6cR80elj52&MkalhHfdCUkTh%@Fhp`b221k,lMhGZ2fcj%cF4M(efdeB`QE#e
-CSlFqAc[kj*rZrA$9RrpfejQ,&bmHH[r1dEZA2AVXZdh22*krr2FfZfhMSESpYUX
-2,EFe(+UcG66822hG,cHh2(@miBfIAYN+!!"(DN&%3e)$!(VJ%&80C&B"%$%elNA
-r[fh1-9FC-ZaLV2ibPQ84RhHKLEA%i*JLbl"UTU@'FQ#PX&QLXN-mAJmIElU"2'q
-!jP$#5HQjZId5QT1U9#A2HbKI5h)-d)45$YHN0!&+%mSK+D@%FJNPKSTlrrjq[cf
-[K[6fHcr2rrIc!"ZYTbJRJL!)J%!dcjH+4h8k[-6P,8i'd"qrJ-a9XX3A%@"*9Mi
-G6"K')#U9T-H5N[qrSrK8*6e3YQRQpCN2TE65rT*pdNPT[mcX84KCHP-9P$&ec,!
-jZ&eApN%NBIKkqY&j)8R6&E0+@UKSp"Qq3"`r)5Jc6$-[J!8QJm0L9JDdi!)3b[@
-Fq8X89QD2G%LHM*2)H)kDKJ+4R$UKaU,-SPH[2RP#K%aRSE6TPBT&A,)(r*&L)!R
-9#0!*0RqR51iBQmV$T%`M)V`kjNrX0bCq2ceJ0IN$$JaSPkk)d2aL%ESH5Z`20Yp
-4T$dCl&MJ+pb#aM%6KJhBRdNhA"Aal-TRjdPG,LaK@DmXkl&F4-Yk&bk'5-JeK+C
-k93AcXPk%-'&$l3RGiQI5(4d[&c&*Rpf4kJ*6eH2kXH[(5R0T8-GCBR4NGUGmf+$
-8&8MbF@$CR,)emB(cdG5jpU[a4G!KYIZ3!&#YFiAkNmNN-kGY,$5TAQKU+ehD`NU
-Ab3a4jNeQ`',`UC%ZI(lb"&M*PBH`U9i%TLeA$*AC8K*J-H4-@N044,JU+l10p5-
-G6(!Pd6TG3cE51+rS6TUGk0*VU)m$55ceBG"H'V6CFP#CP5RDQXCc3b)jq"p5ea2
-QbJaD(*U`U$AP"S#5`)EcJj9J!Bj0RJaXDKMLL3Q4DVq,YeKEH3LLbeN6,K$30p9
-@mVCk5Y,j3PM-$KbB!(UprrI"`@+l16JS'aRp68bSNR4-chIK)XcJG3B"m"U*cDR
-'`HBd#h'UU%GBES@C[`KHHP`3a4`cLqh-IQdrS0@m&)TRI`eXE"2q1d5,5##I-LT
-FTVSIQ'+2MJLM"Y(pX6T%8iJ1a#4%@a(pBU`0d5&%Xf0f4*1)TXG#)d#3!*BAFi1
-+!dJ#$)kY)*3T8$GL649@QK,l`B$V!fUc5N2cAldH5TN1EI-XN!!ABeZC*CrkAi3
-QNZk"@PPY5)JIUVpQ'R3f$ATMa!VbQj3KSrpMQr$(($PA4A0-2kpB*'2qP-PSYcM
-J!DNK%(FIdMU"SFeCIERa%3J4`SrAN!")IJmCIl#@pQIZcG`,SDG0-bkf5qZIQkS
-Vdk`2Aa&Y30hqXA'Kqp$-8Dd[XIml4BHfBD*m+EfV46PmN5AU#fkGI$55b@iU9[@
-"YUBk9Gpd4AdrZr,jF%TNTJIm6rDTHM3f8f2cLaUEd6K%M8-[DKb5kQ33F3Jl!8U
-X*9@RRJTBQcc1b4&jFSpkbRe&A4SQ%$0+k)&5dK"T4P%0&H6Uh$D"!R)S&MHK)C!
-!41'GCLJbaU9aR5lrHDF#!N$)a6ZcZV%j3i()iNKr4*L4H$0XNrbXmJ8,cQj-5Lp
-V2h)j-NkE6N2Bp%4Ac[(&YNC#Zh)PIdBZ!PDcp(,*4kkEmQGXHG!cc5H&-*fDZ+[
-m'9XHFDT!dLa*#m"a'1SpRa,$lDcpLZJ5SFad-0HrBa5HLi`#15!qPJG1H#Hr""3
-H$L$mak$U2rK,%HVEaJL@Pl5q'Bh*+k*G*!**83b1LP$MED[Y(L%&((Jp"99[IVl
-(M[8$RCKJYNei+K$(kq%BG`0-UI%JL`LV8bUffT,dL2DBPCDZ#*8@ila)KdJmL![
-NjU3!BT8-pk(!b!QICH,2[dp%@@#4"rC0R$V-,,6`H@ALX(ZL'4-e9d5#96+VG)`
-D9Tk9Qb3d19CI-N0&fFB,`NF,4Lc%JfC[X4T2VXE&iX%NIi!NUM`j+0N@j-N1QXb
-N8[(TjmmRla-A96eHBfScAMI8)E`'e$Dm-Y8@1&E%eABJfhr%`P(e&&iPDMCH4PA
-lf(f3!'[1iG@MMZ-98irLG9deif95ac#T9ah&+k8fiP@RAX4J(5UVcRXSfDjH#S2
-TA+bkk2-qJpPPYRe@JqhXr#Ld44YrCr"H93hddF44Sa#PG$%qb%8(pDSAj3XSaie
-"4%JCc)DLamad`BKUaP+GXZ6#8ShDXjZhdJ[LDk"(e1dfUiFa9&E)D#S1'30QI"`
-2AHI0K3SFUd0#YfUh1940"l3(@SMd53a4'#SdaRIRL9#S%*m&SIZ#`IcF*mfKBCP
-S3!MC!B10G$(e&#H-2*ak6KQZ98NF([!qp5rbJ1TIm2NVp4NH-,miG2e*XhVmb4l
-2*3`cl"R"+qUTCe@J$9%-+Q,j8*k!X[T2VLVGp-CD,UVP`&D'E+KSF6PH38$8hAY
-`K@lcc2!B)jbiaQ-8b9E6QCK9,YErA0c)4ASmZ"!0ISM#CESF"&[pKLV4$,(k(HU
-mCNc%4(X9a1TY!20GmV#eKh8VQ,NC&lVPVl!DH`Q,iEM+aJM%EmN2iAhjr*1hp*,
-RCLl%Tq9j+Jrf53L(V0$0JE2$LXMqPlH+U,6ri(B4V8[qilj8adB8RIKTaK$,Cjm
-mM!kCqc,hMDdH,M2ei3Sek$C(fQqrqGri&iL2!)fdKdeA4%FJ16DH$lHBGMf"MKq
-LUa8r$[cBmF20caY&I#Z+jVD!#`Lb$F&8`m(81SmrJ6bUG)ZD")+i"U,m&4'rP*r
-[E4*"$6*SH[`d3h&!L0Lk#m%jqXTpb-V2Fpe(5%'b$9E0Rrm6Jme'Xi3-l$`HP+l
-jCebc9qi'0XULi6Jj#2c*1N[i!5)G3*EhLD3DabX1P)QA#!(Jp"5BQp8@[)BSU,G
-48'p"8"r@[81!e#RmcN**&P[!mTdD'+m&F1PH#qVQca,4Q0k**)eKG(b0N!""LT!
-!34f"G+0k,[2)m52"jSfqf6lM964%U6P&c5MJGR0J+m'V9ReQ0hA!UdRpbpqZUL@
-ke`0K1E'$cIPl*A2I0Y@)j'V8[6kMN5DmLFmkYH45FljhI4%e[CR[6CPaf$i6J$b
-@-X9M83dF[Ja&mh-,`jbK*[!--AKf3,d*N!##bP%$Y`GffPQH$`E0G"1#4NPkS*Q
-ATD3d!!E1p"Q0r*NbV*qkFCmbH"5$G`Epmh`(*JhXRqFF'!(B3iKb6e#0fZG!G0j
-pA*8S'bcYIMqTiM0+Re(q0$UNJD`MMf9LLKb*PKal*PIUZ!N!32"1Q+kUd3"BeCS
-k9FS[9K0BM,b#4Gem@ScL3p*9)C1*#AIk8JFhHY(3U*Z2T8CGeCfqpHr1hSG*RET
-"kY#*)&BFlEK@TAXRGI"0hbd'TN8SC*ImIS@ZZ0U!,#1"(UEiD+$"QdaDE(rp&k5
-'"c%3N8%#'9T0ZF16L1"jc8N%"T!!)J!)6d"3AqiBHVN)!D`YJaf[CY0V'lp#0i`
-LY(HL%133X53ki9UKB@H4adPUc`A4,KjSQA5SfANS5'Qr@D9Em50d"[*BT&ZZ*)"
-G'ZMEUY0*rKQ0'8G5!bDV%`eir0M1e&J,&BY3f3BFFZ&bk5+jcb`haS-*MM#DQ8I
-"$+KVN6%qXKkAQcS+F30"1m6&2GJ6LcKS1kl0`bFAj-jJ'TTCV`E6C-%"BN0Bf5b
-+p)$L&!+a+&3[G[HS0FL%lifDqRkU0V,$$[qRJ'#PaD214EUd8,@fD`Ze&i%V%6,
-L&D(LU5C8`-%UG*@$9HJq,Y4#eAJp(#S-ei@ZSSX9BY2&[QfK5b`@cfK%4M[d3XN
-JYM2j#HKEQIK"2a2&R36U1j`%4Mde,1*'%(bEjfb3!!B@a5mim%dD@,)0,%dD1+B
--,%dD@-,!fKF0'kGKEp#JcEC"QbF01U3-f[cL33RTKi%)&J9BX'kM4,9Rjc5rSl$
-'5Kq%Ha54Iic%J5M3!mMQZC5rP`Yh+YCETEV3X,0S0MCE6P'2-cU*X)-U3$T@!%f
-V'V-#PI@5i`f+(rjiZBL"!NMhmaD"BQ`k&pQ'UfSF)Z2dIL#eTJC%2iHJhmDCDJD
-k&DGi+&bb,@E0DG4p(QMHM5PU,aIY$SM1((#%lPDF&*`k-)LR3eaZjq#`Z`ICAKb
-!M(1MEMU'XX0Y$4RR@,+T26[RrV55G,N)9iVYB9f1%[4k0"i,eYpQCMT`0RDL'!&
-Q!aAa)0C`i"`,"*,Ti2E3*D$E&Bc#3i@"CJ8T$(dG'39M'k1+S)")G49*a!iMbrP
-$2Yj*@!6ajFaNX5AUH4$qH+$%HB"UG"kJrZ@&$P",h!HS*Fi$e10!X0V*"d`J3Bm
-P!CbX#Cf,K5``ZXJaJef1S*!!YMBfL[#)$ZbDZUD1IRp62$YRfCD83@T!3L%6+@G
-BqqlNl'Td!fGA,d**$PDPm+"!%md[&kA-Z$K[32m04TFKS*)jF%BQB5Bd$kcb5`G
-PaF[PB"!AITZZH&EUb$q$cleS2#H$I1K)82ep85b2!3NrFqb0%%PZ"X+)D""a)2)
-8)NP%(YEGK)!Ac$r'))KK0[-(XeEaXa8,ldQpm`I&UGYq$23H#2kQJAmi`c1XZ`C
-RL!mYXcD)3%AEF"SE$MGe01RPKHA*-8(C(+XLjYUEp-aqATSc*SkR[bK3#h@c#aP
-VS+Ihr[L&Ekl$)-mJD#E!3'PRXN)Xl4`6#*,2%2Jc3k89"Hmf@a'm!m@RK-L'VkI
-hqp%p+lYbHCUQ5bj1XD8M!2`Mc"a0'CK40GD9P4ic)dJFZA@$Zi!eTH*5LI`cc2"
-EAMc@&BXU3aeT@SfP(@0GcSNBLSF["VZf,aDM)YS91%q&U-[bU-K21LUbeU1X,hJ
-8YSlYqC!!)*Ri'F#2!6mpB+0ST2h-f+h0d'@#5GQ!$R2"S$5!DGJQ$9"6PQi!6AD
-PUBF)fmJ4h3"q$2M*C$)hkEZBZ8!J[1*H!Z!)LY6p-qZB!BR"kSMX9P,rlm1("2%
-0#LcT#!VN"TTk3CPk!D54%#4DJ9am("L!D29bm#"%&QE'K59UN9PPV&6!pDc-D'f
-U%pHGV!Yi3QB"*CST)h1C!%Z+fEQ*PeEdC+CE-Vk)iF"S#U`aCRB!4GM%IJ3aU$2
-8b%J3VqL)KJIBHY3NQ)9*D$dTLjahq5)!8FP[#D3"!bqSF21-M4&+RiM'GAaYlLl
-Lr3+XaABN+G`lp6X-4AIjH-2'T0aX-AJ5`X'3!#cHbB*GLIG1heeH4BKLT(!82pR
-i-4S[6EV1J@$L,Kp[i*G[d`Dd9&30%-+pbL,cA6lMd8QG'NY1'ZXQ,EB%*8be6PV
-f"j[[mNNH5lBXXiJZMUYMdXZ*Ki4$SfBF*,CD@)l'&Pe`#FG%KK,)EcIkY4pTpeV
-A"**K4m$rQMq`c1%`q)C#"ZmeXdD0Z0P8(Hj13+X1Z@2'XB!pM-j@G*iA#QbPcQZ
-FRHZF,+BCl'3lS[YkHZFmrIP`&cc&i3J1e$L$+LA!cBL3!2Y'4"r!mTaJFSEaKJJ
-NqcXH[NG[00EeX`#!!Ja*0Q2`L5lrQR[dja%),CB4025$,@0GFL1$VY-&9eINc(J
-6iT@chY1i1pKY`lTTM)L1XQ)!bdE4-Fr@9)5QdU0Je(GmBPRdN!"JALbid#VMc,3
-IQ@P@ANNHbMjAkBU3!)&Ze"AG2-R&'Lki2$[RlP,1f%3-FYBQCTHCm8HlF+!"KIP
-dh3UjN!!lbYQL-I[#M*HcRN+"F6-eF&QeIqA5`#rq8qM4e'V,@MBc%qj*bNa#b25
-c%N#Y`dmMILi#a)B8CC!!`pJ5E%29J#5pl%Bl1MQFRb4Q$5PCDcm(r)lcA#5`LN1
-IQ6S"4qq&iehXc-m**QH!daiG%h,bfIYd1Q66K,T6lL#GH1X,XG"P11YecfB(pic
-Ej3'ZFN%$9@KBiI%T%)d3-jeS-0*eUec+H+`!`Da9bRJb%a8H#V#CF&!r$pNK,"8
-)[HJ-1ZEjUQmJ%pQU-1EM"fTXM2N%rMIMIaXbbmeJ4iC%Uj%M(BM%j3AAMi'DJ1L
-f$i&&fASmh4KfA3@MjDVJ5"YqV2KTK@+K%dlXhhhKCN5L8%)akNKNjfbVEKVri[l
-ErbC[N6H)BU31'd`jYbGeiF#SP!%4,m%S4%4R02)4SSjjMkkV+PFD'AGGqRqq-B&
--#3`L#DiiTEU('J#JiCm9c,%)$i,Z+I`NL0#r+ZqE-!5Mmai-)9N1JDi*lXTG2L[
-rYqS*AGUi!*J`1F@664d"2j,c(r[MhE-KkR`j08$XRqX!&iHKm&dlJmcAlM@C[`(
-@4&KFGZ6j'Ab-VCS1lD'f(`S"*UkQN!"CZGqkTEL`6a93%5Dj8JJ3dJCm)-q'SCJ
-PBm9J"5CcCMS!rp'a+q)!-R3()PI%H63H`*(AqEM31r`CI&pQed#!AJ''qA8Xj)*
-CFjfB03LD6QC0D1Y4,SUL%&jf,N$(32)SC369,ED!T%9@,)1#8KB&TH1#@DmP##,
-A1BKmHm#`hHK-%%j@*5KHj1#)M'('*8H4&f`m)bUef,(Cmaamq!I%hSaU&''jS5K
-YBN2!(US6Ia8U-fq-RG*!jK&h!*(C%`Jd!b@mh"PXIV"Bf1N`#CR3FB9pN9!L+96
-MXjIiN!$YDD5L,!(KZK'I&qNc439EJJZf[cZ(B6CeSp)p!KF*L%-$ik-%JPNRll!
-m,(N("X224@+4CJ5B$Gc+J!qP9hchqjU%YNm'IUl+m+D[F1X0I'J2MA9SqU6NK'X
-hD`kPNV`S$`LPP2ekr#Lc4"+SeL3MUaC'9L4mq&RG)LHcbUkbECDCTahj*HNb'PH
-%Y'Q+N!!'GJT8YP#"Dmk!9I8RYhK6GXSThSaX)L%J#mLc&cqZEl"#I4c$)8JDKXY
-1FA%"NE!1Pi!J4!+3!#`)fG&mcP)3H[U5,!K092NCIQYRaaZUH0&hrl[9l$!lDT8
-k-Sj"3F2-4hm#1K9(1"Tkba[b8L@3!)GEK1&G+E6$*eF+H4fZlh+(@2jSlX!p$Se
-&3DFj+PIkDiBkTq8ITZF*8fk-eGe#ABj0X-Mc(QrK4KH8,k`JI`p0-d#BS8"b(NM
-mFk(QTP#"C["rrEJA49D4C[b$bZrf`UfTL*80d[LYcb3*PCLQIe!Ch8X+lE0"4a'
-62NmD(bQFd(JdU&,6Q$4qk4H&PNd*Ce9!&*26Epk-qh3k!AaP2iEUPH*@21GNG5M
-9dH54(5@iS,c4*HQcS(Jc(3U%GTk8p0L5ZX"A[FQdKjQLVA#PL*P5IQFAGU`)k*h
-UlSPG%*AF8q8T'&STN!"[S%!@#dha3$0PNUB"I$S(rjAF+4iL*[TKG`CFk&(mDm(
-!d-"pD2QmNpIpb*)Ul)dE8"df066*iXN+&*V*f8"B'')*)dM6SCJIb6*e`N'5FY#
-&IjKZG+!c!rJ3-Q1EUFSMXUPVR`iQ-$+!b&3MF49JIdm'GNd(9!p1YX"'Td-3XXE
-XmZAijVSrIZ'Sji($$r4G9V0clXN#m+(S0[80Yb,Vbq!J3LJiXh1qDSE)0a6G@j+
-1!N$r0khZ!FH3!-)LdBFEG3q%r1*RaTE*MJ0K-,*iNY@RD6F8!F`fj[ZiJNFMR0(
-[rPG0(lXVSR!CSUTSC9h)2(leA!X(&VfT!mT5IibVG6C`"N+h1$YRdpb8S55G&jb
-*#U"p@l,(p-`DfI6P#$IE*c3E-9!E"LpYDN"P!$J@2-e94j&jTFUJ%0EBKDNTcUL
-%,V%,cXSF1,E,RH"%-"-C-DJHG&[Kd)),L5heF2l3HH%HC!!ClVNX)#lZS-il))B
-Z)9E328"'GQB&X3["2-T5a+6,DMd)HbX-"m`G8Up$BaEcKjMBfMhDRRPpKAc)$N*
-F1l#C-*Jq(B&B[8MX4q@p*HLS-3h&%KU`caQ"A[0*kX&Y3S9)%CV4D#d64IMaDIZ
-bHL#-Bm!&2F2jP(cR0Af4*$28[q56%a"CJN`+'$h5rUL*'8jJcc&+CA'q$5T&1GP
-6YSk'54he8Ur5%8i-b%3QQ4hhT3*1'(bJD2l5F6KIj(aee`4f&$QLJ4AMH&YmFpf
-BripIS))h$8%"&HBf2F#98#'3!+HCHSCEkjf!PmQ!Yh'U"H!GC@6CiR"d++"R4e5
-)Rh'@cYJj'IKiQDGa*cL-)LRUQ)'b9HUiQbSC)D1H&Q$J@1Ek-5VZ)31im3&d5Q2
-`Bb$6p$!"0KV@!R3,0$d5CAqLqfFdML#46$fhc*`i05,$a`P8TllTUdiKkeN8Nq`
-NjXA#5$"@LDY5r1Da$#M%A5dC2GSq5V#qHAh$43bkFJ@@p9[@!XSZU2f8J,$q09E
-lmB,&K'JE0[(bP-#BIEJG&B)#M36#pRj')'!S2(hp"JHXjPJE#+dMSXc9q9l*imP
-`'L4bJ"&`-YBkZD2*6"e4*FbB583cb9@FQ8"0$4C"TefThL`((R4qGRCG9k!9JrC
-5FMZ2pGU1IAZ8JCZ6q`!kPfERE0Ji#Ga-82UBf2N3!(H8!&92J(U6UR"beiLQ*d@
-JZZ(,NcVE+BP-NSH"&@#&bN@-+$E-CH,+J,YK[KY`0hc#J2ZP'ShI8Kb!baa91VX
-X8)3@UqmVKHJ3#4mSh"m`M4,c$-TC2p$+NY49pAf!5c15[80NACHAGf'TMUH,R6`
-)-RiYF#**2QP3hjH6F,4,'5$RXTUR`LQ&R8`d+@B@&+6UK0&i3#BdL4LHb3,',iG
-'C8C,,`XQQ(#9"R$)9iYTZ!-%e#``B$i'Uk"aU9&@*%,%4JBelChmUU9IZFYRkSR
-&&a5$PEJ383P((9FZ%SB!I0c8!G%e6*[BK-$BM'*),q'JQ4FJhVl24,0EZ,YeMXU
-13C`G6#MC4a409i5VkBVSD@TJmCBckCaeK%"afTCaR-i&HBXYkrKbqX%#"'[IB"F
-08c%+!5$@D1r4Q314$eSL"VFTJ4HB2M$c#@c(LS,6JDVMel#"bZG((c&`)PKQDYc
-1HVU&cL5hc2cHk#,"c`@bp)$j0Lim&YGIJ#*J*YcT2hhPUR$TLS(8jYGH&6fkD4!
-#&JCAcM#kXm@R+)2%fe-UaPYF1R8#B-+&,E%q8I6E'TYULjCdcb*3YD*"6TC)+bF
-J-Z[GPA)f(*QS1'r)b0[kjX4,@9a)2m2Bhm&EYNp`6b5'(LG[[XQ-`-0UX0j8lC6
-U51f8i"AYP1SV8*0-#FUL"4"$MVKS-Km(5&cT3f22P#"-E441UBDbl8B`K+be(Je
-jD2#aii10+EqXbF0$+&-GF[8$&YhAa-$m@!CA69CAP6N(@l@#83RrB%S2@#Z,&`"
-a!+KEkB+G*J6`30Z9`LRP8h,aUTqbp`U'Q9+1`q[GeEV"X1++D+`q(XMmb''G(kC
-Ue2'hrR4lF9#0R(#c0CN)lJZZ#L)V!*)iTNZe8mVIZSCAr9[&3QEhSQ&9*V%eL4b
-16rPD0VEQ0KU-K63f,E#Cf6$%D&59T6)j%TU2b$Ej`l--bE10#`Ji9U'+El"M4Q-
-rh-18,PrQ!1iqJ+[#-ZX0`FbU6#PJTh!jqd%,Xj9$"L`119+2bUL(F"#'Dc%k(%2
-cIkJ4R'QIbQ*)(fA*89$12hClPmAK8BIrH,UlbU[XIKG'"JaJi'09[f!A,$m8hDU
-NIY$*JRH!&9e$8C1Xb14Ahh*b[V6,(@Bd'ZVp("LCjCaN&6pFjr5-KTrSBD4eCAp
-P&X6DVJQ1cieFD8b`1bP3@DZ0J3RP@&DJQC+&QTlS2-k1TPN6%aD-J`)q-,'ASd#
-P3pQ9%-5d6q8&$Pd!TjLMIrf[@4p"b%CdGXkQ0'60%(9Fc"S49Pc+iFkkb8",e@D
-5%ipK!Cf(IRi[!fG*qUdNS4b),j,*PRc%KQ53!)3kbMi1FJ6l8eQ4eIFHQFVUrAL
-Gq1hHkhiYR%DNMYrZPE)H[#Qc53,edQ(Y'BeIfa20@Re6K1dp`K`lIPR8#lMD&#@
-b1-ZBiLcMaG%@GYC#SP`FID)mI(IhD4mY2rkl[6i[9qk!5rh&F$MAPcTGXNplU+3
-(KM`FYppK4UH8"6B+-dcXp8![#RYQVi8J0pqCJC!!Y,@CZK9iJ4%""9krT+eah2[
-a1PpYVfiq+Lb0kYkXYQ[L-0XabX+U88mIpIb"bK*F'I!e",-M(*!!dPB!C5l+%`J
-!#j!!)5KP!5bPC9,3GRjSfmi2,EEc3pYfiYM1$hNlB!+95UG,UR5PU+UbU+3AefM
-@,EVp'MDf30,+'e-ICA8BLjfCk4%Y+B,58N*ke*k8Xp6NS&(fZ#pF%KQ5HL60H(,
-(AXZQ'R@0,ra-hC!!G)JEA@D$@@jHibXiecJN(HCPYp%',2m&PdNV`B'iMPqAGRZ
-2"6(KMVmUc!8P""Gl1Hb@4-$UA$hI8')30d,D3iCImfG*5BNB$fAe'YlMci+5!R%
-dG1U`iA2qV#q"le+S"+jb-"Z#KDNP8l&`cNaCV6+B"K+VjbG,`PJm,Lq@@LkHPaF
-AZaFcAABS"JU&EX6eX!6%(9kQA(8ZNMh-ef53!'pdT'!QSLk#6#4-U%LHAPr4fDK
-RcV(6[YVRG&[[r&(FHmI96qSIm%VYpBp[(ibdrrA)AYq'Nj)I%ip&rA01BZ+[3)c
-51lZ&2qlGr[R[6fhb5[&,eTf$dALjR4-iGI#1D9)$1Tb-0Xc*T3j*h64d5-Dp#5R
-iTBeHU50[eGE"QSlb0AGA(I&YfLI&-6dAdmr5G,XZ(p2YFHqlEfaHFCGAmPc@EaZ
-Xmj5hh9fjalF4#YPHAl5Kb"[Y8$SiG*[3`4(hrMP[9F8'Vq3IHIcH`C6rVr[1qZi
-k0Q',-*DPfil*eVMhm*RhkZji9fTiflTLX,%"9krif2I!5DQG0YUZE$5-DNIG)Kc
-h$QTk9p0'9p&'ebJErGbfd628S99AK!kYFHr5hRp3DD0kfQLEa8E2f$BUkGCKZK6
-hrXShH`0[P%MZ)C+ICC,60[h+p)4Z!kBRiYjp2FpAF!)4dGYPSU1#IpPkaC!!!'d
-B%BAi%GdZG)c%[6VGApkL,DqL,DqK,A1RGL*rqaam8*FDh6*dUBPl2cTqacZmE8U
-!Z*)!CcJ"LYJ33iHbEBeZ,MTSiYllEUk*VM8"cYJ5i&(G9%aq&#5DrFq[rPfj-Qd
-&%ANcNB2VTdMfAP5b39,BPD3Be@e"ap'ipp0rkrZBYVq+YZp-LR@F&)f#%b0KRh1
-D1ShVGU$6H0clmQ[*TpD5(!hBYTh*LiT%TA([SXiR$e!b2-(*m%Xj'H+8B,NdDA(
-F@f4qhEcqAFPqk6FihPkqNSq2([cl0!@%9bV$,BYl8qI228IN(L*b0a1j2k*NKD1
-he&k8kr1b%d$Fpp-&RaG[mS(-GL+c95(c5L,F5LBFKY`Hppl9j2Kh)Zm660jIbZ5
-9!GE$5B&TZq,H8)meiqr[5L[TLL[P+a**1`K8lFU!1q,H$4rFkb95$K%TQjA0V1-
-NBbF[D@A45EVNTVM[YhrrfY502T!!d%iNY")*2q*NSZhBLml5e!eahe1rqkpl@D%
-jJB`V#5KA+S6F%[G1q9llAC-*5BM$!K9JDRlFZrJl2cM$'b*#VP3)Z8m1(KD%A"I
-h(6TR[AmYK'a3!TfmmDPaErFrrE6Mri+3!02LhV+rIVH8%j!!VYKJ5fSR)Cd*8a6
-h"Qk&eM-KmiC!(#DN6"b23Tbi3XDjFGrhk`Ef-"RVl5!1Nr%VFP"r!e2ImXV*V&[
-b,4FK[9C'HMrp2MB"emAriB['DFUkZ2I-2brb8K,[TL4Z8)MhDkRK$lkSRkB"!![
-rrep%1I"b-GFB0aaf(5E#Y8FEA[G&1fJD%Q,ThD0f)XC+*NEjEqkH"A+FN6cr![,
-5*!5-6plCeX2"Tlk9Vre6T8$i[5rD6P-faEhl(rMrZSPBZiPB$ECJX4)App!d%'V
-4(rBEQ9"mTCTf3kqVP`J9MkjmhAPa!2!lrc)h5!4B58Mr0dkNEb-5NM$brllp(Pf
-lPDrp8`A4r-&*T+eallB2(PP#B,1E`+E"LGjrlp`m3'[,AcA(R#5+aJd(A3ITfTp
-,+rr&H@d%HIrH[h83mPK*S2mE*ARPDmXNf"$hVYq5rbe#(N`Ncdq26%VBZA([[9r
-kjYd8h(C6F'Y`&j@fa%@Jl*U49mSATf4E15RCC#)"1+GpjG4Y3X`V#G4ri`Cehc(
-P8L$#iSHL285Q&LE6r6C!pje8L)"%kD[6rC'5VSf56Qq*,U,fd`M)Ve1eq,K[eX)
-,2hi!!Hl5'YV!UJRSBL@QfQRUpVL[l0@Chb*Nd8!Nfqe'&VkcES,FrXXc8iKN,8b
-bqff)`THVN!!$5I5[pRAA#%fd%CV3@k+*D!-1pG1KZk"kq1[Lrq2[48M`0C6JUpa
-S`RI'$FV(F[rp35*F!a&ZpeS)K`"fDr$Yp*p)1#48@Xfp1bB6cSNHL"`bi4E(IGp
-9qka-Z,`eK"j@ZG'$M4`!kHcNQJmSN!!e%'VBVD!'5i)JS$fImICT#K`Y($MZPj&
-$R+j[#rK[h&Mq')235"ZZ[a*AQd8Em&YX!#"8GmHGIf"5%-(L#X&1m[9"-)m6V(p
-jpZmrBP*38[U9T$ccTCYI(46qH`C&mSj"BBHJ@6V*35-j)S+V)2)2EII1!HY@fiI
--3G&6AVp`Y&aD9H4pb[HSd2ECqb#XEUJAPe&r"1+ebJjXc)5pY1UDldl[h4mGZRr
-+ZZqmDp3c`jFqLU69ZrCH@[@Shc!R&FSmIHld0#m2R0$8L,[hj2S5Th&S`jdRjrK
-Ue+LQ9Hck+1%jIRUD6jRJrGfHBpHLRP1i8U-bS9brjD4lJX(PF['86%b*((31SE8
-B)KMqAI'aI`cfAeT9[K*G[G(92rhSp2`D-FHAm&jDPI"Ni8T43r6KDZ&Xq0e(*kp
-KHM00Khe@C`-M'fj+H(JEdBIAfCT`52I*DeR(N!#ekd%@%H*mfLk,6!Ha8q3-V'L
-4@5YUA'%Ei%2XYA3K8M,XMbYC)&3(NRcZ"DS3G01pJ#T"&TrHfHk2Ek[M'UAMcFP
-AN!$@Z,08ML*TM6[EaCr1$"Sq(RF[IeXGP#-G2MGMSiYC+P$(6PQA@TfR4MhPAEZ
-kjjbYm@`kHm3,&`6rC6AUap+a1[r'BhZmEd2pZRd[JPXV"cITmEGbJre&Z3I[Rck
-3!0,B4E!rkYrad4cI`IZR$TbGhbULIYG"`d&HH%pC+!pM-#a-Si9)4r6aeh0jJ#p
-J`A+!2ddDi(0P3HlqDlPl[+DMc[rlBpV$pX18LBY*(6[h4M[+Z`MT[5[&m4QR$qr
-!28Qh-jpG8VBFH4NZ(ElSKYIAh9jL`4DE0%&DEcP"9im+Um6-B$0e!+*k-%DQeqD
-T&`i&G+@eH4r0qUqr%N12`+ZX%kB65RmcV(Y@U(JY%5'm[LBmH*8*2ej,43GHD5+
-1PdkdMl!$YGiB5Hb(%i(GB@9PceXYVPB+r-PU[mNDf`D'+"Zm5Sf!BB'&,A"Rc&F
-Z%Ld"fkT9BG(S&V%C3kl55&8E&9BIe(hk*Mm8T@G0T"i*k,[B#2*&X2MK`+!C5JQ
-SrC0FC4fUb)Y`R`M*3!-Q4TVG,"UK*US6cEbS#KM!8bESf$922!EPlqKF%F*")6T
-NQ!BI"AX8lV"fGL4,LcP-YE1@J)Nm2`-40!bLi3Nd*&hb!S`$`9X198B4JEYNl*c
-l`%"f8(`36E&ck4*ff@NDccT8NSA0,qPH+X(&3EI%lB+8kV+IP"h18l,$H8EIrE1
-qaUU4*rTQ,@&h8'-0MZM5TGe+f'Z&EYD5kfeDA!%"%kq$pmpDXUD+e@R'1*1YHfS
-6Xd(p"YQeH*'KX$LVqr[dLVLdVLb&L(jANlLS'(-X"j[d90SL`h"Df@!jXr%'2i-
-LLUX*LINiiRUR&P'U0X5-),&QV[K[B@Zq[G2Tj)%"PZ$(iXM"$rM9K'Y"TG#YU5d
-qC5M+m[@MXReaLD(S'iJ1[ST,LX&F0RQ*b"%SqXd2&Q*L2C6k"fL3!"RiH'S35LK
-Flc1kEK`JXa9%C5EZXX&b9(&1T%i`ST39-Ghl1)%-pHa+#V0Bl5"bHF,3K'h"G9S
-Q$60jYl*KJHl[bi[pV'kZIH-k,E*a1E!bhbKJ)RErL!X`*CP$51ClQH5%!,P+NS#
-lQ,ll*&MpADai'ra-RXE+K*H,%LG55Q"-@qaNj,I99[aF*MAm`!XVZETeK"aCh+l
-VTk&1rC!!'dd4pG@!#a1qVLK9aq3Z--%k`P&8GDR[@j'f'#cEiE6&['3S8"GQjra
-fUNbZS*V*UPNY0lQ(LE9#8@0RiS6BGIVbmA4P1T4RS45j-B#B-BGNJMZ)F'l6#$-
-"hlYQU&r*UJ%fE**RmN(*B69jf26!pc,GJkJlPF9a9Zd`b"#c'3$$9BfTHqA6[Fl
-VbX0p68Y1D5Pj@qT#2KVZTBd!a15NU4'B3R*[p4e@LF5QIRZ%ZAFqZDijH'N0!S,
-kDMdEc+JMBUJb-E$3BL0qf),iGLG4M@aIr0XQUGMbNdJkCRD6G'QG*8NI5l-Bj+D
-bZ1f&51S'*6BkmpX@HG1LALC+%jXk9Z8ZE'cjYqF)TEB&1QN`6%CeUBA"1%b9@j,
-'BGZ@DVNYa`3M%aC''k4*4KXm-+U"J"l32#1lZ3iC8iTD*SN"V`%ifmB`aER)KRe
-rqaUaQ#f-rX))dVKpSqD`P2bJ%fBbcV&LX@Nmml2EjDaqkjkCkNS0)#Me*6*(e)c
-$K5"@F"@c@%'b*$Z!ErFCrBk@PiZBU98$pDA$`dU90S&U6j%ARMTEY%ec6M@1f6[
-%UTmdIB2Pp+5Mii6JTBc$e8*AIQ@J-LJ0!+J2i[VP(!fG4V6qT6c48*PhKBe9kbV
-ITSCVD$M08FrI%6h,d3iVSRX`q3H9(r2N"PhP6@T)S'%K4q1h%Ch0dIC2%AdINjX
-VCr,NeEV+'G5`!!fIFM6j2+,&(0@2)PT&PhK6ZF4Ve'"!`cb10Rb%k&b1fUFM@N5
-6TbQ6hl1XFL!jfH5UX9R,&3)GDpi#,!JY9caIFc(%,S@hlV98D%C)b%eZ"i)h`)Q
-UYM+9AEQSe&6Eh5HVkef&9DH-@6#%N6,PhKT)qEQ!e#N&T%jha939Zp*AG49ANUS
-Z[94B1EhU[+Zb5JXe9@ePh&"Be3ZecM)HLJ2$bKk6J00[r$Y6CTmFIUfrYZS8&M@
-m''"c+0-R'%b"Xfa8-DDF8&4iNNYb4+h)S+pjbj[bXK(QD)e!eM6kN!"!YZb4Je!
-&V8QXrJpI!L,S@kHMB*c$THjd3,pcMcM0f-%BfVN(,[hqe)R)LFQQ*"4K[h'YbUT
-Q9P1Y68R&4'`2mb@KT(*F&Z@#"H1XI6b-Dp!IadrSNSMZMhSP9HZl!)-2NTV&ND5
-NRZ+)A9*,11+3!04c(,&+kR'1K#8B$%@NYHqR3XVdfVf-U!VRjI&JDj!!Q)q@L(c
-[&PrS0)XTdGGVa#2H'U%pPR1'(FT,2Y+HYCqP,RI+cL3#CRE#1pbAAX@%*9$KLbG
-Ur+&)M6m1"pDpaNEYDARB1Q6(0K`,83@m'Xf!H1SBIXl@3*M22mY'0$RVp[VM8R[
-''6K@6Rr)j3mpe112`lebQI-JJ%+4'`84+Lm3jmJ!rcNiiU'C2V*0(0AcK#X&`PK
-9a)R49)[11H)'&a0341Z-N45@H$Y0%E@C*b2##RlTLVQU+*-VpqXi+RRF+)YG9&1
-b)A'ldB(*"SL4cm*JK!k)r%1q`KZjJIL#bPPlURGqRBSb0L*#kPbUDR9AjDb2P@P
-F`4rSj8IiJ&+8PE#eP9$XVQXKYam(AG(P(N4@IV0T%NabjCr-6#Fc9Rj8hj)(Y$E
-TPB+"TdJmF'Ek4"-m6M&P4-#9iC6PPYQS#JRN1ES@Q8!`H($GA3%YiM6()V&*PiP
-Gb8M*M,[-9-MRS(SP9eAM!4*`E4lM3Y3XBL&YhiZlST!!f$2CT0'BA'N`b5iHX6T
-6BGA8J!-"HbSIdhMk*A29HmI6X6`03DLfq&ZSQXNLA[[J)kE+#Q[!#QF4N!!5(Gk
-6#LZXf6IKS"A5H2Va`!+&%#4J#X'19-,Hr4ZTbqllV2akM-dpp5X"&pXT4dHr"J[
-S1N6Gp(4"L+@TB6NM3mIhdPA-R'&jcKFEj5`#98&'*31HJ%68`q@q(D*`C2+5+i"
-V6ZYq'qK`'Ll[#,!61JkJ`P,HJ%2H3&"dQGR&)AA#+Fj$pBk,"P)34r9`%1ZNDh!
-P%KL0%AVh`'cDUU,"f3d9B@3(DqXcr'J(pqE2Q@SV'J,MMYUUE9c-'AaM`S8P)Ld
-l6La4K1VP%+LjUNpKeEEZmkLFUEGpRZ#(466C#*LfaG'&5cG54U644RU(E2kHYmM
-GA)pBZ0UhQ@UVTJGS!$41arEYf6H0c8j%+Lr3-%PX4DYN+C-)M(CkN!$$32TK)R#
-5$IYX[bdEq&RfLhl4260aJMI3l8KTB4iL"$G1')NJ4diX3i!D-K3p'N(eQcN,I3Z
-pF2(HbrpAl-dr[G1(c1B-GK0V+'D6A4!3Y1j2lSj("cJ-lk+l&Gfp#hd4VFD+!e#
-%m!'6K`068BXKClk%kS"9dr#+9Nfp![1I&9Dm)K81UMMSi1eMbkJX%hN!!F6[!Q%
-i14$CPTe6Ck4Y3LaPTm[Z%`S*je`j8@&(TXCRX6K9FBlR"lKmdMqqr6D5DbBQPH-
-R$i!L%+PQ!9#dGfpVUUf`@hD@HQ")[PMUJe'qVa"J`E8+9aU!N!$j#DlPSX'8!c"
-3%"01pBm[q`8qkM'N"d0kQMMMG6`ljj(TbK"'$+((%+IB,GIpU!'JGFlD"4!!@mQ
-P2facklF9SfPfQp-*)9aNMTr&Xi&b)#Z,!%bb!%6`!!`#q-Ij0HYCRM+KfQ5p1Q#
-DT`i%HUJb4*`B$(&L-+5`B&@bpLhmZ#@&lGE)Mab4Xph)'$6r4kQD'BJRY"#Fjdj
-%V,)j1MbDSl+LjABGVP@$)28F9qH4'bl9jRZ[Q#YDM-h1TH-qAR!qYU6*Bc&%jqd
-#)+2aVrd,1h3bD3D0E9fa835"'hJXbQ8T%iiI)E"i#N3F!!`h6KK#5DX1Fi9m4-Z
-UQq%H(pGYVd8(hEB4&5)YCkAaS*XI`(e``J8k,4beC!0X-R&K(XcS!MZ(Lp)Ef6N
-2A3BbpXAm$Sqa4Y2AK-!lD`Q+(Me(E*Pb"U4MR*&3b1mjRZiF2Qd(Zb8k$I@Rj)S
-43e34Xf95!FHZ6H3k$aFcVQJDIY'%&RN#3'NZ'@!DNee)Ki)`F9GEN@#"D[PmVZU
-*+VJ`[X*9j$P6Y#D,hCMpD93T*%)6MV)"-XX#L60S6L-86jJV%Xk-BQcL8(SD#ND
-cGjq&fB'0,0M'U0)b3"kX)+ifL#c-,bk9JdJ464HC#IdbLD36"R,-SB'UL4"#T1%
-+F*-fe(-QmrQT2#bb[Th1J4%`3dK'L0*24j9"mIJKUXCDrC+jZ2I+eG$eL[0i'5[
-10HPG!@UkVer)KJANL1HN%MQQ0&3MmS8L',TUiU,0`aA)2EZ#CPj#%1d-a+pFpEa
-GFBl"!Jl3$3M1+CMRFU%!jNhEUI)RVV4m)kSke"DEjPm0&34UD(V+kCkXJ-CT621
-"H)Zi+j`Aic+B0(A`CYRjGr8"5R#KYY%!H(5C6"!kDQeND*A*X,4(*S0k6LD$UQ8
-bU0P-"JBCDRa'hV$k&i8!Tj9)VY*`$Sm%)e%(6erjRTXBS3fS@'0*M-X9j`"UmkK
-DXpkC9("RR8#Jhd54PHk`5-5e%!S'lAiLS4bE*a)+alU)&#)d5S'd4EPNjI,CR+9
-Q8T6Gb',f4KN(J8A,6%*fji@CrdpK(+%B&@5QXAZXdc'@6%-dJQ'aN!#c!dj6+L'
-J%YeF)+m,Z2LML$`CD)5cEKe9FANR%%AKme`JQQ`%GT`ED!N0TqQJ$KaqD`I8NIa
-kaaLA&a'd,Z+R%3PehX6QXb4%"b)'*0imr,b'kl1$H`QpQ$PNa6'GLPQb0VVF8H9
-b@Fl,e9j9fh5Em'V4lH!XHShi1L0`cebBSq-(HQAR*0Jic5Dj'NFLM)mGQHQmFDI
-c,4d`&ML+E@3'kRLEXF3V2@NlD[[5GS+9G#mMNUHZSLL-i"1$228q#q)33Tc%rN5
-Z(K0S`e$Y-+M3l!4-E1046CGLCU%HE1%)1HC(')@`ZC1EJh!H&l+!rkH`,1$(-X%
-SMJ4-Q(i85H3L*QN0M[Nb+S-LdkL,N!"CJ[fkSr`"Plm"F[k2+!B+-V'eipKD66!
-b`dM6,mJ)%5bQfR9IP0dbXh2XMb,BlFe#%,XVFk*Ce#i*U(J)9G9DBDLb%kLCX`C
-4b81&hl*!%J*+Z0J-!D5`f1`UV%LjDSX$3A[4bCLG*S%(J1$kk%Z(+dZF#kJfG"L
-,#CPpTViU#j2MJLXJ1Bf+)G'5L'3bJph8Jm)'CJ6!DN&Pr$DZdQaM"hCjd*b8$CK
-!Q#0$+BE-IQBSe9DFGaB+)-B4"KqMDI*J2+8V!VCLJIS2rh1$8F"-iV%R3!%rk*@
-CA&6PZH2!Q+h+-l,Cq0r)2bmGUNJK@2Ib`kf!3&BKfqMi8@A&HFdK+FN4ia"0FAi
-b@k,%iS%`'jd9"YN`-*+JHB5I10,eFcqFNEZiDK-A@CeE+"V[4b@+PL)#S#&8#rN
-3lUFEYIYXdkUdI94!ie%MA%!65h"MIHGXm`frTJ2U@6'%`2%QLVPErVrK`5mdB3H
-!D!HBrSf`S06SA06kH,P[@9,Ji@-dc)a'HjrRYr6BVKTHH,#4(JMS[&30A8U2ajZ
-8%q-H`DG6#L,SZb[!,68i9F`X"M5b5r'N!MKPcZ1-4i)GQ-(J,A#b8Q'+T5ZYJ-e
-ISM),SR)4d3%63'N&-"daJS3U8j!!,3bN4)!S'%dX06L4h0+YPJKZk@)RLS33N!"
-Ne,Cd8FcfF+qP[f5d&d19U+@r("%@8jZ9c$!J24!D8Ir@Yr49L&C$6Q5eG+(c%,j
-@8cZC%)m5)eBId-YS(-@pPP"'1dm#QB*)TXDaVS2B,0a[C84pH#+LCY5qb%K-,Z'
-h(X4Q*L0Y%kiDL01eie5Gp"dX[4VJb3YIK%32@e4&i+(MmY#H(!9j`5c1dM*'AN[
-,eSDmTKeAN!"APJN6!pQZUV3KS0!f4PjT3N&H&b9dCq3PEbaYL"GU-p-N4Q",bf3
-%PTDS2CbQ`43K)c"dZF!XiMqA+eH+!"3H[S(#H6+V)L9)c(q5`B!UUUFCl8j'$$k
-A6@$#h$Z"#92`!NbB!TN*dqKaXf&b&[*'Q8L,GmTA#RfiGQC-cS,m-cqC'C1c8'E
-'6'D!T!M!RKF6*KI3B$Ra6db(L04Xj06-TJAGc*K'*c1Q-H-3YP91CTYc@VK+!a4
-mZL"!M%h!I(`%JBN$&#X$)"TXYTp4M!J9Q2B&f$aXh#RUXY,,"S)!60fd9r+!c#D
-!iG-EC8+S(c1!SKTT+B-6M0K[UKeHDT!!#q@88LJ[X"A+V6IGKA*VVP`SVa@-NGb
-"Z"L')Bqj,`c!,`Cf5h"qHP5qSYL+kMc49hU@IP*lH1QR$)B)S-9"-eGpB)E'dNm
-JTZ9"D9eC%3Q-Fi%2mPP[#&5l2B5+!q(aMZGkiCLI[+A2l&[3@lM%#1E9JN1&5q5
-TMpHld*("Nif$9G3%fR$8!)l+aS3D$$q!53H3!%QqRR&S![K9bq!ReFlk'#EjUMR
-Cj16#ihG+h3NChJj!33@`d2$%"&dqcb*")b3'LU9@#`F62&+L9@([-81+c3Q+c8L
-3!"(mA-+R&K(T"+XJMcb(5Tm!L5*Qfq"aM8m-YQQk4PMe95A"30YEpeIF3%,2`)C
-Z$(lQC'V*5Npqk+*G2k+5X1QcQ&iZ6`ISlU'KVNGB*8qXAME`aTAqlAl4#%@VAcb
-"$Mf+1VZfJS*6plrcJchKlV"#YhMQ5e%I0lJ#hImZSdiD%L`k9!+MUMhG06HkZ%L
-,S0*R$&@IZD(l&6C($k&UXD+UJENVCY,)&a4EQ&N&K4[-pX8Z)X%rV5dFR-lCj-(
-0p*Lb-QA`lGe2ZJVI'-"2YJ'4`5!QDieC33mk`X4jbc!UG1PPCjl"IkD(U*BUjQq
-@G9GVZZ#DS'G6995j'Bd3l3Z8CEZmCDG)rhJCYMA1C*,S-C%C#0"3,Z3')Ucb4T8
-e[RLV6&Bd`15k1`RdHcN*('aib&Be5-NJ*a@QLF2#Y8,*e))PCl8a!p1)f6VZfHj
-NRr9lq-'mJBZ+DYeMS9L[IF-S+mYC'3j'VN@(iqQacCDX%'3qDb[k%6"Z)1Y3@@(
-')kZ4P0eI4k!amfDkVBMHN!#hL1T+5@6Ip95*$Jb[aiFX"ZS!`f2X+B#c@)M(Nbj
--4-6lVhPMc9'$p*!!Q!QcDl-"hYGHJr%,RZJD&*p`*'Ui8#!@L[IaQLeQ`J$6l0I
-39&KJ'K3,Ecf+LK-,*94JeLf$m0S@$Hh`$Sb(fD$'Vk@1(Ei"FeJe$N9$cX@"3eL
-!US89*H,AYq,4FCU+Baiq++DcmQ8J!XY8#`IbNY3"Mr(qT+jV,4ZBrErM"RJL'1$
-*"`[%cE8XAV2B+#p99KL3!0b'@d!j2%fUV6!m1#K[r8e%U[eiX2PXfZ,r0X3!S"V
-UZLC92'X'@f#Hfh`A+b8jJ2*3Bq0UeiF&iQ-8j0Abp0@Gh'#2`(Kl0BZ[8,dMLZa
-RHS#0fAQiQDHl!NhMTj1k(B2r`C@4i6USiV'q!a#U#YGP$aiClH*L4*l+,M6cBC!
-!i--H)a%V)b+U*cF2hmXGRB[C16[(-m'+Xc!KCVXb*Jc)9aeLak!N$a!(UL,#Q-A
-(NlU`HJp0A'a$D'Z8'IQ61TNXJ38DRYNf96p3-4l'$+DN+5+'Bif%$(B$D*!!0F0
-($bVP%V+$S`eH%1GGcJIZGJR,*LjLN!!%1D&,F*q%QCN3-i&2@D#D3KR41ihF%5U
-5k*%!k)kY'S#-rFFTDkTFHKe%,MiJLJ3q4G%,,bB@e)cV!X035Rq[1!X[II%T[&c
-&*AJp@(`1489@X99fLP*)ZePHF,T(8H#"Le4qJCL13kH#AA9+FB!UI10FXI8PZ%8
-9Rf-e[,2"D(VKibBlAp(5GpGbL$cCpJ!$0KS&JX@GMRP3SGC@$-"N8j,0[pUBd$#
-8FMXQId+a-##6!BH2dR81&TI`85m9L+R&Ti)0I"`I05B@B#R3q(#IQ#SCL'$XPVL
-Nq(&jLr*9E-5-8k29cB,'d(qcf'kYlCL2P@em&pYp#1jVVcU"Gc"hBN)KD'9JB%S
--pcDG3pZ'8iCr+8ppb$NdN5k#`&Yd5Cr[lHI#p#(E3G@6$m)!+bfZ'VCGe@4a9D[
-&95AR%1`+fEU@kmT$fSC4KX89`jCA()f)Di@2M[Q"CQlHm*J1&8D8l2iLcZiVQc"
-CE-*+$RL,"R-Y$2%YN9d3+"296`MAiBU)!Ia8idGk')+r-0$V'P!aA)N"5MF048#
-*#fPj1L0Sr-c%crX2Xj%h%ldqaUY"6!@l+@%[e1RH')KP!KL08)I9&PpRG4KABNZ
-l3e*Y+M([6Yp,jMHbh5Se6$d2G9TYm3&@TehUhZ)Gb)Z%f0MF&Yp,VMF'D'!Y@,%
-3c0l)I!N[*!-%0B$K0r*"*S"K#3H!Z&PpL%'5!cp%[f)@0`$)286bLr6`G8`RpF8
-MpX*f8Abmd"rXB*@K%(Sm6*p%)$b+[IJ3ZYd`DVlp,YfVZBZ-l14NPP',M&CNe%4
-%MiM"Kr-q(a@EkC92T,f6Ji5-TRi`im9S5N&'HV"6Me-``L#a8B$+$`NB$a0kf-6
-!SrkYq0`cK03)5C!!J%82EF+V1`YA0"XCkF+!4IF*"83(1BYK(dDfTG8jZ&0dFek
-B46JBV$X$`,)2lV&9U5kch#l8dK$T#,LHBp9PaA1-mR'!ScXb%6%lf9kF34SRpY[
-c'r#6$hDM!3kHceiTV"bU$2(V+fPJ-Ni(ff`61`kj#VZcm,2C9GPGMCpl,9P[!5M
-Krm*'e'ZqcLqi%SIH6S(&Cbm8rXS50RXV'd1TmdJG(h4bpAH!arXlMm(SPIKCDI8
-f21kRZ@kF2pK3#c)3[NK(cXPESBM(80Mp$Y5CC*E9Xrc3rGh[C1l*h%0rqN$1,Q(
-5$TIf`e$8VRQ8!69qQ)[(-C83Zc`3D!fLQPY!V`%,&Bpff'Z%Z0p%CUShc-e-ChH
-Qr[BQ-[[S4aEjReiM"kFFIa@cq%`RCC&r#!6jaVXpkX[[`Q!k(Xm08c!`IU%@`AQ
-BcFr-B`HURj8@*ZA,'d0e(Q@B!VTi"bjH@iQVHNBr2#C2jZ%,Na'P!fq`FKdkM+*
-$$ffdYK)!i8PqQ)Y,5DCMh!(#AC&ckpKb@ApYpfBd6e-bhCr3TK1dk8jXqTLbk3l
-DG!HaN!"`L6[HXffl3lR@GP-ZNr+@%F2h@!`2GXJra@MihNQ$[jLJG1%lV[,JPHZ
-)T2)@MR"'Q6*")QfM6"D29YkZa`4`[`c!23I!+i%bEKJJIJU#'9LDKX*RMIL"@F4
-R-r&6!S-kbmCB!)&lfCqAmd36f)f"FB#ISGF-C'1!@l`[9Q1TJ$Ebi`6e%p3lCpd
-+8[cT!*A2ld#aEbJf@4J*+f8$$mj(c`1"R4mQeb)94e@N$%Aj@'*Q0-$96L3!H)-
-)K)Kq9XV9c"2lS&!S8pK3-DRfM9`8jkA9afX,hmM9P8ed55)(G4K5$PLKi&d2P3%
-BF,pE(04ajPj-Rq6FP-19IF'i+(h`'KX&iJ0Za@RBdJR$PV)4KZ8l4TfXX#42C`C
-BBKp(q5(`,l!C(("c,dbU)C)5Id5cY2r"+A!SFd6h`T`J'fB['ak#!CVe-%N,TXR
-[@!'UJbD,JF01@AJ%`Zr%)-jK)dpIcmjj(Sq*i)S)EN-@Z#JB&Pp*JkQP`Up!*+`
-F!M$Jd84TCiQaD5HR+cY2deC@mL19('jA959K&2Ae!NSF[UE4l1,AME@5@#m6)hD
-jLIimKH@ER@3&XcVf)ED%am'@Z9Q@Eq31cb-`Y`,-6mEmNXHB*1*im[HQK'Z@X(q
-2(r89KPR1'[c"'p)MI5)"0""5K[$r%5mB4YV)*&Kq!!aHqd3#N!$c'KadlKNJjdb
-2l+aViCcT4h@2+0a4NYd2A1RVhXP1Q0hES!TbG0r&b!6Ahci'SM+Sh$-p+ph#JB$
-%#QI`94kH"@(cRNr`Cf#FX(c%'KX"TZ0YcX+6,R!aCH+(ejJbKX['kS3$TMlajhJ
-J)bdpbCY2`+#X*'SHimHFKBQ"ZPfj%"5JPSpK3f%8MV83H&L*U-f+5`Q%`lr$aDf
-*KfJKKXL3!)diE2jGjBj3$dehGdLEaJA6#,(cQrU%l$K"(EN5[,!M!h`Uk!")DqA
-((GS%kE,EB4PYr*pc'@dS)V8@4YUQGaA1HPCKb#59S-qQQrL26E"c)"jE$C2NT8a
-@ed)jb&@F[f@%@mGjADQaa!PZrD[GJ)DJR1c[%aS%efXb`#dll`Bi01ETeU1jR%&
-dE&#Ba`#QcQ$0bUR[&$fid-BB9e"(iBHF9D@!V9pl`+BJ1339@c-(bkqqeYmM,J+
-&0-X6+XirZ"",'X[++%)!a*UlmepL30Z#$hhh#K6U'`qLH'&fXc-*AccY*3K+,jl
-Bj#'$L8PbS4XIrXrUDM,BaApbaRMbbF'fX5k0aa*8&51M-&P*ACJ&kZGT-6)kT+Y
-L%*pS-06CbA3YPJcb3cApcZbTK8(e0q9!J-5ELjqLi$L!B4UL8cNjMH@Ni*fV')q
-m-IL[8*8Bl5L4HV5k,E&6pUS[(Zc,d'f)$C!!DpmS6Am68lp(8b2bJM,%(p$`#M8
-i)!cm!HE&V`9$-"AQ0qS61"k2)#S5I-%fq9"-(qAT8-rPDFDA$Ni-N!$XAXb%#aE
-miZG`4hK%-pj45q4S5@5!4&CESjiD9CQJPN'Yb30RjL6F%2RaM@&E"blqZ)[J,NE
-PXBX+XI,*&$NEF+6+1JKLSfc)$K%09p*""%Ti9L#N59fb%q)@I,a2D,U0rY3GHHP
-kQ*9c3p)2kZTAqZP22XP(%UEBp#bZmGN`CrfhX(XBrDNX#MM%HVNj0Rcp%Plr'H4
-U39[Ck*,m4jPSaKZX0%f5VlCd(3-%1iM+3-8",KJD[$$'$cD!)@dZQ#"FcQCQmmb
-(H1KI92rU-rjXFY$LNe4"BjIYq"JPbq+Qm9VmNj[L$QSDN!#*X23F(AP8RXL%B'5
-*C(6)c&RAMcAM2rL0R%JbQCC'U)YG*Yl5&[kN`q[iBE"!"[Q-)Y1bT)jh[`rh(Ej
-bR#CFN!!(+0XZGbhE)9qKE)1mqE*mMBI98*Cr5SR6'*4Xq"G+-N,L6pr3f*bNCE1
-r6E*4V'ECqIPTXmB@")0LJRN`UZBB(A!UHC6r0qe@dAA,(iBD2$,K%D)c,eJmD*-
-HB!!`M6-#J"VhBk1,R9[PLRGeRS'mc!jN)([VHf(f!+BcCbCNShp!PHbJh"EX(HK
-!bD*pX+J[Rak#d)Y(A%eJUj1MF(+#!I"HYm,&,Dc95ki-cQ$+4JV&Qf0c#@ca"mJ
-`#adUXm9XDSR*2"L8rc`A2$4kXDk8rc`BrZ0Ji,kh1"r'VH%J@SE(0m2809GdI#D
-pq+(%#@c`2!&$+4P6LR,L$"E$DADFd4F!i`I&0IKX9$jAdDH%aa%AL$BT%fKHiLC
-AJ"YL)9I'JTlUd+L(#99mKBH2c5!MJSUBX(360T*0lY9I$(!5hi5,CFKi(LVH69b
-G#B!%BiG,0c(c5Ef#T'hM6fl1c[Q[I$JIJT9*"RUh)AK[a3r-Uk9YiJIPik18Jcb
-8GTYQRQIJFB(44jp1*)Sr&N0)*K&VBaG)F[CDe[h2$VMl`I&'",BTdeB319B%G8h
--j[J@)cFH2"MLiPFQ&8r!cr019!QRKHIGaTpD"8bi*A(dBSM1GV&VjR2mm)$35Il
-c@b)HHXJ$2j!!+Lj1XKh6MDKF2b%)S$LJLP%&iRd3f*(94dU8Pl-'qYQTI#BPf4!
-TBcK"m+MNj3[iMqHC@+L3!0&8IrIrJ%"`(GPN+-cjeH3BI)kb%6ph6Kc-4%DD2SA
-&2`!!-BP"4%05!`"B)Jp9$@C'%4!KiqjKrffrPUVdjZqk[VQHj['jVUYkUVCk3I0
-%GP)h"Zc+!VeZ*V1cb*r(e[+3!)lVQlQ&%-)9lHHA(A$+M)K1McJA$K0VN[%mkf3
-HYa"Hcm*kK("k!b1%j9Q(dB#"*YdNlh`c(Z[[hprrph8G),ql*1mP,cm!&AGH*2-
-J-L)5)I%!%5)'AhPG*Q-ar-LqCJ'NQ"c!*L')CV-(JC2-S[20R!1c&,&8JZr0qr1
-q#52iqmk#M2G`pECDKMbLd51Y3amCHVZK48lF$KFUBV(IrB)9$i+jGMADr*`4l'r
-h@haI,j*'%1&V@$'3!$VG3"D&JAKK))8c#+3,I1N**R'qR0U+J,#d[d@@iSMNQ$K
-F4Yka2ZGiShr!2`#`r@&r($qAeDh0F5L,bQK3@RaM-0(+iVm'I"EQ!l&N"+cJFTK
-`k@35*Qc#G2I$E""9ifAHl#RqDeZ%Lf9SP9)$-MJpFG4(,I%a,MkL'[&(2c,M3"S
-Y[YDM,QA4,b@h!L#Z%jG$)#S[5Y8d3Vr[c#R(PeXFh5Q'2B1c&p9G9m3$fZml-mS
-$RIS$fR6*8CIT%CIaF6+LbT-UD*qdb*i0(EjQGF,3E#fb'F&d-d$N%%((G3LakR`
-CBrj4Qm0[*)ZeU58Cp6rXD9CVUILMYU@lYJ%jEKQh`A#VM&"r&`##-#p$%1HMj5%
-5b%2'aX&Z,k$'M)!D@DbS3(m(PYUc23a'$(r+"[qKa90L"&8#+92@`D@PLaQ&*2"
-5K(&fK("@jrR#mUhGNd&1A5$mrLahGlrP#DHa(%U`eCPAHiaN@cY!iqA+)aH94k*
-B'YKlIc6Bhf@%("E!ZZGZKp5GMhkNDJAYqIZ65@@"Ab`iZmY)#PLI$,5'$C6$b%*
-1DM"$ZkfpXGehK8d@#85Y+,,VLqj)JfA"Cq5NfAD#LLNRl@dR#[RK(!F6fFLNa$5
-9Q#E&G(+j#d$#C!#AjV$$bU$*'!cfcqq6UVYPj#X)%Ph-b2#+dp1Ke1PBc*FdU,!
-",Cj!+UX($1R$aXEGV*TU[$PThAQLX14G[Y0L,"'`a[#@YY-#k+6ZSVbX!9+bmX8
-rDe&65br&k[aCP`6jk9l@[9$VeTUk@9K)h@MH1)SSE)KZjX8Q8XjV-J`$#MLkHD'
-CP5J(a36hXrM53F25SiX,ZFVd!K-&a"[%e%V6ZQf`IPD*Na&-cF4d3N`RT9jBkej
-8#UXUKf,k,+Y2*X0G*(Mab-1+i+@m6SANB`(jl+1Kh9r-aU(ZjI!m&m2V&R8E95,
-U8dG$[-%XNKld`+IL!EIjqc9)K*!!`,E0meDDcQfhB01Y,&iBAVH4cjNH,eq'J2'
-EFcNC&U$JP#CPf`RHQ(rH*`Vc)G@Ib8R$Nc45E4dXEM8Ni%)Zq%PF[!q9j1+H00'
-P@A@'HBT8%J6h$!`(B"+JPFd(8%&[QSP@!CBmZY$[FT8b+2+p*a)&A[8R+QCdKXS
-VA-a+SI+(-9'S(VdU&a19GSmZ[p%#SmIPTUkj!P)E,!4[B#U#BYLN#,N5e@r&%DK
-q)DpLF5(r5kZq2+hLP0EibNkPkS[T%,@H''#Bja9@&#J+L*+KjpS-EAIQ6TqINkC
-3[6[R!Z-Il@kRi)HCSAXC*"b8`+I+@%)+512ZiZr`D(iNfX3"@2Lk9f2QbENd&pm
-@j1,bRr2B,dAHHpL6Z46&6m@P)(jFkV@V+*KR0Nk'5+e!A,'[BG2fM&4lMhe9I9T
-jYI,B9j8VP&I'XDqqkPCHK@KVMcVZT$TiLlj`!`+TIj%aVk%09F1N["J+Xh0K#i2
-)jQ6TZ+faBlUdS1fqEd`"k,*Yl5cFbldEUaTl0eETld,eEk8TQ`mJ0*Mb+r1,%1(
-`4KBZ+h-#M(-%(Jq`@[@-U%9A@@MDC)$)%SXcKDVHj@dAT2VD`9k[Hd9jR6rBkkp
-Z8PjlMhN0#(EcJ[)b41c'SmaBT&IH&)Nq4m&9'*9Q9iZdcc`,!U)F6N)SCh)jb)j
-`NSi)R`'f!da-%2U"M`pKNQ9@1@9EBT!!hK1@lG"UH)N*k,d4e&0iJqi5P-jb&9c
-'ZqJ!p`&6S@-B8hhMNq&*1mMeZl,e9-2A(aFE5$K,V!$K0'(5GQ&k@+`94G'GFc$
-CCFBmZY'+l,Z5`hmE+K(QbL#%"R`PV3SK-625h`&J--SGbV#S5+M3Y"drjUr[389
-SEb%p2r@hBDX5r0NTF9h$56ERf8(#Zl3jZTi$qkA0N3maUIV$!55eB!k4-hmii,2
-6X9BkYY9SGdZmm+'6e3"3V6A1piiM`,B[b%K@U$L4CK+Gc'U1GiJ8"5H!(11r2A"
-EQ0Tra5&HmDSi!(-U,GE)`0Ld9T+CMC2*hBAaqG5cJKNkSU3HAQE'Z[,rhNHaXD,
-Sl[8L"$(-(q0cUN9bVV*b)66h8UaD(FF(NcrF$Xe9aYDTLhT4c"Dd&MBBFAKaFQp
-p+,pGcYR!S&C(mm&B+&q1@e8RZQ"PQKKHjb+f'-ZE10cJJVB3X59@+G)UraIr,r)
-rq#pkc(p"j6m0r`A`Rhj3eS)8NL@icl"XK[29`rK$d%+0`SSN@&!BY-D'r!q(&%1
-ZqBG$"cAN(CcDC82q,b`k'ENah+SNkHT51(blR+lJb3pM#p[qi4!HZ$L-BqBLUAB
-Tbq@d`C1rM5eB3jCB,#1,NmrAYl@(X-$*AD'ZGiU04PS!F@NA)kU,Em15EU2U6%U
-B#Gm'`Ci!0&GZ0E@3!'V4T()E8+fTPVq'TFAU&V5,)69j-FTTJYLk@&e&!#a-L!,
-DqmD!k)Cb1j[G)cCf([%iUA1YT-lPSXlPSmjeQ6UAP"G!lKV"f2mEEa1klIreRcI
-18rKG9d1TdIrI,j9d-bZ2['PDm+Ki*0&G[1+44cMerX,GKYJPP,@dlDQYUL4AN!$
-*j6#-C230p&K1V)DjXa0Kif+CS!)aUA$LDV0m!r'B9#Gi%Q(&MdP8&Mk6&["`%YD
-dYmL2fB%MHLmN'B+`JQa`JT*[K[R&8N6L@$im5BG(eDJM,Pl4NNMaah[Aqj*f!QE
-LH1dP"@kH3rV81TMb*6)44M#AZT6kfF0PIrQp*8lU8J@1fISA,XGL-USLmIL&2#B
-KGi3RFqr+k#)+F-1!akZNi`%qI"GK,C,jH-P-cTCcR+,qEPk'`1kC2Jll+SpJbVH
-#J0"fhQFfiia%3"Q-[FpN,m[TS$qmaD$a#K5+hBJ6l,%-,T`J2M&Ei5Dl8RK5R*4
-MYdjm2)$$rq#6d@SiX2`"j-aJmJD5CJH"5[*aUScZ"DRE-4PmrMk!'CYalaQ&4IJ
-R*Z)6Ba+ZR4X"rMmFaa&F&)!mpf`M*RFU%TEfXGJMA+"YjiSLT-6,1-$#NAr!RrH
-cpP3Hi48cY15d`Xi`fi)rQf'"1#aAj6-K*E41$BHL5iY#8-[hVLH(`I98i+08i0I
-)H1$S4ae-bVh8h@5NP6SI!!J!$HkX[IL2'TG!(ReCHfqqZ0Uf"),H0S1$'3+m'(h
-eFm5JhMIZI4IKq,#G`6N!H@&M"Kqd43BbFMKNJJlaCZf1I((%FV"$USBF8MAd%&Q
-LEd5qQ,k4iXL3!%2UKKa5Gm`KDr50b"[T'bQ1$MQNGXJKY8-18BIYJk39,r*`[G,
-i%"D*CfE4`XRQh@Yhh!H-Q5($K0[,H`K&h&(m4&8$KUI"3+a$6DIb1Ged@'3f)E+
-*[HXpeTQPJYc5[[@qmpl65l(UB6Yq+[[cLjE8'"X`3ZVhB$SPF#+p#G-SChG2r0Q
-(2kX"#qlMp"FcNE&pB0m1FCJ%X'81kQSIM'Sl6(NIEVErQ*0NF+p%Z&X2pQ%C`ZE
-9"VTVE-AZ0h[206%FD&16U9ZX`(cj-a*`h`Sea`UNPd192FbXpBf$A*8a#HZGiXl
-HGakIlHi8ZB1@B$-V0Z$SD9QjApRk034r4R(HGXlh'LkqST&IpqVGJ3q(+ep8la$
-8$F#!V84akpe!J4ZLU3'P-b5(JrZ@8(3DG3)%eepYjNk!)Qkp5JR6c3dM$`Bl(,U
-q*4d'%UPiVJ)!Vj1AC@'UllacbZ9AHh'jebG$KG$cpmR8V`pfjiN*lXiC#G$J*T6
-#IbFi$Kd!4IMCli+d!VDeim9*Aj)!V*0[R8DDpM354&h'I'2A`MIi*6VD'"DG3"%
-diFD,`MVKD-mJ13`JE"[IASbmqU8l1$)lR*@[EKSHcX['*@3N#(Thq9I''HChRFr
-1El2-GF2-p`"X1&'BFTh(cB(&#KNE"@bL0KF#cprRMFePXh,$`+bf'"`$40+!bbj
--k#rplUcdE69#+2"kF8R3e`&fEmTXh,d*K,U%#68"q18-'[-$Z(PaG+0D83KFL4c
-qNNK))%N(pm4#J$l8m3FSjM#$(lM-$Ha!FS+"LXPLb[lZKUi&Qe,!0Gcpi"$&&kL
-K4eTL,dVTk&U'V8l,@(C3C0AEG6L@PIAhmY9P4I+YHp8PSm'ai'8j-eCG4H69,!l
-DB-69YIK6``'@FIk4%XN+IF!lIZ5`0''L,K)3a!f$,QFbd+HEYQl%CAcMBM-[JAS
-IJ1LQ2,-J,SB("KmVAhUTZY*Y'Mrmihe`9iE*FC!!Jr![LFlR%N&FV"bJ!-1UV6R
-T+I!#GN9hrDREp'lRC8B)")%A@i@EC&9Uj!&-FBU&`q4KDj0)ID,DCk[h6!DHNC-
-%SLkrcNB)V'5XHLqE0UTC,N**``A!`'SIUbjMBM)9b@X!K,3YRHMm!iScfrMhcXE
-1ar*JlFIK3JQMpYJ*CSVi1#4-ZH2'Fl`j*!6(P8"DK$81)L!M4$Km4%EF4$`Z%ZQ
-i8Vb4#-S0K*rR2-A&(q1RU$K*(lZ+Pr0(eFe&APd&9[#R8PEAUBmR2N6T`dMLJdB
-ITK)I`[5K)[%K3KpbB`%e!j0ZU5j4ME'!1mSL9jXaMG!dP@-'l(GL'DVYVbjcG*X
-`%Pm48VaP"3H)r10'B%XRM-lekrY5+XTd"aGq`A6RbC3Y&1l1IpJa'@5QVkeM8U*
-T!94`fdQ!T2&6$8r0XTV059qc%HIdYT1C`adrCPHDl8IHJ"VY)MADI&RUc!EFDm+
-m%BpFYiNf*'8Y40(+bY'6T'hr$ETbZ3M4K9!Kl$)@pT6-DflV#iNe6@`$*,Ca%YY
-8'M[G5f,V)l(G*E%9Np!F*,5l*$5940DV1K,#1T83dd"#3#X6SXNQK&+!8,b+8(S
-53M%63JN*S6LTQceUJ`0lTK$SEpp`#ijphCj@JiV)Zh(,Aajr+GClr*ZQE(VM5$f
-+BGjTmAIj*P+hf"Pf@Kcc0rJNj9TMSm2#h4i0G,3V8R4PYC5KFe,H&lJ6#3J0US(
-CaE#MBm@Yfbp5S"1T,VNpS8!ZJ#Lq8Z0kJ#1X!2dd*R,#T4X11A"EBjAcI#F$d0M
-L@(A0kA1fFjD@kPUR*@U*eFCLZ+Pc@N"ZmMUji5fT9P)CmB0erk(!0,N3Nd-B+c8
-+$Za`JUpM*hM[GQDA&-8A4RGMiBk4F--NeKRe-KcPN9SJKh9b@Z!+[A3UFe@"i%D
--m`cZ*"j)#8C%GLU3!&h&83m!`T)ha@[P%1[",[,bI[dLR[Khm*Q+c[lVXl%U9"r
-%%+!U&l'G!DfA,Di("!!*J2#h"!HQT9C-)XIFjIa)5AL'[mhL5,Pdq"A-!!N,%02
-N[0J`B#[qD$9k6c89VUV4SSF)CKX%c$L)3P-M0$%T*HM-Y$%mpLA*F@dT"4dAkA@
-4(Lc&4K6BeS!b9Y2K+Ib-b8ba"5a-d565`a[AiY,E6M9mIX6e!!T!DVZJ8Zjb9kB
-IUmFe&P6R#KZhh0FCjS+*p'0f&JNN6ZJ#$"j`YPq-I0,0,LKbQq(bCb*VI0(q#ij
-ED*!!j&c92[dc%IJM`BB2D1lc%-#a46KA26ccYVMiBhd`69l-DQ!%651Zb99'dM1
-""b$!aeDkf%9rBHCYU,`4Q(8a2KESifdm-KTT`BGQqM#,iKRPK*U2652$bkYYh"e
-L)hIfbiHS3Fp$I3riTF'(C@6TUBCAcr,PBb0XkVajcaL1cFLH8`f,0[(+Hdhf'2q
-%"j!!DX*2mYGRC8ifibFV%Icam6rJQq32q!8H3JI62pZP$cpKHGB2SrG0*$DBF2'
-2IH[1rXJDN!"YG[3EF5H*E+qQQ`QkfCIKQqE[L`ILp2&!J@p+(k'25b9b&6kfd32
-&p!#Vra%LqpYj5QaZ16hJS`IfL)@4&X%Li)9AX,ad8k#E'Z@K$a9RSa(h6G&)LQl
-1dJhJrQLBa&SUQ*E'pJ8l'CXT)))q'!K5bNiXX[P0c`!BLYA-"U0ipKRaiRcE15C
-!"S$cf)'f#lLaRfVB[edK4M+bcl!c('[B35EHcc"4H[r(&m!@Ii[%Zjb2`jmf((Q
-0(3d4,Uc&iKjDl)ET,m1&Yq2#cX*mY*h""3D1!!lBH4+9RT3!*J63J)I,+4QdKii
-Z1p9`Z*6"A[6L,P)Ga9ae0*l`XY+k2F[`,iU-(CIf'DiX1`I9C#dJa0IJJ,6$(9G
-8T+Kk+cHU-ZcS0#[J"2&q8mH4*JiJP)SGGHQ508-Z28#'Jc5pCq@9b&@0&aLQY)"
-b544DBU&`JGjFK-A01IQpJGJb1Z#h2Jdh+P)1!"PLbcbpbUBQ5#(B!H+X10,%5FM
-BDLGA+IlM*UT8r%UNT2j`2EE+$mCj%YZ$4qU84kV%4iKE6%a&0CLiP&bhAe`F8ei
-diKp&edSK16$+AH[TY528YC5ZRS*3&lKl2Repj!&ZEJpfpDH[d+GCdG'I[JRfmPQ
-K0TjqEH3"%e485[@%LCcq9Qe@@"@UR,r**mMX6P*S59*%-&GX2m4++-dj+bZDeic
-[ELBhIb5k*SU-CHfc`d`b'lYmSk2ajlSDfUHM0pS,J5hh1Cb#!SL$Q!@Hlq3JllX
-S#0RTq%##('MAdKScQ)UEp!3h@10N!eLR#VI4B*QGbma[lbib9Z$BepZCf&-3NC'
-Gl,6ZXiTQCm3NXFX+8Y6Nk'%4$G(#D3f16+1)NVr1pKrFS`f%del5"U#+8hrr*DN
-pmSBaAf3diT*rr`B1#3qQ0kh@c+#$5*`53"22D%KF+Ha$E*JCGM5XBp8ekcrT'dD
-hUk+%bq-JAbBl-[hd$$p8N!#q`XcmMp!B38E`!f!-2qYN819dSmCGA(+U-eQ3!2j
-fRh9brYK,9A0LG)**S09kM)0!Z'+-NrbFCRAf)Z&N,rMGVBrBcL!je'rK"2eSF1p
-I8F%pKH+Z"32D@3MX[Xp!4$EHH(V"cNR,aY26+AUS&JmpTFiL"!`HrK)9[YPiqRD
-TXI&`24FjhbkB4N!j@MjhDqpIJ4312TlK`fEC$DP'@8+ITLI!20j#8iFD@U,aC5#
-dTh`bGJQ6@XqX%GLY#jA"ZVUSK9YrHC*4"A"@lfC$R#6h"RDR0@"jhH,XK8YR(CN
-%6+jJ-NQ1YY0LN`2iU)82S+BepVF!5IkZ2&C&a9@(#UGLAcHi)BK)jeHP-@i%iqI
-BN4pX(X6[4&&RLJ$RC'"X-SZ1-bCcP%k[B4FICJYC@#!!PA!iDhC($ZA[rQ3J-0i
-prK-81C0ldi%NMA$G)RHb5VeC%%'!V@#6*rlM-U$dfS,SYXQ#RJ3q3CIm'KXAXfL
-LBBI-kHcDUBEGebPY,RdU-lPJ[RZ-HHlBAV2a(*b&Q2bdJZ`!NZkr`"8pFT+f$fJ
-EA6kR'SDpep,BXF!%+YIE)R-)fQYl6kUk-eA5m3D$(!MC9r*@I!A96"aT2Yr*abS
-A6JeHH,DF'$EG@@!2QqXB#K-&QEZ-JX5$'8-8*UIQEk%Spp"RTm%165K1DR$-l(*
-iU85c-jQ&bQpQPCrZ'J43dUXA,c8(+,0+"Vkh+-Pf00kja`iJ0bj3)bf#qQ"Nf$J
-Re!Vjl,b!B1(X&',&0BS'm6iR16(C55#l%,,XZKK9P'NKTiZP)8l03%afRc[U@&3
-K8iK6pECa-f'P%F8H0#GPjALIhA"10@cCUC!!pFHj`abjJ)*!)L'69je82'CEGq1
-Yfd+0rd)GjimrE&+ea4rqTKZEV&)+[C8+c8`)2*836M[%MCH1*[&)BiY-6F[U(8-
-#P$T&M44QlLdb-cbDECm*BM*QYRm2B6*3aV#H4Q!(,Sm$P@hQK!J$C-2#F6E5eXj
-"Uq`Tj%f'm+0`I"1TeGmKL9rPadH2q2!S2T6JS5!%9CHGT`YDp"3)1C@@NXS`f9R
-,hdi0e1&NaZj9&CrkQKI4c&jkMI[qAXmP4A#2U`jf"MZ(VSVL6Tf4T9*e1FrhRPr
-jU4R(CIjGQ!-E`bHhf!3f@(b&a@lPS$ZHR$M)Nc*(CB3UEP'Y-i"PeEL5!,S2)d%
-$EVJIe[YlI38BS8PXKpdGAE633G5!6(4Da8dP1X3jU9iaIQl)Q)%bb9k@C&SVb1"
-c"UN2N!$p9T!!r9D$Qjr"PElB22)A-2Tk)`q'Ni'Y6@U5!XKkr0QNZ!eCS8!DXI8
-H928pE+f((!JdGaCE82(a(e%Sfe$il+VQa-([X`+MlU8djbI&e5-8&aKA(mM2M'k
-`bX!$jH5d-"EEK$reHY)Il-FrSJP,)iH%k(VfUkEL#$ZDJmX%3)ZDf(X!,lI$4A9
-2V"`1ZVYLCHbQ'b["bjGM0@#(NJSM*L09KYeKDE`e1i$MAmDIrILcLiFmq#@A,KP
-bk8@q0#UiR8M,bmhS6YDaf(XE00q%2`Jc1V!"Rc&C2A2(VhQX'c52I6MJZ#1D,S!
-pAIEGCA"@NM#P'Xm`rc4LZ5F$J$X5Uf%h+U!6Ed&"m'4X'jB+*eTD#YJ6S&[ChR&
-ZE+Xb8e[H#p!cDalm3EL)Pm'BYY2&[-V&A[CB$lDK'3'F,Z03KCZ1mL8J[P`KVMG
-"Ll1!&`F$ppMlNmY*#C86%`bJm[GRpG""-RYG"c@cA#JTGB$-cd6$KM,4)"-U`TP
-31#UreLm%CYJFV0UFl6HLL9qCEcmfe!SeC#8bBb48N!!"&@3)&45V!N(K-+S5cAY
-U(#F,pJfhTZ@k$iFSS[@k5jAaK'c0X2-+KcRVL95[SHkbU8KdPhC5MZh$l`UR3Ma
-3,aJP&02laT65A9BFT$XXSqiJJpq!8XNUAD*4PF%2UG&0bf9*,0"U"YlC[%ccLV4
-+a@8%3BQZpP#-p8,Pa9B8mR'S0b8"fL-DXK*m8b"SET4!Z9I82MVk%`KdYATh*JM
-9qJRqV&EpZTS-RP*8IKHk!NMCG+RZQK,FGX`V0[(9iN!eS9D$c2*riU%ZiHL#D&T
-qc`ECmTGRBbh#lC!!#dT4[6r"`k["HVA1(!F4Dp'*'%*J-&")A&`hi-!1TMH2elp
-3QJ2XJq1FqBJ0k9X0$4EfE4KBD)9$8+KaB0Sq#YJ'M34U$lA%eR0LS-%bf&JrGXJ
-[ICUrhrFcX-P`beR*a49Tb(Y#lQK$h[FD*hPJI%&+64fJMf#YBJHHjm6Y!CK"LVI
-#D5[aq8J,J3+fV%PU'bR%-p'X)$T,-2%frc83'bRhRG'BlH*Nmj8J8XeKE[c168h
-e)jd-UHiM"dY85EKBEV%mDQ1S&daI(SY#rc%5Dr1&AfQ&@iC0C6Ce'C`!IS*+lH3
-'Kh$A+eHh1DGkTeDf%URjH4UT%8N2*MEK9`*d`$D&R*c)-%6I"MA3"RIp8R89E6q
-!lFGjFfJqe()QLNl2-)60IpaAi+B#(MXqEH*2Ck,%a2ifYNC0dI3K6'8NTDL&M3Q
-P-+1$hP!$M9#F@9),0P),YP-0[qY6h&RA`,%G#T*!l3ZLBh!k8@E9diTkf*LQ(-4
-&Im%APDq6JYJSe!-,"FV"aL'rc)+*c'BY[cQ1#Za5&)5KQh'rjB88KFcmMJmUJEV
-i3"fPT)ASeRZS-`pPr-S`,)G9"fMiD1SFXT*6SQZ'0Tfh@NPeQ+3k8JVBpeQ!I6i
-#qciR3ZHIZKR#"$PUi(5QCi$#i`'#qel*"&9R392J2Yk`$[Jj&DE5#[D[hG("i"j
-#ead("rFL2RD5,BVBfMhK*)(8dMi)c[&3-Eb4Mc%!%!0r5'ip!AECC3Kh4bZT&6r
-"qaG&FPpZBP9ep9hjUH+5Pe)!EcX65Jabi54)#+`q'm!NNTcIc$#Kc("6J*Brbm+
-k[,+`k%qqM"RFIp1`F!`,ArQc,Ia+VE*3F6FP'$S0`-JF(-$3")"KYDB$')$#P+C
-H02M)++Q60Lj##0[1$TVM,mP`E!m)`q@-R`I@Z#`jC-i%qc[8-35mafp2C!,p(D2
-DFef1EJ5[28L'hPF5Sp('il20ZB#MLer[r5[peE+1k8q-`1&1GYI1cMFHAj!!`H[
-Fd4Z26mZJTF!+%iN!0*!!Q'#&#68KJcGCRG,J5kHJi-X94B@KBY3i+IYbGFcr")B
-4bl!DTN0VP50,P!2VP!2VF1!1p4!89MNU&GH2B[D),N+U-[Ukk,UkHrPZ#e6VGV#
-!&NUID&"pB"MQq+(J(XY+'Ef$0V["k!"DM`@8*N-i9!3pbND6rRk2M+lP$@*,e+"
--f9)9YV5Ah8FE"aDH`b3*XV(cQ)dT+MbU%&bSjI$3V89fdGD#Y$8E05B#!dc#U`4
-TX8'dCY[e3[kLc!Ah[M0%I+(qMTa@hZhSf[X1a"FkI$m"98"mR&,Reh[Id9me3(b
-&d"@0)3d#55$!b#'#55$!L+h2Em4[KX%qlm#fA)12-LbQ9'Q(8Vaa8BQT#[)B6+%
-U[+L9UK+PUU`H@XJ9`HKT'I2ImE&K*p%(l1SB9hB1eGY`"aZC`8ELMAH`N88K#N%
-qaD!Q@'$ehf+h(eldk2qq+$2q[LR9QQD-TaI#C$LRCm11EL2Hf,f`PhrJ'&$#30c
-0*+GI'#jA,r'(4)9#kHBbT%,#X6##kUa-E28i0pQPVD,)j$ZL1-4@pF@mBEGG321
-+5pfMkZ0`NQKc"cCB`#"S-"YZ`,XGkE8iTmV8#KiJ,"YR-'l1JV!RqL-iP'%5a#5
-)53!6$C-`*J&-2[i4Zj!!S5%&*KXC+-43,H*5j80$0(*BYbSTUK5D#fKJDV5FI@a
-qf5h2"&3ch,#-94MkkCE2ZD+E2J(D-cEaB&#qH)%"2aJXYTedacCB"SGZXUE"5@J
-md$$4`)#4NFqih1EhE9IJ'Q!bf&8&jV&Jj0GrKjPPT`X*DRqX8SFri&jh@53C#Rj
-eN4e&j3k#)KQ!21hLBEeDPD3aZ3HrfXQ$E,Mh(,%CB6aFldipBJ0T![RDbSrFi`(
-k8Kd33@"k"4a"Qr@%BI9Q2XaRCa8)dd!)Ka3e!&B-Ge@HIMXp$M&8&4c(Aj8A`0L
-piSl--9KIkad[5[hm)hF@!r)K(2'1pb%KbMG`&X4V)bKH'0dcHF1"C1d&ESL")Ep
-`f2T4)jA@Z++1#fZPD)JeF88D+5j3$2Ph"`eVeTjUq+0G$0l0"AKBU-2R8'8AX`N
-l1`Y,B1q6[XHK*T1qVj(5V()q!B)2+0f)$eKqE(&B`+C9Q3cY-#K6q3bR'b(SbAN
--3[HHF2r*"XCYKbfd94H(i'fGKIbcH&LQ%2lKZ29qKKNmiZBl5(K11(""Jcp"S5&
-YS3e@463&B+I-*eCLif212!r"KH-GqY'm@Br@MarDYTfU-!(@*L9Jhq6Q[JGT64B
-VGHJDA6J1KSJCE(Bc3DS!JE"%K3!N9km53,+[K`NY[4UMbMEMj9VaNU'jF&T$b-&
-"VKK85MmH0pDEF93`!rH85LjZ`maBe*j*[QLVFM55aGAMbQ8[+TI9Ab+a8Ce6AVi
-f5GY*[%4$K'T6H6Q$6J9"I+m[Fc8"G&CFFKHlZDYYC2F[%iqe8YSja!*#Gi&S-6K
-JRG4q`%RT-!'1#9G9N5"1VdbLL(ap$p)+TDr[35*&I0!LTS9FbE(%3Uk@NEMPLX4
-jqkdh#PH9E@-BYBf(A!m'#aTT+3D0`fJ5bJaK5QdQf-FeNhmk,kdc!(%if)8)2X2
-X5pm$[A'%Z@J)Nq2&JTNd`8cf`M`HChALCcA*5Qf9mQUPfrPhhX+iXGbAqXf$9eC
-%MEQViamKJFkT"5QI02U0CFcf)U%,9U[R58ScKihlQAj12I-J3Md[8Z+i8L6Tf4A
-Qdc8Bd"%-U'm'J8LYm4crrf9f$IRdMj8K(cre'eFRT6i!j+GhqAEQE4a@*3Bpj)9
-[MD2DfNb1@%'`PCY,qM"%SC(d#D$j4EAA5!T9`afNUA2U-LIcT2%GGXh`HkIJBT'
-#'J%,KdpS8L-D%%fLFBZlP5HF,#2h5k4Ef+%"BVRHakNaVZKT*-E!H#14VaRRehq
-H4DG80iHd@j!!#dqi&aLIF6h3%er#')VNXrFL(q,2$EGm0KrjmjPh)fYrL@#h#F&
-5bVZ8a!Y("0`8dH"0p@$[r8K22m3GI-[G[JF(%AXCLje*%EClV1$hR'S)Aq*'h8F
-*rK0Uf2l*hhNcidEUB-+2G"Lp*2be*2)6*(!-`'PpL34H*EVJPeFS`TiecZY$0AU
-h'lhr")&(eT!!`&&XArjD3Z"mkp-&rZ8`#E`'S(Q01rphAQr[jmIK+"!qHN0`%@G
-cl*f"H`'!d&ii%I5`U+TfdZ#LCGcJ@M%-+3pa'1c-Se0Gd98qQUSN6)5A4lk"#X'
-XV!Bj+*4jHqmGMVa(*S0E%+m80T12V$*-RXK$F,@Q&"*prQ$Q@@F[Nefi4+bD6)*
-N9@*jbq6(iXCGr(-EEL#bc@fF5#j)Q"8ZpU0D0L[I+"*[0b-Yk&TJf0)$eIm$Tk4
-[2a$0#J&6lZJ64JL5CNb4%9B*%IbSrZ"'5!T*`',,2A&R2a%cKf&b-j!!MCrcD%8
-2UGP6$D&C%0)8f!!(*mpHl64k"B(KKN3mq1IQ*f&drHXrciNUEJ62"UGIU#rY3X`
-!iD"iSCHGj&%GFD'eG+&A-*KX*AGAA!J9MA`$&h)FFb%E1R3r*E9$aNhCJk'%HrQ
-bQ4Hi,)1TNJCT)AFi5P#!f$qN3Z8%QQ!!JPPEaFcDi!#MVBNKYTL"#Ud@3pRk3X3
-Dl4*$d[)2ZU!9)UdM4SVKacTh6MKaC2VGelj[8iF(3hSmF!mEk-B!!a63-j0QQ)F
-&+e@VX&,A%fa8c9!fkNT%6@&SiQk2b@bGSi--3@hXQ0f[6kIc2+JV-8e0B*VQ&+D
-TC*!!68*('l`T-33$eU%`5dd*CURfB-`5&dB4#N2,-'Z%EX$$h2B)*Bl2'jM&9$j
-Vp(QG#-9MG9#4Q`"l`(c51Y[192HPXprk&`$dh8c+2'%eKHDA+IUC8%0&R2aU`6!
-%mUB9!M3"VJPia8*(2),A69P0BD1U"YNS02j-dU!+8m6XR#B@VISJ,&Uemcbl%)*
-4UrBd8i2&-0a[SCSL%d+jkk`BZTk6f#rH4T)C-,%4JiCD0R,#B3e$CVGlV+PfC)%
-I3NSij8RK11%L0qTkS"!#&)AG58i9+*aB&@kEZ8ZQ&68$5@$KSkYC$38AD$$ET+H
-BLK++IGfX+%L2bZ3kC9'+d+)8SCq+81-Lp!mm86'R+D`JP%YE8b(23I-ac+!e8@"
-T$+(Fc`aKkj!!)3Xi(1+ZM3&T6eCFa4EI36I&YT4!kh6EK8cH0BA"K&2XM1cqS`m
-F+kqkB`"DSC,Ir-ALeA%'[$ZI#EcjZ[l"0d*J&!qeB[*Jd38,GmD-%'mqmGJFP)T
-rF[l0#r`*3iP(hicKd`m+8UKkHLL1*JX3h8qV'&b$fQ-e&&Z@pfM2K0jm[H%d*S%
-hEk3GS!fQM(8A2rmE''3hM+@Mq21R#9E0j)%Hq)&[BcMAf$TFj-A#94!jGZGC"dD
-RqMFBTYBL*bZQVe`k1r-X(VU)2jIGX[lc'0b@h%JSZA!#DDQ,X3m"ZYbBi3%E2`Y
-RqC93'4H3!,UkM!6AFXqFG4i$YTchqJ'&Sd(#qM&q$!b0C@d+L4`dL2[9YFFABZ[
-Ka0SbIICf8@b0Mb&k'KVCJkl1JeQTcX4MCZ+a%$m'T`5k%)BB5KcUf8Q,3@$-#qj
-("90"fpa'$mqabffX&Bp[JcSc8#d3P`K-Bdk1Iq3"Zfb1k1T@$*1VUeZmQK&$#@2
-"#9,Q)5BRV'!63`Ac5hIL*4,EcXmN&[A4Ll!J0%FY@kQrrM8lpfPT#ifdKH'M&ND
-(,%blS#a*@jJkGU%m0'4KbTPS%NH[0`ejEDBGHb(Y@2Y4aeiDXY!qH#`2hEjm[I%
-CIK'P,UKr-M,iN!!BI)6*@3%TD2KmcKGK80aX2*@2`-R"jAHdEqLBVYh3-DXCbI6
-"4hKJD,#'la%cc1""-l'+M3K-mX3#[LZ+QiD#9Z#%m1+9Q$*XX4JqPD$jf'-mJ'a
-Nkfm%d`%@ae3krH,9Cc64aAP!F5B8!"e#9f*i["jNS)5'$m&3m-2,)PP",#Df#a*
-#!r(HP1B)'Mq#'DVbrR(IR`Sh&Zi-LJ+&bT`SJmU%dJPHHhX)#mSAj1f,Lk+,,M,
-VY1iNA%iaLC36ZbGH0EZca!M1mN&*mff['-EYKBk5Z`6lZHj-Rm+)"Um0(LGAZ9e
-%@&eJpe,%("Y[$`Q-MMV`K"K!&1`5+ZcY4m"aHZdBKTA[4e01+#pfKZ@$0,'efKI
-FfT`)JpB4HdrJL-YVFHGT+aS#PHAN`S2U4fXiX)9SEXcNe4`(*Xa%9ql5+b3[L'+
-5Vq'Sf!T@R(LBKbH'SM66JeCKGQi66@%Ub3@fXQ#U2848dJM)jJrk([5h%lPTpqe
-0$f,B#)R4l(GLN!"iU'Sr$`-[0[69%S)Kj#pjq21*Kjp-IjJCP0*&FQR'j90G)YJ
-XZ(MSprqFrYAX-aA5S[ac"!$""%PDHC9GTL*R"IY!JhKc+M8j+L"#r1-'&(C8RIV
-LNmYb9ih3fk@CF5%'AZV4"e`DSr!'KTNbK5(cJ9k6"pR!F"Y64LMGH&1CN3H&%dA
-1lhpNT1jDVP6D1M*jZ)jVlMiH9[ZZaGEKc'F!qlDGH$B[QLM4P2jT%*UD(*E5e%j
-!0%qYQ0TTfSUTPDB'TUddG@*Ud$5$UC1Q18`c0-eLQU2T0Nbc0&h%G"Y0+c"GT'N
-Hd`UD$Q#DTqNiTJ-dRF*dR+BZ6+GSfSZTLkCpQ2E5G!61Cpj-J*S,bAr9-S'"MQF
-(T)NrG[baiNmVrKK'B!Kj6T)BIF@r%Q*dINCKj+qc8H!I+lLJUaYGL9CI5JaTa-e
-%Z,XFQ&bZQdH3!*0-U3,B"$$PqJXB[eDErN)RkkX[69mKXVi@IpB`@HI3dP1-fcE
-HN!!lJZ(K[[M0CYi%[d,hlY)ArmZhE[rUk-@q@Gj506IiDd2hMS,NVSf&b$8J432
-L'QMU8H[qH+h+K0BhKim'%U(E$VE-(6[i-LMc)%,e$U5iLTajiFVrXCX-P#'50Uq
-Mf2Rc[iJc#$kSB'[TXDi4JJUU,Ab*kZYS%[F1-aI968Xd$'Ce&eqZQT2"cIpaY[T
-kE)3ZraUr4KLrJ%2VaD&Va`5Vb-2J`fNp35")`5"TVK-+TGKZR*(1AU8"GGeS(!-
-D,IDamfHPcQ#k,%3mTYBl"d0mN!!M#)Z9&CM,#e$U$+&Uf-a))6"9NHA468j[2HQ
-p*e3X&+,#NNFUa(!r[UMMP[+CeH4,Jjq4hNJD[3k%4(b*3@Cba@P2R#kB5L0b"d5
-K1-jb-99I)ZC+9ZpP9i+K+H+VeM%aC(0F$"Z#4'lciIXCqpD1`Me@PmC!MSF$DdB
-UKCf9-830TE21FZ$Kk1C('VUQbaUkCYNGZFIS9Re',`r`Xkc$YcLUZBhR,*`DG*X
-BXQl+#1T&T@bcNNN'#ZQ1e#J&G9*FY!$QkpRM8[X#,S1'V0bJ*FN!&)8j28BA&i0
-"EXrTDBDVj,6+AI25YGRL0!A,3#%FD'%J(c*CA1mA8&X"$!4F*$UQY3dGYm8$ERT
-J+#12I`CN8KPLA-XTLI,aa"%Q-3Q1V9r#b%([bYR'GMJ!qihJiFlLDfhRp1SU"mA
-"@Yf6XcVB'#SQmkr6e8"SJ6lm1am1JQEA#4T$DM"$&8(jp8bH!hJ+pPbMl*C8LF5
-AbB'R-3m)(L*Lb($QhQ2hC"KrN!#8H3c&"QH3!,!R3fj5E&JQ"RHUi$#0Nc[V0M1
-XNj'2BH"qQ&U(la3YQX#Lj&','0lP4CqN,CV!STiLmj'23%*)$6VU84JEqfmaBa'
-lH98-')N+"eC4Q2R[SVU"aK%Lp@pq,Rhi*$%iU5l)ra`Ub"*GN!$4'``9N!!J5a4
-"KY)&'Ee%$a`Mb1KV*%L!6Y&C)FMS91))Hd+3!*c35ZQ#I,@cf$a@N!$4CK*N5JF
-4Y3q'#P+lN4"NL3,&L*4@68+Bi9H&--fMK'Q('6Bjf35Q#Xrarf4U'3*q8dMFpN!
-ijN`H2h%5P(d1"Z!C(5USrlcdVlpL39@@TJR+$N(K(qULCFem,*E'$l+8c1+VC@P
-,QfQT4NZYbP,l88Y"$QRT"fP,VEa8(U+P2FV5jS-X[8e,h@P,HfKT%beY9CCDMc9
-),"AER8YEfSUPGfPKk3X[r*pdbFh9D3Y,XE!8F(U,q#G'%XBFeSfj@MGQ0U%Rdid
-j@NE'A$,8Q-8!*3@#kiaJBTK(!HeY93eK$S"dHVCE[Yd1Y[6Vf!)(35(ab0$"4ki
-Z-ZMhC#G",D2-'MpjA3Q6@X(X4Mh0!)4i!+U`Z3bDM+"e%0`mIjT"Q2cN+3+l@Yf
-'#&)m,*JJ"4dD(@IYSb"'RL3@[j,r-5eC$hMAlcSr&Vr-iGbm%XkG4c2f@p1ebfl
-jAS-MJVEKPXme'ZcYKS)2&!9helXX3cT-NE2h"e$`2'3L1bQicZFfU['CHh2YAlM
-(lS2-E0+4hG2lm9#RH'J1`CMM!U8I06&i#QeZ$F+BX-IN&006F33'!ra"$d8)d!R
-65k5V-*aF"4-*cbKh,F-&*f0lJQAA2jRTRr!c*9MjTe)S$%f"EDYd))%('F2,%)A
-*!!+C1ANUT!K"bMmR-8Mj)B!XFXb$!9r2`('&#YYbUU%f3d[Y[2#E!j`-%CHV(FA
-a$IqmNekRp-rrA%kI1d436SXXp1Q9Y%mc1+Ch509kKe4VLN&S,Q)DlN`N"j2L(f)
-#9#2KE1pIrpmi4+$K8hR4GbMP&MELBLJcKQ25i)8J`GE@CMc%Jld##"l$[bV"+6S
-FZRjdF%!fIV$iTlCca6h2er1!1G&cl,pbbGcbTJA$)NZ62k"j-9`INCB8,NZT3@#
-Frr%MEVL#MmG!jP&,-#CPXFRrh-R"AV19&2FFr4TG8I)rKmI0rQ)a0T+A[mkK2J1
-K'@8aQLC*VjDf0BKI@SmjKSG*6BQZ#fJ!#6*b-c(45!30J!QZQ)!jYb2Ga)dI5`B
-E!kF2``8!!#-E384$8J-!9q)293eQ4!)3)H,Z91r"58kmfLZjQ#[$k#Fj,aH#(%f
-Yie+UJ-DF*cfZB#RMZ[%8lNk-r2i@N!"5amfF!5eMhDiD0q0f-PNhQdN6'`aLaY"
-EkeVMC"a$l@QXieLEB4cUd&3003FPS[$hrhl[ppeh`1'Cp0PRRhPq!"eQ2L34%#m
-3!"!3!""4,j@*[fKU`KraSeFSN!$5B481A*FXl*'maYH8V$&P0li@53akdN3GL+E
---E2PNq8[P9Pl!Cbc)d@IcCmB%HfQ69D%%KXA4a*(HX!#39VJCaFkE"jBfEKVS%`
-%Tq`3CDrTE`C@0LfQJGZQaXh)P-kiD1Zq2BBLBUrZ*)9pq,3#dkC$#)GD4FIA)a3
-XkM6PI[BDN!!*)0m!`QikdABZ8[6&*"jS[eejIY+Pkm+2-@i+&Ef6CMDEkX4jG(!
-C6CSpF`b"@a3l3XpQMMehpCddeUP$kD4A1RNLL8JT1[@JNf&JAP[3j2j'%hYkSqc
-TG[ATh(I51Pi4RD3-kqehdL+*I@pc%HM#d(ZB-S-VkMhm6-HbaGS2a``&ADIMjd3
-Nm@#Hp8emBZ+I"HN$2e$LSRCF!U+dF6-'pQ$L88aXia2hi'Gh*0'qJclS%RT@qe%
-h3X(G1F)6@5Tek&c*TbDQ9V-VNqTmqrZEQKJka"CdH4TES*Y@aKBid-PTE)&MHJq
-b"@hL9EDJl9%4p)(iCE"iV,(JC,p`a50mXB38V*Y`UU9MqLJqD0JpTJ[ZKaUX0p4
-Mfb0,6iee!$PH9(NqDDJBImaGD62LE@Qdh6)SZbkdcc`ce)`#MB3@F`,mLCQb*bE
-FBp,41!2PX`@fpIY9l-M%VMpJ#,$dYbrXhqGEJLeiQ4K"NKHP*'Idp8AVdU0*bDL
-,&Lhk9NSdp42R@SM15pPTC`rQC'JCmNT,5dNqQaaG*2Cq!3reAV(f5N&Qh8RV-)k
-eap"L(0HZJ!QpK-43!-cTX`lcaABF-KK#&CKPTi%[YQ51D5($'H-CCbM1-D'%iSM
-pX0NYNB6Bj!DldT5B"qaI&1Xb#RlK[)dZA1P)l`CVVi36jCM*6B&fS'*ZcZ!LSM!
-i!XB9r-U8)rcBF%4dDb'JKK&LXY-"8T*6Fl*e@RT@0Mi2T#GRTICTfGSa,IGXhCQ
-8R"0489-TI1"JPLiRr8`d068V94Q+CZZ5,bTMNUSSk+Z%H@9U'cA#qD"Gd38RRcF
-l5)@aB5YFYD3FpeJ9UQT9,M%X3@@`@&J)m-#0dj&%3EC@+0h#(APer$)#3(Cma)f
-QZ9H&K435pdV2GAbGrLFe+5aUma!)&`F(RN5iI(HPF)"-RJjh"Q8UC8LrS39EFbb
-Y0&)Sb%2(X!i$l3$b*%$@&BL*`cT%S*4Rh34e`i#(2cmU(5aQd-De@P2Z,aBU`kD
-N)`+I@iPKiL0b&UTji2K-J+EFGcl&"+m"DS-3U+S'iU)TGdiT2Jj%LZDXCBSS$Ye
-qKeHMCV$11bG-Z6%62QlLLSM5jBrJF*)kSI-Xh[%"X0N'pP5(6FGCe"'2[Y680-p
-0$j1VH'"jB(&hbiY3R,$JM`-CINPP!B8"JY60d&)cUjdLi9@$dhS#b+6'@rR)8Q,
-lf0YJqd,1pK9!0%YXlqY9f&lUIUfC!T@A9T)l&-k))*Kre-LZNN6)I)S*K6dNN!"
-P%HY68(CC5%#3!$[dippp`GbPKH*#0+0Li8+Z(pFmA-Jpp3ZjYCHZN!!b*"lkKiI
-0R9C,apFjbp3Y)+!j4-q*fHLm1MlDm6iE@)m21YC"BJ%6&r*BUX)Ne&N,+5k,bfG
-6)(D5d2EeR8e+LQCRD%PC+9V@J@3YbkbPRXh@4Id@@F`kNf8q`fFT)T[N8l+,K,H
-EA$*I+lk@dB@P"kB,UN!h08VC598G-U)4!9#($'$*Q*-$()HDZ6&N,JpSNm'!"0#
-8M1AJl&S0F&DJCL`*bUH83HEJ!Q+,AVLjDI"$3`X2qG$L!AlG9QPK&"ZE-mFbZME
-8EQb1cS1LD4J&890Zi,Y1X60aXB-i0R0`ITmH3cLl(T9,3%lM@Kc4Y2%SB#6"6a[
-p2`'3!!QL3((,M($@$h+&JQ'GV0pfKkYSRC2efd+ULRMhDl8%$N'SYBlBL8!"B%S
-dMS`k&(96KPcZP*CF6(DcLIG310rY9M1MEC3rYF1C'@hpeCkk&fLH%NV'3)KQFX6
-,fqM!`KH8!dfM53@@9a4J#G,0JfQVV9hm%N&X6q+QJN`9B()488&RU*Nkk0V""Pi
-``48E!%T%3Dpd`1kK&IHZh59#9,TUf8I8,90)8k3Pchi$@1*ejd8A18XBEbV9qqh
-aTP)L0A6Yh+5LA[%hr"6!iSGmq%TBX(e`,`FEVRD`9kTYGEMQ9R(dI#ILSX,-0a&
-Z#5N&$&Xf6SdQ(6bE(Ud*1Cidk+Mr!EQi2$&#!Z$NC9DPr5CXPEE,cbTYP9p9QJ[
-LZ!EJ$3Bq*lF-,&qfQUUh&dh#5d"`%F,f$T5iC)X,bQ*3L"!Y8,$3f%FRqiL`Mh(
-fB@!IHTMkM$@9Q1SXb,i[AQ02698EQ+"U"Dbd"XbeQ`i1F(Q)LbL-!XVcXIecY*!
-!#JDam`amRL)'C#3dG4`N%SQ62!bB-aE)MHCQTIj%bmR@"P*6SYNjkFkS$SM#[RT
-'DfCT69*CUI)l5)8`221#d$2Jq@Rid,12+IBa34mG1US8Ijp2a!&9I[85#*YKG+C
-@)LG%d[&m9fjANMIIPA8"fp[P9*!!ckJS+$C0TU"e6JAj1Qd9&02`l&BB%'UkmD6
-MfrM&fk5,0mNZY[#,5c"KN!"GA)+I5TRL'f8ASq0R1qMLr-9#ba,LCR8eK!$+Xl,
-6I&rq"KLK`MT%f3je'G42rHM3QRZ-!6E,''!MUbi6RbN-%11&41G"0XN13Kd(*3B
-"!pa!*9G(+XeKCD,Xk)qeb`HcdMr3`T!!rMBCV%b,eZ@N*&-Y+*YEp96r@#iR1bG
-Cl*A*'Zr,R-dHJ0qRLI3h5#%"Mr8jFC)BD[5BH`c'FmF`F!c&arY3d+DM[ZlRK2C
-A5c#SiDF2"9ShLV1GND8M!PRF"a-UNE5rHqdhGk#3!2%0%H%NSpj8ep4%KNf01b&
--([UJd-5G1kaJ5X1VdE@pB`Bp&NNmPjNjKSTKplBCPm&%M9YN6,5@-Um462I9f9,
-Q0B)j'f-bjPcMc$cHN5U$VG,&YlGb3Y8S,DG+MF)ldL4#Y4M-di,M-l32K2jVcAB
-a@@ZZL"pLh4*'!E*!Y%mF%GiEDVGlGQQLia-JIrC4F(&6dq3Y6#cmbd003TSk1Kf
-(PKifm)G&d`3l'#NcSEejDN`eaI+e$9PZG,eT2pjlaI1PQ9p`I'hiUH!cUardrU(
-pMcVrFZX#E9(hLiDja[Ie$idq0h9la$VaUdGqIZIh*rrXb(rUqfhrYirY(acSf(I
-SN`[[QLk&V[Cm*c,QrZEij,P[jIdSmmr2rlp6rrIC-r'cPp-cSQEGaCc$(ac-cFj
-+qZqT+FN(dRjFpj-6Ih(d[lhpakklVpBfhl[jrCBrZIA6krrPKrrMfY,TcmriR`r
-mml6rqS0rrI$[h[[rmrr2TrrlihpmlHZ[[,Ai'fm8,AQRH'("V*IrBH2VqGp0r)G
-Yhp[mRcIpCYG(ZrrqXErCmGIE(klmhDTI"*DYH'(GccEmlGTr@r2,2Epqr*p+rqA
-qAl9qEZHrPhhjkDqXAllbdBU[E[NX9PliaC+AjMA-RY2B*-P"9KTUX!2C@XB"AX#
-f#6IXRDfGjMQM8Q$9%4S9Gm$30cMS5,5rl4j,%q5SpJPH$%TB%`TVNTK[5G8I&SD
-T'k&la,BS[UjYYp3*EqINc38JPaLV)p`d[KL9dDJBlcQ-Qbk%lTiD-hZid`C#-e(
-J(KX"8RZ6Sd1KZfE(lAFjS)Y4Kem0ZXF3)Vf4$`220&mmHl`@aNqZA2-*dBk(Y"Z
-6pf"XNRFD$hDiaicdi*!!l-&pcJFR!L"Tq,AQa@NLG0-XQUDFJ1fVmpN#bKMC,C(
-`5TLkB6j-HiiiLbX0J8ML$`JmVBK,iCD'9ULd$m!MU)3F1E&(4ITfkNiL2NV&0Jm
-##5H4"5FaR!r'AdX,#(NlZRE+*MZ3!&9!d84$PhX-drS`d)GT,f0D*EVEDF!*FVb
-LjQ!l$9TX"e12"qiDBBENX+31&0mPeijj0@9#DJSCe#BGhmJVV)fm`QVi9!CX&K1
-`DDL-**CINi"03b9qhT!!!C[&6Q$$1hSjX%%493hd15*,hehCd2VZ9bafr9984TQ
-b`hNM5bGG2pTd5$`c+1j`%f6Ra'"N+8*AC#SM(mB823@&,,*"E"(2'Q`[$U%`SCY
-"l!h%1)kh+C*iG$Tp%&Z-*0LKDIK$#J'[[NrCbLl!ie#MCUY'Sq#CAK3cmd$!L)l
-809p@V@lMkYS@5Dbrc05e$6mIbkV9(6*eSH0ARZEUiZc`d#Q'S-aqM#f)A9D`"GM
-01j-Y`)S2"LQ-$REP*PrC@FRD@E9+e"5`%Fe!M$)eHMChEm"MhrJq,IeL02f$P!1
-j@Qj15ZlCj25,[b8k2`R9EXECj,0D6SV'+Qmr5$J3bQXBkIh[B8R[-Mp*ljKIT2G
-m!-"+kj!!NBVi2*!!6N6iP3XJ)3Z)&1jZiD6f2Z&Jj,-p91XH-a1*YUS'DB4UmqR
-h6,N0,BcdJh(rPlDb6&aR5rSpED4-"!%@NmJZ4RD$N!$JC&HPl2,G#[RhG)H-r![
-)''52,IRhjHf8Z%!KZh(S)!q[Q&km#%YK$bdN)q%6dG3X,5X9T*MZE(*1@P5lI-"
-XMUCbUSSST3kqMQCFbNCf6R+1N!$(EU[-d%YMmYbY3B69FhGIAcfMTd2fkbR6$#d
-3$-VU&SQi2riT)qjlkb2ZZ6N`*qj486MZYk"+#'jdA4lZ2SbK`e$@d+FMF`q6f[4
-!8DGVc9B"P*d(ca"'CS,Z)%&2DZ)LlY&CrRDa##T"(HFK3aJf$h1$[jZd)2GB8P-
-m1)N&2BF+bq0`5#E5mL0fDLa)ikJ6XNXkC*GN)!&5-&'EBG5'VYfc8MM0`i[i0NI
-8L`F`KBl)3femJkPDmGfSjG14q%a8S,hGaiIA6VV-mlS(X!A22k2lfPTkV('$CXN
-%d@9aQRrR&JY*9)Zr&%j8LfIk*kV&lAk*kSlk40Aqb-$b&DBR)kSlBlDLHMbCLG-
-'@e(GHG4[8Ae-%G@Gdm+)DUQYU1l8j+)U&e&X*(MkSMV')@mpX[Vj%&Ejl8jTP3q
-ITVLZ-&8AekjErSNVa0("KE9CTpFXefUYa1Tf@hD(i$U3!05)Lkmmb-U2`CQRD3Q
-T'%PR,-i+["k4YA0aHa9(8B38$L%5fTS()qE8mi1PDhaD$hI-H'b24N4Er!Lj+(N
-R"'6LSpf(HFEl)C,bM8"iM%`-Iaj@$1ri+BD$ISPK"F5`K"*r'&RJf&KE*`aA1f#
-f(@V@RGFXX$!&4Be!EdQ5$b(H%L*i)%K&X9CHQ1XPJj(l,DqliPh5*cP1Z$J8a4l
-RA5b[5bEJ*IGGcQ[-#53DQbdXQEI'Qch0p%6ZG8kQJHb&fIG9FNTj[(*h`L+Sdf*
-4-j5l%`akLd9V+ff"kE[RdQrdEE1DfjS*h1SRHL`,QaFGXPMd#p3T50DQCfi*FJX
-CTL`@E,&EkmPXFIcKdUEZYS9hfql5G,UbHk*6c()Ca'5cqIj$(A54rSb-h4LiqN)
-a(F0dNBMrf0-3!8CNd#I-(!`-Z($4lp",iEmD$Ud,e0fJ6N,!*SJ#QeI('AAikF`
-a*&d+m8F53dXN`IT#+K1XqPeJMGBK#L8M'jUNJcle)DScRe+GSB,TT33$8Y9N9&8
-8JL$S1[((JD#k$9KqLT[k8()N'D[f-&Epml#XHYj29MAl`kS0QUhbCpk4+EpLB2N
-,JiVbAaMd@rNpe0fJ6P+92j-A,"J3N@G"Ejk8"9qUU#S,K&042#084Dk@-a%&mhN
-BAeS8FPF&lcLm8YC4PK($'f3CN!$+-Z#2`fD!bmm-Z1jA"Y3j9FFG%@$i&hBC@ZC
-bGkd@bKacEPp9m&DTNk3d`C9fDUaqP98$hKiCm'C+U0E&84fmmf1"&GB&phiXkL3
-GbpjFeE%@e(ci54a0FPZ['`c[YZD%)3I#Q1!CjF3KTNdKkEFH!BYlU)"NS4!pL&0
-b9HTkRfNq)XCV0pk,PZU(0)Xck3pRN@Q-4Iia,)ZmjLH,&2M&)MYNQF%FY,(cf(J
-"1A,GiE+LJ'9&8HcFhKL%%lT,&q8)Ll#Jf'r4MZ[DaTFUB!m'+if5S2J84r0pZ(Q
-(*1B!1*`A+5ShmQ5a$H6d+QrR!4H2,LP0J#!XP!DPlC8r-Ji&QbmJ10A"hHq%$$,
-N6(8)C#-5@4D9Yi8%N6QkQ8kh(9f04qpc%kBKR8HC&*YpLKNVm30T@ZM8Q('"6$P
-9Q,U8(r((e%A3NDDFM1AJM'A+I4e"KI+E4Zl!,'F',Z8R0VVFBaPHbBbJ2*N0CaZ
-3!"!Cj2Ba!,#CXU!iIl$m)VVemJQAqB5%k+jj!C&&j%6df'9(19,28I,S#&'Be@K
-$ibkV01KQ,PaDK!`Q-Tk!UeFMpflj)6+5`@''Z5QC)KEFN!"-!UAPa``YQEC',6!
-*SFTI3fEc5r,d!Q)&phlk56+YiFr`,HXd[X8U(KNRFi$YP)9D$bS&")h@M0+5Ah0
-G9Lei@0Ed1*1-%ZY,$'PN!P*qLV[RpH4SP`DkKkC6jR$(GrPlQC*C4%*Xi'6QP(0
-5KQE6TDKm'VP`q`A[2T-1)@FV8VkHJ4F+#F2!"1!a(Z((IQrT`jVp[UZdKIjIha*
-SDA8CLA4EMH0ke%H)000c`mHV5lGARl$d$3+hFU9E19JNa`V%eV'`%X6[YFb@c$p
-C@'NZe#lTce3h!YBc`)IM"3(fK#r'Ye9X&!Ni'#lh8P'i''CE'Fc!`,H(&mpDR3B
-'[Teb!i2baG6daiTl5"`iZ`!+Zj`R+@aTCEfEe4!1X(bZKB)"bcETlGSK8p)TN!#
-C&"6d28DAFM$FUhpq[$Ec1J"Zi5paQ,M`4@jM5P--`@ilQ3E$f9ma0Dce))P$6'q
-rheakRIjIIheY5fYc#+E"jVDM[QdJL$1kpYcFH22b2*MiG2'$I8`0Dc#(IC!!LMr
-DZkDN(Q&p%mAe![8!5'DKhILQ5cqBC%qiX,bT@3+eG1K&chX%#9#JfENmCl2-XeP
-QfLc2fba2f5bIP5hGY4Z[4kr(CmUIjGA25K6I,2Qe'3B05L3bAe)N+C%fdLp-5AB
-BJmmTipA+pd&J$9[Ij"ZIcN2M[$"JZ+Q%hG1Lh*J3EMbB8#EEfJ)m%9-!UiH$!5G
-6GVfSJ5(R14Q59jbE@FAjF0L+Xp,2LR1YAa9R@A95i@Ip9C-+AT98S+)-*R@M+,1
-93&UkGm%MC+iTFjX!B*dDLjE*#e5bcEDbcAiel'Dhq,RC4Vmf@k)Bqb'CVLF9lSM
-3UqRYf2+j3('R''G&X0jI#CpG&,mDh9Q0a*2!CU)mE@$jQJ3)KmAFP01"(hYi%S0
-hjF4HH8C9*)BTGf'[T)k&$iC6ad+[IqTBD2"((E1p-M)5&@P&XN*1QLjD-&"Z'&M
-q5lG8P,%iD1&ZB8Yl[3@D)p4TVYSCRhDTm%,Aa@C,K&EjaUS,,dkLeq*a-Y)#Y4K
-5i9)IPX*h3lE(MZd-eA*!0Xc#*G+dSe+P*&2h"&2hYm1UqjLIkJljTHj-HKLUZH8
---+)+"d%9LcZh3!'XmQh5SF@jHY9mKbiaY(!L)-5R*0idUdXNM9RKV9V&dP9)m(#
-B6hilFfbr`!+9lCD5L38U`X`3-(IEdMLK9ZH0+a8b!NJkrLdNX49XJ@)NM!r3#!D
-+q1,6%954D2S%VRB3Qe[@R9a`ENb(-'IM5PQBmlaL5V!-C2kFDIZ(Q$%"R+%[HVN
-j()8kcpQD%bbMC$eEpimdcT-1fl@G"lr)j,4A)6c5cfD64bS,KUDD1HFJ$feH`!G
--`$"f'N(-lja0Y`eU3JQ2Rki5S)!YD+U(,kcpqr'Ip!H)p5FAF,@8bY55VkJPm+'
-0@T!!K,ql69A,4PZe",J"%#9NB@S[P061Vhqma[8)'3H1UGHAF)1)a++2eHYIPPf
-2cVrBaC4H+#Rp"T%dL6R&p5Jp(I(Ej'JeY8ZM6d6aiE2dL9p1KJZb6-8',5Gj!$&
-C%3K,(JN%9,VQj!)fT!rYbq3X6FEFURTl&+I!UP*&[6`SLB34fJ99[4&Eam#U$&)
-[Udime49k-#Z&YNYqd'Sl*p36h2KkCH0)aZP!X(48H+lK)%C"cAXFj-Pa36c1cNT
-69$(8`d%$ZFTjN@G,+CM-lGRAp'pF'HYPbR!V6ScIV9193@k-PC(%JMj9'BGX(4Q
-rbb4P8%"h'3j#(iT#N!$2'4)PjY3"$Akq9-#$N!!`QqGKb+153T4YYq99frC15E4
-X0MbZE,LbYIU'YiE#EEMbSRc$h0@JXX#28h-J5Y+HT3hcS5Hfi5eUCC2`ZEP4qJA
-1S28BCeCfbKaE-&CCq5&c2KfcCH#(2qDEN!!D5[,)6I0X1AE[jRR9MmXVkca@@DH
-(VD`cr+bXNrbUV1Z8S)qf4+UDDe6$-m16b"T[2UVi@Kk-5Q3%4`ZUp'&L)PDpVjC
-23,0HEFV!"*RkE1,2Zf3A($APcSk6Qd+kV1PC0cXq"Ui6%LC8Z3[4G&h6)4RU3fN
-D!X'j#emK"j%-q3C$YQ'"aLHD2!S5UTKJUQKaETYI8qHMX(+E3Jb,632,pdbaT",
-"qNPJkX##X)rYK36HaM,kVm0Qp(Br-hU$AaNpcBDmpr*N6caj"SL+!)iqR39c[EC
-*3DTYF,Ub`6HEpl,"qfb$MiEGB)@I'jcYe`CI83p,"UCf-X['"i*mc'RC*KYZJpY
-"!JbG+2DAm54T%XULSSi!Y8U'XUZSFd#p,%-j9&358$rJE#DK0"9e(5LA$$@SSX#
-UM@D*i6M+TD+3!)LdXBH,Q!m0XjBbph`VFl58d3F8-,qHV%*V05UC60IdU8YkENT
-GdV'fUNXk[N0GdMEEe#A8-5HQ,U'f16Yj-)i)Scf-#*qSedQfKEQ%4d@CfB)U[e9
-eqAM*jH-KjeM[CH%c6[bfV5[5J#5i'PScb"5Aa9(aJ#J@P@)R8[1Z6QT#JjDP#!3
-GQNY0-D,49AkPm0hKLF1fN`'[6mq4E5V5bj&,10+6j'0AY+'Dkh3HiTb,%0`!Z!b
-S)l,M19'VJ$VR4,QGU*H"5R+L8Kf"ZbTb'T!!ef9)688H"HS9'@T349d'DVF6e88
-+8TkVARNG8bU[[ir,$1GPaXR#E9YjlDE!d&BTFj4U+q8RZCHc$SDam2l1Z3[IbFU
-)(ZcVddAp-24f"Pij%03iBHP"d+U9XPiE3Z+d89%U$jJ5'iI!eXr+Ua"Q&X!c[6A
-0p``e59`'!i&5lX,fQE[Je'q01rLbc@cAKJ)Z%"5Y'lM4cCcVcUjiISI86EHT!d`
-"-i4@@`-M4Ji"BDDUE,%S9CTAY!RVjKEB*B"@m%`iJ&D`fMq!9Y$Y&d$E9#0TVTm
-9-LTbab,ZPMZGUDT"er#N+pAh,fr0(C!!3Mi`B"l@,*20-+VSP*PM)&!4U0hJNP!
-JUeVR`S")VPUCkNDBkRiE9RApIUV1j*IUbRLL),jT9&Pl&#FPrJ5T)9dbEk'%2'M
-Hc[1j&UYJL6F8`k3e0BKF#-iZ%5EK6Ya@`(l6SL6F8F%F919dMpB`%MS2#k@ae)a
-S+K-cfi(6-3cD+Qf@'3C0Skc1V-,&4iempZJ"A"bSA$a`mYQlbE(UQlb,V2CdPk%
-i`KIQQ00K4Z%Fl5(K#E`P(#pLQJCA$DPaS!)"l)H%BpNe3KHr*B,T)ae[JE4(Kqk
-(e'[EYDI3('D,dF8[q9GqKI6)6UG,MBHk2+(DA&i0ERa&@(*9JC3ae6R'9'I$-Y9
-P2jNUfaqQQQ153PUrlR@'Y1Tc2IqkYkU!XZSq6h603qFH)LE$1Fi*cBbl@UXLY6K
-j8e5qMK%0j%ED)6pHZ)A6qDP@kc4j&k[@LmTA9@Rk8N,'&P5SB`IBkDC'R%YBSC'
-'eUMCTCKP&*8hUNd%F%+0KU@3!%*K(f[DQaBMlM'fK2P6SCi+RK++RQ&,3PQi-pL
-V-h'R-`ee)J-G6X(M#5h+'0+aPiXkcIPUiJ4Xrj5D-FTa&4@cBciV1h+QcC((C8q
-9f$`e@12)298FqF*H,V)pmLlCNGH6FeYaAI#N'q6JAFm[UC!!M-E+U4(epB3S[+0
-H(Q1)%QP4f-X1,-4L0Y5YZ4HZ!-!r`4+ac@C6k&LVfG6CkY5JESS0+"-l`hEfQ0I
-aa!G5iqJaFS1f25Bl6)Cd'20@0V#kaN%p5'abAYjNKk+'d20%%V0V&8A%C)USN!!
-TSN+f,GXMHRA8E0TXG3XmdE6T!`U&&KkZfGfmSZ0j`pA-@h0$F,RGUZpJr0QMNf5
-Z*ahK935L+Ta*Zd9QM@6fFFAe+LADCXqR`@`!eGYF0i%AAZ4"+,X`DIaj[L$"TJB
-H0H83"j%@m22Yp+2QC)AUB$EPrMSZ0F"3Q'mk5#jVb3&3@'!-CIldI66dBI`T9DA
-NpLjmJbYqMj3KKDm4Dj2C-*NAm`lcHBHe6,f[)9(,9VEiJH+8,jc"KRl)c%'8c'L
-K"1rQ3*`A"HDXYdRX,4N3Kf6r6%+MNMAB`#PHm+GXbAFfRb"i8%'lbVDcfCR"fP8
-T,'!m8bqiCFBQe-3&6qV2'CSD)+%KPNQPf&UF-Y,UB&Qi@cC"BLZ(MPb5$MBS-H%
-9+4aIH(KbHSd*AR2!pJRj%9(pR@!9kII$9U3YIPDN-rbU5*0B4CUfPiSdcEq+G&I
-E`2,(KbR*-SM9[$$9kDM5#F44RM2jmNGG94P00ke4%K$`*M!XI-U889$LB#3$2UT
-F4XBY@GNRI&mZiN6P$4P*Q8I,$Djk#-Z3!%*B[[j+'-)bdjD`I(e#)5cTRh4!iMZ
-@T#"F)Yd,Ce15Rda#ADNa30Tf'LAAQ1SSlPFq,1c$cMiml-2"2S,X`mXq1YfeRPT
-ZF,`aMCZm`SbLNXM&ElTimqhfiLA8p,)S`!3pA%K)lNT6aiXp3Khbe4KUUc%d9'2
-)8Q2S4SfKVKT$EbT$-,j!mfp4dA3a(Uaj1,MjFI$S6Ja-G&a,me(6`++ND6e-b#D
-SNrEcrYQ"i[lClk2TEldbH+GIB&!mj1UhS($+"lX2DErUY`4)XBF@ZIVYS`VL%b$
-X!9,d*d"iTK6%"5!m!9,m"5!F)`VLA5!F!FU)Gi%)`NaQ!Ui03S&eJ!`'+(-Z!HR
-Pb"+',!(5'k!-)f3RhrEkA$4('pr+1mCBaaJkmLhaMP!!bpBe,&ZRR%V5NjSQB*+
-IechK%5r@G[+"mH)H4@hV-*!!Tj(a%6UF3&0hr!Sh$#ST-@N(%T0f5iP$Bp19"+I
-P+ja*4Q0Na$*-$fShaZrK)F06a8H3!%k"VM91i($0qI4--5@D9j+9FM!hRi'jSV"
-JESQIB#lK&jLlCJZQ[RF+)'LA(f"U9dd`Y6PqZQ"UmmfpJkQ!5`kQ!UkU`G5X0[r
-!9-'Yd`06N`HcI[aN`&4$krmD-0A3qKmhQ'TS26d`e9$fT`&-0C5G(TK#FZJ+8S4
-4BT1*pj2`lm&Bf+HG*eLN6`p2fNHI$Z&JRd'H`*!!2Vh#bcil4HHlAi&i+8pmc"M
-R%FS'DV5"NRVVdB4$3i89B)ih(eD%IhF(!dj35-!LZSShQQEK(3*'N!#$V(0JP!`
-Lf86pN!$a"X#DJmK,mq-dj5JPM)Cja+2CdY-`Dc@aj2J%3LRTr(S#""A6F#8bJ$f
-aR9r,(`#JlKUrL3-EU&N*p8M"+#Y3mZZ0@THcZ3J'5"pMJ25&X)"dRCq!Y03[3*T
-Idb4Y@GI!mRp+0V6mAQUf,U`a'R@53'LJT-S!#L20CFf@V6D1Fb0b0"6('jZ509a
-@Z%GUq'hC5Z'a*DDPDp"F($YS`EB&5T)5H90a5fcGKl`4258*R%Gh3QNk%QDdlDc
-TVeTH21308ZfeH&KRfr#AAY"'b)M8bXf9#r3,*$-bGL6@I"9[RT-+3TE`cGF"3Km
-iQ%aTdMA@'+@XpFNReQK8`AV'9Lq&CDYjrV(9V+kUf5TdHpD$CJFk8PEH*m5X"c2
-(',-&!#)Ih(GSAmiRha[ifF"(!pmDh$6`YAdI$UB0IRr`pAdE"Zm0CJdQG9`Fr,Z
-"dAdIGk4dI$a`8V$r!*!$+aY"4%05!`"TZa"9#f5C!&PYNqr@ET4DPQB-deZ'[)a
-DkTcEN!$&')l!fdfPeV'9EXK#5&UhYGedep1cke-)Ke9h23b[Mmej$"J1-BD)'03
-&G8iLdSJh%I%(`aJ3BN!%3BKkHh*c2$YLl22prqrEkpZQQd$1ZArh04e@0L32%4!
-3!"!3!"!3)HlIe5Y4M`Gr&088FU5%&GQP)Yq%Lpa5T@cDaeaN%2ice%ZZ'4-CTXf
-5B#)f+F5%8G(bk(!3cX'Ep2@(&'GpE2"1-5'Pc6d+"-3dmh3eF-)FFrHTG,GFmRM
-UE5NV2*klTV'EraLQ3Bi@-QEjKr+N1-I#qKV&Pl*#86kM@krTeXPZh4!0K0Ud'-)
-ZcL3T6R3$-$`!rShGATCMYhpeqZVdR,*pT@RTp[`MkGUpf9bmV+qI@aqMSq`#%b8
-b@+0FlCkJf'3ReUf#F[T2chZ(i,!GTe5'mq#feZ&@2"MRDBdH9Xam19F`+TU6iP3
-#3S@YdFb9*q[*a8D(DS03hHT'Tk@*%+RUKI9QpK++26X3aiqjhRV-A6X9d4'ME36
-qmE!E5fRbEU8YVp0BeSNI-hjXq2(LTamr2[`d4Ha"1ahejG+-dJU1'X"CCFHQb9d
-MKRlb0pA01L"*Y!&P*c401MMFP8B*(38-[$*#)Xfl$LK1a8P)&HHUKN,0(-"F)9`
-Vl2BMkDCe'q`KVDBR,6FM4eX@b%Q9[Mrd*lZp1+h`5,(@ATSCYMmNMlrkY$fK0%1
-&led0Y1m0p6aH[#A!e-IU,Hk$8jr9T)3YKi5Tjm+0q(-jH($UZ4"8ZGF&aca(G#4
-kb$heT1KZQ(l0q-(T8lX[,TRD(FeFlSXqTbK(MNR+Ph8h%$D94)dA6*GVh*cTH-j
-d(*L1$ih@@i`B6K$GhZRA2!Q'Nm"`%KK'L1%[9[XaA%i-JlG(#0(r"YpR!d1SYm&
-pF1ecQXTSjYTLQ[EFF$6c-ATmJC4-0bf!65iVQlA286A"P,rb+9qDTMb2abd96[N
-VQe*b+ddT-CZQV-IMfBUQP0`U65RN8il6P-1V'&NPC66PcfmC6#Q8TRc$TcaVQJ+
-b5[396[Q'69Pj0deCf@+D!V*@0P8dCHAGI$2Zi2+'d26P$@iAYR`l,bjCANHJiQS
-ISfR[EX((T`JBeSpR+bmZ@41MirTrA,lCm+-DNcXcPpIG%9AUf-1D'$f)Z&(2aTC
-#G$X*F3YLG898JZikPc4P-`h$-J%#NC9Prf*m(%0!X(im-rlLNV9"1UEracAc$$q
-U-4NN""Jjp,!fb-KC'qb+($jP(Jd$Z!,NE)F6d8b9r%fl[C!!4-[9IU+PEJF%cYj
-X8c8bG3Q,%`"QK%+cS-j2FB%b*3S`b,I,0l0E%[piV"1rl5aAc*fP%+JGdXHRq%H
-RmFFeXD)IPfmfrSK"BqMih`FSe`EPfcAcf+h%*P"dZ69MLV*H'kb!K(R'(`'N+(8
-prYd1Vk)%X,+U!3a#2U*aGQaaE(IA+#1UX`b"0A9Z*5Q1[cL&6QN%iTKh)Bj(h0J
-J90',2)MqL,bJDepKF9UkeL6lrS$e5J[YQY*LEAkZaVjIPS&eKH9(8ZdjU8G+Fp,
-afFkk35B##H'4FL@b"ZiP93XMj%Jq@c$XBCY3dR*r6RmZSh#X9Z[Uk0I,4lplJpr
-4Vhq&4bqXN!#D`XIRk*0GM3FcpE4&K1@Lj8U6RaPJC1c`KD+PQIQjTQ292F4@5Xp
-*e4l*R$b8jHjb1q[X8,h6d*ARZUj0eqE3e,(J'GKIV($c,pIe"f-!e)C*YXcLq[6
-bY2fC4c+H'eXq5"la%+2FM$*YUUBiEIpB-J*#&P)A5SlJqVQSfJ&8E&e+"`+PK6E
-"ii%DjQh(BSjBj)"LM[mT0RAD'bbb5(6GR2X+&TF2%Fir8RK!Fk5dH'`Bl6FaZMB
-YHqaKXIr99XkZkm&B+fIA2!1&aE94VFR@dA"9&@XLBS8fh)SU&Y[bSUdk%R$C(SH
-0&#X%aF,f9,YBGG@U`L'US&KGXbQ9$m'#2,kPIP6aG6b#6C)SY[(-@A!5&1HTPhU
-f1TcUTGMfpDC9)M6Slp`TMSM19$&VYpBjUGV4JSh#@1H,l3X5A*V&RHSE%E,FZ2N
-P6%D)j8hEHlB*E2YrmSML+fZRfa!'"+2H8B$MAFIC&j3cP[V%qTJ%`(dT(8%P%"I
-fP,K8YJ3`#284Qi`[4DFFk,QZ2j`HcXh*'#XekL%pBXIf'4rEKQ1E*hYXFqF)dR#
-k2[CQ(0aX1VB!TQBFfPE@3T0aD$-rX0Gde%SkDK)lDRY`*(6Kl+M4JIAm`$ce`(A
-YiA59GL`2c+X0UKr5+j!!JML09d1B+0S$iE6dXH()A[aC3r0,$3fII@PKE8CQ@TQ
-fk+)(D0%dc9M9r@+$GIj-c-T+8bHcI&H+,CVR$G1rTF1p`l0F9&8V3(H%P"a*F6C
-XAd*!UU$X[DkJmMBTpJH%BKk@%*S(YeZ9fdZhm9bj'dDh[q[S[pPbLjpLEeFqMl2
-eH$aqLVfk0SSpQDklCrpN&,[+acEMf(2*0@!ppShkQb6&0KhlHT0bffJ5$QhHEU$
-Dfk(Dr,"3lIJ,fie9He0Y9(YLaNUY9EYVMSqIDRHpk0LTGLYh#!$"UNlUb!2$5F1
-8H0Xj6)J2R%XkaaaekLAcb[QI!,e'Z'HQ"p2`VcU(Z8(-2h9X3+,[cI5"MX9H`&#
-3!)aNC5Y-m6UB#+hX3mB#HZ$"hF["+2)V49-(f*65F9EKB43IJX&MEZe4pK&,fP`
-`GAlP8U6TCf#A-U"06U$9@Rc8$Q6hAHCrXUdJZbrle35CS[bKaJ"N[,ViJqa2Y3E
-CC#T+VGA5!'5R'-L-!@DJB*XNF$RTS5*`@B(eIk&@DBqA@[f50M4dT!*)6i-`A43
-DeTN([A3E2`aRm3@iMpH,#8%[8Y*dbQP0qF&bTFlc&2pc`SfY1P8l0JbH3P)#*5Y
-`j`9F#`Q9AR%[Ra$M+Ef,()TbeF'pRJRLhR[,PG1H(i548YCHlIR"(YHpDXmE520
-m!``Q%)1M@cq2`r!XE"f0%h[im%R5m%Pmq'8-[icKiib'la%6a!"F4DHVcIF'2&I
-ZcI"Fm6b*G*XR+FRCV@M1LKrMaBr#MCc4MrDi$RlXbI$Z&K-1"V#P'q$,A-#d#jj
-Ri!DIJ`pAHkCK1k6Dm`bI-Qf6#aX4hX&Rk"m2-F,8P3#9"FcpMHfG98UM'!r!4$`
-[m$r$!-m`dZCr#G$q0m"i2`$eJQF0T@CB93)G@4mhY2YJD-GcB2fhBd5-Tm28Q-@
-,)(Zm42CiN!"pdC-+XZ-jJFY"hR*+`8-+GN@Np8U1H5`20pH#52bp4h(-+4+l+AY
-FYkU9dpbaFBDrHTQrH(Q25h66mM!NIqRGM9GAHplL!hl-!I)@(rCM$K!!(SU56bD
-RHXQlHl!C[,86P@RG8RC,'`T*`l5"(Xfm2ir3pI2H%"`9NSZk$EFm2CdH&hYT%([
-%`%e*h#@+fh%!feE2'(+E(RJ,!q"N[&md(E6TB))RQk0aYS6'Pd$N5kQ*qYe)i4R
-&i8Fe05"NpVAP5S2RG@ca[6l%RBMBe'SAMf%VM9*TXNf+1b*[8,RfDBTcdmZlUSF
-6#pDV*(SN3Eh8+RVZ@rV+4FqV,Cl6(NIac0+JXaYY&U84,YLq(8XpV8NAS&5YT&3
-)15YCi3iL2(T!dCR-Xrk8$Kr5*+'5&KbK(f&-Hi*,eB+I[!5Hm)NYXHdA`3M*kc!
-3bcUaY4IaRSQkSRT52lMS6S4Ff1ULVE-@T(pXe9j&4+Mk+$9H-ZaZcXe),br9j)b
-PZmk648T!+#GR4I5SJD-LbqUSX#)aHCi*L6P!HU89DE6TL+1fmmRcV*0K[&EkGc&
-*E)%YeN(SCQia)AQ[Rd1NkSFUiJjK@kZR1!Ta6"ZP*ETrUN48hV#2K)6L#cD5Q0$
-B`Tk)LlB%)DM(ki"8&(jJ"2Y51R3b`8D1Ql"A2`UKeZNq"&GVNlZ[f-H#'-RG'M-
-a2)k85)JqK0k(Q11ec1YfNIK6@3HG$TXjZe2L6YT+Z"-9cA4V0YhD"V&B"+EpVVf
-+Na@#!E$X"UCieF&9C80F6KSa!U2A%%M"#S"8Bq(!0VZl99lhD)BaN!$[Ye@MF%L
-raSQA%3l%8ql4iM0q3$5HX)B%Zp+2LK1MRkpG+Y(4H4K&-JihiXAC9$2[BXk)"a#
-)r9%a[cRXD$Nmj,##1"AXKej3kTeLBLFAmmk0pFTN8$*Sa,B+D*&CjDqT9L*2%iZ
-N1*1B,M8)A+U1SV%,@bE*k4pmSr[kJdI4d@r@j-(aVJ`p44fjBY2d5cFNA*a)r,E
-KC6kf$@j4kG$CE#Ca`%331[m&[20I`%@4ac5m$S`V2C33mT&9$6"mSk3)Ni`U5b-
-BE+4%[RXcP1pij[1T'c")MjqVm20hr+b5EZC$$"%4'b5fYT31G*2[iHFQhVRI40f
-"T!JN5-dSI)'M0Ei1dfLqjqqd[8%Tc%A%+!G!ie1-r-EX3EJ0XGbAJhFLlF"#)T`
-'hqcM*0l&MCa(SD6i3qQT)(i"42jG)6)9CT(4%#aAE*dlrpCEq5,50+J,@&5I9cq
-A$J6LCq(Q,Rk3!%5rBrbA$ij9Vj11J1lJ%XL2PilKFa4,JT3R1[aEDpM$MFD2B%M
-H"4)Ej9IIRFE61Di(%BXk2UNf$pjCrkP-rU90r'8R%BMdAeH)A"#r`a!U41BhL"d
-0+H(Eb6A"#dpLJ!k(FP4c%2BA!@"r"34@KbM0EcBChM!RE8L(JQ(kYpi9lfQqp"p
-1B2rF@LAqeG#pA[8k!9mUhf++T#'eU4j13"L(UTMN+((Q`f(!YjCb%mD4m`!Z[ca
-kk4fP"eCB8V5`)Dj,4CbkYD)$9HfiA09SBieAY$DQD*D0*YG01lNNk4'SehRSC3Q
-[D1KSj($%6QP-(r&UpP'5T+U@0M"dHMC,VL8RN!"d!6mhK&X`l)+Q%S$Ic!hACf&
-mE[D8!23Pq2KX1)CL`8Mk6l83kd3R@0r!MH@'A56!h'm[pGb!aiF`GCL+(+1)kE"
-L3q9jfr-HNIRl$-pl(Jq[DZq"M"L[V"-Sm2'VjPG*e6c*50aAHkj#94p!+X#3!,c
-*b)qfJ4pYJhbdS4)XprmpXcMVF@!5PSVj2S#I(1PQPL3'aNR,HRN&HJNr2q2%rDa
-L-6$d'CM2mMc!JDFh!PiIIUlM`1[M`00ci%d#m25Hm3$HH(bF*!([1L2JA@F![1X
-Ni,NNi,Qimir!pS!%YJFJAYEK#-GPp9qmM`[!U`*aaAZYJ!NUT*)!bYQ++RlMbGX
-YIY8q+f%Jh2JPG91aM#qjH&V'+r%bL+D0*Y%dalU!$JX8G,h!k5ERlARq5mKL6EH
-6"0["(ClIF43YNJT"c1&#M4HmmIbZhLBKD*%IJ[lV&!Qi6d&QcGHbB009+0LHjF9
-3fG*6%%$H&BKM"i*3ZX64YmS)IFrMCb0(hr-FIDXiqXB!IDZ3!%*0DFG)cTA3Yp%
-)I4X0d,G43YpK#Af(6HLl5d,IACKf`P"iH8iB#DppZ@-RZE,PP$&QF*2)B"[f8&b
-qlE'5a!8+jARIG66jEei`99%j5DJCE@YG+V+a9P[cr`QC(2@5@B1GEL3TGj%8a`(
-C4!&2VG2aRV#+##bcQ3@C&0EGaK-%*FHHMYrSN!$9613!DA,!DI$"E2#"`LiNT#T
-Q8fKb$`Y0T!&bH(+23AJbhdS@XB6L9abLE2BIq(Z%+FCT2+kHLX,4LF0I#NIrC0q
-lBq5Lm[p%U$NaGm0BK*UZikC3mjeA0G4m[iUKCLf53ViRSHD)FDJTT63pAU(Q5+e
-$c9GKbqGa#$9rCa"UMKL(QK)3M5GX+K*U9MXD%'TZp`XeGA+SkErPpkEVHaTiMVb
-L`229hLkEiKGiMR#$H*2'6#Ne--e1fM)m(S5FCk3EXiJA%$e8$*f&P'%BaZqVUY'
-&E')ICH&%KKJh)UqM3)icG%U6,R%MC6dQVIFc8(XP*CPL%)Ef3V#fA3[9mYc!Tfl
-"S09'BHLA2!4&J9R*`0RL&m$p&6rrj)E#2`d-8#6BXi-fMS-*qSr*"+)53"VhX#-
-d[L#&SJ@'S5JRFh%&SHJ0k")@aeFp&&dmd9$dHKcKZ(58-ii-I`1)#1C'@qrM()c
-@&3P''lS)4Xp@5',Ai@L"`B4DKU166r@5`p(Y4F24'*('`Xf[B9EaMASHN!!fM0+
-$U4*3i`&9$dXR5ip"@$SLKD@5fMNE6)'T0ei+6"YdRS9iGCCA2`K![l"d2Dpikj0
--LQYCbXhc6E*jAL6Pi3*h'E%`G6X3JSe+)$8,a[SQcaUS6``,C2'L[j6m3%@-&KL
-Cl!Yi@VR9E-IVAQcf[+fAYRZ-JPB8IIV)m`iGiD%-ccZHKGJiH3F%T[#+r35@H-*
-2*-b[-'5G,i@X%Eq3!(8,2rB@kl'(@P'Y2r(FajP2-`TDCdP"+phF*`Q0DAj"d@r
-`Xi),M49&K%Dla(i-AYmAG5&4FKB(lqSZ`GZ(Rh95)%[JAFh"1`AJAHejA3,[&#V
-FD3,[1L2`VLX#hR9qi$8)DaqLB*S!1`Z#DP%&3Hem",A4#S*DAm8LT2(CbB5e"3C
-KV9A-946@GV9%B+`#fm@e$Qc21+Ul%*-I'BHfALp(kf+Mm,D1SrM,,P(m2(9I8V"
-,+2k5SrKPS2K,cjX5LPr'cjXQ&2FDSELh#)Tlr9"X%2S#aBXp#kqP2bF-K@3Y`Yk
-*TX-EKEdM21aPhAL0+I"e0KL%[GX9%T%8pT,SE+K0f$Za8-3Sl(hJHa,f2V"K)Q(
-[b#X*HhQBa-,HGakhX2IpUSHp%pf%03jl&m+S@#JIjGTLcViK&m820%F+Y6Pb%EM
-#R1I#@Z*KYp1(#X-[2eEA2mX+&aLb!P'`9`ZcFa#')kQRDij&@0kbG@)XpdqFT8X
-1EY!dS`eT&mI##dYF+*9p'F,Z(NT#S"3&+YL[A[*K2M8qb"-8PR&heaceN[Yr'ID
-%A'kICM'UqXXKPd'5`Kb@T-"Z+8%"dhK$'MfB+TUp0fU3!!,ai45q!"DXiBA22Nq
-Y6d5kJXZ8VZ#$N!$aXZ*d9&JqL%)i5!bCM53'Pbi"k5)ZeHQ`46rDD6Qqqk4VQeT
-"FfVE"+KSTH,N4Pi"Eqj$CY#f$HV+Nfh3m"i2VDMaU3[ee%62KASH%T9Y4f,-+*U
-dK*!!IRIkr6[h+56%)-aMeHr@ImS+!KQRMN""el'd%BME"ph6Tij6YB6`4ih#IMS
-c'DV@)d5LR2aHASLU")dIC%93,"!(`*r1Je-Rd5(3b"%+i%dG,lU4U-m,`0UAF4-
-$4pY&4kZ4MMD01RI6dISJ5QeL1hrejX(-U423$81SHelRM5iJp)$`IE1V*'Cqa!J
-)@X0-S3S1ZBSG8KF,pTR%F+&aHG3rrF'8bi"5Q9elQk6[Tim8NblQT+9b&p6AaB@
-bM[Ur-a9YCFeZm5EB3N'[cR)l&BC,C%@c&JXP!p4YPh8'3d'%`MGpJ+4V)&G-E1Y
-$J'YKiA8C,k)Z0j[PLN0E"+8[D&qe!jK)4A)BUUPlqXSX65`dIH@H3jNVpkc-#Kj
-FQ58H#`BL1d9,&N3mNZ)Y-iF4Z*XMB6-DUU%QC+e&ML1Xb,&A[H5ICb+m5e![QGN
-8'4D2eAL$&h8A$GRAJ(ePSTLBp92&U6eER4Kk'Xb8qNqPiVjkhK(RX3AIePHEN5M
-eX5k!SX("K#F8TmBTMML'1VB%SlUG+2lEcJS+5k)B4H%qMm1f%4Uk&FpaSSq*!5T
-L&rNA%1ifUF0HZlffSP)'*J4iH4T+HD@Le'i4-"BB(E3!B#bB#"LcLS$4"MF8Gq'
-0G+*j%5X)r9J$K!Arab"m[bJ)UpK&9!a*3e#Z-MV`+S"beGL$FZF0IU$dB`e3V[U
-I$-VpB`R+fKFMRjPN,8DqmZJV,dBqmaI@BZ3VXkY3M$b,'PqQ*K"3Q2SCc9(CJ6h
-ieX8P+kI*VQdb)S0ZhJNB1,#a$%mMc"K$)T5@kF,TEH63jX@aRe&M!91c"BA&4p*
-*YYVp3#dAQQ`P`"ThN[kUPU*(8HqB62Vl363Ge-T5YfIQb`C)%%)qQMNcAjTbKVS
-+iq-9)EY6,[$jljP($QMYA9-S0ce+95JS05B(NkNrdP0bS8ah5hXplk,h*SRZMJm
-kcI0HShp,ApXi2'[hpedq*IlFf[@IafNAm#4*YR'a[5`0fGYf3`RC3d8jk(rQe(b
-SJEhKTBScMk3I-#+&0I$3MN1fV0a3'$QXq%!B5,%a8Xj5F'M4plP4l%56"a)qdFl
-L982D1!%"kB9(-LUQSS[P'A&M4i5U+"(r+K14NCC6HbTi%lCIam(*G5DBTTaDqdP
-CF&rlGUIY@+1LG6CB(,cBHbq+ZbmV[Ml,V$4m[ml&5EK"h"NIaaZXcA9eJS5FY0a
-`'"@m!Pb`PDUkd0+*,B6SF(),3Ec"BDG,8lbGD5K8Y,iXj[9&ADIe2eQ[A551k-J
-0G`FBl5mYdfC8U$Q&p2pqa9pGDF1#e"@'8$q3!(9flISbhqf@@ml!qFq%D4e#,2h
-DpB%il@`M"Gf&T6+1T+CD!pSL5PSB+14SZ&f"Nl(*eY1SP2A,`*K6h0"J9QM,J)T
-9`m`dKa'S+@K'[X+"&RRJFIdaaDG81#M2H&#6FNEajRf,@h,$YMZMZk0rUFC@&M9
-ecaEb*Y+V5N@2CMc$3p*(Tca&hih2cXQ3!#5D52qX`J&HSk-e6)D4B$63)C&a5CP
-5a5Q#dF#crJ0j8m`ZD@J-6&eX-'rQ'6G[-QQQHDi#"*+53-QFC&Cf$Yq4TV63`qb
-6r-'XQ0q&)U+`ej1+'3f[,jPC4X(qi$CdecZJ'UH0`fb*Db%93HZL`ZCrA@c3F-4
-T@L`b$0HZ6@@$'idC&bmM))ZTmTLTfe@$#rk0r*K@cjDF1DJiU+3q9&,GfIESD23
-$+F(+3pA8De%[q@-aYMdEN!$'hYM[#P%eA5$Zj!k%b3Q$3Y*jUPe9AHD4L5e6N5M
-`@qE6"LbK`e*e%!U4$VKSrEX9I'l!jdSbQb+0cbZVGjFjRfq-*!DR+Q*NUP+CUVM
-hJ&0hcG"A!f(c'PFK8[hMQcY$SC2Yde$BiR&i#1aqGN!laY&Lr$'dqpNpfUAH2"a
-q(Jjr03kIPQ[#Rk%TeV-h9-T%5iMq3Vk%*"(cU4IJL%"P'h"`%3G[kM6MYK+hZKV
-c[#[dEqQ9'iCR$93R'S#MUA1UST2!-FB%$N8j*bD%QXN4+Ri9hi&Qd"lh4`kJF`k
-[rfF1SMN%)M1"k$5C"4Q6Ka$T5)L,qJ!JYGqiFP%5Ja6LM%%P1iT!d4f)BeARamE
-eeT!!p9lr5QV%D*jkbD1AUm#Sd-U)#[X$@@EapePYaAP8A",TZE`"J1C-R+l8DR+
-AiRm$8@5QKdHT#!`*'jhaDUH[YRqXcG#Q`N+VJ2`+f%5Ub+E3'!M86"eV2JZT"Z4
-iGF*9Xa@AI`L&UA(Zqf'L1[Nfbf'Ti5aANY`%N8-Aa@8ZR-b0%Q60E-ePc@`CZ&&
-Q5d@IV)eVlIF6UkpqieU",Yl*33f#!h)"dPBS'[@Ebp`TBN+%YR(G)K8QaSZZ(%I
-L6YjiQ'6SZlkLRNH9mHUi9+$UK"RZqT5k%2GJQq`FKlRrZ99GikS"A)3V-ae5!aF
-me&bX5-9eI&,M,U+I$KZ#4&D%1E+*Uf20&ATYIEFJPS,`'+kDBh6f)QYJ)PSQlKK
-&b12Z`64rTbJ5T1k4A+*SRQVfDUY,&!hV9HVkYKe$'1bF1@`01lHjBCBl)m8)pP%
-d6Q@10#HG5aM9Y*U-Zhh'$VZVkl+eK36Y3%qf#69@(0"RJNQS"lI@!"ME5GKmN!"
-#X5JHZU22mFEpT$!8J5CYQ[CVmRJJZ!!IET3HEX6$$G,$$AMiKr6`$cc-PalQiq(
-[dX2ImA#9p(!9(Uk4(Ul"`ccTB4iHlT-HlX2$,1PK&KiHN!!H(UKGd2kBcbKSelr
-bS2faZif#p[86#GTcDE13!-#V[84X9pi[IrKUA5!Z*AIJ5(jDDSkL`19b[fDlHhV
-"l,3c#IJM(LbB24-&ieE1&Z'm381-q*Ma)%r`QH#H[Q)CNJ!b9ba,D4[%3hdpFbZ
-(JNPJfDFpA!U1B,PL$M&E-8FmZ')1-5ZB)c0E-5F$MZd9ph!fph!fpcaj6dTZYpd
-Z6CI-)bp5i2[$&YFS(0@fAGLqfYFDG!I1"mk6%+b2K@IhMX)Gbjfam@&k*)GfZ&9
-2'eh2QVH5-++A#4P86*%C6Qm-3L-23'4R3)cN&ZE3BUIf)9J5+qZ9##BrSGJL1HD
-Y36GF9ZD1,6`p,$Hb-l[eRHBDLbkaT,XX%S%M("p1ePJ+F-%BR@AY*aSEUSpTH%Q
-hGVjSDHY1$8$-fC!!VX,*L&q&jNMi!YY!)-L,XI!f2NDG)TYkQC'ART[2laJSEJC
-j2KJZ684%q,YrD4Ch[[e"*"UqkbpYZp$JXN6db$re[cTAkAE281d63hH@NrP0$V(
-EGLUf1d2Nj-DY1A)HblE6XPr(4iC0$`q5bU$CS[0hBK"qE1&@-D4[#bTC6bMQ3ZH
-f(YSFqacJ1mF),#l0B-3TCq3`-l9e8dGiD(G(f,Rl*dLqi83&4fl5rqTmjFlPefQ
-F`5F9fr+rDFb$cB0JLXD$NDTc@bNR%hp`Db0AHK+DjER!&XR0N!#@i@C!24$Ek*U
-+5EMJQVME29AaSUNYjqifh2DVE&Lk$BpC2L5Eh,EEYc8Ppf5#"%4MA(2R*CQ!eI@
-+lS9@hEXEqX*$qMijQ!XUcc[A0dGfr[1[iB9k1"Yaf5+,r&+R30Abd*6(Tl,#SBN
-,01f",B'RmBUK1-`E,0@TcU,a5aYV0Z-f#0&G"&BhE9acKf,ZC40akH&L5H&EcJ#
--69"#-Hc8GfMbDlBK*6B4j0%Ph(B!01'8h1#1hf`+IrUAjR!VJA[MRNfZd@B-DGE
-%$VGZk9L`jmkqk&CaEfAJLrIJp)64B3@b$VFL"2PY)h5a'mC1CYYX)LG6QkV5fY'
-NFMC$,N$P"B,lJFlQL),d!RhP$L`i3a0L"$"Lp,Yh-c+FG`,dr0B-j9cZSq3hjfl
-F"10AJL6G6k%#kc4$JbHk4ViK-4RD`cR-*)2!D%A+B1D+eXifmD[EGLM11r!!CF!
-ImE9$1eDd1Q,dTr1e1hD3!)RB*kN20Ei5*(F)QL2Y(&RaL@DSqEf95eDdDT`dA(a
-4CHjXCJ`(JI,"CR&(d%iZNQk6!P)h"8&NbaY9&1rhKdBpRQ@+E43TJ%TC(Llad%J
-AB5,dDeDKiie48JfFc6cC#4Y&A$&#CHcQH+V)hD,Xp@9D!%IFEmqh9[B'+[3$"(p
-RiqJQ9l!a(#KaP3eP"rMamqL`MKKEl[LbT,KJ&-lfZ8a-NA!VJ5'6lc-YfiZQ!qB
-'i$!lj-E%"SJYjeSkqJ+CKC9JaX"i+Yca1`2$l-9[T'iF$[$8Y%al0UbYF&TDF6S
-RQ5T8reIR@CA"K40-3TH*DYe1U-3**"1d-m&-&iq$qM3rkj+Ec+9dEJP!%pL0CL-
-AL&MkT6,YC"Br4BZ,#-iLGb,)K6,8+jA8e6c@p,Bq%Vdc!21P2@P8Cm',ZNiR5b+
-T9'S8+$95AN8NZX!)Fchr(r-(a-3%&bk8XlZ`(),d!pejQ$j1RI[9Z3hd&A4VTcP
-DM&Q(qQM*!TIf%Gej)M[9aT*Re8Y@E(dEKAGJI!8!cUP+!qXB6ZiY29b4122GV)2
-,,&ZjL%-lR%N`3JT1jVH+&Rq'`@M5X#lUEY-FMalqcK4kpHeRaXMr(+j&A',2rD[
-KbUJHbA6LF9`bbqcJADQRp5XAdT,ZkFA'*j+(E&#5Gf9AHY*`m"`hKq0e-+1TB6,
-4R66-',lNMcK0k@&YQ49eR($4N!"`G2P0[cTR5,i1j&G'G`%JPHH`S@2@L-&i8Ra
-92c8Z,*&LSdmid*c"%i-c'!Qr0P3H2b*iT6CVmULbi[M(5Pcj0PBaIR81f`j50I[
-f-e3c$1M1j,`NCc%jEZ"LZTi",FL!PZ!2Y+#LXh#f,I85NCm0"SLa4(#5j0,Ydk4
-U+Af#+Jl!8GP`U9'[am(Q4&A5B-FM)-+0kMZ#p1i@PG5Be'F,3HDCS3-,Ed%cb`F
-JKC`J+3CA@)Z+40N)c*Fe2*!!bMf2+)@hH)Nc-(('!@qmP0H[#FZKE!mY"aEcjF+
-%B-,DBZ"-5#"61"laLN-*He#"1pYrEfY8(YENYDp#8Q`-$c'0%`m2KejM3c4AFCF
-EY"HjU$N-(a"p%)(Dp#iCaMM$KcR$KcR$Q$($rl3bc%NcBNF'`feSNP#*i)q)*#5
-GiY02Jj-(#8Rij)1M1[H+RIUjX"d*24TYUT("#G3bB(b14MUbi2DKBRflMK)M1"L
-M2(fZ4QQUT`ES,UA!4!S2P9##(jU$4aLTJeSkJlKaMkVNSNbj5,$3SFN[(bi@De%
-509kC#9mQ"+03B31[82aiT-b)+*r*4BMP)NLRDp+CJ`M'9+&G2BUZ3SC$f0`b*&3
-J3X@j4+B"H6iVHDCM+l*UATD4,P0%*)N%*MSU91eKMFfU41Md2EJB&bBL93+Zf%I
-QSJ)d&U#B6RLI(LNQ$jUTQ4401dqHIjKBb"2#PK*AjRB[66)R+(mdijU+miCUP0X
-9mfjmT0FF"3d!Vq9E&abLTmfr&a[CC$C3SF[`QPP3`)qa,XL6E$4j5-E6D@T`'6Z
-AaQCGfZ&P%rNRQc%a#B4%!"YE`K'iB,hXmcQl(Df,fFR0`!d#!-%F2Bb'k&Ph0GZ
-0T1e-FYY'#*c%"%VFBXa)V[JrAja%lUrF!3di&M+3!%)8HMQLkH)&qRF)R$Y0)(D
-k4kfJ*@A6m+3Ll5N'-)5-3kRl0K'!Ak3#1+UEB6k1UNiKc"Z5`@%UKX%[eqX(0K%
-Z1JRa5A%b#P39)5Q2N!!ibrbe`Jj'bSJdDe(6+5rcmh)#3d@6MB(UlC0CR9A!V-&
-Y8H@&B`@ZUM$L$dMU0b%&EGcj)F9@)9+UMC!!dQmLC+Sb&mcUPEN101@#%*Ch1ID
-4J)3Hm#kd+Mb&JM)CILS[!93@RpJfTJTh,+80eldm5U*jm#5UU4-0cX6a$BSQ@A3
-$V8j8C+QaB-DQ@m2PY&(+24EQK2eL042$&98kpNUZC!N+NF8q-S6DF%eAVFfiSV!
-AAbY-C*R3hX)'bG2jT65NKH#FNaUmb9r$LbF0C5Z63aKM`4K#92NBkYMREJfA+R6
--4(,ZRXCa0T9LQ4eeMEBK&-V,JlJI3YAGTMb-`1k13m)AP@&2$6VKrQdJ&DJ3YbN
-qqS$J)G,a'"ccfj5kMF1BE0(L-RYRKViH1$NJ0Y+3!'kl*NG,2CBL1bRbSq5N'*!
-![TY%,)`S+eJ"a$`#085AY$`6L$+S0$U$`rZ-$ZmhK3XHA%T3!Pj8Tpc)Za5Ub+S
-b'@RI+USNaYa(P5,2jP3XQVd`#he)Sr'9aA$aLlU#UBU[d-a!kQLJPfep8$8BZNM
-6)l(MDm-3ZYL%-DSGHHa4%KE(B$$Y3aG&65"%NH!!iaN1J'BZ(VaG(`0*cECGk)4
-N4,,2!#k9QP)N8mS'%(YK(0DcLfhNEf#"$J'EMDYRJfabC5[l("deE`U5c#YY*KV
-dj9h-+6)(qTPCHlCHZ6XX`Nb'Uc4XUARaf-!'9f@Lb[EbJ,JMp*Th0'&!X`LGf9R
-4%K8'K8j,MQrQNfJkbh,IX'YhYk['qFJ9$+m6Gb5pKJ6-+[m"fr8[h,kKlhkD(M0
-pA"5fE('KdXDNaIXdLl""HTL,)Z3'&b0NcF34e*3QXq"3&1iakN,K"5e0Xm-'06Q
-fpR'R&P3M-bqF9q*+ik+&JKe+2e)[qD,KE6dCPET!C#6FZ%+['KTX$MHZe@2KQ+D
-&Ua3A2(a+6"1Mc3"bjm%CE%NjbET[HMN!GcK*%c,hB-T-rb++jJND#59ZHUKQh3J
-ZFN20@0RF3R`FE@m$m9&(1ahLZhSFiKjb'Ri4c@iN3a!Q5Q'j9ST"dLMRPiYGMR$
-Y""KP@)#U1&f)J3R%qRDJZjm[SBZi81MN*1q@T3X8mb$BENG$9@9@RPd`jDciCq8
-8Bm@,mjSB[@'hldmYKD9[iN302,mKQlkQckJkcKqGiJCYqR2TGXQU*j0abZdFPI4
-C-XRTF`4"!KF0j9cJ1SPYZ!(HS-6CCPl3T3%r1NHPHdpDbj!!6[P3583J+LU*$Up
-l6l(0p-QV*(B11I*53A#U4fbNDN(C&eE6&i6CHPeGESYJmqRTr9#``["cKT23+!"
-H$p2V6"6d8[Kr&i5Hm9F0#epGqFpcU`H%6fBYq0N#BFZMp*rDIGGG3UVk0RA+XHq
-V$kQcNLmN,aILm62QDI92PmkD)D3+*p91YH@aj+`VDVI`KR"0mM2khLmq&$+%[`X
-jFj,A#MeU44lBV[jdG[,8bqUI#e1%CFN[*hrci6FI#@(KMp*)BGR6`UcNbmN6K"2
-VNVqC*ka-[Lcm,hj@#qA6K0q1&j,(#b@FYSprm1$jTmH0HhT`bjA"Z)%Vh30#3#J
-62RlkeeHq%Akp),P$k&Z``b2J8R(+3qSI6"2HIr44iAmIII6MHfB)Sc1%jfF)Nai
-6PTiBk"EHQ#'X9aIf,%Zq,6PrF,m`@hhdf-(Nlb4r0ILQfYBXR"YmF0Vb[42DK,p
--+qQa#h(6"0Ud'Lmi!"*lYlU-X4AHIf[4SLr`)r`lAKbj8,$L3X&bGFTJQr"EGCl
-`dK9K3$hcUGI9Dki)*eHG%-je#"d&2e3I6ABN[b8F&[jPk@"LEh*1F[0J@IFh`X[
-5L'pqU-j*rQAbQm*[KG5PJc8I*KFQ$kJhFXVb-Fla`bH&kF)5GD2`3q%DiIM6*eF
-)&iA"RY@[Ulm9[K5Q$Mrjc@@Kjm,2ZSAA&kPI[0)RI(c0K!Hq'G-Rr13(`XAahH1
-lCj`I*h3[RcC&+&`jir8C*i@,mi@2IrhM%bm*&em6[RhQ0d*fKr$-VrYqG+jlc(N
-!N!-B!!!NL!!!9lJ!N!-)!*!$)!!!2c`!"kR`!*!$#PM!!&h!!!"G`!#3"#j"9A-
-b!*!&!e0PCc)(Ff9RE@9ZG&0PCc-(Ff9RE@9ZG&0PCc3(Ff9RE@9ZG!!!'Qi!N!-
-"GJ"1F8U$CL*"l3!J)$`r2!!!)MbTm!!"5N&Q"%T!C`T)3%K"))!K33!%3UG"q[r
-1d2`"!#m),c`!!"PZ,`0K!!+X9)pR3%)i#Pj#Tbmm4%&836mm"0@S(h!"%F!+ANU
-ICaK1F6!mUA#R4N2k!#SLL%(k!#!`2+P`TNG+JfF%F!&1G8lY!#*1F8U$CJ+Tp(!
-!6R9J"J#3"3&1F4mkrrC+(fB551IJi%(krqT3d%kk"Dj-h`F(,cVrhNjeB(*"6%&
-%4%008!!$!*!d8(*"E8MRB2"d8*r#,dJ!)#"2)P3aD3!8!"JK3!!N-A`!!3!XdT%
-K33!ZS!,I`NcI$`C1G8Si#PjR$#!U!!KR$#"!)""R"Lmkri41G8MR(`C"q[qHF!`
-L+J!%`VJ$'Q'NCJ!"2NKkrij1ZJGZ@%q`H[pDCJ!"$U%D,JJ)+J"!!!4R"L"i!UD
-J'b`U!!3U+J!)'#S!"*I8PG3J1[p@S4ir1!)JCJ!!l&42,%JJ1[p%)JE#Z!-D@%&
-K!2p-)$Vr2-#i!aT"q[mi))"+K@B%S5*J"#"&S#GQ!!#d+NJJ$P#!3IVr###!)$V
-r#P'!3IVr!##!3QG)HJ#m,a9)H[m#,cVqiLmkrZ)[1[l+,cVqbLmkrXTK!!e1-"p
-R)$m!5S9R##"0S#UJ+f!%)%fJ)b"1S"mJ4k!E-Gm#)'"J)%kJ(b"(S"Yb!")%j`R
-M'H34!!%!)!)"!1!J6D"T!J!!(i!")%fJDYA8ep4"q[jf5T!!C`K`!D#BF!1JQ#"
-0*8J!#(!!60pJq%je60pJq'!!rVir!#"1S"mJ4k!E-Gm#)0A8ep3`1!)J-F!+B*(
-)*8J!#%cIB2K1G8j@!!")j`!i+'i!$%IkrLT&q[iU)"5`NQd%)")SJ%U!Ea)J8b*
-Z!!LL,L!8dC14NR!!B!3`22rC60mF!%jH6R919[r)51FH1#BZ!!JS,J!-+'i!%%(
-krESY52r83Llrb+%D,8Mrc&92U"``(cS!$%8!!'pF5'lrl$!&8d8r!+J298m[,[r
-XU!d`(c`!$%B!!'rF3LHTQeP2,blrl$!'8dBr!+J1)"mY32r`FJ%I!DQE)'lrm%U
-3!'F398m[#+QQ-"p)`()%`)&Ra#mZrr#TSf#m%#i!&'F+@8mZZ!+Q)&qJ'cmmS2a
-1ZJ5'9%mY32r35S"R!!'H,`"1ZJ2@@%p+!'F+F!%G3!!@6[S#'%KZrq4)E[rJ5'l
-rf%kk"@T2l`!-)#lri+%H,8Mrh#!)C`!"C#!Zrq5K(Le)rqJJ#'F!!93[,[rN,`K
-1ZJ@i8%mJ!fB!!+CC6bmm3dp%48*RU"mJ(be!rr"+J'F!!)iJ3#*3FKM6`5m*6VS
-%Y&K2FJ1`3@Cf)!dJ3(!SdF!Y52rd)Qlrm#44F"M9`#e+rrJ[#Nkk",TB6be!rr`
-JE[r`S#P35LCZrp3R5J!S@8m[,[r`6VS9c#!IFZM3J9'!*d!!,&925(Vq-LmZrr4
-)E[rm,``["#mZrp`[,[rJ,blrk%kk#XC86bmZrr#TSb4Zrp3PE[r3!!`PE[rF!"!
-PE[rJ!"3PE[rS!"Jr2+'B6VS$9P42*N!r2+LI6VS$5P42)J!J#l#"CJ4`!'!#F!%
-J!#9!!"`P4!!J*8`!*%Kkqm`r2+$m2cbJr%kk![K86am!6VS98MmmSCK1ZJ--9%p
-+J'F%F!'JQ#"m!!!"@M!35-$JJ()'X)&Q$%(k!+iLI!!!!c`LL"em!!(rb#"Zrmb
-J'e92U"``(cS!$%8!!'pd5'lrl$!&8d8r!+J298m[,[rXU!d`(c`!$%B!!'rF3LH
-TQeP2,blrl$!'8dBr!+J1)"mY32r`FJ%I!DQE98m[,[r`UDB`(dM!FJ6!J@F),bl
-rm+QLB-)NE[r`5T*R%&92,`UTTM!I5-"b"-#"CkS[#UQMB+33,[r)(8!!&NcI((K
-1AL"I6qm!$Nl36PErr%MR!$"#,[rm2cbJr%kk!La86b4!5S"RA#m!6VS"J&K25J"
-R8#!+*N!J3#mS!!`r2+$m2cbJr%kk!Gj86am!6VS81#",)'J!%+!I)%XJD!!BS"m
-JI!!!!9S`%%M!i)"b"V#"CJT`!#"m!!!$2##!(A`!!Irm%#lrr%cI$!"1ANje6PE
-rk%MR(cKC6kPe)"mU!%KZrqLSG#!0)%!J%(+'d)%Y32rm)%"F5%2Zrq`Lf#,B@8m
-[2%4"9%%r2!69UD!J(bK!)%!N8$)U!!L5DJ!%2!%d+J!'P'S!!Mi#0LlrmNM$1#l
-rlNM%PS3i!8M%PS4U!P+$iS-p3rrf0Llrm%M$1#lrl%M%PS3i!NM%PS4U!P+$iS-
-p3rrd0LlrpYC"282rqM)Zrr653Me"rrKC6d+R5'lrp%Kk!'Cb!4m"FJ%r!A,r,`&
-#*d+RU4-J(bC!,`#SF`D&!*!$H#m-)%Y`%0(!,`LSpPP2UA8J(l#&C!*Jp&92UA3
-3(fB#B2C`rcm!3QFJ(k!b,`ZT&#m-UD-[,[rSU(0-haci6Pj1G3!#!!"19J!!51F
-!-#4Z!!JJ#LC!)%!L+!!#$)&"6%&%CKBL+!!'$)&%3de3CJS`+!!+FJ1`3@F%F!"
-J!R!"60m-!%jH6R8[#PP22cbSER!"(`"1ZK*i)&mN5&P22cbUER!"(`"1ZK*Q)Pm
-J5V(*CJB`2!)!B!3`2!3!*&p1G8j@!!![!cBZ!!J`!dM!!S!!!!J!5S"["(!"B!*
-`!#BI6Pj1G8j@rra)ja`!0Li!#$m$6VVrc&42(8$rr()"X!&Q%!*$"rp1Z[q!X%0
-Z"(!!B#KC6cmmU*p`!4m!6VS4m#!I+J"C6cm$(blrr%kk%H!J(bJ!X)9Q!R!!60m
-!1%jH6R919J!!51FB-$JZ!!JNEJ!+)%SJ%#C!)%!b%!a"384Q+$)S!!)-3805CKi
-f"(,rYN&R'L!S!!4b'1+S!S!!N!2r-J0)`E#"C`4`!'!#F!%G3!!160m-'%jH)&p
-F6dl36PB!!&925'i!#($r2`"1Z[q5%"pR%L"Z!!JJ+!!%FKMLU!*!!2pJ!R$r6Pj
-1G8j@!!"96dKZ!!K`rcm!6VVrC"!ICa!JEJ!))#J!"!+!!2q3!f!#F2p1ANje6PB
-!!%MR'$JQEJ!)+'i!$#",-,`$!A!!*%`NJ#Bm!!!"*0H5"T)!!!*)"T)!N!-J+$`
-!N!1!fC,CNLJm!!!%N!$CNYH5fC)'NJ#3!h`'NJ!!J!"`!#4Z!"!NJ!D5!*!$*!D
-5!*!$)!D5!*!$5!D5!*!$2N*!60mF'%jH6R919[rN51FI1#CZ!!JU,J!-)!XS3#e
-!rqK`*0R!,8crl(!JfF!Y62r`F%MC`#e-rr4`2YR!)!b3!)Z`K@-'F'91qJ#b3N!
-q!%*!28$rj$B(F#5f3'4)F!5f3'3%F!"J$(!!-!0CJ'S#9S$NJ(J!1!-Y42rif+l
-rk#4%&)!J,[rid)$3V[r`)%!`V[rNF!%8%R)!%J,MB0&Zrq454f#`3N!q!(!"2!!
-f"h!IYN"N4(!"YN"N"(!!B!a`!$!$8i"U!P+!iS"i!$J$,86rr0LZrq`N4"5!)#l
-rr0#!d+lrp#"!-)C`!435FJ!5!Z0Jh%"54f#d3N"-haci6Pj1G8j@rr")jami*'i
-!##CZ!!`k,J!3+'i!%N*!2!!b"A!!-!(3J$3'FJ!b!V#"Ea4#3$3'FJ!b!Y+"dS`
-J36#!8NCJfN*!2!"`!Me!rr)f"VC&C!!!Z%*!2J"#3$e!rr"`!$!$jB$3LL"!)"!
-Y32rd-JC`!$!"d)XJ3"J3GJ!@",C(B`!!JM!ZrrCb!F""d@lrm(!!-!06J$3(FJ!
-b!V#"Ecii,[r`GJ!f"#e$rrc@JpD-)%0+8'B5)#lrr0#!d)`J3$#Zrr*8E[rb-Ll
-rm(!!-!(3J0#-)%!`%$e!rr"J&M!&d%$34M3Zrr"b!$)#dS(5M#""-)"54b!Zrr6
-LL#e!rr4J!2pX8NCJ!2p%60mFq%jH6R919[rm51FF-#4Z!!Jf,J!-*Qi!$M)$F!!
-`!HD!1!!`!h)(`%%k!(!!,8$rr$3%FJ!b!Y++)%%5%(!!%!%d"A)!-J,LS()"`)(
-4V[rm)Llrr11*dSXJ36)3F!!`!5e!rra546!&FJL`3@B'3N!k!&*%-Li!%R!!-!(
-3J,#ZrraM!Q#U%#lrra)Z!"25!C!!!8cI$$K1ANje6PErr%MR(b!NEJ!)1#i!$$S
-Z!!ib"(!!-!(QJ$`!-J4d"m*#2J&f!$B!eSSJ3a!3G!!8!#e#rra`!$!"0!9b!$)
-#d)(QJ()#X)&R$()"X)&R)%U!Cc4J-M3'FJ!b!P5"dSSJ34)3F!!3!A)3ikL"V[r
-m0!Cb!$)#8S(5LL""%K"`!"!"iBL"V[rm)#lrr$3(FJ!b!Z+S,8$rr($rFL!f"A3
-!0!15JZ+S`'lrrNcI"2K1ANje6PErf%MR(cJQEJ!)+'i!$L!m!!!"*0'Z!")J2!!
-!!NM4VJ!5)#i!%Le!rqab)01Z!")L,J!5,8(rm#3m!*!$J0@Z!")N,J!5,8,rp#4
-,'"*f!"B%,82rq1D$HJI'49*$282rh#BZrrMLJhS$aN983ce$rqCf!6SZrqEVBce
-$rqKq3-J(I!!F"$e'rq*i!HYN8d3p42rJ+Llrq(i"bSGR#(S!1J46K@!#H[mp4Ir
-HH!Jp42rN5NCR4LmZ!")[!$m$8NS[#NkkrcT2l`!1jd$4E[rN,bi!%LmZrr!r!bm
-Zrqa1ZJX)6qm!$LmZrr3r!bmZrq`[,[r`6VVmV%r[!!j#3$e!rpJ`,[rBX'i!$'3
-!!6S`,[rLCcSN3$mZrqJ[,[rd2blrj#m,6VVpMNr[!!`5!#!+F!!3!6e!rpTd!$3
-!e+lrl#"#%""b!")!dflrj'!F2blrjMmZrq3[#dkkrI"36ce!rpS`,[rQd@lrj$!
-ZrpU`E[rHCKBb,[rB8Qlrf(!!-!(3M#"!3K"J!2pk-#lrfV"Zrq"Q!!#8-#lriQF
-k*%!r,[rS,blrp$mZrq3[#dkkr3C2l`!-%J!J#R!!%!%p32rDG!!d!05Zrq`J3K!
-3FJ!5!00Zrq4J($mZrqBr,[rN,`Y1Z[eS8%mp32rD-#lrjY&Zrq4@E[rD-#lrfP0
-ZrpT+3'F!r`!i,[rBGJ!f"#e$rra6JpD-)%-3%#)Zrrc5M#""%)"5E[rBB-i3,[r
-Gd#lrfc3ZrpK5E[rBFJ!b!Y+-)%%3J'!!rVib,[rNF!!`!9k!jS"-haci6Pj1G8j
-@ria)jami*Qi!##SZ!!`SEJ!3,#i!&#e,rmK`*0I!,8[ri(!Jem!Y5rr-F%MA`#e
-,rq3Y62q8*M`!!!%NeklrP#!m!!!#50'Zrj4`)0'Zrj3S2!#3!i$CV[q8fDlrP#e
-Zrj6rY#Jm!!!%N!$CV[q8,@lrP2qieklrP#eZrj6r[0QZrj3YE[q8rp4`I0'Zrj3
-YE[q8rk3J2!!!J!$4V[q8)#lrP*!!M,#&B`T`C6e!!#K1qJCkF!!Z!%*!28$rM#4
-Zrk69r!!!J!!Y5[qS,@lrT2q3!#em!!#!!2rS5'lrk#mZrk3JEJ!N6T!!8%mJ,[r
-SCJT`Cce!!#K1qJBd*'lrN!"55VAZrkKMD#"Zrj!!8NL4l[qS,8Mrp#"Zrj!!NHl
-rT#e)rr!JE[qSNHlrN!!Y52rX)!KR$L"Zrj!!)QlrT#!ZrqbL,L4Zrk69l[rX,8V
-rN!")E[r`,blrT#"Z!#41N!"36b!Zrr#`V[rdC!T`Cce!!#K1qJA!)'lrN!"5V[q
-3!"!3(8$rS()!%J$5390"28(rd$!Zrp$33$e!rp)JEJ!F)"$3VJ!J,8$rX#4!,``
-[,[qi2c`"*#mZrj!!6VVlmNr[!!ib!#!+F!!`!G'Zrj!!,``[,[qd2c`"*#mZrlK
-1ZJHk6qm!$LmZrl`r2!%N,blrZ#mZrl41Z[PF6qm!$L4!,``[,[qi2blrd#mZrj!
-!6VVlS%r[!!ib!#!+F!!`!G'Zrj!!,``[,[qd2blrd#mZrlK1ZJGS6qm!$LmZrp3
-r,[r3,blrZ#mZrl41Z[N+6qm!$R!!,J"#3$e!ri`YEJ!Jrk`JE[qXXHlrX'3!"+K
-#3$e!rjJ-EJ*)rjKN!!$#-#lrM'B!!)`NE[q3!&*+YHlrU'0S)'lrN!"55*(ZrkJ
-Y52rd)'lrN!#4l[qN,8Mrm#"ZrkL4l[q3!#e)rq`J#'F1)'lrN!!LE[qN)#lrl+)
-Z*'lrT0AZrq`Y5[q3!%KZrr![,[qN)'i!*%k3!&"2)#lrm,#Zrr4N#R"R28!!+%l
-k"%)JE[q3!&+Zrj!!%K"`!"!",J"`#$e!ri``"h)"`%(4E[qB-LlrQ(!!-!(3J0#
-Zrl`J3$!328$rQ#!(iSJZ!&0ZriaJ!2mi"'i#52qB$'i"!2qBC"!JE[qX8UlrV"#
-ZrjPJ!2m)"'i"!2qB1#lrQ(B!0J3Y3rrieS2@V[r-)%-`%$e!rjSL,[ridUlrb#"
-"%K"`!"!"28$rR%T!C`!!`JaZ!"MrM')!!*JNE[q3!&*+YHlrU'0S)'lrN!"55*(
-ZrkJY52rd)'lrN!#4l[qN,8Mrm#"ZrkL4l[q3!#e)rq`J#'F1)'lrN!!LE[qN)#l
-rl+)Z*'lrT0AZrq`Y5[q3!%KZrr![,[qN)'i!*%k3!&"2)#lrm,#Zrr4N#R"R28!
-!+%lk!bJJE[q3!&+Zrj!!%K"`!"!"0#lrM()!-J,MU)k!8'lrM'!!rf*`rh)J1#l
-rR(B!0J55Jq+S`%I4E[qD)!IQU#i!Q@lrM%*!28$rQ$!ZrjL`E[r5C!!!`M!Zria
-Q!!#-*'lrN!"55VAZrkKMD#"Zrj!!8NL4l[qS,8Mrp#"Zrj!!NHlrT#e)rr!JE[q
-SNHlrN!!Y52rX)!KR$L"Zrj!!)QlrT#!ZrqbL,L4Zrk69l[rX,8VrN!")E[r`,bl
-rT#"Z!#41N!"36b!Zrr#`V[rdC!T`Cce!!#K1qJ*B)'lrN!"5V[q3!")3F!!3!5i
-!F!Jp32q--!Gb!F""d@lrQ$)ZrjK`!$!"d)$3V[r8)%!`%$e!rjJJ"q+),J"6E[q
--B!$r0M!Zrp+4E[qB1#lrQ(B!0J3Y3rrmeS2@V[rN)%-`%$e!rjiL,[rmdUlri#"
-"%K"`!"!"28$rR%T!C`!!`JaZ!"MrM')!!*JNE[q3!&*+YHlrU'0S)'lrN!"55*(
-ZrkJY52rd)'lrN!#4l[qN,8Mrm#"ZrkL4l[q3!#e)rq`J#'F1)'lrN!!LE[qN)#l
-rl+)Z*'lrT0AZrq`Y5[q3!%KZrr![,[qN)'i!*%k3!&"2)#lrm,#Zrr4N#R"R28!
-!+%lk!9SJE[q3!&+Zrj!!%K"`!"!"0#lrM()!-J,MU)k!8'lrM'!!rf*`rh)J1#l
-rR(B!0J55Jq+S`%I4E[qH)!IQU#i!Q@lrM#"Zrk`b,[qHF!!`!C(!,8MrP,(Z!#"
-PB#"Zrj45V[q8%"!JE[qX8UlrV"#!)'lrP&+Zrj33%#"Zrka5V[qX%)!JE[q88Ul
-rP"!3)'lrV&+Zrk`3J$!ZrjT6E[qD5N"R!2[H)'lrP&+Zrj33%#"Zrka5V[qX%)"
-Jh&CZrjSJEJ!BdFBb,[qHF!!`!5*Zrkb6lJ!JN!#*NF!Y52q8-#lrQQFQ)'i!'0(
-'XHlrP'-D)'lrP&+Zrj33%#"Zrka5V[qX%)"6E[qDB03YEJ!Jrj3`,[qD8flrQNT
-!C`$lCL"Zrj45V[q8%"!JE[qX8UlrV"#!B0`JE[qXXHlrX'F)F'Fp3!!SB"3JE[q
-XNHi!)#*Z!"`LL%*!28!!+%cI(2K1AL"I6qm!)%l3!(!m!$iJ!!"i)$i`)#BQ)(J
-J2$dc-J!!1N0[EA"bCA0cD@pZ1N4PBfpYF(*PFh0TEfi`-c!a,Q-!!$`!2L!!!(J
-J2M!J*LBJH#!m26-b!!!k3fpYF(*PFh0TEfik4'9MEfe`FQ9cFfP[EM!c-$%ZB`!
-!6PErk%MR(cJq,J!)+'i!$$BZ!!T`!$!$1!Gb!$)%N!#"FJ'`J@m!!E3p42rS282
-rkP*ZrqJ`,[rSX'i!#Q3FFJ!b!0+-)%%3%$3(FJ!b!Y+-)%%5%,!"C!*JeP0ZrqS
-`,[rUX%GM(()!-J$5M#""%"!d"h)!-J,5M#""%K#`!@-#B0J`,[rSX'lrkQ8#B()
-i,[rSGJ!f"#e$rr$@M#4$%K*`!"!"28$rl$SZrqTi!$J&,86rp0L-*N33%a5!&Ul
-rl5!Zrr$3J0#Z!"!J3$!328$rl#)Zrr65JG+Z!"!J36)3*#lrm05#e+i!%#"#-)%
-L,[rddS(5VJ!3)%%`J'!!rc)`,[rUX%GQ"P*(B!$r"$J(GJ!f"#e$rrM@M#4$%K*
-`!"!"28$rl$`ZrqTk!$S',8Arr0U-*N83%a5!&Ulrl5!ZrrM3J0#Z!"!J3$!328$
-rl#)Zrrc5JG+Z!"!J36)3*#lrq05#e+i!%#"#-)%L,[rmdS(5VJ!3)%%`J#!Zrr`
-L,[riN!#"0#i!#R)!-J)N,[rm8S+5JV#"E"i[,J!3,``r"Mm%6VVqA%r[!!``,[r
-U8N!q!'!!rP`[,J!3,``r,J!+-#lrkP*!2`"1Z[if6qm!$$eZrqS!#Q!!rMK-hac
-i6Pj1G8j@rq4)jami*'i!#$SZ!!`QEJ!1+'i!%Le-rr!J2!!!!56C`#e-rr4#3$`
-!0JDf4@3XH!!i!be%rrMBLL"%%"!L,[ridUlrm#""%)!J,[rid)$3V[rd)%!`Je*
-'B-i[,[rd,blrm$m&3QG1Z[fb6qm!$%*!2!!f"VC&C"*`!$!$d+lrm#"!5K"Q"&*
-'B1K`!#e!rq3f"VC&C!!!U%T$Cc)J,[rNH!!i!be%rrcBV[r`)%38%()!%J)Q,[r
-m8i2@V[r`)%-@%(3!&!15JZ1S,8$rj$3'FJ!b!Y+Zrr!J34)3F!!3!6i!,@lrj2r
-XF!!Y32rS-!G64dT!Cb!J,[rSiiJL,[rXG!(#JS#",8$rk#!ZrqcLL#e!rqaJf$3
-'FJ!b!Y+"dUlrp#""-K"`!$!"jB$3Lb"!)+lrk&*'8Ulrj'!!re4-haci6Pj1G5*
-I)&qJ*5k!DJ*#Pdl4)Pm5(c!I5J&R"+G'B!+M4Lk)6Y%LAa)I-"mJAdS"C`5Q4f!
-#SNG1d3#3!`S!1+!"!!8!N!B"!!!"MdN!!Bj*!!!%E&028P3&PJ#!!"`$dJ!838a
-59!!+!+T"9A-b!!!",N*14%`!!3%k3dp%43!(!9*%394"!!!"XN4*9%`!$3'q4%a
-24`!#!QC'8N9'!!3#LNCPBA3!!!,'5801)`!%!Y**3dp1!!!$$P"*3e3!!!-D8(0
-PG!!!!bC659T&!!!$-P088L!!!3-q8e45)`!!!eCKGA0d!!%$BQ0TBfi!!!0kD@0
-X1!!!!iCVD@jN!!!$NRCPFR-!!31H!)$rrb!!",-!N!@"rrmJ!!6$!*!&J[rr)!!
-%F`#3"BArrb3!")--l8hS!)Errb3!"+--mjFi!)Irrb!!"*-!N!@)rrmJ!!66!*!
-%!J$rrb!!"18!N!3#!Irr)!!%p3#3"!3"rrmJ!!4M!*!%"+rrr`!!&"`!N!G!!!!
-Cc`#3"B$rr`!!'CF!N!3"!2rr!!!CG`#3"[rr+!&cE3#3"3%!AK`!(PB-mjFX!!)
-!D"`!N!!I$21A*!!$!()F!+`d$21A"!!%!(`F!21L$21A4!!&!)BF!58[$1raK!!
-'!*!!(!&)6JcaVlJ!"rrr!!&cb3#3"[rr+!"J'!#3"B$rr`!!!DF!N!@#rrm!!!*
-h!*!&KIrr*!!!J!cY6NJ!K[rr*!!"*JcY6H3!Krrr!*!$eJ#3"BMrr`!!!`%!N!@
-errmJ!!)&!*!%!3F!0#!!%fi!N!3#!2rr!!!$f3#3"!)"rrm!!!3A!*!%!qMrrb!
-!!Y8!N!3%!Irr)!#3"`4,!#J%!",J$21A3!5[rrm!!"-`!*!%!3F!(#!!%5-!N!3
-$k2rr)!!*@!#3"!4,!"!%!"%+$21A!!#!rrm!!"P!!*!&JIrr!!!C5`#3"B,rr`!
-!'9B!N!@$rrm!!"PK!*!&K2rr!!!CE!#3"[rr!!'11`#3"B$rr`!!&#`!N!@"rrm
-!!"8`!*!&J[rr!!!@0!#3"B2rr`!!&cJ!N!@%rrm!!"Jm!*!%"%[rr`3!%Q8-mjE
-S!qMrr`!!#E3!N!@!rrm!!!8K!*!%rj!%!!&cL3#3"!)!N!-J!!8&!*!%!J%!"b!
-!"48!N!@!rrm!!!Pd!*!(6`!!'IF!N!@%rrm!!"Rc!*!%"%[rr`3!%6m-l8hX!)6
-rr`!!'P)!N!@!rrm!!A1A!*!&!Irr)!!3q!#3"3,rrb!!%0S!N!3'F(*[EA"d#-3
-JFh9QCQPi#dPZFf9bG#"%DA0V#d9iDA0dD@jR)&"A#dPZFf9bG#"%DA0V#d9iDA0
-dD@jR)&"A$NphEQ9b)(*PFfpeFQ0P$NphEQ9b)(*PFfpeFQ0P#90PCfePER3J-3P
-6C@GYC@jd)$)*8f9RE@9ZG#!c#90PCfePER3J03P6C@GYC@jd)$B*8f9RE@9ZG#!
-fS33:
diff --git a/mac/tclMacResource.c b/mac/tclMacResource.c
deleted file mode 100644
index fe2c879..0000000
--- a/mac/tclMacResource.c
+++ /dev/null
@@ -1,2220 +0,0 @@
-/*
- * tclMacResource.c --
- *
- * This file contains several commands that manipulate or use
- * Macintosh resources. Included are extensions to the "source"
- * command, the mac specific "beep" and "resource" commands, and
- * administration for open resource file references.
- *
- * Copyright (c) 1996-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include <Errors.h>
-#include <FSpCompat.h>
-#include <Processes.h>
-#include <Resources.h>
-#include <Sound.h>
-#include <Strings.h>
-#include <Traps.h>
-#include <LowMem.h>
-
-#include "FullPath.h"
-#include "tcl.h"
-#include "tclInt.h"
-#include "tclMac.h"
-#include "tclMacInt.h"
-#include "tclMacPort.h"
-
-/*
- * This flag tells the RegisterResource function to insert the
- * resource into the tail of the resource fork list. Needed only
- * Resource_Init.
- */
-
-#define TCL_RESOURCE_INSERT_TAIL 1
-/*
- * 2 is taken by TCL_RESOURCE_DONT_CLOSE
- * which is the only public flag to TclMacRegisterResourceFork.
- */
-
-#define TCL_RESOURCE_CHECK_IF_OPEN 4
-
-/*
- * Pass this in the mode parameter of SetSoundVolume to determine
- * which volume to set.
- */
-
-enum WhichVolume {
- SYS_BEEP_VOLUME, /* This sets the volume for SysBeep calls */
- DEFAULT_SND_VOLUME, /* This one for SndPlay calls */
- RESET_VOLUME /* And this undoes the last call to SetSoundVolume */
-};
-
-/*
- * Hash table to track open resource files.
- */
-
-typedef struct OpenResourceFork {
- short fileRef;
- int flags;
-} OpenResourceFork;
-
-
-
-static Tcl_HashTable nameTable; /* Id to process number mapping. */
-static Tcl_HashTable resourceTable; /* Process number to id mapping. */
-static Tcl_Obj *resourceForkList; /* Ordered list of resource forks */
-static int appResourceIndex; /* This is the index of the application*
- * in the list of resource forks */
-static int newId = 0; /* Id source. */
-static int initialized = 0; /* 0 means static structures haven't
- * been initialized yet. */
-static int osTypeInit = 0; /* 0 means Tcl object of osType hasn't
- * been initialized yet. */
-/*
- * Prototypes for procedures defined later in this file:
- */
-
-static void DupOSTypeInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
- Tcl_Obj *copyPtr));
-static void ResourceInit _ANSI_ARGS_((void));
-static void BuildResourceForkList _ANSI_ARGS_((void));
-static int SetOSTypeFromAny _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
-static void UpdateStringOfOSType _ANSI_ARGS_((Tcl_Obj *objPtr));
-static OpenResourceFork* GetRsrcRefFromObj _ANSI_ARGS_((Tcl_Obj *objPtr,
- int okayOnReadOnly, const char *operation,
- Tcl_Obj *resultPtr));
-
-static void SetSoundVolume(int volume, enum WhichVolume mode);
-
-/*
- * The structures below defines the Tcl object type defined in this file by
- * means of procedures that can be invoked by generic object code.
- */
-
-static Tcl_ObjType osType = {
- "ostype", /* name */
- (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
- DupOSTypeInternalRep, /* dupIntRepProc */
- UpdateStringOfOSType, /* updateStringProc */
- SetOSTypeFromAny /* setFromAnyProc */
-};
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_ResourceObjCmd --
- *
- * This procedure is invoked to process the "resource" Tcl command.
- * See the user documentation for details on what it does.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * See the user documentation.
- *
- *----------------------------------------------------------------------
- */
-
-int
-Tcl_ResourceObjCmd(
- ClientData clientData, /* Not used. */
- Tcl_Interp *interp, /* Current interpreter. */
- int objc, /* Number of arguments. */
- Tcl_Obj *CONST objv[]) /* Argument values. */
-{
- Tcl_Obj *resultPtr, *objPtr;
- int index, result;
- long fileRef, rsrcId;
- FSSpec fileSpec;
- char *stringPtr;
- char errbuf[16];
- OpenResourceFork *resourceRef;
- Handle resource = NULL;
- OSErr err;
- int count, i, limitSearch = false, length;
- short id, saveRef, resInfo;
- Str255 theName;
- OSType rezType;
- int gotInt, releaseIt = 0, force;
- char *resourceId = NULL;
- long size;
- char macPermision;
- int mode;
-
- static CONST char *switches[] = {"close", "delete" ,"files", "list",
- "open", "read", "types", "write", (char *) NULL
- };
-
- enum {
- RESOURCE_CLOSE, RESOURCE_DELETE, RESOURCE_FILES, RESOURCE_LIST,
- RESOURCE_OPEN, RESOURCE_READ, RESOURCE_TYPES, RESOURCE_WRITE
- };
-
- static CONST char *writeSwitches[] = {
- "-id", "-name", "-file", "-force", (char *) NULL
- };
-
- enum {
- RESOURCE_WRITE_ID, RESOURCE_WRITE_NAME,
- RESOURCE_WRITE_FILE, RESOURCE_FORCE
- };
-
- static CONST char *deleteSwitches[] = {"-id", "-name", "-file", (char *) NULL};
-
- enum {RESOURCE_DELETE_ID, RESOURCE_DELETE_NAME, RESOURCE_DELETE_FILE};
-
- resultPtr = Tcl_GetObjResult(interp);
-
- if (objc < 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
- return TCL_ERROR;
- }
-
- if (Tcl_GetIndexFromObj(interp, objv[1], switches, "option", 0, &index)
- != TCL_OK) {
- return TCL_ERROR;
- }
- if (!initialized) {
- ResourceInit();
- }
- result = TCL_OK;
-
- switch (index) {
- case RESOURCE_CLOSE:
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "resourceRef");
- return TCL_ERROR;
- }
- stringPtr = Tcl_GetStringFromObj(objv[2], &length);
- fileRef = TclMacUnRegisterResourceFork(stringPtr, resultPtr);
-
- if (fileRef >= 0) {
- CloseResFile((short) fileRef);
- return TCL_OK;
- } else {
- return TCL_ERROR;
- }
- case RESOURCE_DELETE:
- if (!((objc >= 3) && (objc <= 9) && ((objc % 2) == 1))) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-id resourceId? ?-name resourceName? ?-file \
-resourceRef? resourceType");
- return TCL_ERROR;
- }
-
- i = 2;
- fileRef = -1;
- gotInt = false;
- resourceId = NULL;
- limitSearch = false;
-
- while (i < (objc - 2)) {
- if (Tcl_GetIndexFromObj(interp, objv[i], deleteSwitches,
- "option", 0, &index) != TCL_OK) {
- return TCL_ERROR;
- }
-
- switch (index) {
- case RESOURCE_DELETE_ID:
- if (Tcl_GetLongFromObj(interp, objv[i+1], &rsrcId)
- != TCL_OK) {
- return TCL_ERROR;
- }
- gotInt = true;
- break;
- case RESOURCE_DELETE_NAME:
- resourceId = Tcl_GetStringFromObj(objv[i+1], &length);
- if (length > 255) {
- Tcl_AppendStringsToObj(resultPtr,"-name argument ",
- "too long, must be < 255 characters",
- (char *) NULL);
- return TCL_ERROR;
- }
- strcpy((char *) theName, resourceId);
- resourceId = (char *) theName;
- c2pstr(resourceId);
- break;
- case RESOURCE_DELETE_FILE:
- resourceRef = GetRsrcRefFromObj(objv[i+1], 0,
- "delete from", resultPtr);
- if (resourceRef == NULL) {
- return TCL_ERROR;
- }
- limitSearch = true;
- break;
- }
- i += 2;
- }
-
- if ((resourceId == NULL) && !gotInt) {
- Tcl_AppendStringsToObj(resultPtr,"you must specify either ",
- "\"-id\" or \"-name\" or both ",
- "to \"resource delete\"",
- (char *) NULL);
- return TCL_ERROR;
- }
-
- if (Tcl_GetOSTypeFromObj(interp, objv[i], &rezType) != TCL_OK) {
- return TCL_ERROR;
- }
-
- if (limitSearch) {
- saveRef = CurResFile();
- UseResFile((short) resourceRef->fileRef);
- }
-
- SetResLoad(false);
-
- if (gotInt == true) {
- if (limitSearch) {
- resource = Get1Resource(rezType, rsrcId);
- } else {
- resource = GetResource(rezType, rsrcId);
- }
- err = ResError();
-
- if (err == resNotFound || resource == NULL) {
- Tcl_AppendStringsToObj(resultPtr, "resource not found",
- (char *) NULL);
- result = TCL_ERROR;
- goto deleteDone;
- } else if (err != noErr) {
- char buffer[16];
-
- sprintf(buffer, "%12d", err);
- Tcl_AppendStringsToObj(resultPtr, "resource error #",
- buffer, "occured while trying to find resource",
- (char *) NULL);
- result = TCL_ERROR;
- goto deleteDone;
- }
- }
-
- if (resourceId != NULL) {
- Handle tmpResource;
- if (limitSearch) {
- tmpResource = Get1NamedResource(rezType,
- (StringPtr) resourceId);
- } else {
- tmpResource = GetNamedResource(rezType,
- (StringPtr) resourceId);
- }
- err = ResError();
-
- if (err == resNotFound || tmpResource == NULL) {
- Tcl_AppendStringsToObj(resultPtr, "resource not found",
- (char *) NULL);
- result = TCL_ERROR;
- goto deleteDone;
- } else if (err != noErr) {
- char buffer[16];
-
- sprintf(buffer, "%12d", err);
- Tcl_AppendStringsToObj(resultPtr, "resource error #",
- buffer, "occured while trying to find resource",
- (char *) NULL);
- result = TCL_ERROR;
- goto deleteDone;
- }
-
- if (gotInt) {
- if (resource != tmpResource) {
- Tcl_AppendStringsToObj(resultPtr,
- "\"-id\" and \"-name\" ",
- "values do not point to the same resource",
- (char *) NULL);
- result = TCL_ERROR;
- goto deleteDone;
- }
- } else {
- resource = tmpResource;
- }
- }
-
- resInfo = GetResAttrs(resource);
-
- if ((resInfo & resProtected) == resProtected) {
- Tcl_AppendStringsToObj(resultPtr, "resource ",
- "cannot be deleted: it is protected.",
- (char *) NULL);
- result = TCL_ERROR;
- goto deleteDone;
- } else if ((resInfo & resSysHeap) == resSysHeap) {
- Tcl_AppendStringsToObj(resultPtr, "resource",
- "cannot be deleted: it is in the system heap.",
- (char *) NULL);
- result = TCL_ERROR;
- goto deleteDone;
- }
-
- /*
- * Find the resource file, if it was not specified,
- * so we can flush the changes now. Perhaps this is
- * a little paranoid, but better safe than sorry.
- */
-
- RemoveResource(resource);
-
- if (!limitSearch) {
- UpdateResFile(HomeResFile(resource));
- } else {
- UpdateResFile(resourceRef->fileRef);
- }
-
-
- deleteDone:
-
- SetResLoad(true);
- if (limitSearch) {
- UseResFile(saveRef);
- }
- return result;
-
- case RESOURCE_FILES:
- if ((objc < 2) || (objc > 3)) {
- Tcl_SetStringObj(resultPtr,
- "wrong # args: should be \"resource files \
-?resourceId?\"", -1);
- return TCL_ERROR;
- }
-
- if (objc == 2) {
- stringPtr = Tcl_GetStringFromObj(resourceForkList, &length);
- Tcl_SetStringObj(resultPtr, stringPtr, length);
- } else {
- FCBPBRec fileRec;
- Handle pathHandle;
- short pathLength;
- Str255 fileName;
- Tcl_DString dstr;
-
- if (strcmp(Tcl_GetString(objv[2]), "ROM Map") == 0) {
- Tcl_SetStringObj(resultPtr,"no file path for ROM Map", -1);
- return TCL_ERROR;
- }
-
- resourceRef = GetRsrcRefFromObj(objv[2], 1, "files", resultPtr);
- if (resourceRef == NULL) {
- return TCL_ERROR;
- }
-
- fileRec.ioCompletion = NULL;
- fileRec.ioFCBIndx = 0;
- fileRec.ioNamePtr = fileName;
- fileRec.ioVRefNum = 0;
- fileRec.ioRefNum = resourceRef->fileRef;
- err = PBGetFCBInfo(&fileRec, false);
- if (err != noErr) {
- Tcl_SetStringObj(resultPtr,
- "could not get FCB for resource file", -1);
- return TCL_ERROR;
- }
-
- err = GetFullPath(fileRec.ioFCBVRefNum, fileRec.ioFCBParID,
- fileRec.ioNamePtr, &pathLength, &pathHandle);
- if ( err != noErr) {
- Tcl_SetStringObj(resultPtr,
- "could not get file path from token", -1);
- return TCL_ERROR;
- }
-
- HLock(pathHandle);
- Tcl_ExternalToUtfDString(NULL, *pathHandle, pathLength, &dstr);
-
- Tcl_SetStringObj(resultPtr, Tcl_DStringValue(&dstr), Tcl_DStringLength(&dstr));
- HUnlock(pathHandle);
- DisposeHandle(pathHandle);
- Tcl_DStringFree(&dstr);
- }
- return TCL_OK;
- case RESOURCE_LIST:
- if (!((objc == 3) || (objc == 4))) {
- Tcl_WrongNumArgs(interp, 2, objv, "resourceType ?resourceRef?");
- return TCL_ERROR;
- }
- if (Tcl_GetOSTypeFromObj(interp, objv[2], &rezType) != TCL_OK) {
- return TCL_ERROR;
- }
-
- if (objc == 4) {
- resourceRef = GetRsrcRefFromObj(objv[3], 1,
- "list", resultPtr);
- if (resourceRef == NULL) {
- return TCL_ERROR;
- }
-
- saveRef = CurResFile();
- UseResFile((short) resourceRef->fileRef);
- limitSearch = true;
- }
-
- Tcl_ResetResult(interp);
- if (limitSearch) {
- count = Count1Resources(rezType);
- } else {
- count = CountResources(rezType);
- }
- SetResLoad(false);
- for (i = 1; i <= count; i++) {
- if (limitSearch) {
- resource = Get1IndResource(rezType, i);
- } else {
- resource = GetIndResource(rezType, i);
- }
- if (resource != NULL) {
- GetResInfo(resource, &id, (ResType *) &rezType, theName);
- if (theName[0] != 0) {
-
- objPtr = Tcl_NewStringObj((char *) theName + 1,
- theName[0]);
- } else {
- objPtr = Tcl_NewIntObj(id);
- }
- ReleaseResource(resource);
- result = Tcl_ListObjAppendElement(interp, resultPtr,
- objPtr);
- if (result != TCL_OK) {
- Tcl_DecrRefCount(objPtr);
- break;
- }
- }
- }
- SetResLoad(true);
-
- if (limitSearch) {
- UseResFile(saveRef);
- }
-
- return TCL_OK;
- case RESOURCE_OPEN: {
- Tcl_DString ds, buffer;
- CONST char *str, *native;
- int length;
-
- if (!((objc == 3) || (objc == 4))) {
- Tcl_WrongNumArgs(interp, 2, objv, "fileName ?permissions?");
- return TCL_ERROR;
- }
- str = Tcl_GetStringFromObj(objv[2], &length);
- if (Tcl_TranslateFileName(interp, str, &buffer) == NULL) {
- return TCL_ERROR;
- }
- native = Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&buffer),
- Tcl_DStringLength(&buffer), &ds);
- err = FSpLocationFromPath(Tcl_DStringLength(&ds), native, &fileSpec);
- Tcl_DStringFree(&ds);
- Tcl_DStringFree(&buffer);
-
- if (!((err == noErr) || (err == fnfErr))) {
- Tcl_AppendStringsToObj(resultPtr, "invalid path", (char *) NULL);
- return TCL_ERROR;
- }
-
- /*
- * Get permissions for the file. We really only understand
- * read-only and shared-read-write. If no permissions are
- * given we default to read only.
- */
-
- if (objc == 4) {
- stringPtr = Tcl_GetStringFromObj(objv[3], &length);
- mode = TclGetOpenMode(interp, stringPtr, &index);
- if (mode == -1) {
- /* TODO: TclGetOpenMode doesn't work with Obj commands. */
- return TCL_ERROR;
- }
- switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) {
- case O_RDONLY:
- macPermision = fsRdPerm;
- break;
- case O_WRONLY:
- case O_RDWR:
- macPermision = fsRdWrShPerm;
- break;
- default:
- panic("Tcl_ResourceObjCmd: invalid mode value");
- break;
- }
- } else {
- macPermision = fsRdPerm;
- }
-
- /*
- * Don't load in any of the resources in the file, this could
- * cause problems if you open a file that has CODE resources...
- */
-
- SetResLoad(false);
- fileRef = (long) FSpOpenResFileCompat(&fileSpec, macPermision);
- SetResLoad(true);
-
- if (fileRef == -1) {
- err = ResError();
- if (((err == fnfErr) || (err == eofErr)) &&
- (macPermision == fsRdWrShPerm)) {
- /*
- * No resource fork existed for this file. Since we are
- * opening it for writing we will create the resource fork
- * now.
- */
-
- HCreateResFile(fileSpec.vRefNum, fileSpec.parID,
- fileSpec.name);
- fileRef = (long) FSpOpenResFileCompat(&fileSpec,
- macPermision);
- if (fileRef == -1) {
- goto openError;
- }
- } else if (err == fnfErr) {
- Tcl_AppendStringsToObj(resultPtr,
- "file does not exist", (char *) NULL);
- return TCL_ERROR;
- } else if (err == eofErr) {
- Tcl_AppendStringsToObj(resultPtr,
- "file does not contain resource fork", (char *) NULL);
- return TCL_ERROR;
- } else {
- openError:
- Tcl_AppendStringsToObj(resultPtr,
- "error opening resource file", (char *) NULL);
- return TCL_ERROR;
- }
- }
-
- /*
- * The FspOpenResFile function does not set the ResFileAttrs.
- * Even if you open the file read only, the mapReadOnly
- * attribute is not set. This means we can't detect writes to a
- * read only resource fork until the write fails, which is bogus.
- * So set it here...
- */
-
- if (macPermision == fsRdPerm) {
- SetResFileAttrs(fileRef, mapReadOnly);
- }
-
- Tcl_SetStringObj(resultPtr, "", 0);
- if (TclMacRegisterResourceFork(fileRef, resultPtr,
- TCL_RESOURCE_CHECK_IF_OPEN) != TCL_OK) {
- CloseResFile(fileRef);
- return TCL_ERROR;
- }
- return TCL_OK;
- }
- case RESOURCE_READ:
- if (!((objc == 4) || (objc == 5))) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "resourceType resourceId ?resourceRef?");
- return TCL_ERROR;
- }
-
- if (Tcl_GetOSTypeFromObj(interp, objv[2], &rezType) != TCL_OK) {
- return TCL_ERROR;
- }
-
- if (Tcl_GetLongFromObj((Tcl_Interp *) NULL, objv[3], &rsrcId)
- != TCL_OK) {
- resourceId = Tcl_GetStringFromObj(objv[3], &length);
- }
-
- if (objc == 5) {
- stringPtr = Tcl_GetStringFromObj(objv[4], &length);
- } else {
- stringPtr = NULL;
- }
-
- resource = Tcl_MacFindResource(interp, rezType, resourceId,
- rsrcId, stringPtr, &releaseIt);
-
- if (resource != NULL) {
- size = GetResourceSizeOnDisk(resource);
- Tcl_SetByteArrayObj(resultPtr, (unsigned char *) *resource, size);
-
- /*
- * Don't release the resource unless WE loaded it...
- */
-
- if (releaseIt) {
- ReleaseResource(resource);
- }
- return TCL_OK;
- } else {
- Tcl_AppendStringsToObj(resultPtr, "could not load resource",
- (char *) NULL);
- return TCL_ERROR;
- }
- case RESOURCE_TYPES:
- if (!((objc == 2) || (objc == 3))) {
- Tcl_WrongNumArgs(interp, 2, objv, "?resourceRef?");
- return TCL_ERROR;
- }
-
- if (objc == 3) {
- resourceRef = GetRsrcRefFromObj(objv[2], 1,
- "get types of", resultPtr);
- if (resourceRef == NULL) {
- return TCL_ERROR;
- }
-
- saveRef = CurResFile();
- UseResFile((short) resourceRef->fileRef);
- limitSearch = true;
- }
-
- if (limitSearch) {
- count = Count1Types();
- } else {
- count = CountTypes();
- }
- for (i = 1; i <= count; i++) {
- if (limitSearch) {
- Get1IndType((ResType *) &rezType, i);
- } else {
- GetIndType((ResType *) &rezType, i);
- }
- objPtr = Tcl_NewOSTypeObj(rezType);
- result = Tcl_ListObjAppendElement(interp, resultPtr, objPtr);
- if (result != TCL_OK) {
- Tcl_DecrRefCount(objPtr);
- break;
- }
- }
-
- if (limitSearch) {
- UseResFile(saveRef);
- }
-
- return result;
- case RESOURCE_WRITE:
- if ((objc < 4) || (objc > 11)) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-id resourceId? ?-name resourceName? ?-file resourceRef?\
- ?-force? resourceType data");
- return TCL_ERROR;
- }
-
- i = 2;
- gotInt = false;
- resourceId = NULL;
- limitSearch = false;
- force = 0;
-
- while (i < (objc - 2)) {
- if (Tcl_GetIndexFromObj(interp, objv[i], writeSwitches,
- "switch", 0, &index) != TCL_OK) {
- return TCL_ERROR;
- }
-
- switch (index) {
- case RESOURCE_WRITE_ID:
- if (Tcl_GetLongFromObj(interp, objv[i+1], &rsrcId)
- != TCL_OK) {
- return TCL_ERROR;
- }
- gotInt = true;
- i += 2;
- break;
- case RESOURCE_WRITE_NAME:
- resourceId = Tcl_GetStringFromObj(objv[i+1], &length);
- strcpy((char *) theName, resourceId);
- resourceId = (char *) theName;
- c2pstr(resourceId);
- i += 2;
- break;
- case RESOURCE_WRITE_FILE:
- resourceRef = GetRsrcRefFromObj(objv[i+1], 0,
- "write to", resultPtr);
- if (resourceRef == NULL) {
- return TCL_ERROR;
- }
- limitSearch = true;
- i += 2;
- break;
- case RESOURCE_FORCE:
- force = 1;
- i += 1;
- break;
- }
- }
- if (Tcl_GetOSTypeFromObj(interp, objv[i], &rezType) != TCL_OK) {
- return TCL_ERROR;
- }
- stringPtr = (char *) Tcl_GetByteArrayFromObj(objv[i+1], &length);
-
- if (gotInt == false) {
- rsrcId = UniqueID(rezType);
- }
- if (resourceId == NULL) {
- resourceId = (char *) "\p";
- }
- if (limitSearch) {
- saveRef = CurResFile();
- UseResFile((short) resourceRef->fileRef);
- }
-
- /*
- * If we are adding the resource by number, then we must make sure
- * there is not already a resource of that number. We are not going
- * load it here, since we want to detect whether we loaded it or
- * not. Remember that releasing some resources in particular menu
- * related ones, can be fatal.
- */
-
- if (gotInt == true) {
- SetResLoad(false);
- resource = Get1Resource(rezType,rsrcId);
- SetResLoad(true);
- }
-
- if (resource == NULL) {
- /*
- * We get into this branch either if there was not already a
- * resource of this type & id, or the id was not specified.
- */
-
- resource = NewHandle(length);
- if (resource == NULL) {
- resource = NewHandleSys(length);
- if (resource == NULL) {
- panic("could not allocate memory to write resource");
- }
- }
- HLock(resource);
- memcpy(*resource, stringPtr, length);
- HUnlock(resource);
- AddResource(resource, rezType, (short) rsrcId,
- (StringPtr) resourceId);
- releaseIt = 1;
- } else {
- /*
- * We got here because there was a resource of this type
- * & ID in the file.
- */
-
- if (*resource == NULL) {
- releaseIt = 1;
- } else {
- releaseIt = 0;
- }
-
- if (!force) {
- /*
- *We only overwrite extant resources
- * when the -force flag has been set.
- */
-
- sprintf(errbuf,"%d", rsrcId);
-
- Tcl_AppendStringsToObj(resultPtr, "the resource ",
- errbuf, " already exists, use \"-force\"",
- " to overwrite it.", (char *) NULL);
-
- result = TCL_ERROR;
- goto writeDone;
- } else if (GetResAttrs(resource) & resProtected) {
- /*
- *
- * Next, check to see if it is protected...
- */
-
- sprintf(errbuf,"%d", rsrcId);
- Tcl_AppendStringsToObj(resultPtr,
- "could not write resource id ",
- errbuf, " of type ",
- Tcl_GetStringFromObj(objv[i],&length),
- ", it was protected.",(char *) NULL);
- result = TCL_ERROR;
- goto writeDone;
- } else {
- /*
- * Be careful, the resource might already be in memory
- * if something else loaded it.
- */
-
- if (*resource == 0) {
- LoadResource(resource);
- err = ResError();
- if (err != noErr) {
- sprintf(errbuf,"%d", rsrcId);
- Tcl_AppendStringsToObj(resultPtr,
- "error loading resource ",
- errbuf, " of type ",
- Tcl_GetStringFromObj(objv[i],&length),
- " to overwrite it", (char *) NULL);
- goto writeDone;
- }
- }
-
- SetHandleSize(resource, length);
- if ( MemError() != noErr ) {
- panic("could not allocate memory to write resource");
- }
-
- HLock(resource);
- memcpy(*resource, stringPtr, length);
- HUnlock(resource);
-
- ChangedResource(resource);
-
- /*
- * We also may have changed the name...
- */
-
- SetResInfo(resource, rsrcId, (StringPtr) resourceId);
- }
- }
-
- err = ResError();
- if (err != noErr) {
- Tcl_AppendStringsToObj(resultPtr,
- "error adding resource to resource map",
- (char *) NULL);
- result = TCL_ERROR;
- goto writeDone;
- }
-
- WriteResource(resource);
- err = ResError();
- if (err != noErr) {
- Tcl_AppendStringsToObj(resultPtr,
- "error writing resource to disk",
- (char *) NULL);
- result = TCL_ERROR;
- }
-
- writeDone:
-
- if (releaseIt) {
- ReleaseResource(resource);
- err = ResError();
- if (err != noErr) {
- Tcl_AppendStringsToObj(resultPtr,
- "error releasing resource",
- (char *) NULL);
- result = TCL_ERROR;
- }
- }
-
- if (limitSearch) {
- UseResFile(saveRef);
- }
-
- return result;
- default:
- panic("Tcl_GetIndexFromObj returned unrecognized option");
- return TCL_ERROR; /* Should never be reached. */
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_MacSourceObjCmd --
- *
- * This procedure is invoked to process the "source" Tcl command.
- * See the user documentation for details on what it does. In
- * addition, it supports sourceing from the resource fork of
- * type 'TEXT'.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * See the user documentation.
- *
- *----------------------------------------------------------------------
- */
-
-int
-Tcl_MacSourceObjCmd(
- ClientData dummy, /* Not used. */
- Tcl_Interp *interp, /* Current interpreter. */
- int objc, /* Number of arguments. */
- Tcl_Obj *CONST objv[]) /* Argument objects. */
-{
- char *errNum = "wrong # args: ";
- char *errBad = "bad argument: ";
- char *errStr;
- char *fileName = NULL, *rsrcName = NULL;
- long rsrcID = -1;
- char *string;
- int length;
-
- if (objc < 2 || objc > 4) {
- errStr = errNum;
- goto sourceFmtErr;
- }
-
- if (objc == 2) {
- return Tcl_FSEvalFile(interp, objv[1]);
- }
-
- /*
- * The following code supports a few older forms of this command
- * for backward compatability.
- */
- string = Tcl_GetStringFromObj(objv[1], &length);
- if (!strcmp(string, "-rsrc") || !strcmp(string, "-rsrcname")) {
- rsrcName = Tcl_GetStringFromObj(objv[2], &length);
- } else if (!strcmp(string, "-rsrcid")) {
- if (Tcl_GetLongFromObj(interp, objv[2], &rsrcID) != TCL_OK) {
- return TCL_ERROR;
- }
- } else {
- errStr = errBad;
- goto sourceFmtErr;
- }
-
- if (objc == 4) {
- fileName = Tcl_GetStringFromObj(objv[3], &length);
- }
- return Tcl_MacEvalResource(interp, rsrcName, rsrcID, fileName);
-
- sourceFmtErr:
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), errStr, "should be \"",
- Tcl_GetString(objv[0]), " fileName\" or \"",
- Tcl_GetString(objv[0]), " -rsrc name ?fileName?\" or \"",
- Tcl_GetString(objv[0]), " -rsrcid id ?fileName?\"",
- (char *) NULL);
- return TCL_ERROR;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_BeepObjCmd --
- *
- * This procedure makes the beep sound.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * Makes a beep.
- *
- *----------------------------------------------------------------------
- */
-
-int
-Tcl_BeepObjCmd(
- ClientData dummy, /* Not used. */
- Tcl_Interp *interp, /* Current interpreter. */
- int objc, /* Number of arguments. */
- Tcl_Obj *CONST objv[]) /* Argument values. */
-{
- Tcl_Obj *resultPtr, *objPtr;
- Handle sound;
- Str255 sndName;
- int volume = -1, length;
- char * sndArg = NULL;
-
- resultPtr = Tcl_GetObjResult(interp);
- if (objc == 1) {
- SysBeep(1);
- return TCL_OK;
- } else if (objc == 2) {
- if (!strcmp(Tcl_GetStringFromObj(objv[1], &length), "-list")) {
- int count, i;
- short id;
- Str255 theName;
- ResType rezType;
-
- count = CountResources('snd ');
- for (i = 1; i <= count; i++) {
- sound = GetIndResource('snd ', i);
- if (sound != NULL) {
- GetResInfo(sound, &id, &rezType, theName);
- if (theName[0] == 0) {
- continue;
- }
- objPtr = Tcl_NewStringObj((char *) theName + 1,
- theName[0]);
- Tcl_ListObjAppendElement(interp, resultPtr, objPtr);
- }
- }
- return TCL_OK;
- } else {
- sndArg = Tcl_GetStringFromObj(objv[1], &length);
- }
- } else if (objc == 3) {
- if (!strcmp(Tcl_GetStringFromObj(objv[1], &length), "-volume")) {
- Tcl_GetIntFromObj(interp, objv[2], &volume);
- } else {
- goto beepUsage;
- }
- } else if (objc == 4) {
- if (!strcmp(Tcl_GetStringFromObj(objv[1], &length), "-volume")) {
- Tcl_GetIntFromObj(interp, objv[2], &volume);
- sndArg = Tcl_GetStringFromObj(objv[3], &length);
- } else {
- goto beepUsage;
- }
- } else {
- goto beepUsage;
- }
-
- /*
- * Play the sound
- */
- if (sndArg == NULL) {
- /*
- * Set Volume for SysBeep
- */
-
- if (volume >= 0) {
- SetSoundVolume(volume, SYS_BEEP_VOLUME);
- }
- SysBeep(1);
-
- /*
- * Reset Volume
- */
-
- if (volume >= 0) {
- SetSoundVolume(0, RESET_VOLUME);
- }
- } else {
- strcpy((char *) sndName + 1, sndArg);
- sndName[0] = length;
- sound = GetNamedResource('snd ', sndName);
- if (sound != NULL) {
- /*
- * Set Volume for Default Output device
- */
-
- if (volume >= 0) {
- SetSoundVolume(volume, DEFAULT_SND_VOLUME);
- }
-
- SndPlay(NULL, (SndListHandle) sound, false);
-
- /*
- * Reset Volume
- */
-
- if (volume >= 0) {
- SetSoundVolume(0, RESET_VOLUME);
- }
- } else {
- Tcl_AppendStringsToObj(resultPtr, " \"", sndArg,
- "\" is not a valid sound. (Try ",
- Tcl_GetString(objv[0]), " -list)", NULL);
- return TCL_ERROR;
- }
- }
-
- return TCL_OK;
-
- beepUsage:
- Tcl_WrongNumArgs(interp, 1, objv, "[-volume num] [-list | sndName]?");
- return TCL_ERROR;
-}
-
-/*
- *-----------------------------------------------------------------------------
- *
- * SetSoundVolume --
- *
- * Set the volume for either the SysBeep or the SndPlay call depending
- * on the value of mode (SYS_BEEP_VOLUME or DEFAULT_SND_VOLUME
- * respectively.
- *
- * It also stores the last channel set, and the old value of its
- * VOLUME. If you call SetSoundVolume with a mode of RESET_VOLUME,
- * it will undo the last setting. The volume parameter is
- * ignored in this case.
- *
- * Side Effects:
- * Sets the System Volume
- *
- * Results:
- * None
- *
- *-----------------------------------------------------------------------------
- */
-
-void
-SetSoundVolume(
- int volume, /* This is the new volume */
- enum WhichVolume mode) /* This flag says which volume to
- * set: SysBeep, SndPlay, or instructs us
- * to reset the volume */
-{
- static int hasSM3 = -1;
- static enum WhichVolume oldMode;
- static long oldVolume = -1;
-
- /*
- * The volume setting calls only work if we have SoundManager
- * 3.0 or higher. So we check that here.
- */
-
- if (hasSM3 == -1) {
- if (GetToolboxTrapAddress(_SoundDispatch)
- != GetToolboxTrapAddress(_Unimplemented)) {
- NumVersion SMVers = SndSoundManagerVersion();
- if (SMVers.majorRev > 2) {
- hasSM3 = 1;
- } else {
- hasSM3 = 0;
- }
- } else {
- /*
- * If the SoundDispatch trap is not present, then
- * we don't have the SoundManager at all.
- */
-
- hasSM3 = 0;
- }
- }
-
- /*
- * If we don't have Sound Manager 3.0, we can't set the sound volume.
- * We will just ignore the request rather than raising an error.
- */
-
- if (!hasSM3) {
- return;
- }
-
- switch (mode) {
- case SYS_BEEP_VOLUME:
- GetSysBeepVolume(&oldVolume);
- SetSysBeepVolume(volume);
- oldMode = SYS_BEEP_VOLUME;
- break;
- case DEFAULT_SND_VOLUME:
- GetDefaultOutputVolume(&oldVolume);
- SetDefaultOutputVolume(volume);
- oldMode = DEFAULT_SND_VOLUME;
- break;
- case RESET_VOLUME:
- /*
- * If oldVolume is -1 someone has made a programming error
- * and called reset before setting the volume. This is benign
- * however, so we will just exit.
- */
-
- if (oldVolume != -1) {
- if (oldMode == SYS_BEEP_VOLUME) {
- SetSysBeepVolume(oldVolume);
- } else if (oldMode == DEFAULT_SND_VOLUME) {
- SetDefaultOutputVolume(oldVolume);
- }
- }
- oldVolume = -1;
- }
-}
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Tcl_MacEvalResource --
- *
- * Used to extend the source command. Sources Tcl code from a Text
- * resource. Currently only sources the resouce by name file ID may be
- * supported at a later date.
- *
- * Side Effects:
- * Depends on the Tcl code in the resource.
- *
- * Results:
- * Returns a Tcl result.
- *
- *-----------------------------------------------------------------------------
- */
-
-int
-Tcl_MacEvalResource(
- Tcl_Interp *interp, /* Interpreter in which to process file. */
- CONST char *resourceName, /* Name of TEXT resource to source,
- NULL if number should be used. */
- int resourceNumber, /* Resource id of source. */
- CONST char *fileName) /* Name of file to process.
- NULL if application resource. */
-{
- Handle sourceText;
- Str255 rezName;
- char msg[200];
- int result, iOpenedResFile = false;
- short saveRef, fileRef = -1;
- char idStr[64];
- FSSpec fileSpec;
- Tcl_DString ds, buffer;
- CONST char *nativeName;
-
- saveRef = CurResFile();
-
- if (fileName != NULL) {
- OSErr err;
-
- if (Tcl_TranslateFileName(interp, fileName, &buffer) == NULL) {
- return TCL_ERROR;
- }
- nativeName = Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&buffer),
- Tcl_DStringLength(&buffer), &ds);
- err = FSpLocationFromPath(strlen(nativeName), nativeName,
- &fileSpec);
- Tcl_DStringFree(&ds);
- Tcl_DStringFree(&buffer);
- if (err != noErr) {
- Tcl_AppendResult(interp, "Error finding the file: \"",
- fileName, "\".", NULL);
- return TCL_ERROR;
- }
-
- fileRef = FSpOpenResFileCompat(&fileSpec, fsRdPerm);
- if (fileRef == -1) {
- Tcl_AppendResult(interp, "Error reading the file: \"",
- fileName, "\".", NULL);
- return TCL_ERROR;
- }
-
- UseResFile(fileRef);
- iOpenedResFile = true;
- } else {
- /*
- * The default behavior will search through all open resource files.
- * This may not be the behavior you desire. If you want the behavior
- * of this call to *only* search the application resource fork, you
- * must call UseResFile at this point to set it to the application
- * file. This means you must have already obtained the application's
- * fileRef when the application started up.
- */
- }
-
- /*
- * Load the resource by name or ID
- */
- if (resourceName != NULL) {
- Tcl_DString ds;
- Tcl_UtfToExternalDString(NULL, resourceName, -1, &ds);
- strcpy((char *) rezName + 1, Tcl_DStringValue(&ds));
- rezName[0] = (unsigned) Tcl_DStringLength(&ds);
- sourceText = GetNamedResource('TEXT', rezName);
- Tcl_DStringFree(&ds);
- } else {
- sourceText = GetResource('TEXT', (short) resourceNumber);
- }
-
- if (sourceText == NULL) {
- result = TCL_ERROR;
- } else {
- char *sourceStr = NULL;
-
- HLock(sourceText);
- sourceStr = Tcl_MacConvertTextResource(sourceText);
- HUnlock(sourceText);
- ReleaseResource(sourceText);
-
- /*
- * We now evaluate the Tcl source
- */
- result = Tcl_Eval(interp, sourceStr);
- ckfree(sourceStr);
- if (result == TCL_RETURN) {
- result = TCL_OK;
- } else if (result == TCL_ERROR) {
- sprintf(msg, "\n (rsrc \"%.150s\" line %d)",
- resourceName,
- interp->errorLine);
- Tcl_AddErrorInfo(interp, msg);
- }
-
- goto rezEvalCleanUp;
- }
-
- rezEvalError:
- sprintf(idStr, "ID=%d", resourceNumber);
- Tcl_AppendResult(interp, "The resource \"",
- (resourceName != NULL ? resourceName : idStr),
- "\" could not be loaded from ",
- (fileName != NULL ? fileName : "application"),
- ".", NULL);
-
- rezEvalCleanUp:
-
- /*
- * TRICKY POINT: The code that you are sourcing here could load a
- * shared library. This will go AHEAD of the resource we stored away
- * in saveRef on the resource path.
- * If you restore the saveRef in this case, you will never be able
- * to get to the resources in the shared library, since you are now
- * pointing too far down on the resource list.
- * So, we only reset the current resource file if WE opened a resource
- * explicitly, and then only if the CurResFile is still the
- * one we opened...
- */
-
- if (iOpenedResFile && (CurResFile() == fileRef)) {
- UseResFile(saveRef);
- }
-
- if (fileRef != -1) {
- CloseResFile(fileRef);
- }
-
- return result;
-}
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Tcl_MacConvertTextResource --
- *
- * Converts a TEXT resource into a Tcl suitable string.
- *
- * Side Effects:
- * Mallocs the returned memory, converts '\r' to '\n', and appends a NULL.
- *
- * Results:
- * A new malloced string.
- *
- *-----------------------------------------------------------------------------
- */
-
-char *
-Tcl_MacConvertTextResource(
- Handle resource) /* Handle to TEXT resource. */
-{
- int i, size;
- char *resultStr;
- Tcl_DString dstr;
-
- size = GetResourceSizeOnDisk(resource);
-
- Tcl_ExternalToUtfDString(NULL, *resource, size, &dstr);
-
- size = Tcl_DStringLength(&dstr) + 1;
- resultStr = (char *) ckalloc((unsigned) size);
-
- memcpy((VOID *) resultStr, (VOID *) Tcl_DStringValue(&dstr), (size_t) size);
-
- Tcl_DStringFree(&dstr);
-
- for (i=0; i<size; i++) {
- if (resultStr[i] == '\r') {
- resultStr[i] = '\n';
- }
- }
-
- return resultStr;
-}
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Tcl_MacFindResource --
- *
- * Higher level interface for loading resources.
- *
- * Side Effects:
- * Attempts to load a resource.
- *
- * Results:
- * A handle on success.
- *
- *-----------------------------------------------------------------------------
- */
-
-Handle
-Tcl_MacFindResource(
- Tcl_Interp *interp, /* Interpreter in which to process file. */
- long resourceType, /* Type of resource to load. */
- CONST char *resourceName, /* Name of resource to find,
- * NULL if number should be used. */
- int resourceNumber, /* Resource id of source. */
- CONST char *resFileRef, /* Registered resource file reference,
- * NULL if searching all open resource files. */
- int *releaseIt) /* Should we release this resource when done. */
-{
- Tcl_HashEntry *nameHashPtr;
- OpenResourceFork *resourceRef;
- int limitSearch = false;
- short saveRef;
- Handle resource;
-
- if (resFileRef != NULL) {
- nameHashPtr = Tcl_FindHashEntry(&nameTable, resFileRef);
- if (nameHashPtr == NULL) {
- Tcl_AppendResult(interp, "invalid resource file reference \"",
- resFileRef, "\"", (char *) NULL);
- return NULL;
- }
- resourceRef = (OpenResourceFork *) Tcl_GetHashValue(nameHashPtr);
- saveRef = CurResFile();
- UseResFile((short) resourceRef->fileRef);
- limitSearch = true;
- }
-
- /*
- * Some system resources (for example system resources) should not
- * be released. So we set autoload to false, and try to get the resource.
- * If the Master Pointer of the returned handle is null, then resource was
- * not in memory, and it is safe to release it. Otherwise, it is not.
- */
-
- SetResLoad(false);
-
- if (resourceName == NULL) {
- if (limitSearch) {
- resource = Get1Resource(resourceType, resourceNumber);
- } else {
- resource = GetResource(resourceType, resourceNumber);
- }
- } else {
- Str255 rezName;
- Tcl_DString ds;
- Tcl_UtfToExternalDString(NULL, resourceName, -1, &ds);
- strcpy((char *) rezName + 1, Tcl_DStringValue(&ds));
- rezName[0] = (unsigned) Tcl_DStringLength(&ds);
- if (limitSearch) {
- resource = Get1NamedResource(resourceType,
- rezName);
- } else {
- resource = GetNamedResource(resourceType,
- rezName);
- }
- Tcl_DStringFree(&ds);
- }
-
- if (resource != NULL && *resource == NULL) {
- *releaseIt = 1;
- LoadResource(resource);
- } else {
- *releaseIt = 0;
- }
-
- SetResLoad(true);
-
-
- if (limitSearch) {
- UseResFile(saveRef);
- }
-
- return resource;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ResourceInit --
- *
- * Initialize the structures used for resource management.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Read the code.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-ResourceInit()
-{
-
- initialized = 1;
- Tcl_InitHashTable(&nameTable, TCL_STRING_KEYS);
- Tcl_InitHashTable(&resourceTable, TCL_ONE_WORD_KEYS);
- resourceForkList = Tcl_NewObj();
- Tcl_IncrRefCount(resourceForkList);
-
- BuildResourceForkList();
-
-}
-/***/
-
-/*Tcl_RegisterObjType(typePtr) */
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_NewOSTypeObj --
- *
- * This procedure is used to create a new resource name type object.
- *
- * Results:
- * The newly created object is returned. This object will have a NULL
- * string representation. The returned object has ref count 0.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_Obj *
-Tcl_NewOSTypeObj(
- OSType newOSType) /* Int used to initialize the new object. */
-{
- register Tcl_Obj *objPtr;
-
- if (!osTypeInit) {
- osTypeInit = 1;
- Tcl_RegisterObjType(&osType);
- }
-
- objPtr = Tcl_NewObj();
- objPtr->bytes = NULL;
- objPtr->internalRep.longValue = newOSType;
- objPtr->typePtr = &osType;
- return objPtr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_SetOSTypeObj --
- *
- * Modify an object to be a resource type and to have the
- * specified long value.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The object's old string rep, if any, is freed. Also, any old
- * internal rep is freed.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tcl_SetOSTypeObj(
- Tcl_Obj *objPtr, /* Object whose internal rep to init. */
- OSType newOSType) /* Integer used to set object's value. */
-{
- register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
-
- if (!osTypeInit) {
- osTypeInit = 1;
- Tcl_RegisterObjType(&osType);
- }
-
- if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
- oldTypePtr->freeIntRepProc(objPtr);
- }
-
- objPtr->internalRep.longValue = newOSType;
- objPtr->typePtr = &osType;
-
- Tcl_InvalidateStringRep(objPtr);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_GetOSTypeFromObj --
- *
- * Attempt to return an int from the Tcl object "objPtr". If the object
- * is not already an int, an attempt will be made to convert it to one.
- *
- * Results:
- * The return value is a standard Tcl object result. If an error occurs
- * during conversion, an error message is left in interp->objResult
- * unless "interp" is NULL.
- *
- * Side effects:
- * If the object is not already an int, the conversion will free
- * any old internal representation.
- *
- *----------------------------------------------------------------------
- */
-
-int
-Tcl_GetOSTypeFromObj(
- Tcl_Interp *interp, /* Used for error reporting if not NULL. */
- Tcl_Obj *objPtr, /* The object from which to get a int. */
- OSType *osTypePtr) /* Place to store resulting int. */
-{
- register int result;
-
- if (!osTypeInit) {
- osTypeInit = 1;
- Tcl_RegisterObjType(&osType);
- }
-
- if (objPtr->typePtr == &osType) {
- *osTypePtr = objPtr->internalRep.longValue;
- return TCL_OK;
- }
-
- result = SetOSTypeFromAny(interp, objPtr);
- if (result == TCL_OK) {
- *osTypePtr = objPtr->internalRep.longValue;
- }
- return result;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * DupOSTypeInternalRep --
- *
- * Initialize the internal representation of an int Tcl_Obj to a
- * copy of the internal representation of an existing int object.
- *
- * Results:
- * None.
- *
- * Side effects:
- * "copyPtr"s internal rep is set to the integer corresponding to
- * "srcPtr"s internal rep.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-DupOSTypeInternalRep(
- Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
- Tcl_Obj *copyPtr) /* Object with internal rep to set. */
-{
- copyPtr->internalRep.longValue = srcPtr->internalRep.longValue;
- copyPtr->typePtr = &osType;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * SetOSTypeFromAny --
- *
- * Attempt to generate an integer internal form for the Tcl object
- * "objPtr".
- *
- * Results:
- * The return value is a standard object Tcl result. If an error occurs
- * during conversion, an error message is left in interp->objResult
- * unless "interp" is NULL.
- *
- * Side effects:
- * If no error occurs, an int is stored as "objPtr"s internal
- * representation.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-SetOSTypeFromAny(
- Tcl_Interp *interp, /* Used for error reporting if not NULL. */
- Tcl_Obj *objPtr) /* The object to convert. */
-{
- Tcl_ObjType *oldTypePtr = objPtr->typePtr;
- char *string;
- int length;
- long newOSType;
-
- /*
- * Get the string representation. Make it up-to-date if necessary.
- */
-
- string = Tcl_GetStringFromObj(objPtr, &length);
-
- if (length != 4) {
- if (interp != NULL) {
- Tcl_ResetResult(interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "expected Macintosh OS type but got \"", string, "\"",
- (char *) NULL);
- }
- return TCL_ERROR;
- }
- newOSType = *((long *) string);
-
- /*
- * The conversion to resource type succeeded. Free the old internalRep
- * before setting the new one.
- */
-
- if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
- oldTypePtr->freeIntRepProc(objPtr);
- }
-
- objPtr->internalRep.longValue = newOSType;
- objPtr->typePtr = &osType;
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * UpdateStringOfOSType --
- *
- * Update the string representation for an resource type object.
- * Note: This procedure does not free an existing old string rep
- * so storage will be lost if this has not already been done.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The object's string is set to a valid string that results from
- * the int-to-string conversion.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-UpdateStringOfOSType(
- register Tcl_Obj *objPtr) /* Int object whose string rep to update. */
-{
- objPtr->bytes = ckalloc(5);
- sprintf(objPtr->bytes, "%-4.4s", &(objPtr->internalRep.longValue));
- objPtr->length = 4;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * GetRsrcRefFromObj --
- *
- * Given a String object containing a resource file token, return
- * the OpenResourceFork structure that it represents, or NULL if
- * the token cannot be found. If okayOnReadOnly is false, it will
- * also check whether the token corresponds to a read-only file,
- * and return NULL if it is.
- *
- * Results:
- * A pointer to an OpenResourceFork structure, or NULL.
- *
- * Side effects:
- * An error message may be left in resultPtr.
- *
- *----------------------------------------------------------------------
- */
-
-static OpenResourceFork *
-GetRsrcRefFromObj(
- register Tcl_Obj *objPtr, /* String obj containing file token */
- int okayOnReadOnly, /* Whether this operation is okay for a *
- * read only file. */
- const char *operation, /* String containing the operation we *
- * were trying to perform, used for errors */
- Tcl_Obj *resultPtr) /* Tcl_Obj to contain error message */
-{
- char *stringPtr;
- Tcl_HashEntry *nameHashPtr;
- OpenResourceFork *resourceRef;
- int length;
- OSErr err;
-
- stringPtr = Tcl_GetStringFromObj(objPtr, &length);
- nameHashPtr = Tcl_FindHashEntry(&nameTable, stringPtr);
- if (nameHashPtr == NULL) {
- Tcl_AppendStringsToObj(resultPtr,
- "invalid resource file reference \"",
- stringPtr, "\"", (char *) NULL);
- return NULL;
- }
-
- resourceRef = (OpenResourceFork *) Tcl_GetHashValue(nameHashPtr);
-
- if (!okayOnReadOnly) {
- err = GetResFileAttrs((short) resourceRef->fileRef);
- if (err & mapReadOnly) {
- Tcl_AppendStringsToObj(resultPtr, "cannot ", operation,
- " resource file \"",
- stringPtr, "\", it was opened read only",
- (char *) NULL);
- return NULL;
- }
- }
- return resourceRef;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclMacRegisterResourceFork --
- *
- * Register an open resource fork in the table of open resources
- * managed by the procedures in this file. If the resource file
- * is already registered with the table, then no new token is made.
- *
- * The behavior is controlled by the value of tokenPtr, and of the
- * flags variable. For tokenPtr, the possibilities are:
- * - NULL: The new token is auto-generated, but not returned.
- * - The string value of tokenPtr is the empty string: Then
- * the new token is auto-generated, and returned in tokenPtr
- * - tokenPtr has a value: The string value will be used for the token,
- * unless it is already in use, in which case a new token will
- * be generated, and returned in tokenPtr.
- *
- * For the flags variable: it can be one of:
- * - TCL_RESOURCE__INSERT_TAIL: The element is inserted at the
- * end of the list of open resources. Used only in Resource_Init.
- * - TCL_RESOURCE_DONT_CLOSE: The resource close command will not close
- * this resource.
- * - TCL_RESOURCE_CHECK_IF_OPEN: This will check to see if this file's
- * resource fork is already opened by this Tcl shell, and return
- * an error without registering the resource fork.
- *
- * Results:
- * Standard Tcl Result
- *
- * Side effects:
- * An entry may be added to the resource name table.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclMacRegisterResourceFork(
- short fileRef, /* File ref for an open resource fork. */
- Tcl_Obj *tokenPtr, /* A Tcl Object to which to write the *
- * new token */
- int flags) /* 1 means insert at the head of the resource
- * fork list, 0 means at the tail */
-
-{
- Tcl_HashEntry *resourceHashPtr;
- Tcl_HashEntry *nameHashPtr;
- OpenResourceFork *resourceRef;
- int new;
- char *resourceId = NULL;
-
- if (!initialized) {
- ResourceInit();
- }
-
- /*
- * If we were asked to, check that this file has not been opened
- * already with a different permission. It it has, then return an error.
- */
-
- new = 1;
-
- if (flags & TCL_RESOURCE_CHECK_IF_OPEN) {
- Tcl_HashSearch search;
- short oldFileRef, filePermissionFlag;
- FCBPBRec newFileRec, oldFileRec;
- OSErr err;
-
- oldFileRec.ioCompletion = NULL;
- oldFileRec.ioFCBIndx = 0;
- oldFileRec.ioNamePtr = NULL;
-
- newFileRec.ioCompletion = NULL;
- newFileRec.ioFCBIndx = 0;
- newFileRec.ioNamePtr = NULL;
- newFileRec.ioVRefNum = 0;
- newFileRec.ioRefNum = fileRef;
- err = PBGetFCBInfo(&newFileRec, false);
- filePermissionFlag = ( newFileRec.ioFCBFlags >> 12 ) & 0x1;
-
-
- resourceHashPtr = Tcl_FirstHashEntry(&resourceTable, &search);
- while (resourceHashPtr != NULL) {
- oldFileRef = (short) Tcl_GetHashKey(&resourceTable,
- resourceHashPtr);
- if (oldFileRef == fileRef) {
- new = 0;
- break;
- }
- oldFileRec.ioVRefNum = 0;
- oldFileRec.ioRefNum = oldFileRef;
- err = PBGetFCBInfo(&oldFileRec, false);
-
- /*
- * err might not be noErr either because the file has closed
- * out from under us somehow, which is bad but we're not going
- * to fix it here, OR because it is the ROM MAP, which has a
- * fileRef, but can't be gotten to by PBGetFCBInfo.
- */
- if ((err == noErr)
- && (newFileRec.ioFCBVRefNum == oldFileRec.ioFCBVRefNum)
- && (newFileRec.ioFCBFlNm == oldFileRec.ioFCBFlNm)) {
- /*
- * In MacOS 8.1 it seems like we get different file refs even
- * though we pass the same file & permissions. This is not
- * what Inside Mac says should happen, but it does, so if it
- * does, then close the new res file and return the original
- * one...
- */
-
- if (filePermissionFlag == ((oldFileRec.ioFCBFlags >> 12) & 0x1)) {
- CloseResFile(fileRef);
- new = 0;
- break;
- } else {
- if (tokenPtr != NULL) {
- Tcl_SetStringObj(tokenPtr, "Resource already open with different permissions.", -1);
- }
- return TCL_ERROR;
- }
- }
- resourceHashPtr = Tcl_NextHashEntry(&search);
- }
- }
-
-
- /*
- * If the file has already been opened with these same permissions, then it
- * will be in our list and we will have set new to 0 above.
- * So we will just return the token (if tokenPtr is non-null)
- */
-
- if (new) {
- resourceHashPtr = Tcl_CreateHashEntry(&resourceTable,
- (char *) fileRef, &new);
- }
-
- if (!new) {
- if (tokenPtr != NULL) {
- resourceId = (char *) Tcl_GetHashValue(resourceHashPtr);
- Tcl_SetStringObj(tokenPtr, resourceId, -1);
- }
- return TCL_OK;
- }
-
- /*
- * If we were passed in a result pointer which is not an empty
- * string, attempt to use that as the key. If the key already
- * exists, silently fall back on resource%d...
- */
-
- if (tokenPtr != NULL) {
- char *tokenVal;
- int length;
- tokenVal = Tcl_GetStringFromObj(tokenPtr, &length);
- if (length > 0) {
- nameHashPtr = Tcl_FindHashEntry(&nameTable, tokenVal);
- if (nameHashPtr == NULL) {
- resourceId = ckalloc(length + 1);
- memcpy(resourceId, tokenVal, length);
- resourceId[length] = '\0';
- }
- }
- }
-
- if (resourceId == NULL) {
- resourceId = (char *) ckalloc(15);
- sprintf(resourceId, "resource%d", newId);
- }
-
- Tcl_SetHashValue(resourceHashPtr, resourceId);
- newId++;
-
- nameHashPtr = Tcl_CreateHashEntry(&nameTable, resourceId, &new);
- if (!new) {
- panic("resource id has repeated itself");
- }
-
- resourceRef = (OpenResourceFork *) ckalloc(sizeof(OpenResourceFork));
- resourceRef->fileRef = fileRef;
- resourceRef->flags = flags;
-
- Tcl_SetHashValue(nameHashPtr, (ClientData) resourceRef);
- if (tokenPtr != NULL) {
- Tcl_SetStringObj(tokenPtr, resourceId, -1);
- }
-
- if (flags & TCL_RESOURCE_INSERT_TAIL) {
- Tcl_ListObjAppendElement(NULL, resourceForkList, tokenPtr);
- } else {
- Tcl_ListObjReplace(NULL, resourceForkList, 0, 0, 1, &tokenPtr);
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclMacUnRegisterResourceFork --
- *
- * Removes the entry for an open resource fork from the table of
- * open resources managed by the procedures in this file.
- * If resultPtr is not NULL, it will be used for error reporting.
- *
- * Results:
- * The fileRef for this token, or -1 if an error occured.
- *
- * Side effects:
- * An entry is removed from the resource name table.
- *
- *----------------------------------------------------------------------
- */
-
-short
-TclMacUnRegisterResourceFork(
- char *tokenPtr,
- Tcl_Obj *resultPtr)
-
-{
- Tcl_HashEntry *resourceHashPtr;
- Tcl_HashEntry *nameHashPtr;
- OpenResourceFork *resourceRef;
- char *resourceId = NULL;
- short fileRef;
- char *bytes;
- int i, match, index, listLen, length, elemLen;
- Tcl_Obj **elemPtrs;
-
-
- nameHashPtr = Tcl_FindHashEntry(&nameTable, tokenPtr);
- if (nameHashPtr == NULL) {
- if (resultPtr != NULL) {
- Tcl_AppendStringsToObj(resultPtr,
- "invalid resource file reference \"",
- tokenPtr, "\"", (char *) NULL);
- }
- return -1;
- }
-
- resourceRef = (OpenResourceFork *) Tcl_GetHashValue(nameHashPtr);
- fileRef = resourceRef->fileRef;
-
- if ( resourceRef->flags & TCL_RESOURCE_DONT_CLOSE ) {
- if (resultPtr != NULL) {
- Tcl_AppendStringsToObj(resultPtr,
- "can't close \"", tokenPtr, "\" resource file",
- (char *) NULL);
- }
- return -1;
- }
-
- Tcl_DeleteHashEntry(nameHashPtr);
- ckfree((char *) resourceRef);
-
-
- /*
- * Now remove the resource from the resourceForkList object
- */
-
- Tcl_ListObjGetElements(NULL, resourceForkList, &listLen, &elemPtrs);
-
-
- index = -1;
- length = strlen(tokenPtr);
-
- for (i = 0; i < listLen; i++) {
- match = 0;
- bytes = Tcl_GetStringFromObj(elemPtrs[i], &elemLen);
- if (length == elemLen) {
- match = (memcmp(bytes, tokenPtr,
- (size_t) length) == 0);
- }
- if (match) {
- index = i;
- break;
- }
- }
- if (!match) {
- panic("the resource Fork List is out of synch!");
- }
-
- Tcl_ListObjReplace(NULL, resourceForkList, index, 1, 0, NULL);
-
- resourceHashPtr = Tcl_FindHashEntry(&resourceTable, (char *) fileRef);
-
- if (resourceHashPtr == NULL) {
- panic("Resource & Name tables are out of synch in resource command.");
- }
- ckfree(Tcl_GetHashValue(resourceHashPtr));
- Tcl_DeleteHashEntry(resourceHashPtr);
-
- return fileRef;
-
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * BuildResourceForkList --
- *
- * Traverses the list of open resource forks, and builds the
- * list of resources forks. Also creates a resource token for any that
- * are opened but not registered with our resource system.
- * This is based on code from Apple DTS.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The list of resource forks is updated.
- * The resource name table may be augmented.
- *
- *----------------------------------------------------------------------
- */
-
-void
-BuildResourceForkList()
-{
- Handle currentMapHandle, mSysMapHandle;
- Ptr tempPtr;
- FCBPBRec fileRec;
- char fileName[256];
- char appName[62];
- Tcl_Obj *nameObj;
- OSErr err;
- ProcessSerialNumber psn;
- ProcessInfoRec info;
- FSSpec fileSpec;
-
- /*
- * Get the application name, so we can substitute
- * the token "application" for the application's resource.
- */
-
- GetCurrentProcess(&psn);
- info.processInfoLength = sizeof(ProcessInfoRec);
- info.processName = (StringPtr) &appName;
- info.processAppSpec = &fileSpec;
- GetProcessInformation(&psn, &info);
- p2cstr((StringPtr) appName);
-
-
- fileRec.ioCompletion = NULL;
- fileRec.ioVRefNum = 0;
- fileRec.ioFCBIndx = 0;
- fileRec.ioNamePtr = (StringPtr) &fileName;
-
-
- currentMapHandle = LMGetTopMapHndl();
- mSysMapHandle = LMGetSysMapHndl();
-
- while (1) {
- /*
- * Now do the ones opened after the application.
- */
-
- nameObj = Tcl_NewObj();
-
- tempPtr = *currentMapHandle;
-
- fileRec.ioRefNum = *((short *) (tempPtr + 20));
- err = PBGetFCBInfo(&fileRec, false);
-
- if (err != noErr) {
- /*
- * The ROM resource map does not correspond to an opened file...
- */
- Tcl_SetStringObj(nameObj, "ROM Map", -1);
- } else {
- p2cstr((StringPtr) fileName);
- if (strcmp(fileName,appName) == 0) {
- Tcl_SetStringObj(nameObj, "application", -1);
- } else {
- Tcl_SetStringObj(nameObj, fileName, -1);
- }
- c2pstr(fileName);
- }
-
- TclMacRegisterResourceFork(fileRec.ioRefNum, nameObj,
- TCL_RESOURCE_DONT_CLOSE | TCL_RESOURCE_INSERT_TAIL);
-
- if (currentMapHandle == mSysMapHandle) {
- break;
- }
-
- currentMapHandle = *((Handle *) (tempPtr + 16));
- }
-}
diff --git a/mac/tclMacResource.r b/mac/tclMacResource.r
deleted file mode 100644
index 766bc96..0000000
--- a/mac/tclMacResource.r
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * tclMacResource.r --
- *
- * This file creates resources for use in a simple shell.
- * This is designed to be an example of using the Tcl libraries
- * statically in a Macintosh Application. For an example of
- * of using the dynamic libraries look at tclMacApplication.r.
- *
- * Copyright (c) 1993-94 Lockheed Missle & Space Company
- * Copyright (c) 1994-97 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include <Types.r>
-#include <SysTypes.r>
-
-/*
- * The folowing include and defines help construct
- * the version string for Tcl.
- */
-
-#define RC_INVOKED
-#include "tcl.h"
-
-/*
- * The mechanisim below loads Tcl source into the resource fork of the
- * application. The example below creates a TEXT resource named
- * "Init" from the file "init.tcl". This allows applications to use
- * Tcl to define the behavior of the application without having to
- * require some predetermined file structure - all needed Tcl "files"
- * are located within the application. To source a file for the
- * resource fork the source command has been modified to support
- * sourcing from resources. In the below case "source -rsrc {Init}"
- * will load the TEXT resource named "Init".
- */
-
-#ifndef TCLTK_NO_LIBRARY_TEXT_RESOURCES
-#include "tclMacTclCode.r"
-#endif
-
diff --git a/mac/tclMacSock.c b/mac/tclMacSock.c
deleted file mode 100644
index f2bd171..0000000
--- a/mac/tclMacSock.c
+++ /dev/null
@@ -1,2788 +0,0 @@
-/*
- * tclMacSock.c
- *
- * Channel drivers for Macintosh sockets.
- *
- * Copyright (c) 1996-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include "tclInt.h"
-#include "tclPort.h"
-#include "tclMacInt.h"
-#include <AddressXlation.h>
-#include <Aliases.h>
-#undef Status
-#include <Devices.h>
-#include <Errors.h>
-#include <Events.h>
-#include <Files.h>
-#include <Gestalt.h>
-#include <MacTCP.h>
-#include <Processes.h>
-#include <Strings.h>
-
-/*
- * The following variable is used to tell whether this module has been
- * initialized.
- */
-
-static int initialized = 0;
-
-/*
- * If debugging is on we may drop into the debugger to handle certain cases
- * that are not supposed to happen. Otherwise, we change ignore the error
- * and most code should handle such errors ok.
- */
-
-#ifndef TCL_DEBUG
- #define Debugger()
-#endif
-
-/*
- * The preferred buffer size for Macintosh channels.
- */
-
-#define CHANNEL_BUF_SIZE 8192
-
-/*
- * Port information structure. Used to match service names
- * to a Tcp/Ip port number.
- */
-
-typedef struct {
- char *name; /* Name of service. */
- int port; /* Port number. */
-} PortInfo;
-
-/*
- * This structure describes per-instance state of a tcp based channel.
- */
-
-typedef struct TcpState {
- TCPiopb pb; /* Parameter block used by this stream.
- * This must be in the first position. */
- ProcessSerialNumber psn; /* PSN used to wake up process. */
- StreamPtr tcpStream; /* Macintosh tcp stream pointer. */
- int port; /* The port we are connected to. */
- int flags; /* Bit field comprised of the flags
- * described below. */
- int checkMask; /* OR'ed combination of TCL_READABLE and
- * TCL_WRITABLE as set by an asynchronous
- * event handler. */
- int watchMask; /* OR'ed combination of TCL_READABLE and
- * TCL_WRITABLE as set by TcpWatch. */
- Tcl_TcpAcceptProc *acceptProc; /* Proc to call on accept. */
- ClientData acceptProcData; /* The data for the accept proc. */
- wdsEntry dataSegment[2]; /* List of buffers to be written async. */
- rdsEntry rdsarray[5+1]; /* Array used when cleaning out recieve
- * buffers on a closing socket. */
- Tcl_Channel channel; /* Channel associated with this socket. */
- int writeBufferSize; /* Size of buffer to hold data for
- * asynchronous writes. */
- void *writeBuffer; /* Buffer for async write data. */
- struct TcpState *nextPtr; /* The next socket on the global socket
- * list. */
-} TcpState;
-
-/*
- * This structure is used by domain name resolver callback.
- */
-
-typedef struct DNRState {
- struct hostInfo hostInfo; /* Data structure used by DNR functions. */
- int done; /* Flag to determine when we are done. */
- ProcessSerialNumber psn; /* Process to wake up when we are done. */
-} DNRState;
-
-/*
- * The following macros may be used to set the flags field of
- * a TcpState structure.
- */
-
-#define TCP_ASYNC_SOCKET (1<<0) /* The socket is in async mode. */
-#define TCP_ASYNC_CONNECT (1<<1) /* The socket is trying to connect. */
-#define TCP_CONNECTED (1<<2) /* The socket is connected. */
-#define TCP_PENDING (1<<3) /* A SocketEvent is on the queue. */
-#define TCP_LISTENING (1<<4) /* This socket is listening for
- * a connection. */
-#define TCP_LISTEN_CONNECT (1<<5) /* Someone has connect to the
- * listening port. */
-#define TCP_REMOTE_CLOSED (1<<6) /* The remote side has closed
- * the connection. */
-#define TCP_RELEASE (1<<7) /* The socket may now be released. */
-#define TCP_WRITING (1<<8) /* A background write is in progress. */
-#define TCP_SERVER_ZOMBIE (1<<9) /* The server can no longer accept connects. */
-
-/*
- * The following structure is what is added to the Tcl event queue when
- * a socket event occurs.
- */
-
-typedef struct SocketEvent {
- Tcl_Event header; /* Information that is standard for
- * all events. */
- TcpState *statePtr; /* Socket descriptor that is ready. */
- StreamPtr tcpStream; /* Low level Macintosh stream. */
-} SocketEvent;
-
-/*
- * Static routines for this file:
- */
-
-static pascal void CleanUpExitProc _ANSI_ARGS_((void));
-static void ClearZombieSockets _ANSI_ARGS_((void));
-static void CloseCompletionRoutine _ANSI_ARGS_((TCPiopb *pb));
-static TcpState * CreateSocket _ANSI_ARGS_((Tcl_Interp *interp,
- int port, CONST char *host, CONST char *myAddr,
- int myPort, int server, int async));
-static pascal void DNRCompletionRoutine _ANSI_ARGS_((
- struct hostInfo *hostinfoPtr,
- DNRState *dnrStatePtr));
-static void FreeSocketInfo _ANSI_ARGS_((TcpState *statePtr));
-static long GetBufferSize _ANSI_ARGS_((void));
-static OSErr GetHostFromString _ANSI_ARGS_((CONST char *name,
- ip_addr *address));
-static OSErr GetLocalAddress _ANSI_ARGS_((unsigned long *addr));
-static void IOCompletionRoutine _ANSI_ARGS_((TCPiopb *pb));
-static void InitMacTCPParamBlock _ANSI_ARGS_((TCPiopb *pBlock,
- int csCode));
-static void InitSockets _ANSI_ARGS_((void));
-static TcpState * NewSocketInfo _ANSI_ARGS_((StreamPtr stream));
-static OSErr ResolveAddress _ANSI_ARGS_((ip_addr tcpAddress,
- Tcl_DString *dsPtr));
-static void SocketCheckProc _ANSI_ARGS_((ClientData clientData,
- int flags));
-static int SocketEventProc _ANSI_ARGS_((Tcl_Event *evPtr,
- int flags));
-static void SocketFreeProc _ANSI_ARGS_((ClientData clientData));
-static int SocketReady _ANSI_ARGS_((TcpState *statePtr));
-static void SocketSetupProc _ANSI_ARGS_((ClientData clientData,
- int flags));
-static void TcpAccept _ANSI_ARGS_((TcpState *statePtr));
-static int TcpBlockMode _ANSI_ARGS_((ClientData instanceData, int mode));
-static int TcpClose _ANSI_ARGS_((ClientData instanceData,
- Tcl_Interp *interp));
-static int TcpGetHandle _ANSI_ARGS_((ClientData instanceData,
- int direction, ClientData *handlePtr));
-static int TcpGetOptionProc _ANSI_ARGS_((ClientData instanceData,
- Tcl_Interp *interp, CONST char *optionName,
- Tcl_DString *dsPtr));
-static int TcpInput _ANSI_ARGS_((ClientData instanceData,
- char *buf, int toRead, int *errorCodePtr));
-static int TcpOutput _ANSI_ARGS_((ClientData instanceData,
- CONST char *buf, int toWrite, int *errorCodePtr));
-static void TcpWatch _ANSI_ARGS_((ClientData instanceData,
- int mask));
-static int WaitForSocketEvent _ANSI_ARGS_((TcpState *infoPtr,
- int mask, int *errorCodePtr));
-
-pascal void NotifyRoutine (
- StreamPtr tcpStream,
- unsigned short eventCode,
- Ptr userDataPtr,
- unsigned short terminReason,
- struct ICMPReport *icmpMsg);
-
-/*
- * This structure describes the channel type structure for TCP socket
- * based IO:
- */
-
-static Tcl_ChannelType tcpChannelType = {
- "tcp", /* Type name. */
- (Tcl_ChannelTypeVersion)TcpBlockMode, /* Set blocking or
- * non-blocking mode.*/
- TcpClose, /* Close proc. */
- TcpInput, /* Input proc. */
- TcpOutput, /* Output proc. */
- NULL, /* Seek proc. */
- NULL, /* Set option proc. */
- TcpGetOptionProc, /* Get option proc. */
- TcpWatch, /* Initialize notifier. */
- TcpGetHandle /* Get handles out of channel. */
-};
-
-/*
- * Universal Procedure Pointers (UPP) for various callback
- * routines used by MacTcp code.
- */
-
-ResultUPP resultUPP = NULL;
-TCPIOCompletionUPP completeUPP = NULL;
-TCPIOCompletionUPP closeUPP = NULL;
-TCPNotifyUPP notifyUPP = NULL;
-
-/*
- * Built-in commands, and the procedures associated with them:
- */
-
-static PortInfo portServices[] = {
- {"echo", 7},
- {"discard", 9},
- {"systat", 11},
- {"daytime", 13},
- {"netstat", 15},
- {"chargen", 19},
- {"ftp-data", 20},
- {"ftp", 21},
- {"telnet", 23},
- {"telneto", 24},
- {"smtp", 25},
- {"time", 37},
- {"whois", 43},
- {"domain", 53},
- {"gopher", 70},
- {"finger", 79},
- {"hostnames", 101},
- {"sunrpc", 111},
- {"nntp", 119},
- {"exec", 512},
- {"login", 513},
- {"shell", 514},
- {"printer", 515},
- {"courier", 530},
- {"uucp", 540},
- {NULL, 0},
-};
-
-typedef struct ThreadSpecificData {
- /*
- * Every open socket has an entry on the following list.
- */
-
- TcpState *socketList;
-} ThreadSpecificData;
-
-static Tcl_ThreadDataKey dataKey;
-
-/*
- * Globals for holding information about OS support for sockets.
- */
-
-static int socketsTestInited = false;
-static int hasSockets = false;
-static short driverRefNum = 0;
-static int socketNumber = 0;
-static int socketBufferSize = CHANNEL_BUF_SIZE;
-static ProcessSerialNumber applicationPSN;
-
-/*
- *----------------------------------------------------------------------
- *
- * InitSockets --
- *
- * Load the MacTCP driver and open the name resolver. We also
- * create several UPP's used by our code. Lastly, we install
- * a patch to ExitToShell to clean up socket connections if
- * we are about to exit.
- *
- * Results:
- * 1 if successful, 0 on failure.
- *
- * Side effects:
- * Creates a new event source, loads the MacTCP driver,
- * registers an exit to shell callback.
- *
- *----------------------------------------------------------------------
- */
-
-#define gestaltMacTCPVersion 'mtcp'
-static void
-InitSockets()
-{
- ParamBlockRec pb;
- OSErr err;
- long response;
- ThreadSpecificData *tsdPtr;
-
- if (! initialized) {
- /*
- * Do process wide initialization.
- */
-
- initialized = 1;
-
- if (Gestalt(gestaltMacTCPVersion, &response) == noErr) {
- hasSockets = true;
- } else {
- hasSockets = false;
- }
-
- if (!hasSockets) {
- return;
- }
-
- /*
- * Load MacTcp driver and name server resolver.
- */
-
-
- pb.ioParam.ioCompletion = 0L;
- pb.ioParam.ioNamePtr = "\p.IPP";
- pb.ioParam.ioPermssn = fsCurPerm;
- err = PBOpenSync(&pb);
- if (err != noErr) {
- hasSockets = 0;
- return;
- }
- driverRefNum = pb.ioParam.ioRefNum;
-
- socketBufferSize = GetBufferSize();
- err = OpenResolver(NULL);
- if (err != noErr) {
- hasSockets = 0;
- return;
- }
-
- GetCurrentProcess(&applicationPSN);
- /*
- * Create UPP's for various callback routines.
- */
-
- resultUPP = NewResultProc(DNRCompletionRoutine);
- completeUPP = NewTCPIOCompletionProc(IOCompletionRoutine);
- closeUPP = NewTCPIOCompletionProc(CloseCompletionRoutine);
- notifyUPP = NewTCPNotifyProc(NotifyRoutine);
-
- /*
- * Install an ExitToShell patch. We use this patch instead
- * of the Tcl exit mechanism because we need to ensure that
- * these routines are cleaned up even if we crash or are forced
- * to quit. There are some circumstances when the Tcl exit
- * handlers may not fire.
- */
-
- TclMacInstallExitToShellPatch(CleanUpExitProc);
- }
-
- /*
- * Do per-thread initialization.
- */
-
- tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
- if (tsdPtr == NULL) {
- tsdPtr = TCL_TSD_INIT(&dataKey);
- tsdPtr->socketList = NULL;
- Tcl_CreateEventSource(SocketSetupProc, SocketCheckProc, NULL);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpFinalizeSockets --
- *
- * Invoked during exit clean up to deinitialize the socket module.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Removed event source.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpFinalizeSockets()
-{
- ThreadSpecificData *tsdPtr;
-
- tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
- if (tsdPtr != NULL) {
- Tcl_DeleteEventSource(SocketSetupProc, SocketCheckProc, NULL);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpHasSockets --
- *
- * This function determines whether sockets are available on the
- * current system and returns an error in interp if they are not.
- * Note that interp may be NULL.
- *
- * Results:
- * Returns TCL_OK if the system supports sockets, or TCL_ERROR with
- * an error in interp.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclpHasSockets(
- Tcl_Interp *interp) /* Interp for error messages. */
-{
- InitSockets();
-
- if (hasSockets) {
- return TCL_OK;
- }
- if (interp != NULL) {
- Tcl_AppendResult(interp, "sockets are not available on this system",
- NULL);
- }
- return TCL_ERROR;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * SocketSetupProc --
- *
- * This procedure is invoked before Tcl_DoOneEvent blocks waiting
- * for an event.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Adjusts the block time if needed.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-SocketSetupProc(
- ClientData data, /* Not used. */
- int flags) /* Event flags as passed to Tcl_DoOneEvent. */
-{
- TcpState *statePtr;
- Tcl_Time blockTime = { 0, 0 };
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
- if (!(flags & TCL_FILE_EVENTS)) {
- return;
- }
-
- /*
- * Check to see if there is a ready socket. If so, poll.
- */
-
- for (statePtr = tsdPtr->socketList; statePtr != NULL;
- statePtr = statePtr->nextPtr) {
- if (statePtr->flags & TCP_RELEASE) {
- continue;
- }
- if (SocketReady(statePtr)) {
- Tcl_SetMaxBlockTime(&blockTime);
- break;
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * SocketCheckProc --
- *
- * This procedure is called by Tcl_DoOneEvent to check the socket
- * event source for events.
- *
- * Results:
- * None.
- *
- * Side effects:
- * May queue an event.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-SocketCheckProc(
- ClientData data, /* Not used. */
- int flags) /* Event flags as passed to Tcl_DoOneEvent. */
-{
- TcpState *statePtr;
- SocketEvent *evPtr;
- TcpState dummyState;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
- if (!(flags & TCL_FILE_EVENTS)) {
- return;
- }
-
- /*
- * Queue events for any ready sockets that don't already have events
- * queued (caused by persistent states that won't generate WinSock
- * events).
- */
-
- for (statePtr = tsdPtr->socketList; statePtr != NULL;
- statePtr = statePtr->nextPtr) {
- /*
- * Check to see if this socket is dead and needs to be cleaned
- * up. We use a dummy statePtr whose only valid field is the
- * nextPtr to allow the loop to continue even if the element
- * is deleted.
- */
-
- if (statePtr->flags & TCP_RELEASE) {
- if (!(statePtr->flags & TCP_PENDING)) {
- dummyState.nextPtr = statePtr->nextPtr;
- SocketFreeProc(statePtr);
- statePtr = &dummyState;
- }
- continue;
- }
-
- if (!(statePtr->flags & TCP_PENDING) && SocketReady(statePtr)) {
- statePtr->flags |= TCP_PENDING;
- evPtr = (SocketEvent *) ckalloc(sizeof(SocketEvent));
- evPtr->header.proc = SocketEventProc;
- evPtr->statePtr = statePtr;
- evPtr->tcpStream = statePtr->tcpStream;
- Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL);
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * SocketReady --
- *
- * This function checks the current state of a socket to see
- * if any interesting conditions are present.
- *
- * Results:
- * Returns 1 if an event that someone is watching is present, else
- * returns 0.
- *
- * Side effects:
- * Updates the checkMask for the socket to reflect any newly
- * detected events.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-SocketReady(
- TcpState *statePtr)
-{
- TCPiopb statusPB;
- int foundSomething = 0;
- int didStatus = 0;
- int amount;
- OSErr err;
-
- if (statePtr->flags & TCP_LISTEN_CONNECT) {
- foundSomething = 1;
- statePtr->checkMask |= TCL_READABLE;
- }
- if (statePtr->watchMask & TCL_READABLE) {
- if (statePtr->checkMask & TCL_READABLE) {
- foundSomething = 1;
- } else if (statePtr->flags & TCP_CONNECTED) {
- statusPB.ioCRefNum = driverRefNum;
- statusPB.tcpStream = statePtr->tcpStream;
- statusPB.csCode = TCPStatus;
- err = PBControlSync((ParmBlkPtr) &statusPB);
- didStatus = 1;
-
- /*
- * We make the fchannel readable if 1) we get an error,
- * 2) there is more data available, or 3) we detect
- * that a close from the remote connection has arrived.
- */
-
- if ((err != noErr) ||
- (statusPB.csParam.status.amtUnreadData > 0) ||
- (statusPB.csParam.status.connectionState == 14)) {
- statePtr->checkMask |= TCL_READABLE;
- foundSomething = 1;
- }
- }
- }
- if (statePtr->watchMask & TCL_WRITABLE) {
- if (statePtr->checkMask & TCL_WRITABLE) {
- foundSomething = 1;
- } else if (statePtr->flags & TCP_CONNECTED) {
- if (!didStatus) {
- statusPB.ioCRefNum = driverRefNum;
- statusPB.tcpStream = statePtr->tcpStream;
- statusPB.csCode = TCPStatus;
- err = PBControlSync((ParmBlkPtr) &statusPB);
- }
-
- /*
- * If there is an error or there if there is room to
- * send more data we make the channel writeable.
- */
-
- amount = statusPB.csParam.status.sendWindow -
- statusPB.csParam.status.amtUnackedData;
- if ((err != noErr) || (amount > 0)) {
- statePtr->checkMask |= TCL_WRITABLE;
- foundSomething = 1;
- }
- }
- }
- return foundSomething;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * InitMacTCPParamBlock--
- *
- * Initialize a MacTCP parameter block.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Initializes the parameter block.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-InitMacTCPParamBlock(
- TCPiopb *pBlock, /* Tcp parmeter block. */
- int csCode) /* Tcp operation code. */
-{
- memset(pBlock, 0, sizeof(TCPiopb));
- pBlock->ioResult = 1;
- pBlock->ioCRefNum = driverRefNum;
- pBlock->csCode = (short) csCode;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TcpBlockMode --
- *
- * Set blocking or non-blocking mode on channel.
- *
- * Results:
- * 0 if successful, errno when failed.
- *
- * Side effects:
- * Sets the device into blocking or non-blocking mode.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-TcpBlockMode(
- ClientData instanceData, /* Channel state. */
- int mode) /* The mode to set. */
-{
- TcpState *statePtr = (TcpState *) instanceData;
-
- if (mode == TCL_MODE_BLOCKING) {
- statePtr->flags &= ~TCP_ASYNC_SOCKET;
- } else {
- statePtr->flags |= TCP_ASYNC_SOCKET;
- }
- return 0;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TcpClose --
- *
- * Close the socket.
- *
- * Results:
- * 0 if successful, the value of errno if failed.
- *
- * Side effects:
- * Closes the socket.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-TcpClose(
- ClientData instanceData, /* The socket to close. */
- Tcl_Interp *interp) /* Interp for error messages. */
-{
- TcpState *statePtr = (TcpState *) instanceData;
- StreamPtr tcpStream;
- TCPiopb closePB;
- OSErr err;
-
- tcpStream = statePtr->tcpStream;
- statePtr->flags &= ~TCP_CONNECTED;
-
- /*
- * If this is a server socket we can't use the statePtr
- * param block because it is in use. However, we can
- * close syncronously.
- */
-
- if ((statePtr->flags & TCP_LISTENING) ||
- (statePtr->flags & TCP_LISTEN_CONNECT)) {
- InitMacTCPParamBlock(&closePB, TCPClose);
- closePB.tcpStream = tcpStream;
- closePB.ioCompletion = NULL;
- closePB.csParam.close.ulpTimeoutValue = 60 /* seconds */;
- closePB.csParam.close.ulpTimeoutAction = 1 /* 1:abort 0:report */;
- closePB.csParam.close.validityFlags = timeoutValue | timeoutAction;
- err = PBControlSync((ParmBlkPtr) &closePB);
- if (err != noErr) {
- Debugger();
- goto afterRelease;
- /* panic("error closing server socket"); */
- }
- statePtr->flags |= TCP_RELEASE;
-
- /*
- * Server sockets are closed sync. Therefor, we know it is OK to
- * release the socket now.
- */
-
- InitMacTCPParamBlock(&statePtr->pb, TCPRelease);
- statePtr->pb.tcpStream = statePtr->tcpStream;
- err = PBControlSync((ParmBlkPtr) &statePtr->pb);
- if (err != noErr) {
- panic("error releasing server socket");
- }
-
- /*
- * Free the buffer space used by the socket and the
- * actual socket state data structure.
- */
- afterRelease:
-
- /*
- * Have to check whether the pointer is NULL, since we could get here
- * on a failed socket open, and then the rcvBuff would never have been
- * allocated.
- */
-
- if (err == noErr) {
- ckfree((char *) statePtr->pb.csParam.create.rcvBuff);
- }
- FreeSocketInfo(statePtr);
- return 0;
- }
-
- /*
- * If this socket is in the midddle on async connect we can just
- * abort the connect and release the stream right now.
- */
-
- if (statePtr->flags & TCP_ASYNC_CONNECT) {
- InitMacTCPParamBlock(&closePB, TCPClose);
- closePB.tcpStream = tcpStream;
- closePB.ioCompletion = NULL;
- err = PBControlSync((ParmBlkPtr) &closePB);
- if (err == noErr) {
- statePtr->flags |= TCP_RELEASE;
-
- InitMacTCPParamBlock(&closePB, TCPRelease);
- closePB.tcpStream = tcpStream;
- closePB.ioCompletion = NULL;
-
- err = PBControlSync((ParmBlkPtr) &closePB);
- }
-
- /*
- * Free the buffer space used by the socket and the
- * actual socket state data structure. However, if the
- * RELEASE returns an error, then the rcvBuff is usually
- * bad, so we can't release it. I think this means we will
- * leak the buffer, so in the future, we may want to track the
- * buffers separately, and nuke them on our own (or just not
- * use MacTCP!).
- */
-
- if (err == noErr) {
- ckfree((char *) closePB.csParam.create.rcvBuff);
- }
-
- FreeSocketInfo(statePtr);
- return err;
- }
-
- /*
- * Client sockets:
- * If a background write is in progress, don't close
- * the socket yet. The completion routine for the
- * write will take care of it.
- */
-
- if (!(statePtr->flags & TCP_WRITING)) {
- InitMacTCPParamBlock(&statePtr->pb, TCPClose);
- statePtr->pb.tcpStream = tcpStream;
- statePtr->pb.ioCompletion = closeUPP;
- statePtr->pb.csParam.close.userDataPtr = (Ptr) statePtr;
- err = PBControlAsync((ParmBlkPtr) &statePtr->pb);
- if (err != noErr) {
- Debugger();
- statePtr->flags |= TCP_RELEASE;
- /* return 0; */
- }
- }
-
- SocketFreeProc(instanceData);
- return 0;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * CloseCompletionRoutine --
- *
- * Handles the close protocol for a Tcp socket. This will do
- * a series of calls to release all data currently buffered for
- * the socket. This is important to do to as it allows the remote
- * connection to recieve and issue it's own close on the socket.
- * Note that this function is running at interupt time and can't
- * allocate memory or do much else except set state.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The buffers for the socket are flushed.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-CloseCompletionRoutine(
- TCPiopb *pbPtr) /* Tcp parameter block. */
-{
- TcpState *statePtr;
- OSErr err;
-
- if (pbPtr->csCode == TCPClose) {
- statePtr = (TcpState *) (pbPtr->csParam.close.userDataPtr);
- } else {
- statePtr = (TcpState *) (pbPtr->csParam.receive.userDataPtr);
- }
-
- /*
- * It's very bad if the statePtr is nNULL - we should probably panic...
- */
-
- if (statePtr == NULL) {
- Debugger();
- return;
- }
-
- WakeUpProcess(&statePtr->psn);
-
- /*
- * If there is an error we assume the remote side has already
- * close. We are done closing as soon as we decide that the
- * remote connection has closed.
- */
-
- if (pbPtr->ioResult != noErr) {
- statePtr->flags |= TCP_RELEASE;
- return;
- }
- if (statePtr->flags & TCP_REMOTE_CLOSED) {
- statePtr->flags |= TCP_RELEASE;
- return;
- }
-
- /*
- * If we just did a recieve we need to return the buffers.
- * Otherwise, attempt to recieve more data until we recieve an
- * error (usually because we have no more data).
- */
-
- if (statePtr->pb.csCode == TCPNoCopyRcv) {
- InitMacTCPParamBlock(&statePtr->pb, TCPRcvBfrReturn);
- statePtr->pb.tcpStream = statePtr->tcpStream;
- statePtr->pb.ioCompletion = closeUPP;
- statePtr->pb.csParam.receive.rdsPtr = (Ptr) statePtr->rdsarray;
- statePtr->pb.csParam.receive.userDataPtr = (Ptr) statePtr;
- err = PBControlAsync((ParmBlkPtr) &statePtr->pb);
- } else {
- InitMacTCPParamBlock(&statePtr->pb, TCPNoCopyRcv);
- statePtr->pb.tcpStream = statePtr->tcpStream;
- statePtr->pb.ioCompletion = closeUPP;
- statePtr->pb.csParam.receive.commandTimeoutValue = 1;
- statePtr->pb.csParam.receive.rdsPtr = (Ptr) statePtr->rdsarray;
- statePtr->pb.csParam.receive.rdsLength = 5;
- statePtr->pb.csParam.receive.userDataPtr = (Ptr) statePtr;
- err = PBControlAsync((ParmBlkPtr) &statePtr->pb);
- }
-
- if (err != noErr) {
- statePtr->flags |= TCP_RELEASE;
- }
-}
-/*
- *----------------------------------------------------------------------
- *
- * SocketFreeProc --
- *
- * This callback is invoked in order to delete
- * the notifier data associated with a file handle.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Removes the SocketInfo from the global socket list.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-SocketFreeProc(
- ClientData clientData) /* Channel state. */
-{
- TcpState *statePtr = (TcpState *) clientData;
- OSErr err;
- TCPiopb statusPB;
-
- /*
- * Get the status of this connection. We need to do a
- * few tests to see if it's OK to release the stream now.
- */
-
- if (!(statePtr->flags & TCP_RELEASE)) {
- return;
- }
- statusPB.ioCRefNum = driverRefNum;
- statusPB.tcpStream = statePtr->tcpStream;
- statusPB.csCode = TCPStatus;
- err = PBControlSync((ParmBlkPtr) &statusPB);
- if ((statusPB.csParam.status.connectionState == 0) ||
- (statusPB.csParam.status.connectionState == 2)) {
- /*
- * If the conection state is 0 then this was a client
- * connection and it's closed. If it is 2 then this a
- * server client and we may release it. If it isn't
- * one of those values then we return and we'll try to
- * clean up later.
- */
-
- } else {
- return;
- }
-
- /*
- * The Close request is made async. We know it's
- * OK to release the socket when the TCP_RELEASE flag
- * gets set.
- */
-
- InitMacTCPParamBlock(&statePtr->pb, TCPRelease);
- statePtr->pb.tcpStream = statePtr->tcpStream;
- err = PBControlSync((ParmBlkPtr) &statePtr->pb);
- if (err != noErr) {
- Debugger(); /* Ignoreing leaves stranded stream. Is there an
- alternative? */
- }
-
- /*
- * Free the buffer space used by the socket and the
- * actual socket state data structure.
- */
-
- ckfree((char *) statePtr->pb.csParam.create.rcvBuff);
- FreeSocketInfo(statePtr);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TcpInput --
- *
- * Reads input from the IO channel into the buffer given. Returns
- * count of how many bytes were actually read, and an error
- * indication.
- *
- * Results:
- * A count of how many bytes were read is returned. A value of -1
- * implies an error occured. A value of zero means we have reached
- * the end of data (EOF).
- *
- * Side effects:
- * Reads input from the actual channel.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TcpInput(
- ClientData instanceData, /* Channel state. */
- char *buf, /* Where to store data read. */
- int bufSize, /* How much space is available
- * in the buffer? */
- int *errorCodePtr) /* Where to store error code. */
-{
- TcpState *statePtr = (TcpState *) instanceData;
- StreamPtr tcpStream;
- OSErr err;
- TCPiopb statusPB;
- int toRead, dataAvail;
-
- *errorCodePtr = 0;
- errno = 0;
- tcpStream = statePtr->tcpStream;
-
- if (bufSize == 0) {
- return 0;
- }
- toRead = bufSize;
-
- /*
- * First check to see if EOF was already detected, to prevent
- * calling the socket stack after the first time EOF is detected.
- */
-
- if (statePtr->flags & TCP_REMOTE_CLOSED) {
- return 0;
- }
-
- /*
- * If an asynchronous connect is in progress, attempt to wait for it
- * to complete before reading.
- */
-
- if ((statePtr->flags & TCP_ASYNC_CONNECT)
- && ! WaitForSocketEvent(statePtr, TCL_READABLE, errorCodePtr)) {
- return -1;
- }
-
- /*
- * No EOF, and it is connected, so try to read more from the socket.
- * If the socket is blocking, we keep trying until there is data
- * available or the socket is closed.
- */
-
- while (1) {
-
- statusPB.ioCRefNum = driverRefNum;
- statusPB.tcpStream = tcpStream;
- statusPB.csCode = TCPStatus;
- err = PBControlSync((ParmBlkPtr) &statusPB);
- if (err != noErr) {
- Debugger();
- statePtr->flags |= TCP_REMOTE_CLOSED;
- return 0; /* EOF */
- }
- dataAvail = statusPB.csParam.status.amtUnreadData;
- if (dataAvail < bufSize) {
- toRead = dataAvail;
- } else {
- toRead = bufSize;
- }
- if (toRead != 0) {
- /*
- * Try to read the data.
- */
-
- InitMacTCPParamBlock(&statusPB, TCPRcv);
- statusPB.tcpStream = tcpStream;
- statusPB.csParam.receive.rcvBuff = buf;
- statusPB.csParam.receive.rcvBuffLen = toRead;
- err = PBControlSync((ParmBlkPtr) &statusPB);
-
- statePtr->checkMask &= ~TCL_READABLE;
- switch (err) {
- case noErr:
- /*
- * The channel remains readable only if this read succeds
- * and we had more data then the size of the buffer we were
- * trying to fill. Use the info from the call to status to
- * determine this.
- */
-
- if (dataAvail > bufSize) {
- statePtr->checkMask |= TCL_READABLE;
- }
- return statusPB.csParam.receive.rcvBuffLen;
- case connectionClosing:
- *errorCodePtr = errno = ESHUTDOWN;
- statePtr->flags |= TCP_REMOTE_CLOSED;
- return 0;
- case connectionDoesntExist:
- case connectionTerminated:
- *errorCodePtr = errno = ENOTCONN;
- statePtr->flags |= TCP_REMOTE_CLOSED;
- return 0;
- case invalidStreamPtr:
- default:
- *errorCodePtr = EINVAL;
- return -1;
- }
- }
-
- /*
- * No data is available, so check the connection state to
- * see why this is the case.
- */
-
- if (statusPB.csParam.status.connectionState == 14) {
- statePtr->flags |= TCP_REMOTE_CLOSED;
- return 0;
- }
- if (statusPB.csParam.status.connectionState != 8) {
- Debugger();
- }
- statePtr->checkMask &= ~TCL_READABLE;
- if (statePtr->flags & TCP_ASYNC_SOCKET) {
- *errorCodePtr = EWOULDBLOCK;
- return -1;
- }
-
- /*
- * In the blocking case, wait until the file becomes readable
- * or closed and try again.
- */
-
- if (!WaitForSocketEvent(statePtr, TCL_READABLE, errorCodePtr)) {
- return -1;
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TcpGetHandle --
- *
- * Called from Tcl_GetChannelHandle to retrieve handles from inside
- * a file based channel.
- *
- * Results:
- * The appropriate handle or NULL if not present.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-TcpGetHandle(
- ClientData instanceData, /* The file state. */
- int direction, /* Which handle to retrieve? */
- ClientData *handlePtr)
-{
- TcpState *statePtr = (TcpState *) instanceData;
-
- *handlePtr = (ClientData) statePtr->tcpStream;
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TcpOutput--
- *
- * Writes the given output on the IO channel. Returns count of how
- * many characters were actually written, and an error indication.
- *
- * Results:
- * A count of how many characters were written is returned and an
- * error indication is returned in an output argument.
- *
- * Side effects:
- * Writes output on the actual channel.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-TcpOutput(
- ClientData instanceData, /* Channel state. */
- CONST char *buf, /* The data buffer. */
- int toWrite, /* How many bytes to write? */
- int *errorCodePtr) /* Where to store error code. */
-{
- TcpState *statePtr = (TcpState *) instanceData;
- StreamPtr tcpStream;
- OSErr err;
- int amount;
- TCPiopb statusPB;
-
- *errorCodePtr = 0;
- tcpStream = statePtr->tcpStream;
-
- /*
- * If an asynchronous connect is in progress, attempt to wait for it
- * to complete before writing.
- */
-
- if ((statePtr->flags & TCP_ASYNC_CONNECT)
- && ! WaitForSocketEvent(statePtr, TCL_WRITABLE, errorCodePtr)) {
- return -1;
- }
-
- /*
- * Loop until we have written some data, or an error occurs.
- */
-
- while (1) {
- statusPB.ioCRefNum = driverRefNum;
- statusPB.tcpStream = tcpStream;
- statusPB.csCode = TCPStatus;
- err = PBControlSync((ParmBlkPtr) &statusPB);
- if ((err == connectionDoesntExist) || ((err == noErr) &&
- (statusPB.csParam.status.connectionState == 14))) {
- /*
- * The remote connection is gone away. Report an error
- * and don't write anything.
- */
-
- *errorCodePtr = errno = EPIPE;
- return -1;
- } else if (err != noErr) {
- return -1;
- }
- amount = statusPB.csParam.status.sendWindow
- - statusPB.csParam.status.amtUnackedData;
-
- /*
- * Attempt to write the data to the socket if a background
- * write isn't in progress and there is room in the output buffers.
- */
-
- if (!(statePtr->flags & TCP_WRITING) && amount > 0) {
- if (toWrite < amount) {
- amount = toWrite;
- }
-
- /* We need to copy the data, otherwise the caller may overwrite
- * the buffer in the middle of our asynchronous call
- */
-
- if (amount > statePtr->writeBufferSize) {
- /*
- * need to grow write buffer
- */
-
- if (statePtr->writeBuffer != (void *) NULL) {
- ckfree(statePtr->writeBuffer);
- }
- statePtr->writeBuffer = (void *) ckalloc(amount);
- statePtr->writeBufferSize = amount;
- }
- memcpy(statePtr->writeBuffer, buf, amount);
- statePtr->dataSegment[0].ptr = statePtr->writeBuffer;
-
- statePtr->dataSegment[0].length = amount;
- statePtr->dataSegment[1].length = 0;
- InitMacTCPParamBlock(&statePtr->pb, TCPSend);
- statePtr->pb.ioCompletion = completeUPP;
- statePtr->pb.tcpStream = tcpStream;
- statePtr->pb.csParam.send.wdsPtr = (Ptr) statePtr->dataSegment;
- statePtr->pb.csParam.send.pushFlag = 1;
- statePtr->pb.csParam.send.userDataPtr = (Ptr) statePtr;
- statePtr->flags |= TCP_WRITING;
- err = PBControlAsync((ParmBlkPtr) &(statePtr->pb));
- switch (err) {
- case noErr:
- return amount;
- case connectionClosing:
- *errorCodePtr = errno = ESHUTDOWN;
- statePtr->flags |= TCP_REMOTE_CLOSED;
- return -1;
- case connectionDoesntExist:
- case connectionTerminated:
- *errorCodePtr = errno = ENOTCONN;
- statePtr->flags |= TCP_REMOTE_CLOSED;
- return -1;
- case invalidStreamPtr:
- default:
- return -1;
- }
-
- }
-
- /*
- * The socket wasn't writable. In the non-blocking case, return
- * immediately, otherwise wait until the file becomes writable
- * or closed and try again.
- */
-
- if (statePtr->flags & TCP_ASYNC_SOCKET) {
- statePtr->checkMask &= ~TCL_WRITABLE;
- *errorCodePtr = EWOULDBLOCK;
- return -1;
- } else if (!WaitForSocketEvent(statePtr, TCL_WRITABLE, errorCodePtr)) {
- return -1;
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TcpGetOptionProc --
- *
- * Computes an option value for a TCP socket based channel, or a
- * list of all options and their values.
- *
- * Note: This code is based on code contributed by John Haxby.
- *
- * Results:
- * A standard Tcl result. The value of the specified option or a
- * list of all options and their values is returned in the
- * supplied DString.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-TcpGetOptionProc(
- ClientData instanceData, /* Socket state. */
- Tcl_Interp *interp, /* For error reporting - can be NULL.*/
- CONST char *optionName, /* Name of the option to
- * retrieve the value for, or
- * NULL to get all options and
- * their values. */
- Tcl_DString *dsPtr) /* Where to store the computed
- * value; initialized by caller. */
-{
- TcpState *statePtr = (TcpState *) instanceData;
- int doPeerName = false, doSockName = false, doError = false, doAll = false;
- ip_addr tcpAddress;
- char buffer[128];
- OSErr err;
- Tcl_DString dString;
- TCPiopb statusPB;
- int errorCode;
- size_t len = 0;
-
- /*
- * If an asynchronous connect is in progress, attempt to wait for it
- * to complete before accessing the socket state.
- */
-
- if ((statePtr->flags & TCP_ASYNC_CONNECT)
- && ! WaitForSocketEvent(statePtr, TCL_WRITABLE, &errorCode)) {
- if (interp) {
- /*
- * fix the error message.
- */
-
- Tcl_AppendResult(interp, "connect is in progress and can't wait",
- NULL);
- }
- return TCL_ERROR;
- }
-
- /*
- * Determine which options we need to do. Do all of them
- * if optionName is NULL.
- */
-
- if (optionName == (CONST char *) NULL || optionName[0] == '\0') {
- doAll = true;
- } else {
- len = strlen(optionName);
- if (!strncmp(optionName, "-peername", len)) {
- doPeerName = true;
- } else if (!strncmp(optionName, "-sockname", len)) {
- doSockName = true;
- } else if (!strncmp(optionName, "-error", len)) {
- /* SF Bug #483575 */
- doError = true;
- } else {
- return Tcl_BadChannelOption(interp, optionName,
- "error peername sockname");
- }
- }
-
- /*
- * SF Bug #483575
- *
- * Return error information. Currently we ignore
- * this option. IOW, we always return the empty
- * string, signaling 'no error'.
- *
- * FIXME: Get a mac/socket expert to write a correct
- * FIXME: implementation.
- */
-
- if (doAll || doError) {
- if (doAll) {
- Tcl_DStringAppendElement(dsPtr, "-error");
- Tcl_DStringAppendElement(dsPtr, "");
- } else {
- Tcl_DStringAppend (dsPtr, "", -1);
- return TCL_OK;
- }
- }
-
- /*
- * Get status on the stream. Make sure to use a new pb struct because
- * the struct in the statePtr may be part of an asyncronous call.
- */
-
- statusPB.ioCRefNum = driverRefNum;
- statusPB.tcpStream = statePtr->tcpStream;
- statusPB.csCode = TCPStatus;
- err = PBControlSync((ParmBlkPtr) &statusPB);
- if ((err == connectionDoesntExist) ||
- ((err == noErr) && (statusPB.csParam.status.connectionState == 14))) {
- /*
- * The socket was probably closed on the other side of the connection.
- */
-
- if (interp) {
- Tcl_AppendResult(interp, "can't access socket info: ",
- "connection reset by peer", NULL);
- }
- return TCL_ERROR;
- } else if (err != noErr) {
- if (interp) {
- Tcl_AppendResult(interp, "unknown socket error", NULL);
- }
- Debugger();
- return TCL_ERROR;
- }
-
-
- /*
- * Get the sockname for the socket.
- */
-
- Tcl_DStringInit(&dString);
- if (doAll || doSockName) {
- if (doAll) {
- Tcl_DStringAppendElement(dsPtr, "-sockname");
- Tcl_DStringStartSublist(dsPtr);
- }
- tcpAddress = statusPB.csParam.status.localHost;
- sprintf(buffer, "%d.%d.%d.%d", tcpAddress>>24,
- tcpAddress>>16 & 0xff, tcpAddress>>8 & 0xff,
- tcpAddress & 0xff);
- Tcl_DStringAppendElement(dsPtr, buffer);
- if (ResolveAddress(tcpAddress, &dString) == noErr) {
- Tcl_DStringAppendElement(dsPtr, dString.string);
- } else {
- Tcl_DStringAppendElement(dsPtr, "<unknown>");
- }
- sprintf(buffer, "%d", statusPB.csParam.status.localPort);
- Tcl_DStringAppendElement(dsPtr, buffer);
- if (doAll) {
- Tcl_DStringEndSublist(dsPtr);
- }
- }
-
- /*
- * Get the peername for the socket.
- */
-
- if ((doAll || doPeerName) && (statePtr->flags & TCP_CONNECTED)) {
- if (doAll) {
- Tcl_DStringAppendElement(dsPtr, "-peername");
- Tcl_DStringStartSublist(dsPtr);
- }
- tcpAddress = statusPB.csParam.status.remoteHost;
- sprintf(buffer, "%d.%d.%d.%d", tcpAddress>>24,
- tcpAddress>>16 & 0xff, tcpAddress>>8 & 0xff,
- tcpAddress & 0xff);
- Tcl_DStringAppendElement(dsPtr, buffer);
- Tcl_DStringSetLength(&dString, 0);
- if (ResolveAddress(tcpAddress, &dString) == noErr) {
- Tcl_DStringAppendElement(dsPtr, dString.string);
- } else {
- Tcl_DStringAppendElement(dsPtr, "<unknown>");
- }
- sprintf(buffer, "%d", statusPB.csParam.status.remotePort);
- Tcl_DStringAppendElement(dsPtr, buffer);
- if (doAll) {
- Tcl_DStringEndSublist(dsPtr);
- }
- }
-
- Tcl_DStringFree(&dString);
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TcpWatch --
- *
- * Initialize the notifier to watch this channel.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Sets the watchMask for the channel.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-TcpWatch(instanceData, mask)
- ClientData instanceData; /* The file state. */
- int mask; /* Events of interest; an OR-ed
- * combination of TCL_READABLE,
- * TCL_WRITABLE and TCL_EXCEPTION. */
-{
- TcpState *statePtr = (TcpState *) instanceData;
-
- statePtr->watchMask = mask;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * NewSocketInfo --
- *
- * This function allocates and initializes a new SocketInfo
- * structure.
- *
- * Results:
- * Returns a newly allocated SocketInfo.
- *
- * Side effects:
- * Adds the socket to the global socket list, allocates memory.
- *
- *----------------------------------------------------------------------
- */
-
-static TcpState *
-NewSocketInfo(
- StreamPtr tcpStream)
-{
- TcpState *statePtr;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
- statePtr = (TcpState *) ckalloc((unsigned) sizeof(TcpState));
- statePtr->tcpStream = tcpStream;
- statePtr->psn = applicationPSN;
- statePtr->flags = 0;
- statePtr->checkMask = 0;
- statePtr->watchMask = 0;
- statePtr->acceptProc = (Tcl_TcpAcceptProc *) NULL;
- statePtr->acceptProcData = (ClientData) NULL;
- statePtr->writeBuffer = (void *) NULL;
- statePtr->writeBufferSize = 0;
- statePtr->nextPtr = tsdPtr->socketList;
- tsdPtr->socketList = statePtr;
- return statePtr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * FreeSocketInfo --
- *
- * This function deallocates a SocketInfo structure that is no
- * longer needed.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Removes the socket from the global socket list, frees memory.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-FreeSocketInfo(
- TcpState *statePtr) /* The state pointer to free. */
-{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
- if (statePtr == tsdPtr->socketList) {
- tsdPtr->socketList = statePtr->nextPtr;
- } else {
- TcpState *p;
- for (p = tsdPtr->socketList; p != NULL; p = p->nextPtr) {
- if (p->nextPtr == statePtr) {
- p->nextPtr = statePtr->nextPtr;
- break;
- }
- }
- }
-
- if (statePtr->writeBuffer != (void *) NULL) {
- ckfree(statePtr->writeBuffer);
- }
-
- ckfree((char *) statePtr);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_MakeTcpClientChannel --
- *
- * Creates a Tcl_Channel from an existing client TCP socket.
- *
- * Results:
- * The Tcl_Channel wrapped around the preexisting TCP socket.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_Channel
-Tcl_MakeTcpClientChannel(
- ClientData sock) /* The socket to wrap up into a channel. */
-{
- TcpState *statePtr;
- char channelName[20];
-
- if (TclpHasSockets(NULL) != TCL_OK) {
- return NULL;
- }
-
- statePtr = NewSocketInfo((StreamPtr) sock);
- /* TODO: do we need to set the port??? */
-
- sprintf(channelName, "sock%d", socketNumber++);
-
- statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
- (ClientData) statePtr, (TCL_READABLE | TCL_WRITABLE));
- Tcl_SetChannelBufferSize(statePtr->channel, socketBufferSize);
- Tcl_SetChannelOption(NULL, statePtr->channel, "-translation", "auto crlf");
- return statePtr->channel;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * CreateSocket --
- *
- * This function opens a new socket and initializes the
- * SocketInfo structure.
- *
- * Results:
- * Returns a new SocketInfo, or NULL with an error in interp.
- *
- * Side effects:
- * Adds a new socket to the socketList.
- *
- *----------------------------------------------------------------------
- */
-
-static TcpState *
-CreateSocket(
- Tcl_Interp *interp, /* For error reporting; can be NULL. */
- int port, /* Port number to open. */
- CONST char *host, /* Name of host on which to open port. */
- CONST char *myaddr, /* Optional client-side address */
- int myport, /* Optional client-side port */
- int server, /* 1 if socket should be a server socket,
- * else 0 for a client socket. */
- int async) /* 1 create async, 0 do sync. */
-{
- ip_addr macAddr;
- OSErr err;
- TCPiopb pb;
- StreamPtr tcpStream;
- TcpState *statePtr;
- char * buffer;
-
- /*
- * Figure out the ip address from the host string.
- */
-
- if (host == NULL) {
- err = GetLocalAddress(&macAddr);
- } else {
- err = GetHostFromString(host, &macAddr);
- }
- if (err != noErr) {
- Tcl_SetErrno(EHOSTUNREACH);
- if (interp != (Tcl_Interp *) NULL) {
- Tcl_AppendResult(interp, "couldn't open socket: ",
- Tcl_PosixError(interp), (char *) NULL);
- }
- return (TcpState *) NULL;
- }
-
- /*
- * Create a MacTCP stream and create the state used for socket
- * transactions from here on out.
- */
-
- ClearZombieSockets();
- buffer = ckalloc(socketBufferSize);
- InitMacTCPParamBlock(&pb, TCPCreate);
- pb.csParam.create.rcvBuff = buffer;
- pb.csParam.create.rcvBuffLen = socketBufferSize;
- pb.csParam.create.notifyProc = nil /* notifyUPP */;
- err = PBControlSync((ParmBlkPtr) &pb);
- if (err != noErr) {
- Tcl_SetErrno(0); /* TODO: set to ENOSR - maybe?*/
- if (interp != (Tcl_Interp *) NULL) {
- Tcl_AppendResult(interp, "couldn't open socket: ",
- Tcl_PosixError(interp), (char *) NULL);
- }
- return (TcpState *) NULL;
- }
-
- tcpStream = pb.tcpStream;
- statePtr = NewSocketInfo(tcpStream);
- statePtr->port = port;
-
- if (server) {
- /*
- * Set up server connection.
- */
-
- InitMacTCPParamBlock(&statePtr->pb, TCPPassiveOpen);
- statePtr->pb.tcpStream = tcpStream;
- statePtr->pb.csParam.open.localPort = statePtr->port;
- statePtr->pb.ioCompletion = completeUPP;
- statePtr->pb.csParam.open.userDataPtr = (Ptr) statePtr;
- statePtr->pb.csParam.open.ulpTimeoutValue = 100;
- statePtr->pb.csParam.open.ulpTimeoutAction = 1 /* 1:abort 0:report */;
- statePtr->pb.csParam.open.commandTimeoutValue = 0 /* infinity */;
-
- statePtr->flags |= TCP_LISTENING;
- err = PBControlAsync((ParmBlkPtr) &(statePtr->pb));
-
- /*
- * If this is a server on port 0 then we need to wait until
- * the dynamic port allocation is made by the MacTcp driver.
- */
-
- if (statePtr->port == 0) {
- EventRecord dummy;
-
- while (statePtr->pb.csParam.open.localPort == 0) {
- WaitNextEvent(0, &dummy, 1, NULL);
- if (statePtr->pb.ioResult != 0) {
- break;
- }
- }
- statePtr->port = statePtr->pb.csParam.open.localPort;
- }
- Tcl_SetErrno(EINPROGRESS);
- } else {
- /*
- * Attempt to connect. The connect may fail at present with an
- * EINPROGRESS but at a later time it will complete. The caller
- * will set up a file handler on the socket if she is interested in
- * being informed when the connect completes.
- */
-
- InitMacTCPParamBlock(&statePtr->pb, TCPActiveOpen);
-
- statePtr->pb.tcpStream = tcpStream;
- statePtr->pb.csParam.open.remoteHost = macAddr;
- statePtr->pb.csParam.open.remotePort = port;
- statePtr->pb.csParam.open.localHost = 0;
- statePtr->pb.csParam.open.localPort = myport;
- statePtr->pb.csParam.open.userDataPtr = (Ptr) statePtr;
- statePtr->pb.csParam.open.validityFlags = timeoutValue | timeoutAction;
- statePtr->pb.csParam.open.ulpTimeoutValue = 60 /* seconds */;
- statePtr->pb.csParam.open.ulpTimeoutAction = 1 /* 1:abort 0:report */;
- statePtr->pb.csParam.open.commandTimeoutValue = 0;
-
- statePtr->pb.ioCompletion = completeUPP;
- if (async) {
- statePtr->flags |= TCP_ASYNC_CONNECT;
- err = PBControlAsync((ParmBlkPtr) &(statePtr->pb));
- Tcl_SetErrno(EINPROGRESS);
- } else {
- err = PBControlSync((ParmBlkPtr) &(statePtr->pb));
- }
- }
-
- switch (err) {
- case noErr:
- if (!async) {
- statePtr->flags |= TCP_CONNECTED;
- }
- return statePtr;
- case duplicateSocket:
- Tcl_SetErrno(EADDRINUSE);
- break;
- case openFailed:
- case connectionTerminated:
- Tcl_SetErrno(ECONNREFUSED);
- break;
- case invalidStreamPtr:
- case connectionExists:
- default:
- /*
- * These cases should never occur. However, we will fail
- * gracefully and hope Tcl can resume. The alternative is to panic
- * which is probably a bit drastic.
- */
-
- Debugger();
- Tcl_SetErrno(err);
- }
-
- /*
- * We had error during the connection. Release the stream
- * and file handle. Also report to the interp.
- */
-
- pb.ioCRefNum = driverRefNum;
- pb.csCode = TCPRelease;
- pb.tcpStream = tcpStream;
- pb.ioCompletion = NULL;
- err = PBControlSync((ParmBlkPtr) &pb);
-
- if (interp != (Tcl_Interp *) NULL) {
- Tcl_AppendResult(interp, "couldn't open socket: ",
- Tcl_PosixError(interp), (char *) NULL);
- }
-
- ckfree(buffer);
- FreeSocketInfo(statePtr);
- return (TcpState *) NULL;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_OpenTcpClient --
- *
- * Opens a TCP client socket and creates a channel around it.
- *
- * Results:
- * The channel or NULL if failed. On failure, the routine also
- * sets the output argument errorCodePtr to the error code.
- *
- * Side effects:
- * Opens a client socket and creates a new channel.
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_Channel
-Tcl_OpenTcpClient(
- Tcl_Interp *interp, /* For error reporting; can be NULL. */
- int port, /* Port number to open. */
- CONST char *host, /* Host on which to open port. */
- CONST char *myaddr, /* Client-side address */
- int myport, /* Client-side port */
- int async) /* If nonzero, attempt to do an
- * asynchronous connect. Otherwise
- * we do a blocking connect.
- * - currently ignored */
-{
- TcpState *statePtr;
- char channelName[20];
-
- if (TclpHasSockets(interp) != TCL_OK) {
- return NULL;
- }
-
- /*
- * Create a new client socket and wrap it in a channel.
- */
-
- statePtr = CreateSocket(interp, port, host, myaddr, myport, 0, async);
- if (statePtr == NULL) {
- return NULL;
- }
-
- sprintf(channelName, "sock%d", socketNumber++);
-
- statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
- (ClientData) statePtr, (TCL_READABLE | TCL_WRITABLE));
- Tcl_SetChannelBufferSize(statePtr->channel, socketBufferSize);
- Tcl_SetChannelOption(NULL, statePtr->channel, "-translation", "auto crlf");
- return statePtr->channel;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_OpenTcpServer --
- *
- * Opens a TCP server socket and creates a channel around it.
- *
- * Results:
- * The channel or NULL if failed.
- *
- * Side effects:
- * Opens a server socket and creates a new channel.
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_Channel
-Tcl_OpenTcpServer(
- Tcl_Interp *interp, /* For error reporting - may be
- * NULL. */
- int port, /* Port number to open. */
- CONST char *host, /* Name of local host. */
- Tcl_TcpAcceptProc *acceptProc, /* Callback for accepting connections
- * from new clients. */
- ClientData acceptProcData) /* Data for the callback. */
-{
- TcpState *statePtr;
- char channelName[20];
-
- if (TclpHasSockets(interp) != TCL_OK) {
- return NULL;
- }
-
- /*
- * Create a new client socket and wrap it in a channel.
- */
-
- statePtr = CreateSocket(interp, port, host, NULL, 0, 1, 1);
- if (statePtr == NULL) {
- return NULL;
- }
-
- statePtr->acceptProc = acceptProc;
- statePtr->acceptProcData = acceptProcData;
-
- sprintf(channelName, "sock%d", socketNumber++);
-
- statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
- (ClientData) statePtr, 0);
- Tcl_SetChannelBufferSize(statePtr->channel, socketBufferSize);
- Tcl_SetChannelOption(NULL, statePtr->channel, "-translation", "auto crlf");
- return statePtr->channel;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * SocketEventProc --
- *
- * This procedure is called by Tcl_ServiceEvent when a socket event
- * reaches the front of the event queue. This procedure is
- * responsible for notifying the generic channel code.
- *
- * Results:
- * Returns 1 if the event was handled, meaning it should be removed
- * from the queue. Returns 0 if the event was not handled, meaning
- * it should stay on the queue. The only time the event isn't
- * handled is if the TCL_FILE_EVENTS flag bit isn't set.
- *
- * Side effects:
- * Whatever the channel callback procedures do.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-SocketEventProc(
- Tcl_Event *evPtr, /* Event to service. */
- int flags) /* Flags that indicate what events to
- * handle, such as TCL_FILE_EVENTS. */
-{
- TcpState *statePtr;
- SocketEvent *eventPtr = (SocketEvent *) evPtr;
- int mask = 0;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
- if (!(flags & TCL_FILE_EVENTS)) {
- return 0;
- }
-
- /*
- * Find the specified socket on the socket list.
- */
-
- for (statePtr = tsdPtr->socketList; statePtr != NULL;
- statePtr = statePtr->nextPtr) {
- if ((statePtr == eventPtr->statePtr) &&
- (statePtr->tcpStream == eventPtr->tcpStream)) {
- break;
- }
- }
-
- /*
- * Discard events that have gone stale.
- */
-
- if (!statePtr) {
- return 1;
- }
- statePtr->flags &= ~(TCP_PENDING);
- if (statePtr->flags & TCP_RELEASE) {
- SocketFreeProc(statePtr);
- return 1;
- }
-
-
- /*
- * Handle connection requests directly.
- */
-
- if (statePtr->flags & TCP_LISTEN_CONNECT) {
- if (statePtr->checkMask & TCL_READABLE) {
- TcpAccept(statePtr);
- }
- return 1;
- }
-
- /*
- * Mask off unwanted events then notify the channel.
- */
-
- mask = statePtr->checkMask & statePtr->watchMask;
- if (mask) {
- Tcl_NotifyChannel(statePtr->channel, mask);
- }
- return 1;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * WaitForSocketEvent --
- *
- * Waits until one of the specified events occurs on a socket.
- *
- * Results:
- * Returns 1 on success or 0 on failure, with an error code in
- * errorCodePtr.
- *
- * Side effects:
- * Processes socket events off the system queue.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-WaitForSocketEvent(
- TcpState *statePtr, /* Information about this socket. */
- int mask, /* Events to look for. */
- int *errorCodePtr) /* Where to store errors? */
-{
- OSErr err;
- TCPiopb statusPB;
- EventRecord dummy;
-
- /*
- * Loop until we get the specified condition, unless the socket is
- * asynchronous.
- */
-
- do {
- statusPB.ioCRefNum = driverRefNum;
- statusPB.tcpStream = statePtr->tcpStream;
- statusPB.csCode = TCPStatus;
- err = PBControlSync((ParmBlkPtr) &statusPB);
- if (err != noErr) {
- /*
- * I am not sure why it is right to return 1 - indicating success
- * for synchronous sockets when an attempt to get status on the
- * driver yeilds an error. But it is CERTAINLY wrong for async
- * sockect which have not yet connected.
- */
-
- if (statePtr->flags & TCP_ASYNC_CONNECT) {
- *errorCodePtr = EWOULDBLOCK;
- return 0;
- } else {
- statePtr->checkMask |= (TCL_READABLE | TCL_WRITABLE);
- return 1;
- }
- }
- statePtr->checkMask = 0;
-
- /*
- * The "6" below is the "connection being established" flag. I couldn't
- * find a define for this in MacTCP.h, but that's what the programmer's
- * guide says.
- */
-
- if ((statusPB.csParam.status.connectionState != 0)
- && (statusPB.csParam.status.connectionState != 4)
- && (statusPB.csParam.status.connectionState != 6)) {
- if (statusPB.csParam.status.amtUnreadData > 0) {
- statePtr->checkMask |= TCL_READABLE;
- }
- if (!(statePtr->flags & TCP_WRITING)
- && (statusPB.csParam.status.sendWindow -
- statusPB.csParam.status.amtUnackedData) > 0) {
- statePtr->flags &= ~(TCP_ASYNC_CONNECT);
- statePtr->checkMask |= TCL_WRITABLE;
- }
- if (mask & statePtr->checkMask) {
- return 1;
- }
- } else {
- break;
- }
-
- /*
- * Call the system to let other applications run while we
- * are waiting for this event to occur.
- */
-
- WaitNextEvent(0, &dummy, 1, NULL);
- } while (!(statePtr->flags & TCP_ASYNC_SOCKET));
- *errorCodePtr = EWOULDBLOCK;
- return 0;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TcpAccept --
- * Accept a TCP socket connection. This is called by the event
- * loop, and it in turns calls any registered callbacks for this
- * channel.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Evals the Tcl script associated with the server socket.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-TcpAccept(
- TcpState *statePtr)
-{
- TcpState *newStatePtr;
- StreamPtr tcpStream;
- char remoteHostname[255];
- OSErr err;
- ip_addr remoteAddress;
- long remotePort;
- char channelName[20];
-
- statePtr->flags &= ~TCP_LISTEN_CONNECT;
- statePtr->checkMask &= ~TCL_READABLE;
-
- /*
- * Transfer sever stream to new connection.
- */
-
- tcpStream = statePtr->tcpStream;
- newStatePtr = NewSocketInfo(tcpStream);
- newStatePtr->tcpStream = tcpStream;
- sprintf(channelName, "sock%d", socketNumber++);
-
-
- newStatePtr->flags |= TCP_CONNECTED;
- newStatePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
- (ClientData) newStatePtr, (TCL_READABLE | TCL_WRITABLE));
- Tcl_SetChannelBufferSize(newStatePtr->channel, socketBufferSize);
- Tcl_SetChannelOption(NULL, newStatePtr->channel, "-translation",
- "auto crlf");
-
- remoteAddress = statePtr->pb.csParam.open.remoteHost;
- remotePort = statePtr->pb.csParam.open.remotePort;
-
- /*
- * Reopen passive connect. Make new tcpStream the server.
- */
-
- ClearZombieSockets();
- InitMacTCPParamBlock(&statePtr->pb, TCPCreate);
- statePtr->pb.csParam.create.rcvBuff = ckalloc(socketBufferSize);
- statePtr->pb.csParam.create.rcvBuffLen = socketBufferSize;
- err = PBControlSync((ParmBlkPtr) &statePtr->pb);
- if (err != noErr) {
- /*
- * Hmmm... We can't reopen the server. We'll go ahead
- * an continue - but we are kind of broken now...
- */
- Debugger();
- statePtr->tcpStream = -1;
- statePtr->flags |= TCP_SERVER_ZOMBIE;
- }
-
- tcpStream = statePtr->tcpStream = statePtr->pb.tcpStream;
-
- InitMacTCPParamBlock(&statePtr->pb, TCPPassiveOpen);
- statePtr->pb.tcpStream = tcpStream;
- statePtr->pb.csParam.open.localHost = 0;
- statePtr->pb.csParam.open.localPort = statePtr->port;
- statePtr->pb.ioCompletion = completeUPP;
- statePtr->pb.csParam.open.userDataPtr = (Ptr) statePtr;
- statePtr->flags |= TCP_LISTENING;
- err = PBControlAsync((ParmBlkPtr) &(statePtr->pb));
- /*
- * TODO: deal with case where we can't recreate server socket...
- */
-
- /*
- * Finally we run the accept procedure. We must do this last to make
- * sure we are in a nice clean state. This Tcl code can do anything
- * including closing the server or client sockets we've just delt with.
- */
-
- if (statePtr->acceptProc != NULL) {
- sprintf(remoteHostname, "%d.%d.%d.%d", remoteAddress>>24,
- remoteAddress>>16 & 0xff, remoteAddress>>8 & 0xff,
- remoteAddress & 0xff);
-
- (statePtr->acceptProc)(statePtr->acceptProcData, newStatePtr->channel,
- remoteHostname, remotePort);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_GetHostName --
- *
- * Returns the name of the local host.
- *
- * Results:
- * A string containing the network name for this machine, or
- * an empty string if we can't figure out the name. The caller
- * must not modify or free this string.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-CONST char *
-Tcl_GetHostName()
-{
- static int hostnameInited = 0;
- static char hostname[255];
- ip_addr ourAddress;
- Tcl_DString dString;
- OSErr err;
-
- if (hostnameInited) {
- return hostname;
- }
-
- if (TclpHasSockets(NULL) == TCL_OK) {
- err = GetLocalAddress(&ourAddress);
- if (err == noErr) {
- /*
- * Search for the doman name and return it if found. Otherwise,
- * just print the IP number to a string and return that.
- */
-
- Tcl_DStringInit(&dString);
- err = ResolveAddress(ourAddress, &dString);
- if (err == noErr) {
- strcpy(hostname, dString.string);
- } else {
- sprintf(hostname, "%d.%d.%d.%d", ourAddress>>24, ourAddress>>16 & 0xff,
- ourAddress>>8 & 0xff, ourAddress & 0xff);
- }
- Tcl_DStringFree(&dString);
-
- hostnameInited = 1;
- return hostname;
- }
- }
-
- hostname[0] = '\0';
- hostnameInited = 1;
- return hostname;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ResolveAddress --
- *
- * This function is used to resolve an ip address to it's full
- * domain name address.
- *
- * Results:
- * An os err value.
- *
- * Side effects:
- * Treats client data as int we set to true.
- *
- *----------------------------------------------------------------------
- */
-
-static OSErr
-ResolveAddress(
- ip_addr tcpAddress, /* Address to resolve. */
- Tcl_DString *dsPtr) /* Returned address in string. */
-{
- int i;
- EventRecord dummy;
- DNRState dnrState;
- OSErr err;
-
- /*
- * Call AddrToName to resolve our ip address to our domain name.
- * The call is async, so we must wait for a callback to tell us
- * when to continue.
- */
-
- for (i = 0; i < NUM_ALT_ADDRS; i++) {
- dnrState.hostInfo.addr[i] = 0;
- }
- dnrState.done = 0;
- GetCurrentProcess(&(dnrState.psn));
- err = AddrToName(tcpAddress, &dnrState.hostInfo, resultUPP, (Ptr) &dnrState);
- if (err == cacheFault) {
- while (!dnrState.done) {
- WaitNextEvent(0, &dummy, 1, NULL);
- }
- }
-
- /*
- * If there is no error in finding the domain name we set the
- * result into the dynamic string. We also work around a bug in
- * MacTcp where an extranious '.' may be found at the end of the name.
- */
-
- if (dnrState.hostInfo.rtnCode == noErr) {
- i = strlen(dnrState.hostInfo.cname) - 1;
- if (dnrState.hostInfo.cname[i] == '.') {
- dnrState.hostInfo.cname[i] = '\0';
- }
- Tcl_DStringAppend(dsPtr, dnrState.hostInfo.cname, -1);
- }
-
- return dnrState.hostInfo.rtnCode;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * DNRCompletionRoutine --
- *
- * This function is called when the Domain Name Server is done
- * seviceing our request. It just sets a flag that we can poll
- * in functions like Tcl_GetHostName to let them know to continue.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Treats client data as int we set to true.
- *
- *----------------------------------------------------------------------
- */
-
-static pascal void
-DNRCompletionRoutine(
- struct hostInfo *hostinfoPtr, /* Host infor struct. */
- DNRState *dnrStatePtr) /* Completetion state. */
-{
- dnrStatePtr->done = true;
- WakeUpProcess(&(dnrStatePtr->psn));
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * CleanUpExitProc --
- *
- * This procedure is invoked as an exit handler when ExitToShell
- * is called. It aborts any lingering socket connections. This
- * must be called or the Mac OS will more than likely crash.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static pascal void
-CleanUpExitProc()
-{
- TCPiopb exitPB;
- TcpState *statePtr;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
- while (tsdPtr->socketList != NULL) {
- statePtr = tsdPtr->socketList;
- tsdPtr->socketList = statePtr->nextPtr;
-
- /*
- * Close and Release the connection.
- */
-
- exitPB.ioCRefNum = driverRefNum;
- exitPB.csCode = TCPClose;
- exitPB.tcpStream = statePtr->tcpStream;
- exitPB.csParam.close.ulpTimeoutValue = 60 /* seconds */;
- exitPB.csParam.close.ulpTimeoutAction = 1 /* 1:abort 0:report */;
- exitPB.csParam.close.validityFlags = timeoutValue | timeoutAction;
- exitPB.ioCompletion = NULL;
- PBControlSync((ParmBlkPtr) &exitPB);
-
- exitPB.ioCRefNum = driverRefNum;
- exitPB.csCode = TCPRelease;
- exitPB.tcpStream = statePtr->tcpStream;
- exitPB.ioCompletion = NULL;
- PBControlSync((ParmBlkPtr) &exitPB);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * GetHostFromString --
- *
- * Looks up the passed in domain name in the domain resolver. It
- * can accept strings of two types: 1) the ip number in string
- * format, or 2) the domain name.
- *
- * Results:
- * We return a ip address or 0 if there was an error or the
- * domain does not exist.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static OSErr
-GetHostFromString(
- CONST char *name, /* Host in string form. */
- ip_addr *address) /* Returned IP address. */
-{
- OSErr err;
- int i;
- EventRecord dummy;
- DNRState dnrState;
-
- if (TclpHasSockets(NULL) != TCL_OK) {
- return 0;
- }
-
- /*
- * Call StrToAddr to get the ip number for the passed in domain
- * name. The call is async, so we must wait for a callback to
- * tell us when to continue.
- */
-
- for (i = 0; i < NUM_ALT_ADDRS; i++) {
- dnrState.hostInfo.addr[i] = 0;
- }
- dnrState.done = 0;
- GetCurrentProcess(&(dnrState.psn));
- err = StrToAddr((char*)name, &dnrState.hostInfo, resultUPP, (Ptr) &dnrState);
- if (err == cacheFault) {
- while (!dnrState.done) {
- WaitNextEvent(0, &dummy, 1, NULL);
- }
- }
-
- /*
- * For some reason MacTcp may return a cachFault a second time via
- * the hostinfo block. This seems to be a bug in MacTcp. In this case
- * we run StrToAddr again - which seems to then work just fine.
- */
-
- if (dnrState.hostInfo.rtnCode == cacheFault) {
- dnrState.done = 0;
- err = StrToAddr((char*)name, &dnrState.hostInfo, resultUPP, (Ptr) &dnrState);
- if (err == cacheFault) {
- while (!dnrState.done) {
- WaitNextEvent(0, &dummy, 1, NULL);
- }
- }
- }
-
- if (dnrState.hostInfo.rtnCode == noErr) {
- *address = dnrState.hostInfo.addr[0];
- }
-
- return dnrState.hostInfo.rtnCode;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * IOCompletionRoutine --
- *
- * This function is called when an asynchronous socket operation
- * completes. Since this routine runs as an interrupt handler,
- * it will simply set state to tell the notifier that this socket
- * is now ready for action. Note that this function is running at
- * interupt time and can't allocate memory or do much else except
- * set state.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Sets some state in the socket state. May also wake the process
- * if we are not currently running.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-IOCompletionRoutine(
- TCPiopb *pbPtr) /* Tcp parameter block. */
-{
- TcpState *statePtr;
-
- if (pbPtr->csCode == TCPSend) {
- statePtr = (TcpState *) pbPtr->csParam.send.userDataPtr;
- } else {
- statePtr = (TcpState *) pbPtr->csParam.open.userDataPtr;
- }
-
- /*
- * Always wake the process in case it's in WaitNextEvent.
- * If an error has a occured - just return. We will deal
- * with the problem later.
- */
-
- WakeUpProcess(&statePtr->psn);
- if (pbPtr->ioResult != noErr) {
- return;
- }
-
- if (statePtr->flags & TCP_ASYNC_CONNECT) {
- statePtr->flags &= ~TCP_ASYNC_CONNECT;
- statePtr->flags |= TCP_CONNECTED;
- statePtr->checkMask |= TCL_READABLE & TCL_WRITABLE;
- } else if (statePtr->flags & TCP_LISTENING) {
- if (statePtr->port == 0) {
- Debugger();
- }
- statePtr->flags &= ~TCP_LISTENING;
- statePtr->flags |= TCP_LISTEN_CONNECT;
- statePtr->checkMask |= TCL_READABLE;
- } else if (statePtr->flags & TCP_WRITING) {
- statePtr->flags &= ~TCP_WRITING;
- statePtr->checkMask |= TCL_WRITABLE;
- if (!(statePtr->flags & TCP_CONNECTED)) {
- InitMacTCPParamBlock(&statePtr->pb, TCPClose);
- statePtr->pb.tcpStream = statePtr->tcpStream;
- statePtr->pb.ioCompletion = closeUPP;
- statePtr->pb.csParam.close.userDataPtr = (Ptr) statePtr;
- if (PBControlAsync((ParmBlkPtr) &statePtr->pb) != noErr) {
- statePtr->flags |= TCP_RELEASE;
- }
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * GetLocalAddress --
- *
- * Get the IP address for this machine. The result is cached so
- * the result is returned quickly after the first call.
- *
- * Results:
- * Macintosh error code.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static OSErr
-GetLocalAddress(
- unsigned long *addr) /* Returns host IP address. */
-{
- struct GetAddrParamBlock pBlock;
- OSErr err = noErr;
- static unsigned long localAddress = 0;
-
- if (localAddress == 0) {
- memset(&pBlock, 0, sizeof(pBlock));
- pBlock.ioResult = 1;
- pBlock.csCode = ipctlGetAddr;
- pBlock.ioCRefNum = driverRefNum;
- err = PBControlSync((ParmBlkPtr) &pBlock);
-
- if (err != noErr) {
- return err;
- }
- localAddress = pBlock.ourAddress;
- }
-
- *addr = localAddress;
- return noErr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * GetBufferSize --
- *
- * Get the appropiate buffer size for our machine & network. This
- * value will be used by the rest of Tcl & the MacTcp driver for
- * the size of its buffers. If out method for determining the
- * optimal buffer size fails for any reason - we return a
- * reasonable default.
- *
- * Results:
- * Size of optimal buffer in bytes.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static long
-GetBufferSize()
-{
- UDPiopb iopb;
- OSErr err = noErr;
- long bufferSize;
-
- memset(&iopb, 0, sizeof(iopb));
- err = GetLocalAddress(&iopb.csParam.mtu.remoteHost);
- if (err != noErr) {
- return CHANNEL_BUF_SIZE;
- }
- iopb.ioCRefNum = driverRefNum;
- iopb.csCode = UDPMaxMTUSize;
- err = PBControlSync((ParmBlkPtr)&iopb);
- if (err != noErr) {
- return CHANNEL_BUF_SIZE;
- }
- bufferSize = (iopb.csParam.mtu.mtuSize * 4) + 1024;
- if (bufferSize < CHANNEL_BUF_SIZE) {
- bufferSize = CHANNEL_BUF_SIZE;
- }
- return bufferSize;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclSockGetPort --
- *
- * Maps from a string, which could be a service name, to a port.
- * Used by socket creation code to get port numbers and resolve
- * registered service names to port numbers.
- *
- * Results:
- * A standard Tcl result. On success, the port number is
- * returned in portPtr. On failure, an error message is left in
- * the interp's result.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclSockGetPort(
- Tcl_Interp *interp, /* Interp for error messages. */
- char *string, /* Integer or service name */
- char *proto, /* "tcp" or "udp", typically -
- * ignored on Mac - assumed to be tcp */
- int *portPtr) /* Return port number */
-{
- PortInfo *portInfoPtr = NULL;
-
- if (Tcl_GetInt(interp, string, portPtr) == TCL_OK) {
- if (*portPtr > 0xFFFF) {
- Tcl_AppendResult(interp, "couldn't open socket: port number too high",
- (char *) NULL);
- return TCL_ERROR;
- }
- if (*portPtr < 0) {
- Tcl_AppendResult(interp, "couldn't open socket: negative port number",
- (char *) NULL);
- return TCL_ERROR;
- }
- return TCL_OK;
- }
- for (portInfoPtr = portServices; portInfoPtr->name != NULL; portInfoPtr++) {
- if (!strcmp(portInfoPtr->name, string)) {
- break;
- }
- }
- if (portInfoPtr != NULL && portInfoPtr->name != NULL) {
- *portPtr = portInfoPtr->port;
- Tcl_ResetResult(interp);
- return TCL_OK;
- }
-
- return TCL_ERROR;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ClearZombieSockets --
- *
- * This procedure looks through the socket list and removes the
- * first stream it finds that is ready for release. This procedure
- * should be called before we ever try to create new Tcp streams
- * to ensure we can least allocate one stream.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Tcp streams may be released.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-ClearZombieSockets()
-{
- TcpState *statePtr;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
- for (statePtr = tsdPtr->socketList; statePtr != NULL;
- statePtr = statePtr->nextPtr) {
- if (statePtr->flags & TCP_RELEASE) {
- SocketFreeProc(statePtr);
- return;
- }
- }
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * NotifyRoutine --
- *
- * This routine does nothing currently, and is not being used. But
- * it is useful if you want to experiment with what MacTCP thinks that
- * it is doing...
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-pascal void NotifyRoutine (
- StreamPtr tcpStream,
- unsigned short eventCode,
- Ptr userDataPtr,
- unsigned short terminReason,
- struct ICMPReport *icmpMsg)
-{
- StreamPtr localTcpStream;
- unsigned short localEventCode;
- unsigned short localTerminReason;
- struct ICMPReport localIcmpMsg;
-
- localTcpStream = tcpStream;
- localEventCode = eventCode;
- localTerminReason = terminReason;
- localIcmpMsg = *icmpMsg;
-
-}
diff --git a/mac/tclMacTclCode.r b/mac/tclMacTclCode.r
deleted file mode 100644
index d5544b0..0000000
--- a/mac/tclMacTclCode.r
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * tclMacTclCode.r --
- *
- * This file creates resources from the Tcl code that is
- * usually stored in the TCL_LiBRARY
- *
- * Copyright (c) 1996-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include <Types.r>
-#include <SysTypes.r>
-
-#define TCL_LIBRARY_RESOURCES 2000
-
-/*
- * The mechanisim below loads Tcl source into the resource fork of the
- * application. The example below creates a TEXT resource named
- * "Init" from the file "init.tcl". This allows applications to use
- * Tcl to define the behavior of the application without having to
- * require some predetermined file structure - all needed Tcl "files"
- * are located within the application. To source a file for the
- * resource fork the source command has been modified to support
- * sourcing from resources. In the below case "source -rsrc {Init}"
- * will load the TEXT resource named "Init".
- */
-
-read 'TEXT' (TCL_LIBRARY_RESOURCES, "init", purgeable) "::library:init.tcl";
-read 'TEXT' (TCL_LIBRARY_RESOURCES + 1, "auto", purgeable) "::library:auto.tcl";
-read 'TEXT' (TCL_LIBRARY_RESOURCES + 2, "package", purgeable,preload) "::library:package.tcl";
-read 'TEXT' (TCL_LIBRARY_RESOURCES + 3, "history", purgeable) "::library:history.tcl";
-read 'TEXT' (TCL_LIBRARY_RESOURCES + 4, "word", purgeable,preload) "::library:word.tcl";
-read 'TEXT' (TCL_LIBRARY_RESOURCES + 5, "parray", purgeable,preload) "::library:parray.tcl";
diff --git a/mac/tclMacTest.c b/mac/tclMacTest.c
deleted file mode 100644
index 64ca90c..0000000
--- a/mac/tclMacTest.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * tclMacTest.c --
- *
- * Contains commands for platform specific tests for
- * the Macintosh platform.
- *
- * Copyright (c) 1996 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#define TCL_TEST
-#define USE_COMPAT_CONST
-#include "tclInt.h"
-#include "tclMacInt.h"
-#include "tclMacPort.h"
-#include "Files.h"
-#include <Errors.h>
-#include <Resources.h>
-#include <Script.h>
-#include <Strings.h>
-#include <FSpCompat.h>
-
-/*
- * Forward declarations of procedures defined later in this file:
- */
-
-int TclplatformtestInit _ANSI_ARGS_((Tcl_Interp *interp));
-static int DebuggerCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int WriteTextResource _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TclplatformtestInit --
- *
- * Defines commands that test platform specific functionality for
- * Unix platforms.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * Defines new commands.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclplatformtestInit(
- Tcl_Interp *interp) /* Interpreter to add commands to. */
-{
- /*
- * Add commands for platform specific tests on MacOS here.
- */
-
- Tcl_CreateCommand(interp, "debugger", DebuggerCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
- Tcl_CreateCommand(interp, "testWriteTextResource", WriteTextResource,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
-
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * DebuggerCmd --
- *
- * This procedure simply calls the low level debugger.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-DebuggerCmd(
- ClientData clientData, /* Not used. */
- Tcl_Interp *interp, /* Not used. */
- int argc, /* Not used. */
- CONST char **argv) /* Not used. */
-{
- Debugger();
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * WriteTextResource --
- *
- * This procedure will write a text resource out to the
- * application or a given file. The format for this command is
- * textwriteresource
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-WriteTextResource(
- ClientData clientData, /* Not used. */
- Tcl_Interp *interp, /* Current interpreter. */
- int argc, /* Number of arguments. */
- CONST char **argv) /* Argument strings. */
-{
- char *errNum = "wrong # args: ";
- char *errBad = "bad argument: ";
- char *errStr;
- CONST char *fileName = NULL, *rsrcName = NULL;
- CONST char *data = NULL;
- int rsrcID = -1, i, protectIt = 0;
- short fileRef = -1;
- OSErr err;
- Handle dataHandle;
- Str255 resourceName;
- FSSpec fileSpec;
-
- /*
- * Process the arguments.
- */
- for (i = 1 ; i < argc ; i++) {
- if (!strcmp(argv[i], "-rsrc")) {
- rsrcName = argv[i + 1];
- i++;
- } else if (!strcmp(argv[i], "-rsrcid")) {
- rsrcID = atoi(argv[i + 1]);
- i++;
- } else if (!strcmp(argv[i], "-file")) {
- fileName = argv[i + 1];
- i++;
- } else if (!strcmp(argv[i], "-protected")) {
- protectIt = 1;
- } else {
- data = argv[i];
- }
- }
-
- if ((rsrcName == NULL && rsrcID < 0) ||
- (fileName == NULL) || (data == NULL)) {
- errStr = errBad;
- goto sourceFmtErr;
- }
-
- /*
- * Open the resource file.
- */
- err = FSpLocationFromPath(strlen(fileName), fileName, &fileSpec);
- if (!(err == noErr || err == fnfErr)) {
- Tcl_AppendResult(interp, "couldn't validate file name", (char *) NULL);
- return TCL_ERROR;
- }
-
- if (err == fnfErr) {
- FSpCreateResFile(&fileSpec, 'WIsH', 'rsrc', smSystemScript);
- }
- fileRef = FSpOpenResFile(&fileSpec, fsRdWrPerm);
- if (fileRef == -1) {
- Tcl_AppendResult(interp, "couldn't open resource file", (char *) NULL);
- return TCL_ERROR;
- }
-
- UseResFile(fileRef);
-
- /*
- * Prepare data needed to create resource.
- */
- if (rsrcID < 0) {
- rsrcID = UniqueID('TEXT');
- }
-
- strcpy((char *) resourceName, rsrcName);
- c2pstr((char *) resourceName);
-
- dataHandle = NewHandle(strlen(data));
- HLock(dataHandle);
- strcpy(*dataHandle, data);
- HUnlock(dataHandle);
-
- /*
- * Add the resource to the file and close it.
- */
- AddResource(dataHandle, 'TEXT', rsrcID, resourceName);
-
- UpdateResFile(fileRef);
- if (protectIt) {
- SetResAttrs(Get1Resource('TEXT', rsrcID), resProtected);
- }
-
- CloseResFile(fileRef);
- return TCL_OK;
-
- sourceFmtErr:
- Tcl_AppendResult(interp, errStr, "error in \"", argv[0], "\"",
- (char *) NULL);
- return TCL_ERROR;
-}
diff --git a/mac/tclMacThrd.c b/mac/tclMacThrd.c
deleted file mode 100644
index 57a5a99..0000000
--- a/mac/tclMacThrd.c
+++ /dev/null
@@ -1,869 +0,0 @@
-/*
- * tclMacThrd.c --
- *
- * This file implements the Mac-specific thread support.
- *
- * Copyright (c) 1991-1994 The Regents of the University of California.
- * Copyright (c) 1994-1998 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include "tclInt.h"
-#include "tclPort.h"
-#include "tclMacInt.h"
-#include <Threads.h>
-#include <Gestalt.h>
-
-#define TCL_MAC_THRD_DEFAULT_STACK (256*1024)
-
-
-typedef struct TclMacThrdData {
- ThreadID threadID;
- VOID *data;
- struct TclMacThrdData *next;
-} TclMacThrdData;
-
-/*
- * This is an array of the Thread Data Keys. It is a process-wide table.
- * Its size is originally set to 32, but it can grow if needed.
- */
-
-static TclMacThrdData **tclMacDataKeyArray;
-#define TCL_MAC_INITIAL_KEYSIZE 32
-
-/*
- * These two bits of data store the current maximum number of keys
- * and the keyCounter (which is the number of occupied slots in the
- * KeyData array.
- *
- */
-
-static int maxNumKeys = 0;
-static int keyCounter = 0;
-
-/*
- * Prototypes for functions used only in this file
- */
-
-TclMacThrdData *GetThreadDataStruct(Tcl_ThreadDataKey keyVal);
-TclMacThrdData *RemoveThreadDataStruct(Tcl_ThreadDataKey keyVal);
-
-/*
- * Note: The race evoked by the emulation layer for joinable threads
- * (see ../win/tclWinThrd.c) cannot occur on this platform due to
- * the cooperative implementation of multithreading.
- */
-
-/*
- *----------------------------------------------------------------------
- *
- * TclMacHaveThreads --
- *
- * Do we have the Thread Manager?
- *
- * Results:
- * 1 if the ThreadManager is present, 0 otherwise.
- *
- * Side effects:
- * If this is the first time this is called, the return is cached.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclMacHaveThreads(void)
-{
- static initialized = false;
- static int tclMacHaveThreads = false;
- long response = 0;
- OSErr err = noErr;
-
- if (!initialized) {
- err = Gestalt(gestaltThreadMgrAttr, &response);
- if (err == noErr) {
- tclMacHaveThreads = response | (1 << gestaltThreadMgrPresent);
- }
- }
-
- return tclMacHaveThreads;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_CreateThread --
- *
- * This procedure creates a new thread.
- *
- * Results:
- * TCL_OK if the thread could be created. The thread ID is
- * returned in a parameter.
- *
- * Side effects:
- * A new thread is created.
- *
- *----------------------------------------------------------------------
- */
-
-int
-Tcl_CreateThread(idPtr, proc, clientData, stackSize, flags)
- Tcl_ThreadId *idPtr; /* Return, the ID of the thread */
- Tcl_ThreadCreateProc proc; /* Main() function of the thread */
- ClientData clientData; /* The one argument to Main() */
- int stackSize; /* Size of stack for the new thread */
- int flags; /* Flags controlling behaviour of
- * the new thread */
-{
- if (!TclMacHaveThreads()) {
- return TCL_ERROR;
- }
-
- if (stackSize == TCL_THREAD_STACK_DEFAULT) {
- stackSize = TCL_MAC_THRD_DEFAULT_STACK;
- }
-
-#if TARGET_CPU_68K && TARGET_RT_MAC_CFM
- {
- ThreadEntryProcPtr entryProc;
- entryProc = NewThreadEntryUPP(proc);
-
- NewThread(kCooperativeThread, entryProc, (void *) clientData,
- stackSize, kCreateIfNeeded, NULL, (ThreadID *) idPtr);
- }
-#else
- NewThread(kCooperativeThread, proc, (void *) clientData,
- stackSize, kCreateIfNeeded, NULL, (ThreadID *) idPtr);
-#endif
- if ((ThreadID) *idPtr == kNoThreadID) {
- return TCL_ERROR;
- } else {
- if (flags & TCL_THREAD_JOINABLE) {
- TclRememberJoinableThread (*idPtr);
- }
-
- return TCL_OK;
- }
-
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_JoinThread --
- *
- * This procedure waits upon the exit of the specified thread.
- *
- * Results:
- * TCL_OK if the wait was successful, TCL_ERROR else.
- *
- * Side effects:
- * The result area is set to the exit code of the thread we
- * waited upon.
- *
- *----------------------------------------------------------------------
- */
-
-int
-Tcl_JoinThread(threadId, result)
- Tcl_ThreadId threadId; /* Id of the thread to wait upon */
- int* result; /* Reference to the storage the result
- * of the thread we wait upon will be
- * written into. */
-{
- if (!TclMacHaveThreads()) {
- return TCL_ERROR;
- }
-
- return TclJoinThread (threadId, result);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpThreadExit --
- *
- * This procedure terminates the current thread.
- *
- * Results:
- * None.
- *
- * Side effects:
- * This procedure terminates the current thread.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpThreadExit(status)
- int status;
-{
- ThreadID curThread;
-
- if (!TclMacHaveThreads()) {
- return;
- }
-
- GetCurrentThread(&curThread);
- TclSignalExitThread ((Tcl_ThreadId) curThread, status);
-
- DisposeThread(curThread, NULL, false);
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_GetCurrentThread --
- *
- * This procedure returns the ID of the currently running thread.
- *
- * Results:
- * A thread ID.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_ThreadId
-Tcl_GetCurrentThread()
-{
-#ifdef TCL_THREADS
- ThreadID curThread;
-
- if (!TclMacHaveThreads()) {
- return (Tcl_ThreadId) 0;
- } else {
- GetCurrentThread(&curThread);
- return (Tcl_ThreadId) curThread;
- }
-#else
- return (Tcl_ThreadId) 0;
-#endif
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpInitLock
- *
- * This procedure is used to grab a lock that serializes initialization
- * and finalization of Tcl. On some platforms this may also initialize
- * the mutex used to serialize creation of more mutexes and thread
- * local storage keys.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Acquire the initialization mutex.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpInitLock()
-{
-#ifdef TCL_THREADS
- /* There is nothing to do on the Mac. */;
-#endif
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpInitUnlock
- *
- * This procedure is used to release a lock that serializes initialization
- * and finalization of Tcl.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Release the initialization mutex.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpInitUnlock()
-{
-#ifdef TCL_THREADS
- /* There is nothing to do on the Mac */;
-#endif
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpMasterLock
- *
- * This procedure is used to grab a lock that serializes creation
- * and finalization of serialization objects. This interface is
- * only needed in finalization; it is hidden during
- * creation of the objects.
- *
- * This lock must be different than the initLock because the
- * initLock is held during creation of syncronization objects.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Acquire the master mutex.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpMasterLock()
-{
-#ifdef TCL_THREADS
- /* There is nothing to do on the Mac */;
-#endif
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpMasterUnlock
- *
- * This procedure is used to release a lock that serializes creation
- * and finalization of synchronization objects.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Release the master mutex.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpMasterUnlock()
-{
-#ifdef TCL_THREADS
- /* There is nothing to do on the Mac */
-#endif
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_GetAllocMutex
- *
- * This procedure returns a pointer to a statically initialized
- * mutex for use by the memory allocator. The alloctor must
- * use this lock, because all other locks are allocated...
- *
- * Results:
- * A pointer to a mutex that is suitable for passing to
- * Tcl_MutexLock and Tcl_MutexUnlock.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_Mutex *
-Tcl_GetAllocMutex()
-{
- /* There is nothing to do on the Mac */
- return NULL;
-}
-
-#ifdef TCL_THREADS
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_MutexLock --
- *
- * This procedure is invoked to lock a mutex. This procedure
- * handles initializing the mutex, if necessary. The caller
- * can rely on the fact that Tcl_Mutex is an opaque pointer.
- * This routine will change that pointer from NULL after first use.
- *
- * Results:
- * None.
- *
- * Side effects:
- * May block the current thread. The mutex is aquired when
- * this returns. Will allocate memory for a pthread_mutex_t
- * and initialize this the first time this Tcl_Mutex is used.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tcl_MutexLock(mutexPtr)
- Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */
-{
-/* There is nothing to do on the Mac */
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpMutexUnlock --
- *
- * This procedure is invoked to unlock a mutex. The mutex must
- * have been locked by Tcl_MutexLock.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The mutex is released when this returns.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tcl_MutexUnlock(mutexPtr)
- Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */
-{
-/* There is nothing to do on the Mac */
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpFinalizeMutex --
- *
- * This procedure is invoked to clean up one mutex. This is only
- * safe to call at the end of time.
- *
- * This assumes the Master Lock is held.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The mutex list is deallocated.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpFinalizeMutex(mutexPtr)
- Tcl_Mutex *mutexPtr;
-{
-/* There is nothing to do on the Mac */
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpThreadDataKeyInit --
- *
- * This procedure initializes a thread specific data block key.
- * Each thread has table of pointers to thread specific data.
- * all threads agree on which table entry is used by each module.
- * this is remembered in a "data key", that is just an index into
- * this table. To allow self initialization, the interface
- * passes a pointer to this key and the first thread to use
- * the key fills in the pointer to the key. The key should be
- * a process-wide static.
- *
- * There is no system-wide support for thread specific data on the
- * Mac. So we implement this as an array of pointers. The keys are
- * allocated sequentially, and each key maps to a slot in the table.
- * The table element points to a linked list of the instances of
- * the data for each thread.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Will bump the key counter if this is the first time this key
- * has been initialized. May grow the DataKeyArray if that is
- * necessary.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpThreadDataKeyInit(keyPtr)
- Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
- * really (pthread_key_t **) */
-{
-
- if (*keyPtr == NULL) {
- keyCounter += 1;
- *keyPtr = (Tcl_ThreadDataKey) keyCounter;
- if (keyCounter > maxNumKeys) {
- TclMacThrdData **newArray;
- int i, oldMax = maxNumKeys;
-
- maxNumKeys = maxNumKeys + TCL_MAC_INITIAL_KEYSIZE;
-
- newArray = (TclMacThrdData **)
- ckalloc(maxNumKeys * sizeof(TclMacThrdData *));
-
- for (i = 0; i < oldMax; i++) {
- newArray[i] = tclMacDataKeyArray[i];
- }
- for (i = oldMax; i < maxNumKeys; i++) {
- newArray[i] = NULL;
- }
-
- if (tclMacDataKeyArray != NULL) {
- ckfree((char *) tclMacDataKeyArray);
- }
- tclMacDataKeyArray = newArray;
-
- }
- /* TclRememberDataKey(keyPtr); */
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpThreadDataKeyGet --
- *
- * This procedure returns a pointer to a block of thread local storage.
- *
- * Results:
- * A thread-specific pointer to the data structure, or NULL
- * if the memory has not been assigned to this key for this thread.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-VOID *
-TclpThreadDataKeyGet(keyPtr)
- Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
- * really (pthread_key_t **) */
-{
- TclMacThrdData *dataPtr;
-
- dataPtr = GetThreadDataStruct(*keyPtr);
-
- if (dataPtr == NULL) {
- return NULL;
- } else {
- return dataPtr->data;
- }
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpThreadDataKeySet --
- *
- * This procedure sets the pointer to a block of thread local storage.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Sets up the thread so future calls to TclpThreadDataKeyGet with
- * this key will return the data pointer.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpThreadDataKeySet(keyPtr, data)
- Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
- * really (pthread_key_t **) */
- VOID *data; /* Thread local storage */
-{
- TclMacThrdData *dataPtr;
- ThreadID curThread;
-
- dataPtr = GetThreadDataStruct(*keyPtr);
-
- /*
- * Is it legal to reset the thread data like this?
- * And if so, who owns the memory?
- */
-
- if (dataPtr != NULL) {
- dataPtr->data = data;
- } else {
- dataPtr = (TclMacThrdData *) ckalloc(sizeof(TclMacThrdData));
- GetCurrentThread(&curThread);
- dataPtr->threadID = curThread;
- dataPtr->data = data;
- dataPtr->next = tclMacDataKeyArray[(int) *keyPtr - 1];
- tclMacDataKeyArray[(int) *keyPtr - 1] = dataPtr;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpFinalizeThreadData --
- *
- * This procedure cleans up the thread-local storage. This is
- * called once for each thread.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Frees up all thread local storage.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpFinalizeThreadData(keyPtr)
- Tcl_ThreadDataKey *keyPtr;
-{
- TclMacThrdData *dataPtr;
-
- if (*keyPtr != NULL) {
- dataPtr = RemoveThreadDataStruct(*keyPtr);
-
- if ((dataPtr != NULL) && (dataPtr->data != NULL)) {
- ckfree((char *) dataPtr->data);
- ckfree((char *) dataPtr);
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpFinalizeThreadDataKey --
- *
- * This procedure is invoked to clean up one key. This is a
- * process-wide storage identifier. The thread finalization code
- * cleans up the thread local storage itself.
- *
- * On the Mac, there is really nothing to do here, since the key
- * is just an array index. But we set the key to 0 just in case
- * someone else is relying on that.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The keyPtr value is set to 0.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpFinalizeThreadDataKey(keyPtr)
- Tcl_ThreadDataKey *keyPtr;
-{
- ckfree((char *) tclMacDataKeyArray[(int) *keyPtr - 1]);
- tclMacDataKeyArray[(int) *keyPtr - 1] = NULL;
- *keyPtr = NULL;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * GetThreadDataStruct --
- *
- * This procedure gets the data structure corresponding to
- * keyVal for the current process.
- *
- * Results:
- * The requested key data.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-TclMacThrdData *
-GetThreadDataStruct(keyVal)
- Tcl_ThreadDataKey keyVal;
-{
- ThreadID curThread;
- TclMacThrdData *dataPtr;
-
- /*
- * The keyPtr will only be greater than keyCounter is someone
- * has passed us a key without getting the value from
- * TclpInitDataKey.
- */
-
- if ((int) keyVal <= 0) {
- return NULL;
- } else if ((int) keyVal > keyCounter) {
- panic("illegal data key value");
- }
-
- GetCurrentThread(&curThread);
-
- for (dataPtr = tclMacDataKeyArray[(int) keyVal - 1]; dataPtr != NULL;
- dataPtr = dataPtr->next) {
- if (dataPtr->threadID == curThread) {
- break;
- }
- }
-
- return dataPtr;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * RemoveThreadDataStruct --
- *
- * This procedure removes the data structure corresponding to
- * keyVal for the current process from the list kept for keyVal.
- *
- * Results:
- * The requested key data is removed from the list, and a pointer
- * to it is returned.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-TclMacThrdData *
-RemoveThreadDataStruct(keyVal)
- Tcl_ThreadDataKey keyVal;
-{
- ThreadID curThread;
- TclMacThrdData *dataPtr, *prevPtr;
-
-
- if ((int) keyVal <= 0) {
- return NULL;
- } else if ((int) keyVal > keyCounter) {
- panic("illegal data key value");
- }
-
- GetCurrentThread(&curThread);
-
- for (dataPtr = tclMacDataKeyArray[(int) keyVal - 1], prevPtr = NULL;
- dataPtr != NULL;
- prevPtr = dataPtr, dataPtr = dataPtr->next) {
- if (dataPtr->threadID == curThread) {
- break;
- }
- }
-
- if (dataPtr == NULL) {
- /* No body */
- } else if ( prevPtr == NULL) {
- tclMacDataKeyArray[(int) keyVal - 1] = dataPtr->next;
- } else {
- prevPtr->next = dataPtr->next;
- }
-
- return dataPtr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_ConditionWait --
- *
- * This procedure is invoked to wait on a condition variable.
- * On the Mac, mutexes are no-ops, and we just yield. After
- * all, it is the application's job to loop till the condition
- * variable is changed...
- *
- *
- * Results:
- * None.
- *
- * Side effects:
- * Will block the current thread till someone else yields.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
- Tcl_Condition *condPtr; /* Really (pthread_cond_t **) */
- Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */
- Tcl_Time *timePtr; /* Timeout on waiting period */
-{
- if (TclMacHaveThreads()) {
- YieldToAnyThread();
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_ConditionNotify --
- *
- * This procedure is invoked to signal a condition variable.
- *
- * The mutex must be held during this call to avoid races,
- * but this interface does not enforce that.
- *
- * Results:
- * None.
- *
- * Side effects:
- * May unblock another thread.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tcl_ConditionNotify(condPtr)
- Tcl_Condition *condPtr;
-{
- if (TclMacHaveThreads()) {
- YieldToAnyThread();
- }
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpFinalizeCondition --
- *
- * This procedure is invoked to clean up a condition variable.
- * This is only safe to call at the end of time.
- *
- * This assumes the Master Lock is held.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The condition variable is deallocated.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpFinalizeCondition(condPtr)
- Tcl_Condition *condPtr;
-{
- /* Nothing to do on the Mac */
-}
-
-
-
-#endif /* TCL_THREADS */
-
diff --git a/mac/tclMacThrd.h b/mac/tclMacThrd.h
deleted file mode 100644
index 7872f3d..0000000
--- a/mac/tclMacThrd.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * tclUnixThrd.h --
- *
- * This header file defines things for thread support.
- *
- * Copyright (c) 1998 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#ifndef _TCLMACTHRD
-#define _TCLMACTHRD
-
-#ifdef TCL_THREADS
-
-#endif /* TCL_THREADS */
-#endif /* _TCLMACTHRD */
diff --git a/mac/tclMacTime.c b/mac/tclMacTime.c
deleted file mode 100644
index 3761eca..0000000
--- a/mac/tclMacTime.c
+++ /dev/null
@@ -1,433 +0,0 @@
-/*
- * tclMacTime.c --
- *
- * Contains Macintosh specific versions of Tcl functions that
- * obtain time values from the operating system.
- *
- * Copyright (c) 1995-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include "tclInt.h"
-#include "tclPort.h"
-#include "tclMacInt.h"
-#include <OSUtils.h>
-#include <Timer.h>
-#include <time.h>
-
-/*
- * Static variables used by the Tcl_GetTime function.
- */
-
-static int initalized = false;
-static unsigned long baseSeconds;
-static UnsignedWide microOffset;
-
-static int gmt_initialized = false;
-static long gmt_offset;
-static int gmt_isdst;
-TCL_DECLARE_MUTEX(gmtMutex)
-
-static int gmt_lastGetDateUseGMT = 0;
-
-typedef struct _TABLE {
- char *name;
- int type;
- time_t value;
-} TABLE;
-
-
-#define HOUR(x) ((time_t) (3600 * x))
-
-#define tZONE 0
-#define tDAYZONE 1
-
-
-/*
- * inverse timezone table, adapted from tclDate.c by removing duplicates and
- * adding some made up names for unusual daylight savings
- */
-static TABLE invTimezoneTable[] = {
- { "Z", -1, HOUR( 36) }, /* Unknown */
- { "GMT", tZONE, HOUR( 0) }, /* Greenwich Mean */
- { "BST", tDAYZONE, HOUR( 0) }, /* British Summer */
- { "WAT", tZONE, HOUR( 1) }, /* West Africa */
- { "WADST", tDAYZONE, HOUR( 1) }, /* West Africa Daylight*/
- { "AT", tZONE, HOUR( 2) }, /* Azores Daylight*/
- { "ADST", tDAYZONE, HOUR( 2) }, /* Azores */
- { "NFT", tZONE, HOUR( 7/2) }, /* Newfoundland */
- { "NDT", tDAYZONE, HOUR( 7/2) }, /* Newfoundland Daylight */
- { "AST", tZONE, HOUR( 4) }, /* Atlantic Standard */
- { "ADT", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
- { "EST", tZONE, HOUR( 5) }, /* Eastern Standard */
- { "EDT", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
- { "CST", tZONE, HOUR( 6) }, /* Central Standard */
- { "CDT", tDAYZONE, HOUR( 6) }, /* Central Daylight */
- { "MST", tZONE, HOUR( 7) }, /* Mountain Standard */
- { "MDT", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
- { "PST", tZONE, HOUR( 8) }, /* Pacific Standard */
- { "PDT", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
- { "YST", tZONE, HOUR( 9) }, /* Yukon Standard */
- { "YDT", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
- { "HST", tZONE, HOUR(10) }, /* Hawaii Standard */
- { "HDT", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
- { "NT", tZONE, HOUR(11) }, /* Nome */
- { "NST", tDAYZONE, HOUR(11) }, /* Nome Daylight*/
- { "IDLW", tZONE, HOUR(12) }, /* International Date Line West */
- { "CET", tZONE, -HOUR( 1) }, /* Central European */
- { "CEST", tDAYZONE, -HOUR( 1) }, /* Central European Summer */
- { "EET", tZONE, -HOUR( 2) }, /* Eastern Europe, USSR Zone 1 */
- { "EEST", tDAYZONE, -HOUR( 2) }, /* Eastern Europe, USSR Zone 1 Daylight*/
- { "BT", tZONE, -HOUR( 3) }, /* Baghdad, USSR Zone 2 */
- { "BDST", tDAYZONE, -HOUR( 3) }, /* Baghdad, USSR Zone 2 Daylight*/
- { "IT", tZONE, -HOUR( 7/2) }, /* Iran */
- { "IDST", tDAYZONE, -HOUR( 7/2) }, /* Iran Daylight*/
- { "ZP4", tZONE, -HOUR( 4) }, /* USSR Zone 3 */
- { "ZP4S", tDAYZONE, -HOUR( 4) }, /* USSR Zone 3 */
- { "ZP5", tZONE, -HOUR( 5) }, /* USSR Zone 4 */
- { "ZP5S", tDAYZONE, -HOUR( 5) }, /* USSR Zone 4 */
- { "IST", tZONE, -HOUR(11/2) }, /* Indian Standard */
- { "ISDST", tDAYZONE, -HOUR(11/2) }, /* Indian Standard */
- { "ZP6", tZONE, -HOUR( 6) }, /* USSR Zone 5 */
- { "ZP6S", tDAYZONE, -HOUR( 6) }, /* USSR Zone 5 */
- { "WAST", tZONE, -HOUR( 7) }, /* West Australian Standard */
- { "WADT", tDAYZONE, -HOUR( 7) }, /* West Australian Daylight */
- { "JT", tZONE, -HOUR(15/2) }, /* Java (3pm in Cronusland!) */
- { "JDST", tDAYZONE, -HOUR(15/2) }, /* Java (3pm in Cronusland!) */
- { "CCT", tZONE, -HOUR( 8) }, /* China Coast, USSR Zone 7 */
- { "CCST", tDAYZONE, -HOUR( 8) }, /* China Coast, USSR Zone 7 */
- { "JST", tZONE, -HOUR( 9) }, /* Japan Standard, USSR Zone 8 */
- { "JSDST", tDAYZONE, -HOUR( 9) }, /* Japan Standard, USSR Zone 8 */
- { "CAST", tZONE, -HOUR(19/2) }, /* Central Australian Standard */
- { "CADT", tDAYZONE, -HOUR(19/2) }, /* Central Australian Daylight */
- { "EAST", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
- { "EADT", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
- { "NZT", tZONE, -HOUR(12) }, /* New Zealand */
- { "NZDT", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
- { NULL }
-};
-
-/*
- * Prototypes for procedures that are private to this file:
- */
-
-static void SubtractUnsignedWide _ANSI_ARGS_((UnsignedWide *x,
- UnsignedWide *y, UnsignedWide *result));
-
-/*
- *-----------------------------------------------------------------------------
- *
- * TclpGetGMTOffset --
- *
- * This procedure gets the offset seconds that needs to be _added_ to tcl time
- * in seconds (i.e. GMT time) to get local time needed as input to various
- * Mac OS APIs, to convert Mac OS API output to tcl time, _subtract_ this value.
- *
- * Results:
- * Number of seconds separating GMT time and mac.
- *
- * Side effects:
- * None.
- *
- *-----------------------------------------------------------------------------
- */
-
-long
-TclpGetGMTOffset()
-{
- if (gmt_initialized == false) {
- MachineLocation loc;
-
- Tcl_MutexLock(&gmtMutex);
- ReadLocation(&loc);
- gmt_offset = loc.u.gmtDelta & 0x00ffffff;
- if (gmt_offset & 0x00800000) {
- gmt_offset = gmt_offset | 0xff000000;
- }
- gmt_isdst=(loc.u.dlsDelta < 0);
- gmt_initialized = true;
- Tcl_MutexUnlock(&gmtMutex);
- }
- return (gmt_offset);
-}
-
-/*
- *-----------------------------------------------------------------------------
- *
- * TclpGetSeconds --
- *
- * This procedure returns the number of seconds from the epoch. On
- * the Macintosh the epoch is Midnight Jan 1, 1904. Unfortunatly,
- * the Macintosh doesn't tie the epoch to a particular time zone. For
- * Tcl we tie the epoch to GMT. This makes the time zone date parsing
- * code work. The epoch for Mac-Tcl is: Midnight Jan 1, 1904 GMT.
- *
- * Results:
- * Number of seconds from the epoch in GMT.
- *
- * Side effects:
- * None.
- *
- *-----------------------------------------------------------------------------
- */
-
-unsigned long
-TclpGetSeconds()
-{
- unsigned long seconds;
-
- GetDateTime(&seconds);
- return (seconds - TclpGetGMTOffset() + tcl_mac_epoch_offset);
-}
-
-/*
- *-----------------------------------------------------------------------------
- *
- * TclpGetClicks --
- *
- * This procedure returns a value that represents the highest resolution
- * clock available on the system. There are no garantees on what the
- * resolution will be. In Tcl we will call this value a "click". The
- * start time is also system dependant.
- *
- * Results:
- * Number of clicks from some start time.
- *
- * Side effects:
- * None.
- *
- *-----------------------------------------------------------------------------
- */
-
-unsigned long
-TclpGetClicks()
-{
- UnsignedWide micros;
-
- Microseconds(&micros);
- return micros.lo;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpGetTimeZone --
- *
- * Get the current time zone.
- *
- * Results:
- * The return value is the local time zone, measured in
- * minutes away from GMT (-ve for east, +ve for west).
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclpGetTimeZone (
- unsigned long currentTime) /* Ignored on Mac. */
-{
- long offset;
-
- /*
- * Convert the Mac offset from seconds to minutes and
- * add an hour if we have daylight savings time.
- */
- offset = -TclpGetGMTOffset();
- offset /= 60;
- if (gmt_isdst) {
- offset += 60;
- }
-
- return offset;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_GetTime --
- *
- * Gets the current system time in seconds and microseconds
- * since the beginning of the epoch: 00:00 UCT, January 1, 1970.
- *
- * Results:
- * Returns the current time (in the local timezone) in timePtr.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tcl_GetTime(
- Tcl_Time *timePtr) /* Location to store time information. */
-{
- UnsignedWide micro;
-#ifndef NO_LONG_LONG
- long long *microPtr;
-#endif
-
- if (initalized == false) {
- GetDateTime(&baseSeconds);
- /*
- * Remove the local offset that ReadDateTime() adds.
- */
- baseSeconds -= TclpGetGMTOffset() - tcl_mac_epoch_offset;
- Microseconds(&microOffset);
- initalized = true;
- }
-
- Microseconds(&micro);
-
-#ifndef NO_LONG_LONG
- microPtr = (long long *) &micro;
- *microPtr -= *((long long *) &microOffset);
- timePtr->sec = baseSeconds + (*microPtr / 1000000);
- timePtr->usec = *microPtr % 1000000;
-#else
- SubtractUnsignedWide(&micro, &microOffset, &micro);
-
- /*
- * This lovely computation is equal to: base + (micro / 1000000)
- * For the .hi part the ratio of 0x100000000 / 1000000 has been
- * reduced to avoid overflow. This computation certainly has
- * problems as the .hi part gets large. However, your application
- * would have to run for a long time to make that happen.
- */
-
- timePtr->sec = baseSeconds + (micro.lo / 1000000) +
- (long) (micro.hi * ((double) 33554432.0 / 15625.0));
- timePtr->usec = micro.lo % 1000000;
-#endif
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpGetDate --
- *
- * Converts raw seconds to a struct tm data structure. The
- * returned time will be for Greenwich Mean Time if the useGMT flag
- * is set. Otherwise, the returned time will be for the local
- * time zone. This function is meant to be used as a replacement
- * for localtime and gmtime which is broken on most ANSI libs
- * on the Macintosh.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The passed in struct tm data structure is modified.
- *
- *----------------------------------------------------------------------
- */
-
-struct tm *
-TclpGetDate(
- TclpTime_t time, /* Time struct to fill. */
- int useGMT) /* True if date should reflect GNT time. */
-{
- const time_t *tp = (const time_t *)time;
- DateTimeRec dtr;
- unsigned long offset=0L;
- static struct tm statictime;
- static const short monthday[12] =
- {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
-
- if(useGMT)
- SecondsToDate(*tp - tcl_mac_epoch_offset, &dtr);
- else
- SecondsToDate(*tp + TclpGetGMTOffset() - tcl_mac_epoch_offset, &dtr);
-
- statictime.tm_sec = dtr.second;
- statictime.tm_min = dtr.minute;
- statictime.tm_hour = dtr.hour;
- statictime.tm_mday = dtr.day;
- statictime.tm_mon = dtr.month - 1;
- statictime.tm_year = dtr.year - 1900;
- statictime.tm_wday = dtr.dayOfWeek - 1;
- statictime.tm_yday = monthday[statictime.tm_mon]
- + statictime.tm_mday - 1;
- if (1 < statictime.tm_mon && !(statictime.tm_year & 3)) {
- ++statictime.tm_yday;
- }
- if(useGMT)
- statictime.tm_isdst = 0;
- else
- statictime.tm_isdst = gmt_isdst;
- gmt_lastGetDateUseGMT=useGMT; /* hack to make TclpGetTZName below work */
- return(&statictime);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpGetTZName --
- *
- * Gets the current timezone string.
- *
- * Results:
- * Returns a pointer to a static string, or NULL on failure.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-char *
-TclpGetTZName(int dst)
-{
- register TABLE *tp;
- long zonevalue=-TclpGetGMTOffset();
-
- if (gmt_isdst)
- zonevalue += HOUR(1);
-
- if(gmt_lastGetDateUseGMT) /* hack: if last TclpGetDate was called */
- zonevalue=0; /* with useGMT==1 then we're using GMT */
-
- for (tp = invTimezoneTable; tp->name; tp++) {
- if ((tp->value == zonevalue) && (tp->type == dst)) break;
- }
- if(!tp->name)
- tp = invTimezoneTable; /* default to unknown */
-
- return tp->name;
-}
-
-#ifdef NO_LONG_LONG
-/*
- *----------------------------------------------------------------------
- *
- * SubtractUnsignedWide --
- *
- * Subtracts one UnsignedWide value from another.
- *
- * Results:
- * The subtracted value.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-SubtractUnsignedWide(
- UnsignedWide *x, /* Ptr to wide int. */
- UnsignedWide *y, /* Ptr to wide int. */
- UnsignedWide *result) /* Ptr to result. */
-{
- result->hi = x->hi - y->hi;
- if (x->lo < y->lo) {
- result->hi--;
- }
- result->lo = x->lo - y->lo;
-}
-#endif
diff --git a/mac/tclMacUnix.c b/mac/tclMacUnix.c
deleted file mode 100644
index 6a9d398..0000000
--- a/mac/tclMacUnix.c
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * tclMacUnix.c --
- *
- * This file contains routines to implement several features
- * available to the Unix implementation, but that require
- * extra work to do on a Macintosh. These include routines
- * Unix Tcl normally hands off to the Unix OS.
- *
- * Copyright (c) 1993-1994 Lockheed Missle & Space Company, AI Center
- * Copyright (c) 1994-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include <Files.h>
-#include <Strings.h>
-#include <TextUtils.h>
-#include <Finder.h>
-#include <FSpCompat.h>
-#include <Aliases.h>
-#include <Errors.h>
-
-#include "tclInt.h"
-#include "tclMacInt.h"
-
-/*
- * The following two Includes are from the More Files package
- */
-#include "FileCopy.h"
-#include "MoreFiles.h"
-#include "MoreFilesExtras.h"
-
-/*
- * The following may not be defined in some versions of
- * MPW header files.
- */
-#ifndef kIsInvisible
-#define kIsInvisible 0x4000
-#endif
-#ifndef kIsAlias
-#define kIsAlias 0x8000
-#endif
-
-/*
- * Missing error codes
- */
-#define usageErr 500
-#define noSourceErr 501
-#define isDirErr 502
-
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_EchoCmd --
- *
- * Implements the TCL echo command:
- * echo ?str ...?
- *
- * Results:
- * Always returns TCL_OK.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-Tcl_EchoCmd(
- ClientData dummy, /* Not used. */
- Tcl_Interp *interp, /* Current interpreter. */
- int argc, /* Number of arguments. */
- CONST char **argv) /* Argument strings. */
-{
- Tcl_Channel chan;
- int mode, result, i;
-
- chan = Tcl_GetChannel(interp, "stdout", &mode);
- if (chan == (Tcl_Channel) NULL) {
- return TCL_ERROR;
- }
- for (i = 1; i < argc; i++) {
- result = Tcl_WriteChars(chan, argv[i], -1);
- if (result < 0) {
- Tcl_AppendResult(interp, "echo: ", Tcl_GetChannelName(chan),
- ": ", Tcl_PosixError(interp), (char *) NULL);
- return TCL_ERROR;
- }
- if (i < (argc - 1)) {
- Tcl_WriteChars(chan, " ", -1);
- }
- }
- Tcl_WriteChars(chan, "\n", -1);
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_LsObjCmd --
- *
- * This procedure is invoked to process the "ls" Tcl command.
- * See the user documentation for details on what it does.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * See the user documentation.
- *
- *----------------------------------------------------------------------
- */
-int
-Tcl_LsObjCmd(
- ClientData dummy, /* Not used. */
- Tcl_Interp *interp, /* Current interpreter. */
- int objc, /* Number of arguments. */
- Tcl_Obj *CONST objv[]) /* Argument strings. */
-{
-#define STRING_LENGTH 80
-#define CR '\n'
- int i, j;
- int fieldLength, len = 0, maxLen = 0, perLine;
- OSErr err;
- CInfoPBRec paramBlock;
- HFileInfo *hpb = (HFileInfo *)&paramBlock;
- DirInfo *dpb = (DirInfo *)&paramBlock;
- char theFile[256];
- char theLine[STRING_LENGTH + 2];
- int fFlag = false, pFlag = false, aFlag = false, lFlag = false,
- cFlag = false, hFlag = false;
- char *argv;
- Tcl_Obj *newObjv[2], *resultObjPtr;
-
- /*
- * Process command flags. End if argument doesn't start
- * with a dash or is a dash by itself. The remaining arguments
- * should be files.
- */
- for (i = 1; i < objc; i++) {
- argv = Tcl_GetString(objv[i]);
- if (argv[0] != '-') {
- break;
- }
-
- if (!strcmp(argv, "-")) {
- i++;
- break;
- }
-
- for (j = 1 ; argv[j] ; ++j) {
- switch(argv[j]) {
- case 'a':
- case 'A':
- aFlag = true;
- break;
- case '1':
- cFlag = false;
- break;
- case 'C':
- cFlag = true;
- break;
- case 'F':
- fFlag = true;
- break;
- case 'H':
- hFlag = true;
- break;
- case 'p':
- pFlag = true;
- break;
- case 'l':
- pFlag = false;
- lFlag = true;
- break;
- default:
- Tcl_AppendResult(interp, "error - unknown flag ",
- "usage: ls -apCFHl1 ?files? ", NULL);
- return TCL_ERROR;
- }
- }
- }
-
- objv += i;
- objc -= i;
-
- /*
- * No file specifications means we search for all files.
- * Glob will be doing most of the work.
- */
- if (!objc) {
- objc = 1;
- newObjv[0] = Tcl_NewStringObj("*", -1);
- newObjv[1] = NULL;
- objv = newObjv;
- }
-
- if (Tcl_GlobObjCmd(NULL, interp, objc + 1, objv - 1) != TCL_OK) {
- Tcl_ResetResult(interp);
- return TCL_ERROR;
- }
-
- resultObjPtr = Tcl_GetObjResult(interp);
- Tcl_IncrRefCount(resultObjPtr);
- if (Tcl_ListObjGetElements(interp, resultObjPtr, &objc, (Tcl_Obj ***)&objv) != TCL_OK) {
- Tcl_DecrRefCount(resultObjPtr);
- return TCL_ERROR;
- }
-
- Tcl_ResetResult(interp);
-
- /*
- * There are two major methods for listing files: the long
- * method and the normal method.
- */
- if (lFlag) {
- char creator[5], type[5], time[16], date[16];
- char lineTag;
- long size;
- unsigned short flags;
- Tcl_Obj *objPtr;
- char *string;
- int length;
-
- /*
- * Print the header for long listing.
- */
- if (hFlag) {
- sprintf(theLine, "T %7s %8s %8s %4s %4s %6s %s",
- "Size", "ModTime", "ModDate",
- "CRTR", "TYPE", "Flags", "Name");
- Tcl_AppendResult(interp, theLine, "\n", NULL);
- Tcl_AppendResult(interp,
- "-------------------------------------------------------------\n",
- NULL);
- }
-
- for (i = 0; i < objc; i++) {
- strcpy(theFile, Tcl_GetString(objv[i]));
-
- c2pstr(theFile);
- hpb->ioCompletion = NULL;
- hpb->ioVRefNum = 0;
- hpb->ioFDirIndex = 0;
- hpb->ioNamePtr = (StringPtr) theFile;
- hpb->ioDirID = 0L;
- err = PBGetCatInfoSync(&paramBlock);
- p2cstr((StringPtr) theFile);
-
- if (hpb->ioFlAttrib & 16) {
- /*
- * For directories use zero as the size, use no Creator
- * type, and use 'DIR ' as the file type.
- */
- if ((aFlag == false) && (dpb->ioDrUsrWds.frFlags & 0x1000)) {
- continue;
- }
- lineTag = 'D';
- size = 0;
- IUTimeString(dpb->ioDrMdDat, false, (unsigned char *)time);
- p2cstr((StringPtr)time);
- IUDateString(dpb->ioDrMdDat, shortDate, (unsigned char *)date);
- p2cstr((StringPtr)date);
- strcpy(creator, " ");
- strcpy(type, "DIR ");
- flags = dpb->ioDrUsrWds.frFlags;
- if (fFlag || pFlag) {
- strcat(theFile, ":");
- }
- } else {
- /*
- * All information for files should be printed. This
- * includes size, modtime, moddate, creator type, file
- * type, flags, anf file name.
- */
- if ((aFlag == false) &&
- (hpb->ioFlFndrInfo.fdFlags & kIsInvisible)) {
- continue;
- }
- lineTag = 'F';
- size = hpb->ioFlLgLen + hpb->ioFlRLgLen;
- IUTimeString(hpb->ioFlMdDat, false, (unsigned char *)time);
- p2cstr((StringPtr)time);
- IUDateString(hpb->ioFlMdDat, shortDate, (unsigned char *)date);
- p2cstr((StringPtr)date);
- strncpy(creator, (char *) &hpb->ioFlFndrInfo.fdCreator, 4);
- creator[4] = 0;
- strncpy(type, (char *) &hpb->ioFlFndrInfo.fdType, 4);
- type[4] = 0;
- flags = hpb->ioFlFndrInfo.fdFlags;
- if (fFlag) {
- if (hpb->ioFlFndrInfo.fdFlags & kIsAlias) {
- strcat(theFile, "@");
- } else if (hpb->ioFlFndrInfo.fdType == 'APPL') {
- strcat(theFile, "*");
- }
- }
- }
-
- sprintf(theLine, "%c %7ld %8s %8s %-4.4s %-4.4s 0x%4.4X %s",
- lineTag, size, time, date, creator, type, flags, theFile);
-
- Tcl_AppendResult(interp, theLine, "\n", NULL);
-
- }
-
- objPtr = Tcl_GetObjResult(interp);
- string = Tcl_GetStringFromObj(objPtr, &length);
- if ((length > 0) && (string[length - 1] == '\n')) {
- Tcl_SetObjLength(objPtr, length - 1);
- }
- } else {
- /*
- * Not in long format. We only print files names. If the
- * -C flag is set we need to print in multiple coloumns.
- */
- int argCount, linePos;
- Boolean needNewLine = false;
-
- /*
- * Fiend the field length: the length each string printed
- * to the terminal will be.
- */
- if (!cFlag) {
- perLine = 1;
- fieldLength = STRING_LENGTH;
- } else {
- for (i = 0; i < objc; i++) {
- argv = Tcl_GetString(objv[i]);
- len = strlen(argv);
- if (len > maxLen) {
- maxLen = len;
- }
- }
- fieldLength = maxLen + 3;
- perLine = STRING_LENGTH / fieldLength;
- }
-
- argCount = 0;
- linePos = 0;
- memset(theLine, ' ', STRING_LENGTH);
- while (argCount < objc) {
- strcpy(theFile, Tcl_GetString(objv[argCount]));
-
- c2pstr(theFile);
- hpb->ioCompletion = NULL;
- hpb->ioVRefNum = 0;
- hpb->ioFDirIndex = 0;
- hpb->ioNamePtr = (StringPtr) theFile;
- hpb->ioDirID = 0L;
- err = PBGetCatInfoSync(&paramBlock);
- p2cstr((StringPtr) theFile);
-
- if (hpb->ioFlAttrib & 16) {
- /*
- * Directory. If -a show hidden files. If -f or -p
- * denote that this is a directory.
- */
- if ((aFlag == false) && (dpb->ioDrUsrWds.frFlags & 0x1000)) {
- argCount++;
- continue;
- }
- if (fFlag || pFlag) {
- strcat(theFile, ":");
- }
- } else {
- /*
- * File: If -a show hidden files, if -f show links
- * (aliases) and executables (APPLs).
- */
- if ((aFlag == false) &&
- (hpb->ioFlFndrInfo.fdFlags & kIsInvisible)) {
- argCount++;
- continue;
- }
- if (fFlag) {
- if (hpb->ioFlFndrInfo.fdFlags & kIsAlias) {
- strcat(theFile, "@");
- } else if (hpb->ioFlFndrInfo.fdType == 'APPL') {
- strcat(theFile, "*");
- }
- }
- }
-
- /*
- * Print the item, taking into account multi-
- * coloum output.
- */
- strncpy(theLine + (linePos * fieldLength), theFile,
- strlen(theFile));
- linePos++;
-
- if (linePos == perLine) {
- theLine[STRING_LENGTH] = '\0';
- if (needNewLine) {
- Tcl_AppendResult(interp, "\n", theLine, NULL);
- } else {
- Tcl_AppendResult(interp, theLine, NULL);
- needNewLine = true;
- }
- linePos = 0;
- memset(theLine, ' ', STRING_LENGTH);
- }
-
- argCount++;
- }
-
- if (linePos != 0) {
- theLine[STRING_LENGTH] = '\0';
- if (needNewLine) {
- Tcl_AppendResult(interp, "\n", theLine, NULL);
- } else {
- Tcl_AppendResult(interp, theLine, NULL);
- }
- }
- }
-
- Tcl_DecrRefCount(resultObjPtr);
-
- return TCL_OK;
-}
diff --git a/mac/tclMacUtil.c b/mac/tclMacUtil.c
deleted file mode 100644
index eea9631..0000000
--- a/mac/tclMacUtil.c
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- * tclMacUtil.c --
- *
- * This contains utility functions used to help with
- * implementing Macintosh specific portions of the Tcl port.
- *
- * Copyright (c) 1993-1994 Lockheed Missle & Space Company, AI Center
- * Copyright (c) 1995-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include "tcl.h"
-#include "tclInt.h"
-#include "tclMacInt.h"
-#include "tclMath.h"
-#include "tclMacPort.h"
-
-#include <Aliases.h>
-#include <Errors.h>
-#include <Files.h>
-#include <Folders.h>
-#include <FSpCompat.h>
-#include <Strings.h>
-#include <TextUtils.h>
-#include <MoreFilesExtras.h>
-
-/*
- * The following two Includes are from the More Files package.
- */
-#include <FileCopy.h>
-#include <MoreFiles.h>
-
-/*
- *----------------------------------------------------------------------
- *
- * hypotd --
- *
- * The standard math function hypot is not supported by Think C.
- * It is included here so everything works. It is supported by
- * CodeWarrior Pro 1, but the 68K version does not support doubles.
- * So we hack it in.
- *
- * Results:
- * Result of computation.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-#if defined(THINK_C)
-double hypotd(double x, double y);
-
-double
-hypotd(
- double x, /* X value */
- double y) /* Y value */
-{
- double sum;
-
- sum = x*x + y*y;
- return sqrt(sum);
-}
-#endif
-
-/*
- *----------------------------------------------------------------------
- *
- * FSpGetDefaultDir --
- *
- * This function gets the current default directory.
- *
- * Results:
- * The provided FSSpec is changed to point to the "default"
- * directory. The function returns what ever errors
- * FSMakeFSSpecCompat may encounter.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-FSpGetDefaultDir(
- FSSpecPtr dirSpec) /* On return the default directory. */
-{
- OSErr err;
- short vRefNum = 0;
- long int dirID = 0;
-
- err = HGetVol(NULL, &vRefNum, &dirID);
-
- if (err == noErr) {
- err = FSMakeFSSpecCompat(vRefNum, dirID, (ConstStr255Param) NULL,
- dirSpec);
- }
-
- return err;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * FSpSetDefaultDir --
- *
- * This function sets the default directory to the directory
- * pointed to by the provided FSSpec.
- *
- * Results:
- * The function returns what ever errors HSetVol may encounter.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-FSpSetDefaultDir(
- FSSpecPtr dirSpec) /* The new default directory. */
-{
- OSErr err;
-
- /*
- * The following special case is needed to work around a bug
- * in the Macintosh OS. (Acutally PC Exchange.)
- */
-
- if (dirSpec->parID == fsRtParID) {
- err = HSetVol(NULL, dirSpec->vRefNum, fsRtDirID);
- } else {
- err = HSetVol(dirSpec->name, dirSpec->vRefNum, dirSpec->parID);
- }
-
- return err;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * FSpFindFolder --
- *
- * This function is a version of the FindFolder function that
- * returns the result as a FSSpec rather than a vRefNum and dirID.
- *
- * Results:
- * Results will be simaler to that of the FindFolder function.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-OSErr
-FSpFindFolder(
- short vRefNum, /* Volume reference number. */
- OSType folderType, /* Folder type taken by FindFolder. */
- Boolean createFolder, /* Should we create it if non-existant. */
- FSSpec *spec) /* Pointer to resulting directory. */
-{
- short foundVRefNum;
- long foundDirID;
- OSErr err;
-
- err = FindFolder(vRefNum, folderType, createFolder,
- &foundVRefNum, &foundDirID);
- if (err != noErr) {
- return err;
- }
-
- err = FSMakeFSSpecCompat(foundVRefNum, foundDirID, "\p", spec);
- return err;
-}
-
-static int
-FSpLocationFromPathAlias _ANSI_ARGS_((int length, CONST char *path,
- FSSpecPtr fileSpecPtr, Boolean resolveLink));
-
-/*
- *----------------------------------------------------------------------
- *
- * FSpLocationFromPath --
- *
- * This function obtains an FSSpec for a given macintosh path.
- * Unlike the More Files function FSpLocationFromFullPath, this
- * function will also accept partial paths and resolve any aliases
- * along the path.
- *
- * Results:
- * OSErr code.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-FSpLocationFromPath(
- int length, /* Length of path. */
- CONST char *path, /* The path to convert. */
- FSSpecPtr fileSpecPtr) /* On return the spec for the path. */
-{
- return FSpLocationFromPathAlias(length, path, fileSpecPtr, TRUE);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * FSpLLocationFromPath --
- *
- * This function obtains an FSSpec for a given macintosh path.
- * Unlike the More Files function FSpLocationFromFullPath, this
- * function will also accept partial paths and resolve any aliases
- * along the path expect for the last path component.
- *
- * Results:
- * OSErr code.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-FSpLLocationFromPath(
- int length, /* Length of path. */
- CONST char *path, /* The path to convert. */
- FSSpecPtr fileSpecPtr) /* On return the spec for the path. */
-{
- return FSpLocationFromPathAlias(length, path, fileSpecPtr, FALSE);
-}
-
-static int
-FSpLocationFromPathAlias(
- int length, /* Length of path. */
- CONST char *path, /* The path to convert. */
- FSSpecPtr fileSpecPtr, /* On return the spec for the path. */
- Boolean resolveLink) /* Resolve the last path component? */
-{
- Str255 fileName;
- OSErr err;
- short vRefNum;
- long dirID;
- int pos, cur;
- Boolean isDirectory;
- Boolean wasAlias=FALSE;
- FSSpec lastFileSpec;
-
- /*
- * Check to see if this is a full path. If partial
- * we assume that path starts with the current working
- * directory. (Ie. volume & dir = 0)
- */
- vRefNum = 0;
- dirID = 0;
- cur = 0;
- if (length == 0) {
- return fnfErr;
- }
- if (path[cur] == ':') {
- cur++;
- if (cur >= length) {
- /*
- * If path = ":", just return current directory.
- */
- FSMakeFSSpecCompat(0, 0, NULL, fileSpecPtr);
- return noErr;
- }
- } else {
- while (path[cur] != ':' && cur < length) {
- cur++;
- }
- if (cur > 255) {
- return bdNamErr;
- }
- if (cur < length) {
- /*
- * This is a full path
- */
- cur++;
- strncpy((char *) fileName + 1, path, cur);
- fileName[0] = cur;
- err = FSMakeFSSpecCompat(0, 0, fileName, fileSpecPtr);
- if (err != noErr) return err;
- FSpGetDirectoryID(fileSpecPtr, &dirID, &isDirectory);
- vRefNum = fileSpecPtr->vRefNum;
- } else {
- cur = 0;
- }
- }
-
- isDirectory = 1;
- while (cur < length) {
- if (!isDirectory) {
- return dirNFErr;
- }
- pos = cur;
- while (path[pos] != ':' && pos < length) {
- pos++;
- }
- if (pos == cur) {
- /* Move up one dir */
- /* cur++; */
- strcpy((char *) fileName + 1, "::");
- fileName[0] = 2;
- } else if (pos - cur > 255) {
- return bdNamErr;
- } else {
- strncpy((char *) fileName + 1, &path[cur], pos - cur);
- fileName[0] = pos - cur;
- }
- err = FSMakeFSSpecCompat(vRefNum, dirID, fileName, fileSpecPtr);
- if (err != noErr) return err;
- lastFileSpec=*fileSpecPtr;
- err = ResolveAliasFile(fileSpecPtr, true, &isDirectory, &wasAlias);
- if (err != noErr) {
- /* ignore alias resolve errors on last path component */
- if (pos < length) return err;
- else *fileSpecPtr=lastFileSpec;
- }
- FSpGetDirectoryID(fileSpecPtr, &dirID, &isDirectory);
- vRefNum = fileSpecPtr->vRefNum;
- cur = pos;
- if (path[cur] == ':') {
- cur++;
- }
- }
-
- if(!resolveLink && wasAlias)
- *fileSpecPtr=lastFileSpec;
-
- return noErr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * FSpPathFromLocation --
- *
- * This function obtains a full path name for a given macintosh
- * FSSpec. Unlike the More Files function FSpGetFullPath, this
- * function will return a C string in the Handle. It also will
- * create paths for FSSpec that do not yet exist.
- *
- * Results:
- * OSErr code.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-OSErr
-FSpPathFromLocation(
- FSSpec *spec, /* The location we want a path for. */
- int *length, /* Length of the resulting path. */
- Handle *fullPath) /* Handle to path. */
-{
- OSErr err;
- FSSpec tempSpec;
- CInfoPBRec pb;
-
- *fullPath = NULL;
-
- /*
- * Make a copy of the input FSSpec that can be modified.
- */
- BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
-
- if (tempSpec.parID == fsRtParID) {
- /*
- * The object is a volume. Add a colon to make it a full
- * pathname. Allocate a handle for it and we are done.
- */
- tempSpec.name[0] += 2;
- tempSpec.name[tempSpec.name[0] - 1] = ':';
- tempSpec.name[tempSpec.name[0]] = '\0';
-
- err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
- } else {
- /*
- * The object isn't a volume. Is the object a file or a directory?
- */
- pb.dirInfo.ioNamePtr = tempSpec.name;
- pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
- pb.dirInfo.ioDrDirID = tempSpec.parID;
- pb.dirInfo.ioFDirIndex = 0;
- err = PBGetCatInfoSync(&pb);
-
- if ((err == noErr) || (err == fnfErr)) {
- /*
- * If the file doesn't currently exist we start over. If the
- * directory exists everything will work just fine. Otherwise we
- * will just fail later. If the object is a directory, append a
- * colon so full pathname ends with colon, but only if the name is
- * not empty. NavServices returns FSSpec's with the parent ID set,
- * but the name empty...
- */
- if (err == fnfErr) {
- BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
- } else if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 ) {
- if (tempSpec.name[0] > 0) {
- tempSpec.name[0] += 1;
- tempSpec.name[tempSpec.name[0]] = ':';
- }
- }
-
- /*
- * Create a new Handle for the object - make it a C string.
- */
- tempSpec.name[0] += 1;
- tempSpec.name[tempSpec.name[0]] = '\0';
- err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
- if (err == noErr) {
- /*
- * Get the ancestor directory names - loop until we have an
- * error or find the root directory.
- */
- pb.dirInfo.ioNamePtr = tempSpec.name;
- pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
- pb.dirInfo.ioDrParID = tempSpec.parID;
- do {
- pb.dirInfo.ioFDirIndex = -1;
- pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
- err = PBGetCatInfoSync(&pb);
- if (err == noErr) {
- /*
- * Append colon to directory name and add
- * directory name to beginning of fullPath.
- */
- ++tempSpec.name[0];
- tempSpec.name[tempSpec.name[0]] = ':';
-
- (void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1],
- tempSpec.name[0]);
- err = MemError();
- }
- } while ( (err == noErr) &&
- (pb.dirInfo.ioDrDirID != fsRtDirID) );
- }
- }
- }
-
- /*
- * On error Dispose the handle, set it to NULL & return the err.
- * Otherwise, set the length & return.
- */
- if (err == noErr) {
- *length = GetHandleSize(*fullPath) - 1;
- } else {
- if ( *fullPath != NULL ) {
- DisposeHandle(*fullPath);
- }
- *fullPath = NULL;
- *length = 0;
- }
-
- return err;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * GetGlobalMouseTcl --
- *
- * This procedure obtains the current mouse position in global
- * coordinates.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-void
-GetGlobalMouseTcl(
- Point *mouse) /* Mouse position. */
-{
- EventRecord event;
-
- OSEventAvail(0, &event);
- *mouse = event.where;
-}
-
-pascal OSErr FSpGetDirectoryIDTcl (CONST FSSpec * spec,
- long * theDirID, Boolean * isDirectory)
-{
- return(FSpGetDirectoryID(spec, theDirID, isDirectory));
-}
-
-pascal short FSpOpenResFileCompatTcl (CONST FSSpec * spec, SignedByte permission)
-{
- return(FSpOpenResFileCompat(spec,permission));
-}
-
-pascal void FSpCreateResFileCompatTcl (
- CONST FSSpec * spec, OSType creator,
- OSType fileType, ScriptCode scriptTag)
-{
- FSpCreateResFileCompat (spec,creator,fileType,scriptTag);
-}
diff --git a/mac/tcltkMacBuildSupport.sea.hqx b/mac/tcltkMacBuildSupport.sea.hqx
deleted file mode 100644
index 0f39e28..0000000
--- a/mac/tcltkMacBuildSupport.sea.hqx
+++ /dev/null
@@ -1,3970 +0,0 @@
-(This file must be converted with BinHex 4.0)
-:'(4ME(4V6@&M3R9TE'46GA"`Eh*d,R0PB3""8&"-BA9cG#!!!!&F-!!"NlA#He0
-dG@CQ5A3J+'-T-6Nj0bda16Ni)%&XB@4ND@iJ8hPcG'9YFb`J5@jM,L`JD(4dF$S
-[,hH3!bjKE'&NC'PZFhPc,Q0[E5p6G(9QCNPd,`d+'J!&%!!"A$!!N!0b!!%!N!0
-b+G30TD95CA0PFRCPC+@P!+@3"!%!!%3!4,GD)HHjbMAT!*!0&'J"!*!$fJ!E+'8
-!!9Y@!!*dBfadDdeKBd*eD@aN8h9`F'pbG!!!dCB!mJ'%!Y8$FJ(!rj!%!Klrq2r
-`bd!!!)!!N!3",JZPN!3"!!!e!!#h@L(RYeSKj`#3!h)!!!(%!*!$FJ!&Qcd!N!j
-*BfpZ$3!"fipTBfpZ68&$8d%!N!q!!*!*!HB!N!1$!*!%$`"#`G4pkZC)Fdpk#E"
-3,[R(401[QF!K8#m3cp6`UEN(l!F(kE$mF3UPMQ%Cji[M2`6'l@`N5(%)p!jpec$
-iXXJI,GDb'reFiYi1&`4QA#$cfMm*U3HrSJU)q3Y-NAL(FV%[6'K([88c@M9ehcr
-RHNJC`RVr%f@Ki9pVfJ5KjNGZr)mi!+@3"!%!!$d!4,5KD[qjbM&r!*!$fJ!"A!#
-3"()!$B+V!!!#*3!E*Rm!!9RE!"48Bf`[9'XJ4QpXC'9b!!$YV!![!!X"b3)#!F$
-rN!3"$[rm!&R,4!!!J!#3"k@3"!%!!%3!4,BJ!3+jbL'e!!!"a!!!Z"-!!!(%!"6
-@lJ!!!Sd!&eh"!!#eKJ!&+&"bEcBJ3R9TE'3J8h9`F'pbG#N!!'D$!(`!6`+0!J!
-"`!&!!)%$$[rirr$,4!!!J!#3"k@3"!%!!%%!%,B4*!Dja[-2!!!#*3!!&Di!!!)
-P!"&Fj!!!0"i!!"('!*!%$`"#G@PXC'PZCb"0B@08Bfa8D`!"q"T849K83eG*43%
-!rj!%!*!+J!#3#3'D!*!$k!#3"!m!3X(8LR5QN9I`Z)-Fq$Y-QHk+Q*e3ZSAj*b9
-e*fN`#Q%cH$(X0PVIdXIVaI'B*NFL"q4m8KkAY`LZHTHKMcM,YbZ6E@Hir+([lTr
-!H4DFBb0"[)ejqqE$22-d")j2X65`LhV*!M'EVkai@'C&C5&1X3MS0!Y1UiD'E0d
-l-3lheaEpDEFFkMe#5pfDI3if*Pm([4e51#pXZf#AMV,bp6fAl2V5HhUe(8XZAp*
-'j,M`8+0RS0q+MmrS"MU"GM#%F(P#@)qmrJ9+DKEE-d-49L9RZ(YBRTr9ZIq,f9i
-Gl4Sd#AP)a5h`X-6d!%,"e1Si2T,Ni"XaM+Lk0AbK@)D"d+d3b@&mVR[5CH3C#hZ
-Ur((1M+#"JTVj2$-cVZUhAm`(-Mm3JJak'DIJAJN5adpNa$TcI[d*KkFXF-erjlf
-RQ@Q2MmMPbQ#YLNdUJKJkY-iN&j[CLlp9&%!IL-4FCfhJ$jG0)P8m`YB*`9Z3!"-
-V3p*XG0*#1"rZh(0&Y83'9e$jLa[fE3pf6maGMB!Kfml(qePU`adB0&'CC25%cHS
-kD"Z,3USPXS!&!j!!fPP1KE&qbMfe2I9fb9[1kK1'B!,eNP8Fa8d-Nh#XA5c+Y0V
-IHPC'k,5`LXVqZipRbBj`cMam3!%(I!Ml#&YpiLX[l%H$Jh,0)Z(%h9,&'$AhSbL
-4BYjTQU&"mlZ)Y(53!)3"b&d2J)306QURcfPYK,3`UB(-G1T4U3m&FEf'QU9aTY6
-V+VQS&hM-!U[8BA,S(V2&N@`eY6Bq0*R9(I-6Z90lPA4GcY1S!Ym[Dj([k65eDfj
-F&N[G"@KqYVRLhT4qCYq(XEVN@2G!aqF-c3`96G283JK)4$9%VEPambHkr)64R82
-H*%G6GFEC[SN80iHal(H1q(peQ(PNX`p-JVTFJUE86(-)[-2Sli-Dp8-YJ(%im,V
-3P`JCe`'A)(9TkL[DfCbqe0D+hQV+1l551k61bjUV9eb,DjK"-4kZMA*Lh*faf1Z
-0XNYjfIG+m*IAkSNi%*'kC6J`j$HPaR,T)ZP6cDc#b@qC)#Q2`[)4U4X+ih&26b[
-FVab"a%,ahmZRQ5Tr`"PS6kppkK&AC$DVQp-Zd8)BLmN"RH,mZc9RXGUM)b-"!YD
-"9Q,(6"NI%*h,)bd3)cp1[H8$CAHi4,RY2L0BFhIQk65P2X9$h5`FY[``JpYqU@P
-KM2)$)IJ`qBBP*'+R2Ae,JeNR`P('!4Kj23(QfMJ2-41RfqRUcjKp%$8r'#pHT**
-%()39HbF$UfT@d9-4b$,EqX,QNIYrI"LQS-QQ0Cb+RHXAk@+)1Klhi,j5a4`Ufq!
-'kP*(PbbGP(4Up@Nb@m2VU0)mil&GjT%'&[$`AaN%[2#YPf8h(FNEmk,T5`J%A,a
-2I#r+HFq1,T([rC95&-l@i[Fe8dQ4F'e+ri9$0c)q1fT-m'$T(Fr8EllI1RZMh*H
-4G1UV0QAhU-Bdcdf'SSIi"81PK(9+)1JI8-amURk,!4ZU&$!VcQN"0ZZ!X9$NS,S
-9f13c)2m(@`[jc*0a25T*X#)*C"5@k#X,bX$QR3HmkNBGi[mFBL"FMTT0!E"%B%N
-DdKIkr`HbaZpL#jqXRX*'lSaj,-852Hd4#[QJN!!'PDVTkP*d2LF5e9TLEQ[*R3,
-B$mDRdXMYhkiB-`'V*rJ6fqMLFpp5icZdKaU#4[&+G2ep3+(ahG9@fbL,p45%Vq"
-T1M)V88G9e4!*Ef++AG5MfeDVr38@0kcHc'p+5)SX$@PG#JZ*AJq)Y2&h4KJTlpK
-'pkD1`)H$Ab@eXf'd0rYLB#I")$k,PKHT,Z[8r8`BrLMeXDc12!qITQ8`ZkUradq
-45S2'NLCj#L0E8e4@`A%iJ+$@4a'0$6%3(3UHEkUFbdXSd$KUC'GlVh8&iSC5c+3
-ja!*ME%iY$3Z4D%)S'6kS#I&e%MIME%VCL4NK2TT%4B+P`KH[H@hh``S[,+$2GRU
-Vbcr*4VcBE6hMI&Eh-fjf9L"QBq'b#phQL*MN9aHTUDVJ&EMr42(H+D2ZqFb4R#c
-Ne9mlC++%5CX-ikRKBA3dk[bQ-KN#cPqKNbpdFGZC5eGdN5-2N!!`UU,RXhEqMSA
-%30[c@l*0FG*1K%Z@H1QH$#aHGFr`3TM1X[1qGkreFU1@$,CT1d@S)YM@5H@Ul%h
-A4kTZBA1hGC+JJ#K#Jp92KM23D64cKI5Lf&&LddN1QRlR!KYX%`m$"ZfUGl3%B'a
-r0liHGa1+6)5+eef6X&1#re&jBq2KNU[+QV[qQG!lGG44jJFl[Q3)"6l!c191&ZJ
-jNeLA'9-ir,N9NqpfKml!A'CEQ8,hUH5+ji&@JcjY[EaYYYh&90LVbE,m,RjfRZr
-T'H86jcKFNP4eN5[&@L2[Mj+0N6CVpPrEIL"4S!%p+"8Y0Z*B!T6Lh8M`pqYBDqd
-qamklC8ZGD"Hhfa&E$'"35f3h8&H'Cr,UUG3'M3QHG0Qep90q95f`FiC-BC1MTSY
-%'m-HrpH(a5C,I,*`)@K#S-Z$"0JckGN@J'9XYTh-ZiTS93Hl%k+)!RdKEIPbB[@
-4B8M%Uh#"5ifd0'4fGV$,j%SHb'YbpFdc!Qhh3`XTU9hbQY,%(c36)q6CFi$[!QA
--hUTk@(pi2H6fhBkH+hJXrk3XEb0rV15CPS9#KK36lNHa`C9feCeb,M`PrUq8II3
-[R3KUaH6SS@Y)A[p41N@84(Q"b&)jTl@dGlB'kQBLeZeUS05Xp5Q)6h,A4'[C-4)
-p%4,'reCEJIG#LbrQ3335CVBae!'p,J06bjpk@j88CimK'+!-r-10%iQTbl+"p94
-@2!'fpj2FI&DLm&hi**+f1DBcK-@jN!!&UK9hZCMYi'DNVHpF',VVcr2R#!f*,Y8
-&bA@&RHLCI0fSHI9hK6p)U-l(Hj+VU3YQ6mK$2KYPZ$&GU$N5XrA),q%$&B9ce(r
-qAa85rK9rrC03Dk&mPJ9!Sh,I@f84#$KR,2Mh-bVlJdM(jR5T2rHZB&QM-V&-T)'
-E)kC6b"YTD#Q`51eef#CK+(Cj8(XT'Pd!Q+pp#MM9!rYaBBC%)hm8qE)c2`Lk$hT
-"NX[%kNm(,'XZlVl#9033r3'MS8(4Iq-ldA0Sc#dhQl%d)N%89GMjNXMMqK29*Xi
-PfqTX5LMXQ-9&)3FfRr@$dlU4#Y"%&$Cep'[DLYjC!G%M(E#bEM%r-PX-YBh*efC
-29C5ea-d)lFprEb$P)JQYp&*#dQXh1EUjZJ#3!,-)`NMED2pihkIMQ--a"d9%C8R
-p*VD52qaMb82HC1$ZDP+mN!"rKG[+*[#q'9pUmlS#6PfIfcIY)*R9-c%$0HF2R@p
-8FD'k1#r(NU%*IfqV)eFB`I9bZ9hAL%I1[p8b0"`([Tm#l)#*P)cM*a1i`C6Ii%6
-mCel*clEFVBJ0%AK!TJXkMf,Ub!)2"1c#H)Fbc*0q,e1F"52'["DM#&IVieQU&MH
-3!02`L8qRh'4AG8#S%KGMYXA0RPYJQ8EQCbk8Fa%aMhYT`lGd5S&&5))X,RD(jYq
-*X-aV%j4l$()),9B%HkCE@3ehl!2@R6&jIjN*2KaiAlCkXHKkr[[a)PUSPeJpZde
-%M-+aZfrVXK%X&K4IY0bb@S!FNpfENibGbk(XJ)V[#NNRI&#a`fN&E@h%NPq!a1i
-H+N($r)HVjX,68@jV&BjZ')A"'iM!mH"aE&p9(Y$PL%#88S&3(kV!KF*GU2!S(K(
-L$9MaFQJhc0MKT+a(XCI'"el#ql+&4+ppRDPU$DX8*a)")-rGb@!jE%)!5JZdFbp
-V6JB@!#2[eS(RSRX(X55i[&8X[LKXl$@V5&SX[3JDQ*3GfQH%!(2XjHmZ&Bc#Dr4
-cHhZf@`1iMHl0G0IV((@&Qrd93MjD%KF)[UG#&RA,m[ka4[TqXP4A9CVGF!M4Dqp
-hG$9,TD`q$d3CHFN'#N"HaDE,2&BrPF&)#qJHUY[F)'6ZN!#H%Z)3fe0J8DC8fJf
-!!c6D#QB9Hi##""+6(`liGp0m#J3eb"jGcDV(FU6rmG22E+fEICcfHXS(D!B%Br,
-8C-IjaD)RkYaq@C!!F!#LEXp,)LNlNNB93&dek2J-I#&qVBc6YVHAPq$C-06V$Fr
-Y6*A($SE$%4GEekX%C8(3YldCC1TP5QEp(TBQYT`4[Tp4%85X("#ppp,(M,1G#A+
-*++b611JLe*IIV#K[LGE*`4HCFa-hS5T!Mc',mL[9G$b616&RmB#6bUAAcTQ*U"H
-lBI#3!!-!rDfSrD5frQeGeFIEXEi8hjrTRdD8lJUkRp&KCq1U-hUjqhJq34l*YG+
-l8`e1dd2h$[rDj+`+*E2aA#(PflSZL+a(Jp!dXBC[RQ24d6dQZ,p!F4Kf*bX"GqD
-Ad!)9pfelmR$ip2&RR&VJLQJbParq9h5KU`H2@#B![%k'Z15ZYVJCU4bcE)B9A'Z
-Ti[i&(j!!B4ZchNHBZR0@*cPjhPHC2DRaSfGCT-2R,4&l@mRb5%l6Shjif&m0ea,
-KC!G0f[aPK("r-(rLIGT5Z((,V10rEF,HSZKJRH%Up+!23m-Kd@I,Q*BcVl-GQNm
-jkkFrB4+DH-GkYq+Va*4j,meEl-6,#LaKPPTVq#dFcQmGdNeqHmZ400!`I)IehqF
-aj!*-FY`2RES8ETUAl-UBYY0qai)eD&BSqDfNhi[[!LVpHKE`aSC+eT!!M1jZlfF
-KqUXN2V6YV'qSJ!568k5m0XaCd28IEiL#$aciJcEh#$JET2dQV'pGllXQ'JiYP*T
-q!c1fcMaBY!SB1TPMR6f,%d+2cUP9[K6FPBrF2IZM6QN8SiSD3CKCpGf9k'brrVk
-CUN2"PEBk9e$q5VVa@Hl+C9pMUc%lXk'L6bb24B(@[A(ZbRBaQN0J-XSM()`&),6
-raap$#k0mjr,5H6Dj"BPh'++H02UFJI0qk%c9hmPIDU5'dKYk[CjkXU9R$QDX+"j
-i$5l'9j5&)"F@m&bEMCMq')qN)([R@3H+rYF'r3QZh4FLdS`bhJZDrT5%QHbiF-e
-LblAE,l(FNSM3TY'kB$YL"A2Y9D$NAr(((&3+2j)SaShmKGaEr-E945ajfHBM60b
-j6MRT2*QeINA*d9PGpa'9Lp*6(6h[fRE+%2DjQl(FpXQ@2-f&*-p142L@I3)6S%c
-j*YJQl"-2kpXPmGYBAErBI-ChT24,Ia2%ZZKi%Kl6K[JjURISC9iY"N2KY(8hD)f
-k$2#qfk2m@@eHpqb9N3K,rm-E,ka3RcZCYm"%Gf2mE"cCB&UNfNRf2a!LX,BIe%$
-KN!$GM(Qq(XDKaeQ#U[cENYqfR!Z+r2UYeBKZ[Ip)8KNdp@m)Ij6ISZ*TEEbESE%
-S+L@eX6lcY)*XRF(SPedJ#E")9h%0XLZr"AP1q%YVfj,V9$b8,J)B2,[UiMZcjMM
-EP[3U0bS0jbUl2+`*2@K(a+2j2A8!I5A8E#*#9VKlF*21`kPEBNNCAZGC+hbHk9G
-("Ra`jVdH(9-4YaIK1j3MrZ'JEpjpYHI!b[b,`SaY,[%6+$J#18F+'JUb`aXKI1e
-m4J6k9hB$0l,k[BLJpYY8DJ8H#@jN9'Pe58ie&h%B%YPKFj`,'-0PFF)+%JPiFNa
-$DlBl!&YN8UZ92V@Rb#dPSk8kGNEmEXCbIe@6bUfiU3Vf0%H@k2#ieZYGB+#Lk,m
-NjPZU31DiZLi6lM4f0CEq3K+jhPHRp!MGc+Z3!18$`2@#[jpIRMIXJa+ea19m8[P
-C%M&[K)&k'BPUXGPH@3,,b+h)alA-"peR!9mXSpk#b4,XBVdpjJ8C!&R45c@XNbI
--h,-mR%ed,1VA(CRbCmmfK&EA"l(4ZY)38Zd*$,mSIl$m8DL4IJS0FX)69CVk$Vk
-JECm5L2ljXa+m!$Xce-Peh%`LZPk,qB2V,c#MC[)m-X&r3%e*M$FH$E[4c"qAmUH
--qKSIDcaU[Vd9+A(p3'Y-QBJKh4-2PJ#Z6H`Z4UZ"I0MZAVkX)I"JU[if%U!Ga3a
-SMHc"iT9@Cb,2YCG-Q`*pEUPjYHTDmdjXPFIlReNLkJpI+2fCL`bX+`cHVD5&+Y[
-6G6!&ESaK!0ET9FINZll0fVMSZkfEHl-%S0m(G`ci*Le)GhT-H,HPYDVF2YL81%X
-`$"YJ&*6!XYF44mjaj-)PeFjE8'4S,kjk0,(UjEpJm#5fX@Gi,0lRD),f5!r,mhX
-5Z(%2&,pIJkqhk-De0r%1"5+R11qHi@d8)03(L4jFb*h$L!8VqU'1J8k0r(DC,,,
-Ni,cK*5cKGT&0E"q4FN3-F*Ml-2rcYbG#0J$"&8SMKq(2j$SmkAV3LKS"TB3N3h1
-A+aGa1*99cdShc0B#emfJldNZCl!N#aN*iAj&Eki-LfiF#j63b`r11e3Q5JcIA15
-kTEJN%8a`*if)$dX0Ld-2jPU1ZaB)V$YTm"i8+&G0JcbG)G8)4H9+,$,H(Zjp#Nb
-#'HNrN5laLaMdD34(kSHKNML,J+@3"!%!!$m!%,BJ"!bja[+l!!!#M3!!(1X!!!)
-P!!pj#`!!$NJ!!!BP!*!%$`"$9b"3FQmf)'0SB@jRCA-!!6bN9%9B9%0A588"!2q
-3"!#3#S!!N!N"QJ#3!kF!N!32!%,"e3hVJ)DL+(k5(ekhZa[@hQ)a8$28*ae,e$-
-Kl!1M-Tk(*K"6N!$V98I5XC5'52IeC1`E`U66Bb#Jkb!HYl6pC6PY61KFbUJ9qJT
--J6)FLq@pSS1l8(MXlkI3c554bSRJfjA29@bY`PcqA8IpU'lUA6(HFc)pi'"k*4k
-V+`p@'9H!Nbed'ZHVqH12UhdhdMa($Q#3!(94,[UT65#Y3hj@A3KMXcdjl%"#`G8
-25AAp3DGeN3%,QDiR)5[1r65qVB06hC))(iml#TrVTAQbhaScA-iFG2`JU[&95Xr
-dJM9p9N2Kh-kk8(i!E)eAUX#U%%R*AR'-aAFq66A9K[B)5$r$cUK(&[["$0dXjE4
-RFFV'1*JEe3E90B"r-%K&(@+P3d*pkd%RC#iSP#NrDNa(MkK,ANm5(EG)13Gj[-e
-TC0Rrc3([FFd#0NXGU0chFr9jIdX0q3Hb+LJSHd,mrlm!131FfI"QKIDEeXXMVil
-j*9'TM415fX13!",ec066E)cN@[[`,D(pDKL2J)LeChPZNK#Gccd3p!ZXq9&V&*I
-L@#j4Qp4k2H*&!@UHT"!X#Z%*#THD30pU!3##P[i!)k&8Bd,E6K+(,09j11!jmHV
-,QaZ2,E*l4pF@1LC8i8m$m0YUlP%aKaK4pNXa2"e5i@T(J&pP86M%PQAV@+G&%4[
-cPKXV"@-b4HkYM[$d)#dLRkac'NkpXdENi04'A%pV%e8&%&P*iT'+l$Q*LA""%(0
-BrD(d0IK4X5Gqa&m8,06dU(PTVJ2'2(bLj5KmK4eBZbD8JI+DDmCDZECX,dXraHR
-@XDZK42DE"@AVB4Ik,FNU")rfqPA&9*jaQ0S1DEab65IRUc,`2dV(qLbP9J4ZKI+
-GMhf$NRDX3pbZPMI*4jFKaCHfq3ClFc6ZDP'SfY6@r%XU3,Ub34e[!+m+l(p$F!K
-ea*rI#IQ`&-#[qQMm+DSBc*dIVHa9#i&aJb*JI*IPNVGZE*NL2DZ3!'$9BZk(0%8
-"mKcLU0L[QRY%Ld3'Yd286XeKDLE2VR$UK3SHc%a#UN-rcdf$6YcD$1T#lb4@ReE
-'Y%C,MJ`-ZIZ05Qe6(2@#64NQTBiPER15$m1A6$65SqBXD0+1j-)UMkD2f9%c%84
-B8MQE@ChI`@A6"dIh+laG#!Q"T3-"PrlJ&A4")qSR9a-AYjH6T,q&*KR-X81(cA)
-bND8C&23hm95A"r-q"rrFk-JJ&5hmm-IaER"b%4L8AXZma+fS1R)YDU4VEdeGj!&
-#ZNcM&-X3QV$R56VENZiJkQ-GqXX#AfSMLc!6ZT6@6JF(a1%mHEF28Q4bkM!RULc
-F#`2M#IQ)@%cXAKMimSf0CjH,JB`ha-Q3!(S9!J"d`6'AUaE#NP-0,CAdrjpeT"[
-`&M'!l(`BUIPHCCUF-8*cfPDL[(E-ADp*4D`e%DQdJd2r&$F4YpTh5Gh()TpT6&L
-KG1dTq-S,cMqfF*,c)B'Zl3)22-m3B*RYMLqKLD'1I8J(eUhAT!NSi'#ke9%#Y+b
-##1(fS82dd9FNL4%*8DBmE@ha*TBf5k`5+),FTpbEcb`HYA4Y++-iZ$PH1G9d"C1
-&fRd%"!Y&Q[(cX6alDi[+R%U1QN5jb6pbKM@b!dY(DN%[36THL)&XU+6f6G!ZH5(
-MMiqJcNChq8hM*U+"h,9[3XVdY0TVQc0(+Ur"YK6TSH4$RHXbpY)Sq5FRRfr4Fjr
-dE`8)6I!8Y&bRTV'lJ4I!IXG3GV@Z0VS'KNXX#epS`3Lk3*SF2fSZq1dMG9m#%4K
-Ijf5rF58+9bH8#DR"#m5[mmNML'%Z#Yi@"83rV!i2ICMKrTL',Y4`(f4)YLrTmBK
-6A"ClFhIlXiG9fq"ZGA6q,ff5RCC2i&kc6dC0*[4-lfN#-,#2RmVX2N`5DRZ66Pi
-3ISZd`a[$8[AZMSINU3[fEI880PXQY8H@Y9`Y53f+31V)c3m%Z53N+SBrPHX$JBR
-!baE0U0"r4HB,0Nr5%L,TErh,4&B#5-5"r"XmaMcfSE#0Ar10Va38c30%Qfh((Yp
-XYZNbR5%dqVPI,LU-a99J-Pm`eL@c0QK!0dUNF8biQK[!'b+1A#mUpFXjJ)EUPKm
-XU%cF0!a1Gh0"-+(MS&5'&j[B*JUV"2mlYU[)$(dH1!lZ'K!AhM4k$rBkkG&lh0c
-j6%c`5eSablY%64kbIrQZU&hilqeMNTa$ECFkajl)!mUXB,KN%[b$&$0bq'HPE!%
-Q*0@Sff,K%LfpZq`98HlqV#V'QT6!1S'QLleBX3AJf1N8-bba4rqqY6iV#Alc9Z+
-6D0HqS@3mL[b@+Ue"XQDrVMGrGm2Jp1e9`+6%9LjbYAZDi[!!TC!%!3!!2`"%Y%a
-f[ER+)DJ!!"@Z!!#Q"`!!!L8!$q*Z!!!G6J!@lCd!!)Lj!!C0Eh*P4QPXCA-J-5i
-e,M-!!1Lh!+X!MJ,9!J!"`2q3"!-HrrcrmXY%!!#!!*!(TC!%!3!!03!!Y`$fFEF
-!pR%!!"cV!!!GdJ!!(1X!"CVe!*!15@0[EJd!!Fh8D@0[ENe"3e0"!,(JXH!!N!U
-!!*!*!4i!N!-G!*!%$`"#`G5I66Y4QLC-XLL#I[0id6aLSH3I'-#V81EJ!+@3"!%
-!!$d!%,9j5)QjaU+b!!!G6J!!)`m!!"cV!!hE@!!!#HN!!!0J!*!%$`"0Eh*P4QP
-XCA-ZCAK`!!(m2&4&@&4$9dP&!3$rN!3!N!U!!*!*!CS!!!&Z!*!%$`"#`G8(%b3
-"`b25lJXE%")r[3j980d'(SNJ8$qqG6jMYDjl-BeDdS-RA`!E49VD"RdrI@lFrL'
-hV@e[QadRPja6)elNKm0QHLBqB!ceeCI!p,`eQ8fIHV6Y+[H9qHl[lFbjkCdheQe
-rV-+4p"h'66Z3!-VPNQ3BET0SAB10fdCE*lHaEZJ%V@MCiip5e9)%HXDV))0Vl0A
-MHZpBq3G6D'FM`lE,"*5PScmaM4TG103i#FC8jQIfKqHLXN%UaQ3N6"m$llG&U[X
-*8jET[rF#*MlXDKeE-N'9e[Gh8Q2BdIThar3aY*T9)Zb[S)MMZ#LCR5+i-R9BqDD
-`%VGq'eaU*%r6R1*,@f&[A@%EihD'P,mEQ5P`H@b+"52lT("6iJ$h-qe`I3f5pQ4
-QLP!r1%N&Ga8(0Z49Qj`UeI`N8#P&dQp!F''2jp8TeN`@,2T,UM06$66RI1hNIJT
-*#JV5HZj+XJ,!C&rc!ME)b*IUSZVLIl1B3X(8hC5Z1SUfeJYkk[H8!d*rLMc%d&B
-RlY%mUHF'([KE"Qde$bAPF'R`Z8%KJB)MiD*!CZ+E%#,bH%bkF`FFCRUIh(r,dPY
-K46jl8qbfQq'RlBSPk&"R)`165TiB!HDlk%*Z5P(fHl5YeD,HUeEMe5Q9&'G5(iZ
-AZke,0mGK"c@Fb!Y9[9Q8,Ch-a!2(YQ66&Ai5'+'cm!b&5p`5VAPQ@5rV,'h#6dl
-+[NLRPQ5,MAeSbfp9`LGFmLZRmMBj0-1&5rR*ILr"34'bXTN)Nk#,L!5I(I0'pZU
-'2SDpk,-R,-q)p8#'k``$3Kq-GH6@9C'"LSUcJjU9pi2DqI+,l0HGYkX@U2k05!G
-I$Ek`0A8JQ@G`iYcB@d&Ep,hMbVACqiX9c4h$4'SA*XVi2&T0-+ipF5Ic4M1dHM-
-b[DY[S"E9`Dhj4U+!p#*c[UecGHF%'M5M,pUC-VQBZ3Z9'lM599P8X@c*iApV5!V
-V5jFKdrEX6jUkk)6**cH&&q4@c4EC!15UjUlH1mRCQP6&YAe1h!Tp5kMAR0"9UM$
-BUX#M5J@'"DEZT#eJLpq@2[CkDD,Zp"1@$$!)P6R'*YH3!*NAG!mC6fSIDF`aiP,
-rbK$lTp!LDB"rCM04T0NYDaq44q%lp'6BkY14-RL$hYbe9Xhm-@Bb4'i5@ZrF$4S
-ElfP-(3p64+GNJC!!9p'[c-Qf"24bKrHDTj)dmU@M*JL+jaUd&KA'bh%B0j)dX'$
-5mB8QD#p1`SVm,Mih,8'bp(80Z85HdmqQSU"$0KBkjEGp2H@(Tp64BUmZl4++,UC
-2mXR8bRDk6rJ[`Nd@,iZCHmYC$$qb3CVk$pATBGr3k5$-cD(8adXH!NLC[!M6J3i
-!R#bGPj@q`)Q2dKPRdSlP,$rPE+rD*XNbH1qIpcb%iZ1UVBQk95cAc@NYR'S"qce
-I'Ap0,a*l@R`+P!$hN!!*)V@-FQ[URklX`i6l89q495RR([[KjP2AJ)6`cQ+ibT5
-k%J0%pB,'mf0bdBa,F++N[&dXHl6TpV8(C![%BP&662Pkh6)a!4`e'-[LNkK&2")
-kAL`CMhKeT'p8("(i[m-C2,P8E11d2X5aA&T&`N46SXL[N9TTVJJZ+c6["0NS'!p
-[f1GqLkXkkI6km49Rc*%A(8B,`Mi!4rKM@Gi!TC!%!3!!23#!Y`54PlR+)9`!!"h
-5!!"a4`!!(1X!$3S%!!IrI!!!6GF!N!32!%e[FQ9'D@aPFbjYBh!!!%#b68e3FN0
-A588"!2q3"!#3#S"`!*!'3X(8aNfkPhLk2cj#2+31a9UdABaeEQbY%,BTkA6ND2k
-RqIYXVm9X@[1c+eD2BFSFJYjZYG1k"JL8RcLkM9SkrDUbc@KVV[Frl0*YB5B!3U+
-41(E-6N"F*141%iQ`DRlPi2%II9KLq)lih5P,C6EbHHYA9[N![2bQBTdpJjr5fXN
-(e+@a8q%#IEDKj@qEd#-#KB,3"V9Q0a9ZDhQ')RDX'm*)LQf93QY8)PpYRCIF+f&
-jb3"&)M0j"jCG",KpCj!!HLM%Qkm9PLN"YH&ljN2EE[GCQjQj`!q+@%@DDjLH#"T
-F-UB)lXHXf$!YZJ2%e5-0S1`E8r)YST2aJc,6U!E6Y(S`Z&fTCGl-RX*qmL$S#ih
-Mh!9F"9$*-YlPh@*#-iJSSFIT&2XaTB``Al3Se*dkCV"-Cmk8j`leq84-"dEPZ&5
-HJ*h6%qjVM2d+"mN4DDUlB"Rl()e-X4#KVNp$$Kr5IpPl6RpabU1Qf!V2Vb)+)EQ
-M-a+)SUk)E*lHdjXd#rqRS2Qk[cGeNaH`mIH[l6Af8-R&)M0QJ+K&-p-9FSG,qN#
-XVYi*3"IBl0,Zl*@2(3Xkm`N-(C'SGYH-+pG$RET2aj+PbD3iN!#KVFK2$U!edCV
-r+T6pr+$`B&'h@!0[kVTBfa%N,C3kMMdfE%H(96N[PGN9Q*V"-9mV(B26I'JQ`Zl
-rBS&bE)[5PfB-GV9E4[Zl5'p4J-U)m)P)!qN2bLjZliL`krc$XiC#TTK[T9NP&pb
-lEkh@2(5T5)mBHNkIF,d9Zb$KXYj2@8k&r&(j'D$(p)RRIj!!EQDH%L-8&IQQ1a"
-'rkN3("Ij20imE4!aVR,%c6Gh*CH,r&GG5aZT-%`(mcCGhB#fX0-G[f5ZmLeY(,3
-',(EUKd&9@V$1lT2T#&HTaH6Uh(h,Km"0$Zf+#j'SDmJK0GdU+3&9!,SEcHHFd"L
-@$58!*X-IC,+RJKbD')q@JMfJXYU(T[`CM1iI*',"6)%ld3Xl4&Kf)&C@ci%h-%D
-L6H-&5BI[&)Hm,+AY(I(kUJ0N)T3$6+3J9BJ,*Zaq,(6Thcc-9LP3M9XIAEBRbAa
-[j1mlmF6k!X(Bk%-,SLbGME&K)`GK6ceH##hEIpFAcB0eG-k1i$VN#b)(4&-UpRD
-!HE1LQ&aqmR&dl&bMjh%C9A$[#*F+qJGJ1$9%`E8cFemM%&N!9GqFkr'q8#BL%I@
-YbMiB2Qe&&p(J5(VAJpQ9V9kYHfGI-4aR"!l`Ce#@ArZHN!"aaBYIi8V6TaiXEm&
-C``plh"`Iml)1+0DSq$V+!#3L)f#bY[[2,Yr5Dp[*m$l`lb`9ki"1Bj!!BF-'-@U
-1M8"[b[1l),+Udm44EmSCC,2E8`HRX"YA#h+B3Ei1-qSp@VB'9H5fYSMp*QVjrk(
-'Kk[Br[H2#Cm(F9(+,Nrr@8IGD89cDYQNF$Q-$e6$b#*5'FUTe9'%T#UA$aSH80r
-$8aRkkXeMaJBbBbI#dkTCfMLLN!#q+882-*m"Fk@rA+N3bT0$9LEJaf28RACQ68D
-m[S9N[XfVfr+[Ki#e55+V0S6L-,QRL29d@T-B+*GNXeP6M4p$N!#BRm!T(QKEjma
-4&*0LaeiDRN92$IPfqMQ6D$&j`d3%'VGT4U`(qF+hKeE%!M0J@rj+(KC03hE!bMc
-RBSj@B#lMCkA42JAGmA`&*54+BMf$4ba5M86a-@85pkUi%LAZ"@@XJ4*9Ki%b,G,
-P!a)dM@NC,V150,6PN[T[["kX[mIkIY$d1L'Z9`eRNe9$cG+p&eaXmPh3eKCh$+5
-hk,Ta@DP"&KB[#G)MNP+3!#4af6*&%qcDlQBiX(`pBL3jCiG6"iAm+f5H&")6p#!
-YcGG$8X$0GBM@d5lXEe0EA$R@NZISZD0qT*VA"V-Yl5G86-5Cr"#%$NS#fY`IMrD
-P5XPcb,!AXdJ)NA#F3GZR2*!!APh8e49E3j&r%!d(&pP,lfIY5P8GGC9(9L%EDaD
-`T$bRQNM&`AT2H)hGGf8M)Gdl'"')'$!Nci(RMYZ9%CHYCE[G1X65Z-)2#CJ#4JI
-%DfaE[Y+P,TiQ2(MP5hI[)4VT,T[R"*RmQbMVhl1Xl[ENLl5p(l6IR%!"Nq!e3+D
-m(6h-1XaX*KS-J6VHHh5Dc`5EdI03ILFADaRZDJff6+rA`A-8aUr0M5pebdBL@[!
-Fb@1842Va0IiR9"*MY8$rKMJ0BGaFpKH9QLFjI)+F"#AqI)Pl2#-(EdVYTeLlNBd
-Ril(,hdik85Ncqh%6P6!@63f+,HXIIU+1aS*qeeU&Ei1&&'VJ1j!!eJ*'VIf%H-T
-Bq$*,bL(bQIEJ[VI@1dlFTD0FTBCpJ*E5MZJ#"Gci+52VHm64`(FQ`be86c)k6CE
-4L[mS#j!!29+Da@c)LeYdrl%4h2'GalG9HE6ML%HU5"ZPV4M2$VrihT3$m5qA#K3
-maE4h`H`PX(e-C`lG-4L$Ih(#*Tq$Zmd9MUHX&P$1!3VDQl3[N6RZ8*`Nm"l!$FZ
-MC9+L$ANchb*rFKM9RiEcSDUfRiFTda[ZbJb&9MCTNbL)&jNNME1mq9Lb9cZQ[Q6
-b!r3b)f5c60X!a1NQS-l[Jr#[bH,P4"4RYf,@0Q8%-pmGPK9X2pQ'FPT9(d(d,6M
-[dT!!bS,Z@Z8ajBHJ*lN0U["@FZhJ3&*Vi+`A"q9ZUPLIJh),6kESCJIES+*JCUl
-HL0K0Df-DkLK[Kd5*U&VP1'(#0@jBNbq(SVZ,1,5%l,S3SQMQXliYi%5lBc)(G)e
-QFH$C)'JBk#F'%h4Y3E5`PUh'r3plX19X4-q+#$RAY#jC$)b[65T8Iiic8iA9P3b
-B$eRN4VFSARM12r22RfFj1h!"h#cdH1(G$b3XNLf*kD`qhF`k@Lb!cf!!Z!Bb%+J
--",`jpKHNcKFSUN,dT+Nr%$fp#k4j"pe@I&I4#V%fkqeYA5Gkm,YBk0M`4qShbk#
-ef-p,5f)[k!I[i62,i86p5)0'#M%Mb-#AKAi,k`@'88'bbMUam&ArLKHM99KDVEV
-B)N#'!llAQ(5Qa-B$4j)SUL)!HRlX&1GVki['QeQZr-#b*plVUE@q)p1TD*@dcZS
-0%G-9aejq3C+`BBpXh)p&'BQdpSke*,hS`iiKfEb-V*kMV[)PGm4+V'fH+6b4H",
-(m([JBX0A"qSliIH6EeeVkDm&!UL9,$Ab(Q'd@fMJLiJY*)q'JEeidNFXj)2Qc#5
-"ANXk84NhYC0`c@"KFEJSCCU'FKC`k0'1P2e+T(!&G1XLDpMPS1jpRiBbU@[f4q&
-f*P*P&mEH$"3TC!5qI*k9D@+KpCjI09Ie`ED*heUq[P9T-Uk8Aqaf)VAD8L-3!IK
-RXX,D@`C3r1%8V*e&d-BkS"E1qQ+ZqTiXM6Md5eA8HTLf)#%LEeF66#c@6a*m"Xh
-[IJAqKUcQZfLa*i3#pI[rChL-jmP1l++'+9hS3"6"[3c(#*c-4DkXX(,8+00CM*1
-p4qT"JcV9e+q&TMbPd02@hV"lF[8a#e%X`-@%e@m,#+`6*F),L#Xp!aI3q[-@k)C
-laJDpeBMKP,H64b!N(+pA063q69T2%ZbZlVU!PQjR)00EH1'CS[VB!*4$K8#4-#&
-@J3YeX%i6GX)ipErFA-+rj2JZYRIpcCh'c,Eh098D(k&cjqPB,S8@1M!L5mj6Ar`
-pk1%rJI8UQkLV')e2Ep6LjVjG1,k(d&+b!1!c@JCH-pH[1fljJF)%"MkKrr'Iq0Q
-GX%+3!-jc90D%JSmrSC@MV0&ph6fBMYAi(VFd"8JZ9N,k%[BFPpS6X5e3IeK9*J)
-QjfSD0-i*2&%@(13e8jj`+BLjMZJ[5b)Y(8%5)N[*6C(APDS&M1([merR[0F,Z('
-9p8*eSSqG%G82&"U+hCE6eSBmGh-*@-D&d'R[L!QqdNCQVq8i+i(X',QA6j`Hh+%
-$+8p#m"I4Hq$jlbQq0!N5mZ,N5BhPA[IaarNK8S@icjK*PQq'ERq`3kpp0UlDY0P
-rfV%&S5LF0%qD#`EXdkj#+Z@,#+HMcMK$*F8F"`TKK6PBb%(GCrqiL3j,*XrH*E1
-bk$k8CXC#2b6MP$4)B&&Bd&LD[f#F$bTlD#$3GVpBaXTrZ)Xa+r`eiBBl04MKPYD
-H2NPL5NhI5HP+8a1*-pfU`d1YqU2!f2YGIhqd`NA$F'4L51aA36LNa4erRjT`,,,
-PGV@NUr(rra%C[5"*-9R[j#SBe,B),6,i`iVKfiq1%4)@C&j-'D9%dbG0BF0('SP
-bilbH9+*%jfk,Li1!H(,(LpKKQABBc!Q,eU0P9K6-$T1$998S8X5G(JKfKMFl`A"
-08$6!'LFkj3-K%j(2RVPEY!Q&AFqC%AfdHD1)Bm)1H0J8![$+IQe"G@r')H%BX#E
-M&aH@'C!!ailTj2ajX%K!HbYE"'25bEcd0k)#$MSTNq252EZ`'@UhI0(#PkkS#Jh
-'d5*[NEcA5rN[JXJeC`PP(F3ElG$mf1VDjK2Q'AcYmKL"(4TLhq4$SRqk8#ja(rb
-UCR@a+V0INLlaX@B@EcGmNj8MA0fmT2@cjQN"iIUXjp6ZR[[0"kCV58SX0*dDVdi
-diX84VV5$Qa-()J)Jk,$kd8bpJIjVbEBDTK#%K[&6ZJkQHbCXMDjZe)&-fN&ZlYe
-G4kEbJ6djrS4B@QFpDF[B,(b`#Ta``F!Lf#6FC6PDSPXfc4NMb2ShP1H9'PUYVlj
-#hCX"-BI%D,P9&NbM#"`-5JJKaAmd2Vm!IAkfQZCZP6Z-"$P@Nl,i*+Z8-ZYRXD*
-,%6eA1@$d4SYiIK1jqU%C*LR+irV`Nh3I8++,KQS`0ZQU2RQDDdSmH1[%0EA'V!m
-(&T`HmFXiXe9HA$if@U-`Yp1jTMQ'+PZ90NENTMS4YX@&a0IfU5XR5"$(*,mJLD,
-1BCL3!)@IK8-!q@0B8Mac`XGF9Ta(dT5m[bp[+MBXmVQ$e)mVNmRRRcV1"cN@53J
-,G%ERY5N1Tkm!"%CD`M34Xp#0qG%B1ND*Yh-,Y5($SD[95$Xm+$q-*2pUa-R&lhd
-1kmUhAK'&fcCiAV9(Ea%M6[8J*T2pS`Iqh+Z+%BRIARMb+'lM&f%%1H*8SG`1$SF
-jc2Y#2"e%!0B&9NI`dY+"lqfZ(d"QC5Z0e"Cjl6Q)$**G!HiAU0K1hd+biFIiU9Y
-XJ49)9-lAQGj0DTlGr+@+!AJ4IDYL"h,2#3MPZCrN1jG$p+)KRQD@LL-'E(%"*f[
-`#YYK5*aj8q+6UIJkG1l`J3l+[I$"3+dpjhYeP$F!((D3!$EqU!da(,bH5"0N!ec
-X"LF&*PRqGX`Z-6dbm+Aa4bBUrD&AjBBerbqc4HITFbH3!)'dU(EZI3NMf!B*Mm'
-8N[lZ8ql[(VP0Rm5`elp*DYAeTjPp5SVpS-@5L)EfY)L9MXq8ZirV#m1c`ke8H1[
-b)l0)Dqk6&eV9VC8`ai5"R,e"G*3e-G6RUUEZGK9*DAIjiE*eTrJ3V"!"3ikF[[0
-khp"59d[qVJU-8MCK@6FbkGD04UC6,J'Yb[e6Z5r$Y,-A30a`83qJ[q!Z'R689Q4
-!pFXq"em9918RkLjX5[,TGA!JRP,925!rRZ%jIBh$3R!(A[B+d"+(Mr-'8kc&rNm
-9AD`VC*bLC6q0JKS585qXVJ+6kAd`I8AT'TGk6S3LD*4i5rlTYq(%i@YId0G2bm,
-L[9dc[$'4hABJE'B@k3pP`ZppL06G"rc*$DHA!h$YV8NM1T!!UU5)AKLf0SL!"XI
-G3HDfkT*iYB0(3)HU)epl)"`ScX'-ikjqEmH645ME,A$TF5rG3h%kYI2QSP@@C!)
-fG3k[8Y-mJM'lVrXGRqEMYrfLS514JrCJBUC2VI)F@c0l45`1+q++fr`e`"EQjm(
-d$"L*4kBKc'V,6C!!TJ@!,H&rB+FBBUC'R3a'h)[`48G6G#XFZ9eG9e3@kadJr-B
-j'(T3N!#PS%!bJHF*8BJ9dd9reX1bQV`4a3J"rTR8,'@ALE%Fb"NmH(1S`i,CFFC
-[#k*Ed5d11E98*`*N0akImXrUNhdN+Uilcf+X'e!+K6rR-8FeaZ%Uqk8h#cH,"T!
-!Y6B'rFmS04d6S5B3'-ISLD+09ZeeSL9fH@RDX,mp-U&+@8j*AK"Bd*eRL#LGp5S
-%FMNjKl)@+UNNd9@IJRTRRF@LfM9r-!VdjDZGX$RYK0$HjFLcVCe#+efH9*Qj-U6
-&**!!"K&h*Xi$-r5ai'%*clh1RD$m(U#jIL'KS`Ja[@4([SCS@L!5D[S'E9S8l4(
-PqGde@I4cf*RZIZ1H!(Z"PT%)4&3YE&IX36p+edMJciM"3Pj*"e0F+P0,k+8pl!2
-KTmXTe9,2jGeQr2UAHP8J0fd,pLri["13!&Nd0D%`S60`T*2JQepY42m!MGHU4B9
-!IA-&8)(jMk%I6HY`bJ53!#V0eLJ``1A%rU@#dVi0T0NVB@F#e6DFmfdiXCI!eB`
-ie-48$6rjL0Zfqi2254ZkIRK8N!"G#jJHB(BrIXCpFi'NQd#%-ZUl4f9bPF3U!pp
-UCYT81$N*0-)-5+@kQTEpNh!4p"lJp1PHl@fhjBp)dGh'4mT"9kBTl@d'5$dcM0d
-VLk!V-"0eYhAaNC,Tm2Cm3S0-*EJ1De""m%`HNMjc%kSKjKlZ`q$!Rq'Q3T@4Ak5
-kIq3&2-+$A,k[EdUU#0XN[KHF*hGr@-UG*H`i*P1-Zdl'J$H3!)R#pQ0peaAN-I&
-jA`N%+Z-a)(iCd+UD'$@UG1h-I(CTKCmkccfKZZq2+'Ye',`)hiSU8I0fDXM&q!H
-rDK!mS'RA+J,A9-2fC9mL8&8,DT8RT[fcN44EG06HFr#S,4VJeI"NaB,%i+FA&4(
-aQ4Z`%+1)HEaD3elV0FD1G8dE-r*2CT4&"N59GL6ITIFP5UKR`1*9K"eMQ3`a*a2
-DQ))L8fprCZJSpjGRZA!95Y"qELf5@%I`L"!MRRPQT8(8*V6LCDDY%!@lSS5('3,
-&L3`Ch2PI#04NNld#SR455H!)302TA`48%A%Ymj2qlpVKb$!(4NAYAJpM+MZC%h1
-3!-8iI-Xq`TM(%AiM`aMNTE!e+-CE9"YZS26mVTjB&GU3!,I3(fG5b(,N%1,FFRF
-BPM2Tb`qee)2A4'JLTJQ&a%%Z"!f2YQD`b'GS2A%"4dC%h0@lN!##EA%8aPa6Q)0
-1k@ilXAVTamjGCiRDP[ZiLeXFp,TjU"CJf2q,Ea%BJhMreX)6D`B!*r6%iiCL@II
-k5h[)Z#Lm!BKm9qm*5ZbLVeaYUD#0M4L*Fk+IPVFAR2UM(L[RNRq+`@qBI4F)-KI
-)IahmqVZR%)(`Z,@%`hHYPj&Qr"1%aeTBMM9r+%XGbQMG*CXVI%,8N!#A4pIaa`N
-DUr%jfjh(@56eaP3`di0Nrp6`U3i'#1-EheQE%VPXdbBRcPp-24U(GAeh+T!!T$A
-@X1,J@4bTe`4jdBX+6F09%L,Pk(2jZC[HVr)c+6`%HbXqL,Jhfm2[SAZ@4cI02!+
-abQUQ(h5E1mk+NFi%1Jj4#TjQipL2kC!!(rqYG5Mj()4HmAKPL*G!M"61mE`jUb[
-&[-)rAj,#hR5DVlT(%$Z9bY[J"&)(5D)0hh#L+hDD*QF911EA#M3#*4LXlicZ3-q
-hQ-lELjm$le-hhNq'[1!dK)rG!def53r8`p%AB0V%(2(YR"T3(qrl-('&CBaNj'B
-TaJFfNp5q*r3jK5A#J%U4TpQQBl8+jdlCE`l%hjQh'#"A)A,%IF!ImBhhepqN*GU
-1MZdjE%c20#e,bPmGd[B[kcU1!H4"*DIcZ+-@e`p0F)LpQ2'c@QLc*U[MZdla8#@
-TH2fRA'U9[%%RiIdE@*bQf,i`ETl%Z0*cpa9LVY,1[p,1m3SfpUIp[a[Alj!!Cd)
-&@9JR6@ShcK1Q,*bKNTB@0DcCALm$r60l-d`VAbGF$3Pme(jVK$j4VRc+`-3,Jq5
-aC9AV0"$Nl&L+q)F#&m@*1LEiT8!H@JPiZFFQmALBC5BJ1UUBpde'[&4EFSFR[BZ
-f#jI-aNdH`K43e+1RVB'm5NKlSQR'(B26@PSlap2j9b,qHiL#m9cUZFaj39&(SKr
-,rNk+"cT$LmT4%8RE9$`Ih,!C`mE6YQe6iM0BhA@9+QeTEba`*2Zi8hTZHh"MX"1
-AVT,beUVeUh5fE6J)![r[L9DlJE4a5EfCh$e`aRYl)9(DNG&ReCjh+)&VRG5)U-b
-6ULMe(I+E!"KfY*5dj)X8YLil4FTHNQM6+pf4mhE`*R,!rFe%0UNc#RIf)jIbr-#
-l#FY"6[A@DV4'0+%peSK#4*ZhcPaY[4brD,4@ETHLd2AfrIPU&e4,+GqAI[,jP0j
-XU8QrUV%+1FXM[hS0+Dm#`(laFCa3K6VFr(&D)dP%m6U9*`2mr0DZG#cVK)Ffdhd
-fQ32r@(2G"8d0a0X#pb(U4fHB&mj"1c,m[[(PUSR*b+PM#a#q3f32!hV1V`%$Uf)
-M`C!!$hm9#%'[$Hr6j%UrNQBQf&`1"SPGEI%+"8eE8q*`Kjql-lf00'F1QclXdfS
-3*4F,(BBEH9DpA%4QM+E%,*E$k4ECM[he-94(T-%K2i)ZPX**&QTKAbIh(m+eYpN
-,Kb*qGB6aqe5lLE!qmTI+cl,TZimcFX+8ibS"4A`90TNF9,ZJ3&#CbG3eGKS(,R+
-,X"e$"E+Jh!Z065-*j9f8qFjU+US($Yphkc+U0bRfS8!j(%)@6`UF&JL*!D8q+L(
-kZj!!l'BCUSG%6Um%K+`dK(Ki1"l!XjAQV$TRNr21KJCNq(Q#rV6lDhU-rVM%9f1
-`+3i@2,rVpMB,lb&pQh+#K+R&,DTMb8C8"q38%V'@`Eer%&`jN!#)0a*EC3m6%S+
-e)cEMa$m!Uf@KM&E+m"a`rZp'rNZr2H[6Q15-!aa1qfrb,$U*PlUkprcBdU`$eJc
-HU(Xp"ZR[fbEJIQ+6e2L9RpGZ)0%h(00LZKr"`lGTHdN4[Pm$@X#p%M1jC!Q)3H1
-!S(9i4pRSIQTkmhHbTNJD@['1F*-+dD!Q8Y!Z1p&"k8cPJINbK-1B63PKh$p3RZ%
-m)MIKZS2lNCG(%2&*d0!ELZ2[Y$fHP@$Z30BJGaB+Eq)Ff3V*8hh)j!,e2Lf,K+(
-UZ6F"fU&0NG%9emAq9c$'3[M0a8!6(mP8aQM@Ib9c"-HRX$VT14ArIS`[aFV(b"+
--5,AlVL-3RqL5qGB&l)FA-*3`QCK*C%hir#i$5MN1qpZ8qAP)EF)[YDAk[-aGhH-
-SAA'fT38ZVEf9J*D8aVHdT$IiBp29%M&FkHM1KUF*6R&4M1JK*66NI!@@E92J1Fl
-#d'*ab!cf5YSN,hLce,&5%9)EVmLZA!V1AiFrJ62FNZa%6$ZqDAq#r6XS@91HDbX
-8+#X(*Hr3I`6SE2+9BNQC@``R)q3D$p&P8B(6-[`mQ3Fb(DBB0P@6D-*"-1BHY+k
-K8amZ9V5J-E@ZVE3`XJ&H3EfQ+*-82IP@U1L&U!Qk)lD0A5!50#NJ-bL[5Vb*%rK
-EhHUM%8&E2mi8qK1LpH&4#6![QR#Ec-K4GUDZ$Q5'GZGAr#4M%hTabS9TS+b$Y6m
-"(,,ALi85*B3-BdYG%a)+VPl(5eiTTFC*KYQ8*iSGibBBAK1Ea)#ACQUG@XB-j'J
-Q3$@$+931`f%!k@-'&lh3[QeD!`LRTH%@8-m)%$CDFcY9*cJ!S#Ll!LmCRj18d-h
-RCIfRP*X&*9A$C9l&D03c-r((#h'M($'JZLBcHRZ"A)1mrp'cUc2i$0Ak6j!![Nb
-6[PL5C-e,CKLSHE)qVBG`999`,P+cDG,NfcRm"9P&S`a0C`ZSB%6I4-BZQ[rUjkJ
-5q5Q`fch*NPGLpcLJU+a18&@AJcN`jBdpfb@9NT9h(cJpKEb$rLr1)P[Q$K"0D$e
-T2)%,+Z&JK#eTAS@K2Rj-`),*UZf!$Ca,5T5@@XNCGBk+fFc&%ZI0*L-i$09h'RA
-ahd82D+3kl&6Kbk)9+ae3XG3ZGILZ&K+-fd29*d9`5V9lpbPaeG!N@XeVAcKceTp
-UadcicfiE`1JaVjJajDDV1G+$a)Z(edU5$h25!H"f,RMSUUcMh&66Za-0U@iEeeE
-Y#SN31A%b)Jc`04FmaBe`efZLbr0)`*!!8RJDf`PYrrPT9RD83T%Y6"S3"'-&4)I
-KpBZkaU[J"+Tb#8I[+2d9kR#qU"KEU$qc+HH64(&UCB%S&B+!haJ1(CkX5b!frEJ
-J5RmP#XclL1RRVKE+Kk,lhD9Q33GLG!+0#aN(RLEX9aKh(rL'%NChlGJEZ%hUGb)
-1X+&!`Rq5hF&Mi-KBrPa0hjL4a5GJ!&H(BiBMrPPX!PC$PJ`'(8rPLqrCC#Q133U
-rF+N*cfr"XPpLk)8+IeDl)ip'9kM5B(5k0**"E8MNiKChT"URLjlr,C!!#eCkF[F
-k$kJ@HUekIDi[HkRRpMjS'f$d`)eZj`+r"cVM9N$0M#j4X+(UQHQi$4%Nq*L#TF8
-C+Rk*)N@M4AA`UhpDTDJ*"CHSeGmPP2+FdT6h*VGJMU*0jTT!5YES)AlFG3T5KN#
-!Xc'e1lhkR33r$,iC`"0I6m)fZ,%d-JXDlAlj"SJCf8SF(ZrJJ!FarR#K&(Z[93(
-Y,KCKL5aM+j%GRS$F-J5i5T!!TpeJF49ECGNRFr1+Dd#mpMRN$)Z2VUY@6dmA%&$
-$'9Mj5+4#,L6cKcXpa#QSAcU[N5m0hUTKGQf2,)U%*GV#-YSe%paQB[bTNQQ,#*-
-8"024dP,mDSH#ql[FdfLH8+54&0E@YH6e5ZpTiU2ddpaq%ip3(T!!SMMMqq'LaZ9
-prSmecbaS&"H&#M*3l$2AaK*5-SUkC,m6rqAY2epID5Z88NNbG&A$+)@U$DUNKQr
-!rUV,2[!%rPQj!r[VmilJirNfre"%'YjJBpQX15El-CBiJQXT0cb#bD'Qh0ha)f3
-iJS0'BD"H!Ajf#R9`h-c*!b![B5CM6P4c(iKZPr4mTFlfY"q)-Ckc[C29AP-j$@`
-XYJ98iUmQ1N'9Nl"4+pp!bf(rCIbAr#5KYC0Z5`c)8ZZQaA*V[1-N4e!f5U21chK
-50P6T!%R3q0aeD#+h+$`Pl6,SP(aLG,$2IVdJXKb-lX1lVDE"B"9aaqG!,3DpF0@
-epKrUf+6p1mBB3J`dG$6L0B0RAKUY0DhP'83!qF%j6m30mRdbc1%LlJA6mkPGRUP
-#F2'bZXH)B8iGGpBRb%d$1-PjI0Ti-4'3!)8C$plU$+XC@),&hl-#mrARDmbYEMR
-H,Y6hi@!*$h2aB3&Qp1mP#II[T!B9#'6*p"KSiiGhc[X##AIL!3(Z!UI`!JAq*#X
-&TGN2aQG68&1Bkd5d#fA%p,+#A8S9TU"rq!UPF[jFVmjc)Z)k0EKEm62E*a["1DI
-X$j5ShE*)8I"GkR#RMdf,!cZCVebrbKH`K@rm&`P%ET6cAae'er'cJ!SjcbHXEk#
-&NHC(-pG[5)+(B3@"RAaJ1Ae*N4P,mp+"mHRi(HAEFrAXIQrjp*'X!B'EQPXaiCJ
-a3b!#TEVD4MUA*e1bPqTbYUBQCdTa)NXIfX1Pp&PcI&i!qc+pd0VlqG3&JI(,5ij
-IdJ)-r3rNhr$VP)#**5MDqHT1[6##K1"`X++EY#bQYiA`N!"@0KqQlh("Q9'B'ik
-Fk1Xd"N6N2%0c&j)rP*lGF(jBf6AF&(UYcY+5+Tdie%"q%fP4qqcGHp(0+ap4LQD
-!rfFb4aeDCj)&BM*dMXfY!F+D6EI+)3c6JMNcffjh()jXBC*I"KZ1X5pkf4Pq29N
-D@H11KJe6GZYcELb8jl(I&*e+1a%@"&%a'qE4r4kL*(0Q%92+jb(NbU#HT[SfSM*
-5IcVa`@(iSff*1hr#m3`iXK`A,'AYDFHDH1e`VL%hTKcT%U2ll*(%*MXXPEaF#lX
-90SNRJHRVlr5N3`5R"(br'%#3!)I!rM-!3+*pmSmJMB,Z+8kJTlTah4LC+m)HeL`
-U5ppHGPUBLIDZZMfiA8lhH$IbPVjmVkhb9RRKq0P-"pCq0ZK'!aUIe!l2GmmR3[r
-0Nj!!,UbZpHr8b9G3``e[pY-'A[0`T8)MVQ0FI[6Ti%RJ%rUZ201e5q%VXLD@2Y6
-b`EM1XTTmE%$*&M%@NQ9ed4VHEZ0TDXI,-KbZ'!CV'mjT"40+8)dV2pIiKHArCa-
-X1Jm6d$V9fN($,(8JSb(!b8[T38[qHplMVMYl'SXja&3'Y8FYA&8e`"c-a`f!fCk
-5G43UYTe'Z1BQhV#9kZ&&HG+ZSRVP(ii1HUk$iH29-3eDikN(b,["STHE#6D+G#D
-!XKa)I*Ek3&HRlrNpF'+a+4[XfPB[%"AD18X)ZrDGPQ*CcE*eXbR(QjIBQpqC)"R
-f`Gb#iFC3IS%S)X8MH"')'#mrl!+DiSqb-*T$'VDkicAS69aaL5(%qcU*1Vp,MZr
-5p2@VS`M@j0-jkQN)EpPVPqE3fKp234#UT8SLlI`X(Mfc6eG-dqHqY'*ilYTZl18
-Cm,,iQlGd$1e9+U#U3m2C!`,@idZ04-iKQ4Edd+bSF[BiJZ$a8f5Kj!bE-(U68Q4
-N""I*9DpdXE9GkYjV9!a[(UmfjM"-pQ+"CNFCZM5rhql29FcPlB*mbFkL*CeYL`r
-JMN,RCSZBlS6*IRpi+@fLLc%qcZYUID-p+qpc`cP3+ZZI4hT+("Y"PQ6)lS9CMQ0
-P)0iKQ[,2#bY#dJK6Yr'S@&r4Mme"4K9-3&&F[9H%Ff9qaq!PAIU1Mp(0r[@h2DI
-(c#r9A5Cj*[1dXA#m+$-T8S2PNYQ2-i#Qqkd+p#J`Sh8iL4e`#&N#8XfQ3i!ZPJF
-"*J`Ua0Xb(5DK5KIRd'+SBAGj`3Y6Q,XBJ2-HdjP@'3XVrdLaeAcCGA$F`)&ki!6
-U"dc%J,d80AY8Ja)ld@kRI`+G[DFj)jI)CER0[8Ea#kpE%*CNFXr#N!"2[dFi*@T
-d0"QfiE12$i#dXMfQaFI[*8JU8PimSm%I4hp9S@-PBZjLRT!!)!*r#Dl)jaRVEf8
-Lr"A8PhG$KT[+-%lbE[AF-3Vh[cdqbQTbRpXSX!5%D8L+&S$5i9XI9$UG#Vp+L,Y
-Br0!)Ib[RJaK0B'LaI83Bf+EV&Y6(P15*Mk1#kqHqr+U8Ma'3!1U%dE41Z5YJrKQ
-RA'*[3("f4dF!P-ikp'#clp%q`NJ6d4hX")(C-E(V0,fcBiU%dLAVMpQ%8&`0G12
-H`+1$aX(,$*8(9cE1Fl#SUZdl2&85MBC"eMV3jAJQb+Z"HSZ2qLR#`kMUXXHjLHN
-b9DZZKPY8#98c#Z$)+4Llhk-h1ICiTVUkMAD5#&Xj4$3#S9dRj(M'f*SUK[6dDr6
-4)``,(J)GDj6a9+$RkMZhPD4dpPGLHd9-"$m)rJ[*%*AEb[e05KUXhVYeLkKM`4F
-3kjY2"l+lZDePqkHk'-qPVI6mI'XL%qC$bC6QV9hDC[T&bmaD*V(GP,FGR030$bl
-qr!C,G6*Ea(@kr+5Ypkc6m'$GYfk6K25+df-963+I$KA,H*%a-%35P!@'bIVCE[4
-2)4-#ZX#T!"62!eLj&CGq+daT-b0DXG38%9@&0MkfP'fk$RINUI03D$#RZe!#SkN
-YJZ([!-"Um*k4j1&eGIh5jlLMSQl5GI)QIaR5![fE`"[%-NL,Q9SqT)"NVSi%bX5
-N!MD'bKa`(!@G9SE2"P(k**0%Q@fV)$JLc#d4dZ)IPj`B+4rmq&*iDbZ[fQ1K4cq
-k9CTQ8,'V5XBrJK'MjFI-Yf`4i$8j!QDNrdARP,,8*XJE'DKZ([hJB+YH!D%L4lD
-P'F60jLZm+FFVSHXB6SeJ$meifJ)ldpA1[)jKqmHp&ri%2[,5`q&4%VQ(cqjf6*j
-rKSN#Iq6(bY8k2!k%R-aeEPeM)+'hUbqqLIQ3!(UYJeaLKeI'"UXFU#i&YPMbfBj
-9DZG0ZT1@('!p)'e+k+UICi6kAB0j)ld!GlN,iBQ@l[0dc"[H`,JENDK-)V(5[Ge
-+Qf(2*jCcafr2NJ'Ed%#Ql@,jURG"Q[jSa&#8(Q6p%[Y4RcjY1hr'cf"LVGBr,%B
-mj%9M2ejDTQ[l`)LppYRkFc$k""kUJCe,rrE89j!!)HSbqTUTBh(&diL!pLE)k,P
-L`59YT'YiN!$5JdDUqkcSR-8-DY!a!&2!P`$j)MPRM3m6mm%bB*6JFY&dZ+p3`Z(
-5D8K*[Lh&%'2ehT%SYpFYmX*'UrL1E'pcI!KN+&ED@dEQ,[mVH6mf#3!9BHkrc9`
-'1N[0YEDhHEb3!&D,JhLfCq08"ri0U&qRH"bTfq1+&5)BcPDPHcdd[mEj-F0R'[U
--j*Ql2SbqF3YF@br5#6j#X$%V#KTIc&[TrSpPHJ3b,ETH6(hdHU,Kh10IC@*qcE$
-11e@ZE*[Yrr*Rmi`m3VibiX!hF6Qah+1%QRD10NMH$cVPkrYSbVE+H!b8E-Y)0BT
-9[#haK[pNm1Yp2bldB2C`)TT$K!B$VUF5Ra#")+l40MYTN!$XrkA-#@FdKEd6&e(
-#TX%l08)PkM9`QjfN1BkU!X4[NYeFEKXAV)+`a&3PDB+FcSeYCVZpUEq(`)%fhe9
-$Z,[SBrZBf)XJf-RG5"j6X5NlFk$ccYJ0#XDiNE*5[aIa%T'ZjNJGAThm34Q#H!'
-i1lSq@+DZ*K[04"3`XX"CN5Ca&qYel(RcK53CdcGlZ9YAQNH(rkAj"$BT3jXaUdd
-SPFl103aaX*M0lfDRVkVZDV@RZd6YPTTeb+k29N%GSCAUqBNFqa+`N!#2'FUDI!*
-9m!d1UKj#rk#$C+Q+9[(``jZ%RM03QKA,NV"CZq2a+HaFCk+E"M0PAA+&pDXdq(T
-h-j[)IGd%'q+1!0kSVJE)0V3dhk,Xej1Gj"8lVQ`-C6NriXTd%Uj'3IESSYdrK(S
-'4D65,LUYc`+P993AM!@ZV[4QqIejB5U`d+R`5pCTc%jQ3)a*V(pqZG+kl#p&LYL
-QYqiY*a)l49'bX-bCYlV$B'e-PifNNIZeiH(Pbd[pDVl++lqD'`R9HaPUL%5$Lm$
-`K,jr[Kl&!ipFG'85[U8UA3j)TMdE882JpPACHdDHe$kK$FQa%9)Qc[4J[6+R(G5
-1(ePlT@DZ"1qh5l60dH`"fLkA4*F[Z+'N@'@L`hj-5d%U8`T$iS9VC1eN86"PK#B
-jG&TcNX)UdbA`TpGRffX#Q-b5DK0%4DdT%,2F#dQJ`2d@Fm'Cph05#jfPd05NGkT
-j!@P6iGKU%1BbUFl9BB34)GC`V[aka%8Xd-bdVe1bb`J8aIk0NX`9'f(B!3iTbX*
-cA*kq2H(l59)P9Z8@baGNq-&GiJZ0!V%FRbe59-b'bqbVLVX@2LmDQG0'f@B4*qI
-j(iNS#ANP,5JVI!4`VA8GfjkHbbA!l""iMG[`'HVm+Ii"CJ0+!bQ'+K#,`d$i`Ej
-9K3ia$QJjVZheP@5BHJ3R,N`,!CYeMeNlk58J,A86%Q6%91F2fT31qp'+'RXG)a6
-YR%G(ZH0`kjZi6@qJL4pl!(dc[fYRKlS%G-HemjQEQ0,G&8j+P34I34Q6TP8#$%T
-dQ42eKZTYGm,JPLX%K2`+C4f(UZk3!#p'$HPUT[*mi9Cf6B-Til)mM!m9$rRfih8
-LITe89*r(h'DJT1I`N4eK#F5cc!*fXpZN`'MYLrX%fkR$-9k@dYElj2Y3LD@Y'!)
--FT`!LirjG8dAUicm!YR-c2D8MU409f@m8JjL%'YUi2Q5&d$Aeel0FbacGhD09ZG
--(dil#pDA%%9hY2,`KfjD18'SYaV(CP4[j3e,*rI0(*6rGMmb#IY0&"8HeZhXJ*@
-CHc*Vmb2-EA4LTKb+FDrp0cNYUe,9!Q$Y4mP@Q5lVRk%KE$dke&M#`qa5!c,0ahB
-a)If$`LKeNRbDihQT@aLQ2GY"bbm%rKbB2S)iEU26qUH4$%U84jV,ki9a-0jba"q
-$Y*MpPiR3X462pi)R-EG@r`U6Tp*8&m3B2BP9l*a`c-GDBY&eYjCTr13046d$$Q9
-HHZ*0GXND5PkAj'`%USGPm`6p35)"Z)"H,"AP'4YjXf$VSd-bCY@6UJXZG8c&IA!
-E*P%Hq@U)KPMM5-0#qqP@Jq$FMXRAF[mk",k)-N1,0,XHk*dE$LCQ"0,)Tj6j463
-RDc"rZE4(6e3!X$[V59bQI8R!"N,$KHmq*fi5HPC)(XVEc#9SaAZ#qK"(S+IN*AM
-Z`e21cAJ9i(HKPQEE&V$qZUJSbUa$Dk(F$N(QPp!%"L6+RE8fL#HF@I`FIShN5$F
-Uq#*86Tq-Fqd"&5R!d+iGJkcl$Y%2c5Ki,!'ZN!$&#Ec$0pE%6+Lqf`eVFi+)##'
-a00`IRKiV%2b[LGp2ZcS`PC)@2@PTZU[4UMIMi`J4k3j[9'PVp!IXp%+ablH6K6C
-Nc%5(XS-jV"rGhjM$kHhTU0`[iN-8#E*Z0X9((bH!IS@66QQY44G5p46#6e%`#XL
-FZGe'NVHAjd@k,35HUHJ`TaaYeq#$C"'qA@C*dVF2Xal)8H[380e%II[YAqP*DcF
-I2J3LcQZBeaRmMG5#F'3E1h#U+J&*(JmSM9j2[-Mc2IGI)M-bEY55P1lfe`pM$p!
-'3-SHLlkq%r3#b`lKKBpK[#B1'(c-r&p(NcG,Y`-'$kNNe-MSD3Hd`iXpmdVrd(6
-[4#&d90[1bHR&(md!8DL%2p2DeREGaiNA5@T,2fhK+FACMYS2[aD2E0ZE1466i8h
-Lf)Y%0!HQb@JQMB!0bQNJ[1Rki*+XJFYcQqR!#)5HVI!m5B3hE4RQLPEq`UdCiPC
-ZZTMf8NHCQ-DTJ%"Br'kI2(IR)A6i`[3qlSelrIIB`8C`$ebPe$8HJJL9f-a4QHm
-#Vdi4JjQJAb(#$Y'X5TZeZC+eZ8@D8FHaE51hpTF38l%#0YVK[fFSUVad*dmX9#R
-3V-ElCX5G@UCr0"qH*K#VUpJJk1&C6NNd#23DRFT!-[a&TN,mDSB%p`eJa6Q[bN8
-R4r+Er&AG1b%LiVDQKHG+-IZ'"242$CqaqSlQCbjMek63,k(f,(*J!F@Sc25M02V
-J9mB[F1IN%I'FF)pJ5E!5X"%ckReEmkdY1MaCbIA@piLH9rS"r6BaLJLiT#"q+G&
-29Pp*,E!K+Y*4Rd$RMmX'9Abd%'J%hYIr'fcNMbY+FCGR'[!)HlD$3M5MRJ%'m#S
-9VJBrKPjT`9-RAZc"#D"fA+C5eqRi0J1,1I)AF+e"U2iNJDXJqrj[dMk-B(hSR!G
-$-B9`UM"N`NJaDFp)C0*Vr8@SkLqXUGR,`jA[Q)fQFmpZ8VfBZ#cPjm@'@GL-Zm$
-k)N@ER,d2K!2LG,BPK($[3SUbpTGH,3B'e2PZ![pIaad$V'4'(KPLP!2aSkU9'Ld
-VrLl+iG3*XX(CVUSddT1%H,fDeAH$&8SN+&hbD6[#&e)6$c`TH[Rif8eE06"68,E
-'U3,rV-B'fTY*5dkGa&pab8IfDbq'K3CQY"B'[8le-Jrq3aqXS&"1e&PbY#+26(R
-lhpPR!K&@j4ZZ'JK4,SKpBS@eIaBj&eU3!2#kG2+4Mb4fZR*r8#P`!bL2P5D-d$2
-jXqf`EFD@ihTa'-G-QNq*hhBS&hfXY"$ZG9@iq3c6Zi2J9R$d$35+fVETcJNN(Ef
-UY@q+h5SMU"eRGBjMrC+mchS5AJX9q"lbr40pjK",9Rm53q-1(8B93Hdqi'+,E$L
-,ibrQ'MVZHH"DJJd$)@*,U2i,&hl'MfF@ZAP!I4ZT2SAcdfXK"eQ`q[NQ()mPV$m
-8IZJ'[kHMPmj$U1B%0*RCRqdKdVBeQjDhp,h4')%PU!3+EK+X"JC6Jl24VamCD3[
-KL'hT15A"099+EQ(hdK41Ump-KA#4#%QYXd83f%IJQ,'R4Zqch"'c+%Vj),3PSl6
-&4fr3@C8%Caf`&D2*KH0iX-6dL$jD6+MMSk'$TXI(h@MQP8fL,F4'+2[jj5RNP)d
-IpY8UNXc4Y@HmQ,GUZr`2m`*Im4T!5dqEdS3PP)%B,+'#G5!j&1CXRq[-TBpL2H!
-YIS4JV1i)fT!!)CCC'K3NSA1eXV(k8NZ(eTAFA(48a3CR8V93!jh3Xp%GfmC4c@h
-1fM+"&0Chr2Ec4Z4eM)I,2EM6%K,21(rM"8D*V[EBikL54kh2Z(ZJ%aec%lA9m4S
-eeJkm5J-k&aDj@R@&9TX@hFN*Z-&F-cb*#qhPAZ`JP'q3!(YT!i2)beP3KilP&B&
-@9al4aCfUX9#YH`lA,NQ*+GS#4Gb22"@Z`d8S,dc#rhVV3ppH3RY)QM[bSAjZ%5q
-[IkiLj`R'V##c(@E)0[QBhM2L8T*$EH15k-raS(YKSETRATk`)G)m@+cZLi#@lBV
-l1H(lE33C2p&c*[ZK(UElmaXll+Z*TT`'U9X[S)#k6J!SYPc"&2YDDAJ0cVb5qj!
-!r9UIDlVSE`#&2"K6,@LJBpBN&ACSpY&H@0SRN!!IS[X`K4PEj!6kC84lX,3A#9Q
-c26B#J%ZVjTeMi(,Q)ae)2kT[HMGfeqNreb2r-!e+TVV8QGd!-%8BLhm@R)*B29&
-qc`5L4j)b+%#59TA6Ph)))bD@lD`L),kjSVY&Q[TiBXh@'Z8JVCJScIdb"X3q[Xe
-LiRGDcRPQLJCNcSFTibGq3N4[94*QCXj[Sl38h-8'p+E2TDS36U5MKBm@*+rbplp
-hE&RmLd"VR$E0GM$-8#a8&#Tm'lcM8Vq*SLBSLP!Bp!2-hrQX4Y3c-$-,(a,VX%I
-cTEG9ZpR9AZQk4+P0L&X+#ZUl3!V,8YSR#!aH0R*i-2,cRilABCS`&9%2ib"ZAB1
-IJ0%2Y#3QSd$[Xj!!RjelD(,RE%L&bI9aLlCGH[ha`!mJ@N`Jm"&-kaddepX3&c$
-C`KE[$3X"0@h,N!#@m"TIqA$IUajd@RY-R@aF@jDRQZk,4*!!m9N&m5e)f6jcm8l
-0)TSQXpUQbF89A"E(A'[4eH#FH[a-%NEc1a2*(S"R!m1V$P4H@GX[)KhXL*(#9#q
-D(jZ)hT!!GpTBl9CZj$-X*!PIE4@`SqM0D3Q9TRi&`[,$'E#%[H"mFH0'N9[1!*a
-U2*L$6(I8qL)@krG[&Q$5VVjYSIR4@Z%5ASIF*l4q%DQCGjcM)Q#c(QEUIk19Y2,
-ES56+c!L5T"$$cFkT0Z@p[Y"P5([c03Uc15GYi$2ZKD81b'4F@ApV!ZaqK%-APaI
-+(aT6ILAS'j0$HS[8HX5$NV-cY6!Tc4daHDS!hQT2@iqLjP5fqjY9i$raI-m%b!+
-heG*&kd!rUq9*TQ*`)#ljb+h0hCqKKQhTDQ-R0K1lmIU[cI1,I)Dqjr'-%HmhVfB
-'A"22i&Xe*m'q3cf-`!dXQ#a0U&@U#br2IGcjiSIXSRj!(PeQGDZpEceH1Ij6F+K
-Ed`XAC8@PD5rqa$mdRd,Iq5))[+(eJ`Z+SQDR,T2D8dF[i%+p$V!2&6*GG3*RP2$
-+@"-%YMAAepJ9YBXBZ6rXdY)@&bYp"$"iQI(rr0`UCkej3GNQem$H-iEd%I(Yq8p
-iC,m!%3ThJd"`5*RB5-UcMi5LpFlPc,IrAR*A64qZ`*U)qHpQU1pP([r[U1N!fKX
-rj5-69(QV#bqqXXbb$hqI`0j)U&'2Vb2rIq4&UGD3!#4Eb&'F*8k0K4X)%1%6Q2i
-GHIaRc(hXeRr!`G@b83M5$2c4c1Z9S*HqeZQhpEb[!k3IQfj["1&NS4)N&Udke55
-'EeeS@5(kE3@#ZLD1L6BI,M&VqmdY%L%C44QV@eDN(GPqBqP'%*Hbe8T%j1T!L@'
-QqUlh,dESfp5N2+AT(3EYA&!h(Z0b2"#9EjhQYqF)%c'B1pIJD4r#f[bAD%@0eNZ
-G)P45%GR6X,(6)N16aJB)M)V+b$+"aGX030VpbpI'dME#E*K'8RI15I`4)YKBbJL
-0Z#&(4cEBYI3`Jl+2(8+`q@baB&!)f(P6RGE434-d1F'V&$+90eX'f!6bLe&Qh"a
-JBVaS3QfhP2#*8JCUU[12*+dN9#m+i$fp2bZSS`2qlB)"RS5q)'J[pQ,#JD+#LVj
-TFEA9!(lRVZdM(dE+iiY&BUNNA"GMHSLBRqDN1[N,eV)Y@LUFAUFae)XN2eFihi1
-kVK#"A$ke$KA"l`V63aI5XKp$$,5&F$"hF2K#PN``#Njr$*2%Mej5"DRKNGfEpXL
-,TPZQ5BP*"EC9TCGFZ0(reLJFph)*XKB8ch4i"lHk@564#d9*-lC`,FdUXGF13Q2
-E#IBU(`3P0DhI3V)%NE"*VMX1HFQ3!,)6rPB-fXpS2k+T1eZ0%k3+5@R)(8)*KkI
-N)[YAf8@r3"B`r!%&X-fCKm"@3Xi'#lRmKjpXTMQX"i1*UFfa9P0I(qMYf6jJ&3`
-N@KFT22+`q`UJh$Yf3,3XRh(3i9EY[QiaFhpiD1#QCM@XERMS$DD`kC1a,li1"bB
-kTBkFP&NYZTJcQ[AdKpTrm1'4eC[-RANDAVF2Q#hl6k,@NT4fY#JN)heHKa"[@f0
-Q'Y2*"38!h"c!6FZ`(2VFk'8d'LP)`5flmVa8BNGL(q)b&8&R8Y+bXpUem#HNZ),
-D1l2dVH@Zm,SJT3-ZdYl5)JXed!-%&f#5ih($Y4Ta`@%P`VqLC[L-#VQ,"RTi""C
-Y4ZVEEK'#h`NH9LMbbq#P62MldKQM)9rFKA!1XraKAdBcpc9M9ZFj$`PE`[`8bJ5
-6K!kfTM(ThHe'Jdi8X6pNMQ$J9lLkke8Ci&Z%0j%@T6JI8L(Z!Da""c)81l2G`Kd
-P+mppr["R2hN[ZB6Z9Ei+Z"THGicXYTYP(TSPP0,HGMEfik#VSPUK[+`Tk'X-QT%
-EmS9YJ9$623RPhNBR*p@TT(h3l&qMbJj%!$FBd"bpe(Y5HSih313jV**JJ`$J'Gk
-8p4q3!2)6E1&bQLZ3!$3P[!RNdF6pkmNXeS9A05MA)ql6JL)*[m`I,&H,'Y%U$!3
-&6,F+hBd'GYp[2macpN@m)UC&#AG9(#fZ%2NR$PD-@%pPr$2B!B$kr6m-4*M!dkE
-1S6`p)+5[&4cmMjCpTEAMraN0"N,A20lCY`UNmkjm86Am(E%Rq"1!e!#5A*h#aI`
-aQ4%kC5LD#LfN8`5dqE5b4raH4mDZFf1(DEj+UeUXfLDKFA'0LQY*)4BJfe[p@QL
-p8%+S03QG6$h2,T@$U8j9ChA5Cl3$@`I",Zr2LfCY0ZD[Yc2#eSXfKiVYi2m[8'R
-5Ek0GJq$6P0dZUf3FDeXEb4"!PAL2Pj!!1IRZSR'(BT1,Jl%De#$4N9c,5b!Fj6F
-abkP)CV0h)M-9rTh"5jSM90!5feEJ$YXlkk84*fm9KeL18E&UXjS"VQYYd9ZR4-4
-2e8eJe6SdZaVd)K@&AQFFlqUlDJ"NFF54(mILh)LJ49TPG"[c*9*C0@IQKTeae[l
-jd,1rIALke9fp+'8rCHFXMc2bUVepp&#jVrm823I0p-0RdqeLfC1N83`E&Q-dYk)
-3a5",US($N!$3a9&88f-cD)'e2Cjq(fKKd2F3*Z$9fL2pd)6,8')k$E$haYal9*X
-+Eiked+f&CRaXh$Nah'QZUH1,Sp+`#1ID1Aj,mZZ0H0dc,lrPGVCf1a,f@!BL&Yj
-3ibph$)6HP*8"kmrh@hjY'AaV+chF88iU+(h*LfPG4J"IKYK8cMR5eJ8B4GkL*63
-XBCim4VaFY0URB5Eh@aEY,&HLmr)#Z5LI&c#0KY&*B8"U,`Zq2&i!`)CFr+R[dSU
-S2TaI20V@&df*L2hFrC1QT8)&`klZj)ceAjFGQrJR"H@ekjk&&N3fFZFd545aNZY
-iLl3J$@K0F*MR-JeM8Mb"12`GQ!JmKHUMjYQ51%FH2`4c0Uri#HhQLFDPlEE2dh#
-Yj6f`NC5jlEk$MQIhDF6,i-9BB9RGa'FV[8U#*'d[J$Y5f[GfbU%b-hE@$kmhV8!
-&jQ*hG[Q&(H&pEXb08H%ScC*HLk5D4bLZ%cFTC&"(4(R2LE6ZB$d11-**X"@D@[6
-Y)fD0L86Yl(QPb+6,[HP-ie2#daQV"%NVSF#SVC(8Vl!Q+%cE6+-!F)PFD8kE@'[
-iZT8ZRc08j[kH0IHQ'&V6KT@Z&dJV25Z0r@)a@F%mS*r9TeT-YShE)$*HSG46a*G
-2fGI(9$G8VreclpEF%aMPe[k(%J1f"Kk2)pbla8ef8450a()&Ik@#9)bp+@&!E'D
-R$f+%HNdAq+(Fe#29-42YfD[-#5,K[*ZP-2#pGP@bea1N8XP-J-8L0RV@r[(Q&Zr
-X6-dlerIDD)#`PC(YGbE%mE1$6)HrQAJD3C,6`ZSa(1$1EX&a+8kEL[M30hAI3al
-L0'q6(8&2S(&-IJ9Lk9k*r6*mDamr3+LcHce1K,pMfYJ[eP28HT1*pZH8Yq%r2Hf
-*kV$#@NM1p"VP!ecb"FpR20e8Zl2DBKpCfXjb1(,[6XFBUCpK-ZpSI-fRh2$r%04
-H'DC*&+q-LieX![@@$l0+Gf*qjNXh6qkjf*h#FJmi`PUi%"X,h&THH[9H0L2b8R8
-`2))Y1'X'6JN(CM`5"H'3!$2XmmF1C2'Xr$fF!$'[Jp8FV,q0LM9XRFGTl@YKbi1
-6A&%M#qbAjMS)afb%5@`3@4`e)VNhd@ZkjqPJjb(da'3&1dk!LL6I#',E4H')C+8
-apU2(-Pf(#Rd`amJQhCp[!4YQFc-%@d1k%3C,'40%GmlX*CF'T81d)kFEeFJ2r(3
-4EF$-%#lJNV4A,ZKm*!"E3(Vc2L&3E$DbPdLmJL2[CSeUm*i2Mr3MU,BMrqj61b%
-[Fm0`6khk53UHbEee`KrDhY0rIcCE!I4TDR+%@8l[kNQZZja'a-#VYGYbY@rV&Qe
-AXZlpV`XcHrpEJb)mZ6e)Fb(0BiR!GCR2G3-*Z9!ZJ%K%NPV[X9c49Q+b[3"i5Di
-ibEpadNl(mY+kZ"@mY[a#ejZD'5C`0qR8lG,Q0`81FaM6b-mmbJC2B`R+,$3jNVP
-Dhb5j(f%d$,3BAAmhGLQQBG@[Ye1MQ(B,%ak4E!(RlmSrc,)-m!'YN!"J%RhGj!V
-6F1iTiPcm0&K"EHAjhhfjRPM1%aHa5CmTZG@r-mC%-YZdhPiB9iAVSamkMa8I+q1
-PlYA5VA&bH@0K35F5YHFFh2Vl@H@#J,5`p%Z*`G+J2l8M*0R[3(rrLhF8hZeD!`B
-DI!1#4(abd8M+E4m(QMVe0ULI!-j%%V'S!BBIDLJb,R+XZNa-9$cb5,jahj43YlY
-SLlS0@dApIL'R1b[LR4"ViMe1`82Zq!"KA@mqpHZABD2XLYIiVr[d[XPJMGk6l5p
-8(+qNpZ"H0D#2*E`DR9%1$,qP#M*MZ1Ij(243bEfddRjYfY"5)[N,N!!&UFpX8`(
-Q+Ub6M'1h&GQ2lG5K!NidjV6LbjmJaP9X2CSdPP*Nm4ALiQ4QMCfq4(p##rfBYqB
-QmM4mGj!!eqe34RNEEkS3,XGG(2ZBCJ&m`S`BqLD61d161M)+#M,K3PhKM&XVmj9
-!kFE2`CNTb642C4l")hkU#mF5Z(#m,8dc"cZ+6AVKB4%lCSd2q)p[30$hbpQqMkq
-q8""h@Lirf8reMGpDa!YD1epK1d)+pCK(9j'bXJ,2kQXh4,9$S*AdB#6RqriTaZE
-B%1m5!M2*rPj&2&fC,[A+3G8F4Mb9q"jb1'2M5DGL"Y&12"&P8`d%h"aFPK@S%8&
-Imb#%AAJVBB'@##afI2)DS042R+,U@Yj9VDeFa5LYS&['$`QK&+f!TV"F[3&JcS@
-U%hckUAP-(bB#p&FMN!!i#RH!aJhN&pP5E('*('L[8[m)f"ZE#mM3k"q+dJ*MUCc
-X@F8J2KqCAD,$Z,afl04Sm0*6Ta42aT%`@BY)ZZ@#q`VchjX!H[CLRj@f!0@5Jm,
-2QS4Uj`*q8eYDS14)S4T0KF1$CIb"6+khUV&+$J`qX`j+Vlm`&0Q-A!m04,B8Ke$
-ihb92[eVk3Y@*DVEc%J8fA9F`fM,G&lbbaiM04RBL9ec$N!"CIZ"9a`SE,"Al"1J
-eiieM60-15jdjdYAB,lPYIeVD@&Ra,'U@PDA[4cV+Q38*rDX!,4h+(9AG)k'%j'+
-00Nh1LmDS"&hT8%RfmZ%$-9FmP(hZ@1BEj3fp@TkVd#frfrM(QAYdf@)TqLR"b6V
-9Me"8GY![X9EbB142Tkfl*2UGSDMi%al,,'Z%91'jCZRKL84)ak0PbEY"$,!H[Ff
-TUHZMkH+S@4%&*[+IkXD%KpG*!,'YK496iS1Sp9XQ@(fRP!#hUN"4(5rJq9dQBZ4
-r`K(`RaLqrjE)SIQ4h)"$X80+(f+3!&!P[5bYCh@YK&8#0rBlJ'h5jqHA(I`4KK(
-!Ii8hflG)PD#49'3@eFRUkN!CIRblFb4Nbjb$[p%!Gd1+3""GIDfqf0Yqd1h"TR%
-3hb46h1lIUG8N*X88E+L6hk`q#8HNI%r2QY*meIjrGN+kb3(5ql-1A2[j6iHUYj'
-e(T!!-CQbhLUDIZTa*fhm1k4A$X)m-K9q*5baV4ap1IfF-LpCPAUXC2rdeHqM"q'
-&6MrEjdhUNRe!k##*'5Y#)HaZ20LC3Tf8@Za6!`9H!V"ER88(i'Y0Y'kd-r'FcTb
-D,lEh,@#Nid%GC#8#D'fDrKc3UB%MUdS2LZP`KP9KmeC6jR6P)`"H!"eI45lZ!ml
-IBJGCV2Z#40fJUFUp314#l(b@,3D-[PYT9295L,UU4#Idi+5XFr9K&c*`j&['VpK
-)3)5`"FYUT#)J`Db"LK2'!b!Q-!TdS&1p1I(fTLTa1PSXPBqIHSJ,MTINh2I@)fL
-i[fd!*N`pS[%#+d!iiU3S[XH$D&p-NKR8R'Sq0CUm6RlSrD1f3E9p8Q)S+)Z"5QZ
-V0R'Nij%iH-C5f!'6FU6KX5R"aiU9!"0TF2jTkZbQC@cHapS86mS'DNUL32q!SJL
-YAATd#d`BG`(4a@'UppjZET0@2488@&i[)E`SeY++",0Mf%RBPIc!k545"cfU0d*
-(0qfV1$aIlSDm4XEUQl4h('`6,"FYcX-R(EY*5%+@bc1i135jTC9PJU8'qd$K`&4
-$L!9e&$mrhXkDbf3ABS4m0'[Ac)#(#"IKF2B(1`@U!@mV*3)frVe2!kcRE60iKp'
-1,A'89D6Jl&ERe&"M3XZmc%&2DJmIq*Fi"E)ldDi4IjlRS9mHZ+2LST%`p+,1pCF
-QcZ4FJKd,iRhdA@)qq``958a"q93k5pF[de2,&&MU%bIMm#8Fd+PXD6kmZGA-+e'
-#JEEY+8&B"2*iSb-lkjIF0p$(SjQ@6P,@"-L!Pi4pNmZ)J1#*1$lkYTjmQ-5M,4a
-@d$lR(dR)"IQqD5X,YKLPP3UB`$!qY(FLj2Jilckq#m"'9*q%J`r1*m2`h3cj@f,
-+ac*0X9beQ+#49IEVGlF6mE"2m(RH3+VNCPjG6#i&+-`,ZQU$a$b3!"AKP(`ee1R
-&`S$r#IGRml&3ff%kLH@fH"U+[Kb)++Rj"&Pk@H5r*qT[phr4rIJa)0Ha$K(*Yp@
-h&Nka9hp!aF((N!"H*$GHMQ0Qh,V5V#%S-k%8'H5c)P2JDk4e('2%2SbA`2B`R3i
-C81i*pT6jX5`5+'aiZSjGBr&2+aY"18%j%)&&Z`dZ3`'jV!IC)-EbbYeE2AC4jG`
-+aXd8H&8#U`,IG8c8aLrpLcAe(dl0lB,Pr3l)e6MQRB1bblBEZkZLI!EMH"#Pb$I
--`Yf*9bX'#Tm1SYac)U4&83-!1qlT4HEVEFA0#6,63pE6eUBQjYK8q8!dL-U-PpC
-,r&'mp328bR&rMC5U[ieacr"UUXpS3`&cm%)eReJdIcrQZDY0FQFMc"0f$cA%K+l
-lTfI6A6j+4B"Z1c)JrXP3G2ZG3%QRbj'Q&Q(8'mVR,D#Qm'Nlj%'%`G!EI!m%h$p
-H&Pq3!$VS4-9HZ$Cc!2iR4TlVm6k$#SkFRF6kl9RBZpMTR`PZBS#lMp[)`JTCVC*
-Y@Ml#Q8pF$Fc3`Nq&UDMpNr1ANFkU'X!%0d-2#mp(icr&'YmbkcKRJi0h$ph9X%$
-Z#KYdqNmAUIMRh@bI#FA%aAJ5mYaKq3!-*c4+e'fGRVXS#KLKM,bQJq3bPH1'kEB
-BIUG&15+2(,1aG2HNTeB54P&I)AMVa-TVeMAlijJlB'K9&0ekH`k%h,L4LPTk%AJ
-DhIh[KbM56G+1SdNI*hBG00%G""k!2pkJl`+GKhHeJ(d'F+&Lf2Z@XPl*dfrmd+(
-L&a,haf)&61(1DQ8jbZ"B)BAU"HMY(P%fXUY,cMqkm@fS`mX$V)eV5Vm,96M*&bI
-M)[j"H,(ihfXM!q08(2iE8BeD8D94[#@4Z6RilBRr-DJ(4Jak,*-q*laJ1p*08Uc
-@0X"*i`0eH*5S6"""QQTq!&DLC%N*Ua*Qf59Y%`KC@kF`%h6#`j6aMjPa*!6AG,L
-QNBh53IDp#HrD,XeYfKlDAYBFFYTUDr"h6Bi80CHCP!qJ#0hbP!qlrH2R!!r)UlB
-EAPBVm1+JC!!1hI1EX'k[pQH1LGQ!Sj!!Ch-aFA9PF(5K9bY8fJKiZARBeQ32T"1
-9rM1V@88-HK"M(U-PX%!cH&ADA`219S51RBBl5+XU+RejqflC-aBSC`4kaL3mlGp
-ra1EAFNX2q,6VrbfKJR#Gb&3HIEp1Z4"@fi@U@620AT0F*@Z*-pVN`#($hEpMEX[
-hj33X8GF34eqlKq#T0J@)(LD2ZMe1ZQC2"Dl6)AphMLRe589$5,P,&r,r*$Ih3F8
-K03U-PdlD(*ZR(kD0eYp#)+BM0hQSXaRh@@,p+CBRddl)1F9S[*YD5jr@A$#eqi0
-RJD2b,Fb(,R$2YD&fS!A2"SNb-(hN0T%5$$'Ca"(m0cA[iDZ[,R)Z%JPck1k#$8b
-9E,hlarNU(YZ4q[Ql21HY4N@FSI2R`26E)5NjPK(`cm#r#L"+2!qpDeY"&G51B+N
-q+8f,AY(9[P2Ub1@L&f(@5dK4HImVpIjjMS'lJ5TRp*8eJ4pq#5)KPJfD#&TGR9-
-GR#pJ#3TbR)M8-aC6deN-#Z)Z`m"qi&2IFEr$*f8FcVMHR$ck"2hpm(`#3M-lrK`
-V&C11"jp2TDd!TC!%!3!!33!3ZFSKJVR+)B)!!#-2!!#L13!!(1X!%F3)!!lGN3!
-!-)d!N!32!%e[FQ9'D@aPFbjYBh!ZH'eX!!"c`94&@&4$9dP&!3$rN!3!N!U!!*!
-(3X(8LN*8U`-`iJEf8fGVT,&#222S)3ZX`a4"SN6,%hDX%J$p0DcZB+`Q)C9Ae01
-09CZhU+*[TE`@6Gcp#)q,"#TkHAdQ'q`DiI"hGkLXG4'1hXS@[38XI-50(LVj9ml
-6pm,(H1NESEKbBm)Q6c`6bS4kZC8%NGXU@CKDpI%cMQUHG*V'3eH4U2iUjdbZH49
-Y)%aqT8R!qR$AiZUYj"QTPp!HpVKfTN0*'8mhk*-UYUkPl(V+IETGQH)-A[i-Hd-
-Y(qKLIN!pYfKQYHNrMr58#rlZ`$-,@[f[4+QBN!$)bkBL06m2,aIPHhDf$!DGEef
-iV4Sl(ZXC*H$+biT#J&2r30CZcM,L1lH'`bf,#V"NU"NC4)`)ar3"fr)Q0bkNj$m
-5Dq9Gf"#H#hIP%#2eJ0k6Z8#K@$rJJcD51+*X)VibIL&falF80(FA-mQEpmaULIk
-rm+(S[4Y'iK3'5EQMRjq(kfbYD,C333K4AL,ceAE-A5q+`N0B)qM@(PEHH'II8KN
-Jr(Zj9PcB-cC9c3CkA60"IVA`lSfF6`ffQiN`0JkA'-jkZkP`i(b8(2C5VF)L+[j
-`19B2A3G+9AUXkBi"lYGY%)BZ*Si&qPf)lqCSjM%*"8!+G"%S0+Vl*+TTAFdfr#%
-HP1$lRS@Da"41PA8HGJjfIp"hDLl(r'L'QM!fQDapK,am*rkRTb"V'dl36HPNXcr
-ke1J`HX4&V601AJ5+RaB0UqSX$pc)ZK#fIL-iP!Il"D`#HjE6A[a*%L9*6jC*4B3
-Q+(mdh`YS,$cKI8cPMf,1q2'k5Jl&,V0,+$MY3r$51hhH9jb8HF#)%X#5"3N6!Y9
-F@R*XBD3Vb-MD8GbS9Gp$RB,LjHBd42SjYbI[*cTpq!D%l[HYce*He1)daFihE'3
-!ph'XJ195pIj&0[4l%DX@3hEl$'6dck4mm*-SG&JK%NbfrJ`)AL'PBGH1`)6cVCU
-#ViVE0d#6'([lmZqbP3&&-k'qTbSZB)*pRqhVca*)!MdCbr"3&'S4JU&-2Ee8eBH
-l[5+Xp'ck#d2(KPBk#hID@MD-UHIl"+AjYY`b9V3Vi(VFcQCU)&8AK@f5cL2IfP+
-$m3A+fLGT1S1IUYjXq$B!BVN6#QUZbjQF*2SALa[Ri3aU0)5RM')DmrNm'#$AEJ0
-be+9,ZHVJF()N(b31NSZp*(%)JH6e*XcrJdPKD+h"M8)mrVeH8Z%88f1M'DXB)5#
-b[,VUFEcJ3$e9R41Vf99(YmBmH*A@cUl1IjY+!U@A@'aZADfhYhI-ALrdB+TIk52
-!3+22Bd*Vl)qd@c)!j!riGAliMMJE&bBV*r5KE!$-G1i5(q5-58dV3EL,N!!66k)
-+`CThRmLN%+eJYHR"k4,"9JA",Keh`,G#NEDq4R3q5@p!QdfZ0Ncm"9KmNbpDmX+
-T,TKZ2YS54i)e2Q,VkG!H'q"+D"eGY(&dI%"ZK%-k26G6P@$8H!+VGL#0JJm&)M9
-I1B*+V@86mCeTU)k8*"%GmESJl)h#bY+eX#q@GEb!e(KDme)8TepTLCMck2$jr[j
-Q#`bZ5JY%6pkDA%6NL-dYiKJphK9BZ&E2TaXlm+b@kem&UBR6[kVj0cF84'8HQY,
-CfX9Nm59kKhNQd,HPM4[9Cr8blMaAaDGLN!#B`hM3phkJjkQDD!jq8"CLGh!q&TV
-KLb&iF6@m@#i!G&RJGcTKhjRGE4kT*0Uk!IQ+)9hFmfJjk62RTSj['V889-U`R8N
-CE#184B"2V%cH3mFNTm(dMPT)r@'PSrE*0c,,$j+9M!Hb@NU[V+$11D+C2l2HX6L
-@XZrLqf,,&F#0(GrTTcK"+kIVIJ+c3D#cL3f4ZTq(&Tj%6$fN)(#AYjkdG!kcJK[
-I--,MFmZSaF8DU6jaf+Sh-iSB9rYr$'HfMSLZl)Bpe,epHf(&+VIC[!'A50LL+pM
-(Z)BLm"SEpUd,dUic%h%pST[T#1'pNFE$95k9q1-A-cZNi$4h3ILfGeNVG*YipQS
-6(`A(,D9aam'jXqj2lI"SAULE5"d6Q1+aL3T3%NF)p)&SU3bqrACLb3mZbQ6)#ba
-Z`!)!Ur-QbMKqqeN&hd@TSp1QE@@DG8@pliVNU8BE6QV`[H'fl@3r(d8!mG+C'pe
-CJPQ@q(r5@(b5c-4,&q*VIeRKfVa4bNF[XU2H0r,4YM1*)rCMIL(,G3hZ+4BN8M)
-[i(BkPBAjmQ9H2`eL8e-X+f32eJhGA8d*J0fTmq&$+SEHNBl@Kl[[2EFK,cdf(Cl
-dfC3,b1IM`186ijLjbGL6h3BQTbcH9f`K@DX(0qAaaq!GBm#mXUTQ%+[MRp1qp4l
-Qh3l"U1GmQpYI-XrRDbleq)IY+Hr849b#)11VH*!!H,M2CG5E5hTimP99*43VjrV
-fIEKp!(@aJmNI3l&UThFQABqeCQ6h8I0d-aml49S&-0b'N[8kfkM-TB($'mi%A#*
-)IN%VU1j6XC4BSae+56H'$m0jpK%4%rqMl4M*,Y`k##RYR1f"1V15*ae[IM0&ja+
-aa5YUV08'b*mU`C(jDNh(5c-AMkMEM*3,qqh4k,pP24'd8@ZUK'VK0@PiHZ9Bl&N
-GmL0-%MR(,C+eEU`#K@J"Y4h4+KX[`b)[ceFCqE2(5VEj,KMA3eY,pUA#(6Uc5Ia
-f3Jj@D#NkUiJ4KF,eAIfbX%q'eUfFGB&JHqNd@%dkF#$RGePF3r!SHC4S#'V+J#P
-f2dE[@CB6)-%3bVHLc@haU+Qq44Ql41pqerEUTr&RI6cVX9B)jaj-UcAPRXY($,b
-XB(QlY+NDk,"h'2V8-[VAhidb*(Eiie![T2riVm'%lXFiiNP!@T!!(EM3cj,eDj4
-#JRE`6KT+T2*EQS1#S-l('rafDRp*Ni%)Sb-E,S[fk,2)mf"m3GjNXTI)9*BEFkA
-)Uq``D!pI!)m`TR-C2ABr'R,ZBe29ieBYLFPm`d'ck5kMZF'JK9cPN4@3!*RE#p4
-eTkikb$@f3rYbJq%2cGJ6NeA+TF23l&6Lh[5%[$pjaB#(BF-Uq*Xl115Nf'M2eR5
-,i[Hk9b8"[J5F2P)rm-,jTlH(QhEQCdSHAebm,Iq$%B0KL,I$rJJf%R3d$U,%1Af
-PTUQUm)Yb5#l*&Upm*1%Sa&ae*K*YBQ-iVK%$A1V*pSM0pM"8@m#&-9F1X+RH'%L
-(*23bk%5GAj+Q3i%1[#JbG[A(q"F[e3(f*)a!0-SDp6l9bbQ5Lm@k8L`N#1$fVNj
-TeH@'JC),VideU%QGY-d2Z4)$)3JSMr'6rfB),Jrc9e3`kL%+qh#85U'T')U9@Y+
-6ZK*$NIr&!X%fSDp#"`ZJmL,IP*AaDF0@)k2YYP,11q*PIT`eh#d[mQ*a,lIliq2
-c1[2VJ9imUaQi-LKf3F*P%iE`pNfiAdFTd$edQrA68DCr'ET$[$4PT0AH$6+IjKQ
-jJ(S[+85XTe(&Y&6MQF$d#N2*XDFdF8r'*N'Bm`)$ic5V"MEJiSS"3Fl%*Zp*9aS
-6kbe19*pENY6+2hFLNF+GQl(aB8kRi1UIF4fJ`QP$)29*hMHUXb1*LMl(ljh8Q`!
-ZB4#Vdb-Uc+@G0-jKG-!+c&UUUS0rBX+I5p*HSK1,S@BI9E9G64E6B$Rr$MG26pU
-B$E#$Br!p+fV+EjC8kRLHcKT6LAp*,FeUM2%Yi($'4TGSHYb'4k5PJU"48@+XSA1
-Hpb@(fpHABTR`pE%S8,"r9CLm61RMV,3bSD'd5bmPBV"ZDrDVMh$J696[-ac"GJR
-#dmc&F%"ph5lBc[1fLr-CkAG#Qd'NqZjGp,J[+Mk-JXr'fl9L%[dk)+jK`)XY5,j
-eq5&jlNU&UP)LP9MM386+1+j)Al9$-lFHeVjcpb6V8('jcE6YfE,309,RD'3#GDk
-lMiY84jU1!6afUaEGpV9@5bMNpQr@dSiE6Am&"IacGS&9q'+$(SkR`0dP-JP-EJ-
--NAC1a6mKY*4AH,5QimBR#h2ep&2"648re,8NRh&A#2Rm(`Hk(D`1"E[8YNHjKYY
-#Ke*0R$UClk0h0*+Mk8I*3m4MSp`bj'0qjmL81+SS0D,rLpqMGK)+rUSX!@IC)4r
-maj1MCDpe*6$V&2d[KXe&$-f6e,Yr5F2cGr&aH2Y83Nf&9$%e[p$BArNUjd4"p%p
-UcZMI@FYB,S5*3@9'rmh"X5[LA[IdUXh+lTfMlk9CSri*H1Jr0*Tc9"MjSR,S'"Z
--NFcd)U"[H"pF*8&&hjffk4U*F9aC%63ek,A-(jTHr8Mc"jMq#R'$`R&4Y@c9N8C
-F0hlYIHZ9&"D3!'MG5Bf2La%leUR*rI'B("dMq8i&A9V2eL8--9%S`M68L3U6C*'
-!N!$6f5qLc+VXYX%XeZKh!Sd%4NdJTmXeNjGN,dI&%Ip-#2$)l*PL!U0$$EeG(l"
-e+j``(rk@G9G-%k5-$cC+&LH&0qTV+F4-5K2*bhS&mURV"',Hm!4P8hP84VdHfD4
-Hi,5r1MD0(jX+C3Ef@8R"UTk+T"Pf4&3`HGj(UE,5)C*i+!`Ea+P$c@'i%bMVrKU
-XEG$0)+hY#Ye1$-N8k!S2Bq-5%ma#dB!jIr`aAlq,I4N)R8l4ql1Zp4-%T*fcq&@
-KQFjDRMB4U(0"0M'd&1CIkKdAc*&G5b%SqSQf'e1&dQK[%He-49Brr9)'0a`cTjX
-MleUQ44,f,),464lSKBa1H)$TZ[If"[Hr9fhrb,QXMI#-RmUr$8i4,)F5PBF5#E&
-eq!4b$4H-DrGakL$M-q[kaj%#BVX0l9e[Mcf#d83-$BS+6UEBbC!!T-SUXHm'Z1h
-NTVAj1Y!+-dVPBU+D,KV%$5`#@KbNk[aSRiGQ[9jVUUj`iHei+1[5*TH63('JCFJ
-%STGB$mCY8qcqN!$`GcP8fKL9A(QSYiFf0'`rbZ+65ldRjdieH,Q[6DXqj#0FM1V
-LTJ9KmGdPqUeqV[24+JlCLYij[VC9d9a2$,(%Q$8XmS[2TmmA8%D$6XR24Ia$FC1
-YTI+EVS9qb+0)UqS+X5a9"(MC,Ekfk![pe+0!EQ[PkN,K)6EH!!,b3kC(3mh2LXJ
-'aB%%P*+J!$h,,S08B4QapCp)0*S-!fT)i,X%kXr9!3SQ-Q[(DVV8[,hk'K'V%mq
-*f8PLh)j9kP@MNJHF83fB2!*iYiQY%RZMjh1FG,qH8YGH18@2-66@UiELe+Cj!*[
-Z+'-!)IGY&-PXa*+1S))+@cmBU8$6ZF$kmL8TTU)Ek-XHpp-R(G[[dmAcq9FH*Jb
-[J,eTFYKP#CrP83Y'Z%RbrD%ZPX2)(PlCj0+IfID0Z[48eT*XLhfPll[j$IBMEB`
-IBUeT($1MJ$Yh6$9"T'rN"6[XM-Rhk6R5([KafHKeZ1XUcRda-N!J[e+`bF1C@cY
-FK+U[E+%JL04JMFATC%I&e1el`12D`TfSX39i[r,bkBr(D#!@mHb02CTf*2LI6bZ
-IjSp3ZF[iLNID8Pbmh40*[3+K,)Ur&ZGp0%h*L5I,@S'dB*3U$IQA2d@R"HV["Gk
-Pf+aiTpTEe3EIT3KFJ[D!,45A(ZBc$VPPGlX6ppXeJjCV%+c*6jeq0SB%YdGmX!k
-bLVf8CeIBY'f,llmNh"8dfZ%c451`F5q&Y@H'AI#,'@B9cQ5R%h-pCX'CbD(&bY0
-ia%08ACcL-#2Ni-F2haYBG-bV8BCTj4R0&#N'hcTG(,j%qlkIp"%hhQ"')0`+L&d
-i9-4hF+Erb*36D16XqT@J5qa!2KM9!D-`$5Bf!M"5JDUNY$@8fa&pV"iTC,N2'9N
-'kr5J9Z8H1r"A,[eBIX+e`mXp@R@)CTUlQRRbYQ[XB[5KaM!c%JV92F0)qE5dkE8
-8cc&*q8aUY''A0AMV'P11R@)K29-Y6UF86$L2!M(3rea`Vm!)80&(fRkIYURGRr5
-V$f0*YDf)`4GY@a4rNF3p'mBG$Rb3!)jUB*,+UH[#jDAeAGbPbPq`UZmHVNIk`1!
-CYp8e+E!(0iZ)8)P0[k2&#F5ie(r(rA9E1-)`R#A&KCq[&Fm'Lq-SMSC9i5#8NV!
-caSP525UV9(K4G`G@dIh,%r@J[cdSNURE@Ep"#(BmIDAfkA""C2rKpH3"'ELYrIG
-(HGpdfl2%943GVYVCK%[D@F`jLU"M66+f1#er%Dr&kiX1Y6U`ZM$RUSEJRD21@Mi
-28mI#[8fqhqje"!4QYTM8diF5q2Sfa[-J%+$aR2pjGBf9rCX[d!kD&I3XP`hR*Pb
-r[YI!bjqhSJVDXAM&YrFCCG!U-@-AUhB5dd(!i'TkZ[Z$fQDGrVl[Mq2[EDXhUK9
-SiY3f+rJj`3SGik8p3+3QiX*5%8@mm0Z4&Ah-AhB1AGiL*R9(q,M[L@q`%Bk2&U5
-3!&,!kp[5f0E9P[eVT!*H5Y-[iAThK6CSQ@eP@GN$*!Ge!c$4@aKQp*e3#jiNB3H
-amj!!VEEJ*"6"!3,%25V9c)dirm@R3MrRIKfZ$q#YRL%YC&dk'G50PB"0RBPMDT[
-A3Yd,I9E"96a*YIX[U9"GBKKhIRRZLq-(8C0`PeSPN!!fHU)FNDXSAk'heYVp"Ke
-RCC0jVmPpc+*aH#26+$@NbK,EJhhAPM6+%8KSTD1i@2DZf[AAF3[5*cXac"ACD16
-#)GV'GrUU0HJH6iNrXUY9[S@Y!q$*qi4-+$(6")f'LRjNbMC,(0U6')V4$QfF`qR
-+H%+$F!QBClJ!E'N-4(M#c#'%Zqe,44$Dib&@[A1@V&,ZFC(ZAN1J)6,JdkHmZi!
-5HKZQAF15A$S2h%T[aImHqQ3SSApDlK[mj)DGpbD0Y$+M)4[,%KbKC*5Ekd#%A6V
-46S9ec%"Jc*)qUK%RA#CD0!$9[JPC6@f9)i"-%23JFKm"$`RklK2r"4cBL02k$jP
-B#U#2jC'lIjiY"4B1#lHl'R'dVr'LelBUVcXkp!2pm@qEpI#@l#DBqh3a2'0!p,D
--9Bl)kURAdU($E3Te"dbiS$@p`UU-j"!cDU5ScmFXVF@1C`10d'RSN!"1%[Ui3-G
-cSaIGUK2cI6'F4-'f&Q4Me@5JdAbZ5YZ[[p9c4'm-1Z*H43+2L8ETLVl40jkIiGM
-6pMe#2(AC*Ci"'66KB+Xq(DQLk31$GCVci$V2Uj3`)15e,TX%F`$4Rl4"$,R$D"&
-Vf8iIi0MHD-A!(L9Ip`ecTL*lNQ3jIl0EDlCeUP5U*9AQ-ke6d+DlY80*Zi1YXbS
-Yq$FJaL8SkE*4*$-aBEr''Xp#@D&&4+k9KH1A2IGkUDjBU3X*pXZ,i0hB0)8X"h)
-NU-Ii&FB6NRD%-C8fPH8H66ZS,5'ZpRe1)+VXh$K![9Bhfj2BM9KcVPDfU#'A@Pq
-d*m46f%[[YP1&DKMj`C'B%MYbK8!6N!#Z)jdH'Ih6MYE5!,YcT-&qX@qrCXQ!JT2
-,-`(&cVlih-"b5TiP3`i4V,,4%VUrZ-ZdTK+B!,(Jr63RZaZp&%'jNZShb5+01eU
-PKAKqf(FkF)HLSIbeN!!r69i@[*e9-d"3MJYIXM5``a6fDV#Dd%m#"qFCIaU-r9A
-NUhIZiY8B3B$KB248F1dC31UHDT+(-,b9,c!C,!bErS8hk@PpcF`ESVpkpDfAk[$
-mAPF)!QpB+LkkS&T&+rR`X3aa`mM5&Ym,8`(PC,2q1QhSI!ZU0!A4IaGX&SMleMq
-aY8K2A9H3!"ZTh*USGrdI6lB(f)0f!mQV3ehMXqjYCX+NS5,p4CV+VQ4')"VepdG
-J4UFpLPDEja2&SjMEZGdcSIXiHX&FPqQ3!05#Mirq68%IEZCHBXGR#KeD"UhJ$'3
-@"D6f-iCZbq-&4AJ9Y-NYb458"KJ02*h+LmFc,I9%@aQ"bKiQ'3'3!2M6#,a+K0#
-aFE'fLeh#E''LA0!PbMNV&rrFPPXfbARKXSc#"abGX(be"D(NE0Ir-+,%8"Khe'P
--#`2EAcV@abTaq$)NHi8U(#61GKQ%0"&IcYIXIRBj"Z[(%Hk[`Gmrh9YH3Y26TNc
-cPb`)H+CSGN"d9rR&)ik,m,pUH%4055@e%C('J#l1$$JPYR[GZifC'H(9[m"[ca@
-I(dkF&p%8-c11Y-eMGT&@fbVeeK$5CU@rG@Qi6ilQBIhDUUTXVp5Bpd,rqXb"VMd
-fkd"(+(RASPBVK52TPEmDTDfZHYk&-Kc5ekY"P[RmEa*CPpc1e%drT9YhLjXK4Pi
-5f[YhP(YDf5rdmZ'[h[8JXEAL`3PV%+*LEd3Zbl#CN!#JqM85jl+H[UHCrK`4GZC
-#f![,pKML!)&HEcKjdXj@P#4F4(Tl+[Klj!aL'dE"C'#VDHUqr$I8fjC2)IJ[F1J
-T@N+@#bAIAaBHrK&JE9`F1pTMFEf2TUiFL5rA2hS-1[@dDc'&22*M+H4j2,,&1fZ
-eD,#1LYGUcG*BXS[4pZKQD`3I91aDAh2@$lQ%*EilVZ@mY!)+qqAPN!$lDPc&3Q2
-0q%lMT+HJSA%j)J4j5XFLXMe[e#)09h3G,mHb`Cp&FBar*erY-Z85!ae'-!AeS5*
-A$Q-[ATA(8NHJpbdi5!E+8!HBT+bX6D@,M6[)0dMI0d@YCdN#BJU%TXY(qfZcQU+
-JJcZ,*EERedM`Qd`e*qprR*&S6RH#eFmCJ(&Z%K)U88Z[B[Ad2!4pSrqB(kh4Zp5
-UcMT'K([MVJPP*`Xf#0blAl%Ckf3p[J'm9R`D$d(i-eaRCTcQG$fRk&l&L!Zh#+T
-E**!!9mri2GSpP2XXQRH5`Mbe#!+IU"Y,,FZN#2cX`)iL-J0pB5qYahQIXjXl4P!
-6Y&dpZ*!!GEDKZXPe+1*GXVGNr5l$GR@eDCG*Ek1Gakk-FL,[BeZd4ZrHGikJ#TC
-aEC!!2ANZI$5KVprVJ!11eS$dl@Fl`5CA&XK5,1lddZ(!)k#0Sa-J-GqeEPXL"Z%
-4IUZU3ECJI(K-)KjJZfkl%A3#d98dV0DP&'-L$VSGZcp(Eqr6lTUfL'Ze$fJfF28
-XX!U3!!(Ffi2U,MIQldHGTD-r$Xq0JQ[)0`a*1X2%ZUjVCGjUjmDAqbp1$DTM!B*
-"J4TH)GPUC*0%,qqfTlpfb%$"X4DiUKZ5C#$hZ4jp!2BpeiaS0H,,P5)X5pa(pJd
-#pJhkJ,p%fK)!cRcM5c3Kk-U51ZM#3$L48j,e-'L00kCcEDk@imXTr*lD@BQdJql
-5LYNV!M%3'fMfp&0b@1JfUPHKek2@cPKNcb081h$2Ql0J@+!X#(h8U`[,L%%b@AH
-3!(+*#UjC4#@A,"5KI"&@RJhASk5G"IC38"e4b)M6!L[d,&2qdD$lGe@#p&+$eXI
-0Gl&$6DS)li)3-pC2)k4Zk8pS8QEP`Lr)'cl6fYY6Y0D2&i@lmRA@)cdN)m&ea*p
-pYe*$R`li"35+HZ#-Y`2GS`6`jlVepQE'56-`U6Q%AFf3!,"r,mcSNj+ZJa-C@,S
-R%+LeZTID!!jCck%d,qPM4[IB2Xd)!!P1pbEPl1LG4,+$,$dG`aBB5l4LCYdl6aP
-4$kUZD5cVR3aU+AT-0b2(j3ZXime9Q"5EN[lCmL'B4TrHV(-qp(("UpX4D+3e&-@
-X,@E#Q#kVMZ[!VF&608SX49G$hA929fE01*DJ`L5$JMqIF&bU`A!rVrh6f[#!19A
-V',Pc&R)ScQ#5p**IK[dcpfP8pD&#a(HiBP,2ULVhX!l82ILZ*8N!hSV([h"#bP6
-,p6U$(FUdNSF@Nla5$C51PBS&KU1fm8"0PmKRXQN!LZ2[X(LBr3ji926jRFS!9MM
-H@*JE6+'5&d"3Nm2FTc&`fe2AC,fer)iE-,&QM!f'dTLqP)r&E`aCGMG#iAT[449
-3!C0ic1$NeaX'm,0fd4BC5A4X(YLKS$0VST6HJ%1L6(&lHY#0Xc0QZPj"h6J&qPU
-RfYRlLUi4mdI)2Lam5R`*5`d&eZ,2A4&b#&H)6h,pe#NAb3h`FP0QGr68)jBY*['
-BY5CH,1d3-&43$bF*l6qXYIk8lFIR268F-FNHXlhGPfRjRLi3JJ4T-+LQFUVCq)r
-kCM%SN5(frf*0ja35[jdQY`[3Yka6D,@Q4-jQlrQSS@1h`jkM+0MXpf-jT,KYk&E
-ZKKD2Q'XL[Lj"J)3#KXp-Sm58SKKeVAqYYCKIVJ`@k-DBFHQCbC(LR(D8B4-S10P
-ZUBGVeSRdpQP(bS&c,i`PZ8#dN!#-pHJjh$%%2mY,@YkR9Y-(ZJ-qRLCUBSiQTYK
-dTU'qU6bhQe))!4N!%I1GZXd59P0hV6MmT#8(#)Ar*H1QZf#NhiT'GR[b'4#lNqa
-GM(9aFAY+-)'I'[Xd(45RJdPXr6dDcl,%iL"6iNrdP11[E)[SCX9qDjQUbhDP!21
-6''ARYLB'`m8@pS16C4U(GX5F&XHG$I'rBeXUNdD-U34[4rG!+*PkXLN@pTSFYfG
-%,Y$U663K8,FD$9+8*NZYNT!!@JbT,L8`'N,@cKG"6AV'PDdI+Y()aj`"(-R6(,*
-3SSMJ4q'4Y@P@HhqdFl9qr!+MaP3QDTU*,+cdQHpYqU"0CK1fXh-K@V-G4HZ!-TP
-VFJY%k3i$+)(5lahdj'j,`0Xqie5fGVa4mL96BYY'83HZ+lF6+J@83pZdfNC@&L,
-qCReXZUL(kPNpQp4(T,`1YjD%AEV[qmF@c%Iki4%N!$BhcEJ3DJUfXiqDaqQEiE@
-a'CSDM`NqB[2)P`XaPLSbhXQcM-ldEe#lNqrrJA$VY"!e%lj2Uj'4X!&I(',M8e(
-ddDK1MjfX!la,362Gkl)YS3Yf&@C5[)U4ELbI*[YpLBSPN!"RiU%@dL6lP1A6QYQ
-,-KS"rq2,LhYG1[(qfJNrlCU(`KmEbQ814FlcZ%La1J&-0j3CdfBNkU8()+2YhAb
-R1hN5D*a%Y!p"#3EU@XI$fXAXI+jB'[PI[la[01Gh-Yai`)mYeeA!1f&cA0I""Gm
-[8G4-TD@KPJMYM1K$R8EZ(K0eDPTlb6kSNc&h0kZq%hTcK0YJe4VM1*PmYLbk4SR
-ZDF,fTB+#J*490kIbjk!p3-6QhAkqld)V0@+BCAJjrBR5,(e*VNV"`4R0VCZr06[
-+4"*L-$m6rI6qfjT!A1Hpl5%Fre8FmLMF,%+)6#68DNIl6Z5bNPkh1eB&8E59%@[
-!mX,earh,8PMiV15Fl+j&"f3-e8')fSpTdJ)$3MG$KU5Nejd6D6ELk&@3!!XQ6)Z
-l'a`m),m,QG(HZASf6[,"#FKbJ-`S"B`+dT[2CheVMCH48lr`fK)mpENGTR3(1Xj
-afJ&TPCr"Q*M%*jI1'G9$"S'8(KKjm"h(V0D6V)%QEK'5jM2VEF53!+1a*U-`(c)
-SDB%55mVpYC)pS[U+#0M9SllQZ`,6jVjQ4G$"(SDh!b&SGI&LJVB4$4$NZe,Fl8$
-bT%-f(UX9%F++BX$2D#Sa8j[IQfK(d*m2$!0pZ3PLala,"$-NhEBleeE131M[bT2
-BG)XS%A(-93l0,,*&qYeQ*mBiSpHHBS`VQd8kBhC`f2Nf9m3BIbN4FA*m%S`GpI(
-6bUk)b4[$eFP+Ep*SmU99%B"Z!,pZQCiJJ2ldmaqCSP8A$P(dV1!GI$6bCi4"i#1
-F'500+[6K*ld)`Nm)pD)4%EN'Vl5Jf9F%mePaL@#aeVC#Pm3TJb+B%SddiU`kFm2
-9`bMM)kDV(0J3TY@1(UfH%31rcC+'"*RXYTQ@jY*M4bcYYq6c-A1ZY$*@PBFjC*A
-`M6`HXLbD#eNH6DAl@GUDdU"QrFFm54eS(cBK21kGr9`&rAQ@Ga@"[leQ,(Sc%rD
-i4pfieILNpLi(Hc!q6@eSIDZCe9KdJjqZV#ImdF(f0RbIi@+LpaT@%DF%42J)UXJ
-2*$AEKfbii#iCphljbQ-f&0irIBSiY9Tf&$JHrpdU5'RY8&HfbcAcNV6Q3Ff!i$)
-MQMfkJlSDK2le+Dlp1[+fEEH$N`Qrl*!!!YFV98Hh%HUbm"1!'aA[,'3IP,&GEdS
-9B1'GeRjG"IrcFY45qAMaEV&rBBd6d+mJ3YC09[$[eG&JkXQe`Lm1e9+%3@(ZIRQ
-*b`Yac)4-cqJqj[9MXK)jDkXi$QD4Z`Qrbk85BeYm4kCZCD6)JP"qNh2YHK"jaSE
-dbkV1kVB[MQ&Ibh9`A5I&D'%8(r%H#iT%kfF10j,T)6fjHlrI[dIa*B3$2$ZfNhK
-&J32R'!p`HSc-,cJS+Z64(56MD+m*Hj!!*[#3!1d$(M"Zj1INFeP)*0M5T"`mTEJ
-`LXFje)qT@V(6#X0(aHTj%)#Kc`qjVl0hqr!e(pfRE9q*9X6eTjm4)!QR-c!1TD'
-Ea"MXJK4L12GPbrf9GRikF"c*ai6+Ff0Vbi)Rbd"J$N(e90XFTRa(ULB((ad'd`k
-c05KVi3%[H[6@4fq*hrji0V1)!AhVZkDJKjAAQ95*&chk$fAP-fm1`)6Pp,jV'fT
-2+42#Jjja[f[PDJN5+'faAPd)Ih''pGLAa-)eCMVM-&D$&QESm5FlqpG4`Nf@NqY
-Yi4@,$[#ZJZ[-(%-hqj%Rk#IjV#aKTF,qXE8!$52j1kPV-RY"%r3chBBhk1jA[lZ
-HTV'U`18C-"Q&l8$5,BYrE-GqCP9@0Hec6l!-iL%0Fq)-hemM%'cR$,"Q`D$-IQX
-Q+QI0!E#C2[&P@Lq2c1LPF2P*mH"bapVq[Rf"ZSGaMje`4@NDJqCR"A@&!j93XM%
-G8&&[Fal,'EGP+aq'[L)!C!KJSSD6)5#e,k$4[CA5ZT8C3UXGPYR2,0bb+@)-Fek
-bS6"MA$I,lS"$!'[[XKiHNf26d5Qa[chVl"GV``jEri,$#)9+4SKCZYBe+A-cIMN
--f!@9G(L4Fiq*XlrAVQ%#)[TIVc&DbXYkRB"QlZh5T%6C@"imQ)p-!'G8(1(MM'A
-Lh'h--LVId'$")ak6qKj@!d(LP'VE%H(mb2%'NL,C(HAbBPT19(9,"c&-KK3Xif#
-#HV433AiTX**ATr3Jb'dA&PDI1-MD@H@C$4KCI2TZb2LMQdFlf&rC+jh-c(qqEj,
-+[FrQ@k&%Uh%8(J6p*PemR+Pb$EHB*MdSm*TIrhLVNBEc$UP&q&4(Pl5c'PF*ViH
-,*Zik15rU-IA3dZ-KJJ-VbNCIm+@DL5jQ3i*$Y,jHZ&NRZ'![fTF6",*0lmVG++S
-5liEC['['l`0V$cS+e3`8ApB9T),S9C5HdLp$Uj5CV$adlBhQFXL0j[Kc4Fb#)8S
-3Ld$X&YK)@(QJqdrPB!FqdCC((ldl%R!SmpbP%MdheQ$NN!#MFN[e#AD4R,1+M,Y
-2cYf6p4cQ*6@dCFrLE#MIQmX![lRZ0%H&5A0["[1`YXSMD3$0YhSSYd$q`$FG+@,
-e5qX'$RlR"HDl5DkpDjK8[*1A4AZM(0,kPr6Qm-*e,b&@XK,DPK[U0RS)V"YLRfR
-E,lpS&[fHlS#EM)6'E-QBNcC&H)IeKYQKTRFc*@2#UiH%04#jlZID`MTpfPXmc'8
-F`F`Re[r(UCXZ$2IEBq!3*%RPc)pTBikCkM4qUqQGK-[5aMiBS!+i+8,BXj!!3N+
-1mR#khp8EkZS&)X"XFYpGU5(rBdj`MYI#1!Yqaq@425fdDk1&XjLRhH)U83Y@4Pa
-,2'q0hRMeJBq8XFZ9EZ%2Vjj0dSDS3bmDbKb+J#QXZjMi@%mk-h!1(iFlCX2PdVV
-8V26QEH'`Z&0aiq'*UB4TNaGDeIM[m%Rp'5J$A[l+@)QrJK[&I5X48,la@jU(*Lc
-Q[[KR4SLG+!F@`1VG&6GB8Ne'IZTa(Vr`qPap-l3KDT@Y,eDC)XA`2a#("`3p'5`
-1%eL!lqcmPD'pi[32S0MF4(LkC*flMpQY1dl8!aZj%P&mU38GNci4JpQpi#&U429
-#@bK0,#VT4I'J-S@,0!)EQY(L(-ZG9@-M'IG5hB8AJ#m*q299q-)UA)+@ReAG,V#
-H3$&9(pAh[KdLAN,5T&Qbr@kefifi&`C'ec&8Q`fl,(b!k'T[D3&X1r33iQ,X"cX
-,SDV5iAXSX!1DT29ZP3H6dNU8X$GEUC%ckS+1%02Gl1pR+@hJVJYYY6H@,YRKHS[
-p&iCkZT[S@kpU4hTCjY"1TH,d`89EJ8FF#a1+lk'A89'*Ye%[c6Sbq1j4ReH#Kf4
-YT!#i0%[,2CELC-YNqLcX*2NSr*)djkc$6%Z`%9)45`P`SaYbQ$aTDr@F9@6V$B2
-rZDlQjXDJ(Lie1ELQ!0jjTBi`M!YV9R#[F`24qp4ref#3!#q'fD"iKE9%qU[r4Ki
-%YH$e2Y&Mdqeb("Q%+GY5"GG!6*SkD8Rj(ieae#[k&Rf`ZC`LDpMdcrA@h2,+A48
-dN!$i3Z&H1&$jhh4!aD$KKYJRq%64EdQ3!,afZ*l,8hL@Xq&-DQKBL&S4`c,MGUQ
-SJ0i-((4d84iMN!"1,VSR56K"38Sl@&ql[MX!l)+Y-4Zf266aD40%m54fFm204rN
-eB0f-Rj&2h2RprB119R3fGEK`T06+KfMGQVQMF#BMC`+K-kU'%'HZ%HSX-p![f,(
-+#44B1deM(MUmCcKl2rJ,SD1@A11THN)%B9Lb*eZ&3NRL3ZmpLD[!q!&5-5jPV&$
-KkQSX(3J,YGSqlUakAD+r4b[A+P3,HF)*"!4SS[fU2+d!'k8Z,9"[KhPmajRCMU(
-#CB`,(`I!ZaF0fABe`q(9)[KmPZPA!KcNF,,`e,XkXl1I%94)8b8adYGSj'G8NAl
-0mrfFR[#kF@R#VCH6Rrc(S+KC3kT,NZ-*-hqIEq+aC+1$jHJJRZ9KQ0Q*ZijkJL8
-[e(',q48E0b&Kl9$S"#ffVPDc#8iA[rQ,VVDmUD*j`2TKkXmIMFJ9pM$0Kk,KmeZ
-6V[*XqCrJ-d"LfRreJTTd,q8aP,6aUEXrfik5FkFabH,V3[1Y2bqVee0bRR$X6FQ
-JjAm`'5fkFYXb,eXl`M[&@"Xea*q8Xr+M"95!TS)$bU(VKNIV3&lP3Eh$)l1@$El
-Zf*!!2-HZMBM'S,&ZKXDC4d%NDlq514aLkB'+VB*fa`1#8X&(rq!Z,i,12AkICMZ
-N"'iebXDFp[*K(SaBmm4EMPL[&4pjB2&Ne89TXB"kd4Urrq[l+k*$2#bJ2J0MRQ9
-Q"E,UC[HQ3B)*1*NfAb8)$qrSX([%X@'@%I5qA-09DY"K"$$F+*!!eK`IK!@1aU0
-!bGJ+iGNVqS6%U#%dbj%Y'GFSHlK[8DT[dQM!8pk1+1Ze0e-AA-%3LQIkHqZ!a#!
-5ImSmFVcc0EKQNH)aq21(d%@$6-IAfbkq-ql3j+8#N9CK'j!!K,(&"r(1,areGCr
-SCG0'TE[h)PCH9%aS+'G'E)cpQDqHQECUi0X2[Y)'@R@CXp!@0,kNdqc1TJ92b,V
-24@pPdVU"2KAB(mf-fhN(aiNVlpGAUiTP1qZQ-HNl$0,+Xl$Il#-l*Aim%,kLAK3
-rdF39Ap%ECM(R-G[LRTER[HEaeGfMUQc!-AaQCmcHRdQDfJ%$jfYr-R"hI1Xlr!L
-68@[CefhVc,CZji-,YQ8B*KbURdmTahT%pXaYU2(hd"Erf26KFmVM$Qi+d%5U@R@
-rQC&a%pJjk[*`a5cef##L@cT'B6XP5i82HJB,I)A6pE%RDV3ll&1RamXX+dZqj+)
-TGa)Na,P![+JSKGA$kqR[JAFQmXD3!)LjT2UM@l$rTS8['EB53`43&1AN#mbR4Tb
-NNb(3S'$CG2jVV+CAH2r1,KS8VjNmp1*l"V0UaKC8%00IQ+U,4+'*(pcqceXp@&L
-jY1Z,ZSD3!$8jMr5ZPT1$88C*pp0"3Upl![I,ji,"N[3LckFEQK#UA3PpKViiHq1
-@)e$CKc+Z0NiIKLRMDiDZ&NZ2*8U3!$P@+9V#`aMFSS*cR2P'`LQJ&S+FQIF&D4[
-6eHUX&b%-GdehT(MiG'A[qdM2rK$cA0@3!))E5"RfI'%8r4H9bd892eV4AZPc54m
-Qc@95CFF*fS54L,eRFdGfV%ZMP[@VS$8M1BM1eAHM-@m!+N4I&6Y(dNV0-+cCIH-
-rb,c#6UcNZ(q!BL6Q!e#RMaK&m!&h(-#KI1"6aQf+H6JDCk'EN!!a-+34@GF94J1
-i0V8)hBrblG1ZKc+N96m61GUB41V*jYkKDXabce2FI+@SB`&G-0[8Z!rKDCJ,A)N
-QM",MFN$10C65aFX!6()BcUp2V0*YS&Hq4r&b90C)-Q-#+j)!GbYhJNeek[3e0DB
-V3*c1N9M'3LB(SX&f@A)"Y%1GkBmP'Z4`IX1K$IS465VIDQ)l1$2I,HBJB)4AAZ8
-'aa-S*@$!`N%@f0*0[#"Ej4,-DA$H"TH3!-AA4b$qQZcr0E!iIPRIa('f3ML6hfl
-elEj#8kmMGBAcD"U,263qfSk`!c%JDpTA"mmql9[cB%C@N!#Xi9I6jFYfHi(Ak+X
-@SU"aL+(hh,2rK3+J3BXQRkS@e3ZRY85USU@5VN54BhS'l[G+HK)6hTQr5N,Ah`6
-Z+c+V9rkUldBj!+"K1ZTB1Vk`"q%mh2dq6')6YmRl[rEN4-R-21+T8-+FQr0hCbU
-Jq)@j!4pIf++P`Y0[CLGR3ddNE'e#NeFkMNUF28cm(I`'BDbaeS%M5M"*(ElhJdr
-LTl)Tl26@@p$H5&rPEplHQM[2QK`KHFi`U2E)b0EC#"YEJ$b(+T%Dbb[EirYl@Y0
-0&6@3!%'%-A2edf54)`FB'0i#cJFE4ClkqRC#Qq$5N!0H5XPY2d5%UpakDf`p%(e
-VSKX9+qT69rr)[8Ak80bVS#c4UG8NCZ4F)8rE3a15!BH[qZh+6miFI3Em-H#14-p
-PfE)ZSTImah$6Dk+R`9#b13*ZldGjYje'dUd%30h4`a*Z1UdPI+C`J4V(&-"64H4
-rBKR6hEQQm8PS*bIeTbTGEf@+`#6!i&GhA1P4B8&&R$ri[,VN&h2#I&FB-l&+",+
-a&B#PN!3"!!!q!!#f'm*aZFBeSJ!!F8F!!+3Z!!!Fk`!1,I!!N!j0Eh*P4QPXCA-
-ZFR0bB`!"MfT58e*$4'peC`%!rj!%!*!+J!#3#3(&!!!"K3#3"!m!3X(8XV*A0IP
-,Jh@K8-dE%&f2l-$qV2QP!a%bb$pIf3Gj6mN,IN85ifB[0GI2a'CF*GrLi6B6MEl
-FZANkMYamSJMNejRUdYqM`Y)%BiJk,L)lF)*KT)2Rh"C+,3XHF#GB,QY$Z01Q!-A
-kV&DFZlm*9VS*0i1H*aR`-A63,CSapI+l!KMmX(`Ef`fmHJkL&&UB)!kR5HGKaeT
-b8UpR`UkidP&B#-XqMK9d)a86`hIEe1*G@#ZfG&H1ar!iG$5''ApLcrP(B3LdEEB
-H4qm'VkeHCpD+LjNe*#PH1hSCINTfS`Y&IV**iM%#q`DL*9p2''9N16BhX$H91eq
-KmPl"l28H5L4X$e"(N`k@fep("haf-c`S`*0qK4"2@"9%P3CMPD0lq@a#rqq90Ua
-S5eCFCCVT4X9(UPHZkYM**%TTb(amR2@bX"f'11+kYq@6eDQ@LirVQ`&GbHN$ab(
-m`JdCEIk8066pqhKhmjj!M6cF%@h!LLCe#N$b'[")X%"!b%r(X*mCD1#+BJ#PN!3
-"!!"(!"#eC)cZYddAq3!!SMN!!+AA!!!Fk`!A'Ni!N!13!!#3!hB!N!32!%e[FQ9
-'D@aPFd0KFQ*[EP"bC@CTH#jS!!%pD94&@&4$9dP&!3$rN!3!N!U!!*!*!CS!N!1
-k!*!%$`"#`G89'GalIN(V$qaIh*Z,&+VR"ZQ3!+8L3d[pK4B&%*1Q1`qd3h9d(hQ
-iq@)bL9G(hSf[hmV%PR&hDmj$$[SX#h0c85CTmBAH3-QqkZ%)Ub3`pq"A@$ZAGKU
-d62I2[mUp$$1YZbf4idTPHR,c,B@K+(+Qjm4&N!",LKb5hr&mlkDLQVZ-&'J"Z@E
-"6BU'Sl`TX&1c@6MCd-'E`FQh@AiUEr"`%l-5iaqfj8bX#+TpIXhm*69V'JlVfEI
-#`%,"e*PXVMAQ-B1-8kp&c8(eVTG&RV6#*Qf*b!Z&mr'+P6NqE"'6qN%&Gr)BKmZ
-Bm2Z,&k&#pBZA)pYeKi%pGDqCK93Mjb0T%@+(Y"IrhTA40bJR#8R0lAc`Gm[e6h)
-QT)*cYP3b)5,Z,eJ`ci,MhIXi!`P1&'#PN!3"!!!`!%!!N!UN,J#3"KcV!!"Mf2q
-3"!#3#U@3"!%!!%%!3,BJ!5Li)pl@!!!Fk`!!X6i!!!)P!"&#[3!!TQ`!!"-e!!!
-+dJ!(8R9ZG'PYC5"-D@*bBA*TCA-!!1hD!,J!6!'E!I%"`2q3"!-HrrMrm-Y%!!#
-!!*!(TC!%!3!!4J!!Yr1jUVR+)8`!!+B(!!#S!J!!TJF!&QN8!*!16@pbC8CTE'9
-c3eFZ3f&bBQpZ,N4-6!!"QMacD'aL2j!%J3$rN!3!N!U!!*!*!Y-!!!%H!*!%$`"
-#`G5+G3CkX1hNA6&qT0!`-Xp`C0)-Y),CVLhPJk$Nm[$&f+c@%Ja5JcABj$)161E
-3hTY$V-!dI,QAm%B-8P"q#aR8MTq8B$efc2``Mejq%aL$LA[2p94VY6)#f`UbYN3
-bH1MF)$lMN9h$"""C(9`$Jj,K3RT"&MXbU&!263hq2Q5Ae)5ll@92l3-BhmTe4Sk
-3!"RB%$SmE%aLMLETQMCU@1h!qY9AhRe&dmp'A64S((N@S3D4rXaC!lDi%Q@Ajf3
-q)B(C&9GMMlfcafb+G+QZGG,#d'ZPDK"XCRATZ&JrEjGXiHPd"(ZciM)f2rr#1X4
-N2rf!Gm3R6`*riUJI&E0c@kd)`U[0[YaTXcElTaT1aJI3AdG&(lhS[)d4ZFILm+@
-3"!%!!%B!!,IcZDUjbL&,!!#QE!!!UCN!!+B(!"Cq5`#3$Ne[FQ9'D@aPFd0A,N0
-'66BiDbj%6%`!!9SXFfKXBMq3")%!rj!%!*!+J!#3#3,6!!!"(`#3"!m!3X(8LR8
-'HV$Yj&daIU63-$,2F'65$,5#fDiYjB1Jj2,`aGLXeK)-8S-ef13b$NcQd0kE3kc
-!0(bjPk[k[&*3IJXCe)kL[$0N`L![!SF@A05"D0IHAT@qclLj!jpFb!%`KfXM`Yc
-aC&A211k`)&fQ5MMLmXV$2F4H,p)DZdjJ"NFd[UP[f[kQq!dAZ`Eqpb)"&K'+9ZT
-4EN@E6Hj#%(Ue+f2Sb[pikfP0K,6DD%%3DY)DP3&!k!JbR1pih"@r8LV"l6d`KYV
-m)E`2raUY&Cm4!fraIK`FR2bhhSX4!Yiq&SF1RM5-rcG@-qHpHYhY'd4QAd$(hcP
-1la"`MV8m-P'ckHT8eC@0,BaX,aD80M)6'c+d(0V*GZF@%5Ck6**((!#PN!3"!!"
-$!!#hmlQUZFSK5`!!U!)!!+XV!!#Q"`!6SlF!N!j0Eh*P4QPXCA0$9bj38%-Z4%a
--!!(fB(0SE')rN!5"!2q3"!#3#S!!N!N#cJ!!!4d!N!32!%,"e)Te"RSaAb4G-Ak
-Ncb*JMh"Nb`4@JYQZ,H@$S16bm-ABUihe2@RaQZab'3FQFfK[ANS4'H#cZJrP+GZ
-aEd!)3T3#j5i8b0-IPqSJ0@0B3Rqe(LHZA'c9+TeKG1c$3aFGKBJaK-j!Gd2%GlS
-Z*fak@XQk%T,"9fM-!mMZcQ*V$P1c3B%*Jb[%bdTk4j($eaC#HeeBeCI1Cp&FjEA
--*Q42U5d%P#GY"dIIEM)$9kLD[,%SGKU4D*Ajq054A'!q'+PLPH#!)[$pJ#,*01r
-aA0D2ML!UrQ8D4fMFDPP2Fpd"UNRlF"Q@%6A*NRe'Dc6bNHY(H4D'e@epMdilfPM
-j+q$qrF`HK,Ph`KN%fF,HjReI&[T,K2[jq"3LqX6UB+@3"!%!!%!!!,Id-B1hp$'
-$!!#TQ3!!V+%!!+B(!"!@K!#3$Ne66#"$,N0'66Bi5bj%6%`!!4hGFfKXBQ0QE@H
-!!2q3"!#3#S!!N!N#V3!!!33!N!32!%,"e-LrjC2Z&PX(i`b,J"3hd&qQJ[d-FT,
-Dkq+,q"GJ[TpJ`fHQ1UZQfe9[0!0!6ZmmG4aBjhlbN!"P415aUR'1bdHSQiLkm2R
-`4`[2NfRcMJK41+42)qp8BiJB2!,pBK*%I'l3B66LHIVRZ3dk)Y)EQmKXE)piU(m
-q+-m5AD5!cDAki@"fa`k2GPPkZSjii3NSaXfbpI!B,K!,fK&%S",(f#SmKcLX+Pb
-)MA8963iS4iXa@SDrS&9`R!LY5H&-jE8TVdIlP'Rh(Nh$BjQ*89QN$Rk!1"m859K
-rf%jed29A1T&6"8YrL"EkcHqI1Tr0L`Kd5V*&H30q24+CacJR@G-"6X&a3+@3"!%
-!!%B!!,Id-B1hp$'$!!#V+`!!VKm!!+B(!"Cri3#3$Ne66#"09e*eER4TE@9-D@*
-$4Ndf1%X!!5frFfKXBQ0QE@H!!2q3"!#3#S!!N!N#Z3!!!3B!N!32!%,"e-LrjC5
-)DNX(iYmYf+0[PjAkjL6!m`m+ai+,q"GJ[U+4&[VjbjA6EDUhQ"N#RGjfLl4Th4(
-Nh8YjE&L)Y$0k3`84kdCCQ3Gj`ebT#qrckhR*8S`c)*'MmHBJQ!GM@L"AT,YH(@(
-[1dZf8YCA%U5q+3YhKD))a55GUALHr`"PQJC01F&kK!"+)0#AjSU8bqEBNX3$r+0
-KDBHS6V#b)DDmIkp9KFFL++aQ18@,`k4$f'-A&SN2&3LVJMaP3D*S-R0abMJRUB9
-(rSNE"KRHG2US#P"#D8BKQA(9Z83NmQLf+TIIcTqAL5F"UiR@X96p6cY+qE$4XS9
-hf*-bIr#"0aK@)E(Q'!#PN!3"!!"#!!#hp$'$Yr3aJ`!!V+%!!+qB!!#Q"`!5Zhd
-!N!j09ep08d`Z3f&bBQpZ,P0SE')!!8fQFfKXBQ0QE@H!!2q3"!#3#S!!N!N#X3!
-!!38!N!32!%,"e-LrjC3KKkX(bB6DA#1E*eNdrZJ*YGed+"e"kZf#-G%K0&K1-)(
-PPJCj*)-M,j[LImi4Hj)j0C9iQ940G3RU0ql'@"ea+Q+$`L(6l0H&&AJ!jHDY[3-
-39dQ15IDi+BA2*l$@H(rqD3BCl53'0TkcV6CLR$jIbfP`9V(iLb[M[pG#[V`c95q
-aqf8c4H@4`KreqT6GGQrM%e8N$[Bkrh(i@GNTFRlNf%l66%r(J&`VJ6A*AFp-'2A
-K@LD-i1JV(YiQd)j+X3+kXdMPHMY""Em$-@k#82+B#3cl#5KmqAG[A[+EN!!rV68
-rXQ*r(Fm(Q-CaVV206kkcVCM`-2-"Ir%LY8'aC3#PN!3"!!!r!!#hp$'$Yr3aJ`!
-!VKm!!,%1!!#Q"`!2&`S!N!j09ep08d`Z8&"$,P0SE')!!DRAFfKXBQ0QE@H!!2q
-3"!#3#S!!N!N#UJ!!!38!N!32!%,"e-LrjC1kT3X(j`@J,T0[Pj@@KZH$aKeBIA!
-ATHb'B@f95#&-cb)"5`VeSQrr4B#`JcH5mNJA#jp%FQJB3U*eQ'jH@Yj@)D1UllP
-*2R6+HE$@IGhX&Bb`%+5-%pMY0!peiF$ACKr6J&58a*GXbqlQKc!&d&1,Z%im4T%
-J9Qia'6+IJXXUSX3Aj$"8@&Gj5dR3'I@l(JYiK8jq&b*E*+bK5iDT4YqB@UpBKN4
-JJbJ)3*1dXb"[p'G'i2Q"hIM8AD5`4LZYMc8,$hQP)1Gc`#4KK,Mr0U*U05E5$3m
-4Uc&bc)"aS92N5q36FTlL(Pl'8`%AH[9!N!#c2UD,mZr$#0P"NjbVL!#PN!3"!!!
-`!%!!N!U[Q!#3"UB(!!$N8rq3"!#3#U@3"!%!!$X!%,M8$'Die!dH!!#Q"`!!Yq-
-!!!)P!!XXK`!!&EX!!!A0!*!%$`"658p9@#j`BA4MD!!"-+K849K83eG*43%!rj!
-%!*!+J!#3#3'D!*!$D`#3"!m!3X(8LR5S%[ccd)#%E942VNJ1jkhchrY9S&b[J"m
-Yqq8p3G`(#3J-3,Zp,A2NfMkSZk"EQH)$'2QJ5ZdMJ5Ec4B20(GCiT&L6GIGRhH*
-XVd[rmKFkNY@0he'#M8%)k#(bM(f`rd6hS6BhfY"#`G51HMXG3eUAqXGfi3iMXM@
-8eClMCPHb&-XD4Nc$QS%0Y[@BSEIik,HA,@0`"i8*42fbP@IhLVr0BmIdX(B5XYF
-l#id@$!D$cJ[#X8&5H'V8($*$%h43VlCXNFFe+M9eNm%lAdd[RIPYh%#ele3k1"h
-KQU@lTa)1ErN'm+*i1HP*i4AJY%[&hehZU1H,BYKF%THF8k'`l#2)h,G4%[Ha@E$
-UA"ThEMJ(9kpP24c8TH0Q4Mc*KSe*)j-h05FJmZ#-0@1HV5mE&2S)0!X0&cN0(PK
-9*V)AV,3"ierDU)!"fM+SIT!!qXZLNZ"l!+hYAePmD3K#IDC-NTZ[5@bV@j'b5hr
-5-GX(Xb1GR8a+[c%#SZ-YQEf%`XXTj$[Le9Uik[l4d#2E0AC+0Iq54N1e3KB!I,H
-,((55#bH,f$-6cXV'BmVK`*+0*-e90#$Pqh",6ilFSd`#rDjA3[KQJNmRYF@dI$5
-c@SBl'U@L&a2)Z)qQm3U,"VrATpc9rXM66X`lK3JqFrb*+'Ki'lXC+@BMp4kU-f8
-)(1%UdKPKR#2fNS+%LS[2pdBIm!RLE'DS0RdHH"Y5JMkK5rAbrphdi`qb-+#h#Ja
-)N!"ee!X)'@r&%JE&B-5kqGb,0iiR%rS6qI`&Z,i)HQ`(`#+aAReBDebq2K)J0,2
-pQ)lQa*K4iRHeGUi5db-cB`6Y@89IU@&XCT@4*rPPARm[D!cB-[*I()l*Q*LmN9S
-N1NqGd[A@YSGrf3kA*+jV&%rh1G`&Y,&[iEXl2A-E!iVVb4q#K8h)RBL-`2cr,c5
-Xq1&Ab'h6+`&Z*lI13!VcmG!)RbVl#&P%%BU(lIX)MIJArEHZU5kcHd&YrkA3[58
-1LEHm[PBpRULIUbfF!IXqAkej@Naf6EII!9p+k-dXdrA(U'pGRNGXPG8SFcZ2h1)
-f#H*VB`1me*-Gj4!B4Q[31S$2FbE@jKNb+K)j5LB2!40cp$[N2q3UFRkV1F[0+RS
-brG)2iG*6kJm(Tp2d44GraTY-3V[LbqhH*!"M)ZaC8#!)@3KB40+&q#E$q[CG`kQ
-c89i3rMmQl-IkRcpPFCKBaV2*CqeUdELr`GYK`YCVCbZr1#@1U(P'FK4llIXab(G
-VNGm[FEF9%m3Z@)aQYX6*LLaUIkY8a`N+!'$rl&(R*-brB2Jrd-8ArF`RERRE$Gc
-%4q5C3EVYEHE8YKqFaaX[YY5C("PlpUcP8'AYe4j2SM(R[9M%fC@V86,GMU[SH#p
-BRKf)khSP%,cijHR+6(2i-4qJa)%EF3mrLK'$)idBAkTc@E%E2j2YUqA[*cCX4iI
-'Xmm6-6%UKX(L*B%rS[U0`'NDZ"2AEkGj"2Gf3&l+FGa3aNBLm*!!TJ,6"@ImG9+
-3!2J6Fl)8$8N2U'eam'55(L@6S$R91)N,1r`3d'lK#c6,bh,k%+plCZT(b$`6@V$
-b3"kj)%@al)h`9j1*![#R-AI$`d#m5c@LZiQd4UADejTPEb#QfB[,%(d%lAjDrFK
-JANppLZ65Ar01IhJl!bBdGp!386r2(TKCAX8Vf&R,E%"'LlI`@I!%`p#eCAY%N!"
-LMf#S35Y1EbKT%2Yb!cp3FM(a`F5#B3eiF-rRI%jh'1%NjH8I-YUJ*+$VeXbE*6Q
-H#!#C1EK!Jd-*kq#EIrXB+*Q-fIh*fAj&r"kcm"baZmM6'9G0I@iCL%rC8lG0"@'
-",-iSla#KXImU30V@m0TpA',K6N3SV+d3DSFV4`P8!5I-J'b!1h*$"D5((A*mr8f
-YleiT0f0el"#9ZA3"UI*ap#aePl0"4KD6fkr,@p*b8#-V3rL[2'`8,G8-laiiA#B
-,JXX#JC!!%q8K@Ce8DZRbe@-T5GPqmEr6$-+C[relb$!L43E)[H$meVXS90(hVZ@
-V9$Jq#,KmVQK@'Ip-)MpC-9%"CrH$DlKHN!$6ESDr5r$G$cIM39*2*3+1+P'HP5C
-NGF%MHkSb$Z6&5q!"M")5ClSmUN&G(D#!r"BajI(Zp6%!TC!%!3!!-!"!!*!+X6i
-!N!B#*3!!#2crN!3!N!UPN!3"!!!e!%#d(A&SYr3`M3!!!L8!!31k!!!"a!!&,[3
-!!,KX!!-CmJ!!5di!"%*eD@aN!!!*aJ!f!%-#h!)h!F!!`!#"!`lrq2r`bd3!!)!
-!N!HPN!3"!!!i!%#f#%[MZFSec`!!Z"-!!00J!!#i%`!)"6m!!,M)!!""2!!!'TJ
-!"#K$BA*LEfiT!!"M8J")!'N#13)V!F$rN!3$([rirr$,3!!!J!#3"k@3"!%!!%-
-!3,BAYX'f*KNU!!#iE!!![F%!!,KX!"-8LJ!!Z5m!!!KL!!!%NJ!$+&0eF("[FR3
-J6'PLFQ&bD@9c+3!!q4!!6`"@!N%#!!(!rj!%!`lrq2r`bd!!!)!!N!HPN!3"!!!
-e!!#f&lE"YKHf`3!!Z-J!!,S@!!#ib!!&ZHB!N!j*BfpZ$3!"Cl&TBfpZ68&$8d%
-!XH#ai!#3#S!!N!N"jJ#3!i!!N!32!%,"e+,![f6NI0d+dKR3"qIiU-$mII[XG$0
-D@+,$Gdk#0&52j1BCd8`Pl-5%8846FB@%fUNDlE0"XR'&YHPV%Qe*S9GE030`N!"
-9-EUe*eM,IfAF5aFcd8"fAEjE2@A6LDZ%e@q`2"QrMeVLhUC'(,QV6$&P5EMc!&Q
-$[bmmBRbN!+@3"!%!!%B!!,BJ(CQjbL(a!!#j,`!!Zl8!!,M)!"B*P!#3$Ne[FQ9
-'D@aPFd0A,N0KFQ*[ELj%6%`!!@!4FfKXBMq3")!!rj!%!*!+J!#3#3,A!!!"*`#
-3"!m!3X(8LR8'Hl!,C&f,MQ63-$,2F'6J(A!E2(HBZP!Z3A-#KPR[CJ[Ca1BYbL4
-i%Yi$"h'S+"'bfa4AB0-MMiSCbdji48+92Ab$mSGdNbDkEH0GC[CZ)@ALljKQU@6
-YI2)Dla9Rb2dUTL1*5QXZZbM2KedAi'`E'V#B,HF&TBc$R2pL%GlEir6mKV$`iLl
-8FrK1K5kc8dEe-pd5)`NFJ))5#"RjUa9DXT%&1Fh"`UcB%,"L10F-EK`2kbl+S$K
-@JZ"a#Zr6p%+JHTefeVaciLFfPNEq+iEQhqYQ0p4JK*U0UPIfeLk%`1l#3%*`3b@
-T[68M036UE&hJFYl0P'D!!)(k4bR)k(`ieD&XGPjcFMLbk)!,!h'e3D@[qRIqNke
-mh`"G@l4)bhFS!+@3"!%!!%)!!,BJ(CQjbMCK!!#k&J!![C%!!,M)!"+3!!3!N!j
-09ep08d`Z3f&bBQpZ,P0SE')!!ELQFfKXBQ0QE@H!!2q3"!#3#S!!N!N$T3!!!@J
-!N!32!%,"e2)G%@H4F2*ZM6J6+"A*-mSq$0rFT@0kSZ5fT@bjKE"[*,3#KXJCL&q
-JaZilrjP`pE!HT&0GYF`H8jJ,k[a+k%m8(*2eBXBZ361I5F,mbTGi*C%iY+qD#j!
-!TMDQ`8%c6QHQ$R#rBf-TdPmd%R+b-#FUrrFqPrDDSZbJFYQA!*P&R,f$&QfA%m#
-%T[BhfY5N6kk4MFPpIIFiaP++YMIPD8AN(RaPCmRE*L"`*"T$DGGUc,&&H2(T*-+
-+IdML!Mb@+DS9+8ckm,RI)pE4(0,lE03@e8d2EPpF!Y*fkI$&[lbiB%U')eb[+eY
-1TZi*pIX@L`#BS"Na-8C"k5d6cQjfc,A*M[@)Z,Yi(XBl#LM#PAam3!0P*A8f5km
-AdNdb3r%5LGV`dNX+Y[66A,#lNfE(FQRRYq2ZRF'3!jXl0CRG62rM+l@H'k&3%)N
-FJZ*6JUab'PICEI(8)I2(bL$X6Zb`[N'%*e@BR!#PN!3"!!!`!%!!N!UlY3#3"VM
-)!!!GYrq3"!#3#U@3"!%!!$8!!,B)5q1f#%[M!!#ib!!![[8!!,KX!!@K$`#3$NP
-MEfi0!!&M,'PMEfj0380633#ai,(J!*!+J!#3#3(Q!*!$c3#3"!m!3X(9'K`iM&U
-E%LIfj)N+[0G%EAlahS2&B5A#&XUH%QdSf'9hQeZlG#I2kL!Iki0r$S0)X-QR&0k
-9F[DTpQTcaUf0F!35MGf#UhF3R3@4mRG[TcBB1!X"D%6!X%&HfV3KHQbXNq(p#[r
-,b,QfcE2%a[kChdEa`DF8qkP+e5F"ddFYGVQMQ*l5XYdCZ!R5LmH*C%Rk6K@9T@I
-&01G()&IrqI&KQE[k,aqEc)S)ie8'I8KITKjDlMU-3DliH)P+NKaL(&04'T)614F
-`ah"$!+@3"!%!!%X!3,BJ&cbf*KNV!!#p`3!!c"F!!,KX!"ZLjJ!![f3!!#*(!!!
--X`!%F(0PG@4[3f&bBQpZ8h9`F'pbG#"6Eh9bBf9c!!#eEJ#h!IB#U31J!F$rN!3
-$$[rirr$,3!!!J!#3"k@3"!%!!$8!!,BJ&cbf)"Fm!!#qp3!!`%S!!,le!!AYV3#
-3$NPMEfi0!!&S[QPMEfj0380633#ai,(J!*!+J!#3#3(Q!*!$I`#3"!m!3X(8SX#
-rC14mh3V5'G!(k#"aKEJECJ2jrL!jjSaSP+STm92c)@lSl4Ma1DGj!L!eABiE@")
-!-Y6UV9&YDidDkIkQ1jKArl-dm1l163PSX%lTrLF5MTkjDa8@l9Hhbq"S8k@0X9R
-Y*r'I80eU8%bH6T[GC&"dc@-0FQp%JYM+!+@3"!%!!%8!%,B(cVkf@Q8[!!#rC!!
-!b!J!!,le!"ALN3!!'9`!!!DJ!*!%$`"`Ff9eC'p$BA*LEfj6GA"`Eh*d,Q-!!6b
-N9%9B9%0A588"!2q3"!#3#S!!N!N"QJ#3!kF!N!32!%,"e*cHM&S+,A4SLT'PBQA
-GG`3BJP[K918&ZFGFaLYZf511'f&fP[PSB!&IEqlZ'cm9c[Y4N!!YYZ+Ee%qr@Xf
-P$fAc9q[N)amN)8jmC'BA@'MicCrQa8ak*3id-`JGB'(3ZGk'mqUB4FXZak,Z0qK
-X#KPDemKHH0+X4P[%8IL!+F*amf&6!-E@-c5-3(Ub+(k1h`04`MMC-dc2+'h`VRB
-8HFL824c3!%,"e)E(S'`jYFjSHiCA3cbU*2)QIaDjjl*b`SI(X8pcbR0GXa(STV1
-P3iGi*BPJMc2aZHKlLGQJiGrTpYVEGRYD"&+1(-C','APL2B(RE(kAPM#Cb+@e4N
-B)k"3X,a1)l(23cYSp[,eA5D#b[5B%%5S#5e#%KB-q%SZJ#QEXXE)`9NTrXcq4$b
-6!IdIf6'83&EGC)hkA@Vma5JSeIVYrBKR$hqQ'bam(L9ZT*b8Z)hTqLM9%8!Z@23
-#)Kpi+lLF04*RA!re15KQ%m%cAqRhXU!@M1&UhBrdqlEeG*E3&qq*C4-X`l4mTdA
-Rp1Q4C9(Qh9[rG"alX+2eTZaS%8djVh)LHldCR[CdpQNMLAcR8Y-2GaS9hjh-6d2
-,(b6P4)f8US,5!N(,EE'RLke@lGMq!1!#3ZdHp+'#G%L9!8E26i-#)5blddDMRS+
-JA,@KY5mmJYLC*46i--Y`S2JH2,S%CT`+12baCdmd#aM,Ik6!frTLLI9+"L,KqLQ
-3!*,)D%#&`"G%+,p(40Rkp06IGQ'9QAe$`URTBGJ*UTT4BNFi!hi+459MUajHGMY
-rbf"FV)#3!%@k`@R64S6&f9iEh[!GH+kZ![LZ*fB'4Aa@Cm3%U8#"a!*LpJmNHYQ
-pir!Zi6A)!XaXdaFe[ZGc)fJ&TE`8K1X*RR+&h`5IS3rU%rq6T2%N)Y2b4J(0j`-
-9RQah`jS!Yq[Ap*(beqjI$2K!TEEe3MbeeKYVjAr4[#b$TK18cpJk)-Sf+BNP[1*
-`K[0p9Z0462pZrS,5lm-k1$m!aqi9ZZa9q+qEeL4r$Nf2C`1F"KT`b,8AppfMFEq
-"02@M3'9(Q!CQhT)-C[5(rikHrST@EJQG-2YHM@4qV%*N!ZNld#8Rjb9)pmA*,0*
-)qe"eH#F@lfla&KCK-%TU($YZ`UP[$prDiF9-aHkb@XG'rHKN3j!!KVqlAhR1#k,
-3EY`MLFCFq8@r!!-aEA6`'D*-'YHD6Q9)S"kE0U,BGaIp"T5%U5F3pR%i,8,(cfi
-pT@I5bXNPHQeNKd5XAkd5%EaCadcaEp(EhlC#VcP`@6%Ii&ChDYch+4bI6%55iX4
-Q$VGMa1'mN55QKX9[LmDhBQEjY&(Jip#PphU(dA'&phf)6eA9L(IPjdDl[%V+F2Q
-SLlq9,D@C92i4cNYVapNMS%p"@G,AV[ChcmqETmEIiqiR0hZm5"jIp`HH`&0rC6c
-iiE+H6jkq8`FL'R'`Tm'H,@19KLaEcii)8,m!d)bSPRja"65%a[(+6GRPK+Q0%$R
-Api(+#%0eTmFbpGe#CN2[#XPcGQ(hC3TUZJGErch!qmA&)bI6T(-p2*&B"9p9j3S
-'HeI0e)DjU$iQdC%JU2iGGlNN5"D"Zh50f3GrHkq0@KbG3Nb5Q4rh(K8)fX!4*NC
-UeHDKkVfYq51NGMXQrQ9C(+dZP6"&VY#HIcPEf3aN,LG90YHRklI(hNma3"TiP"P
-LMZ@k"(Z-GJjLEj!!#j,flljC"iEaqpJ'CJ%ae#K[NMkEZi!4%`K$5-Z,-JeATc8
-RC!j0&'1$Frk()fUYjr)fJVia)iDQ#iVT1PL$jPfAQ'CP@bj9bZhIk`P'XK9j-H9
-jcj(BjBqb%GHYA+baJf%bp&+0$80#TSpVHM3&C!9"JhqqA'219Qbc"(T(RTDdfQS
-NAb[((*REeSmmipmdNK%2l#DH"@(Gp#V--AV+)JbV[8%)1XGTi5mh)3faK(&iC[)
-AeEVfdYaFZ,k,4mMNKLXYYUT["GXHQaR"U9k`!qb[cq1IUDI+B[E1kpCXDYekYrJ
-jJjci&al`m59f+[+2,IUTjbCR1k$[@2%('FH6BYD2i[*DfBJ#cN%"K@MZj,3N)fC
-%&XbYYcjf$-T`%dZhJYMP-LE94UdDeac&k6%)@-G#l'8f`-8!UVccG#!Id"TE&6%
-H&!9AQr8Jfh,RLG$XB$MG`9829V)#b1ES#%Q`ic#IKNeiVrplArIIT!d+ZHf`cKK
-5)NIIeXLmL5!NpE*E-Dd#R1pD9+!YADp'9@BjSGpC'd!15A8MBa[1l0K-iMHlkM-
-Y++DK&N"$3"qfMa2!F"#K21#+d0+!%p,0djYN9eiUjjFhBGeDDdl@8e32K[kVFB8
-`mTQ1XR)rXd6FlCHf'K`VGF%-H5Bl[AiD0pk(YaLRVb93D-!9#&pmiYB5HmX@AYb
-@Sl1bMmlGR6mU,R%[0iaM!UU0SPa@K55@GI'N6',k$,lmq,PeC!iX%KGrhe5Qh#)
-`&4*SUAj&``-)Zif#0$FqZJCI,f39+kb,3e+!TC!%!3!!4`!3YJJ$[lB)@cd!!-"
-+!!$+#3!![[8!&fNm!!!"F3#3!r)!N!32!("cCA9NEd0KFQ*[EP0eF("[FR3ZCAK
-`!!(rK&4&@&4$9dP&!3$rN!3!N!U!!*!*!CS!N!1@!*!%$`"#`G64NCm8$IbF5eT
-hS,X-IFf+rhi(p%6HSN%T&bZl-rmSVH$lZc32+p3Ul#)ZrYP6l[5U2#DlVSMlMDT
-N5Upec&X)S-9H14!p'@(qKfGA*9rE$Pb,'p4a81%k[@)22eY)N!$X%H$[Yd(!Id)
-hPNfY9a89,4R$cjm30[QeCI$8NPAbJG)HVS$i+MVVfD+j+Z39jhBhCDL!3X(8b6L
-j'REmq*T")-`TD`MT*B*@Y0k$Ck6MY&%'&JAY2k98-X)r-KB#2Vq`BB&[Xrp3AKA
-0ACeY+-pEI[C"9che)T8S)cKmBmI,EKEfl'bHTbdc525Fq)HdTQP!khjHkj4mR2%
-1,VjK2E52R3mSR[IE+4V88D0e-"TjE%ql1Sd22ab3!)j!Yh1S%,HD2"F30$'#(Hl
-E$95CNNBri,ZM%Ck#GD9&NQG(YY$N@B,'(,eDpZd3Fc$2GcDcIBBDUAQ8lXCX006
-P3i@Mcc)0Xp'2&MAMSD81m)+EUYk$Pp"!p1DV8q9Vi@!f4P4Kbf#4m,'dD`f!TC!
-%!3!!53!3YJK0V,B)BTX!!-J)!!$,j`!![[8!'GbA!*!$aJ#3!id!N!32!("cCA9
-NEd0KFQ*[EP0eF("[FR48CA0d,Q-!!6[&9%9B9%0A588"!2q3"!#3#S!!N!N"QJ#
-3!pB!N!32!%,"e++rrjhVBX8"%VHjeXH3!(JDmHMI,e$k$8mJ4[LGU"l@+'1j#Zp
-2H1!X!X4XHRP36CeP@c'0[`d[MiIUc$(Y)rB5f4dijG9'4M-+Z62[06$SD@f9$G0
-J#KN2rD%ci3[K%d3J1ep!NCm!`cXRTqZ@`'eRc"(&+R"X"&NrT6b`ree'mFqZ`fe
-m1HPhHMXYC4@UCHCC"SV6iUeF*#T9DK@&q!hiT5LeiHYB4c22+R+k4fP"+YQSiVa
-Zm4H4+beqBS!S3D)B5B1q#L$,6,a,-PcCddIDdBqS3X(8aP!C'YG0Km99"Y#,k!5
-9*3iPac#Z24b4iIk#q'#*aLcJVkJM180"RX-F$i#0l+0Rj11"@Aj+Cd`bkd#U!!G
-%c6jTeG+K!05#U$QMZdQJ$[K!ch4Z$0@0lprdP3Z2EC1+MR2NFGZ$q5$8JFb%GV#
-H2+AJ"Yk*-98D33d0T`9p1"AY96U'q083M2C!TC!%!3!!-!"!!*!+bJN!N!Dqp3!
-!!@lrN!3!N!UPN!3"!!")!!#h6DV+Ydfr23!![[8!!0-`!!#iE!!BUhF!!!l+!!!
-&i3#3"!m!F(0PG@4[3f&bBQpZ8h9`F'pbG#jcD'aL!!(I@A0SE')rN!3"!2q3"!#
-3#S!!N!N&i`#3!li!N!32!%,"e*Al%##fEPM[BIN4+#qd,!G*CAUdi`f%8-)rP!Z
-Ep(k3!"UP1p(0VkUUVT!!(@15E"lr"C)5B%Rfl#!pYCY2%RRf`,Ida+aH2*k&FBd
-lS`6rp"+6U6A0IJfL9jE'ZMZ8ak0Kr(`MXbY4"'ZE'SqMq%I&XKk-(0bS[(9L0Ar
-ElPR`*3E1S%dA-ifdb"K+8e0cJ[E0mES8"NZ,bUJ'd*CQ[e#B-r)41l3AMb2De%b
-m6DDJ)Q!L#4fGi$HTNd8-`%,"e4r5SrS*-X4([KP!1bFF$FLe2cBjBC3#`&F2DT[
-`K$VU%r4)S"IHDC*@,JcNf"!q-d`T`#[!pBUR&P)A%#kdej'idfe%NZ"jXGm!C%(
-![EmTePKh1`FAH6MR5+Q`H3"JcNNRU%JBX&m%k'[k(SU4,-qf&24N)cUE+UpYJSC
-P&PV59"cbq!qkY''6@EL3!-Ql2hl(JNqYKjQeH'eh4,i,KF#01(l6KN8ZPCp"qH,
--r&0&e*rf9BS*0'S@6cYi2!!c#eqc4K0!6FPRXkDE'+dHjH631IGrFTQMIdlYGU[
-&Vh*@Fe["Dfr0(B(!*VdYV`%RmCEl'`%CkIh(UFCm2)lIU8ehSlK["[%!&$[-MH(
-(Mp(&Dm@&ecG9'6V$If(F$,q*XPhE'ZXX#Jrmp8*f%b@'c,C!@NlDamTma)ajc%"
-K6aqVTL(!*'&2GT!!"Tmb$pe9eUIMci%3pAFd'k*6GQC"l6ERQddJJ-G&8TTb4M,
-IAScIV-a4dfNG!V@2ICR)AUTKaUfMc@dC0TNPR3Ef,YC9NHNAH#ALh-d&EmAV)A,
-jNFh")[M[6b2Zl2K'ePEZrQ5Yk'STN6NS@MDHl!V!@P)Mf'l&5Q@6j+6M-&"lD'K
-T[lCDcM*h3GeTB%r22YpZ4X+Uk[IC!3&&q"V@$laTl3"8IVfJm$%Sjlp@GJpA9"@
-QQFM4rPXlP@Tcf"9FGPLQdR"ZfM%2mNk'99m,[U(ckMRNlVC#+MSEBQL'5riZj!j
-`reZT%MjZP)0Z4,VM@$01Fk'qP'(YeJ5ZTVCQrY`U06!`aT!!H&`XqMLk$NK8pL6
-A"4$Ijr1e6C!!BjQ$-E$hih#D6plU*BJjB9kMAlpId`c5M'p*HC-93qjGD)aJ+SK
-[5!6`KY)fj8ffd!L-51[-VSV1mSI(RX0518-TXHDlBF%KN!$!Rpm'QE0L929Q(Y1
-D&HYrkbP5%9mA02V'p4UiI"&Rd4+CSqY2QTa836Kk[XAK)MPB)`NMVb1f!JIbKUf
-2MXhG3e4KE5K&Ea5$E*a@P&A5B+`rjpD8)e1Ejj4LDL@65+F'jM*NH1bPS#H1aE8
-QDV!2Tcj!pfQP#PV3MEAmKlEplNP9Z+BHENCNRUj%JmPlp`GiANDqEk*3+JGjY9#
-h*Ye)JmIVXIRZF[m!)&b3!)f5e()ZXqR'8$90jU9p2#X(#c4[F+V91`Vbp,K)ZXk
-MfThP1F[(GHGJ#`IK-cVXAGZ#aEa,q1[AP#QQkCY#9YN$,T!!HU1R@T'd5D@p6@p
-3YQ32r!I'$*I2`f6XJ%-JQhk!8EGjSfekmiX'SDiZHcR-mC&["HadNPY["dZ'5-E
-hC#0k)m8QU@a`-pl2KZf'bECdhj!!63UCfY1cllhZXa`dfMT,R$j+N!#KjK+"6&i
-8laVM2&r$(1jb2`dH'(cUQC*BADNFU6Y0F5mCA'G+qI@#1'bZ0)NK)2aHq`C-P&0
-4P@mFPKBSAlZ4"JKi8'R-R6C@-f#p+NcP$c'!U)NXeER%VeEESV'D#d&eakEDU-5
--qm4N'86P&+F("TA13F`*2Dp-EJed-QK*52C*#Va%Xi),E''I+Arp8TMrDKUE9S0
-'kI$RHICEV"'Db,S6Lj6KTCL*pVUF2LEZ"IlQKMLCHImSM1iE+XZkZM0cGkqhb9U
-M)DKE(#VNY$X*8J%QUREC2`f5Rq`d!dAKBTHUTci`Nq!-(qL!C0m8@C48a0$!0S3
-Kd%VmlljZ$E5%rjHRCT!!b[ia3[60I["$N!!ZeKV91-FpGd[e4M%j+(TjNA*NU2)
-rrbVraQFJPUk)&IRdeR4*E2294lCp68q4#0B25d-U)D,e12qerNT1RrMepiAUq$0
-33*fE@cR%"#pE!ZA%`iVdhpqBF$&j"0"EJC!!1!N[QrkP&Mm8F,'Vmd$&DXb8SD(
-@@Xj2mF1)AJbF*'(d1jD58N!2l`LGmN(fT1('*[bfK8"*L"Z1HIFi+S)MHiSU*R8
-VX4GU8S,E#9&pk#JI`RCCAkXK$1Vi1,)JaX1NT5c5lh#VS6JIEN&!QL&%,``!TC!
-%!3!!-!"!!*!+c"F!N!DiE!!!%G[rN!3!N!UPN!3"!!"$!%#f&i+MY`Y51J!!Z'`
-!!0fp!!#i%`!6a8)!!02(!!!4T`!!#IB!"LK6GA"`Eh*d)%aTBR*KFQPPFbN!!&f
-0!,F",J+T!YJ"`2q3"!-HrrMrm-Y%!!#!!*!(TC!%!3!!03!!YKH#SlBAJU-!!00
-J!!$9#3!!df!!"GM,!*!15@0[EJd!!D*ED@0[ENe"3e0"!,(JXH!!N!U!!*!*!HB
-!N!2E!*!%$`"#`G56kGAZ`HYlHG!LV4m!frPBR2QHBhj!4Bri+(X,#ZMR4&*VXRk
-UJ2CF84B$f[$`jeE&C(!CPPM06$CM"2QiPiL#!4612e-a%Ip2YG$!,!l#+MY0TYD
-+1A4VLliK,m`9H5dYeAUNfjE1JeU!1fcIY2iTqMle`m&L,`,Sk#cA2cLpLVKCp!E
-J0[*I%SQ)IYLR64S'"eVk[,Qq0J'kaI5'ZHA22R5Q@r[Zr1GC'1$,'QD$SELMES)
-Jmf6d*$A5G*PedZ!4QXX'd2M*kUE6rbfiVMXJ[c)jlhqE"!#PN!3"!!"'!!#f)"f
--ZFSKi3!!dmF!!0DU!!$6B!!@)G-!N!j0Eh*P4QPXCA0$9bj$4Ndf1'XZ4%a-!!'
-JrR0SE')rN!5!!2q3"!#3#S!!N!N#e`!!!5N!N!32!%,"e)Te"RZ`#f4GLijNd$!
-bch"Ni"e`'cahQ,T3,N&c!SCClfB,fF6Q,FSNH",H!`FrCbJ4Y398@hj'aN$0p6T
-2ZHd*PCfr%RPrj0MLr[QJ2B)RN6M!i`36+jRf2KZQdS(Erm[BlQacqa5Qjd3hL8`
-6JK1bP'H1XAI%UDZQDI'p%&E[Dka-TBm2PT6KDf1T9*HcX!$p6hPbQU44'`Mc[kk
-X9NNc4-*J`,Nc,5hHFTHl&&Z6PaQ#'ff-eRrLb13G2U&S#j%(hI-0QqD,Nl-KmfN
-)5i!9a8!NY+d9+cQZiMAqU[r"5DN4+R2F"hYPkZ)J8,Cd)`9$BP&JH+6%q*3#bUl
-GpQcVfVp9fA1-J,-UPF-&DDdprikSSSi(kZE2KC@[B833j(#+V!*-!+@3"!%!!%-
-!!,BJ(BfjbL(T!!$9#3!!f%3!!00J!"0%'!#3$Ne[FQ9'D@aPFd0A,P"33bj%6%`
-!!@`MFfKXBMq3")!!rj!%!*!+J!#3#3,5!!!"*3#3"!m!3X(8LR8'Hc"mT&f,MQ6
-2)Q#2F'6C&4)E2(HBZP!Z3A-#KPTEU*dlUR-@j4)m#@m"JjqcP!h#RDr391PEXjk
--Fcdrq1+C[ClBHhTNSL8ce&KS)l+L3G+a6q(X)%hj-P&q(LDUMA90,Aa*HAQ9RbC
-@'`V4j9Q1SfTAC)CQ5RSr1'Y-f&-ZK5@kLRM3`HCKfVJha*mJNNEUiD6If-P-m,e
-'T(MIGhG8aE(h!`fRN3CYPKZkXrFD2UPYR@MIJ14*2N)6'(4mrK,`Fkb&dq86e12
-N8dbp-&8FmMJ%fI3d%%PEU,mZ$D#I6"0)!,3TL2c2l-ZNFlPfH+"(*GQG"iq@02G
-(&UI4+cpGN!"+&SX$pFX2TRB&6(P([AFA"4+bIDM0FNCqHHBF0083TC!%!3!!3!!
-!YL!GMER+0Q%!!0DU!!$D(3!!df!!%-B&!*!1690-)%-Z3dC00MK,,N4-6!!"L%a
-cD'aLBfCYCi!!rj!%!*!+J!#3#31K!!!"C`#3"!m!3X(8mKd4CehrSQk01"-S&FM
-UB29A1Abr!31UHSKpUM"i9L5kKlVB'*(NJUGP*"KIjC2i`4(G9HE$SC2&+TVE2D9
-D"(*#l2k9,V@DdIc)kMk!XcAIfdj&#Pc@PG3hpkmr$E5iKVl+05F"D`d!(picSpD
-hAM3!NI$i1C!!#MJ8PMIl[R%DmSF+!ZK@f+[FCbkAhi+9jMQ@TdU3!,&8f4NTq-)
-1kj!!fHG[eSf0QG$kdb,@YkASG(dErZKA#iYpL$08FJFFUbk%-,FfGQ,NA@Dj&&E
-0hLBVCe6YGqadpSA5$KpN-cr8NRU3!1"6B+,T4mG)jTUm(D5l2q@*RdiS9$iQ)d2
-+BKdJp"MMr$TbF6j$#0(SkZP[j4Rmd!@JSfeN!IG(eL%mfDlbeCm`%0+lcYLGpP&
-4DC*0#"$#Di,@+L&!l,-&'q(p(&XC8A90ad5&)@)2'RbBdFj-4k&#5-+6,LBb'r6
-YhYN&JMdBM5(!TC!%!3!!4J!!YL!GMER+0Q)!!0K%!!$ErJ!!df!!&S#I!*!1690
--)%eA8R9ZG'PYC8aTBN0'66Bi5`!"'*acD'aLBfCYCi!!rj!%!*!+J!#3#31Y!!!
-"D3#3"!m!3X(8mKd4CrK6NQk01"-S&FMR#VK"@Abr!31UV%pGUM"i9L5kKlVB'*(
-NJUGP%IH+DUH5Y6*S1TG$5fi3A)-XG-$e2aaCKDK[dU-0F,fp6!rZ86rBLZH)8b8
-`-ZiA6`S04K%$HUkT#6kbId(iY*CQf9I!8,6@LBR@D'K1FG&#`DEi@J,VCP5pX[%
-hUj,9BUDb0c[PKcCIY+,"BbrMkZZ`cKj@KliX$2+b1jhS*KAQ%LN5!1kaIf$(hXH
-NCV"JUp5Q@MTbfj5e#Ai8l)hpL#)#E1eZ$a`"Tb$*XEI@G6#iNhId53Q)HZDUf@F
-eKD3"1)re9!ir!C,I$3a-Z8RiFa+(BALXiGj,lKbbk#Cp@RjI3&eaDm$C4`IedkX
-"ldTe$Na(d6d"+L%qHSVT(p,#hr@$6h(l4H1J2NCfR%-4V8JfIRHrNKBPYhbHJ`0
-rDAK8+"qrbUSAQR,'V2D%3`9LdM3E2ADpF45m5XV5++@3"!%!!$m!!,BJ(BbjbL(
-Y!!$D(3!!hBd!!00J!!q+m3#3$NeAAde66#j38%-Z8fKXBJ!"UB*cD'aLBfCYCi!
-!rj!%!*!+J!#3#3,+!!!"(J#3"!m!3X(8LR8'HM&I*&f,N!"hdA516h"Nb`4@'cb
-()K"dJSlcrH*6q+Kl%(q'!JhL9I&,c@%,Z124l4`5cS%J-XCrhZjhYqcNM%1+Y%&
-Pa&BpAVM4hk)2$eRV#4p!jB@5!cXh1a)'r"e3hN,Vj8E3cZ$CiJ#BP[ai8$)X3$D
-jL-UQfF&,FCRqqe6UJ-l%ff9akFHVSp8V#6UmeDVfp&h,%HlhmHcbLIhSb"`JeHA
-T$a[ZMh'lNhPkZ861("hrTR!8#9VlEd+@,D)*L+YGjUGC#5LIKJFMNlfGfNCU+Kk
-8[,3hqM3R2I3fAfF8M'-a%F*,16XIhYGd8R1mqSR!1SpmClj3jk5P%Tq'1YY@G"L
-b-&R#b#CErc2,G#3S,REC`rc+%!#PN!3"!!!`!%!!N!VErJ#3"Y0J!!$B1[q3"!#
-3#U@3"!%!!$-!3,3GFA1hp$#T!!$6B!!"!`3!!,J6!!2LJ`!!hK3!!XF2!!!Nm!!
-#G'0X!!#Xd!#*!-d"j3*p!F!!(`!I!alrq2r`bd3!!)!!N!HPN!3"!!"'!!#f"mk
-IYddDp3!!hEd!!1mC!!$G[3!@HS)!!3[r!!!3Q`#3"!m!F(0PG@4[3f&bBQpZ8h9
-`F'pbG#l2J!!!Km0069"b3eG*43%!rj!%!*!+J!#3"d,"e-G'He+T[B,$K$G423b
-kbq(X6fqaq@HSFciK6fUE8)6qhQiYA!EIp1L[!16L#KTZYB[#')IPISbk2HHH,#M
-4+'("V4Dcqchp(khNfF,B0FYkr-ReGFaUYAN@KZkm!ZDBT!2iD+RcT8cZ!#Nc,J8
-0(hb9*&ZcU3bR*mJFqVF41cl#aFi)@MA6NJ62IU'$,a`YRkH-MM!K2mBD!A$BPe8
-EN!$4G8UUD@&R+1dENaTlHiD)prrpem8RhP$FD'Ilfm,!)V+c*e&YjV%KlU6YeL8
-kL%ach4(!2dHiJpdJ%MiT+bKUq-XLmm+*dJ@aA+8%4EUX628U[Y`5@CER4a)-GDi
-@3QC(08q'*+VM`V0BrV&Q8$,1UTLk#)PNq9X1b,Dbh#5V"F3hU6`2V2NJ$ek@9$l
-Sj2T$)RT&[SEiZ'6p*jf&LGB+3T0I$,Gq"lMll44Y@RM,Pi%mM[fpp53bDhc"*-C
-Z0#"-US+1X2Lab%IM!X[6+5YY%M#03&(@Pka*#9iYkHpmF`0!k"jN8P)V+p*4&6!
-Dfq2JUiTk*q@@98DiRB)ePVMS$%3BYMrFq2IDL84854(%Z+4GEm8[5iG&aiS`p$Y
-H$l4p''8aa5f%dNRJ'G3M[rMPaQ@eq4BK3Ycd(J2fZ$8Zam)eTTMGiCdKEmD#Tj+
-[h-dMSQ"El0A28`kK&I!jEb#H'SBSmL4$NHR%rm"(m44Df@kL[V'p4B!rJ9'*(R)
-X1Fp`cf@+jNYl,6!rEbPk0GS2q0qHi0F,@$M(H-Qb1ZT!GK)'c'F*3*flVRq9m&a
-pZqLPqdmV5#jJ,)"C2kA#p0Mpm0U&dkUPq8l5U1lJ[b&0ZVbl9k[V-QkZ54$QP,l
-[2E2DSK1LaG3$,)2#C6UJiD4r1V&&@ea20SU,,980QH&P0$b(i'%6bSSh**h@!A3
-*DXR`N!$i[jdKeN+c1bIN4+!`eKZ-8JZF[mXL,@+kHEDb([A&p9k!NK%rHE"L'J$
-lP4&*YH*40-[[AP)6[lRpkh!2[F8[&3(R%B'RMQc@XN-M90ri8`N"-M4+K'c(!i1
-U0f"cY6BeBQ4A!1ceGSlI@Kk#%[@CC65a3!EE$DS"@2*9@pe4`%b,aq((JC-`0ZU
-rH-Qq65'JHNh+R+CL`cX,@BmG)MZ,mhI$qT`X1SCJ(VFqZb8$*+6ce+DrA`p#K+k
-YhcG,T%DiQRR3CfGXm&HE&[9UJA!10iFfk59JL'*Jf3I%rHThjUZAL`#DBArb%,5
-aU3m#E*+FrEj15*m(Q86pP"'aXk@9UVCE"%-'&3`NffBCdcadA8a4%,$G2R(lN8X
-pqHaZZ1lCr!)rK&fh1%'$e&A%Sl6#*mBYj)N%4K30!#mSdIhrDdISSXZ5QZFl4i9
-!&I($04DTl#-dH2Q!!ad-X#ihj4X!++X("pVZKNQ&FS66k9EVBcphVe&aFHQSEKE
-88Zrl2mN-)1E06PrBeJKl'UN`-R1`3&I9[q2pa1LP[fm)H@Il@-mJ)jrGY**q1XK
-+8AQ(9J*16YG(!qMmN92U8P52aeN4RIeH5(KF!KrGLjF,d1Qmfb1&&[BaFT(@ibV
-%RH@pj+aQN!#J&AL!K3`b#Am'JL53!00U%AlbH+&)BJB%fN$a@F0lhj%U4,rQF-V
-mAR`dlq+$k6aIPrK3M3kj$TXq8AeBEr5UM-k1'3rBJ23"KE3`B2$IpP3F4A4JS+4
-2P6kf('a[[jH4fPX)bcND[f8&acTaiFX1eIS-l1G0k!)&Gi@(e$D5hQ`HQlPXfMp
-ebeIq-aUi5M#!pJVmC6[QKJZNMKic'&VF3RS)'-@MD`FlIQARB,a$04@DH+Ia$`J
-Q)ihIJ0*lZ&'Ncir1X,hl2HNrP,8X*Y3YePQb39fY!1AXaIP3r,(V%`'F[Jk3!#G
-*P2*,Dhq8412YXBElqjCQ'M)a2JQE&G)UIL9T[fiVI1`6N!$P)RHRND"Q!-0D-YF
-GD,FLF0rL3l32CDPS%N9%c!MdA!+af1e3XUdFCiRSKNMZML288BAmh3eS`(Z"!If
-K4Bp*AqT34-!#0ZJjaf1U5V+eIJER3bmFMaZrEFf+$,,(@2%Yd"NG!KX&kPr#IZb
-LjGCVdlL,i4Xq@-d$MVV+#Y2q@mH%1%c&DQAY&GU&[Y1419M,JmbrJC!!c*[eCIh
-KciVpl!Dl10eGVEKGqc1ZM1T0[01`[L@i[96A9cp#*fD5)aiIV%QiKF#jabeYbHr
-2&CXJRk`j'IHAMR&cmC!!pQCc1GQcFqAqUl"RUjY%-e6cbSJ+JmEr[iDVIm4aTee
-*$"T$lihTXSG12S4cH14&%eq#pDC"(U"#2#`0mhYG#pX-ll6S2Z4GiVZ(Ah#!Gf*
-050blHDGR4aGXFR@r&&TGMK8*&9XH-XNX94p'8%Kk$BHM`pT[)3GGX2cQrEGTIHV
-M1(5mX&Hc+*N%0lH[XV!bA!"He`DmHm9)I"3*qCYQP10#CSTfaCDfmqA21)#8!P5
-YkK+H0krR!#DRl"Y0X8d8F`hRS26j`)&9qZ0bT,Ba(4(8P23dK,kjV#FJ&Af`Q+3
-CP#M"Kr!QCEV3)G9K5UQ5Zk4$S``eZL*jZP3X&FDh`dVD"5`fdj+-![PU[aAP'dV
-Q2VqF"mTU5RPb4I-'F2,J0f2#hfF'6L08e"U"#$SQ6L%"1ML-GH@!mi-HG6Z8QJ9
-$)jJ+a6+Y5RJ)QimY05'%EA4FGF12'291U)C'AQ"Lb0B'%&*Z+XIc`Zkbl883!EN
-Decl+laCA@qhQJ5,KGlJFCd0fm-#3!0bp#KC3KiPC85#JF@30@mkDeQDZXHS"SIk
-3!1G*6Jj0#QmCi8aJEj@#E'[@FF'0%2#QL69f,P4e368&fAM&)V`-42SFFYV5`38
-$fL0E(4`q#5HA(r`mc6eSc&*iRm-FQU1FhcTkb`V6@eDH9b1kqi,#5JVFjR*VpT!
-!qX1)%FHR8QQmaFF-M8q,S8UPJ&Tc9Vm-38h6KL+!9,VB6!A0I@Y3[Mhb@SCa-dM
-qHc[&EqP*j*6IV+KD0%NLPlj!K&X,ec!4YicJ#hkQd#cG@9['H6jFXd3cH(%jkFl
-9CDG'i'@Aa1*af`F'F8"-B)&1SBF1Fi`%RP,i@Nej,KUI&4e3-Vc4AD-hZd6LB3i
-0%GSbZ%,`-UUdfl3`L"%U@m9!AAN@mJNEJ6+bccIAbR'Nl!S!&0icKmKL8rPA0eQ
-(3UP4iNC+$D&EqAd*pJ01fp*L9b8+40ZkLHIN)0JDFTQpfC8)P4dmHj@5CZ)"-rR
-YJS51V%[KMepA41ZCqb$kGrFT&)fNN9P!XMZ`ciaZSMBZj8PLZ#6N!Rl!IS9dPNV
-`e-2(dkFjM[p+PEJ9B@D@1XNS)kIEmZH)@5k)-H-pd*@hETD(cHq)c,J@"2dcMm1
-!ACiCrQcmI2k)MD+BI'$6Pf0SCqLTdf1LJBLXfaB5M2i!"%N9ME(GHQb(k6i9I28
-Eb@,T-'YF983AGmZe3eZ'JcB(j"cP*!Ja@$A61HGG"EQd*Z$P49S8,#(P6jD[-Vq
-0T$5L*LXjEDNR5ZXKEd@P)9!H3MC+MBlMYlpr&LL0DfH1'X%q86e8B'&G'"a-+pD
-Bdf$"ajcbGQAb+J-P*BQdC1+6H46+q$kDip@VC)M#fiU*Z$@!%"aQp2B)Y'Blh+S
-9+ZjMH"k2E`T+C0Ci-"U[[JD#*CmCHr(JpbU(c"5&e+h3GHeRYJ+0m@ckdN0cXPj
-X!$U,+&YkJf,'3-RD,8Q9d*c[M4U2D6L5N!$4$mbUSJNb*#!$ipF2QmEj!QKm@Me
-0EU1p8cD*Fb4YidlqR($N6[-,f2h$Xe1@q`d92bUNSLlSGV`RU4H+H@P'd8*#S9Q
-BRDYj$$hd3l6G0(2&[D05*l*flPqEa[c5M!C5TciqK6",i0-EFlAMbehpeXeKkek
-,(0QASi#9&N6CaET6ZD`C#h0qF,!%N!"$I&@p8He%HJ3X25`Y0"*["3H9&p[lD!k
-GeP-4DUX0'b+XBJfUh2*LF-!jD%52mUrJ2e9fqqT-4Icd1KA`a)fMkA*Z*dk"%%f
-l8)ZaEehRYI,Bj3Z[-KE)qZM8`8UjCbhBRT[k+3"qV'NbNNBd)VcF3R5M`*K#dc`
-RhGAZE0"LY6(S"12dqLXS5H4-AJrKLNm@-lrjiQ(4"P$q&f1A8`q+c%9p(B4"hK+
-R,)0ZF#*f6#jX-arq!)FG+aa2#KXX*i-HaiBN4*U'8&kYpV5dj,klAe8PZ+!JFMZ
-,f&X@"mF,DM`,k%8M4",qTTLH#3-("$$aSUSa&C+KPeDACaZDKE95+kUJ"Xl)L-9
-a`lD+0NDV`)&*h5P5Z6%1pdT0FM#e5HFJhZ[q5[mJJ$F"'P1kZED1c`4dG@E%G$8
-V3Y2I+'af`EeDYDDTcZQM@6@pZrTG5XPXbIQJY-lIr0X9##NXq8GmB,)EDmf4LZ2
-qaJ6Ij*lXh@1[L*!!i[l)LUaHGhQH#%qi,aUA*U`-QIPk&U"j%DImMAiBGh-kSG8
-GUP+XZ&46BJaXm"P1[(KTP6U0qHYcQG-AdN02h0fK#0$d6"'iVZlh-RQEI5%H`1K
-#6B9#rMM!L(EfMjl(T51r'ASTiFZq)ckrKhD0CVeP`3d"G3`8h(6Qb0cY[aJRJ8'
-rcMrZb@V%@k(H4pj#,i5DYCh2FQPT%IL+)c$rj)'-YRSBII`CbPR((GlcZ60VUrp
-ZYC38M80N)-m6QGUUD%PrKdh11S)d0jG`qhe1,%PUZH2UHK8e&NZ&Id,RYE#*lLV
-H(h3(R$AP3$+-SX1L9J`f%A22`@l+#MZ)'HSmJAGXZM-U4AMSBjXFfFHBDUc0%@Q
-rK+Ua"43Xe@[1S+d"2XCp3')9c6mMLF#Fa*HErARilMEr!0Z6TJ,93dq&TS"61le
-S4e-Q@d5Zcf"kMNZhGmhcC(6a-R4Aqi%0m!VXXUD5Se)lCaa+F6Y4H9JR3Yqq*Ep
-c#!Y`Hcj$#bf1&&Ai+"GX!3DS`M)$'AaU)LQK`8qmKBC6-'"h-L[i`)E0PP%$2@&
-L+Ue[0PTB)p0[U11YCj2RU(@a-LR3E6qR5%Y)@-8%LM#-ADMN+,MFC6Bl@UY0e$m
-&$`!pNi[206'P2)2LlC3q$RC)l-lQD`ZS&-Zi0SXSDZIHc1fBP%,2'*Nc83eQ`RL
-pqcV[%F&)"mq2NTJj%hIS8%2)h[K#B+YK%Z!mJbp0@3S6"81eZY`*[hme)96Z%0p
-iP6-r%*IR&(@USIS-rarp(k![U*01LJfk[qPABjC4+1lDU-1C(E!NZ*MBXB[KY#'
-K8rh'%I#qGi8,+aT2&0MILY"cib[RJ[-F$T`GRjKSN3!@3jhZ"d$L68,dGJ@LZIB
-LDUqr'dClP3qJI'qdi4J6h[l#--VlHpM)5VGGc'8`NG`mb!1XQ(A9F(-%@#aCefq
-A2"ZVTTq6Xe2(&"!(V0ch8'6$+YIq),r&$m@5bDQql%aCl*j!1&p``%M"Armj2+)
-T+a))JZcm-&0N0FQ*r-Vm$@DU0q8Ga*,+KaXGmXFZ+RLBM)jYXh63MECqPN6Vk3b
-6bQETl&ifHYC(R2(`cPq5A9N3&C,RI*Z@$MZ'5`23$b$%'c+BEhTrf#S8$!D-H#f
-r#4l0Z6HTME(fT'8Z#Sa1hj49&aLR$DJ0EN%U#Ql`18aj,SSlcYA6BdXGhSI09cJ
-Kj2G)A6XfDiY`j5Ae$I*eV2LXd,9IcaZRaYmrif+(NJ!1VQP+V@EhL@R[VED[kK!
-C3KJVH@6PEr,TH4&YTS$bleF+Q@'HX@[STC!%!3!!5J!3Yr3Yq,Id,IJ!!0i8!!%
-#e!!!hEd!'YM4!!'l%!!!%dd!N!32!("cCA9NEd0KFQ*[EP0eF("[FR3Zci!ZH'e
-X!!"c`94&@&4$9dP&!3$rN!3!N!U!!*!(3X(8lP[kGrJKe!QJHNbLUM#k`m('ZF&
-M!NPN,RC*UY#S)QYB$rP(cJ[(M'HqleCTQ!bA%`98V$*adhY$6[kPk`0,PI1A-&e
-he9M!0f)Y`Qpi1QKGCCUNP,f4[FDmA#C8k8jpLe&NBAQM6,TclSTmId6[V6-6,k3
-[*ah%55(K0d'a$Y6j2D3K$J%Z[cF9'Ar#!@QFh6M65q8IB'iZkh1Ul#%'@EGI336
-fk,Q*0-IQ$m@ZNAc!8+6C9a,+&m+1,kKjQ5NkMp9Bk#Q[pVJ)r!VeIh96(2dLh(%
-GKj6X3Pq&XrebG`GlC5q8BTJqUM"`HD!HJD`f$ahm[k10q5,jR!RhULTfZ8ed[Hr
-Db#rp'`U)ZE4r'(Lk!9EEQh%r"AijUDiYmh3hcBDLeP"k,YAU!6C*X2iAVp9(YpI
-mjAQijFd!fCl*EHTk"#r*)JAZ,@1X6BUIFBQI,'5$)1[IEDFp)IY$*BrA@VGYX%Q
-1E*''RJi1p,+iR-@Rf*GkTjM-HF338S-06**ZJpC!f+cE(a3mi"[4kmS'ZPk@h-r
-a,5k`*q9CB1"9@C%*P++J'1,T[D(Q1dfFjc(4Z!4FZa41Id34pYlm+6EdY6lhheN
-+[6)BmH1Nq)%6RfH&r&QPNfE4XaS!YN6)Vb[6ZDN%dSiLqh,*TmRji9+ZH'`MjUL
-mZ+KSQer%'jG2T#4Cd)Bk$2q@+q@+6ZjeKqTjP"Jk[9,308Aq"T@hBYFSMICfX&*
-!r'V#G83RMEcBXX*,j4RGSSG'Ek&9cAjKILIImc"!`CVJRiK0VF&3)DTJm`k6Y+r
-h1NckmreC)6Y+pDpJVh5pLJ9LH[+AhjYGj9jUbXQJEG$Lm@d,b8A'UL!*D,+a0X9
-CBKlQZ1%A(H&p$5UF34Sd$%lH[2m*F9$Kl1%e*dRc&#-rbbMHl$e(2NP'j&KM,["
-6'jMPS,2@b9Zi8DqJZM*(U09YT*RfQJk"Y$SESkD)""Q#hC!!DPk8Y-P25GL6f&C
-aF%Tj!MINEa!'@*0['aa1#m([CUqPa))pV'Al&LEiKPX+dSj"p#Zi0@PYMM8V(,#
-j`DpR!GGZ9hfm"bIS+EEVb#SeECc`J1*1AP9`-@9$akRB0mN#`&*T4`R+98Y1'R+
-S9(RNk1JD9CERC`5mfVdY+`U"kMB8HD4e#T!!NK3+m+rd$`0HVCX8LJ(jFI%bBqr
-Fd[A-GZN0aiZ,VYjCCNUh[KZ[ZR9AmNhLL2idY1lPEl+Xrh"Fq$*%$XTh5DmDhb2
-5bc$*bm5,&BdIaVGd80,lRJ98!kf4i"4bq0$qr2fN84MX'`98J+m!%&(6Y*ll-dE
-)V-L6m(rF83$@la-Da#qifZ*0,pAF[@6FYlJQrfPIQ,3LFaKV'GFH,FfTDYBQl8T
-@bDEjqU-b5Ipic2l@,P#NTJ4M9cEk!P*I6c4(NS98)SPYIDA@)mDD%2a@ej'Q'Vq
-J64K#jU2Sf53ieCIG,,f)"k8Sc3Q[ia)e,Y("fFAeGk4I$Q+SYA(GTTb8U)SpHPR
-6fRU#2(l-(Z((d!A@arRD89YRCLHNi&SN[Jk18r9#42rF)ZaRA3rd4Tl5Y(Xb1%I
-jj%M%I$bpPqm*&H`5FLLehbJkI,8%D&FNc(X'XL$Ti-J#R5+)GcqC90MS$UBlQq4
-C'L4q"l9LAiFLJG9+i[$(U&L4k!VSI22PUG0RV&-"SS))6(-JC,,RrHH+NU3kk,6
-0jI8d,(&SRGjc,,I9p0cNDcJ,8,Gc0fZ,Fm5`JJ(kZB'f'k@9HH*`@dhmcqmcKEI
-&mHPYkI8i(Y[D89cTJ$-@24TEl6rbL+3MiG[Y$1eSqINE*N"RkK$jVd4FNi@K*ck
-%d+4[JiUKPiQj6,+0UXNiZEpP$LVDX,[VParHH4I%2eX1fp)D18G@mC!!2D[QXhU
-dT%Qclm(*Y)MH,I8i83kZ900S+q9-#lUKq*C38HdQ3(5bqSbH3rYfm@[Cc`qK9(6
-U%Q%#T+K31l8YXbXE$[9*5hD0`bVeH'$,M[3lal"V0NY*RAJD&VLI5M4mqJ1A)91
-lqa$B"Q(6Lk&cbhRC"Re3dr[@Ab+j(MQcqEA"I&T2Im6HY3j(*U#95N4!E)`[M4l
-$8TPaA8SP6fBi6Bl#FAJXZV&qL-cTlaqG$4UDjBjS6E`"@EZR28NE6@23(1)d+Y[
-a"JqqQ'Z)qH8rXerQ`Hq+0Lbb)5%EJ"aRf1ZA'm"LD5'N&dD5PmHJehK[XI9f9"$
-kEm2i14#2DDYB$120rfQK"dJ3f,@k(TL1[1,jb$DIARBXMdVF%DlRBMRkqk2*LeS
-&Q@H3!',D*PaEN!#XSd6fU*Um*HDJRBHB4e+Bc-5S-G*N+NhMVM-Pr)"9XIfHa-d
-V*1%i3#hiqPKG(YF@UiaCYTXIkY&q+Xa[kh2(&F(%aFhMAZU"!9&A%05AL)$L3fL
-6rR@[BCSrSQGQK3!P%a0MfVJ2SY-V5TUe9L%@2cpSS+Lc5*'#d6`X'P-NpGFAUPf
-,*"aPK1kDNmdXq%Uk!heXYZ$3B!UKJe6*Pei6E9rINZr'r%b,"Maf6`"e![HpCkF
-0UHV[rpqII#IaN!$L8LDM)F[3X[LV0"j6QH+BXh2SD%HM4-58l2`VjLl)qRTa!Y"
-b*+GmfXe`-64RfL"ZHX99ESK*lUcM%JD6`+KD%+#X4bQCZ"KlhY6iTpM-i`Nk`S%
-)[QJK69VHQC!!HP'Y1I(2LrQrG3qK`[8bV5hE[K1IjMJlfb146Y+Z*)0Yq)'GV+i
-[dhqBH%eVh"Zibf(AfZZ9$S(c0jc28hSNGMIRiddM&*ISe9YhhEY9GK"eN4MZ+M3
-[b5lV$Rj[e14DRNmA,bqLApM&TY4cC5X&m,X(B2G*"1R*e(!`CG,4`+#A&l3jaJK
-6[-NF-52Fr5$2qh+'N9%%,))+cISja"cj9(6U(mGF#F4NZT9@@%8-ACZm-G"3&F-
-HIhMmXEFCj`X@a904-ZBT9Xc8F),,mp!4G9P)#(i$Y*r+m8%1pmE#p"AYVC)81C%
-KQSQD%Sdf`Ra-XK+%ZGHjiYIh$`je5Amrc!RhrF`'PGI[EAL*-,bLVL)%Jeb2jr3
-Z[(&$irFUI$8ePQ0Up(HG+K+e-*h(kN[d#6AQUIkF+M@,Ra[LlHBNhJT243Rl@$I
-HRM-T9kR9&dBa0R3#614ed['a5q23MNES*DU'lIC*$!p1&$ST90Q52l-5h!QE#K)
-cH$EcH(Jqq4dpR%SY(Pm,Dp[6cq6jlJHR@$cjqNU4PPiTc'3#DLl6kKD@8hbRc%T
-QkQF#&[JMBT(a#k-#jHBCY'VKGM)pQB@cDf1'rDjddP81h%k)EM(5%0DLQCD*5r%
-!S(EP6dcT&,f#j[CCCpl%00X9XQ9"r5%)%Z2&r3C@Q99cV,C,"5L-idMQ0)lFak[
-#a3[Q5Qdj"R&r*b(V51fBXle%L-Q@-$HrHNDl[U#l,H339qeF(@QBJKMZS-A(eGd
-01ZV2)M"`YB)SdJSXGaCjYqRXZBD-0!`!)(j,a1kjp,Qik["5c2"dN63[#dF6L,8
-K`5CJD8hJQ-cmPkC,VqhV8m9,"+`p3D@5d+@cm[hTh`1[KXIm5arV,b1a`edSc[e
-M+JV@T0!2%$1RklCPGJ)*0-j0j4rPG)dX(UHXB,a`4*VcE6m"q!kmKRBPL90S,Y*
-Xh)1dR!pE62ChNI9h8,c+1*E`bBa(iXi0U#1H866*f0YcY00S(iS2R2FPU@SR*jc
-ZXN`PiF+`P1"iUm`r#)1GpSJQ,U6fJ1NrQXY-3-bRcN&X!BH(LR5*6(lk$0cK#1E
-NDd@m-&k!TN8I9cC+fUS49SG[D*@`k@!QF5N([c'kS&(KSGDP3--diBSkrp@Db04
-JXhmU))K+B0#-L4'"YZ'%26-J[$(UR"[P[HDVQXH[,cY`S%TP5XUm+m!$ab&3hQf
-YR(0i-llSeA[$ibR94@G1K(4IA-*`Dd#"i@ef&IrkAp-3ifF4!da%[kcJ0hZ#K*P
-N(fj",AV)%Q,lARJY(4G*V0F#id&B(Kk[h,Y5)cCNNA%h0ANV!q@JabBr`!2YdeI
-XiMRDDHIZ9[2iT2e9,@*e`5G(8N$,k%UMl2qim5F`+PAfJ[eEVS5`'JrP)eZ#amc
-L@bp5dYDZCc"hfB!m[6B$DNRI@2C+91#R@8ULJeJ(qS,Xpb6Zd&6*4hK36VdGJr-
-6CCZMAQ5,E&lNX0qNa-M*hN)HUX,3dbm+E`2c6)%BT@cYPlH1[c3Z'5UlAH&-e-J
-r+Y$US+id,AZ,DZ9ATN"&)GP-`Kq@GCBXkVdaI[`,#%9+V@5ZlbGK'pRRff2@*MP
-`l[+*E`fDflj"b(j4pI%iRf`Irf#ZNfh!T#%@3ijd$8kXSM#RRA3@%6A`lkfiXPE
-GGiVKd)qfYrT$H)'BdENX-+N(c-&DPL,R5AV1AaFUpCS`4CS2c+,#pQm&A*,NMfR
-p,IblZkT"[J`a9N9UiXHRJ%V$P%X'f&-`rM9BZmfTle5hNfN6KGU%lQFSba-*GZG
-%Dc(J"m3*EdQ(V+5G-j2b"hPq`AU('f-J6b6@P3JfTKKmZ4Q$GcP5&#"Q)+-KPk)
-H1#+4D@4kpEE!1CK"hd%i4fQ0"RPhVIj2Vi)pVLfeIU,`QATKT@9FDQ9*hI0pE[X
-D-M3eldqKS5baVRCa(RKHJQ-J5MiC**Ka+U#L@UakD(4S"&![!NrFE*LhK,%DLDA
-cdGii1(r2PbGdARQV10F+l#MMe&G4VS"XN6%951VRBE%%Z,2d@l*(kCK`ICb3!*2
-[T#,TKi58)#f9)k2X(q(FQJk"&5MiXq%qTAr#$6[)+l*2!TDK9'`!61)SeNL&Y,c
-,IY(P!Y6-0V%J6-dJ[e-VUFeGKfk3!-5LY$p"RCh&j!ahAVH0*`6h)*Aqbic(+$8
-(dR8rAGdIUH['[XmX`f45EBBMTHMc+e3G!+mJNV,KRNd0LF&Y4iHa&r%bf2Bf0[l
-j3EHk(ab1-TS+Vi[*5&AlRIk[q"(6dfGT3,qcCPDSYZ`)1'`4jS`,9)6aQ%M%A!R
-M-D!1Mp%KE@m`p#dFb'8'Gah@&Y-BJ$lNf0NUhHShHH2Z'4!TJ)1MPV%El8a"-I)
-BSjH*!&@rJMmffB6bXD@1"a6MZNGqJ,bc%eBFZcpfCDlS!NS[H)$"ff9&mk&rAXZ
-YH!U)9mfkpVMM5C,ZFcSR,!ZAU2`$)(e)#be'0Bi&@4+0mMESGE8a1rLi2UUFKh3
--G)ji,1EGaQX-I@!$F28r1dr9@j0Spj1PZPi-Vlk[K!ATN!#8C+qaFlAU[*([3$%
-'bZ3)fAHLCHpD@@ZdhAi(Aq)ZZjV4b0lm)NiZM"'H#!"irbGc,933dIibI*@r$3Q
-cJrC4Z+J[38AP`lI`C1EQNVmflcd$5diq(a*eTjEVIlAp`!%TMcCr!"*cUp!T$9p
-Nq!D#rC,$PQcm9IY'S4fFXYV-D+JEHUc8C+2(#a3F0&PV4Qm"N!$c)CN@`dQ0Aj!
-!M$VD`3mQM,H3!(P(Di,29$[@&+M[)QJJ[lF9UYYjhP"2Hme43P[@[b%LqMNm-X"
-@2Z2!hm*RCir$0!a`db2V"b$ih5rJ`a43hi$@b3clpF'3!#KAd0D4)(6N6UYd%0q
-UU,q0IVjd1p$AAMjmHRXPm2F%c(E0'PbH"S2(HJEraja6[22qLXdEPG@G,KPjJ26
-c0f`(hArbk%Dkfj[*H*!!Q`Z(*UiY#qCULAXTaPV'0q*-KC[X&LLUJ")TM[!3BVI
-c1b,9-lN-SNC+q+3qVQ@e3*j[EBhe'lYURAMQ2`bI@ISd1$XDKCX0mAA,1b)0T`F
-L!`mmf0iLZ1'2dD&2T[FPq)b@)aLf*N2)Zr9fc@fC&Z+CKacLm$0TZ4VB!$HS2,c
-mQRY-UpPE*9C8qdXDY&35Eqbde($I%rkl'#Y`p45brbm3r36E,#T`C($DRS,,,hM
-2KM[d-%l*fHpJ,%0VJq[U2kS*AXIJhb#PVL@Z,i@ekN@(He3a&[NGM@F*ek56'k`
-&HPBYX[ARB6-FU!&ci!8@Cj4+US6XLGfLqPYm-[qH+&)%D2jbYcGBZGV8KTKk9c*
-kX[@FDf2`8*'SU-bfeABGL'61&h!5&Tc(Hp+iH#p5dD6M%ZMaLR&Ur%KULKl(,PX
-1qQ@+m1F@CYhhPR$DF`dVV-SEr&G9)Z30-5C!Gl(rjQ(@ka%krL,cmleT$R(@(6J
-)*P#[CGaPmY`84A@582#YG9pdXmI&U@GcHK)R,Z&3X5M0dc,$-*FdVImpU'jqE3j
-BrGZ["EZYXUqGZT+E$idG"1G,C3b+Z9B0HM,"%X41hkId!Prm$6FU&RpT(1VL'6i
-9h(J8EMC@NHZHUi3pVm3hEk+JV+G0hdaDc!aV3eH8l1f`)F$q&A'(+NIUQcLpKk1
-`E*XkEE(q9@&J0fpReC9%Gd1YAqF9[[mTjDSb@NR1TcN`F$Nr90XJ0QdXm9E458%
-8C$`Q2Aa6phUPQ#k9@5((Ie$#ieFU-XBI9SeLlhY%fV+8h[e-N!!ikHQRZJ#dCDG
-29V8eHI@rV04`HfIh2UJpi9H20mII5UF8cL48+'D`'Skm0KlRNGdc1&1K"rSdP&D
-E!fD64`h9U6dX%"j&I2kKTMalqQcQk'EPl-0$6(Z"Jpe$'@Lp+T5SPY3[8'K),4d
-K!lE&l68PBTGXA[-M0qdA0cm3I4d'8S6Gmdq0Pl09rJaj6b,c[+@3"!%!!$!!3!#
-3#ZmC!*!'hEd!!0[mrj!%!*!+TC!%!3!!-J"!Y"eaGVId-*)!!0fp!!%$LJ!!Z"-
-!!VU*!!%$@J#3"c!!!(4V!!!Hd3$4!$3#!`(P!F!!$`!2!alrr2rPbd3!!)!!N!H
-PN!3"!!!`!%!!N!N"!`3!N!8"!`3!!&'Yrj!%!*!+TC!%!3!!-!"!!*!*!3-%!*!
-'Z"-!!'Fcrj!%!*!+TC!%!3!!33!3Yr1kGER+0Q)!!,J6!!%&I!!!!F3!%@FF!*!
-13R9TE'4TEQFJ6@&M9'0X9'X!!F%h9%9B9%0A58@"!!$!!J%!N!U!!*!*!j!!!!!
-"6`#3"!m!3X(8mKd4CBm$dQk01"-S&K&*dK%16E*5[T*9K,aQbQKl8JPkjAe"Ab1
-1JFEEQiKMEBVVjDTj2$F@E$@i+9q`Mk1SDe+*dq8@dJ1M&"rp25I(1G&fr9(Y54+
-j$D!BlTHIIX%'4fdHp%5Y*b9Sll%`HS6dehHZd[5(S3Npa%D8hrmF2#+GD+@*jL6
-Xli-4ANL$Uf#9Gi8Q#"&3BPb'U['-*Z(Ci[`#F#p9LPAJq@*dhqhNqYKHTGLbNq-
-ZSP8J@"lm,pi-#5pTm#(M3HEGThi8A*)S+1m"@&*`X8TH0[GXQI5*9`-qR9kD!6j
-*+HbQ+1d0le5ZMp2GTP8qd#34TfK!6kNaN!!VNEeQ,KYh22@mZGU9#XU93eMRj68
-X+Tr'lB,3'e&LZeH'D)R,qeJJj8JNqIK*&qb(B5`[U3E3V0S'dibD1R1%BVklZG'
-dK8d"CN%!TC!%!3!!-`"!Y[,b!EEbmJ%!!31k!!%)&`!!!F3!!`9#!!%&d`!!!Fm
-!!!*%!!4$9P-!!,Fk!*!)3!#3$i!!N!HPN!3"!!!h!"#fm[)"Yr3D'J!""A`!!3C
-"!!%&I!!(lI`!N!-6!*!$%f!T!*!%4@jdFQPPF`!!Nr0849K83eG*43%!XH#ai!#
-3#S!!N!G%,h4ME#q3"!e%,h4V,j!%$D@3"!%!!$S!%,EbmJ'fm[)"!!%&d`!""U`
-!!39m!!T'H3#3!`d!N!-0%p3!N!45CA"[FfPdEh*j!!#6me4&@&4$9dP&!3#ai,(
-J!*!+J!#3"bpMGR0bEfpd,h4ME!fPN!3"!!!d!"#fm[)"Yr39*!!""N%!!3H2!!%
-&I!!%61%!N!-i!*!$1-M6!*!%8Qp[G!!"-N0849K83eG*43%!XH#ai!#3#S!!N!N
-"GJ#3!d8!N!32!%,"e4[e("HEj*8ma$,1k0CR*e8pmQCV5KfrDe)K#(BJS%%'81Q
-rlr8NrKT#'p*,!mBUpI"N%8,S(Z!p,2l"b*!!HJ)T0#!kF(0PFRCPFMTKEQpZH@e
-[GA0!BhCc,R4ME#jcEh9bBf9QEh*RC5jZCA3k,f0fFh*[Eh3[G'0X$D@3"!%!!$-
-!%,EbmJ'fm[)"!!%'V!!""qF!!39m!!0lQ!#3!`%!N!-"aF%!N!48B@F!!*2c9%9
-B9%0A588"!,(JXH!!N!U!!*!($D@3"!%!!$!!3!#3#3%(M`#3"3%&I!!!mTArN!3
-!N!UPN!3"!!"#!!#dSQ-cYkH3!%m!!39m!!%2-3!!!F3!%JL,!*!14(*KCb!Q)%4
-bEh!J9'0XCA4c!!%&2f&NFR"A5A0)K3#3!`)"!*!+J!#3#4@l!!!'TJ#3"!m!3X(
-9(-Pmlka0CPUrlX"K#20p"G6"GrNb,Y6*15!jZP$GffpU)RC@9!3GbJPrbk-9#3D
-Mm6J4l1K4D9e(G#eUpl4-+AVqrm+3!"B'FEH)-*bEIKaR8fmQZ$#F9f[-2C+(P`T
-852,C1PZE-fCR,cH#8BPI!9YaceJ@kE6FpjKRK!(*B[-ZXCD#T6fe1,%G&c)4Z&a
-)UP%@dUq,H4%N)',VH"2%bYjC(Lh1N6CmYhE,qAm6J&haVCUX`lcFj+le'RrY`13
-8iA@cM20MUJBFQ$Z9a)G*RTY8aK0e5ZT1%BX%iFQY,5S`#*Ep4m&G@QD2M*I`J($
-6UGi1lcUr[eJhc$5fhCFL[(-iY*r"d-),9QP,SXL1rREFDSIS,2SI8qVdhX['54S
-SqL2kmLY1lSGX'25!h(HjpN9KS*!!XNYFmam3&R[@,J6ql),AIV,iQi@HU[9%8Qm
-89pb(-fR+k1XfCdJ,8rAB4Ea!-b)1[-0f-'&dL(qhrZXk5frNb[M9a!IXJFGa(AD
-Kr1&Vcf,KqBHeP@8e@)rK#XNqqpf5Sm$N&e$ekdp96S9a@`*[TKikRi61S%*aGhb
-CEcld6akmdqa[K(,q4*AmF!RhjT2(S9b`jQ-5LRi2L5CDGp(m,c2GDM3i%0($Vdi
-4Z)r!CPSZ3H*$Jc52XXBmE`9"PBI'XLGpamF@([3e1pMM&$*br@L#k"f+U*(#E%E
-Jc(,[qMi6#`2D3DhK[0jFTJ"FQFV3*5MC3hUhaK`!9P)@S,GD`!TRr(e(Pk*lS9Y
-bSqRp+XmV#T@3!%GNHDZV%4)Y1mRP+NG'3*c1"6EJXL2&9U!(GPULK`(QPl-A(Tl
-*ARma'K*j!$lChIq@jIE*mVPmS*+QB'Udli)11qkHl5SfqK,0mjk[pN)ANV)%fTp
-fJ`S'fH[UQEN$k[UJE`LG`f9f6PaF42j"k)6BCH$1r&a3UQY+pDee1,EGZ9Nkrd[
-c)BXXA@I&81b&kN+5)bPMHL3cEF5@I9EQRP!jb)fYKr[VK6JZZE[N,DHG8hqV%S3
-qXXiSY-Pc(LcpXX`kjHJ`@'`Xa'@)DlRNeT4F"[JK-ql&M4kX`iZXM[GCSd[q@bG
-#-`!C'9LUT36-8,SEj0J!4I640p#cmr@$"IcEA-SrRKKT)dC+SAZmcUYelqdE+(-
--d&,`IP'13UDc-55AYkd6Yr'AFLjAZlCQJFAVcqcLHIXjF2iE!IZ[8GYm0&PfbC-
-9f+l%,jM"&MX%Y2Up!P-`%)iVQHY%!9k@TENkT6&-#Vf*UBCIQN*km[rf`$SlSR9
-)$LA#rr*U#!GiAdDFc+j8&aQj(e+e4KH#VQ,QQDm8j#V"$8&4M25`UrBhqA*F4E6
-Fb,2X$6C`*Ck`mT-ZcamDd,+bQFk9UMXGbTe9B[SYahB6J4&FADFYZ31$QX%5J#p
-,!GEELhi+d"VTr`$I1D0P-YNk9E[`13R2Y16p6BKc`KfG)0K3qBLaMqZ-c!8FmV4
-)@Pf%)pRCLAeA4XPf0(,N1*2I&JhjX+HRj#-GaMH*5f9dYPL`Y,C+hI@EPk@90aY
-pB*m,R68R0,ffi039-Q-+h3`)h,#hMVS'RaPDV2dN1K,AXA1!F"pPY#QkaVPZcH'
-U@`hMU+Y2#XLJQ%(EH!)B6c(Y($4m)TZklG3r%[mLMqF3*iH`1f*aR44P(%KlDQc
-bT5j-XCU'm#Tc-i**(Ii@`XK8)c,*Ci%$aH$0I8'&%-$!6%pN)$$*6(EBGkS%@F%
-E*lhN05C#B*ETr$MF&a&NcbZR2+2HUC0i#P,N3kf2%E&Tj`G((SJaQM(SNR3'Q9C
-iqFlb,A&[a"iUI$VV@m52Kql[!"e"ZRGl6[SelEfZ#P%lL%am,MmI5@p3eRQd0hM
-M'RmM(k'%Y6@`H!-NC3j8Tl9EjGhd*+[TA,ZfN!!(f6!h2`-6,M*HlNGC[NC5TPY
-PX'*,1iiD-`Y5MD3!'KX#e"`+qdF*,l'S[rGjpDM(5P!+e,rfBRQ+Vh,SEC!!*II
-9J5TmSa5,V#Yd15re6UMa#h,$"(l"q4mDm,GIYIJe2Z@kU9Zf-JfUXT45ReQT@VK
--i"BCXd)cc3k*11iALHVaVHc2DQ*(khU#k*SH0'-'(qbcL4%IXjXRrD1P@%a6J(,
-JD*-Dc"T2F*&`*c88bjJ03G,'f(Z'iRC[J"!XE$'BEkfLBT!!0-56LX`q`6U0Rja
-QLT8`QM$b1kFP!B+bQB"+LAQ-i%qE2hcp`@SaZE"#lCD(AR)q4fFkem@eY@JpHTZ
-ElC1U'$EdhJH8(JFjYc-'Pm0bj4DK62Y93+@3"!%!!%%!%,EifXQjbM&f!!%)&`!
-"2jd!!!(%!"'5f!!!4em!!"M4!*!%$`"0B@-J9'0X,e4V)&*PB@4YC3!"-mY849K
-8G(4iG!%!!%!"J3#3#S!!N!NDb!!!&bJ!N!32!%,"e(6[5Y5K+*!!@)9UEf!V&TD
-[Y14lJe5&[3A,"(pe10@Zi#HDUDK32Sjk@p"jcASU5G+eRQk"2ml80XB*c"'M3m,
-PMQAPVG&B&+8*GjYT1dr@FT0fYAPG)4!d`0f6-Zd"5+FTCVB#5,8lil'@K1!ChTJ
-fGQ%0+)VA"E8+IRQTp+cCCpK50DhBTK$M`Di`E%5$ie+iEHJKp3d&G9d&iPpHqrb
-Thmd5Z1Rb+RlQ#-60SkrliZ'c(E!)DQKrmI85XCbIA9YS2(m3'iEiNLl1qDc4kCf
-jqP)2mZbc68bT*&!ZmBhb1'MhEp[PU2H#mFpi%,aP(EG$CUa1HILj3AIQ#XaR&1@
-Z!T30[D1im)2$41jIdFql2UkIKN0beH*ii85h![L%98%38#-QFI+P-[m)XdFQ6kq
-IKd-q'BH!NS0B+i2+"FaB6[3X51+ZX+4BAN*0I*6b6rcd"eCALbZYG(r64,GCT`4
-GV""%a2HC*SYF$Qi)"ZT9$)e&%S%VjSkb#TBU*MhNkVd'rEa!4aG*P1CfApEmK8+
-mc(5THDh,!R4S2%Q9ZLX4$bDCCdV0$aX+B)q!&+*mGJ0)ANUJiNV(!3+Sq[prR*!
-!SD"&qZ6E$V'AQX8GV%S@"LZ++BUlb6r+-&Z'6#,`#A68DYS0f[N@d9$`55($G!*
-CLCiJEQ%C[Ml0BY182rfGLdr4Nb4#4ljd[Dp0$(V4TCKG$GX&-rmr'K-aQicjCr"
-MDrH4U8PJ%flF'YS6C$'h#iUGaGIp((BX'*T@FM%(8XKjH6q'kDpp"d@H*kAK@M"
-$)9'FR!$@ai-a[Xa4XD948a+P-d`jZhTSihMlhN[[1VCM%fp"TC!!,9+2M4+AH15
-IXq2&3&iIM-C+mdE#,ZYN+GJX*KpBM-FP80aGQcD"hakd[he"+bB2GDd*J!PlF#L
-CFE'9+'ADD'AZjmb8Eqh+jIU4,k$9U(S@M6iY2U5+m9k6BqbUJ`DDT6Kj[4Yfcdp
-[S(%ZpcRbLq1Tb9ZPKGQBV46XfD!I#DEq4ad69c&kEe-K4$J!5VP`BaQ,$Y15N85
-mNJ85FpMAA+(`"P6&U@5kmFc-&,fYde[UKe6kiq(j+ph$LYi`'f$2X`Z2l4kZq1m
-Yf4G5kqT+cD[FPlRVfGD[e)qUp4VICcLFPLM%)80'mUJ,1GG5QmI)JVHSl#)1dpV
-51a26c(iDT1@je$#kT$&q,X)PZjTVIj!!M9E'NKa@LIKMPZ"2Bc&e$b(S*!rZ9hV
-P`Fj3V`c!U2-R&P#UXR0iR8%)HcTE1`cY(16G)NIp,)(N1&FP@*Z%A6pQ-BZrB(F
-BNXI-,S4k%)Kl+Ki"#q$j5Mj'mSTi)5GraLR2%5@3!(6J`AM`%rd5qjP'i8(MpX+
-LbqGV2(&iZJTYPP2b`fBpK)EhiqL55h)Vj`VV!JX@CBEIUT(QSQ&ZV#VLj95c+E(
-D!TYA[8@N%DUApM35elUeR*P6VjTMCdeXMf)$KbaFM#HG$%@Z2M)-GMLF($`jbSQ
-kIU8U&N`h-)R5b$&h4lld'l3*+@YA"I*"lk4Ir0Q1,L6FqVdfkX0U*f+2ZXaB-Bh
-pi*(142Q1L0!@49ZZmX)[HB[f26jeTTrR6U-X-cCYNh)rj!8@'P`*PiY$*Bk"%Ei
-()CXb0jKMUFQ$JES,)h$Ul[6!Bk$)`A,4Bj!!l0XPfaG8P5(,p+[-P"Z)hQlPEf4
-eH'm#C@ET@c#AHUYj2cH!)8ae&fBdIEcG`h@Ejp0qSqb-3IAQNJ-)GSi6BBDL0V'
-D-GL-pmX(L03X&JP*Qp!5Fj9B9pXB@lfPd'kGhSDh"6"N`)5KAFAmP[hf2ITYZp(
-DLeLR$NjZTe,ZJL(kM9ceDcl+49bQ8A&f"6mKJ(XHB,aqEGqr$Q(#6jGS!V%r@1j
-,,aRLa!46l5F6X+H5@Ba0TpBa2`@R9'-0GUJB&TFVQ@Le)ki`kq-BC-c1(1T0-QH
-L!p'8T,cl4*Qd)A[6f,T'd`LKP6J@&bhlV!!Se)$K@c4#jbpJ9C[I&k+`9l[@f!e
-5mFEPGDXX8C!!ASa+(Y&5Z`pB)6Y0mHM&6*!!#M@0XF4[d(ZF4$rfD8iJKM(Mb-F
-4[prN"%Sk@I%Qc9HiJQH26"EmL+i&(%+JJ*,[P9+9R"p(22Z+F0VEBVD(b*4$X"!
-mSe`)L[4@Im[3qBA(ZlTFLV`)'X[c@K#Qf[j,2dMHDf+6!I@$jLre-N,JG''!A,$
-#h)D)Z$F$0R++rIA8U*6HHpp*CS,"G!F2BG9"6BbAEPH!1Gl@bUf(RA8F5AbS@U@
-#%K)%VSQB2(RI6mH"#*9@i8S)@N9KE#)me5c6M66BLJ'Ye)81KJ--H+@!61(Q)G*
-!X''2HZQ&H+ibN!$81QNap55S5('jD0P5j+RIM)4iHjfLDfXXqjEY3I5#2J&12)p
-69dicmZl[bCp5&Y+6+"`NKaJ)PU*bhqbjaNXI$bjrcdPrK#%H(m2*CG&NKXrF8A'
-AG3(%QLlMM41q@VlTh,-B0#FAYcD6hY,cYq%4CA)-0PU+h`$-I8Y64jm`e'BmJ)&
-"R(aPEq3H5cj8p&TYIJjqL6-)iA)ME%R#DjQ8bkFpd*!!AUB,X26J9Y00%HC`dU8
-AlLXYBLYMBqc12jAjcdjIG"`df,Emh&m#@IDaApe!Tma2"I#8l&H-dc#!I+#8hHE
-6HHEQ-Bm24Y%R+G&Y,4U'QL6E`jpM58H,rcI1-4HFrNKA"*XBcL'RfIf@%Q0ZTqr
-DKC)hFcc4eDC@MEhf9Uq6dQ9)Bfm*(e$C*5+k)8B6`"iN-SB9rRGBdYE@Z6L"T-j
-Ia(P#AX3""@Y0c*Y2`EF[rfVSKl2#-8i#-aG+dfpUVJTp#Z)-pc#bMhk$p%SbSEr
-Q0JI'HcEc#mSq6hRNlAmAAp$5+B9$2K*X`MZ)+l6(ipaG$dfMZSb3!$b,"qlmA*!
-!&*,fC*BE!&)pITM86"%'L!84HiR+[PA$(rT3TjPmAHTm!N5(`rZ(R6jYP+H`[4V
-f)PXAXE*RQQh5dLCZ3e&D"%+cXe'G66ZT'[8B%E10+U*X*ANGLR@D3kk$mlUXAqi
-iU4lY,3YNQ'1qA'pMi[1kR'Ch21lqPR3e5pk[amFbC[YCB("Nmkjr`qJpQ"#VXRH
-**5Y'4ST9ji$,JD)-"F%%'5&(I!@QaeX%62Z"lpjj(30b0l#QDmT54!lGkR$N1`k
-6!6!L!3hmZa65b9*5#mpPR`[RbFNLGVeRMbhZEm5lKC-cSMS`&*`GaqiK6m@$SAB
-b50!&%[LV*XGGHAXj%4b+0!mld*D$Ll#b*ikL!QRC$-kI[lM(rICFJLK8,IC2[8+
-!!r#mL*J46C@Tk0LLe`Vce&2bFBh2Vpd-KS25`S8aD@fkRbR#`*IkbPh0RbXpJ5[
-MUpq@BY"A#BD43XhlG%*DMjGL%5bp)kaPM"Y9TB'Kf!6*PQ'#NV[B0Kb[0KakUcQ
-a[El11C2kG92B42IB`k`e44iQR*fZmb@e$0`(d@I2DCT1+3*VYI5'XG$RpZ#%%#k
-V`Y35emDfd)a$C4[EAdGUf'FaZ1bU+U'@1rQbmf9bN@e!'FUDPXcc!"q,ISP(%(J
-(mT!!dTP3j!U,b$Cl0`p9"`#[T,jJUlac-G("ZYdHQfEL,9dYZfLj'Y[%2Sba8q0
-2a"0rc[82cT1VkVCd!&LLQ6YHr(TSPH3+6JhJJBap'B--kI*8TLR*1Dr`X@iq-Ul
-2Jc*AGS[4!1!"IYS4'mm"RSIiUSb4GcJ5-&rq$iLaCL5546pCI06,klaMB`[!Nak
-)FcJ2Q"0V[lQ1$KpQlY62kSafY(deFZ,R+")Aa8F5qPEd3PIAB98rr'r"4QRD35K
-8ijZLa+5)C!H#1d0jIZKaFCNI4DI@S2*m)h5S3%&(!5Zc(+L2E[!r$IqC5#IK"8Q
-Z'a"`qd8)p8$53Z4rEpA2Ap4jK4cLR$I(*1H,J3UcrC(ap!kmL`["M559i,#Y)IA
-NM2ISi[9P890JIkJh0edBYGZp`QEMMd#a!4""A2[-M&YV[p!"c`Ge2U&YXSY463i
-$$22S#ISFIZS`C94346AU!er5H3VjSrKEbSMALJ$DAJFkeeRV5L6#&hpYS",B,*K
-QG!9bHc!VEKdTC8K`1k[eVXpD'mYU)3C62`1eC*L,8QFlQkTSI'H1EhC+'*)rGAC
-'AAA&J(5`5Z5ZPaY`kM4q@fTNdSk#6IeeP@P-j1NBqNRGPdHU[0$KV@ljmHZMd@#
-+J'"4Z'Z(Hiad()rjF"V&eR*ML2GAm%qYkdNUZNQF`$mK%k9lP`NZ9``I(!JjE#)
-BpSTEdkD+Mc@E)lrMQfZN)GL#a'M&&VH[clHTM8QrPaiU,Z-ULaU*1hR"YhjHIb@
-dkV"0hi'TMQIbfTjeBQ'M`3JLbRXCTIkIl2h6Yj`ba(HF1$%FaRa%Fb#UjYC8BVU
-2R98Tak3He6p&f8fDSj2ZA$%m-2V[M9RpNUaIr-T3Bp*b(5Q-+pTq+LarhGi&L6*
-8(k1)JcA+VYVaL`$q*AY`(Ycf(IMrTcJp2cAlcT&Z9Z!@bki4LGGY*9&IJ[D3!'S
-!G*,RSGi[Z81r%9#l&HfDIMLJDK-leMdr8)HY(-(#LD(Gi'`%bIQldGRfHINjA1f
-K!8Xj"KFf4fkIA1#ciDE@@K&rS&Qf+2H+V2ErcK2PKZJP$ADp1*f&GbX8(h"%(e"
-m!T!!ebleeA(SR9IF-AE&A+8l)5mG)UL0kYLilDQ3!0qBf`rEeUTipM*41VSFi$-
-A(e)qUAKfS(aU3$i"P+MQG)fpJEYE*H'EaN5%0!")Zaj1rrN[Ek0d%YK6iNRG#Ni
-%lPqrk$1b9BQ&e-Jhair'+ipBS3f"E+V,hBYDMr(1EC4-42%1)Q5%"HI,&6iQdFS
-,C4(AKZH1b+#bIqXe6,KQNlV9[p-dHR5)GNC%`I+,3&'!MFKK`q$6PkCmVk)))$"
-Br)p*iJ"Ck@-V6-QpfrBD9Klh5kcD'lG,)4Z2UG*PPDpY+[GD)a+8Q[Uc(4J5-ZK
-(E9DhCHlSp2868CfkmI*0Drl)LqLAe(19SXq2bY!$T1!5XJC#er*Nc-6PlAbkVNk
-f,Q0DT"BeT1Yc-4P6rd6LaVGA&BXZ'l+hkbmS[iZ22p+qc2UB-l!3Nc*#Hff"L!J
-GrEc3+R52Qb&)AdpmaZ-#kTF+#lb)#Ab2[6cNSICRaCJUf(Y3j$*bd)qVGMAIA8j
-GH(k9TVS&#+fQ!(6*hCdSbR9TkCK8c#&4EDlE%P4NUDVAh2d8'kHlS`C@pPF%4fH
-U`H@h)9Z&ITLX6DNdFL2H&q&l"BI8*SD(,Q)G4K`qSiZ#jA!P-Bd[('$I-$N#1Da
-*38L9edBY)lSG'dp-!Zq3!0dC((GqHD%IqB`*B+%J-jM!IeG#Ye#m5KC,'`+[8"p
-riSpMLQb6A3AeiBPijEhQe)1D0Rj2IkJX6#l#EH[X0VS2RKe@fQQYQ4SHY`DR#$H
-IcTFFb#hCDj8$j'R`HbfQ-&rH,iH'`b-*9B+bfF$l3k)NhB,j+-SATP[*E)rL-B"
-&4'QG2m(XS[d5"Fq!F,!5#FlSjkaSBVIbU!Dd%qVGCFHc3ldM`hX9*mUJ-UrTK%d
-pH2LKQK%&Z)kaZEK1LfVS4PKP55JJF&#)[mQ51TPT&+8HYSZ5![S`iFr*f1CdH+c
-VhEKR`1YECkNJirYZ"lX"(B`d1kh-dk&pE%I``F'TL0N"`Ra*AGUTZ"pR-ET#ZIf
-RjQVPbcd'2$4)I1N#QerG1iMAT$+Vck[1$XTBPD4pFLMjmi8+4G'p,M6e`Kf3!,P
-raplmM)FEl1pIGq@2%cpBcFH'5JBpVFFF`Sb"Nip&N!#cNmRL$U#@Dal4r8)*L11
-J+eb%KP`6jakUFq#1NT3Iqf32rp%hc2+BF24pTS2B`-$''a)md5X`2PBYKjR"'IE
-Qd1H8d&@+G5UDe*MbRpB6*mbSj6AJmceDRUS1h'N%0hRD!!PQ!R`("&HUrD*$EM`
-Rj*V0ZG1G!q'0UfBFIm#bqbrk+@'M"bf99Jl3EZUZiRL14Tb$+VkkJ4+)bdQFR0Q
-)8bMYJU"`mHSGM",1Xbae`6p6"QjSaQlb5$4C92b3!*AI9(hH6Z4jY$%5EQ4!V99
-+UIIVf"N1(CFh80TK"%[fa3#QEh$9JS#``a-K#iqS6FEJrl[k5mC0FeE(h64J8SM
-3%G[3GGC%Z#hDE,kc$h%D*CC0)pkGj!M6&@VVF#eHqf)9*5FY,aRkDhq-+S*@J6!
-hf$#5l'QIqB!@ifjl6&p#!XR)G`X!I-jLe--A*!UjK+)lKb!Ie[*90`206``9-2`
-5!N[XAfEBeE&D"LA[dlN6ej!!601C1AE9lB)m$4X'Eph1+Jl#Z"HPhS2$pCG8*m[
-0bCJR$Hq(P2iUG,``j)(BpLSlQ%+S)fq2-p8qk5ET2FJL-S%K+,RBD`FL-II%,8&
-PC`)--eKad5kNCSP4-fB[[5[ZK1D@C14k3Sh[)E#hCf5e*Gb,*[-AU2)4j2j%9rj
-if**@-T1bp%m4C$R93E4KI`S&[VmGYXL2KIBfrCj#i%j62rH%C2d!PP8[YRTb&*p
-'@re4V@+9(2ZF&h[,K5%5d,ji4Aq#+Z2-2X%JpDCrpVE-V,M@8*r2P5F2iGS9fAd
-51`EL)3i4K`3%4kGe(@(D65Vk$KXC0lR@NYEd1CH%pU!hlEU3!"[G'"1d5VkM*aq
-IYX93pR%9[m'@L,-GpDR2q25"0)pDikpI3X05CJ!D+03UH6Aa(fmVkQ(qqB3'6TB
-*bXVR[Qh&'4m'&iX2(MHr[CD*aM&NAN('SR9QUkreB*VB`q"e`qM*YK,f!JE5"8-
-,BAZ1+D4j-#r*2i%TCYQ6dKF-iVlS")Zb22bqr5TNlMILJKmaXb4HTia%p6Yp5&h
-LEPd#@%J$jY9HSJTJMb((Ze#!bKB-*K`c4HArCr(6@6RS86&bFEj1RNq@N!!%&p*
-V3Tqp3j9HNqYQ"U`%0"2qKSdNKJKU")YT$RYCH5L)1c(YYKTh'8EA9@QRT-XVCqa
-4ceL8a%bFDTIL[29`E%e$ZfP#k5hY03DlG'm(#4kM0Jbm3*m83VFeFK8[0AQj+r0
-0jlC260q)iq+ZcCkDhI2#!ZMC9kam9[bX`K`i1&KbPM5l&AdYVr`Zm66jBNHkqE$
-D68L3!(-5EGD2V#9c`bP-Dc&pDiBjqe*[)c`TcJe4310$U%h`b#0I%V4UN!!%d6(
-5hZQ%#))%Ca'f''XIdP,Iq%ik5iM3bY,"DHDA)L'1T-2JHe@DfbfCpT@V3IYqik+
-,QM)h2YBE@1E[CTDk`+`eEI##KMV18V1)4@Nk4&Eq&`R[GrKJKBAY)$"cFf%,VK6
-GrEd3"hKePBiB,-'E`c&B6)XR$l-XV+rFlDM+lb)e2!91#XY6%MeK[KGNB'M,F%k
-N6LBqSZ"KaYX[jG"%RK(NN@Uh+,ZC-#eGjZDIpD9Dr0P3JZcH($%HIC-p*(QYIb4
-&ERa5h9-'V2Sprq%2V,`9"!&2P,lDf,"f##2h5imeMVjF0U'dDbm9HYqDYPPBr)L
--CHJTI`eYU)jR3M"i1BHdBYBC5$&b["'X0UP#$1II6apZY$J6cZ[fZYX!SAqD[,k
-LA4YDU4Qd4hJ3lJh,B54D2pALDfkD'9)bTj)E2YjrAcH8l0eKVcZeriHZ%PMIQ&(
-BRcQLEA5$U-X8PFZ'FKkq'!,ifPDk0PXp$BZ@RqCV4B`IcV#0RLFUSh!B18KhQbc
-EXi4c'a3h"pQ0N!"Y43pUf3[5&0iRS0'2!J2dQ&45h04EHkZ4f%-`eLUMIG+bUI%
-1ZBSA*@T3,8q2NJEHbX#J*@1@k&U9"rLBqHf#L5"G`f8He*'@2NSCAGQcMp[mC!@
-mIUi@!J'p,9@Jk,$`*)1RpF)"YlI&'V&eQDN$%RX&J'3chh,XS19fR$fb*mmp+[S
-Q&M$pDEHY2DZ)3Cp#i*Tc@!TR(q6*QFCLYeX93a!hh,8*+U`AGddhe(!S8*ND3N-
-N53'(bR1R2l4jMFDN@&$((IILQBFfic0r1q*6!bi!3X(8M2d1#,(4h+Hh0L*`3FN
-j,0[+@&&ND91DN!$8llX+Lm!@9fEN8&%TQ!KF!Y3ILMe#'aQcS)&)56)FqHArH)C
-ThcdKhNrrN@aXZV`R5-)%F%`TE%%&m6"F)r)Sl#F4q2fBDkN9kX$rZ@p(bHd'k[e
-L0mjXP,1jk,FV!P)&*SIpr$*XKJerZb0C8pe`LA2J2ph1(r32irF2#'!!0Ppb5@%
-VAIe(J`3HlC3i[0XaT6JL-Nm2)IBbETHdR*4krlKJ6Dk2YER(XBAlRN[1`#P%qS6
-38SYJE[-[aqkqfdkBl0p4m[9K*@,UL#4H9jX[`$$%Y8@2,P"+)BN3aVM'r2q'FZ2
-M#aD&,TEE`[GdDlcPEU21*qH3!0UEC+SRe6k@Zqe$Mm!*#KVl+m@cJGXrR8P2CfC
-e00UU0Qd$eMl)3HUFQX(UU'"2GRIBXlG@P8Bj(j6N(2qEZBSm+R&(i-iAEIcDk%(
-F[fbqh+6$jmB&LJlLGJZ&pMRXhchAk%3T)dN,Na%NJ*XN2,aDFjdB`R-P-FMeN`i
-*e*BKaSeaG-pCKm$TJTl)mX5[F!R5mJPNNUjb*Im+fQ6e,!J-JGjH5N2kH3`%U58
-KF,jcjkM81"FU8h6XSl6-BAMI4QfVrYe1C"2Bri2AKTqMk@F'TY9e'1iCQ8kMNaj
-SAUe4*I%&Q&)R2dClKlfXMQ+N1`YTCeK8%VPKKIPH)pIJ!C03fe*T8Rf!4U'"3Ai
-+#Q&&NHMQUY)1Jd699`X$e(-6kG&"lSYk("802Ve14T0P66p3jPL&acc5efh5QB+
-NA13mPjkA+mTGrm#"f%XEc*2p%p("fd1V5#M,f',BkI2XI,bT,MTVm9N*9G&k0hh
-,aBAkbiRNY*eXXK%@Il!5A'TZMch0+XAfd!V14bXCj+(ZM98cq24SPGMTdLkkV(B
-&$8!J1IVU5@2VJ3#pZ(S1q-EGbfQ!"MZlAIK4HR%Y3eiUZdmiFeH$1ldbkiF8hrF
-brLem`k1-Y6q,GYaNSIVJ`p3@p298PHM(`"Nj6C+%AI+kCP!FJ'(hc`$eF5rN5#j
-Y5K-YZC!!8XCIGh&K$CAic!'+$eIeZ1UYm-65@@1Ulj&HC&H0G8Tq5&%5M-UhPZL
-E+UKLiaG"1hm45da'#kiUK9,QR4SdrDA8Lm0mh%[LDk166V[dhcQKc466@hibQQI
-BIGdfNmq+dr@`)+id[fLm6kaRpG[FTpQL)&qm@6UU2a+,pA-9MVf,I!mI!GU-P'N
-#Z@'f)"BUHDScF`bJI'@6,p`$kj'41iila,0jj$@QJC!!Z$`KheCTSSBTMcI(#h*
-%C0A)-K,$BUlQJ0cJENq49q`JD-LlN8V6``I1UZi4QGK+'G+ZNmZij%UdmP'cqKJ
-,AHCSXEEqPH1p5ANBliq5fDD#La#Sj&dP%4eI+a$Ldk"-'A8``6TajQe"%-,a!&e
-ZHNcaTb4X+'NMNU%pBI4Fer#!rFG3CIK$U3j8kN'22SQaTfSRa4'fYlmmiBZ4[51
-'R-H-CqRaXT@3!((m9P+)d8M--%0qJcK!'GP0heV4albQTA2-)FZZRBd@M[MKDi`
-VP#U`#$K6",dR(-%(**,i2,N&GT@hZYCUqb!+R1TKYlbCTjV(c9$kTrLaKK%K#6K
-AJ(8X#!d@Q0%eS3VFBPN3lhNAimb1B)T!3k5qK5bVUP@H!Q5HSljf[82SX$lh5hq
-I$%@jM`6K62XB,fZ)L'L1dU-bpa`&GCHp823b,Ghe#%#9X$IZDfahNe-+d"8[cJ+
-@MaeA*YVd%*9UM%Nq+qS'ABjMk3BZUmqJ`mGGLmF64ZEL%[fDYq',ll([fSaJ$H!
-bSmXfNDElf4AcD%1,J'E@G*!![9A,2,Z)D#MpJMi6M9BBJarD+5Ur1TGr,YkcVh&
-qVRfYRijTEY$Ve3i-4+JGZK[5-R2rQe[9cNi[Sj9d0XaMiqC,A-%q0j!!KD'%cVP
-CmNb[Z&e9iAj`bA(4p65'KPq`&B+QMB9CY5B6b@DLi,SM'[6j`JdjS'AS5M1`0*A
-*rp90GeSGhRP2Pl&Q`k&d*bGdjbhF,3[fI'3G[a&@$,fN,V,DLMHR4$8#%2El0&q
-#)8LmE2SQIEp)J69dNV@UjA53!&J`cp+lN!#MVqKfrH4'["T,l8Xj*Tr-EkRKm-d
-2R4iA1(#cpB+kjTI!%NVZrh,9H[@`[LGCCH+-)MC%pIF8qYJR(&c%ArTQR+,NMSP
-,P"f)*P"X$+K@f2!LF3RlGBVZc9"1X`%0r!T[T592)6ZLV*l,L1JiFk,fQDe`8l8
-#e'F%Y1A0KUH[1HPmHQQk)XJ`'!++'(GIP&K0'(r-8G8JUD54aTc#21ZT,rpH!+B
-+9NXE$qSP%qb[L10A$a1F@NSQfR,hSNYP[mVFl+rZMQaP-3&A%L1adb2Q$Xq+%#,
-aBN(#N68%ReGXr%I+4,-@d(chfNpEeq`6SbYaaUK`LKFKKm#MBqATNNp#dGEq6II
-I,)r4FK[2'hjVPN8b&i,S5A'-Y6df"eK#SAI&b0VbSGZ&Emmk8J#HS3(ReBF%qVc
-"T$aA05HY2KVmH,qJ0@UX("JMX'hPXUi!@iiT!cDTiD!8mr###4%R4dlh5pU5P[h
-Pjh$b-b@p1Q"6dUKh"BidY5,N$80*H-0j[3'*SU0R)"-,VDB-'eNhL5b`YV5ZaR0
-GI5eLbp69E,3Pje(DGBT6-'#+*S!"@(9KE*)jr$mBlh6%4l4mb)pXbJdU3MEc8@l
-K#j)5R08HS+NdA$-H!UF6)Bl0QVeh8,0el"*k1iANi,cqX-IQ3X6lb-3eUS[(SLB
-#2#aNQCKXQ%ADQECBkA8!G(@jpiq)1'9%VY+HYa6"S#TI29NXmI-XYT0aE6321bH
-0BPQI18,"BAK2KGhrY0j%[BkHYhE96h%T2m0$`eM*K6%26!,`G)r4rN&RZ2"+jUR
-5Jaf0+aMpS9H0",i'L@ZeE!d!eqjKk-YV5F@lG-(E"%,k5Z8MLjKYEfAS4(SjfDG
-kd&EB-erh2je8PB)jZh$d)`S)jGmIP[LVN!$-#K3M@B$MkKk0&13HFZIIB8@Rml+
-S`)+#pE!eGh,*[cKdSDQ%TR[eH-%a)9fS8h30VeR%T3Pq%I"C16HSYar0B[&X[0%
-qmF(,jI@k)kd2)qh1)T(lJFc$-U4hSa-f9Z@5p9$8JZ8`*Nf#ZFlDA-afm9He&)*
-HBprE$9I,HEZ3!'PU5Nkp9!8d&2G`MlU#NDTKES#b%,Lc4KU9j!I3SH$-UkAL#kl
-*(C!!iZBF`H"0q-9p("lpA[YP@p-8@XZUr&Q)a-f4-G2E9&j)j2RI%Kbij9-UEBM
-$8'@F0k41hUSTlpHapq)$-ArhN`AFH%*le11KbYSH0QK)S,h&-`AeNS+Dq$3!#kr
-4hFJ(-6hhY(4*hELPdb119fd1P2()l&5'k,@538pP#MK3@*A!@6jPJBmGVIf!j,$
-UD`DS15eil1Y18rBG2b$E+"X(PI[[19j$1VF1L#bf"h"2N!$,VIac3e!FrAG,S)L
-3!%BI4jaHkffV5FBlppa`'L)(Fl$JXRRUH(R#qDH'$R)mc[`$")#@'88UBH&k4C2
-X)@VkPMNJEmJjK#$-iY4j#p@@+eh*R%&2kMlbFR90aPG5L0pM'Di)rDVJ"hMm8BX
-jRGpLbDDZ&$hdCLN@$h'J"p$If4X9(4))`aI1'%e9cl9E4XdVcD8jG[@8VEMeEp4
-'Lp6kpHqMqaiCdVU%XNZLheQ3!1Fi3d1QETF`@@6efN5Y0`"DEB052XfP+lP(KFB
-qB@I%&Ufq$lmT#PY+%FY-k[p%%,eeJ))C1`Fh32beQfV!kLV*MX&J*$9AXDDc3"L
-J89HLQFFm[mi(e2P"0,41%Hk(V!dBqLESq*bb&(@l)bK6+Qm64'QX-4U%T6+[hCe
-9)DMhVb8G5(c3PUkS'%9ZMK*RST8BcXQQK(rP%,"Z3rVjY+`'+Irc8T33BBM#9Pi
-!lqaF3"M@([ZY8jcUBMp%F"IAqCHSB0FjD8Db5@pabp%J4qq8!"RY5qm+D1D'3S2
-ThPUb$b,`J&Q`ASqIS'M1Bqlf6!+qaY42aPC#H%P6dGFQb1A9,4ql#Jf"j,ZjBbd
-9M0rL,'B-XAE$H-kN+"dfE!4YRBhc%UZVhJh&qkF&q+aEY%C0$'Y,Yf6GSNa!BD,
-m,1m9CqbdSc`8(hE9!M#h(BRE,4+#*Bre,jIFPqUi6iJkp"@Xiibjq3`0XLi"iC5
-jD(`KjZq8NU#e"!4iDIAG5ei!-@LA92X-rBE*XaaL%!p+9aZFIp@S)6FQFTTDbYT
-1%bJ1LpAl8aCI`B%lq3Ea)#mjT&3baQ4@1Xh3qKTr-`["iRjMALdMBL,`'+l!I1-
-FXdTDT%&8cFR53)5VPe[P'RCdm3P8q4+hq`+&T4YKVh'lVUX2k[HfL(8G+J66PcB
-(U-&Dj*INm`IM[[e$9QUI0ma@Pd3pk+i@JI*e6!$TTaQf`GV#4a$e2Am8@9Z8B8R
-mkmrr,MIT6Z'V&YT)Np*U-jD"Dh!U,ZZVqVmdSX2E(rPfleIAk'FE&,XI+J'IS&-
-f4Nl0BL(f!b+9lb)DID*$TfXcH246$M5(q*X)$mT++,5aiQ,UEXZ0XdH-Qa24lMD
-CacZ-qk#%rfQGrD1YKUBNGb*Ij`p@NNSV0l24ClT6`IP)$3e(jCAeqJS#(*NCQhC
-p8(QYCM4)dQmb'LPbJf'r#"%A#KMQFdaD&kAqQja!d*hAU!9Dbb&5JCDGfPYdT#V
-925b-V1,)2QQ(IVL+-LZ4B%ILlaVNl8cd3[q8C49#-6e6'fG@+,RF`4@Hfq$D"%k
-aSRedJ4)%p'IUAfcUC'c)m[hJ$%V$#S+E64l'@D-kM4qmF'6k,G[ZZAdT"(B6r%$
-&ZpZ,k)#$a&1F5`2KqRlN*phCM6((A2m6+TZcIFFR)(VmS0%ZmI`96E!kc+qc0(S
-&'K1iCVNZ-8'QA9)E1NjGE`YfRq3lG'959P)jdeqpr5+kc(IQB5L"hC,P"Mca%CJ
-rNdpp3`5!ZUidbK(6@Tia!0ZNLN)FA"1Gk@K*PZkch+U5T6D1M90U8TB+1Z8-rh5
-@a`@GiUldCI62a+(U03qj-H9&Nb'k5VS3[N5L0I*#jiA[N!"&JKlPNL(T@%d`B'Z
-BdGL04CkJjrGJYrIqV+"`'XhV,2X@'GmFQSB6-0AI4i+`LNa0N!#0Al"G"B2K$e@
-*4mYMRPJ-'-fpV5kb#X9#fL4Fbh@B1l*,UF0X9r0fa`!3eGaS[FqU963jTCR5*PG
-jB[E11EP(NbYfUj1$45FCGLJ,9E+[FR!j5INbP0D1kJlC6dKfRrr$Kl!HFJBXGlJ
-CTU6J9NE1b$3Fi80c!iA1*ZKc%hIX#mqPUl$F6@Hjm4,5IdK%6%kqec,i'R0ZZe9
-(A"26ei(J-lDQSU@LS(#I9cFcL'%HPc!CJXa"YmhheQ,*P'JdA!5N(8FTMc$30G5
-afF[F#GiL-ZeV,PSSKPXGb"f42qkcaHa[UH6ICqBKamEBEe`QYk5M40-AJkDe![@
-brT-[ccmAV2PI,X`ZhSA3JfALZ$qhN@(i%UUB2lQrh6qVh!@rB$Jl46XX+Klc&PI
-[p$&(A"0JT6rp54lMmq`V2VI$[9XRrkJ6+6AI&eA92XF*r&-H*$Ei%e905G%c%[`
-(A44mV4h$Rk8+)'klVl%[!-$EIFr@-"mVjl!4FUMV'*IAJI[MS!I![#183)%VZKU
-iVaH$SRMZe(R2F2%'F@+N#rX-IbMbCS(hCIASS-5$JAD63PNI+1EG!XT2p4VES*c
-C4dLNHDXD+rp())Bd)I@fNKQTI6cS+S`1Brk2"jkb1X1Kr$#iAA@A(C)5i4r8c3Z
-66MRqA16[UfpY%4h9+EeK!iMEr%b0%klX'54-mL#HMSRY(GrGEF5RY2GpNPiGE"(
-LLAU8r,I%6L3LUL%82rU@Y!DjhS#THaZ1ber+PiC4h6f-mB-8C9%lDYVmBeMd0)P
-E5(LbIDL92EK#M0NpZJe&AS!k22"ppQ*APpKm6A)HjDEE(f3GqXqMDAR39E[db*)
-iRLEZ@j3@-*0rqjiML#Z[)0Xl`L`GpY`*G)3Q-4@PMDqK1`Mh(fq&H9qd(QDPqjY
-F[dYlX-,5BPER$8-bm$NJfTZEa$+FJM[#U@R"mEPP9qjh@3MPdDMZ$9hX`d"jp+%
-B`Uhr(k@2*KH%paAI'dFmd&6@hUIl&%*-Jha!#5N"i0QVJ6Mb`AM[XJV(A28VQI"
-NR,KjrK&T28+i64i-hB%IABbSei&BjLi$5MqE*JYq25aR@R!FDU*SVP9h"C6lYP5
-FhRF5rr'e89(rjD@PH5CIE$rF'$%m*'Fj`G$9Zb`E-X0pSpGM0RJ8`AV$1U([e-a
-l$NZE,JZdpPS`!ck,H)3GM4i9Nf(M&[$Jq3#d4DD3!+1r0afqSqT@HR!Z*+aErFD
-'2kMDk0`mIiQ23,,*)5#Ia2@Ib9Pa'NJPb!IR&3R[LcM0JJi`98#'GifJ$M'98hL
-Xdk[eJL@0Q58SI"i4PN#Xc0G'D,Zm%%5E!X)*"4im+ZZ!&R4eBYUCiPp68bVHHJl
-F-J8%Y6A(-$UM1AfQ8Q3-%&aaUJlTMV52aK&FTldCjR3B)"NDP&pK,DPmH#T(IlA
-e3dSU#[k4Z&VHG8'C2f+6[qV,I"`N052fJiHPL8XlHC8d'Qr4U[ami)k#$FJp0Sf
-)G+1ZH3Akm`T0+!VlHpI#0a+M`9Xrc8,9IUeAE+jPQS&5-f"8DpbBMJIk"-U-pRU
-T&a)"L8mfFSFm%0SL4TCKe$UNV53D5VmKKR90lca6Cl@Y'pA1BC%R8'Bk3ejjI)[
-VK2SmVQqIY(rAb#!AUp+fb[T*-8d8*PDTK!%G,B#H0`aCrS3beGVV$J-m#UfKde`
-fcmalF&GJP0ZP2C!!M!mEe6E'Epi+Jieq8"EV2aQAF'bjf-S-ZJedB-+Zp3I1ah`
-CpX8QbjI`32TKj%JJCMkk*QAC*N"VQGTr@[R4mF1[qeIVr"3eFG5EFC%4RL@#kZa
-"ILHkq(B0f5Th(F`VdFG5a%8$8kmLIiDp$PYahK,GKE04U@&BiaFeB"h*d+dCUYr
--`&b)H5Z%jbPDrlFim39@Qa$T,m'XY5SedI!@+'K'RSITG"$m6FGI`S9dhpCJZ),
-QB4TbM%rSTLQdl(D&2C!!A"B)Z+K++1I[5CiFYd(kdqFKemRc$h#4FI6(fb-c#&Q
-V3jkDB8I9CZY%NZG2qp(l+%2(IJ8#AP1MV40Z5S0QpHSPB%U,13Za9E@E[L5,&Le
-)&rjKcZ"bN!$V'341a6``036h*IM83mB!mbrUSZaT9-!66qL3!0L8`qR*i$HqIJd
-&a8j0RSZq%`9#&PYP9("%rY2S@9*DRC`(#H$SLSbV"hSm1rLmHE%U!3)'j%BB6`"
-F&-Xr%)bZpGBCU%Xh&!5LXF)lXP22U25kTh5@3CeT%QlYL@3CkeDiEBbMEZDBqjc
-Eh3$C$%l$,-Ihe-3ZQb5+0%F4`eqGmbH!,r-HV)ZTUKiJ!$9'DCF*DH*aQqT99er
-8apS@i&(A1*lAkM`p6,V4BeJ["%K&T%rZhNaXR3%")P'qkT,T5a)3UVJXAm8DArI
-@B(VmdC`)dij8`P5YA3(JP-XFB)`$aX9[,M'e!Lm0hRH0D5UH$SI2QYGHD4(K3Gd
-eMH6(Q[504%c"@GVbU063E1)6m&mQdld2I[*9i(k@"pc'edS*,iq@U(DH0'jD82S
-GR2Y`!EMf-DICjKNqQD,dp6iJ[3&pbb*l"X&KK+i9NT3QVJZEPi3a(6T@6h+-"AN
-E!60+`Pe-8!3XSA,&cCLkKX2&SDNf88-20b3`"*E1q2)F`,@&Zc(L(@52-hm&&d)
-',0PJ*LZ`r'FX''0'b!Fe'Pmi1Sl5FbKmr[U4RV4Qche"3P'q,1LUI3B[9rQrMrL
-#RBk+B-2G!HJl)"9[hVrkFMXM2Q,2G#)A3Ir8(eY*Prb5#,U#Y+8VH[%MVFM)kPe
-X**AaSC0I#dRSUHVi!Fh4"YF0#3Hk@Q*liGG@UDm&E9`&j!bS#VF8f%Z[06rfElR
-&Hf+`(dLPBG+0Uc'+qF3LTA3L"Mc@ApX@jFm,LUUC$c,k%KDiB916krYj+%R5X22
-r5%#Nim#G""BXK0L[U,FmUFP%1&&Z))LS12k0H1![+2@S26#!e,b"I$'"E3Tl4"(
-#NDh''b3f,L,lYElf)UDe2bpTSq"R(c45PLV*U'@5HqY(jkA&E%ffdpJ2`&YFFFk
-cdkYADS$@(A-+QqI3@aQB9l!U$HkXBpR8NFSj38-a5G`CMq%lMf[!-Tl2&jdFjjf
-rRNFal+SQ"[--06M00F5Q!F!BFC6eJJ-fNPG25i2*Em`!kh(534)LC-@FeFaClbp
-@9PiXbpe-9%$A[c!k2$'&)&Dk1TL3!#!"A9M1+,Mll0Jr95[SV#HG1PGZR4GqDP`
-Ic0%)mF#)H`c5RY(@LU`[V,#qYN,96k&M[ikDEhTF(2+-34cP-mH2Z6K1+'mEX+f
-9B3EPS&[kEai,CZL$%-9lJZr@FkM8GIJ',A4+IFckG[dGpP,)Mi+&GA`9$TN"T0D
-j[6#pQ)#Z'+!)V"4pqd%JJL&YNQpi`+@3"!%!!$d!%,5L@2HdSPMh!!%2-3!"33i
-!!!(%!!dF*J#3$NeKBe4ME#"548&%688!!@Xa9%9B9%0A58@"!!#!!B%!N!U!!*!
-*!QX!!!%#!*!%$`"#`G6Klm3F&9#AHcaI4ZNj)ck,mGLZP-K4adD5)jSYi+l3#iN
-YM&TFJ,25UG+$3U1i2@VI$e)fIF#@e&cH,F)bqLS)JIrG8Mh#PlMqk6*0,c8dRDq
-5UX*VB454,R0a2SrC''MPALCdcU8MK1a#ZZ3,*X&Z5fjKa"[$AYmLJk[8,M*djHJ
-ejX+&S"XQh3F`96Ge2&ZJ*q#FHV#adc&3'4"Xj6E`+XJGkBb8JZX'#IIjr[,4feP
-CU2ZBI+!JMQRM',!TK&(4kB4rC#%Mib(LSk*p856"bb,"p,p0a,U1&,R-q*he8[c
-4ir6b"53-dB'm")T`8NM3jZMG4ZAHT3Y9YYqfN!!!TC!%!3!!2!!3Y+*C%V5L@4-
-!!6qG!!&#H`!!!F3!$,Rf!*!16@&M9'XJ8N9"4%e&!!(Th94&@&4$9dP&J3!!J!)
-"!*!+J!#3#3*V!*!$r`#3"!m!3X(9#B)c4Se[0J-"fCEFXLfeQ!@$TUU)bed4'jX
-Z#XFfYLkl2@%X0Td40$r@p#3*[h(-A[rE`&dqI8aGGmXC+NkJ)+'r&(%Aep2M6fN
-9K5$1-4I1FJX[9K8ID4m5lpeAbXc*ZU1R[$h#G@a`'@BAAdN(eX`dV'kEb&$V0XE
-TFY86R&B9fXlNqNdrGNe4ZY+(p[%lQKL%4$dZLj!!qej2&J1,SD+*YMFD+YF+!$a
-KBT(La`lK!j-[ekcr$VrC5dVVLa9U[JNm[3![+@6&,&IH"$2S!'6RQ8K8Um13!&i
-[6eHXrISKTbKCMe!qQZCF*3a[Z,km&j%YjX0mr$N&N3kV!!#PN!3"!!!j!!#hmlT
-HZFSK(`!"33i!!82c!!!"a!!*[[X!N!j0Eh*P4QPXCA-!!3mJCQ4bF%e"3e1"!!&
-!!3%!N!U!!*!*!VB!!!%0!*!%$`"#`G5+G3Ce,aL9eGK"FNBTYEV2HJZ`E2eATDA
-*5IH4ZB(Ap@D(1R#h&ieE&@k6iI!l5hKC-ArHe[CbcTL'0kVbSC(6$9q%eN[BMfT
-IMNPT,hjp(a5HQ%rVq5YGKJD%38&r4SaIXf9&hk`!99Y+$q0JMcRZJ&[`GB-Qd)K
-59biH-[LT94$S9EDk5!5Pm2LDrf2,`E56TMrC2dS'Rl5$Jc9IUaYR%DM%4hp6N5,
-%5$&l[C(r[!iLGA*f3A-r6&(bL$1`f$b&$MGVBCZmiqJ6RSBS5l)TbST#TKYEADT
-E$dd-M0Z6DBU%$-k%9N-Mf6qBSK&qV-kBNP#24#d'aMZAXCY#e)lBXBFhY#ZJ!rA
-r8+@3"!%!!$S!%,5L@1kdSPMZ!!&#H`!"453!!!(%!!TV[`#3$P4ME#"548&%688
-!!9jQ9%9B9%0A58@"!!#!!)%!N!U!!*!*!Q%!N!2&!*!%$`"#`G6)[q9[ia5rrCf
-$YG%282R4qUP$0pePH(6PU&["r*U0[-C1YZ-`5PPf['Zq1D6ph#pLG6eHF[karp#
-8SjiJ(LI&RZc[Rk62Vr-DFaaL4)RaRqP5fE+Bp[P3h"'+#bQlQUIGaNA-RSGh99'
-c!+eF#9Y&j5FkM+H3!2K)Mp92HRk86jUV8q"NrYj$(pCRUhEZ6TY(+@TEAm[AD+"
-F1U(M#K4V#mKX'&kV2HKPKEkZMeB(9k0L"dR(+SIY(r-BCbh5)b899qLPN!3"!!!
-l!!#f$CC'YM-2dJ!"3r-!!8Ed!!!"a!!,T9d!N!j8Bfa#6d&6D'9XE!!"N!"ZB@4
-bF&4ME%b"!*!$!B%!N!U!!*!*!R!!!!&M!*!%$`"#`G6U30Ad1'NYqHG`L&SklS1
-D%EXE(ZiNlASdi(mef&3#82L3!+TreYT("BiV8)Ia&0B-d9J[8`R"ek2'RX%P6RR
-RI4(![Rd,ahc-TI6EFP1U268'Q5Iha&jeHq"qf,#ph3`6Ulp"$9br19SCN6PHHe1
-92X9L8mfjP4+jHK!QA![U3&"L"8GjacfDV'EF(K(B*m-J&%*#AKcT,3(`Ebe8j!6
-C"a3i!8Kl2YpM4LLBMVXbei!"k%NZNe$h&#SP+)U-2,[a1V,Rq[SNN[*1Ve5fZBi
-#m+K5(lA6[Y`MkQMmEHfTcPADd8eB"jFT)lM"XST1U[P[9X5)E%&@miP`K"AT[8Y
-@A`KT&-6r0Tb8Sa+k-6$a[M%b+93DcCNB1%h#-qC)0$0r'kGJAp52ih+0Q&GF%+d
-!BZaX4GN`"%%T$!-Xl`LCMV"rLjmLqh`1Ml3$i#KmRFf2JTVfrfCC,jeqR*5@`h#
-%!+@3"!%!!$J!!,5L@'QhASKU!!&&*!!"5&X!!!(%!!K95!#3$P4ME&0SC@aX!!%
-NUf&NFR"8Bfa-J3#3")%!N!U!!*!*!QN!N!2p!*!%$`"#`G5f)h82m"l-IhSNb'l
-Vh55pGTYQ@B4P@5[m-K-0"3'F(9UQE4"AX+5-Z,GrH5-01c9&`T'r(VTLHV@(X*f
-XVl6,Ur8$f2LG[88`VESaiUX%X6kABlH!dMGq6bAYTRS`"GlZaPI[0S'%Nre,hmA
-rSkG"I49F!lNNk2dQS(H1aKF-%l0VTVkrjlcCb+*'S%NkZXN$K##Q+I)-RT)@XJ)
-Z!&N&56Ei[GPj3V&5I!kKY3hMf$KeIXDB1UTPHR5#J9S(c#!Z4Hb,FeZAe&C*Tf,
-S4'HBj2'ZiMrCK)FrXZc`m525l#Ef(Bb1'icSL,hM0`DQ@c`V`Pdb'f"&6`J!TC!
-%!3!!1`!!Y+*BaEE0Va)!!8Ed!!&*mJ!!!F3!#h1F!*!19'0X8h4eBLjXD@)!!IA
-169"-4N0A58@"!!%!!)%!N!U!!*!*!R!!!!%U!*!%$`"#`G62PkF+-[53!$T8PB9
-*"iKG58(Y*8i@52LT1M(Y[Bec'2M$-GP)MiLEpqF2LS)k,KrCee[UcT0EYj2Spd4
-VUa-P$`2UAq[HJ'(#*eMdfBEC5'5d1[J('eV&"0#QYZ1@mBV`)-djCBMm1$jT,C@
-Vmj)JGFhTJ$0kH4S*"4VYdYhK6EF0"M`f+H'ra5Y8LIZm8MmcDK3GZ8lJZ"0dD*r
-FV39RAY!P2DXF#TCmpCLMXSL(j%3IJXkSGM50HibXU$&6"HYMSD5"Gm5i-8NDIQA
-*-NH+%c*hL%L)3MPFC2$qQpPB#h)Vr4QY3C5RNBSI&GE'*)%`&jlZYDa%iI)2'M#
-++a-Gfdk+iq9-hL"l'P'88',ML2MHY1rbL@'bl1ZeKbN5NDG8l#'8PPH&!+@3"!%
-!!%%!!,5L@-DfcDm4!!&)@`!"5jN!!!(%!"&(I!#3$P4ME&0dG@*$4Ndf1%XZE'P
-L!!&*$Ne36%C$9dP&J3!"!!'"!*!+J!#3#3*m!!!"0!#3"!m!3X(8SX#rFMl+Shb
-dEq9Y'85q-+ZeAp``H)`Q$aDN3fmdmjP-Z@[ppjaj5)8EVYc#1DEm(ANaANZBmSa
-mGYE6*KbrqDQ&mIm%i"0qqDZ5Ep0P"Yk`V8M5QC1#[L4AIb-Q43K&$Dm4QmqXb9a
-UL%,eViCp9@lrDlr@2H4`6K(i&LfMiH)@MI$k$SA(`)M'"!hm@C!!ZIk$%BEcPEV
-5jaM!0Y"LBNbBL3e*0kfTQJ+%JYEqT(l!mJ28b02qNCh#lGF[M2#@+05m2qLUNpk
-SmS",KhFAC555D26)f"k5H&0m)4TSY1NDCP6Zddf)mFbhYGEi*c&bd5X4N4h`Ar+
-iYf5Spi38&9jqkIk*hY,3H'eC)DBHmfi#8S3Z*H##@[D$l)9,&$Gl*(H2`0"6Np(
-9H@jY(d2R+-MBTC!%!3!!13!3Y+*C#VB(daJ!!8Rb!!&-q`!!!F3!#D3J!*!19'X
-J8N9"4%e&!!&Z[P4&@&4$9dP&J3!!J!%"!*!+J!#3#3*I!*!$p`#3"!m!3X(8iHr
-%(%"8d,`I'0BH"mdEe(UJqDb8kV(4AF9rF,!FE$D0PQp`r$`b,'P$bR`+c)a*`CC
-+Q)39!XCPmMeQbT2AL,8LcSNBX&6NSIX6@HqF!&#kZ@6JG%9%4i*+%U5VHMi'U",
-1Ti8MF!`8V)PCFiiX+JRV(Y8EaD,[6ZE@UB'*$[Zq3h&EK0m[a%lh%XJ3X3EhcZP
-krQKlJ4pN2)`dqKaEJ3DpE6+X5Jdk@0"fGX,eJAk&mi%pC9f,Z*iibLEAddF)TTp
-$U)0!""'jRHMrl'IrDAiYf,`m#6X8*E(f)fKZXVd@b1H-!,'&&'USr[K%BYB$aD8
-VJ+@3"!%!!$S!!,5L@-Lf"p-B!!&,Q3!"6SJ!!!(%!!USmJ#3$P4V8h4eBLjXD@)
-!!8)E69"-4N0A58@"!!%!!3%!N!U!!*!*!Qd!!!%K!*!%$`"#`G5L`,pJ(TX6KJ#
-4ipN)4FP8kqhqhA&KZ-GAJqh1#EM"3J`b+,YBLi(EpimeK4pBSbM,"[ld"JH*F3+
-kBND@frI$h([6@4rLGp9[l3IRJdM&k+`C"ClU6cQjqQHUUJ9lhC-XR4TY&XNaTAP
-mFZ4TDQX19d,!H"(R'ka-jhL@0(a-NhP%LeYM,QSR0-bZF@ZXXPB`&r"1Gb[1NKj
-'3+jbmrJ86@4TbfLXPSPfm6(C,bUN$6jG&KFmS'Lr`IA#,(Z%NVDSZF4h6G[F(JU
-Tr2LAhqdV"JmBSFale1UfheNX(+P&!f0$Qa`AYYL2m9i9a,M$-L2*miMi'FpD*LS
-j315MrQX,8kHpXY@fr`*)Md+h2B33NKJ$Z@)h4phZlTUYHr@!TC!%!3!!3!!!Y+*
-Bb,B(daJ!!8cl!!&2k3!!!F3!%'d&!*!19'Y6G(9L3dC00MK,,QaTBJ!"aE408%a
-'3eG*4B%!!3!#!3#3#S!!N!N#H3#3!qm!N!32!%,"e,jdKR`3iTfkhi,G6T9caZY
-BMTjT%QBTd(CE-$Na(BHN1GECNiG@+Td+HEf'H+iq5PRQ3qBrGdbQYC!!rKXeQGM
-"YE!"H4rhJCB3D8'*LLXSZEUE`'-`@kG*pXBaF9"*RVDB4qF&!mYYKc8KQjq,XQC
-c*,hHJ'cl0fHZYmpLGdYF,8TmP*YA-N4q)60PT$ka4&d855SaN!$pjT!!hR63"a@
-2S)dp@6mKR+%rqGd-$+A"R$qHQCFP-e3Z!r%6[hBH[)(i(YId[aY4DkPLJI!#feV
-#[NAreipm4P-BG*Z3!2rp4*rP1Pq3!'(9-P2ePGiqTB#PN!3"!!"&!%#d+4kjZ#2
-Fk`!"6SJ!!9N0!!!"a!!9kX)!!9"5!!!3j!!!#,X!"e4[Ef`J3fpYE@&ZC#"-B@j
-RG@&RC3!!r'N"3`!@!Kd"L3(!!-!"N!-1!(`!AXY!!!#!!*!(TC!%!3!!0J!!Y[&
-%T,Ea4+3!!8rT!!&4D!!"6qN!"LI!!*!1G'0X1#id!!%cVQCNFR"03806J3!"!!#
-"!*!+J!#3#3)i!*!$VJ#3"!m!3X(8[R4c@UAXkj+@*q"UK-hNc65P8qbjCBr1eSf
-69plRCdMLiPSY%-'P[pqk$XZFFB42'$j`[ID-Jl$*c8G&8$Yl2Mkb`IXbZLcX"*V
-kXUa$%+i%)2bCbri3pjiFfDD[*%lhXQ0`5NeNi[E9*DT5#"C-S3P1Ta'S5aU#Y0j
-%5Hd'D+("2iX1hAZc'PD@P`8"8&l2CPVZ1qrDXTVjCif`ULqTS$k(R33-pqV81J-
-!TC!%!3!!1`!!Yqe)blIY5-X!!9"5!!&5L3!"6qN!#bMl!*!19'0X1#id,R0SE')
-!!@fJFfKXBP4ME%b"!!#!!)%!N!U!!*!*!N)!N!1d!*!%$`"#`G6dM$A-(U0qfH"
-Urf*A(dP4pEQ,,Kd5%#biNb&H%f2JT@1)UiH0C8*XP8+ZfNKGS[-a'Mp-B5c[lI0
-Bj'LVE9D99j)4T&[`A@'j[@Q&cBX9#*ZRc9[$IfkqbY,6*DHL&f1miA0C+TPB)Ja
-lL,4E[M$FX*a2iCS0TJYS[&3%"5KCLF4ZZk-*%VR8+V4r%mTf5-fr)rAj5Dm1E()
-+p5NDVDFjfPGD3$l)S(jCV4I-!cHbpZ#PN!3"!!""!!#hl8M,Yqe)b`!"8@J!!91
-k!!&2k3!4"U-!N!j8Bf`i,M4$4Ndf1%XZFfKXBJ!"pR4cD'aL9'0X6)%!!-!!J3#
-3#S!!N!N#6J#3!li!N!32!%,"e-LrjA`3ijMXTZfAY[8Z53lh1%6Tbc6aP["rF#k
-)mMCi0DrJ2ciLq8Y,#&G[9`p21N9e6#rLBRDLe'K)ljIPq!e3E,13!,MQrjrpaTX
-%%cdNG!KFF&'maBV!"YL++dHcPC!!2B,+%)--GDNfhRfRJY+`iH80+6LdHG6lHlf
-Y,EFQk6HJGfQm-6BTLV9+N3Sa1NYaK&Med80lCp3H$f&#k6U4L4jElZa%,b'+HeM
-'ShR(%pQ8ETFCH8-"EI%jX+@3"!%!!%-!!,B0PY'i)pcK!!&5L3!"9B!!!8rT!"-
-lb!#3$P4ME'&`F'aPFf0bDA"d,R0SE')!!G&#FfKXBP4ME%b"!!#!!B%!N!U!!*!
-*!ei!!!&4!*!%$`"#`G62PkF1Z,EVAc+CkX[GaeaETl`6VHiC$Nq(*VCfB'1jSa'
-+V5%D2ip0bXZ)F#ABSfCK0$LX2Jqm$cV3a01UNrS,YBm"08IQM203Dm#ap'qD4f`
-E!iBlB&)d238SR@G!jpASDG0$8l1Q$(,)r)I$@k`L*N8lYKjjMiD`FLXkG"UdS#p
-KDSR%i!2RNRdHI,"V,M2a%STpZ0)e'DmR9@UU29BS3Rjd8,!Hq9+(5D@j)*Iqr[!
-%(FL1R6#e#pC6q%GP%`BJ59eJ)cq92)6SqaUrB6c38jc19LdKMXf,&kUHGPrU#U4
-B6$8#6(#2`'Z"f@Q1`d-XiN'99BqHI0jNp5mRPm-1'YG)kB[DEXXerd'NecGCiAV
-[880M*a6re4ILF4EmqPjbD3r)fD!F8mXp0J+pLR3NP[TLbPZ9,BVS0DFZe!h0dNc
-S0ljREYR62dJ`jNE!TC!%!3!!03!!Y[&%V,Ea4+`!!91k!!&@N3!"6qN!"46h!*!
-1G'Xi,M3!!EM8CQ4bF%e"3e1"!!%!!3%!N!U!!*!*!M3!N!1U!*!%$`"#`G5qG%+
-%4#m)C(9SfdRYU4Z58$DILlN3p+2[,h&HRVTjq543Gp-r(MArFH[[H-e'E2bV)4&
-b#9bC))NK&%9`Mi(%mKa[2H98,eH!)b`c#D#XJQRm6j!!+NF&SZ%q"3`GjaJ%ULC
-*)k(UK-4L6@X9DbcpNhVel$Kf)b1!%jH5k"&fAFSEQ8([lei6HYq[HTAP&!VX1JG
-cI6!!((T906L9Gh5R6XF13NeQ+G5PN!3"!!!k!!#hl8M,Yqe)b`!"9B!!!9HZ!!&
-2k3!+Ikd!N!j8DcJZ0#jcD'aL!!%EC(0SE'*8Bfa-J3!!J!%"!*!+J!#3#3)r!*!
-$X3#3"!m!3X(8p)`ecqr)kkT!lNaB@b9f+BAIe"8r*'1+"Tj1!bM%+EF`%S+E@dS
-2Kj8+M29E!DfG8I)+Yb4JEl#X*BNcl#jT#K0lPN1jFrLaQD8rel$9rZ`cYfFFME'
-G+qT**)c@Ir(I(0h%VSiAh1`4M&qVPBNp4RQDEp2&Url-UmGbcC8XJ'rT&bk6SIk
-E1)(Q('&A0%[a39l1$kk&iK)ETq,'&b)f'L4YM#R6@@KF@JpTMe1!TC!%!3!!3!!
-!Yqe)blIY5-X!!9D4!!&Bh3!"6qN!%*1)!*!19'Xi,M4$4Ndf1%XZFfKXBJ!")9C
-cD'aL9'0X6)%!!-!"!3#3#S!!N!N#5`#3!ld!N!32!%,"e-LrjAMCcTM`5,bHd23
-LK1ppdR3*Yhk[EbB"mF8EE'H@1)8&qe[##K[Z8V,*45'4F1YEK6iej8P!"b*%eBL
-2aE)GBXI`kd2mj@Z(,$dp"eRB#I5"H%p5)Nk-4BP6cr-R)Nd5&KJ+E1eNR9"dp`N
-CG9QEDi,(0X$MkLcm'N`,jM+,ke"j`P8+[!eQ5*cKQ-3`$Z[$NdVQLiVjY8PTSDk
-Q4P6Df#djpbACRd@A9fCfhDX*HXqF"Zi1Fc3JJ+@3"!%!!$!!3!#3#3&AVJ#3"3&
-2k3!!fV2rN!3!N!UPN!3"!!!m!!#f-bp"YkGR-3!"6qN!!9T+!!!"a!!-kGX!N!j
-AD@4RCA3J4'9YEh-!!HZ[B@4bF&G*FdL"!!"!!J%!N!U!!*!*!R%!N!22!*!%$`"
-#`G6)[q9dCcJhm#*Zq)VdK2$iRN#q0XIX6`qfUGB1HbS4Aal)iRI,6F0XdJl-hH6
-%Lq662fm"CPc`(rKClf64TbIl1486mc-08E[h#+0Smpk(SkH3!-LSQN$lcKY&!I,
-GhAq+b2FDiM$FUSBA@6j%A*4pa#'(X0ZCa&2N$IhFf+ecA3PGJN"q+G$h&,bdJ6P
-$hA0B[m@S)$F$LqjMAaQ#*5CeZ`E3F1PNpl@PCIe3i&blBK+2$N-CJ`G1,2E5eV)
-4BPN(peRKTUi8QV-hIkJ!TC!%!3!!0!!!YM-2qlBc$rX!!9N0!!&Ed!!!!F3!",d
-[!*!19fPcD!!"[keKC(*`9dPc5)%!N!-"!3#3#S!!N!N$2`!!!5!!N!32!%,"e(+
-SSMTD!GR2!ZYAQ(%hfFD,4-KE%flQD)d&i+fa(NmUH4!JRN8i18de0McEKTM1GRY
-2lmkJMR%VqS*VqR((JFde[@3X8@(2q%,C3TC%"`8"I20QcjC)PC32q*46*[(hqpq
-mp"i9hAAGd8D,46e@#fA3lq@H"l1PS9@5%hLmQ++EA&-XkYDrrP(D0[GVQ(-,%`H
-,Tf4lSS"Lk+b-"Te#i9$U`DI2&K1"4[,)iFGerlMV3QV!D-2V!UJfm81Jelm@""6
-@0f$'8(bm0V'!i#mjjSZ2Em!(*mpQH-HJdX5@kd*+8bmK4H6F+Q,X"39NQXC(pjc
-L3[PAPJ06"IC3"bfAeA%d[R8P'X2Qh-c225(9VJI'If[GRpkY`b('YibB!+@3"!%
-!!$!!3!#3#3&D5J#3"J(%!!!9I2q3"!#3#U@3"!%!!$!!3!#3#J(%!*!(FJ!!mHc
-rN!3!N!UPl!!!!3!!!Bp*!!'153!!"'`!N20m!!%!N!9T!'-!I3#I"!*25`#3"cd
-!B!$cL&a8D'9bC5"TFb"ZEh3JC@j[G@GS)(*[EfdJEfiJdPi`db"dEb"MEfjdD@j
-eC5"9EP0dG@CQD@jR,L!J3@iJB@4NDA4TEfjKE#"H-5"LHA4PFb"KFQ8JEQ9PC'9
-N,J#3!e)!!3#3"@d!CJ#"!+)%!Np,!*!&"!")!'F"!iJb8fpbFRNX)'*eG#"K)'4
-TFfXJFQ9XBA4PC#"PFR*[FL!SAM!T)'KKFb"[Bf0eFR*PC#i!N!0-!!)!N!8a!'F
-!43#Y"!44G@Pd!*!&#J"3!"`"%)JD9@j6G(9QCQPZCb"hBA-JFh9MBf9cFfCeE#%
-!N!8)!!i!+!!ZS!)!!3#3!he"4%05!`!!IJe6#T1%!D0Y!1`,FJ1dXM)V+q0E6Gj
-ElfVhTQiQei!a!%!$!*!$ZV8-J!!*D5Vqi!&9%Lcl5XKE$Z2PFlU&8Bkb2mq2rki
-J16HX'[J4bSBeHBCLSfGVm+aH2`AZl![!X+N')MK-9ckpkmZYSaN$a4aC5aXi#`#
-3!eS!!3#3"9d!F!"a!+`%!Np,!*!(5J"9!41)1P0[FR*j,L!J5@jcG'&XE'&dD@p
-Z)'0KEL"[EQaj)'*P)("PFQC[FQePC#"[EL")4P-JGQpXG@ePFbi!N!0Z!!%!N!9
-S!(S!I!#f"!*25`#3"dJ!AJ%PL%j6EfeP)'PdC@ec)(GPFQ8JFfYTF("PC#"LC@0
-KGA0P)(4SCANJBA*P)'j[G#"cGA"`Eh*dC@3JBRNJG'KTFb"cC@aQ,@9iG(*KBh4
-[FLi!N!0D!!%!N!9G!(!!F3#X"!*25`#3"dS!93%6L$T8D'8JCQPXC5$5AM$6)'e
-KH5"LC5"NB@eKCf9N,L!J8'aPBA0P)(9cC5"TG#"hDA4S)'0KGA4TEfiZ!*!$+!!
-"!*!&T!#0!,J!d33)3fpZG'PZG@8!N!QH!9l!!J2S!*!$e%&%3e)$!!%5$9-+Qb3
-!1iU)LKA2&Y"cV%4X%28X2hmrl0HG[qIZcJbR@0KK*5TBK999BZ@rm35aUJ8,XQ8
-l6L$jN!!I!93NQ2Se[)@RhFACh8h5b(U5[AdI,N2FaCI(T3X@qBdi9dq9p3XN2%U
-1NN'qk(5em(4U&CSL2JAQ6XFXGBZPFi&Plh`8(,JebXbQG8"2"b%-6&H8@CbY`EY
-PFb)Ah(i-H"r`2%#L6q-DV)Mdc!mhH5K3fic)FDZRR-9M@e'jc-h@kB'VP$IIbIX
--kIp8rmPY!*!%1J!"!*!&8!"C!'3!N`3#6dX!N!8$!%3!5!$SL"P8D'Pc)'&bBfK
-TGQ8JDA-JC'&YB@GPC#iJ!*!%5!!"!*!&4`"D!&X!P!3#6dX!N!8#!%8!-3$SL#G
-CEh8JD'&fC5"PER4PFQ9N)'&Z)'PZBfpbFQ9MG#"`BA0cGfpbC#i!N!3-!#J!+!#
-f!4`%!999!*!$$!!J!!J!SJ%F!)*993#3!``!BJ#5!2!"Q!#&998!N!--!#J!+!"
-e!6`!Ke99!*!$$!"'!+B!ZJ(@!)C993#3!``!)!!)!+)"(!#!998!N!--!#J!+!#
-Z!8i!Y999!*!$$J!S!#J!`J'N!)K995J+!*!$$!!S!#J!P!%5!J"993#3!``!+!!
-S!)d"&`)"998!N!--#e9Z8h4eCQBJBA-k!*!$#!FJCQpXC'9b!!!%-d&%3e)$!!C
-h$9803b)5%HCHEK"N,4P%D[*%*!X3@DZQ*LHh2BZ-i(ERb%Qh-e2bQAph[qrELM`
-EhmbhY8#5eFlXbH4*f,ilNa'5j9ENLDc)laq42j1IbEcCeRB454B6XMFYb5)S31)
-(rdjCKT&84$LS#cYiiLGf)5c5J1e3aD%@GK*H(mq1D3bR6lpC+R)6)mRY[@4[%r6
-@hmf'R%[)+8FIZEr5&V,ejRAjaL3*5bPTf0kN&a@6NPGC,a$mi-RK`KFHI%V$*QM
-4BN6+hFfqTX2b,*5j55k)jb(*(2h&i)XDJqim&Fee*9$cG*JIMZ6*i#SGjViNe#X
-q)@+3!*h[`af,NK")heX@$ED[(5XhPA-`LA1fRcbNbSE0RBqrZ,m'l)YVm[NQUD!
-A@)"Ck2@aqNDT+'b%UlJKdF4%D4j'8D8QKLJRXm5(8JQR40@4X8N6+L,JmB-'82K
-L!,85ECR3J#8d%@TbLdfC`eLTT"qR$+aeU)[Di0J#T6DMFe4B`aLflrdNJ-)Z!m3
-jBTLiESAmcl%RFHbLl9fAJNh,JDRU`pD$+ZFdM(GdeX@!G"Z$#pDfYBXaSNc2)HB
-bh"2bA1lEQ20L2d(0f,[Q&#I)A'ZQ2(KBb@@qIDUNT-rSkShVZbh3b(2j4EE#Hi"
-%aD`5%YXK48JPi!JpjfESS#*')G-lpU&Zma9#N6ZP%AF+hP-PhjBJ16hDlDNc*qD
-mR%1jlK@TB-cEfPh+FK[jplG1#3aZ,GrmP`rLNbG@J3Mpl)N"@`NmD#E1Ye,'NV,
-SJ&0-'N"4lGDH(L15jV)kGQArf*KLjXEBBNT+ilSFVqIQ2L6S6,2!-qdr5A,SM5r
-Z8%e+qrrFIEa)TAK+(ePf3"KU9mH96KeiJM&J8-CCH2(UplHlTpQ8&pIV!mfS&!e
-YS22Y"H59K,,GX(5'$iDUN!!D1!1%4[Dm+R'd+EK+q$Ll6eBP[SHY1Jm&+*f0f9@
-c1LPl$U`!LB0EA#,N"l-#h9`&eEjM4RfXIVf`GZf$Y!rlJeGII3NEUUX[JA!5-Xp
-,Z*!!K9k#PFalib#6LH[)jR!53fYB8Y@+#cA4e!fZkRA5eL(bC5reTB0Nq+`1N!#
-ULm1*SfpKL@KA(V8&MK(J'6fDpK)ZJ-$X$'lTUd'pQXb1L-Hl60lqhlJ2YkIbbBf
-VNkBAI5lbXT26-1CCQI@i%dADZX@J'V("P$45$f-VG@mlh@!+D@pipZKGMr,CUC9
-ZcXXMqF'dI'XXGU%XA8IkajQ+#fPh$2Aj@FVRjqVrINKT#[0r9hl1a'Bar[EhjGL
-F9@FZ6fPZ&[UQ90aX9RVbi))fT0[hNY60m9Pip++5qIc2PqqBK`c8pE9GaLXRlhF
-Hm(""&mY9YB2CTqfiUkZ$G385RX(1bd[ERX3qk'4JZaVPpDGj!R%'T["3[!PH+Gc
-$PhJ`"hHqIVA3@F0Eeq31!*!$'!!d!*!$m`&H!!%"!!%!N!8$k!#3!j3!N!-m!!8
-%)'pQ)!FJDA4PEA-Z"&0dEh!E5A4PEA-JFQ9YB@PZD@jR)(4[)&9Z8h4eCQBk#e9
-Z8h4eCQCTEQFk!!!()N&%3e)$!!a$$Pd,Ui)N2ZS3lhphR)43a5(84'T810%MS(b
-[!l0jX'a")SSV8KBVbQ+[0TjCD%NmccDdYChiHr8KY"C`Ue$"QT-,j(X6pKCrEk[
-MlbQ1[`F,Jf69NMUcZp41E&&)`V`NbdLA#L'NpcmKR9KFHflpr3!0jZBd-3%N0#-
-e(eAN$UCp52mkb!q(b695LPY'TUCrJZKDII@ppEl(rlRl5i*QejU+Hecc1bIFCcl
-8LmMq'HE2p5iMQd2ck0GK'iR"4f5B0#+4`[A)5`SU+5#qB`JLi6#4C5$#4N3T"j5
-b&q`kDKmRkD25CTref,G[hQX6[bdlXT,CV2eiCNcRIkmDr"$QMpZQ'baACk1([14
-ZG(rKLPRjdB)KkRG8V-%Qb30CRXTmIFLEQ2,[2hGPc#&Y,GRT[aZ!E5(qUH'-,&q
-GJQ4$8p&Nf&kBLRX-4MpCQfc1YLRrDML6V@Y)C!c*&I[jTB@CGChYNa)'Xb(l9qM
-fTBJ"@Y`+Rq9f[9$!2NGf,dSH-S3M+#(m@MEY2-ILikd"AKk6e"Z@KreR@9bQAK1
-b,k1G*0['qM+VPeTedZX2lepCG"lNhPRC'q"lT`YMGRmdEK-qp2GiK1ArlbPS2Pr
-ekqN#plr9RC-%I16"lcfRq8SG[*kmBB$)8"q$bdGk`J'qF(1X-2,UN!"KcVEki6!
-QBTjilbEecFMq"El@ATMh)eZ+K,#pck8R3D,6%-a6lN5RN5KdS9a`B8d-bCTBAG"
-%``&0C$K0X!S9*Q42SN*'DkPkRLTHU5R#h5@jf'aBNrPa[Da*kIYf5C2#frD#*LI
-IVRT,Naf2mk8"jMZp!DE`Kjk!&k9YUB#Nq4qc!3rNjTZecIMJXL#cdI)k2,rdMj@
-lXp+"`3J-8Q$`!S2U$RE!Gr!LKi@ep`M62Kk9BRq0LV&%0pV1aj!!ci@XHE"LL$(
-6)-CQbLfVfc)L2iZcJeeSLN91T%bMear92q,E$YHlN!"%$E`B3Vj36H)ij""Rd[@
-Z`5P4`q))),0Gm2b)8ded8`4R3NrKJ6KRE#2C`cRB"b!i5"'q1ZI+`BmfijR1,*j
-D3iK-MTTbJUMkE)jZ`UQD"VqREF,U!P,'-cihSUB5Ybr%CQam*914B3C*&2P)Ta2
-9Ql#dLQ`pFZ5VSKJa[NZFfZ)3IaX@@cri`,d)r812I!rbrbkkT1m9XL-HNVcbj)P
-QmQ6(MK59-CT-I2,I&#QLq"*GL%9BfTL2-Fk1X*jIS3i26Z`hB23`6cHcHPjmGZ(
-R"lGe`QMZ[2a!(BfG5(9G'0hX)*A9*cZ"[)KX&qEer$Hrb!kHr))eiJ3$3Y85VFj
-harRamBH8Df!5cZ1RT2ZSDA[fX"j&hrbf%d50'*fLHRb&"h)0L*IEBURXpR*`91d
-#m0Ea*KFSK-$"4EA@qC8H13T'p%kbT$2b2SCUBDK2F9jm&P&rkl`1%4Q-I$16FbU
-kmBq-!3m%KZmHEAVJl0#M4*PEDLV9jE`P0Je89M1JMBk*D)+@BNU&G-bPS4e9)Sk
-NARc,J5Cr%%81aPG36hQiF*2Z4#2RBj[L#Tc4EbrcIeYUILh"KM(2SS`1HKN+*Z9
-`#r3(fS1K+)EQAZ#5$PRJ)"F$!5!arpcCTb$NCmpQpM3fTPXrQlYrX@rFmphlpri
-S[Xqer'Qcc&+-CMpCedRTEJDRU@9M"EjK&13EDY6J,8cckd*bDEI`XRh5A'LAGrN
-0dEKNY@V*+bVZAq1U"(@"`A&D5,*r&lKmi@IjGMNR'ACPTFM082)@Bi9JV4-%Ma[
-R!(Id#*bpX"q5ErJ0,BSd-44+RRkVSN4ZV%TEiR-$&`ZE[+FUQHN@%PGlaMc"iSE
-*B#h,@pTS5#4NUf%[qP!mcFa+mpiA#[i9C$Za(e$jaS+#3c,8'RQ@3pk)BRRj$8F
-CD&G-rmZK6aBKdR#eA+DYQU'BNYa&2D8*V8I6edFXPh65PjEGIG9Rcj49EEGG2km
-9l'KTlJc"FApM-'L)QYIV[(,&'m+e#5rA'&`+PI,B,RHk0LT2qMh"B-P1"Vjr69"
-rlq8m`F93NBrYfKkQ+'[`6`c4[&E"8dGC4kMi,mrVKZI5Li*PA6H4$lC*e9EK8Z0
-ZEP&`K-i#FV#4`PZB+NV3#0LYlK-H%i4Mf[T,p&`!4VMqMN$hZqhLC4#[dI%MdJF
-*-SUd6cH55!r8)PQ"#"GTMmehZ5"F0Z)V'Hj!ij&NrZU'&Bk6R!aR6"FN81McTE*
-rh[cSArRNN53#Y&XT5CqZj9UcTrVkhmb&+%IdBqrd4(lIYN19,4Y@Vl,3ALGAh6!
-B@(-dN!#Um%jc"m+CT%+Ta1q!XUXGKPPcA+-f++9)B8H5Sa6hdrBkUpfcB*!!h+R
-U+(9mS1ceKX*5FCpTC,4XS,D0fe9f6kkf6"SUcC2KmU#Pd#FKJE!41%C$P8M+2@D
-R8*&Q46"%##Yd3rIjqJFI6CMM[Jm!N!-D"J#!!*!$!cBZ-!p6G(9QCNPd)&0&35!
-f,M!!N!-1"J#!!*!$!cBZ-!-f,M!!N!-9!&3!C!#,!BB!!3%!N!F%5`#3""J!2!"
-!!,!"Q!!"!3#3"`%(!*!'!5*"4%05!`!$LJe6#TXN!(q'4E$G16N6X-81A8Y16ah
-E!48$fl(kf!a@pFiq++KBI@c"EUcUaX!rBhp8p,rrEircGPBCaZS!#jNe$9a@MI6
-"MNEhVP-Dl!5cmbJ8h-AL-N+fe,NJbA-,N!$IEi*fJZR44(62+AQc%pfmbHiVKB3
-cc%YDkTT5LKd,2KqEdhm%m(Vq1HV+dqTUrjpIEXHVRre$rrZ4PL8#Z$0USi*Y9X&
-)*Va&Ufb-9E9H@cjLQlH&l@%9IG`AaY*D6+58Y!*a(daqM-2AVK[QKkBCkP2EpNh
-G$lS3D&U!*`6)!*`!6,hk,3$qkJN$%Am!m+*bi3)3()+!!B*LB#diLj&"M0m-3Z3
-51Z,UBj,-[5Ka(dcIG2P&a#YXbaJ!N!0h384$8J-!!)!08`YE)!-$TQ$$UQUc-,!
-")Q*J0dZafeQ9S#"L`alUfF#B96%,BbUkpkG6V!S,L@2)YZ*heJ"5+2hK[F##5VM
-&3+GM5$+1VpRh*L)1[qR'r[[BRcTA6bLQN38GNEU#'ELMa4UZU'SRT%mb#Zp&cJ8
-!N!0-!!)!N!8)!$3!'J%EL"Y3E'9KFf8JD@jcCA*d)'4TFfXJAM!JGfPdD$S!N!B
-,!!X!+`!VS!)%5`#3"4d!0!!Y!4L)!Pia!*!$1J!"!*!&0J#(!%S!`33#6dX!N!8
-#!%8!,`%rL"PH-#"KF("PBA*c)(4[)'*P)'4KE@&RC@3Z5`#3!kT"4%05!`!!YJe
-E#e-`!hGc,@B'l"R6bPA'0c6M[V999XBrEdr[eAUhlMhriKXD!!$`$3!!k$B0!!!
-,XLdEJDAi"hCRqrRPV5ecdeE0heRBNa&Y1kd$*bTR@GR*V[*iehG%KH"5a(q#'"5
-q4!bGmd**U)B"*8+!,UJ1hY8&`*1&(+!BY25$@4r[#**R3EiJhiV0BEcLr@Z6"D@
-&%LZ+ZA,FjlR#dP4ijI&K!3#3!``!+!!S!(m"F!5[998!!!%!N!1!!"rr3!!J!L!
-!)J53!!!Q#FJ!)K2N!#)J!J!L3!%!))IJJ#%2m%!L($!J*"Rr%#JDLJJb-SSN*M,
-b-Nid"MNQCI3b%Q88*!KRr!J%F-!3!MrJ)!%"J%!!KX#!!%!"!!!J!J!!%q3!!!R
-)!!!%N!!!!!)J!!!"3!#3!i!!N!H!!"rr`!!rrq!!2rr`!$rrq!!rrr`!2rrq!$r
-rr`!rrrq!2rrr`$rrrq!rrrr`2rrrq$rrrr`rrrrqIrq3!crrrriIrrrm$rrrq!I
-rrr!$rrrJ!Irr`!$rri!!Irm!!$rq!!!Ir!!!$rJ!!!I`!!!$i!!!!F!!N!1!!*!
-(!3!(rri!#!#$!!Q"!S!+3J*!#)3#)!N)!K!,d!2i##!!#!K!!!J)J!!)#3!!#!S
-!!!J-!!!)#!!!#!J"q!J)!r`)#!F-#!J'ImJ)"U#)#!bJL!J-!BJ)$3')#"Pp#!J
-C4`J)'Im)#"``#!J2q!J)!'!)#!'`#!J!!!J)!!!)$rrrq!IrrJ!2rrm!$rrrJ!r
-rrm!2rrrJ$rrrm!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!r
-rrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!r
-rrrJ2rrri$rrrq!rrrrJ2rrri!!!"!!IrrJ!)!)-!#i%#J!K#!N!*K!)J#%J#%!Z
-3!!2i##!!#!K!!!J)J!!)#3!!#!S!!!J-!!!)#!!!#!J"q!J)!r`)#!F-#!J'ImJ
-)"U#)#!bJL!J-!BJ)$3')#"Pp#!JC4`J)'Im)#"``#!J2q!J)!'!)#!'`#!J!!!J
-)!!!)$rrrq!IrrJ!2rrm!$rrrJ!rrrm!2rrrJ$rrrm!rrrrJ2rrri$rrrq!rrrrJ
-2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ
-2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri!!!"!!IrrJ!
-)!)-!#i%#J!T#!N!+4!)J#NJ#%!T3!rJ))!!)#%!!#!L!!!J*!!!)#J!!#!`!!!J
-)!!!)#!(i#!J$r!J)"``)#!Crb!J'S)J)$+#)#!`"L!J0!BJ)'Ad)#"P(#!JCr`J
-)($!)#!ri#!J!B!J)!E!)#!!!#!J!!!J2rrri"rrq!!rrr`!2rrq!$rrr`!rrrq!
-2rrr`$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ
-2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ2rrri$rrrq!rrrrJ
-2rrri$rrrq!rrrrJ!!!%!N!1!!!!"3!!!!L!!!!53!!!!#FJ!!"2N!!!J!J!!3!%
-!!)IJJ!%2m%!#($!J""Rr%!JDLJJ5-SSN*M,b-Nid"MNQCI3b%Q88*!KRr!J%F-!
-3!MrJ)!%"J%!!KX#!!%!"!!!J!J!!%q3!!!R)!!!%N!!!!!)J!!!"3!#3!i!!N!H
-!!!!"`!!!!q!!!!I`!!!2q!!!(r`!!$rq!!"rr`!!rrq!!Irr`!2rrq!(rrr`$rr
-rq"rrrr`rrrrqIrq3!crrrriIrrrm$rrrq!Irrr!$rrrJ!Irr`!$rri!!Irm!!$r
-q!!!Ir!!!$rJ!!!I`!!!$i!!!!F!!N!1!!*!)"d&38%`!N!B(8f9R-J!"!*!%"e0
-PCc-!!Rm!N!-(8f9R6J!$r`#3!`G"8&"-!*!'('&eFh3!N!-"5801)`#3"B4'8N9
-'!*!&K!#3!c4"9A-b!*!$!8P$6L-!!`#3!i!!!3#"!!)!JJ!$!)0'8N9'!!-!N!1
-!!!%!J3!#!))!!`#$!*!$)"qT)$%j16!Y16JJ3@aKC'4TEL"6HA0dC@ec,#"*EQ-
-Z!*!(9d&%3e)$!!%"$9-#h0B'NrI54Xe&%fd!Y2Nh,VcE64YQ`QbqU`[IK0f`fq6
-GGYA9G@%!#6LPL2pd"ISD0+Bf([[%R@[C6S+*X0-3qX#ck!"SN!$&[[i%[JB!!!3
-!N"'"!*!HJ3$r!*!FJ3"8+rm!N"U"!&6r9#[r!*!BJ3"8rj!$9#[r!*!@J3"8rj!
-&9#[r!*!8J3$epT!$92D3"#[r!*!5J3$epT!%q2D3"5[r!*!3J3$ep[D"N!C@prE
-f+rm!N!k"!2Afp[hrN!Em9[D3!b[r!*!-J3$ep[C@rhrhN!5"rrIfN!3Vr`#3#S%
-!pID3!rcppeCrN!@VN!0rp[BVr`#3#)%!92D3"2prpRmUI`#3!e48IeBVpP3Vr`#
-3"S%!92rfN!0@rrMhIbTr!*!$9&5Vpb[fre3Vr`#3")%!92rrpT!$r2hh9P3U9*!
-&Ik[hp[Erre3Vr`!!J3"8rj!$92MfrhrfIbU3"948Ihrhq&6rN!08q2m!!2mV92r
-rp[C@rrIhIbU"N!5X9+Y@pT!$rrp8q2m!N!6r+e6rp[EmrIC@UbU"pT!$JArrprD
-3!rp8q2m!N!Er+e6fp[hppeDVUrq3"RrhpT!$92Mr!*!)rb[fpPEqIrH3"2q"pj!
-%pT!$prMr!*!+rb[fpPEprj!'JID3"IIir`#3$2mVpT!'ri(hN!2fN!2hq2m!N!l
-r+rD3!rrrq2rrq2D3!rIir`#3%2mVpT!$prIipj!$p[Iir`#3%[mVpT!%92D3!rI
-ir`#3&2mV92q3"96ir`#3&[mV92q3!e6ir`#3'2mV92p8q2m!N"Vr+e6ir`#3(2r
-ir`#3([m!N$&"[N&%3e)$!)L8%&80C984!#&9lNDI2Tq98TFkPk@C#reCjkb$V48
-jAMZFd(A2QkiZ@qd'6S+ZX+d&h22ZD`aF1&jF`B%,)!lN$%F-QG2$E3JZa#ra1-q
-ER'H)ja%daP2Meb"IRcFaZK"$b"cEq[llr$jYIad$)CIAprmj(9Bf%K%#!C!%%3'
-3!a&#$J"G!pqDp[N(HU)c#(`r4)(q$+l4p(LfUCZr"#Ra1aIILiA8p6rlPlb5LBH
-&EZMVDB*2r$L[K)i5FC!!(hf6L0TLZ[8@@@-q,f!FSN(c`9#*kT%er8fR%pm"XG1
-6b'XkM38%ir19DD!Tf`BLe9Z$9Vm0j0i["hrf&fIb8j!!,*ZbMB%ljp['QVHm0EM
-'h,3EberaC36,RAcC5DmR5N,RPjfPea-P`9Dqh!QLF-qbXjhr"K#mMMlZNb!J*K`
-$cq3j3bBR6)%Qcjri`24@jlq"MP32)R09mdj"p"ddhcr[EXm4ipLL%%qZr'EmHb+
-!Ra"qJUdj3[l6I`prDRl@&J5abZ+X#!f*rjRkkq53!'-SUcMf!*pf15[iBPr%CDl
-r8heX,Kr+cL5Bij'KN8pM%S2D#B+Gq-B"eG3r-`(,E-%S-U"1CXaefCi5[XlY)%M
-'4&+-Lfh#P(pPUP#PiMprRISV0FcBe&rCa$N-Qr'cCI3+68@Zm1P4rA6NLX6+ASc
-Y'a2ID2jaT#rD*i*j3Z@4Emr[jL5$JeEhjpf*("&GqCracl(jcl(jcd@`iiIT)YE
-@mJ0eJ'mpHNG!(6"Ec2AA@f+kP8H)PEpb1D1f(cjKhZVLVbVdaeYrq-59V8IP("3
-Z9M&e9i016"jb(-TYN!$lmlXliN3dEHfhhQ*08PD)bQ)GD$V0"ZPB5%[+6QNP3UR
-%h2GGpL*#l0TKRc@T(A6TMra(LG$C3j3G++Sk$U#aNGHdfi%YfVeB4T!!bCKXqmX
-EBV3E*'$mKfbj%[RMcS0$M`SaP9jI+062erQhG"k%bJ)3qm*SYrRqM4Y2[5dm-!L
-220!8FbCPeci3`6YV4Mr3&#I[e3FRQU3!C4m'@aBb2k"b!f[X*NIAZYP1VqbUcT!
-!hkcq5-k@0E+rqK6)rRiE-Fe3l8QBlpSXX*QLMA*fiMYrh#bm)$Z(%[jBp*kpR8$
-`MmdLT2RTbh08ccJ3P#L6j-ljZ#a$L9,EAmV+(&f"!@HS@F@h3F9a+E*bNYL!2hU
-1"0N24%(!&lkmP)Ycf1@KeEEKcImJ&U'#3B[@IJ4j6@A%QVF)mC)@-@bY!`96IaL
-#jj8)YQEhr!B9`F'1Y,9H#Vk)P%iHN!#h8%4*JCXL#N%DN4qE@K0T-ZiE8kQXb)#
-3!*%"d9PcSVXeVmNS*qe28R5EllH*p&$RpS5)*GX#JXMEdFk$VF*XH[qcpS"jk,h
-kkiI-*T1TrV1j4k@AB8FQY%F#*T2CC"qIKDDHfHAd@6lE"#'f)#hNN!$%Y)Qr0*[
-D!bRIZ2lSACD'Cc1p0Fp'3Lrr'&YR6*f2UP3P(L,$@B18V4L`)DV(9%8@-E(&,kS
-(UP20HFf(Qh+ELUb)(*@+-LLD@jTYcAFMNq1rQM69XkTRb@2'P*a8C-J8hVNi86G
-,f-HTJTkd1(hi#FAmC*c0Ff*4&,RUQ%mDDV--jPZ$Dr+D2Qbm&jpTM5Fl&hql'#5
-mU1NY-0BKNh$2L@jMB!,JGRA08`#f'dpmQU[kHZ1N2'Br)m[k5adZZpmBUJFC6jq
-*pkQV-3+Qh)b896+p,)qG5Fq`Kc%&+M(pAHILiSe2l9dV'XIiCqP6He@UaX1Q[-D
-qTrD+D+1TFr'Zc8$m1A0D5'!a"`I-b"V+@e+(RkV1'6qiaKBh,@kHHrLjd*3YhZG
-kbY9m[5Q[q5BLLH"R,P6m4HF-mc8$HbIkS16jTN@U4r"6MBTjXqT&X&66clia@dA
-cV`e$[lVjef"V(-KV,P8Y`Q3Mr@MCf*!!f0J3*!Qr3330[Aci!Rkqd,*qJCrhY+c
-cfG$Ir1Y6pAeL@0J'QTqN$"@,KF!9CfKri&5hFQ1)UZ[AQ*XI0dkYF69[aEBrG!6
-Y,4-20hpKY0A'S1"Kab,9idieQ3%blUI-D5,daPq#b%TGP`,&'E+5GPNT'`P!&e!
-SS5aIFelMD22(9Tie+C,06e-@SNJLkRC92j@`d!Y8mdmEXP`-a2mZ1%R-Mba&N!#
-HKi,%!C+DFm6fUVPqQl#Y%9jcIFfaYVeq+PepFir&0Y'V([fVea*LidrTAqP2ll"
-X2@,$C+[BH)AqP9kjhV)9)1FGVpN#XqK!b&b[Ff(K`m(,fm6'Ur5[p1V0PUh(E1l
-+"amjH[2P6DLUjrEp2DV9[am8)CY[ELm'[R##2@@%!SKTkci,CILEUeZ42BFLf9(
-p8AZN#dM1Reb++qIG*N*M!ddIQYrE-G!dcIcCmQ0MA[0lbipY#fM41,,e@%VbjL1
-("jVZ0RmIE(2"pYTKYrRlberV#@cmJ2k9I[$iNDf[c6S'92VNb!e!$*qc3+eXELq
-Im(&NqNIEj-JqR@KTVKl)jYRhKG81bJkMV,[K'J"f!if66TdZ3YR@)JRLe8"p5Ab
-E51lE*T!!23d5-M*)+F)DEjHcBlVf&XBB*%Cj#$Pr5BJ2BfhqrqAXGM1fh5(IEP!
-3XL56K0*%@f5dXRV)`-`S@+`Y4&5@(6$A*!TJl8&VN!#1S#UCd@UQ*D(3I'a@R#k
-a"G[Mj6*I96#rGKh-*aA-KeCR9Me$"Yjd4Q(Qcr$-j&a9FI2(p,'1U3T9K8h0+(L
-$)YMd6@P5U)@kU3',!-$3EqU&8FBSNBaEbGa",JBihY)ZRVBie8ErG)YG4V9C3CN
-hcZ'IhbG#GKlmpRQ*d+hDVqQ1j4Z$de&F'peJES1M8NM+-QdA+EFJ5m9(VqfEV1[
-fH4QDKB4UmmF8pE)QUJ-er&BRQZK#EDZ5a"DkM)%6h6'HI4[e+09$@CGS+&HBrd%
-14ZNDpdQElDQ3!!43GSSSrZRSCdfNmI`D9+#0@A*5Bj&GDc50aM8!fa[6Bqha(M%
-#a3eM-@903Rd9FYlLB64QG')8cER&a6T%YpSaX144Hd)11MfI5e@41PD"3X5)Rr0
-JNMAG"-Sh1X-L%&&"88*-a)`UbfFS8Y6N4X5,&0S'A)+Q(VJd1C3hc-(!GGBSa-B
-d9bD(k2UXqf#SIX2KFCNbVN(56q*`"3kid6aGr1Mj@B*-dcj,2G"mFiSD8D5f$M5
-A8Y-ei*mPS-6a8pe3UTZbE(j4CBXVKL1ciVBJ-U88fH0aR[N14kANRX$H`&1$c6H
-Yk@XZI@S)"I2$5dT3--rP4I&DAK3,-8pllHN1A!ZN+0YqZX0bSYZj9aU+8P4L*Ab
-`q&%MXS1m0!%hMf+1M'(LXLh1P9r[S#fTR8FMJh[33P$Y$@1E@HRBlU9aC+ENlh2
-6d6dL-MMDM80Q@jQj(J"+X8+"I'ZN`$6"%+hJL*SBSS19%"eS6,",1YQPfUPA0pV
-LA8*#Pj!!YAR$R3c'a9+Q4UUf5@@e8mmYELkeYmc)DhlF(L8!J&6Dr%Ae,kaH3[l
-40)SXTiFZ`T9*@ecj`VjCHB'96-$r#N`)fG'0F$5#3BP0XX2i5Qe-BBVV*%DBQjV
-Bj0ZV2hTP8XJSm"$!+STIb4DY[`!LBN!5m-THir'$@D),JK)NU(de8EbBR8*`m66
-&fl2PGFkZFJ4AFm'jiNGD`B3S%`[Q$MLRI+N86kEGUXqXkZ'"QbVe!"3qeMr8qEb
-9QDYU2eAe0(dK0@Z6GMU'k5#ElY*11c$YPDE2'%4X`V5E64Y%V-5dMddE4&!'CT8
-KF""iZrpQU6%2XQ8KPKqm03J5Bb'!IA,MN!"VBl2%[L%aa3'3!(3!lVX,(U$U9aP
-XCFG3D3'bRY8Y%8YYcei"m#Z+RaB3q)BR5JXHJ'MC1!8#55[!)%%!cbcKp0Q#-8!
-GFNr"CLT@eF)1C`&-GH&))Bl`ib#1f8bjUR&qF+hLB!Z!3&PP!8'R&9F4D,J!"fT
-jGAXC'fer*lZJa*&E8!)hdDh%`X3ZJ,KP)-E93q4PilZe-9ca#5DU826dU+UNi`8
-TjV3!'PclTZ0)(6QD5B8,I-m#652[C"F9dV,jQilFSN,+@!)a-`hZC'1QcVkfTP[
-!8231Z@mG!(Np8&58*`+ZcpPVC%XGJ+0D0J6[jDk%`kJXpU)CL8qVCL#LUSSfNRN
-)[pfMFfJZflB4Z29%A8VbMXYh@*!!9EicjT%GQMSLc+2aTRpCGiG&0i'Y&G[`)rZ
-IU)2!RGbpX!3%NDrSqX&)lb#Q5`L%D%,4,LHGkHf4MPIKdUED$kHE,P`9'k&QC-0
-Y`QZ2FJFdeH&0Qr`aIrk9b0$d[TbY$M!lfdNF)EQ[M!QDfPF'p4M8&b+Pc&LNXMK
-Ei+VRbSVLiVU%j[P$'5M)mKHT5L+%*P!%SE'i!C9AMP$GbaA4!6&lQlm%!f9J(fM
-),5V+%8ANj&PRZ'"lbEkHSX,QHGa4%k+VRlIe&*5%J6p"&$LSr[DaDUYc4[5,@A'
-&'IXP4b@V")K%6Hr'1CNJZ8A0`1b5*iQSC&T8#+H"Y)$NPJJb6b"2L#X%H1rc0Rf
-$3(bJ98*1LIaPM,XMPZ`,0P@dCPZ6B#`bjaEDm,1TZ5QkL-!a9BQp(@EaQUSScir
-&*994MMUDkal%4!8@1*,Viik)AJ"'MXL3!1'+kDkFkNLIK-Tc,UMXJ!N916BkX+6
-11V#NbTbf9NhES#SIC$`A0Rf6SHSClAEbi19Z-#eHFT@BEN!c6*MH3%0-p1(!+"M
-9p-,8*$)!A!iXZ@SG@$b-DEr$a5XZri'!-@10DmR9FPj(lF,G`DBmA)`Zm",!MP-
-FB)*cT&-QN!!9Ved1m5BD6*qkPMa+J-J*2@)HKaY%b-ZRZZNiM04Pc[Yh0"'6U"L
-0'4FArh[9'N`XZ6,J+[3DQ!KFJpJC49(P9Zh#Zd!K+,H3!#V9jCdceVjHL5hY+Ea
-BXJZIKBeT8B66*3ZG&@LSDQ,#Hm+S@Z-##SXIVCNSAUXH!TL!!UjVVCU+1(2ZGLm
-(2be!F4S0`GM&+pSaiHA6cr%UGI'MDMEYjY1eE0UI*YUpK',d2!$@deb&#D"f(ZK
-59"L*%B26B,BF#"!$!R,6!F&I)+VT4A4!H*H8D,T6"i(D`*+50bd%c""jBULdm1q
-0hZSH"'*[i5DSXSk-%%%ck4#DERX,TUj+8iA&01AdIJi"&,!R4b2b[V&3J*S-a)*
-Q!Ul#"6f&Qe,Lbbh593e(00dj5@1m"Y1)5N*eNl5eBSfQ@b&)m+C(C1MKaJ-m@d$
-8pX"aRP65JN1NR$hi1BU$$4`m'VCc-[+54e(%hl3'VjFF-1FL-)+C%*NS,Ga%`"U
-Ll+LH9&$Sadp8)K9dlBhQQIUDLb"UbMR-5593qpGdNP!!M5*N-DSDB%jCCN+c0md
-i53lEVGNdl$bB0dM$GLV8e(*%TljQ8@&dXUSYeq8YK)XJUX6*IB3)c)FLVedRGXI
-f+U20!9221BFUVAEZSU)AjY*a5eZZ%)A4Dj!!c9'`$022A8[,d`JB,V8!S1m#'@q
-+#8M,lbB$T3[JbYC6F)@#Md[BNjb)b9mSVmVpb[%XUT!!4FqKQ%TG+RYVX'MVSHZ
-X3J,SbNVe8@0k#f5T5k35,`UkCiB0+JRN1RVY-9)aJ[8H&#G(#IcQ`6TT6i5pQ,'
-cNkD9J5KJidA38@,54bQ#fSR`S"C)NTTi!9"X"5"D[!@Ab,fPKD-RVU#C*F4lMPk
-Rcc6`pLXaEKJ!94$GK16EVfLk-I!NS,ilS$j8G)(9&$LL4*1TD#j93V%9E8`A[V'
-[l3rIQ022c&"Ml5PSX2B8c5cRLMPNX&B[E3ULEA!!TiC9Lck+G)*(%PU,I-[%T-[
-(CSSh'`SRN!$aLQaa+Q43l,Li!)R!peVRM#dIJX!R$1k!h&Q@Jj6'3(Y(`&IrV0-
-Il4#Ui#'l`qM(81hT#19&[DLmPq,MYQr#kl*3PR1EdDCPVV+[0(U*HEJMm,eS%-`
-9q,MYp,SXF0U1l*Dh%`b*)jdcrP"kSPY5"Bq-K168$2#40ehP1-`T*(GE4I8PRYN
-FlCcV5!YG[5eK'a-eA`iQc&J!X2cP(+HDXVN!r+qYVYN(mJN1ji$i$,01Q'1qi+[
-VN!$H"82e9YHNbj32!R6KMNp%#!Pk&Yfc9e8%pf9U5UpeQK`!AR,PH`Lm$r'VE2G
-3`L)-eLA1Y@)3%U(BZ1N#2a)#-kSY6(XalF-L+%*ikBefL9$!QTY8G`@X%GHV,P(
-'K9AiZi4hAF,THj@%qU0Tqe5KUbHPi9Te9fJPXKLqY`-&I)2mjSq4U6Taci4)1VT
-#&frcY(3&YQ-2hiL#q'"2!['EAcd[bX3Ypk5&e+,#N4EFPGH(UbY`I-cN"*Qj81k
-q)5fC,ca'Ifh-hRV$HIMG$GH@f8IH1#p1#pXEHhXMrEH,F@-!VhhhR!GpX3)+2L$
-h*q#8IIL6qkSklb+6S%*9bSDMCI9LRK&A!4I,+)Lf-*9%AD`Gf@UcE'2h[3aAbqM
-Xq8kIBlkc*ECVU%6)Ijb,c%9LXh#h!6@j$'Jqk*`,pNLXG(pQbKP8hV'mikRRXFJ
-imrXcql'S)j)f&X[YaS0`$K!,rTm-Q4DEEcZCJ89Jj(KkeQeBQ2,bL#'3!*&b2)m
-@G9PBd8+`rf"-4a1)BU-hHN%F4"+`PZL&d(i![Yk)+qC6Gd9rHB)bdf-JfA3&6Q1
-jQbTJLM)-()K%Em$Ul'+4YNRZIJD&jGIHYIf`aaaea6h1iDKVRmHTaUI,@B'T,VK
--L&J&VNdDB3l')*Nb4!NTSR2(T8C3+eIPNZ"EJe+&p8+GhBFM)ZEMlS1886j0-JB
-aR$#hH*bLk)lC`VlViSpP2el1jXEX+r1kr@[K-Xc0BcM-22aN(J#0bX"H*CPL(T&
-SZU)rLq*'Ca5IB*jhdL8K@"46)ND0-lNVi(qK$NQG2N!J(@lk3)k$EHR[PSf-B"K
-&TL&8SrDBAHSI1+a)5&H"MmrTIA%XTUiHLd@PiE)a("P,!X8i6%8Ih0'!R#Ch[i%
-QS'LjJCV&!2c%#(iq"4JjEKbTMN9GUQRf8,8J3p[4*$``Y"EQQT,8#m"42j,$`#N
-#NhJj#L0mqE0B521CpJ+rN!"[S!Dh"i+LEl`X@NhRa6CFdZ-)f,h9S9LS1NLLkA@
-L#Fj&pbDN+a"-929F4*+Mk"I$eEm!D`@aR2L!-c4`KKE1S*Df81fh$q1+mHUS[@*
-S-jaV5K&-&SPSp5h[8+)a5A`&2ciYA$`r[VE5&G)QSpMNVI5+"cSSU&`@Mi+PCc@
-@#Z(KM0Zi8RUUqk5!Qk#!5p(T48DY(q6q8J4P*0k!@F4ld!a$BM1K9XHmkXdLJ1+
-ea+4Ql*VQaf!!hN3GLQ8rcp"$XF)!Z1I*&D5jQT4UZP@11a18L@Mc`(hGlabHl6S
-*4ic*#DG2lEQV2VC,VBkiUR[d43J3[YXDK&Z6@[8i'YThedl0%L!R41'm[j8R"N&
-'NSfLM$I)&1Cd0`j9U"jr"mbUV4Mi9B9F`#p@-j`UDa"X`kTjB'Y4[F!2ISA'l))
-IdH(IF+H0DKbZ-Si3fB#ZaI@2m'XpfQ[9'bDX0RPGSP"*LhI)U@iHN8&"@(L"Ui'
-,ib*3BYPeh!P4%SNb`1iCS)ZDq)CIT%2me5e)I1$&*5-JNRRB05d+K+Fi`QTq496
-e&GqX6lpCU2J&MZ+`&N8T'9[91h4S(Mrd!Vr5J0cDeG@m#[D*$@)hVFCqpc[%XT8
-Lf"LUM@Q$IlIHJ2JQYh*P2F!MJ4Z6XBaY8QdM4h9+1%5*&+40Ebjhd`mKS5TP!b4
-"L+X!#E0&Rr!Zk[+*[&P8a0ij+#AhDKU4%Pk9I#%Ppq+N5cI)Cq[LP#daBSZ6f5)
-"d*bp+Z8V5UU)"YB,Xq,f+"%ID,Jp-5X1Cb4rG%Me%a#9Vjb5NX@9NQXNQPihJcQ
-G-jIU-cLNV#*9#+p1%cYG!0E0Q!!LmVVU8eBNKD-,QpmI!r'fqHeCmHJLe+BK9E&
-pLKq"1*BSBACA2&DKRm5@GR8"(AYS&JL)0r`P'E2jD#X!-02#JZ"$42MJ#6LN4#I
-U-'9eK#RV8dPCMbjRbST+#QRk&#"p[9ipTRFPj4619bURa!I8Ke4rXVGS'GqLTRc
-K*k3dqi&`C@e[`'&lHFSUZ"D[fJc+fJi"GQ3k02pXeHVC[M"F2BpH%kiH#I!fQ#X
-[&MNTUH4e1!,`$)aMaKfTCp*6K*6mN!!+E6*(bG%X-[(#V6a*hBJY-$N"ac(e,re
-m)LP0f,FB!`T5X5%4h145GD4hPMXk*!*CG'"X[h$djQa+%kf6IhTrp!Sb$BQ-@m1
-El6aV5@i82LbQX%#LCL358epM!EQZ0fmDJHVMLZC$e%2C0&5J(a!M8ehZ69j(Adi
-NZNRdb-)qU(EAK#+LaC)@D'qlGQEN8Uc9eYIUIh@*5P8R4Qj!hT0E(-q-iR2JT-p
-l!j,MLFLP5"mUPPYhH-fIcEENc-Ae[NP6lL+kf'26ArajYcR[GC!!3#El4c14a9#
-2UX4R@[ak5@`69$V`HJPFZa$a8rI+FAZ,0#84ihia&k#0@TV#`4)j6XGiXhh(k1q
-jijU@f1l!+f4R-HBIHZ5ipZ"-18i4"mFeLE"A5dN1@AD9'XfTUIh5m9ETL*9R1CC
-XKCJ@AGaHdEkSC(2VST+(X$Q3!+IN+)K8)%1@e")M#%p02#,Dp!E*Ap',$TEC%fe
-(iG5k5&@m2a"cD0RbrRdKCr-b0TZ#VE8b@m(MM#eTB&-($3NCNG)4'b6`hLLL4rI
-K2hXdHS3[+"(UbZM4dGlm8CV-b$PcR%mQ(8IY2XF4*#)0k,-"6%lVQ$dR+d-+9Pp
-ldC(pCMdPNrIhN!"cbql2kJ0p!NP$ZH&Il"mkCClBh6[BhpNhf0h@ea[K,VpFb2'
-X#fHBN!$BUS5ma)4-Y2926(jRSR2LV&i-"5+!89kfF,1&Mbr15i(-+0#T4*+pUQ#
-[1YQ%KV,'L65-U$`[)M!#Qj3G,k)6Qm9b0(hDM@lj4QTQfLj5aF+D2UKik[U()T1
-M%j&4)8Bm3bQCap-cjG5FA2X&jm'8iqR`F*D2ReP+D"CCbl"GAL$iYL'*UhI2Y&M
-)G*Dbjb!`fS-+L-#TelM!EJhIfP@UT1#@8C+iCNF0A'T,80P$9DS[*!$M(64V9Bd
-JMq@#0CXb1`jE+(%k#C6%AGi0GI@3!dFQ0Ee$[0K4AE'@3@a&Q0KD,[B6ZZi%C43
-Xi1"8%aGp@5rkF0aq,`0PDQRa"JTD%8*8H9@0ZqX6)2"2''I$kAchCaBd'2B%BMC
-ba5dD`@EETDe6-)A)5rLjBS`f2Ami[V[HdU1k"(I#J$1d*r$1@G(5`b[La`ZT%2h
-TB2FT'%ar@bp((9RcC4`Se#-[5i@6qN6Gd'p&a2J0+BSifL9kC50V-r[0lrH9UF[
-X2AX$G)4-3f,Djj1BLZiMYA8JUm%BD$MN[-PaL)lmk#a9GQ)M3`L9(I+M*cVepXZ
-,F'ii&E3aqM&N(UJ6!pN5m#*Y"3%J3XBre0djf(p@ZkAlc2F(U"$hNkS+AiHU9PV
-(L2jYK4YBTTf%@U2Q,)''(DNVTJ0C'%RAUCVVR&%k"e%bE(+L1LU8f2$L[XiCZhB
-GMN19dEDrU#f%!NK)Fkr5l4VNjbM39be$TKbrRK+,lK%mk&(#kaB36638q"!Tdab
-[m4FV(Ae2IiDQdj5MErG-4mKCd4jpmarH$ai09@ClN`i1)fQU1SR'Dhd!dhli!&8
-3QfP3crMFi,fFdI5@cIGC)GamdXPCXD#L*dl*K4f[!IMj`M4SFS1a[X8YLA,DH+5
-f')jJ`mY`l)'4Z$4*VQe$F1q9El4GK+#CDMFe2h&K&e"31hI`D(m'%Ak-)Va(f'9
-**(2&)'(c4Z*F6#RFqL"'%X%hN!"!8(N)'B&3[UU*e!5Qee%m`2!5ej!!i4d)U0e
-fA`mF&J[Za4E8h$KD*-%9G6eaVYVA+#[M9K#d"Xj5Ka(UBQBN!$[R`dM1pREf4LE
-D+YX+4GFZ')Y(AqR[%BjY3L1ThMlfcU4Uem"Y",4`%'JAJ*AhHq,f%EP08jG!9`R
-kSZX(4*KbQlB*Ri6)$b4%e+Km,IS#E5%93#JYqJFrVi5#i-d%&)BfSlIm`R!j$[I
-e$NkFDKZPBjd6hm(4iDRqh26-P0c-G&N$Smj-bFa0c6c$"DS*$,C-`Z852mQBQV*
-!N@JJqJi4hT)aVbRA!1"Ie[4'[M2D26K*#`9#C+a`0*a'K4k)0-*3q&dD-[F1hGl
-I1GRI*`8hZ)!&aEK8d2Y0C1S9Rq$iQr8TSGQdq#`pm),[cCNc3l`!%l&Ya-)[''F
-"(HkbYf6aU24,+N3#'bR+-k()&K3ApBC!IfQ`1c,8Dd"!fV"6-Jb!C"8[ST!!U'"
-)9qJl6rJidY[@1c%CGY"+59Ip&1@lkhQ&'(9NL8iR1B&e0XmcBB")eHLbp4Y[kiD
-!`@j0EbIIH,(jrQq3!0NN4i#!C$UlkahZ0kQJPNc)VdC@VMfdjkmmk+&+iHjPF$0
-$X9+"jS-EJ8CMLa2SrXb6Bh'!8Qp,3FMiT`BS)ZA'fDpaFEPUYcC#rE'BLGa@6SH
-,Xr++3[Tdc[L9k)SVA`-)D#M[qS)lf29fjI9!0rThJk,c"lfS`VF*Ykh-ke*pk24
-pc`9A@5PLML0Ld$Q&HSYH`94KQhV2pRG+`DU%4`H+l))'U[,ee8E4P4pPUlC6YDJ
-hTf-if0[Caim989)P(KK028A&fej&Tad@!Ub0+KRCA6SA&qU4UVZLhd*i98rmcAT
-+f18!d-',5!Np1bm3&iNTAYa5BKYNl"39%h"ZFK'"a&a[&A+F5(@e2C`C&lljQH2
-Bdc0a,,SlV!K'e,d)jD#C3PFKXk#cHEj"@AKp$)K"m4%0AG)Nkl)0Vq@SABX5+T@
-h#)cmpFD1Z0(EF#K(HT@"9iGPpqF@E(D8UYe%$8HLh[%54crab8YCIXjk-KEDpUS
-mP@qa5NjJ2[d@pRQEj`-JpP+(,%a*2D5J`LHKr'*Fi1e"pMkLE"a&NVjSR%,&bi[
-'8DV!K$iSXiS668!jIQHLTdlh'j-6cV-bfqi`[f#+*e!L*+D3!*9UliP(Ak00fUH
-X8h33"0"@#6L8,AX%,[ES+deF$2*-MH&Lm`4F-9K46)!)[hi2+3l+jq$B6Ki&bk5
-,'DMc046&+2TK9P&FGQ'PC6`1YT&`j+51Ej!!"AC[$leHbCNlH$,PR4+5bUf"4HB
-X(eAH)K2MkBPESh'IQSkHBqMdF&6fG0!&S4kh60(f'SmfZ*6U9F%8X0'J!$hBSY3
-!JE*-rD5i8E@krK0bF)aB$JXVSH-RN!$@B,Bd['ZKAV&86A`me+hj(06#rXkchDG
-'Y5UP!$8&pb#ekDbmMX!%Zmla%K8VGYPak'PDH+`%F-'ekVH$#A5BpI54fI`&0rq
-cpSLZpmBr-SEfEA&5)&$d'9$K86d-jj(3EK+r-Q'QEQjQ[h`[#DIU),T$EIlXNb0
-FU2I`Q1SXa+)l,NN8*dEUb$%jA+3d1IFb61!C$NJJk`8&#$QN2b-e+!)dmD&K)N3
-6-``63CTS0%aiD@)H&ijZRT!!E1bCjCGVMR"bPH8G(NNH454G1Y@TQ4Lk[EGc02+
-jATRI)'@UL4a6MM+V`T9jI`P6CP@B-[[dbVcrTJj*QIj+b[5[8TPq8ZD-F'815S*
-i)f*e9E,*EH,QbeBIU4(Q0@J`,`2c1a``pf`a!1DA"bFQ4a&5Q4EdP6fTJ9HG*M)
-VPrT9dd6,e'aAETTq8$-a"U"r6`!68`eRmb)J,,M8pm6JcJMh(!(LK4!9@2`ANJM
-k[)!h$PXibbEM+PKXmBCXURk3!'c[E'bC*2TTUGSQ3+YH(`bZpNqLNGf,DVklFrF
-%!mP493IpV*Z++"8[22,D(3Yjj+e%`8q,B4jj++)I1%b40rYBYU%Upe"KBq80'b)
-,S(#YP3S1&VcV$DCc95VH[M1K-5LZ5'mq[,--9'q&e$")V11&KFHk$P9()DN[['T
-LL,B`4*1STJS9i%@@DI#!i)Lj@@9lfT&Yhmh"-"FbYSBrF6e0cB)ZQ[+M)5pq`5Y
-*(C%Zk8Tk`3*@H`ZfM*F5%$FiMZ-k0cFI"*DE,,(jV)P4i4J-VfMY8kc!j*hG5Fh
-`RVLN&Uda35er#l8`RI6h6KVJ@%626M6K5BJDL3a(p84&C-M["l!Y5kp3D"GEYFe
-!0iTdQN,aqMbZQY)fEU15qR'4i3CrfAH1'idAFTed&6-%&,%k#a&*8Sfjk9)"[h8
--bU20M&'a,!&5aMHD1R5rF5bdS`+f#%XJTJ-$,ibjFa'b&CXkHY!&&d40'Ie0(@3
-5f`3*Pm"rGEf#R$(%b"PkJj3DZ53+65&*P!3Q'86aDX8h`"ZG"!)c3XD3!*D3!+'
-[X+1%113X4k@pFV9+Z`G9dDM9cd#`%U"FSGm)QVXHUKj4B8e"RA%&mYU+"9Fbh*8
-JJQ-K*B!L!%"PkiR(NP,3+69508QL"V40C3EQ59MV'aJ9k%!5N8Y,UeVI`-FQI,a
-4hN(0r*J%E#KF"rr`3(Mc(i"%18dkIN%,,Y$a#eUXDT!!kHQR3R&48UaN&`h(9NT
-0bXTXF2cB4!b'TZ4hqiG@d**NedCal6Lr0QT9D`dPb+j5aeSNJTJNrPG90+PA-mK
-`jE329bPih3S%,e)+"V#a@YZ4L8eUa5DjN[bF$1*QBLZBf'5FLrfDQLEei$k-JN(
-l6*K(Uh!24p%!3%Q#eF,(")mcKAXUXq'5)Q)`!+Jr*B8cq*4G0)@,@[P&8r`Lj59
-4dFSZmF3U!B25"9prK&k'!D+9iE$eZfKNe4IYR"jqd3IDM4M!2GE-VR&kq$9qA%0
-&3C+*MXBUp%fSCfE6K"53!!le$r(@%K1JeJBMY9@*)M,aQD!T&S`8k*9FT4H')[2
-MrU'`%R1p9$#qDK8m@K'ZJSAmNY9+rr@lE'V9PaA,iCGpc09YU(pCXK-EZX#J4$%
-9e-$F,p,%!H%iQf-IIcAU%rpcdSq%h814UPJ%`lNClA$S#"'BYVCp#JNil&&+q$e
-D06Td3"@c4Dj%UNB[M3l&L#h)f34RUj!!%SM[VYT0M(jLh(eTpp$dXhN%GVE)96B
-h-V-8#8C@fXB85"d3qiA0(HPY'-`5rJ8H0(r9ALphfZ@*N!$qjk6`TqQ6)B&b9a%
-B$h3%ZJ+$JG(!bB!aX#G`16![d"5B(RJrF%GJBk!d8"K+KMbKpY#QN!!TT!RG'mS
-+(3M9KEi+[4LD(DS2h4(D'#S0&3D6`I&J4l!V1"JF$GU$kF'M`BA"fQ"$F'C`ER"
-VF+Fhj&9l%pj0hN([U0IZ6IFHpGCi&hKIpml`c[&HkphXhHAfZdIF1[FXYpQpfjh
-K6R&Eh&IGMlJAZH[GGlLIG1rbqAh$2Te[PUr2YpYhhRI!GpQh`0IJQqQEkp[UfeR
-Q+jXU5j6CbJkAYC@G,MYIYVqXUQaj@AACl,,kXQPP0jIG9lE,(r*Aq%ImlIiGrX0
-qKhqhrq48SIJ(r&502KX6CABf2-5(q@ci'Kmkf2#RI$M'KKIjX)F0[q*$Q3dIiF-
-@0Vb6$leX@%e$hbifV1A$c@ci)KrHa)CImZ(GE2L[I2J&'ll&K`eXf-b(Y@cBa)F
-,fE#4$iqai4)q6'2$aAaiMJeIjm-6E,L)$c[Cm'dqG,(KcrK`"a[qNJpEfA!f(`k
-ci3Ymk'I$k64dPl$KrqE$KpK`"KmqcSEraSGcfI!rq(!Q'hl#KbpJZ48r&P,UETS
-L"4"6!fGBb)CFaHjME-L9kNjM3kj'pcQ&U&SZ+Tma5!MV$H!hI$M'AR)&ZA[BN!"
-(J9YQSUUdSLSB!eH%@l!KMb,[-icpTrSYH$HbUijaKM[BF$iI[XrBkr#cJ,22CZ*
-iG(KI9)KlN6-X9dcp+jqbX#2FQ,`TE-JM`TZKZ1!SCimSTLlb+CGLkJ-q43Vi#5Q
-2#j%9$%XiJei"h!bpHJA`b!k5!UETP4GmNQeh'4pHbiE2mH%FG[!IqA!''r+!&Ab
-G$ERj"KFS8*K(+!3[BrNHITCcKMd+TG4aKLc&N@0mkM36b30,X)d0Z4%'$bZ-C4P
-RhmBBH-!1VQ5)Fi8%e@ci,"q'f2"[D4MDLH8rka%,2F#',r(K0BTVAU*V3ZmTTKE
-b+@8!H)42e5UQ[X@RDK46mrR8(XA8Ir+T,)E@crR9pc+'lq,R#QGSB`aFqD($$&%
-H-5%EBcp#4XrC53&r)22A'h8SUVMbhfJU8++BQX'R0V0M&*P(q05eLLPZMS(h&FI
-Zj&2k!-"4$lbSB1"4(eLZQ1*"*Q"46$A`U9bf[D0F5)`0Vr"KK!f2m'%I'elL`eP
-X@-H(1MEmQ!p(f2!U(dECm!-DLL)f[-b(@pL3!%Fl4if'#rR`HUD#,dRjK+c3&i$
-FC-3,E$L2$jHai6IjF$iErLFISSXDm6iV+2CLm8qXL$'b!99A'8bC90$RXaG8m,5
-a!BPbX3&GZBNG)%23X4II`Q#F$3J404Y30HUGHMrbE155"*cNL@rE16Mc,#AX*CH
-PX)66P*3U4)Q3!,af5S6)!CLC()#jjD6`YQQ68Br$Ff)dH$ki`'Z5rJ9Rmm@)Y`F
-(1d5!(khQ4q2S&1mDlG(TBS%`#ifBKKilTiRG)PfF&jG&ShJ4`j0L*T)K(-"bQXJ
-9am3*-8GmJX&bdF!RTiRj`f2L6P)X&V9B(-ALbpJ"I&k-TH1c,*D,6e2X2$l0XC2
-i,)QG`1Ief'jmIKE6i20#c)(2rileiI-IXF2iI",V`UFqYJ1Icf,Em*NCDmIRqc%
-CRcQa%A`qM%hK8aLV`+FijXIRX4LmV09)3ZNf+cBYJA[l6SU3!%i,lLd,c!9BpcU
-fA!HhlCV!c@*qi-2!YB'GJDf"cB(5d%T4(I)&5N))@+)TY$*3!m!['QS4$D'9'&T
-%[AJ1UVK'c"8E!r2&CP%XYJ#%p!Fmk(0)$ZM!C!Zi!%bD!rN"6H#j3(AJI#!'S$+
-0#rJ#b-)"2$!2Lb-81,%iLJ8TNB)*+E%+#e,M)5a5X$L'a6NXAX1#e&L(a@NXINU
-"%iXV@*!!'LpKBF)#A3`'PQ,a-4DNaUYBG'$a!4B*,'SSF'*a%BX@,*CMNF6L*5a
-#@#a%C*CJmEGB2)2&9eMFKm9h+A"L-4q,Ql"!Pj[L$LcQBI%K&YqN`)R&)eM-`1*
-E@-c'BJ%@M9Mm"SYD,0l#JK5`#!Y5`0[-L,jJ4[52h)MqL4[4hGb)rS8EdEAFL+l
-K4[3%0k)(Z"(GcieS-cHLhh)MZSmEdDqj%6h%MHKKEN5Ph)Mq`)hS9pb)RZ&'p$9
-Z4$[e4K6d)Z()cq$@lP12LDp,,ZZK,3V$@ZkXS!i'q1!9*jVh1$k0LrS*&h@MAP4
-S"N3YCk,HCk+@+83GFbBJbX`(Yr*"+hlDmG1$(b5dFXSa'd6ZiY[i0Yr'Sh`E*A`
-EfrNf#[MP4IabPIEb`lLmQ9hqlqcb$NaDf15rXFPKrN'#6@4TSlJ*HBGEN!"mCLX
-51&@MUfUJqYJPMR))LEb#K+VP*563kTLNKipdI%kI@C1'cqJTqRJQ$4mc6BND2V$
-44ebQBf,VbaE1h21bKErd5aqZM!qTfcGD"PFk-rKL)cQTmB-[5JG%&BkRk3GieID
-bjAX@C`SAm(qGqrR#iqc"Uk9J1N`6Yc`"CM,`HULUQKRU[c*$E@5'ZTJCDJ-ce0R
--8(r*$(8k-p5IFd0pMK[U$'kSrm!0pCqjSEl($IA(h&$RFN1pLa[U(Ga3rmJ0pAT
-ZU(rLK[VI2)T[iP&m-irLrmZMH#12iUdmL[mAMq)R@45I3$6p`DkT(%R4Ci9irDK
-c'emFFDkNaCIrk%c5SVBDQGiH#0R#aIk9LhfFLrd,%q[M(5%*4GFP5%c2(m%LN3T
-!*K!VH6F@8AZ8Z6G4mJ3EGAFL(5Ni4XkIVF`4K$*k"Xl""Ahq1qIJM[i)%R6AbSl
-DXPQ8iAYYp*bT$afeqBc6U"K"ecepk,M(K13a(H+`cX)A2Hd@5ZU1cXdI3@*i1&i
-A()-$f$,UD$SN9)dm8ITX'RS&Gc)r9Kf#m,4SVRP08FLHFYf(F8e2NEHYabm+jYP
-b#fS6rY%Mk@ZID1C*dl8LR9iNd@p(!XCMjRUU@-aVR0lpdf)YVq3@,")fhD+#kHf
-,#QD6'UNkelZS8PDN4kE(#98M*`$*'Cp&3XejZ3QSm9TN!T!!FbLTY`J%N!!I0D(
-lX9L&(2cA4#X5N!$*`6ZaN!!GqS4T$$53!&c'Q[!UL36)DY1lR,L$EQpiBLSm*U0
-9d9P$e1p"Y#%6h1qm0m'kEBKj@pkR$Zr3@8``XADQaEi&$Uk(AUh+&mCir5(l6Vc
-DJ5iN[A,SXESULa`bZd`Z,2Ter6IqXblkbrFcTZ5CiIpqGRIQ3b"3f``')irP+,V
-V3R3NUBX`HL#0[U-YEFG2QkAZ+T!!1,9e!Tfr[HTUVF2!c`G(@q[3I9-d"afZ81H
-)hkl,ljBGk0B&(@AaLI2jhE%LDF2IbXl15-r1IRR(2HMJkiCl6Kl2b-j-5mddNRr
-Mi(kTmeEY9Ci0&6pI+Il[`L3,5CL8i)55Rh$fe&@bTh8Hr-m(cam[KfQ)Z$M6MXk
-$#j4-P6E&1FAU#QcTr0d8',j&ZZYi9PC1+VY'3UUPMeM$8GHb$NPUeRGi!L4@6Mc
-mNpE@1Q6&)1(VGJfKFU)ladp$#49P4dTdL"-LLGNX(H@GNIM4-84hC9C*r,3&@['
-f$4#[NijHTrM4heRmk(@,rjH(p1),a(U)ak[#BZNBlkJ&(5RNVdMdILCk4N&d[86
-2+$JX(3XA5J8'%[Yp*"UGRX4(BTNFU'N@YFp2L&Uj(dk&+jmhL`@V)G!"8D+eMMj
-JDX@$fDDNECCFXf*Ni(LX*d%[,TP,Kk9NRRSa0-4e8j*,,a3l`V0@Qd3Y@bbMaDh
-NQYG)5d+2(9V!$e(AF4D*(CQdZ+E`2*,I&&("bbCVmA#V"AKme8JR1M5$ZfU4JYR
-)UcRcmf#6VQ*ShkG[U$NkS+5NSe(8fVdQ$2M%&,U$A""T&!YqT&'T*KYj%fNqQ%E
-Xh&"+0ZC6%[%D)ce-CDIjR"DY3Rf(@rK433K3QN8S&6)QSf1)R214c14'jk$N6LZ
-@jH2aF8Lmk6"VH)E[iK)NPGpHajcZ(i*C@M4J3DC`"-VR(9C+M)m@Sp*B53pUB9f
-!X@SI6Z)CFQC+5Nk+I#&AlNe,(lb3!*ACRfXmQ$kCMTGj5jF5LqiM)Gj!+E"dUEC
-FHZ10AX1k[eXadQE8-28K5BlDTZqbVjhF(j!!%+"F9HkJVYrE1d6YG,"NmBlJ5EQ
-*fkP53GBq2RG"dE5i+#Pk'9Gd#lUB@mH9[CPe0E%Fh4dJX5pe-##1NL#&iN[d(3p
-DebR8AV)#Y6p%QE9-lAeFlEX8DYr&hCm0DXpAU(fAAZfbp"!dr`BS22AmmC51EI+
-C#`FbXp-rfL$PU`ST@C!!P%%Q8hI)0A$P(XI$lQC+#4ZfPqC,b&*A)8DHF!U)VAE
-&U61C+8V*,%Y)c40AD616eQ(cVRB1*$T(@QrM430!(3kX4+e"RLJ+'Hab8+m!#9"
-LBZKi9lX`UUC6&bXG2aT5UCL3!*8NK!)'G6QP&c0-j[XXQ@qB3)!KBCPE"T63Z3-
-K`96KekZLj$P*&592-P@dk&8K-p"fIG6",[D(E@)(1R$L++pfD4qle2JhZG33"45
-3!*LbTMl[jXlj#T@haf(kDSkJ&%NaZXUJ0!K+)kG!5@AbQ`P0iJ+b!5mUZmZM`PX
-r`6Zqj8Q'$0hQDDZ#GR3Xk#@R+(50'c@Iiae`Me-P3*HZS%UUG)'KLK+$$T(IECF
-'`rRG+&#4T"l!61MLR2$Z'(Q43SpHpFU8'$k!4c[kP9hqmDcL*Z%R0qAbUXqI91Z
-V6c&bhG8R$[AJd-R@1P+'l'!GMEG+)Vjqq6SfV"Fb`P9*4C9r[8'0'D*&3VF5N!!
-KCFpR%9T50FTF!rd-ZD5K%'BURb&14f#Q9ZV-YSB-N9A&LSaKd8%[+KrA0rpN[rT
-'1al5U(`KDj4$)pcM("jlLA,5USE!68``'[rk"J''8l%S"e)A5b#UrTMK!AXN),m
-ZI01UK5Y39)9THEL5&0A3CS9UB&MPAm`ZD!qE@2cYqBE(9`TY8NIq-+RjC+j1If3
-*&(&lE"$ZXfQ86!DG2$l3DLD$'1LQLJB'5qUhmHTT*@IL8i8,+F"5ac,I0M+%dUJ
-K1#l#'S*4()%5!mHS-BMU+FS,20TbdV"GrS"2EGHiV5pCA`A$9r6!Xrj5RLMR0J)
-QQ3SkT3#$JSS&AKC`f`()4H8@(TcAB*-Gh'`1m'j@G@')58(BXL+6*IH+eTS943H
-L1&LrL#IlmqmqXY`L"a4-86,RPKSPH-U65@26+A,$N8a[E8m-A83kNiQe,GG-@Z`
-PL3Qj2m`NcdZ9'LqNefP4J`T9adJKCd[j#`SZ6#'U`q8V4$A-&8,E(eGfMNJ)D3F
-3p0Xk(UMdTPfL[jD5KUTD$*F5k)&%84XT-1J[,jTCrZ9&mqKbFpj2[Lp&3p&@-Qq
-TFrRfl$pr-4b1YQLSM,DBVN4Ea&CJ3TXBfZmcifNT$fep01qS8DTaVN@TaMqV8A%
-QhpY)S[J3d#cCZFd`q2UpKX(A9PBZmZHU`iTmJ(45NIq(HGHTA(+qQdBLT1*C83#
-CVkZSCS@aSB[D0*9+iDkfZ%5R"DE3Y)(ce&9&FGi9&KKdAQr5JJf'&DR5a@AUbX9
-di4HV6EfqfY3mrC68LE-5p#SaPeI9cNhA9lAS*QfpUle(ak@MUdFi(PLJ0K6*%J'
-bRESTECPHP4&Upk,$UKRE(fNAH)bkGrUKr1k-#"A$lHI)j9-1'SaeHjHLZ&XR'Hc
-fUpU!Y%jLqlEQP5(K*411DI5&G'a`qU&8NfieN582+%5biR2lQ&BN#jLlL[3LP3R
-Fp3qC99Bf8RGC$3##-Rd!JY#-C&8-,mkf(feA9$*5*E(pT-iX4e&*Y2#+!aG5491
-bLaJ*Q(,3BmB(UA0(#[`P0KNG!U,a`SX0+[,"I,Pp1DqSC(l91ZQbVppA6P9eZl*
-+N!!PC!&bM5T!,QAaM5CF[p,-J35""Ld%NNJ'T0SB*JkG[P3f[k*V&DjJ[$XaFNq
-('eJJ66L1jBaEN`bFpA4HT!l-R+%VcellE+6UZ@0j6mT`*I1Q9HkfJ&GdDh"J4U"
-%*h3!UP[E1UEDh61U00dRdAASYFZR9k8@ki,cPh0@G(%XXB[fpZ4AU2LII*DDR`B
-J@Jj#ICl`VJZNak$f!&cY+'[VJ8Y[G*YEei'ZTU(fqFG)13e)H*943@$p9dM)e&C
-Q!r(dUd0bbbPdRrMBiQhZkFG1VVcf@856Ped9lEbBm1)a2HK3MS`mG5Z-+ST(QkX
-0$c-e!-VFL03j83Rd!2)*6IIq`(Z0J[jiJHM@1K6PC"jU1D`MFhf(EC4i!mCA&Aj
-pZ`$4`bmeI1b$8Q,@,6l@9$l2QmU&LUBb*h8SQXSCLUCbSEDT(*6)%a-2hcL+ELK
-Xk$F*DRUXq9QJUJ'#cq%(AG+Pk8RP&kMP,0[4KTBcFc21b!Gc-p1-QDRTQ4PC[pp
-3NJ8VXU!3k[)3bR6aSEVY()Cq+kqL*UQ+#J1lH0AP4r4&-hbd4-HR29V``d#b(HD
-%Had9IrPKa9mi)'S3ZdpUdK&*SMUXL&JN94ermbZNScc,S)9IT`mkrXk,*bSAZAq
-fDa8EHfl&9e$hDM5XVe%fhmUER(MiHTHKJJfVjKmZfDJBE&B-VT'1rQNXr+LKiLj
-q+&c8GU%Bq"8$Md*X-3Q)Dk[[3%mqIfaqB"BY`UYd*0rJ+[`&NAKhJ)M9DZF*pe&
-Jlm#4[K2GH'Vk2ILKB39[C#33D-iKD#9id%,L#e(0JP+(RT3JUIP#cTRXNmI2C-V
-fiaHb3(!L3P0U9ZEaP08$"*r3(eLkP*d)$a!F$,Uq0,cKqkYY8SAq`-,e!B-HQ%-
-LbQZNrXTHZCQ**$JlY"&1LC6a%$JNi2FIYDJ$jEfBUAM""0bM"Ilj&LK+iM"6e5)
-meV%3$aS2)hic-[+1F*30S"GV8,5Z"YJi3$`-mDCY#LGCE0Xh*J[YC#I[#R8'1RK
-c8HBGb*Y)LS3#0)3LX"TGEHDZ5'@84FNII-FhC`[E("+PDEZPBGdm8%2K@M)`BSL
-6mQB8SF-93a$4"eC6#mLX!CkP%#+!3B[U-pbm00U*1f4rIMFRDNX6-hR$RD1YRIa
-#D[C1I5+S@jRjK)MqC@%KGFSUUX)Q0f25U*`UDT%#4p%1VMbH2&RlmTa%+LJkI%*
-lCF&@[NNpbj4d['!R4k6#!*U3!#ND'Y+9#M&d8KP'()+khP38*HVb#QiY`@CldqU
-JkiS+13kX)!miR'4'$dR@NLKjGb'DFXN35P,&(l*@4+S`N!")&#5mF3-*cbK@,h+
-hKa@jN5EH5Ber0G1H3Y%i`M)8bc951MD*ihEUe-C2T,P909kS3RbL6Nm3[DYH`D`
-NfYD[-JKU!H2+4#G%rEXXdFGL9GUU%0N3j-)[B@5KM"@6[4`eGRpNmFq2b[5MANf
-PRJdL0!iEQ20Aa+arL!3b,C!!e9&KEH%C)**V3$5-3&#*e+SP6#X"p)q%&fUi%+B
-#VTV`"MNrV#irSSLFpp$JNh8V)+cT0eG4[PP40EUpQ+V43VpLS&B-K**`N!#S+GG
-d0ec4L`Yd+eDd[RNYCQQEeiB0&dP0'$!X,["VY-h[!PIP+Qe&D+V59j94ZTjAUkr
-lDTi)G%V+)Z30VYdDkT5rQ,Rkd&%L6+VC4(3&JDBb3ELmL'#2)m$QEYB5*IAAJ0L
-Vk6CFSUUY6*!!U(ajH@#K!5(9!F8@&GHS&S9GFrGU4aFAb+XX%[4EHrQAFaA9D#&
-,a&a)P6Xle+*3fG+`!29bJJVArP8@D4T0hHU)&,eBrVE#P9GNVe69-,8AI9M1GVY
-@S-#TFVE@`9jf+EBfA+NBG+dZV+"d"C&aEaMDVZY#6kPmCG@m@RB4L1m*KG1Cr2)
-EEF+VZjLip'krm,CRk`cJ9*3kP-GeB39C@'5-r8mPiTLXAV8aP"I*8N*VrL![55@
-ke32CLU)r2"*A(3$+$hMK38MerJS)U"ikhPVc#PJT+f"&C030)l[5(hbM2+#D69h
-m[8+Ge95ka,UZACq002R'"Bi%2[*,bNF1PBNHUB'!6LKEH3I@(B'EMQipY-hp481
-@b23Qh,&3UeX1e4`"iIp*15"eL@D)PPBkIN'JUfdEr!NISdT04i3%R6LU)!Kc&8U
-XZPXAL9Fp90fT0a,llKXX)f%N,6LGP&HSEYCA`5M3pdmmr,mq*&HBhfj$KGckmcN
-JHQi@'Lb'D4+$DJbBDeE"CK6d5HF1($)4F41[afAH"'I0Uh&Lfpi%N!#jN[[@kJj
-HqSVHm[mUIEVZJD[@Q3ZTf83@1AR3R[fJhUpX%hN9C+HR(,q3!(i'dpN'al+`c@a
-pIldh8kcIc0Er3jY*,AFcUGV0'%!M),CliZ((5N'3!2A53P1AAjH)*1VD)r6iSB[
-rp+jC,#8dm%"X6!"Y$pLZdTqAK$r9aX%GJQL,FdjdEbLb1@Hi*mGe+Mi-fG1iIMp
-G6iY`C219k#DN+3A#8BC`p(G&q-,[JM#8Zh'QT0b0-pG(Z4[2rcQ9Zd''!19Ze%M
-+hDKCAq9bK2pXbPd2K2AS*ZKbPQ(#Vf9JBU9VqDAhK&hkpqc5R$-EH1&M9rqQ&kj
-()D1rd26R+5ii3RqR4'M6$4*#NXlATlJ)4q[285#[$eUV9TED5Yd3GKjm*#-Rqm%
-,'CQjHNPGUHQr0fD#F@J`9HLGJ6aGE!0pb)`+YBm1Va%l2-%8pj`M$UpGRV@'R2@
-*T#i,kX+CND'i14FpPeq11HZljE8FCTZiCi1+YPPR-R268hiIjSDY*rH05aGYajp
-589Q9($#4P$IQc%b(Mr([%+P$repHZm)YmfZMH*SCCG%KmY"4*$jViG+0#-`p$NH
-r"mZ*`3FT#ZNKEl1Xk,*T+!$3"NN1e2`23m"$X%Uc$MIiKHf(q&1fiT+Sp*bXR!F
-c8mU6Y8T4@mS4GG"SA+%SAM4iqD0Z+cMJ5RqSJ(&B)VP'di3R1-HLpK)`I!)LGGa
-ac@+$h!YRbK%TQFm00QQ+L-bEmSkIZHh"5N@3!$cam"2Mh*RGTb!pP41d[UX-@GU
-,+!V)(4p"GkQXIYPbepXJ'-#*rF#SF[TclB[r+TIp[aV+CpplSM+bpaHZ$l+@GjA
-BlVJRqfaQEQB+V#Se*b-cGAmk-%IC@8k"6&HdrPQZ5!frJX"Ur+%GF1)#!$a-jVp
-#GaSL&0!9Vkc)LP-4[CUK92bIUNPPaGBUM*li8e2,3f4U[4"jIJ@PS3%2M45NJ%L
-8rM`%C%jDN!!!489"34fFH2Lq,'S'i2,!US08+LYH9bcUeq@)+Lp)k8@KLr+$&Kh
-imSkRC@GPjMV6cfFE5T1`U0)ABF8%[!c33cL+HdY9[!01+%a0McIP$MPi2!!2Q%f
-bQKTB$!$T`5AAG8&Nk)+NVe0C$,8e1(Bmkm(M[cq6RCZ$VX,hVa)lk9!l$U(Ih*`
--p!qf5RjM%1`$B$qBHqEm"A[k+M#lS%%F4RJd)L"1b@r$32"R6f$Ki@*f8#'6ZdS
-*I'F4EJa-9VQLlS'SR)2T'bK,9%lmF2p9(NM9kaYF&i3P@pT86L"G,e0jd+$HPlY
-lhJD`JMm'iL)H&iJr*m)Vrl#K,XXlmGmalm3I-)4jA)GK2&LZBBMe-i`(0m``(Y`
-3`hL`(-1S(!@EcfQMS2"[%!@+JKJ!!$!$384$8J-!9V!293XX+3!UEA1rPhGC9d4
-F9L)LSK84dG5-FF`B4prhhAh*mm[)6-e-3FiY'!(#JQDQclZl!L+HcG3D-kGa(-G
-Tc*V'-DHJF4bRc$br'XFm0jil*613!b1NjAkH"9`mGp0mrqqk[Zqlc[0Ge`8E()%
-%34!%3C!!5)TN4#[@eGApC[e6qRP(X2J9D-%cB)l$R)ET#X0K3Q%Z`h5#kAZ`cA-
-UTXP0#%&4j-RGTh+cJdGENZSd3rU&)H2ceE[UC#-32Blr8LfQAbHedcc5,+-fHKP
-r6ce!(bI0dBUN22SJk90YY24EBdbdQFp8CaJPdBra2kL2d(G*Ll4X+Cf@*#h3(TH
-@'Sp'Cr(&DLP06hT$HeVkXr&8G"Pr6CeLH+-2mUPU!8e,QUfCT-('kHJAk[JpkVr
-TlU5"@U9dKSBNhDrG+6eJr$2k,"qN(U@DT,Xde!2M423aEP9$M2,S2r'KkQed4e+
-`GPaUS*5NKl8pdN2'mp(lq("eK(%UqMPqVhU5(N`DUHfAjKSjdA[j0qTZ'TBd5UZ
-AFQPqdN,YN!!dccJFEH'4DLFM2$UUMMqM*Y1rNMTV1k4QkT2dGffcp%FM+$U"hkj
-Q8,qN[fV[5(mcmU-cq8pUIf0Mp1[mGfS6r5@TVpBSlD+H56rAIT4H0Gk1[X"lUjm
-E0k0[m#r9EqNh5GfeLp)RKMXkP[pAh8,r5(TI5j-LU%I5KeU-p)1a+EU9pe*6kA,
-5VAZdck3"aPI4+rNjYCZa)RS9Id,pRTj-kU)YPeifYN9ra2qMlU4RNcTSfk@Ye$l
-T&He0UD2a9[4UhP800Bj%Eq$AeE9d*5P-@b1YSkY*Pl3[T'['ep(VHC[U)QI5H8f
-A%ShlSZ0i['ShP'J(YeP8bDBPFFdLfG$d-*6q"XNdMJl3ih5#EP#G85IAMDXl82G
-ihBNk-RYU#r-#4FDBiQAbk(%(9([aM0'kYYUXDa*-Y$Q1)qiDTf[2"h5YY&MADQ'
-bB"k"'3fN#4d,1XI"9!)cBic,2RT'VFYZm$bA2F"(ZqbbX!FiN!$MK29`,#&`KHa
-8-"m3GTb`BpMH'E@kjS&NSe#h&1VD1&RAC)qZQBXP)rS1[Xcbam5936&"%@P"#CB
-r5[D[h,'@j[J0ENY$mTiA,,IClcb*i$aZ861L,!RRQM)YArdBi`jk*fDrC80QmUR
-pPND,@fXYYcahH)[Y9*4JDQ[+M2NajK5b[1HBX,!0lZH@j@A6X[XbJLbCm4Be0XE
-GP+RmVd#GfXRjM4Xh,3Ehk0a3,BE&Bc%NZiI38d4dD"kb'-aD2+V0)klk#Kl0BqM
-FSeSmm3B*V%I9$!rN#dl)`4#-U,(N`3$'bEKd)('Gf--04m9b#[H`(@)aK4XZYK6
-63,&"QU&L&Hjaf$e-)'F+SQH(Y+TP111U2ZCi-De@5cr2HKiAT#Ck1(*a6PcKA(@
-L6bEAG3XhN8"DZ#S'A"L`f'&9ER)P-JBbF6@qJY("ZDY#!$FT0S&@ZF@PQEL5@,(
-Gj0#!#Q8XBVGkRUeJ8Zdi9fb#448V1%,CNK"[8EL&i9a1*J4VUebS40AU*E)"Q&e
-f[iDiYKr'Y2I,8(LKa@`TG0R0K@3a5ebi'YC40B&4m@mh8b(b8NZK$6dJHD&$l0,
-&4ZaA,B@5CLj8R4"K*VEGALKk+Jl&(V-L@$NNJ8-4NL6Nc'+NfJUVK%YLQELUG5[
-%J!AlH,9k9Ia-#U)QeQ%@)P@KQRp&95M)#aA'C6(Er*U"9+,`,CS`5KXM%$j4D6!
-#$bJ#169'8M"`c48[cMQ$-"3@5#[SCl"5GQ#$HYi[3*clqk*-eAJQ&b+ZD&3KJFC
-,2B)9P1YqGVEE+Bl(kqAdEqCDaDTfSGeeLe'PVG"8Y9NU#V0#'lpmP,D"e!ZMfK9
-4#8"QJb4&%aM*,$$UY8,SJ`'"Ja5cBM-,&K!,1CdUFVYE%M[aQd)f`'ibA&a4R%b
-m`K@(jKFReP(X$1PITdfTN!$2eP%dl)iAZi$c-`U8(E*9XE+LR'I,X(a@KGcV99Z
-CqJ`Gb[B,"k,DmFVJJ$)@Lb6kU$fX5j*UYm"@$%#0kqMJM3%@98`bZH,p3p31`5E
-Ca%!*K3aLaQ@4Q#c&,U&Q5"+h-+X)XBlcM+F+,jD!$LDK$4CcqKGK'#C$Bkc`N!"
-+K9#A6HaA8$0YB"9ic[5SdXP4XCSMY!+$K#Ck,&6S)A1K2X"-SJ2J,r4B-,#)JI#
-JSX3+2BT0X)UU"cEe#MYQ@q&BlGLLfV&&D)Q"!h8KP-N4mKcBlV!*Q3"PXb$D*E%
-5-i`ICAAH,diiG-BLT!NC&HSSU*8H&+q(M4A)ZFr*4LiR3cRX3JqE%)S+UmC$Q)P
--%R05(RK#MdPLRY!%1!%Ki1SPNdF0%`IN!Gi$GqGK'`6&25UM)3i8*q03Vl-G`TJ
-80![ZFl+4R`NCKq"5r"'&j4&Pi(#b(8,8HE%m`H9L#a2[hqk!DN`R4kKI%DTL5!5
-Df&&mKBV)S0M+m2&q6N@XJma&2RbU3,XIlb6hpe9q-JjrMbDD[LXjU0@0E`L(kE$
-230rPMQ[+#0U3!0NDkrl+(4%8pBjka@G%"GUXU`kEi&(4lqbi0!'li'L[m&,%[Jj
-M9LpdSRe`aUcT3&p!Ic&-X+jprdQ"9Y-!JjHSQZ1UYLS&R5-`UB,"bdHUfSif'$F
---UX9r@2F#CEbd+!UPD('HdFGeeSN#8UmYpjK[,FFR4d`Q9MRV$TJjA`P+[Rec4(
-jXCN*kj[3m-`-LP!6Ul[JE1qiT#BhZQ-c0eHKKDcE)DXI1Yh&`(K[*XEak-q'QDY
-VbaHTIhPVY5[+(395Z)-LI)Na+8V3`Q(-m4CSFh,%`*Kc'[*U--D,j*ceN!"h8GA
-H#PB6hqU4'T'r15,)%R0ViQ,BeMQ0f'D(kBDYkDUf09TpBZZ4mGTm%H[f+FJ@3qc
-k`(&V)R`iQ3(4NHJ-%J2MBm+i4i(fX4NQ5pHqLPDe0k(RQfF,R%-M@B(%Cq4[ENV
-H'@5*d2)C+8(rMiq#Iah-9PhEeNGeEXpN[)NC3CQEhBf#fCl2#,cHq(JVq#2!ki6
-T#[i)9GZHUGS1Xbh1(9%*1k-X'IEmj-2k4*!!URe5S2KiNH1k,d"m2"a,$%3(Y*i
-00lkMUqT-6TZSmS*hYUA!1EZ5REIPalThjMI[M)M+h"c%4"QcMi%P$T*@`f6S@[*
-L0A&lCP@"$G$6JM,G4f-cBjSfCq)p+#-rFr-a#*lY0'Ch0N)XMSQPiDSD%418fC4
-FpAA2%K-+kMJU"VIb)jK89e0-Dj3lZC%"jZa)BhB)0*P9S%dVK#Nb3U"3b#kBF*K
-')k4eBNYT#YkMAJQ+#%V`"DQ@i$9YQf1LB$HYd@&-DdA(,JE'Y+XBSl*1k`E6h`M
-"Yiq3!-X&jd1kMQhG5f,GP`6+D52'!T66DKc'&%q"0U9%$)`T19JEheqQl)H4M*!
-![PLl*dad`6-K[4lXDE0-k*GDTQ5+ZpU*63NeTR$QRUBJ29-5d%&kTL!p-haG%i6
-lZ+BTrCPVfJK!hEJ9TVRJ9NLNN!$i8URM8ee9UdiY-kB@X9@RCQ(9%HM!(d`pES3
-%Yebe4LV3KTEi9jekh,rU6*KH-0eKEXFjkZ938m'c3bILEeSQHfTlBfSIKc%9"6A
-e*jMHaP#X-r4i`B#KdSY`'&1('e1$XIqe!Qdka%f[0BC#VD'!ZU(K"GH'4VCFEIT
-qBrTaBfLM-E6ekSB[aPI'55[Vp2#@PA9kUm1B$MLHEKF$BcV+C6TmqA58br6qaY$
-3kUUEf*3IXh0(9%`3DR&c9&0'E)3J,Y[r,MU,B%ETfZXG9'Gq#GYa2L-r13TI$XU
-Gc9(*3@l"E6AHm1VAmUp1N!$B0qU00miD3fFE3`%'3b-92N,K+a3HV2"I+2`r#Rp
-@i6mTI,r#rkV`pa5H`l"pm2URm"+&recKcbMFV["BK6r-Z,pAH,2#0bSmAZ'E&,j
-Bi8iQX4X,cl$a,SAr3q'9M%p@q%,4"ZB&6#MD+bk&fe6aZZPJCeN+(mc%JIYeK4p
-JHdibe&-+IaYY#i82`IXKNhZ"V6&2iIFU[)dG*#TmVF,rV[$j#YqLm"#&pf3Yr"&
-X(-h5XdF4Vh1lQFCHK8HbPDBTr+,#ma4qAH(I-N(YQ)T*#Rp"iAp6q('Q5U2#(e&
-iQX*r92J*KAqRm&mbe"QQ(&C0VPU[PJfZ-%@aq3Q&[k,`2b[mNX+A+RbJ`[r&G'T
-MT,q0kI3K8kK!i88XY3T,*`UMRF,2+I`YKFpN5dT-J`5&Im)+)&[K(44Z9IK1K3F
-8IP6K+U2)G)Ah9hKAPQ#8jH1-lReCfUBS[*2#"l$MHjQZS2k$M$V[+[`KPSD(f4U
-(@*V6&EjAiDX8[N6KD2*mV2!E#[p'iEhCBX2CraQQ5J-M$4+cR8(-1NE@U`TIc8S
-,LpeLHQ$Y9kY!C!1Mi)mXNAFceLm8[P,K,c2@,BckqaMK`$TEi4d9rM98Cm86$PN
--HQ*C1FeK6"BQHK8VM`F8AUr`ja8HT[![@3)J`UE`X`SIT03p49b+YR3+Mc4G6Te
-pZPIVB(2SNCN0I4Y65VUZRR'mjkjJMp29,ZIfK,QPACC22rZ*He"YfrTCqrYPM-a
-kHG[LSpd[eK6DPAGc1qqBlcfhFNTPMiL"H@&V2YMAIq2`l2CE&jAh[K!5L)qEA0q
-RH94CYa@[RANrE8M4eA9c6[f815+p`rBPackr@@Fe0$ATm$04m`TZI6EYK4mfh62
-QqSEIl[P,dm12GAcV$lIpr-FlLXrV[pllak"[RRlbqcIqqGrB"jCGqrUpNhppjm&
-(rr24dYrrjYZlC*[M&iIqPEc`i)#[T[ll`jLl4epCqqRc[h[pS8GHHI1l2lhkpY"
-aLIIpF[II0`plkSP9Illc(e[Z2h$TLiqIqe[q[BmrZh2"L5p[Q+iT6HkAD"3[5TK
-iMVN)cQJ4I0QL-$%`&RA$',jX83HB(XE3`DUfH3GFYq4BkIKhTDm2SJNFdU,)X@5
--LdC!jT!!JX6[mTJ3,2TGZV&S"&i&N!![I&G@d8&fZ@J11XJZ[cYLI)GXE'L`UNA
-8`a6"C!XRKe`'ff[-"HGV6"Aje(FAMHrX4SePdN`*1H(PQY4*@LeGmb0!UDrc%i)
-bD'Y342iA%3P"%@`Xa(hJQ,5G%jmrRQ'4`rKZ2MSeBQ!X0Q1-I'Ua#5E(U-(9P4S
-dZQY%[KbTDXdheF[0amBZm0SN#LaZ0KDR1Bc&kp'r#40Qe&bH41MjjQ-6DEj-4&S
-lBr&dSfCQYB4VN!$JIhPJE6A"-mKB@QM8$(jL`TF+RhH1TIA'8M6NPjDK$pSZG4P
-hd9VIPj+P#FE5611Ze)QejFj9*$mZ+XEp+l3FPrDE5%(i'q0,*d-C3-V5q@*J,!9
-d,Hf#rT!!!Qe*RR&A432c,YE!4+F4VEh@Pp$XUicm,Eq#CNZfM9@c*5Lj*5Le*HI
-%`&M5!@-AqReJHKYhlDV3M&GS&PT`+D6ekkKNRjE(a&i6PJaXfI4B81J`&Z39A&Y
-3kYYN%3I'!J[18!X@R+dB'`Z13!N3DJ&D33XbM,['[e+%9M9-a&kRXH#FFGG-Khr
-pEX$ME3-&,#V`dH6'U)Mp&RCd53afZL1LQY`al-"bV%TRAhQ,+b5GUj!!P"rcXk4
-J&ejT&Z$Y*p)L"XM)d%Gq@@XXk)mZ8K4j40FZEK-G,bj@D2CcJN0hIP[VUh6qLe2
-D[iEC[iECL(5MLf++l+eVErF5(5m29ThfLda#ajEdf1)A@#(qR+riLV0UUM`jRJ!
-[DTZI$22`jMd[VTS-meB+-N5LT6K[+``q&,a0SZ-R3i,J!"PDk*VrUqKD63baNYQ
-BealG+6"SPPjB,MTqBUaM3VVk9r![X#1fq@G6HRl!Q&qZDpq1,0#Xm1P@3+)9,Xd
-DUQVj+%iVkUX99F++qQT&YE$LeFfk#brY[Ac,Y4QqrX8Y9qi`jU-1cNFacZqZDcr
-L2F)DAE%ZR+!9cY"+2ZX1KX&,NcA5[kje"T2qbS6TI('Nj!XPBb&5Ha0["9D3!05
-+E-%+9DaipE2L$FN+i,EL#jF9PG5+R-S+GfVYLQ8Phq+V5Zf,,,k&520#T(RKqc$
-[iR)V[J&CJmAUAQlf)KqmDh$9dPlHi18@,aHkG29f-&@rQe5mQ9K`Y6-j)bJUJJj
-2i)JXKqeMHjfa(&BQj[LI"I@D-MGEN[2a658L0YQG(e&ZbE3FXl`6Y@YR601&S+T
-2*j1ZdZ*V4rA5ilr*-(4&(C[dG@PZc`VhFb[Cr@0V8"@aM[RIkX)BYXT9c8dajJB
-ck*mlbf(-R9kJI32d0k@kTPP96H[QjALIPEcm#%EV[6`9XG$,9k[DM4)[$mG9MeP
-HhRLIE4mjD,GaU2!d,SHG0$HFhQ[1k96*Fm`jiC95VTNE0flB*l,kU!6(f")akU,
-$G`X$F&(BSpa-fe'A(FBS!-iSrjI'6M[[%cNaD*D-R$mjc9e48IbK+G0GjC!!fLS
-BUP8BB3bMm5)R&fM$-"L'lfHffMIpHlU165B9m'%1rejM'$i3$%16CGK'Q(KGLmH
-VIh`#6,DURCm,mck-(DC%G6T6Q1$E*e'k'YiRZJK@!)!23cdG0NMAl2dVp'[r%YY
-9Aa8(1B`8I,j)J@00fD&VSC9HhYA,1kPDBJh-(*Mf-!S-h1qScidkVQV1$Pi12q9
-FlZ@A95hcUUVCKX$-8FrE-[pR`(Xq,8M8#%YjPqVk)B6iq5aq[[[%Ze`THfph1E3
-mrTR4Hlqi"&ZJpGlrK9'AiZ@$iCU0Kbmk0#p1AkdiIEA&k5`(,T9qCR5[11hZHcS
-mkdCUR9%SHiS$imaMmNEA,LXkB#V`(LapZZbTNXHb(mPk02eabq(F3cPlkhFhl0R
-hr2k6Tjilr8,P[mrqmmbGafmVrp24haml)8AY5%i)DYlFf,6apBah-[0E0dA%Z'2
-6YZckmF+EfclD[M0ml!a[ArcfjSf`@@hAVRCVrfaLk2@`+qKIZRcVh)!Z6hClSQ[
-(pUqmr*m1chCkT[1rE[pMRlrhr8[rhrAlkqGIp[UKaiHIr2IpIr6mHHpAZrrQmbq
-MNplp4EYI6rlPc0pq%(VP&F[(LE1R6CNkrBhArQbC8EISZm9,Pbb)R$GriGcVPa0
-[A6VAjFN"6h3Fh2AP$[pjB-Mp`AH%$+fjbeT(re-DU)V$TFIGGf6$QVAV[elh4HT
-R+lpDr[f+9D[IZRZVR`KMjGM+L-!eZmej2RlBTpr`@HJr2#TPq)-2MA51Z1IHmqm
-0((4hI%XDr25hPM6ik@mq02KdeRZ@1H0Tm!GI'R`cDPM+`m-I'[RJL(X(hc2`lN%
-YD$$*Vl$kClb)RlKf0Y'I91I[RCl)Vb9[*jmIIj%rA`(K2Mr*jeFRdGKr9EZ0#54
-,[r+[C@Tm%5$"K-UD*q'AaR)dAU0*0r'a#*L3!%bGUkJe-ET9r&aeSXaPP'3a"6$
-GbdaM+)p'8bdYSb*-rM*4!Hlf1)LlbCkQ-RU+5ZJabUC(+)XHTA4-$E23BFUP3j4
-$HkQHGP-$lD&pp$cYTj1iZq)j&2F,Q*IlEpa(p%rFQhBR(DIEU*cqK,R%[kGMQ&L
-'JSUL(C4-#44%cE5C'UQ*0Y,VP%([8#EPidDl644"-H5Q@%UM,E5,IU3,p#CYSip
-S1qe%UIqr#(LE,Y+hG"2cfX+SVSfZd9AU4ZhT@8UN8,S1l"AbSbr4CET&jfJ!GD%
-R`I3%GD@1B(f&AUEr8!GXk8628'Ik&pe1Ik3qp(IU5hqKr[3lkNGrTFrT5qT&2e!
-2qT!!2U(rd[[d$qT*2kIHp#TeTpm`KQM-[U*hk4I8MRj0NqQA0*0q5ap!MbYBj@2
-mCY-dQN*6D6Up3Dr4RfN'IS[S1eT-5fN*,D")QNIcD5(0KHDANB*Ed2SFdhF!p1e
-)Jk(cbp$e2r3!$D(l+CMZS"!D5M9d&eQT6[Qr$`)UCPFib%8kaG&pG)3fd"TD5q[
-TDeT(Ae!UI8BVk5YD6Yr6#PT&UqNYfYS#"2jI")`(!GadTC'GE15Nma42`qK6qJE
-B@H4(2dbM+)@'di2d%)d%d`LkKqi&khXdN!!'dGhBmP)Jm"2pl59"3$"%8ph%31"
-6k2!HcF&[3K$i!hi6"i&[S1d`k2X`0"Ek2JKpl`8)h!0YliDq%`8"-YEa1e6EZ1"
-e#1BD%I+@Xm"&'*h$`JFLe'D`d%i%8a`,&d3iQ#h#Bi0&b(D+N!"Z3V#NDfa3b3,
-EN!!Hcm*N&L*CQ#[#idGBB-H2pfGK&JXM4,#8XU#`X*S&U`L(el$3KB83%A)6@)K
-QBBN)Hc0&U1mM`Zim&Xk)d'!@i83R%D5c)U61&Z%VY[QV35)X6fGK*3XA@HM&`L)
-4[LpLJ@hq[T'&8"BqBB'*@,9BK$IEXm!5pZER)QaMUQ`VCf%l#a%LI-4)q4%MbRC
-'qZf-I0YCiVGhCU'(#1'-+1(e,,!##fH*$qr0!L0a1&-dbXA#C4&fG'@"UCA-$T,
-$@ALCKCpBB#4)CN`**KCB)K2BKL#@l#"'QU!j,$"eJaMS01mASA'q#%fR@@$EQPJ
-"0$(P0M,5EmaLJ6&YC%`EEl,!LR2MG"%bMV13!-S#8c5$J9F'BmTJK(kR@B6mSb`
-`)-[hSaKSj[GNB3S,$'KDbeKJK'YPS0$+PQrGbJ)VUYDq,,$0VBb8V3aB0c%5Eh+
-c`&6Ca!LhLB(&*PDdQiD,%-'+,B+"G33VYJJ'bM%Xf6%-A')B1@)BqG`"&KKCh3b
-XhDbbZ9NPG,-%ZrZa`%MM6Q'"9GTB4Y"B#`X-8'*CBQ)C5-@b5KA,LMD@U4Ml'JY
-XFaSVi,3'&KLjdhD`X)Z&Fbb`5T,'b*('UQAD%"'f-+@hX+4ZB8RG`JTT5cF@'1'
-fX'6[%X[`A4EKD5blQ&IB*D4UZhV*9&XS8hqBGS@b89SS&bk(F4I+mNfB$p")leX
-S&`GJ+J[P-8F,j6`-PUdTP)[k&-SP(3VP3pX+jGdif0d$CN5Kh(!-"J)DZK6+HmT
-K`,!(`Tp2J!(bqGYKHX,-K*N"Ne)SlbFX'T!!jF*)@3kFNZ@50&RH(5h,crHAjIh
-6CIP%Q#bV4E+XC-LbhPQ@liZ$FF[b%C-XE`$$"QaFkiAT)F[VXf"@`Lb@jDq"r,U
-E,(m"3DPjX[cCIKJ)HqZb,)H2N!$PU(3B#)VU,XXl,XTbFUSX"jA"()%")UK0PTX
-9@Gi-38diD%9RNe@@)k"N4$2-6l)Fdai'bQlT#J2P,R5!Q5c,@HFmmZPiMr`RPdI
-qIEP(2S(1LAiHfEAG)qZA2I)UJX%"e4E,P&dXbfkBGX@bTcr-L')j8!V6$qDeBYQ
-m&HB#6)pLHFcXBVPf9,&Fe!&Q5,&F8&JX(ja4,$pGAbbAK"I,f9f+j8H1`d"J9Pk
-aR+l!c)3CAL`rAJ*cZ9JqI!EQ)J`fjKE"P--%&mZ(X0#K(6"Bl&"RQ0l&FNiPc'U
-B0TJq-"#@!`AhjX*)-0L`&iGl&aI,pFYKGX&!mISj-21,jGe3D$F@DNJTP[G%&-X
-RNE#6f($bI4JXHSTJ&KA,cd'4jb$mG"N-"*q'JLqFJZPC,&Gf,jE23[&rKKE,Cm+
-+j6ZKi2%'Q%q+jG[--%MBEIYKS%5j#3BEbJFAbdHELq86dF@bj)+j#405,#Y)T()
-9"X4fl)0C"i10VJ!-L1L#F&Fmc,PL1Dke@,i[V9Jq!Z@1c#f@0r3YPYGd+jEAjX#
-!`'ZK`(S8f"G30K@&Q!VKRk8@bmXKr(XXrRel'""K"3jA`9"C3+C+3$V"p!c)JEL
-!2#iY)*X"rHC@Q*U!2'BMc2b!R,F2*J1Q"da)3"i0aY'I"q6D!-a0Q-N"H9NYc%U
-Bf3'j#-)2!(%!3N`3CKS4N!!,jJCNlfX"qH#DJ2a8DN$1kKq3!"pY#mMT8`+b"8)
-1lB"*#FJ0f3(jq9+B)3(jj0'!I!UG&`B(j%S`h@N+b#S8G4b$Q4Q3!&hVB5"!,iI
-T$$-b)-HY$U!b`Q$$NFL![!%E0[3,b'Yk"q6e5&!U%*rp"$-p)'q&iPZY!IR0&3%
-ji8a!EXk$f3l6*i!R!+!"+k`8ZV"d(4A9dlMp,Mi1FeY`m3Dc3(NY2U+SfXUYQ,4
-CH&4-aqIMa'a0V6A5&4UCGCEbFQKF'4J,[2B8ESVMDlb*+A6BR%2,LP4E+CP2+4S
-hm"8'AlVlmMa-J-iVL,mrP-+20j!!a5YGcbX$*eP-p+JLC%3bCY@@fCi1Z[KTAi`
-iRmQ"6[!QcN3MEKX9Pf0fXepQ+'41J,-*R)A(VkHRkXP8UFD[Sj`eG,K-MGp+clX
-T[F`aXA6kNp*Gf1NFAlARVXF(T8UI8D(Afk%l45ehd91BlCP0UjST0imH,4-cFmq
-8d"i6i6Sr*11bkG#q%-FdY[FM3ec'%1QSCI5lDAIaJ`l0b2ADfrRJX1jLAaBA$fQ
-*+[$G`,4YkdGe[,p@4L9HHMTEG@VPP&k#9LQP(e&Y@C6HV$V,+*hhpLGY09XfAI3
--S@AE(F&iHK&[Sc+mmlK8*rq!LNkTcL`U`Z39cFpNZb0Bl1dNp1RL$HY%G58jP'H
-LFFHU#KiRqlaK+A4[54`l5IFj@HpY5b&,56DCLr$'9Be2&aZL8V1TV)J1QY4EH96
-NT5`629p+Hdei`@T4m,hm@rbGV3)XUU$KTZJ8H$Y%rXr,j0Z4Nj5*`2Q8#@0T85B
-9(1-hq*3*$kNZNa*@*L@X6,*CQC5L6$ViPNPKGCPF%@@br@CeN8aQ4C)YLX64XNJ
-k#hAL[@'GrcFXNMB8LEQ4DV0TA#lZAKfrfm`Q80@#@KH90R`eiTeAd1rj+#S[8JF
-FTrVP9&P%KrP9bQkJJcPd1*@jSm'LRVT%0DfTU+B31%5ehF#NH0cqeY9VRcdH9H!
-l&)Ve&*lT!fpEcjqT8kh3+FUFpV-8VrfCA,8LALmTQi$+f9kH-P&mQ#J6h(YF411
-m2S99qC)Ri58*Nj`dM[hN-Nl1(U'XE#S`%HlE1e6UUUiB$,6YAYXX%[jcY2#IJQc
-G[2DjS1LNq,#j0+aN0H@9d,JLRe@D[GG6U-kCK8Y&J@2#Jd$ib)*E0B0TGle#hM)
-kN!!V0Ke!DIU#mPcKAjGJYPfU0h3Z`0RH$8qXmaIci"HjIDPGE)GHN3hE+@p0GH)
-MKF+G[D'4C-QUT`"h9XK9VdIJ-DeCZEii,@+%BLrabHBL4VLZ@ZSVb@YkUE8Ape"
-iZG$F8U4GS%"*96hYL+TX`FHI1l2TG$EYbDCFI%M+TP,F-DQ`&6"AjE*Lld[M"fd
-qJeDI`A+I`A'I39De)0eC*&&a5CAA$XALKdXh8R&f93lX4efF%'9UV%E9&*`A+#h
-A`L@Y+&ZeZ@K-YVm8FD&9*&PdD`UZ-cC[*J@b(9S&8VXM@$QrMfV09+a@+4@1@d!
-U"MM'$A5iB8B3eqmY0`hAVjIJNfbYEdfS&Hf(+(bc+XkVcXT[)5XrR*j,bdV*Qd9
-jafPC&R1lmiA5)H+eQ&$'4kSa@XBRU'1Q#85AqUXHm#CII!NkZ''S4)ShCrNHl2I
-A22M90"Uh`kH&d`C"LVhH*b8VYmECXkS45,KP3S5VSh(f'*APdU-P`VhZ+D@$Z94
-83JI09+Ek#`2N*3DZrNe$8hd!E6`1d$CY-LBGYZ$meD@IRP6kDErd-bfPRhD&@8V
-3M'Y"Q`Cr"M)TrZFT0-`ChN#9CMTC3YrLJ@aQDXLL*LmeH1R34H5#G)MhT6YVkG!
-15X@SK"TUk@3Y9GBkQ+ZBa939h8r%Ga6@l5QqSV$Zh!*E$6('f3@fSB-C-VV!&Q,
-jPECdIp',1,'PfZhp5SbqajG`A'GbLEEe'$k,LQSCm3F*aIhql4Vmfm6)LCT`U'L
-V6jd@pDj15pp(KlcUCIL4Xh5JPNS9HUb%5RPA4N,V+,pJG1H,Ve,NVje9GAHqkQb
-Flp0QINij!V$"EAh33'dl6ERTp(3ZQ8VSDA19QRirYlJDN!$'3`lJC6EQdPUpZ#A
-l8[d&HLbRfNRLFBV9M-6FT"qJlLTa9HhVjSZ@#SrbJG,jdA`*QD[c,("qM0Re4MY
-4&50,MP,HDTmFM4eMKV@Jdl!5KBU2Jdi9f!K44mmMDcD0pdE`3,LM[UV'iZ@Pa%9
-jhJNN`T'[%F[0+j%SErQNTk%XFmfU&,QRcfNFMk[f,K0c1["bHEli21C$6P9R0+*
-e%cH"6h(&4jAbP1VFC)MIkjEaAY@iB*%Uh$qAjZ0V3QC)KGV@rG,(EK2PQfMM'8T
-G36q@8@S4rGe%UHYTVCILmNLYTD-QZY0,P59dXKle6e6+SlAL)+k@eYC5kMjkiaJ
-&9G,'@XU[*EFIDYX"Z[U+G[0LmG9Bp2S$&5akD3$jF0'l!&5Sk*d6Aj0&Vi2iP%`
-JiDcYH(mk*4bZ''9L9-j'ZPBB,hS#40m9Aj0CYhq9b%caqCR"Ejm#Cdd[RlVfreG
-SlIp(S6B),AL4c2%e[5VQ%fRjbBVQhBkEZNkVfPIG9-f,@eUmc6$fqq`YCKk"&E-
-K`K`66U08i+p26j!!aCd4LS4EXL5RD+f9q-&fV[m9`6PhE2-lI*Db(-BYm-VeNU)
-*@UeH2hLA6S![m9j,%E[(Dk8G60@ecp#qqLUJDJFaAqBJCKBG2&H4U,B@h'USlmC
-c1ZS#kX0mE'JrDA+GmdJd+Dja,mZV@bCmRcqIQT3HYq"2cQC6YSQ+cP""#BdZ3F[
-0)6KQ-6Eal5'cDL5UGlVAQ6)f3V98(l5UQ1deiB&UXTAQXUVUaDbF,UT@L[P#id*
-elG3Z9F[+`"4r6%1FrV@fZZaVE99I9A[d+'D,TqMDCNcGbFd"%+jqLp(`i'b9dH6
-J*qKmiSF9EhX",cSU*Hi6aT8F%CDRXl#5KBXXp'*KN3MI&l&`PS9'"1hl8"eJbVU
-BEQPDS@SVqU[LlP9Ye@)G0i*LX%pe[V@DikjCfeXpH*6$q9B`MbT8R&Z2F!0hdQk
-0&Y(fjPQFfGqmL1F*[0PHf2lFK8Y!N!"XIc-%r@ejBT&Yj6UZriMPYr9KBEJ)(f@
-,`iq1BE&59IXS3p81@&Al4a#KII5ZE[pS0J4q0"I25GLZD!F!%pZcGI[f5NM&I4[
-BZ4hcRA#MSRCJXQVIIJl-fcYMkrBH3)@VYTdjB(,Z61@4D)MZl)jY1fH*E6X(krE
-`HR#',pHGi3Nmh+0SiEf"R)bR*S3[iZ%""4H8a!-DSLa!49d@+#dU4,I[U)@8(4B
-KCBG,aj8QePf-pFT9Hh)C0%MHKbh*,LlZDdm1eqh*D3)E*Zc,`[iNE$6%*#m@"%J
-`#4%*Ch8Y`38aZDS@9+4V3HNUlLM5JZESpL#NhKj8!ffEXh4lmhjXE6l'Rh2BQQp
-L#TLY1B@IF0Jflq#((3a`PXe!)q#U%0Si@GFD3E*Ph99l8aB%0*h@Y5DX8VX$ECU
-EJUHT$e#pJBS$cb$`E$6VpSeG41pfp+BM+4YVZ+9@XEhH3@ai(I*'0k#eEG+G'H%
-FMpc3-Tbk280XbEKG4l0FX,e6UY[I13VF1r"MSe(r-cIU@LB!0QqiDXqFJC0-3(8
-HjUAPSb'5Km,+2kVEmq0`NVm0[@E4Zk$EmPNkmRX#0dAJ4U&R"69D3@HYY9khYlV
-%F+Z`Q3*R"kk[k2A8F5e,N!"h%`2k6H8mh'(IP)#c6@lG[ZPPdHZ&hZHL"dAbiX3
-P,E&F4*'1#eTL9d5D!*k)cU)NR4'IX`+0Q)rM%H)J*SXGa"aR"c(EG'G-)bDI+2B
-B!B!a!+BBJ+icCUkS2(Ch!&KhZQjh!h5GlM9qE!E!fQd44eedTlZI`'VZkH"+%FK
-Jh4jV"RZXKE(M[L'A29BN0MC#S12pD!&1XCm,c'Yq6$!fTjPdHeU$k"e(E`GidRD
-*S90hTXd5DQTT3h6l&U(9&QLej3L!DNZi52q@-"eAYPLhYqlF-TRMPRjYb`Jam4D
-Z#p$j)qB-MX-605iX"deYEa-,[85iZ%f%EfX&mEi9hJHIaP3Y-&pmY86RA6'[9"G
-ICaBkY"ZieF1$)`kI8aJXTTVU0UdEPadf6&c'9[Xkh@E[,d6CK%#l6C5[$EA"0J3
-p*fVYq4)H$Yh1fh9E[("bQ0USfd)V46HdbpI1aml`1T!!-rYchID)'Gj*beUMfl)
-kmcU(pQJ2A8[(cG1P'e9RlJ`q$hb(YX'j3YZF%Ph,@Bj"Ip@jem-A0LMDlU1kE6H
-V,,YlS$Y#e,-'H+Z$CDUp`3eY'Z$A[AJ"ECL-c[ZUI8mjk,eRQl!hKHd%TMhYeR(
--&M9PU$EC$6)jjABm#Xm*m(63EClq`'JHh#pdi(C9+`C&$JKkPHUf3$m"DB(Aq%,
-`QP0eTrN#am09R1BHr&#YSSe"VP!%ce1,ZHc,d(`TZUVDLPJe,F*%cL,N*39iF-S
-bT1[J$(63Y(JDGa[9hP5eNR!mMJV)dI!9f9d%QE1Rm%-1fb2(aH!40pm0JZAK89E
-3C24'6&i3VTDR@cLil1Nc!5hTc(FrAJ+-pMJq3q$"+XNS$NYIA6Ym"VZ@BkD#J!(
-Ri4RF+&6XZ88J3biQMqHLYSmqKPN,`8,63eYeqb%"RiFZ##ZUcU(HZLe(P+-YCl8
-SqT`f(1Ad`D)j-aPD9$rlhPbJpdT!lpdKd([Eq'D(YRHaEUYI,K$eZi6mqRkkXhi
-1Uk(eJ,Dm0-b+k#*F`@lKK(BM-mk$+fc)j2-FYSB8!+CY6`3+f,CR1&$D2P6UI8j
-HPk9Sq`IVYT0Y3[,*pcPDB5H$GGXT"TqR40DU23HAr9`mj*e@EFm*2HfRiD0XTp'
-'FQLR,qVDk8'U*8qe[A"+E(U"DIG#6e8EJfbh%M9V$(c3@Fc#(30Ir%r8X$&p91e
--'$VR91h1#qLJe)ihk,EMc,mHRk(EMip%%QicklEEQ"khLEa%+cITY[*3J5M[cK#
-$GHe2MGL2#RZd@D#1iP1UHD4U1cCF!2+*E0efiT3Sa"0GGCXN-Ma0DN4A!,a0kLb
-1T)'kTU**DZkYfT5YJN@jUYXF,1pb"9LS&fJAfLGQ3,!,MYYe6T5pD`TcL#k4GHP
-i")BC8icecp(CT6VM@RPiUH+m,if(ip%G4iT%e)kJ4-`V91H'[M`FCECKN!"Z@b-
-FM,B'lCbe)LZhV9h(JPXXZ4DY)60D5H[4CM(M(VS[,ZUf,eJl+*@e+9+KdMK8N!$
-2-,&p('VRmRCSl4aPVCpQ&YS,KrApI+(XLQaq##UXbPl(+m(H4a(IR-FTUXe)iC%
-1,XICj*j`)lC!R0Jk6Q300R1K!"Cc+a[8#)+1fBLDLl)E-ephjS@)KT)f1Je2K8-
-@'!J6G8ph,P[*Sq"aPXh'TlXb2JaYU!1eI#&3"fTdTfN%3aA-C5M[DlTf%#r$!8c
-&,i@(#D"QP@'UF`#IQTp#SSUGUTD0jBUhUXj(2Z!,83'c3!X2j[BrLZGeH1"adkH
-JdaP2"`)!HD$G)E5@$U&CjmN"h'F,[pL!CUIFUMVhR@85RNFE6)Cj(LkN%#lL*0a
-))5$eP%"Jd[J,!+R+Qq,Y5,AGD4)5lZb!er9ieARE2TBKhZEfamQXfT8MIcGb!Ah
-[SRlDITmKr1maZ!!$jA@L4K(IlG3i!"KZ#Ii*cbI!cF&KUXea6&4&ad`4A1Y&GZ'
-DSY[dND)EYeUh(@(Zq%JNJ)+eDpIR#X4kY$'qaJfdMDTYAED!QR@iKASP`1)8E[9
-9YG3i"kji&MDlqpEd`qrbM"R5bJUcI-D-'aeVDQS'@81XeS&1je5VGBL`k,mKqX(
-cB1mGH+-96$9@Dc"$$Vpa2Y4U23G%I,!e'-L3!2R@mAmK0Cp1F2b0rk5'R8D'##'
-,3PJ-XBDdBlfPeBK[&YI82&$$9"J#&$5lIkl6'H*d$UcJ'$LPj4JElUi4SZqTUER
-(EVF2U9NSJN!Ym2FBilf,lHa[F-hp6Q[0%2m5JiC#`R"RF!A6hGpZG%,!h68MX(e
-`63AkrT(1i*U"6UZ6#AhB+@J98M-Yl*c914F5RIB4M#ah["CkHEJB9b&5r([mDLj
-Jqrc,I#Hf$445S2c$!Rd2&!6LrZr%k#&d(kMHZ9$d[UNBcUhS$(TB-%9@,9G"V-&
-h,,&H@(l68988+2Ad(ZGlK6hCmBj18Z-!kB+`jk6AAVlRKd[aPbl&5hVmTHjhX,r
-h`m,#"Jbp(*Ei4qQG+lIIdr(k`%'IXb#j1mk4GSlXH-r)BF1NV5`NRqrD*5bXmp$
-Jb`1ZA4rBi9EEe@khHRHpF[f6X$#THFS28kC)b6#K$dp"q"f#G#(-kV`Ul84i-K4
-2LYhfGX4GrdIr[EeAJ(00-!2hhrkjJYbIh[$@#1b096Hk*refb'[a(`b+[p%TrMf
-%UcHIX(jX[A(9DEha`lHR4PVRhPJ&i,MaSG0kmchl,2YNqc`VLMM*DPeJYFkarYV
-qkH@8Fdk8Aejjl%0A*18"bGAc`b&h$lPEq[!h&Cfr*clc5[#JrSPAm9-p9kj,NhX
-1NP+P'T62@P&)IadL25X&59ZlR*HZL6,i9PLEAGTLIpC1rVrE*+i@U6Q%fEcaSD(
-2KSCfHq,FbqKfAIRA!BRA*BH`kd+Pe&"rq$#d9fM2a1Z[![e@k#H*Rb4+6h`TVIK
-"$8M6T#6)'bGPfX+)e00Y9pU%I!!!("&"4%05!`!Zm3p9$@9&%3!aCHj$[fe[PMP
-I`XX-qBD3!*1mK$R(6,,KN64(*5jC%ZFbNV&%#GambG4N%mQ50FBdjAT`-6'%D#'
-'&LbA3`1PTr(j$#a3Uak"!CE$&5mhmRbXpAJj)K5NL1@fA+rBe(hqIZqlC!Q@FZr
-TIIi"'kBRj8%3"%!3!+)"&qIa%Cd1,cjFb&a3L@5%!ElqCp-,,Fl'lKBqfHd02Nk
-9r(UUr'*miC%lRHrprB[e%)P$@TXDHABkE&PSF[T8dqPb*"di"TiicB48I+iIR@H
-MMh(aBjKB93M2%[YD&%+(lQ-&cHLm3r[`85eq*-32[km0lM(4c5-jJ)*qFMJjq%j
-A&cFF*4FN+bM0S%T)T*`ih1X`$PPq&DjiQEGH1a,kli*3!6QT4Qrji*ReU9CZH5F
-3@VXh4+j$hAGlHadCeir[$E6j9MU9MAYU,I1j[r[(p,Ia3[H2cqrRfrZFIhCSJe2
-pj*iV)F02!p'F3&2CP"9r999Naq@Ah,dH02HMCYQ"ld&@X1(!hGA1#ZZSdDT`1BY
-HNk'`AfQ53F&N'9kYm@UmBN9q[$il%-VP[G[MJLRS1D-%KpVdLHe@LPeKE42$`ib
---J*(r3iiE+'5p6[#0Y9I[f1)UkEMHhba3%cGd+5%fheQ8hlFfrL4(1%*6d)@q'F
-HS5N5eE#+@&Njr`a&SHcGTNM[AXpUGB15TLBDXSS9'0I'G'MZjK%K*C8*VIbcNE"
-&65"TCG8'NEb,U5E$9M+A"#16QQ!J&8iG*-cmfKZMR0pYHJ-L"DEbZP8CRcIkc1%
-HH1Z$b3TU1!DR[&bVQq@!-LFJEV9i0A&jqCGpX8PTq2piiC5HGF@6A6KRpCAlVZ5
-@V5k!QebS$qrS(jX98XIEiZf'j!kkeh+emeNI1X,bH#STp$RrT29DT'8prCjT60m
-+jrF#E28jY3eTV"iNX6VVAr#Ce3hU&C2GNr$fKXhDa1R0A%$45`P)keBH'p&FGNc
-,DMX5I4TVhH@pe8U8LPrfb8MFYDYl8a&pm-&Pa*`c")Sm0%NmJUmLkN@b,baH'Ui
-%2VridNKa@RfT2MQ8h`BRU!TQ`X4E-P2"V,ElV-KU@Sq9Rl&5UM+TT-k@S6&!F'5
-N4jdpmNd1(&G)M5'efZZ)Md8pTS)$5`1K03@pHeIpHVK#66d[Kaa%d$Q(4e!VSKB
-eGA9*eD3`8K%9`KA@lGm@&&f+"M$B9ccih)VR&6DSl0b+Uj95LpGSGHEr9GEUA@p
-#rhVa-@a2aFDIHYYm9QqRlr"p&e46rF1cmT'LU8K'Y*'@N@3&%JJCA%Bae$+#9-!
-AUEBAB6BDS36e!B8fSZ6LD!*@d-9c1DkYd,8$hi3V!$aK*$8F8i1"0QmTp'8T!P2
-pFipm#$)5K#5qYN)j%(RJed-9UYp-L@S1F5A4`")U%-N6j+D68Q"UCI0H8N69Iep
-QFjS"190YRQU[96AEEdIH1r,8X-qN,SLhKR[$HbqhFk46eIA9JJ48Uq-b+94RD85
-DCSN"+GP!b!1Lh[Df5HN)3m93fk`X6ibj-(M86am#$k!MP")1KR6$"*HlZ*K5S(6
-%LVe'B4c*"*C!%)K43',m1`0MAp[bI$,)5#B8'X"%R3Q"+Bpheb'Cji54'$$aR[j
-iNlUrerbF&JQQmQHG)jNQQmFI"R$bJQefhL3Dr"`ZP'CLqKVTr8C+69S+)rIfeCN
-`C#IE6(Hr%Y([*X4"#3a*a*Y-!%VFN!"'3BS&`rrD9qIZ,akL+pr4$h%&L6fH`%m
-eA8Se1KYKp'd`#NJNaZ&qKR(C4Y9IJ4cHr4)Qi&hD5GTF$2Gb*$YjX2[(!-C@E'6
-VMRjD6!H-C11@1KbY"DZbiL08V8QeJI98DR$,EeBBYaBLV65iT@k&FF[&P5jFTmI
-@q%%D$[EKB2+imi-d1QK`EUPT3)Hpd,EP&AA`Jl66U0!'La&%QC!!%'6i(&+$1hd
-chTYj+'`'ZQZf,H%@*+3#[#mD#eYK1)j4@UJfTSr`,!eSlYp!S0TB(dB5Uhk5&-j
-RR9M)KF@p*aCbrk0JQ4TXZ@4al4pXZG(bbG11P'"a2Hd`(jR[KcViYBNcMV("PMf
-@reJrf0*XHDIZME%+bhr8[6%FA2X%r4eliXk#9@q-CkAmc9fUp5Z%Bq#e!8`VQcY
-BKCq4-E[(V&S""Xh'qX%CPYiZVcG4ZJLT,HHI&!JqJeYliek[PG+kf&3j1HMDe6E
-%%qH(f$CA8`)4JQ(jeNje*ZVeDF5&%9USfT%C5i"pUD8Ere@Gm9R)E*4@1j24f4T
-A8i219QaECVbaflQaq43U0eirHX['pqVr2hY9Li"F5mQl%e+J!d1eT(#qSXpjfhb
-6MA9RY5@9brqia-5CNBjK35E3Y`H)V)QEmi+Rl"[A,1cDH1a8"bBjTPZld,+aQDE
-4cRNU#P8++)-Ecq3UVJ)),A$ELZaUUl$c@qh4EIUT2phEP#4J3(`EMZMZeVBMh&3
-4*lFB9H69mS&q$'kSLTC8l)DLQ!Dhh)C!QVP@S$'B0&X+jbJBi*!!M6biYG$GRfj
-*i5JC`q%Rf#4b&!rV2LQFAQ`E%e+95*ec$4aYAb,Kq5pG''jmraPLdqIFjkBKKJ)
-ZSA5IT5*0M24i&dMT4[2L5AC"@ETJP!Ih5mXJ,T``mDPqN!!@`(88Neqk8[GC1!%
-h64NZ!aE"CQDDDQN$UIV8I0jGHK1Mdh4)DJk!V$KP+hhFdfmJ9")5,B8k(3Q+3LH
-@[aHf*"-Y*a%B8%$EJ+[-3T*I4NAq4qJSYY`@cB%4fDr6NE1$',4%NHiN4c`D,c-
-1cieH*0C9`@+cZ,$&+@TfP3q2Fc*8%V"jL0,"Ihb'JD%kANfX#45Rl-l@D"0$5RZ
-9km#e$j!!D!!5FR1qc3cjmPe[6rAV*@%Z8TG,M[*'G,N'`q'G8IGldM-QBEi[LZB
-EJ85ZVh8A$H%G66``"025JFicf`66%PrD&NNZB'6#a)$iLrVE"A3dQB6i'%#!iq6
-qbD+60l2Y1iLIA9VHmJ)-UNSX31JZZ'-2JX@h99K)CUZ1Q5d4T3pQNFRVrPTA0hV
-XB"D%[F82iLUkTlZcG8p"FE+HUN3cM%JH3qM"Tq,eBRTQ-3bck2Fd03CdIi3`()[
-lmE*iT!5UBFScqSB54KCSVpp-%,k!QVaFUP%"8&UdXLJdFrr+K"Yd0Cpk6Ek1J5[
-,IM8C9M3@4f1C*ImKfd6%e*9G4S*R#J"HJC!!LdNr,5SkmrU&Remk%+#P6BFYDBY
-Yia")MDfQ,Sq5@LJYl89A1GZ9lDHP5cFYqh!bjL[c2Zl,MclkmdXHBD!QfZ26K&'
-KGJjNMR3mrUNkCj9ME5Ep,FTXIZeZKpTjr0*)E&A"fYISEp&Vef6HAI#P)d2"YP#
-UDbcF19$MlSp@*bXX0k2VAUiE#Lb!XklMq#@Ym![A8Uj,k3YE+4)ZFGeHQc(@[EK
-lFDmYSm5NRYmIimP"jhS`fG5hI%k1(SJS%1"1U'IS&lGX2ZLKcBG+3,K'PGAT4!H
-[+10F-N9m&`NZmj!!H"@hf3mK"d,6#4kbmdU%4RebIVp#%jd!dfaadR%8PRBERH&
-ZTc0JkQ)SeUI9[$2AadG[F9kG6-9!AR"8'MDR9DUF%+J54*b`c,H"a$NK1TK)6FJ
-iM*dA*-Da4@!h(4d`GF6$a8cmbfRJ#(lXppSiL@-frY3`'T@UhU+(5NrJcb,#Y)P
-QqhQ4D(r192p#J01T!U85HNEpGZUiD5Je[U%#ql`Sj(%Bj5CR1-1@`P@CBrBY38T
-ZUEYD(!$*3TXci-BJLB(4&4Kd"UJ*rER15`Pr!5R6GA*Sc#p[i(*f,DSU*YE*20@
-ZBL'3!+HH'2`l'%4ITDTF@DS5M&afKQRjZK`CB[epQ@'MFrJk9h3)CJA6aNN`%4!
-S%d$@cA9I*SJE2Ze#da*-9MQ)45m4CGATiMG1D15Z)*mF9L2@I#cdIC-@ih)qf[J
-kSbBCJH%GH-6T9!IkM6cdAKiRF-!Cp@F*C8+E[GQkI@!`0TNi)IJlG"%SB[hh#PM
-%f$0Y!&P%ad#3!#J"33*J'FBLQdH@#"hSMr*3Uf(!)@R!jb8$2RH'r4emp(Y&hK"
-0P-@fNJ)Y"!`EIjj2Tq63JaYd"dXfe$q4`SCZd0r3hp''AVh5$I9M)mIAjf*6jrc
-R0K@L5&HmF%cSh3"bbSm%eeIHPIfpZRTUJcGQ[qApTe*IeA#,LiLlBL-bjT9F,q@
-hJZ%`Aj'IVUL9$IN@&b9hGEV&MQK#1[4'&MY5&4EA#$ZSF``&Ca9N#0ZbM'1UB#A
-4h$F#K"ba(&i4idd'K&4+)H3`e$+0(B3+H@q(jj-S,hm9320Gpki2Vhr-6A9XbLc
-l,acY`T&0A`3p"4(LrIVeJqrAbk193XCdDP50%8#lYG8#IN*IRG2TUVPeP)k0Ur6
-G406Fe6*MR+31U4VTc9H2m%+HaeqQ!+KUkG"RJf%hRdQEeLL9Xed8j2@P)plD@'R
-*RiM)A6UG4bK%X&R+VP8E-JZ$pf`ffG0EdC9$*%RkBC!!`J2pB#rMFaBCVS%D#Q0
-"Nr+#FA-T*j)I$MadLMQIcbdB[H9p9aRLkfDr2HmelHHZ!J@'GlCV+(6[+fFFqP8
-"rlfrAP1U+PaaEmheT4H&2[iL*G98XN!0"GS-,MEG,S!VC3Kd3UT,jNTfi18J!R#
-8ZiajR,UDjJYHIMr#6Q4qapIm'h0S8iGX9lJ4,PTqSlU!QYHIkh`F6[KGhJ93PFh
-Dfj[KTRc3aJ*Y)[*khLD(iV9-j0[PXpeaMLV'XDP@ir[epqHIip'%G$LqAUD2FL3
-`bY'eHD"3DA&IbKk)S4XC([[U&5%1J6UUT-6"K!TI1Di@aRPd+'8IBXXHr-NV)Ge
-"%ej34!K89CGRKmEjUL[&dhJHC3HihMM%(AQIIV1`N!!$6@[c'+T!&@`q'm6[0+L
-A![AF,kTRq3p8ch+%$MP,9"1$MA0*$5A!$A-XAhm#aJGG61T)k+TG#U'83%')E6+
-p+T!!L*bA1KAbprd6IJi%dI*@a$G0mRTV&i(lMM5CQ[2Ap1SAjl)#P)89YiQ'5Nj
-&V(C+%0f49XX0bdZE+5c2I,Rb%TEhl+@M"pM4LibXhJjX8TNq%kR5XkKNDY2,jfP
-`EQ*0!3eIa)Er[imlA&BUV"c(N6XFYC`5&8hVcGb5CVA6%LJC2jLAahdQVab0IGr
-13`-Aa+-didh*a(P5I5D)r[-B08a++55D`hRXb[GPGYcbI[0eV[-4"8EEiS$BSC%
-%Y2)(h$9@ZfcRPdQeLql8Gm+)!CR9ASBHB61))p&@[KpNP(fAiM!%GZCD5M-ZBXN
-L!bQ6)LNX[$)THp2K8%dL+3@RR*V1j4'cU5$ZekcZ,I$X8Xe`bHh1QTNjN!#Zr5h
-f25Q-B$Q5-GHU)4D5kSLRY$EApRLVp[aF"e$Y@QrSRLZCl$-Xh&16jSJ+KU14d$f
-[EAH%Jc5*ZPfGl@hVfre)4q(i41I-KU+FISrRC&(1c%blqi"l4`C,6*BE6#J%@EQ
-l!BN5Z%[*fGja'qGP19!$e@H&!im(bjCp@)4(6061dqmZqh3T$`UQV9a'fM+QQSp
-rk)hj!Paqi),k@60FaclE%4k)l0LV4RBiLYEjr*[fVVS`(&%VlmZFp9f-&l@Uf!i
-`FRNYXeTiE&,`QD2+8-5D&48#F-qIfhYJcb-IBP+rD3XA2!*3mdR9H[S'*%EN&r$
-!aZ,(eB882%Z`J9ZH42e-U1*Rc9K1ee!GC1"m[6dAU!MhP`$Rpc,1QrBJ4KrGJTZ
-j@#$`LjANJR2haa[Ai'0jfY*UK0QehY-*F,CQfD,A)hh@b&*X$XEFIGSP%J)dd#V
-AZA"a`F-2RM'JR5-P`E[pZHc*MX)$4GSFC)+Y5![R6NU3!2rUrXGH,$QCRHe**c6
-&KXA#mlRm,4*1(NR3ee!J-B981l`55r[Zh0bLl*c4!c55Q0Qr@LH9CZF8j4l05Fm
-e"(iVNTPI3S'mFARmX13BGA!N!TG`a8FJ58K!ZAEF"#HL*iC(@A3!p2@di,+E+l5
-jmIG30BXCGS,eBCLM*jYYU90F-NL,BC*5H%e!fVG`0aq!aCN2AA1MN[i+-H0LRSA
-%!TK&XlA9l--M9PbYeE#2RH*(RlLJAD`BdcDbMh&a`,#i`#Gq6%r4U`RNS@RiYma
-FZEQ!(IMC94+iL*a5#)3`pDaKk`K,B1`V+Y5$i99"L+d38NNHFj9,&rfcBZ&pZr&
-bd'Xf+maQ"4-VQ&LKNa8k8IL$0-pMkAP&2HRYlN+fkbF0@b1PL`K"N4LDcbI8hR%
-&bD'R`qBrh-STR$@#0M(!(9NEpdiJX$l2lpZ`i9EH&'!#V@Y[h2pkc9NV9eqrd'Y
-ICBE4#Q8mS'ecCFA$H8TK*9YFbaC(X&Ki[FCAKk9GUcVK#)pNc&0C)R!rM`FQpUX
-mVl+%VI*QcHXe%(@B8Y5DT[T&pN,'RHU'PhT!U0QG1E)"D,pIcH"##E*rAlUY1eh
-EQh2d`-hYZ8H043bZkh[QjkErb*kHR30iV`cR'CVkdS'1556iJ+$)"h#C+E9RCbL
-I%TVDbQf1l)3Dq4Xc&Y&U0I+Q3bU-cZ0Uf)*YDV+iGMML'[bd`Ua(,!k,LfhilK5
-F"@T-+UJDk50m-jqilYf5B3Tq'XRC8$,)@R@)Bk6%GZimQV&l*AI,B&Z,4d(%8%`
-SRZ`PaC-p2S15e6lPKH--`U1SF16qmkbKiX224kmC,aZ,5!V+G3C&Lf`Z9V4)245
-Y$kpAZ#YB&V`a&!Zp'VS8fKGm+&,2rXBLCV`bI6+jhP6l#+k*K`Y#PTr%1"kVmIF
-e5#U%jML2[%V,B02YF$Vk*I,qj8Z6P%CVA5Q$4&r$9,qSG$c5+Nd$*J*M%M)`)4C
-*VYUV6KQD0i5N)Ca4%hqCad-"6$X)TVTb(jc6q+a'Bpk,`'L%2*!!q%6-K'[qiM,
-PTfYq2jHQ`Z-`(Ad0[IP6rGR(402!3lmCNKN*lISNH'dPP59Amr'5bS5K-P"F@9d
-bQ+[#5+4iHPc(qjBND(abGrbUB!$iE!!H"9FQp$DJfJ#1i*SI"X!I1,5HE9eST9X
-hp"E%91ZaP$C6[%5`MlD'EFFL'PjUX1dd`YDm&V9Gh,*UhHhBXQTmDR3hBF[S!B5
-EU$PD#QL*P3*0-Z5FhqQ62alLN!$6J+r33p9%P3Z2r#"'!`D8RErX'*+pH@,a94@
-)H(S4$d&FLDPG*JJIm4(9lR8[Za8ZdGMCq8L*3434Vd$-BJ3beY9--eC$-*K$T6X
-F5C&6P@)AbmY$hHc#rpa9e8cZb2i4K!*Q+6q1NA6RFB1)TM!4MES0*)aK%-1GF%+
-S6)b"f#@CPSF2LXjN5K)U%%ccTFjaQm1iUGLpkdK+a-`q16Zl9eYdi$R2F`H1'RT
-$##IM4B8c*r82*#,fd+1aj1U%m&!ff#qTkX2ef+MYc+'pL#T'9TXF%+4%ec&9RGe
-2*-&T$VQfV%G[NDhM'-,R@AGMrAB8SZCK@cM6Dm,@9q0DHqMJK5N8$p,30fp+bSc
-&F$&6#K*Ra5qP$6!mKRYPCQChGP%KVT!!8c6*THkFa'Rc2,k2bqCjL$(hpTdf'(C
-cHREFY0ZSAFPqj*8)8mb`qm33Hb6K)K,564pK(FSL'2dYh(,jCYl&"Ec-2)D(3FZ
-JIN!IG3K0$5LI0#6F"0,,5VEL-BN)bp(XbBbL(598IbcFq'%EYCSD,#6m0IdE*R3
-FCS&-B3I!G3DSBK1lS+peCb$dLDJ,8Dm,MQDN&h4R$)p+dKmU&VNchCN`!e[j"$e
-k5J0DhaY(#Ne2++apd@Eda4X&'dmBTe'3!100[ECi'$qKD2AKZ65pf08T"LBIaBK
-*G$N5R[Ym2Ip!a`$!#EcVFLqh3(R-PcZj1bVJdef9U-%PI!)+mF1)b3!"HA%2)bB
-EKDPi!S4-iXI+e'8e6FR-4S"hk5Z0aaSGNbimN!$TXb39``)*A6dMbF--K!aK`cd
-dT-VP0&8Zah9,b!fEP)X(6Kq"3$laMd8miG[+,@HA%-,J"B5"X0SP+cc!5'P91`R
-XCp(!`)'&(LM3VFCMc44mJ`SBjY9d+%f2#pd0*20EY%!bLE`QGlqKf@N3H4Nb5AL
-@HeAdi[bCFYjMq6ZH91'@[q[S%F%[!-j*[MqCcRZi$Dm"hSAA&,IJ&HAQj1Fde@A
-KMCQC(1)NU8Sb3BM(M+F'T$,6+6@N(aIE,dGc$X`Rp1eLJMB'3$'"IMaHKPH-dRe
--TCmIk-IQFi3KP5%prq+`VDmCDPf8$G8i3$biBF*NK"kfpi6b"$JKPd'!r"5ZepK
-![kI94+!i!MF02VbIS$R`@kVSDiKZ8Nf'j[eV-c2C2`)ma)E`2"DB)6AIL9QcD)c
-Q&4XMFGKN"N&40"$5!*!!IBb1DiMT8C%VBfYBi"eE1F-DBRK8j%K$lUC8P!RUUpR
-(c'5j[TR8p)8cI3BcHAGT-pQENJbYCP1aQ3c25+'![aHhDQETdFQCSaNCk3GQC[l
-[C-jNZhJ0GZ9CY26iC-jm!kU8AN+),LhC[G)PUR'2YDq",8&Mb[KFpY'FSUXXf5N
-YUGZYCqm-DcKc@MKEY#m"-EL!Pm"M#bdY@M,LIEXAcmcN&X@I1`RZ-r'-p+9(-fE
-5Pbi"%bkP(G'3!+L&Qd80*(PBlHKZ3(LE6#PGPV$E(EE,CGcY@@qp)"rQGNq)IH`
-82r)m6DUp58(3S"[T8835&3m%'cbZ4Bd%jTKl+BjrH)(3-A*+Y2ab36`QTQTh+jS
-9(hR@bDhm*FrYH6cDT%Cb%j*`T'Qe&&MHZFDKEEl'i3[LkE+A2+[8$MAI-!8EY%Y
-kQ65H%TBqXr9#Y-9D)j+F`&!L("@0&04S,el+VT*!j8jT!CEZ,$jQbpdXl@[e0'i
-l(0mF98b4iLY+,((`9m13!$mBd)ATf``&Y"r0,4)4(ZLTh8QKXJMV3L!'K6+'jJl
-d)h"fc"$qC8!l0Q$313DRHBYqN!#P@,QebU*[Ue4m@UALNU'#a!Xp4QqA",%iR@-
-Xq%6"Mia3`C*&3HTk0G'53aD5@-aL&ahVTlIaX&r%9C!!1qHZ%X+e%EMejC`jGfp
-mfm'@&"5l'-R`@CC3Z[Lk%hG3`&bS'ih4JIl5!ErId&'`9,#VP`HVKVZb"L3%$B6
-@P-'e&-DrEP&p(8"P[lI$LiTCq3G#hJMqT3A#,T*)!22h@UN,8q)#a!i9J6f4rCb
-&L,4lj)I5rM(hXTf(dD'UU)bK8M$PCjp,qDX%ETD)PjK@!k2DD+)3bA$Bh2&A&+c
-Cj5BVh2%DK%1DTc,Y0fJ2Uhpjme-diXa6&lCYiH%$JQmK$bH*V!8X44*SjDBd4TE
-'91&*31a@4lSS&2!XrP@'f[PNUB"&3mJ!%B#`!D@3!$GU6!%HM#m&bJEM8bL%iUe
-!f8D!0C5NU4EL-BlP0`cFBH-4Gcm@4$b%hL&2#X'hL3#1"frQB9k'CUHDV%#S3TN
-P"afN,'h5$8qL1`dA"SP!45J91TQ3!))Kb@@)KFH!CJJ+1"MUAX)EfDH'[ET9%`P
-bd[E#+(aMhYVKHk*Z021G3hA[P)m@2V([GlE4QVURF4CcIh$)mmlS[Z2GfirE2N6
-0a'-IAE69M#CX,9QMYcjI1rVNRqlpF0@IrhEAQBXA,ajkrml4ZjFpHZbl6FmmRVr
-mpcDlEH1KZMffU`mYYc8FUV0e003mrGd[0lFmGEcKMCpHf3S!!%GU384$8J-!HZ!
-393eN9J%3-6AZ4IqrEFia9aNbl'+XrM+@C4'IGk'*YF6JQ#,,X'UQTBCbB+@`@D+
-b3caH$ap[ZS%mEi$Q8-**kEQjr4+DNkT8*Fpl+&p,FJc3K&)1ek3d!8S6bL%TTB4
-b#5@'LR[rrRkr2Dq'p2Cl2mrrpr-!'kfR+#H#)!L!3$62PiT(G6Uma18Y6JE3(lq
-!c&@ba"F4B%P@2Ke-'%BJ+T@Naj+5rlqMq&3P29#fDHEeQ3qPY0,qNRh55@Qrc1a
-4'&Pk8a@8-AA-X$QiA9If354Kq(VkdANK5G-9XdTDU'Md'Ej!($mK+$0--bq!"5D
-$`f*@"V6J!K$+pCcj5a4@CSpd5*k-NmKiMTU'!T'F1U('SXbL9kmqH8+%6'HKY1Q
-9LN9FXJImN@)J#G8)d!NfIkG)lKLEbX1N6#-L[$VQ6q`h*Rir2@!eq3-1$'LAVSM
-3r')4ZKj+l!mfhe'N24RX@1!Vh),'-41'$GLI56GF&I(XbQIR59dZ,'&CVbcVX9a
-%bhSA,SC)b$@%TRT9"I1bAS3`B82Y#GhLCp)G(5mA-8QIhC(U!P29irUakmG+FfP
-3aePLG'4fThcBS03952*aB0QFXMAaJI24e,RfUr&&d#'eqj!!8+ecKIU6b53cTfd
-X0+PHD'SVAGV#5TI*$&(Q6@E!B[#TN5jmI[)%@-Q9Kl#TAJ5Q,9F-PGP5%Q!aj%a
-D3e&%Z#SVXihe)ae-F#A41Pe$0Y)iVqK1QThSdQZSM`0*,29Kd&iDY0Pb8*Q9+GU
-DaR0$)MRi(e,A%qE+$&SFQV#S0H8'J*,!K[1$P@!"MNfH$'aU'1+*#C&U[iZh@&Y
-j#+,,@4-Z%0!he9EbYRT+d[P#@-`1(*J!HVhrpm("BVXj1#JE'Ie06+L5G%c2Gq%
-Lc1"e"J(`'SR0UFE"jM3,FDUS4eKZKCQr#&jkA"$&($1,lFaqE6qJeE`8LQGr$@a
-X%ril4)Y))*mb+PbQZKqBBSq1#+-'dIfa1N46L!l%*%4E%IeLV!h4)85cBhC%NiL
-Qad)M3*!!PKGcJiS$5!)-MUdJP#P30f*0&9DD%[["J1X$DV0+3r0I[4j+Q3jYmbb
-3!"GM@jNPRrTIK#D5lS&D@@e)L"qU[fBDG$B0HQ2%#[+EP#'Mrf1Em-FF19G&Fd`
-rVeJNBrk8b@Lh11!"U5%3Gar51S'Kc9PpZI%4#"(#MpH3!%Kq$aPrX*EfCql0h!Z
-KTddc,VC,kjqEUL[6V!pI%@e!hIkaFD(ld-a4V5qarcY&KlCKSR`T[DY&1Ab4*HS
-,ETem0*,*ELT@pB'fTMT9hh4&I6qlm[P`5Q5Q"ra2pUPk0$C6Br1,'T[41%503bp
-U(*,UC""a#$X"5U`P9DHH#PLE2-l*%APbMhV+I89G'LB3-dVSJ9,5%'P'83d9j1V
-F0S%#FLJ@0k%KN!"%iCeQ+$,'TA'G,[pjT`)#3-M&1l1kX6P$JFML5(p%Q*&i-fb
-6r+cb"3[1ENa+,fXrFMNb6TY13pMd4&I1mF@f4N+lFL9r4Li#9V2dFXP(VT[bCfa
-jd$20*i8`RCUiUr`C@ajaUN$5,%N,`(%BkMfI%X2YV2f+k"+Kc(3`elpM&*k,M!)
-j)$k@"dji*lm%&"i1)2c(S1Srq%X4kY['#*DAY,iCMFNVSPdN!NP4$)k+810YUqd
-H)38FH$d&9@pq[XH1p31GQ'#f6AJU%-IVi4Kh!dbTm5#,#+Y6+VEDN[5)pTL9PUi
-)P4EM[%L(5$b)#q6QT!"LP3chSF$)#CpPiXqr6d4CB*%(pNfF1X`XY2"jCH+`Hk)
-C%c9A4)*9-UYdM"T@RT@E*$3j9Pmb3dACaJ[#4`Y',-5$CQqa'NqZaXAL`54rJ#5
-U2$NSf4ENb3kDc+45mHRRcbI[%aG929jMDM0H0p3K[!E80V`be4Bi9X69GL$EIm6
-#8I88AL9U0Pj'9I[BIC!!DmlKeD11ia96Mq*eA6AMC9,(-+PA(F8VT6EL9DGHa'!
-G+U[1HbMCVPi+JqPFV,VSmck$f@@fI9D$lHcm+,4&'hpRm&j9$I64a&'M%+9d-6l
-)43IeUKIP#bM(M8&%5"R-KU,(c(6"L'V'8Tfbj-*5MGUcQlI5#q*VS%I8l6DVKc&
-89XKS+JiC!fCm(!pGjmf&#KbV3d+hDVFj9%d(Y!GDL24*$&%B+M6'GqH*8+J3R`@
-Kqi,"r0`RcD&KQ@K!#0N"Jied-I88*i`mR(T1'Dj954`Hm$le,r+!kPr`q5[e'4i
-`[cKdr8QcH[c*(XmP$$2X'F%VkUPR9D!083`UB[P3RS#bqNqZ+YhdaPSZUZA!9SC
-XU'Ka19j"306GHh#&E[2-m"JMR,M'Ba6*9Y1CQ&8Ze[pFh-K&HMbi%!eqL-*PZK`
-%@rf'+Y%-XISGkVaQ6-4%HaA%kQd!mehbX,@(G5ZBZ4NAZZ@[X"Tl#B[KZ-V'#-4
-[b3rKIIRmNlIdNZGQ,X5RjANU$rC*#)HXd-f"Xm1+b2kAYiUSY2rJGK'Y5rlM[P6
-(4K5Gq'R'%-YRRcb-$TRl-[H0V4iZ-rAK#MAS0NIDElrjhrJAL)m!ME5(69G%4b!
-j0Ti2YjKf2B'1(k+V&6m1r0Ma`mh2'd9m+iVQYS!,#,)0`96$`G3kMcq"2+TdLjS
-%JVJ'S[`9%Eq8RqpY%N%0-QKkr$4$F8#)f,S,`6RkbRh)bXpch8G)3E)09XfIra1
-$c8DcK!cX2"k8V[PRA,0AlJBfbU,K1$N)r-Nk5rJ")Ke!P[H*T"V(+`k8LCF)!H$
-d&*LEe4DmKLLSYe&3Ed&3(pDp3i$8+Ic13NN@@m$bR4SBV`9`k9i,kZE2%Y'BhSN
-NM@&dI)f3!%'+N!""(B&dShSZmmMa)m(QMElC2Z090%5T18A0+1"fFf!V`DY@I@B
-hGF#V5Ih,hkkU*EVA!f%jXB20qAXPFpmfeBMNDY5p2U14*Vb*ccUej&*c[RGp%6@
-pQHp0QA(B2K1!2*Bba@04$4bq$%AcF`[$R+%Qm!`aH(C![3Q3!),+831h"hED@Ci
-2"Xed%i*'5AUJQCHPT$3!"Xld'BhmQ6+XRlTaRc*i&)0h"[hcI!FQ$HbIja`B!GK
-$L(*28)hDjd"dhReFP5JE,1eq2kRL-dUI8Iid1U5"V#12C@++()Q@((XQ9qUi#3"
-!m%kBVUV4!&M9QMT9bLp@%eL-[)*&hAaDM1*$dP8KNiN*GrT5"cGkdG#SQiqP4Ph
-9RElelmlHKdQGZN(Ud)NJ9KcYZ&DPHbGem%hI,3DQ45KNPraqKDkifS!X)i%HT[K
-SS-'E6&TXIrdAT)B(-4#433)C@Nfj`j1)i(R0533'N!!L!!K23&"IlKKkZ3J"V#f
-$(DpQdfXE[d)hM#+dGk)3j"#a*$VK@U&KCj((5@V2"G%Z(QLCG+MCH5K)DEpCT9[
-a)h3'mPLN@kiNJ&dDk0ZUddRq'BdC4e)$*UX6$AMmf-l8@!X9Le$C"KabiA,T)VR
-2,$I'J`Q1-*UC4m%-U'Z4-6kb(THE1JTa!d%la-8pf"1,1'JlVXh$*aINcQ!DQPQ
-["Y0N`3&L3eMC,)VdJ1)8!V%S9#pfpkJeb)6[MCVkIUSfXX-1rkH!B+A&Smj&ZV4
-3YECV#l8AJ5X4-Z)9SH+T*P6!`5TdPB09k$iZe%,9H$dF+JcAKDkLLa9Ldm@qED&
-,,"E2D%4'1r4#b5#f-rN*k&ZCq%%r%m@G"1SlR!4'268XiNB3I*[RE*!!"KE&,cM
-`64TBXJdX64SiTJ`X64TB`X$D&`dETf&[d+$0YN'E*`dkT!cDr1*"#HQ(J3J@"9L
-`EU0%Y@IR0,qMX-C+(i4l&*&rM-5"+0!$b1DjP,qA#hFUePZPZY#`XfJf0PY18Bm
-c1SQ`JbT!1PB!6DXDX`+9pC,M$BSIrRLjL)%#52Ic&S&LE$SAfBDVDK`Lir4q),@
-Q"N3rKk$IaTPU"VS9ThJSA,)YCXeTe(dHD0k0+@S[&qd1L-iFF)6Z9T`8R$S`L+G
-$A'lRi,#l"pPH()#-Fk0Z1SDb`fd0'HGBXUNp1qIqY**dZ3KALZeKABi5p(Sd(J[
-@hfCQ1R!fGU)B!@B$&I%JeR$J(!X%NZRJpY!PS0X9M-*$KB&Q"5N-I4dC"@-ESiU
-JJ%Ke&8R%$L2,q8-qhNPB"2(Pc'5a*HTj%2jiS-4jJ'Td(U$qjB818%[F"kJPcJ2
-8id#`fXN(6#""Mb8"R+`*RBZ&,$#kb$'$ABkJN!#f0MD+m)J1l*UkTSjqIe-m1fI
-CPT4"DN"#)4-TCeMllZ6XDR3$CeF[3NN19UA`S%!6c5mATFbi1'p!r`e'Pb'JNMP
-`4LCK*M32V2*,"fA&bq9J%"GqQkji9ZV)2i22[@Jm*i0mk%K3rAe4,)m"#6pcl)d
-35@i'`SKS%(%JmK3L583HeYf%J"I-2mBJL'%fm`Hc9['c&3[[5Ehc"m@Tfhi-p"i
-)rUD"IcM$-kbl"QH)$bfc0SK!4GY`'KX10h8dkH@&jFNa3GNFUb,QfT[dc(jHQM-
-QMUHr+&!,GE-,'@ZJTrIqq)9[VX-Jcb"S*X"!D@Hb3LcY("-)NXm3q$0$T48&lcC
-E%E`$aDH%b)D[TrIld6dVZh*jQUC,,NkaT5-!r#2-(%dCQ&%eeT@9(M-M5"bjGB1
-lJ$@PiP+*r$2-m&YH20B9LbT$(@PDMD8GBeh1L4L+Kbm'ZlB[&U-LfK8i6i@Sbr+
-Sb%mk+V,@Sk`[H"5fMZhjN!!JQIJC`)m"2ceJSfLNrFcBVFh3CB**fB!1Fm'J0)"
-Tf#B08&1@EJ"0GU@TK`MEb"(G!(i-q-PN-MITZjLj3##miPi#i!L+e2dckjJ"LF(
-UL1a@8[r[`iF%m3d+,1N)#Z3'QRT"QAS"T*%3*&U"A(`F')"SpA,`)%3@CXD&*@U
-4@@@X9-$eV-aSEDS6ejfX#hK#CJ%PQLNMFjN!5iVCZBQA9[4NTPXb[SMK`'J+V$&
-QGJ"&f-4q"$'S-p6)5"#[k)L'"pKke#5BK8PS25Q,R(Ij)J"4b@m*T!%$,kK`mib
-0%8UIL-CeI'hZ,Z,p!Uc&GL3Th$[e1`a&GrPi`mDNh'`aH",#`C!!,0l*JPf*pdl
-IA9j&L'+NF"3rfIJa'Lp0ZXk"B1)Z(frJPfr6"V489!d3`Vh+)[0G2Z245CdD5di
-DkbBYYJ3P6,91@[B(Qqrb54j,YLbcL#k1Uf25biQ(K%1MCK`NYPTBMXB@AA!*ad5
-'%XK[0rUe(fRh@YF%NQ&(`2qD2l$-i6$iKN)'lc@c4Sfif93GlNj!U`kjBmDaJ$f
--cPCdRKF+E+A1DjbGkj`XTKRXC$ZLqhTkjccpqA!A2-AK#!l81)-U*F$0L*!!qdC
-%(m$bR'"bK[''##6l1akq4fmde[@c!)!#$%NfBr#*,[qDHr6R%3JYPK%dp)-YBee
-b)i1Zd`9A9q6-H"2LPE2HdlJlf'h$ZQQ-L)kbBJ$,4Y%acpC8K+E5Sf$8GhaL@I5
-3!'"H,,M3+Z2-Y"qCD9CH54l+2PITLT!!J@l8&GdmbF8D,VJm1qIZ8XlB4!abeLC
-QPjRa4lY`S!'&qA6G#VQ3!$[+fD)aqm+-Pl1H3S&a-c9`@E9rjG,!,rj6k0(8DXY
-D0M-6lNR+6%,)p,-53+h$6b0q,J,%KK4PN!$$f"*X3p@!*,hX4MXk1CbI*'B0+9P
-V2`ImM[0F*,#+3jqC1J&(liAMAHc-c`NQCi$6(Kd6F[,Cqh3kC01%ZP2Z)*eik`Z
-ad'8ikhA2CJIhM0[P!Djb3309D&MKm5N3M4!cR@J`dR@VA-TiV!$"V&A+H$)6&4i
-+X*P`8$m2f5%X&3Lpk!`kj[QUEb!6fDS`jZ-(DQb-q36q0q0r'c,,c@"(KN5VN5-
-GL-6P"GH2JCU!k,B2J8ACHMcG'(CG"D2PUZ")'hkXq'Q&BU%66ZcIIH&Q4+*33M(
-U5'6RE+YZ'[rLrY[r*Qq40iKLT!iE6$Qh*hAK`+L8!4%[`5K%4'FdmK'LMRQ2VUX
-U9aSCGehkIliaJ8`*$#)*VMLPZSFD!+$KRaA-X3J2JZiTr#5)d,mUljX`"+2c(J`
-K@3k"VJRZbPdq+rqhkJPGfVJ!Q$!jaC00(3%rN[-Iqq2GXb(UI$Ne31bIk`!AKk(
-`A6Z$c0IZ0CQr!GC%@&afj2NCI)bYQJlYSEBI#J%QVUD3!&QjhlUPZ,"2&9!4*VP
-5#"$5"R`JciDKQ#9Ma@!&*R0Q1J$rdE%ViJ!bG!FL9m4j0"l!NGIjZ0!lr"PmAfE
-A3)"H!BEjG5cNJPPcRCJe#*T1CNeSke%ZLU)3ARBZ3-G!mLKP"08YYS#N49BXJi*
-5&J@Pii*CVb8))YFjL(al`,$Gk%`36PBP+&lNi)L-BFBP4j%AE$`M+VABXGRc((c
-i"m6HM'S8BEQK+'eL3m!HUK0r&5ScEibGdN$Q%AF!NGN6#$3$*EcF'@aqX&MBk6!
-*QG"aKAf48#)T911cPrL3!1eTT+)X!H'k%CmAk60&"9Z##lDr1iGK0R@MdMd#&`Q
-)3`2MS`5#@5I[X$`XH3F'`mp&BT&Q"*J0h-U!$k9AI2IlQS5f6`CqVXV`TUp`k`e
-mD!q0G@MkT15%DcGV$U@5[#J2#+@8rAVm+,0%%UM@*#1V&NC@*(ci@GdL*l2+VV*
-YPTQR(INPk6)D9i5dDBU3!!Cf#P5f8)&VcS"9p5HhH&0fbLRHM'`L)5!,b,-A2kj
-[X%*p(--K5"U'bdjaF3'4X!kAJ#"%!T!!,!MCdAc18K"kqT)X#%e8q4PqDfI('kT
-idAIrZpAX-$YUP6SbMN&"`ma(I`)k&8Fi'RV,'r*5*C!!KeZ%i9dTY--R9`Tj(Dl
-[FSGBrQMZ`$d1M89"TcNU9rTVKMURj4qQj`P6ESc9h8*GMNf`b2-HEq&'&j3[V#"
-r$ddc3*LK3()H52acSHDQ8)&Qm(rpZ"G&9T&Qr)2+lrE#VDQ)P3h5q+h2*!Q9Q+C
-r8"RG5`VYXd&(%C-q6aSI+Cc3H$5S8Y1B0(lT&i@@63PR98!8Np0[hSclG$S"I'8
-rKZU9iPBmjf4e+0A4j*%G*ELJ[0%PkE1JH$-G#S4fRT6df*+k`&HpbE5(QD+YF+@
-)Q9*qCaGfV!MSRHVZL9d3PGa6j5NB@LQ3!'qJ3"B,6I&!-f@5TJ&m1JIrPG`T(L)
-QqQ&h"PcS8IaV`F$3`(eSqEb6erh)NLVXM4Y3(6Be0-RLb3S8QXRC3&JBBJNM501
-KQ"r*-RA#3C*bd)9rQ'jdS$-$q"!bBjZTbL1bU@ZI$LB`-S$)9#0a&@"r6`Cf63G
-8$dkf`%DR3a#baZcbjIMQZMpqiDMRJF-2p&e@Xh2Zb3,`SHJfp3fh)Z[,i#"#+$L
-cFljUKXJh&0eENSi#32mhVHi"aj!!`L,4KaYe$i6miQI'PXQ1!f%`XRL5eDGT0a3
-"c$EQqlL#4b1FdHrq9ddIZbZLF"QLUQKPAFJmI[9F#`F@[DN$bP*rM+Ye0R!'3VF
-i1fI6h*5K**dAR)N+S(eEXXIdc"VCp18)0pXR0"Xa8"X',feU3'8!1"Bmc99(NAQ
-PbU!3eYL&U5R1U)3ZX3[1bK`iYXZGi%3`%aNaU"jd@q(3JJZ*,I9`rY"ji4jN!"R
-ZZ5`J,ZkJcMXJKLiK9Y!p3%CfCJ@a#m%mbP,%T-YU23Kl+``(c"e5Vd0M&[1(Q0M
-D2GUHHAf&I-J13P`lX*N`Q$iGJ9Lp51a(jEdPk+Ja$F85'V$2'B&HmdRU`@e#K8J
-4QY&S,40&q2&Tql*k))aM`!8p`rQ8I1FeIC%N-p5rj*-6%&Q#6!SB2G,qU)NC6Q$
-2-8TPFEi0+N8jf91fMSC*(I95Vp)46Jc)4#DC(IHP!NiBI+"SrY*a1&rNI(AA"(B
-81D+"&H0i@hachCMrMeqJJMF033%9jMBp`*93)C!!TjPkKP[VRB#AbB#hFDS&i"e
-PC0RLF(3SS'G(9)LIFCE1f$NCq(LCTh%R1)`L+HUBJE*9kVLE+KNKSji@B1"Bj[S
-a+ZiK!lMa!A4+Br"M)02d-!%f'YB#G!Xd24*PIk,lCc51)*&-2EI-R$Je)X2(#95
-R[ZQV6L(V@456l#6QaF*)-&D*Ue,mjV%-+-4G,4NpfMj+X,jjIF0&$,Tb"CEe@pB
-#bLkSrC5!X2ie9[[aJX@%D"XfmI+8`*KpZ"d9JJ+0"-,fINBJB#JmIId'"kcQ@"X
-)V51Lc0AjAXRMbA!D*(+!%A!beMUjSmP-(9%Pc*K*4$2*9CbC3%d0&N'RADRH,!F
-HG(jfGPeAS"@$pP*b1irefSjpHj5"Qj2l!$UACZGXf$J*h%a3qTMBq4!!Gj3!98q
-!HT1UF(,AL+BR4D#kiFZ61YXTL8b5Ki%9B)A+4B`S0XaPiXU!Zf'q'h!hI-+!qk8
-DMGp5()$,(&8kZba3K"DVlbZ&k"!*(bMF(c#0%[--bPNrd-U5e&AeIB",-j+p3f4
-GPjGhBDQ1TiZG2!JbILe`)NNqD9$IPj0`Y%XC)1HbQUI#+B@G6$3TCKB8T1U%dAK
-!*M5*'*l*!XB[KdCP4NX[#bDBF*8'F-KALfQi!`68,$"J2JDVS('T89BN3X4'"MA
-YRIbUT9qjbfIULF8A&)19Z""4#8FG9bi5KJ"mh03"d69-QpL%`0L-BNJ[iD#C&b$
-H[Xp%XeZiZh@1bSj"R"e-+0P(&%eAK+[TLZKTDQ$aPM2TR(@%3((DPR'FcJ9jLbh
-Vq(,k`3)%DppJ&`e6-3S")0CSlp'C!j%2@L)'YbQ"&jJq-2-*E-H+JY1"UZ2AX)(
-+jdFI-A!L@'CUh-jkZSA1*,I-r0lS)X(2"E,dJ2Nf,M`@eeq!)Q!Qh1NrIH@UF1Q
-+JG6Qeei92ETT%!)@"PI1-,UcaDFSJm6E8bV'@e`kG3*J`S8YX6j4p0XDQfU,PR6
-2)P#eSN&1PNJV*b!bkpf9FMBFQDJiEmM)frVQa%YCA%Jr`pMI`9Zf6h"2*)BH*fq
-qbBc!`fU`hP6YP1T)lC6J&Hf8kLY3Nd`*bU)&%%11Z'Jb(`G)A1P$Bmq8)%aY&%k
-TKV,Y4M#%V,8H$APSm,(MJidT[kc*`d-S8aebp3-@hGI%`2aB"PG09PH913GEYB*
-4#IpJ5JpB+iXA!(%!U&[TJTdQ"2"!fjA#+H96F['URl,h#SDC8Sl$kph9ZX'`iST
-SV$iHb2c)BCdITQV8mEIqG(Ya8)fFF,-eQ3MZ#ki+)LX!NMLQ5l96bYqkKPIp@m9
-#C[HLB98QX6@*()j2q9SfYZBf'Sb&0$BYX*RC--4S9*@P-MN5QSr)0[R$X`c*Xid
-,#$K@SBT[X'0'BcrF`j3ZAqB!lMk!Um)bk`h"c+T-+@#RF$Rl33ZcP8-',!ij8Sr
-+U)G`%)CV-6SF3r0rU"'FDCr+BNJICFP48-irGRZAaH&4KrpiZV[+Uqaq&dB'$'$
-JBe@rB"FX2a6GUU4qd-Q#Gi!9A804Nkc)j&IIFR+qY-XGCM3Dk[dF'*RPR'392ec
-Rp)b'RqKKT(9PIf8@a0UZ#Bl2M9aT6,!l+9"CUif"#H9B9U#CNS@DRZJmcSkQ@4-
-6&Sb$!Mi`XCHM3+9$fC83a,42j381A3#RQ+0rrDpC(d()4R4fcUBdC-d3G9c-'K&
-@A-VKcVV*3%[9CT)6Mf%"RBGqILm$CdRkV55K()J[NXQ@I-5'C*!!K$V+2Jjb"2Y
-6@C(9pakCbZVpH*hilGlVILfF4U51hqk9XKkm+E0*![A5BHdCM9rE%meDI91%l6h
-#($Yq@G3,Z0S8*E)ibjML,12&d4CfeN+LA"apSMamGrGT(bdrrVZp2LpAlS",rF9
-`10HA1Pfb6hZST!H'2"bhhf&'Tj3&0JSc61ce3#m+HfD[K5!hhjQ"N!#dYCQk&AL
-"%3%&AVqNVA(Fqr%kAff[EMiU,)hUhUbfDq)`fc(+`UT46arer)(+%P`Cm$8%Xb-
-FN!$59J"P,XS6#!!,N!!K+'8",+9P8Y"fIQMEcJmYY[0$fhELf-i2H6YJ!T9+TdZ
-UG+@SUV+ST"IAD0BYZ[dD0VC!dXSE8apPG4L,RCRT%5dTJY*53RV8RT5ce15J8ID
-i,e`5'C*k*-eiFXGHbkBDGBd[r%cGN!"dL"YGCS0CEPlM+cMA1#3GjQ@hd3BXr`@
-A55["JEL1AjGfHim&-H'1[bV-"58%&hXjl*C%`1TF2Gp3BK!h3YT$KPrcCdP*L4J
-2CI8DhZ22JT)#F64dkV$KFrkX,i([8UJ%VR)`'i+&U596XA$16&QY-TJ'%U[R*d[
-#@$`Z,jCD,TkA&aHl&c0GGLJ'#S9Za2@`"-3GAUCFG5k52FcAC*!!Eh5NB#DL,S*
--*%bS5*jHAp(CU'I1XG1qfZGd@qrm8Galap92kKr`5ZheMfmIM,6rpFKHhiD6NKm
-6MdApFdjLiUp!M0)lZi8rlYhqqHp2EI*+m8[@RB24H,QG%cKem)jT8J-kR)`fc-Q
-P$NRG0(4)aVd*+ILPM9kT)fr9eX'DM[)eGeFGm@hD*m8a24I6cp*dZbiIdqeallY
-[E&jaPeIbA0C['kccP,IGAER(Ya%+f9jIY+()'qe31MKdQp$"%IIq1@p9a3D[j"p
-jr0l"P2q[qmlklMSfBBX`PUAEMXR@Z2I`QIIUlRKADRMEZQ+`X3&AVrMBpm"*UCd
-ffUjX0)aU4pdL(2F1DRTAddCAd8EA+"[ph,E4-p5K99H%$Uealp,HIe"TShVDD*[
-&4XrB0LVTeQ'k&2IqbMGl!fq851iKNTpPNY-frFVdK'i$TLILhRdpceG`!K(4ff@
-LSi*rfAV&N!!!E4J4KIJ4h5jdM-5p1YeIhU)YVk)YVk%YFkGf)Rrl((a3PaVG-R5
-TLAXr1Rl(1laY5S#iNJ"R1!'+f""$Kl*YM@iZ1QMLh[YZVSQZ03(1f",J8Ge86(i
-8**VpckrqAENbE384H614JqZR52CH9,*"8YL9T"M9E8((dEMhdhrVqjLf[iUfldb
-+GC`8MB)6)f'IFjSkMHYfS00ih2[bDmQReT)F$GLfRFQ,LN5PFHqLcLF28$)m`FR
-`5cNCiT4JZ64TFGaEC(lG[2jGbAlT0cMHAVk5MimHr2Xd"B4A+X-YLhY6jmmp4q3
-H)R)h%lNrSQ5&SlI8AT6Vml)630chd`@I&frbJFaf)V09)I0+)Ya+*Kb'h"lhhYA
-Nq(FLla0-hPr+j*8"eX0*J@QliYj3McAMlqp++qQ++q8V%NNl#&6YbS!liYi0(pc
-V*9)1%5QEPFfXib4M*bpTCG&*ZZ5QZ1qhIrrDe)dqN!$36L5d%JNriQ5LlGL,cY,
-8$A(I8lrlVhYCS6Q"M#X*+&FUK0`5pdljA[YGN`P*L--#&@"UIYblq$Xr1--E)N+
-Z9!Lj6`iH&S4F&rFG1QHpIbf%E&!#REcaUA&[pcrpY12rJT!!dq,HXVpqYj36N!#
-Zf'",DLFKR3P6&2F'ESA@-b(cKN!F*U4-()p#R,K#aVPahrIV"[B`'H[Y)!k6m5Y
-b8(m$8prbbXQX@r)Y&b'p9NCk2rdq0J(AaIrKLmCTbVUipm`r,r*5%ZqQ*'j3L2G
-VUH%2[ULITJ%!#rrrAd3jm()aeaJh((BG*X+e4aYHpd8lD"S5BZRGShBLaNSQ4[P
-[lTi&FTb422m#mY)N")a2hYR@`m'R[T@[r91P32Lp,pT18cE&[IXIq2qkL9LlL9J
-0YQ#a%KIhd$33DY%IpKZC8(bPQRC$VkZA#"@2VRcGHA%!m$[r-MG)"&K*52mh6U4
-[)a+5-2,r[[dHAEZ9Vre6"G(m`8QNVA([YJmH@8*JXj[!TX'*hRr[h$a!DmYI0FH
-F*)V'$3GG"qRDRdXVrm9jE34jrpkrG4$b@%QJraXPHH9Vbb6B%2HZhj,r,8)H6#6
-26ip-5YLjFHqpArVQh46FGP0`Dh!APEE%4D$XQT&AbKHRC&Xj+GPN)J%iThhPe'e
-#c#X*e(rM"RAI-H95)-,LKk)p4+B@*Y2p0N$hR95)J%6TUp2pNC+ZMC*1EiNZS[E
-6#-L[8lAiZ'r@`JXrIJ!"lY)DfX#U#HKL*DEDDHVfZ+rXeCRI)Q643#6El8B@[V0
-ZJYcqbc06L'3Y6,,lEBM#PkZ3!!0*p+rfGGF)6E34QY"ESSPS!`ledk'lS(Vikq,
-riqp&52!eP1#Vh'M#GmB0bXGbrre")P`$%@lh@JL(!(CVm1hdRdJi*&4DcEdl*K2
-1L4k)($,K&XGpheAlV%bi[$@%(PDjdB10(!$Tl15D$bL3!$83DYLYS!C,JL#J2Cr
-apQN+(#dF11kAN81FVQm,q'rF@2iBJp")'kkr%PHE44[`@f`!)&4hajerB&)3`H)
-+`8lbp8%`Ma1XIhRflcpL8P"5qT@N221PQemG&2jl"NAbMN&KKk"C1XP")cNLJUX
-JmJpYpmi"keEEKma"d90H[h#dA&T9j(h+pkM3pYRl)+aZU"HA8Am%iVA+$Qc-K,f
-dkTV[6ZrG(afkImUkllaVe$2$Pck+T0@lpPjDpDMI-#F9bMapl[3d,`qFd05)ZrI
-NqK+RF@M$R5IRq'V8U+C9l2SSi6PqHTT2QH$phCjMek+H8lK5Sc+KA,rPT(Z#`H9
-bmC4-6)NFG!kKY4JL'2jGmE&r$2CI@P@q%PfpdG8rrHMdr"SaajI`APU9m'6K5P&
-$p1&Ui@cih8FRVf&k-df(I9CR!b-EENTiH"[4KpICQR")pmPV@FH3!,AV34B4iRc
-D,SY-"l&6j!bXD*&C+fTFB4[J3qbeG#&5-Zb2+eNJ9!H5I1i&UK"ddlf!+N%@Rpl
-ClSp[Uq-DTH20b9H3!0DiXe51)QQ01p[&Rmi-'MiHGbpr@af8)adq0f1MLeNU8-G
-1@CGDRDG'2H9GZlVRR+haE$Tla!XA"2pP0HV(dV%krmCMHla[3rfkI5q#@bX(0qR
-aYh+$r8@j"qqI2T!!dYK&X$rUhr(4(0r"qkF1R*hI+U*qed($39ji6eNS$f-`,%b
-MK8K(p2(AFhQ!,f$"FS!r64VJFf9"l[jVZAZmTU21rrYMfX2f`j5*LdNG1rG'1mU
-l#1Qp+mAa'DF2lm!p5EFcRee5YKaj'5iG[ZL'epIGAQ,"&TXd39T[18&AM`UVa-a
-J-h8!SRS`4UEAjUNA$J9dTE9j(mhkVlm53ir!Uk`6TK0+Ic1XHeDSH#d4)Ebq*Ma
-iP3NrANY&"ejT)SkA6V52X!1ehKK*l)F6JGeKC@A2@bfZ9JVmb@Urb4VE"SBS'la
-+MB"KJB8YF'I-9bi5,3(EUP9KdHJ@X4P$VY*)94X99Kr8IISQ2a5PCdfN(JRSZpJ
-)mN@`q1(!S"P+#DMpNeaP(DV)Lh#I#-P!!bC'QYdX'U%QUK20[+J+'-"6*ZMB08m
-m"ZA[k&`4`N%K1Q5B"Km&Ha6ZX(Cf*%Z,18beXjD!L6`r!a%d$+,K#63NAI)#M!2
-"@`j94K'"Zf6XR2[!3(C3I""0XA2T%RECD4V21P55KFd[k9iU`F9"Ym6YJT6UXTq
-8(Fj6XX0j4YrpXll'UT%RqQBYBAG3B`f1k0+Ph8VBDi9ZeT,VE9TF!3%6Vi2hceU
-bTSV9DFBiNkelDK1c3Id'fE9iND'`1+[lqr5+Z,5Z,)@)IPH6Z+JBFb`(Qr48fL,
-$F&VCB$Qcm3BrJb++U`Q*q6MLHUF@8DSfa)`JX@DZq'pKDlkpdqRNJ3'@i-ILb-%
-2q0@%Dd'Pd+fT,6jP+-VbpD1bIA'*SHJEL!kqLNZ+`9`fHBR)%5Mkc3m@BQ)pP2S
-(D*!!'IKiDK"++&c[-lTZ(##c&84P*Zkb`A*8F8kN6M#LP"8ahIXiJ3cel%S+XeM
-Y)(*j`Y#%EF&e@LB0-hQhXQ'"lZr,LrfXEUjpicSYXR%jX$,I+'!LG[q)#c!PQ80
-)jRZCj)3!Z8U5J,ZB[[XN@2eGV(JEr%bHaXU%PiX5*e*+B%aEl'6NYp9@r&`Q0Ic
-!#bZjZR@%(&RFVZZRS8lpN!!E64(eeB!,%lkZ+&A(j#i``6V#894eUHpENEBB,0[
-KY-@mC#K3&fERr(DU6+kJQXQU@5dhZBH*Y8*4BfILK0Keq[,aG'8kP'HK&,NaJ*J
-aKf5#1iK`EY-)-`(IZfDSAmQU!6CXNQIb3FPK0ARBp-$h-Yf$U$Z9aA&@l6$)%,-
-C!-09MDPljG1pcZ[+`he05djT+APEkN)q'ZkPM3$%j+5T%CK#FQre(9D*a+CqHi5
-jGckjVMPiD3d#J[TU24[-U#0LU$)aX0"L)hlBJ[Kf*e'0E&rmfbDTf2+65$TQGT0
-dDCdP54p,XaMNTV+ilB9)kJBP0MVcfaCjdk*H*NS6QcT@j5jXE2Qhj`LPYJ8kD6"
--4R@TKF%i6*9ENXCKfjCUZ5h("#-6&NBET%P''c``US'!(Y!m)lZj$KP6LPSQL3'
-[!6MEaM$&ZFL'IArl'V'B,Bcq`JM5Z(fMjV#8r+!6CM,1X@+aD6ccXp[PV(lVRTR
-U5JdJ+28P-NI8M-1&)&C`&E0B3E)N1i"[paRpMTDALjLT932eTF2$5T8fJ@T2N4H
-H1PZd6A010BlC1m5URc4pJqAdT+2MK1#PM-293PGqCD!b+!d!U!rLqZ8F$Ce'Y2k
-P20&3QAH&M9AV+YqQKQYS1-e4cpm42F[4$LZLHc$j"j8Imq3'AH90DNLJB5&(ilF
-4RFh4pNm4I4q6QbYRmZ69ZXSCe,!!$Cpb02NmSX8FeBmL@N@AH&1ja'[8B%$$2)i
-fI)6SA)lDTb0D4*1R+C2IXkab)$RCj+Ua@FX9!KeVhJ)X##eA2&pc-F3ZKEIZY94
-S4NM)6@i(JMI!LDUf-T9GZDM890[G*k[VAB99TiaC-)54-ZAH'NMjZB$8+3@N6RI
-&9"@ldPGe&9H5ULkp9&Jj[HUmUl*+#c99E@AF8&M9#lA1-Kk+!m2+(T1!dfrm1e0
-QRaaqVEqfkK3@0E`BB(-SdbFB6)'cE&3aTTa39(L55h*%VFLJVhR,Qr+b%HCSM8$
-@02U3!%#fl*'$8!@Y5Dcq$em#)ZKETk0JR-1PlR4![h121-hB`4MDZ3FZrIl8LFL
-*bDBN&''rFDh+UQC@8ke05F9%E!rc*D'NFP`@jB)&ikap2)aVd"r(6qL5L1k2HL9
-9klX!J`q5QX@4T+5HiSKG8NXiiT!!e(-FX8VUFBk%*4J-4D5elkG#b[6D[BbS#ZI
-Pm@"VN!#BMjD)I1m@AqJdLbR4ef[%)piDS6f@FiBGbNXqdTkeRk8ZGmV1*!*QGX)
-lh*GHaB3P81',*fVmS8L02`i(eVh'4ZeTHGJkC-Ff(!Y4"E`DcB"ikKKqcYC!Q-m
-rbdBd1H[fqZ05HmBC1&C1ImMP$ch8iir$[A+Cmb#!3T%E"4%U,a$Rb!$r16MLSCN
-qXNdFeI1%+`A#@&A%LG&8LmijiJBA%e"%kib4&*Ci1dd4YCNR)m)+IZQ+ZDSSNb[
-hkcJUHG`SLee88l)KFE[4JFN'L*(2`Q#%$SMm3ll#'lQ"q),+@AZUGhkGLM)f)N,
-UA+TUG9IPV)q9D9c"(qMP4rL!8T59X,@981bZDb'h(`GGdH8H4&CqXfN56(,PRma
--*c0@IP6INJHd0ZQ9JS'R5$a`C[T%%ca1-@9%`*AKP1@@fDJ+#H3jZKDC3$"iF0e
-G!5hL0-FLX8QAL9h*5-Q-Zma8b1HJHL9A9H-"%R"Y(Z0#e#aL)@hILlZLN!$B-pQ
-NdCKFD6$*,Kka1P0KeG5!!`&l+Kr6H2SPFp9lap1a2!e"U,Ei@kLDb5*Hqq!MTXS
-+Dm!+Ca'3!")GhT-++kcC0q'J&G*iq[(!!S83*'!+`Bj8`Ylp'kR,l[ZXr(U-c6h
-e+`%AfbP(4lm'#qJk40hdG%')TDPK150$arI59FbFBAR1&a[P,!*938BP!jk!406
-$jEiGSR"NmT)VJ'Y1khiEk(!D,Zm)X"-k$U$#8Yk!3pj!8(5CfF8KGF)TcN2eMSX
-'8K"(pA!3kk4VF#85')d4H[I!E0UUSX(C$49KC!GVkc2mD!IhjXqCDLXD!Z11fUT
-YA-`CI'2#K58L,6Y1,&'%kZ83U,QU6f(9YZlcU*bTYhfHi)G&00N)Q,E&dB9,0e*
-'T0&'HSGXrTkhb0eFMeLifVHCDUZQ"fJ!0%l(pZhC0ih06N3U,p!`5@a&Uf3TN`L
--GRU3!-0!qQ%LF*)0qfbr,4[i@ID,IY%p-h'#0p$Y5'PK(L)%0diBL5"(6La$J"S
-b&$dD3I@E13Yp#le`mGl,reIXc6qpdiI-jJaf%fXSCT0G%"#dlNrZMNF(1!c[SVX
-9hEd,I4'YaSS$8)6`!C1(!e04Lb&R[S6UJ&A6m)T@6Ed#mjm99V`L&3kU11MJl@2
-,U#`6H3!"a1m#B6Jj%0Q@R90RT'e#,'@Rbqi6#JRRA$P4B8HQaQHa1&9aMZF(Z(c
-52llp0T*V*LD9ibF2J#)3U@B"8,4hEfZUVE"EGTCkB%Lq@1U$8Ek[%'$"Y3TA'S#
-3!2N*VZ@L`C3$-&!3%dleMbrl"6lU-D3(3hUD110e2$[RNHR+%%B-SFF3TpJYerf
-S!D"ecYS&%!"EbD8rE(2VYa@MDADEd`NKA'51Rm@cJA)J+iX!6,)!42!!$!,iarN
-ekeQH-U(DC,dkB*UR$J4kU$*%R"J-F@)`T,"J9E,f,Ibi*BAYeXL2(*'chFJB02p
-(UCSCL#Hd%*cR6N5XXMNk2*UMXU,PGKfZ9B-Jp4aAjj%E,YAQHkqB+eU-cFkPicj
-HF$kfT-PM-86Rl3)JSr'[r3XlG$*T"SeYAE&4")%EH#c+C5N6MKmKX(J+4"`!$$G
-1'%**U`jcKAa%bkUEi4iIeff[43IGYK%9)LeRTI'JQar!IA$#"6SY(,9N!f`bF@%
-Hc1J#1iH,dK[C13pG"M,faI`1Ml&'dpH%`$YV#BSH28GXQA)'T'1FN9$)lcQHlK`
-qE3Hl*6S0pDINLK&$9"'cC9)"akj0j$S2&c1ZD"TqdB3@H3*!D5iCB"U6A8L(JM"
-a9eZ4B)&UqAbZkSNUZ$#q`PAN191d*S[GQ2eT9#NN3K11XJ%bb`+*-fK1)a42Q#X
-5cSaLE1*3HKS+4V0hRiACJBdXf-DSdM*!(U`JVMD),-`[,T@$5"&0&jN*r6+*T"-
-'FXbKJDU*%%+Ni3T`NcE8FbEcqDNm,,+qRFk"%6"$5%D)dNp(P8(aq#'UaPVpNVQ
-ipmV9d2@+mhJC+miek9d"DVU[AmL'"H5)jk351DBd9#2bK5)BZQVLSXh$&FJpZi*
-QAN)3l3c%Vece[&eaMX%#$Y!0#-iTQ1GbS3$Q6GZTmLHZY(`MUMV8&T[QA`d9"'T
-SHXVTRUb!aQP-mi&iLlJVR"IM-TJdGI"QfIPhp3&+F+'fd3"iG*P-%$TUE@4SPFQ
-`Y%FQJhT1*S1UC6+Sf8`'"KPUI%EHX2SAK3#RP8LZdR!1M`3M83G2ArQHQaLK$DK
-BBdQ-baAR!'VcU&UchTP8F'HG3+$I4*'9lV")a,83#JEYIL+K(*XR%JV(ZSJ8)M4
-+JE4&Z@6PmYQFT@C5P0h)B[C''3H"4FY-3RERKCRr6f%FS4J9C+DaHkc6-CC-3c5
-#BE'3!,-$6P-U)D!5h9`JV`Ziq+1)2"PSK,0Z(99aH5F34H(cA##DE!4fR"YS#3f
-RkD!1((jV"p54r(V('*FA%E3ZiUF4#AAHa1Dc*%3()JBNhMcm[)EVXi0l#EfB1@6
-&-Cf+@E)fZYa4jA*CcX[9APAEG*[`DY(Yi#akMIJk)h$2A*LMi`GkCHFNf$M0*VN
-D4b+-MafCkEaaTr-Y(6!@1)TYC!EUH*Zaa#XpD6YUqp*fJT9d,b15TkkL+)cJ%i-
-mp6i,iK"#R-6q4+iH%fM$81d`U0$X"%aXie&0Pf*QS4jXi3JjjNFBKE#jNjZ$F"i
-AXS$rTl!Xi-Fb`5L1"%bBIK4*j#)QD3f1q6)UJb,6U)Z3!&Q#rEUMr!'A[`&brSm
-S"JSbXEAMf&T0-$,$50-[b!J4,+EDG9q8h6+cFqb2)YMYc8)3ZbYcSPR8,JQSH!K
-9e9TKU,)6U*Qc"P(*3iAIXN!5!NUif!`"T,$Bl#UX5,PUL`0"Hp(*Q*dQJ3H!i2V
-S5iFV5j`,U$Cd')X*QAfQ[LS,Nq1#+b!jMBSKdC+)C$+$hG5$`JCQ"-"U3@Am0Ul
-5E'-(GRR3R*30Q%#B)d-TKXaqCLM99Tah&JSJaK%'(k0TmQ!mT5X#YQ+"qJrrFi0
-4`%cLX5G!!6rSPCPF91@jim#BVFScXYRihmJr,afU5#&Bpr,$VB"!9L(Ek2K4CF9
-jc5%Tb4(M%%eaIM*ESX6LJ6!ER48'f6!`NU"jK*mid[9c2jb4ZlKU%aGCR9XS'Zp
-(*BU@)J+J)93,q4$ZTaZeqfc6UV4p9%$M850F3"0,F'0pjfcc$EqQ!qTC-B6!m5D
-+Z9[q[q(",c4K"i"S"jMqME#Je1KFe2TiZ@pC8Z$KBc6-M%ClRqHhp0LZ'PjiX*%
-H#1Lm9!eG5Sr(Qj36ial"Te-+)ZLl+m!Y06K9c#`'0,*,mD3#1'A1iia(JKfB`H!
-YF,*5BBUP+kf!c9qL-JZLFK(4!40!D38`(6'#K#T6N!!Y$+4%J#JB65`e1*(FdUf
-@#'lTBLH+K"#3!'68YR44c2C`Vk@rC,3A3j@STEmF%4C6QjA--#!p%"T4rpDhp&@
-)9N01C,9dSI-3[PC61jN3Ma)M9Kr3bfJFaEf@8%Bl6`+CJNLQaV'ZJpJXh'pP4(e
-i)U*Qe,l)5%`ZiEFHa'BQ)fd6VKU)dlAM9*hd(5bp'Z$*#eq%4!pE9%AJSH2bd*i
-F"AR",-l5-NCH5m[@KVbQ(9H3!&H@#4-$fDkUY#'Jd$C'AQP#39iA*A4Rj#9[,'f
-)&fScdb4'B%[,C!5@PUJpR+E"&#%M-(5j`#cL2jFV9iS!&"kqJF*j-UXL*8M-Ij,
-"J#UUTaRY6NB-2TG0B-,F1i%*8r!#6*J#Q3R6k('cBA)@mNDC5)YhbPF+IEKfCNc
-1J[`c2jNCNl03CXC-CS#N#-#H&a-Q&p"J1I&26)H)e'cNe-bQ"Gh-Q%BR-kBaia#
-f98jQQh0DZ%S$&(bk)%#-6F"mI!5"L3-8+`-J'QbfRe'-#"@BpJAB2'cF+HUbdXX
-'JJ"-hE4AmS$-*S$KdaYP3UJI-i#L'QNTJa1-f'qU(9jUN!!,jC45+#q`&FUY0pf
-&FQZZA#L[&Bb4h)'i')BKMlN[$-!["RC,F(jk9,kLf)VU20&AHTCq8RYikDF-KJL
-Ja8%c9heJKXE56b#Qj8&TA9N4#BacJ3rb@@m)9,XpK)S$iI'1jhVKQ*qmTFrX@p"
-EZ-3)jY@#3i9,j+Q2el[3NF'6MB09e!6DF03!MXV'K"S-2i"*"j!!5EkHF@J#q&A
-,i#I9c[SB*[QU1GRNj-,MGdVG#4RH$N"""E$3m-3%A6l2)N%M*!D+T9B,"a-m8U*
-9BHma3iV0#BV05*!!%IaF`UF@%HN%Ub#22)G+R`#*)QEEi('06`bfDET'@299*F&
-!fe[h9pa!3Xr!KQi-IZCNDXP+6hlSSPdrST+`kE1BALj2"qMZSD'Z4eJP6kaH0[$
-'PIlYIY%)4DYI2)%12BSkZlD#JP2h[r1$2H(ZX%+hH1C,84mhZ!,GrbkM6KS5,$T
-8!U1U2Gde0lUi5)ZJdQF-9CqjSIX90NF2S@UaSUU"Z5YQdXJA&&ZB@3@&'mcfa5i
-L`6qY,4bFcYRN`FhdQ,)bCI$Yh8qk#YmB`%qf!C(")#CVM9P"$cV#a(R,-#Tdk@9
-RRX&rTSHSPLVQEjCe9fZki*UJCe099,NCM4$Y#j4PZlaPTdMrH"Qf0FjNNZJaN4N
-)d&!Zj!BLV2*'P6@qH+Y-9M6!j,Sl#I4l13NFE(M)9M9)b5!R&DD*`m+e3XR8JL9
-RY6%$diMC1ZlClQ5IpA[i`Eb"LiTUh@1K@+pp`bJVbeNC$NDZ4BIMkE(0PU`3C$j
-V+rS4-'iJke"CBFBMUj'8h9p(S$(cCVUYL0k3!,H)kNT*C0re9)N1$+r(Kb`'kJ$
-$Bq`TJ,0BL-H6,Na%a2Z[H@208B2dN!#B#E0VX`(Heek$m3ZHk"S8Rh!NDVK3)"D
-+pr'D,@E#!02Xep"8@'!D&!Y[2BU+%`XP9'$@,B2`fKB0lI!1M)ICS-D[TBiG[J&
-c@$814821aB&$@)#UK48PiYHhiY&aQSTM(MiSTV2bC5!#be3,"r+5e!'2mIkNVQX
-Y'jMp[q-'H#)Bi-N(#m60Y5aHXpJS,e9@'*!!h)CE3$Nm6DUY-$`i+'rp685UrAL
-`q@cDi[mfa!#J'ZUk*P8mD`CEB*lEI"FV*6Q!mP"MifVAK`ALBa6NeI,deChFB)r
-!H(XeLkp3[51+l'GkJ)hCHELCTlX#6H1RNlSGJrr"PC(K1UMLXEi$%+S+ef82(KR
-YiQ*%RXSZ020KN!$J`aiM%5XM)USR0`rIbafGLpNj1mFc`BUc-#&QZc)Q$-KA(@,
-(S#32%!HU)X+BaFH6ZV"k$deFE%0SDj3CqC-kQ5b""4UHf6C92e!a(XB-TU3T)SC
-MMB3-GJ0SN!!e`dF2+Z85XS1M$9i3jeh1"qjf#FXQ,Q+3!!3jS8Y`Ri5CQ4!cJ8p
-CS*T#'G%lMG`4+T,SN3$SMUdDJ)cpabPVUPak(83Z2L#+"$j&d3X[*KE8M1X#`e"
-+Ikmi#bppm5QmA-8PH$eBI!j&49Da9AD+8NLl@9j`ZNG4i)',9(k"Q)j$Ti*GG8T
-aJ#Tmiebap5@i44@IBc@mXm&SHZ(M*MYIdG*heh+)20Rf!!-f'J@#aCf1H9#KePB
--`'46NXfrfTM3-*4b1bCr3V%`)*-"Kir5G3i@Pr"4,a@)UF@RJJem("me*KCJ+G$
-iF*qB+KQ)B1b@Z+6iFAQ,mP9Xa)a6SpA0JXE3Il2BEUhYQ)q9EA`Afhd)lQZ[1S&
-h-(GL3L&SC@"J5Jch0Te$fiC6KRmT6hh)1654,S,!@h4*RqrYjm,d)GY"eC-2`J!
-V,DiDYPh9C(&9Um99*HF3l!VCZTEVbN2DKP''a4A$PPFFMBKVKBq1qB&QEYl`Q!i
-94T6XrL,1lLZE-&PX`NS1H)X'Fbd-m5f4A4!S%p92#0IKLSJ"r&6M4hSBJVm`d1X
-D8$&FL3&+0`e&3)N,DANk)fMmc-62q`qcN6F6[6l'Ud&-"EXTB5r8kGiBL'8#')e
-3Kp8@AfGe'&GL5lY$8QdU-Hp1hd[Q0l,G+M9-23pe@Qha!9DRAHVHiKh)Li6Bf0`
-@hdZZ0`CSB#eBX4$-hXKm#5mN!`3eJ1%hmN%QJ'%*"i#i@Af)3C)$2d5rBKBh!-J
-p42+,p2"e6#Iea52f`RC4I,c3(qaJPD%3HMa-Rd3J2)Upq"#kh6"U[[dZhDZjLic
-Xj'5@8BZ-9Q684%52L-'(mciI&C[TP8qN[C1$K)bQIM$Ma@K+38CkX&128c$#),&
-4J-S2#4J2%hVBa-#MrUhih$1%e!K*N!#!43pY`UXl#eFd'aRT`S"&p`N&4!FjLf%
-I4VDPe6Qi8h4cATK&1"LX1`2!XJrZX9@T,V2F,Y65%1N)Z*jMe@A&FicbFB#M1c)
-4-6[CATa"'LIffr-Em*-2GU-"$Tl2ALQX(+S-mHXVD@!b6JIEE"-l$VN+Zl2`XpP
-9f9f0RhXY@@m"+1(r`NE8Dll1,lJ5Kpj1JF9R,a6qbK)fHbXE3kRc5"dIG(,eGi$
-(qcZ2`HL9q&PTp6BmlUHjET`rf&!,-K#q5%I1b9ZKL-G3f2d1e*PNPY@cr0$phHp
-NlXRF3hrk3-iZBG)1PrE$805ZHC3"0AkBLmFaP4#l2""S$D+D@d#[!3X9MhEBDi5
-ihd4QUMI-c8aRGkEqpLBbqqK(&[QIAL-(Taar&E2i6#GPNAm)"2R'ZchUbqr#B$S
-Hc`e6-$"qS4E"HCM0cmaM"kUIP4BQjFXE3h8HCCJ#ZRJ(,PjELDYk4Mmm*NrQi3Z
-6%D8$El"b(6U-SN-2EE5f%J$K5AkBLdY*TQ2F!F*GNA2Vf(*CIfhhCM428c,GRp#
-Q%l6T6QckQ,,T$YTd"l'3!(#*1pkcEEY$ZGCf8bk6mTB4`rGB$!pfb$r&D2MH5B1
-rQ+"di6ZZmZ#9kiLNmKD1F%DC-N%LED0-&Sp@hUl("(#r$-!p"m!VJ6*Z'#"q#S)
-C@*U'`QH0q)&Ca'Fcm9-#JcV,aPJ!JA[CRjIc4"2BMB&aJ*qKe`aNBi"E[#p@BkQ
-!0[,M"286e$YRh3T5r1N!PFr[3,&[+$CC'!NVC3-2cNI2!i'G(bEA)K9(9D3-4IP
-BBQBd`091*!"iJ`L%L(j@bYA-%rZJ8#K6f&!aUID0A"6RTGA(D`[Ib0@96A4*)JG
-e'&)1@+(JA3q9!4K`[eXFe((QANbIj0b8`j9p`EJSII!D'`AL!fl&DGM5#F1@XK'
-'j6Y'RDb`*%pR"PKL(dIj)I![X"NFF(-[6+SKNK*r4,1drm%TF#Kc42I#R#!ECLm
-E(S)"Q[8`53ZQbHpB!DU$*SZ"`djCH!6#lm3JcQ%M6er2cRNHMiRJLJKZ3aDi+"J
-@AdQ$UDA#Vd!NV"`#-1$44'PRLE&T*kFV1dr69PEb)j8FEPG9*@%8pI8#5KbqTY(
-XiYH0YC*B,a-MGVQ*rMb&jCZGC!@c1[BKYS6(`CDj@CC[j!l2)c#h!Xa2a[b5ajJ
-NiRMbpkD%DjD`IimIp4@'@FiDr-%EdL0p)J%d%&+'m2m4,aK'fXJN@(i!$&ll4!+
-3!2-D((6Z'5$R6)rXV'[KR1P(GBmSh&'5h3pFkH[Hb8kBhGZJ#R*dhmA)"0II2JD
-L-UMF-cdVhF+"J-3+Cr"9(Ti&BI1H6r"RB*b`I-3D'`'Qifh1`T-ZF$&PiSIAQ$+
-'bmEUK!1Q2[(RH#!M,6h*Qdr!S+`NDKlMajb&LB'kAEN3&+#@Mf&$B451Y4"i@)Q
-ScBT,#B6$[m2&VBQ(D#''b*!!M6KXrPhPMP!26AGh5*['"G-)XI1EqS6X1%%GZ4+
-mX#-$I#VS!%KVjFFGfJ6TXYYK'@hmRh-CE5JLY4C'fUCh&Fjk9Q()**@JckDEq)p
-0X(-J(PX0Nq5P6&EA3MR)9CbrCB4EahPGUE(%#@lpUpf!KU#Fl1m6'J6ADc,!,6[
-["MJdjZR@SlQF3A4X8*M(!+E1B-h+UHm82EM3aKKA8%IKKja9TB#YAh[!TL!j""9
-E-`I,Vll@hb-Z!S8dba-UcMqi%%XDbmSS3J$%QV[cAf*!fi)2IIF+&1SE$k*iBAD
-c-`PI21dP#%S[RYMN)B1*5A+K'arqcqTU-YM&Ih,'H2,*`EDa,Sh(%P39)k-`@8P
-GQ!AUjfNa-MUNUf)3RfJ`e0R*G#f@$2*$0Ih1l+Q&3I8hj8#!a*Z,Rk,J1)"K'U*
-616Q0jD6JRDXBMl`aq+p3P4MY+*&kY,SYX92fULmHl-[3EBJ0N!"VhbK0Ia06[dG
-6)r+#-X3Id2!+06JJ$2`"jX@["8-`&HBhkK-i(SmJ+K*m`6Ej8%`IjHP3cq9TaTF
-16Jb3!1aHc)3,&[cLjh"(H%3chP&,j'K*C)"%9PZMRKT9QD#@3Dh*!fIQ*0`3qI'
-0B9X(,[kiLq!Z4Z@aL`UamXN814Y`T-Sk#'+ME-J1%3eAdN%%5RK@)+4*AE)6iKC
-m[%pSZShqe"ejkAUBPA0$dJrUkPIkk8mqb8F5TYMd,+laf6"RrEH`HaMpU5`+1-4
-kZ6NfI2d5A[mCj'T"@pRSN[a(Q@M''k`d6C+[YR3G!`3lL-T!a3%Z'"Um--B20S!
-KE5kB)&c1CQEcc)Gik&p8rqScrQabd1+69%&MPqhi'#A,iUEa@[b6Qq)1DKU3!)Q
-`p"`GH95Hb)4JC)PNG-M-@GH20H-rq)fF5$+CPNDSLedQhY)@rU6$krKKX%!'qB`
-Ldl+NMRHr$rFG[R+F*Pb3!!FSfbjh,GXKAk&XJlcjXRb0Kp93PRp+LG-BP'ci&dS
-b3Z*2hp$BR+4PXlp0XP'XCYRjq@QcaKB%Jf+#H6#UjKJGF#TjP2mhl9E4GFXIKKS
-m-Z%4SM-[@$aSNajJ!$#0-`+!'[GMSiZG@q@+Gh@HJEc-$Q3JHqYlBIB!TM0R*Q5
-MId#9l+$F&Z`Gk%$*SRf`U#qI(S,3LdGF6@#VNk0`FS)"m&kh`X8YV09,VJc1B-T
-'#X@EBh-*E2%(b$!,(5Uca@aULFNm'*6r2"Fm0(UaVT6r2"Mqif$J[VFi(mDYi5"
-DKXFh`p3e9h4m*VhiSF3*E2!m!8-T'91+FZ)-&X0TGTc4&`$M"m8eq'a82PI4Ti6
-(%4H)0LN6D&lL*PH!'f)K9mD#RZV3U)F*9Ab&Kir0)#1#LTL`G"-fNNhZe9m-F",
-IK)YPb(JH+Yj0A*d*J!4MKdXh-I0*[B+NEH02EXl1qDpm1"q#P8N'HVFKH'r&$mb
-VT@hL"qAMSj5$2*4fQfDHCq"aJG&(RdiNLMm@3dJQ%@YM&dKbpPV@rFm1Z2["m8B
-%YLR69K!j9J4e6FcQq"BM0aim'1,L9bB96m$2mdj8#DH&jph'ReS&6,JPFI4LL-j
-fX@[QFrc`J0"*r[0E)Kjkb!-rN!!U,Nkb(G10U&`r)3LJ1+#+83ALI4$BNG9(5T5
-AX`EkfDPm*LAC%#PM1%(`U16P#rL2jjPBU*!!d94rprq!3(!Gf@3Sc2R9j"KmMV)
-42hG1(-a%4TSqKF8r!!!aL8&%3e)$!&JL$e80CNB4%#(MlQ(rEEq@U[6QllUqZCl
-QmEQZUhUUYRT"md4f8MF'l-S#[@iQXl2)RmI@mT!!MZZEZB83`KAYjjFGF-U-L%k
-21"F1%fZ5m6cVC"kh%&l2`RU%F(S$)i6P@BI4J)%Qh56[I$-HkqrIhrrhG4dJ[lX
-Nlb8[2`!9GeiNmb!b)K)Km3!4)JCIH9dQBc(mb,jQ!D5B(-!Q)BKQX`H"NmbLmmf
-F!l-8X95#lmhlmli*)rMlcS+-ph$eYPU'2+,4)ke$(aPkZk&&6Y`1&bTLXGrpJK8
-2JVPf0GVmR"(XErGEI&m[NNB3i@YB-C!!1Ye!&S@"H'%JK6-)T!Ymk3NQFEkFfSU
-!X,5r4CELL15B1&a'hV%qjhLMIm!r!,$pBAmF2jI9VFea+)[+D&"DI'-`dFVL[`C
-m&ZB$X@3%V1"bQ($TC")QE-*dpm0X%&AMCGlX+IjV@i5,C@L98J-b1$eae%FYm6%
-Z2U)Dm8Fr-Z0!'LfqeU-ZCG%[*EF#)+i6Pd-J+Lp+e64#[qr-+FHA@acG+BBpJl-
-Ae9eAa!2DlcXcbJ1GqJ2DG-P4PqN4Pr&a-U,+NbTSRl6)RJdG[QCe`Y"X,E)C`A3
-c31333FGe#,(UI"PMrP'E`fmNLl@T*4Re2qaT9QZTq+1fTEZf!6PZ'EI"F+Z-8(m
-A!))`,d-3jk2P)4,)3mE'`@i[S-D-J"TCV+K!I`H@fV-p$%B-ImS'rk(&8f)%93)
-T8pE"TD@,'B8Nm&+%FAD%F&ERqF,bVGf638jG)2cq,(Gh[q8*Tl%F5V$9Q9GlM'4
-E1d$MjFSM&j9(SPJDf(Yr00MICB3F&X#kjfk(e*f2IU4U"Hhjqj0*CB&I,$LlbdJ
-+@*m-Y)B0P-2)3NjU-%1lVEfahAH&64B*4+dSXZZ,lNL$CF&Rj+6CGS+++5IYE5F
-+qH%F"a2Cb+6%0*@B*X9dFVN,3-*N!*IQX-2+S-NB$2E2lj1UZfAN+`J5AFc)m)V
-6dk(8k9M-Pc5SX!%YRN!UU`F-kF2'aYfXQQUm1@RGHD+`j&fqdf)X%E$'m*Dfd`,
-ST1kL[+`"8V,ba6pV890,,mAUr&QA"2RTAYDp81[@QVTC@%MGD0iiLLKXL'lQa5C
-5cQXb$!-+1,TjSCQ9+!I&"2Hcq0*"`p+ML`Zjb[3#%`A%'m685Y1kEE"q9SQ6%8c
-0a(4#6#HPAPMVAP3+UbU(B[SXUdmQ`edNH2()`iVJTEa1KH4M!IRXSk(GAmc'SHl
-Pm$`A`qX@G4Y9)ZT64d1m`5b5([6!Tq)"YrRl08L%N!$!YXhc9TV1EEGJdkdXAKK
-HYj(2Q4i[AiD!mCYc14N@S1#8*QAE#GkBIpiR#[-KeCr*5F160&*Y(5aZ056J3Ll
-i59bm$jANiTiddD9CGBCjLP35"2F-$!GJ%U#9c3G33@qDL9B"PMbkd1pbP6)SmVd
-R%J9Hp5FUCR5'bLYFc%UKmSFa8DJH[5SA%j9fMbkrd3+Maq@QVVN#8KXX"'pJ+S*
-Lf+3)Z4,9Em84U(iKVf*a)Ip,UlimVH+8e[M+6UAULqN3YCiBB*MR&9B8+!U)NU(
-RfJaYGqC1Rjq6TP#p1qF#iarYEUIJKjQKHaNN(*6!TmTB3JT)iqlLlr"SIL6Da!&
-Bq,TABqE*Z63AhaENi[+ImpJ[4Gjlf*1j&-92aD8JIPcUYDXSQ'Ff6SC)V8"FXDp
-KdrD-9(Z2I99p@RQemYKAP5Z89mDaVllU9Pk&D'Z21ZkN1RL,[R!$!UPrN6'[S3e
-9`k5m'!UcFf%,JmMQC1QiVE&MZV5JlEj[6!(SXQhY,0c,[4ZV'RXh9ZR[3[9[T5Q
-E$b!dQ2)VmiX3iI"'&LiVF`+-F`3H$l"DpBbS49GCD0TNJ-J5Lc1&UYlPE4HNqYV
-"AUpl4AQG2pMVVfj5ARZ2H3d)G[1#mM*%l-DMc&LN9pi8L6j(`98BP@CALl622!X
-#SKa13LKRFMR)MR#5MJLI!EB$6%`3qS'2$f'5C9BjC9YLN!$H%jEYd'TiL3RS[4(
-88hL$lK+8cR)9A-Dlk!$h!91KBaK6IH16i8Nlb2@lX[98`pFI&aY)1%ZX!1%dBG*
-fBATBV"9&dCec-0PPaMbkdBVXZj,$IaXU%HE+))3'I#@Y#L%a-p,I!@!`bKh+X+K
-)U0#d(6rQVqp"4@K[)6drpEGKUa,mf5PaAF0*0ZIC3F+lY$QkRJ2lTFf4$c'TqX-
-"*,9J$T%cIcMJXp1a9MUfe@Kh5lc`SC29!&#Y0FlhML2!YLr)5&DS1*&Q%Th-DSj
-hL"3&*i!FilmpF&ZBfRr&)9laUMJ!FbSYeXM!f,4@NTQ0NmRGKI(je,1#'6ULT"j
-HCXDkm[rH4l'aSZMZp5)%-F`Iih1U4A+ZXR)K02G5V&SGa`H62p`1c9A'eUQ,HP(
--&V3@0KKaH(&bEhdS[eh1fF#J9NIc`9JSAijE95HkB'@D'&lR)VBBbjXih1##YK#
-a*9BTdLVr&rm[mMri,hV-Id(P2`hr"I#IIP$@JK55*EM2X'b'mpA$q%233Sh#LL4
-B8"LdaSEm$iF83kljKd-(0H3GR0TP3ri[,$SCZ6(FUL6TkP)iI,ZFVZ$*$f-,frl
-K%"ki1)aMjL+TGLR,jE6"Nlq0,9K$PPJX)iZ6cpHhYBH``-PGSDjhLSe'@J"aD4F
-MUSY[`j*ZSqT-5TJ*h`E"RJ!d9fieYC!!DY'NFKY3VDQ@[iDPaHS@Y)XK0ANabQQ
-#f,TBA88!,%b)!YVlaS$SKR)lQpdM0RBHm6LTFkfNcZ@LcZ@McR@C1TH8&d$Z'X(
-BraY[%lVYrr@I0mj6q&eA3kR4rpm[PA3c+iqmD9V`U(JNd9fmiT&(12Aq`Yf'f#@
-8YE6YUDfU*&H3!-RP-)aNp!hd@%kXKVQc%f(MBTQJ!M'TF1*UXh`$mCK8*hJ5BF@
-2593@2T-@m(!5eV5hb)rCJ50k,b3CJV##E(##NQq'qF9541*B2Ma*KdI9U#-ZAY'
-552((HpIlNRB#CZ*il58&ETj$qY3kQ2)P-K&'-*HkP2VC`f9rqEdP6ZT5"BlCqKF
-Zaf)bUL,aq)8m*L&hK#GclmVS)JT``i$(Uk6M!6jm&f%YN[Pib8c1PR1FS[jZASE
-!lTNq$[XUMf$+Yi+!d(EHCcEMM%4!'Bbpcf3[bqQJ2lc&S2%+&)VGL"2XX3`ZR#!
-q-9[K*VY5H&+FP'1h6R`mJ-2ri*24DML`r!(Nc'$b"T*Q"i&+mR'UM1i&UGXa'Ac
-q2S!CQh(['B9&q#FQiK0M%UkG'`(q2ac(%9`8J$chE#-QGbS5P[Daf#0FS'hRLL+
-Na-Xi`-+4Im#Ipl2f9"lK&61dj,6#cM$EJMqEBB%i,&IP-b%PY%i0Kk*,Ld*3brH
-Z*iI"p96JSe6JemKii1K((8c+[G6GC+591Km!#!!0lUbpq)mDPd!HI9PlElkifVB
-%JYifJi-C!V`BII9ca+$H0qjp&q(iX*h"13"jB@-'(l4&"M*b1'5#$[&QlBjmFF4
-bX%1UKKa50I33@D*[4,kB[T(Lb*!!3qU'(&*hc#&Vp)h)'qNE+Bi11D4fb#'e3`j
-4Kqf$T"8[mR#pd[J3&SPRCY(#bHEGDhIF"ibC)F1%fmYl#%AF8Ia%931'Tm&!V%0
-0Tr)jhA4BC$BKXSQpkch@QD@#h0+qpElchY0,XHTK1hiUqr1,PY3B'c"#k[GJ1L9
-`)Vd*dbKRGdrmfBFrU`%,lZ2d&c14XAeJh`jaQ!5`C3lUDKq-DMY-H4pZY[qBNf4
-`Vd5i@`rfB4R#jY8'ZQYXaHihHmme-4aS8j1T@kc!I2Nc%R$I#MA(#U5A3j8pc+c
-eMB0FP6%*kjhLcYjh(TrYlK5jJjCJ-bXfi1KT@EPIfISe"(p'FGjfc[FD,VkLN9r
-hkYf"$iFVAe6[%030`)#Y4((Vh8#"'k+T!D8c*)H$qjC3G"Te!J6AAfhQ6S!LEVe
-+#G20$5-2"MXFZViP(3B5UALZ!J#[NjGPBDV[[(2+j9GlFERA*d1&d22hbG5[$hE
-RL3RZcKN*d1!QP-*r*cJ1(3"&q0R[JV3#YVAMa8PINJ#XNfqG4TVf0"*%AFCmBpI
-#0rJP1YSB&Te!%66KaS[#1Z&Scb!j$#"X'ppHM,ckT6Xi-MZFPDpZ'Kl1bmBPC#3
-)HRIj9mBCjRHGcmj[Xmae`mch!'`i8CKbRFI0JF8+'4X&E+)f&`,2hqH0c@@cFX2
-!V,BB(!0%dS$,,NcS,rhZV24Y08)Sm(Ta5G$A!AC[bQcF[3Q%ZS3*03(ij3`Dm`1
-iHA&dSeT4#&b*(2k55%JJ53Iha%+!2Y6a"bMQ-)-IZ-`0l%"bJS'+b@,+rZk'VJ@
-E8X!eh2hJ%-8AU+&(@Q)[5ZRS@SDY6XYBGP"NeGYe1*D9pIIbe@9&mUele5@M`E(
-JC6Nc9Pe&j08X$YTJa0@eq&2$!CCarT%5b3Tp`$Yqj,!dBD)Z%K$%$B-ZCc,3TjZ
-fEX4PI10L-bq"HKq!k+BmXb!ZKJF'(bYIHUQkdQdD2rcMIA"AKXPaN!#$m#q*cZF
-539bX(+!!`kUY1HNTm!*f4AIpUG[dEZGP4JJ%J4GEKCYN9@VN!8aaLSA$j'&VNdK
-pSYTRUrG-"Tk4N`5L,Vr14JLXC+ak,jXfUPNZ3NR$"F$!DKqV,Q0L-KA*D`#%Y#f
-Gk2`$LM2Eq2I1aXl(mQ$Yaq&##D2ff!PQL[Ji*%bjimCc[$NN"-H93&U%03iL)#0
-%1(a%4Ya%2#i5kEK5[*%)bJf%RqFmaF8IikHS1%NIZiUAmdI9c89HA39@m+G59YH
-TMbFq41R$51+$4KqQ%Kr#p+%Lm5&#(h*M!68$NfkT,P'0XB!lbL*AQc'0d$59B`E
-XGf)CUZf[,R0dQc!5Aa&5['8&"iMmidCJ5bH-c[AVqe)UbR3(&hl"G1I*P#d8lXj
-rf$%CC+D[V@05SQN"9($E5B#Nm9-06mfbQXe*Al-4jr5fNjR$(6pQ9jVY4pk!'Zd
-L0GTm@HV-"YaV`V`4MebhL6BNC5e%dFV+dC1NEIm0ZR+j#0'&8#(X-KEfP-aVEZX
-,L690E!-NYR%5fe3D1pe,BZXMXGdPX4@6d"`NY,XN0*9%eUXk%X)kP4$63%*!+a1
-Lb5D%8S"3[)T3HK*#-40##3QK1+QE2@U$!hZQ%1K[hh!,MRhGRPD$LXLlFFYI(Rm
-TeR[mQkCXHZ0)2BTKhQRaGrNQ8VIB'ACD(2-hq#6P@Q1M`m,G(JedY#Y5G'@eP+&
-c8YiAZ"-*#!fUJGR&X+0MaDhE,e+J%kNZZ6fK3#k!+,j5ihU!)k`!r63QFX+P'`i
-jF&YMPI0m*`23f1*BGFhTFlCcPTEU@UFPDSR9aQ+iUA0D3'lb1VRK,DP@8KRaJhA
-rSF!dZ4#63aJV03S1l(##Vf-RH1pfCTF8a4G'Gf2KMT&``b6@'I8b(1@4@L#(GA*
-Di!UpG#Tc9B(J4Scc$1iN(NJ*4N4f+T!!AF94$`$#NMI&Dq83km%Zm[*qr5+Hq(I
-`QBV1rZZcX5T8(m33S#SAXCd"VCFYVJF%!!Q!m,F%"kDP9N`LapcPr%K*H)DrcH*
-)ZA6i&F`!#3X3dq5mf$"J+rjS0AT204@ZUY'LK`KQ'`6-1)K#8b-d-5NPk-bd-6c
-f*FPaE5N&(4ITGC%H,-9'&0M@J$*@dq%Tr)c*6,%&,%c4*0,$'pILdYY10Aaqa28
-!#N"UZk"5lR*ATKqVac8@91F+'lIFeaRQJSRdBhB@#541k!)-(R#fAiamdXdZ+(+
-EiI*R)QYmdIi,MPYSN!$NA08qr6-4q#2"KJpSl[-3`,&&1&Fp221fZ2KMI6"0AXa
-UB!40)kl*98E5-i%()-$(9VVB4ApKjQfS["'BG6%q&ZMME6`b'QR"KfEk-)[L'H@
-%QSp0)m2,UfhF(@)MGrE,KkK"cd0p$rLP`BGPC1QTKPI2mZ9M)fcU[(R2')l0b*j
-6$BXfmFTl6IBBri3(N!"U`NrbefGP6MEM*bX4r2(a2q#Ej!ri"4j#"p-rfk822f&
-jeJqMpddN0TK`mBppkmlqb"U3!'efp"Ya*iPXVkDE#EVCPq'EjZq,"q,dm8#"EdS
-ISBp,*A)92VE4!mAd!+[r%5,lfhP+E'ij2H#M"rD)KC%@`5,JK9H`[(46S*XDjD%
-2&@HM%IG0d8L+EXl5$H$qD*M%@LUBPXEf"6XCQbNJJMiB#&,+6Lbbq8h2!"L+eF`
-'ShMf'I(LI0Xj*N!'J22BJEB,Z,'IDYLrA5&'-V,2X$-FDpK"*Yl2-&&krmFA`"C
-rLm5lR)r$RcBFHBdG$4%ZV-AL(PVXKZN[`i@him,1`RbdRF%&"Si!$YKj%T@HP!!
-Q"0#!KmXT'E5(MLileA#iP-&Hp1)Z8Kh&A(8dR[#bdVSpbr![LS`GPrBCVL`l"p9
-N,5$%eq#!Y--G9e5NU(SV0kSbl1Jd+q!%mAj6aj%Q$L#8LKeekC)e3bip3)D$0,e
-RjCA)9BdA'+DdJ(**&&TLSA#"hPb%aFdjqEf"f$)ki,Fq$6FU8Ji!'@,,2,h+TLC
-))GJ"iU`idX4*b0KU*eFTrZ-QUP6m5U5NrR!pYXS2aRN5fi0(kT4(UX4(L&Y-6%8
-eQ,L8A,GIA"a6AM6L(dAA5L%j--TGkqQe)p5eP+kHJP!AZ(XqIAhN!@jZ$hEeTkr
-3TeR4dCqq#IEb@D%fRRjYj!%69&4+pB5*R2j@E9CB&DUF[mNRb1a18QK*8N3`9f`
-ra%SSc6NV+jVAM1pZ*MGr*,SQLSaPlE2$6$)EZhbMSr(RZKVDTk-hfJZ",IFjR))
-#L)1B"Cl[j#$[ZbJ)fHRi3))FD0I5'M1BLT[d"$GBif3$@+F+Yp&JQCh,c'r[,M*
-@i0MAfjRB8a#4NChXY1kcLQCRa#5ab`T5e16SB4%0dF*T$Bj-SiL5[mlf(pbM$B6
-6AY)'S)T6IrmPU6hbKM&IC$6LNRrr"Ji*$kBhVGE-S)0)R"*!%mpS5&`Tl%0XQ"P
-f0+aMe6AV2qNE4VHVSS6,ib"I*MXbrI3-2e53!,l#c2b2d"K"4[!$B!`rkf43jA5
-MaPeFFUSc@C!!rRDIGA,qf%Y9Ff*dJNQJeAU-Jd#iBSb6r*aQGIBLi@3[q0fYMpM
-1)$R8Eq%%r@K`lep4`6f&iUi&!pTC#1bqcd"%0YjiHX(15F['dp-THUJ@$cfPcL)
-%$"lq%K@qfAMkGUQamA!p&cRI,TK'3$PD2RGVleq"&!iqRZ($CYN0U8CC3TqQ*m!
-mhN*6KaTDS[&P),5RI$*f#C0Dck`4f+d,PF'kZUL&@hpjNP%&F&E[CN1F*2F'GUF
-eB(RGiZb&5fFGQ34-VQ!b5Bkfdf+6!rLSK3qJTMAfY`"*rUim9NA&9BF+Tf*I0lJ
-KL%MR9k8aEJ6MjpL4(f`Ha1p%8@H+!1GNB'`bLiic*R186UpK&apQ#ePB)!#9F$K
-VGNF1jHrqC#!`hMhq%a3jNh[6J550F0dLGl*+[9N33B#YB*-RrZ-bS26DJZLfbB+
-H"$j"Pr`D'aHcD+*KKmcTl0UTKYhA+@dZI5ScZ@#qHiajlYKHXr%FR)@Br,5#l!#
-5lVr!&6ebNVB2D"YG2UFDKVhAdYLa`!3UepXLF`MDDhY2UVSc9G,a"S-F#0PAmPC
-m"G9-('NqhmR(+KG1$9jiYT`B0YeCB!qEkaJ+%`@CZib#a)-C3a3QTqC[S5Mhd'H
-R`3j0+%jUF-cXFRLT4,-cQBA+EfD9RqiD"&$5UaF[03FSXdS'[VFSbABdhVR($L!
-h,P!M,B,kB'6B1#I8#[RX[)"JiH`8BX8eLJEa2LFj-GP*),X3XZbk'&@8D5'RLk8
-K6Xe!6(DI1qTB9#&6L&2eYR%cBD84a4id*fAPH*rGF%ieE0QTN!$ealR$(,Q!JN!
-L)C0AR93mCPYhikhE3Shr3KhRMcpX8VA&(rkQ'jZX8JUpP3V06!JmP4"11m50Pii
-Qm8KMLda0bqSG3`+81N@0&'EZ,6)c2*TYR`PL-QDfI`pK-P$'X*j'B!FZM`19EHD
-%#!0N`m*a0Y,@cN'Vl#RN6BE`Sh"m%kR9hb'*AqA(4irim#JqP1#K)!49PjfR#eV
-d&!JjPCD5bM$C@F[I6Jh8i@6'lP89RrUD&p(-ARU0qrjHcb9&F)qV$RB'1iHZLZ*
-1RC'P8R8jcrHHArQT'FGPrPfB!a[$*lIB"$CBI)A&EZ@J1jkF1-L6-NGPK#TZ8Dd
-cJ'A9Z*)!ZJmM330ZZ"r@qhYp"4LK5@b(h4eGY0""e)"-G&V&658ka$QTAM&qEXL
-BJ6,*ATCN@L[)i(-'U3q3!2e@N!$p9S1ERm'9[YJmmKF`qRSM$iD6JDe0DT)#b(V
-mfD5i$9QK3"Uap4j8p6eXVBFF#$4h&PY3mI%I85ME82MXUZE%`Hqc!U2ZT66R*mA
-9)a3A'&FIb-q-EV$+`!2Pj,3`&YZ%2r9kdKrXacqL#8XMKi6SH[DVTZ))1jU$b`4
-!LjVBH`![Ym0&G8qX(!kkZf*Pl+BE+m(,Pf-eB)H5#L-Q)e@'h@&T[$8lJ10IaTr
-pq,1,Kcci*CFZ'A,T4Eid+VLG5-[,cHK1eV(BHaXdhi3r#$-kX!'I-9NpFmH[HD`
-E0)pp11#i)jSZJ$eGpYePF&D5-+8Dcc$r0'+j*`1!1a+VB6FUS"0[38(`C'`EPJS
-R@PS+f"1J@pRHF@jXUc*6@pi,d$0V([a"Z)LA`CLfdm@mbX9HpPJ2YU%C!C`Zie#
-&Qilb*5#qA#'Z0d',Xi!A"`2hf2Z6bdN*P4-6$+$bpfIed%%bHed(0E0F+#PeJ-c
-24-1'-Y%J%bV#Q9!i+Vr@,`4Qf"bXfTcY0k+*AjP[2cE8#M9N*6*M*&53!!%9C!J
-9&+X#3H%`UK,0HfSF*`[f$EHQjES2KbLLpET,PI'%E-f`m`U(1HZ*9+qKlV+T5(5
-AGP+1lF2[#UG#2&!['#88dr['P0*G9KbN1bbMlL#$hi"5b5TGSP'9`3qTd8h,C8N
-Xd'S'hYQm621+Y%V&C34"LDlf8)ce3ZA&9K6bFDJh*3(D)aUb%Ra6)'KZP%#j9p3
-q1[S6#(5eHRFQ#0Ak#IkX9[fkQJbH8P4q&lS#50PdUHkD%Yafc#XfmGAL3$@K9S2
--mRrLS5lKk)*S@Rl2"YRbPfGM,F,YN!!,5P'p2m($Um&kYFiF"a&VdBNB3Q!`8%K
-FA$IJ`!kQ0irA[e#D!qb$ijcjL!hT@`d0&[CY'&KSK803U(&JfMi+f!D0"'S2YF6
-@Ff+J`6,B@$pfb#ppQVrIpc1`bA$,@FR&&@R)Hd,ZD%2HpaSRH@"m38T0(D#2B+e
-L"jlRa1d"Q%'+Ym*T+r(j5!Z"!VDX5@SE+F3cdD`J1NX`m6Er04!E+IHGdCMYiQ6
-cP5"5c@&Zr-j06I8MR3bTlL-(5e4*Z&KZX6aUBkJA6&mHLd,r-4*Vmi9IDB9EKNe
-P0R8CR!"qJNVYj!D(F0FV9lFjThUR9VB5UIPj'UN453mQ0Z&A!R6!0S@FR-J`40m
-'0G!'Gre5G49Y2i$YahPcD$l8FLD+6Xm`K-erh&IJTJ)H1cjYiNpRSX6%rMDf4Nh
-4p#&-C55PU)@0#D8`Si2H8!108*aC8JXf8JZf8`frke2F@GI!X4d+NN$Y#k*MF$T
-4CYA6LRVBQ+BFa%9r`4H9Vj1#f#M8!`X&bX(')Er-JSR-CLfr1Bi+l&)8K+'EFEr
-PK45&c2b1$bU"Z[K!(D@NKHM@HkJc$fAmbM!XKe8(D2KSkKbbNP1LDiBfREGD5A@
-BT$T5#YMh@B"p2J,l2LG#jjqk'F)%1@VJG+CRJ-,M!B,lAXN%9@G"8q!qhV!1q$N
-9TY)+pUrGdF(J(N,A(3F(pb)qGT)YLYMD2H%NJG652JM1m9!a[*'2-3!3!hp)EMd
-"GYPP#(G(+kN92m(l&d9bAfjL9AAeAIQTiT+A8J"[1a0+$(,K*%J)V$iE`#55R0r
---+(-F&1!PMr,`VUmXV$S6lk-'Gardl"`$!YIqE-Yr%UYXP"a0b8B1Jh!b"`F`0!
-%J''eTJ-BJ-+8TPidq-JSUC-f,N))fmi1QZ-[bA"X$`M$jBbI"pDi,$PNcJ6l1p3
-a",c(EdpN![dGSpTcABjZ"+mp5)EH9a+MdFEMXmfjJ+1,Aqrp+rh9XSlT6ic!i8j
-feml10ajIN!$"kpc4'ip2bk#P`!S6L3!dN!#BB)8*05'$0eQGdZ",Tk$Jba9&KD&
-Le$JTqh*ec2m%KK(,X"UQ3fZ9)dZ8!qZ8!qY`i!le%"4@15S9eipLpSJZ3USbqVV
-SZVTlq@i,91YfX)!@5TpS8(eJ'1EiSH!HbdSC[B-fZm(S!&U2"C3Q3cK8"$h+4T2
-qISq-VZ80BN[8S%cC8K@fY*IG4aX(&Tl$*!QbXI1BM5NU2+S3A+MPm0#Y4AE4eS+
-d04Xe*J)$6-+V"'Qa3E4Qfr9#rU,-"IHq-d4mSIk1R&EHlHMDq`l%&cTm2`&93(b
-F8ZIAHpr4Ac9!I)A3&BdK$3**)-$))B**)-#)VFp[a'q'`6l[`,CFJimb,+C8DBG
-5[(&4LDN+mKK-S5UmU*@U%U@UV"jDb"A"k'NCmpraX@%Rd3IXkKKAGJl9fh!('jR
-"4Z+0Gl#445%+36l&S#CBB2AIBVFIA[6SrliS-rkq+G@DCSbR&m*N1+GR`ijZ)pl
-B[E#AIq!B8-*!h-dNTemB,PF[mBG%K8,TjM+N3X+a-),UV%aXp6JhfD@YSXMN1k)
-ia&EeaEaKYee!miT,hD2Uih#5D(-(0PM!)'J`'fl!ZahTY6LRbY3+(L!X'fF`EXk
-#X#Ik)cL8B4,%*)K*!"-0Nc!Q!8`qrK'lN!#K)38Q'aNSa&!YiP,P3d-dFPLh+LQ
-U&*S,D'"UY*apE(lC,Fm%9$2FX)a9'2VTPXqjSTXq!GSc0[&J8,jiJ3%r'#bfRA6
-(0PJ'KfkbTX&*D$c3-0(!J*'4clMFj[GY9q!DB$,B93AQX@$Nehq(Q@@R#`PUIka
-5KcrJARGC*"N+IR@4(8AP$S)L'B!mlH*K[9U9T$'j"lrDbB0XZ2FFX4PK2&c[6Me
-L!fN#qGV+MpcM!IT5(4""B(S&(%'EpB4Kp@Bqc'GR&3M63!L(&$8!9Jah9Cjq1cd
-1-939(-GIP4I!f,hLMX`a@&rV(5p+rI`MGaB$mL%FmBlh)5(+0h!@a'XM+&iBh60
-j`i&Nl39ZL)%K[h$BqP%MPGDiSSi,Dk9SL$9a44ST,P!-qAF($@[@RQViSed-hXd
-&H&LS`qG3C4Hc#6Xl#dYJlj1qak%QNlk[NG+XFMi"JJmShBJ2@(jXF9M!TP@C$1d
-`+&2j$+FE)HM*H3a#pjj`rmN'aQf(,E49&iIJECf&r,0i@+B3rZ'ipAk''6cLjMY
-)H%iiF%'$2d'K)@fK$9C&0!9JTm`R9Q,MBmim$m'&iahkdEaCMpD2(pUfRDS`!GB
-Q*@$Ij1Dq"fP0&LYek"TG1!k'L"PXGM0"UJ#"X%5&!#4AVa*!XUq(#5fp'U2+0Z2
-P@['5SEP`@N2)`8'Z'&4+2aiheTYa9$!$pj4+,Ql$c&M8RNQqD+Yb0*,&eH2+C5m
-UPp9I)V&4R90H[MC*fdQm4%1%DP0j1B01"8&mVbpc03&d9Pab&lZjUfeNpbm6Ml9
-5fMR%!N*hJ@Ja1'#Ge(l!5HN`!Bi*9e@4)%k[6++)I(d2dJUPVqp")N9md#+QK9c
-*XF4#VTD4Z1@+a(RlV6F+9j9YBaLeMBGF$`B,'QNT"Sh$D",+$'&+E5EBac@6IcS
-[V6-!F6MBK3Jq`qa,h`1pFB5jD!L6im@#Q66"62E#2"jRGH*R0FP+ECAbDUAEqAI
-H`VLah*IkcB0A9N50ZD[M(b'"cUN&+CmdqSePc2BLS3Y@UqG*5M1(MIZCINipmb"
-#25p5iVK5*1RC&HE604M3%3bSE`D"5+ha(2rrCAB0qI52P5%I2r8E9bHP2J$NThI
-jGZCY(&BP"MhNK@q0SpVD6)jB3E#9Qd[k-%5KNI3*S2P&YGG)#PA$(D5TFqSb*r1
-Nm4efcI"lTq"LNB)D!3Z(6fK5)aS36D*aLlZ9*j`X)rG,T&[BS3&LZGl(U6'Zk'N
-NaX"i)j'['HIAIjj&Te3hKl4EN!!,6lJA'*pa2G!6Am)BLZ5cpb)IiXm0Yh`f(rR
-cQAFMDhq*B,F*`9,+Zj6%#dF%h"64i%heB1rp5%mra"embpfq"`F4HaQ,R8N4YRZ
-Xi2HFDJKIiNEG4`Rq%fVBrXRIH62M4ZTJ`Spd',dNr,8NmK-NF!c!DAf*"&iPZZ#
-A9bM#RMA1kd-eHVFE[Im%J8I@N!$!8@aIrPT#i(cVd`Aqj6!*[!DJHBdlrhGHEqr
-Raq%S%$jk3h!4Ch2XRB&l!B$3AMJ4p,#SURE5i+*Ph1"D-3`T$h%Bl-bM8eh496k
-DUL4-K*G([S%+`DbX"MNSP(Pllaf1[%FQJeX3Va3fNiqX-NbHb%0`YDB8%RhqB1C
-CCbq6AEK%V*T-JQ49BRR,j-ILaPhmFaYZ),,0ECa),NLB&5lfSeSf+pmS%Qmh)bh
-S@Q$BdJ29r`1RT'mr%-d+!92Zk"0'#**Q6*%49JN4r+Mqi%C)#NR!BXXpF@Fr%61
-(BA)cN!#0Rr0S43qTf9-0S9N3dK6B!!FRcelY0(S&JH''4$cijqBRBA6pkcr2L5T
-Z"-m'TeqS,qe#c!$KS(LKPjhN84eaSE9dS9F`Q'`PGeGF#"@0I!-AFKac)4XkG$m
-PY82'6GQ$SB4lqE+C&lJXJkQ5"QNKGcK+8)$B2k4#j35DB!##@9[&c0VJ!+1YL5'
-fQ)%+V4C$fIT#a"VY%N25mJqkS"8LV50'LZ((1RG11(&NqYhA[Qp6K`G$HMa`$a[
-SaJ!$&0!cNfDBK`8V9DZ`8YF6E&608$EU5N40B@MLESr*E*fMJ`a"EHbBhDp2Tr-
-mU#Xa68eJQZB8TUPNN!"03NFE[#Na"!2@S6",63PQUICJc")A4K%+3mX`Di4Z`-2
-FpJJPMXmEQ-982Q[dHCd)a@0e8*'E!([!I0)kfmj8pk@chrSA!26G6-SmB6@&jTF
-TqTP33d@Fr'V"-!6bTK8#0!'Z#AM&3NFmJYG0@8eKSkS'f5JdrNc5S!T6a1bF*KD
-YqL!X@VAc2,X3JP'VpM46Jm8`h'qKQL)63VRVV"LkRT2B,pj'NKN`X4'$KPSfFX*
-K$80QYhZXUACNJ4p#5MMP5H%ii5)hkRUJ%!)8KGe*6K8SR&J9ETZj5kB9030*B1'
-MUeN0"4GS-0ZNTjL+%STphD`S5)r+j$TP8BV3SK5KRiT3ib,d$ca4-DFTV##85eY
-6)Fp"mc(-S$94B'N-SGc2$'(VN!!K#cJFiUk0!@P29Pc&&Yp"0m@fP%$VG0Z&60i
-eKF'%8qb-l2kM$a`VVlTM!&UKNYrmaH,9F3Dm1jm*[2QkrX%h3Q!8$l9LmQ$4"3Y
-haS`3Eclaf"b8LRpbrXd,r!P$L8IIM1(6$`T5U(Tk+)iQ#a$G6kXBA)2DBc88@jE
-hD-q%hRbpi63QJ6G[T"fJ$DD-G4FrraXBC$H-TD2imkF*9XhNJ4liJ@pM10IB1Pc
-NaF*9%$PfjeN(4UIk0aLQeL)R+kD[A$Slmb`HZSJrPpfbr[-Bh*EF5#LjF!*TUBZ
-a$`'kh*MK!4Xr#fIjP9!C&j!!ZVU-"0Gbcjae(J1fR2Ik!B@M3F,k-Ai-$)ePE3U
-*($5)qp@eaaGLkq(%fM*ppRC4E)f2)ASD'YQ$VXk$@DR1a'0QiV%32`DR",S3KKK
-+(1VC5BY"B-`,lNF&8d(Eh%B2cl(,ED`9Mfq$1M03,4#A#%aM6Sjrj!'lE)lSkPB
--NkZV@lbD%8-*Bm%*8ZBK*LHXB"0$"I0,Gq)P%Y[1cb3@pG',X#!d4beEUErq06[
-hD@N,ME5&iD-@4SFX6,ZJ,%PEQ$TfS6`dC'(+Q@J54kmh$APYTKel)HeBqe((AKU
-bd$ji,!rG[Rbpm4Pq%D8ZU(mb-[L3!"KmK-PC!5PSq(c1&f&3h'`mPBr!bF(PGl4
-[k*LZhG!aUaR*p-&(H'"SX)E[%62-i%%cXBU0#%cba!+q+iUEKS*@i)6`iT@B-Qb
-a'$k9S2RBBcb!E'6VE`66!4E(9$VpiY9R00(&H8"a*K3!(8*ABRLm(Q5JK)B2`9$
-``mXL@8%X*VB,%N)$mGk8jJJD2i)CU[,qFGqI#MF@lJb+!SA+R#L$bS65#9jlH`J
-,bKINlBZ,SSXZ-ZZdlL4F6M'*P"1l*eieZl2%#-lb38RcEDmBaZf&MT+l"2ZjlNb
-I`SJ'V`dH*eHjA84BA@$h8X3F'fm2#Bb11[#%'%!8l")Ul1e(`(&kl4L'PHp(8di
-S,hD'jB-dXEAD&pcDR!L$eK&l6q#)bfYajfNV'J+9jH6#JqT(DcL`K@KZc169(!F
-Qc%4AlY)V*#q)BT+[iDMB#PDFH*L(*iDL001$9Q&fEK00B5V*"EDbB+Sp4&65#-M
-Q$rSHp,F6Z@Rhl8d2BYJ)LG(XGf+3!(LSDMm2!bmfp085JL(N,hRimiQ(RdarQ"Q
-8dN9bDFEP8edLf#biH1MhrjcqeH`c&G+Lr(-%!-%%59TjP9fQ)QF&qd#$H(-U06N
-U)%,mi`B8GP5GqZ+6bh*AMG$ETCPa)3CHkY%(A"UMm!D'Q6+&)I1"AT-(fF"`'e0
-'+0ei8jQ4"i864Fl[If5NlPUZ90Sk-RQiMQ[Z2Kj@qkl&eZ(-C`$lYTei0LqD+0'
-8rQN3QTSFPY,86N!d6kfBfQRDLUQ9TJDQV64eBQV30)1TNkBj6$-dc@+DSqNf6,-
-dAF4d'ddV-&fND4l6#TS1B*URk6LQ!c5G`R5FTLj-TfMDLkQ,TRfBpY*d"-jRhNb
-!QJ[*Ip8bJB'1C`HNL6pfr,(L6b[q'%CJ#(P1NKKpaEm5BR4q4Q(NVl04i"mVZ+#
-V'ef*9Pp+$'R%c85iZabBA+kE4j!!NdbT!YJ%-1Ak#aLr9T[q3LIVUbp0Ab'b[KC
-reM"Cjp$58icE0Yk3!$Z#iH'qq-eQhJ5r3[IZdKIrblGZrqVSaEjChP)e0rKV3rH
-1JZ5ZMBA)05"&!q)DD1T4krjiVFU%eMH(M`B5SGX1YX`G1rJb+2-J3[81T,L+R(R
-Kb[qaQ`b8)C)fVk2BqI1rL$-)2UKJDqQaVK'##USYI)RUkfJ5p`ic&p905c3-CR8
-AAkkDNm(0rh'fqRTXK#lr'Vp'',q!3q[&S@[("+[)`q$$D6e")%M")'QZ%`UPf'k
-FNFjHT3&eh@JF!aSYpV(cCkA1B,SX4$bQeMX(3hb3!#-)Lj89Q-X,81S-S@VBc%J
-K-&@4jG&06QmpkEdR9#`8SX+54bV%F$qqU11@mTR9j%Z$Rj(H5"Up$S4%I)P"CR,
-&D8qF,TK+)h)(4+%icR)a99mLjNT@lf9AJU%TiU[@-6&NFe`-'i*%E[2KqaRleSl
-#29DAaN#1K`0V4LU&RC8a4!fPXmjbi1(SjNFDZUE,'VTQf4fjaqK@I8B[$r#cV-1
-h1+UjMHFXR"TdQaLbEXS)kN@PE,1553B+kBl8+!9e8Pbd!1EVfH05q`)ZJiDXh+!
-Pb3!8K6Np4KFAJd&ZcqPTKU[NY-TGmp+efH)d"FY!)4aSB5!I-PPFlaG3@`%-"&`
-N1UDe$4fha30ZHQ!S)ipr"Q45'@*FbbQ*m[(%%5Ba#BkYAm,)3Hr+fFCf1!$lMH$
-KcZ*VEHIdkLS(aF&DhC1c1YJB+LEcVp293'L"2[`l(`k#CYF*'N0U-%-93IRe6*i
-$H!VfA+2XPP5*a*I*JDFa$`JH)Q,)F1EHBrGN'(q3!*4j$-8'Cj!!X#G$EP*X@#B
-'GkVJ-)f61qXf-kb6NBpKi(kB@SI[&#fD`+,N8BXBhZ9&Rk3YQX#LRL,cNBp!3NJ
-01ZT4'"[lEc&M%EYj93`BL3S(9P'BqHqLZS('%5,eEhiZIIJN-6LT,XMr(#V)%Pf
-3!0%E$"@3!#",&%''dJ8C[832(#2)k'XN5)"1d9NKb1K8iJKl3T!!R0"+kB*mYE2
-B2&D3!0&Q%Q4+"a'e$iB+8VZ4%'5*!X@)P&C03TMK9i8`cD1%DBFC0MRC"+B+cr(
-rC'SC!Rj650cf3$MQ6"irF4+8I3i'i"NG+UMr[25[[f*"9CDQ#FS13H%IkU*PcA`
-XPXB2XT6-iUYPD8ZEDDP'5kh+8[Y45d%1DHN(D8ZY[&3HSU8pbY,QJbbp68[GD8Y
-lD'N6,@e9PPU208JX&GZG5e[DLU9hD@(T#brmRh6*cG9T#dZaX"4`HS[i*dB5aKc
-@MEPD0fBfS5I6M6PD4XCF-Y5Ba3!P"B,VM'"LQ%F"l@e9$@%1J(4kYPZqh3kfp1[
-B!JG")I()d-&(VLibk2GN*d%YSm`D2hPG#C0D`Ha'2Fd!K(J!UV#j$*U-S(83h$a
-rQN'Br13T!VYDhBB)8M`XQ#!&(4SGCqfM)%DH*"DrN[ma,9N2H0I[1Mm@[mcKh,`
-5cTe(-rCEdlA,E[PHJb1#YZ'@cc8Dl1f'JJm8"AIAZba$1Nb4XrF(82!mC#)l+EM
-1jcDUmCPlFqeIZ-IZJmaXdT(Gdr[a8+GiD!l"Q1-#T4me-AJ+E@i0`TL`aq38de0
-a"!B$r%%243M3#G0,T+X`R&`&%`R2+(FY``8RBhZ#CGFrQHQIm$-P@2QR8LJ-6B&
-YUh3JJ3FC`mX3KFN!!TNjH5UN#%(+2bFa52NKJ#abc)-"Amr!FB8+fh+US6C$5qf
-mm*X$R!`4PkXGaI%0rlb6AUIdcrpF6Tml4&"1LbcdkC@d6c-iTRG)eAU(9'Z+3@J
-ZBKVZ6#3(Nq)IBJ*8)q&XlerrhcK%S1&6HG&h+18@0Z*L+$1'Bp,JK5$"eYCQ2-5
-$[3))(X1r+X%T1KbkIR4`3$CqX2LRYR2&2FrAmi!jdA2X[h,*h2+Q"F-L5j-rS(N
-aA"q4PK3Z5kP"B*crm50ZZ)+2ad$Q88X`*Q@abIrFbF&HXj88pacp'Pe4mMq(amh
-qBM%fNTHrcU%q!k%CC6'D*NQ[PVBeL&pDMcQ'KdP0LDi,D!!*-R)c-G&)"!f!#Dk
-BJ$Qh)ph%M4p,"KX$T`r$"3!!)aY"4%05!`"AiJp9$@C%!K!KiZj8lm&*6VcD+lQ
-B+m2S*cN[&i)F6DhM8UU!aT`R2DjJ+H1km46Z6ScmrKD3!&,(cC`",@2GVKShihB
-b@6HE54-E$','d&[V@Z0N(%2YDDcM@*YK(1V39!de"b@Lm2IrIZrhhAI!iCRdf@H
-IHAi!(@Bq*"%3,a!!%"!!%&%[PBQrD'V#(r'M9bL3!0*K&3jFPbcXNEc'ej5X-@8
-h[KC*$(V54"f)TX`aXq@6j5q9@AX"R,-M4Cr0RaJ4lDC09S35'aG(%NGk`!*"@Z"
-R&cTX(PMCZ'ZJ6!5Rl""PVqP["PBf,DD"fkE'cFL8cVKSklipKL*LVqiNKAhiY!,
-6TN-)KeT&apFM&#cU019qpKU3!!NJh`$#EMV4GLj5p-8N(QLrAAPqdUAV`SmaEJS
-9[C0Q0T[Ua(PdF"P0QMec$)&E&$Y#cfD12AIeR66@U82TT&FkH5+*5#NkpD#6B@"
-H@p$NrNB6HhUMl1PfpHRFGp)kAK'GT!cVlAI5)SPpEh-4k-,3HjJbJb[U2Ia-al,
-&fJr($!9GTq2R4#6aB*le6AaLiTm&k3-r81+LGP`#SV4a-`EfB1*46'cM%rIJChF
-NdEk$2ZJ5HPEl86G#`Gdj`K0C+RASA-QR*UC@XbZ6kRclqjZD'$V%&R4j'PZJQeE
-'&MM3b@PXJ@0k$l)&EH*9YU$Y84(dJIKPX(LXXH"N[h$&)hbaK"5XQh#UT@2k+$j
-Sf$fQ#qk('U`he'2E)dY2MA8!19j8H6jTU"Krc&eT-q*YDE6G-LLl,V622$28M!+
-0K"Cc![b*QE)R*YaMdY%i!q@c"EEeqeAXb-5Z2f!)X25h,qcIjeZ#,ALC'%'5&k8
-NCr6e4H[5SdR*U)X@,IT@5M6e%qGDL-j,f@PR$qCND"Rb5NY,56kE(&dNpRi"$r9
-HXIC+3@EG5HX`MVA(d')Fekk!#Ef%a&!!c1Qc$[2&GK`b'%)9Q'@RJ5qfC)jT)F-
-CiaPR+-iaSB6LL2f`f5f4K0MN"V[5P*J(l&m8kc)+IZ'mM5jFk8M["QZ[K"2PQ-P
-0JADJBQl1i#+L-$J#aKAmbT3Mr0K`4(4V)D#'%@+bd`&5NP0cXR9DHPBf2JqN*fH
-PpQRCfM%YpfcGQC5F%e&48bPmi'#@,LIp6$3e05Y9'BTQkj)[+Q15ULMSUi4jC@S
-E0F,jS&h4"5HI0cY)KE&K+ebeT"ch@"@UDP8Z-5a"CE"B@!M``)h6N84"YPBShF)
-GHAAm-J*!GRc%MDDj9i@&&",h5XpeI*hq*c8T,'Vc%!JA"`HH4,KmGk9`J%bH$RF
-'C5TP5,qK"9Yc,+dd8LM)3mH`$J2Y!2)N30B9L)R$1N5JP'IG"(A$J)Fr2bSG,'E
-3aV9D8qi[&LV$TU3M!TpEL@(L)h)@URRJq%b!TYah2X8%V`&UJa#SUJELSLPh6LN
-q$N5+jUaPLLJ1hAk(9k0QX-il*dbj-4-qEZ++L0,PMq"`NMUKmbcHm3'`f3Ef9)G
-0aeR8%Bqqe03dcdd2NkYiB(PJFAI,Le#FX1#2!aPq5@8"K3'#e-h38M1VR5,K9B2
-6HJ,)T-CEqFK5B[[Bff$l3Xlf&8!d5fc[keABAZTqVCN#PCG@NMX8cSJJQ(r8b+k
-54-KmLJQ&2553!'84ke03GPP)3*!!1r6Mhhh"h+@&iN)dSf,K3UiIecaFb$he#lQ
-ePkk3!$)N([U(KmfG9N[(ecR,e#dJS$P%ciRCk,`k2YVa2KYBM`mkeN&L!4-AmPL
-U`L68@3XT,S[,Ce-JGT,3p[@G68U+CQGS59NT@YD"C#h,V+@HcGC&r4CCc$U6C6l
-$CbNLQq46XSZ%YjYF-PmV[TE4KD8(TJZU3$Fe5YP*94dbSK%"8)F-B-QBN`-FKjU
-j-@3Z$fL6`B!%d*5-jH$X@Je`9U"Q,!R+Tj4"jZ!#BSYHZ,PTm%0$#`rjd1)"IYe
-@D@%8'jXcac+k0Y4ZE)l1Jk*T'!948flJZdka-h'aJcJfFh"qRaj$1,XHP8Y!6Z0
-D(0'dm5KJ*-&2'rdr!C!!#D*!FFZ-F0B2FS@#BCfXhhD(UfLGNrAE3UU+H2GVY33
-13DLeMYL*3!&J5M51M$S8G91'A1k8PPa-GV1*pe!ihqe@-k0YP$qe`jNCEIh9RVS
-AD*i55XC!L'Cba-[Ek-$#&j3$6D0*"CCA&'!*dXf$DDZYAI`53@a2iUD#6"9JFK&
-43@HSQ6VSfX%'AM$"&4X!5N4"Vh6!lU%9pklG*8*8ZQVC4p3Y8dK6T#A2IJ0BiRA
-R44Fj5aK[+YAllI'Q8L)eG1hFT+*Hm6Im&-$LKhci5PL`IA!["aZZGV"AUQeeZ1C
-@FI4m*q+L`X`h%@i*+38-@cC1M5BG2*XHV3NjRM6SU2m"ZEJm-8)#i14P9UAp*Qb
-9YX[2+Qf9Ae@D#q+i"Z!0"MiRY``XAlDDUVFA6F*,3(!4`[B1P,KNL`[+BP#)%#e
-3X0$B4bIlL,#2FICKB"pkQ2U-0C@BkLc)[LpHBdp094ZBS'S&V,3'c,@E$Jj`HBL
-,+)`#b[1arA1dN!!+"V(c$(bH)JCN*$4e(#35LC-m$*Jc&XL0jQDPrN6,bGB'8P1
-Lf6RTcUJ1L-+qHNCVCQP08PQTmMY)K6!mmi,3-q$jDIM3XimTpM&"(adkUK4rRdr
-%!99qp4))Qf&dTPBL*d65mAaAEPH50pq9G3(Efq98N!$2U#JS0NfQS(91"INkE48
-8dr$X9KJ3DVVaT12Eq-AET)Xhb5kfm)Y,-''3!&eFJTp+QH)EC4HMifFlk1,ma8,
-,%Z*QG6@%!-UcXY0mAri''+(#1N6C$R8Ce%rpk0#DHi`"0XXBB#1V,K1I+3`3ii9
-%jd%fb3j#(3FP"J%$h%!P9dFUc@&PSZcSMlA,"l252p$#N!$q0KQX6)[@jD3N8bd
-SQe[e92pB,LFl*eRXPFNDlmZFc4k!hkH*p$G))3'2p6PaNKKUp*Kl$-Ccac"`$-A
-(qe$3TU1qlZH%pPG,-+MKT`m&@MH+Xjf4T5-#@G`(%bU4Y,pll6GhS*!!m3d4i55
-MhP6Ae%5'6Bdl)8`HqU$3a*dlV'"+`k[4YEeM"Md@56bAQ6Q'LQ(hYKQA`850@f4
--Y*BbVa&-ppAC8ZBeJMNEBc,QA12-20k4+S1YdX@hYh*#e5JYTdU0`M[5*%+e'-c
-6JZ-cY!q%rQ[0GM&CDkk)(f,G%NB"XN#d6a`4hKYUYhYfDD,M%b"rpP&`F926j#e
--,2c,3de#QMSk(BH@(ME`KdA6"$XB+61K[APU6$A&mV80@@jd[@NrhR[&mk@CAh"
-mEILTi$1V(r6qSIf21[pbk`*Y8IH,KVR'pr82M6ihGA[%1['V4hjqjrFRrqc)IqV
-lEIqhMqdI(1MBGqL6#qqD,S@ZpR`R-ZEqj[MNZ@rPr5Mccmrr[e2rppNcmE1Adc1
-LCYh&R--I(-c0cNVklkNTb3I5IPchNa0rFI5r[Ih(VVZ[eMEIZrRpPMqjpG2Vrq@
-(rq2DdZR2crLI$rccY2rkJhrpm1rHqrrcrmqRrr[MIhcYkkqmYIJEEa3YHDGiBF'
-XPrpKiq[jhdhmKfhIfrbI0reQedHlrrka[pRaepXIV[cGUPm%PUeiBGh20[cYfRp
-EmmXp[hlmRdVrjIjIYAjZjlqAIIRTVkaI[[,4LUpZq5a@A[M&NTIQ0FbHdpJNb8&
-@'QU`!pPDaJ&H`,B*0qbGVChQ1D05B084'K9h`0!h11K)Y,rY(NX6j+Mf#9i-5PJ
-6#QZ5Q'p*e4m@KUNESA[%YLLqVQfhe!P[jq60"5#A'+XMh$5q'*A4U"M[1BbE,S6
-ZRKScHlM6"N)c8H!H'`&5Hj1M3k'lCXIYGcQJLe'(A`fkaa!L[C%2!mmdAcal["E
-'6kjFm`R4MSHd'j2hB'b5GaS2GVM(M26JN!$X`Ah1"bF#)'RiYHE&D5*ddbbDTTb
-!lD[cf3,+'0NYNI"+Q,TK2NalMML,+`f"51)2#$bYL%[KPSC@U,32`#1SK"`jX8G
-&qREU6L)q5X8f$`)**j%&*c'F$mCI5`X)H6ZkGXSQ1j!!98$44%1AH`c6qM$3KfN
-[BeSPZYYT`!Pb[+,QB$X0@Q`(8im(lKTKKZ5`T!i8hbAAMRNeC8*U#KR8*KhIb#Z
-XMEc#D[K8"Q`@%l"TU)`NPPq6J%e$*AlHN!!"Qm91B--lHMQ`34&9$I3j)N[IAGR
-3qZjA,(Ep994'QE,$H50,*edrfR4)2$-SlR!6C1I%B'3T3PGN+L-IaK3p"B8XXN&
-X%FmDE#m1S6#KQd(X$F3iMVFTNRKd1Rd3@i`Nf+&Tq%-+!Dqq6pR+,X$M8+0QUdD
-Mi*PH&$2c3-#)MY3eAeDYEZ2UfKC*V,r-e,802ar,UY8G-R@KieHHjZVLl2$3+BD
-Jc(k-,BKG9V!&f-dlNbh!LJm'+B`1GZ8QApPCbGTCY8V8&,!4c8#--M9k0RG[`'2
-Iq$iYr@)drB18!lPDENj+lYRNp)Zr*6Sr#G9ZaYRNXeT1LXBUEcp)1"$+DaMTrHp
-K5Hmb2dR[Q&qNph`!`%VVN!#4L[JmN!"142L9#b!K#iJ8lQlKT2Bqi@$NXce8kai
-c%iQfUJCTK'VckIG-Z3dYM25$FIqAYV*-A'G,qMeYT%`%!4D6b#j'GS13!1"N9kA
-XmYd+qIGdKicm#mJBC)mYqIIPlC5i3#'lFHJJ$kqBAV`)5f%2,53Mi424e#`Y+a@
-NQ1jXFNjD9,Ym`'b1TR+ULLLP$Vk1CPc+4RC1FSk3!-GZUmc35f2bh+e"K09cGep
-I2D1R3rEV+G--,4!-bZS@LEJrrLNMlR[V)qkj16!RlP&411khS%S)ER4G(ZiqM+(
-$80E3Tb0c$j2Dp%"4Tf[09J'8R3I2%%CQJZiJ38pUiL,Zd9RqGV%)+N%Gjb&$'$B
-2Fi1rQl3JpeK58c`iL38pK`V,ih")*Y,b)hCU,%MMU"1b5cTNPf3J!9)`8CYKe)D
-ZhE051-h$LrJf4p5,"c#&MXK$EAb$U9VahDMPdj(i6&5J[Gh(KpG1ZXccZJH`"Fm
-rSr[D@RUXFB0Qb364CA'DIqF@#dP8Llm86P5,CrSRUXAYISRUM[T%eIl)`2)9TLF
-MUMYMYU*k2*Q*d`CE8Geje'p4I8`4eCh6`SKUUDfSlY6NSLSA8@`NH2UL1XBKEcf
-bq[N39[RY6QQ9$jqQZ+i`94IAVP[qL5[%dF'&Y9QRebcADUh%kRCEGSIJ1T!!e)L
-,Vcc)bSr"QDGT#DNB5@FXcJUm(T'eFh&l&8G4K"31)4,DQJFMjY6cJk9VI&S2Gma
-iE)p'4&[m#,NSH5F%C1+MhBGja[XKN[+03(L-6!ar(PB-lrJTKS0qL@%&a,#%%Rm
-B@H$B@&XR$&FlB,BGDYDGebb`-!9&M8"[5C)2)Gi5)RJJ5%@a9PkBkb@$NIXYVl[
-LAG)R18ki1"6&(ZGG,+p,*Z!Ppeh1Dm`**"UE,5bCYmDE2Fhd41je6UD"l)ACpe9
-b5RQmFRI#)UM6BP%cP,X6$(U,4@XVEB(TZqI5Er4YXjVEQJRFkLGk,!ZE&afb@23
-,e#P)eUCREJPb#aQQ,"CXX9[Vb@aar1(5TZkfKAIElY*dZV*lSP2-FKR%C,2jrN-
-GG*(qM)cG',Mk3M%G`h54L2rBda!"4Q63*m`F$!biF0([d%[K[aS1V3[8hD"13X!
-QL!+E9mFCGIMTc$%NA3Va4a*$5b6"qN)U%kckA@#0eL%+*5-EQU5$2[8KUM1I8Tf
-KJZQP"!05e@48945#)1JkmFH"S,S0@(k+QrT3FL3CUrB`9[hcX+akhNp@0I[$UJf
-DVI*RhT%T[f*Jq3Z$L[*I'24Eq6h8hD"18T8rNaFX'"#4Cd&[RT3&AkUS+JZ%8e%
-m)e4&VTBc%3AcH4KI@K4b9`A[1,a5eP'@%F-EC"Q3!-Sbi)r$CS$,c`bilPF'e$P
-9aad4B2JAGKPDjR*hV4E+((0ZAeA`9UQ6T$6"PACUV(k9932H(KR`CNUSeX94(Ec
-cBi%9eJAhILcU*"h,hPc9X4E8I2K*(%eb@kmE$1qfjS3K"m+Bi"RPa#'Q65(TYai
-"LhZSJ'5K%$f)8h*9kRUID6iLaQXhhSZ@kSFdLc2T$fH4DBa&rM%XLlcQ*iX8q-8
-L1f5C`4bdXI2BH!%jFYhKXU+!C894l0cH')36ZNXAj3L,X+$BEp'1kpV'PbTJ$`B
-VMC+Jq"4(mhfiHBFNjJ!iR"FT+MIbC,%0j23UEqF"&imZ+8f!)#b8"UAYP6mb$J@
-E,b!ieF(Gli3--Z4-G3KN)a*C&T@hK3541EUC6VFGABe(lh-6TL'G4jN8Qhf+'5[
-a!fPDk05BFB&-19@BZT3ImFI84G#4TTb-jH#-CFTp(8'&mTY'lX!XC`BZj5FfZYa
-M'9l*M+!mQ3eR'j!!%"RNpM%!X*QbS$KrX2`LZ[Ab#CIjK)6SVRN"N8AN426BC8F
-j8Xp4mZJ)8CM9D%2M,UXdk'BZA&U%$#BbRS#V9b2hE[NK-T,"BBDj+CNL&Yb3!%`
-#THA($#fCYNBY-!QKbPp$C[0,m[3#BJAhI[T*-UhKcr!Ykc5qa5SH'5GcJ1f8K9S
-2+J8%MGD-dT*IFee@,AKBe[3iNi`5kdX-D@3#8Rk+ZqIej'LA"VU(TP2QF-GhqAZ
-CNPP%3QcJC1D8Fe+'CY1PU(`DZA$l"HmqN`iKCbY5[Tk"&`S*`m!%i$%HiFGqEqR
-$Q[fqUl5&rPrI%QKTG4Q*G&Z0ihV84iJddh2$akY,YeHIX230!VGbT9Xj@#6(#X6
-@XE!5a1qec*E-2ePBD5l8,ZR29$F#eM2!Kq-&!ID%,mDh9@`8#6JB,[G58EJBCPX
-Cc-$!YiFAceUG"JDqRA)$Jr,&e26(LRY)($Ll!!UlR#FTE'PP[C[9%!k`I+k&JJ(
-,0ZRYfL&6dLQ3!*N8&23p4TGb-0bVIhkm0[-k!'lK,h'BZ2"&EQ0+8`c"EMZC"X2
-CAc%eV28JL80-ElrIA(UGrPprI@e,Dh-)TX(QYU1qE5#)-lVfh0aimr)mQ2KdmB0
-p6!eV-)GpN!#+2pUlTU3HBAd6aI8#p3")CU(Gq+C,2jKN6lL`[+PC!V9dk%A2H`3
-*8+$CZ6aRXmbc@@ED,-rE,%rC,*q9,Gfe'kp(VmGRbTrPeFp+&0mXqE8C"Je+*$*
-I8L3TN6E5,da*GKL$cbRMeFVh3@!0@prN'jr13q1m-'#iUB6Gdk,FQ""Z2*K3*Y[
-D!M`48`#VKi-"*e0f[DL")HFj'C*AR*YCaIP`f)UcdXq+FkeI&@GCG9,KCre9N`T
-HP95JSJ`QGD-SXj9!@VTh`50NVLPcQ`"JR4U,PXN,9,,0YV,0IMAXCVIiZGP'[cC
-ESKMl)CQZ*aAZL0#VkHhBmVP!FDFBCd@`hPm*Red8[aVG@Bh%Nm"QSMaYB2QD"!L
-(aGb8di%IHhJ5JhIPa&jj4P8NKLPhBDqNMS82KP2(3UprkPKSm%FGXldb-K)9D8@
-b3NkD,PS`8'iB@2j,Ye58X6KSi@jK5hZp"CSMe'QZfKQIGUR`3YI&CNZ%9[R'UJX
-[6U,AiR%bdJ+e'&,K8Kq@`RG$YXH1l3c9FN!fc-)PdV5M8U8N8rF%8rHh`kVlQ*r
-U$[QPlNak'+Ujj3``SJS(34@,1lG!!DcbEG+KaEPkeAb(,M'dF#)Ja+FNhM5V5b5
-0@H'Y@XA598M`F*K2IMYcE,r!!TAYPT+*"5V#c"!`Gp[51+&@jidV&6)#5$Vq,55
-a&@b"BL5-$p!)"SViiY-49*&SqJ5ZGK#E@pDGA("Z6)F`Cq0+@CMc['*+X!aNrTa
-TqiHB-3'FS5pkZ6NFK6V2fCS6,+0N29[hMc61N`lEYCd([mMNY&FK20,2CT0(+JZ
-'TTSjjb!2E9l!"dc!-(BD3Fc[R%fh$@T##BqIVK+JJ#eSUSF[V2hlmCrd"iMe*aG
-`YC6+e*+[U#A`SBeDN!#%[lY09FY'@l8%Z!%3*@4KDLq8e-k[Ilc'p3JC"ikTejG
-`JiM%SSr9keq@ABr1[pM&P&iS+Id'N65*1FAe+$dGmG[ND$@e5k0242(KXr5*Adk
-'#l*-a3BY*hN!-9N4#%XH#348ZZEN!MDN$qh,j#a0aYbUHRX8Tm#U8N@p2#L*K"(
-D"9@p%9[(`+S-8LqV6Mc9&AS`+i@f5hl3DMXRe"2Fq(TPidM'k8#`G&4iVZ%J4N(
-0HacNbA&"2-l15P08-G6$331jbRQ4CdXTQ-cYfGIdEe`CkfA+F#Y1M0qY8j9"ESb
-9NF5#2P8CKf`G'Er,*'933(FC$N)ILN+3!-mC%LAQe!%0IVj8`)13!$#Ejf()Sj*
-#P'fhj9AEpNj*Y'`f2+jXZ,+eqSDhKX*YZ2+LI-2FeD#b`)p6Fb"+dTkP$I1K*lE
-K,@TPNr#jZ9(k"FkJp4KR9RE+(&X`9PRj)A-q(E0Pi)FrjTZ3!"T+mXK0mf`jGZr
-QHG@2bb[V2&CCTiHYV$2mV+b6r+UXkj5JMlC%UTTV9--c`j2)'QmqU[KD(Sa+C!4
-(#kVdB@)L9Vf[PNp!XejYbX!%QITXiXqlC"FF0HA1MT1E3VUXk9Nh1ci'VK-5*P5
-j#p&dAG-K'HT$D4S#`EN,Ab%(N3cj"N1fBB('*jSm#K+UQ'#UD(&ZQep6jk1`FTY
-#$)Y0!m[h6,'N%X(k5@$U`)+`Mqf&"0l'-[U[`fEdGMmcHS0I'6h0KVchmQ422(N
-'L)S!MMkG"A1pYNP"UQe`ZV,"0j[hXX(lE)12KYeJKCmER1hA"Pp4$dX'TRBbbmB
-(JRc-DGNQ'fk$fd%#$*dSpTIa*'N5bU+LMJ#e5SDbUkKc3,dX3cP89"*32q"X*U%
-d&A8G+*F-0DLL`+U0CSRK1-UPST!!L,5aKiZB$`fcPM,hI#YcY*64"a3`[jkX3QX
-e+TP-er5T5hTZ5Ph5XEDU5cUq3eh50Y[8*G3a*kBZSEBj1hN`MJLM2B`)RkMA5ED
-&ZB4(4CRCJLUr9AAjH-RPib(R@1pPi601r,DY+p+!*,JD@M2)&*I&8I'!+"D9BLG
-5mkj1DN+$PU8)""fD5ddaSY&9IUA`hH'*`lD6!Dp2cj&Y+Y,,N8XidT2NBeHdSCV
-VG"lLR)X3h!#i$+JMXZ-j8DZ!1ZG%ZCfSPi&+FU*5(B'l+R)DN!$AC8K044i&kK8
-CDP"&A3CUYa2943T5RUYHH4e6+UqrMmX-jfA'bF*Y@hRYTX$39LPcP'SVj5HjPl-
-1KV(`rXkj#pr*bSJHl1[64Id`p(B'AMN3e$KKk8(3UT@bAKY#iV4485S2Q")EKm$
-@cmUV%'B@`$1p0Fhh$$9*A!B$J9,Z`[DCZq$8Eidlq,,0E0H'!Li3&+dEZ0(0R1[
-1VRKqKp40YkN$6!%cK&CE!b0'$J&KTUTXX5K9QPHd#H[Q&YJPJ&E`6$L!9V$D2i"
-@d1dA30Y8)fQZRa8b+R,()Zk@1jfTUN(Am+3VeIF[EmdGN!"#2M"J(YBXNmd`UZL
-8Q@-J8"'ShH#58##V@ZI#J%LZ@TRU4TMUIKY@GIeqUXlNPqV+H+)J[QP8@AX8*bA
-q"+NKA6*[SB3mD0l1mlN@Uf#*0a6$T$8eL&`)cLi4*Z&1h&E!IY1L*0a4`4a8jA5
-2eM!51Jm,TE(8M'JU%c2EJG-a$0SUECBC"NfMV-kX`X9(MAcfk!&F(+KF2($bfE[
-*XHUE[)ZXpR5AS6M#&qDBdf&'i4cY)H%*[#8F,f+D"PF0UA'J!J(XKi4Mf69#&lm
-PJZNM(@q"Y%H(lSI8DpZeTp!FCS[4a5rj9hk&p-K1TdZ0KlSmSGTFAJeZI%9BFP@
-"P$(91FC8Cm-be@8rQ5VE(kDDBj*#@VrZGBDdkR-prlUhUS#bkMj2G-e$jaiL*X-
-jcJR0M,YDUb+e1(P69,k1%3hN4YSK2ekiKG2jU9EV0(NAUpD,bPG9DIT53XB@9+K
-M"pMTTNDF5eLKNBE@U0QPQ'88P6HU634`3Sf'TC!!3Q%IDpUE&L2Z-ED%q91KRJU
-H%SUHB8Y#@EJcf+XcFDFc$A8L!ae1`H-*,FSBdV'ALcV0q@VL"'crP*SabR%9&E0
-M2LXlFUE0NFGP6jAB2$9BimJp94cj`PiZXMhb,YQ4ej0c@h&Gm+3Ej1"GcbqTN!#
--aXUT%IAeK#LmSeiHBiJ5D9(Bb`iXa')fe+fj&ki!`$r"%V(0CP2S@+[Ce0RUe+"
-ZLJdS%c[$G[DBer(%"e,Mk$&bJlBp*MY-KR3BmeBfX,V'36e)E(*HhQ5(SSE3md3
-5XfX94F4NLUL3!#QL3VBYfb0kGG4XfQae#cc4Y1N$#S8@(UlChEbLihR$eFaEFd0
-`ZGfUlf$mfD16C+iR(H&9"+)UR%Ql4@D0C2CaaI8U*GTQckI"E!$9fe`hJ4GHj%%
-SZc"Tr(Qq)-'Q"Kiej4!(N4E`mqhdSqCNKHTJ0ZAq1Lie`&#BEcT),Q[*!9"BB!a
-Pr[4p024Kr#P9TH6f,Rb$+hk2P#'&Va&VNpN`Q4Ic$[0jKl9-[DmK8FY@Y[L"iT3
-[R-''IXM-3C6-D+%%lqC!R"F&jUbh5H`Y'4#(C2p-3U150GM!+9l`Tfc*GcDI)(K
-33E[+YV2CQF(D95NXB$a6,lKPaLE8a!92kXmCQKSJS5'@5DAB@T`bdZTJ@EKE0N&
-L+iH1A*)10LJai48T(&piH(*kM3PHFm$f#IN48IfGB"ATpm0@T#eq9U3cr+T)NeK
-&QVDALM60[iTd9p[!mXH(+FNbL0@m-0ATU0)*a&'H-rRb4ee9'8dhV9%5%2!Q-#a
-mbT4481*J*!-qUPa'aLeCf5GmAblL4180'8QC4mX0VRS)bj!!3PLqrNSB`M,6PV"
-mI8)K,1QIG%$L1jDN)&`Lh3YR8j+I6%*GU6&!fRBD*GHBkLMZ9ciXl-212McX`m%
-qJZc$bcikhE@H@Qj`[$'0Qlc#M++5b-9[ZRMclIEL*G6dXLM!"$eF5%MZ5P2(Lce
-#(I,9''UV-648BmK5BqK'MD'Z'N0[+N-`[N$cEe(4G$%HV(NiZ2Pam1K1$%adA%[
-c8G2!SU4T28c)*UL6p[2qfB(LrYR[SqP[[6*iTepJ8$cNkVHJF-S(Z`pT[qUh"%L
-aKaDjqZfM#Z)6)1`"8[3R3(LQ&-3&)$`"8[`&)"`M#Z*G)"`"bSKhJ3M#6'B#VJe
-#JA@!$!BSFbi"kHA)%SBX!G)ES!`MC#IIp[TF0%FEhmSlaPM('$Vb,I'18!$,eM8
-X@kHF5Y+6QLCJNTrA2H%4,pCfmS(aiKj&EHX`N!#RNI%41Ta!8hIm#MF-+LNaD3F
-5NhC,L80Mdj8%Tq8VR%P'Bf6%-N`2DMI'lq%K`e2&4j!!6S'Z08lJF-hjp%`a*CT
-ANT9b-$HIJEQLX'"ZLCpJ,Z%AQ,YQ#kDqG`SJD*FIB'TA66#e1AkkB'VccEf$UB"
-,$UB#VUV"e+`frm"8`Dh6!e16"l0qr'6!9%2VraS`eG$k(cHBDQJp26$982DR!8`
-eP*dHQ%*bk!T5K&&LNiRhNr$[`9MBTjdR@+42$drD4jm1i@#I3Cl!N!!q[F,,2MY
-&jlYIJAJT6hc-'1F4bJCUY)'5HZ[4K%0$K49JMMFI9S4rG`F$6P")`#+kLMHDCZ%
-G!ND3!)1XFf#8$#,C42f3!2%'`*U$b%[cic6P+#@-KRR%SpR5dc"V0E(Nq!4#+HR
-mHJ)%&G0`*6+!2E'GAmXI!+$Z'Vq*!aZS@3Re5-%S+e$bkieDPl1j#!C)(f1!p)@
-`J(5GRi#de#p!QPr6*'eCem$bIdSfY2aHDVBZV$%DGC*!D+#NbJ!+)mePcCDY0Sj
-c)h)d&-FEQj)eA&Di4fViEGP+iE%PTU9Vd&`F1fM"YJ9+NK*j8h&,E0f(["%p*3Q
-F4hG#D6S5CV6YV1Q[@Pimj!e5lE9i@'IEm*GHd%E)L06+cC8,p!XN-c*f*0Cm&@q
-HN`T#P[$0e`&#(cLB6'R50GBBTDceb5I@D&6"HXC@,i9PUhRqXG@XVUVC+R4leS0
-Q"cT59YiRa+`(-mFBX`8!)KrFGfKIcLII'rMC`%F$haVF02#eI4m1TJeqIr$eI4X
-'l`eQ$5CeA"cmZi(4I4phT(4m2("5X2m!N!-V'd&%3e)$!'Ql%&8,C*N!@@f6lpC
-ZP&U@CJc6@iDmM&VUR0Z3!-8BMX$E6DA@XC9Zb%*)@VHehA6Adl2V8`L(9AFp$+q
-2cAN-'!iaKSJBe!9e6L,5L$F4m3I$'""L3!4"L(TlFR-m1f,Xmrhrlp[VfkDE3-k
-jIrFe(9Bf*!m4%"!!%"!!%"!KlYr9+e'2"hm8e44bT)39fD8Lhi5,h&+PE0V(A'3
-3rM285kiC%aQQcC*J)MBTa)44dI,SF"$1`C[dpBF8CheXm%ia)DA023S%a$6cG$9
-``KacpkPdYecbH1TY+5XmRVZQXC[r'+C"MKBbC[Q(mU3iam,k'X@AXN*42U0EVqR
-@b@lG%!f%fV3B`Ll1*#P1G!-`2!$qMGeHPQ1hIhAkk[5FXRfPDHRfr#2TfVhCA,b
-XVjpE(k1Ml!)6*6*BSecYRU$BC#I@VB*bqNr2HiIJX"fR9)Eci,E@i9Bm'1GTM4j
-@c(`j9c!UQT2L9!*#KDh4c*8RkmR&4SGUJe$GkNDRTBN3UHU&p@Ef%SSp1a$(MlR
-HHXaG1aA4%D0Y"2laX"Y,DI*ZT5f[deM@L4mcIQcimH+R(cmqr$4&l%%l(IAPdSc
-5#SiD`&PPakE*A51'I[)heFdk)%Qd!@8R0%dk10b94JNG"3bm-N)LcEX1+%l&58J
-9jkU'3XdF`&`KA#[XpL2TTR8El#'YTLFY0b0(@aE)5C@q2r3RZldiVI")XGCHQKQ
-f2b52[rUd2D%d3iA[A3fdl`he2&km*F$8aqSYlS06Rp@NK#f(K+RR`ShiFcPiF1U
-j%&5je`A(2%Gd*(V)2I@Nk'kBIXhi`HP6ZbmZQGSGc9cZLckR+%H15FUAG6F30T9
-%M4G-Pf[FR1PicR3FQ)i2MGCEM"K1%0hHkGFm#BD6`(!5'%D)i5p@qc&F6Jb$YdF
-)dIm'hfF$3kLh`Ae`lA1DbQMQfQ+DpYa`02-aHRb"P%`h,B"0,LZEYFp40F'8[r)
-TAjUQ2)r(,491q5ZE8R)V65NaQkDXaq2CLUD8h#T0+H46MY18`kXB@59P01A2EaP
--+C5QI-1R2'ZD!V*+p"91qBC0@ANh69RCBTS#XPBf964PjGem-qlJmSE3p180EKH
-fI$X[,PPH4k$LDKqMDHpZ`FHR#"M@MfFV,bjC%k2MqRpF[YR`SaU61c1Aepd49HV
-B`jSB2BLi8Fr'PN*d1`Pa#f*e495#lMUA0'8c$F-b!3+4P@ArBR`F3d#`IM`crZ+
-5Y8%kT[r(0I--2kSa'53%'$RdX$E)b&NEl)SF2Q8H$31i!Z4XKa246*Am6EZpN!"
-%bp9qSU9Z"`61hQa606*e#BX6!'D%3V1JcNpaJ6)P#M$)YmXhXeX5rhLX%lrY,&I
--RD83U"h5akIi4kIaac@aSKqAEcEqL%&Mk2MI"bMA"ZAE0I2BVF3Q8(5j0@1+XPi
-EV)#%HFBI!D3SG6hqh3k[SJ5`XUS"$%)qSR&fE(&XGpFS)kUc$)%eG@iP+Bkr1)9
-1D36LQ(FKMNIFf#"8dBXmL2k)[+"VAf&a@VV@*2[qJ29+#qfDdQ*YIUl'[Pq@JA@
-&j8G5l6QT4dTcd[(CcVT"*J)*iC&b*E)'lL99#b2N5$jE-1aKQe$5FRp1IbkMF+a
-@kqVSemY([hZ$hp'[Ii9(,kb3!*V#aqISNef0"c2eY%@%jD,P5T1I'@"Nl2#&SU@
-CqEQQBp8pa&C+cdR9(XQF2*6PlR)lkqa3[G23PHHkVNhAjY$8XH!Cf&qXF2-[er8
-(B`$8KNQfc1,kp2+drCP(-TiE@cj)([%3Spb--QfUTMKYreJb!N)@8KG+MZ$kZDM
-D!94XA8S(!U@&0X(MJ4VQEFGLMPMNJ'+1rbNfGGSE,,*)G0fFq`S@P`m4cMp5H%"
-cT,4iE"MY0c'k0Lell''arp9@cUlV`9JVCpFm!iA&Y9'YbGE4F&89Db*LK6EFLLS
-@fr+LV6S5F0NHKid8+`6&`[C8ZeKeeDV#)DUJ@&fc+C82`B)m[U9q92&e2)*0NLL
-fmFaCF")8jkQAHVBkR1UPf2EeTP8L01M[h#Q1L-j8-@ZheMQTfY'#MF*Bji[Y#a*
-FQX@GkKX4XYbiq59-4SMP6GYlYJPXqhrbL1)VDkIE%!B%Spj4J10GapNAP$1@qX6
-kQ!6!I5NG3583&rD8Z&5f"$!)p4'EM#p&TacSZDirR"l1cFNB+cAU)6eLarBC(pZ
-'BjXRHfacj`M5F,SqpQBFh'`kYJ#QCKcD9YC#Nh&S-cq`eh685MTU%MYUHh!NG1(
-XU0'"pIc!22A!GHhKG*9f,!r-U`fU(p)VN!##1)eA3jJSfJ2KY25aiFKHr&P$mdX
-0$CppD@&Y4QCDQEESSJGSd660@0ApBS0erNc-bNT6*l0m9iSYQZF0dlqP`lh$Xea
-895Y!Gi58(%Pa0QaI3N#US1bpVU$b0LRf"i4L(TB3QJHh@jAE5lIaA,NE4VHrkqL
-rfA+,Rf*[9ck2Xr9i2(k+[ESfLMfCVVYRrf38ZmV(0Z2BFmNeB$hfMIUE*-8f(IY
-kNh,ED")1EGjZS0VESGVmX&$Yq![EM99l8fe8Hf,'5Ue9ZfZ1MjpUGlhSf+Pf+hF
-)!-'U6ZV)!m0*`j4ifcP-L!qF5cV(((AU*I2+qCm![8DiCkB(dr#[1SHj3F`rG@a
-!SZr0p)'1a9l!8*!!M'4P+dca1TJ)VHa$aJ*ki-(Gbm%SmLY&8`IBP0*a9Z&K&"q
-#`@0Zl9(f%8[DA$"eIZ95T1PRB*FbS%e1S09DI031C2GGjRqbV5#l,r[9"*QLr+(
-'!'5mZ[L$l%qe"YPN+NUYeG)!C+FBb)`"CU"JQb4`1HQK)R"CJI9rS9CTMjGDrC)
-f0(5N!NK2Jc"G&"V@Q3HpG"Xr$'Ia"EL2eiX*35p5dR6+D8hj`A+Pc[-8rh2#MDd
-k96Xf$*j#8J)P+h$R"9`,#C9HF5qI%1-T[BXFLR,9`EfH#H,HHmZ9djiIK*&5ePl
-YqF%HeleUcaY)mh`$$#B3Jk0E2ir$m#aX(Bd6HrM`5G,`5AciC3brM1(MM)E[%42
-%!&a&Tk[0p`Bm9ql0m&ca2)PdQbFTbGQYD-k+(q2&Mm+0R0'2pVJ1IZc*m1i@%`i
-'X+8Ei-YF`,3,RQIJ"Tq$$eGlTQ%lT0Vc$*mbEC-,'a(H`@IS(`ma`Y59!*8&c2f
-0lCe95U-B$m"%2#r`2m-!cc$5jRm*d2ih`(Jr!2@#C`fPCPK9!KeC(cHdqf"Sah0
-JrEGM4)bR`p5BaBXJHla%pRL3!(h4N`UbicQ"bd(HFNV"3`Tf4D6e5Sjj,!mhei*
-)r,e(FF`T%VXTHebhUTA6h,&aKVpkQEpiHBp,G02b-#4rkGf09eGlhZ)$IX`"mKB
-IpQ-1%!!HLT*2*UGkbEYlX"QmY419DGe5GNXE#NR$Y)%HcE`rMp$empi3("@5LlS
-0Yc`pR4iAHfN3Hm6!68RF*BVEF3$E9XmBFTXHH!X$i'5mAc3GY1PJJLHESh'fK-D
-A314,UBRkh8MK'FAK4c8e)'6fYH9+JqGeE2'p2X5GL0M8DKH2B5Z08QQb6BSl)Qp
-3ZICTLR26blZUKa-,eUXNHL4"[G3UHZjEqXT&ckXYRY-H4r(-dU#c'fd@T4%Zf,i
-G5cfY54HJ9+fN9!Jj+eRK$L)mHN$4QFbcrT31(p)NSC)@(+%IB8alJN[9JTqm"*l
-`L5fal4I"#-RV-"$,1V'e&r'HLEULHP)rZ1K1K&cBkU+YXaDNIfc9AN9%U2SS09i
-bl'l1c8J[,pANM+@lcT0&5N!S*fG&p+L"Sb,,kUL`)M&jRJQ*18"kT49TY1Q)SlE
-cbI1XNf'm9[Th-8PXJ5h@3HKQEM%KHDqI3k6UKbVL$Q&EUkFi#R&-'k8PZRqU4&6
-HX)q%K1),0T+Bd0M#RSL,YJ3KU-IVJ&38IQ!%qe)kG$,"4SkEX&Fr#U(@k6i%9fZ
-6ZkrBai)BbGdD-c%mMT4)L$k%hSHBilA-khD4q&0C"jd1QcQl8q*1fNUi%aA0G'X
-fhGS'X9J%T[fZ[BU6&B)"X1`'TRM9`99P3ea1'M%#SpF35-%+J&4MiF!fZlY9A[G
-SKM'3!1qh9D0`5,r'LCF4$X46lY(L-hj!0*k`KJ5ldSq+%k1IVedUdG&j'%8b$MI
-LaGP8-qpLcSJ(%)Mp86'r1HaS16cNX))i&Hb(AP$UR@*L*aIccShebQ43-QM%YJT
-SN9RPVkP@)Nm6Lk3iNjJZ03KFUSkLX3YE*XRT(hbMqrU$4p(4EpEN`I'Z$$e&(EP
-Ldr4,0b4FR%MmYZ&P2VB0EP(Td0PX*R(!4"!kr`@mmer!4C((0,`1M#XpP"$bN98
-0-(bMT!L6M#T,)aKXT%5qHc18lhMQmkNE-%L2Rk[`mhImV**ZjN--%4%E*,DfP!j
-dNqrKjbEHZGp%hB'N##4)c5KmJD-e[Jl6D,lRll5p35R-4F3S"d$M8icmaZa"Z!f
-ah*H$Gb,Y`%)LR!EIl1-NhX@0R%HKT2K$kDNJIJ&%rPdK-K9QNG%3,&GXR6[reP[
-j)Y)dU!YB9*pA2jF1"1*RiHBZIT!!4,pMr*F2MP@[Nik!lZ!5b)qAMZ&c&%Z#P#F
-kr&YVf-10aSpJ50i&%K[P9pqGaY-jVJF4LcSqU6B2hPRrU8cqT8hmC5F4L24I9iK
-F%,r$%#T%jMH)(3dTiG[*0F%,6f+!$SGb9(-3pKF"B(m&"&D(+-e[0KRH-#GY5)H
-#BIUhhKA[DEld(djJrpaD*Il9d,eHp6S"AbVIBSUN)E@T(Nj!')HUQ13SFHE$BF#
-hPR)6aT(c!#kr2(VT(D8(9PK5Y,!KVNY&R,UeSJ09lEKFe@KMM9Hd0UCSPSdQedd
-lZ56T%DMAHHKP#DpSk'MNF-41D8`Im@Vf8C+NUTBf-(4k0NZZ*5H3!(3"2cH%@c$
-XJUB5J0r-$GGRBAaZpT3!p#Aiq'`iKQ,"52T2Y4$V4#GBhm#0jBCG*-$FEbreh)$
-(Kc"eQ)SFSiMTX'*$jAREmak4qIX-chXH$kpUli'-'+qX%bM`mD[Q9dR92-P)h&G
-lVN*9(d!U`*!![-R)MlD"(ff$I,5K%Lchrcfc11YaB"+@L[NqJ*mFk@D@*!E'5FY
-kH39k#6mrim6pV')a-23CQ-rb2-#"TcF#AKpqVZ2!kq2!dh2J63,`p*la!0jiI*`
-N!Hmk)q"GC`#mkb6JZ56JZEMcMm$fJ!5f"b"HeZ%)afAeAlb2#m#V!R(&Hkf!#5U
-NNJ$+fBSUIZ2*fbeqe6iVB5$Fq#9e8l'-,lPi@XBVm6+)TSdQd66(ZS!1#a4d[F$
-T*ZIYHIj,b'*0Yj-%fm%GRYpa&#f5#N(-i8+0&lcar+lH*L&SN4q#rZX8#EK23@E
-0el*Jde8Sf*lPa9$CdP-330i9L'-(JP#ka0'hbJKpcq0R)dIImaapUcMkaJ"pUj!
-!3NeTadM1PG#hd3Kp'`h3Ye&#hf%*IBG0k,Y,3YpGQ(E#8(Kj6KJ*VhfjBbHjXZ@
-8-@C`NmKJ'rC3A,lYXC,%"3VPHGpe02P[AM"986P*U"PYDedUXV&@@r2r#CNFpC*
-CJjeZ*#PhN46(!GP%!8qYdr'HX)S),,1C"CN8eYh'%`3Pajk1hqL3!09-j!"TFX"
-Tm-&Xm)(#,L5N+QC6D()2#dfN!A*iFSp"H$,I5KDaK1*A(+*XpKriHi3TaQNmVTk
-+`Y'*`em+4rpNhlYMj+,brd5S16&h`eL%QUlMTP$cR9Fee(brLU&Q,C*#[LHKjSK
-aU#QP0$eHSHC)V8209f(,jh%)0ApR%'U1')HD%K#0*f`U%QT@1aS3DQlh#c9eFUM
-T[qAhTZYl'RL1[+,!mpAH,T[L&hL1F)0iNmC-+68`c8lD-M`HK*aRT"ZcL"F3293
--RB@8B4M'lkZUdB9XBKpPi85''$FLVk0!MM0d5T-ZF50P25DYpc03Hb8PQ@)3K[C
-#X,CG#pAbh-#REX'Je8CKk*Fm"%@"@FR!fH)A`2d92rrNKX)r$3a3*0LcJcD1J`R
-kMmN%SK*!'[H`)c5q))@L"BDK+#GcF3@Kk!hS%KE(9cd8A6c4824k(1'iG*3cMJa
-r!iJ)jNCElq-FM0B9#8BEZJK'ceC)BYIKD)("K&U'Sj02pC,$dHe&`p%BNFE#cDp
-K9['0HKk3!$D-dS1T%P$M!9825bG,Md&B1L+&TC,D14Y-JDNhAJT-'h5HKAKePPF
-r#%#rX(3pVhMVNdb+DeR+cI00XRPH*1AK!RFCX6"e1a##M8SJ03['qLE2'UK2$!Y
-NmD+rP2a!4B`@'*RX#hKDZG9XaqYHE2DmVCHfHib#9K4pqXMc$KhKS3c21jk&f$K
-j"`5Qm)Vp"*Ci`NmNc+m`C*d[KD`4[j!!G3XrpKEVXBGD8DdrmGc(Q8mc#PTR58%
-VhG`R#BeTIN(4Er#cJJZ0&8@%4V[%IJaHhaGe)9&b&JI[kLl"fiHIG9)J5q"GcF%
-l"H"GlAPG!Zm8+YaT!Zmk)r#Z+`,HGAlJ03KV(k*JQJ!l#i*U839"lA`%YG%+JPT
-Ia5+NmGR*K,8&"Q'Y9Fa9&0CfY84JV!,EaE81E-miUVX3NamCKlCH,dIVBU2`YSk
-Mq-XZ8I`mG9p5X%XSrT+Mq'@Jq%[2Qa++AmE2QbB8paUKZ,F)LR[p8'`3qJ,&Lcd
-,Vk8r*`b&C#h#hSQQ`aZ&[5-ml'AGH)dTm(8f')5pfa85N46fNZKXU%hB1l&3a#M
-XIH"l%[BqX'%LBHr)+`PlHCM%`Yjh(VH`prfUKld6hB3e$RXA`UKB+"rPfQ,1[L%
-Aa3md4`Ue1A)4Z-+Fjm*DiQ'hdiF+`bmr9YFrb`SA',)#8E"A#l0c%)BMUDGVMN9
-BhV*eBLch6jbP5`jZd$5M$@NAam),5e`SPAdC`ZiH5N+J&!8Uf+pHmQ%q06l)%a5
-@FAIA(2@5qhmCpS4FETpQ-DVkbb'A3C,#(*DN`'iT33(6H%-D2CJUQVdhDT!!![(
-K&,i!&UcKKFmq6ke24,U#bj5Zi)13!2'biR48@$k)3MK)$*Q0*!DA,J(T)Ll9kE"
-&2pTT1EllT'ZE@N&cDYX%U'LPiZ4'AJ&[lN0Qd,B0kXU6EG$`(JqYU2'T#rA84-q
-&HKi5P@e(BX`SQV5%N!"qGrVp1rFT*-3Jc'29lpCrbJS#'DH13%(AXE34L0X(hG1
-RMP1eK2"(MF*q1M-CUYBM4++Fr&jHL+S%M4pN49!X%!I!Rmk$8bI4)G$)%3VJ64d
-[ZT'Sc`[!fTGa%`0(fd9(Uj'10SdkGp24qL"+E@)lIrAQ`FbT%p!03kKlAZH0,L$
-dJ2"pXkXNCRl%#!KD`dbK#JkjLKe5&`[fQF4`SA&je$rp`C6,J&+CAAZET1qRMa5
-6,ZDNTA)Ae0I&KE+1qVmc&@ePc@la*YK#3Dr1FMX9KNYN4E-@#b8$e'fAG3C$3B6
-#0hf!T'XJ9daXkd1!Df(KG4N[SLihQq@+3eX%T5pSAl8$Q%K&FKLUUA[kbLa0,$4
-pjCj$Q5[hV-`+(PbC*4i,"L)l48X@4$b5iLdcKa'iQb0K-aUUS5CNV8@1)kc)X9H
-pj*pR)Va,8#qCf43C&Sr9H)-AG4F0fGH!I@@LQ*Me8m@T29ZG'(SDc*6k6kAL[RV
-H%HHa"Gr@9jZ4+2@a,S#L`F'%*a5RaLQ11)BkYJ5MZTdSrY[1#JT,SKK&i6k2`lB
-4'VS9ch'LMiN"+Q)Aq4F3lMDT`ekl[EDL8JBQ"(Kj'NTjTD,8EK%`&KJGY!"J,*J
-)',1+J0%'0a4hiBedSRN4+`Mp@!1%"Ir()(br+!LVf%98$%P$8+ib1[!UJ(,9f)0
-bj`eqS24M$9#ZqTm-b[eM#FVD&b1IQ@3Y4Vlbk#X[4Mlc&pCLj#ZcUe#-2)XDAkB
-Q%&#BqKR08GQ"2IM@a58VTmQZE6)LJflH#4JiX,%-6b2-'%-LP*ET`ZPYj0$QaE'
-I8@-"8l-&KF9(dNQff[e!,4HDE#A!'RH5rUU@SNG4ljK-q[Y"0"h8bP+hCqE,"NJ
-33MkD160IQR+'ZJVMia8KZe-Zm2R[Q8F1D1eG8bJh28T9+#Je*JH6U6r58h+K6(G
-,Hch[S[FQLHk1$cV0mekMIdYIfcJmDrIhA6iPrYcDpCr(D4I`*%QfFE'p,!hCfhC
-$#GP$46RSIqE8I+L"[H'PLM12T"m`)S8em0#13lDXh&!B1Dci3"K)X6&5cP*`D0(
-hZ9(X4*-(%Ml4cZ*93pSi!3(TK8Fb+UDLLq8CF@0(K+SS%ImU%j'4PP0l+RJ6YPr
-(`FPe*TLQR&Vl59P`ArYfTqeBSk*e0PJF[0Kl,iUl,bZq2XZX0(brcX9*Z%(F'4r
-('kc0GA@#K*bdh(!B&E`#A,#9UVV3dSNYK1K`FJY"[-&KTdY6[*eT+&5d[LcQp89
-GTr8r@DpG*)lSb!eh"aMY,bh6CP5S1BAdrhl&AeeT`i,8&BC32j!!GAEYqM,IlCC
-EcX$jci4T(8)XrGVeJ6MYE#-&hB@P-SkNTPS$fL*+@KJSj'LiAB'6XFR@dkL8pF[
-!Q&2Fd'"@D-Z!LPA$c$5(%DJTD%Dq`S%@HH"ar6(&Te3i+-pi8*0b4[(QIBYEFX1
-f1k1lShqTaPB@0AA2&[)QdUY+4BpQ2-0$dNHR2%AIMFr1bC!!**T)rkc#!9kMSc9
--KT&J00!KNA&*Q9,&+B,4`,2q!hP6c#jTD!a-A@``EqBC0fmbDDCjVJ)%NT*!bCa
-N9RB1hj'QY0$$l*2m`DbBhi8LSV$ANiSC$Dm[Q9P'`IlJ0R6A1k!DTih$E)PV)49
-"kk,#jRpGE0"`a'PD,$)-ekj0CB-EM4NA,b-JLkRbQ+RE9B-,rShmQ&E2PT`jU$L
-ST$j88YhCpZKSp!-T`FT$eG4V85rjBc'f24Z3!-EHf1m+869G)1lN$S6*#B0#dRQ
-UA99GjT'*,914+2"EjY-',+($8R83#T%1Z'MpZa9mEX$R5M+E)Sh2+kYhPcQIEi`
-N"UFUBQ5U8TQUZ2H!8hI0d&F$BI-D9b&5rH1E1d1KNqh680MLFAJ)l(jf3$['d@,
-m-E6lf6hDTGim((iH$Rme$Tq@Dm+IS5R@XcG8bN4,L2j#[S3N%I1T&q#)3'8EF(!
-4"frU011f%VHk'[1m+r4[kC8EKQF09#FDJ+1TFkULNm!aaJ3146NR*S5Db4%UIKA
-IJ@E3([G($U"c$UrrC`kL133L-i(S0*N&'C1(%1P)L)[k!##ehlKb84+$&1+-358
-lLN$4(BKM9HI(a[A@N!$eA[p+DX4SRRV*SjHV`+M3bSJ+q`0CC[(h@@h&H94F%ZQ
-j[!'!jNbFVY4UFTILI`04C+D(4kN)$!NERI&UTkqfIkc0d+E#3UZ!r!VB4+V)TY!
-B#04-(@Xq#kN'j(Ke`P@c&CGr#)@TFHllBD)kq6E,BDRK,&H5h!543aI&C5kFc)d
-5C-eXc@A0E"Qi8@C,4CqXM@[Ypa1VVhlM@S%ZhXP"$B)$FJ(59LJDpC[,h#PL3S5
-fFGdL&5E'LkiF4q*1hRLBC1Ll[U+H4jAakVK8S1U%'HlkP,S3pf#El"b(ZIqj99h
-MUJ&FK#Xc(9)$&cc8A+a)aA9m8Z-ZSTm1'i*%9S3jXSQVBmd9HQepYb#@J[!BVTT
-MG2BLDf!L@LEZ'%A)iql"0(qR+"+NlT&FSQLHD[CUUdX8$HY9k[Uf(8-Bl*`jE!d
-lYlPKPMXMa3Mf8641CBid*je,'0@dQSblIFB1Zk[VXV@&"1e!6lB*09BFd'H#5DJ
-(YpB!'0Y*f(b3!%+a+"kkSmraa[fN-"5"*QfDpQ[bH##i!"pZP"jZa--0dX-0H2L
-(p2!22-bA(ZEMiHr5`praF*AdF"8HVT%HVX($21PK(KlZNalZ`m-Xk@%@(Kk3!"i
-HU&h3rTM2+'MA[r+JrE'lMB,fp4-*fR0TXj!!`+Zp4'aAhLprq'TG)#iPGq")IPT
-UMU,!jA+rCVYlHX(XY$-*q#-H,*Jp%`AM9Xi@iEa"3iciQ2%J6r#Ci*kqBKQ5!$*
-A,%YT'm4$I6ec+iH#5@$CTceF#SjJZ@)1-9Xa4cbiBJia+jJM-eXa*`11l4AhF$E
-hF$Eh2(P25Qkhh5j0Pm`M,e,Jqm-@ebJFeECGf,lDeaTd"mi(cT-3V)q&CrH1`Kh
-,RE(aBASNKhDi98mEAFqDYj)`STF*'94-N4P1E`a#)`p!C'G!M13@jY"LTrBK@")
-Vkj8)*MqKf#)jjUe"0ea@jSiY2$dX0l)cZr@GjKU,,V'NZb`5J5-F(dl@@!T``4L
-GCHdR'KZUMfPi5EGf[QKTkdi03-cCN!#Z`XQ)AiAQ52J#fd!Jb)Zam$Bq4TdLQhU
-CNCHHQmr['#KZ"RNq'#j04%6iZhpT&RHqr8%N'VlV,ffld1#b426)2r@r1PITGXp
-3l40$GjD6q8d1XGYf+VBl3q6NaUdjFKl,YY1bAmG(KNd2$j,+S0QLmhGL%(jXi9B
-aT'm,+PP2+1C#jlBHfKcl(1!la`JX,XeJa#PRj$!cYA964hKSGdIBZIXR5,lK4!9
-(EY,rkRcPcZAADCc"*aAEmVpTc)20Jf#+aS14UR0E+5F6Ih"V)eGk%TVPZF!@bFf
-3!*EKCN!p%0[SQST*Z1#DZ0Xp9I'LU5hRlMEFpUYX@,S0MeNq**[FYYZh05AhC))
-%4'0FFqFPQB$9pBVZK9EGZa[k`N2k2MQB#bV21pFh4hEqmkrKKASi'h(C)S[m8UG
-!eI,3P-HRXX+KL3XdlB%YJDIaLU%ic"XXeDR1S[&,'fXficB)d9d%9MGYA(1(BZj
-P%h(Ti@**i9[1!)a08%)al04hD2*VYL%P0K(Nd5AFGJ!diC6Fi)lIE!TrqTIQF#Z
-"Hq1H6Dl4CJaTeX31YflT@,$RcVlS9R&[CH#,pq$dK0&K"E)1Yb)%q@dMG,%EaNj
-Qff`L*e1EUY,DdD4b0N-Z318&J[Z"cZD)J[3#IH81,$K$%f)%-',dZhFc-Tah![6
-meJcPA1kMj$IREY`%ieH#*0e2S3,V0%1$*lT'[L%a'GV$1F`NJm"S4FTJjSV@cME
-aUpYf+-ilm!"P`"raY8-l9V3kB[5Rml8lGT!!LGJRU3me[K)NG`LD)qdF@I'*CUM
-j[C9,9V4UR$4FI&&PlQaQ$!H"mX&QF8I36Lk5ET-#8MF&3@6,'e88lrH(4MfHCBT
-Y&#Q!5PNH,[(35"GK)[4V9U(MM9&5$Cc020N*'d9F-8*Pl1CiUXMGSZceC9S!4pa
-[clG@pJBUp!-%IfIMk#CAX$%F+('9$@8(q2(ck,#1'&[Zq,+NZ'!8c[Dj6%b4F#Z
-")C2[-bhELkB$jJEJ-$[NaX3'L#hR@MVk!TQ&P@$'`(JUh2%l!m2Xa@qNEK`1m05
-d6(XfV+e`@PTa1LHC+P6r9qGCPF'&%da#PiPUh8kSa!NN%l3c`8`AMi2k0$rVNT[
--TA4Z#8!6f)eQ)aH)@2UP-ZeN&Mp&LiX)cL*h)XL&-Y3VPG6920EdYMi5[6-!mk8
-pD94R`BZk6LG,)UP8DK3S09*H455k`!Kc2ImIm`I%a!3A,T5cZl!FJ[3$hAQB2Nk
-Gqp@j$I39G'ZR19U-@BIkD-N#PrB4hANL1pA'NQI95eCXI4Z&Gf"m"3$1U8S$kaK
-1lLdpA*%impfXJmXX@lQ)3cZF56"##NlQYiS@IiE"D0+`,ZTZdab2([l1&(Vel@I
-'b2mFVN9FBXrpUq(+U"l*G1*aA$,,l1"GUDIe+aI5NZlTaFBRNSGX8**hC9GkdR$
-`($H(ih8`SkPK-Y'G0-`B[Z521%hTB@fC&A@FF0'3!("dq8fr1QG)[JlN9dCh!5#
-9jl#KBpD)`AK5I&8r05iXN@+M6cM3R-%6Jc-B#Emf9"ir)RLP0Q[bU,,Lq-G+A2N
-f9M&qG3lE$P)eqrBc9$--k-lN[#4R-6PZi'+kRJ%Yb)#@i!qdS++cF,BYp4+4R`d
-'L,&%F*,NdZh6T'STIB)U$X"4fA#T8Dr(`HC%9G*Jab-J`ShU1i,dlKD9e*M8C`Y
-"jTQK!`Y[362,"b#&R#!T"PGBLiT%f3M-Pc8mN!$+2BmSKEGiL6-`FFB"Elb8ekm
-*bk&X$bd(&[2P`S4J`YTLi%a))&-i(['+3`Pl8)%lfhp[De3HeZ5eVd*5E!`2-Bd
-6$`q(AQ0$0&GaPaZd&lQS13`I%(d3JGVd,KR'1-1(1F1(1F1B-F2rY$,-560L4`E
-$E@L58)RJMiJN**hLddq$N`F*5IMNJk-kpiUGqVQ`(3Np'QfUNF%*e$*JI)j'1V,
-JpU&LIEZ1%L-i'+-mIDj'DDUR"ZJZTF"%#Jq98))IQS0('+Q$@MU$Z('2UZ5L6,P
-)X0#Kb5mI,KCV84)eATN*AbB%Se"K!kp3r(LNc)JSRmP&L18L5+GVdTQ$#-C8S9d
-pLUj#KN2Bh$)N9#"#aEP%TJ&j2LYjTQ-VXQTHPT%Z8d3NL33Q1LT8l@'0cDT%k23
-pZ"JA*L*9!UlB4qDL!M3@S*K1H*mH+5B2QUQC&%dl6jjrQ&M)%m+@%PIQGLp0-LF
-SIc6MQSVcKQU8faAcERbNea`&$3#[j9XA(++RcEmA'pPN0P#Kbr#D@9$!Ml%Zb*0
-X0(P)aY0TDR!C1jI'CPhDi@86q5HE-6%*K%3!'e[#%EKJ[Hcc1EXGVB[CbFh!$3)
-!`4`pM)ES@AFefifNl8abfdB)R-3%5YaLc%LZq$pIR%6ZVp`"$6J@-T!!3K4k1D,
-TiJAkG`LF1ddJGVT(VD!PCG2`T#,Y+3B`K)a$UIXf%B"IT!)iUTYK2SkU6L(-'j,
-"B5U'`5rAk`Ff%5ik#I&*F6)+9"8K+Bq3!$M,r,A#$NE+L$4V8G-T,r2cFJ*$4C1
-0JHVYNeQG9F#X`@e4jB9M"DkU-1)251Sh)39Yh2NKa9BK8UU0N!$5Eb*NUM)Ac1U
-9Z3idjB)3PRFjpT'!K"l`,V3U2)@#-KPq+Lm"9"DIf$DQ#RFXT3hA[6a+SRR`*+U
-T%`h1a2%0LLCCG!1Y6P4NUE&JaUCE`q@d8FSp&ZD%r@)e%m-996Vf5UjN#3U4a6i
-bK0T`69HYcELLX"GI+daNQG$H`JE*drQP0+5&i*b6'Vc*Am1,*`eP+j0$''2"'%*
-8q4MUf1GZ$CFUG-a%FZkHaR%fP@+C(A@0YL%8bXZ$Z"p#eGfQ2)c!lSj$`KH9B8m
-01Z(qE5!9U"#h+6lkJ1!Kd[%B(22EP,U0`jKXdH)bHfH'[Kii15!fdT!!EVXQ4dX
-pPL)l+I+Mj+3BN!#qQd3XM#JV@!(%2!)e4*Hd2"1)-UJd1S2$qi`1lcH&#ajF5P!
-#AP5Rh-Ll&+V)UM)CDGmUUL6'h%H9)XrQ9#bD[6!,I8LMmCA&F2',ZS+TLUr3c%$
-UD+#AEAe304Lk50-MXH0V`a#kf)3aUKejl&%5&XGJ-1e$&d90)%54i!$M'3k!CLi
-H[&dI!dR0YPhSK'4%XXm!,T@D8L46bJB3Hf%FeV1,EH4[B)%1!CZ0UfH$E(*P+rX
-F(69[#T,-+fdQ'[6PAF`T-JIkQ9PlYPkj1bc#6)DV0'bTHI(B`!CACD,+p[+!Z#2
-dQRFdB8#c#*hC@G%5&3D&6NZ1EqD6D$V,FYq`DhHhUmEjb"8-Va0h*,f'"-`Ur`(
-Ep5rF[U([ITSH-heF&,CXFD(5aU6&qc5,X%&kQ)XLj!BA)f60a"(8P#Dci&!8lM(
-U3Z%&,8fc``Be1EEfFDF@9#-c,jaAiNVMSS@#(8Sr8LrjSZ&Y24Q9ZN"N*0bi3Um
-D'Q`10kl9Bq'BTS@V&"FmI%T-%k20!(,R`4PX56R*ZQpk13"h1%N6-[GJbNcr)SV
-Q#4S**@jkU'EG##jb3meBfGa#I"aYE`2a88Fl(H+lHKcL(R)DIK(0EL4$%#C+BEP
-@LN(5+1HALef1F1d%''9BJ+SiABL"#F6kGU#lRbqKLlK3k13NljDP#a6c)0KZ4d0
-9C9DHA6$PV2KRj44MaB[cQKLpBEI[6bf&T@rL4!dm[b'E[UE2U$V1(jhL"QhkFqP
-fbDSRNh(+l4b9p&NbbHPc"%%#&`hPA1!kL@fi!GkJa0PQAY#P!6mk4k9l6eV,N!"
-1q9"*4#!U+SN1VhY2XFhdbDXNGJijmP*"F+T(E+4U3GNA9Y-AK0PkA9eZLf$ckHR
-p8,$#m(1'Np!S!&i2dqY-&245q(mAK*la9`d,Aehjch1V"i42CLhif3*Kbk2dRpT
-peee#U[SfGFUalkX2UE15,b3[&q,a-qCTp8qAcTSKT!SRe8kejE(NV#YUYr#'F%h
-b-rVH,ci8-S5r#cPcNYF+2@T&(YLZrR4fmY6,kTm,8i4Pb5mRIr2K0am*BH'2dNK
-KfG2#V16,b41%%qZ5[jNRV%bq,2`[IPB,jG1%hiiANXF,*CbfMhr`i2QRaielHR$
-,PF'iJ5[G!d*!+"-qI[VA9li4IVdJZ82S@l$$)q"5FFT$kKp-%pjrp&(KIappp10
-lCJLM-i6RC`L6(K1@RKMS&YkB)DaA&rBX5liY1Ap`[c"EII6B`H6[*(meq+EDeLb
-F'ha`f[+p%pU%[d`VkE%,FG-%fV3D,cJ!%RZhZSba&GjrDp'L,r!Mr$YH(,P3X1*
-#`A*ebQ#Em&YeR[$5&@&!2I1Tep9VVJJR9jd3cR8)(38r9"p0GL5r*4`@rQATB'*
-[FNjbmf"CpcI#bp+)EhkScNRqCI+E`Qq&e+@$04mQ&bB2U$Gbb[)ac[($*iAT`K*
-eSr"$i4VKq0-R9`JAKF'HeDqV[a@q&+B12rR0CD(R`XqkKGFAU9qmdLGmI-f%"li
-CdbImj!I#aI(GilYRR"mRG#qI0N8SA$RMp4NRKB[cKBprrH-6,`NAAa1qIHBh3RD
-(m-b[qhjdVR[-H3#3!aJ!!#5)!!"AZ!#3!`J!N!-J!!!r2!!(UI!!N!-+@-!!AF!
-!!&h!!*!%,N&9Fc)!N!8$8f9R-JGcC@GYC@jd8f9R-`GcC@GYC@jd8f9R0!GcC@G
-YC@jd!!!DEJ#3!`&f!%ja5S0Q)N(Y!#!J2$mm!!!L2+R`!!&+3@B%5N"R#NK!5%%
-JJ#&"!!4#Td(krml3r!%!,`J[2!!!'@i[!f%!!Ua8MfG!3MJ+AN+R,ca%394"2c`
-%eDJIF!%4`!TH5TpR'%ja-$bTF+G'3rS!+L+)3IS!)$!mUA#Q4dU$C`4`!8je6Zd
-!)Nja5S0Q!URdF!"1G@!'!*!&!8ja(cVrpNSICK*)jq$J3IVrkP$36VS&VNcI"`F
-[1[rH6R9JFN&-384%3de3!!-!N$43FN&Y51GJm(43Rm)[5!!J)%mL9$&T!"3!'#&
-!!#3aI!!"!#c5N5&"!#kJ!Yr#60m2"Nje5MJ+AQF-)#S!#'F-)%!J%'F',cVrK%j
-e51FI"N(krjj`$#)U!!6#Z!-DBD4Q!!%q5(VrMNkk"fjB6l"kreTQ!!%1S4SZ#!J
-U!%!!"'F')(J#TU!E,#S!"#SU!!JB+J!%Pp59e#!kreDK(Mmi!L"Q!!$X9%mX5#!
-krd3L"X+i!aTB3@%!rd`J1[mm`,J$'N(krcJJJ%U&CJ5K)Q!%)%@J*fB!!,3U5#!
-18)""q[m)))!J1[m+8B""q[m!))"#CdKk!,`[&8Kkr`)[1[lL,cVqiLmkrXS[1[l
-+,cVqbQ%!$8i`(fFJ2`"+K@F))%fJ+U!VB!3J6D!M)%kJ(b"(S"Xah`)JB'!J6U!
-I)%HJ'h)!%J6R#H-Cj"%!!3!J!J%!i#"0S'N#!!!IJ!%J6D"UeG6Ae%(krRC+N!"
-R#(!"S*K`!k#B)%dP5!!)F!"-hf$i6R9-hf$iB!$q[Mm!)%kJ(b"(S"Xah`)JeG6
-Ae$!i!L!a`!TJNFJP5!!)60pJq%je6PB!!%MR!$JSEJ!-4rVq+NAkrLSJ&,#5E33
-J%LL!5S"[%L"6)Qi!#+)Z)"64Nj'5F!"J"$!mrpP-ha`!6Pj1G8j@rmK)jaii*Li
-!##JZ!!`SEJ!33IVpZLe)rp4#,[r)S4SY52r-98qS($!I1J!-43!!Eea)E[rX-!9
-646m!U!p96bmZrqbS$6!I2!!-4J!!Epa#*kQE@8m[,[rX-!C64Mm!U!iJ(be!rr"
-b!4m"UCXJE[r`5T!!Ca"96bm)UDB`(dM!FJ6!J@I%,blrm+QMB,`3,J!8C`TC6bk
-i!UBJAk!E2cbJr%kk")C86be!rp"+J'F!!Ci[!%kk!pCB6dS!C`T`!4e!!"C1qJ)
-B5'lrj%KZrq")E[rB6VS&DNr[!!`J,[rJS4iY52rF)!KR!!&N)#lrj+%H,8Mrk#!
-)C`!"9#mZrq3[#%kk"EK36b!$CJ!!TPP2,ca$6d4&3QHS(b!I,8$rm%U!C`!!ML"
-!)P"b'02",`P1ZJ5d@%pb!l""CRBJ$5"!F#M4`#e)rr3LE[r`*&&`'0A!,8Vrq#m
-+6VS%ZPK2,8$rr#"Zrr#J+9"+*Qlre#G+!#KC6bmZrr"1ZKA-)"pbk0#"8B!R3!!
-X98p)H[ib,blrp%KZrr`[$#m%,blrh#mZrq![,[rS6VS+aP42,blrm+QM*'lre#9
-Zrp!!$#9Zrp`!%#9Zrq!!&#9ZrqJ!'$mmSCK1ZJ0@9%mQ3$mmU*p1ZJ0+9%mL!#!
-,X)&Q"(!!B!*`!5!!*8!!(#9%!#!P6!!N5(Vlc$mmS2`r2+$m6VS#q&42(`"1ZK9
-52cbKQ%kk!`a86dU!C`4`!D#B)(`!!!&D-"")`1#!FJD`J@B-3IS!VL*m!!!$2#+
-)(A`!!Ir))'lrc+!E98qS($!I1J!-43!!Eh4)E[rX-!9646m!U!p96bmZrqbS$6!
-I2!!-4J!!Epa#*kQE@8m[,[rX-!C64Mm!U!iJ(be!rr"b!4m"UCY96bmZrr#TTM!
-I5-"b"-#"C`J[,[r`UD*J`L4Zrr"+NQF398m[#UQQ-"p)`()%`)&RULm+UD0JT"!
-ZrmJG3!!@60mFH%jH)&p2l`!16Y"19[rm51F!-%)Zrr`r2+$m6VS#,&42*%"+J'G
-F,`"1ZJ'!@%p+!'G3)!SQ3#"!,bJ!$$mmS2`r2+$m6VS"hP42(`"1ZK3i)%XJD!!
-3S"mJ5b"S!"LJ(b"m!!!"@M!35-$JJ()'X)&Q#R!!)(`!!!-m))!GI!!"rr`3,[r
-m60m-!%jH6R919[rS51FI1&P2UA8J(bS!5'lrk+Kd)!dJ3#!3FSE3J5e!rr`J3&a
-)3qlrl#,B)YKC6bmm4%&836mm"0@TS#!I+%!J3#43-LS!#**U!!3m!63U!!D8DJ!
-#2J)f,[rb5--i,[rZ5-5@K$J"5-5@K'S#8S2LJce$rrBf,[r`5--i,[rX5-5@K$J
-#5-5@K'S#8S2LJce$rr3f,[rfeN%p3rrk-Llrp0*#28(rq&P23UG)E[rd5(S!CR)
-"(`&b!6m"F[m[!8)R3UHT%b!I*N![!+Kc"S8!N!0i,``J5h!3dF![#+Mf@8qTG5!
-IX)9N!Q$d98qTG"!ICJ*JpR$r2`"#Cb!IS$)[#kN8,`bTSbmZrqLSFdcI(2K1ANj
-e!!)!!%j@!!")j`!`*'i!##!+*N!J3#)S!!)-J8&-384Q&L)S!!B-J84$69"Q#M!
-S!!Tb!l""C`4`!'!#F!&-h``!6Pj1G5m+@8mr2+KZF!%I!%kk%RJJAb4)@8mr2+T
-ZF!%I!%kk%QBLAb"+XFPQ"M!m!J"J"$!m"!!NAdje6PB!!#m$0Li!#$!$5-!#J!!
-!#!"+J'm%F!&J!R!!*Kp1ANje6PErr%MR(!!f,J!)2`01Z[r-9%mG32rmFJ'`!@B
-3!N-(rdkkri#`3fi%F!"J+&P22cbSRh!"(`"1ZK(`)"mU!&P22`-I,[rm6VS4i#!
-I+!#`K@B#F!"-h`!i6Pj1G8j@!!")jaJ`1#i!##4Z!!SJ5L!3*N!J3$)3$%&"4'B
-S-LJ!!Ja"3e*Q(MB%F[qf3@FD)#J!"()BiUJ#J!#3!rmb!dM"X)&R"(!!B!*`!4e
-!!!j-h``B6PiJAea26Y"19J!!98p)EJ!)F2mr!%kkrj)3(fF5)'i!##!S!!4b'1+
-S!N!!rf!#F2p1ANje6PB!!&925'i!#($r2`"1Z[pN%"pR%#"Z!!JJ+!!%!S!!rj!
-$B!*`rdjH6R919J!!51FB1#CZ!!JSEJ!-)%X`[!-"F!!N6#5!*M`!!!%Nej)'NJ!
-!!NJ'NJ#3!b!S2!#3!i$CNYQ5+$`!!!53!0Q5ej,CNJD5!*!$I!D5!!#!!(!!*'i
-!%#5!"T)!N!-N"T)!N!-J"T)!N!0)"T)!N!-q3N"-ha`B6Pj1G8j@rq4)jami*Qi
-!##SZ!!`J#bK!,8$rk(!NfF!Y62rXF#$C`#e-rr"`50R!,8crp(!qfF!J$*!!Ll#
-&B`C`C8lk!,*#3$i!3N!p32rN0JG`*,C!C%K`",C!C!4`!'!-F!!`!eQ!DJ*@J15
-!H!!i!be%rrMBV[rS*%38J#!ZrrM3J0#Zrr!J3$#Zrq4`!435FJ!5!Z0Jd@lrj&*
-(B,"#3$i!F!%m!$B(F"qf3'4%F!'f3'3%F!"J$(!!-!06J'S#8S$LJ(J!1!-Y42r
-mf+lrl#4%&)!J,[rmd)$3V[rd)%!`KR!"&"*b!")#if$F3&*(B,4#3%cI(2K1ANj
-e6PErm%MR(cJNEJ!)*Qi!$$SZ!"!SEJ!53N!m!$)&F!!`!G#!0!Cb!$)#X)&[&%*
-!0!Cb!$)#dS(5M#""-)"54Q$D3N!m!(!#28$rmMB'YN9N!!#i3N!q!%*!28$rm(!
-!-!2PJ0#+)%!J%#e!rr3b"R!!-!(3Lb"!'""f!"B%YNGM!!##-#lrpR)"`%(4E[r
-`F!!`!e1!0!Gb!$)#X)&[2MJZrr"f!$B%,82rr0D$eS`J3dT3CK)J,[rmd)$3M#"
-!-+lrmP4Zrr)b,[r`F!!`!G#!d)`J3$!328$rm'!@-!A330"'0#lrm()!-J,5JG+
--)%%`J&*()#lrp1+),8$rp'!!rfa54Q!!rd4-haci6Pj1G8j@rra)ja``*'i!#$B
-Z!!`QEJ!1-J0`!$!"jS!i!$!$FJI!36S!F!!Y32rm0!4b!$)#dSSJ34)3F!!3!63
-&FJ!b!Z+JFJ(!JG'Zrr`L,[rmiiR5Lb""-K"`!$!",8$rr&*&-!9b#,""CJC#3$S
-!8N3b,J!5F!!`!G#!X+lrr'-#B+S3,[rr%Li!%p)"N!!"60m-1%jH6R919[rm51F
-I)#4Z!!Ji,J!-1Li!$M)%F!!`!HD!2!!b"(3(`N)q!AB!0J$@LL"$%""d!"3!,8,
-rr(!!-!%d"A)!-J,3JHD!FJ+`J@F-FJ'`J@FJ5S"R0'!b0!Cb!$)#9)(5LL""%K"
-`!"!"FK$MU)'Zrr`d"R)!-J*5JG++)%%5%(!!%!(KL)'Zrr`J,[rm0!Gb!$)#iUJ
-Y32rmF2pb)$B&G!!d!j+#iUM!E[rq60m%q%jH6R919[rB51FI1#CZ!!JSEJ!1)$`
-!!!%NdDi!%L!m!!!#50'Z!")J,J!5,8$rl()Jdki!%L)Z!")Y3Ir`*$`!N!1!eDi
-!%L3Z!")Y3[rd*%XB%RB!&J3Y3rrijS0k"mC&8N-p3rrF*Llrq1+$HJ2'494$282
-rjRB"1LlrjZYM282rk(j!b!Gm!"`%28EriRJ"kf464$e%rq!U,[riIJ(+KfF)HJ!
-k"&1&B!*krce&rpji#$e%rq4+4QG',bi!%Lm!2`055Lm+6VVr1Nr[!!lR30&Zrq3
-[,J!5,blrm$m$,blrl%kk#`K2l`!1,blrp$m$,blrl#mZrr"1Z[bX6qm!$N*!28$
-rf$!ZrpL`EJ!-C!!"1M!Zrq*R1L4!2blrk#mZrr3r,[rN,`Y1Z[f16qm!$")!)!T
-`!"!"28$rfR3!0!$8V[rX)%)3%()!%J$6E[rNB"`r,[rQ2blrj#m,6VVpm&"228$
-rfM!ZrqE4E[rN-#lrfV"ZrpjQ&M)ZrpK5E[rBF!!`!G#-)%"#%'!!rhS`,[rDX'l
-ri'B!!*3`,[rLCcSN3$mZrqJ[,[rd2blrj#m,6VVp"Nr[!!`5!#!+F!!3!6e!rpT
-d!$3!e+lrl#"#%""b!")!dflrj'!F2blrjMmZrq3[#dkkr@K36ce!rpS`,[rQd@l
-rj&CZrpS`,[rD8flrfNT!C`$r!$JZrpKf!$B%,82rr&1$eS`J3a!3)Llrr0+-)%%
-3J&*ZrpKJcK!Zrph3,[rE0#lrf&*ZrpKb!$)#dS`J34#!B!$q[M)Zrq4`!$!"AS$
-QJ%cI(2K1ANje6PErM%MR(cJQEJ!)+Li!$#KZ!"!X,J!8,8[rb(!Nem!Y5rrJF#$
-A`#e,rma`50I!,8[rj#e-rj3Q2!!!!56AV[q8)$`!!!*)dDlrP(!JdDlrP#Jm!*!
-$J0QZrj6CV[q8,@lrP2qd+$`!!!53!0QZrj3YE[q8rlMAV[q8,@lrP2qmfDlrP#e
-Zrj6re("mdDlrP#eZrj6rT#!m!!#!!0'Zrj3J,[q8N!#-X)9M#R"P28!!+%lk"RT
-`!#i!3N!p32q-*'lrT0Am!!#!!#e+rkJYE[qNrj!!,A`!!)!!rqK)E[rS,blrT#"
-Z!#41N!"36b!ZrqKQ#R"R28!!+%lk"M3NE[q3!&*+YHlrU'0S)'lrN!"55*(ZrkJ
-Y52rd)'lrN!#4l[qN,8Mrm#"ZrkL4l[q3!#e)rq`J#'F1)'lrN!!LE[qN)#lrl+)
-Z*'lrT0AZrq`Y5[q3!%KZrr![,[qN)'i!*%k3!&"2)#lrm,#Zrr4N#R"R28!!+%l
-k"F!JE[q3!&+Zrj!!%"!G32qJFJ!5!0*"8d%p3Ir3-#lrd0"!28$rdL"Z!"`J%0#
-Z!#!Y32q`*%![$#mZrlJr2!%N,blrN!"1Z[[b6qm!$M)!)!T`!$!"dDlrN!![$#m
-Zrl3r2!%N,blrZ%kk"lT2l`!1,blr[$mm!53[,[qi,blrY%kkq9a2l`!1*%![$#m
-ZrlJr,[r3,blrN!"1Z[ZJ6qm!$M)!)!T`!$!"dDlrN!![$#mZrl3r,[r3,blrZ%k
-k"fK2l`!1,blre$mZrp![,[qi,blrY%kkq3T2l`!1F!!Z!%*!28$rM#eZ!#$rV#"
-Zrkbal[q`C!!%U%*!28$rQ!aZ!NMrQ'3!!-)`,[q-CJ!!M#4Zrj!!8NUel[qSBfJ
-JE[q3!&*)NHlrU#e)rr3JE[q3!*(Zrk3Y52r`)'lrU*(Zrj!!,8Mrl#!)C`iJE[q
-3!#*Zrk3J,[rXSLiNE[qNeHlrl#e+rj!!5'lrm#mZrk3JEJ!N6T!!8%mJ,[r`X+l
-rp'3+F'Fp3!!S6[S%3L"Zrj!!8UlrN!!5%(!!%!%Z!(!)28$rM$!(FJ(!3G&ZrjJ
-b,[qBF!!`!G#!d+lr[#"!-"!p32qB)!ILL#i!8flrM'!!rcJ%EJ*)rjJ-EJ%!rjK
-N%#"Zrka5V[qX%+lrQ@!!r`J%EJ%!rjJi,[qBGJ!f"#e$rrM@JpDZrm`J3c!328$
-rQL)ZrrM5V[r))%%5%(!!%!%p32qF5N"R!!$#$'i!'2q-BJ!!Q#4Zrj!!8NUel[q
-SBfJJE[q3!&*)NHlrU#e)rr3JE[q3!*(Zrk3Y52r`)'lrU*(Zrj!!,8Mrl#!)C`i
-JE[q3!#*Zrk3J,[rXSLiNE[qNeHlrl#e+rj!!5'lrm#mZrk3JEJ!N6T!!8%mJ,[r
-`X+lrp'3+F'Fp3!!S6[S$+#"Zrj!!8UlrN!!5%(!!%!%d,[q-FJ!b!Z1SMS"3E[q
--B!$rBR$rFL!i,[qFGJ!f"*+$iUM!4p&ZrjSJ"qDS,J#CE[q-3N!p32qB-#lrQ,"
-Zrp*N!!$#-#lrM'B!!)`NE[q3!&*+YHlrU'0S)'lrN!"55*(ZrkJY52rd)'lrN!#
-4l[qN,8Mrm#"ZrkL4l[q3!#e)rq`J#'F1)'lrN!!LE[qN)#lrl+)Z*'lrT0AZrq`
-Y5[q3!%KZrr![,[qN)'i!*%k3!&"2)#lrm,#Zrr4N#R"R28!!+%lk!PJJE[q3!&+
-Zrj!!%K"`!"!",J"`#$e!ri``"h)"`%(4E[qB-LlrQ(!!-!(3J0#Zrp3J3$!328$
-rQ#!(iSJZ!&0ZriaJ!2mf-#lrdT&ZrjJi,[qBGJ!f"#e$rrc@JpDZrq3J3c!328$
-rRL)Zrrc5V[rJ)%%5%(!!%!%p32qF5N"R!!$#$'i!'2q-BJ!!Q#4Zrj!!8NUel[q
-SBfJJE[q3!&*)NHlrU#e)rr3JE[q3!*(Zrk3Y52r`)'lrU*(Zrj!!,8Mrl#!)C`i
-JE[q3!#*Zrk3J,[rXSLiNE[qNeHlrl#e+rj!!5'lrm#mZrk3JEJ!N6T!!8%mJ,[r
-`X+lrp'3+F'Fp3!!S6[S"@L"Zrj!!8UlrN!!5%(!!%!%d,[q-FJ!b!Z1SMS"3E[q
--B!$rBR$rFL!i,[qFGJ!f"*+$iUM!4p&ZrjiJ"qDS,J#CE[q-)'lrV$)Zrjj`!$!
-"NF!Y52q8XHi!)'9J)'lrP&+Zrj33%#"Zrka5V[qX%)!JE[q88UlrP"!3)'lrV&+
-Zrk`3J#"Zrj45V[q8%"!JE[qX8UlrV"#!-#lrQP0ZrjT+3'F!qpiJE[q88UlrP"!
-3)'lrV&+Zrk`3J'$F9QlrQL"Z!"M4aM)Zrjj`!$!")QlrV*2Z!##3!)Q4`#e)rj3
-`,[qDCbBJEJ!BdFDal[q8BaSJE[q88UlrP"!3)'lrV&+Zrk`3J&0ZrjTJe#eZ!#$
-rP$!ZrjT6E[qD5N"R!2YQ)'lrP&+Zrj33%#"Zrka5V[qX%)"Jh#"Zrkbal[q`C`K
-`Cce!!#KJ&#"Zrkb4lJ!J)Qi!(#+)3N!p3!!S60mFq%jH)&p2l`!J6Y!!F$`!2L!
-!!(JJ2M!J*LBJH#!m26-b!!!k3fpYF(*PFh0TEfik4'9MEfe`FQ9cFfP[EM!c-$%
-ZB`!!2!!q)!!!H#!q-#!Q*L"i)$`p-c)!!$T$Efe`FQ9cFfP[EMT%C@0[EA"bCA0
-cD@pZ-$-`-5jM!!"19[rS51FI1$iZ!!JSEJ!-0Li!#R!!-!-i"h)!-J53!)&b!E#
-"E`!"Y$e%rqJp3rrU8Qlrk$!ZrqL`EJ!+C"ab!$)!dS`J34!30!Gb!$)#dS`J34)
-3X!&N!Q$@8flrkM!ZrqU`4f-FFJ!b!0+-)%%3%$3(FJ!b!Y+-)%%5%,!"B`*Jf$!
-ZrqL`E[rUC3*JFMJZrqKf!$B%,82rm0D-*%-5%R!!%!%p32rX1LlrkRJ!1!8Y42r
-df)`Q4"!6&)!@V[rY)#lrm0#!d+i!%#"!-"!p32rX)Llrp0+"dUi!%#""-K!N,[r
-`e),8VJ!3)%)`J5)Zrr65JG+Z!"!J36#!B!$r-M!ZrqU`4fB'8NGJ!2m%1!Gf!$B
-%,82rq0D-*%-5%R!!%!%p32rX2#lrkRS!1JBY4IrmfS`Q44!6&)!@V[rY)#lrq0#
-!d+i!%#"!-"!p32rX)Llrr0+"dUi!%#""-K!N,[rie),8VJ!3)%)`J5)Zrrc5JG+
-Z!"!J36#!)#lrr#)ZrrL3!)%d,J!+FJ!b!L3Zrra5JT+#X)&X(LmZ!"![$$m'2`4
-1Z[jF6qm!$$!ZrqT53$i!B!$qA#mZ!"![$$mZ!!S`,[rU8N!r!%kkrMC2l`!-2@l
-rkJ!+B!$q1%cI(2K1ANje6PErj%MR(cJNEJ!)1Li!$#CZ!!iSEJ!5,8crm#!m!!!
-"*0R!,8crp%*!2!!f"VC&C#ai!$J$,86rq0L+)%33%#)ZrrM5V[r`)%%3J#!ZrrM
-3J0#Zrr3J3$#$8NCJcLmZrr3[,[r`2`9#CdkkrE*2l`!-3N!m!$B'YN9N%R!!-!2
-3V[r`)%"+%'B%8NCJk(!!,8$rj$B'YN9N!!#S5N0R-L!Zrq4i!$J$,86rr0LZrr!
-J4"33FJ!5!LBZrra6JpDZrr!J3aB3G!!8!j+#ikJY32rN0!Cb!$)#dUlrm#""%K"
-`!"!"2J!YE[rNrqa`!#e!rqJ`"e0(5N"R)#!ZrqMML#)Zrqad!F+#J)%Y32rS)#l
-rl1+),8$rl'$B0!Cb!$)#dS(5V[rd)%%b%(!!-!(PJ0#,)%!JV[rS8NC5V[rNB!$
-r9%cI(2K1ANje)PmJAk!P,S"U!N+A6Y%LAa)I-"p+!@F%TdCJ!U0',SK1d5*I%Km
-`(b"I5J&R"+C(B!+L4dl4!*!$#J!iS!%!"3#3"J%!!!'253!"MNN!!!4X8dp59!,
-U!)!!(!25!"4"6&*8!!S!UN&9Fc)!!!%Z3Nj%6!!"!6T$6d4&!!F"8N4"9%%!!!'
-b4%P86!!0!Ej%6%p(!!)#CNC548B!"!++4Q9KG!!!!XC*3diM!!3#dNP$6di!!!-
-18%P$9!!!!aT3Ff9d!!!$*P0*@N8!!!-b8e45)!!"!cj69&)M!!!$9Q&eFh3!!30
-LBfPMEJ!!!hTTBf`i!!!$KQYTEQ3!!!15GQ9bF`!"!ji!J2rr)!!%X`#3"B(rrb!
-!"--!N!@#rrmJ!!4c!*!&KIrr*!!%J`cb!)J!K[rr*!!%S`c[mBJ!Krrr)!!%N`#
-3"BMrrb!!"0-!N!3#!2rr)!!%j3#3"!)"rrmJ!!6e!*!%"!(rrb!!"'-!N!3%Vrr
-r!!!8(!#3"d!!!"R2!*!&J2rr!!!CP`#3"!%!rrm!!"Ph!*!'rrmS!A0Y!*!&!3"
-H(!!H9JcaX(J!!J"S(!#3!"m-mJ#3!`-!FK`!V$3-mE"J!!3!I"`!mk)-lr&X!!8
-!KK`"*5m-mJ!i!!B!N!!F!8K1$2)!#!!(rrm!!A2*!*!'rrmS!'!B!*!&J2rr!!!
-"T`#3"B,rr`!!!RF!N!@&rrmN!!#!$1e0Q!#'rrmN!!%Q$1e0`!#(rrm!N!2@!*!
-&L2rr!!!$!3#3"EArrb!!!J8!N!3""`!d)!!6EJ#3"!)!rrm!!!2C!*!%!J(rr`!
-!""F!N!3$k2rr)!!#e3#3"!3"rrmJ!*!("%X!+!3!%Z!-mE"d"+rrr`!!%c!!N!3
-""`!F)!!4)`#3"!2SrrmJ!!PB!*!%"%X!%!3!%3S-mJ#S!)$rr`!!'8!!N!@"rrm
-!!"P,!*!&J[rr!!!C9J#3"B2rr`!!'@%!N!@%rrm!!"PX!*!'rrm!!Bil!*!&J2r
-r!!!8,!#3"B(rr`!!&6!!N!@#rrm!!"Bd!*!&Jrrr!!!A1!#3"B6rr`!!'$`!N!3
-%5rrr"!!5C3cb!*3$k2rr!!!*Y!#3"B$rr`!!"5%!N!6rN!3!!A1*!*!%!J#3!b!
-!"38!N!3#!3!()!!&&3#3"B$rr`!!#A3!N!G2!!!Cp`#3"B6rr`!!'I-!N!3%5rr
-r"!!42`cb!!`!K2rr!!!D8J#3"B$rr`!"FjF!N!8"rrmJ!"$i!*!&![rr)!!3fJ#
-3"!C`FQpYF(3)a#"cG@CQDAJ,5@jcCA*d)%4TFfX,4AKTFh4TEQFJ8&F,5@jcCA*
-d)%4TFfX,4AKTFh4TEQFJ8&F16hGZCA)JFQ9cEh9bBf816hGZCA)JFQ9cEh9bBf8
-*8f9RE@9ZG#!a#90PCfePER3J-JP6C@GYC@jd)$-*8f9RE@9ZG#!e#90PCfePER3
-J0JP6C@GYC@jd)$B(V`:
diff --git a/macosx/Makefile b/macosx/GNUmakefile
index 9f8f9b0..7d19fc6 100644
--- a/macosx/Makefile
+++ b/macosx/GNUmakefile
@@ -4,11 +4,10 @@
# uses the standard unix build system in tcl/unix (which can be used directly instead of this
# if you are not using the tk/macosx projects).
#
-# Copyright (c) 2002-2007 Daniel A. Steffen <das@users.sourceforge.net>
+# Copyright (c) 2002-2008 Daniel A. Steffen <das@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
-#
########################################################################################################
#-------------------------------------------------------------------------------------------------------
@@ -72,9 +71,13 @@ BUILD_STYLE =
CONFIGURE_ARGS =
OBJ_DIR = ${OBJROOT}/${BUILD_STYLE}
+empty :=
+space := ${empty} ${empty}
+objdir = $(subst ${space},\ ,${OBJ_DIR})
+
develop_make_args := BUILD_STYLE=Development CONFIGURE_ARGS=--enable-symbols
deploy_make_args := BUILD_STYLE=Deployment INSTALL_TARGET=install-strip \
- GENERIC_FLAGS=-DNDEBUG
+ EXTRA_CFLAGS=-DNDEBUG
embedded_make_args := EMBEDDED_BUILD=1
install_make_args := INSTALL_BUILD=1
@@ -116,31 +119,31 @@ install-${PROJECT}: target = ${INSTALL_TARGET}
clean-${PROJECT} distclean-${PROJECT} test-${PROJECT}: \
target = $*
-DO_MAKE = +${MAKE} -C ${OBJ_DIR} ${target} ${MAKE_ARGS_V} ${MAKE_ARGS} ${EXTRA_MAKE_ARGS}
+DO_MAKE = +${MAKE} -C "${OBJ_DIR}" ${target} ${MAKE_ARGS_V} ${MAKE_ARGS} ${EXTRA_MAKE_ARGS}
#-------------------------------------------------------------------------------------------------------
# build rules
${PROJECT}:
- ${MAKE} install-${PROJECT} INSTALL_ROOT=${OBJ_DIR}/
+ ${MAKE} install-${PROJECT} INSTALL_ROOT="${OBJ_DIR}/"
-${OBJ_DIR}/Makefile: ${UNIX_DIR}/Makefile.in ${UNIX_DIR}/configure \
+${objdir}/Makefile: ${UNIX_DIR}/Makefile.in ${UNIX_DIR}/configure \
${UNIX_DIR}/tclConfig.sh.in Tcl-Info.plist.in
- mkdir -p ${OBJ_DIR} && cd ${OBJ_DIR} && \
- if [ ${UNIX_DIR}/configure -nt config.status ]; then ${UNIX_DIR}/configure \
- --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} \
- --mandir=${MANDIR} --enable-threads --enable-framework --enable-dtrace \
+ mkdir -p "${OBJ_DIR}" && cd "${OBJ_DIR}" && \
+ if [ ${UNIX_DIR}/configure -nt config.status ]; then ${UNIX_DIR}/configure -C \
+ --prefix="${PREFIX}" --bindir="${BINDIR}" --libdir="${LIBDIR}" \
+ --mandir="${MANDIR}" --enable-threads --enable-framework --enable-dtrace \
${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS}; else ./config.status; fi
-build-${PROJECT}: ${OBJ_DIR}/Makefile
+build-${PROJECT}: ${objdir}/Makefile
${DO_MAKE}
ifeq (${INSTALL_BUILD},)
# symolic link hackery to trick
# 'make install INSTALL_ROOT=${OBJ_DIR}'
# into building Tcl.framework and tclsh in ${SYMROOT}
- @cd ${OBJ_DIR} && mkdir -p $(dir ./${LIBDIR}) $(dir ./${BINDIR}) ${SYMROOT} && \
- rm -f ./${LIBDIR} ./${BINDIR} && ln -fs ${SYMROOT} ./${LIBDIR} && \
- ln -fs ${SYMROOT} ./${BINDIR} && ln -fs ${OBJ_DIR}/tcltest ${SYMROOT}
+ @cd "${OBJ_DIR}" && mkdir -p $(dir $(subst ${space},\ ,./${LIBDIR})) $(dir $(subst ${space},\ ,./${BINDIR})) "${SYMROOT}" && \
+ rm -f "./${LIBDIR}" "./${BINDIR}" && ln -fs "${SYMROOT}" "./${LIBDIR}" && \
+ ln -fs "${SYMROOT}" "./${BINDIR}" && ln -fs "${OBJ_DIR}/tcltest" "${SYMROOT}"
endif
install-${PROJECT}: build-${PROJECT}
@@ -169,7 +172,7 @@ else
if [ -n "$${RM_USRLIB:-}" ]; then rm -f usr/lib; rmdir -p usr 2>&-; fi; \
if [ -n "$${RM_SYSTEM:-}" ]; then rm -f System; fi; fi
# install tclsh symbolic link
- @ln -fs ${TCLSH} ${INSTALL_ROOT}${BINDIR}/tclsh
+ @ln -fs ${TCLSH} "${INSTALL_ROOT}${BINDIR}/tclsh"
endif
endif
ifeq (${BUILD_STYLE}_${EMBEDDED_BUILD},Development_)
@@ -177,20 +180,20 @@ ifeq (${BUILD_STYLE}_${EMBEDDED_BUILD},Development_)
# Deployment build can be installed on top
# of Development build without overwriting
# the debug library
- @cd ${INSTALL_ROOT}${LIBDIR}/${PRODUCT_NAME}.framework/Versions/${VERSION} && \
+ @cd "${INSTALL_ROOT}${LIBDIR}/${PRODUCT_NAME}.framework/Versions/${VERSION}" && \
ln -f "${PRODUCT_NAME}" "${PRODUCT_NAME}_debug"
endif
clean-${PROJECT}: %-${PROJECT}:
${DO_MAKE}
- rm -rf ${SYMROOT}/{${PRODUCT_NAME}.framework,${TCLSH},tcltest}
- rm -f ${OBJ_DIR}{${LIBDIR},${BINDIR}} && \
- rmdir -p ${OBJ_DIR}$(dir ${LIBDIR}) 2>&- || true && \
- rmdir -p ${OBJ_DIR}$(dir ${BINDIR}) 2>&- || true
+ rm -rf "${SYMROOT}"/{${PRODUCT_NAME}.framework,${TCLSH},tcltest}
+ rm -f "${OBJ_DIR}"{"${LIBDIR}","${BINDIR}"} && \
+ rmdir -p "${OBJ_DIR}"$(dir $(subst ${space},\ ,${LIBDIR})) 2>&- || true && \
+ rmdir -p "${OBJ_DIR}"$(dir $(subst ${space},\ ,${BINDIR})) 2>&- || true
distclean-${PROJECT}: %-${PROJECT}: clean-${PROJECT}
${DO_MAKE}
- rm -rf ${OBJ_DIR}
+ rm -rf "${OBJ_DIR}"
test-${PROJECT}: %-${PROJECT}: build-${PROJECT}
${DO_MAKE}
diff --git a/macosx/README b/macosx/README
index 7c19f9c..80bed14 100644
--- a/macosx/README
+++ b/macosx/README
@@ -50,10 +50,10 @@ the Resources/Scripts directory of the framework.
and bundles are also loaded more efficiently from VFS (no temporary copy to the
native filesystem required).
-- The 'deploy' target of macosx/Makefile installs the html manpages into the
+- The 'deploy' target of macosx/GNUmakefile installs the html manpages into the
standard documentation location in the Tcl framework:
Tcl.framework/Resources/Documentation/Reference/Tcl
-No nroff manpages are installed by default by the Makefile.
+No nroff manpages are installed by default by the GNUmakefile.
- The Tcl framework can be installed in any of the system's standard
framework directories:
@@ -71,18 +71,71 @@ or is present in /Applications/Installers on Macs that came with OS X
preinstalled. The most recent version can be downloaded from the ADC website
http://connect.apple.com (after you register for free ADC membership).
-- Tcl is most easily built as a Mac OS X framework via Makefile in tcl/macosx
+- Tcl is most easily built as a Mac OS X framework via GNUmakefile in tcl/macosx
(see below for details), but can also be built with the standard unix configure
and make buildsystem in tcl/unix as on any other unix platform (indeed, the
-Makefile is just a wrapper around the unix buildsystem).
+GNUmakefile is just a wrapper around the unix buildsystem).
The Mac OS X specific configure flags are --enable-framework and
--disable-corefoundation (which disables CF and notably reverts to the standard
select based notifier).
-- It is also possible to build with Apple's IDE via the tcl/macosx/Tcl.pbproj
-project, this simply calls through to the tcl/macosx/Makefile.
-
-- To build universal binaries, set CFLAGS as follows:
+- It is also possible to build with Apple's IDE via the projects in tcl/macosx,
+take care to only use the project matching your DevTools and OS version:
+ * Tcl.pbproj for Xcode or ProjectBuilder on 10.3 and earlier, this has a
+ 'Tcl' target that simply calls through to the tcl/macosx/GNUMakefile.
+ * Tcl.xcode for Xcode 2.4 on 10.4 and Xcode 2.5 on 10.4 and later, which
+ additionally has native 'tcltest' and 'tests' targets for debugging and
+ running the testsuite, these targets' 'Debug' build configuration has
+ ZeroLink and Fix&Continue enabled, use the 'DebugNoFixZL' build
+ configuration if you need a debug build without these features. The
+ following build configurations are available:
+ 'DebugUnthreaded': debug build with threading turned off.
+ 'DebugNoCF': debug build with corefoundation turned off.
+ 'DebugNoCFUnthreaded': debug build with corefoundation & threading off.
+ 'DebugMemCompile': debug build with memory and bytecode debugging on.
+ 'DebugLeaks': debug build with PURIFY defined.
+ 'DebugGCov': debug build with generation of gcov data files enabled.
+ 'Debug64bit': builds the targets as 64bit with debugging enabled,
+ requires a 64bit capable processor (i.e. G5 or Core2/Xeon).
+ 'ReleaseUniversal': builds the targets as universal binaries for the
+ ppc, ppc64, i386 and x86_64 architectures.
+ 'ReleaseUniversal10.4uSDK': same as 'ReleaseUniversal' but builds
+ against the 10.4u SDK, required to build universal binaries on
+ PowerPC Tiger (where the system libraries are not universal).
+ 'ReleasePPC10.3.9SDK': builds for PowerPC against the 10.3.9 SDK, useful
+ for verifying on Tiger that building on Panther would succeed.
+ 'ReleasePPC10.2.8SDK': builds for PowerPC with gcc-3.3 against the
+ 10.2.8 SDK, useful to verify on Tiger that building on Jaguar
+ would succeed.
+ * Tcl.xcodeproj for Xcode 3.1 on 10.5 and later, which has the following
+ additional build configurations:
+ 'ReleaseUniversal10.5SDK': same as 'ReleaseUniversal' but builds
+ against the 10.5 SDK on Leopard (with 10.5 deployment target).
+ 'Debug gcc42': same as 'Debug' but builds with gcc 4.2.
+ 'Debug llvmgcc42': same as 'Debug' but builds with llvm-gcc 4.2.
+ 'ReleaseUniversal gcc42': same as 'ReleaseUniversal' but builds with
+ gcc 4.2.
+ 'ReleaseUniversal llvmgcc42': same as 'ReleaseUniversal' but builds
+ with llvm-gcc 4.2.
+ Note that all non-SDK configurations have 10.5 deployment target.
+
+Notes about the native targets of the Xcode projects:
+ * the Xcode projects refer to the toplevel tcl source directory through the
+ TCL_SRCROOT user build setting, by default this is set to the
+ project-relative path '../../tcl', if your tcl source directory is named
+ differently, e.g. '../../tcl8.5', you'll need to manually change the
+ TCL_SRCROOT setting by editing your ${USER}.pbxuser file (located inside
+ the Tcl.xcodeproj bundle directory) with a text editor.
+ * the native targets need a version of the unix configure script with config
+ headers enabled, this is automatically generated as tcl/macosx/configure
+ by the project but that requires 2.59 versions of autoconf & autoheader.
+ These are not available on Mac OS X 10.5 by default and need to be
+ installed manually. By default they are assumed to be installed as
+ /usr/local/bin/autoconf-2.59 and /usr/local/bin/autoheader-2.59, set the
+ AUTOCONF and AUTOHEADER build settings in ${USER}.pbxuser to their true
+ locations if necessary.
+
+- To build universal binaries outside of Tcl.xcodeproj, set CFLAGS as follows:
export CFLAGS="-arch ppc -arch ppc64 -arch i386 -arch x86_64 \
-isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4"
This requires Mac OS X 10.4 and Xcode 2.4 (or Xcode 2.2 if -arch x86_64 is
@@ -100,10 +153,12 @@ to the minimal OS version (>= 10.2) the binaries should be able to run on, e.g:
This requires Mac OS X 10.2 and gcc 3.1; if you have gcc 4 or later you can set
CFLAGS instead:
export CFLAGS="-mmacosx-version-min=10.2"
+The Tcl.xcode project is setup to produce binaries that can run on 10.2 or
+later (except for the Universal and SDK configurations).
Support for weak-linking was added to the code for 8.4.14/8.5a5.
-Detailed Instructions for building with macosx/Makefile
--------------------------------------------------------
+Detailed Instructions for building with macosx/GNUmakefile
+----------------------------------------------------------
- Unpack the tcl source release archive.
diff --git a/macosx/Tcl-Common.xcconfig b/macosx/Tcl-Common.xcconfig
new file mode 100644
index 0000000..b711d36
--- /dev/null
+++ b/macosx/Tcl-Common.xcconfig
@@ -0,0 +1,40 @@
+//
+// Tcl-Common.xcconfig --
+//
+// This file contains the Xcode build settings comon to all
+// project configurations in Tcl.xcodeproj.
+//
+// Copyright (c) 2007-2008 Daniel A. Steffen <das@users.sourceforge.net>
+//
+// See the file "license.terms" for information on usage and redistribution
+// of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+HEADER_SEARCH_PATHS = "$(DERIVED_FILE_DIR)/tcl" $(HEADER_SEARCH_PATHS)
+OTHER_LDFLAGS = -headerpad_max_install_names -sectcreate __TEXT __info_plist "$(DERIVED_FILE_DIR)/tcl/Tclsh-Info.plist" $(OTHER_LDFLAGS)
+INSTALL_PATH = $(BINDIR)
+INSTALL_MODE_FLAG = go-w,a+rX
+GCC_PREFIX_HEADER = $(DERIVED_FILE_DIR)/tcl/tclConfig.h
+GCC_GENERATE_DEBUGGING_SYMBOLS = YES
+GCC_NO_COMMON_BLOCKS = YES
+GCC_DYNAMIC_NO_PIC = YES
+GCC = $(DEVELOPER_DIR)/usr/bin/gcc
+GCC_VERSION = 4.0
+CC = $(GCC)-$(GCC_VERSION)
+LD = $(CC)
+WARNING_CFLAGS_GCC3 = -Wall -Wno-implicit-int -Wno-unused-parameter -Wno-deprecated-declarations
+WARNING_CFLAGS = -Wextra -Wno-missing-field-initializers -Winit-self -Wpointer-arith -Wcast-align -Wdisabled-optimization -Winline $(WARNING_CFLAGS_GCC3) $(WARNING_CFLAGS)
+BINDIR = $(PREFIX)/bin
+CFLAGS = $(CFLAGS)
+CPPFLAGS = -mmacosx-version-min=$(MACOSX_DEPLOYMENT_TARGET) $(CPPFLAGS)
+FRAMEWORK_INSTALL_PATH = /Library/Frameworks
+INCLUDEDIR = $(PREFIX)/include
+LIBDIR = $(PREFIX)/lib
+MANDIR = $(PREFIX)/man
+PER_ARCH_CFLAGS_ppc = -mcpu=G3 -mtune=G4 $(PER_ARCH_CFLAGS_ppc)
+PER_ARCH_CFLAGS_ppc64 = -mcpu=G5 -mpowerpc64 $(PER_ARCH_CFLAGS_ppc64)
+PREFIX = /usr/local
+TCL_CONFIGURE_ARGS = --enable-threads --enable-dtrace
+TCL_LIBRARY = $(LIBDIR)/tcl$(VERSION)
+TCL_PACKAGE_PATH = "$(LIBDIR)"
+TCL_DEFS = HAVE_TCL_CONFIG_H
+VERSION = 8.5
diff --git a/macosx/Tcl-Debug.xcconfig b/macosx/Tcl-Debug.xcconfig
new file mode 100644
index 0000000..03d2b2d
--- /dev/null
+++ b/macosx/Tcl-Debug.xcconfig
@@ -0,0 +1,20 @@
+//
+// Tcl-Debug.xcconfig --
+//
+// This file contains the Xcode build settings for all Debug
+// project configurations in Tcl.xcodeproj.
+//
+// Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
+//
+// See the file "license.terms" for information on usage and redistribution
+// of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+#include "Tcl-Common.xcconfig"
+
+DEBUG_INFORMATION_FORMAT = dwarf
+DEAD_CODE_STRIPPING = NO
+DEPLOYMENT_POSTPROCESSING = NO
+GCC_OPTIMIZATION_LEVEL = 0
+GCC_PREPROCESSOR_DEFINITIONS = $(TCL_DEFS) $(GCC_PREPROCESSOR_DEFINITIONS)
+CONFIGURE_ARGS = --enable-symbols $(TCL_CONFIGURE_ARGS) $(CONFIGURE_ARGS)
+MAKE_TARGET = develop
diff --git a/macosx/Tcl-Info.plist.in b/macosx/Tcl-Info.plist.in
index 871b7a4..f5c6b15 100644
--- a/macosx/Tcl-Info.plist.in
+++ b/macosx/Tcl-Info.plist.in
@@ -14,10 +14,10 @@
<string>@TCL_LIB_FILE@</string>
<key>CFBundleGetInfoString</key>
<string>Tcl @TCL_VERSION@@TCL_PATCH_LEVEL@,
-Copyright © @TCL_YEAR@ Tcl Core Team,
+Copyright © 1987-@TCL_YEAR@ Tcl Core Team,
Copyright © 2001-@TCL_YEAR@ Daniel A. Steffen,
-Initial MacOS X Port by Jim Ingham &amp; Ian Reid,
-Copyright © 2001-2002, Apple Computer, Inc.</string>
+Copyright © 2001-2009 Apple Inc.,
+Copyright © 2001-2002 Jim Ingham &amp; Ian Reid</string>
<key>CFBundleIdentifier</key>
<string>com.tcltk.tcllibrary</string>
<key>CFBundleInfoDictionaryVersion</key>
diff --git a/macosx/Tcl-Release.xcconfig b/macosx/Tcl-Release.xcconfig
new file mode 100644
index 0000000..d960a52
--- /dev/null
+++ b/macosx/Tcl-Release.xcconfig
@@ -0,0 +1,20 @@
+//
+// Tcl-Release.xcconfig --
+//
+// This file contains the Xcode build settings for all Release
+// project configurations in Tcl.xcodeproj.
+//
+// Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
+//
+// See the file "license.terms" for information on usage and redistribution
+// of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+#include "Tcl-Common.xcconfig"
+
+DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
+DEAD_CODE_STRIPPING = YES
+DEPLOYMENT_POSTPROCESSING = YES
+GCC_OPTIMIZATION_LEVEL = s
+GCC_PREPROCESSOR_DEFINITIONS = NDEBUG $(TCL_DEFS) $(GCC_PREPROCESSOR_DEFINITIONS)
+CONFIGURE_ARGS = --disable-symbols $(TCL_CONFIGURE_ARGS) $(CONFIGURE_ARGS)
+MAKE_TARGET = deploy
diff --git a/macosx/Tcl.pbproj/default.pbxuser b/macosx/Tcl.pbproj/default.pbxuser
index 22035d0..2472114 100644
--- a/macosx/Tcl.pbproj/default.pbxuser
+++ b/macosx/Tcl.pbproj/default.pbxuser
@@ -144,7 +144,7 @@
F98F02E608E7EF9A00D0320A = {
isa = PBXFileReference;
lastKnownFileType = "compiled.mach-o.executable";
- path = tclsh8.4;
+ path = tclsh8.5;
refType = 3;
sourceTree = BUILT_PRODUCTS_DIR;
};
diff --git a/macosx/Tcl.pbproj/jingham.pbxuser b/macosx/Tcl.pbproj/jingham.pbxuser
index 22035d0..2472114 100644
--- a/macosx/Tcl.pbproj/jingham.pbxuser
+++ b/macosx/Tcl.pbproj/jingham.pbxuser
@@ -144,7 +144,7 @@
F98F02E608E7EF9A00D0320A = {
isa = PBXFileReference;
lastKnownFileType = "compiled.mach-o.executable";
- path = tclsh8.4;
+ path = tclsh8.5;
refType = 3;
sourceTree = BUILT_PRODUCTS_DIR;
};
diff --git a/macosx/Tcl.pbproj/project.pbxproj b/macosx/Tcl.pbproj/project.pbxproj
index 7949108..8cd58dc 100644
--- a/macosx/Tcl.pbproj/project.pbxproj
+++ b/macosx/Tcl.pbproj/project.pbxproj
@@ -62,11 +62,12 @@
sourceTree = "<group>";
};
00E2F84C016E8B780ACA28DC = {
- buildArgumentsString = "-c \"cd \\\"${TCL_SRCROOT}/macosx\\\" && ACTION=${ACTION} && gnumake \\${ACTION:+\\${ACTION/clean/distclean}-}${MAKE_TARGET} INSTALL_ROOT=\\\"${DSTROOT}\\\" INSTALL_PATH=\\\"${INSTALL_PATH}\\\" PREFIX=\\\"${PREFIX}\\\" BINDIR=\\\"${BINDIR}\\\" MANDIR=\\\"${MANDIR}\\\" \\${EXTRA_MAKE_FLAGS} ${ALL_SETTINGS}\"";
+ buildArgumentsString = "-c \"cd \\\"${TCL_SRCROOT}/macosx\\\" && ACTION=${ACTION} && CFLAGS=\\\"${CFLAGS}\\\" gnumake \\${ACTION:+\\${ACTION/clean/distclean}-}${MAKE_TARGET} INSTALL_ROOT=\\\"${DSTROOT}\\\" INSTALL_PATH=\\\"${INSTALL_PATH}\\\" PREFIX=\\\"${PREFIX}\\\" BINDIR=\\\"${BINDIR}\\\" MANDIR=\\\"${MANDIR}\\\" \\${EXTRA_MAKE_FLAGS} ${ALL_SETTINGS}\"";
buildPhases = (
);
buildSettings = {
BINDIR = "${PREFIX}/bin";
+ CFLAGS = "";
INSTALL_PATH = /Library/Frameworks;
MANDIR = "${PREFIX}/man";
PREFIX = /usr/local;
@@ -137,6 +138,7 @@
F5F24FB8016ECAFC01DC9062,
F5F24FB9016ECAFC01DC9062,
F5F24FBA016ECAFC01DC9062,
+ F9FED5C7047C7D1B006F146B,
F5F24FBB016ECAFC01DC9062,
F5F24FD3016ECB4901DC9062,
F5F24FBC016ECAFC01DC9062,
@@ -185,12 +187,10 @@
F5F24F6E016ECAA401DC9062,
F5F24F6F016ECAA401DC9062,
F5F24F70016ECAA401DC9062,
- F5F24F71016ECAA401DC9062,
F5F24F72016ECAA401DC9062,
F5F24F73016ECAA401DC9062,
F5F24F74016ECAA401DC9062,
F5F24F75016ECAA401DC9062,
- F5F24F76016ECAA401DC9062,
F5F24F77016ECAA401DC9062,
F5F24F78016ECAA401DC9062,
F5F24FD1016ECB1E01DC9062,
@@ -222,6 +222,7 @@
00E2F859016E92B00ACA28DC = {
children = (
F5A1836F018242A501DC9062,
+ F9FED5C6047C7CEC006F146B,
);
isa = PBXGroup;
name = Sources;
@@ -330,7 +331,7 @@
F53ACC5C031D9D11016F146B = {
isa = PBXFileReference;
lastKnownFileType = "compiled.mach-o.executable";
- path = tclsh8.4;
+ path = tclsh8.5;
refType = 3;
sourceTree = BUILT_PRODUCTS_DIR;
};
@@ -438,15 +439,6 @@
refType = 2;
sourceTree = SOURCE_ROOT;
};
- F5F24F71016ECAA401DC9062 = {
- fileEncoding = 5;
- isa = PBXFileReference;
- lastKnownFileType = sourcecode.c.h;
- name = tclInitScript.h;
- path = ../generic/tclInitScript.h;
- refType = 2;
- sourceTree = SOURCE_ROOT;
- };
F5F24F72016ECAA401DC9062 = {
fileEncoding = 5;
isa = PBXFileReference;
@@ -483,15 +475,6 @@
refType = 2;
sourceTree = SOURCE_ROOT;
};
- F5F24F76016ECAA401DC9062 = {
- fileEncoding = 5;
- isa = PBXFileReference;
- lastKnownFileType = sourcecode.c.h;
- name = tclMath.h;
- path = ../generic/tclMath.h;
- refType = 2;
- sourceTree = SOURCE_ROOT;
- };
F5F24F77016ECAA401DC9062 = {
fileEncoding = 5;
isa = PBXFileReference;
@@ -1365,7 +1348,6 @@
F5F24FF5016ED0DF01DC9062,
F5F24FF6016ED0DF01DC9062,
F5F24FFA016ED0DF01DC9062,
- F5F24FFB016ED0DF01DC9062,
F5F24FFC016ED0DF01DC9062,
F5F24FFE016ED0DF01DC9062,
F5F25001016ED0DF01DC9062,
@@ -1441,14 +1423,6 @@
refType = 2;
sourceTree = SOURCE_ROOT;
};
- F5F24FFB016ED0DF01DC9062 = {
- isa = PBXFileReference;
- lastKnownFileType = text;
- name = ldAout.tcl;
- path = ../library/ldAout.tcl;
- refType = 2;
- sourceTree = SOURCE_ROOT;
- };
F5F24FFC016ED0DF01DC9062 = {
includeInIndex = 0;
isa = PBXFileReference;
@@ -1543,6 +1517,23 @@
refType = 3;
sourceTree = BUILT_PRODUCTS_DIR;
};
+ F9FED5C6047C7CEC006F146B = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = tclMacOSXFCmd.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ F9FED5C7047C7D1B006F146B = {
+ fileEncoding = 5;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ name = tclPathObj.c;
+ path = ../generic/tclPathObj.c;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
};
rootObject = 00E2F845016E82EB0ACA28DC;
}
diff --git a/macosx/Tcl.xcode/default.pbxuser b/macosx/Tcl.xcode/default.pbxuser
new file mode 100644
index 0000000..5c67540
--- /dev/null
+++ b/macosx/Tcl.xcode/default.pbxuser
@@ -0,0 +1,198 @@
+// !$*UTF8*$!
+{
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ activeBuildConfigurationName = Debug;
+ activeExecutable = F9E61D1C090A4282002B3151 /* tclsh */;
+ activeTarget = F9E61D16090A3E94002B3151 /* Tcl */;
+ codeSenseManager = F944EB9D08F798180049FDD4 /* Code sense */;
+ executables = (
+ F9E61D1C090A4282002B3151 /* tclsh */,
+ F944EB8F08F798100049FDD4 /* tcltest */,
+ );
+ perUserDictionary = {
+ com.apple.ide.smrt.PBXUserSmartGroupsKey.Rev10 = <040b747970656473747265616d8103e88401408484840e4e534d757461626c654172726179008484074e534172726179008484084e534f626a65637400858401690192848484134e534d757461626c6544696374696f6e6172790084840c4e5344696374696f6e6172790095960792848484084e53537472696e67019584012b146162736f6c75746550617468546f42756e646c658692849a9a008692849a9a046e616d658692849a9a14496d706c656d656e746174696f6e2046696c65738692849a9a03636c7a8692849a9a1550425846696c656e616d65536d61727447726f75708692849a9a0b6465736372697074696f6e8692849a9a103c6e6f206465736372697074696f6e3e8692849a9a08676c6f62616c49448692849a9a183143433045413430303433353045463930303434343130428692849a9a195042585472616e7369656e744c6f636174696f6e4174546f708692849a9a06626f74746f6d8692849a9a0b707265666572656e63657386928497960892849a9a1250425850726f6a65637453636f70654b65798692849a9a035945538692849a9a05696d6167658692849a9a0b536d617274466f6c6465728692849a9a0763616e536176658692848484084e534e756d626572008484074e5356616c7565009584012a849696018692849a9a0572656765788692849a9a065c2e286329248692849a9a04726f6f748692849a9a093c50524f4a4543543e8692849a9a097265637572736976658692ad92849a9a0669734c656166869284ae9db096008692849a9a07666e6d617463688692849a9a0086868686>;
+ };
+ sourceControlManager = F944EB9C08F798180049FDD4 /* Source Control */;
+ userBuildSettings = {
+ GCC = "${DEVELOPER_DIR}/usr/bin/gcc";
+ SYMROOT = "${SRCROOT}/../../build/tcl";
+ TCL_SRCROOT = "${SRCROOT}/../../tcl";
+ };
+ };
+ 8DD76FA90486AB0100D96B5E /* tcltest */ = {
+ activeExec = 0;
+ executables = (
+ F944EB8F08F798100049FDD4 /* tcltest */,
+ );
+ };
+ F944EB8F08F798100049FDD4 /* tcltest */ = {
+ isa = PBXExecutable;
+ activeArgIndex = 2147483647;
+ activeArgIndices = (
+ NO,
+ NO,
+ NO,
+ );
+ argumentStrings = (
+ "${TCL_SRCROOT}/tests/all.tcl",
+ "-singleproc 1",
+ "-verbose \"bet\"",
+ );
+ autoAttachOnCrash = 1;
+ configStateDict = {
+ "PBXLSLaunchAction-0" = {
+ PBXLSLaunchAction = 0;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 2;
+ PBXLSLaunchStyle = 0;
+ class = PBXLSRunLaunchConfig;
+ displayName = "Executable Runner";
+ identifier = com.apple.Xcode.launch.runConfig;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ "PBXLSLaunchAction-1" = {
+ PBXLSLaunchAction = 1;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 2;
+ PBXLSLaunchStyle = 0;
+ class = PBXGDB_LaunchConfig;
+ displayName = GDB;
+ identifier = com.apple.Xcode.launch.GDBMI_Config;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ };
+ customDataFormattersEnabled = 1;
+ debuggerPlugin = GDBDebugging;
+ disassemblyDisplayState = 0;
+ dylibVariantSuffix = "";
+ enableDebugStr = 0;
+ environmentEntries = (
+ {
+ active = YES;
+ name = TCL_LIBRARY;
+ value = "${TCL_SRCROOT}/library";
+ },
+ {
+ active = YES;
+ name = TCLLIBPATH;
+ value = /Library/Tcl;
+ },
+ {
+ active = NO;
+ name = DYLD_PRINT_LIBRARIES;
+ },
+ {
+ active = NO;
+ name = MallocBadFreeAbort;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocLogFile;
+ value = /tmp/malloc.log;
+ },
+ {
+ active = NO;
+ name = MallocStackLogging;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocStackLoggingNoCompact;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocPreScribble;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocScribble;
+ value = 1;
+ },
+ );
+ executableSystemSymbolLevel = 0;
+ executableUserSymbolLevel = 0;
+ libgmallocEnabled = 0;
+ name = tcltest;
+ sourceDirectories = (
+ );
+ };
+ F944EB9C08F798180049FDD4 /* Source Control */ = {
+ isa = PBXSourceControlManager;
+ fallbackIsa = XCSourceControlManager;
+ isSCMEnabled = 0;
+ scmConfiguration = {
+ CVSToolPath = /usr/bin/cvs;
+ CVSUseSSH = NO;
+ SubversionToolPath = /usr/local/bin/svn;
+ };
+ scmType = scm.cvs;
+ };
+ F944EB9D08F798180049FDD4 /* Code sense */ = {
+ isa = PBXCodeSenseManager;
+ indexTemplatePath = "";
+ };
+ F97258A50A86873C00096C78 /* tests */ = {
+ activeExec = 0;
+ };
+ F9E61D16090A3E94002B3151 /* Tcl */ = {
+ activeExec = 0;
+ executables = (
+ F9E61D1C090A4282002B3151 /* tclsh */,
+ );
+ };
+ F9E61D1C090A4282002B3151 /* tclsh */ = {
+ isa = PBXExecutable;
+ activeArgIndex = 2147483647;
+ activeArgIndices = (
+ );
+ argumentStrings = (
+ );
+ autoAttachOnCrash = 1;
+ configStateDict = {
+ "PBXLSLaunchAction-0" = {
+ PBXLSLaunchAction = 0;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 2;
+ PBXLSLaunchStyle = 0;
+ class = PBXLSRunLaunchConfig;
+ displayName = "Executable Runner";
+ identifier = com.apple.Xcode.launch.runConfig;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ "PBXLSLaunchAction-1" = {
+ PBXLSLaunchAction = 1;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 2;
+ PBXLSLaunchStyle = 0;
+ class = PBXGDB_LaunchConfig;
+ displayName = GDB;
+ identifier = com.apple.Xcode.launch.GDBMI_Config;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ };
+ customDataFormattersEnabled = 1;
+ debuggerPlugin = GDBDebugging;
+ disassemblyDisplayState = 0;
+ dylibVariantSuffix = _debug;
+ enableDebugStr = 0;
+ environmentEntries = (
+ {
+ active = NO;
+ name = DYLD_PRINT_LIBRARIES;
+ },
+ );
+ executableSystemSymbolLevel = 0;
+ executableUserSymbolLevel = 0;
+ libgmallocEnabled = 0;
+ name = tclsh;
+ sourceDirectories = (
+ );
+ };
+}
diff --git a/macosx/Tcl.xcode/project.pbxproj b/macosx/Tcl.xcode/project.pbxproj
new file mode 100644
index 0000000..0153b26
--- /dev/null
+++ b/macosx/Tcl.xcode/project.pbxproj
@@ -0,0 +1,2792 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 42;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ F90509300913A72400327603 /* tclAppInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445508F272B9004A47F5 /* tclAppInit.c */; settings = {COMPILER_FLAGS = "-DTCL_TEST -DTCL_BUILDTIME_LIBRARY=\\\"$(TCL_SRCROOT)/library\\\""; }; };
+ F966C07508F2820D005CB29B /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F966C07408F2820D005CB29B /* CoreFoundation.framework */; };
+ F96D456F08F272BB004A47F5 /* regcomp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED008F272A7004A47F5 /* regcomp.c */; };
+ F96D457208F272BB004A47F5 /* regerror.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED308F272A7004A47F5 /* regerror.c */; };
+ F96D457508F272BB004A47F5 /* regexec.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED608F272A7004A47F5 /* regexec.c */; };
+ F96D457608F272BB004A47F5 /* regfree.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED708F272A7004A47F5 /* regfree.c */; };
+ F96D457B08F272BB004A47F5 /* tclAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDC08F272A7004A47F5 /* tclAlloc.c */; settings = {COMPILER_FLAGS = "-DUSE_TCLALLOC=0"; }; };
+ F96D457C08F272BB004A47F5 /* tclAsync.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDD08F272A7004A47F5 /* tclAsync.c */; };
+ F96D457D08F272BB004A47F5 /* tclBasic.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDE08F272A7004A47F5 /* tclBasic.c */; };
+ F96D457E08F272BC004A47F5 /* tclBinary.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDF08F272A7004A47F5 /* tclBinary.c */; };
+ F96D457F08F272BC004A47F5 /* tclCkalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE008F272A7004A47F5 /* tclCkalloc.c */; };
+ F96D458008F272BC004A47F5 /* tclClock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE108F272A7004A47F5 /* tclClock.c */; };
+ F96D458108F272BC004A47F5 /* tclCmdAH.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE208F272A7004A47F5 /* tclCmdAH.c */; };
+ F96D458208F272BC004A47F5 /* tclCmdIL.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE308F272A7004A47F5 /* tclCmdIL.c */; };
+ F96D458308F272BC004A47F5 /* tclCmdMZ.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */; };
+ F96D458408F272BC004A47F5 /* tclCompCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE508F272A7004A47F5 /* tclCompCmds.c */; };
+ F96D458508F272BC004A47F5 /* tclCompExpr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE608F272A7004A47F5 /* tclCompExpr.c */; };
+ F96D458608F272BC004A47F5 /* tclCompile.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE708F272A7004A47F5 /* tclCompile.c */; };
+ F96D458808F272BC004A47F5 /* tclConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE908F272A7004A47F5 /* tclConfig.c */; };
+ F96D458908F272BC004A47F5 /* tclDate.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEA08F272A7004A47F5 /* tclDate.c */; };
+ F96D458B08F272BC004A47F5 /* tclDictObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEC08F272A7004A47F5 /* tclDictObj.c */; };
+ F96D458C08F272BC004A47F5 /* tclEncoding.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EED08F272A7004A47F5 /* tclEncoding.c */; };
+ F96D458D08F272BC004A47F5 /* tclEnv.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEE08F272A7004A47F5 /* tclEnv.c */; };
+ F96D458E08F272BC004A47F5 /* tclEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEF08F272A7004A47F5 /* tclEvent.c */; };
+ F96D458F08F272BC004A47F5 /* tclExecute.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF008F272A7004A47F5 /* tclExecute.c */; };
+ F96D459008F272BC004A47F5 /* tclFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF108F272A7004A47F5 /* tclFCmd.c */; };
+ F96D459108F272BC004A47F5 /* tclFileName.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF208F272A7004A47F5 /* tclFileName.c */; };
+ F96D459308F272BC004A47F5 /* tclGet.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF408F272A7004A47F5 /* tclGet.c */; };
+ F96D459508F272BC004A47F5 /* tclHash.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF608F272A7004A47F5 /* tclHash.c */; };
+ F96D459608F272BC004A47F5 /* tclHistory.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF708F272A7004A47F5 /* tclHistory.c */; };
+ F96D459708F272BC004A47F5 /* tclIndexObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF808F272A7004A47F5 /* tclIndexObj.c */; };
+ F96D459B08F272BC004A47F5 /* tclInterp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EFC08F272A7004A47F5 /* tclInterp.c */; };
+ F96D459D08F272BC004A47F5 /* tclIO.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EFE08F272A7004A47F5 /* tclIO.c */; };
+ F96D459F08F272BC004A47F5 /* tclIOCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0008F272A7004A47F5 /* tclIOCmd.c */; };
+ F96D45A008F272BC004A47F5 /* tclIOGT.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0108F272A7004A47F5 /* tclIOGT.c */; };
+ F96D45A108F272BC004A47F5 /* tclIORChan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0208F272A7004A47F5 /* tclIORChan.c */; };
+ F96D45A208F272BC004A47F5 /* tclIOSock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0308F272A7004A47F5 /* tclIOSock.c */; };
+ F96D45A308F272BC004A47F5 /* tclIOUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0408F272A7004A47F5 /* tclIOUtil.c */; };
+ F96D45A408F272BC004A47F5 /* tclLink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0508F272A7004A47F5 /* tclLink.c */; };
+ F96D45A508F272BC004A47F5 /* tclListObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0608F272A7004A47F5 /* tclListObj.c */; };
+ F96D45A608F272BC004A47F5 /* tclLiteral.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0708F272A7004A47F5 /* tclLiteral.c */; };
+ F96D45A708F272BC004A47F5 /* tclLoad.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0808F272A7004A47F5 /* tclLoad.c */; };
+ F96D45A908F272BC004A47F5 /* tclMain.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0A08F272A7004A47F5 /* tclMain.c */; };
+ F96D45AA08F272BC004A47F5 /* tclNamesp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0B08F272A7004A47F5 /* tclNamesp.c */; };
+ F96D45AB08F272BC004A47F5 /* tclNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0C08F272A7004A47F5 /* tclNotify.c */; };
+ F96D45AC08F272BC004A47F5 /* tclObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0D08F272A7004A47F5 /* tclObj.c */; };
+ F96D45AD08F272BC004A47F5 /* tclPanic.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0E08F272A7004A47F5 /* tclPanic.c */; };
+ F96D45AE08F272BC004A47F5 /* tclParse.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0F08F272A7004A47F5 /* tclParse.c */; };
+ F96D45B008F272BC004A47F5 /* tclPathObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1108F272A7004A47F5 /* tclPathObj.c */; };
+ F96D45B108F272BC004A47F5 /* tclPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1208F272A7004A47F5 /* tclPipe.c */; };
+ F96D45B208F272BC004A47F5 /* tclPkg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1308F272A7004A47F5 /* tclPkg.c */; };
+ F96D45B308F272BC004A47F5 /* tclPkgConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */; settings = {COMPILER_FLAGS = "-DCFG_INSTALL_LIBDIR=\\\"$(LIBDIR)\\\" -DCFG_INSTALL_BINDIR=\\\"$(BINDIR)\\\" -DCFG_INSTALL_SCRDIR=\\\"$(TCL_LIBRARY)\\\" -DCFG_INSTALL_INCDIR=\\\"$(INCLUDEDIR)\\\" -DCFG_INSTALL_DOCDIR=\\\"$(MANDIR)\\\" -DCFG_RUNTIME_LIBDIR=\\\"$(LIBDIR)\\\" -DCFG_RUNTIME_BINDIR=\\\"$(BINDIR)\\\" -DCFG_RUNTIME_SCRDIR=\\\"$(TCL_LIBRARY)\\\" -DCFG_RUNTIME_INCDIR=\\\"$(INCLUDEDIR)\\\" -DCFG_RUNTIME_DOCDIR=\\\"$(MANDIR)\\\""; }; };
+ F96D45B608F272BC004A47F5 /* tclPosixStr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1708F272A7004A47F5 /* tclPosixStr.c */; };
+ F96D45B708F272BC004A47F5 /* tclPreserve.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1808F272A7004A47F5 /* tclPreserve.c */; };
+ F96D45B808F272BC004A47F5 /* tclProc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1908F272A7004A47F5 /* tclProc.c */; };
+ F96D45B908F272BC004A47F5 /* tclRegexp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1A08F272A7004A47F5 /* tclRegexp.c */; };
+ F96D45BB08F272BC004A47F5 /* tclResolve.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1C08F272A7004A47F5 /* tclResolve.c */; };
+ F96D45BC08F272BC004A47F5 /* tclResult.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1D08F272A7004A47F5 /* tclResult.c */; };
+ F96D45BD08F272BC004A47F5 /* tclScan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1E08F272A7004A47F5 /* tclScan.c */; };
+ F96D45BE08F272BC004A47F5 /* tclStringObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1F08F272A7004A47F5 /* tclStringObj.c */; };
+ F96D45C308F272BC004A47F5 /* tclStrToD.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2408F272A7004A47F5 /* tclStrToD.c */; };
+ F96D45C408F272BC004A47F5 /* tclStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2508F272A7004A47F5 /* tclStubInit.c */; };
+ F96D45C508F272BC004A47F5 /* tclStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2608F272A7004A47F5 /* tclStubLib.c */; };
+ F96D45C608F272BC004A47F5 /* tclTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2708F272A7004A47F5 /* tclTest.c */; };
+ F96D45C708F272BC004A47F5 /* tclTestObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2808F272A7004A47F5 /* tclTestObj.c */; };
+ F96D45C808F272BC004A47F5 /* tclTestProcBodyObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */; };
+ F96D45C908F272BC004A47F5 /* tclThread.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2A08F272A7004A47F5 /* tclThread.c */; };
+ F96D45CA08F272BC004A47F5 /* tclThreadAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */; };
+ F96D45CB08F272BC004A47F5 /* tclThreadJoin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */; };
+ F96D45CC08F272BC004A47F5 /* tclThreadStorage.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */; };
+ F96D45CD08F272BC004A47F5 /* tclThreadTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */; };
+ F96D45CE08F272BC004A47F5 /* tclTimer.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2F08F272A7004A47F5 /* tclTimer.c */; };
+ F96D45D008F272BC004A47F5 /* tclTomMathInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */; };
+ F96D45D108F272BC004A47F5 /* tclTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3208F272A7004A47F5 /* tclTrace.c */; };
+ F96D45D308F272BC004A47F5 /* tclUtf.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3408F272A7004A47F5 /* tclUtf.c */; };
+ F96D45D408F272BC004A47F5 /* tclUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3508F272A7004A47F5 /* tclUtil.c */; };
+ F96D45D508F272BC004A47F5 /* tclVar.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3608F272A7004A47F5 /* tclVar.c */; };
+ F96D48E208F272C3004A47F5 /* bn_fast_s_mp_mul_digs.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */; };
+ F96D48E408F272C3004A47F5 /* bn_fast_s_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */; };
+ F96D48E708F272C3004A47F5 /* bn_mp_add.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426908F272B3004A47F5 /* bn_mp_add.c */; };
+ F96D48E808F272C3004A47F5 /* bn_mp_add_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */; };
+ F96D48EB08F272C3004A47F5 /* bn_mp_clamp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */; };
+ F96D48EC08F272C3004A47F5 /* bn_mp_clear.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426E08F272B3004A47F5 /* bn_mp_clear.c */; };
+ F96D48ED08F272C3004A47F5 /* bn_mp_clear_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */; };
+ F96D48EE08F272C3004A47F5 /* bn_mp_cmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427008F272B3004A47F5 /* bn_mp_cmp.c */; };
+ F96D48F008F272C3004A47F5 /* bn_mp_cmp_mag.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */; };
+ F96D48F208F272C3004A47F5 /* bn_mp_cnt_lsb.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427408F272B3004A47F5 /* bn_mp_cnt_lsb.c */; };
+ F96D48F208F272C3004A47F5 /* bn_mp_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427408F272B3004A47F5 /* bn_mp_copy.c */; };
+ F96D48F308F272C3004A47F5 /* bn_mp_count_bits.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */; };
+ F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427608F272B3004A47F5 /* bn_mp_div.c */; };
+ F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427708F272B3004A47F5 /* bn_mp_div_2.c */; };
+ F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */; };
+ F96D48F708F272C3004A47F5 /* bn_mp_div_3.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427908F272B3004A47F5 /* bn_mp_div_3.c */; };
+ F96D48F808F272C3004A47F5 /* bn_mp_div_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */; };
+ F96D48FC08F272C3004A47F5 /* bn_mp_exch.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427E08F272B3004A47F5 /* bn_mp_exch.c */; };
+ F96D490508F272C3004A47F5 /* bn_mp_grow.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428708F272B3004A47F5 /* bn_mp_grow.c */; };
+ F96D490608F272C3004A47F5 /* bn_mp_init.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428808F272B3004A47F5 /* bn_mp_init.c */; };
+ F96D490708F272C3004A47F5 /* bn_mp_init_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */; };
+ F96D490808F272C3004A47F5 /* bn_mp_init_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */; };
+ F96D490908F272C3004A47F5 /* bn_mp_init_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */; };
+ F96D490B08F272C3004A47F5 /* bn_mp_init_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */; };
+ F96D491008F272C3004A47F5 /* bn_mp_karatsuba_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */; };
+ F96D491108F272C3004A47F5 /* bn_mp_karatsuba_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */; };
+ F96D491308F272C3004A47F5 /* bn_mp_lshd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429508F272B3004A47F5 /* bn_mp_lshd.c */; };
+ F96D491408F272C3004A47F5 /* bn_mp_mod.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429608F272B3004A47F5 /* bn_mp_mod.c */; };
+ F96D491508F272C3004A47F5 /* bn_mp_mod_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */; };
+ F96D491A08F272C3004A47F5 /* bn_mp_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429C08F272B3004A47F5 /* bn_mp_mul.c */; };
+ F96D491B08F272C3004A47F5 /* bn_mp_mul_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */; };
+ F96D491C08F272C3004A47F5 /* bn_mp_mul_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */; };
+ F96D491D08F272C3004A47F5 /* bn_mp_mul_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */; };
+ F96D492908F272C3004A47F5 /* bn_mp_radix_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */; };
+ F96D492A08F272C3004A47F5 /* bn_mp_radix_smap.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */; };
+ F96D492C08F272C3004A47F5 /* bn_mp_read_radix.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */; };
+ F96D493708F272C3004A47F5 /* bn_mp_rshd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */; };
+ F96D493808F272C3004A47F5 /* bn_mp_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BA08F272B3004A47F5 /* bn_mp_set.c */; };
+ F96D493C08F272C3004A47F5 /* bn_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */; };
+ F96D493F08F272C3004A47F5 /* bn_mp_sub.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C108F272B3004A47F5 /* bn_mp_sub.c */; };
+ F96D494008F272C3004A47F5 /* bn_mp_sub_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */; };
+ F96D494608F272C3004A47F5 /* bn_mp_toom_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */; };
+ F96D494708F272C3004A47F5 /* bn_mp_toom_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */; };
+ F96D494908F272C3004A47F5 /* bn_mp_toradix_n.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CB08F272B3004A47F5 /* bn_mp_toradix_n.c */; };
+ F96D494C08F272C3004A47F5 /* bn_mp_zero.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */; };
+ F96D494E08F272C3004A47F5 /* bn_reverse.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D008F272B3004A47F5 /* bn_reverse.c */; };
+ F96D494F08F272C3004A47F5 /* bn_s_mp_add.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */; };
+ F96D495108F272C3004A47F5 /* bn_s_mp_mul_digs.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */; };
+ F96D495308F272C3004A47F5 /* bn_s_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */; };
+ F96D495408F272C3004A47F5 /* bn_s_mp_sub.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */; };
+ F96D495508F272C3004A47F5 /* bncore.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D708F272B3004A47F5 /* bncore.c */; };
+ F96D49A908F272C4004A47F5 /* tclMacOSXBundle.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */; };
+ F96D49AD08F272C4004A47F5 /* tclMacOSXFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */; };
+ F96D49AE08F272C4004A47F5 /* tclMacOSXNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */; };
+ F96D4AC608F272C9004A47F5 /* tclLoadDyld.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445B08F272B9004A47F5 /* tclLoadDyld.c */; };
+ F96D4ACA08F272C9004A47F5 /* tclUnixChan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445F08F272B9004A47F5 /* tclUnixChan.c */; };
+ F96D4ACB08F272C9004A47F5 /* tclUnixEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446008F272B9004A47F5 /* tclUnixEvent.c */; };
+ F96D4ACC08F272C9004A47F5 /* tclUnixFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446108F272B9004A47F5 /* tclUnixFCmd.c */; };
+ F96D4ACD08F272C9004A47F5 /* tclUnixFile.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446208F272B9004A47F5 /* tclUnixFile.c */; };
+ F96D4ACE08F272C9004A47F5 /* tclUnixInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446308F272B9004A47F5 /* tclUnixInit.c */; settings = {COMPILER_FLAGS = "-DTCL_LIBRARY=\\\"$(TCL_LIBRARY)\\\" -DTCL_PACKAGE_PATH=\\\"$(TCL_PACKAGE_PATH)\\\""; }; };
+ F96D4ACF08F272C9004A47F5 /* tclUnixNotfy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446408F272B9004A47F5 /* tclUnixNotfy.c */; };
+ F96D4AD008F272C9004A47F5 /* tclUnixPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446508F272B9004A47F5 /* tclUnixPipe.c */; };
+ F96D4AD208F272CA004A47F5 /* tclUnixSock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446708F272B9004A47F5 /* tclUnixSock.c */; };
+ F96D4AD308F272CA004A47F5 /* tclUnixTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446808F272B9004A47F5 /* tclUnixTest.c */; };
+ F96D4AD408F272CA004A47F5 /* tclUnixThrd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446908F272B9004A47F5 /* tclUnixThrd.c */; };
+ F96D4AD608F272CA004A47F5 /* tclUnixTime.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446B08F272B9004A47F5 /* tclUnixTime.c */; };
+ F9E61D28090A481F002B3151 /* bn_mp_cmp_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */; };
+ F9E61D29090A486C002B3151 /* bn_mp_neg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A208F272B3004A47F5 /* bn_mp_neg.c */; };
+ F9E61D2A090A4891002B3151 /* bn_mp_sqrt.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */; };
+ F9E61D2B090A48A4002B3151 /* bn_mp_and.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426C08F272B3004A47F5 /* bn_mp_and.c */; };
+ F9E61D2C090A48AC002B3151 /* bn_mp_expt_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427F08F272B3004A47F5 /* bn_mp_expt_d.c */; };
+ F9E61D2D090A48BB002B3151 /* bn_mp_xor.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */; };
+ F9E61D2E090A48BF002B3151 /* bn_mp_or.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A308F272B3004A47F5 /* bn_mp_or.c */; };
+ F9E61D2F090A48C7002B3151 /* bn_mp_shrink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */; };
+ F9E61D30090A48E2002B3151 /* bn_mp_to_unsigned_bin_n.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C708F272B3004A47F5 /* bn_mp_to_unsigned_bin_n.c */; };
+ F9E61D31090A48F9002B3151 /* bn_mp_to_unsigned_bin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */; };
+ F9E61D32090A48FA002B3151 /* bn_mp_unsigned_bin_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */; };
+ F9FC77B80AB29E9100B7077D /* tclUnixCompat.c in Sources */ = {isa = PBXBuildFile; fileRef = F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ F97258D20A868C6F00096C78 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 8DD76FA90486AB0100D96B5E;
+ remoteInfo = tcltest;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 8DD76FB20486AB0100D96B5E /* tcltest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tcltest; sourceTree = BUILT_PRODUCTS_DIR; };
+ F91E62260C1AE686006C9D96 /* Tclsh-Info.plist.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = "Tclsh-Info.plist.in"; sourceTree = "<group>"; };
+ F95FAFF90B34F1130072E431 /* macOSXLoad.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = macOSXLoad.test; sourceTree = "<group>"; };
+ F966C07408F2820D005CB29B /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
+ F96D3DFA08F272A4004A47F5 /* ChangeLog */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = ChangeLog; sourceTree = "<group>"; };
+ F96D3DFB08F272A4004A47F5 /* changes */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = changes; sourceTree = "<group>"; };
+ F96D3DFD08F272A4004A47F5 /* Access.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Access.3; sourceTree = "<group>"; };
+ F96D3DFE08F272A4004A47F5 /* AddErrInfo.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AddErrInfo.3; sourceTree = "<group>"; };
+ F96D3DFF08F272A4004A47F5 /* after.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = after.n; sourceTree = "<group>"; };
+ F96D3E0008F272A4004A47F5 /* Alloc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Alloc.3; sourceTree = "<group>"; };
+ F96D3E0108F272A4004A47F5 /* AllowExc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AllowExc.3; sourceTree = "<group>"; };
+ F96D3E0208F272A4004A47F5 /* append.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = append.n; sourceTree = "<group>"; };
+ F96D3E0308F272A4004A47F5 /* AppInit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AppInit.3; sourceTree = "<group>"; };
+ F96D3E0408F272A5004A47F5 /* array.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = array.n; sourceTree = "<group>"; };
+ F96D3E0508F272A5004A47F5 /* AssocData.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AssocData.3; sourceTree = "<group>"; };
+ F96D3E0608F272A5004A47F5 /* Async.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Async.3; sourceTree = "<group>"; };
+ F96D3E0708F272A5004A47F5 /* BackgdErr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = BackgdErr.3; sourceTree = "<group>"; };
+ F96D3E0808F272A5004A47F5 /* Backslash.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Backslash.3; sourceTree = "<group>"; };
+ F96D3E0908F272A5004A47F5 /* bgerror.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = bgerror.n; sourceTree = "<group>"; };
+ F96D3E0A08F272A5004A47F5 /* binary.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = binary.n; sourceTree = "<group>"; };
+ F96D3E0B08F272A5004A47F5 /* BoolObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = BoolObj.3; sourceTree = "<group>"; };
+ F96D3E0C08F272A5004A47F5 /* break.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = break.n; sourceTree = "<group>"; };
+ F96D3E0D08F272A5004A47F5 /* ByteArrObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ByteArrObj.3; sourceTree = "<group>"; };
+ F96D3E0E08F272A5004A47F5 /* CallDel.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CallDel.3; sourceTree = "<group>"; };
+ F96D3E0F08F272A5004A47F5 /* case.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = case.n; sourceTree = "<group>"; };
+ F96D3E1008F272A5004A47F5 /* catch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = catch.n; sourceTree = "<group>"; };
+ F96D3E1108F272A5004A47F5 /* cd.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = cd.n; sourceTree = "<group>"; };
+ F96D3E1208F272A5004A47F5 /* chan.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = chan.n; sourceTree = "<group>"; };
+ F96D3E1308F272A5004A47F5 /* ChnlStack.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ChnlStack.3; sourceTree = "<group>"; };
+ F96D3E1408F272A5004A47F5 /* clock.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = clock.n; sourceTree = "<group>"; };
+ F96D3E1508F272A5004A47F5 /* close.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = close.n; sourceTree = "<group>"; };
+ F96D3E1608F272A5004A47F5 /* CmdCmplt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CmdCmplt.3; sourceTree = "<group>"; };
+ F96D3E1708F272A5004A47F5 /* Concat.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Concat.3; sourceTree = "<group>"; };
+ F96D3E1808F272A5004A47F5 /* concat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = concat.n; sourceTree = "<group>"; };
+ F96D3E1908F272A5004A47F5 /* continue.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = continue.n; sourceTree = "<group>"; };
+ F96D3E1A08F272A5004A47F5 /* CrtChannel.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtChannel.3; sourceTree = "<group>"; };
+ F96D3E1B08F272A5004A47F5 /* CrtChnlHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtChnlHdlr.3; sourceTree = "<group>"; };
+ F96D3E1C08F272A5004A47F5 /* CrtCloseHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCloseHdlr.3; sourceTree = "<group>"; };
+ F96D3E1D08F272A5004A47F5 /* CrtCommand.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCommand.3; sourceTree = "<group>"; };
+ F96D3E1E08F272A5004A47F5 /* CrtFileHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtFileHdlr.3; sourceTree = "<group>"; };
+ F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtInterp.3; sourceTree = "<group>"; };
+ F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtMathFnc.3; sourceTree = "<group>"; };
+ F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtObjCmd.3; sourceTree = "<group>"; };
+ F96D3E2208F272A5004A47F5 /* CrtSlave.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtSlave.3; sourceTree = "<group>"; };
+ F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTimerHdlr.3; sourceTree = "<group>"; };
+ F96D3E2408F272A5004A47F5 /* CrtTrace.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTrace.3; sourceTree = "<group>"; };
+ F96D3E2508F272A5004A47F5 /* dde.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dde.n; sourceTree = "<group>"; };
+ F96D3E2608F272A5004A47F5 /* DetachPids.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DetachPids.3; sourceTree = "<group>"; };
+ F96D3E2708F272A5004A47F5 /* dict.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dict.n; sourceTree = "<group>"; };
+ F96D3E2808F272A5004A47F5 /* DictObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DictObj.3; sourceTree = "<group>"; };
+ F96D3E2908F272A5004A47F5 /* DoOneEvent.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoOneEvent.3; sourceTree = "<group>"; };
+ F96D3E2A08F272A5004A47F5 /* DoubleObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoubleObj.3; sourceTree = "<group>"; };
+ F96D3E2B08F272A5004A47F5 /* DoWhenIdle.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoWhenIdle.3; sourceTree = "<group>"; };
+ F96D3E2C08F272A5004A47F5 /* DString.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DString.3; sourceTree = "<group>"; };
+ F96D3E2D08F272A5004A47F5 /* DumpActiveMemory.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DumpActiveMemory.3; sourceTree = "<group>"; };
+ F96D3E2E08F272A5004A47F5 /* Encoding.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Encoding.3; sourceTree = "<group>"; };
+ F96D3E2F08F272A5004A47F5 /* encoding.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = encoding.n; sourceTree = "<group>"; };
+ F96D3E3008F272A5004A47F5 /* Ensemble.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Ensemble.3; sourceTree = "<group>"; };
+ F96D3E3108F272A5004A47F5 /* Environment.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Environment.3; sourceTree = "<group>"; };
+ F96D3E3208F272A5004A47F5 /* eof.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = eof.n; sourceTree = "<group>"; };
+ F96D3E3308F272A5004A47F5 /* error.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = error.n; sourceTree = "<group>"; };
+ F96D3E3408F272A5004A47F5 /* Eval.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Eval.3; sourceTree = "<group>"; };
+ F96D3E3508F272A5004A47F5 /* eval.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = eval.n; sourceTree = "<group>"; };
+ F96D3E3608F272A5004A47F5 /* exec.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = exec.n; sourceTree = "<group>"; };
+ F96D3E3708F272A5004A47F5 /* Exit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Exit.3; sourceTree = "<group>"; };
+ F96D3E3808F272A5004A47F5 /* exit.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = exit.n; sourceTree = "<group>"; };
+ F96D3E3908F272A5004A47F5 /* expr.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = expr.n; sourceTree = "<group>"; };
+ F96D3E3A08F272A5004A47F5 /* ExprLong.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ExprLong.3; sourceTree = "<group>"; };
+ F96D3E3B08F272A5004A47F5 /* ExprLongObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ExprLongObj.3; sourceTree = "<group>"; };
+ F96D3E3C08F272A5004A47F5 /* fblocked.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fblocked.n; sourceTree = "<group>"; };
+ F96D3E3D08F272A5004A47F5 /* fconfigure.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fconfigure.n; sourceTree = "<group>"; };
+ F96D3E3E08F272A5004A47F5 /* fcopy.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fcopy.n; sourceTree = "<group>"; };
+ F96D3E3F08F272A5004A47F5 /* file.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = file.n; sourceTree = "<group>"; };
+ F96D3E4008F272A5004A47F5 /* fileevent.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fileevent.n; sourceTree = "<group>"; };
+ F96D3E4108F272A5004A47F5 /* filename.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = filename.n; sourceTree = "<group>"; };
+ F96D3E4208F272A5004A47F5 /* FileSystem.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FileSystem.3; sourceTree = "<group>"; };
+ F96D3E4308F272A5004A47F5 /* FindExec.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FindExec.3; sourceTree = "<group>"; };
+ F96D3E4408F272A5004A47F5 /* flush.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = flush.n; sourceTree = "<group>"; };
+ F96D3E4508F272A5004A47F5 /* for.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = for.n; sourceTree = "<group>"; };
+ F96D3E4608F272A5004A47F5 /* foreach.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = foreach.n; sourceTree = "<group>"; };
+ F96D3E4708F272A5004A47F5 /* format.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = format.n; sourceTree = "<group>"; };
+ F96D3E4808F272A5004A47F5 /* GetCwd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetCwd.3; sourceTree = "<group>"; };
+ F96D3E4908F272A5004A47F5 /* GetHostName.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetHostName.3; sourceTree = "<group>"; };
+ F96D3E4A08F272A5004A47F5 /* GetIndex.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetIndex.3; sourceTree = "<group>"; };
+ F96D3E4B08F272A5004A47F5 /* GetInt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetInt.3; sourceTree = "<group>"; };
+ F96D3E4C08F272A5004A47F5 /* GetOpnFl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetOpnFl.3; sourceTree = "<group>"; };
+ F96D3E4D08F272A5004A47F5 /* gets.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = gets.n; sourceTree = "<group>"; };
+ F96D3E4E08F272A5004A47F5 /* GetStdChan.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetStdChan.3; sourceTree = "<group>"; };
+ F96D3E4F08F272A5004A47F5 /* GetTime.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetTime.3; sourceTree = "<group>"; };
+ F96D3E5008F272A5004A47F5 /* GetVersion.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetVersion.3; sourceTree = "<group>"; };
+ F96D3E5108F272A5004A47F5 /* glob.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = glob.n; sourceTree = "<group>"; };
+ F96D3E5208F272A6004A47F5 /* global.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = global.n; sourceTree = "<group>"; };
+ F96D3E5308F272A6004A47F5 /* Hash.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Hash.3; sourceTree = "<group>"; };
+ F96D3E5408F272A6004A47F5 /* history.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = history.n; sourceTree = "<group>"; };
+ F96D3E5508F272A6004A47F5 /* http.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = http.n; sourceTree = "<group>"; };
+ F96D3E5608F272A6004A47F5 /* if.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = if.n; sourceTree = "<group>"; };
+ F96D3E5708F272A6004A47F5 /* incr.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = incr.n; sourceTree = "<group>"; };
+ F96D3E5808F272A6004A47F5 /* info.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = info.n; sourceTree = "<group>"; };
+ F96D3E5908F272A6004A47F5 /* Init.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Init.3; sourceTree = "<group>"; };
+ F96D3E5A08F272A6004A47F5 /* InitStubs.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = InitStubs.3; sourceTree = "<group>"; };
+ F96D3E5B08F272A6004A47F5 /* Interp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Interp.3; sourceTree = "<group>"; };
+ F96D3E5C08F272A6004A47F5 /* interp.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = interp.n; sourceTree = "<group>"; };
+ F96D3E5D08F272A6004A47F5 /* IntObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = IntObj.3; sourceTree = "<group>"; };
+ F96D3E5E08F272A6004A47F5 /* join.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = join.n; sourceTree = "<group>"; };
+ F96D3E5F08F272A6004A47F5 /* lappend.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lappend.n; sourceTree = "<group>"; };
+ F96D3E6008F272A6004A47F5 /* lassign.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lassign.n; sourceTree = "<group>"; };
+ F96D3E6108F272A6004A47F5 /* library.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = library.n; sourceTree = "<group>"; };
+ F96D3E6208F272A6004A47F5 /* Limit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Limit.3; sourceTree = "<group>"; };
+ F96D3E6308F272A6004A47F5 /* lindex.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lindex.n; sourceTree = "<group>"; };
+ F96D3E6408F272A6004A47F5 /* LinkVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = LinkVar.3; sourceTree = "<group>"; };
+ F96D3E6508F272A6004A47F5 /* linsert.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = linsert.n; sourceTree = "<group>"; };
+ F96D3E6608F272A6004A47F5 /* list.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = list.n; sourceTree = "<group>"; };
+ F96D3E6708F272A6004A47F5 /* ListObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ListObj.3; sourceTree = "<group>"; };
+ F96D3E6808F272A6004A47F5 /* llength.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = llength.n; sourceTree = "<group>"; };
+ F96D3E6908F272A6004A47F5 /* load.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = load.n; sourceTree = "<group>"; };
+ F96D3E6A08F272A6004A47F5 /* lrange.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lrange.n; sourceTree = "<group>"; };
+ F96D3E6B08F272A6004A47F5 /* lrepeat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lrepeat.n; sourceTree = "<group>"; };
+ F96D3E6C08F272A6004A47F5 /* lreplace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lreplace.n; sourceTree = "<group>"; };
+ F96D3E6D08F272A6004A47F5 /* lsearch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lsearch.n; sourceTree = "<group>"; };
+ F96D3E6E08F272A6004A47F5 /* lset.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lset.n; sourceTree = "<group>"; };
+ F96D3E6F08F272A6004A47F5 /* lsort.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lsort.n; sourceTree = "<group>"; };
+ F96D3E7008F272A6004A47F5 /* man.macros */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = man.macros; sourceTree = "<group>"; };
+ F96D3E7108F272A6004A47F5 /* mathfunc.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = mathfunc.n; sourceTree = "<group>"; };
+ F96D3E7208F272A6004A47F5 /* memory.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = memory.n; sourceTree = "<group>"; };
+ F96D3E7308F272A6004A47F5 /* msgcat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = msgcat.n; sourceTree = "<group>"; };
+ F96D3E7408F272A6004A47F5 /* Namespace.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Namespace.3; sourceTree = "<group>"; };
+ F96D3E7508F272A6004A47F5 /* namespace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = namespace.n; sourceTree = "<group>"; };
+ F96D3E7608F272A6004A47F5 /* Notifier.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Notifier.3; sourceTree = "<group>"; };
+ F96D3E7708F272A6004A47F5 /* Object.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Object.3; sourceTree = "<group>"; };
+ F96D3E7808F272A6004A47F5 /* ObjectType.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ObjectType.3; sourceTree = "<group>"; };
+ F96D3E7908F272A6004A47F5 /* open.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = open.n; sourceTree = "<group>"; };
+ F96D3E7A08F272A6004A47F5 /* OpenFileChnl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = OpenFileChnl.3; sourceTree = "<group>"; };
+ F96D3E7B08F272A6004A47F5 /* OpenTcp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = OpenTcp.3; sourceTree = "<group>"; };
+ F96D3E7C08F272A6004A47F5 /* package.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = package.n; sourceTree = "<group>"; };
+ F96D3E7D08F272A6004A47F5 /* packagens.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = packagens.n; sourceTree = "<group>"; };
+ F96D3E7E08F272A6004A47F5 /* Panic.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Panic.3; sourceTree = "<group>"; };
+ F96D3E7F08F272A6004A47F5 /* ParseCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ParseCmd.3; sourceTree = "<group>"; };
+ F96D3E8008F272A6004A47F5 /* pid.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pid.n; sourceTree = "<group>"; };
+ F96D3E8108F272A6004A47F5 /* pkgMkIndex.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pkgMkIndex.n; sourceTree = "<group>"; };
+ F96D3E8208F272A6004A47F5 /* PkgRequire.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = PkgRequire.3; sourceTree = "<group>"; };
+ F96D3E8308F272A6004A47F5 /* Preserve.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Preserve.3; sourceTree = "<group>"; };
+ F96D3E8408F272A6004A47F5 /* PrintDbl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = PrintDbl.3; sourceTree = "<group>"; };
+ F96D3E8508F272A6004A47F5 /* proc.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = proc.n; sourceTree = "<group>"; };
+ F96D3E8608F272A6004A47F5 /* puts.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = puts.n; sourceTree = "<group>"; };
+ F96D3E8708F272A6004A47F5 /* pwd.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pwd.n; sourceTree = "<group>"; };
+ F96D3E8808F272A6004A47F5 /* re_syntax.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = re_syntax.n; sourceTree = "<group>"; };
+ F96D3E8908F272A6004A47F5 /* read.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = read.n; sourceTree = "<group>"; };
+ F96D3E8A08F272A6004A47F5 /* RecEvalObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RecEvalObj.3; sourceTree = "<group>"; };
+ F96D3E8B08F272A6004A47F5 /* RecordEval.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RecordEval.3; sourceTree = "<group>"; };
+ F96D3E8C08F272A6004A47F5 /* RegConfig.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RegConfig.3; sourceTree = "<group>"; };
+ F96D3E8D08F272A6004A47F5 /* RegExp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RegExp.3; sourceTree = "<group>"; };
+ F96D3E8E08F272A6004A47F5 /* regexp.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = regexp.n; sourceTree = "<group>"; };
+ F96D3E8F08F272A6004A47F5 /* registry.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = registry.n; sourceTree = "<group>"; };
+ F96D3E9008F272A6004A47F5 /* regsub.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = regsub.n; sourceTree = "<group>"; };
+ F96D3E9108F272A6004A47F5 /* rename.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = rename.n; sourceTree = "<group>"; };
+ F96D3E9208F272A6004A47F5 /* return.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = return.n; sourceTree = "<group>"; };
+ F96D3E9308F272A6004A47F5 /* safe.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = safe.n; sourceTree = "<group>"; };
+ F96D3E9408F272A6004A47F5 /* SaveResult.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SaveResult.3; sourceTree = "<group>"; };
+ F96D3E9508F272A6004A47F5 /* scan.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = scan.n; sourceTree = "<group>"; };
+ F96D3E9608F272A6004A47F5 /* seek.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = seek.n; sourceTree = "<group>"; };
+ F96D3E9708F272A6004A47F5 /* set.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = set.n; sourceTree = "<group>"; };
+ F96D3E9808F272A6004A47F5 /* SetChanErr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetChanErr.3; sourceTree = "<group>"; };
+ F96D3E9908F272A6004A47F5 /* SetErrno.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetErrno.3; sourceTree = "<group>"; };
+ F96D3E9A08F272A6004A47F5 /* SetRecLmt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetRecLmt.3; sourceTree = "<group>"; };
+ F96D3E9B08F272A7004A47F5 /* SetResult.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetResult.3; sourceTree = "<group>"; };
+ F96D3E9C08F272A7004A47F5 /* SetVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetVar.3; sourceTree = "<group>"; };
+ F96D3E9D08F272A7004A47F5 /* Signal.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Signal.3; sourceTree = "<group>"; };
+ F96D3E9E08F272A7004A47F5 /* Sleep.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Sleep.3; sourceTree = "<group>"; };
+ F96D3E9F08F272A7004A47F5 /* socket.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = socket.n; sourceTree = "<group>"; };
+ F96D3EA008F272A7004A47F5 /* source.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = source.n; sourceTree = "<group>"; };
+ F96D3EA108F272A7004A47F5 /* SourceRCFile.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SourceRCFile.3; sourceTree = "<group>"; };
+ F96D3EA208F272A7004A47F5 /* split.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = split.n; sourceTree = "<group>"; };
+ F96D3EA308F272A7004A47F5 /* SplitList.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SplitList.3; sourceTree = "<group>"; };
+ F96D3EA408F272A7004A47F5 /* SplitPath.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SplitPath.3; sourceTree = "<group>"; };
+ F96D3EA508F272A7004A47F5 /* StaticPkg.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StaticPkg.3; sourceTree = "<group>"; };
+ F96D3EA608F272A7004A47F5 /* StdChannels.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StdChannels.3; sourceTree = "<group>"; };
+ F96D3EA708F272A7004A47F5 /* string.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = string.n; sourceTree = "<group>"; };
+ F96D3EA808F272A7004A47F5 /* StringObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StringObj.3; sourceTree = "<group>"; };
+ F96D3EA908F272A7004A47F5 /* StrMatch.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StrMatch.3; sourceTree = "<group>"; };
+ F96D3EAA08F272A7004A47F5 /* subst.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = subst.n; sourceTree = "<group>"; };
+ F96D3EAB08F272A7004A47F5 /* SubstObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SubstObj.3; sourceTree = "<group>"; };
+ F96D3EAC08F272A7004A47F5 /* switch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = switch.n; sourceTree = "<group>"; };
+ F96D3EAD08F272A7004A47F5 /* Tcl.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Tcl.n; sourceTree = "<group>"; };
+ F96D3EAE08F272A7004A47F5 /* Tcl_Main.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Tcl_Main.3; sourceTree = "<group>"; };
+ F96D3EAF08F272A7004A47F5 /* TCL_MEM_DEBUG.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TCL_MEM_DEBUG.3; sourceTree = "<group>"; };
+ F96D3EB008F272A7004A47F5 /* tclsh.1 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tclsh.1; sourceTree = "<group>"; };
+ F96D3EB108F272A7004A47F5 /* tcltest.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tcltest.n; sourceTree = "<group>"; };
+ F96D3EB208F272A7004A47F5 /* tclvars.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tclvars.n; sourceTree = "<group>"; };
+ F96D3EB308F272A7004A47F5 /* tell.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tell.n; sourceTree = "<group>"; };
+ F96D3EB408F272A7004A47F5 /* Thread.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Thread.3; sourceTree = "<group>"; };
+ F96D3EB508F272A7004A47F5 /* time.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = time.n; sourceTree = "<group>"; };
+ F96D3EB608F272A7004A47F5 /* tm.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tm.n; sourceTree = "<group>"; };
+ F96D3EB708F272A7004A47F5 /* ToUpper.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ToUpper.3; sourceTree = "<group>"; };
+ F96D3EB808F272A7004A47F5 /* trace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = trace.n; sourceTree = "<group>"; };
+ F96D3EB908F272A7004A47F5 /* TraceCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TraceCmd.3; sourceTree = "<group>"; };
+ F96D3EBA08F272A7004A47F5 /* TraceVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TraceVar.3; sourceTree = "<group>"; };
+ F96D3EBB08F272A7004A47F5 /* Translate.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Translate.3; sourceTree = "<group>"; };
+ F96D3EBC08F272A7004A47F5 /* UniCharIsAlpha.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = UniCharIsAlpha.3; sourceTree = "<group>"; };
+ F96D3EBD08F272A7004A47F5 /* unknown.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unknown.n; sourceTree = "<group>"; };
+ F96D3EBE08F272A7004A47F5 /* unload.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unload.n; sourceTree = "<group>"; };
+ F96D3EBF08F272A7004A47F5 /* unset.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unset.n; sourceTree = "<group>"; };
+ F96D3EC008F272A7004A47F5 /* update.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = update.n; sourceTree = "<group>"; };
+ F96D3EC108F272A7004A47F5 /* uplevel.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = uplevel.n; sourceTree = "<group>"; };
+ F96D3EC208F272A7004A47F5 /* UpVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = UpVar.3; sourceTree = "<group>"; };
+ F96D3EC308F272A7004A47F5 /* upvar.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = upvar.n; sourceTree = "<group>"; };
+ F96D3EC408F272A7004A47F5 /* Utf.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Utf.3; sourceTree = "<group>"; };
+ F96D3EC508F272A7004A47F5 /* variable.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = variable.n; sourceTree = "<group>"; };
+ F96D3EC608F272A7004A47F5 /* vwait.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = vwait.n; sourceTree = "<group>"; };
+ F96D3EC708F272A7004A47F5 /* while.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = while.n; sourceTree = "<group>"; };
+ F96D3EC808F272A7004A47F5 /* WrongNumArgs.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = WrongNumArgs.3; sourceTree = "<group>"; };
+ F96D3ECA08F272A7004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D3ECB08F272A7004A47F5 /* regc_color.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_color.c; sourceTree = "<group>"; };
+ F96D3ECC08F272A7004A47F5 /* regc_cvec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_cvec.c; sourceTree = "<group>"; };
+ F96D3ECD08F272A7004A47F5 /* regc_lex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_lex.c; sourceTree = "<group>"; };
+ F96D3ECE08F272A7004A47F5 /* regc_locale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_locale.c; sourceTree = "<group>"; };
+ F96D3ECF08F272A7004A47F5 /* regc_nfa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_nfa.c; sourceTree = "<group>"; };
+ F96D3ED008F272A7004A47F5 /* regcomp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regcomp.c; sourceTree = "<group>"; };
+ F96D3ED108F272A7004A47F5 /* regcustom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regcustom.h; sourceTree = "<group>"; };
+ F96D3ED208F272A7004A47F5 /* rege_dfa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rege_dfa.c; sourceTree = "<group>"; };
+ F96D3ED308F272A7004A47F5 /* regerror.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regerror.c; sourceTree = "<group>"; };
+ F96D3ED408F272A7004A47F5 /* regerrs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regerrs.h; sourceTree = "<group>"; };
+ F96D3ED508F272A7004A47F5 /* regex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regex.h; sourceTree = "<group>"; };
+ F96D3ED608F272A7004A47F5 /* regexec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regexec.c; sourceTree = "<group>"; };
+ F96D3ED708F272A7004A47F5 /* regfree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regfree.c; sourceTree = "<group>"; };
+ F96D3ED808F272A7004A47F5 /* regfronts.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regfronts.c; sourceTree = "<group>"; };
+ F96D3ED908F272A7004A47F5 /* regguts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regguts.h; sourceTree = "<group>"; };
+ F96D3EDA08F272A7004A47F5 /* tcl.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcl.decls; sourceTree = "<group>"; };
+ F96D3EDB08F272A7004A47F5 /* tcl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tcl.h; sourceTree = "<group>"; };
+ F96D3EDC08F272A7004A47F5 /* tclAlloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAlloc.c; sourceTree = "<group>"; };
+ F96D3EDD08F272A7004A47F5 /* tclAsync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAsync.c; sourceTree = "<group>"; };
+ F96D3EDE08F272A7004A47F5 /* tclBasic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclBasic.c; sourceTree = "<group>"; };
+ F96D3EDF08F272A7004A47F5 /* tclBinary.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclBinary.c; sourceTree = "<group>"; };
+ F96D3EE008F272A7004A47F5 /* tclCkalloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCkalloc.c; sourceTree = "<group>"; };
+ F96D3EE108F272A7004A47F5 /* tclClock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclClock.c; sourceTree = "<group>"; };
+ F96D3EE208F272A7004A47F5 /* tclCmdAH.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdAH.c; sourceTree = "<group>"; };
+ F96D3EE308F272A7004A47F5 /* tclCmdIL.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdIL.c; sourceTree = "<group>"; };
+ F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdMZ.c; sourceTree = "<group>"; };
+ F96D3EE508F272A7004A47F5 /* tclCompCmds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompCmds.c; sourceTree = "<group>"; };
+ F96D3EE608F272A7004A47F5 /* tclCompExpr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompExpr.c; sourceTree = "<group>"; };
+ F96D3EE708F272A7004A47F5 /* tclCompile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompile.c; sourceTree = "<group>"; };
+ F96D3EE808F272A7004A47F5 /* tclCompile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclCompile.h; sourceTree = "<group>"; };
+ F96D3EE908F272A7004A47F5 /* tclConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclConfig.c; sourceTree = "<group>"; };
+ F96D3EEA08F272A7004A47F5 /* tclDate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclDate.c; sourceTree = "<group>"; };
+ F96D3EEB08F272A7004A47F5 /* tclDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclDecls.h; sourceTree = "<group>"; };
+ F96D3EEC08F272A7004A47F5 /* tclDictObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclDictObj.c; sourceTree = "<group>"; };
+ F96D3EED08F272A7004A47F5 /* tclEncoding.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEncoding.c; sourceTree = "<group>"; };
+ F96D3EEE08F272A7004A47F5 /* tclEnv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEnv.c; sourceTree = "<group>"; };
+ F96D3EEF08F272A7004A47F5 /* tclEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEvent.c; sourceTree = "<group>"; };
+ F96D3EF008F272A7004A47F5 /* tclExecute.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclExecute.c; sourceTree = "<group>"; };
+ F96D3EF108F272A7004A47F5 /* tclFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclFCmd.c; sourceTree = "<group>"; };
+ F96D3EF208F272A7004A47F5 /* tclFileName.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclFileName.c; sourceTree = "<group>"; };
+ F96D3EF308F272A7004A47F5 /* tclFileSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclFileSystem.h; sourceTree = "<group>"; };
+ F96D3EF408F272A7004A47F5 /* tclGet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclGet.c; sourceTree = "<group>"; };
+ F96D3EF508F272A7004A47F5 /* tclGetDate.y */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.yacc; path = tclGetDate.y; sourceTree = "<group>"; };
+ F96D3EF608F272A7004A47F5 /* tclHash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclHash.c; sourceTree = "<group>"; };
+ F96D3EF708F272A7004A47F5 /* tclHistory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclHistory.c; sourceTree = "<group>"; };
+ F96D3EF808F272A7004A47F5 /* tclIndexObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIndexObj.c; sourceTree = "<group>"; };
+ F96D3EF908F272A7004A47F5 /* tclInt.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclInt.decls; sourceTree = "<group>"; };
+ F96D3EFA08F272A7004A47F5 /* tclInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclInt.h; sourceTree = "<group>"; };
+ F96D3EFB08F272A7004A47F5 /* tclIntDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIntDecls.h; sourceTree = "<group>"; };
+ F96D3EFC08F272A7004A47F5 /* tclInterp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclInterp.c; sourceTree = "<group>"; };
+ F96D3EFD08F272A7004A47F5 /* tclIntPlatDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIntPlatDecls.h; sourceTree = "<group>"; };
+ F96D3EFE08F272A7004A47F5 /* tclIO.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIO.c; sourceTree = "<group>"; };
+ F96D3EFF08F272A7004A47F5 /* tclIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIO.h; sourceTree = "<group>"; };
+ F96D3F0008F272A7004A47F5 /* tclIOCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOCmd.c; sourceTree = "<group>"; };
+ F96D3F0108F272A7004A47F5 /* tclIOGT.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOGT.c; sourceTree = "<group>"; };
+ F96D3F0208F272A7004A47F5 /* tclIORChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIORChan.c; sourceTree = "<group>"; };
+ F96D3F0308F272A7004A47F5 /* tclIOSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOSock.c; sourceTree = "<group>"; };
+ F96D3F0408F272A7004A47F5 /* tclIOUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOUtil.c; sourceTree = "<group>"; };
+ F96D3F0508F272A7004A47F5 /* tclLink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLink.c; sourceTree = "<group>"; };
+ F96D3F0608F272A7004A47F5 /* tclListObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclListObj.c; sourceTree = "<group>"; };
+ F96D3F0708F272A7004A47F5 /* tclLiteral.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLiteral.c; sourceTree = "<group>"; };
+ F96D3F0808F272A7004A47F5 /* tclLoad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoad.c; sourceTree = "<group>"; };
+ F96D3F0908F272A7004A47F5 /* tclLoadNone.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadNone.c; sourceTree = "<group>"; };
+ F96D3F0A08F272A7004A47F5 /* tclMain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMain.c; sourceTree = "<group>"; };
+ F96D3F0B08F272A7004A47F5 /* tclNamesp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclNamesp.c; sourceTree = "<group>"; };
+ F96D3F0C08F272A7004A47F5 /* tclNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclNotify.c; sourceTree = "<group>"; };
+ F96D3F0D08F272A7004A47F5 /* tclObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclObj.c; sourceTree = "<group>"; };
+ F96D3F0E08F272A7004A47F5 /* tclPanic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPanic.c; sourceTree = "<group>"; };
+ F96D3F0F08F272A7004A47F5 /* tclParse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclParse.c; sourceTree = "<group>"; };
+ F96D3F1108F272A7004A47F5 /* tclPathObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPathObj.c; sourceTree = "<group>"; };
+ F96D3F1208F272A7004A47F5 /* tclPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPipe.c; sourceTree = "<group>"; };
+ F96D3F1308F272A7004A47F5 /* tclPkg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPkg.c; sourceTree = "<group>"; };
+ F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPkgConfig.c; sourceTree = "<group>"; };
+ F96D3F1508F272A7004A47F5 /* tclPlatDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclPlatDecls.h; sourceTree = "<group>"; };
+ F96D3F1608F272A7004A47F5 /* tclPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclPort.h; sourceTree = "<group>"; };
+ F96D3F1708F272A7004A47F5 /* tclPosixStr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPosixStr.c; sourceTree = "<group>"; };
+ F96D3F1808F272A7004A47F5 /* tclPreserve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPreserve.c; sourceTree = "<group>"; };
+ F96D3F1908F272A7004A47F5 /* tclProc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclProc.c; sourceTree = "<group>"; };
+ F96D3F1A08F272A7004A47F5 /* tclRegexp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclRegexp.c; sourceTree = "<group>"; };
+ F96D3F1B08F272A7004A47F5 /* tclRegexp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclRegexp.h; sourceTree = "<group>"; };
+ F96D3F1C08F272A7004A47F5 /* tclResolve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclResolve.c; sourceTree = "<group>"; };
+ F96D3F1D08F272A7004A47F5 /* tclResult.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclResult.c; sourceTree = "<group>"; };
+ F96D3F1E08F272A7004A47F5 /* tclScan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclScan.c; sourceTree = "<group>"; };
+ F96D3F1F08F272A7004A47F5 /* tclStringObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStringObj.c; sourceTree = "<group>"; };
+ F96D3F2408F272A7004A47F5 /* tclStrToD.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStrToD.c; sourceTree = "<group>"; };
+ F96D3F2508F272A7004A47F5 /* tclStubInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStubInit.c; sourceTree = "<group>"; };
+ F96D3F2608F272A7004A47F5 /* tclStubLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStubLib.c; sourceTree = "<group>"; };
+ F96D3F2708F272A7004A47F5 /* tclTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTest.c; sourceTree = "<group>"; };
+ F96D3F2808F272A7004A47F5 /* tclTestObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTestObj.c; sourceTree = "<group>"; };
+ F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTestProcBodyObj.c; sourceTree = "<group>"; };
+ F96D3F2A08F272A7004A47F5 /* tclThread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThread.c; sourceTree = "<group>"; };
+ F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadAlloc.c; sourceTree = "<group>"; };
+ F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadJoin.c; sourceTree = "<group>"; };
+ F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadStorage.c; sourceTree = "<group>"; };
+ F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadTest.c; sourceTree = "<group>"; };
+ F96D3F2F08F272A7004A47F5 /* tclTimer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTimer.c; sourceTree = "<group>"; };
+ F96D3F3008F272A7004A47F5 /* tclTomMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclTomMath.h; sourceTree = "<group>"; };
+ F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTomMathInterface.c; sourceTree = "<group>"; };
+ F96D3F3208F272A7004A47F5 /* tclTrace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTrace.c; sourceTree = "<group>"; };
+ F96D3F3308F272A7004A47F5 /* tclUniData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUniData.c; sourceTree = "<group>"; };
+ F96D3F3408F272A7004A47F5 /* tclUtf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUtf.c; sourceTree = "<group>"; };
+ F96D3F3508F272A7004A47F5 /* tclUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUtil.c; sourceTree = "<group>"; };
+ F96D3F3608F272A7004A47F5 /* tclVar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclVar.c; sourceTree = "<group>"; };
+ F96D3F3708F272A7004A47F5 /* tommath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath.h; sourceTree = "<group>"; };
+ F96D3F3908F272A8004A47F5 /* auto.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = auto.tcl; sourceTree = "<group>"; };
+ F96D3F3A08F272A8004A47F5 /* clock.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clock.tcl; sourceTree = "<group>"; };
+ F96D3F3C08F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D3F8C08F272A8004A47F5 /* history.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = history.tcl; sourceTree = "<group>"; };
+ F96D3F8E08F272A8004A47F5 /* http.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.tcl; sourceTree = "<group>"; };
+ F96D3F8F08F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D3F9108F272A8004A47F5 /* http.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.tcl; sourceTree = "<group>"; };
+ F96D3F9208F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D3F9308F272A8004A47F5 /* init.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = init.tcl; sourceTree = "<group>"; };
+ F96D3F9508F272A8004A47F5 /* msgcat.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgcat.tcl; sourceTree = "<group>"; };
+ F96D3F9608F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D401808F272AA004A47F5 /* optparse.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = optparse.tcl; sourceTree = "<group>"; };
+ F96D401908F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D401A08F272AA004A47F5 /* package.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = package.tcl; sourceTree = "<group>"; };
+ F96D401B08F272AA004A47F5 /* parray.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parray.tcl; sourceTree = "<group>"; };
+ F96D401D08F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D401E08F272AA004A47F5 /* safe.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = safe.tcl; sourceTree = "<group>"; };
+ F96D401F08F272AA004A47F5 /* tclIndex */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclIndex; sourceTree = "<group>"; };
+ F96D402108F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D402208F272AA004A47F5 /* tcltest.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcltest.tcl; sourceTree = "<group>"; };
+ F96D402308F272AA004A47F5 /* tm.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tm.tcl; sourceTree = "<group>"; };
+ F96D425B08F272B2004A47F5 /* word.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = word.tcl; sourceTree = "<group>"; };
+ F96D425F08F272B3004A47F5 /* bn.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = bn.pdf; sourceTree = "<group>"; };
+ F96D426108F272B3004A47F5 /* bn_error.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_error.c; sourceTree = "<group>"; };
+ F96D426208F272B3004A47F5 /* bn_fast_mp_invmod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_mp_invmod.c; sourceTree = "<group>"; };
+ F96D426308F272B3004A47F5 /* bn_fast_mp_montgomery_reduce.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_mp_montgomery_reduce.c; sourceTree = "<group>"; };
+ F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_s_mp_mul_digs.c; sourceTree = "<group>"; };
+ F96D426508F272B3004A47F5 /* bn_fast_s_mp_mul_high_digs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_s_mp_mul_high_digs.c; sourceTree = "<group>"; };
+ F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_s_mp_sqr.c; sourceTree = "<group>"; };
+ F96D426708F272B3004A47F5 /* bn_mp_2expt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_2expt.c; sourceTree = "<group>"; };
+ F96D426808F272B3004A47F5 /* bn_mp_abs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_abs.c; sourceTree = "<group>"; };
+ F96D426908F272B3004A47F5 /* bn_mp_add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_add.c; sourceTree = "<group>"; };
+ F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_add_d.c; sourceTree = "<group>"; };
+ F96D426B08F272B3004A47F5 /* bn_mp_addmod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_addmod.c; sourceTree = "<group>"; };
+ F96D426C08F272B3004A47F5 /* bn_mp_and.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_and.c; sourceTree = "<group>"; };
+ F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clamp.c; sourceTree = "<group>"; };
+ F96D426E08F272B3004A47F5 /* bn_mp_clear.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clear.c; sourceTree = "<group>"; };
+ F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clear_multi.c; sourceTree = "<group>"; };
+ F96D427008F272B3004A47F5 /* bn_mp_cmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp.c; sourceTree = "<group>"; };
+ F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp_d.c; sourceTree = "<group>"; };
+ F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp_mag.c; sourceTree = "<group>"; };
+ F96D427308F272B3004A47F5 /* bn_mp_cnt_lsb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cnt_lsb.c; sourceTree = "<group>"; };
+ F96D427408F272B3004A47F5 /* bn_mp_copy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_copy.c; sourceTree = "<group>"; };
+ F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_count_bits.c; sourceTree = "<group>"; };
+ F96D427608F272B3004A47F5 /* bn_mp_div.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div.c; sourceTree = "<group>"; };
+ F96D427708F272B3004A47F5 /* bn_mp_div_2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2.c; sourceTree = "<group>"; };
+ F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2d.c; sourceTree = "<group>"; };
+ F96D427908F272B3004A47F5 /* bn_mp_div_3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_3.c; sourceTree = "<group>"; };
+ F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_d.c; sourceTree = "<group>"; };
+ F96D427B08F272B3004A47F5 /* bn_mp_dr_is_modulus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_dr_is_modulus.c; sourceTree = "<group>"; };
+ F96D427C08F272B3004A47F5 /* bn_mp_dr_reduce.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_dr_reduce.c; sourceTree = "<group>"; };
+ F96D427D08F272B3004A47F5 /* bn_mp_dr_setup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_dr_setup.c; sourceTree = "<group>"; };
+ F96D427E08F272B3004A47F5 /* bn_mp_exch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_exch.c; sourceTree = "<group>"; };
+ F96D427F08F272B3004A47F5 /* bn_mp_expt_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_expt_d.c; sourceTree = "<group>"; };
+ F96D428008F272B3004A47F5 /* bn_mp_exptmod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_exptmod.c; sourceTree = "<group>"; };
+ F96D428108F272B3004A47F5 /* bn_mp_exptmod_fast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_exptmod_fast.c; sourceTree = "<group>"; };
+ F96D428208F272B3004A47F5 /* bn_mp_exteuclid.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_exteuclid.c; sourceTree = "<group>"; };
+ F96D428308F272B3004A47F5 /* bn_mp_fread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_fread.c; sourceTree = "<group>"; };
+ F96D428408F272B3004A47F5 /* bn_mp_fwrite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_fwrite.c; sourceTree = "<group>"; };
+ F96D428508F272B3004A47F5 /* bn_mp_gcd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_gcd.c; sourceTree = "<group>"; };
+ F96D428608F272B3004A47F5 /* bn_mp_get_int.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_get_int.c; sourceTree = "<group>"; };
+ F96D428708F272B3004A47F5 /* bn_mp_grow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_grow.c; sourceTree = "<group>"; };
+ F96D428808F272B3004A47F5 /* bn_mp_init.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init.c; sourceTree = "<group>"; };
+ F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_copy.c; sourceTree = "<group>"; };
+ F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_multi.c; sourceTree = "<group>"; };
+ F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_set.c; sourceTree = "<group>"; };
+ F96D428C08F272B3004A47F5 /* bn_mp_init_set_int.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_set_int.c; sourceTree = "<group>"; };
+ F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_size.c; sourceTree = "<group>"; };
+ F96D428E08F272B3004A47F5 /* bn_mp_invmod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_invmod.c; sourceTree = "<group>"; };
+ F96D428F08F272B3004A47F5 /* bn_mp_invmod_slow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_invmod_slow.c; sourceTree = "<group>"; };
+ F96D429008F272B3004A47F5 /* bn_mp_is_square.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_is_square.c; sourceTree = "<group>"; };
+ F96D429108F272B3004A47F5 /* bn_mp_jacobi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_jacobi.c; sourceTree = "<group>"; };
+ F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_karatsuba_mul.c; sourceTree = "<group>"; };
+ F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_karatsuba_sqr.c; sourceTree = "<group>"; };
+ F96D429408F272B3004A47F5 /* bn_mp_lcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_lcm.c; sourceTree = "<group>"; };
+ F96D429508F272B3004A47F5 /* bn_mp_lshd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_lshd.c; sourceTree = "<group>"; };
+ F96D429608F272B3004A47F5 /* bn_mp_mod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mod.c; sourceTree = "<group>"; };
+ F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mod_2d.c; sourceTree = "<group>"; };
+ F96D429808F272B3004A47F5 /* bn_mp_mod_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mod_d.c; sourceTree = "<group>"; };
+ F96D429908F272B3004A47F5 /* bn_mp_montgomery_calc_normalization.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_montgomery_calc_normalization.c; sourceTree = "<group>"; };
+ F96D429A08F272B3004A47F5 /* bn_mp_montgomery_reduce.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_montgomery_reduce.c; sourceTree = "<group>"; };
+ F96D429B08F272B3004A47F5 /* bn_mp_montgomery_setup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_montgomery_setup.c; sourceTree = "<group>"; };
+ F96D429C08F272B3004A47F5 /* bn_mp_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul.c; sourceTree = "<group>"; };
+ F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_2.c; sourceTree = "<group>"; };
+ F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_2d.c; sourceTree = "<group>"; };
+ F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_d.c; sourceTree = "<group>"; };
+ F96D42A008F272B3004A47F5 /* bn_mp_mulmod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mulmod.c; sourceTree = "<group>"; };
+ F96D42A108F272B3004A47F5 /* bn_mp_n_root.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_n_root.c; sourceTree = "<group>"; };
+ F96D42A208F272B3004A47F5 /* bn_mp_neg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_neg.c; sourceTree = "<group>"; };
+ F96D42A308F272B3004A47F5 /* bn_mp_or.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_or.c; sourceTree = "<group>"; };
+ F96D42A408F272B3004A47F5 /* bn_mp_prime_fermat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_prime_fermat.c; sourceTree = "<group>"; };
+ F96D42A508F272B3004A47F5 /* bn_mp_prime_is_divisible.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_prime_is_divisible.c; sourceTree = "<group>"; };
+ F96D42A608F272B3004A47F5 /* bn_mp_prime_is_prime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_prime_is_prime.c; sourceTree = "<group>"; };
+ F96D42A708F272B3004A47F5 /* bn_mp_prime_miller_rabin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_prime_miller_rabin.c; sourceTree = "<group>"; };
+ F96D42A808F272B3004A47F5 /* bn_mp_prime_next_prime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_prime_next_prime.c; sourceTree = "<group>"; };
+ F96D42A908F272B3004A47F5 /* bn_mp_prime_rabin_miller_trials.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_prime_rabin_miller_trials.c; sourceTree = "<group>"; };
+ F96D42AA08F272B3004A47F5 /* bn_mp_prime_random_ex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_prime_random_ex.c; sourceTree = "<group>"; };
+ F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_radix_size.c; sourceTree = "<group>"; };
+ F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_radix_smap.c; sourceTree = "<group>"; };
+ F96D42AD08F272B3004A47F5 /* bn_mp_rand.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_rand.c; sourceTree = "<group>"; };
+ F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_read_radix.c; sourceTree = "<group>"; };
+ F96D42AF08F272B3004A47F5 /* bn_mp_read_signed_bin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_read_signed_bin.c; sourceTree = "<group>"; };
+ F96D42B008F272B3004A47F5 /* bn_mp_read_unsigned_bin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_read_unsigned_bin.c; sourceTree = "<group>"; };
+ F96D42B108F272B3004A47F5 /* bn_mp_reduce.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_reduce.c; sourceTree = "<group>"; };
+ F96D42B208F272B3004A47F5 /* bn_mp_reduce_2k.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_reduce_2k.c; sourceTree = "<group>"; };
+ F96D42B308F272B3004A47F5 /* bn_mp_reduce_2k_l.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_reduce_2k_l.c; sourceTree = "<group>"; };
+ F96D42B408F272B3004A47F5 /* bn_mp_reduce_2k_setup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_reduce_2k_setup.c; sourceTree = "<group>"; };
+ F96D42B508F272B3004A47F5 /* bn_mp_reduce_2k_setup_l.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_reduce_2k_setup_l.c; sourceTree = "<group>"; };
+ F96D42B608F272B3004A47F5 /* bn_mp_reduce_is_2k.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_reduce_is_2k.c; sourceTree = "<group>"; };
+ F96D42B708F272B3004A47F5 /* bn_mp_reduce_is_2k_l.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_reduce_is_2k_l.c; sourceTree = "<group>"; };
+ F96D42B808F272B3004A47F5 /* bn_mp_reduce_setup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_reduce_setup.c; sourceTree = "<group>"; };
+ F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_rshd.c; sourceTree = "<group>"; };
+ F96D42BA08F272B3004A47F5 /* bn_mp_set.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_set.c; sourceTree = "<group>"; };
+ F96D42BB08F272B3004A47F5 /* bn_mp_set_int.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_set_int.c; sourceTree = "<group>"; };
+ F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_shrink.c; sourceTree = "<group>"; };
+ F96D42BD08F272B3004A47F5 /* bn_mp_signed_bin_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_signed_bin_size.c; sourceTree = "<group>"; };
+ F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sqr.c; sourceTree = "<group>"; };
+ F96D42BF08F272B3004A47F5 /* bn_mp_sqrmod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sqrmod.c; sourceTree = "<group>"; };
+ F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sqrt.c; sourceTree = "<group>"; };
+ F96D42C108F272B3004A47F5 /* bn_mp_sub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sub.c; sourceTree = "<group>"; };
+ F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sub_d.c; sourceTree = "<group>"; };
+ F96D42C308F272B3004A47F5 /* bn_mp_submod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_submod.c; sourceTree = "<group>"; };
+ F96D42C408F272B3004A47F5 /* bn_mp_to_signed_bin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_to_signed_bin.c; sourceTree = "<group>"; };
+ F96D42C508F272B3004A47F5 /* bn_mp_to_signed_bin_n.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_to_signed_bin_n.c; sourceTree = "<group>"; };
+ F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_to_unsigned_bin.c; sourceTree = "<group>"; };
+ F96D42C708F272B3004A47F5 /* bn_mp_to_unsigned_bin_n.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_to_unsigned_bin_n.c; sourceTree = "<group>"; };
+ F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toom_mul.c; sourceTree = "<group>"; };
+ F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toom_sqr.c; sourceTree = "<group>"; };
+ F96D42CA08F272B3004A47F5 /* bn_mp_toradix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toradix.c; sourceTree = "<group>"; };
+ F96D42CB08F272B3004A47F5 /* bn_mp_toradix_n.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toradix_n.c; sourceTree = "<group>"; };
+ F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_unsigned_bin_size.c; sourceTree = "<group>"; };
+ F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_xor.c; sourceTree = "<group>"; };
+ F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_zero.c; sourceTree = "<group>"; };
+ F96D42CF08F272B3004A47F5 /* bn_prime_tab.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_prime_tab.c; sourceTree = "<group>"; };
+ F96D42D008F272B3004A47F5 /* bn_reverse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_reverse.c; sourceTree = "<group>"; };
+ F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_add.c; sourceTree = "<group>"; };
+ F96D42D208F272B3004A47F5 /* bn_s_mp_exptmod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_exptmod.c; sourceTree = "<group>"; };
+ F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_mul_digs.c; sourceTree = "<group>"; };
+ F96D42D408F272B3004A47F5 /* bn_s_mp_mul_high_digs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_mul_high_digs.c; sourceTree = "<group>"; };
+ F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_sqr.c; sourceTree = "<group>"; };
+ F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_sub.c; sourceTree = "<group>"; };
+ F96D42D708F272B3004A47F5 /* bncore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bncore.c; sourceTree = "<group>"; };
+ F96D42D908F272B3004A47F5 /* callgraph.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = callgraph.txt; sourceTree = "<group>"; };
+ F96D42DA08F272B3004A47F5 /* changes.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = changes.txt; sourceTree = "<group>"; };
+ F96D42F008F272B3004A47F5 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
+ F96D431D08F272B4004A47F5 /* poster.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = poster.pdf; sourceTree = "<group>"; };
+ F96D432608F272B4004A47F5 /* tommath.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = tommath.pdf; sourceTree = "<group>"; };
+ F96D432908F272B4004A47F5 /* tommath_class.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath_class.h; sourceTree = "<group>"; };
+ F96D432A08F272B4004A47F5 /* tommath_superclass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath_superclass.h; sourceTree = "<group>"; };
+ F96D432B08F272B4004A47F5 /* license.terms */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = license.terms; sourceTree = "<group>"; };
+ F96D432E08F272B5004A47F5 /* configure.ac */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure.ac; sourceTree = "<group>"; };
+ F96D432F08F272B5004A47F5 /* GNUmakefile */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = GNUmakefile; sourceTree = "<group>"; };
+ F96D433108F272B5004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D433208F272B5004A47F5 /* Tcl-Info.plist.in */ = {isa = PBXFileReference; explicitFileType = text.plist; fileEncoding = 4; path = "Tcl-Info.plist.in"; sourceTree = "<group>"; };
+ F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXBundle.c; sourceTree = "<group>"; };
+ F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXFCmd.c; sourceTree = "<group>"; };
+ F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXNotify.c; sourceTree = "<group>"; };
+ F96D434308F272B5004A47F5 /* README */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = README; sourceTree = "<group>"; };
+ F96D434508F272B5004A47F5 /* all.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = all.tcl; sourceTree = "<group>"; };
+ F96D434608F272B5004A47F5 /* append.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = append.test; sourceTree = "<group>"; };
+ F96D434708F272B5004A47F5 /* appendComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = appendComp.test; sourceTree = "<group>"; };
+ F96D434808F272B5004A47F5 /* assocd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = assocd.test; sourceTree = "<group>"; };
+ F96D434908F272B5004A47F5 /* async.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = async.test; sourceTree = "<group>"; };
+ F96D434A08F272B5004A47F5 /* autoMkindex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = autoMkindex.test; sourceTree = "<group>"; };
+ F96D434B08F272B5004A47F5 /* basic.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = basic.test; sourceTree = "<group>"; };
+ F96D434C08F272B5004A47F5 /* binary.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = binary.test; sourceTree = "<group>"; };
+ F96D434D08F272B5004A47F5 /* case.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = case.test; sourceTree = "<group>"; };
+ F96D434E08F272B5004A47F5 /* chan.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = chan.test; sourceTree = "<group>"; };
+ F96D434F08F272B5004A47F5 /* clock.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clock.test; sourceTree = "<group>"; };
+ F96D435008F272B5004A47F5 /* cmdAH.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdAH.test; sourceTree = "<group>"; };
+ F96D435108F272B5004A47F5 /* cmdIL.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdIL.test; sourceTree = "<group>"; };
+ F96D435208F272B5004A47F5 /* cmdInfo.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdInfo.test; sourceTree = "<group>"; };
+ F96D435308F272B5004A47F5 /* cmdMZ.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdMZ.test; sourceTree = "<group>"; };
+ F96D435408F272B5004A47F5 /* compExpr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "compExpr-old.test"; sourceTree = "<group>"; };
+ F96D435508F272B5004A47F5 /* compExpr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = compExpr.test; sourceTree = "<group>"; };
+ F96D435608F272B5004A47F5 /* compile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = compile.test; sourceTree = "<group>"; };
+ F96D435708F272B5004A47F5 /* concat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = concat.test; sourceTree = "<group>"; };
+ F96D435808F272B5004A47F5 /* config.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = config.test; sourceTree = "<group>"; };
+ F96D435908F272B5004A47F5 /* dcall.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dcall.test; sourceTree = "<group>"; };
+ F96D435A08F272B5004A47F5 /* dict.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dict.test; sourceTree = "<group>"; };
+ F96D435C08F272B5004A47F5 /* dstring.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dstring.test; sourceTree = "<group>"; };
+ F96D435E08F272B5004A47F5 /* encoding.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = encoding.test; sourceTree = "<group>"; };
+ F96D435F08F272B5004A47F5 /* env.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = env.test; sourceTree = "<group>"; };
+ F96D436008F272B5004A47F5 /* error.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = error.test; sourceTree = "<group>"; };
+ F96D436108F272B5004A47F5 /* eval.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = eval.test; sourceTree = "<group>"; };
+ F96D436208F272B5004A47F5 /* event.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = event.test; sourceTree = "<group>"; };
+ F96D436308F272B5004A47F5 /* exec.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = exec.test; sourceTree = "<group>"; };
+ F96D436408F272B5004A47F5 /* execute.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = execute.test; sourceTree = "<group>"; };
+ F96D436508F272B5004A47F5 /* expr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "expr-old.test"; sourceTree = "<group>"; };
+ F96D436608F272B5004A47F5 /* expr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = expr.test; sourceTree = "<group>"; };
+ F96D436708F272B6004A47F5 /* fCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fCmd.test; sourceTree = "<group>"; };
+ F96D436808F272B6004A47F5 /* fileName.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fileName.test; sourceTree = "<group>"; };
+ F96D436908F272B6004A47F5 /* fileSystem.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fileSystem.test; sourceTree = "<group>"; };
+ F96D436A08F272B6004A47F5 /* for-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "for-old.test"; sourceTree = "<group>"; };
+ F96D436B08F272B6004A47F5 /* for.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = for.test; sourceTree = "<group>"; };
+ F96D436C08F272B6004A47F5 /* foreach.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = foreach.test; sourceTree = "<group>"; };
+ F96D436D08F272B6004A47F5 /* format.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = format.test; sourceTree = "<group>"; };
+ F96D436E08F272B6004A47F5 /* get.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = get.test; sourceTree = "<group>"; };
+ F96D436F08F272B6004A47F5 /* history.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = history.test; sourceTree = "<group>"; };
+ F96D437008F272B6004A47F5 /* http.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.test; sourceTree = "<group>"; };
+ F96D437108F272B6004A47F5 /* httpd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = httpd; sourceTree = "<group>"; };
+ F96D437208F272B6004A47F5 /* httpold.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = httpold.test; sourceTree = "<group>"; };
+ F96D437308F272B6004A47F5 /* if-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "if-old.test"; sourceTree = "<group>"; };
+ F96D437408F272B6004A47F5 /* if.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = if.test; sourceTree = "<group>"; };
+ F96D437508F272B6004A47F5 /* incr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "incr-old.test"; sourceTree = "<group>"; };
+ F96D437608F272B6004A47F5 /* incr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = incr.test; sourceTree = "<group>"; };
+ F96D437708F272B6004A47F5 /* indexObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = indexObj.test; sourceTree = "<group>"; };
+ F96D437808F272B6004A47F5 /* info.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = info.test; sourceTree = "<group>"; };
+ F96D437908F272B6004A47F5 /* init.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = init.test; sourceTree = "<group>"; };
+ F96D437A08F272B6004A47F5 /* interp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = interp.test; sourceTree = "<group>"; };
+ F96D437B08F272B6004A47F5 /* io.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = io.test; sourceTree = "<group>"; };
+ F96D437C08F272B6004A47F5 /* ioCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ioCmd.test; sourceTree = "<group>"; };
+ F96D437D08F272B6004A47F5 /* iogt.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = iogt.test; sourceTree = "<group>"; };
+ F96D437E08F272B6004A47F5 /* ioUtil.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ioUtil.test; sourceTree = "<group>"; };
+ F96D437F08F272B6004A47F5 /* join.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = join.test; sourceTree = "<group>"; };
+ F96D438008F272B6004A47F5 /* lindex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lindex.test; sourceTree = "<group>"; };
+ F96D438108F272B6004A47F5 /* link.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = link.test; sourceTree = "<group>"; };
+ F96D438208F272B6004A47F5 /* linsert.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = linsert.test; sourceTree = "<group>"; };
+ F96D438308F272B6004A47F5 /* list.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = list.test; sourceTree = "<group>"; };
+ F96D438408F272B6004A47F5 /* listObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = listObj.test; sourceTree = "<group>"; };
+ F96D438508F272B6004A47F5 /* llength.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = llength.test; sourceTree = "<group>"; };
+ F96D438608F272B6004A47F5 /* load.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = load.test; sourceTree = "<group>"; };
+ F96D438708F272B6004A47F5 /* lrange.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lrange.test; sourceTree = "<group>"; };
+ F96D438808F272B6004A47F5 /* lrepeat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lrepeat.test; sourceTree = "<group>"; };
+ F96D438908F272B6004A47F5 /* lreplace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lreplace.test; sourceTree = "<group>"; };
+ F96D438A08F272B6004A47F5 /* lsearch.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lsearch.test; sourceTree = "<group>"; };
+ F96D438B08F272B6004A47F5 /* lset.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lset.test; sourceTree = "<group>"; };
+ F96D438C08F272B6004A47F5 /* lsetComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lsetComp.test; sourceTree = "<group>"; };
+ F96D438D08F272B6004A47F5 /* macOSXFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = macOSXFCmd.test; sourceTree = "<group>"; };
+ F96D438E08F272B6004A47F5 /* main.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = main.test; sourceTree = "<group>"; };
+ F96D438F08F272B6004A47F5 /* misc.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = misc.test; sourceTree = "<group>"; };
+ F96D439008F272B6004A47F5 /* msgcat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgcat.test; sourceTree = "<group>"; };
+ F96D439108F272B6004A47F5 /* namespace-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "namespace-old.test"; sourceTree = "<group>"; };
+ F96D439208F272B7004A47F5 /* namespace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = namespace.test; sourceTree = "<group>"; };
+ F96D439308F272B7004A47F5 /* notify.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = notify.test; sourceTree = "<group>"; };
+ F96D439408F272B7004A47F5 /* obj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = obj.test; sourceTree = "<group>"; };
+ F96D439508F272B7004A47F5 /* opt.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = opt.test; sourceTree = "<group>"; };
+ F96D439608F272B7004A47F5 /* package.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = package.test; sourceTree = "<group>"; };
+ F96D439708F272B7004A47F5 /* parse.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parse.test; sourceTree = "<group>"; };
+ F96D439808F272B7004A47F5 /* parseExpr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parseExpr.test; sourceTree = "<group>"; };
+ F96D439908F272B7004A47F5 /* parseOld.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parseOld.test; sourceTree = "<group>"; };
+ F96D439A08F272B7004A47F5 /* pid.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pid.test; sourceTree = "<group>"; };
+ F96D439B08F272B7004A47F5 /* pkg.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkg.test; sourceTree = "<group>"; };
+ F96D439C08F272B7004A47F5 /* pkgMkIndex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgMkIndex.test; sourceTree = "<group>"; };
+ F96D439D08F272B7004A47F5 /* platform.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = platform.test; sourceTree = "<group>"; };
+ F96D439E08F272B7004A47F5 /* proc-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "proc-old.test"; sourceTree = "<group>"; };
+ F96D439F08F272B7004A47F5 /* proc.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = proc.test; sourceTree = "<group>"; };
+ F96D43A008F272B7004A47F5 /* pwd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pwd.test; sourceTree = "<group>"; };
+ F96D43A108F272B7004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D43A208F272B7004A47F5 /* reg.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = reg.test; sourceTree = "<group>"; };
+ F96D43A308F272B7004A47F5 /* regexp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexp.test; sourceTree = "<group>"; };
+ F96D43A408F272B7004A47F5 /* regexpComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexpComp.test; sourceTree = "<group>"; };
+ F96D43A508F272B7004A47F5 /* registry.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = registry.test; sourceTree = "<group>"; };
+ F96D43A608F272B7004A47F5 /* remote.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = remote.tcl; sourceTree = "<group>"; };
+ F96D43A708F272B7004A47F5 /* rename.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = rename.test; sourceTree = "<group>"; };
+ F96D43A808F272B7004A47F5 /* result.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = result.test; sourceTree = "<group>"; };
+ F96D43A908F272B7004A47F5 /* safe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = safe.test; sourceTree = "<group>"; };
+ F96D43AA08F272B7004A47F5 /* scan.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scan.test; sourceTree = "<group>"; };
+ F96D43AB08F272B7004A47F5 /* security.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = security.test; sourceTree = "<group>"; };
+ F96D43AC08F272B7004A47F5 /* set-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "set-old.test"; sourceTree = "<group>"; };
+ F96D43AD08F272B7004A47F5 /* set.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = set.test; sourceTree = "<group>"; };
+ F96D43AE08F272B7004A47F5 /* socket.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = socket.test; sourceTree = "<group>"; };
+ F96D43AF08F272B7004A47F5 /* source.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = source.test; sourceTree = "<group>"; };
+ F96D43B008F272B7004A47F5 /* split.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = split.test; sourceTree = "<group>"; };
+ F96D43B108F272B7004A47F5 /* stack.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stack.test; sourceTree = "<group>"; };
+ F96D43B208F272B7004A47F5 /* string.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = string.test; sourceTree = "<group>"; };
+ F96D43B308F272B7004A47F5 /* stringComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stringComp.test; sourceTree = "<group>"; };
+ F96D43B408F272B7004A47F5 /* stringObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stringObj.test; sourceTree = "<group>"; };
+ F96D43B508F272B7004A47F5 /* subst.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = subst.test; sourceTree = "<group>"; };
+ F96D43B608F272B7004A47F5 /* switch.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = switch.test; sourceTree = "<group>"; };
+ F96D43B708F272B7004A47F5 /* tcltest.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcltest.test; sourceTree = "<group>"; };
+ F96D43B808F272B7004A47F5 /* thread.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = thread.test; sourceTree = "<group>"; };
+ F96D43B908F272B7004A47F5 /* timer.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = timer.test; sourceTree = "<group>"; };
+ F96D43BA08F272B7004A47F5 /* tm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tm.test; sourceTree = "<group>"; };
+ F96D43BB08F272B7004A47F5 /* trace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = trace.test; sourceTree = "<group>"; };
+ F96D43BC08F272B7004A47F5 /* unixFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixFCmd.test; sourceTree = "<group>"; };
+ F96D43BD08F272B7004A47F5 /* unixFile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixFile.test; sourceTree = "<group>"; };
+ F96D43BE08F272B7004A47F5 /* unixInit.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixInit.test; sourceTree = "<group>"; };
+ F96D43BF08F272B7004A47F5 /* unixNotfy.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixNotfy.test; sourceTree = "<group>"; };
+ F96D43C008F272B7004A47F5 /* unknown.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unknown.test; sourceTree = "<group>"; };
+ F96D43C108F272B7004A47F5 /* unload.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unload.test; sourceTree = "<group>"; };
+ F96D43C208F272B7004A47F5 /* uplevel.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uplevel.test; sourceTree = "<group>"; };
+ F96D43C308F272B7004A47F5 /* upvar.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = upvar.test; sourceTree = "<group>"; };
+ F96D43C408F272B7004A47F5 /* utf.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = utf.test; sourceTree = "<group>"; };
+ F96D43C508F272B7004A47F5 /* util.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = util.test; sourceTree = "<group>"; };
+ F96D43C608F272B7004A47F5 /* var.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = var.test; sourceTree = "<group>"; };
+ F96D43C708F272B7004A47F5 /* while-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "while-old.test"; sourceTree = "<group>"; };
+ F96D43C808F272B7004A47F5 /* while.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = while.test; sourceTree = "<group>"; };
+ F96D43C908F272B7004A47F5 /* winConsole.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winConsole.test; sourceTree = "<group>"; };
+ F96D43CA08F272B7004A47F5 /* winDde.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winDde.test; sourceTree = "<group>"; };
+ F96D43CB08F272B7004A47F5 /* winFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFCmd.test; sourceTree = "<group>"; };
+ F96D43CC08F272B7004A47F5 /* winFile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFile.test; sourceTree = "<group>"; };
+ F96D43CD08F272B7004A47F5 /* winNotify.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winNotify.test; sourceTree = "<group>"; };
+ F96D43CE08F272B7004A47F5 /* winPipe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winPipe.test; sourceTree = "<group>"; };
+ F96D43CF08F272B7004A47F5 /* winTime.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winTime.test; sourceTree = "<group>"; };
+ F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = checkLibraryDoc.tcl; sourceTree = "<group>"; };
+ F96D43D208F272B8004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
+ F96D43D308F272B8004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
+ F96D442208F272B8004A47F5 /* eolFix.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = eolFix.tcl; sourceTree = "<group>"; };
+ F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fix_tommath_h.tcl; sourceTree = "<group>"; };
+ F96D442508F272B8004A47F5 /* genStubs.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = genStubs.tcl; sourceTree = "<group>"; };
+ F96D442708F272B8004A47F5 /* index.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = index.tcl; sourceTree = "<group>"; };
+ F96D442808F272B8004A47F5 /* installData.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = installData.tcl; sourceTree = "<group>"; };
+ F96D442908F272B8004A47F5 /* loadICU.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = loadICU.tcl; sourceTree = "<group>"; };
+ F96D442A08F272B8004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
+ F96D442B08F272B8004A47F5 /* makeTestCases.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = makeTestCases.tcl; sourceTree = "<group>"; };
+ F96D442C08F272B8004A47F5 /* man2help.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2help.tcl; sourceTree = "<group>"; };
+ F96D442D08F272B8004A47F5 /* man2help2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2help2.tcl; sourceTree = "<group>"; };
+ F96D442E08F272B8004A47F5 /* man2html.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html.tcl; sourceTree = "<group>"; };
+ F96D442F08F272B8004A47F5 /* man2html1.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html1.tcl; sourceTree = "<group>"; };
+ F96D443008F272B8004A47F5 /* man2html2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html2.tcl; sourceTree = "<group>"; };
+ F96D443108F272B8004A47F5 /* man2tcl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = man2tcl.c; sourceTree = "<group>"; };
+ F96D443208F272B8004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D443308F272B8004A47F5 /* regexpTestLib.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexpTestLib.tcl; sourceTree = "<group>"; };
+ F96D443408F272B8004A47F5 /* str2c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = str2c; sourceTree = "<group>"; };
+ F96D443508F272B8004A47F5 /* tcl.hpj.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.hpj.in; sourceTree = "<group>"; };
+ F96D443608F272B8004A47F5 /* tcl.wse.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.wse.in; sourceTree = "<group>"; };
+ F96D443708F272B9004A47F5 /* tclmin.wse */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tclmin.wse; sourceTree = "<group>"; };
+ F96D443908F272B9004A47F5 /* tcltk-man2html.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "tcltk-man2html.tcl"; sourceTree = "<group>"; };
+ F96D443A08F272B9004A47F5 /* tclZIC.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclZIC.tcl; sourceTree = "<group>"; };
+ F96D443B08F272B9004A47F5 /* uniClass.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniClass.tcl; sourceTree = "<group>"; };
+ F96D443C08F272B9004A47F5 /* uniParse.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniParse.tcl; sourceTree = "<group>"; };
+ F96D444008F272B9004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
+ F96D444108F272B9004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
+ F96D444208F272B9004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
+ F96D444408F272B9004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
+ F96D444508F272B9004A47F5 /* pkga.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkga.c; sourceTree = "<group>"; };
+ F96D444608F272B9004A47F5 /* pkgb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgb.c; sourceTree = "<group>"; };
+ F96D444708F272B9004A47F5 /* pkgc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgc.c; sourceTree = "<group>"; };
+ F96D444808F272B9004A47F5 /* pkgd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgd.c; sourceTree = "<group>"; };
+ F96D444908F272B9004A47F5 /* pkge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkge.c; sourceTree = "<group>"; };
+ F96D444B08F272B9004A47F5 /* pkgua.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgua.c; sourceTree = "<group>"; };
+ F96D444C08F272B9004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D444D08F272B9004A47F5 /* install-sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "install-sh"; sourceTree = "<group>"; };
+ F96D444E08F272B9004A47F5 /* installManPage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = installManPage; sourceTree = "<group>"; };
+ F96D444F08F272B9004A47F5 /* ldAix */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ldAix; sourceTree = "<group>"; };
+ F96D445008F272B9004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
+ F96D445208F272B9004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D445308F272B9004A47F5 /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = "<group>"; };
+ F96D445408F272B9004A47F5 /* tcl.spec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.spec; sourceTree = "<group>"; };
+ F96D445508F272B9004A47F5 /* tclAppInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAppInit.c; sourceTree = "<group>"; };
+ F96D445608F272B9004A47F5 /* tclConfig.h.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = tclConfig.h.in; sourceTree = "<group>"; };
+ F96D445708F272B9004A47F5 /* tclConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tclConfig.sh.in; sourceTree = "<group>"; };
+ F96D445808F272B9004A47F5 /* tclLoadAix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadAix.c; sourceTree = "<group>"; };
+ F96D445908F272B9004A47F5 /* tclLoadDl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadDl.c; sourceTree = "<group>"; };
+ F96D445B08F272B9004A47F5 /* tclLoadDyld.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadDyld.c; sourceTree = "<group>"; };
+ F96D445C08F272B9004A47F5 /* tclLoadNext.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadNext.c; sourceTree = "<group>"; };
+ F96D445D08F272B9004A47F5 /* tclLoadOSF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadOSF.c; sourceTree = "<group>"; };
+ F96D445E08F272B9004A47F5 /* tclLoadShl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadShl.c; sourceTree = "<group>"; };
+ F96D445F08F272B9004A47F5 /* tclUnixChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixChan.c; sourceTree = "<group>"; };
+ F96D446008F272B9004A47F5 /* tclUnixEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixEvent.c; sourceTree = "<group>"; };
+ F96D446108F272B9004A47F5 /* tclUnixFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixFCmd.c; sourceTree = "<group>"; };
+ F96D446208F272B9004A47F5 /* tclUnixFile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixFile.c; sourceTree = "<group>"; };
+ F96D446308F272B9004A47F5 /* tclUnixInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixInit.c; sourceTree = "<group>"; };
+ F96D446408F272B9004A47F5 /* tclUnixNotfy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixNotfy.c; sourceTree = "<group>"; };
+ F96D446508F272B9004A47F5 /* tclUnixPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixPipe.c; sourceTree = "<group>"; };
+ F96D446608F272B9004A47F5 /* tclUnixPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclUnixPort.h; sourceTree = "<group>"; };
+ F96D446708F272B9004A47F5 /* tclUnixSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixSock.c; sourceTree = "<group>"; };
+ F96D446808F272B9004A47F5 /* tclUnixTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTest.c; sourceTree = "<group>"; };
+ F96D446908F272B9004A47F5 /* tclUnixThrd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixThrd.c; sourceTree = "<group>"; };
+ F96D446A08F272B9004A47F5 /* tclUnixThrd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclUnixThrd.h; sourceTree = "<group>"; };
+ F96D446B08F272B9004A47F5 /* tclUnixTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTime.c; sourceTree = "<group>"; };
+ F96D446C08F272B9004A47F5 /* tclXtNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtNotify.c; sourceTree = "<group>"; };
+ F96D446D08F272B9004A47F5 /* tclXtTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtTest.c; sourceTree = "<group>"; };
+ F96D447008F272BA004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
+ F96D447108F272BA004A47F5 /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = "<group>"; };
+ F96D447208F272BA004A47F5 /* cat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cat.c; sourceTree = "<group>"; };
+ F96D447308F272BA004A47F5 /* coffbase.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = coffbase.txt; sourceTree = "<group>"; };
+ F96D447408F272BA004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
+ F96D447508F272BA004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
+ F96D447608F272BA004A47F5 /* makefile.bc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.bc; sourceTree = "<group>"; };
+ F96D447708F272BA004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
+ F96D447808F272BA004A47F5 /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = "<group>"; };
+ F96D447908F272BA004A47F5 /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = "<group>"; };
+ F96D447A08F272BA004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D447C08F272BA004A47F5 /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = "<group>"; };
+ F96D447D08F272BA004A47F5 /* stub16.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stub16.c; sourceTree = "<group>"; };
+ F96D447E08F272BA004A47F5 /* tcl.dsp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.dsp; sourceTree = "<group>"; };
+ F96D447F08F272BA004A47F5 /* tcl.dsw */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.dsw; sourceTree = "<group>"; };
+ F96D448008F272BA004A47F5 /* tcl.hpj.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.hpj.in; sourceTree = "<group>"; };
+ F96D448108F272BA004A47F5 /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = "<group>"; };
+ F96D448208F272BA004A47F5 /* tcl.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.rc; sourceTree = "<group>"; };
+ F96D448308F272BA004A47F5 /* tclAppInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAppInit.c; sourceTree = "<group>"; };
+ F96D448408F272BA004A47F5 /* tclConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tclConfig.sh.in; sourceTree = "<group>"; };
+ F96D448608F272BA004A47F5 /* tclsh.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tclsh.rc; sourceTree = "<group>"; };
+ F96D448708F272BA004A47F5 /* tclWin32Dll.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWin32Dll.c; sourceTree = "<group>"; };
+ F96D448808F272BA004A47F5 /* tclWinChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinChan.c; sourceTree = "<group>"; };
+ F96D448908F272BA004A47F5 /* tclWinConsole.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinConsole.c; sourceTree = "<group>"; };
+ F96D448A08F272BA004A47F5 /* tclWinDde.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinDde.c; sourceTree = "<group>"; };
+ F96D448B08F272BA004A47F5 /* tclWinError.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinError.c; sourceTree = "<group>"; };
+ F96D448C08F272BA004A47F5 /* tclWinFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinFCmd.c; sourceTree = "<group>"; };
+ F96D448D08F272BA004A47F5 /* tclWinFile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinFile.c; sourceTree = "<group>"; };
+ F96D448E08F272BA004A47F5 /* tclWinInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinInit.c; sourceTree = "<group>"; };
+ F96D448F08F272BA004A47F5 /* tclWinInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinInt.h; sourceTree = "<group>"; };
+ F96D449008F272BA004A47F5 /* tclWinLoad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinLoad.c; sourceTree = "<group>"; };
+ F96D449108F272BA004A47F5 /* tclWinNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinNotify.c; sourceTree = "<group>"; };
+ F96D449208F272BA004A47F5 /* tclWinPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinPipe.c; sourceTree = "<group>"; };
+ F96D449308F272BA004A47F5 /* tclWinPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinPort.h; sourceTree = "<group>"; };
+ F96D449408F272BA004A47F5 /* tclWinReg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinReg.c; sourceTree = "<group>"; };
+ F96D449508F272BA004A47F5 /* tclWinSerial.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSerial.c; sourceTree = "<group>"; };
+ F96D449608F272BA004A47F5 /* tclWinSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSock.c; sourceTree = "<group>"; };
+ F96D449708F272BA004A47F5 /* tclWinTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTest.c; sourceTree = "<group>"; };
+ F96D449808F272BA004A47F5 /* tclWinThrd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinThrd.c; sourceTree = "<group>"; };
+ F96D449908F272BA004A47F5 /* tclWinThrd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinThrd.h; sourceTree = "<group>"; };
+ F96D449A08F272BA004A47F5 /* tclWinTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTime.c; sourceTree = "<group>"; };
+ F97AE7F10B65C1E900310EA2 /* Tcl-Common.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Common.xcconfig"; sourceTree = "<group>"; };
+ F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Release.xcconfig"; sourceTree = "<group>"; };
+ F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Debug.xcconfig"; sourceTree = "<group>"; };
+ F9903CAF094FAADA004613E9 /* tclTomMath.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclTomMath.decls; sourceTree = "<group>"; };
+ F9903CB0094FAADA004613E9 /* tclTomMathDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclTomMathDecls.h; sourceTree = "<group>"; };
+ F9A3084B08F2D4CE00BAE1AB /* tclsh */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tclsh; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9A3084E08F2D4F400BAE1AB /* Tcl.framework */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.framework; path = Tcl.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9A493240CEBF38300B78AE2 /* chanio.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = chanio.test; sourceTree = "<group>"; };
+ F9ECB1120B26521500A28025 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F9ECB1130B26521500A28025 /* platform.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = platform.tcl; sourceTree = "<group>"; };
+ F9ECB1140B26521500A28025 /* shell.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = shell.tcl; sourceTree = "<group>"; };
+ F9ECB1CA0B2652D300A28025 /* apply.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = apply.test; sourceTree = "<group>"; };
+ F9ECB1CB0B26534C00A28025 /* mathop.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = mathop.test; sourceTree = "<group>"; };
+ F9ECB1E10B26543C00A28025 /* platform_shell.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = platform_shell.n; sourceTree = "<group>"; };
+ F9ECB1E20B26543C00A28025 /* platform.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = platform.n; sourceTree = "<group>"; };
+ F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixCompat.c; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8DD76FAD0486AB0100D96B5E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F966C07508F2820D005CB29B /* CoreFoundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 08FB7794FE84155DC02AAC07 /* Tcl */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3DF608F27169004A47F5 /* Tcl Sources */,
+ F966C06F08F281DC005CB29B /* Frameworks */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ );
+ comments = "Copyright (c) 2004-2008 Daniel A. Steffen <das@users.sourceforge.net>\n\nSee the file \"license.terms\" for information on usage and redistribution of\nthis file, and for a DISCLAIMER OF ALL WARRANTIES.\n";
+ name = Tcl;
+ path = .;
+ sourceTree = SOURCE_ROOT;
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ F9A3084B08F2D4CE00BAE1AB /* tclsh */,
+ 8DD76FB20486AB0100D96B5E /* tcltest */,
+ F9A3084E08F2D4F400BAE1AB /* Tcl.framework */,
+ );
+ includeInIndex = 0;
+ name = Products;
+ sourceTree = "<group>";
+ };
+ F966C06F08F281DC005CB29B /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ F966C07408F2820D005CB29B /* CoreFoundation.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ F96D3DF608F27169004A47F5 /* Tcl Sources */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3EC908F272A7004A47F5 /* generic */,
+ F96D432C08F272B4004A47F5 /* macosx */,
+ F96D443E08F272B9004A47F5 /* unix */,
+ F96D425C08F272B2004A47F5 /* libtommath */,
+ F96D446E08F272B9004A47F5 /* win */,
+ F96D3F3808F272A7004A47F5 /* library */,
+ F96D434408F272B5004A47F5 /* tests */,
+ F96D3DFC08F272A4004A47F5 /* doc */,
+ F96D43D008F272B8004A47F5 /* tools */,
+ F96D3DFA08F272A4004A47F5 /* ChangeLog */,
+ F96D3DFB08F272A4004A47F5 /* changes */,
+ F96D434308F272B5004A47F5 /* README */,
+ F96D432B08F272B4004A47F5 /* license.terms */,
+ );
+ name = "Tcl Sources";
+ sourceTree = TCL_SRCROOT;
+ };
+ F96D3DFC08F272A4004A47F5 /* doc */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3DFD08F272A4004A47F5 /* Access.3 */,
+ F96D3DFE08F272A4004A47F5 /* AddErrInfo.3 */,
+ F96D3DFF08F272A4004A47F5 /* after.n */,
+ F96D3E0008F272A4004A47F5 /* Alloc.3 */,
+ F96D3E0108F272A4004A47F5 /* AllowExc.3 */,
+ F96D3E0208F272A4004A47F5 /* append.n */,
+ F96D3E0308F272A4004A47F5 /* AppInit.3 */,
+ F96D3E0408F272A5004A47F5 /* array.n */,
+ F96D3E0508F272A5004A47F5 /* AssocData.3 */,
+ F96D3E0608F272A5004A47F5 /* Async.3 */,
+ F96D3E0708F272A5004A47F5 /* BackgdErr.3 */,
+ F96D3E0808F272A5004A47F5 /* Backslash.3 */,
+ F96D3E0908F272A5004A47F5 /* bgerror.n */,
+ F96D3E0A08F272A5004A47F5 /* binary.n */,
+ F96D3E0B08F272A5004A47F5 /* BoolObj.3 */,
+ F96D3E0C08F272A5004A47F5 /* break.n */,
+ F96D3E0D08F272A5004A47F5 /* ByteArrObj.3 */,
+ F96D3E0E08F272A5004A47F5 /* CallDel.3 */,
+ F96D3E0F08F272A5004A47F5 /* case.n */,
+ F96D3E1008F272A5004A47F5 /* catch.n */,
+ F96D3E1108F272A5004A47F5 /* cd.n */,
+ F96D3E1208F272A5004A47F5 /* chan.n */,
+ F96D3E1308F272A5004A47F5 /* ChnlStack.3 */,
+ F96D3E1408F272A5004A47F5 /* clock.n */,
+ F96D3E1508F272A5004A47F5 /* close.n */,
+ F96D3E1608F272A5004A47F5 /* CmdCmplt.3 */,
+ F96D3E1708F272A5004A47F5 /* Concat.3 */,
+ F96D3E1808F272A5004A47F5 /* concat.n */,
+ F96D3E1908F272A5004A47F5 /* continue.n */,
+ F96D3E1A08F272A5004A47F5 /* CrtChannel.3 */,
+ F96D3E1B08F272A5004A47F5 /* CrtChnlHdlr.3 */,
+ F96D3E1C08F272A5004A47F5 /* CrtCloseHdlr.3 */,
+ F96D3E1D08F272A5004A47F5 /* CrtCommand.3 */,
+ F96D3E1E08F272A5004A47F5 /* CrtFileHdlr.3 */,
+ F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */,
+ F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */,
+ F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */,
+ F96D3E2208F272A5004A47F5 /* CrtSlave.3 */,
+ F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */,
+ F96D3E2408F272A5004A47F5 /* CrtTrace.3 */,
+ F96D3E2508F272A5004A47F5 /* dde.n */,
+ F96D3E2608F272A5004A47F5 /* DetachPids.3 */,
+ F96D3E2708F272A5004A47F5 /* dict.n */,
+ F96D3E2808F272A5004A47F5 /* DictObj.3 */,
+ F96D3E2908F272A5004A47F5 /* DoOneEvent.3 */,
+ F96D3E2A08F272A5004A47F5 /* DoubleObj.3 */,
+ F96D3E2B08F272A5004A47F5 /* DoWhenIdle.3 */,
+ F96D3E2C08F272A5004A47F5 /* DString.3 */,
+ F96D3E2D08F272A5004A47F5 /* DumpActiveMemory.3 */,
+ F96D3E2E08F272A5004A47F5 /* Encoding.3 */,
+ F96D3E2F08F272A5004A47F5 /* encoding.n */,
+ F96D3E3008F272A5004A47F5 /* Ensemble.3 */,
+ F96D3E3108F272A5004A47F5 /* Environment.3 */,
+ F96D3E3208F272A5004A47F5 /* eof.n */,
+ F96D3E3308F272A5004A47F5 /* error.n */,
+ F96D3E3408F272A5004A47F5 /* Eval.3 */,
+ F96D3E3508F272A5004A47F5 /* eval.n */,
+ F96D3E3608F272A5004A47F5 /* exec.n */,
+ F96D3E3708F272A5004A47F5 /* Exit.3 */,
+ F96D3E3808F272A5004A47F5 /* exit.n */,
+ F96D3E3908F272A5004A47F5 /* expr.n */,
+ F96D3E3A08F272A5004A47F5 /* ExprLong.3 */,
+ F96D3E3B08F272A5004A47F5 /* ExprLongObj.3 */,
+ F96D3E3C08F272A5004A47F5 /* fblocked.n */,
+ F96D3E3D08F272A5004A47F5 /* fconfigure.n */,
+ F96D3E3E08F272A5004A47F5 /* fcopy.n */,
+ F96D3E3F08F272A5004A47F5 /* file.n */,
+ F96D3E4008F272A5004A47F5 /* fileevent.n */,
+ F96D3E4108F272A5004A47F5 /* filename.n */,
+ F96D3E4208F272A5004A47F5 /* FileSystem.3 */,
+ F96D3E4308F272A5004A47F5 /* FindExec.3 */,
+ F96D3E4408F272A5004A47F5 /* flush.n */,
+ F96D3E4508F272A5004A47F5 /* for.n */,
+ F96D3E4608F272A5004A47F5 /* foreach.n */,
+ F96D3E4708F272A5004A47F5 /* format.n */,
+ F96D3E4808F272A5004A47F5 /* GetCwd.3 */,
+ F96D3E4908F272A5004A47F5 /* GetHostName.3 */,
+ F96D3E4A08F272A5004A47F5 /* GetIndex.3 */,
+ F96D3E4B08F272A5004A47F5 /* GetInt.3 */,
+ F96D3E4C08F272A5004A47F5 /* GetOpnFl.3 */,
+ F96D3E4D08F272A5004A47F5 /* gets.n */,
+ F96D3E4E08F272A5004A47F5 /* GetStdChan.3 */,
+ F96D3E4F08F272A5004A47F5 /* GetTime.3 */,
+ F96D3E5008F272A5004A47F5 /* GetVersion.3 */,
+ F96D3E5108F272A5004A47F5 /* glob.n */,
+ F96D3E5208F272A6004A47F5 /* global.n */,
+ F96D3E5308F272A6004A47F5 /* Hash.3 */,
+ F96D3E5408F272A6004A47F5 /* history.n */,
+ F96D3E5508F272A6004A47F5 /* http.n */,
+ F96D3E5608F272A6004A47F5 /* if.n */,
+ F96D3E5708F272A6004A47F5 /* incr.n */,
+ F96D3E5808F272A6004A47F5 /* info.n */,
+ F96D3E5908F272A6004A47F5 /* Init.3 */,
+ F96D3E5A08F272A6004A47F5 /* InitStubs.3 */,
+ F96D3E5B08F272A6004A47F5 /* Interp.3 */,
+ F96D3E5C08F272A6004A47F5 /* interp.n */,
+ F96D3E5D08F272A6004A47F5 /* IntObj.3 */,
+ F96D3E5E08F272A6004A47F5 /* join.n */,
+ F96D3E5F08F272A6004A47F5 /* lappend.n */,
+ F96D3E6008F272A6004A47F5 /* lassign.n */,
+ F96D3E6108F272A6004A47F5 /* library.n */,
+ F96D3E6208F272A6004A47F5 /* Limit.3 */,
+ F96D3E6308F272A6004A47F5 /* lindex.n */,
+ F96D3E6408F272A6004A47F5 /* LinkVar.3 */,
+ F96D3E6508F272A6004A47F5 /* linsert.n */,
+ F96D3E6608F272A6004A47F5 /* list.n */,
+ F96D3E6708F272A6004A47F5 /* ListObj.3 */,
+ F96D3E6808F272A6004A47F5 /* llength.n */,
+ F96D3E6908F272A6004A47F5 /* load.n */,
+ F96D3E6A08F272A6004A47F5 /* lrange.n */,
+ F96D3E6B08F272A6004A47F5 /* lrepeat.n */,
+ F96D3E6C08F272A6004A47F5 /* lreplace.n */,
+ F96D3E6D08F272A6004A47F5 /* lsearch.n */,
+ F96D3E6E08F272A6004A47F5 /* lset.n */,
+ F96D3E6F08F272A6004A47F5 /* lsort.n */,
+ F96D3E7008F272A6004A47F5 /* man.macros */,
+ F96D3E7108F272A6004A47F5 /* mathfunc.n */,
+ F96D3E7208F272A6004A47F5 /* memory.n */,
+ F96D3E7308F272A6004A47F5 /* msgcat.n */,
+ F96D3E7408F272A6004A47F5 /* Namespace.3 */,
+ F96D3E7508F272A6004A47F5 /* namespace.n */,
+ F96D3E7608F272A6004A47F5 /* Notifier.3 */,
+ F96D3E7708F272A6004A47F5 /* Object.3 */,
+ F96D3E7808F272A6004A47F5 /* ObjectType.3 */,
+ F96D3E7908F272A6004A47F5 /* open.n */,
+ F96D3E7A08F272A6004A47F5 /* OpenFileChnl.3 */,
+ F96D3E7B08F272A6004A47F5 /* OpenTcp.3 */,
+ F96D3E7C08F272A6004A47F5 /* package.n */,
+ F96D3E7D08F272A6004A47F5 /* packagens.n */,
+ F96D3E7E08F272A6004A47F5 /* Panic.3 */,
+ F96D3E7F08F272A6004A47F5 /* ParseCmd.3 */,
+ F96D3E8008F272A6004A47F5 /* pid.n */,
+ F96D3E8108F272A6004A47F5 /* pkgMkIndex.n */,
+ F96D3E8208F272A6004A47F5 /* PkgRequire.3 */,
+ F9ECB1E10B26543C00A28025 /* platform_shell.n */,
+ F9ECB1E20B26543C00A28025 /* platform.n */,
+ F96D3E8308F272A6004A47F5 /* Preserve.3 */,
+ F96D3E8408F272A6004A47F5 /* PrintDbl.3 */,
+ F96D3E8508F272A6004A47F5 /* proc.n */,
+ F96D3E8608F272A6004A47F5 /* puts.n */,
+ F96D3E8708F272A6004A47F5 /* pwd.n */,
+ F96D3E8808F272A6004A47F5 /* re_syntax.n */,
+ F96D3E8908F272A6004A47F5 /* read.n */,
+ F96D3E8A08F272A6004A47F5 /* RecEvalObj.3 */,
+ F96D3E8B08F272A6004A47F5 /* RecordEval.3 */,
+ F96D3E8C08F272A6004A47F5 /* RegConfig.3 */,
+ F96D3E8D08F272A6004A47F5 /* RegExp.3 */,
+ F96D3E8E08F272A6004A47F5 /* regexp.n */,
+ F96D3E8F08F272A6004A47F5 /* registry.n */,
+ F96D3E9008F272A6004A47F5 /* regsub.n */,
+ F96D3E9108F272A6004A47F5 /* rename.n */,
+ F96D3E9208F272A6004A47F5 /* return.n */,
+ F96D3E9308F272A6004A47F5 /* safe.n */,
+ F96D3E9408F272A6004A47F5 /* SaveResult.3 */,
+ F96D3E9508F272A6004A47F5 /* scan.n */,
+ F96D3E9608F272A6004A47F5 /* seek.n */,
+ F96D3E9708F272A6004A47F5 /* set.n */,
+ F96D3E9808F272A6004A47F5 /* SetChanErr.3 */,
+ F96D3E9908F272A6004A47F5 /* SetErrno.3 */,
+ F96D3E9A08F272A6004A47F5 /* SetRecLmt.3 */,
+ F96D3E9B08F272A7004A47F5 /* SetResult.3 */,
+ F96D3E9C08F272A7004A47F5 /* SetVar.3 */,
+ F96D3E9D08F272A7004A47F5 /* Signal.3 */,
+ F96D3E9E08F272A7004A47F5 /* Sleep.3 */,
+ F96D3E9F08F272A7004A47F5 /* socket.n */,
+ F96D3EA008F272A7004A47F5 /* source.n */,
+ F96D3EA108F272A7004A47F5 /* SourceRCFile.3 */,
+ F96D3EA208F272A7004A47F5 /* split.n */,
+ F96D3EA308F272A7004A47F5 /* SplitList.3 */,
+ F96D3EA408F272A7004A47F5 /* SplitPath.3 */,
+ F96D3EA508F272A7004A47F5 /* StaticPkg.3 */,
+ F96D3EA608F272A7004A47F5 /* StdChannels.3 */,
+ F96D3EA708F272A7004A47F5 /* string.n */,
+ F96D3EA808F272A7004A47F5 /* StringObj.3 */,
+ F96D3EA908F272A7004A47F5 /* StrMatch.3 */,
+ F96D3EAA08F272A7004A47F5 /* subst.n */,
+ F96D3EAB08F272A7004A47F5 /* SubstObj.3 */,
+ F96D3EAC08F272A7004A47F5 /* switch.n */,
+ F96D3EAD08F272A7004A47F5 /* Tcl.n */,
+ F96D3EAE08F272A7004A47F5 /* Tcl_Main.3 */,
+ F96D3EAF08F272A7004A47F5 /* TCL_MEM_DEBUG.3 */,
+ F96D3EB008F272A7004A47F5 /* tclsh.1 */,
+ F96D3EB108F272A7004A47F5 /* tcltest.n */,
+ F96D3EB208F272A7004A47F5 /* tclvars.n */,
+ F96D3EB308F272A7004A47F5 /* tell.n */,
+ F96D3EB408F272A7004A47F5 /* Thread.3 */,
+ F96D3EB508F272A7004A47F5 /* time.n */,
+ F96D3EB608F272A7004A47F5 /* tm.n */,
+ F96D3EB708F272A7004A47F5 /* ToUpper.3 */,
+ F96D3EB808F272A7004A47F5 /* trace.n */,
+ F96D3EB908F272A7004A47F5 /* TraceCmd.3 */,
+ F96D3EBA08F272A7004A47F5 /* TraceVar.3 */,
+ F96D3EBB08F272A7004A47F5 /* Translate.3 */,
+ F96D3EBC08F272A7004A47F5 /* UniCharIsAlpha.3 */,
+ F96D3EBD08F272A7004A47F5 /* unknown.n */,
+ F96D3EBE08F272A7004A47F5 /* unload.n */,
+ F96D3EBF08F272A7004A47F5 /* unset.n */,
+ F96D3EC008F272A7004A47F5 /* update.n */,
+ F96D3EC108F272A7004A47F5 /* uplevel.n */,
+ F96D3EC208F272A7004A47F5 /* UpVar.3 */,
+ F96D3EC308F272A7004A47F5 /* upvar.n */,
+ F96D3EC408F272A7004A47F5 /* Utf.3 */,
+ F96D3EC508F272A7004A47F5 /* variable.n */,
+ F96D3EC608F272A7004A47F5 /* vwait.n */,
+ F96D3EC708F272A7004A47F5 /* while.n */,
+ F96D3EC808F272A7004A47F5 /* WrongNumArgs.3 */,
+ );
+ path = doc;
+ sourceTree = "<group>";
+ };
+ F96D3EC908F272A7004A47F5 /* generic */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3ECA08F272A7004A47F5 /* README */,
+ F96D3ECB08F272A7004A47F5 /* regc_color.c */,
+ F96D3ECC08F272A7004A47F5 /* regc_cvec.c */,
+ F96D3ECD08F272A7004A47F5 /* regc_lex.c */,
+ F96D3ECE08F272A7004A47F5 /* regc_locale.c */,
+ F96D3ECF08F272A7004A47F5 /* regc_nfa.c */,
+ F96D3ED008F272A7004A47F5 /* regcomp.c */,
+ F96D3ED108F272A7004A47F5 /* regcustom.h */,
+ F96D3ED208F272A7004A47F5 /* rege_dfa.c */,
+ F96D3ED308F272A7004A47F5 /* regerror.c */,
+ F96D3ED408F272A7004A47F5 /* regerrs.h */,
+ F96D3ED508F272A7004A47F5 /* regex.h */,
+ F96D3ED608F272A7004A47F5 /* regexec.c */,
+ F96D3ED708F272A7004A47F5 /* regfree.c */,
+ F96D3ED808F272A7004A47F5 /* regfronts.c */,
+ F96D3ED908F272A7004A47F5 /* regguts.h */,
+ F96D3EDA08F272A7004A47F5 /* tcl.decls */,
+ F96D3EDB08F272A7004A47F5 /* tcl.h */,
+ F96D3EDC08F272A7004A47F5 /* tclAlloc.c */,
+ F96D3EDD08F272A7004A47F5 /* tclAsync.c */,
+ F96D3EDE08F272A7004A47F5 /* tclBasic.c */,
+ F96D3EDF08F272A7004A47F5 /* tclBinary.c */,
+ F96D3EE008F272A7004A47F5 /* tclCkalloc.c */,
+ F96D3EE108F272A7004A47F5 /* tclClock.c */,
+ F96D3EE208F272A7004A47F5 /* tclCmdAH.c */,
+ F96D3EE308F272A7004A47F5 /* tclCmdIL.c */,
+ F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */,
+ F96D3EE508F272A7004A47F5 /* tclCompCmds.c */,
+ F96D3EE608F272A7004A47F5 /* tclCompExpr.c */,
+ F96D3EE708F272A7004A47F5 /* tclCompile.c */,
+ F96D3EE808F272A7004A47F5 /* tclCompile.h */,
+ F96D3EE908F272A7004A47F5 /* tclConfig.c */,
+ F96D3EEA08F272A7004A47F5 /* tclDate.c */,
+ F96D3EEB08F272A7004A47F5 /* tclDecls.h */,
+ F96D3EEC08F272A7004A47F5 /* tclDictObj.c */,
+ F96D3EED08F272A7004A47F5 /* tclEncoding.c */,
+ F96D3EEE08F272A7004A47F5 /* tclEnv.c */,
+ F96D3EEF08F272A7004A47F5 /* tclEvent.c */,
+ F96D3EF008F272A7004A47F5 /* tclExecute.c */,
+ F96D3EF108F272A7004A47F5 /* tclFCmd.c */,
+ F96D3EF208F272A7004A47F5 /* tclFileName.c */,
+ F96D3EF308F272A7004A47F5 /* tclFileSystem.h */,
+ F96D3EF408F272A7004A47F5 /* tclGet.c */,
+ F96D3EF508F272A7004A47F5 /* tclGetDate.y */,
+ F96D3EF608F272A7004A47F5 /* tclHash.c */,
+ F96D3EF708F272A7004A47F5 /* tclHistory.c */,
+ F96D3EF808F272A7004A47F5 /* tclIndexObj.c */,
+ F96D3EF908F272A7004A47F5 /* tclInt.decls */,
+ F96D3EFA08F272A7004A47F5 /* tclInt.h */,
+ F96D3EFB08F272A7004A47F5 /* tclIntDecls.h */,
+ F96D3EFC08F272A7004A47F5 /* tclInterp.c */,
+ F96D3EFD08F272A7004A47F5 /* tclIntPlatDecls.h */,
+ F96D3EFE08F272A7004A47F5 /* tclIO.c */,
+ F96D3EFF08F272A7004A47F5 /* tclIO.h */,
+ F96D3F0008F272A7004A47F5 /* tclIOCmd.c */,
+ F96D3F0108F272A7004A47F5 /* tclIOGT.c */,
+ F96D3F0208F272A7004A47F5 /* tclIORChan.c */,
+ F96D3F0308F272A7004A47F5 /* tclIOSock.c */,
+ F96D3F0408F272A7004A47F5 /* tclIOUtil.c */,
+ F96D3F0508F272A7004A47F5 /* tclLink.c */,
+ F96D3F0608F272A7004A47F5 /* tclListObj.c */,
+ F96D3F0708F272A7004A47F5 /* tclLiteral.c */,
+ F96D3F0808F272A7004A47F5 /* tclLoad.c */,
+ F96D3F0908F272A7004A47F5 /* tclLoadNone.c */,
+ F96D3F0A08F272A7004A47F5 /* tclMain.c */,
+ F96D3F0B08F272A7004A47F5 /* tclNamesp.c */,
+ F96D3F0C08F272A7004A47F5 /* tclNotify.c */,
+ F96D3F0D08F272A7004A47F5 /* tclObj.c */,
+ F96D3F0E08F272A7004A47F5 /* tclPanic.c */,
+ F96D3F0F08F272A7004A47F5 /* tclParse.c */,
+ F96D3F1108F272A7004A47F5 /* tclPathObj.c */,
+ F96D3F1208F272A7004A47F5 /* tclPipe.c */,
+ F96D3F1308F272A7004A47F5 /* tclPkg.c */,
+ F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */,
+ F96D3F1508F272A7004A47F5 /* tclPlatDecls.h */,
+ F96D3F1608F272A7004A47F5 /* tclPort.h */,
+ F96D3F1708F272A7004A47F5 /* tclPosixStr.c */,
+ F96D3F1808F272A7004A47F5 /* tclPreserve.c */,
+ F96D3F1908F272A7004A47F5 /* tclProc.c */,
+ F96D3F1A08F272A7004A47F5 /* tclRegexp.c */,
+ F96D3F1B08F272A7004A47F5 /* tclRegexp.h */,
+ F96D3F1C08F272A7004A47F5 /* tclResolve.c */,
+ F96D3F1D08F272A7004A47F5 /* tclResult.c */,
+ F96D3F1E08F272A7004A47F5 /* tclScan.c */,
+ F96D3F1F08F272A7004A47F5 /* tclStringObj.c */,
+ F96D3F2408F272A7004A47F5 /* tclStrToD.c */,
+ F96D3F2508F272A7004A47F5 /* tclStubInit.c */,
+ F96D3F2608F272A7004A47F5 /* tclStubLib.c */,
+ F96D3F2708F272A7004A47F5 /* tclTest.c */,
+ F96D3F2808F272A7004A47F5 /* tclTestObj.c */,
+ F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */,
+ F96D3F2A08F272A7004A47F5 /* tclThread.c */,
+ F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */,
+ F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */,
+ F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */,
+ F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */,
+ F96D3F2F08F272A7004A47F5 /* tclTimer.c */,
+ F9903CAF094FAADA004613E9 /* tclTomMath.decls */,
+ F96D3F3008F272A7004A47F5 /* tclTomMath.h */,
+ F9903CB0094FAADA004613E9 /* tclTomMathDecls.h */,
+ F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */,
+ F96D3F3208F272A7004A47F5 /* tclTrace.c */,
+ F96D3F3308F272A7004A47F5 /* tclUniData.c */,
+ F96D3F3408F272A7004A47F5 /* tclUtf.c */,
+ F96D3F3508F272A7004A47F5 /* tclUtil.c */,
+ F96D3F3608F272A7004A47F5 /* tclVar.c */,
+ F96D3F3708F272A7004A47F5 /* tommath.h */,
+ );
+ path = generic;
+ sourceTree = "<group>";
+ };
+ F96D3F3808F272A7004A47F5 /* library */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3F3908F272A8004A47F5 /* auto.tcl */,
+ F96D3F3A08F272A8004A47F5 /* clock.tcl */,
+ F96D3F3B08F272A8004A47F5 /* dde */,
+ F96D3F8C08F272A8004A47F5 /* history.tcl */,
+ F96D3F8D08F272A8004A47F5 /* http */,
+ F96D3F9008F272A8004A47F5 /* http1.0 */,
+ F96D3F9308F272A8004A47F5 /* init.tcl */,
+ F96D3F9408F272A8004A47F5 /* msgcat */,
+ F96D401708F272AA004A47F5 /* opt */,
+ F96D401A08F272AA004A47F5 /* package.tcl */,
+ F96D401B08F272AA004A47F5 /* parray.tcl */,
+ F9ECB1110B26521500A28025 /* platform */,
+ F96D401C08F272AA004A47F5 /* reg */,
+ F96D401E08F272AA004A47F5 /* safe.tcl */,
+ F96D401F08F272AA004A47F5 /* tclIndex */,
+ F96D402008F272AA004A47F5 /* tcltest */,
+ F96D402308F272AA004A47F5 /* tm.tcl */,
+ F96D425B08F272B2004A47F5 /* word.tcl */,
+ );
+ path = library;
+ sourceTree = "<group>";
+ };
+ F96D3F3B08F272A8004A47F5 /* dde */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3F3C08F272A8004A47F5 /* pkgIndex.tcl */,
+ );
+ path = dde;
+ sourceTree = "<group>";
+ };
+ F96D3F8D08F272A8004A47F5 /* http */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3F8E08F272A8004A47F5 /* http.tcl */,
+ F96D3F8F08F272A8004A47F5 /* pkgIndex.tcl */,
+ );
+ path = http;
+ sourceTree = "<group>";
+ };
+ F96D3F9008F272A8004A47F5 /* http1.0 */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3F9108F272A8004A47F5 /* http.tcl */,
+ F96D3F9208F272A8004A47F5 /* pkgIndex.tcl */,
+ );
+ path = http1.0;
+ sourceTree = "<group>";
+ };
+ F96D3F9408F272A8004A47F5 /* msgcat */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3F9508F272A8004A47F5 /* msgcat.tcl */,
+ F96D3F9608F272A8004A47F5 /* pkgIndex.tcl */,
+ );
+ path = msgcat;
+ sourceTree = "<group>";
+ };
+ F96D401708F272AA004A47F5 /* opt */ = {
+ isa = PBXGroup;
+ children = (
+ F96D401808F272AA004A47F5 /* optparse.tcl */,
+ F96D401908F272AA004A47F5 /* pkgIndex.tcl */,
+ );
+ path = opt;
+ sourceTree = "<group>";
+ };
+ F96D401C08F272AA004A47F5 /* reg */ = {
+ isa = PBXGroup;
+ children = (
+ F96D401D08F272AA004A47F5 /* pkgIndex.tcl */,
+ );
+ path = reg;
+ sourceTree = "<group>";
+ };
+ F96D402008F272AA004A47F5 /* tcltest */ = {
+ isa = PBXGroup;
+ children = (
+ F96D402108F272AA004A47F5 /* pkgIndex.tcl */,
+ F96D402208F272AA004A47F5 /* tcltest.tcl */,
+ );
+ path = tcltest;
+ sourceTree = "<group>";
+ };
+ F96D425C08F272B2004A47F5 /* libtommath */ = {
+ isa = PBXGroup;
+ children = (
+ F96D425F08F272B3004A47F5 /* bn.pdf */,
+ F96D426108F272B3004A47F5 /* bn_error.c */,
+ F96D426208F272B3004A47F5 /* bn_fast_mp_invmod.c */,
+ F96D426308F272B3004A47F5 /* bn_fast_mp_montgomery_reduce.c */,
+ F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */,
+ F96D426508F272B3004A47F5 /* bn_fast_s_mp_mul_high_digs.c */,
+ F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */,
+ F96D426708F272B3004A47F5 /* bn_mp_2expt.c */,
+ F96D426808F272B3004A47F5 /* bn_mp_abs.c */,
+ F96D426908F272B3004A47F5 /* bn_mp_add.c */,
+ F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */,
+ F96D426B08F272B3004A47F5 /* bn_mp_addmod.c */,
+ F96D426C08F272B3004A47F5 /* bn_mp_and.c */,
+ F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */,
+ F96D426E08F272B3004A47F5 /* bn_mp_clear.c */,
+ F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */,
+ F96D427008F272B3004A47F5 /* bn_mp_cmp.c */,
+ F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */,
+ F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */,
+ F96D427308F272B3004A47F5 /* bn_mp_cnt_lsb.c */,
+ F96D427408F272B3004A47F5 /* bn_mp_copy.c */,
+ F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */,
+ F96D427608F272B3004A47F5 /* bn_mp_div.c */,
+ F96D427708F272B3004A47F5 /* bn_mp_div_2.c */,
+ F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */,
+ F96D427908F272B3004A47F5 /* bn_mp_div_3.c */,
+ F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */,
+ F96D427B08F272B3004A47F5 /* bn_mp_dr_is_modulus.c */,
+ F96D427C08F272B3004A47F5 /* bn_mp_dr_reduce.c */,
+ F96D427D08F272B3004A47F5 /* bn_mp_dr_setup.c */,
+ F96D427E08F272B3004A47F5 /* bn_mp_exch.c */,
+ F96D427F08F272B3004A47F5 /* bn_mp_expt_d.c */,
+ F96D428008F272B3004A47F5 /* bn_mp_exptmod.c */,
+ F96D428108F272B3004A47F5 /* bn_mp_exptmod_fast.c */,
+ F96D428208F272B3004A47F5 /* bn_mp_exteuclid.c */,
+ F96D428308F272B3004A47F5 /* bn_mp_fread.c */,
+ F96D428408F272B3004A47F5 /* bn_mp_fwrite.c */,
+ F96D428508F272B3004A47F5 /* bn_mp_gcd.c */,
+ F96D428608F272B3004A47F5 /* bn_mp_get_int.c */,
+ F96D428708F272B3004A47F5 /* bn_mp_grow.c */,
+ F96D428808F272B3004A47F5 /* bn_mp_init.c */,
+ F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */,
+ F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */,
+ F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */,
+ F96D428C08F272B3004A47F5 /* bn_mp_init_set_int.c */,
+ F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */,
+ F96D428E08F272B3004A47F5 /* bn_mp_invmod.c */,
+ F96D428F08F272B3004A47F5 /* bn_mp_invmod_slow.c */,
+ F96D429008F272B3004A47F5 /* bn_mp_is_square.c */,
+ F96D429108F272B3004A47F5 /* bn_mp_jacobi.c */,
+ F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */,
+ F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */,
+ F96D429408F272B3004A47F5 /* bn_mp_lcm.c */,
+ F96D429508F272B3004A47F5 /* bn_mp_lshd.c */,
+ F96D429608F272B3004A47F5 /* bn_mp_mod.c */,
+ F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */,
+ F96D429808F272B3004A47F5 /* bn_mp_mod_d.c */,
+ F96D429908F272B3004A47F5 /* bn_mp_montgomery_calc_normalization.c */,
+ F96D429A08F272B3004A47F5 /* bn_mp_montgomery_reduce.c */,
+ F96D429B08F272B3004A47F5 /* bn_mp_montgomery_setup.c */,
+ F96D429C08F272B3004A47F5 /* bn_mp_mul.c */,
+ F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */,
+ F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */,
+ F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */,
+ F96D42A008F272B3004A47F5 /* bn_mp_mulmod.c */,
+ F96D42A108F272B3004A47F5 /* bn_mp_n_root.c */,
+ F96D42A208F272B3004A47F5 /* bn_mp_neg.c */,
+ F96D42A308F272B3004A47F5 /* bn_mp_or.c */,
+ F96D42A408F272B3004A47F5 /* bn_mp_prime_fermat.c */,
+ F96D42A508F272B3004A47F5 /* bn_mp_prime_is_divisible.c */,
+ F96D42A608F272B3004A47F5 /* bn_mp_prime_is_prime.c */,
+ F96D42A708F272B3004A47F5 /* bn_mp_prime_miller_rabin.c */,
+ F96D42A808F272B3004A47F5 /* bn_mp_prime_next_prime.c */,
+ F96D42A908F272B3004A47F5 /* bn_mp_prime_rabin_miller_trials.c */,
+ F96D42AA08F272B3004A47F5 /* bn_mp_prime_random_ex.c */,
+ F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */,
+ F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */,
+ F96D42AD08F272B3004A47F5 /* bn_mp_rand.c */,
+ F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */,
+ F96D42AF08F272B3004A47F5 /* bn_mp_read_signed_bin.c */,
+ F96D42B008F272B3004A47F5 /* bn_mp_read_unsigned_bin.c */,
+ F96D42B108F272B3004A47F5 /* bn_mp_reduce.c */,
+ F96D42B208F272B3004A47F5 /* bn_mp_reduce_2k.c */,
+ F96D42B308F272B3004A47F5 /* bn_mp_reduce_2k_l.c */,
+ F96D42B408F272B3004A47F5 /* bn_mp_reduce_2k_setup.c */,
+ F96D42B508F272B3004A47F5 /* bn_mp_reduce_2k_setup_l.c */,
+ F96D42B608F272B3004A47F5 /* bn_mp_reduce_is_2k.c */,
+ F96D42B708F272B3004A47F5 /* bn_mp_reduce_is_2k_l.c */,
+ F96D42B808F272B3004A47F5 /* bn_mp_reduce_setup.c */,
+ F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */,
+ F96D42BA08F272B3004A47F5 /* bn_mp_set.c */,
+ F96D42BB08F272B3004A47F5 /* bn_mp_set_int.c */,
+ F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */,
+ F96D42BD08F272B3004A47F5 /* bn_mp_signed_bin_size.c */,
+ F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */,
+ F96D42BF08F272B3004A47F5 /* bn_mp_sqrmod.c */,
+ F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */,
+ F96D42C108F272B3004A47F5 /* bn_mp_sub.c */,
+ F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */,
+ F96D42C308F272B3004A47F5 /* bn_mp_submod.c */,
+ F96D42C408F272B3004A47F5 /* bn_mp_to_signed_bin.c */,
+ F96D42C508F272B3004A47F5 /* bn_mp_to_signed_bin_n.c */,
+ F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */,
+ F96D42C708F272B3004A47F5 /* bn_mp_to_unsigned_bin_n.c */,
+ F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */,
+ F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */,
+ F96D42CA08F272B3004A47F5 /* bn_mp_toradix.c */,
+ F96D42CB08F272B3004A47F5 /* bn_mp_toradix_n.c */,
+ F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */,
+ F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */,
+ F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */,
+ F96D42CF08F272B3004A47F5 /* bn_prime_tab.c */,
+ F96D42D008F272B3004A47F5 /* bn_reverse.c */,
+ F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */,
+ F96D42D208F272B3004A47F5 /* bn_s_mp_exptmod.c */,
+ F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */,
+ F96D42D408F272B3004A47F5 /* bn_s_mp_mul_high_digs.c */,
+ F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */,
+ F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */,
+ F96D42D708F272B3004A47F5 /* bncore.c */,
+ F96D42D908F272B3004A47F5 /* callgraph.txt */,
+ F96D42DA08F272B3004A47F5 /* changes.txt */,
+ F96D42F008F272B3004A47F5 /* LICENSE */,
+ F96D431D08F272B4004A47F5 /* poster.pdf */,
+ F96D432608F272B4004A47F5 /* tommath.pdf */,
+ F96D432908F272B4004A47F5 /* tommath_class.h */,
+ F96D432A08F272B4004A47F5 /* tommath_superclass.h */,
+ );
+ path = libtommath;
+ sourceTree = "<group>";
+ };
+ F96D432C08F272B4004A47F5 /* macosx */ = {
+ isa = PBXGroup;
+ children = (
+ F96D432E08F272B5004A47F5 /* configure.ac */,
+ F96D432F08F272B5004A47F5 /* GNUmakefile */,
+ F96D433108F272B5004A47F5 /* README */,
+ F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */,
+ F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */,
+ F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */,
+ F96D433208F272B5004A47F5 /* Tcl-Info.plist.in */,
+ F91E62260C1AE686006C9D96 /* Tclsh-Info.plist.in */,
+ F97AE7F10B65C1E900310EA2 /* Tcl-Common.xcconfig */,
+ F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */,
+ F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */,
+ );
+ path = macosx;
+ sourceTree = "<group>";
+ };
+ F96D434408F272B5004A47F5 /* tests */ = {
+ isa = PBXGroup;
+ children = (
+ F96D434508F272B5004A47F5 /* all.tcl */,
+ F96D434608F272B5004A47F5 /* append.test */,
+ F96D434708F272B5004A47F5 /* appendComp.test */,
+ F9ECB1CA0B2652D300A28025 /* apply.test */,
+ F96D434808F272B5004A47F5 /* assocd.test */,
+ F96D434908F272B5004A47F5 /* async.test */,
+ F96D434A08F272B5004A47F5 /* autoMkindex.test */,
+ F96D434B08F272B5004A47F5 /* basic.test */,
+ F96D434C08F272B5004A47F5 /* binary.test */,
+ F96D434D08F272B5004A47F5 /* case.test */,
+ F96D434E08F272B5004A47F5 /* chan.test */,
+ F9A493240CEBF38300B78AE2 /* chanio.test */,
+ F96D434F08F272B5004A47F5 /* clock.test */,
+ F96D435008F272B5004A47F5 /* cmdAH.test */,
+ F96D435108F272B5004A47F5 /* cmdIL.test */,
+ F96D435208F272B5004A47F5 /* cmdInfo.test */,
+ F96D435308F272B5004A47F5 /* cmdMZ.test */,
+ F96D435408F272B5004A47F5 /* compExpr-old.test */,
+ F96D435508F272B5004A47F5 /* compExpr.test */,
+ F96D435608F272B5004A47F5 /* compile.test */,
+ F96D435708F272B5004A47F5 /* concat.test */,
+ F96D435808F272B5004A47F5 /* config.test */,
+ F96D435908F272B5004A47F5 /* dcall.test */,
+ F96D435A08F272B5004A47F5 /* dict.test */,
+ F96D435C08F272B5004A47F5 /* dstring.test */,
+ F96D435E08F272B5004A47F5 /* encoding.test */,
+ F96D435F08F272B5004A47F5 /* env.test */,
+ F96D436008F272B5004A47F5 /* error.test */,
+ F96D436108F272B5004A47F5 /* eval.test */,
+ F96D436208F272B5004A47F5 /* event.test */,
+ F96D436308F272B5004A47F5 /* exec.test */,
+ F96D436408F272B5004A47F5 /* execute.test */,
+ F96D436508F272B5004A47F5 /* expr-old.test */,
+ F96D436608F272B5004A47F5 /* expr.test */,
+ F96D436708F272B6004A47F5 /* fCmd.test */,
+ F96D436808F272B6004A47F5 /* fileName.test */,
+ F96D436908F272B6004A47F5 /* fileSystem.test */,
+ F96D436A08F272B6004A47F5 /* for-old.test */,
+ F96D436B08F272B6004A47F5 /* for.test */,
+ F96D436C08F272B6004A47F5 /* foreach.test */,
+ F96D436D08F272B6004A47F5 /* format.test */,
+ F96D436E08F272B6004A47F5 /* get.test */,
+ F96D436F08F272B6004A47F5 /* history.test */,
+ F96D437008F272B6004A47F5 /* http.test */,
+ F96D437108F272B6004A47F5 /* httpd */,
+ F96D437208F272B6004A47F5 /* httpold.test */,
+ F96D437308F272B6004A47F5 /* if-old.test */,
+ F96D437408F272B6004A47F5 /* if.test */,
+ F96D437508F272B6004A47F5 /* incr-old.test */,
+ F96D437608F272B6004A47F5 /* incr.test */,
+ F96D437708F272B6004A47F5 /* indexObj.test */,
+ F96D437808F272B6004A47F5 /* info.test */,
+ F96D437908F272B6004A47F5 /* init.test */,
+ F96D437A08F272B6004A47F5 /* interp.test */,
+ F96D437B08F272B6004A47F5 /* io.test */,
+ F96D437C08F272B6004A47F5 /* ioCmd.test */,
+ F96D437D08F272B6004A47F5 /* iogt.test */,
+ F96D437E08F272B6004A47F5 /* ioUtil.test */,
+ F96D437F08F272B6004A47F5 /* join.test */,
+ F96D438008F272B6004A47F5 /* lindex.test */,
+ F96D438108F272B6004A47F5 /* link.test */,
+ F96D438208F272B6004A47F5 /* linsert.test */,
+ F96D438308F272B6004A47F5 /* list.test */,
+ F96D438408F272B6004A47F5 /* listObj.test */,
+ F96D438508F272B6004A47F5 /* llength.test */,
+ F96D438608F272B6004A47F5 /* load.test */,
+ F96D438708F272B6004A47F5 /* lrange.test */,
+ F96D438808F272B6004A47F5 /* lrepeat.test */,
+ F96D438908F272B6004A47F5 /* lreplace.test */,
+ F96D438A08F272B6004A47F5 /* lsearch.test */,
+ F96D438B08F272B6004A47F5 /* lset.test */,
+ F96D438C08F272B6004A47F5 /* lsetComp.test */,
+ F96D438D08F272B6004A47F5 /* macOSXFCmd.test */,
+ F95FAFF90B34F1130072E431 /* macOSXLoad.test */,
+ F96D438E08F272B6004A47F5 /* main.test */,
+ F9ECB1CB0B26534C00A28025 /* mathop.test */,
+ F96D438F08F272B6004A47F5 /* misc.test */,
+ F96D439008F272B6004A47F5 /* msgcat.test */,
+ F96D439108F272B6004A47F5 /* namespace-old.test */,
+ F96D439208F272B7004A47F5 /* namespace.test */,
+ F96D439308F272B7004A47F5 /* notify.test */,
+ F96D439408F272B7004A47F5 /* obj.test */,
+ F96D439508F272B7004A47F5 /* opt.test */,
+ F96D439608F272B7004A47F5 /* package.test */,
+ F96D439708F272B7004A47F5 /* parse.test */,
+ F96D439808F272B7004A47F5 /* parseExpr.test */,
+ F96D439908F272B7004A47F5 /* parseOld.test */,
+ F96D439A08F272B7004A47F5 /* pid.test */,
+ F96D439B08F272B7004A47F5 /* pkg.test */,
+ F96D439C08F272B7004A47F5 /* pkgMkIndex.test */,
+ F96D439D08F272B7004A47F5 /* platform.test */,
+ F96D439E08F272B7004A47F5 /* proc-old.test */,
+ F96D439F08F272B7004A47F5 /* proc.test */,
+ F96D43A008F272B7004A47F5 /* pwd.test */,
+ F96D43A108F272B7004A47F5 /* README */,
+ F96D43A208F272B7004A47F5 /* reg.test */,
+ F96D43A308F272B7004A47F5 /* regexp.test */,
+ F96D43A408F272B7004A47F5 /* regexpComp.test */,
+ F96D43A508F272B7004A47F5 /* registry.test */,
+ F96D43A608F272B7004A47F5 /* remote.tcl */,
+ F96D43A708F272B7004A47F5 /* rename.test */,
+ F96D43A808F272B7004A47F5 /* result.test */,
+ F96D43A908F272B7004A47F5 /* safe.test */,
+ F96D43AA08F272B7004A47F5 /* scan.test */,
+ F96D43AB08F272B7004A47F5 /* security.test */,
+ F96D43AC08F272B7004A47F5 /* set-old.test */,
+ F96D43AD08F272B7004A47F5 /* set.test */,
+ F96D43AE08F272B7004A47F5 /* socket.test */,
+ F96D43AF08F272B7004A47F5 /* source.test */,
+ F96D43B008F272B7004A47F5 /* split.test */,
+ F96D43B108F272B7004A47F5 /* stack.test */,
+ F96D43B208F272B7004A47F5 /* string.test */,
+ F96D43B308F272B7004A47F5 /* stringComp.test */,
+ F96D43B408F272B7004A47F5 /* stringObj.test */,
+ F96D43B508F272B7004A47F5 /* subst.test */,
+ F96D43B608F272B7004A47F5 /* switch.test */,
+ F96D43B708F272B7004A47F5 /* tcltest.test */,
+ F96D43B808F272B7004A47F5 /* thread.test */,
+ F96D43B908F272B7004A47F5 /* timer.test */,
+ F96D43BA08F272B7004A47F5 /* tm.test */,
+ F96D43BB08F272B7004A47F5 /* trace.test */,
+ F96D43BC08F272B7004A47F5 /* unixFCmd.test */,
+ F96D43BD08F272B7004A47F5 /* unixFile.test */,
+ F96D43BE08F272B7004A47F5 /* unixInit.test */,
+ F96D43BF08F272B7004A47F5 /* unixNotfy.test */,
+ F96D43C008F272B7004A47F5 /* unknown.test */,
+ F96D43C108F272B7004A47F5 /* unload.test */,
+ F96D43C208F272B7004A47F5 /* uplevel.test */,
+ F96D43C308F272B7004A47F5 /* upvar.test */,
+ F96D43C408F272B7004A47F5 /* utf.test */,
+ F96D43C508F272B7004A47F5 /* util.test */,
+ F96D43C608F272B7004A47F5 /* var.test */,
+ F96D43C708F272B7004A47F5 /* while-old.test */,
+ F96D43C808F272B7004A47F5 /* while.test */,
+ F96D43C908F272B7004A47F5 /* winConsole.test */,
+ F96D43CA08F272B7004A47F5 /* winDde.test */,
+ F96D43CB08F272B7004A47F5 /* winFCmd.test */,
+ F96D43CC08F272B7004A47F5 /* winFile.test */,
+ F96D43CD08F272B7004A47F5 /* winNotify.test */,
+ F96D43CE08F272B7004A47F5 /* winPipe.test */,
+ F96D43CF08F272B7004A47F5 /* winTime.test */,
+ );
+ path = tests;
+ sourceTree = "<group>";
+ };
+ F96D43D008F272B8004A47F5 /* tools */ = {
+ isa = PBXGroup;
+ children = (
+ F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */,
+ F96D43D208F272B8004A47F5 /* configure */,
+ F96D43D308F272B8004A47F5 /* configure.in */,
+ F96D442208F272B8004A47F5 /* eolFix.tcl */,
+ F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */,
+ F96D442508F272B8004A47F5 /* genStubs.tcl */,
+ F96D442708F272B8004A47F5 /* index.tcl */,
+ F96D442808F272B8004A47F5 /* installData.tcl */,
+ F96D442908F272B8004A47F5 /* loadICU.tcl */,
+ F96D442A08F272B8004A47F5 /* Makefile.in */,
+ F96D442B08F272B8004A47F5 /* makeTestCases.tcl */,
+ F96D442C08F272B8004A47F5 /* man2help.tcl */,
+ F96D442D08F272B8004A47F5 /* man2help2.tcl */,
+ F96D442E08F272B8004A47F5 /* man2html.tcl */,
+ F96D442F08F272B8004A47F5 /* man2html1.tcl */,
+ F96D443008F272B8004A47F5 /* man2html2.tcl */,
+ F96D443108F272B8004A47F5 /* man2tcl.c */,
+ F96D443208F272B8004A47F5 /* README */,
+ F96D443308F272B8004A47F5 /* regexpTestLib.tcl */,
+ F96D443408F272B8004A47F5 /* str2c */,
+ F96D443508F272B8004A47F5 /* tcl.hpj.in */,
+ F96D443608F272B8004A47F5 /* tcl.wse.in */,
+ F96D443708F272B9004A47F5 /* tclmin.wse */,
+ F96D443908F272B9004A47F5 /* tcltk-man2html.tcl */,
+ F96D443A08F272B9004A47F5 /* tclZIC.tcl */,
+ F96D443B08F272B9004A47F5 /* uniClass.tcl */,
+ F96D443C08F272B9004A47F5 /* uniParse.tcl */,
+ );
+ path = tools;
+ sourceTree = "<group>";
+ };
+ F96D443E08F272B9004A47F5 /* unix */ = {
+ isa = PBXGroup;
+ children = (
+ F96D444008F272B9004A47F5 /* aclocal.m4 */,
+ F96D444108F272B9004A47F5 /* configure */,
+ F96D444208F272B9004A47F5 /* configure.in */,
+ F96D444308F272B9004A47F5 /* dltest */,
+ F96D444D08F272B9004A47F5 /* install-sh */,
+ F96D444E08F272B9004A47F5 /* installManPage */,
+ F96D444F08F272B9004A47F5 /* ldAix */,
+ F96D445008F272B9004A47F5 /* Makefile.in */,
+ F96D445208F272B9004A47F5 /* README */,
+ F96D445308F272B9004A47F5 /* tcl.m4 */,
+ F96D445408F272B9004A47F5 /* tcl.spec */,
+ F96D445508F272B9004A47F5 /* tclAppInit.c */,
+ F96D445608F272B9004A47F5 /* tclConfig.h.in */,
+ F96D445708F272B9004A47F5 /* tclConfig.sh.in */,
+ F96D445808F272B9004A47F5 /* tclLoadAix.c */,
+ F96D445908F272B9004A47F5 /* tclLoadDl.c */,
+ F96D445B08F272B9004A47F5 /* tclLoadDyld.c */,
+ F96D445C08F272B9004A47F5 /* tclLoadNext.c */,
+ F96D445D08F272B9004A47F5 /* tclLoadOSF.c */,
+ F96D445E08F272B9004A47F5 /* tclLoadShl.c */,
+ F96D445F08F272B9004A47F5 /* tclUnixChan.c */,
+ F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */,
+ F96D446008F272B9004A47F5 /* tclUnixEvent.c */,
+ F96D446108F272B9004A47F5 /* tclUnixFCmd.c */,
+ F96D446208F272B9004A47F5 /* tclUnixFile.c */,
+ F96D446308F272B9004A47F5 /* tclUnixInit.c */,
+ F96D446408F272B9004A47F5 /* tclUnixNotfy.c */,
+ F96D446508F272B9004A47F5 /* tclUnixPipe.c */,
+ F96D446608F272B9004A47F5 /* tclUnixPort.h */,
+ F96D446708F272B9004A47F5 /* tclUnixSock.c */,
+ F96D446808F272B9004A47F5 /* tclUnixTest.c */,
+ F96D446908F272B9004A47F5 /* tclUnixThrd.c */,
+ F96D446A08F272B9004A47F5 /* tclUnixThrd.h */,
+ F96D446B08F272B9004A47F5 /* tclUnixTime.c */,
+ F96D446C08F272B9004A47F5 /* tclXtNotify.c */,
+ F96D446D08F272B9004A47F5 /* tclXtTest.c */,
+ );
+ path = unix;
+ sourceTree = "<group>";
+ };
+ F96D444308F272B9004A47F5 /* dltest */ = {
+ isa = PBXGroup;
+ children = (
+ F96D444408F272B9004A47F5 /* Makefile.in */,
+ F96D444508F272B9004A47F5 /* pkga.c */,
+ F96D444608F272B9004A47F5 /* pkgb.c */,
+ F96D444708F272B9004A47F5 /* pkgc.c */,
+ F96D444808F272B9004A47F5 /* pkgd.c */,
+ F96D444908F272B9004A47F5 /* pkge.c */,
+ F96D444B08F272B9004A47F5 /* pkgua.c */,
+ F96D444C08F272B9004A47F5 /* README */,
+ );
+ path = dltest;
+ sourceTree = "<group>";
+ };
+ F96D446E08F272B9004A47F5 /* win */ = {
+ isa = PBXGroup;
+ children = (
+ F96D447008F272BA004A47F5 /* aclocal.m4 */,
+ F96D447108F272BA004A47F5 /* buildall.vc.bat */,
+ F96D447208F272BA004A47F5 /* cat.c */,
+ F96D447308F272BA004A47F5 /* coffbase.txt */,
+ F96D447408F272BA004A47F5 /* configure */,
+ F96D447508F272BA004A47F5 /* configure.in */,
+ F96D447608F272BA004A47F5 /* makefile.bc */,
+ F96D447708F272BA004A47F5 /* Makefile.in */,
+ F96D447808F272BA004A47F5 /* makefile.vc */,
+ F96D447908F272BA004A47F5 /* nmakehlp.c */,
+ F96D447A08F272BA004A47F5 /* README */,
+ F96D447C08F272BA004A47F5 /* rules.vc */,
+ F96D447D08F272BA004A47F5 /* stub16.c */,
+ F96D447E08F272BA004A47F5 /* tcl.dsp */,
+ F96D447F08F272BA004A47F5 /* tcl.dsw */,
+ F96D448008F272BA004A47F5 /* tcl.hpj.in */,
+ F96D448108F272BA004A47F5 /* tcl.m4 */,
+ F96D448208F272BA004A47F5 /* tcl.rc */,
+ F96D448308F272BA004A47F5 /* tclAppInit.c */,
+ F96D448408F272BA004A47F5 /* tclConfig.sh.in */,
+ F96D448608F272BA004A47F5 /* tclsh.rc */,
+ F96D448708F272BA004A47F5 /* tclWin32Dll.c */,
+ F96D448808F272BA004A47F5 /* tclWinChan.c */,
+ F96D448908F272BA004A47F5 /* tclWinConsole.c */,
+ F96D448A08F272BA004A47F5 /* tclWinDde.c */,
+ F96D448B08F272BA004A47F5 /* tclWinError.c */,
+ F96D448C08F272BA004A47F5 /* tclWinFCmd.c */,
+ F96D448D08F272BA004A47F5 /* tclWinFile.c */,
+ F96D448E08F272BA004A47F5 /* tclWinInit.c */,
+ F96D448F08F272BA004A47F5 /* tclWinInt.h */,
+ F96D449008F272BA004A47F5 /* tclWinLoad.c */,
+ F96D449108F272BA004A47F5 /* tclWinNotify.c */,
+ F96D449208F272BA004A47F5 /* tclWinPipe.c */,
+ F96D449308F272BA004A47F5 /* tclWinPort.h */,
+ F96D449408F272BA004A47F5 /* tclWinReg.c */,
+ F96D449508F272BA004A47F5 /* tclWinSerial.c */,
+ F96D449608F272BA004A47F5 /* tclWinSock.c */,
+ F96D449708F272BA004A47F5 /* tclWinTest.c */,
+ F96D449808F272BA004A47F5 /* tclWinThrd.c */,
+ F96D449908F272BA004A47F5 /* tclWinThrd.h */,
+ F96D449A08F272BA004A47F5 /* tclWinTime.c */,
+ );
+ path = win;
+ sourceTree = "<group>";
+ };
+ F9ECB1110B26521500A28025 /* platform */ = {
+ isa = PBXGroup;
+ children = (
+ F9ECB1120B26521500A28025 /* pkgIndex.tcl */,
+ F9ECB1130B26521500A28025 /* platform.tcl */,
+ F9ECB1140B26521500A28025 /* shell.tcl */,
+ );
+ path = platform;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8DD76FA90486AB0100D96B5E /* tcltest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F95CC8B009158F3100EA5ACE /* Build configuration list for PBXNativeTarget "tcltest" */;
+ buildPhases = (
+ F9A5C5F508F651A2008AE941 /* ShellScript */,
+ 8DD76FAB0486AB0100D96B5E /* Sources */,
+ 8DD76FAD0486AB0100D96B5E /* Frameworks */,
+ F95FA74C0B32CE190072E431 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = tcltest;
+ productInstallPath = "$(BINDIR)";
+ productName = tcltest;
+ productReference = 8DD76FB20486AB0100D96B5E /* tcltest */;
+ productType = "com.apple.product-type.tool";
+ };
+ F97258A50A86873C00096C78 /* tests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F97258A80A86873D00096C78 /* Build configuration list for PBXNativeTarget "tests" */;
+ buildPhases = (
+ F97258A40A86873C00096C78 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ F97258D30A868C6F00096C78 /* PBXTargetDependency */,
+ );
+ name = tests;
+ productName = tests;
+ productType = "com.apple.product-type.bundle";
+ };
+ F9E61D16090A3E94002B3151 /* Tcl */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F95CC8AB09158F3100EA5ACE /* Build configuration list for PBXNativeTarget "Tcl" */;
+ buildPhases = (
+ F97AF02F0B665DA900310EA2 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Tcl;
+ productName = tclsh;
+ productReference = F9A3084B08F2D4CE00BAE1AB /* tclsh */;
+ productType = "com.apple.product-type.tool";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = F95CC8B509158F3100EA5ACE /* Build configuration list for PBXProject "Tcl" */;
+ hasScannedForEncodings = 1;
+ mainGroup = 08FB7794FE84155DC02AAC07 /* Tcl */;
+ projectDirPath = "";
+ projectRoot = ..;
+ targets = (
+ F9E61D16090A3E94002B3151 /* Tcl */,
+ 8DD76FA90486AB0100D96B5E /* tcltest */,
+ F97258A50A86873C00096C78 /* tests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ F95FA74C0B32CE190072E431 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(DERIVED_FILE_DIR)/tcl/tclConfig.sh",
+ "$(TCL_SRCROOT)/generic/tclStubLib.c",
+ "$(TCL_SRCROOT)/unix/dltest/pkga.c",
+ "$(TCL_SRCROOT)/unix/dltest/pkgb.c",
+ "$(TCL_SRCROOT)/unix/dltest/pkgc.c",
+ "$(TCL_SRCROOT)/unix/dltest/pkgd.c",
+ "$(TCL_SRCROOT)/unix/dltest/pkge.c",
+ "$(TCL_SRCROOT)/unix/dltest/pkgua.c",
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/tcl/dltest.marker",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "## dltest build script phase\n\nrm -f \"${DERIVED_FILE_DIR}/tcl/dltest.marker\"\nmake -C \"${DERIVED_FILE_DIR}/tcl\" dltest.marker\nln -fsh \"${DERIVED_FILE_DIR}/tcl/dltest\" \"${CONFIGURATION_BUILD_DIR}\"\n";
+ };
+ F97258A40A86873C00096C78 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "if [ \"${ACTION:-build}\" == \"build\" ]; then\nif [ -z \"${HOME}\" ]; then export HOME=\"$(echo ~)\"; fi\ncd \"${TARGET_TEMP_DIR}\"; rm -rf \"${DERIVED_FILE_DIR}\"; mkdir -p \"${DERIVED_FILE_DIR}\"\nprintf '%s%s%s%s%s' '\npackage require tcltest 2.2\nnamespace import tcltest::*\nconfigure -testdir [file normalize {' \"${TCL_SRCROOT}\" '/tests}]\nconfigure -tmpdir [file normalize {' \"${DERIVED_FILE_DIR}\" '}]\nconfigure -verbose [concat [configure -verbose] line]\n# following test only fails when testsuite is run from inside Xcode, so skip it\nconfigure -skip [concat [configure -skip] stack-3.1]\nrunAllTests\n' | \"${TEST_RIG}\"; TEST_RIG_RESULT=$?\n[ ${TEST_RIG_RESULT} -ne 0 ] && echo \"tcltest:0: error: tcltest exited abnormally with code ${TEST_RIG_RESULT}.\"\nexit ${TEST_RIG_RESULT}\nfi";
+ };
+ F97AF02F0B665DA900310EA2 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "${TARGET_TEMP_DIR}/.none",
+ );
+ outputPaths = (
+ "${TARGET_BUILD_DIR}/${EXECUTABLE_NAME}",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "if [ -e \"${TARGET_BUILD_DIR}/tclsh\" ]; then\n mv -f \"${TARGET_BUILD_DIR}/tclsh\" \"${TARGET_BUILD_DIR}/tclsh${VERSION}\"\nfi\ngnumake -C \"${TCL_SRCROOT}/macosx\" -j \"$(sysctl -n hw.activecpu)\" \"$(echo \"${ACTION}\" | sed -e s/build// -e s/clean/distclean/ -e s/..\\*/\\&-/)${MAKE_TARGET}\" CFLAGS_WARNING=\"${WARNING_CFLAGS}\" CFLAGS_OPTIMIZE=\"-O${GCC_OPTIMIZATION_LEVEL}\" SYMROOT=\"${BUILT_PRODUCTS_DIR}\" OBJ_DIR=\"${OBJECT_FILE_DIR}\" INSTALL_ROOT=\"${DSTROOT}\" PREFIX=\"${PREFIX}\" BINDIR=\"${BINDIR}\" LIBDIR=\"${FRAMEWORK_INSTALL_PATH}\" MANDIR=\"${MANDIR}\" EXTRA_CONFIGURE_ARGS=\"${CONFIGURE_ARGS}\" ${EXTRA_MAKE_FLAGS}\nresult=$?\nif [ -e \"${TARGET_BUILD_DIR}/tclsh${VERSION}\" ]; then\n mv -f \"${TARGET_BUILD_DIR}/tclsh${VERSION}\" \"${TARGET_BUILD_DIR}/tclsh\"\nfi\nif [ -e \"${BUILT_PRODUCTS_DIR}/tcltest\" ]; then\n\trm -f \"${BUILT_PRODUCTS_DIR}/tcltest\"\nfi\necho \"Done\"\nrm -f \"${SCRIPT_INPUT_FILE_0}\"\nexit ${result}\n";
+ };
+ F9A5C5F508F651A2008AE941 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(TCL_SRCROOT)/macosx/configure.ac",
+ "$(TCL_SRCROOT)/unix/configure.in",
+ "$(TCL_SRCROOT)/unix/tcl.m4",
+ "$(TCL_SRCROOT)/unix/aclocal.m4",
+ "$(TCL_SRCROOT)/unix/tclConfig.sh.in",
+ "$(TCL_SRCROOT)/unix/Makefile.in",
+ "$(TCL_SRCROOT)/unix/dltest/Makefile.in",
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/tcl/tclConfig.sh",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tcl/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tcl\"\n \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8DD76FAB0486AB0100D96B5E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F96D456F08F272BB004A47F5 /* regcomp.c in Sources */,
+ F96D457208F272BB004A47F5 /* regerror.c in Sources */,
+ F96D457508F272BB004A47F5 /* regexec.c in Sources */,
+ F96D457608F272BB004A47F5 /* regfree.c in Sources */,
+ F96D457B08F272BB004A47F5 /* tclAlloc.c in Sources */,
+ F96D457C08F272BB004A47F5 /* tclAsync.c in Sources */,
+ F96D457D08F272BB004A47F5 /* tclBasic.c in Sources */,
+ F96D457E08F272BC004A47F5 /* tclBinary.c in Sources */,
+ F96D457F08F272BC004A47F5 /* tclCkalloc.c in Sources */,
+ F96D458008F272BC004A47F5 /* tclClock.c in Sources */,
+ F96D458108F272BC004A47F5 /* tclCmdAH.c in Sources */,
+ F96D458208F272BC004A47F5 /* tclCmdIL.c in Sources */,
+ F96D458308F272BC004A47F5 /* tclCmdMZ.c in Sources */,
+ F96D458408F272BC004A47F5 /* tclCompCmds.c in Sources */,
+ F96D458508F272BC004A47F5 /* tclCompExpr.c in Sources */,
+ F96D458608F272BC004A47F5 /* tclCompile.c in Sources */,
+ F96D458808F272BC004A47F5 /* tclConfig.c in Sources */,
+ F96D458908F272BC004A47F5 /* tclDate.c in Sources */,
+ F96D458B08F272BC004A47F5 /* tclDictObj.c in Sources */,
+ F96D458C08F272BC004A47F5 /* tclEncoding.c in Sources */,
+ F96D458D08F272BC004A47F5 /* tclEnv.c in Sources */,
+ F96D458E08F272BC004A47F5 /* tclEvent.c in Sources */,
+ F96D458F08F272BC004A47F5 /* tclExecute.c in Sources */,
+ F96D459008F272BC004A47F5 /* tclFCmd.c in Sources */,
+ F96D459108F272BC004A47F5 /* tclFileName.c in Sources */,
+ F96D459308F272BC004A47F5 /* tclGet.c in Sources */,
+ F96D459508F272BC004A47F5 /* tclHash.c in Sources */,
+ F96D459608F272BC004A47F5 /* tclHistory.c in Sources */,
+ F96D459708F272BC004A47F5 /* tclIndexObj.c in Sources */,
+ F96D459B08F272BC004A47F5 /* tclInterp.c in Sources */,
+ F96D459D08F272BC004A47F5 /* tclIO.c in Sources */,
+ F96D459F08F272BC004A47F5 /* tclIOCmd.c in Sources */,
+ F96D45A008F272BC004A47F5 /* tclIOGT.c in Sources */,
+ F96D45A108F272BC004A47F5 /* tclIORChan.c in Sources */,
+ F96D45A208F272BC004A47F5 /* tclIOSock.c in Sources */,
+ F96D45A308F272BC004A47F5 /* tclIOUtil.c in Sources */,
+ F96D45A408F272BC004A47F5 /* tclLink.c in Sources */,
+ F96D45A508F272BC004A47F5 /* tclListObj.c in Sources */,
+ F96D45A608F272BC004A47F5 /* tclLiteral.c in Sources */,
+ F96D45A708F272BC004A47F5 /* tclLoad.c in Sources */,
+ F96D45A908F272BC004A47F5 /* tclMain.c in Sources */,
+ F96D45AA08F272BC004A47F5 /* tclNamesp.c in Sources */,
+ F96D45AB08F272BC004A47F5 /* tclNotify.c in Sources */,
+ F96D45AC08F272BC004A47F5 /* tclObj.c in Sources */,
+ F96D45AD08F272BC004A47F5 /* tclPanic.c in Sources */,
+ F96D45AE08F272BC004A47F5 /* tclParse.c in Sources */,
+ F96D45B008F272BC004A47F5 /* tclPathObj.c in Sources */,
+ F96D45B108F272BC004A47F5 /* tclPipe.c in Sources */,
+ F96D45B208F272BC004A47F5 /* tclPkg.c in Sources */,
+ F96D45B308F272BC004A47F5 /* tclPkgConfig.c in Sources */,
+ F96D45B608F272BC004A47F5 /* tclPosixStr.c in Sources */,
+ F96D45B708F272BC004A47F5 /* tclPreserve.c in Sources */,
+ F96D45B808F272BC004A47F5 /* tclProc.c in Sources */,
+ F96D45B908F272BC004A47F5 /* tclRegexp.c in Sources */,
+ F96D45BB08F272BC004A47F5 /* tclResolve.c in Sources */,
+ F96D45BC08F272BC004A47F5 /* tclResult.c in Sources */,
+ F96D45BD08F272BC004A47F5 /* tclScan.c in Sources */,
+ F96D45BE08F272BC004A47F5 /* tclStringObj.c in Sources */,
+ F96D45C308F272BC004A47F5 /* tclStrToD.c in Sources */,
+ F96D45C408F272BC004A47F5 /* tclStubInit.c in Sources */,
+ F96D45C508F272BC004A47F5 /* tclStubLib.c in Sources */,
+ F96D45C608F272BC004A47F5 /* tclTest.c in Sources */,
+ F96D45C708F272BC004A47F5 /* tclTestObj.c in Sources */,
+ F96D45C808F272BC004A47F5 /* tclTestProcBodyObj.c in Sources */,
+ F96D45C908F272BC004A47F5 /* tclThread.c in Sources */,
+ F96D45CA08F272BC004A47F5 /* tclThreadAlloc.c in Sources */,
+ F96D45CB08F272BC004A47F5 /* tclThreadJoin.c in Sources */,
+ F96D45CC08F272BC004A47F5 /* tclThreadStorage.c in Sources */,
+ F96D45CD08F272BC004A47F5 /* tclThreadTest.c in Sources */,
+ F96D45CE08F272BC004A47F5 /* tclTimer.c in Sources */,
+ F96D45D008F272BC004A47F5 /* tclTomMathInterface.c in Sources */,
+ F96D45D108F272BC004A47F5 /* tclTrace.c in Sources */,
+ F96D45D308F272BC004A47F5 /* tclUtf.c in Sources */,
+ F96D45D408F272BC004A47F5 /* tclUtil.c in Sources */,
+ F96D45D508F272BC004A47F5 /* tclVar.c in Sources */,
+ F96D48E208F272C3004A47F5 /* bn_fast_s_mp_mul_digs.c in Sources */,
+ F96D48E408F272C3004A47F5 /* bn_fast_s_mp_sqr.c in Sources */,
+ F96D48E708F272C3004A47F5 /* bn_mp_add.c in Sources */,
+ F96D48E808F272C3004A47F5 /* bn_mp_add_d.c in Sources */,
+ F9E61D2B090A48A4002B3151 /* bn_mp_and.c in Sources */,
+ F96D48EB08F272C3004A47F5 /* bn_mp_clamp.c in Sources */,
+ F96D48EC08F272C3004A47F5 /* bn_mp_clear.c in Sources */,
+ F96D48ED08F272C3004A47F5 /* bn_mp_clear_multi.c in Sources */,
+ F96D48EE08F272C3004A47F5 /* bn_mp_cmp.c in Sources */,
+ F9E61D28090A481F002B3151 /* bn_mp_cmp_d.c in Sources */,
+ F96D48F008F272C3004A47F5 /* bn_mp_cmp_mag.c in Sources */,
+ F96D48F208F272C3004A47F5 /* bn_mp_cnt_lsb.c in Sources */,
+ F96D48F208F272C3004A47F5 /* bn_mp_copy.c in Sources */,
+ F96D48F308F272C3004A47F5 /* bn_mp_count_bits.c in Sources */,
+ F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */,
+ F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */,
+ F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */,
+ F96D48F708F272C3004A47F5 /* bn_mp_div_3.c in Sources */,
+ F96D48F808F272C3004A47F5 /* bn_mp_div_d.c in Sources */,
+ F96D48FC08F272C3004A47F5 /* bn_mp_exch.c in Sources */,
+ F9E61D2C090A48AC002B3151 /* bn_mp_expt_d.c in Sources */,
+ F96D490508F272C3004A47F5 /* bn_mp_grow.c in Sources */,
+ F96D490608F272C3004A47F5 /* bn_mp_init.c in Sources */,
+ F96D490708F272C3004A47F5 /* bn_mp_init_copy.c in Sources */,
+ F96D490808F272C3004A47F5 /* bn_mp_init_multi.c in Sources */,
+ F96D490908F272C3004A47F5 /* bn_mp_init_set.c in Sources */,
+ F96D490B08F272C3004A47F5 /* bn_mp_init_size.c in Sources */,
+ F96D491008F272C3004A47F5 /* bn_mp_karatsuba_mul.c in Sources */,
+ F96D491108F272C3004A47F5 /* bn_mp_karatsuba_sqr.c in Sources */,
+ F96D491308F272C3004A47F5 /* bn_mp_lshd.c in Sources */,
+ F96D491408F272C3004A47F5 /* bn_mp_mod.c in Sources */,
+ F96D491508F272C3004A47F5 /* bn_mp_mod_2d.c in Sources */,
+ F96D491A08F272C3004A47F5 /* bn_mp_mul.c in Sources */,
+ F96D491B08F272C3004A47F5 /* bn_mp_mul_2.c in Sources */,
+ F96D491C08F272C3004A47F5 /* bn_mp_mul_2d.c in Sources */,
+ F96D491D08F272C3004A47F5 /* bn_mp_mul_d.c in Sources */,
+ F9E61D29090A486C002B3151 /* bn_mp_neg.c in Sources */,
+ F9E61D2E090A48BF002B3151 /* bn_mp_or.c in Sources */,
+ F96D492908F272C3004A47F5 /* bn_mp_radix_size.c in Sources */,
+ F96D492A08F272C3004A47F5 /* bn_mp_radix_smap.c in Sources */,
+ F96D492C08F272C3004A47F5 /* bn_mp_read_radix.c in Sources */,
+ F96D493708F272C3004A47F5 /* bn_mp_rshd.c in Sources */,
+ F96D493808F272C3004A47F5 /* bn_mp_set.c in Sources */,
+ F9E61D2F090A48C7002B3151 /* bn_mp_shrink.c in Sources */,
+ F96D493C08F272C3004A47F5 /* bn_mp_sqr.c in Sources */,
+ F9E61D2A090A4891002B3151 /* bn_mp_sqrt.c in Sources */,
+ F96D493F08F272C3004A47F5 /* bn_mp_sub.c in Sources */,
+ F96D494008F272C3004A47F5 /* bn_mp_sub_d.c in Sources */,
+ F9E61D30090A48E2002B3151 /* bn_mp_to_unsigned_bin_n.c in Sources */,
+ F9E61D31090A48F9002B3151 /* bn_mp_to_unsigned_bin.c in Sources */,
+ F96D494608F272C3004A47F5 /* bn_mp_toom_mul.c in Sources */,
+ F96D494708F272C3004A47F5 /* bn_mp_toom_sqr.c in Sources */,
+ F96D494908F272C3004A47F5 /* bn_mp_toradix_n.c in Sources */,
+ F9E61D32090A48FA002B3151 /* bn_mp_unsigned_bin_size.c in Sources */,
+ F9E61D2D090A48BB002B3151 /* bn_mp_xor.c in Sources */,
+ F96D494C08F272C3004A47F5 /* bn_mp_zero.c in Sources */,
+ F96D494E08F272C3004A47F5 /* bn_reverse.c in Sources */,
+ F96D494F08F272C3004A47F5 /* bn_s_mp_add.c in Sources */,
+ F96D495108F272C3004A47F5 /* bn_s_mp_mul_digs.c in Sources */,
+ F96D495308F272C3004A47F5 /* bn_s_mp_sqr.c in Sources */,
+ F96D495408F272C3004A47F5 /* bn_s_mp_sub.c in Sources */,
+ F96D495508F272C3004A47F5 /* bncore.c in Sources */,
+ F96D49A908F272C4004A47F5 /* tclMacOSXBundle.c in Sources */,
+ F96D49AD08F272C4004A47F5 /* tclMacOSXFCmd.c in Sources */,
+ F96D49AE08F272C4004A47F5 /* tclMacOSXNotify.c in Sources */,
+ F90509300913A72400327603 /* tclAppInit.c in Sources */,
+ F96D4AC608F272C9004A47F5 /* tclLoadDyld.c in Sources */,
+ F96D4ACA08F272C9004A47F5 /* tclUnixChan.c in Sources */,
+ F9FC77B80AB29E9100B7077D /* tclUnixCompat.c in Sources */,
+ F96D4ACB08F272C9004A47F5 /* tclUnixEvent.c in Sources */,
+ F96D4ACC08F272C9004A47F5 /* tclUnixFCmd.c in Sources */,
+ F96D4ACD08F272C9004A47F5 /* tclUnixFile.c in Sources */,
+ F96D4ACE08F272C9004A47F5 /* tclUnixInit.c in Sources */,
+ F96D4ACF08F272C9004A47F5 /* tclUnixNotfy.c in Sources */,
+ F96D4AD008F272C9004A47F5 /* tclUnixPipe.c in Sources */,
+ F96D4AD208F272CA004A47F5 /* tclUnixSock.c in Sources */,
+ F96D4AD308F272CA004A47F5 /* tclUnixTest.c in Sources */,
+ F96D4AD408F272CA004A47F5 /* tclUnixThrd.c in Sources */,
+ F96D4AD608F272CA004A47F5 /* tclUnixTime.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ F97258D30A868C6F00096C78 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 8DD76FA90486AB0100D96B5E /* tcltest */;
+ targetProxy = F97258D20A868C6F00096C78 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ F91BCC4F093152310042A6BF /* ReleaseUniversal */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = ReleaseUniversal;
+ };
+ F91BCC50093152310042A6BF /* ReleaseUniversal */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = ReleaseUniversal;
+ };
+ F91BCC51093152310042A6BF /* ReleaseUniversal */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ ppc,
+ ppc64,
+ i386,
+ x86_64,
+ );
+ CFLAGS = "-arch ppc -arch ppc64 -arch i386 -arch x86_64 $(CFLAGS)";
+ MACOSX_DEPLOYMENT_TARGET = 10.4;
+ OTHER_LDFLAGS = (
+ "-Wl,-no_arch_warnings",
+ "$(OTHER_LDFLAGS)",
+ );
+ PREBINDING = NO;
+ };
+ name = ReleaseUniversal;
+ };
+ F93084370BB93D2800CD0B9E /* DebugMemCompile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugMemCompile;
+ };
+ F93084380BB93D2800CD0B9E /* DebugMemCompile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = DebugMemCompile;
+ };
+ F93084390BB93D2800CD0B9E /* DebugMemCompile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = DebugMemCompile;
+ };
+ F930843A0BB93D2800CD0B9E /* DebugMemCompile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
+ buildSettings = {
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --enable-symbols=all";
+ MACOSX_DEPLOYMENT_TARGET = 10.2;
+ PREBINDING = NO;
+ };
+ name = DebugMemCompile;
+ };
+ F9359B250DF212DA00E04F67 /* DebugGCov */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
+ buildSettings = {
+ GCC_GENERATE_TEST_COVERAGE_FILES = YES;
+ GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.2;
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS)",
+ "-lgcov",
+ );
+ PREBINDING = NO;
+ };
+ name = DebugGCov;
+ };
+ F9359B260DF212DA00E04F67 /* DebugGCov */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugGCov;
+ };
+ F9359B270DF212DA00E04F67 /* DebugGCov */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = DebugGCov;
+ };
+ F9359B280DF212DA00E04F67 /* DebugGCov */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "-notfile http.test";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = DebugGCov;
+ };
+ F95CC8AC09158F3100EA5ACE /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = Debug;
+ };
+ F95CC8AD09158F3100EA5ACE /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = Release;
+ };
+ F95CC8AE09158F3100EA5ACE /* DebugNoFixZL */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugNoFixZL;
+ };
+ F95CC8B109158F3100EA5ACE /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__private_extern__=extern",
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ PRODUCT_NAME = tcltest;
+ ZERO_LINK = YES;
+ };
+ name = Debug;
+ };
+ F95CC8B209158F3100EA5ACE /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = Release;
+ };
+ F95CC8B309158F3100EA5ACE /* DebugNoFixZL */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = DebugNoFixZL;
+ };
+ F95CC8B609158F3100EA5ACE /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
+ buildSettings = {
+ MACOSX_DEPLOYMENT_TARGET = 10.2;
+ PREBINDING = NO;
+ };
+ name = Debug;
+ };
+ F95CC8B709158F3100EA5ACE /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
+ buildSettings = {
+ MACOSX_DEPLOYMENT_TARGET = 10.2;
+ PREBINDING = YES;
+ };
+ name = Release;
+ };
+ F95CC8B809158F3100EA5ACE /* DebugNoFixZL */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
+ buildSettings = {
+ MACOSX_DEPLOYMENT_TARGET = 10.2;
+ PREBINDING = NO;
+ };
+ name = DebugNoFixZL;
+ };
+ F97258A90A86873D00096C78 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = Debug;
+ };
+ F97258AA0A86873D00096C78 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = Release;
+ };
+ F97258AB0A86873D00096C78 /* DebugNoFixZL */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = DebugNoFixZL;
+ };
+ F97258AC0A86873D00096C78 /* ReleaseUniversal */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = ReleaseUniversal;
+ };
+ F97AED080B660A6C00310EA2 /* ReleaseUniversal10.4uSDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = ReleaseUniversal10.4uSDK;
+ };
+ F97AED0F0B660AA300310EA2 /* ReleasePPC10.3.9SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = ReleasePPC10.3.9SDK;
+ };
+ F97AED160B660AF100310EA2 /* ReleasePPC10.2.8SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = ReleasePPC10.2.8SDK;
+ };
+ F97AED1B0B660B2100310EA2 /* Debug64bit */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = Debug64bit;
+ };
+ F97AED1C0B660B2100310EA2 /* Debug64bit */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = Debug64bit;
+ };
+ F97AED1D0B660B2100310EA2 /* Debug64bit */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = Debug64bit;
+ };
+ F97AED1E0B660B2100310EA2 /* Debug64bit */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(NATIVE_ARCH_64_BIT)";
+ CONFIGURE_ARGS = "--enable-64bit $(CONFIGURE_ARGS)";
+ CPPFLAGS = "-arch $(NATIVE_ARCH_64_BIT) $(CPPFLAGS)";
+ MACOSX_DEPLOYMENT_TARGET = 10.2;
+ PREBINDING = NO;
+ };
+ name = Debug64bit;
+ };
+ F987512F0DE7B57E00B1C9EC /* DebugNoCF */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
+ buildSettings = {
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-corefoundation";
+ MACOSX_DEPLOYMENT_TARGET = 10.2;
+ PREBINDING = NO;
+ };
+ name = DebugNoCF;
+ };
+ F98751300DE7B57E00B1C9EC /* DebugNoCF */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugNoCF;
+ };
+ F98751310DE7B57E00B1C9EC /* DebugNoCF */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = DebugNoCF;
+ };
+ F98751320DE7B57E00B1C9EC /* DebugNoCF */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = DebugNoCF;
+ };
+ F98751330DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
+ buildSettings = {
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-threads --disable-corefoundation";
+ MACOSX_DEPLOYMENT_TARGET = 10.2;
+ PREBINDING = NO;
+ };
+ name = DebugNoCFUnthreaded;
+ };
+ F98751340DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugNoCFUnthreaded;
+ };
+ F98751350DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = DebugNoCFUnthreaded;
+ };
+ F98751360DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = DebugNoCFUnthreaded;
+ };
+ F99EE73B0BE835310060D4AF /* DebugUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugUnthreaded;
+ };
+ F99EE73C0BE835310060D4AF /* DebugLeaks */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugLeaks;
+ };
+ F99EE73D0BE835310060D4AF /* DebugUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = DebugUnthreaded;
+ };
+ F99EE73E0BE835310060D4AF /* DebugLeaks */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = DebugLeaks;
+ };
+ F99EE73F0BE835310060D4AF /* DebugUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = DebugUnthreaded;
+ };
+ F99EE7400BE835310060D4AF /* DebugLeaks */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = DebugLeaks;
+ };
+ F99EE7410BE835310060D4AF /* DebugUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
+ buildSettings = {
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-threads";
+ MACOSX_DEPLOYMENT_TARGET = 10.2;
+ PREBINDING = NO;
+ };
+ name = DebugUnthreaded;
+ };
+ F99EE7420BE835310060D4AF /* DebugLeaks */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
+ buildSettings = {
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ PURIFY,
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ MACOSX_DEPLOYMENT_TARGET = 10.2;
+ PREBINDING = NO;
+ };
+ name = DebugLeaks;
+ };
+ F9DB62080B65ADA800A370FB /* ReleaseUniversal10.4uSDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = ReleaseUniversal10.4uSDK;
+ };
+ F9DB62090B65ADA800A370FB /* ReleaseUniversal10.4uSDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = ReleaseUniversal10.4uSDK;
+ };
+ F9DB620A0B65ADA800A370FB /* ReleaseUniversal10.4uSDK */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = (
+ ppc,
+ ppc64,
+ i386,
+ x86_64,
+ );
+ CFLAGS = "-arch ppc -arch ppc64 -arch i386 -arch x86_64 $(CFLAGS)";
+ CPPFLAGS = "-isysroot $(SDKROOT) $(CPPFLAGS)";
+ MACOSX_DEPLOYMENT_TARGET = 10.4;
+ OTHER_LDFLAGS = (
+ "-Wl,-no_arch_warnings",
+ "$(OTHER_LDFLAGS)",
+ );
+ PREBINDING = NO;
+ SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+ };
+ name = ReleaseUniversal10.4uSDK;
+ };
+ F9DB621F0B65AFDE00A370FB /* ReleasePPC10.3.9SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ LDFLAGS = "-force_cpusubtype_ALL $(LDFLAGS)";
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = ReleasePPC10.3.9SDK;
+ };
+ F9DB62200B65AFDE00A370FB /* ReleasePPC10.3.9SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = ReleasePPC10.3.9SDK;
+ };
+ F9DB62210B65AFDE00A370FB /* ReleasePPC10.3.9SDK */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = ppc;
+ CFLAGS = "$(PER_ARCH_CFLAGS_ppc) $(CFLAGS)";
+ CPPFLAGS = "-arch ppc -isysroot $(SDKROOT) $(CPPFLAGS)";
+ MACOSX_DEPLOYMENT_TARGET = 10.3;
+ PREBINDING = YES;
+ SDKROOT = /Developer/SDKs/MacOSX10.3.9.sdk;
+ };
+ name = ReleasePPC10.3.9SDK;
+ };
+ F9DB62350B65B03A00A370FB /* ReleasePPC10.2.8SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = ReleasePPC10.2.8SDK;
+ };
+ F9DB62360B65B03A00A370FB /* ReleasePPC10.2.8SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = ReleasePPC10.2.8SDK;
+ };
+ F9DB62370B65B03A00A370FB /* ReleasePPC10.2.8SDK */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = ppc;
+ CFLAGS = "$(PER_ARCH_CFLAGS_ppc) -fconstant-cfstrings $(CFLAGS)";
+ CPPFLAGS = "-arch ppc -D__CONSTANT_CFSTRINGS__ -DMAC_OS_X_VERSION_MIN_REQUIRED=1020 -nostdinc -isystem $(SDKROOT)/usr/include/gcc/darwin/$(GCC_VERSION) -isystem $(SDKROOT)/usr/include -F$(SDKROOT)/System/Library/Frameworks";
+ DEBUG_INFORMATION_FORMAT = stabs;
+ GCC = /usr/bin/gcc;
+ GCC_VERSION = 3.3;
+ LDFLAGS = "-L$(SDKROOT)/usr/lib/gcc/darwin/$(GCC_VERSION) -Wl,-syslibroot,$(SDKROOT)";
+ MACOSX_DEPLOYMENT_TARGET = 10.2;
+ PREBINDING = YES;
+ SDKROOT = /Developer/SDKs/MacOSX10.2.8.sdk;
+ WARNING_CFLAGS = (
+ "$(WARNING_CFLAGS_GCC3)",
+ "-Wno-long-double",
+ );
+ };
+ name = ReleasePPC10.2.8SDK;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ F95CC8AB09158F3100EA5ACE /* Build configuration list for PBXNativeTarget "Tcl" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F95CC8AC09158F3100EA5ACE /* Debug */,
+ F95CC8AE09158F3100EA5ACE /* DebugNoFixZL */,
+ F99EE73B0BE835310060D4AF /* DebugUnthreaded */,
+ F98751300DE7B57E00B1C9EC /* DebugNoCF */,
+ F98751340DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
+ F93084370BB93D2800CD0B9E /* DebugMemCompile */,
+ F99EE73C0BE835310060D4AF /* DebugLeaks */,
+ F9359B260DF212DA00E04F67 /* DebugGCov */,
+ F97AED1B0B660B2100310EA2 /* Debug64bit */,
+ F95CC8AD09158F3100EA5ACE /* Release */,
+ F91BCC4F093152310042A6BF /* ReleaseUniversal */,
+ F9DB62080B65ADA800A370FB /* ReleaseUniversal10.4uSDK */,
+ F9DB621F0B65AFDE00A370FB /* ReleasePPC10.3.9SDK */,
+ F9DB62350B65B03A00A370FB /* ReleasePPC10.2.8SDK */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ F95CC8B009158F3100EA5ACE /* Build configuration list for PBXNativeTarget "tcltest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F95CC8B109158F3100EA5ACE /* Debug */,
+ F95CC8B309158F3100EA5ACE /* DebugNoFixZL */,
+ F99EE73D0BE835310060D4AF /* DebugUnthreaded */,
+ F98751310DE7B57E00B1C9EC /* DebugNoCF */,
+ F98751350DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
+ F93084380BB93D2800CD0B9E /* DebugMemCompile */,
+ F99EE73E0BE835310060D4AF /* DebugLeaks */,
+ F9359B270DF212DA00E04F67 /* DebugGCov */,
+ F97AED1C0B660B2100310EA2 /* Debug64bit */,
+ F95CC8B209158F3100EA5ACE /* Release */,
+ F91BCC50093152310042A6BF /* ReleaseUniversal */,
+ F9DB62090B65ADA800A370FB /* ReleaseUniversal10.4uSDK */,
+ F9DB62200B65AFDE00A370FB /* ReleasePPC10.3.9SDK */,
+ F9DB62360B65B03A00A370FB /* ReleasePPC10.2.8SDK */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ F95CC8B509158F3100EA5ACE /* Build configuration list for PBXProject "Tcl" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F95CC8B609158F3100EA5ACE /* Debug */,
+ F95CC8B809158F3100EA5ACE /* DebugNoFixZL */,
+ F99EE7410BE835310060D4AF /* DebugUnthreaded */,
+ F987512F0DE7B57E00B1C9EC /* DebugNoCF */,
+ F98751330DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
+ F930843A0BB93D2800CD0B9E /* DebugMemCompile */,
+ F99EE7420BE835310060D4AF /* DebugLeaks */,
+ F9359B250DF212DA00E04F67 /* DebugGCov */,
+ F97AED1E0B660B2100310EA2 /* Debug64bit */,
+ F95CC8B709158F3100EA5ACE /* Release */,
+ F91BCC51093152310042A6BF /* ReleaseUniversal */,
+ F9DB620A0B65ADA800A370FB /* ReleaseUniversal10.4uSDK */,
+ F9DB62210B65AFDE00A370FB /* ReleasePPC10.3.9SDK */,
+ F9DB62370B65B03A00A370FB /* ReleasePPC10.2.8SDK */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ F97258A80A86873D00096C78 /* Build configuration list for PBXNativeTarget "tests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F97258A90A86873D00096C78 /* Debug */,
+ F97258AB0A86873D00096C78 /* DebugNoFixZL */,
+ F99EE73F0BE835310060D4AF /* DebugUnthreaded */,
+ F98751320DE7B57E00B1C9EC /* DebugNoCF */,
+ F98751360DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
+ F93084390BB93D2800CD0B9E /* DebugMemCompile */,
+ F99EE7400BE835310060D4AF /* DebugLeaks */,
+ F9359B280DF212DA00E04F67 /* DebugGCov */,
+ F97AED1D0B660B2100310EA2 /* Debug64bit */,
+ F97258AA0A86873D00096C78 /* Release */,
+ F97258AC0A86873D00096C78 /* ReleaseUniversal */,
+ F97AED080B660A6C00310EA2 /* ReleaseUniversal10.4uSDK */,
+ F97AED0F0B660AA300310EA2 /* ReleasePPC10.3.9SDK */,
+ F97AED160B660AF100310EA2 /* ReleasePPC10.2.8SDK */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/macosx/Tcl.xcodeproj/default.pbxuser b/macosx/Tcl.xcodeproj/default.pbxuser
new file mode 100644
index 0000000..45224d6
--- /dev/null
+++ b/macosx/Tcl.xcodeproj/default.pbxuser
@@ -0,0 +1,200 @@
+// !$*UTF8*$!
+{
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ activeBuildConfigurationName = Debug;
+ activeExecutable = F9E61D1C090A4282002B3151 /* tclsh */;
+ activeTarget = F9E61D16090A3E94002B3151 /* Tcl */;
+ codeSenseManager = F944EB9D08F798180049FDD4 /* Code sense */;
+ executables = (
+ F9E61D1C090A4282002B3151 /* tclsh */,
+ F944EB8F08F798100049FDD4 /* tcltest */,
+ );
+ perUserDictionary = {
+ com.apple.ide.smrt.PBXUserSmartGroupsKey.Rev10 = <040b73747265616d747970656481e8038401408484840e4e534d757461626c654172726179008484074e534172726179008484084e534f626a65637400858401690192848484134e534d757461626c6544696374696f6e6172790084840c4e5344696374696f6e6172790095960792848484084e53537472696e67019584012b046e616d658692849a9a14496d706c656d656e746174696f6e2046696c65738692849a9a146162736f6c75746550617468546f42756e646c658692849a9a008692849a9a195042585472616e7369656e744c6f636174696f6e4174546f708692849a9a06626f74746f6d8692849a9a03636c7a8692849a9a1550425846696c656e616d65536d61727447726f75708692849a9a0b6465736372697074696f6e8692849a9a103c6e6f206465736372697074696f6e3e8692849a9a0b707265666572656e63657386928497960892849a9a07666e6d617463688692849a9a008692849a9a05696d6167658692849a9a0b536d617274466f6c6465728692849a9a04726f6f748692849a9a093c50524f4a4543543e8692849a9a0572656765788692849a9a065c2e286329248692849a9a097265637572736976658692848484084e534e756d626572008484074e5356616c7565009584012a849696018692849a9a0669734c656166869284b09db296008692849a9a0763616e536176658692af92849a9a1250425850726f6a65637453636f70654b65798692849a9a03594553868692849a9a08676c6f62616c49448692849a9a18314343304541343030343335304546393030343434313042868686>;
+ };
+ sourceControlManager = F944EB9C08F798180049FDD4 /* Source Control */;
+ userBuildSettings = {
+ AUTOCONF = "/usr/local/bin/autoconf-2.59";
+ AUTOHEADER = "/usr/local/bin/autoheader-2.59";
+ CODE_SIGN_IDENTITY = "";
+ SYMROOT = "${SRCROOT}/../../build/tcl";
+ TCL_SRCROOT = "${SRCROOT}/../../tcl";
+ };
+ };
+ 8DD76FA90486AB0100D96B5E /* tcltest */ = {
+ activeExec = 0;
+ executables = (
+ F944EB8F08F798100049FDD4 /* tcltest */,
+ );
+ };
+ F944EB8F08F798100049FDD4 /* tcltest */ = {
+ isa = PBXExecutable;
+ activeArgIndices = (
+ NO,
+ NO,
+ NO,
+ );
+ argumentStrings = (
+ "${TCL_SRCROOT}/tests/all.tcl",
+ "-singleproc 1",
+ "-verbose \"bet\"",
+ );
+ autoAttachOnCrash = 1;
+ breakpointsEnabled = 1;
+ configStateDict = {
+ "PBXLSLaunchAction-0" = {
+ PBXLSLaunchAction = 0;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 2;
+ PBXLSLaunchStyle = 0;
+ class = PBXLSRunLaunchConfig;
+ displayName = "Executable Runner";
+ identifier = com.apple.Xcode.launch.runConfig;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ "PBXLSLaunchAction-1" = {
+ PBXLSLaunchAction = 1;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 2;
+ PBXLSLaunchStyle = 0;
+ class = PBXGDB_LaunchConfig;
+ displayName = GDB;
+ identifier = com.apple.Xcode.launch.GDBMI_Config;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ };
+ customDataFormattersEnabled = 1;
+ debuggerPlugin = GDBDebugging;
+ disassemblyDisplayState = 0;
+ dylibVariantSuffix = "";
+ enableDebugStr = 0;
+ environmentEntries = (
+ {
+ active = YES;
+ name = TCL_LIBRARY;
+ value = "${TCL_SRCROOT}/library";
+ },
+ {
+ active = YES;
+ name = TCLLIBPATH;
+ value = /Library/Tcl;
+ },
+ {
+ active = NO;
+ name = DYLD_PRINT_LIBRARIES;
+ },
+ {
+ active = NO;
+ name = MallocBadFreeAbort;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocLogFile;
+ value = /tmp/malloc.log;
+ },
+ {
+ active = NO;
+ name = MallocStackLogging;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocStackLoggingNoCompact;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocPreScribble;
+ value = 1;
+ },
+ {
+ active = NO;
+ name = MallocScribble;
+ value = 1;
+ },
+ );
+ executableSystemSymbolLevel = 0;
+ executableUserSymbolLevel = 0;
+ libgmallocEnabled = 0;
+ name = tcltest;
+ sourceDirectories = (
+ );
+ };
+ F944EB9C08F798180049FDD4 /* Source Control */ = {
+ isa = PBXSourceControlManager;
+ fallbackIsa = XCSourceControlManager;
+ isSCMEnabled = 0;
+ scmConfiguration = {
+ CVSToolPath = /usr/bin/cvs;
+ CVSUseSSH = NO;
+ SubversionToolPath = /usr/bin/svn;
+ };
+ scmType = scm.cvs;
+ };
+ F944EB9D08F798180049FDD4 /* Code sense */ = {
+ isa = PBXCodeSenseManager;
+ indexTemplatePath = "";
+ };
+ F97258A50A86873C00096C78 /* tests */ = {
+ activeExec = 0;
+ };
+ F9E61D16090A3E94002B3151 /* Tcl */ = {
+ activeExec = 0;
+ executables = (
+ F9E61D1C090A4282002B3151 /* tclsh */,
+ );
+ };
+ F9E61D1C090A4282002B3151 /* tclsh */ = {
+ isa = PBXExecutable;
+ activeArgIndices = (
+ );
+ argumentStrings = (
+ );
+ autoAttachOnCrash = 1;
+ breakpointsEnabled = 1;
+ configStateDict = {
+ "PBXLSLaunchAction-0" = {
+ PBXLSLaunchAction = 0;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 2;
+ PBXLSLaunchStyle = 0;
+ class = PBXLSRunLaunchConfig;
+ displayName = "Executable Runner";
+ identifier = com.apple.Xcode.launch.runConfig;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ "PBXLSLaunchAction-1" = {
+ PBXLSLaunchAction = 1;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 2;
+ PBXLSLaunchStyle = 0;
+ class = PBXGDB_LaunchConfig;
+ displayName = GDB;
+ identifier = com.apple.Xcode.launch.GDBMI_Config;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ };
+ customDataFormattersEnabled = 1;
+ debuggerPlugin = GDBDebugging;
+ disassemblyDisplayState = 0;
+ dylibVariantSuffix = _debug;
+ enableDebugStr = 0;
+ environmentEntries = (
+ {
+ active = NO;
+ name = DYLD_PRINT_LIBRARIES;
+ },
+ );
+ executableSystemSymbolLevel = 0;
+ executableUserSymbolLevel = 0;
+ libgmallocEnabled = 0;
+ name = tclsh;
+ sourceDirectories = (
+ );
+ };
+}
diff --git a/macosx/Tcl.xcodeproj/project.pbxproj b/macosx/Tcl.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..97158b0
--- /dev/null
+++ b/macosx/Tcl.xcodeproj/project.pbxproj
@@ -0,0 +1,3035 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ F90509300913A72400327603 /* tclAppInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445508F272B9004A47F5 /* tclAppInit.c */; settings = {COMPILER_FLAGS = "-DTCL_TEST -DTCL_BUILDTIME_LIBRARY=\\\"$(TCL_SRCROOT)/library\\\""; }; };
+ F966C07508F2820D005CB29B /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F966C07408F2820D005CB29B /* CoreFoundation.framework */; };
+ F96D456F08F272BB004A47F5 /* regcomp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED008F272A7004A47F5 /* regcomp.c */; };
+ F96D457208F272BB004A47F5 /* regerror.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED308F272A7004A47F5 /* regerror.c */; };
+ F96D457508F272BB004A47F5 /* regexec.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED608F272A7004A47F5 /* regexec.c */; };
+ F96D457608F272BB004A47F5 /* regfree.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED708F272A7004A47F5 /* regfree.c */; };
+ F96D457B08F272BB004A47F5 /* tclAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDC08F272A7004A47F5 /* tclAlloc.c */; settings = {COMPILER_FLAGS = "-DUSE_TCLALLOC=0"; }; };
+ F96D457C08F272BB004A47F5 /* tclAsync.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDD08F272A7004A47F5 /* tclAsync.c */; };
+ F96D457D08F272BB004A47F5 /* tclBasic.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDE08F272A7004A47F5 /* tclBasic.c */; };
+ F96D457E08F272BC004A47F5 /* tclBinary.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDF08F272A7004A47F5 /* tclBinary.c */; };
+ F96D457F08F272BC004A47F5 /* tclCkalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE008F272A7004A47F5 /* tclCkalloc.c */; };
+ F96D458008F272BC004A47F5 /* tclClock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE108F272A7004A47F5 /* tclClock.c */; };
+ F96D458108F272BC004A47F5 /* tclCmdAH.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE208F272A7004A47F5 /* tclCmdAH.c */; };
+ F96D458208F272BC004A47F5 /* tclCmdIL.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE308F272A7004A47F5 /* tclCmdIL.c */; };
+ F96D458308F272BC004A47F5 /* tclCmdMZ.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */; };
+ F96D458408F272BC004A47F5 /* tclCompCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE508F272A7004A47F5 /* tclCompCmds.c */; };
+ F96D458508F272BC004A47F5 /* tclCompExpr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE608F272A7004A47F5 /* tclCompExpr.c */; };
+ F96D458608F272BC004A47F5 /* tclCompile.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE708F272A7004A47F5 /* tclCompile.c */; };
+ F96D458808F272BC004A47F5 /* tclConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE908F272A7004A47F5 /* tclConfig.c */; };
+ F96D458908F272BC004A47F5 /* tclDate.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEA08F272A7004A47F5 /* tclDate.c */; };
+ F96D458B08F272BC004A47F5 /* tclDictObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEC08F272A7004A47F5 /* tclDictObj.c */; };
+ F96D458C08F272BC004A47F5 /* tclEncoding.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EED08F272A7004A47F5 /* tclEncoding.c */; };
+ F96D458D08F272BC004A47F5 /* tclEnv.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEE08F272A7004A47F5 /* tclEnv.c */; };
+ F96D458E08F272BC004A47F5 /* tclEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEF08F272A7004A47F5 /* tclEvent.c */; };
+ F96D458F08F272BC004A47F5 /* tclExecute.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF008F272A7004A47F5 /* tclExecute.c */; };
+ F96D459008F272BC004A47F5 /* tclFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF108F272A7004A47F5 /* tclFCmd.c */; };
+ F96D459108F272BC004A47F5 /* tclFileName.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF208F272A7004A47F5 /* tclFileName.c */; };
+ F96D459308F272BC004A47F5 /* tclGet.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF408F272A7004A47F5 /* tclGet.c */; };
+ F96D459508F272BC004A47F5 /* tclHash.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF608F272A7004A47F5 /* tclHash.c */; };
+ F96D459608F272BC004A47F5 /* tclHistory.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF708F272A7004A47F5 /* tclHistory.c */; };
+ F96D459708F272BC004A47F5 /* tclIndexObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF808F272A7004A47F5 /* tclIndexObj.c */; };
+ F96D459B08F272BC004A47F5 /* tclInterp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EFC08F272A7004A47F5 /* tclInterp.c */; };
+ F96D459D08F272BC004A47F5 /* tclIO.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EFE08F272A7004A47F5 /* tclIO.c */; };
+ F96D459F08F272BC004A47F5 /* tclIOCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0008F272A7004A47F5 /* tclIOCmd.c */; };
+ F96D45A008F272BC004A47F5 /* tclIOGT.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0108F272A7004A47F5 /* tclIOGT.c */; };
+ F96D45A108F272BC004A47F5 /* tclIORChan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0208F272A7004A47F5 /* tclIORChan.c */; };
+ F96D45A208F272BC004A47F5 /* tclIOSock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0308F272A7004A47F5 /* tclIOSock.c */; };
+ F96D45A308F272BC004A47F5 /* tclIOUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0408F272A7004A47F5 /* tclIOUtil.c */; };
+ F96D45A408F272BC004A47F5 /* tclLink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0508F272A7004A47F5 /* tclLink.c */; };
+ F96D45A508F272BC004A47F5 /* tclListObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0608F272A7004A47F5 /* tclListObj.c */; };
+ F96D45A608F272BC004A47F5 /* tclLiteral.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0708F272A7004A47F5 /* tclLiteral.c */; };
+ F96D45A708F272BC004A47F5 /* tclLoad.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0808F272A7004A47F5 /* tclLoad.c */; };
+ F96D45A908F272BC004A47F5 /* tclMain.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0A08F272A7004A47F5 /* tclMain.c */; };
+ F96D45AA08F272BC004A47F5 /* tclNamesp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0B08F272A7004A47F5 /* tclNamesp.c */; };
+ F96D45AB08F272BC004A47F5 /* tclNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0C08F272A7004A47F5 /* tclNotify.c */; };
+ F96D45AC08F272BC004A47F5 /* tclObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0D08F272A7004A47F5 /* tclObj.c */; };
+ F96D45AD08F272BC004A47F5 /* tclPanic.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0E08F272A7004A47F5 /* tclPanic.c */; };
+ F96D45AE08F272BC004A47F5 /* tclParse.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0F08F272A7004A47F5 /* tclParse.c */; };
+ F96D45B008F272BC004A47F5 /* tclPathObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1108F272A7004A47F5 /* tclPathObj.c */; };
+ F96D45B108F272BC004A47F5 /* tclPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1208F272A7004A47F5 /* tclPipe.c */; };
+ F96D45B208F272BC004A47F5 /* tclPkg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1308F272A7004A47F5 /* tclPkg.c */; };
+ F96D45B308F272BC004A47F5 /* tclPkgConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */; settings = {COMPILER_FLAGS = "-DCFG_INSTALL_LIBDIR=\\\"$(LIBDIR)\\\" -DCFG_INSTALL_BINDIR=\\\"$(BINDIR)\\\" -DCFG_INSTALL_SCRDIR=\\\"$(TCL_LIBRARY)\\\" -DCFG_INSTALL_INCDIR=\\\"$(INCLUDEDIR)\\\" -DCFG_INSTALL_DOCDIR=\\\"$(MANDIR)\\\" -DCFG_RUNTIME_LIBDIR=\\\"$(LIBDIR)\\\" -DCFG_RUNTIME_BINDIR=\\\"$(BINDIR)\\\" -DCFG_RUNTIME_SCRDIR=\\\"$(TCL_LIBRARY)\\\" -DCFG_RUNTIME_INCDIR=\\\"$(INCLUDEDIR)\\\" -DCFG_RUNTIME_DOCDIR=\\\"$(MANDIR)\\\""; }; };
+ F96D45B608F272BC004A47F5 /* tclPosixStr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1708F272A7004A47F5 /* tclPosixStr.c */; };
+ F96D45B708F272BC004A47F5 /* tclPreserve.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1808F272A7004A47F5 /* tclPreserve.c */; };
+ F96D45B808F272BC004A47F5 /* tclProc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1908F272A7004A47F5 /* tclProc.c */; };
+ F96D45B908F272BC004A47F5 /* tclRegexp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1A08F272A7004A47F5 /* tclRegexp.c */; };
+ F96D45BB08F272BC004A47F5 /* tclResolve.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1C08F272A7004A47F5 /* tclResolve.c */; };
+ F96D45BC08F272BC004A47F5 /* tclResult.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1D08F272A7004A47F5 /* tclResult.c */; };
+ F96D45BD08F272BC004A47F5 /* tclScan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1E08F272A7004A47F5 /* tclScan.c */; };
+ F96D45BE08F272BC004A47F5 /* tclStringObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1F08F272A7004A47F5 /* tclStringObj.c */; };
+ F96D45C308F272BC004A47F5 /* tclStrToD.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2408F272A7004A47F5 /* tclStrToD.c */; };
+ F96D45C408F272BC004A47F5 /* tclStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2508F272A7004A47F5 /* tclStubInit.c */; };
+ F96D45C508F272BC004A47F5 /* tclStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2608F272A7004A47F5 /* tclStubLib.c */; };
+ F96D45C608F272BC004A47F5 /* tclTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2708F272A7004A47F5 /* tclTest.c */; };
+ F96D45C708F272BC004A47F5 /* tclTestObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2808F272A7004A47F5 /* tclTestObj.c */; };
+ F96D45C808F272BC004A47F5 /* tclTestProcBodyObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */; };
+ F96D45C908F272BC004A47F5 /* tclThread.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2A08F272A7004A47F5 /* tclThread.c */; };
+ F96D45CA08F272BC004A47F5 /* tclThreadAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */; };
+ F96D45CB08F272BC004A47F5 /* tclThreadJoin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */; };
+ F96D45CC08F272BC004A47F5 /* tclThreadStorage.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */; };
+ F96D45CD08F272BC004A47F5 /* tclThreadTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */; };
+ F96D45CE08F272BC004A47F5 /* tclTimer.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2F08F272A7004A47F5 /* tclTimer.c */; };
+ F96D45D008F272BC004A47F5 /* tclTomMathInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */; };
+ F96D45D108F272BC004A47F5 /* tclTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3208F272A7004A47F5 /* tclTrace.c */; };
+ F96D45D308F272BC004A47F5 /* tclUtf.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3408F272A7004A47F5 /* tclUtf.c */; };
+ F96D45D408F272BC004A47F5 /* tclUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3508F272A7004A47F5 /* tclUtil.c */; };
+ F96D45D508F272BC004A47F5 /* tclVar.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3608F272A7004A47F5 /* tclVar.c */; };
+ F96D48E208F272C3004A47F5 /* bn_fast_s_mp_mul_digs.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */; };
+ F96D48E408F272C3004A47F5 /* bn_fast_s_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */; };
+ F96D48E708F272C3004A47F5 /* bn_mp_add.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426908F272B3004A47F5 /* bn_mp_add.c */; };
+ F96D48E808F272C3004A47F5 /* bn_mp_add_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */; };
+ F96D48EB08F272C3004A47F5 /* bn_mp_clamp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */; };
+ F96D48EC08F272C3004A47F5 /* bn_mp_clear.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426E08F272B3004A47F5 /* bn_mp_clear.c */; };
+ F96D48ED08F272C3004A47F5 /* bn_mp_clear_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */; };
+ F96D48EE08F272C3004A47F5 /* bn_mp_cmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427008F272B3004A47F5 /* bn_mp_cmp.c */; };
+ F96D48F008F272C3004A47F5 /* bn_mp_cmp_mag.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */; };
+ F96D48F208F272C3004A47F5 /* bn_mp_cnt_lsb.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427408F272B3004A47F5 /* bn_mp_cnt_lsb.c */; };
+ F96D48F208F272C3004A47F5 /* bn_mp_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427408F272B3004A47F5 /* bn_mp_copy.c */; };
+ F96D48F308F272C3004A47F5 /* bn_mp_count_bits.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */; };
+ F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427608F272B3004A47F5 /* bn_mp_div.c */; };
+ F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427708F272B3004A47F5 /* bn_mp_div_2.c */; };
+ F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */; };
+ F96D48F708F272C3004A47F5 /* bn_mp_div_3.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427908F272B3004A47F5 /* bn_mp_div_3.c */; };
+ F96D48F808F272C3004A47F5 /* bn_mp_div_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */; };
+ F96D48FC08F272C3004A47F5 /* bn_mp_exch.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427E08F272B3004A47F5 /* bn_mp_exch.c */; };
+ F96D490508F272C3004A47F5 /* bn_mp_grow.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428708F272B3004A47F5 /* bn_mp_grow.c */; };
+ F96D490608F272C3004A47F5 /* bn_mp_init.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428808F272B3004A47F5 /* bn_mp_init.c */; };
+ F96D490708F272C3004A47F5 /* bn_mp_init_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */; };
+ F96D490808F272C3004A47F5 /* bn_mp_init_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */; };
+ F96D490908F272C3004A47F5 /* bn_mp_init_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */; };
+ F96D490B08F272C3004A47F5 /* bn_mp_init_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */; };
+ F96D491008F272C3004A47F5 /* bn_mp_karatsuba_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */; };
+ F96D491108F272C3004A47F5 /* bn_mp_karatsuba_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */; };
+ F96D491308F272C3004A47F5 /* bn_mp_lshd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429508F272B3004A47F5 /* bn_mp_lshd.c */; };
+ F96D491408F272C3004A47F5 /* bn_mp_mod.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429608F272B3004A47F5 /* bn_mp_mod.c */; };
+ F96D491508F272C3004A47F5 /* bn_mp_mod_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */; };
+ F96D491A08F272C3004A47F5 /* bn_mp_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429C08F272B3004A47F5 /* bn_mp_mul.c */; };
+ F96D491B08F272C3004A47F5 /* bn_mp_mul_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */; };
+ F96D491C08F272C3004A47F5 /* bn_mp_mul_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */; };
+ F96D491D08F272C3004A47F5 /* bn_mp_mul_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */; };
+ F96D492908F272C3004A47F5 /* bn_mp_radix_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */; };
+ F96D492A08F272C3004A47F5 /* bn_mp_radix_smap.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */; };
+ F96D492C08F272C3004A47F5 /* bn_mp_read_radix.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */; };
+ F96D493708F272C3004A47F5 /* bn_mp_rshd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */; };
+ F96D493808F272C3004A47F5 /* bn_mp_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BA08F272B3004A47F5 /* bn_mp_set.c */; };
+ F96D493C08F272C3004A47F5 /* bn_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */; };
+ F96D493F08F272C3004A47F5 /* bn_mp_sub.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C108F272B3004A47F5 /* bn_mp_sub.c */; };
+ F96D494008F272C3004A47F5 /* bn_mp_sub_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */; };
+ F96D494608F272C3004A47F5 /* bn_mp_toom_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */; };
+ F96D494708F272C3004A47F5 /* bn_mp_toom_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */; };
+ F96D494908F272C3004A47F5 /* bn_mp_toradix_n.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CB08F272B3004A47F5 /* bn_mp_toradix_n.c */; };
+ F96D494C08F272C3004A47F5 /* bn_mp_zero.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */; };
+ F96D494E08F272C3004A47F5 /* bn_reverse.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D008F272B3004A47F5 /* bn_reverse.c */; };
+ F96D494F08F272C3004A47F5 /* bn_s_mp_add.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */; };
+ F96D495108F272C3004A47F5 /* bn_s_mp_mul_digs.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */; };
+ F96D495308F272C3004A47F5 /* bn_s_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */; };
+ F96D495408F272C3004A47F5 /* bn_s_mp_sub.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */; };
+ F96D495508F272C3004A47F5 /* bncore.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D708F272B3004A47F5 /* bncore.c */; };
+ F96D49A908F272C4004A47F5 /* tclMacOSXBundle.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */; };
+ F96D49AD08F272C4004A47F5 /* tclMacOSXFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */; };
+ F96D49AE08F272C4004A47F5 /* tclMacOSXNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */; };
+ F96D4AC608F272C9004A47F5 /* tclLoadDyld.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445B08F272B9004A47F5 /* tclLoadDyld.c */; };
+ F96D4ACA08F272C9004A47F5 /* tclUnixChan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445F08F272B9004A47F5 /* tclUnixChan.c */; };
+ F96D4ACB08F272C9004A47F5 /* tclUnixEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446008F272B9004A47F5 /* tclUnixEvent.c */; };
+ F96D4ACC08F272C9004A47F5 /* tclUnixFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446108F272B9004A47F5 /* tclUnixFCmd.c */; };
+ F96D4ACD08F272C9004A47F5 /* tclUnixFile.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446208F272B9004A47F5 /* tclUnixFile.c */; };
+ F96D4ACE08F272C9004A47F5 /* tclUnixInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446308F272B9004A47F5 /* tclUnixInit.c */; settings = {COMPILER_FLAGS = "-DTCL_LIBRARY=\\\"$(TCL_LIBRARY)\\\" -DTCL_PACKAGE_PATH=\\\"$(TCL_PACKAGE_PATH)\\\""; }; };
+ F96D4ACF08F272C9004A47F5 /* tclUnixNotfy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446408F272B9004A47F5 /* tclUnixNotfy.c */; };
+ F96D4AD008F272C9004A47F5 /* tclUnixPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446508F272B9004A47F5 /* tclUnixPipe.c */; };
+ F96D4AD208F272CA004A47F5 /* tclUnixSock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446708F272B9004A47F5 /* tclUnixSock.c */; };
+ F96D4AD308F272CA004A47F5 /* tclUnixTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446808F272B9004A47F5 /* tclUnixTest.c */; };
+ F96D4AD408F272CA004A47F5 /* tclUnixThrd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446908F272B9004A47F5 /* tclUnixThrd.c */; };
+ F96D4AD608F272CA004A47F5 /* tclUnixTime.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446B08F272B9004A47F5 /* tclUnixTime.c */; };
+ F9E61D28090A481F002B3151 /* bn_mp_cmp_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */; };
+ F9E61D29090A486C002B3151 /* bn_mp_neg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A208F272B3004A47F5 /* bn_mp_neg.c */; };
+ F9E61D2A090A4891002B3151 /* bn_mp_sqrt.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */; };
+ F9E61D2B090A48A4002B3151 /* bn_mp_and.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426C08F272B3004A47F5 /* bn_mp_and.c */; };
+ F9E61D2C090A48AC002B3151 /* bn_mp_expt_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427F08F272B3004A47F5 /* bn_mp_expt_d.c */; };
+ F9E61D2D090A48BB002B3151 /* bn_mp_xor.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */; };
+ F9E61D2E090A48BF002B3151 /* bn_mp_or.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A308F272B3004A47F5 /* bn_mp_or.c */; };
+ F9E61D2F090A48C7002B3151 /* bn_mp_shrink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */; };
+ F9E61D30090A48E2002B3151 /* bn_mp_to_unsigned_bin_n.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C708F272B3004A47F5 /* bn_mp_to_unsigned_bin_n.c */; };
+ F9E61D31090A48F9002B3151 /* bn_mp_to_unsigned_bin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */; };
+ F9E61D32090A48FA002B3151 /* bn_mp_unsigned_bin_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */; };
+ F9F4415E0C8BAE6F00BCCD67 /* tclDTrace.d in Sources */ = {isa = PBXBuildFile; fileRef = F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */; };
+ F9FC77B80AB29E9100B7077D /* tclUnixCompat.c in Sources */ = {isa = PBXBuildFile; fileRef = F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ F97258D20A868C6F00096C78 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 8DD76FA90486AB0100D96B5E;
+ remoteInfo = tcltest;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 8DD76FB20486AB0100D96B5E /* tcltest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tcltest; sourceTree = BUILT_PRODUCTS_DIR; };
+ F91E62260C1AE686006C9D96 /* Tclsh-Info.plist.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = "Tclsh-Info.plist.in"; sourceTree = "<group>"; };
+ F95FAFF90B34F1130072E431 /* macOSXLoad.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = macOSXLoad.test; sourceTree = "<group>"; };
+ F966C07408F2820D005CB29B /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
+ F96D3DFA08F272A4004A47F5 /* ChangeLog */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = ChangeLog; sourceTree = "<group>"; };
+ F96D3DFB08F272A4004A47F5 /* changes */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = changes; sourceTree = "<group>"; };
+ F96D3DFD08F272A4004A47F5 /* Access.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Access.3; sourceTree = "<group>"; };
+ F96D3DFE08F272A4004A47F5 /* AddErrInfo.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AddErrInfo.3; sourceTree = "<group>"; };
+ F96D3DFF08F272A4004A47F5 /* after.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = after.n; sourceTree = "<group>"; };
+ F96D3E0008F272A4004A47F5 /* Alloc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Alloc.3; sourceTree = "<group>"; };
+ F96D3E0108F272A4004A47F5 /* AllowExc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AllowExc.3; sourceTree = "<group>"; };
+ F96D3E0208F272A4004A47F5 /* append.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = append.n; sourceTree = "<group>"; };
+ F96D3E0308F272A4004A47F5 /* AppInit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AppInit.3; sourceTree = "<group>"; };
+ F96D3E0408F272A5004A47F5 /* array.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = array.n; sourceTree = "<group>"; };
+ F96D3E0508F272A5004A47F5 /* AssocData.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AssocData.3; sourceTree = "<group>"; };
+ F96D3E0608F272A5004A47F5 /* Async.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Async.3; sourceTree = "<group>"; };
+ F96D3E0708F272A5004A47F5 /* BackgdErr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = BackgdErr.3; sourceTree = "<group>"; };
+ F96D3E0808F272A5004A47F5 /* Backslash.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Backslash.3; sourceTree = "<group>"; };
+ F96D3E0908F272A5004A47F5 /* bgerror.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = bgerror.n; sourceTree = "<group>"; };
+ F96D3E0A08F272A5004A47F5 /* binary.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = binary.n; sourceTree = "<group>"; };
+ F96D3E0B08F272A5004A47F5 /* BoolObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = BoolObj.3; sourceTree = "<group>"; };
+ F96D3E0C08F272A5004A47F5 /* break.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = break.n; sourceTree = "<group>"; };
+ F96D3E0D08F272A5004A47F5 /* ByteArrObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ByteArrObj.3; sourceTree = "<group>"; };
+ F96D3E0E08F272A5004A47F5 /* CallDel.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CallDel.3; sourceTree = "<group>"; };
+ F96D3E0F08F272A5004A47F5 /* case.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = case.n; sourceTree = "<group>"; };
+ F96D3E1008F272A5004A47F5 /* catch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = catch.n; sourceTree = "<group>"; };
+ F96D3E1108F272A5004A47F5 /* cd.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = cd.n; sourceTree = "<group>"; };
+ F96D3E1208F272A5004A47F5 /* chan.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = chan.n; sourceTree = "<group>"; };
+ F96D3E1308F272A5004A47F5 /* ChnlStack.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ChnlStack.3; sourceTree = "<group>"; };
+ F96D3E1408F272A5004A47F5 /* clock.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = clock.n; sourceTree = "<group>"; };
+ F96D3E1508F272A5004A47F5 /* close.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = close.n; sourceTree = "<group>"; };
+ F96D3E1608F272A5004A47F5 /* CmdCmplt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CmdCmplt.3; sourceTree = "<group>"; };
+ F96D3E1708F272A5004A47F5 /* Concat.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Concat.3; sourceTree = "<group>"; };
+ F96D3E1808F272A5004A47F5 /* concat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = concat.n; sourceTree = "<group>"; };
+ F96D3E1908F272A5004A47F5 /* continue.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = continue.n; sourceTree = "<group>"; };
+ F96D3E1A08F272A5004A47F5 /* CrtChannel.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtChannel.3; sourceTree = "<group>"; };
+ F96D3E1B08F272A5004A47F5 /* CrtChnlHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtChnlHdlr.3; sourceTree = "<group>"; };
+ F96D3E1C08F272A5004A47F5 /* CrtCloseHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCloseHdlr.3; sourceTree = "<group>"; };
+ F96D3E1D08F272A5004A47F5 /* CrtCommand.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCommand.3; sourceTree = "<group>"; };
+ F96D3E1E08F272A5004A47F5 /* CrtFileHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtFileHdlr.3; sourceTree = "<group>"; };
+ F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtInterp.3; sourceTree = "<group>"; };
+ F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtMathFnc.3; sourceTree = "<group>"; };
+ F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtObjCmd.3; sourceTree = "<group>"; };
+ F96D3E2208F272A5004A47F5 /* CrtSlave.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtSlave.3; sourceTree = "<group>"; };
+ F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTimerHdlr.3; sourceTree = "<group>"; };
+ F96D3E2408F272A5004A47F5 /* CrtTrace.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTrace.3; sourceTree = "<group>"; };
+ F96D3E2508F272A5004A47F5 /* dde.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dde.n; sourceTree = "<group>"; };
+ F96D3E2608F272A5004A47F5 /* DetachPids.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DetachPids.3; sourceTree = "<group>"; };
+ F96D3E2708F272A5004A47F5 /* dict.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dict.n; sourceTree = "<group>"; };
+ F96D3E2808F272A5004A47F5 /* DictObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DictObj.3; sourceTree = "<group>"; };
+ F96D3E2908F272A5004A47F5 /* DoOneEvent.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoOneEvent.3; sourceTree = "<group>"; };
+ F96D3E2A08F272A5004A47F5 /* DoubleObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoubleObj.3; sourceTree = "<group>"; };
+ F96D3E2B08F272A5004A47F5 /* DoWhenIdle.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoWhenIdle.3; sourceTree = "<group>"; };
+ F96D3E2C08F272A5004A47F5 /* DString.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DString.3; sourceTree = "<group>"; };
+ F96D3E2D08F272A5004A47F5 /* DumpActiveMemory.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DumpActiveMemory.3; sourceTree = "<group>"; };
+ F96D3E2E08F272A5004A47F5 /* Encoding.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Encoding.3; sourceTree = "<group>"; };
+ F96D3E2F08F272A5004A47F5 /* encoding.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = encoding.n; sourceTree = "<group>"; };
+ F96D3E3008F272A5004A47F5 /* Ensemble.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Ensemble.3; sourceTree = "<group>"; };
+ F96D3E3108F272A5004A47F5 /* Environment.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Environment.3; sourceTree = "<group>"; };
+ F96D3E3208F272A5004A47F5 /* eof.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = eof.n; sourceTree = "<group>"; };
+ F96D3E3308F272A5004A47F5 /* error.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = error.n; sourceTree = "<group>"; };
+ F96D3E3408F272A5004A47F5 /* Eval.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Eval.3; sourceTree = "<group>"; };
+ F96D3E3508F272A5004A47F5 /* eval.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = eval.n; sourceTree = "<group>"; };
+ F96D3E3608F272A5004A47F5 /* exec.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = exec.n; sourceTree = "<group>"; };
+ F96D3E3708F272A5004A47F5 /* Exit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Exit.3; sourceTree = "<group>"; };
+ F96D3E3808F272A5004A47F5 /* exit.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = exit.n; sourceTree = "<group>"; };
+ F96D3E3908F272A5004A47F5 /* expr.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = expr.n; sourceTree = "<group>"; };
+ F96D3E3A08F272A5004A47F5 /* ExprLong.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ExprLong.3; sourceTree = "<group>"; };
+ F96D3E3B08F272A5004A47F5 /* ExprLongObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ExprLongObj.3; sourceTree = "<group>"; };
+ F96D3E3C08F272A5004A47F5 /* fblocked.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fblocked.n; sourceTree = "<group>"; };
+ F96D3E3D08F272A5004A47F5 /* fconfigure.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fconfigure.n; sourceTree = "<group>"; };
+ F96D3E3E08F272A5004A47F5 /* fcopy.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fcopy.n; sourceTree = "<group>"; };
+ F96D3E3F08F272A5004A47F5 /* file.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = file.n; sourceTree = "<group>"; };
+ F96D3E4008F272A5004A47F5 /* fileevent.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fileevent.n; sourceTree = "<group>"; };
+ F96D3E4108F272A5004A47F5 /* filename.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = filename.n; sourceTree = "<group>"; };
+ F96D3E4208F272A5004A47F5 /* FileSystem.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FileSystem.3; sourceTree = "<group>"; };
+ F96D3E4308F272A5004A47F5 /* FindExec.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FindExec.3; sourceTree = "<group>"; };
+ F96D3E4408F272A5004A47F5 /* flush.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = flush.n; sourceTree = "<group>"; };
+ F96D3E4508F272A5004A47F5 /* for.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = for.n; sourceTree = "<group>"; };
+ F96D3E4608F272A5004A47F5 /* foreach.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = foreach.n; sourceTree = "<group>"; };
+ F96D3E4708F272A5004A47F5 /* format.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = format.n; sourceTree = "<group>"; };
+ F96D3E4808F272A5004A47F5 /* GetCwd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetCwd.3; sourceTree = "<group>"; };
+ F96D3E4908F272A5004A47F5 /* GetHostName.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetHostName.3; sourceTree = "<group>"; };
+ F96D3E4A08F272A5004A47F5 /* GetIndex.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetIndex.3; sourceTree = "<group>"; };
+ F96D3E4B08F272A5004A47F5 /* GetInt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetInt.3; sourceTree = "<group>"; };
+ F96D3E4C08F272A5004A47F5 /* GetOpnFl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetOpnFl.3; sourceTree = "<group>"; };
+ F96D3E4D08F272A5004A47F5 /* gets.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = gets.n; sourceTree = "<group>"; };
+ F96D3E4E08F272A5004A47F5 /* GetStdChan.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetStdChan.3; sourceTree = "<group>"; };
+ F96D3E4F08F272A5004A47F5 /* GetTime.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetTime.3; sourceTree = "<group>"; };
+ F96D3E5008F272A5004A47F5 /* GetVersion.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetVersion.3; sourceTree = "<group>"; };
+ F96D3E5108F272A5004A47F5 /* glob.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = glob.n; sourceTree = "<group>"; };
+ F96D3E5208F272A6004A47F5 /* global.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = global.n; sourceTree = "<group>"; };
+ F96D3E5308F272A6004A47F5 /* Hash.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Hash.3; sourceTree = "<group>"; };
+ F96D3E5408F272A6004A47F5 /* history.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = history.n; sourceTree = "<group>"; };
+ F96D3E5508F272A6004A47F5 /* http.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = http.n; sourceTree = "<group>"; };
+ F96D3E5608F272A6004A47F5 /* if.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = if.n; sourceTree = "<group>"; };
+ F96D3E5708F272A6004A47F5 /* incr.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = incr.n; sourceTree = "<group>"; };
+ F96D3E5808F272A6004A47F5 /* info.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = info.n; sourceTree = "<group>"; };
+ F96D3E5908F272A6004A47F5 /* Init.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Init.3; sourceTree = "<group>"; };
+ F96D3E5A08F272A6004A47F5 /* InitStubs.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = InitStubs.3; sourceTree = "<group>"; };
+ F96D3E5B08F272A6004A47F5 /* Interp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Interp.3; sourceTree = "<group>"; };
+ F96D3E5C08F272A6004A47F5 /* interp.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = interp.n; sourceTree = "<group>"; };
+ F96D3E5D08F272A6004A47F5 /* IntObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = IntObj.3; sourceTree = "<group>"; };
+ F96D3E5E08F272A6004A47F5 /* join.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = join.n; sourceTree = "<group>"; };
+ F96D3E5F08F272A6004A47F5 /* lappend.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lappend.n; sourceTree = "<group>"; };
+ F96D3E6008F272A6004A47F5 /* lassign.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lassign.n; sourceTree = "<group>"; };
+ F96D3E6108F272A6004A47F5 /* library.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = library.n; sourceTree = "<group>"; };
+ F96D3E6208F272A6004A47F5 /* Limit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Limit.3; sourceTree = "<group>"; };
+ F96D3E6308F272A6004A47F5 /* lindex.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lindex.n; sourceTree = "<group>"; };
+ F96D3E6408F272A6004A47F5 /* LinkVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = LinkVar.3; sourceTree = "<group>"; };
+ F96D3E6508F272A6004A47F5 /* linsert.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = linsert.n; sourceTree = "<group>"; };
+ F96D3E6608F272A6004A47F5 /* list.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = list.n; sourceTree = "<group>"; };
+ F96D3E6708F272A6004A47F5 /* ListObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ListObj.3; sourceTree = "<group>"; };
+ F96D3E6808F272A6004A47F5 /* llength.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = llength.n; sourceTree = "<group>"; };
+ F96D3E6908F272A6004A47F5 /* load.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = load.n; sourceTree = "<group>"; };
+ F96D3E6A08F272A6004A47F5 /* lrange.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lrange.n; sourceTree = "<group>"; };
+ F96D3E6B08F272A6004A47F5 /* lrepeat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lrepeat.n; sourceTree = "<group>"; };
+ F96D3E6C08F272A6004A47F5 /* lreplace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lreplace.n; sourceTree = "<group>"; };
+ F96D3E6D08F272A6004A47F5 /* lsearch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lsearch.n; sourceTree = "<group>"; };
+ F96D3E6E08F272A6004A47F5 /* lset.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lset.n; sourceTree = "<group>"; };
+ F96D3E6F08F272A6004A47F5 /* lsort.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lsort.n; sourceTree = "<group>"; };
+ F96D3E7008F272A6004A47F5 /* man.macros */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = man.macros; sourceTree = "<group>"; };
+ F96D3E7108F272A6004A47F5 /* mathfunc.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = mathfunc.n; sourceTree = "<group>"; };
+ F96D3E7208F272A6004A47F5 /* memory.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = memory.n; sourceTree = "<group>"; };
+ F96D3E7308F272A6004A47F5 /* msgcat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = msgcat.n; sourceTree = "<group>"; };
+ F96D3E7408F272A6004A47F5 /* Namespace.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Namespace.3; sourceTree = "<group>"; };
+ F96D3E7508F272A6004A47F5 /* namespace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = namespace.n; sourceTree = "<group>"; };
+ F96D3E7608F272A6004A47F5 /* Notifier.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Notifier.3; sourceTree = "<group>"; };
+ F96D3E7708F272A6004A47F5 /* Object.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Object.3; sourceTree = "<group>"; };
+ F96D3E7808F272A6004A47F5 /* ObjectType.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ObjectType.3; sourceTree = "<group>"; };
+ F96D3E7908F272A6004A47F5 /* open.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = open.n; sourceTree = "<group>"; };
+ F96D3E7A08F272A6004A47F5 /* OpenFileChnl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = OpenFileChnl.3; sourceTree = "<group>"; };
+ F96D3E7B08F272A6004A47F5 /* OpenTcp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = OpenTcp.3; sourceTree = "<group>"; };
+ F96D3E7C08F272A6004A47F5 /* package.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = package.n; sourceTree = "<group>"; };
+ F96D3E7D08F272A6004A47F5 /* packagens.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = packagens.n; sourceTree = "<group>"; };
+ F96D3E7E08F272A6004A47F5 /* Panic.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Panic.3; sourceTree = "<group>"; };
+ F96D3E7F08F272A6004A47F5 /* ParseCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ParseCmd.3; sourceTree = "<group>"; };
+ F96D3E8008F272A6004A47F5 /* pid.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pid.n; sourceTree = "<group>"; };
+ F96D3E8108F272A6004A47F5 /* pkgMkIndex.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pkgMkIndex.n; sourceTree = "<group>"; };
+ F96D3E8208F272A6004A47F5 /* PkgRequire.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = PkgRequire.3; sourceTree = "<group>"; };
+ F96D3E8308F272A6004A47F5 /* Preserve.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Preserve.3; sourceTree = "<group>"; };
+ F96D3E8408F272A6004A47F5 /* PrintDbl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = PrintDbl.3; sourceTree = "<group>"; };
+ F96D3E8508F272A6004A47F5 /* proc.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = proc.n; sourceTree = "<group>"; };
+ F96D3E8608F272A6004A47F5 /* puts.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = puts.n; sourceTree = "<group>"; };
+ F96D3E8708F272A6004A47F5 /* pwd.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pwd.n; sourceTree = "<group>"; };
+ F96D3E8808F272A6004A47F5 /* re_syntax.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = re_syntax.n; sourceTree = "<group>"; };
+ F96D3E8908F272A6004A47F5 /* read.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = read.n; sourceTree = "<group>"; };
+ F96D3E8A08F272A6004A47F5 /* RecEvalObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RecEvalObj.3; sourceTree = "<group>"; };
+ F96D3E8B08F272A6004A47F5 /* RecordEval.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RecordEval.3; sourceTree = "<group>"; };
+ F96D3E8C08F272A6004A47F5 /* RegConfig.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RegConfig.3; sourceTree = "<group>"; };
+ F96D3E8D08F272A6004A47F5 /* RegExp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RegExp.3; sourceTree = "<group>"; };
+ F96D3E8E08F272A6004A47F5 /* regexp.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = regexp.n; sourceTree = "<group>"; };
+ F96D3E8F08F272A6004A47F5 /* registry.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = registry.n; sourceTree = "<group>"; };
+ F96D3E9008F272A6004A47F5 /* regsub.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = regsub.n; sourceTree = "<group>"; };
+ F96D3E9108F272A6004A47F5 /* rename.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = rename.n; sourceTree = "<group>"; };
+ F96D3E9208F272A6004A47F5 /* return.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = return.n; sourceTree = "<group>"; };
+ F96D3E9308F272A6004A47F5 /* safe.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = safe.n; sourceTree = "<group>"; };
+ F96D3E9408F272A6004A47F5 /* SaveResult.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SaveResult.3; sourceTree = "<group>"; };
+ F96D3E9508F272A6004A47F5 /* scan.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = scan.n; sourceTree = "<group>"; };
+ F96D3E9608F272A6004A47F5 /* seek.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = seek.n; sourceTree = "<group>"; };
+ F96D3E9708F272A6004A47F5 /* set.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = set.n; sourceTree = "<group>"; };
+ F96D3E9808F272A6004A47F5 /* SetChanErr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetChanErr.3; sourceTree = "<group>"; };
+ F96D3E9908F272A6004A47F5 /* SetErrno.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetErrno.3; sourceTree = "<group>"; };
+ F96D3E9A08F272A6004A47F5 /* SetRecLmt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetRecLmt.3; sourceTree = "<group>"; };
+ F96D3E9B08F272A7004A47F5 /* SetResult.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetResult.3; sourceTree = "<group>"; };
+ F96D3E9C08F272A7004A47F5 /* SetVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetVar.3; sourceTree = "<group>"; };
+ F96D3E9D08F272A7004A47F5 /* Signal.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Signal.3; sourceTree = "<group>"; };
+ F96D3E9E08F272A7004A47F5 /* Sleep.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Sleep.3; sourceTree = "<group>"; };
+ F96D3E9F08F272A7004A47F5 /* socket.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = socket.n; sourceTree = "<group>"; };
+ F96D3EA008F272A7004A47F5 /* source.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = source.n; sourceTree = "<group>"; };
+ F96D3EA108F272A7004A47F5 /* SourceRCFile.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SourceRCFile.3; sourceTree = "<group>"; };
+ F96D3EA208F272A7004A47F5 /* split.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = split.n; sourceTree = "<group>"; };
+ F96D3EA308F272A7004A47F5 /* SplitList.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SplitList.3; sourceTree = "<group>"; };
+ F96D3EA408F272A7004A47F5 /* SplitPath.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SplitPath.3; sourceTree = "<group>"; };
+ F96D3EA508F272A7004A47F5 /* StaticPkg.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StaticPkg.3; sourceTree = "<group>"; };
+ F96D3EA608F272A7004A47F5 /* StdChannels.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StdChannels.3; sourceTree = "<group>"; };
+ F96D3EA708F272A7004A47F5 /* string.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = string.n; sourceTree = "<group>"; };
+ F96D3EA808F272A7004A47F5 /* StringObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StringObj.3; sourceTree = "<group>"; };
+ F96D3EA908F272A7004A47F5 /* StrMatch.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StrMatch.3; sourceTree = "<group>"; };
+ F96D3EAA08F272A7004A47F5 /* subst.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = subst.n; sourceTree = "<group>"; };
+ F96D3EAB08F272A7004A47F5 /* SubstObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SubstObj.3; sourceTree = "<group>"; };
+ F96D3EAC08F272A7004A47F5 /* switch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = switch.n; sourceTree = "<group>"; };
+ F96D3EAD08F272A7004A47F5 /* Tcl.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Tcl.n; sourceTree = "<group>"; };
+ F96D3EAE08F272A7004A47F5 /* Tcl_Main.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Tcl_Main.3; sourceTree = "<group>"; };
+ F96D3EAF08F272A7004A47F5 /* TCL_MEM_DEBUG.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TCL_MEM_DEBUG.3; sourceTree = "<group>"; };
+ F96D3EB008F272A7004A47F5 /* tclsh.1 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tclsh.1; sourceTree = "<group>"; };
+ F96D3EB108F272A7004A47F5 /* tcltest.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tcltest.n; sourceTree = "<group>"; };
+ F96D3EB208F272A7004A47F5 /* tclvars.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tclvars.n; sourceTree = "<group>"; };
+ F96D3EB308F272A7004A47F5 /* tell.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tell.n; sourceTree = "<group>"; };
+ F96D3EB408F272A7004A47F5 /* Thread.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Thread.3; sourceTree = "<group>"; };
+ F96D3EB508F272A7004A47F5 /* time.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = time.n; sourceTree = "<group>"; };
+ F96D3EB608F272A7004A47F5 /* tm.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tm.n; sourceTree = "<group>"; };
+ F96D3EB708F272A7004A47F5 /* ToUpper.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ToUpper.3; sourceTree = "<group>"; };
+ F96D3EB808F272A7004A47F5 /* trace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = trace.n; sourceTree = "<group>"; };
+ F96D3EB908F272A7004A47F5 /* TraceCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TraceCmd.3; sourceTree = "<group>"; };
+ F96D3EBA08F272A7004A47F5 /* TraceVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TraceVar.3; sourceTree = "<group>"; };
+ F96D3EBB08F272A7004A47F5 /* Translate.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Translate.3; sourceTree = "<group>"; };
+ F96D3EBC08F272A7004A47F5 /* UniCharIsAlpha.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = UniCharIsAlpha.3; sourceTree = "<group>"; };
+ F96D3EBD08F272A7004A47F5 /* unknown.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unknown.n; sourceTree = "<group>"; };
+ F96D3EBE08F272A7004A47F5 /* unload.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unload.n; sourceTree = "<group>"; };
+ F96D3EBF08F272A7004A47F5 /* unset.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unset.n; sourceTree = "<group>"; };
+ F96D3EC008F272A7004A47F5 /* update.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = update.n; sourceTree = "<group>"; };
+ F96D3EC108F272A7004A47F5 /* uplevel.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = uplevel.n; sourceTree = "<group>"; };
+ F96D3EC208F272A7004A47F5 /* UpVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = UpVar.3; sourceTree = "<group>"; };
+ F96D3EC308F272A7004A47F5 /* upvar.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = upvar.n; sourceTree = "<group>"; };
+ F96D3EC408F272A7004A47F5 /* Utf.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Utf.3; sourceTree = "<group>"; };
+ F96D3EC508F272A7004A47F5 /* variable.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = variable.n; sourceTree = "<group>"; };
+ F96D3EC608F272A7004A47F5 /* vwait.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = vwait.n; sourceTree = "<group>"; };
+ F96D3EC708F272A7004A47F5 /* while.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = while.n; sourceTree = "<group>"; };
+ F96D3EC808F272A7004A47F5 /* WrongNumArgs.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = WrongNumArgs.3; sourceTree = "<group>"; };
+ F96D3ECA08F272A7004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D3ECB08F272A7004A47F5 /* regc_color.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_color.c; sourceTree = "<group>"; };
+ F96D3ECC08F272A7004A47F5 /* regc_cvec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_cvec.c; sourceTree = "<group>"; };
+ F96D3ECD08F272A7004A47F5 /* regc_lex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_lex.c; sourceTree = "<group>"; };
+ F96D3ECE08F272A7004A47F5 /* regc_locale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_locale.c; sourceTree = "<group>"; };
+ F96D3ECF08F272A7004A47F5 /* regc_nfa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_nfa.c; sourceTree = "<group>"; };
+ F96D3ED008F272A7004A47F5 /* regcomp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regcomp.c; sourceTree = "<group>"; };
+ F96D3ED108F272A7004A47F5 /* regcustom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regcustom.h; sourceTree = "<group>"; };
+ F96D3ED208F272A7004A47F5 /* rege_dfa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rege_dfa.c; sourceTree = "<group>"; };
+ F96D3ED308F272A7004A47F5 /* regerror.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regerror.c; sourceTree = "<group>"; };
+ F96D3ED408F272A7004A47F5 /* regerrs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regerrs.h; sourceTree = "<group>"; };
+ F96D3ED508F272A7004A47F5 /* regex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regex.h; sourceTree = "<group>"; };
+ F96D3ED608F272A7004A47F5 /* regexec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regexec.c; sourceTree = "<group>"; };
+ F96D3ED708F272A7004A47F5 /* regfree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regfree.c; sourceTree = "<group>"; };
+ F96D3ED808F272A7004A47F5 /* regfronts.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regfronts.c; sourceTree = "<group>"; };
+ F96D3ED908F272A7004A47F5 /* regguts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regguts.h; sourceTree = "<group>"; };
+ F96D3EDA08F272A7004A47F5 /* tcl.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcl.decls; sourceTree = "<group>"; };
+ F96D3EDB08F272A7004A47F5 /* tcl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tcl.h; sourceTree = "<group>"; };
+ F96D3EDC08F272A7004A47F5 /* tclAlloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAlloc.c; sourceTree = "<group>"; };
+ F96D3EDD08F272A7004A47F5 /* tclAsync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAsync.c; sourceTree = "<group>"; };
+ F96D3EDE08F272A7004A47F5 /* tclBasic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclBasic.c; sourceTree = "<group>"; };
+ F96D3EDF08F272A7004A47F5 /* tclBinary.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclBinary.c; sourceTree = "<group>"; };
+ F96D3EE008F272A7004A47F5 /* tclCkalloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCkalloc.c; sourceTree = "<group>"; };
+ F96D3EE108F272A7004A47F5 /* tclClock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclClock.c; sourceTree = "<group>"; };
+ F96D3EE208F272A7004A47F5 /* tclCmdAH.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdAH.c; sourceTree = "<group>"; };
+ F96D3EE308F272A7004A47F5 /* tclCmdIL.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdIL.c; sourceTree = "<group>"; };
+ F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdMZ.c; sourceTree = "<group>"; };
+ F96D3EE508F272A7004A47F5 /* tclCompCmds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompCmds.c; sourceTree = "<group>"; };
+ F96D3EE608F272A7004A47F5 /* tclCompExpr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompExpr.c; sourceTree = "<group>"; };
+ F96D3EE708F272A7004A47F5 /* tclCompile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompile.c; sourceTree = "<group>"; };
+ F96D3EE808F272A7004A47F5 /* tclCompile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclCompile.h; sourceTree = "<group>"; };
+ F96D3EE908F272A7004A47F5 /* tclConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclConfig.c; sourceTree = "<group>"; };
+ F96D3EEA08F272A7004A47F5 /* tclDate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclDate.c; sourceTree = "<group>"; };
+ F96D3EEB08F272A7004A47F5 /* tclDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclDecls.h; sourceTree = "<group>"; };
+ F96D3EEC08F272A7004A47F5 /* tclDictObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclDictObj.c; sourceTree = "<group>"; };
+ F96D3EED08F272A7004A47F5 /* tclEncoding.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEncoding.c; sourceTree = "<group>"; };
+ F96D3EEE08F272A7004A47F5 /* tclEnv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEnv.c; sourceTree = "<group>"; };
+ F96D3EEF08F272A7004A47F5 /* tclEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEvent.c; sourceTree = "<group>"; };
+ F96D3EF008F272A7004A47F5 /* tclExecute.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclExecute.c; sourceTree = "<group>"; };
+ F96D3EF108F272A7004A47F5 /* tclFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclFCmd.c; sourceTree = "<group>"; };
+ F96D3EF208F272A7004A47F5 /* tclFileName.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclFileName.c; sourceTree = "<group>"; };
+ F96D3EF308F272A7004A47F5 /* tclFileSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclFileSystem.h; sourceTree = "<group>"; };
+ F96D3EF408F272A7004A47F5 /* tclGet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclGet.c; sourceTree = "<group>"; };
+ F96D3EF508F272A7004A47F5 /* tclGetDate.y */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.yacc; path = tclGetDate.y; sourceTree = "<group>"; };
+ F96D3EF608F272A7004A47F5 /* tclHash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclHash.c; sourceTree = "<group>"; };
+ F96D3EF708F272A7004A47F5 /* tclHistory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclHistory.c; sourceTree = "<group>"; };
+ F96D3EF808F272A7004A47F5 /* tclIndexObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIndexObj.c; sourceTree = "<group>"; };
+ F96D3EF908F272A7004A47F5 /* tclInt.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclInt.decls; sourceTree = "<group>"; };
+ F96D3EFA08F272A7004A47F5 /* tclInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclInt.h; sourceTree = "<group>"; };
+ F96D3EFB08F272A7004A47F5 /* tclIntDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIntDecls.h; sourceTree = "<group>"; };
+ F96D3EFC08F272A7004A47F5 /* tclInterp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclInterp.c; sourceTree = "<group>"; };
+ F96D3EFD08F272A7004A47F5 /* tclIntPlatDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIntPlatDecls.h; sourceTree = "<group>"; };
+ F96D3EFE08F272A7004A47F5 /* tclIO.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIO.c; sourceTree = "<group>"; };
+ F96D3EFF08F272A7004A47F5 /* tclIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIO.h; sourceTree = "<group>"; };
+ F96D3F0008F272A7004A47F5 /* tclIOCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOCmd.c; sourceTree = "<group>"; };
+ F96D3F0108F272A7004A47F5 /* tclIOGT.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOGT.c; sourceTree = "<group>"; };
+ F96D3F0208F272A7004A47F5 /* tclIORChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIORChan.c; sourceTree = "<group>"; };
+ F96D3F0308F272A7004A47F5 /* tclIOSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOSock.c; sourceTree = "<group>"; };
+ F96D3F0408F272A7004A47F5 /* tclIOUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOUtil.c; sourceTree = "<group>"; };
+ F96D3F0508F272A7004A47F5 /* tclLink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLink.c; sourceTree = "<group>"; };
+ F96D3F0608F272A7004A47F5 /* tclListObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclListObj.c; sourceTree = "<group>"; };
+ F96D3F0708F272A7004A47F5 /* tclLiteral.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLiteral.c; sourceTree = "<group>"; };
+ F96D3F0808F272A7004A47F5 /* tclLoad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoad.c; sourceTree = "<group>"; };
+ F96D3F0908F272A7004A47F5 /* tclLoadNone.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadNone.c; sourceTree = "<group>"; };
+ F96D3F0A08F272A7004A47F5 /* tclMain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMain.c; sourceTree = "<group>"; };
+ F96D3F0B08F272A7004A47F5 /* tclNamesp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclNamesp.c; sourceTree = "<group>"; };
+ F96D3F0C08F272A7004A47F5 /* tclNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclNotify.c; sourceTree = "<group>"; };
+ F96D3F0D08F272A7004A47F5 /* tclObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclObj.c; sourceTree = "<group>"; };
+ F96D3F0E08F272A7004A47F5 /* tclPanic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPanic.c; sourceTree = "<group>"; };
+ F96D3F0F08F272A7004A47F5 /* tclParse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclParse.c; sourceTree = "<group>"; };
+ F96D3F1108F272A7004A47F5 /* tclPathObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPathObj.c; sourceTree = "<group>"; };
+ F96D3F1208F272A7004A47F5 /* tclPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPipe.c; sourceTree = "<group>"; };
+ F96D3F1308F272A7004A47F5 /* tclPkg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPkg.c; sourceTree = "<group>"; };
+ F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPkgConfig.c; sourceTree = "<group>"; };
+ F96D3F1508F272A7004A47F5 /* tclPlatDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclPlatDecls.h; sourceTree = "<group>"; };
+ F96D3F1608F272A7004A47F5 /* tclPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclPort.h; sourceTree = "<group>"; };
+ F96D3F1708F272A7004A47F5 /* tclPosixStr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPosixStr.c; sourceTree = "<group>"; };
+ F96D3F1808F272A7004A47F5 /* tclPreserve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPreserve.c; sourceTree = "<group>"; };
+ F96D3F1908F272A7004A47F5 /* tclProc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclProc.c; sourceTree = "<group>"; };
+ F96D3F1A08F272A7004A47F5 /* tclRegexp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclRegexp.c; sourceTree = "<group>"; };
+ F96D3F1B08F272A7004A47F5 /* tclRegexp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclRegexp.h; sourceTree = "<group>"; };
+ F96D3F1C08F272A7004A47F5 /* tclResolve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclResolve.c; sourceTree = "<group>"; };
+ F96D3F1D08F272A7004A47F5 /* tclResult.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclResult.c; sourceTree = "<group>"; };
+ F96D3F1E08F272A7004A47F5 /* tclScan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclScan.c; sourceTree = "<group>"; };
+ F96D3F1F08F272A7004A47F5 /* tclStringObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStringObj.c; sourceTree = "<group>"; };
+ F96D3F2408F272A7004A47F5 /* tclStrToD.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStrToD.c; sourceTree = "<group>"; };
+ F96D3F2508F272A7004A47F5 /* tclStubInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStubInit.c; sourceTree = "<group>"; };
+ F96D3F2608F272A7004A47F5 /* tclStubLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStubLib.c; sourceTree = "<group>"; };
+ F96D3F2708F272A7004A47F5 /* tclTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTest.c; sourceTree = "<group>"; };
+ F96D3F2808F272A7004A47F5 /* tclTestObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTestObj.c; sourceTree = "<group>"; };
+ F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTestProcBodyObj.c; sourceTree = "<group>"; };
+ F96D3F2A08F272A7004A47F5 /* tclThread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThread.c; sourceTree = "<group>"; };
+ F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadAlloc.c; sourceTree = "<group>"; };
+ F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadJoin.c; sourceTree = "<group>"; };
+ F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadStorage.c; sourceTree = "<group>"; };
+ F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadTest.c; sourceTree = "<group>"; };
+ F96D3F2F08F272A7004A47F5 /* tclTimer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTimer.c; sourceTree = "<group>"; };
+ F96D3F3008F272A7004A47F5 /* tclTomMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclTomMath.h; sourceTree = "<group>"; };
+ F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTomMathInterface.c; sourceTree = "<group>"; };
+ F96D3F3208F272A7004A47F5 /* tclTrace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTrace.c; sourceTree = "<group>"; };
+ F96D3F3308F272A7004A47F5 /* tclUniData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUniData.c; sourceTree = "<group>"; };
+ F96D3F3408F272A7004A47F5 /* tclUtf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUtf.c; sourceTree = "<group>"; };
+ F96D3F3508F272A7004A47F5 /* tclUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUtil.c; sourceTree = "<group>"; };
+ F96D3F3608F272A7004A47F5 /* tclVar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclVar.c; sourceTree = "<group>"; };
+ F96D3F3708F272A7004A47F5 /* tommath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath.h; sourceTree = "<group>"; };
+ F96D3F3908F272A8004A47F5 /* auto.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = auto.tcl; sourceTree = "<group>"; };
+ F96D3F3A08F272A8004A47F5 /* clock.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clock.tcl; sourceTree = "<group>"; };
+ F96D3F3C08F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D3F8C08F272A8004A47F5 /* history.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = history.tcl; sourceTree = "<group>"; };
+ F96D3F8E08F272A8004A47F5 /* http.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.tcl; sourceTree = "<group>"; };
+ F96D3F8F08F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D3F9108F272A8004A47F5 /* http.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.tcl; sourceTree = "<group>"; };
+ F96D3F9208F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D3F9308F272A8004A47F5 /* init.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = init.tcl; sourceTree = "<group>"; };
+ F96D3F9508F272A8004A47F5 /* msgcat.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgcat.tcl; sourceTree = "<group>"; };
+ F96D3F9608F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D401808F272AA004A47F5 /* optparse.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = optparse.tcl; sourceTree = "<group>"; };
+ F96D401908F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D401A08F272AA004A47F5 /* package.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = package.tcl; sourceTree = "<group>"; };
+ F96D401B08F272AA004A47F5 /* parray.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parray.tcl; sourceTree = "<group>"; };
+ F96D401D08F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D401E08F272AA004A47F5 /* safe.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = safe.tcl; sourceTree = "<group>"; };
+ F96D401F08F272AA004A47F5 /* tclIndex */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclIndex; sourceTree = "<group>"; };
+ F96D402108F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F96D402208F272AA004A47F5 /* tcltest.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcltest.tcl; sourceTree = "<group>"; };
+ F96D402308F272AA004A47F5 /* tm.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tm.tcl; sourceTree = "<group>"; };
+ F96D425B08F272B2004A47F5 /* word.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = word.tcl; sourceTree = "<group>"; };
+ F96D425F08F272B3004A47F5 /* bn.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = bn.pdf; sourceTree = "<group>"; };
+ F96D426108F272B3004A47F5 /* bn_error.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_error.c; sourceTree = "<group>"; };
+ F96D426208F272B3004A47F5 /* bn_fast_mp_invmod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_mp_invmod.c; sourceTree = "<group>"; };
+ F96D426308F272B3004A47F5 /* bn_fast_mp_montgomery_reduce.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_mp_montgomery_reduce.c; sourceTree = "<group>"; };
+ F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_s_mp_mul_digs.c; sourceTree = "<group>"; };
+ F96D426508F272B3004A47F5 /* bn_fast_s_mp_mul_high_digs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_s_mp_mul_high_digs.c; sourceTree = "<group>"; };
+ F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_s_mp_sqr.c; sourceTree = "<group>"; };
+ F96D426708F272B3004A47F5 /* bn_mp_2expt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_2expt.c; sourceTree = "<group>"; };
+ F96D426808F272B3004A47F5 /* bn_mp_abs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_abs.c; sourceTree = "<group>"; };
+ F96D426908F272B3004A47F5 /* bn_mp_add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_add.c; sourceTree = "<group>"; };
+ F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_add_d.c; sourceTree = "<group>"; };
+ F96D426B08F272B3004A47F5 /* bn_mp_addmod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_addmod.c; sourceTree = "<group>"; };
+ F96D426C08F272B3004A47F5 /* bn_mp_and.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_and.c; sourceTree = "<group>"; };
+ F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clamp.c; sourceTree = "<group>"; };
+ F96D426E08F272B3004A47F5 /* bn_mp_clear.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clear.c; sourceTree = "<group>"; };
+ F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clear_multi.c; sourceTree = "<group>"; };
+ F96D427008F272B3004A47F5 /* bn_mp_cmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp.c; sourceTree = "<group>"; };
+ F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp_d.c; sourceTree = "<group>"; };
+ F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp_mag.c; sourceTree = "<group>"; };
+ F96D427308F272B3004A47F5 /* bn_mp_cnt_lsb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cnt_lsb.c; sourceTree = "<group>"; };
+ F96D427408F272B3004A47F5 /* bn_mp_copy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_copy.c; sourceTree = "<group>"; };
+ F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_count_bits.c; sourceTree = "<group>"; };
+ F96D427608F272B3004A47F5 /* bn_mp_div.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div.c; sourceTree = "<group>"; };
+ F96D427708F272B3004A47F5 /* bn_mp_div_2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2.c; sourceTree = "<group>"; };
+ F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2d.c; sourceTree = "<group>"; };
+ F96D427908F272B3004A47F5 /* bn_mp_div_3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_3.c; sourceTree = "<group>"; };
+ F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_d.c; sourceTree = "<group>"; };
+ F96D427B08F272B3004A47F5 /* bn_mp_dr_is_modulus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_dr_is_modulus.c; sourceTree = "<group>"; };
+ F96D427C08F272B3004A47F5 /* bn_mp_dr_reduce.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_dr_reduce.c; sourceTree = "<group>"; };
+ F96D427D08F272B3004A47F5 /* bn_mp_dr_setup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_dr_setup.c; sourceTree = "<group>"; };
+ F96D427E08F272B3004A47F5 /* bn_mp_exch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_exch.c; sourceTree = "<group>"; };
+ F96D427F08F272B3004A47F5 /* bn_mp_expt_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_expt_d.c; sourceTree = "<group>"; };
+ F96D428008F272B3004A47F5 /* bn_mp_exptmod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_exptmod.c; sourceTree = "<group>"; };
+ F96D428108F272B3004A47F5 /* bn_mp_exptmod_fast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_exptmod_fast.c; sourceTree = "<group>"; };
+ F96D428208F272B3004A47F5 /* bn_mp_exteuclid.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_exteuclid.c; sourceTree = "<group>"; };
+ F96D428308F272B3004A47F5 /* bn_mp_fread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_fread.c; sourceTree = "<group>"; };
+ F96D428408F272B3004A47F5 /* bn_mp_fwrite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_fwrite.c; sourceTree = "<group>"; };
+ F96D428508F272B3004A47F5 /* bn_mp_gcd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_gcd.c; sourceTree = "<group>"; };
+ F96D428608F272B3004A47F5 /* bn_mp_get_int.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_get_int.c; sourceTree = "<group>"; };
+ F96D428708F272B3004A47F5 /* bn_mp_grow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_grow.c; sourceTree = "<group>"; };
+ F96D428808F272B3004A47F5 /* bn_mp_init.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init.c; sourceTree = "<group>"; };
+ F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_copy.c; sourceTree = "<group>"; };
+ F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_multi.c; sourceTree = "<group>"; };
+ F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_set.c; sourceTree = "<group>"; };
+ F96D428C08F272B3004A47F5 /* bn_mp_init_set_int.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_set_int.c; sourceTree = "<group>"; };
+ F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_size.c; sourceTree = "<group>"; };
+ F96D428E08F272B3004A47F5 /* bn_mp_invmod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_invmod.c; sourceTree = "<group>"; };
+ F96D428F08F272B3004A47F5 /* bn_mp_invmod_slow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_invmod_slow.c; sourceTree = "<group>"; };
+ F96D429008F272B3004A47F5 /* bn_mp_is_square.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_is_square.c; sourceTree = "<group>"; };
+ F96D429108F272B3004A47F5 /* bn_mp_jacobi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_jacobi.c; sourceTree = "<group>"; };
+ F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_karatsuba_mul.c; sourceTree = "<group>"; };
+ F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_karatsuba_sqr.c; sourceTree = "<group>"; };
+ F96D429408F272B3004A47F5 /* bn_mp_lcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_lcm.c; sourceTree = "<group>"; };
+ F96D429508F272B3004A47F5 /* bn_mp_lshd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_lshd.c; sourceTree = "<group>"; };
+ F96D429608F272B3004A47F5 /* bn_mp_mod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mod.c; sourceTree = "<group>"; };
+ F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mod_2d.c; sourceTree = "<group>"; };
+ F96D429808F272B3004A47F5 /* bn_mp_mod_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mod_d.c; sourceTree = "<group>"; };
+ F96D429908F272B3004A47F5 /* bn_mp_montgomery_calc_normalization.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_montgomery_calc_normalization.c; sourceTree = "<group>"; };
+ F96D429A08F272B3004A47F5 /* bn_mp_montgomery_reduce.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_montgomery_reduce.c; sourceTree = "<group>"; };
+ F96D429B08F272B3004A47F5 /* bn_mp_montgomery_setup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_montgomery_setup.c; sourceTree = "<group>"; };
+ F96D429C08F272B3004A47F5 /* bn_mp_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul.c; sourceTree = "<group>"; };
+ F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_2.c; sourceTree = "<group>"; };
+ F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_2d.c; sourceTree = "<group>"; };
+ F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_d.c; sourceTree = "<group>"; };
+ F96D42A008F272B3004A47F5 /* bn_mp_mulmod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mulmod.c; sourceTree = "<group>"; };
+ F96D42A108F272B3004A47F5 /* bn_mp_n_root.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_n_root.c; sourceTree = "<group>"; };
+ F96D42A208F272B3004A47F5 /* bn_mp_neg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_neg.c; sourceTree = "<group>"; };
+ F96D42A308F272B3004A47F5 /* bn_mp_or.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_or.c; sourceTree = "<group>"; };
+ F96D42A408F272B3004A47F5 /* bn_mp_prime_fermat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_prime_fermat.c; sourceTree = "<group>"; };
+ F96D42A508F272B3004A47F5 /* bn_mp_prime_is_divisible.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_prime_is_divisible.c; sourceTree = "<group>"; };
+ F96D42A608F272B3004A47F5 /* bn_mp_prime_is_prime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_prime_is_prime.c; sourceTree = "<group>"; };
+ F96D42A708F272B3004A47F5 /* bn_mp_prime_miller_rabin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_prime_miller_rabin.c; sourceTree = "<group>"; };
+ F96D42A808F272B3004A47F5 /* bn_mp_prime_next_prime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_prime_next_prime.c; sourceTree = "<group>"; };
+ F96D42A908F272B3004A47F5 /* bn_mp_prime_rabin_miller_trials.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_prime_rabin_miller_trials.c; sourceTree = "<group>"; };
+ F96D42AA08F272B3004A47F5 /* bn_mp_prime_random_ex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_prime_random_ex.c; sourceTree = "<group>"; };
+ F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_radix_size.c; sourceTree = "<group>"; };
+ F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_radix_smap.c; sourceTree = "<group>"; };
+ F96D42AD08F272B3004A47F5 /* bn_mp_rand.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_rand.c; sourceTree = "<group>"; };
+ F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_read_radix.c; sourceTree = "<group>"; };
+ F96D42AF08F272B3004A47F5 /* bn_mp_read_signed_bin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_read_signed_bin.c; sourceTree = "<group>"; };
+ F96D42B008F272B3004A47F5 /* bn_mp_read_unsigned_bin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_read_unsigned_bin.c; sourceTree = "<group>"; };
+ F96D42B108F272B3004A47F5 /* bn_mp_reduce.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_reduce.c; sourceTree = "<group>"; };
+ F96D42B208F272B3004A47F5 /* bn_mp_reduce_2k.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_reduce_2k.c; sourceTree = "<group>"; };
+ F96D42B308F272B3004A47F5 /* bn_mp_reduce_2k_l.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_reduce_2k_l.c; sourceTree = "<group>"; };
+ F96D42B408F272B3004A47F5 /* bn_mp_reduce_2k_setup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_reduce_2k_setup.c; sourceTree = "<group>"; };
+ F96D42B508F272B3004A47F5 /* bn_mp_reduce_2k_setup_l.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_reduce_2k_setup_l.c; sourceTree = "<group>"; };
+ F96D42B608F272B3004A47F5 /* bn_mp_reduce_is_2k.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_reduce_is_2k.c; sourceTree = "<group>"; };
+ F96D42B708F272B3004A47F5 /* bn_mp_reduce_is_2k_l.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_reduce_is_2k_l.c; sourceTree = "<group>"; };
+ F96D42B808F272B3004A47F5 /* bn_mp_reduce_setup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_reduce_setup.c; sourceTree = "<group>"; };
+ F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_rshd.c; sourceTree = "<group>"; };
+ F96D42BA08F272B3004A47F5 /* bn_mp_set.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_set.c; sourceTree = "<group>"; };
+ F96D42BB08F272B3004A47F5 /* bn_mp_set_int.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_set_int.c; sourceTree = "<group>"; };
+ F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_shrink.c; sourceTree = "<group>"; };
+ F96D42BD08F272B3004A47F5 /* bn_mp_signed_bin_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_signed_bin_size.c; sourceTree = "<group>"; };
+ F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sqr.c; sourceTree = "<group>"; };
+ F96D42BF08F272B3004A47F5 /* bn_mp_sqrmod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sqrmod.c; sourceTree = "<group>"; };
+ F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sqrt.c; sourceTree = "<group>"; };
+ F96D42C108F272B3004A47F5 /* bn_mp_sub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sub.c; sourceTree = "<group>"; };
+ F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sub_d.c; sourceTree = "<group>"; };
+ F96D42C308F272B3004A47F5 /* bn_mp_submod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_submod.c; sourceTree = "<group>"; };
+ F96D42C408F272B3004A47F5 /* bn_mp_to_signed_bin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_to_signed_bin.c; sourceTree = "<group>"; };
+ F96D42C508F272B3004A47F5 /* bn_mp_to_signed_bin_n.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_to_signed_bin_n.c; sourceTree = "<group>"; };
+ F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_to_unsigned_bin.c; sourceTree = "<group>"; };
+ F96D42C708F272B3004A47F5 /* bn_mp_to_unsigned_bin_n.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_to_unsigned_bin_n.c; sourceTree = "<group>"; };
+ F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toom_mul.c; sourceTree = "<group>"; };
+ F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toom_sqr.c; sourceTree = "<group>"; };
+ F96D42CA08F272B3004A47F5 /* bn_mp_toradix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toradix.c; sourceTree = "<group>"; };
+ F96D42CB08F272B3004A47F5 /* bn_mp_toradix_n.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toradix_n.c; sourceTree = "<group>"; };
+ F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_unsigned_bin_size.c; sourceTree = "<group>"; };
+ F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_xor.c; sourceTree = "<group>"; };
+ F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_zero.c; sourceTree = "<group>"; };
+ F96D42CF08F272B3004A47F5 /* bn_prime_tab.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_prime_tab.c; sourceTree = "<group>"; };
+ F96D42D008F272B3004A47F5 /* bn_reverse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_reverse.c; sourceTree = "<group>"; };
+ F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_add.c; sourceTree = "<group>"; };
+ F96D42D208F272B3004A47F5 /* bn_s_mp_exptmod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_exptmod.c; sourceTree = "<group>"; };
+ F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_mul_digs.c; sourceTree = "<group>"; };
+ F96D42D408F272B3004A47F5 /* bn_s_mp_mul_high_digs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_mul_high_digs.c; sourceTree = "<group>"; };
+ F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_sqr.c; sourceTree = "<group>"; };
+ F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_sub.c; sourceTree = "<group>"; };
+ F96D42D708F272B3004A47F5 /* bncore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bncore.c; sourceTree = "<group>"; };
+ F96D42D908F272B3004A47F5 /* callgraph.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = callgraph.txt; sourceTree = "<group>"; };
+ F96D42DA08F272B3004A47F5 /* changes.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = changes.txt; sourceTree = "<group>"; };
+ F96D42F008F272B3004A47F5 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
+ F96D431D08F272B4004A47F5 /* poster.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = poster.pdf; sourceTree = "<group>"; };
+ F96D432608F272B4004A47F5 /* tommath.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = tommath.pdf; sourceTree = "<group>"; };
+ F96D432908F272B4004A47F5 /* tommath_class.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath_class.h; sourceTree = "<group>"; };
+ F96D432A08F272B4004A47F5 /* tommath_superclass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath_superclass.h; sourceTree = "<group>"; };
+ F96D432B08F272B4004A47F5 /* license.terms */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = license.terms; sourceTree = "<group>"; };
+ F96D432E08F272B5004A47F5 /* configure.ac */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure.ac; sourceTree = "<group>"; };
+ F96D432F08F272B5004A47F5 /* GNUmakefile */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = GNUmakefile; sourceTree = "<group>"; };
+ F96D433108F272B5004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D433208F272B5004A47F5 /* Tcl-Info.plist.in */ = {isa = PBXFileReference; explicitFileType = text.plist; fileEncoding = 4; path = "Tcl-Info.plist.in"; sourceTree = "<group>"; };
+ F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXBundle.c; sourceTree = "<group>"; };
+ F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXFCmd.c; sourceTree = "<group>"; };
+ F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXNotify.c; sourceTree = "<group>"; };
+ F96D434308F272B5004A47F5 /* README */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = README; sourceTree = "<group>"; };
+ F96D434508F272B5004A47F5 /* all.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = all.tcl; sourceTree = "<group>"; };
+ F96D434608F272B5004A47F5 /* append.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = append.test; sourceTree = "<group>"; };
+ F96D434708F272B5004A47F5 /* appendComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = appendComp.test; sourceTree = "<group>"; };
+ F96D434808F272B5004A47F5 /* assocd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = assocd.test; sourceTree = "<group>"; };
+ F96D434908F272B5004A47F5 /* async.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = async.test; sourceTree = "<group>"; };
+ F96D434A08F272B5004A47F5 /* autoMkindex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = autoMkindex.test; sourceTree = "<group>"; };
+ F96D434B08F272B5004A47F5 /* basic.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = basic.test; sourceTree = "<group>"; };
+ F96D434C08F272B5004A47F5 /* binary.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = binary.test; sourceTree = "<group>"; };
+ F96D434D08F272B5004A47F5 /* case.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = case.test; sourceTree = "<group>"; };
+ F96D434E08F272B5004A47F5 /* chan.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = chan.test; sourceTree = "<group>"; };
+ F96D434F08F272B5004A47F5 /* clock.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clock.test; sourceTree = "<group>"; };
+ F96D435008F272B5004A47F5 /* cmdAH.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdAH.test; sourceTree = "<group>"; };
+ F96D435108F272B5004A47F5 /* cmdIL.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdIL.test; sourceTree = "<group>"; };
+ F96D435208F272B5004A47F5 /* cmdInfo.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdInfo.test; sourceTree = "<group>"; };
+ F96D435308F272B5004A47F5 /* cmdMZ.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdMZ.test; sourceTree = "<group>"; };
+ F96D435408F272B5004A47F5 /* compExpr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "compExpr-old.test"; sourceTree = "<group>"; };
+ F96D435508F272B5004A47F5 /* compExpr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = compExpr.test; sourceTree = "<group>"; };
+ F96D435608F272B5004A47F5 /* compile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = compile.test; sourceTree = "<group>"; };
+ F96D435708F272B5004A47F5 /* concat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = concat.test; sourceTree = "<group>"; };
+ F96D435808F272B5004A47F5 /* config.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = config.test; sourceTree = "<group>"; };
+ F96D435908F272B5004A47F5 /* dcall.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dcall.test; sourceTree = "<group>"; };
+ F96D435A08F272B5004A47F5 /* dict.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dict.test; sourceTree = "<group>"; };
+ F96D435C08F272B5004A47F5 /* dstring.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dstring.test; sourceTree = "<group>"; };
+ F96D435E08F272B5004A47F5 /* encoding.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = encoding.test; sourceTree = "<group>"; };
+ F96D435F08F272B5004A47F5 /* env.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = env.test; sourceTree = "<group>"; };
+ F96D436008F272B5004A47F5 /* error.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = error.test; sourceTree = "<group>"; };
+ F96D436108F272B5004A47F5 /* eval.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = eval.test; sourceTree = "<group>"; };
+ F96D436208F272B5004A47F5 /* event.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = event.test; sourceTree = "<group>"; };
+ F96D436308F272B5004A47F5 /* exec.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = exec.test; sourceTree = "<group>"; };
+ F96D436408F272B5004A47F5 /* execute.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = execute.test; sourceTree = "<group>"; };
+ F96D436508F272B5004A47F5 /* expr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "expr-old.test"; sourceTree = "<group>"; };
+ F96D436608F272B5004A47F5 /* expr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = expr.test; sourceTree = "<group>"; };
+ F96D436708F272B6004A47F5 /* fCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fCmd.test; sourceTree = "<group>"; };
+ F96D436808F272B6004A47F5 /* fileName.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fileName.test; sourceTree = "<group>"; };
+ F96D436908F272B6004A47F5 /* fileSystem.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fileSystem.test; sourceTree = "<group>"; };
+ F96D436A08F272B6004A47F5 /* for-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "for-old.test"; sourceTree = "<group>"; };
+ F96D436B08F272B6004A47F5 /* for.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = for.test; sourceTree = "<group>"; };
+ F96D436C08F272B6004A47F5 /* foreach.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = foreach.test; sourceTree = "<group>"; };
+ F96D436D08F272B6004A47F5 /* format.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = format.test; sourceTree = "<group>"; };
+ F96D436E08F272B6004A47F5 /* get.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = get.test; sourceTree = "<group>"; };
+ F96D436F08F272B6004A47F5 /* history.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = history.test; sourceTree = "<group>"; };
+ F96D437008F272B6004A47F5 /* http.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.test; sourceTree = "<group>"; };
+ F96D437108F272B6004A47F5 /* httpd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = httpd; sourceTree = "<group>"; };
+ F96D437208F272B6004A47F5 /* httpold.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = httpold.test; sourceTree = "<group>"; };
+ F96D437308F272B6004A47F5 /* if-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "if-old.test"; sourceTree = "<group>"; };
+ F96D437408F272B6004A47F5 /* if.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = if.test; sourceTree = "<group>"; };
+ F96D437508F272B6004A47F5 /* incr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "incr-old.test"; sourceTree = "<group>"; };
+ F96D437608F272B6004A47F5 /* incr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = incr.test; sourceTree = "<group>"; };
+ F96D437708F272B6004A47F5 /* indexObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = indexObj.test; sourceTree = "<group>"; };
+ F96D437808F272B6004A47F5 /* info.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = info.test; sourceTree = "<group>"; };
+ F96D437908F272B6004A47F5 /* init.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = init.test; sourceTree = "<group>"; };
+ F96D437A08F272B6004A47F5 /* interp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = interp.test; sourceTree = "<group>"; };
+ F96D437B08F272B6004A47F5 /* io.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = io.test; sourceTree = "<group>"; };
+ F96D437C08F272B6004A47F5 /* ioCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ioCmd.test; sourceTree = "<group>"; };
+ F96D437D08F272B6004A47F5 /* iogt.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = iogt.test; sourceTree = "<group>"; };
+ F96D437E08F272B6004A47F5 /* ioUtil.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ioUtil.test; sourceTree = "<group>"; };
+ F96D437F08F272B6004A47F5 /* join.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = join.test; sourceTree = "<group>"; };
+ F96D438008F272B6004A47F5 /* lindex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lindex.test; sourceTree = "<group>"; };
+ F96D438108F272B6004A47F5 /* link.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = link.test; sourceTree = "<group>"; };
+ F96D438208F272B6004A47F5 /* linsert.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = linsert.test; sourceTree = "<group>"; };
+ F96D438308F272B6004A47F5 /* list.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = list.test; sourceTree = "<group>"; };
+ F96D438408F272B6004A47F5 /* listObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = listObj.test; sourceTree = "<group>"; };
+ F96D438508F272B6004A47F5 /* llength.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = llength.test; sourceTree = "<group>"; };
+ F96D438608F272B6004A47F5 /* load.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = load.test; sourceTree = "<group>"; };
+ F96D438708F272B6004A47F5 /* lrange.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lrange.test; sourceTree = "<group>"; };
+ F96D438808F272B6004A47F5 /* lrepeat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lrepeat.test; sourceTree = "<group>"; };
+ F96D438908F272B6004A47F5 /* lreplace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lreplace.test; sourceTree = "<group>"; };
+ F96D438A08F272B6004A47F5 /* lsearch.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lsearch.test; sourceTree = "<group>"; };
+ F96D438B08F272B6004A47F5 /* lset.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lset.test; sourceTree = "<group>"; };
+ F96D438C08F272B6004A47F5 /* lsetComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lsetComp.test; sourceTree = "<group>"; };
+ F96D438D08F272B6004A47F5 /* macOSXFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = macOSXFCmd.test; sourceTree = "<group>"; };
+ F96D438E08F272B6004A47F5 /* main.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = main.test; sourceTree = "<group>"; };
+ F96D438F08F272B6004A47F5 /* misc.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = misc.test; sourceTree = "<group>"; };
+ F96D439008F272B6004A47F5 /* msgcat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgcat.test; sourceTree = "<group>"; };
+ F96D439108F272B6004A47F5 /* namespace-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "namespace-old.test"; sourceTree = "<group>"; };
+ F96D439208F272B7004A47F5 /* namespace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = namespace.test; sourceTree = "<group>"; };
+ F96D439308F272B7004A47F5 /* notify.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = notify.test; sourceTree = "<group>"; };
+ F96D439408F272B7004A47F5 /* obj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = obj.test; sourceTree = "<group>"; };
+ F96D439508F272B7004A47F5 /* opt.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = opt.test; sourceTree = "<group>"; };
+ F96D439608F272B7004A47F5 /* package.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = package.test; sourceTree = "<group>"; };
+ F96D439708F272B7004A47F5 /* parse.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parse.test; sourceTree = "<group>"; };
+ F96D439808F272B7004A47F5 /* parseExpr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parseExpr.test; sourceTree = "<group>"; };
+ F96D439908F272B7004A47F5 /* parseOld.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parseOld.test; sourceTree = "<group>"; };
+ F96D439A08F272B7004A47F5 /* pid.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pid.test; sourceTree = "<group>"; };
+ F96D439B08F272B7004A47F5 /* pkg.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkg.test; sourceTree = "<group>"; };
+ F96D439C08F272B7004A47F5 /* pkgMkIndex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgMkIndex.test; sourceTree = "<group>"; };
+ F96D439D08F272B7004A47F5 /* platform.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = platform.test; sourceTree = "<group>"; };
+ F96D439E08F272B7004A47F5 /* proc-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "proc-old.test"; sourceTree = "<group>"; };
+ F96D439F08F272B7004A47F5 /* proc.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = proc.test; sourceTree = "<group>"; };
+ F96D43A008F272B7004A47F5 /* pwd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pwd.test; sourceTree = "<group>"; };
+ F96D43A108F272B7004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D43A208F272B7004A47F5 /* reg.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = reg.test; sourceTree = "<group>"; };
+ F96D43A308F272B7004A47F5 /* regexp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexp.test; sourceTree = "<group>"; };
+ F96D43A408F272B7004A47F5 /* regexpComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexpComp.test; sourceTree = "<group>"; };
+ F96D43A508F272B7004A47F5 /* registry.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = registry.test; sourceTree = "<group>"; };
+ F96D43A608F272B7004A47F5 /* remote.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = remote.tcl; sourceTree = "<group>"; };
+ F96D43A708F272B7004A47F5 /* rename.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = rename.test; sourceTree = "<group>"; };
+ F96D43A808F272B7004A47F5 /* result.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = result.test; sourceTree = "<group>"; };
+ F96D43A908F272B7004A47F5 /* safe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = safe.test; sourceTree = "<group>"; };
+ F96D43AA08F272B7004A47F5 /* scan.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scan.test; sourceTree = "<group>"; };
+ F96D43AB08F272B7004A47F5 /* security.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = security.test; sourceTree = "<group>"; };
+ F96D43AC08F272B7004A47F5 /* set-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "set-old.test"; sourceTree = "<group>"; };
+ F96D43AD08F272B7004A47F5 /* set.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = set.test; sourceTree = "<group>"; };
+ F96D43AE08F272B7004A47F5 /* socket.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = socket.test; sourceTree = "<group>"; };
+ F96D43AF08F272B7004A47F5 /* source.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = source.test; sourceTree = "<group>"; };
+ F96D43B008F272B7004A47F5 /* split.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = split.test; sourceTree = "<group>"; };
+ F96D43B108F272B7004A47F5 /* stack.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stack.test; sourceTree = "<group>"; };
+ F96D43B208F272B7004A47F5 /* string.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = string.test; sourceTree = "<group>"; };
+ F96D43B308F272B7004A47F5 /* stringComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stringComp.test; sourceTree = "<group>"; };
+ F96D43B408F272B7004A47F5 /* stringObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stringObj.test; sourceTree = "<group>"; };
+ F96D43B508F272B7004A47F5 /* subst.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = subst.test; sourceTree = "<group>"; };
+ F96D43B608F272B7004A47F5 /* switch.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = switch.test; sourceTree = "<group>"; };
+ F96D43B708F272B7004A47F5 /* tcltest.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcltest.test; sourceTree = "<group>"; };
+ F96D43B808F272B7004A47F5 /* thread.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = thread.test; sourceTree = "<group>"; };
+ F96D43B908F272B7004A47F5 /* timer.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = timer.test; sourceTree = "<group>"; };
+ F96D43BA08F272B7004A47F5 /* tm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tm.test; sourceTree = "<group>"; };
+ F96D43BB08F272B7004A47F5 /* trace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = trace.test; sourceTree = "<group>"; };
+ F96D43BC08F272B7004A47F5 /* unixFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixFCmd.test; sourceTree = "<group>"; };
+ F96D43BD08F272B7004A47F5 /* unixFile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixFile.test; sourceTree = "<group>"; };
+ F96D43BE08F272B7004A47F5 /* unixInit.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixInit.test; sourceTree = "<group>"; };
+ F96D43BF08F272B7004A47F5 /* unixNotfy.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixNotfy.test; sourceTree = "<group>"; };
+ F96D43C008F272B7004A47F5 /* unknown.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unknown.test; sourceTree = "<group>"; };
+ F96D43C108F272B7004A47F5 /* unload.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unload.test; sourceTree = "<group>"; };
+ F96D43C208F272B7004A47F5 /* uplevel.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uplevel.test; sourceTree = "<group>"; };
+ F96D43C308F272B7004A47F5 /* upvar.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = upvar.test; sourceTree = "<group>"; };
+ F96D43C408F272B7004A47F5 /* utf.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = utf.test; sourceTree = "<group>"; };
+ F96D43C508F272B7004A47F5 /* util.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = util.test; sourceTree = "<group>"; };
+ F96D43C608F272B7004A47F5 /* var.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = var.test; sourceTree = "<group>"; };
+ F96D43C708F272B7004A47F5 /* while-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "while-old.test"; sourceTree = "<group>"; };
+ F96D43C808F272B7004A47F5 /* while.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = while.test; sourceTree = "<group>"; };
+ F96D43C908F272B7004A47F5 /* winConsole.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winConsole.test; sourceTree = "<group>"; };
+ F96D43CA08F272B7004A47F5 /* winDde.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winDde.test; sourceTree = "<group>"; };
+ F96D43CB08F272B7004A47F5 /* winFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFCmd.test; sourceTree = "<group>"; };
+ F96D43CC08F272B7004A47F5 /* winFile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFile.test; sourceTree = "<group>"; };
+ F96D43CD08F272B7004A47F5 /* winNotify.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winNotify.test; sourceTree = "<group>"; };
+ F96D43CE08F272B7004A47F5 /* winPipe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winPipe.test; sourceTree = "<group>"; };
+ F96D43CF08F272B7004A47F5 /* winTime.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winTime.test; sourceTree = "<group>"; };
+ F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = checkLibraryDoc.tcl; sourceTree = "<group>"; };
+ F96D43D208F272B8004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
+ F96D43D308F272B8004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
+ F96D442208F272B8004A47F5 /* eolFix.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = eolFix.tcl; sourceTree = "<group>"; };
+ F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fix_tommath_h.tcl; sourceTree = "<group>"; };
+ F96D442508F272B8004A47F5 /* genStubs.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = genStubs.tcl; sourceTree = "<group>"; };
+ F96D442708F272B8004A47F5 /* index.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = index.tcl; sourceTree = "<group>"; };
+ F96D442808F272B8004A47F5 /* installData.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = installData.tcl; sourceTree = "<group>"; };
+ F96D442908F272B8004A47F5 /* loadICU.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = loadICU.tcl; sourceTree = "<group>"; };
+ F96D442A08F272B8004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
+ F96D442B08F272B8004A47F5 /* makeTestCases.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = makeTestCases.tcl; sourceTree = "<group>"; };
+ F96D442C08F272B8004A47F5 /* man2help.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2help.tcl; sourceTree = "<group>"; };
+ F96D442D08F272B8004A47F5 /* man2help2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2help2.tcl; sourceTree = "<group>"; };
+ F96D442E08F272B8004A47F5 /* man2html.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html.tcl; sourceTree = "<group>"; };
+ F96D442F08F272B8004A47F5 /* man2html1.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html1.tcl; sourceTree = "<group>"; };
+ F96D443008F272B8004A47F5 /* man2html2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html2.tcl; sourceTree = "<group>"; };
+ F96D443108F272B8004A47F5 /* man2tcl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = man2tcl.c; sourceTree = "<group>"; };
+ F96D443208F272B8004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D443308F272B8004A47F5 /* regexpTestLib.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexpTestLib.tcl; sourceTree = "<group>"; };
+ F96D443408F272B8004A47F5 /* str2c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = str2c; sourceTree = "<group>"; };
+ F96D443508F272B8004A47F5 /* tcl.hpj.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.hpj.in; sourceTree = "<group>"; };
+ F96D443608F272B8004A47F5 /* tcl.wse.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.wse.in; sourceTree = "<group>"; };
+ F96D443708F272B9004A47F5 /* tclmin.wse */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tclmin.wse; sourceTree = "<group>"; };
+ F96D443908F272B9004A47F5 /* tcltk-man2html.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "tcltk-man2html.tcl"; sourceTree = "<group>"; };
+ F96D443A08F272B9004A47F5 /* tclZIC.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclZIC.tcl; sourceTree = "<group>"; };
+ F96D443B08F272B9004A47F5 /* uniClass.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniClass.tcl; sourceTree = "<group>"; };
+ F96D443C08F272B9004A47F5 /* uniParse.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniParse.tcl; sourceTree = "<group>"; };
+ F96D444008F272B9004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
+ F96D444108F272B9004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
+ F96D444208F272B9004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
+ F96D444408F272B9004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
+ F96D444508F272B9004A47F5 /* pkga.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkga.c; sourceTree = "<group>"; };
+ F96D444608F272B9004A47F5 /* pkgb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgb.c; sourceTree = "<group>"; };
+ F96D444708F272B9004A47F5 /* pkgc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgc.c; sourceTree = "<group>"; };
+ F96D444808F272B9004A47F5 /* pkgd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgd.c; sourceTree = "<group>"; };
+ F96D444908F272B9004A47F5 /* pkge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkge.c; sourceTree = "<group>"; };
+ F96D444B08F272B9004A47F5 /* pkgua.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgua.c; sourceTree = "<group>"; };
+ F96D444C08F272B9004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D444D08F272B9004A47F5 /* install-sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "install-sh"; sourceTree = "<group>"; };
+ F96D444E08F272B9004A47F5 /* installManPage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = installManPage; sourceTree = "<group>"; };
+ F96D444F08F272B9004A47F5 /* ldAix */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ldAix; sourceTree = "<group>"; };
+ F96D445008F272B9004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
+ F96D445208F272B9004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D445308F272B9004A47F5 /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = "<group>"; };
+ F96D445408F272B9004A47F5 /* tcl.spec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.spec; sourceTree = "<group>"; };
+ F96D445508F272B9004A47F5 /* tclAppInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAppInit.c; sourceTree = "<group>"; };
+ F96D445608F272B9004A47F5 /* tclConfig.h.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = tclConfig.h.in; sourceTree = "<group>"; };
+ F96D445708F272B9004A47F5 /* tclConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tclConfig.sh.in; sourceTree = "<group>"; };
+ F96D445808F272B9004A47F5 /* tclLoadAix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadAix.c; sourceTree = "<group>"; };
+ F96D445908F272B9004A47F5 /* tclLoadDl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadDl.c; sourceTree = "<group>"; };
+ F96D445B08F272B9004A47F5 /* tclLoadDyld.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadDyld.c; sourceTree = "<group>"; };
+ F96D445C08F272B9004A47F5 /* tclLoadNext.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadNext.c; sourceTree = "<group>"; };
+ F96D445D08F272B9004A47F5 /* tclLoadOSF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadOSF.c; sourceTree = "<group>"; };
+ F96D445E08F272B9004A47F5 /* tclLoadShl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadShl.c; sourceTree = "<group>"; };
+ F96D445F08F272B9004A47F5 /* tclUnixChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixChan.c; sourceTree = "<group>"; };
+ F96D446008F272B9004A47F5 /* tclUnixEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixEvent.c; sourceTree = "<group>"; };
+ F96D446108F272B9004A47F5 /* tclUnixFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixFCmd.c; sourceTree = "<group>"; };
+ F96D446208F272B9004A47F5 /* tclUnixFile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixFile.c; sourceTree = "<group>"; };
+ F96D446308F272B9004A47F5 /* tclUnixInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixInit.c; sourceTree = "<group>"; };
+ F96D446408F272B9004A47F5 /* tclUnixNotfy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixNotfy.c; sourceTree = "<group>"; };
+ F96D446508F272B9004A47F5 /* tclUnixPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixPipe.c; sourceTree = "<group>"; };
+ F96D446608F272B9004A47F5 /* tclUnixPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclUnixPort.h; sourceTree = "<group>"; };
+ F96D446708F272B9004A47F5 /* tclUnixSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixSock.c; sourceTree = "<group>"; };
+ F96D446808F272B9004A47F5 /* tclUnixTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTest.c; sourceTree = "<group>"; };
+ F96D446908F272B9004A47F5 /* tclUnixThrd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixThrd.c; sourceTree = "<group>"; };
+ F96D446A08F272B9004A47F5 /* tclUnixThrd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclUnixThrd.h; sourceTree = "<group>"; };
+ F96D446B08F272B9004A47F5 /* tclUnixTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTime.c; sourceTree = "<group>"; };
+ F96D446C08F272B9004A47F5 /* tclXtNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtNotify.c; sourceTree = "<group>"; };
+ F96D446D08F272B9004A47F5 /* tclXtTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtTest.c; sourceTree = "<group>"; };
+ F96D447008F272BA004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = "<group>"; };
+ F96D447108F272BA004A47F5 /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = "<group>"; };
+ F96D447208F272BA004A47F5 /* cat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cat.c; sourceTree = "<group>"; };
+ F96D447308F272BA004A47F5 /* coffbase.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = coffbase.txt; sourceTree = "<group>"; };
+ F96D447408F272BA004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
+ F96D447508F272BA004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
+ F96D447608F272BA004A47F5 /* makefile.bc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.bc; sourceTree = "<group>"; };
+ F96D447708F272BA004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = "<group>"; };
+ F96D447808F272BA004A47F5 /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = "<group>"; };
+ F96D447908F272BA004A47F5 /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = "<group>"; };
+ F96D447A08F272BA004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ F96D447C08F272BA004A47F5 /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = "<group>"; };
+ F96D447D08F272BA004A47F5 /* stub16.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stub16.c; sourceTree = "<group>"; };
+ F96D447E08F272BA004A47F5 /* tcl.dsp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.dsp; sourceTree = "<group>"; };
+ F96D447F08F272BA004A47F5 /* tcl.dsw */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.dsw; sourceTree = "<group>"; };
+ F96D448008F272BA004A47F5 /* tcl.hpj.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.hpj.in; sourceTree = "<group>"; };
+ F96D448108F272BA004A47F5 /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = "<group>"; };
+ F96D448208F272BA004A47F5 /* tcl.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.rc; sourceTree = "<group>"; };
+ F96D448308F272BA004A47F5 /* tclAppInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAppInit.c; sourceTree = "<group>"; };
+ F96D448408F272BA004A47F5 /* tclConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tclConfig.sh.in; sourceTree = "<group>"; };
+ F96D448608F272BA004A47F5 /* tclsh.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tclsh.rc; sourceTree = "<group>"; };
+ F96D448708F272BA004A47F5 /* tclWin32Dll.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWin32Dll.c; sourceTree = "<group>"; };
+ F96D448808F272BA004A47F5 /* tclWinChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinChan.c; sourceTree = "<group>"; };
+ F96D448908F272BA004A47F5 /* tclWinConsole.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinConsole.c; sourceTree = "<group>"; };
+ F96D448A08F272BA004A47F5 /* tclWinDde.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinDde.c; sourceTree = "<group>"; };
+ F96D448B08F272BA004A47F5 /* tclWinError.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinError.c; sourceTree = "<group>"; };
+ F96D448C08F272BA004A47F5 /* tclWinFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinFCmd.c; sourceTree = "<group>"; };
+ F96D448D08F272BA004A47F5 /* tclWinFile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinFile.c; sourceTree = "<group>"; };
+ F96D448E08F272BA004A47F5 /* tclWinInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinInit.c; sourceTree = "<group>"; };
+ F96D448F08F272BA004A47F5 /* tclWinInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinInt.h; sourceTree = "<group>"; };
+ F96D449008F272BA004A47F5 /* tclWinLoad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinLoad.c; sourceTree = "<group>"; };
+ F96D449108F272BA004A47F5 /* tclWinNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinNotify.c; sourceTree = "<group>"; };
+ F96D449208F272BA004A47F5 /* tclWinPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinPipe.c; sourceTree = "<group>"; };
+ F96D449308F272BA004A47F5 /* tclWinPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinPort.h; sourceTree = "<group>"; };
+ F96D449408F272BA004A47F5 /* tclWinReg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinReg.c; sourceTree = "<group>"; };
+ F96D449508F272BA004A47F5 /* tclWinSerial.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSerial.c; sourceTree = "<group>"; };
+ F96D449608F272BA004A47F5 /* tclWinSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSock.c; sourceTree = "<group>"; };
+ F96D449708F272BA004A47F5 /* tclWinTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTest.c; sourceTree = "<group>"; };
+ F96D449808F272BA004A47F5 /* tclWinThrd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinThrd.c; sourceTree = "<group>"; };
+ F96D449908F272BA004A47F5 /* tclWinThrd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinThrd.h; sourceTree = "<group>"; };
+ F96D449A08F272BA004A47F5 /* tclWinTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTime.c; sourceTree = "<group>"; };
+ F97AE7F10B65C1E900310EA2 /* Tcl-Common.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Common.xcconfig"; sourceTree = "<group>"; };
+ F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Release.xcconfig"; sourceTree = "<group>"; };
+ F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Debug.xcconfig"; sourceTree = "<group>"; };
+ F9903CAF094FAADA004613E9 /* tclTomMath.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclTomMath.decls; sourceTree = "<group>"; };
+ F9903CB0094FAADA004613E9 /* tclTomMathDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclTomMathDecls.h; sourceTree = "<group>"; };
+ F9A3084B08F2D4CE00BAE1AB /* tclsh */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tclsh; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9A3084E08F2D4F400BAE1AB /* Tcl.framework */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.framework; path = Tcl.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9A493240CEBF38300B78AE2 /* chanio.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = chanio.test; sourceTree = "<group>"; };
+ F9ECB1120B26521500A28025 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = "<group>"; };
+ F9ECB1130B26521500A28025 /* platform.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = platform.tcl; sourceTree = "<group>"; };
+ F9ECB1140B26521500A28025 /* shell.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = shell.tcl; sourceTree = "<group>"; };
+ F9ECB1CA0B2652D300A28025 /* apply.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = apply.test; sourceTree = "<group>"; };
+ F9ECB1CB0B26534C00A28025 /* mathop.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = mathop.test; sourceTree = "<group>"; };
+ F9ECB1E10B26543C00A28025 /* platform_shell.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = platform_shell.n; sourceTree = "<group>"; };
+ F9ECB1E20B26543C00A28025 /* platform.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = platform.n; sourceTree = "<group>"; };
+ F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = tclDTrace.d; sourceTree = "<group>"; };
+ F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixCompat.c; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8DD76FAD0486AB0100D96B5E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F966C07508F2820D005CB29B /* CoreFoundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 08FB7794FE84155DC02AAC07 /* Tcl */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3DF608F27169004A47F5 /* Tcl Sources */,
+ F966C06F08F281DC005CB29B /* Frameworks */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ );
+ comments = "Copyright (c) 2004-2008 Daniel A. Steffen <das@users.sourceforge.net>\n\nSee the file \"license.terms\" for information on usage and redistribution of\nthis file, and for a DISCLAIMER OF ALL WARRANTIES.\n";
+ name = Tcl;
+ path = .;
+ sourceTree = SOURCE_ROOT;
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ F9A3084B08F2D4CE00BAE1AB /* tclsh */,
+ 8DD76FB20486AB0100D96B5E /* tcltest */,
+ F9A3084E08F2D4F400BAE1AB /* Tcl.framework */,
+ );
+ includeInIndex = 0;
+ name = Products;
+ sourceTree = "<group>";
+ };
+ F966C06F08F281DC005CB29B /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ F966C07408F2820D005CB29B /* CoreFoundation.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ F96D3DF608F27169004A47F5 /* Tcl Sources */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3EC908F272A7004A47F5 /* generic */,
+ F96D432C08F272B4004A47F5 /* macosx */,
+ F96D443E08F272B9004A47F5 /* unix */,
+ F96D425C08F272B2004A47F5 /* libtommath */,
+ F96D446E08F272B9004A47F5 /* win */,
+ F96D3F3808F272A7004A47F5 /* library */,
+ F96D434408F272B5004A47F5 /* tests */,
+ F96D3DFC08F272A4004A47F5 /* doc */,
+ F96D43D008F272B8004A47F5 /* tools */,
+ F96D3DFA08F272A4004A47F5 /* ChangeLog */,
+ F96D3DFB08F272A4004A47F5 /* changes */,
+ F96D434308F272B5004A47F5 /* README */,
+ F96D432B08F272B4004A47F5 /* license.terms */,
+ );
+ name = "Tcl Sources";
+ sourceTree = TCL_SRCROOT;
+ };
+ F96D3DFC08F272A4004A47F5 /* doc */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3DFD08F272A4004A47F5 /* Access.3 */,
+ F96D3DFE08F272A4004A47F5 /* AddErrInfo.3 */,
+ F96D3DFF08F272A4004A47F5 /* after.n */,
+ F96D3E0008F272A4004A47F5 /* Alloc.3 */,
+ F96D3E0108F272A4004A47F5 /* AllowExc.3 */,
+ F96D3E0208F272A4004A47F5 /* append.n */,
+ F96D3E0308F272A4004A47F5 /* AppInit.3 */,
+ F96D3E0408F272A5004A47F5 /* array.n */,
+ F96D3E0508F272A5004A47F5 /* AssocData.3 */,
+ F96D3E0608F272A5004A47F5 /* Async.3 */,
+ F96D3E0708F272A5004A47F5 /* BackgdErr.3 */,
+ F96D3E0808F272A5004A47F5 /* Backslash.3 */,
+ F96D3E0908F272A5004A47F5 /* bgerror.n */,
+ F96D3E0A08F272A5004A47F5 /* binary.n */,
+ F96D3E0B08F272A5004A47F5 /* BoolObj.3 */,
+ F96D3E0C08F272A5004A47F5 /* break.n */,
+ F96D3E0D08F272A5004A47F5 /* ByteArrObj.3 */,
+ F96D3E0E08F272A5004A47F5 /* CallDel.3 */,
+ F96D3E0F08F272A5004A47F5 /* case.n */,
+ F96D3E1008F272A5004A47F5 /* catch.n */,
+ F96D3E1108F272A5004A47F5 /* cd.n */,
+ F96D3E1208F272A5004A47F5 /* chan.n */,
+ F96D3E1308F272A5004A47F5 /* ChnlStack.3 */,
+ F96D3E1408F272A5004A47F5 /* clock.n */,
+ F96D3E1508F272A5004A47F5 /* close.n */,
+ F96D3E1608F272A5004A47F5 /* CmdCmplt.3 */,
+ F96D3E1708F272A5004A47F5 /* Concat.3 */,
+ F96D3E1808F272A5004A47F5 /* concat.n */,
+ F96D3E1908F272A5004A47F5 /* continue.n */,
+ F96D3E1A08F272A5004A47F5 /* CrtChannel.3 */,
+ F96D3E1B08F272A5004A47F5 /* CrtChnlHdlr.3 */,
+ F96D3E1C08F272A5004A47F5 /* CrtCloseHdlr.3 */,
+ F96D3E1D08F272A5004A47F5 /* CrtCommand.3 */,
+ F96D3E1E08F272A5004A47F5 /* CrtFileHdlr.3 */,
+ F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */,
+ F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */,
+ F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */,
+ F96D3E2208F272A5004A47F5 /* CrtSlave.3 */,
+ F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */,
+ F96D3E2408F272A5004A47F5 /* CrtTrace.3 */,
+ F96D3E2508F272A5004A47F5 /* dde.n */,
+ F96D3E2608F272A5004A47F5 /* DetachPids.3 */,
+ F96D3E2708F272A5004A47F5 /* dict.n */,
+ F96D3E2808F272A5004A47F5 /* DictObj.3 */,
+ F96D3E2908F272A5004A47F5 /* DoOneEvent.3 */,
+ F96D3E2A08F272A5004A47F5 /* DoubleObj.3 */,
+ F96D3E2B08F272A5004A47F5 /* DoWhenIdle.3 */,
+ F96D3E2C08F272A5004A47F5 /* DString.3 */,
+ F96D3E2D08F272A5004A47F5 /* DumpActiveMemory.3 */,
+ F96D3E2E08F272A5004A47F5 /* Encoding.3 */,
+ F96D3E2F08F272A5004A47F5 /* encoding.n */,
+ F96D3E3008F272A5004A47F5 /* Ensemble.3 */,
+ F96D3E3108F272A5004A47F5 /* Environment.3 */,
+ F96D3E3208F272A5004A47F5 /* eof.n */,
+ F96D3E3308F272A5004A47F5 /* error.n */,
+ F96D3E3408F272A5004A47F5 /* Eval.3 */,
+ F96D3E3508F272A5004A47F5 /* eval.n */,
+ F96D3E3608F272A5004A47F5 /* exec.n */,
+ F96D3E3708F272A5004A47F5 /* Exit.3 */,
+ F96D3E3808F272A5004A47F5 /* exit.n */,
+ F96D3E3908F272A5004A47F5 /* expr.n */,
+ F96D3E3A08F272A5004A47F5 /* ExprLong.3 */,
+ F96D3E3B08F272A5004A47F5 /* ExprLongObj.3 */,
+ F96D3E3C08F272A5004A47F5 /* fblocked.n */,
+ F96D3E3D08F272A5004A47F5 /* fconfigure.n */,
+ F96D3E3E08F272A5004A47F5 /* fcopy.n */,
+ F96D3E3F08F272A5004A47F5 /* file.n */,
+ F96D3E4008F272A5004A47F5 /* fileevent.n */,
+ F96D3E4108F272A5004A47F5 /* filename.n */,
+ F96D3E4208F272A5004A47F5 /* FileSystem.3 */,
+ F96D3E4308F272A5004A47F5 /* FindExec.3 */,
+ F96D3E4408F272A5004A47F5 /* flush.n */,
+ F96D3E4508F272A5004A47F5 /* for.n */,
+ F96D3E4608F272A5004A47F5 /* foreach.n */,
+ F96D3E4708F272A5004A47F5 /* format.n */,
+ F96D3E4808F272A5004A47F5 /* GetCwd.3 */,
+ F96D3E4908F272A5004A47F5 /* GetHostName.3 */,
+ F96D3E4A08F272A5004A47F5 /* GetIndex.3 */,
+ F96D3E4B08F272A5004A47F5 /* GetInt.3 */,
+ F96D3E4C08F272A5004A47F5 /* GetOpnFl.3 */,
+ F96D3E4D08F272A5004A47F5 /* gets.n */,
+ F96D3E4E08F272A5004A47F5 /* GetStdChan.3 */,
+ F96D3E4F08F272A5004A47F5 /* GetTime.3 */,
+ F96D3E5008F272A5004A47F5 /* GetVersion.3 */,
+ F96D3E5108F272A5004A47F5 /* glob.n */,
+ F96D3E5208F272A6004A47F5 /* global.n */,
+ F96D3E5308F272A6004A47F5 /* Hash.3 */,
+ F96D3E5408F272A6004A47F5 /* history.n */,
+ F96D3E5508F272A6004A47F5 /* http.n */,
+ F96D3E5608F272A6004A47F5 /* if.n */,
+ F96D3E5708F272A6004A47F5 /* incr.n */,
+ F96D3E5808F272A6004A47F5 /* info.n */,
+ F96D3E5908F272A6004A47F5 /* Init.3 */,
+ F96D3E5A08F272A6004A47F5 /* InitStubs.3 */,
+ F96D3E5B08F272A6004A47F5 /* Interp.3 */,
+ F96D3E5C08F272A6004A47F5 /* interp.n */,
+ F96D3E5D08F272A6004A47F5 /* IntObj.3 */,
+ F96D3E5E08F272A6004A47F5 /* join.n */,
+ F96D3E5F08F272A6004A47F5 /* lappend.n */,
+ F96D3E6008F272A6004A47F5 /* lassign.n */,
+ F96D3E6108F272A6004A47F5 /* library.n */,
+ F96D3E6208F272A6004A47F5 /* Limit.3 */,
+ F96D3E6308F272A6004A47F5 /* lindex.n */,
+ F96D3E6408F272A6004A47F5 /* LinkVar.3 */,
+ F96D3E6508F272A6004A47F5 /* linsert.n */,
+ F96D3E6608F272A6004A47F5 /* list.n */,
+ F96D3E6708F272A6004A47F5 /* ListObj.3 */,
+ F96D3E6808F272A6004A47F5 /* llength.n */,
+ F96D3E6908F272A6004A47F5 /* load.n */,
+ F96D3E6A08F272A6004A47F5 /* lrange.n */,
+ F96D3E6B08F272A6004A47F5 /* lrepeat.n */,
+ F96D3E6C08F272A6004A47F5 /* lreplace.n */,
+ F96D3E6D08F272A6004A47F5 /* lsearch.n */,
+ F96D3E6E08F272A6004A47F5 /* lset.n */,
+ F96D3E6F08F272A6004A47F5 /* lsort.n */,
+ F96D3E7008F272A6004A47F5 /* man.macros */,
+ F96D3E7108F272A6004A47F5 /* mathfunc.n */,
+ F96D3E7208F272A6004A47F5 /* memory.n */,
+ F96D3E7308F272A6004A47F5 /* msgcat.n */,
+ F96D3E7408F272A6004A47F5 /* Namespace.3 */,
+ F96D3E7508F272A6004A47F5 /* namespace.n */,
+ F96D3E7608F272A6004A47F5 /* Notifier.3 */,
+ F96D3E7708F272A6004A47F5 /* Object.3 */,
+ F96D3E7808F272A6004A47F5 /* ObjectType.3 */,
+ F96D3E7908F272A6004A47F5 /* open.n */,
+ F96D3E7A08F272A6004A47F5 /* OpenFileChnl.3 */,
+ F96D3E7B08F272A6004A47F5 /* OpenTcp.3 */,
+ F96D3E7C08F272A6004A47F5 /* package.n */,
+ F96D3E7D08F272A6004A47F5 /* packagens.n */,
+ F96D3E7E08F272A6004A47F5 /* Panic.3 */,
+ F96D3E7F08F272A6004A47F5 /* ParseCmd.3 */,
+ F96D3E8008F272A6004A47F5 /* pid.n */,
+ F96D3E8108F272A6004A47F5 /* pkgMkIndex.n */,
+ F96D3E8208F272A6004A47F5 /* PkgRequire.3 */,
+ F9ECB1E10B26543C00A28025 /* platform_shell.n */,
+ F9ECB1E20B26543C00A28025 /* platform.n */,
+ F96D3E8308F272A6004A47F5 /* Preserve.3 */,
+ F96D3E8408F272A6004A47F5 /* PrintDbl.3 */,
+ F96D3E8508F272A6004A47F5 /* proc.n */,
+ F96D3E8608F272A6004A47F5 /* puts.n */,
+ F96D3E8708F272A6004A47F5 /* pwd.n */,
+ F96D3E8808F272A6004A47F5 /* re_syntax.n */,
+ F96D3E8908F272A6004A47F5 /* read.n */,
+ F96D3E8A08F272A6004A47F5 /* RecEvalObj.3 */,
+ F96D3E8B08F272A6004A47F5 /* RecordEval.3 */,
+ F96D3E8C08F272A6004A47F5 /* RegConfig.3 */,
+ F96D3E8D08F272A6004A47F5 /* RegExp.3 */,
+ F96D3E8E08F272A6004A47F5 /* regexp.n */,
+ F96D3E8F08F272A6004A47F5 /* registry.n */,
+ F96D3E9008F272A6004A47F5 /* regsub.n */,
+ F96D3E9108F272A6004A47F5 /* rename.n */,
+ F96D3E9208F272A6004A47F5 /* return.n */,
+ F96D3E9308F272A6004A47F5 /* safe.n */,
+ F96D3E9408F272A6004A47F5 /* SaveResult.3 */,
+ F96D3E9508F272A6004A47F5 /* scan.n */,
+ F96D3E9608F272A6004A47F5 /* seek.n */,
+ F96D3E9708F272A6004A47F5 /* set.n */,
+ F96D3E9808F272A6004A47F5 /* SetChanErr.3 */,
+ F96D3E9908F272A6004A47F5 /* SetErrno.3 */,
+ F96D3E9A08F272A6004A47F5 /* SetRecLmt.3 */,
+ F96D3E9B08F272A7004A47F5 /* SetResult.3 */,
+ F96D3E9C08F272A7004A47F5 /* SetVar.3 */,
+ F96D3E9D08F272A7004A47F5 /* Signal.3 */,
+ F96D3E9E08F272A7004A47F5 /* Sleep.3 */,
+ F96D3E9F08F272A7004A47F5 /* socket.n */,
+ F96D3EA008F272A7004A47F5 /* source.n */,
+ F96D3EA108F272A7004A47F5 /* SourceRCFile.3 */,
+ F96D3EA208F272A7004A47F5 /* split.n */,
+ F96D3EA308F272A7004A47F5 /* SplitList.3 */,
+ F96D3EA408F272A7004A47F5 /* SplitPath.3 */,
+ F96D3EA508F272A7004A47F5 /* StaticPkg.3 */,
+ F96D3EA608F272A7004A47F5 /* StdChannels.3 */,
+ F96D3EA708F272A7004A47F5 /* string.n */,
+ F96D3EA808F272A7004A47F5 /* StringObj.3 */,
+ F96D3EA908F272A7004A47F5 /* StrMatch.3 */,
+ F96D3EAA08F272A7004A47F5 /* subst.n */,
+ F96D3EAB08F272A7004A47F5 /* SubstObj.3 */,
+ F96D3EAC08F272A7004A47F5 /* switch.n */,
+ F96D3EAD08F272A7004A47F5 /* Tcl.n */,
+ F96D3EAE08F272A7004A47F5 /* Tcl_Main.3 */,
+ F96D3EAF08F272A7004A47F5 /* TCL_MEM_DEBUG.3 */,
+ F96D3EB008F272A7004A47F5 /* tclsh.1 */,
+ F96D3EB108F272A7004A47F5 /* tcltest.n */,
+ F96D3EB208F272A7004A47F5 /* tclvars.n */,
+ F96D3EB308F272A7004A47F5 /* tell.n */,
+ F96D3EB408F272A7004A47F5 /* Thread.3 */,
+ F96D3EB508F272A7004A47F5 /* time.n */,
+ F96D3EB608F272A7004A47F5 /* tm.n */,
+ F96D3EB708F272A7004A47F5 /* ToUpper.3 */,
+ F96D3EB808F272A7004A47F5 /* trace.n */,
+ F96D3EB908F272A7004A47F5 /* TraceCmd.3 */,
+ F96D3EBA08F272A7004A47F5 /* TraceVar.3 */,
+ F96D3EBB08F272A7004A47F5 /* Translate.3 */,
+ F96D3EBC08F272A7004A47F5 /* UniCharIsAlpha.3 */,
+ F96D3EBD08F272A7004A47F5 /* unknown.n */,
+ F96D3EBE08F272A7004A47F5 /* unload.n */,
+ F96D3EBF08F272A7004A47F5 /* unset.n */,
+ F96D3EC008F272A7004A47F5 /* update.n */,
+ F96D3EC108F272A7004A47F5 /* uplevel.n */,
+ F96D3EC208F272A7004A47F5 /* UpVar.3 */,
+ F96D3EC308F272A7004A47F5 /* upvar.n */,
+ F96D3EC408F272A7004A47F5 /* Utf.3 */,
+ F96D3EC508F272A7004A47F5 /* variable.n */,
+ F96D3EC608F272A7004A47F5 /* vwait.n */,
+ F96D3EC708F272A7004A47F5 /* while.n */,
+ F96D3EC808F272A7004A47F5 /* WrongNumArgs.3 */,
+ );
+ path = doc;
+ sourceTree = "<group>";
+ };
+ F96D3EC908F272A7004A47F5 /* generic */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3ECA08F272A7004A47F5 /* README */,
+ F96D3ECB08F272A7004A47F5 /* regc_color.c */,
+ F96D3ECC08F272A7004A47F5 /* regc_cvec.c */,
+ F96D3ECD08F272A7004A47F5 /* regc_lex.c */,
+ F96D3ECE08F272A7004A47F5 /* regc_locale.c */,
+ F96D3ECF08F272A7004A47F5 /* regc_nfa.c */,
+ F96D3ED008F272A7004A47F5 /* regcomp.c */,
+ F96D3ED108F272A7004A47F5 /* regcustom.h */,
+ F96D3ED208F272A7004A47F5 /* rege_dfa.c */,
+ F96D3ED308F272A7004A47F5 /* regerror.c */,
+ F96D3ED408F272A7004A47F5 /* regerrs.h */,
+ F96D3ED508F272A7004A47F5 /* regex.h */,
+ F96D3ED608F272A7004A47F5 /* regexec.c */,
+ F96D3ED708F272A7004A47F5 /* regfree.c */,
+ F96D3ED808F272A7004A47F5 /* regfronts.c */,
+ F96D3ED908F272A7004A47F5 /* regguts.h */,
+ F96D3EDA08F272A7004A47F5 /* tcl.decls */,
+ F96D3EDB08F272A7004A47F5 /* tcl.h */,
+ F96D3EDC08F272A7004A47F5 /* tclAlloc.c */,
+ F96D3EDD08F272A7004A47F5 /* tclAsync.c */,
+ F96D3EDE08F272A7004A47F5 /* tclBasic.c */,
+ F96D3EDF08F272A7004A47F5 /* tclBinary.c */,
+ F96D3EE008F272A7004A47F5 /* tclCkalloc.c */,
+ F96D3EE108F272A7004A47F5 /* tclClock.c */,
+ F96D3EE208F272A7004A47F5 /* tclCmdAH.c */,
+ F96D3EE308F272A7004A47F5 /* tclCmdIL.c */,
+ F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */,
+ F96D3EE508F272A7004A47F5 /* tclCompCmds.c */,
+ F96D3EE608F272A7004A47F5 /* tclCompExpr.c */,
+ F96D3EE708F272A7004A47F5 /* tclCompile.c */,
+ F96D3EE808F272A7004A47F5 /* tclCompile.h */,
+ F96D3EE908F272A7004A47F5 /* tclConfig.c */,
+ F96D3EEA08F272A7004A47F5 /* tclDate.c */,
+ F96D3EEB08F272A7004A47F5 /* tclDecls.h */,
+ F96D3EEC08F272A7004A47F5 /* tclDictObj.c */,
+ F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */,
+ F96D3EED08F272A7004A47F5 /* tclEncoding.c */,
+ F96D3EEE08F272A7004A47F5 /* tclEnv.c */,
+ F96D3EEF08F272A7004A47F5 /* tclEvent.c */,
+ F96D3EF008F272A7004A47F5 /* tclExecute.c */,
+ F96D3EF108F272A7004A47F5 /* tclFCmd.c */,
+ F96D3EF208F272A7004A47F5 /* tclFileName.c */,
+ F96D3EF308F272A7004A47F5 /* tclFileSystem.h */,
+ F96D3EF408F272A7004A47F5 /* tclGet.c */,
+ F96D3EF508F272A7004A47F5 /* tclGetDate.y */,
+ F96D3EF608F272A7004A47F5 /* tclHash.c */,
+ F96D3EF708F272A7004A47F5 /* tclHistory.c */,
+ F96D3EF808F272A7004A47F5 /* tclIndexObj.c */,
+ F96D3EF908F272A7004A47F5 /* tclInt.decls */,
+ F96D3EFA08F272A7004A47F5 /* tclInt.h */,
+ F96D3EFB08F272A7004A47F5 /* tclIntDecls.h */,
+ F96D3EFC08F272A7004A47F5 /* tclInterp.c */,
+ F96D3EFD08F272A7004A47F5 /* tclIntPlatDecls.h */,
+ F96D3EFE08F272A7004A47F5 /* tclIO.c */,
+ F96D3EFF08F272A7004A47F5 /* tclIO.h */,
+ F96D3F0008F272A7004A47F5 /* tclIOCmd.c */,
+ F96D3F0108F272A7004A47F5 /* tclIOGT.c */,
+ F96D3F0208F272A7004A47F5 /* tclIORChan.c */,
+ F96D3F0308F272A7004A47F5 /* tclIOSock.c */,
+ F96D3F0408F272A7004A47F5 /* tclIOUtil.c */,
+ F96D3F0508F272A7004A47F5 /* tclLink.c */,
+ F96D3F0608F272A7004A47F5 /* tclListObj.c */,
+ F96D3F0708F272A7004A47F5 /* tclLiteral.c */,
+ F96D3F0808F272A7004A47F5 /* tclLoad.c */,
+ F96D3F0908F272A7004A47F5 /* tclLoadNone.c */,
+ F96D3F0A08F272A7004A47F5 /* tclMain.c */,
+ F96D3F0B08F272A7004A47F5 /* tclNamesp.c */,
+ F96D3F0C08F272A7004A47F5 /* tclNotify.c */,
+ F96D3F0D08F272A7004A47F5 /* tclObj.c */,
+ F96D3F0E08F272A7004A47F5 /* tclPanic.c */,
+ F96D3F0F08F272A7004A47F5 /* tclParse.c */,
+ F96D3F1108F272A7004A47F5 /* tclPathObj.c */,
+ F96D3F1208F272A7004A47F5 /* tclPipe.c */,
+ F96D3F1308F272A7004A47F5 /* tclPkg.c */,
+ F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */,
+ F96D3F1508F272A7004A47F5 /* tclPlatDecls.h */,
+ F96D3F1608F272A7004A47F5 /* tclPort.h */,
+ F96D3F1708F272A7004A47F5 /* tclPosixStr.c */,
+ F96D3F1808F272A7004A47F5 /* tclPreserve.c */,
+ F96D3F1908F272A7004A47F5 /* tclProc.c */,
+ F96D3F1A08F272A7004A47F5 /* tclRegexp.c */,
+ F96D3F1B08F272A7004A47F5 /* tclRegexp.h */,
+ F96D3F1C08F272A7004A47F5 /* tclResolve.c */,
+ F96D3F1D08F272A7004A47F5 /* tclResult.c */,
+ F96D3F1E08F272A7004A47F5 /* tclScan.c */,
+ F96D3F1F08F272A7004A47F5 /* tclStringObj.c */,
+ F96D3F2408F272A7004A47F5 /* tclStrToD.c */,
+ F96D3F2508F272A7004A47F5 /* tclStubInit.c */,
+ F96D3F2608F272A7004A47F5 /* tclStubLib.c */,
+ F96D3F2708F272A7004A47F5 /* tclTest.c */,
+ F96D3F2808F272A7004A47F5 /* tclTestObj.c */,
+ F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */,
+ F96D3F2A08F272A7004A47F5 /* tclThread.c */,
+ F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */,
+ F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */,
+ F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */,
+ F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */,
+ F96D3F2F08F272A7004A47F5 /* tclTimer.c */,
+ F9903CAF094FAADA004613E9 /* tclTomMath.decls */,
+ F96D3F3008F272A7004A47F5 /* tclTomMath.h */,
+ F9903CB0094FAADA004613E9 /* tclTomMathDecls.h */,
+ F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */,
+ F96D3F3208F272A7004A47F5 /* tclTrace.c */,
+ F96D3F3308F272A7004A47F5 /* tclUniData.c */,
+ F96D3F3408F272A7004A47F5 /* tclUtf.c */,
+ F96D3F3508F272A7004A47F5 /* tclUtil.c */,
+ F96D3F3608F272A7004A47F5 /* tclVar.c */,
+ F96D3F3708F272A7004A47F5 /* tommath.h */,
+ );
+ path = generic;
+ sourceTree = "<group>";
+ };
+ F96D3F3808F272A7004A47F5 /* library */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3F3908F272A8004A47F5 /* auto.tcl */,
+ F96D3F3A08F272A8004A47F5 /* clock.tcl */,
+ F96D3F3B08F272A8004A47F5 /* dde */,
+ F96D3F8C08F272A8004A47F5 /* history.tcl */,
+ F96D3F8D08F272A8004A47F5 /* http */,
+ F96D3F9008F272A8004A47F5 /* http1.0 */,
+ F96D3F9308F272A8004A47F5 /* init.tcl */,
+ F96D3F9408F272A8004A47F5 /* msgcat */,
+ F96D401708F272AA004A47F5 /* opt */,
+ F96D401A08F272AA004A47F5 /* package.tcl */,
+ F96D401B08F272AA004A47F5 /* parray.tcl */,
+ F9ECB1110B26521500A28025 /* platform */,
+ F96D401C08F272AA004A47F5 /* reg */,
+ F96D401E08F272AA004A47F5 /* safe.tcl */,
+ F96D401F08F272AA004A47F5 /* tclIndex */,
+ F96D402008F272AA004A47F5 /* tcltest */,
+ F96D402308F272AA004A47F5 /* tm.tcl */,
+ F96D425B08F272B2004A47F5 /* word.tcl */,
+ );
+ path = library;
+ sourceTree = "<group>";
+ };
+ F96D3F3B08F272A8004A47F5 /* dde */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3F3C08F272A8004A47F5 /* pkgIndex.tcl */,
+ );
+ path = dde;
+ sourceTree = "<group>";
+ };
+ F96D3F8D08F272A8004A47F5 /* http */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3F8E08F272A8004A47F5 /* http.tcl */,
+ F96D3F8F08F272A8004A47F5 /* pkgIndex.tcl */,
+ );
+ path = http;
+ sourceTree = "<group>";
+ };
+ F96D3F9008F272A8004A47F5 /* http1.0 */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3F9108F272A8004A47F5 /* http.tcl */,
+ F96D3F9208F272A8004A47F5 /* pkgIndex.tcl */,
+ );
+ path = http1.0;
+ sourceTree = "<group>";
+ };
+ F96D3F9408F272A8004A47F5 /* msgcat */ = {
+ isa = PBXGroup;
+ children = (
+ F96D3F9508F272A8004A47F5 /* msgcat.tcl */,
+ F96D3F9608F272A8004A47F5 /* pkgIndex.tcl */,
+ );
+ path = msgcat;
+ sourceTree = "<group>";
+ };
+ F96D401708F272AA004A47F5 /* opt */ = {
+ isa = PBXGroup;
+ children = (
+ F96D401808F272AA004A47F5 /* optparse.tcl */,
+ F96D401908F272AA004A47F5 /* pkgIndex.tcl */,
+ );
+ path = opt;
+ sourceTree = "<group>";
+ };
+ F96D401C08F272AA004A47F5 /* reg */ = {
+ isa = PBXGroup;
+ children = (
+ F96D401D08F272AA004A47F5 /* pkgIndex.tcl */,
+ );
+ path = reg;
+ sourceTree = "<group>";
+ };
+ F96D402008F272AA004A47F5 /* tcltest */ = {
+ isa = PBXGroup;
+ children = (
+ F96D402108F272AA004A47F5 /* pkgIndex.tcl */,
+ F96D402208F272AA004A47F5 /* tcltest.tcl */,
+ );
+ path = tcltest;
+ sourceTree = "<group>";
+ };
+ F96D425C08F272B2004A47F5 /* libtommath */ = {
+ isa = PBXGroup;
+ children = (
+ F96D425F08F272B3004A47F5 /* bn.pdf */,
+ F96D426108F272B3004A47F5 /* bn_error.c */,
+ F96D426208F272B3004A47F5 /* bn_fast_mp_invmod.c */,
+ F96D426308F272B3004A47F5 /* bn_fast_mp_montgomery_reduce.c */,
+ F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */,
+ F96D426508F272B3004A47F5 /* bn_fast_s_mp_mul_high_digs.c */,
+ F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */,
+ F96D426708F272B3004A47F5 /* bn_mp_2expt.c */,
+ F96D426808F272B3004A47F5 /* bn_mp_abs.c */,
+ F96D426908F272B3004A47F5 /* bn_mp_add.c */,
+ F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */,
+ F96D426B08F272B3004A47F5 /* bn_mp_addmod.c */,
+ F96D426C08F272B3004A47F5 /* bn_mp_and.c */,
+ F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */,
+ F96D426E08F272B3004A47F5 /* bn_mp_clear.c */,
+ F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */,
+ F96D427008F272B3004A47F5 /* bn_mp_cmp.c */,
+ F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */,
+ F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */,
+ F96D427308F272B3004A47F5 /* bn_mp_cnt_lsb.c */,
+ F96D427408F272B3004A47F5 /* bn_mp_copy.c */,
+ F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */,
+ F96D427608F272B3004A47F5 /* bn_mp_div.c */,
+ F96D427708F272B3004A47F5 /* bn_mp_div_2.c */,
+ F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */,
+ F96D427908F272B3004A47F5 /* bn_mp_div_3.c */,
+ F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */,
+ F96D427B08F272B3004A47F5 /* bn_mp_dr_is_modulus.c */,
+ F96D427C08F272B3004A47F5 /* bn_mp_dr_reduce.c */,
+ F96D427D08F272B3004A47F5 /* bn_mp_dr_setup.c */,
+ F96D427E08F272B3004A47F5 /* bn_mp_exch.c */,
+ F96D427F08F272B3004A47F5 /* bn_mp_expt_d.c */,
+ F96D428008F272B3004A47F5 /* bn_mp_exptmod.c */,
+ F96D428108F272B3004A47F5 /* bn_mp_exptmod_fast.c */,
+ F96D428208F272B3004A47F5 /* bn_mp_exteuclid.c */,
+ F96D428308F272B3004A47F5 /* bn_mp_fread.c */,
+ F96D428408F272B3004A47F5 /* bn_mp_fwrite.c */,
+ F96D428508F272B3004A47F5 /* bn_mp_gcd.c */,
+ F96D428608F272B3004A47F5 /* bn_mp_get_int.c */,
+ F96D428708F272B3004A47F5 /* bn_mp_grow.c */,
+ F96D428808F272B3004A47F5 /* bn_mp_init.c */,
+ F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */,
+ F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */,
+ F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */,
+ F96D428C08F272B3004A47F5 /* bn_mp_init_set_int.c */,
+ F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */,
+ F96D428E08F272B3004A47F5 /* bn_mp_invmod.c */,
+ F96D428F08F272B3004A47F5 /* bn_mp_invmod_slow.c */,
+ F96D429008F272B3004A47F5 /* bn_mp_is_square.c */,
+ F96D429108F272B3004A47F5 /* bn_mp_jacobi.c */,
+ F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */,
+ F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */,
+ F96D429408F272B3004A47F5 /* bn_mp_lcm.c */,
+ F96D429508F272B3004A47F5 /* bn_mp_lshd.c */,
+ F96D429608F272B3004A47F5 /* bn_mp_mod.c */,
+ F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */,
+ F96D429808F272B3004A47F5 /* bn_mp_mod_d.c */,
+ F96D429908F272B3004A47F5 /* bn_mp_montgomery_calc_normalization.c */,
+ F96D429A08F272B3004A47F5 /* bn_mp_montgomery_reduce.c */,
+ F96D429B08F272B3004A47F5 /* bn_mp_montgomery_setup.c */,
+ F96D429C08F272B3004A47F5 /* bn_mp_mul.c */,
+ F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */,
+ F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */,
+ F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */,
+ F96D42A008F272B3004A47F5 /* bn_mp_mulmod.c */,
+ F96D42A108F272B3004A47F5 /* bn_mp_n_root.c */,
+ F96D42A208F272B3004A47F5 /* bn_mp_neg.c */,
+ F96D42A308F272B3004A47F5 /* bn_mp_or.c */,
+ F96D42A408F272B3004A47F5 /* bn_mp_prime_fermat.c */,
+ F96D42A508F272B3004A47F5 /* bn_mp_prime_is_divisible.c */,
+ F96D42A608F272B3004A47F5 /* bn_mp_prime_is_prime.c */,
+ F96D42A708F272B3004A47F5 /* bn_mp_prime_miller_rabin.c */,
+ F96D42A808F272B3004A47F5 /* bn_mp_prime_next_prime.c */,
+ F96D42A908F272B3004A47F5 /* bn_mp_prime_rabin_miller_trials.c */,
+ F96D42AA08F272B3004A47F5 /* bn_mp_prime_random_ex.c */,
+ F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */,
+ F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */,
+ F96D42AD08F272B3004A47F5 /* bn_mp_rand.c */,
+ F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */,
+ F96D42AF08F272B3004A47F5 /* bn_mp_read_signed_bin.c */,
+ F96D42B008F272B3004A47F5 /* bn_mp_read_unsigned_bin.c */,
+ F96D42B108F272B3004A47F5 /* bn_mp_reduce.c */,
+ F96D42B208F272B3004A47F5 /* bn_mp_reduce_2k.c */,
+ F96D42B308F272B3004A47F5 /* bn_mp_reduce_2k_l.c */,
+ F96D42B408F272B3004A47F5 /* bn_mp_reduce_2k_setup.c */,
+ F96D42B508F272B3004A47F5 /* bn_mp_reduce_2k_setup_l.c */,
+ F96D42B608F272B3004A47F5 /* bn_mp_reduce_is_2k.c */,
+ F96D42B708F272B3004A47F5 /* bn_mp_reduce_is_2k_l.c */,
+ F96D42B808F272B3004A47F5 /* bn_mp_reduce_setup.c */,
+ F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */,
+ F96D42BA08F272B3004A47F5 /* bn_mp_set.c */,
+ F96D42BB08F272B3004A47F5 /* bn_mp_set_int.c */,
+ F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */,
+ F96D42BD08F272B3004A47F5 /* bn_mp_signed_bin_size.c */,
+ F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */,
+ F96D42BF08F272B3004A47F5 /* bn_mp_sqrmod.c */,
+ F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */,
+ F96D42C108F272B3004A47F5 /* bn_mp_sub.c */,
+ F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */,
+ F96D42C308F272B3004A47F5 /* bn_mp_submod.c */,
+ F96D42C408F272B3004A47F5 /* bn_mp_to_signed_bin.c */,
+ F96D42C508F272B3004A47F5 /* bn_mp_to_signed_bin_n.c */,
+ F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */,
+ F96D42C708F272B3004A47F5 /* bn_mp_to_unsigned_bin_n.c */,
+ F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */,
+ F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */,
+ F96D42CA08F272B3004A47F5 /* bn_mp_toradix.c */,
+ F96D42CB08F272B3004A47F5 /* bn_mp_toradix_n.c */,
+ F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */,
+ F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */,
+ F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */,
+ F96D42CF08F272B3004A47F5 /* bn_prime_tab.c */,
+ F96D42D008F272B3004A47F5 /* bn_reverse.c */,
+ F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */,
+ F96D42D208F272B3004A47F5 /* bn_s_mp_exptmod.c */,
+ F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */,
+ F96D42D408F272B3004A47F5 /* bn_s_mp_mul_high_digs.c */,
+ F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */,
+ F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */,
+ F96D42D708F272B3004A47F5 /* bncore.c */,
+ F96D42D908F272B3004A47F5 /* callgraph.txt */,
+ F96D42DA08F272B3004A47F5 /* changes.txt */,
+ F96D42F008F272B3004A47F5 /* LICENSE */,
+ F96D431D08F272B4004A47F5 /* poster.pdf */,
+ F96D432608F272B4004A47F5 /* tommath.pdf */,
+ F96D432908F272B4004A47F5 /* tommath_class.h */,
+ F96D432A08F272B4004A47F5 /* tommath_superclass.h */,
+ );
+ path = libtommath;
+ sourceTree = "<group>";
+ };
+ F96D432C08F272B4004A47F5 /* macosx */ = {
+ isa = PBXGroup;
+ children = (
+ F96D432E08F272B5004A47F5 /* configure.ac */,
+ F96D432F08F272B5004A47F5 /* GNUmakefile */,
+ F96D433108F272B5004A47F5 /* README */,
+ F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */,
+ F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */,
+ F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */,
+ F96D433208F272B5004A47F5 /* Tcl-Info.plist.in */,
+ F91E62260C1AE686006C9D96 /* Tclsh-Info.plist.in */,
+ F97AE7F10B65C1E900310EA2 /* Tcl-Common.xcconfig */,
+ F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */,
+ F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */,
+ );
+ path = macosx;
+ sourceTree = "<group>";
+ };
+ F96D434408F272B5004A47F5 /* tests */ = {
+ isa = PBXGroup;
+ children = (
+ F96D434508F272B5004A47F5 /* all.tcl */,
+ F96D434608F272B5004A47F5 /* append.test */,
+ F96D434708F272B5004A47F5 /* appendComp.test */,
+ F9ECB1CA0B2652D300A28025 /* apply.test */,
+ F96D434808F272B5004A47F5 /* assocd.test */,
+ F96D434908F272B5004A47F5 /* async.test */,
+ F96D434A08F272B5004A47F5 /* autoMkindex.test */,
+ F96D434B08F272B5004A47F5 /* basic.test */,
+ F96D434C08F272B5004A47F5 /* binary.test */,
+ F96D434D08F272B5004A47F5 /* case.test */,
+ F96D434E08F272B5004A47F5 /* chan.test */,
+ F9A493240CEBF38300B78AE2 /* chanio.test */,
+ F96D434F08F272B5004A47F5 /* clock.test */,
+ F96D435008F272B5004A47F5 /* cmdAH.test */,
+ F96D435108F272B5004A47F5 /* cmdIL.test */,
+ F96D435208F272B5004A47F5 /* cmdInfo.test */,
+ F96D435308F272B5004A47F5 /* cmdMZ.test */,
+ F96D435408F272B5004A47F5 /* compExpr-old.test */,
+ F96D435508F272B5004A47F5 /* compExpr.test */,
+ F96D435608F272B5004A47F5 /* compile.test */,
+ F96D435708F272B5004A47F5 /* concat.test */,
+ F96D435808F272B5004A47F5 /* config.test */,
+ F96D435908F272B5004A47F5 /* dcall.test */,
+ F96D435A08F272B5004A47F5 /* dict.test */,
+ F96D435C08F272B5004A47F5 /* dstring.test */,
+ F96D435E08F272B5004A47F5 /* encoding.test */,
+ F96D435F08F272B5004A47F5 /* env.test */,
+ F96D436008F272B5004A47F5 /* error.test */,
+ F96D436108F272B5004A47F5 /* eval.test */,
+ F96D436208F272B5004A47F5 /* event.test */,
+ F96D436308F272B5004A47F5 /* exec.test */,
+ F96D436408F272B5004A47F5 /* execute.test */,
+ F96D436508F272B5004A47F5 /* expr-old.test */,
+ F96D436608F272B5004A47F5 /* expr.test */,
+ F96D436708F272B6004A47F5 /* fCmd.test */,
+ F96D436808F272B6004A47F5 /* fileName.test */,
+ F96D436908F272B6004A47F5 /* fileSystem.test */,
+ F96D436A08F272B6004A47F5 /* for-old.test */,
+ F96D436B08F272B6004A47F5 /* for.test */,
+ F96D436C08F272B6004A47F5 /* foreach.test */,
+ F96D436D08F272B6004A47F5 /* format.test */,
+ F96D436E08F272B6004A47F5 /* get.test */,
+ F96D436F08F272B6004A47F5 /* history.test */,
+ F96D437008F272B6004A47F5 /* http.test */,
+ F96D437108F272B6004A47F5 /* httpd */,
+ F96D437208F272B6004A47F5 /* httpold.test */,
+ F96D437308F272B6004A47F5 /* if-old.test */,
+ F96D437408F272B6004A47F5 /* if.test */,
+ F96D437508F272B6004A47F5 /* incr-old.test */,
+ F96D437608F272B6004A47F5 /* incr.test */,
+ F96D437708F272B6004A47F5 /* indexObj.test */,
+ F96D437808F272B6004A47F5 /* info.test */,
+ F96D437908F272B6004A47F5 /* init.test */,
+ F96D437A08F272B6004A47F5 /* interp.test */,
+ F96D437B08F272B6004A47F5 /* io.test */,
+ F96D437C08F272B6004A47F5 /* ioCmd.test */,
+ F96D437D08F272B6004A47F5 /* iogt.test */,
+ F96D437E08F272B6004A47F5 /* ioUtil.test */,
+ F96D437F08F272B6004A47F5 /* join.test */,
+ F96D438008F272B6004A47F5 /* lindex.test */,
+ F96D438108F272B6004A47F5 /* link.test */,
+ F96D438208F272B6004A47F5 /* linsert.test */,
+ F96D438308F272B6004A47F5 /* list.test */,
+ F96D438408F272B6004A47F5 /* listObj.test */,
+ F96D438508F272B6004A47F5 /* llength.test */,
+ F96D438608F272B6004A47F5 /* load.test */,
+ F96D438708F272B6004A47F5 /* lrange.test */,
+ F96D438808F272B6004A47F5 /* lrepeat.test */,
+ F96D438908F272B6004A47F5 /* lreplace.test */,
+ F96D438A08F272B6004A47F5 /* lsearch.test */,
+ F96D438B08F272B6004A47F5 /* lset.test */,
+ F96D438C08F272B6004A47F5 /* lsetComp.test */,
+ F96D438D08F272B6004A47F5 /* macOSXFCmd.test */,
+ F95FAFF90B34F1130072E431 /* macOSXLoad.test */,
+ F96D438E08F272B6004A47F5 /* main.test */,
+ F9ECB1CB0B26534C00A28025 /* mathop.test */,
+ F96D438F08F272B6004A47F5 /* misc.test */,
+ F96D439008F272B6004A47F5 /* msgcat.test */,
+ F96D439108F272B6004A47F5 /* namespace-old.test */,
+ F96D439208F272B7004A47F5 /* namespace.test */,
+ F96D439308F272B7004A47F5 /* notify.test */,
+ F96D439408F272B7004A47F5 /* obj.test */,
+ F96D439508F272B7004A47F5 /* opt.test */,
+ F96D439608F272B7004A47F5 /* package.test */,
+ F96D439708F272B7004A47F5 /* parse.test */,
+ F96D439808F272B7004A47F5 /* parseExpr.test */,
+ F96D439908F272B7004A47F5 /* parseOld.test */,
+ F96D439A08F272B7004A47F5 /* pid.test */,
+ F96D439B08F272B7004A47F5 /* pkg.test */,
+ F96D439C08F272B7004A47F5 /* pkgMkIndex.test */,
+ F96D439D08F272B7004A47F5 /* platform.test */,
+ F96D439E08F272B7004A47F5 /* proc-old.test */,
+ F96D439F08F272B7004A47F5 /* proc.test */,
+ F96D43A008F272B7004A47F5 /* pwd.test */,
+ F96D43A108F272B7004A47F5 /* README */,
+ F96D43A208F272B7004A47F5 /* reg.test */,
+ F96D43A308F272B7004A47F5 /* regexp.test */,
+ F96D43A408F272B7004A47F5 /* regexpComp.test */,
+ F96D43A508F272B7004A47F5 /* registry.test */,
+ F96D43A608F272B7004A47F5 /* remote.tcl */,
+ F96D43A708F272B7004A47F5 /* rename.test */,
+ F96D43A808F272B7004A47F5 /* result.test */,
+ F96D43A908F272B7004A47F5 /* safe.test */,
+ F96D43AA08F272B7004A47F5 /* scan.test */,
+ F96D43AB08F272B7004A47F5 /* security.test */,
+ F96D43AC08F272B7004A47F5 /* set-old.test */,
+ F96D43AD08F272B7004A47F5 /* set.test */,
+ F96D43AE08F272B7004A47F5 /* socket.test */,
+ F96D43AF08F272B7004A47F5 /* source.test */,
+ F96D43B008F272B7004A47F5 /* split.test */,
+ F96D43B108F272B7004A47F5 /* stack.test */,
+ F96D43B208F272B7004A47F5 /* string.test */,
+ F96D43B308F272B7004A47F5 /* stringComp.test */,
+ F96D43B408F272B7004A47F5 /* stringObj.test */,
+ F96D43B508F272B7004A47F5 /* subst.test */,
+ F96D43B608F272B7004A47F5 /* switch.test */,
+ F96D43B708F272B7004A47F5 /* tcltest.test */,
+ F96D43B808F272B7004A47F5 /* thread.test */,
+ F96D43B908F272B7004A47F5 /* timer.test */,
+ F96D43BA08F272B7004A47F5 /* tm.test */,
+ F96D43BB08F272B7004A47F5 /* trace.test */,
+ F96D43BC08F272B7004A47F5 /* unixFCmd.test */,
+ F96D43BD08F272B7004A47F5 /* unixFile.test */,
+ F96D43BE08F272B7004A47F5 /* unixInit.test */,
+ F96D43BF08F272B7004A47F5 /* unixNotfy.test */,
+ F96D43C008F272B7004A47F5 /* unknown.test */,
+ F96D43C108F272B7004A47F5 /* unload.test */,
+ F96D43C208F272B7004A47F5 /* uplevel.test */,
+ F96D43C308F272B7004A47F5 /* upvar.test */,
+ F96D43C408F272B7004A47F5 /* utf.test */,
+ F96D43C508F272B7004A47F5 /* util.test */,
+ F96D43C608F272B7004A47F5 /* var.test */,
+ F96D43C708F272B7004A47F5 /* while-old.test */,
+ F96D43C808F272B7004A47F5 /* while.test */,
+ F96D43C908F272B7004A47F5 /* winConsole.test */,
+ F96D43CA08F272B7004A47F5 /* winDde.test */,
+ F96D43CB08F272B7004A47F5 /* winFCmd.test */,
+ F96D43CC08F272B7004A47F5 /* winFile.test */,
+ F96D43CD08F272B7004A47F5 /* winNotify.test */,
+ F96D43CE08F272B7004A47F5 /* winPipe.test */,
+ F96D43CF08F272B7004A47F5 /* winTime.test */,
+ );
+ path = tests;
+ sourceTree = "<group>";
+ };
+ F96D43D008F272B8004A47F5 /* tools */ = {
+ isa = PBXGroup;
+ children = (
+ F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */,
+ F96D43D208F272B8004A47F5 /* configure */,
+ F96D43D308F272B8004A47F5 /* configure.in */,
+ F96D442208F272B8004A47F5 /* eolFix.tcl */,
+ F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */,
+ F96D442508F272B8004A47F5 /* genStubs.tcl */,
+ F96D442708F272B8004A47F5 /* index.tcl */,
+ F96D442808F272B8004A47F5 /* installData.tcl */,
+ F96D442908F272B8004A47F5 /* loadICU.tcl */,
+ F96D442A08F272B8004A47F5 /* Makefile.in */,
+ F96D442B08F272B8004A47F5 /* makeTestCases.tcl */,
+ F96D442C08F272B8004A47F5 /* man2help.tcl */,
+ F96D442D08F272B8004A47F5 /* man2help2.tcl */,
+ F96D442E08F272B8004A47F5 /* man2html.tcl */,
+ F96D442F08F272B8004A47F5 /* man2html1.tcl */,
+ F96D443008F272B8004A47F5 /* man2html2.tcl */,
+ F96D443108F272B8004A47F5 /* man2tcl.c */,
+ F96D443208F272B8004A47F5 /* README */,
+ F96D443308F272B8004A47F5 /* regexpTestLib.tcl */,
+ F96D443408F272B8004A47F5 /* str2c */,
+ F96D443508F272B8004A47F5 /* tcl.hpj.in */,
+ F96D443608F272B8004A47F5 /* tcl.wse.in */,
+ F96D443708F272B9004A47F5 /* tclmin.wse */,
+ F96D443908F272B9004A47F5 /* tcltk-man2html.tcl */,
+ F96D443A08F272B9004A47F5 /* tclZIC.tcl */,
+ F96D443B08F272B9004A47F5 /* uniClass.tcl */,
+ F96D443C08F272B9004A47F5 /* uniParse.tcl */,
+ );
+ path = tools;
+ sourceTree = "<group>";
+ };
+ F96D443E08F272B9004A47F5 /* unix */ = {
+ isa = PBXGroup;
+ children = (
+ F96D444008F272B9004A47F5 /* aclocal.m4 */,
+ F96D444108F272B9004A47F5 /* configure */,
+ F96D444208F272B9004A47F5 /* configure.in */,
+ F96D444308F272B9004A47F5 /* dltest */,
+ F96D444D08F272B9004A47F5 /* install-sh */,
+ F96D444E08F272B9004A47F5 /* installManPage */,
+ F96D444F08F272B9004A47F5 /* ldAix */,
+ F96D445008F272B9004A47F5 /* Makefile.in */,
+ F96D445208F272B9004A47F5 /* README */,
+ F96D445308F272B9004A47F5 /* tcl.m4 */,
+ F96D445408F272B9004A47F5 /* tcl.spec */,
+ F96D445508F272B9004A47F5 /* tclAppInit.c */,
+ F96D445608F272B9004A47F5 /* tclConfig.h.in */,
+ F96D445708F272B9004A47F5 /* tclConfig.sh.in */,
+ F96D445808F272B9004A47F5 /* tclLoadAix.c */,
+ F96D445908F272B9004A47F5 /* tclLoadDl.c */,
+ F96D445B08F272B9004A47F5 /* tclLoadDyld.c */,
+ F96D445C08F272B9004A47F5 /* tclLoadNext.c */,
+ F96D445D08F272B9004A47F5 /* tclLoadOSF.c */,
+ F96D445E08F272B9004A47F5 /* tclLoadShl.c */,
+ F96D445F08F272B9004A47F5 /* tclUnixChan.c */,
+ F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */,
+ F96D446008F272B9004A47F5 /* tclUnixEvent.c */,
+ F96D446108F272B9004A47F5 /* tclUnixFCmd.c */,
+ F96D446208F272B9004A47F5 /* tclUnixFile.c */,
+ F96D446308F272B9004A47F5 /* tclUnixInit.c */,
+ F96D446408F272B9004A47F5 /* tclUnixNotfy.c */,
+ F96D446508F272B9004A47F5 /* tclUnixPipe.c */,
+ F96D446608F272B9004A47F5 /* tclUnixPort.h */,
+ F96D446708F272B9004A47F5 /* tclUnixSock.c */,
+ F96D446808F272B9004A47F5 /* tclUnixTest.c */,
+ F96D446908F272B9004A47F5 /* tclUnixThrd.c */,
+ F96D446A08F272B9004A47F5 /* tclUnixThrd.h */,
+ F96D446B08F272B9004A47F5 /* tclUnixTime.c */,
+ F96D446C08F272B9004A47F5 /* tclXtNotify.c */,
+ F96D446D08F272B9004A47F5 /* tclXtTest.c */,
+ );
+ path = unix;
+ sourceTree = "<group>";
+ };
+ F96D444308F272B9004A47F5 /* dltest */ = {
+ isa = PBXGroup;
+ children = (
+ F96D444408F272B9004A47F5 /* Makefile.in */,
+ F96D444508F272B9004A47F5 /* pkga.c */,
+ F96D444608F272B9004A47F5 /* pkgb.c */,
+ F96D444708F272B9004A47F5 /* pkgc.c */,
+ F96D444808F272B9004A47F5 /* pkgd.c */,
+ F96D444908F272B9004A47F5 /* pkge.c */,
+ F96D444B08F272B9004A47F5 /* pkgua.c */,
+ F96D444C08F272B9004A47F5 /* README */,
+ );
+ path = dltest;
+ sourceTree = "<group>";
+ };
+ F96D446E08F272B9004A47F5 /* win */ = {
+ isa = PBXGroup;
+ children = (
+ F96D447008F272BA004A47F5 /* aclocal.m4 */,
+ F96D447108F272BA004A47F5 /* buildall.vc.bat */,
+ F96D447208F272BA004A47F5 /* cat.c */,
+ F96D447308F272BA004A47F5 /* coffbase.txt */,
+ F96D447408F272BA004A47F5 /* configure */,
+ F96D447508F272BA004A47F5 /* configure.in */,
+ F96D447608F272BA004A47F5 /* makefile.bc */,
+ F96D447708F272BA004A47F5 /* Makefile.in */,
+ F96D447808F272BA004A47F5 /* makefile.vc */,
+ F96D447908F272BA004A47F5 /* nmakehlp.c */,
+ F96D447A08F272BA004A47F5 /* README */,
+ F96D447C08F272BA004A47F5 /* rules.vc */,
+ F96D447D08F272BA004A47F5 /* stub16.c */,
+ F96D447E08F272BA004A47F5 /* tcl.dsp */,
+ F96D447F08F272BA004A47F5 /* tcl.dsw */,
+ F96D448008F272BA004A47F5 /* tcl.hpj.in */,
+ F96D448108F272BA004A47F5 /* tcl.m4 */,
+ F96D448208F272BA004A47F5 /* tcl.rc */,
+ F96D448308F272BA004A47F5 /* tclAppInit.c */,
+ F96D448408F272BA004A47F5 /* tclConfig.sh.in */,
+ F96D448608F272BA004A47F5 /* tclsh.rc */,
+ F96D448708F272BA004A47F5 /* tclWin32Dll.c */,
+ F96D448808F272BA004A47F5 /* tclWinChan.c */,
+ F96D448908F272BA004A47F5 /* tclWinConsole.c */,
+ F96D448A08F272BA004A47F5 /* tclWinDde.c */,
+ F96D448B08F272BA004A47F5 /* tclWinError.c */,
+ F96D448C08F272BA004A47F5 /* tclWinFCmd.c */,
+ F96D448D08F272BA004A47F5 /* tclWinFile.c */,
+ F96D448E08F272BA004A47F5 /* tclWinInit.c */,
+ F96D448F08F272BA004A47F5 /* tclWinInt.h */,
+ F96D449008F272BA004A47F5 /* tclWinLoad.c */,
+ F96D449108F272BA004A47F5 /* tclWinNotify.c */,
+ F96D449208F272BA004A47F5 /* tclWinPipe.c */,
+ F96D449308F272BA004A47F5 /* tclWinPort.h */,
+ F96D449408F272BA004A47F5 /* tclWinReg.c */,
+ F96D449508F272BA004A47F5 /* tclWinSerial.c */,
+ F96D449608F272BA004A47F5 /* tclWinSock.c */,
+ F96D449708F272BA004A47F5 /* tclWinTest.c */,
+ F96D449808F272BA004A47F5 /* tclWinThrd.c */,
+ F96D449908F272BA004A47F5 /* tclWinThrd.h */,
+ F96D449A08F272BA004A47F5 /* tclWinTime.c */,
+ );
+ path = win;
+ sourceTree = "<group>";
+ };
+ F9ECB1110B26521500A28025 /* platform */ = {
+ isa = PBXGroup;
+ children = (
+ F9ECB1120B26521500A28025 /* pkgIndex.tcl */,
+ F9ECB1130B26521500A28025 /* platform.tcl */,
+ F9ECB1140B26521500A28025 /* shell.tcl */,
+ );
+ path = platform;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8DD76FA90486AB0100D96B5E /* tcltest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F95CC8B009158F3100EA5ACE /* Build configuration list for PBXNativeTarget "tcltest" */;
+ buildPhases = (
+ F9A5C5F508F651A2008AE941 /* ShellScript */,
+ 8DD76FAB0486AB0100D96B5E /* Sources */,
+ 8DD76FAD0486AB0100D96B5E /* Frameworks */,
+ F95FA74C0B32CE190072E431 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = tcltest;
+ productInstallPath = "$(BINDIR)";
+ productName = tcltest;
+ productReference = 8DD76FB20486AB0100D96B5E /* tcltest */;
+ productType = "com.apple.product-type.tool";
+ };
+ F97258A50A86873C00096C78 /* tests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F97258A80A86873D00096C78 /* Build configuration list for PBXNativeTarget "tests" */;
+ buildPhases = (
+ F97258A40A86873C00096C78 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ F97258D30A868C6F00096C78 /* PBXTargetDependency */,
+ );
+ name = tests;
+ productName = tests;
+ productType = "com.apple.product-type.bundle";
+ };
+ F9E61D16090A3E94002B3151 /* Tcl */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F95CC8AB09158F3100EA5ACE /* Build configuration list for PBXNativeTarget "Tcl" */;
+ buildPhases = (
+ F97AF02F0B665DA900310EA2 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Tcl;
+ productName = tclsh;
+ productReference = F9A3084B08F2D4CE00BAE1AB /* tclsh */;
+ productType = "com.apple.product-type.tool";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ BuildIndependentTargetsInParallel = YES;
+ };
+ buildConfigurationList = F95CC8B509158F3100EA5ACE /* Build configuration list for PBXProject "Tcl" */;
+ compatibilityVersion = "Xcode 3.1";
+ hasScannedForEncodings = 1;
+ mainGroup = 08FB7794FE84155DC02AAC07 /* Tcl */;
+ projectDirPath = "";
+ projectRoot = ..;
+ targets = (
+ F9E61D16090A3E94002B3151 /* Tcl */,
+ 8DD76FA90486AB0100D96B5E /* tcltest */,
+ F97258A50A86873C00096C78 /* tests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ F95FA74C0B32CE190072E431 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(DERIVED_FILE_DIR)/tcl/tclConfig.sh",
+ "$(TCL_SRCROOT)/generic/tclStubLib.c",
+ "$(TCL_SRCROOT)/unix/dltest/pkga.c",
+ "$(TCL_SRCROOT)/unix/dltest/pkgb.c",
+ "$(TCL_SRCROOT)/unix/dltest/pkgc.c",
+ "$(TCL_SRCROOT)/unix/dltest/pkgd.c",
+ "$(TCL_SRCROOT)/unix/dltest/pkge.c",
+ "$(TCL_SRCROOT)/unix/dltest/pkgua.c",
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/tcl/dltest.marker",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "## dltest build script phase\n\nrm -f \"${DERIVED_FILE_DIR}/tcl/dltest.marker\"\nmake -C \"${DERIVED_FILE_DIR}/tcl\" dltest.marker\nln -fsh \"${DERIVED_FILE_DIR}/tcl/dltest\" \"${CONFIGURATION_BUILD_DIR}\"\n";
+ showEnvVarsInLog = 0;
+ };
+ F97258A40A86873C00096C78 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "if [ \"${ACTION:-build}\" == \"build\" ]; then\nif [ -z \"${HOME}\" ]; then export HOME=\"$(echo ~)\"; fi\ncd \"${TARGET_TEMP_DIR}\"; rm -rf \"${DERIVED_FILE_DIR}\"; mkdir -p \"${DERIVED_FILE_DIR}\"\nprintf '%s%s%s%s%s' '\npackage require tcltest 2.2\nnamespace import tcltest::*\nconfigure -testdir [file normalize {' \"${TCL_SRCROOT}\" '/tests}]\nconfigure -tmpdir [file normalize {' \"${DERIVED_FILE_DIR}\" '}]\nconfigure -verbose [concat [configure -verbose] line]\n# following test only fails when testsuite is run from inside Xcode, so skip it\nconfigure -skip [concat [configure -skip] stack-3.1]\nrunAllTests\n' | \"${TEST_RIG}\"; TEST_RIG_RESULT=$?\n[ ${TEST_RIG_RESULT} -ne 0 ] && echo \"tcltest:0: error: tcltest exited abnormally with code ${TEST_RIG_RESULT}.\"\nexit ${TEST_RIG_RESULT}\nfi";
+ showEnvVarsInLog = 0;
+ };
+ F97AF02F0B665DA900310EA2 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "${TARGET_TEMP_DIR}/.none",
+ );
+ outputPaths = (
+ "${TARGET_BUILD_DIR}/${EXECUTABLE_NAME}",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "if [ -e \"${TARGET_BUILD_DIR}/tclsh\" ]; then\n mv -f \"${TARGET_BUILD_DIR}/tclsh\" \"${TARGET_BUILD_DIR}/tclsh${VERSION}\"\nfi\ngnumake -C \"${TCL_SRCROOT}/macosx\" -j \"$(sysctl -n hw.activecpu)\" \"$(echo \"${ACTION}\" | sed -e s/build// -e s/clean/distclean/ -e s/..\\*/\\&-/)${MAKE_TARGET}\" CFLAGS_WARNING=\"${WARNING_CFLAGS}\" CFLAGS_OPTIMIZE=\"-O${GCC_OPTIMIZATION_LEVEL}\" SYMROOT=\"${BUILT_PRODUCTS_DIR}\" OBJ_DIR=\"${OBJECT_FILE_DIR}\" INSTALL_ROOT=\"${DSTROOT}\" PREFIX=\"${PREFIX}\" BINDIR=\"${BINDIR}\" LIBDIR=\"${FRAMEWORK_INSTALL_PATH}\" MANDIR=\"${MANDIR}\" EXTRA_CONFIGURE_ARGS=\"${CONFIGURE_ARGS}\" ${EXTRA_MAKE_FLAGS}\nresult=$?\nif [ -e \"${TARGET_BUILD_DIR}/tclsh${VERSION}\" ]; then\n mv -f \"${TARGET_BUILD_DIR}/tclsh${VERSION}\" \"${TARGET_BUILD_DIR}/tclsh\"\nfi\nif [ -e \"${BUILT_PRODUCTS_DIR}/tcltest\" ]; then\n\trm -f \"${BUILT_PRODUCTS_DIR}/tcltest\"\nfi\necho \"Done\"\nrm -f \"${SCRIPT_INPUT_FILE_0}\"\nexit ${result}\n";
+ showEnvVarsInLog = 0;
+ };
+ F9A5C5F508F651A2008AE941 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(TCL_SRCROOT)/macosx/configure.ac",
+ "$(TCL_SRCROOT)/unix/configure.in",
+ "$(TCL_SRCROOT)/unix/tcl.m4",
+ "$(TCL_SRCROOT)/unix/aclocal.m4",
+ "$(TCL_SRCROOT)/unix/tclConfig.sh.in",
+ "$(TCL_SRCROOT)/unix/Makefile.in",
+ "$(TCL_SRCROOT)/unix/dltest/Makefile.in",
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/tcl/tclConfig.sh",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tcl/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tcl\"\n \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8DD76FAB0486AB0100D96B5E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F96D456F08F272BB004A47F5 /* regcomp.c in Sources */,
+ F96D457208F272BB004A47F5 /* regerror.c in Sources */,
+ F96D457508F272BB004A47F5 /* regexec.c in Sources */,
+ F96D457608F272BB004A47F5 /* regfree.c in Sources */,
+ F96D457B08F272BB004A47F5 /* tclAlloc.c in Sources */,
+ F96D457C08F272BB004A47F5 /* tclAsync.c in Sources */,
+ F96D457D08F272BB004A47F5 /* tclBasic.c in Sources */,
+ F96D457E08F272BC004A47F5 /* tclBinary.c in Sources */,
+ F96D457F08F272BC004A47F5 /* tclCkalloc.c in Sources */,
+ F96D458008F272BC004A47F5 /* tclClock.c in Sources */,
+ F96D458108F272BC004A47F5 /* tclCmdAH.c in Sources */,
+ F96D458208F272BC004A47F5 /* tclCmdIL.c in Sources */,
+ F96D458308F272BC004A47F5 /* tclCmdMZ.c in Sources */,
+ F96D458408F272BC004A47F5 /* tclCompCmds.c in Sources */,
+ F96D458508F272BC004A47F5 /* tclCompExpr.c in Sources */,
+ F96D458608F272BC004A47F5 /* tclCompile.c in Sources */,
+ F96D458808F272BC004A47F5 /* tclConfig.c in Sources */,
+ F96D458908F272BC004A47F5 /* tclDate.c in Sources */,
+ F96D458B08F272BC004A47F5 /* tclDictObj.c in Sources */,
+ F96D458C08F272BC004A47F5 /* tclEncoding.c in Sources */,
+ F96D458D08F272BC004A47F5 /* tclEnv.c in Sources */,
+ F96D458E08F272BC004A47F5 /* tclEvent.c in Sources */,
+ F96D458F08F272BC004A47F5 /* tclExecute.c in Sources */,
+ F96D459008F272BC004A47F5 /* tclFCmd.c in Sources */,
+ F96D459108F272BC004A47F5 /* tclFileName.c in Sources */,
+ F96D459308F272BC004A47F5 /* tclGet.c in Sources */,
+ F96D459508F272BC004A47F5 /* tclHash.c in Sources */,
+ F96D459608F272BC004A47F5 /* tclHistory.c in Sources */,
+ F96D459708F272BC004A47F5 /* tclIndexObj.c in Sources */,
+ F96D459B08F272BC004A47F5 /* tclInterp.c in Sources */,
+ F96D459D08F272BC004A47F5 /* tclIO.c in Sources */,
+ F96D459F08F272BC004A47F5 /* tclIOCmd.c in Sources */,
+ F96D45A008F272BC004A47F5 /* tclIOGT.c in Sources */,
+ F96D45A108F272BC004A47F5 /* tclIORChan.c in Sources */,
+ F96D45A208F272BC004A47F5 /* tclIOSock.c in Sources */,
+ F96D45A308F272BC004A47F5 /* tclIOUtil.c in Sources */,
+ F96D45A408F272BC004A47F5 /* tclLink.c in Sources */,
+ F96D45A508F272BC004A47F5 /* tclListObj.c in Sources */,
+ F96D45A608F272BC004A47F5 /* tclLiteral.c in Sources */,
+ F96D45A708F272BC004A47F5 /* tclLoad.c in Sources */,
+ F96D45A908F272BC004A47F5 /* tclMain.c in Sources */,
+ F96D45AA08F272BC004A47F5 /* tclNamesp.c in Sources */,
+ F96D45AB08F272BC004A47F5 /* tclNotify.c in Sources */,
+ F96D45AC08F272BC004A47F5 /* tclObj.c in Sources */,
+ F96D45AD08F272BC004A47F5 /* tclPanic.c in Sources */,
+ F96D45AE08F272BC004A47F5 /* tclParse.c in Sources */,
+ F96D45B008F272BC004A47F5 /* tclPathObj.c in Sources */,
+ F96D45B108F272BC004A47F5 /* tclPipe.c in Sources */,
+ F96D45B208F272BC004A47F5 /* tclPkg.c in Sources */,
+ F96D45B308F272BC004A47F5 /* tclPkgConfig.c in Sources */,
+ F96D45B608F272BC004A47F5 /* tclPosixStr.c in Sources */,
+ F96D45B708F272BC004A47F5 /* tclPreserve.c in Sources */,
+ F96D45B808F272BC004A47F5 /* tclProc.c in Sources */,
+ F96D45B908F272BC004A47F5 /* tclRegexp.c in Sources */,
+ F96D45BB08F272BC004A47F5 /* tclResolve.c in Sources */,
+ F96D45BC08F272BC004A47F5 /* tclResult.c in Sources */,
+ F96D45BD08F272BC004A47F5 /* tclScan.c in Sources */,
+ F96D45BE08F272BC004A47F5 /* tclStringObj.c in Sources */,
+ F96D45C308F272BC004A47F5 /* tclStrToD.c in Sources */,
+ F96D45C408F272BC004A47F5 /* tclStubInit.c in Sources */,
+ F96D45C508F272BC004A47F5 /* tclStubLib.c in Sources */,
+ F96D45C608F272BC004A47F5 /* tclTest.c in Sources */,
+ F96D45C708F272BC004A47F5 /* tclTestObj.c in Sources */,
+ F96D45C808F272BC004A47F5 /* tclTestProcBodyObj.c in Sources */,
+ F96D45C908F272BC004A47F5 /* tclThread.c in Sources */,
+ F96D45CA08F272BC004A47F5 /* tclThreadAlloc.c in Sources */,
+ F96D45CB08F272BC004A47F5 /* tclThreadJoin.c in Sources */,
+ F96D45CC08F272BC004A47F5 /* tclThreadStorage.c in Sources */,
+ F96D45CD08F272BC004A47F5 /* tclThreadTest.c in Sources */,
+ F96D45CE08F272BC004A47F5 /* tclTimer.c in Sources */,
+ F96D45D008F272BC004A47F5 /* tclTomMathInterface.c in Sources */,
+ F96D45D108F272BC004A47F5 /* tclTrace.c in Sources */,
+ F96D45D308F272BC004A47F5 /* tclUtf.c in Sources */,
+ F96D45D408F272BC004A47F5 /* tclUtil.c in Sources */,
+ F96D45D508F272BC004A47F5 /* tclVar.c in Sources */,
+ F96D48E208F272C3004A47F5 /* bn_fast_s_mp_mul_digs.c in Sources */,
+ F96D48E408F272C3004A47F5 /* bn_fast_s_mp_sqr.c in Sources */,
+ F96D48E708F272C3004A47F5 /* bn_mp_add.c in Sources */,
+ F96D48E808F272C3004A47F5 /* bn_mp_add_d.c in Sources */,
+ F9E61D2B090A48A4002B3151 /* bn_mp_and.c in Sources */,
+ F96D48EB08F272C3004A47F5 /* bn_mp_clamp.c in Sources */,
+ F96D48EC08F272C3004A47F5 /* bn_mp_clear.c in Sources */,
+ F96D48ED08F272C3004A47F5 /* bn_mp_clear_multi.c in Sources */,
+ F96D48EE08F272C3004A47F5 /* bn_mp_cmp.c in Sources */,
+ F9E61D28090A481F002B3151 /* bn_mp_cmp_d.c in Sources */,
+ F96D48F008F272C3004A47F5 /* bn_mp_cmp_mag.c in Sources */,
+ F96D48F208F272C3004A47F5 /* bn_mp_cnt_lsb.c in Sources */,
+ F96D48F208F272C3004A47F5 /* bn_mp_copy.c in Sources */,
+ F96D48F308F272C3004A47F5 /* bn_mp_count_bits.c in Sources */,
+ F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */,
+ F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */,
+ F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */,
+ F96D48F708F272C3004A47F5 /* bn_mp_div_3.c in Sources */,
+ F96D48F808F272C3004A47F5 /* bn_mp_div_d.c in Sources */,
+ F96D48FC08F272C3004A47F5 /* bn_mp_exch.c in Sources */,
+ F9E61D2C090A48AC002B3151 /* bn_mp_expt_d.c in Sources */,
+ F96D490508F272C3004A47F5 /* bn_mp_grow.c in Sources */,
+ F96D490608F272C3004A47F5 /* bn_mp_init.c in Sources */,
+ F96D490708F272C3004A47F5 /* bn_mp_init_copy.c in Sources */,
+ F96D490808F272C3004A47F5 /* bn_mp_init_multi.c in Sources */,
+ F96D490908F272C3004A47F5 /* bn_mp_init_set.c in Sources */,
+ F96D490B08F272C3004A47F5 /* bn_mp_init_size.c in Sources */,
+ F96D491008F272C3004A47F5 /* bn_mp_karatsuba_mul.c in Sources */,
+ F96D491108F272C3004A47F5 /* bn_mp_karatsuba_sqr.c in Sources */,
+ F96D491308F272C3004A47F5 /* bn_mp_lshd.c in Sources */,
+ F96D491408F272C3004A47F5 /* bn_mp_mod.c in Sources */,
+ F96D491508F272C3004A47F5 /* bn_mp_mod_2d.c in Sources */,
+ F96D491A08F272C3004A47F5 /* bn_mp_mul.c in Sources */,
+ F96D491B08F272C3004A47F5 /* bn_mp_mul_2.c in Sources */,
+ F96D491C08F272C3004A47F5 /* bn_mp_mul_2d.c in Sources */,
+ F96D491D08F272C3004A47F5 /* bn_mp_mul_d.c in Sources */,
+ F9E61D29090A486C002B3151 /* bn_mp_neg.c in Sources */,
+ F9E61D2E090A48BF002B3151 /* bn_mp_or.c in Sources */,
+ F96D492908F272C3004A47F5 /* bn_mp_radix_size.c in Sources */,
+ F96D492A08F272C3004A47F5 /* bn_mp_radix_smap.c in Sources */,
+ F96D492C08F272C3004A47F5 /* bn_mp_read_radix.c in Sources */,
+ F96D493708F272C3004A47F5 /* bn_mp_rshd.c in Sources */,
+ F96D493808F272C3004A47F5 /* bn_mp_set.c in Sources */,
+ F9E61D2F090A48C7002B3151 /* bn_mp_shrink.c in Sources */,
+ F96D493C08F272C3004A47F5 /* bn_mp_sqr.c in Sources */,
+ F9E61D2A090A4891002B3151 /* bn_mp_sqrt.c in Sources */,
+ F96D493F08F272C3004A47F5 /* bn_mp_sub.c in Sources */,
+ F96D494008F272C3004A47F5 /* bn_mp_sub_d.c in Sources */,
+ F9E61D30090A48E2002B3151 /* bn_mp_to_unsigned_bin_n.c in Sources */,
+ F9E61D31090A48F9002B3151 /* bn_mp_to_unsigned_bin.c in Sources */,
+ F96D494608F272C3004A47F5 /* bn_mp_toom_mul.c in Sources */,
+ F96D494708F272C3004A47F5 /* bn_mp_toom_sqr.c in Sources */,
+ F96D494908F272C3004A47F5 /* bn_mp_toradix_n.c in Sources */,
+ F9E61D32090A48FA002B3151 /* bn_mp_unsigned_bin_size.c in Sources */,
+ F9E61D2D090A48BB002B3151 /* bn_mp_xor.c in Sources */,
+ F96D494C08F272C3004A47F5 /* bn_mp_zero.c in Sources */,
+ F96D494E08F272C3004A47F5 /* bn_reverse.c in Sources */,
+ F96D494F08F272C3004A47F5 /* bn_s_mp_add.c in Sources */,
+ F96D495108F272C3004A47F5 /* bn_s_mp_mul_digs.c in Sources */,
+ F96D495308F272C3004A47F5 /* bn_s_mp_sqr.c in Sources */,
+ F96D495408F272C3004A47F5 /* bn_s_mp_sub.c in Sources */,
+ F96D495508F272C3004A47F5 /* bncore.c in Sources */,
+ F96D49A908F272C4004A47F5 /* tclMacOSXBundle.c in Sources */,
+ F96D49AD08F272C4004A47F5 /* tclMacOSXFCmd.c in Sources */,
+ F96D49AE08F272C4004A47F5 /* tclMacOSXNotify.c in Sources */,
+ F90509300913A72400327603 /* tclAppInit.c in Sources */,
+ F96D4AC608F272C9004A47F5 /* tclLoadDyld.c in Sources */,
+ F96D4ACA08F272C9004A47F5 /* tclUnixChan.c in Sources */,
+ F9FC77B80AB29E9100B7077D /* tclUnixCompat.c in Sources */,
+ F96D4ACB08F272C9004A47F5 /* tclUnixEvent.c in Sources */,
+ F96D4ACC08F272C9004A47F5 /* tclUnixFCmd.c in Sources */,
+ F96D4ACD08F272C9004A47F5 /* tclUnixFile.c in Sources */,
+ F96D4ACE08F272C9004A47F5 /* tclUnixInit.c in Sources */,
+ F96D4ACF08F272C9004A47F5 /* tclUnixNotfy.c in Sources */,
+ F96D4AD008F272C9004A47F5 /* tclUnixPipe.c in Sources */,
+ F96D4AD208F272CA004A47F5 /* tclUnixSock.c in Sources */,
+ F96D4AD308F272CA004A47F5 /* tclUnixTest.c in Sources */,
+ F96D4AD408F272CA004A47F5 /* tclUnixThrd.c in Sources */,
+ F96D4AD608F272CA004A47F5 /* tclUnixTime.c in Sources */,
+ F9F4415E0C8BAE6F00BCCD67 /* tclDTrace.d in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ F97258D30A868C6F00096C78 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 8DD76FA90486AB0100D96B5E /* tcltest */;
+ targetProxy = F97258D20A868C6F00096C78 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ F91BCC4F093152310042A6BF /* ReleaseUniversal */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = ReleaseUniversal;
+ };
+ F91BCC50093152310042A6BF /* ReleaseUniversal */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = ReleaseUniversal;
+ };
+ F91BCC51093152310042A6BF /* ReleaseUniversal */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc -arch ppc64 $(CFLAGS)";
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ PREBINDING = NO;
+ };
+ name = ReleaseUniversal;
+ };
+ F93084370BB93D2800CD0B9E /* DebugMemCompile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugMemCompile;
+ };
+ F93084380BB93D2800CD0B9E /* DebugMemCompile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = DebugMemCompile;
+ };
+ F93084390BB93D2800CD0B9E /* DebugMemCompile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "";
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = DebugMemCompile;
+ };
+ F930843A0BB93D2800CD0B9E /* DebugMemCompile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
+ buildSettings = {
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --enable-symbols=all";
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ PREBINDING = NO;
+ };
+ name = DebugMemCompile;
+ };
+ F9359B250DF212DA00E04F67 /* DebugGCov */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
+ buildSettings = {
+ GCC_GENERATE_TEST_COVERAGE_FILES = YES;
+ GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ OTHER_LDFLAGS = (
+ "$(OTHER_LDFLAGS)",
+ "-lgcov",
+ );
+ PREBINDING = NO;
+ };
+ name = DebugGCov;
+ };
+ F9359B260DF212DA00E04F67 /* DebugGCov */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugGCov;
+ };
+ F9359B270DF212DA00E04F67 /* DebugGCov */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = DebugGCov;
+ };
+ F9359B280DF212DA00E04F67 /* DebugGCov */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "";
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "-notfile http.test";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = DebugGCov;
+ };
+ F95CC8AC09158F3100EA5ACE /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = Debug;
+ };
+ F95CC8AD09158F3100EA5ACE /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = Release;
+ };
+ F95CC8AE09158F3100EA5ACE /* DebugNoFixZL */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugNoFixZL;
+ };
+ F95CC8B109158F3100EA5ACE /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__private_extern__=extern",
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ PRODUCT_NAME = tcltest;
+ };
+ name = Debug;
+ };
+ F95CC8B209158F3100EA5ACE /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = Release;
+ };
+ F95CC8B309158F3100EA5ACE /* DebugNoFixZL */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = DebugNoFixZL;
+ };
+ F95CC8B609158F3100EA5ACE /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
+ buildSettings = {
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ PREBINDING = NO;
+ };
+ name = Debug;
+ };
+ F95CC8B709158F3100EA5ACE /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
+ buildSettings = {
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ PREBINDING = NO;
+ };
+ name = Release;
+ };
+ F95CC8B809158F3100EA5ACE /* DebugNoFixZL */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
+ buildSettings = {
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ PREBINDING = NO;
+ };
+ name = DebugNoFixZL;
+ };
+ F97258A90A86873D00096C78 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "";
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = Debug;
+ };
+ F97258AA0A86873D00096C78 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "";
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = Release;
+ };
+ F97258AB0A86873D00096C78 /* DebugNoFixZL */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "";
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = DebugNoFixZL;
+ };
+ F97258AC0A86873D00096C78 /* ReleaseUniversal */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "";
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = ReleaseUniversal;
+ };
+ F97AED080B660A6C00310EA2 /* ReleaseUniversal10.4uSDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "";
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = ReleaseUniversal10.4uSDK;
+ };
+ F97AED0F0B660AA300310EA2 /* ReleasePPC10.3.9SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "";
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = ReleasePPC10.3.9SDK;
+ };
+ F97AED160B660AF100310EA2 /* ReleasePPC10.2.8SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "";
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = ReleasePPC10.2.8SDK;
+ };
+ F97AED1B0B660B2100310EA2 /* Debug64bit */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = Debug64bit;
+ };
+ F97AED1C0B660B2100310EA2 /* Debug64bit */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = Debug64bit;
+ };
+ F97AED1D0B660B2100310EA2 /* Debug64bit */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "";
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = Debug64bit;
+ };
+ F97AED1E0B660B2100310EA2 /* Debug64bit */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(NATIVE_ARCH_64_BIT)";
+ CONFIGURE_ARGS = "--enable-64bit $(CONFIGURE_ARGS)";
+ CPPFLAGS = "-arch $(NATIVE_ARCH_64_BIT) $(CPPFLAGS)";
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ PREBINDING = NO;
+ };
+ name = Debug64bit;
+ };
+ F987512F0DE7B57E00B1C9EC /* DebugNoCF */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
+ buildSettings = {
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-corefoundation";
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ PREBINDING = NO;
+ };
+ name = DebugNoCF;
+ };
+ F98751300DE7B57E00B1C9EC /* DebugNoCF */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugNoCF;
+ };
+ F98751310DE7B57E00B1C9EC /* DebugNoCF */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = DebugNoCF;
+ };
+ F98751320DE7B57E00B1C9EC /* DebugNoCF */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "";
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = DebugNoCF;
+ };
+ F98751330DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
+ buildSettings = {
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-threads --disable-corefoundation";
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ PREBINDING = NO;
+ };
+ name = DebugNoCFUnthreaded;
+ };
+ F98751340DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugNoCFUnthreaded;
+ };
+ F98751350DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = DebugNoCFUnthreaded;
+ };
+ F98751360DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "";
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = DebugNoCFUnthreaded;
+ };
+ F9988AB10D814C6500B6B03B /* Debug gcc42 */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
+ buildSettings = {
+ GCC_VERSION = 4.2;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ PREBINDING = NO;
+ };
+ name = "Debug gcc42";
+ };
+ F9988AB20D814C6500B6B03B /* Debug gcc42 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = "Debug gcc42";
+ };
+ F9988AB30D814C6500B6B03B /* Debug gcc42 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__private_extern__=extern",
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ PRODUCT_NAME = tcltest;
+ };
+ name = "Debug gcc42";
+ };
+ F9988AB40D814C6500B6B03B /* Debug gcc42 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "";
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = "Debug gcc42";
+ };
+ F9988AB50D814C7500B6B03B /* Debug llvmgcc42 */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
+ buildSettings = {
+ CC = "$(DEVELOPER_DIR)/usr/bin/llvm-gcc-4.2";
+ GCC_VERSION = com.apple.compilers.llvmgcc42;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ PREBINDING = NO;
+ };
+ name = "Debug llvmgcc42";
+ };
+ F9988AB60D814C7500B6B03B /* Debug llvmgcc42 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = "Debug llvmgcc42";
+ };
+ F9988AB70D814C7500B6B03B /* Debug llvmgcc42 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__private_extern__=extern",
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ PRODUCT_NAME = tcltest;
+ };
+ name = "Debug llvmgcc42";
+ };
+ F9988AB80D814C7500B6B03B /* Debug llvmgcc42 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "";
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = "Debug llvmgcc42";
+ };
+ F9988BB10D81586D00B6B03B /* ReleaseUniversal gcc42 */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc -arch ppc64 $(CFLAGS)";
+ GCC_VERSION = 4.2;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ PREBINDING = NO;
+ };
+ name = "ReleaseUniversal gcc42";
+ };
+ F9988BB20D81586D00B6B03B /* ReleaseUniversal gcc42 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = "ReleaseUniversal gcc42";
+ };
+ F9988BB30D81586D00B6B03B /* ReleaseUniversal gcc42 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = "ReleaseUniversal gcc42";
+ };
+ F9988BB40D81586D00B6B03B /* ReleaseUniversal gcc42 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "";
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = "ReleaseUniversal gcc42";
+ };
+ F9988BB50D81587400B6B03B /* ReleaseUniversal llvmgcc42 */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CC = "$(DEVELOPER_DIR)/usr/bin/llvm-gcc-4.2";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc -arch ppc64 $(CFLAGS)";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ GCC_OPTIMIZATION_LEVEL = 4;
+ GCC_VERSION = com.apple.compilers.llvmgcc42;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ OTHER_CFLAGS = (
+ "$(OTHER_CFLAGS)",
+ "-emit-llvm",
+ );
+ PREBINDING = NO;
+ TCL_CONFIGURE_ARGS = "$(TCL_CONFIGURE_ARGS) --disable-dtrace";
+ };
+ name = "ReleaseUniversal llvmgcc42";
+ };
+ F9988BB60D81587400B6B03B /* ReleaseUniversal llvmgcc42 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = "ReleaseUniversal llvmgcc42";
+ };
+ F9988BB70D81587400B6B03B /* ReleaseUniversal llvmgcc42 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = "ReleaseUniversal llvmgcc42";
+ };
+ F9988BB80D81587400B6B03B /* ReleaseUniversal llvmgcc42 */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "";
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = "ReleaseUniversal llvmgcc42";
+ };
+ F99EE73B0BE835310060D4AF /* DebugUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugUnthreaded;
+ };
+ F99EE73C0BE835310060D4AF /* DebugLeaks */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = DebugLeaks;
+ };
+ F99EE73D0BE835310060D4AF /* DebugUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = DebugUnthreaded;
+ };
+ F99EE73E0BE835310060D4AF /* DebugLeaks */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = DebugLeaks;
+ };
+ F99EE73F0BE835310060D4AF /* DebugUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "";
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = DebugUnthreaded;
+ };
+ F99EE7400BE835310060D4AF /* DebugLeaks */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "";
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = DebugLeaks;
+ };
+ F99EE7410BE835310060D4AF /* DebugUnthreaded */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
+ buildSettings = {
+ CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-threads";
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ PREBINDING = NO;
+ };
+ name = DebugUnthreaded;
+ };
+ F99EE7420BE835310060D4AF /* DebugLeaks */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
+ buildSettings = {
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ PURIFY,
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ );
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ PREBINDING = NO;
+ };
+ name = DebugLeaks;
+ };
+ F9DB62080B65ADA800A370FB /* ReleaseUniversal10.4uSDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = ReleaseUniversal10.4uSDK;
+ };
+ F9DB62090B65ADA800A370FB /* ReleaseUniversal10.4uSDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = ReleaseUniversal10.4uSDK;
+ };
+ F9DB620A0B65ADA800A370FB /* ReleaseUniversal10.4uSDK */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc -arch ppc64 $(CFLAGS)";
+ CPPFLAGS = "-isysroot $(SDKROOT) $(CPPFLAGS)";
+ MACOSX_DEPLOYMENT_TARGET = 10.4;
+ OTHER_LDFLAGS = (
+ "-Wl,-no_arch_warnings",
+ "$(OTHER_LDFLAGS)",
+ );
+ PREBINDING = NO;
+ SDKROOT = macosx10.4;
+ };
+ name = ReleaseUniversal10.4uSDK;
+ };
+ F9DB621F0B65AFDE00A370FB /* ReleasePPC10.3.9SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ LDFLAGS = "-force_cpusubtype_ALL $(LDFLAGS)";
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = ReleasePPC10.3.9SDK;
+ };
+ F9DB62200B65AFDE00A370FB /* ReleasePPC10.3.9SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = ReleasePPC10.3.9SDK;
+ };
+ F9DB62210B65AFDE00A370FB /* ReleasePPC10.3.9SDK */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = ppc;
+ CFLAGS = "$(PER_ARCH_CFLAGS_ppc) $(CFLAGS)";
+ CPPFLAGS = "-arch ppc -isysroot $(SDKROOT) $(CPPFLAGS)";
+ MACOSX_DEPLOYMENT_TARGET = 10.3;
+ PREBINDING = YES;
+ SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.3.9.sdk";
+ };
+ name = ReleasePPC10.3.9SDK;
+ };
+ F9DB62350B65B03A00A370FB /* ReleasePPC10.2.8SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = ReleasePPC10.2.8SDK;
+ };
+ F9DB62360B65B03A00A370FB /* ReleasePPC10.2.8SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = ReleasePPC10.2.8SDK;
+ };
+ F9DB62370B65B03A00A370FB /* ReleasePPC10.2.8SDK */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = ppc;
+ CFLAGS = "$(PER_ARCH_CFLAGS_ppc) -fconstant-cfstrings $(CFLAGS)";
+ CPPFLAGS = "-arch ppc -D__CONSTANT_CFSTRINGS__ -DMAC_OS_X_VERSION_MIN_REQUIRED=1020 -nostdinc -isystem $(SDKROOT)/usr/include/gcc/darwin/$(GCC_VERSION) -isystem $(SDKROOT)/usr/include -F$(SDKROOT)/System/Library/Frameworks";
+ DEBUG_INFORMATION_FORMAT = stabs;
+ GCC = /usr/bin/gcc;
+ GCC_VERSION = 3.3;
+ LDFLAGS = "-L$(SDKROOT)/usr/lib/gcc/darwin/$(GCC_VERSION) -Wl,-syslibroot,$(SDKROOT)";
+ MACOSX_DEPLOYMENT_TARGET = 10.2;
+ PREBINDING = YES;
+ SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.2.8.sdk";
+ WARNING_CFLAGS = (
+ "$(WARNING_CFLAGS_GCC3)",
+ "-Wno-long-double",
+ );
+ };
+ name = ReleasePPC10.2.8SDK;
+ };
+ F9EEED960C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tclsh;
+ SKIP_INSTALL = NO;
+ };
+ name = ReleaseUniversal10.5SDK;
+ };
+ F9EEED970C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tcltest;
+ };
+ name = ReleaseUniversal10.5SDK;
+ };
+ F9EEED980C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "";
+ PRODUCT_NAME = tests;
+ TCLTEST_OPTIONS = "";
+ TCL_LIBRARY = "$(TCL_SRCROOT)/library";
+ TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
+ };
+ name = ReleaseUniversal10.5SDK;
+ };
+ F9EEED990C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ CFLAGS = "-arch i386 -arch x86_64 -arch ppc -arch ppc64 $(CFLAGS)";
+ CPPFLAGS = "-isysroot $(SDKROOT) $(CPPFLAGS)";
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ };
+ name = ReleaseUniversal10.5SDK;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ F95CC8AB09158F3100EA5ACE /* Build configuration list for PBXNativeTarget "Tcl" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F95CC8AC09158F3100EA5ACE /* Debug */,
+ F9988AB20D814C6500B6B03B /* Debug gcc42 */,
+ F9988AB60D814C7500B6B03B /* Debug llvmgcc42 */,
+ F95CC8AE09158F3100EA5ACE /* DebugNoFixZL */,
+ F99EE73B0BE835310060D4AF /* DebugUnthreaded */,
+ F98751300DE7B57E00B1C9EC /* DebugNoCF */,
+ F98751340DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
+ F93084370BB93D2800CD0B9E /* DebugMemCompile */,
+ F99EE73C0BE835310060D4AF /* DebugLeaks */,
+ F9359B260DF212DA00E04F67 /* DebugGCov */,
+ F97AED1B0B660B2100310EA2 /* Debug64bit */,
+ F95CC8AD09158F3100EA5ACE /* Release */,
+ F91BCC4F093152310042A6BF /* ReleaseUniversal */,
+ F9988BB20D81586D00B6B03B /* ReleaseUniversal gcc42 */,
+ F9988BB60D81587400B6B03B /* ReleaseUniversal llvmgcc42 */,
+ F9EEED960C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
+ F9DB62080B65ADA800A370FB /* ReleaseUniversal10.4uSDK */,
+ F9DB621F0B65AFDE00A370FB /* ReleasePPC10.3.9SDK */,
+ F9DB62350B65B03A00A370FB /* ReleasePPC10.2.8SDK */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ F95CC8B009158F3100EA5ACE /* Build configuration list for PBXNativeTarget "tcltest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F95CC8B109158F3100EA5ACE /* Debug */,
+ F9988AB30D814C6500B6B03B /* Debug gcc42 */,
+ F9988AB70D814C7500B6B03B /* Debug llvmgcc42 */,
+ F95CC8B309158F3100EA5ACE /* DebugNoFixZL */,
+ F99EE73D0BE835310060D4AF /* DebugUnthreaded */,
+ F98751310DE7B57E00B1C9EC /* DebugNoCF */,
+ F98751350DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
+ F93084380BB93D2800CD0B9E /* DebugMemCompile */,
+ F99EE73E0BE835310060D4AF /* DebugLeaks */,
+ F9359B270DF212DA00E04F67 /* DebugGCov */,
+ F97AED1C0B660B2100310EA2 /* Debug64bit */,
+ F95CC8B209158F3100EA5ACE /* Release */,
+ F91BCC50093152310042A6BF /* ReleaseUniversal */,
+ F9988BB30D81586D00B6B03B /* ReleaseUniversal gcc42 */,
+ F9988BB70D81587400B6B03B /* ReleaseUniversal llvmgcc42 */,
+ F9EEED970C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
+ F9DB62090B65ADA800A370FB /* ReleaseUniversal10.4uSDK */,
+ F9DB62200B65AFDE00A370FB /* ReleasePPC10.3.9SDK */,
+ F9DB62360B65B03A00A370FB /* ReleasePPC10.2.8SDK */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ F95CC8B509158F3100EA5ACE /* Build configuration list for PBXProject "Tcl" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F95CC8B609158F3100EA5ACE /* Debug */,
+ F9988AB10D814C6500B6B03B /* Debug gcc42 */,
+ F9988AB50D814C7500B6B03B /* Debug llvmgcc42 */,
+ F95CC8B809158F3100EA5ACE /* DebugNoFixZL */,
+ F99EE7410BE835310060D4AF /* DebugUnthreaded */,
+ F987512F0DE7B57E00B1C9EC /* DebugNoCF */,
+ F98751330DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
+ F930843A0BB93D2800CD0B9E /* DebugMemCompile */,
+ F99EE7420BE835310060D4AF /* DebugLeaks */,
+ F9359B250DF212DA00E04F67 /* DebugGCov */,
+ F97AED1E0B660B2100310EA2 /* Debug64bit */,
+ F95CC8B709158F3100EA5ACE /* Release */,
+ F91BCC51093152310042A6BF /* ReleaseUniversal */,
+ F9988BB10D81586D00B6B03B /* ReleaseUniversal gcc42 */,
+ F9988BB50D81587400B6B03B /* ReleaseUniversal llvmgcc42 */,
+ F9EEED990C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
+ F9DB620A0B65ADA800A370FB /* ReleaseUniversal10.4uSDK */,
+ F9DB62210B65AFDE00A370FB /* ReleasePPC10.3.9SDK */,
+ F9DB62370B65B03A00A370FB /* ReleasePPC10.2.8SDK */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ F97258A80A86873D00096C78 /* Build configuration list for PBXNativeTarget "tests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F97258A90A86873D00096C78 /* Debug */,
+ F9988AB40D814C6500B6B03B /* Debug gcc42 */,
+ F9988AB80D814C7500B6B03B /* Debug llvmgcc42 */,
+ F97258AB0A86873D00096C78 /* DebugNoFixZL */,
+ F99EE73F0BE835310060D4AF /* DebugUnthreaded */,
+ F98751320DE7B57E00B1C9EC /* DebugNoCF */,
+ F98751360DE7B5A200B1C9EC /* DebugNoCFUnthreaded */,
+ F93084390BB93D2800CD0B9E /* DebugMemCompile */,
+ F99EE7400BE835310060D4AF /* DebugLeaks */,
+ F9359B280DF212DA00E04F67 /* DebugGCov */,
+ F97AED1D0B660B2100310EA2 /* Debug64bit */,
+ F97258AA0A86873D00096C78 /* Release */,
+ F97258AC0A86873D00096C78 /* ReleaseUniversal */,
+ F9988BB40D81586D00B6B03B /* ReleaseUniversal gcc42 */,
+ F9988BB80D81587400B6B03B /* ReleaseUniversal llvmgcc42 */,
+ F9EEED980C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
+ F97AED080B660A6C00310EA2 /* ReleaseUniversal10.4uSDK */,
+ F97AED0F0B660AA300310EA2 /* ReleasePPC10.3.9SDK */,
+ F97AED160B660AF100310EA2 /* ReleasePPC10.2.8SDK */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/macosx/Tclsh-Info.plist.in b/macosx/Tclsh-Info.plist.in
index 47810b1..ecc7f21 100644
--- a/macosx/Tclsh-Info.plist.in
+++ b/macosx/Tclsh-Info.plist.in
@@ -14,10 +14,10 @@
<string>tclsh@TCL_VERSION@</string>
<key>CFBundleGetInfoString</key>
<string>Tcl Shell @TCL_VERSION@@TCL_PATCH_LEVEL@,
-Copyright © @TCL_YEAR@ Tcl Core Team,
+Copyright © 1987-@TCL_YEAR@ Tcl Core Team,
Copyright © 2001-@TCL_YEAR@ Daniel A. Steffen,
-Initial MacOS X Port by Jim Ingham &amp; Ian Reid,
-Copyright © 2001-2002, Apple Computer, Inc.</string>
+Copyright © 2001-2009 Apple Inc.,
+Copyright © 2001-2002 Jim Ingham &amp; Ian Reid</string>
<key>CFBundleIdentifier</key>
<string>com.tcltk.tclsh</string>
<key>CFBundleInfoDictionaryVersion</key>
diff --git a/macosx/configure.ac b/macosx/configure.ac
new file mode 100644
index 0000000..01c3697
--- /dev/null
+++ b/macosx/configure.ac
@@ -0,0 +1,11 @@
+#! /bin/bash -norc
+dnl This file is an input file used by the GNU "autoconf" program to
+dnl generate the file "configure", which is run during Tcl installation
+dnl to configure the system for the local environment.
+
+dnl Ensure that the config (auto)headers support is used, then just
+dnl include the configure sources from ../unix:
+
+m4_include(../unix/aclocal.m4)
+m4_define(SC_USE_CONFIG_HEADERS)
+m4_include(../unix/configure.in)
diff --git a/macosx/tclMacOSXBundle.c b/macosx/tclMacOSXBundle.c
index 96b116b..c4fc82d 100644
--- a/macosx/tclMacOSXBundle.c
+++ b/macosx/tclMacOSXBundle.c
@@ -4,61 +4,69 @@
* This file implements functions that inspect CFBundle structures on
* MacOS X.
*
- * Copyright 2001, Apple Computer, Inc.
+ * Copyright 2001-2009, Apple Inc.
* Copyright (c) 2003-2009 Daniel A. Steffen <das@users.sourceforge.net>
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * The following terms apply to all files originating from Apple
- * Computer, Inc. ("Apple") and associated with the software unless
- * explicitly disclaimed in individual files.
- *
- * Apple hereby grants permission to use, copy, modify, distribute, and
- * license this software and its documentation for any purpose, provided
- * that existing copyright notices are retained in all copies and that
- * this notice is included verbatim in any distributions. No written
- * agreement, license, or royalty fee is required for any of the
- * authorized uses. Modifications to this software may be copyrighted by
- * their authors and need not follow the licensing terms described here,
- * provided that the new terms are clearly indicated on the first page of
- * each file where they apply.
- *
- * IN NO EVENT SHALL APPLE, THE AUTHORS OR DISTRIBUTORS OF THE SOFTWARE
- * BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
- * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS
- * DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF APPLE OR THE
- * AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. APPLE,
- * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
- * NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
- * APPLE,THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
- * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * GOVERNMENT USE: If you are acquiring this software on behalf of the
- * U.S. government, the Government shall have only "Restricted Rights" in
- * the software and related documentation as defined in the Federal
- * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are
- * acquiring the software on behalf of the Department of Defense, the
- * software shall be classified as "Commercial Computer Software" and the
- * Government shall have only "Restricted Rights" as defined in Clause
- * 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
- * authors grant the U.S. Government and others acting in its behalf
- * permission to use and distribute the software in accordance with the
- * terms specified in this license.
*/
#include "tclPort.h"
#ifdef HAVE_COREFOUNDATION
#include <CoreFoundation/CoreFoundation.h>
+
+#ifndef TCL_DYLD_USE_DLFCN
+/*
+ * Use preferred dlfcn API on 10.4 and later
+ */
+# if !defined(NO_DLFCN_H) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
+# define TCL_DYLD_USE_DLFCN 1
+# else
+# define TCL_DYLD_USE_DLFCN 0
+# endif
+#endif
+
+#ifndef TCL_DYLD_USE_NSMODULE
+/*
+ * Use deprecated NSModule API only to support 10.3 and earlier:
+ */
+# if MAC_OS_X_VERSION_MIN_REQUIRED < 1040
+# define TCL_DYLD_USE_NSMODULE 1
+# else
+# define TCL_DYLD_USE_NSMODULE 0
+# endif
+#endif
+
+#if TCL_DYLD_USE_DLFCN
+#include <dlfcn.h>
+#if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040
+/*
+ * Support for weakly importing dlfcn API.
+ */
+extern void *dlsym(void *handle, const char *symbol) WEAK_IMPORT_ATTRIBUTE;
+extern char *dlerror(void) WEAK_IMPORT_ATTRIBUTE;
+#endif
+#endif
+
+#if TCL_DYLD_USE_NSMODULE
#include <mach-o/dyld.h>
+#endif
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+#if (TCL_DYLD_USE_DLFCN && MAC_OS_X_VERSION_MIN_REQUIRED < 1040) || \
+ (MAC_OS_X_VERSION_MIN_REQUIRED < 1050)
MODULE_SCOPE long tclMacOSXDarwinRelease;
#endif
+#ifdef TCL_DEBUG_LOAD
+#define TclLoadDbgMsg(m, ...) do { \
+ fprintf(stderr, "%s:%d: %s(): " m ".\n", \
+ strrchr(__FILE__, '/')+1, __LINE__, __func__, ##__VA_ARGS__); \
+ } while (0)
+#else
+#define TclLoadDbgMsg(m, ...)
+#endif
+
#endif /* HAVE_COREFOUNDATION */
/*
@@ -195,15 +203,36 @@ Tcl_MacOSXOpenVersionedBundleResources(
static short (*openresourcemap)(CFBundleRef) = NULL;
if (!initialized) {
- NSSymbol nsSymbol = NULL;
- if (NSIsSymbolNameDefinedWithHint(
- "_CFBundleOpenBundleResourceMap", "CoreFoundation")) {
- nsSymbol = NSLookupAndBindSymbolWithHint(
- "_CFBundleOpenBundleResourceMap","CoreFoundation");
- if (nsSymbol) {
- openresourcemap = NSAddressOfSymbol(nsSymbol);
+#if TCL_DYLD_USE_DLFCN
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040
+ if (tclMacOSXDarwinRelease >= 8)
+#endif
+ {
+ const char *errMsg = nil;
+ openresourcemap = dlsym(RTLD_NEXT,
+ "CFBundleOpenBundleResourceMap");
+ if (!openresourcemap) {
+ errMsg = dlerror();
+ TclLoadDbgMsg("dlsym() failed: %s", errMsg);
}
}
+ if (!openresourcemap)
+#endif
+ {
+#if TCL_DYLD_USE_NSMODULE
+ NSSymbol nsSymbol = NULL;
+ if (NSIsSymbolNameDefinedWithHint(
+ "_CFBundleOpenBundleResourceMap",
+ "CoreFoundation")) {
+ nsSymbol = NSLookupAndBindSymbolWithHint(
+ "_CFBundleOpenBundleResourceMap",
+ "CoreFoundation");
+ if (nsSymbol) {
+ openresourcemap = NSAddressOfSymbol(nsSymbol);
+ }
+ }
+#endif
+ }
initialized = TRUE;
}
@@ -247,3 +276,11 @@ Tcl_MacOSXOpenVersionedBundleResources(
return TCL_ERROR;
#endif /* HAVE_COREFOUNDATION */
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/macosx/tclMacOSXFCmd.c b/macosx/tclMacOSXFCmd.c
new file mode 100644
index 0000000..09ee96d
--- /dev/null
+++ b/macosx/tclMacOSXFCmd.c
@@ -0,0 +1,696 @@
+/*
+ * tclMacOSXFCmd.c
+ *
+ * This file implements the MacOSX specific portion of file manipulation
+ * subcommands of the "file" command.
+ *
+ * Copyright (c) 2003-2007 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tclInt.h"
+
+#ifdef HAVE_GETATTRLIST
+#include <sys/attr.h>
+#include <sys/paths.h>
+#include <libkern/OSByteOrder.h>
+#endif
+
+/* Darwin 8 copyfile API. */
+#ifdef HAVE_COPYFILE
+#ifdef HAVE_COPYFILE_H
+#include <copyfile.h>
+#if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040
+/* Support for weakly importing copyfile. */
+#define WEAK_IMPORT_COPYFILE
+extern int copyfile(const char *from, const char *to, copyfile_state_t state,
+ copyfile_flags_t flags) WEAK_IMPORT_ATTRIBUTE;
+#endif /* HAVE_WEAK_IMPORT */
+#else /* HAVE_COPYFILE_H */
+int copyfile(const char *from, const char *to, void *state, uint32_t flags);
+#define COPYFILE_ACL (1<<0)
+#define COPYFILE_XATTR (1<<2)
+#define COPYFILE_NOFOLLOW_SRC (1<<18)
+#if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040
+/* Support for weakly importing copyfile. */
+#define WEAK_IMPORT_COPYFILE
+extern int copyfile(const char *from, const char *to, void *state,
+ uint32_t flags) WEAK_IMPORT_ATTRIBUTE;
+#endif /* HAVE_WEAK_IMPORT */
+#endif /* HAVE_COPYFILE_H */
+#endif /* HAVE_COPYFILE */
+
+#include <libkern/OSByteOrder.h>
+
+/*
+ * Constants for file attributes subcommand. Need to be kept in sync with
+ * tclUnixFCmd.c !
+ */
+
+enum {
+ UNIX_GROUP_ATTRIBUTE,
+ UNIX_OWNER_ATTRIBUTE,
+ UNIX_PERMISSIONS_ATTRIBUTE,
+#ifdef HAVE_CHFLAGS
+ UNIX_READONLY_ATTRIBUTE,
+#endif
+#ifdef MAC_OSX_TCL
+ MACOSX_CREATOR_ATTRIBUTE,
+ MACOSX_TYPE_ATTRIBUTE,
+ MACOSX_HIDDEN_ATTRIBUTE,
+ MACOSX_RSRCLENGTH_ATTRIBUTE,
+#endif
+};
+
+typedef u_int32_t OSType;
+
+static int GetOSTypeFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, OSType *osTypePtr);
+static Tcl_Obj * NewOSTypeObj(const OSType newOSType);
+static int SetOSTypeFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
+static void UpdateStringOfOSType(Tcl_Obj *objPtr);
+
+static Tcl_ObjType tclOSTypeType = {
+ "osType", /* name */
+ NULL, /* freeIntRepProc */
+ NULL, /* dupIntRepProc */
+ UpdateStringOfOSType, /* updateStringProc */
+ SetOSTypeFromAny /* setFromAnyProc */
+};
+
+enum {
+ kIsInvisible = 0x4000,
+};
+
+#define kFinfoIsInvisible (OSSwapHostToBigConstInt16(kIsInvisible))
+
+typedef struct finderinfo {
+ u_int32_t type;
+ u_int32_t creator;
+ u_int16_t fdFlags;
+ u_int32_t location;
+ u_int16_t reserved;
+ u_int32_t extendedFileInfo[4];
+} __attribute__ ((__packed__)) finderinfo;
+
+typedef struct fileinfobuf {
+ u_int32_t info_length;
+ u_int32_t data[8];
+} fileinfobuf;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMacOSXGetFileAttribute
+ *
+ * Gets a MacOSX attribute of a file. Which attribute is controlled by
+ * objIndex. The object will have ref count 0.
+ *
+ * Results:
+ * Standard TCL result. Returns a new Tcl_Obj in attributePtrPtr if there
+ * is no error.
+ *
+ * Side effects:
+ * A new object is allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclMacOSXGetFileAttribute(
+ Tcl_Interp *interp, /* The interp we are using for errors. */
+ int objIndex, /* The index of the attribute. */
+ Tcl_Obj *fileName, /* The name of the file (UTF-8). */
+ Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */
+{
+#ifdef HAVE_GETATTRLIST
+ int result;
+ Tcl_StatBuf statBuf;
+ struct attrlist alist;
+ fileinfobuf finfo;
+ finderinfo *finder = (finderinfo*)(&finfo.data);
+ off_t *rsrcForkSize = (off_t*)(&finfo.data);
+ const char *native;
+
+ result = TclpObjStat(fileName, &statBuf);
+
+ if (result != 0) {
+ Tcl_AppendResult(interp, "could not read \"",
+ TclGetString(fileName), "\": ", Tcl_PosixError(interp), NULL);
+ return TCL_ERROR;
+ }
+
+ if (S_ISDIR(statBuf.st_mode) && objIndex != MACOSX_HIDDEN_ATTRIBUTE) {
+ /*
+ * Directories only support attribute "-hidden".
+ */
+
+ errno = EISDIR;
+ Tcl_AppendResult(interp, "invalid attribute: ",
+ Tcl_PosixError(interp), NULL);
+ return TCL_ERROR;
+ }
+
+ bzero(&alist, sizeof(struct attrlist));
+ alist.bitmapcount = ATTR_BIT_MAP_COUNT;
+ if (objIndex == MACOSX_RSRCLENGTH_ATTRIBUTE) {
+ alist.fileattr = ATTR_FILE_RSRCLENGTH;
+ } else {
+ alist.commonattr = ATTR_CMN_FNDRINFO;
+ }
+ native = Tcl_FSGetNativePath(fileName);
+ result = getattrlist(native, &alist, &finfo, sizeof(fileinfobuf), 0);
+
+ if (result != 0) {
+ Tcl_AppendResult(interp, "could not read attributes of \"",
+ TclGetString(fileName), "\": ", Tcl_PosixError(interp), NULL);
+ return TCL_ERROR;
+ }
+
+ switch (objIndex) {
+ case MACOSX_CREATOR_ATTRIBUTE:
+ *attributePtrPtr = NewOSTypeObj(
+ OSSwapBigToHostInt32(finder->creator));
+ break;
+ case MACOSX_TYPE_ATTRIBUTE:
+ *attributePtrPtr = NewOSTypeObj(
+ OSSwapBigToHostInt32(finder->type));
+ break;
+ case MACOSX_HIDDEN_ATTRIBUTE:
+ *attributePtrPtr = Tcl_NewBooleanObj(
+ (finder->fdFlags & kFinfoIsInvisible) != 0);
+ break;
+ case MACOSX_RSRCLENGTH_ATTRIBUTE:
+ *attributePtrPtr = Tcl_NewWideIntObj(*rsrcForkSize);
+ break;
+ }
+ return TCL_OK;
+#else
+ Tcl_AppendResult(interp, "Mac OS X file attributes not supported", NULL);
+ return TCL_ERROR;
+#endif
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclMacOSXSetFileAttribute --
+ *
+ * Sets a MacOSX attribute of a file. Which attribute is controlled by
+ * objIndex.
+ *
+ * Results:
+ * Standard TCL result.
+ *
+ * Side effects:
+ * As above.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclMacOSXSetFileAttribute(
+ Tcl_Interp *interp, /* The interp for error reporting. */
+ int objIndex, /* The index of the attribute. */
+ Tcl_Obj *fileName, /* The name of the file (UTF-8). */
+ Tcl_Obj *attributePtr) /* New owner for file. */
+{
+#ifdef HAVE_GETATTRLIST
+ int result;
+ Tcl_StatBuf statBuf;
+ struct attrlist alist;
+ fileinfobuf finfo;
+ finderinfo *finder = (finderinfo*)(&finfo.data);
+ off_t *rsrcForkSize = (off_t*)(&finfo.data);
+ const char *native;
+
+ result = TclpObjStat(fileName, &statBuf);
+
+ if (result != 0) {
+ Tcl_AppendResult(interp, "could not read \"",
+ TclGetString(fileName), "\": ", Tcl_PosixError(interp), NULL);
+ return TCL_ERROR;
+ }
+
+ if (S_ISDIR(statBuf.st_mode) && objIndex != MACOSX_HIDDEN_ATTRIBUTE) {
+ /*
+ * Directories only support attribute "-hidden".
+ */
+
+ errno = EISDIR;
+ Tcl_AppendResult(interp, "invalid attribute: ",
+ Tcl_PosixError(interp), NULL);
+ return TCL_ERROR;
+ }
+
+ bzero(&alist, sizeof(struct attrlist));
+ alist.bitmapcount = ATTR_BIT_MAP_COUNT;
+ if (objIndex == MACOSX_RSRCLENGTH_ATTRIBUTE) {
+ alist.fileattr = ATTR_FILE_RSRCLENGTH;
+ } else {
+ alist.commonattr = ATTR_CMN_FNDRINFO;
+ }
+ native = Tcl_FSGetNativePath(fileName);
+ result = getattrlist(native, &alist, &finfo, sizeof(fileinfobuf), 0);
+
+ if (result != 0) {
+ Tcl_AppendResult(interp, "could not read attributes of \"",
+ TclGetString(fileName), "\": ", Tcl_PosixError(interp), NULL);
+ return TCL_ERROR;
+ }
+
+ if (objIndex != MACOSX_RSRCLENGTH_ATTRIBUTE) {
+ OSType t;
+ int h;
+
+ switch (objIndex) {
+ case MACOSX_CREATOR_ATTRIBUTE:
+ if (GetOSTypeFromObj(interp, attributePtr, &t) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ finder->creator = OSSwapHostToBigInt32(t);
+ break;
+ case MACOSX_TYPE_ATTRIBUTE:
+ if (GetOSTypeFromObj(interp, attributePtr, &t) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ finder->type = OSSwapHostToBigInt32(t);
+ break;
+ case MACOSX_HIDDEN_ATTRIBUTE:
+ if (Tcl_GetBooleanFromObj(interp, attributePtr, &h) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (h) {
+ finder->fdFlags |= kFinfoIsInvisible;
+ } else {
+ finder->fdFlags &= ~kFinfoIsInvisible;
+ }
+ break;
+ }
+
+ result = setattrlist(native, &alist,
+ &finfo.data, sizeof(finfo.data), 0);
+
+ if (result != 0) {
+ Tcl_AppendResult(interp, "could not set attributes of \"",
+ TclGetString(fileName), "\": ",
+ Tcl_PosixError(interp), NULL);
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_WideInt newRsrcForkSize;
+
+ if (Tcl_GetWideIntFromObj(interp, attributePtr,
+ &newRsrcForkSize) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (newRsrcForkSize != *rsrcForkSize) {
+ Tcl_DString ds;
+
+ /*
+ * Only setting rsrclength to 0 to strip a file's resource fork is
+ * supported.
+ */
+
+ if(newRsrcForkSize != 0) {
+ Tcl_AppendResult(interp,
+ "setting nonzero rsrclength not supported", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Construct path to resource fork.
+ */
+
+ Tcl_DStringInit(&ds);
+ Tcl_DStringAppend(&ds, native, -1);
+ Tcl_DStringAppend(&ds, _PATH_RSRCFORKSPEC, -1);
+
+ result = truncate(Tcl_DStringValue(&ds), (off_t)0);
+ if (result != 0) {
+ /*
+ * truncate() on a valid resource fork path may fail with
+ * a permission error in some OS releases, try truncating
+ * with open() instead:
+ */
+ int fd = open(Tcl_DStringValue(&ds), O_WRONLY | O_TRUNC);
+ if (fd > 0) {
+ result = close(fd);
+ }
+ }
+
+ Tcl_DStringFree(&ds);
+
+ if (result != 0) {
+ Tcl_AppendResult(interp,
+ "could not truncate resource fork of \"",
+ TclGetString(fileName), "\": ",
+ Tcl_PosixError(interp), NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+ return TCL_OK;
+#else
+ Tcl_AppendResult(interp, "Mac OS X file attributes not supported", NULL);
+ return TCL_ERROR;
+#endif
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclMacOSXCopyFileAttributes --
+ *
+ * Copy the MacOSX attributes and resource fork (if present) from one
+ * file to another.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * MacOSX attributes and resource fork are updated in the new file to
+ * reflect the old file.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclMacOSXCopyFileAttributes(
+ CONST char *src, /* Path name of source file (native). */
+ CONST char *dst, /* Path name of target file (native). */
+ CONST Tcl_StatBuf *statBufPtr)
+ /* Stat info for source file */
+{
+#ifdef WEAK_IMPORT_COPYFILE
+ if (copyfile != NULL) {
+#endif
+#ifdef HAVE_COPYFILE
+ if (copyfile(src, dst, NULL, COPYFILE_XATTR |
+ (S_ISLNK(statBufPtr->st_mode) ? COPYFILE_NOFOLLOW_SRC :
+ COPYFILE_ACL)) < 0) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+#endif /* HAVE_COPYFILE */
+#ifdef WEAK_IMPORT_COPYFILE
+ } else {
+#endif
+#if !defined(HAVE_COPYFILE) || defined(WEAK_IMPORT_COPYFILE)
+#ifdef HAVE_GETATTRLIST
+ struct attrlist alist;
+ fileinfobuf finfo;
+ off_t *rsrcForkSize = (off_t*)(&finfo.data);
+
+ bzero(&alist, sizeof(struct attrlist));
+ alist.bitmapcount = ATTR_BIT_MAP_COUNT;
+ alist.commonattr = ATTR_CMN_FNDRINFO;
+
+ if (getattrlist(src, &alist, &finfo, sizeof(fileinfobuf), 0)) {
+ return TCL_ERROR;
+ }
+
+ if (setattrlist(dst, &alist, &finfo.data, sizeof(finfo.data), 0)) {
+ return TCL_ERROR;
+ }
+
+ if (!S_ISDIR(statBufPtr->st_mode)) {
+ /*
+ * Only copy non-empty resource fork.
+ */
+
+ alist.commonattr = 0;
+ alist.fileattr = ATTR_FILE_RSRCLENGTH;
+
+ if (getattrlist(src, &alist, &finfo, sizeof(fileinfobuf), 0)) {
+ return TCL_ERROR;
+ }
+
+ if(*rsrcForkSize > 0) {
+ int result;
+ Tcl_DString ds_src, ds_dst;
+
+ /*
+ * Construct paths to resource forks.
+ */
+
+ Tcl_DStringInit(&ds_src);
+ Tcl_DStringAppend(&ds_src, src, -1);
+ Tcl_DStringAppend(&ds_src, _PATH_RSRCFORKSPEC, -1);
+ Tcl_DStringInit(&ds_dst);
+ Tcl_DStringAppend(&ds_dst, dst, -1);
+ Tcl_DStringAppend(&ds_dst, _PATH_RSRCFORKSPEC, -1);
+
+ result = TclUnixCopyFile(Tcl_DStringValue(&ds_src),
+ Tcl_DStringValue(&ds_dst), statBufPtr, 1);
+
+ Tcl_DStringFree(&ds_src);
+ Tcl_DStringFree(&ds_dst);
+
+ if (result != 0) {
+ return TCL_ERROR;
+ }
+ }
+ }
+ return TCL_OK;
+#else
+ return TCL_ERROR;
+#endif /* HAVE_GETATTRLIST */
+#endif /* !defined(HAVE_COPYFILE) || defined(WEAK_IMPORT_COPYFILE) */
+#ifdef WEAK_IMPORT_COPYFILE
+ }
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMacOSXMatchType --
+ *
+ * This routine is used by the globbing code to check if a file
+ * matches a given mac type and/or creator code.
+ *
+ * Results:
+ * The return value is 1, 0 or -1 indicating whether the file
+ * matches the given criteria, does not match them, or an error
+ * occurred (in wich case an error is left in interp).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclMacOSXMatchType(
+ Tcl_Interp *interp, /* Interpreter to receive errors. */
+ CONST char *pathName, /* Native path to check. */
+ CONST char *fileName, /* Native filename to check. */
+ Tcl_StatBuf *statBufPtr, /* Stat info for file to check */
+ Tcl_GlobTypeData *types) /* Type description to match against. */
+{
+#ifdef HAVE_GETATTRLIST
+ struct attrlist alist;
+ fileinfobuf finfo;
+ finderinfo *finder = (finderinfo*)(&finfo.data);
+ OSType osType;
+
+ bzero(&alist, sizeof(struct attrlist));
+ alist.bitmapcount = ATTR_BIT_MAP_COUNT;
+ alist.commonattr = ATTR_CMN_FNDRINFO;
+ if (getattrlist(pathName, &alist, &finfo, sizeof(fileinfobuf), 0) != 0) {
+ return 0;
+ }
+ if ((types->perm & TCL_GLOB_PERM_HIDDEN) &&
+ !((finder->fdFlags & kFinfoIsInvisible) || (*fileName == '.'))) {
+ return 0;
+ }
+ if (S_ISDIR(statBufPtr->st_mode) && (types->macType || types->macCreator)) {
+ /* Directories don't support types or creators */
+ return 0;
+ }
+ if (types->macType) {
+ if (GetOSTypeFromObj(interp, types->macType, &osType) != TCL_OK) {
+ return -1;
+ }
+ if (osType != OSSwapBigToHostInt32(finder->type)) {
+ return 0;
+ }
+ }
+ if (types->macCreator) {
+ if (GetOSTypeFromObj(interp, types->macCreator, &osType) != TCL_OK) {
+ return -1;
+ }
+ if (osType != OSSwapBigToHostInt32(finder->creator)) {
+ return 0;
+ }
+ }
+#endif
+ return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetOSTypeFromObj --
+ *
+ * Attempt to return an OSType from the Tcl object "objPtr".
+ *
+ * Results:
+ * Standard TCL result. If an error occurs during conversion, an error
+ * message is left in interp->objResult.
+ *
+ * Side effects:
+ * The string representation of objPtr will be updated if necessary.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetOSTypeFromObj(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tcl_Obj *objPtr, /* The object from which to get an OSType. */
+ OSType *osTypePtr) /* Place to store resulting OSType. */
+{
+ int result = TCL_OK;
+
+ if (objPtr->typePtr != &tclOSTypeType) {
+ result = tclOSTypeType.setFromAnyProc(interp, objPtr);
+ };
+ *osTypePtr = (OSType) objPtr->internalRep.longValue;
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NewOSTypeObj --
+ *
+ * Create a new OSType object.
+ *
+ * Results:
+ * The newly created OSType object is returned, it has ref count 0.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+NewOSTypeObj(
+ const OSType osType) /* OSType used to initialize the new object. */
+{
+ Tcl_Obj *objPtr;
+
+ TclNewObj(objPtr);
+ Tcl_InvalidateStringRep(objPtr);
+ objPtr->internalRep.longValue = (long) osType;
+ objPtr->typePtr = &tclOSTypeType;
+ return objPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetOSTypeFromAny --
+ *
+ * Attempts to force the internal representation for a Tcl object to
+ * tclOSTypeType, specifically.
+ *
+ * Results:
+ * The return value is a standard object Tcl result. If an error occurs
+ * during conversion, an error message is left in the interpreter's
+ * result unless "interp" is NULL.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetOSTypeFromAny(
+ Tcl_Interp *interp, /* Tcl interpreter */
+ Tcl_Obj *objPtr) /* Pointer to the object to convert */
+{
+ char *string;
+ int length, result = TCL_OK;
+ Tcl_DString ds;
+ Tcl_Encoding encoding = Tcl_GetEncoding(NULL, "macRoman");
+
+ string = Tcl_GetStringFromObj(objPtr, &length);
+ Tcl_UtfToExternalDString(encoding, string, length, &ds);
+
+ if (Tcl_DStringLength(&ds) > 4) {
+ if (interp) {
+ Tcl_AppendResult(interp, "expected Macintosh OS type but got \"",
+ string, "\": ", NULL);
+ }
+ result = TCL_ERROR;
+ } else {
+ OSType osType;
+ char string[4] = {'\0','\0','\0','\0'};
+ memcpy(string, Tcl_DStringValue(&ds),
+ (size_t) Tcl_DStringLength(&ds));
+ osType = (OSType) string[0] << 24 |
+ (OSType) string[1] << 16 |
+ (OSType) string[2] << 8 |
+ (OSType) string[3];
+ TclFreeIntRep(objPtr);
+ objPtr->internalRep.longValue = (long) osType;
+ objPtr->typePtr = &tclOSTypeType;
+ }
+ Tcl_DStringFree(&ds);
+ Tcl_FreeEncoding(encoding);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateStringOfOSType --
+ *
+ * Update the string representation for an OSType object. Note: This
+ * function does not free an existing old string rep so storage will be
+ * lost if this has not already been done.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The object's string is set to a valid string that results from the
+ * OSType-to-string conversion.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateStringOfOSType(
+ register Tcl_Obj *objPtr) /* OSType object whose string rep to update. */
+{
+ char string[5];
+ OSType osType = (OSType) objPtr->internalRep.longValue;
+ Tcl_DString ds;
+ Tcl_Encoding encoding = Tcl_GetEncoding(NULL, "macRoman");
+
+ string[0] = (char) (osType >> 24);
+ string[1] = (char) (osType >> 16);
+ string[2] = (char) (osType >> 8);
+ string[3] = (char) (osType);
+ string[4] = '\0';
+ Tcl_ExternalToUtfDString(encoding, string, -1, &ds);
+ objPtr->bytes = ckalloc((unsigned) Tcl_DStringLength(&ds) + 1);
+ strcpy(objPtr->bytes, Tcl_DStringValue(&ds));
+ objPtr->length = Tcl_DStringLength(&ds);
+ Tcl_DStringFree(&ds);
+ Tcl_FreeEncoding(encoding);
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/macosx/tclMacOSXNotify.c b/macosx/tclMacOSXNotify.c
index d342452..fb3c848 100644
--- a/macosx/tclMacOSXNotify.c
+++ b/macosx/tclMacOSXNotify.c
@@ -6,24 +6,184 @@
* This file works together with generic/tclNotify.c.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
- * Copyright 2001, Apple Computer, Inc.
- * Copyright (c) 2005-2008 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
#ifdef HAVE_COREFOUNDATION /* Traditional unix select-based notifier is
* in tclUnixNotfy.c */
#include <CoreFoundation/CoreFoundation.h>
#include <pthread.h>
+/* #define TCL_MAC_DEBUG_NOTIFIER 1 */
+
extern TclStubs tclStubs;
extern Tcl_NotifierProcs tclOriginalNotifier;
/*
+ * We use the Darwin-native spinlock API rather than pthread mutexes for
+ * notifier locking: this radically simplifies the implementation and lowers
+ * overhead. Note that these are not pure spinlocks, they employ various
+ * strategies to back off and relinquish the processor, making them immune to
+ * most priority-inversion livelocks (c.f. 'man 3 OSSpinLockLock' and Darwin
+ * sources: xnu/osfmk/{ppc,i386}/commpage/spinlocks.s).
+ */
+
+#if defined(HAVE_LIBKERN_OSATOMIC_H) && defined(HAVE_OSSPINLOCKLOCK)
+/*
+ * Use OSSpinLock API where available (Tiger or later).
+ */
+
+#include <libkern/OSAtomic.h>
+
+#if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040
+/*
+ * Support for weakly importing spinlock API.
+ */
+#define WEAK_IMPORT_SPINLOCKLOCK
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
+#define VOLATILE volatile
+#else
+#define VOLATILE
+#endif
+#ifndef bool
+#define bool int
+#endif
+extern void OSSpinLockLock(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE;
+extern void OSSpinLockUnlock(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE;
+extern bool OSSpinLockTry(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE;
+extern void _spin_lock(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE;
+extern void _spin_unlock(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE;
+extern bool _spin_lock_try(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE;
+static void (* lockLock)(VOLATILE OSSpinLock *lock) = NULL;
+static void (* lockUnlock)(VOLATILE OSSpinLock *lock) = NULL;
+static bool (* lockTry)(VOLATILE OSSpinLock *lock) = NULL;
+#undef VOLATILE
+static pthread_once_t spinLockLockInitControl = PTHREAD_ONCE_INIT;
+static void SpinLockLockInit(void) {
+ lockLock = OSSpinLockLock != NULL ? OSSpinLockLock : _spin_lock;
+ lockUnlock = OSSpinLockUnlock != NULL ? OSSpinLockUnlock : _spin_unlock;
+ lockTry = OSSpinLockTry != NULL ? OSSpinLockTry : _spin_lock_try;
+ if (lockLock == NULL || lockUnlock == NULL) {
+ Tcl_Panic("SpinLockLockInit: no spinlock API available");
+ }
+}
+#define SpinLockLock(p) lockLock(p)
+#define SpinLockUnlock(p) lockUnlock(p)
+#define SpinLockTry(p) lockTry(p)
+#else
+#define SpinLockLock(p) OSSpinLockLock(p)
+#define SpinLockUnlock(p) OSSpinLockUnlock(p)
+#define SpinLockTry(p) OSSpinLockTry(p)
+#endif /* HAVE_WEAK_IMPORT */
+#define SPINLOCK_INIT OS_SPINLOCK_INIT
+
+#else
+/*
+ * Otherwise, use commpage spinlock SPI directly.
+ */
+
+typedef uint32_t OSSpinLock;
+extern void _spin_lock(OSSpinLock *lock);
+extern void _spin_unlock(OSSpinLock *lock);
+extern int _spin_lock_try(OSSpinLock *lock);
+#define SpinLockLock(p) _spin_lock(p)
+#define SpinLockUnlock(p) _spin_unlock(p)
+#define SpinLockTry(p) _spin_lock_try(p)
+#define SPINLOCK_INIT 0
+
+#endif /* HAVE_LIBKERN_OSATOMIC_H && HAVE_OSSPINLOCKLOCK */
+
+/*
+ * These spinlocks lock access to the global notifier state.
+ */
+
+static OSSpinLock notifierInitLock = SPINLOCK_INIT;
+static OSSpinLock notifierLock = SPINLOCK_INIT;
+
+/*
+ * Macros abstracting notifier locking/unlocking
+ */
+
+#define LOCK_NOTIFIER_INIT SpinLockLock(&notifierInitLock)
+#define UNLOCK_NOTIFIER_INIT SpinLockUnlock(&notifierInitLock)
+#define LOCK_NOTIFIER SpinLockLock(&notifierLock)
+#define UNLOCK_NOTIFIER SpinLockUnlock(&notifierLock)
+#define LOCK_NOTIFIER_TSD SpinLockLock(&tsdPtr->tsdLock)
+#define UNLOCK_NOTIFIER_TSD SpinLockUnlock(&tsdPtr->tsdLock)
+
+#ifdef TCL_MAC_DEBUG_NOTIFIER
+#define TclMacOSXNotifierDbgMsg(m, ...) do { \
+ fprintf(notifierLog?notifierLog:stderr, "tclMacOSXNotify.c:%d: " \
+ "%s() pid %5d thread %10p: " m "\n", __LINE__, __func__, \
+ getpid(), pthread_self(), ##__VA_ARGS__); \
+ fflush(notifierLog?notifierLog:stderr); \
+ } while (0)
+
+/*
+ * Debug version of SpinLockLock that logs the time spent waiting for the lock
+ */
+
+#define SpinLockLockDbg(p) if (!SpinLockTry(p)) { \
+ Tcl_WideInt s = TclpGetWideClicks(), e; \
+ SpinLockLock(p); e = TclpGetWideClicks(); \
+ TclMacOSXNotifierDbgMsg("waited on %s for %8.0f ns", \
+ #p, TclpWideClicksToNanoseconds(e-s)); \
+ }
+#undef LOCK_NOTIFIER_INIT
+#define LOCK_NOTIFIER_INIT SpinLockLockDbg(&notifierInitLock)
+#undef LOCK_NOTIFIER
+#define LOCK_NOTIFIER SpinLockLockDbg(&notifierLock)
+#undef LOCK_NOTIFIER_TSD
+#define LOCK_NOTIFIER_TSD SpinLockLockDbg(&tsdPtr->tsdLock)
+#include <asl.h>
+static FILE *notifierLog = NULL;
+#ifndef NOTIFIER_LOG
+#define NOTIFIER_LOG "/tmp/tclMacOSXNotify.log"
+#endif
+#define OPEN_NOTIFIER_LOG if (!notifierLog) { \
+ notifierLog = fopen(NOTIFIER_LOG, "a"); \
+ /*TclMacOSXNotifierDbgMsg("open log"); \
+ asl_set_filter(NULL, \
+ ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG)); \
+ asl_add_log_file(NULL, \
+ fileno(notifierLog));*/ \
+ }
+#define CLOSE_NOTIFIER_LOG if (notifierLog) { \
+ /*asl_remove_log_file(NULL, \
+ fileno(notifierLog)); \
+ TclMacOSXNotifierDbgMsg("close log");*/ \
+ fclose(notifierLog); \
+ notifierLog = NULL; \
+ }
+#define ENABLE_ASL if (notifierLog) { \
+ /*tsdPtr->asl = asl_open(NULL, "com.apple.console", ASL_OPT_NO_REMOTE); \
+ asl_set_filter(tsdPtr->asl, \
+ ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG)); \
+ asl_add_log_file(tsdPtr->asl, \
+ fileno(notifierLog));*/ \
+ }
+#define DISABLE_ASL /*if (tsdPtr->asl) { \
+ if (notifierLog) { \
+ asl_remove_log_file(tsdPtr->asl, \
+ fileno(notifierLog)); \
+ } \
+ asl_close(tsdPtr->asl); \
+ }*/
+#define ASLCLIENT /*aslclient asl*/
+#else
+#define TclMacOSXNotifierDbgMsg(m, ...)
+#define OPEN_NOTIFIER_LOG
+#define CLOSE_NOTIFIER_LOG
+#define ENABLE_ASL
+#define DISABLE_ASL
+#endif /* TCL_MAC_DEBUG_NOTIFIER */
+
+/*
* This structure is used to keep track of the notifier info for a registered
* file.
*/
@@ -76,6 +236,30 @@ typedef struct SelectMasks {
typedef struct ThreadSpecificData {
FileHandler *firstFileHandlerPtr;
/* Pointer to head of file handler list. */
+ int polled; /* True if the notifier thread has polled for
+ * this thread.
+ */
+ int sleeping; /* True if runloop is inside Tcl_Sleep. */
+ int runLoopSourcePerformed; /* True after the runLoopSource callack was
+ * performed. */
+ int runLoopRunning; /* True if this thread's Tcl runLoop is running */
+ int runLoopNestingLevel; /* Level of nested runLoop invocations */
+ int runLoopServicingEvents; /* True if this thread's runLoop is servicing
+ * tcl events */
+ /* Must hold the notifierLock before accessing the following fields: */
+ /* Start notifierLock section */
+ int onList; /* True if this thread is on the waitingList */
+ struct ThreadSpecificData *nextPtr, *prevPtr;
+ /* All threads that are currently waiting on
+ * an event have their ThreadSpecificData
+ * structure on a doubly-linked listed formed
+ * from these pointers.
+ */
+ /* End notifierLock section */
+ OSSpinLock tsdLock; /* Must hold this lock before acessing the
+ * following fields from more than one thread.
+ */
+ /* Start tsdLock section */
SelectMasks checkMasks; /* This structure is used to build up the
* masks to be used in the next call to
* select. Bits are set in response to calls
@@ -86,26 +270,25 @@ typedef struct ThreadSpecificData {
int numFdBits; /* Number of valid bits in checkMasks (one
* more than highest fd for which
* Tcl_WatchFile has been called). */
- int onList; /* True if it is in this list */
- unsigned int pollState; /* pollState is used to implement a polling
- * handshake between each thread and the
- * notifier thread. Bits defined below. */
- struct ThreadSpecificData *nextPtr, *prevPtr;
- /* All threads that are currently waiting on
- * an event have their ThreadSpecificData
- * structure on a doubly-linked listed formed
- * from these pointers. You must hold the
- * notifierLock before accessing these
- * fields. */
+ int polling; /* True if this thread is polling for events */
+ CFRunLoopRef runLoop; /* This thread's CFRunLoop, needs to be woken
+ * up whenever the runLoopSource is signaled */
CFRunLoopSourceRef runLoopSource;
/* Any other thread alerts a notifier that an
* event is ready to be processed by signaling
* this CFRunLoopSource. */
- CFRunLoopRef runLoop; /* This thread's CFRunLoop, needs to be woken
- * up whenever the runLoopSource is
- * signaled. */
- int eventReady; /* True if an event is ready to be
- * processed. */
+ CFRunLoopObserverRef runLoopObserver, runLoopObserverTcl;
+ /* Adds/removes this thread from waitingList
+ * when the CFRunLoop starts/stops. */
+ CFRunLoopTimerRef runLoopTimer;
+ /* Wakes up CFRunLoop after given timeout when
+ * running embedded. */
+ /* End tsdLock section */
+ CFTimeInterval waitTime; /* runLoopTimer wait time when running
+ * embedded. */
+#ifdef TCL_MAC_DEBUG_NOTIFIER
+ ASLCLIENT;
+#endif
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
@@ -147,134 +330,56 @@ static int triggerPipe = -1;
static int receivePipe = -1; /* Output end of triggerPipe */
/*
- * We use the Darwin-native spinlock API rather than pthread mutexes for
- * notifier locking: this radically simplifies the implementation and lowers
- * overhead. Note that these are not pure spinlocks, they employ various
- * strategies to back off and relinquish the processor, making them immune to
- * most priority-inversion livelocks (c.f. 'man 3 OSSpinLockLock' and Darwin
- * sources: xnu/osfmk/{ppc,i386}/commpage/spinlocks.s).
- */
-
-#if defined(HAVE_LIBKERN_OSATOMIC_H) && defined(HAVE_OSSPINLOCKLOCK)
-/*
- * Use OSSpinLock API where available (Tiger or later).
- */
-
-#include <libkern/OSAtomic.h>
-
-#if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040
-/*
- * Support for weakly importing spinlock API.
- */
-#define WEAK_IMPORT_SPINLOCKLOCK
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
-#define VOLATILE volatile
-#else
-#define VOLATILE
-#endif
-#ifndef bool
-#define bool int
-#endif
-extern void OSSpinLockLock(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE;
-extern void OSSpinLockUnlock(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE;
-extern bool OSSpinLockTry(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE;
-extern void _spin_lock(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE;
-extern void _spin_unlock(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE;
-extern bool _spin_lock_try(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE;
-static void (* lockLock)(VOLATILE OSSpinLock *lock) = NULL;
-static void (* lockUnlock)(VOLATILE OSSpinLock *lock) = NULL;
-static bool (* lockTry)(VOLATILE OSSpinLock *lock) = NULL;
-#undef VOLATILE
-static pthread_once_t spinLockLockInitControl = PTHREAD_ONCE_INIT;
-static void SpinLockLockInit(void) {
- lockLock = OSSpinLockLock != NULL ? OSSpinLockLock : _spin_lock;
- lockUnlock = OSSpinLockUnlock != NULL ? OSSpinLockUnlock : _spin_unlock;
- lockTry = OSSpinLockTry != NULL ? OSSpinLockTry : _spin_lock_try;
- if (lockLock == NULL || lockUnlock == NULL) {
- Tcl_Panic("SpinLockLockInit: no spinlock API available");
- }
-}
-#define SpinLockLock(p) lockLock(p)
-#define SpinLockUnlock(p) lockUnlock(p)
-#define SpinLockTry(p) lockTry(p)
-#else
-#define SpinLockLock(p) OSSpinLockLock(p)
-#define SpinLockUnlock(p) OSSpinLockUnlock(p)
-#define SpinLockTry(p) OSSpinLockTry(p)
-#endif /* HAVE_WEAK_IMPORT */
-#define SPINLOCK_INIT OS_SPINLOCK_INIT
-
-#else
-/*
- * Otherwise, use commpage spinlock SPI directly.
- */
-
-typedef uint32_t OSSpinLock;
-extern void _spin_lock(OSSpinLock *lock);
-extern void _spin_unlock(OSSpinLock *lock);
-extern int _spin_lock_try(OSSpinLock *lock);
-#define SpinLockLock(p) _spin_lock(p)
-#define SpinLockUnlock(p) _spin_unlock(p)
-#define SpinLockTry(p) _spin_lock_try(p)
-#define SPINLOCK_INIT 0
-
-#endif /* HAVE_LIBKERN_OSATOMIC_H && HAVE_OSSPINLOCKLOCK */
-
-/*
- * These spinlocks lock access to the global notifier state.
- */
-
-static OSSpinLock notifierInitLock = SPINLOCK_INIT;
-static OSSpinLock notifierLock = SPINLOCK_INIT;
-
-/*
- * Macros abstracting notifier locking/unlocking
- */
-
-#define LOCK_NOTIFIER_INIT SpinLockLock(&notifierInitLock)
-#define UNLOCK_NOTIFIER_INIT SpinLockUnlock(&notifierInitLock)
-#define LOCK_NOTIFIER SpinLockLock(&notifierLock)
-#define UNLOCK_NOTIFIER SpinLockUnlock(&notifierLock)
-
-/*
- * The pollState bits
- * POLL_WANT is set by each thread before it waits on its condition
- * variable. It is checked by the notifier before it does select.
- * POLL_DONE is set by the notifier if it goes into select after seeing
- * POLL_WANT. The idea is to ensure it tries a select with the
- * same bits the initial thread had set.
+ * The following static indicates if the notifier thread is running.
+ *
+ * You must hold the notifierInitLock before accessing this variable.
*/
-#define POLL_WANT 0x1
-#define POLL_DONE 0x2
+static int notifierThreadRunning;
/*
* This is the thread ID of the notifier thread that does select.
+ * Only valid when notifierThreadRunning is non-zero.
+ *
+ * You must hold the notifierInitLock before accessing this variable.
*/
static pthread_t notifierThread;
/*
- * Custom run loop mode containing only the run loop source for the
- * notifier thread.
+ * Custom runloop mode for running with only the runloop source for the
+ * notifier thread
*/
#ifndef TCL_EVENTS_ONLY_RUN_LOOP_MODE
-#define TCL_EVENTS_ONLY_RUN_LOOP_MODE "com.tcltk.tclEventsOnlyRunLoopMode"
+#define TCL_EVENTS_ONLY_RUN_LOOP_MODE "com.tcltk.tclEventsOnlyRunLoopMode"
#endif
#ifdef __CONSTANT_CFSTRINGS__
-#define tclEventsOnlyRunLoopMode CFSTR(TCL_EVENTS_ONLY_RUN_LOOP_MODE)
+#define tclEventsOnlyRunLoopMode CFSTR(TCL_EVENTS_ONLY_RUN_LOOP_MODE)
#else
static CFStringRef tclEventsOnlyRunLoopMode = NULL;
#endif
/*
+ * CFTimeInterval to wait forever.
+ */
+
+#define CF_TIMEINTERVAL_FOREVER 5.05e8
+
+/*
* Static routines defined in this file.
*/
+static void StartNotifierThread(void);
static void NotifierThreadProc(ClientData clientData)
- __attribute__ ((__noreturn__));
+ __attribute__ ((__noreturn__));
static int FileHandlerEventProc(Tcl_Event *evPtr, int flags);
+static void TimerWakeUp(CFRunLoopTimerRef timer, void *info);
+static void QueueFileEvents(void *info);
+static void UpdateWaitingListAndServiceEvents(CFRunLoopObserverRef observer,
+ CFRunLoopActivity activity, void *info);
+static int OnOffWaitingList(ThreadSpecificData *tsdPtr, int onList,
+ int signalNotifier);
#ifdef HAVE_PTHREAD_ATFORK
static int atForkInit = 0;
@@ -284,8 +389,8 @@ static void AtForkChild(void);
#if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040
/* Support for weakly importing pthread_atfork. */
#define WEAK_IMPORT_PTHREAD_ATFORK
-extern int pthread_atfork(void (*prepare)(void), void (*parent)(void),
- void (*child)(void)) WEAK_IMPORT_ATTRIBUTE;
+extern int pthread_atfork(void (*prepare)(void), void (*parent)(void),
+ void (*child)(void)) WEAK_IMPORT_ATTRIBUTE;
#endif /* HAVE_WEAK_IMPORT */
/*
* On Darwin 9 and later, it is not possible to call CoreFoundation after
@@ -319,14 +424,15 @@ MODULE_SCOPE long tclMacOSXDarwinRelease;
ClientData
Tcl_InitNotifier(void)
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ThreadSpecificData *tsdPtr;
- tsdPtr->eventReady = 0;
+ tsdPtr = TCL_TSD_INIT(&dataKey);
#ifdef WEAK_IMPORT_SPINLOCKLOCK
/*
* Initialize support for weakly imported spinlock API.
*/
+
if (pthread_once(&spinLockLockInitControl, SpinLockLockInit)) {
Tcl_Panic("Tcl_InitNotifier: pthread_once failed");
}
@@ -346,17 +452,58 @@ Tcl_InitNotifier(void)
CFRunLoopRef runLoop = CFRunLoopGetCurrent();
CFRunLoopSourceRef runLoopSource;
CFRunLoopSourceContext runLoopSourceContext;
+ CFRunLoopObserverContext runLoopObserverContext;
+ CFRunLoopObserverRef runLoopObserver, runLoopObserverTcl;
bzero(&runLoopSourceContext, sizeof(CFRunLoopSourceContext));
runLoopSourceContext.info = tsdPtr;
- runLoopSource = CFRunLoopSourceCreate(NULL, 0, &runLoopSourceContext);
+ runLoopSourceContext.perform = QueueFileEvents;
+ runLoopSource = CFRunLoopSourceCreate(NULL, LONG_MIN,
+ &runLoopSourceContext);
if (!runLoopSource) {
Tcl_Panic("Tcl_InitNotifier: could not create CFRunLoopSource");
}
CFRunLoopAddSource(runLoop, runLoopSource, kCFRunLoopCommonModes);
CFRunLoopAddSource(runLoop, runLoopSource, tclEventsOnlyRunLoopMode);
- tsdPtr->runLoopSource = runLoopSource;
+
+ bzero(&runLoopObserverContext, sizeof(CFRunLoopObserverContext));
+ runLoopObserverContext.info = tsdPtr;
+ runLoopObserver = CFRunLoopObserverCreate(NULL,
+ kCFRunLoopEntry|kCFRunLoopExit|kCFRunLoopBeforeWaiting, TRUE,
+ LONG_MIN, UpdateWaitingListAndServiceEvents,
+ &runLoopObserverContext);
+ if (!runLoopObserver) {
+ Tcl_Panic("Tcl_InitNotifier: could not create "
+ "CFRunLoopObserver");
+ }
+ CFRunLoopAddObserver(runLoop, runLoopObserver, kCFRunLoopCommonModes);
+
+ /*
+ * Create a second CFRunLoopObserver with the same callback as above
+ * for the tclEventsOnlyRunLoopMode to ensure that the callback can be
+ * re-entered via Tcl_ServiceAll() in the kCFRunLoopBeforeWaiting case
+ * (CFRunLoop prevents observer callback re-entry of a given observer
+ * instance).
+ */
+
+ runLoopObserverTcl = CFRunLoopObserverCreate(NULL,
+ kCFRunLoopEntry|kCFRunLoopExit|kCFRunLoopBeforeWaiting, TRUE,
+ LONG_MIN, UpdateWaitingListAndServiceEvents,
+ &runLoopObserverContext);
+ if (!runLoopObserverTcl) {
+ Tcl_Panic("Tcl_InitNotifier: could not create "
+ "CFRunLoopObserver");
+ }
+ CFRunLoopAddObserver(runLoop, runLoopObserverTcl,
+ tclEventsOnlyRunLoopMode);
+
tsdPtr->runLoop = runLoop;
+ tsdPtr->runLoopSource = runLoopSource;
+ tsdPtr->runLoopObserver = runLoopObserver;
+ tsdPtr->runLoopObserverTcl = runLoopObserverTcl;
+ tsdPtr->runLoopTimer = NULL;
+ tsdPtr->waitTime = CF_TIMEINTERVAL_FOREVER;
+ tsdPtr->tsdLock = SPINLOCK_INIT;
}
LOCK_NOTIFIER_INIT;
@@ -372,6 +519,7 @@ Tcl_InitNotifier(void)
#endif
!atForkInit) {
int result = pthread_atfork(AtForkPrepare, AtForkParent, AtForkChild);
+
if (result) {
Tcl_Panic("Tcl_InitNotifier: pthread_atfork failed");
}
@@ -392,12 +540,14 @@ Tcl_InitNotifier(void)
status = fcntl(fds[0], F_GETFL);
status |= O_NONBLOCK;
if (fcntl(fds[0], F_SETFL, status) < 0) {
- Tcl_Panic("Tcl_InitNotifier: could not make receive pipe non blocking");
+ Tcl_Panic("Tcl_InitNotifier: could not make receive pipe non "
+ "blocking");
}
status = fcntl(fds[1], F_GETFL);
status |= O_NONBLOCK;
if (fcntl(fds[1], F_SETFL, status) < 0) {
- Tcl_Panic("Tcl_InitNotifier: could not make trigger pipe non blocking");
+ Tcl_Panic("Tcl_InitNotifier: could not make trigger pipe non "
+ "blocking");
}
receivePipe = fds[0];
@@ -405,12 +555,14 @@ Tcl_InitNotifier(void)
/*
* Create notifier thread lazily in Tcl_WaitForEvent() to avoid
- * interfering with fork() followed immediately by execve()
- * (cannot execve() when more than one thread is present).
+ * interfering with fork() followed immediately by execve() (we cannot
+ * execve() when more than one thread is present).
*/
- notifierThread = 0;
+ notifierThreadRunning = 0;
+ OPEN_NOTIFIER_LOG;
}
+ ENABLE_ASL;
notifierCount++;
UNLOCK_NOTIFIER_INIT;
@@ -420,6 +572,82 @@ Tcl_InitNotifier(void)
/*
*----------------------------------------------------------------------
*
+ * TclMacOSXNotifierAddRunLoopMode --
+ *
+ * Add the tcl notifier RunLoop source, observer and timer (if any)
+ * to the given RunLoop mode.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclMacOSXNotifierAddRunLoopMode(
+ CONST void *runLoopMode)
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ CFStringRef mode = (CFStringRef) runLoopMode;
+
+ if (tsdPtr->runLoop) {
+ CFRunLoopAddSource(tsdPtr->runLoop, tsdPtr->runLoopSource, mode);
+ CFRunLoopAddObserver(tsdPtr->runLoop, tsdPtr->runLoopObserver, mode);
+ if (tsdPtr->runLoopTimer) {
+ CFRunLoopAddTimer(tsdPtr->runLoop, tsdPtr->runLoopTimer, mode);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StartNotifierThread --
+ *
+ * Start notifier thread if necessary.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+StartNotifierThread(void)
+{
+ LOCK_NOTIFIER_INIT;
+ if (!notifierCount) {
+ Tcl_Panic("StartNotifierThread: notifier not initialized");
+ }
+ if (!notifierThreadRunning) {
+ int result;
+ pthread_attr_t attr;
+
+ pthread_attr_init(&attr);
+ pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ pthread_attr_setstacksize(&attr, 60 * 1024);
+ result = pthread_create(&notifierThread, &attr,
+ (void * (*)(void *))NotifierThreadProc, NULL);
+ pthread_attr_destroy(&attr);
+ if (result) {
+ Tcl_Panic("StartNotifierThread: unable to start notifier thread");
+ }
+ notifierThreadRunning = 1;
+ }
+ UNLOCK_NOTIFIER_INIT;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tcl_FinalizeNotifier --
*
* This function is called to cleanup the notifier state before a thread
@@ -439,10 +667,13 @@ void
Tcl_FinalizeNotifier(
ClientData clientData) /* Not used. */
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ThreadSpecificData *tsdPtr;
+
+ tsdPtr = TCL_TSD_INIT(&dataKey);
LOCK_NOTIFIER_INIT;
notifierCount--;
+ DISABLE_ASL;
/*
* If this is the last thread to use the notifier, close the notifier pipe
@@ -450,52 +681,63 @@ Tcl_FinalizeNotifier(
*/
if (notifierCount == 0) {
- int result;
+ if (triggerPipe != -1) {
+ /*
+ * Send "q" message to the notifier thread so that it will
+ * terminate. The notifier will return from its call to select()
+ * and notice that a "q" message has arrived, it will then close
+ * its side of the pipe and terminate its thread. Note the we can
+ * not just close the pipe and check for EOF in the notifier thread
+ * because if a background child process was created with exec,
+ * select() would not register the EOF on the pipe until the child
+ * processes had terminated. [Bug: 4139] [Bug: 1222872]
+ */
- if (triggerPipe < 0) {
- Tcl_Panic("Tcl_FinalizeNotifier: notifier pipe not initialized");
- }
+ write(triggerPipe, "q", 1);
+ close(triggerPipe);
- /*
- * Send "q" message to the notifier thread so that it will terminate.
- * The notifier will return from its call to select() and notice that
- * a "q" message has arrived, it will then close its side of the pipe
- * and terminate its thread. Note the we can not just close the pipe
- * and check for EOF in the notifier thread because if a background
- * child process was created with exec, select() would not register
- * the EOF on the pipe until the child processes had terminated. [Bug:
- * 4139] [Bug: 1222872]
- */
+ if (notifierThreadRunning) {
+ int result = pthread_join(notifierThread, NULL);
- write(triggerPipe, "q", 1);
- close(triggerPipe);
-
- if (notifierThread) {
- result = pthread_join(notifierThread, NULL);
- if (result) {
- Tcl_Panic("Tcl_FinalizeNotifier: unable to join notifier thread");
+ if (result) {
+ Tcl_Panic("Tcl_FinalizeNotifier: unable to join notifier "
+ "thread");
+ }
+ notifierThreadRunning = 0;
}
- notifierThread = 0;
- }
- close(receivePipe);
- triggerPipe = -1;
+ close(receivePipe);
+ triggerPipe = -1;
+ }
+ CLOSE_NOTIFIER_LOG;
}
UNLOCK_NOTIFIER_INIT;
- LOCK_NOTIFIER; /* for concurrency with Tcl_AlertNotifier */
+ LOCK_NOTIFIER_TSD; /* For concurrency with Tcl_AlertNotifier */
if (tsdPtr->runLoop) {
tsdPtr->runLoop = NULL;
/*
- * Remove runLoopSource from all CFRunLoops and release it.
+ * Remove runLoopSource, runLoopObserver and runLoopTimer from all
+ * CFRunLoops.
*/
CFRunLoopSourceInvalidate(tsdPtr->runLoopSource);
CFRelease(tsdPtr->runLoopSource);
tsdPtr->runLoopSource = NULL;
+ CFRunLoopObserverInvalidate(tsdPtr->runLoopObserver);
+ CFRelease(tsdPtr->runLoopObserver);
+ tsdPtr->runLoopObserver = NULL;
+ CFRunLoopObserverInvalidate(tsdPtr->runLoopObserverTcl);
+ CFRelease(tsdPtr->runLoopObserverTcl);
+ tsdPtr->runLoopObserverTcl = NULL;
+ if (tsdPtr->runLoopTimer) {
+ CFRunLoopTimerInvalidate(tsdPtr->runLoopTimer);
+ CFRelease(tsdPtr->runLoopTimer);
+ tsdPtr->runLoopTimer = NULL;
+ }
}
- UNLOCK_NOTIFIER;
+ UNLOCK_NOTIFIER_TSD;
}
/*
@@ -521,15 +763,14 @@ void
Tcl_AlertNotifier(
ClientData clientData)
{
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;
+ ThreadSpecificData *tsdPtr = clientData;
- LOCK_NOTIFIER;
+ LOCK_NOTIFIER_TSD;
if (tsdPtr->runLoop) {
- tsdPtr->eventReady = 1;
CFRunLoopSourceSignal(tsdPtr->runLoopSource);
CFRunLoopWakeUp(tsdPtr->runLoop);
}
- UNLOCK_NOTIFIER;
+ UNLOCK_NOTIFIER_TSD;
}
/*
@@ -537,15 +778,13 @@ Tcl_AlertNotifier(
*
* Tcl_SetTimer --
*
- * This function sets the current notifier timer value. This interface is
- * not implemented in this notifier because we are always running inside
- * of Tcl_DoOneEvent.
+ * This function sets the current notifier timer value.
*
* Results:
* None.
*
* Side effects:
- * None.
+ * Replaces any previous timer.
*
*----------------------------------------------------------------------
*/
@@ -554,15 +793,58 @@ void
Tcl_SetTimer(
Tcl_Time *timePtr) /* Timeout value, may be NULL. */
{
- /*
- * The interval timer doesn't do anything in this implementation, because
- * the only event loop is via Tcl_DoOneEvent, which passes timeout values
- * to Tcl_WaitForEvent.
- */
+ ThreadSpecificData *tsdPtr;
+ CFRunLoopTimerRef runLoopTimer;
+ CFTimeInterval waitTime;
if (tclStubs.tcl_SetTimer != tclOriginalNotifier.setTimerProc) {
tclStubs.tcl_SetTimer(timePtr);
+ return;
+ }
+
+ tsdPtr = TCL_TSD_INIT(&dataKey);
+ runLoopTimer = tsdPtr->runLoopTimer;
+ if (!runLoopTimer) {
+ return;
}
+ if (timePtr) {
+ Tcl_Time vTime = *timePtr;
+
+ if (vTime.sec != 0 || vTime.usec != 0) {
+ tclScaleTimeProcPtr(&vTime, tclTimeClientData);
+ waitTime = vTime.sec + 1.0e-6 * vTime.usec;
+ } else {
+ waitTime = 0;
+ }
+ } else {
+ waitTime = CF_TIMEINTERVAL_FOREVER;
+ }
+ tsdPtr->waitTime = waitTime;
+ CFRunLoopTimerSetNextFireDate(runLoopTimer,
+ CFAbsoluteTimeGetCurrent() + waitTime);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TimerWakeUp --
+ *
+ * CFRunLoopTimer callback.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TimerWakeUp(
+ CFRunLoopTimerRef timer,
+ void *info)
+{
}
/*
@@ -586,6 +868,23 @@ Tcl_ServiceModeHook(
int mode) /* Either TCL_SERVICE_ALL, or
* TCL_SERVICE_NONE. */
{
+ ThreadSpecificData *tsdPtr;
+
+ tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ if (mode == TCL_SERVICE_ALL && !tsdPtr->runLoopTimer) {
+ if (!tsdPtr->runLoop) {
+ Tcl_Panic("Tcl_ServiceModeHook: Notifier not initialized");
+ }
+ tsdPtr->runLoopTimer = CFRunLoopTimerCreate(NULL,
+ CFAbsoluteTimeGetCurrent() + CF_TIMEINTERVAL_FOREVER,
+ CF_TIMEINTERVAL_FOREVER, 0, 0, TimerWakeUp, NULL);
+ if (tsdPtr->runLoopTimer) {
+ CFRunLoopAddTimer(tsdPtr->runLoop, tsdPtr->runLoopTimer,
+ kCFRunLoopCommonModes);
+ StartNotifierThread();
+ }
+ }
}
/*
@@ -615,7 +914,7 @@ Tcl_CreateFileHandler(
* event. */
ClientData clientData) /* Arbitrary data to pass to proc. */
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ThreadSpecificData *tsdPtr;
FileHandler *filePtr;
if (tclStubs.tcl_CreateFileHandler !=
@@ -624,6 +923,8 @@ Tcl_CreateFileHandler(
return;
}
+ tsdPtr = TCL_TSD_INIT(&dataKey);
+
for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
filePtr = filePtr->nextPtr) {
if (filePtr->fd == fd) {
@@ -631,7 +932,7 @@ Tcl_CreateFileHandler(
}
}
if (filePtr == NULL) {
- filePtr = (FileHandler*) ckalloc(sizeof(FileHandler));
+ filePtr = (FileHandler *) ckalloc(sizeof(FileHandler));
filePtr->fd = fd;
filePtr->readyMask = 0;
filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
@@ -645,6 +946,7 @@ Tcl_CreateFileHandler(
* Update the check masks for this file.
*/
+ LOCK_NOTIFIER_TSD;
if (mask & TCL_READABLE) {
FD_SET(fd, &(tsdPtr->checkMasks.readable));
} else {
@@ -663,6 +965,7 @@ Tcl_CreateFileHandler(
if (tsdPtr->numFdBits <= fd) {
tsdPtr->numFdBits = fd+1;
}
+ UNLOCK_NOTIFIER_TSD;
}
/*
@@ -687,8 +990,8 @@ Tcl_DeleteFileHandler(
* function. */
{
FileHandler *filePtr, *prevPtr;
- int i;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ int i, numFdBits;
+ ThreadSpecificData *tsdPtr;
if (tclStubs.tcl_DeleteFileHandler !=
tclOriginalNotifier.deleteFileHandlerProc) {
@@ -696,12 +999,15 @@ Tcl_DeleteFileHandler(
return;
}
+ tsdPtr = TCL_TSD_INIT(&dataKey);
+ numFdBits = -1;
+
/*
* Find the entry for the given file (and return if there isn't one).
*/
for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
- prevPtr = filePtr, filePtr = filePtr->nextPtr) {
+ prevPtr = filePtr, filePtr = filePtr->nextPtr) {
if (filePtr == NULL) {
return;
}
@@ -711,35 +1017,41 @@ Tcl_DeleteFileHandler(
}
/*
- * Update the check masks for this file.
- */
-
- if (filePtr->mask & TCL_READABLE) {
- FD_CLR(fd, &(tsdPtr->checkMasks.readable));
- }
- if (filePtr->mask & TCL_WRITABLE) {
- FD_CLR(fd, &(tsdPtr->checkMasks.writable));
- }
- if (filePtr->mask & TCL_EXCEPTION) {
- FD_CLR(fd, &(tsdPtr->checkMasks.exceptional));
- }
-
- /*
* Find current max fd.
*/
if (fd+1 == tsdPtr->numFdBits) {
- tsdPtr->numFdBits = 0;
+ numFdBits = 0;
for (i = fd-1; i >= 0; i--) {
if (FD_ISSET(i, &(tsdPtr->checkMasks.readable))
|| FD_ISSET(i, &(tsdPtr->checkMasks.writable))
|| FD_ISSET(i, &(tsdPtr->checkMasks.exceptional))) {
- tsdPtr->numFdBits = i+1;
+ numFdBits = i+1;
break;
}
}
}
+ LOCK_NOTIFIER_TSD;
+ if (numFdBits != -1) {
+ tsdPtr->numFdBits = numFdBits;
+ }
+
+ /*
+ * Update the check masks for this file.
+ */
+
+ if (filePtr->mask & TCL_READABLE) {
+ FD_CLR(fd, &(tsdPtr->checkMasks.readable));
+ }
+ if (filePtr->mask & TCL_WRITABLE) {
+ FD_CLR(fd, &(tsdPtr->checkMasks.writable));
+ }
+ if (filePtr->mask & TCL_EXCEPTION) {
+ FD_CLR(fd, &(tsdPtr->checkMasks.exceptional));
+ }
+ UNLOCK_NOTIFIER_TSD;
+
/*
* Clean up information in the callback record.
*/
@@ -818,7 +1130,18 @@ FileHandlerEventProc(
mask = filePtr->readyMask & filePtr->mask;
filePtr->readyMask = 0;
if (mask != 0) {
- (*filePtr->proc)(filePtr->clientData, mask);
+ LOCK_NOTIFIER_TSD;
+ if (mask & TCL_READABLE) {
+ FD_CLR(filePtr->fd, &(tsdPtr->readyMasks.readable));
+ }
+ if (mask & TCL_WRITABLE) {
+ FD_CLR(filePtr->fd, &(tsdPtr->readyMasks.writable));
+ }
+ if (mask & TCL_EXCEPTION) {
+ FD_CLR(filePtr->fd, &(tsdPtr->readyMasks.exceptional));
+ }
+ UNLOCK_NOTIFIER_TSD;
+ filePtr->proc(filePtr->clientData, mask);
}
break;
}
@@ -835,10 +1158,11 @@ FileHandlerEventProc(
* polls without blocking.
*
* Results:
- * Returns -1 if the select would block forever, otherwise returns 0.
+ * Returns 0 if a tcl event or timeout ocurred and 1 if a non-tcl
+ * CFRunLoop source was processed.
*
* Side effects:
- * Queues file events that are detected by the select.
+ * None.
*
*----------------------------------------------------------------------
*/
@@ -847,174 +1171,525 @@ int
Tcl_WaitForEvent(
Tcl_Time *timePtr) /* Maximum block time, or NULL. */
{
- FileHandler *filePtr;
- FileHandlerEvent *fileEvPtr;
- int mask;
- int waitForFiles;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ int result, polling, runLoopRunning;
+ CFTimeInterval waitTime;
+ SInt32 runLoopStatus;
+ ThreadSpecificData *tsdPtr;
if (tclStubs.tcl_WaitForEvent != tclOriginalNotifier.waitForEventProc) {
return tclStubs.tcl_WaitForEvent(timePtr);
}
+ result = -1;
+ polling = 0;
+ waitTime = CF_TIMEINTERVAL_FOREVER;
+ tsdPtr = TCL_TSD_INIT(&dataKey);
- /*
- * Start notifier thread if necessary.
- */
-
- LOCK_NOTIFIER_INIT;
- if (!notifierCount) {
- Tcl_Panic("Tcl_WaitForEvent: notifier not initialized");
+ if (!tsdPtr->runLoop) {
+ Tcl_Panic("Tcl_WaitForEvent: Notifier not initialized");
}
- if (!notifierThread) {
- int result;
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
- pthread_attr_setstacksize(&attr, 60 * 1024);
- result = pthread_create(&notifierThread, &attr,
- (void * (*)(void *))NotifierThreadProc, NULL);
- pthread_attr_destroy(&attr);
- if (result || !notifierThread) {
- Tcl_Panic("Tcl_WaitForEvent: unable to start notifier thread");
+ if (timePtr) {
+ Tcl_Time vTime = *timePtr;
+
+ /*
+ * TIP #233 (Virtualized Time). Is virtual time in effect? And do we
+ * actually have something to scale? If yes to both then we call the
+ * handler to do this scaling.
+ */
+
+ if (vTime.sec != 0 || vTime.usec != 0) {
+ tclScaleTimeProcPtr(&vTime, tclTimeClientData);
+ waitTime = vTime.sec + 1.0e-6 * vTime.usec;
+ } else {
+ /*
+ * Polling: pretend to wait for files and tell the notifier thread
+ * what we are doing. The notifier thread makes sure it goes
+ * through select with its select mask in the same state as ours
+ * currently is. We block until that happens.
+ */
+
+ polling = 1;
}
}
- UNLOCK_NOTIFIER_INIT;
+
+ StartNotifierThread();
+
+ LOCK_NOTIFIER_TSD;
+ tsdPtr->polling = polling;
+ UNLOCK_NOTIFIER_TSD;
+ tsdPtr->runLoopSourcePerformed = 0;
/*
- * Place this thread on the list of interested threads, signal the
- * notifier thread, and wait for a response or a timeout.
+ * If the Tcl runloop is already running (e.g. if Tcl_WaitForEvent was
+ * called recursively) or is servicing events via the runloop observer,
+ * re-run it in a custom runloop mode containing only the source for the
+ * notifier thread, otherwise wakeups from other sources added to the
+ * common runloop modes might get lost or 3rd party event handlers might
+ * get called when they do not expect to be.
*/
- LOCK_NOTIFIER;
- if (!tsdPtr->runLoop) {
- Tcl_Panic("Tcl_WaitForEvent: CFRunLoop not initialized");
- }
- waitForFiles = (tsdPtr->numFdBits > 0);
- if (timePtr != NULL && timePtr->sec == 0 && timePtr->usec == 0) {
- /*
- * Cannot emulate a polling select with a polling condition variable.
- * Instead, pretend to wait for files and tell the notifier thread
- * what we are doing. The notifier thread makes sure it goes through
- * select with its select mask in the same state as ours currently is.
- * We block until that happens.
- */
-
- waitForFiles = 1;
- tsdPtr->pollState = POLL_WANT;
- timePtr = NULL;
- } else {
- tsdPtr->pollState = 0;
+ runLoopRunning = tsdPtr->runLoopRunning;
+ tsdPtr->runLoopRunning = 1;
+ runLoopStatus = CFRunLoopRunInMode(tsdPtr->runLoopServicingEvents ||
+ runLoopRunning ? tclEventsOnlyRunLoopMode : kCFRunLoopDefaultMode,
+ waitTime, TRUE);
+ tsdPtr->runLoopRunning = runLoopRunning;
+
+ LOCK_NOTIFIER_TSD;
+ tsdPtr->polling = 0;
+ UNLOCK_NOTIFIER_TSD;
+ switch (runLoopStatus) {
+ case kCFRunLoopRunFinished:
+ Tcl_Panic("Tcl_WaitForEvent: CFRunLoop finished");
+ break;
+ case kCFRunLoopRunTimedOut:
+ QueueFileEvents(tsdPtr);
+ result = 0;
+ break;
+ case kCFRunLoopRunStopped:
+ case kCFRunLoopRunHandledSource:
+ result = tsdPtr->runLoopSourcePerformed ? 0 : 1;
+ break;
}
- if (waitForFiles) {
- /*
- * Add the ThreadSpecificData structure of this thread to the list of
- * ThreadSpecificData structures of all threads that are waiting on
- * file events.
- */
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * QueueFileEvents --
+ *
+ * CFRunLoopSource callback for queueing file events.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Queues file events that are detected by the select.
+ *
+ *----------------------------------------------------------------------
+ */
- tsdPtr->nextPtr = waitingListPtr;
- if (waitingListPtr) {
- waitingListPtr->prevPtr = tsdPtr;
- }
- tsdPtr->prevPtr = 0;
- waitingListPtr = tsdPtr;
- tsdPtr->onList = 1;
+static void
+QueueFileEvents(
+ void *info)
+{
+ SelectMasks readyMasks;
+ FileHandler *filePtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *) info;
- write(triggerPipe, "", 1);
- }
+ /*
+ * Queue all detected file events.
+ */
+ LOCK_NOTIFIER_TSD;
+ FD_COPY(&(tsdPtr->readyMasks.readable), &readyMasks.readable);
+ FD_COPY(&(tsdPtr->readyMasks.writable), &readyMasks.writable);
+ FD_COPY(&(tsdPtr->readyMasks.exceptional), &readyMasks.exceptional);
FD_ZERO(&(tsdPtr->readyMasks.readable));
FD_ZERO(&(tsdPtr->readyMasks.writable));
FD_ZERO(&(tsdPtr->readyMasks.exceptional));
+ UNLOCK_NOTIFIER_TSD;
+ tsdPtr->runLoopSourcePerformed = 1;
- if (!tsdPtr->eventReady) {
- CFTimeInterval waitTime;
- CFStringRef runLoopMode;
+ for (filePtr = tsdPtr->firstFileHandlerPtr; (filePtr != NULL);
+ filePtr = filePtr->nextPtr) {
+ int mask = 0;
- if (timePtr == NULL) {
- waitTime = 1.0e10; /* Wait forever, as per CFRunLoop.c */
- } else {
- waitTime = timePtr->sec + 1.0e-6 * timePtr->usec;
+ if (FD_ISSET(filePtr->fd, &readyMasks.readable)) {
+ mask |= TCL_READABLE;
+ }
+ if (FD_ISSET(filePtr->fd, &readyMasks.writable)) {
+ mask |= TCL_WRITABLE;
+ }
+ if (FD_ISSET(filePtr->fd, &readyMasks.exceptional)) {
+ mask |= TCL_EXCEPTION;
}
+ if (!mask) {
+ continue;
+ }
+
/*
- * If the run loop is already running (e.g. if Tcl_WaitForEvent was
- * called recursively), re-run it in a custom run loop mode containing
- * only the source for the notifier thread, otherwise wakeups from other
- * sources added to the common run loop modes might get lost.
+ * Don't bother to queue an event if the mask was previously non-zero
+ * since an event must still be on the queue.
*/
- if ((runLoopMode = CFRunLoopCopyCurrentMode(tsdPtr->runLoop))) {
- CFRelease(runLoopMode);
- runLoopMode = tclEventsOnlyRunLoopMode;
- } else {
- runLoopMode = kCFRunLoopDefaultMode;
+
+ if (filePtr->readyMask == 0) {
+ FileHandlerEvent *fileEvPtr = (FileHandlerEvent *)
+ ckalloc(sizeof(FileHandlerEvent));
+ fileEvPtr->header.proc = FileHandlerEventProc;
+ fileEvPtr->fd = filePtr->fd;
+ Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
}
- UNLOCK_NOTIFIER;
- CFRunLoopRunInMode(runLoopMode, waitTime, TRUE);
- LOCK_NOTIFIER;
+ filePtr->readyMask = mask;
}
- tsdPtr->eventReady = 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateWaitingListAndServiceEvents --
+ *
+ * CFRunLoopObserver callback for updating waitingList and
+ * servicing Tcl events.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
- if (waitForFiles && tsdPtr->onList) {
- /*
- * Remove the ThreadSpecificData structure of this thread from the
- * waiting list. Alert the notifier thread to recompute its select
- * masks - skipping this caused a hang when trying to close a pipe
- * which the notifier thread was still doing a select on.
- */
+static void
+UpdateWaitingListAndServiceEvents(
+ CFRunLoopObserverRef observer,
+ CFRunLoopActivity activity,
+ void *info)
+{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData*) info;
- if (tsdPtr->prevPtr) {
- tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
+ if (tsdPtr->sleeping) {
+ return;
+ }
+ switch (activity) {
+ case kCFRunLoopEntry:
+ tsdPtr->runLoopNestingLevel++;
+ if (tsdPtr->numFdBits > 0 || tsdPtr->polling) {
+ LOCK_NOTIFIER;
+ if (!OnOffWaitingList(tsdPtr, 1, 1) && tsdPtr->polling) {
+ write(triggerPipe, "", 1);
+ }
+ UNLOCK_NOTIFIER;
+ }
+ break;
+ case kCFRunLoopExit:
+ if (tsdPtr->runLoopNestingLevel == 1) {
+ LOCK_NOTIFIER;
+ OnOffWaitingList(tsdPtr, 0, 1);
+ UNLOCK_NOTIFIER;
+ }
+ tsdPtr->runLoopNestingLevel--;
+ break;
+ case kCFRunLoopBeforeWaiting:
+ if (tsdPtr->runLoopTimer && !tsdPtr->runLoopServicingEvents &&
+ (tsdPtr->runLoopNestingLevel > 1 || !tsdPtr->runLoopRunning)) {
+ tsdPtr->runLoopServicingEvents = 1;
+ while (Tcl_ServiceAll() && tsdPtr->waitTime == 0) {}
+ tsdPtr->runLoopServicingEvents = 0;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * OnOffWaitingList --
+ *
+ * Add/remove the specified thread to/from the global waitingList
+ * and optionally signal the notifier.
+ *
+ * !!! Requires notifierLock to be held !!!
+ *
+ * Results:
+ * Boolean indicating whether the waitingList was changed.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+OnOffWaitingList(
+ ThreadSpecificData *tsdPtr,
+ int onList,
+ int signalNotifier)
+{
+ int changeWaitingList;
+#ifdef TCL_MAC_DEBUG_NOTIFIER
+ if(SpinLockTry(&notifierLock)) {
+ Tcl_Panic("OnOffWaitingList: notifierLock unlocked");
+ }
+#endif
+ changeWaitingList = (!onList ^ !tsdPtr->onList);
+ if (changeWaitingList) {
+ if (onList) {
+ tsdPtr->nextPtr = waitingListPtr;
+ if (waitingListPtr) {
+ waitingListPtr->prevPtr = tsdPtr;
+ }
+ tsdPtr->prevPtr = NULL;
+ waitingListPtr = tsdPtr;
+ tsdPtr->onList = 1;
} else {
- waitingListPtr = tsdPtr->nextPtr;
+ if (tsdPtr->prevPtr) {
+ tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
+ } else {
+ waitingListPtr = tsdPtr->nextPtr;
+ }
+ if (tsdPtr->nextPtr) {
+ tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
+ }
+ tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
+ tsdPtr->onList = 0;
}
- if (tsdPtr->nextPtr) {
- tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
+ if (signalNotifier) {
+ write(triggerPipe, "", 1);
}
- tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
- tsdPtr->onList = 0;
- write(triggerPipe, "", 1);
+ }
+
+ return changeWaitingList;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_Sleep --
+ *
+ * Delay execution for the specified number of milliseconds.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Time passes.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_Sleep(
+ int ms) /* Number of milliseconds to sleep. */
+{
+ Tcl_Time vdelay;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ if (ms <= 0) {
+ return;
}
/*
- * Queue all detected file events before returning.
+ * TIP #233: Scale from virtual time to real-time.
*/
- for (filePtr = tsdPtr->firstFileHandlerPtr; (filePtr != NULL);
- filePtr = filePtr->nextPtr) {
+ vdelay.sec = ms / 1000;
+ vdelay.usec = (ms % 1000) * 1000;
+ tclScaleTimeProcPtr(&vdelay, tclTimeClientData);
- mask = 0;
- if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.readable))) {
- mask |= TCL_READABLE;
+
+ if (tsdPtr->runLoop) {
+ CFTimeInterval waitTime;
+ CFRunLoopTimerRef runLoopTimer = tsdPtr->runLoopTimer;
+ CFAbsoluteTime nextTimerFire = 0, waitEnd, now;
+ SInt32 runLoopStatus;
+
+ waitTime = vdelay.sec + 1.0e-6 * vdelay.usec;
+ now = CFAbsoluteTimeGetCurrent();
+ waitEnd = now + waitTime;
+
+ if (runLoopTimer) {
+ nextTimerFire = CFRunLoopTimerGetNextFireDate(runLoopTimer);
+ if (nextTimerFire < waitEnd) {
+ CFRunLoopTimerSetNextFireDate(runLoopTimer, now +
+ CF_TIMEINTERVAL_FOREVER);
+ } else {
+ runLoopTimer = NULL;
+ }
}
- if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.writable))) {
- mask |= TCL_WRITABLE;
+ tsdPtr->sleeping = 1;
+ do {
+ runLoopStatus = CFRunLoopRunInMode(kCFRunLoopDefaultMode, waitTime,
+ FALSE);
+ switch (runLoopStatus) {
+ case kCFRunLoopRunFinished:
+ Tcl_Panic("Tcl_Sleep: CFRunLoop finished");
+ break;
+ case kCFRunLoopRunStopped:
+ TclMacOSXNotifierDbgMsg("CFRunLoop stopped");
+ waitTime = waitEnd - CFAbsoluteTimeGetCurrent();
+ break;
+ case kCFRunLoopRunTimedOut:
+ waitTime = 0;
+ break;
+ }
+ } while (waitTime > 0);
+ tsdPtr->sleeping = 0;
+ if (runLoopTimer) {
+ CFRunLoopTimerSetNextFireDate(runLoopTimer, nextTimerFire);
}
- if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.exceptional))) {
- mask |= TCL_EXCEPTION;
+ } else {
+ struct timespec waitTime;
+
+ waitTime.tv_sec = vdelay.sec;
+ waitTime.tv_nsec = vdelay.usec * 1000;
+ while (nanosleep(&waitTime, &waitTime));
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclUnixWaitForFile --
+ *
+ * This function waits synchronously for a file to become readable or
+ * writable, with an optional timeout.
+ *
+ * Results:
+ * The return value is an OR'ed combination of TCL_READABLE,
+ * TCL_WRITABLE, and TCL_EXCEPTION, indicating the conditions that are
+ * present on file at the time of the return. This function will not
+ * return until either "timeout" milliseconds have elapsed or at least
+ * one of the conditions given by mask has occurred for file (a return
+ * value of 0 means that a timeout occurred). No normal events will be
+ * serviced during the execution of this function.
+ *
+ * Side effects:
+ * Time passes.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclUnixWaitForFile(
+ int fd, /* Handle for file on which to wait. */
+ int mask, /* What to wait for: OR'ed combination of
+ * TCL_READABLE, TCL_WRITABLE, and
+ * TCL_EXCEPTION. */
+ int timeout) /* Maximum amount of time to wait for one of
+ * the conditions in mask to occur, in
+ * milliseconds. A value of 0 means don't wait
+ * at all, and a value of -1 means wait
+ * forever. */
+{
+ Tcl_Time abortTime = {0, 0}, now; /* silence gcc 4 warning */
+ struct timeval blockTime, *timeoutPtr;
+ int numFound, result = 0;
+ fd_set readableMask;
+ fd_set writableMask;
+ fd_set exceptionalMask;
+
+#define SET_BITS(var, bits) ((var) |= (bits))
+#define CLEAR_BITS(var, bits) ((var) &= ~(bits))
+
+#ifndef _DARWIN_C_SOURCE
+ /*
+ * Sanity check fd.
+ */
+
+ if (fd >= FD_SETSIZE) {
+ Tcl_Panic("TclUnixWaitForFile can't handle file id %d", fd);
+ /* must never get here, or select masks overrun will occur below */
+ }
+#endif
+
+ /*
+ * If there is a non-zero finite timeout, compute the time when we give
+ * up.
+ */
+
+ if (timeout > 0) {
+ Tcl_GetTime(&now);
+ abortTime.sec = now.sec + timeout/1000;
+ abortTime.usec = now.usec + (timeout%1000)*1000;
+ if (abortTime.usec >= 1000000) {
+ abortTime.usec -= 1000000;
+ abortTime.sec += 1;
}
+ timeoutPtr = &blockTime;
+ } else if (timeout == 0) {
+ timeoutPtr = &blockTime;
+ blockTime.tv_sec = 0;
+ blockTime.tv_usec = 0;
+ } else {
+ timeoutPtr = NULL;
+ }
- if (!mask) {
+ /*
+ * Initialize the select masks.
+ */
+
+ FD_ZERO(&readableMask);
+ FD_ZERO(&writableMask);
+ FD_ZERO(&exceptionalMask);
+
+ /*
+ * Loop in a mini-event loop of our own, waiting for either the file to
+ * become ready or a timeout to occur.
+ */
+
+ while (1) {
+ if (timeout > 0) {
+ blockTime.tv_sec = abortTime.sec - now.sec;
+ blockTime.tv_usec = abortTime.usec - now.usec;
+ if (blockTime.tv_usec < 0) {
+ blockTime.tv_sec -= 1;
+ blockTime.tv_usec += 1000000;
+ }
+ if (blockTime.tv_sec < 0) {
+ blockTime.tv_sec = 0;
+ blockTime.tv_usec = 0;
+ }
+ }
+
+ /*
+ * Setup the select masks for the fd.
+ */
+
+ if (mask & TCL_READABLE) {
+ FD_SET(fd, &readableMask);
+ }
+ if (mask & TCL_WRITABLE) {
+ FD_SET(fd, &writableMask);
+ }
+ if (mask & TCL_EXCEPTION) {
+ FD_SET(fd, &exceptionalMask);
+ }
+
+ /*
+ * Wait for the event or a timeout.
+ */
+
+ numFound = select(fd + 1, &readableMask, &writableMask,
+ &exceptionalMask, timeoutPtr);
+ if (numFound == 1) {
+ if (FD_ISSET(fd, &readableMask)) {
+ SET_BITS(result, TCL_READABLE);
+ }
+ if (FD_ISSET(fd, &writableMask)) {
+ SET_BITS(result, TCL_WRITABLE);
+ }
+ if (FD_ISSET(fd, &exceptionalMask)) {
+ SET_BITS(result, TCL_EXCEPTION);
+ }
+ result &= mask;
+ if (result) {
+ break;
+ }
+ }
+ if (timeout == 0) {
+ break;
+ }
+ if (timeout < 0) {
continue;
}
/*
- * Don't bother to queue an event if the mask was previously non-zero
- * since an event must still be on the queue.
+ * The select returned early, so we need to recompute the timeout.
*/
- if (filePtr->readyMask == 0) {
- fileEvPtr = (FileHandlerEvent *) ckalloc(sizeof(FileHandlerEvent));
- fileEvPtr->header.proc = FileHandlerEventProc;
- fileEvPtr->fd = filePtr->fd;
- Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
+ Tcl_GetTime(&now);
+ if ((abortTime.sec < now.sec)
+ || (abortTime.sec==now.sec && abortTime.usec<=now.usec)) {
+ break;
}
- filePtr->readyMask = mask;
}
- UNLOCK_NOTIFIER;
- return 0;
+ return result;
}
/*
@@ -1046,11 +1721,8 @@ NotifierThreadProc(
ClientData clientData) /* Not used. */
{
ThreadSpecificData *tsdPtr;
- fd_set readableMask;
- fd_set writableMask;
- fd_set exceptionalMask;
- int i, numFdBits = 0;
- long found;
+ fd_set readableMask, writableMask, exceptionalMask;
+ int i, numFdBits = 0, polling;
struct timeval poll = {0., 0.}, *timePtr;
char buf[2];
@@ -1068,9 +1740,10 @@ NotifierThreadProc(
* notifiers.
*/
- LOCK_NOTIFIER;
timePtr = NULL;
+ LOCK_NOTIFIER;
for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {
+ LOCK_NOTIFIER_TSD;
for (i = tsdPtr->numFdBits-1; i >= 0; --i) {
if (FD_ISSET(i, &(tsdPtr->checkMasks.readable))) {
FD_SET(i, &readableMask);
@@ -1085,13 +1758,9 @@ NotifierThreadProc(
if (tsdPtr->numFdBits > numFdBits) {
numFdBits = tsdPtr->numFdBits;
}
- if (tsdPtr->pollState & POLL_WANT) {
- /*
- * Here we make sure we go through select() with the same mask
- * bits that were present when the thread tried to poll.
- */
-
- tsdPtr->pollState |= POLL_DONE;
+ polling = tsdPtr->polling;
+ UNLOCK_NOTIFIER_TSD;
+ if ((tsdPtr->polled = polling)) {
timePtr = &poll;
}
}
@@ -1121,48 +1790,53 @@ NotifierThreadProc(
LOCK_NOTIFIER;
for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {
- found = 0;
+ int found = 0;
+ SelectMasks readyMasks, checkMasks;
+
+ LOCK_NOTIFIER_TSD;
+ FD_COPY(&(tsdPtr->checkMasks.readable), &checkMasks.readable);
+ FD_COPY(&(tsdPtr->checkMasks.writable), &checkMasks.writable);
+ FD_COPY(&(tsdPtr->checkMasks.exceptional), &checkMasks.exceptional);
+ UNLOCK_NOTIFIER_TSD;
+ found = tsdPtr->polled;
+ FD_ZERO(&readyMasks.readable);
+ FD_ZERO(&readyMasks.writable);
+ FD_ZERO(&readyMasks.exceptional);
for (i = tsdPtr->numFdBits-1; i >= 0; --i) {
- if (FD_ISSET(i, &(tsdPtr->checkMasks.readable))
+ if (FD_ISSET(i, &checkMasks.readable)
&& FD_ISSET(i, &readableMask)) {
- FD_SET(i, &(tsdPtr->readyMasks.readable));
+ FD_SET(i, &readyMasks.readable);
found = 1;
}
- if (FD_ISSET(i, &(tsdPtr->checkMasks.writable))
+ if (FD_ISSET(i, &checkMasks.writable)
&& FD_ISSET(i, &writableMask)) {
- FD_SET(i, &(tsdPtr->readyMasks.writable));
+ FD_SET(i, &readyMasks.writable);
found = 1;
}
- if (FD_ISSET(i, &(tsdPtr->checkMasks.exceptional))
+ if (FD_ISSET(i, &checkMasks.exceptional)
&& FD_ISSET(i, &exceptionalMask)) {
- FD_SET(i, &(tsdPtr->readyMasks.exceptional));
+ FD_SET(i, &readyMasks.exceptional);
found = 1;
}
}
- if (found || (tsdPtr->pollState & POLL_DONE)) {
- tsdPtr->eventReady = 1;
- if (tsdPtr->onList) {
- /*
- * Remove the ThreadSpecificData structure of this thread
- * from the waiting list. This prevents us from
- * continuously spining on select until the other threads
- * runs and services the file event.
- */
-
- if (tsdPtr->prevPtr) {
- tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
- } else {
- waitingListPtr = tsdPtr->nextPtr;
- }
- if (tsdPtr->nextPtr) {
- tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
- }
- tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
- tsdPtr->onList = 0;
- tsdPtr->pollState = 0;
- }
+ if (found) {
+ /*
+ * Remove the ThreadSpecificData structure of this thread from
+ * the waiting list. This prevents us from spinning
+ * continuously on select until the other threads runs and
+ * services the file event.
+ */
+
+ OnOffWaitingList(tsdPtr, 0, 0);
+
+ LOCK_NOTIFIER_TSD;
+ FD_COPY(&readyMasks.readable, &(tsdPtr->readyMasks.readable));
+ FD_COPY(&readyMasks.writable, &(tsdPtr->readyMasks.writable));
+ FD_COPY(&readyMasks.exceptional, &(tsdPtr->readyMasks.exceptional));
+ UNLOCK_NOTIFIER_TSD;
+ tsdPtr->polled = 0;
if (tsdPtr->runLoop) {
CFRunLoopSourceSignal(tsdPtr->runLoopSource);
CFRunLoopWakeUp(tsdPtr->runLoop);
@@ -1214,8 +1888,11 @@ NotifierThreadProc(
static void
AtForkPrepare(void)
{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
LOCK_NOTIFIER_INIT;
LOCK_NOTIFIER;
+ LOCK_NOTIFIER_TSD;
}
/*
@@ -1237,6 +1914,9 @@ AtForkPrepare(void)
static void
AtForkParent(void)
{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ UNLOCK_NOTIFIER_TSD;
UNLOCK_NOTIFIER;
UNLOCK_NOTIFIER_INIT;
}
@@ -1262,18 +1942,25 @@ AtForkChild(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ UNLOCK_NOTIFIER_TSD;
UNLOCK_NOTIFIER;
UNLOCK_NOTIFIER_INIT;
if (tsdPtr->runLoop) {
tsdPtr->runLoop = NULL;
if (!noCFafterFork) {
CFRunLoopSourceInvalidate(tsdPtr->runLoopSource);
+ CFRelease(tsdPtr->runLoopSource);
+ if (tsdPtr->runLoopTimer) {
+ CFRunLoopTimerInvalidate(tsdPtr->runLoopTimer);
+ CFRelease(tsdPtr->runLoopTimer);
+ }
}
- CFRelease(tsdPtr->runLoopSource);
tsdPtr->runLoopSource = NULL;
+ tsdPtr->runLoopTimer = NULL;
}
if (notifierCount > 0) {
- notifierCount = 0;
+ notifierCount = 1;
+ notifierThreadRunning = 0;
/*
* Assume that the return value of Tcl_InitNotifier in the child will
@@ -1291,4 +1978,22 @@ AtForkChild(void)
}
#endif /* HAVE_PTHREAD_ATFORK */
+#else /* HAVE_COREFOUNDATION */
+
+void
+TclMacOSXNotifierAddRunLoopMode(
+ CONST void *runLoopMode)
+{
+ Tcl_Panic("TclMacOSXNotifierAddRunLoopMode: "
+ "Tcl not built with CoreFoundation support");
+}
+
#endif /* HAVE_COREFOUNDATION */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tests/all.tcl b/tests/all.tcl
index db811a7..d01a54d 100644
--- a/tests/all.tcl
+++ b/tests/all.tcl
@@ -10,14 +10,8 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-set tcltestVersion [package require tcltest]
-namespace import -force tcltest::*
-
-if {$tcl_platform(platform) == "macintosh"} {
- tcltest::singleProcess 1
-}
-
-tcltest::testsDirectory [file dir [info script]]
-tcltest::runAllTests
-
-return
+package require Tcl 8.5
+package require tcltest 2.2
+namespace import tcltest::*
+configure {*}$argv -testdir [file dir [info script]]
+runAllTests
diff --git a/tests/append.test b/tests/append.test
index 6e70f8c..caf6210 100644
--- a/tests/append.test
+++ b/tests/append.test
@@ -141,7 +141,7 @@ test append-4.20 {lappend command} {
catch {unset x}
lappend x(0) abc
} {abc}
-unset x
+unset -nocomplain x
test append-4.21 {lappend command} {
set x \"
list [catch {lappend x} msg] $msg
@@ -229,8 +229,6 @@ test append-7.5 {append var does not trigger read trace} {
info exists ::result
} {0}
-
-
# New tests for bug 3057639 to show off the more consistent behaviour
# of lappend in both direct-eval and bytecompiled code paths (see
# appendComp.test for the compiled variants). lappend now behaves like
@@ -281,6 +279,7 @@ test append-9.3 {bug 3057639, append direct eval, read trace on non-existing env
} {0 {new value}}
+
catch {unset i x result y}
catch {rename foo ""}
catch {rename check ""}
diff --git a/tests/appendComp.test b/tests/appendComp.test
index f2a9ebf..14e9567 100644
--- a/tests/appendComp.test
+++ b/tests/appendComp.test
@@ -12,7 +12,7 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2
namespace import -force ::tcltest::*
}
catch {unset x}
@@ -349,6 +349,21 @@ test appendComp-7.9 {append var does not trigger read trace} {
bar
} {0}
+test appendComp-8.1 {defer error to runtime} -setup {
+ interp create slave
+} -body {
+ slave eval {
+ proc foo {} {
+ proc append args {}
+ append
+ }
+ foo
+ }
+} -cleanup {
+ interp delete slave
+} -result {}
+
+
# New tests for bug 3057639 to show off the more consistent behaviour
# of lappend in both direct-eval and bytecompiled code paths (see
# append.test for the direct-eval variants). lappend now behaves like
@@ -416,6 +431,10 @@ test appendComp-9.3 {bug 3057639, append direct eval, read trace on non-existing
list [catch { foo } msg] $msg
} {0 {new value}}
+
+
+
+
catch {unset i x result y}
catch {rename foo ""}
catch {rename bar ""}
diff --git a/tests/apply.test b/tests/apply.test
new file mode 100644
index 0000000..31fe918
--- /dev/null
+++ b/tests/apply.test
@@ -0,0 +1,324 @@
+# Commands covered: apply
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands. Sourcing this file into Tcl runs the tests and
+# generates output for errors. No output means no errors were found.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1994-1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# Copyright (c) 2005-2006 Miguel Sofer
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+if {[lsearch [namespace children] ::tcltest] == -1} {
+ package require tcltest 2.2
+ namespace import -force ::tcltest::*
+}
+
+if {[info commands ::apply] eq {}} {
+ return
+}
+
+testConstraint memory [llength [info commands memory]]
+
+# Tests for wrong number of arguments
+
+test apply-1.1 {too few arguments} {
+ set res [catch apply msg]
+ list $res $msg
+} {1 {wrong # args: should be "apply lambdaExpr ?arg1 arg2 ...?"}}
+
+# Tests for malformed lambda
+
+test apply-2.0 {malformed lambda} {
+ set lambda a
+ set res [catch {apply $lambda} msg]
+ list $res $msg
+} {1 {can't interpret "a" as a lambda expression}}
+test apply-2.1 {malformed lambda} {
+ set lambda [list a b c d]
+ set res [catch {apply $lambda} msg]
+ list $res $msg
+} {1 {can't interpret "a b c d" as a lambda expression}}
+test apply-2.2 {malformed lambda} {
+ set lambda [list {{}} boo]
+ set res [catch {apply $lambda} msg]
+ list $res $msg $::errorInfo
+} {1 {argument with no name} {argument with no name
+ (parsing lambda expression "{{}} boo")
+ invoked from within
+"apply $lambda"}}
+test apply-2.3 {malformed lambda} {
+ set lambda [list {{a b c}} boo]
+ set res [catch {apply $lambda} msg]
+ list $res $msg $::errorInfo
+} {1 {too many fields in argument specifier "a b c"} {too many fields in argument specifier "a b c"
+ (parsing lambda expression "{{a b c}} boo")
+ invoked from within
+"apply $lambda"}}
+test apply-2.4 {malformed lambda} {
+ set lambda [list a(1) boo]
+ set res [catch {apply $lambda} msg]
+ list $res $msg $::errorInfo
+} {1 {formal parameter "a(1)" is an array element} {formal parameter "a(1)" is an array element
+ (parsing lambda expression "a(1) boo")
+ invoked from within
+"apply $lambda"}}
+test apply-2.5 {malformed lambda} {
+ set lambda [list a::b boo]
+ set res [catch {apply $lambda} msg]
+ list $res $msg $::errorInfo
+} {1 {formal parameter "a::b" is not a simple name} {formal parameter "a::b" is not a simple name
+ (parsing lambda expression "a::b boo")
+ invoked from within
+"apply $lambda"}}
+
+# Tests for runtime errors in the lambda expression
+
+test apply-3.1 {non-existing namespace} -body {
+ apply [list x {set x 1} ::NONEXIST::FOR::SURE] x
+} -returnCodes error -result {namespace "::NONEXIST::FOR::SURE" not found}
+test apply-3.2 {non-existing namespace} -body {
+ namespace eval ::NONEXIST::FOR::SURE {}
+ set lambda [list x {set x 1} ::NONEXIST::FOR::SURE]
+ apply $lambda x
+ namespace delete ::NONEXIST
+ apply $lambda x
+} -returnCodes error -result {namespace "::NONEXIST::FOR::SURE" not found}
+test apply-3.3 {non-existing namespace} -body {
+ apply [list x {set x 1} NONEXIST::FOR::SURE] x
+} -returnCodes error -result {namespace "::NONEXIST::FOR::SURE" not found}
+test apply-3.4 {non-existing namespace} -body {
+ namespace eval ::NONEXIST::FOR::SURE {}
+ set lambda [list x {set x 1} NONEXIST::FOR::SURE]
+ apply $lambda x
+ namespace delete ::NONEXIST
+ apply $lambda x
+} -returnCodes error -result {namespace "::NONEXIST::FOR::SURE" not found}
+
+test apply-4.1 {error in arguments to lambda expression} {
+ set lambda [list x {set x 1}]
+ set res [catch {apply $lambda} msg]
+ list $res $msg
+} {1 {wrong # args: should be "apply lambdaExpr x"}}
+test apply-4.2 {error in arguments to lambda expression} {
+ set lambda [list x {set x 1}]
+ set res [catch {apply $lambda a b} msg]
+ list $res $msg
+} {1 {wrong # args: should be "apply lambdaExpr x"}}
+test apply-4.3 {error in arguments to lambda expression} {
+ set lambda [list x {set x 1}]
+ interp alias {} foo {} ::apply $lambda
+ set res [catch {foo a b} msg]
+ list $res $msg [rename foo {}]
+} {1 {wrong # args: should be "foo x"} {}}
+test apply-4.4 {error in arguments to lambda expression} {
+ set lambda [list x {set x 1}]
+ interp alias {} foo {} ::apply $lambda a
+ set res [catch {foo b} msg]
+ list $res $msg [rename foo {}]
+} {1 {wrong # args: should be "foo"} {}}
+test apply-4.5 {error in arguments to lambda expression} {
+ set lambda [list x {set x 1}]
+ namespace eval a {
+ namespace ensemble create -command ::bar -map {id {::a::const foo}}
+ proc const val { return $val }
+ proc alias {object slot = command args} {
+ set map [namespace ensemble configure $object -map]
+ dict set map $slot [linsert $args 0 $command]
+ namespace ensemble configure $object -map $map
+ }
+ proc method {object name params body} {
+ set params [linsert $params 0 self]
+ alias $object $name = ::apply [list $params $body] $object
+ }
+ method ::bar boo x {return "[expr {$x*$x}] - $self"}
+ }
+ set res [catch {bar boo} msg]
+ list $res $msg [namespace delete ::a]
+} {1 {wrong # args: should be "bar boo x"} {}}
+
+test apply-5.1 {runtime error in lambda expression} {
+ set lambda [list {} {error foo}]
+ set res [catch {apply $lambda}]
+ list $res $::errorInfo
+} {1 {foo
+ while executing
+"error foo"
+ (lambda term "{} {error foo}" line 1)
+ invoked from within
+"apply $lambda"}}
+
+# Tests for correct execution; as the implementation is the same as that for
+# procs, the general functionality is mostly tested elsewhere
+
+test apply-6.1 {info level} {
+ set lev [info level]
+ set lambda [list {} {info level}]
+ expr {[apply $lambda] - $lev}
+} 1
+test apply-6.2 {info level} {
+ set lambda [list {} {info level 0}]
+ apply $lambda
+} {apply {{} {info level 0}}}
+test apply-6.3 {info level} {
+ set lambda [list args {info level 0}]
+ apply $lambda x y
+} {apply {args {info level 0}} x y}
+
+# Tests for correct namespace scope
+
+namespace eval ::testApply {
+ proc testApply args {return testApply}
+}
+
+test apply-7.1 {namespace access} {
+ set ::testApply::x 0
+ set body {set x 1; set x}
+ list [apply [list args $body ::testApply]] $::testApply::x
+} {1 0}
+test apply-7.2 {namespace access} {
+ set ::testApply::x 0
+ set body {variable x; set x}
+ list [apply [list args $body ::testApply]] $::testApply::x
+} {0 0}
+test apply-7.3 {namespace access} {
+ set ::testApply::x 0
+ set body {variable x; set x 1}
+ list [apply [list args $body ::testApply]] $::testApply::x
+} {1 1}
+test apply-7.4 {namespace access} {
+ set ::testApply::x 0
+ set body {testApply}
+ apply [list args $body ::testApply]
+} testApply
+test apply-7.5 {namespace access} {
+ set ::testApply::x 0
+ set body {set x 1; set x}
+ list [apply [list args $body testApply]] $::testApply::x
+} {1 0}
+test apply-7.6 {namespace access} {
+ set ::testApply::x 0
+ set body {variable x; set x}
+ list [apply [list args $body testApply]] $::testApply::x
+} {0 0}
+test apply-7.7 {namespace access} {
+ set ::testApply::x 0
+ set body {variable x; set x 1}
+ list [apply [list args $body testApply]] $::testApply::x
+} {1 1}
+test apply-7.8 {namespace access} {
+ set ::testApply::x 0
+ set body {testApply}
+ apply [list args $body testApply]
+} testApply
+
+# Tests for correct argument treatment
+
+set applyBody {
+ set res {}
+ foreach v [info locals] {
+ if {$v eq "res"} continue
+ lappend res [list $v [set $v]]
+ }
+ set res
+}
+
+test apply-8.1 {args treatment} {
+ apply [list args $applyBody] 1 2 3
+} {{args {1 2 3}}}
+test apply-8.2 {args treatment} {
+ apply [list {x args} $applyBody] 1 2
+} {{x 1} {args 2}}
+test apply-8.3 {args treatment} {
+ apply [list {x args} $applyBody] 1 2 3
+} {{x 1} {args {2 3}}}
+test apply-8.4 {default values} {
+ apply [list {{x 1} {y 2}} $applyBody]
+} {{x 1} {y 2}}
+test apply-8.5 {default values} {
+ apply [list {{x 1} {y 2}} $applyBody] 3 4
+} {{x 3} {y 4}}
+test apply-8.6 {default values} {
+ apply [list {{x 1} {y 2}} $applyBody] 3
+} {{x 3} {y 2}}
+test apply-8.7 {default values} {
+ apply [list {x {y 2}} $applyBody] 1
+} {{x 1} {y 2}}
+test apply-8.8 {default values} {
+ apply [list {x {y 2}} $applyBody] 1 3
+} {{x 1} {y 3}}
+test apply-8.9 {default values} {
+ apply [list {x {y 2} args} $applyBody] 1
+} {{x 1} {y 2} {args {}}}
+test apply-8.10 {default values} {
+ apply [list {x {y 2} args} $applyBody] 1 3
+} {{x 1} {y 3} {args {}}}
+
+# Tests for leaks
+
+test apply-9.1 {leaking internal rep} -setup {
+ proc getbytes {} {
+ set lines [split [memory info] "\n"]
+ lindex $lines 3 3
+ }
+ set lam [list {} {set a 1}]
+} -constraints memory -body {
+ set end [getbytes]
+ for {set i 0} {$i < 5} {incr i} {
+ ::apply [lrange $lam 0 end]
+ set tmp $end
+ set end [getbytes]
+ }
+ set leakedBytes [expr {$end - $tmp}]
+} -cleanup {
+ rename getbytes {}
+ unset -nocomplain lam end i tmp leakedBytes
+} -result 0
+test apply-9.2 {leaking internal rep} -setup {
+ proc getbytes {} {
+ set lines [split [memory info] "\n"]
+ lindex $lines 3 3
+ }
+} -constraints memory -body {
+ set end [getbytes]
+ for {set i 0} {$i < 5} {incr i} {
+ ::apply [list {} {set a 1}]
+ set tmp $end
+ set end [getbytes]
+ }
+ set leakedBytes [expr {$end - $tmp}]
+} -cleanup {
+ rename getbytes {}
+ unset -nocomplain end i tmp leakedBytes
+} -result 0
+test apply-9.3 {leaking internal rep} -setup {
+ proc getbytes {} {
+ set lines [split [memory info] "\n"]
+ lindex $lines 3 3
+ }
+} -constraints memory -body {
+ set end [getbytes]
+ for {set i 0} {$i < 5} {incr i} {
+ set x [list {} {set a 1} ::NS::THAT::DOES::NOT::EXIST]
+ catch {::apply $x}
+ set x {}
+ set tmp $end
+ set end [getbytes]
+ }
+ set leakedBytes [expr {$end - $tmp}]
+} -cleanup {
+ rename getbytes {}
+ unset -nocomplain end i x tmp leakedBytes
+} -result 0
+
+# Tests for the avoidance of recompilation
+
+# cleanup
+
+namespace delete testApply
+
+::tcltest::cleanupTests
+return
diff --git a/tests/assocd.test b/tests/assocd.test
index 7bcf601..1ca1c9b 100644
--- a/tests/assocd.test
+++ b/tests/assocd.test
@@ -16,61 +16,46 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-if {[string compare testsetassocdata [info commands testsetassocdata]] != 0} {
- puts "This application hasn't been compiled with the tests for assocData,"
- puts "therefore I am skipping all of these tests."
- ::tcltest::cleanupTests
- return
-}
+testConstraint testgetassocdata [llength [info commands testgetassocdata]]
+testConstraint testsetassocdata [llength [info commands testsetassocdata]]
+testConstraint testdelassocdata [llength [info commands testdelassocdata]]
-test assocd-1.1 {testing setting assoc data} {
+test assocd-1.1 {testing setting assoc data} testsetassocdata {
testsetassocdata a 1
} ""
-test assocd-1.2 {testing setting assoc data} {
+test assocd-1.2 {testing setting assoc data} testsetassocdata {
testsetassocdata a 2
} ""
-test assocd-1.3 {testing setting assoc data} {
+test assocd-1.3 {testing setting assoc data} testsetassocdata {
testsetassocdata 123 456
} ""
-test assocd-1.4 {testing setting assoc data} {
+test assocd-1.4 {testing setting assoc data} testsetassocdata {
testsetassocdata abc "abc d e f"
} ""
-test assocd-2.1 {testing getting assoc data} {
+test assocd-2.1 {testing getting assoc data} testgetassocdata {
testgetassocdata a
} 2
-test assocd-2.2 {testing getting assoc data} {
+test assocd-2.2 {testing getting assoc data} testgetassocdata {
testgetassocdata 123
} 456
-test assocd-2.3 {testing getting assoc data} {
+test assocd-2.3 {testing getting assoc data} testgetassocdata {
testgetassocdata abc
} {abc d e f}
-test assocd-2.4 {testing getting assoc data} {
+test assocd-2.4 {testing getting assoc data} testgetassocdata {
testgetassocdata xxx
} ""
-test assocd-3.1 {testing deleting assoc data} {
+test assocd-3.1 {testing deleting assoc data} testdelassocdata {
testdelassocdata a
} ""
-test assocd-3.2 {testing deleting assoc data} {
+test assocd-3.2 {testing deleting assoc data} testdelassocdata {
testdelassocdata 123
} ""
-test assocd-3.3 {testing deleting assoc data} {
+test assocd-3.3 {testing deleting assoc data} testdelassocdata {
list [catch {testdelassocdata nonexistent} msg] $msg
} {0 {}}
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/async.test b/tests/async.test
index b0582fc..f89413f 100644
--- a/tests/async.test
+++ b/tests/async.test
@@ -16,12 +16,10 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-if {[info commands testasync] == {}} {
- puts "This application hasn't been compiled with the \"testasync\""
- puts "command, so I can't test Tcl_AsyncCreate et al."
- ::tcltest::cleanupTests
- return
-}
+testConstraint testasync [llength [info commands testasync]]
+testConstraint threaded [expr {
+ [info exists ::tcl_platform(threaded)] && $::tcl_platform(threaded)
+}]
proc async1 {result code} {
global aresult acode
@@ -40,55 +38,68 @@ proc async3 {result code} {
set aresult "test pattern"
return -code $code $result
}
+proc \# {result code} {
+ global aresult acode
+ set aresult $result
+ set acode $code
+ return "comment quoting"
+}
-set handler1 [testasync create async1]
-set handler2 [testasync create async2]
-set handler3 [testasync create async3]
-test async-1.1 {basic async handlers} {
+if {[testConstraint testasync]} {
+ set handler1 [testasync create async1]
+ set handler2 [testasync create async2]
+ set handler3 [testasync create async3]
+ set handler4 [testasync create \#]
+}
+test async-1.1 {basic async handlers} testasync {
set aresult xxx
set acode yyy
list [catch {testasync mark $handler1 "original" 0} msg] $msg \
$acode $aresult
} {0 {new result} 0 original}
-test async-1.2 {basic async handlers} {
+test async-1.2 {basic async handlers} testasync {
set aresult xxx
set acode yyy
list [catch {testasync mark $handler1 "original" 1} msg] $msg \
$acode $aresult
} {0 {new result} 1 original}
-test async-1.3 {basic async handlers} {
+test async-1.3 {basic async handlers} testasync {
set aresult xxx
set acode yyy
list [catch {testasync mark $handler2 "old" 0} msg] $msg \
$acode $aresult
} {1 xyzzy 0 old}
-test async-1.4 {basic async handlers} {
+test async-1.4 {basic async handlers} testasync {
set aresult xxx
set acode yyy
list [catch {testasync mark $handler2 "old" 3} msg] $msg \
$acode $aresult
} {1 xyzzy 3 old}
-test async-1.5 {basic async handlers} {
+test async-1.5 {basic async handlers} testasync {
set aresult xxx
list [catch {testasync mark $handler3 "foobar" 0} msg] $msg $aresult
} {0 foobar {test pattern}}
-test async-1.6 {basic async handlers} {
+test async-1.6 {basic async handlers} testasync {
set aresult xxx
list [catch {testasync mark $handler3 "foobar" 1} msg] $msg $aresult
} {1 foobar {test pattern}}
+test async-1.7 {basic async handlers} testasync {
+ set aresult xxx
+ set acode yyy
+ list [catch {testasync mark $handler4 "original" 0} msg] $msg \
+ $acode $aresult
+} {0 {comment quoting} 0 original}
proc mult1 {result code} {
global x
lappend x mult1
return -code 7 mult1
}
-set hm1 [testasync create mult1]
proc mult2 {result code} {
global x
lappend x mult2
return -code 9 mult2
}
-set hm2 [testasync create mult2]
proc mult3 {result code} {
global x hm1 hm2
lappend x [catch {testasync mark $hm2 serial2 0}]
@@ -96,9 +107,12 @@ proc mult3 {result code} {
lappend x mult3
return -code 11 mult3
}
-set hm3 [testasync create mult3]
-
-test async-2.1 {multiple handlers} {
+if {[testConstraint testasync]} {
+ set hm1 [testasync create mult1]
+ set hm2 [testasync create mult2]
+ set hm3 [testasync create mult3]
+}
+test async-2.1 {multiple handlers} testasync {
set x {}
list [catch {testasync mark $hm3 "foobar" 5} msg] $msg $x
} {9 mult2 {0 0 mult3 mult1 mult2}}
@@ -119,31 +133,87 @@ proc del2 {result code} {
lappend x del2
return -code 3 del2
}
-testasync delete $handler1
-testasync delete $hm2
-testasync delete $hm3
-set hm2 [testasync create del1]
-set hm3 [testasync create mult2]
-set hm4 [testasync create del2]
+if {[testConstraint testasync]} {
+ testasync delete $handler1
+ testasync delete $hm2
+ testasync delete $hm3
+ set hm2 [testasync create del1]
+ set hm3 [testasync create mult2]
+ set hm4 [testasync create del2]
+}
-test async-3.1 {deleting handlers} {
+test async-3.1 {deleting handlers} testasync {
set x {}
list [catch {testasync mark $hm2 "foobar" 5} msg] $msg $x
} {3 del2 {0 0 0 del1 del2}}
+proc nothing {} {
+ # empty proc
+}
+proc hang1 {handle} {
+ global aresult
+ set aresult {Async event not delivered}
+ testasync marklater $handle
+ for {set i 0} {
+ $i < 2500000 && $aresult eq "Async event not delivered"
+ } {incr i} {
+ nothing
+ }
+ return $aresult
+}
+proc hang2 {handle} {
+ global aresult
+ set aresult {Async event not delivered}
+ testasync marklater $handle
+ for {set i 0} {
+ $i < 2500000 && $aresult eq "Async event not delivered"
+ } {incr i} {}
+ return $aresult
+}
+proc hang3 {handle} [concat {
+ global aresult
+ set aresult {Async event not delivered}
+ testasync marklater $handle
+ set i 0
+} [string repeat {;incr i;} 1500000] {
+ return $aresult
+}]
+
+test async-4.1 {async interrupting bytecode sequence} -constraints {
+ testasync threaded
+} -setup {
+ set hm [testasync create async3]
+} -body {
+ hang1 $hm
+} -result {test pattern} -cleanup {
+ testasync delete $hm
+}
+test async-4.2 {async interrupting straight bytecode sequence} -constraints {
+ testasync threaded
+} -setup {
+ set hm [testasync create async3]
+} -body {
+ hang2 $hm
+} -result {test pattern} -cleanup {
+ testasync delete $hm
+}
+test async-4.3 {async interrupting loop-less bytecode sequence} -constraints {
+ testasync threaded
+} -setup {
+ set hm [testasync create async3]
+} -body {
+ hang3 $hm
+} -result {test pattern} -cleanup {
+ testasync delete $hm
+}
+
# cleanup
-testasync delete
+if {[testConstraint testasync]} {
+ testasync delete
+}
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/basic.test b/tests/basic.test
index e769a00..318e5c4 100644
--- a/tests/basic.test
+++ b/tests/basic.test
@@ -18,16 +18,11 @@
package require tcltest 2
namespace import -force ::tcltest::*
+testConstraint testevalex [llength [info commands testevalex]]
testConstraint testcmdtoken [llength [info commands testcmdtoken]]
-testConstraint testcmdtrace [llength [info commands testcmdtrace]]
testConstraint testcreatecommand [llength [info commands testcreatecommand]]
-testConstraint testevalex [llength [info commands testevalex]]
testConstraint exec [llength [info commands exec]]
-# This variable needs to be changed when the major or minor version number for
-# Tcl changes.
-set tclvers 8.4
-
catch {namespace delete test_ns_basic}
catch {interp delete test_interp}
catch {rename p ""}
@@ -157,7 +152,7 @@ test basic-12.2 {Tcl_HideCommand, a hidden cmd remembers its containing namespac
[namespace delete test_ns_basic]
} {:: {} 1 {invalid command name "cmd"} {} :: {}}
-test basic-13.1 {Tcl_ExposeCommand, a command stays in the global namespace and can not go to another namespace} {
+test basic-13.1 {Tcl_ExposeCommand, a command stays in the global namespace and cannot go to another namespace} {
catch {namespace delete test_ns_basic}
catch {rename cmd ""}
proc cmd {} { ;# note that this is global
@@ -184,7 +179,7 @@ test basic-13.1 {Tcl_ExposeCommand, a command stays in the global namespace and
[test_ns_basic::exposeCmdWorkAround] \
[test_ns_basic::newCmd] \
[namespace delete test_ns_basic]
-} {:: {} 1 {can not expose to a namespace (use expose to toplevel, then rename)} {} ::test_ns_basic {}}
+} {:: {} 1 {cannot expose to a namespace (use expose to toplevel, then rename)} {} ::test_ns_basic {}}
test basic-13.2 {Tcl_ExposeCommand, invalidate cached refs to cmd now being exposed} {
catch {rename p ""}
catch {rename cmd ""}
@@ -204,13 +199,13 @@ test basic-13.2 {Tcl_ExposeCommand, invalidate cached refs to cmd now being expo
} {42 {} {} Hello {} {} 42}
test basic-14.1 {Tcl_CreateCommand, new cmd goes into a namespace specified in its name, if any} {testcreatecommand} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
list [testcreatecommand create] \
[test_ns_basic::createdcommand] \
[testcreatecommand delete]
} {{} {CreatedCommandProc in ::test_ns_basic} {}}
test basic-14.2 {Tcl_CreateCommand, namespace code ignore single ":"s in middle or end of names} {testcreatecommand} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {rename value:at: ""}
list [testcreatecommand create2] \
[value:at:] \
@@ -218,7 +213,7 @@ test basic-14.2 {Tcl_CreateCommand, namespace code ignore single ":"s in middle
} {{} {CreatedCommandProc2 in ::} {}}
test basic-15.1 {Tcl_CreateObjCommand, new cmd goes into a namespace specified in its name, if any} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_basic {}
proc test_ns_basic::cmd {} { ;# proc requires that ns already exist
return [namespace current]
@@ -234,7 +229,7 @@ test basic-17.1 {TclInvokeObjCommand} {emptyTest} {
} {}
test basic-18.1 {TclRenameCommand, name of existing cmd can have namespace qualifiers} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {rename cmd ""}
namespace eval test_ns_basic {
proc p {} {
@@ -246,11 +241,11 @@ test basic-18.1 {TclRenameCommand, name of existing cmd can have namespace quali
[test_ns_basic::q]
} {{p in ::test_ns_basic} {} {p in ::test_ns_basic}}
test basic-18.2 {TclRenameCommand, existing cmd must be found} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
list [catch {rename test_ns_basic::p test_ns_basic::q} msg] $msg
} {1 {can't rename "test_ns_basic::p": command doesn't exist}}
test basic-18.3 {TclRenameCommand, delete cmd if new name is empty} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_basic {
proc p {} {
return "p in [namespace current]"
@@ -261,7 +256,7 @@ test basic-18.3 {TclRenameCommand, delete cmd if new name is empty} {
[info commands test_ns_basic::*]
} {::test_ns_basic::p {} {}}
test basic-18.4 {TclRenameCommand, bad new name} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_basic {
proc p {} {
return "p in [namespace current]"
@@ -278,7 +273,7 @@ test basic-18.5 {TclRenameCommand, new name must not already exist} {
list [catch {rename test_ns_basic::q :::george::martha} msg] $msg
} {1 {can't rename to ":::george::martha": command already exists}}
test basic-18.6 {TclRenameCommand, check for command shadowing by newly renamed cmd} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {rename p ""}
catch {rename q ""}
proc p {} {
@@ -301,7 +296,7 @@ test basic-19.1 {Tcl_SetCommandInfo} {emptyTest} {
} {}
test basic-20.1 {Tcl_GetCommandInfo, names for commands created inside namespaces} {testcmdtoken} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {rename p ""}
catch {rename q ""}
catch {unset x}
@@ -320,12 +315,17 @@ test basic-20.2 {Tcl_GetCommandInfo, names for commands created outside namespac
[rename test_ns_basic::test_ns_basic2::p q] \
[testcmdtoken name $x]
} {{p ::test_ns_basic::test_ns_basic2::p} {} {q ::q}}
+test basic-20.3 {Tcl_GetCommandInfo, #-quoting} testcmdtoken {
+ catch {rename \# ""}
+ set x [testcmdtoken create \#]
+ testcmdtoken name $x
+} {{#} ::#}
test basic-21.1 {Tcl_GetCommandName} {emptyTest} {
} {}
test basic-22.1 {Tcl_GetCommandFullName} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_basic1 {
namespace export cmd*
proc cmd1 {} {}
@@ -371,7 +371,7 @@ test basic-24.1 {Tcl_DeleteCommandFromToken, invalidate all compiled code if cmd
[interp delete test_interp]
} {123 {set called with a 123} {}}
test basic-24.2 {Tcl_DeleteCommandFromToken, deleting commands changes command epoch} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {rename p ""}
proc p {} {
return "global p"
@@ -389,7 +389,7 @@ test basic-24.2 {Tcl_DeleteCommandFromToken, deleting commands changes command e
[test_ns_basic::callP]
} {{namespace p} {} {global p}}
test basic-24.3 {Tcl_DeleteCommandFromToken, delete imported cmds that refer to a deleted cmd} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {rename p ""}
namespace eval test_ns_basic {
namespace export p
@@ -411,31 +411,38 @@ test basic-24.3 {Tcl_DeleteCommandFromToken, delete imported cmds that refer to
test basic-25.1 {TclCleanupCommand} {emptyTest} {
} {}
-test basic-26.1 {Tcl_EvalObj: preserve object while evaling it} {
+test basic-26.1 {Tcl_EvalObj: preserve object while evaling it} -setup {
+ proc myHandler {msg options} {
+ set ::x [dict get $options -errorinfo]
+ }
+ set handler [interp bgerror {}]
+ interp bgerror {} [namespace which myHandler]
+ set fName [makeFile {} test1]
+} -body {
# If object isn't preserved, errorInfo would be set to
# "foo\n while executing\n\"garbage bytes\"" because the object's
# string would have been freed, leaving garbage bytes for the error
# message.
-
- proc bgerror {args} {set ::x $::errorInfo}
- set fName [makeFile {} test1]
set f [open $fName w]
fileevent $f writable "fileevent $f writable {}; error foo"
set x {}
vwait x
close $f
- removeFile test1
- rename bgerror {}
set x
-} "foo\n while executing\n\"error foo\""
+} -cleanup {
+ removeFile test1
+ interp bgerror {} $handler
+ rename myHandler {}
+} -result "foo\n while executing\n\"error foo\""
-test basic-26.2 {Tcl_EvalObjEx, pure-list branch: preserve "objv"} {
+test basic-26.2 {Tcl_EvalObjEx, pure-list branch: preserve "objv"} -body {
#
# Follow the pure-list branch in a manner that
# a - the pure-list internal rep is destroyed by shimmering
# b - the command returns an error
# As the error code in Tcl_EvalObjv accesses the list elements, this will
- # cause a segfault if [Bug 1119369] has not been fixed.
+ # cause a segfault if [Bug 1119369] has not been fixed.
+ # NOTE: a MEM_DEBUG build may be necessary to guarantee the segfault.
#
set SRC [list foo 1] ;# pure-list command
@@ -445,7 +452,33 @@ test basic-26.2 {Tcl_EvalObjEx, pure-list branch: preserve "objv"} {
error "BAD CALL"
}
catch {eval $SRC}
-} 1
+} -result 1 -cleanup {
+ rename foo {}
+ rename $::SRC {}
+ unset ::SRC
+}
+
+test basic-26.3 {Tcl_EvalObjEx, pure-list branch: preserve "objv"} -body {
+ #
+ # Follow the pure-list branch in a manner that
+ # a - the pure-list internal rep is destroyed by shimmering
+ # b - the command accesses its command line
+ # This will cause a segfault if [Bug 1119369] has not been fixed.
+ # NOTE: a MEM_DEBUG build may be necessary to guarantee the segfault.
+ #
+
+ set SRC [list foo 1] ;# pure-list command
+ proc foo str {
+ # Shimmer pure-list to cmdName, cleanup and error
+ proc $::SRC {} {}; $::SRC
+ info level 0
+ }
+ catch {eval $SRC}
+} -result 0 -cleanup {
+ rename foo {}
+ rename $::SRC {}
+ unset ::SRC
+}
test basic-27.1 {Tcl_ExprLong} {emptyTest} {
} {}
@@ -465,17 +498,8 @@ test basic-31.1 {Tcl_ExprDoubleObj} {emptyTest} {
test basic-32.1 {Tcl_ExprBooleanObj} {emptyTest} {
} {}
-test basic-33.1 {TclInvoke} {emptyTest} {
-} {}
-
-test basic-34.1 {TclGlobalInvoke} {emptyTest} {
-} {}
-
-test basic-35.1 {TclObjInvokeGlobal} {emptyTest} {
-} {}
-
-test basic-36.1 {TclObjInvoke, lookup of "unknown" command} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+test basic-36.1 {Tcl_EvalObjv, lookup of "unknown" command} {
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {interp delete test_interp}
interp create test_interp
interp eval test_interp {
@@ -499,75 +523,7 @@ test basic-37.1 {Tcl_ExprString: see expr.test} {emptyTest} {
test basic-38.1 {Tcl_ExprObj} {emptyTest} {
} {}
-test basic-39.1 {Tcl_CreateTrace, correct command and argc/argv arguments of trace proc} {testcmdtrace} {
- testcmdtrace tracetest {set stuff [expr 14 + 16]}
-} {{expr 14 + 16} {expr 14 + 16} {set stuff [expr 14 + 16]} {set stuff 30}}
-test basic-39.2 {Tcl_CreateTrace, correct command and argc/argv arguments of trace proc} {testcmdtrace} {
- testcmdtrace tracetest {set stuff [info tclversion]}
-} [list {info tclversion} {info tclversion} {set stuff [info tclversion]} "set stuff $tclvers"]
-test basic-39.3 {Tcl_CreateTrace, correct command and argc/argv arguments of trace proc} {testcmdtrace} {
- testcmdtrace deletetest {set stuff [info tclversion]}
-} $tclvers
-test basic-39.4 {Tcl_CreateTrace, check that tracing doesn't cause memory faults} {testcmdtrace} {
- # Note that the proc call is the same as the variable name, and that
- # the call can be direct or indirect by way of another procedure
- proc tracer {args} {}
- proc tracedLoop {level} {
- incr level
- tracer
- foreach tracer [expr {$level==1 ? {1 2} : {}}] {tracedLoop $level}
- }
- testcmdtrace tracetest {tracedLoop 0}
-} {{tracedLoop 0} {tracedLoop 0} {incr level} {incr level} tracer {tracer} {expr {$level==1 ? {1 2} : {}}} {expr {$level==1 ? {1 2} : {}}} {foreach tracer [expr {$level==1 ? {1 2} : {}}] {tracedLoop $level}} {foreach tracer {1 2} {tracedLoop $level}} {tracedLoop $level} {tracedLoop 1} {incr level} {incr level} tracer {tracer} {expr {$level==1 ? {1 2} : {}}} {expr {$level==1 ? {1 2} : {}}} {foreach tracer [expr {$level==1 ? {1 2} : {}}] {tracedLoop $level}} {foreach tracer {} {tracedLoop $level}} {tracedLoop $level} {tracedLoop 1} {incr level} {incr level} tracer {tracer} {expr {$level==1 ? {1 2} : {}}} {expr {$level==1 ? {1 2} : {}}} {foreach tracer [expr {$level==1 ? {1 2} : {}}] {tracedLoop $level}} {foreach tracer {} {tracedLoop $level}}}
-catch {rename tracer {}}
-catch {rename tracedLoop {}}
-
-test basic-39.5 {Tcl_CreateObjTrace, status return TCL_ERROR} {testcmdtrace} {
- proc Error { args } { error "Shouldn't get here" }
- set x 1;
- list [catch {testcmdtrace resulttest {Error $x}} result] [set result]
-} {1 {Error $x}}
-
-test basic-39.6 {Tcl_CreateObjTrace, status return TCL_RETURN} {testcmdtrace} {
- proc Return { args } { error "Shouldn't get here" }
- set x 1;
- list [catch {testcmdtrace resulttest {Return $x}} result] [set result]
-} {2 {}}
-
-test basic-39.7 {Tcl_CreateObjTrace, status return TCL_BREAK} {testcmdtrace} {
- proc Break { args } { error "Shouldn't get here" }
- set x 1;
- list [catch {testcmdtrace resulttest {Break $x}} result] [set result]
-} {3 {}}
-
-test basic-39.8 {Tcl_CreateObjTrace, status return TCL_CONTINUE} {testcmdtrace} {
- proc Continue { args } { error "Shouldn't get here" }
- set x 1;
- list [catch {testcmdtrace resulttest {Continue $x}} result] [set result]
-} {4 {}}
-
-test basic-39.9 {Tcl_CreateObjTrace, status return unknown} {testcmdtrace} {
- proc OtherStatus { args } { error "Shouldn't get here" }
- set x 1;
- list [catch {testcmdtrace resulttest {OtherStatus $x}} result] [set result]
-} {6 {}}
-
-test basic-39.10 {Tcl_CreateTrace, correct level interpretation} {testcmdtrace} {
- proc foo {} {uplevel 1 bar}
- proc bar {} {uplevel 1 grok}
- proc grok {} {uplevel 1 spock}
- proc spock {} {uplevel 1 fascinating}
- proc fascinating {} {}
- testcmdtrace leveltest {foo}
-} {foo {foo} {uplevel 1 bar} {uplevel 1 bar} bar {bar} {uplevel 1 grok} {uplevel 1 grok}}
-
-test basic-39.11 {Tcl_CreateTrace, multiple traces} {testcmdtrace} {
- testcmdtrace doubletest {format xx}
-} {{format xx} {format xx}}
-
-test basic-40.1 {Tcl_DeleteTrace} {emptyTest} {
- # the above tests have tested Tcl_DeleteTrace
-} {}
+# Tests basic-39.* and basic-40.* refactored into trace.test
test basic-41.1 {Tcl_AddErrorInfo} {emptyTest} {
} {}
@@ -591,7 +547,7 @@ test basic-46.1 {Tcl_AllowExceptions: exception return not allowed} {stdio} {
fconfigure $f -buffering line
puts $f {fconfigure stdout -buffering line}
puts $f continue
- puts $f {puts $errorInfo}
+ puts $f {puts $::errorInfo}
puts $f {puts DONE}
set newMsg {}
set msg {}
@@ -676,28 +632,335 @@ test basic-47.1 {Tcl_EvalEx: check for missing close-bracket} -body {
subst {a[set b [format cd]}
} -returnCodes error -result {missing close-bracket}
+# Some lists for expansion tests to work with
+set l1 [list a {b b} c d]
+set l2 [list e f {g g} h]
+proc l3 {} {
+ list i j k {l l}
+}
+
+# Do all tests once byte compiled and once with direct string evaluation
+for {set noComp 0} {$noComp <= 1} {incr noComp} {
+
+if $noComp {
+ interp alias {} run {} testevalex
+ set constraints testevalex
+} else {
+ interp alias {} run {} if 1
+ set constraints {}
+}
+
+test basic-47.2.$noComp {Tcl_EvalEx: error during word expansion} -body {
+ run {{*}\{}
+} -constraints $constraints -returnCodes error -result {unmatched open brace in list}
+
+test basic-47.3.$noComp {Tcl_EvalEx, error during substitution} -body {
+ run {{*}[error foo]}
+} -constraints $constraints -returnCodes error -result foo
+
+test basic-47.4.$noComp {Tcl_EvalEx: no expansion} $constraints {
+ run {list {*} {*} {*}}
+} {* * *}
+
+test basic-47.5.$noComp {Tcl_EvalEx: expansion} $constraints {
+ run {list {*}{} {*} {*}x {*}"y z"}
+} {* x y z}
+
+test basic-47.6.$noComp {Tcl_EvalEx: expansion to zero args} $constraints {
+ run {list {*}{}}
+} {}
+
+test basic-47.7.$noComp {Tcl_EvalEx: expansion to one arg} $constraints {
+ run {list {*}x}
+} x
+
+test basic-47.8.$noComp {Tcl_EvalEx: expansion to many args} $constraints {
+ run {list {*}"y z"}
+} {y z}
+
+test basic-47.9.$noComp {Tcl_EvalEx: expansion and subst order} $constraints {
+ set x 0
+ run {list [incr x] {*}[incr x] [incr x] \
+ {*}[list [incr x] [incr x]] [incr x]}
+} {1 2 3 4 5 6}
+
+test basic-47.10.$noComp {Tcl_EvalEx: expand and memory management} $constraints {
+ run {concat {*}{} a b c d e f g h i j k l m n o p q r}
+} {a b c d e f g h i j k l m n o p q r}
+
+test basic-47.11.$noComp {Tcl_EvalEx: expand and memory management} $constraints {
+ run {concat {*}1 a b c d e f g h i j k l m n o p q r}
+} {1 a b c d e f g h i j k l m n o p q r}
+
+test basic-47.12.$noComp {Tcl_EvalEx: expand and memory management} $constraints {
+ run {concat {*}{1 2} a b c d e f g h i j k l m n o p q r}
+} {1 2 a b c d e f g h i j k l m n o p q r}
+
+test basic-47.13.$noComp {Tcl_EvalEx: expand and memory management} $constraints {
+ run {concat {*}{} {*}{1 2} a b c d e f g h i j k l m n o p q}
+} {1 2 a b c d e f g h i j k l m n o p q}
+
+test basic-47.14.$noComp {Tcl_EvalEx: expand and memory management} $constraints {
+ run {concat {*}{} a b c d e f g h i j k l m n o p q r s}
+} {a b c d e f g h i j k l m n o p q r s}
+
+test basic-47.15.$noComp {Tcl_EvalEx: expand and memory management} $constraints {
+ run {concat {*}1 a b c d e f g h i j k l m n o p q r s}
+} {1 a b c d e f g h i j k l m n o p q r s}
+
+test basic-47.16.$noComp {Tcl_EvalEx: expand and memory management} $constraints {
+ run {concat {*}{1 2} a b c d e f g h i j k l m n o p q r s}
+} {1 2 a b c d e f g h i j k l m n o p q r s}
+
+test basic-47.17.$noComp {Tcl_EvalEx: expand and memory management} $constraints {
+ run {concat {*}{} {*}{1 2} a b c d e f g h i j k l m n o p q r}
+} {1 2 a b c d e f g h i j k l m n o p q r}
+
+test basic-48.1.$noComp {expansion: parsing} $constraints {
+ run { # A comment
+
+ # Another comment
+ list 1 2\
+ 3 {*}$::l1
+
+ # Comment again
+ }
+} {1 2 3 a {b b} c d}
+
+test basic-48.2.$noComp {no expansion} $constraints {
+ run {list $::l1 $::l2 [l3]}
+} {{a {b b} c d} {e f {g g} h} {i j k {l l}}}
+
+test basic-48.3.$noComp {expansion} $constraints {
+ run {list {*}$::l1 $::l2 {*}[l3]}
+} {a {b b} c d {e f {g g} h} i j k {l l}}
+
+test basic-48.4.$noComp {expansion: really long cmd} $constraints {
+ set cmd [list list]
+ for {set t 0} {$t < 500} {incr t} {
+ lappend cmd {{*}$::l1}
+ }
+ llength [run [join $cmd]]
+} 2000
+
+test basic-48.5.$noComp {expansion: error detection} -setup {
+ set l "a {a b}x y"
+} -constraints $constraints -body {
+ run {list $::l1 {*}$l}
+} -cleanup {
+ unset l
+} -returnCodes 1 -result {list element in braces followed by "x" instead of space}
+
+test basic-48.6.$noComp {expansion: odd usage} $constraints {
+ run {list {*}$::l1$::l2}
+} {a {b b} c de f {g g} h}
+
+test basic-48.7.$noComp {expansion: odd usage} -constraints $constraints -body {
+ run {list {*}[l3]$::l1}
+} -returnCodes 1 -result {list element in braces followed by "a" instead of space}
+
+test basic-48.8.$noComp {expansion: odd usage} $constraints {
+ run {list {*}hej$::l1}
+} {heja {b b} c d}
+
+test basic-48.9.$noComp {expansion: Not all {*} should trigger} $constraints {
+ run {list {*}$::l1 \{*\}$::l2 "{*}$::l1" {{*} i j k}}
+} {a {b b} c d {{*}e f {g g} h} {{*}a {b b} c d} {{*} i j k}}
+
+test basic-48.10.$noComp {expansion: expansion of command word} -setup {
+ set cmd [list string range jultomte]
+} -constraints $constraints -body {
+ run {{*}$cmd 2 6}
+} -cleanup {
+ unset cmd
+} -result ltomt
+
+test basic-48.11.$noComp {expansion: expansion into nothing} -setup {
+ set cmd {}
+ set bar {}
+} -constraints $constraints -body {
+ run {{*}$cmd {*}$bar}
+} -cleanup {
+ unset cmd bar
+} -result {}
+
+test basic-48.12.$noComp {expansion: odd usage} $constraints {
+ run {list {*}$::l1 {*}"hej hopp" {*}$::l2}
+} {a {b b} c d hej hopp e f {g g} h}
+
+test basic-48.13.$noComp {expansion: odd usage} $constraints {
+ run {list {*}$::l1 {*}{hej hopp} {*}$::l2}
+} {a {b b} c d hej hopp e f {g g} h}
+
+test basic-48.14.$noComp {expansion: hash command} -setup {
+ catch {rename \# ""}
+ set cmd "#"
+ } -constraints $constraints -body {
+ run { {*}$cmd apa bepa }
+ } -cleanup {
+ unset cmd
+} -returnCodes 1 -result {invalid command name "#"}
+
+test basic-48.15.$noComp {expansion: complex words} -setup {
+ set a(x) [list a {b c} d e]
+ set b x
+ set c [list {f\ g h\ i j k} x y]
+ set d {0\ 1 2 3}
+ } -constraints $constraints -body {
+ run { lappend d {*}$a($b) {*}[lindex $c 0] }
+ } -cleanup {
+ unset a b c d
+} -result {{0 1} 2 3 a {b c} d e {f g} {h i} j k}
+
+testConstraint memory [llength [info commands memory]]
+test basic-48.16.$noComp {expansion: testing for leaks} -setup {
+ proc getbytes {} {
+ set lines [split [memory info] "\n"]
+ lindex [lindex $lines 3] 3
+ }
+ # This test is made to stress the allocation, reallocation and
+ # object reference management in Tcl_EvalEx.
+ proc stress {} {
+ set a x
+ # Create free objects that should disappear
+ set l [list 1$a 2$a 3$a 4$a 5$a 6$a 7$a]
+ # A short number of words and a short result (8)
+ set l [run {list {*}$l $a$a}]
+ # A short number of words and a longer result (27)
+ set l [run {list {*}$l $a$a {*}$l $a$a {*}$l $a$a}]
+ # A short number of words and a longer result, with an error
+ # This is to stress the cleanup in the error case
+ if {![catch {run {_moo_ {*}$l $a$a {*}$l $a$a {*}$l}}]} {
+ error "An error was expected in the previous statement"
+ }
+ # Many words
+ set l [run {list {*}$l $a$a {*}$l $a$a \
+ {*}$l $a$a {*}$l $a$a \
+ {*}$l $a$a {*}$l $a$a \
+ {*}$l $a$a {*}$l $a$a \
+ {*}$l $a$a {*}$l $a$a \
+ {*}$l $a$a {*}$l $a$a \
+ {*}$l $a$a {*}$l $a$a \
+ {*}$l $a$a {*}$l $a$a \
+ {*}$l $a$a {*}$l $a$a \
+ {*}$l $a$a}]
+
+ if {[llength $l] != 19*28} {
+ error "Bad Length: [llength $l] should be [expr {19*28}]"
+ }
+ }
+ } -constraints [linsert $constraints 0 memory] -body {
+ set end [getbytes]
+ for {set i 0} {$i < 5} {incr i} {
+ stress
+ set tmp $end
+ set end [getbytes]
+ }
+ set leak [expr {$end - $tmp}]
+ } -cleanup {
+ unset end i tmp
+ rename getbytes {}
+ rename stress {}
+} -result 0
+
+test basic-48.17.$noComp {expansion: object safety} -setup {
+ set old_precision $::tcl_precision
+ set ::tcl_precision 4
+ } -constraints $constraints -body {
+ set third [expr {1.0/3.0}]
+ set l [list $third $third]
+ set x [run {list $third {*}$l $third}]
+ set res [list]
+ foreach t $x {
+ lappend res [expr {$t * 3.0}]
+ }
+ set res
+ } -cleanup {
+ set ::tcl_precision $old_precision
+ unset old_precision res t l x third
+} -result {1.0 1.0 1.0 1.0}
+
+test basic-48.18.$noComp {expansion: list semantics} -constraints $constraints -body {
+ set badcmd {
+ list a b
+ set apa 10
+ }
+ set apa 0
+ list [llength [run { {*}$badcmd }]] $apa
+ } -cleanup {
+ unset apa badcmd
+} -result {5 0}
+
+test basic-48.19.$noComp {expansion: error checking order} -body {
+ set badlist "a {}x y"
+ set a 0
+ set b 0
+ catch {run {list [incr a] {*}$badlist [incr b]}}
+ list $a $b
+ } -constraints $constraints -cleanup {
+ unset badlist a b
+} -result {1 0}
+
+test basic-48.20.$noComp {expansion: odd case with word boundaries} $constraints {
+ run {list {*}$::l1 {*}"hej hopp" {*}$::l2}
+} {a {b b} c d hej hopp e f {g g} h}
+
+test basic-48.21.$noComp {expansion: odd case with word boundaries} $constraints {
+ run {list {*}$::l1 {*}{hej hopp} {*}$::l2}
+} {a {b b} c d hej hopp e f {g g} h}
+
+test basic-48.22.$noComp {expansion: odd case with word boundaries} -body {
+ run {list {*}$::l1 {*}"hej hopp {*}$::l2}
+} -constraints $constraints -returnCodes error -result {missing "}
+
+test basic-48.23.$noComp {expansion: handle return codes} -constraints $constraints -body {
+ set res {}
+ for {set t 0} {$t < 10} {incr t} {
+ run { {*}break }
+ }
+ lappend res $t
+
+ for {set t 0} {$t < 10} {incr t} {
+ run { {*}continue }
+ set t 20
+ }
+ lappend res $t
+
+ lappend res [catch { run { {*}{error Hejsan} } } err]
+ lappend res $err
+ } -cleanup {
+ unset res t
+} -result {0 10 1 Hejsan}
+
+} ;# End of noComp loop
+
test basic-49.1 {Tcl_EvalEx: verify TCL_EVAL_GLOBAL operation} testevalex {
set ::x global
namespace eval ns {
- variable x namespace
- testevalex {set x changed} global
- set ::result [list $::x $x]
- }
+ variable x namespace
+ testevalex {set x changed} global
+ set ::result [list $::x $x]
+ }
namespace delete ns
set ::result
} {changed namespace}
test basic-49.2 {Tcl_EvalEx: verify TCL_EVAL_GLOBAL operation} testevalex {
set ::x global
namespace eval ns {
- variable x namespace
- testevalex {set ::context $x} global
+ variable x namespace
+ testevalex {set ::context $x} global
}
namespace delete ns
set ::context
} {global}
-# cleanup
-catch {eval namespace delete [namespace children :: test_ns_*]}
+# Clean up after expand tests
+unset noComp l1 l2 constraints
+rename l3 {}
+rename run {}
+
+ #cleanup
+catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {namespace delete george}
catch {interp delete test_interp}
catch {rename p ""}
diff --git a/tests/binary.test b/tests/binary.test
index 122fcdf..44af9e5 100644
--- a/tests/binary.test
+++ b/tests/binary.test
@@ -14,6 +14,8 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
namespace import -force ::tcltest::*
}
+testConstraint bigEndian [expr {$tcl_platform(byteOrder) eq "bigEndian"}]
+testConstraint littleEndian [expr {$tcl_platform(byteOrder) eq "littleEndian"}]
test binary-0.1 {DupByteArrayInternalRep} {
set hdr [binary format cc 0 0316]
@@ -424,40 +426,40 @@ test binary-13.2 {Tcl_BinaryObjCmd: format} {
test binary-13.3 {Tcl_BinaryObjCmd: format} {
binary format f0 1.6
} {}
-test binary-13.4 {Tcl_BinaryObjCmd: format} {nonPortable macOrUnix} {
+test binary-13.4 {Tcl_BinaryObjCmd: format} bigEndian {
binary format f 1.6
} \x3f\xcc\xcc\xcd
-test binary-13.5 {Tcl_BinaryObjCmd: format} {nonPortable pcOnly} {
+test binary-13.5 {Tcl_BinaryObjCmd: format} littleEndian {
binary format f 1.6
} \xcd\xcc\xcc\x3f
-test binary-13.6 {Tcl_BinaryObjCmd: format} {nonPortable macOrUnix} {
+test binary-13.6 {Tcl_BinaryObjCmd: format} bigEndian {
binary format f* {1.6 3.4}
} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a
-test binary-13.7 {Tcl_BinaryObjCmd: format} {nonPortable pcOnly} {
+test binary-13.7 {Tcl_BinaryObjCmd: format} littleEndian {
binary format f* {1.6 3.4}
} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40
-test binary-13.8 {Tcl_BinaryObjCmd: format} {nonPortable macOrUnix} {
+test binary-13.8 {Tcl_BinaryObjCmd: format} bigEndian {
binary format f2 {1.6 3.4}
} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a
-test binary-13.9 {Tcl_BinaryObjCmd: format} {nonPortable pcOnly} {
+test binary-13.9 {Tcl_BinaryObjCmd: format} littleEndian {
binary format f2 {1.6 3.4}
} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40
-test binary-13.10 {Tcl_BinaryObjCmd: format} {nonPortable macOrUnix} {
+test binary-13.10 {Tcl_BinaryObjCmd: format} bigEndian {
binary format f2 {1.6 3.4 5.6}
} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a
-test binary-13.11 {Tcl_BinaryObjCmd: format} {nonPortable pcOnly} {
+test binary-13.11 {Tcl_BinaryObjCmd: format} littleEndian {
binary format f2 {1.6 3.4 5.6}
} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40
-test binary-13.12 {Tcl_BinaryObjCmd: float overflow} {nonPortable macOrUnix} {
+test binary-13.12 {Tcl_BinaryObjCmd: float overflow} bigEndian {
binary format f -3.402825e+38
} \xff\x7f\xff\xff
-test binary-13.13 {Tcl_BinaryObjCmd: float overflow} {nonPortable pcOnly} {
+test binary-13.13 {Tcl_BinaryObjCmd: float overflow} littleEndian {
binary format f -3.402825e+38
} \xff\xff\x7f\xff
-test binary-13.14 {Tcl_BinaryObjCmd: float underflow} {nonPortable macOrUnix} {
+test binary-13.14 {Tcl_BinaryObjCmd: float underflow} bigEndian {
binary format f -3.402825e-100
} \x80\x00\x00\x00
-test binary-13.15 {Tcl_BinaryObjCmd: float underflow} {nonPortable pcOnly} {
+test binary-13.15 {Tcl_BinaryObjCmd: float underflow} littleEndian {
binary format f -3.402825e-100
} \x00\x00\x00\x80
test binary-13.16 {Tcl_BinaryObjCmd: format} {
@@ -467,11 +469,11 @@ test binary-13.17 {Tcl_BinaryObjCmd: format} {
set a {1.6 3.4}
list [catch {binary format f $a} msg] $msg
} [list 1 "expected floating-point number but got \"1.6 3.4\""]
-test binary-13.18 {Tcl_BinaryObjCmd: format} {nonPortable macOrUnix} {
+test binary-13.18 {Tcl_BinaryObjCmd: format} bigEndian {
set a {1.6 3.4}
binary format f1 $a
} \x3f\xcc\xcc\xcd
-test binary-13.19 {Tcl_BinaryObjCmd: format} {nonPortable pcOnly} {
+test binary-13.19 {Tcl_BinaryObjCmd: format} littleEndian {
set a {1.6 3.4}
binary format f1 $a
} \xcd\xcc\xcc\x3f
@@ -485,36 +487,30 @@ test binary-14.2 {Tcl_BinaryObjCmd: format} {
test binary-14.3 {Tcl_BinaryObjCmd: format} {
binary format d0 1.6
} {}
-test binary-14.4 {Tcl_BinaryObjCmd: format} {nonPortable macOrUnix} {
+test binary-14.4 {Tcl_BinaryObjCmd: format} bigEndian {
binary format d 1.6
} \x3f\xf9\x99\x99\x99\x99\x99\x9a
-test binary-14.5 {Tcl_BinaryObjCmd: format} {nonPortable pcOnly} {
+test binary-14.5 {Tcl_BinaryObjCmd: format} littleEndian {
binary format d 1.6
} \x9a\x99\x99\x99\x99\x99\xf9\x3f
-test binary-14.6 {Tcl_BinaryObjCmd: format} {nonPortable macOrUnix} {
+test binary-14.6 {Tcl_BinaryObjCmd: format} bigEndian {
binary format d* {1.6 3.4}
} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33
-test binary-14.7 {Tcl_BinaryObjCmd: format} {nonPortable pcOnly} {
+test binary-14.7 {Tcl_BinaryObjCmd: format} littleEndian {
binary format d* {1.6 3.4}
} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40
-test binary-14.8 {Tcl_BinaryObjCmd: format} {nonPortable macOrUnix} {
+test binary-14.8 {Tcl_BinaryObjCmd: format} bigEndian {
binary format d2 {1.6 3.4}
} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33
-test binary-14.9 {Tcl_BinaryObjCmd: format} {nonPortable pcOnly} {
+test binary-14.9 {Tcl_BinaryObjCmd: format} littleEndian {
binary format d2 {1.6 3.4}
} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40
-test binary-14.10 {Tcl_BinaryObjCmd: format} {nonPortable macOrUnix} {
+test binary-14.10 {Tcl_BinaryObjCmd: format} bigEndian {
binary format d2 {1.6 3.4 5.6}
} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33
-test binary-14.11 {Tcl_BinaryObjCmd: format} {nonPortable pcOnly} {
+test binary-14.11 {Tcl_BinaryObjCmd: format} littleEndian {
binary format d2 {1.6 3.4 5.6}
} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40
-test binary-14.12 {Tcl_BinaryObjCmd: float overflow} {nonPortable unixOnly} {
- binary format d NaN
-} \x7f\xff\xff\xff\xff\xff\xff\xff
-test binary-14.13 {Tcl_BinaryObjCmd: float overflow} {nonPortable macOnly} {
- binary format d NaN
-} \x7f\xf8\x02\xa0\x00\x00\x00\x00
test binary-14.14 {Tcl_BinaryObjCmd: format} {
list [catch {binary format d2 {1.6}} msg] $msg
} {1 {number of elements in list does not match count}}
@@ -522,11 +518,11 @@ test binary-14.15 {Tcl_BinaryObjCmd: format} {
set a {1.6 3.4}
list [catch {binary format d $a} msg] $msg
} [list 1 "expected floating-point number but got \"1.6 3.4\""]
-test binary-14.16 {Tcl_BinaryObjCmd: format} {nonPortable macOrUnix} {
+test binary-14.16 {Tcl_BinaryObjCmd: format} bigEndian {
set a {1.6 3.4}
binary format d1 $a
} \x3f\xf9\x99\x99\x99\x99\x99\x9a
-test binary-14.17 {Tcl_BinaryObjCmd: format} {nonPortable pcOnly} {
+test binary-14.17 {Tcl_BinaryObjCmd: format} littleEndian {
set a {1.6 3.4}
binary format d1 $a
} \x9a\x99\x99\x99\x99\x99\xf9\x3f
@@ -919,6 +915,30 @@ test binary-26.10 {Tcl_BinaryObjCmd: scan} {
set arg2 bar
list [binary scan \x70\x87\x05 c2c* arg1 arg2] $arg1 $arg2
} {2 {112 -121} 5}
+test binary-26.11 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1}
+ list [binary scan \x52\xa3 cu* arg1] $arg1
+} {1 {82 163}}
+test binary-26.12 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1}
+ list [binary scan \x52\xa3 cu arg1] $arg1
+} {1 82}
+test binary-26.13 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1}
+ list [binary scan \xff cu arg1] $arg1
+} {1 255}
+test binary-26.14 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1 arg2}
+ set arg1 foo
+ set arg2 bar
+ list [binary scan \x80\x80 cuc arg1 arg2] $arg1 $arg2
+} {2 128 -128}
+test binary-26.15 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1 arg2}
+ set arg1 foo
+ set arg2 bar
+ list [binary scan \x80\x80 ccu arg1 arg2] $arg1 $arg2
+} {2 -128 128}
test binary-27.1 {Tcl_BinaryObjCmd: scan} {
list [catch {binary scan abc s} msg] $msg
@@ -959,6 +979,22 @@ test binary-27.9 {Tcl_BinaryObjCmd: scan} {
set arg2 bar
list [binary scan \x52\xa3\x53\x54\x05 s2c* arg1 arg2] $arg1 $arg2
} {2 {-23726 21587} 5}
+test binary-27.10 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1}
+ list [binary scan \x52\xa3\x53\x54 su* arg1] $arg1
+} {1 {41810 21587}}
+test binary-27.11 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1 arg2}
+ set arg1 foo
+ set arg2 bar
+ list [binary scan \xff\xff\xff\xff sus arg1 arg2] $arg1 $arg2
+} {2 65535 -1}
+test binary-27.12 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1 arg2}
+ set arg1 foo
+ set arg2 bar
+ list [binary scan \xff\xff\xff\xff ssu arg1 arg2] $arg1 $arg2
+} {2 -1 65535}
test binary-28.1 {Tcl_BinaryObjCmd: scan} {
list [catch {binary scan abc S} msg] $msg
@@ -999,6 +1035,14 @@ test binary-28.9 {Tcl_BinaryObjCmd: scan} {
set arg2 bar
list [binary scan \x52\xa3\x53\x54\x05 S2c* arg1 arg2] $arg1 $arg2
} {2 {21155 21332} 5}
+test binary-28.10 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1}
+ list [binary scan \x52\xa3\x53\x54 Su* arg1] $arg1
+} {1 {21155 21332}}
+test binary-28.11 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1}
+ list [binary scan \xa3\x52\x54\x53 Su* arg1] $arg1
+} {1 {41810 21587}}
test binary-29.1 {Tcl_BinaryObjCmd: scan} {
list [catch {binary scan abc i} msg] $msg
@@ -1039,6 +1083,18 @@ test binary-29.9 {Tcl_BinaryObjCmd: scan} {
set arg2 bar
list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04\x05 i2c* arg1 arg2] $arg1 $arg2
} {2 {1414767442 67305985} 5}
+test binary-29.10 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1 arg2}
+ list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff iui arg1 arg2] $arg1 $arg2
+} {2 4294967295 -1}
+test binary-29.11 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1 arg2}
+ list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff iiu arg1 arg2] $arg1 $arg2
+} {2 -1 4294967295}
+test binary-29.12 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1 arg2}
+ list [binary scan \x80\x00\x00\x00\x00\x00\x00\x80 iuiu arg1 arg2] $arg1 $arg2
+} {2 128 2147483648}
test binary-30.1 {Tcl_BinaryObjCmd: scan} {
list [catch {binary scan abc I} msg] $msg
@@ -1079,50 +1135,62 @@ test binary-30.9 {Tcl_BinaryObjCmd: scan} {
set arg2 bar
list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04\x05 I2c* arg1 arg2] $arg1 $arg2
} {2 {1386435412 16909060} 5}
+test binary-30.10 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1 arg2}
+ list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff IuI arg1 arg2] $arg1 $arg2
+} {2 4294967295 -1}
+test binary-30.11 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1 arg2}
+ list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff IIu arg1 arg2] $arg1 $arg2
+} {2 -1 4294967295}
+test binary-30.12 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1 arg2}
+ list [binary scan \x80\x00\x00\x00\x00\x00\x00\x80 IuIu arg1 arg2] $arg1 $arg2
+} {2 2147483648 128}
test binary-31.1 {Tcl_BinaryObjCmd: scan} {
list [catch {binary scan abc f} msg] $msg
} {1 {not enough arguments for all format specifiers}}
-test binary-31.2 {Tcl_BinaryObjCmd: scan} {nonPortable macOrUnix} {
+test binary-31.2 {Tcl_BinaryObjCmd: scan} bigEndian {
catch {unset arg1}
list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a f* arg1] $arg1
-} {1 {1.60000002384 3.40000009537}}
-test binary-31.3 {Tcl_BinaryObjCmd: scan} {nonPortable pcOnly} {
+} {1 {1.600000023841858 3.4000000953674316}}
+test binary-31.3 {Tcl_BinaryObjCmd: scan} littleEndian {
catch {unset arg1}
list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 f* arg1] $arg1
-} {1 {1.60000002384 3.40000009537}}
-test binary-31.4 {Tcl_BinaryObjCmd: scan} {nonPortable macOrUnix} {
+} {1 {1.600000023841858 3.4000000953674316}}
+test binary-31.4 {Tcl_BinaryObjCmd: scan} bigEndian {
catch {unset arg1}
list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a f arg1] $arg1
-} {1 1.60000002384}
-test binary-31.5 {Tcl_BinaryObjCmd: scan} {nonPortable pcOnly} {
+} {1 1.600000023841858}
+test binary-31.5 {Tcl_BinaryObjCmd: scan} littleEndian {
catch {unset arg1}
list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 f arg1] $arg1
-} {1 1.60000002384}
-test binary-31.6 {Tcl_BinaryObjCmd: scan} {nonPortable macOrUnix} {
+} {1 1.600000023841858}
+test binary-31.6 {Tcl_BinaryObjCmd: scan} bigEndian {
catch {unset arg1}
list [binary scan \x3f\xcc\xcc\xcd f1 arg1] $arg1
-} {1 1.60000002384}
-test binary-31.7 {Tcl_BinaryObjCmd: scan} {nonPortable pcOnly} {
+} {1 1.600000023841858}
+test binary-31.7 {Tcl_BinaryObjCmd: scan} littleEndian {
catch {unset arg1}
list [binary scan \xcd\xcc\xcc\x3f f1 arg1] $arg1
-} {1 1.60000002384}
-test binary-31.8 {Tcl_BinaryObjCmd: scan} {nonPortable macOrUnix} {
+} {1 1.600000023841858}
+test binary-31.8 {Tcl_BinaryObjCmd: scan} bigEndian {
catch {unset arg1}
list [binary scan \x3f\xcc\xcc\xcd f0 arg1] $arg1
} {1 {}}
-test binary-31.9 {Tcl_BinaryObjCmd: scan} {nonPortable pcOnly} {
+test binary-31.9 {Tcl_BinaryObjCmd: scan} littleEndian {
catch {unset arg1}
list [binary scan \xcd\xcc\xcc\x3f f0 arg1] $arg1
} {1 {}}
-test binary-31.10 {Tcl_BinaryObjCmd: scan} {nonPortable macOrUnix} {
+test binary-31.10 {Tcl_BinaryObjCmd: scan} bigEndian {
catch {unset arg1}
list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a f2 arg1] $arg1
-} {1 {1.60000002384 3.40000009537}}
-test binary-31.11 {Tcl_BinaryObjCmd: scan} {nonPortable pcOnly} {
+} {1 {1.600000023841858 3.4000000953674316}}
+test binary-31.11 {Tcl_BinaryObjCmd: scan} littleEndian {
catch {unset arg1}
list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 f2 arg1] $arg1
-} {1 {1.60000002384 3.40000009537}}
+} {1 {1.600000023841858 3.4000000953674316}}
test binary-31.12 {Tcl_BinaryObjCmd: scan} {
catch {unset arg1}
set arg1 foo
@@ -1133,59 +1201,59 @@ test binary-31.13 {Tcl_BinaryObjCmd: scan} {
set arg1 1
list [catch {binary scan \x3f\xcc\xcc\xcd f1 arg1(a)} msg] $msg
} {1 {can't set "arg1(a)": variable isn't array}}
-test binary-31.14 {Tcl_BinaryObjCmd: scan} {nonPortable macOrUnix} {
+test binary-31.14 {Tcl_BinaryObjCmd: scan} bigEndian {
catch {unset arg1 arg2}
set arg1 foo
set arg2 bar
list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a\x05 f2c* arg1 arg2] $arg1 $arg2
-} {2 {1.60000002384 3.40000009537} 5}
-test binary-31.15 {Tcl_BinaryObjCmd: scan} {nonPortable pcOnly} {
+} {2 {1.600000023841858 3.4000000953674316} 5}
+test binary-31.15 {Tcl_BinaryObjCmd: scan} littleEndian {
catch {unset arg1 arg2}
set arg1 foo
set arg2 bar
list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40\x05 f2c* arg1 arg2] $arg1 $arg2
-} {2 {1.60000002384 3.40000009537} 5}
+} {2 {1.600000023841858 3.4000000953674316} 5}
test binary-32.1 {Tcl_BinaryObjCmd: scan} {
list [catch {binary scan abc d} msg] $msg
} {1 {not enough arguments for all format specifiers}}
-test binary-32.2 {Tcl_BinaryObjCmd: scan} {nonPortable macOrUnix} {
+test binary-32.2 {Tcl_BinaryObjCmd: scan} bigEndian {
catch {unset arg1}
list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 d* arg1] $arg1
} {1 {1.6 3.4}}
-test binary-32.3 {Tcl_BinaryObjCmd: scan} {nonPortable pcOnly} {
+test binary-32.3 {Tcl_BinaryObjCmd: scan} littleEndian {
catch {unset arg1}
list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 d* arg1] $arg1
} {1 {1.6 3.4}}
-test binary-32.4 {Tcl_BinaryObjCmd: scan} {nonPortable macOrUnix} {
+test binary-32.4 {Tcl_BinaryObjCmd: scan} bigEndian {
catch {unset arg1}
list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 d arg1] $arg1
} {1 1.6}
-test binary-32.5 {Tcl_BinaryObjCmd: scan} {nonPortable pcOnly} {
+test binary-32.5 {Tcl_BinaryObjCmd: scan} littleEndian {
catch {unset arg1}
list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 d arg1] $arg1
} {1 1.6}
-test binary-32.6 {Tcl_BinaryObjCmd: scan} {nonPortable macOrUnix} {
+test binary-32.6 {Tcl_BinaryObjCmd: scan} bigEndian {
catch {unset arg1}
list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a d1 arg1] $arg1
} {1 1.6}
-test binary-32.7 {Tcl_BinaryObjCmd: scan} {nonPortable pcOnly} {
+test binary-32.7 {Tcl_BinaryObjCmd: scan} littleEndian {
catch {unset arg1}
list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f d1 arg1] $arg1
} {1 1.6}
-test binary-32.8 {Tcl_BinaryObjCmd: scan} {nonPortable macOrUnix} {
+test binary-32.8 {Tcl_BinaryObjCmd: scan} bigEndian {
catch {unset arg1}
list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a d0 arg1] $arg1
} {1 {}}
-test binary-32.9 {Tcl_BinaryObjCmd: scan} {nonPortable pcOnly} {
+test binary-32.9 {Tcl_BinaryObjCmd: scan} littleEndian {
catch {unset arg1}
list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f d0 arg1] $arg1
} {1 {}}
-test binary-32.10 {Tcl_BinaryObjCmd: scan} {nonPortable macOrUnix} {
+test binary-32.10 {Tcl_BinaryObjCmd: scan} bigEndian {
catch {unset arg1}
list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 d2 arg1] $arg1
} {1 {1.6 3.4}}
-test binary-32.11 {Tcl_BinaryObjCmd: scan} {nonPortable pcOnly} {
+test binary-32.11 {Tcl_BinaryObjCmd: scan} littleEndian {
catch {unset arg1}
list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 d2 arg1] $arg1
} {1 {1.6 3.4}}
@@ -1199,13 +1267,13 @@ test binary-32.13 {Tcl_BinaryObjCmd: scan} {
set arg1 1
list [catch {binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a d1 arg1(a)} msg] $msg
} {1 {can't set "arg1(a)": variable isn't array}}
-test binary-32.14 {Tcl_BinaryObjCmd: scan} {nonPortable macOrUnix} {
+test binary-32.14 {Tcl_BinaryObjCmd: scan} bigEndian {
catch {unset arg1 arg2}
set arg1 foo
set arg2 bar
list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33\x05 d2c* arg1 arg2] $arg1 $arg2
} {2 {1.6 3.4} 5}
-test binary-32.15 {Tcl_BinaryObjCmd: scan} {nonPortable pcOnly} {
+test binary-32.15 {Tcl_BinaryObjCmd: scan} littleEndian {
catch {unset arg1 arg2}
set arg1 foo
set arg2 bar
@@ -1365,16 +1433,16 @@ test binary-38.3 {FormatNumber: word alignment} {
test binary-38.4 {FormatNumber: word alignment} {
set x [binary format c1I1 1 1]
} \x01\x00\x00\x00\x01
-test binary-38.5 {FormatNumber: word alignment} {nonPortable macOrUnix} {
+test binary-38.5 {FormatNumber: word alignment} bigEndian {
set x [binary format c1d1 1 1.6]
} \x01\x3f\xf9\x99\x99\x99\x99\x99\x9a
-test binary-38.6 {FormatNumber: word alignment} {nonPortable pcOnly} {
+test binary-38.6 {FormatNumber: word alignment} littleEndian {
set x [binary format c1d1 1 1.6]
} \x01\x9a\x99\x99\x99\x99\x99\xf9\x3f
-test binary-38.7 {FormatNumber: word alignment} {nonPortable macOrUnix} {
+test binary-38.7 {FormatNumber: word alignment} bigEndian {
set x [binary format c1f1 1 1.6]
} \x01\x3f\xcc\xcc\xcd
-test binary-38.8 {FormatNumber: word alignment} {nonPortable pcOnly} {
+test binary-38.8 {FormatNumber: word alignment} littleEndian {
set x [binary format c1f1 1 1.6]
} \x01\xcd\xcc\xcc\x3f
@@ -1398,43 +1466,42 @@ test binary-39.5 {ScanNumber: sign extension} {
catch {unset arg1}
list [binary scan \x01\x01\x01\x02\x81\x01\x01\x01\x01\x82\x01\x01\x01\x01\x82\x01\x01\x01\x01\x81 I5 arg1] $arg1
} {1 {16843010 -2130640639 25297153 16876033 16843137}}
-
-test binary-40.1 {ScanNumber: floating point overflow} {nonPortable unixOnly} {
+test binary-39.6 {ScanNumber: no sign extension} {
catch {unset arg1}
- list [binary scan \xff\xff\xff\xff f1 arg1] $arg1
-} {1 -NaN}
-test binary-40.2 {ScanNumber: floating point overflow} {nonPortable macOnly} {
+ list [binary scan \x52\xa3 cu2 arg1] $arg1
+} {1 {82 163}}
+test binary-39.7 {ScanNumber: no sign extension} {
catch {unset arg1}
- list [binary scan \xff\xff\xff\xff f1 arg1] $arg1
-} {1 -NAN(255)}
-test binary-40.3 {ScanNumber: floating point overflow} {nonPortable pcOnly} {
+ list [binary scan \x01\x02\x01\x81\x82\x01\x81\x82 su4 arg1] $arg1
+} {1 {513 33025 386 33409}}
+test binary-39.8 {ScanNumber: no sign extension} {
catch {unset arg1}
- set result [binary scan \xff\xff\xff\xff f1 arg1]
- if {([string compare $arg1 -1.\#QNAN] == 0)
- || ([string compare $arg1 -NAN] == 0)} {
- lappend result success
- } else {
- lappend result failure
- }
-} {1 success}
-test binary-40.4 {ScanNumber: floating point overflow} {nonPortable unixOnly} {
- catch {unset arg1}
- list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff d1 arg1] $arg1
-} {1 -NaN}
-test binary-40.5 {ScanNumber: floating point overflow} {nonPortable macOnly} {
- catch {unset arg1}
- list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff d1 arg1] $arg1
-} {1 -NAN(255)}
-test binary-40.6 {ScanNumber: floating point overflow} {nonPortable pcOnly} {
- catch {unset arg1}
- set result [binary scan \xff\xff\xff\xff\xff\xff\xff\xff d1 arg1]
- if {([string compare $arg1 -1.\#QNAN] == 0)
- || ([string compare $arg1 -NAN] == 0)} {
- lappend result success
- } else {
- lappend result failure
- }
-} {1 success}
+ list [binary scan \x01\x02\x01\x81\x82\x01\x81\x82 Su4 arg1] $arg1
+} {1 {258 385 33281 33154}}
+test binary-39.9 {ScanNumber: no sign extension} {
+ catch {unset arg1}
+ list [binary scan \x01\x01\x01\x02\x81\x01\x01\x01\x01\x82\x01\x01\x01\x01\x82\x01\x01\x01\x01\x81 iu5 arg1] $arg1
+} {1 {33620225 16843137 16876033 25297153 2164326657}}
+test binary-39.10 {ScanNumber: no sign extension} {
+ catch {unset arg1}
+ list [binary scan \x01\x01\x01\x02\x81\x01\x01\x01\x01\x82\x01\x01\x01\x01\x82\x01\x01\x01\x01\x81 Iu5 arg1] $arg1
+} {1 {16843010 2164326657 25297153 16876033 16843137}}
+
+test binary-40.3 {ScanNumber: NaN} \
+ -body {
+ catch {unset arg1}
+ list [binary scan \xff\xff\xff\xff f1 arg1] $arg1
+ } \
+ -match glob \
+ -result {1 -NaN*}
+
+test binary-40.4 {ScanNumber: NaN} \
+ -body {
+ catch {unset arg1}
+ list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff d arg1] $arg1
+ } \
+ -match glob \
+ -result {1 -NaN*}
test binary-41.1 {ScanNumber: word alignment} {
catch {unset arg1; unset arg2}
@@ -1452,19 +1519,19 @@ test binary-41.4 {ScanNumber: word alignment} {
catch {unset arg1; unset arg2}
list [binary scan \x01\x00\x00\x00\x01 c1I1 arg1 arg2] $arg1 $arg2
} {2 1 1}
-test binary-41.5 {ScanNumber: word alignment} {nonPortable macOrUnix} {
+test binary-41.5 {ScanNumber: word alignment} bigEndian {
catch {unset arg1; unset arg2}
list [binary scan \x01\x3f\xcc\xcc\xcd c1f1 arg1 arg2] $arg1 $arg2
-} {2 1 1.60000002384}
-test binary-41.6 {ScanNumber: word alignment} {nonPortable pcOnly} {
+} {2 1 1.600000023841858}
+test binary-41.6 {ScanNumber: word alignment} littleEndian {
catch {unset arg1; unset arg2}
list [binary scan \x01\xcd\xcc\xcc\x3f c1f1 arg1 arg2] $arg1 $arg2
-} {2 1 1.60000002384}
-test binary-41.7 {ScanNumber: word alignment} {nonPortable macOrUnix} {
+} {2 1 1.600000023841858}
+test binary-41.7 {ScanNumber: word alignment} bigEndian {
catch {unset arg1; unset arg2}
list [binary scan \x01\x3f\xf9\x99\x99\x99\x99\x99\x9a c1d1 arg1 arg2] $arg1 $arg2
} {2 1 1.6}
-test binary-41.8 {ScanNumber: word alignment} {nonPortable pcOnly} {
+test binary-41.8 {ScanNumber: word alignment} littleEndian {
catch {unset arg1; unset arg2}
list [binary scan \x01\x9a\x99\x99\x99\x99\x99\xf9\x3f c1d1 arg1 arg2] $arg1 $arg2
} {2 1 1.6}
@@ -1498,6 +1565,26 @@ test binary-44.4 {Tcl_BinaryObjCmd: scan wide int with bit 31 set} {} {
binary scan [binary format W [expr {wide(3) << 31}]] W x
set x
} 6442450944
+test binary-43.5 {Tcl_BinaryObjCmd: scan wide int} {} {
+ catch {unset arg1}
+ list [binary scan \x80[string repeat \x00 7] W arg1] $arg1
+} {1 -9223372036854775808}
+test binary-43.6 {Tcl_BinaryObjCmd: scan unsigned wide int} {} {
+ catch {unset arg1}
+ list [binary scan \x80[string repeat \x00 7] Wu arg1] $arg1
+} {1 9223372036854775808}
+test binary-43.7 {Tcl_BinaryObjCmd: scan unsigned wide int} {} {
+ catch {unset arg1}
+ list [binary scan [string repeat \x00 7]\x80 wu arg1] $arg1
+} {1 9223372036854775808}
+test binary-43.8 {Tcl_BinaryObjCmd: scan unsigned wide int} {} {
+ catch {unset arg1 arg2}
+ list [binary scan \x80[string repeat \x00 7]\x80[string repeat \x00 7] WuW arg1 arg2] $arg1 $arg2
+} {2 9223372036854775808 -9223372036854775808}
+test binary-43.9 {Tcl_BinaryObjCmd: scan unsigned wide int} {} {
+ catch {unset arg1 arg2}
+ list [binary scan [string repeat \x00 7]\x80[string repeat \x00 7]\x80 wuw arg1 arg2] $arg1 $arg2
+} {2 9223372036854775808 -9223372036854775808}
test binary-45.1 {Tcl_BinaryObjCmd: combined wide int handling} {
binary scan [binary format sws 16450 -1 19521] c* x
@@ -1538,6 +1625,793 @@ test binary-47.1 {Tcl_BinaryObjCmd: number cache reference count handling} {
list [binary scan aba ccc x x x] $x
} {3 97}
+### TIP#129: endian specifiers ----
+
+# format t
+test binary-48.1 {Tcl_BinaryObjCmd: format} {
+ list [catch {binary format t} msg] $msg
+} {1 {not enough arguments for all format specifiers}}
+test binary-48.2 {Tcl_BinaryObjCmd: format} {
+ list [catch {binary format t blat} msg] $msg
+} {1 {expected integer but got "blat"}}
+test binary-48.3 {Tcl_BinaryObjCmd: format} {
+ binary format S0 0x50
+} {}
+test binary-48.4 {Tcl_BinaryObjCmd: format} bigEndian {
+ binary format t 0x50
+} \x00P
+test binary-48.5 {Tcl_BinaryObjCmd: format} littleEndian {
+ binary format t 0x50
+} P\x00
+test binary-48.6 {Tcl_BinaryObjCmd: format} bigEndian {
+ binary format t 0x5052
+} PR
+test binary-48.7 {Tcl_BinaryObjCmd: format} littleEndian {
+ binary format t 0x5052
+} RP
+test binary-48.8 {Tcl_BinaryObjCmd: format} bigEndian {
+ binary format t 0x505251 0x53
+} RQ
+test binary-48.9 {Tcl_BinaryObjCmd: format} littleEndian {
+ binary format t 0x505251 0x53
+} QR
+test binary-48.10 {Tcl_BinaryObjCmd: format} bigEndian {
+ binary format t2 {0x50 0x52}
+} \x00P\x00R
+test binary-48.11 {Tcl_BinaryObjCmd: format} littleEndian {
+ binary format t2 {0x50 0x52}
+} P\x00R\x00
+test binary-48.12 {Tcl_BinaryObjCmd: format} bigEndian {
+ binary format t* {0x5051 0x52}
+} PQ\x00R
+test binary-48.13 {Tcl_BinaryObjCmd: format} littleEndian {
+ binary format t* {0x5051 0x52}
+} QPR\x00
+test binary-48.14 {Tcl_BinaryObjCmd: format} bigEndian {
+ binary format t2 {0x50 0x52 0x53} 0x54
+} \x00P\x00R
+test binary-48.15 {Tcl_BinaryObjCmd: format} littleEndian {
+ binary format t2 {0x50 0x52 0x53} 0x54
+} P\x00R\x00
+test binary-48.16 {Tcl_BinaryObjCmd: format} {
+ list [catch {binary format t2 {0x50}} msg] $msg
+} {1 {number of elements in list does not match count}}
+test binary-48.17 {Tcl_BinaryObjCmd: format} {
+ set a {0x50 0x51}
+ list [catch {binary format t $a} msg] $msg
+} [list 1 "expected integer but got \"0x50 0x51\""]
+test binary-48.18 {Tcl_BinaryObjCmd: format} bigEndian {
+ set a {0x50 0x51}
+ binary format t1 $a
+} \x00P
+test binary-48.19 {Tcl_BinaryObjCmd: format} littleEndian {
+ set a {0x50 0x51}
+ binary format t1 $a
+} P\x00
+
+# format n
+test binary-49.1 {Tcl_BinaryObjCmd: format} {
+ list [catch {binary format n} msg] $msg
+} {1 {not enough arguments for all format specifiers}}
+test binary-49.2 {Tcl_BinaryObjCmd: format} {
+ list [catch {binary format n blat} msg] $msg
+} {1 {expected integer but got "blat"}}
+test binary-49.3 {Tcl_BinaryObjCmd: format} {
+ binary format n0 0x50
+} {}
+test binary-49.4 {Tcl_BinaryObjCmd: format} littleEndian {
+ binary format n 0x50
+} P\x00\x00\x00
+test binary-49.5 {Tcl_BinaryObjCmd: format} littleEndian {
+ binary format n 0x5052
+} RP\x00\x00
+test binary-49.6 {Tcl_BinaryObjCmd: format} littleEndian {
+ binary format n 0x505251 0x53
+} QRP\x00
+test binary-49.7 {Tcl_BinaryObjCmd: format} littleEndian {
+ binary format i1 {0x505251 0x53}
+} QRP\x00
+test binary-49.8 {Tcl_BinaryObjCmd: format} littleEndian {
+ binary format n 0x53525150
+} PQRS
+test binary-49.9 {Tcl_BinaryObjCmd: format} littleEndian {
+ binary format n2 {0x50 0x52}
+} P\x00\x00\x00R\x00\x00\x00
+test binary-49.10 {Tcl_BinaryObjCmd: format} littleEndian {
+ binary format n* {0x50515253 0x52}
+} SRQPR\x00\x00\x00
+test binary-49.11 {Tcl_BinaryObjCmd: format} {
+ list [catch {binary format n2 {0x50}} msg] $msg
+} {1 {number of elements in list does not match count}}
+test binary-49.12 {Tcl_BinaryObjCmd: format} {
+ set a {0x50 0x51}
+ list [catch {binary format n $a} msg] $msg
+} [list 1 "expected integer but got \"0x50 0x51\""]
+test binary-49.13 {Tcl_BinaryObjCmd: format} littleEndian {
+ set a {0x50 0x51}
+ binary format n1 $a
+} P\x00\x00\x00
+test binary-49.14 {Tcl_BinaryObjCmd: format} bigEndian {
+ binary format n 0x50
+} \x00\x00\x00P
+test binary-49.15 {Tcl_BinaryObjCmd: format} bigEndian {
+ binary format n 0x5052
+} \x00\x00PR
+test binary-49.16 {Tcl_BinaryObjCmd: format} bigEndian {
+ binary format n 0x505251 0x53
+} \x00PRQ
+test binary-49.17 {Tcl_BinaryObjCmd: format} bigEndian {
+ binary format i1 {0x505251 0x53}
+} QRP\x00
+test binary-49.18 {Tcl_BinaryObjCmd: format} bigEndian {
+ binary format n 0x53525150
+} SRQP
+test binary-49.19 {Tcl_BinaryObjCmd: format} bigEndian {
+ binary format n2 {0x50 0x52}
+} \x00\x00\x00P\x00\x00\x00R
+test binary-49.20 {Tcl_BinaryObjCmd: format} bigEndian {
+ binary format n* {0x50515253 0x52}
+} PQRS\x00\x00\x00R
+
+# format m
+test binary-50.1 {Tcl_BinaryObjCmd: format wide int} littleEndian {
+ binary format m 7810179016327718216
+} HelloTcl
+test binary-50.2 {Tcl_BinaryObjCmd: format wide int} bigEndian {
+ binary format m 7810179016327718216
+} lcTolleH
+test binary-50.3 {Tcl_BinaryObjCmd: scan wide int with bit 31 set} littleEndian {
+ binary scan [binary format m [expr {wide(3) << 31}]] w x
+ set x
+} 6442450944
+test binary-50.4 {Tcl_BinaryObjCmd: scan wide int with bit 31 set} bigEndian {
+ binary scan [binary format m [expr {wide(3) << 31}]] W x
+ set x
+} 6442450944
+
+
+# format Q/q
+test binary-51.1 {Tcl_BinaryObjCmd: format} {
+ list [catch {binary format Q} msg] $msg
+} {1 {not enough arguments for all format specifiers}}
+test binary-51.2 {Tcl_BinaryObjCmd: format} {
+ list [catch {binary format q blat} msg] $msg
+} {1 {expected floating-point number but got "blat"}}
+test binary-51.3 {Tcl_BinaryObjCmd: format} {
+ binary format q0 1.6
+} {}
+test binary-51.4 {Tcl_BinaryObjCmd: format} {} {
+ binary format Q 1.6
+} \x3f\xf9\x99\x99\x99\x99\x99\x9a
+test binary-51.5 {Tcl_BinaryObjCmd: format} {} {
+ binary format q 1.6
+} \x9a\x99\x99\x99\x99\x99\xf9\x3f
+test binary-51.6 {Tcl_BinaryObjCmd: format} {} {
+ binary format Q* {1.6 3.4}
+} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33
+test binary-51.7 {Tcl_BinaryObjCmd: format} {} {
+ binary format q* {1.6 3.4}
+} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40
+test binary-51.8 {Tcl_BinaryObjCmd: format} {} {
+ binary format Q2 {1.6 3.4}
+} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33
+test binary-51.9 {Tcl_BinaryObjCmd: format} {} {
+ binary format q2 {1.6 3.4}
+} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40
+test binary-51.10 {Tcl_BinaryObjCmd: format} {} {
+ binary format Q2 {1.6 3.4 5.6}
+} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33
+test binary-51.11 {Tcl_BinaryObjCmd: format} {} {
+ binary format q2 {1.6 3.4 5.6}
+} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40
+test binary-51.14 {Tcl_BinaryObjCmd: format} {
+ list [catch {binary format q2 {1.6}} msg] $msg
+} {1 {number of elements in list does not match count}}
+test binary-51.15 {Tcl_BinaryObjCmd: format} {
+ set a {1.6 3.4}
+ list [catch {binary format q $a} msg] $msg
+} [list 1 "expected floating-point number but got \"1.6 3.4\""]
+test binary-51.16 {Tcl_BinaryObjCmd: format} {} {
+ set a {1.6 3.4}
+ binary format Q1 $a
+} \x3f\xf9\x99\x99\x99\x99\x99\x9a
+test binary-51.17 {Tcl_BinaryObjCmd: format} {} {
+ set a {1.6 3.4}
+ binary format q1 $a
+} \x9a\x99\x99\x99\x99\x99\xf9\x3f
+
+# format R/r
+test binary-53.1 {Tcl_BinaryObjCmd: format} {
+ list [catch {binary format r} msg] $msg
+} {1 {not enough arguments for all format specifiers}}
+test binary-53.2 {Tcl_BinaryObjCmd: format} {
+ list [catch {binary format r blat} msg] $msg
+} {1 {expected floating-point number but got "blat"}}
+test binary-53.3 {Tcl_BinaryObjCmd: format} {
+ binary format f0 1.6
+} {}
+test binary-53.4 {Tcl_BinaryObjCmd: format} {} {
+ binary format R 1.6
+} \x3f\xcc\xcc\xcd
+test binary-53.5 {Tcl_BinaryObjCmd: format} {} {
+ binary format r 1.6
+} \xcd\xcc\xcc\x3f
+test binary-53.6 {Tcl_BinaryObjCmd: format} {} {
+ binary format R* {1.6 3.4}
+} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a
+test binary-53.7 {Tcl_BinaryObjCmd: format} {} {
+ binary format r* {1.6 3.4}
+} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40
+test binary-53.8 {Tcl_BinaryObjCmd: format} {} {
+ binary format R2 {1.6 3.4}
+} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a
+test binary-53.9 {Tcl_BinaryObjCmd: format} {} {
+ binary format r2 {1.6 3.4}
+} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40
+test binary-53.10 {Tcl_BinaryObjCmd: format} {} {
+ binary format R2 {1.6 3.4 5.6}
+} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a
+test binary-53.11 {Tcl_BinaryObjCmd: format} {} {
+ binary format r2 {1.6 3.4 5.6}
+} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40
+test binary-53.12 {Tcl_BinaryObjCmd: float overflow} {} {
+ binary format R -3.402825e+38
+} \xff\x7f\xff\xff
+test binary-53.13 {Tcl_BinaryObjCmd: float overflow} {} {
+ binary format r -3.402825e+38
+} \xff\xff\x7f\xff
+test binary-53.14 {Tcl_BinaryObjCmd: float underflow} {} {
+ binary format R -3.402825e-100
+} \x80\x00\x00\x00
+test binary-53.15 {Tcl_BinaryObjCmd: float underflow} {} {
+ binary format r -3.402825e-100
+} \x00\x00\x00\x80
+test binary-53.16 {Tcl_BinaryObjCmd: format} {
+ list [catch {binary format r2 {1.6}} msg] $msg
+} {1 {number of elements in list does not match count}}
+test binary-53.17 {Tcl_BinaryObjCmd: format} {
+ set a {1.6 3.4}
+ list [catch {binary format r $a} msg] $msg
+} [list 1 "expected floating-point number but got \"1.6 3.4\""]
+test binary-53.18 {Tcl_BinaryObjCmd: format} {} {
+ set a {1.6 3.4}
+ binary format R1 $a
+} \x3f\xcc\xcc\xcd
+test binary-53.19 {Tcl_BinaryObjCmd: format} {} {
+ set a {1.6 3.4}
+ binary format r1 $a
+} \xcd\xcc\xcc\x3f
+
+# scan t (s)
+test binary-54.1 {Tcl_BinaryObjCmd: scan} {
+ list [catch {binary scan abc t} msg] $msg
+} {1 {not enough arguments for all format specifiers}}
+test binary-54.2 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ list [binary scan \x52\xa3\x53\x54 t* arg1] $arg1
+} {1 {-23726 21587}}
+test binary-54.3 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ list [binary scan \x52\xa3\x53\x54 t arg1] $arg1
+} {1 -23726}
+test binary-54.4 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ list [binary scan \x52\xa3 t1 arg1] $arg1
+} {1 -23726}
+test binary-54.5 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ list [binary scan \x52\xa3 t0 arg1] $arg1
+} {1 {}}
+test binary-54.6 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ list [binary scan \x52\xa3\x53\x54 t2 arg1] $arg1
+} {1 {-23726 21587}}
+test binary-54.7 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ set arg1 foo
+ list [binary scan \x52 t1 arg1] $arg1
+} {0 foo}
+test binary-54.8 {Tcl_BinaryObjCmd: scan} {} {
+ catch {unset arg1}
+ set arg1 1
+ list [catch {binary scan \x52\x53 t1 arg1(a)} msg] $msg
+} {1 {can't set "arg1(a)": variable isn't array}}
+test binary-54.9 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1 arg2}
+ set arg1 foo
+ set arg2 bar
+ list [binary scan \x52\xa3\x53\x54\x05 t2c* arg1 arg2] $arg1 $arg2
+} {2 {-23726 21587} 5}
+test binary-54.10 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1 arg2}
+ set arg1 foo
+ set arg2 bar
+ list [binary scan \x00\x80\x00\x80 tut arg1 arg2] $arg1 $arg2
+} {2 32768 -32768}
+test binary-54.11 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1 arg2}
+ set arg1 foo
+ set arg2 bar
+ list [binary scan \x00\x80\x00\x80 ttu arg1 arg2] $arg1 $arg2
+} {2 -32768 32768}
+
+# scan t (b)
+test binary-55.1 {Tcl_BinaryObjCmd: scan} {
+ list [catch {binary scan abc t} msg] $msg
+} {1 {not enough arguments for all format specifiers}}
+test binary-55.2 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ list [binary scan \x52\xa3\x53\x54 t* arg1] $arg1
+} {1 {21155 21332}}
+test binary-55.3 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ list [binary scan \x52\xa3\x53\x54 t arg1] $arg1
+} {1 21155}
+test binary-55.4 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ list [binary scan \x52\xa3 t1 arg1] $arg1
+} {1 21155}
+test binary-55.5 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ list [binary scan \x52\xa3 t0 arg1] $arg1
+} {1 {}}
+test binary-55.6 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ list [binary scan \x52\xa3\x53\x54 t2 arg1] $arg1
+} {1 {21155 21332}}
+test binary-55.7 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ set arg1 foo
+ list [binary scan \x52 t1 arg1] $arg1
+} {0 foo}
+test binary-55.8 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1}
+ set arg1 1
+ list [catch {binary scan \x52\x53 t1 arg1(a)} msg] $msg
+} {1 {can't set "arg1(a)": variable isn't array}}
+test binary-55.9 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1 arg2}
+ set arg1 foo
+ set arg2 bar
+ list [binary scan \x52\xa3\x53\x54\x05 t2c* arg1 arg2] $arg1 $arg2
+} {2 {21155 21332} 5}
+test binary-55.10 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1 arg2}
+ set arg1 foo
+ set arg2 bar
+ list [binary scan \x80\x00\x80\x00 tut arg1 arg2] $arg1 $arg2
+} {2 32768 -32768}
+test binary-55.11 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1 arg2}
+ set arg1 foo
+ set arg2 bar
+ list [binary scan \x80\x00\x80\x00 ttu arg1 arg2] $arg1 $arg2
+} {2 -32768 32768}
+
+# scan n (s)
+test binary-56.1 {Tcl_BinaryObjCmd: scan} {
+ list [catch {binary scan abc n} msg] $msg
+} {1 {not enough arguments for all format specifiers}}
+test binary-56.2 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n* arg1] $arg1
+} {1 {1414767442 67305985}}
+test binary-56.3 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n arg1] $arg1
+} {1 1414767442}
+test binary-56.4 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ list [binary scan \x52\xa3\x53\x54 n1 arg1] $arg1
+} {1 1414767442}
+test binary-56.5 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ list [binary scan \x52\xa3\x53 n0 arg1] $arg1
+} {1 {}}
+test binary-56.6 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n2 arg1] $arg1
+} {1 {1414767442 67305985}}
+test binary-56.7 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ set arg1 foo
+ list [binary scan \x52 n1 arg1] $arg1
+} {0 foo}
+test binary-56.8 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1}
+ set arg1 1
+ list [catch {binary scan \x52\x53\x53\x54 n1 arg1(a)} msg] $msg
+} {1 {can't set "arg1(a)": variable isn't array}}
+test binary-56.9 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1 arg2}
+ set arg1 foo
+ set arg2 bar
+ list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04\x05 n2c* arg1 arg2] $arg1 $arg2
+} {2 {1414767442 67305985} 5}
+test binary-56.10 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1 arg2}
+ set arg1 foo
+ set arg2 bar
+ list [binary scan \x80\x00\x00\x00\x80\x00\x00\x00 nun arg1 arg2] $arg1 $arg2
+} {2 128 128}
+test binary-56.11 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1 arg2}
+ set arg1 foo
+ set arg2 bar
+ list [binary scan \x00\x00\x00\x80\x00\x00\x00\x80 nun arg1 arg2] $arg1 $arg2
+} {2 2147483648 -2147483648}
+
+# scan n (b)
+test binary-57.1 {Tcl_BinaryObjCmd: scan} {
+ list [catch {binary scan abc n} msg] $msg
+} {1 {not enough arguments for all format specifiers}}
+test binary-57.2 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n* arg1] $arg1
+} {1 {1386435412 16909060}}
+test binary-57.3 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n arg1] $arg1
+} {1 1386435412}
+test binary-57.4 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ list [binary scan \x52\xa3\x53\x54 n1 arg1] $arg1
+} {1 1386435412}
+test binary-57.5 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ list [binary scan \x52\xa3\x53 n0 arg1] $arg1
+} {1 {}}
+test binary-57.6 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n2 arg1] $arg1
+} {1 {1386435412 16909060}}
+test binary-57.7 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ set arg1 foo
+ list [binary scan \x52 n1 arg1] $arg1
+} {0 foo}
+test binary-57.8 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1}
+ set arg1 1
+ list [catch {binary scan \x52\x53\x53\x54 n1 arg1(a)} msg] $msg
+} {1 {can't set "arg1(a)": variable isn't array}}
+test binary-57.9 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1 arg2}
+ set arg1 foo
+ set arg2 bar
+ list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04\x05 n2c* arg1 arg2] $arg1 $arg2
+} {2 {1386435412 16909060} 5}
+test binary-57.10 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1 arg2}
+ set arg1 foo
+ set arg2 bar
+ list [binary scan \x80\x00\x00\x00\x80\x00\x00\x00 nun arg1 arg2] $arg1 $arg2
+} {2 2147483648 -2147483648}
+test binary-57.11 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1 arg2}
+ set arg1 foo
+ set arg2 bar
+ list [binary scan \x00\x00\x00\x80\x00\x00\x00\x80 nun arg1 arg2] $arg1 $arg2
+} {2 128 128}
+
+# scan Q/q
+test binary-58.1 {Tcl_BinaryObjCmd: scan} {
+ list [catch {binary scan abc q} msg] $msg
+} {1 {not enough arguments for all format specifiers}}
+test binary-58.2 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 Q* arg1] $arg1
+} {1 {1.6 3.4}}
+test binary-58.3 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 q* arg1] $arg1
+} {1 {1.6 3.4}}
+test binary-58.4 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 Q arg1] $arg1
+} {1 1.6}
+test binary-58.5 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 q arg1] $arg1
+} {1 1.6}
+test binary-58.6 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a Q1 arg1] $arg1
+} {1 1.6}
+test binary-58.7 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f q1 arg1] $arg1
+} {1 1.6}
+test binary-58.8 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a Q0 arg1] $arg1
+} {1 {}}
+test binary-58.9 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f q0 arg1] $arg1
+} {1 {}}
+test binary-58.10 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 Q2 arg1] $arg1
+} {1 {1.6 3.4}}
+test binary-58.11 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 q2 arg1] $arg1
+} {1 {1.6 3.4}}
+test binary-58.12 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1}
+ set arg1 foo
+ list [binary scan \x52 q1 arg1] $arg1
+} {0 foo}
+test binary-58.13 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1}
+ set arg1 1
+ list [catch {binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a q1 arg1(a)} msg] $msg
+} {1 {can't set "arg1(a)": variable isn't array}}
+test binary-58.14 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1 arg2}
+ set arg1 foo
+ set arg2 bar
+ list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33\x05 Q2c* arg1 arg2] $arg1 $arg2
+} {2 {1.6 3.4} 5}
+test binary-58.15 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1 arg2}
+ set arg1 foo
+ set arg2 bar
+ list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40\x05 q2c* arg1 arg2] $arg1 $arg2
+} {2 {1.6 3.4} 5}
+
+# scan R/r
+test binary-59.1 {Tcl_BinaryObjCmd: scan} {
+ list [catch {binary scan abc r} msg] $msg
+} {1 {not enough arguments for all format specifiers}}
+test binary-59.2 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a R* arg1] $arg1
+} {1 {1.600000023841858 3.4000000953674316}}
+test binary-59.3 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 r* arg1] $arg1
+} {1 {1.600000023841858 3.4000000953674316}}
+test binary-59.4 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a R arg1] $arg1
+} {1 1.600000023841858}
+test binary-59.5 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 r arg1] $arg1
+} {1 1.600000023841858}
+test binary-59.6 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ list [binary scan \x3f\xcc\xcc\xcd R1 arg1] $arg1
+} {1 1.600000023841858}
+test binary-59.7 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ list [binary scan \xcd\xcc\xcc\x3f r1 arg1] $arg1
+} {1 1.600000023841858}
+test binary-59.8 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ list [binary scan \x3f\xcc\xcc\xcd R0 arg1] $arg1
+} {1 {}}
+test binary-59.9 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ list [binary scan \xcd\xcc\xcc\x3f r0 arg1] $arg1
+} {1 {}}
+test binary-59.10 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1}
+ list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a R2 arg1] $arg1
+} {1 {1.600000023841858 3.4000000953674316}}
+test binary-59.11 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1}
+ list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 r2 arg1] $arg1
+} {1 {1.600000023841858 3.4000000953674316}}
+test binary-59.12 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1}
+ set arg1 foo
+ list [binary scan \x52 r1 arg1] $arg1
+} {0 foo}
+test binary-59.13 {Tcl_BinaryObjCmd: scan} {
+ catch {unset arg1}
+ set arg1 1
+ list [catch {binary scan \x3f\xcc\xcc\xcd r1 arg1(a)} msg] $msg
+} {1 {can't set "arg1(a)": variable isn't array}}
+test binary-59.14 {Tcl_BinaryObjCmd: scan} bigEndian {
+ catch {unset arg1 arg2}
+ set arg1 foo
+ set arg2 bar
+ list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a\x05 R2c* arg1 arg2] $arg1 $arg2
+} {2 {1.600000023841858 3.4000000953674316} 5}
+test binary-59.15 {Tcl_BinaryObjCmd: scan} littleEndian {
+ catch {unset arg1 arg2}
+ set arg1 foo
+ set arg2 bar
+ list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40\x05 r2c* arg1 arg2] $arg1 $arg2
+} {2 {1.600000023841858 3.4000000953674316} 5}
+
+test binary-60.1 {[binary format] with NaN} -body {
+ binary scan [binary format dqQfrR NaN NaN NaN NaN NaN NaN] dqQfrR \
+ v1 v2 v3 v4 v5 v6
+ list $v1 $v2 $v3 $v4 $v5 $v6
+} -match regexp -result {NaN(\([[:xdigit:]]+\))? NaN(\([[:xdigit:]]+\))? NaN(\([[:xdigit:]]+\))? NaN(\([[:xdigit:]]+\))? NaN(\([[:xdigit:]]+\))? NaN(\([[:xdigit:]]+\))?}
+
+# scan m
+test binary-61.1 {Tcl_BinaryObjCmd: scan wide int} bigEndian {
+ binary scan HelloTcl m x
+ set x
+} 5216694956358656876
+test binary-61.2 {Tcl_BinaryObjCmd: scan wide int} littleEndian {
+ binary scan lcTolleH m x
+ set x
+} 5216694956358656876
+test binary-61.3 {Tcl_BinaryObjCmd: scan wide int with bit 31 set} littleEndian {
+ binary scan [binary format w [expr {wide(3) << 31}]] m x
+ set x
+} 6442450944
+test binary-61.4 {Tcl_BinaryObjCmd: scan wide int with bit 31 set} bigEndian {
+ binary scan [binary format W [expr {wide(3) << 31}]] m x
+ set x
+} 6442450944
+
+# Big test for correct ordering of data in [expr]
+
+proc testIEEE {} {
+ variable ieeeValues
+ binary scan [binary format dd -1.0 1.0] c* c
+ switch -exact -- $c {
+ {0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
+ # little endian
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \
+ ieeeValues(-Infinity)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \
+ ieeeValues(-Normal)
+ binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
+ ieeeValues(-Subnormal)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
+ ieeeValues(-0)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+0)
+ binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
+ ieeeValues(+Subnormal)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \
+ ieeeValues(+Normal)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
+ ieeeValues(+Infinity)
+ binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
+ ieeeValues(NaN)
+ set ieeeValues(littleEndian) 1
+ return 1
+ }
+ {-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
+ binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Infinity)
+ binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Normal)
+ binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Subnormal)
+ binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-0)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+0)
+ binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Subnormal)
+ binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Normal)
+ binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Infinity)
+ binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(NaN)
+ set ieeeValues(littleEndian) 0
+ return 1
+ }
+ default {
+ return 0
+ }
+ }
+}
+
+testConstraint ieeeFloatingPoint [testIEEE]
+
+# scan/format infinities
+
+test binary-62.1 {infinity} ieeeFloatingPoint {
+ binary scan [binary format q Infinity] w w
+ format 0x%016lx $w
+} 0x7ff0000000000000
+test binary-62.2 {infinity} ieeeFloatingPoint {
+ binary scan [binary format q -Infinity] w w
+ format 0x%016lx $w
+} 0xfff0000000000000
+test binary-62.3 {infinity} ieeeFloatingPoint {
+ binary scan [binary format q Inf] w w
+ format 0x%016lx $w
+} 0x7ff0000000000000
+test binary-62.4 {infinity} ieeeFloatingPoint {
+ binary scan [binary format q -Infinity] w w
+ format 0x%016lx $w
+} 0xfff0000000000000
+test binary-62.5 {infinity} ieeeFloatingPoint {
+ binary scan [binary format w 0x7ff0000000000000] q d
+ set d
+} Inf
+test binary-62.6 {infinity} ieeeFloatingPoint {
+ binary scan [binary format w 0xfff0000000000000] q d
+ set d
+} -Inf
+
+# scan/format Not-a-Number
+
+test binary-63.1 {NaN} ieeeFloatingPoint {
+ binary scan [binary format q NaN] w w
+ format 0x%016lx [expr {$w & 0xfff3ffffffffffff}]
+} 0x7ff0000000000000
+test binary-63.2 {NaN} ieeeFloatingPoint {
+ binary scan [binary format q -NaN] w w
+ format 0x%016lx [expr {$w & 0xfff3ffffffffffff}]
+} 0xfff0000000000000
+test binary-63.3 {NaN} ieeeFloatingPoint {
+ binary scan [binary format q NaN(3123456789aBc)] w w
+ format 0x%016lx [expr {$w & 0xfff3ffffffffffff}]
+} 0x7ff3123456789abc
+test binary-63.4 {NaN} ieeeFloatingPoint {
+ binary scan [binary format q {NaN( 3123456789aBc)}] w w
+ format 0x%016lx [expr {$w & 0xfff3ffffffffffff}]
+} 0x7ff3123456789abc
+test binary-64.1 {NaN} \
+ -constraints ieeeFloatingPoint \
+ -body {
+ binary scan [binary format w 0x7ff8000000000000] q d
+ set d
+ } \
+ -match glob -result NaN*
+test binary-64.2 {NaN} \
+ -constraints ieeeFloatingPoint \
+ -body {
+ binary scan [binary format w 0x7ff0123456789aBc] q d
+ set d
+ } \
+ -match glob -result NaN(*123456789abc)
+
+test binary-65.1 {largest significand} ieeeFloatingPoint {
+ binary scan [binary format w 0x3fcfffffffffffff] q d
+ set d
+} 0.24999999999999997
+test binary-65.2 {smallest significand} ieeeFloatingPoint {
+ binary scan [binary format w 0x3fd0000000000000] q d
+ set d
+} 0.25
+test binary-65.3 {largest significand} ieeeFloatingPoint {
+ binary scan [binary format w 0x3fdfffffffffffff] q d
+ set d
+} 0.49999999999999994
+test binary-65.4 {smallest significand} ieeeFloatingPoint {
+ binary scan [binary format w 0x3fe0000000000000] q d
+ set d
+} 0.5
+test binary-65.5 {largest significand} ieeeFloatingPoint {
+ binary scan [binary format w 0x3fffffffffffffff] q d
+ set d
+} 1.9999999999999998
+test binary-65.6 {smallest significand} ieeeFloatingPoint {
+ binary scan [binary format w 0x4000000000000000] q d
+ set d
+} 2.0
+test binary-65.7 {smallest significand} ieeeFloatingPoint {
+ binary scan [binary format w 0x434fffffffffffff] q d
+ set d
+} 18014398509481982.0
+test binary-65.8 {largest significand} ieeeFloatingPoint {
+ binary scan [binary format w 0x4350000000000000] q d
+ set d
+} 18014398509481984.0
+test binary-65.9 {largest significand} ieeeFloatingPoint {
+ binary scan [binary format w 0x4350000000000001] q d
+ set d
+} 18014398509481988.0
+
# cleanup
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/case.test b/tests/case.test
index f310113..2960c9d 100644
--- a/tests/case.test
+++ b/tests/case.test
@@ -40,7 +40,7 @@ test case-1.7 {list of patterns} {
test case-2.1 {error in executed command} {
list [catch {case a in a {error "Just a test"} default {format 1}} msg] \
- $msg $errorInfo
+ $msg $::errorInfo
} {1 {Just a test} {Just a test
while executing
"error "Just a test""
@@ -58,7 +58,7 @@ test case-2.4 {error: pattern with no body} {
} {1 {extra case pattern with no body}}
test case-2.5 {error in default command} {
list [catch {case foo in a {error case1} default {error case2} \
- b {error case 3}} msg] $msg $errorInfo
+ b {error case 3}} msg] $msg $::errorInfo
} {1 case2 {case2
while executing
"error case2"
@@ -87,15 +87,3 @@ test case-3.3 {single-argument form for pattern/command pairs} {
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/chan.test b/tests/chan.test
new file mode 100644
index 0000000..f5e35bc
--- /dev/null
+++ b/tests/chan.test
@@ -0,0 +1,229 @@
+# This file contains a collection of tests for the Tcl built-in 'chan'
+# command. Sourcing this file into Tcl runs the tests and generates
+# output for errors. No output means no errors were found.
+#
+# Copyright (c) 2005 Donal K. Fellows
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+if {[lsearch [namespace children] ::tcltest] == -1} {
+ package require tcltest 2
+ namespace import -force ::tcltest::*
+}
+
+#
+# Note: The tests for the chan methods "create" and "postevent"
+# currently reside in the file "ioCmd.test".
+#
+
+test chan-1.1 {chan command general syntax} -body {
+ chan
+} -returnCodes error -result "wrong # args: should be \"chan subcommand ?argument ...?\""
+test chan-1.2 {chan command general syntax} -body {
+ chan FOOBAR
+} -returnCodes error -result "unknown or ambiguous subcommand \"FOOBAR\": must be blocked, close, configure, copy, create, eof, event, flush, gets, names, pending, postevent, puts, read, seek, tell, or truncate"
+
+test chan-2.1 {chan command: blocked subcommand} -body {
+ chan blocked foo bar
+} -returnCodes error -result "wrong # args: should be \"chan blocked channelId\""
+
+test chan-3.1 {chan command: close subcommand} -body {
+ chan close foo bar
+} -returnCodes error -result "wrong # args: should be \"chan close channelId\""
+
+test chan-4.1 {chan command: configure subcommand} -body {
+ chan configure
+} -returnCodes error -result "wrong # args: should be \"chan configure channelId ?optionName? ?value? ?optionName value?...\""
+test chan-4.2 {chan command: [Bug 800753]} -body {
+ chan configure stdout -eofchar \u0100
+} -returnCodes error -match glob -result {bad value*}
+test chan-4.3 {chan command: [Bug 800753]} -body {
+ chan configure stdout -eofchar \u0000
+} -returnCodes error -match glob -result {bad value*}
+test chan-4.4 {chan command: check valid inValue, no outValue} -body {
+ chan configure stdout -eofchar [list \x27 {}]
+} -returnCodes ok -result {}
+test chan-4.5 {chan command: check valid inValue, invalid outValue} -body {
+ chan configure stdout -eofchar [list \x27 \x80]
+} -returnCodes error -match glob -result {bad value for -eofchar:*}
+test chan-4.6 {chan command: check no inValue, valid outValue} -body {
+ chan configure stdout -eofchar [list {} \x27]
+} -returnCodes ok -result {}
+
+test chan-5.1 {chan command: copy subcommand} -body {
+ chan copy foo
+} -returnCodes error -result "wrong # args: should be \"chan copy input output ?-size size? ?-command callback?\""
+
+test chan-6.1 {chan command: eof subcommand} -body {
+ chan eof foo bar
+} -returnCodes error -result "wrong # args: should be \"chan eof channelId\""
+
+test chan-7.1 {chan command: event subcommand} -body {
+ chan event foo
+} -returnCodes error -result "wrong # args: should be \"chan event channelId event ?script?\""
+
+test chan-8.1 {chan command: flush subcommand} -body {
+ chan flush foo bar
+} -returnCodes error -result "wrong # args: should be \"chan flush channelId\""
+
+test chan-9.1 {chan command: gets subcommand} -body {
+ chan gets
+} -returnCodes error -result "wrong # args: should be \"chan gets channelId ?varName?\""
+
+test chan-10.1 {chan command: names subcommand} -body {
+ chan names foo bar
+} -returnCodes error -result "wrong # args: should be \"chan names ?pattern?\""
+
+test chan-11.1 {chan command: puts subcommand} -body {
+ chan puts foo bar foo bar
+} -returnCodes error -result "wrong # args: should be \"chan puts ?-nonewline? ?channelId? string\""
+
+test chan-12.1 {chan command: read subcommand} -body {
+ chan read
+} -returnCodes error -result "wrong # args: should be \"chan read channelId ?numChars?\" or \"chan read ?-nonewline? channelId\""
+
+test chan-13.1 {chan command: seek subcommand} -body {
+ chan seek foo bar foo bar
+} -returnCodes error -result "wrong # args: should be \"chan seek channelId offset ?origin?\""
+
+test chan-14.1 {chan command: tell subcommand} -body {
+ chan tell foo bar
+} -returnCodes error -result "wrong # args: should be \"chan tell channelId\""
+
+test chan-15.1 {chan command: truncate subcommand} -body {
+ chan truncate foo bar foo bar
+} -returnCodes error -result "wrong \# args: should be \"chan truncate channelId ?length?\""
+test chan-15.2 {chan command: truncate subcommand} -setup {
+ set file [makeFile {} testTruncate]
+ set f [open $file w+]
+ fconfigure $f -translation binary
+} -body {
+ seek $f 0
+ puts -nonewline $f 12345
+ seek $f 0
+ chan truncate $f 2
+ read $f
+} -result 12 -cleanup {
+ catch {close $f}
+ catch {removeFile $file}
+}
+
+# TIP 287: chan pending
+test chan-16.1 {chan command: pending subcommand} -body {
+ chan pending
+} -returnCodes error -result "wrong # args: should be \"chan pending mode channelId\""
+test chan-16.2 {chan command: pending subcommand} -body {
+ chan pending stdin
+} -returnCodes error -result "wrong # args: should be \"chan pending mode channelId\""
+test chan-16.3 {chan command: pending subcommand} -body {
+ chan pending stdin stdout stderr
+} -returnCodes error -result "wrong # args: should be \"chan pending mode channelId\""
+test chan-16.4 {chan command: pending subcommand} -body {
+ chan pending {input output} stdout
+} -returnCodes error -result "bad mode \"input output\": must be input or output"
+test chan-16.5 {chan command: pending input subcommand} -body {
+ chan pending input stdout
+} -result -1
+test chan-16.6 {chan command: pending input subcommand} -body {
+ chan pending input stdin
+} -result 0
+test chan-16.7 {chan command: pending input subcommand} -body {
+ chan pending input FOOBAR
+} -returnCodes error -result "can not find channel named \"FOOBAR\""
+test chan-16.8 {chan command: pending input subcommand} -setup {
+ set file [makeFile {} testAvailable]
+ set f [open $file w+]
+ chan configure $f -translation lf -buffering line
+} -body {
+ chan puts $f foo
+ chan puts $f bar
+ chan puts $f baz
+ chan seek $f 0
+ chan gets $f
+ chan pending input $f
+} -result 8 -cleanup {
+ catch {chan close $f}
+ catch {removeFile $file}
+}
+test chan-16.9 {chan command: pending input subcommand} -setup {
+ proc chan-16.9-accept {sock addr port} {
+ chan configure $sock -blocking 0 -buffering line -buffersize 32
+ chan event $sock readable [list chan-16.9-readable $sock]
+ }
+
+ proc chan-16.9-readable {sock} {
+ set r [chan gets $sock line]
+ set l [string length $line]
+ set e [chan eof $sock]
+ set b [chan blocked $sock]
+ set i [chan pending input $sock]
+
+ lappend ::chan-16.9-data $r $l $e $b $i
+
+ if {$r != -1 || $e || $l || !$b || $i > 128} {
+ set data [read $sock $i]
+ lappend ::chan-16.9-data [string range $data 0 2]
+ lappend ::chan-16.9-data [string range $data end-2 end]
+ set ::chan-16.9-done 1
+ chan event $sock readable {}
+ } else {
+ after idle chan-16.9-client
+ }
+ }
+
+ proc chan-16.9-client {} {
+ chan puts -nonewline $::client ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890
+ chan flush $::client
+ }
+
+ set ::server [socket -server chan-16.9-accept -myaddr 127.0.0.1 0]
+ set ::client [socket 127.0.0.1 [lindex [fconfigure $::server -sockname] 2]]
+ set ::chan-16.9-data [list]
+ set ::chan-16.9-done 0
+} -body {
+ after idle chan-16.9-client
+ vwait ::chan-16.9-done
+ set ::chan-16.9-data
+} -result {-1 0 0 1 36 -1 0 0 1 72 -1 0 0 1 108 -1 0 0 1 144 ABC 890} -cleanup {
+ catch {chan close $client}
+ catch {chan close $server}
+ rename chan-16.9-accept {}
+ rename chan-16.9-readable {}
+ rename chan-16.9-client {}
+ unset -nocomplain ::chan-16.9-data
+ unset -nocomplain ::chan-16.9-done
+ unset -nocomplain ::server
+ unset -nocomplain ::client
+}
+test chan-16.10 {chan command: pending output subcommand} -body {
+ chan pending output stdin
+} -result -1
+test chan-16.11 {chan command: pending output subcommand} -body {
+ chan pending output stdout
+} -result 0
+test chan-16.12 {chan command: pending output subcommand} -body {
+ chan pending output FOOBAR
+} -returnCodes error -result "can not find channel named \"FOOBAR\""
+test chan-16.13 {chan command: pending output subcommand} -setup {
+ set file [makeFile {} testPendingOutput]
+ set f [open $file w+]
+ chan configure $f -translation lf -buffering full -buffersize 1024
+} -body {
+ set result [list]
+ chan puts $f [string repeat x 512]
+ lappend result [chan pending output $f]
+ chan flush $f
+ lappend result [chan pending output $f]
+} -result [list 513 0] -cleanup {
+ unset -nocomplain result
+ catch {chan close $f}
+ catch {removeFile $file}
+}
+
+cleanupTests
+return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/chanio.test b/tests/chanio.test
new file mode 100644
index 0000000..b195f7b
--- /dev/null
+++ b/tests/chanio.test
@@ -0,0 +1,7705 @@
+# -*- tcl -*-
+# Functionality covered: operation of all IO commands, and all procedures
+# defined in generic/tclIO.c.
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands. Sourcing this file into Tcl runs the tests and
+# generates output for errors. No output means no errors were found.
+#
+# Copyright (c) 1991-1994 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.
+
+if {[catch {package require tcltest 2}]} {
+ chan puts stderr "Skipping tests in [info script]. tcltest 2 required."
+ return
+}
+namespace eval ::tcl::test::io {
+ namespace import ::tcltest::*
+
+ variable umaskValue
+ variable path
+ variable f
+ variable i
+ variable n
+ variable v
+ variable msg
+ variable expected
+
+ testConstraint testchannel [llength [info commands testchannel]]
+ testConstraint exec [llength [info commands exec]]
+ testConstraint openpipe 1
+ testConstraint fileevent [llength [info commands fileevent]]
+ testConstraint fcopy [llength [info commands fcopy]]
+ testConstraint testfevent [llength [info commands testfevent]]
+ testConstraint testchannelevent [llength [info commands testchannelevent]]
+ testConstraint testmainthread [llength [info commands testmainthread]]
+ testConstraint testthread [llength [info commands testthread]]
+
+ # You need a *very* special environment to do some tests. In
+ # particular, many file systems do not support large-files...
+ testConstraint largefileSupport 0
+
+ # some tests can only be run is umask is 2
+ # if "umask" cannot be run, the tests will be skipped.
+ set umaskValue 0
+ testConstraint umask [expr {![catch {set umaskValue [scan [exec /bin/sh -c umask] %o]}]}]
+
+ testConstraint makeFileInHome [expr {![file exists ~/_test_] && [file writable ~]}]
+
+ # set up a long data file for some of the following tests
+
+ set path(longfile) [makeFile {} longfile]
+ set f [open $path(longfile) w]
+ chan configure $f -eofchar {} -translation lf
+ for { set i 0 } { $i < 100 } { incr i} {
+ chan puts $f "#123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
+\#123456789abcdef01
+\#"
+ }
+ chan close $f
+
+ set path(cat) [makeFile {
+ set f stdin
+ if {$argv != ""} {
+ set f [open [lindex $argv 0]]
+ }
+ chan configure $f -encoding binary -translation lf -blocking 0 -eofchar \x1a
+ chan configure stdout -encoding binary -translation lf -buffering none
+ chan event $f readable "foo $f"
+ proc foo {f} {
+ set x [chan read $f]
+ catch {chan puts -nonewline $x}
+ if {[chan eof $f]} {
+ chan close $f
+ exit 0
+ }
+ }
+ vwait forever
+ } cat]
+
+ set thisScript [file join [pwd] [info script]]
+
+ proc contents {file} {
+ set f [open $file]
+ chan configure $f -translation binary
+ set a [chan read $f]
+ chan close $f
+ return $a
+ }
+
+test chan-io-1.5 {Tcl_WriteChars: CheckChannelErrors} {emptyTest} {
+ # no test, need to cause an async error.
+} {}
+set path(test1) [makeFile {} test1]
+test chan-io-1.6 {Tcl_WriteChars: WriteBytes} {
+ set f [open $path(test1) w]
+ chan configure $f -encoding binary
+ chan puts -nonewline $f "a\u4e4d\0"
+ chan close $f
+ contents $path(test1)
+} "a\x4d\x00"
+test chan-io-1.7 {Tcl_WriteChars: WriteChars} {
+ set f [open $path(test1) w]
+ chan configure $f -encoding shiftjis
+ chan puts -nonewline $f "a\u4e4d\0"
+ chan close $f
+ contents $path(test1)
+} "a\x93\xe1\x00"
+set path(test2) [makeFile {} test2]
+test chan-io-1.8 {Tcl_WriteChars: WriteChars} {
+ # This test written for SF bug #506297.
+ #
+ # Executing this test without the fix for the referenced bug
+ # applied to tcl will cause tcl, more specifically WriteChars, to
+ # go into an infinite loop.
+
+ set f [open $path(test2) w]
+ chan configure $f -encoding iso2022-jp
+ chan puts -nonewline $f [format %s%c [string repeat " " 4] 12399]
+ chan close $f
+ contents $path(test2)
+} " \x1b\$B\$O\x1b(B"
+
+test chan-io-1.9 {Tcl_WriteChars: WriteChars} {
+ # When closing a channel with an encoding that appends
+ # escape bytes, check for the case where the escape
+ # bytes overflow the current IO buffer. The bytes
+ # should be moved into a new buffer.
+
+ set data "1234567890 [format %c 12399]"
+
+ set sizes [list]
+
+ # With default buffer size
+ set f [open $path(test2) w]
+ chan configure $f -encoding iso2022-jp
+ chan puts -nonewline $f $data
+ chan close $f
+ lappend sizes [file size $path(test2)]
+
+ # With buffer size equal to the length
+ # of the data, the escape bytes would
+ # go into the next buffer.
+
+ set f [open $path(test2) w]
+ chan configure $f -encoding iso2022-jp -buffersize 16
+ chan puts -nonewline $f $data
+ chan close $f
+ lappend sizes [file size $path(test2)]
+
+ # With buffer size that is large enough
+ # to hold 1 byte of escaped data, but
+ # not all 3. This should not write
+ # the escape bytes to the first buffer
+ # and then again to the second buffer.
+
+ set f [open $path(test2) w]
+ chan configure $f -encoding iso2022-jp -buffersize 17
+ chan puts -nonewline $f $data
+ chan close $f
+ lappend sizes [file size $path(test2)]
+
+ # With buffer size that can hold 2 out of
+ # 3 bytes of escaped data.
+
+ set f [open $path(test2) w]
+ chan configure $f -encoding iso2022-jp -buffersize 18
+ chan puts -nonewline $f $data
+ chan close $f
+ lappend sizes [file size $path(test2)]
+
+ # With buffer size that can hold all the
+ # data and escape bytes.
+
+ set f [open $path(test2) w]
+ chan configure $f -encoding iso2022-jp -buffersize 19
+ chan puts -nonewline $f $data
+ chan close $f
+ lappend sizes [file size $path(test2)]
+
+ set sizes
+} {19 19 19 19 19}
+
+test chan-io-2.1 {WriteBytes} {
+ # loop until all bytes are written
+
+ set f [open $path(test1) w]
+ chan configure $f -encoding binary -buffersize 16 -translation crlf
+ chan puts $f "abcdefghijklmnopqrstuvwxyz"
+ chan close $f
+ contents $path(test1)
+} "abcdefghijklmnopqrstuvwxyz\r\n"
+test chan-io-2.2 {WriteBytes: savedLF > 0} {
+ # After flushing buffer, there was a \n left over from the last
+ # \n -> \r\n expansion. It gets stuck at beginning of this buffer.
+
+ set f [open $path(test1) w]
+ chan configure $f -encoding binary -buffersize 16 -translation crlf
+ chan puts -nonewline $f "123456789012345\n12"
+ set x [list [contents $path(test1)]]
+ chan close $f
+ lappend x [contents $path(test1)]
+} [list "123456789012345\r" "123456789012345\r\n12"]
+test chan-io-2.3 {WriteBytes: flush on line} {
+ # Tcl "line" buffering has weird behavior: if current buffer contains
+ # a \n, entire buffer gets flushed. Logical behavior would be to flush
+ # only up to the \n.
+
+ set f [open $path(test1) w]
+ chan configure $f -encoding binary -buffering line -translation crlf
+ chan puts -nonewline $f "\n12"
+ set x [contents $path(test1)]
+ chan close $f
+ set x
+} "\r\n12"
+test chan-io-2.4 {WriteBytes: reset sawLF after each buffer} {
+ set f [open $path(test1) w]
+ chan configure $f -encoding binary -buffering line -translation lf \
+ -buffersize 16
+ chan puts -nonewline $f "abcdefg\nhijklmnopqrstuvwxyz"
+ set x [list [contents $path(test1)]]
+ chan close $f
+ lappend x [contents $path(test1)]
+} [list "abcdefg\nhijklmno" "abcdefg\nhijklmnopqrstuvwxyz"]
+
+test chan-io-3.1 {WriteChars: compatibility with WriteBytes} {
+ # loop until all bytes are written
+
+ set f [open $path(test1) w]
+ chan configure $f -encoding ascii -buffersize 16 -translation crlf
+ chan puts $f "abcdefghijklmnopqrstuvwxyz"
+ chan close $f
+ contents $path(test1)
+} "abcdefghijklmnopqrstuvwxyz\r\n"
+test chan-io-3.2 {WriteChars: compatibility with WriteBytes: savedLF > 0} {
+ # After flushing buffer, there was a \n left over from the last
+ # \n -> \r\n expansion. It gets stuck at beginning of this buffer.
+
+ set f [open $path(test1) w]
+ chan configure $f -encoding ascii -buffersize 16 -translation crlf
+ chan puts -nonewline $f "123456789012345\n12"
+ set x [list [contents $path(test1)]]
+ chan close $f
+ lappend x [contents $path(test1)]
+} [list "123456789012345\r" "123456789012345\r\n12"]
+test chan-io-3.3 {WriteChars: compatibility with WriteBytes: flush on line} {
+ # Tcl "line" buffering has weird behavior: if current buffer contains
+ # a \n, entire buffer gets flushed. Logical behavior would be to flush
+ # only up to the \n.
+
+ set f [open $path(test1) w]
+ chan configure $f -encoding ascii -buffering line -translation crlf
+ chan puts -nonewline $f "\n12"
+ set x [contents $path(test1)]
+ chan close $f
+ set x
+} "\r\n12"
+test chan-io-3.4 {WriteChars: loop over stage buffer} {
+ # stage buffer maps to more than can be queued at once.
+
+ set f [open $path(test1) w]
+ chan configure $f -encoding jis0208 -buffersize 16
+ chan puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
+ set x [list [contents $path(test1)]]
+ chan close $f
+ lappend x [contents $path(test1)]
+} [list "!)!)!)!)!)!)!)!)" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
+test chan-io-3.5 {WriteChars: saved != 0} {
+ # Bytes produced by UtfToExternal from end of last channel buffer
+ # had to be moved to beginning of next channel buffer to preserve
+ # requested buffersize.
+
+ set f [open $path(test1) w]
+ chan configure $f -encoding jis0208 -buffersize 17
+ chan puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
+ set x [list [contents $path(test1)]]
+ chan close $f
+ lappend x [contents $path(test1)]
+} [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
+test chan-io-3.6 {WriteChars: (stageRead + dstWrote == 0)} {
+ # One incomplete UTF-8 character at end of staging buffer. Backup
+ # in src to the beginning of that UTF-8 character and try again.
+ #
+ # Translate the first 16 bytes, produce 14 bytes of output, 2 left over
+ # (first two bytes of \uff21 in UTF-8). Given those two bytes try
+ # translating them again, find that no bytes are read produced, and break
+ # to outer loop where those two bytes will have the remaining 4 bytes
+ # (the last byte of \uff21 plus the all of \uff22) appended.
+
+ set f [open $path(test1) w]
+ chan configure $f -encoding shiftjis -buffersize 16
+ chan puts -nonewline $f "12345678901234\uff21\uff22"
+ set x [list [contents $path(test1)]]
+ chan close $f
+ lappend x [contents $path(test1)]
+} [list "12345678901234\x82\x60" "12345678901234\x82\x60\x82\x61"]
+test chan-io-3.7 {WriteChars: (bufPtr->nextAdded > bufPtr->length)} {
+ # When translating UTF-8 to external, the produced bytes went past end
+ # of the channel buffer. This is done purpose -- we then truncate the
+ # bytes at the end of the partial character to preserve the requested
+ # blocksize on flush. The truncated bytes are moved to the beginning
+ # of the next channel buffer.
+
+ set f [open $path(test1) w]
+ chan configure $f -encoding jis0208 -buffersize 17
+ chan puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
+ set x [list [contents $path(test1)]]
+ chan close $f
+ lappend x [contents $path(test1)]
+} [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
+test chan-io-3.8 {WriteChars: reset sawLF after each buffer} {
+ set f [open $path(test1) w]
+ chan configure $f -encoding ascii -buffering line -translation lf \
+ -buffersize 16
+ chan puts -nonewline $f "abcdefg\nhijklmnopqrstuvwxyz"
+ set x [list [contents $path(test1)]]
+ chan close $f
+ lappend x [contents $path(test1)]
+} [list "abcdefg\nhijklmno" "abcdefg\nhijklmnopqrstuvwxyz"]
+
+test chan-io-4.1 {TranslateOutputEOL: lf} {
+ # search for \n
+
+ set f [open $path(test1) w]
+ chan configure $f -buffering line -translation lf
+ chan puts $f "abcde"
+ set x [list [contents $path(test1)]]
+ chan close $f
+ lappend x [contents $path(test1)]
+} [list "abcde\n" "abcde\n"]
+test chan-io-4.2 {TranslateOutputEOL: cr} {
+ # search for \n, replace with \r
+
+ set f [open $path(test1) w]
+ chan configure $f -buffering line -translation cr
+ chan puts $f "abcde"
+ set x [list [contents $path(test1)]]
+ chan close $f
+ lappend x [contents $path(test1)]
+} [list "abcde\r" "abcde\r"]
+test chan-io-4.3 {TranslateOutputEOL: crlf} {
+ # simple case: search for \n, replace with \r
+
+ set f [open $path(test1) w]
+ chan configure $f -buffering line -translation crlf
+ chan puts $f "abcde"
+ set x [list [contents $path(test1)]]
+ chan close $f
+ lappend x [contents $path(test1)]
+} [list "abcde\r\n" "abcde\r\n"]
+test chan-io-4.4 {TranslateOutputEOL: crlf} {
+ # keep storing more bytes in output buffer until output buffer is full.
+ # We have 13 bytes initially that would turn into 18 bytes. Fill
+ # dest buffer while (dstEnd < dstMax).
+
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf -buffersize 16
+ chan puts -nonewline $f "1234567\n\n\n\n\nA"
+ set x [list [contents $path(test1)]]
+ chan close $f
+ lappend x [contents $path(test1)]
+} [list "1234567\r\n\r\n\r\n\r\n\r" "1234567\r\n\r\n\r\n\r\n\r\nA"]
+test chan-io-4.5 {TranslateOutputEOL: crlf} {
+ # Check for overflow of the destination buffer
+
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf -buffersize 12
+ chan puts -nonewline $f "12345678901\n456789012345678901234"
+ chan close $f
+ set x [contents $path(test1)]
+} "12345678901\r\n456789012345678901234"
+
+test chan-io-5.1 {CheckFlush: not full} {
+ set f [open $path(test1) w]
+ chan configure $f
+ chan puts -nonewline $f "12345678901234567890"
+ set x [list [contents $path(test1)]]
+ chan close $f
+ lappend x [contents $path(test1)]
+} [list "" "12345678901234567890"]
+test chan-io-5.2 {CheckFlush: full} {
+ set f [open $path(test1) w]
+ chan configure $f -buffersize 16
+ chan puts -nonewline $f "12345678901234567890"
+ set x [list [contents $path(test1)]]
+ chan close $f
+ lappend x [contents $path(test1)]
+} [list "1234567890123456" "12345678901234567890"]
+test chan-io-5.3 {CheckFlush: not line} {
+ set f [open $path(test1) w]
+ chan configure $f -buffering line
+ chan puts -nonewline $f "12345678901234567890"
+ set x [list [contents $path(test1)]]
+ chan close $f
+ lappend x [contents $path(test1)]
+} [list "" "12345678901234567890"]
+test chan-io-5.4 {CheckFlush: line} {
+ set f [open $path(test1) w]
+ chan configure $f -buffering line -translation lf -encoding ascii
+ chan puts -nonewline $f "1234567890\n1234567890"
+ set x [list [contents $path(test1)]]
+ chan close $f
+ lappend x [contents $path(test1)]
+} [list "1234567890\n1234567890" "1234567890\n1234567890"]
+test chan-io-5.5 {CheckFlush: none} {
+ set f [open $path(test1) w]
+ chan configure $f -buffering none
+ chan puts -nonewline $f "1234567890"
+ set x [list [contents $path(test1)]]
+ chan close $f
+ lappend x [contents $path(test1)]
+} [list "1234567890" "1234567890"]
+
+test chan-io-6.1 {Tcl_GetsObj: working} {
+ set f [open $path(test1) w]
+ chan puts $f "foo\nboo"
+ chan close $f
+ set f [open $path(test1)]
+ set x [chan gets $f]
+ chan close $f
+ set x
+} {foo}
+test chan-io-6.2 {Tcl_GetsObj: CheckChannelErrors() != 0} emptyTest {
+ # no test, need to cause an async error.
+} {}
+test chan-io-6.3 {Tcl_GetsObj: how many have we used?} {
+ # if (bufPtr != NULL) {oldRemoved = bufPtr->nextRemoved}
+
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf
+ chan puts $f "abc\ndefg"
+ chan close $f
+ set f [open $path(test1)]
+ set x [list [chan tell $f] [chan gets $f line] [chan tell $f] [chan gets $f line] $line]
+ chan close $f
+ set x
+} {0 3 5 4 defg}
+test chan-io-6.4 {Tcl_GetsObj: encoding == NULL} {
+ set f [open $path(test1) w]
+ chan configure $f -translation binary
+ chan puts $f "\x81\u1234\0"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation binary
+ set x [list [chan gets $f line] $line]
+ chan close $f
+ set x
+} [list 3 "\x81\x34\x00"]
+test chan-io-6.5 {Tcl_GetsObj: encoding != NULL} {
+ set f [open $path(test1) w]
+ chan configure $f -translation binary
+ chan puts $f "\x88\xea\x92\x9a"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -encoding shiftjis
+ set x [list [chan gets $f line] $line]
+ chan close $f
+ set x
+} [list 2 "\u4e00\u4e01"]
+set a "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
+append a $a
+append a $a
+test chan-io-6.6 {Tcl_GetsObj: loop test} {
+ # if (dst >= dstEnd)
+
+ set f [open $path(test1) w]
+ chan puts $f $a
+ chan puts $f hi
+ chan close $f
+ set f [open $path(test1)]
+ set x [list [chan gets $f line] $line]
+ chan close $f
+ set x
+} [list 256 $a]
+test chan-io-6.7 {Tcl_GetsObj: error in input} {stdio openpipe} {
+ # if (FilterInputBytes(chanPtr, &gs) != 0)
+
+ set f [open "|[list [interpreter] $path(cat)]" w+]
+ chan puts -nonewline $f "hi\nwould"
+ chan flush $f
+ chan gets $f
+ chan configure $f -blocking 0
+ set x [chan gets $f line]
+ chan close $f
+ set x
+} {-1}
+test chan-io-6.8 {Tcl_GetsObj: remember if EOF is seen} {
+ set f [open $path(test1) w]
+ chan puts $f "abcdef\x1aghijk\nwombat"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -eofchar \x1a
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} {6 abcdef -1 {}}
+test chan-io-6.9 {Tcl_GetsObj: remember if EOF is seen} {
+ set f [open $path(test1) w]
+ chan puts $f "abcdefghijk\nwom\u001abat"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -eofchar \x1a
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} {11 abcdefghijk 3 wom}
+# Comprehensive tests
+test chan-io-6.10 {Tcl_GetsObj: lf mode: no chars} {
+ set f [open $path(test1) w]
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation lf
+ set x [list [chan gets $f line] $line]
+ chan close $f
+ set x
+} {-1 {}}
+test chan-io-6.11 {Tcl_GetsObj: lf mode: lone \n} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "\n"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation lf
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} {0 {} -1 {}}
+test chan-io-6.12 {Tcl_GetsObj: lf mode: lone \r} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "\r"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation lf
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} [list 1 "\r" -1 ""]
+test chan-io-6.13 {Tcl_GetsObj: lf mode: 1 char} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f a
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation lf
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} {1 a -1 {}}
+test chan-io-6.14 {Tcl_GetsObj: lf mode: 1 char followed by EOL} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "a\n"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation lf
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} {1 a -1 {}}
+test chan-io-6.15 {Tcl_GetsObj: lf mode: several chars} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "abcd\nefgh\rijkl\r\nmnop"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation lf
+ set x [list [chan gets $f line] $line [chan gets $f line] $line [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} [list 4 "abcd" 10 "efgh\rijkl\r" 4 "mnop" -1 ""]
+test chan-io-6.16 {Tcl_GetsObj: cr mode: no chars} {
+ set f [open $path(test1) w]
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation cr
+ set x [list [chan gets $f line] $line]
+ chan close $f
+ set x
+} {-1 {}}
+test chan-io-6.17 {Tcl_GetsObj: cr mode: lone \n} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "\n"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation cr
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} [list 1 "\n" -1 ""]
+test chan-io-6.18 {Tcl_GetsObj: cr mode: lone \r} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "\r"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation cr
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} {0 {} -1 {}}
+test chan-io-6.19 {Tcl_GetsObj: cr mode: 1 char} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f a
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation cr
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} {1 a -1 {}}
+test chan-io-6.20 {Tcl_GetsObj: cr mode: 1 char followed by EOL} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "a\r"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation cr
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} {1 a -1 {}}
+test chan-io-6.21 {Tcl_GetsObj: cr mode: several chars} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "abcd\nefgh\rijkl\r\nmnop"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation cr
+ set x [list [chan gets $f line] $line [chan gets $f line] $line [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} [list 9 "abcd\nefgh" 4 "ijkl" 5 "\nmnop" -1 ""]
+test chan-io-6.22 {Tcl_GetsObj: crlf mode: no chars} {
+ set f [open $path(test1) w]
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation crlf
+ set x [list [chan gets $f line] $line]
+ chan close $f
+ set x
+} {-1 {}}
+test chan-io-6.23 {Tcl_GetsObj: crlf mode: lone \n} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "\n"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation crlf
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} [list 1 "\n" -1 ""]
+test chan-io-6.24 {Tcl_GetsObj: crlf mode: lone \r} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "\r"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation crlf
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} [list 1 "\r" -1 ""]
+test chan-io-6.25 {Tcl_GetsObj: crlf mode: \r\r} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "\r\r"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation crlf
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} [list 2 "\r\r" -1 ""]
+test chan-io-6.26 {Tcl_GetsObj: crlf mode: \r\n} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "\r\n"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation crlf
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} [list 0 "" -1 ""]
+test chan-io-6.27 {Tcl_GetsObj: crlf mode: 1 char} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f a
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation crlf
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} {1 a -1 {}}
+test chan-io-6.28 {Tcl_GetsObj: crlf mode: 1 char followed by EOL} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "a\r\n"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation crlf
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} {1 a -1 {}}
+test chan-io-6.29 {Tcl_GetsObj: crlf mode: several chars} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "abcd\nefgh\rijkl\r\nmnop"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation crlf
+ set x [list [chan gets $f line] $line [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} [list 14 "abcd\nefgh\rijkl" 4 "mnop" -1 ""]
+test chan-io-6.30 {Tcl_GetsObj: crlf mode: buffer exhausted} {testchannel} {
+ # if (eol >= dstEnd)
+
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "123456789012345\r\nabcdefghijklmnoprstuvwxyz"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation crlf -buffersize 16
+ set x [list [chan gets $f line] $line [testchannel inputbuffered $f]]
+ chan close $f
+ set x
+} [list 15 "123456789012345" 15]
+test chan-io-6.31 {Tcl_GetsObj: crlf mode: buffer exhausted, blocked} {stdio testchannel openpipe fileevent} {
+ # (FilterInputBytes() != 0)
+
+ set f [open "|[list [interpreter] $path(cat)]" w+]
+ chan configure $f -translation {crlf lf} -buffering none
+ chan puts -nonewline $f "bbbbbbbbbbbbbb\r\n123456789012345\r"
+ chan configure $f -buffersize 16
+ set x [chan gets $f]
+ chan configure $f -blocking 0
+ lappend x [chan gets $f line] $line [chan blocked $f] [testchannel inputbuffered $f]
+ chan close $f
+ set x
+} [list "bbbbbbbbbbbbbb" -1 "" 1 16]
+test chan-io-6.32 {Tcl_GetsObj: crlf mode: buffer exhausted, more data} {testchannel} {
+ # not (FilterInputBytes() != 0)
+
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "123456789012345\r\n123"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation crlf -buffersize 16
+ set x [list [chan gets $f line] $line [chan tell $f] [testchannel inputbuffered $f]]
+ chan close $f
+ set x
+} [list 15 "123456789012345" 17 3]
+test chan-io-6.33 {Tcl_GetsObj: crlf mode: buffer exhausted, at eof} {
+ # eol still equals dstEnd
+
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "123456789012345\r"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation crlf -buffersize 16
+ set x [list [chan gets $f line] $line [chan eof $f]]
+ chan close $f
+ set x
+} [list 16 "123456789012345\r" 1]
+test chan-io-6.34 {Tcl_GetsObj: crlf mode: buffer exhausted, not followed by \n} {
+ # not (*eol == '\n')
+
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "123456789012345\rabcd\r\nefg"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation crlf -buffersize 16
+ set x [list [chan gets $f line] $line [chan tell $f]]
+ chan close $f
+ set x
+} [list 20 "123456789012345\rabcd" 22]
+test chan-io-6.35 {Tcl_GetsObj: auto mode: no chars} {
+ set f [open $path(test1) w]
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation auto
+ set x [list [chan gets $f line] $line]
+ chan close $f
+ set x
+} {-1 {}}
+test chan-io-6.36 {Tcl_GetsObj: auto mode: lone \n} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "\n"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation auto
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} [list 0 "" -1 ""]
+test chan-io-6.37 {Tcl_GetsObj: auto mode: lone \r} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "\r"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation auto
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} [list 0 "" -1 ""]
+test chan-io-6.38 {Tcl_GetsObj: auto mode: \r\r} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "\r\r"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation auto
+ set x [list [chan gets $f line] $line [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} [list 0 "" 0 "" -1 ""]
+test chan-io-6.39 {Tcl_GetsObj: auto mode: \r\n} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "\r\n"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation auto
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} [list 0 "" -1 ""]
+test chan-io-6.40 {Tcl_GetsObj: auto mode: 1 char} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f a
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation auto
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} {1 a -1 {}}
+test chan-io-6.41 {Tcl_GetsObj: auto mode: 1 char followed by EOL} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "a\r\n"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation auto
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} {1 a -1 {}}
+test chan-io-6.42 {Tcl_GetsObj: auto mode: several chars} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "abcd\nefgh\rijkl\r\nmnop"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation auto
+ set x [list [chan gets $f line] $line [chan gets $f line] $line]
+ lappend x [chan gets $f line] $line [chan gets $f line] $line [chan gets $f line] $line
+ chan close $f
+ set x
+} [list 4 "abcd" 4 "efgh" 4 "ijkl" 4 "mnop" -1 ""]
+test chan-io-6.43 {Tcl_GetsObj: input saw cr} {stdio testchannel openpipe fileevent} {
+ # if (chanPtr->flags & INPUT_SAW_CR)
+
+ set f [open "|[list [interpreter] $path(cat)]" w+]
+ chan configure $f -translation {auto lf} -buffering none
+ chan puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
+ chan configure $f -buffersize 16
+ set x [list [chan gets $f]]
+ chan configure $f -blocking 0
+ lappend x [chan gets $f line] $line [testchannel queuedcr $f]
+ chan configure $f -blocking 1
+ chan puts -nonewline $f "\nabcd\refg\x1a"
+ lappend x [chan gets $f line] $line [testchannel queuedcr $f]
+ lappend x [chan gets $f line] $line
+ chan close $f
+ set x
+} [list "bbbbbbbbbbbbbbb" 15 "123456789abcdef" 1 4 "abcd" 0 3 "efg"]
+test chan-io-6.44 {Tcl_GetsObj: input saw cr, not followed by cr} {stdio testchannel openpipe fileevent} {
+ # not (*eol == '\n')
+
+ set f [open "|[list [interpreter] $path(cat)]" w+]
+ chan configure $f -translation {auto lf} -buffering none
+ chan puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
+ chan configure $f -buffersize 16
+ set x [list [chan gets $f]]
+ chan configure $f -blocking 0
+ lappend x [chan gets $f line] $line [testchannel queuedcr $f]
+ chan configure $f -blocking 1
+ chan puts -nonewline $f "abcd\refg\x1a"
+ lappend x [chan gets $f line] $line [testchannel queuedcr $f]
+ lappend x [chan gets $f line] $line
+ chan close $f
+ set x
+} [list "bbbbbbbbbbbbbbb" 15 "123456789abcdef" 1 4 "abcd" 0 3 "efg"]
+test chan-io-6.45 {Tcl_GetsObj: input saw cr, skip right number of bytes} {stdio testchannel openpipe fileevent} {
+ # Tcl_ExternalToUtf()
+
+ set f [open "|[list [interpreter] $path(cat)]" w+]
+ chan configure $f -translation {auto lf} -buffering none
+ chan configure $f -encoding unicode
+ chan puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
+ chan configure $f -buffersize 16
+ chan gets $f
+ chan configure $f -blocking 0
+ set x [list [chan gets $f line] $line [testchannel queuedcr $f]]
+ chan configure $f -blocking 1
+ chan puts -nonewline $f "\nabcd\refg"
+ lappend x [chan gets $f line] $line [testchannel queuedcr $f]
+ chan close $f
+ set x
+} [list 15 "123456789abcdef" 1 4 "abcd" 0]
+test chan-io-6.46 {Tcl_GetsObj: input saw cr, followed by just \n should give eof} {stdio testchannel openpipe fileevent} {
+ # memmove()
+
+ set f [open "|[list [interpreter] $path(cat)]" w+]
+ chan configure $f -translation {auto lf} -buffering none
+ chan puts -nonewline $f "bbbbbbbbbbbbbbb\n123456789abcdef\r"
+ chan configure $f -buffersize 16
+ chan gets $f
+ chan configure $f -blocking 0
+ set x [list [chan gets $f line] $line [testchannel queuedcr $f]]
+ chan configure $f -blocking 1
+ chan puts -nonewline $f "\n\x1a"
+ lappend x [chan gets $f line] $line [testchannel queuedcr $f]
+ chan close $f
+ set x
+} [list 15 "123456789abcdef" 1 -1 "" 0]
+test chan-io-6.47 {Tcl_GetsObj: auto mode: \r at end of buffer, peek for \n} {testchannel} {
+ # (eol == dstEnd)
+
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "123456789012345\r\nabcdefghijklmnopq"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation auto -buffersize 16
+ set x [list [chan gets $f] [testchannel inputbuffered $f]]
+ chan close $f
+ set x
+} [list "123456789012345" 15]
+test chan-io-6.48 {Tcl_GetsObj: auto mode: \r at end of buffer, no more avail} {testchannel} {
+ # PeekAhead() did not get any, so (eol >= dstEnd)
+
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "123456789012345\r"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation auto -buffersize 16
+ set x [list [chan gets $f] [testchannel queuedcr $f]]
+ chan close $f
+ set x
+} [list "123456789012345" 1]
+test chan-io-6.49 {Tcl_GetsObj: auto mode: \r followed by \n} {testchannel} {
+ # if (*eol == '\n') {skip++}
+
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "123456\r\n78901"
+ chan close $f
+ set f [open $path(test1)]
+ set x [list [chan gets $f] [testchannel queuedcr $f] [chan tell $f] [chan gets $f]]
+ chan close $f
+ set x
+} [list "123456" 0 8 "78901"]
+test chan-io-6.50 {Tcl_GetsObj: auto mode: \r not followed by \n} {testchannel} {
+ # not (*eol == '\n')
+
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "123456\r78901"
+ chan close $f
+ set f [open $path(test1)]
+ set x [list [chan gets $f] [testchannel queuedcr $f] [chan tell $f] [chan gets $f]]
+ chan close $f
+ set x
+} [list "123456" 0 7 "78901"]
+test chan-io-6.51 {Tcl_GetsObj: auto mode: \n} {
+ # else if (*eol == '\n') {goto gotoeol;}
+
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "123456\n78901"
+ chan close $f
+ set f [open $path(test1)]
+ set x [list [chan gets $f] [chan tell $f] [chan gets $f]]
+ chan close $f
+ set x
+} [list "123456" 7 "78901"]
+test chan-io-6.52 {Tcl_GetsObj: saw EOF character} {testchannel} {
+ # if (eof != NULL)
+
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "123456\x1ak9012345\r"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -eofchar \x1a
+ set x [list [chan gets $f] [testchannel queuedcr $f] [chan tell $f] [chan gets $f]]
+ chan close $f
+ set x
+} [list "123456" 0 6 ""]
+test chan-io-6.53 {Tcl_GetsObj: device EOF} {
+ # didn't produce any bytes
+
+ set f [open $path(test1) w]
+ chan close $f
+ set f [open $path(test1)]
+ set x [list [chan gets $f line] $line [chan eof $f]]
+ chan close $f
+ set x
+} {-1 {} 1}
+test chan-io-6.54 {Tcl_GetsObj: device EOF} {
+ # got some bytes before EOF.
+
+ set f [open $path(test1) w]
+ chan puts -nonewline $f abc
+ chan close $f
+ set f [open $path(test1)]
+ set x [list [chan gets $f line] $line [chan eof $f]]
+ chan close $f
+ set x
+} {3 abc 1}
+test chan-io-6.55 {Tcl_GetsObj: overconverted} {
+ # Tcl_ExternalToUtf(), make sure state updated
+
+ set f [open $path(test1) w]
+ chan configure $f -encoding iso2022-jp
+ chan puts $f "there\u4e00ok\n\u4e01more bytes\nhere"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -encoding iso2022-jp
+ set x [list [chan gets $f line] $line [chan gets $f line] $line [chan gets $f line] $line]
+ chan close $f
+ set x
+} [list 8 "there\u4e00ok" 11 "\u4e01more bytes" 4 "here"]
+test chan-io-6.56 {Tcl_GetsObj: incomplete lines should disable file events} {stdio openpipe fileevent} {
+ update
+ set f [open "|[list [interpreter] $path(cat)]" w+]
+ chan configure $f -buffering none
+ chan puts -nonewline $f "foobar"
+ chan configure $f -blocking 0
+ variable x {}
+ after 500 [namespace code { lappend x timeout }]
+ chan event $f readable [namespace code { lappend x [chan gets $f] }]
+ vwait [namespace which -variable x]
+ vwait [namespace which -variable x]
+ chan configure $f -blocking 1
+ chan puts -nonewline $f "baz\n"
+ after 500 [namespace code { lappend x timeout }]
+ chan configure $f -blocking 0
+ vwait [namespace which -variable x]
+ vwait [namespace which -variable x]
+ chan close $f
+ set x
+} {{} timeout foobarbaz timeout}
+
+test chan-io-7.1 {FilterInputBytes: split up character at end of buffer} {
+ # (result == TCL_CONVERT_MULTIBYTE)
+
+ set f [open $path(test1) w]
+ chan configure $f -encoding shiftjis
+ chan puts $f "1234567890123\uff10\uff11\uff12\uff13\uff14\nend"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -encoding shiftjis -buffersize 16
+ set x [chan gets $f]
+ chan close $f
+ set x
+} "1234567890123\uff10\uff11\uff12\uff13\uff14"
+test chan-io-7.2 {FilterInputBytes: split up character in middle of buffer} {
+ # (bufPtr->nextAdded < bufPtr->bufLength)
+
+ set f [open $path(test1) w]
+ chan configure $f -encoding binary
+ chan puts -nonewline $f "1234567890\n123\x82\x4f\x82\x50\x82"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -encoding shiftjis
+ set x [list [chan gets $f line] $line [chan eof $f]]
+ chan close $f
+ set x
+} [list 10 "1234567890" 0]
+test chan-io-7.3 {FilterInputBytes: split up character at EOF} {testchannel} {
+ set f [open $path(test1) w]
+ chan configure $f -encoding binary
+ chan puts -nonewline $f "1234567890123\x82\x4f\x82\x50\x82"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -encoding shiftjis
+ set x [list [chan gets $f line] $line]
+ lappend x [chan tell $f] [testchannel inputbuffered $f] [chan eof $f]
+ lappend x [chan gets $f line] $line
+ chan close $f
+ set x
+} [list 15 "1234567890123\uff10\uff11" 18 0 1 -1 ""]
+test chan-io-7.4 {FilterInputBytes: recover from split up character} {stdio openpipe fileevent} {
+ set f [open "|[list [interpreter] $path(cat)]" w+]
+ chan configure $f -encoding binary -buffering none
+ chan puts -nonewline $f "1234567890123\x82\x4f\x82\x50\x82"
+ chan configure $f -encoding shiftjis -blocking 0
+ chan event $f read [namespace code "ready $f"]
+ variable x {}
+ proc ready {f} {
+ variable x
+ lappend x [chan gets $f line] $line [chan blocked $f]
+ }
+ vwait [namespace which -variable x]
+ chan configure $f -encoding binary -blocking 1
+ chan puts $f "\x51\x82\x52"
+ chan configure $f -encoding shiftjis
+ vwait [namespace which -variable x]
+ chan close $f
+ set x
+} [list -1 "" 1 17 "1234567890123\uff10\uff11\uff12\uff13" 0]
+
+test chan-io-8.1 {PeekAhead: only go to device if no more cached data} {testchannel} {
+ # (bufPtr->nextPtr == NULL)
+
+ set f [open $path(test1) w]
+ chan configure $f -encoding ascii -translation lf
+ chan puts -nonewline $f "123456789012345\r\n2345678"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -encoding ascii -translation auto -buffersize 16
+ # here
+ chan gets $f
+ set x [testchannel inputbuffered $f]
+ chan close $f
+ set x
+} "7"
+test chan-io-8.2 {PeekAhead: only go to device if no more cached data} {stdio testchannel openpipe fileevent} {
+ # not (bufPtr->nextPtr == NULL)
+
+ set f [open "|[list [interpreter] $path(cat)]" w+]
+ chan configure $f -translation lf -encoding ascii -buffering none
+ chan puts -nonewline $f "123456789012345\r\nbcdefghijklmnopqrstuvwxyz"
+ variable x {}
+ chan event $f read [namespace code "ready $f"]
+ proc ready {f} {
+ variable x
+ lappend x [chan gets $f line] $line [testchannel inputbuffered $f]
+ }
+ chan configure $f -encoding unicode -buffersize 16 -blocking 0
+ vwait [namespace which -variable x]
+ chan configure $f -translation auto -encoding ascii -blocking 1
+ # here
+ vwait [namespace which -variable x]
+ chan close $f
+ set x
+} [list -1 "" 42 15 "123456789012345" 25]
+test chan-io-8.3 {PeekAhead: no cached data available} {stdio testchannel openpipe fileevent} {
+ # (bytesLeft == 0)
+
+ set f [open "|[list [interpreter] $path(cat)]" w+]
+ chan configure $f -translation {auto binary}
+ chan puts -nonewline $f "abcdefghijklmno\r"
+ chan flush $f
+ set x [list [chan gets $f line] $line [testchannel queuedcr $f]]
+ chan close $f
+ set x
+} [list 15 "abcdefghijklmno" 1]
+set a "123456789012345678901234567890"
+append a "123456789012345678901234567890"
+append a "1234567890123456789012345678901"
+test chan-io-8.4 {PeekAhead: cached data available in this buffer} {
+ # not (bytesLeft == 0)
+
+ set f [open $path(test1) w+]
+ chan configure $f -translation binary
+ chan puts $f "${a}\r\nabcdef"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -encoding binary -translation auto
+
+ # "${a}\r" was converted in one operation (because ENCODING_LINESIZE
+ # is 30). To check if "\n" follows, calls PeekAhead and determines
+ # that cached data is available in buffer w/o having to call driver.
+
+ set x [chan gets $f]
+ chan close $f
+ set x
+} $a
+unset a
+test chan-io-8.5 {PeekAhead: don't peek if last read was short} {stdio testchannel openpipe fileevent} {
+ # (bufPtr->nextAdded < bufPtr->length)
+
+ set f [open "|[list [interpreter] $path(cat)]" w+]
+ chan configure $f -translation {auto binary}
+ chan puts -nonewline $f "abcdefghijklmno\r"
+ chan flush $f
+ # here
+ set x [list [chan gets $f line] $line [testchannel queuedcr $f]]
+ chan close $f
+ set x
+} {15 abcdefghijklmno 1}
+test chan-io-8.6 {PeekAhead: change to non-blocking mode} {stdio testchannel openpipe fileevent} {
+ # ((chanPtr->flags & CHANNEL_NONBLOCKING) == 0)
+
+ set f [open "|[list [interpreter] $path(cat)]" w+]
+ chan configure $f -translation {auto binary} -buffersize 16
+ chan puts -nonewline $f "abcdefghijklmno\r"
+ chan flush $f
+ # here
+ set x [list [chan gets $f line] $line [testchannel queuedcr $f]]
+ chan close $f
+ set x
+} {15 abcdefghijklmno 1}
+test chan-io-8.7 {PeekAhead: cleanup} {stdio testchannel openpipe fileevent} {
+ # Make sure bytes are removed from buffer.
+
+ set f [open "|[list [interpreter] $path(cat)]" w+]
+ chan configure $f -translation {auto binary} -buffering none
+ chan puts -nonewline $f "abcdefghijklmno\r"
+ # here
+ set x [list [chan gets $f line] $line [testchannel queuedcr $f]]
+ chan puts -nonewline $f "\x1a"
+ lappend x [chan gets $f line] $line
+ chan close $f
+ set x
+} {15 abcdefghijklmno 1 -1 {}}
+
+test chan-io-9.1 {CommonGetsCleanup} emptyTest {
+} {}
+
+test chan-io-10.1 {Tcl_ReadChars: CheckChannelErrors} emptyTest {
+ # no test, need to cause an async error.
+} {}
+test chan-io-10.2 {Tcl_ReadChars: loop until enough copied} {
+ # one time
+ # for (copied = 0; (unsigned) toRead > 0; )
+
+ set f [open $path(test1) w]
+ chan puts $f abcdefghijklmnop
+ chan close $f
+
+ set f [open $path(test1)]
+ set x [chan read $f 5]
+ chan close $f
+ set x
+} {abcde}
+test chan-io-10.3 {Tcl_ReadChars: loop until enough copied} {
+ # multiple times
+ # for (copied = 0; (unsigned) toRead > 0; )
+
+ set f [open $path(test1) w]
+ chan puts $f abcdefghijklmnopqrstuvwxyz
+ chan close $f
+
+ set f [open $path(test1)]
+ chan configure $f -buffersize 16
+ # here
+ set x [chan read $f 19]
+ chan close $f
+ set x
+} {abcdefghijklmnopqrs}
+test chan-io-10.4 {Tcl_ReadChars: no more in channel buffer} {
+ # (copiedNow < 0)
+
+ set f [open $path(test1) w]
+ chan puts -nonewline $f abcdefghijkl
+ chan close $f
+
+ set f [open $path(test1)]
+ # here
+ set x [chan read $f 1000]
+ chan close $f
+ set x
+} {abcdefghijkl}
+test chan-io-10.5 {Tcl_ReadChars: stop on EOF} {
+ # (chanPtr->flags & CHANNEL_EOF)
+
+ set f [open $path(test1) w]
+ chan puts -nonewline $f abcdefghijkl
+ chan close $f
+
+ set f [open $path(test1)]
+ # here
+ set x [chan read $f 1000]
+ chan close $f
+ set x
+} {abcdefghijkl}
+
+test chan-io-11.1 {ReadBytes: want to read a lot} {
+ # ((unsigned) toRead > (unsigned) srcLen)
+
+ set f [open $path(test1) w]
+ chan puts -nonewline $f abcdefghijkl
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -encoding binary
+ # here
+ set x [chan read $f 1000]
+ chan close $f
+ set x
+} {abcdefghijkl}
+test chan-io-11.2 {ReadBytes: want to read all} {
+ # ((unsigned) toRead > (unsigned) srcLen)
+
+ set f [open $path(test1) w]
+ chan puts -nonewline $f abcdefghijkl
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -encoding binary
+ # here
+ set x [chan read $f]
+ chan close $f
+ set x
+} {abcdefghijkl}
+test chan-io-11.3 {ReadBytes: allocate more space} {
+ # (toRead > length - offset - 1)
+
+ set f [open $path(test1) w]
+ chan puts -nonewline $f abcdefghijklmnopqrstuvwxyz
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -buffersize 16 -encoding binary
+ # here
+ set x [chan read $f]
+ chan close $f
+ set x
+} {abcdefghijklmnopqrstuvwxyz}
+test chan-io-11.4 {ReadBytes: EOF char found} {
+ # (TranslateInputEOL() != 0)
+
+ set f [open $path(test1) w]
+ chan puts $f abcdefghijklmnopqrstuvwxyz
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -eofchar m -encoding binary
+ # here
+ set x [list [chan read $f] [chan eof $f] [chan read $f] [chan eof $f]]
+ chan close $f
+ set x
+} [list "abcdefghijkl" 1 "" 1]
+
+test chan-io-12.1 {ReadChars: want to read a lot} {
+ # ((unsigned) toRead > (unsigned) srcLen)
+
+ set f [open $path(test1) w]
+ chan puts -nonewline $f abcdefghijkl
+ chan close $f
+ set f [open $path(test1)]
+ # here
+ set x [chan read $f 1000]
+ chan close $f
+ set x
+} {abcdefghijkl}
+test chan-io-12.2 {ReadChars: want to read all} {
+ # ((unsigned) toRead > (unsigned) srcLen)
+
+ set f [open $path(test1) w]
+ chan puts -nonewline $f abcdefghijkl
+ chan close $f
+ set f [open $path(test1)]
+ # here
+ set x [chan read $f]
+ chan close $f
+ set x
+} {abcdefghijkl}
+test chan-io-12.3 {ReadChars: allocate more space} {
+ # (toRead > length - offset - 1)
+
+ set f [open $path(test1) w]
+ chan puts -nonewline $f abcdefghijklmnopqrstuvwxyz
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -buffersize 16
+ # here
+ set x [chan read $f]
+ chan close $f
+ set x
+} {abcdefghijklmnopqrstuvwxyz}
+test chan-io-12.4 {ReadChars: split-up char} {stdio testchannel openpipe fileevent} {
+ # (srcRead == 0)
+
+ set f [open "|[list [interpreter] $path(cat)]" w+]
+ chan configure $f -encoding binary -buffering none -buffersize 16
+ chan puts -nonewline $f "123456789012345\x96"
+ chan configure $f -encoding shiftjis -blocking 0
+
+ chan event $f read [namespace code "ready $f"]
+ proc ready {f} {
+ variable x
+ lappend x [chan read $f] [testchannel inputbuffered $f]
+ }
+ variable x {}
+
+ chan configure $f -encoding shiftjis
+ vwait [namespace which -variable x]
+ chan configure $f -encoding binary -blocking 1
+ chan puts -nonewline $f "\x7b"
+ after 500 ;# Give the cat process time to catch up
+ chan configure $f -encoding shiftjis -blocking 0
+ vwait [namespace which -variable x]
+ chan close $f
+ set x
+} [list "123456789012345" 1 "\u672c" 0]
+test chan-io-12.5 {ReadChars: chan events on partial characters} {stdio openpipe fileevent} {
+ set path(test1) [makeFile {
+ chan configure stdout -encoding binary -buffering none
+ chan gets stdin; chan puts -nonewline "\xe7"
+ chan gets stdin; chan puts -nonewline "\x89"
+ chan gets stdin; chan puts -nonewline "\xa6"
+ } test1]
+ set f [open "|[list [interpreter] $path(test1)]" r+]
+ chan event $f readable [namespace code {
+ lappend x [chan read $f]
+ if {[chan eof $f]} {
+ lappend x eof
+ }
+ }]
+ chan puts $f "go1"
+ chan flush $f
+ chan configure $f -blocking 0 -encoding utf-8
+ variable x {}
+ vwait [namespace which -variable x]
+ after 500 [namespace code { lappend x timeout }]
+ vwait [namespace which -variable x]
+ chan puts $f "go2"
+ chan flush $f
+ vwait [namespace which -variable x]
+ after 500 [namespace code { lappend x timeout }]
+ vwait [namespace which -variable x]
+ chan puts $f "go3"
+ chan flush $f
+ vwait [namespace which -variable x]
+ vwait [namespace which -variable x]
+ lappend x [catch {chan close $f} msg] $msg
+ set x
+} "{} timeout {} timeout \u7266 {} eof 0 {}"
+
+test chan-io-13.1 {TranslateInputEOL: cr mode} {} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "abcd\rdef\r"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation cr
+ set x [chan read $f]
+ chan close $f
+ set x
+} "abcd\ndef\n"
+test chan-io-13.2 {TranslateInputEOL: crlf mode} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "abcd\r\ndef\r\n"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation crlf
+ set x [chan read $f]
+ chan close $f
+ set x
+} "abcd\ndef\n"
+test chan-io-13.3 {TranslateInputEOL: crlf mode: naked cr} {
+ # (src >= srcMax)
+
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "abcd\r\ndef\r"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation crlf
+ set x [chan read $f]
+ chan close $f
+ set x
+} "abcd\ndef\r"
+test chan-io-13.4 {TranslateInputEOL: crlf mode: cr followed by not \n} {
+ # (src >= srcMax)
+
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "abcd\r\ndef\rfgh"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation crlf
+ set x [chan read $f]
+ chan close $f
+ set x
+} "abcd\ndef\rfgh"
+test chan-io-13.5 {TranslateInputEOL: crlf mode: naked lf} {
+ # (src >= srcMax)
+
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "abcd\r\ndef\nfgh"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation crlf
+ set x [chan read $f]
+ chan close $f
+ set x
+} "abcd\ndef\nfgh"
+test chan-io-13.6 {TranslateInputEOL: auto mode: saw cr in last segment} {stdio testchannel openpipe fileevent} {
+ # (chanPtr->flags & INPUT_SAW_CR)
+ # This test may fail on slower machines.
+
+ set f [open "|[list [interpreter] $path(cat)]" w+]
+ chan configure $f -blocking 0 -buffering none -translation {auto lf}
+
+ chan event $f read [namespace code "ready $f"]
+ proc ready {f} {
+ variable x
+ lappend x [chan read $f] [testchannel queuedcr $f]
+ }
+ variable x {}
+ variable y {}
+
+ chan puts -nonewline $f "abcdefghj\r"
+ after 500 [namespace code {set y ok}]
+ vwait [namespace which -variable y]
+
+ chan puts -nonewline $f "\n01234"
+ after 500 [namespace code {set y ok}]
+ vwait [namespace which -variable y]
+
+ chan close $f
+ set x
+} [list "abcdefghj\n" 1 "01234" 0]
+test chan-io-13.7 {TranslateInputEOL: auto mode: naked \r} {testchannel openpipe} {
+ # (src >= srcMax)
+
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "abcd\r"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation auto
+ set x [list [chan read $f] [testchannel queuedcr $f]]
+ chan close $f
+ set x
+} [list "abcd\n" 1]
+test chan-io-13.8 {TranslateInputEOL: auto mode: \r\n} {
+ # (*src == '\n')
+
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "abcd\r\ndef"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation auto
+ set x [chan read $f]
+ chan close $f
+ set x
+} "abcd\ndef"
+test chan-io-13.9 {TranslateInputEOL: auto mode: \r followed by not \n} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "abcd\rdef"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation auto
+ set x [chan read $f]
+ chan close $f
+ set x
+} "abcd\ndef"
+test chan-io-13.10 {TranslateInputEOL: auto mode: \n} {
+ # not (*src == '\r')
+
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "abcd\ndef"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation auto
+ set x [chan read $f]
+ chan close $f
+ set x
+} "abcd\ndef"
+test chan-io-13.11 {TranslateInputEOL: EOF char} {
+ # (*chanPtr->inEofChar != '\0')
+
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "abcd\ndefgh"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation auto -eofchar e
+ set x [chan read $f]
+ chan close $f
+ set x
+} "abcd\nd"
+test chan-io-13.12 {TranslateInputEOL: find EOF char in src} {
+ # (*chanPtr->inEofChar != '\0')
+
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "\r\n\r\n\r\nab\r\n\r\ndef\r\n\r\n\r\n"
+ chan close $f
+ set f [open $path(test1)]
+ chan configure $f -translation auto -eofchar e
+ set x [chan read $f]
+ chan close $f
+ set x
+} "\n\n\nab\n\nd"
+
+# Test standard handle management. The functions tested are
+# Tcl_SetStdChannel and Tcl_GetStdChannel. Incidentally we are
+# also testing channel table management.
+
+if {[info commands testchannel] != ""} {
+ set consoleFileNames [lsort [testchannel open]]
+} else {
+ # just to avoid an error
+ set consoleFileNames [list]
+}
+
+test chan-io-14.1 {Tcl_SetStdChannel and Tcl_GetStdChannel} {testchannel} {
+ set l ""
+ lappend l [chan configure stdin -buffering]
+ lappend l [chan configure stdout -buffering]
+ lappend l [chan configure stderr -buffering]
+ lappend l [lsort [testchannel open]]
+ set l
+} [list line line none $consoleFileNames]
+test chan-io-14.2 {Tcl_SetStdChannel and Tcl_GetStdChannel} {
+ interp create x
+ set l ""
+ lappend l [x eval {chan configure stdin -buffering}]
+ lappend l [x eval {chan configure stdout -buffering}]
+ lappend l [x eval {chan configure stderr -buffering}]
+ interp delete x
+ set l
+} {line line none}
+set path(test3) [makeFile {} test3]
+test chan-io-14.3 {Tcl_SetStdChannel & Tcl_GetStdChannel} {exec openpipe} {
+ set f [open $path(test1) w]
+ chan puts -nonewline $f {
+ chan close stdin
+ chan close stdout
+ chan close stderr
+ set f [}
+ chan puts $f [list open $path(test1) r]]
+ chan puts $f "set f2 \[[list open $path(test2) w]]"
+ chan puts $f "set f3 \[[list open $path(test3) w]]"
+ chan puts $f { chan puts stdout [chan gets stdin]
+ chan puts stdout out
+ chan puts stderr err
+ chan close $f
+ chan close $f2
+ chan close $f3
+ }
+ chan close $f
+ set result [exec [interpreter] $path(test1)]
+ set f [open $path(test2) r]
+ set f2 [open $path(test3) r]
+ lappend result [chan read $f] [chan read $f2]
+ chan close $f
+ chan close $f2
+ set result
+} {{
+out
+} {err
+}}
+# This test relies on the fact that the smallest available fd is used first.
+test chan-io-14.4 {Tcl_SetStdChannel & Tcl_GetStdChannel} {exec unix} {
+ set f [open $path(test1) w]
+ chan puts -nonewline $f { chan close stdin
+ chan close stdout
+ chan close stderr
+ set f [}
+ chan puts $f [list open $path(test1) r]]
+ chan puts $f "set f2 \[[list open $path(test2) w]]"
+ chan puts $f "set f3 \[[list open $path(test3) w]]"
+ chan puts $f { chan puts stdout [chan gets stdin]
+ chan puts stdout $f2
+ chan puts stderr $f3
+ chan close $f
+ chan close $f2
+ chan close $f3
+ }
+ chan close $f
+ set result [exec [interpreter] $path(test1)]
+ set f [open $path(test2) r]
+ set f2 [open $path(test3) r]
+ lappend result [chan read $f] [chan read $f2]
+ chan close $f
+ chan close $f2
+ set result
+} {{ chan close stdin
+file1
+} {file2
+}}
+catch {interp delete z}
+test chan-io-14.5 {Tcl_GetChannel: stdio name translation} {
+ interp create z
+ chan eof stdin
+ catch {z eval chan flush stdin} msg1
+ catch {z eval chan close stdin} msg2
+ catch {z eval chan flush stdin} msg3
+ set result [list $msg1 $msg2 $msg3]
+ interp delete z
+ set result
+} {{channel "stdin" wasn't opened for writing} {} {can not find channel named "stdin"}}
+test chan-io-14.6 {Tcl_GetChannel: stdio name translation} {
+ interp create z
+ chan eof stdout
+ catch {z eval chan flush stdout} msg1
+ catch {z eval chan close stdout} msg2
+ catch {z eval chan flush stdout} msg3
+ set result [list $msg1 $msg2 $msg3]
+ interp delete z
+ set result
+} {{} {} {can not find channel named "stdout"}}
+test chan-io-14.7 {Tcl_GetChannel: stdio name translation} {
+ interp create z
+ chan eof stderr
+ catch {z eval chan flush stderr} msg1
+ catch {z eval chan close stderr} msg2
+ catch {z eval chan flush stderr} msg3
+ set result [list $msg1 $msg2 $msg3]
+ interp delete z
+ set result
+} {{} {} {can not find channel named "stderr"}}
+set path(script) [makeFile {} script]
+test chan-io-14.8 {reuse of stdio special channels} {stdio openpipe} {
+ file delete $path(script)
+ file delete $path(test1)
+ set f [open $path(script) w]
+ chan puts -nonewline $f {
+ chan close stderr
+ set f [}
+ chan puts $f [list open $path(test1) w]]
+ chan puts -nonewline $f {
+ chan puts stderr hello
+ chan close $f
+ set f [}
+ chan puts $f [list open $path(test1) r]]
+ chan puts $f {
+ chan puts [chan gets $f]
+ }
+ chan close $f
+ set f [open "|[list [interpreter] $path(script)]" r]
+ set c [chan gets $f]
+ chan close $f
+ set c
+} hello
+test chan-io-14.9 {reuse of stdio special channels} {stdio openpipe fileevent} {
+ file delete $path(script)
+ file delete $path(test1)
+ set f [open $path(script) w]
+ chan puts $f {
+ array set path [lindex $argv 0]
+ set f [open $path(test1) w]
+ chan puts $f hello
+ chan close $f
+ chan close stderr
+ set f [open "|[list [info nameofexecutable] $path(cat) $path(test1)]" r]
+ chan puts [chan gets $f]
+ }
+ chan close $f
+ set f [open "|[list [interpreter] $path(script) [array get path]]" r]
+ set c [chan gets $f]
+ chan close $f
+ # Added delay to give Windows time to stop the spawned process and clean
+ # up its grip on the file test1. Added delete as proper test cleanup.
+ # The failing tests were 18.1 and 18.2 as first re-users of file "test1".
+ after 10000
+ file delete $path(script)
+ file delete $path(test1)
+ set c
+} hello
+
+test chan-io-15.1 {Tcl_CreateChan CloseHandler} emptyTest {
+} {}
+
+test chan-io-16.1 {Tcl_DeleteChan CloseHandler} emptyTest {
+} {}
+
+# Test channel table management. The functions tested are
+# GetChannelTable, DeleteChannelTable, Tcl_RegisterChannel,
+# Tcl_UnregisterChannel, Tcl_GetChannel and Tcl_CreateChannel.
+#
+# These functions use "eof stdin" to ensure that the standard
+# channels are added to the channel table of the interpreter.
+
+test chan-io-17.1 {GetChannelTable, DeleteChannelTable on std handles} {testchannel} {
+ set l1 [testchannel refcount stdin]
+ chan eof stdin
+ interp create x
+ set l ""
+ lappend l [expr [testchannel refcount stdin] - $l1]
+ x eval {chan eof stdin}
+ lappend l [expr [testchannel refcount stdin] - $l1]
+ interp delete x
+ lappend l [expr [testchannel refcount stdin] - $l1]
+ set l
+} {0 1 0}
+test chan-io-17.2 {GetChannelTable, DeleteChannelTable on std handles} {testchannel} {
+ set l1 [testchannel refcount stdout]
+ chan eof stdin
+ interp create x
+ set l ""
+ lappend l [expr [testchannel refcount stdout] - $l1]
+ x eval {chan eof stdout}
+ lappend l [expr [testchannel refcount stdout] - $l1]
+ interp delete x
+ lappend l [expr [testchannel refcount stdout] - $l1]
+ set l
+} {0 1 0}
+test chan-io-17.3 {GetChannelTable, DeleteChannelTable on std handles} {testchannel} {
+ set l1 [testchannel refcount stderr]
+ chan eof stdin
+ interp create x
+ set l ""
+ lappend l [expr [testchannel refcount stderr] - $l1]
+ x eval {chan eof stderr}
+ lappend l [expr [testchannel refcount stderr] - $l1]
+ interp delete x
+ lappend l [expr [testchannel refcount stderr] - $l1]
+ set l
+} {0 1 0}
+
+test chan-io-18.1 {Tcl_RegisterChannel, Tcl_UnregisterChannel} {testchannel} {
+ file delete -force $path(test1)
+ set l ""
+ set f [open $path(test1) w]
+ lappend l [lindex [testchannel info $f] 15]
+ chan close $f
+ if {[catch {lindex [testchannel info $f] 15} msg]} {
+ lappend l $msg
+ } else {
+ lappend l "very broken: $f found after being chan closed"
+ }
+ string compare [string tolower $l] \
+ [list 1 [format "can not find channel named \"%s\"" $f]]
+} 0
+test chan-io-18.2 {Tcl_RegisterChannel, Tcl_UnregisterChannel} {testchannel} {
+ file delete -force $path(test1)
+ set l ""
+ set f [open $path(test1) w]
+ lappend l [lindex [testchannel info $f] 15]
+ interp create x
+ interp share "" $f x
+ lappend l [lindex [testchannel info $f] 15]
+ x eval chan close $f
+ lappend l [lindex [testchannel info $f] 15]
+ interp delete x
+ lappend l [lindex [testchannel info $f] 15]
+ chan close $f
+ if {[catch {lindex [testchannel info $f] 15} msg]} {
+ lappend l $msg
+ } else {
+ lappend l "very broken: $f found after being chan closed"
+ }
+ string compare [string tolower $l] \
+ [list 1 2 1 1 [format "can not find channel named \"%s\"" $f]]
+} 0
+test chan-io-18.3 {Tcl_RegisterChannel, Tcl_UnregisterChannel} {testchannel} {
+ file delete $path(test1)
+ set l ""
+ set f [open $path(test1) w]
+ lappend l [lindex [testchannel info $f] 15]
+ interp create x
+ interp share "" $f x
+ lappend l [lindex [testchannel info $f] 15]
+ interp delete x
+ lappend l [lindex [testchannel info $f] 15]
+ chan close $f
+ if {[catch {lindex [testchannel info $f] 15} msg]} {
+ lappend l $msg
+ } else {
+ lappend l "very broken: $f found after being chan closed"
+ }
+ string compare [string tolower $l] \
+ [list 1 2 1 [format "can not find channel named \"%s\"" $f]]
+} 0
+
+test chan-io-19.1 {Tcl_GetChannel->Tcl_GetStdChannel, standard handles} {
+ chan eof stdin
+} 0
+test chan-io-19.2 {testing Tcl_GetChannel, user opened handle} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ set x [chan eof $f]
+ chan close $f
+ set x
+} 0
+test chan-io-19.3 {Tcl_GetChannel, channel not found} {
+ list [catch {chan eof file34} msg] $msg
+} {1 {can not find channel named "file34"}}
+test chan-io-19.4 {Tcl_CreateChannel, insertion into channel table} {testchannel} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ set l ""
+ lappend l [chan eof $f]
+ chan close $f
+ if {[catch {lindex [testchannel info $f] 15} msg]} {
+ lappend l $msg
+ } else {
+ lappend l "very broken: $f found after being chan closed"
+ }
+ string compare [string tolower $l] \
+ [list 0 [format "can not find channel named \"%s\"" $f]]
+} 0
+
+test chan-io-20.1 {Tcl_CreateChannel: initial settings} {
+ set a [open $path(test2) w]
+ set old [encoding system]
+ encoding system ascii
+ set f [open $path(test1) w]
+ set x [chan configure $f -encoding]
+ chan close $f
+ encoding system $old
+ chan close $a
+ set x
+} {ascii}
+test chan-io-20.2 {Tcl_CreateChannel: initial settings} {win} {
+ set f [open $path(test1) w+]
+ set x [list [chan configure $f -eofchar] [chan configure $f -translation]]
+ chan close $f
+ set x
+} [list [list \x1a ""] {auto crlf}]
+test chan-io-20.3 {Tcl_CreateChannel: initial settings} {unix} {
+ set f [open $path(test1) w+]
+ set x [list [chan configure $f -eofchar] [chan configure $f -translation]]
+ chan close $f
+ set x
+} {{{} {}} {auto lf}}
+set path(stdout) [makeFile {} stdout]
+test chan-io-20.5 {Tcl_CreateChannel: install channel in empty slot} {stdio openpipe} {
+ set f [open $path(script) w]
+ chan puts -nonewline $f {
+ chan close stdout
+ set f1 [}
+ chan puts $f [list open $path(stdout) w]]
+ chan puts $f {
+ chan configure $f1 -buffersize 777
+ chan puts stderr [chan configure stdout -buffersize]
+ }
+ chan close $f
+ set f [open "|[list [interpreter] $path(script)]"]
+ catch {chan close $f} msg
+ set msg
+} {777}
+
+test chan-io-21.1 {Chan CloseChannelsOnExit} emptyTest {
+} {}
+
+# Test management of attributes associated with a channel, such as
+# its default translation, its name and type, etc. The functions
+# tested in this group are Tcl_GetChannelName,
+# Tcl_GetChannelType and Tcl_GetChannelFile. Tcl_GetChannelInstanceData
+# not tested because files do not use the instance data.
+
+test chan-io-22.1 {Tcl_GetChannelMode} emptyTest {
+ # Not used anywhere in Tcl.
+} {}
+
+test chan-io-23.1 {Tcl_GetChannelName} {testchannel} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ set n [testchannel name $f]
+ chan close $f
+ string compare $n $f
+} 0
+
+test chan-io-24.1 {Tcl_GetChannelType} {testchannel} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ set t [testchannel type $f]
+ chan close $f
+ string compare $t file
+} 0
+
+test chan-io-25.1 {Tcl_GetChannelHandle, input} {testchannel} {
+ set f [open $path(test1) w]
+ chan configure $f -translation lf -eofchar {}
+ chan puts $f "1234567890\n098765432"
+ chan close $f
+ set f [open $path(test1) r]
+ chan gets $f
+ set l ""
+ lappend l [testchannel inputbuffered $f]
+ lappend l [chan tell $f]
+ chan close $f
+ set l
+} {10 11}
+test chan-io-25.2 {Tcl_GetChannelHandle, output} {testchannel} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts $f hello
+ set l ""
+ lappend l [testchannel outputbuffered $f]
+ lappend l [chan tell $f]
+ chan flush $f
+ lappend l [testchannel outputbuffered $f]
+ lappend l [chan tell $f]
+ chan close $f
+ file delete $path(test1)
+ set l
+} {6 6 0 6}
+
+test chan-io-26.1 {Tcl_GetChannelInstanceData} {stdio openpipe} {
+ # "pid" command uses Tcl_GetChannelInstanceData
+ # Don't care what pid is (but must be a number), just want to exercise it.
+
+ set f [open "|[list [interpreter] << exit]"]
+ expr [pid $f]
+ chan close $f
+} {}
+
+# Test flushing. The functions tested here are FlushChannel.
+
+test chan-io-27.1 {FlushChannel, no output buffered} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan flush $f
+ set s [file size $path(test1)]
+ chan close $f
+ set s
+} 0
+test chan-io-27.2 {FlushChannel, some output buffered} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf -eofchar {}
+ set l ""
+ chan puts $f hello
+ lappend l [file size $path(test1)]
+ chan flush $f
+ lappend l [file size $path(test1)]
+ chan close $f
+ lappend l [file size $path(test1)]
+ set l
+} {0 6 6}
+test chan-io-27.3 {FlushChannel, implicit flush on chan close} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf -eofchar {}
+ set l ""
+ chan puts $f hello
+ lappend l [file size $path(test1)]
+ chan close $f
+ lappend l [file size $path(test1)]
+ set l
+} {0 6}
+test chan-io-27.4 {FlushChannel, implicit flush when buffer fills} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf -eofchar {}
+ chan configure $f -buffersize 60
+ set l ""
+ lappend l [file size $path(test1)]
+ for {set i 0} {$i < 12} {incr i} {
+ chan puts $f hello
+ }
+ lappend l [file size $path(test1)]
+ chan flush $f
+ lappend l [file size $path(test1)]
+ chan close $f
+ set l
+} {0 60 72}
+test chan-io-27.5 {FlushChannel, implicit flush when buffer fills and on chan close} \
+ {unixOrPc} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf -buffersize 60 -eofchar {}
+ set l ""
+ lappend l [file size $path(test1)]
+ for {set i 0} {$i < 12} {incr i} {
+ chan puts $f hello
+ }
+ lappend l [file size $path(test1)]
+ chan close $f
+ lappend l [file size $path(test1)]
+ set l
+} {0 60 72}
+set path(pipe) [makeFile {} pipe]
+set path(output) [makeFile {} output]
+test chan-io-27.6 {FlushChannel, async flushing, async chan close} \
+ {stdio asyncPipeChan Close openpipe} {
+ file delete $path(pipe)
+ file delete $path(output)
+ set f [open $path(pipe) w]
+ chan puts $f "set f \[[list open $path(output) w]]"
+ chan puts $f {
+ chan configure $f -translation lf -buffering none -eofchar {}
+ while {![chan eof stdin]} {
+ after 20
+ chan puts -nonewline $f [chan read stdin 1024]
+ }
+ chan close $f
+ }
+ chan close $f
+ set x 01234567890123456789012345678901
+ for {set i 0} {$i < 11} {incr i} {
+ set x "$x$x"
+ }
+ set f [open $path(output) w]
+ chan close $f
+ set f [open "|[list [interpreter] $path(pipe)]" w]
+ chan configure $f -blocking off
+ chan puts -nonewline $f $x
+ chan close $f
+ set counter 0
+ while {([file size $path(output)] < 65536) && ($counter < 1000)} {
+ after 20 [list incr [namespace which -variable counter]]
+ vwait [namespace which -variable counter]
+ }
+ if {$counter == 1000} {
+ set result "file size only [file size $path(output)]"
+ } else {
+ set result ok
+ }
+} ok
+
+# Tests closing a channel. The functions tested are Chan CloseChannel and Tcl_Chan Close.
+
+test chan-io-28.1 {Chan CloseChannel called when all references are dropped} {testchannel} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ interp create x
+ interp share "" $f x
+ set l ""
+ lappend l [testchannel refcount $f]
+ x eval chan close $f
+ interp delete x
+ lappend l [testchannel refcount $f]
+ chan close $f
+ set l
+} {2 1}
+test chan-io-28.2 {Chan CloseChannel called when all references are dropped} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ interp create x
+ interp share "" $f x
+ chan puts -nonewline $f abc
+ chan close $f
+ x eval chan puts $f def
+ x eval chan close $f
+ interp delete x
+ set f [open $path(test1) r]
+ set l [chan gets $f]
+ chan close $f
+ set l
+} abcdef
+test chan-io-28.3 {Chan CloseChannel, not called before output queue is empty} \
+ {stdio asyncPipeChan Close nonPortable openpipe} {
+ file delete $path(pipe)
+ file delete $path(output)
+ set f [open $path(pipe) w]
+ chan puts $f {
+
+ # Need to not have eof char appended on chan close, because the other
+ # side of the pipe already chan closed, so that writing would cause an
+ # error "invalid file".
+
+ chan configure stdout -eofchar {}
+ chan configure stderr -eofchar {}
+
+ set f [open $path(output) w]
+ chan configure $f -translation lf -buffering none
+ for {set x 0} {$x < 20} {incr x} {
+ after 20
+ chan puts -nonewline $f [chan read stdin 1024]
+ }
+ chan close $f
+ }
+ chan close $f
+ set x 01234567890123456789012345678901
+ for {set i 0} {$i < 11} {incr i} {
+ set x "$x$x"
+ }
+ set f [open $path(output) w]
+ chan close $f
+ set f [open "|[list [interpreter] pipe]" r+]
+ chan configure $f -blocking off -eofchar {}
+
+ chan puts -nonewline $f $x
+ chan close $f
+ set counter 0
+ while {([file size $path(output)] < 20480) && ($counter < 1000)} {
+ after 20 [list incr [namespace which -variable counter]]
+ vwait [namespace which -variable counter]
+ }
+ if {$counter == 1000} {
+ set result probably_broken
+ } else {
+ set result ok
+ }
+} ok
+test chan-io-28.4 {Tcl_Chan Close} {testchannel} {
+ file delete $path(test1)
+ set l ""
+ lappend l [lsort [testchannel open]]
+ set f [open $path(test1) w]
+ lappend l [lsort [testchannel open]]
+ chan close $f
+ lappend l [lsort [testchannel open]]
+ set x [list $consoleFileNames \
+ [lsort [list {*}$consoleFileNames $f]] \
+ $consoleFileNames]
+ string compare $l $x
+} 0
+test chan-io-28.5 {Tcl_Chan Close vs standard handles} {stdio unix testchannel openpipe} {
+ file delete $path(script)
+ set f [open $path(script) w]
+ chan puts $f {
+ chan close stdin
+ chan puts [testchannel open]
+ }
+ chan close $f
+ set f [open "|[list [interpreter] $path(script)]" r]
+ set l [chan gets $f]
+ chan close $f
+ set l
+} {file1 file2}
+
+test chan-io-29.1 {Tcl_WriteChars, channel not writable} {
+ list [catch {chan puts stdin hello} msg] $msg
+} {1 {channel "stdin" wasn't opened for writing}}
+test chan-io-29.2 {Tcl_WriteChars, empty string} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -eofchar {}
+ chan puts -nonewline $f ""
+ chan close $f
+ file size $path(test1)
+} 0
+test chan-io-29.3 {Tcl_WriteChars, nonempty string} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -eofchar {}
+ chan puts -nonewline $f hello
+ chan close $f
+ file size $path(test1)
+} 5
+test chan-io-29.4 {Tcl_WriteChars, buffering in full buffering mode} {testchannel} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf -buffering full -eofchar {}
+ chan puts $f hello
+ set l ""
+ lappend l [testchannel outputbuffered $f]
+ lappend l [file size $path(test1)]
+ chan flush $f
+ lappend l [testchannel outputbuffered $f]
+ lappend l [file size $path(test1)]
+ chan close $f
+ set l
+} {6 0 0 6}
+test chan-io-29.5 {Tcl_WriteChars, buffering in line buffering mode} {testchannel} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf -buffering line -eofchar {}
+ chan puts -nonewline $f hello
+ set l ""
+ lappend l [testchannel outputbuffered $f]
+ lappend l [file size $path(test1)]
+ chan puts $f hello
+ lappend l [testchannel outputbuffered $f]
+ lappend l [file size $path(test1)]
+ chan close $f
+ set l
+} {5 0 0 11}
+test chan-io-29.6 {Tcl_WriteChars, buffering in no buffering mode} {testchannel} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf -buffering none -eofchar {}
+ chan puts -nonewline $f hello
+ set l ""
+ lappend l [testchannel outputbuffered $f]
+ lappend l [file size $path(test1)]
+ chan puts $f hello
+ lappend l [testchannel outputbuffered $f]
+ lappend l [file size $path(test1)]
+ chan close $f
+ set l
+} {0 5 0 11}
+test chan-io-29.7 {Tcl_Flush, full buffering} {testchannel} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf -buffering full -eofchar {}
+ chan puts -nonewline $f hello
+ set l ""
+ lappend l [testchannel outputbuffered $f]
+ lappend l [file size $path(test1)]
+ chan puts $f hello
+ lappend l [testchannel outputbuffered $f]
+ lappend l [file size $path(test1)]
+ chan flush $f
+ lappend l [testchannel outputbuffered $f]
+ lappend l [file size $path(test1)]
+ chan close $f
+ set l
+} {5 0 11 0 0 11}
+test chan-io-29.8 {Tcl_Flush, full buffering} {testchannel} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf -buffering line
+ chan puts -nonewline $f hello
+ set l ""
+ lappend l [testchannel outputbuffered $f]
+ lappend l [file size $path(test1)]
+ chan flush $f
+ lappend l [testchannel outputbuffered $f]
+ lappend l [file size $path(test1)]
+ chan puts $f hello
+ lappend l [testchannel outputbuffered $f]
+ lappend l [file size $path(test1)]
+ chan flush $f
+ lappend l [testchannel outputbuffered $f]
+ lappend l [file size $path(test1)]
+ chan close $f
+ set l
+} {5 0 0 5 0 11 0 11}
+test chan-io-29.9 {Tcl_Flush, channel not writable} {
+ list [catch {chan flush stdin} msg] $msg
+} {1 {channel "stdin" wasn't opened for writing}}
+test chan-io-29.10 {Tcl_WriteChars, looping and buffering} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ chan configure $f1 -translation lf -eofchar {}
+ set f2 [open $path(longfile) r]
+ for {set x 0} {$x < 10} {incr x} {
+ chan puts $f1 [chan gets $f2]
+ }
+ chan close $f2
+ chan close $f1
+ file size $path(test1)
+} 387
+test chan-io-29.11 {Tcl_WriteChars, no newline, implicit flush} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ chan configure $f1 -eofchar {}
+ set f2 [open $path(longfile) r]
+ for {set x 0} {$x < 10} {incr x} {
+ chan puts -nonewline $f1 [chan gets $f2]
+ }
+ chan close $f1
+ chan close $f2
+ file size $path(test1)
+} 377
+test chan-io-29.12 {Tcl_WriteChars on a pipe} {stdio openpipe} {
+ file delete $path(test1)
+ file delete $path(pipe)
+ set f1 [open $path(pipe) w]
+ chan puts $f1 "set f1 \[[list open $path(longfile) r]]"
+ chan puts $f1 {
+ for {set x 0} {$x < 10} {incr x} {
+ chan puts [chan gets $f1]
+ }
+ }
+ chan close $f1
+ set f1 [open "|[list [interpreter] $path(pipe)]" r]
+ set f2 [open $path(longfile) r]
+ set y ok
+ for {set x 0} {$x < 10} {incr x} {
+ set l1 [chan gets $f1]
+ set l2 [chan gets $f2]
+ if {"$l1" != "$l2"} {
+ set y broken
+ }
+ }
+ chan close $f1
+ chan close $f2
+ set y
+} ok
+test chan-io-29.13 {Tcl_WriteChars to a pipe, line buffered} {stdio openpipe} {
+ file delete $path(test1)
+ file delete $path(pipe)
+ set f1 [open $path(pipe) w]
+ chan puts $f1 {
+ chan puts [chan gets stdin]
+ chan puts [chan gets stdin]
+ }
+ chan close $f1
+ set y ok
+ set f1 [open "|[list [interpreter] $path(pipe)]" r+]
+ chan configure $f1 -buffering line
+ set f2 [open $path(longfile) r]
+ set line [chan gets $f2]
+ chan puts $f1 $line
+ set backline [chan gets $f1]
+ if {"$line" != "$backline"} {
+ set y broken
+ }
+ set line [chan gets $f2]
+ chan puts $f1 $line
+ set backline [chan gets $f1]
+ if {"$line" != "$backline"} {
+ set y broken
+ }
+ chan close $f1
+ chan close $f2
+ set y
+} ok
+test chan-io-29.14 {Tcl_WriteChars, buffering and implicit flush at chan close} {
+ file delete $path(test3)
+ set f [open $path(test3) w]
+ chan puts -nonewline $f "Text1"
+ chan puts -nonewline $f " Text 2"
+ chan puts $f " Text 3"
+ chan close $f
+ set f [open $path(test3) r]
+ set x [chan gets $f]
+ chan close $f
+ set x
+} {Text1 Text 2 Text 3}
+test chan-io-29.15 {Tcl_Flush, channel not open for writing} {
+ file delete $path(test1)
+ set fd [open $path(test1) w]
+ chan close $fd
+ set fd [open $path(test1) r]
+ set x [list [catch {chan flush $fd} msg] $msg]
+ chan close $fd
+ string compare $x \
+ [list 1 "channel \"$fd\" wasn't opened for writing"]
+} 0
+test chan-io-29.16 {Tcl_Flush on pipe opened only for reading} {stdio openpipe} {
+ set fd [open "|[list [interpreter] cat longfile]" r]
+ set x [list [catch {chan flush $fd} msg] $msg]
+ catch {chan close $fd}
+ string compare $x \
+ [list 1 "channel \"$fd\" wasn't opened for writing"]
+} 0
+test chan-io-29.17 {Tcl_WriteChars buffers, then Tcl_Flush flushes} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ chan configure $f1 -translation lf
+ chan puts $f1 hello
+ chan puts $f1 hello
+ chan puts $f1 hello
+ chan flush $f1
+ set x [file size $path(test1)]
+ chan close $f1
+ set x
+} 18
+test chan-io-29.18 {Tcl_WriteChars and Tcl_Flush intermixed} {
+ file delete $path(test1)
+ set x ""
+ set f1 [open $path(test1) w]
+ chan configure $f1 -translation lf
+ chan puts $f1 hello
+ chan puts $f1 hello
+ chan puts $f1 hello
+ chan flush $f1
+ lappend x [file size $path(test1)]
+ chan puts $f1 hello
+ chan flush $f1
+ lappend x [file size $path(test1)]
+ chan puts $f1 hello
+ chan flush $f1
+ lappend x [file size $path(test1)]
+ chan close $f1
+ set x
+} {18 24 30}
+test chan-io-29.19 {Explicit and implicit flushes} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ chan configure $f1 -translation lf -eofchar {}
+ set x ""
+ chan puts $f1 hello
+ chan puts $f1 hello
+ chan puts $f1 hello
+ chan flush $f1
+ lappend x [file size $path(test1)]
+ chan puts $f1 hello
+ chan flush $f1
+ lappend x [file size $path(test1)]
+ chan puts $f1 hello
+ chan close $f1
+ lappend x [file size $path(test1)]
+ set x
+} {18 24 30}
+test chan-io-29.20 {Implicit flush when buffer is full} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ chan configure $f1 -translation lf -eofchar {}
+ set line "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+ for {set x 0} {$x < 100} {incr x} {
+ chan puts $f1 $line
+ }
+ set z ""
+ lappend z [file size $path(test1)]
+ for {set x 0} {$x < 100} {incr x} {
+ chan puts $f1 $line
+ }
+ lappend z [file size $path(test1)]
+ chan close $f1
+ lappend z [file size $path(test1)]
+ set z
+} {4096 12288 12600}
+test chan-io-29.21 {Tcl_Flush to pipe} {stdio openpipe} {
+ file delete $path(pipe)
+ set f1 [open $path(pipe) w]
+ chan puts $f1 {set x [chan read stdin 6]}
+ chan puts $f1 {set cnt [string length $x]}
+ chan puts $f1 {chan puts "read $cnt characters"}
+ chan close $f1
+ set f1 [open "|[list [interpreter] $path(pipe)]" r+]
+ chan puts $f1 hello
+ chan flush $f1
+ set x [chan gets $f1]
+ catch {chan close $f1}
+ set x
+} "read 6 characters"
+test chan-io-29.22 {Tcl_Flush called at other end of pipe} {stdio openpipe} {
+ file delete $path(pipe)
+ set f1 [open $path(pipe) w]
+ chan puts $f1 {
+ chan configure stdout -buffering full
+ chan puts hello
+ chan puts hello
+ chan flush stdout
+ chan gets stdin
+ chan puts bye
+ chan flush stdout
+ }
+ chan close $f1
+ set f1 [open "|[list [interpreter] $path(pipe)]" r+]
+ set x ""
+ lappend x [chan gets $f1]
+ lappend x [chan gets $f1]
+ chan puts $f1 hello
+ chan flush $f1
+ lappend x [chan gets $f1]
+ chan close $f1
+ set x
+} {hello hello bye}
+test chan-io-29.23 {Tcl_Flush and line buffering at end of pipe} {stdio openpipe} {
+ file delete $path(pipe)
+ set f1 [open $path(pipe) w]
+ chan puts $f1 {
+ chan puts hello
+ chan puts hello
+ chan gets stdin
+ chan puts bye
+ }
+ chan close $f1
+ set f1 [open "|[list [interpreter] $path(pipe)]" r+]
+ set x ""
+ lappend x [chan gets $f1]
+ lappend x [chan gets $f1]
+ chan puts $f1 hello
+ chan flush $f1
+ lappend x [chan gets $f1]
+ chan close $f1
+ set x
+} {hello hello bye}
+test chan-io-29.24 {Tcl_WriteChars and Tcl_Flush move end of file} {
+ set f [open $path(test3) w]
+ chan puts $f "Line 1"
+ chan puts $f "Line 2"
+ set f2 [open $path(test3)]
+ set x {}
+ lappend x [chan read -nonewline $f2]
+ chan close $f2
+ chan flush $f
+ set f2 [open $path(test3)]
+ lappend x [chan read -nonewline $f2]
+ chan close $f2
+ chan close $f
+ set x
+} "{} {Line 1\nLine 2}"
+test chan-io-29.25 {Implicit flush with Tcl_Flush to command pipelines} {stdio openpipe fileevent} {
+ file delete $path(test3)
+ set f [open "|[list [interpreter] $path(cat) | [interpreter] $path(cat) > $path(test3)]" w]
+ chan puts $f "Line 1"
+ chan puts $f "Line 2"
+ chan close $f
+ after 100
+ set f [open $path(test3) r]
+ set x [chan read $f]
+ chan close $f
+ set x
+} "Line 1\nLine 2\n"
+test chan-io-29.26 {Tcl_Flush, Tcl_Write on bidirectional pipelines} {stdio unixExecs openpipe} {
+ set f [open "|[list cat -u]" r+]
+ chan puts $f "Line1"
+ chan flush $f
+ set x [chan gets $f]
+ chan close $f
+ set x
+} {Line1}
+test chan-io-29.27 {Tcl_Flush on chan closed pipeline} {stdio openpipe} {
+ file delete $path(pipe)
+ set f [open $path(pipe) w]
+ chan puts $f {exit}
+ chan close $f
+ set f [open "|[list [interpreter] $path(pipe)]" r+]
+ chan gets $f
+ chan puts $f output
+ after 50
+ #
+ # The flush below will get a SIGPIPE. This is an expected part of
+ # test and indicates that the test operates correctly. If you run
+ # this test under a debugger, the signal will by intercepted unless
+ # you disable the debugger's signal interception.
+ #
+ if {[catch {chan flush $f} msg]} {
+ set x [list 1 $msg $::errorCode]
+ catch {chan close $f}
+ } else {
+ if {[catch {chan close $f} msg]} {
+ set x [list 1 $msg $::errorCode]
+ } else {
+ set x {this was supposed to fail and did not}
+ }
+ }
+ regsub {".*":} $x {"":} x
+ string tolower $x
+} {1 {error flushing "": broken pipe} {posix epipe {broken pipe}}}
+test chan-io-29.28 {Tcl_WriteChars, lf mode} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf -eofchar {}
+ chan puts $f hello\nthere\nand\nhere
+ chan flush $f
+ set s [file size $path(test1)]
+ chan close $f
+ set s
+} 21
+test chan-io-29.29 {Tcl_WriteChars, cr mode} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr -eofchar {}
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ file size $path(test1)
+} 21
+test chan-io-29.30 {Tcl_WriteChars, crlf mode} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf -eofchar {}
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ file size $path(test1)
+} 25
+test chan-io-29.31 {Tcl_WriteChars, background flush} {stdio openpipe} {
+ file delete $path(pipe)
+ file delete $path(output)
+ set f [open $path(pipe) w]
+ chan puts $f "set f \[[list open $path(output) w]]"
+ chan puts $f {chan configure $f -translation lf}
+ set x [list while {![chan eof stdin]}]
+ set x "$x {"
+ chan puts $f $x
+ chan puts $f { chan puts -nonewline $f [chan read stdin 4096]}
+ chan puts $f { chan flush $f}
+ chan puts $f "}"
+ chan puts $f {chan close $f}
+ chan close $f
+ set x 01234567890123456789012345678901
+ for {set i 0} {$i < 11} {incr i} {
+ set x "$x$x"
+ }
+ set f [open $path(output) w]
+ chan close $f
+ set f [open "|[list [interpreter] $path(pipe)]" r+]
+ chan configure $f -blocking off
+ chan puts -nonewline $f $x
+ chan close $f
+ set counter 0
+ while {([file size $path(output)] < 65536) && ($counter < 1000)} {
+ after 10 [list incr [namespace which -variable counter]]
+ vwait [namespace which -variable counter]
+ }
+ if {$counter == 1000} {
+ set result "file size only [file size $path(output)]"
+ } else {
+ set result ok
+ }
+ # allow a little time for the background process to chan close.
+ # otherwise, the following test fails on the [file delete $path(output)
+ # on Windows because a process still has the file open.
+ after 100 set v 1; vwait v
+ set result
+} ok
+test chan-io-29.32 {Tcl_WriteChars, background flush to slow reader} \
+ {stdio asyncPipeChan Close openpipe} {
+ file delete $path(pipe)
+ file delete $path(output)
+ set f [open $path(pipe) w]
+ chan puts $f "set f \[[list open $path(output) w]]"
+ chan puts $f {chan configure $f -translation lf}
+ set x [list while {![chan eof stdin]}]
+ set x "$x \{"
+ chan puts $f $x
+ chan puts $f { after 20}
+ chan puts $f { chan puts -nonewline $f [chan read stdin 1024]}
+ chan puts $f { chan flush $f}
+ chan puts $f "\}"
+ chan puts $f {chan close $f}
+ chan close $f
+ set x 01234567890123456789012345678901
+ for {set i 0} {$i < 11} {incr i} {
+ set x "$x$x"
+ }
+ set f [open $path(output) w]
+ chan close $f
+ set f [open "|[list [interpreter] $path(pipe)]" r+]
+ chan configure $f -blocking off
+ chan puts -nonewline $f $x
+ chan close $f
+ set counter 0
+ while {([file size $path(output)] < 65536) && ($counter < 1000)} {
+ after 20 [list incr [namespace which -variable counter]]
+ vwait [namespace which -variable counter]
+ }
+ if {$counter == 1000} {
+ set result "file size only [file size $path(output)]"
+ } else {
+ set result ok
+ }
+} ok
+test chan-io-29.33 {Tcl_Flush, implicit flush on exit} {exec} {
+ set f [open $path(script) w]
+ chan puts $f "set f \[[list open $path(test1) w]]"
+ chan puts $f {chan configure $f -translation lf
+ chan puts $f hello
+ chan puts $f bye
+ chan puts $f strange
+ }
+ chan close $f
+ exec [interpreter] $path(script)
+ set f [open $path(test1) r]
+ set r [chan read $f]
+ chan close $f
+ set r
+} "hello\nbye\nstrange\n"
+test chan-io-29.34 {Tcl_Chan Close, async flush on chan close, using sockets} {socket tempNotMac fileevent} {
+ variable c 0
+ variable x running
+ set l abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
+ proc writelots {s l} {
+ for {set i 0} {$i < 2000} {incr i} {
+ chan puts $s $l
+ }
+ }
+ proc accept {s a p} {
+ variable x
+ chan event $s readable [namespace code [list readit $s]]
+ chan configure $s -blocking off
+ set x accepted
+ }
+ proc readit {s} {
+ variable c
+ variable x
+ set l [chan gets $s]
+
+ if {[chan eof $s]} {
+ chan close $s
+ set x done
+ } elseif {([string length $l] > 0) || ![chan blocked $s]} {
+ incr c
+ }
+ }
+ set ss [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
+ set cs [socket 127.0.0.1 [lindex [chan configure $ss -sockname] 2]]
+ vwait [namespace which -variable x]
+ chan configure $cs -blocking off
+ writelots $cs $l
+ chan close $cs
+ chan close $ss
+ vwait [namespace which -variable x]
+ set c
+} 2000
+test chan-io-29.35 {Tcl_Chan Close vs chan event vs multiple interpreters} {socket tempNotMac fileevent} {
+ # On Mac, this test screws up sockets such that subsequent tests using port 2828
+ # either cause errors or panic().
+
+ catch {interp delete x}
+ catch {interp delete y}
+ interp create x
+ interp create y
+ set s [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
+ proc accept {s a p} {
+ chan puts $s hello
+ chan close $s
+ }
+ set c [socket 127.0.0.1 [lindex [chan configure $s -sockname] 2]]
+ interp share {} $c x
+ interp share {} $c y
+ chan close $c
+ x eval {
+ proc readit {s} {
+ chan gets $s
+ if {[chan eof $s]} {
+ chan close $s
+ }
+ }
+ }
+ y eval {
+ proc readit {s} {
+ chan gets $s
+ if {[chan eof $s]} {
+ chan close $s
+ }
+ }
+ }
+ x eval "chan event $c readable \{readit $c\}"
+ y eval "chan event $c readable \{readit $c\}"
+ y eval [list chan close $c]
+ update
+ chan close $s
+ interp delete x
+ interp delete y
+} ""
+
+# Test end of line translations. Procedures tested are Tcl_Write, Tcl_Read.
+
+test chan-io-30.1 {Tcl_Write lf, Tcl_Read lf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation lf
+ set x [chan read $f]
+ chan close $f
+ set x
+} "hello\nthere\nand\nhere\n"
+test chan-io-30.2 {Tcl_Write lf, Tcl_Read cr} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation cr
+ set x [chan read $f]
+ chan close $f
+ set x
+} "hello\nthere\nand\nhere\n"
+test chan-io-30.3 {Tcl_Write lf, Tcl_Read crlf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation crlf
+ set x [chan read $f]
+ chan close $f
+ set x
+} "hello\nthere\nand\nhere\n"
+test chan-io-30.4 {Tcl_Write cr, Tcl_Read cr} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation cr
+ set x [chan read $f]
+ chan close $f
+ set x
+} "hello\nthere\nand\nhere\n"
+test chan-io-30.5 {Tcl_Write cr, Tcl_Read lf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation lf
+ set x [chan read $f]
+ chan close $f
+ set x
+} "hello\rthere\rand\rhere\r"
+test chan-io-30.6 {Tcl_Write cr, Tcl_Read crlf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation crlf
+ set x [chan read $f]
+ chan close $f
+ set x
+} "hello\rthere\rand\rhere\r"
+test chan-io-30.7 {Tcl_Write crlf, Tcl_Read crlf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation crlf
+ set x [chan read $f]
+ chan close $f
+ set x
+} "hello\nthere\nand\nhere\n"
+test chan-io-30.8 {Tcl_Write crlf, Tcl_Read lf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation lf
+ set x [chan read $f]
+ chan close $f
+ set x
+} "hello\r\nthere\r\nand\r\nhere\r\n"
+test chan-io-30.9 {Tcl_Write crlf, Tcl_Read cr} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation cr
+ set x [chan read $f]
+ chan close $f
+ set x
+} "hello\n\nthere\n\nand\n\nhere\n\n"
+test chan-io-30.10 {Tcl_Write lf, Tcl_Read auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ set c [chan read $f]
+ set x [chan configure $f -translation]
+ chan close $f
+ list $c $x
+} {{hello
+there
+and
+here
+} auto}
+test chan-io-30.11 {Tcl_Write cr, Tcl_Read auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ set c [chan read $f]
+ set x [chan configure $f -translation]
+ chan close $f
+ list $c $x
+} {{hello
+there
+and
+here
+} auto}
+test chan-io-30.12 {Tcl_Write crlf, Tcl_Read auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ set c [chan read $f]
+ set x [chan configure $f -translation]
+ chan close $f
+ list $c $x
+} {{hello
+there
+and
+here
+} auto}
+test chan-io-30.13 {Tcl_Write crlf on block boundary, Tcl_Read auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf
+ set line "123456789ABCDE" ;# 14 char plus crlf
+ chan puts -nonewline $f x ;# shift crlf across block boundary
+ for {set i 0} {$i < 700} {incr i} {
+ chan puts $f $line
+ }
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation auto
+ set c [chan read $f]
+ chan close $f
+ string length $c
+} [expr 700*15+1]
+test chan-io-30.14 {Tcl_Write crlf on block boundary, Tcl_Read crlf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf
+ set line "123456789ABCDE" ;# 14 char plus crlf
+ chan puts -nonewline $f x ;# shift crlf across block boundary
+ for {set i 0} {$i < 700} {incr i} {
+ chan puts $f $line
+ }
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation crlf
+ set c [chan read $f]
+ chan close $f
+ string length $c
+} [expr 700*15+1]
+test chan-io-30.15 {Tcl_Write mixed, Tcl_Read auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts $f hello\nthere\nand\rhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation auto
+ set c [chan read $f]
+ chan close $f
+ set c
+} {hello
+there
+and
+here
+}
+test chan-io-30.16 {Tcl_Write ^Z at end, Tcl_Read auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f hello\nthere\nand\rhere\n\x1a
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -eofchar \x1a -translation auto
+ set c [chan read $f]
+ chan close $f
+ set c
+} {hello
+there
+and
+here
+}
+test chan-io-30.17 {Tcl_Write, implicit ^Z at end, Tcl_Read auto} {win} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -eofchar \x1a -translation lf
+ chan puts $f hello\nthere\nand\rhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -eofchar \x1a -translation auto
+ set c [chan read $f]
+ chan close $f
+ set c
+} {hello
+there
+and
+here
+}
+test chan-io-30.18 {Tcl_Write, ^Z in middle, Tcl_Read auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ set s [format "abc\ndef\n%cghi\nqrs" 26]
+ chan puts $f $s
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -eofchar \x1a -translation auto
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {abc def 0 {} 1 {} 1}
+test chan-io-30.19 {Tcl_Write, ^Z no newline in middle, Tcl_Read auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ set s [format "abc\ndef\n%cghi\nqrs" 26]
+ chan puts $f $s
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -eofchar \x1a -translation auto
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {abc def 0 {} 1 {} 1}
+test chan-io-30.20 {Tcl_Write, ^Z in middle ignored, Tcl_Read lf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf -eofchar {}
+ set s [format "abc\ndef\n%cghi\nqrs" 26]
+ chan puts $f $s
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation lf -eofchar {}
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} "abc def 0 \x1aghi 0 qrs 0 {} 1"
+test chan-io-30.21 {Tcl_Write, ^Z in middle ignored, Tcl_Read cr} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf -eofchar {}
+ set s [format "abc\ndef\n%cghi\nqrs" 26]
+ chan puts $f $s
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation cr -eofchar {}
+ set l ""
+ set x [chan gets $f]
+ lappend l [string compare $x "abc\ndef\n\x1aghi\nqrs\n"]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {0 1 {} 1}
+test chan-io-30.22 {Tcl_Write, ^Z in middle ignored, Tcl_Read crlf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf -eofchar {}
+ set s [format "abc\ndef\n%cghi\nqrs" 26]
+ chan puts $f $s
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation crlf -eofchar {}
+ set l ""
+ set x [chan gets $f]
+ lappend l [string compare $x "abc\ndef\n\x1aghi\nqrs\n"]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {0 1 {} 1}
+test chan-io-30.23 {Tcl_Write lf, ^Z in middle, Tcl_Read auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ set c [format abc\ndef\n%cqrs\ntuv 26]
+ chan puts $f $c
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation auto -eofchar \x1a
+ set c [string length [chan read $f]]
+ set e [chan eof $f]
+ chan close $f
+ list $c $e
+} {8 1}
+test chan-io-30.24 {Tcl_Write lf, ^Z in middle, Tcl_Read lf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ set c [format abc\ndef\n%cqrs\ntuv 26]
+ chan puts $f $c
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation lf -eofchar \x1a
+ set c [string length [chan read $f]]
+ set e [chan eof $f]
+ chan close $f
+ list $c $e
+} {8 1}
+test chan-io-30.25 {Tcl_Write cr, ^Z in middle, Tcl_Read auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr
+ set c [format abc\ndef\n%cqrs\ntuv 26]
+ chan puts $f $c
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation auto -eofchar \x1a
+ set c [string length [chan read $f]]
+ set e [chan eof $f]
+ chan close $f
+ list $c $e
+} {8 1}
+test chan-io-30.26 {Tcl_Write cr, ^Z in middle, Tcl_Read cr} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr
+ set c [format abc\ndef\n%cqrs\ntuv 26]
+ chan puts $f $c
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation cr -eofchar \x1a
+ set c [string length [chan read $f]]
+ set e [chan eof $f]
+ chan close $f
+ list $c $e
+} {8 1}
+test chan-io-30.27 {Tcl_Write crlf, ^Z in middle, Tcl_Read auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf
+ set c [format abc\ndef\n%cqrs\ntuv 26]
+ chan puts $f $c
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation auto -eofchar \x1a
+ set c [string length [chan read $f]]
+ set e [chan eof $f]
+ chan close $f
+ list $c $e
+} {8 1}
+test chan-io-30.28 {Tcl_Write crlf, ^Z in middle, Tcl_Read crlf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf
+ set c [format abc\ndef\n%cqrs\ntuv 26]
+ chan puts $f $c
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation crlf -eofchar \x1a
+ set c [string length [chan read $f]]
+ set e [chan eof $f]
+ chan close $f
+ list $c $e
+} {8 1}
+
+# Test end of line translations. Functions tested are Tcl_Write and Tcl_Gets.
+
+test chan-io-31.1 {Tcl_Write lf, Tcl_Gets auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ lappend l [chan gets $f]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ chan close $f
+ set l
+} {hello 6 auto there 12 auto}
+test chan-io-31.2 {Tcl_Write cr, Tcl_Gets auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ lappend l [chan gets $f]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ chan close $f
+ set l
+} {hello 6 auto there 12 auto}
+test chan-io-31.3 {Tcl_Write crlf, Tcl_Gets auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ lappend l [chan gets $f]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ chan close $f
+ set l
+} {hello 7 auto there 14 auto}
+test chan-io-31.4 {Tcl_Write lf, Tcl_Gets lf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation lf
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ lappend l [chan gets $f]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ chan close $f
+ set l
+} {hello 6 lf there 12 lf}
+test chan-io-31.5 {Tcl_Write lf, Tcl_Gets cr} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation cr
+ set l ""
+ lappend l [string length [chan gets $f]]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {21 21 cr 1 {} 21 cr 1}
+test chan-io-31.6 {Tcl_Write lf, Tcl_Gets crlf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation crlf
+ set l ""
+ lappend l [string length [chan gets $f]]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {21 21 crlf 1 {} 21 crlf 1}
+test chan-io-31.7 {Tcl_Write cr, Tcl_Gets cr} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation cr
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {hello 6 cr 0 there 12 cr 0}
+test chan-io-31.8 {Tcl_Write cr, Tcl_Gets lf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation lf
+ set l ""
+ lappend l [string length [chan gets $f]]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {21 21 lf 1 {} 21 lf 1}
+test chan-io-31.9 {Tcl_Write cr, Tcl_Gets crlf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation crlf
+ set l ""
+ lappend l [string length [chan gets $f]]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {21 21 crlf 1 {} 21 crlf 1}
+test chan-io-31.10 {Tcl_Write crlf, Tcl_Gets crlf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation crlf
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {hello 7 crlf 0 there 14 crlf 0}
+test chan-io-31.11 {Tcl_Write crlf, Tcl_Gets cr} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation cr
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ lappend l [chan eof $f]
+ lappend l [string length [chan gets $f]]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {hello 6 cr 0 6 13 cr 0}
+test chan-io-31.12 {Tcl_Write crlf, Tcl_Gets lf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf
+ chan puts $f hello\nthere\nand\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation lf
+ set l ""
+ lappend l [string length [chan gets $f]]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ lappend l [chan eof $f]
+ lappend l [string length [chan gets $f]]
+ lappend l [chan tell $f]
+ lappend l [chan configure $f -translation]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {6 7 lf 0 6 14 lf 0}
+test chan-io-31.13 {binary mode is synonym of lf mode} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation binary
+ set x [chan configure $f -translation]
+ chan close $f
+ set x
+} lf
+#
+# Test chan-io-9.14 has been removed because "auto" output translation mode is
+# not supoprted.
+#
+test chan-io-31.14 {Tcl_Write mixed, Tcl_Gets auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts $f hello\nthere\rand\r\nhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation auto
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {hello there and here 0 {} 1}
+test chan-io-31.15 {Tcl_Write mixed, Tcl_Gets auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f hello\nthere\rand\r\nhere\r
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation auto
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {hello there and here 0 {} 1}
+test chan-io-31.16 {Tcl_Write mixed, Tcl_Gets auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f hello\nthere\rand\r\nhere\n
+ chan close $f
+ set f [open $path(test1) r]
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {hello there and here 0 {} 1}
+test chan-io-31.17 {Tcl_Write mixed, Tcl_Gets auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f hello\nthere\rand\r\nhere\r\n
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation auto
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {hello there and here 0 {} 1}
+test chan-io-31.18 {Tcl_Write ^Z at end, Tcl_Gets auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ set s [format "hello\nthere\nand\rhere\n\%c" 26]
+ chan puts $f $s
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -eofchar \x1a -translation auto
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {hello there and here 0 {} 1}
+test chan-io-31.19 {Tcl_Write, implicit ^Z at end, Tcl_Gets auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -eofchar \x1a -translation lf
+ chan puts $f hello\nthere\nand\rhere
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -eofchar \x1a -translation auto
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {hello there and here 0 {} 1}
+test chan-io-31.20 {Tcl_Write, ^Z in middle, Tcl_Gets auto, eofChar} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ set s [format "abc\ndef\n%cqrs\ntuv" 26]
+ chan puts $f $s
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -eofchar \x1a
+ chan configure $f -translation auto
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {abc def 0 {} 1}
+test chan-io-31.21 {Tcl_Write, no newline ^Z in middle, Tcl_Gets auto, eofChar} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ set s [format "abc\ndef\n%cqrs\ntuv" 26]
+ chan puts $f $s
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -eofchar \x1a -translation auto
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {abc def 0 {} 1}
+test chan-io-31.22 {Tcl_Write, ^Z in middle ignored, Tcl_Gets lf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf -eofchar {}
+ set s [format "abc\ndef\n%cqrs\ntuv" 26]
+ chan puts $f $s
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation lf -eofchar {}
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} "abc def 0 \x1aqrs 0 tuv 0 {} 1"
+test chan-io-31.23 {Tcl_Write, ^Z in middle ignored, Tcl_Gets cr} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr -eofchar {}
+ set s [format "abc\ndef\n%cqrs\ntuv" 26]
+ chan puts $f $s
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation cr -eofchar {}
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} "abc def 0 \x1aqrs 0 tuv 0 {} 1"
+test chan-io-31.24 {Tcl_Write, ^Z in middle ignored, Tcl_Gets crlf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf -eofchar {}
+ set s [format "abc\ndef\n%cqrs\ntuv" 26]
+ chan puts $f $s
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation crlf -eofchar {}
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} "abc def 0 \x1aqrs 0 tuv 0 {} 1"
+test chan-io-31.25 {Tcl_Write lf, ^Z in middle, Tcl_Gets auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ set s [format "abc\ndef\n%cqrs\ntuv" 26]
+ chan puts $f $s
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation auto -eofchar \x1a
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {abc def 0 {} 1}
+test chan-io-31.26 {Tcl_Write lf, ^Z in middle, Tcl_Gets lf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ set s [format "abc\ndef\n%cqrs\ntuv" 26]
+ chan puts $f $s
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation lf -eofchar \x1a
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {abc def 0 {} 1}
+test chan-io-31.27 {Tcl_Write cr, ^Z in middle, Tcl_Gets auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr -eofchar {}
+ set s [format "abc\ndef\n%cqrs\ntuv" 26]
+ chan puts $f $s
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation auto -eofchar \x1a
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {abc def 0 {} 1}
+test chan-io-31.28 {Tcl_Write cr, ^Z in middle, Tcl_Gets cr} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr -eofchar {}
+ set s [format "abc\ndef\n%cqrs\ntuv" 26]
+ chan puts $f $s
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation cr -eofchar \x1a
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {abc def 0 {} 1}
+test chan-io-31.29 {Tcl_Write crlf, ^Z in middle, Tcl_Gets auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf -eofchar {}
+ set s [format "abc\ndef\n%cqrs\ntuv" 26]
+ chan puts $f $s
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation auto -eofchar \x1a
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {abc def 0 {} 1}
+test chan-io-31.30 {Tcl_Write crlf, ^Z in middle, Tcl_Gets crlf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf -eofchar {}
+ set s [format "abc\ndef\n%cqrs\ntuv" 26]
+ chan puts $f $s
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation crlf -eofchar \x1a
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {abc def 0 {} 1}
+test chan-io-31.31 {Tcl_Write crlf on block boundary, Tcl_Gets crlf} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf
+ set line "123456789ABCDE" ;# 14 char plus crlf
+ chan puts -nonewline $f x ;# shift crlf across block boundary
+ for {set i 0} {$i < 700} {incr i} {
+ chan puts $f $line
+ }
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation crlf
+ set c ""
+ while {[chan gets $f line] >= 0} {
+ append c $line\n
+ }
+ chan close $f
+ string length $c
+} [expr 700*15+1]
+test chan-io-31.32 {Tcl_Write crlf on block boundary, Tcl_Gets auto} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf
+ set line "123456789ABCDE" ;# 14 char plus crlf
+ chan puts -nonewline $f x ;# shift crlf across block boundary
+ for {set i 0} {$i < 700} {incr i} {
+ chan puts $f $line
+ }
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -translation auto
+ set c ""
+ while {[chan gets $f line] >= 0} {
+ append c $line\n
+ }
+ chan close $f
+ string length $c
+} [expr 700*15+1]
+
+# Test Tcl_Read and buffering.
+
+test chan-io-32.1 {Tcl_Read, channel not readable} {
+ list [catch {read stdout} msg] $msg
+} {1 {channel "stdout" wasn't opened for reading}}
+test chan-io-32.2 {Tcl_Read, zero byte count} {
+ chan read stdin 0
+} ""
+test chan-io-32.3 {Tcl_Read, negative byte count} {
+ set f [open $path(longfile) r]
+ set l [list [catch {chan read $f -1} msg] $msg]
+ chan close $f
+ set l
+} {1 {expected non-negative integer but got "-1"}}
+test chan-io-32.4 {Tcl_Read, positive byte count} {
+ set f [open $path(longfile) r]
+ set x [chan read $f 1024]
+ set s [string length $x]
+ unset x
+ chan close $f
+ set s
+} 1024
+test chan-io-32.5 {Tcl_Read, multiple buffers} {
+ set f [open $path(longfile) r]
+ chan configure $f -buffersize 100
+ set x [chan read $f 1024]
+ set s [string length $x]
+ unset x
+ chan close $f
+ set s
+} 1024
+test chan-io-32.6 {Tcl_Read, very large read} {
+ set f1 [open $path(longfile) r]
+ set z [chan read $f1 1000000]
+ chan close $f1
+ set l [string length $z]
+ set x ok
+ set z [file size $path(longfile)]
+ if {$z != $l} {
+ set x broken
+ }
+ set x
+} ok
+test chan-io-32.7 {Tcl_Read, nonblocking, file} {nonBlockFiles} {
+ set f1 [open $path(longfile) r]
+ chan configure $f1 -blocking off
+ set z [chan read $f1 20]
+ chan close $f1
+ set l [string length $z]
+ set x ok
+ if {$l != 20} {
+ set x broken
+ }
+ set x
+} ok
+test chan-io-32.8 {Tcl_Read, nonblocking, file} {nonBlockFiles} {
+ set f1 [open $path(longfile) r]
+ chan configure $f1 -blocking off
+ set z [chan read $f1 1000000]
+ chan close $f1
+ set x ok
+ set l [string length $z]
+ set z [file size $path(longfile)]
+ if {$z != $l} {
+ set x broken
+ }
+ set x
+} ok
+test chan-io-32.9 {Tcl_Read, read to end of file} {
+ set f1 [open $path(longfile) r]
+ set z [chan read $f1]
+ chan close $f1
+ set l [string length $z]
+ set x ok
+ set z [file size $path(longfile)]
+ if {$z != $l} {
+ set x broken
+ }
+ set x
+} ok
+test chan-io-32.10 {Tcl_Read from a pipe} {stdio openpipe} {
+ file delete $path(pipe)
+ set f1 [open $path(pipe) w]
+ chan puts $f1 {chan puts [chan gets stdin]}
+ chan close $f1
+ set f1 [open "|[list [interpreter] $path(pipe)]" r+]
+ chan puts $f1 hello
+ chan flush $f1
+ set x [chan read $f1]
+ chan close $f1
+ set x
+} "hello\n"
+test chan-io-32.11 {Tcl_Read from a pipe} {stdio openpipe} {
+ file delete $path(pipe)
+ set f1 [open $path(pipe) w]
+ chan puts $f1 {chan puts [chan gets stdin]}
+ chan puts $f1 {chan puts [chan gets stdin]}
+ chan close $f1
+ set f1 [open "|[list [interpreter] $path(pipe)]" r+]
+ chan puts $f1 hello
+ chan flush $f1
+ set x ""
+ lappend x [chan read $f1 6]
+ chan puts $f1 hello
+ chan flush $f1
+ lappend x [chan read $f1]
+ chan close $f1
+ set x
+} {{hello
+} {hello
+}}
+test chan-io-32.12 {Tcl_Read, -nonewline} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ chan puts $f1 hello
+ chan puts $f1 bye
+ chan close $f1
+ set f1 [open $path(test1) r]
+ set c [chan read -nonewline $f1]
+ chan close $f1
+ set c
+} {hello
+bye}
+test chan-io-32.13 {Tcl_Read, -nonewline} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ chan puts $f1 hello
+ chan puts $f1 bye
+ chan close $f1
+ set f1 [open $path(test1) r]
+ set c [chan read -nonewline $f1]
+ chan close $f1
+ list [string length $c] $c
+} {9 {hello
+bye}}
+test chan-io-32.14 {Tcl_Read, reading in small chunks} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan puts $f "Two lines: this one"
+ chan puts $f "and this one"
+ chan close $f
+ set f [open $path(test1)]
+ set x [list [chan read $f 1] [chan read $f 2] [chan read $f]]
+ chan close $f
+ set x
+} {T wo { lines: this one
+and this one
+}}
+test chan-io-32.15 {Tcl_Read, asking for more input than available} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan puts $f "Two lines: this one"
+ chan puts $f "and this one"
+ chan close $f
+ set f [open $path(test1)]
+ set x [chan read $f 100]
+ chan close $f
+ set x
+} {Two lines: this one
+and this one
+}
+test chan-io-32.16 {Tcl_Read, read to end of file with -nonewline} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan puts $f "Two lines: this one"
+ chan puts $f "and this one"
+ chan close $f
+ set f [open $path(test1)]
+ set x [chan read -nonewline $f]
+ chan close $f
+ set x
+} {Two lines: this one
+and this one}
+
+# Test Tcl_Gets.
+
+test chan-io-33.1 {Tcl_Gets, reading what was written} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ set y "first line"
+ chan puts $f1 $y
+ chan close $f1
+ set f1 [open $path(test1) r]
+ set x [chan gets $f1]
+ set z ok
+ if {"$x" != "$y"} {
+ set z broken
+ }
+ chan close $f1
+ set z
+} ok
+test chan-io-33.2 {Tcl_Gets into variable} {
+ set f1 [open $path(longfile) r]
+ set c [chan gets $f1 x]
+ set l [string length x]
+ set z ok
+ if {$l != $l} {
+ set z broken
+ }
+ chan close $f1
+ set z
+} ok
+test chan-io-33.3 {Tcl_Gets from pipe} {stdio openpipe} {
+ file delete $path(pipe)
+ set f1 [open $path(pipe) w]
+ chan puts $f1 {chan puts [chan gets stdin]}
+ chan close $f1
+ set f1 [open "|[list [interpreter] $path(pipe)]" r+]
+ chan puts $f1 hello
+ chan flush $f1
+ set x [chan gets $f1]
+ chan close $f1
+ set z ok
+ if {"$x" != "hello"} {
+ set z broken
+ }
+ set z
+} ok
+test chan-io-33.4 {Tcl_Gets with long line} {
+ file delete $path(test3)
+ set f [open $path(test3) w]
+ chan puts -nonewline $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ chan puts -nonewline $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ chan puts -nonewline $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ chan puts -nonewline $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ chan puts $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ chan close $f
+ set f [open $path(test3)]
+ set x [chan gets $f]
+ chan close $f
+ set x
+} {abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ}
+test chan-io-33.5 {Tcl_Gets with long line} {
+ set f [open $path(test3)]
+ set x [chan gets $f y]
+ chan close $f
+ list $x $y
+} {260 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ}
+test chan-io-33.6 {Tcl_Gets and end of file} {
+ file delete $path(test3)
+ set f [open $path(test3) w]
+ chan puts -nonewline $f "Test1\nTest2"
+ chan close $f
+ set f [open $path(test3)]
+ set x {}
+ set y {}
+ lappend x [chan gets $f y] $y
+ set y {}
+ lappend x [chan gets $f y] $y
+ set y {}
+ lappend x [chan gets $f y] $y
+ chan close $f
+ set x
+} {5 Test1 5 Test2 -1 {}}
+test chan-io-33.7 {Tcl_Gets and bad variable} {
+ set f [open $path(test3) w]
+ chan puts $f "Line 1"
+ chan puts $f "Line 2"
+ chan close $f
+ catch {unset x}
+ set x 24
+ set f [open $path(test3) r]
+ set result [list [catch {chan gets $f x(0)} msg] $msg]
+ chan close $f
+ set result
+} {1 {can't set "x(0)": variable isn't array}}
+test chan-io-33.8 {Tcl_Gets, exercising double buffering} {
+ set f [open $path(test3) w]
+ chan configure $f -translation lf -eofchar {}
+ set x ""
+ for {set y 0} {$y < 99} {incr y} {set x "a$x"}
+ for {set y 0} {$y < 100} {incr y} {chan puts $f $x}
+ chan close $f
+ set f [open $path(test3) r]
+ chan configure $f -translation lf
+ for {set y 0} {$y < 100} {incr y} {chan gets $f}
+ chan close $f
+ set y
+} 100
+test chan-io-33.9 {Tcl_Gets, exercising double buffering} {
+ set f [open $path(test3) w]
+ chan configure $f -translation lf -eofchar {}
+ set x ""
+ for {set y 0} {$y < 99} {incr y} {set x "a$x"}
+ for {set y 0} {$y < 200} {incr y} {chan puts $f $x}
+ chan close $f
+ set f [open $path(test3) r]
+ chan configure $f -translation lf
+ for {set y 0} {$y < 200} {incr y} {chan gets $f}
+ chan close $f
+ set y
+} 200
+test chan-io-33.10 {Tcl_Gets, exercising double buffering} {
+ set f [open $path(test3) w]
+ chan configure $f -translation lf -eofchar {}
+ set x ""
+ for {set y 0} {$y < 99} {incr y} {set x "a$x"}
+ for {set y 0} {$y < 300} {incr y} {chan puts $f $x}
+ chan close $f
+ set f [open $path(test3) r]
+ chan configure $f -translation lf
+ for {set y 0} {$y < 300} {incr y} {chan gets $f}
+ chan close $f
+ set y
+} 300
+
+# Test Tcl_Seek and Tcl_Tell.
+
+test chan-io-34.1 {Tcl_Seek to current position at start of file} {
+ set f1 [open $path(longfile) r]
+ chan seek $f1 0 current
+ set c [chan tell $f1]
+ chan close $f1
+ set c
+} 0
+test chan-io-34.2 {Tcl_Seek to offset from start} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ chan configure $f1 -translation lf -eofchar {}
+ chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
+ chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
+ chan close $f1
+ set f1 [open $path(test1) r]
+ chan seek $f1 10 start
+ set c [chan tell $f1]
+ chan close $f1
+ set c
+} 10
+test chan-io-34.3 {Tcl_Seek to end of file} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ chan configure $f1 -translation lf -eofchar {}
+ chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
+ chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
+ chan close $f1
+ set f1 [open $path(test1) r]
+ chan seek $f1 0 end
+ set c [chan tell $f1]
+ chan close $f1
+ set c
+} 54
+test chan-io-34.4 {Tcl_Seek to offset from end of file} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ chan configure $f1 -translation lf -eofchar {}
+ chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
+ chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
+ chan close $f1
+ set f1 [open $path(test1) r]
+ chan seek $f1 -10 end
+ set c [chan tell $f1]
+ chan close $f1
+ set c
+} 44
+test chan-io-34.5 {Tcl_Seek to offset from current position} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ chan configure $f1 -translation lf -eofchar {}
+ chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
+ chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
+ chan close $f1
+ set f1 [open $path(test1) r]
+ chan seek $f1 10 current
+ chan seek $f1 10 current
+ set c [chan tell $f1]
+ chan close $f1
+ set c
+} 20
+test chan-io-34.6 {Tcl_Seek to offset from end of file} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ chan configure $f1 -translation lf -eofchar {}
+ chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
+ chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
+ chan close $f1
+ set f1 [open $path(test1) r]
+ chan seek $f1 -10 end
+ set c [chan tell $f1]
+ set r [chan read $f1]
+ chan close $f1
+ list $c $r
+} {44 {rstuvwxyz
+}}
+test chan-io-34.7 {Tcl_Seek to offset from end of file, then to current position} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ chan configure $f1 -translation lf -eofchar {}
+ chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
+ chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
+ chan close $f1
+ set f1 [open $path(test1) r]
+ chan seek $f1 -10 end
+ set c1 [chan tell $f1]
+ set r1 [chan read $f1 5]
+ chan seek $f1 0 current
+ set c2 [chan tell $f1]
+ chan close $f1
+ list $c1 $r1 $c2
+} {44 rstuv 49}
+test chan-io-34.8 {Tcl_Seek on pipes: not supported} {stdio openpipe} {
+ set f1 [open "|[list [interpreter]]" r+]
+ set x [list [catch {chan seek $f1 0 current} msg] $msg]
+ chan close $f1
+ regsub {".*":} $x {"":} x
+ string tolower $x
+} {1 {error during seek on "": invalid argument}}
+test chan-io-34.9 {Tcl_Seek, testing buffered input flushing} {
+ file delete $path(test3)
+ set f [open $path(test3) w]
+ chan configure $f -eofchar {}
+ chan puts -nonewline $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ chan close $f
+ set f [open $path(test3) RDWR]
+ set x [chan read $f 1]
+ chan seek $f 3
+ lappend x [chan read $f 1]
+ chan seek $f 0 start
+ lappend x [chan read $f 1]
+ chan seek $f 10 current
+ lappend x [chan read $f 1]
+ chan seek $f -2 end
+ lappend x [chan read $f 1]
+ chan seek $f 50 end
+ lappend x [chan read $f 1]
+ chan seek $f 1
+ lappend x [chan read $f 1]
+ chan close $f
+ set x
+} {a d a l Y {} b}
+set path(test3) [makeFile {} test3]
+test chan-io-34.10 {Tcl_Seek testing flushing of buffered input} {
+ set f [open $path(test3) w]
+ chan configure $f -translation lf
+ chan puts $f xyz\n123
+ chan close $f
+ set f [open $path(test3) r+]
+ chan configure $f -translation lf
+ set x [chan gets $f]
+ chan seek $f 0 current
+ chan puts $f 456
+ chan close $f
+ list $x [viewFile test3]
+} "xyz {xyz
+456}"
+test chan-io-34.11 {Tcl_Seek testing flushing of buffered output} {
+ set f [open $path(test3) w]
+ chan puts $f xyz\n123
+ chan close $f
+ set f [open $path(test3) w+]
+ chan puts $f xyzzy
+ chan seek $f 2
+ set x [chan gets $f]
+ chan close $f
+ list $x [viewFile test3]
+} "zzy xyzzy"
+test chan-io-34.12 {Tcl_Seek testing combination of write, seek back and read} {
+ set f [open $path(test3) w]
+ chan configure $f -translation lf -eofchar {}
+ chan puts $f xyz\n123
+ chan close $f
+ set f [open $path(test3) a+]
+ chan configure $f -translation lf -eofchar {}
+ chan puts $f xyzzy
+ chan flush $f
+ set x [chan tell $f]
+ chan seek $f -4 cur
+ set y [chan gets $f]
+ chan close $f
+ list $x [viewFile test3] $y
+} {14 {xyz
+123
+xyzzy} zzy}
+test chan-io-34.13 {Tcl_Tell at start of file} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ set p [chan tell $f1]
+ chan close $f1
+ set p
+} 0
+test chan-io-34.14 {Tcl_Tell after seek to end of file} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ chan configure $f1 -translation lf -eofchar {}
+ chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
+ chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
+ chan close $f1
+ set f1 [open $path(test1) r]
+ chan seek $f1 0 end
+ set c1 [chan tell $f1]
+ chan close $f1
+ set c1
+} 54
+test chan-io-34.15 {Tcl_Tell combined with seeking} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ chan configure $f1 -translation lf -eofchar {}
+ chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
+ chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
+ chan close $f1
+ set f1 [open $path(test1) r]
+ chan seek $f1 10 start
+ set c1 [chan tell $f1]
+ chan seek $f1 10 current
+ set c2 [chan tell $f1]
+ chan close $f1
+ list $c1 $c2
+} {10 20}
+test chan-io-34.16 {Tcl_Tell on pipe: always -1} {stdio openpipe} {
+ set f1 [open "|[list [interpreter]]" r+]
+ set c [chan tell $f1]
+ chan close $f1
+ set c
+} -1
+test chan-io-34.17 {Tcl_Tell on pipe: always -1} {stdio openpipe} {
+ set f1 [open "|[list [interpreter]]" r+]
+ chan puts $f1 {chan puts hello}
+ chan flush $f1
+ set c [chan tell $f1]
+ chan gets $f1
+ chan close $f1
+ set c
+} -1
+test chan-io-34.18 {Tcl_Tell combined with seeking and reading} {
+ file delete $path(test2)
+ set f [open $path(test2) w]
+ chan configure $f -translation lf -eofchar {}
+ chan puts -nonewline $f "line1\nline2\nline3\nline4\nline5\n"
+ chan close $f
+ set f [open $path(test2)]
+ chan configure $f -translation lf
+ set x [chan tell $f]
+ chan read $f 3
+ lappend x [chan tell $f]
+ chan seek $f 2
+ lappend x [chan tell $f]
+ chan seek $f 10 current
+ lappend x [chan tell $f]
+ chan seek $f 0 end
+ lappend x [chan tell $f]
+ chan close $f
+ set x
+} {0 3 2 12 30}
+test chan-io-34.19 {Tcl_Tell combined with opening in append mode} {
+ set f [open $path(test3) w]
+ chan configure $f -translation lf -eofchar {}
+ chan puts $f "abcdefghijklmnopqrstuvwxyz"
+ chan puts $f "abcdefghijklmnopqrstuvwxyz"
+ chan close $f
+ set f [open $path(test3) a]
+ set c [chan tell $f]
+ chan close $f
+ set c
+} 54
+test chan-io-34.20 {Tcl_Tell combined with writing} {
+ set f [open $path(test3) w]
+ set l ""
+ chan seek $f 29 start
+ lappend l [chan tell $f]
+ chan puts -nonewline $f a
+ chan seek $f 39 start
+ lappend l [chan tell $f]
+ chan puts -nonewline $f a
+ lappend l [chan tell $f]
+ chan seek $f 407 end
+ lappend l [chan tell $f]
+ chan close $f
+ set l
+} {29 39 40 447}
+test chan-io-34.21 {Tcl_Seek and Tcl_Tell on large files} {largefileSupport} {
+ file delete $path(test3)
+ set f [open $path(test3) w]
+ chan configure $f -encoding binary
+ set l ""
+ lappend l [chan tell $f]
+ chan puts -nonewline $f abcdef
+ lappend l [chan tell $f]
+ chan flush $f
+ lappend l [chan tell $f]
+ # 4GB offset!
+ chan seek $f 0x100000000
+ lappend l [chan tell $f]
+ chan puts -nonewline $f abcdef
+ lappend l [chan tell $f]
+ chan close $f
+ lappend l [file size $f]
+ # truncate...
+ chan close [open $path(test3) w]
+ lappend l [file size $f]
+ set l
+} {0 6 6 4294967296 4294967302 4294967302 0}
+
+# Test Tcl_Eof
+
+test chan-io-35.1 {Tcl_Eof} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan puts $f hello
+ chan puts $f hello
+ chan close $f
+ set f [open $path(test1)]
+ set x [chan eof $f]
+ lappend x [chan eof $f]
+ chan gets $f
+ lappend x [chan eof $f]
+ chan gets $f
+ lappend x [chan eof $f]
+ chan gets $f
+ lappend x [chan eof $f]
+ lappend x [chan eof $f]
+ chan close $f
+ set x
+} {0 0 0 0 1 1}
+test chan-io-35.2 {Tcl_Eof with pipe} {stdio openpipe} {
+ file delete $path(pipe)
+ set f1 [open $path(pipe) w]
+ chan puts $f1 {chan gets stdin}
+ chan puts $f1 {chan puts hello}
+ chan close $f1
+ set f1 [open "|[list [interpreter] $path(pipe)]" r+]
+ chan puts $f1 hello
+ set x [chan eof $f1]
+ chan flush $f1
+ lappend x [chan eof $f1]
+ chan gets $f1
+ lappend x [chan eof $f1]
+ chan gets $f1
+ lappend x [chan eof $f1]
+ chan close $f1
+ set x
+} {0 0 0 1}
+test chan-io-35.3 {Tcl_Eof with pipe} {stdio openpipe} {
+ file delete $path(pipe)
+ set f1 [open $path(pipe) w]
+ chan puts $f1 {chan gets stdin}
+ chan puts $f1 {chan puts hello}
+ chan close $f1
+ set f1 [open "|[list [interpreter] $path(pipe)]" r+]
+ chan puts $f1 hello
+ set x [chan eof $f1]
+ chan flush $f1
+ lappend x [chan eof $f1]
+ chan gets $f1
+ lappend x [chan eof $f1]
+ chan gets $f1
+ lappend x [chan eof $f1]
+ chan gets $f1
+ lappend x [chan eof $f1]
+ chan gets $f1
+ lappend x [chan eof $f1]
+ chan close $f1
+ set x
+} {0 0 0 1 1 1}
+test chan-io-35.4 {Tcl_Eof, eof detection on nonblocking file} {nonBlockFiles} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -blocking off
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {{} 1}
+test chan-io-35.5 {Tcl_Eof, eof detection on nonblocking pipe} {stdio openpipe} {
+ file delete $path(pipe)
+ set f [open $path(pipe) w]
+ chan puts $f {
+ exit
+ }
+ chan close $f
+ set f [open "|[list [interpreter] $path(pipe)]" r]
+ set l ""
+ lappend l [chan gets $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {{} 1}
+test chan-io-35.6 {Tcl_Eof, eof char, lf write, auto read} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf -eofchar \x1a
+ chan puts $f abc\ndef
+ chan close $f
+ set s [file size $path(test1)]
+ set f [open $path(test1) r]
+ chan configure $f -translation auto -eofchar \x1a
+ set l [string length [chan read $f]]
+ set e [chan eof $f]
+ chan close $f
+ list $s $l $e
+} {9 8 1}
+test chan-io-35.7 {Tcl_Eof, eof char, lf write, lf read} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf -eofchar \x1a
+ chan puts $f abc\ndef
+ chan close $f
+ set s [file size $path(test1)]
+ set f [open $path(test1) r]
+ chan configure $f -translation lf -eofchar \x1a
+ set l [string length [chan read $f]]
+ set e [chan eof $f]
+ chan close $f
+ list $s $l $e
+} {9 8 1}
+test chan-io-35.8 {Tcl_Eof, eof char, cr write, auto read} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr -eofchar \x1a
+ chan puts $f abc\ndef
+ chan close $f
+ set s [file size $path(test1)]
+ set f [open $path(test1) r]
+ chan configure $f -translation auto -eofchar \x1a
+ set l [string length [chan read $f]]
+ set e [chan eof $f]
+ chan close $f
+ list $s $l $e
+} {9 8 1}
+test chan-io-35.9 {Tcl_Eof, eof char, cr write, cr read} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr -eofchar \x1a
+ chan puts $f abc\ndef
+ chan close $f
+ set s [file size $path(test1)]
+ set f [open $path(test1) r]
+ chan configure $f -translation cr -eofchar \x1a
+ set l [string length [chan read $f]]
+ set e [chan eof $f]
+ chan close $f
+ list $s $l $e
+} {9 8 1}
+test chan-io-35.10 {Tcl_Eof, eof char, crlf write, auto read} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf -eofchar \x1a
+ chan puts $f abc\ndef
+ chan close $f
+ set s [file size $path(test1)]
+ set f [open $path(test1) r]
+ chan configure $f -translation auto -eofchar \x1a
+ set l [string length [chan read $f]]
+ set e [chan eof $f]
+ chan close $f
+ list $s $l $e
+} {11 8 1}
+test chan-io-35.11 {Tcl_Eof, eof char, crlf write, crlf read} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf -eofchar \x1a
+ chan puts $f abc\ndef
+ chan close $f
+ set s [file size $path(test1)]
+ set f [open $path(test1) r]
+ chan configure $f -translation crlf -eofchar \x1a
+ set l [string length [chan read $f]]
+ set e [chan eof $f]
+ chan close $f
+ list $s $l $e
+} {11 8 1}
+test chan-io-35.12 {Tcl_Eof, eof char in middle, lf write, auto read} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf -eofchar {}
+ set i [format abc\ndef\n%cqrs\nuvw 26]
+ chan puts $f $i
+ chan close $f
+ set c [file size $path(test1)]
+ set f [open $path(test1) r]
+ chan configure $f -translation auto -eofchar \x1a
+ set l [string length [chan read $f]]
+ set e [chan eof $f]
+ chan close $f
+ list $c $l $e
+} {17 8 1}
+test chan-io-35.13 {Tcl_Eof, eof char in middle, lf write, lf read} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf -eofchar {}
+ set i [format abc\ndef\n%cqrs\nuvw 26]
+ chan puts $f $i
+ chan close $f
+ set c [file size $path(test1)]
+ set f [open $path(test1) r]
+ chan configure $f -translation lf -eofchar \x1a
+ set l [string length [chan read $f]]
+ set e [chan eof $f]
+ chan close $f
+ list $c $l $e
+} {17 8 1}
+test chan-io-35.14 {Tcl_Eof, eof char in middle, cr write, auto read} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr -eofchar {}
+ set i [format abc\ndef\n%cqrs\nuvw 26]
+ chan puts $f $i
+ chan close $f
+ set c [file size $path(test1)]
+ set f [open $path(test1) r]
+ chan configure $f -translation auto -eofchar \x1a
+ set l [string length [chan read $f]]
+ set e [chan eof $f]
+ chan close $f
+ list $c $l $e
+} {17 8 1}
+test chan-io-35.15 {Tcl_Eof, eof char in middle, cr write, cr read} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr -eofchar {}
+ set i [format abc\ndef\n%cqrs\nuvw 26]
+ chan puts $f $i
+ chan close $f
+ set c [file size $path(test1)]
+ set f [open $path(test1) r]
+ chan configure $f -translation cr -eofchar \x1a
+ set l [string length [chan read $f]]
+ set e [chan eof $f]
+ chan close $f
+ list $c $l $e
+} {17 8 1}
+test chan-io-35.16 {Tcl_Eof, eof char in middle, crlf write, auto read} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf -eofchar {}
+ set i [format abc\ndef\n%cqrs\nuvw 26]
+ chan puts $f $i
+ chan close $f
+ set c [file size $path(test1)]
+ set f [open $path(test1) r]
+ chan configure $f -translation auto -eofchar \x1a
+ set l [string length [chan read $f]]
+ set e [chan eof $f]
+ chan close $f
+ list $c $l $e
+} {21 8 1}
+test chan-io-35.17 {Tcl_Eof, eof char in middle, crlf write, crlf read} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf -eofchar {}
+ set i [format abc\ndef\n%cqrs\nuvw 26]
+ chan puts $f $i
+ chan close $f
+ set c [file size $path(test1)]
+ set f [open $path(test1) r]
+ chan configure $f -translation crlf -eofchar \x1a
+ set l [string length [chan read $f]]
+ set e [chan eof $f]
+ chan close $f
+ list $c $l $e
+} {21 8 1}
+
+# Test Tcl_InputBlocked
+
+test chan-io-36.1 {Tcl_InputBlocked on nonblocking pipe} {stdio openpipe} {
+ set f1 [open "|[list [interpreter]]" r+]
+ chan puts $f1 {chan puts hello_from_pipe}
+ chan flush $f1
+ chan gets $f1
+ chan configure $f1 -blocking off -buffering full
+ chan puts $f1 {chan puts hello}
+ set x ""
+ lappend x [chan gets $f1]
+ lappend x [chan blocked $f1]
+ chan flush $f1
+ after 200
+ lappend x [chan gets $f1]
+ lappend x [chan blocked $f1]
+ lappend x [chan gets $f1]
+ lappend x [chan blocked $f1]
+ chan close $f1
+ set x
+} {{} 1 hello 0 {} 1}
+test chan-io-36.2 {Tcl_InputBlocked on blocking pipe} {stdio openpipe} {
+ set f1 [open "|[list [interpreter]]" r+]
+ chan configure $f1 -buffering line
+ chan puts $f1 {chan puts hello_from_pipe}
+ set x ""
+ lappend x [chan gets $f1]
+ lappend x [chan blocked $f1]
+ chan puts $f1 {exit}
+ lappend x [chan gets $f1]
+ lappend x [chan blocked $f1]
+ lappend x [chan eof $f1]
+ chan close $f1
+ set x
+} {hello_from_pipe 0 {} 0 1}
+test chan-io-36.3 {Tcl_InputBlocked vs files, short read} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan puts $f abcdefghijklmnop
+ chan close $f
+ set f [open $path(test1) r]
+ set l ""
+ lappend l [chan blocked $f]
+ lappend l [chan read $f 3]
+ lappend l [chan blocked $f]
+ lappend l [chan read -nonewline $f]
+ lappend l [chan blocked $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {0 abc 0 defghijklmnop 0 1}
+test chan-io-36.4 {Tcl_InputBlocked vs files, event driven read} {fileevent} {
+ proc in {f} {
+ variable l
+ variable x
+ lappend l [chan read $f 3]
+ if {[chan eof $f]} {lappend l eof; chan close $f; set x done}
+ }
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan puts $f abcdefghijklmnop
+ chan close $f
+ set f [open $path(test1) r]
+ set l ""
+ chan event $f readable [namespace code [list in $f]]
+ variable x
+ vwait [namespace which -variable x]
+ set l
+} {abc def ghi jkl mno {p
+} eof}
+test chan-io-36.5 {Tcl_InputBlocked vs files, short read, nonblocking} {nonBlockFiles} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan puts $f abcdefghijklmnop
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -blocking off
+ set l ""
+ lappend l [chan blocked $f]
+ lappend l [chan read $f 3]
+ lappend l [chan blocked $f]
+ lappend l [chan read -nonewline $f]
+ lappend l [chan blocked $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} {0 abc 0 defghijklmnop 0 1}
+test chan-io-36.6 {Tcl_InputBlocked vs files, event driven read} {nonBlockFiles fileevent} {
+ proc in {f} {
+ variable l
+ variable x
+ lappend l [chan read $f 3]
+ if {[chan eof $f]} {lappend l eof; chan close $f; set x done}
+ }
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan puts $f abcdefghijklmnop
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -blocking off
+ set l ""
+ chan event $f readable [namespace code [list in $f]]
+ variable x
+ vwait [namespace which -variable x]
+ set l
+} {abc def ghi jkl mno {p
+} eof}
+
+# Test Tcl_InputBuffered
+
+test chan-io-37.1 {Tcl_InputBuffered} {testchannel} {
+ set f [open $path(longfile) r]
+ chan configure $f -buffersize 4096
+ chan read $f 3
+ set l ""
+ lappend l [testchannel inputbuffered $f]
+ lappend l [chan tell $f]
+ chan close $f
+ set l
+} {4093 3}
+test chan-io-37.2 {Tcl_InputBuffered, test input flushing on seek} {testchannel} {
+ set f [open $path(longfile) r]
+ chan configure $f -buffersize 4096
+ chan read $f 3
+ set l ""
+ lappend l [testchannel inputbuffered $f]
+ lappend l [chan tell $f]
+ chan seek $f 0 current
+ lappend l [testchannel inputbuffered $f]
+ lappend l [chan tell $f]
+ chan close $f
+ set l
+} {4093 3 0 3}
+
+# Test Tcl_SetChannelBufferSize, Tcl_GetChannelBufferSize
+
+test chan-io-38.1 {Tcl_GetChannelBufferSize, default buffer size} {
+ set f [open $path(longfile) r]
+ set s [chan configure $f -buffersize]
+ chan close $f
+ set s
+} 4096
+test chan-io-38.2 {Tcl_SetChannelBufferSize, Tcl_GetChannelBufferSize} {
+ set f [open $path(longfile) r]
+ set l ""
+ lappend l [chan configure $f -buffersize]
+ chan configure $f -buffersize 10000
+ lappend l [chan configure $f -buffersize]
+ chan configure $f -buffersize 1
+ lappend l [chan configure $f -buffersize]
+ chan configure $f -buffersize -1
+ lappend l [chan configure $f -buffersize]
+ chan configure $f -buffersize 0
+ lappend l [chan configure $f -buffersize]
+ chan configure $f -buffersize 100000
+ lappend l [chan configure $f -buffersize]
+ chan configure $f -buffersize 10000000
+ lappend l [chan configure $f -buffersize]
+ chan close $f
+ set l
+} {4096 10000 1 1 1 100000 1048576}
+test chan-io-38.3 {Tcl_SetChannelBufferSize, changing buffersize between reads} {
+ # This test crashes the interp if Bug #427196 is not fixed
+
+ set chan [open [info script] r]
+ chan configure $chan -buffersize 10
+ set var [chan read $chan 2]
+ chan configure $chan -buffersize 32
+ append var [chan read $chan]
+ chan close $chan
+} {}
+
+# Test Tcl_SetChannelOption, Tcl_GetChannelOption
+
+test chan-io-39.1 {Tcl_GetChannelOption} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ set x [chan configure $f1 -blocking]
+ chan close $f1
+ set x
+} 1
+#
+# Test 17.2 was removed.
+#
+test chan-io-39.2 {Tcl_GetChannelOption} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ set x [chan configure $f1 -buffering]
+ chan close $f1
+ set x
+} full
+test chan-io-39.3 {Tcl_GetChannelOption} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ chan configure $f1 -buffering line
+ set x [chan configure $f1 -buffering]
+ chan close $f1
+ set x
+} line
+test chan-io-39.4 {Tcl_GetChannelOption, Tcl_SetChannelOption} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ set l ""
+ lappend l [chan configure $f1 -buffering]
+ chan configure $f1 -buffering line
+ lappend l [chan configure $f1 -buffering]
+ chan configure $f1 -buffering none
+ lappend l [chan configure $f1 -buffering]
+ chan configure $f1 -buffering line
+ lappend l [chan configure $f1 -buffering]
+ chan configure $f1 -buffering full
+ lappend l [chan configure $f1 -buffering]
+ chan close $f1
+ set l
+} {full line none line full}
+test chan-io-39.5 {Tcl_GetChannelOption, invariance} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ set l ""
+ lappend l [chan configure $f1 -buffering]
+ lappend l [list [catch {chan configure $f1 -buffering green} msg] $msg]
+ lappend l [chan configure $f1 -buffering]
+ chan close $f1
+ set l
+} {full {1 {bad value for -buffering: must be one of full, line, or none}} full}
+test chan-io-39.6 {Tcl_SetChannelOption, multiple options} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ chan configure $f1 -translation lf -buffering line
+ chan puts $f1 hello
+ chan puts $f1 bye
+ set x [file size $path(test1)]
+ chan close $f1
+ set x
+} 10
+test chan-io-39.7 {Tcl_SetChannelOption, buffering, translation} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ chan configure $f1 -translation lf
+ chan puts $f1 hello
+ chan puts $f1 bye
+ set x ""
+ chan configure $f1 -buffering line
+ lappend x [file size $path(test1)]
+ chan puts $f1 really_bye
+ lappend x [file size $path(test1)]
+ chan close $f1
+ set x
+} {0 21}
+test chan-io-39.8 {Tcl_SetChannelOption, different buffering options} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ set l ""
+ chan configure $f1 -translation lf -buffering none -eofchar {}
+ chan puts -nonewline $f1 hello
+ lappend l [file size $path(test1)]
+ chan puts -nonewline $f1 hello
+ lappend l [file size $path(test1)]
+ chan configure $f1 -buffering full
+ chan puts -nonewline $f1 hello
+ lappend l [file size $path(test1)]
+ chan configure $f1 -buffering none
+ lappend l [file size $path(test1)]
+ chan puts -nonewline $f1 hello
+ lappend l [file size $path(test1)]
+ chan close $f1
+ lappend l [file size $path(test1)]
+ set l
+} {5 10 10 10 20 20}
+test chan-io-39.9 {Tcl_SetChannelOption, blocking mode} {nonBlockFiles} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w]
+ chan close $f1
+ set f1 [open $path(test1) r]
+ set x ""
+ lappend x [chan configure $f1 -blocking]
+ chan configure $f1 -blocking off
+ lappend x [chan configure $f1 -blocking]
+ lappend x [chan gets $f1]
+ lappend x [chan read $f1 1000]
+ lappend x [chan blocked $f1]
+ lappend x [chan eof $f1]
+ chan close $f1
+ set x
+} {1 0 {} {} 0 1}
+test chan-io-39.10 {Tcl_SetChannelOption, blocking mode} {stdio openpipe} {
+ file delete $path(pipe)
+ set f1 [open $path(pipe) w]
+ chan puts $f1 {
+ chan gets stdin
+ after 100
+ chan puts hi
+ chan gets stdin
+ }
+ chan close $f1
+ set x ""
+ set f1 [open "|[list [interpreter] $path(pipe)]" r+]
+ chan configure $f1 -blocking off -buffering line
+ lappend x [chan configure $f1 -blocking]
+ lappend x [chan gets $f1]
+ lappend x [chan blocked $f1]
+ chan configure $f1 -blocking on
+ chan puts $f1 hello
+ chan configure $f1 -blocking off
+ lappend x [chan gets $f1]
+ lappend x [chan blocked $f1]
+ chan configure $f1 -blocking on
+ chan puts $f1 bye
+ chan configure $f1 -blocking off
+ lappend x [chan gets $f1]
+ lappend x [chan blocked $f1]
+ chan configure $f1 -blocking on
+ lappend x [chan configure $f1 -blocking]
+ lappend x [chan gets $f1]
+ lappend x [chan blocked $f1]
+ lappend x [chan eof $f1]
+ lappend x [chan gets $f1]
+ lappend x [chan eof $f1]
+ chan close $f1
+ set x
+} {0 {} 1 {} 1 {} 1 1 hi 0 0 {} 1}
+test chan-io-39.11 {Tcl_SetChannelOption, Tcl_GetChannelOption, buffer size clipped to lower bound} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -buffersize -10
+ set x [chan configure $f -buffersize]
+ chan close $f
+ set x
+} 1
+test chan-io-39.12 {Tcl_SetChannelOption, Tcl_GetChannelOption buffer size clipped to upper bound} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -buffersize 10000000
+ set x [chan configure $f -buffersize]
+ chan close $f
+ set x
+} 1048576
+test chan-io-39.13 {Tcl_SetChannelOption, Tcl_GetChannelOption, buffer size} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -buffersize 40000
+ set x [chan configure $f -buffersize]
+ chan close $f
+ set x
+} 40000
+test chan-io-39.14 {Tcl_SetChannelOption: -encoding, binary & utf-8} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -encoding {}
+ chan puts -nonewline $f \xe7\x89\xa6
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -encoding utf-8
+ set x [chan read $f]
+ chan close $f
+ set x
+} \u7266
+test chan-io-39.15 {Tcl_SetChannelOption: -encoding, binary & utf-8} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -encoding binary
+ chan puts -nonewline $f \xe7\x89\xa6
+ chan close $f
+ set f [open $path(test1) r]
+ chan configure $f -encoding utf-8
+ set x [chan read $f]
+ chan close $f
+ set x
+} \u7266
+test chan-io-39.16 {Tcl_SetChannelOption: -encoding, errors} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ set result [list [catch {chan configure $f -encoding foobar} msg] $msg]
+ chan close $f
+ set result
+} {1 {unknown encoding "foobar"}}
+test chan-io-39.17 {Tcl_SetChannelOption: -encoding, clearing CHANNEL_NEED_MORE_DATA} {stdio openpipe fileevent} {
+ set f [open "|[list [interpreter] $path(cat)]" r+]
+ chan configure $f -encoding binary
+ chan puts -nonewline $f "\xe7"
+ chan flush $f
+ chan configure $f -encoding utf-8 -blocking 0
+ variable x {}
+ chan event $f readable [namespace code { lappend x [chan read $f] }]
+ vwait [namespace which -variable x]
+ after 300 [namespace code { lappend x timeout }]
+ vwait [namespace which -variable x]
+ chan configure $f -encoding utf-8
+ vwait [namespace which -variable x]
+ after 300 [namespace code { lappend x timeout }]
+ vwait [namespace which -variable x]
+ chan configure $f -encoding binary
+ vwait [namespace which -variable x]
+ after 300 [namespace code { lappend x timeout }]
+ vwait [namespace which -variable x]
+ chan close $f
+ set x
+} "{} timeout {} timeout \xe7 timeout"
+test chan-io-39.18 {Tcl_SetChannelOption, setting read mode independently} \
+ {socket} {
+ proc accept {s a p} {chan close $s}
+ set s1 [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
+ set port [lindex [chan configure $s1 -sockname] 2]
+ set s2 [socket 127.0.0.1 $port]
+ update
+ chan configure $s2 -translation {auto lf}
+ set modes [chan configure $s2 -translation]
+ chan close $s1
+ chan close $s2
+ set modes
+} {auto lf}
+test chan-io-39.19 {Tcl_SetChannelOption, setting read mode independently} \
+ {socket} {
+ proc accept {s a p} {chan close $s}
+ set s1 [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
+ set port [lindex [chan configure $s1 -sockname] 2]
+ set s2 [socket 127.0.0.1 $port]
+ update
+ chan configure $s2 -translation {auto crlf}
+ set modes [chan configure $s2 -translation]
+ chan close $s1
+ chan close $s2
+ set modes
+} {auto crlf}
+test chan-io-39.20 {Tcl_SetChannelOption, setting read mode independently} \
+ {socket} {
+ proc accept {s a p} {chan close $s}
+ set s1 [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
+ set port [lindex [chan configure $s1 -sockname] 2]
+ set s2 [socket 127.0.0.1 $port]
+ update
+ chan configure $s2 -translation {auto cr}
+ set modes [chan configure $s2 -translation]
+ chan close $s1
+ chan close $s2
+ set modes
+} {auto cr}
+test chan-io-39.21 {Tcl_SetChannelOption, setting read mode independently} \
+ {socket} {
+ proc accept {s a p} {chan close $s}
+ set s1 [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
+ set port [lindex [chan configure $s1 -sockname] 2]
+ set s2 [socket 127.0.0.1 $port]
+ update
+ chan configure $s2 -translation {auto auto}
+ set modes [chan configure $s2 -translation]
+ chan close $s1
+ chan close $s2
+ set modes
+} {auto crlf}
+test chan-io-39.22 {Tcl_SetChannelOption, invariance} {unix} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w+]
+ set l ""
+ lappend l [chan configure $f1 -eofchar]
+ chan configure $f1 -eofchar {ON GO}
+ lappend l [chan configure $f1 -eofchar]
+ chan configure $f1 -eofchar D
+ lappend l [chan configure $f1 -eofchar]
+ chan close $f1
+ set l
+} {{{} {}} {O G} {D D}}
+test chan-io-39.22a {Tcl_SetChannelOption, invariance} {
+ file delete $path(test1)
+ set f1 [open $path(test1) w+]
+ set l [list]
+ chan configure $f1 -eofchar {ON GO}
+ lappend l [chan configure $f1 -eofchar]
+ chan configure $f1 -eofchar D
+ lappend l [chan configure $f1 -eofchar]
+ lappend l [list [catch {chan configure $f1 -eofchar {1 2 3}} msg] $msg]
+ chan close $f1
+ set l
+} {{O G} {D D} {1 {bad value for -eofchar: should be a list of zero, one, or two elements}}}
+test chan-io-39.23 {Tcl_GetChannelOption, server socket is not readable or
+ writeable, it should still have valid -eofchar and -translation options } {
+ set l [list]
+ set sock [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
+ lappend l [chan configure $sock -eofchar] [chan configure $sock -translation]
+ chan close $sock
+ set l
+} {{{}} auto}
+test chan-io-39.24 {Tcl_SetChannelOption, server socket is not readable or
+ writable so we can't change -eofchar or -translation } {
+ set l [list]
+ set sock [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
+ chan configure $sock -eofchar D -translation lf
+ lappend l [chan configure $sock -eofchar] [chan configure $sock -translation]
+ chan close $sock
+ set l
+} {{{}} auto}
+
+test chan-io-40.1 {POSIX open access modes: RDWR} {
+ file delete $path(test3)
+ set f [open $path(test3) w]
+ chan puts $f xyzzy
+ chan close $f
+ set f [open $path(test3) RDWR]
+ chan puts -nonewline $f "ab"
+ chan seek $f 0 current
+ set x [chan gets $f]
+ chan close $f
+ set f [open $path(test3) r]
+ lappend x [chan gets $f]
+ chan close $f
+ set x
+} {zzy abzzy}
+test chan-io-40.2 {POSIX open access modes: CREAT} {unix} {
+ file delete $path(test3)
+ set f [open $path(test3) {WRONLY CREAT} 0600]
+ file stat $path(test3) stats
+ set x [format "0%o" [expr $stats(mode)&0o777]]
+ chan puts $f "line 1"
+ chan close $f
+ set f [open $path(test3) r]
+ lappend x [chan gets $f]
+ chan close $f
+ set x
+} {0600 {line 1}}
+test chan-io-40.3 {POSIX open access modes: CREAT} {unix umask} {
+ # This test only works if your umask is 2, like ouster's.
+ file delete $path(test3)
+ set f [open $path(test3) {WRONLY CREAT}]
+ chan close $f
+ file stat $path(test3) stats
+ format "0%o" [expr $stats(mode)&0o777]
+} [format %04o [expr {0o666 & ~ $umaskValue}]]
+test chan-io-40.4 {POSIX open access modes: CREAT} {
+ file delete $path(test3)
+ set f [open $path(test3) w]
+ chan configure $f -eofchar {}
+ chan puts $f xyzzy
+ chan close $f
+ set f [open $path(test3) {WRONLY CREAT}]
+ chan configure $f -eofchar {}
+ chan puts -nonewline $f "ab"
+ chan close $f
+ set f [open $path(test3) r]
+ set x [chan gets $f]
+ chan close $f
+ set x
+} abzzy
+test chan-io-40.5 {POSIX open access modes: APPEND} {
+ file delete $path(test3)
+ set f [open $path(test3) w]
+ chan configure $f -translation lf -eofchar {}
+ chan puts $f xyzzy
+ chan close $f
+ set f [open $path(test3) {WRONLY APPEND}]
+ chan configure $f -translation lf
+ chan puts $f "new line"
+ chan seek $f 0
+ chan puts $f "abc"
+ chan close $f
+ set f [open $path(test3) r]
+ chan configure $f -translation lf
+ set x ""
+ chan seek $f 6 current
+ lappend x [chan gets $f]
+ lappend x [chan gets $f]
+ chan close $f
+ set x
+} {{new line} abc}
+test chan-io-40.6 {POSIX open access modes: EXCL} -match regexp -body {
+ file delete $path(test3)
+ set f [open $path(test3) w]
+ chan puts $f xyzzy
+ chan close $f
+ open $path(test3) {WRONLY CREAT EXCL}
+} -returnCodes error -result {(?i)couldn't open ".*test3": file (already )?exists}
+test chan-io-40.7 {POSIX open access modes: EXCL} {
+ file delete $path(test3)
+ set f [open $path(test3) {WRONLY CREAT EXCL}]
+ chan configure $f -eofchar {}
+ chan puts $f "A test line"
+ chan close $f
+ viewFile test3
+} {A test line}
+test chan-io-40.8 {POSIX open access modes: TRUNC} {
+ file delete $path(test3)
+ set f [open $path(test3) w]
+ chan puts $f xyzzy
+ chan close $f
+ set f [open $path(test3) {WRONLY TRUNC}]
+ chan puts $f abc
+ chan close $f
+ set f [open $path(test3) r]
+ set x [chan gets $f]
+ chan close $f
+ set x
+} abc
+test chan-io-40.9 {POSIX open access modes: NONBLOCK} {nonPortable unix} {
+ file delete $path(test3)
+ set f [open $path(test3) {WRONLY NONBLOCK CREAT}]
+ chan puts $f "NONBLOCK test"
+ chan close $f
+ set f [open $path(test3) r]
+ set x [chan gets $f]
+ chan close $f
+ set x
+} {NONBLOCK test}
+test chan-io-40.10 {POSIX open access modes: RDONLY} {
+ set f [open $path(test1) w]
+ chan puts $f "two lines: this one"
+ chan puts $f "and this"
+ chan close $f
+ set f [open $path(test1) RDONLY]
+ set x [list [chan gets $f] [catch {chan puts $f Test} msg] $msg]
+ chan close $f
+ string compare [string tolower $x] \
+ [list {two lines: this one} 1 \
+ [format "channel \"%s\" wasn't opened for writing" $f]]
+} 0
+test chan-io-40.11 {POSIX open access modes: RDONLY} -match regexp -body {
+ file delete $path(test3)
+ open $path(test3) RDONLY
+} -returnCodes error -result {(?i)couldn't open ".*test3": no such file or directory}
+test chan-io-40.12 {POSIX open access modes: WRONLY} -match regexp -body {
+ file delete $path(test3)
+ open $path(test3) WRONLY
+} -returnCodes error -result {(?i)couldn't open ".*test3": no such file or directory}
+test chan-io-40.13 {POSIX open access modes: WRONLY} {
+ makeFile xyzzy test3
+ set f [open $path(test3) WRONLY]
+ chan configure $f -eofchar {}
+ chan puts -nonewline $f "ab"
+ chan seek $f 0 current
+ set x [list [catch {chan gets $f} msg] $msg]
+ chan close $f
+ lappend x [viewFile test3]
+ string compare [string tolower $x] \
+ [list 1 "channel \"$f\" wasn't opened for reading" abzzy]
+} 0
+test chan-io-40.14 {POSIX open access modes: RDWR} -match regexp -body {
+ file delete $path(test3)
+ open $path(test3) RDWR
+} -returnCodes error -result {(?i)couldn't open ".*test3": no such file or directory}
+test chan-io-40.15 {POSIX open access modes: RDWR} {
+ makeFile xyzzy test3
+ set f [open $path(test3) RDWR]
+ chan puts -nonewline $f "ab"
+ chan seek $f 0 current
+ set x [chan gets $f]
+ chan close $f
+ lappend x [viewFile test3]
+} {zzy abzzy}
+test chan-io-40.16 {tilde substitution in open} -constraints makeFileInHome -setup {
+ makeFile {Some text} _test_ ~
+} -body {
+ file exists [file join $::env(HOME) _test_]
+} -cleanup {
+ removeFile _test_ ~
+} -result 1
+test chan-io-40.17 {tilde substitution in open} {
+ set home $::env(HOME)
+ unset ::env(HOME)
+ set x [list [catch {open ~/foo} msg] $msg]
+ set ::env(HOME) $home
+ set x
+} {1 {couldn't find HOME environment variable to expand path}}
+
+test chan-io-41.1 {Tcl_FileeventCmd: errors} {fileevent} {
+ list [catch {chan event foo} msg] $msg
+} {1 {wrong # args: should be "chan event channelId event ?script?"}}
+test chan-io-41.2 {Tcl_FileeventCmd: errors} {fileevent} {
+ list [catch {chan event foo bar baz q} msg] $msg
+} {1 {wrong # args: should be "chan event channelId event ?script?"}}
+test chan-io-41.3 {Tcl_FileeventCmd: errors} {fileevent} {
+ list [catch {chan event gorp readable} msg] $msg
+} {1 {can not find channel named "gorp"}}
+test chan-io-41.4 {Tcl_FileeventCmd: errors} {fileevent} {
+ list [catch {chan event gorp writable} msg] $msg
+} {1 {can not find channel named "gorp"}}
+test chan-io-41.5 {Tcl_FileeventCmd: errors} {fileevent} {
+ list [catch {chan event gorp who-knows} msg] $msg
+} {1 {bad event name "who-knows": must be readable or writable}}
+
+#
+# Test chan event on a file
+#
+
+set path(foo) [makeFile {} foo]
+set f [open $path(foo) w+]
+
+test chan-io-42.1 {Tcl_FileeventCmd: creating, deleting, querying} {fileevent} {
+ list [chan event $f readable] [chan event $f writable]
+} {{} {}}
+test chan-io-42.2 {Tcl_FileeventCmd: replacing} {fileevent} {
+ set result {}
+ chan event $f r "first script"
+ lappend result [chan event $f readable]
+ chan event $f r "new script"
+ lappend result [chan event $f readable]
+ chan event $f r "yet another"
+ lappend result [chan event $f readable]
+ chan event $f r ""
+ lappend result [chan event $f readable]
+} {{first script} {new script} {yet another} {}}
+test chan-io-42.3 {Tcl_FileeventCmd: replacing, with NULL chars in script} {fileevent} {
+ set result {}
+ chan event $f r "first scr\0ipt"
+ lappend result [string length [chan event $f readable]]
+ chan event $f r "new scr\0ipt"
+ lappend result [string length [chan event $f readable]]
+ chan event $f r "yet ano\0ther"
+ lappend result [string length [chan event $f readable]]
+ chan event $f r ""
+ lappend result [chan event $f readable]
+} {13 11 12 {}}
+
+
+test chan-io-43.1 {Tcl_FileeventCmd: creating, deleting, querying} {stdio unixExecs fileevent} {
+ set result {}
+ chan event $f readable "script 1"
+ lappend result [chan event $f readable] [chan event $f writable]
+ chan event $f writable "write script"
+ lappend result [chan event $f readable] [chan event $f writable]
+ chan event $f readable {}
+ lappend result [chan event $f readable] [chan event $f writable]
+ chan event $f writable {}
+ lappend result [chan event $f readable] [chan event $f writable]
+} {{script 1} {} {script 1} {write script} {} {write script} {} {}}
+test chan-io-43.2 {Tcl_FileeventCmd: deleting when many present} -setup {
+ set f2 [open "|[list cat -u]" r+]
+ set f3 [open "|[list cat -u]" r+]
+} -constraints {stdio unixExecs fileevent openpipe} -body {
+ set result {}
+ lappend result [chan event $f r] [chan event $f2 r] [chan event $f3 r]
+ chan event $f r "chan read f"
+ chan event $f2 r "chan read f2"
+ chan event $f3 r "chan read f3"
+ lappend result [chan event $f r] [chan event $f2 r] [chan event $f3 r]
+ chan event $f2 r {}
+ lappend result [chan event $f r] [chan event $f2 r] [chan event $f3 r]
+ chan event $f3 r {}
+ lappend result [chan event $f r] [chan event $f2 r] [chan event $f3 r]
+ chan event $f r {}
+ lappend result [chan event $f r] [chan event $f2 r] [chan event $f3 r]
+} -cleanup {
+ catch {chan close $f2}
+ catch {chan close $f3}
+} -result {{} {} {} {chan read f} {chan read f2} {chan read f3} {chan read f} {} {chan read f3} {chan read f} {} {} {} {} {}}
+
+test chan-io-44.1 {FileEventProc procedure: normal read event} -setup {
+ set f2 [open "|[list cat -u]" r+]
+ set f3 [open "|[list cat -u]" r+]
+} -constraints {stdio unixExecs fileevent openpipe} -body {
+ chan event $f2 readable [namespace code {
+ set x [chan gets $f2]; chan event $f2 readable {}
+ }]
+ chan puts $f2 text; chan flush $f2
+ variable x initial
+ vwait [namespace which -variable x]
+ set x
+} -cleanup {
+ catch {chan close $f2}
+ catch {chan close $f3}
+} -result {text}
+test chan-io-44.2 {FileEventProc procedure: error in read event} -constraints {
+ stdio unixExecs fileevent openpipe
+} -setup {
+ set f2 [open "|[list cat -u]" r+]
+ set f3 [open "|[list cat -u]" r+]
+ proc myHandler {msg options} {
+ variable x $msg
+ }
+ set handler [interp bgerror {}]
+ interp bgerror {} [namespace which myHandler]
+} -body {
+ chan event $f2 readable {error bogus}
+ chan puts $f2 text; chan flush $f2
+ variable x initial
+ vwait [namespace which -variable x]
+ list $x [chan event $f2 readable]
+} -cleanup {
+ interp bgerror {} $handler
+ catch {chan close $f2}
+ catch {chan close $f3}
+} -result {bogus {}}
+test chan-io-44.3 {FileEventProc procedure: normal write event} -setup {
+ set f2 [open "|[list cat -u]" r+]
+ set f3 [open "|[list cat -u]" r+]
+} -constraints {stdio unixExecs fileevent openpipe} -body {
+ chan event $f2 writable [namespace code {
+ lappend x "triggered"
+ incr count -1
+ if {$count <= 0} {
+ chan event $f2 writable {}
+ }
+ }]
+ variable x initial
+ set count 3
+ vwait [namespace which -variable x]
+ vwait [namespace which -variable x]
+ vwait [namespace which -variable x]
+ set x
+} -cleanup {
+ catch {chan close $f2}
+ catch {chan close $f3}
+} -result {initial triggered triggered triggered}
+test chan-io-44.4 {FileEventProc procedure: eror in write event} -constraints {
+ stdio unixExecs fileevent openpipe
+} -setup {
+ set f2 [open "|[list cat -u]" r+]
+ set f3 [open "|[list cat -u]" r+]
+ proc myHandler {msg options} {
+ variable x $msg
+ }
+ set handler [interp bgerror {}]
+ interp bgerror {} [namespace which myHandler]
+} -body {
+ chan event $f2 writable {error bad-write}
+ variable x initial
+ vwait [namespace which -variable x]
+ list $x [chan event $f2 writable]
+} -cleanup {
+ interp bgerror {} $handler
+ catch {chan close $f2}
+ catch {chan close $f3}
+} -result {bad-write {}}
+test chan-io-44.5 {FileEventProc procedure: end of file} {stdio unixExecs openpipe fileevent} {
+ set f4 [open "|[list [interpreter] $path(cat) << foo]" r]
+ chan event $f4 readable [namespace code {
+ if {[chan gets $f4 line] < 0} {
+ lappend x eof
+ chan event $f4 readable {}
+ } else {
+ lappend x $line
+ }
+ }]
+ variable x initial
+ vwait [namespace which -variable x]
+ vwait [namespace which -variable x]
+ chan close $f4
+ set x
+} {initial foo eof}
+
+chan close $f
+makeFile "foo bar" foo
+
+test chan-io-45.1 {DeleteFileEvent, cleanup on chan close} {fileevent} {
+ set f [open $path(foo) r]
+ chan event $f readable [namespace code {
+ lappend x "binding triggered: \"[chan gets $f]\""
+ chan event $f readable {}
+ }]
+ chan close $f
+ set x initial
+ after 100 [namespace code { set y done }]
+ variable y
+ vwait [namespace which -variable y]
+ set x
+} {initial}
+test chan-io-45.2 {DeleteFileEvent, cleanup on chan close} {fileevent} {
+ set f [open $path(foo) r]
+ set f2 [open $path(foo) r]
+ chan event $f readable [namespace code {
+ lappend x "f triggered: \"[chan gets $f]\""
+ chan event $f readable {}
+ }]
+ chan event $f2 readable [namespace code {
+ lappend x "f2 triggered: \"[chan gets $f2]\""
+ chan event $f2 readable {}
+ }]
+ chan close $f
+ variable x initial
+ vwait [namespace which -variable x]
+ chan close $f2
+ set x
+} {initial {f2 triggered: "foo bar"}}
+test chan-io-45.3 {DeleteFileEvent, cleanup on chan close} {fileevent} {
+ set f [open $path(foo) r]
+ set f2 [open $path(foo) r]
+ set f3 [open $path(foo) r]
+ chan event $f readable {f script}
+ chan event $f2 readable {f2 script}
+ chan event $f3 readable {f3 script}
+ set x {}
+ chan close $f2
+ lappend x [catch {chan event $f readable} msg] $msg \
+ [catch {chan event $f2 readable}] \
+ [catch {chan event $f3 readable} msg] $msg
+ chan close $f3
+ lappend x [catch {chan event $f readable} msg] $msg \
+ [catch {chan event $f2 readable}] \
+ [catch {chan event $f3 readable}]
+ chan close $f
+ lappend x [catch {chan event $f readable}] \
+ [catch {chan event $f2 readable}] \
+ [catch {chan event $f3 readable}]
+} {0 {f script} 1 0 {f3 script} 0 {f script} 1 1 1 1 1}
+
+# Execute these tests only if the "testfevent" command is present.
+
+test chan-io-46.1 {Tcl event loop vs multiple interpreters} {testfevent fileevent} {
+ testfevent create
+ set script "set f \[[list open $path(foo) r]]\n"
+ append script {
+ set x "no event"
+ chan event $f readable [namespace code {
+ set x "f triggered: [chan gets $f]"
+ chan event $f readable {}
+ }]
+ }
+ testfevent cmd $script
+ after 1 ;# We must delay because Windows takes a little time to notice
+ update
+ testfevent cmd {chan close $f}
+ list [testfevent cmd {set x}] [testfevent cmd {info commands after}]
+} {{f triggered: foo bar} after}
+test chan-io-46.2 {Tcl event loop vs multiple interpreters} testfevent {
+ testfevent create
+ testfevent cmd {
+ variable x 0
+ after 100 {set x triggered}
+ vwait [namespace which -variable x]
+ set x
+ }
+} {triggered}
+test chan-io-46.3 {Tcl event loop vs multiple interpreters} testfevent {
+ testfevent create
+ testfevent cmd {
+ set x 0
+ after 10 {lappend x timer}
+ after 30
+ set result $x
+ update idletasks
+ lappend result $x
+ update
+ lappend result $x
+ }
+} {0 0 {0 timer}}
+
+test chan-io-47.1 {chan event vs multiple interpreters} {testfevent fileevent} {
+ set f [open $path(foo) r]
+ set f2 [open $path(foo) r]
+ set f3 [open $path(foo) r]
+ chan event $f readable {script 1}
+ testfevent create
+ testfevent share $f2
+ testfevent cmd "chan event $f2 readable {script 2}"
+ chan event $f3 readable {sript 3}
+ set x {}
+ lappend x [chan event $f2 readable]
+ testfevent delete
+ lappend x [chan event $f readable] [chan event $f2 readable] \
+ [chan event $f3 readable]
+ chan close $f
+ chan close $f2
+ chan close $f3
+ set x
+} {{} {script 1} {} {sript 3}}
+test chan-io-47.2 {deleting chan event on interpreter delete} {testfevent fileevent} {
+ set f [open $path(foo) r]
+ set f2 [open $path(foo) r]
+ set f3 [open $path(foo) r]
+ set f4 [open $path(foo) r]
+ chan event $f readable {script 1}
+ testfevent create
+ testfevent share $f2
+ testfevent share $f3
+ testfevent cmd "chan event $f2 readable {script 2}
+ chan event $f3 readable {script 3}"
+ chan event $f4 readable {script 4}
+ testfevent delete
+ set x [list [chan event $f readable] [chan event $f2 readable] \
+ [chan event $f3 readable] [chan event $f4 readable]]
+ chan close $f
+ chan close $f2
+ chan close $f3
+ chan close $f4
+ set x
+} {{script 1} {} {} {script 4}}
+test chan-io-47.3 {deleting chan event on interpreter delete} {testfevent fileevent} {
+ set f [open $path(foo) r]
+ set f2 [open $path(foo) r]
+ set f3 [open $path(foo) r]
+ set f4 [open $path(foo) r]
+ testfevent create
+ testfevent share $f3
+ testfevent share $f4
+ chan event $f readable {script 1}
+ chan event $f2 readable {script 2}
+ testfevent cmd "chan event $f3 readable {script 3}
+ chan event $f4 readable {script 4}"
+ testfevent delete
+ set x [list [chan event $f readable] [chan event $f2 readable] \
+ [chan event $f3 readable] [chan event $f4 readable]]
+ chan close $f
+ chan close $f2
+ chan close $f3
+ chan close $f4
+ set x
+} {{script 1} {script 2} {} {}}
+test chan-io-47.4 {file events on shared files and multiple interpreters} {testfevent fileevent} {
+ set f [open $path(foo) r]
+ set f2 [open $path(foo) r]
+ testfevent create
+ testfevent share $f
+ testfevent cmd "chan event $f readable {script 1}"
+ chan event $f readable {script 2}
+ chan event $f2 readable {script 3}
+ set x [list [chan event $f2 readable] \
+ [testfevent cmd "chan event $f readable"] \
+ [chan event $f readable]]
+ testfevent delete
+ chan close $f
+ chan close $f2
+ set x
+} {{script 3} {script 1} {script 2}}
+test chan-io-47.5 {file events on shared files, deleting file events} {testfevent fileevent} {
+ set f [open $path(foo) r]
+ testfevent create
+ testfevent share $f
+ testfevent cmd "chan event $f readable {script 1}"
+ chan event $f readable {script 2}
+ testfevent cmd "chan event $f readable {}"
+ set x [list [testfevent cmd "chan event $f readable"] \
+ [chan event $f readable]]
+ testfevent delete
+ chan close $f
+ set x
+} {{} {script 2}}
+test chan-io-47.6 {file events on shared files, deleting file events} {testfevent fileevent} {
+ set f [open $path(foo) r]
+ testfevent create
+ testfevent share $f
+ testfevent cmd "chan event $f readable {script 1}"
+ chan event $f readable {script 2}
+ chan event $f readable {}
+ set x [list [testfevent cmd "chan event $f readable"] \
+ [chan event $f readable]]
+ testfevent delete
+ chan close $f
+ set x
+} {{script 1} {}}
+
+set path(bar) [makeFile {} bar]
+
+test chan-io-48.1 {testing readability conditions} {fileevent} {
+ set f [open $path(bar) w]
+ chan puts $f abcdefg
+ chan puts $f abcdefg
+ chan puts $f abcdefg
+ chan puts $f abcdefg
+ chan puts $f abcdefg
+ chan close $f
+ set f [open $path(bar) r]
+ chan event $f readable [namespace code [list consume $f]]
+ proc consume {f} {
+ variable l
+ variable x
+ lappend l called
+ if {[chan eof $f]} {
+ chan close $f
+ set x done
+ } else {
+ chan gets $f
+ }
+ }
+ set l ""
+ variable x not_done
+ vwait [namespace which -variable x]
+ list $x $l
+} {done {called called called called called called called}}
+test chan-io-48.2 {testing readability conditions} {nonBlockFiles fileevent} {
+ set f [open $path(bar) w]
+ chan puts $f abcdefg
+ chan puts $f abcdefg
+ chan puts $f abcdefg
+ chan puts $f abcdefg
+ chan puts $f abcdefg
+ chan close $f
+ set f [open $path(bar) r]
+ chan event $f readable [namespace code [list consume $f]]
+ chan configure $f -blocking off
+ proc consume {f} {
+ variable x
+ variable l
+ lappend l called
+ if {[chan eof $f]} {
+ chan close $f
+ set x done
+ } else {
+ chan gets $f
+ }
+ }
+ set l ""
+ variable x not_done
+ vwait [namespace which -variable x]
+ list $x $l
+} {done {called called called called called called called}}
+set path(my_script) [makeFile {} my_script]
+test chan-io-48.3 {testing readability conditions} {stdio unix nonBlockFiles openpipe fileevent} {
+ set f [open $path(bar) w]
+ chan puts $f abcdefg
+ chan puts $f abcdefg
+ chan puts $f abcdefg
+ chan puts $f abcdefg
+ chan puts $f abcdefg
+ chan close $f
+ set f [open $path(my_script) w]
+ chan puts $f {
+ proc copy_slowly {f} {
+ while {![chan eof $f]} {
+ chan puts [chan gets $f]
+ after 200
+ }
+ chan close $f
+ }
+ }
+ chan close $f
+ set f [open "|[list [interpreter]]" r+]
+ chan event $f readable [namespace code [list consume $f]]
+ chan configure $f -buffering line
+ chan configure $f -blocking off
+ proc consume {f} {
+ variable l
+ variable x
+ if {[chan eof $f]} {
+ set x done
+ } else {
+ chan gets $f
+ lappend l [chan blocked $f]
+ chan gets $f
+ lappend l [chan blocked $f]
+ }
+ }
+ set l ""
+ variable x not_done
+ chan puts $f [list source $path(my_script)]
+ chan puts $f "set f \[[list open $path(bar) r]]"
+ chan puts $f {copy_slowly $f}
+ chan puts $f {exit}
+ vwait [namespace which -variable x]
+ chan close $f
+ list $x $l
+} {done {0 1 0 1 0 1 0 1 0 1 0 1 0 0}}
+test chan-io-48.4 {lf write, testing readability, ^Z termination, auto read mode} {fileevent} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ variable c [format "abc\ndef\n%c" 26]
+ chan puts -nonewline $f $c
+ chan close $f
+ proc consume {f} {
+ variable l
+ variable c
+ variable x
+ if {[chan eof $f]} {
+ set x done
+ chan close $f
+ } else {
+ lappend l [chan gets $f]
+ incr c
+ }
+ }
+ set c 0
+ set l ""
+ set f [open $path(test1) r]
+ chan configure $f -translation auto -eofchar \x1a
+ chan event $f readable [namespace code [list consume $f]]
+ variable x
+ vwait [namespace which -variable x]
+ list $c $l
+} {3 {abc def {}}}
+test chan-io-48.5 {lf write, testing readability, ^Z in middle, auto read mode} {fileevent} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ set c [format "abc\ndef\n%cfoo\nbar\n" 26]
+ chan puts -nonewline $f $c
+ chan close $f
+ proc consume {f} {
+ variable l
+ variable x
+ variable c
+ if {[chan eof $f]} {
+ set x done
+ chan close $f
+ } else {
+ lappend l [chan gets $f]
+ incr c
+ }
+ }
+ set c 0
+ set l ""
+ set f [open $path(test1) r]
+ chan configure $f -eofchar \x1a -translation auto
+ chan event $f readable [namespace code [list consume $f]]
+ variable x
+ vwait [namespace which -variable x]
+ list $c $l
+} {3 {abc def {}}}
+test chan-io-48.6 {cr write, testing readability, ^Z termination, auto read mode} {fileevent} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr
+ set c [format "abc\ndef\n%c" 26]
+ chan puts -nonewline $f $c
+ chan close $f
+ proc consume {f} {
+ variable l
+ variable x
+ variable c
+ if {[chan eof $f]} {
+ set x done
+ chan close $f
+ } else {
+ lappend l [chan gets $f]
+ incr c
+ }
+ }
+ set c 0
+ set l ""
+ set f [open $path(test1) r]
+ chan configure $f -translation auto -eofchar \x1a
+ chan event $f readable [namespace code [list consume $f]]
+ variable x
+ vwait [namespace which -variable x]
+ list $c $l
+} {3 {abc def {}}}
+test chan-io-48.7 {cr write, testing readability, ^Z in middle, auto read mode} {fileevent} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr
+ set c [format "abc\ndef\n%cfoo\nbar\n" 26]
+ chan puts -nonewline $f $c
+ chan close $f
+ proc consume {f} {
+ variable l
+ variable c
+ variable x
+ if {[chan eof $f]} {
+ set x done
+ chan close $f
+ } else {
+ lappend l [chan gets $f]
+ incr c
+ }
+ }
+ set c 0
+ set l ""
+ set f [open $path(test1) r]
+ chan configure $f -eofchar \x1a -translation auto
+ chan event $f readable [namespace code [list consume $f]]
+ variable x
+ vwait [namespace which -variable x]
+ list $c $l
+} {3 {abc def {}}}
+test chan-io-48.8 {crlf write, testing readability, ^Z termination, auto read mode} {fileevent} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf
+ set c [format "abc\ndef\n%c" 26]
+ chan puts -nonewline $f $c
+ chan close $f
+ proc consume {f} {
+ variable l
+ variable x
+ variable c
+ if {[chan eof $f]} {
+ set x done
+ chan close $f
+ } else {
+ lappend l [chan gets $f]
+ incr c
+ }
+ }
+ set c 0
+ set l ""
+ set f [open $path(test1) r]
+ chan configure $f -translation auto -eofchar \x1a
+ chan event $f readable [namespace code [list consume $f]]
+ variable x
+ vwait [namespace which -variable x]
+ list $c $l
+} {3 {abc def {}}}
+test chan-io-48.9 {crlf write, testing readability, ^Z in middle, auto read mode} {fileevent} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf
+ set c [format "abc\ndef\n%cfoo\nbar\n" 26]
+ chan puts -nonewline $f $c
+ chan close $f
+ proc consume {f} {
+ variable l
+ variable c
+ variable x
+ if {[chan eof $f]} {
+ set x done
+ chan close $f
+ } else {
+ lappend l [chan gets $f]
+ incr c
+ }
+ }
+ set c 0
+ set l ""
+ set f [open $path(test1) r]
+ chan configure $f -eofchar \x1a -translation auto
+ chan event $f readable [namespace code [list consume $f]]
+ variable x
+ vwait [namespace which -variable x]
+ list $c $l
+} {3 {abc def {}}}
+test chan-io-48.10 {lf write, testing readability, ^Z in middle, lf read mode} {fileevent} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ set c [format "abc\ndef\n%cfoo\nbar\n" 26]
+ chan puts -nonewline $f $c
+ chan close $f
+ proc consume {f} {
+ variable l
+ variable c
+ variable x
+ if {[chan eof $f]} {
+ set x done
+ chan close $f
+ } else {
+ lappend l [chan gets $f]
+ incr c
+ }
+ }
+ set c 0
+ set l ""
+ set f [open $path(test1) r]
+ chan configure $f -eofchar \x1a -translation lf
+ chan event $f readable [namespace code [list consume $f]]
+ variable x
+ vwait [namespace which -variable x]
+ list $c $l
+} {3 {abc def {}}}
+test chan-io-48.11 {lf write, testing readability, ^Z termination, lf read mode} {fileevent} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ set c [format "abc\ndef\n%c" 26]
+ chan puts -nonewline $f $c
+ chan close $f
+ proc consume {f} {
+ variable l
+ variable x
+ variable c
+ if {[chan eof $f]} {
+ set x done
+ chan close $f
+ } else {
+ lappend l [chan gets $f]
+ incr c
+ }
+ }
+ set c 0
+ set l ""
+ set f [open $path(test1) r]
+ chan configure $f -translation lf -eofchar \x1a
+ chan event $f readable [namespace code [list consume $f]]
+ variable x
+ vwait [namespace which -variable x]
+ list $c $l
+} {3 {abc def {}}}
+test chan-io-48.12 {cr write, testing readability, ^Z in middle, cr read mode} {fileevent} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr
+ set c [format "abc\ndef\n%cfoo\nbar\n" 26]
+ chan puts -nonewline $f $c
+ chan close $f
+ proc consume {f} {
+ variable l
+ variable x
+ variable c
+ if {[chan eof $f]} {
+ set x done
+ chan close $f
+ } else {
+ lappend l [chan gets $f]
+ incr c
+ }
+ }
+ set c 0
+ set l ""
+ set f [open $path(test1) r]
+ chan configure $f -eofchar \x1a -translation cr
+ chan event $f readable [namespace code [list consume $f]]
+ variable x
+ vwait [namespace which -variable x]
+ list $c $l
+} {3 {abc def {}}}
+test chan-io-48.13 {cr write, testing readability, ^Z termination, cr read mode} {fileevent} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation cr
+ set c [format "abc\ndef\n%c" 26]
+ chan puts -nonewline $f $c
+ chan close $f
+ proc consume {f} {
+ variable c
+ variable x
+ variable l
+ if {[chan eof $f]} {
+ set x done
+ chan close $f
+ } else {
+ lappend l [chan gets $f]
+ incr c
+ }
+ }
+ set c 0
+ set l ""
+ set f [open $path(test1) r]
+ chan configure $f -translation cr -eofchar \x1a
+ chan event $f readable [namespace code [list consume $f]]
+ variable x
+ vwait [namespace which -variable x]
+ list $c $l
+} {3 {abc def {}}}
+test chan-io-48.14 {crlf write, testing readability, ^Z in middle, crlf read mode} {fileevent} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf
+ set c [format "abc\ndef\n%cfoo\nbar\n" 26]
+ chan puts -nonewline $f $c
+ chan close $f
+ proc consume {f} {
+ variable c
+ variable x
+ variable l
+ if {[chan eof $f]} {
+ set x done
+ chan close $f
+ } else {
+ lappend l [chan gets $f]
+ incr c
+ }
+ }
+ set c 0
+ set l ""
+ set f [open $path(test1) r]
+ chan configure $f -eofchar \x1a -translation crlf
+ chan event $f readable [namespace code [list consume $f]]
+ variable x
+ vwait [namespace which -variable x]
+ list $c $l
+} {3 {abc def {}}}
+test chan-io-48.15 {crlf write, testing readability, ^Z termi, crlf read mode} {fileevent} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation crlf
+ set c [format "abc\ndef\n%c" 26]
+ chan puts -nonewline $f $c
+ chan close $f
+ proc consume {f} {
+ variable c
+ variable x
+ variable l
+ if {[chan eof $f]} {
+ set x done
+ chan close $f
+ } else {
+ lappend l [chan gets $f]
+ incr c
+ }
+ }
+ set c 0
+ set l ""
+ set f [open $path(test1) r]
+ chan configure $f -translation crlf -eofchar \x1a
+ chan event $f readable [namespace code [list consume $f]]
+ variable x
+ vwait [namespace which -variable x]
+ list $c $l
+} {3 {abc def {}}}
+
+test chan-io-49.1 {testing crlf reading, leftover cr disgorgment} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "a\rb\rc\r\n"
+ chan close $f
+ set f [open $path(test1) r]
+ set l ""
+ lappend l [file size $path(test1)]
+ chan configure $f -translation crlf
+ lappend l [chan read $f 1]
+ lappend l [chan tell $f]
+ lappend l [chan read $f 1]
+ lappend l [chan tell $f]
+ lappend l [chan read $f 1]
+ lappend l [chan tell $f]
+ lappend l [chan read $f 1]
+ lappend l [chan tell $f]
+ lappend l [chan read $f 1]
+ lappend l [chan tell $f]
+ lappend l [chan read $f 1]
+ lappend l [chan tell $f]
+ lappend l [chan eof $f]
+ lappend l [chan read $f 1]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} "7 a 1 [list \r] 2 b 3 [list \r] 4 c 5 {
+} 7 0 {} 1"
+test chan-io-49.2 {testing crlf reading, leftover cr disgorgment} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "a\rb\rc\r\n"
+ chan close $f
+ set f [open $path(test1) r]
+ set l ""
+ lappend l [file size $path(test1)]
+ chan configure $f -translation crlf
+ lappend l [chan read $f 2]
+ lappend l [chan tell $f]
+ lappend l [chan read $f 2]
+ lappend l [chan tell $f]
+ lappend l [chan read $f 2]
+ lappend l [chan tell $f]
+ lappend l [chan eof $f]
+ lappend l [chan read $f 2]
+ lappend l [chan tell $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} "7 [list a\r] 2 [list b\r] 4 [list c\n] 7 0 {} 7 1"
+test chan-io-49.3 {testing crlf reading, leftover cr disgorgment} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "a\rb\rc\r\n"
+ chan close $f
+ set f [open $path(test1) r]
+ set l ""
+ lappend l [file size $path(test1)]
+ chan configure $f -translation crlf
+ lappend l [chan read $f 3]
+ lappend l [chan tell $f]
+ lappend l [chan read $f 3]
+ lappend l [chan tell $f]
+ lappend l [chan eof $f]
+ lappend l [chan read $f 3]
+ lappend l [chan tell $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} "7 [list a\rb] 3 [list \rc\n] 7 0 {} 7 1"
+test chan-io-49.4 {testing crlf reading, leftover cr disgorgment} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "a\rb\rc\r\n"
+ chan close $f
+ set f [open $path(test1) r]
+ set l ""
+ lappend l [file size $path(test1)]
+ chan configure $f -translation crlf
+ lappend l [chan read $f 3]
+ lappend l [chan tell $f]
+ lappend l [chan gets $f]
+ lappend l [chan tell $f]
+ lappend l [chan eof $f]
+ lappend l [chan gets $f]
+ lappend l [chan tell $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} "7 [list a\rb] 3 [list \rc] 7 0 {} 7 1"
+test chan-io-49.5 {testing crlf reading, leftover cr disgorgment} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts -nonewline $f "a\rb\rc\r\n"
+ chan close $f
+ set f [open $path(test1) r]
+ set l ""
+ lappend l [file size $path(test1)]
+ chan configure $f -translation crlf
+ lappend l [set x [chan gets $f]]
+ lappend l [chan tell $f]
+ lappend l [chan gets $f]
+ lappend l [chan tell $f]
+ lappend l [chan eof $f]
+ chan close $f
+ set l
+} [list 7 a\rb\rc 7 {} 7 1]
+
+test chan-io-50.1 {testing handler deletion} {testchannelevent} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan close $f
+ set f [open $path(test1) r]
+ testchannelevent $f add readable [namespace code [list delhandler $f]]
+ proc delhandler {f} {
+ variable z
+ set z called
+ testchannelevent $f delete 0
+ }
+ set z not_called
+ update
+ chan close $f
+ set z
+} called
+test chan-io-50.2 {testing handler deletion with multiple handlers} {testchannelevent} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan close $f
+ set f [open $path(test1) r]
+ testchannelevent $f add readable [namespace code [list delhandler $f 1]]
+ testchannelevent $f add readable [namespace code [list delhandler $f 0]]
+ proc delhandler {f i} {
+ variable z
+ lappend z "called delhandler $f $i"
+ testchannelevent $f delete 0
+ }
+ set z ""
+ update
+ chan close $f
+ string compare [string tolower $z] \
+ [list [list called delhandler $f 0] [list called delhandler $f 1]]
+} 0
+test chan-io-50.3 {testing handler deletion with multiple handlers} {testchannelevent} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan close $f
+ set f [open $path(test1) r]
+ testchannelevent $f add readable [namespace code [list notcalled $f 1]]
+ testchannelevent $f add readable [namespace code [list delhandler $f 0]]
+ set z ""
+ proc notcalled {f i} {
+ variable z
+ lappend z "notcalled was called!! $f $i"
+ }
+ proc delhandler {f i} {
+ variable z
+ testchannelevent $f delete 1
+ lappend z "delhandler $f $i called"
+ testchannelevent $f delete 0
+ lappend z "delhandler $f $i deleted myself"
+ }
+ set z ""
+ update
+ chan close $f
+ string compare [string tolower $z] \
+ [list [list delhandler $f 0 called] \
+ [list delhandler $f 0 deleted myself]]
+} 0
+test chan-io-50.4 {testing handler deletion vs reentrant calls} {testchannelevent} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan close $f
+ set f [open $path(test1) r]
+ testchannelevent $f add readable [namespace code [list delrecursive $f]]
+ proc delrecursive {f} {
+ variable z
+ variable u
+ if {"$u" == "recursive"} {
+ testchannelevent $f delete 0
+ lappend z "delrecursive deleting recursive"
+ } else {
+ lappend z "delrecursive calling recursive"
+ set u recursive
+ update
+ }
+ }
+ variable u toplevel
+ variable z ""
+ update
+ chan close $f
+ string compare [string tolower $z] \
+ {{delrecursive calling recursive} {delrecursive deleting recursive}}
+} 0
+test chan-io-50.5 {testing handler deletion vs reentrant calls} {testchannelevent} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan close $f
+ set f [open $path(test1) r]
+ testchannelevent $f add readable [namespace code [list notcalled $f]]
+ testchannelevent $f add readable [namespace code [list del $f]]
+ proc notcalled {f} {
+ variable z
+ lappend z "notcalled was called!! $f"
+ }
+ proc del {f} {
+ variable u
+ variable z
+ if {"$u" == "recursive"} {
+ testchannelevent $f delete 1
+ testchannelevent $f delete 0
+ lappend z "del deleted notcalled"
+ lappend z "del deleted myself"
+ } else {
+ set u recursive
+ lappend z "del calling recursive"
+ update
+ lappend z "del after update"
+ }
+ }
+ set z ""
+ set u toplevel
+ update
+ chan close $f
+ string compare [string tolower $z] \
+ [list {del calling recursive} {del deleted notcalled} \
+ {del deleted myself} {del after update}]
+} 0
+test chan-io-50.6 {testing handler deletion vs reentrant calls} {testchannelevent} {
+ file delete $path(test1)
+ set f [open $path(test1) w]
+ chan close $f
+ set f [open $path(test1) r]
+ testchannelevent $f add readable [namespace code [list second $f]]
+ testchannelevent $f add readable [namespace code [list first $f]]
+ proc first {f} {
+ variable u
+ variable z
+ if {"$u" == "toplevel"} {
+ lappend z "first called"
+ set u first
+ update
+ lappend z "first after update"
+ } else {
+ lappend z "first called not toplevel"
+ }
+ }
+ proc second {f} {
+ variable u
+ variable z
+ if {"$u" == "first"} {
+ lappend z "second called, first time"
+ set u second
+ testchannelevent $f delete 0
+ } elseif {"$u" == "second"} {
+ lappend z "second called, second time"
+ testchannelevent $f delete 0
+ } else {
+ lappend z "second called, cannot happen!"
+ testchannelevent $f removeall
+ }
+ }
+ set z ""
+ set u toplevel
+ update
+ chan close $f
+ string compare [string tolower $z] \
+ [list {first called} {first called not toplevel} \
+ {second called, first time} {second called, second time} \
+ {first after update}]
+} 0
+
+test chan-io-51.1 {Test old socket deletion on Macintosh} {socket} {
+ set x 0
+ set result ""
+ proc accept {s a p} {
+ variable x
+ variable wait
+ chan configure $s -blocking off
+ chan puts $s "sock[incr x]"
+ chan close $s
+ set wait done
+ }
+ set ss [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
+ set port [lindex [chan configure $ss -sockname] 2]
+
+ variable wait ""
+ set cs [socket 127.0.0.1 $port]
+ vwait [namespace which -variable wait]
+ lappend result [chan gets $cs]
+ chan close $cs
+
+ set wait ""
+ set cs [socket 127.0.0.1 $port]
+ vwait [namespace which -variable wait]
+ lappend result [chan gets $cs]
+ chan close $cs
+
+ set wait ""
+ set cs [socket 127.0.0.1 $port]
+ vwait [namespace which -variable wait]
+ lappend result [chan gets $cs]
+ chan close $cs
+
+ set wait ""
+ set cs [socket 127.0.0.1 $port]
+ vwait [namespace which -variable wait]
+ lappend result [chan gets $cs]
+ chan close $cs
+ chan close $ss
+ set result
+} {sock1 sock2 sock3 sock4}
+
+test chan-io-52.1 {TclCopyChannel} {fcopy} {
+ file delete $path(test1)
+ set f1 [open $thisScript]
+ set f2 [open $path(test1) w]
+ chan copy $f1 $f2 -command { # }
+ catch { chan copy $f1 $f2 } msg
+ chan close $f1
+ chan close $f2
+ string compare $msg "channel \"$f1\" is busy"
+} {0}
+test chan-io-52.2 {TclCopyChannel} {fcopy} {
+ file delete $path(test1)
+ set f1 [open $thisScript]
+ set f2 [open $path(test1) w]
+ set f3 [open $thisScript]
+ chan copy $f1 $f2 -command { # }
+ catch { chan copy $f3 $f2 } msg
+ chan close $f1
+ chan close $f2
+ chan close $f3
+ string compare $msg "channel \"$f2\" is busy"
+} {0}
+test chan-io-52.3 {TclCopyChannel} {fcopy} {
+ file delete $path(test1)
+ set f1 [open $thisScript]
+ set f2 [open $path(test1) w]
+ chan configure $f1 -translation lf -blocking 0
+ chan configure $f2 -translation cr -blocking 0
+ set s0 [chan copy $f1 $f2]
+ set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
+ chan close $f1
+ chan close $f2
+ set s1 [file size $thisScript]
+ set s2 [file size $path(test1)]
+ if {("$s1" == "$s2") && ($s0 == $s1)} {
+ lappend result ok
+ }
+ set result
+} {0 0 ok}
+test chan-io-52.4 {TclCopyChannel} {fcopy} {
+ file delete $path(test1)
+ set f1 [open $thisScript]
+ set f2 [open $path(test1) w]
+ chan configure $f1 -translation lf -blocking 0
+ chan configure $f2 -translation cr -blocking 0
+ chan copy $f1 $f2 -size 40
+ set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
+ chan close $f1
+ chan close $f2
+ lappend result [file size $path(test1)]
+} {0 0 40}
+test chan-io-52.5 {TclCopyChannel, all} {fcopy} {
+ file delete $path(test1)
+ set f1 [open $thisScript]
+ set f2 [open $path(test1) w]
+ chan configure $f1 -translation lf -blocking 0
+ chan configure $f2 -translation lf -blocking 0
+ chan copy $f1 $f2 -size -1 ;# -1 means 'copy all', same as if no -size specified.
+ set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
+ chan close $f1
+ chan close $f2
+ set s1 [file size $thisScript]
+ set s2 [file size $path(test1)]
+ if {"$s1" == "$s2"} {
+ lappend result ok
+ }
+ set result
+} {0 0 ok}
+test chan-io-52.5a {TclCopyChannel, all, other negative value} {fcopy} {
+ file delete $path(test1)
+ set f1 [open $thisScript]
+ set f2 [open $path(test1) w]
+ chan configure $f1 -translation lf -blocking 0
+ chan configure $f2 -translation lf -blocking 0
+ chan copy $f1 $f2 -size -2 ;# < 0 behaves like -1, copy all
+ set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
+ chan close $f1
+ chan close $f2
+ set s1 [file size $thisScript]
+ set s2 [file size $path(test1)]
+ if {"$s1" == "$s2"} {
+ lappend result ok
+ }
+ set result
+} {0 0 ok}
+test chan-io-52.5b {TclCopyChannel, all, wrapped to ngative value} {fcopy} {
+ file delete $path(test1)
+ set f1 [open $thisScript]
+ set f2 [open $path(test1) w]
+ chan configure $f1 -translation lf -blocking 0
+ chan configure $f2 -translation lf -blocking 0
+ chan copy $f1 $f2 -size 3221176172 ;# Wrapped to < 0, behaves like -1, copy all
+ set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
+ chan close $f1
+ chan close $f2
+ set s1 [file size $thisScript]
+ set s2 [file size $path(test1)]
+ if {"$s1" == "$s2"} {
+ lappend result ok
+ }
+ set result
+} {0 0 ok}
+test chan-io-52.6 {TclCopyChannel} {fcopy} {
+ file delete $path(test1)
+ set f1 [open $thisScript]
+ set f2 [open $path(test1) w]
+ chan configure $f1 -translation lf -blocking 0
+ chan configure $f2 -translation lf -blocking 0
+ set s0 [chan copy $f1 $f2 -size [expr [file size $thisScript] + 5]]
+ set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
+ chan close $f1
+ chan close $f2
+ set s1 [file size $thisScript]
+ set s2 [file size $path(test1)]
+ if {("$s1" == "$s2") && ($s0 == $s1)} {
+ lappend result ok
+ }
+ set result
+} {0 0 ok}
+test chan-io-52.7 {TclCopyChannel} {fcopy} {
+ file delete $path(test1)
+ set f1 [open $thisScript]
+ set f2 [open $path(test1) w]
+ chan configure $f1 -translation lf -blocking 0
+ chan configure $f2 -translation lf -blocking 0
+ chan copy $f1 $f2
+ set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
+ set s1 [file size $thisScript]
+ set s2 [file size $path(test1)]
+ chan close $f1
+ chan close $f2
+ if {"$s1" == "$s2"} {
+ lappend result ok
+ }
+ set result
+} {0 0 ok}
+test chan-io-52.8 {TclCopyChannel} {stdio openpipe fcopy} {
+ file delete $path(test1)
+ file delete $path(pipe)
+ set f1 [open $path(pipe) w]
+ chan configure $f1 -translation lf
+ chan puts $f1 "
+ chan puts ready
+ chan gets stdin
+ set f1 \[open [list $thisScript] r\]
+ chan configure \$f1 -translation lf
+ chan puts \[chan read \$f1 100\]
+ chan close \$f1
+ "
+ chan close $f1
+ set f1 [open "|[list [interpreter] $path(pipe)]" r+]
+ chan configure $f1 -translation lf
+ chan gets $f1
+ chan puts $f1 ready
+ chan flush $f1
+ set f2 [open $path(test1) w]
+ chan configure $f2 -translation lf
+ set s0 [chan copy $f1 $f2 -size 40]
+ catch {chan close $f1}
+ chan close $f2
+ list $s0 [file size $path(test1)]
+} {40 40}
+# Empty files, to register them with the test facility
+set path(kyrillic.txt) [makeFile {} kyrillic.txt]
+set path(utf8-fcopy.txt) [makeFile {} utf8-fcopy.txt]
+set path(utf8-rp.txt) [makeFile {} utf8-rp.txt]
+# Create kyrillic file, use lf translation to avoid os eol issues
+set out [open $path(kyrillic.txt) w]
+chan configure $out -encoding koi8-r -translation lf
+chan puts $out "\u0410\u0410"
+chan close $out
+test chan-io-52.9 {TclCopyChannel & encodings} {fcopy} {
+ # Copy kyrillic to UTF-8, using chan copy.
+
+ set in [open $path(kyrillic.txt) r]
+ set out [open $path(utf8-fcopy.txt) w]
+
+ chan configure $in -encoding koi8-r -translation lf
+ chan configure $out -encoding utf-8 -translation lf
+
+ chan copy $in $out
+ chan close $in
+ chan close $out
+
+ # Do the same again, but differently (read/chan puts).
+
+ set in [open $path(kyrillic.txt) r]
+ set out [open $path(utf8-rp.txt) w]
+
+ chan configure $in -encoding koi8-r -translation lf
+ chan configure $out -encoding utf-8 -translation lf
+
+ chan puts -nonewline $out [chan read $in]
+
+ chan close $in
+ chan close $out
+
+ list [file size $path(kyrillic.txt)] \
+ [file size $path(utf8-fcopy.txt)] \
+ [file size $path(utf8-rp.txt)]
+} {3 5 5}
+test chan-io-52.10 {TclCopyChannel & encodings} {fcopy} {
+ # encoding to binary (=> implies that the
+ # internal utf-8 is written)
+
+ set in [open $path(kyrillic.txt) r]
+ set out [open $path(utf8-fcopy.txt) w]
+
+ chan configure $in -encoding koi8-r -translation lf
+ # -translation binary is also -encoding binary
+ chan configure $out -translation binary
+
+ chan copy $in $out
+ chan close $in
+ chan close $out
+
+ file size $path(utf8-fcopy.txt)
+} 5
+test chan-io-52.11 {TclCopyChannel & encodings} {fcopy} {
+ # binary to encoding => the input has to be
+ # in utf-8 to make sense to the encoder
+
+ set in [open $path(utf8-fcopy.txt) r]
+ set out [open $path(kyrillic.txt) w]
+
+ # -translation binary is also -encoding binary
+ chan configure $in -translation binary
+ chan configure $out -encoding koi8-r -translation lf
+
+ chan copy $in $out
+ chan close $in
+ chan close $out
+
+ file size $path(kyrillic.txt)
+} 3
+
+test chan-io-53.1 {CopyData} {fcopy} {
+ file delete $path(test1)
+ set f1 [open $thisScript]
+ set f2 [open $path(test1) w]
+ chan configure $f1 -translation lf -blocking 0
+ chan configure $f2 -translation cr -blocking 0
+ chan copy $f1 $f2 -size 0
+ set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
+ chan close $f1
+ chan close $f2
+ lappend result [file size $path(test1)]
+} {0 0 0}
+test chan-io-53.2 {CopyData} {fcopy} {
+ file delete $path(test1)
+ set f1 [open $thisScript]
+ set f2 [open $path(test1) w]
+ chan configure $f1 -translation lf -blocking 0
+ chan configure $f2 -translation cr -blocking 0
+ chan copy $f1 $f2 -command [namespace code {set s0}]
+ set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
+ variable s0
+ vwait [namespace which -variable s0]
+ chan close $f1
+ chan close $f2
+ set s1 [file size $thisScript]
+ set s2 [file size $path(test1)]
+ if {("$s1" == "$s2") && ($s0 == $s1)} {
+ lappend result ok
+ }
+ set result
+} {0 0 ok}
+test chan-io-53.3 {CopyData: background read underflow} {stdio unix openpipe fcopy} {
+ file delete $path(test1)
+ file delete $path(pipe)
+ set f1 [open $path(pipe) w]
+ chan puts -nonewline $f1 {
+ chan puts ready
+ chan flush stdout ;# Don't assume line buffered!
+ chan copy stdin stdout -command { set x }
+ vwait x
+ set f [}
+ chan puts $f1 [list open $path(test1) w]]
+ chan puts $f1 {
+ chan configure $f -translation lf
+ chan puts $f "done"
+ chan close $f
+ }
+ chan close $f1
+ set f1 [open "|[list [interpreter] $path(pipe)]" r+]
+ set result [chan gets $f1]
+ chan puts $f1 line1
+ chan flush $f1
+ lappend result [chan gets $f1]
+ chan puts $f1 line2
+ chan flush $f1
+ lappend result [chan gets $f1]
+ chan close $f1
+ after 500
+ set f [open $path(test1)]
+ lappend result [chan read $f]
+ chan close $f
+ set result
+} "ready line1 line2 {done\n}"
+test chan-io-53.4 {CopyData: background write overflow} {stdio unix openpipe fileevent fcopy} {
+ set big bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n
+ variable x
+ for {set x 0} {$x < 12} {incr x} {
+ append big $big
+ }
+ file delete $path(test1)
+ file delete $path(pipe)
+ set f1 [open $path(pipe) w]
+ chan puts $f1 {
+ chan puts ready
+ chan copy stdin stdout -command { set x }
+ vwait x
+ set f [open $path(test1) w]
+ chan configure $f -translation lf
+ chan puts $f "done"
+ chan close $f
+ }
+ chan close $f1
+ set f1 [open "|[list [interpreter] $path(pipe)]" r+]
+ set result [chan gets $f1]
+ chan configure $f1 -blocking 0
+ chan puts $f1 $big
+ chan flush $f1
+ after 500
+ set result ""
+ chan event $f1 read [namespace code {
+ append result [chan read $f1 1024]
+ if {[string length $result] >= [string length $big]} {
+ set x done
+ }
+ }]
+ vwait [namespace which -variable x]
+ chan close $f1
+ set big {}
+ set x
+} done
+set result {}
+proc FcopyTestAccept {sock args} {
+ after 1000 "chan close $sock"
+}
+proc FcopyTestDone {bytes {error {}}} {
+ variable fcopyTestDone
+ if {[string length $error]} {
+ set fcopyTestDone 1
+ } else {
+ set fcopyTestDone 0
+ }
+}
+test chan-io-53.5 {CopyData: error during chan copy} {socket fcopy} {
+ variable fcopyTestDone
+ set listen [socket -server [namespace code FcopyTestAccept] -myaddr 127.0.0.1 0]
+ set in [open $thisScript] ;# 126 K
+ set out [socket 127.0.0.1 [lindex [chan configure $listen -sockname] 2]]
+ catch {unset fcopyTestDone}
+ chan close $listen ;# This means the socket open never really succeeds
+ chan copy $in $out -command [namespace code FcopyTestDone]
+ variable fcopyTestDone
+ if ![info exists fcopyTestDone] {
+ vwait [namespace which -variable fcopyTestDone] ;# The error occurs here in the b.g.
+ }
+ chan close $in
+ chan close $out
+ set fcopyTestDone ;# 1 for error condition
+} 1
+test chan-io-53.6 {CopyData: error during chan copy} {stdio openpipe fcopy} {
+ variable fcopyTestDone
+ file delete $path(pipe)
+ file delete $path(test1)
+ catch {unset fcopyTestDone}
+ set f1 [open $path(pipe) w]
+ chan puts $f1 "exit 1"
+ chan close $f1
+ set in [open "|[list [interpreter] $path(pipe)]" r+]
+ set out [open $path(test1) w]
+ chan copy $in $out -command [namespace code FcopyTestDone]
+ variable fcopyTestDone
+ if ![info exists fcopyTestDone] {
+ vwait [namespace which -variable fcopyTestDone]
+ }
+ catch {chan close $in}
+ chan close $out
+ set fcopyTestDone ;# 0 for plain end of file
+} {0}
+proc doFcopy {in out {bytes 0} {error {}}} {
+ variable fcopyTestDone
+ variable fcopyTestCount
+ incr fcopyTestCount $bytes
+ if {[string length $error]} {
+ set fcopyTestDone 1
+ } elseif {[chan eof $in]} {
+ set fcopyTestDone 0
+ } else {
+ # Delay next chan copy to wait for size>0 input bytes
+ after 100 [list chan copy $in $out -size 1000 \
+ -command [namespace code [list doFcopy $in $out]]]
+ }
+}
+test chan-io-53.7 {CopyData: Flooding chan copy from pipe} {stdio openpipe fcopy} {
+ variable fcopyTestDone
+ file delete $path(pipe)
+ catch {unset fcopyTestDone}
+ set fcopyTestCount 0
+ set f1 [open $path(pipe) w]
+ chan puts $f1 {
+ # Write 10 bytes / 10 msec
+ proc Write {count} {
+ chan puts -nonewline "1234567890"
+ if {[incr count -1]} {
+ after 10 [list Write $count]
+ } else {
+ set ::ready 1
+ }
+ }
+ chan configure stdout -buffering none
+ Write 345 ;# 3450 bytes ~3.45 sec
+ vwait ready
+ exit 0
+ }
+ chan close $f1
+ set in [open "|[list [interpreter] $path(pipe) &]" r+]
+ set out [open $path(test1) w]
+ doFcopy $in $out
+ variable fcopyTestDone
+ if ![info exists fcopyTestDone] {
+ vwait [namespace which -variable fcopyTestDone]
+ }
+ catch {chan close $in}
+ chan close $out
+ # -1=error 0=script error N=number of bytes
+ expr ($fcopyTestDone == 0) ? $fcopyTestCount : -1
+} {3450}
+test chan-io-53.8 {CopyData: async callback and error handling, Bug 1932639} -setup {
+ # copy progress callback. errors out intentionally
+ proc ::cmd args {
+ lappend ::RES "CMD $args"
+ error !STOP
+ }
+ # capture callback error here
+ proc ::bgerror args {
+ lappend ::RES "bgerror/OK $args"
+ set ::forever has-been-reached
+ return
+ }
+ # Files we use for our channels
+ set foo [makeFile ashgdfashdgfasdhgfasdhgf foo]
+ set bar [makeFile {} bar]
+ # Channels to copy between
+ set f [open $foo r] ; fconfigure $f -translation binary
+ set g [open $bar w] ; fconfigure $g -translation binary -buffering none
+} -constraints {stdio openpipe fcopy} -body {
+ # Record input size, so that result is always defined
+ lappend ::RES [file size $bar]
+ # Run the copy. Should not invoke -command now.
+ chan copy $f $g -size 2 -command ::cmd
+ # Check that -command was not called synchronously
+ set sbs [file size $bar]
+ lappend ::RES [expr {($sbs > 0) ? "sync/FAIL" : "sync/OK"}] $sbs
+ # Now let the async part happen. Should capture the error in cmd
+ # via bgerror. If not break the event loop via timer.
+ set token [after 1000 {
+ lappend ::RES {bgerror/FAIL timeout}
+ set ::forever has-been-reached
+ }]
+ vwait ::forever
+ catch {after cancel $token}
+ # Report
+ set ::RES
+} -cleanup {
+ chan close $f
+ chan close $g
+ catch {unset ::RES}
+ catch {unset ::forever}
+ rename ::cmd {}
+ rename ::bgerror {}
+ removeFile foo
+ removeFile bar
+} -result {0 sync/OK 0 {CMD 2} {bgerror/OK !STOP}}
+test chan-io-53.8a {CopyData: async callback and error handling, Bug 1932639, at eof} -setup {
+ # copy progress callback. errors out intentionally
+ proc ::cmd args {
+ lappend ::RES "CMD $args"
+ set ::forever has-been-reached
+ return
+ }
+ # Files we use for our channels
+ set foo [makeFile ashgdfashdgfasdhgfasdhgf foo]
+ set bar [makeFile {} bar]
+ # Channels to copy between
+ set f [open $foo r] ; chan configure $f -translation binary
+ set g [open $bar w] ; chan configure $g -translation binary -buffering none
+} -constraints {stdio openpipe fcopy} -body {
+ # Initialize and force eof on the input.
+ chan seek $f 0 end ; chan read $f 1
+ set ::RES [chan eof $f]
+ # Run the copy. Should not invoke -command now.
+ chan copy $f $g -size 2 -command ::cmd
+ # Check that -command was not called synchronously
+ lappend ::RES [expr {([llength $::RES] > 1) ? "sync/FAIL" : "sync/OK"}]
+ # Now let the async part happen. Should capture the eof in cmd
+ # If not break the event loop via timer.
+ set token [after 1000 {
+ lappend ::RES {cmd/FAIL timeout}
+ set ::forever has-been-reached
+ }]
+ vwait ::forever
+ catch {after cancel $token}
+ # Report
+ set ::RES
+} -cleanup {
+ chan close $f
+ chan close $g
+ catch {unset ::RES}
+ catch {unset ::forever}
+ rename ::cmd {}
+ removeFile foo
+ removeFile bar
+} -result {1 sync/OK {CMD 0}}
+test chan-io-53.9 {CopyData: -size and event interaction, Bug 780533} -setup {
+ set out [makeFile {} out]
+ set err [makeFile {} err]
+ set pipe [open "|[list [info nameofexecutable] 2> $err]" r+]
+ chan configure $pipe -translation binary -buffering line
+ chan puts $pipe {
+ chan configure stdout -translation binary -buffering line
+ chan puts stderr Waiting...
+ after 1000
+ foreach x {a b c} {
+ chan puts stderr Looping...
+ chan puts $x
+ after 500
+ }
+ proc bye args {
+ if {[chan gets stdin line]<0} {
+ chan puts stderr "CHILD: EOF detected, exiting"
+ exit
+ } else {
+ chan puts stderr "CHILD: ignoring line: $line"
+ }
+ }
+ chan puts stderr Now-sleeping-forever
+ chan event stdin readable bye
+ vwait forever
+ }
+ proc ::done args {
+ set ::forever OK
+ return
+ }
+ set ::forever {}
+ set out [open $out w]
+} -constraints {stdio openpipe fcopy} -body {
+ chan copy $pipe $out -size 6 -command ::done
+ set token [after 5000 {
+ set ::forever {fcopy hangs}
+ }]
+ vwait ::forever
+ catch {after cancel $token}
+ set ::forever
+} -cleanup {
+ chan close $pipe
+ rename ::done {}
+ after 1000; # Allow Windows time to figure out that the
+ # process is gone
+ catch {removeFile out}
+ catch {removeFile err}
+ catch {unset ::forever}
+} -result OK
+test chan-io-53.10 {Bug 1350564, multi-directional fcopy} -setup {
+ set err [makeFile {} err]
+ set pipe [open "|[list [info nameofexecutable] 2> $err]" r+]
+ chan configure $pipe -translation binary -buffering line
+ chan puts $pipe {
+ chan configure stderr -buffering line
+ # Kill server when pipe closed by invoker.
+ proc bye args {
+ if {![chan eof stdin]} { chan gets stdin ; return }
+ chan puts stderr BYE
+ exit
+ }
+ # Server code. Bi-directional copy between 2 sockets.
+ proc geof {sok} {
+ chan puts stderr DONE/$sok
+ chan close $sok
+ }
+ proc new {sok args} {
+ chan puts stderr NEW/$sok
+ global l srv
+ chan configure $sok -translation binary -buffering none
+ lappend l $sok
+ if {[llength $l]==2} {
+ chan close $srv
+ foreach {a b} $l break
+ chan copy $a $b -command [list geof $a]
+ chan copy $b $a -command [list geof $b]
+ chan puts stderr 2COPY
+ }
+ chan puts stderr ...
+ }
+ chan puts stderr SRV
+ set l {}
+ set srv [socket -server new 9999]
+ chan puts stderr WAITING
+ chan event stdin readable bye
+ chan puts OK
+ vwait forever
+ }
+ # wait for OK from server.
+ chan gets $pipe
+ # Now the two clients.
+ proc ::done {sock} {
+ if {[chan eof $sock]} { chan close $sock ; return }
+ lappend ::forever [chan gets $sock]
+ return
+ }
+ set a [socket 127.0.0.1 9999]
+ set b [socket 127.0.0.1 9999]
+ chan configure $a -translation binary -buffering none
+ chan configure $b -translation binary -buffering none
+ chan event $a readable [list ::done $a]
+ chan event $b readable [list ::done $b]
+} -constraints {stdio openpipe fcopy} -body {
+ # Now pass data through the server in both directions.
+ set ::forever {}
+ chan puts $a AB
+ vwait ::forever
+ chan puts $b BA
+ vwait ::forever
+ set ::forever
+} -cleanup {
+ catch {chan close $a}
+ catch {chan close $b}
+ chan close $pipe
+ rename ::done {}
+ after 1000 ;# Give Windows time to kill the process
+ removeFile err
+ catch {unset ::forever}
+} -result {AB BA}
+
+test chan-io-54.1 {Recursive channel events} {socket fileevent} {
+ # This test checks to see if file events are delivered during recursive
+ # event loops when there is buffered data on the channel.
+
+ proc accept {s a p} {
+ variable as
+ chan configure $s -translation lf
+ chan puts $s "line 1\nline2\nline3"
+ chan flush $s
+ set as $s
+ }
+ proc readit {s next} {
+ variable x
+ variable result
+ lappend result $next
+ if {$next == 1} {
+ chan event $s readable [namespace code [list readit $s 2]]
+ vwait [namespace which -variable x]
+ }
+ incr x
+ }
+ set ss [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
+
+ # We need to delay on some systems until the creation of the
+ # server socket completes.
+
+ set done 0
+ for {set i 0} {$i < 10} {incr i} {
+ if {![catch {set cs [socket 127.0.0.1 [lindex [chan configure $ss -sockname] 2]]}]} {
+ set done 1
+ break
+ }
+ after 100
+ }
+ if {$done == 0} {
+ chan close $ss
+ error "failed to connect to server"
+ }
+ variable result {}
+ variable x 0
+ variable as
+ vwait [namespace which -variable as]
+ chan configure $cs -translation lf
+ lappend result [chan gets $cs]
+ chan configure $cs -blocking off
+ chan event $cs readable [namespace code [list readit $cs 1]]
+ set a [after 2000 [namespace code { set x failure }]]
+ vwait [namespace which -variable x]
+ after cancel $a
+ chan close $as
+ chan close $ss
+ chan close $cs
+ list $result $x
+} {{{line 1} 1 2} 2}
+test chan-io-54.2 {Testing for busy-wait in recursive channel events} {socket fileevent} {
+ set accept {}
+ set after {}
+ variable s [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
+ proc accept {s a p} {
+ variable counter
+ variable accept
+
+ set accept $s
+ set counter 0
+ chan configure $s -blocking off -buffering line -translation lf
+ chan event $s readable [namespace code "doit $s"]
+ }
+ proc doit {s} {
+ variable counter
+ variable after
+
+ incr counter
+ set l [chan gets $s]
+ if {"$l" == ""} {
+ chan event $s readable [namespace code "doit1 $s"]
+ set after [after 1000 [namespace code newline]]
+ }
+ }
+ proc doit1 {s} {
+ variable counter
+ variable accept
+
+ incr counter
+ set l [chan gets $s]
+ chan close $s
+ set accept {}
+ }
+ proc producer {} {
+ variable s
+ variable writer
+
+ set writer [socket 127.0.0.1 [lindex [chan configure $s -sockname] 2]]
+ chan configure $writer -buffering line
+ chan puts -nonewline $writer hello
+ chan flush $writer
+ }
+ proc newline {} {
+ variable done
+ variable writer
+
+ chan puts $writer hello
+ chan flush $writer
+ set done 1
+ }
+ producer
+ variable done
+ vwait [namespace which -variable done]
+ chan close $writer
+ chan close $s
+ after cancel $after
+ if {$accept != {}} {chan close $accept}
+ set counter
+} 1
+
+set path(fooBar) [makeFile {} fooBar]
+
+test chan-io-55.1 {ChannelEventScriptInvoker: deletion} -constraints {
+ fileevent
+} -setup {
+ variable x
+ proc eventScript {fd} {
+ variable x
+ chan close $fd
+ error "planned error"
+ set x whoops
+ }
+ proc myHandler args {
+ variable x got_error
+ }
+ set handler [interp bgerror {}]
+ interp bgerror {} [namespace which myHandler]
+} -body {
+ set f [open $path(fooBar) w]
+ chan event $f writable [namespace code [list eventScript $f]]
+ variable x not_done
+ vwait [namespace which -variable x]
+ set x
+} -cleanup {
+ interp bgerror {} $handler
+} -result {got_error}
+
+test chan-io-56.1 {ChannelTimerProc} {testchannelevent} {
+ set f [open $path(fooBar) w]
+ chan puts $f "this is a test"
+ chan close $f
+ set f [open $path(fooBar) r]
+ testchannelevent $f add readable [namespace code {
+ chan read $f 1
+ incr x
+ }]
+ variable x 0
+ vwait [namespace which -variable x]
+ vwait [namespace which -variable x]
+ set result $x
+ testchannelevent $f set 0 none
+ after idle [namespace code {set y done}]
+ variable y
+ vwait [namespace which -variable y]
+ chan close $f
+ lappend result $y
+} {2 done}
+
+test chan-io-57.1 {buffered data and file events, gets} {fileevent} {
+ proc accept {sock args} {
+ variable s2
+ set s2 $sock
+ }
+ set server [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
+ set s [socket 127.0.0.1 [lindex [chan configure $server -sockname] 2]]
+ variable s2
+ vwait [namespace which -variable s2]
+ update
+ chan event $s2 readable [namespace code {lappend result readable}]
+ chan puts $s "12\n34567890"
+ chan flush $s
+ variable result [chan gets $s2]
+ after 1000 [namespace code {lappend result timer}]
+ vwait [namespace which -variable result]
+ lappend result [chan gets $s2]
+ vwait [namespace which -variable result]
+ chan close $s
+ chan close $s2
+ chan close $server
+ set result
+} {12 readable 34567890 timer}
+test chan-io-57.2 {buffered data and file events, read} {fileevent} {
+ proc accept {sock args} {
+ variable s2
+ set s2 $sock
+ }
+ set server [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
+ set s [socket 127.0.0.1 [lindex [chan configure $server -sockname] 2]]
+ variable s2
+ vwait [namespace which -variable s2]
+ update
+ chan event $s2 readable [namespace code {lappend result readable}]
+ chan puts -nonewline $s "1234567890"
+ chan flush $s
+ variable result [chan read $s2 1]
+ after 1000 [namespace code {lappend result timer}]
+ vwait [namespace which -variable result]
+ lappend result [chan read $s2 9]
+ vwait [namespace which -variable result]
+ chan close $s
+ chan close $s2
+ chan close $server
+ set result
+} {1 readable 234567890 timer}
+
+test chan-io-58.1 {Tcl_NotifyChannel and error when closing} {stdio unixOrPc openpipe fileevent} {
+ set out [open $path(script) w]
+ chan puts $out {
+ chan puts "normal message from pipe"
+ chan puts stderr "error message from pipe"
+ exit 1
+ }
+ proc readit {pipe} {
+ variable x
+ variable result
+ if {[chan eof $pipe]} {
+ set x [catch {chan close $pipe} line]
+ lappend result catch $line
+ } else {
+ chan gets $pipe line
+ lappend result chan gets $line
+ }
+ }
+ chan close $out
+ set pipe [open "|[list [interpreter] $path(script)]" r]
+ chan event $pipe readable [namespace code [list readit $pipe]]
+ variable x ""
+ set result ""
+ vwait [namespace which -variable x]
+ list $x $result
+} {1 {chan gets {normal message from pipe} chan gets {} catch {error message from pipe}}}
+
+test chan-io-59.1 {Thread reference of channels} {testmainthread testchannel} {
+ # TIP #10
+ # More complicated tests (like that the reference changes as a
+ # channel is moved from thread to thread) can be done only in the
+ # extension which fully implements the moving of channels between
+ # threads, i.e. 'Threads'. Or we have to extend [testthread] as well.
+
+ set f [open $path(longfile) r]
+ set result [testchannel mthread $f]
+ chan close $f
+ string equal $result [testmainthread]
+} {1}
+
+test chan-io-60.1 {writing illegal utf sequences} {openpipe fileevent} {
+ # This test will hang in older revisions of the core.
+
+ set out [open $path(script) w]
+ chan puts $out {
+ chan puts [encoding convertfrom identity \xe2]
+ exit 1
+ }
+ proc readit {pipe} {
+ variable x
+ variable result
+ if {[chan eof $pipe]} {
+ set x [catch {chan close $pipe} line]
+ lappend result catch $line
+ } else {
+ chan gets $pipe line
+ lappend result gets $line
+ }
+ }
+ chan close $out
+ set pipe [open "|[list [interpreter] $path(script)]" r]
+ chan event $pipe readable [namespace code [list readit $pipe]]
+ variable x ""
+ set result ""
+ vwait [namespace which -variable x]
+
+ # cut of the remainder of the error stack, especially the filename
+ set result [lreplace $result 3 3 [lindex [split [lindex $result 3] \n] 0]]
+ list $x $result
+} {1 {gets {} catch {error writing "stdout": invalid argument}}}
+
+test chan-io-61.1 {Reset eof state after changing the eof char} -setup {
+ set datafile [makeFile {} eofchar]
+ set f [open $datafile w]
+ chan configure $f -translation binary
+ chan puts -nonewline $f [string repeat "Ho hum\n" 11]
+ chan puts $f =
+ set line [string repeat "Ge gla " 4]
+ chan puts -nonewline $f [string repeat [string trimright $line]\n 834]
+ chan close $f
+} -body {
+ set f [open $datafile r]
+ chan configure $f -eofchar =
+ set res {}
+ lappend res [chan read $f; chan tell $f]
+ chan configure $f -eofchar {}
+ lappend res [chan read $f 1]
+ lappend res [chan read $f; chan tell $f]
+ # Any seek zaps the internals into a good state.
+ #chan seek $f 0 start
+ #chan seek $f 0 current
+ #lappend res [chan read $f; chan tell $f]
+ chan close $f
+ set res
+} -cleanup {
+ removeFile eofchar
+} -result {77 = 23431}
+
+
+# Test the cutting and splicing of channels, this is incidentially the
+# attach/detach facility of package Thread, but __without any
+# safeguards__. It can also be used to emulate transfer of channels
+# between threads, and is used for that here.
+
+test chan-io-70.0 {Cutting & Splicing channels} {testchannel} {
+ set f [makeFile {... dummy ...} cutsplice]
+ set c [open $f r]
+
+ set res {}
+ lappend res [catch {chan seek $c 0 start}]
+ testchannel cut $c
+
+ lappend res [catch {chan seek $c 0 start}]
+ testchannel splice $c
+
+ lappend res [catch {chan seek $c 0 start}]
+ chan close $c
+
+ removeFile cutsplice
+
+ set res
+} {0 1 0}
+
+
+# Duplicate of code in "thread.test". Find a better way of doing this
+# without duplication. Maybe placement into a proc which transforms to
+# nop after the first call, and placement of its defintion in a
+# central location.
+
+if {[testConstraint testthread]} {
+ testthread errorproc ThreadError
+
+ proc ThreadError {id info} {
+ global threadError
+ set threadError $info
+ }
+
+ proc ThreadNullError {id info} {
+ # ignore
+ }
+}
+
+test chan-io-70.1 {Transfer channel} {testchannel testthread} {
+ set f [makeFile {... dummy ...} cutsplice]
+ set c [open $f r]
+
+ set res {}
+ lappend res [catch {chan seek $c 0 start}]
+ testchannel cut $c
+ lappend res [catch {chan seek $c 0 start}]
+
+ set tid [testthread create]
+ testthread send $tid [list set c $c]
+ lappend res [testthread send $tid {
+ testchannel splice $c
+ set res [catch {chan seek $c 0 start}]
+ chan close $c
+ set res
+ }]
+
+ tcltest::threadReap
+ removeFile cutsplice
+
+ set res
+} {0 1 0}
+
+# ### ### ### ######### ######### #########
+
+foreach {n msg expected} {
+ 0 {} {}
+ 1 {{message only}} {{message only}}
+ 2 {-options x} {-options x}
+ 3 {-options {x y} {the message}} {-options {x y} {the message}}
+
+ 4 {-code 1 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 5 {-code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 6 {-code 1 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 7 {-code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 8 {-code error -level 0 -f ba snarf} {-code error -level 0 -f ba snarf}
+ 9 {-code ok -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 10 {-code error -level 5 -f ba snarf} {-code error -level 0 -f ba snarf}
+ 11 {-code ok -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 12 {-code boss -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 13 {-code boss -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 14 {-code 1 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 15 {-code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 16 {-code 1 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 17 {-code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 18 {-code error -level 0 -f ba} {-code error -level 0 -f ba}
+ 19 {-code ok -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 20 {-code error -level 5 -f ba} {-code error -level 0 -f ba}
+ 21 {-code ok -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 22 {-code boss -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 23 {-code boss -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 24 {-code 1 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 25 {-code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 26 {-code error -level X -f ba snarf} {-code error -level 0 -f ba snarf}
+ 27 {-code ok -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 28 {-code boss -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 29 {-code 1 -level X -f ba} {-code 1 -level 0 -f ba}
+ 30 {-code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ 31 {-code error -level X -f ba} {-code error -level 0 -f ba}
+ 32 {-code ok -level X -f ba} {-code 1 -level 0 -f ba}
+ 33 {-code boss -level X -f ba} {-code 1 -level 0 -f ba}
+
+ 34 {-code 1 -code 1 -level 0 -f ba snarf} {-code 1 -code 1 -level 0 -f ba snarf}
+ 35 {-code 1 -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 36 {-code 1 -code 1 -level 5 -f ba snarf} {-code 1 -code 1 -level 0 -f ba snarf}
+ 37 {-code 1 -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 38 {-code 1 -code error -level 0 -f ba snarf} {-code 1 -code error -level 0 -f ba snarf}
+ 39 {-code 1 -code ok -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 40 {-code 1 -code error -level 5 -f ba snarf} {-code 1 -code error -level 0 -f ba snarf}
+ 41 {-code 1 -code ok -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 42 {-code 1 -code boss -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 43 {-code 1 -code boss -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 44 {-code 1 -code 1 -level 0 -f ba} {-code 1 -code 1 -level 0 -f ba}
+ 45 {-code 1 -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 46 {-code 1 -code 1 -level 5 -f ba} {-code 1 -code 1 -level 0 -f ba}
+ 47 {-code 1 -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 48 {-code 1 -code error -level 0 -f ba} {-code 1 -code error -level 0 -f ba}
+ 49 {-code 1 -code ok -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 50 {-code 1 -code error -level 5 -f ba} {-code 1 -code error -level 0 -f ba}
+ 51 {-code 1 -code ok -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 52 {-code 1 -code boss -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 53 {-code 1 -code boss -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 54 {-code 1 -code 1 -level X -f ba snarf} {-code 1 -code 1 -level 0 -f ba snarf}
+ 55 {-code 1 -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 56 {-code 1 -code error -level X -f ba snarf} {-code 1 -code error -level 0 -f ba snarf}
+ 57 {-code 1 -code ok -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 58 {-code 1 -code boss -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 59 {-code 1 -code 1 -level X -f ba} {-code 1 -code 1 -level 0 -f ba}
+ 60 {-code 1 -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ 61 {-code 1 -code error -level X -f ba} {-code 1 -code error -level 0 -f ba}
+ 62 {-code 1 -code ok -level X -f ba} {-code 1 -level 0 -f ba}
+ 63 {-code 1 -code boss -level X -f ba} {-code 1 -level 0 -f ba}
+
+ 64 {-code 0 -code 1 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 65 {-code 0 -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 66 {-code 0 -code 1 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 67 {-code 0 -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 68 {-code 0 -code error -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 69 {-code 0 -code ok -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 70 {-code 0 -code error -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 71 {-code 0 -code ok -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 72 {-code 0 -code boss -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 73 {-code 0 -code boss -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 74 {-code 0 -code 1 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 75 {-code 0 -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 76 {-code 0 -code 1 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 77 {-code 0 -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 78 {-code 0 -code error -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 79 {-code 0 -code ok -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 80 {-code 0 -code error -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 81 {-code 0 -code ok -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 82 {-code 0 -code boss -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 83 {-code 0 -code boss -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 84 {-code 0 -code 1 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 85 {-code 0 -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 86 {-code 0 -code error -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 87 {-code 0 -code ok -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 88 {-code 0 -code boss -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 89 {-code 0 -code 1 -level X -f ba} {-code 1 -level 0 -f ba}
+ 90 {-code 0 -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ 91 {-code 0 -code error -level X -f ba} {-code 1 -level 0 -f ba}
+ 92 {-code 0 -code ok -level X -f ba} {-code 1 -level 0 -f ba}
+ 93 {-code 0 -code boss -level X -f ba} {-code 1 -level 0 -f ba}
+
+ 94 {-code 1 -code 1 -level 0 -f ba snarf} {-code 1 -code 1 -level 0 -f ba snarf}
+ 95 {-code 0 -code 1 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 96 {-code 1 -code 1 -level 5 -f ba snarf} {-code 1 -code 1 -level 0 -f ba snarf}
+ 97 {-code 0 -code 1 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 98 {-code error -code 1 -level 0 -f ba snarf} {-code error -code 1 -level 0 -f ba snarf}
+ 99 {-code ok -code 1 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ a0 {-code error -code 1 -level 5 -f ba snarf} {-code error -code 1 -level 0 -f ba snarf}
+ a1 {-code ok -code 1 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ a2 {-code boss -code 1 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ a3 {-code boss -code 1 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ a4 {-code 1 -code 1 -level 0 -f ba} {-code 1 -code 1 -level 0 -f ba}
+ a5 {-code 0 -code 1 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ a6 {-code 1 -code 1 -level 5 -f ba} {-code 1 -code 1 -level 0 -f ba}
+ a7 {-code 0 -code 1 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ a8 {-code error -code 1 -level 0 -f ba} {-code error -code 1 -level 0 -f ba}
+ a9 {-code ok -code 1 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ b0 {-code error -code 1 -level 5 -f ba} {-code error -code 1 -level 0 -f ba}
+ b1 {-code ok -code 1 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ b2 {-code boss -code 1 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ b3 {-code boss -code 1 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ b4 {-code 1 -code 1 -level X -f ba snarf} {-code 1 -code 1 -level 0 -f ba snarf}
+ b5 {-code 0 -code 1 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ b6 {-code error -code 1 -level X -f ba snarf} {-code error -code 1 -level 0 -f ba snarf}
+ b7 {-code ok -code 1 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ b8 {-code boss -code 1 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ b9 {-code 1 -code 1 -level X -f ba} {-code 1 -code 1 -level 0 -f ba}
+ c0 {-code 0 -code 1 -level X -f ba} {-code 1 -level 0 -f ba}
+ c1 {-code error -code 1 -level X -f ba} {-code error -code 1 -level 0 -f ba}
+ c2 {-code ok -code 1 -level X -f ba} {-code 1 -level 0 -f ba}
+ c3 {-code boss -code 1 -level X -f ba} {-code 1 -level 0 -f ba}
+
+ c4 {-code 1 -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ c5 {-code 0 -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ c6 {-code 1 -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ c7 {-code 0 -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ c8 {-code error -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ c9 {-code ok -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ d0 {-code error -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ d1 {-code ok -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ d2 {-code boss -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ d3 {-code boss -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ d4 {-code 1 -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ d5 {-code 0 -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ d6 {-code 1 -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ d7 {-code 0 -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ d8 {-code error -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ d9 {-code ok -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ e0 {-code error -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ e1 {-code ok -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ e2 {-code boss -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ e3 {-code boss -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ e4 {-code 1 -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ e5 {-code 0 -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ e6 {-code error -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ e7 {-code ok -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ e8 {-code boss -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ e9 {-code 1 -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ f0 {-code 0 -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ f1 {-code error -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ f2 {-code ok -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ f3 {-code boss -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+} {
+ test chan-io-71.$n {Tcl_SetChannelError} {testchannel} {
+
+ set f [makeFile {... dummy ...} cutsplice]
+ set c [open $f r]
+
+ set res [testchannel setchannelerror $c [lrange $msg 0 end]]
+ chan close $c
+ removeFile cutsplice
+
+ set res
+ } [lrange $expected 0 end]
+
+ test chan-io-72.$n {Tcl_SetChannelErrorInterp} {testchannel} {
+
+ set f [makeFile {... dummy ...} cutsplice]
+ set c [open $f r]
+
+ set res [testchannel setchannelerrorinterp $c [lrange $msg 0 end]]
+ chan close $c
+ removeFile cutsplice
+
+ set res
+ } [lrange $expected 0 end]
+}
+
+test chan-io-73.1 {channel Tcl_Obj SetChannelFromAny} {} {
+ # Test for Bug 1847044 - don't spoil type unless we have a valid channel
+ catch {chan close [lreplace [list a] 0 end]}
+} {1}
+
+# ### ### ### ######### ######### #########
+
+# cleanup
+foreach file [list fooBar longfile script output test1 pipe my_script \
+ test2 test3 cat stdout kyrillic.txt utf8-fcopy.txt utf8-rp.txt] {
+ removeFile $file
+}
+cleanupTests
+}
+namespace delete ::tcl::test::io
diff --git a/tests/clock.test b/tests/clock.test
index a7476d2..7937933 100644
--- a/tests/clock.test
+++ b/tests/clock.test
@@ -1,230 +1,35650 @@
-# Commands covered: clock
+# clock.test --
+#
+# This test file covers the 'clock' command that manipulates time.
#
# This file contains a collection of tests for one or more of the Tcl
-# built-in commands. Sourcing this file into Tcl runs the tests and
+# built-in commands. Sourcing this file into Tcl runs the tests and
# generates output for errors. No output means no errors were found.
#
-# Copyright (c) 1995-1998 Sun Microsystems, Inc.
-# Copyright (c) 1998-1999 by Scriptics Corporation.
+# Copyright (c) 2004 by Kevin B. Kenny. All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-set env(LC_TIME) POSIX
-
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2
namespace import -force ::tcltest::*
}
-test clock-1.1 {clock tests} {
- list [catch {clock} msg] $msg
-} {1 {wrong # args: should be "clock option ?arg ...?"}}
-test clock-1.2 {clock tests} {
- list [catch {clock foo} msg] $msg
-} {1 {bad option "foo": must be clicks, format, scan, or seconds}}
+if {[testConstraint win]} {
+ if {[catch {package require registry 1.1}]
+ && [catch {load {} Registry}]
+ && [catch {
+ ::tcltest::loadTestedCommands
+ load $::reglib Registry
+ }]} {
+ namespace eval ::tcl::clock {variable NoRegistry {}}
+ }
+}
+
+package require msgcat 1.4
+
+testConstraint detroit \
+ [expr {![catch {clock format 0 -timezone :America/Detroit -format %z}]}]
+testConstraint y2038 \
+ [expr {[clock format 2158894800 -format %z -timezone :America/Detroit] eq {-0400}}]
+
+# TEST PLAN
+
+# clock-1:
+# [clock format] - tests of bad and empty arguments
+#
+# clock-2
+# formatting of year, month and day of month
+#
+# clock-3
+# formatting of fiscal year, fiscal week and day of week.
+#
+# clock-4
+# formatting of time of day.
+#
+# clock-5
+# handling of Daylight Saving Time in a known locale, formatting of
+# %z and %Z
+#
+# clock-6
+# input conversion - seconds
+#
+# clock-7
+# input conversion - Julian Day
+#
+# clock-8
+# input conversion - ccyymmdd
+#
+# clock-9
+# input conversion - ccyymmdd (test that %s and %J take precedence)
+#
+# clock-10
+# input conversion - ccyyddd
+#
+# clock-11
+# input conversion - relative precedence of ccyyddd and ccyymmdd
+# (tests the 'rightmost field' comparison)
+#
+# clock-12
+# input conversion - ccyyWwwd
+#
+# clock-13
+# input conversion - ccyyWwwd (test that %s and %J take precedence,
+# and that invalid days are rejected).
+#
+# clock-14
+# input conversion - yymmdd
+#
+# clock-15
+# precedence - yymmdd
+#
+# clock-16
+# input conversion and precedence - yyddd
+#
+# clock-17
+# input conversion - yyWwwd
+#
+# clock-18
+# precedence - yyWwwd
+#
+# clock-19
+# input conversion - mmdd
+#
+# clock-20
+# precedence - mmdd
+#
+# clock-21
+# input conversion and precedence - ddd
+#
+# clock-22
+# input conversion - Wwwd
+#
+# clock-23
+# precedence - Wwwd
+#
+# clock-24
+# input conversion - naked day of month
+#
+# clock-25
+# precedence - naked day of month
+#
+# clock-26
+# input conversion - naked day of week
+#
+# clock-27
+# precedence - day of week
+#
+# clock-28
+# scan with empty -format is midnight of base date
+#
+# clock-29
+# scanning of all time-of-day formats
+#
+# clock-30
+# [clock add]
+#
+# clock-31
+# Use of -locale system on Windows
+#
+# clock-32
+# Handling of the Julian-Gregorian transition
+#
+# clock-33
+# Legacy tests - [clock clicks]
+#
+# clock-34
+# Legacy tests - [clock scan] without -format
+#
+# clock-35
+# Legacy tests - [clock seconds]
+#
+# clock-36
+# Legacy tests - [clock scan] with 'next monthname'
+#
+# clock-37
+# Test that -gmt does not affect the value of %s
+#
+# clock-38
+# Regression test to verify that changes in TZ work
+# both east and west of Greenwich
+
+
+# Note that all code between comments '# BEGIN' and '# END' is
+# autogenerated by 'tools/makeTestCases.tcl'. DO NOT EDIT CODE BETWEEN
+# '# BEGIN' and '# END'.
+
+# Define a fictitious locale, 'en_US_roman', for formatting of clock
+# strings with localized numerics and eras. This locale will be used
+# in testing the 'clock' command.
+
+namespace eval ::tcl::clock {
+ ::msgcat::mcmset en_US_roman {
+ LOCALE_ERAS {
+ {-62164627200 {} 0}
+ {-59008867200 c 100}
+ {-55853107200 cc 200}
+ {-52697347200 ccc 300}
+ {-49541587200 cd 400}
+ {-46385827200 d 500}
+ {-43230067200 dc 600}
+ {-40074307200 dcc 700}
+ {-36918547200 dccc 800}
+ {-33762787200 cm 900}
+ {-30607027200 m 1000}
+ {-27451267200 mc 1100}
+ {-24295507200 mcc 1200}
+ {-21139747200 mccc 1300}
+ {-17983987200 mcd 1400}
+ {-14828227200 md 1500}
+ {-11672467200 mdc 1600}
+ {-8516707200 mdcc 1700}
+ {-5364662400 mdccc 1800}
+ {-2208988800 mcm 1900}
+ {946684800 mm 2000}
+ }
+ LOCALE_NUMERALS {
+ ? i ii iii iv v vi vii viii ix
+ x xi xii xiii xiv xv xvi xvii xviii xix
+ xx xxi xxii xxiii xxiv xxv xxvi xxvii xxviii xxix
+ xxx xxxi xxxii xxxiii xxxiv xxxv xxxvi xxxvii xxxviii xxxix
+ xl xli xlii xliii xliv xlv xlvi xlvii xlviii xlix
+ l li lii liii liv lv lvi lvii lviii lix
+ lx lxi lxii lxiii lxiv lxv lxvi lxvii lxviii lxix
+ lxx lxxi lxxii lxxiii lxxiv lxxv lxxvi lxxvii lxxviii lxxix
+ lxxx lxxxi lxxxii lxxxiii lxxxiv lxxxv lxxxvi lxxxvii lxxxviii
+ lxxxix
+ xc xci xcii xciii xciv xcv xcvi xcvii xcviii xcix
+ c
+ }
+ DATE_FORMAT {%m/%d/%Y}
+ TIME_FORMAT {%H:%M:%S}
+ DATE_TIME_FORMAT {%x %X}
+ LOCALE_DATE_FORMAT {die %Od mensis %Om annoque %EY}
+ LOCALE_TIME_FORMAT {%OH h %OM m %OS s}
+ LOCALE_DATE_TIME_FORMAT {%Ex %EX}
+ BCE {Before Christ}
+ CE {Anno Domini}
+ }
+}
+
+#----------------------------------------------------------------------
+#
+# The tests for the Windows platform are careful *not* to muck with
+# the system registry. Instead, the 'registry' command is overridden
+# in the '::tcl::clock' namespace.
+#
+#----------------------------------------------------------------------
+
+namespace eval ::testClock {
+ namespace export registry
+ set reg \
+ [dict create \
+ HKEY_CURRENT_USER\\Control\ Panel\\International \
+ [dict create \
+ locale 0409 \
+ sShortDate dd-MMM-yyyy \
+ sLongDate "'the' dd''' day of' MMMM yyyy" \
+ sTimeFormat "h:mm:ss tt"] \
+ HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\TimeZoneInformation \
+ [dict create \
+ Bias 300 \
+ StandardBias 0 \
+ DaylightBias -60 \
+ StandardStart \x00\x00\x0b\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00 \
+ DaylightStart \x00\x00\x03\x00\x02\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00]]
+}
+
+
+proc ::testClock::registry { cmd path key } {
+ variable reg
+ if { $cmd ne {get} } {
+ return -code error "test case attempts to write/query the registry"
+ }
+ if { ![dict exists $reg $path $key] } {
+ return -code error "test case attempts to read unknown registry entry $path $key"
+ }
+ return [dict get $reg $path $key]
+}
+
+# Test some of the basics of [clock format]
+
+test clock-1.0 "clock format - wrong # args" {
+ list [catch {clock format} msg] $msg $::errorCode
+} {1 {wrong # args: should be "clock format clockval ?-format string? ?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?"} {CLOCK wrongNumArgs}}
+
+test clock-1.1 "clock format - bad time" {
+ list [catch {clock format foo} msg] $msg
+} {1 {expected integer but got "foo"}}
+
+test clock-1.2 "clock format - bad gmt val" {
+ list [catch {clock format 0 -gmt foo} msg] $msg
+} {1 {expected boolean value but got "foo"}}
+
+test clock-1.3 "clock format - empty val" {
+ clock format 0 -gmt 1 -format ""
+} {}
+
+test clock-1.4 "clock format - bad flag" {*}{
+ -body {
+ list [catch {clock format 0 -oops badflag} msg] $msg $::errorCode
+ }
+ -match glob
+ -result {1 {bad switch "-oops": must be -format, -gmt, -locale, or -timezone} {CLOCK badSwitch -oops}}
+}
+
+test clock-1.5 "clock format - bad timezone" {
+ list [catch {clock format 0 -format "%s" -timezone :NOWHERE} msg] $msg $::errorCode
+} {1 {time zone ":NOWHERE" not found} {CLOCK badTimeZone :NOWHERE}}
+
+test clock-1.6 "clock format - gmt + timezone" {
+ list [catch {clock format 0 -timezone :GMT -gmt true} msg] $msg $::errorCode
+} {1 {cannot use -gmt and -timezone in same call} {CLOCK gmtWithTimezone}}
+
+test clock-1.7 "clock format - option abbreviations" {
+ clock format 0 -g true -f "%Y-%m-%d"
+} 1970-01-01
+
+# BEGIN testcases2
+
+# Test formatting of Gregorian year, month, day, all formats
+# Formats tested: %b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y %EY
+
+test clock-2.1 {conversion of 1872-01-01} {
+ clock format -3092556304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1872 12:34:56 die i mensis i annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jan 001 2404794 01 i 1 01/01/1872 die i mensis i annoque mdccclxxii 72 lxxii 1872}
+test clock-2.2 {conversion of 1872-01-31} {
+ clock format -3089964304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1872 12:34:56 die xxxi mensis i annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jan 031 2404824 01 i 1 01/31/1872 die xxxi mensis i annoque mdccclxxii 72 lxxii 1872}
+test clock-2.3 {conversion of 1872-02-01} {
+ clock format -3089877904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1872 12:34:56 die i mensis ii annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Feb 032 2404825 02 ii 2 02/01/1872 die i mensis ii annoque mdccclxxii 72 lxxii 1872}
+test clock-2.4 {conversion of 1872-02-29} {
+ clock format -3087458704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1872 12:34:56 die xxix mensis ii annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 29 xxix 29 xxix Feb 060 2404853 02 ii 2 02/29/1872 die xxix mensis ii annoque mdccclxxii 72 lxxii 1872}
+test clock-2.5 {conversion of 1872-03-01} {
+ clock format -3087372304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1872 12:34:56 die i mensis iii annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Mar 061 2404854 03 iii 3 03/01/1872 die i mensis iii annoque mdccclxxii 72 lxxii 1872}
+test clock-2.6 {conversion of 1872-03-31} {
+ clock format -3084780304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1872 12:34:56 die xxxi mensis iii annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Mar 091 2404884 03 iii 3 03/31/1872 die xxxi mensis iii annoque mdccclxxii 72 lxxii 1872}
+test clock-2.7 {conversion of 1872-04-01} {
+ clock format -3084693904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1872 12:34:56 die i mensis iv annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Apr 092 2404885 04 iv 4 04/01/1872 die i mensis iv annoque mdccclxxii 72 lxxii 1872}
+test clock-2.8 {conversion of 1872-04-30} {
+ clock format -3082188304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1872 12:34:56 die xxx mensis iv annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Apr 121 2404914 04 iv 4 04/30/1872 die xxx mensis iv annoque mdccclxxii 72 lxxii 1872}
+test clock-2.9 {conversion of 1872-05-01} {
+ clock format -3082101904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1872 12:34:56 die i mensis v annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 01 i 1 i May 122 2404915 05 v 5 05/01/1872 die i mensis v annoque mdccclxxii 72 lxxii 1872}
+test clock-2.10 {conversion of 1872-05-31} {
+ clock format -3079509904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1872 12:34:56 die xxxi mensis v annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi May 152 2404945 05 v 5 05/31/1872 die xxxi mensis v annoque mdccclxxii 72 lxxii 1872}
+test clock-2.11 {conversion of 1872-06-01} {
+ clock format -3079423504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1872 12:34:56 die i mensis vi annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jun 153 2404946 06 vi 6 06/01/1872 die i mensis vi annoque mdccclxxii 72 lxxii 1872}
+test clock-2.12 {conversion of 1872-06-30} {
+ clock format -3076917904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1872 12:34:56 die xxx mensis vi annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Jun 182 2404975 06 vi 6 06/30/1872 die xxx mensis vi annoque mdccclxxii 72 lxxii 1872}
+test clock-2.13 {conversion of 1872-07-01} {
+ clock format -3076831504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1872 12:34:56 die i mensis vii annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jul 183 2404976 07 vii 7 07/01/1872 die i mensis vii annoque mdccclxxii 72 lxxii 1872}
+test clock-2.14 {conversion of 1872-07-31} {
+ clock format -3074239504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1872 12:34:56 die xxxi mensis vii annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jul 213 2405006 07 vii 7 07/31/1872 die xxxi mensis vii annoque mdccclxxii 72 lxxii 1872}
+test clock-2.15 {conversion of 1872-08-01} {
+ clock format -3074153104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1872 12:34:56 die i mensis viii annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Aug 214 2405007 08 viii 8 08/01/1872 die i mensis viii annoque mdccclxxii 72 lxxii 1872}
+test clock-2.16 {conversion of 1872-08-31} {
+ clock format -3071561104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1872 12:34:56 die xxxi mensis viii annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Aug 244 2405037 08 viii 8 08/31/1872 die xxxi mensis viii annoque mdccclxxii 72 lxxii 1872}
+test clock-2.17 {conversion of 1872-09-01} {
+ clock format -3071474704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1872 12:34:56 die i mensis ix annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Sep 245 2405038 09 ix 9 09/01/1872 die i mensis ix annoque mdccclxxii 72 lxxii 1872}
+test clock-2.18 {conversion of 1872-09-30} {
+ clock format -3068969104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1872 12:34:56 die xxx mensis ix annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Sep 274 2405067 09 ix 9 09/30/1872 die xxx mensis ix annoque mdccclxxii 72 lxxii 1872}
+test clock-2.19 {conversion of 1872-10-01} {
+ clock format -3068882704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1872 12:34:56 die i mensis x annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Oct 275 2405068 10 x 10 10/01/1872 die i mensis x annoque mdccclxxii 72 lxxii 1872}
+test clock-2.20 {conversion of 1872-10-31} {
+ clock format -3066290704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1872 12:34:56 die xxxi mensis x annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Oct 305 2405098 10 x 10 10/31/1872 die xxxi mensis x annoque mdccclxxii 72 lxxii 1872}
+test clock-2.21 {conversion of 1872-11-01} {
+ clock format -3066204304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1872 12:34:56 die i mensis xi annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Nov 306 2405099 11 xi 11 11/01/1872 die i mensis xi annoque mdccclxxii 72 lxxii 1872}
+test clock-2.22 {conversion of 1872-11-30} {
+ clock format -3063698704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1872 12:34:56 die xxx mensis xi annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Nov 335 2405128 11 xi 11 11/30/1872 die xxx mensis xi annoque mdccclxxii 72 lxxii 1872}
+test clock-2.23 {conversion of 1872-12-01} {
+ clock format -3063612304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1872 12:34:56 die i mensis xii annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Dec 336 2405129 12 xii 12 12/01/1872 die i mensis xii annoque mdccclxxii 72 lxxii 1872}
+test clock-2.24 {conversion of 1872-12-31} {
+ clock format -3061020304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1872 12:34:56 die xxxi mensis xii annoque mdccclxxii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Dec 366 2405159 12 xii 12 12/31/1872 die xxxi mensis xii annoque mdccclxxii 72 lxxii 1872}
+test clock-2.25 {conversion of 1873-01-01} {
+ clock format -3060933904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1873 12:34:56 die i mensis i annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jan 001 2405160 01 i 1 01/01/1873 die i mensis i annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.26 {conversion of 1873-01-31} {
+ clock format -3058341904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1873 12:34:56 die xxxi mensis i annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jan 031 2405190 01 i 1 01/31/1873 die xxxi mensis i annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.27 {conversion of 1873-02-01} {
+ clock format -3058255504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1873 12:34:56 die i mensis ii annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Feb 032 2405191 02 ii 2 02/01/1873 die i mensis ii annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.28 {conversion of 1873-02-28} {
+ clock format -3055922704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1873 12:34:56 die xxviii mensis ii annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 28 xxviii 28 xxviii Feb 059 2405218 02 ii 2 02/28/1873 die xxviii mensis ii annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.29 {conversion of 1873-03-01} {
+ clock format -3055836304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1873 12:34:56 die i mensis iii annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Mar 060 2405219 03 iii 3 03/01/1873 die i mensis iii annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.30 {conversion of 1873-03-31} {
+ clock format -3053244304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1873 12:34:56 die xxxi mensis iii annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Mar 090 2405249 03 iii 3 03/31/1873 die xxxi mensis iii annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.31 {conversion of 1873-04-01} {
+ clock format -3053157904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1873 12:34:56 die i mensis iv annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Apr 091 2405250 04 iv 4 04/01/1873 die i mensis iv annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.32 {conversion of 1873-04-30} {
+ clock format -3050652304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1873 12:34:56 die xxx mensis iv annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Apr 120 2405279 04 iv 4 04/30/1873 die xxx mensis iv annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.33 {conversion of 1873-05-01} {
+ clock format -3050565904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1873 12:34:56 die i mensis v annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 01 i 1 i May 121 2405280 05 v 5 05/01/1873 die i mensis v annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.34 {conversion of 1873-05-31} {
+ clock format -3047973904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1873 12:34:56 die xxxi mensis v annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi May 151 2405310 05 v 5 05/31/1873 die xxxi mensis v annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.35 {conversion of 1873-06-01} {
+ clock format -3047887504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1873 12:34:56 die i mensis vi annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jun 152 2405311 06 vi 6 06/01/1873 die i mensis vi annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.36 {conversion of 1873-06-30} {
+ clock format -3045381904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1873 12:34:56 die xxx mensis vi annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Jun 181 2405340 06 vi 6 06/30/1873 die xxx mensis vi annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.37 {conversion of 1873-07-01} {
+ clock format -3045295504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1873 12:34:56 die i mensis vii annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jul 182 2405341 07 vii 7 07/01/1873 die i mensis vii annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.38 {conversion of 1873-07-31} {
+ clock format -3042703504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1873 12:34:56 die xxxi mensis vii annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jul 212 2405371 07 vii 7 07/31/1873 die xxxi mensis vii annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.39 {conversion of 1873-08-01} {
+ clock format -3042617104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1873 12:34:56 die i mensis viii annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Aug 213 2405372 08 viii 8 08/01/1873 die i mensis viii annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.40 {conversion of 1873-08-31} {
+ clock format -3040025104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1873 12:34:56 die xxxi mensis viii annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Aug 243 2405402 08 viii 8 08/31/1873 die xxxi mensis viii annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.41 {conversion of 1873-09-01} {
+ clock format -3039938704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1873 12:34:56 die i mensis ix annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Sep 244 2405403 09 ix 9 09/01/1873 die i mensis ix annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.42 {conversion of 1873-09-30} {
+ clock format -3037433104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1873 12:34:56 die xxx mensis ix annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Sep 273 2405432 09 ix 9 09/30/1873 die xxx mensis ix annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.43 {conversion of 1873-10-01} {
+ clock format -3037346704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1873 12:34:56 die i mensis x annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Oct 274 2405433 10 x 10 10/01/1873 die i mensis x annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.44 {conversion of 1873-10-31} {
+ clock format -3034754704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1873 12:34:56 die xxxi mensis x annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Oct 304 2405463 10 x 10 10/31/1873 die xxxi mensis x annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.45 {conversion of 1873-11-01} {
+ clock format -3034668304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1873 12:34:56 die i mensis xi annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Nov 305 2405464 11 xi 11 11/01/1873 die i mensis xi annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.46 {conversion of 1873-11-30} {
+ clock format -3032162704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1873 12:34:56 die xxx mensis xi annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Nov 334 2405493 11 xi 11 11/30/1873 die xxx mensis xi annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.47 {conversion of 1873-12-01} {
+ clock format -3032076304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1873 12:34:56 die i mensis xii annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Dec 335 2405494 12 xii 12 12/01/1873 die i mensis xii annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.48 {conversion of 1873-12-31} {
+ clock format -3029484304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1873 12:34:56 die xxxi mensis xii annoque mdccclxxiii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Dec 365 2405524 12 xii 12 12/31/1873 die xxxi mensis xii annoque mdccclxxiii 73 lxxiii 1873}
+test clock-2.49 {conversion of 1876-01-01} {
+ clock format -2966325904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1876 12:34:56 die i mensis i annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jan 001 2406255 01 i 1 01/01/1876 die i mensis i annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.50 {conversion of 1876-01-31} {
+ clock format -2963733904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1876 12:34:56 die xxxi mensis i annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jan 031 2406285 01 i 1 01/31/1876 die xxxi mensis i annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.51 {conversion of 1876-02-01} {
+ clock format -2963647504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1876 12:34:56 die i mensis ii annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Feb 032 2406286 02 ii 2 02/01/1876 die i mensis ii annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.52 {conversion of 1876-02-29} {
+ clock format -2961228304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1876 12:34:56 die xxix mensis ii annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 29 xxix 29 xxix Feb 060 2406314 02 ii 2 02/29/1876 die xxix mensis ii annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.53 {conversion of 1876-03-01} {
+ clock format -2961141904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1876 12:34:56 die i mensis iii annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Mar 061 2406315 03 iii 3 03/01/1876 die i mensis iii annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.54 {conversion of 1876-03-31} {
+ clock format -2958549904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1876 12:34:56 die xxxi mensis iii annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Mar 091 2406345 03 iii 3 03/31/1876 die xxxi mensis iii annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.55 {conversion of 1876-04-01} {
+ clock format -2958463504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1876 12:34:56 die i mensis iv annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Apr 092 2406346 04 iv 4 04/01/1876 die i mensis iv annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.56 {conversion of 1876-04-30} {
+ clock format -2955957904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1876 12:34:56 die xxx mensis iv annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Apr 121 2406375 04 iv 4 04/30/1876 die xxx mensis iv annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.57 {conversion of 1876-05-01} {
+ clock format -2955871504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1876 12:34:56 die i mensis v annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i May 122 2406376 05 v 5 05/01/1876 die i mensis v annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.58 {conversion of 1876-05-31} {
+ clock format -2953279504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1876 12:34:56 die xxxi mensis v annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi May 152 2406406 05 v 5 05/31/1876 die xxxi mensis v annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.59 {conversion of 1876-06-01} {
+ clock format -2953193104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1876 12:34:56 die i mensis vi annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jun 153 2406407 06 vi 6 06/01/1876 die i mensis vi annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.60 {conversion of 1876-06-30} {
+ clock format -2950687504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1876 12:34:56 die xxx mensis vi annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Jun 182 2406436 06 vi 6 06/30/1876 die xxx mensis vi annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.61 {conversion of 1876-07-01} {
+ clock format -2950601104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1876 12:34:56 die i mensis vii annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jul 183 2406437 07 vii 7 07/01/1876 die i mensis vii annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.62 {conversion of 1876-07-31} {
+ clock format -2948009104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1876 12:34:56 die xxxi mensis vii annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jul 213 2406467 07 vii 7 07/31/1876 die xxxi mensis vii annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.63 {conversion of 1876-08-01} {
+ clock format -2947922704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1876 12:34:56 die i mensis viii annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Aug 214 2406468 08 viii 8 08/01/1876 die i mensis viii annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.64 {conversion of 1876-08-31} {
+ clock format -2945330704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1876 12:34:56 die xxxi mensis viii annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Aug 244 2406498 08 viii 8 08/31/1876 die xxxi mensis viii annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.65 {conversion of 1876-09-01} {
+ clock format -2945244304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1876 12:34:56 die i mensis ix annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Sep 245 2406499 09 ix 9 09/01/1876 die i mensis ix annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.66 {conversion of 1876-09-30} {
+ clock format -2942738704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1876 12:34:56 die xxx mensis ix annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Sep 274 2406528 09 ix 9 09/30/1876 die xxx mensis ix annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.67 {conversion of 1876-10-01} {
+ clock format -2942652304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1876 12:34:56 die i mensis x annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Oct 275 2406529 10 x 10 10/01/1876 die i mensis x annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.68 {conversion of 1876-10-31} {
+ clock format -2940060304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1876 12:34:56 die xxxi mensis x annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Oct 305 2406559 10 x 10 10/31/1876 die xxxi mensis x annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.69 {conversion of 1876-11-01} {
+ clock format -2939973904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1876 12:34:56 die i mensis xi annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Nov 306 2406560 11 xi 11 11/01/1876 die i mensis xi annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.70 {conversion of 1876-11-30} {
+ clock format -2937468304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1876 12:34:56 die xxx mensis xi annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Nov 335 2406589 11 xi 11 11/30/1876 die xxx mensis xi annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.71 {conversion of 1876-12-01} {
+ clock format -2937381904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1876 12:34:56 die i mensis xii annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Dec 336 2406590 12 xii 12 12/01/1876 die i mensis xii annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.72 {conversion of 1876-12-31} {
+ clock format -2934789904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1876 12:34:56 die xxxi mensis xii annoque mdccclxxvi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Dec 366 2406620 12 xii 12 12/31/1876 die xxxi mensis xii annoque mdccclxxvi 76 lxxvi 1876}
+test clock-2.73 {conversion of 1877-01-01} {
+ clock format -2934703504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1877 12:34:56 die i mensis i annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jan 001 2406621 01 i 1 01/01/1877 die i mensis i annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.74 {conversion of 1877-01-31} {
+ clock format -2932111504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1877 12:34:56 die xxxi mensis i annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jan 031 2406651 01 i 1 01/31/1877 die xxxi mensis i annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.75 {conversion of 1877-02-01} {
+ clock format -2932025104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1877 12:34:56 die i mensis ii annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Feb 032 2406652 02 ii 2 02/01/1877 die i mensis ii annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.76 {conversion of 1877-02-28} {
+ clock format -2929692304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1877 12:34:56 die xxviii mensis ii annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 28 xxviii 28 xxviii Feb 059 2406679 02 ii 2 02/28/1877 die xxviii mensis ii annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.77 {conversion of 1877-03-01} {
+ clock format -2929605904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1877 12:34:56 die i mensis iii annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Mar 060 2406680 03 iii 3 03/01/1877 die i mensis iii annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.78 {conversion of 1877-03-31} {
+ clock format -2927013904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1877 12:34:56 die xxxi mensis iii annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Mar 090 2406710 03 iii 3 03/31/1877 die xxxi mensis iii annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.79 {conversion of 1877-04-01} {
+ clock format -2926927504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1877 12:34:56 die i mensis iv annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Apr 091 2406711 04 iv 4 04/01/1877 die i mensis iv annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.80 {conversion of 1877-04-30} {
+ clock format -2924421904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1877 12:34:56 die xxx mensis iv annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Apr 120 2406740 04 iv 4 04/30/1877 die xxx mensis iv annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.81 {conversion of 1877-05-01} {
+ clock format -2924335504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1877 12:34:56 die i mensis v annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i May 121 2406741 05 v 5 05/01/1877 die i mensis v annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.82 {conversion of 1877-05-31} {
+ clock format -2921743504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1877 12:34:56 die xxxi mensis v annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi May 151 2406771 05 v 5 05/31/1877 die xxxi mensis v annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.83 {conversion of 1877-06-01} {
+ clock format -2921657104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1877 12:34:56 die i mensis vi annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jun 152 2406772 06 vi 6 06/01/1877 die i mensis vi annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.84 {conversion of 1877-06-30} {
+ clock format -2919151504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1877 12:34:56 die xxx mensis vi annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Jun 181 2406801 06 vi 6 06/30/1877 die xxx mensis vi annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.85 {conversion of 1877-07-01} {
+ clock format -2919065104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1877 12:34:56 die i mensis vii annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jul 182 2406802 07 vii 7 07/01/1877 die i mensis vii annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.86 {conversion of 1877-07-31} {
+ clock format -2916473104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1877 12:34:56 die xxxi mensis vii annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jul 212 2406832 07 vii 7 07/31/1877 die xxxi mensis vii annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.87 {conversion of 1877-08-01} {
+ clock format -2916386704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1877 12:34:56 die i mensis viii annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Aug 213 2406833 08 viii 8 08/01/1877 die i mensis viii annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.88 {conversion of 1877-08-31} {
+ clock format -2913794704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1877 12:34:56 die xxxi mensis viii annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Aug 243 2406863 08 viii 8 08/31/1877 die xxxi mensis viii annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.89 {conversion of 1877-09-01} {
+ clock format -2913708304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1877 12:34:56 die i mensis ix annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Sep 244 2406864 09 ix 9 09/01/1877 die i mensis ix annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.90 {conversion of 1877-09-30} {
+ clock format -2911202704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1877 12:34:56 die xxx mensis ix annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Sep 273 2406893 09 ix 9 09/30/1877 die xxx mensis ix annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.91 {conversion of 1877-10-01} {
+ clock format -2911116304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1877 12:34:56 die i mensis x annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Oct 274 2406894 10 x 10 10/01/1877 die i mensis x annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.92 {conversion of 1877-10-31} {
+ clock format -2908524304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1877 12:34:56 die xxxi mensis x annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Oct 304 2406924 10 x 10 10/31/1877 die xxxi mensis x annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.93 {conversion of 1877-11-01} {
+ clock format -2908437904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1877 12:34:56 die i mensis xi annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Nov 305 2406925 11 xi 11 11/01/1877 die i mensis xi annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.94 {conversion of 1877-11-30} {
+ clock format -2905932304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1877 12:34:56 die xxx mensis xi annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Nov 334 2406954 11 xi 11 11/30/1877 die xxx mensis xi annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.95 {conversion of 1877-12-01} {
+ clock format -2905845904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1877 12:34:56 die i mensis xii annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Dec 335 2406955 12 xii 12 12/01/1877 die i mensis xii annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.96 {conversion of 1877-12-31} {
+ clock format -2903253904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1877 12:34:56 die xxxi mensis xii annoque mdccclxxvii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Dec 365 2406985 12 xii 12 12/31/1877 die xxxi mensis xii annoque mdccclxxvii 77 lxxvii 1877}
+test clock-2.97 {conversion of 1880-01-01} {
+ clock format -2840095504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1880 12:34:56 die i mensis i annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jan 001 2407716 01 i 1 01/01/1880 die i mensis i annoque mdccclxxx 80 lxxx 1880}
+test clock-2.98 {conversion of 1880-01-31} {
+ clock format -2837503504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1880 12:34:56 die xxxi mensis i annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jan 031 2407746 01 i 1 01/31/1880 die xxxi mensis i annoque mdccclxxx 80 lxxx 1880}
+test clock-2.99 {conversion of 1880-02-01} {
+ clock format -2837417104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1880 12:34:56 die i mensis ii annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 01 i 1 i Feb 032 2407747 02 ii 2 02/01/1880 die i mensis ii annoque mdccclxxx 80 lxxx 1880}
+test clock-2.100 {conversion of 1880-02-29} {
+ clock format -2834997904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1880 12:34:56 die xxix mensis ii annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 29 xxix 29 xxix Feb 060 2407775 02 ii 2 02/29/1880 die xxix mensis ii annoque mdccclxxx 80 lxxx 1880}
+test clock-2.101 {conversion of 1880-03-01} {
+ clock format -2834911504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1880 12:34:56 die i mensis iii annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 01 i 1 i Mar 061 2407776 03 iii 3 03/01/1880 die i mensis iii annoque mdccclxxx 80 lxxx 1880}
+test clock-2.102 {conversion of 1880-03-31} {
+ clock format -2832319504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1880 12:34:56 die xxxi mensis iii annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Mar 091 2407806 03 iii 3 03/31/1880 die xxxi mensis iii annoque mdccclxxx 80 lxxx 1880}
+test clock-2.103 {conversion of 1880-04-01} {
+ clock format -2832233104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1880 12:34:56 die i mensis iv annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 01 i 1 i Apr 092 2407807 04 iv 4 04/01/1880 die i mensis iv annoque mdccclxxx 80 lxxx 1880}
+test clock-2.104 {conversion of 1880-04-30} {
+ clock format -2829727504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1880 12:34:56 die xxx mensis iv annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Apr 121 2407836 04 iv 4 04/30/1880 die xxx mensis iv annoque mdccclxxx 80 lxxx 1880}
+test clock-2.105 {conversion of 1880-05-01} {
+ clock format -2829641104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1880 12:34:56 die i mensis v annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 01 i 1 i May 122 2407837 05 v 5 05/01/1880 die i mensis v annoque mdccclxxx 80 lxxx 1880}
+test clock-2.106 {conversion of 1880-05-31} {
+ clock format -2827049104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1880 12:34:56 die xxxi mensis v annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi May 152 2407867 05 v 5 05/31/1880 die xxxi mensis v annoque mdccclxxx 80 lxxx 1880}
+test clock-2.107 {conversion of 1880-06-01} {
+ clock format -2826962704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1880 12:34:56 die i mensis vi annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jun 153 2407868 06 vi 6 06/01/1880 die i mensis vi annoque mdccclxxx 80 lxxx 1880}
+test clock-2.108 {conversion of 1880-06-30} {
+ clock format -2824457104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1880 12:34:56 die xxx mensis vi annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Jun 182 2407897 06 vi 6 06/30/1880 die xxx mensis vi annoque mdccclxxx 80 lxxx 1880}
+test clock-2.109 {conversion of 1880-07-01} {
+ clock format -2824370704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1880 12:34:56 die i mensis vii annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jul 183 2407898 07 vii 7 07/01/1880 die i mensis vii annoque mdccclxxx 80 lxxx 1880}
+test clock-2.110 {conversion of 1880-07-31} {
+ clock format -2821778704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1880 12:34:56 die xxxi mensis vii annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jul 213 2407928 07 vii 7 07/31/1880 die xxxi mensis vii annoque mdccclxxx 80 lxxx 1880}
+test clock-2.111 {conversion of 1880-08-01} {
+ clock format -2821692304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1880 12:34:56 die i mensis viii annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 01 i 1 i Aug 214 2407929 08 viii 8 08/01/1880 die i mensis viii annoque mdccclxxx 80 lxxx 1880}
+test clock-2.112 {conversion of 1880-08-31} {
+ clock format -2819100304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1880 12:34:56 die xxxi mensis viii annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Aug 244 2407959 08 viii 8 08/31/1880 die xxxi mensis viii annoque mdccclxxx 80 lxxx 1880}
+test clock-2.113 {conversion of 1880-09-01} {
+ clock format -2819013904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1880 12:34:56 die i mensis ix annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 01 i 1 i Sep 245 2407960 09 ix 9 09/01/1880 die i mensis ix annoque mdccclxxx 80 lxxx 1880}
+test clock-2.114 {conversion of 1880-09-30} {
+ clock format -2816508304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1880 12:34:56 die xxx mensis ix annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Sep 274 2407989 09 ix 9 09/30/1880 die xxx mensis ix annoque mdccclxxx 80 lxxx 1880}
+test clock-2.115 {conversion of 1880-10-01} {
+ clock format -2816421904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1880 12:34:56 die i mensis x annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 01 i 1 i Oct 275 2407990 10 x 10 10/01/1880 die i mensis x annoque mdccclxxx 80 lxxx 1880}
+test clock-2.116 {conversion of 1880-10-31} {
+ clock format -2813829904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1880 12:34:56 die xxxi mensis x annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Oct 305 2408020 10 x 10 10/31/1880 die xxxi mensis x annoque mdccclxxx 80 lxxx 1880}
+test clock-2.117 {conversion of 1880-11-01} {
+ clock format -2813743504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1880 12:34:56 die i mensis xi annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 01 i 1 i Nov 306 2408021 11 xi 11 11/01/1880 die i mensis xi annoque mdccclxxx 80 lxxx 1880}
+test clock-2.118 {conversion of 1880-11-30} {
+ clock format -2811237904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1880 12:34:56 die xxx mensis xi annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Nov 335 2408050 11 xi 11 11/30/1880 die xxx mensis xi annoque mdccclxxx 80 lxxx 1880}
+test clock-2.119 {conversion of 1880-12-01} {
+ clock format -2811151504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1880 12:34:56 die i mensis xii annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 01 i 1 i Dec 336 2408051 12 xii 12 12/01/1880 die i mensis xii annoque mdccclxxx 80 lxxx 1880}
+test clock-2.120 {conversion of 1880-12-31} {
+ clock format -2808559504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1880 12:34:56 die xxxi mensis xii annoque mdccclxxx xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Dec 366 2408081 12 xii 12 12/31/1880 die xxxi mensis xii annoque mdccclxxx 80 lxxx 1880}
+test clock-2.121 {conversion of 1881-01-01} {
+ clock format -2808473104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1881 12:34:56 die i mensis i annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jan 001 2408082 01 i 1 01/01/1881 die i mensis i annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.122 {conversion of 1881-01-31} {
+ clock format -2805881104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1881 12:34:56 die xxxi mensis i annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jan 031 2408112 01 i 1 01/31/1881 die xxxi mensis i annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.123 {conversion of 1881-02-01} {
+ clock format -2805794704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1881 12:34:56 die i mensis ii annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Feb 032 2408113 02 ii 2 02/01/1881 die i mensis ii annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.124 {conversion of 1881-02-28} {
+ clock format -2803461904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1881 12:34:56 die xxviii mensis ii annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 28 xxviii 28 xxviii Feb 059 2408140 02 ii 2 02/28/1881 die xxviii mensis ii annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.125 {conversion of 1881-03-01} {
+ clock format -2803375504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1881 12:34:56 die i mensis iii annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Mar 060 2408141 03 iii 3 03/01/1881 die i mensis iii annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.126 {conversion of 1881-03-31} {
+ clock format -2800783504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1881 12:34:56 die xxxi mensis iii annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Mar 090 2408171 03 iii 3 03/31/1881 die xxxi mensis iii annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.127 {conversion of 1881-04-01} {
+ clock format -2800697104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1881 12:34:56 die i mensis iv annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Apr 091 2408172 04 iv 4 04/01/1881 die i mensis iv annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.128 {conversion of 1881-04-30} {
+ clock format -2798191504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1881 12:34:56 die xxx mensis iv annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Apr 120 2408201 04 iv 4 04/30/1881 die xxx mensis iv annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.129 {conversion of 1881-05-01} {
+ clock format -2798105104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1881 12:34:56 die i mensis v annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 01 i 1 i May 121 2408202 05 v 5 05/01/1881 die i mensis v annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.130 {conversion of 1881-05-31} {
+ clock format -2795513104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1881 12:34:56 die xxxi mensis v annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi May 151 2408232 05 v 5 05/31/1881 die xxxi mensis v annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.131 {conversion of 1881-06-01} {
+ clock format -2795426704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1881 12:34:56 die i mensis vi annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jun 152 2408233 06 vi 6 06/01/1881 die i mensis vi annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.132 {conversion of 1881-06-30} {
+ clock format -2792921104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1881 12:34:56 die xxx mensis vi annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Jun 181 2408262 06 vi 6 06/30/1881 die xxx mensis vi annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.133 {conversion of 1881-07-01} {
+ clock format -2792834704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1881 12:34:56 die i mensis vii annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jul 182 2408263 07 vii 7 07/01/1881 die i mensis vii annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.134 {conversion of 1881-07-31} {
+ clock format -2790242704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1881 12:34:56 die xxxi mensis vii annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jul 212 2408293 07 vii 7 07/31/1881 die xxxi mensis vii annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.135 {conversion of 1881-08-01} {
+ clock format -2790156304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1881 12:34:56 die i mensis viii annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Aug 213 2408294 08 viii 8 08/01/1881 die i mensis viii annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.136 {conversion of 1881-08-31} {
+ clock format -2787564304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1881 12:34:56 die xxxi mensis viii annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Aug 243 2408324 08 viii 8 08/31/1881 die xxxi mensis viii annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.137 {conversion of 1881-09-01} {
+ clock format -2787477904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1881 12:34:56 die i mensis ix annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Sep 244 2408325 09 ix 9 09/01/1881 die i mensis ix annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.138 {conversion of 1881-09-30} {
+ clock format -2784972304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1881 12:34:56 die xxx mensis ix annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Sep 273 2408354 09 ix 9 09/30/1881 die xxx mensis ix annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.139 {conversion of 1881-10-01} {
+ clock format -2784885904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1881 12:34:56 die i mensis x annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Oct 274 2408355 10 x 10 10/01/1881 die i mensis x annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.140 {conversion of 1881-10-31} {
+ clock format -2782293904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1881 12:34:56 die xxxi mensis x annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Oct 304 2408385 10 x 10 10/31/1881 die xxxi mensis x annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.141 {conversion of 1881-11-01} {
+ clock format -2782207504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1881 12:34:56 die i mensis xi annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Nov 305 2408386 11 xi 11 11/01/1881 die i mensis xi annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.142 {conversion of 1881-11-30} {
+ clock format -2779701904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1881 12:34:56 die xxx mensis xi annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Nov 334 2408415 11 xi 11 11/30/1881 die xxx mensis xi annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.143 {conversion of 1881-12-01} {
+ clock format -2779615504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1881 12:34:56 die i mensis xii annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Dec 335 2408416 12 xii 12 12/01/1881 die i mensis xii annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.144 {conversion of 1881-12-31} {
+ clock format -2777023504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1881 12:34:56 die xxxi mensis xii annoque mdccclxxxi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Dec 365 2408446 12 xii 12 12/31/1881 die xxxi mensis xii annoque mdccclxxxi 81 lxxxi 1881}
+test clock-2.145 {conversion of 1884-01-01} {
+ clock format -2713865104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1884 12:34:56 die i mensis i annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jan 001 2409177 01 i 1 01/01/1884 die i mensis i annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.146 {conversion of 1884-01-31} {
+ clock format -2711273104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1884 12:34:56 die xxxi mensis i annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jan 031 2409207 01 i 1 01/31/1884 die xxxi mensis i annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.147 {conversion of 1884-02-01} {
+ clock format -2711186704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1884 12:34:56 die i mensis ii annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Feb 032 2409208 02 ii 2 02/01/1884 die i mensis ii annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.148 {conversion of 1884-02-29} {
+ clock format -2708767504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1884 12:34:56 die xxix mensis ii annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 29 xxix 29 xxix Feb 060 2409236 02 ii 2 02/29/1884 die xxix mensis ii annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.149 {conversion of 1884-03-01} {
+ clock format -2708681104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1884 12:34:56 die i mensis iii annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Mar 061 2409237 03 iii 3 03/01/1884 die i mensis iii annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.150 {conversion of 1884-03-31} {
+ clock format -2706089104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1884 12:34:56 die xxxi mensis iii annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Mar 091 2409267 03 iii 3 03/31/1884 die xxxi mensis iii annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.151 {conversion of 1884-04-01} {
+ clock format -2706002704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1884 12:34:56 die i mensis iv annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Apr 092 2409268 04 iv 4 04/01/1884 die i mensis iv annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.152 {conversion of 1884-04-30} {
+ clock format -2703497104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1884 12:34:56 die xxx mensis iv annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Apr 121 2409297 04 iv 4 04/30/1884 die xxx mensis iv annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.153 {conversion of 1884-05-01} {
+ clock format -2703410704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1884 12:34:56 die i mensis v annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 01 i 1 i May 122 2409298 05 v 5 05/01/1884 die i mensis v annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.154 {conversion of 1884-05-31} {
+ clock format -2700818704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1884 12:34:56 die xxxi mensis v annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi May 152 2409328 05 v 5 05/31/1884 die xxxi mensis v annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.155 {conversion of 1884-06-01} {
+ clock format -2700732304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1884 12:34:56 die i mensis vi annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jun 153 2409329 06 vi 6 06/01/1884 die i mensis vi annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.156 {conversion of 1884-06-30} {
+ clock format -2698226704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1884 12:34:56 die xxx mensis vi annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Jun 182 2409358 06 vi 6 06/30/1884 die xxx mensis vi annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.157 {conversion of 1884-07-01} {
+ clock format -2698140304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1884 12:34:56 die i mensis vii annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jul 183 2409359 07 vii 7 07/01/1884 die i mensis vii annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.158 {conversion of 1884-07-31} {
+ clock format -2695548304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1884 12:34:56 die xxxi mensis vii annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jul 213 2409389 07 vii 7 07/31/1884 die xxxi mensis vii annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.159 {conversion of 1884-08-01} {
+ clock format -2695461904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1884 12:34:56 die i mensis viii annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Aug 214 2409390 08 viii 8 08/01/1884 die i mensis viii annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.160 {conversion of 1884-08-31} {
+ clock format -2692869904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1884 12:34:56 die xxxi mensis viii annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Aug 244 2409420 08 viii 8 08/31/1884 die xxxi mensis viii annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.161 {conversion of 1884-09-01} {
+ clock format -2692783504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1884 12:34:56 die i mensis ix annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Sep 245 2409421 09 ix 9 09/01/1884 die i mensis ix annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.162 {conversion of 1884-09-30} {
+ clock format -2690277904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1884 12:34:56 die xxx mensis ix annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Sep 274 2409450 09 ix 9 09/30/1884 die xxx mensis ix annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.163 {conversion of 1884-10-01} {
+ clock format -2690191504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1884 12:34:56 die i mensis x annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Oct 275 2409451 10 x 10 10/01/1884 die i mensis x annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.164 {conversion of 1884-10-31} {
+ clock format -2687599504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1884 12:34:56 die xxxi mensis x annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Oct 305 2409481 10 x 10 10/31/1884 die xxxi mensis x annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.165 {conversion of 1884-11-01} {
+ clock format -2687513104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1884 12:34:56 die i mensis xi annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Nov 306 2409482 11 xi 11 11/01/1884 die i mensis xi annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.166 {conversion of 1884-11-30} {
+ clock format -2685007504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1884 12:34:56 die xxx mensis xi annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Nov 335 2409511 11 xi 11 11/30/1884 die xxx mensis xi annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.167 {conversion of 1884-12-01} {
+ clock format -2684921104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1884 12:34:56 die i mensis xii annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Dec 336 2409512 12 xii 12 12/01/1884 die i mensis xii annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.168 {conversion of 1884-12-31} {
+ clock format -2682329104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1884 12:34:56 die xxxi mensis xii annoque mdccclxxxiv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Dec 366 2409542 12 xii 12 12/31/1884 die xxxi mensis xii annoque mdccclxxxiv 84 lxxxiv 1884}
+test clock-2.169 {conversion of 1885-01-01} {
+ clock format -2682242704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1885 12:34:56 die i mensis i annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jan 001 2409543 01 i 1 01/01/1885 die i mensis i annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.170 {conversion of 1885-01-31} {
+ clock format -2679650704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1885 12:34:56 die xxxi mensis i annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jan 031 2409573 01 i 1 01/31/1885 die xxxi mensis i annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.171 {conversion of 1885-02-01} {
+ clock format -2679564304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1885 12:34:56 die i mensis ii annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Feb 032 2409574 02 ii 2 02/01/1885 die i mensis ii annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.172 {conversion of 1885-02-28} {
+ clock format -2677231504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1885 12:34:56 die xxviii mensis ii annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 28 xxviii 28 xxviii Feb 059 2409601 02 ii 2 02/28/1885 die xxviii mensis ii annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.173 {conversion of 1885-03-01} {
+ clock format -2677145104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1885 12:34:56 die i mensis iii annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Mar 060 2409602 03 iii 3 03/01/1885 die i mensis iii annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.174 {conversion of 1885-03-31} {
+ clock format -2674553104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1885 12:34:56 die xxxi mensis iii annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Mar 090 2409632 03 iii 3 03/31/1885 die xxxi mensis iii annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.175 {conversion of 1885-04-01} {
+ clock format -2674466704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1885 12:34:56 die i mensis iv annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Apr 091 2409633 04 iv 4 04/01/1885 die i mensis iv annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.176 {conversion of 1885-04-30} {
+ clock format -2671961104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1885 12:34:56 die xxx mensis iv annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Apr 120 2409662 04 iv 4 04/30/1885 die xxx mensis iv annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.177 {conversion of 1885-05-01} {
+ clock format -2671874704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1885 12:34:56 die i mensis v annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 01 i 1 i May 121 2409663 05 v 5 05/01/1885 die i mensis v annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.178 {conversion of 1885-05-31} {
+ clock format -2669282704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1885 12:34:56 die xxxi mensis v annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi May 151 2409693 05 v 5 05/31/1885 die xxxi mensis v annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.179 {conversion of 1885-06-01} {
+ clock format -2669196304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1885 12:34:56 die i mensis vi annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jun 152 2409694 06 vi 6 06/01/1885 die i mensis vi annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.180 {conversion of 1885-06-30} {
+ clock format -2666690704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1885 12:34:56 die xxx mensis vi annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Jun 181 2409723 06 vi 6 06/30/1885 die xxx mensis vi annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.181 {conversion of 1885-07-01} {
+ clock format -2666604304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1885 12:34:56 die i mensis vii annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jul 182 2409724 07 vii 7 07/01/1885 die i mensis vii annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.182 {conversion of 1885-07-31} {
+ clock format -2664012304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1885 12:34:56 die xxxi mensis vii annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jul 212 2409754 07 vii 7 07/31/1885 die xxxi mensis vii annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.183 {conversion of 1885-08-01} {
+ clock format -2663925904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1885 12:34:56 die i mensis viii annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Aug 213 2409755 08 viii 8 08/01/1885 die i mensis viii annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.184 {conversion of 1885-08-31} {
+ clock format -2661333904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1885 12:34:56 die xxxi mensis viii annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Aug 243 2409785 08 viii 8 08/31/1885 die xxxi mensis viii annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.185 {conversion of 1885-09-01} {
+ clock format -2661247504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1885 12:34:56 die i mensis ix annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Sep 244 2409786 09 ix 9 09/01/1885 die i mensis ix annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.186 {conversion of 1885-09-30} {
+ clock format -2658741904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1885 12:34:56 die xxx mensis ix annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Sep 273 2409815 09 ix 9 09/30/1885 die xxx mensis ix annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.187 {conversion of 1885-10-01} {
+ clock format -2658655504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1885 12:34:56 die i mensis x annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Oct 274 2409816 10 x 10 10/01/1885 die i mensis x annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.188 {conversion of 1885-10-31} {
+ clock format -2656063504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1885 12:34:56 die xxxi mensis x annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Oct 304 2409846 10 x 10 10/31/1885 die xxxi mensis x annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.189 {conversion of 1885-11-01} {
+ clock format -2655977104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1885 12:34:56 die i mensis xi annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Nov 305 2409847 11 xi 11 11/01/1885 die i mensis xi annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.190 {conversion of 1885-11-30} {
+ clock format -2653471504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1885 12:34:56 die xxx mensis xi annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Nov 334 2409876 11 xi 11 11/30/1885 die xxx mensis xi annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.191 {conversion of 1885-12-01} {
+ clock format -2653385104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1885 12:34:56 die i mensis xii annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Dec 335 2409877 12 xii 12 12/01/1885 die i mensis xii annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.192 {conversion of 1885-12-31} {
+ clock format -2650793104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1885 12:34:56 die xxxi mensis xii annoque mdccclxxxv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Dec 365 2409907 12 xii 12 12/31/1885 die xxxi mensis xii annoque mdccclxxxv 85 lxxxv 1885}
+test clock-2.193 {conversion of 1888-01-01} {
+ clock format -2587634704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1888 12:34:56 die i mensis i annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jan 001 2410638 01 i 1 01/01/1888 die i mensis i annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.194 {conversion of 1888-01-31} {
+ clock format -2585042704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1888 12:34:56 die xxxi mensis i annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jan 031 2410668 01 i 1 01/31/1888 die xxxi mensis i annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.195 {conversion of 1888-02-01} {
+ clock format -2584956304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1888 12:34:56 die i mensis ii annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Feb 032 2410669 02 ii 2 02/01/1888 die i mensis ii annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.196 {conversion of 1888-02-29} {
+ clock format -2582537104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1888 12:34:56 die xxix mensis ii annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 29 xxix 29 xxix Feb 060 2410697 02 ii 2 02/29/1888 die xxix mensis ii annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.197 {conversion of 1888-03-01} {
+ clock format -2582450704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1888 12:34:56 die i mensis iii annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Mar 061 2410698 03 iii 3 03/01/1888 die i mensis iii annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.198 {conversion of 1888-03-31} {
+ clock format -2579858704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1888 12:34:56 die xxxi mensis iii annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Mar 091 2410728 03 iii 3 03/31/1888 die xxxi mensis iii annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.199 {conversion of 1888-04-01} {
+ clock format -2579772304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1888 12:34:56 die i mensis iv annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Apr 092 2410729 04 iv 4 04/01/1888 die i mensis iv annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.200 {conversion of 1888-04-30} {
+ clock format -2577266704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1888 12:34:56 die xxx mensis iv annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Apr 121 2410758 04 iv 4 04/30/1888 die xxx mensis iv annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.201 {conversion of 1888-05-01} {
+ clock format -2577180304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1888 12:34:56 die i mensis v annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i May 122 2410759 05 v 5 05/01/1888 die i mensis v annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.202 {conversion of 1888-05-31} {
+ clock format -2574588304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1888 12:34:56 die xxxi mensis v annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi May 152 2410789 05 v 5 05/31/1888 die xxxi mensis v annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.203 {conversion of 1888-06-01} {
+ clock format -2574501904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1888 12:34:56 die i mensis vi annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jun 153 2410790 06 vi 6 06/01/1888 die i mensis vi annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.204 {conversion of 1888-06-30} {
+ clock format -2571996304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1888 12:34:56 die xxx mensis vi annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Jun 182 2410819 06 vi 6 06/30/1888 die xxx mensis vi annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.205 {conversion of 1888-07-01} {
+ clock format -2571909904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1888 12:34:56 die i mensis vii annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jul 183 2410820 07 vii 7 07/01/1888 die i mensis vii annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.206 {conversion of 1888-07-31} {
+ clock format -2569317904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1888 12:34:56 die xxxi mensis vii annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jul 213 2410850 07 vii 7 07/31/1888 die xxxi mensis vii annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.207 {conversion of 1888-08-01} {
+ clock format -2569231504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1888 12:34:56 die i mensis viii annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Aug 214 2410851 08 viii 8 08/01/1888 die i mensis viii annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.208 {conversion of 1888-08-31} {
+ clock format -2566639504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1888 12:34:56 die xxxi mensis viii annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Aug 244 2410881 08 viii 8 08/31/1888 die xxxi mensis viii annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.209 {conversion of 1888-09-01} {
+ clock format -2566553104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1888 12:34:56 die i mensis ix annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Sep 245 2410882 09 ix 9 09/01/1888 die i mensis ix annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.210 {conversion of 1888-09-30} {
+ clock format -2564047504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1888 12:34:56 die xxx mensis ix annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Sep 274 2410911 09 ix 9 09/30/1888 die xxx mensis ix annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.211 {conversion of 1888-10-01} {
+ clock format -2563961104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1888 12:34:56 die i mensis x annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Oct 275 2410912 10 x 10 10/01/1888 die i mensis x annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.212 {conversion of 1888-10-31} {
+ clock format -2561369104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1888 12:34:56 die xxxi mensis x annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Oct 305 2410942 10 x 10 10/31/1888 die xxxi mensis x annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.213 {conversion of 1888-11-01} {
+ clock format -2561282704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1888 12:34:56 die i mensis xi annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Nov 306 2410943 11 xi 11 11/01/1888 die i mensis xi annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.214 {conversion of 1888-11-30} {
+ clock format -2558777104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1888 12:34:56 die xxx mensis xi annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Nov 335 2410972 11 xi 11 11/30/1888 die xxx mensis xi annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.215 {conversion of 1888-12-01} {
+ clock format -2558690704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1888 12:34:56 die i mensis xii annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Dec 336 2410973 12 xii 12 12/01/1888 die i mensis xii annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.216 {conversion of 1888-12-31} {
+ clock format -2556098704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1888 12:34:56 die xxxi mensis xii annoque mdccclxxxviii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Dec 366 2411003 12 xii 12 12/31/1888 die xxxi mensis xii annoque mdccclxxxviii 88 lxxxviii 1888}
+test clock-2.217 {conversion of 1889-01-01} {
+ clock format -2556012304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1889 12:34:56 die i mensis i annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jan 001 2411004 01 i 1 01/01/1889 die i mensis i annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.218 {conversion of 1889-01-31} {
+ clock format -2553420304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1889 12:34:56 die xxxi mensis i annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jan 031 2411034 01 i 1 01/31/1889 die xxxi mensis i annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.219 {conversion of 1889-02-01} {
+ clock format -2553333904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1889 12:34:56 die i mensis ii annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Feb 032 2411035 02 ii 2 02/01/1889 die i mensis ii annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.220 {conversion of 1889-02-28} {
+ clock format -2551001104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1889 12:34:56 die xxviii mensis ii annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 28 xxviii 28 xxviii Feb 059 2411062 02 ii 2 02/28/1889 die xxviii mensis ii annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.221 {conversion of 1889-03-01} {
+ clock format -2550914704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1889 12:34:56 die i mensis iii annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Mar 060 2411063 03 iii 3 03/01/1889 die i mensis iii annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.222 {conversion of 1889-03-31} {
+ clock format -2548322704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1889 12:34:56 die xxxi mensis iii annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Mar 090 2411093 03 iii 3 03/31/1889 die xxxi mensis iii annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.223 {conversion of 1889-04-01} {
+ clock format -2548236304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1889 12:34:56 die i mensis iv annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Apr 091 2411094 04 iv 4 04/01/1889 die i mensis iv annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.224 {conversion of 1889-04-30} {
+ clock format -2545730704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1889 12:34:56 die xxx mensis iv annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Apr 120 2411123 04 iv 4 04/30/1889 die xxx mensis iv annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.225 {conversion of 1889-05-01} {
+ clock format -2545644304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1889 12:34:56 die i mensis v annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 01 i 1 i May 121 2411124 05 v 5 05/01/1889 die i mensis v annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.226 {conversion of 1889-05-31} {
+ clock format -2543052304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1889 12:34:56 die xxxi mensis v annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi May 151 2411154 05 v 5 05/31/1889 die xxxi mensis v annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.227 {conversion of 1889-06-01} {
+ clock format -2542965904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1889 12:34:56 die i mensis vi annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jun 152 2411155 06 vi 6 06/01/1889 die i mensis vi annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.228 {conversion of 1889-06-30} {
+ clock format -2540460304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1889 12:34:56 die xxx mensis vi annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Jun 181 2411184 06 vi 6 06/30/1889 die xxx mensis vi annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.229 {conversion of 1889-07-01} {
+ clock format -2540373904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1889 12:34:56 die i mensis vii annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jul 182 2411185 07 vii 7 07/01/1889 die i mensis vii annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.230 {conversion of 1889-07-31} {
+ clock format -2537781904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1889 12:34:56 die xxxi mensis vii annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jul 212 2411215 07 vii 7 07/31/1889 die xxxi mensis vii annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.231 {conversion of 1889-08-01} {
+ clock format -2537695504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1889 12:34:56 die i mensis viii annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Aug 213 2411216 08 viii 8 08/01/1889 die i mensis viii annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.232 {conversion of 1889-08-31} {
+ clock format -2535103504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1889 12:34:56 die xxxi mensis viii annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Aug 243 2411246 08 viii 8 08/31/1889 die xxxi mensis viii annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.233 {conversion of 1889-09-01} {
+ clock format -2535017104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1889 12:34:56 die i mensis ix annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Sep 244 2411247 09 ix 9 09/01/1889 die i mensis ix annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.234 {conversion of 1889-09-30} {
+ clock format -2532511504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1889 12:34:56 die xxx mensis ix annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Sep 273 2411276 09 ix 9 09/30/1889 die xxx mensis ix annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.235 {conversion of 1889-10-01} {
+ clock format -2532425104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1889 12:34:56 die i mensis x annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Oct 274 2411277 10 x 10 10/01/1889 die i mensis x annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.236 {conversion of 1889-10-31} {
+ clock format -2529833104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1889 12:34:56 die xxxi mensis x annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Oct 304 2411307 10 x 10 10/31/1889 die xxxi mensis x annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.237 {conversion of 1889-11-01} {
+ clock format -2529746704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1889 12:34:56 die i mensis xi annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Nov 305 2411308 11 xi 11 11/01/1889 die i mensis xi annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.238 {conversion of 1889-11-30} {
+ clock format -2527241104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1889 12:34:56 die xxx mensis xi annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Nov 334 2411337 11 xi 11 11/30/1889 die xxx mensis xi annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.239 {conversion of 1889-12-01} {
+ clock format -2527154704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1889 12:34:56 die i mensis xii annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Dec 335 2411338 12 xii 12 12/01/1889 die i mensis xii annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.240 {conversion of 1889-12-31} {
+ clock format -2524562704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1889 12:34:56 die xxxi mensis xii annoque mdccclxxxix xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Dec 365 2411368 12 xii 12 12/31/1889 die xxxi mensis xii annoque mdccclxxxix 89 lxxxix 1889}
+test clock-2.241 {conversion of 1890-01-01} {
+ clock format -2524476304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1890 12:34:56 die i mensis i annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jan 001 2411369 01 i 1 01/01/1890 die i mensis i annoque mdcccxc 90 xc 1890}
+test clock-2.242 {conversion of 1890-01-31} {
+ clock format -2521884304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1890 12:34:56 die xxxi mensis i annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jan 031 2411399 01 i 1 01/31/1890 die xxxi mensis i annoque mdcccxc 90 xc 1890}
+test clock-2.243 {conversion of 1890-02-01} {
+ clock format -2521797904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1890 12:34:56 die i mensis ii annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 01 i 1 i Feb 032 2411400 02 ii 2 02/01/1890 die i mensis ii annoque mdcccxc 90 xc 1890}
+test clock-2.244 {conversion of 1890-02-28} {
+ clock format -2519465104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1890 12:34:56 die xxviii mensis ii annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 28 xxviii 28 xxviii Feb 059 2411427 02 ii 2 02/28/1890 die xxviii mensis ii annoque mdcccxc 90 xc 1890}
+test clock-2.245 {conversion of 1890-03-01} {
+ clock format -2519378704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1890 12:34:56 die i mensis iii annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 01 i 1 i Mar 060 2411428 03 iii 3 03/01/1890 die i mensis iii annoque mdcccxc 90 xc 1890}
+test clock-2.246 {conversion of 1890-03-31} {
+ clock format -2516786704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1890 12:34:56 die xxxi mensis iii annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Mar 090 2411458 03 iii 3 03/31/1890 die xxxi mensis iii annoque mdcccxc 90 xc 1890}
+test clock-2.247 {conversion of 1890-04-01} {
+ clock format -2516700304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1890 12:34:56 die i mensis iv annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 01 i 1 i Apr 091 2411459 04 iv 4 04/01/1890 die i mensis iv annoque mdcccxc 90 xc 1890}
+test clock-2.248 {conversion of 1890-04-30} {
+ clock format -2514194704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1890 12:34:56 die xxx mensis iv annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Apr 120 2411488 04 iv 4 04/30/1890 die xxx mensis iv annoque mdcccxc 90 xc 1890}
+test clock-2.249 {conversion of 1890-05-01} {
+ clock format -2514108304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1890 12:34:56 die i mensis v annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 01 i 1 i May 121 2411489 05 v 5 05/01/1890 die i mensis v annoque mdcccxc 90 xc 1890}
+test clock-2.250 {conversion of 1890-05-31} {
+ clock format -2511516304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1890 12:34:56 die xxxi mensis v annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi May 151 2411519 05 v 5 05/31/1890 die xxxi mensis v annoque mdcccxc 90 xc 1890}
+test clock-2.251 {conversion of 1890-06-01} {
+ clock format -2511429904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1890 12:34:56 die i mensis vi annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jun 152 2411520 06 vi 6 06/01/1890 die i mensis vi annoque mdcccxc 90 xc 1890}
+test clock-2.252 {conversion of 1890-06-30} {
+ clock format -2508924304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1890 12:34:56 die xxx mensis vi annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Jun 181 2411549 06 vi 6 06/30/1890 die xxx mensis vi annoque mdcccxc 90 xc 1890}
+test clock-2.253 {conversion of 1890-07-01} {
+ clock format -2508837904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1890 12:34:56 die i mensis vii annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jul 182 2411550 07 vii 7 07/01/1890 die i mensis vii annoque mdcccxc 90 xc 1890}
+test clock-2.254 {conversion of 1890-07-31} {
+ clock format -2506245904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1890 12:34:56 die xxxi mensis vii annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jul 212 2411580 07 vii 7 07/31/1890 die xxxi mensis vii annoque mdcccxc 90 xc 1890}
+test clock-2.255 {conversion of 1890-08-01} {
+ clock format -2506159504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1890 12:34:56 die i mensis viii annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 01 i 1 i Aug 213 2411581 08 viii 8 08/01/1890 die i mensis viii annoque mdcccxc 90 xc 1890}
+test clock-2.256 {conversion of 1890-08-31} {
+ clock format -2503567504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1890 12:34:56 die xxxi mensis viii annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Aug 243 2411611 08 viii 8 08/31/1890 die xxxi mensis viii annoque mdcccxc 90 xc 1890}
+test clock-2.257 {conversion of 1890-09-01} {
+ clock format -2503481104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1890 12:34:56 die i mensis ix annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 01 i 1 i Sep 244 2411612 09 ix 9 09/01/1890 die i mensis ix annoque mdcccxc 90 xc 1890}
+test clock-2.258 {conversion of 1890-09-30} {
+ clock format -2500975504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1890 12:34:56 die xxx mensis ix annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Sep 273 2411641 09 ix 9 09/30/1890 die xxx mensis ix annoque mdcccxc 90 xc 1890}
+test clock-2.259 {conversion of 1890-10-01} {
+ clock format -2500889104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1890 12:34:56 die i mensis x annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 01 i 1 i Oct 274 2411642 10 x 10 10/01/1890 die i mensis x annoque mdcccxc 90 xc 1890}
+test clock-2.260 {conversion of 1890-10-31} {
+ clock format -2498297104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1890 12:34:56 die xxxi mensis x annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Oct 304 2411672 10 x 10 10/31/1890 die xxxi mensis x annoque mdcccxc 90 xc 1890}
+test clock-2.261 {conversion of 1890-11-01} {
+ clock format -2498210704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1890 12:34:56 die i mensis xi annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 01 i 1 i Nov 305 2411673 11 xi 11 11/01/1890 die i mensis xi annoque mdcccxc 90 xc 1890}
+test clock-2.262 {conversion of 1890-11-30} {
+ clock format -2495705104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1890 12:34:56 die xxx mensis xi annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Nov 334 2411702 11 xi 11 11/30/1890 die xxx mensis xi annoque mdcccxc 90 xc 1890}
+test clock-2.263 {conversion of 1890-12-01} {
+ clock format -2495618704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1890 12:34:56 die i mensis xii annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 01 i 1 i Dec 335 2411703 12 xii 12 12/01/1890 die i mensis xii annoque mdcccxc 90 xc 1890}
+test clock-2.264 {conversion of 1890-12-31} {
+ clock format -2493026704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1890 12:34:56 die xxxi mensis xii annoque mdcccxc xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Dec 365 2411733 12 xii 12 12/31/1890 die xxxi mensis xii annoque mdcccxc 90 xc 1890}
+test clock-2.265 {conversion of 1891-01-01} {
+ clock format -2492940304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1891 12:34:56 die i mensis i annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jan 001 2411734 01 i 1 01/01/1891 die i mensis i annoque mdcccxci 91 xci 1891}
+test clock-2.266 {conversion of 1891-01-31} {
+ clock format -2490348304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1891 12:34:56 die xxxi mensis i annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jan 031 2411764 01 i 1 01/31/1891 die xxxi mensis i annoque mdcccxci 91 xci 1891}
+test clock-2.267 {conversion of 1891-02-01} {
+ clock format -2490261904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1891 12:34:56 die i mensis ii annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 01 i 1 i Feb 032 2411765 02 ii 2 02/01/1891 die i mensis ii annoque mdcccxci 91 xci 1891}
+test clock-2.268 {conversion of 1891-02-28} {
+ clock format -2487929104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1891 12:34:56 die xxviii mensis ii annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 28 xxviii 28 xxviii Feb 059 2411792 02 ii 2 02/28/1891 die xxviii mensis ii annoque mdcccxci 91 xci 1891}
+test clock-2.269 {conversion of 1891-03-01} {
+ clock format -2487842704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1891 12:34:56 die i mensis iii annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 01 i 1 i Mar 060 2411793 03 iii 3 03/01/1891 die i mensis iii annoque mdcccxci 91 xci 1891}
+test clock-2.270 {conversion of 1891-03-31} {
+ clock format -2485250704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1891 12:34:56 die xxxi mensis iii annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Mar 090 2411823 03 iii 3 03/31/1891 die xxxi mensis iii annoque mdcccxci 91 xci 1891}
+test clock-2.271 {conversion of 1891-04-01} {
+ clock format -2485164304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1891 12:34:56 die i mensis iv annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 01 i 1 i Apr 091 2411824 04 iv 4 04/01/1891 die i mensis iv annoque mdcccxci 91 xci 1891}
+test clock-2.272 {conversion of 1891-04-30} {
+ clock format -2482658704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1891 12:34:56 die xxx mensis iv annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Apr 120 2411853 04 iv 4 04/30/1891 die xxx mensis iv annoque mdcccxci 91 xci 1891}
+test clock-2.273 {conversion of 1891-05-01} {
+ clock format -2482572304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1891 12:34:56 die i mensis v annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 01 i 1 i May 121 2411854 05 v 5 05/01/1891 die i mensis v annoque mdcccxci 91 xci 1891}
+test clock-2.274 {conversion of 1891-05-31} {
+ clock format -2479980304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1891 12:34:56 die xxxi mensis v annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi May 151 2411884 05 v 5 05/31/1891 die xxxi mensis v annoque mdcccxci 91 xci 1891}
+test clock-2.275 {conversion of 1891-06-01} {
+ clock format -2479893904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1891 12:34:56 die i mensis vi annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jun 152 2411885 06 vi 6 06/01/1891 die i mensis vi annoque mdcccxci 91 xci 1891}
+test clock-2.276 {conversion of 1891-06-30} {
+ clock format -2477388304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1891 12:34:56 die xxx mensis vi annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Jun 181 2411914 06 vi 6 06/30/1891 die xxx mensis vi annoque mdcccxci 91 xci 1891}
+test clock-2.277 {conversion of 1891-07-01} {
+ clock format -2477301904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1891 12:34:56 die i mensis vii annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jul 182 2411915 07 vii 7 07/01/1891 die i mensis vii annoque mdcccxci 91 xci 1891}
+test clock-2.278 {conversion of 1891-07-31} {
+ clock format -2474709904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1891 12:34:56 die xxxi mensis vii annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jul 212 2411945 07 vii 7 07/31/1891 die xxxi mensis vii annoque mdcccxci 91 xci 1891}
+test clock-2.279 {conversion of 1891-08-01} {
+ clock format -2474623504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1891 12:34:56 die i mensis viii annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 01 i 1 i Aug 213 2411946 08 viii 8 08/01/1891 die i mensis viii annoque mdcccxci 91 xci 1891}
+test clock-2.280 {conversion of 1891-08-31} {
+ clock format -2472031504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1891 12:34:56 die xxxi mensis viii annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Aug 243 2411976 08 viii 8 08/31/1891 die xxxi mensis viii annoque mdcccxci 91 xci 1891}
+test clock-2.281 {conversion of 1891-09-01} {
+ clock format -2471945104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1891 12:34:56 die i mensis ix annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 01 i 1 i Sep 244 2411977 09 ix 9 09/01/1891 die i mensis ix annoque mdcccxci 91 xci 1891}
+test clock-2.282 {conversion of 1891-09-30} {
+ clock format -2469439504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1891 12:34:56 die xxx mensis ix annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Sep 273 2412006 09 ix 9 09/30/1891 die xxx mensis ix annoque mdcccxci 91 xci 1891}
+test clock-2.283 {conversion of 1891-10-01} {
+ clock format -2469353104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1891 12:34:56 die i mensis x annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 01 i 1 i Oct 274 2412007 10 x 10 10/01/1891 die i mensis x annoque mdcccxci 91 xci 1891}
+test clock-2.284 {conversion of 1891-10-31} {
+ clock format -2466761104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1891 12:34:56 die xxxi mensis x annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Oct 304 2412037 10 x 10 10/31/1891 die xxxi mensis x annoque mdcccxci 91 xci 1891}
+test clock-2.285 {conversion of 1891-11-01} {
+ clock format -2466674704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1891 12:34:56 die i mensis xi annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 01 i 1 i Nov 305 2412038 11 xi 11 11/01/1891 die i mensis xi annoque mdcccxci 91 xci 1891}
+test clock-2.286 {conversion of 1891-11-30} {
+ clock format -2464169104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1891 12:34:56 die xxx mensis xi annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Nov 334 2412067 11 xi 11 11/30/1891 die xxx mensis xi annoque mdcccxci 91 xci 1891}
+test clock-2.287 {conversion of 1891-12-01} {
+ clock format -2464082704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1891 12:34:56 die i mensis xii annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 01 i 1 i Dec 335 2412068 12 xii 12 12/01/1891 die i mensis xii annoque mdcccxci 91 xci 1891}
+test clock-2.288 {conversion of 1891-12-31} {
+ clock format -2461490704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1891 12:34:56 die xxxi mensis xii annoque mdcccxci xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Dec 365 2412098 12 xii 12 12/31/1891 die xxxi mensis xii annoque mdcccxci 91 xci 1891}
+test clock-2.289 {conversion of 1892-01-01} {
+ clock format -2461404304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1892 12:34:56 die i mensis i annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jan 001 2412099 01 i 1 01/01/1892 die i mensis i annoque mdcccxcii 92 xcii 1892}
+test clock-2.290 {conversion of 1892-01-31} {
+ clock format -2458812304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1892 12:34:56 die xxxi mensis i annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jan 031 2412129 01 i 1 01/31/1892 die xxxi mensis i annoque mdcccxcii 92 xcii 1892}
+test clock-2.291 {conversion of 1892-02-01} {
+ clock format -2458725904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1892 12:34:56 die i mensis ii annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Feb 032 2412130 02 ii 2 02/01/1892 die i mensis ii annoque mdcccxcii 92 xcii 1892}
+test clock-2.292 {conversion of 1892-02-29} {
+ clock format -2456306704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1892 12:34:56 die xxix mensis ii annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 29 xxix 29 xxix Feb 060 2412158 02 ii 2 02/29/1892 die xxix mensis ii annoque mdcccxcii 92 xcii 1892}
+test clock-2.293 {conversion of 1892-03-01} {
+ clock format -2456220304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1892 12:34:56 die i mensis iii annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Mar 061 2412159 03 iii 3 03/01/1892 die i mensis iii annoque mdcccxcii 92 xcii 1892}
+test clock-2.294 {conversion of 1892-03-31} {
+ clock format -2453628304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1892 12:34:56 die xxxi mensis iii annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Mar 091 2412189 03 iii 3 03/31/1892 die xxxi mensis iii annoque mdcccxcii 92 xcii 1892}
+test clock-2.295 {conversion of 1892-04-01} {
+ clock format -2453541904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1892 12:34:56 die i mensis iv annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Apr 092 2412190 04 iv 4 04/01/1892 die i mensis iv annoque mdcccxcii 92 xcii 1892}
+test clock-2.296 {conversion of 1892-04-30} {
+ clock format -2451036304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1892 12:34:56 die xxx mensis iv annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Apr 121 2412219 04 iv 4 04/30/1892 die xxx mensis iv annoque mdcccxcii 92 xcii 1892}
+test clock-2.297 {conversion of 1892-05-01} {
+ clock format -2450949904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1892 12:34:56 die i mensis v annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 01 i 1 i May 122 2412220 05 v 5 05/01/1892 die i mensis v annoque mdcccxcii 92 xcii 1892}
+test clock-2.298 {conversion of 1892-05-31} {
+ clock format -2448357904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1892 12:34:56 die xxxi mensis v annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi May 152 2412250 05 v 5 05/31/1892 die xxxi mensis v annoque mdcccxcii 92 xcii 1892}
+test clock-2.299 {conversion of 1892-06-01} {
+ clock format -2448271504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1892 12:34:56 die i mensis vi annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jun 153 2412251 06 vi 6 06/01/1892 die i mensis vi annoque mdcccxcii 92 xcii 1892}
+test clock-2.300 {conversion of 1892-06-30} {
+ clock format -2445765904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1892 12:34:56 die xxx mensis vi annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Jun 182 2412280 06 vi 6 06/30/1892 die xxx mensis vi annoque mdcccxcii 92 xcii 1892}
+test clock-2.301 {conversion of 1892-07-01} {
+ clock format -2445679504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1892 12:34:56 die i mensis vii annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jul 183 2412281 07 vii 7 07/01/1892 die i mensis vii annoque mdcccxcii 92 xcii 1892}
+test clock-2.302 {conversion of 1892-07-31} {
+ clock format -2443087504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1892 12:34:56 die xxxi mensis vii annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jul 213 2412311 07 vii 7 07/31/1892 die xxxi mensis vii annoque mdcccxcii 92 xcii 1892}
+test clock-2.303 {conversion of 1892-08-01} {
+ clock format -2443001104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1892 12:34:56 die i mensis viii annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Aug 214 2412312 08 viii 8 08/01/1892 die i mensis viii annoque mdcccxcii 92 xcii 1892}
+test clock-2.304 {conversion of 1892-08-31} {
+ clock format -2440409104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1892 12:34:56 die xxxi mensis viii annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Aug 244 2412342 08 viii 8 08/31/1892 die xxxi mensis viii annoque mdcccxcii 92 xcii 1892}
+test clock-2.305 {conversion of 1892-09-01} {
+ clock format -2440322704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1892 12:34:56 die i mensis ix annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Sep 245 2412343 09 ix 9 09/01/1892 die i mensis ix annoque mdcccxcii 92 xcii 1892}
+test clock-2.306 {conversion of 1892-09-30} {
+ clock format -2437817104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1892 12:34:56 die xxx mensis ix annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Sep 274 2412372 09 ix 9 09/30/1892 die xxx mensis ix annoque mdcccxcii 92 xcii 1892}
+test clock-2.307 {conversion of 1892-10-01} {
+ clock format -2437730704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1892 12:34:56 die i mensis x annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Oct 275 2412373 10 x 10 10/01/1892 die i mensis x annoque mdcccxcii 92 xcii 1892}
+test clock-2.308 {conversion of 1892-10-31} {
+ clock format -2435138704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1892 12:34:56 die xxxi mensis x annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Oct 305 2412403 10 x 10 10/31/1892 die xxxi mensis x annoque mdcccxcii 92 xcii 1892}
+test clock-2.309 {conversion of 1892-11-01} {
+ clock format -2435052304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1892 12:34:56 die i mensis xi annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Nov 306 2412404 11 xi 11 11/01/1892 die i mensis xi annoque mdcccxcii 92 xcii 1892}
+test clock-2.310 {conversion of 1892-11-30} {
+ clock format -2432546704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1892 12:34:56 die xxx mensis xi annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Nov 335 2412433 11 xi 11 11/30/1892 die xxx mensis xi annoque mdcccxcii 92 xcii 1892}
+test clock-2.311 {conversion of 1892-12-01} {
+ clock format -2432460304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1892 12:34:56 die i mensis xii annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Dec 336 2412434 12 xii 12 12/01/1892 die i mensis xii annoque mdcccxcii 92 xcii 1892}
+test clock-2.312 {conversion of 1892-12-31} {
+ clock format -2429868304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1892 12:34:56 die xxxi mensis xii annoque mdcccxcii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Dec 366 2412464 12 xii 12 12/31/1892 die xxxi mensis xii annoque mdcccxcii 92 xcii 1892}
+test clock-2.313 {conversion of 1893-01-01} {
+ clock format -2429781904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1893 12:34:56 die i mensis i annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jan 001 2412465 01 i 1 01/01/1893 die i mensis i annoque mdcccxciii 93 xciii 1893}
+test clock-2.314 {conversion of 1893-01-31} {
+ clock format -2427189904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1893 12:34:56 die xxxi mensis i annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jan 031 2412495 01 i 1 01/31/1893 die xxxi mensis i annoque mdcccxciii 93 xciii 1893}
+test clock-2.315 {conversion of 1893-02-01} {
+ clock format -2427103504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1893 12:34:56 die i mensis ii annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Feb 032 2412496 02 ii 2 02/01/1893 die i mensis ii annoque mdcccxciii 93 xciii 1893}
+test clock-2.316 {conversion of 1893-02-28} {
+ clock format -2424770704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1893 12:34:56 die xxviii mensis ii annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 28 xxviii 28 xxviii Feb 059 2412523 02 ii 2 02/28/1893 die xxviii mensis ii annoque mdcccxciii 93 xciii 1893}
+test clock-2.317 {conversion of 1893-03-01} {
+ clock format -2424684304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1893 12:34:56 die i mensis iii annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Mar 060 2412524 03 iii 3 03/01/1893 die i mensis iii annoque mdcccxciii 93 xciii 1893}
+test clock-2.318 {conversion of 1893-03-31} {
+ clock format -2422092304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1893 12:34:56 die xxxi mensis iii annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Mar 090 2412554 03 iii 3 03/31/1893 die xxxi mensis iii annoque mdcccxciii 93 xciii 1893}
+test clock-2.319 {conversion of 1893-04-01} {
+ clock format -2422005904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1893 12:34:56 die i mensis iv annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Apr 091 2412555 04 iv 4 04/01/1893 die i mensis iv annoque mdcccxciii 93 xciii 1893}
+test clock-2.320 {conversion of 1893-04-30} {
+ clock format -2419500304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1893 12:34:56 die xxx mensis iv annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Apr 120 2412584 04 iv 4 04/30/1893 die xxx mensis iv annoque mdcccxciii 93 xciii 1893}
+test clock-2.321 {conversion of 1893-05-01} {
+ clock format -2419413904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1893 12:34:56 die i mensis v annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 01 i 1 i May 121 2412585 05 v 5 05/01/1893 die i mensis v annoque mdcccxciii 93 xciii 1893}
+test clock-2.322 {conversion of 1893-05-31} {
+ clock format -2416821904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1893 12:34:56 die xxxi mensis v annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi May 151 2412615 05 v 5 05/31/1893 die xxxi mensis v annoque mdcccxciii 93 xciii 1893}
+test clock-2.323 {conversion of 1893-06-01} {
+ clock format -2416735504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1893 12:34:56 die i mensis vi annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jun 152 2412616 06 vi 6 06/01/1893 die i mensis vi annoque mdcccxciii 93 xciii 1893}
+test clock-2.324 {conversion of 1893-06-30} {
+ clock format -2414229904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1893 12:34:56 die xxx mensis vi annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Jun 181 2412645 06 vi 6 06/30/1893 die xxx mensis vi annoque mdcccxciii 93 xciii 1893}
+test clock-2.325 {conversion of 1893-07-01} {
+ clock format -2414143504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1893 12:34:56 die i mensis vii annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jul 182 2412646 07 vii 7 07/01/1893 die i mensis vii annoque mdcccxciii 93 xciii 1893}
+test clock-2.326 {conversion of 1893-07-31} {
+ clock format -2411551504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1893 12:34:56 die xxxi mensis vii annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jul 212 2412676 07 vii 7 07/31/1893 die xxxi mensis vii annoque mdcccxciii 93 xciii 1893}
+test clock-2.327 {conversion of 1893-08-01} {
+ clock format -2411465104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1893 12:34:56 die i mensis viii annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Aug 213 2412677 08 viii 8 08/01/1893 die i mensis viii annoque mdcccxciii 93 xciii 1893}
+test clock-2.328 {conversion of 1893-08-31} {
+ clock format -2408873104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1893 12:34:56 die xxxi mensis viii annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Aug 243 2412707 08 viii 8 08/31/1893 die xxxi mensis viii annoque mdcccxciii 93 xciii 1893}
+test clock-2.329 {conversion of 1893-09-01} {
+ clock format -2408786704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1893 12:34:56 die i mensis ix annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Sep 244 2412708 09 ix 9 09/01/1893 die i mensis ix annoque mdcccxciii 93 xciii 1893}
+test clock-2.330 {conversion of 1893-09-30} {
+ clock format -2406281104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1893 12:34:56 die xxx mensis ix annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Sep 273 2412737 09 ix 9 09/30/1893 die xxx mensis ix annoque mdcccxciii 93 xciii 1893}
+test clock-2.331 {conversion of 1893-10-01} {
+ clock format -2406194704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1893 12:34:56 die i mensis x annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Oct 274 2412738 10 x 10 10/01/1893 die i mensis x annoque mdcccxciii 93 xciii 1893}
+test clock-2.332 {conversion of 1893-10-31} {
+ clock format -2403602704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1893 12:34:56 die xxxi mensis x annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Oct 304 2412768 10 x 10 10/31/1893 die xxxi mensis x annoque mdcccxciii 93 xciii 1893}
+test clock-2.333 {conversion of 1893-11-01} {
+ clock format -2403516304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1893 12:34:56 die i mensis xi annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Nov 305 2412769 11 xi 11 11/01/1893 die i mensis xi annoque mdcccxciii 93 xciii 1893}
+test clock-2.334 {conversion of 1893-11-30} {
+ clock format -2401010704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1893 12:34:56 die xxx mensis xi annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Nov 334 2412798 11 xi 11 11/30/1893 die xxx mensis xi annoque mdcccxciii 93 xciii 1893}
+test clock-2.335 {conversion of 1893-12-01} {
+ clock format -2400924304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1893 12:34:56 die i mensis xii annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Dec 335 2412799 12 xii 12 12/01/1893 die i mensis xii annoque mdcccxciii 93 xciii 1893}
+test clock-2.336 {conversion of 1893-12-31} {
+ clock format -2398332304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1893 12:34:56 die xxxi mensis xii annoque mdcccxciii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Dec 365 2412829 12 xii 12 12/31/1893 die xxxi mensis xii annoque mdcccxciii 93 xciii 1893}
+test clock-2.337 {conversion of 1894-01-01} {
+ clock format -2398245904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1894 12:34:56 die i mensis i annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jan 001 2412830 01 i 1 01/01/1894 die i mensis i annoque mdcccxciv 94 xciv 1894}
+test clock-2.338 {conversion of 1894-01-31} {
+ clock format -2395653904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1894 12:34:56 die xxxi mensis i annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jan 031 2412860 01 i 1 01/31/1894 die xxxi mensis i annoque mdcccxciv 94 xciv 1894}
+test clock-2.339 {conversion of 1894-02-01} {
+ clock format -2395567504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1894 12:34:56 die i mensis ii annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Feb 032 2412861 02 ii 2 02/01/1894 die i mensis ii annoque mdcccxciv 94 xciv 1894}
+test clock-2.340 {conversion of 1894-02-28} {
+ clock format -2393234704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1894 12:34:56 die xxviii mensis ii annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 28 xxviii 28 xxviii Feb 059 2412888 02 ii 2 02/28/1894 die xxviii mensis ii annoque mdcccxciv 94 xciv 1894}
+test clock-2.341 {conversion of 1894-03-01} {
+ clock format -2393148304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1894 12:34:56 die i mensis iii annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Mar 060 2412889 03 iii 3 03/01/1894 die i mensis iii annoque mdcccxciv 94 xciv 1894}
+test clock-2.342 {conversion of 1894-03-31} {
+ clock format -2390556304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1894 12:34:56 die xxxi mensis iii annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Mar 090 2412919 03 iii 3 03/31/1894 die xxxi mensis iii annoque mdcccxciv 94 xciv 1894}
+test clock-2.343 {conversion of 1894-04-01} {
+ clock format -2390469904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1894 12:34:56 die i mensis iv annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Apr 091 2412920 04 iv 4 04/01/1894 die i mensis iv annoque mdcccxciv 94 xciv 1894}
+test clock-2.344 {conversion of 1894-04-30} {
+ clock format -2387964304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1894 12:34:56 die xxx mensis iv annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Apr 120 2412949 04 iv 4 04/30/1894 die xxx mensis iv annoque mdcccxciv 94 xciv 1894}
+test clock-2.345 {conversion of 1894-05-01} {
+ clock format -2387877904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1894 12:34:56 die i mensis v annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 01 i 1 i May 121 2412950 05 v 5 05/01/1894 die i mensis v annoque mdcccxciv 94 xciv 1894}
+test clock-2.346 {conversion of 1894-05-31} {
+ clock format -2385285904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1894 12:34:56 die xxxi mensis v annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi May 151 2412980 05 v 5 05/31/1894 die xxxi mensis v annoque mdcccxciv 94 xciv 1894}
+test clock-2.347 {conversion of 1894-06-01} {
+ clock format -2385199504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1894 12:34:56 die i mensis vi annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jun 152 2412981 06 vi 6 06/01/1894 die i mensis vi annoque mdcccxciv 94 xciv 1894}
+test clock-2.348 {conversion of 1894-06-30} {
+ clock format -2382693904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1894 12:34:56 die xxx mensis vi annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Jun 181 2413010 06 vi 6 06/30/1894 die xxx mensis vi annoque mdcccxciv 94 xciv 1894}
+test clock-2.349 {conversion of 1894-07-01} {
+ clock format -2382607504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1894 12:34:56 die i mensis vii annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jul 182 2413011 07 vii 7 07/01/1894 die i mensis vii annoque mdcccxciv 94 xciv 1894}
+test clock-2.350 {conversion of 1894-07-31} {
+ clock format -2380015504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1894 12:34:56 die xxxi mensis vii annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jul 212 2413041 07 vii 7 07/31/1894 die xxxi mensis vii annoque mdcccxciv 94 xciv 1894}
+test clock-2.351 {conversion of 1894-08-01} {
+ clock format -2379929104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1894 12:34:56 die i mensis viii annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Aug 213 2413042 08 viii 8 08/01/1894 die i mensis viii annoque mdcccxciv 94 xciv 1894}
+test clock-2.352 {conversion of 1894-08-31} {
+ clock format -2377337104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1894 12:34:56 die xxxi mensis viii annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Aug 243 2413072 08 viii 8 08/31/1894 die xxxi mensis viii annoque mdcccxciv 94 xciv 1894}
+test clock-2.353 {conversion of 1894-09-01} {
+ clock format -2377250704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1894 12:34:56 die i mensis ix annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Sep 244 2413073 09 ix 9 09/01/1894 die i mensis ix annoque mdcccxciv 94 xciv 1894}
+test clock-2.354 {conversion of 1894-09-30} {
+ clock format -2374745104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1894 12:34:56 die xxx mensis ix annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Sep 273 2413102 09 ix 9 09/30/1894 die xxx mensis ix annoque mdcccxciv 94 xciv 1894}
+test clock-2.355 {conversion of 1894-10-01} {
+ clock format -2374658704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1894 12:34:56 die i mensis x annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Oct 274 2413103 10 x 10 10/01/1894 die i mensis x annoque mdcccxciv 94 xciv 1894}
+test clock-2.356 {conversion of 1894-10-31} {
+ clock format -2372066704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1894 12:34:56 die xxxi mensis x annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Oct 304 2413133 10 x 10 10/31/1894 die xxxi mensis x annoque mdcccxciv 94 xciv 1894}
+test clock-2.357 {conversion of 1894-11-01} {
+ clock format -2371980304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1894 12:34:56 die i mensis xi annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Nov 305 2413134 11 xi 11 11/01/1894 die i mensis xi annoque mdcccxciv 94 xciv 1894}
+test clock-2.358 {conversion of 1894-11-30} {
+ clock format -2369474704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1894 12:34:56 die xxx mensis xi annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Nov 334 2413163 11 xi 11 11/30/1894 die xxx mensis xi annoque mdcccxciv 94 xciv 1894}
+test clock-2.359 {conversion of 1894-12-01} {
+ clock format -2369388304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1894 12:34:56 die i mensis xii annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Dec 335 2413164 12 xii 12 12/01/1894 die i mensis xii annoque mdcccxciv 94 xciv 1894}
+test clock-2.360 {conversion of 1894-12-31} {
+ clock format -2366796304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1894 12:34:56 die xxxi mensis xii annoque mdcccxciv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Dec 365 2413194 12 xii 12 12/31/1894 die xxxi mensis xii annoque mdcccxciv 94 xciv 1894}
+test clock-2.361 {conversion of 1895-01-01} {
+ clock format -2366709904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1895 12:34:56 die i mensis i annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jan 001 2413195 01 i 1 01/01/1895 die i mensis i annoque mdcccxcv 95 xcv 1895}
+test clock-2.362 {conversion of 1895-01-31} {
+ clock format -2364117904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1895 12:34:56 die xxxi mensis i annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jan 031 2413225 01 i 1 01/31/1895 die xxxi mensis i annoque mdcccxcv 95 xcv 1895}
+test clock-2.363 {conversion of 1895-02-01} {
+ clock format -2364031504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1895 12:34:56 die i mensis ii annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Feb 032 2413226 02 ii 2 02/01/1895 die i mensis ii annoque mdcccxcv 95 xcv 1895}
+test clock-2.364 {conversion of 1895-02-28} {
+ clock format -2361698704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1895 12:34:56 die xxviii mensis ii annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 28 xxviii 28 xxviii Feb 059 2413253 02 ii 2 02/28/1895 die xxviii mensis ii annoque mdcccxcv 95 xcv 1895}
+test clock-2.365 {conversion of 1895-03-01} {
+ clock format -2361612304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1895 12:34:56 die i mensis iii annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Mar 060 2413254 03 iii 3 03/01/1895 die i mensis iii annoque mdcccxcv 95 xcv 1895}
+test clock-2.366 {conversion of 1895-03-31} {
+ clock format -2359020304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1895 12:34:56 die xxxi mensis iii annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Mar 090 2413284 03 iii 3 03/31/1895 die xxxi mensis iii annoque mdcccxcv 95 xcv 1895}
+test clock-2.367 {conversion of 1895-04-01} {
+ clock format -2358933904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1895 12:34:56 die i mensis iv annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Apr 091 2413285 04 iv 4 04/01/1895 die i mensis iv annoque mdcccxcv 95 xcv 1895}
+test clock-2.368 {conversion of 1895-04-30} {
+ clock format -2356428304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1895 12:34:56 die xxx mensis iv annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Apr 120 2413314 04 iv 4 04/30/1895 die xxx mensis iv annoque mdcccxcv 95 xcv 1895}
+test clock-2.369 {conversion of 1895-05-01} {
+ clock format -2356341904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1895 12:34:56 die i mensis v annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 01 i 1 i May 121 2413315 05 v 5 05/01/1895 die i mensis v annoque mdcccxcv 95 xcv 1895}
+test clock-2.370 {conversion of 1895-05-31} {
+ clock format -2353749904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1895 12:34:56 die xxxi mensis v annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi May 151 2413345 05 v 5 05/31/1895 die xxxi mensis v annoque mdcccxcv 95 xcv 1895}
+test clock-2.371 {conversion of 1895-06-01} {
+ clock format -2353663504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1895 12:34:56 die i mensis vi annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jun 152 2413346 06 vi 6 06/01/1895 die i mensis vi annoque mdcccxcv 95 xcv 1895}
+test clock-2.372 {conversion of 1895-06-30} {
+ clock format -2351157904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1895 12:34:56 die xxx mensis vi annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Jun 181 2413375 06 vi 6 06/30/1895 die xxx mensis vi annoque mdcccxcv 95 xcv 1895}
+test clock-2.373 {conversion of 1895-07-01} {
+ clock format -2351071504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1895 12:34:56 die i mensis vii annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jul 182 2413376 07 vii 7 07/01/1895 die i mensis vii annoque mdcccxcv 95 xcv 1895}
+test clock-2.374 {conversion of 1895-07-31} {
+ clock format -2348479504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1895 12:34:56 die xxxi mensis vii annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jul 212 2413406 07 vii 7 07/31/1895 die xxxi mensis vii annoque mdcccxcv 95 xcv 1895}
+test clock-2.375 {conversion of 1895-08-01} {
+ clock format -2348393104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1895 12:34:56 die i mensis viii annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Aug 213 2413407 08 viii 8 08/01/1895 die i mensis viii annoque mdcccxcv 95 xcv 1895}
+test clock-2.376 {conversion of 1895-08-31} {
+ clock format -2345801104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1895 12:34:56 die xxxi mensis viii annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Aug 243 2413437 08 viii 8 08/31/1895 die xxxi mensis viii annoque mdcccxcv 95 xcv 1895}
+test clock-2.377 {conversion of 1895-09-01} {
+ clock format -2345714704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1895 12:34:56 die i mensis ix annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Sep 244 2413438 09 ix 9 09/01/1895 die i mensis ix annoque mdcccxcv 95 xcv 1895}
+test clock-2.378 {conversion of 1895-09-30} {
+ clock format -2343209104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1895 12:34:56 die xxx mensis ix annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Sep 273 2413467 09 ix 9 09/30/1895 die xxx mensis ix annoque mdcccxcv 95 xcv 1895}
+test clock-2.379 {conversion of 1895-10-01} {
+ clock format -2343122704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1895 12:34:56 die i mensis x annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Oct 274 2413468 10 x 10 10/01/1895 die i mensis x annoque mdcccxcv 95 xcv 1895}
+test clock-2.380 {conversion of 1895-10-31} {
+ clock format -2340530704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1895 12:34:56 die xxxi mensis x annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Oct 304 2413498 10 x 10 10/31/1895 die xxxi mensis x annoque mdcccxcv 95 xcv 1895}
+test clock-2.381 {conversion of 1895-11-01} {
+ clock format -2340444304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1895 12:34:56 die i mensis xi annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Nov 305 2413499 11 xi 11 11/01/1895 die i mensis xi annoque mdcccxcv 95 xcv 1895}
+test clock-2.382 {conversion of 1895-11-30} {
+ clock format -2337938704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1895 12:34:56 die xxx mensis xi annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Nov 334 2413528 11 xi 11 11/30/1895 die xxx mensis xi annoque mdcccxcv 95 xcv 1895}
+test clock-2.383 {conversion of 1895-12-01} {
+ clock format -2337852304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1895 12:34:56 die i mensis xii annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 01 i 1 i Dec 335 2413529 12 xii 12 12/01/1895 die i mensis xii annoque mdcccxcv 95 xcv 1895}
+test clock-2.384 {conversion of 1895-12-31} {
+ clock format -2335260304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1895 12:34:56 die xxxi mensis xii annoque mdcccxcv xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Dec 365 2413559 12 xii 12 12/31/1895 die xxxi mensis xii annoque mdcccxcv 95 xcv 1895}
+test clock-2.385 {conversion of 1896-01-01} {
+ clock format -2335173904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1896 12:34:56 die i mensis i annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jan 001 2413560 01 i 1 01/01/1896 die i mensis i annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.386 {conversion of 1896-01-31} {
+ clock format -2332581904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1896 12:34:56 die xxxi mensis i annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jan 031 2413590 01 i 1 01/31/1896 die xxxi mensis i annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.387 {conversion of 1896-02-01} {
+ clock format -2332495504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1896 12:34:56 die i mensis ii annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Feb 032 2413591 02 ii 2 02/01/1896 die i mensis ii annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.388 {conversion of 1896-02-29} {
+ clock format -2330076304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1896 12:34:56 die xxix mensis ii annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 29 xxix 29 xxix Feb 060 2413619 02 ii 2 02/29/1896 die xxix mensis ii annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.389 {conversion of 1896-03-01} {
+ clock format -2329989904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1896 12:34:56 die i mensis iii annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Mar 061 2413620 03 iii 3 03/01/1896 die i mensis iii annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.390 {conversion of 1896-03-31} {
+ clock format -2327397904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1896 12:34:56 die xxxi mensis iii annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Mar 091 2413650 03 iii 3 03/31/1896 die xxxi mensis iii annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.391 {conversion of 1896-04-01} {
+ clock format -2327311504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1896 12:34:56 die i mensis iv annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Apr 092 2413651 04 iv 4 04/01/1896 die i mensis iv annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.392 {conversion of 1896-04-30} {
+ clock format -2324805904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1896 12:34:56 die xxx mensis iv annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Apr 121 2413680 04 iv 4 04/30/1896 die xxx mensis iv annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.393 {conversion of 1896-05-01} {
+ clock format -2324719504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1896 12:34:56 die i mensis v annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i May 122 2413681 05 v 5 05/01/1896 die i mensis v annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.394 {conversion of 1896-05-31} {
+ clock format -2322127504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1896 12:34:56 die xxxi mensis v annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi May 152 2413711 05 v 5 05/31/1896 die xxxi mensis v annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.395 {conversion of 1896-06-01} {
+ clock format -2322041104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1896 12:34:56 die i mensis vi annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jun 153 2413712 06 vi 6 06/01/1896 die i mensis vi annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.396 {conversion of 1896-06-30} {
+ clock format -2319535504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1896 12:34:56 die xxx mensis vi annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Jun 182 2413741 06 vi 6 06/30/1896 die xxx mensis vi annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.397 {conversion of 1896-07-01} {
+ clock format -2319449104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1896 12:34:56 die i mensis vii annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jul 183 2413742 07 vii 7 07/01/1896 die i mensis vii annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.398 {conversion of 1896-07-31} {
+ clock format -2316857104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1896 12:34:56 die xxxi mensis vii annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jul 213 2413772 07 vii 7 07/31/1896 die xxxi mensis vii annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.399 {conversion of 1896-08-01} {
+ clock format -2316770704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1896 12:34:56 die i mensis viii annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Aug 214 2413773 08 viii 8 08/01/1896 die i mensis viii annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.400 {conversion of 1896-08-31} {
+ clock format -2314178704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1896 12:34:56 die xxxi mensis viii annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Aug 244 2413803 08 viii 8 08/31/1896 die xxxi mensis viii annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.401 {conversion of 1896-09-01} {
+ clock format -2314092304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1896 12:34:56 die i mensis ix annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Sep 245 2413804 09 ix 9 09/01/1896 die i mensis ix annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.402 {conversion of 1896-09-30} {
+ clock format -2311586704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1896 12:34:56 die xxx mensis ix annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Sep 274 2413833 09 ix 9 09/30/1896 die xxx mensis ix annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.403 {conversion of 1896-10-01} {
+ clock format -2311500304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1896 12:34:56 die i mensis x annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Oct 275 2413834 10 x 10 10/01/1896 die i mensis x annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.404 {conversion of 1896-10-31} {
+ clock format -2308908304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1896 12:34:56 die xxxi mensis x annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Oct 305 2413864 10 x 10 10/31/1896 die xxxi mensis x annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.405 {conversion of 1896-11-01} {
+ clock format -2308821904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1896 12:34:56 die i mensis xi annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Nov 306 2413865 11 xi 11 11/01/1896 die i mensis xi annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.406 {conversion of 1896-11-30} {
+ clock format -2306316304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1896 12:34:56 die xxx mensis xi annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Nov 335 2413894 11 xi 11 11/30/1896 die xxx mensis xi annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.407 {conversion of 1896-12-01} {
+ clock format -2306229904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1896 12:34:56 die i mensis xii annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 01 i 1 i Dec 336 2413895 12 xii 12 12/01/1896 die i mensis xii annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.408 {conversion of 1896-12-31} {
+ clock format -2303637904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1896 12:34:56 die xxxi mensis xii annoque mdcccxcvi xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Dec 366 2413925 12 xii 12 12/31/1896 die xxxi mensis xii annoque mdcccxcvi 96 xcvi 1896}
+test clock-2.409 {conversion of 1897-01-01} {
+ clock format -2303551504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1897 12:34:56 die i mensis i annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jan 001 2413926 01 i 1 01/01/1897 die i mensis i annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.410 {conversion of 1897-01-31} {
+ clock format -2300959504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1897 12:34:56 die xxxi mensis i annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jan 031 2413956 01 i 1 01/31/1897 die xxxi mensis i annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.411 {conversion of 1897-02-01} {
+ clock format -2300873104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1897 12:34:56 die i mensis ii annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Feb 032 2413957 02 ii 2 02/01/1897 die i mensis ii annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.412 {conversion of 1897-02-28} {
+ clock format -2298540304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1897 12:34:56 die xxviii mensis ii annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 28 xxviii 28 xxviii Feb 059 2413984 02 ii 2 02/28/1897 die xxviii mensis ii annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.413 {conversion of 1897-03-01} {
+ clock format -2298453904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1897 12:34:56 die i mensis iii annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Mar 060 2413985 03 iii 3 03/01/1897 die i mensis iii annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.414 {conversion of 1897-03-31} {
+ clock format -2295861904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1897 12:34:56 die xxxi mensis iii annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Mar 090 2414015 03 iii 3 03/31/1897 die xxxi mensis iii annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.415 {conversion of 1897-04-01} {
+ clock format -2295775504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1897 12:34:56 die i mensis iv annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Apr 091 2414016 04 iv 4 04/01/1897 die i mensis iv annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.416 {conversion of 1897-04-30} {
+ clock format -2293269904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1897 12:34:56 die xxx mensis iv annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Apr 120 2414045 04 iv 4 04/30/1897 die xxx mensis iv annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.417 {conversion of 1897-05-01} {
+ clock format -2293183504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1897 12:34:56 die i mensis v annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i May 121 2414046 05 v 5 05/01/1897 die i mensis v annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.418 {conversion of 1897-05-31} {
+ clock format -2290591504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1897 12:34:56 die xxxi mensis v annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi May 151 2414076 05 v 5 05/31/1897 die xxxi mensis v annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.419 {conversion of 1897-06-01} {
+ clock format -2290505104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1897 12:34:56 die i mensis vi annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jun 152 2414077 06 vi 6 06/01/1897 die i mensis vi annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.420 {conversion of 1897-06-30} {
+ clock format -2287999504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1897 12:34:56 die xxx mensis vi annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Jun 181 2414106 06 vi 6 06/30/1897 die xxx mensis vi annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.421 {conversion of 1897-07-01} {
+ clock format -2287913104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1897 12:34:56 die i mensis vii annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jul 182 2414107 07 vii 7 07/01/1897 die i mensis vii annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.422 {conversion of 1897-07-31} {
+ clock format -2285321104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1897 12:34:56 die xxxi mensis vii annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jul 212 2414137 07 vii 7 07/31/1897 die xxxi mensis vii annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.423 {conversion of 1897-08-01} {
+ clock format -2285234704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1897 12:34:56 die i mensis viii annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Aug 213 2414138 08 viii 8 08/01/1897 die i mensis viii annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.424 {conversion of 1897-08-31} {
+ clock format -2282642704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1897 12:34:56 die xxxi mensis viii annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Aug 243 2414168 08 viii 8 08/31/1897 die xxxi mensis viii annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.425 {conversion of 1897-09-01} {
+ clock format -2282556304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1897 12:34:56 die i mensis ix annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Sep 244 2414169 09 ix 9 09/01/1897 die i mensis ix annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.426 {conversion of 1897-09-30} {
+ clock format -2280050704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1897 12:34:56 die xxx mensis ix annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Sep 273 2414198 09 ix 9 09/30/1897 die xxx mensis ix annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.427 {conversion of 1897-10-01} {
+ clock format -2279964304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1897 12:34:56 die i mensis x annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Oct 274 2414199 10 x 10 10/01/1897 die i mensis x annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.428 {conversion of 1897-10-31} {
+ clock format -2277372304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1897 12:34:56 die xxxi mensis x annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Oct 304 2414229 10 x 10 10/31/1897 die xxxi mensis x annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.429 {conversion of 1897-11-01} {
+ clock format -2277285904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1897 12:34:56 die i mensis xi annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Nov 305 2414230 11 xi 11 11/01/1897 die i mensis xi annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.430 {conversion of 1897-11-30} {
+ clock format -2274780304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1897 12:34:56 die xxx mensis xi annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Nov 334 2414259 11 xi 11 11/30/1897 die xxx mensis xi annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.431 {conversion of 1897-12-01} {
+ clock format -2274693904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1897 12:34:56 die i mensis xii annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Dec 335 2414260 12 xii 12 12/01/1897 die i mensis xii annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.432 {conversion of 1897-12-31} {
+ clock format -2272101904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1897 12:34:56 die xxxi mensis xii annoque mdcccxcvii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Dec 365 2414290 12 xii 12 12/31/1897 die xxxi mensis xii annoque mdcccxcvii 97 xcvii 1897}
+test clock-2.433 {conversion of 1898-01-01} {
+ clock format -2272015504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1898 12:34:56 die i mensis i annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jan 001 2414291 01 i 1 01/01/1898 die i mensis i annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.434 {conversion of 1898-01-31} {
+ clock format -2269423504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1898 12:34:56 die xxxi mensis i annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jan 031 2414321 01 i 1 01/31/1898 die xxxi mensis i annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.435 {conversion of 1898-02-01} {
+ clock format -2269337104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1898 12:34:56 die i mensis ii annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Feb 032 2414322 02 ii 2 02/01/1898 die i mensis ii annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.436 {conversion of 1898-02-28} {
+ clock format -2267004304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1898 12:34:56 die xxviii mensis ii annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 28 xxviii 28 xxviii Feb 059 2414349 02 ii 2 02/28/1898 die xxviii mensis ii annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.437 {conversion of 1898-03-01} {
+ clock format -2266917904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1898 12:34:56 die i mensis iii annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Mar 060 2414350 03 iii 3 03/01/1898 die i mensis iii annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.438 {conversion of 1898-03-31} {
+ clock format -2264325904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1898 12:34:56 die xxxi mensis iii annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Mar 090 2414380 03 iii 3 03/31/1898 die xxxi mensis iii annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.439 {conversion of 1898-04-01} {
+ clock format -2264239504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1898 12:34:56 die i mensis iv annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Apr 091 2414381 04 iv 4 04/01/1898 die i mensis iv annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.440 {conversion of 1898-04-30} {
+ clock format -2261733904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1898 12:34:56 die xxx mensis iv annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Apr 120 2414410 04 iv 4 04/30/1898 die xxx mensis iv annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.441 {conversion of 1898-05-01} {
+ clock format -2261647504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1898 12:34:56 die i mensis v annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i May 121 2414411 05 v 5 05/01/1898 die i mensis v annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.442 {conversion of 1898-05-31} {
+ clock format -2259055504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1898 12:34:56 die xxxi mensis v annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi May 151 2414441 05 v 5 05/31/1898 die xxxi mensis v annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.443 {conversion of 1898-06-01} {
+ clock format -2258969104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1898 12:34:56 die i mensis vi annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jun 152 2414442 06 vi 6 06/01/1898 die i mensis vi annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.444 {conversion of 1898-06-30} {
+ clock format -2256463504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1898 12:34:56 die xxx mensis vi annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Jun 181 2414471 06 vi 6 06/30/1898 die xxx mensis vi annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.445 {conversion of 1898-07-01} {
+ clock format -2256377104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1898 12:34:56 die i mensis vii annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jul 182 2414472 07 vii 7 07/01/1898 die i mensis vii annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.446 {conversion of 1898-07-31} {
+ clock format -2253785104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1898 12:34:56 die xxxi mensis vii annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jul 212 2414502 07 vii 7 07/31/1898 die xxxi mensis vii annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.447 {conversion of 1898-08-01} {
+ clock format -2253698704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1898 12:34:56 die i mensis viii annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Aug 213 2414503 08 viii 8 08/01/1898 die i mensis viii annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.448 {conversion of 1898-08-31} {
+ clock format -2251106704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1898 12:34:56 die xxxi mensis viii annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Aug 243 2414533 08 viii 8 08/31/1898 die xxxi mensis viii annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.449 {conversion of 1898-09-01} {
+ clock format -2251020304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1898 12:34:56 die i mensis ix annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Sep 244 2414534 09 ix 9 09/01/1898 die i mensis ix annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.450 {conversion of 1898-09-30} {
+ clock format -2248514704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1898 12:34:56 die xxx mensis ix annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Sep 273 2414563 09 ix 9 09/30/1898 die xxx mensis ix annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.451 {conversion of 1898-10-01} {
+ clock format -2248428304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1898 12:34:56 die i mensis x annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Oct 274 2414564 10 x 10 10/01/1898 die i mensis x annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.452 {conversion of 1898-10-31} {
+ clock format -2245836304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1898 12:34:56 die xxxi mensis x annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Oct 304 2414594 10 x 10 10/31/1898 die xxxi mensis x annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.453 {conversion of 1898-11-01} {
+ clock format -2245749904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1898 12:34:56 die i mensis xi annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Nov 305 2414595 11 xi 11 11/01/1898 die i mensis xi annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.454 {conversion of 1898-11-30} {
+ clock format -2243244304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1898 12:34:56 die xxx mensis xi annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Nov 334 2414624 11 xi 11 11/30/1898 die xxx mensis xi annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.455 {conversion of 1898-12-01} {
+ clock format -2243157904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1898 12:34:56 die i mensis xii annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 01 i 1 i Dec 335 2414625 12 xii 12 12/01/1898 die i mensis xii annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.456 {conversion of 1898-12-31} {
+ clock format -2240565904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1898 12:34:56 die xxxi mensis xii annoque mdcccxcviii xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Dec 365 2414655 12 xii 12 12/31/1898 die xxxi mensis xii annoque mdcccxcviii 98 xcviii 1898}
+test clock-2.457 {conversion of 1899-01-01} {
+ clock format -2240479504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1899 12:34:56 die i mensis i annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jan 001 2414656 01 i 1 01/01/1899 die i mensis i annoque mdcccxcix 99 xcix 1899}
+test clock-2.458 {conversion of 1899-01-31} {
+ clock format -2237887504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1899 12:34:56 die xxxi mensis i annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jan 031 2414686 01 i 1 01/31/1899 die xxxi mensis i annoque mdcccxcix 99 xcix 1899}
+test clock-2.459 {conversion of 1899-02-01} {
+ clock format -2237801104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1899 12:34:56 die i mensis ii annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Feb 032 2414687 02 ii 2 02/01/1899 die i mensis ii annoque mdcccxcix 99 xcix 1899}
+test clock-2.460 {conversion of 1899-02-28} {
+ clock format -2235468304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1899 12:34:56 die xxviii mensis ii annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 28 xxviii 28 xxviii Feb 059 2414714 02 ii 2 02/28/1899 die xxviii mensis ii annoque mdcccxcix 99 xcix 1899}
+test clock-2.461 {conversion of 1899-03-01} {
+ clock format -2235381904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1899 12:34:56 die i mensis iii annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Mar 060 2414715 03 iii 3 03/01/1899 die i mensis iii annoque mdcccxcix 99 xcix 1899}
+test clock-2.462 {conversion of 1899-03-31} {
+ clock format -2232789904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1899 12:34:56 die xxxi mensis iii annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Mar 090 2414745 03 iii 3 03/31/1899 die xxxi mensis iii annoque mdcccxcix 99 xcix 1899}
+test clock-2.463 {conversion of 1899-04-01} {
+ clock format -2232703504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1899 12:34:56 die i mensis iv annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Apr 091 2414746 04 iv 4 04/01/1899 die i mensis iv annoque mdcccxcix 99 xcix 1899}
+test clock-2.464 {conversion of 1899-04-30} {
+ clock format -2230197904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1899 12:34:56 die xxx mensis iv annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Apr 120 2414775 04 iv 4 04/30/1899 die xxx mensis iv annoque mdcccxcix 99 xcix 1899}
+test clock-2.465 {conversion of 1899-05-01} {
+ clock format -2230111504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1899 12:34:56 die i mensis v annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 01 i 1 i May 121 2414776 05 v 5 05/01/1899 die i mensis v annoque mdcccxcix 99 xcix 1899}
+test clock-2.466 {conversion of 1899-05-31} {
+ clock format -2227519504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1899 12:34:56 die xxxi mensis v annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi May 151 2414806 05 v 5 05/31/1899 die xxxi mensis v annoque mdcccxcix 99 xcix 1899}
+test clock-2.467 {conversion of 1899-06-01} {
+ clock format -2227433104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1899 12:34:56 die i mensis vi annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jun 152 2414807 06 vi 6 06/01/1899 die i mensis vi annoque mdcccxcix 99 xcix 1899}
+test clock-2.468 {conversion of 1899-06-30} {
+ clock format -2224927504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1899 12:34:56 die xxx mensis vi annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Jun 181 2414836 06 vi 6 06/30/1899 die xxx mensis vi annoque mdcccxcix 99 xcix 1899}
+test clock-2.469 {conversion of 1899-07-01} {
+ clock format -2224841104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1899 12:34:56 die i mensis vii annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Jul 182 2414837 07 vii 7 07/01/1899 die i mensis vii annoque mdcccxcix 99 xcix 1899}
+test clock-2.470 {conversion of 1899-07-31} {
+ clock format -2222249104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1899 12:34:56 die xxxi mensis vii annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Jul 212 2414867 07 vii 7 07/31/1899 die xxxi mensis vii annoque mdcccxcix 99 xcix 1899}
+test clock-2.471 {conversion of 1899-08-01} {
+ clock format -2222162704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1899 12:34:56 die i mensis viii annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Aug 213 2414868 08 viii 8 08/01/1899 die i mensis viii annoque mdcccxcix 99 xcix 1899}
+test clock-2.472 {conversion of 1899-08-31} {
+ clock format -2219570704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1899 12:34:56 die xxxi mensis viii annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Aug 243 2414898 08 viii 8 08/31/1899 die xxxi mensis viii annoque mdcccxcix 99 xcix 1899}
+test clock-2.473 {conversion of 1899-09-01} {
+ clock format -2219484304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1899 12:34:56 die i mensis ix annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Sep 244 2414899 09 ix 9 09/01/1899 die i mensis ix annoque mdcccxcix 99 xcix 1899}
+test clock-2.474 {conversion of 1899-09-30} {
+ clock format -2216978704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1899 12:34:56 die xxx mensis ix annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Sep 273 2414928 09 ix 9 09/30/1899 die xxx mensis ix annoque mdcccxcix 99 xcix 1899}
+test clock-2.475 {conversion of 1899-10-01} {
+ clock format -2216892304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1899 12:34:56 die i mensis x annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Oct 274 2414929 10 x 10 10/01/1899 die i mensis x annoque mdcccxcix 99 xcix 1899}
+test clock-2.476 {conversion of 1899-10-31} {
+ clock format -2214300304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1899 12:34:56 die xxxi mensis x annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Oct 304 2414959 10 x 10 10/31/1899 die xxxi mensis x annoque mdcccxcix 99 xcix 1899}
+test clock-2.477 {conversion of 1899-11-01} {
+ clock format -2214213904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1899 12:34:56 die i mensis xi annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Nov 305 2414960 11 xi 11 11/01/1899 die i mensis xi annoque mdcccxcix 99 xcix 1899}
+test clock-2.478 {conversion of 1899-11-30} {
+ clock format -2211708304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1899 12:34:56 die xxx mensis xi annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 30 xxx 30 xxx Nov 334 2414989 11 xi 11 11/30/1899 die xxx mensis xi annoque mdcccxcix 99 xcix 1899}
+test clock-2.479 {conversion of 1899-12-01} {
+ clock format -2211621904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1899 12:34:56 die i mensis xii annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 01 i 1 i Dec 335 2414990 12 xii 12 12/01/1899 die i mensis xii annoque mdcccxcix 99 xcix 1899}
+test clock-2.480 {conversion of 1899-12-31} {
+ clock format -2209029904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1899 12:34:56 die xxxi mensis xii annoque mdcccxcix xii h xxxiv m lvi s 18 mdccc 31 xxxi 31 xxxi Dec 365 2415020 12 xii 12 12/31/1899 die xxxi mensis xii annoque mdcccxcix 99 xcix 1899}
+test clock-2.481 {conversion of 1900-01-01} {
+ clock format -2208943504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1900 12:34:56 die i mensis i annoque mcm? xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2415021 01 i 1 01/01/1900 die i mensis i annoque mcm? 00 ? 1900}
+test clock-2.482 {conversion of 1900-01-31} {
+ clock format -2206351504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1900 12:34:56 die xxxi mensis i annoque mcm? xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2415051 01 i 1 01/31/1900 die xxxi mensis i annoque mcm? 00 ? 1900}
+test clock-2.483 {conversion of 1900-02-01} {
+ clock format -2206265104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1900 12:34:56 die i mensis ii annoque mcm? xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2415052 02 ii 2 02/01/1900 die i mensis ii annoque mcm? 00 ? 1900}
+test clock-2.484 {conversion of 1900-02-28} {
+ clock format -2203932304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1900 12:34:56 die xxviii mensis ii annoque mcm? xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2415079 02 ii 2 02/28/1900 die xxviii mensis ii annoque mcm? 00 ? 1900}
+test clock-2.485 {conversion of 1900-03-01} {
+ clock format -2203845904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1900 12:34:56 die i mensis iii annoque mcm? xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2415080 03 iii 3 03/01/1900 die i mensis iii annoque mcm? 00 ? 1900}
+test clock-2.486 {conversion of 1900-03-31} {
+ clock format -2201253904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1900 12:34:56 die xxxi mensis iii annoque mcm? xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2415110 03 iii 3 03/31/1900 die xxxi mensis iii annoque mcm? 00 ? 1900}
+test clock-2.487 {conversion of 1900-04-01} {
+ clock format -2201167504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1900 12:34:56 die i mensis iv annoque mcm? xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2415111 04 iv 4 04/01/1900 die i mensis iv annoque mcm? 00 ? 1900}
+test clock-2.488 {conversion of 1900-04-30} {
+ clock format -2198661904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1900 12:34:56 die xxx mensis iv annoque mcm? xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2415140 04 iv 4 04/30/1900 die xxx mensis iv annoque mcm? 00 ? 1900}
+test clock-2.489 {conversion of 1900-05-01} {
+ clock format -2198575504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1900 12:34:56 die i mensis v annoque mcm? xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2415141 05 v 5 05/01/1900 die i mensis v annoque mcm? 00 ? 1900}
+test clock-2.490 {conversion of 1900-05-31} {
+ clock format -2195983504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1900 12:34:56 die xxxi mensis v annoque mcm? xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2415171 05 v 5 05/31/1900 die xxxi mensis v annoque mcm? 00 ? 1900}
+test clock-2.491 {conversion of 1900-06-01} {
+ clock format -2195897104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1900 12:34:56 die i mensis vi annoque mcm? xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2415172 06 vi 6 06/01/1900 die i mensis vi annoque mcm? 00 ? 1900}
+test clock-2.492 {conversion of 1900-06-30} {
+ clock format -2193391504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1900 12:34:56 die xxx mensis vi annoque mcm? xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2415201 06 vi 6 06/30/1900 die xxx mensis vi annoque mcm? 00 ? 1900}
+test clock-2.493 {conversion of 1900-07-01} {
+ clock format -2193305104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1900 12:34:56 die i mensis vii annoque mcm? xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2415202 07 vii 7 07/01/1900 die i mensis vii annoque mcm? 00 ? 1900}
+test clock-2.494 {conversion of 1900-07-31} {
+ clock format -2190713104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1900 12:34:56 die xxxi mensis vii annoque mcm? xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2415232 07 vii 7 07/31/1900 die xxxi mensis vii annoque mcm? 00 ? 1900}
+test clock-2.495 {conversion of 1900-08-01} {
+ clock format -2190626704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1900 12:34:56 die i mensis viii annoque mcm? xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2415233 08 viii 8 08/01/1900 die i mensis viii annoque mcm? 00 ? 1900}
+test clock-2.496 {conversion of 1900-08-31} {
+ clock format -2188034704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1900 12:34:56 die xxxi mensis viii annoque mcm? xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2415263 08 viii 8 08/31/1900 die xxxi mensis viii annoque mcm? 00 ? 1900}
+test clock-2.497 {conversion of 1900-09-01} {
+ clock format -2187948304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1900 12:34:56 die i mensis ix annoque mcm? xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2415264 09 ix 9 09/01/1900 die i mensis ix annoque mcm? 00 ? 1900}
+test clock-2.498 {conversion of 1900-09-30} {
+ clock format -2185442704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1900 12:34:56 die xxx mensis ix annoque mcm? xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2415293 09 ix 9 09/30/1900 die xxx mensis ix annoque mcm? 00 ? 1900}
+test clock-2.499 {conversion of 1900-10-01} {
+ clock format -2185356304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1900 12:34:56 die i mensis x annoque mcm? xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2415294 10 x 10 10/01/1900 die i mensis x annoque mcm? 00 ? 1900}
+test clock-2.500 {conversion of 1900-10-31} {
+ clock format -2182764304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1900 12:34:56 die xxxi mensis x annoque mcm? xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2415324 10 x 10 10/31/1900 die xxxi mensis x annoque mcm? 00 ? 1900}
+test clock-2.501 {conversion of 1900-11-01} {
+ clock format -2182677904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1900 12:34:56 die i mensis xi annoque mcm? xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2415325 11 xi 11 11/01/1900 die i mensis xi annoque mcm? 00 ? 1900}
+test clock-2.502 {conversion of 1900-11-30} {
+ clock format -2180172304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1900 12:34:56 die xxx mensis xi annoque mcm? xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2415354 11 xi 11 11/30/1900 die xxx mensis xi annoque mcm? 00 ? 1900}
+test clock-2.503 {conversion of 1900-12-01} {
+ clock format -2180085904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1900 12:34:56 die i mensis xii annoque mcm? xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2415355 12 xii 12 12/01/1900 die i mensis xii annoque mcm? 00 ? 1900}
+test clock-2.504 {conversion of 1900-12-31} {
+ clock format -2177493904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1900 12:34:56 die xxxi mensis xii annoque mcm? xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2415385 12 xii 12 12/31/1900 die xxxi mensis xii annoque mcm? 00 ? 1900}
+test clock-2.505 {conversion of 1944-01-01} {
+ clock format -820495504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1944 12:34:56 die i mensis i annoque mcmxliv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2431091 01 i 1 01/01/1944 die i mensis i annoque mcmxliv 44 xliv 1944}
+test clock-2.506 {conversion of 1944-01-31} {
+ clock format -817903504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1944 12:34:56 die xxxi mensis i annoque mcmxliv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2431121 01 i 1 01/31/1944 die xxxi mensis i annoque mcmxliv 44 xliv 1944}
+test clock-2.507 {conversion of 1944-02-01} {
+ clock format -817817104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1944 12:34:56 die i mensis ii annoque mcmxliv xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2431122 02 ii 2 02/01/1944 die i mensis ii annoque mcmxliv 44 xliv 1944}
+test clock-2.508 {conversion of 1944-02-29} {
+ clock format -815397904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1944 12:34:56 die xxix mensis ii annoque mcmxliv xii h xxxiv m lvi s 19 mcm 29 xxix 29 xxix Feb 060 2431150 02 ii 2 02/29/1944 die xxix mensis ii annoque mcmxliv 44 xliv 1944}
+test clock-2.509 {conversion of 1944-03-01} {
+ clock format -815311504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1944 12:34:56 die i mensis iii annoque mcmxliv xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 061 2431151 03 iii 3 03/01/1944 die i mensis iii annoque mcmxliv 44 xliv 1944}
+test clock-2.510 {conversion of 1944-03-31} {
+ clock format -812719504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1944 12:34:56 die xxxi mensis iii annoque mcmxliv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 091 2431181 03 iii 3 03/31/1944 die xxxi mensis iii annoque mcmxliv 44 xliv 1944}
+test clock-2.511 {conversion of 1944-04-01} {
+ clock format -812633104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1944 12:34:56 die i mensis iv annoque mcmxliv xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 092 2431182 04 iv 4 04/01/1944 die i mensis iv annoque mcmxliv 44 xliv 1944}
+test clock-2.512 {conversion of 1944-04-30} {
+ clock format -810127504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1944 12:34:56 die xxx mensis iv annoque mcmxliv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 121 2431211 04 iv 4 04/30/1944 die xxx mensis iv annoque mcmxliv 44 xliv 1944}
+test clock-2.513 {conversion of 1944-05-01} {
+ clock format -810041104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1944 12:34:56 die i mensis v annoque mcmxliv xii h xxxiv m lvi s 19 mcm 01 i 1 i May 122 2431212 05 v 5 05/01/1944 die i mensis v annoque mcmxliv 44 xliv 1944}
+test clock-2.514 {conversion of 1944-05-31} {
+ clock format -807449104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1944 12:34:56 die xxxi mensis v annoque mcmxliv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 152 2431242 05 v 5 05/31/1944 die xxxi mensis v annoque mcmxliv 44 xliv 1944}
+test clock-2.515 {conversion of 1944-06-01} {
+ clock format -807362704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1944 12:34:56 die i mensis vi annoque mcmxliv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 153 2431243 06 vi 6 06/01/1944 die i mensis vi annoque mcmxliv 44 xliv 1944}
+test clock-2.516 {conversion of 1944-06-30} {
+ clock format -804857104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1944 12:34:56 die xxx mensis vi annoque mcmxliv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 182 2431272 06 vi 6 06/30/1944 die xxx mensis vi annoque mcmxliv 44 xliv 1944}
+test clock-2.517 {conversion of 1944-07-01} {
+ clock format -804770704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1944 12:34:56 die i mensis vii annoque mcmxliv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 183 2431273 07 vii 7 07/01/1944 die i mensis vii annoque mcmxliv 44 xliv 1944}
+test clock-2.518 {conversion of 1944-07-31} {
+ clock format -802178704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1944 12:34:56 die xxxi mensis vii annoque mcmxliv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 213 2431303 07 vii 7 07/31/1944 die xxxi mensis vii annoque mcmxliv 44 xliv 1944}
+test clock-2.519 {conversion of 1944-08-01} {
+ clock format -802092304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1944 12:34:56 die i mensis viii annoque mcmxliv xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 214 2431304 08 viii 8 08/01/1944 die i mensis viii annoque mcmxliv 44 xliv 1944}
+test clock-2.520 {conversion of 1944-08-31} {
+ clock format -799500304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1944 12:34:56 die xxxi mensis viii annoque mcmxliv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 244 2431334 08 viii 8 08/31/1944 die xxxi mensis viii annoque mcmxliv 44 xliv 1944}
+test clock-2.521 {conversion of 1944-09-01} {
+ clock format -799413904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1944 12:34:56 die i mensis ix annoque mcmxliv xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 245 2431335 09 ix 9 09/01/1944 die i mensis ix annoque mcmxliv 44 xliv 1944}
+test clock-2.522 {conversion of 1944-09-30} {
+ clock format -796908304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1944 12:34:56 die xxx mensis ix annoque mcmxliv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 274 2431364 09 ix 9 09/30/1944 die xxx mensis ix annoque mcmxliv 44 xliv 1944}
+test clock-2.523 {conversion of 1944-10-01} {
+ clock format -796821904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1944 12:34:56 die i mensis x annoque mcmxliv xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 275 2431365 10 x 10 10/01/1944 die i mensis x annoque mcmxliv 44 xliv 1944}
+test clock-2.524 {conversion of 1944-10-31} {
+ clock format -794229904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1944 12:34:56 die xxxi mensis x annoque mcmxliv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 305 2431395 10 x 10 10/31/1944 die xxxi mensis x annoque mcmxliv 44 xliv 1944}
+test clock-2.525 {conversion of 1944-11-01} {
+ clock format -794143504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1944 12:34:56 die i mensis xi annoque mcmxliv xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 306 2431396 11 xi 11 11/01/1944 die i mensis xi annoque mcmxliv 44 xliv 1944}
+test clock-2.526 {conversion of 1944-11-30} {
+ clock format -791637904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1944 12:34:56 die xxx mensis xi annoque mcmxliv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 335 2431425 11 xi 11 11/30/1944 die xxx mensis xi annoque mcmxliv 44 xliv 1944}
+test clock-2.527 {conversion of 1944-12-01} {
+ clock format -791551504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1944 12:34:56 die i mensis xii annoque mcmxliv xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 336 2431426 12 xii 12 12/01/1944 die i mensis xii annoque mcmxliv 44 xliv 1944}
+test clock-2.528 {conversion of 1944-12-31} {
+ clock format -788959504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1944 12:34:56 die xxxi mensis xii annoque mcmxliv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 366 2431456 12 xii 12 12/31/1944 die xxxi mensis xii annoque mcmxliv 44 xliv 1944}
+test clock-2.529 {conversion of 1945-01-01} {
+ clock format -788873104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1945 12:34:56 die i mensis i annoque mcmxlv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2431457 01 i 1 01/01/1945 die i mensis i annoque mcmxlv 45 xlv 1945}
+test clock-2.530 {conversion of 1945-01-31} {
+ clock format -786281104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1945 12:34:56 die xxxi mensis i annoque mcmxlv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2431487 01 i 1 01/31/1945 die xxxi mensis i annoque mcmxlv 45 xlv 1945}
+test clock-2.531 {conversion of 1945-02-01} {
+ clock format -786194704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1945 12:34:56 die i mensis ii annoque mcmxlv xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2431488 02 ii 2 02/01/1945 die i mensis ii annoque mcmxlv 45 xlv 1945}
+test clock-2.532 {conversion of 1945-02-28} {
+ clock format -783861904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1945 12:34:56 die xxviii mensis ii annoque mcmxlv xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2431515 02 ii 2 02/28/1945 die xxviii mensis ii annoque mcmxlv 45 xlv 1945}
+test clock-2.533 {conversion of 1945-03-01} {
+ clock format -783775504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1945 12:34:56 die i mensis iii annoque mcmxlv xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2431516 03 iii 3 03/01/1945 die i mensis iii annoque mcmxlv 45 xlv 1945}
+test clock-2.534 {conversion of 1945-03-31} {
+ clock format -781183504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1945 12:34:56 die xxxi mensis iii annoque mcmxlv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2431546 03 iii 3 03/31/1945 die xxxi mensis iii annoque mcmxlv 45 xlv 1945}
+test clock-2.535 {conversion of 1945-04-01} {
+ clock format -781097104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1945 12:34:56 die i mensis iv annoque mcmxlv xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2431547 04 iv 4 04/01/1945 die i mensis iv annoque mcmxlv 45 xlv 1945}
+test clock-2.536 {conversion of 1945-04-30} {
+ clock format -778591504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1945 12:34:56 die xxx mensis iv annoque mcmxlv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2431576 04 iv 4 04/30/1945 die xxx mensis iv annoque mcmxlv 45 xlv 1945}
+test clock-2.537 {conversion of 1945-05-01} {
+ clock format -778505104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1945 12:34:56 die i mensis v annoque mcmxlv xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2431577 05 v 5 05/01/1945 die i mensis v annoque mcmxlv 45 xlv 1945}
+test clock-2.538 {conversion of 1945-05-31} {
+ clock format -775913104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1945 12:34:56 die xxxi mensis v annoque mcmxlv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2431607 05 v 5 05/31/1945 die xxxi mensis v annoque mcmxlv 45 xlv 1945}
+test clock-2.539 {conversion of 1945-06-01} {
+ clock format -775826704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1945 12:34:56 die i mensis vi annoque mcmxlv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2431608 06 vi 6 06/01/1945 die i mensis vi annoque mcmxlv 45 xlv 1945}
+test clock-2.540 {conversion of 1945-06-30} {
+ clock format -773321104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1945 12:34:56 die xxx mensis vi annoque mcmxlv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2431637 06 vi 6 06/30/1945 die xxx mensis vi annoque mcmxlv 45 xlv 1945}
+test clock-2.541 {conversion of 1945-07-01} {
+ clock format -773234704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1945 12:34:56 die i mensis vii annoque mcmxlv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2431638 07 vii 7 07/01/1945 die i mensis vii annoque mcmxlv 45 xlv 1945}
+test clock-2.542 {conversion of 1945-07-31} {
+ clock format -770642704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1945 12:34:56 die xxxi mensis vii annoque mcmxlv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2431668 07 vii 7 07/31/1945 die xxxi mensis vii annoque mcmxlv 45 xlv 1945}
+test clock-2.543 {conversion of 1945-08-01} {
+ clock format -770556304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1945 12:34:56 die i mensis viii annoque mcmxlv xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2431669 08 viii 8 08/01/1945 die i mensis viii annoque mcmxlv 45 xlv 1945}
+test clock-2.544 {conversion of 1945-08-31} {
+ clock format -767964304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1945 12:34:56 die xxxi mensis viii annoque mcmxlv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2431699 08 viii 8 08/31/1945 die xxxi mensis viii annoque mcmxlv 45 xlv 1945}
+test clock-2.545 {conversion of 1945-09-01} {
+ clock format -767877904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1945 12:34:56 die i mensis ix annoque mcmxlv xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2431700 09 ix 9 09/01/1945 die i mensis ix annoque mcmxlv 45 xlv 1945}
+test clock-2.546 {conversion of 1945-09-30} {
+ clock format -765372304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1945 12:34:56 die xxx mensis ix annoque mcmxlv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2431729 09 ix 9 09/30/1945 die xxx mensis ix annoque mcmxlv 45 xlv 1945}
+test clock-2.547 {conversion of 1945-10-01} {
+ clock format -765285904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1945 12:34:56 die i mensis x annoque mcmxlv xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2431730 10 x 10 10/01/1945 die i mensis x annoque mcmxlv 45 xlv 1945}
+test clock-2.548 {conversion of 1945-10-31} {
+ clock format -762693904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1945 12:34:56 die xxxi mensis x annoque mcmxlv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2431760 10 x 10 10/31/1945 die xxxi mensis x annoque mcmxlv 45 xlv 1945}
+test clock-2.549 {conversion of 1945-11-01} {
+ clock format -762607504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1945 12:34:56 die i mensis xi annoque mcmxlv xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2431761 11 xi 11 11/01/1945 die i mensis xi annoque mcmxlv 45 xlv 1945}
+test clock-2.550 {conversion of 1945-11-30} {
+ clock format -760101904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1945 12:34:56 die xxx mensis xi annoque mcmxlv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2431790 11 xi 11 11/30/1945 die xxx mensis xi annoque mcmxlv 45 xlv 1945}
+test clock-2.551 {conversion of 1945-12-01} {
+ clock format -760015504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1945 12:34:56 die i mensis xii annoque mcmxlv xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2431791 12 xii 12 12/01/1945 die i mensis xii annoque mcmxlv 45 xlv 1945}
+test clock-2.552 {conversion of 1945-12-31} {
+ clock format -757423504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1945 12:34:56 die xxxi mensis xii annoque mcmxlv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2431821 12 xii 12 12/31/1945 die xxxi mensis xii annoque mcmxlv 45 xlv 1945}
+test clock-2.553 {conversion of 1948-01-01} {
+ clock format -694265104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1948 12:34:56 die i mensis i annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2432552 01 i 1 01/01/1948 die i mensis i annoque mcmxlviii 48 xlviii 1948}
+test clock-2.554 {conversion of 1948-01-31} {
+ clock format -691673104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1948 12:34:56 die xxxi mensis i annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2432582 01 i 1 01/31/1948 die xxxi mensis i annoque mcmxlviii 48 xlviii 1948}
+test clock-2.555 {conversion of 1948-02-01} {
+ clock format -691586704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1948 12:34:56 die i mensis ii annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2432583 02 ii 2 02/01/1948 die i mensis ii annoque mcmxlviii 48 xlviii 1948}
+test clock-2.556 {conversion of 1948-02-29} {
+ clock format -689167504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1948 12:34:56 die xxix mensis ii annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 29 xxix 29 xxix Feb 060 2432611 02 ii 2 02/29/1948 die xxix mensis ii annoque mcmxlviii 48 xlviii 1948}
+test clock-2.557 {conversion of 1948-03-01} {
+ clock format -689081104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1948 12:34:56 die i mensis iii annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 061 2432612 03 iii 3 03/01/1948 die i mensis iii annoque mcmxlviii 48 xlviii 1948}
+test clock-2.558 {conversion of 1948-03-31} {
+ clock format -686489104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1948 12:34:56 die xxxi mensis iii annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 091 2432642 03 iii 3 03/31/1948 die xxxi mensis iii annoque mcmxlviii 48 xlviii 1948}
+test clock-2.559 {conversion of 1948-04-01} {
+ clock format -686402704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1948 12:34:56 die i mensis iv annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 092 2432643 04 iv 4 04/01/1948 die i mensis iv annoque mcmxlviii 48 xlviii 1948}
+test clock-2.560 {conversion of 1948-04-30} {
+ clock format -683897104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1948 12:34:56 die xxx mensis iv annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 121 2432672 04 iv 4 04/30/1948 die xxx mensis iv annoque mcmxlviii 48 xlviii 1948}
+test clock-2.561 {conversion of 1948-05-01} {
+ clock format -683810704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1948 12:34:56 die i mensis v annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 01 i 1 i May 122 2432673 05 v 5 05/01/1948 die i mensis v annoque mcmxlviii 48 xlviii 1948}
+test clock-2.562 {conversion of 1948-05-31} {
+ clock format -681218704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1948 12:34:56 die xxxi mensis v annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 152 2432703 05 v 5 05/31/1948 die xxxi mensis v annoque mcmxlviii 48 xlviii 1948}
+test clock-2.563 {conversion of 1948-06-01} {
+ clock format -681132304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1948 12:34:56 die i mensis vi annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 153 2432704 06 vi 6 06/01/1948 die i mensis vi annoque mcmxlviii 48 xlviii 1948}
+test clock-2.564 {conversion of 1948-06-30} {
+ clock format -678626704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1948 12:34:56 die xxx mensis vi annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 182 2432733 06 vi 6 06/30/1948 die xxx mensis vi annoque mcmxlviii 48 xlviii 1948}
+test clock-2.565 {conversion of 1948-07-01} {
+ clock format -678540304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1948 12:34:56 die i mensis vii annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 183 2432734 07 vii 7 07/01/1948 die i mensis vii annoque mcmxlviii 48 xlviii 1948}
+test clock-2.566 {conversion of 1948-07-31} {
+ clock format -675948304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1948 12:34:56 die xxxi mensis vii annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 213 2432764 07 vii 7 07/31/1948 die xxxi mensis vii annoque mcmxlviii 48 xlviii 1948}
+test clock-2.567 {conversion of 1948-08-01} {
+ clock format -675861904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1948 12:34:56 die i mensis viii annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 214 2432765 08 viii 8 08/01/1948 die i mensis viii annoque mcmxlviii 48 xlviii 1948}
+test clock-2.568 {conversion of 1948-08-31} {
+ clock format -673269904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1948 12:34:56 die xxxi mensis viii annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 244 2432795 08 viii 8 08/31/1948 die xxxi mensis viii annoque mcmxlviii 48 xlviii 1948}
+test clock-2.569 {conversion of 1948-09-01} {
+ clock format -673183504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1948 12:34:56 die i mensis ix annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 245 2432796 09 ix 9 09/01/1948 die i mensis ix annoque mcmxlviii 48 xlviii 1948}
+test clock-2.570 {conversion of 1948-09-30} {
+ clock format -670677904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1948 12:34:56 die xxx mensis ix annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 274 2432825 09 ix 9 09/30/1948 die xxx mensis ix annoque mcmxlviii 48 xlviii 1948}
+test clock-2.571 {conversion of 1948-10-01} {
+ clock format -670591504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1948 12:34:56 die i mensis x annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 275 2432826 10 x 10 10/01/1948 die i mensis x annoque mcmxlviii 48 xlviii 1948}
+test clock-2.572 {conversion of 1948-10-31} {
+ clock format -667999504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1948 12:34:56 die xxxi mensis x annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 305 2432856 10 x 10 10/31/1948 die xxxi mensis x annoque mcmxlviii 48 xlviii 1948}
+test clock-2.573 {conversion of 1948-11-01} {
+ clock format -667913104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1948 12:34:56 die i mensis xi annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 306 2432857 11 xi 11 11/01/1948 die i mensis xi annoque mcmxlviii 48 xlviii 1948}
+test clock-2.574 {conversion of 1948-11-30} {
+ clock format -665407504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1948 12:34:56 die xxx mensis xi annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 335 2432886 11 xi 11 11/30/1948 die xxx mensis xi annoque mcmxlviii 48 xlviii 1948}
+test clock-2.575 {conversion of 1948-12-01} {
+ clock format -665321104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1948 12:34:56 die i mensis xii annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 336 2432887 12 xii 12 12/01/1948 die i mensis xii annoque mcmxlviii 48 xlviii 1948}
+test clock-2.576 {conversion of 1948-12-31} {
+ clock format -662729104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1948 12:34:56 die xxxi mensis xii annoque mcmxlviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 366 2432917 12 xii 12 12/31/1948 die xxxi mensis xii annoque mcmxlviii 48 xlviii 1948}
+test clock-2.577 {conversion of 1949-01-01} {
+ clock format -662642704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1949 12:34:56 die i mensis i annoque mcmxlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2432918 01 i 1 01/01/1949 die i mensis i annoque mcmxlix 49 xlix 1949}
+test clock-2.578 {conversion of 1949-01-31} {
+ clock format -660050704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1949 12:34:56 die xxxi mensis i annoque mcmxlix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2432948 01 i 1 01/31/1949 die xxxi mensis i annoque mcmxlix 49 xlix 1949}
+test clock-2.579 {conversion of 1949-02-01} {
+ clock format -659964304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1949 12:34:56 die i mensis ii annoque mcmxlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2432949 02 ii 2 02/01/1949 die i mensis ii annoque mcmxlix 49 xlix 1949}
+test clock-2.580 {conversion of 1949-02-28} {
+ clock format -657631504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1949 12:34:56 die xxviii mensis ii annoque mcmxlix xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2432976 02 ii 2 02/28/1949 die xxviii mensis ii annoque mcmxlix 49 xlix 1949}
+test clock-2.581 {conversion of 1949-03-01} {
+ clock format -657545104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1949 12:34:56 die i mensis iii annoque mcmxlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2432977 03 iii 3 03/01/1949 die i mensis iii annoque mcmxlix 49 xlix 1949}
+test clock-2.582 {conversion of 1949-03-31} {
+ clock format -654953104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1949 12:34:56 die xxxi mensis iii annoque mcmxlix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2433007 03 iii 3 03/31/1949 die xxxi mensis iii annoque mcmxlix 49 xlix 1949}
+test clock-2.583 {conversion of 1949-04-01} {
+ clock format -654866704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1949 12:34:56 die i mensis iv annoque mcmxlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2433008 04 iv 4 04/01/1949 die i mensis iv annoque mcmxlix 49 xlix 1949}
+test clock-2.584 {conversion of 1949-04-30} {
+ clock format -652361104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1949 12:34:56 die xxx mensis iv annoque mcmxlix xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2433037 04 iv 4 04/30/1949 die xxx mensis iv annoque mcmxlix 49 xlix 1949}
+test clock-2.585 {conversion of 1949-05-01} {
+ clock format -652274704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1949 12:34:56 die i mensis v annoque mcmxlix xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2433038 05 v 5 05/01/1949 die i mensis v annoque mcmxlix 49 xlix 1949}
+test clock-2.586 {conversion of 1949-05-31} {
+ clock format -649682704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1949 12:34:56 die xxxi mensis v annoque mcmxlix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2433068 05 v 5 05/31/1949 die xxxi mensis v annoque mcmxlix 49 xlix 1949}
+test clock-2.587 {conversion of 1949-06-01} {
+ clock format -649596304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1949 12:34:56 die i mensis vi annoque mcmxlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2433069 06 vi 6 06/01/1949 die i mensis vi annoque mcmxlix 49 xlix 1949}
+test clock-2.588 {conversion of 1949-06-30} {
+ clock format -647090704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1949 12:34:56 die xxx mensis vi annoque mcmxlix xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2433098 06 vi 6 06/30/1949 die xxx mensis vi annoque mcmxlix 49 xlix 1949}
+test clock-2.589 {conversion of 1949-07-01} {
+ clock format -647004304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1949 12:34:56 die i mensis vii annoque mcmxlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2433099 07 vii 7 07/01/1949 die i mensis vii annoque mcmxlix 49 xlix 1949}
+test clock-2.590 {conversion of 1949-07-31} {
+ clock format -644412304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1949 12:34:56 die xxxi mensis vii annoque mcmxlix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2433129 07 vii 7 07/31/1949 die xxxi mensis vii annoque mcmxlix 49 xlix 1949}
+test clock-2.591 {conversion of 1949-08-01} {
+ clock format -644325904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1949 12:34:56 die i mensis viii annoque mcmxlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2433130 08 viii 8 08/01/1949 die i mensis viii annoque mcmxlix 49 xlix 1949}
+test clock-2.592 {conversion of 1949-08-31} {
+ clock format -641733904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1949 12:34:56 die xxxi mensis viii annoque mcmxlix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2433160 08 viii 8 08/31/1949 die xxxi mensis viii annoque mcmxlix 49 xlix 1949}
+test clock-2.593 {conversion of 1949-09-01} {
+ clock format -641647504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1949 12:34:56 die i mensis ix annoque mcmxlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2433161 09 ix 9 09/01/1949 die i mensis ix annoque mcmxlix 49 xlix 1949}
+test clock-2.594 {conversion of 1949-09-30} {
+ clock format -639141904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1949 12:34:56 die xxx mensis ix annoque mcmxlix xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2433190 09 ix 9 09/30/1949 die xxx mensis ix annoque mcmxlix 49 xlix 1949}
+test clock-2.595 {conversion of 1949-10-01} {
+ clock format -639055504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1949 12:34:56 die i mensis x annoque mcmxlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2433191 10 x 10 10/01/1949 die i mensis x annoque mcmxlix 49 xlix 1949}
+test clock-2.596 {conversion of 1949-10-31} {
+ clock format -636463504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1949 12:34:56 die xxxi mensis x annoque mcmxlix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2433221 10 x 10 10/31/1949 die xxxi mensis x annoque mcmxlix 49 xlix 1949}
+test clock-2.597 {conversion of 1949-11-01} {
+ clock format -636377104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1949 12:34:56 die i mensis xi annoque mcmxlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2433222 11 xi 11 11/01/1949 die i mensis xi annoque mcmxlix 49 xlix 1949}
+test clock-2.598 {conversion of 1949-11-30} {
+ clock format -633871504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1949 12:34:56 die xxx mensis xi annoque mcmxlix xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2433251 11 xi 11 11/30/1949 die xxx mensis xi annoque mcmxlix 49 xlix 1949}
+test clock-2.599 {conversion of 1949-12-01} {
+ clock format -633785104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1949 12:34:56 die i mensis xii annoque mcmxlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2433252 12 xii 12 12/01/1949 die i mensis xii annoque mcmxlix 49 xlix 1949}
+test clock-2.600 {conversion of 1949-12-31} {
+ clock format -631193104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1949 12:34:56 die xxxi mensis xii annoque mcmxlix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2433282 12 xii 12 12/31/1949 die xxxi mensis xii annoque mcmxlix 49 xlix 1949}
+test clock-2.601 {conversion of 1952-01-01} {
+ clock format -568034704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1952 12:34:56 die i mensis i annoque mcmlii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2434013 01 i 1 01/01/1952 die i mensis i annoque mcmlii 52 lii 1952}
+test clock-2.602 {conversion of 1952-01-31} {
+ clock format -565442704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1952 12:34:56 die xxxi mensis i annoque mcmlii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2434043 01 i 1 01/31/1952 die xxxi mensis i annoque mcmlii 52 lii 1952}
+test clock-2.603 {conversion of 1952-02-01} {
+ clock format -565356304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1952 12:34:56 die i mensis ii annoque mcmlii xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2434044 02 ii 2 02/01/1952 die i mensis ii annoque mcmlii 52 lii 1952}
+test clock-2.604 {conversion of 1952-02-29} {
+ clock format -562937104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1952 12:34:56 die xxix mensis ii annoque mcmlii xii h xxxiv m lvi s 19 mcm 29 xxix 29 xxix Feb 060 2434072 02 ii 2 02/29/1952 die xxix mensis ii annoque mcmlii 52 lii 1952}
+test clock-2.605 {conversion of 1952-03-01} {
+ clock format -562850704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1952 12:34:56 die i mensis iii annoque mcmlii xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 061 2434073 03 iii 3 03/01/1952 die i mensis iii annoque mcmlii 52 lii 1952}
+test clock-2.606 {conversion of 1952-03-31} {
+ clock format -560258704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1952 12:34:56 die xxxi mensis iii annoque mcmlii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 091 2434103 03 iii 3 03/31/1952 die xxxi mensis iii annoque mcmlii 52 lii 1952}
+test clock-2.607 {conversion of 1952-04-01} {
+ clock format -560172304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1952 12:34:56 die i mensis iv annoque mcmlii xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 092 2434104 04 iv 4 04/01/1952 die i mensis iv annoque mcmlii 52 lii 1952}
+test clock-2.608 {conversion of 1952-04-30} {
+ clock format -557666704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1952 12:34:56 die xxx mensis iv annoque mcmlii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 121 2434133 04 iv 4 04/30/1952 die xxx mensis iv annoque mcmlii 52 lii 1952}
+test clock-2.609 {conversion of 1952-05-01} {
+ clock format -557580304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1952 12:34:56 die i mensis v annoque mcmlii xii h xxxiv m lvi s 19 mcm 01 i 1 i May 122 2434134 05 v 5 05/01/1952 die i mensis v annoque mcmlii 52 lii 1952}
+test clock-2.610 {conversion of 1952-05-31} {
+ clock format -554988304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1952 12:34:56 die xxxi mensis v annoque mcmlii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 152 2434164 05 v 5 05/31/1952 die xxxi mensis v annoque mcmlii 52 lii 1952}
+test clock-2.611 {conversion of 1952-06-01} {
+ clock format -554901904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1952 12:34:56 die i mensis vi annoque mcmlii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 153 2434165 06 vi 6 06/01/1952 die i mensis vi annoque mcmlii 52 lii 1952}
+test clock-2.612 {conversion of 1952-06-30} {
+ clock format -552396304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1952 12:34:56 die xxx mensis vi annoque mcmlii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 182 2434194 06 vi 6 06/30/1952 die xxx mensis vi annoque mcmlii 52 lii 1952}
+test clock-2.613 {conversion of 1952-07-01} {
+ clock format -552309904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1952 12:34:56 die i mensis vii annoque mcmlii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 183 2434195 07 vii 7 07/01/1952 die i mensis vii annoque mcmlii 52 lii 1952}
+test clock-2.614 {conversion of 1952-07-31} {
+ clock format -549717904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1952 12:34:56 die xxxi mensis vii annoque mcmlii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 213 2434225 07 vii 7 07/31/1952 die xxxi mensis vii annoque mcmlii 52 lii 1952}
+test clock-2.615 {conversion of 1952-08-01} {
+ clock format -549631504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1952 12:34:56 die i mensis viii annoque mcmlii xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 214 2434226 08 viii 8 08/01/1952 die i mensis viii annoque mcmlii 52 lii 1952}
+test clock-2.616 {conversion of 1952-08-31} {
+ clock format -547039504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1952 12:34:56 die xxxi mensis viii annoque mcmlii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 244 2434256 08 viii 8 08/31/1952 die xxxi mensis viii annoque mcmlii 52 lii 1952}
+test clock-2.617 {conversion of 1952-09-01} {
+ clock format -546953104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1952 12:34:56 die i mensis ix annoque mcmlii xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 245 2434257 09 ix 9 09/01/1952 die i mensis ix annoque mcmlii 52 lii 1952}
+test clock-2.618 {conversion of 1952-09-30} {
+ clock format -544447504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1952 12:34:56 die xxx mensis ix annoque mcmlii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 274 2434286 09 ix 9 09/30/1952 die xxx mensis ix annoque mcmlii 52 lii 1952}
+test clock-2.619 {conversion of 1952-10-01} {
+ clock format -544361104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1952 12:34:56 die i mensis x annoque mcmlii xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 275 2434287 10 x 10 10/01/1952 die i mensis x annoque mcmlii 52 lii 1952}
+test clock-2.620 {conversion of 1952-10-31} {
+ clock format -541769104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1952 12:34:56 die xxxi mensis x annoque mcmlii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 305 2434317 10 x 10 10/31/1952 die xxxi mensis x annoque mcmlii 52 lii 1952}
+test clock-2.621 {conversion of 1952-11-01} {
+ clock format -541682704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1952 12:34:56 die i mensis xi annoque mcmlii xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 306 2434318 11 xi 11 11/01/1952 die i mensis xi annoque mcmlii 52 lii 1952}
+test clock-2.622 {conversion of 1952-11-30} {
+ clock format -539177104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1952 12:34:56 die xxx mensis xi annoque mcmlii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 335 2434347 11 xi 11 11/30/1952 die xxx mensis xi annoque mcmlii 52 lii 1952}
+test clock-2.623 {conversion of 1952-12-01} {
+ clock format -539090704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1952 12:34:56 die i mensis xii annoque mcmlii xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 336 2434348 12 xii 12 12/01/1952 die i mensis xii annoque mcmlii 52 lii 1952}
+test clock-2.624 {conversion of 1952-12-31} {
+ clock format -536498704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1952 12:34:56 die xxxi mensis xii annoque mcmlii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 366 2434378 12 xii 12 12/31/1952 die xxxi mensis xii annoque mcmlii 52 lii 1952}
+test clock-2.625 {conversion of 1953-01-01} {
+ clock format -536412304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1953 12:34:56 die i mensis i annoque mcmliii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2434379 01 i 1 01/01/1953 die i mensis i annoque mcmliii 53 liii 1953}
+test clock-2.626 {conversion of 1953-01-31} {
+ clock format -533820304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1953 12:34:56 die xxxi mensis i annoque mcmliii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2434409 01 i 1 01/31/1953 die xxxi mensis i annoque mcmliii 53 liii 1953}
+test clock-2.627 {conversion of 1953-02-01} {
+ clock format -533733904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1953 12:34:56 die i mensis ii annoque mcmliii xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2434410 02 ii 2 02/01/1953 die i mensis ii annoque mcmliii 53 liii 1953}
+test clock-2.628 {conversion of 1953-02-28} {
+ clock format -531401104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1953 12:34:56 die xxviii mensis ii annoque mcmliii xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2434437 02 ii 2 02/28/1953 die xxviii mensis ii annoque mcmliii 53 liii 1953}
+test clock-2.629 {conversion of 1953-03-01} {
+ clock format -531314704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1953 12:34:56 die i mensis iii annoque mcmliii xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2434438 03 iii 3 03/01/1953 die i mensis iii annoque mcmliii 53 liii 1953}
+test clock-2.630 {conversion of 1953-03-31} {
+ clock format -528722704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1953 12:34:56 die xxxi mensis iii annoque mcmliii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2434468 03 iii 3 03/31/1953 die xxxi mensis iii annoque mcmliii 53 liii 1953}
+test clock-2.631 {conversion of 1953-04-01} {
+ clock format -528636304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1953 12:34:56 die i mensis iv annoque mcmliii xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2434469 04 iv 4 04/01/1953 die i mensis iv annoque mcmliii 53 liii 1953}
+test clock-2.632 {conversion of 1953-04-30} {
+ clock format -526130704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1953 12:34:56 die xxx mensis iv annoque mcmliii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2434498 04 iv 4 04/30/1953 die xxx mensis iv annoque mcmliii 53 liii 1953}
+test clock-2.633 {conversion of 1953-05-01} {
+ clock format -526044304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1953 12:34:56 die i mensis v annoque mcmliii xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2434499 05 v 5 05/01/1953 die i mensis v annoque mcmliii 53 liii 1953}
+test clock-2.634 {conversion of 1953-05-31} {
+ clock format -523452304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1953 12:34:56 die xxxi mensis v annoque mcmliii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2434529 05 v 5 05/31/1953 die xxxi mensis v annoque mcmliii 53 liii 1953}
+test clock-2.635 {conversion of 1953-06-01} {
+ clock format -523365904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1953 12:34:56 die i mensis vi annoque mcmliii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2434530 06 vi 6 06/01/1953 die i mensis vi annoque mcmliii 53 liii 1953}
+test clock-2.636 {conversion of 1953-06-30} {
+ clock format -520860304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1953 12:34:56 die xxx mensis vi annoque mcmliii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2434559 06 vi 6 06/30/1953 die xxx mensis vi annoque mcmliii 53 liii 1953}
+test clock-2.637 {conversion of 1953-07-01} {
+ clock format -520773904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1953 12:34:56 die i mensis vii annoque mcmliii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2434560 07 vii 7 07/01/1953 die i mensis vii annoque mcmliii 53 liii 1953}
+test clock-2.638 {conversion of 1953-07-31} {
+ clock format -518181904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1953 12:34:56 die xxxi mensis vii annoque mcmliii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2434590 07 vii 7 07/31/1953 die xxxi mensis vii annoque mcmliii 53 liii 1953}
+test clock-2.639 {conversion of 1953-08-01} {
+ clock format -518095504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1953 12:34:56 die i mensis viii annoque mcmliii xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2434591 08 viii 8 08/01/1953 die i mensis viii annoque mcmliii 53 liii 1953}
+test clock-2.640 {conversion of 1953-08-31} {
+ clock format -515503504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1953 12:34:56 die xxxi mensis viii annoque mcmliii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2434621 08 viii 8 08/31/1953 die xxxi mensis viii annoque mcmliii 53 liii 1953}
+test clock-2.641 {conversion of 1953-09-01} {
+ clock format -515417104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1953 12:34:56 die i mensis ix annoque mcmliii xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2434622 09 ix 9 09/01/1953 die i mensis ix annoque mcmliii 53 liii 1953}
+test clock-2.642 {conversion of 1953-09-30} {
+ clock format -512911504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1953 12:34:56 die xxx mensis ix annoque mcmliii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2434651 09 ix 9 09/30/1953 die xxx mensis ix annoque mcmliii 53 liii 1953}
+test clock-2.643 {conversion of 1953-10-01} {
+ clock format -512825104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1953 12:34:56 die i mensis x annoque mcmliii xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2434652 10 x 10 10/01/1953 die i mensis x annoque mcmliii 53 liii 1953}
+test clock-2.644 {conversion of 1953-10-31} {
+ clock format -510233104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1953 12:34:56 die xxxi mensis x annoque mcmliii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2434682 10 x 10 10/31/1953 die xxxi mensis x annoque mcmliii 53 liii 1953}
+test clock-2.645 {conversion of 1953-11-01} {
+ clock format -510146704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1953 12:34:56 die i mensis xi annoque mcmliii xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2434683 11 xi 11 11/01/1953 die i mensis xi annoque mcmliii 53 liii 1953}
+test clock-2.646 {conversion of 1953-11-30} {
+ clock format -507641104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1953 12:34:56 die xxx mensis xi annoque mcmliii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2434712 11 xi 11 11/30/1953 die xxx mensis xi annoque mcmliii 53 liii 1953}
+test clock-2.647 {conversion of 1953-12-01} {
+ clock format -507554704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1953 12:34:56 die i mensis xii annoque mcmliii xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2434713 12 xii 12 12/01/1953 die i mensis xii annoque mcmliii 53 liii 1953}
+test clock-2.648 {conversion of 1953-12-31} {
+ clock format -504962704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1953 12:34:56 die xxxi mensis xii annoque mcmliii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2434743 12 xii 12 12/31/1953 die xxxi mensis xii annoque mcmliii 53 liii 1953}
+test clock-2.649 {conversion of 1956-01-01} {
+ clock format -441804304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1956 12:34:56 die i mensis i annoque mcmlvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2435474 01 i 1 01/01/1956 die i mensis i annoque mcmlvi 56 lvi 1956}
+test clock-2.650 {conversion of 1956-01-31} {
+ clock format -439212304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1956 12:34:56 die xxxi mensis i annoque mcmlvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2435504 01 i 1 01/31/1956 die xxxi mensis i annoque mcmlvi 56 lvi 1956}
+test clock-2.651 {conversion of 1956-02-01} {
+ clock format -439125904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1956 12:34:56 die i mensis ii annoque mcmlvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2435505 02 ii 2 02/01/1956 die i mensis ii annoque mcmlvi 56 lvi 1956}
+test clock-2.652 {conversion of 1956-02-29} {
+ clock format -436706704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1956 12:34:56 die xxix mensis ii annoque mcmlvi xii h xxxiv m lvi s 19 mcm 29 xxix 29 xxix Feb 060 2435533 02 ii 2 02/29/1956 die xxix mensis ii annoque mcmlvi 56 lvi 1956}
+test clock-2.653 {conversion of 1956-03-01} {
+ clock format -436620304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1956 12:34:56 die i mensis iii annoque mcmlvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 061 2435534 03 iii 3 03/01/1956 die i mensis iii annoque mcmlvi 56 lvi 1956}
+test clock-2.654 {conversion of 1956-03-31} {
+ clock format -434028304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1956 12:34:56 die xxxi mensis iii annoque mcmlvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 091 2435564 03 iii 3 03/31/1956 die xxxi mensis iii annoque mcmlvi 56 lvi 1956}
+test clock-2.655 {conversion of 1956-04-01} {
+ clock format -433941904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1956 12:34:56 die i mensis iv annoque mcmlvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 092 2435565 04 iv 4 04/01/1956 die i mensis iv annoque mcmlvi 56 lvi 1956}
+test clock-2.656 {conversion of 1956-04-30} {
+ clock format -431436304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1956 12:34:56 die xxx mensis iv annoque mcmlvi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 121 2435594 04 iv 4 04/30/1956 die xxx mensis iv annoque mcmlvi 56 lvi 1956}
+test clock-2.657 {conversion of 1956-05-01} {
+ clock format -431349904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1956 12:34:56 die i mensis v annoque mcmlvi xii h xxxiv m lvi s 19 mcm 01 i 1 i May 122 2435595 05 v 5 05/01/1956 die i mensis v annoque mcmlvi 56 lvi 1956}
+test clock-2.658 {conversion of 1956-05-31} {
+ clock format -428757904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1956 12:34:56 die xxxi mensis v annoque mcmlvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 152 2435625 05 v 5 05/31/1956 die xxxi mensis v annoque mcmlvi 56 lvi 1956}
+test clock-2.659 {conversion of 1956-06-01} {
+ clock format -428671504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1956 12:34:56 die i mensis vi annoque mcmlvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 153 2435626 06 vi 6 06/01/1956 die i mensis vi annoque mcmlvi 56 lvi 1956}
+test clock-2.660 {conversion of 1956-06-30} {
+ clock format -426165904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1956 12:34:56 die xxx mensis vi annoque mcmlvi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 182 2435655 06 vi 6 06/30/1956 die xxx mensis vi annoque mcmlvi 56 lvi 1956}
+test clock-2.661 {conversion of 1956-07-01} {
+ clock format -426079504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1956 12:34:56 die i mensis vii annoque mcmlvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 183 2435656 07 vii 7 07/01/1956 die i mensis vii annoque mcmlvi 56 lvi 1956}
+test clock-2.662 {conversion of 1956-07-31} {
+ clock format -423487504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1956 12:34:56 die xxxi mensis vii annoque mcmlvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 213 2435686 07 vii 7 07/31/1956 die xxxi mensis vii annoque mcmlvi 56 lvi 1956}
+test clock-2.663 {conversion of 1956-08-01} {
+ clock format -423401104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1956 12:34:56 die i mensis viii annoque mcmlvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 214 2435687 08 viii 8 08/01/1956 die i mensis viii annoque mcmlvi 56 lvi 1956}
+test clock-2.664 {conversion of 1956-08-31} {
+ clock format -420809104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1956 12:34:56 die xxxi mensis viii annoque mcmlvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 244 2435717 08 viii 8 08/31/1956 die xxxi mensis viii annoque mcmlvi 56 lvi 1956}
+test clock-2.665 {conversion of 1956-09-01} {
+ clock format -420722704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1956 12:34:56 die i mensis ix annoque mcmlvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 245 2435718 09 ix 9 09/01/1956 die i mensis ix annoque mcmlvi 56 lvi 1956}
+test clock-2.666 {conversion of 1956-09-30} {
+ clock format -418217104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1956 12:34:56 die xxx mensis ix annoque mcmlvi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 274 2435747 09 ix 9 09/30/1956 die xxx mensis ix annoque mcmlvi 56 lvi 1956}
+test clock-2.667 {conversion of 1956-10-01} {
+ clock format -418130704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1956 12:34:56 die i mensis x annoque mcmlvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 275 2435748 10 x 10 10/01/1956 die i mensis x annoque mcmlvi 56 lvi 1956}
+test clock-2.668 {conversion of 1956-10-31} {
+ clock format -415538704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1956 12:34:56 die xxxi mensis x annoque mcmlvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 305 2435778 10 x 10 10/31/1956 die xxxi mensis x annoque mcmlvi 56 lvi 1956}
+test clock-2.669 {conversion of 1956-11-01} {
+ clock format -415452304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1956 12:34:56 die i mensis xi annoque mcmlvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 306 2435779 11 xi 11 11/01/1956 die i mensis xi annoque mcmlvi 56 lvi 1956}
+test clock-2.670 {conversion of 1956-11-30} {
+ clock format -412946704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1956 12:34:56 die xxx mensis xi annoque mcmlvi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 335 2435808 11 xi 11 11/30/1956 die xxx mensis xi annoque mcmlvi 56 lvi 1956}
+test clock-2.671 {conversion of 1956-12-01} {
+ clock format -412860304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1956 12:34:56 die i mensis xii annoque mcmlvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 336 2435809 12 xii 12 12/01/1956 die i mensis xii annoque mcmlvi 56 lvi 1956}
+test clock-2.672 {conversion of 1956-12-31} {
+ clock format -410268304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1956 12:34:56 die xxxi mensis xii annoque mcmlvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 366 2435839 12 xii 12 12/31/1956 die xxxi mensis xii annoque mcmlvi 56 lvi 1956}
+test clock-2.673 {conversion of 1957-01-01} {
+ clock format -410181904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1957 12:34:56 die i mensis i annoque mcmlvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2435840 01 i 1 01/01/1957 die i mensis i annoque mcmlvii 57 lvii 1957}
+test clock-2.674 {conversion of 1957-01-31} {
+ clock format -407589904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1957 12:34:56 die xxxi mensis i annoque mcmlvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2435870 01 i 1 01/31/1957 die xxxi mensis i annoque mcmlvii 57 lvii 1957}
+test clock-2.675 {conversion of 1957-02-01} {
+ clock format -407503504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1957 12:34:56 die i mensis ii annoque mcmlvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2435871 02 ii 2 02/01/1957 die i mensis ii annoque mcmlvii 57 lvii 1957}
+test clock-2.676 {conversion of 1957-02-28} {
+ clock format -405170704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1957 12:34:56 die xxviii mensis ii annoque mcmlvii xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2435898 02 ii 2 02/28/1957 die xxviii mensis ii annoque mcmlvii 57 lvii 1957}
+test clock-2.677 {conversion of 1957-03-01} {
+ clock format -405084304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1957 12:34:56 die i mensis iii annoque mcmlvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2435899 03 iii 3 03/01/1957 die i mensis iii annoque mcmlvii 57 lvii 1957}
+test clock-2.678 {conversion of 1957-03-31} {
+ clock format -402492304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1957 12:34:56 die xxxi mensis iii annoque mcmlvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2435929 03 iii 3 03/31/1957 die xxxi mensis iii annoque mcmlvii 57 lvii 1957}
+test clock-2.679 {conversion of 1957-04-01} {
+ clock format -402405904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1957 12:34:56 die i mensis iv annoque mcmlvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2435930 04 iv 4 04/01/1957 die i mensis iv annoque mcmlvii 57 lvii 1957}
+test clock-2.680 {conversion of 1957-04-30} {
+ clock format -399900304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1957 12:34:56 die xxx mensis iv annoque mcmlvii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2435959 04 iv 4 04/30/1957 die xxx mensis iv annoque mcmlvii 57 lvii 1957}
+test clock-2.681 {conversion of 1957-05-01} {
+ clock format -399813904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1957 12:34:56 die i mensis v annoque mcmlvii xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2435960 05 v 5 05/01/1957 die i mensis v annoque mcmlvii 57 lvii 1957}
+test clock-2.682 {conversion of 1957-05-31} {
+ clock format -397221904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1957 12:34:56 die xxxi mensis v annoque mcmlvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2435990 05 v 5 05/31/1957 die xxxi mensis v annoque mcmlvii 57 lvii 1957}
+test clock-2.683 {conversion of 1957-06-01} {
+ clock format -397135504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1957 12:34:56 die i mensis vi annoque mcmlvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2435991 06 vi 6 06/01/1957 die i mensis vi annoque mcmlvii 57 lvii 1957}
+test clock-2.684 {conversion of 1957-06-30} {
+ clock format -394629904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1957 12:34:56 die xxx mensis vi annoque mcmlvii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2436020 06 vi 6 06/30/1957 die xxx mensis vi annoque mcmlvii 57 lvii 1957}
+test clock-2.685 {conversion of 1957-07-01} {
+ clock format -394543504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1957 12:34:56 die i mensis vii annoque mcmlvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2436021 07 vii 7 07/01/1957 die i mensis vii annoque mcmlvii 57 lvii 1957}
+test clock-2.686 {conversion of 1957-07-31} {
+ clock format -391951504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1957 12:34:56 die xxxi mensis vii annoque mcmlvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2436051 07 vii 7 07/31/1957 die xxxi mensis vii annoque mcmlvii 57 lvii 1957}
+test clock-2.687 {conversion of 1957-08-01} {
+ clock format -391865104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1957 12:34:56 die i mensis viii annoque mcmlvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2436052 08 viii 8 08/01/1957 die i mensis viii annoque mcmlvii 57 lvii 1957}
+test clock-2.688 {conversion of 1957-08-31} {
+ clock format -389273104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1957 12:34:56 die xxxi mensis viii annoque mcmlvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2436082 08 viii 8 08/31/1957 die xxxi mensis viii annoque mcmlvii 57 lvii 1957}
+test clock-2.689 {conversion of 1957-09-01} {
+ clock format -389186704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1957 12:34:56 die i mensis ix annoque mcmlvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2436083 09 ix 9 09/01/1957 die i mensis ix annoque mcmlvii 57 lvii 1957}
+test clock-2.690 {conversion of 1957-09-30} {
+ clock format -386681104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1957 12:34:56 die xxx mensis ix annoque mcmlvii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2436112 09 ix 9 09/30/1957 die xxx mensis ix annoque mcmlvii 57 lvii 1957}
+test clock-2.691 {conversion of 1957-10-01} {
+ clock format -386594704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1957 12:34:56 die i mensis x annoque mcmlvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2436113 10 x 10 10/01/1957 die i mensis x annoque mcmlvii 57 lvii 1957}
+test clock-2.692 {conversion of 1957-10-31} {
+ clock format -384002704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1957 12:34:56 die xxxi mensis x annoque mcmlvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2436143 10 x 10 10/31/1957 die xxxi mensis x annoque mcmlvii 57 lvii 1957}
+test clock-2.693 {conversion of 1957-11-01} {
+ clock format -383916304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1957 12:34:56 die i mensis xi annoque mcmlvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2436144 11 xi 11 11/01/1957 die i mensis xi annoque mcmlvii 57 lvii 1957}
+test clock-2.694 {conversion of 1957-11-30} {
+ clock format -381410704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1957 12:34:56 die xxx mensis xi annoque mcmlvii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2436173 11 xi 11 11/30/1957 die xxx mensis xi annoque mcmlvii 57 lvii 1957}
+test clock-2.695 {conversion of 1957-12-01} {
+ clock format -381324304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1957 12:34:56 die i mensis xii annoque mcmlvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2436174 12 xii 12 12/01/1957 die i mensis xii annoque mcmlvii 57 lvii 1957}
+test clock-2.696 {conversion of 1957-12-31} {
+ clock format -378732304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1957 12:34:56 die xxxi mensis xii annoque mcmlvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2436204 12 xii 12 12/31/1957 die xxxi mensis xii annoque mcmlvii 57 lvii 1957}
+test clock-2.697 {conversion of 1959-01-01} {
+ clock format -347109904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1959 12:34:56 die i mensis i annoque mcmlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2436570 01 i 1 01/01/1959 die i mensis i annoque mcmlix 59 lix 1959}
+test clock-2.698 {conversion of 1959-01-31} {
+ clock format -344517904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1959 12:34:56 die xxxi mensis i annoque mcmlix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2436600 01 i 1 01/31/1959 die xxxi mensis i annoque mcmlix 59 lix 1959}
+test clock-2.699 {conversion of 1959-02-01} {
+ clock format -344431504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1959 12:34:56 die i mensis ii annoque mcmlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2436601 02 ii 2 02/01/1959 die i mensis ii annoque mcmlix 59 lix 1959}
+test clock-2.700 {conversion of 1959-02-28} {
+ clock format -342098704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1959 12:34:56 die xxviii mensis ii annoque mcmlix xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2436628 02 ii 2 02/28/1959 die xxviii mensis ii annoque mcmlix 59 lix 1959}
+test clock-2.701 {conversion of 1959-03-01} {
+ clock format -342012304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1959 12:34:56 die i mensis iii annoque mcmlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2436629 03 iii 3 03/01/1959 die i mensis iii annoque mcmlix 59 lix 1959}
+test clock-2.702 {conversion of 1959-03-31} {
+ clock format -339420304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1959 12:34:56 die xxxi mensis iii annoque mcmlix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2436659 03 iii 3 03/31/1959 die xxxi mensis iii annoque mcmlix 59 lix 1959}
+test clock-2.703 {conversion of 1959-04-01} {
+ clock format -339333904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1959 12:34:56 die i mensis iv annoque mcmlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2436660 04 iv 4 04/01/1959 die i mensis iv annoque mcmlix 59 lix 1959}
+test clock-2.704 {conversion of 1959-04-30} {
+ clock format -336828304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1959 12:34:56 die xxx mensis iv annoque mcmlix xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2436689 04 iv 4 04/30/1959 die xxx mensis iv annoque mcmlix 59 lix 1959}
+test clock-2.705 {conversion of 1959-05-01} {
+ clock format -336741904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1959 12:34:56 die i mensis v annoque mcmlix xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2436690 05 v 5 05/01/1959 die i mensis v annoque mcmlix 59 lix 1959}
+test clock-2.706 {conversion of 1959-05-31} {
+ clock format -334149904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1959 12:34:56 die xxxi mensis v annoque mcmlix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2436720 05 v 5 05/31/1959 die xxxi mensis v annoque mcmlix 59 lix 1959}
+test clock-2.707 {conversion of 1959-06-01} {
+ clock format -334063504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1959 12:34:56 die i mensis vi annoque mcmlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2436721 06 vi 6 06/01/1959 die i mensis vi annoque mcmlix 59 lix 1959}
+test clock-2.708 {conversion of 1959-06-30} {
+ clock format -331557904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1959 12:34:56 die xxx mensis vi annoque mcmlix xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2436750 06 vi 6 06/30/1959 die xxx mensis vi annoque mcmlix 59 lix 1959}
+test clock-2.709 {conversion of 1959-07-01} {
+ clock format -331471504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1959 12:34:56 die i mensis vii annoque mcmlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2436751 07 vii 7 07/01/1959 die i mensis vii annoque mcmlix 59 lix 1959}
+test clock-2.710 {conversion of 1959-07-31} {
+ clock format -328879504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1959 12:34:56 die xxxi mensis vii annoque mcmlix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2436781 07 vii 7 07/31/1959 die xxxi mensis vii annoque mcmlix 59 lix 1959}
+test clock-2.711 {conversion of 1959-08-01} {
+ clock format -328793104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1959 12:34:56 die i mensis viii annoque mcmlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2436782 08 viii 8 08/01/1959 die i mensis viii annoque mcmlix 59 lix 1959}
+test clock-2.712 {conversion of 1959-08-31} {
+ clock format -326201104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1959 12:34:56 die xxxi mensis viii annoque mcmlix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2436812 08 viii 8 08/31/1959 die xxxi mensis viii annoque mcmlix 59 lix 1959}
+test clock-2.713 {conversion of 1959-09-01} {
+ clock format -326114704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1959 12:34:56 die i mensis ix annoque mcmlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2436813 09 ix 9 09/01/1959 die i mensis ix annoque mcmlix 59 lix 1959}
+test clock-2.714 {conversion of 1959-09-30} {
+ clock format -323609104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1959 12:34:56 die xxx mensis ix annoque mcmlix xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2436842 09 ix 9 09/30/1959 die xxx mensis ix annoque mcmlix 59 lix 1959}
+test clock-2.715 {conversion of 1959-10-01} {
+ clock format -323522704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1959 12:34:56 die i mensis x annoque mcmlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2436843 10 x 10 10/01/1959 die i mensis x annoque mcmlix 59 lix 1959}
+test clock-2.716 {conversion of 1959-10-31} {
+ clock format -320930704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1959 12:34:56 die xxxi mensis x annoque mcmlix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2436873 10 x 10 10/31/1959 die xxxi mensis x annoque mcmlix 59 lix 1959}
+test clock-2.717 {conversion of 1959-11-01} {
+ clock format -320844304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1959 12:34:56 die i mensis xi annoque mcmlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2436874 11 xi 11 11/01/1959 die i mensis xi annoque mcmlix 59 lix 1959}
+test clock-2.718 {conversion of 1959-11-30} {
+ clock format -318338704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1959 12:34:56 die xxx mensis xi annoque mcmlix xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2436903 11 xi 11 11/30/1959 die xxx mensis xi annoque mcmlix 59 lix 1959}
+test clock-2.719 {conversion of 1959-12-01} {
+ clock format -318252304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1959 12:34:56 die i mensis xii annoque mcmlix xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2436904 12 xii 12 12/01/1959 die i mensis xii annoque mcmlix 59 lix 1959}
+test clock-2.720 {conversion of 1959-12-31} {
+ clock format -315660304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1959 12:34:56 die xxxi mensis xii annoque mcmlix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2436934 12 xii 12 12/31/1959 die xxxi mensis xii annoque mcmlix 59 lix 1959}
+test clock-2.721 {conversion of 1960-01-01} {
+ clock format -315573904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1960 12:34:56 die i mensis i annoque mcmlx xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2436935 01 i 1 01/01/1960 die i mensis i annoque mcmlx 60 lx 1960}
+test clock-2.722 {conversion of 1960-01-31} {
+ clock format -312981904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1960 12:34:56 die xxxi mensis i annoque mcmlx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2436965 01 i 1 01/31/1960 die xxxi mensis i annoque mcmlx 60 lx 1960}
+test clock-2.723 {conversion of 1960-02-01} {
+ clock format -312895504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1960 12:34:56 die i mensis ii annoque mcmlx xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2436966 02 ii 2 02/01/1960 die i mensis ii annoque mcmlx 60 lx 1960}
+test clock-2.724 {conversion of 1960-02-29} {
+ clock format -310476304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1960 12:34:56 die xxix mensis ii annoque mcmlx xii h xxxiv m lvi s 19 mcm 29 xxix 29 xxix Feb 060 2436994 02 ii 2 02/29/1960 die xxix mensis ii annoque mcmlx 60 lx 1960}
+test clock-2.725 {conversion of 1960-03-01} {
+ clock format -310389904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1960 12:34:56 die i mensis iii annoque mcmlx xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 061 2436995 03 iii 3 03/01/1960 die i mensis iii annoque mcmlx 60 lx 1960}
+test clock-2.726 {conversion of 1960-03-31} {
+ clock format -307797904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1960 12:34:56 die xxxi mensis iii annoque mcmlx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 091 2437025 03 iii 3 03/31/1960 die xxxi mensis iii annoque mcmlx 60 lx 1960}
+test clock-2.727 {conversion of 1960-04-01} {
+ clock format -307711504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1960 12:34:56 die i mensis iv annoque mcmlx xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 092 2437026 04 iv 4 04/01/1960 die i mensis iv annoque mcmlx 60 lx 1960}
+test clock-2.728 {conversion of 1960-04-30} {
+ clock format -305205904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1960 12:34:56 die xxx mensis iv annoque mcmlx xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 121 2437055 04 iv 4 04/30/1960 die xxx mensis iv annoque mcmlx 60 lx 1960}
+test clock-2.729 {conversion of 1960-05-01} {
+ clock format -305119504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1960 12:34:56 die i mensis v annoque mcmlx xii h xxxiv m lvi s 19 mcm 01 i 1 i May 122 2437056 05 v 5 05/01/1960 die i mensis v annoque mcmlx 60 lx 1960}
+test clock-2.730 {conversion of 1960-05-31} {
+ clock format -302527504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1960 12:34:56 die xxxi mensis v annoque mcmlx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 152 2437086 05 v 5 05/31/1960 die xxxi mensis v annoque mcmlx 60 lx 1960}
+test clock-2.731 {conversion of 1960-06-01} {
+ clock format -302441104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1960 12:34:56 die i mensis vi annoque mcmlx xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 153 2437087 06 vi 6 06/01/1960 die i mensis vi annoque mcmlx 60 lx 1960}
+test clock-2.732 {conversion of 1960-06-30} {
+ clock format -299935504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1960 12:34:56 die xxx mensis vi annoque mcmlx xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 182 2437116 06 vi 6 06/30/1960 die xxx mensis vi annoque mcmlx 60 lx 1960}
+test clock-2.733 {conversion of 1960-07-01} {
+ clock format -299849104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1960 12:34:56 die i mensis vii annoque mcmlx xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 183 2437117 07 vii 7 07/01/1960 die i mensis vii annoque mcmlx 60 lx 1960}
+test clock-2.734 {conversion of 1960-07-31} {
+ clock format -297257104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1960 12:34:56 die xxxi mensis vii annoque mcmlx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 213 2437147 07 vii 7 07/31/1960 die xxxi mensis vii annoque mcmlx 60 lx 1960}
+test clock-2.735 {conversion of 1960-08-01} {
+ clock format -297170704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1960 12:34:56 die i mensis viii annoque mcmlx xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 214 2437148 08 viii 8 08/01/1960 die i mensis viii annoque mcmlx 60 lx 1960}
+test clock-2.736 {conversion of 1960-08-31} {
+ clock format -294578704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1960 12:34:56 die xxxi mensis viii annoque mcmlx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 244 2437178 08 viii 8 08/31/1960 die xxxi mensis viii annoque mcmlx 60 lx 1960}
+test clock-2.737 {conversion of 1960-09-01} {
+ clock format -294492304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1960 12:34:56 die i mensis ix annoque mcmlx xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 245 2437179 09 ix 9 09/01/1960 die i mensis ix annoque mcmlx 60 lx 1960}
+test clock-2.738 {conversion of 1960-09-30} {
+ clock format -291986704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1960 12:34:56 die xxx mensis ix annoque mcmlx xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 274 2437208 09 ix 9 09/30/1960 die xxx mensis ix annoque mcmlx 60 lx 1960}
+test clock-2.739 {conversion of 1960-10-01} {
+ clock format -291900304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1960 12:34:56 die i mensis x annoque mcmlx xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 275 2437209 10 x 10 10/01/1960 die i mensis x annoque mcmlx 60 lx 1960}
+test clock-2.740 {conversion of 1960-10-31} {
+ clock format -289308304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1960 12:34:56 die xxxi mensis x annoque mcmlx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 305 2437239 10 x 10 10/31/1960 die xxxi mensis x annoque mcmlx 60 lx 1960}
+test clock-2.741 {conversion of 1960-11-01} {
+ clock format -289221904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1960 12:34:56 die i mensis xi annoque mcmlx xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 306 2437240 11 xi 11 11/01/1960 die i mensis xi annoque mcmlx 60 lx 1960}
+test clock-2.742 {conversion of 1960-11-30} {
+ clock format -286716304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1960 12:34:56 die xxx mensis xi annoque mcmlx xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 335 2437269 11 xi 11 11/30/1960 die xxx mensis xi annoque mcmlx 60 lx 1960}
+test clock-2.743 {conversion of 1960-12-01} {
+ clock format -286629904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1960 12:34:56 die i mensis xii annoque mcmlx xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 336 2437270 12 xii 12 12/01/1960 die i mensis xii annoque mcmlx 60 lx 1960}
+test clock-2.744 {conversion of 1960-12-31} {
+ clock format -284037904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1960 12:34:56 die xxxi mensis xii annoque mcmlx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 366 2437300 12 xii 12 12/31/1960 die xxxi mensis xii annoque mcmlx 60 lx 1960}
+test clock-2.745 {conversion of 1961-01-01} {
+ clock format -283951504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1961 12:34:56 die i mensis i annoque mcmlxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2437301 01 i 1 01/01/1961 die i mensis i annoque mcmlxi 61 lxi 1961}
+test clock-2.746 {conversion of 1961-01-31} {
+ clock format -281359504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1961 12:34:56 die xxxi mensis i annoque mcmlxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2437331 01 i 1 01/31/1961 die xxxi mensis i annoque mcmlxi 61 lxi 1961}
+test clock-2.747 {conversion of 1961-02-01} {
+ clock format -281273104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1961 12:34:56 die i mensis ii annoque mcmlxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2437332 02 ii 2 02/01/1961 die i mensis ii annoque mcmlxi 61 lxi 1961}
+test clock-2.748 {conversion of 1961-02-28} {
+ clock format -278940304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1961 12:34:56 die xxviii mensis ii annoque mcmlxi xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2437359 02 ii 2 02/28/1961 die xxviii mensis ii annoque mcmlxi 61 lxi 1961}
+test clock-2.749 {conversion of 1961-03-01} {
+ clock format -278853904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1961 12:34:56 die i mensis iii annoque mcmlxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2437360 03 iii 3 03/01/1961 die i mensis iii annoque mcmlxi 61 lxi 1961}
+test clock-2.750 {conversion of 1961-03-31} {
+ clock format -276261904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1961 12:34:56 die xxxi mensis iii annoque mcmlxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2437390 03 iii 3 03/31/1961 die xxxi mensis iii annoque mcmlxi 61 lxi 1961}
+test clock-2.751 {conversion of 1961-04-01} {
+ clock format -276175504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1961 12:34:56 die i mensis iv annoque mcmlxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2437391 04 iv 4 04/01/1961 die i mensis iv annoque mcmlxi 61 lxi 1961}
+test clock-2.752 {conversion of 1961-04-30} {
+ clock format -273669904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1961 12:34:56 die xxx mensis iv annoque mcmlxi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2437420 04 iv 4 04/30/1961 die xxx mensis iv annoque mcmlxi 61 lxi 1961}
+test clock-2.753 {conversion of 1961-05-01} {
+ clock format -273583504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1961 12:34:56 die i mensis v annoque mcmlxi xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2437421 05 v 5 05/01/1961 die i mensis v annoque mcmlxi 61 lxi 1961}
+test clock-2.754 {conversion of 1961-05-31} {
+ clock format -270991504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1961 12:34:56 die xxxi mensis v annoque mcmlxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2437451 05 v 5 05/31/1961 die xxxi mensis v annoque mcmlxi 61 lxi 1961}
+test clock-2.755 {conversion of 1961-06-01} {
+ clock format -270905104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1961 12:34:56 die i mensis vi annoque mcmlxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2437452 06 vi 6 06/01/1961 die i mensis vi annoque mcmlxi 61 lxi 1961}
+test clock-2.756 {conversion of 1961-06-30} {
+ clock format -268399504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1961 12:34:56 die xxx mensis vi annoque mcmlxi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2437481 06 vi 6 06/30/1961 die xxx mensis vi annoque mcmlxi 61 lxi 1961}
+test clock-2.757 {conversion of 1961-07-01} {
+ clock format -268313104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1961 12:34:56 die i mensis vii annoque mcmlxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2437482 07 vii 7 07/01/1961 die i mensis vii annoque mcmlxi 61 lxi 1961}
+test clock-2.758 {conversion of 1961-07-31} {
+ clock format -265721104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1961 12:34:56 die xxxi mensis vii annoque mcmlxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2437512 07 vii 7 07/31/1961 die xxxi mensis vii annoque mcmlxi 61 lxi 1961}
+test clock-2.759 {conversion of 1961-08-01} {
+ clock format -265634704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1961 12:34:56 die i mensis viii annoque mcmlxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2437513 08 viii 8 08/01/1961 die i mensis viii annoque mcmlxi 61 lxi 1961}
+test clock-2.760 {conversion of 1961-08-31} {
+ clock format -263042704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1961 12:34:56 die xxxi mensis viii annoque mcmlxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2437543 08 viii 8 08/31/1961 die xxxi mensis viii annoque mcmlxi 61 lxi 1961}
+test clock-2.761 {conversion of 1961-09-01} {
+ clock format -262956304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1961 12:34:56 die i mensis ix annoque mcmlxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2437544 09 ix 9 09/01/1961 die i mensis ix annoque mcmlxi 61 lxi 1961}
+test clock-2.762 {conversion of 1961-09-30} {
+ clock format -260450704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1961 12:34:56 die xxx mensis ix annoque mcmlxi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2437573 09 ix 9 09/30/1961 die xxx mensis ix annoque mcmlxi 61 lxi 1961}
+test clock-2.763 {conversion of 1961-10-01} {
+ clock format -260364304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1961 12:34:56 die i mensis x annoque mcmlxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2437574 10 x 10 10/01/1961 die i mensis x annoque mcmlxi 61 lxi 1961}
+test clock-2.764 {conversion of 1961-10-31} {
+ clock format -257772304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1961 12:34:56 die xxxi mensis x annoque mcmlxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2437604 10 x 10 10/31/1961 die xxxi mensis x annoque mcmlxi 61 lxi 1961}
+test clock-2.765 {conversion of 1961-11-01} {
+ clock format -257685904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1961 12:34:56 die i mensis xi annoque mcmlxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2437605 11 xi 11 11/01/1961 die i mensis xi annoque mcmlxi 61 lxi 1961}
+test clock-2.766 {conversion of 1961-11-30} {
+ clock format -255180304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1961 12:34:56 die xxx mensis xi annoque mcmlxi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2437634 11 xi 11 11/30/1961 die xxx mensis xi annoque mcmlxi 61 lxi 1961}
+test clock-2.767 {conversion of 1961-12-01} {
+ clock format -255093904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1961 12:34:56 die i mensis xii annoque mcmlxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2437635 12 xii 12 12/01/1961 die i mensis xii annoque mcmlxi 61 lxi 1961}
+test clock-2.768 {conversion of 1961-12-31} {
+ clock format -252501904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1961 12:34:56 die xxxi mensis xii annoque mcmlxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2437665 12 xii 12 12/31/1961 die xxxi mensis xii annoque mcmlxi 61 lxi 1961}
+test clock-2.769 {conversion of 1962-01-01} {
+ clock format -252415504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1962 12:34:56 die i mensis i annoque mcmlxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2437666 01 i 1 01/01/1962 die i mensis i annoque mcmlxii 62 lxii 1962}
+test clock-2.770 {conversion of 1962-01-31} {
+ clock format -249823504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1962 12:34:56 die xxxi mensis i annoque mcmlxii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2437696 01 i 1 01/31/1962 die xxxi mensis i annoque mcmlxii 62 lxii 1962}
+test clock-2.771 {conversion of 1962-02-01} {
+ clock format -249737104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1962 12:34:56 die i mensis ii annoque mcmlxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2437697 02 ii 2 02/01/1962 die i mensis ii annoque mcmlxii 62 lxii 1962}
+test clock-2.772 {conversion of 1962-02-28} {
+ clock format -247404304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1962 12:34:56 die xxviii mensis ii annoque mcmlxii xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2437724 02 ii 2 02/28/1962 die xxviii mensis ii annoque mcmlxii 62 lxii 1962}
+test clock-2.773 {conversion of 1962-03-01} {
+ clock format -247317904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1962 12:34:56 die i mensis iii annoque mcmlxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2437725 03 iii 3 03/01/1962 die i mensis iii annoque mcmlxii 62 lxii 1962}
+test clock-2.774 {conversion of 1962-03-31} {
+ clock format -244725904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1962 12:34:56 die xxxi mensis iii annoque mcmlxii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2437755 03 iii 3 03/31/1962 die xxxi mensis iii annoque mcmlxii 62 lxii 1962}
+test clock-2.775 {conversion of 1962-04-01} {
+ clock format -244639504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1962 12:34:56 die i mensis iv annoque mcmlxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2437756 04 iv 4 04/01/1962 die i mensis iv annoque mcmlxii 62 lxii 1962}
+test clock-2.776 {conversion of 1962-04-30} {
+ clock format -242133904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1962 12:34:56 die xxx mensis iv annoque mcmlxii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2437785 04 iv 4 04/30/1962 die xxx mensis iv annoque mcmlxii 62 lxii 1962}
+test clock-2.777 {conversion of 1962-05-01} {
+ clock format -242047504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1962 12:34:56 die i mensis v annoque mcmlxii xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2437786 05 v 5 05/01/1962 die i mensis v annoque mcmlxii 62 lxii 1962}
+test clock-2.778 {conversion of 1962-05-31} {
+ clock format -239455504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1962 12:34:56 die xxxi mensis v annoque mcmlxii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2437816 05 v 5 05/31/1962 die xxxi mensis v annoque mcmlxii 62 lxii 1962}
+test clock-2.779 {conversion of 1962-06-01} {
+ clock format -239369104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1962 12:34:56 die i mensis vi annoque mcmlxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2437817 06 vi 6 06/01/1962 die i mensis vi annoque mcmlxii 62 lxii 1962}
+test clock-2.780 {conversion of 1962-06-30} {
+ clock format -236863504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1962 12:34:56 die xxx mensis vi annoque mcmlxii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2437846 06 vi 6 06/30/1962 die xxx mensis vi annoque mcmlxii 62 lxii 1962}
+test clock-2.781 {conversion of 1962-07-01} {
+ clock format -236777104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1962 12:34:56 die i mensis vii annoque mcmlxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2437847 07 vii 7 07/01/1962 die i mensis vii annoque mcmlxii 62 lxii 1962}
+test clock-2.782 {conversion of 1962-07-31} {
+ clock format -234185104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1962 12:34:56 die xxxi mensis vii annoque mcmlxii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2437877 07 vii 7 07/31/1962 die xxxi mensis vii annoque mcmlxii 62 lxii 1962}
+test clock-2.783 {conversion of 1962-08-01} {
+ clock format -234098704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1962 12:34:56 die i mensis viii annoque mcmlxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2437878 08 viii 8 08/01/1962 die i mensis viii annoque mcmlxii 62 lxii 1962}
+test clock-2.784 {conversion of 1962-08-31} {
+ clock format -231506704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1962 12:34:56 die xxxi mensis viii annoque mcmlxii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2437908 08 viii 8 08/31/1962 die xxxi mensis viii annoque mcmlxii 62 lxii 1962}
+test clock-2.785 {conversion of 1962-09-01} {
+ clock format -231420304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1962 12:34:56 die i mensis ix annoque mcmlxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2437909 09 ix 9 09/01/1962 die i mensis ix annoque mcmlxii 62 lxii 1962}
+test clock-2.786 {conversion of 1962-09-30} {
+ clock format -228914704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1962 12:34:56 die xxx mensis ix annoque mcmlxii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2437938 09 ix 9 09/30/1962 die xxx mensis ix annoque mcmlxii 62 lxii 1962}
+test clock-2.787 {conversion of 1962-10-01} {
+ clock format -228828304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1962 12:34:56 die i mensis x annoque mcmlxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2437939 10 x 10 10/01/1962 die i mensis x annoque mcmlxii 62 lxii 1962}
+test clock-2.788 {conversion of 1962-10-31} {
+ clock format -226236304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1962 12:34:56 die xxxi mensis x annoque mcmlxii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2437969 10 x 10 10/31/1962 die xxxi mensis x annoque mcmlxii 62 lxii 1962}
+test clock-2.789 {conversion of 1962-11-01} {
+ clock format -226149904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1962 12:34:56 die i mensis xi annoque mcmlxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2437970 11 xi 11 11/01/1962 die i mensis xi annoque mcmlxii 62 lxii 1962}
+test clock-2.790 {conversion of 1962-11-30} {
+ clock format -223644304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1962 12:34:56 die xxx mensis xi annoque mcmlxii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2437999 11 xi 11 11/30/1962 die xxx mensis xi annoque mcmlxii 62 lxii 1962}
+test clock-2.791 {conversion of 1962-12-01} {
+ clock format -223557904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1962 12:34:56 die i mensis xii annoque mcmlxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2438000 12 xii 12 12/01/1962 die i mensis xii annoque mcmlxii 62 lxii 1962}
+test clock-2.792 {conversion of 1962-12-31} {
+ clock format -220965904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1962 12:34:56 die xxxi mensis xii annoque mcmlxii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2438030 12 xii 12 12/31/1962 die xxxi mensis xii annoque mcmlxii 62 lxii 1962}
+test clock-2.793 {conversion of 1963-01-01} {
+ clock format -220879504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1963 12:34:56 die i mensis i annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2438031 01 i 1 01/01/1963 die i mensis i annoque mcmlxiii 63 lxiii 1963}
+test clock-2.794 {conversion of 1963-01-31} {
+ clock format -218287504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1963 12:34:56 die xxxi mensis i annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2438061 01 i 1 01/31/1963 die xxxi mensis i annoque mcmlxiii 63 lxiii 1963}
+test clock-2.795 {conversion of 1963-02-01} {
+ clock format -218201104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1963 12:34:56 die i mensis ii annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2438062 02 ii 2 02/01/1963 die i mensis ii annoque mcmlxiii 63 lxiii 1963}
+test clock-2.796 {conversion of 1963-02-28} {
+ clock format -215868304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1963 12:34:56 die xxviii mensis ii annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2438089 02 ii 2 02/28/1963 die xxviii mensis ii annoque mcmlxiii 63 lxiii 1963}
+test clock-2.797 {conversion of 1963-03-01} {
+ clock format -215781904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1963 12:34:56 die i mensis iii annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2438090 03 iii 3 03/01/1963 die i mensis iii annoque mcmlxiii 63 lxiii 1963}
+test clock-2.798 {conversion of 1963-03-31} {
+ clock format -213189904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1963 12:34:56 die xxxi mensis iii annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2438120 03 iii 3 03/31/1963 die xxxi mensis iii annoque mcmlxiii 63 lxiii 1963}
+test clock-2.799 {conversion of 1963-04-01} {
+ clock format -213103504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1963 12:34:56 die i mensis iv annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2438121 04 iv 4 04/01/1963 die i mensis iv annoque mcmlxiii 63 lxiii 1963}
+test clock-2.800 {conversion of 1963-04-30} {
+ clock format -210597904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1963 12:34:56 die xxx mensis iv annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2438150 04 iv 4 04/30/1963 die xxx mensis iv annoque mcmlxiii 63 lxiii 1963}
+test clock-2.801 {conversion of 1963-05-01} {
+ clock format -210511504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1963 12:34:56 die i mensis v annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2438151 05 v 5 05/01/1963 die i mensis v annoque mcmlxiii 63 lxiii 1963}
+test clock-2.802 {conversion of 1963-05-31} {
+ clock format -207919504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1963 12:34:56 die xxxi mensis v annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2438181 05 v 5 05/31/1963 die xxxi mensis v annoque mcmlxiii 63 lxiii 1963}
+test clock-2.803 {conversion of 1963-06-01} {
+ clock format -207833104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1963 12:34:56 die i mensis vi annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2438182 06 vi 6 06/01/1963 die i mensis vi annoque mcmlxiii 63 lxiii 1963}
+test clock-2.804 {conversion of 1963-06-30} {
+ clock format -205327504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1963 12:34:56 die xxx mensis vi annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2438211 06 vi 6 06/30/1963 die xxx mensis vi annoque mcmlxiii 63 lxiii 1963}
+test clock-2.805 {conversion of 1963-07-01} {
+ clock format -205241104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1963 12:34:56 die i mensis vii annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2438212 07 vii 7 07/01/1963 die i mensis vii annoque mcmlxiii 63 lxiii 1963}
+test clock-2.806 {conversion of 1963-07-31} {
+ clock format -202649104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1963 12:34:56 die xxxi mensis vii annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2438242 07 vii 7 07/31/1963 die xxxi mensis vii annoque mcmlxiii 63 lxiii 1963}
+test clock-2.807 {conversion of 1963-08-01} {
+ clock format -202562704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1963 12:34:56 die i mensis viii annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2438243 08 viii 8 08/01/1963 die i mensis viii annoque mcmlxiii 63 lxiii 1963}
+test clock-2.808 {conversion of 1963-08-31} {
+ clock format -199970704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1963 12:34:56 die xxxi mensis viii annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2438273 08 viii 8 08/31/1963 die xxxi mensis viii annoque mcmlxiii 63 lxiii 1963}
+test clock-2.809 {conversion of 1963-09-01} {
+ clock format -199884304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1963 12:34:56 die i mensis ix annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2438274 09 ix 9 09/01/1963 die i mensis ix annoque mcmlxiii 63 lxiii 1963}
+test clock-2.810 {conversion of 1963-09-30} {
+ clock format -197378704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1963 12:34:56 die xxx mensis ix annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2438303 09 ix 9 09/30/1963 die xxx mensis ix annoque mcmlxiii 63 lxiii 1963}
+test clock-2.811 {conversion of 1963-10-01} {
+ clock format -197292304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1963 12:34:56 die i mensis x annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2438304 10 x 10 10/01/1963 die i mensis x annoque mcmlxiii 63 lxiii 1963}
+test clock-2.812 {conversion of 1963-10-31} {
+ clock format -194700304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1963 12:34:56 die xxxi mensis x annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2438334 10 x 10 10/31/1963 die xxxi mensis x annoque mcmlxiii 63 lxiii 1963}
+test clock-2.813 {conversion of 1963-11-01} {
+ clock format -194613904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1963 12:34:56 die i mensis xi annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2438335 11 xi 11 11/01/1963 die i mensis xi annoque mcmlxiii 63 lxiii 1963}
+test clock-2.814 {conversion of 1963-11-30} {
+ clock format -192108304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1963 12:34:56 die xxx mensis xi annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2438364 11 xi 11 11/30/1963 die xxx mensis xi annoque mcmlxiii 63 lxiii 1963}
+test clock-2.815 {conversion of 1963-12-01} {
+ clock format -192021904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1963 12:34:56 die i mensis xii annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2438365 12 xii 12 12/01/1963 die i mensis xii annoque mcmlxiii 63 lxiii 1963}
+test clock-2.816 {conversion of 1963-12-31} {
+ clock format -189429904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1963 12:34:56 die xxxi mensis xii annoque mcmlxiii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2438395 12 xii 12 12/31/1963 die xxxi mensis xii annoque mcmlxiii 63 lxiii 1963}
+test clock-2.817 {conversion of 1964-01-01} {
+ clock format -189343504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1964 12:34:56 die i mensis i annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2438396 01 i 1 01/01/1964 die i mensis i annoque mcmlxiv 64 lxiv 1964}
+test clock-2.818 {conversion of 1964-01-31} {
+ clock format -186751504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1964 12:34:56 die xxxi mensis i annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2438426 01 i 1 01/31/1964 die xxxi mensis i annoque mcmlxiv 64 lxiv 1964}
+test clock-2.819 {conversion of 1964-02-01} {
+ clock format -186665104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1964 12:34:56 die i mensis ii annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2438427 02 ii 2 02/01/1964 die i mensis ii annoque mcmlxiv 64 lxiv 1964}
+test clock-2.820 {conversion of 1964-02-29} {
+ clock format -184245904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1964 12:34:56 die xxix mensis ii annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 29 xxix 29 xxix Feb 060 2438455 02 ii 2 02/29/1964 die xxix mensis ii annoque mcmlxiv 64 lxiv 1964}
+test clock-2.821 {conversion of 1964-03-01} {
+ clock format -184159504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1964 12:34:56 die i mensis iii annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 061 2438456 03 iii 3 03/01/1964 die i mensis iii annoque mcmlxiv 64 lxiv 1964}
+test clock-2.822 {conversion of 1964-03-31} {
+ clock format -181567504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1964 12:34:56 die xxxi mensis iii annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 091 2438486 03 iii 3 03/31/1964 die xxxi mensis iii annoque mcmlxiv 64 lxiv 1964}
+test clock-2.823 {conversion of 1964-04-01} {
+ clock format -181481104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1964 12:34:56 die i mensis iv annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 092 2438487 04 iv 4 04/01/1964 die i mensis iv annoque mcmlxiv 64 lxiv 1964}
+test clock-2.824 {conversion of 1964-04-30} {
+ clock format -178975504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1964 12:34:56 die xxx mensis iv annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 121 2438516 04 iv 4 04/30/1964 die xxx mensis iv annoque mcmlxiv 64 lxiv 1964}
+test clock-2.825 {conversion of 1964-05-01} {
+ clock format -178889104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1964 12:34:56 die i mensis v annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i May 122 2438517 05 v 5 05/01/1964 die i mensis v annoque mcmlxiv 64 lxiv 1964}
+test clock-2.826 {conversion of 1964-05-31} {
+ clock format -176297104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1964 12:34:56 die xxxi mensis v annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 152 2438547 05 v 5 05/31/1964 die xxxi mensis v annoque mcmlxiv 64 lxiv 1964}
+test clock-2.827 {conversion of 1964-06-01} {
+ clock format -176210704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1964 12:34:56 die i mensis vi annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 153 2438548 06 vi 6 06/01/1964 die i mensis vi annoque mcmlxiv 64 lxiv 1964}
+test clock-2.828 {conversion of 1964-06-30} {
+ clock format -173705104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1964 12:34:56 die xxx mensis vi annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 182 2438577 06 vi 6 06/30/1964 die xxx mensis vi annoque mcmlxiv 64 lxiv 1964}
+test clock-2.829 {conversion of 1964-07-01} {
+ clock format -173618704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1964 12:34:56 die i mensis vii annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 183 2438578 07 vii 7 07/01/1964 die i mensis vii annoque mcmlxiv 64 lxiv 1964}
+test clock-2.830 {conversion of 1964-07-31} {
+ clock format -171026704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1964 12:34:56 die xxxi mensis vii annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 213 2438608 07 vii 7 07/31/1964 die xxxi mensis vii annoque mcmlxiv 64 lxiv 1964}
+test clock-2.831 {conversion of 1964-08-01} {
+ clock format -170940304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1964 12:34:56 die i mensis viii annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 214 2438609 08 viii 8 08/01/1964 die i mensis viii annoque mcmlxiv 64 lxiv 1964}
+test clock-2.832 {conversion of 1964-08-31} {
+ clock format -168348304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1964 12:34:56 die xxxi mensis viii annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 244 2438639 08 viii 8 08/31/1964 die xxxi mensis viii annoque mcmlxiv 64 lxiv 1964}
+test clock-2.833 {conversion of 1964-09-01} {
+ clock format -168261904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1964 12:34:56 die i mensis ix annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 245 2438640 09 ix 9 09/01/1964 die i mensis ix annoque mcmlxiv 64 lxiv 1964}
+test clock-2.834 {conversion of 1964-09-30} {
+ clock format -165756304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1964 12:34:56 die xxx mensis ix annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 274 2438669 09 ix 9 09/30/1964 die xxx mensis ix annoque mcmlxiv 64 lxiv 1964}
+test clock-2.835 {conversion of 1964-10-01} {
+ clock format -165669904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1964 12:34:56 die i mensis x annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 275 2438670 10 x 10 10/01/1964 die i mensis x annoque mcmlxiv 64 lxiv 1964}
+test clock-2.836 {conversion of 1964-10-31} {
+ clock format -163077904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1964 12:34:56 die xxxi mensis x annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 305 2438700 10 x 10 10/31/1964 die xxxi mensis x annoque mcmlxiv 64 lxiv 1964}
+test clock-2.837 {conversion of 1964-11-01} {
+ clock format -162991504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1964 12:34:56 die i mensis xi annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 306 2438701 11 xi 11 11/01/1964 die i mensis xi annoque mcmlxiv 64 lxiv 1964}
+test clock-2.838 {conversion of 1964-11-30} {
+ clock format -160485904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1964 12:34:56 die xxx mensis xi annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 335 2438730 11 xi 11 11/30/1964 die xxx mensis xi annoque mcmlxiv 64 lxiv 1964}
+test clock-2.839 {conversion of 1964-12-01} {
+ clock format -160399504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1964 12:34:56 die i mensis xii annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 336 2438731 12 xii 12 12/01/1964 die i mensis xii annoque mcmlxiv 64 lxiv 1964}
+test clock-2.840 {conversion of 1964-12-31} {
+ clock format -157807504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1964 12:34:56 die xxxi mensis xii annoque mcmlxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 366 2438761 12 xii 12 12/31/1964 die xxxi mensis xii annoque mcmlxiv 64 lxiv 1964}
+test clock-2.841 {conversion of 1965-01-01} {
+ clock format -157721104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1965 12:34:56 die i mensis i annoque mcmlxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2438762 01 i 1 01/01/1965 die i mensis i annoque mcmlxv 65 lxv 1965}
+test clock-2.842 {conversion of 1965-01-31} {
+ clock format -155129104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1965 12:34:56 die xxxi mensis i annoque mcmlxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2438792 01 i 1 01/31/1965 die xxxi mensis i annoque mcmlxv 65 lxv 1965}
+test clock-2.843 {conversion of 1965-02-01} {
+ clock format -155042704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1965 12:34:56 die i mensis ii annoque mcmlxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2438793 02 ii 2 02/01/1965 die i mensis ii annoque mcmlxv 65 lxv 1965}
+test clock-2.844 {conversion of 1965-02-28} {
+ clock format -152709904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1965 12:34:56 die xxviii mensis ii annoque mcmlxv xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2438820 02 ii 2 02/28/1965 die xxviii mensis ii annoque mcmlxv 65 lxv 1965}
+test clock-2.845 {conversion of 1965-03-01} {
+ clock format -152623504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1965 12:34:56 die i mensis iii annoque mcmlxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2438821 03 iii 3 03/01/1965 die i mensis iii annoque mcmlxv 65 lxv 1965}
+test clock-2.846 {conversion of 1965-03-31} {
+ clock format -150031504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1965 12:34:56 die xxxi mensis iii annoque mcmlxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2438851 03 iii 3 03/31/1965 die xxxi mensis iii annoque mcmlxv 65 lxv 1965}
+test clock-2.847 {conversion of 1965-04-01} {
+ clock format -149945104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1965 12:34:56 die i mensis iv annoque mcmlxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2438852 04 iv 4 04/01/1965 die i mensis iv annoque mcmlxv 65 lxv 1965}
+test clock-2.848 {conversion of 1965-04-30} {
+ clock format -147439504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1965 12:34:56 die xxx mensis iv annoque mcmlxv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2438881 04 iv 4 04/30/1965 die xxx mensis iv annoque mcmlxv 65 lxv 1965}
+test clock-2.849 {conversion of 1965-05-01} {
+ clock format -147353104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1965 12:34:56 die i mensis v annoque mcmlxv xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2438882 05 v 5 05/01/1965 die i mensis v annoque mcmlxv 65 lxv 1965}
+test clock-2.850 {conversion of 1965-05-31} {
+ clock format -144761104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1965 12:34:56 die xxxi mensis v annoque mcmlxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2438912 05 v 5 05/31/1965 die xxxi mensis v annoque mcmlxv 65 lxv 1965}
+test clock-2.851 {conversion of 1965-06-01} {
+ clock format -144674704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1965 12:34:56 die i mensis vi annoque mcmlxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2438913 06 vi 6 06/01/1965 die i mensis vi annoque mcmlxv 65 lxv 1965}
+test clock-2.852 {conversion of 1965-06-30} {
+ clock format -142169104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1965 12:34:56 die xxx mensis vi annoque mcmlxv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2438942 06 vi 6 06/30/1965 die xxx mensis vi annoque mcmlxv 65 lxv 1965}
+test clock-2.853 {conversion of 1965-07-01} {
+ clock format -142082704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1965 12:34:56 die i mensis vii annoque mcmlxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2438943 07 vii 7 07/01/1965 die i mensis vii annoque mcmlxv 65 lxv 1965}
+test clock-2.854 {conversion of 1965-07-31} {
+ clock format -139490704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1965 12:34:56 die xxxi mensis vii annoque mcmlxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2438973 07 vii 7 07/31/1965 die xxxi mensis vii annoque mcmlxv 65 lxv 1965}
+test clock-2.855 {conversion of 1965-08-01} {
+ clock format -139404304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1965 12:34:56 die i mensis viii annoque mcmlxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2438974 08 viii 8 08/01/1965 die i mensis viii annoque mcmlxv 65 lxv 1965}
+test clock-2.856 {conversion of 1965-08-31} {
+ clock format -136812304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1965 12:34:56 die xxxi mensis viii annoque mcmlxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2439004 08 viii 8 08/31/1965 die xxxi mensis viii annoque mcmlxv 65 lxv 1965}
+test clock-2.857 {conversion of 1965-09-01} {
+ clock format -136725904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1965 12:34:56 die i mensis ix annoque mcmlxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2439005 09 ix 9 09/01/1965 die i mensis ix annoque mcmlxv 65 lxv 1965}
+test clock-2.858 {conversion of 1965-09-30} {
+ clock format -134220304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1965 12:34:56 die xxx mensis ix annoque mcmlxv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2439034 09 ix 9 09/30/1965 die xxx mensis ix annoque mcmlxv 65 lxv 1965}
+test clock-2.859 {conversion of 1965-10-01} {
+ clock format -134133904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1965 12:34:56 die i mensis x annoque mcmlxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2439035 10 x 10 10/01/1965 die i mensis x annoque mcmlxv 65 lxv 1965}
+test clock-2.860 {conversion of 1965-10-31} {
+ clock format -131541904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1965 12:34:56 die xxxi mensis x annoque mcmlxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2439065 10 x 10 10/31/1965 die xxxi mensis x annoque mcmlxv 65 lxv 1965}
+test clock-2.861 {conversion of 1965-11-01} {
+ clock format -131455504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1965 12:34:56 die i mensis xi annoque mcmlxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2439066 11 xi 11 11/01/1965 die i mensis xi annoque mcmlxv 65 lxv 1965}
+test clock-2.862 {conversion of 1965-11-30} {
+ clock format -128949904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1965 12:34:56 die xxx mensis xi annoque mcmlxv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2439095 11 xi 11 11/30/1965 die xxx mensis xi annoque mcmlxv 65 lxv 1965}
+test clock-2.863 {conversion of 1965-12-01} {
+ clock format -128863504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1965 12:34:56 die i mensis xii annoque mcmlxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2439096 12 xii 12 12/01/1965 die i mensis xii annoque mcmlxv 65 lxv 1965}
+test clock-2.864 {conversion of 1965-12-31} {
+ clock format -126271504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1965 12:34:56 die xxxi mensis xii annoque mcmlxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2439126 12 xii 12 12/31/1965 die xxxi mensis xii annoque mcmlxv 65 lxv 1965}
+test clock-2.865 {conversion of 1966-01-01} {
+ clock format -126185104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1966 12:34:56 die i mensis i annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2439127 01 i 1 01/01/1966 die i mensis i annoque mcmlxvi 66 lxvi 1966}
+test clock-2.866 {conversion of 1966-01-31} {
+ clock format -123593104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1966 12:34:56 die xxxi mensis i annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2439157 01 i 1 01/31/1966 die xxxi mensis i annoque mcmlxvi 66 lxvi 1966}
+test clock-2.867 {conversion of 1966-02-01} {
+ clock format -123506704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1966 12:34:56 die i mensis ii annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2439158 02 ii 2 02/01/1966 die i mensis ii annoque mcmlxvi 66 lxvi 1966}
+test clock-2.868 {conversion of 1966-02-28} {
+ clock format -121173904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1966 12:34:56 die xxviii mensis ii annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2439185 02 ii 2 02/28/1966 die xxviii mensis ii annoque mcmlxvi 66 lxvi 1966}
+test clock-2.869 {conversion of 1966-03-01} {
+ clock format -121087504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1966 12:34:56 die i mensis iii annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2439186 03 iii 3 03/01/1966 die i mensis iii annoque mcmlxvi 66 lxvi 1966}
+test clock-2.870 {conversion of 1966-03-31} {
+ clock format -118495504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1966 12:34:56 die xxxi mensis iii annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2439216 03 iii 3 03/31/1966 die xxxi mensis iii annoque mcmlxvi 66 lxvi 1966}
+test clock-2.871 {conversion of 1966-04-01} {
+ clock format -118409104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1966 12:34:56 die i mensis iv annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2439217 04 iv 4 04/01/1966 die i mensis iv annoque mcmlxvi 66 lxvi 1966}
+test clock-2.872 {conversion of 1966-04-30} {
+ clock format -115903504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1966 12:34:56 die xxx mensis iv annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2439246 04 iv 4 04/30/1966 die xxx mensis iv annoque mcmlxvi 66 lxvi 1966}
+test clock-2.873 {conversion of 1966-05-01} {
+ clock format -115817104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1966 12:34:56 die i mensis v annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2439247 05 v 5 05/01/1966 die i mensis v annoque mcmlxvi 66 lxvi 1966}
+test clock-2.874 {conversion of 1966-05-31} {
+ clock format -113225104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1966 12:34:56 die xxxi mensis v annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2439277 05 v 5 05/31/1966 die xxxi mensis v annoque mcmlxvi 66 lxvi 1966}
+test clock-2.875 {conversion of 1966-06-01} {
+ clock format -113138704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1966 12:34:56 die i mensis vi annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2439278 06 vi 6 06/01/1966 die i mensis vi annoque mcmlxvi 66 lxvi 1966}
+test clock-2.876 {conversion of 1966-06-30} {
+ clock format -110633104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1966 12:34:56 die xxx mensis vi annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2439307 06 vi 6 06/30/1966 die xxx mensis vi annoque mcmlxvi 66 lxvi 1966}
+test clock-2.877 {conversion of 1966-07-01} {
+ clock format -110546704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1966 12:34:56 die i mensis vii annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2439308 07 vii 7 07/01/1966 die i mensis vii annoque mcmlxvi 66 lxvi 1966}
+test clock-2.878 {conversion of 1966-07-31} {
+ clock format -107954704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1966 12:34:56 die xxxi mensis vii annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2439338 07 vii 7 07/31/1966 die xxxi mensis vii annoque mcmlxvi 66 lxvi 1966}
+test clock-2.879 {conversion of 1966-08-01} {
+ clock format -107868304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1966 12:34:56 die i mensis viii annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2439339 08 viii 8 08/01/1966 die i mensis viii annoque mcmlxvi 66 lxvi 1966}
+test clock-2.880 {conversion of 1966-08-31} {
+ clock format -105276304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1966 12:34:56 die xxxi mensis viii annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2439369 08 viii 8 08/31/1966 die xxxi mensis viii annoque mcmlxvi 66 lxvi 1966}
+test clock-2.881 {conversion of 1966-09-01} {
+ clock format -105189904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1966 12:34:56 die i mensis ix annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2439370 09 ix 9 09/01/1966 die i mensis ix annoque mcmlxvi 66 lxvi 1966}
+test clock-2.882 {conversion of 1966-09-30} {
+ clock format -102684304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1966 12:34:56 die xxx mensis ix annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2439399 09 ix 9 09/30/1966 die xxx mensis ix annoque mcmlxvi 66 lxvi 1966}
+test clock-2.883 {conversion of 1966-10-01} {
+ clock format -102597904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1966 12:34:56 die i mensis x annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2439400 10 x 10 10/01/1966 die i mensis x annoque mcmlxvi 66 lxvi 1966}
+test clock-2.884 {conversion of 1966-10-31} {
+ clock format -100005904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1966 12:34:56 die xxxi mensis x annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2439430 10 x 10 10/31/1966 die xxxi mensis x annoque mcmlxvi 66 lxvi 1966}
+test clock-2.885 {conversion of 1966-11-01} {
+ clock format -99919504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1966 12:34:56 die i mensis xi annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2439431 11 xi 11 11/01/1966 die i mensis xi annoque mcmlxvi 66 lxvi 1966}
+test clock-2.886 {conversion of 1966-11-30} {
+ clock format -97413904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1966 12:34:56 die xxx mensis xi annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2439460 11 xi 11 11/30/1966 die xxx mensis xi annoque mcmlxvi 66 lxvi 1966}
+test clock-2.887 {conversion of 1966-12-01} {
+ clock format -97327504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1966 12:34:56 die i mensis xii annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2439461 12 xii 12 12/01/1966 die i mensis xii annoque mcmlxvi 66 lxvi 1966}
+test clock-2.888 {conversion of 1966-12-31} {
+ clock format -94735504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1966 12:34:56 die xxxi mensis xii annoque mcmlxvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2439491 12 xii 12 12/31/1966 die xxxi mensis xii annoque mcmlxvi 66 lxvi 1966}
+test clock-2.889 {conversion of 1967-01-01} {
+ clock format -94649104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1967 12:34:56 die i mensis i annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2439492 01 i 1 01/01/1967 die i mensis i annoque mcmlxvii 67 lxvii 1967}
+test clock-2.890 {conversion of 1967-01-31} {
+ clock format -92057104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1967 12:34:56 die xxxi mensis i annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2439522 01 i 1 01/31/1967 die xxxi mensis i annoque mcmlxvii 67 lxvii 1967}
+test clock-2.891 {conversion of 1967-02-01} {
+ clock format -91970704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1967 12:34:56 die i mensis ii annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2439523 02 ii 2 02/01/1967 die i mensis ii annoque mcmlxvii 67 lxvii 1967}
+test clock-2.892 {conversion of 1967-02-28} {
+ clock format -89637904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1967 12:34:56 die xxviii mensis ii annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2439550 02 ii 2 02/28/1967 die xxviii mensis ii annoque mcmlxvii 67 lxvii 1967}
+test clock-2.893 {conversion of 1967-03-01} {
+ clock format -89551504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1967 12:34:56 die i mensis iii annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2439551 03 iii 3 03/01/1967 die i mensis iii annoque mcmlxvii 67 lxvii 1967}
+test clock-2.894 {conversion of 1967-03-31} {
+ clock format -86959504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1967 12:34:56 die xxxi mensis iii annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2439581 03 iii 3 03/31/1967 die xxxi mensis iii annoque mcmlxvii 67 lxvii 1967}
+test clock-2.895 {conversion of 1967-04-01} {
+ clock format -86873104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1967 12:34:56 die i mensis iv annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2439582 04 iv 4 04/01/1967 die i mensis iv annoque mcmlxvii 67 lxvii 1967}
+test clock-2.896 {conversion of 1967-04-30} {
+ clock format -84367504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1967 12:34:56 die xxx mensis iv annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2439611 04 iv 4 04/30/1967 die xxx mensis iv annoque mcmlxvii 67 lxvii 1967}
+test clock-2.897 {conversion of 1967-05-01} {
+ clock format -84281104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1967 12:34:56 die i mensis v annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2439612 05 v 5 05/01/1967 die i mensis v annoque mcmlxvii 67 lxvii 1967}
+test clock-2.898 {conversion of 1967-05-31} {
+ clock format -81689104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1967 12:34:56 die xxxi mensis v annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2439642 05 v 5 05/31/1967 die xxxi mensis v annoque mcmlxvii 67 lxvii 1967}
+test clock-2.899 {conversion of 1967-06-01} {
+ clock format -81602704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1967 12:34:56 die i mensis vi annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2439643 06 vi 6 06/01/1967 die i mensis vi annoque mcmlxvii 67 lxvii 1967}
+test clock-2.900 {conversion of 1967-06-30} {
+ clock format -79097104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1967 12:34:56 die xxx mensis vi annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2439672 06 vi 6 06/30/1967 die xxx mensis vi annoque mcmlxvii 67 lxvii 1967}
+test clock-2.901 {conversion of 1967-07-01} {
+ clock format -79010704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1967 12:34:56 die i mensis vii annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2439673 07 vii 7 07/01/1967 die i mensis vii annoque mcmlxvii 67 lxvii 1967}
+test clock-2.902 {conversion of 1967-07-31} {
+ clock format -76418704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1967 12:34:56 die xxxi mensis vii annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2439703 07 vii 7 07/31/1967 die xxxi mensis vii annoque mcmlxvii 67 lxvii 1967}
+test clock-2.903 {conversion of 1967-08-01} {
+ clock format -76332304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1967 12:34:56 die i mensis viii annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2439704 08 viii 8 08/01/1967 die i mensis viii annoque mcmlxvii 67 lxvii 1967}
+test clock-2.904 {conversion of 1967-08-31} {
+ clock format -73740304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1967 12:34:56 die xxxi mensis viii annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2439734 08 viii 8 08/31/1967 die xxxi mensis viii annoque mcmlxvii 67 lxvii 1967}
+test clock-2.905 {conversion of 1967-09-01} {
+ clock format -73653904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1967 12:34:56 die i mensis ix annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2439735 09 ix 9 09/01/1967 die i mensis ix annoque mcmlxvii 67 lxvii 1967}
+test clock-2.906 {conversion of 1967-09-30} {
+ clock format -71148304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1967 12:34:56 die xxx mensis ix annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2439764 09 ix 9 09/30/1967 die xxx mensis ix annoque mcmlxvii 67 lxvii 1967}
+test clock-2.907 {conversion of 1967-10-01} {
+ clock format -71061904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1967 12:34:56 die i mensis x annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2439765 10 x 10 10/01/1967 die i mensis x annoque mcmlxvii 67 lxvii 1967}
+test clock-2.908 {conversion of 1967-10-31} {
+ clock format -68469904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1967 12:34:56 die xxxi mensis x annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2439795 10 x 10 10/31/1967 die xxxi mensis x annoque mcmlxvii 67 lxvii 1967}
+test clock-2.909 {conversion of 1967-11-01} {
+ clock format -68383504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1967 12:34:56 die i mensis xi annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2439796 11 xi 11 11/01/1967 die i mensis xi annoque mcmlxvii 67 lxvii 1967}
+test clock-2.910 {conversion of 1967-11-30} {
+ clock format -65877904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1967 12:34:56 die xxx mensis xi annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2439825 11 xi 11 11/30/1967 die xxx mensis xi annoque mcmlxvii 67 lxvii 1967}
+test clock-2.911 {conversion of 1967-12-01} {
+ clock format -65791504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1967 12:34:56 die i mensis xii annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2439826 12 xii 12 12/01/1967 die i mensis xii annoque mcmlxvii 67 lxvii 1967}
+test clock-2.912 {conversion of 1967-12-31} {
+ clock format -63199504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1967 12:34:56 die xxxi mensis xii annoque mcmlxvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2439856 12 xii 12 12/31/1967 die xxxi mensis xii annoque mcmlxvii 67 lxvii 1967}
+test clock-2.913 {conversion of 1968-01-01} {
+ clock format -63113104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1968 12:34:56 die i mensis i annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2439857 01 i 1 01/01/1968 die i mensis i annoque mcmlxviii 68 lxviii 1968}
+test clock-2.914 {conversion of 1968-01-31} {
+ clock format -60521104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1968 12:34:56 die xxxi mensis i annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2439887 01 i 1 01/31/1968 die xxxi mensis i annoque mcmlxviii 68 lxviii 1968}
+test clock-2.915 {conversion of 1968-02-01} {
+ clock format -60434704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1968 12:34:56 die i mensis ii annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2439888 02 ii 2 02/01/1968 die i mensis ii annoque mcmlxviii 68 lxviii 1968}
+test clock-2.916 {conversion of 1968-02-29} {
+ clock format -58015504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1968 12:34:56 die xxix mensis ii annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 29 xxix 29 xxix Feb 060 2439916 02 ii 2 02/29/1968 die xxix mensis ii annoque mcmlxviii 68 lxviii 1968}
+test clock-2.917 {conversion of 1968-03-01} {
+ clock format -57929104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1968 12:34:56 die i mensis iii annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 061 2439917 03 iii 3 03/01/1968 die i mensis iii annoque mcmlxviii 68 lxviii 1968}
+test clock-2.918 {conversion of 1968-03-31} {
+ clock format -55337104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1968 12:34:56 die xxxi mensis iii annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 091 2439947 03 iii 3 03/31/1968 die xxxi mensis iii annoque mcmlxviii 68 lxviii 1968}
+test clock-2.919 {conversion of 1968-04-01} {
+ clock format -55250704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1968 12:34:56 die i mensis iv annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 092 2439948 04 iv 4 04/01/1968 die i mensis iv annoque mcmlxviii 68 lxviii 1968}
+test clock-2.920 {conversion of 1968-04-30} {
+ clock format -52745104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1968 12:34:56 die xxx mensis iv annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 121 2439977 04 iv 4 04/30/1968 die xxx mensis iv annoque mcmlxviii 68 lxviii 1968}
+test clock-2.921 {conversion of 1968-05-01} {
+ clock format -52658704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1968 12:34:56 die i mensis v annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i May 122 2439978 05 v 5 05/01/1968 die i mensis v annoque mcmlxviii 68 lxviii 1968}
+test clock-2.922 {conversion of 1968-05-31} {
+ clock format -50066704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1968 12:34:56 die xxxi mensis v annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 152 2440008 05 v 5 05/31/1968 die xxxi mensis v annoque mcmlxviii 68 lxviii 1968}
+test clock-2.923 {conversion of 1968-06-01} {
+ clock format -49980304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1968 12:34:56 die i mensis vi annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 153 2440009 06 vi 6 06/01/1968 die i mensis vi annoque mcmlxviii 68 lxviii 1968}
+test clock-2.924 {conversion of 1968-06-30} {
+ clock format -47474704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1968 12:34:56 die xxx mensis vi annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 182 2440038 06 vi 6 06/30/1968 die xxx mensis vi annoque mcmlxviii 68 lxviii 1968}
+test clock-2.925 {conversion of 1968-07-01} {
+ clock format -47388304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1968 12:34:56 die i mensis vii annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 183 2440039 07 vii 7 07/01/1968 die i mensis vii annoque mcmlxviii 68 lxviii 1968}
+test clock-2.926 {conversion of 1968-07-31} {
+ clock format -44796304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1968 12:34:56 die xxxi mensis vii annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 213 2440069 07 vii 7 07/31/1968 die xxxi mensis vii annoque mcmlxviii 68 lxviii 1968}
+test clock-2.927 {conversion of 1968-08-01} {
+ clock format -44709904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1968 12:34:56 die i mensis viii annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 214 2440070 08 viii 8 08/01/1968 die i mensis viii annoque mcmlxviii 68 lxviii 1968}
+test clock-2.928 {conversion of 1968-08-31} {
+ clock format -42117904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1968 12:34:56 die xxxi mensis viii annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 244 2440100 08 viii 8 08/31/1968 die xxxi mensis viii annoque mcmlxviii 68 lxviii 1968}
+test clock-2.929 {conversion of 1968-09-01} {
+ clock format -42031504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1968 12:34:56 die i mensis ix annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 245 2440101 09 ix 9 09/01/1968 die i mensis ix annoque mcmlxviii 68 lxviii 1968}
+test clock-2.930 {conversion of 1968-09-30} {
+ clock format -39525904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1968 12:34:56 die xxx mensis ix annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 274 2440130 09 ix 9 09/30/1968 die xxx mensis ix annoque mcmlxviii 68 lxviii 1968}
+test clock-2.931 {conversion of 1968-10-01} {
+ clock format -39439504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1968 12:34:56 die i mensis x annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 275 2440131 10 x 10 10/01/1968 die i mensis x annoque mcmlxviii 68 lxviii 1968}
+test clock-2.932 {conversion of 1968-10-31} {
+ clock format -36847504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1968 12:34:56 die xxxi mensis x annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 305 2440161 10 x 10 10/31/1968 die xxxi mensis x annoque mcmlxviii 68 lxviii 1968}
+test clock-2.933 {conversion of 1968-11-01} {
+ clock format -36761104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1968 12:34:56 die i mensis xi annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 306 2440162 11 xi 11 11/01/1968 die i mensis xi annoque mcmlxviii 68 lxviii 1968}
+test clock-2.934 {conversion of 1968-11-30} {
+ clock format -34255504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1968 12:34:56 die xxx mensis xi annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 335 2440191 11 xi 11 11/30/1968 die xxx mensis xi annoque mcmlxviii 68 lxviii 1968}
+test clock-2.935 {conversion of 1968-12-01} {
+ clock format -34169104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1968 12:34:56 die i mensis xii annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 336 2440192 12 xii 12 12/01/1968 die i mensis xii annoque mcmlxviii 68 lxviii 1968}
+test clock-2.936 {conversion of 1968-12-31} {
+ clock format -31577104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1968 12:34:56 die xxxi mensis xii annoque mcmlxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 366 2440222 12 xii 12 12/31/1968 die xxxi mensis xii annoque mcmlxviii 68 lxviii 1968}
+test clock-2.937 {conversion of 1969-01-01} {
+ clock format -31490704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1969 12:34:56 die i mensis i annoque mcmlxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2440223 01 i 1 01/01/1969 die i mensis i annoque mcmlxix 69 lxix 1969}
+test clock-2.938 {conversion of 1969-01-31} {
+ clock format -28898704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1969 12:34:56 die xxxi mensis i annoque mcmlxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2440253 01 i 1 01/31/1969 die xxxi mensis i annoque mcmlxix 69 lxix 1969}
+test clock-2.939 {conversion of 1969-02-01} {
+ clock format -28812304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1969 12:34:56 die i mensis ii annoque mcmlxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2440254 02 ii 2 02/01/1969 die i mensis ii annoque mcmlxix 69 lxix 1969}
+test clock-2.940 {conversion of 1969-02-28} {
+ clock format -26479504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1969 12:34:56 die xxviii mensis ii annoque mcmlxix xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2440281 02 ii 2 02/28/1969 die xxviii mensis ii annoque mcmlxix 69 lxix 1969}
+test clock-2.941 {conversion of 1969-03-01} {
+ clock format -26393104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1969 12:34:56 die i mensis iii annoque mcmlxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2440282 03 iii 3 03/01/1969 die i mensis iii annoque mcmlxix 69 lxix 1969}
+test clock-2.942 {conversion of 1969-03-31} {
+ clock format -23801104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1969 12:34:56 die xxxi mensis iii annoque mcmlxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2440312 03 iii 3 03/31/1969 die xxxi mensis iii annoque mcmlxix 69 lxix 1969}
+test clock-2.943 {conversion of 1969-04-01} {
+ clock format -23714704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1969 12:34:56 die i mensis iv annoque mcmlxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2440313 04 iv 4 04/01/1969 die i mensis iv annoque mcmlxix 69 lxix 1969}
+test clock-2.944 {conversion of 1969-04-30} {
+ clock format -21209104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1969 12:34:56 die xxx mensis iv annoque mcmlxix xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2440342 04 iv 4 04/30/1969 die xxx mensis iv annoque mcmlxix 69 lxix 1969}
+test clock-2.945 {conversion of 1969-05-01} {
+ clock format -21122704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1969 12:34:56 die i mensis v annoque mcmlxix xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2440343 05 v 5 05/01/1969 die i mensis v annoque mcmlxix 69 lxix 1969}
+test clock-2.946 {conversion of 1969-05-31} {
+ clock format -18530704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1969 12:34:56 die xxxi mensis v annoque mcmlxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2440373 05 v 5 05/31/1969 die xxxi mensis v annoque mcmlxix 69 lxix 1969}
+test clock-2.947 {conversion of 1969-06-01} {
+ clock format -18444304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1969 12:34:56 die i mensis vi annoque mcmlxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2440374 06 vi 6 06/01/1969 die i mensis vi annoque mcmlxix 69 lxix 1969}
+test clock-2.948 {conversion of 1969-06-30} {
+ clock format -15938704 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1969 12:34:56 die xxx mensis vi annoque mcmlxix xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2440403 06 vi 6 06/30/1969 die xxx mensis vi annoque mcmlxix 69 lxix 1969}
+test clock-2.949 {conversion of 1969-07-01} {
+ clock format -15852304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1969 12:34:56 die i mensis vii annoque mcmlxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2440404 07 vii 7 07/01/1969 die i mensis vii annoque mcmlxix 69 lxix 1969}
+test clock-2.950 {conversion of 1969-07-31} {
+ clock format -13260304 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1969 12:34:56 die xxxi mensis vii annoque mcmlxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2440434 07 vii 7 07/31/1969 die xxxi mensis vii annoque mcmlxix 69 lxix 1969}
+test clock-2.951 {conversion of 1969-08-01} {
+ clock format -13173904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1969 12:34:56 die i mensis viii annoque mcmlxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2440435 08 viii 8 08/01/1969 die i mensis viii annoque mcmlxix 69 lxix 1969}
+test clock-2.952 {conversion of 1969-08-31} {
+ clock format -10581904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1969 12:34:56 die xxxi mensis viii annoque mcmlxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2440465 08 viii 8 08/31/1969 die xxxi mensis viii annoque mcmlxix 69 lxix 1969}
+test clock-2.953 {conversion of 1969-09-01} {
+ clock format -10495504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1969 12:34:56 die i mensis ix annoque mcmlxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2440466 09 ix 9 09/01/1969 die i mensis ix annoque mcmlxix 69 lxix 1969}
+test clock-2.954 {conversion of 1969-09-30} {
+ clock format -7989904 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1969 12:34:56 die xxx mensis ix annoque mcmlxix xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2440495 09 ix 9 09/30/1969 die xxx mensis ix annoque mcmlxix 69 lxix 1969}
+test clock-2.955 {conversion of 1969-10-01} {
+ clock format -7903504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1969 12:34:56 die i mensis x annoque mcmlxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2440496 10 x 10 10/01/1969 die i mensis x annoque mcmlxix 69 lxix 1969}
+test clock-2.956 {conversion of 1969-10-31} {
+ clock format -5311504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1969 12:34:56 die xxxi mensis x annoque mcmlxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2440526 10 x 10 10/31/1969 die xxxi mensis x annoque mcmlxix 69 lxix 1969}
+test clock-2.957 {conversion of 1969-11-01} {
+ clock format -5225104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1969 12:34:56 die i mensis xi annoque mcmlxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2440527 11 xi 11 11/01/1969 die i mensis xi annoque mcmlxix 69 lxix 1969}
+test clock-2.958 {conversion of 1969-11-30} {
+ clock format -2719504 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1969 12:34:56 die xxx mensis xi annoque mcmlxix xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2440556 11 xi 11 11/30/1969 die xxx mensis xi annoque mcmlxix 69 lxix 1969}
+test clock-2.959 {conversion of 1969-12-01} {
+ clock format -2633104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1969 12:34:56 die i mensis xii annoque mcmlxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2440557 12 xii 12 12/01/1969 die i mensis xii annoque mcmlxix 69 lxix 1969}
+test clock-2.960 {conversion of 1969-12-31} {
+ clock format -41104 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1969 12:34:56 die xxxi mensis xii annoque mcmlxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2440587 12 xii 12 12/31/1969 die xxxi mensis xii annoque mcmlxix 69 lxix 1969}
+test clock-2.961 {conversion of 1970-01-01} {
+ clock format 45296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1970 12:34:56 die i mensis i annoque mcmlxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2440588 01 i 1 01/01/1970 die i mensis i annoque mcmlxx 70 lxx 1970}
+test clock-2.962 {conversion of 1970-01-31} {
+ clock format 2637296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1970 12:34:56 die xxxi mensis i annoque mcmlxx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2440618 01 i 1 01/31/1970 die xxxi mensis i annoque mcmlxx 70 lxx 1970}
+test clock-2.963 {conversion of 1970-02-01} {
+ clock format 2723696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1970 12:34:56 die i mensis ii annoque mcmlxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2440619 02 ii 2 02/01/1970 die i mensis ii annoque mcmlxx 70 lxx 1970}
+test clock-2.964 {conversion of 1970-02-28} {
+ clock format 5056496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1970 12:34:56 die xxviii mensis ii annoque mcmlxx xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2440646 02 ii 2 02/28/1970 die xxviii mensis ii annoque mcmlxx 70 lxx 1970}
+test clock-2.965 {conversion of 1970-03-01} {
+ clock format 5142896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1970 12:34:56 die i mensis iii annoque mcmlxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2440647 03 iii 3 03/01/1970 die i mensis iii annoque mcmlxx 70 lxx 1970}
+test clock-2.966 {conversion of 1970-03-31} {
+ clock format 7734896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1970 12:34:56 die xxxi mensis iii annoque mcmlxx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2440677 03 iii 3 03/31/1970 die xxxi mensis iii annoque mcmlxx 70 lxx 1970}
+test clock-2.967 {conversion of 1970-04-01} {
+ clock format 7821296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1970 12:34:56 die i mensis iv annoque mcmlxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2440678 04 iv 4 04/01/1970 die i mensis iv annoque mcmlxx 70 lxx 1970}
+test clock-2.968 {conversion of 1970-04-30} {
+ clock format 10326896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1970 12:34:56 die xxx mensis iv annoque mcmlxx xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2440707 04 iv 4 04/30/1970 die xxx mensis iv annoque mcmlxx 70 lxx 1970}
+test clock-2.969 {conversion of 1970-05-01} {
+ clock format 10413296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1970 12:34:56 die i mensis v annoque mcmlxx xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2440708 05 v 5 05/01/1970 die i mensis v annoque mcmlxx 70 lxx 1970}
+test clock-2.970 {conversion of 1970-05-31} {
+ clock format 13005296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1970 12:34:56 die xxxi mensis v annoque mcmlxx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2440738 05 v 5 05/31/1970 die xxxi mensis v annoque mcmlxx 70 lxx 1970}
+test clock-2.971 {conversion of 1970-06-01} {
+ clock format 13091696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1970 12:34:56 die i mensis vi annoque mcmlxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2440739 06 vi 6 06/01/1970 die i mensis vi annoque mcmlxx 70 lxx 1970}
+test clock-2.972 {conversion of 1970-06-30} {
+ clock format 15597296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1970 12:34:56 die xxx mensis vi annoque mcmlxx xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2440768 06 vi 6 06/30/1970 die xxx mensis vi annoque mcmlxx 70 lxx 1970}
+test clock-2.973 {conversion of 1970-07-01} {
+ clock format 15683696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1970 12:34:56 die i mensis vii annoque mcmlxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2440769 07 vii 7 07/01/1970 die i mensis vii annoque mcmlxx 70 lxx 1970}
+test clock-2.974 {conversion of 1970-07-31} {
+ clock format 18275696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1970 12:34:56 die xxxi mensis vii annoque mcmlxx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2440799 07 vii 7 07/31/1970 die xxxi mensis vii annoque mcmlxx 70 lxx 1970}
+test clock-2.975 {conversion of 1970-08-01} {
+ clock format 18362096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1970 12:34:56 die i mensis viii annoque mcmlxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2440800 08 viii 8 08/01/1970 die i mensis viii annoque mcmlxx 70 lxx 1970}
+test clock-2.976 {conversion of 1970-08-31} {
+ clock format 20954096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1970 12:34:56 die xxxi mensis viii annoque mcmlxx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2440830 08 viii 8 08/31/1970 die xxxi mensis viii annoque mcmlxx 70 lxx 1970}
+test clock-2.977 {conversion of 1970-09-01} {
+ clock format 21040496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1970 12:34:56 die i mensis ix annoque mcmlxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2440831 09 ix 9 09/01/1970 die i mensis ix annoque mcmlxx 70 lxx 1970}
+test clock-2.978 {conversion of 1970-09-30} {
+ clock format 23546096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1970 12:34:56 die xxx mensis ix annoque mcmlxx xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2440860 09 ix 9 09/30/1970 die xxx mensis ix annoque mcmlxx 70 lxx 1970}
+test clock-2.979 {conversion of 1970-10-01} {
+ clock format 23632496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1970 12:34:56 die i mensis x annoque mcmlxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2440861 10 x 10 10/01/1970 die i mensis x annoque mcmlxx 70 lxx 1970}
+test clock-2.980 {conversion of 1970-10-31} {
+ clock format 26224496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1970 12:34:56 die xxxi mensis x annoque mcmlxx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2440891 10 x 10 10/31/1970 die xxxi mensis x annoque mcmlxx 70 lxx 1970}
+test clock-2.981 {conversion of 1970-11-01} {
+ clock format 26310896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1970 12:34:56 die i mensis xi annoque mcmlxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2440892 11 xi 11 11/01/1970 die i mensis xi annoque mcmlxx 70 lxx 1970}
+test clock-2.982 {conversion of 1970-11-30} {
+ clock format 28816496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1970 12:34:56 die xxx mensis xi annoque mcmlxx xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2440921 11 xi 11 11/30/1970 die xxx mensis xi annoque mcmlxx 70 lxx 1970}
+test clock-2.983 {conversion of 1970-12-01} {
+ clock format 28902896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1970 12:34:56 die i mensis xii annoque mcmlxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2440922 12 xii 12 12/01/1970 die i mensis xii annoque mcmlxx 70 lxx 1970}
+test clock-2.984 {conversion of 1970-12-31} {
+ clock format 31494896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1970 12:34:56 die xxxi mensis xii annoque mcmlxx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2440952 12 xii 12 12/31/1970 die xxxi mensis xii annoque mcmlxx 70 lxx 1970}
+test clock-2.985 {conversion of 1971-01-01} {
+ clock format 31581296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1971 12:34:56 die i mensis i annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2440953 01 i 1 01/01/1971 die i mensis i annoque mcmlxxi 71 lxxi 1971}
+test clock-2.986 {conversion of 1971-01-31} {
+ clock format 34173296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1971 12:34:56 die xxxi mensis i annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2440983 01 i 1 01/31/1971 die xxxi mensis i annoque mcmlxxi 71 lxxi 1971}
+test clock-2.987 {conversion of 1971-02-01} {
+ clock format 34259696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1971 12:34:56 die i mensis ii annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2440984 02 ii 2 02/01/1971 die i mensis ii annoque mcmlxxi 71 lxxi 1971}
+test clock-2.988 {conversion of 1971-02-28} {
+ clock format 36592496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1971 12:34:56 die xxviii mensis ii annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2441011 02 ii 2 02/28/1971 die xxviii mensis ii annoque mcmlxxi 71 lxxi 1971}
+test clock-2.989 {conversion of 1971-03-01} {
+ clock format 36678896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1971 12:34:56 die i mensis iii annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2441012 03 iii 3 03/01/1971 die i mensis iii annoque mcmlxxi 71 lxxi 1971}
+test clock-2.990 {conversion of 1971-03-31} {
+ clock format 39270896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1971 12:34:56 die xxxi mensis iii annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2441042 03 iii 3 03/31/1971 die xxxi mensis iii annoque mcmlxxi 71 lxxi 1971}
+test clock-2.991 {conversion of 1971-04-01} {
+ clock format 39357296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1971 12:34:56 die i mensis iv annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2441043 04 iv 4 04/01/1971 die i mensis iv annoque mcmlxxi 71 lxxi 1971}
+test clock-2.992 {conversion of 1971-04-30} {
+ clock format 41862896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1971 12:34:56 die xxx mensis iv annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2441072 04 iv 4 04/30/1971 die xxx mensis iv annoque mcmlxxi 71 lxxi 1971}
+test clock-2.993 {conversion of 1971-05-01} {
+ clock format 41949296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1971 12:34:56 die i mensis v annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2441073 05 v 5 05/01/1971 die i mensis v annoque mcmlxxi 71 lxxi 1971}
+test clock-2.994 {conversion of 1971-05-31} {
+ clock format 44541296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1971 12:34:56 die xxxi mensis v annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2441103 05 v 5 05/31/1971 die xxxi mensis v annoque mcmlxxi 71 lxxi 1971}
+test clock-2.995 {conversion of 1971-06-01} {
+ clock format 44627696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1971 12:34:56 die i mensis vi annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2441104 06 vi 6 06/01/1971 die i mensis vi annoque mcmlxxi 71 lxxi 1971}
+test clock-2.996 {conversion of 1971-06-30} {
+ clock format 47133296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1971 12:34:56 die xxx mensis vi annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2441133 06 vi 6 06/30/1971 die xxx mensis vi annoque mcmlxxi 71 lxxi 1971}
+test clock-2.997 {conversion of 1971-07-01} {
+ clock format 47219696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1971 12:34:56 die i mensis vii annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2441134 07 vii 7 07/01/1971 die i mensis vii annoque mcmlxxi 71 lxxi 1971}
+test clock-2.998 {conversion of 1971-07-31} {
+ clock format 49811696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1971 12:34:56 die xxxi mensis vii annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2441164 07 vii 7 07/31/1971 die xxxi mensis vii annoque mcmlxxi 71 lxxi 1971}
+test clock-2.999 {conversion of 1971-08-01} {
+ clock format 49898096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1971 12:34:56 die i mensis viii annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2441165 08 viii 8 08/01/1971 die i mensis viii annoque mcmlxxi 71 lxxi 1971}
+test clock-2.1000 {conversion of 1971-08-31} {
+ clock format 52490096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1971 12:34:56 die xxxi mensis viii annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2441195 08 viii 8 08/31/1971 die xxxi mensis viii annoque mcmlxxi 71 lxxi 1971}
+test clock-2.1001 {conversion of 1971-09-01} {
+ clock format 52576496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1971 12:34:56 die i mensis ix annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2441196 09 ix 9 09/01/1971 die i mensis ix annoque mcmlxxi 71 lxxi 1971}
+test clock-2.1002 {conversion of 1971-09-30} {
+ clock format 55082096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1971 12:34:56 die xxx mensis ix annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2441225 09 ix 9 09/30/1971 die xxx mensis ix annoque mcmlxxi 71 lxxi 1971}
+test clock-2.1003 {conversion of 1971-10-01} {
+ clock format 55168496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1971 12:34:56 die i mensis x annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2441226 10 x 10 10/01/1971 die i mensis x annoque mcmlxxi 71 lxxi 1971}
+test clock-2.1004 {conversion of 1971-10-31} {
+ clock format 57760496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1971 12:34:56 die xxxi mensis x annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2441256 10 x 10 10/31/1971 die xxxi mensis x annoque mcmlxxi 71 lxxi 1971}
+test clock-2.1005 {conversion of 1971-11-01} {
+ clock format 57846896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1971 12:34:56 die i mensis xi annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2441257 11 xi 11 11/01/1971 die i mensis xi annoque mcmlxxi 71 lxxi 1971}
+test clock-2.1006 {conversion of 1971-11-30} {
+ clock format 60352496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1971 12:34:56 die xxx mensis xi annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2441286 11 xi 11 11/30/1971 die xxx mensis xi annoque mcmlxxi 71 lxxi 1971}
+test clock-2.1007 {conversion of 1971-12-01} {
+ clock format 60438896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1971 12:34:56 die i mensis xii annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2441287 12 xii 12 12/01/1971 die i mensis xii annoque mcmlxxi 71 lxxi 1971}
+test clock-2.1008 {conversion of 1971-12-31} {
+ clock format 63030896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1971 12:34:56 die xxxi mensis xii annoque mcmlxxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2441317 12 xii 12 12/31/1971 die xxxi mensis xii annoque mcmlxxi 71 lxxi 1971}
+test clock-2.1009 {conversion of 1972-01-01} {
+ clock format 63117296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1972 12:34:56 die i mensis i annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2441318 01 i 1 01/01/1972 die i mensis i annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1010 {conversion of 1972-01-31} {
+ clock format 65709296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1972 12:34:56 die xxxi mensis i annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2441348 01 i 1 01/31/1972 die xxxi mensis i annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1011 {conversion of 1972-02-01} {
+ clock format 65795696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1972 12:34:56 die i mensis ii annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2441349 02 ii 2 02/01/1972 die i mensis ii annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1012 {conversion of 1972-02-29} {
+ clock format 68214896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1972 12:34:56 die xxix mensis ii annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 29 xxix 29 xxix Feb 060 2441377 02 ii 2 02/29/1972 die xxix mensis ii annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1013 {conversion of 1972-03-01} {
+ clock format 68301296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1972 12:34:56 die i mensis iii annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 061 2441378 03 iii 3 03/01/1972 die i mensis iii annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1014 {conversion of 1972-03-31} {
+ clock format 70893296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1972 12:34:56 die xxxi mensis iii annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 091 2441408 03 iii 3 03/31/1972 die xxxi mensis iii annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1015 {conversion of 1972-04-01} {
+ clock format 70979696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1972 12:34:56 die i mensis iv annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 092 2441409 04 iv 4 04/01/1972 die i mensis iv annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1016 {conversion of 1972-04-30} {
+ clock format 73485296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1972 12:34:56 die xxx mensis iv annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 121 2441438 04 iv 4 04/30/1972 die xxx mensis iv annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1017 {conversion of 1972-05-01} {
+ clock format 73571696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1972 12:34:56 die i mensis v annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 01 i 1 i May 122 2441439 05 v 5 05/01/1972 die i mensis v annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1018 {conversion of 1972-05-31} {
+ clock format 76163696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1972 12:34:56 die xxxi mensis v annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 152 2441469 05 v 5 05/31/1972 die xxxi mensis v annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1019 {conversion of 1972-06-01} {
+ clock format 76250096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1972 12:34:56 die i mensis vi annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 153 2441470 06 vi 6 06/01/1972 die i mensis vi annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1020 {conversion of 1972-06-30} {
+ clock format 78755696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1972 12:34:56 die xxx mensis vi annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 182 2441499 06 vi 6 06/30/1972 die xxx mensis vi annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1021 {conversion of 1972-07-01} {
+ clock format 78842096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1972 12:34:56 die i mensis vii annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 183 2441500 07 vii 7 07/01/1972 die i mensis vii annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1022 {conversion of 1972-07-31} {
+ clock format 81434096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1972 12:34:56 die xxxi mensis vii annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 213 2441530 07 vii 7 07/31/1972 die xxxi mensis vii annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1023 {conversion of 1972-08-01} {
+ clock format 81520496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1972 12:34:56 die i mensis viii annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 214 2441531 08 viii 8 08/01/1972 die i mensis viii annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1024 {conversion of 1972-08-31} {
+ clock format 84112496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1972 12:34:56 die xxxi mensis viii annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 244 2441561 08 viii 8 08/31/1972 die xxxi mensis viii annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1025 {conversion of 1972-09-01} {
+ clock format 84198896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1972 12:34:56 die i mensis ix annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 245 2441562 09 ix 9 09/01/1972 die i mensis ix annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1026 {conversion of 1972-09-30} {
+ clock format 86704496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1972 12:34:56 die xxx mensis ix annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 274 2441591 09 ix 9 09/30/1972 die xxx mensis ix annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1027 {conversion of 1972-10-01} {
+ clock format 86790896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1972 12:34:56 die i mensis x annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 275 2441592 10 x 10 10/01/1972 die i mensis x annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1028 {conversion of 1972-10-31} {
+ clock format 89382896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1972 12:34:56 die xxxi mensis x annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 305 2441622 10 x 10 10/31/1972 die xxxi mensis x annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1029 {conversion of 1972-11-01} {
+ clock format 89469296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1972 12:34:56 die i mensis xi annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 306 2441623 11 xi 11 11/01/1972 die i mensis xi annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1030 {conversion of 1972-11-30} {
+ clock format 91974896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1972 12:34:56 die xxx mensis xi annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 335 2441652 11 xi 11 11/30/1972 die xxx mensis xi annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1031 {conversion of 1972-12-01} {
+ clock format 92061296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1972 12:34:56 die i mensis xii annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 336 2441653 12 xii 12 12/01/1972 die i mensis xii annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1032 {conversion of 1972-12-31} {
+ clock format 94653296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1972 12:34:56 die xxxi mensis xii annoque mcmlxxii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 366 2441683 12 xii 12 12/31/1972 die xxxi mensis xii annoque mcmlxxii 72 lxxii 1972}
+test clock-2.1033 {conversion of 1973-01-01} {
+ clock format 94739696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1973 12:34:56 die i mensis i annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2441684 01 i 1 01/01/1973 die i mensis i annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1034 {conversion of 1973-01-31} {
+ clock format 97331696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1973 12:34:56 die xxxi mensis i annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2441714 01 i 1 01/31/1973 die xxxi mensis i annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1035 {conversion of 1973-02-01} {
+ clock format 97418096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1973 12:34:56 die i mensis ii annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2441715 02 ii 2 02/01/1973 die i mensis ii annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1036 {conversion of 1973-02-28} {
+ clock format 99750896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1973 12:34:56 die xxviii mensis ii annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2441742 02 ii 2 02/28/1973 die xxviii mensis ii annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1037 {conversion of 1973-03-01} {
+ clock format 99837296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1973 12:34:56 die i mensis iii annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2441743 03 iii 3 03/01/1973 die i mensis iii annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1038 {conversion of 1973-03-31} {
+ clock format 102429296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1973 12:34:56 die xxxi mensis iii annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2441773 03 iii 3 03/31/1973 die xxxi mensis iii annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1039 {conversion of 1973-04-01} {
+ clock format 102515696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1973 12:34:56 die i mensis iv annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2441774 04 iv 4 04/01/1973 die i mensis iv annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1040 {conversion of 1973-04-30} {
+ clock format 105021296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1973 12:34:56 die xxx mensis iv annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2441803 04 iv 4 04/30/1973 die xxx mensis iv annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1041 {conversion of 1973-05-01} {
+ clock format 105107696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1973 12:34:56 die i mensis v annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2441804 05 v 5 05/01/1973 die i mensis v annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1042 {conversion of 1973-05-31} {
+ clock format 107699696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1973 12:34:56 die xxxi mensis v annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2441834 05 v 5 05/31/1973 die xxxi mensis v annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1043 {conversion of 1973-06-01} {
+ clock format 107786096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1973 12:34:56 die i mensis vi annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2441835 06 vi 6 06/01/1973 die i mensis vi annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1044 {conversion of 1973-06-30} {
+ clock format 110291696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1973 12:34:56 die xxx mensis vi annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2441864 06 vi 6 06/30/1973 die xxx mensis vi annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1045 {conversion of 1973-07-01} {
+ clock format 110378096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1973 12:34:56 die i mensis vii annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2441865 07 vii 7 07/01/1973 die i mensis vii annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1046 {conversion of 1973-07-31} {
+ clock format 112970096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1973 12:34:56 die xxxi mensis vii annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2441895 07 vii 7 07/31/1973 die xxxi mensis vii annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1047 {conversion of 1973-08-01} {
+ clock format 113056496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1973 12:34:56 die i mensis viii annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2441896 08 viii 8 08/01/1973 die i mensis viii annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1048 {conversion of 1973-08-31} {
+ clock format 115648496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1973 12:34:56 die xxxi mensis viii annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2441926 08 viii 8 08/31/1973 die xxxi mensis viii annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1049 {conversion of 1973-09-01} {
+ clock format 115734896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1973 12:34:56 die i mensis ix annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2441927 09 ix 9 09/01/1973 die i mensis ix annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1050 {conversion of 1973-09-30} {
+ clock format 118240496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1973 12:34:56 die xxx mensis ix annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2441956 09 ix 9 09/30/1973 die xxx mensis ix annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1051 {conversion of 1973-10-01} {
+ clock format 118326896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1973 12:34:56 die i mensis x annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2441957 10 x 10 10/01/1973 die i mensis x annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1052 {conversion of 1973-10-31} {
+ clock format 120918896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1973 12:34:56 die xxxi mensis x annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2441987 10 x 10 10/31/1973 die xxxi mensis x annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1053 {conversion of 1973-11-01} {
+ clock format 121005296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1973 12:34:56 die i mensis xi annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2441988 11 xi 11 11/01/1973 die i mensis xi annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1054 {conversion of 1973-11-30} {
+ clock format 123510896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1973 12:34:56 die xxx mensis xi annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2442017 11 xi 11 11/30/1973 die xxx mensis xi annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1055 {conversion of 1973-12-01} {
+ clock format 123597296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1973 12:34:56 die i mensis xii annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2442018 12 xii 12 12/01/1973 die i mensis xii annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1056 {conversion of 1973-12-31} {
+ clock format 126189296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1973 12:34:56 die xxxi mensis xii annoque mcmlxxiii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2442048 12 xii 12 12/31/1973 die xxxi mensis xii annoque mcmlxxiii 73 lxxiii 1973}
+test clock-2.1057 {conversion of 1974-01-01} {
+ clock format 126275696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1974 12:34:56 die i mensis i annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2442049 01 i 1 01/01/1974 die i mensis i annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1058 {conversion of 1974-01-31} {
+ clock format 128867696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1974 12:34:56 die xxxi mensis i annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2442079 01 i 1 01/31/1974 die xxxi mensis i annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1059 {conversion of 1974-02-01} {
+ clock format 128954096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1974 12:34:56 die i mensis ii annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2442080 02 ii 2 02/01/1974 die i mensis ii annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1060 {conversion of 1974-02-28} {
+ clock format 131286896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1974 12:34:56 die xxviii mensis ii annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2442107 02 ii 2 02/28/1974 die xxviii mensis ii annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1061 {conversion of 1974-03-01} {
+ clock format 131373296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1974 12:34:56 die i mensis iii annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2442108 03 iii 3 03/01/1974 die i mensis iii annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1062 {conversion of 1974-03-31} {
+ clock format 133965296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1974 12:34:56 die xxxi mensis iii annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2442138 03 iii 3 03/31/1974 die xxxi mensis iii annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1063 {conversion of 1974-04-01} {
+ clock format 134051696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1974 12:34:56 die i mensis iv annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2442139 04 iv 4 04/01/1974 die i mensis iv annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1064 {conversion of 1974-04-30} {
+ clock format 136557296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1974 12:34:56 die xxx mensis iv annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2442168 04 iv 4 04/30/1974 die xxx mensis iv annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1065 {conversion of 1974-05-01} {
+ clock format 136643696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1974 12:34:56 die i mensis v annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2442169 05 v 5 05/01/1974 die i mensis v annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1066 {conversion of 1974-05-31} {
+ clock format 139235696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1974 12:34:56 die xxxi mensis v annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2442199 05 v 5 05/31/1974 die xxxi mensis v annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1067 {conversion of 1974-06-01} {
+ clock format 139322096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1974 12:34:56 die i mensis vi annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2442200 06 vi 6 06/01/1974 die i mensis vi annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1068 {conversion of 1974-06-30} {
+ clock format 141827696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1974 12:34:56 die xxx mensis vi annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2442229 06 vi 6 06/30/1974 die xxx mensis vi annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1069 {conversion of 1974-07-01} {
+ clock format 141914096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1974 12:34:56 die i mensis vii annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2442230 07 vii 7 07/01/1974 die i mensis vii annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1070 {conversion of 1974-07-31} {
+ clock format 144506096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1974 12:34:56 die xxxi mensis vii annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2442260 07 vii 7 07/31/1974 die xxxi mensis vii annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1071 {conversion of 1974-08-01} {
+ clock format 144592496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1974 12:34:56 die i mensis viii annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2442261 08 viii 8 08/01/1974 die i mensis viii annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1072 {conversion of 1974-08-31} {
+ clock format 147184496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1974 12:34:56 die xxxi mensis viii annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2442291 08 viii 8 08/31/1974 die xxxi mensis viii annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1073 {conversion of 1974-09-01} {
+ clock format 147270896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1974 12:34:56 die i mensis ix annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2442292 09 ix 9 09/01/1974 die i mensis ix annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1074 {conversion of 1974-09-30} {
+ clock format 149776496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1974 12:34:56 die xxx mensis ix annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2442321 09 ix 9 09/30/1974 die xxx mensis ix annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1075 {conversion of 1974-10-01} {
+ clock format 149862896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1974 12:34:56 die i mensis x annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2442322 10 x 10 10/01/1974 die i mensis x annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1076 {conversion of 1974-10-31} {
+ clock format 152454896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1974 12:34:56 die xxxi mensis x annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2442352 10 x 10 10/31/1974 die xxxi mensis x annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1077 {conversion of 1974-11-01} {
+ clock format 152541296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1974 12:34:56 die i mensis xi annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2442353 11 xi 11 11/01/1974 die i mensis xi annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1078 {conversion of 1974-11-30} {
+ clock format 155046896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1974 12:34:56 die xxx mensis xi annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2442382 11 xi 11 11/30/1974 die xxx mensis xi annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1079 {conversion of 1974-12-01} {
+ clock format 155133296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1974 12:34:56 die i mensis xii annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2442383 12 xii 12 12/01/1974 die i mensis xii annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1080 {conversion of 1974-12-31} {
+ clock format 157725296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1974 12:34:56 die xxxi mensis xii annoque mcmlxxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2442413 12 xii 12 12/31/1974 die xxxi mensis xii annoque mcmlxxiv 74 lxxiv 1974}
+test clock-2.1081 {conversion of 1975-01-01} {
+ clock format 157811696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1975 12:34:56 die i mensis i annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2442414 01 i 1 01/01/1975 die i mensis i annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1082 {conversion of 1975-01-31} {
+ clock format 160403696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1975 12:34:56 die xxxi mensis i annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2442444 01 i 1 01/31/1975 die xxxi mensis i annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1083 {conversion of 1975-02-01} {
+ clock format 160490096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1975 12:34:56 die i mensis ii annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2442445 02 ii 2 02/01/1975 die i mensis ii annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1084 {conversion of 1975-02-28} {
+ clock format 162822896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1975 12:34:56 die xxviii mensis ii annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2442472 02 ii 2 02/28/1975 die xxviii mensis ii annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1085 {conversion of 1975-03-01} {
+ clock format 162909296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1975 12:34:56 die i mensis iii annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2442473 03 iii 3 03/01/1975 die i mensis iii annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1086 {conversion of 1975-03-31} {
+ clock format 165501296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1975 12:34:56 die xxxi mensis iii annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2442503 03 iii 3 03/31/1975 die xxxi mensis iii annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1087 {conversion of 1975-04-01} {
+ clock format 165587696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1975 12:34:56 die i mensis iv annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2442504 04 iv 4 04/01/1975 die i mensis iv annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1088 {conversion of 1975-04-30} {
+ clock format 168093296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1975 12:34:56 die xxx mensis iv annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2442533 04 iv 4 04/30/1975 die xxx mensis iv annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1089 {conversion of 1975-05-01} {
+ clock format 168179696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1975 12:34:56 die i mensis v annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2442534 05 v 5 05/01/1975 die i mensis v annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1090 {conversion of 1975-05-31} {
+ clock format 170771696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1975 12:34:56 die xxxi mensis v annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2442564 05 v 5 05/31/1975 die xxxi mensis v annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1091 {conversion of 1975-06-01} {
+ clock format 170858096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1975 12:34:56 die i mensis vi annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2442565 06 vi 6 06/01/1975 die i mensis vi annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1092 {conversion of 1975-06-30} {
+ clock format 173363696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1975 12:34:56 die xxx mensis vi annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2442594 06 vi 6 06/30/1975 die xxx mensis vi annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1093 {conversion of 1975-07-01} {
+ clock format 173450096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1975 12:34:56 die i mensis vii annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2442595 07 vii 7 07/01/1975 die i mensis vii annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1094 {conversion of 1975-07-31} {
+ clock format 176042096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1975 12:34:56 die xxxi mensis vii annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2442625 07 vii 7 07/31/1975 die xxxi mensis vii annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1095 {conversion of 1975-08-01} {
+ clock format 176128496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1975 12:34:56 die i mensis viii annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2442626 08 viii 8 08/01/1975 die i mensis viii annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1096 {conversion of 1975-08-31} {
+ clock format 178720496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1975 12:34:56 die xxxi mensis viii annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2442656 08 viii 8 08/31/1975 die xxxi mensis viii annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1097 {conversion of 1975-09-01} {
+ clock format 178806896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1975 12:34:56 die i mensis ix annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2442657 09 ix 9 09/01/1975 die i mensis ix annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1098 {conversion of 1975-09-30} {
+ clock format 181312496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1975 12:34:56 die xxx mensis ix annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2442686 09 ix 9 09/30/1975 die xxx mensis ix annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1099 {conversion of 1975-10-01} {
+ clock format 181398896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1975 12:34:56 die i mensis x annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2442687 10 x 10 10/01/1975 die i mensis x annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1100 {conversion of 1975-10-31} {
+ clock format 183990896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1975 12:34:56 die xxxi mensis x annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2442717 10 x 10 10/31/1975 die xxxi mensis x annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1101 {conversion of 1975-11-01} {
+ clock format 184077296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1975 12:34:56 die i mensis xi annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2442718 11 xi 11 11/01/1975 die i mensis xi annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1102 {conversion of 1975-11-30} {
+ clock format 186582896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1975 12:34:56 die xxx mensis xi annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2442747 11 xi 11 11/30/1975 die xxx mensis xi annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1103 {conversion of 1975-12-01} {
+ clock format 186669296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1975 12:34:56 die i mensis xii annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2442748 12 xii 12 12/01/1975 die i mensis xii annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1104 {conversion of 1975-12-31} {
+ clock format 189261296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1975 12:34:56 die xxxi mensis xii annoque mcmlxxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2442778 12 xii 12 12/31/1975 die xxxi mensis xii annoque mcmlxxv 75 lxxv 1975}
+test clock-2.1105 {conversion of 1976-01-01} {
+ clock format 189347696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1976 12:34:56 die i mensis i annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2442779 01 i 1 01/01/1976 die i mensis i annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1106 {conversion of 1976-01-31} {
+ clock format 191939696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1976 12:34:56 die xxxi mensis i annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2442809 01 i 1 01/31/1976 die xxxi mensis i annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1107 {conversion of 1976-02-01} {
+ clock format 192026096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1976 12:34:56 die i mensis ii annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2442810 02 ii 2 02/01/1976 die i mensis ii annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1108 {conversion of 1976-02-29} {
+ clock format 194445296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1976 12:34:56 die xxix mensis ii annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 29 xxix 29 xxix Feb 060 2442838 02 ii 2 02/29/1976 die xxix mensis ii annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1109 {conversion of 1976-03-01} {
+ clock format 194531696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1976 12:34:56 die i mensis iii annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 061 2442839 03 iii 3 03/01/1976 die i mensis iii annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1110 {conversion of 1976-03-31} {
+ clock format 197123696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1976 12:34:56 die xxxi mensis iii annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 091 2442869 03 iii 3 03/31/1976 die xxxi mensis iii annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1111 {conversion of 1976-04-01} {
+ clock format 197210096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1976 12:34:56 die i mensis iv annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 092 2442870 04 iv 4 04/01/1976 die i mensis iv annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1112 {conversion of 1976-04-30} {
+ clock format 199715696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1976 12:34:56 die xxx mensis iv annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 121 2442899 04 iv 4 04/30/1976 die xxx mensis iv annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1113 {conversion of 1976-05-01} {
+ clock format 199802096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1976 12:34:56 die i mensis v annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i May 122 2442900 05 v 5 05/01/1976 die i mensis v annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1114 {conversion of 1976-05-31} {
+ clock format 202394096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1976 12:34:56 die xxxi mensis v annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 152 2442930 05 v 5 05/31/1976 die xxxi mensis v annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1115 {conversion of 1976-06-01} {
+ clock format 202480496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1976 12:34:56 die i mensis vi annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 153 2442931 06 vi 6 06/01/1976 die i mensis vi annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1116 {conversion of 1976-06-30} {
+ clock format 204986096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1976 12:34:56 die xxx mensis vi annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 182 2442960 06 vi 6 06/30/1976 die xxx mensis vi annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1117 {conversion of 1976-07-01} {
+ clock format 205072496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1976 12:34:56 die i mensis vii annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 183 2442961 07 vii 7 07/01/1976 die i mensis vii annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1118 {conversion of 1976-07-31} {
+ clock format 207664496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1976 12:34:56 die xxxi mensis vii annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 213 2442991 07 vii 7 07/31/1976 die xxxi mensis vii annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1119 {conversion of 1976-08-01} {
+ clock format 207750896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1976 12:34:56 die i mensis viii annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 214 2442992 08 viii 8 08/01/1976 die i mensis viii annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1120 {conversion of 1976-08-31} {
+ clock format 210342896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1976 12:34:56 die xxxi mensis viii annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 244 2443022 08 viii 8 08/31/1976 die xxxi mensis viii annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1121 {conversion of 1976-09-01} {
+ clock format 210429296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1976 12:34:56 die i mensis ix annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 245 2443023 09 ix 9 09/01/1976 die i mensis ix annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1122 {conversion of 1976-09-30} {
+ clock format 212934896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1976 12:34:56 die xxx mensis ix annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 274 2443052 09 ix 9 09/30/1976 die xxx mensis ix annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1123 {conversion of 1976-10-01} {
+ clock format 213021296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1976 12:34:56 die i mensis x annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 275 2443053 10 x 10 10/01/1976 die i mensis x annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1124 {conversion of 1976-10-31} {
+ clock format 215613296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1976 12:34:56 die xxxi mensis x annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 305 2443083 10 x 10 10/31/1976 die xxxi mensis x annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1125 {conversion of 1976-11-01} {
+ clock format 215699696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1976 12:34:56 die i mensis xi annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 306 2443084 11 xi 11 11/01/1976 die i mensis xi annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1126 {conversion of 1976-11-30} {
+ clock format 218205296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1976 12:34:56 die xxx mensis xi annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 335 2443113 11 xi 11 11/30/1976 die xxx mensis xi annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1127 {conversion of 1976-12-01} {
+ clock format 218291696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1976 12:34:56 die i mensis xii annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 336 2443114 12 xii 12 12/01/1976 die i mensis xii annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1128 {conversion of 1976-12-31} {
+ clock format 220883696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1976 12:34:56 die xxxi mensis xii annoque mcmlxxvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 366 2443144 12 xii 12 12/31/1976 die xxxi mensis xii annoque mcmlxxvi 76 lxxvi 1976}
+test clock-2.1129 {conversion of 1977-01-01} {
+ clock format 220970096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1977 12:34:56 die i mensis i annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2443145 01 i 1 01/01/1977 die i mensis i annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1130 {conversion of 1977-01-31} {
+ clock format 223562096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1977 12:34:56 die xxxi mensis i annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2443175 01 i 1 01/31/1977 die xxxi mensis i annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1131 {conversion of 1977-02-01} {
+ clock format 223648496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1977 12:34:56 die i mensis ii annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2443176 02 ii 2 02/01/1977 die i mensis ii annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1132 {conversion of 1977-02-28} {
+ clock format 225981296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1977 12:34:56 die xxviii mensis ii annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2443203 02 ii 2 02/28/1977 die xxviii mensis ii annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1133 {conversion of 1977-03-01} {
+ clock format 226067696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1977 12:34:56 die i mensis iii annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2443204 03 iii 3 03/01/1977 die i mensis iii annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1134 {conversion of 1977-03-31} {
+ clock format 228659696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1977 12:34:56 die xxxi mensis iii annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2443234 03 iii 3 03/31/1977 die xxxi mensis iii annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1135 {conversion of 1977-04-01} {
+ clock format 228746096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1977 12:34:56 die i mensis iv annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2443235 04 iv 4 04/01/1977 die i mensis iv annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1136 {conversion of 1977-04-30} {
+ clock format 231251696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1977 12:34:56 die xxx mensis iv annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2443264 04 iv 4 04/30/1977 die xxx mensis iv annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1137 {conversion of 1977-05-01} {
+ clock format 231338096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1977 12:34:56 die i mensis v annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2443265 05 v 5 05/01/1977 die i mensis v annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1138 {conversion of 1977-05-31} {
+ clock format 233930096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1977 12:34:56 die xxxi mensis v annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2443295 05 v 5 05/31/1977 die xxxi mensis v annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1139 {conversion of 1977-06-01} {
+ clock format 234016496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1977 12:34:56 die i mensis vi annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2443296 06 vi 6 06/01/1977 die i mensis vi annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1140 {conversion of 1977-06-30} {
+ clock format 236522096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1977 12:34:56 die xxx mensis vi annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2443325 06 vi 6 06/30/1977 die xxx mensis vi annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1141 {conversion of 1977-07-01} {
+ clock format 236608496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1977 12:34:56 die i mensis vii annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2443326 07 vii 7 07/01/1977 die i mensis vii annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1142 {conversion of 1977-07-31} {
+ clock format 239200496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1977 12:34:56 die xxxi mensis vii annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2443356 07 vii 7 07/31/1977 die xxxi mensis vii annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1143 {conversion of 1977-08-01} {
+ clock format 239286896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1977 12:34:56 die i mensis viii annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2443357 08 viii 8 08/01/1977 die i mensis viii annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1144 {conversion of 1977-08-31} {
+ clock format 241878896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1977 12:34:56 die xxxi mensis viii annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2443387 08 viii 8 08/31/1977 die xxxi mensis viii annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1145 {conversion of 1977-09-01} {
+ clock format 241965296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1977 12:34:56 die i mensis ix annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2443388 09 ix 9 09/01/1977 die i mensis ix annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1146 {conversion of 1977-09-30} {
+ clock format 244470896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1977 12:34:56 die xxx mensis ix annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2443417 09 ix 9 09/30/1977 die xxx mensis ix annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1147 {conversion of 1977-10-01} {
+ clock format 244557296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1977 12:34:56 die i mensis x annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2443418 10 x 10 10/01/1977 die i mensis x annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1148 {conversion of 1977-10-31} {
+ clock format 247149296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1977 12:34:56 die xxxi mensis x annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2443448 10 x 10 10/31/1977 die xxxi mensis x annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1149 {conversion of 1977-11-01} {
+ clock format 247235696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1977 12:34:56 die i mensis xi annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2443449 11 xi 11 11/01/1977 die i mensis xi annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1150 {conversion of 1977-11-30} {
+ clock format 249741296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1977 12:34:56 die xxx mensis xi annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2443478 11 xi 11 11/30/1977 die xxx mensis xi annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1151 {conversion of 1977-12-01} {
+ clock format 249827696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1977 12:34:56 die i mensis xii annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2443479 12 xii 12 12/01/1977 die i mensis xii annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1152 {conversion of 1977-12-31} {
+ clock format 252419696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1977 12:34:56 die xxxi mensis xii annoque mcmlxxvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2443509 12 xii 12 12/31/1977 die xxxi mensis xii annoque mcmlxxvii 77 lxxvii 1977}
+test clock-2.1153 {conversion of 1978-01-01} {
+ clock format 252506096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1978 12:34:56 die i mensis i annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2443510 01 i 1 01/01/1978 die i mensis i annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1154 {conversion of 1978-01-31} {
+ clock format 255098096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1978 12:34:56 die xxxi mensis i annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2443540 01 i 1 01/31/1978 die xxxi mensis i annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1155 {conversion of 1978-02-01} {
+ clock format 255184496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1978 12:34:56 die i mensis ii annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2443541 02 ii 2 02/01/1978 die i mensis ii annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1156 {conversion of 1978-02-28} {
+ clock format 257517296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1978 12:34:56 die xxviii mensis ii annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2443568 02 ii 2 02/28/1978 die xxviii mensis ii annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1157 {conversion of 1978-03-01} {
+ clock format 257603696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1978 12:34:56 die i mensis iii annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2443569 03 iii 3 03/01/1978 die i mensis iii annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1158 {conversion of 1978-03-31} {
+ clock format 260195696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1978 12:34:56 die xxxi mensis iii annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2443599 03 iii 3 03/31/1978 die xxxi mensis iii annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1159 {conversion of 1978-04-01} {
+ clock format 260282096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1978 12:34:56 die i mensis iv annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2443600 04 iv 4 04/01/1978 die i mensis iv annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1160 {conversion of 1978-04-30} {
+ clock format 262787696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1978 12:34:56 die xxx mensis iv annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2443629 04 iv 4 04/30/1978 die xxx mensis iv annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1161 {conversion of 1978-05-01} {
+ clock format 262874096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1978 12:34:56 die i mensis v annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2443630 05 v 5 05/01/1978 die i mensis v annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1162 {conversion of 1978-05-31} {
+ clock format 265466096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1978 12:34:56 die xxxi mensis v annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2443660 05 v 5 05/31/1978 die xxxi mensis v annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1163 {conversion of 1978-06-01} {
+ clock format 265552496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1978 12:34:56 die i mensis vi annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2443661 06 vi 6 06/01/1978 die i mensis vi annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1164 {conversion of 1978-06-30} {
+ clock format 268058096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1978 12:34:56 die xxx mensis vi annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2443690 06 vi 6 06/30/1978 die xxx mensis vi annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1165 {conversion of 1978-07-01} {
+ clock format 268144496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1978 12:34:56 die i mensis vii annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2443691 07 vii 7 07/01/1978 die i mensis vii annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1166 {conversion of 1978-07-31} {
+ clock format 270736496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1978 12:34:56 die xxxi mensis vii annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2443721 07 vii 7 07/31/1978 die xxxi mensis vii annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1167 {conversion of 1978-08-01} {
+ clock format 270822896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1978 12:34:56 die i mensis viii annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2443722 08 viii 8 08/01/1978 die i mensis viii annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1168 {conversion of 1978-08-31} {
+ clock format 273414896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1978 12:34:56 die xxxi mensis viii annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2443752 08 viii 8 08/31/1978 die xxxi mensis viii annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1169 {conversion of 1978-09-01} {
+ clock format 273501296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1978 12:34:56 die i mensis ix annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2443753 09 ix 9 09/01/1978 die i mensis ix annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1170 {conversion of 1978-09-30} {
+ clock format 276006896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1978 12:34:56 die xxx mensis ix annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2443782 09 ix 9 09/30/1978 die xxx mensis ix annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1171 {conversion of 1978-10-01} {
+ clock format 276093296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1978 12:34:56 die i mensis x annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2443783 10 x 10 10/01/1978 die i mensis x annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1172 {conversion of 1978-10-31} {
+ clock format 278685296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1978 12:34:56 die xxxi mensis x annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2443813 10 x 10 10/31/1978 die xxxi mensis x annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1173 {conversion of 1978-11-01} {
+ clock format 278771696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1978 12:34:56 die i mensis xi annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2443814 11 xi 11 11/01/1978 die i mensis xi annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1174 {conversion of 1978-11-30} {
+ clock format 281277296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1978 12:34:56 die xxx mensis xi annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2443843 11 xi 11 11/30/1978 die xxx mensis xi annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1175 {conversion of 1978-12-01} {
+ clock format 281363696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1978 12:34:56 die i mensis xii annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2443844 12 xii 12 12/01/1978 die i mensis xii annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1176 {conversion of 1978-12-31} {
+ clock format 283955696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1978 12:34:56 die xxxi mensis xii annoque mcmlxxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2443874 12 xii 12 12/31/1978 die xxxi mensis xii annoque mcmlxxviii 78 lxxviii 1978}
+test clock-2.1177 {conversion of 1979-01-01} {
+ clock format 284042096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1979 12:34:56 die i mensis i annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2443875 01 i 1 01/01/1979 die i mensis i annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1178 {conversion of 1979-01-31} {
+ clock format 286634096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1979 12:34:56 die xxxi mensis i annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2443905 01 i 1 01/31/1979 die xxxi mensis i annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1179 {conversion of 1979-02-01} {
+ clock format 286720496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1979 12:34:56 die i mensis ii annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2443906 02 ii 2 02/01/1979 die i mensis ii annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1180 {conversion of 1979-02-28} {
+ clock format 289053296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1979 12:34:56 die xxviii mensis ii annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2443933 02 ii 2 02/28/1979 die xxviii mensis ii annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1181 {conversion of 1979-03-01} {
+ clock format 289139696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1979 12:34:56 die i mensis iii annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2443934 03 iii 3 03/01/1979 die i mensis iii annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1182 {conversion of 1979-03-31} {
+ clock format 291731696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1979 12:34:56 die xxxi mensis iii annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2443964 03 iii 3 03/31/1979 die xxxi mensis iii annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1183 {conversion of 1979-04-01} {
+ clock format 291818096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1979 12:34:56 die i mensis iv annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2443965 04 iv 4 04/01/1979 die i mensis iv annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1184 {conversion of 1979-04-30} {
+ clock format 294323696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1979 12:34:56 die xxx mensis iv annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2443994 04 iv 4 04/30/1979 die xxx mensis iv annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1185 {conversion of 1979-05-01} {
+ clock format 294410096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1979 12:34:56 die i mensis v annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2443995 05 v 5 05/01/1979 die i mensis v annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1186 {conversion of 1979-05-31} {
+ clock format 297002096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1979 12:34:56 die xxxi mensis v annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2444025 05 v 5 05/31/1979 die xxxi mensis v annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1187 {conversion of 1979-06-01} {
+ clock format 297088496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1979 12:34:56 die i mensis vi annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2444026 06 vi 6 06/01/1979 die i mensis vi annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1188 {conversion of 1979-06-30} {
+ clock format 299594096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1979 12:34:56 die xxx mensis vi annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2444055 06 vi 6 06/30/1979 die xxx mensis vi annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1189 {conversion of 1979-07-01} {
+ clock format 299680496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1979 12:34:56 die i mensis vii annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2444056 07 vii 7 07/01/1979 die i mensis vii annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1190 {conversion of 1979-07-31} {
+ clock format 302272496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1979 12:34:56 die xxxi mensis vii annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2444086 07 vii 7 07/31/1979 die xxxi mensis vii annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1191 {conversion of 1979-08-01} {
+ clock format 302358896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1979 12:34:56 die i mensis viii annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2444087 08 viii 8 08/01/1979 die i mensis viii annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1192 {conversion of 1979-08-31} {
+ clock format 304950896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1979 12:34:56 die xxxi mensis viii annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2444117 08 viii 8 08/31/1979 die xxxi mensis viii annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1193 {conversion of 1979-09-01} {
+ clock format 305037296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1979 12:34:56 die i mensis ix annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2444118 09 ix 9 09/01/1979 die i mensis ix annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1194 {conversion of 1979-09-30} {
+ clock format 307542896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1979 12:34:56 die xxx mensis ix annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2444147 09 ix 9 09/30/1979 die xxx mensis ix annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1195 {conversion of 1979-10-01} {
+ clock format 307629296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1979 12:34:56 die i mensis x annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2444148 10 x 10 10/01/1979 die i mensis x annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1196 {conversion of 1979-10-31} {
+ clock format 310221296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1979 12:34:56 die xxxi mensis x annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2444178 10 x 10 10/31/1979 die xxxi mensis x annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1197 {conversion of 1979-11-01} {
+ clock format 310307696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1979 12:34:56 die i mensis xi annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2444179 11 xi 11 11/01/1979 die i mensis xi annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1198 {conversion of 1979-11-30} {
+ clock format 312813296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1979 12:34:56 die xxx mensis xi annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2444208 11 xi 11 11/30/1979 die xxx mensis xi annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1199 {conversion of 1979-12-01} {
+ clock format 312899696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1979 12:34:56 die i mensis xii annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2444209 12 xii 12 12/01/1979 die i mensis xii annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1200 {conversion of 1979-12-31} {
+ clock format 315491696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1979 12:34:56 die xxxi mensis xii annoque mcmlxxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2444239 12 xii 12 12/31/1979 die xxxi mensis xii annoque mcmlxxix 79 lxxix 1979}
+test clock-2.1201 {conversion of 1980-01-01} {
+ clock format 315578096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1980 12:34:56 die i mensis i annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2444240 01 i 1 01/01/1980 die i mensis i annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1202 {conversion of 1980-01-31} {
+ clock format 318170096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1980 12:34:56 die xxxi mensis i annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2444270 01 i 1 01/31/1980 die xxxi mensis i annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1203 {conversion of 1980-02-01} {
+ clock format 318256496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1980 12:34:56 die i mensis ii annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2444271 02 ii 2 02/01/1980 die i mensis ii annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1204 {conversion of 1980-02-29} {
+ clock format 320675696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1980 12:34:56 die xxix mensis ii annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 29 xxix 29 xxix Feb 060 2444299 02 ii 2 02/29/1980 die xxix mensis ii annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1205 {conversion of 1980-03-01} {
+ clock format 320762096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1980 12:34:56 die i mensis iii annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 061 2444300 03 iii 3 03/01/1980 die i mensis iii annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1206 {conversion of 1980-03-31} {
+ clock format 323354096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1980 12:34:56 die xxxi mensis iii annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 091 2444330 03 iii 3 03/31/1980 die xxxi mensis iii annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1207 {conversion of 1980-04-01} {
+ clock format 323440496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1980 12:34:56 die i mensis iv annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 092 2444331 04 iv 4 04/01/1980 die i mensis iv annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1208 {conversion of 1980-04-30} {
+ clock format 325946096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1980 12:34:56 die xxx mensis iv annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 121 2444360 04 iv 4 04/30/1980 die xxx mensis iv annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1209 {conversion of 1980-05-01} {
+ clock format 326032496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1980 12:34:56 die i mensis v annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 01 i 1 i May 122 2444361 05 v 5 05/01/1980 die i mensis v annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1210 {conversion of 1980-05-31} {
+ clock format 328624496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1980 12:34:56 die xxxi mensis v annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 152 2444391 05 v 5 05/31/1980 die xxxi mensis v annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1211 {conversion of 1980-06-01} {
+ clock format 328710896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1980 12:34:56 die i mensis vi annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 153 2444392 06 vi 6 06/01/1980 die i mensis vi annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1212 {conversion of 1980-06-30} {
+ clock format 331216496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1980 12:34:56 die xxx mensis vi annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 182 2444421 06 vi 6 06/30/1980 die xxx mensis vi annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1213 {conversion of 1980-07-01} {
+ clock format 331302896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1980 12:34:56 die i mensis vii annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 183 2444422 07 vii 7 07/01/1980 die i mensis vii annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1214 {conversion of 1980-07-31} {
+ clock format 333894896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1980 12:34:56 die xxxi mensis vii annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 213 2444452 07 vii 7 07/31/1980 die xxxi mensis vii annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1215 {conversion of 1980-08-01} {
+ clock format 333981296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1980 12:34:56 die i mensis viii annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 214 2444453 08 viii 8 08/01/1980 die i mensis viii annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1216 {conversion of 1980-08-31} {
+ clock format 336573296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1980 12:34:56 die xxxi mensis viii annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 244 2444483 08 viii 8 08/31/1980 die xxxi mensis viii annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1217 {conversion of 1980-09-01} {
+ clock format 336659696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1980 12:34:56 die i mensis ix annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 245 2444484 09 ix 9 09/01/1980 die i mensis ix annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1218 {conversion of 1980-09-30} {
+ clock format 339165296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1980 12:34:56 die xxx mensis ix annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 274 2444513 09 ix 9 09/30/1980 die xxx mensis ix annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1219 {conversion of 1980-10-01} {
+ clock format 339251696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1980 12:34:56 die i mensis x annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 275 2444514 10 x 10 10/01/1980 die i mensis x annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1220 {conversion of 1980-10-31} {
+ clock format 341843696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1980 12:34:56 die xxxi mensis x annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 305 2444544 10 x 10 10/31/1980 die xxxi mensis x annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1221 {conversion of 1980-11-01} {
+ clock format 341930096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1980 12:34:56 die i mensis xi annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 306 2444545 11 xi 11 11/01/1980 die i mensis xi annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1222 {conversion of 1980-11-30} {
+ clock format 344435696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1980 12:34:56 die xxx mensis xi annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 335 2444574 11 xi 11 11/30/1980 die xxx mensis xi annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1223 {conversion of 1980-12-01} {
+ clock format 344522096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1980 12:34:56 die i mensis xii annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 336 2444575 12 xii 12 12/01/1980 die i mensis xii annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1224 {conversion of 1980-12-31} {
+ clock format 347114096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1980 12:34:56 die xxxi mensis xii annoque mcmlxxx xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 366 2444605 12 xii 12 12/31/1980 die xxxi mensis xii annoque mcmlxxx 80 lxxx 1980}
+test clock-2.1225 {conversion of 1981-01-01} {
+ clock format 347200496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1981 12:34:56 die i mensis i annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2444606 01 i 1 01/01/1981 die i mensis i annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1226 {conversion of 1981-01-31} {
+ clock format 349792496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1981 12:34:56 die xxxi mensis i annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2444636 01 i 1 01/31/1981 die xxxi mensis i annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1227 {conversion of 1981-02-01} {
+ clock format 349878896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1981 12:34:56 die i mensis ii annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2444637 02 ii 2 02/01/1981 die i mensis ii annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1228 {conversion of 1981-02-28} {
+ clock format 352211696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1981 12:34:56 die xxviii mensis ii annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2444664 02 ii 2 02/28/1981 die xxviii mensis ii annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1229 {conversion of 1981-03-01} {
+ clock format 352298096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1981 12:34:56 die i mensis iii annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2444665 03 iii 3 03/01/1981 die i mensis iii annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1230 {conversion of 1981-03-31} {
+ clock format 354890096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1981 12:34:56 die xxxi mensis iii annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2444695 03 iii 3 03/31/1981 die xxxi mensis iii annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1231 {conversion of 1981-04-01} {
+ clock format 354976496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1981 12:34:56 die i mensis iv annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2444696 04 iv 4 04/01/1981 die i mensis iv annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1232 {conversion of 1981-04-30} {
+ clock format 357482096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1981 12:34:56 die xxx mensis iv annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2444725 04 iv 4 04/30/1981 die xxx mensis iv annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1233 {conversion of 1981-05-01} {
+ clock format 357568496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1981 12:34:56 die i mensis v annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2444726 05 v 5 05/01/1981 die i mensis v annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1234 {conversion of 1981-05-31} {
+ clock format 360160496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1981 12:34:56 die xxxi mensis v annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2444756 05 v 5 05/31/1981 die xxxi mensis v annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1235 {conversion of 1981-06-01} {
+ clock format 360246896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1981 12:34:56 die i mensis vi annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2444757 06 vi 6 06/01/1981 die i mensis vi annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1236 {conversion of 1981-06-30} {
+ clock format 362752496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1981 12:34:56 die xxx mensis vi annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2444786 06 vi 6 06/30/1981 die xxx mensis vi annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1237 {conversion of 1981-07-01} {
+ clock format 362838896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1981 12:34:56 die i mensis vii annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2444787 07 vii 7 07/01/1981 die i mensis vii annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1238 {conversion of 1981-07-31} {
+ clock format 365430896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1981 12:34:56 die xxxi mensis vii annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2444817 07 vii 7 07/31/1981 die xxxi mensis vii annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1239 {conversion of 1981-08-01} {
+ clock format 365517296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1981 12:34:56 die i mensis viii annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2444818 08 viii 8 08/01/1981 die i mensis viii annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1240 {conversion of 1981-08-31} {
+ clock format 368109296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1981 12:34:56 die xxxi mensis viii annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2444848 08 viii 8 08/31/1981 die xxxi mensis viii annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1241 {conversion of 1981-09-01} {
+ clock format 368195696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1981 12:34:56 die i mensis ix annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2444849 09 ix 9 09/01/1981 die i mensis ix annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1242 {conversion of 1981-09-30} {
+ clock format 370701296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1981 12:34:56 die xxx mensis ix annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2444878 09 ix 9 09/30/1981 die xxx mensis ix annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1243 {conversion of 1981-10-01} {
+ clock format 370787696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1981 12:34:56 die i mensis x annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2444879 10 x 10 10/01/1981 die i mensis x annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1244 {conversion of 1981-10-31} {
+ clock format 373379696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1981 12:34:56 die xxxi mensis x annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2444909 10 x 10 10/31/1981 die xxxi mensis x annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1245 {conversion of 1981-11-01} {
+ clock format 373466096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1981 12:34:56 die i mensis xi annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2444910 11 xi 11 11/01/1981 die i mensis xi annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1246 {conversion of 1981-11-30} {
+ clock format 375971696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1981 12:34:56 die xxx mensis xi annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2444939 11 xi 11 11/30/1981 die xxx mensis xi annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1247 {conversion of 1981-12-01} {
+ clock format 376058096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1981 12:34:56 die i mensis xii annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2444940 12 xii 12 12/01/1981 die i mensis xii annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1248 {conversion of 1981-12-31} {
+ clock format 378650096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1981 12:34:56 die xxxi mensis xii annoque mcmlxxxi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2444970 12 xii 12 12/31/1981 die xxxi mensis xii annoque mcmlxxxi 81 lxxxi 1981}
+test clock-2.1249 {conversion of 1984-01-01} {
+ clock format 441808496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1984 12:34:56 die i mensis i annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2445701 01 i 1 01/01/1984 die i mensis i annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1250 {conversion of 1984-01-31} {
+ clock format 444400496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1984 12:34:56 die xxxi mensis i annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2445731 01 i 1 01/31/1984 die xxxi mensis i annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1251 {conversion of 1984-02-01} {
+ clock format 444486896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1984 12:34:56 die i mensis ii annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2445732 02 ii 2 02/01/1984 die i mensis ii annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1252 {conversion of 1984-02-29} {
+ clock format 446906096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1984 12:34:56 die xxix mensis ii annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 29 xxix 29 xxix Feb 060 2445760 02 ii 2 02/29/1984 die xxix mensis ii annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1253 {conversion of 1984-03-01} {
+ clock format 446992496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1984 12:34:56 die i mensis iii annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 061 2445761 03 iii 3 03/01/1984 die i mensis iii annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1254 {conversion of 1984-03-31} {
+ clock format 449584496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1984 12:34:56 die xxxi mensis iii annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 091 2445791 03 iii 3 03/31/1984 die xxxi mensis iii annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1255 {conversion of 1984-04-01} {
+ clock format 449670896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1984 12:34:56 die i mensis iv annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 092 2445792 04 iv 4 04/01/1984 die i mensis iv annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1256 {conversion of 1984-04-30} {
+ clock format 452176496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1984 12:34:56 die xxx mensis iv annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 121 2445821 04 iv 4 04/30/1984 die xxx mensis iv annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1257 {conversion of 1984-05-01} {
+ clock format 452262896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1984 12:34:56 die i mensis v annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i May 122 2445822 05 v 5 05/01/1984 die i mensis v annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1258 {conversion of 1984-05-31} {
+ clock format 454854896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1984 12:34:56 die xxxi mensis v annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 152 2445852 05 v 5 05/31/1984 die xxxi mensis v annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1259 {conversion of 1984-06-01} {
+ clock format 454941296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1984 12:34:56 die i mensis vi annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 153 2445853 06 vi 6 06/01/1984 die i mensis vi annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1260 {conversion of 1984-06-30} {
+ clock format 457446896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1984 12:34:56 die xxx mensis vi annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 182 2445882 06 vi 6 06/30/1984 die xxx mensis vi annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1261 {conversion of 1984-07-01} {
+ clock format 457533296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1984 12:34:56 die i mensis vii annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 183 2445883 07 vii 7 07/01/1984 die i mensis vii annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1262 {conversion of 1984-07-31} {
+ clock format 460125296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1984 12:34:56 die xxxi mensis vii annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 213 2445913 07 vii 7 07/31/1984 die xxxi mensis vii annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1263 {conversion of 1984-08-01} {
+ clock format 460211696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1984 12:34:56 die i mensis viii annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 214 2445914 08 viii 8 08/01/1984 die i mensis viii annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1264 {conversion of 1984-08-31} {
+ clock format 462803696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1984 12:34:56 die xxxi mensis viii annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 244 2445944 08 viii 8 08/31/1984 die xxxi mensis viii annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1265 {conversion of 1984-09-01} {
+ clock format 462890096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1984 12:34:56 die i mensis ix annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 245 2445945 09 ix 9 09/01/1984 die i mensis ix annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1266 {conversion of 1984-09-30} {
+ clock format 465395696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1984 12:34:56 die xxx mensis ix annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 274 2445974 09 ix 9 09/30/1984 die xxx mensis ix annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1267 {conversion of 1984-10-01} {
+ clock format 465482096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1984 12:34:56 die i mensis x annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 275 2445975 10 x 10 10/01/1984 die i mensis x annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1268 {conversion of 1984-10-31} {
+ clock format 468074096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1984 12:34:56 die xxxi mensis x annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 305 2446005 10 x 10 10/31/1984 die xxxi mensis x annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1269 {conversion of 1984-11-01} {
+ clock format 468160496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1984 12:34:56 die i mensis xi annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 306 2446006 11 xi 11 11/01/1984 die i mensis xi annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1270 {conversion of 1984-11-30} {
+ clock format 470666096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1984 12:34:56 die xxx mensis xi annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 335 2446035 11 xi 11 11/30/1984 die xxx mensis xi annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1271 {conversion of 1984-12-01} {
+ clock format 470752496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1984 12:34:56 die i mensis xii annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 336 2446036 12 xii 12 12/01/1984 die i mensis xii annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1272 {conversion of 1984-12-31} {
+ clock format 473344496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1984 12:34:56 die xxxi mensis xii annoque mcmlxxxiv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 366 2446066 12 xii 12 12/31/1984 die xxxi mensis xii annoque mcmlxxxiv 84 lxxxiv 1984}
+test clock-2.1273 {conversion of 1985-01-01} {
+ clock format 473430896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1985 12:34:56 die i mensis i annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2446067 01 i 1 01/01/1985 die i mensis i annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1274 {conversion of 1985-01-31} {
+ clock format 476022896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1985 12:34:56 die xxxi mensis i annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2446097 01 i 1 01/31/1985 die xxxi mensis i annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1275 {conversion of 1985-02-01} {
+ clock format 476109296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1985 12:34:56 die i mensis ii annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2446098 02 ii 2 02/01/1985 die i mensis ii annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1276 {conversion of 1985-02-28} {
+ clock format 478442096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1985 12:34:56 die xxviii mensis ii annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2446125 02 ii 2 02/28/1985 die xxviii mensis ii annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1277 {conversion of 1985-03-01} {
+ clock format 478528496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1985 12:34:56 die i mensis iii annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2446126 03 iii 3 03/01/1985 die i mensis iii annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1278 {conversion of 1985-03-31} {
+ clock format 481120496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1985 12:34:56 die xxxi mensis iii annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2446156 03 iii 3 03/31/1985 die xxxi mensis iii annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1279 {conversion of 1985-04-01} {
+ clock format 481206896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1985 12:34:56 die i mensis iv annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2446157 04 iv 4 04/01/1985 die i mensis iv annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1280 {conversion of 1985-04-30} {
+ clock format 483712496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1985 12:34:56 die xxx mensis iv annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2446186 04 iv 4 04/30/1985 die xxx mensis iv annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1281 {conversion of 1985-05-01} {
+ clock format 483798896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1985 12:34:56 die i mensis v annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2446187 05 v 5 05/01/1985 die i mensis v annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1282 {conversion of 1985-05-31} {
+ clock format 486390896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1985 12:34:56 die xxxi mensis v annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2446217 05 v 5 05/31/1985 die xxxi mensis v annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1283 {conversion of 1985-06-01} {
+ clock format 486477296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1985 12:34:56 die i mensis vi annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2446218 06 vi 6 06/01/1985 die i mensis vi annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1284 {conversion of 1985-06-30} {
+ clock format 488982896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1985 12:34:56 die xxx mensis vi annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2446247 06 vi 6 06/30/1985 die xxx mensis vi annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1285 {conversion of 1985-07-01} {
+ clock format 489069296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1985 12:34:56 die i mensis vii annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2446248 07 vii 7 07/01/1985 die i mensis vii annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1286 {conversion of 1985-07-31} {
+ clock format 491661296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1985 12:34:56 die xxxi mensis vii annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2446278 07 vii 7 07/31/1985 die xxxi mensis vii annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1287 {conversion of 1985-08-01} {
+ clock format 491747696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1985 12:34:56 die i mensis viii annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2446279 08 viii 8 08/01/1985 die i mensis viii annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1288 {conversion of 1985-08-31} {
+ clock format 494339696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1985 12:34:56 die xxxi mensis viii annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2446309 08 viii 8 08/31/1985 die xxxi mensis viii annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1289 {conversion of 1985-09-01} {
+ clock format 494426096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1985 12:34:56 die i mensis ix annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2446310 09 ix 9 09/01/1985 die i mensis ix annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1290 {conversion of 1985-09-30} {
+ clock format 496931696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1985 12:34:56 die xxx mensis ix annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2446339 09 ix 9 09/30/1985 die xxx mensis ix annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1291 {conversion of 1985-10-01} {
+ clock format 497018096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1985 12:34:56 die i mensis x annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2446340 10 x 10 10/01/1985 die i mensis x annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1292 {conversion of 1985-10-31} {
+ clock format 499610096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1985 12:34:56 die xxxi mensis x annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2446370 10 x 10 10/31/1985 die xxxi mensis x annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1293 {conversion of 1985-11-01} {
+ clock format 499696496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1985 12:34:56 die i mensis xi annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2446371 11 xi 11 11/01/1985 die i mensis xi annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1294 {conversion of 1985-11-30} {
+ clock format 502202096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1985 12:34:56 die xxx mensis xi annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2446400 11 xi 11 11/30/1985 die xxx mensis xi annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1295 {conversion of 1985-12-01} {
+ clock format 502288496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1985 12:34:56 die i mensis xii annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2446401 12 xii 12 12/01/1985 die i mensis xii annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1296 {conversion of 1985-12-31} {
+ clock format 504880496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1985 12:34:56 die xxxi mensis xii annoque mcmlxxxv xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2446431 12 xii 12 12/31/1985 die xxxi mensis xii annoque mcmlxxxv 85 lxxxv 1985}
+test clock-2.1297 {conversion of 1988-01-01} {
+ clock format 568038896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1988 12:34:56 die i mensis i annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2447162 01 i 1 01/01/1988 die i mensis i annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1298 {conversion of 1988-01-31} {
+ clock format 570630896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1988 12:34:56 die xxxi mensis i annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2447192 01 i 1 01/31/1988 die xxxi mensis i annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1299 {conversion of 1988-02-01} {
+ clock format 570717296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1988 12:34:56 die i mensis ii annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2447193 02 ii 2 02/01/1988 die i mensis ii annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1300 {conversion of 1988-02-29} {
+ clock format 573136496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1988 12:34:56 die xxix mensis ii annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 29 xxix 29 xxix Feb 060 2447221 02 ii 2 02/29/1988 die xxix mensis ii annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1301 {conversion of 1988-03-01} {
+ clock format 573222896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1988 12:34:56 die i mensis iii annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 061 2447222 03 iii 3 03/01/1988 die i mensis iii annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1302 {conversion of 1988-03-31} {
+ clock format 575814896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1988 12:34:56 die xxxi mensis iii annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 091 2447252 03 iii 3 03/31/1988 die xxxi mensis iii annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1303 {conversion of 1988-04-01} {
+ clock format 575901296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1988 12:34:56 die i mensis iv annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 092 2447253 04 iv 4 04/01/1988 die i mensis iv annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1304 {conversion of 1988-04-30} {
+ clock format 578406896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1988 12:34:56 die xxx mensis iv annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 121 2447282 04 iv 4 04/30/1988 die xxx mensis iv annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1305 {conversion of 1988-05-01} {
+ clock format 578493296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1988 12:34:56 die i mensis v annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i May 122 2447283 05 v 5 05/01/1988 die i mensis v annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1306 {conversion of 1988-05-31} {
+ clock format 581085296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1988 12:34:56 die xxxi mensis v annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 152 2447313 05 v 5 05/31/1988 die xxxi mensis v annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1307 {conversion of 1988-06-01} {
+ clock format 581171696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1988 12:34:56 die i mensis vi annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 153 2447314 06 vi 6 06/01/1988 die i mensis vi annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1308 {conversion of 1988-06-30} {
+ clock format 583677296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1988 12:34:56 die xxx mensis vi annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 182 2447343 06 vi 6 06/30/1988 die xxx mensis vi annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1309 {conversion of 1988-07-01} {
+ clock format 583763696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1988 12:34:56 die i mensis vii annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 183 2447344 07 vii 7 07/01/1988 die i mensis vii annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1310 {conversion of 1988-07-31} {
+ clock format 586355696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1988 12:34:56 die xxxi mensis vii annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 213 2447374 07 vii 7 07/31/1988 die xxxi mensis vii annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1311 {conversion of 1988-08-01} {
+ clock format 586442096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1988 12:34:56 die i mensis viii annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 214 2447375 08 viii 8 08/01/1988 die i mensis viii annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1312 {conversion of 1988-08-31} {
+ clock format 589034096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1988 12:34:56 die xxxi mensis viii annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 244 2447405 08 viii 8 08/31/1988 die xxxi mensis viii annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1313 {conversion of 1988-09-01} {
+ clock format 589120496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1988 12:34:56 die i mensis ix annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 245 2447406 09 ix 9 09/01/1988 die i mensis ix annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1314 {conversion of 1988-09-30} {
+ clock format 591626096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1988 12:34:56 die xxx mensis ix annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 274 2447435 09 ix 9 09/30/1988 die xxx mensis ix annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1315 {conversion of 1988-10-01} {
+ clock format 591712496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1988 12:34:56 die i mensis x annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 275 2447436 10 x 10 10/01/1988 die i mensis x annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1316 {conversion of 1988-10-31} {
+ clock format 594304496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1988 12:34:56 die xxxi mensis x annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 305 2447466 10 x 10 10/31/1988 die xxxi mensis x annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1317 {conversion of 1988-11-01} {
+ clock format 594390896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1988 12:34:56 die i mensis xi annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 306 2447467 11 xi 11 11/01/1988 die i mensis xi annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1318 {conversion of 1988-11-30} {
+ clock format 596896496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1988 12:34:56 die xxx mensis xi annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 335 2447496 11 xi 11 11/30/1988 die xxx mensis xi annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1319 {conversion of 1988-12-01} {
+ clock format 596982896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1988 12:34:56 die i mensis xii annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 336 2447497 12 xii 12 12/01/1988 die i mensis xii annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1320 {conversion of 1988-12-31} {
+ clock format 599574896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1988 12:34:56 die xxxi mensis xii annoque mcmlxxxviii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 366 2447527 12 xii 12 12/31/1988 die xxxi mensis xii annoque mcmlxxxviii 88 lxxxviii 1988}
+test clock-2.1321 {conversion of 1989-01-01} {
+ clock format 599661296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1989 12:34:56 die i mensis i annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2447528 01 i 1 01/01/1989 die i mensis i annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1322 {conversion of 1989-01-31} {
+ clock format 602253296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1989 12:34:56 die xxxi mensis i annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2447558 01 i 1 01/31/1989 die xxxi mensis i annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1323 {conversion of 1989-02-01} {
+ clock format 602339696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1989 12:34:56 die i mensis ii annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2447559 02 ii 2 02/01/1989 die i mensis ii annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1324 {conversion of 1989-02-28} {
+ clock format 604672496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1989 12:34:56 die xxviii mensis ii annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2447586 02 ii 2 02/28/1989 die xxviii mensis ii annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1325 {conversion of 1989-03-01} {
+ clock format 604758896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1989 12:34:56 die i mensis iii annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2447587 03 iii 3 03/01/1989 die i mensis iii annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1326 {conversion of 1989-03-31} {
+ clock format 607350896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1989 12:34:56 die xxxi mensis iii annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2447617 03 iii 3 03/31/1989 die xxxi mensis iii annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1327 {conversion of 1989-04-01} {
+ clock format 607437296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1989 12:34:56 die i mensis iv annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2447618 04 iv 4 04/01/1989 die i mensis iv annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1328 {conversion of 1989-04-30} {
+ clock format 609942896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1989 12:34:56 die xxx mensis iv annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2447647 04 iv 4 04/30/1989 die xxx mensis iv annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1329 {conversion of 1989-05-01} {
+ clock format 610029296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1989 12:34:56 die i mensis v annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2447648 05 v 5 05/01/1989 die i mensis v annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1330 {conversion of 1989-05-31} {
+ clock format 612621296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1989 12:34:56 die xxxi mensis v annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2447678 05 v 5 05/31/1989 die xxxi mensis v annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1331 {conversion of 1989-06-01} {
+ clock format 612707696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1989 12:34:56 die i mensis vi annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2447679 06 vi 6 06/01/1989 die i mensis vi annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1332 {conversion of 1989-06-30} {
+ clock format 615213296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1989 12:34:56 die xxx mensis vi annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2447708 06 vi 6 06/30/1989 die xxx mensis vi annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1333 {conversion of 1989-07-01} {
+ clock format 615299696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1989 12:34:56 die i mensis vii annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2447709 07 vii 7 07/01/1989 die i mensis vii annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1334 {conversion of 1989-07-31} {
+ clock format 617891696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1989 12:34:56 die xxxi mensis vii annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2447739 07 vii 7 07/31/1989 die xxxi mensis vii annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1335 {conversion of 1989-08-01} {
+ clock format 617978096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1989 12:34:56 die i mensis viii annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2447740 08 viii 8 08/01/1989 die i mensis viii annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1336 {conversion of 1989-08-31} {
+ clock format 620570096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1989 12:34:56 die xxxi mensis viii annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2447770 08 viii 8 08/31/1989 die xxxi mensis viii annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1337 {conversion of 1989-09-01} {
+ clock format 620656496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1989 12:34:56 die i mensis ix annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2447771 09 ix 9 09/01/1989 die i mensis ix annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1338 {conversion of 1989-09-30} {
+ clock format 623162096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1989 12:34:56 die xxx mensis ix annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2447800 09 ix 9 09/30/1989 die xxx mensis ix annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1339 {conversion of 1989-10-01} {
+ clock format 623248496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1989 12:34:56 die i mensis x annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2447801 10 x 10 10/01/1989 die i mensis x annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1340 {conversion of 1989-10-31} {
+ clock format 625840496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1989 12:34:56 die xxxi mensis x annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2447831 10 x 10 10/31/1989 die xxxi mensis x annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1341 {conversion of 1989-11-01} {
+ clock format 625926896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1989 12:34:56 die i mensis xi annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2447832 11 xi 11 11/01/1989 die i mensis xi annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1342 {conversion of 1989-11-30} {
+ clock format 628432496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1989 12:34:56 die xxx mensis xi annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2447861 11 xi 11 11/30/1989 die xxx mensis xi annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1343 {conversion of 1989-12-01} {
+ clock format 628518896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1989 12:34:56 die i mensis xii annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2447862 12 xii 12 12/01/1989 die i mensis xii annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1344 {conversion of 1989-12-31} {
+ clock format 631110896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1989 12:34:56 die xxxi mensis xii annoque mcmlxxxix xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2447892 12 xii 12 12/31/1989 die xxxi mensis xii annoque mcmlxxxix 89 lxxxix 1989}
+test clock-2.1345 {conversion of 1992-01-01} {
+ clock format 694269296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1992 12:34:56 die i mensis i annoque mcmxcii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2448623 01 i 1 01/01/1992 die i mensis i annoque mcmxcii 92 xcii 1992}
+test clock-2.1346 {conversion of 1992-01-31} {
+ clock format 696861296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1992 12:34:56 die xxxi mensis i annoque mcmxcii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2448653 01 i 1 01/31/1992 die xxxi mensis i annoque mcmxcii 92 xcii 1992}
+test clock-2.1347 {conversion of 1992-02-01} {
+ clock format 696947696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1992 12:34:56 die i mensis ii annoque mcmxcii xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2448654 02 ii 2 02/01/1992 die i mensis ii annoque mcmxcii 92 xcii 1992}
+test clock-2.1348 {conversion of 1992-02-29} {
+ clock format 699366896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1992 12:34:56 die xxix mensis ii annoque mcmxcii xii h xxxiv m lvi s 19 mcm 29 xxix 29 xxix Feb 060 2448682 02 ii 2 02/29/1992 die xxix mensis ii annoque mcmxcii 92 xcii 1992}
+test clock-2.1349 {conversion of 1992-03-01} {
+ clock format 699453296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1992 12:34:56 die i mensis iii annoque mcmxcii xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 061 2448683 03 iii 3 03/01/1992 die i mensis iii annoque mcmxcii 92 xcii 1992}
+test clock-2.1350 {conversion of 1992-03-31} {
+ clock format 702045296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1992 12:34:56 die xxxi mensis iii annoque mcmxcii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 091 2448713 03 iii 3 03/31/1992 die xxxi mensis iii annoque mcmxcii 92 xcii 1992}
+test clock-2.1351 {conversion of 1992-04-01} {
+ clock format 702131696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1992 12:34:56 die i mensis iv annoque mcmxcii xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 092 2448714 04 iv 4 04/01/1992 die i mensis iv annoque mcmxcii 92 xcii 1992}
+test clock-2.1352 {conversion of 1992-04-30} {
+ clock format 704637296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1992 12:34:56 die xxx mensis iv annoque mcmxcii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 121 2448743 04 iv 4 04/30/1992 die xxx mensis iv annoque mcmxcii 92 xcii 1992}
+test clock-2.1353 {conversion of 1992-05-01} {
+ clock format 704723696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1992 12:34:56 die i mensis v annoque mcmxcii xii h xxxiv m lvi s 19 mcm 01 i 1 i May 122 2448744 05 v 5 05/01/1992 die i mensis v annoque mcmxcii 92 xcii 1992}
+test clock-2.1354 {conversion of 1992-05-31} {
+ clock format 707315696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1992 12:34:56 die xxxi mensis v annoque mcmxcii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 152 2448774 05 v 5 05/31/1992 die xxxi mensis v annoque mcmxcii 92 xcii 1992}
+test clock-2.1355 {conversion of 1992-06-01} {
+ clock format 707402096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1992 12:34:56 die i mensis vi annoque mcmxcii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 153 2448775 06 vi 6 06/01/1992 die i mensis vi annoque mcmxcii 92 xcii 1992}
+test clock-2.1356 {conversion of 1992-06-30} {
+ clock format 709907696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1992 12:34:56 die xxx mensis vi annoque mcmxcii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 182 2448804 06 vi 6 06/30/1992 die xxx mensis vi annoque mcmxcii 92 xcii 1992}
+test clock-2.1357 {conversion of 1992-07-01} {
+ clock format 709994096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1992 12:34:56 die i mensis vii annoque mcmxcii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 183 2448805 07 vii 7 07/01/1992 die i mensis vii annoque mcmxcii 92 xcii 1992}
+test clock-2.1358 {conversion of 1992-07-31} {
+ clock format 712586096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1992 12:34:56 die xxxi mensis vii annoque mcmxcii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 213 2448835 07 vii 7 07/31/1992 die xxxi mensis vii annoque mcmxcii 92 xcii 1992}
+test clock-2.1359 {conversion of 1992-08-01} {
+ clock format 712672496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1992 12:34:56 die i mensis viii annoque mcmxcii xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 214 2448836 08 viii 8 08/01/1992 die i mensis viii annoque mcmxcii 92 xcii 1992}
+test clock-2.1360 {conversion of 1992-08-31} {
+ clock format 715264496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1992 12:34:56 die xxxi mensis viii annoque mcmxcii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 244 2448866 08 viii 8 08/31/1992 die xxxi mensis viii annoque mcmxcii 92 xcii 1992}
+test clock-2.1361 {conversion of 1992-09-01} {
+ clock format 715350896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1992 12:34:56 die i mensis ix annoque mcmxcii xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 245 2448867 09 ix 9 09/01/1992 die i mensis ix annoque mcmxcii 92 xcii 1992}
+test clock-2.1362 {conversion of 1992-09-30} {
+ clock format 717856496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1992 12:34:56 die xxx mensis ix annoque mcmxcii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 274 2448896 09 ix 9 09/30/1992 die xxx mensis ix annoque mcmxcii 92 xcii 1992}
+test clock-2.1363 {conversion of 1992-10-01} {
+ clock format 717942896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1992 12:34:56 die i mensis x annoque mcmxcii xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 275 2448897 10 x 10 10/01/1992 die i mensis x annoque mcmxcii 92 xcii 1992}
+test clock-2.1364 {conversion of 1992-10-31} {
+ clock format 720534896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1992 12:34:56 die xxxi mensis x annoque mcmxcii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 305 2448927 10 x 10 10/31/1992 die xxxi mensis x annoque mcmxcii 92 xcii 1992}
+test clock-2.1365 {conversion of 1992-11-01} {
+ clock format 720621296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1992 12:34:56 die i mensis xi annoque mcmxcii xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 306 2448928 11 xi 11 11/01/1992 die i mensis xi annoque mcmxcii 92 xcii 1992}
+test clock-2.1366 {conversion of 1992-11-30} {
+ clock format 723126896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1992 12:34:56 die xxx mensis xi annoque mcmxcii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 335 2448957 11 xi 11 11/30/1992 die xxx mensis xi annoque mcmxcii 92 xcii 1992}
+test clock-2.1367 {conversion of 1992-12-01} {
+ clock format 723213296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1992 12:34:56 die i mensis xii annoque mcmxcii xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 336 2448958 12 xii 12 12/01/1992 die i mensis xii annoque mcmxcii 92 xcii 1992}
+test clock-2.1368 {conversion of 1992-12-31} {
+ clock format 725805296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1992 12:34:56 die xxxi mensis xii annoque mcmxcii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 366 2448988 12 xii 12 12/31/1992 die xxxi mensis xii annoque mcmxcii 92 xcii 1992}
+test clock-2.1369 {conversion of 1993-01-01} {
+ clock format 725891696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1993 12:34:56 die i mensis i annoque mcmxciii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2448989 01 i 1 01/01/1993 die i mensis i annoque mcmxciii 93 xciii 1993}
+test clock-2.1370 {conversion of 1993-01-31} {
+ clock format 728483696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1993 12:34:56 die xxxi mensis i annoque mcmxciii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2449019 01 i 1 01/31/1993 die xxxi mensis i annoque mcmxciii 93 xciii 1993}
+test clock-2.1371 {conversion of 1993-02-01} {
+ clock format 728570096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1993 12:34:56 die i mensis ii annoque mcmxciii xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2449020 02 ii 2 02/01/1993 die i mensis ii annoque mcmxciii 93 xciii 1993}
+test clock-2.1372 {conversion of 1993-02-28} {
+ clock format 730902896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1993 12:34:56 die xxviii mensis ii annoque mcmxciii xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2449047 02 ii 2 02/28/1993 die xxviii mensis ii annoque mcmxciii 93 xciii 1993}
+test clock-2.1373 {conversion of 1993-03-01} {
+ clock format 730989296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1993 12:34:56 die i mensis iii annoque mcmxciii xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2449048 03 iii 3 03/01/1993 die i mensis iii annoque mcmxciii 93 xciii 1993}
+test clock-2.1374 {conversion of 1993-03-31} {
+ clock format 733581296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1993 12:34:56 die xxxi mensis iii annoque mcmxciii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2449078 03 iii 3 03/31/1993 die xxxi mensis iii annoque mcmxciii 93 xciii 1993}
+test clock-2.1375 {conversion of 1993-04-01} {
+ clock format 733667696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1993 12:34:56 die i mensis iv annoque mcmxciii xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2449079 04 iv 4 04/01/1993 die i mensis iv annoque mcmxciii 93 xciii 1993}
+test clock-2.1376 {conversion of 1993-04-30} {
+ clock format 736173296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1993 12:34:56 die xxx mensis iv annoque mcmxciii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2449108 04 iv 4 04/30/1993 die xxx mensis iv annoque mcmxciii 93 xciii 1993}
+test clock-2.1377 {conversion of 1993-05-01} {
+ clock format 736259696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1993 12:34:56 die i mensis v annoque mcmxciii xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2449109 05 v 5 05/01/1993 die i mensis v annoque mcmxciii 93 xciii 1993}
+test clock-2.1378 {conversion of 1993-05-31} {
+ clock format 738851696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1993 12:34:56 die xxxi mensis v annoque mcmxciii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2449139 05 v 5 05/31/1993 die xxxi mensis v annoque mcmxciii 93 xciii 1993}
+test clock-2.1379 {conversion of 1993-06-01} {
+ clock format 738938096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1993 12:34:56 die i mensis vi annoque mcmxciii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2449140 06 vi 6 06/01/1993 die i mensis vi annoque mcmxciii 93 xciii 1993}
+test clock-2.1380 {conversion of 1993-06-30} {
+ clock format 741443696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1993 12:34:56 die xxx mensis vi annoque mcmxciii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2449169 06 vi 6 06/30/1993 die xxx mensis vi annoque mcmxciii 93 xciii 1993}
+test clock-2.1381 {conversion of 1993-07-01} {
+ clock format 741530096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1993 12:34:56 die i mensis vii annoque mcmxciii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2449170 07 vii 7 07/01/1993 die i mensis vii annoque mcmxciii 93 xciii 1993}
+test clock-2.1382 {conversion of 1993-07-31} {
+ clock format 744122096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1993 12:34:56 die xxxi mensis vii annoque mcmxciii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2449200 07 vii 7 07/31/1993 die xxxi mensis vii annoque mcmxciii 93 xciii 1993}
+test clock-2.1383 {conversion of 1993-08-01} {
+ clock format 744208496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1993 12:34:56 die i mensis viii annoque mcmxciii xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2449201 08 viii 8 08/01/1993 die i mensis viii annoque mcmxciii 93 xciii 1993}
+test clock-2.1384 {conversion of 1993-08-31} {
+ clock format 746800496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1993 12:34:56 die xxxi mensis viii annoque mcmxciii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2449231 08 viii 8 08/31/1993 die xxxi mensis viii annoque mcmxciii 93 xciii 1993}
+test clock-2.1385 {conversion of 1993-09-01} {
+ clock format 746886896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1993 12:34:56 die i mensis ix annoque mcmxciii xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2449232 09 ix 9 09/01/1993 die i mensis ix annoque mcmxciii 93 xciii 1993}
+test clock-2.1386 {conversion of 1993-09-30} {
+ clock format 749392496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1993 12:34:56 die xxx mensis ix annoque mcmxciii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2449261 09 ix 9 09/30/1993 die xxx mensis ix annoque mcmxciii 93 xciii 1993}
+test clock-2.1387 {conversion of 1993-10-01} {
+ clock format 749478896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1993 12:34:56 die i mensis x annoque mcmxciii xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2449262 10 x 10 10/01/1993 die i mensis x annoque mcmxciii 93 xciii 1993}
+test clock-2.1388 {conversion of 1993-10-31} {
+ clock format 752070896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1993 12:34:56 die xxxi mensis x annoque mcmxciii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2449292 10 x 10 10/31/1993 die xxxi mensis x annoque mcmxciii 93 xciii 1993}
+test clock-2.1389 {conversion of 1993-11-01} {
+ clock format 752157296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1993 12:34:56 die i mensis xi annoque mcmxciii xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2449293 11 xi 11 11/01/1993 die i mensis xi annoque mcmxciii 93 xciii 1993}
+test clock-2.1390 {conversion of 1993-11-30} {
+ clock format 754662896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1993 12:34:56 die xxx mensis xi annoque mcmxciii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2449322 11 xi 11 11/30/1993 die xxx mensis xi annoque mcmxciii 93 xciii 1993}
+test clock-2.1391 {conversion of 1993-12-01} {
+ clock format 754749296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1993 12:34:56 die i mensis xii annoque mcmxciii xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2449323 12 xii 12 12/01/1993 die i mensis xii annoque mcmxciii 93 xciii 1993}
+test clock-2.1392 {conversion of 1993-12-31} {
+ clock format 757341296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1993 12:34:56 die xxxi mensis xii annoque mcmxciii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2449353 12 xii 12 12/31/1993 die xxxi mensis xii annoque mcmxciii 93 xciii 1993}
+test clock-2.1393 {conversion of 1996-01-01} {
+ clock format 820499696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1996 12:34:56 die i mensis i annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2450084 01 i 1 01/01/1996 die i mensis i annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1394 {conversion of 1996-01-31} {
+ clock format 823091696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1996 12:34:56 die xxxi mensis i annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2450114 01 i 1 01/31/1996 die xxxi mensis i annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1395 {conversion of 1996-02-01} {
+ clock format 823178096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1996 12:34:56 die i mensis ii annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2450115 02 ii 2 02/01/1996 die i mensis ii annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1396 {conversion of 1996-02-29} {
+ clock format 825597296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/1996 12:34:56 die xxix mensis ii annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 29 xxix 29 xxix Feb 060 2450143 02 ii 2 02/29/1996 die xxix mensis ii annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1397 {conversion of 1996-03-01} {
+ clock format 825683696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1996 12:34:56 die i mensis iii annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 061 2450144 03 iii 3 03/01/1996 die i mensis iii annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1398 {conversion of 1996-03-31} {
+ clock format 828275696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1996 12:34:56 die xxxi mensis iii annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 091 2450174 03 iii 3 03/31/1996 die xxxi mensis iii annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1399 {conversion of 1996-04-01} {
+ clock format 828362096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1996 12:34:56 die i mensis iv annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 092 2450175 04 iv 4 04/01/1996 die i mensis iv annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1400 {conversion of 1996-04-30} {
+ clock format 830867696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1996 12:34:56 die xxx mensis iv annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 121 2450204 04 iv 4 04/30/1996 die xxx mensis iv annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1401 {conversion of 1996-05-01} {
+ clock format 830954096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1996 12:34:56 die i mensis v annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 01 i 1 i May 122 2450205 05 v 5 05/01/1996 die i mensis v annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1402 {conversion of 1996-05-31} {
+ clock format 833546096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1996 12:34:56 die xxxi mensis v annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 152 2450235 05 v 5 05/31/1996 die xxxi mensis v annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1403 {conversion of 1996-06-01} {
+ clock format 833632496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1996 12:34:56 die i mensis vi annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 153 2450236 06 vi 6 06/01/1996 die i mensis vi annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1404 {conversion of 1996-06-30} {
+ clock format 836138096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1996 12:34:56 die xxx mensis vi annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 182 2450265 06 vi 6 06/30/1996 die xxx mensis vi annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1405 {conversion of 1996-07-01} {
+ clock format 836224496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1996 12:34:56 die i mensis vii annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 183 2450266 07 vii 7 07/01/1996 die i mensis vii annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1406 {conversion of 1996-07-31} {
+ clock format 838816496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1996 12:34:56 die xxxi mensis vii annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 213 2450296 07 vii 7 07/31/1996 die xxxi mensis vii annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1407 {conversion of 1996-08-01} {
+ clock format 838902896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1996 12:34:56 die i mensis viii annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 214 2450297 08 viii 8 08/01/1996 die i mensis viii annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1408 {conversion of 1996-08-31} {
+ clock format 841494896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1996 12:34:56 die xxxi mensis viii annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 244 2450327 08 viii 8 08/31/1996 die xxxi mensis viii annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1409 {conversion of 1996-09-01} {
+ clock format 841581296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1996 12:34:56 die i mensis ix annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 245 2450328 09 ix 9 09/01/1996 die i mensis ix annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1410 {conversion of 1996-09-30} {
+ clock format 844086896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1996 12:34:56 die xxx mensis ix annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 274 2450357 09 ix 9 09/30/1996 die xxx mensis ix annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1411 {conversion of 1996-10-01} {
+ clock format 844173296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1996 12:34:56 die i mensis x annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 275 2450358 10 x 10 10/01/1996 die i mensis x annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1412 {conversion of 1996-10-31} {
+ clock format 846765296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1996 12:34:56 die xxxi mensis x annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 305 2450388 10 x 10 10/31/1996 die xxxi mensis x annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1413 {conversion of 1996-11-01} {
+ clock format 846851696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1996 12:34:56 die i mensis xi annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 306 2450389 11 xi 11 11/01/1996 die i mensis xi annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1414 {conversion of 1996-11-30} {
+ clock format 849357296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1996 12:34:56 die xxx mensis xi annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 335 2450418 11 xi 11 11/30/1996 die xxx mensis xi annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1415 {conversion of 1996-12-01} {
+ clock format 849443696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1996 12:34:56 die i mensis xii annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 336 2450419 12 xii 12 12/01/1996 die i mensis xii annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1416 {conversion of 1996-12-31} {
+ clock format 852035696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1996 12:34:56 die xxxi mensis xii annoque mcmxcvi xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 366 2450449 12 xii 12 12/31/1996 die xxxi mensis xii annoque mcmxcvi 96 xcvi 1996}
+test clock-2.1417 {conversion of 1997-01-01} {
+ clock format 852122096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/1997 12:34:56 die i mensis i annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jan 001 2450450 01 i 1 01/01/1997 die i mensis i annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1418 {conversion of 1997-01-31} {
+ clock format 854714096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/1997 12:34:56 die xxxi mensis i annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jan 031 2450480 01 i 1 01/31/1997 die xxxi mensis i annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1419 {conversion of 1997-02-01} {
+ clock format 854800496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/1997 12:34:56 die i mensis ii annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Feb 032 2450481 02 ii 2 02/01/1997 die i mensis ii annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1420 {conversion of 1997-02-28} {
+ clock format 857133296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/1997 12:34:56 die xxviii mensis ii annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 28 xxviii 28 xxviii Feb 059 2450508 02 ii 2 02/28/1997 die xxviii mensis ii annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1421 {conversion of 1997-03-01} {
+ clock format 857219696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/1997 12:34:56 die i mensis iii annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Mar 060 2450509 03 iii 3 03/01/1997 die i mensis iii annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1422 {conversion of 1997-03-31} {
+ clock format 859811696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/1997 12:34:56 die xxxi mensis iii annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Mar 090 2450539 03 iii 3 03/31/1997 die xxxi mensis iii annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1423 {conversion of 1997-04-01} {
+ clock format 859898096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/1997 12:34:56 die i mensis iv annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Apr 091 2450540 04 iv 4 04/01/1997 die i mensis iv annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1424 {conversion of 1997-04-30} {
+ clock format 862403696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/1997 12:34:56 die xxx mensis iv annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Apr 120 2450569 04 iv 4 04/30/1997 die xxx mensis iv annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1425 {conversion of 1997-05-01} {
+ clock format 862490096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/1997 12:34:56 die i mensis v annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 01 i 1 i May 121 2450570 05 v 5 05/01/1997 die i mensis v annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1426 {conversion of 1997-05-31} {
+ clock format 865082096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/1997 12:34:56 die xxxi mensis v annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi May 151 2450600 05 v 5 05/31/1997 die xxxi mensis v annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1427 {conversion of 1997-06-01} {
+ clock format 865168496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/1997 12:34:56 die i mensis vi annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jun 152 2450601 06 vi 6 06/01/1997 die i mensis vi annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1428 {conversion of 1997-06-30} {
+ clock format 867674096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/1997 12:34:56 die xxx mensis vi annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Jun 181 2450630 06 vi 6 06/30/1997 die xxx mensis vi annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1429 {conversion of 1997-07-01} {
+ clock format 867760496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/1997 12:34:56 die i mensis vii annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Jul 182 2450631 07 vii 7 07/01/1997 die i mensis vii annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1430 {conversion of 1997-07-31} {
+ clock format 870352496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/1997 12:34:56 die xxxi mensis vii annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Jul 212 2450661 07 vii 7 07/31/1997 die xxxi mensis vii annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1431 {conversion of 1997-08-01} {
+ clock format 870438896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/1997 12:34:56 die i mensis viii annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Aug 213 2450662 08 viii 8 08/01/1997 die i mensis viii annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1432 {conversion of 1997-08-31} {
+ clock format 873030896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/1997 12:34:56 die xxxi mensis viii annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Aug 243 2450692 08 viii 8 08/31/1997 die xxxi mensis viii annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1433 {conversion of 1997-09-01} {
+ clock format 873117296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/1997 12:34:56 die i mensis ix annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Sep 244 2450693 09 ix 9 09/01/1997 die i mensis ix annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1434 {conversion of 1997-09-30} {
+ clock format 875622896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/1997 12:34:56 die xxx mensis ix annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Sep 273 2450722 09 ix 9 09/30/1997 die xxx mensis ix annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1435 {conversion of 1997-10-01} {
+ clock format 875709296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/1997 12:34:56 die i mensis x annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Oct 274 2450723 10 x 10 10/01/1997 die i mensis x annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1436 {conversion of 1997-10-31} {
+ clock format 878301296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/1997 12:34:56 die xxxi mensis x annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Oct 304 2450753 10 x 10 10/31/1997 die xxxi mensis x annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1437 {conversion of 1997-11-01} {
+ clock format 878387696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/1997 12:34:56 die i mensis xi annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Nov 305 2450754 11 xi 11 11/01/1997 die i mensis xi annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1438 {conversion of 1997-11-30} {
+ clock format 880893296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/1997 12:34:56 die xxx mensis xi annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 30 xxx 30 xxx Nov 334 2450783 11 xi 11 11/30/1997 die xxx mensis xi annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1439 {conversion of 1997-12-01} {
+ clock format 880979696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/1997 12:34:56 die i mensis xii annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 01 i 1 i Dec 335 2450784 12 xii 12 12/01/1997 die i mensis xii annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1440 {conversion of 1997-12-31} {
+ clock format 883571696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/1997 12:34:56 die xxxi mensis xii annoque mcmxcvii xii h xxxiv m lvi s 19 mcm 31 xxxi 31 xxxi Dec 365 2450814 12 xii 12 12/31/1997 die xxxi mensis xii annoque mcmxcvii 97 xcvii 1997}
+test clock-2.1441 {conversion of 2000-01-01} {
+ clock format 946730096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2000 12:34:56 die i mensis i annoque mm? xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2451545 01 i 1 01/01/2000 die i mensis i annoque mm? 00 ? 2000}
+test clock-2.1442 {conversion of 2000-01-31} {
+ clock format 949322096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2000 12:34:56 die xxxi mensis i annoque mm? xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2451575 01 i 1 01/31/2000 die xxxi mensis i annoque mm? 00 ? 2000}
+test clock-2.1443 {conversion of 2000-02-01} {
+ clock format 949408496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2000 12:34:56 die i mensis ii annoque mm? xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2451576 02 ii 2 02/01/2000 die i mensis ii annoque mm? 00 ? 2000}
+test clock-2.1444 {conversion of 2000-02-29} {
+ clock format 951827696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/2000 12:34:56 die xxix mensis ii annoque mm? xii h xxxiv m lvi s 20 mm 29 xxix 29 xxix Feb 060 2451604 02 ii 2 02/29/2000 die xxix mensis ii annoque mm? 00 ? 2000}
+test clock-2.1445 {conversion of 2000-03-01} {
+ clock format 951914096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2000 12:34:56 die i mensis iii annoque mm? xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 061 2451605 03 iii 3 03/01/2000 die i mensis iii annoque mm? 00 ? 2000}
+test clock-2.1446 {conversion of 2000-03-31} {
+ clock format 954506096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2000 12:34:56 die xxxi mensis iii annoque mm? xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 091 2451635 03 iii 3 03/31/2000 die xxxi mensis iii annoque mm? 00 ? 2000}
+test clock-2.1447 {conversion of 2000-04-01} {
+ clock format 954592496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2000 12:34:56 die i mensis iv annoque mm? xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 092 2451636 04 iv 4 04/01/2000 die i mensis iv annoque mm? 00 ? 2000}
+test clock-2.1448 {conversion of 2000-04-30} {
+ clock format 957098096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2000 12:34:56 die xxx mensis iv annoque mm? xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 121 2451665 04 iv 4 04/30/2000 die xxx mensis iv annoque mm? 00 ? 2000}
+test clock-2.1449 {conversion of 2000-05-01} {
+ clock format 957184496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2000 12:34:56 die i mensis v annoque mm? xii h xxxiv m lvi s 20 mm 01 i 1 i May 122 2451666 05 v 5 05/01/2000 die i mensis v annoque mm? 00 ? 2000}
+test clock-2.1450 {conversion of 2000-05-31} {
+ clock format 959776496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2000 12:34:56 die xxxi mensis v annoque mm? xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 152 2451696 05 v 5 05/31/2000 die xxxi mensis v annoque mm? 00 ? 2000}
+test clock-2.1451 {conversion of 2000-06-01} {
+ clock format 959862896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2000 12:34:56 die i mensis vi annoque mm? xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 153 2451697 06 vi 6 06/01/2000 die i mensis vi annoque mm? 00 ? 2000}
+test clock-2.1452 {conversion of 2000-06-30} {
+ clock format 962368496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2000 12:34:56 die xxx mensis vi annoque mm? xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 182 2451726 06 vi 6 06/30/2000 die xxx mensis vi annoque mm? 00 ? 2000}
+test clock-2.1453 {conversion of 2000-07-01} {
+ clock format 962454896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2000 12:34:56 die i mensis vii annoque mm? xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 183 2451727 07 vii 7 07/01/2000 die i mensis vii annoque mm? 00 ? 2000}
+test clock-2.1454 {conversion of 2000-07-31} {
+ clock format 965046896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2000 12:34:56 die xxxi mensis vii annoque mm? xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 213 2451757 07 vii 7 07/31/2000 die xxxi mensis vii annoque mm? 00 ? 2000}
+test clock-2.1455 {conversion of 2000-08-01} {
+ clock format 965133296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2000 12:34:56 die i mensis viii annoque mm? xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 214 2451758 08 viii 8 08/01/2000 die i mensis viii annoque mm? 00 ? 2000}
+test clock-2.1456 {conversion of 2000-08-31} {
+ clock format 967725296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2000 12:34:56 die xxxi mensis viii annoque mm? xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 244 2451788 08 viii 8 08/31/2000 die xxxi mensis viii annoque mm? 00 ? 2000}
+test clock-2.1457 {conversion of 2000-09-01} {
+ clock format 967811696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2000 12:34:56 die i mensis ix annoque mm? xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 245 2451789 09 ix 9 09/01/2000 die i mensis ix annoque mm? 00 ? 2000}
+test clock-2.1458 {conversion of 2000-09-30} {
+ clock format 970317296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2000 12:34:56 die xxx mensis ix annoque mm? xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 274 2451818 09 ix 9 09/30/2000 die xxx mensis ix annoque mm? 00 ? 2000}
+test clock-2.1459 {conversion of 2000-10-01} {
+ clock format 970403696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2000 12:34:56 die i mensis x annoque mm? xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 275 2451819 10 x 10 10/01/2000 die i mensis x annoque mm? 00 ? 2000}
+test clock-2.1460 {conversion of 2000-10-31} {
+ clock format 972995696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2000 12:34:56 die xxxi mensis x annoque mm? xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 305 2451849 10 x 10 10/31/2000 die xxxi mensis x annoque mm? 00 ? 2000}
+test clock-2.1461 {conversion of 2000-11-01} {
+ clock format 973082096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2000 12:34:56 die i mensis xi annoque mm? xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 306 2451850 11 xi 11 11/01/2000 die i mensis xi annoque mm? 00 ? 2000}
+test clock-2.1462 {conversion of 2000-11-30} {
+ clock format 975587696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2000 12:34:56 die xxx mensis xi annoque mm? xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 335 2451879 11 xi 11 11/30/2000 die xxx mensis xi annoque mm? 00 ? 2000}
+test clock-2.1463 {conversion of 2000-12-01} {
+ clock format 975674096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2000 12:34:56 die i mensis xii annoque mm? xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 336 2451880 12 xii 12 12/01/2000 die i mensis xii annoque mm? 00 ? 2000}
+test clock-2.1464 {conversion of 2000-12-31} {
+ clock format 978266096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2000 12:34:56 die xxxi mensis xii annoque mm? xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 366 2451910 12 xii 12 12/31/2000 die xxxi mensis xii annoque mm? 00 ? 2000}
+test clock-2.1465 {conversion of 2001-01-01} {
+ clock format 978352496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2001 12:34:56 die i mensis i annoque mmi xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2451911 01 i 1 01/01/2001 die i mensis i annoque mmi 01 i 2001}
+test clock-2.1466 {conversion of 2001-01-31} {
+ clock format 980944496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2001 12:34:56 die xxxi mensis i annoque mmi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2451941 01 i 1 01/31/2001 die xxxi mensis i annoque mmi 01 i 2001}
+test clock-2.1467 {conversion of 2001-02-01} {
+ clock format 981030896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2001 12:34:56 die i mensis ii annoque mmi xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2451942 02 ii 2 02/01/2001 die i mensis ii annoque mmi 01 i 2001}
+test clock-2.1468 {conversion of 2001-02-28} {
+ clock format 983363696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2001 12:34:56 die xxviii mensis ii annoque mmi xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2451969 02 ii 2 02/28/2001 die xxviii mensis ii annoque mmi 01 i 2001}
+test clock-2.1469 {conversion of 2001-03-01} {
+ clock format 983450096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2001 12:34:56 die i mensis iii annoque mmi xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2451970 03 iii 3 03/01/2001 die i mensis iii annoque mmi 01 i 2001}
+test clock-2.1470 {conversion of 2001-03-31} {
+ clock format 986042096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2001 12:34:56 die xxxi mensis iii annoque mmi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2452000 03 iii 3 03/31/2001 die xxxi mensis iii annoque mmi 01 i 2001}
+test clock-2.1471 {conversion of 2001-04-01} {
+ clock format 986128496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2001 12:34:56 die i mensis iv annoque mmi xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2452001 04 iv 4 04/01/2001 die i mensis iv annoque mmi 01 i 2001}
+test clock-2.1472 {conversion of 2001-04-30} {
+ clock format 988634096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2001 12:34:56 die xxx mensis iv annoque mmi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2452030 04 iv 4 04/30/2001 die xxx mensis iv annoque mmi 01 i 2001}
+test clock-2.1473 {conversion of 2001-05-01} {
+ clock format 988720496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2001 12:34:56 die i mensis v annoque mmi xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2452031 05 v 5 05/01/2001 die i mensis v annoque mmi 01 i 2001}
+test clock-2.1474 {conversion of 2001-05-31} {
+ clock format 991312496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2001 12:34:56 die xxxi mensis v annoque mmi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2452061 05 v 5 05/31/2001 die xxxi mensis v annoque mmi 01 i 2001}
+test clock-2.1475 {conversion of 2001-06-01} {
+ clock format 991398896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2001 12:34:56 die i mensis vi annoque mmi xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2452062 06 vi 6 06/01/2001 die i mensis vi annoque mmi 01 i 2001}
+test clock-2.1476 {conversion of 2001-06-30} {
+ clock format 993904496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2001 12:34:56 die xxx mensis vi annoque mmi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2452091 06 vi 6 06/30/2001 die xxx mensis vi annoque mmi 01 i 2001}
+test clock-2.1477 {conversion of 2001-07-01} {
+ clock format 993990896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2001 12:34:56 die i mensis vii annoque mmi xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2452092 07 vii 7 07/01/2001 die i mensis vii annoque mmi 01 i 2001}
+test clock-2.1478 {conversion of 2001-07-31} {
+ clock format 996582896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2001 12:34:56 die xxxi mensis vii annoque mmi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2452122 07 vii 7 07/31/2001 die xxxi mensis vii annoque mmi 01 i 2001}
+test clock-2.1479 {conversion of 2001-08-01} {
+ clock format 996669296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2001 12:34:56 die i mensis viii annoque mmi xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2452123 08 viii 8 08/01/2001 die i mensis viii annoque mmi 01 i 2001}
+test clock-2.1480 {conversion of 2001-08-31} {
+ clock format 999261296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2001 12:34:56 die xxxi mensis viii annoque mmi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2452153 08 viii 8 08/31/2001 die xxxi mensis viii annoque mmi 01 i 2001}
+test clock-2.1481 {conversion of 2001-09-01} {
+ clock format 999347696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2001 12:34:56 die i mensis ix annoque mmi xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2452154 09 ix 9 09/01/2001 die i mensis ix annoque mmi 01 i 2001}
+test clock-2.1482 {conversion of 2001-09-30} {
+ clock format 1001853296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2001 12:34:56 die xxx mensis ix annoque mmi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2452183 09 ix 9 09/30/2001 die xxx mensis ix annoque mmi 01 i 2001}
+test clock-2.1483 {conversion of 2001-10-01} {
+ clock format 1001939696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2001 12:34:56 die i mensis x annoque mmi xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2452184 10 x 10 10/01/2001 die i mensis x annoque mmi 01 i 2001}
+test clock-2.1484 {conversion of 2001-10-31} {
+ clock format 1004531696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2001 12:34:56 die xxxi mensis x annoque mmi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2452214 10 x 10 10/31/2001 die xxxi mensis x annoque mmi 01 i 2001}
+test clock-2.1485 {conversion of 2001-11-01} {
+ clock format 1004618096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2001 12:34:56 die i mensis xi annoque mmi xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2452215 11 xi 11 11/01/2001 die i mensis xi annoque mmi 01 i 2001}
+test clock-2.1486 {conversion of 2001-11-30} {
+ clock format 1007123696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2001 12:34:56 die xxx mensis xi annoque mmi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2452244 11 xi 11 11/30/2001 die xxx mensis xi annoque mmi 01 i 2001}
+test clock-2.1487 {conversion of 2001-12-01} {
+ clock format 1007210096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2001 12:34:56 die i mensis xii annoque mmi xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2452245 12 xii 12 12/01/2001 die i mensis xii annoque mmi 01 i 2001}
+test clock-2.1488 {conversion of 2001-12-31} {
+ clock format 1009802096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2001 12:34:56 die xxxi mensis xii annoque mmi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2452275 12 xii 12 12/31/2001 die xxxi mensis xii annoque mmi 01 i 2001}
+test clock-2.1489 {conversion of 2002-01-01} {
+ clock format 1009888496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2002 12:34:56 die i mensis i annoque mmii xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2452276 01 i 1 01/01/2002 die i mensis i annoque mmii 02 ii 2002}
+test clock-2.1490 {conversion of 2002-01-31} {
+ clock format 1012480496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2002 12:34:56 die xxxi mensis i annoque mmii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2452306 01 i 1 01/31/2002 die xxxi mensis i annoque mmii 02 ii 2002}
+test clock-2.1491 {conversion of 2002-02-01} {
+ clock format 1012566896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2002 12:34:56 die i mensis ii annoque mmii xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2452307 02 ii 2 02/01/2002 die i mensis ii annoque mmii 02 ii 2002}
+test clock-2.1492 {conversion of 2002-02-28} {
+ clock format 1014899696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2002 12:34:56 die xxviii mensis ii annoque mmii xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2452334 02 ii 2 02/28/2002 die xxviii mensis ii annoque mmii 02 ii 2002}
+test clock-2.1493 {conversion of 2002-03-01} {
+ clock format 1014986096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2002 12:34:56 die i mensis iii annoque mmii xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2452335 03 iii 3 03/01/2002 die i mensis iii annoque mmii 02 ii 2002}
+test clock-2.1494 {conversion of 2002-03-31} {
+ clock format 1017578096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2002 12:34:56 die xxxi mensis iii annoque mmii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2452365 03 iii 3 03/31/2002 die xxxi mensis iii annoque mmii 02 ii 2002}
+test clock-2.1495 {conversion of 2002-04-01} {
+ clock format 1017664496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2002 12:34:56 die i mensis iv annoque mmii xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2452366 04 iv 4 04/01/2002 die i mensis iv annoque mmii 02 ii 2002}
+test clock-2.1496 {conversion of 2002-04-30} {
+ clock format 1020170096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2002 12:34:56 die xxx mensis iv annoque mmii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2452395 04 iv 4 04/30/2002 die xxx mensis iv annoque mmii 02 ii 2002}
+test clock-2.1497 {conversion of 2002-05-01} {
+ clock format 1020256496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2002 12:34:56 die i mensis v annoque mmii xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2452396 05 v 5 05/01/2002 die i mensis v annoque mmii 02 ii 2002}
+test clock-2.1498 {conversion of 2002-05-31} {
+ clock format 1022848496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2002 12:34:56 die xxxi mensis v annoque mmii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2452426 05 v 5 05/31/2002 die xxxi mensis v annoque mmii 02 ii 2002}
+test clock-2.1499 {conversion of 2002-06-01} {
+ clock format 1022934896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2002 12:34:56 die i mensis vi annoque mmii xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2452427 06 vi 6 06/01/2002 die i mensis vi annoque mmii 02 ii 2002}
+test clock-2.1500 {conversion of 2002-06-30} {
+ clock format 1025440496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2002 12:34:56 die xxx mensis vi annoque mmii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2452456 06 vi 6 06/30/2002 die xxx mensis vi annoque mmii 02 ii 2002}
+test clock-2.1501 {conversion of 2002-07-01} {
+ clock format 1025526896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2002 12:34:56 die i mensis vii annoque mmii xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2452457 07 vii 7 07/01/2002 die i mensis vii annoque mmii 02 ii 2002}
+test clock-2.1502 {conversion of 2002-07-31} {
+ clock format 1028118896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2002 12:34:56 die xxxi mensis vii annoque mmii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2452487 07 vii 7 07/31/2002 die xxxi mensis vii annoque mmii 02 ii 2002}
+test clock-2.1503 {conversion of 2002-08-01} {
+ clock format 1028205296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2002 12:34:56 die i mensis viii annoque mmii xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2452488 08 viii 8 08/01/2002 die i mensis viii annoque mmii 02 ii 2002}
+test clock-2.1504 {conversion of 2002-08-31} {
+ clock format 1030797296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2002 12:34:56 die xxxi mensis viii annoque mmii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2452518 08 viii 8 08/31/2002 die xxxi mensis viii annoque mmii 02 ii 2002}
+test clock-2.1505 {conversion of 2002-09-01} {
+ clock format 1030883696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2002 12:34:56 die i mensis ix annoque mmii xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2452519 09 ix 9 09/01/2002 die i mensis ix annoque mmii 02 ii 2002}
+test clock-2.1506 {conversion of 2002-09-30} {
+ clock format 1033389296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2002 12:34:56 die xxx mensis ix annoque mmii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2452548 09 ix 9 09/30/2002 die xxx mensis ix annoque mmii 02 ii 2002}
+test clock-2.1507 {conversion of 2002-10-01} {
+ clock format 1033475696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2002 12:34:56 die i mensis x annoque mmii xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2452549 10 x 10 10/01/2002 die i mensis x annoque mmii 02 ii 2002}
+test clock-2.1508 {conversion of 2002-10-31} {
+ clock format 1036067696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2002 12:34:56 die xxxi mensis x annoque mmii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2452579 10 x 10 10/31/2002 die xxxi mensis x annoque mmii 02 ii 2002}
+test clock-2.1509 {conversion of 2002-11-01} {
+ clock format 1036154096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2002 12:34:56 die i mensis xi annoque mmii xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2452580 11 xi 11 11/01/2002 die i mensis xi annoque mmii 02 ii 2002}
+test clock-2.1510 {conversion of 2002-11-30} {
+ clock format 1038659696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2002 12:34:56 die xxx mensis xi annoque mmii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2452609 11 xi 11 11/30/2002 die xxx mensis xi annoque mmii 02 ii 2002}
+test clock-2.1511 {conversion of 2002-12-01} {
+ clock format 1038746096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2002 12:34:56 die i mensis xii annoque mmii xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2452610 12 xii 12 12/01/2002 die i mensis xii annoque mmii 02 ii 2002}
+test clock-2.1512 {conversion of 2002-12-31} {
+ clock format 1041338096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2002 12:34:56 die xxxi mensis xii annoque mmii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2452640 12 xii 12 12/31/2002 die xxxi mensis xii annoque mmii 02 ii 2002}
+test clock-2.1513 {conversion of 2003-01-01} {
+ clock format 1041424496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2003 12:34:56 die i mensis i annoque mmiii xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2452641 01 i 1 01/01/2003 die i mensis i annoque mmiii 03 iii 2003}
+test clock-2.1514 {conversion of 2003-01-31} {
+ clock format 1044016496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2003 12:34:56 die xxxi mensis i annoque mmiii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2452671 01 i 1 01/31/2003 die xxxi mensis i annoque mmiii 03 iii 2003}
+test clock-2.1515 {conversion of 2003-02-01} {
+ clock format 1044102896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2003 12:34:56 die i mensis ii annoque mmiii xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2452672 02 ii 2 02/01/2003 die i mensis ii annoque mmiii 03 iii 2003}
+test clock-2.1516 {conversion of 2003-02-28} {
+ clock format 1046435696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2003 12:34:56 die xxviii mensis ii annoque mmiii xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2452699 02 ii 2 02/28/2003 die xxviii mensis ii annoque mmiii 03 iii 2003}
+test clock-2.1517 {conversion of 2003-03-01} {
+ clock format 1046522096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2003 12:34:56 die i mensis iii annoque mmiii xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2452700 03 iii 3 03/01/2003 die i mensis iii annoque mmiii 03 iii 2003}
+test clock-2.1518 {conversion of 2003-03-31} {
+ clock format 1049114096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2003 12:34:56 die xxxi mensis iii annoque mmiii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2452730 03 iii 3 03/31/2003 die xxxi mensis iii annoque mmiii 03 iii 2003}
+test clock-2.1519 {conversion of 2003-04-01} {
+ clock format 1049200496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2003 12:34:56 die i mensis iv annoque mmiii xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2452731 04 iv 4 04/01/2003 die i mensis iv annoque mmiii 03 iii 2003}
+test clock-2.1520 {conversion of 2003-04-30} {
+ clock format 1051706096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2003 12:34:56 die xxx mensis iv annoque mmiii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2452760 04 iv 4 04/30/2003 die xxx mensis iv annoque mmiii 03 iii 2003}
+test clock-2.1521 {conversion of 2003-05-01} {
+ clock format 1051792496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2003 12:34:56 die i mensis v annoque mmiii xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2452761 05 v 5 05/01/2003 die i mensis v annoque mmiii 03 iii 2003}
+test clock-2.1522 {conversion of 2003-05-31} {
+ clock format 1054384496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2003 12:34:56 die xxxi mensis v annoque mmiii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2452791 05 v 5 05/31/2003 die xxxi mensis v annoque mmiii 03 iii 2003}
+test clock-2.1523 {conversion of 2003-06-01} {
+ clock format 1054470896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2003 12:34:56 die i mensis vi annoque mmiii xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2452792 06 vi 6 06/01/2003 die i mensis vi annoque mmiii 03 iii 2003}
+test clock-2.1524 {conversion of 2003-06-30} {
+ clock format 1056976496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2003 12:34:56 die xxx mensis vi annoque mmiii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2452821 06 vi 6 06/30/2003 die xxx mensis vi annoque mmiii 03 iii 2003}
+test clock-2.1525 {conversion of 2003-07-01} {
+ clock format 1057062896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2003 12:34:56 die i mensis vii annoque mmiii xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2452822 07 vii 7 07/01/2003 die i mensis vii annoque mmiii 03 iii 2003}
+test clock-2.1526 {conversion of 2003-07-31} {
+ clock format 1059654896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2003 12:34:56 die xxxi mensis vii annoque mmiii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2452852 07 vii 7 07/31/2003 die xxxi mensis vii annoque mmiii 03 iii 2003}
+test clock-2.1527 {conversion of 2003-08-01} {
+ clock format 1059741296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2003 12:34:56 die i mensis viii annoque mmiii xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2452853 08 viii 8 08/01/2003 die i mensis viii annoque mmiii 03 iii 2003}
+test clock-2.1528 {conversion of 2003-08-31} {
+ clock format 1062333296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2003 12:34:56 die xxxi mensis viii annoque mmiii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2452883 08 viii 8 08/31/2003 die xxxi mensis viii annoque mmiii 03 iii 2003}
+test clock-2.1529 {conversion of 2003-09-01} {
+ clock format 1062419696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2003 12:34:56 die i mensis ix annoque mmiii xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2452884 09 ix 9 09/01/2003 die i mensis ix annoque mmiii 03 iii 2003}
+test clock-2.1530 {conversion of 2003-09-30} {
+ clock format 1064925296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2003 12:34:56 die xxx mensis ix annoque mmiii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2452913 09 ix 9 09/30/2003 die xxx mensis ix annoque mmiii 03 iii 2003}
+test clock-2.1531 {conversion of 2003-10-01} {
+ clock format 1065011696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2003 12:34:56 die i mensis x annoque mmiii xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2452914 10 x 10 10/01/2003 die i mensis x annoque mmiii 03 iii 2003}
+test clock-2.1532 {conversion of 2003-10-31} {
+ clock format 1067603696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2003 12:34:56 die xxxi mensis x annoque mmiii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2452944 10 x 10 10/31/2003 die xxxi mensis x annoque mmiii 03 iii 2003}
+test clock-2.1533 {conversion of 2003-11-01} {
+ clock format 1067690096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2003 12:34:56 die i mensis xi annoque mmiii xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2452945 11 xi 11 11/01/2003 die i mensis xi annoque mmiii 03 iii 2003}
+test clock-2.1534 {conversion of 2003-11-30} {
+ clock format 1070195696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2003 12:34:56 die xxx mensis xi annoque mmiii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2452974 11 xi 11 11/30/2003 die xxx mensis xi annoque mmiii 03 iii 2003}
+test clock-2.1535 {conversion of 2003-12-01} {
+ clock format 1070282096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2003 12:34:56 die i mensis xii annoque mmiii xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2452975 12 xii 12 12/01/2003 die i mensis xii annoque mmiii 03 iii 2003}
+test clock-2.1536 {conversion of 2003-12-31} {
+ clock format 1072874096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2003 12:34:56 die xxxi mensis xii annoque mmiii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2453005 12 xii 12 12/31/2003 die xxxi mensis xii annoque mmiii 03 iii 2003}
+test clock-2.1537 {conversion of 2004-01-01} {
+ clock format 1072960496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2004 12:34:56 die i mensis i annoque mmiv xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2453006 01 i 1 01/01/2004 die i mensis i annoque mmiv 04 iv 2004}
+test clock-2.1538 {conversion of 2004-01-31} {
+ clock format 1075552496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2004 12:34:56 die xxxi mensis i annoque mmiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2453036 01 i 1 01/31/2004 die xxxi mensis i annoque mmiv 04 iv 2004}
+test clock-2.1539 {conversion of 2004-02-01} {
+ clock format 1075638896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2004 12:34:56 die i mensis ii annoque mmiv xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2453037 02 ii 2 02/01/2004 die i mensis ii annoque mmiv 04 iv 2004}
+test clock-2.1540 {conversion of 2004-02-29} {
+ clock format 1078058096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/2004 12:34:56 die xxix mensis ii annoque mmiv xii h xxxiv m lvi s 20 mm 29 xxix 29 xxix Feb 060 2453065 02 ii 2 02/29/2004 die xxix mensis ii annoque mmiv 04 iv 2004}
+test clock-2.1541 {conversion of 2004-03-01} {
+ clock format 1078144496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2004 12:34:56 die i mensis iii annoque mmiv xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 061 2453066 03 iii 3 03/01/2004 die i mensis iii annoque mmiv 04 iv 2004}
+test clock-2.1542 {conversion of 2004-03-31} {
+ clock format 1080736496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2004 12:34:56 die xxxi mensis iii annoque mmiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 091 2453096 03 iii 3 03/31/2004 die xxxi mensis iii annoque mmiv 04 iv 2004}
+test clock-2.1543 {conversion of 2004-04-01} {
+ clock format 1080822896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2004 12:34:56 die i mensis iv annoque mmiv xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 092 2453097 04 iv 4 04/01/2004 die i mensis iv annoque mmiv 04 iv 2004}
+test clock-2.1544 {conversion of 2004-04-30} {
+ clock format 1083328496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2004 12:34:56 die xxx mensis iv annoque mmiv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 121 2453126 04 iv 4 04/30/2004 die xxx mensis iv annoque mmiv 04 iv 2004}
+test clock-2.1545 {conversion of 2004-05-01} {
+ clock format 1083414896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2004 12:34:56 die i mensis v annoque mmiv xii h xxxiv m lvi s 20 mm 01 i 1 i May 122 2453127 05 v 5 05/01/2004 die i mensis v annoque mmiv 04 iv 2004}
+test clock-2.1546 {conversion of 2004-05-31} {
+ clock format 1086006896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2004 12:34:56 die xxxi mensis v annoque mmiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 152 2453157 05 v 5 05/31/2004 die xxxi mensis v annoque mmiv 04 iv 2004}
+test clock-2.1547 {conversion of 2004-06-01} {
+ clock format 1086093296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2004 12:34:56 die i mensis vi annoque mmiv xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 153 2453158 06 vi 6 06/01/2004 die i mensis vi annoque mmiv 04 iv 2004}
+test clock-2.1548 {conversion of 2004-06-30} {
+ clock format 1088598896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2004 12:34:56 die xxx mensis vi annoque mmiv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 182 2453187 06 vi 6 06/30/2004 die xxx mensis vi annoque mmiv 04 iv 2004}
+test clock-2.1549 {conversion of 2004-07-01} {
+ clock format 1088685296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2004 12:34:56 die i mensis vii annoque mmiv xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 183 2453188 07 vii 7 07/01/2004 die i mensis vii annoque mmiv 04 iv 2004}
+test clock-2.1550 {conversion of 2004-07-31} {
+ clock format 1091277296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2004 12:34:56 die xxxi mensis vii annoque mmiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 213 2453218 07 vii 7 07/31/2004 die xxxi mensis vii annoque mmiv 04 iv 2004}
+test clock-2.1551 {conversion of 2004-08-01} {
+ clock format 1091363696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2004 12:34:56 die i mensis viii annoque mmiv xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 214 2453219 08 viii 8 08/01/2004 die i mensis viii annoque mmiv 04 iv 2004}
+test clock-2.1552 {conversion of 2004-08-31} {
+ clock format 1093955696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2004 12:34:56 die xxxi mensis viii annoque mmiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 244 2453249 08 viii 8 08/31/2004 die xxxi mensis viii annoque mmiv 04 iv 2004}
+test clock-2.1553 {conversion of 2004-09-01} {
+ clock format 1094042096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2004 12:34:56 die i mensis ix annoque mmiv xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 245 2453250 09 ix 9 09/01/2004 die i mensis ix annoque mmiv 04 iv 2004}
+test clock-2.1554 {conversion of 2004-09-30} {
+ clock format 1096547696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2004 12:34:56 die xxx mensis ix annoque mmiv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 274 2453279 09 ix 9 09/30/2004 die xxx mensis ix annoque mmiv 04 iv 2004}
+test clock-2.1555 {conversion of 2004-10-01} {
+ clock format 1096634096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2004 12:34:56 die i mensis x annoque mmiv xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 275 2453280 10 x 10 10/01/2004 die i mensis x annoque mmiv 04 iv 2004}
+test clock-2.1556 {conversion of 2004-10-31} {
+ clock format 1099226096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2004 12:34:56 die xxxi mensis x annoque mmiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 305 2453310 10 x 10 10/31/2004 die xxxi mensis x annoque mmiv 04 iv 2004}
+test clock-2.1557 {conversion of 2004-11-01} {
+ clock format 1099312496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2004 12:34:56 die i mensis xi annoque mmiv xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 306 2453311 11 xi 11 11/01/2004 die i mensis xi annoque mmiv 04 iv 2004}
+test clock-2.1558 {conversion of 2004-11-30} {
+ clock format 1101818096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2004 12:34:56 die xxx mensis xi annoque mmiv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 335 2453340 11 xi 11 11/30/2004 die xxx mensis xi annoque mmiv 04 iv 2004}
+test clock-2.1559 {conversion of 2004-12-01} {
+ clock format 1101904496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2004 12:34:56 die i mensis xii annoque mmiv xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 336 2453341 12 xii 12 12/01/2004 die i mensis xii annoque mmiv 04 iv 2004}
+test clock-2.1560 {conversion of 2004-12-31} {
+ clock format 1104496496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2004 12:34:56 die xxxi mensis xii annoque mmiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 366 2453371 12 xii 12 12/31/2004 die xxxi mensis xii annoque mmiv 04 iv 2004}
+test clock-2.1561 {conversion of 2005-01-01} {
+ clock format 1104582896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2005 12:34:56 die i mensis i annoque mmv xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2453372 01 i 1 01/01/2005 die i mensis i annoque mmv 05 v 2005}
+test clock-2.1562 {conversion of 2005-01-31} {
+ clock format 1107174896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2005 12:34:56 die xxxi mensis i annoque mmv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2453402 01 i 1 01/31/2005 die xxxi mensis i annoque mmv 05 v 2005}
+test clock-2.1563 {conversion of 2005-02-01} {
+ clock format 1107261296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2005 12:34:56 die i mensis ii annoque mmv xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2453403 02 ii 2 02/01/2005 die i mensis ii annoque mmv 05 v 2005}
+test clock-2.1564 {conversion of 2005-02-28} {
+ clock format 1109594096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2005 12:34:56 die xxviii mensis ii annoque mmv xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2453430 02 ii 2 02/28/2005 die xxviii mensis ii annoque mmv 05 v 2005}
+test clock-2.1565 {conversion of 2005-03-01} {
+ clock format 1109680496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2005 12:34:56 die i mensis iii annoque mmv xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2453431 03 iii 3 03/01/2005 die i mensis iii annoque mmv 05 v 2005}
+test clock-2.1566 {conversion of 2005-03-31} {
+ clock format 1112272496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2005 12:34:56 die xxxi mensis iii annoque mmv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2453461 03 iii 3 03/31/2005 die xxxi mensis iii annoque mmv 05 v 2005}
+test clock-2.1567 {conversion of 2005-04-01} {
+ clock format 1112358896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2005 12:34:56 die i mensis iv annoque mmv xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2453462 04 iv 4 04/01/2005 die i mensis iv annoque mmv 05 v 2005}
+test clock-2.1568 {conversion of 2005-04-30} {
+ clock format 1114864496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2005 12:34:56 die xxx mensis iv annoque mmv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2453491 04 iv 4 04/30/2005 die xxx mensis iv annoque mmv 05 v 2005}
+test clock-2.1569 {conversion of 2005-05-01} {
+ clock format 1114950896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2005 12:34:56 die i mensis v annoque mmv xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2453492 05 v 5 05/01/2005 die i mensis v annoque mmv 05 v 2005}
+test clock-2.1570 {conversion of 2005-05-31} {
+ clock format 1117542896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2005 12:34:56 die xxxi mensis v annoque mmv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2453522 05 v 5 05/31/2005 die xxxi mensis v annoque mmv 05 v 2005}
+test clock-2.1571 {conversion of 2005-06-01} {
+ clock format 1117629296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2005 12:34:56 die i mensis vi annoque mmv xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2453523 06 vi 6 06/01/2005 die i mensis vi annoque mmv 05 v 2005}
+test clock-2.1572 {conversion of 2005-06-30} {
+ clock format 1120134896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2005 12:34:56 die xxx mensis vi annoque mmv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2453552 06 vi 6 06/30/2005 die xxx mensis vi annoque mmv 05 v 2005}
+test clock-2.1573 {conversion of 2005-07-01} {
+ clock format 1120221296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2005 12:34:56 die i mensis vii annoque mmv xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2453553 07 vii 7 07/01/2005 die i mensis vii annoque mmv 05 v 2005}
+test clock-2.1574 {conversion of 2005-07-31} {
+ clock format 1122813296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2005 12:34:56 die xxxi mensis vii annoque mmv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2453583 07 vii 7 07/31/2005 die xxxi mensis vii annoque mmv 05 v 2005}
+test clock-2.1575 {conversion of 2005-08-01} {
+ clock format 1122899696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2005 12:34:56 die i mensis viii annoque mmv xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2453584 08 viii 8 08/01/2005 die i mensis viii annoque mmv 05 v 2005}
+test clock-2.1576 {conversion of 2005-08-31} {
+ clock format 1125491696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2005 12:34:56 die xxxi mensis viii annoque mmv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2453614 08 viii 8 08/31/2005 die xxxi mensis viii annoque mmv 05 v 2005}
+test clock-2.1577 {conversion of 2005-09-01} {
+ clock format 1125578096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2005 12:34:56 die i mensis ix annoque mmv xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2453615 09 ix 9 09/01/2005 die i mensis ix annoque mmv 05 v 2005}
+test clock-2.1578 {conversion of 2005-09-30} {
+ clock format 1128083696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2005 12:34:56 die xxx mensis ix annoque mmv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2453644 09 ix 9 09/30/2005 die xxx mensis ix annoque mmv 05 v 2005}
+test clock-2.1579 {conversion of 2005-10-01} {
+ clock format 1128170096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2005 12:34:56 die i mensis x annoque mmv xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2453645 10 x 10 10/01/2005 die i mensis x annoque mmv 05 v 2005}
+test clock-2.1580 {conversion of 2005-10-31} {
+ clock format 1130762096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2005 12:34:56 die xxxi mensis x annoque mmv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2453675 10 x 10 10/31/2005 die xxxi mensis x annoque mmv 05 v 2005}
+test clock-2.1581 {conversion of 2005-11-01} {
+ clock format 1130848496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2005 12:34:56 die i mensis xi annoque mmv xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2453676 11 xi 11 11/01/2005 die i mensis xi annoque mmv 05 v 2005}
+test clock-2.1582 {conversion of 2005-11-30} {
+ clock format 1133354096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2005 12:34:56 die xxx mensis xi annoque mmv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2453705 11 xi 11 11/30/2005 die xxx mensis xi annoque mmv 05 v 2005}
+test clock-2.1583 {conversion of 2005-12-01} {
+ clock format 1133440496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2005 12:34:56 die i mensis xii annoque mmv xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2453706 12 xii 12 12/01/2005 die i mensis xii annoque mmv 05 v 2005}
+test clock-2.1584 {conversion of 2005-12-31} {
+ clock format 1136032496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2005 12:34:56 die xxxi mensis xii annoque mmv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2453736 12 xii 12 12/31/2005 die xxxi mensis xii annoque mmv 05 v 2005}
+test clock-2.1585 {conversion of 2006-01-01} {
+ clock format 1136118896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2006 12:34:56 die i mensis i annoque mmvi xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2453737 01 i 1 01/01/2006 die i mensis i annoque mmvi 06 vi 2006}
+test clock-2.1586 {conversion of 2006-01-31} {
+ clock format 1138710896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2006 12:34:56 die xxxi mensis i annoque mmvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2453767 01 i 1 01/31/2006 die xxxi mensis i annoque mmvi 06 vi 2006}
+test clock-2.1587 {conversion of 2006-02-01} {
+ clock format 1138797296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2006 12:34:56 die i mensis ii annoque mmvi xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2453768 02 ii 2 02/01/2006 die i mensis ii annoque mmvi 06 vi 2006}
+test clock-2.1588 {conversion of 2006-02-28} {
+ clock format 1141130096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2006 12:34:56 die xxviii mensis ii annoque mmvi xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2453795 02 ii 2 02/28/2006 die xxviii mensis ii annoque mmvi 06 vi 2006}
+test clock-2.1589 {conversion of 2006-03-01} {
+ clock format 1141216496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2006 12:34:56 die i mensis iii annoque mmvi xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2453796 03 iii 3 03/01/2006 die i mensis iii annoque mmvi 06 vi 2006}
+test clock-2.1590 {conversion of 2006-03-31} {
+ clock format 1143808496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2006 12:34:56 die xxxi mensis iii annoque mmvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2453826 03 iii 3 03/31/2006 die xxxi mensis iii annoque mmvi 06 vi 2006}
+test clock-2.1591 {conversion of 2006-04-01} {
+ clock format 1143894896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2006 12:34:56 die i mensis iv annoque mmvi xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2453827 04 iv 4 04/01/2006 die i mensis iv annoque mmvi 06 vi 2006}
+test clock-2.1592 {conversion of 2006-04-30} {
+ clock format 1146400496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2006 12:34:56 die xxx mensis iv annoque mmvi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2453856 04 iv 4 04/30/2006 die xxx mensis iv annoque mmvi 06 vi 2006}
+test clock-2.1593 {conversion of 2006-05-01} {
+ clock format 1146486896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2006 12:34:56 die i mensis v annoque mmvi xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2453857 05 v 5 05/01/2006 die i mensis v annoque mmvi 06 vi 2006}
+test clock-2.1594 {conversion of 2006-05-31} {
+ clock format 1149078896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2006 12:34:56 die xxxi mensis v annoque mmvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2453887 05 v 5 05/31/2006 die xxxi mensis v annoque mmvi 06 vi 2006}
+test clock-2.1595 {conversion of 2006-06-01} {
+ clock format 1149165296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2006 12:34:56 die i mensis vi annoque mmvi xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2453888 06 vi 6 06/01/2006 die i mensis vi annoque mmvi 06 vi 2006}
+test clock-2.1596 {conversion of 2006-06-30} {
+ clock format 1151670896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2006 12:34:56 die xxx mensis vi annoque mmvi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2453917 06 vi 6 06/30/2006 die xxx mensis vi annoque mmvi 06 vi 2006}
+test clock-2.1597 {conversion of 2006-07-01} {
+ clock format 1151757296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2006 12:34:56 die i mensis vii annoque mmvi xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2453918 07 vii 7 07/01/2006 die i mensis vii annoque mmvi 06 vi 2006}
+test clock-2.1598 {conversion of 2006-07-31} {
+ clock format 1154349296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2006 12:34:56 die xxxi mensis vii annoque mmvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2453948 07 vii 7 07/31/2006 die xxxi mensis vii annoque mmvi 06 vi 2006}
+test clock-2.1599 {conversion of 2006-08-01} {
+ clock format 1154435696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2006 12:34:56 die i mensis viii annoque mmvi xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2453949 08 viii 8 08/01/2006 die i mensis viii annoque mmvi 06 vi 2006}
+test clock-2.1600 {conversion of 2006-08-31} {
+ clock format 1157027696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2006 12:34:56 die xxxi mensis viii annoque mmvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2453979 08 viii 8 08/31/2006 die xxxi mensis viii annoque mmvi 06 vi 2006}
+test clock-2.1601 {conversion of 2006-09-01} {
+ clock format 1157114096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2006 12:34:56 die i mensis ix annoque mmvi xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2453980 09 ix 9 09/01/2006 die i mensis ix annoque mmvi 06 vi 2006}
+test clock-2.1602 {conversion of 2006-09-30} {
+ clock format 1159619696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2006 12:34:56 die xxx mensis ix annoque mmvi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2454009 09 ix 9 09/30/2006 die xxx mensis ix annoque mmvi 06 vi 2006}
+test clock-2.1603 {conversion of 2006-10-01} {
+ clock format 1159706096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2006 12:34:56 die i mensis x annoque mmvi xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2454010 10 x 10 10/01/2006 die i mensis x annoque mmvi 06 vi 2006}
+test clock-2.1604 {conversion of 2006-10-31} {
+ clock format 1162298096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2006 12:34:56 die xxxi mensis x annoque mmvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2454040 10 x 10 10/31/2006 die xxxi mensis x annoque mmvi 06 vi 2006}
+test clock-2.1605 {conversion of 2006-11-01} {
+ clock format 1162384496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2006 12:34:56 die i mensis xi annoque mmvi xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2454041 11 xi 11 11/01/2006 die i mensis xi annoque mmvi 06 vi 2006}
+test clock-2.1606 {conversion of 2006-11-30} {
+ clock format 1164890096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2006 12:34:56 die xxx mensis xi annoque mmvi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2454070 11 xi 11 11/30/2006 die xxx mensis xi annoque mmvi 06 vi 2006}
+test clock-2.1607 {conversion of 2006-12-01} {
+ clock format 1164976496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2006 12:34:56 die i mensis xii annoque mmvi xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2454071 12 xii 12 12/01/2006 die i mensis xii annoque mmvi 06 vi 2006}
+test clock-2.1608 {conversion of 2006-12-31} {
+ clock format 1167568496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2006 12:34:56 die xxxi mensis xii annoque mmvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2454101 12 xii 12 12/31/2006 die xxxi mensis xii annoque mmvi 06 vi 2006}
+test clock-2.1609 {conversion of 2007-01-01} {
+ clock format 1167654896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2007 12:34:56 die i mensis i annoque mmvii xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2454102 01 i 1 01/01/2007 die i mensis i annoque mmvii 07 vii 2007}
+test clock-2.1610 {conversion of 2007-01-31} {
+ clock format 1170246896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2007 12:34:56 die xxxi mensis i annoque mmvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2454132 01 i 1 01/31/2007 die xxxi mensis i annoque mmvii 07 vii 2007}
+test clock-2.1611 {conversion of 2007-02-01} {
+ clock format 1170333296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2007 12:34:56 die i mensis ii annoque mmvii xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2454133 02 ii 2 02/01/2007 die i mensis ii annoque mmvii 07 vii 2007}
+test clock-2.1612 {conversion of 2007-02-28} {
+ clock format 1172666096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2007 12:34:56 die xxviii mensis ii annoque mmvii xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2454160 02 ii 2 02/28/2007 die xxviii mensis ii annoque mmvii 07 vii 2007}
+test clock-2.1613 {conversion of 2007-03-01} {
+ clock format 1172752496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2007 12:34:56 die i mensis iii annoque mmvii xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2454161 03 iii 3 03/01/2007 die i mensis iii annoque mmvii 07 vii 2007}
+test clock-2.1614 {conversion of 2007-03-31} {
+ clock format 1175344496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2007 12:34:56 die xxxi mensis iii annoque mmvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2454191 03 iii 3 03/31/2007 die xxxi mensis iii annoque mmvii 07 vii 2007}
+test clock-2.1615 {conversion of 2007-04-01} {
+ clock format 1175430896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2007 12:34:56 die i mensis iv annoque mmvii xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2454192 04 iv 4 04/01/2007 die i mensis iv annoque mmvii 07 vii 2007}
+test clock-2.1616 {conversion of 2007-04-30} {
+ clock format 1177936496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2007 12:34:56 die xxx mensis iv annoque mmvii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2454221 04 iv 4 04/30/2007 die xxx mensis iv annoque mmvii 07 vii 2007}
+test clock-2.1617 {conversion of 2007-05-01} {
+ clock format 1178022896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2007 12:34:56 die i mensis v annoque mmvii xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2454222 05 v 5 05/01/2007 die i mensis v annoque mmvii 07 vii 2007}
+test clock-2.1618 {conversion of 2007-05-31} {
+ clock format 1180614896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2007 12:34:56 die xxxi mensis v annoque mmvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2454252 05 v 5 05/31/2007 die xxxi mensis v annoque mmvii 07 vii 2007}
+test clock-2.1619 {conversion of 2007-06-01} {
+ clock format 1180701296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2007 12:34:56 die i mensis vi annoque mmvii xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2454253 06 vi 6 06/01/2007 die i mensis vi annoque mmvii 07 vii 2007}
+test clock-2.1620 {conversion of 2007-06-30} {
+ clock format 1183206896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2007 12:34:56 die xxx mensis vi annoque mmvii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2454282 06 vi 6 06/30/2007 die xxx mensis vi annoque mmvii 07 vii 2007}
+test clock-2.1621 {conversion of 2007-07-01} {
+ clock format 1183293296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2007 12:34:56 die i mensis vii annoque mmvii xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2454283 07 vii 7 07/01/2007 die i mensis vii annoque mmvii 07 vii 2007}
+test clock-2.1622 {conversion of 2007-07-31} {
+ clock format 1185885296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2007 12:34:56 die xxxi mensis vii annoque mmvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2454313 07 vii 7 07/31/2007 die xxxi mensis vii annoque mmvii 07 vii 2007}
+test clock-2.1623 {conversion of 2007-08-01} {
+ clock format 1185971696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2007 12:34:56 die i mensis viii annoque mmvii xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2454314 08 viii 8 08/01/2007 die i mensis viii annoque mmvii 07 vii 2007}
+test clock-2.1624 {conversion of 2007-08-31} {
+ clock format 1188563696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2007 12:34:56 die xxxi mensis viii annoque mmvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2454344 08 viii 8 08/31/2007 die xxxi mensis viii annoque mmvii 07 vii 2007}
+test clock-2.1625 {conversion of 2007-09-01} {
+ clock format 1188650096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2007 12:34:56 die i mensis ix annoque mmvii xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2454345 09 ix 9 09/01/2007 die i mensis ix annoque mmvii 07 vii 2007}
+test clock-2.1626 {conversion of 2007-09-30} {
+ clock format 1191155696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2007 12:34:56 die xxx mensis ix annoque mmvii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2454374 09 ix 9 09/30/2007 die xxx mensis ix annoque mmvii 07 vii 2007}
+test clock-2.1627 {conversion of 2007-10-01} {
+ clock format 1191242096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2007 12:34:56 die i mensis x annoque mmvii xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2454375 10 x 10 10/01/2007 die i mensis x annoque mmvii 07 vii 2007}
+test clock-2.1628 {conversion of 2007-10-31} {
+ clock format 1193834096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2007 12:34:56 die xxxi mensis x annoque mmvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2454405 10 x 10 10/31/2007 die xxxi mensis x annoque mmvii 07 vii 2007}
+test clock-2.1629 {conversion of 2007-11-01} {
+ clock format 1193920496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2007 12:34:56 die i mensis xi annoque mmvii xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2454406 11 xi 11 11/01/2007 die i mensis xi annoque mmvii 07 vii 2007}
+test clock-2.1630 {conversion of 2007-11-30} {
+ clock format 1196426096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2007 12:34:56 die xxx mensis xi annoque mmvii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2454435 11 xi 11 11/30/2007 die xxx mensis xi annoque mmvii 07 vii 2007}
+test clock-2.1631 {conversion of 2007-12-01} {
+ clock format 1196512496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2007 12:34:56 die i mensis xii annoque mmvii xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2454436 12 xii 12 12/01/2007 die i mensis xii annoque mmvii 07 vii 2007}
+test clock-2.1632 {conversion of 2007-12-31} {
+ clock format 1199104496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2007 12:34:56 die xxxi mensis xii annoque mmvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2454466 12 xii 12 12/31/2007 die xxxi mensis xii annoque mmvii 07 vii 2007}
+test clock-2.1633 {conversion of 2008-01-01} {
+ clock format 1199190896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2008 12:34:56 die i mensis i annoque mmviii xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2454467 01 i 1 01/01/2008 die i mensis i annoque mmviii 08 viii 2008}
+test clock-2.1634 {conversion of 2008-01-31} {
+ clock format 1201782896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2008 12:34:56 die xxxi mensis i annoque mmviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2454497 01 i 1 01/31/2008 die xxxi mensis i annoque mmviii 08 viii 2008}
+test clock-2.1635 {conversion of 2008-02-01} {
+ clock format 1201869296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2008 12:34:56 die i mensis ii annoque mmviii xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2454498 02 ii 2 02/01/2008 die i mensis ii annoque mmviii 08 viii 2008}
+test clock-2.1636 {conversion of 2008-02-29} {
+ clock format 1204288496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/2008 12:34:56 die xxix mensis ii annoque mmviii xii h xxxiv m lvi s 20 mm 29 xxix 29 xxix Feb 060 2454526 02 ii 2 02/29/2008 die xxix mensis ii annoque mmviii 08 viii 2008}
+test clock-2.1637 {conversion of 2008-03-01} {
+ clock format 1204374896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2008 12:34:56 die i mensis iii annoque mmviii xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 061 2454527 03 iii 3 03/01/2008 die i mensis iii annoque mmviii 08 viii 2008}
+test clock-2.1638 {conversion of 2008-03-31} {
+ clock format 1206966896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2008 12:34:56 die xxxi mensis iii annoque mmviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 091 2454557 03 iii 3 03/31/2008 die xxxi mensis iii annoque mmviii 08 viii 2008}
+test clock-2.1639 {conversion of 2008-04-01} {
+ clock format 1207053296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2008 12:34:56 die i mensis iv annoque mmviii xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 092 2454558 04 iv 4 04/01/2008 die i mensis iv annoque mmviii 08 viii 2008}
+test clock-2.1640 {conversion of 2008-04-30} {
+ clock format 1209558896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2008 12:34:56 die xxx mensis iv annoque mmviii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 121 2454587 04 iv 4 04/30/2008 die xxx mensis iv annoque mmviii 08 viii 2008}
+test clock-2.1641 {conversion of 2008-05-01} {
+ clock format 1209645296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2008 12:34:56 die i mensis v annoque mmviii xii h xxxiv m lvi s 20 mm 01 i 1 i May 122 2454588 05 v 5 05/01/2008 die i mensis v annoque mmviii 08 viii 2008}
+test clock-2.1642 {conversion of 2008-05-31} {
+ clock format 1212237296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2008 12:34:56 die xxxi mensis v annoque mmviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 152 2454618 05 v 5 05/31/2008 die xxxi mensis v annoque mmviii 08 viii 2008}
+test clock-2.1643 {conversion of 2008-06-01} {
+ clock format 1212323696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2008 12:34:56 die i mensis vi annoque mmviii xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 153 2454619 06 vi 6 06/01/2008 die i mensis vi annoque mmviii 08 viii 2008}
+test clock-2.1644 {conversion of 2008-06-30} {
+ clock format 1214829296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2008 12:34:56 die xxx mensis vi annoque mmviii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 182 2454648 06 vi 6 06/30/2008 die xxx mensis vi annoque mmviii 08 viii 2008}
+test clock-2.1645 {conversion of 2008-07-01} {
+ clock format 1214915696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2008 12:34:56 die i mensis vii annoque mmviii xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 183 2454649 07 vii 7 07/01/2008 die i mensis vii annoque mmviii 08 viii 2008}
+test clock-2.1646 {conversion of 2008-07-31} {
+ clock format 1217507696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2008 12:34:56 die xxxi mensis vii annoque mmviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 213 2454679 07 vii 7 07/31/2008 die xxxi mensis vii annoque mmviii 08 viii 2008}
+test clock-2.1647 {conversion of 2008-08-01} {
+ clock format 1217594096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2008 12:34:56 die i mensis viii annoque mmviii xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 214 2454680 08 viii 8 08/01/2008 die i mensis viii annoque mmviii 08 viii 2008}
+test clock-2.1648 {conversion of 2008-08-31} {
+ clock format 1220186096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2008 12:34:56 die xxxi mensis viii annoque mmviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 244 2454710 08 viii 8 08/31/2008 die xxxi mensis viii annoque mmviii 08 viii 2008}
+test clock-2.1649 {conversion of 2008-09-01} {
+ clock format 1220272496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2008 12:34:56 die i mensis ix annoque mmviii xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 245 2454711 09 ix 9 09/01/2008 die i mensis ix annoque mmviii 08 viii 2008}
+test clock-2.1650 {conversion of 2008-09-30} {
+ clock format 1222778096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2008 12:34:56 die xxx mensis ix annoque mmviii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 274 2454740 09 ix 9 09/30/2008 die xxx mensis ix annoque mmviii 08 viii 2008}
+test clock-2.1651 {conversion of 2008-10-01} {
+ clock format 1222864496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2008 12:34:56 die i mensis x annoque mmviii xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 275 2454741 10 x 10 10/01/2008 die i mensis x annoque mmviii 08 viii 2008}
+test clock-2.1652 {conversion of 2008-10-31} {
+ clock format 1225456496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2008 12:34:56 die xxxi mensis x annoque mmviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 305 2454771 10 x 10 10/31/2008 die xxxi mensis x annoque mmviii 08 viii 2008}
+test clock-2.1653 {conversion of 2008-11-01} {
+ clock format 1225542896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2008 12:34:56 die i mensis xi annoque mmviii xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 306 2454772 11 xi 11 11/01/2008 die i mensis xi annoque mmviii 08 viii 2008}
+test clock-2.1654 {conversion of 2008-11-30} {
+ clock format 1228048496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2008 12:34:56 die xxx mensis xi annoque mmviii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 335 2454801 11 xi 11 11/30/2008 die xxx mensis xi annoque mmviii 08 viii 2008}
+test clock-2.1655 {conversion of 2008-12-01} {
+ clock format 1228134896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2008 12:34:56 die i mensis xii annoque mmviii xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 336 2454802 12 xii 12 12/01/2008 die i mensis xii annoque mmviii 08 viii 2008}
+test clock-2.1656 {conversion of 2008-12-31} {
+ clock format 1230726896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2008 12:34:56 die xxxi mensis xii annoque mmviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 366 2454832 12 xii 12 12/31/2008 die xxxi mensis xii annoque mmviii 08 viii 2008}
+test clock-2.1657 {conversion of 2009-01-01} {
+ clock format 1230813296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2009 12:34:56 die i mensis i annoque mmix xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2454833 01 i 1 01/01/2009 die i mensis i annoque mmix 09 ix 2009}
+test clock-2.1658 {conversion of 2009-01-31} {
+ clock format 1233405296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2009 12:34:56 die xxxi mensis i annoque mmix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2454863 01 i 1 01/31/2009 die xxxi mensis i annoque mmix 09 ix 2009}
+test clock-2.1659 {conversion of 2009-02-01} {
+ clock format 1233491696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2009 12:34:56 die i mensis ii annoque mmix xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2454864 02 ii 2 02/01/2009 die i mensis ii annoque mmix 09 ix 2009}
+test clock-2.1660 {conversion of 2009-02-28} {
+ clock format 1235824496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2009 12:34:56 die xxviii mensis ii annoque mmix xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2454891 02 ii 2 02/28/2009 die xxviii mensis ii annoque mmix 09 ix 2009}
+test clock-2.1661 {conversion of 2009-03-01} {
+ clock format 1235910896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2009 12:34:56 die i mensis iii annoque mmix xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2454892 03 iii 3 03/01/2009 die i mensis iii annoque mmix 09 ix 2009}
+test clock-2.1662 {conversion of 2009-03-31} {
+ clock format 1238502896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2009 12:34:56 die xxxi mensis iii annoque mmix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2454922 03 iii 3 03/31/2009 die xxxi mensis iii annoque mmix 09 ix 2009}
+test clock-2.1663 {conversion of 2009-04-01} {
+ clock format 1238589296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2009 12:34:56 die i mensis iv annoque mmix xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2454923 04 iv 4 04/01/2009 die i mensis iv annoque mmix 09 ix 2009}
+test clock-2.1664 {conversion of 2009-04-30} {
+ clock format 1241094896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2009 12:34:56 die xxx mensis iv annoque mmix xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2454952 04 iv 4 04/30/2009 die xxx mensis iv annoque mmix 09 ix 2009}
+test clock-2.1665 {conversion of 2009-05-01} {
+ clock format 1241181296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2009 12:34:56 die i mensis v annoque mmix xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2454953 05 v 5 05/01/2009 die i mensis v annoque mmix 09 ix 2009}
+test clock-2.1666 {conversion of 2009-05-31} {
+ clock format 1243773296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2009 12:34:56 die xxxi mensis v annoque mmix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2454983 05 v 5 05/31/2009 die xxxi mensis v annoque mmix 09 ix 2009}
+test clock-2.1667 {conversion of 2009-06-01} {
+ clock format 1243859696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2009 12:34:56 die i mensis vi annoque mmix xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2454984 06 vi 6 06/01/2009 die i mensis vi annoque mmix 09 ix 2009}
+test clock-2.1668 {conversion of 2009-06-30} {
+ clock format 1246365296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2009 12:34:56 die xxx mensis vi annoque mmix xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2455013 06 vi 6 06/30/2009 die xxx mensis vi annoque mmix 09 ix 2009}
+test clock-2.1669 {conversion of 2009-07-01} {
+ clock format 1246451696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2009 12:34:56 die i mensis vii annoque mmix xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2455014 07 vii 7 07/01/2009 die i mensis vii annoque mmix 09 ix 2009}
+test clock-2.1670 {conversion of 2009-07-31} {
+ clock format 1249043696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2009 12:34:56 die xxxi mensis vii annoque mmix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2455044 07 vii 7 07/31/2009 die xxxi mensis vii annoque mmix 09 ix 2009}
+test clock-2.1671 {conversion of 2009-08-01} {
+ clock format 1249130096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2009 12:34:56 die i mensis viii annoque mmix xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2455045 08 viii 8 08/01/2009 die i mensis viii annoque mmix 09 ix 2009}
+test clock-2.1672 {conversion of 2009-08-31} {
+ clock format 1251722096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2009 12:34:56 die xxxi mensis viii annoque mmix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2455075 08 viii 8 08/31/2009 die xxxi mensis viii annoque mmix 09 ix 2009}
+test clock-2.1673 {conversion of 2009-09-01} {
+ clock format 1251808496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2009 12:34:56 die i mensis ix annoque mmix xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2455076 09 ix 9 09/01/2009 die i mensis ix annoque mmix 09 ix 2009}
+test clock-2.1674 {conversion of 2009-09-30} {
+ clock format 1254314096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2009 12:34:56 die xxx mensis ix annoque mmix xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2455105 09 ix 9 09/30/2009 die xxx mensis ix annoque mmix 09 ix 2009}
+test clock-2.1675 {conversion of 2009-10-01} {
+ clock format 1254400496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2009 12:34:56 die i mensis x annoque mmix xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2455106 10 x 10 10/01/2009 die i mensis x annoque mmix 09 ix 2009}
+test clock-2.1676 {conversion of 2009-10-31} {
+ clock format 1256992496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2009 12:34:56 die xxxi mensis x annoque mmix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2455136 10 x 10 10/31/2009 die xxxi mensis x annoque mmix 09 ix 2009}
+test clock-2.1677 {conversion of 2009-11-01} {
+ clock format 1257078896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2009 12:34:56 die i mensis xi annoque mmix xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2455137 11 xi 11 11/01/2009 die i mensis xi annoque mmix 09 ix 2009}
+test clock-2.1678 {conversion of 2009-11-30} {
+ clock format 1259584496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2009 12:34:56 die xxx mensis xi annoque mmix xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2455166 11 xi 11 11/30/2009 die xxx mensis xi annoque mmix 09 ix 2009}
+test clock-2.1679 {conversion of 2009-12-01} {
+ clock format 1259670896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2009 12:34:56 die i mensis xii annoque mmix xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2455167 12 xii 12 12/01/2009 die i mensis xii annoque mmix 09 ix 2009}
+test clock-2.1680 {conversion of 2009-12-31} {
+ clock format 1262262896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2009 12:34:56 die xxxi mensis xii annoque mmix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2455197 12 xii 12 12/31/2009 die xxxi mensis xii annoque mmix 09 ix 2009}
+test clock-2.1681 {conversion of 2010-01-01} {
+ clock format 1262349296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2010 12:34:56 die i mensis i annoque mmx xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2455198 01 i 1 01/01/2010 die i mensis i annoque mmx 10 x 2010}
+test clock-2.1682 {conversion of 2010-01-31} {
+ clock format 1264941296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2010 12:34:56 die xxxi mensis i annoque mmx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2455228 01 i 1 01/31/2010 die xxxi mensis i annoque mmx 10 x 2010}
+test clock-2.1683 {conversion of 2010-02-01} {
+ clock format 1265027696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2010 12:34:56 die i mensis ii annoque mmx xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2455229 02 ii 2 02/01/2010 die i mensis ii annoque mmx 10 x 2010}
+test clock-2.1684 {conversion of 2010-02-28} {
+ clock format 1267360496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2010 12:34:56 die xxviii mensis ii annoque mmx xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2455256 02 ii 2 02/28/2010 die xxviii mensis ii annoque mmx 10 x 2010}
+test clock-2.1685 {conversion of 2010-03-01} {
+ clock format 1267446896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2010 12:34:56 die i mensis iii annoque mmx xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2455257 03 iii 3 03/01/2010 die i mensis iii annoque mmx 10 x 2010}
+test clock-2.1686 {conversion of 2010-03-31} {
+ clock format 1270038896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2010 12:34:56 die xxxi mensis iii annoque mmx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2455287 03 iii 3 03/31/2010 die xxxi mensis iii annoque mmx 10 x 2010}
+test clock-2.1687 {conversion of 2010-04-01} {
+ clock format 1270125296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2010 12:34:56 die i mensis iv annoque mmx xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2455288 04 iv 4 04/01/2010 die i mensis iv annoque mmx 10 x 2010}
+test clock-2.1688 {conversion of 2010-04-30} {
+ clock format 1272630896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2010 12:34:56 die xxx mensis iv annoque mmx xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2455317 04 iv 4 04/30/2010 die xxx mensis iv annoque mmx 10 x 2010}
+test clock-2.1689 {conversion of 2010-05-01} {
+ clock format 1272717296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2010 12:34:56 die i mensis v annoque mmx xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2455318 05 v 5 05/01/2010 die i mensis v annoque mmx 10 x 2010}
+test clock-2.1690 {conversion of 2010-05-31} {
+ clock format 1275309296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2010 12:34:56 die xxxi mensis v annoque mmx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2455348 05 v 5 05/31/2010 die xxxi mensis v annoque mmx 10 x 2010}
+test clock-2.1691 {conversion of 2010-06-01} {
+ clock format 1275395696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2010 12:34:56 die i mensis vi annoque mmx xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2455349 06 vi 6 06/01/2010 die i mensis vi annoque mmx 10 x 2010}
+test clock-2.1692 {conversion of 2010-06-30} {
+ clock format 1277901296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2010 12:34:56 die xxx mensis vi annoque mmx xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2455378 06 vi 6 06/30/2010 die xxx mensis vi annoque mmx 10 x 2010}
+test clock-2.1693 {conversion of 2010-07-01} {
+ clock format 1277987696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2010 12:34:56 die i mensis vii annoque mmx xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2455379 07 vii 7 07/01/2010 die i mensis vii annoque mmx 10 x 2010}
+test clock-2.1694 {conversion of 2010-07-31} {
+ clock format 1280579696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2010 12:34:56 die xxxi mensis vii annoque mmx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2455409 07 vii 7 07/31/2010 die xxxi mensis vii annoque mmx 10 x 2010}
+test clock-2.1695 {conversion of 2010-08-01} {
+ clock format 1280666096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2010 12:34:56 die i mensis viii annoque mmx xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2455410 08 viii 8 08/01/2010 die i mensis viii annoque mmx 10 x 2010}
+test clock-2.1696 {conversion of 2010-08-31} {
+ clock format 1283258096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2010 12:34:56 die xxxi mensis viii annoque mmx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2455440 08 viii 8 08/31/2010 die xxxi mensis viii annoque mmx 10 x 2010}
+test clock-2.1697 {conversion of 2010-09-01} {
+ clock format 1283344496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2010 12:34:56 die i mensis ix annoque mmx xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2455441 09 ix 9 09/01/2010 die i mensis ix annoque mmx 10 x 2010}
+test clock-2.1698 {conversion of 2010-09-30} {
+ clock format 1285850096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2010 12:34:56 die xxx mensis ix annoque mmx xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2455470 09 ix 9 09/30/2010 die xxx mensis ix annoque mmx 10 x 2010}
+test clock-2.1699 {conversion of 2010-10-01} {
+ clock format 1285936496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2010 12:34:56 die i mensis x annoque mmx xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2455471 10 x 10 10/01/2010 die i mensis x annoque mmx 10 x 2010}
+test clock-2.1700 {conversion of 2010-10-31} {
+ clock format 1288528496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2010 12:34:56 die xxxi mensis x annoque mmx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2455501 10 x 10 10/31/2010 die xxxi mensis x annoque mmx 10 x 2010}
+test clock-2.1701 {conversion of 2010-11-01} {
+ clock format 1288614896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2010 12:34:56 die i mensis xi annoque mmx xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2455502 11 xi 11 11/01/2010 die i mensis xi annoque mmx 10 x 2010}
+test clock-2.1702 {conversion of 2010-11-30} {
+ clock format 1291120496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2010 12:34:56 die xxx mensis xi annoque mmx xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2455531 11 xi 11 11/30/2010 die xxx mensis xi annoque mmx 10 x 2010}
+test clock-2.1703 {conversion of 2010-12-01} {
+ clock format 1291206896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2010 12:34:56 die i mensis xii annoque mmx xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2455532 12 xii 12 12/01/2010 die i mensis xii annoque mmx 10 x 2010}
+test clock-2.1704 {conversion of 2010-12-31} {
+ clock format 1293798896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2010 12:34:56 die xxxi mensis xii annoque mmx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2455562 12 xii 12 12/31/2010 die xxxi mensis xii annoque mmx 10 x 2010}
+test clock-2.1705 {conversion of 2011-01-01} {
+ clock format 1293885296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2011 12:34:56 die i mensis i annoque mmxi xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2455563 01 i 1 01/01/2011 die i mensis i annoque mmxi 11 xi 2011}
+test clock-2.1706 {conversion of 2011-01-31} {
+ clock format 1296477296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2011 12:34:56 die xxxi mensis i annoque mmxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2455593 01 i 1 01/31/2011 die xxxi mensis i annoque mmxi 11 xi 2011}
+test clock-2.1707 {conversion of 2011-02-01} {
+ clock format 1296563696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2011 12:34:56 die i mensis ii annoque mmxi xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2455594 02 ii 2 02/01/2011 die i mensis ii annoque mmxi 11 xi 2011}
+test clock-2.1708 {conversion of 2011-02-28} {
+ clock format 1298896496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2011 12:34:56 die xxviii mensis ii annoque mmxi xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2455621 02 ii 2 02/28/2011 die xxviii mensis ii annoque mmxi 11 xi 2011}
+test clock-2.1709 {conversion of 2011-03-01} {
+ clock format 1298982896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2011 12:34:56 die i mensis iii annoque mmxi xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2455622 03 iii 3 03/01/2011 die i mensis iii annoque mmxi 11 xi 2011}
+test clock-2.1710 {conversion of 2011-03-31} {
+ clock format 1301574896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2011 12:34:56 die xxxi mensis iii annoque mmxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2455652 03 iii 3 03/31/2011 die xxxi mensis iii annoque mmxi 11 xi 2011}
+test clock-2.1711 {conversion of 2011-04-01} {
+ clock format 1301661296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2011 12:34:56 die i mensis iv annoque mmxi xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2455653 04 iv 4 04/01/2011 die i mensis iv annoque mmxi 11 xi 2011}
+test clock-2.1712 {conversion of 2011-04-30} {
+ clock format 1304166896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2011 12:34:56 die xxx mensis iv annoque mmxi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2455682 04 iv 4 04/30/2011 die xxx mensis iv annoque mmxi 11 xi 2011}
+test clock-2.1713 {conversion of 2011-05-01} {
+ clock format 1304253296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2011 12:34:56 die i mensis v annoque mmxi xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2455683 05 v 5 05/01/2011 die i mensis v annoque mmxi 11 xi 2011}
+test clock-2.1714 {conversion of 2011-05-31} {
+ clock format 1306845296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2011 12:34:56 die xxxi mensis v annoque mmxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2455713 05 v 5 05/31/2011 die xxxi mensis v annoque mmxi 11 xi 2011}
+test clock-2.1715 {conversion of 2011-06-01} {
+ clock format 1306931696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2011 12:34:56 die i mensis vi annoque mmxi xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2455714 06 vi 6 06/01/2011 die i mensis vi annoque mmxi 11 xi 2011}
+test clock-2.1716 {conversion of 2011-06-30} {
+ clock format 1309437296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2011 12:34:56 die xxx mensis vi annoque mmxi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2455743 06 vi 6 06/30/2011 die xxx mensis vi annoque mmxi 11 xi 2011}
+test clock-2.1717 {conversion of 2011-07-01} {
+ clock format 1309523696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2011 12:34:56 die i mensis vii annoque mmxi xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2455744 07 vii 7 07/01/2011 die i mensis vii annoque mmxi 11 xi 2011}
+test clock-2.1718 {conversion of 2011-07-31} {
+ clock format 1312115696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2011 12:34:56 die xxxi mensis vii annoque mmxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2455774 07 vii 7 07/31/2011 die xxxi mensis vii annoque mmxi 11 xi 2011}
+test clock-2.1719 {conversion of 2011-08-01} {
+ clock format 1312202096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2011 12:34:56 die i mensis viii annoque mmxi xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2455775 08 viii 8 08/01/2011 die i mensis viii annoque mmxi 11 xi 2011}
+test clock-2.1720 {conversion of 2011-08-31} {
+ clock format 1314794096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2011 12:34:56 die xxxi mensis viii annoque mmxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2455805 08 viii 8 08/31/2011 die xxxi mensis viii annoque mmxi 11 xi 2011}
+test clock-2.1721 {conversion of 2011-09-01} {
+ clock format 1314880496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2011 12:34:56 die i mensis ix annoque mmxi xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2455806 09 ix 9 09/01/2011 die i mensis ix annoque mmxi 11 xi 2011}
+test clock-2.1722 {conversion of 2011-09-30} {
+ clock format 1317386096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2011 12:34:56 die xxx mensis ix annoque mmxi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2455835 09 ix 9 09/30/2011 die xxx mensis ix annoque mmxi 11 xi 2011}
+test clock-2.1723 {conversion of 2011-10-01} {
+ clock format 1317472496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2011 12:34:56 die i mensis x annoque mmxi xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2455836 10 x 10 10/01/2011 die i mensis x annoque mmxi 11 xi 2011}
+test clock-2.1724 {conversion of 2011-10-31} {
+ clock format 1320064496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2011 12:34:56 die xxxi mensis x annoque mmxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2455866 10 x 10 10/31/2011 die xxxi mensis x annoque mmxi 11 xi 2011}
+test clock-2.1725 {conversion of 2011-11-01} {
+ clock format 1320150896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2011 12:34:56 die i mensis xi annoque mmxi xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2455867 11 xi 11 11/01/2011 die i mensis xi annoque mmxi 11 xi 2011}
+test clock-2.1726 {conversion of 2011-11-30} {
+ clock format 1322656496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2011 12:34:56 die xxx mensis xi annoque mmxi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2455896 11 xi 11 11/30/2011 die xxx mensis xi annoque mmxi 11 xi 2011}
+test clock-2.1727 {conversion of 2011-12-01} {
+ clock format 1322742896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2011 12:34:56 die i mensis xii annoque mmxi xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2455897 12 xii 12 12/01/2011 die i mensis xii annoque mmxi 11 xi 2011}
+test clock-2.1728 {conversion of 2011-12-31} {
+ clock format 1325334896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2011 12:34:56 die xxxi mensis xii annoque mmxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2455927 12 xii 12 12/31/2011 die xxxi mensis xii annoque mmxi 11 xi 2011}
+test clock-2.1729 {conversion of 2012-01-01} {
+ clock format 1325421296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2012 12:34:56 die i mensis i annoque mmxii xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2455928 01 i 1 01/01/2012 die i mensis i annoque mmxii 12 xii 2012}
+test clock-2.1730 {conversion of 2012-01-31} {
+ clock format 1328013296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2012 12:34:56 die xxxi mensis i annoque mmxii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2455958 01 i 1 01/31/2012 die xxxi mensis i annoque mmxii 12 xii 2012}
+test clock-2.1731 {conversion of 2012-02-01} {
+ clock format 1328099696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2012 12:34:56 die i mensis ii annoque mmxii xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2455959 02 ii 2 02/01/2012 die i mensis ii annoque mmxii 12 xii 2012}
+test clock-2.1732 {conversion of 2012-02-29} {
+ clock format 1330518896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/2012 12:34:56 die xxix mensis ii annoque mmxii xii h xxxiv m lvi s 20 mm 29 xxix 29 xxix Feb 060 2455987 02 ii 2 02/29/2012 die xxix mensis ii annoque mmxii 12 xii 2012}
+test clock-2.1733 {conversion of 2012-03-01} {
+ clock format 1330605296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2012 12:34:56 die i mensis iii annoque mmxii xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 061 2455988 03 iii 3 03/01/2012 die i mensis iii annoque mmxii 12 xii 2012}
+test clock-2.1734 {conversion of 2012-03-31} {
+ clock format 1333197296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2012 12:34:56 die xxxi mensis iii annoque mmxii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 091 2456018 03 iii 3 03/31/2012 die xxxi mensis iii annoque mmxii 12 xii 2012}
+test clock-2.1735 {conversion of 2012-04-01} {
+ clock format 1333283696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2012 12:34:56 die i mensis iv annoque mmxii xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 092 2456019 04 iv 4 04/01/2012 die i mensis iv annoque mmxii 12 xii 2012}
+test clock-2.1736 {conversion of 2012-04-30} {
+ clock format 1335789296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2012 12:34:56 die xxx mensis iv annoque mmxii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 121 2456048 04 iv 4 04/30/2012 die xxx mensis iv annoque mmxii 12 xii 2012}
+test clock-2.1737 {conversion of 2012-05-01} {
+ clock format 1335875696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2012 12:34:56 die i mensis v annoque mmxii xii h xxxiv m lvi s 20 mm 01 i 1 i May 122 2456049 05 v 5 05/01/2012 die i mensis v annoque mmxii 12 xii 2012}
+test clock-2.1738 {conversion of 2012-05-31} {
+ clock format 1338467696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2012 12:34:56 die xxxi mensis v annoque mmxii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 152 2456079 05 v 5 05/31/2012 die xxxi mensis v annoque mmxii 12 xii 2012}
+test clock-2.1739 {conversion of 2012-06-01} {
+ clock format 1338554096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2012 12:34:56 die i mensis vi annoque mmxii xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 153 2456080 06 vi 6 06/01/2012 die i mensis vi annoque mmxii 12 xii 2012}
+test clock-2.1740 {conversion of 2012-06-30} {
+ clock format 1341059696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2012 12:34:56 die xxx mensis vi annoque mmxii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 182 2456109 06 vi 6 06/30/2012 die xxx mensis vi annoque mmxii 12 xii 2012}
+test clock-2.1741 {conversion of 2012-07-01} {
+ clock format 1341146096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2012 12:34:56 die i mensis vii annoque mmxii xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 183 2456110 07 vii 7 07/01/2012 die i mensis vii annoque mmxii 12 xii 2012}
+test clock-2.1742 {conversion of 2012-07-31} {
+ clock format 1343738096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2012 12:34:56 die xxxi mensis vii annoque mmxii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 213 2456140 07 vii 7 07/31/2012 die xxxi mensis vii annoque mmxii 12 xii 2012}
+test clock-2.1743 {conversion of 2012-08-01} {
+ clock format 1343824496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2012 12:34:56 die i mensis viii annoque mmxii xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 214 2456141 08 viii 8 08/01/2012 die i mensis viii annoque mmxii 12 xii 2012}
+test clock-2.1744 {conversion of 2012-08-31} {
+ clock format 1346416496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2012 12:34:56 die xxxi mensis viii annoque mmxii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 244 2456171 08 viii 8 08/31/2012 die xxxi mensis viii annoque mmxii 12 xii 2012}
+test clock-2.1745 {conversion of 2012-09-01} {
+ clock format 1346502896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2012 12:34:56 die i mensis ix annoque mmxii xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 245 2456172 09 ix 9 09/01/2012 die i mensis ix annoque mmxii 12 xii 2012}
+test clock-2.1746 {conversion of 2012-09-30} {
+ clock format 1349008496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2012 12:34:56 die xxx mensis ix annoque mmxii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 274 2456201 09 ix 9 09/30/2012 die xxx mensis ix annoque mmxii 12 xii 2012}
+test clock-2.1747 {conversion of 2012-10-01} {
+ clock format 1349094896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2012 12:34:56 die i mensis x annoque mmxii xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 275 2456202 10 x 10 10/01/2012 die i mensis x annoque mmxii 12 xii 2012}
+test clock-2.1748 {conversion of 2012-10-31} {
+ clock format 1351686896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2012 12:34:56 die xxxi mensis x annoque mmxii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 305 2456232 10 x 10 10/31/2012 die xxxi mensis x annoque mmxii 12 xii 2012}
+test clock-2.1749 {conversion of 2012-11-01} {
+ clock format 1351773296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2012 12:34:56 die i mensis xi annoque mmxii xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 306 2456233 11 xi 11 11/01/2012 die i mensis xi annoque mmxii 12 xii 2012}
+test clock-2.1750 {conversion of 2012-11-30} {
+ clock format 1354278896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2012 12:34:56 die xxx mensis xi annoque mmxii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 335 2456262 11 xi 11 11/30/2012 die xxx mensis xi annoque mmxii 12 xii 2012}
+test clock-2.1751 {conversion of 2012-12-01} {
+ clock format 1354365296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2012 12:34:56 die i mensis xii annoque mmxii xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 336 2456263 12 xii 12 12/01/2012 die i mensis xii annoque mmxii 12 xii 2012}
+test clock-2.1752 {conversion of 2012-12-31} {
+ clock format 1356957296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2012 12:34:56 die xxxi mensis xii annoque mmxii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 366 2456293 12 xii 12 12/31/2012 die xxxi mensis xii annoque mmxii 12 xii 2012}
+test clock-2.1753 {conversion of 2013-01-01} {
+ clock format 1357043696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2013 12:34:56 die i mensis i annoque mmxiii xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2456294 01 i 1 01/01/2013 die i mensis i annoque mmxiii 13 xiii 2013}
+test clock-2.1754 {conversion of 2013-01-31} {
+ clock format 1359635696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2013 12:34:56 die xxxi mensis i annoque mmxiii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2456324 01 i 1 01/31/2013 die xxxi mensis i annoque mmxiii 13 xiii 2013}
+test clock-2.1755 {conversion of 2013-02-01} {
+ clock format 1359722096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2013 12:34:56 die i mensis ii annoque mmxiii xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2456325 02 ii 2 02/01/2013 die i mensis ii annoque mmxiii 13 xiii 2013}
+test clock-2.1756 {conversion of 2013-02-28} {
+ clock format 1362054896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2013 12:34:56 die xxviii mensis ii annoque mmxiii xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2456352 02 ii 2 02/28/2013 die xxviii mensis ii annoque mmxiii 13 xiii 2013}
+test clock-2.1757 {conversion of 2013-03-01} {
+ clock format 1362141296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2013 12:34:56 die i mensis iii annoque mmxiii xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2456353 03 iii 3 03/01/2013 die i mensis iii annoque mmxiii 13 xiii 2013}
+test clock-2.1758 {conversion of 2013-03-31} {
+ clock format 1364733296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2013 12:34:56 die xxxi mensis iii annoque mmxiii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2456383 03 iii 3 03/31/2013 die xxxi mensis iii annoque mmxiii 13 xiii 2013}
+test clock-2.1759 {conversion of 2013-04-01} {
+ clock format 1364819696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2013 12:34:56 die i mensis iv annoque mmxiii xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2456384 04 iv 4 04/01/2013 die i mensis iv annoque mmxiii 13 xiii 2013}
+test clock-2.1760 {conversion of 2013-04-30} {
+ clock format 1367325296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2013 12:34:56 die xxx mensis iv annoque mmxiii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2456413 04 iv 4 04/30/2013 die xxx mensis iv annoque mmxiii 13 xiii 2013}
+test clock-2.1761 {conversion of 2013-05-01} {
+ clock format 1367411696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2013 12:34:56 die i mensis v annoque mmxiii xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2456414 05 v 5 05/01/2013 die i mensis v annoque mmxiii 13 xiii 2013}
+test clock-2.1762 {conversion of 2013-05-31} {
+ clock format 1370003696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2013 12:34:56 die xxxi mensis v annoque mmxiii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2456444 05 v 5 05/31/2013 die xxxi mensis v annoque mmxiii 13 xiii 2013}
+test clock-2.1763 {conversion of 2013-06-01} {
+ clock format 1370090096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2013 12:34:56 die i mensis vi annoque mmxiii xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2456445 06 vi 6 06/01/2013 die i mensis vi annoque mmxiii 13 xiii 2013}
+test clock-2.1764 {conversion of 2013-06-30} {
+ clock format 1372595696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2013 12:34:56 die xxx mensis vi annoque mmxiii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2456474 06 vi 6 06/30/2013 die xxx mensis vi annoque mmxiii 13 xiii 2013}
+test clock-2.1765 {conversion of 2013-07-01} {
+ clock format 1372682096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2013 12:34:56 die i mensis vii annoque mmxiii xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2456475 07 vii 7 07/01/2013 die i mensis vii annoque mmxiii 13 xiii 2013}
+test clock-2.1766 {conversion of 2013-07-31} {
+ clock format 1375274096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2013 12:34:56 die xxxi mensis vii annoque mmxiii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2456505 07 vii 7 07/31/2013 die xxxi mensis vii annoque mmxiii 13 xiii 2013}
+test clock-2.1767 {conversion of 2013-08-01} {
+ clock format 1375360496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2013 12:34:56 die i mensis viii annoque mmxiii xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2456506 08 viii 8 08/01/2013 die i mensis viii annoque mmxiii 13 xiii 2013}
+test clock-2.1768 {conversion of 2013-08-31} {
+ clock format 1377952496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2013 12:34:56 die xxxi mensis viii annoque mmxiii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2456536 08 viii 8 08/31/2013 die xxxi mensis viii annoque mmxiii 13 xiii 2013}
+test clock-2.1769 {conversion of 2013-09-01} {
+ clock format 1378038896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2013 12:34:56 die i mensis ix annoque mmxiii xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2456537 09 ix 9 09/01/2013 die i mensis ix annoque mmxiii 13 xiii 2013}
+test clock-2.1770 {conversion of 2013-09-30} {
+ clock format 1380544496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2013 12:34:56 die xxx mensis ix annoque mmxiii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2456566 09 ix 9 09/30/2013 die xxx mensis ix annoque mmxiii 13 xiii 2013}
+test clock-2.1771 {conversion of 2013-10-01} {
+ clock format 1380630896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2013 12:34:56 die i mensis x annoque mmxiii xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2456567 10 x 10 10/01/2013 die i mensis x annoque mmxiii 13 xiii 2013}
+test clock-2.1772 {conversion of 2013-10-31} {
+ clock format 1383222896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2013 12:34:56 die xxxi mensis x annoque mmxiii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2456597 10 x 10 10/31/2013 die xxxi mensis x annoque mmxiii 13 xiii 2013}
+test clock-2.1773 {conversion of 2013-11-01} {
+ clock format 1383309296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2013 12:34:56 die i mensis xi annoque mmxiii xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2456598 11 xi 11 11/01/2013 die i mensis xi annoque mmxiii 13 xiii 2013}
+test clock-2.1774 {conversion of 2013-11-30} {
+ clock format 1385814896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2013 12:34:56 die xxx mensis xi annoque mmxiii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2456627 11 xi 11 11/30/2013 die xxx mensis xi annoque mmxiii 13 xiii 2013}
+test clock-2.1775 {conversion of 2013-12-01} {
+ clock format 1385901296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2013 12:34:56 die i mensis xii annoque mmxiii xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2456628 12 xii 12 12/01/2013 die i mensis xii annoque mmxiii 13 xiii 2013}
+test clock-2.1776 {conversion of 2013-12-31} {
+ clock format 1388493296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2013 12:34:56 die xxxi mensis xii annoque mmxiii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2456658 12 xii 12 12/31/2013 die xxxi mensis xii annoque mmxiii 13 xiii 2013}
+test clock-2.1777 {conversion of 2016-01-01} {
+ clock format 1451651696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2016 12:34:56 die i mensis i annoque mmxvi xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2457389 01 i 1 01/01/2016 die i mensis i annoque mmxvi 16 xvi 2016}
+test clock-2.1778 {conversion of 2016-01-31} {
+ clock format 1454243696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2016 12:34:56 die xxxi mensis i annoque mmxvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2457419 01 i 1 01/31/2016 die xxxi mensis i annoque mmxvi 16 xvi 2016}
+test clock-2.1779 {conversion of 2016-02-01} {
+ clock format 1454330096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2016 12:34:56 die i mensis ii annoque mmxvi xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2457420 02 ii 2 02/01/2016 die i mensis ii annoque mmxvi 16 xvi 2016}
+test clock-2.1780 {conversion of 2016-02-29} {
+ clock format 1456749296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/2016 12:34:56 die xxix mensis ii annoque mmxvi xii h xxxiv m lvi s 20 mm 29 xxix 29 xxix Feb 060 2457448 02 ii 2 02/29/2016 die xxix mensis ii annoque mmxvi 16 xvi 2016}
+test clock-2.1781 {conversion of 2016-03-01} {
+ clock format 1456835696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2016 12:34:56 die i mensis iii annoque mmxvi xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 061 2457449 03 iii 3 03/01/2016 die i mensis iii annoque mmxvi 16 xvi 2016}
+test clock-2.1782 {conversion of 2016-03-31} {
+ clock format 1459427696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2016 12:34:56 die xxxi mensis iii annoque mmxvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 091 2457479 03 iii 3 03/31/2016 die xxxi mensis iii annoque mmxvi 16 xvi 2016}
+test clock-2.1783 {conversion of 2016-04-01} {
+ clock format 1459514096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2016 12:34:56 die i mensis iv annoque mmxvi xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 092 2457480 04 iv 4 04/01/2016 die i mensis iv annoque mmxvi 16 xvi 2016}
+test clock-2.1784 {conversion of 2016-04-30} {
+ clock format 1462019696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2016 12:34:56 die xxx mensis iv annoque mmxvi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 121 2457509 04 iv 4 04/30/2016 die xxx mensis iv annoque mmxvi 16 xvi 2016}
+test clock-2.1785 {conversion of 2016-05-01} {
+ clock format 1462106096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2016 12:34:56 die i mensis v annoque mmxvi xii h xxxiv m lvi s 20 mm 01 i 1 i May 122 2457510 05 v 5 05/01/2016 die i mensis v annoque mmxvi 16 xvi 2016}
+test clock-2.1786 {conversion of 2016-05-31} {
+ clock format 1464698096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2016 12:34:56 die xxxi mensis v annoque mmxvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 152 2457540 05 v 5 05/31/2016 die xxxi mensis v annoque mmxvi 16 xvi 2016}
+test clock-2.1787 {conversion of 2016-06-01} {
+ clock format 1464784496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2016 12:34:56 die i mensis vi annoque mmxvi xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 153 2457541 06 vi 6 06/01/2016 die i mensis vi annoque mmxvi 16 xvi 2016}
+test clock-2.1788 {conversion of 2016-06-30} {
+ clock format 1467290096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2016 12:34:56 die xxx mensis vi annoque mmxvi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 182 2457570 06 vi 6 06/30/2016 die xxx mensis vi annoque mmxvi 16 xvi 2016}
+test clock-2.1789 {conversion of 2016-07-01} {
+ clock format 1467376496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2016 12:34:56 die i mensis vii annoque mmxvi xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 183 2457571 07 vii 7 07/01/2016 die i mensis vii annoque mmxvi 16 xvi 2016}
+test clock-2.1790 {conversion of 2016-07-31} {
+ clock format 1469968496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2016 12:34:56 die xxxi mensis vii annoque mmxvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 213 2457601 07 vii 7 07/31/2016 die xxxi mensis vii annoque mmxvi 16 xvi 2016}
+test clock-2.1791 {conversion of 2016-08-01} {
+ clock format 1470054896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2016 12:34:56 die i mensis viii annoque mmxvi xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 214 2457602 08 viii 8 08/01/2016 die i mensis viii annoque mmxvi 16 xvi 2016}
+test clock-2.1792 {conversion of 2016-08-31} {
+ clock format 1472646896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2016 12:34:56 die xxxi mensis viii annoque mmxvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 244 2457632 08 viii 8 08/31/2016 die xxxi mensis viii annoque mmxvi 16 xvi 2016}
+test clock-2.1793 {conversion of 2016-09-01} {
+ clock format 1472733296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2016 12:34:56 die i mensis ix annoque mmxvi xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 245 2457633 09 ix 9 09/01/2016 die i mensis ix annoque mmxvi 16 xvi 2016}
+test clock-2.1794 {conversion of 2016-09-30} {
+ clock format 1475238896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2016 12:34:56 die xxx mensis ix annoque mmxvi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 274 2457662 09 ix 9 09/30/2016 die xxx mensis ix annoque mmxvi 16 xvi 2016}
+test clock-2.1795 {conversion of 2016-10-01} {
+ clock format 1475325296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2016 12:34:56 die i mensis x annoque mmxvi xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 275 2457663 10 x 10 10/01/2016 die i mensis x annoque mmxvi 16 xvi 2016}
+test clock-2.1796 {conversion of 2016-10-31} {
+ clock format 1477917296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2016 12:34:56 die xxxi mensis x annoque mmxvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 305 2457693 10 x 10 10/31/2016 die xxxi mensis x annoque mmxvi 16 xvi 2016}
+test clock-2.1797 {conversion of 2016-11-01} {
+ clock format 1478003696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2016 12:34:56 die i mensis xi annoque mmxvi xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 306 2457694 11 xi 11 11/01/2016 die i mensis xi annoque mmxvi 16 xvi 2016}
+test clock-2.1798 {conversion of 2016-11-30} {
+ clock format 1480509296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2016 12:34:56 die xxx mensis xi annoque mmxvi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 335 2457723 11 xi 11 11/30/2016 die xxx mensis xi annoque mmxvi 16 xvi 2016}
+test clock-2.1799 {conversion of 2016-12-01} {
+ clock format 1480595696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2016 12:34:56 die i mensis xii annoque mmxvi xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 336 2457724 12 xii 12 12/01/2016 die i mensis xii annoque mmxvi 16 xvi 2016}
+test clock-2.1800 {conversion of 2016-12-31} {
+ clock format 1483187696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2016 12:34:56 die xxxi mensis xii annoque mmxvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 366 2457754 12 xii 12 12/31/2016 die xxxi mensis xii annoque mmxvi 16 xvi 2016}
+test clock-2.1801 {conversion of 2017-01-01} {
+ clock format 1483274096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2017 12:34:56 die i mensis i annoque mmxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2457755 01 i 1 01/01/2017 die i mensis i annoque mmxvii 17 xvii 2017}
+test clock-2.1802 {conversion of 2017-01-31} {
+ clock format 1485866096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2017 12:34:56 die xxxi mensis i annoque mmxvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2457785 01 i 1 01/31/2017 die xxxi mensis i annoque mmxvii 17 xvii 2017}
+test clock-2.1803 {conversion of 2017-02-01} {
+ clock format 1485952496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2017 12:34:56 die i mensis ii annoque mmxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2457786 02 ii 2 02/01/2017 die i mensis ii annoque mmxvii 17 xvii 2017}
+test clock-2.1804 {conversion of 2017-02-28} {
+ clock format 1488285296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2017 12:34:56 die xxviii mensis ii annoque mmxvii xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2457813 02 ii 2 02/28/2017 die xxviii mensis ii annoque mmxvii 17 xvii 2017}
+test clock-2.1805 {conversion of 2017-03-01} {
+ clock format 1488371696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2017 12:34:56 die i mensis iii annoque mmxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2457814 03 iii 3 03/01/2017 die i mensis iii annoque mmxvii 17 xvii 2017}
+test clock-2.1806 {conversion of 2017-03-31} {
+ clock format 1490963696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2017 12:34:56 die xxxi mensis iii annoque mmxvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2457844 03 iii 3 03/31/2017 die xxxi mensis iii annoque mmxvii 17 xvii 2017}
+test clock-2.1807 {conversion of 2017-04-01} {
+ clock format 1491050096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2017 12:34:56 die i mensis iv annoque mmxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2457845 04 iv 4 04/01/2017 die i mensis iv annoque mmxvii 17 xvii 2017}
+test clock-2.1808 {conversion of 2017-04-30} {
+ clock format 1493555696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2017 12:34:56 die xxx mensis iv annoque mmxvii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2457874 04 iv 4 04/30/2017 die xxx mensis iv annoque mmxvii 17 xvii 2017}
+test clock-2.1809 {conversion of 2017-05-01} {
+ clock format 1493642096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2017 12:34:56 die i mensis v annoque mmxvii xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2457875 05 v 5 05/01/2017 die i mensis v annoque mmxvii 17 xvii 2017}
+test clock-2.1810 {conversion of 2017-05-31} {
+ clock format 1496234096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2017 12:34:56 die xxxi mensis v annoque mmxvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2457905 05 v 5 05/31/2017 die xxxi mensis v annoque mmxvii 17 xvii 2017}
+test clock-2.1811 {conversion of 2017-06-01} {
+ clock format 1496320496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2017 12:34:56 die i mensis vi annoque mmxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2457906 06 vi 6 06/01/2017 die i mensis vi annoque mmxvii 17 xvii 2017}
+test clock-2.1812 {conversion of 2017-06-30} {
+ clock format 1498826096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2017 12:34:56 die xxx mensis vi annoque mmxvii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2457935 06 vi 6 06/30/2017 die xxx mensis vi annoque mmxvii 17 xvii 2017}
+test clock-2.1813 {conversion of 2017-07-01} {
+ clock format 1498912496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2017 12:34:56 die i mensis vii annoque mmxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2457936 07 vii 7 07/01/2017 die i mensis vii annoque mmxvii 17 xvii 2017}
+test clock-2.1814 {conversion of 2017-07-31} {
+ clock format 1501504496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2017 12:34:56 die xxxi mensis vii annoque mmxvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2457966 07 vii 7 07/31/2017 die xxxi mensis vii annoque mmxvii 17 xvii 2017}
+test clock-2.1815 {conversion of 2017-08-01} {
+ clock format 1501590896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2017 12:34:56 die i mensis viii annoque mmxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2457967 08 viii 8 08/01/2017 die i mensis viii annoque mmxvii 17 xvii 2017}
+test clock-2.1816 {conversion of 2017-08-31} {
+ clock format 1504182896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2017 12:34:56 die xxxi mensis viii annoque mmxvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2457997 08 viii 8 08/31/2017 die xxxi mensis viii annoque mmxvii 17 xvii 2017}
+test clock-2.1817 {conversion of 2017-09-01} {
+ clock format 1504269296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2017 12:34:56 die i mensis ix annoque mmxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2457998 09 ix 9 09/01/2017 die i mensis ix annoque mmxvii 17 xvii 2017}
+test clock-2.1818 {conversion of 2017-09-30} {
+ clock format 1506774896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2017 12:34:56 die xxx mensis ix annoque mmxvii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2458027 09 ix 9 09/30/2017 die xxx mensis ix annoque mmxvii 17 xvii 2017}
+test clock-2.1819 {conversion of 2017-10-01} {
+ clock format 1506861296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2017 12:34:56 die i mensis x annoque mmxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2458028 10 x 10 10/01/2017 die i mensis x annoque mmxvii 17 xvii 2017}
+test clock-2.1820 {conversion of 2017-10-31} {
+ clock format 1509453296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2017 12:34:56 die xxxi mensis x annoque mmxvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2458058 10 x 10 10/31/2017 die xxxi mensis x annoque mmxvii 17 xvii 2017}
+test clock-2.1821 {conversion of 2017-11-01} {
+ clock format 1509539696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2017 12:34:56 die i mensis xi annoque mmxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2458059 11 xi 11 11/01/2017 die i mensis xi annoque mmxvii 17 xvii 2017}
+test clock-2.1822 {conversion of 2017-11-30} {
+ clock format 1512045296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2017 12:34:56 die xxx mensis xi annoque mmxvii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2458088 11 xi 11 11/30/2017 die xxx mensis xi annoque mmxvii 17 xvii 2017}
+test clock-2.1823 {conversion of 2017-12-01} {
+ clock format 1512131696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2017 12:34:56 die i mensis xii annoque mmxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2458089 12 xii 12 12/01/2017 die i mensis xii annoque mmxvii 17 xvii 2017}
+test clock-2.1824 {conversion of 2017-12-31} {
+ clock format 1514723696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2017 12:34:56 die xxxi mensis xii annoque mmxvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2458119 12 xii 12 12/31/2017 die xxxi mensis xii annoque mmxvii 17 xvii 2017}
+test clock-2.1825 {conversion of 2020-01-01} {
+ clock format 1577882096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2020 12:34:56 die i mensis i annoque mmxx xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2458850 01 i 1 01/01/2020 die i mensis i annoque mmxx 20 xx 2020}
+test clock-2.1826 {conversion of 2020-01-31} {
+ clock format 1580474096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2020 12:34:56 die xxxi mensis i annoque mmxx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2458880 01 i 1 01/31/2020 die xxxi mensis i annoque mmxx 20 xx 2020}
+test clock-2.1827 {conversion of 2020-02-01} {
+ clock format 1580560496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2020 12:34:56 die i mensis ii annoque mmxx xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2458881 02 ii 2 02/01/2020 die i mensis ii annoque mmxx 20 xx 2020}
+test clock-2.1828 {conversion of 2020-02-29} {
+ clock format 1582979696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/2020 12:34:56 die xxix mensis ii annoque mmxx xii h xxxiv m lvi s 20 mm 29 xxix 29 xxix Feb 060 2458909 02 ii 2 02/29/2020 die xxix mensis ii annoque mmxx 20 xx 2020}
+test clock-2.1829 {conversion of 2020-03-01} {
+ clock format 1583066096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2020 12:34:56 die i mensis iii annoque mmxx xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 061 2458910 03 iii 3 03/01/2020 die i mensis iii annoque mmxx 20 xx 2020}
+test clock-2.1830 {conversion of 2020-03-31} {
+ clock format 1585658096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2020 12:34:56 die xxxi mensis iii annoque mmxx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 091 2458940 03 iii 3 03/31/2020 die xxxi mensis iii annoque mmxx 20 xx 2020}
+test clock-2.1831 {conversion of 2020-04-01} {
+ clock format 1585744496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2020 12:34:56 die i mensis iv annoque mmxx xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 092 2458941 04 iv 4 04/01/2020 die i mensis iv annoque mmxx 20 xx 2020}
+test clock-2.1832 {conversion of 2020-04-30} {
+ clock format 1588250096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2020 12:34:56 die xxx mensis iv annoque mmxx xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 121 2458970 04 iv 4 04/30/2020 die xxx mensis iv annoque mmxx 20 xx 2020}
+test clock-2.1833 {conversion of 2020-05-01} {
+ clock format 1588336496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2020 12:34:56 die i mensis v annoque mmxx xii h xxxiv m lvi s 20 mm 01 i 1 i May 122 2458971 05 v 5 05/01/2020 die i mensis v annoque mmxx 20 xx 2020}
+test clock-2.1834 {conversion of 2020-05-31} {
+ clock format 1590928496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2020 12:34:56 die xxxi mensis v annoque mmxx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 152 2459001 05 v 5 05/31/2020 die xxxi mensis v annoque mmxx 20 xx 2020}
+test clock-2.1835 {conversion of 2020-06-01} {
+ clock format 1591014896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2020 12:34:56 die i mensis vi annoque mmxx xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 153 2459002 06 vi 6 06/01/2020 die i mensis vi annoque mmxx 20 xx 2020}
+test clock-2.1836 {conversion of 2020-06-30} {
+ clock format 1593520496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2020 12:34:56 die xxx mensis vi annoque mmxx xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 182 2459031 06 vi 6 06/30/2020 die xxx mensis vi annoque mmxx 20 xx 2020}
+test clock-2.1837 {conversion of 2020-07-01} {
+ clock format 1593606896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2020 12:34:56 die i mensis vii annoque mmxx xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 183 2459032 07 vii 7 07/01/2020 die i mensis vii annoque mmxx 20 xx 2020}
+test clock-2.1838 {conversion of 2020-07-31} {
+ clock format 1596198896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2020 12:34:56 die xxxi mensis vii annoque mmxx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 213 2459062 07 vii 7 07/31/2020 die xxxi mensis vii annoque mmxx 20 xx 2020}
+test clock-2.1839 {conversion of 2020-08-01} {
+ clock format 1596285296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2020 12:34:56 die i mensis viii annoque mmxx xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 214 2459063 08 viii 8 08/01/2020 die i mensis viii annoque mmxx 20 xx 2020}
+test clock-2.1840 {conversion of 2020-08-31} {
+ clock format 1598877296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2020 12:34:56 die xxxi mensis viii annoque mmxx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 244 2459093 08 viii 8 08/31/2020 die xxxi mensis viii annoque mmxx 20 xx 2020}
+test clock-2.1841 {conversion of 2020-09-01} {
+ clock format 1598963696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2020 12:34:56 die i mensis ix annoque mmxx xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 245 2459094 09 ix 9 09/01/2020 die i mensis ix annoque mmxx 20 xx 2020}
+test clock-2.1842 {conversion of 2020-09-30} {
+ clock format 1601469296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2020 12:34:56 die xxx mensis ix annoque mmxx xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 274 2459123 09 ix 9 09/30/2020 die xxx mensis ix annoque mmxx 20 xx 2020}
+test clock-2.1843 {conversion of 2020-10-01} {
+ clock format 1601555696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2020 12:34:56 die i mensis x annoque mmxx xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 275 2459124 10 x 10 10/01/2020 die i mensis x annoque mmxx 20 xx 2020}
+test clock-2.1844 {conversion of 2020-10-31} {
+ clock format 1604147696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2020 12:34:56 die xxxi mensis x annoque mmxx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 305 2459154 10 x 10 10/31/2020 die xxxi mensis x annoque mmxx 20 xx 2020}
+test clock-2.1845 {conversion of 2020-11-01} {
+ clock format 1604234096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2020 12:34:56 die i mensis xi annoque mmxx xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 306 2459155 11 xi 11 11/01/2020 die i mensis xi annoque mmxx 20 xx 2020}
+test clock-2.1846 {conversion of 2020-11-30} {
+ clock format 1606739696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2020 12:34:56 die xxx mensis xi annoque mmxx xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 335 2459184 11 xi 11 11/30/2020 die xxx mensis xi annoque mmxx 20 xx 2020}
+test clock-2.1847 {conversion of 2020-12-01} {
+ clock format 1606826096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2020 12:34:56 die i mensis xii annoque mmxx xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 336 2459185 12 xii 12 12/01/2020 die i mensis xii annoque mmxx 20 xx 2020}
+test clock-2.1848 {conversion of 2020-12-31} {
+ clock format 1609418096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2020 12:34:56 die xxxi mensis xii annoque mmxx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 366 2459215 12 xii 12 12/31/2020 die xxxi mensis xii annoque mmxx 20 xx 2020}
+test clock-2.1849 {conversion of 2021-01-01} {
+ clock format 1609504496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2021 12:34:56 die i mensis i annoque mmxxi xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2459216 01 i 1 01/01/2021 die i mensis i annoque mmxxi 21 xxi 2021}
+test clock-2.1850 {conversion of 2021-01-31} {
+ clock format 1612096496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2021 12:34:56 die xxxi mensis i annoque mmxxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2459246 01 i 1 01/31/2021 die xxxi mensis i annoque mmxxi 21 xxi 2021}
+test clock-2.1851 {conversion of 2021-02-01} {
+ clock format 1612182896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2021 12:34:56 die i mensis ii annoque mmxxi xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2459247 02 ii 2 02/01/2021 die i mensis ii annoque mmxxi 21 xxi 2021}
+test clock-2.1852 {conversion of 2021-02-28} {
+ clock format 1614515696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2021 12:34:56 die xxviii mensis ii annoque mmxxi xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2459274 02 ii 2 02/28/2021 die xxviii mensis ii annoque mmxxi 21 xxi 2021}
+test clock-2.1853 {conversion of 2021-03-01} {
+ clock format 1614602096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2021 12:34:56 die i mensis iii annoque mmxxi xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2459275 03 iii 3 03/01/2021 die i mensis iii annoque mmxxi 21 xxi 2021}
+test clock-2.1854 {conversion of 2021-03-31} {
+ clock format 1617194096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2021 12:34:56 die xxxi mensis iii annoque mmxxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2459305 03 iii 3 03/31/2021 die xxxi mensis iii annoque mmxxi 21 xxi 2021}
+test clock-2.1855 {conversion of 2021-04-01} {
+ clock format 1617280496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2021 12:34:56 die i mensis iv annoque mmxxi xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2459306 04 iv 4 04/01/2021 die i mensis iv annoque mmxxi 21 xxi 2021}
+test clock-2.1856 {conversion of 2021-04-30} {
+ clock format 1619786096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2021 12:34:56 die xxx mensis iv annoque mmxxi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2459335 04 iv 4 04/30/2021 die xxx mensis iv annoque mmxxi 21 xxi 2021}
+test clock-2.1857 {conversion of 2021-05-01} {
+ clock format 1619872496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2021 12:34:56 die i mensis v annoque mmxxi xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2459336 05 v 5 05/01/2021 die i mensis v annoque mmxxi 21 xxi 2021}
+test clock-2.1858 {conversion of 2021-05-31} {
+ clock format 1622464496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2021 12:34:56 die xxxi mensis v annoque mmxxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2459366 05 v 5 05/31/2021 die xxxi mensis v annoque mmxxi 21 xxi 2021}
+test clock-2.1859 {conversion of 2021-06-01} {
+ clock format 1622550896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2021 12:34:56 die i mensis vi annoque mmxxi xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2459367 06 vi 6 06/01/2021 die i mensis vi annoque mmxxi 21 xxi 2021}
+test clock-2.1860 {conversion of 2021-06-30} {
+ clock format 1625056496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2021 12:34:56 die xxx mensis vi annoque mmxxi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2459396 06 vi 6 06/30/2021 die xxx mensis vi annoque mmxxi 21 xxi 2021}
+test clock-2.1861 {conversion of 2021-07-01} {
+ clock format 1625142896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2021 12:34:56 die i mensis vii annoque mmxxi xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2459397 07 vii 7 07/01/2021 die i mensis vii annoque mmxxi 21 xxi 2021}
+test clock-2.1862 {conversion of 2021-07-31} {
+ clock format 1627734896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2021 12:34:56 die xxxi mensis vii annoque mmxxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2459427 07 vii 7 07/31/2021 die xxxi mensis vii annoque mmxxi 21 xxi 2021}
+test clock-2.1863 {conversion of 2021-08-01} {
+ clock format 1627821296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2021 12:34:56 die i mensis viii annoque mmxxi xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2459428 08 viii 8 08/01/2021 die i mensis viii annoque mmxxi 21 xxi 2021}
+test clock-2.1864 {conversion of 2021-08-31} {
+ clock format 1630413296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2021 12:34:56 die xxxi mensis viii annoque mmxxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2459458 08 viii 8 08/31/2021 die xxxi mensis viii annoque mmxxi 21 xxi 2021}
+test clock-2.1865 {conversion of 2021-09-01} {
+ clock format 1630499696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2021 12:34:56 die i mensis ix annoque mmxxi xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2459459 09 ix 9 09/01/2021 die i mensis ix annoque mmxxi 21 xxi 2021}
+test clock-2.1866 {conversion of 2021-09-30} {
+ clock format 1633005296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2021 12:34:56 die xxx mensis ix annoque mmxxi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2459488 09 ix 9 09/30/2021 die xxx mensis ix annoque mmxxi 21 xxi 2021}
+test clock-2.1867 {conversion of 2021-10-01} {
+ clock format 1633091696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2021 12:34:56 die i mensis x annoque mmxxi xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2459489 10 x 10 10/01/2021 die i mensis x annoque mmxxi 21 xxi 2021}
+test clock-2.1868 {conversion of 2021-10-31} {
+ clock format 1635683696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2021 12:34:56 die xxxi mensis x annoque mmxxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2459519 10 x 10 10/31/2021 die xxxi mensis x annoque mmxxi 21 xxi 2021}
+test clock-2.1869 {conversion of 2021-11-01} {
+ clock format 1635770096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2021 12:34:56 die i mensis xi annoque mmxxi xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2459520 11 xi 11 11/01/2021 die i mensis xi annoque mmxxi 21 xxi 2021}
+test clock-2.1870 {conversion of 2021-11-30} {
+ clock format 1638275696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2021 12:34:56 die xxx mensis xi annoque mmxxi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2459549 11 xi 11 11/30/2021 die xxx mensis xi annoque mmxxi 21 xxi 2021}
+test clock-2.1871 {conversion of 2021-12-01} {
+ clock format 1638362096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2021 12:34:56 die i mensis xii annoque mmxxi xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2459550 12 xii 12 12/01/2021 die i mensis xii annoque mmxxi 21 xxi 2021}
+test clock-2.1872 {conversion of 2021-12-31} {
+ clock format 1640954096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2021 12:34:56 die xxxi mensis xii annoque mmxxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2459580 12 xii 12 12/31/2021 die xxxi mensis xii annoque mmxxi 21 xxi 2021}
+test clock-2.1873 {conversion of 2024-01-01} {
+ clock format 1704112496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2024 12:34:56 die i mensis i annoque mmxxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2460311 01 i 1 01/01/2024 die i mensis i annoque mmxxiv 24 xxiv 2024}
+test clock-2.1874 {conversion of 2024-01-31} {
+ clock format 1706704496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2024 12:34:56 die xxxi mensis i annoque mmxxiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2460341 01 i 1 01/31/2024 die xxxi mensis i annoque mmxxiv 24 xxiv 2024}
+test clock-2.1875 {conversion of 2024-02-01} {
+ clock format 1706790896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2024 12:34:56 die i mensis ii annoque mmxxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2460342 02 ii 2 02/01/2024 die i mensis ii annoque mmxxiv 24 xxiv 2024}
+test clock-2.1876 {conversion of 2024-02-29} {
+ clock format 1709210096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/2024 12:34:56 die xxix mensis ii annoque mmxxiv xii h xxxiv m lvi s 20 mm 29 xxix 29 xxix Feb 060 2460370 02 ii 2 02/29/2024 die xxix mensis ii annoque mmxxiv 24 xxiv 2024}
+test clock-2.1877 {conversion of 2024-03-01} {
+ clock format 1709296496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2024 12:34:56 die i mensis iii annoque mmxxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 061 2460371 03 iii 3 03/01/2024 die i mensis iii annoque mmxxiv 24 xxiv 2024}
+test clock-2.1878 {conversion of 2024-03-31} {
+ clock format 1711888496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2024 12:34:56 die xxxi mensis iii annoque mmxxiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 091 2460401 03 iii 3 03/31/2024 die xxxi mensis iii annoque mmxxiv 24 xxiv 2024}
+test clock-2.1879 {conversion of 2024-04-01} {
+ clock format 1711974896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2024 12:34:56 die i mensis iv annoque mmxxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 092 2460402 04 iv 4 04/01/2024 die i mensis iv annoque mmxxiv 24 xxiv 2024}
+test clock-2.1880 {conversion of 2024-04-30} {
+ clock format 1714480496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2024 12:34:56 die xxx mensis iv annoque mmxxiv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 121 2460431 04 iv 4 04/30/2024 die xxx mensis iv annoque mmxxiv 24 xxiv 2024}
+test clock-2.1881 {conversion of 2024-05-01} {
+ clock format 1714566896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2024 12:34:56 die i mensis v annoque mmxxiv xii h xxxiv m lvi s 20 mm 01 i 1 i May 122 2460432 05 v 5 05/01/2024 die i mensis v annoque mmxxiv 24 xxiv 2024}
+test clock-2.1882 {conversion of 2024-05-31} {
+ clock format 1717158896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2024 12:34:56 die xxxi mensis v annoque mmxxiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 152 2460462 05 v 5 05/31/2024 die xxxi mensis v annoque mmxxiv 24 xxiv 2024}
+test clock-2.1883 {conversion of 2024-06-01} {
+ clock format 1717245296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2024 12:34:56 die i mensis vi annoque mmxxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 153 2460463 06 vi 6 06/01/2024 die i mensis vi annoque mmxxiv 24 xxiv 2024}
+test clock-2.1884 {conversion of 2024-06-30} {
+ clock format 1719750896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2024 12:34:56 die xxx mensis vi annoque mmxxiv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 182 2460492 06 vi 6 06/30/2024 die xxx mensis vi annoque mmxxiv 24 xxiv 2024}
+test clock-2.1885 {conversion of 2024-07-01} {
+ clock format 1719837296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2024 12:34:56 die i mensis vii annoque mmxxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 183 2460493 07 vii 7 07/01/2024 die i mensis vii annoque mmxxiv 24 xxiv 2024}
+test clock-2.1886 {conversion of 2024-07-31} {
+ clock format 1722429296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2024 12:34:56 die xxxi mensis vii annoque mmxxiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 213 2460523 07 vii 7 07/31/2024 die xxxi mensis vii annoque mmxxiv 24 xxiv 2024}
+test clock-2.1887 {conversion of 2024-08-01} {
+ clock format 1722515696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2024 12:34:56 die i mensis viii annoque mmxxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 214 2460524 08 viii 8 08/01/2024 die i mensis viii annoque mmxxiv 24 xxiv 2024}
+test clock-2.1888 {conversion of 2024-08-31} {
+ clock format 1725107696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2024 12:34:56 die xxxi mensis viii annoque mmxxiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 244 2460554 08 viii 8 08/31/2024 die xxxi mensis viii annoque mmxxiv 24 xxiv 2024}
+test clock-2.1889 {conversion of 2024-09-01} {
+ clock format 1725194096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2024 12:34:56 die i mensis ix annoque mmxxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 245 2460555 09 ix 9 09/01/2024 die i mensis ix annoque mmxxiv 24 xxiv 2024}
+test clock-2.1890 {conversion of 2024-09-30} {
+ clock format 1727699696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2024 12:34:56 die xxx mensis ix annoque mmxxiv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 274 2460584 09 ix 9 09/30/2024 die xxx mensis ix annoque mmxxiv 24 xxiv 2024}
+test clock-2.1891 {conversion of 2024-10-01} {
+ clock format 1727786096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2024 12:34:56 die i mensis x annoque mmxxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 275 2460585 10 x 10 10/01/2024 die i mensis x annoque mmxxiv 24 xxiv 2024}
+test clock-2.1892 {conversion of 2024-10-31} {
+ clock format 1730378096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2024 12:34:56 die xxxi mensis x annoque mmxxiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 305 2460615 10 x 10 10/31/2024 die xxxi mensis x annoque mmxxiv 24 xxiv 2024}
+test clock-2.1893 {conversion of 2024-11-01} {
+ clock format 1730464496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2024 12:34:56 die i mensis xi annoque mmxxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 306 2460616 11 xi 11 11/01/2024 die i mensis xi annoque mmxxiv 24 xxiv 2024}
+test clock-2.1894 {conversion of 2024-11-30} {
+ clock format 1732970096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2024 12:34:56 die xxx mensis xi annoque mmxxiv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 335 2460645 11 xi 11 11/30/2024 die xxx mensis xi annoque mmxxiv 24 xxiv 2024}
+test clock-2.1895 {conversion of 2024-12-01} {
+ clock format 1733056496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2024 12:34:56 die i mensis xii annoque mmxxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 336 2460646 12 xii 12 12/01/2024 die i mensis xii annoque mmxxiv 24 xxiv 2024}
+test clock-2.1896 {conversion of 2024-12-31} {
+ clock format 1735648496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2024 12:34:56 die xxxi mensis xii annoque mmxxiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 366 2460676 12 xii 12 12/31/2024 die xxxi mensis xii annoque mmxxiv 24 xxiv 2024}
+test clock-2.1897 {conversion of 2025-01-01} {
+ clock format 1735734896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2025 12:34:56 die i mensis i annoque mmxxv xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2460677 01 i 1 01/01/2025 die i mensis i annoque mmxxv 25 xxv 2025}
+test clock-2.1898 {conversion of 2025-01-31} {
+ clock format 1738326896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2025 12:34:56 die xxxi mensis i annoque mmxxv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2460707 01 i 1 01/31/2025 die xxxi mensis i annoque mmxxv 25 xxv 2025}
+test clock-2.1899 {conversion of 2025-02-01} {
+ clock format 1738413296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2025 12:34:56 die i mensis ii annoque mmxxv xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2460708 02 ii 2 02/01/2025 die i mensis ii annoque mmxxv 25 xxv 2025}
+test clock-2.1900 {conversion of 2025-02-28} {
+ clock format 1740746096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2025 12:34:56 die xxviii mensis ii annoque mmxxv xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2460735 02 ii 2 02/28/2025 die xxviii mensis ii annoque mmxxv 25 xxv 2025}
+test clock-2.1901 {conversion of 2025-03-01} {
+ clock format 1740832496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2025 12:34:56 die i mensis iii annoque mmxxv xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2460736 03 iii 3 03/01/2025 die i mensis iii annoque mmxxv 25 xxv 2025}
+test clock-2.1902 {conversion of 2025-03-31} {
+ clock format 1743424496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2025 12:34:56 die xxxi mensis iii annoque mmxxv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2460766 03 iii 3 03/31/2025 die xxxi mensis iii annoque mmxxv 25 xxv 2025}
+test clock-2.1903 {conversion of 2025-04-01} {
+ clock format 1743510896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2025 12:34:56 die i mensis iv annoque mmxxv xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2460767 04 iv 4 04/01/2025 die i mensis iv annoque mmxxv 25 xxv 2025}
+test clock-2.1904 {conversion of 2025-04-30} {
+ clock format 1746016496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2025 12:34:56 die xxx mensis iv annoque mmxxv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2460796 04 iv 4 04/30/2025 die xxx mensis iv annoque mmxxv 25 xxv 2025}
+test clock-2.1905 {conversion of 2025-05-01} {
+ clock format 1746102896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2025 12:34:56 die i mensis v annoque mmxxv xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2460797 05 v 5 05/01/2025 die i mensis v annoque mmxxv 25 xxv 2025}
+test clock-2.1906 {conversion of 2025-05-31} {
+ clock format 1748694896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2025 12:34:56 die xxxi mensis v annoque mmxxv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2460827 05 v 5 05/31/2025 die xxxi mensis v annoque mmxxv 25 xxv 2025}
+test clock-2.1907 {conversion of 2025-06-01} {
+ clock format 1748781296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2025 12:34:56 die i mensis vi annoque mmxxv xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2460828 06 vi 6 06/01/2025 die i mensis vi annoque mmxxv 25 xxv 2025}
+test clock-2.1908 {conversion of 2025-06-30} {
+ clock format 1751286896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2025 12:34:56 die xxx mensis vi annoque mmxxv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2460857 06 vi 6 06/30/2025 die xxx mensis vi annoque mmxxv 25 xxv 2025}
+test clock-2.1909 {conversion of 2025-07-01} {
+ clock format 1751373296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2025 12:34:56 die i mensis vii annoque mmxxv xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2460858 07 vii 7 07/01/2025 die i mensis vii annoque mmxxv 25 xxv 2025}
+test clock-2.1910 {conversion of 2025-07-31} {
+ clock format 1753965296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2025 12:34:56 die xxxi mensis vii annoque mmxxv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2460888 07 vii 7 07/31/2025 die xxxi mensis vii annoque mmxxv 25 xxv 2025}
+test clock-2.1911 {conversion of 2025-08-01} {
+ clock format 1754051696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2025 12:34:56 die i mensis viii annoque mmxxv xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2460889 08 viii 8 08/01/2025 die i mensis viii annoque mmxxv 25 xxv 2025}
+test clock-2.1912 {conversion of 2025-08-31} {
+ clock format 1756643696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2025 12:34:56 die xxxi mensis viii annoque mmxxv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2460919 08 viii 8 08/31/2025 die xxxi mensis viii annoque mmxxv 25 xxv 2025}
+test clock-2.1913 {conversion of 2025-09-01} {
+ clock format 1756730096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2025 12:34:56 die i mensis ix annoque mmxxv xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2460920 09 ix 9 09/01/2025 die i mensis ix annoque mmxxv 25 xxv 2025}
+test clock-2.1914 {conversion of 2025-09-30} {
+ clock format 1759235696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2025 12:34:56 die xxx mensis ix annoque mmxxv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2460949 09 ix 9 09/30/2025 die xxx mensis ix annoque mmxxv 25 xxv 2025}
+test clock-2.1915 {conversion of 2025-10-01} {
+ clock format 1759322096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2025 12:34:56 die i mensis x annoque mmxxv xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2460950 10 x 10 10/01/2025 die i mensis x annoque mmxxv 25 xxv 2025}
+test clock-2.1916 {conversion of 2025-10-31} {
+ clock format 1761914096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2025 12:34:56 die xxxi mensis x annoque mmxxv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2460980 10 x 10 10/31/2025 die xxxi mensis x annoque mmxxv 25 xxv 2025}
+test clock-2.1917 {conversion of 2025-11-01} {
+ clock format 1762000496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2025 12:34:56 die i mensis xi annoque mmxxv xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2460981 11 xi 11 11/01/2025 die i mensis xi annoque mmxxv 25 xxv 2025}
+test clock-2.1918 {conversion of 2025-11-30} {
+ clock format 1764506096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2025 12:34:56 die xxx mensis xi annoque mmxxv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2461010 11 xi 11 11/30/2025 die xxx mensis xi annoque mmxxv 25 xxv 2025}
+test clock-2.1919 {conversion of 2025-12-01} {
+ clock format 1764592496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2025 12:34:56 die i mensis xii annoque mmxxv xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2461011 12 xii 12 12/01/2025 die i mensis xii annoque mmxxv 25 xxv 2025}
+test clock-2.1920 {conversion of 2025-12-31} {
+ clock format 1767184496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2025 12:34:56 die xxxi mensis xii annoque mmxxv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2461041 12 xii 12 12/31/2025 die xxxi mensis xii annoque mmxxv 25 xxv 2025}
+test clock-2.1921 {conversion of 2037-01-01} {
+ clock format 2114426096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2037 12:34:56 die i mensis i annoque mmxxxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2465060 01 i 1 01/01/2037 die i mensis i annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1922 {conversion of 2037-01-31} {
+ clock format 2117018096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2037 12:34:56 die xxxi mensis i annoque mmxxxvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2465090 01 i 1 01/31/2037 die xxxi mensis i annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1923 {conversion of 2037-02-01} {
+ clock format 2117104496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2037 12:34:56 die i mensis ii annoque mmxxxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2465091 02 ii 2 02/01/2037 die i mensis ii annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1924 {conversion of 2037-02-28} {
+ clock format 2119437296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2037 12:34:56 die xxviii mensis ii annoque mmxxxvii xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2465118 02 ii 2 02/28/2037 die xxviii mensis ii annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1925 {conversion of 2037-03-01} {
+ clock format 2119523696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2037 12:34:56 die i mensis iii annoque mmxxxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2465119 03 iii 3 03/01/2037 die i mensis iii annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1926 {conversion of 2037-03-31} {
+ clock format 2122115696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2037 12:34:56 die xxxi mensis iii annoque mmxxxvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2465149 03 iii 3 03/31/2037 die xxxi mensis iii annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1927 {conversion of 2037-04-01} {
+ clock format 2122202096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2037 12:34:56 die i mensis iv annoque mmxxxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2465150 04 iv 4 04/01/2037 die i mensis iv annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1928 {conversion of 2037-04-30} {
+ clock format 2124707696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2037 12:34:56 die xxx mensis iv annoque mmxxxvii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2465179 04 iv 4 04/30/2037 die xxx mensis iv annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1929 {conversion of 2037-05-01} {
+ clock format 2124794096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2037 12:34:56 die i mensis v annoque mmxxxvii xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2465180 05 v 5 05/01/2037 die i mensis v annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1930 {conversion of 2037-05-31} {
+ clock format 2127386096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2037 12:34:56 die xxxi mensis v annoque mmxxxvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2465210 05 v 5 05/31/2037 die xxxi mensis v annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1931 {conversion of 2037-06-01} {
+ clock format 2127472496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2037 12:34:56 die i mensis vi annoque mmxxxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2465211 06 vi 6 06/01/2037 die i mensis vi annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1932 {conversion of 2037-06-30} {
+ clock format 2129978096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2037 12:34:56 die xxx mensis vi annoque mmxxxvii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2465240 06 vi 6 06/30/2037 die xxx mensis vi annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1933 {conversion of 2037-07-01} {
+ clock format 2130064496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2037 12:34:56 die i mensis vii annoque mmxxxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2465241 07 vii 7 07/01/2037 die i mensis vii annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1934 {conversion of 2037-07-31} {
+ clock format 2132656496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2037 12:34:56 die xxxi mensis vii annoque mmxxxvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2465271 07 vii 7 07/31/2037 die xxxi mensis vii annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1935 {conversion of 2037-08-01} {
+ clock format 2132742896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2037 12:34:56 die i mensis viii annoque mmxxxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2465272 08 viii 8 08/01/2037 die i mensis viii annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1936 {conversion of 2037-08-31} {
+ clock format 2135334896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2037 12:34:56 die xxxi mensis viii annoque mmxxxvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2465302 08 viii 8 08/31/2037 die xxxi mensis viii annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1937 {conversion of 2037-09-01} {
+ clock format 2135421296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2037 12:34:56 die i mensis ix annoque mmxxxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2465303 09 ix 9 09/01/2037 die i mensis ix annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1938 {conversion of 2037-09-30} {
+ clock format 2137926896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2037 12:34:56 die xxx mensis ix annoque mmxxxvii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2465332 09 ix 9 09/30/2037 die xxx mensis ix annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1939 {conversion of 2037-10-01} {
+ clock format 2138013296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2037 12:34:56 die i mensis x annoque mmxxxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2465333 10 x 10 10/01/2037 die i mensis x annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1940 {conversion of 2037-10-31} {
+ clock format 2140605296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2037 12:34:56 die xxxi mensis x annoque mmxxxvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2465363 10 x 10 10/31/2037 die xxxi mensis x annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1941 {conversion of 2037-11-01} {
+ clock format 2140691696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2037 12:34:56 die i mensis xi annoque mmxxxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2465364 11 xi 11 11/01/2037 die i mensis xi annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1942 {conversion of 2037-11-30} {
+ clock format 2143197296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2037 12:34:56 die xxx mensis xi annoque mmxxxvii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2465393 11 xi 11 11/30/2037 die xxx mensis xi annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1943 {conversion of 2037-12-01} {
+ clock format 2143283696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2037 12:34:56 die i mensis xii annoque mmxxxvii xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2465394 12 xii 12 12/01/2037 die i mensis xii annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1944 {conversion of 2037-12-31} {
+ clock format 2145875696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2037 12:34:56 die xxxi mensis xii annoque mmxxxvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2465424 12 xii 12 12/31/2037 die xxxi mensis xii annoque mmxxxvii 37 xxxvii 2037}
+test clock-2.1945 {conversion of 2038-01-01} {
+ clock format 2145962096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2038 12:34:56 die i mensis i annoque mmxxxviii xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2465425 01 i 1 01/01/2038 die i mensis i annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1946 {conversion of 2038-01-31} {
+ clock format 2148554096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2038 12:34:56 die xxxi mensis i annoque mmxxxviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2465455 01 i 1 01/31/2038 die xxxi mensis i annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1947 {conversion of 2038-02-01} {
+ clock format 2148640496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2038 12:34:56 die i mensis ii annoque mmxxxviii xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2465456 02 ii 2 02/01/2038 die i mensis ii annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1948 {conversion of 2038-02-28} {
+ clock format 2150973296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2038 12:34:56 die xxviii mensis ii annoque mmxxxviii xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2465483 02 ii 2 02/28/2038 die xxviii mensis ii annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1949 {conversion of 2038-03-01} {
+ clock format 2151059696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2038 12:34:56 die i mensis iii annoque mmxxxviii xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2465484 03 iii 3 03/01/2038 die i mensis iii annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1950 {conversion of 2038-03-31} {
+ clock format 2153651696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2038 12:34:56 die xxxi mensis iii annoque mmxxxviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2465514 03 iii 3 03/31/2038 die xxxi mensis iii annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1951 {conversion of 2038-04-01} {
+ clock format 2153738096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2038 12:34:56 die i mensis iv annoque mmxxxviii xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2465515 04 iv 4 04/01/2038 die i mensis iv annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1952 {conversion of 2038-04-30} {
+ clock format 2156243696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2038 12:34:56 die xxx mensis iv annoque mmxxxviii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2465544 04 iv 4 04/30/2038 die xxx mensis iv annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1953 {conversion of 2038-05-01} {
+ clock format 2156330096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2038 12:34:56 die i mensis v annoque mmxxxviii xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2465545 05 v 5 05/01/2038 die i mensis v annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1954 {conversion of 2038-05-31} {
+ clock format 2158922096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2038 12:34:56 die xxxi mensis v annoque mmxxxviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2465575 05 v 5 05/31/2038 die xxxi mensis v annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1955 {conversion of 2038-06-01} {
+ clock format 2159008496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2038 12:34:56 die i mensis vi annoque mmxxxviii xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2465576 06 vi 6 06/01/2038 die i mensis vi annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1956 {conversion of 2038-06-30} {
+ clock format 2161514096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2038 12:34:56 die xxx mensis vi annoque mmxxxviii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2465605 06 vi 6 06/30/2038 die xxx mensis vi annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1957 {conversion of 2038-07-01} {
+ clock format 2161600496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2038 12:34:56 die i mensis vii annoque mmxxxviii xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2465606 07 vii 7 07/01/2038 die i mensis vii annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1958 {conversion of 2038-07-31} {
+ clock format 2164192496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2038 12:34:56 die xxxi mensis vii annoque mmxxxviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2465636 07 vii 7 07/31/2038 die xxxi mensis vii annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1959 {conversion of 2038-08-01} {
+ clock format 2164278896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2038 12:34:56 die i mensis viii annoque mmxxxviii xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2465637 08 viii 8 08/01/2038 die i mensis viii annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1960 {conversion of 2038-08-31} {
+ clock format 2166870896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2038 12:34:56 die xxxi mensis viii annoque mmxxxviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2465667 08 viii 8 08/31/2038 die xxxi mensis viii annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1961 {conversion of 2038-09-01} {
+ clock format 2166957296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2038 12:34:56 die i mensis ix annoque mmxxxviii xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2465668 09 ix 9 09/01/2038 die i mensis ix annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1962 {conversion of 2038-09-30} {
+ clock format 2169462896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2038 12:34:56 die xxx mensis ix annoque mmxxxviii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2465697 09 ix 9 09/30/2038 die xxx mensis ix annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1963 {conversion of 2038-10-01} {
+ clock format 2169549296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2038 12:34:56 die i mensis x annoque mmxxxviii xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2465698 10 x 10 10/01/2038 die i mensis x annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1964 {conversion of 2038-10-31} {
+ clock format 2172141296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2038 12:34:56 die xxxi mensis x annoque mmxxxviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2465728 10 x 10 10/31/2038 die xxxi mensis x annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1965 {conversion of 2038-11-01} {
+ clock format 2172227696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2038 12:34:56 die i mensis xi annoque mmxxxviii xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2465729 11 xi 11 11/01/2038 die i mensis xi annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1966 {conversion of 2038-11-30} {
+ clock format 2174733296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2038 12:34:56 die xxx mensis xi annoque mmxxxviii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2465758 11 xi 11 11/30/2038 die xxx mensis xi annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1967 {conversion of 2038-12-01} {
+ clock format 2174819696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2038 12:34:56 die i mensis xii annoque mmxxxviii xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2465759 12 xii 12 12/01/2038 die i mensis xii annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1968 {conversion of 2038-12-31} {
+ clock format 2177411696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2038 12:34:56 die xxxi mensis xii annoque mmxxxviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2465789 12 xii 12 12/31/2038 die xxxi mensis xii annoque mmxxxviii 38 xxxviii 2038}
+test clock-2.1969 {conversion of 2039-01-01} {
+ clock format 2177498096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2039 12:34:56 die i mensis i annoque mmxxxix xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2465790 01 i 1 01/01/2039 die i mensis i annoque mmxxxix 39 xxxix 2039}
+test clock-2.1970 {conversion of 2039-01-31} {
+ clock format 2180090096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2039 12:34:56 die xxxi mensis i annoque mmxxxix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2465820 01 i 1 01/31/2039 die xxxi mensis i annoque mmxxxix 39 xxxix 2039}
+test clock-2.1971 {conversion of 2039-02-01} {
+ clock format 2180176496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2039 12:34:56 die i mensis ii annoque mmxxxix xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2465821 02 ii 2 02/01/2039 die i mensis ii annoque mmxxxix 39 xxxix 2039}
+test clock-2.1972 {conversion of 2039-02-28} {
+ clock format 2182509296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2039 12:34:56 die xxviii mensis ii annoque mmxxxix xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2465848 02 ii 2 02/28/2039 die xxviii mensis ii annoque mmxxxix 39 xxxix 2039}
+test clock-2.1973 {conversion of 2039-03-01} {
+ clock format 2182595696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2039 12:34:56 die i mensis iii annoque mmxxxix xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2465849 03 iii 3 03/01/2039 die i mensis iii annoque mmxxxix 39 xxxix 2039}
+test clock-2.1974 {conversion of 2039-03-31} {
+ clock format 2185187696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2039 12:34:56 die xxxi mensis iii annoque mmxxxix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2465879 03 iii 3 03/31/2039 die xxxi mensis iii annoque mmxxxix 39 xxxix 2039}
+test clock-2.1975 {conversion of 2039-04-01} {
+ clock format 2185274096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2039 12:34:56 die i mensis iv annoque mmxxxix xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2465880 04 iv 4 04/01/2039 die i mensis iv annoque mmxxxix 39 xxxix 2039}
+test clock-2.1976 {conversion of 2039-04-30} {
+ clock format 2187779696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2039 12:34:56 die xxx mensis iv annoque mmxxxix xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2465909 04 iv 4 04/30/2039 die xxx mensis iv annoque mmxxxix 39 xxxix 2039}
+test clock-2.1977 {conversion of 2039-05-01} {
+ clock format 2187866096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2039 12:34:56 die i mensis v annoque mmxxxix xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2465910 05 v 5 05/01/2039 die i mensis v annoque mmxxxix 39 xxxix 2039}
+test clock-2.1978 {conversion of 2039-05-31} {
+ clock format 2190458096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2039 12:34:56 die xxxi mensis v annoque mmxxxix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2465940 05 v 5 05/31/2039 die xxxi mensis v annoque mmxxxix 39 xxxix 2039}
+test clock-2.1979 {conversion of 2039-06-01} {
+ clock format 2190544496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2039 12:34:56 die i mensis vi annoque mmxxxix xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2465941 06 vi 6 06/01/2039 die i mensis vi annoque mmxxxix 39 xxxix 2039}
+test clock-2.1980 {conversion of 2039-06-30} {
+ clock format 2193050096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2039 12:34:56 die xxx mensis vi annoque mmxxxix xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2465970 06 vi 6 06/30/2039 die xxx mensis vi annoque mmxxxix 39 xxxix 2039}
+test clock-2.1981 {conversion of 2039-07-01} {
+ clock format 2193136496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2039 12:34:56 die i mensis vii annoque mmxxxix xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2465971 07 vii 7 07/01/2039 die i mensis vii annoque mmxxxix 39 xxxix 2039}
+test clock-2.1982 {conversion of 2039-07-31} {
+ clock format 2195728496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2039 12:34:56 die xxxi mensis vii annoque mmxxxix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2466001 07 vii 7 07/31/2039 die xxxi mensis vii annoque mmxxxix 39 xxxix 2039}
+test clock-2.1983 {conversion of 2039-08-01} {
+ clock format 2195814896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2039 12:34:56 die i mensis viii annoque mmxxxix xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2466002 08 viii 8 08/01/2039 die i mensis viii annoque mmxxxix 39 xxxix 2039}
+test clock-2.1984 {conversion of 2039-08-31} {
+ clock format 2198406896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2039 12:34:56 die xxxi mensis viii annoque mmxxxix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2466032 08 viii 8 08/31/2039 die xxxi mensis viii annoque mmxxxix 39 xxxix 2039}
+test clock-2.1985 {conversion of 2039-09-01} {
+ clock format 2198493296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2039 12:34:56 die i mensis ix annoque mmxxxix xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2466033 09 ix 9 09/01/2039 die i mensis ix annoque mmxxxix 39 xxxix 2039}
+test clock-2.1986 {conversion of 2039-09-30} {
+ clock format 2200998896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2039 12:34:56 die xxx mensis ix annoque mmxxxix xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2466062 09 ix 9 09/30/2039 die xxx mensis ix annoque mmxxxix 39 xxxix 2039}
+test clock-2.1987 {conversion of 2039-10-01} {
+ clock format 2201085296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2039 12:34:56 die i mensis x annoque mmxxxix xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2466063 10 x 10 10/01/2039 die i mensis x annoque mmxxxix 39 xxxix 2039}
+test clock-2.1988 {conversion of 2039-10-31} {
+ clock format 2203677296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2039 12:34:56 die xxxi mensis x annoque mmxxxix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2466093 10 x 10 10/31/2039 die xxxi mensis x annoque mmxxxix 39 xxxix 2039}
+test clock-2.1989 {conversion of 2039-11-01} {
+ clock format 2203763696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2039 12:34:56 die i mensis xi annoque mmxxxix xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2466094 11 xi 11 11/01/2039 die i mensis xi annoque mmxxxix 39 xxxix 2039}
+test clock-2.1990 {conversion of 2039-11-30} {
+ clock format 2206269296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2039 12:34:56 die xxx mensis xi annoque mmxxxix xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2466123 11 xi 11 11/30/2039 die xxx mensis xi annoque mmxxxix 39 xxxix 2039}
+test clock-2.1991 {conversion of 2039-12-01} {
+ clock format 2206355696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2039 12:34:56 die i mensis xii annoque mmxxxix xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2466124 12 xii 12 12/01/2039 die i mensis xii annoque mmxxxix 39 xxxix 2039}
+test clock-2.1992 {conversion of 2039-12-31} {
+ clock format 2208947696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2039 12:34:56 die xxxi mensis xii annoque mmxxxix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2466154 12 xii 12 12/31/2039 die xxxi mensis xii annoque mmxxxix 39 xxxix 2039}
+test clock-2.1993 {conversion of 2040-01-01} {
+ clock format 2209034096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2040 12:34:56 die i mensis i annoque mmxl xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2466155 01 i 1 01/01/2040 die i mensis i annoque mmxl 40 xl 2040}
+test clock-2.1994 {conversion of 2040-01-31} {
+ clock format 2211626096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2040 12:34:56 die xxxi mensis i annoque mmxl xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2466185 01 i 1 01/31/2040 die xxxi mensis i annoque mmxl 40 xl 2040}
+test clock-2.1995 {conversion of 2040-02-01} {
+ clock format 2211712496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2040 12:34:56 die i mensis ii annoque mmxl xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2466186 02 ii 2 02/01/2040 die i mensis ii annoque mmxl 40 xl 2040}
+test clock-2.1996 {conversion of 2040-02-29} {
+ clock format 2214131696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/2040 12:34:56 die xxix mensis ii annoque mmxl xii h xxxiv m lvi s 20 mm 29 xxix 29 xxix Feb 060 2466214 02 ii 2 02/29/2040 die xxix mensis ii annoque mmxl 40 xl 2040}
+test clock-2.1997 {conversion of 2040-03-01} {
+ clock format 2214218096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2040 12:34:56 die i mensis iii annoque mmxl xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 061 2466215 03 iii 3 03/01/2040 die i mensis iii annoque mmxl 40 xl 2040}
+test clock-2.1998 {conversion of 2040-03-31} {
+ clock format 2216810096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2040 12:34:56 die xxxi mensis iii annoque mmxl xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 091 2466245 03 iii 3 03/31/2040 die xxxi mensis iii annoque mmxl 40 xl 2040}
+test clock-2.1999 {conversion of 2040-04-01} {
+ clock format 2216896496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2040 12:34:56 die i mensis iv annoque mmxl xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 092 2466246 04 iv 4 04/01/2040 die i mensis iv annoque mmxl 40 xl 2040}
+test clock-2.2000 {conversion of 2040-04-30} {
+ clock format 2219402096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2040 12:34:56 die xxx mensis iv annoque mmxl xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 121 2466275 04 iv 4 04/30/2040 die xxx mensis iv annoque mmxl 40 xl 2040}
+test clock-2.2001 {conversion of 2040-05-01} {
+ clock format 2219488496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2040 12:34:56 die i mensis v annoque mmxl xii h xxxiv m lvi s 20 mm 01 i 1 i May 122 2466276 05 v 5 05/01/2040 die i mensis v annoque mmxl 40 xl 2040}
+test clock-2.2002 {conversion of 2040-05-31} {
+ clock format 2222080496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2040 12:34:56 die xxxi mensis v annoque mmxl xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 152 2466306 05 v 5 05/31/2040 die xxxi mensis v annoque mmxl 40 xl 2040}
+test clock-2.2003 {conversion of 2040-06-01} {
+ clock format 2222166896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2040 12:34:56 die i mensis vi annoque mmxl xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 153 2466307 06 vi 6 06/01/2040 die i mensis vi annoque mmxl 40 xl 2040}
+test clock-2.2004 {conversion of 2040-06-30} {
+ clock format 2224672496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2040 12:34:56 die xxx mensis vi annoque mmxl xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 182 2466336 06 vi 6 06/30/2040 die xxx mensis vi annoque mmxl 40 xl 2040}
+test clock-2.2005 {conversion of 2040-07-01} {
+ clock format 2224758896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2040 12:34:56 die i mensis vii annoque mmxl xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 183 2466337 07 vii 7 07/01/2040 die i mensis vii annoque mmxl 40 xl 2040}
+test clock-2.2006 {conversion of 2040-07-31} {
+ clock format 2227350896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2040 12:34:56 die xxxi mensis vii annoque mmxl xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 213 2466367 07 vii 7 07/31/2040 die xxxi mensis vii annoque mmxl 40 xl 2040}
+test clock-2.2007 {conversion of 2040-08-01} {
+ clock format 2227437296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2040 12:34:56 die i mensis viii annoque mmxl xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 214 2466368 08 viii 8 08/01/2040 die i mensis viii annoque mmxl 40 xl 2040}
+test clock-2.2008 {conversion of 2040-08-31} {
+ clock format 2230029296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2040 12:34:56 die xxxi mensis viii annoque mmxl xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 244 2466398 08 viii 8 08/31/2040 die xxxi mensis viii annoque mmxl 40 xl 2040}
+test clock-2.2009 {conversion of 2040-09-01} {
+ clock format 2230115696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2040 12:34:56 die i mensis ix annoque mmxl xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 245 2466399 09 ix 9 09/01/2040 die i mensis ix annoque mmxl 40 xl 2040}
+test clock-2.2010 {conversion of 2040-09-30} {
+ clock format 2232621296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2040 12:34:56 die xxx mensis ix annoque mmxl xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 274 2466428 09 ix 9 09/30/2040 die xxx mensis ix annoque mmxl 40 xl 2040}
+test clock-2.2011 {conversion of 2040-10-01} {
+ clock format 2232707696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2040 12:34:56 die i mensis x annoque mmxl xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 275 2466429 10 x 10 10/01/2040 die i mensis x annoque mmxl 40 xl 2040}
+test clock-2.2012 {conversion of 2040-10-31} {
+ clock format 2235299696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2040 12:34:56 die xxxi mensis x annoque mmxl xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 305 2466459 10 x 10 10/31/2040 die xxxi mensis x annoque mmxl 40 xl 2040}
+test clock-2.2013 {conversion of 2040-11-01} {
+ clock format 2235386096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2040 12:34:56 die i mensis xi annoque mmxl xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 306 2466460 11 xi 11 11/01/2040 die i mensis xi annoque mmxl 40 xl 2040}
+test clock-2.2014 {conversion of 2040-11-30} {
+ clock format 2237891696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2040 12:34:56 die xxx mensis xi annoque mmxl xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 335 2466489 11 xi 11 11/30/2040 die xxx mensis xi annoque mmxl 40 xl 2040}
+test clock-2.2015 {conversion of 2040-12-01} {
+ clock format 2237978096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2040 12:34:56 die i mensis xii annoque mmxl xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 336 2466490 12 xii 12 12/01/2040 die i mensis xii annoque mmxl 40 xl 2040}
+test clock-2.2016 {conversion of 2040-12-31} {
+ clock format 2240570096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2040 12:34:56 die xxxi mensis xii annoque mmxl xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 366 2466520 12 xii 12 12/31/2040 die xxxi mensis xii annoque mmxl 40 xl 2040}
+test clock-2.2017 {conversion of 2041-01-01} {
+ clock format 2240656496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2041 12:34:56 die i mensis i annoque mmxli xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2466521 01 i 1 01/01/2041 die i mensis i annoque mmxli 41 xli 2041}
+test clock-2.2018 {conversion of 2041-01-31} {
+ clock format 2243248496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2041 12:34:56 die xxxi mensis i annoque mmxli xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2466551 01 i 1 01/31/2041 die xxxi mensis i annoque mmxli 41 xli 2041}
+test clock-2.2019 {conversion of 2041-02-01} {
+ clock format 2243334896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2041 12:34:56 die i mensis ii annoque mmxli xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2466552 02 ii 2 02/01/2041 die i mensis ii annoque mmxli 41 xli 2041}
+test clock-2.2020 {conversion of 2041-02-28} {
+ clock format 2245667696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2041 12:34:56 die xxviii mensis ii annoque mmxli xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2466579 02 ii 2 02/28/2041 die xxviii mensis ii annoque mmxli 41 xli 2041}
+test clock-2.2021 {conversion of 2041-03-01} {
+ clock format 2245754096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2041 12:34:56 die i mensis iii annoque mmxli xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2466580 03 iii 3 03/01/2041 die i mensis iii annoque mmxli 41 xli 2041}
+test clock-2.2022 {conversion of 2041-03-31} {
+ clock format 2248346096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2041 12:34:56 die xxxi mensis iii annoque mmxli xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2466610 03 iii 3 03/31/2041 die xxxi mensis iii annoque mmxli 41 xli 2041}
+test clock-2.2023 {conversion of 2041-04-01} {
+ clock format 2248432496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2041 12:34:56 die i mensis iv annoque mmxli xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2466611 04 iv 4 04/01/2041 die i mensis iv annoque mmxli 41 xli 2041}
+test clock-2.2024 {conversion of 2041-04-30} {
+ clock format 2250938096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2041 12:34:56 die xxx mensis iv annoque mmxli xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2466640 04 iv 4 04/30/2041 die xxx mensis iv annoque mmxli 41 xli 2041}
+test clock-2.2025 {conversion of 2041-05-01} {
+ clock format 2251024496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2041 12:34:56 die i mensis v annoque mmxli xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2466641 05 v 5 05/01/2041 die i mensis v annoque mmxli 41 xli 2041}
+test clock-2.2026 {conversion of 2041-05-31} {
+ clock format 2253616496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2041 12:34:56 die xxxi mensis v annoque mmxli xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2466671 05 v 5 05/31/2041 die xxxi mensis v annoque mmxli 41 xli 2041}
+test clock-2.2027 {conversion of 2041-06-01} {
+ clock format 2253702896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2041 12:34:56 die i mensis vi annoque mmxli xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2466672 06 vi 6 06/01/2041 die i mensis vi annoque mmxli 41 xli 2041}
+test clock-2.2028 {conversion of 2041-06-30} {
+ clock format 2256208496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2041 12:34:56 die xxx mensis vi annoque mmxli xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2466701 06 vi 6 06/30/2041 die xxx mensis vi annoque mmxli 41 xli 2041}
+test clock-2.2029 {conversion of 2041-07-01} {
+ clock format 2256294896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2041 12:34:56 die i mensis vii annoque mmxli xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2466702 07 vii 7 07/01/2041 die i mensis vii annoque mmxli 41 xli 2041}
+test clock-2.2030 {conversion of 2041-07-31} {
+ clock format 2258886896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2041 12:34:56 die xxxi mensis vii annoque mmxli xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2466732 07 vii 7 07/31/2041 die xxxi mensis vii annoque mmxli 41 xli 2041}
+test clock-2.2031 {conversion of 2041-08-01} {
+ clock format 2258973296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2041 12:34:56 die i mensis viii annoque mmxli xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2466733 08 viii 8 08/01/2041 die i mensis viii annoque mmxli 41 xli 2041}
+test clock-2.2032 {conversion of 2041-08-31} {
+ clock format 2261565296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2041 12:34:56 die xxxi mensis viii annoque mmxli xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2466763 08 viii 8 08/31/2041 die xxxi mensis viii annoque mmxli 41 xli 2041}
+test clock-2.2033 {conversion of 2041-09-01} {
+ clock format 2261651696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2041 12:34:56 die i mensis ix annoque mmxli xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2466764 09 ix 9 09/01/2041 die i mensis ix annoque mmxli 41 xli 2041}
+test clock-2.2034 {conversion of 2041-09-30} {
+ clock format 2264157296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2041 12:34:56 die xxx mensis ix annoque mmxli xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2466793 09 ix 9 09/30/2041 die xxx mensis ix annoque mmxli 41 xli 2041}
+test clock-2.2035 {conversion of 2041-10-01} {
+ clock format 2264243696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2041 12:34:56 die i mensis x annoque mmxli xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2466794 10 x 10 10/01/2041 die i mensis x annoque mmxli 41 xli 2041}
+test clock-2.2036 {conversion of 2041-10-31} {
+ clock format 2266835696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2041 12:34:56 die xxxi mensis x annoque mmxli xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2466824 10 x 10 10/31/2041 die xxxi mensis x annoque mmxli 41 xli 2041}
+test clock-2.2037 {conversion of 2041-11-01} {
+ clock format 2266922096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2041 12:34:56 die i mensis xi annoque mmxli xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2466825 11 xi 11 11/01/2041 die i mensis xi annoque mmxli 41 xli 2041}
+test clock-2.2038 {conversion of 2041-11-30} {
+ clock format 2269427696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2041 12:34:56 die xxx mensis xi annoque mmxli xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2466854 11 xi 11 11/30/2041 die xxx mensis xi annoque mmxli 41 xli 2041}
+test clock-2.2039 {conversion of 2041-12-01} {
+ clock format 2269514096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2041 12:34:56 die i mensis xii annoque mmxli xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2466855 12 xii 12 12/01/2041 die i mensis xii annoque mmxli 41 xli 2041}
+test clock-2.2040 {conversion of 2041-12-31} {
+ clock format 2272106096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2041 12:34:56 die xxxi mensis xii annoque mmxli xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2466885 12 xii 12 12/31/2041 die xxxi mensis xii annoque mmxli 41 xli 2041}
+test clock-2.2041 {conversion of 2042-01-01} {
+ clock format 2272192496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2042 12:34:56 die i mensis i annoque mmxlii xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2466886 01 i 1 01/01/2042 die i mensis i annoque mmxlii 42 xlii 2042}
+test clock-2.2042 {conversion of 2042-01-31} {
+ clock format 2274784496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2042 12:34:56 die xxxi mensis i annoque mmxlii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2466916 01 i 1 01/31/2042 die xxxi mensis i annoque mmxlii 42 xlii 2042}
+test clock-2.2043 {conversion of 2042-02-01} {
+ clock format 2274870896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2042 12:34:56 die i mensis ii annoque mmxlii xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2466917 02 ii 2 02/01/2042 die i mensis ii annoque mmxlii 42 xlii 2042}
+test clock-2.2044 {conversion of 2042-02-28} {
+ clock format 2277203696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2042 12:34:56 die xxviii mensis ii annoque mmxlii xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2466944 02 ii 2 02/28/2042 die xxviii mensis ii annoque mmxlii 42 xlii 2042}
+test clock-2.2045 {conversion of 2042-03-01} {
+ clock format 2277290096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2042 12:34:56 die i mensis iii annoque mmxlii xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2466945 03 iii 3 03/01/2042 die i mensis iii annoque mmxlii 42 xlii 2042}
+test clock-2.2046 {conversion of 2042-03-31} {
+ clock format 2279882096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2042 12:34:56 die xxxi mensis iii annoque mmxlii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2466975 03 iii 3 03/31/2042 die xxxi mensis iii annoque mmxlii 42 xlii 2042}
+test clock-2.2047 {conversion of 2042-04-01} {
+ clock format 2279968496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2042 12:34:56 die i mensis iv annoque mmxlii xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2466976 04 iv 4 04/01/2042 die i mensis iv annoque mmxlii 42 xlii 2042}
+test clock-2.2048 {conversion of 2042-04-30} {
+ clock format 2282474096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2042 12:34:56 die xxx mensis iv annoque mmxlii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2467005 04 iv 4 04/30/2042 die xxx mensis iv annoque mmxlii 42 xlii 2042}
+test clock-2.2049 {conversion of 2042-05-01} {
+ clock format 2282560496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2042 12:34:56 die i mensis v annoque mmxlii xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2467006 05 v 5 05/01/2042 die i mensis v annoque mmxlii 42 xlii 2042}
+test clock-2.2050 {conversion of 2042-05-31} {
+ clock format 2285152496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2042 12:34:56 die xxxi mensis v annoque mmxlii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2467036 05 v 5 05/31/2042 die xxxi mensis v annoque mmxlii 42 xlii 2042}
+test clock-2.2051 {conversion of 2042-06-01} {
+ clock format 2285238896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2042 12:34:56 die i mensis vi annoque mmxlii xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2467037 06 vi 6 06/01/2042 die i mensis vi annoque mmxlii 42 xlii 2042}
+test clock-2.2052 {conversion of 2042-06-30} {
+ clock format 2287744496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2042 12:34:56 die xxx mensis vi annoque mmxlii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2467066 06 vi 6 06/30/2042 die xxx mensis vi annoque mmxlii 42 xlii 2042}
+test clock-2.2053 {conversion of 2042-07-01} {
+ clock format 2287830896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2042 12:34:56 die i mensis vii annoque mmxlii xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2467067 07 vii 7 07/01/2042 die i mensis vii annoque mmxlii 42 xlii 2042}
+test clock-2.2054 {conversion of 2042-07-31} {
+ clock format 2290422896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2042 12:34:56 die xxxi mensis vii annoque mmxlii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2467097 07 vii 7 07/31/2042 die xxxi mensis vii annoque mmxlii 42 xlii 2042}
+test clock-2.2055 {conversion of 2042-08-01} {
+ clock format 2290509296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2042 12:34:56 die i mensis viii annoque mmxlii xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2467098 08 viii 8 08/01/2042 die i mensis viii annoque mmxlii 42 xlii 2042}
+test clock-2.2056 {conversion of 2042-08-31} {
+ clock format 2293101296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2042 12:34:56 die xxxi mensis viii annoque mmxlii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2467128 08 viii 8 08/31/2042 die xxxi mensis viii annoque mmxlii 42 xlii 2042}
+test clock-2.2057 {conversion of 2042-09-01} {
+ clock format 2293187696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2042 12:34:56 die i mensis ix annoque mmxlii xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2467129 09 ix 9 09/01/2042 die i mensis ix annoque mmxlii 42 xlii 2042}
+test clock-2.2058 {conversion of 2042-09-30} {
+ clock format 2295693296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2042 12:34:56 die xxx mensis ix annoque mmxlii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2467158 09 ix 9 09/30/2042 die xxx mensis ix annoque mmxlii 42 xlii 2042}
+test clock-2.2059 {conversion of 2042-10-01} {
+ clock format 2295779696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2042 12:34:56 die i mensis x annoque mmxlii xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2467159 10 x 10 10/01/2042 die i mensis x annoque mmxlii 42 xlii 2042}
+test clock-2.2060 {conversion of 2042-10-31} {
+ clock format 2298371696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2042 12:34:56 die xxxi mensis x annoque mmxlii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2467189 10 x 10 10/31/2042 die xxxi mensis x annoque mmxlii 42 xlii 2042}
+test clock-2.2061 {conversion of 2042-11-01} {
+ clock format 2298458096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2042 12:34:56 die i mensis xi annoque mmxlii xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2467190 11 xi 11 11/01/2042 die i mensis xi annoque mmxlii 42 xlii 2042}
+test clock-2.2062 {conversion of 2042-11-30} {
+ clock format 2300963696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2042 12:34:56 die xxx mensis xi annoque mmxlii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2467219 11 xi 11 11/30/2042 die xxx mensis xi annoque mmxlii 42 xlii 2042}
+test clock-2.2063 {conversion of 2042-12-01} {
+ clock format 2301050096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2042 12:34:56 die i mensis xii annoque mmxlii xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2467220 12 xii 12 12/01/2042 die i mensis xii annoque mmxlii 42 xlii 2042}
+test clock-2.2064 {conversion of 2042-12-31} {
+ clock format 2303642096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2042 12:34:56 die xxxi mensis xii annoque mmxlii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2467250 12 xii 12 12/31/2042 die xxxi mensis xii annoque mmxlii 42 xlii 2042}
+test clock-2.2065 {conversion of 2043-01-01} {
+ clock format 2303728496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2043 12:34:56 die i mensis i annoque mmxliii xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2467251 01 i 1 01/01/2043 die i mensis i annoque mmxliii 43 xliii 2043}
+test clock-2.2066 {conversion of 2043-01-31} {
+ clock format 2306320496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2043 12:34:56 die xxxi mensis i annoque mmxliii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2467281 01 i 1 01/31/2043 die xxxi mensis i annoque mmxliii 43 xliii 2043}
+test clock-2.2067 {conversion of 2043-02-01} {
+ clock format 2306406896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2043 12:34:56 die i mensis ii annoque mmxliii xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2467282 02 ii 2 02/01/2043 die i mensis ii annoque mmxliii 43 xliii 2043}
+test clock-2.2068 {conversion of 2043-02-28} {
+ clock format 2308739696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2043 12:34:56 die xxviii mensis ii annoque mmxliii xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2467309 02 ii 2 02/28/2043 die xxviii mensis ii annoque mmxliii 43 xliii 2043}
+test clock-2.2069 {conversion of 2043-03-01} {
+ clock format 2308826096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2043 12:34:56 die i mensis iii annoque mmxliii xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2467310 03 iii 3 03/01/2043 die i mensis iii annoque mmxliii 43 xliii 2043}
+test clock-2.2070 {conversion of 2043-03-31} {
+ clock format 2311418096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2043 12:34:56 die xxxi mensis iii annoque mmxliii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2467340 03 iii 3 03/31/2043 die xxxi mensis iii annoque mmxliii 43 xliii 2043}
+test clock-2.2071 {conversion of 2043-04-01} {
+ clock format 2311504496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2043 12:34:56 die i mensis iv annoque mmxliii xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2467341 04 iv 4 04/01/2043 die i mensis iv annoque mmxliii 43 xliii 2043}
+test clock-2.2072 {conversion of 2043-04-30} {
+ clock format 2314010096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2043 12:34:56 die xxx mensis iv annoque mmxliii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2467370 04 iv 4 04/30/2043 die xxx mensis iv annoque mmxliii 43 xliii 2043}
+test clock-2.2073 {conversion of 2043-05-01} {
+ clock format 2314096496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2043 12:34:56 die i mensis v annoque mmxliii xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2467371 05 v 5 05/01/2043 die i mensis v annoque mmxliii 43 xliii 2043}
+test clock-2.2074 {conversion of 2043-05-31} {
+ clock format 2316688496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2043 12:34:56 die xxxi mensis v annoque mmxliii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2467401 05 v 5 05/31/2043 die xxxi mensis v annoque mmxliii 43 xliii 2043}
+test clock-2.2075 {conversion of 2043-06-01} {
+ clock format 2316774896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2043 12:34:56 die i mensis vi annoque mmxliii xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2467402 06 vi 6 06/01/2043 die i mensis vi annoque mmxliii 43 xliii 2043}
+test clock-2.2076 {conversion of 2043-06-30} {
+ clock format 2319280496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2043 12:34:56 die xxx mensis vi annoque mmxliii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2467431 06 vi 6 06/30/2043 die xxx mensis vi annoque mmxliii 43 xliii 2043}
+test clock-2.2077 {conversion of 2043-07-01} {
+ clock format 2319366896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2043 12:34:56 die i mensis vii annoque mmxliii xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2467432 07 vii 7 07/01/2043 die i mensis vii annoque mmxliii 43 xliii 2043}
+test clock-2.2078 {conversion of 2043-07-31} {
+ clock format 2321958896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2043 12:34:56 die xxxi mensis vii annoque mmxliii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2467462 07 vii 7 07/31/2043 die xxxi mensis vii annoque mmxliii 43 xliii 2043}
+test clock-2.2079 {conversion of 2043-08-01} {
+ clock format 2322045296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2043 12:34:56 die i mensis viii annoque mmxliii xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2467463 08 viii 8 08/01/2043 die i mensis viii annoque mmxliii 43 xliii 2043}
+test clock-2.2080 {conversion of 2043-08-31} {
+ clock format 2324637296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2043 12:34:56 die xxxi mensis viii annoque mmxliii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2467493 08 viii 8 08/31/2043 die xxxi mensis viii annoque mmxliii 43 xliii 2043}
+test clock-2.2081 {conversion of 2043-09-01} {
+ clock format 2324723696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2043 12:34:56 die i mensis ix annoque mmxliii xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2467494 09 ix 9 09/01/2043 die i mensis ix annoque mmxliii 43 xliii 2043}
+test clock-2.2082 {conversion of 2043-09-30} {
+ clock format 2327229296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2043 12:34:56 die xxx mensis ix annoque mmxliii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2467523 09 ix 9 09/30/2043 die xxx mensis ix annoque mmxliii 43 xliii 2043}
+test clock-2.2083 {conversion of 2043-10-01} {
+ clock format 2327315696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2043 12:34:56 die i mensis x annoque mmxliii xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2467524 10 x 10 10/01/2043 die i mensis x annoque mmxliii 43 xliii 2043}
+test clock-2.2084 {conversion of 2043-10-31} {
+ clock format 2329907696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2043 12:34:56 die xxxi mensis x annoque mmxliii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2467554 10 x 10 10/31/2043 die xxxi mensis x annoque mmxliii 43 xliii 2043}
+test clock-2.2085 {conversion of 2043-11-01} {
+ clock format 2329994096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2043 12:34:56 die i mensis xi annoque mmxliii xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2467555 11 xi 11 11/01/2043 die i mensis xi annoque mmxliii 43 xliii 2043}
+test clock-2.2086 {conversion of 2043-11-30} {
+ clock format 2332499696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2043 12:34:56 die xxx mensis xi annoque mmxliii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2467584 11 xi 11 11/30/2043 die xxx mensis xi annoque mmxliii 43 xliii 2043}
+test clock-2.2087 {conversion of 2043-12-01} {
+ clock format 2332586096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2043 12:34:56 die i mensis xii annoque mmxliii xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2467585 12 xii 12 12/01/2043 die i mensis xii annoque mmxliii 43 xliii 2043}
+test clock-2.2088 {conversion of 2043-12-31} {
+ clock format 2335178096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2043 12:34:56 die xxxi mensis xii annoque mmxliii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2467615 12 xii 12 12/31/2043 die xxxi mensis xii annoque mmxliii 43 xliii 2043}
+test clock-2.2089 {conversion of 2044-01-01} {
+ clock format 2335264496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2044 12:34:56 die i mensis i annoque mmxliv xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2467616 01 i 1 01/01/2044 die i mensis i annoque mmxliv 44 xliv 2044}
+test clock-2.2090 {conversion of 2044-01-31} {
+ clock format 2337856496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2044 12:34:56 die xxxi mensis i annoque mmxliv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2467646 01 i 1 01/31/2044 die xxxi mensis i annoque mmxliv 44 xliv 2044}
+test clock-2.2091 {conversion of 2044-02-01} {
+ clock format 2337942896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2044 12:34:56 die i mensis ii annoque mmxliv xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2467647 02 ii 2 02/01/2044 die i mensis ii annoque mmxliv 44 xliv 2044}
+test clock-2.2092 {conversion of 2044-02-29} {
+ clock format 2340362096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/2044 12:34:56 die xxix mensis ii annoque mmxliv xii h xxxiv m lvi s 20 mm 29 xxix 29 xxix Feb 060 2467675 02 ii 2 02/29/2044 die xxix mensis ii annoque mmxliv 44 xliv 2044}
+test clock-2.2093 {conversion of 2044-03-01} {
+ clock format 2340448496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2044 12:34:56 die i mensis iii annoque mmxliv xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 061 2467676 03 iii 3 03/01/2044 die i mensis iii annoque mmxliv 44 xliv 2044}
+test clock-2.2094 {conversion of 2044-03-31} {
+ clock format 2343040496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2044 12:34:56 die xxxi mensis iii annoque mmxliv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 091 2467706 03 iii 3 03/31/2044 die xxxi mensis iii annoque mmxliv 44 xliv 2044}
+test clock-2.2095 {conversion of 2044-04-01} {
+ clock format 2343126896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2044 12:34:56 die i mensis iv annoque mmxliv xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 092 2467707 04 iv 4 04/01/2044 die i mensis iv annoque mmxliv 44 xliv 2044}
+test clock-2.2096 {conversion of 2044-04-30} {
+ clock format 2345632496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2044 12:34:56 die xxx mensis iv annoque mmxliv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 121 2467736 04 iv 4 04/30/2044 die xxx mensis iv annoque mmxliv 44 xliv 2044}
+test clock-2.2097 {conversion of 2044-05-01} {
+ clock format 2345718896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2044 12:34:56 die i mensis v annoque mmxliv xii h xxxiv m lvi s 20 mm 01 i 1 i May 122 2467737 05 v 5 05/01/2044 die i mensis v annoque mmxliv 44 xliv 2044}
+test clock-2.2098 {conversion of 2044-05-31} {
+ clock format 2348310896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2044 12:34:56 die xxxi mensis v annoque mmxliv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 152 2467767 05 v 5 05/31/2044 die xxxi mensis v annoque mmxliv 44 xliv 2044}
+test clock-2.2099 {conversion of 2044-06-01} {
+ clock format 2348397296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2044 12:34:56 die i mensis vi annoque mmxliv xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 153 2467768 06 vi 6 06/01/2044 die i mensis vi annoque mmxliv 44 xliv 2044}
+test clock-2.2100 {conversion of 2044-06-30} {
+ clock format 2350902896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2044 12:34:56 die xxx mensis vi annoque mmxliv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 182 2467797 06 vi 6 06/30/2044 die xxx mensis vi annoque mmxliv 44 xliv 2044}
+test clock-2.2101 {conversion of 2044-07-01} {
+ clock format 2350989296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2044 12:34:56 die i mensis vii annoque mmxliv xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 183 2467798 07 vii 7 07/01/2044 die i mensis vii annoque mmxliv 44 xliv 2044}
+test clock-2.2102 {conversion of 2044-07-31} {
+ clock format 2353581296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2044 12:34:56 die xxxi mensis vii annoque mmxliv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 213 2467828 07 vii 7 07/31/2044 die xxxi mensis vii annoque mmxliv 44 xliv 2044}
+test clock-2.2103 {conversion of 2044-08-01} {
+ clock format 2353667696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2044 12:34:56 die i mensis viii annoque mmxliv xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 214 2467829 08 viii 8 08/01/2044 die i mensis viii annoque mmxliv 44 xliv 2044}
+test clock-2.2104 {conversion of 2044-08-31} {
+ clock format 2356259696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2044 12:34:56 die xxxi mensis viii annoque mmxliv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 244 2467859 08 viii 8 08/31/2044 die xxxi mensis viii annoque mmxliv 44 xliv 2044}
+test clock-2.2105 {conversion of 2044-09-01} {
+ clock format 2356346096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2044 12:34:56 die i mensis ix annoque mmxliv xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 245 2467860 09 ix 9 09/01/2044 die i mensis ix annoque mmxliv 44 xliv 2044}
+test clock-2.2106 {conversion of 2044-09-30} {
+ clock format 2358851696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2044 12:34:56 die xxx mensis ix annoque mmxliv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 274 2467889 09 ix 9 09/30/2044 die xxx mensis ix annoque mmxliv 44 xliv 2044}
+test clock-2.2107 {conversion of 2044-10-01} {
+ clock format 2358938096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2044 12:34:56 die i mensis x annoque mmxliv xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 275 2467890 10 x 10 10/01/2044 die i mensis x annoque mmxliv 44 xliv 2044}
+test clock-2.2108 {conversion of 2044-10-31} {
+ clock format 2361530096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2044 12:34:56 die xxxi mensis x annoque mmxliv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 305 2467920 10 x 10 10/31/2044 die xxxi mensis x annoque mmxliv 44 xliv 2044}
+test clock-2.2109 {conversion of 2044-11-01} {
+ clock format 2361616496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2044 12:34:56 die i mensis xi annoque mmxliv xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 306 2467921 11 xi 11 11/01/2044 die i mensis xi annoque mmxliv 44 xliv 2044}
+test clock-2.2110 {conversion of 2044-11-30} {
+ clock format 2364122096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2044 12:34:56 die xxx mensis xi annoque mmxliv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 335 2467950 11 xi 11 11/30/2044 die xxx mensis xi annoque mmxliv 44 xliv 2044}
+test clock-2.2111 {conversion of 2044-12-01} {
+ clock format 2364208496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2044 12:34:56 die i mensis xii annoque mmxliv xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 336 2467951 12 xii 12 12/01/2044 die i mensis xii annoque mmxliv 44 xliv 2044}
+test clock-2.2112 {conversion of 2044-12-31} {
+ clock format 2366800496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2044 12:34:56 die xxxi mensis xii annoque mmxliv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 366 2467981 12 xii 12 12/31/2044 die xxxi mensis xii annoque mmxliv 44 xliv 2044}
+test clock-2.2113 {conversion of 2045-01-01} {
+ clock format 2366886896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2045 12:34:56 die i mensis i annoque mmxlv xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2467982 01 i 1 01/01/2045 die i mensis i annoque mmxlv 45 xlv 2045}
+test clock-2.2114 {conversion of 2045-01-31} {
+ clock format 2369478896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2045 12:34:56 die xxxi mensis i annoque mmxlv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2468012 01 i 1 01/31/2045 die xxxi mensis i annoque mmxlv 45 xlv 2045}
+test clock-2.2115 {conversion of 2045-02-01} {
+ clock format 2369565296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2045 12:34:56 die i mensis ii annoque mmxlv xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2468013 02 ii 2 02/01/2045 die i mensis ii annoque mmxlv 45 xlv 2045}
+test clock-2.2116 {conversion of 2045-02-28} {
+ clock format 2371898096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2045 12:34:56 die xxviii mensis ii annoque mmxlv xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2468040 02 ii 2 02/28/2045 die xxviii mensis ii annoque mmxlv 45 xlv 2045}
+test clock-2.2117 {conversion of 2045-03-01} {
+ clock format 2371984496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2045 12:34:56 die i mensis iii annoque mmxlv xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2468041 03 iii 3 03/01/2045 die i mensis iii annoque mmxlv 45 xlv 2045}
+test clock-2.2118 {conversion of 2045-03-31} {
+ clock format 2374576496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2045 12:34:56 die xxxi mensis iii annoque mmxlv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2468071 03 iii 3 03/31/2045 die xxxi mensis iii annoque mmxlv 45 xlv 2045}
+test clock-2.2119 {conversion of 2045-04-01} {
+ clock format 2374662896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2045 12:34:56 die i mensis iv annoque mmxlv xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2468072 04 iv 4 04/01/2045 die i mensis iv annoque mmxlv 45 xlv 2045}
+test clock-2.2120 {conversion of 2045-04-30} {
+ clock format 2377168496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2045 12:34:56 die xxx mensis iv annoque mmxlv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2468101 04 iv 4 04/30/2045 die xxx mensis iv annoque mmxlv 45 xlv 2045}
+test clock-2.2121 {conversion of 2045-05-01} {
+ clock format 2377254896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2045 12:34:56 die i mensis v annoque mmxlv xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2468102 05 v 5 05/01/2045 die i mensis v annoque mmxlv 45 xlv 2045}
+test clock-2.2122 {conversion of 2045-05-31} {
+ clock format 2379846896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2045 12:34:56 die xxxi mensis v annoque mmxlv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2468132 05 v 5 05/31/2045 die xxxi mensis v annoque mmxlv 45 xlv 2045}
+test clock-2.2123 {conversion of 2045-06-01} {
+ clock format 2379933296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2045 12:34:56 die i mensis vi annoque mmxlv xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2468133 06 vi 6 06/01/2045 die i mensis vi annoque mmxlv 45 xlv 2045}
+test clock-2.2124 {conversion of 2045-06-30} {
+ clock format 2382438896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2045 12:34:56 die xxx mensis vi annoque mmxlv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2468162 06 vi 6 06/30/2045 die xxx mensis vi annoque mmxlv 45 xlv 2045}
+test clock-2.2125 {conversion of 2045-07-01} {
+ clock format 2382525296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2045 12:34:56 die i mensis vii annoque mmxlv xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2468163 07 vii 7 07/01/2045 die i mensis vii annoque mmxlv 45 xlv 2045}
+test clock-2.2126 {conversion of 2045-07-31} {
+ clock format 2385117296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2045 12:34:56 die xxxi mensis vii annoque mmxlv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2468193 07 vii 7 07/31/2045 die xxxi mensis vii annoque mmxlv 45 xlv 2045}
+test clock-2.2127 {conversion of 2045-08-01} {
+ clock format 2385203696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2045 12:34:56 die i mensis viii annoque mmxlv xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2468194 08 viii 8 08/01/2045 die i mensis viii annoque mmxlv 45 xlv 2045}
+test clock-2.2128 {conversion of 2045-08-31} {
+ clock format 2387795696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2045 12:34:56 die xxxi mensis viii annoque mmxlv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2468224 08 viii 8 08/31/2045 die xxxi mensis viii annoque mmxlv 45 xlv 2045}
+test clock-2.2129 {conversion of 2045-09-01} {
+ clock format 2387882096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2045 12:34:56 die i mensis ix annoque mmxlv xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2468225 09 ix 9 09/01/2045 die i mensis ix annoque mmxlv 45 xlv 2045}
+test clock-2.2130 {conversion of 2045-09-30} {
+ clock format 2390387696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2045 12:34:56 die xxx mensis ix annoque mmxlv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2468254 09 ix 9 09/30/2045 die xxx mensis ix annoque mmxlv 45 xlv 2045}
+test clock-2.2131 {conversion of 2045-10-01} {
+ clock format 2390474096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2045 12:34:56 die i mensis x annoque mmxlv xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2468255 10 x 10 10/01/2045 die i mensis x annoque mmxlv 45 xlv 2045}
+test clock-2.2132 {conversion of 2045-10-31} {
+ clock format 2393066096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2045 12:34:56 die xxxi mensis x annoque mmxlv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2468285 10 x 10 10/31/2045 die xxxi mensis x annoque mmxlv 45 xlv 2045}
+test clock-2.2133 {conversion of 2045-11-01} {
+ clock format 2393152496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2045 12:34:56 die i mensis xi annoque mmxlv xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2468286 11 xi 11 11/01/2045 die i mensis xi annoque mmxlv 45 xlv 2045}
+test clock-2.2134 {conversion of 2045-11-30} {
+ clock format 2395658096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2045 12:34:56 die xxx mensis xi annoque mmxlv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2468315 11 xi 11 11/30/2045 die xxx mensis xi annoque mmxlv 45 xlv 2045}
+test clock-2.2135 {conversion of 2045-12-01} {
+ clock format 2395744496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2045 12:34:56 die i mensis xii annoque mmxlv xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2468316 12 xii 12 12/01/2045 die i mensis xii annoque mmxlv 45 xlv 2045}
+test clock-2.2136 {conversion of 2045-12-31} {
+ clock format 2398336496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2045 12:34:56 die xxxi mensis xii annoque mmxlv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2468346 12 xii 12 12/31/2045 die xxxi mensis xii annoque mmxlv 45 xlv 2045}
+test clock-2.2137 {conversion of 2046-01-01} {
+ clock format 2398422896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2046 12:34:56 die i mensis i annoque mmxlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2468347 01 i 1 01/01/2046 die i mensis i annoque mmxlvi 46 xlvi 2046}
+test clock-2.2138 {conversion of 2046-01-31} {
+ clock format 2401014896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2046 12:34:56 die xxxi mensis i annoque mmxlvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2468377 01 i 1 01/31/2046 die xxxi mensis i annoque mmxlvi 46 xlvi 2046}
+test clock-2.2139 {conversion of 2046-02-01} {
+ clock format 2401101296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2046 12:34:56 die i mensis ii annoque mmxlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2468378 02 ii 2 02/01/2046 die i mensis ii annoque mmxlvi 46 xlvi 2046}
+test clock-2.2140 {conversion of 2046-02-28} {
+ clock format 2403434096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2046 12:34:56 die xxviii mensis ii annoque mmxlvi xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2468405 02 ii 2 02/28/2046 die xxviii mensis ii annoque mmxlvi 46 xlvi 2046}
+test clock-2.2141 {conversion of 2046-03-01} {
+ clock format 2403520496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2046 12:34:56 die i mensis iii annoque mmxlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2468406 03 iii 3 03/01/2046 die i mensis iii annoque mmxlvi 46 xlvi 2046}
+test clock-2.2142 {conversion of 2046-03-31} {
+ clock format 2406112496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2046 12:34:56 die xxxi mensis iii annoque mmxlvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2468436 03 iii 3 03/31/2046 die xxxi mensis iii annoque mmxlvi 46 xlvi 2046}
+test clock-2.2143 {conversion of 2046-04-01} {
+ clock format 2406198896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2046 12:34:56 die i mensis iv annoque mmxlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2468437 04 iv 4 04/01/2046 die i mensis iv annoque mmxlvi 46 xlvi 2046}
+test clock-2.2144 {conversion of 2046-04-30} {
+ clock format 2408704496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2046 12:34:56 die xxx mensis iv annoque mmxlvi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2468466 04 iv 4 04/30/2046 die xxx mensis iv annoque mmxlvi 46 xlvi 2046}
+test clock-2.2145 {conversion of 2046-05-01} {
+ clock format 2408790896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2046 12:34:56 die i mensis v annoque mmxlvi xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2468467 05 v 5 05/01/2046 die i mensis v annoque mmxlvi 46 xlvi 2046}
+test clock-2.2146 {conversion of 2046-05-31} {
+ clock format 2411382896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2046 12:34:56 die xxxi mensis v annoque mmxlvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2468497 05 v 5 05/31/2046 die xxxi mensis v annoque mmxlvi 46 xlvi 2046}
+test clock-2.2147 {conversion of 2046-06-01} {
+ clock format 2411469296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2046 12:34:56 die i mensis vi annoque mmxlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2468498 06 vi 6 06/01/2046 die i mensis vi annoque mmxlvi 46 xlvi 2046}
+test clock-2.2148 {conversion of 2046-06-30} {
+ clock format 2413974896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2046 12:34:56 die xxx mensis vi annoque mmxlvi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2468527 06 vi 6 06/30/2046 die xxx mensis vi annoque mmxlvi 46 xlvi 2046}
+test clock-2.2149 {conversion of 2046-07-01} {
+ clock format 2414061296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2046 12:34:56 die i mensis vii annoque mmxlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2468528 07 vii 7 07/01/2046 die i mensis vii annoque mmxlvi 46 xlvi 2046}
+test clock-2.2150 {conversion of 2046-07-31} {
+ clock format 2416653296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2046 12:34:56 die xxxi mensis vii annoque mmxlvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2468558 07 vii 7 07/31/2046 die xxxi mensis vii annoque mmxlvi 46 xlvi 2046}
+test clock-2.2151 {conversion of 2046-08-01} {
+ clock format 2416739696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2046 12:34:56 die i mensis viii annoque mmxlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2468559 08 viii 8 08/01/2046 die i mensis viii annoque mmxlvi 46 xlvi 2046}
+test clock-2.2152 {conversion of 2046-08-31} {
+ clock format 2419331696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2046 12:34:56 die xxxi mensis viii annoque mmxlvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2468589 08 viii 8 08/31/2046 die xxxi mensis viii annoque mmxlvi 46 xlvi 2046}
+test clock-2.2153 {conversion of 2046-09-01} {
+ clock format 2419418096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2046 12:34:56 die i mensis ix annoque mmxlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2468590 09 ix 9 09/01/2046 die i mensis ix annoque mmxlvi 46 xlvi 2046}
+test clock-2.2154 {conversion of 2046-09-30} {
+ clock format 2421923696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2046 12:34:56 die xxx mensis ix annoque mmxlvi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2468619 09 ix 9 09/30/2046 die xxx mensis ix annoque mmxlvi 46 xlvi 2046}
+test clock-2.2155 {conversion of 2046-10-01} {
+ clock format 2422010096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2046 12:34:56 die i mensis x annoque mmxlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2468620 10 x 10 10/01/2046 die i mensis x annoque mmxlvi 46 xlvi 2046}
+test clock-2.2156 {conversion of 2046-10-31} {
+ clock format 2424602096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2046 12:34:56 die xxxi mensis x annoque mmxlvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2468650 10 x 10 10/31/2046 die xxxi mensis x annoque mmxlvi 46 xlvi 2046}
+test clock-2.2157 {conversion of 2046-11-01} {
+ clock format 2424688496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2046 12:34:56 die i mensis xi annoque mmxlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2468651 11 xi 11 11/01/2046 die i mensis xi annoque mmxlvi 46 xlvi 2046}
+test clock-2.2158 {conversion of 2046-11-30} {
+ clock format 2427194096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2046 12:34:56 die xxx mensis xi annoque mmxlvi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2468680 11 xi 11 11/30/2046 die xxx mensis xi annoque mmxlvi 46 xlvi 2046}
+test clock-2.2159 {conversion of 2046-12-01} {
+ clock format 2427280496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2046 12:34:56 die i mensis xii annoque mmxlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2468681 12 xii 12 12/01/2046 die i mensis xii annoque mmxlvi 46 xlvi 2046}
+test clock-2.2160 {conversion of 2046-12-31} {
+ clock format 2429872496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2046 12:34:56 die xxxi mensis xii annoque mmxlvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2468711 12 xii 12 12/31/2046 die xxxi mensis xii annoque mmxlvi 46 xlvi 2046}
+test clock-2.2161 {conversion of 2047-01-01} {
+ clock format 2429958896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2047 12:34:56 die i mensis i annoque mmxlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2468712 01 i 1 01/01/2047 die i mensis i annoque mmxlvii 47 xlvii 2047}
+test clock-2.2162 {conversion of 2047-01-31} {
+ clock format 2432550896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2047 12:34:56 die xxxi mensis i annoque mmxlvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2468742 01 i 1 01/31/2047 die xxxi mensis i annoque mmxlvii 47 xlvii 2047}
+test clock-2.2163 {conversion of 2047-02-01} {
+ clock format 2432637296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2047 12:34:56 die i mensis ii annoque mmxlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2468743 02 ii 2 02/01/2047 die i mensis ii annoque mmxlvii 47 xlvii 2047}
+test clock-2.2164 {conversion of 2047-02-28} {
+ clock format 2434970096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2047 12:34:56 die xxviii mensis ii annoque mmxlvii xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2468770 02 ii 2 02/28/2047 die xxviii mensis ii annoque mmxlvii 47 xlvii 2047}
+test clock-2.2165 {conversion of 2047-03-01} {
+ clock format 2435056496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2047 12:34:56 die i mensis iii annoque mmxlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2468771 03 iii 3 03/01/2047 die i mensis iii annoque mmxlvii 47 xlvii 2047}
+test clock-2.2166 {conversion of 2047-03-31} {
+ clock format 2437648496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2047 12:34:56 die xxxi mensis iii annoque mmxlvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2468801 03 iii 3 03/31/2047 die xxxi mensis iii annoque mmxlvii 47 xlvii 2047}
+test clock-2.2167 {conversion of 2047-04-01} {
+ clock format 2437734896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2047 12:34:56 die i mensis iv annoque mmxlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2468802 04 iv 4 04/01/2047 die i mensis iv annoque mmxlvii 47 xlvii 2047}
+test clock-2.2168 {conversion of 2047-04-30} {
+ clock format 2440240496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2047 12:34:56 die xxx mensis iv annoque mmxlvii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2468831 04 iv 4 04/30/2047 die xxx mensis iv annoque mmxlvii 47 xlvii 2047}
+test clock-2.2169 {conversion of 2047-05-01} {
+ clock format 2440326896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2047 12:34:56 die i mensis v annoque mmxlvii xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2468832 05 v 5 05/01/2047 die i mensis v annoque mmxlvii 47 xlvii 2047}
+test clock-2.2170 {conversion of 2047-05-31} {
+ clock format 2442918896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2047 12:34:56 die xxxi mensis v annoque mmxlvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2468862 05 v 5 05/31/2047 die xxxi mensis v annoque mmxlvii 47 xlvii 2047}
+test clock-2.2171 {conversion of 2047-06-01} {
+ clock format 2443005296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2047 12:34:56 die i mensis vi annoque mmxlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2468863 06 vi 6 06/01/2047 die i mensis vi annoque mmxlvii 47 xlvii 2047}
+test clock-2.2172 {conversion of 2047-06-30} {
+ clock format 2445510896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2047 12:34:56 die xxx mensis vi annoque mmxlvii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2468892 06 vi 6 06/30/2047 die xxx mensis vi annoque mmxlvii 47 xlvii 2047}
+test clock-2.2173 {conversion of 2047-07-01} {
+ clock format 2445597296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2047 12:34:56 die i mensis vii annoque mmxlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2468893 07 vii 7 07/01/2047 die i mensis vii annoque mmxlvii 47 xlvii 2047}
+test clock-2.2174 {conversion of 2047-07-31} {
+ clock format 2448189296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2047 12:34:56 die xxxi mensis vii annoque mmxlvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2468923 07 vii 7 07/31/2047 die xxxi mensis vii annoque mmxlvii 47 xlvii 2047}
+test clock-2.2175 {conversion of 2047-08-01} {
+ clock format 2448275696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2047 12:34:56 die i mensis viii annoque mmxlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2468924 08 viii 8 08/01/2047 die i mensis viii annoque mmxlvii 47 xlvii 2047}
+test clock-2.2176 {conversion of 2047-08-31} {
+ clock format 2450867696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2047 12:34:56 die xxxi mensis viii annoque mmxlvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2468954 08 viii 8 08/31/2047 die xxxi mensis viii annoque mmxlvii 47 xlvii 2047}
+test clock-2.2177 {conversion of 2047-09-01} {
+ clock format 2450954096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2047 12:34:56 die i mensis ix annoque mmxlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2468955 09 ix 9 09/01/2047 die i mensis ix annoque mmxlvii 47 xlvii 2047}
+test clock-2.2178 {conversion of 2047-09-30} {
+ clock format 2453459696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2047 12:34:56 die xxx mensis ix annoque mmxlvii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2468984 09 ix 9 09/30/2047 die xxx mensis ix annoque mmxlvii 47 xlvii 2047}
+test clock-2.2179 {conversion of 2047-10-01} {
+ clock format 2453546096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2047 12:34:56 die i mensis x annoque mmxlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2468985 10 x 10 10/01/2047 die i mensis x annoque mmxlvii 47 xlvii 2047}
+test clock-2.2180 {conversion of 2047-10-31} {
+ clock format 2456138096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2047 12:34:56 die xxxi mensis x annoque mmxlvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2469015 10 x 10 10/31/2047 die xxxi mensis x annoque mmxlvii 47 xlvii 2047}
+test clock-2.2181 {conversion of 2047-11-01} {
+ clock format 2456224496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2047 12:34:56 die i mensis xi annoque mmxlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2469016 11 xi 11 11/01/2047 die i mensis xi annoque mmxlvii 47 xlvii 2047}
+test clock-2.2182 {conversion of 2047-11-30} {
+ clock format 2458730096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2047 12:34:56 die xxx mensis xi annoque mmxlvii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2469045 11 xi 11 11/30/2047 die xxx mensis xi annoque mmxlvii 47 xlvii 2047}
+test clock-2.2183 {conversion of 2047-12-01} {
+ clock format 2458816496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2047 12:34:56 die i mensis xii annoque mmxlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2469046 12 xii 12 12/01/2047 die i mensis xii annoque mmxlvii 47 xlvii 2047}
+test clock-2.2184 {conversion of 2047-12-31} {
+ clock format 2461408496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2047 12:34:56 die xxxi mensis xii annoque mmxlvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2469076 12 xii 12 12/31/2047 die xxxi mensis xii annoque mmxlvii 47 xlvii 2047}
+test clock-2.2185 {conversion of 2048-01-01} {
+ clock format 2461494896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2048 12:34:56 die i mensis i annoque mmxlviii xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2469077 01 i 1 01/01/2048 die i mensis i annoque mmxlviii 48 xlviii 2048}
+test clock-2.2186 {conversion of 2048-01-31} {
+ clock format 2464086896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2048 12:34:56 die xxxi mensis i annoque mmxlviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2469107 01 i 1 01/31/2048 die xxxi mensis i annoque mmxlviii 48 xlviii 2048}
+test clock-2.2187 {conversion of 2048-02-01} {
+ clock format 2464173296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2048 12:34:56 die i mensis ii annoque mmxlviii xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2469108 02 ii 2 02/01/2048 die i mensis ii annoque mmxlviii 48 xlviii 2048}
+test clock-2.2188 {conversion of 2048-02-29} {
+ clock format 2466592496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/2048 12:34:56 die xxix mensis ii annoque mmxlviii xii h xxxiv m lvi s 20 mm 29 xxix 29 xxix Feb 060 2469136 02 ii 2 02/29/2048 die xxix mensis ii annoque mmxlviii 48 xlviii 2048}
+test clock-2.2189 {conversion of 2048-03-01} {
+ clock format 2466678896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2048 12:34:56 die i mensis iii annoque mmxlviii xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 061 2469137 03 iii 3 03/01/2048 die i mensis iii annoque mmxlviii 48 xlviii 2048}
+test clock-2.2190 {conversion of 2048-03-31} {
+ clock format 2469270896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2048 12:34:56 die xxxi mensis iii annoque mmxlviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 091 2469167 03 iii 3 03/31/2048 die xxxi mensis iii annoque mmxlviii 48 xlviii 2048}
+test clock-2.2191 {conversion of 2048-04-01} {
+ clock format 2469357296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2048 12:34:56 die i mensis iv annoque mmxlviii xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 092 2469168 04 iv 4 04/01/2048 die i mensis iv annoque mmxlviii 48 xlviii 2048}
+test clock-2.2192 {conversion of 2048-04-30} {
+ clock format 2471862896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2048 12:34:56 die xxx mensis iv annoque mmxlviii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 121 2469197 04 iv 4 04/30/2048 die xxx mensis iv annoque mmxlviii 48 xlviii 2048}
+test clock-2.2193 {conversion of 2048-05-01} {
+ clock format 2471949296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2048 12:34:56 die i mensis v annoque mmxlviii xii h xxxiv m lvi s 20 mm 01 i 1 i May 122 2469198 05 v 5 05/01/2048 die i mensis v annoque mmxlviii 48 xlviii 2048}
+test clock-2.2194 {conversion of 2048-05-31} {
+ clock format 2474541296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2048 12:34:56 die xxxi mensis v annoque mmxlviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 152 2469228 05 v 5 05/31/2048 die xxxi mensis v annoque mmxlviii 48 xlviii 2048}
+test clock-2.2195 {conversion of 2048-06-01} {
+ clock format 2474627696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2048 12:34:56 die i mensis vi annoque mmxlviii xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 153 2469229 06 vi 6 06/01/2048 die i mensis vi annoque mmxlviii 48 xlviii 2048}
+test clock-2.2196 {conversion of 2048-06-30} {
+ clock format 2477133296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2048 12:34:56 die xxx mensis vi annoque mmxlviii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 182 2469258 06 vi 6 06/30/2048 die xxx mensis vi annoque mmxlviii 48 xlviii 2048}
+test clock-2.2197 {conversion of 2048-07-01} {
+ clock format 2477219696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2048 12:34:56 die i mensis vii annoque mmxlviii xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 183 2469259 07 vii 7 07/01/2048 die i mensis vii annoque mmxlviii 48 xlviii 2048}
+test clock-2.2198 {conversion of 2048-07-31} {
+ clock format 2479811696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2048 12:34:56 die xxxi mensis vii annoque mmxlviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 213 2469289 07 vii 7 07/31/2048 die xxxi mensis vii annoque mmxlviii 48 xlviii 2048}
+test clock-2.2199 {conversion of 2048-08-01} {
+ clock format 2479898096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2048 12:34:56 die i mensis viii annoque mmxlviii xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 214 2469290 08 viii 8 08/01/2048 die i mensis viii annoque mmxlviii 48 xlviii 2048}
+test clock-2.2200 {conversion of 2048-08-31} {
+ clock format 2482490096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2048 12:34:56 die xxxi mensis viii annoque mmxlviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 244 2469320 08 viii 8 08/31/2048 die xxxi mensis viii annoque mmxlviii 48 xlviii 2048}
+test clock-2.2201 {conversion of 2048-09-01} {
+ clock format 2482576496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2048 12:34:56 die i mensis ix annoque mmxlviii xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 245 2469321 09 ix 9 09/01/2048 die i mensis ix annoque mmxlviii 48 xlviii 2048}
+test clock-2.2202 {conversion of 2048-09-30} {
+ clock format 2485082096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2048 12:34:56 die xxx mensis ix annoque mmxlviii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 274 2469350 09 ix 9 09/30/2048 die xxx mensis ix annoque mmxlviii 48 xlviii 2048}
+test clock-2.2203 {conversion of 2048-10-01} {
+ clock format 2485168496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2048 12:34:56 die i mensis x annoque mmxlviii xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 275 2469351 10 x 10 10/01/2048 die i mensis x annoque mmxlviii 48 xlviii 2048}
+test clock-2.2204 {conversion of 2048-10-31} {
+ clock format 2487760496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2048 12:34:56 die xxxi mensis x annoque mmxlviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 305 2469381 10 x 10 10/31/2048 die xxxi mensis x annoque mmxlviii 48 xlviii 2048}
+test clock-2.2205 {conversion of 2048-11-01} {
+ clock format 2487846896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2048 12:34:56 die i mensis xi annoque mmxlviii xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 306 2469382 11 xi 11 11/01/2048 die i mensis xi annoque mmxlviii 48 xlviii 2048}
+test clock-2.2206 {conversion of 2048-11-30} {
+ clock format 2490352496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2048 12:34:56 die xxx mensis xi annoque mmxlviii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 335 2469411 11 xi 11 11/30/2048 die xxx mensis xi annoque mmxlviii 48 xlviii 2048}
+test clock-2.2207 {conversion of 2048-12-01} {
+ clock format 2490438896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2048 12:34:56 die i mensis xii annoque mmxlviii xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 336 2469412 12 xii 12 12/01/2048 die i mensis xii annoque mmxlviii 48 xlviii 2048}
+test clock-2.2208 {conversion of 2048-12-31} {
+ clock format 2493030896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2048 12:34:56 die xxxi mensis xii annoque mmxlviii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 366 2469442 12 xii 12 12/31/2048 die xxxi mensis xii annoque mmxlviii 48 xlviii 2048}
+test clock-2.2209 {conversion of 2049-01-01} {
+ clock format 2493117296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2049 12:34:56 die i mensis i annoque mmxlix xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2469443 01 i 1 01/01/2049 die i mensis i annoque mmxlix 49 xlix 2049}
+test clock-2.2210 {conversion of 2049-01-31} {
+ clock format 2495709296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2049 12:34:56 die xxxi mensis i annoque mmxlix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2469473 01 i 1 01/31/2049 die xxxi mensis i annoque mmxlix 49 xlix 2049}
+test clock-2.2211 {conversion of 2049-02-01} {
+ clock format 2495795696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2049 12:34:56 die i mensis ii annoque mmxlix xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2469474 02 ii 2 02/01/2049 die i mensis ii annoque mmxlix 49 xlix 2049}
+test clock-2.2212 {conversion of 2049-02-28} {
+ clock format 2498128496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2049 12:34:56 die xxviii mensis ii annoque mmxlix xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2469501 02 ii 2 02/28/2049 die xxviii mensis ii annoque mmxlix 49 xlix 2049}
+test clock-2.2213 {conversion of 2049-03-01} {
+ clock format 2498214896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2049 12:34:56 die i mensis iii annoque mmxlix xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2469502 03 iii 3 03/01/2049 die i mensis iii annoque mmxlix 49 xlix 2049}
+test clock-2.2214 {conversion of 2049-03-31} {
+ clock format 2500806896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2049 12:34:56 die xxxi mensis iii annoque mmxlix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2469532 03 iii 3 03/31/2049 die xxxi mensis iii annoque mmxlix 49 xlix 2049}
+test clock-2.2215 {conversion of 2049-04-01} {
+ clock format 2500893296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2049 12:34:56 die i mensis iv annoque mmxlix xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2469533 04 iv 4 04/01/2049 die i mensis iv annoque mmxlix 49 xlix 2049}
+test clock-2.2216 {conversion of 2049-04-30} {
+ clock format 2503398896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2049 12:34:56 die xxx mensis iv annoque mmxlix xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2469562 04 iv 4 04/30/2049 die xxx mensis iv annoque mmxlix 49 xlix 2049}
+test clock-2.2217 {conversion of 2049-05-01} {
+ clock format 2503485296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2049 12:34:56 die i mensis v annoque mmxlix xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2469563 05 v 5 05/01/2049 die i mensis v annoque mmxlix 49 xlix 2049}
+test clock-2.2218 {conversion of 2049-05-31} {
+ clock format 2506077296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2049 12:34:56 die xxxi mensis v annoque mmxlix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2469593 05 v 5 05/31/2049 die xxxi mensis v annoque mmxlix 49 xlix 2049}
+test clock-2.2219 {conversion of 2049-06-01} {
+ clock format 2506163696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2049 12:34:56 die i mensis vi annoque mmxlix xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2469594 06 vi 6 06/01/2049 die i mensis vi annoque mmxlix 49 xlix 2049}
+test clock-2.2220 {conversion of 2049-06-30} {
+ clock format 2508669296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2049 12:34:56 die xxx mensis vi annoque mmxlix xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2469623 06 vi 6 06/30/2049 die xxx mensis vi annoque mmxlix 49 xlix 2049}
+test clock-2.2221 {conversion of 2049-07-01} {
+ clock format 2508755696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2049 12:34:56 die i mensis vii annoque mmxlix xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2469624 07 vii 7 07/01/2049 die i mensis vii annoque mmxlix 49 xlix 2049}
+test clock-2.2222 {conversion of 2049-07-31} {
+ clock format 2511347696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2049 12:34:56 die xxxi mensis vii annoque mmxlix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2469654 07 vii 7 07/31/2049 die xxxi mensis vii annoque mmxlix 49 xlix 2049}
+test clock-2.2223 {conversion of 2049-08-01} {
+ clock format 2511434096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2049 12:34:56 die i mensis viii annoque mmxlix xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2469655 08 viii 8 08/01/2049 die i mensis viii annoque mmxlix 49 xlix 2049}
+test clock-2.2224 {conversion of 2049-08-31} {
+ clock format 2514026096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2049 12:34:56 die xxxi mensis viii annoque mmxlix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2469685 08 viii 8 08/31/2049 die xxxi mensis viii annoque mmxlix 49 xlix 2049}
+test clock-2.2225 {conversion of 2049-09-01} {
+ clock format 2514112496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2049 12:34:56 die i mensis ix annoque mmxlix xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2469686 09 ix 9 09/01/2049 die i mensis ix annoque mmxlix 49 xlix 2049}
+test clock-2.2226 {conversion of 2049-09-30} {
+ clock format 2516618096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2049 12:34:56 die xxx mensis ix annoque mmxlix xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2469715 09 ix 9 09/30/2049 die xxx mensis ix annoque mmxlix 49 xlix 2049}
+test clock-2.2227 {conversion of 2049-10-01} {
+ clock format 2516704496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2049 12:34:56 die i mensis x annoque mmxlix xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2469716 10 x 10 10/01/2049 die i mensis x annoque mmxlix 49 xlix 2049}
+test clock-2.2228 {conversion of 2049-10-31} {
+ clock format 2519296496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2049 12:34:56 die xxxi mensis x annoque mmxlix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2469746 10 x 10 10/31/2049 die xxxi mensis x annoque mmxlix 49 xlix 2049}
+test clock-2.2229 {conversion of 2049-11-01} {
+ clock format 2519382896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2049 12:34:56 die i mensis xi annoque mmxlix xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2469747 11 xi 11 11/01/2049 die i mensis xi annoque mmxlix 49 xlix 2049}
+test clock-2.2230 {conversion of 2049-11-30} {
+ clock format 2521888496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2049 12:34:56 die xxx mensis xi annoque mmxlix xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2469776 11 xi 11 11/30/2049 die xxx mensis xi annoque mmxlix 49 xlix 2049}
+test clock-2.2231 {conversion of 2049-12-01} {
+ clock format 2521974896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2049 12:34:56 die i mensis xii annoque mmxlix xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2469777 12 xii 12 12/01/2049 die i mensis xii annoque mmxlix 49 xlix 2049}
+test clock-2.2232 {conversion of 2049-12-31} {
+ clock format 2524566896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2049 12:34:56 die xxxi mensis xii annoque mmxlix xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2469807 12 xii 12 12/31/2049 die xxxi mensis xii annoque mmxlix 49 xlix 2049}
+test clock-2.2233 {conversion of 2052-01-01} {
+ clock format 2587725296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2052 12:34:56 die i mensis i annoque mmlii xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2470538 01 i 1 01/01/2052 die i mensis i annoque mmlii 52 lii 2052}
+test clock-2.2234 {conversion of 2052-01-31} {
+ clock format 2590317296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2052 12:34:56 die xxxi mensis i annoque mmlii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2470568 01 i 1 01/31/2052 die xxxi mensis i annoque mmlii 52 lii 2052}
+test clock-2.2235 {conversion of 2052-02-01} {
+ clock format 2590403696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2052 12:34:56 die i mensis ii annoque mmlii xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2470569 02 ii 2 02/01/2052 die i mensis ii annoque mmlii 52 lii 2052}
+test clock-2.2236 {conversion of 2052-02-29} {
+ clock format 2592822896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/2052 12:34:56 die xxix mensis ii annoque mmlii xii h xxxiv m lvi s 20 mm 29 xxix 29 xxix Feb 060 2470597 02 ii 2 02/29/2052 die xxix mensis ii annoque mmlii 52 lii 2052}
+test clock-2.2237 {conversion of 2052-03-01} {
+ clock format 2592909296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2052 12:34:56 die i mensis iii annoque mmlii xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 061 2470598 03 iii 3 03/01/2052 die i mensis iii annoque mmlii 52 lii 2052}
+test clock-2.2238 {conversion of 2052-03-31} {
+ clock format 2595501296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2052 12:34:56 die xxxi mensis iii annoque mmlii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 091 2470628 03 iii 3 03/31/2052 die xxxi mensis iii annoque mmlii 52 lii 2052}
+test clock-2.2239 {conversion of 2052-04-01} {
+ clock format 2595587696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2052 12:34:56 die i mensis iv annoque mmlii xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 092 2470629 04 iv 4 04/01/2052 die i mensis iv annoque mmlii 52 lii 2052}
+test clock-2.2240 {conversion of 2052-04-30} {
+ clock format 2598093296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2052 12:34:56 die xxx mensis iv annoque mmlii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 121 2470658 04 iv 4 04/30/2052 die xxx mensis iv annoque mmlii 52 lii 2052}
+test clock-2.2241 {conversion of 2052-05-01} {
+ clock format 2598179696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2052 12:34:56 die i mensis v annoque mmlii xii h xxxiv m lvi s 20 mm 01 i 1 i May 122 2470659 05 v 5 05/01/2052 die i mensis v annoque mmlii 52 lii 2052}
+test clock-2.2242 {conversion of 2052-05-31} {
+ clock format 2600771696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2052 12:34:56 die xxxi mensis v annoque mmlii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 152 2470689 05 v 5 05/31/2052 die xxxi mensis v annoque mmlii 52 lii 2052}
+test clock-2.2243 {conversion of 2052-06-01} {
+ clock format 2600858096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2052 12:34:56 die i mensis vi annoque mmlii xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 153 2470690 06 vi 6 06/01/2052 die i mensis vi annoque mmlii 52 lii 2052}
+test clock-2.2244 {conversion of 2052-06-30} {
+ clock format 2603363696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2052 12:34:56 die xxx mensis vi annoque mmlii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 182 2470719 06 vi 6 06/30/2052 die xxx mensis vi annoque mmlii 52 lii 2052}
+test clock-2.2245 {conversion of 2052-07-01} {
+ clock format 2603450096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2052 12:34:56 die i mensis vii annoque mmlii xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 183 2470720 07 vii 7 07/01/2052 die i mensis vii annoque mmlii 52 lii 2052}
+test clock-2.2246 {conversion of 2052-07-31} {
+ clock format 2606042096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2052 12:34:56 die xxxi mensis vii annoque mmlii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 213 2470750 07 vii 7 07/31/2052 die xxxi mensis vii annoque mmlii 52 lii 2052}
+test clock-2.2247 {conversion of 2052-08-01} {
+ clock format 2606128496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2052 12:34:56 die i mensis viii annoque mmlii xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 214 2470751 08 viii 8 08/01/2052 die i mensis viii annoque mmlii 52 lii 2052}
+test clock-2.2248 {conversion of 2052-08-31} {
+ clock format 2608720496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2052 12:34:56 die xxxi mensis viii annoque mmlii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 244 2470781 08 viii 8 08/31/2052 die xxxi mensis viii annoque mmlii 52 lii 2052}
+test clock-2.2249 {conversion of 2052-09-01} {
+ clock format 2608806896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2052 12:34:56 die i mensis ix annoque mmlii xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 245 2470782 09 ix 9 09/01/2052 die i mensis ix annoque mmlii 52 lii 2052}
+test clock-2.2250 {conversion of 2052-09-30} {
+ clock format 2611312496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2052 12:34:56 die xxx mensis ix annoque mmlii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 274 2470811 09 ix 9 09/30/2052 die xxx mensis ix annoque mmlii 52 lii 2052}
+test clock-2.2251 {conversion of 2052-10-01} {
+ clock format 2611398896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2052 12:34:56 die i mensis x annoque mmlii xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 275 2470812 10 x 10 10/01/2052 die i mensis x annoque mmlii 52 lii 2052}
+test clock-2.2252 {conversion of 2052-10-31} {
+ clock format 2613990896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2052 12:34:56 die xxxi mensis x annoque mmlii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 305 2470842 10 x 10 10/31/2052 die xxxi mensis x annoque mmlii 52 lii 2052}
+test clock-2.2253 {conversion of 2052-11-01} {
+ clock format 2614077296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2052 12:34:56 die i mensis xi annoque mmlii xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 306 2470843 11 xi 11 11/01/2052 die i mensis xi annoque mmlii 52 lii 2052}
+test clock-2.2254 {conversion of 2052-11-30} {
+ clock format 2616582896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2052 12:34:56 die xxx mensis xi annoque mmlii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 335 2470872 11 xi 11 11/30/2052 die xxx mensis xi annoque mmlii 52 lii 2052}
+test clock-2.2255 {conversion of 2052-12-01} {
+ clock format 2616669296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2052 12:34:56 die i mensis xii annoque mmlii xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 336 2470873 12 xii 12 12/01/2052 die i mensis xii annoque mmlii 52 lii 2052}
+test clock-2.2256 {conversion of 2052-12-31} {
+ clock format 2619261296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2052 12:34:56 die xxxi mensis xii annoque mmlii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 366 2470903 12 xii 12 12/31/2052 die xxxi mensis xii annoque mmlii 52 lii 2052}
+test clock-2.2257 {conversion of 2053-01-01} {
+ clock format 2619347696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2053 12:34:56 die i mensis i annoque mmliii xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2470904 01 i 1 01/01/2053 die i mensis i annoque mmliii 53 liii 2053}
+test clock-2.2258 {conversion of 2053-01-31} {
+ clock format 2621939696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2053 12:34:56 die xxxi mensis i annoque mmliii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2470934 01 i 1 01/31/2053 die xxxi mensis i annoque mmliii 53 liii 2053}
+test clock-2.2259 {conversion of 2053-02-01} {
+ clock format 2622026096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2053 12:34:56 die i mensis ii annoque mmliii xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2470935 02 ii 2 02/01/2053 die i mensis ii annoque mmliii 53 liii 2053}
+test clock-2.2260 {conversion of 2053-02-28} {
+ clock format 2624358896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2053 12:34:56 die xxviii mensis ii annoque mmliii xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2470962 02 ii 2 02/28/2053 die xxviii mensis ii annoque mmliii 53 liii 2053}
+test clock-2.2261 {conversion of 2053-03-01} {
+ clock format 2624445296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2053 12:34:56 die i mensis iii annoque mmliii xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2470963 03 iii 3 03/01/2053 die i mensis iii annoque mmliii 53 liii 2053}
+test clock-2.2262 {conversion of 2053-03-31} {
+ clock format 2627037296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2053 12:34:56 die xxxi mensis iii annoque mmliii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2470993 03 iii 3 03/31/2053 die xxxi mensis iii annoque mmliii 53 liii 2053}
+test clock-2.2263 {conversion of 2053-04-01} {
+ clock format 2627123696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2053 12:34:56 die i mensis iv annoque mmliii xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2470994 04 iv 4 04/01/2053 die i mensis iv annoque mmliii 53 liii 2053}
+test clock-2.2264 {conversion of 2053-04-30} {
+ clock format 2629629296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2053 12:34:56 die xxx mensis iv annoque mmliii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2471023 04 iv 4 04/30/2053 die xxx mensis iv annoque mmliii 53 liii 2053}
+test clock-2.2265 {conversion of 2053-05-01} {
+ clock format 2629715696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2053 12:34:56 die i mensis v annoque mmliii xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2471024 05 v 5 05/01/2053 die i mensis v annoque mmliii 53 liii 2053}
+test clock-2.2266 {conversion of 2053-05-31} {
+ clock format 2632307696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2053 12:34:56 die xxxi mensis v annoque mmliii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2471054 05 v 5 05/31/2053 die xxxi mensis v annoque mmliii 53 liii 2053}
+test clock-2.2267 {conversion of 2053-06-01} {
+ clock format 2632394096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2053 12:34:56 die i mensis vi annoque mmliii xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2471055 06 vi 6 06/01/2053 die i mensis vi annoque mmliii 53 liii 2053}
+test clock-2.2268 {conversion of 2053-06-30} {
+ clock format 2634899696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2053 12:34:56 die xxx mensis vi annoque mmliii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2471084 06 vi 6 06/30/2053 die xxx mensis vi annoque mmliii 53 liii 2053}
+test clock-2.2269 {conversion of 2053-07-01} {
+ clock format 2634986096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2053 12:34:56 die i mensis vii annoque mmliii xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2471085 07 vii 7 07/01/2053 die i mensis vii annoque mmliii 53 liii 2053}
+test clock-2.2270 {conversion of 2053-07-31} {
+ clock format 2637578096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2053 12:34:56 die xxxi mensis vii annoque mmliii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2471115 07 vii 7 07/31/2053 die xxxi mensis vii annoque mmliii 53 liii 2053}
+test clock-2.2271 {conversion of 2053-08-01} {
+ clock format 2637664496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2053 12:34:56 die i mensis viii annoque mmliii xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2471116 08 viii 8 08/01/2053 die i mensis viii annoque mmliii 53 liii 2053}
+test clock-2.2272 {conversion of 2053-08-31} {
+ clock format 2640256496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2053 12:34:56 die xxxi mensis viii annoque mmliii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2471146 08 viii 8 08/31/2053 die xxxi mensis viii annoque mmliii 53 liii 2053}
+test clock-2.2273 {conversion of 2053-09-01} {
+ clock format 2640342896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2053 12:34:56 die i mensis ix annoque mmliii xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2471147 09 ix 9 09/01/2053 die i mensis ix annoque mmliii 53 liii 2053}
+test clock-2.2274 {conversion of 2053-09-30} {
+ clock format 2642848496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2053 12:34:56 die xxx mensis ix annoque mmliii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2471176 09 ix 9 09/30/2053 die xxx mensis ix annoque mmliii 53 liii 2053}
+test clock-2.2275 {conversion of 2053-10-01} {
+ clock format 2642934896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2053 12:34:56 die i mensis x annoque mmliii xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2471177 10 x 10 10/01/2053 die i mensis x annoque mmliii 53 liii 2053}
+test clock-2.2276 {conversion of 2053-10-31} {
+ clock format 2645526896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2053 12:34:56 die xxxi mensis x annoque mmliii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2471207 10 x 10 10/31/2053 die xxxi mensis x annoque mmliii 53 liii 2053}
+test clock-2.2277 {conversion of 2053-11-01} {
+ clock format 2645613296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2053 12:34:56 die i mensis xi annoque mmliii xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2471208 11 xi 11 11/01/2053 die i mensis xi annoque mmliii 53 liii 2053}
+test clock-2.2278 {conversion of 2053-11-30} {
+ clock format 2648118896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2053 12:34:56 die xxx mensis xi annoque mmliii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2471237 11 xi 11 11/30/2053 die xxx mensis xi annoque mmliii 53 liii 2053}
+test clock-2.2279 {conversion of 2053-12-01} {
+ clock format 2648205296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2053 12:34:56 die i mensis xii annoque mmliii xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2471238 12 xii 12 12/01/2053 die i mensis xii annoque mmliii 53 liii 2053}
+test clock-2.2280 {conversion of 2053-12-31} {
+ clock format 2650797296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2053 12:34:56 die xxxi mensis xii annoque mmliii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2471268 12 xii 12 12/31/2053 die xxxi mensis xii annoque mmliii 53 liii 2053}
+test clock-2.2281 {conversion of 2056-01-01} {
+ clock format 2713955696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2056 12:34:56 die i mensis i annoque mmlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2471999 01 i 1 01/01/2056 die i mensis i annoque mmlvi 56 lvi 2056}
+test clock-2.2282 {conversion of 2056-01-31} {
+ clock format 2716547696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2056 12:34:56 die xxxi mensis i annoque mmlvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2472029 01 i 1 01/31/2056 die xxxi mensis i annoque mmlvi 56 lvi 2056}
+test clock-2.2283 {conversion of 2056-02-01} {
+ clock format 2716634096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2056 12:34:56 die i mensis ii annoque mmlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2472030 02 ii 2 02/01/2056 die i mensis ii annoque mmlvi 56 lvi 2056}
+test clock-2.2284 {conversion of 2056-02-29} {
+ clock format 2719053296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/2056 12:34:56 die xxix mensis ii annoque mmlvi xii h xxxiv m lvi s 20 mm 29 xxix 29 xxix Feb 060 2472058 02 ii 2 02/29/2056 die xxix mensis ii annoque mmlvi 56 lvi 2056}
+test clock-2.2285 {conversion of 2056-03-01} {
+ clock format 2719139696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2056 12:34:56 die i mensis iii annoque mmlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 061 2472059 03 iii 3 03/01/2056 die i mensis iii annoque mmlvi 56 lvi 2056}
+test clock-2.2286 {conversion of 2056-03-31} {
+ clock format 2721731696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2056 12:34:56 die xxxi mensis iii annoque mmlvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 091 2472089 03 iii 3 03/31/2056 die xxxi mensis iii annoque mmlvi 56 lvi 2056}
+test clock-2.2287 {conversion of 2056-04-01} {
+ clock format 2721818096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2056 12:34:56 die i mensis iv annoque mmlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 092 2472090 04 iv 4 04/01/2056 die i mensis iv annoque mmlvi 56 lvi 2056}
+test clock-2.2288 {conversion of 2056-04-30} {
+ clock format 2724323696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2056 12:34:56 die xxx mensis iv annoque mmlvi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 121 2472119 04 iv 4 04/30/2056 die xxx mensis iv annoque mmlvi 56 lvi 2056}
+test clock-2.2289 {conversion of 2056-05-01} {
+ clock format 2724410096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2056 12:34:56 die i mensis v annoque mmlvi xii h xxxiv m lvi s 20 mm 01 i 1 i May 122 2472120 05 v 5 05/01/2056 die i mensis v annoque mmlvi 56 lvi 2056}
+test clock-2.2290 {conversion of 2056-05-31} {
+ clock format 2727002096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2056 12:34:56 die xxxi mensis v annoque mmlvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 152 2472150 05 v 5 05/31/2056 die xxxi mensis v annoque mmlvi 56 lvi 2056}
+test clock-2.2291 {conversion of 2056-06-01} {
+ clock format 2727088496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2056 12:34:56 die i mensis vi annoque mmlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 153 2472151 06 vi 6 06/01/2056 die i mensis vi annoque mmlvi 56 lvi 2056}
+test clock-2.2292 {conversion of 2056-06-30} {
+ clock format 2729594096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2056 12:34:56 die xxx mensis vi annoque mmlvi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 182 2472180 06 vi 6 06/30/2056 die xxx mensis vi annoque mmlvi 56 lvi 2056}
+test clock-2.2293 {conversion of 2056-07-01} {
+ clock format 2729680496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2056 12:34:56 die i mensis vii annoque mmlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 183 2472181 07 vii 7 07/01/2056 die i mensis vii annoque mmlvi 56 lvi 2056}
+test clock-2.2294 {conversion of 2056-07-31} {
+ clock format 2732272496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2056 12:34:56 die xxxi mensis vii annoque mmlvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 213 2472211 07 vii 7 07/31/2056 die xxxi mensis vii annoque mmlvi 56 lvi 2056}
+test clock-2.2295 {conversion of 2056-08-01} {
+ clock format 2732358896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2056 12:34:56 die i mensis viii annoque mmlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 214 2472212 08 viii 8 08/01/2056 die i mensis viii annoque mmlvi 56 lvi 2056}
+test clock-2.2296 {conversion of 2056-08-31} {
+ clock format 2734950896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2056 12:34:56 die xxxi mensis viii annoque mmlvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 244 2472242 08 viii 8 08/31/2056 die xxxi mensis viii annoque mmlvi 56 lvi 2056}
+test clock-2.2297 {conversion of 2056-09-01} {
+ clock format 2735037296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2056 12:34:56 die i mensis ix annoque mmlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 245 2472243 09 ix 9 09/01/2056 die i mensis ix annoque mmlvi 56 lvi 2056}
+test clock-2.2298 {conversion of 2056-09-30} {
+ clock format 2737542896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2056 12:34:56 die xxx mensis ix annoque mmlvi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 274 2472272 09 ix 9 09/30/2056 die xxx mensis ix annoque mmlvi 56 lvi 2056}
+test clock-2.2299 {conversion of 2056-10-01} {
+ clock format 2737629296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2056 12:34:56 die i mensis x annoque mmlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 275 2472273 10 x 10 10/01/2056 die i mensis x annoque mmlvi 56 lvi 2056}
+test clock-2.2300 {conversion of 2056-10-31} {
+ clock format 2740221296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2056 12:34:56 die xxxi mensis x annoque mmlvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 305 2472303 10 x 10 10/31/2056 die xxxi mensis x annoque mmlvi 56 lvi 2056}
+test clock-2.2301 {conversion of 2056-11-01} {
+ clock format 2740307696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2056 12:34:56 die i mensis xi annoque mmlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 306 2472304 11 xi 11 11/01/2056 die i mensis xi annoque mmlvi 56 lvi 2056}
+test clock-2.2302 {conversion of 2056-11-30} {
+ clock format 2742813296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2056 12:34:56 die xxx mensis xi annoque mmlvi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 335 2472333 11 xi 11 11/30/2056 die xxx mensis xi annoque mmlvi 56 lvi 2056}
+test clock-2.2303 {conversion of 2056-12-01} {
+ clock format 2742899696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2056 12:34:56 die i mensis xii annoque mmlvi xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 336 2472334 12 xii 12 12/01/2056 die i mensis xii annoque mmlvi 56 lvi 2056}
+test clock-2.2304 {conversion of 2056-12-31} {
+ clock format 2745491696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2056 12:34:56 die xxxi mensis xii annoque mmlvi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 366 2472364 12 xii 12 12/31/2056 die xxxi mensis xii annoque mmlvi 56 lvi 2056}
+test clock-2.2305 {conversion of 2057-01-01} {
+ clock format 2745578096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2057 12:34:56 die i mensis i annoque mmlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2472365 01 i 1 01/01/2057 die i mensis i annoque mmlvii 57 lvii 2057}
+test clock-2.2306 {conversion of 2057-01-31} {
+ clock format 2748170096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2057 12:34:56 die xxxi mensis i annoque mmlvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2472395 01 i 1 01/31/2057 die xxxi mensis i annoque mmlvii 57 lvii 2057}
+test clock-2.2307 {conversion of 2057-02-01} {
+ clock format 2748256496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2057 12:34:56 die i mensis ii annoque mmlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2472396 02 ii 2 02/01/2057 die i mensis ii annoque mmlvii 57 lvii 2057}
+test clock-2.2308 {conversion of 2057-02-28} {
+ clock format 2750589296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2057 12:34:56 die xxviii mensis ii annoque mmlvii xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2472423 02 ii 2 02/28/2057 die xxviii mensis ii annoque mmlvii 57 lvii 2057}
+test clock-2.2309 {conversion of 2057-03-01} {
+ clock format 2750675696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2057 12:34:56 die i mensis iii annoque mmlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2472424 03 iii 3 03/01/2057 die i mensis iii annoque mmlvii 57 lvii 2057}
+test clock-2.2310 {conversion of 2057-03-31} {
+ clock format 2753267696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2057 12:34:56 die xxxi mensis iii annoque mmlvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2472454 03 iii 3 03/31/2057 die xxxi mensis iii annoque mmlvii 57 lvii 2057}
+test clock-2.2311 {conversion of 2057-04-01} {
+ clock format 2753354096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2057 12:34:56 die i mensis iv annoque mmlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2472455 04 iv 4 04/01/2057 die i mensis iv annoque mmlvii 57 lvii 2057}
+test clock-2.2312 {conversion of 2057-04-30} {
+ clock format 2755859696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2057 12:34:56 die xxx mensis iv annoque mmlvii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2472484 04 iv 4 04/30/2057 die xxx mensis iv annoque mmlvii 57 lvii 2057}
+test clock-2.2313 {conversion of 2057-05-01} {
+ clock format 2755946096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2057 12:34:56 die i mensis v annoque mmlvii xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2472485 05 v 5 05/01/2057 die i mensis v annoque mmlvii 57 lvii 2057}
+test clock-2.2314 {conversion of 2057-05-31} {
+ clock format 2758538096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2057 12:34:56 die xxxi mensis v annoque mmlvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2472515 05 v 5 05/31/2057 die xxxi mensis v annoque mmlvii 57 lvii 2057}
+test clock-2.2315 {conversion of 2057-06-01} {
+ clock format 2758624496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2057 12:34:56 die i mensis vi annoque mmlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2472516 06 vi 6 06/01/2057 die i mensis vi annoque mmlvii 57 lvii 2057}
+test clock-2.2316 {conversion of 2057-06-30} {
+ clock format 2761130096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2057 12:34:56 die xxx mensis vi annoque mmlvii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2472545 06 vi 6 06/30/2057 die xxx mensis vi annoque mmlvii 57 lvii 2057}
+test clock-2.2317 {conversion of 2057-07-01} {
+ clock format 2761216496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2057 12:34:56 die i mensis vii annoque mmlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2472546 07 vii 7 07/01/2057 die i mensis vii annoque mmlvii 57 lvii 2057}
+test clock-2.2318 {conversion of 2057-07-31} {
+ clock format 2763808496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2057 12:34:56 die xxxi mensis vii annoque mmlvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2472576 07 vii 7 07/31/2057 die xxxi mensis vii annoque mmlvii 57 lvii 2057}
+test clock-2.2319 {conversion of 2057-08-01} {
+ clock format 2763894896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2057 12:34:56 die i mensis viii annoque mmlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2472577 08 viii 8 08/01/2057 die i mensis viii annoque mmlvii 57 lvii 2057}
+test clock-2.2320 {conversion of 2057-08-31} {
+ clock format 2766486896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2057 12:34:56 die xxxi mensis viii annoque mmlvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2472607 08 viii 8 08/31/2057 die xxxi mensis viii annoque mmlvii 57 lvii 2057}
+test clock-2.2321 {conversion of 2057-09-01} {
+ clock format 2766573296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2057 12:34:56 die i mensis ix annoque mmlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2472608 09 ix 9 09/01/2057 die i mensis ix annoque mmlvii 57 lvii 2057}
+test clock-2.2322 {conversion of 2057-09-30} {
+ clock format 2769078896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2057 12:34:56 die xxx mensis ix annoque mmlvii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2472637 09 ix 9 09/30/2057 die xxx mensis ix annoque mmlvii 57 lvii 2057}
+test clock-2.2323 {conversion of 2057-10-01} {
+ clock format 2769165296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2057 12:34:56 die i mensis x annoque mmlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2472638 10 x 10 10/01/2057 die i mensis x annoque mmlvii 57 lvii 2057}
+test clock-2.2324 {conversion of 2057-10-31} {
+ clock format 2771757296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2057 12:34:56 die xxxi mensis x annoque mmlvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2472668 10 x 10 10/31/2057 die xxxi mensis x annoque mmlvii 57 lvii 2057}
+test clock-2.2325 {conversion of 2057-11-01} {
+ clock format 2771843696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2057 12:34:56 die i mensis xi annoque mmlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2472669 11 xi 11 11/01/2057 die i mensis xi annoque mmlvii 57 lvii 2057}
+test clock-2.2326 {conversion of 2057-11-30} {
+ clock format 2774349296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2057 12:34:56 die xxx mensis xi annoque mmlvii xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2472698 11 xi 11 11/30/2057 die xxx mensis xi annoque mmlvii 57 lvii 2057}
+test clock-2.2327 {conversion of 2057-12-01} {
+ clock format 2774435696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2057 12:34:56 die i mensis xii annoque mmlvii xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2472699 12 xii 12 12/01/2057 die i mensis xii annoque mmlvii 57 lvii 2057}
+test clock-2.2328 {conversion of 2057-12-31} {
+ clock format 2777027696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2057 12:34:56 die xxxi mensis xii annoque mmlvii xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2472729 12 xii 12 12/31/2057 die xxxi mensis xii annoque mmlvii 57 lvii 2057}
+test clock-2.2329 {conversion of 2060-01-01} {
+ clock format 2840186096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2060 12:34:56 die i mensis i annoque mmlx xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2473460 01 i 1 01/01/2060 die i mensis i annoque mmlx 60 lx 2060}
+test clock-2.2330 {conversion of 2060-01-31} {
+ clock format 2842778096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2060 12:34:56 die xxxi mensis i annoque mmlx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2473490 01 i 1 01/31/2060 die xxxi mensis i annoque mmlx 60 lx 2060}
+test clock-2.2331 {conversion of 2060-02-01} {
+ clock format 2842864496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2060 12:34:56 die i mensis ii annoque mmlx xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2473491 02 ii 2 02/01/2060 die i mensis ii annoque mmlx 60 lx 2060}
+test clock-2.2332 {conversion of 2060-02-29} {
+ clock format 2845283696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/2060 12:34:56 die xxix mensis ii annoque mmlx xii h xxxiv m lvi s 20 mm 29 xxix 29 xxix Feb 060 2473519 02 ii 2 02/29/2060 die xxix mensis ii annoque mmlx 60 lx 2060}
+test clock-2.2333 {conversion of 2060-03-01} {
+ clock format 2845370096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2060 12:34:56 die i mensis iii annoque mmlx xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 061 2473520 03 iii 3 03/01/2060 die i mensis iii annoque mmlx 60 lx 2060}
+test clock-2.2334 {conversion of 2060-03-31} {
+ clock format 2847962096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2060 12:34:56 die xxxi mensis iii annoque mmlx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 091 2473550 03 iii 3 03/31/2060 die xxxi mensis iii annoque mmlx 60 lx 2060}
+test clock-2.2335 {conversion of 2060-04-01} {
+ clock format 2848048496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2060 12:34:56 die i mensis iv annoque mmlx xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 092 2473551 04 iv 4 04/01/2060 die i mensis iv annoque mmlx 60 lx 2060}
+test clock-2.2336 {conversion of 2060-04-30} {
+ clock format 2850554096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2060 12:34:56 die xxx mensis iv annoque mmlx xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 121 2473580 04 iv 4 04/30/2060 die xxx mensis iv annoque mmlx 60 lx 2060}
+test clock-2.2337 {conversion of 2060-05-01} {
+ clock format 2850640496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2060 12:34:56 die i mensis v annoque mmlx xii h xxxiv m lvi s 20 mm 01 i 1 i May 122 2473581 05 v 5 05/01/2060 die i mensis v annoque mmlx 60 lx 2060}
+test clock-2.2338 {conversion of 2060-05-31} {
+ clock format 2853232496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2060 12:34:56 die xxxi mensis v annoque mmlx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 152 2473611 05 v 5 05/31/2060 die xxxi mensis v annoque mmlx 60 lx 2060}
+test clock-2.2339 {conversion of 2060-06-01} {
+ clock format 2853318896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2060 12:34:56 die i mensis vi annoque mmlx xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 153 2473612 06 vi 6 06/01/2060 die i mensis vi annoque mmlx 60 lx 2060}
+test clock-2.2340 {conversion of 2060-06-30} {
+ clock format 2855824496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2060 12:34:56 die xxx mensis vi annoque mmlx xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 182 2473641 06 vi 6 06/30/2060 die xxx mensis vi annoque mmlx 60 lx 2060}
+test clock-2.2341 {conversion of 2060-07-01} {
+ clock format 2855910896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2060 12:34:56 die i mensis vii annoque mmlx xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 183 2473642 07 vii 7 07/01/2060 die i mensis vii annoque mmlx 60 lx 2060}
+test clock-2.2342 {conversion of 2060-07-31} {
+ clock format 2858502896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2060 12:34:56 die xxxi mensis vii annoque mmlx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 213 2473672 07 vii 7 07/31/2060 die xxxi mensis vii annoque mmlx 60 lx 2060}
+test clock-2.2343 {conversion of 2060-08-01} {
+ clock format 2858589296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2060 12:34:56 die i mensis viii annoque mmlx xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 214 2473673 08 viii 8 08/01/2060 die i mensis viii annoque mmlx 60 lx 2060}
+test clock-2.2344 {conversion of 2060-08-31} {
+ clock format 2861181296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2060 12:34:56 die xxxi mensis viii annoque mmlx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 244 2473703 08 viii 8 08/31/2060 die xxxi mensis viii annoque mmlx 60 lx 2060}
+test clock-2.2345 {conversion of 2060-09-01} {
+ clock format 2861267696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2060 12:34:56 die i mensis ix annoque mmlx xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 245 2473704 09 ix 9 09/01/2060 die i mensis ix annoque mmlx 60 lx 2060}
+test clock-2.2346 {conversion of 2060-09-30} {
+ clock format 2863773296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2060 12:34:56 die xxx mensis ix annoque mmlx xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 274 2473733 09 ix 9 09/30/2060 die xxx mensis ix annoque mmlx 60 lx 2060}
+test clock-2.2347 {conversion of 2060-10-01} {
+ clock format 2863859696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2060 12:34:56 die i mensis x annoque mmlx xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 275 2473734 10 x 10 10/01/2060 die i mensis x annoque mmlx 60 lx 2060}
+test clock-2.2348 {conversion of 2060-10-31} {
+ clock format 2866451696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2060 12:34:56 die xxxi mensis x annoque mmlx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 305 2473764 10 x 10 10/31/2060 die xxxi mensis x annoque mmlx 60 lx 2060}
+test clock-2.2349 {conversion of 2060-11-01} {
+ clock format 2866538096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2060 12:34:56 die i mensis xi annoque mmlx xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 306 2473765 11 xi 11 11/01/2060 die i mensis xi annoque mmlx 60 lx 2060}
+test clock-2.2350 {conversion of 2060-11-30} {
+ clock format 2869043696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2060 12:34:56 die xxx mensis xi annoque mmlx xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 335 2473794 11 xi 11 11/30/2060 die xxx mensis xi annoque mmlx 60 lx 2060}
+test clock-2.2351 {conversion of 2060-12-01} {
+ clock format 2869130096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2060 12:34:56 die i mensis xii annoque mmlx xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 336 2473795 12 xii 12 12/01/2060 die i mensis xii annoque mmlx 60 lx 2060}
+test clock-2.2352 {conversion of 2060-12-31} {
+ clock format 2871722096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2060 12:34:56 die xxxi mensis xii annoque mmlx xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 366 2473825 12 xii 12 12/31/2060 die xxxi mensis xii annoque mmlx 60 lx 2060}
+test clock-2.2353 {conversion of 2061-01-01} {
+ clock format 2871808496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2061 12:34:56 die i mensis i annoque mmlxi xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2473826 01 i 1 01/01/2061 die i mensis i annoque mmlxi 61 lxi 2061}
+test clock-2.2354 {conversion of 2061-01-31} {
+ clock format 2874400496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2061 12:34:56 die xxxi mensis i annoque mmlxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2473856 01 i 1 01/31/2061 die xxxi mensis i annoque mmlxi 61 lxi 2061}
+test clock-2.2355 {conversion of 2061-02-01} {
+ clock format 2874486896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2061 12:34:56 die i mensis ii annoque mmlxi xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2473857 02 ii 2 02/01/2061 die i mensis ii annoque mmlxi 61 lxi 2061}
+test clock-2.2356 {conversion of 2061-02-28} {
+ clock format 2876819696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2061 12:34:56 die xxviii mensis ii annoque mmlxi xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2473884 02 ii 2 02/28/2061 die xxviii mensis ii annoque mmlxi 61 lxi 2061}
+test clock-2.2357 {conversion of 2061-03-01} {
+ clock format 2876906096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2061 12:34:56 die i mensis iii annoque mmlxi xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2473885 03 iii 3 03/01/2061 die i mensis iii annoque mmlxi 61 lxi 2061}
+test clock-2.2358 {conversion of 2061-03-31} {
+ clock format 2879498096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2061 12:34:56 die xxxi mensis iii annoque mmlxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2473915 03 iii 3 03/31/2061 die xxxi mensis iii annoque mmlxi 61 lxi 2061}
+test clock-2.2359 {conversion of 2061-04-01} {
+ clock format 2879584496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2061 12:34:56 die i mensis iv annoque mmlxi xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2473916 04 iv 4 04/01/2061 die i mensis iv annoque mmlxi 61 lxi 2061}
+test clock-2.2360 {conversion of 2061-04-30} {
+ clock format 2882090096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2061 12:34:56 die xxx mensis iv annoque mmlxi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2473945 04 iv 4 04/30/2061 die xxx mensis iv annoque mmlxi 61 lxi 2061}
+test clock-2.2361 {conversion of 2061-05-01} {
+ clock format 2882176496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2061 12:34:56 die i mensis v annoque mmlxi xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2473946 05 v 5 05/01/2061 die i mensis v annoque mmlxi 61 lxi 2061}
+test clock-2.2362 {conversion of 2061-05-31} {
+ clock format 2884768496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2061 12:34:56 die xxxi mensis v annoque mmlxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2473976 05 v 5 05/31/2061 die xxxi mensis v annoque mmlxi 61 lxi 2061}
+test clock-2.2363 {conversion of 2061-06-01} {
+ clock format 2884854896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2061 12:34:56 die i mensis vi annoque mmlxi xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2473977 06 vi 6 06/01/2061 die i mensis vi annoque mmlxi 61 lxi 2061}
+test clock-2.2364 {conversion of 2061-06-30} {
+ clock format 2887360496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2061 12:34:56 die xxx mensis vi annoque mmlxi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2474006 06 vi 6 06/30/2061 die xxx mensis vi annoque mmlxi 61 lxi 2061}
+test clock-2.2365 {conversion of 2061-07-01} {
+ clock format 2887446896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2061 12:34:56 die i mensis vii annoque mmlxi xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2474007 07 vii 7 07/01/2061 die i mensis vii annoque mmlxi 61 lxi 2061}
+test clock-2.2366 {conversion of 2061-07-31} {
+ clock format 2890038896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2061 12:34:56 die xxxi mensis vii annoque mmlxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2474037 07 vii 7 07/31/2061 die xxxi mensis vii annoque mmlxi 61 lxi 2061}
+test clock-2.2367 {conversion of 2061-08-01} {
+ clock format 2890125296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2061 12:34:56 die i mensis viii annoque mmlxi xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2474038 08 viii 8 08/01/2061 die i mensis viii annoque mmlxi 61 lxi 2061}
+test clock-2.2368 {conversion of 2061-08-31} {
+ clock format 2892717296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2061 12:34:56 die xxxi mensis viii annoque mmlxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2474068 08 viii 8 08/31/2061 die xxxi mensis viii annoque mmlxi 61 lxi 2061}
+test clock-2.2369 {conversion of 2061-09-01} {
+ clock format 2892803696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2061 12:34:56 die i mensis ix annoque mmlxi xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2474069 09 ix 9 09/01/2061 die i mensis ix annoque mmlxi 61 lxi 2061}
+test clock-2.2370 {conversion of 2061-09-30} {
+ clock format 2895309296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2061 12:34:56 die xxx mensis ix annoque mmlxi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2474098 09 ix 9 09/30/2061 die xxx mensis ix annoque mmlxi 61 lxi 2061}
+test clock-2.2371 {conversion of 2061-10-01} {
+ clock format 2895395696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2061 12:34:56 die i mensis x annoque mmlxi xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2474099 10 x 10 10/01/2061 die i mensis x annoque mmlxi 61 lxi 2061}
+test clock-2.2372 {conversion of 2061-10-31} {
+ clock format 2897987696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2061 12:34:56 die xxxi mensis x annoque mmlxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2474129 10 x 10 10/31/2061 die xxxi mensis x annoque mmlxi 61 lxi 2061}
+test clock-2.2373 {conversion of 2061-11-01} {
+ clock format 2898074096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2061 12:34:56 die i mensis xi annoque mmlxi xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2474130 11 xi 11 11/01/2061 die i mensis xi annoque mmlxi 61 lxi 2061}
+test clock-2.2374 {conversion of 2061-11-30} {
+ clock format 2900579696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2061 12:34:56 die xxx mensis xi annoque mmlxi xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2474159 11 xi 11 11/30/2061 die xxx mensis xi annoque mmlxi 61 lxi 2061}
+test clock-2.2375 {conversion of 2061-12-01} {
+ clock format 2900666096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2061 12:34:56 die i mensis xii annoque mmlxi xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2474160 12 xii 12 12/01/2061 die i mensis xii annoque mmlxi 61 lxi 2061}
+test clock-2.2376 {conversion of 2061-12-31} {
+ clock format 2903258096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2061 12:34:56 die xxxi mensis xii annoque mmlxi xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2474190 12 xii 12 12/31/2061 die xxxi mensis xii annoque mmlxi 61 lxi 2061}
+test clock-2.2377 {conversion of 2064-01-01} {
+ clock format 2966416496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2064 12:34:56 die i mensis i annoque mmlxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2474921 01 i 1 01/01/2064 die i mensis i annoque mmlxiv 64 lxiv 2064}
+test clock-2.2378 {conversion of 2064-01-31} {
+ clock format 2969008496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2064 12:34:56 die xxxi mensis i annoque mmlxiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2474951 01 i 1 01/31/2064 die xxxi mensis i annoque mmlxiv 64 lxiv 2064}
+test clock-2.2379 {conversion of 2064-02-01} {
+ clock format 2969094896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2064 12:34:56 die i mensis ii annoque mmlxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2474952 02 ii 2 02/01/2064 die i mensis ii annoque mmlxiv 64 lxiv 2064}
+test clock-2.2380 {conversion of 2064-02-29} {
+ clock format 2971514096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/29/2064 12:34:56 die xxix mensis ii annoque mmlxiv xii h xxxiv m lvi s 20 mm 29 xxix 29 xxix Feb 060 2474980 02 ii 2 02/29/2064 die xxix mensis ii annoque mmlxiv 64 lxiv 2064}
+test clock-2.2381 {conversion of 2064-03-01} {
+ clock format 2971600496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2064 12:34:56 die i mensis iii annoque mmlxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 061 2474981 03 iii 3 03/01/2064 die i mensis iii annoque mmlxiv 64 lxiv 2064}
+test clock-2.2382 {conversion of 2064-03-31} {
+ clock format 2974192496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2064 12:34:56 die xxxi mensis iii annoque mmlxiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 091 2475011 03 iii 3 03/31/2064 die xxxi mensis iii annoque mmlxiv 64 lxiv 2064}
+test clock-2.2383 {conversion of 2064-04-01} {
+ clock format 2974278896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2064 12:34:56 die i mensis iv annoque mmlxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 092 2475012 04 iv 4 04/01/2064 die i mensis iv annoque mmlxiv 64 lxiv 2064}
+test clock-2.2384 {conversion of 2064-04-30} {
+ clock format 2976784496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2064 12:34:56 die xxx mensis iv annoque mmlxiv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 121 2475041 04 iv 4 04/30/2064 die xxx mensis iv annoque mmlxiv 64 lxiv 2064}
+test clock-2.2385 {conversion of 2064-05-01} {
+ clock format 2976870896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2064 12:34:56 die i mensis v annoque mmlxiv xii h xxxiv m lvi s 20 mm 01 i 1 i May 122 2475042 05 v 5 05/01/2064 die i mensis v annoque mmlxiv 64 lxiv 2064}
+test clock-2.2386 {conversion of 2064-05-31} {
+ clock format 2979462896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2064 12:34:56 die xxxi mensis v annoque mmlxiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 152 2475072 05 v 5 05/31/2064 die xxxi mensis v annoque mmlxiv 64 lxiv 2064}
+test clock-2.2387 {conversion of 2064-06-01} {
+ clock format 2979549296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2064 12:34:56 die i mensis vi annoque mmlxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 153 2475073 06 vi 6 06/01/2064 die i mensis vi annoque mmlxiv 64 lxiv 2064}
+test clock-2.2388 {conversion of 2064-06-30} {
+ clock format 2982054896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2064 12:34:56 die xxx mensis vi annoque mmlxiv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 182 2475102 06 vi 6 06/30/2064 die xxx mensis vi annoque mmlxiv 64 lxiv 2064}
+test clock-2.2389 {conversion of 2064-07-01} {
+ clock format 2982141296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2064 12:34:56 die i mensis vii annoque mmlxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 183 2475103 07 vii 7 07/01/2064 die i mensis vii annoque mmlxiv 64 lxiv 2064}
+test clock-2.2390 {conversion of 2064-07-31} {
+ clock format 2984733296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2064 12:34:56 die xxxi mensis vii annoque mmlxiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 213 2475133 07 vii 7 07/31/2064 die xxxi mensis vii annoque mmlxiv 64 lxiv 2064}
+test clock-2.2391 {conversion of 2064-08-01} {
+ clock format 2984819696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2064 12:34:56 die i mensis viii annoque mmlxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 214 2475134 08 viii 8 08/01/2064 die i mensis viii annoque mmlxiv 64 lxiv 2064}
+test clock-2.2392 {conversion of 2064-08-31} {
+ clock format 2987411696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2064 12:34:56 die xxxi mensis viii annoque mmlxiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 244 2475164 08 viii 8 08/31/2064 die xxxi mensis viii annoque mmlxiv 64 lxiv 2064}
+test clock-2.2393 {conversion of 2064-09-01} {
+ clock format 2987498096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2064 12:34:56 die i mensis ix annoque mmlxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 245 2475165 09 ix 9 09/01/2064 die i mensis ix annoque mmlxiv 64 lxiv 2064}
+test clock-2.2394 {conversion of 2064-09-30} {
+ clock format 2990003696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2064 12:34:56 die xxx mensis ix annoque mmlxiv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 274 2475194 09 ix 9 09/30/2064 die xxx mensis ix annoque mmlxiv 64 lxiv 2064}
+test clock-2.2395 {conversion of 2064-10-01} {
+ clock format 2990090096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2064 12:34:56 die i mensis x annoque mmlxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 275 2475195 10 x 10 10/01/2064 die i mensis x annoque mmlxiv 64 lxiv 2064}
+test clock-2.2396 {conversion of 2064-10-31} {
+ clock format 2992682096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2064 12:34:56 die xxxi mensis x annoque mmlxiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 305 2475225 10 x 10 10/31/2064 die xxxi mensis x annoque mmlxiv 64 lxiv 2064}
+test clock-2.2397 {conversion of 2064-11-01} {
+ clock format 2992768496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2064 12:34:56 die i mensis xi annoque mmlxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 306 2475226 11 xi 11 11/01/2064 die i mensis xi annoque mmlxiv 64 lxiv 2064}
+test clock-2.2398 {conversion of 2064-11-30} {
+ clock format 2995274096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2064 12:34:56 die xxx mensis xi annoque mmlxiv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 335 2475255 11 xi 11 11/30/2064 die xxx mensis xi annoque mmlxiv 64 lxiv 2064}
+test clock-2.2399 {conversion of 2064-12-01} {
+ clock format 2995360496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2064 12:34:56 die i mensis xii annoque mmlxiv xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 336 2475256 12 xii 12 12/01/2064 die i mensis xii annoque mmlxiv 64 lxiv 2064}
+test clock-2.2400 {conversion of 2064-12-31} {
+ clock format 2997952496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2064 12:34:56 die xxxi mensis xii annoque mmlxiv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 366 2475286 12 xii 12 12/31/2064 die xxxi mensis xii annoque mmlxiv 64 lxiv 2064}
+test clock-2.2401 {conversion of 2065-01-01} {
+ clock format 2998038896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/01/2065 12:34:56 die i mensis i annoque mmlxv xii h xxxiv m lvi s 20 mm 01 i 1 i Jan 001 2475287 01 i 1 01/01/2065 die i mensis i annoque mmlxv 65 lxv 2065}
+test clock-2.2402 {conversion of 2065-01-31} {
+ clock format 3000630896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jan January 01/31/2065 12:34:56 die xxxi mensis i annoque mmlxv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jan 031 2475317 01 i 1 01/31/2065 die xxxi mensis i annoque mmlxv 65 lxv 2065}
+test clock-2.2403 {conversion of 2065-02-01} {
+ clock format 3000717296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/01/2065 12:34:56 die i mensis ii annoque mmlxv xii h xxxiv m lvi s 20 mm 01 i 1 i Feb 032 2475318 02 ii 2 02/01/2065 die i mensis ii annoque mmlxv 65 lxv 2065}
+test clock-2.2404 {conversion of 2065-02-28} {
+ clock format 3003050096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Feb February 02/28/2065 12:34:56 die xxviii mensis ii annoque mmlxv xii h xxxiv m lvi s 20 mm 28 xxviii 28 xxviii Feb 059 2475345 02 ii 2 02/28/2065 die xxviii mensis ii annoque mmlxv 65 lxv 2065}
+test clock-2.2405 {conversion of 2065-03-01} {
+ clock format 3003136496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/01/2065 12:34:56 die i mensis iii annoque mmlxv xii h xxxiv m lvi s 20 mm 01 i 1 i Mar 060 2475346 03 iii 3 03/01/2065 die i mensis iii annoque mmlxv 65 lxv 2065}
+test clock-2.2406 {conversion of 2065-03-31} {
+ clock format 3005728496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Mar March 03/31/2065 12:34:56 die xxxi mensis iii annoque mmlxv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Mar 090 2475376 03 iii 3 03/31/2065 die xxxi mensis iii annoque mmlxv 65 lxv 2065}
+test clock-2.2407 {conversion of 2065-04-01} {
+ clock format 3005814896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/01/2065 12:34:56 die i mensis iv annoque mmlxv xii h xxxiv m lvi s 20 mm 01 i 1 i Apr 091 2475377 04 iv 4 04/01/2065 die i mensis iv annoque mmlxv 65 lxv 2065}
+test clock-2.2408 {conversion of 2065-04-30} {
+ clock format 3008320496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Apr April 04/30/2065 12:34:56 die xxx mensis iv annoque mmlxv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Apr 120 2475406 04 iv 4 04/30/2065 die xxx mensis iv annoque mmlxv 65 lxv 2065}
+test clock-2.2409 {conversion of 2065-05-01} {
+ clock format 3008406896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/01/2065 12:34:56 die i mensis v annoque mmlxv xii h xxxiv m lvi s 20 mm 01 i 1 i May 121 2475407 05 v 5 05/01/2065 die i mensis v annoque mmlxv 65 lxv 2065}
+test clock-2.2410 {conversion of 2065-05-31} {
+ clock format 3010998896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {May May 05/31/2065 12:34:56 die xxxi mensis v annoque mmlxv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi May 151 2475437 05 v 5 05/31/2065 die xxxi mensis v annoque mmlxv 65 lxv 2065}
+test clock-2.2411 {conversion of 2065-06-01} {
+ clock format 3011085296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/01/2065 12:34:56 die i mensis vi annoque mmlxv xii h xxxiv m lvi s 20 mm 01 i 1 i Jun 152 2475438 06 vi 6 06/01/2065 die i mensis vi annoque mmlxv 65 lxv 2065}
+test clock-2.2412 {conversion of 2065-06-30} {
+ clock format 3013590896 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jun June 06/30/2065 12:34:56 die xxx mensis vi annoque mmlxv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Jun 181 2475467 06 vi 6 06/30/2065 die xxx mensis vi annoque mmlxv 65 lxv 2065}
+test clock-2.2413 {conversion of 2065-07-01} {
+ clock format 3013677296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/01/2065 12:34:56 die i mensis vii annoque mmlxv xii h xxxiv m lvi s 20 mm 01 i 1 i Jul 182 2475468 07 vii 7 07/01/2065 die i mensis vii annoque mmlxv 65 lxv 2065}
+test clock-2.2414 {conversion of 2065-07-31} {
+ clock format 3016269296 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Jul July 07/31/2065 12:34:56 die xxxi mensis vii annoque mmlxv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Jul 212 2475498 07 vii 7 07/31/2065 die xxxi mensis vii annoque mmlxv 65 lxv 2065}
+test clock-2.2415 {conversion of 2065-08-01} {
+ clock format 3016355696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/01/2065 12:34:56 die i mensis viii annoque mmlxv xii h xxxiv m lvi s 20 mm 01 i 1 i Aug 213 2475499 08 viii 8 08/01/2065 die i mensis viii annoque mmlxv 65 lxv 2065}
+test clock-2.2416 {conversion of 2065-08-31} {
+ clock format 3018947696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Aug August 08/31/2065 12:34:56 die xxxi mensis viii annoque mmlxv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Aug 243 2475529 08 viii 8 08/31/2065 die xxxi mensis viii annoque mmlxv 65 lxv 2065}
+test clock-2.2417 {conversion of 2065-09-01} {
+ clock format 3019034096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/01/2065 12:34:56 die i mensis ix annoque mmlxv xii h xxxiv m lvi s 20 mm 01 i 1 i Sep 244 2475530 09 ix 9 09/01/2065 die i mensis ix annoque mmlxv 65 lxv 2065}
+test clock-2.2418 {conversion of 2065-09-30} {
+ clock format 3021539696 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Sep September 09/30/2065 12:34:56 die xxx mensis ix annoque mmlxv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Sep 273 2475559 09 ix 9 09/30/2065 die xxx mensis ix annoque mmlxv 65 lxv 2065}
+test clock-2.2419 {conversion of 2065-10-01} {
+ clock format 3021626096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/01/2065 12:34:56 die i mensis x annoque mmlxv xii h xxxiv m lvi s 20 mm 01 i 1 i Oct 274 2475560 10 x 10 10/01/2065 die i mensis x annoque mmlxv 65 lxv 2065}
+test clock-2.2420 {conversion of 2065-10-31} {
+ clock format 3024218096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Oct October 10/31/2065 12:34:56 die xxxi mensis x annoque mmlxv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Oct 304 2475590 10 x 10 10/31/2065 die xxxi mensis x annoque mmlxv 65 lxv 2065}
+test clock-2.2421 {conversion of 2065-11-01} {
+ clock format 3024304496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/01/2065 12:34:56 die i mensis xi annoque mmlxv xii h xxxiv m lvi s 20 mm 01 i 1 i Nov 305 2475591 11 xi 11 11/01/2065 die i mensis xi annoque mmlxv 65 lxv 2065}
+test clock-2.2422 {conversion of 2065-11-30} {
+ clock format 3026810096 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Nov November 11/30/2065 12:34:56 die xxx mensis xi annoque mmlxv xii h xxxiv m lvi s 20 mm 30 xxx 30 xxx Nov 334 2475620 11 xi 11 11/30/2065 die xxx mensis xi annoque mmlxv 65 lxv 2065}
+test clock-2.2423 {conversion of 2065-12-01} {
+ clock format 3026896496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/01/2065 12:34:56 die i mensis xii annoque mmlxv xii h xxxiv m lvi s 20 mm 01 i 1 i Dec 335 2475621 12 xii 12 12/01/2065 die i mensis xii annoque mmlxv 65 lxv 2065}
+test clock-2.2424 {conversion of 2065-12-31} {
+ clock format 3029488496 \
+ -format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \
+ -gmt true -locale en_US_roman
+} {Dec December 12/31/2065 12:34:56 die xxxi mensis xii annoque mmlxv xii h xxxiv m lvi s 20 mm 31 xxxi 31 xxxi Dec 365 2475651 12 xii 12 12/31/2065 die xxxi mensis xii annoque mmlxv 65 lxv 2065}
+# END testcases2
+
+# BEGIN testcases3
+test clock-3.1 {ISO week-based calendar 1871-W52-1} {
+ clock format -3093206400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1871-W52-1
+} {Mon Monday 71 1871 1 52 52 1 52}
+test clock-3.2 {ISO week-based calendar 1871-W52-6} {
+ clock format -3092774400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1871-W52-6
+} {Sat Saturday 71 1871 6 52 52 6 52}
+test clock-3.3 {ISO week-based calendar 1871-W52-7} {
+ clock format -3092688000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1871-W52-7
+} {Sun Sunday 71 1871 7 53 52 0 52}
+test clock-3.4 {ISO week-based calendar 1872-W01-1} {
+ clock format -3092601600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1872-W01-1
+} {Mon Monday 72 1872 1 00 01 1 01}
+test clock-3.5 {ISO week-based calendar 1872-W01-6} {
+ clock format -3092169600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1872-W01-6
+} {Sat Saturday 72 1872 6 00 01 6 01}
+test clock-3.6 {ISO week-based calendar 1872-W01-7} {
+ clock format -3092083200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1872-W01-7
+} {Sun Sunday 72 1872 7 01 01 0 01}
+test clock-3.7 {ISO week-based calendar 1872-W02-1} {
+ clock format -3091996800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1872-W02-1
+} {Mon Monday 72 1872 1 01 02 1 02}
+test clock-3.8 {ISO week-based calendar 1872-W52-1} {
+ clock format -3061756800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1872-W52-1
+} {Mon Monday 72 1872 1 51 52 1 52}
+test clock-3.9 {ISO week-based calendar 1872-W52-6} {
+ clock format -3061324800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1872-W52-6
+} {Sat Saturday 72 1872 6 51 52 6 52}
+test clock-3.10 {ISO week-based calendar 1872-W52-7} {
+ clock format -3061238400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1872-W52-7
+} {Sun Sunday 72 1872 7 52 52 0 52}
+test clock-3.11 {ISO week-based calendar 1873-W01-1} {
+ clock format -3061152000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1873-W01-1
+} {Mon Monday 73 1873 1 52 01 1 53}
+test clock-3.12 {ISO week-based calendar 1873-W01-3} {
+ clock format -3060979200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1873-W01-3
+} {Wed Wednesday 73 1873 3 00 01 3 00}
+test clock-3.13 {ISO week-based calendar 1873-W01-6} {
+ clock format -3060720000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1873-W01-6
+} {Sat Saturday 73 1873 6 00 01 6 00}
+test clock-3.14 {ISO week-based calendar 1873-W01-7} {
+ clock format -3060633600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1873-W01-7
+} {Sun Sunday 73 1873 7 01 01 0 00}
+test clock-3.15 {ISO week-based calendar 1873-W02-1} {
+ clock format -3060547200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1873-W02-1
+} {Mon Monday 73 1873 1 01 02 1 01}
+test clock-3.16 {ISO week-based calendar 1875-W52-1} {
+ clock format -2966803200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1875-W52-1
+} {Mon Monday 75 1875 1 52 52 1 52}
+test clock-3.17 {ISO week-based calendar 1875-W52-6} {
+ clock format -2966371200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1875-W52-6
+} {Sat Saturday 75 1875 6 00 52 6 00}
+test clock-3.18 {ISO week-based calendar 1875-W52-7} {
+ clock format -2966284800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1875-W52-7
+} {Sun Sunday 75 1875 7 01 52 0 00}
+test clock-3.19 {ISO week-based calendar 1876-W01-1} {
+ clock format -2966198400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1876-W01-1
+} {Mon Monday 76 1876 1 01 01 1 01}
+test clock-3.20 {ISO week-based calendar 1876-W01-6} {
+ clock format -2965766400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1876-W01-6
+} {Sat Saturday 76 1876 6 01 01 6 01}
+test clock-3.21 {ISO week-based calendar 1876-W01-7} {
+ clock format -2965680000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1876-W01-7
+} {Sun Sunday 76 1876 7 02 01 0 01}
+test clock-3.22 {ISO week-based calendar 1876-W02-1} {
+ clock format -2965593600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1876-W02-1
+} {Mon Monday 76 1876 1 02 02 1 02}
+test clock-3.23 {ISO week-based calendar 1876-W52-1} {
+ clock format -2935353600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1876-W52-1
+} {Mon Monday 76 1876 1 52 52 1 52}
+test clock-3.24 {ISO week-based calendar 1876-W52-6} {
+ clock format -2934921600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1876-W52-6
+} {Sat Saturday 76 1876 6 52 52 6 52}
+test clock-3.25 {ISO week-based calendar 1876-W52-7} {
+ clock format -2934835200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1876-W52-7
+} {Sun Sunday 76 1876 7 53 52 0 52}
+test clock-3.26 {ISO week-based calendar 1877-W01-1} {
+ clock format -2934748800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1877-W01-1
+} {Mon Monday 77 1877 1 00 01 1 01}
+test clock-3.27 {ISO week-based calendar 1877-W01-6} {
+ clock format -2934316800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1877-W01-6
+} {Sat Saturday 77 1877 6 00 01 6 01}
+test clock-3.28 {ISO week-based calendar 1877-W01-7} {
+ clock format -2934230400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1877-W01-7
+} {Sun Sunday 77 1877 7 01 01 0 01}
+test clock-3.29 {ISO week-based calendar 1877-W02-1} {
+ clock format -2934144000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1877-W02-1
+} {Mon Monday 77 1877 1 01 02 1 02}
+test clock-3.30 {ISO week-based calendar 1879-W52-1} {
+ clock format -2841004800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1879-W52-1
+} {Mon Monday 79 1879 1 51 52 1 51}
+test clock-3.31 {ISO week-based calendar 1879-W52-6} {
+ clock format -2840572800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1879-W52-6
+} {Sat Saturday 79 1879 6 51 52 6 51}
+test clock-3.32 {ISO week-based calendar 1879-W52-7} {
+ clock format -2840486400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1879-W52-7
+} {Sun Sunday 79 1879 7 52 52 0 51}
+test clock-3.33 {ISO week-based calendar 1880-W01-1} {
+ clock format -2840400000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1880-W01-1
+} {Mon Monday 80 1880 1 52 01 1 52}
+test clock-3.34 {ISO week-based calendar 1880-W01-4} {
+ clock format -2840140800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1880-W01-4
+} {Thu Thursday 80 1880 4 00 01 4 00}
+test clock-3.35 {ISO week-based calendar 1880-W01-6} {
+ clock format -2839968000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1880-W01-6
+} {Sat Saturday 80 1880 6 00 01 6 00}
+test clock-3.36 {ISO week-based calendar 1880-W01-7} {
+ clock format -2839881600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1880-W01-7
+} {Sun Sunday 80 1880 7 01 01 0 00}
+test clock-3.37 {ISO week-based calendar 1880-W02-1} {
+ clock format -2839795200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1880-W02-1
+} {Mon Monday 80 1880 1 01 02 1 01}
+test clock-3.38 {ISO week-based calendar 1880-W53-1} {
+ clock format -2808950400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1880-W53-1
+} {Mon Monday 80 1880 1 52 53 1 52}
+test clock-3.39 {ISO week-based calendar 1880-W53-6} {
+ clock format -2808518400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1880-W53-6
+} {Sat Saturday 80 1880 6 00 53 6 00}
+test clock-3.40 {ISO week-based calendar 1880-W53-7} {
+ clock format -2808432000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1880-W53-7
+} {Sun Sunday 80 1880 7 01 53 0 00}
+test clock-3.41 {ISO week-based calendar 1881-W01-1} {
+ clock format -2808345600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1881-W01-1
+} {Mon Monday 81 1881 1 01 01 1 01}
+test clock-3.42 {ISO week-based calendar 1881-W01-6} {
+ clock format -2807913600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1881-W01-6
+} {Sat Saturday 81 1881 6 01 01 6 01}
+test clock-3.43 {ISO week-based calendar 1881-W01-7} {
+ clock format -2807827200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1881-W01-7
+} {Sun Sunday 81 1881 7 02 01 0 01}
+test clock-3.44 {ISO week-based calendar 1881-W02-1} {
+ clock format -2807740800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1881-W02-1
+} {Mon Monday 81 1881 1 02 02 1 02}
+test clock-3.45 {ISO week-based calendar 1883-W52-1} {
+ clock format -2714601600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1883-W52-1
+} {Mon Monday 83 1883 1 51 52 1 52}
+test clock-3.46 {ISO week-based calendar 1883-W52-6} {
+ clock format -2714169600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1883-W52-6
+} {Sat Saturday 83 1883 6 51 52 6 52}
+test clock-3.47 {ISO week-based calendar 1883-W52-7} {
+ clock format -2714083200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1883-W52-7
+} {Sun Sunday 83 1883 7 52 52 0 52}
+test clock-3.48 {ISO week-based calendar 1884-W01-1} {
+ clock format -2713996800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1884-W01-1
+} {Mon Monday 84 1884 1 52 01 1 53}
+test clock-3.49 {ISO week-based calendar 1884-W01-2} {
+ clock format -2713910400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1884-W01-2
+} {Tue Tuesday 84 1884 2 00 01 2 00}
+test clock-3.50 {ISO week-based calendar 1884-W01-6} {
+ clock format -2713564800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1884-W01-6
+} {Sat Saturday 84 1884 6 00 01 6 00}
+test clock-3.51 {ISO week-based calendar 1884-W01-7} {
+ clock format -2713478400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1884-W01-7
+} {Sun Sunday 84 1884 7 01 01 0 00}
+test clock-3.52 {ISO week-based calendar 1884-W02-1} {
+ clock format -2713392000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1884-W02-1
+} {Mon Monday 84 1884 1 01 02 1 01}
+test clock-3.53 {ISO week-based calendar 1884-W52-1} {
+ clock format -2683152000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1884-W52-1
+} {Mon Monday 84 1884 1 51 52 1 51}
+test clock-3.54 {ISO week-based calendar 1884-W52-6} {
+ clock format -2682720000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1884-W52-6
+} {Sat Saturday 84 1884 6 51 52 6 51}
+test clock-3.55 {ISO week-based calendar 1884-W52-7} {
+ clock format -2682633600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1884-W52-7
+} {Sun Sunday 84 1884 7 52 52 0 51}
+test clock-3.56 {ISO week-based calendar 1885-W01-1} {
+ clock format -2682547200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1885-W01-1
+} {Mon Monday 85 1885 1 52 01 1 52}
+test clock-3.57 {ISO week-based calendar 1885-W01-4} {
+ clock format -2682288000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1885-W01-4
+} {Thu Thursday 85 1885 4 00 01 4 00}
+test clock-3.58 {ISO week-based calendar 1885-W01-6} {
+ clock format -2682115200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1885-W01-6
+} {Sat Saturday 85 1885 6 00 01 6 00}
+test clock-3.59 {ISO week-based calendar 1885-W01-7} {
+ clock format -2682028800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1885-W01-7
+} {Sun Sunday 85 1885 7 01 01 0 00}
+test clock-3.60 {ISO week-based calendar 1885-W02-1} {
+ clock format -2681942400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1885-W02-1
+} {Mon Monday 85 1885 1 01 02 1 01}
+test clock-3.61 {ISO week-based calendar 1887-W52-1} {
+ clock format -2588198400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1887-W52-1
+} {Mon Monday 87 1887 1 52 52 1 52}
+test clock-3.62 {ISO week-based calendar 1887-W52-6} {
+ clock format -2587766400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1887-W52-6
+} {Sat Saturday 87 1887 6 52 52 6 52}
+test clock-3.63 {ISO week-based calendar 1887-W52-7} {
+ clock format -2587680000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1887-W52-7
+} {Sun Sunday 87 1887 7 01 52 0 00}
+test clock-3.64 {ISO week-based calendar 1888-W01-1} {
+ clock format -2587593600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1888-W01-1
+} {Mon Monday 88 1888 1 01 01 1 01}
+test clock-3.65 {ISO week-based calendar 1888-W01-6} {
+ clock format -2587161600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1888-W01-6
+} {Sat Saturday 88 1888 6 01 01 6 01}
+test clock-3.66 {ISO week-based calendar 1888-W01-7} {
+ clock format -2587075200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1888-W01-7
+} {Sun Sunday 88 1888 7 02 01 0 01}
+test clock-3.67 {ISO week-based calendar 1888-W02-1} {
+ clock format -2586988800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1888-W02-1
+} {Mon Monday 88 1888 1 02 02 1 02}
+test clock-3.68 {ISO week-based calendar 1888-W52-1} {
+ clock format -2556748800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1888-W52-1
+} {Mon Monday 88 1888 1 52 52 1 52}
+test clock-3.69 {ISO week-based calendar 1888-W52-6} {
+ clock format -2556316800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1888-W52-6
+} {Sat Saturday 88 1888 6 52 52 6 52}
+test clock-3.70 {ISO week-based calendar 1888-W52-7} {
+ clock format -2556230400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1888-W52-7
+} {Sun Sunday 88 1888 7 53 52 0 52}
+test clock-3.71 {ISO week-based calendar 1889-W01-1} {
+ clock format -2556144000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1889-W01-1
+} {Mon Monday 89 1889 1 53 01 1 53}
+test clock-3.72 {ISO week-based calendar 1889-W01-2} {
+ clock format -2556057600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1889-W01-2
+} {Tue Tuesday 89 1889 2 00 01 2 00}
+test clock-3.73 {ISO week-based calendar 1889-W01-6} {
+ clock format -2555712000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1889-W01-6
+} {Sat Saturday 89 1889 6 00 01 6 00}
+test clock-3.74 {ISO week-based calendar 1889-W01-7} {
+ clock format -2555625600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1889-W01-7
+} {Sun Sunday 89 1889 7 01 01 0 00}
+test clock-3.75 {ISO week-based calendar 1889-W02-1} {
+ clock format -2555539200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1889-W02-1
+} {Mon Monday 89 1889 1 01 02 1 01}
+test clock-3.76 {ISO week-based calendar 1889-W52-1} {
+ clock format -2525299200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1889-W52-1
+} {Mon Monday 89 1889 1 51 52 1 51}
+test clock-3.77 {ISO week-based calendar 1889-W52-6} {
+ clock format -2524867200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1889-W52-6
+} {Sat Saturday 89 1889 6 51 52 6 51}
+test clock-3.78 {ISO week-based calendar 1889-W52-7} {
+ clock format -2524780800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1889-W52-7
+} {Sun Sunday 89 1889 7 52 52 0 51}
+test clock-3.79 {ISO week-based calendar 1890-W01-1} {
+ clock format -2524694400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1890-W01-1
+} {Mon Monday 90 1890 1 52 01 1 52}
+test clock-3.80 {ISO week-based calendar 1890-W01-3} {
+ clock format -2524521600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1890-W01-3
+} {Wed Wednesday 90 1890 3 00 01 3 00}
+test clock-3.81 {ISO week-based calendar 1890-W01-6} {
+ clock format -2524262400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1890-W01-6
+} {Sat Saturday 90 1890 6 00 01 6 00}
+test clock-3.82 {ISO week-based calendar 1890-W01-7} {
+ clock format -2524176000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1890-W01-7
+} {Sun Sunday 90 1890 7 01 01 0 00}
+test clock-3.83 {ISO week-based calendar 1890-W02-1} {
+ clock format -2524089600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1890-W02-1
+} {Mon Monday 90 1890 1 01 02 1 01}
+test clock-3.84 {ISO week-based calendar 1890-W52-1} {
+ clock format -2493849600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1890-W52-1
+} {Mon Monday 90 1890 1 51 52 1 51}
+test clock-3.85 {ISO week-based calendar 1890-W52-6} {
+ clock format -2493417600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1890-W52-6
+} {Sat Saturday 90 1890 6 51 52 6 51}
+test clock-3.86 {ISO week-based calendar 1890-W52-7} {
+ clock format -2493331200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1890-W52-7
+} {Sun Sunday 90 1890 7 52 52 0 51}
+test clock-3.87 {ISO week-based calendar 1891-W01-1} {
+ clock format -2493244800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1891-W01-1
+} {Mon Monday 91 1891 1 52 01 1 52}
+test clock-3.88 {ISO week-based calendar 1891-W01-4} {
+ clock format -2492985600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1891-W01-4
+} {Thu Thursday 91 1891 4 00 01 4 00}
+test clock-3.89 {ISO week-based calendar 1891-W01-6} {
+ clock format -2492812800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1891-W01-6
+} {Sat Saturday 91 1891 6 00 01 6 00}
+test clock-3.90 {ISO week-based calendar 1891-W01-7} {
+ clock format -2492726400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1891-W01-7
+} {Sun Sunday 91 1891 7 01 01 0 00}
+test clock-3.91 {ISO week-based calendar 1891-W02-1} {
+ clock format -2492640000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1891-W02-1
+} {Mon Monday 91 1891 1 01 02 1 01}
+test clock-3.92 {ISO week-based calendar 1891-W53-1} {
+ clock format -2461795200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1891-W53-1
+} {Mon Monday 91 1891 1 52 53 1 52}
+test clock-3.93 {ISO week-based calendar 1891-W53-5} {
+ clock format -2461449600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1891-W53-5
+} {Fri Friday 91 1891 5 00 53 5 00}
+test clock-3.94 {ISO week-based calendar 1891-W53-6} {
+ clock format -2461363200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1891-W53-6
+} {Sat Saturday 91 1891 6 00 53 6 00}
+test clock-3.95 {ISO week-based calendar 1891-W53-7} {
+ clock format -2461276800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1891-W53-7
+} {Sun Sunday 91 1891 7 01 53 0 00}
+test clock-3.96 {ISO week-based calendar 1892-W01-1} {
+ clock format -2461190400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1892-W01-1
+} {Mon Monday 92 1892 1 01 01 1 01}
+test clock-3.97 {ISO week-based calendar 1892-W01-6} {
+ clock format -2460758400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1892-W01-6
+} {Sat Saturday 92 1892 6 01 01 6 01}
+test clock-3.98 {ISO week-based calendar 1892-W01-7} {
+ clock format -2460672000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1892-W01-7
+} {Sun Sunday 92 1892 7 02 01 0 01}
+test clock-3.99 {ISO week-based calendar 1892-W02-1} {
+ clock format -2460585600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1892-W02-1
+} {Mon Monday 92 1892 1 02 02 1 02}
+test clock-3.100 {ISO week-based calendar 1892-W52-1} {
+ clock format -2430345600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1892-W52-1
+} {Mon Monday 92 1892 1 52 52 1 52}
+test clock-3.101 {ISO week-based calendar 1892-W52-6} {
+ clock format -2429913600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1892-W52-6
+} {Sat Saturday 92 1892 6 52 52 6 52}
+test clock-3.102 {ISO week-based calendar 1892-W52-7} {
+ clock format -2429827200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1892-W52-7
+} {Sun Sunday 92 1892 7 01 52 0 00}
+test clock-3.103 {ISO week-based calendar 1893-W01-1} {
+ clock format -2429740800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1893-W01-1
+} {Mon Monday 93 1893 1 01 01 1 01}
+test clock-3.104 {ISO week-based calendar 1893-W01-6} {
+ clock format -2429308800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1893-W01-6
+} {Sat Saturday 93 1893 6 01 01 6 01}
+test clock-3.105 {ISO week-based calendar 1893-W01-7} {
+ clock format -2429222400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1893-W01-7
+} {Sun Sunday 93 1893 7 02 01 0 01}
+test clock-3.106 {ISO week-based calendar 1893-W02-1} {
+ clock format -2429136000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1893-W02-1
+} {Mon Monday 93 1893 1 02 02 1 02}
+test clock-3.107 {ISO week-based calendar 1893-W52-1} {
+ clock format -2398896000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1893-W52-1
+} {Mon Monday 93 1893 1 52 52 1 52}
+test clock-3.108 {ISO week-based calendar 1893-W52-6} {
+ clock format -2398464000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1893-W52-6
+} {Sat Saturday 93 1893 6 52 52 6 52}
+test clock-3.109 {ISO week-based calendar 1893-W52-7} {
+ clock format -2398377600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1893-W52-7
+} {Sun Sunday 93 1893 7 53 52 0 52}
+test clock-3.110 {ISO week-based calendar 1894-W01-1} {
+ clock format -2398291200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1894-W01-1
+} {Mon Monday 94 1894 1 00 01 1 01}
+test clock-3.111 {ISO week-based calendar 1894-W01-6} {
+ clock format -2397859200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1894-W01-6
+} {Sat Saturday 94 1894 6 00 01 6 01}
+test clock-3.112 {ISO week-based calendar 1894-W01-7} {
+ clock format -2397772800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1894-W01-7
+} {Sun Sunday 94 1894 7 01 01 0 01}
+test clock-3.113 {ISO week-based calendar 1894-W02-1} {
+ clock format -2397686400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1894-W02-1
+} {Mon Monday 94 1894 1 01 02 1 02}
+test clock-3.114 {ISO week-based calendar 1894-W52-1} {
+ clock format -2367446400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1894-W52-1
+} {Mon Monday 94 1894 1 51 52 1 52}
+test clock-3.115 {ISO week-based calendar 1894-W52-6} {
+ clock format -2367014400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1894-W52-6
+} {Sat Saturday 94 1894 6 51 52 6 52}
+test clock-3.116 {ISO week-based calendar 1894-W52-7} {
+ clock format -2366928000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1894-W52-7
+} {Sun Sunday 94 1894 7 52 52 0 52}
+test clock-3.117 {ISO week-based calendar 1895-W01-1} {
+ clock format -2366841600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1895-W01-1
+} {Mon Monday 95 1895 1 52 01 1 53}
+test clock-3.118 {ISO week-based calendar 1895-W01-2} {
+ clock format -2366755200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1895-W01-2
+} {Tue Tuesday 95 1895 2 00 01 2 00}
+test clock-3.119 {ISO week-based calendar 1895-W01-6} {
+ clock format -2366409600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1895-W01-6
+} {Sat Saturday 95 1895 6 00 01 6 00}
+test clock-3.120 {ISO week-based calendar 1895-W01-7} {
+ clock format -2366323200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1895-W01-7
+} {Sun Sunday 95 1895 7 01 01 0 00}
+test clock-3.121 {ISO week-based calendar 1895-W02-1} {
+ clock format -2366236800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1895-W02-1
+} {Mon Monday 95 1895 1 01 02 1 01}
+test clock-3.122 {ISO week-based calendar 1895-W52-1} {
+ clock format -2335996800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1895-W52-1
+} {Mon Monday 95 1895 1 51 52 1 51}
+test clock-3.123 {ISO week-based calendar 1895-W52-6} {
+ clock format -2335564800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1895-W52-6
+} {Sat Saturday 95 1895 6 51 52 6 51}
+test clock-3.124 {ISO week-based calendar 1895-W52-7} {
+ clock format -2335478400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1895-W52-7
+} {Sun Sunday 95 1895 7 52 52 0 51}
+test clock-3.125 {ISO week-based calendar 1896-W01-1} {
+ clock format -2335392000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1896-W01-1
+} {Mon Monday 96 1896 1 52 01 1 52}
+test clock-3.126 {ISO week-based calendar 1896-W01-3} {
+ clock format -2335219200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1896-W01-3
+} {Wed Wednesday 96 1896 3 00 01 3 00}
+test clock-3.127 {ISO week-based calendar 1896-W01-6} {
+ clock format -2334960000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1896-W01-6
+} {Sat Saturday 96 1896 6 00 01 6 00}
+test clock-3.128 {ISO week-based calendar 1896-W01-7} {
+ clock format -2334873600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1896-W01-7
+} {Sun Sunday 96 1896 7 01 01 0 00}
+test clock-3.129 {ISO week-based calendar 1896-W02-1} {
+ clock format -2334787200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1896-W02-1
+} {Mon Monday 96 1896 1 01 02 1 01}
+test clock-3.130 {ISO week-based calendar 1896-W53-1} {
+ clock format -2303942400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1896-W53-1
+} {Mon Monday 96 1896 1 52 53 1 52}
+test clock-3.131 {ISO week-based calendar 1896-W53-5} {
+ clock format -2303596800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1896-W53-5
+} {Fri Friday 96 1896 5 00 53 5 00}
+test clock-3.132 {ISO week-based calendar 1896-W53-6} {
+ clock format -2303510400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1896-W53-6
+} {Sat Saturday 96 1896 6 00 53 6 00}
+test clock-3.133 {ISO week-based calendar 1896-W53-7} {
+ clock format -2303424000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1896-W53-7
+} {Sun Sunday 96 1896 7 01 53 0 00}
+test clock-3.134 {ISO week-based calendar 1897-W01-1} {
+ clock format -2303337600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1897-W01-1
+} {Mon Monday 97 1897 1 01 01 1 01}
+test clock-3.135 {ISO week-based calendar 1897-W01-6} {
+ clock format -2302905600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1897-W01-6
+} {Sat Saturday 97 1897 6 01 01 6 01}
+test clock-3.136 {ISO week-based calendar 1897-W01-7} {
+ clock format -2302819200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1897-W01-7
+} {Sun Sunday 97 1897 7 02 01 0 01}
+test clock-3.137 {ISO week-based calendar 1897-W02-1} {
+ clock format -2302732800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1897-W02-1
+} {Mon Monday 97 1897 1 02 02 1 02}
+test clock-3.138 {ISO week-based calendar 1897-W52-1} {
+ clock format -2272492800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1897-W52-1
+} {Mon Monday 97 1897 1 52 52 1 52}
+test clock-3.139 {ISO week-based calendar 1897-W52-6} {
+ clock format -2272060800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1897-W52-6
+} {Sat Saturday 97 1897 6 00 52 6 00}
+test clock-3.140 {ISO week-based calendar 1897-W52-7} {
+ clock format -2271974400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1897-W52-7
+} {Sun Sunday 97 1897 7 01 52 0 00}
+test clock-3.141 {ISO week-based calendar 1898-W01-1} {
+ clock format -2271888000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1898-W01-1
+} {Mon Monday 98 1898 1 01 01 1 01}
+test clock-3.142 {ISO week-based calendar 1898-W01-6} {
+ clock format -2271456000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1898-W01-6
+} {Sat Saturday 98 1898 6 01 01 6 01}
+test clock-3.143 {ISO week-based calendar 1898-W01-7} {
+ clock format -2271369600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1898-W01-7
+} {Sun Sunday 98 1898 7 02 01 0 01}
+test clock-3.144 {ISO week-based calendar 1898-W02-1} {
+ clock format -2271283200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1898-W02-1
+} {Mon Monday 98 1898 1 02 02 1 02}
+test clock-3.145 {ISO week-based calendar 1898-W52-1} {
+ clock format -2241043200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1898-W52-1
+} {Mon Monday 98 1898 1 52 52 1 52}
+test clock-3.146 {ISO week-based calendar 1898-W52-6} {
+ clock format -2240611200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1898-W52-6
+} {Sat Saturday 98 1898 6 52 52 6 52}
+test clock-3.147 {ISO week-based calendar 1898-W52-7} {
+ clock format -2240524800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1898-W52-7
+} {Sun Sunday 98 1898 7 01 52 0 00}
+test clock-3.148 {ISO week-based calendar 1899-W01-1} {
+ clock format -2240438400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1899-W01-1
+} {Mon Monday 99 1899 1 01 01 1 01}
+test clock-3.149 {ISO week-based calendar 1899-W01-6} {
+ clock format -2240006400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1899-W01-6
+} {Sat Saturday 99 1899 6 01 01 6 01}
+test clock-3.150 {ISO week-based calendar 1899-W01-7} {
+ clock format -2239920000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1899-W01-7
+} {Sun Sunday 99 1899 7 02 01 0 01}
+test clock-3.151 {ISO week-based calendar 1899-W02-1} {
+ clock format -2239833600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1899-W02-1
+} {Mon Monday 99 1899 1 02 02 1 02}
+test clock-3.152 {ISO week-based calendar 1899-W52-1} {
+ clock format -2209593600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1899-W52-1
+} {Mon Monday 99 1899 1 52 52 1 52}
+test clock-3.153 {ISO week-based calendar 1899-W52-6} {
+ clock format -2209161600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1899-W52-6
+} {Sat Saturday 99 1899 6 52 52 6 52}
+test clock-3.154 {ISO week-based calendar 1899-W52-7} {
+ clock format -2209075200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1899-W52-7
+} {Sun Sunday 99 1899 7 53 52 0 52}
+test clock-3.155 {ISO week-based calendar 1900-W01-1} {
+ clock format -2208988800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1900-W01-1
+} {Mon Monday 00 1900 1 00 01 1 01}
+test clock-3.156 {ISO week-based calendar 1900-W01-6} {
+ clock format -2208556800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1900-W01-6
+} {Sat Saturday 00 1900 6 00 01 6 01}
+test clock-3.157 {ISO week-based calendar 1900-W01-7} {
+ clock format -2208470400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1900-W01-7
+} {Sun Sunday 00 1900 7 01 01 0 01}
+test clock-3.158 {ISO week-based calendar 1900-W02-1} {
+ clock format -2208384000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1900-W02-1
+} {Mon Monday 00 1900 1 01 02 1 02}
+test clock-3.159 {ISO week-based calendar 1943-W52-1} {
+ clock format -820972800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1943-W52-1
+} {Mon Monday 43 1943 1 52 52 1 52}
+test clock-3.160 {ISO week-based calendar 1943-W52-6} {
+ clock format -820540800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1943-W52-6
+} {Sat Saturday 43 1943 6 00 52 6 00}
+test clock-3.161 {ISO week-based calendar 1943-W52-7} {
+ clock format -820454400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1943-W52-7
+} {Sun Sunday 43 1943 7 01 52 0 00}
+test clock-3.162 {ISO week-based calendar 1944-W01-1} {
+ clock format -820368000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1944-W01-1
+} {Mon Monday 44 1944 1 01 01 1 01}
+test clock-3.163 {ISO week-based calendar 1944-W01-6} {
+ clock format -819936000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1944-W01-6
+} {Sat Saturday 44 1944 6 01 01 6 01}
+test clock-3.164 {ISO week-based calendar 1944-W01-7} {
+ clock format -819849600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1944-W01-7
+} {Sun Sunday 44 1944 7 02 01 0 01}
+test clock-3.165 {ISO week-based calendar 1944-W02-1} {
+ clock format -819763200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1944-W02-1
+} {Mon Monday 44 1944 1 02 02 1 02}
+test clock-3.166 {ISO week-based calendar 1944-W52-1} {
+ clock format -789523200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1944-W52-1
+} {Mon Monday 44 1944 1 52 52 1 52}
+test clock-3.167 {ISO week-based calendar 1944-W52-6} {
+ clock format -789091200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1944-W52-6
+} {Sat Saturday 44 1944 6 52 52 6 52}
+test clock-3.168 {ISO week-based calendar 1944-W52-7} {
+ clock format -789004800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1944-W52-7
+} {Sun Sunday 44 1944 7 53 52 0 52}
+test clock-3.169 {ISO week-based calendar 1945-W01-1} {
+ clock format -788918400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1945-W01-1
+} {Mon Monday 45 1945 1 00 01 1 01}
+test clock-3.170 {ISO week-based calendar 1945-W01-6} {
+ clock format -788486400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1945-W01-6
+} {Sat Saturday 45 1945 6 00 01 6 01}
+test clock-3.171 {ISO week-based calendar 1945-W01-7} {
+ clock format -788400000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1945-W01-7
+} {Sun Sunday 45 1945 7 01 01 0 01}
+test clock-3.172 {ISO week-based calendar 1945-W02-1} {
+ clock format -788313600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1945-W02-1
+} {Mon Monday 45 1945 1 01 02 1 02}
+test clock-3.173 {ISO week-based calendar 1947-W52-1} {
+ clock format -695174400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1947-W52-1
+} {Mon Monday 47 1947 1 51 52 1 51}
+test clock-3.174 {ISO week-based calendar 1947-W52-6} {
+ clock format -694742400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1947-W52-6
+} {Sat Saturday 47 1947 6 51 52 6 51}
+test clock-3.175 {ISO week-based calendar 1947-W52-7} {
+ clock format -694656000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1947-W52-7
+} {Sun Sunday 47 1947 7 52 52 0 51}
+test clock-3.176 {ISO week-based calendar 1948-W01-1} {
+ clock format -694569600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1948-W01-1
+} {Mon Monday 48 1948 1 52 01 1 52}
+test clock-3.177 {ISO week-based calendar 1948-W01-4} {
+ clock format -694310400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1948-W01-4
+} {Thu Thursday 48 1948 4 00 01 4 00}
+test clock-3.178 {ISO week-based calendar 1948-W01-6} {
+ clock format -694137600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1948-W01-6
+} {Sat Saturday 48 1948 6 00 01 6 00}
+test clock-3.179 {ISO week-based calendar 1948-W01-7} {
+ clock format -694051200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1948-W01-7
+} {Sun Sunday 48 1948 7 01 01 0 00}
+test clock-3.180 {ISO week-based calendar 1948-W02-1} {
+ clock format -693964800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1948-W02-1
+} {Mon Monday 48 1948 1 01 02 1 01}
+test clock-3.181 {ISO week-based calendar 1948-W53-1} {
+ clock format -663120000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1948-W53-1
+} {Mon Monday 48 1948 1 52 53 1 52}
+test clock-3.182 {ISO week-based calendar 1948-W53-6} {
+ clock format -662688000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1948-W53-6
+} {Sat Saturday 48 1948 6 00 53 6 00}
+test clock-3.183 {ISO week-based calendar 1948-W53-7} {
+ clock format -662601600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1948-W53-7
+} {Sun Sunday 48 1948 7 01 53 0 00}
+test clock-3.184 {ISO week-based calendar 1949-W01-1} {
+ clock format -662515200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1949-W01-1
+} {Mon Monday 49 1949 1 01 01 1 01}
+test clock-3.185 {ISO week-based calendar 1949-W01-6} {
+ clock format -662083200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1949-W01-6
+} {Sat Saturday 49 1949 6 01 01 6 01}
+test clock-3.186 {ISO week-based calendar 1949-W01-7} {
+ clock format -661996800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1949-W01-7
+} {Sun Sunday 49 1949 7 02 01 0 01}
+test clock-3.187 {ISO week-based calendar 1949-W02-1} {
+ clock format -661910400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1949-W02-1
+} {Mon Monday 49 1949 1 02 02 1 02}
+test clock-3.188 {ISO week-based calendar 1951-W52-1} {
+ clock format -568771200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1951-W52-1
+} {Mon Monday 51 1951 1 51 52 1 52}
+test clock-3.189 {ISO week-based calendar 1951-W52-6} {
+ clock format -568339200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1951-W52-6
+} {Sat Saturday 51 1951 6 51 52 6 52}
+test clock-3.190 {ISO week-based calendar 1951-W52-7} {
+ clock format -568252800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1951-W52-7
+} {Sun Sunday 51 1951 7 52 52 0 52}
+test clock-3.191 {ISO week-based calendar 1952-W01-1} {
+ clock format -568166400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1952-W01-1
+} {Mon Monday 52 1952 1 52 01 1 53}
+test clock-3.192 {ISO week-based calendar 1952-W01-2} {
+ clock format -568080000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1952-W01-2
+} {Tue Tuesday 52 1952 2 00 01 2 00}
+test clock-3.193 {ISO week-based calendar 1952-W01-6} {
+ clock format -567734400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1952-W01-6
+} {Sat Saturday 52 1952 6 00 01 6 00}
+test clock-3.194 {ISO week-based calendar 1952-W01-7} {
+ clock format -567648000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1952-W01-7
+} {Sun Sunday 52 1952 7 01 01 0 00}
+test clock-3.195 {ISO week-based calendar 1952-W02-1} {
+ clock format -567561600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1952-W02-1
+} {Mon Monday 52 1952 1 01 02 1 01}
+test clock-3.196 {ISO week-based calendar 1952-W52-1} {
+ clock format -537321600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1952-W52-1
+} {Mon Monday 52 1952 1 51 52 1 51}
+test clock-3.197 {ISO week-based calendar 1952-W52-6} {
+ clock format -536889600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1952-W52-6
+} {Sat Saturday 52 1952 6 51 52 6 51}
+test clock-3.198 {ISO week-based calendar 1952-W52-7} {
+ clock format -536803200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1952-W52-7
+} {Sun Sunday 52 1952 7 52 52 0 51}
+test clock-3.199 {ISO week-based calendar 1953-W01-1} {
+ clock format -536716800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1953-W01-1
+} {Mon Monday 53 1953 1 52 01 1 52}
+test clock-3.200 {ISO week-based calendar 1953-W01-4} {
+ clock format -536457600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1953-W01-4
+} {Thu Thursday 53 1953 4 00 01 4 00}
+test clock-3.201 {ISO week-based calendar 1953-W01-6} {
+ clock format -536284800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1953-W01-6
+} {Sat Saturday 53 1953 6 00 01 6 00}
+test clock-3.202 {ISO week-based calendar 1953-W01-7} {
+ clock format -536198400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1953-W01-7
+} {Sun Sunday 53 1953 7 01 01 0 00}
+test clock-3.203 {ISO week-based calendar 1953-W02-1} {
+ clock format -536112000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1953-W02-1
+} {Mon Monday 53 1953 1 01 02 1 01}
+test clock-3.204 {ISO week-based calendar 1955-W52-1} {
+ clock format -442368000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1955-W52-1
+} {Mon Monday 55 1955 1 52 52 1 52}
+test clock-3.205 {ISO week-based calendar 1955-W52-6} {
+ clock format -441936000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1955-W52-6
+} {Sat Saturday 55 1955 6 52 52 6 52}
+test clock-3.206 {ISO week-based calendar 1955-W52-7} {
+ clock format -441849600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1955-W52-7
+} {Sun Sunday 55 1955 7 01 52 0 00}
+test clock-3.207 {ISO week-based calendar 1956-W01-1} {
+ clock format -441763200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1956-W01-1
+} {Mon Monday 56 1956 1 01 01 1 01}
+test clock-3.208 {ISO week-based calendar 1956-W01-6} {
+ clock format -441331200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1956-W01-6
+} {Sat Saturday 56 1956 6 01 01 6 01}
+test clock-3.209 {ISO week-based calendar 1956-W01-7} {
+ clock format -441244800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1956-W01-7
+} {Sun Sunday 56 1956 7 02 01 0 01}
+test clock-3.210 {ISO week-based calendar 1956-W02-1} {
+ clock format -441158400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1956-W02-1
+} {Mon Monday 56 1956 1 02 02 1 02}
+test clock-3.211 {ISO week-based calendar 1956-W52-1} {
+ clock format -410918400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1956-W52-1
+} {Mon Monday 56 1956 1 52 52 1 52}
+test clock-3.212 {ISO week-based calendar 1956-W52-6} {
+ clock format -410486400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1956-W52-6
+} {Sat Saturday 56 1956 6 52 52 6 52}
+test clock-3.213 {ISO week-based calendar 1956-W52-7} {
+ clock format -410400000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1956-W52-7
+} {Sun Sunday 56 1956 7 53 52 0 52}
+test clock-3.214 {ISO week-based calendar 1957-W01-1} {
+ clock format -410313600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1957-W01-1
+} {Mon Monday 57 1957 1 53 01 1 53}
+test clock-3.215 {ISO week-based calendar 1957-W01-2} {
+ clock format -410227200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1957-W01-2
+} {Tue Tuesday 57 1957 2 00 01 2 00}
+test clock-3.216 {ISO week-based calendar 1957-W01-6} {
+ clock format -409881600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1957-W01-6
+} {Sat Saturday 57 1957 6 00 01 6 00}
+test clock-3.217 {ISO week-based calendar 1957-W01-7} {
+ clock format -409795200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1957-W01-7
+} {Sun Sunday 57 1957 7 01 01 0 00}
+test clock-3.218 {ISO week-based calendar 1957-W02-1} {
+ clock format -409708800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1957-W02-1
+} {Mon Monday 57 1957 1 01 02 1 01}
+test clock-3.219 {ISO week-based calendar 1958-W52-1} {
+ clock format -348019200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1958-W52-1
+} {Mon Monday 58 1958 1 51 52 1 51}
+test clock-3.220 {ISO week-based calendar 1958-W52-6} {
+ clock format -347587200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1958-W52-6
+} {Sat Saturday 58 1958 6 51 52 6 51}
+test clock-3.221 {ISO week-based calendar 1958-W52-7} {
+ clock format -347500800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1958-W52-7
+} {Sun Sunday 58 1958 7 52 52 0 51}
+test clock-3.222 {ISO week-based calendar 1959-W01-1} {
+ clock format -347414400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1959-W01-1
+} {Mon Monday 59 1959 1 52 01 1 52}
+test clock-3.223 {ISO week-based calendar 1959-W01-4} {
+ clock format -347155200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1959-W01-4
+} {Thu Thursday 59 1959 4 00 01 4 00}
+test clock-3.224 {ISO week-based calendar 1959-W01-6} {
+ clock format -346982400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1959-W01-6
+} {Sat Saturday 59 1959 6 00 01 6 00}
+test clock-3.225 {ISO week-based calendar 1959-W01-7} {
+ clock format -346896000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1959-W01-7
+} {Sun Sunday 59 1959 7 01 01 0 00}
+test clock-3.226 {ISO week-based calendar 1959-W02-1} {
+ clock format -346809600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1959-W02-1
+} {Mon Monday 59 1959 1 01 02 1 01}
+test clock-3.227 {ISO week-based calendar 1959-W53-1} {
+ clock format -315964800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1959-W53-1
+} {Mon Monday 59 1959 1 52 53 1 52}
+test clock-3.228 {ISO week-based calendar 1959-W53-5} {
+ clock format -315619200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1959-W53-5
+} {Fri Friday 59 1959 5 00 53 5 00}
+test clock-3.229 {ISO week-based calendar 1959-W53-6} {
+ clock format -315532800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1959-W53-6
+} {Sat Saturday 59 1959 6 00 53 6 00}
+test clock-3.230 {ISO week-based calendar 1959-W53-7} {
+ clock format -315446400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1959-W53-7
+} {Sun Sunday 59 1959 7 01 53 0 00}
+test clock-3.231 {ISO week-based calendar 1960-W01-1} {
+ clock format -315360000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1960-W01-1
+} {Mon Monday 60 1960 1 01 01 1 01}
+test clock-3.232 {ISO week-based calendar 1960-W01-6} {
+ clock format -314928000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1960-W01-6
+} {Sat Saturday 60 1960 6 01 01 6 01}
+test clock-3.233 {ISO week-based calendar 1960-W01-7} {
+ clock format -314841600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1960-W01-7
+} {Sun Sunday 60 1960 7 02 01 0 01}
+test clock-3.234 {ISO week-based calendar 1960-W02-1} {
+ clock format -314755200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1960-W02-1
+} {Mon Monday 60 1960 1 02 02 1 02}
+test clock-3.235 {ISO week-based calendar 1960-W52-1} {
+ clock format -284515200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1960-W52-1
+} {Mon Monday 60 1960 1 52 52 1 52}
+test clock-3.236 {ISO week-based calendar 1960-W52-6} {
+ clock format -284083200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1960-W52-6
+} {Sat Saturday 60 1960 6 52 52 6 52}
+test clock-3.237 {ISO week-based calendar 1960-W52-7} {
+ clock format -283996800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1960-W52-7
+} {Sun Sunday 60 1960 7 01 52 0 00}
+test clock-3.238 {ISO week-based calendar 1961-W01-1} {
+ clock format -283910400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1961-W01-1
+} {Mon Monday 61 1961 1 01 01 1 01}
+test clock-3.239 {ISO week-based calendar 1961-W01-6} {
+ clock format -283478400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1961-W01-6
+} {Sat Saturday 61 1961 6 01 01 6 01}
+test clock-3.240 {ISO week-based calendar 1961-W01-7} {
+ clock format -283392000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1961-W01-7
+} {Sun Sunday 61 1961 7 02 01 0 01}
+test clock-3.241 {ISO week-based calendar 1961-W02-1} {
+ clock format -283305600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1961-W02-1
+} {Mon Monday 61 1961 1 02 02 1 02}
+test clock-3.242 {ISO week-based calendar 1961-W52-1} {
+ clock format -253065600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1961-W52-1
+} {Mon Monday 61 1961 1 52 52 1 52}
+test clock-3.243 {ISO week-based calendar 1961-W52-6} {
+ clock format -252633600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1961-W52-6
+} {Sat Saturday 61 1961 6 52 52 6 52}
+test clock-3.244 {ISO week-based calendar 1961-W52-7} {
+ clock format -252547200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1961-W52-7
+} {Sun Sunday 61 1961 7 53 52 0 52}
+test clock-3.245 {ISO week-based calendar 1962-W01-1} {
+ clock format -252460800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1962-W01-1
+} {Mon Monday 62 1962 1 00 01 1 01}
+test clock-3.246 {ISO week-based calendar 1962-W01-6} {
+ clock format -252028800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1962-W01-6
+} {Sat Saturday 62 1962 6 00 01 6 01}
+test clock-3.247 {ISO week-based calendar 1962-W01-7} {
+ clock format -251942400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1962-W01-7
+} {Sun Sunday 62 1962 7 01 01 0 01}
+test clock-3.248 {ISO week-based calendar 1962-W02-1} {
+ clock format -251856000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1962-W02-1
+} {Mon Monday 62 1962 1 01 02 1 02}
+test clock-3.249 {ISO week-based calendar 1962-W52-1} {
+ clock format -221616000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1962-W52-1
+} {Mon Monday 62 1962 1 51 52 1 52}
+test clock-3.250 {ISO week-based calendar 1962-W52-6} {
+ clock format -221184000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1962-W52-6
+} {Sat Saturday 62 1962 6 51 52 6 52}
+test clock-3.251 {ISO week-based calendar 1962-W52-7} {
+ clock format -221097600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1962-W52-7
+} {Sun Sunday 62 1962 7 52 52 0 52}
+test clock-3.252 {ISO week-based calendar 1963-W01-1} {
+ clock format -221011200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1963-W01-1
+} {Mon Monday 63 1963 1 52 01 1 53}
+test clock-3.253 {ISO week-based calendar 1963-W01-2} {
+ clock format -220924800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1963-W01-2
+} {Tue Tuesday 63 1963 2 00 01 2 00}
+test clock-3.254 {ISO week-based calendar 1963-W01-6} {
+ clock format -220579200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1963-W01-6
+} {Sat Saturday 63 1963 6 00 01 6 00}
+test clock-3.255 {ISO week-based calendar 1963-W01-7} {
+ clock format -220492800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1963-W01-7
+} {Sun Sunday 63 1963 7 01 01 0 00}
+test clock-3.256 {ISO week-based calendar 1963-W02-1} {
+ clock format -220406400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1963-W02-1
+} {Mon Monday 63 1963 1 01 02 1 01}
+test clock-3.257 {ISO week-based calendar 1963-W52-1} {
+ clock format -190166400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1963-W52-1
+} {Mon Monday 63 1963 1 51 52 1 51}
+test clock-3.258 {ISO week-based calendar 1963-W52-6} {
+ clock format -189734400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1963-W52-6
+} {Sat Saturday 63 1963 6 51 52 6 51}
+test clock-3.259 {ISO week-based calendar 1963-W52-7} {
+ clock format -189648000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1963-W52-7
+} {Sun Sunday 63 1963 7 52 52 0 51}
+test clock-3.260 {ISO week-based calendar 1964-W01-1} {
+ clock format -189561600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1964-W01-1
+} {Mon Monday 64 1964 1 52 01 1 52}
+test clock-3.261 {ISO week-based calendar 1964-W01-3} {
+ clock format -189388800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1964-W01-3
+} {Wed Wednesday 64 1964 3 00 01 3 00}
+test clock-3.262 {ISO week-based calendar 1964-W01-6} {
+ clock format -189129600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1964-W01-6
+} {Sat Saturday 64 1964 6 00 01 6 00}
+test clock-3.263 {ISO week-based calendar 1964-W01-7} {
+ clock format -189043200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1964-W01-7
+} {Sun Sunday 64 1964 7 01 01 0 00}
+test clock-3.264 {ISO week-based calendar 1964-W02-1} {
+ clock format -188956800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1964-W02-1
+} {Mon Monday 64 1964 1 01 02 1 01}
+test clock-3.265 {ISO week-based calendar 1964-W53-1} {
+ clock format -158112000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1964-W53-1
+} {Mon Monday 64 1964 1 52 53 1 52}
+test clock-3.266 {ISO week-based calendar 1964-W53-5} {
+ clock format -157766400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1964-W53-5
+} {Fri Friday 64 1964 5 00 53 5 00}
+test clock-3.267 {ISO week-based calendar 1964-W53-6} {
+ clock format -157680000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1964-W53-6
+} {Sat Saturday 64 1964 6 00 53 6 00}
+test clock-3.268 {ISO week-based calendar 1964-W53-7} {
+ clock format -157593600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1964-W53-7
+} {Sun Sunday 64 1964 7 01 53 0 00}
+test clock-3.269 {ISO week-based calendar 1965-W01-1} {
+ clock format -157507200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1965-W01-1
+} {Mon Monday 65 1965 1 01 01 1 01}
+test clock-3.270 {ISO week-based calendar 1965-W01-6} {
+ clock format -157075200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1965-W01-6
+} {Sat Saturday 65 1965 6 01 01 6 01}
+test clock-3.271 {ISO week-based calendar 1965-W01-7} {
+ clock format -156988800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1965-W01-7
+} {Sun Sunday 65 1965 7 02 01 0 01}
+test clock-3.272 {ISO week-based calendar 1965-W02-1} {
+ clock format -156902400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1965-W02-1
+} {Mon Monday 65 1965 1 02 02 1 02}
+test clock-3.273 {ISO week-based calendar 1965-W52-1} {
+ clock format -126662400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1965-W52-1
+} {Mon Monday 65 1965 1 52 52 1 52}
+test clock-3.274 {ISO week-based calendar 1965-W52-6} {
+ clock format -126230400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1965-W52-6
+} {Sat Saturday 65 1965 6 00 52 6 00}
+test clock-3.275 {ISO week-based calendar 1965-W52-7} {
+ clock format -126144000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1965-W52-7
+} {Sun Sunday 65 1965 7 01 52 0 00}
+test clock-3.276 {ISO week-based calendar 1966-W01-1} {
+ clock format -126057600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1966-W01-1
+} {Mon Monday 66 1966 1 01 01 1 01}
+test clock-3.277 {ISO week-based calendar 1966-W01-6} {
+ clock format -125625600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1966-W01-6
+} {Sat Saturday 66 1966 6 01 01 6 01}
+test clock-3.278 {ISO week-based calendar 1966-W01-7} {
+ clock format -125539200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1966-W01-7
+} {Sun Sunday 66 1966 7 02 01 0 01}
+test clock-3.279 {ISO week-based calendar 1966-W02-1} {
+ clock format -125452800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1966-W02-1
+} {Mon Monday 66 1966 1 02 02 1 02}
+test clock-3.280 {ISO week-based calendar 1966-W52-1} {
+ clock format -95212800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1966-W52-1
+} {Mon Monday 66 1966 1 52 52 1 52}
+test clock-3.281 {ISO week-based calendar 1966-W52-6} {
+ clock format -94780800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1966-W52-6
+} {Sat Saturday 66 1966 6 52 52 6 52}
+test clock-3.282 {ISO week-based calendar 1966-W52-7} {
+ clock format -94694400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1966-W52-7
+} {Sun Sunday 66 1966 7 01 52 0 00}
+test clock-3.283 {ISO week-based calendar 1967-W01-1} {
+ clock format -94608000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1967-W01-1
+} {Mon Monday 67 1967 1 01 01 1 01}
+test clock-3.284 {ISO week-based calendar 1967-W01-6} {
+ clock format -94176000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1967-W01-6
+} {Sat Saturday 67 1967 6 01 01 6 01}
+test clock-3.285 {ISO week-based calendar 1967-W01-7} {
+ clock format -94089600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1967-W01-7
+} {Sun Sunday 67 1967 7 02 01 0 01}
+test clock-3.286 {ISO week-based calendar 1967-W02-1} {
+ clock format -94003200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1967-W02-1
+} {Mon Monday 67 1967 1 02 02 1 02}
+test clock-3.287 {ISO week-based calendar 1967-W52-1} {
+ clock format -63763200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1967-W52-1
+} {Mon Monday 67 1967 1 52 52 1 52}
+test clock-3.288 {ISO week-based calendar 1967-W52-6} {
+ clock format -63331200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1967-W52-6
+} {Sat Saturday 67 1967 6 52 52 6 52}
+test clock-3.289 {ISO week-based calendar 1967-W52-7} {
+ clock format -63244800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1967-W52-7
+} {Sun Sunday 67 1967 7 53 52 0 52}
+test clock-3.290 {ISO week-based calendar 1968-W01-1} {
+ clock format -63158400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1968-W01-1
+} {Mon Monday 68 1968 1 00 01 1 01}
+test clock-3.291 {ISO week-based calendar 1968-W01-6} {
+ clock format -62726400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1968-W01-6
+} {Sat Saturday 68 1968 6 00 01 6 01}
+test clock-3.292 {ISO week-based calendar 1968-W01-7} {
+ clock format -62640000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1968-W01-7
+} {Sun Sunday 68 1968 7 01 01 0 01}
+test clock-3.293 {ISO week-based calendar 1968-W02-1} {
+ clock format -62553600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1968-W02-1
+} {Mon Monday 68 1968 1 01 02 1 02}
+test clock-3.294 {ISO week-based calendar 1968-W52-1} {
+ clock format -32313600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1968-W52-1
+} {Mon Monday 68 1968 1 51 52 1 52}
+test clock-3.295 {ISO week-based calendar 1968-W52-6} {
+ clock format -31881600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1968-W52-6
+} {Sat Saturday 68 1968 6 51 52 6 52}
+test clock-3.296 {ISO week-based calendar 1968-W52-7} {
+ clock format -31795200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1968-W52-7
+} {Sun Sunday 68 1968 7 52 52 0 52}
+test clock-3.297 {ISO week-based calendar 1969-W01-1} {
+ clock format -31708800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1969-W01-1
+} {Mon Monday 69 1969 1 52 01 1 53}
+test clock-3.298 {ISO week-based calendar 1969-W01-3} {
+ clock format -31536000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1969-W01-3
+} {Wed Wednesday 69 1969 3 00 01 3 00}
+test clock-3.299 {ISO week-based calendar 1969-W01-6} {
+ clock format -31276800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1969-W01-6
+} {Sat Saturday 69 1969 6 00 01 6 00}
+test clock-3.300 {ISO week-based calendar 1969-W01-7} {
+ clock format -31190400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1969-W01-7
+} {Sun Sunday 69 1969 7 01 01 0 00}
+test clock-3.301 {ISO week-based calendar 1969-W02-1} {
+ clock format -31104000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1969-W02-1
+} {Mon Monday 69 1969 1 01 02 1 01}
+test clock-3.302 {ISO week-based calendar 1969-W52-1} {
+ clock format -864000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1969-W52-1
+} {Mon Monday 69 1969 1 51 52 1 51}
+test clock-3.303 {ISO week-based calendar 1969-W52-6} {
+ clock format -432000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1969-W52-6
+} {Sat Saturday 69 1969 6 51 52 6 51}
+test clock-3.304 {ISO week-based calendar 1969-W52-7} {
+ clock format -345600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1969-W52-7
+} {Sun Sunday 69 1969 7 52 52 0 51}
+test clock-3.305 {ISO week-based calendar 1970-W01-1} {
+ clock format -259200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1970-W01-1
+} {Mon Monday 70 1970 1 52 01 1 52}
+test clock-3.306 {ISO week-based calendar 1970-W01-4} {
+ clock format 0 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1970-W01-4
+} {Thu Thursday 70 1970 4 00 01 4 00}
+test clock-3.307 {ISO week-based calendar 1970-W01-6} {
+ clock format 172800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1970-W01-6
+} {Sat Saturday 70 1970 6 00 01 6 00}
+test clock-3.308 {ISO week-based calendar 1970-W01-7} {
+ clock format 259200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1970-W01-7
+} {Sun Sunday 70 1970 7 01 01 0 00}
+test clock-3.309 {ISO week-based calendar 1970-W02-1} {
+ clock format 345600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1970-W02-1
+} {Mon Monday 70 1970 1 01 02 1 01}
+test clock-3.310 {ISO week-based calendar 1970-W53-1} {
+ clock format 31190400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1970-W53-1
+} {Mon Monday 70 1970 1 52 53 1 52}
+test clock-3.311 {ISO week-based calendar 1970-W53-5} {
+ clock format 31536000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1970-W53-5
+} {Fri Friday 70 1970 5 00 53 5 00}
+test clock-3.312 {ISO week-based calendar 1970-W53-6} {
+ clock format 31622400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1970-W53-6
+} {Sat Saturday 70 1970 6 00 53 6 00}
+test clock-3.313 {ISO week-based calendar 1970-W53-7} {
+ clock format 31708800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1970-W53-7
+} {Sun Sunday 70 1970 7 01 53 0 00}
+test clock-3.314 {ISO week-based calendar 1971-W01-1} {
+ clock format 31795200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1971-W01-1
+} {Mon Monday 71 1971 1 01 01 1 01}
+test clock-3.315 {ISO week-based calendar 1971-W01-6} {
+ clock format 32227200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1971-W01-6
+} {Sat Saturday 71 1971 6 01 01 6 01}
+test clock-3.316 {ISO week-based calendar 1971-W01-7} {
+ clock format 32313600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1971-W01-7
+} {Sun Sunday 71 1971 7 02 01 0 01}
+test clock-3.317 {ISO week-based calendar 1971-W02-1} {
+ clock format 32400000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1971-W02-1
+} {Mon Monday 71 1971 1 02 02 1 02}
+test clock-3.318 {ISO week-based calendar 1971-W52-1} {
+ clock format 62640000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1971-W52-1
+} {Mon Monday 71 1971 1 52 52 1 52}
+test clock-3.319 {ISO week-based calendar 1971-W52-6} {
+ clock format 63072000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1971-W52-6
+} {Sat Saturday 71 1971 6 00 52 6 00}
+test clock-3.320 {ISO week-based calendar 1971-W52-7} {
+ clock format 63158400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1971-W52-7
+} {Sun Sunday 71 1971 7 01 52 0 00}
+test clock-3.321 {ISO week-based calendar 1972-W01-1} {
+ clock format 63244800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1972-W01-1
+} {Mon Monday 72 1972 1 01 01 1 01}
+test clock-3.322 {ISO week-based calendar 1972-W01-6} {
+ clock format 63676800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1972-W01-6
+} {Sat Saturday 72 1972 6 01 01 6 01}
+test clock-3.323 {ISO week-based calendar 1972-W01-7} {
+ clock format 63763200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1972-W01-7
+} {Sun Sunday 72 1972 7 02 01 0 01}
+test clock-3.324 {ISO week-based calendar 1972-W02-1} {
+ clock format 63849600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1972-W02-1
+} {Mon Monday 72 1972 1 02 02 1 02}
+test clock-3.325 {ISO week-based calendar 1972-W52-1} {
+ clock format 94089600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1972-W52-1
+} {Mon Monday 72 1972 1 52 52 1 52}
+test clock-3.326 {ISO week-based calendar 1972-W52-6} {
+ clock format 94521600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1972-W52-6
+} {Sat Saturday 72 1972 6 52 52 6 52}
+test clock-3.327 {ISO week-based calendar 1972-W52-7} {
+ clock format 94608000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1972-W52-7
+} {Sun Sunday 72 1972 7 53 52 0 52}
+test clock-3.328 {ISO week-based calendar 1973-W01-1} {
+ clock format 94694400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1973-W01-1
+} {Mon Monday 73 1973 1 00 01 1 01}
+test clock-3.329 {ISO week-based calendar 1973-W01-6} {
+ clock format 95126400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1973-W01-6
+} {Sat Saturday 73 1973 6 00 01 6 01}
+test clock-3.330 {ISO week-based calendar 1973-W01-7} {
+ clock format 95212800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1973-W01-7
+} {Sun Sunday 73 1973 7 01 01 0 01}
+test clock-3.331 {ISO week-based calendar 1973-W02-1} {
+ clock format 95299200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1973-W02-1
+} {Mon Monday 73 1973 1 01 02 1 02}
+test clock-3.332 {ISO week-based calendar 1973-W52-1} {
+ clock format 125539200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1973-W52-1
+} {Mon Monday 73 1973 1 51 52 1 52}
+test clock-3.333 {ISO week-based calendar 1973-W52-6} {
+ clock format 125971200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1973-W52-6
+} {Sat Saturday 73 1973 6 51 52 6 52}
+test clock-3.334 {ISO week-based calendar 1973-W52-7} {
+ clock format 126057600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1973-W52-7
+} {Sun Sunday 73 1973 7 52 52 0 52}
+test clock-3.335 {ISO week-based calendar 1974-W01-1} {
+ clock format 126144000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1974-W01-1
+} {Mon Monday 74 1974 1 52 01 1 53}
+test clock-3.336 {ISO week-based calendar 1974-W01-2} {
+ clock format 126230400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1974-W01-2
+} {Tue Tuesday 74 1974 2 00 01 2 00}
+test clock-3.337 {ISO week-based calendar 1974-W01-6} {
+ clock format 126576000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1974-W01-6
+} {Sat Saturday 74 1974 6 00 01 6 00}
+test clock-3.338 {ISO week-based calendar 1974-W01-7} {
+ clock format 126662400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1974-W01-7
+} {Sun Sunday 74 1974 7 01 01 0 00}
+test clock-3.339 {ISO week-based calendar 1974-W02-1} {
+ clock format 126748800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1974-W02-1
+} {Mon Monday 74 1974 1 01 02 1 01}
+test clock-3.340 {ISO week-based calendar 1974-W52-1} {
+ clock format 156988800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1974-W52-1
+} {Mon Monday 74 1974 1 51 52 1 51}
+test clock-3.341 {ISO week-based calendar 1974-W52-6} {
+ clock format 157420800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1974-W52-6
+} {Sat Saturday 74 1974 6 51 52 6 51}
+test clock-3.342 {ISO week-based calendar 1974-W52-7} {
+ clock format 157507200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1974-W52-7
+} {Sun Sunday 74 1974 7 52 52 0 51}
+test clock-3.343 {ISO week-based calendar 1975-W01-1} {
+ clock format 157593600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1975-W01-1
+} {Mon Monday 75 1975 1 52 01 1 52}
+test clock-3.344 {ISO week-based calendar 1975-W01-3} {
+ clock format 157766400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1975-W01-3
+} {Wed Wednesday 75 1975 3 00 01 3 00}
+test clock-3.345 {ISO week-based calendar 1975-W01-6} {
+ clock format 158025600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1975-W01-6
+} {Sat Saturday 75 1975 6 00 01 6 00}
+test clock-3.346 {ISO week-based calendar 1975-W01-7} {
+ clock format 158112000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1975-W01-7
+} {Sun Sunday 75 1975 7 01 01 0 00}
+test clock-3.347 {ISO week-based calendar 1975-W02-1} {
+ clock format 158198400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1975-W02-1
+} {Mon Monday 75 1975 1 01 02 1 01}
+test clock-3.348 {ISO week-based calendar 1975-W52-1} {
+ clock format 188438400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1975-W52-1
+} {Mon Monday 75 1975 1 51 52 1 51}
+test clock-3.349 {ISO week-based calendar 1975-W52-6} {
+ clock format 188870400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1975-W52-6
+} {Sat Saturday 75 1975 6 51 52 6 51}
+test clock-3.350 {ISO week-based calendar 1975-W52-7} {
+ clock format 188956800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1975-W52-7
+} {Sun Sunday 75 1975 7 52 52 0 51}
+test clock-3.351 {ISO week-based calendar 1976-W01-1} {
+ clock format 189043200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1976-W01-1
+} {Mon Monday 76 1976 1 52 01 1 52}
+test clock-3.352 {ISO week-based calendar 1976-W01-4} {
+ clock format 189302400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1976-W01-4
+} {Thu Thursday 76 1976 4 00 01 4 00}
+test clock-3.353 {ISO week-based calendar 1976-W01-6} {
+ clock format 189475200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1976-W01-6
+} {Sat Saturday 76 1976 6 00 01 6 00}
+test clock-3.354 {ISO week-based calendar 1976-W01-7} {
+ clock format 189561600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1976-W01-7
+} {Sun Sunday 76 1976 7 01 01 0 00}
+test clock-3.355 {ISO week-based calendar 1976-W02-1} {
+ clock format 189648000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1976-W02-1
+} {Mon Monday 76 1976 1 01 02 1 01}
+test clock-3.356 {ISO week-based calendar 1976-W53-1} {
+ clock format 220492800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1976-W53-1
+} {Mon Monday 76 1976 1 52 53 1 52}
+test clock-3.357 {ISO week-based calendar 1976-W53-6} {
+ clock format 220924800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1976-W53-6
+} {Sat Saturday 76 1976 6 00 53 6 00}
+test clock-3.358 {ISO week-based calendar 1976-W53-7} {
+ clock format 221011200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1976-W53-7
+} {Sun Sunday 76 1976 7 01 53 0 00}
+test clock-3.359 {ISO week-based calendar 1977-W01-1} {
+ clock format 221097600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1977-W01-1
+} {Mon Monday 77 1977 1 01 01 1 01}
+test clock-3.360 {ISO week-based calendar 1977-W01-6} {
+ clock format 221529600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1977-W01-6
+} {Sat Saturday 77 1977 6 01 01 6 01}
+test clock-3.361 {ISO week-based calendar 1977-W01-7} {
+ clock format 221616000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1977-W01-7
+} {Sun Sunday 77 1977 7 02 01 0 01}
+test clock-3.362 {ISO week-based calendar 1977-W02-1} {
+ clock format 221702400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1977-W02-1
+} {Mon Monday 77 1977 1 02 02 1 02}
+test clock-3.363 {ISO week-based calendar 1977-W52-1} {
+ clock format 251942400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1977-W52-1
+} {Mon Monday 77 1977 1 52 52 1 52}
+test clock-3.364 {ISO week-based calendar 1977-W52-6} {
+ clock format 252374400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1977-W52-6
+} {Sat Saturday 77 1977 6 52 52 6 52}
+test clock-3.365 {ISO week-based calendar 1977-W52-7} {
+ clock format 252460800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1977-W52-7
+} {Sun Sunday 77 1977 7 01 52 0 00}
+test clock-3.366 {ISO week-based calendar 1978-W01-1} {
+ clock format 252547200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1978-W01-1
+} {Mon Monday 78 1978 1 01 01 1 01}
+test clock-3.367 {ISO week-based calendar 1978-W01-6} {
+ clock format 252979200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1978-W01-6
+} {Sat Saturday 78 1978 6 01 01 6 01}
+test clock-3.368 {ISO week-based calendar 1978-W01-7} {
+ clock format 253065600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1978-W01-7
+} {Sun Sunday 78 1978 7 02 01 0 01}
+test clock-3.369 {ISO week-based calendar 1978-W02-1} {
+ clock format 253152000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1978-W02-1
+} {Mon Monday 78 1978 1 02 02 1 02}
+test clock-3.370 {ISO week-based calendar 1978-W52-1} {
+ clock format 283392000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1978-W52-1
+} {Mon Monday 78 1978 1 52 52 1 52}
+test clock-3.371 {ISO week-based calendar 1978-W52-6} {
+ clock format 283824000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1978-W52-6
+} {Sat Saturday 78 1978 6 52 52 6 52}
+test clock-3.372 {ISO week-based calendar 1978-W52-7} {
+ clock format 283910400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1978-W52-7
+} {Sun Sunday 78 1978 7 53 52 0 52}
+test clock-3.373 {ISO week-based calendar 1979-W01-1} {
+ clock format 283996800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1979-W01-1
+} {Mon Monday 79 1979 1 00 01 1 01}
+test clock-3.374 {ISO week-based calendar 1979-W01-6} {
+ clock format 284428800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1979-W01-6
+} {Sat Saturday 79 1979 6 00 01 6 01}
+test clock-3.375 {ISO week-based calendar 1979-W01-7} {
+ clock format 284515200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1979-W01-7
+} {Sun Sunday 79 1979 7 01 01 0 01}
+test clock-3.376 {ISO week-based calendar 1979-W02-1} {
+ clock format 284601600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1979-W02-1
+} {Mon Monday 79 1979 1 01 02 1 02}
+test clock-3.377 {ISO week-based calendar 1979-W52-1} {
+ clock format 314841600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1979-W52-1
+} {Mon Monday 79 1979 1 51 52 1 52}
+test clock-3.378 {ISO week-based calendar 1979-W52-6} {
+ clock format 315273600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1979-W52-6
+} {Sat Saturday 79 1979 6 51 52 6 52}
+test clock-3.379 {ISO week-based calendar 1979-W52-7} {
+ clock format 315360000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1979-W52-7
+} {Sun Sunday 79 1979 7 52 52 0 52}
+test clock-3.380 {ISO week-based calendar 1980-W01-1} {
+ clock format 315446400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1980-W01-1
+} {Mon Monday 80 1980 1 52 01 1 53}
+test clock-3.381 {ISO week-based calendar 1980-W01-2} {
+ clock format 315532800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1980-W01-2
+} {Tue Tuesday 80 1980 2 00 01 2 00}
+test clock-3.382 {ISO week-based calendar 1980-W01-6} {
+ clock format 315878400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1980-W01-6
+} {Sat Saturday 80 1980 6 00 01 6 00}
+test clock-3.383 {ISO week-based calendar 1980-W01-7} {
+ clock format 315964800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1980-W01-7
+} {Sun Sunday 80 1980 7 01 01 0 00}
+test clock-3.384 {ISO week-based calendar 1980-W02-1} {
+ clock format 316051200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1980-W02-1
+} {Mon Monday 80 1980 1 01 02 1 01}
+test clock-3.385 {ISO week-based calendar 1980-W52-1} {
+ clock format 346291200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1980-W52-1
+} {Mon Monday 80 1980 1 51 52 1 51}
+test clock-3.386 {ISO week-based calendar 1980-W52-6} {
+ clock format 346723200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1980-W52-6
+} {Sat Saturday 80 1980 6 51 52 6 51}
+test clock-3.387 {ISO week-based calendar 1980-W52-7} {
+ clock format 346809600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1980-W52-7
+} {Sun Sunday 80 1980 7 52 52 0 51}
+test clock-3.388 {ISO week-based calendar 1981-W01-1} {
+ clock format 346896000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1981-W01-1
+} {Mon Monday 81 1981 1 52 01 1 52}
+test clock-3.389 {ISO week-based calendar 1981-W01-4} {
+ clock format 347155200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1981-W01-4
+} {Thu Thursday 81 1981 4 00 01 4 00}
+test clock-3.390 {ISO week-based calendar 1981-W01-6} {
+ clock format 347328000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1981-W01-6
+} {Sat Saturday 81 1981 6 00 01 6 00}
+test clock-3.391 {ISO week-based calendar 1981-W01-7} {
+ clock format 347414400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1981-W01-7
+} {Sun Sunday 81 1981 7 01 01 0 00}
+test clock-3.392 {ISO week-based calendar 1981-W02-1} {
+ clock format 347500800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1981-W02-1
+} {Mon Monday 81 1981 1 01 02 1 01}
+test clock-3.393 {ISO week-based calendar 1983-W52-1} {
+ clock format 441244800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1983-W52-1
+} {Mon Monday 83 1983 1 52 52 1 52}
+test clock-3.394 {ISO week-based calendar 1983-W52-6} {
+ clock format 441676800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1983-W52-6
+} {Sat Saturday 83 1983 6 52 52 6 52}
+test clock-3.395 {ISO week-based calendar 1983-W52-7} {
+ clock format 441763200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1983-W52-7
+} {Sun Sunday 83 1983 7 01 52 0 00}
+test clock-3.396 {ISO week-based calendar 1984-W01-1} {
+ clock format 441849600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1984-W01-1
+} {Mon Monday 84 1984 1 01 01 1 01}
+test clock-3.397 {ISO week-based calendar 1984-W01-6} {
+ clock format 442281600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1984-W01-6
+} {Sat Saturday 84 1984 6 01 01 6 01}
+test clock-3.398 {ISO week-based calendar 1984-W01-7} {
+ clock format 442368000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1984-W01-7
+} {Sun Sunday 84 1984 7 02 01 0 01}
+test clock-3.399 {ISO week-based calendar 1984-W02-1} {
+ clock format 442454400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1984-W02-1
+} {Mon Monday 84 1984 1 02 02 1 02}
+test clock-3.400 {ISO week-based calendar 1984-W52-1} {
+ clock format 472694400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1984-W52-1
+} {Mon Monday 84 1984 1 52 52 1 52}
+test clock-3.401 {ISO week-based calendar 1984-W52-6} {
+ clock format 473126400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1984-W52-6
+} {Sat Saturday 84 1984 6 52 52 6 52}
+test clock-3.402 {ISO week-based calendar 1984-W52-7} {
+ clock format 473212800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1984-W52-7
+} {Sun Sunday 84 1984 7 53 52 0 52}
+test clock-3.403 {ISO week-based calendar 1985-W01-1} {
+ clock format 473299200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1985-W01-1
+} {Mon Monday 85 1985 1 53 01 1 53}
+test clock-3.404 {ISO week-based calendar 1985-W01-2} {
+ clock format 473385600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1985-W01-2
+} {Tue Tuesday 85 1985 2 00 01 2 00}
+test clock-3.405 {ISO week-based calendar 1985-W01-6} {
+ clock format 473731200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1985-W01-6
+} {Sat Saturday 85 1985 6 00 01 6 00}
+test clock-3.406 {ISO week-based calendar 1985-W01-7} {
+ clock format 473817600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1985-W01-7
+} {Sun Sunday 85 1985 7 01 01 0 00}
+test clock-3.407 {ISO week-based calendar 1985-W02-1} {
+ clock format 473904000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1985-W02-1
+} {Mon Monday 85 1985 1 01 02 1 01}
+test clock-3.408 {ISO week-based calendar 1987-W53-1} {
+ clock format 567648000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1987-W53-1
+} {Mon Monday 87 1987 1 52 53 1 52}
+test clock-3.409 {ISO week-based calendar 1987-W53-5} {
+ clock format 567993600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1987-W53-5
+} {Fri Friday 87 1987 5 00 53 5 00}
+test clock-3.410 {ISO week-based calendar 1987-W53-6} {
+ clock format 568080000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1987-W53-6
+} {Sat Saturday 87 1987 6 00 53 6 00}
+test clock-3.411 {ISO week-based calendar 1987-W53-7} {
+ clock format 568166400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1987-W53-7
+} {Sun Sunday 87 1987 7 01 53 0 00}
+test clock-3.412 {ISO week-based calendar 1988-W01-1} {
+ clock format 568252800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1988-W01-1
+} {Mon Monday 88 1988 1 01 01 1 01}
+test clock-3.413 {ISO week-based calendar 1988-W01-6} {
+ clock format 568684800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1988-W01-6
+} {Sat Saturday 88 1988 6 01 01 6 01}
+test clock-3.414 {ISO week-based calendar 1988-W01-7} {
+ clock format 568771200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1988-W01-7
+} {Sun Sunday 88 1988 7 02 01 0 01}
+test clock-3.415 {ISO week-based calendar 1988-W02-1} {
+ clock format 568857600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1988-W02-1
+} {Mon Monday 88 1988 1 02 02 1 02}
+test clock-3.416 {ISO week-based calendar 1988-W52-1} {
+ clock format 599097600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1988-W52-1
+} {Mon Monday 88 1988 1 52 52 1 52}
+test clock-3.417 {ISO week-based calendar 1988-W52-6} {
+ clock format 599529600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1988-W52-6
+} {Sat Saturday 88 1988 6 52 52 6 52}
+test clock-3.418 {ISO week-based calendar 1988-W52-7} {
+ clock format 599616000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1988-W52-7
+} {Sun Sunday 88 1988 7 01 52 0 00}
+test clock-3.419 {ISO week-based calendar 1989-W01-1} {
+ clock format 599702400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1989-W01-1
+} {Mon Monday 89 1989 1 01 01 1 01}
+test clock-3.420 {ISO week-based calendar 1989-W01-6} {
+ clock format 600134400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1989-W01-6
+} {Sat Saturday 89 1989 6 01 01 6 01}
+test clock-3.421 {ISO week-based calendar 1989-W01-7} {
+ clock format 600220800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1989-W01-7
+} {Sun Sunday 89 1989 7 02 01 0 01}
+test clock-3.422 {ISO week-based calendar 1989-W02-1} {
+ clock format 600307200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1989-W02-1
+} {Mon Monday 89 1989 1 02 02 1 02}
+test clock-3.423 {ISO week-based calendar 1991-W52-1} {
+ clock format 693446400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1991-W52-1
+} {Mon Monday 91 1991 1 51 52 1 51}
+test clock-3.424 {ISO week-based calendar 1991-W52-6} {
+ clock format 693878400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1991-W52-6
+} {Sat Saturday 91 1991 6 51 52 6 51}
+test clock-3.425 {ISO week-based calendar 1991-W52-7} {
+ clock format 693964800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1991-W52-7
+} {Sun Sunday 91 1991 7 52 52 0 51}
+test clock-3.426 {ISO week-based calendar 1992-W01-1} {
+ clock format 694051200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1992-W01-1
+} {Mon Monday 92 1992 1 52 01 1 52}
+test clock-3.427 {ISO week-based calendar 1992-W01-3} {
+ clock format 694224000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1992-W01-3
+} {Wed Wednesday 92 1992 3 00 01 3 00}
+test clock-3.428 {ISO week-based calendar 1992-W01-6} {
+ clock format 694483200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1992-W01-6
+} {Sat Saturday 92 1992 6 00 01 6 00}
+test clock-3.429 {ISO week-based calendar 1992-W01-7} {
+ clock format 694569600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1992-W01-7
+} {Sun Sunday 92 1992 7 01 01 0 00}
+test clock-3.430 {ISO week-based calendar 1992-W02-1} {
+ clock format 694656000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1992-W02-1
+} {Mon Monday 92 1992 1 01 02 1 01}
+test clock-3.431 {ISO week-based calendar 1992-W53-1} {
+ clock format 725500800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1992-W53-1
+} {Mon Monday 92 1992 1 52 53 1 52}
+test clock-3.432 {ISO week-based calendar 1992-W53-5} {
+ clock format 725846400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1992-W53-5
+} {Fri Friday 92 1992 5 00 53 5 00}
+test clock-3.433 {ISO week-based calendar 1992-W53-6} {
+ clock format 725932800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1992-W53-6
+} {Sat Saturday 92 1992 6 00 53 6 00}
+test clock-3.434 {ISO week-based calendar 1992-W53-7} {
+ clock format 726019200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1992-W53-7
+} {Sun Sunday 92 1992 7 01 53 0 00}
+test clock-3.435 {ISO week-based calendar 1993-W01-1} {
+ clock format 726105600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1993-W01-1
+} {Mon Monday 93 1993 1 01 01 1 01}
+test clock-3.436 {ISO week-based calendar 1993-W01-6} {
+ clock format 726537600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1993-W01-6
+} {Sat Saturday 93 1993 6 01 01 6 01}
+test clock-3.437 {ISO week-based calendar 1993-W01-7} {
+ clock format 726624000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1993-W01-7
+} {Sun Sunday 93 1993 7 02 01 0 01}
+test clock-3.438 {ISO week-based calendar 1993-W02-1} {
+ clock format 726710400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1993-W02-1
+} {Mon Monday 93 1993 1 02 02 1 02}
+test clock-3.439 {ISO week-based calendar 1995-W52-1} {
+ clock format 819849600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1995-W52-1
+} {Mon Monday 95 1995 1 52 52 1 52}
+test clock-3.440 {ISO week-based calendar 1995-W52-6} {
+ clock format 820281600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1995-W52-6
+} {Sat Saturday 95 1995 6 52 52 6 52}
+test clock-3.441 {ISO week-based calendar 1995-W52-7} {
+ clock format 820368000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1995-W52-7
+} {Sun Sunday 95 1995 7 53 52 0 52}
+test clock-3.442 {ISO week-based calendar 1996-W01-1} {
+ clock format 820454400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1996-W01-1
+} {Mon Monday 96 1996 1 00 01 1 01}
+test clock-3.443 {ISO week-based calendar 1996-W01-6} {
+ clock format 820886400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1996-W01-6
+} {Sat Saturday 96 1996 6 00 01 6 01}
+test clock-3.444 {ISO week-based calendar 1996-W01-7} {
+ clock format 820972800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1996-W01-7
+} {Sun Sunday 96 1996 7 01 01 0 01}
+test clock-3.445 {ISO week-based calendar 1996-W02-1} {
+ clock format 821059200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1996-W02-1
+} {Mon Monday 96 1996 1 01 02 1 02}
+test clock-3.446 {ISO week-based calendar 1996-W52-1} {
+ clock format 851299200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1996-W52-1
+} {Mon Monday 96 1996 1 51 52 1 52}
+test clock-3.447 {ISO week-based calendar 1996-W52-6} {
+ clock format 851731200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1996-W52-6
+} {Sat Saturday 96 1996 6 51 52 6 52}
+test clock-3.448 {ISO week-based calendar 1996-W52-7} {
+ clock format 851817600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1996-W52-7
+} {Sun Sunday 96 1996 7 52 52 0 52}
+test clock-3.449 {ISO week-based calendar 1997-W01-1} {
+ clock format 851904000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1997-W01-1
+} {Mon Monday 97 1997 1 52 01 1 53}
+test clock-3.450 {ISO week-based calendar 1997-W01-3} {
+ clock format 852076800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1997-W01-3
+} {Wed Wednesday 97 1997 3 00 01 3 00}
+test clock-3.451 {ISO week-based calendar 1997-W01-6} {
+ clock format 852336000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1997-W01-6
+} {Sat Saturday 97 1997 6 00 01 6 00}
+test clock-3.452 {ISO week-based calendar 1997-W01-7} {
+ clock format 852422400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1997-W01-7
+} {Sun Sunday 97 1997 7 01 01 0 00}
+test clock-3.453 {ISO week-based calendar 1997-W02-1} {
+ clock format 852508800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1997-W02-1
+} {Mon Monday 97 1997 1 01 02 1 01}
+test clock-3.454 {ISO week-based calendar 1999-W52-1} {
+ clock format 946252800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1999-W52-1
+} {Mon Monday 99 1999 1 52 52 1 52}
+test clock-3.455 {ISO week-based calendar 1999-W52-6} {
+ clock format 946684800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1999-W52-6
+} {Sat Saturday 99 1999 6 00 52 6 00}
+test clock-3.456 {ISO week-based calendar 1999-W52-7} {
+ clock format 946771200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 1999-W52-7
+} {Sun Sunday 99 1999 7 01 52 0 00}
+test clock-3.457 {ISO week-based calendar 2000-W01-1} {
+ clock format 946857600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2000-W01-1
+} {Mon Monday 00 2000 1 01 01 1 01}
+test clock-3.458 {ISO week-based calendar 2000-W01-6} {
+ clock format 947289600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2000-W01-6
+} {Sat Saturday 00 2000 6 01 01 6 01}
+test clock-3.459 {ISO week-based calendar 2000-W01-7} {
+ clock format 947376000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2000-W01-7
+} {Sun Sunday 00 2000 7 02 01 0 01}
+test clock-3.460 {ISO week-based calendar 2000-W02-1} {
+ clock format 947462400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2000-W02-1
+} {Mon Monday 00 2000 1 02 02 1 02}
+test clock-3.461 {ISO week-based calendar 2000-W52-1} {
+ clock format 977702400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2000-W52-1
+} {Mon Monday 00 2000 1 52 52 1 52}
+test clock-3.462 {ISO week-based calendar 2000-W52-6} {
+ clock format 978134400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2000-W52-6
+} {Sat Saturday 00 2000 6 52 52 6 52}
+test clock-3.463 {ISO week-based calendar 2000-W52-7} {
+ clock format 978220800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2000-W52-7
+} {Sun Sunday 00 2000 7 53 52 0 52}
+test clock-3.464 {ISO week-based calendar 2001-W01-1} {
+ clock format 978307200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2001-W01-1
+} {Mon Monday 01 2001 1 00 01 1 01}
+test clock-3.465 {ISO week-based calendar 2001-W01-6} {
+ clock format 978739200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2001-W01-6
+} {Sat Saturday 01 2001 6 00 01 6 01}
+test clock-3.466 {ISO week-based calendar 2001-W01-7} {
+ clock format 978825600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2001-W01-7
+} {Sun Sunday 01 2001 7 01 01 0 01}
+test clock-3.467 {ISO week-based calendar 2001-W02-1} {
+ clock format 978912000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2001-W02-1
+} {Mon Monday 01 2001 1 01 02 1 02}
+test clock-3.468 {ISO week-based calendar 2001-W52-1} {
+ clock format 1009152000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2001-W52-1
+} {Mon Monday 01 2001 1 51 52 1 52}
+test clock-3.469 {ISO week-based calendar 2001-W52-6} {
+ clock format 1009584000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2001-W52-6
+} {Sat Saturday 01 2001 6 51 52 6 52}
+test clock-3.470 {ISO week-based calendar 2001-W52-7} {
+ clock format 1009670400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2001-W52-7
+} {Sun Sunday 01 2001 7 52 52 0 52}
+test clock-3.471 {ISO week-based calendar 2002-W01-1} {
+ clock format 1009756800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2002-W01-1
+} {Mon Monday 02 2002 1 52 01 1 53}
+test clock-3.472 {ISO week-based calendar 2002-W01-2} {
+ clock format 1009843200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2002-W01-2
+} {Tue Tuesday 02 2002 2 00 01 2 00}
+test clock-3.473 {ISO week-based calendar 2002-W01-6} {
+ clock format 1010188800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2002-W01-6
+} {Sat Saturday 02 2002 6 00 01 6 00}
+test clock-3.474 {ISO week-based calendar 2002-W01-7} {
+ clock format 1010275200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2002-W01-7
+} {Sun Sunday 02 2002 7 01 01 0 00}
+test clock-3.475 {ISO week-based calendar 2002-W02-1} {
+ clock format 1010361600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2002-W02-1
+} {Mon Monday 02 2002 1 01 02 1 01}
+test clock-3.476 {ISO week-based calendar 2002-W52-1} {
+ clock format 1040601600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2002-W52-1
+} {Mon Monday 02 2002 1 51 52 1 51}
+test clock-3.477 {ISO week-based calendar 2002-W52-6} {
+ clock format 1041033600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2002-W52-6
+} {Sat Saturday 02 2002 6 51 52 6 51}
+test clock-3.478 {ISO week-based calendar 2002-W52-7} {
+ clock format 1041120000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2002-W52-7
+} {Sun Sunday 02 2002 7 52 52 0 51}
+test clock-3.479 {ISO week-based calendar 2003-W01-1} {
+ clock format 1041206400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2003-W01-1
+} {Mon Monday 03 2003 1 52 01 1 52}
+test clock-3.480 {ISO week-based calendar 2003-W01-3} {
+ clock format 1041379200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2003-W01-3
+} {Wed Wednesday 03 2003 3 00 01 3 00}
+test clock-3.481 {ISO week-based calendar 2003-W01-6} {
+ clock format 1041638400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2003-W01-6
+} {Sat Saturday 03 2003 6 00 01 6 00}
+test clock-3.482 {ISO week-based calendar 2003-W01-7} {
+ clock format 1041724800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2003-W01-7
+} {Sun Sunday 03 2003 7 01 01 0 00}
+test clock-3.483 {ISO week-based calendar 2003-W02-1} {
+ clock format 1041811200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2003-W02-1
+} {Mon Monday 03 2003 1 01 02 1 01}
+test clock-3.484 {ISO week-based calendar 2003-W52-1} {
+ clock format 1072051200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2003-W52-1
+} {Mon Monday 03 2003 1 51 52 1 51}
+test clock-3.485 {ISO week-based calendar 2003-W52-6} {
+ clock format 1072483200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2003-W52-6
+} {Sat Saturday 03 2003 6 51 52 6 51}
+test clock-3.486 {ISO week-based calendar 2003-W52-7} {
+ clock format 1072569600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2003-W52-7
+} {Sun Sunday 03 2003 7 52 52 0 51}
+test clock-3.487 {ISO week-based calendar 2004-W01-1} {
+ clock format 1072656000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2004-W01-1
+} {Mon Monday 04 2004 1 52 01 1 52}
+test clock-3.488 {ISO week-based calendar 2004-W01-4} {
+ clock format 1072915200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2004-W01-4
+} {Thu Thursday 04 2004 4 00 01 4 00}
+test clock-3.489 {ISO week-based calendar 2004-W01-6} {
+ clock format 1073088000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2004-W01-6
+} {Sat Saturday 04 2004 6 00 01 6 00}
+test clock-3.490 {ISO week-based calendar 2004-W01-7} {
+ clock format 1073174400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2004-W01-7
+} {Sun Sunday 04 2004 7 01 01 0 00}
+test clock-3.491 {ISO week-based calendar 2004-W02-1} {
+ clock format 1073260800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2004-W02-1
+} {Mon Monday 04 2004 1 01 02 1 01}
+test clock-3.492 {ISO week-based calendar 2004-W53-1} {
+ clock format 1104105600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2004-W53-1
+} {Mon Monday 04 2004 1 52 53 1 52}
+test clock-3.493 {ISO week-based calendar 2004-W53-6} {
+ clock format 1104537600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2004-W53-6
+} {Sat Saturday 04 2004 6 00 53 6 00}
+test clock-3.494 {ISO week-based calendar 2004-W53-7} {
+ clock format 1104624000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2004-W53-7
+} {Sun Sunday 04 2004 7 01 53 0 00}
+test clock-3.495 {ISO week-based calendar 2005-W01-1} {
+ clock format 1104710400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2005-W01-1
+} {Mon Monday 05 2005 1 01 01 1 01}
+test clock-3.496 {ISO week-based calendar 2005-W01-6} {
+ clock format 1105142400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2005-W01-6
+} {Sat Saturday 05 2005 6 01 01 6 01}
+test clock-3.497 {ISO week-based calendar 2005-W01-7} {
+ clock format 1105228800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2005-W01-7
+} {Sun Sunday 05 2005 7 02 01 0 01}
+test clock-3.498 {ISO week-based calendar 2005-W02-1} {
+ clock format 1105315200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2005-W02-1
+} {Mon Monday 05 2005 1 02 02 1 02}
+test clock-3.499 {ISO week-based calendar 2005-W52-1} {
+ clock format 1135555200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2005-W52-1
+} {Mon Monday 05 2005 1 52 52 1 52}
+test clock-3.500 {ISO week-based calendar 2005-W52-6} {
+ clock format 1135987200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2005-W52-6
+} {Sat Saturday 05 2005 6 52 52 6 52}
+test clock-3.501 {ISO week-based calendar 2005-W52-7} {
+ clock format 1136073600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2005-W52-7
+} {Sun Sunday 05 2005 7 01 52 0 00}
+test clock-3.502 {ISO week-based calendar 2006-W01-1} {
+ clock format 1136160000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2006-W01-1
+} {Mon Monday 06 2006 1 01 01 1 01}
+test clock-3.503 {ISO week-based calendar 2006-W01-6} {
+ clock format 1136592000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2006-W01-6
+} {Sat Saturday 06 2006 6 01 01 6 01}
+test clock-3.504 {ISO week-based calendar 2006-W01-7} {
+ clock format 1136678400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2006-W01-7
+} {Sun Sunday 06 2006 7 02 01 0 01}
+test clock-3.505 {ISO week-based calendar 2006-W02-1} {
+ clock format 1136764800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2006-W02-1
+} {Mon Monday 06 2006 1 02 02 1 02}
+test clock-3.506 {ISO week-based calendar 2006-W52-1} {
+ clock format 1167004800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2006-W52-1
+} {Mon Monday 06 2006 1 52 52 1 52}
+test clock-3.507 {ISO week-based calendar 2006-W52-6} {
+ clock format 1167436800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2006-W52-6
+} {Sat Saturday 06 2006 6 52 52 6 52}
+test clock-3.508 {ISO week-based calendar 2006-W52-7} {
+ clock format 1167523200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2006-W52-7
+} {Sun Sunday 06 2006 7 53 52 0 52}
+test clock-3.509 {ISO week-based calendar 2007-W01-1} {
+ clock format 1167609600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2007-W01-1
+} {Mon Monday 07 2007 1 00 01 1 01}
+test clock-3.510 {ISO week-based calendar 2007-W01-6} {
+ clock format 1168041600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2007-W01-6
+} {Sat Saturday 07 2007 6 00 01 6 01}
+test clock-3.511 {ISO week-based calendar 2007-W01-7} {
+ clock format 1168128000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2007-W01-7
+} {Sun Sunday 07 2007 7 01 01 0 01}
+test clock-3.512 {ISO week-based calendar 2007-W02-1} {
+ clock format 1168214400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2007-W02-1
+} {Mon Monday 07 2007 1 01 02 1 02}
+test clock-3.513 {ISO week-based calendar 2007-W52-1} {
+ clock format 1198454400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2007-W52-1
+} {Mon Monday 07 2007 1 51 52 1 52}
+test clock-3.514 {ISO week-based calendar 2007-W52-6} {
+ clock format 1198886400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2007-W52-6
+} {Sat Saturday 07 2007 6 51 52 6 52}
+test clock-3.515 {ISO week-based calendar 2007-W52-7} {
+ clock format 1198972800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2007-W52-7
+} {Sun Sunday 07 2007 7 52 52 0 52}
+test clock-3.516 {ISO week-based calendar 2008-W01-1} {
+ clock format 1199059200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2008-W01-1
+} {Mon Monday 08 2008 1 52 01 1 53}
+test clock-3.517 {ISO week-based calendar 2008-W01-2} {
+ clock format 1199145600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2008-W01-2
+} {Tue Tuesday 08 2008 2 00 01 2 00}
+test clock-3.518 {ISO week-based calendar 2008-W01-6} {
+ clock format 1199491200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2008-W01-6
+} {Sat Saturday 08 2008 6 00 01 6 00}
+test clock-3.519 {ISO week-based calendar 2008-W01-7} {
+ clock format 1199577600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2008-W01-7
+} {Sun Sunday 08 2008 7 01 01 0 00}
+test clock-3.520 {ISO week-based calendar 2008-W02-1} {
+ clock format 1199664000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2008-W02-1
+} {Mon Monday 08 2008 1 01 02 1 01}
+test clock-3.521 {ISO week-based calendar 2008-W52-1} {
+ clock format 1229904000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2008-W52-1
+} {Mon Monday 08 2008 1 51 52 1 51}
+test clock-3.522 {ISO week-based calendar 2008-W52-6} {
+ clock format 1230336000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2008-W52-6
+} {Sat Saturday 08 2008 6 51 52 6 51}
+test clock-3.523 {ISO week-based calendar 2008-W52-7} {
+ clock format 1230422400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2008-W52-7
+} {Sun Sunday 08 2008 7 52 52 0 51}
+test clock-3.524 {ISO week-based calendar 2009-W01-1} {
+ clock format 1230508800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2009-W01-1
+} {Mon Monday 09 2009 1 52 01 1 52}
+test clock-3.525 {ISO week-based calendar 2009-W01-4} {
+ clock format 1230768000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2009-W01-4
+} {Thu Thursday 09 2009 4 00 01 4 00}
+test clock-3.526 {ISO week-based calendar 2009-W01-6} {
+ clock format 1230940800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2009-W01-6
+} {Sat Saturday 09 2009 6 00 01 6 00}
+test clock-3.527 {ISO week-based calendar 2009-W01-7} {
+ clock format 1231027200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2009-W01-7
+} {Sun Sunday 09 2009 7 01 01 0 00}
+test clock-3.528 {ISO week-based calendar 2009-W02-1} {
+ clock format 1231113600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2009-W02-1
+} {Mon Monday 09 2009 1 01 02 1 01}
+test clock-3.529 {ISO week-based calendar 2009-W53-1} {
+ clock format 1261958400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2009-W53-1
+} {Mon Monday 09 2009 1 52 53 1 52}
+test clock-3.530 {ISO week-based calendar 2009-W53-5} {
+ clock format 1262304000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2009-W53-5
+} {Fri Friday 09 2009 5 00 53 5 00}
+test clock-3.531 {ISO week-based calendar 2009-W53-6} {
+ clock format 1262390400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2009-W53-6
+} {Sat Saturday 09 2009 6 00 53 6 00}
+test clock-3.532 {ISO week-based calendar 2009-W53-7} {
+ clock format 1262476800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2009-W53-7
+} {Sun Sunday 09 2009 7 01 53 0 00}
+test clock-3.533 {ISO week-based calendar 2010-W01-1} {
+ clock format 1262563200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2010-W01-1
+} {Mon Monday 10 2010 1 01 01 1 01}
+test clock-3.534 {ISO week-based calendar 2010-W01-6} {
+ clock format 1262995200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2010-W01-6
+} {Sat Saturday 10 2010 6 01 01 6 01}
+test clock-3.535 {ISO week-based calendar 2010-W01-7} {
+ clock format 1263081600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2010-W01-7
+} {Sun Sunday 10 2010 7 02 01 0 01}
+test clock-3.536 {ISO week-based calendar 2010-W02-1} {
+ clock format 1263168000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2010-W02-1
+} {Mon Monday 10 2010 1 02 02 1 02}
+test clock-3.537 {ISO week-based calendar 2010-W52-1} {
+ clock format 1293408000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2010-W52-1
+} {Mon Monday 10 2010 1 52 52 1 52}
+test clock-3.538 {ISO week-based calendar 2010-W52-6} {
+ clock format 1293840000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2010-W52-6
+} {Sat Saturday 10 2010 6 00 52 6 00}
+test clock-3.539 {ISO week-based calendar 2010-W52-7} {
+ clock format 1293926400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2010-W52-7
+} {Sun Sunday 10 2010 7 01 52 0 00}
+test clock-3.540 {ISO week-based calendar 2011-W01-1} {
+ clock format 1294012800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2011-W01-1
+} {Mon Monday 11 2011 1 01 01 1 01}
+test clock-3.541 {ISO week-based calendar 2011-W01-6} {
+ clock format 1294444800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2011-W01-6
+} {Sat Saturday 11 2011 6 01 01 6 01}
+test clock-3.542 {ISO week-based calendar 2011-W01-7} {
+ clock format 1294531200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2011-W01-7
+} {Sun Sunday 11 2011 7 02 01 0 01}
+test clock-3.543 {ISO week-based calendar 2011-W02-1} {
+ clock format 1294617600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2011-W02-1
+} {Mon Monday 11 2011 1 02 02 1 02}
+test clock-3.544 {ISO week-based calendar 2011-W52-1} {
+ clock format 1324857600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2011-W52-1
+} {Mon Monday 11 2011 1 52 52 1 52}
+test clock-3.545 {ISO week-based calendar 2011-W52-6} {
+ clock format 1325289600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2011-W52-6
+} {Sat Saturday 11 2011 6 52 52 6 52}
+test clock-3.546 {ISO week-based calendar 2011-W52-7} {
+ clock format 1325376000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2011-W52-7
+} {Sun Sunday 11 2011 7 01 52 0 00}
+test clock-3.547 {ISO week-based calendar 2012-W01-1} {
+ clock format 1325462400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2012-W01-1
+} {Mon Monday 12 2012 1 01 01 1 01}
+test clock-3.548 {ISO week-based calendar 2012-W01-6} {
+ clock format 1325894400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2012-W01-6
+} {Sat Saturday 12 2012 6 01 01 6 01}
+test clock-3.549 {ISO week-based calendar 2012-W01-7} {
+ clock format 1325980800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2012-W01-7
+} {Sun Sunday 12 2012 7 02 01 0 01}
+test clock-3.550 {ISO week-based calendar 2012-W02-1} {
+ clock format 1326067200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2012-W02-1
+} {Mon Monday 12 2012 1 02 02 1 02}
+test clock-3.551 {ISO week-based calendar 2012-W52-1} {
+ clock format 1356307200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2012-W52-1
+} {Mon Monday 12 2012 1 52 52 1 52}
+test clock-3.552 {ISO week-based calendar 2012-W52-6} {
+ clock format 1356739200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2012-W52-6
+} {Sat Saturday 12 2012 6 52 52 6 52}
+test clock-3.553 {ISO week-based calendar 2012-W52-7} {
+ clock format 1356825600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2012-W52-7
+} {Sun Sunday 12 2012 7 53 52 0 52}
+test clock-3.554 {ISO week-based calendar 2013-W01-1} {
+ clock format 1356912000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2013-W01-1
+} {Mon Monday 13 2013 1 53 01 1 53}
+test clock-3.555 {ISO week-based calendar 2013-W01-2} {
+ clock format 1356998400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2013-W01-2
+} {Tue Tuesday 13 2013 2 00 01 2 00}
+test clock-3.556 {ISO week-based calendar 2013-W01-6} {
+ clock format 1357344000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2013-W01-6
+} {Sat Saturday 13 2013 6 00 01 6 00}
+test clock-3.557 {ISO week-based calendar 2013-W01-7} {
+ clock format 1357430400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2013-W01-7
+} {Sun Sunday 13 2013 7 01 01 0 00}
+test clock-3.558 {ISO week-based calendar 2013-W02-1} {
+ clock format 1357516800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2013-W02-1
+} {Mon Monday 13 2013 1 01 02 1 01}
+test clock-3.559 {ISO week-based calendar 2015-W53-1} {
+ clock format 1451260800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2015-W53-1
+} {Mon Monday 15 2015 1 52 53 1 52}
+test clock-3.560 {ISO week-based calendar 2015-W53-5} {
+ clock format 1451606400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2015-W53-5
+} {Fri Friday 15 2015 5 00 53 5 00}
+test clock-3.561 {ISO week-based calendar 2015-W53-6} {
+ clock format 1451692800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2015-W53-6
+} {Sat Saturday 15 2015 6 00 53 6 00}
+test clock-3.562 {ISO week-based calendar 2015-W53-7} {
+ clock format 1451779200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2015-W53-7
+} {Sun Sunday 15 2015 7 01 53 0 00}
+test clock-3.563 {ISO week-based calendar 2016-W01-1} {
+ clock format 1451865600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2016-W01-1
+} {Mon Monday 16 2016 1 01 01 1 01}
+test clock-3.564 {ISO week-based calendar 2016-W01-6} {
+ clock format 1452297600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2016-W01-6
+} {Sat Saturday 16 2016 6 01 01 6 01}
+test clock-3.565 {ISO week-based calendar 2016-W01-7} {
+ clock format 1452384000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2016-W01-7
+} {Sun Sunday 16 2016 7 02 01 0 01}
+test clock-3.566 {ISO week-based calendar 2016-W02-1} {
+ clock format 1452470400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2016-W02-1
+} {Mon Monday 16 2016 1 02 02 1 02}
+test clock-3.567 {ISO week-based calendar 2016-W52-1} {
+ clock format 1482710400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2016-W52-1
+} {Mon Monday 16 2016 1 52 52 1 52}
+test clock-3.568 {ISO week-based calendar 2016-W52-6} {
+ clock format 1483142400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2016-W52-6
+} {Sat Saturday 16 2016 6 52 52 6 52}
+test clock-3.569 {ISO week-based calendar 2016-W52-7} {
+ clock format 1483228800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2016-W52-7
+} {Sun Sunday 16 2016 7 01 52 0 00}
+test clock-3.570 {ISO week-based calendar 2017-W01-1} {
+ clock format 1483315200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2017-W01-1
+} {Mon Monday 17 2017 1 01 01 1 01}
+test clock-3.571 {ISO week-based calendar 2017-W01-6} {
+ clock format 1483747200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2017-W01-6
+} {Sat Saturday 17 2017 6 01 01 6 01}
+test clock-3.572 {ISO week-based calendar 2017-W01-7} {
+ clock format 1483833600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2017-W01-7
+} {Sun Sunday 17 2017 7 02 01 0 01}
+test clock-3.573 {ISO week-based calendar 2017-W02-1} {
+ clock format 1483920000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2017-W02-1
+} {Mon Monday 17 2017 1 02 02 1 02}
+test clock-3.574 {ISO week-based calendar 2019-W52-1} {
+ clock format 1577059200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2019-W52-1
+} {Mon Monday 19 2019 1 51 52 1 51}
+test clock-3.575 {ISO week-based calendar 2019-W52-6} {
+ clock format 1577491200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2019-W52-6
+} {Sat Saturday 19 2019 6 51 52 6 51}
+test clock-3.576 {ISO week-based calendar 2019-W52-7} {
+ clock format 1577577600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2019-W52-7
+} {Sun Sunday 19 2019 7 52 52 0 51}
+test clock-3.577 {ISO week-based calendar 2020-W01-1} {
+ clock format 1577664000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2020-W01-1
+} {Mon Monday 20 2020 1 52 01 1 52}
+test clock-3.578 {ISO week-based calendar 2020-W01-3} {
+ clock format 1577836800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2020-W01-3
+} {Wed Wednesday 20 2020 3 00 01 3 00}
+test clock-3.579 {ISO week-based calendar 2020-W01-6} {
+ clock format 1578096000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2020-W01-6
+} {Sat Saturday 20 2020 6 00 01 6 00}
+test clock-3.580 {ISO week-based calendar 2020-W01-7} {
+ clock format 1578182400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2020-W01-7
+} {Sun Sunday 20 2020 7 01 01 0 00}
+test clock-3.581 {ISO week-based calendar 2020-W02-1} {
+ clock format 1578268800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2020-W02-1
+} {Mon Monday 20 2020 1 01 02 1 01}
+test clock-3.582 {ISO week-based calendar 2020-W53-1} {
+ clock format 1609113600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2020-W53-1
+} {Mon Monday 20 2020 1 52 53 1 52}
+test clock-3.583 {ISO week-based calendar 2020-W53-5} {
+ clock format 1609459200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2020-W53-5
+} {Fri Friday 20 2020 5 00 53 5 00}
+test clock-3.584 {ISO week-based calendar 2020-W53-6} {
+ clock format 1609545600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2020-W53-6
+} {Sat Saturday 20 2020 6 00 53 6 00}
+test clock-3.585 {ISO week-based calendar 2020-W53-7} {
+ clock format 1609632000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2020-W53-7
+} {Sun Sunday 20 2020 7 01 53 0 00}
+test clock-3.586 {ISO week-based calendar 2021-W01-1} {
+ clock format 1609718400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2021-W01-1
+} {Mon Monday 21 2021 1 01 01 1 01}
+test clock-3.587 {ISO week-based calendar 2021-W01-6} {
+ clock format 1610150400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2021-W01-6
+} {Sat Saturday 21 2021 6 01 01 6 01}
+test clock-3.588 {ISO week-based calendar 2021-W01-7} {
+ clock format 1610236800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2021-W01-7
+} {Sun Sunday 21 2021 7 02 01 0 01}
+test clock-3.589 {ISO week-based calendar 2021-W02-1} {
+ clock format 1610323200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2021-W02-1
+} {Mon Monday 21 2021 1 02 02 1 02}
+test clock-3.590 {ISO week-based calendar 2023-W52-1} {
+ clock format 1703462400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2023-W52-1
+} {Mon Monday 23 2023 1 52 52 1 52}
+test clock-3.591 {ISO week-based calendar 2023-W52-6} {
+ clock format 1703894400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2023-W52-6
+} {Sat Saturday 23 2023 6 52 52 6 52}
+test clock-3.592 {ISO week-based calendar 2023-W52-7} {
+ clock format 1703980800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2023-W52-7
+} {Sun Sunday 23 2023 7 53 52 0 52}
+test clock-3.593 {ISO week-based calendar 2024-W01-1} {
+ clock format 1704067200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2024-W01-1
+} {Mon Monday 24 2024 1 00 01 1 01}
+test clock-3.594 {ISO week-based calendar 2024-W01-6} {
+ clock format 1704499200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2024-W01-6
+} {Sat Saturday 24 2024 6 00 01 6 01}
+test clock-3.595 {ISO week-based calendar 2024-W01-7} {
+ clock format 1704585600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2024-W01-7
+} {Sun Sunday 24 2024 7 01 01 0 01}
+test clock-3.596 {ISO week-based calendar 2024-W02-1} {
+ clock format 1704672000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2024-W02-1
+} {Mon Monday 24 2024 1 01 02 1 02}
+test clock-3.597 {ISO week-based calendar 2024-W52-1} {
+ clock format 1734912000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2024-W52-1
+} {Mon Monday 24 2024 1 51 52 1 52}
+test clock-3.598 {ISO week-based calendar 2024-W52-6} {
+ clock format 1735344000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2024-W52-6
+} {Sat Saturday 24 2024 6 51 52 6 52}
+test clock-3.599 {ISO week-based calendar 2024-W52-7} {
+ clock format 1735430400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2024-W52-7
+} {Sun Sunday 24 2024 7 52 52 0 52}
+test clock-3.600 {ISO week-based calendar 2025-W01-1} {
+ clock format 1735516800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2025-W01-1
+} {Mon Monday 25 2025 1 52 01 1 53}
+test clock-3.601 {ISO week-based calendar 2025-W01-3} {
+ clock format 1735689600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2025-W01-3
+} {Wed Wednesday 25 2025 3 00 01 3 00}
+test clock-3.602 {ISO week-based calendar 2025-W01-6} {
+ clock format 1735948800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2025-W01-6
+} {Sat Saturday 25 2025 6 00 01 6 00}
+test clock-3.603 {ISO week-based calendar 2025-W01-7} {
+ clock format 1736035200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2025-W01-7
+} {Sun Sunday 25 2025 7 01 01 0 00}
+test clock-3.604 {ISO week-based calendar 2025-W02-1} {
+ clock format 1736121600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2025-W02-1
+} {Mon Monday 25 2025 1 01 02 1 01}
+test clock-3.605 {ISO week-based calendar 2036-W52-1} {
+ clock format 2113516800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2036-W52-1
+} {Mon Monday 36 2036 1 51 52 1 51}
+test clock-3.606 {ISO week-based calendar 2036-W52-6} {
+ clock format 2113948800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2036-W52-6
+} {Sat Saturday 36 2036 6 51 52 6 51}
+test clock-3.607 {ISO week-based calendar 2036-W52-7} {
+ clock format 2114035200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2036-W52-7
+} {Sun Sunday 36 2036 7 52 52 0 51}
+test clock-3.608 {ISO week-based calendar 2037-W01-1} {
+ clock format 2114121600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2037-W01-1
+} {Mon Monday 37 2037 1 52 01 1 52}
+test clock-3.609 {ISO week-based calendar 2037-W01-4} {
+ clock format 2114380800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2037-W01-4
+} {Thu Thursday 37 2037 4 00 01 4 00}
+test clock-3.610 {ISO week-based calendar 2037-W01-6} {
+ clock format 2114553600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2037-W01-6
+} {Sat Saturday 37 2037 6 00 01 6 00}
+test clock-3.611 {ISO week-based calendar 2037-W01-7} {
+ clock format 2114640000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2037-W01-7
+} {Sun Sunday 37 2037 7 01 01 0 00}
+test clock-3.612 {ISO week-based calendar 2037-W02-1} {
+ clock format 2114726400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2037-W02-1
+} {Mon Monday 37 2037 1 01 02 1 01}
+test clock-3.613 {ISO week-based calendar 2037-W53-1} {
+ clock format 2145571200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2037-W53-1
+} {Mon Monday 37 2037 1 52 53 1 52}
+test clock-3.614 {ISO week-based calendar 2037-W53-5} {
+ clock format 2145916800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2037-W53-5
+} {Fri Friday 37 2037 5 00 53 5 00}
+test clock-3.615 {ISO week-based calendar 2037-W53-6} {
+ clock format 2146003200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2037-W53-6
+} {Sat Saturday 37 2037 6 00 53 6 00}
+test clock-3.616 {ISO week-based calendar 2037-W53-7} {
+ clock format 2146089600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2037-W53-7
+} {Sun Sunday 37 2037 7 01 53 0 00}
+test clock-3.617 {ISO week-based calendar 2038-W01-1} {
+ clock format 2146176000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2038-W01-1
+} {Mon Monday 38 2038 1 01 01 1 01}
+test clock-3.618 {ISO week-based calendar 2038-W01-6} {
+ clock format 2146608000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2038-W01-6
+} {Sat Saturday 38 2038 6 01 01 6 01}
+test clock-3.619 {ISO week-based calendar 2038-W01-7} {
+ clock format 2146694400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2038-W01-7
+} {Sun Sunday 38 2038 7 02 01 0 01}
+test clock-3.620 {ISO week-based calendar 2038-W02-1} {
+ clock format 2146780800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2038-W02-1
+} {Mon Monday 38 2038 1 02 02 1 02}
+test clock-3.621 {ISO week-based calendar 2038-W52-1} {
+ clock format 2177020800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2038-W52-1
+} {Mon Monday 38 2038 1 52 52 1 52}
+test clock-3.622 {ISO week-based calendar 2038-W52-6} {
+ clock format 2177452800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2038-W52-6
+} {Sat Saturday 38 2038 6 00 52 6 00}
+test clock-3.623 {ISO week-based calendar 2038-W52-7} {
+ clock format 2177539200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2038-W52-7
+} {Sun Sunday 38 2038 7 01 52 0 00}
+test clock-3.624 {ISO week-based calendar 2039-W01-1} {
+ clock format 2177625600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2039-W01-1
+} {Mon Monday 39 2039 1 01 01 1 01}
+test clock-3.625 {ISO week-based calendar 2039-W01-6} {
+ clock format 2178057600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2039-W01-6
+} {Sat Saturday 39 2039 6 01 01 6 01}
+test clock-3.626 {ISO week-based calendar 2039-W01-7} {
+ clock format 2178144000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2039-W01-7
+} {Sun Sunday 39 2039 7 02 01 0 01}
+test clock-3.627 {ISO week-based calendar 2039-W02-1} {
+ clock format 2178230400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2039-W02-1
+} {Mon Monday 39 2039 1 02 02 1 02}
+test clock-3.628 {ISO week-based calendar 2039-W52-1} {
+ clock format 2208470400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2039-W52-1
+} {Mon Monday 39 2039 1 52 52 1 52}
+test clock-3.629 {ISO week-based calendar 2039-W52-6} {
+ clock format 2208902400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2039-W52-6
+} {Sat Saturday 39 2039 6 52 52 6 52}
+test clock-3.630 {ISO week-based calendar 2039-W52-7} {
+ clock format 2208988800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2039-W52-7
+} {Sun Sunday 39 2039 7 01 52 0 00}
+test clock-3.631 {ISO week-based calendar 2040-W01-1} {
+ clock format 2209075200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2040-W01-1
+} {Mon Monday 40 2040 1 01 01 1 01}
+test clock-3.632 {ISO week-based calendar 2040-W01-6} {
+ clock format 2209507200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2040-W01-6
+} {Sat Saturday 40 2040 6 01 01 6 01}
+test clock-3.633 {ISO week-based calendar 2040-W01-7} {
+ clock format 2209593600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2040-W01-7
+} {Sun Sunday 40 2040 7 02 01 0 01}
+test clock-3.634 {ISO week-based calendar 2040-W02-1} {
+ clock format 2209680000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2040-W02-1
+} {Mon Monday 40 2040 1 02 02 1 02}
+test clock-3.635 {ISO week-based calendar 2040-W52-1} {
+ clock format 2239920000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2040-W52-1
+} {Mon Monday 40 2040 1 52 52 1 52}
+test clock-3.636 {ISO week-based calendar 2040-W52-6} {
+ clock format 2240352000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2040-W52-6
+} {Sat Saturday 40 2040 6 52 52 6 52}
+test clock-3.637 {ISO week-based calendar 2040-W52-7} {
+ clock format 2240438400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2040-W52-7
+} {Sun Sunday 40 2040 7 53 52 0 52}
+test clock-3.638 {ISO week-based calendar 2041-W01-1} {
+ clock format 2240524800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2041-W01-1
+} {Mon Monday 41 2041 1 53 01 1 53}
+test clock-3.639 {ISO week-based calendar 2041-W01-2} {
+ clock format 2240611200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2041-W01-2
+} {Tue Tuesday 41 2041 2 00 01 2 00}
+test clock-3.640 {ISO week-based calendar 2041-W01-6} {
+ clock format 2240956800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2041-W01-6
+} {Sat Saturday 41 2041 6 00 01 6 00}
+test clock-3.641 {ISO week-based calendar 2041-W01-7} {
+ clock format 2241043200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2041-W01-7
+} {Sun Sunday 41 2041 7 01 01 0 00}
+test clock-3.642 {ISO week-based calendar 2041-W02-1} {
+ clock format 2241129600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2041-W02-1
+} {Mon Monday 41 2041 1 01 02 1 01}
+test clock-3.643 {ISO week-based calendar 2041-W52-1} {
+ clock format 2271369600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2041-W52-1
+} {Mon Monday 41 2041 1 51 52 1 51}
+test clock-3.644 {ISO week-based calendar 2041-W52-6} {
+ clock format 2271801600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2041-W52-6
+} {Sat Saturday 41 2041 6 51 52 6 51}
+test clock-3.645 {ISO week-based calendar 2041-W52-7} {
+ clock format 2271888000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2041-W52-7
+} {Sun Sunday 41 2041 7 52 52 0 51}
+test clock-3.646 {ISO week-based calendar 2042-W01-1} {
+ clock format 2271974400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2042-W01-1
+} {Mon Monday 42 2042 1 52 01 1 52}
+test clock-3.647 {ISO week-based calendar 2042-W01-3} {
+ clock format 2272147200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2042-W01-3
+} {Wed Wednesday 42 2042 3 00 01 3 00}
+test clock-3.648 {ISO week-based calendar 2042-W01-6} {
+ clock format 2272406400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2042-W01-6
+} {Sat Saturday 42 2042 6 00 01 6 00}
+test clock-3.649 {ISO week-based calendar 2042-W01-7} {
+ clock format 2272492800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2042-W01-7
+} {Sun Sunday 42 2042 7 01 01 0 00}
+test clock-3.650 {ISO week-based calendar 2042-W02-1} {
+ clock format 2272579200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2042-W02-1
+} {Mon Monday 42 2042 1 01 02 1 01}
+test clock-3.651 {ISO week-based calendar 2042-W52-1} {
+ clock format 2302819200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2042-W52-1
+} {Mon Monday 42 2042 1 51 52 1 51}
+test clock-3.652 {ISO week-based calendar 2042-W52-6} {
+ clock format 2303251200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2042-W52-6
+} {Sat Saturday 42 2042 6 51 52 6 51}
+test clock-3.653 {ISO week-based calendar 2042-W52-7} {
+ clock format 2303337600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2042-W52-7
+} {Sun Sunday 42 2042 7 52 52 0 51}
+test clock-3.654 {ISO week-based calendar 2043-W01-1} {
+ clock format 2303424000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2043-W01-1
+} {Mon Monday 43 2043 1 52 01 1 52}
+test clock-3.655 {ISO week-based calendar 2043-W01-4} {
+ clock format 2303683200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2043-W01-4
+} {Thu Thursday 43 2043 4 00 01 4 00}
+test clock-3.656 {ISO week-based calendar 2043-W01-6} {
+ clock format 2303856000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2043-W01-6
+} {Sat Saturday 43 2043 6 00 01 6 00}
+test clock-3.657 {ISO week-based calendar 2043-W01-7} {
+ clock format 2303942400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2043-W01-7
+} {Sun Sunday 43 2043 7 01 01 0 00}
+test clock-3.658 {ISO week-based calendar 2043-W02-1} {
+ clock format 2304028800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2043-W02-1
+} {Mon Monday 43 2043 1 01 02 1 01}
+test clock-3.659 {ISO week-based calendar 2043-W53-1} {
+ clock format 2334873600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2043-W53-1
+} {Mon Monday 43 2043 1 52 53 1 52}
+test clock-3.660 {ISO week-based calendar 2043-W53-5} {
+ clock format 2335219200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2043-W53-5
+} {Fri Friday 43 2043 5 00 53 5 00}
+test clock-3.661 {ISO week-based calendar 2043-W53-6} {
+ clock format 2335305600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2043-W53-6
+} {Sat Saturday 43 2043 6 00 53 6 00}
+test clock-3.662 {ISO week-based calendar 2043-W53-7} {
+ clock format 2335392000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2043-W53-7
+} {Sun Sunday 43 2043 7 01 53 0 00}
+test clock-3.663 {ISO week-based calendar 2044-W01-1} {
+ clock format 2335478400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2044-W01-1
+} {Mon Monday 44 2044 1 01 01 1 01}
+test clock-3.664 {ISO week-based calendar 2044-W01-6} {
+ clock format 2335910400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2044-W01-6
+} {Sat Saturday 44 2044 6 01 01 6 01}
+test clock-3.665 {ISO week-based calendar 2044-W01-7} {
+ clock format 2335996800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2044-W01-7
+} {Sun Sunday 44 2044 7 02 01 0 01}
+test clock-3.666 {ISO week-based calendar 2044-W02-1} {
+ clock format 2336083200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2044-W02-1
+} {Mon Monday 44 2044 1 02 02 1 02}
+test clock-3.667 {ISO week-based calendar 2044-W52-1} {
+ clock format 2366323200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2044-W52-1
+} {Mon Monday 44 2044 1 52 52 1 52}
+test clock-3.668 {ISO week-based calendar 2044-W52-6} {
+ clock format 2366755200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2044-W52-6
+} {Sat Saturday 44 2044 6 52 52 6 52}
+test clock-3.669 {ISO week-based calendar 2044-W52-7} {
+ clock format 2366841600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2044-W52-7
+} {Sun Sunday 44 2044 7 01 52 0 00}
+test clock-3.670 {ISO week-based calendar 2045-W01-1} {
+ clock format 2366928000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2045-W01-1
+} {Mon Monday 45 2045 1 01 01 1 01}
+test clock-3.671 {ISO week-based calendar 2045-W01-6} {
+ clock format 2367360000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2045-W01-6
+} {Sat Saturday 45 2045 6 01 01 6 01}
+test clock-3.672 {ISO week-based calendar 2045-W01-7} {
+ clock format 2367446400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2045-W01-7
+} {Sun Sunday 45 2045 7 02 01 0 01}
+test clock-3.673 {ISO week-based calendar 2045-W02-1} {
+ clock format 2367532800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2045-W02-1
+} {Mon Monday 45 2045 1 02 02 1 02}
+test clock-3.674 {ISO week-based calendar 2045-W52-1} {
+ clock format 2397772800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2045-W52-1
+} {Mon Monday 45 2045 1 52 52 1 52}
+test clock-3.675 {ISO week-based calendar 2045-W52-6} {
+ clock format 2398204800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2045-W52-6
+} {Sat Saturday 45 2045 6 52 52 6 52}
+test clock-3.676 {ISO week-based calendar 2045-W52-7} {
+ clock format 2398291200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2045-W52-7
+} {Sun Sunday 45 2045 7 53 52 0 52}
+test clock-3.677 {ISO week-based calendar 2046-W01-1} {
+ clock format 2398377600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2046-W01-1
+} {Mon Monday 46 2046 1 00 01 1 01}
+test clock-3.678 {ISO week-based calendar 2046-W01-6} {
+ clock format 2398809600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2046-W01-6
+} {Sat Saturday 46 2046 6 00 01 6 01}
+test clock-3.679 {ISO week-based calendar 2046-W01-7} {
+ clock format 2398896000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2046-W01-7
+} {Sun Sunday 46 2046 7 01 01 0 01}
+test clock-3.680 {ISO week-based calendar 2046-W02-1} {
+ clock format 2398982400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2046-W02-1
+} {Mon Monday 46 2046 1 01 02 1 02}
+test clock-3.681 {ISO week-based calendar 2046-W52-1} {
+ clock format 2429222400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2046-W52-1
+} {Mon Monday 46 2046 1 51 52 1 52}
+test clock-3.682 {ISO week-based calendar 2046-W52-6} {
+ clock format 2429654400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2046-W52-6
+} {Sat Saturday 46 2046 6 51 52 6 52}
+test clock-3.683 {ISO week-based calendar 2046-W52-7} {
+ clock format 2429740800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2046-W52-7
+} {Sun Sunday 46 2046 7 52 52 0 52}
+test clock-3.684 {ISO week-based calendar 2047-W01-1} {
+ clock format 2429827200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2047-W01-1
+} {Mon Monday 47 2047 1 52 01 1 53}
+test clock-3.685 {ISO week-based calendar 2047-W01-2} {
+ clock format 2429913600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2047-W01-2
+} {Tue Tuesday 47 2047 2 00 01 2 00}
+test clock-3.686 {ISO week-based calendar 2047-W01-6} {
+ clock format 2430259200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2047-W01-6
+} {Sat Saturday 47 2047 6 00 01 6 00}
+test clock-3.687 {ISO week-based calendar 2047-W01-7} {
+ clock format 2430345600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2047-W01-7
+} {Sun Sunday 47 2047 7 01 01 0 00}
+test clock-3.688 {ISO week-based calendar 2047-W02-1} {
+ clock format 2430432000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2047-W02-1
+} {Mon Monday 47 2047 1 01 02 1 01}
+test clock-3.689 {ISO week-based calendar 2047-W52-1} {
+ clock format 2460672000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2047-W52-1
+} {Mon Monday 47 2047 1 51 52 1 51}
+test clock-3.690 {ISO week-based calendar 2047-W52-6} {
+ clock format 2461104000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2047-W52-6
+} {Sat Saturday 47 2047 6 51 52 6 51}
+test clock-3.691 {ISO week-based calendar 2047-W52-7} {
+ clock format 2461190400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2047-W52-7
+} {Sun Sunday 47 2047 7 52 52 0 51}
+test clock-3.692 {ISO week-based calendar 2048-W01-1} {
+ clock format 2461276800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2048-W01-1
+} {Mon Monday 48 2048 1 52 01 1 52}
+test clock-3.693 {ISO week-based calendar 2048-W01-3} {
+ clock format 2461449600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2048-W01-3
+} {Wed Wednesday 48 2048 3 00 01 3 00}
+test clock-3.694 {ISO week-based calendar 2048-W01-6} {
+ clock format 2461708800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2048-W01-6
+} {Sat Saturday 48 2048 6 00 01 6 00}
+test clock-3.695 {ISO week-based calendar 2048-W01-7} {
+ clock format 2461795200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2048-W01-7
+} {Sun Sunday 48 2048 7 01 01 0 00}
+test clock-3.696 {ISO week-based calendar 2048-W02-1} {
+ clock format 2461881600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2048-W02-1
+} {Mon Monday 48 2048 1 01 02 1 01}
+test clock-3.697 {ISO week-based calendar 2048-W53-1} {
+ clock format 2492726400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2048-W53-1
+} {Mon Monday 48 2048 1 52 53 1 52}
+test clock-3.698 {ISO week-based calendar 2048-W53-5} {
+ clock format 2493072000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2048-W53-5
+} {Fri Friday 48 2048 5 00 53 5 00}
+test clock-3.699 {ISO week-based calendar 2048-W53-6} {
+ clock format 2493158400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2048-W53-6
+} {Sat Saturday 48 2048 6 00 53 6 00}
+test clock-3.700 {ISO week-based calendar 2048-W53-7} {
+ clock format 2493244800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2048-W53-7
+} {Sun Sunday 48 2048 7 01 53 0 00}
+test clock-3.701 {ISO week-based calendar 2049-W01-1} {
+ clock format 2493331200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2049-W01-1
+} {Mon Monday 49 2049 1 01 01 1 01}
+test clock-3.702 {ISO week-based calendar 2049-W01-6} {
+ clock format 2493763200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2049-W01-6
+} {Sat Saturday 49 2049 6 01 01 6 01}
+test clock-3.703 {ISO week-based calendar 2049-W01-7} {
+ clock format 2493849600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2049-W01-7
+} {Sun Sunday 49 2049 7 02 01 0 01}
+test clock-3.704 {ISO week-based calendar 2049-W02-1} {
+ clock format 2493936000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2049-W02-1
+} {Mon Monday 49 2049 1 02 02 1 02}
+test clock-3.705 {ISO week-based calendar 2051-W52-1} {
+ clock format 2587075200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2051-W52-1
+} {Mon Monday 51 2051 1 52 52 1 52}
+test clock-3.706 {ISO week-based calendar 2051-W52-6} {
+ clock format 2587507200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2051-W52-6
+} {Sat Saturday 51 2051 6 52 52 6 52}
+test clock-3.707 {ISO week-based calendar 2051-W52-7} {
+ clock format 2587593600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2051-W52-7
+} {Sun Sunday 51 2051 7 53 52 0 52}
+test clock-3.708 {ISO week-based calendar 2052-W01-1} {
+ clock format 2587680000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2052-W01-1
+} {Mon Monday 52 2052 1 00 01 1 01}
+test clock-3.709 {ISO week-based calendar 2052-W01-6} {
+ clock format 2588112000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2052-W01-6
+} {Sat Saturday 52 2052 6 00 01 6 01}
+test clock-3.710 {ISO week-based calendar 2052-W01-7} {
+ clock format 2588198400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2052-W01-7
+} {Sun Sunday 52 2052 7 01 01 0 01}
+test clock-3.711 {ISO week-based calendar 2052-W02-1} {
+ clock format 2588284800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2052-W02-1
+} {Mon Monday 52 2052 1 01 02 1 02}
+test clock-3.712 {ISO week-based calendar 2052-W52-1} {
+ clock format 2618524800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2052-W52-1
+} {Mon Monday 52 2052 1 51 52 1 52}
+test clock-3.713 {ISO week-based calendar 2052-W52-6} {
+ clock format 2618956800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2052-W52-6
+} {Sat Saturday 52 2052 6 51 52 6 52}
+test clock-3.714 {ISO week-based calendar 2052-W52-7} {
+ clock format 2619043200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2052-W52-7
+} {Sun Sunday 52 2052 7 52 52 0 52}
+test clock-3.715 {ISO week-based calendar 2053-W01-1} {
+ clock format 2619129600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2053-W01-1
+} {Mon Monday 53 2053 1 52 01 1 53}
+test clock-3.716 {ISO week-based calendar 2053-W01-3} {
+ clock format 2619302400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2053-W01-3
+} {Wed Wednesday 53 2053 3 00 01 3 00}
+test clock-3.717 {ISO week-based calendar 2053-W01-6} {
+ clock format 2619561600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2053-W01-6
+} {Sat Saturday 53 2053 6 00 01 6 00}
+test clock-3.718 {ISO week-based calendar 2053-W01-7} {
+ clock format 2619648000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2053-W01-7
+} {Sun Sunday 53 2053 7 01 01 0 00}
+test clock-3.719 {ISO week-based calendar 2053-W02-1} {
+ clock format 2619734400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2053-W02-1
+} {Mon Monday 53 2053 1 01 02 1 01}
+test clock-3.720 {ISO week-based calendar 2055-W52-1} {
+ clock format 2713478400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2055-W52-1
+} {Mon Monday 55 2055 1 52 52 1 52}
+test clock-3.721 {ISO week-based calendar 2055-W52-6} {
+ clock format 2713910400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2055-W52-6
+} {Sat Saturday 55 2055 6 00 52 6 00}
+test clock-3.722 {ISO week-based calendar 2055-W52-7} {
+ clock format 2713996800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2055-W52-7
+} {Sun Sunday 55 2055 7 01 52 0 00}
+test clock-3.723 {ISO week-based calendar 2056-W01-1} {
+ clock format 2714083200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2056-W01-1
+} {Mon Monday 56 2056 1 01 01 1 01}
+test clock-3.724 {ISO week-based calendar 2056-W01-6} {
+ clock format 2714515200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2056-W01-6
+} {Sat Saturday 56 2056 6 01 01 6 01}
+test clock-3.725 {ISO week-based calendar 2056-W01-7} {
+ clock format 2714601600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2056-W01-7
+} {Sun Sunday 56 2056 7 02 01 0 01}
+test clock-3.726 {ISO week-based calendar 2056-W02-1} {
+ clock format 2714688000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2056-W02-1
+} {Mon Monday 56 2056 1 02 02 1 02}
+test clock-3.727 {ISO week-based calendar 2056-W52-1} {
+ clock format 2744928000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2056-W52-1
+} {Mon Monday 56 2056 1 52 52 1 52}
+test clock-3.728 {ISO week-based calendar 2056-W52-6} {
+ clock format 2745360000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2056-W52-6
+} {Sat Saturday 56 2056 6 52 52 6 52}
+test clock-3.729 {ISO week-based calendar 2056-W52-7} {
+ clock format 2745446400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2056-W52-7
+} {Sun Sunday 56 2056 7 53 52 0 52}
+test clock-3.730 {ISO week-based calendar 2057-W01-1} {
+ clock format 2745532800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2057-W01-1
+} {Mon Monday 57 2057 1 00 01 1 01}
+test clock-3.731 {ISO week-based calendar 2057-W01-6} {
+ clock format 2745964800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2057-W01-6
+} {Sat Saturday 57 2057 6 00 01 6 01}
+test clock-3.732 {ISO week-based calendar 2057-W01-7} {
+ clock format 2746051200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2057-W01-7
+} {Sun Sunday 57 2057 7 01 01 0 01}
+test clock-3.733 {ISO week-based calendar 2057-W02-1} {
+ clock format 2746137600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2057-W02-1
+} {Mon Monday 57 2057 1 01 02 1 02}
+test clock-3.734 {ISO week-based calendar 2059-W52-1} {
+ clock format 2839276800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2059-W52-1
+} {Mon Monday 59 2059 1 51 52 1 51}
+test clock-3.735 {ISO week-based calendar 2059-W52-6} {
+ clock format 2839708800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2059-W52-6
+} {Sat Saturday 59 2059 6 51 52 6 51}
+test clock-3.736 {ISO week-based calendar 2059-W52-7} {
+ clock format 2839795200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2059-W52-7
+} {Sun Sunday 59 2059 7 52 52 0 51}
+test clock-3.737 {ISO week-based calendar 2060-W01-1} {
+ clock format 2839881600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2060-W01-1
+} {Mon Monday 60 2060 1 52 01 1 52}
+test clock-3.738 {ISO week-based calendar 2060-W01-4} {
+ clock format 2840140800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2060-W01-4
+} {Thu Thursday 60 2060 4 00 01 4 00}
+test clock-3.739 {ISO week-based calendar 2060-W01-6} {
+ clock format 2840313600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2060-W01-6
+} {Sat Saturday 60 2060 6 00 01 6 00}
+test clock-3.740 {ISO week-based calendar 2060-W01-7} {
+ clock format 2840400000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2060-W01-7
+} {Sun Sunday 60 2060 7 01 01 0 00}
+test clock-3.741 {ISO week-based calendar 2060-W02-1} {
+ clock format 2840486400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2060-W02-1
+} {Mon Monday 60 2060 1 01 02 1 01}
+test clock-3.742 {ISO week-based calendar 2060-W53-1} {
+ clock format 2871331200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2060-W53-1
+} {Mon Monday 60 2060 1 52 53 1 52}
+test clock-3.743 {ISO week-based calendar 2060-W53-6} {
+ clock format 2871763200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2060-W53-6
+} {Sat Saturday 60 2060 6 00 53 6 00}
+test clock-3.744 {ISO week-based calendar 2060-W53-7} {
+ clock format 2871849600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2060-W53-7
+} {Sun Sunday 60 2060 7 01 53 0 00}
+test clock-3.745 {ISO week-based calendar 2061-W01-1} {
+ clock format 2871936000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2061-W01-1
+} {Mon Monday 61 2061 1 01 01 1 01}
+test clock-3.746 {ISO week-based calendar 2061-W01-6} {
+ clock format 2872368000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2061-W01-6
+} {Sat Saturday 61 2061 6 01 01 6 01}
+test clock-3.747 {ISO week-based calendar 2061-W01-7} {
+ clock format 2872454400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2061-W01-7
+} {Sun Sunday 61 2061 7 02 01 0 01}
+test clock-3.748 {ISO week-based calendar 2061-W02-1} {
+ clock format 2872540800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2061-W02-1
+} {Mon Monday 61 2061 1 02 02 1 02}
+test clock-3.749 {ISO week-based calendar 2063-W52-1} {
+ clock format 2965680000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2063-W52-1
+} {Mon Monday 63 2063 1 51 52 1 52}
+test clock-3.750 {ISO week-based calendar 2063-W52-6} {
+ clock format 2966112000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2063-W52-6
+} {Sat Saturday 63 2063 6 51 52 6 52}
+test clock-3.751 {ISO week-based calendar 2063-W52-7} {
+ clock format 2966198400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2063-W52-7
+} {Sun Sunday 63 2063 7 52 52 0 52}
+test clock-3.752 {ISO week-based calendar 2064-W01-1} {
+ clock format 2966284800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2064-W01-1
+} {Mon Monday 64 2064 1 52 01 1 53}
+test clock-3.753 {ISO week-based calendar 2064-W01-2} {
+ clock format 2966371200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2064-W01-2
+} {Tue Tuesday 64 2064 2 00 01 2 00}
+test clock-3.754 {ISO week-based calendar 2064-W01-6} {
+ clock format 2966716800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2064-W01-6
+} {Sat Saturday 64 2064 6 00 01 6 00}
+test clock-3.755 {ISO week-based calendar 2064-W01-7} {
+ clock format 2966803200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2064-W01-7
+} {Sun Sunday 64 2064 7 01 01 0 00}
+test clock-3.756 {ISO week-based calendar 2064-W02-1} {
+ clock format 2966889600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2064-W02-1
+} {Mon Monday 64 2064 1 01 02 1 01}
+test clock-3.757 {ISO week-based calendar 2064-W52-1} {
+ clock format 2997129600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2064-W52-1
+} {Mon Monday 64 2064 1 51 52 1 51}
+test clock-3.758 {ISO week-based calendar 2064-W52-6} {
+ clock format 2997561600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2064-W52-6
+} {Sat Saturday 64 2064 6 51 52 6 51}
+test clock-3.759 {ISO week-based calendar 2064-W52-7} {
+ clock format 2997648000 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2064-W52-7
+} {Sun Sunday 64 2064 7 52 52 0 51}
+test clock-3.760 {ISO week-based calendar 2065-W01-1} {
+ clock format 2997734400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2065-W01-1
+} {Mon Monday 65 2065 1 52 01 1 52}
+test clock-3.761 {ISO week-based calendar 2065-W01-4} {
+ clock format 2997993600 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2065-W01-4
+} {Thu Thursday 65 2065 4 00 01 4 00}
+test clock-3.762 {ISO week-based calendar 2065-W01-6} {
+ clock format 2998166400 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2065-W01-6
+} {Sat Saturday 65 2065 6 00 01 6 00}
+test clock-3.763 {ISO week-based calendar 2065-W01-7} {
+ clock format 2998252800 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2065-W01-7
+} {Sun Sunday 65 2065 7 01 01 0 00}
+test clock-3.764 {ISO week-based calendar 2065-W02-1} {
+ clock format 2998339200 -format {%a %A %g %G %u %U %V %w %W} -gmt true; # 2065-W02-1
+} {Mon Monday 65 2065 1 01 02 1 01}
+# END testcases3
+
+# BEGIN testcases4
+
+# Test formatting of time of day
+# Format groups tested: %H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+
+
+test clock-4.1 { format time of day 00:00:00 } {
+ clock format 0 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {00 ? 12 xii 0 ? 12 xii 00 ? AM am 12:00:00 am 00:00 00 ? 00:00:00 00:00:00 ? h ? m ? s Thu Jan 1 00:00:00 GMT 1970}
+test clock-4.2 { format time of day 00:00:01 } {
+ clock format 1 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {00 ? 12 xii 0 ? 12 xii 00 ? AM am 12:00:01 am 00:00 01 i 00:00:01 00:00:01 ? h ? m i s Thu Jan 1 00:00:01 GMT 1970}
+test clock-4.3 { format time of day 00:00:58 } {
+ clock format 58 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {00 ? 12 xii 0 ? 12 xii 00 ? AM am 12:00:58 am 00:00 58 lviii 00:00:58 00:00:58 ? h ? m lviii s Thu Jan 1 00:00:58 GMT 1970}
+test clock-4.4 { format time of day 00:00:59 } {
+ clock format 59 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {00 ? 12 xii 0 ? 12 xii 00 ? AM am 12:00:59 am 00:00 59 lix 00:00:59 00:00:59 ? h ? m lix s Thu Jan 1 00:00:59 GMT 1970}
+test clock-4.5 { format time of day 00:01:00 } {
+ clock format 60 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {00 ? 12 xii 0 ? 12 xii 01 i AM am 12:01:00 am 00:01 00 ? 00:01:00 00:01:00 ? h i m ? s Thu Jan 1 00:01:00 GMT 1970}
+test clock-4.6 { format time of day 00:01:01 } {
+ clock format 61 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {00 ? 12 xii 0 ? 12 xii 01 i AM am 12:01:01 am 00:01 01 i 00:01:01 00:01:01 ? h i m i s Thu Jan 1 00:01:01 GMT 1970}
+test clock-4.7 { format time of day 00:01:58 } {
+ clock format 118 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {00 ? 12 xii 0 ? 12 xii 01 i AM am 12:01:58 am 00:01 58 lviii 00:01:58 00:01:58 ? h i m lviii s Thu Jan 1 00:01:58 GMT 1970}
+test clock-4.8 { format time of day 00:01:59 } {
+ clock format 119 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {00 ? 12 xii 0 ? 12 xii 01 i AM am 12:01:59 am 00:01 59 lix 00:01:59 00:01:59 ? h i m lix s Thu Jan 1 00:01:59 GMT 1970}
+test clock-4.9 { format time of day 00:58:00 } {
+ clock format 3480 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {00 ? 12 xii 0 ? 12 xii 58 lviii AM am 12:58:00 am 00:58 00 ? 00:58:00 00:58:00 ? h lviii m ? s Thu Jan 1 00:58:00 GMT 1970}
+test clock-4.10 { format time of day 00:58:01 } {
+ clock format 3481 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {00 ? 12 xii 0 ? 12 xii 58 lviii AM am 12:58:01 am 00:58 01 i 00:58:01 00:58:01 ? h lviii m i s Thu Jan 1 00:58:01 GMT 1970}
+test clock-4.11 { format time of day 00:58:58 } {
+ clock format 3538 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {00 ? 12 xii 0 ? 12 xii 58 lviii AM am 12:58:58 am 00:58 58 lviii 00:58:58 00:58:58 ? h lviii m lviii s Thu Jan 1 00:58:58 GMT 1970}
+test clock-4.12 { format time of day 00:58:59 } {
+ clock format 3539 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {00 ? 12 xii 0 ? 12 xii 58 lviii AM am 12:58:59 am 00:58 59 lix 00:58:59 00:58:59 ? h lviii m lix s Thu Jan 1 00:58:59 GMT 1970}
+test clock-4.13 { format time of day 00:59:00 } {
+ clock format 3540 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {00 ? 12 xii 0 ? 12 xii 59 lix AM am 12:59:00 am 00:59 00 ? 00:59:00 00:59:00 ? h lix m ? s Thu Jan 1 00:59:00 GMT 1970}
+test clock-4.14 { format time of day 00:59:01 } {
+ clock format 3541 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {00 ? 12 xii 0 ? 12 xii 59 lix AM am 12:59:01 am 00:59 01 i 00:59:01 00:59:01 ? h lix m i s Thu Jan 1 00:59:01 GMT 1970}
+test clock-4.15 { format time of day 00:59:58 } {
+ clock format 3598 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {00 ? 12 xii 0 ? 12 xii 59 lix AM am 12:59:58 am 00:59 58 lviii 00:59:58 00:59:58 ? h lix m lviii s Thu Jan 1 00:59:58 GMT 1970}
+test clock-4.16 { format time of day 00:59:59 } {
+ clock format 3599 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {00 ? 12 xii 0 ? 12 xii 59 lix AM am 12:59:59 am 00:59 59 lix 00:59:59 00:59:59 ? h lix m lix s Thu Jan 1 00:59:59 GMT 1970}
+test clock-4.17 { format time of day 01:00:00 } {
+ clock format 3600 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {01 i 01 i 1 i 1 i 00 ? AM am 01:00:00 am 01:00 00 ? 01:00:00 01:00:00 i h ? m ? s Thu Jan 1 01:00:00 GMT 1970}
+test clock-4.18 { format time of day 01:00:01 } {
+ clock format 3601 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {01 i 01 i 1 i 1 i 00 ? AM am 01:00:01 am 01:00 01 i 01:00:01 01:00:01 i h ? m i s Thu Jan 1 01:00:01 GMT 1970}
+test clock-4.19 { format time of day 01:00:58 } {
+ clock format 3658 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {01 i 01 i 1 i 1 i 00 ? AM am 01:00:58 am 01:00 58 lviii 01:00:58 01:00:58 i h ? m lviii s Thu Jan 1 01:00:58 GMT 1970}
+test clock-4.20 { format time of day 01:00:59 } {
+ clock format 3659 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {01 i 01 i 1 i 1 i 00 ? AM am 01:00:59 am 01:00 59 lix 01:00:59 01:00:59 i h ? m lix s Thu Jan 1 01:00:59 GMT 1970}
+test clock-4.21 { format time of day 01:01:00 } {
+ clock format 3660 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {01 i 01 i 1 i 1 i 01 i AM am 01:01:00 am 01:01 00 ? 01:01:00 01:01:00 i h i m ? s Thu Jan 1 01:01:00 GMT 1970}
+test clock-4.22 { format time of day 01:01:01 } {
+ clock format 3661 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {01 i 01 i 1 i 1 i 01 i AM am 01:01:01 am 01:01 01 i 01:01:01 01:01:01 i h i m i s Thu Jan 1 01:01:01 GMT 1970}
+test clock-4.23 { format time of day 01:01:58 } {
+ clock format 3718 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {01 i 01 i 1 i 1 i 01 i AM am 01:01:58 am 01:01 58 lviii 01:01:58 01:01:58 i h i m lviii s Thu Jan 1 01:01:58 GMT 1970}
+test clock-4.24 { format time of day 01:01:59 } {
+ clock format 3719 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {01 i 01 i 1 i 1 i 01 i AM am 01:01:59 am 01:01 59 lix 01:01:59 01:01:59 i h i m lix s Thu Jan 1 01:01:59 GMT 1970}
+test clock-4.25 { format time of day 01:58:00 } {
+ clock format 7080 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {01 i 01 i 1 i 1 i 58 lviii AM am 01:58:00 am 01:58 00 ? 01:58:00 01:58:00 i h lviii m ? s Thu Jan 1 01:58:00 GMT 1970}
+test clock-4.26 { format time of day 01:58:01 } {
+ clock format 7081 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {01 i 01 i 1 i 1 i 58 lviii AM am 01:58:01 am 01:58 01 i 01:58:01 01:58:01 i h lviii m i s Thu Jan 1 01:58:01 GMT 1970}
+test clock-4.27 { format time of day 01:58:58 } {
+ clock format 7138 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {01 i 01 i 1 i 1 i 58 lviii AM am 01:58:58 am 01:58 58 lviii 01:58:58 01:58:58 i h lviii m lviii s Thu Jan 1 01:58:58 GMT 1970}
+test clock-4.28 { format time of day 01:58:59 } {
+ clock format 7139 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {01 i 01 i 1 i 1 i 58 lviii AM am 01:58:59 am 01:58 59 lix 01:58:59 01:58:59 i h lviii m lix s Thu Jan 1 01:58:59 GMT 1970}
+test clock-4.29 { format time of day 01:59:00 } {
+ clock format 7140 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {01 i 01 i 1 i 1 i 59 lix AM am 01:59:00 am 01:59 00 ? 01:59:00 01:59:00 i h lix m ? s Thu Jan 1 01:59:00 GMT 1970}
+test clock-4.30 { format time of day 01:59:01 } {
+ clock format 7141 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {01 i 01 i 1 i 1 i 59 lix AM am 01:59:01 am 01:59 01 i 01:59:01 01:59:01 i h lix m i s Thu Jan 1 01:59:01 GMT 1970}
+test clock-4.31 { format time of day 01:59:58 } {
+ clock format 7198 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {01 i 01 i 1 i 1 i 59 lix AM am 01:59:58 am 01:59 58 lviii 01:59:58 01:59:58 i h lix m lviii s Thu Jan 1 01:59:58 GMT 1970}
+test clock-4.32 { format time of day 01:59:59 } {
+ clock format 7199 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {01 i 01 i 1 i 1 i 59 lix AM am 01:59:59 am 01:59 59 lix 01:59:59 01:59:59 i h lix m lix s Thu Jan 1 01:59:59 GMT 1970}
+test clock-4.33 { format time of day 11:00:00 } {
+ clock format 39600 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {11 xi 11 xi 11 xi 11 xi 00 ? AM am 11:00:00 am 11:00 00 ? 11:00:00 11:00:00 xi h ? m ? s Thu Jan 1 11:00:00 GMT 1970}
+test clock-4.34 { format time of day 11:00:01 } {
+ clock format 39601 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {11 xi 11 xi 11 xi 11 xi 00 ? AM am 11:00:01 am 11:00 01 i 11:00:01 11:00:01 xi h ? m i s Thu Jan 1 11:00:01 GMT 1970}
+test clock-4.35 { format time of day 11:00:58 } {
+ clock format 39658 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {11 xi 11 xi 11 xi 11 xi 00 ? AM am 11:00:58 am 11:00 58 lviii 11:00:58 11:00:58 xi h ? m lviii s Thu Jan 1 11:00:58 GMT 1970}
+test clock-4.36 { format time of day 11:00:59 } {
+ clock format 39659 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {11 xi 11 xi 11 xi 11 xi 00 ? AM am 11:00:59 am 11:00 59 lix 11:00:59 11:00:59 xi h ? m lix s Thu Jan 1 11:00:59 GMT 1970}
+test clock-4.37 { format time of day 11:01:00 } {
+ clock format 39660 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {11 xi 11 xi 11 xi 11 xi 01 i AM am 11:01:00 am 11:01 00 ? 11:01:00 11:01:00 xi h i m ? s Thu Jan 1 11:01:00 GMT 1970}
+test clock-4.38 { format time of day 11:01:01 } {
+ clock format 39661 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {11 xi 11 xi 11 xi 11 xi 01 i AM am 11:01:01 am 11:01 01 i 11:01:01 11:01:01 xi h i m i s Thu Jan 1 11:01:01 GMT 1970}
+test clock-4.39 { format time of day 11:01:58 } {
+ clock format 39718 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {11 xi 11 xi 11 xi 11 xi 01 i AM am 11:01:58 am 11:01 58 lviii 11:01:58 11:01:58 xi h i m lviii s Thu Jan 1 11:01:58 GMT 1970}
+test clock-4.40 { format time of day 11:01:59 } {
+ clock format 39719 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {11 xi 11 xi 11 xi 11 xi 01 i AM am 11:01:59 am 11:01 59 lix 11:01:59 11:01:59 xi h i m lix s Thu Jan 1 11:01:59 GMT 1970}
+test clock-4.41 { format time of day 11:58:00 } {
+ clock format 43080 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {11 xi 11 xi 11 xi 11 xi 58 lviii AM am 11:58:00 am 11:58 00 ? 11:58:00 11:58:00 xi h lviii m ? s Thu Jan 1 11:58:00 GMT 1970}
+test clock-4.42 { format time of day 11:58:01 } {
+ clock format 43081 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {11 xi 11 xi 11 xi 11 xi 58 lviii AM am 11:58:01 am 11:58 01 i 11:58:01 11:58:01 xi h lviii m i s Thu Jan 1 11:58:01 GMT 1970}
+test clock-4.43 { format time of day 11:58:58 } {
+ clock format 43138 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {11 xi 11 xi 11 xi 11 xi 58 lviii AM am 11:58:58 am 11:58 58 lviii 11:58:58 11:58:58 xi h lviii m lviii s Thu Jan 1 11:58:58 GMT 1970}
+test clock-4.44 { format time of day 11:58:59 } {
+ clock format 43139 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {11 xi 11 xi 11 xi 11 xi 58 lviii AM am 11:58:59 am 11:58 59 lix 11:58:59 11:58:59 xi h lviii m lix s Thu Jan 1 11:58:59 GMT 1970}
+test clock-4.45 { format time of day 11:59:00 } {
+ clock format 43140 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {11 xi 11 xi 11 xi 11 xi 59 lix AM am 11:59:00 am 11:59 00 ? 11:59:00 11:59:00 xi h lix m ? s Thu Jan 1 11:59:00 GMT 1970}
+test clock-4.46 { format time of day 11:59:01 } {
+ clock format 43141 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {11 xi 11 xi 11 xi 11 xi 59 lix AM am 11:59:01 am 11:59 01 i 11:59:01 11:59:01 xi h lix m i s Thu Jan 1 11:59:01 GMT 1970}
+test clock-4.47 { format time of day 11:59:58 } {
+ clock format 43198 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {11 xi 11 xi 11 xi 11 xi 59 lix AM am 11:59:58 am 11:59 58 lviii 11:59:58 11:59:58 xi h lix m lviii s Thu Jan 1 11:59:58 GMT 1970}
+test clock-4.48 { format time of day 11:59:59 } {
+ clock format 43199 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {11 xi 11 xi 11 xi 11 xi 59 lix AM am 11:59:59 am 11:59 59 lix 11:59:59 11:59:59 xi h lix m lix s Thu Jan 1 11:59:59 GMT 1970}
+test clock-4.49 { format time of day 12:00:00 } {
+ clock format 43200 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {12 xii 12 xii 12 xii 12 xii 00 ? PM pm 12:00:00 pm 12:00 00 ? 12:00:00 12:00:00 xii h ? m ? s Thu Jan 1 12:00:00 GMT 1970}
+test clock-4.50 { format time of day 12:00:01 } {
+ clock format 43201 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {12 xii 12 xii 12 xii 12 xii 00 ? PM pm 12:00:01 pm 12:00 01 i 12:00:01 12:00:01 xii h ? m i s Thu Jan 1 12:00:01 GMT 1970}
+test clock-4.51 { format time of day 12:00:58 } {
+ clock format 43258 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {12 xii 12 xii 12 xii 12 xii 00 ? PM pm 12:00:58 pm 12:00 58 lviii 12:00:58 12:00:58 xii h ? m lviii s Thu Jan 1 12:00:58 GMT 1970}
+test clock-4.52 { format time of day 12:00:59 } {
+ clock format 43259 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {12 xii 12 xii 12 xii 12 xii 00 ? PM pm 12:00:59 pm 12:00 59 lix 12:00:59 12:00:59 xii h ? m lix s Thu Jan 1 12:00:59 GMT 1970}
+test clock-4.53 { format time of day 12:01:00 } {
+ clock format 43260 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {12 xii 12 xii 12 xii 12 xii 01 i PM pm 12:01:00 pm 12:01 00 ? 12:01:00 12:01:00 xii h i m ? s Thu Jan 1 12:01:00 GMT 1970}
+test clock-4.54 { format time of day 12:01:01 } {
+ clock format 43261 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {12 xii 12 xii 12 xii 12 xii 01 i PM pm 12:01:01 pm 12:01 01 i 12:01:01 12:01:01 xii h i m i s Thu Jan 1 12:01:01 GMT 1970}
+test clock-4.55 { format time of day 12:01:58 } {
+ clock format 43318 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {12 xii 12 xii 12 xii 12 xii 01 i PM pm 12:01:58 pm 12:01 58 lviii 12:01:58 12:01:58 xii h i m lviii s Thu Jan 1 12:01:58 GMT 1970}
+test clock-4.56 { format time of day 12:01:59 } {
+ clock format 43319 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {12 xii 12 xii 12 xii 12 xii 01 i PM pm 12:01:59 pm 12:01 59 lix 12:01:59 12:01:59 xii h i m lix s Thu Jan 1 12:01:59 GMT 1970}
+test clock-4.57 { format time of day 12:58:00 } {
+ clock format 46680 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {12 xii 12 xii 12 xii 12 xii 58 lviii PM pm 12:58:00 pm 12:58 00 ? 12:58:00 12:58:00 xii h lviii m ? s Thu Jan 1 12:58:00 GMT 1970}
+test clock-4.58 { format time of day 12:58:01 } {
+ clock format 46681 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {12 xii 12 xii 12 xii 12 xii 58 lviii PM pm 12:58:01 pm 12:58 01 i 12:58:01 12:58:01 xii h lviii m i s Thu Jan 1 12:58:01 GMT 1970}
+test clock-4.59 { format time of day 12:58:58 } {
+ clock format 46738 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {12 xii 12 xii 12 xii 12 xii 58 lviii PM pm 12:58:58 pm 12:58 58 lviii 12:58:58 12:58:58 xii h lviii m lviii s Thu Jan 1 12:58:58 GMT 1970}
+test clock-4.60 { format time of day 12:58:59 } {
+ clock format 46739 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {12 xii 12 xii 12 xii 12 xii 58 lviii PM pm 12:58:59 pm 12:58 59 lix 12:58:59 12:58:59 xii h lviii m lix s Thu Jan 1 12:58:59 GMT 1970}
+test clock-4.61 { format time of day 12:59:00 } {
+ clock format 46740 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {12 xii 12 xii 12 xii 12 xii 59 lix PM pm 12:59:00 pm 12:59 00 ? 12:59:00 12:59:00 xii h lix m ? s Thu Jan 1 12:59:00 GMT 1970}
+test clock-4.62 { format time of day 12:59:01 } {
+ clock format 46741 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {12 xii 12 xii 12 xii 12 xii 59 lix PM pm 12:59:01 pm 12:59 01 i 12:59:01 12:59:01 xii h lix m i s Thu Jan 1 12:59:01 GMT 1970}
+test clock-4.63 { format time of day 12:59:58 } {
+ clock format 46798 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {12 xii 12 xii 12 xii 12 xii 59 lix PM pm 12:59:58 pm 12:59 58 lviii 12:59:58 12:59:58 xii h lix m lviii s Thu Jan 1 12:59:58 GMT 1970}
+test clock-4.64 { format time of day 12:59:59 } {
+ clock format 46799 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {12 xii 12 xii 12 xii 12 xii 59 lix PM pm 12:59:59 pm 12:59 59 lix 12:59:59 12:59:59 xii h lix m lix s Thu Jan 1 12:59:59 GMT 1970}
+test clock-4.65 { format time of day 13:00:00 } {
+ clock format 46800 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {13 xiii 01 i 13 xiii 1 i 00 ? PM pm 01:00:00 pm 13:00 00 ? 13:00:00 13:00:00 xiii h ? m ? s Thu Jan 1 13:00:00 GMT 1970}
+test clock-4.66 { format time of day 13:00:01 } {
+ clock format 46801 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {13 xiii 01 i 13 xiii 1 i 00 ? PM pm 01:00:01 pm 13:00 01 i 13:00:01 13:00:01 xiii h ? m i s Thu Jan 1 13:00:01 GMT 1970}
+test clock-4.67 { format time of day 13:00:58 } {
+ clock format 46858 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {13 xiii 01 i 13 xiii 1 i 00 ? PM pm 01:00:58 pm 13:00 58 lviii 13:00:58 13:00:58 xiii h ? m lviii s Thu Jan 1 13:00:58 GMT 1970}
+test clock-4.68 { format time of day 13:00:59 } {
+ clock format 46859 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {13 xiii 01 i 13 xiii 1 i 00 ? PM pm 01:00:59 pm 13:00 59 lix 13:00:59 13:00:59 xiii h ? m lix s Thu Jan 1 13:00:59 GMT 1970}
+test clock-4.69 { format time of day 13:01:00 } {
+ clock format 46860 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {13 xiii 01 i 13 xiii 1 i 01 i PM pm 01:01:00 pm 13:01 00 ? 13:01:00 13:01:00 xiii h i m ? s Thu Jan 1 13:01:00 GMT 1970}
+test clock-4.70 { format time of day 13:01:01 } {
+ clock format 46861 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {13 xiii 01 i 13 xiii 1 i 01 i PM pm 01:01:01 pm 13:01 01 i 13:01:01 13:01:01 xiii h i m i s Thu Jan 1 13:01:01 GMT 1970}
+test clock-4.71 { format time of day 13:01:58 } {
+ clock format 46918 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {13 xiii 01 i 13 xiii 1 i 01 i PM pm 01:01:58 pm 13:01 58 lviii 13:01:58 13:01:58 xiii h i m lviii s Thu Jan 1 13:01:58 GMT 1970}
+test clock-4.72 { format time of day 13:01:59 } {
+ clock format 46919 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {13 xiii 01 i 13 xiii 1 i 01 i PM pm 01:01:59 pm 13:01 59 lix 13:01:59 13:01:59 xiii h i m lix s Thu Jan 1 13:01:59 GMT 1970}
+test clock-4.73 { format time of day 13:58:00 } {
+ clock format 50280 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {13 xiii 01 i 13 xiii 1 i 58 lviii PM pm 01:58:00 pm 13:58 00 ? 13:58:00 13:58:00 xiii h lviii m ? s Thu Jan 1 13:58:00 GMT 1970}
+test clock-4.74 { format time of day 13:58:01 } {
+ clock format 50281 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {13 xiii 01 i 13 xiii 1 i 58 lviii PM pm 01:58:01 pm 13:58 01 i 13:58:01 13:58:01 xiii h lviii m i s Thu Jan 1 13:58:01 GMT 1970}
+test clock-4.75 { format time of day 13:58:58 } {
+ clock format 50338 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {13 xiii 01 i 13 xiii 1 i 58 lviii PM pm 01:58:58 pm 13:58 58 lviii 13:58:58 13:58:58 xiii h lviii m lviii s Thu Jan 1 13:58:58 GMT 1970}
+test clock-4.76 { format time of day 13:58:59 } {
+ clock format 50339 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {13 xiii 01 i 13 xiii 1 i 58 lviii PM pm 01:58:59 pm 13:58 59 lix 13:58:59 13:58:59 xiii h lviii m lix s Thu Jan 1 13:58:59 GMT 1970}
+test clock-4.77 { format time of day 13:59:00 } {
+ clock format 50340 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {13 xiii 01 i 13 xiii 1 i 59 lix PM pm 01:59:00 pm 13:59 00 ? 13:59:00 13:59:00 xiii h lix m ? s Thu Jan 1 13:59:00 GMT 1970}
+test clock-4.78 { format time of day 13:59:01 } {
+ clock format 50341 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {13 xiii 01 i 13 xiii 1 i 59 lix PM pm 01:59:01 pm 13:59 01 i 13:59:01 13:59:01 xiii h lix m i s Thu Jan 1 13:59:01 GMT 1970}
+test clock-4.79 { format time of day 13:59:58 } {
+ clock format 50398 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {13 xiii 01 i 13 xiii 1 i 59 lix PM pm 01:59:58 pm 13:59 58 lviii 13:59:58 13:59:58 xiii h lix m lviii s Thu Jan 1 13:59:58 GMT 1970}
+test clock-4.80 { format time of day 13:59:59 } {
+ clock format 50399 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {13 xiii 01 i 13 xiii 1 i 59 lix PM pm 01:59:59 pm 13:59 59 lix 13:59:59 13:59:59 xiii h lix m lix s Thu Jan 1 13:59:59 GMT 1970}
+test clock-4.81 { format time of day 23:00:00 } {
+ clock format 82800 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {23 xxiii 11 xi 23 xxiii 11 xi 00 ? PM pm 11:00:00 pm 23:00 00 ? 23:00:00 23:00:00 xxiii h ? m ? s Thu Jan 1 23:00:00 GMT 1970}
+test clock-4.82 { format time of day 23:00:01 } {
+ clock format 82801 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {23 xxiii 11 xi 23 xxiii 11 xi 00 ? PM pm 11:00:01 pm 23:00 01 i 23:00:01 23:00:01 xxiii h ? m i s Thu Jan 1 23:00:01 GMT 1970}
+test clock-4.83 { format time of day 23:00:58 } {
+ clock format 82858 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {23 xxiii 11 xi 23 xxiii 11 xi 00 ? PM pm 11:00:58 pm 23:00 58 lviii 23:00:58 23:00:58 xxiii h ? m lviii s Thu Jan 1 23:00:58 GMT 1970}
+test clock-4.84 { format time of day 23:00:59 } {
+ clock format 82859 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {23 xxiii 11 xi 23 xxiii 11 xi 00 ? PM pm 11:00:59 pm 23:00 59 lix 23:00:59 23:00:59 xxiii h ? m lix s Thu Jan 1 23:00:59 GMT 1970}
+test clock-4.85 { format time of day 23:01:00 } {
+ clock format 82860 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {23 xxiii 11 xi 23 xxiii 11 xi 01 i PM pm 11:01:00 pm 23:01 00 ? 23:01:00 23:01:00 xxiii h i m ? s Thu Jan 1 23:01:00 GMT 1970}
+test clock-4.86 { format time of day 23:01:01 } {
+ clock format 82861 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {23 xxiii 11 xi 23 xxiii 11 xi 01 i PM pm 11:01:01 pm 23:01 01 i 23:01:01 23:01:01 xxiii h i m i s Thu Jan 1 23:01:01 GMT 1970}
+test clock-4.87 { format time of day 23:01:58 } {
+ clock format 82918 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {23 xxiii 11 xi 23 xxiii 11 xi 01 i PM pm 11:01:58 pm 23:01 58 lviii 23:01:58 23:01:58 xxiii h i m lviii s Thu Jan 1 23:01:58 GMT 1970}
+test clock-4.88 { format time of day 23:01:59 } {
+ clock format 82919 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {23 xxiii 11 xi 23 xxiii 11 xi 01 i PM pm 11:01:59 pm 23:01 59 lix 23:01:59 23:01:59 xxiii h i m lix s Thu Jan 1 23:01:59 GMT 1970}
+test clock-4.89 { format time of day 23:58:00 } {
+ clock format 86280 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {23 xxiii 11 xi 23 xxiii 11 xi 58 lviii PM pm 11:58:00 pm 23:58 00 ? 23:58:00 23:58:00 xxiii h lviii m ? s Thu Jan 1 23:58:00 GMT 1970}
+test clock-4.90 { format time of day 23:58:01 } {
+ clock format 86281 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {23 xxiii 11 xi 23 xxiii 11 xi 58 lviii PM pm 11:58:01 pm 23:58 01 i 23:58:01 23:58:01 xxiii h lviii m i s Thu Jan 1 23:58:01 GMT 1970}
+test clock-4.91 { format time of day 23:58:58 } {
+ clock format 86338 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {23 xxiii 11 xi 23 xxiii 11 xi 58 lviii PM pm 11:58:58 pm 23:58 58 lviii 23:58:58 23:58:58 xxiii h lviii m lviii s Thu Jan 1 23:58:58 GMT 1970}
+test clock-4.92 { format time of day 23:58:59 } {
+ clock format 86339 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {23 xxiii 11 xi 23 xxiii 11 xi 58 lviii PM pm 11:58:59 pm 23:58 59 lix 23:58:59 23:58:59 xxiii h lviii m lix s Thu Jan 1 23:58:59 GMT 1970}
+test clock-4.93 { format time of day 23:59:00 } {
+ clock format 86340 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {23 xxiii 11 xi 23 xxiii 11 xi 59 lix PM pm 11:59:00 pm 23:59 00 ? 23:59:00 23:59:00 xxiii h lix m ? s Thu Jan 1 23:59:00 GMT 1970}
+test clock-4.94 { format time of day 23:59:01 } {
+ clock format 86341 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {23 xxiii 11 xi 23 xxiii 11 xi 59 lix PM pm 11:59:01 pm 23:59 01 i 23:59:01 23:59:01 xxiii h lix m i s Thu Jan 1 23:59:01 GMT 1970}
+test clock-4.95 { format time of day 23:59:58 } {
+ clock format 86398 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {23 xxiii 11 xi 23 xxiii 11 xi 59 lix PM pm 11:59:58 pm 23:59 58 lviii 23:59:58 23:59:58 xxiii h lix m lviii s Thu Jan 1 23:59:58 GMT 1970}
+test clock-4.96 { format time of day 23:59:59 } {
+ clock format 86399 \
+ -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
+ -locale en_US_roman \
+ -gmt true
+} {23 xxiii 11 xi 23 xxiii 11 xi 59 lix PM pm 11:59:59 pm 23:59 59 lix 23:59:59 23:59:59 xxiii h lix m lix s Thu Jan 1 23:59:59 GMT 1970}
+# END testcases4
+
+# BEGIN testcases5
+
+# Test formatting of Daylight Saving Time
+
+test clock-5.1 {does Detroit exist} {
+ clock format 0 -format {} -timezone :America/Detroit
+ concat
+} {}
+test clock-5.2 {does Detroit have a Y2038 problem} detroit {
+ if { [clock format 2158894800 -format %z -timezone :America/Detroit] ne {-0400} } {
+ concat {y2038 problem}
+ } else {
+ concat {ok}
+ }
+} ok
+test clock-5.3 {time zone boundary case 1904-12-31 23:59:59} detroit {
+ clock format -2051202470 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {23:59:59 -053211 LMT}
+test clock-5.4 {time zone boundary case 1904-12-31 23:32:11} detroit {
+ clock format -2051202469 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {23:32:11 -0600 CST}
+test clock-5.5 {time zone boundary case 1904-12-31 23:32:12} detroit {
+ clock format -2051202468 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {23:32:12 -0600 CST}
+test clock-5.6 {time zone boundary case 1915-05-15 01:59:59} detroit {
+ clock format -1724083201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0600 CST}
+test clock-5.7 {time zone boundary case 1915-05-15 03:00:00} detroit {
+ clock format -1724083200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0500 EST}
+test clock-5.8 {time zone boundary case 1915-05-15 03:00:01} detroit {
+ clock format -1724083199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0500 EST}
+test clock-5.9 {time zone boundary case 1941-12-31 23:59:59} detroit {
+ clock format -883594801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {23:59:59 -0500 EST}
+test clock-5.10 {time zone boundary case 1942-01-01 00:00:00} detroit {
+ clock format -883594800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {00:00:00 -0500 EST}
+test clock-5.11 {time zone boundary case 1942-01-01 00:00:01} detroit {
+ clock format -883594799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {00:00:01 -0500 EST}
+test clock-5.12 {time zone boundary case 1942-02-09 01:59:59} detroit {
+ clock format -880218001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.13 {time zone boundary case 1942-02-09 03:00:00} detroit {
+ clock format -880218000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EWT}
+test clock-5.14 {time zone boundary case 1942-02-09 03:00:01} detroit {
+ clock format -880217999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EWT}
+test clock-5.15 {time zone boundary case 1945-08-14 18:59:59} detroit {
+ clock format -769395601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {18:59:59 -0400 EWT}
+test clock-5.16 {time zone boundary case 1945-08-14 19:00:00} detroit {
+ clock format -769395600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {19:00:00 -0400 EPT}
+test clock-5.17 {time zone boundary case 1945-08-14 19:00:01} detroit {
+ clock format -769395599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {19:00:01 -0400 EPT}
+test clock-5.18 {time zone boundary case 1945-09-30 01:59:59} detroit {
+ clock format -765396001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EPT}
+test clock-5.19 {time zone boundary case 1945-09-30 01:00:00} detroit {
+ clock format -765396000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.20 {time zone boundary case 1945-09-30 01:00:01} detroit {
+ clock format -765395999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.21 {time zone boundary case 1945-12-31 23:59:59} detroit {
+ clock format -757364401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {23:59:59 -0500 EST}
+test clock-5.22 {time zone boundary case 1946-01-01 00:00:00} detroit {
+ clock format -757364400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {00:00:00 -0500 EST}
+test clock-5.23 {time zone boundary case 1946-01-01 00:00:01} detroit {
+ clock format -757364399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {00:00:01 -0500 EST}
+test clock-5.24 {time zone boundary case 1948-04-25 01:59:59} detroit {
+ clock format -684349201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.25 {time zone boundary case 1948-04-25 03:00:00} detroit {
+ clock format -684349200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.26 {time zone boundary case 1948-04-25 03:00:01} detroit {
+ clock format -684349199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.27 {time zone boundary case 1948-09-26 01:59:59} detroit {
+ clock format -671047201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.28 {time zone boundary case 1948-09-26 01:00:00} detroit {
+ clock format -671047200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.29 {time zone boundary case 1948-09-26 01:00:01} detroit {
+ clock format -671047199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.30 {time zone boundary case 1967-06-14 01:59:59} detroit {
+ clock format -80499601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.31 {time zone boundary case 1967-06-14 03:00:00} detroit {
+ clock format -80499600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.32 {time zone boundary case 1967-06-14 03:00:01} detroit {
+ clock format -80499599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.33 {time zone boundary case 1967-10-29 01:59:59} detroit {
+ clock format -68666401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.34 {time zone boundary case 1967-10-29 01:00:00} detroit {
+ clock format -68666400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.35 {time zone boundary case 1967-10-29 01:00:01} detroit {
+ clock format -68666399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.36 {time zone boundary case 1972-12-31 23:59:59} detroit {
+ clock format 94712399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {23:59:59 -0500 EST}
+test clock-5.37 {time zone boundary case 1973-01-01 00:00:00} detroit {
+ clock format 94712400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {00:00:00 -0500 EST}
+test clock-5.38 {time zone boundary case 1973-01-01 00:00:01} detroit {
+ clock format 94712401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {00:00:01 -0500 EST}
+test clock-5.39 {time zone boundary case 1973-04-29 01:59:59} detroit {
+ clock format 104914799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.40 {time zone boundary case 1973-04-29 03:00:00} detroit {
+ clock format 104914800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.41 {time zone boundary case 1973-04-29 03:00:01} detroit {
+ clock format 104914801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.42 {time zone boundary case 1973-10-28 01:59:59} detroit {
+ clock format 120635999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.43 {time zone boundary case 1973-10-28 01:00:00} detroit {
+ clock format 120636000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.44 {time zone boundary case 1973-10-28 01:00:01} detroit {
+ clock format 120636001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.45 {time zone boundary case 1974-01-06 01:59:59} detroit {
+ clock format 126687599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.46 {time zone boundary case 1974-01-06 03:00:00} detroit {
+ clock format 126687600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.47 {time zone boundary case 1974-01-06 03:00:01} detroit {
+ clock format 126687601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.48 {time zone boundary case 1974-10-27 01:59:59} detroit {
+ clock format 152085599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.49 {time zone boundary case 1974-10-27 01:00:00} detroit {
+ clock format 152085600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.50 {time zone boundary case 1974-10-27 01:00:01} detroit {
+ clock format 152085601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.51 {time zone boundary case 1974-12-31 23:59:59} detroit {
+ clock format 157784399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {23:59:59 -0500 EST}
+test clock-5.52 {time zone boundary case 1975-01-01 00:00:00} detroit {
+ clock format 157784400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {00:00:00 -0500 EST}
+test clock-5.53 {time zone boundary case 1975-01-01 00:00:01} detroit {
+ clock format 157784401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {00:00:01 -0500 EST}
+test clock-5.54 {time zone boundary case 1975-04-27 01:59:59} detroit {
+ clock format 167813999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.55 {time zone boundary case 1975-04-27 03:00:00} detroit {
+ clock format 167814000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.56 {time zone boundary case 1975-04-27 03:00:01} detroit {
+ clock format 167814001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.57 {time zone boundary case 1975-10-26 01:59:59} detroit {
+ clock format 183535199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.58 {time zone boundary case 1975-10-26 01:00:00} detroit {
+ clock format 183535200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.59 {time zone boundary case 1975-10-26 01:00:01} detroit {
+ clock format 183535201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.60 {time zone boundary case 1976-04-25 01:59:59} detroit {
+ clock format 199263599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.61 {time zone boundary case 1976-04-25 03:00:00} detroit {
+ clock format 199263600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.62 {time zone boundary case 1976-04-25 03:00:01} detroit {
+ clock format 199263601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.63 {time zone boundary case 1976-10-31 01:59:59} detroit {
+ clock format 215589599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.64 {time zone boundary case 1976-10-31 01:00:00} detroit {
+ clock format 215589600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.65 {time zone boundary case 1976-10-31 01:00:01} detroit {
+ clock format 215589601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.66 {time zone boundary case 1977-04-24 01:59:59} detroit {
+ clock format 230713199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.67 {time zone boundary case 1977-04-24 03:00:00} detroit {
+ clock format 230713200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.68 {time zone boundary case 1977-04-24 03:00:01} detroit {
+ clock format 230713201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.69 {time zone boundary case 1977-10-30 01:59:59} detroit {
+ clock format 247039199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.70 {time zone boundary case 1977-10-30 01:00:00} detroit {
+ clock format 247039200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.71 {time zone boundary case 1977-10-30 01:00:01} detroit {
+ clock format 247039201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.72 {time zone boundary case 1978-04-30 01:59:59} detroit {
+ clock format 262767599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.73 {time zone boundary case 1978-04-30 03:00:00} detroit {
+ clock format 262767600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.74 {time zone boundary case 1978-04-30 03:00:01} detroit {
+ clock format 262767601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.75 {time zone boundary case 1978-10-29 01:59:59} detroit {
+ clock format 278488799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.76 {time zone boundary case 1978-10-29 01:00:00} detroit {
+ clock format 278488800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.77 {time zone boundary case 1978-10-29 01:00:01} detroit {
+ clock format 278488801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.78 {time zone boundary case 1979-04-29 01:59:59} detroit {
+ clock format 294217199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.79 {time zone boundary case 1979-04-29 03:00:00} detroit {
+ clock format 294217200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.80 {time zone boundary case 1979-04-29 03:00:01} detroit {
+ clock format 294217201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.81 {time zone boundary case 1979-10-28 01:59:59} detroit {
+ clock format 309938399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.82 {time zone boundary case 1979-10-28 01:00:00} detroit {
+ clock format 309938400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.83 {time zone boundary case 1979-10-28 01:00:01} detroit {
+ clock format 309938401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.84 {time zone boundary case 1980-04-27 01:59:59} detroit {
+ clock format 325666799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.85 {time zone boundary case 1980-04-27 03:00:00} detroit {
+ clock format 325666800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.86 {time zone boundary case 1980-04-27 03:00:01} detroit {
+ clock format 325666801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.87 {time zone boundary case 1980-10-26 01:59:59} detroit {
+ clock format 341387999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.88 {time zone boundary case 1980-10-26 01:00:00} detroit {
+ clock format 341388000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.89 {time zone boundary case 1980-10-26 01:00:01} detroit {
+ clock format 341388001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.90 {time zone boundary case 1981-04-26 01:59:59} detroit {
+ clock format 357116399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.91 {time zone boundary case 1981-04-26 03:00:00} detroit {
+ clock format 357116400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.92 {time zone boundary case 1981-04-26 03:00:01} detroit {
+ clock format 357116401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.93 {time zone boundary case 1981-10-25 01:59:59} detroit {
+ clock format 372837599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.94 {time zone boundary case 1981-10-25 01:00:00} detroit {
+ clock format 372837600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.95 {time zone boundary case 1981-10-25 01:00:01} detroit {
+ clock format 372837601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.96 {time zone boundary case 1982-04-25 01:59:59} detroit {
+ clock format 388565999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.97 {time zone boundary case 1982-04-25 03:00:00} detroit {
+ clock format 388566000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.98 {time zone boundary case 1982-04-25 03:00:01} detroit {
+ clock format 388566001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.99 {time zone boundary case 1982-10-31 01:59:59} detroit {
+ clock format 404891999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.100 {time zone boundary case 1982-10-31 01:00:00} detroit {
+ clock format 404892000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.101 {time zone boundary case 1982-10-31 01:00:01} detroit {
+ clock format 404892001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.102 {time zone boundary case 1983-04-24 01:59:59} detroit {
+ clock format 420015599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.103 {time zone boundary case 1983-04-24 03:00:00} detroit {
+ clock format 420015600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.104 {time zone boundary case 1983-04-24 03:00:01} detroit {
+ clock format 420015601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.105 {time zone boundary case 1983-10-30 01:59:59} detroit {
+ clock format 436341599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.106 {time zone boundary case 1983-10-30 01:00:00} detroit {
+ clock format 436341600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.107 {time zone boundary case 1983-10-30 01:00:01} detroit {
+ clock format 436341601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.108 {time zone boundary case 1984-04-29 01:59:59} detroit {
+ clock format 452069999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.109 {time zone boundary case 1984-04-29 03:00:00} detroit {
+ clock format 452070000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.110 {time zone boundary case 1984-04-29 03:00:01} detroit {
+ clock format 452070001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.111 {time zone boundary case 1984-10-28 01:59:59} detroit {
+ clock format 467791199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.112 {time zone boundary case 1984-10-28 01:00:00} detroit {
+ clock format 467791200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.113 {time zone boundary case 1984-10-28 01:00:01} detroit {
+ clock format 467791201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.114 {time zone boundary case 1985-04-28 01:59:59} detroit {
+ clock format 483519599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.115 {time zone boundary case 1985-04-28 03:00:00} detroit {
+ clock format 483519600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.116 {time zone boundary case 1985-04-28 03:00:01} detroit {
+ clock format 483519601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.117 {time zone boundary case 1985-10-27 01:59:59} detroit {
+ clock format 499240799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.118 {time zone boundary case 1985-10-27 01:00:00} detroit {
+ clock format 499240800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.119 {time zone boundary case 1985-10-27 01:00:01} detroit {
+ clock format 499240801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.120 {time zone boundary case 1986-04-27 01:59:59} detroit {
+ clock format 514969199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.121 {time zone boundary case 1986-04-27 03:00:00} detroit {
+ clock format 514969200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.122 {time zone boundary case 1986-04-27 03:00:01} detroit {
+ clock format 514969201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.123 {time zone boundary case 1986-10-26 01:59:59} detroit {
+ clock format 530690399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.124 {time zone boundary case 1986-10-26 01:00:00} detroit {
+ clock format 530690400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.125 {time zone boundary case 1986-10-26 01:00:01} detroit {
+ clock format 530690401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.126 {time zone boundary case 1987-04-05 01:59:59} detroit {
+ clock format 544604399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.127 {time zone boundary case 1987-04-05 03:00:00} detroit {
+ clock format 544604400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.128 {time zone boundary case 1987-04-05 03:00:01} detroit {
+ clock format 544604401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.129 {time zone boundary case 1987-10-25 01:59:59} detroit {
+ clock format 562139999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.130 {time zone boundary case 1987-10-25 01:00:00} detroit {
+ clock format 562140000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.131 {time zone boundary case 1987-10-25 01:00:01} detroit {
+ clock format 562140001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.132 {time zone boundary case 1988-04-03 01:59:59} detroit {
+ clock format 576053999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.133 {time zone boundary case 1988-04-03 03:00:00} detroit {
+ clock format 576054000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.134 {time zone boundary case 1988-04-03 03:00:01} detroit {
+ clock format 576054001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.135 {time zone boundary case 1988-10-30 01:59:59} detroit {
+ clock format 594194399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.136 {time zone boundary case 1988-10-30 01:00:00} detroit {
+ clock format 594194400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.137 {time zone boundary case 1988-10-30 01:00:01} detroit {
+ clock format 594194401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.138 {time zone boundary case 1989-04-02 01:59:59} detroit {
+ clock format 607503599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.139 {time zone boundary case 1989-04-02 03:00:00} detroit {
+ clock format 607503600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.140 {time zone boundary case 1989-04-02 03:00:01} detroit {
+ clock format 607503601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.141 {time zone boundary case 1989-10-29 01:59:59} detroit {
+ clock format 625643999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.142 {time zone boundary case 1989-10-29 01:00:00} detroit {
+ clock format 625644000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.143 {time zone boundary case 1989-10-29 01:00:01} detroit {
+ clock format 625644001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.144 {time zone boundary case 1990-04-01 01:59:59} detroit {
+ clock format 638953199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.145 {time zone boundary case 1990-04-01 03:00:00} detroit {
+ clock format 638953200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.146 {time zone boundary case 1990-04-01 03:00:01} detroit {
+ clock format 638953201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.147 {time zone boundary case 1990-10-28 01:59:59} detroit {
+ clock format 657093599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.148 {time zone boundary case 1990-10-28 01:00:00} detroit {
+ clock format 657093600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.149 {time zone boundary case 1990-10-28 01:00:01} detroit {
+ clock format 657093601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.150 {time zone boundary case 1991-04-07 01:59:59} detroit {
+ clock format 671007599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.151 {time zone boundary case 1991-04-07 03:00:00} detroit {
+ clock format 671007600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.152 {time zone boundary case 1991-04-07 03:00:01} detroit {
+ clock format 671007601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.153 {time zone boundary case 1991-10-27 01:59:59} detroit {
+ clock format 688543199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.154 {time zone boundary case 1991-10-27 01:00:00} detroit {
+ clock format 688543200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.155 {time zone boundary case 1991-10-27 01:00:01} detroit {
+ clock format 688543201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.156 {time zone boundary case 1992-04-05 01:59:59} detroit {
+ clock format 702457199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.157 {time zone boundary case 1992-04-05 03:00:00} detroit {
+ clock format 702457200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.158 {time zone boundary case 1992-04-05 03:00:01} detroit {
+ clock format 702457201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.159 {time zone boundary case 1992-10-25 01:59:59} detroit {
+ clock format 719992799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.160 {time zone boundary case 1992-10-25 01:00:00} detroit {
+ clock format 719992800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.161 {time zone boundary case 1992-10-25 01:00:01} detroit {
+ clock format 719992801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.162 {time zone boundary case 1993-04-04 01:59:59} detroit {
+ clock format 733906799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.163 {time zone boundary case 1993-04-04 03:00:00} detroit {
+ clock format 733906800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.164 {time zone boundary case 1993-04-04 03:00:01} detroit {
+ clock format 733906801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.165 {time zone boundary case 1993-10-31 01:59:59} detroit {
+ clock format 752047199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.166 {time zone boundary case 1993-10-31 01:00:00} detroit {
+ clock format 752047200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.167 {time zone boundary case 1993-10-31 01:00:01} detroit {
+ clock format 752047201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.168 {time zone boundary case 1994-04-03 01:59:59} detroit {
+ clock format 765356399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.169 {time zone boundary case 1994-04-03 03:00:00} detroit {
+ clock format 765356400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.170 {time zone boundary case 1994-04-03 03:00:01} detroit {
+ clock format 765356401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.171 {time zone boundary case 1994-10-30 01:59:59} detroit {
+ clock format 783496799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.172 {time zone boundary case 1994-10-30 01:00:00} detroit {
+ clock format 783496800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.173 {time zone boundary case 1994-10-30 01:00:01} detroit {
+ clock format 783496801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.174 {time zone boundary case 1995-04-02 01:59:59} detroit {
+ clock format 796805999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.175 {time zone boundary case 1995-04-02 03:00:00} detroit {
+ clock format 796806000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.176 {time zone boundary case 1995-04-02 03:00:01} detroit {
+ clock format 796806001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.177 {time zone boundary case 1995-10-29 01:59:59} detroit {
+ clock format 814946399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.178 {time zone boundary case 1995-10-29 01:00:00} detroit {
+ clock format 814946400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.179 {time zone boundary case 1995-10-29 01:00:01} detroit {
+ clock format 814946401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.180 {time zone boundary case 1996-04-07 01:59:59} detroit {
+ clock format 828860399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.181 {time zone boundary case 1996-04-07 03:00:00} detroit {
+ clock format 828860400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.182 {time zone boundary case 1996-04-07 03:00:01} detroit {
+ clock format 828860401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.183 {time zone boundary case 1996-10-27 01:59:59} detroit {
+ clock format 846395999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.184 {time zone boundary case 1996-10-27 01:00:00} detroit {
+ clock format 846396000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.185 {time zone boundary case 1996-10-27 01:00:01} detroit {
+ clock format 846396001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.186 {time zone boundary case 1997-04-06 01:59:59} detroit {
+ clock format 860309999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.187 {time zone boundary case 1997-04-06 03:00:00} detroit {
+ clock format 860310000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.188 {time zone boundary case 1997-04-06 03:00:01} detroit {
+ clock format 860310001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.189 {time zone boundary case 1997-10-26 01:59:59} detroit {
+ clock format 877845599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.190 {time zone boundary case 1997-10-26 01:00:00} detroit {
+ clock format 877845600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.191 {time zone boundary case 1997-10-26 01:00:01} detroit {
+ clock format 877845601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.192 {time zone boundary case 1998-04-05 01:59:59} detroit {
+ clock format 891759599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.193 {time zone boundary case 1998-04-05 03:00:00} detroit {
+ clock format 891759600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.194 {time zone boundary case 1998-04-05 03:00:01} detroit {
+ clock format 891759601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.195 {time zone boundary case 1998-10-25 01:59:59} detroit {
+ clock format 909295199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.196 {time zone boundary case 1998-10-25 01:00:00} detroit {
+ clock format 909295200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.197 {time zone boundary case 1998-10-25 01:00:01} detroit {
+ clock format 909295201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.198 {time zone boundary case 1999-04-04 01:59:59} detroit {
+ clock format 923209199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.199 {time zone boundary case 1999-04-04 03:00:00} detroit {
+ clock format 923209200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.200 {time zone boundary case 1999-04-04 03:00:01} detroit {
+ clock format 923209201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.201 {time zone boundary case 1999-10-31 01:59:59} detroit {
+ clock format 941349599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.202 {time zone boundary case 1999-10-31 01:00:00} detroit {
+ clock format 941349600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.203 {time zone boundary case 1999-10-31 01:00:01} detroit {
+ clock format 941349601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.204 {time zone boundary case 2000-04-02 01:59:59} detroit {
+ clock format 954658799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.205 {time zone boundary case 2000-04-02 03:00:00} detroit {
+ clock format 954658800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.206 {time zone boundary case 2000-04-02 03:00:01} detroit {
+ clock format 954658801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.207 {time zone boundary case 2000-10-29 01:59:59} detroit {
+ clock format 972799199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.208 {time zone boundary case 2000-10-29 01:00:00} detroit {
+ clock format 972799200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.209 {time zone boundary case 2000-10-29 01:00:01} detroit {
+ clock format 972799201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.210 {time zone boundary case 2001-04-01 01:59:59} detroit {
+ clock format 986108399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.211 {time zone boundary case 2001-04-01 03:00:00} detroit {
+ clock format 986108400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.212 {time zone boundary case 2001-04-01 03:00:01} detroit {
+ clock format 986108401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.213 {time zone boundary case 2001-10-28 01:59:59} detroit {
+ clock format 1004248799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.214 {time zone boundary case 2001-10-28 01:00:00} detroit {
+ clock format 1004248800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.215 {time zone boundary case 2001-10-28 01:00:01} detroit {
+ clock format 1004248801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.216 {time zone boundary case 2002-04-07 01:59:59} detroit {
+ clock format 1018162799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.217 {time zone boundary case 2002-04-07 03:00:00} detroit {
+ clock format 1018162800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.218 {time zone boundary case 2002-04-07 03:00:01} detroit {
+ clock format 1018162801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.219 {time zone boundary case 2002-10-27 01:59:59} detroit {
+ clock format 1035698399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.220 {time zone boundary case 2002-10-27 01:00:00} detroit {
+ clock format 1035698400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.221 {time zone boundary case 2002-10-27 01:00:01} detroit {
+ clock format 1035698401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.222 {time zone boundary case 2003-04-06 01:59:59} detroit {
+ clock format 1049612399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.223 {time zone boundary case 2003-04-06 03:00:00} detroit {
+ clock format 1049612400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.224 {time zone boundary case 2003-04-06 03:00:01} detroit {
+ clock format 1049612401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.225 {time zone boundary case 2003-10-26 01:59:59} detroit {
+ clock format 1067147999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.226 {time zone boundary case 2003-10-26 01:00:00} detroit {
+ clock format 1067148000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.227 {time zone boundary case 2003-10-26 01:00:01} detroit {
+ clock format 1067148001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.228 {time zone boundary case 2004-04-04 01:59:59} detroit {
+ clock format 1081061999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.229 {time zone boundary case 2004-04-04 03:00:00} detroit {
+ clock format 1081062000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.230 {time zone boundary case 2004-04-04 03:00:01} detroit {
+ clock format 1081062001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.231 {time zone boundary case 2004-10-31 01:59:59} detroit {
+ clock format 1099202399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.232 {time zone boundary case 2004-10-31 01:00:00} detroit {
+ clock format 1099202400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.233 {time zone boundary case 2004-10-31 01:00:01} detroit {
+ clock format 1099202401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.234 {time zone boundary case 2005-04-03 01:59:59} detroit {
+ clock format 1112511599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.235 {time zone boundary case 2005-04-03 03:00:00} detroit {
+ clock format 1112511600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.236 {time zone boundary case 2005-04-03 03:00:01} detroit {
+ clock format 1112511601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.237 {time zone boundary case 2005-10-30 01:59:59} detroit {
+ clock format 1130651999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.238 {time zone boundary case 2005-10-30 01:00:00} detroit {
+ clock format 1130652000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.239 {time zone boundary case 2005-10-30 01:00:01} detroit {
+ clock format 1130652001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.240 {time zone boundary case 2006-04-02 01:59:59} detroit {
+ clock format 1143961199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.241 {time zone boundary case 2006-04-02 03:00:00} detroit {
+ clock format 1143961200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.242 {time zone boundary case 2006-04-02 03:00:01} detroit {
+ clock format 1143961201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.243 {time zone boundary case 2006-10-29 01:59:59} detroit {
+ clock format 1162101599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.244 {time zone boundary case 2006-10-29 01:00:00} detroit {
+ clock format 1162101600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.245 {time zone boundary case 2006-10-29 01:00:01} detroit {
+ clock format 1162101601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.246 {time zone boundary case 2007-03-11 01:59:59} detroit {
+ clock format 1173596399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.247 {time zone boundary case 2007-03-11 03:00:00} detroit {
+ clock format 1173596400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.248 {time zone boundary case 2007-03-11 03:00:01} detroit {
+ clock format 1173596401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.249 {time zone boundary case 2007-11-04 01:59:59} detroit {
+ clock format 1194155999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.250 {time zone boundary case 2007-11-04 01:00:00} detroit {
+ clock format 1194156000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.251 {time zone boundary case 2007-11-04 01:00:01} detroit {
+ clock format 1194156001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.252 {time zone boundary case 2008-03-09 01:59:59} detroit {
+ clock format 1205045999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.253 {time zone boundary case 2008-03-09 03:00:00} detroit {
+ clock format 1205046000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.254 {time zone boundary case 2008-03-09 03:00:01} detroit {
+ clock format 1205046001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.255 {time zone boundary case 2008-11-02 01:59:59} detroit {
+ clock format 1225605599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.256 {time zone boundary case 2008-11-02 01:00:00} detroit {
+ clock format 1225605600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.257 {time zone boundary case 2008-11-02 01:00:01} detroit {
+ clock format 1225605601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.258 {time zone boundary case 2009-03-08 01:59:59} detroit {
+ clock format 1236495599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.259 {time zone boundary case 2009-03-08 03:00:00} detroit {
+ clock format 1236495600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.260 {time zone boundary case 2009-03-08 03:00:01} detroit {
+ clock format 1236495601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.261 {time zone boundary case 2009-11-01 01:59:59} detroit {
+ clock format 1257055199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.262 {time zone boundary case 2009-11-01 01:00:00} detroit {
+ clock format 1257055200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.263 {time zone boundary case 2009-11-01 01:00:01} detroit {
+ clock format 1257055201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.264 {time zone boundary case 2010-03-14 01:59:59} detroit {
+ clock format 1268549999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.265 {time zone boundary case 2010-03-14 03:00:00} detroit {
+ clock format 1268550000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.266 {time zone boundary case 2010-03-14 03:00:01} detroit {
+ clock format 1268550001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.267 {time zone boundary case 2010-11-07 01:59:59} detroit {
+ clock format 1289109599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.268 {time zone boundary case 2010-11-07 01:00:00} detroit {
+ clock format 1289109600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.269 {time zone boundary case 2010-11-07 01:00:01} detroit {
+ clock format 1289109601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.270 {time zone boundary case 2011-03-13 01:59:59} detroit {
+ clock format 1299999599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.271 {time zone boundary case 2011-03-13 03:00:00} detroit {
+ clock format 1299999600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.272 {time zone boundary case 2011-03-13 03:00:01} detroit {
+ clock format 1299999601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.273 {time zone boundary case 2011-11-06 01:59:59} detroit {
+ clock format 1320559199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.274 {time zone boundary case 2011-11-06 01:00:00} detroit {
+ clock format 1320559200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.275 {time zone boundary case 2011-11-06 01:00:01} detroit {
+ clock format 1320559201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.276 {time zone boundary case 2012-03-11 01:59:59} detroit {
+ clock format 1331449199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.277 {time zone boundary case 2012-03-11 03:00:00} detroit {
+ clock format 1331449200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.278 {time zone boundary case 2012-03-11 03:00:01} detroit {
+ clock format 1331449201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.279 {time zone boundary case 2012-11-04 01:59:59} detroit {
+ clock format 1352008799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.280 {time zone boundary case 2012-11-04 01:00:00} detroit {
+ clock format 1352008800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.281 {time zone boundary case 2012-11-04 01:00:01} detroit {
+ clock format 1352008801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.282 {time zone boundary case 2013-03-10 01:59:59} detroit {
+ clock format 1362898799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.283 {time zone boundary case 2013-03-10 03:00:00} detroit {
+ clock format 1362898800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.284 {time zone boundary case 2013-03-10 03:00:01} detroit {
+ clock format 1362898801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.285 {time zone boundary case 2013-11-03 01:59:59} detroit {
+ clock format 1383458399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.286 {time zone boundary case 2013-11-03 01:00:00} detroit {
+ clock format 1383458400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.287 {time zone boundary case 2013-11-03 01:00:01} detroit {
+ clock format 1383458401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.288 {time zone boundary case 2014-03-09 01:59:59} detroit {
+ clock format 1394348399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.289 {time zone boundary case 2014-03-09 03:00:00} detroit {
+ clock format 1394348400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.290 {time zone boundary case 2014-03-09 03:00:01} detroit {
+ clock format 1394348401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.291 {time zone boundary case 2014-11-02 01:59:59} detroit {
+ clock format 1414907999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.292 {time zone boundary case 2014-11-02 01:00:00} detroit {
+ clock format 1414908000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.293 {time zone boundary case 2014-11-02 01:00:01} detroit {
+ clock format 1414908001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.294 {time zone boundary case 2015-03-08 01:59:59} detroit {
+ clock format 1425797999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.295 {time zone boundary case 2015-03-08 03:00:00} detroit {
+ clock format 1425798000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.296 {time zone boundary case 2015-03-08 03:00:01} detroit {
+ clock format 1425798001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.297 {time zone boundary case 2015-11-01 01:59:59} detroit {
+ clock format 1446357599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.298 {time zone boundary case 2015-11-01 01:00:00} detroit {
+ clock format 1446357600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.299 {time zone boundary case 2015-11-01 01:00:01} detroit {
+ clock format 1446357601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.300 {time zone boundary case 2016-03-13 01:59:59} detroit {
+ clock format 1457852399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.301 {time zone boundary case 2016-03-13 03:00:00} detroit {
+ clock format 1457852400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.302 {time zone boundary case 2016-03-13 03:00:01} detroit {
+ clock format 1457852401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.303 {time zone boundary case 2016-11-06 01:59:59} detroit {
+ clock format 1478411999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.304 {time zone boundary case 2016-11-06 01:00:00} detroit {
+ clock format 1478412000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.305 {time zone boundary case 2016-11-06 01:00:01} detroit {
+ clock format 1478412001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.306 {time zone boundary case 2017-03-12 01:59:59} detroit {
+ clock format 1489301999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.307 {time zone boundary case 2017-03-12 03:00:00} detroit {
+ clock format 1489302000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.308 {time zone boundary case 2017-03-12 03:00:01} detroit {
+ clock format 1489302001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.309 {time zone boundary case 2017-11-05 01:59:59} detroit {
+ clock format 1509861599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.310 {time zone boundary case 2017-11-05 01:00:00} detroit {
+ clock format 1509861600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.311 {time zone boundary case 2017-11-05 01:00:01} detroit {
+ clock format 1509861601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.312 {time zone boundary case 2018-03-11 01:59:59} detroit {
+ clock format 1520751599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.313 {time zone boundary case 2018-03-11 03:00:00} detroit {
+ clock format 1520751600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.314 {time zone boundary case 2018-03-11 03:00:01} detroit {
+ clock format 1520751601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.315 {time zone boundary case 2018-11-04 01:59:59} detroit {
+ clock format 1541311199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.316 {time zone boundary case 2018-11-04 01:00:00} detroit {
+ clock format 1541311200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.317 {time zone boundary case 2018-11-04 01:00:01} detroit {
+ clock format 1541311201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.318 {time zone boundary case 2019-03-10 01:59:59} detroit {
+ clock format 1552201199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.319 {time zone boundary case 2019-03-10 03:00:00} detroit {
+ clock format 1552201200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.320 {time zone boundary case 2019-03-10 03:00:01} detroit {
+ clock format 1552201201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.321 {time zone boundary case 2019-11-03 01:59:59} detroit {
+ clock format 1572760799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.322 {time zone boundary case 2019-11-03 01:00:00} detroit {
+ clock format 1572760800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.323 {time zone boundary case 2019-11-03 01:00:01} detroit {
+ clock format 1572760801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.324 {time zone boundary case 2020-03-08 01:59:59} detroit {
+ clock format 1583650799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.325 {time zone boundary case 2020-03-08 03:00:00} detroit {
+ clock format 1583650800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.326 {time zone boundary case 2020-03-08 03:00:01} detroit {
+ clock format 1583650801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.327 {time zone boundary case 2020-11-01 01:59:59} detroit {
+ clock format 1604210399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.328 {time zone boundary case 2020-11-01 01:00:00} detroit {
+ clock format 1604210400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.329 {time zone boundary case 2020-11-01 01:00:01} detroit {
+ clock format 1604210401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.330 {time zone boundary case 2021-03-14 01:59:59} detroit {
+ clock format 1615705199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.331 {time zone boundary case 2021-03-14 03:00:00} detroit {
+ clock format 1615705200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.332 {time zone boundary case 2021-03-14 03:00:01} detroit {
+ clock format 1615705201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.333 {time zone boundary case 2021-11-07 01:59:59} detroit {
+ clock format 1636264799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.334 {time zone boundary case 2021-11-07 01:00:00} detroit {
+ clock format 1636264800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.335 {time zone boundary case 2021-11-07 01:00:01} detroit {
+ clock format 1636264801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.336 {time zone boundary case 2022-03-13 01:59:59} detroit {
+ clock format 1647154799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.337 {time zone boundary case 2022-03-13 03:00:00} detroit {
+ clock format 1647154800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.338 {time zone boundary case 2022-03-13 03:00:01} detroit {
+ clock format 1647154801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.339 {time zone boundary case 2022-11-06 01:59:59} detroit {
+ clock format 1667714399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.340 {time zone boundary case 2022-11-06 01:00:00} detroit {
+ clock format 1667714400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.341 {time zone boundary case 2022-11-06 01:00:01} detroit {
+ clock format 1667714401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.342 {time zone boundary case 2023-03-12 01:59:59} detroit {
+ clock format 1678604399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.343 {time zone boundary case 2023-03-12 03:00:00} detroit {
+ clock format 1678604400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.344 {time zone boundary case 2023-03-12 03:00:01} detroit {
+ clock format 1678604401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.345 {time zone boundary case 2023-11-05 01:59:59} detroit {
+ clock format 1699163999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.346 {time zone boundary case 2023-11-05 01:00:00} detroit {
+ clock format 1699164000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.347 {time zone boundary case 2023-11-05 01:00:01} detroit {
+ clock format 1699164001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.348 {time zone boundary case 2024-03-10 01:59:59} detroit {
+ clock format 1710053999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.349 {time zone boundary case 2024-03-10 03:00:00} detroit {
+ clock format 1710054000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.350 {time zone boundary case 2024-03-10 03:00:01} detroit {
+ clock format 1710054001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.351 {time zone boundary case 2024-11-03 01:59:59} detroit {
+ clock format 1730613599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.352 {time zone boundary case 2024-11-03 01:00:00} detroit {
+ clock format 1730613600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.353 {time zone boundary case 2024-11-03 01:00:01} detroit {
+ clock format 1730613601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.354 {time zone boundary case 2025-03-09 01:59:59} detroit {
+ clock format 1741503599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.355 {time zone boundary case 2025-03-09 03:00:00} detroit {
+ clock format 1741503600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.356 {time zone boundary case 2025-03-09 03:00:01} detroit {
+ clock format 1741503601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.357 {time zone boundary case 2025-11-02 01:59:59} detroit {
+ clock format 1762063199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.358 {time zone boundary case 2025-11-02 01:00:00} detroit {
+ clock format 1762063200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.359 {time zone boundary case 2025-11-02 01:00:01} detroit {
+ clock format 1762063201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.360 {time zone boundary case 2026-03-08 01:59:59} detroit {
+ clock format 1772953199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.361 {time zone boundary case 2026-03-08 03:00:00} detroit {
+ clock format 1772953200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.362 {time zone boundary case 2026-03-08 03:00:01} detroit {
+ clock format 1772953201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.363 {time zone boundary case 2026-11-01 01:59:59} detroit {
+ clock format 1793512799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.364 {time zone boundary case 2026-11-01 01:00:00} detroit {
+ clock format 1793512800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.365 {time zone boundary case 2026-11-01 01:00:01} detroit {
+ clock format 1793512801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.366 {time zone boundary case 2027-03-14 01:59:59} detroit {
+ clock format 1805007599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.367 {time zone boundary case 2027-03-14 03:00:00} detroit {
+ clock format 1805007600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.368 {time zone boundary case 2027-03-14 03:00:01} detroit {
+ clock format 1805007601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.369 {time zone boundary case 2027-11-07 01:59:59} detroit {
+ clock format 1825567199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.370 {time zone boundary case 2027-11-07 01:00:00} detroit {
+ clock format 1825567200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.371 {time zone boundary case 2027-11-07 01:00:01} detroit {
+ clock format 1825567201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.372 {time zone boundary case 2028-03-12 01:59:59} detroit {
+ clock format 1836457199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.373 {time zone boundary case 2028-03-12 03:00:00} detroit {
+ clock format 1836457200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.374 {time zone boundary case 2028-03-12 03:00:01} detroit {
+ clock format 1836457201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.375 {time zone boundary case 2028-11-05 01:59:59} detroit {
+ clock format 1857016799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.376 {time zone boundary case 2028-11-05 01:00:00} detroit {
+ clock format 1857016800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.377 {time zone boundary case 2028-11-05 01:00:01} detroit {
+ clock format 1857016801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.378 {time zone boundary case 2029-03-11 01:59:59} detroit {
+ clock format 1867906799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.379 {time zone boundary case 2029-03-11 03:00:00} detroit {
+ clock format 1867906800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.380 {time zone boundary case 2029-03-11 03:00:01} detroit {
+ clock format 1867906801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.381 {time zone boundary case 2029-11-04 01:59:59} detroit {
+ clock format 1888466399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.382 {time zone boundary case 2029-11-04 01:00:00} detroit {
+ clock format 1888466400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.383 {time zone boundary case 2029-11-04 01:00:01} detroit {
+ clock format 1888466401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.384 {time zone boundary case 2030-03-10 01:59:59} detroit {
+ clock format 1899356399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.385 {time zone boundary case 2030-03-10 03:00:00} detroit {
+ clock format 1899356400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.386 {time zone boundary case 2030-03-10 03:00:01} detroit {
+ clock format 1899356401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.387 {time zone boundary case 2030-11-03 01:59:59} detroit {
+ clock format 1919915999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.388 {time zone boundary case 2030-11-03 01:00:00} detroit {
+ clock format 1919916000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.389 {time zone boundary case 2030-11-03 01:00:01} detroit {
+ clock format 1919916001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.390 {time zone boundary case 2031-03-09 01:59:59} detroit {
+ clock format 1930805999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.391 {time zone boundary case 2031-03-09 03:00:00} detroit {
+ clock format 1930806000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.392 {time zone boundary case 2031-03-09 03:00:01} detroit {
+ clock format 1930806001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.393 {time zone boundary case 2031-11-02 01:59:59} detroit {
+ clock format 1951365599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.394 {time zone boundary case 2031-11-02 01:00:00} detroit {
+ clock format 1951365600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.395 {time zone boundary case 2031-11-02 01:00:01} detroit {
+ clock format 1951365601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.396 {time zone boundary case 2032-03-14 01:59:59} detroit {
+ clock format 1962860399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.397 {time zone boundary case 2032-03-14 03:00:00} detroit {
+ clock format 1962860400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.398 {time zone boundary case 2032-03-14 03:00:01} detroit {
+ clock format 1962860401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.399 {time zone boundary case 2032-11-07 01:59:59} detroit {
+ clock format 1983419999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.400 {time zone boundary case 2032-11-07 01:00:00} detroit {
+ clock format 1983420000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.401 {time zone boundary case 2032-11-07 01:00:01} detroit {
+ clock format 1983420001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.402 {time zone boundary case 2033-03-13 01:59:59} detroit {
+ clock format 1994309999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.403 {time zone boundary case 2033-03-13 03:00:00} detroit {
+ clock format 1994310000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.404 {time zone boundary case 2033-03-13 03:00:01} detroit {
+ clock format 1994310001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.405 {time zone boundary case 2033-11-06 01:59:59} detroit {
+ clock format 2014869599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.406 {time zone boundary case 2033-11-06 01:00:00} detroit {
+ clock format 2014869600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.407 {time zone boundary case 2033-11-06 01:00:01} detroit {
+ clock format 2014869601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.408 {time zone boundary case 2034-03-12 01:59:59} detroit {
+ clock format 2025759599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.409 {time zone boundary case 2034-03-12 03:00:00} detroit {
+ clock format 2025759600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.410 {time zone boundary case 2034-03-12 03:00:01} detroit {
+ clock format 2025759601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.411 {time zone boundary case 2034-11-05 01:59:59} detroit {
+ clock format 2046319199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.412 {time zone boundary case 2034-11-05 01:00:00} detroit {
+ clock format 2046319200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.413 {time zone boundary case 2034-11-05 01:00:01} detroit {
+ clock format 2046319201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.414 {time zone boundary case 2035-03-11 01:59:59} detroit {
+ clock format 2057209199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.415 {time zone boundary case 2035-03-11 03:00:00} detroit {
+ clock format 2057209200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.416 {time zone boundary case 2035-03-11 03:00:01} detroit {
+ clock format 2057209201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.417 {time zone boundary case 2035-11-04 01:59:59} detroit {
+ clock format 2077768799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.418 {time zone boundary case 2035-11-04 01:00:00} detroit {
+ clock format 2077768800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.419 {time zone boundary case 2035-11-04 01:00:01} detroit {
+ clock format 2077768801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.420 {time zone boundary case 2036-03-09 01:59:59} detroit {
+ clock format 2088658799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.421 {time zone boundary case 2036-03-09 03:00:00} detroit {
+ clock format 2088658800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.422 {time zone boundary case 2036-03-09 03:00:01} detroit {
+ clock format 2088658801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.423 {time zone boundary case 2036-11-02 01:59:59} detroit {
+ clock format 2109218399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.424 {time zone boundary case 2036-11-02 01:00:00} detroit {
+ clock format 2109218400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.425 {time zone boundary case 2036-11-02 01:00:01} detroit {
+ clock format 2109218401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.426 {time zone boundary case 2037-03-08 01:59:59} detroit {
+ clock format 2120108399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.427 {time zone boundary case 2037-03-08 03:00:00} detroit {
+ clock format 2120108400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.428 {time zone boundary case 2037-03-08 03:00:01} detroit {
+ clock format 2120108401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.429 {time zone boundary case 2037-11-01 01:59:59} detroit {
+ clock format 2140667999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.430 {time zone boundary case 2037-11-01 01:00:00} detroit {
+ clock format 2140668000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.431 {time zone boundary case 2037-11-01 01:00:01} detroit {
+ clock format 2140668001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.432 {time zone boundary case 2038-03-14 01:59:59} {detroit y2038} {
+ clock format 2152162799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.433 {time zone boundary case 2038-03-14 03:00:00} {detroit y2038} {
+ clock format 2152162800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.434 {time zone boundary case 2038-03-14 03:00:01} {detroit y2038} {
+ clock format 2152162801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.435 {time zone boundary case 2038-11-07 01:59:59} {detroit y2038} {
+ clock format 2172722399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.436 {time zone boundary case 2038-11-07 01:00:00} {detroit y2038} {
+ clock format 2172722400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.437 {time zone boundary case 2038-11-07 01:00:01} {detroit y2038} {
+ clock format 2172722401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.438 {time zone boundary case 2039-03-13 01:59:59} {detroit y2038} {
+ clock format 2183612399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.439 {time zone boundary case 2039-03-13 03:00:00} {detroit y2038} {
+ clock format 2183612400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.440 {time zone boundary case 2039-03-13 03:00:01} {detroit y2038} {
+ clock format 2183612401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.441 {time zone boundary case 2039-11-06 01:59:59} {detroit y2038} {
+ clock format 2204171999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.442 {time zone boundary case 2039-11-06 01:00:00} {detroit y2038} {
+ clock format 2204172000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.443 {time zone boundary case 2039-11-06 01:00:01} {detroit y2038} {
+ clock format 2204172001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.444 {time zone boundary case 2040-03-11 01:59:59} {detroit y2038} {
+ clock format 2215061999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.445 {time zone boundary case 2040-03-11 03:00:00} {detroit y2038} {
+ clock format 2215062000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.446 {time zone boundary case 2040-03-11 03:00:01} {detroit y2038} {
+ clock format 2215062001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.447 {time zone boundary case 2040-11-04 01:59:59} {detroit y2038} {
+ clock format 2235621599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.448 {time zone boundary case 2040-11-04 01:00:00} {detroit y2038} {
+ clock format 2235621600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.449 {time zone boundary case 2040-11-04 01:00:01} {detroit y2038} {
+ clock format 2235621601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.450 {time zone boundary case 2041-03-10 01:59:59} {detroit y2038} {
+ clock format 2246511599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.451 {time zone boundary case 2041-03-10 03:00:00} {detroit y2038} {
+ clock format 2246511600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.452 {time zone boundary case 2041-03-10 03:00:01} {detroit y2038} {
+ clock format 2246511601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.453 {time zone boundary case 2041-11-03 01:59:59} {detroit y2038} {
+ clock format 2267071199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.454 {time zone boundary case 2041-11-03 01:00:00} {detroit y2038} {
+ clock format 2267071200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.455 {time zone boundary case 2041-11-03 01:00:01} {detroit y2038} {
+ clock format 2267071201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.456 {time zone boundary case 2042-03-09 01:59:59} {detroit y2038} {
+ clock format 2277961199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.457 {time zone boundary case 2042-03-09 03:00:00} {detroit y2038} {
+ clock format 2277961200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.458 {time zone boundary case 2042-03-09 03:00:01} {detroit y2038} {
+ clock format 2277961201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.459 {time zone boundary case 2042-11-02 01:59:59} {detroit y2038} {
+ clock format 2298520799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.460 {time zone boundary case 2042-11-02 01:00:00} {detroit y2038} {
+ clock format 2298520800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.461 {time zone boundary case 2042-11-02 01:00:01} {detroit y2038} {
+ clock format 2298520801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.462 {time zone boundary case 2043-03-08 01:59:59} {detroit y2038} {
+ clock format 2309410799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.463 {time zone boundary case 2043-03-08 03:00:00} {detroit y2038} {
+ clock format 2309410800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.464 {time zone boundary case 2043-03-08 03:00:01} {detroit y2038} {
+ clock format 2309410801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.465 {time zone boundary case 2043-11-01 01:59:59} {detroit y2038} {
+ clock format 2329970399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.466 {time zone boundary case 2043-11-01 01:00:00} {detroit y2038} {
+ clock format 2329970400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.467 {time zone boundary case 2043-11-01 01:00:01} {detroit y2038} {
+ clock format 2329970401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.468 {time zone boundary case 2044-03-13 01:59:59} {detroit y2038} {
+ clock format 2341465199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.469 {time zone boundary case 2044-03-13 03:00:00} {detroit y2038} {
+ clock format 2341465200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.470 {time zone boundary case 2044-03-13 03:00:01} {detroit y2038} {
+ clock format 2341465201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.471 {time zone boundary case 2044-11-06 01:59:59} {detroit y2038} {
+ clock format 2362024799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.472 {time zone boundary case 2044-11-06 01:00:00} {detroit y2038} {
+ clock format 2362024800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.473 {time zone boundary case 2044-11-06 01:00:01} {detroit y2038} {
+ clock format 2362024801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.474 {time zone boundary case 2045-03-12 01:59:59} {detroit y2038} {
+ clock format 2372914799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.475 {time zone boundary case 2045-03-12 03:00:00} {detroit y2038} {
+ clock format 2372914800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.476 {time zone boundary case 2045-03-12 03:00:01} {detroit y2038} {
+ clock format 2372914801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.477 {time zone boundary case 2045-11-05 01:59:59} {detroit y2038} {
+ clock format 2393474399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.478 {time zone boundary case 2045-11-05 01:00:00} {detroit y2038} {
+ clock format 2393474400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.479 {time zone boundary case 2045-11-05 01:00:01} {detroit y2038} {
+ clock format 2393474401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.480 {time zone boundary case 2046-03-11 01:59:59} {detroit y2038} {
+ clock format 2404364399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.481 {time zone boundary case 2046-03-11 03:00:00} {detroit y2038} {
+ clock format 2404364400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.482 {time zone boundary case 2046-03-11 03:00:01} {detroit y2038} {
+ clock format 2404364401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.483 {time zone boundary case 2046-11-04 01:59:59} {detroit y2038} {
+ clock format 2424923999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.484 {time zone boundary case 2046-11-04 01:00:00} {detroit y2038} {
+ clock format 2424924000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.485 {time zone boundary case 2046-11-04 01:00:01} {detroit y2038} {
+ clock format 2424924001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.486 {time zone boundary case 2047-03-10 01:59:59} {detroit y2038} {
+ clock format 2435813999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.487 {time zone boundary case 2047-03-10 03:00:00} {detroit y2038} {
+ clock format 2435814000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.488 {time zone boundary case 2047-03-10 03:00:01} {detroit y2038} {
+ clock format 2435814001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.489 {time zone boundary case 2047-11-03 01:59:59} {detroit y2038} {
+ clock format 2456373599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.490 {time zone boundary case 2047-11-03 01:00:00} {detroit y2038} {
+ clock format 2456373600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.491 {time zone boundary case 2047-11-03 01:00:01} {detroit y2038} {
+ clock format 2456373601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.492 {time zone boundary case 2048-03-08 01:59:59} {detroit y2038} {
+ clock format 2467263599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.493 {time zone boundary case 2048-03-08 03:00:00} {detroit y2038} {
+ clock format 2467263600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.494 {time zone boundary case 2048-03-08 03:00:01} {detroit y2038} {
+ clock format 2467263601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.495 {time zone boundary case 2048-11-01 01:59:59} {detroit y2038} {
+ clock format 2487823199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.496 {time zone boundary case 2048-11-01 01:00:00} {detroit y2038} {
+ clock format 2487823200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.497 {time zone boundary case 2048-11-01 01:00:01} {detroit y2038} {
+ clock format 2487823201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.498 {time zone boundary case 2049-03-14 01:59:59} {detroit y2038} {
+ clock format 2499317999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.499 {time zone boundary case 2049-03-14 03:00:00} {detroit y2038} {
+ clock format 2499318000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.500 {time zone boundary case 2049-03-14 03:00:01} {detroit y2038} {
+ clock format 2499318001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.501 {time zone boundary case 2049-11-07 01:59:59} {detroit y2038} {
+ clock format 2519877599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.502 {time zone boundary case 2049-11-07 01:00:00} {detroit y2038} {
+ clock format 2519877600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.503 {time zone boundary case 2049-11-07 01:00:01} {detroit y2038} {
+ clock format 2519877601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.504 {time zone boundary case 2050-03-13 01:59:59} {detroit y2038} {
+ clock format 2530767599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.505 {time zone boundary case 2050-03-13 03:00:00} {detroit y2038} {
+ clock format 2530767600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.506 {time zone boundary case 2050-03-13 03:00:01} {detroit y2038} {
+ clock format 2530767601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.507 {time zone boundary case 2050-11-06 01:59:59} {detroit y2038} {
+ clock format 2551327199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.508 {time zone boundary case 2050-11-06 01:00:00} {detroit y2038} {
+ clock format 2551327200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.509 {time zone boundary case 2050-11-06 01:00:01} {detroit y2038} {
+ clock format 2551327201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.510 {time zone boundary case 2051-03-12 01:59:59} {detroit y2038} {
+ clock format 2562217199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.511 {time zone boundary case 2051-03-12 03:00:00} {detroit y2038} {
+ clock format 2562217200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.512 {time zone boundary case 2051-03-12 03:00:01} {detroit y2038} {
+ clock format 2562217201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.513 {time zone boundary case 2051-11-05 01:59:59} {detroit y2038} {
+ clock format 2582776799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.514 {time zone boundary case 2051-11-05 01:00:00} {detroit y2038} {
+ clock format 2582776800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.515 {time zone boundary case 2051-11-05 01:00:01} {detroit y2038} {
+ clock format 2582776801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.516 {time zone boundary case 2052-03-10 01:59:59} {detroit y2038} {
+ clock format 2593666799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.517 {time zone boundary case 2052-03-10 03:00:00} {detroit y2038} {
+ clock format 2593666800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.518 {time zone boundary case 2052-03-10 03:00:01} {detroit y2038} {
+ clock format 2593666801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.519 {time zone boundary case 2052-11-03 01:59:59} {detroit y2038} {
+ clock format 2614226399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.520 {time zone boundary case 2052-11-03 01:00:00} {detroit y2038} {
+ clock format 2614226400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.521 {time zone boundary case 2052-11-03 01:00:01} {detroit y2038} {
+ clock format 2614226401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.522 {time zone boundary case 2053-03-09 01:59:59} {detroit y2038} {
+ clock format 2625116399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.523 {time zone boundary case 2053-03-09 03:00:00} {detroit y2038} {
+ clock format 2625116400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.524 {time zone boundary case 2053-03-09 03:00:01} {detroit y2038} {
+ clock format 2625116401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.525 {time zone boundary case 2053-11-02 01:59:59} {detroit y2038} {
+ clock format 2645675999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.526 {time zone boundary case 2053-11-02 01:00:00} {detroit y2038} {
+ clock format 2645676000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.527 {time zone boundary case 2053-11-02 01:00:01} {detroit y2038} {
+ clock format 2645676001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.528 {time zone boundary case 2054-03-08 01:59:59} {detroit y2038} {
+ clock format 2656565999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.529 {time zone boundary case 2054-03-08 03:00:00} {detroit y2038} {
+ clock format 2656566000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.530 {time zone boundary case 2054-03-08 03:00:01} {detroit y2038} {
+ clock format 2656566001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.531 {time zone boundary case 2054-11-01 01:59:59} {detroit y2038} {
+ clock format 2677125599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.532 {time zone boundary case 2054-11-01 01:00:00} {detroit y2038} {
+ clock format 2677125600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.533 {time zone boundary case 2054-11-01 01:00:01} {detroit y2038} {
+ clock format 2677125601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.534 {time zone boundary case 2055-03-14 01:59:59} {detroit y2038} {
+ clock format 2688620399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.535 {time zone boundary case 2055-03-14 03:00:00} {detroit y2038} {
+ clock format 2688620400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.536 {time zone boundary case 2055-03-14 03:00:01} {detroit y2038} {
+ clock format 2688620401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.537 {time zone boundary case 2055-11-07 01:59:59} {detroit y2038} {
+ clock format 2709179999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.538 {time zone boundary case 2055-11-07 01:00:00} {detroit y2038} {
+ clock format 2709180000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.539 {time zone boundary case 2055-11-07 01:00:01} {detroit y2038} {
+ clock format 2709180001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.540 {time zone boundary case 2056-03-12 01:59:59} {detroit y2038} {
+ clock format 2720069999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.541 {time zone boundary case 2056-03-12 03:00:00} {detroit y2038} {
+ clock format 2720070000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.542 {time zone boundary case 2056-03-12 03:00:01} {detroit y2038} {
+ clock format 2720070001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.543 {time zone boundary case 2056-11-05 01:59:59} {detroit y2038} {
+ clock format 2740629599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.544 {time zone boundary case 2056-11-05 01:00:00} {detroit y2038} {
+ clock format 2740629600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.545 {time zone boundary case 2056-11-05 01:00:01} {detroit y2038} {
+ clock format 2740629601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.546 {time zone boundary case 2057-03-11 01:59:59} {detroit y2038} {
+ clock format 2751519599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.547 {time zone boundary case 2057-03-11 03:00:00} {detroit y2038} {
+ clock format 2751519600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.548 {time zone boundary case 2057-03-11 03:00:01} {detroit y2038} {
+ clock format 2751519601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.549 {time zone boundary case 2057-11-04 01:59:59} {detroit y2038} {
+ clock format 2772079199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.550 {time zone boundary case 2057-11-04 01:00:00} {detroit y2038} {
+ clock format 2772079200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.551 {time zone boundary case 2057-11-04 01:00:01} {detroit y2038} {
+ clock format 2772079201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.552 {time zone boundary case 2058-03-10 01:59:59} {detroit y2038} {
+ clock format 2782969199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.553 {time zone boundary case 2058-03-10 03:00:00} {detroit y2038} {
+ clock format 2782969200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.554 {time zone boundary case 2058-03-10 03:00:01} {detroit y2038} {
+ clock format 2782969201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.555 {time zone boundary case 2058-11-03 01:59:59} {detroit y2038} {
+ clock format 2803528799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.556 {time zone boundary case 2058-11-03 01:00:00} {detroit y2038} {
+ clock format 2803528800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.557 {time zone boundary case 2058-11-03 01:00:01} {detroit y2038} {
+ clock format 2803528801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.558 {time zone boundary case 2059-03-09 01:59:59} {detroit y2038} {
+ clock format 2814418799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.559 {time zone boundary case 2059-03-09 03:00:00} {detroit y2038} {
+ clock format 2814418800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.560 {time zone boundary case 2059-03-09 03:00:01} {detroit y2038} {
+ clock format 2814418801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.561 {time zone boundary case 2059-11-02 01:59:59} {detroit y2038} {
+ clock format 2834978399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.562 {time zone boundary case 2059-11-02 01:00:00} {detroit y2038} {
+ clock format 2834978400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.563 {time zone boundary case 2059-11-02 01:00:01} {detroit y2038} {
+ clock format 2834978401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.564 {time zone boundary case 2060-03-14 01:59:59} {detroit y2038} {
+ clock format 2846473199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.565 {time zone boundary case 2060-03-14 03:00:00} {detroit y2038} {
+ clock format 2846473200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.566 {time zone boundary case 2060-03-14 03:00:01} {detroit y2038} {
+ clock format 2846473201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.567 {time zone boundary case 2060-11-07 01:59:59} {detroit y2038} {
+ clock format 2867032799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.568 {time zone boundary case 2060-11-07 01:00:00} {detroit y2038} {
+ clock format 2867032800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.569 {time zone boundary case 2060-11-07 01:00:01} {detroit y2038} {
+ clock format 2867032801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.570 {time zone boundary case 2061-03-13 01:59:59} {detroit y2038} {
+ clock format 2877922799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.571 {time zone boundary case 2061-03-13 03:00:00} {detroit y2038} {
+ clock format 2877922800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.572 {time zone boundary case 2061-03-13 03:00:01} {detroit y2038} {
+ clock format 2877922801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.573 {time zone boundary case 2061-11-06 01:59:59} {detroit y2038} {
+ clock format 2898482399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.574 {time zone boundary case 2061-11-06 01:00:00} {detroit y2038} {
+ clock format 2898482400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.575 {time zone boundary case 2061-11-06 01:00:01} {detroit y2038} {
+ clock format 2898482401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.576 {time zone boundary case 2062-03-12 01:59:59} {detroit y2038} {
+ clock format 2909372399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.577 {time zone boundary case 2062-03-12 03:00:00} {detroit y2038} {
+ clock format 2909372400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.578 {time zone boundary case 2062-03-12 03:00:01} {detroit y2038} {
+ clock format 2909372401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.579 {time zone boundary case 2062-11-05 01:59:59} {detroit y2038} {
+ clock format 2929931999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.580 {time zone boundary case 2062-11-05 01:00:00} {detroit y2038} {
+ clock format 2929932000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.581 {time zone boundary case 2062-11-05 01:00:01} {detroit y2038} {
+ clock format 2929932001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.582 {time zone boundary case 2063-03-11 01:59:59} {detroit y2038} {
+ clock format 2940821999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.583 {time zone boundary case 2063-03-11 03:00:00} {detroit y2038} {
+ clock format 2940822000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.584 {time zone boundary case 2063-03-11 03:00:01} {detroit y2038} {
+ clock format 2940822001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.585 {time zone boundary case 2063-11-04 01:59:59} {detroit y2038} {
+ clock format 2961381599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.586 {time zone boundary case 2063-11-04 01:00:00} {detroit y2038} {
+ clock format 2961381600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.587 {time zone boundary case 2063-11-04 01:00:01} {detroit y2038} {
+ clock format 2961381601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.588 {time zone boundary case 2064-03-09 01:59:59} {detroit y2038} {
+ clock format 2972271599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.589 {time zone boundary case 2064-03-09 03:00:00} {detroit y2038} {
+ clock format 2972271600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.590 {time zone boundary case 2064-03-09 03:00:01} {detroit y2038} {
+ clock format 2972271601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.591 {time zone boundary case 2064-11-02 01:59:59} {detroit y2038} {
+ clock format 2992831199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.592 {time zone boundary case 2064-11-02 01:00:00} {detroit y2038} {
+ clock format 2992831200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.593 {time zone boundary case 2064-11-02 01:00:01} {detroit y2038} {
+ clock format 2992831201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.594 {time zone boundary case 2065-03-08 01:59:59} {detroit y2038} {
+ clock format 3003721199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.595 {time zone boundary case 2065-03-08 03:00:00} {detroit y2038} {
+ clock format 3003721200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.596 {time zone boundary case 2065-03-08 03:00:01} {detroit y2038} {
+ clock format 3003721201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.597 {time zone boundary case 2065-11-01 01:59:59} {detroit y2038} {
+ clock format 3024280799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.598 {time zone boundary case 2065-11-01 01:00:00} {detroit y2038} {
+ clock format 3024280800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.599 {time zone boundary case 2065-11-01 01:00:01} {detroit y2038} {
+ clock format 3024280801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.600 {time zone boundary case 2066-03-14 01:59:59} {detroit y2038} {
+ clock format 3035775599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.601 {time zone boundary case 2066-03-14 03:00:00} {detroit y2038} {
+ clock format 3035775600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.602 {time zone boundary case 2066-03-14 03:00:01} {detroit y2038} {
+ clock format 3035775601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.603 {time zone boundary case 2066-11-07 01:59:59} {detroit y2038} {
+ clock format 3056335199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.604 {time zone boundary case 2066-11-07 01:00:00} {detroit y2038} {
+ clock format 3056335200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.605 {time zone boundary case 2066-11-07 01:00:01} {detroit y2038} {
+ clock format 3056335201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.606 {time zone boundary case 2067-03-13 01:59:59} {detroit y2038} {
+ clock format 3067225199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.607 {time zone boundary case 2067-03-13 03:00:00} {detroit y2038} {
+ clock format 3067225200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.608 {time zone boundary case 2067-03-13 03:00:01} {detroit y2038} {
+ clock format 3067225201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.609 {time zone boundary case 2067-11-06 01:59:59} {detroit y2038} {
+ clock format 3087784799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.610 {time zone boundary case 2067-11-06 01:00:00} {detroit y2038} {
+ clock format 3087784800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.611 {time zone boundary case 2067-11-06 01:00:01} {detroit y2038} {
+ clock format 3087784801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.612 {time zone boundary case 2068-03-11 01:59:59} {detroit y2038} {
+ clock format 3098674799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.613 {time zone boundary case 2068-03-11 03:00:00} {detroit y2038} {
+ clock format 3098674800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.614 {time zone boundary case 2068-03-11 03:00:01} {detroit y2038} {
+ clock format 3098674801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.615 {time zone boundary case 2068-11-04 01:59:59} {detroit y2038} {
+ clock format 3119234399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.616 {time zone boundary case 2068-11-04 01:00:00} {detroit y2038} {
+ clock format 3119234400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.617 {time zone boundary case 2068-11-04 01:00:01} {detroit y2038} {
+ clock format 3119234401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.618 {time zone boundary case 2069-03-10 01:59:59} {detroit y2038} {
+ clock format 3130124399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.619 {time zone boundary case 2069-03-10 03:00:00} {detroit y2038} {
+ clock format 3130124400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.620 {time zone boundary case 2069-03-10 03:00:01} {detroit y2038} {
+ clock format 3130124401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.621 {time zone boundary case 2069-11-03 01:59:59} {detroit y2038} {
+ clock format 3150683999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.622 {time zone boundary case 2069-11-03 01:00:00} {detroit y2038} {
+ clock format 3150684000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.623 {time zone boundary case 2069-11-03 01:00:01} {detroit y2038} {
+ clock format 3150684001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.624 {time zone boundary case 2070-03-09 01:59:59} {detroit y2038} {
+ clock format 3161573999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.625 {time zone boundary case 2070-03-09 03:00:00} {detroit y2038} {
+ clock format 3161574000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.626 {time zone boundary case 2070-03-09 03:00:01} {detroit y2038} {
+ clock format 3161574001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.627 {time zone boundary case 2070-11-02 01:59:59} {detroit y2038} {
+ clock format 3182133599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.628 {time zone boundary case 2070-11-02 01:00:00} {detroit y2038} {
+ clock format 3182133600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.629 {time zone boundary case 2070-11-02 01:00:01} {detroit y2038} {
+ clock format 3182133601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.630 {time zone boundary case 2071-03-08 01:59:59} {detroit y2038} {
+ clock format 3193023599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.631 {time zone boundary case 2071-03-08 03:00:00} {detroit y2038} {
+ clock format 3193023600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.632 {time zone boundary case 2071-03-08 03:00:01} {detroit y2038} {
+ clock format 3193023601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.633 {time zone boundary case 2071-11-01 01:59:59} {detroit y2038} {
+ clock format 3213583199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.634 {time zone boundary case 2071-11-01 01:00:00} {detroit y2038} {
+ clock format 3213583200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.635 {time zone boundary case 2071-11-01 01:00:01} {detroit y2038} {
+ clock format 3213583201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.636 {time zone boundary case 2072-03-13 01:59:59} {detroit y2038} {
+ clock format 3225077999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.637 {time zone boundary case 2072-03-13 03:00:00} {detroit y2038} {
+ clock format 3225078000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.638 {time zone boundary case 2072-03-13 03:00:01} {detroit y2038} {
+ clock format 3225078001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.639 {time zone boundary case 2072-11-06 01:59:59} {detroit y2038} {
+ clock format 3245637599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.640 {time zone boundary case 2072-11-06 01:00:00} {detroit y2038} {
+ clock format 3245637600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.641 {time zone boundary case 2072-11-06 01:00:01} {detroit y2038} {
+ clock format 3245637601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.642 {time zone boundary case 2073-03-12 01:59:59} {detroit y2038} {
+ clock format 3256527599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.643 {time zone boundary case 2073-03-12 03:00:00} {detroit y2038} {
+ clock format 3256527600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.644 {time zone boundary case 2073-03-12 03:00:01} {detroit y2038} {
+ clock format 3256527601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.645 {time zone boundary case 2073-11-05 01:59:59} {detroit y2038} {
+ clock format 3277087199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.646 {time zone boundary case 2073-11-05 01:00:00} {detroit y2038} {
+ clock format 3277087200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.647 {time zone boundary case 2073-11-05 01:00:01} {detroit y2038} {
+ clock format 3277087201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.648 {time zone boundary case 2074-03-11 01:59:59} {detroit y2038} {
+ clock format 3287977199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.649 {time zone boundary case 2074-03-11 03:00:00} {detroit y2038} {
+ clock format 3287977200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.650 {time zone boundary case 2074-03-11 03:00:01} {detroit y2038} {
+ clock format 3287977201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.651 {time zone boundary case 2074-11-04 01:59:59} {detroit y2038} {
+ clock format 3308536799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.652 {time zone boundary case 2074-11-04 01:00:00} {detroit y2038} {
+ clock format 3308536800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.653 {time zone boundary case 2074-11-04 01:00:01} {detroit y2038} {
+ clock format 3308536801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.654 {time zone boundary case 2075-03-10 01:59:59} {detroit y2038} {
+ clock format 3319426799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.655 {time zone boundary case 2075-03-10 03:00:00} {detroit y2038} {
+ clock format 3319426800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.656 {time zone boundary case 2075-03-10 03:00:01} {detroit y2038} {
+ clock format 3319426801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.657 {time zone boundary case 2075-11-03 01:59:59} {detroit y2038} {
+ clock format 3339986399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.658 {time zone boundary case 2075-11-03 01:00:00} {detroit y2038} {
+ clock format 3339986400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.659 {time zone boundary case 2075-11-03 01:00:01} {detroit y2038} {
+ clock format 3339986401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.660 {time zone boundary case 2076-03-08 01:59:59} {detroit y2038} {
+ clock format 3350876399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.661 {time zone boundary case 2076-03-08 03:00:00} {detroit y2038} {
+ clock format 3350876400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.662 {time zone boundary case 2076-03-08 03:00:01} {detroit y2038} {
+ clock format 3350876401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.663 {time zone boundary case 2076-11-01 01:59:59} {detroit y2038} {
+ clock format 3371435999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.664 {time zone boundary case 2076-11-01 01:00:00} {detroit y2038} {
+ clock format 3371436000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.665 {time zone boundary case 2076-11-01 01:00:01} {detroit y2038} {
+ clock format 3371436001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.666 {time zone boundary case 2077-03-14 01:59:59} {detroit y2038} {
+ clock format 3382930799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.667 {time zone boundary case 2077-03-14 03:00:00} {detroit y2038} {
+ clock format 3382930800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.668 {time zone boundary case 2077-03-14 03:00:01} {detroit y2038} {
+ clock format 3382930801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.669 {time zone boundary case 2077-11-07 01:59:59} {detroit y2038} {
+ clock format 3403490399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.670 {time zone boundary case 2077-11-07 01:00:00} {detroit y2038} {
+ clock format 3403490400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.671 {time zone boundary case 2077-11-07 01:00:01} {detroit y2038} {
+ clock format 3403490401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.672 {time zone boundary case 2078-03-13 01:59:59} {detroit y2038} {
+ clock format 3414380399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.673 {time zone boundary case 2078-03-13 03:00:00} {detroit y2038} {
+ clock format 3414380400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.674 {time zone boundary case 2078-03-13 03:00:01} {detroit y2038} {
+ clock format 3414380401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.675 {time zone boundary case 2078-11-06 01:59:59} {detroit y2038} {
+ clock format 3434939999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.676 {time zone boundary case 2078-11-06 01:00:00} {detroit y2038} {
+ clock format 3434940000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.677 {time zone boundary case 2078-11-06 01:00:01} {detroit y2038} {
+ clock format 3434940001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.678 {time zone boundary case 2079-03-12 01:59:59} {detroit y2038} {
+ clock format 3445829999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.679 {time zone boundary case 2079-03-12 03:00:00} {detroit y2038} {
+ clock format 3445830000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.680 {time zone boundary case 2079-03-12 03:00:01} {detroit y2038} {
+ clock format 3445830001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.681 {time zone boundary case 2079-11-05 01:59:59} {detroit y2038} {
+ clock format 3466389599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.682 {time zone boundary case 2079-11-05 01:00:00} {detroit y2038} {
+ clock format 3466389600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.683 {time zone boundary case 2079-11-05 01:00:01} {detroit y2038} {
+ clock format 3466389601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.684 {time zone boundary case 2080-03-10 01:59:59} {detroit y2038} {
+ clock format 3477279599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.685 {time zone boundary case 2080-03-10 03:00:00} {detroit y2038} {
+ clock format 3477279600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.686 {time zone boundary case 2080-03-10 03:00:01} {detroit y2038} {
+ clock format 3477279601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.687 {time zone boundary case 2080-11-03 01:59:59} {detroit y2038} {
+ clock format 3497839199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.688 {time zone boundary case 2080-11-03 01:00:00} {detroit y2038} {
+ clock format 3497839200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.689 {time zone boundary case 2080-11-03 01:00:01} {detroit y2038} {
+ clock format 3497839201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.690 {time zone boundary case 2081-03-09 01:59:59} {detroit y2038} {
+ clock format 3508729199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.691 {time zone boundary case 2081-03-09 03:00:00} {detroit y2038} {
+ clock format 3508729200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.692 {time zone boundary case 2081-03-09 03:00:01} {detroit y2038} {
+ clock format 3508729201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.693 {time zone boundary case 2081-11-02 01:59:59} {detroit y2038} {
+ clock format 3529288799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.694 {time zone boundary case 2081-11-02 01:00:00} {detroit y2038} {
+ clock format 3529288800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.695 {time zone boundary case 2081-11-02 01:00:01} {detroit y2038} {
+ clock format 3529288801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.696 {time zone boundary case 2082-03-08 01:59:59} {detroit y2038} {
+ clock format 3540178799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.697 {time zone boundary case 2082-03-08 03:00:00} {detroit y2038} {
+ clock format 3540178800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.698 {time zone boundary case 2082-03-08 03:00:01} {detroit y2038} {
+ clock format 3540178801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.699 {time zone boundary case 2082-11-01 01:59:59} {detroit y2038} {
+ clock format 3560738399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.700 {time zone boundary case 2082-11-01 01:00:00} {detroit y2038} {
+ clock format 3560738400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.701 {time zone boundary case 2082-11-01 01:00:01} {detroit y2038} {
+ clock format 3560738401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.702 {time zone boundary case 2083-03-14 01:59:59} {detroit y2038} {
+ clock format 3572233199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.703 {time zone boundary case 2083-03-14 03:00:00} {detroit y2038} {
+ clock format 3572233200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.704 {time zone boundary case 2083-03-14 03:00:01} {detroit y2038} {
+ clock format 3572233201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.705 {time zone boundary case 2083-11-07 01:59:59} {detroit y2038} {
+ clock format 3592792799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.706 {time zone boundary case 2083-11-07 01:00:00} {detroit y2038} {
+ clock format 3592792800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.707 {time zone boundary case 2083-11-07 01:00:01} {detroit y2038} {
+ clock format 3592792801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.708 {time zone boundary case 2084-03-12 01:59:59} {detroit y2038} {
+ clock format 3603682799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.709 {time zone boundary case 2084-03-12 03:00:00} {detroit y2038} {
+ clock format 3603682800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.710 {time zone boundary case 2084-03-12 03:00:01} {detroit y2038} {
+ clock format 3603682801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.711 {time zone boundary case 2084-11-05 01:59:59} {detroit y2038} {
+ clock format 3624242399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.712 {time zone boundary case 2084-11-05 01:00:00} {detroit y2038} {
+ clock format 3624242400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.713 {time zone boundary case 2084-11-05 01:00:01} {detroit y2038} {
+ clock format 3624242401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.714 {time zone boundary case 2085-03-11 01:59:59} {detroit y2038} {
+ clock format 3635132399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.715 {time zone boundary case 2085-03-11 03:00:00} {detroit y2038} {
+ clock format 3635132400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.716 {time zone boundary case 2085-03-11 03:00:01} {detroit y2038} {
+ clock format 3635132401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.717 {time zone boundary case 2085-11-04 01:59:59} {detroit y2038} {
+ clock format 3655691999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.718 {time zone boundary case 2085-11-04 01:00:00} {detroit y2038} {
+ clock format 3655692000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.719 {time zone boundary case 2085-11-04 01:00:01} {detroit y2038} {
+ clock format 3655692001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.720 {time zone boundary case 2086-03-10 01:59:59} {detroit y2038} {
+ clock format 3666581999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.721 {time zone boundary case 2086-03-10 03:00:00} {detroit y2038} {
+ clock format 3666582000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.722 {time zone boundary case 2086-03-10 03:00:01} {detroit y2038} {
+ clock format 3666582001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.723 {time zone boundary case 2086-11-03 01:59:59} {detroit y2038} {
+ clock format 3687141599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.724 {time zone boundary case 2086-11-03 01:00:00} {detroit y2038} {
+ clock format 3687141600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.725 {time zone boundary case 2086-11-03 01:00:01} {detroit y2038} {
+ clock format 3687141601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.726 {time zone boundary case 2087-03-09 01:59:59} {detroit y2038} {
+ clock format 3698031599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.727 {time zone boundary case 2087-03-09 03:00:00} {detroit y2038} {
+ clock format 3698031600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.728 {time zone boundary case 2087-03-09 03:00:01} {detroit y2038} {
+ clock format 3698031601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.729 {time zone boundary case 2087-11-02 01:59:59} {detroit y2038} {
+ clock format 3718591199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.730 {time zone boundary case 2087-11-02 01:00:00} {detroit y2038} {
+ clock format 3718591200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.731 {time zone boundary case 2087-11-02 01:00:01} {detroit y2038} {
+ clock format 3718591201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.732 {time zone boundary case 2088-03-14 01:59:59} {detroit y2038} {
+ clock format 3730085999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.733 {time zone boundary case 2088-03-14 03:00:00} {detroit y2038} {
+ clock format 3730086000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.734 {time zone boundary case 2088-03-14 03:00:01} {detroit y2038} {
+ clock format 3730086001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.735 {time zone boundary case 2088-11-07 01:59:59} {detroit y2038} {
+ clock format 3750645599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.736 {time zone boundary case 2088-11-07 01:00:00} {detroit y2038} {
+ clock format 3750645600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.737 {time zone boundary case 2088-11-07 01:00:01} {detroit y2038} {
+ clock format 3750645601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.738 {time zone boundary case 2089-03-13 01:59:59} {detroit y2038} {
+ clock format 3761535599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.739 {time zone boundary case 2089-03-13 03:00:00} {detroit y2038} {
+ clock format 3761535600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.740 {time zone boundary case 2089-03-13 03:00:01} {detroit y2038} {
+ clock format 3761535601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.741 {time zone boundary case 2089-11-06 01:59:59} {detroit y2038} {
+ clock format 3782095199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.742 {time zone boundary case 2089-11-06 01:00:00} {detroit y2038} {
+ clock format 3782095200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.743 {time zone boundary case 2089-11-06 01:00:01} {detroit y2038} {
+ clock format 3782095201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.744 {time zone boundary case 2090-03-12 01:59:59} {detroit y2038} {
+ clock format 3792985199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.745 {time zone boundary case 2090-03-12 03:00:00} {detroit y2038} {
+ clock format 3792985200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.746 {time zone boundary case 2090-03-12 03:00:01} {detroit y2038} {
+ clock format 3792985201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.747 {time zone boundary case 2090-11-05 01:59:59} {detroit y2038} {
+ clock format 3813544799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.748 {time zone boundary case 2090-11-05 01:00:00} {detroit y2038} {
+ clock format 3813544800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.749 {time zone boundary case 2090-11-05 01:00:01} {detroit y2038} {
+ clock format 3813544801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.750 {time zone boundary case 2091-03-11 01:59:59} {detroit y2038} {
+ clock format 3824434799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.751 {time zone boundary case 2091-03-11 03:00:00} {detroit y2038} {
+ clock format 3824434800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.752 {time zone boundary case 2091-03-11 03:00:01} {detroit y2038} {
+ clock format 3824434801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.753 {time zone boundary case 2091-11-04 01:59:59} {detroit y2038} {
+ clock format 3844994399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.754 {time zone boundary case 2091-11-04 01:00:00} {detroit y2038} {
+ clock format 3844994400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.755 {time zone boundary case 2091-11-04 01:00:01} {detroit y2038} {
+ clock format 3844994401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.756 {time zone boundary case 2092-03-09 01:59:59} {detroit y2038} {
+ clock format 3855884399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.757 {time zone boundary case 2092-03-09 03:00:00} {detroit y2038} {
+ clock format 3855884400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.758 {time zone boundary case 2092-03-09 03:00:01} {detroit y2038} {
+ clock format 3855884401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.759 {time zone boundary case 2092-11-02 01:59:59} {detroit y2038} {
+ clock format 3876443999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.760 {time zone boundary case 2092-11-02 01:00:00} {detroit y2038} {
+ clock format 3876444000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.761 {time zone boundary case 2092-11-02 01:00:01} {detroit y2038} {
+ clock format 3876444001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.762 {time zone boundary case 2093-03-08 01:59:59} {detroit y2038} {
+ clock format 3887333999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.763 {time zone boundary case 2093-03-08 03:00:00} {detroit y2038} {
+ clock format 3887334000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.764 {time zone boundary case 2093-03-08 03:00:01} {detroit y2038} {
+ clock format 3887334001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.765 {time zone boundary case 2093-11-01 01:59:59} {detroit y2038} {
+ clock format 3907893599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.766 {time zone boundary case 2093-11-01 01:00:00} {detroit y2038} {
+ clock format 3907893600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.767 {time zone boundary case 2093-11-01 01:00:01} {detroit y2038} {
+ clock format 3907893601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.768 {time zone boundary case 2094-03-14 01:59:59} {detroit y2038} {
+ clock format 3919388399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.769 {time zone boundary case 2094-03-14 03:00:00} {detroit y2038} {
+ clock format 3919388400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.770 {time zone boundary case 2094-03-14 03:00:01} {detroit y2038} {
+ clock format 3919388401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.771 {time zone boundary case 2094-11-07 01:59:59} {detroit y2038} {
+ clock format 3939947999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.772 {time zone boundary case 2094-11-07 01:00:00} {detroit y2038} {
+ clock format 3939948000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.773 {time zone boundary case 2094-11-07 01:00:01} {detroit y2038} {
+ clock format 3939948001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.774 {time zone boundary case 2095-03-13 01:59:59} {detroit y2038} {
+ clock format 3950837999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.775 {time zone boundary case 2095-03-13 03:00:00} {detroit y2038} {
+ clock format 3950838000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.776 {time zone boundary case 2095-03-13 03:00:01} {detroit y2038} {
+ clock format 3950838001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.777 {time zone boundary case 2095-11-06 01:59:59} {detroit y2038} {
+ clock format 3971397599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.778 {time zone boundary case 2095-11-06 01:00:00} {detroit y2038} {
+ clock format 3971397600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.779 {time zone boundary case 2095-11-06 01:00:01} {detroit y2038} {
+ clock format 3971397601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.780 {time zone boundary case 2096-03-11 01:59:59} {detroit y2038} {
+ clock format 3982287599 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.781 {time zone boundary case 2096-03-11 03:00:00} {detroit y2038} {
+ clock format 3982287600 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.782 {time zone boundary case 2096-03-11 03:00:01} {detroit y2038} {
+ clock format 3982287601 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.783 {time zone boundary case 2096-11-04 01:59:59} {detroit y2038} {
+ clock format 4002847199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.784 {time zone boundary case 2096-11-04 01:00:00} {detroit y2038} {
+ clock format 4002847200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.785 {time zone boundary case 2096-11-04 01:00:01} {detroit y2038} {
+ clock format 4002847201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.786 {time zone boundary case 2097-03-10 01:59:59} {detroit y2038} {
+ clock format 4013737199 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.787 {time zone boundary case 2097-03-10 03:00:00} {detroit y2038} {
+ clock format 4013737200 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.788 {time zone boundary case 2097-03-10 03:00:01} {detroit y2038} {
+ clock format 4013737201 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.789 {time zone boundary case 2097-11-03 01:59:59} {detroit y2038} {
+ clock format 4034296799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.790 {time zone boundary case 2097-11-03 01:00:00} {detroit y2038} {
+ clock format 4034296800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.791 {time zone boundary case 2097-11-03 01:00:01} {detroit y2038} {
+ clock format 4034296801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.792 {time zone boundary case 2098-03-09 01:59:59} {detroit y2038} {
+ clock format 4045186799 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.793 {time zone boundary case 2098-03-09 03:00:00} {detroit y2038} {
+ clock format 4045186800 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.794 {time zone boundary case 2098-03-09 03:00:01} {detroit y2038} {
+ clock format 4045186801 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.795 {time zone boundary case 2098-11-02 01:59:59} {detroit y2038} {
+ clock format 4065746399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.796 {time zone boundary case 2098-11-02 01:00:00} {detroit y2038} {
+ clock format 4065746400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.797 {time zone boundary case 2098-11-02 01:00:01} {detroit y2038} {
+ clock format 4065746401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+test clock-5.798 {time zone boundary case 2099-03-08 01:59:59} {detroit y2038} {
+ clock format 4076636399 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0500 EST}
+test clock-5.799 {time zone boundary case 2099-03-08 03:00:00} {detroit y2038} {
+ clock format 4076636400 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:00 -0400 EDT}
+test clock-5.800 {time zone boundary case 2099-03-08 03:00:01} {detroit y2038} {
+ clock format 4076636401 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {03:00:01 -0400 EDT}
+test clock-5.801 {time zone boundary case 2099-11-01 01:59:59} {detroit y2038} {
+ clock format 4097195999 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:59:59 -0400 EDT}
+test clock-5.802 {time zone boundary case 2099-11-01 01:00:00} {detroit y2038} {
+ clock format 4097196000 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:00 -0500 EST}
+test clock-5.803 {time zone boundary case 2099-11-01 01:00:01} {detroit y2038} {
+ clock format 4097196001 -format {%H:%M:%S %z %Z} \
+ -timezone :America/Detroit
+} {01:00:01 -0500 EST}
+# END testcases5
+
+# Test input conversions.
+
+test clock-6.0 {input of seconds} {
+ clock scan {-9223372036854775808} -format %s -gmt true
+} -9223372036854775808
+
+test clock-6.1 {input of seconds} {
+ clock scan {-2147483649} -format %s -gmt true
+} -2147483649
+
+test clock-6.2 {input of seconds} {
+ clock scan {-2147483648} -format %s -gmt true
+} -2147483648
+
+test clock-6.3 {input of seconds} {
+ clock scan {-1} -format %s -gmt true
+} -1
+
+test clock-6.4 {input of seconds} {
+ clock scan {0} -format %s -gmt true
+} 0
+
+test clock-6.5 {input of seconds} {
+ clock scan {1} -format %s -gmt true
+} 1
+
+test clock-6.6 {input of seconds} {
+ clock scan {2147483647} -format %s -gmt true
+} 2147483647
+
+test clock-6.7 {input of seconds} {
+ clock scan {2147483648} -format %s -gmt true
+} 2147483648
+
+test clock-6.8 {input of seconds} {
+ clock scan {9223372036854775807} -format %s -gmt true
+} 9223372036854775807
+
+test clock-6.9 {input of seconds - overflow} {
+ list [catch {clock scan -9223372036854775809 -format %s -gmt true} result] $result
+} {1 {integer value too large to represent}}
+
+test clock-6.10 {input of seconds - overflow} {
+ list [catch {clock scan 9223372036854775808 -format %s -gmt true} result] $result
+} {1 {integer value too large to represent}}
+
+test clock-6.11 {input of seconds - two values} {
+ clock scan {1 2} -format {%s %s} -gmt true
+} 2
+
+test clock-7.1 {Julian Day} {
+ clock scan 0 -format %J -gmt true
+} -210866803200
+
+test clock-7.2 {Julian Day} {
+ clock format [clock scan 2440588 -format %J -gmt true] \
+ -format %Y-%m-%d -gmt true
+} 1970-01-01
+
+test clock-7.3 {Julian Day} {
+ clock format [clock scan 2451545 -format %J -gmt true] \
+ -format %Y-%m-%d -gmt true
+} 2000-01-01
+
+test clock-7.3.1 {Julian Day} {
+ clock format [clock scan 2488070 -format %J -gmt true] \
+ -format %Y-%m-%d -gmt true
+} 2100-01-01
+
+test clock-7.4 {Julian Day} {
+ clock format [clock scan 5373484 -format %J -gmt true] \
+ -format %Y-%m-%d -gmt true
+} 9999-12-31
+
+test clock-7.5 {Julian Day, bad} {
+ list [catch {
+ clock scan bogus -format %J
+ } result] $result $errorCode
+} {1 {input string does not match supplied format} {CLOCK badInputString}}
+
+test clock-7.6 {Julian Day, overflow} {
+ list [catch {
+ clock scan 5373485 -format %J
+ } result] $result $errorCode
+} {1 {requested date too large to represent} {CLOCK dateTooLarge}}
+
+test clock-7.7 {Julian Day, overflow} {
+ list [catch {
+ clock scan 2147483648 -format %J
+ } result] $result $errorCode
+} {1 {requested date too large to represent} {CLOCK dateTooLarge}}
+
+test clock-7.8 {Julian Day, precedence below seconds} {
+ list [clock scan {2440588 86400} -format {%J %s} -gmt true] \
+ [clock scan {2440589 0} -format {%J %s} -gmt true] \
+ [clock scan {86400 2440588} -format {%s %J} -gmt true] \
+ [clock scan {0 2440589} -format {%s %J} -gmt true]
+} {86400 0 86400 0}
+
+test clock-7.9 {Julian Day, two values} {
+ clock scan {2440588 2440589} -format {%J %J} -gmt true
+} 86400
+
+# BEGIN testcases8
+
+# Test parsing of ccyymmdd
+
+test clock-8.1 {parse ccyymmdd} {
+ clock scan {1970 Jan 02} -format {%C%y %b %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.2 {parse ccyymmdd} {
+ clock scan {1970 Jan ii} -format {%C%y %b %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.3 {parse ccyymmdd} {
+ clock scan {1970 Jan 2} -format {%C%y %b %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.4 {parse ccyymmdd} {
+ clock scan {1970 Jan ii} -format {%C%y %b %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.5 {parse ccyymmdd} {
+ clock scan {1970 January 02} -format {%C%y %B %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.6 {parse ccyymmdd} {
+ clock scan {1970 January ii} -format {%C%y %B %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.7 {parse ccyymmdd} {
+ clock scan {1970 January 2} -format {%C%y %B %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.8 {parse ccyymmdd} {
+ clock scan {1970 January ii} -format {%C%y %B %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.9 {parse ccyymmdd} {
+ clock scan {1970 Jan 02} -format {%C%y %h %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.10 {parse ccyymmdd} {
+ clock scan {1970 Jan ii} -format {%C%y %h %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.11 {parse ccyymmdd} {
+ clock scan {1970 Jan 2} -format {%C%y %h %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.12 {parse ccyymmdd} {
+ clock scan {1970 Jan ii} -format {%C%y %h %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.13 {parse ccyymmdd} {
+ clock scan {1970 01 02} -format {%C%y %m %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.14 {parse ccyymmdd} {
+ clock scan {1970 01 ii} -format {%C%y %m %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.15 {parse ccyymmdd} {
+ clock scan {1970 01 2} -format {%C%y %m %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.16 {parse ccyymmdd} {
+ clock scan {1970 01 ii} -format {%C%y %m %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.17 {parse ccyymmdd} {
+ clock scan {1970 i 02} -format {%C%y %Om %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.18 {parse ccyymmdd} {
+ clock scan {1970 i ii} -format {%C%y %Om %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.19 {parse ccyymmdd} {
+ clock scan {1970 i 2} -format {%C%y %Om %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.20 {parse ccyymmdd} {
+ clock scan {1970 i ii} -format {%C%y %Om %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.21 {parse ccyymmdd} {
+ clock scan {1970 1 02} -format {%C%y %N %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.22 {parse ccyymmdd} {
+ clock scan {1970 1 ii} -format {%C%y %N %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.23 {parse ccyymmdd} {
+ clock scan {1970 1 2} -format {%C%y %N %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.24 {parse ccyymmdd} {
+ clock scan {1970 1 ii} -format {%C%y %N %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.25 {parse ccyymmdd} {
+ clock scan {1970 Jan 02} -format {%Y %b %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.26 {parse ccyymmdd} {
+ clock scan {1970 Jan ii} -format {%Y %b %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.27 {parse ccyymmdd} {
+ clock scan {1970 Jan 2} -format {%Y %b %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.28 {parse ccyymmdd} {
+ clock scan {1970 Jan ii} -format {%Y %b %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.29 {parse ccyymmdd} {
+ clock scan {1970 January 02} -format {%Y %B %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.30 {parse ccyymmdd} {
+ clock scan {1970 January ii} -format {%Y %B %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.31 {parse ccyymmdd} {
+ clock scan {1970 January 2} -format {%Y %B %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.32 {parse ccyymmdd} {
+ clock scan {1970 January ii} -format {%Y %B %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.33 {parse ccyymmdd} {
+ clock scan {1970 Jan 02} -format {%Y %h %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.34 {parse ccyymmdd} {
+ clock scan {1970 Jan ii} -format {%Y %h %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.35 {parse ccyymmdd} {
+ clock scan {1970 Jan 2} -format {%Y %h %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.36 {parse ccyymmdd} {
+ clock scan {1970 Jan ii} -format {%Y %h %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.37 {parse ccyymmdd} {
+ clock scan {1970 01 02} -format {%Y %m %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.38 {parse ccyymmdd} {
+ clock scan {1970 01 ii} -format {%Y %m %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.39 {parse ccyymmdd} {
+ clock scan {1970 01 2} -format {%Y %m %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.40 {parse ccyymmdd} {
+ clock scan {1970 01 ii} -format {%Y %m %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.41 {parse ccyymmdd} {
+ clock scan {1970 i 02} -format {%Y %Om %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.42 {parse ccyymmdd} {
+ clock scan {1970 i ii} -format {%Y %Om %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.43 {parse ccyymmdd} {
+ clock scan {1970 i 2} -format {%Y %Om %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.44 {parse ccyymmdd} {
+ clock scan {1970 i ii} -format {%Y %Om %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.45 {parse ccyymmdd} {
+ clock scan {1970 1 02} -format {%Y %N %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.46 {parse ccyymmdd} {
+ clock scan {1970 1 ii} -format {%Y %N %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.47 {parse ccyymmdd} {
+ clock scan {1970 1 2} -format {%Y %N %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.48 {parse ccyymmdd} {
+ clock scan {1970 1 ii} -format {%Y %N %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-8.49 {parse ccyymmdd} {
+ clock scan 01/02/1970 -format %x -locale en_US_roman -gmt 1
+} 86400
+test clock-8.50 {parse ccyymmdd} {
+ clock scan 01/02/1970 -format %D -locale en_US_roman -gmt 1
+} 86400
+test clock-8.51 {parse ccyymmdd} {
+ clock scan {1970 Jan 31} -format {%C%y %b %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.52 {parse ccyymmdd} {
+ clock scan {1970 Jan xxxi} -format {%C%y %b %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.53 {parse ccyymmdd} {
+ clock scan {1970 Jan 31} -format {%C%y %b %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.54 {parse ccyymmdd} {
+ clock scan {1970 Jan xxxi} -format {%C%y %b %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.55 {parse ccyymmdd} {
+ clock scan {1970 January 31} -format {%C%y %B %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.56 {parse ccyymmdd} {
+ clock scan {1970 January xxxi} -format {%C%y %B %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.57 {parse ccyymmdd} {
+ clock scan {1970 January 31} -format {%C%y %B %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.58 {parse ccyymmdd} {
+ clock scan {1970 January xxxi} -format {%C%y %B %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.59 {parse ccyymmdd} {
+ clock scan {1970 Jan 31} -format {%C%y %h %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.60 {parse ccyymmdd} {
+ clock scan {1970 Jan xxxi} -format {%C%y %h %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.61 {parse ccyymmdd} {
+ clock scan {1970 Jan 31} -format {%C%y %h %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.62 {parse ccyymmdd} {
+ clock scan {1970 Jan xxxi} -format {%C%y %h %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.63 {parse ccyymmdd} {
+ clock scan {1970 01 31} -format {%C%y %m %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.64 {parse ccyymmdd} {
+ clock scan {1970 01 xxxi} -format {%C%y %m %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.65 {parse ccyymmdd} {
+ clock scan {1970 01 31} -format {%C%y %m %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.66 {parse ccyymmdd} {
+ clock scan {1970 01 xxxi} -format {%C%y %m %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.67 {parse ccyymmdd} {
+ clock scan {1970 i 31} -format {%C%y %Om %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.68 {parse ccyymmdd} {
+ clock scan {1970 i xxxi} -format {%C%y %Om %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.69 {parse ccyymmdd} {
+ clock scan {1970 i 31} -format {%C%y %Om %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.70 {parse ccyymmdd} {
+ clock scan {1970 i xxxi} -format {%C%y %Om %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.71 {parse ccyymmdd} {
+ clock scan {1970 1 31} -format {%C%y %N %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.72 {parse ccyymmdd} {
+ clock scan {1970 1 xxxi} -format {%C%y %N %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.73 {parse ccyymmdd} {
+ clock scan {1970 1 31} -format {%C%y %N %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.74 {parse ccyymmdd} {
+ clock scan {1970 1 xxxi} -format {%C%y %N %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.75 {parse ccyymmdd} {
+ clock scan {1970 Jan 31} -format {%Y %b %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.76 {parse ccyymmdd} {
+ clock scan {1970 Jan xxxi} -format {%Y %b %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.77 {parse ccyymmdd} {
+ clock scan {1970 Jan 31} -format {%Y %b %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.78 {parse ccyymmdd} {
+ clock scan {1970 Jan xxxi} -format {%Y %b %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.79 {parse ccyymmdd} {
+ clock scan {1970 January 31} -format {%Y %B %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.80 {parse ccyymmdd} {
+ clock scan {1970 January xxxi} -format {%Y %B %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.81 {parse ccyymmdd} {
+ clock scan {1970 January 31} -format {%Y %B %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.82 {parse ccyymmdd} {
+ clock scan {1970 January xxxi} -format {%Y %B %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.83 {parse ccyymmdd} {
+ clock scan {1970 Jan 31} -format {%Y %h %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.84 {parse ccyymmdd} {
+ clock scan {1970 Jan xxxi} -format {%Y %h %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.85 {parse ccyymmdd} {
+ clock scan {1970 Jan 31} -format {%Y %h %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.86 {parse ccyymmdd} {
+ clock scan {1970 Jan xxxi} -format {%Y %h %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.87 {parse ccyymmdd} {
+ clock scan {1970 01 31} -format {%Y %m %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.88 {parse ccyymmdd} {
+ clock scan {1970 01 xxxi} -format {%Y %m %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.89 {parse ccyymmdd} {
+ clock scan {1970 01 31} -format {%Y %m %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.90 {parse ccyymmdd} {
+ clock scan {1970 01 xxxi} -format {%Y %m %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.91 {parse ccyymmdd} {
+ clock scan {1970 i 31} -format {%Y %Om %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.92 {parse ccyymmdd} {
+ clock scan {1970 i xxxi} -format {%Y %Om %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.93 {parse ccyymmdd} {
+ clock scan {1970 i 31} -format {%Y %Om %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.94 {parse ccyymmdd} {
+ clock scan {1970 i xxxi} -format {%Y %Om %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.95 {parse ccyymmdd} {
+ clock scan {1970 1 31} -format {%Y %N %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.96 {parse ccyymmdd} {
+ clock scan {1970 1 xxxi} -format {%Y %N %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.97 {parse ccyymmdd} {
+ clock scan {1970 1 31} -format {%Y %N %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.98 {parse ccyymmdd} {
+ clock scan {1970 1 xxxi} -format {%Y %N %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.99 {parse ccyymmdd} {
+ clock scan 01/31/1970 -format %x -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.100 {parse ccyymmdd} {
+ clock scan 01/31/1970 -format %D -locale en_US_roman -gmt 1
+} 2592000
+test clock-8.101 {parse ccyymmdd} {
+ clock scan {1970 Dec 02} -format {%C%y %b %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.102 {parse ccyymmdd} {
+ clock scan {1970 Dec ii} -format {%C%y %b %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.103 {parse ccyymmdd} {
+ clock scan {1970 Dec 2} -format {%C%y %b %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.104 {parse ccyymmdd} {
+ clock scan {1970 Dec ii} -format {%C%y %b %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.105 {parse ccyymmdd} {
+ clock scan {1970 December 02} -format {%C%y %B %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.106 {parse ccyymmdd} {
+ clock scan {1970 December ii} -format {%C%y %B %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.107 {parse ccyymmdd} {
+ clock scan {1970 December 2} -format {%C%y %B %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.108 {parse ccyymmdd} {
+ clock scan {1970 December ii} -format {%C%y %B %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.109 {parse ccyymmdd} {
+ clock scan {1970 Dec 02} -format {%C%y %h %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.110 {parse ccyymmdd} {
+ clock scan {1970 Dec ii} -format {%C%y %h %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.111 {parse ccyymmdd} {
+ clock scan {1970 Dec 2} -format {%C%y %h %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.112 {parse ccyymmdd} {
+ clock scan {1970 Dec ii} -format {%C%y %h %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.113 {parse ccyymmdd} {
+ clock scan {1970 12 02} -format {%C%y %m %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.114 {parse ccyymmdd} {
+ clock scan {1970 12 ii} -format {%C%y %m %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.115 {parse ccyymmdd} {
+ clock scan {1970 12 2} -format {%C%y %m %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.116 {parse ccyymmdd} {
+ clock scan {1970 12 ii} -format {%C%y %m %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.117 {parse ccyymmdd} {
+ clock scan {1970 xii 02} -format {%C%y %Om %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.118 {parse ccyymmdd} {
+ clock scan {1970 xii ii} -format {%C%y %Om %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.119 {parse ccyymmdd} {
+ clock scan {1970 xii 2} -format {%C%y %Om %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.120 {parse ccyymmdd} {
+ clock scan {1970 xii ii} -format {%C%y %Om %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.121 {parse ccyymmdd} {
+ clock scan {1970 12 02} -format {%C%y %N %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.122 {parse ccyymmdd} {
+ clock scan {1970 12 ii} -format {%C%y %N %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.123 {parse ccyymmdd} {
+ clock scan {1970 12 2} -format {%C%y %N %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.124 {parse ccyymmdd} {
+ clock scan {1970 12 ii} -format {%C%y %N %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.125 {parse ccyymmdd} {
+ clock scan {1970 Dec 02} -format {%Y %b %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.126 {parse ccyymmdd} {
+ clock scan {1970 Dec ii} -format {%Y %b %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.127 {parse ccyymmdd} {
+ clock scan {1970 Dec 2} -format {%Y %b %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.128 {parse ccyymmdd} {
+ clock scan {1970 Dec ii} -format {%Y %b %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.129 {parse ccyymmdd} {
+ clock scan {1970 December 02} -format {%Y %B %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.130 {parse ccyymmdd} {
+ clock scan {1970 December ii} -format {%Y %B %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.131 {parse ccyymmdd} {
+ clock scan {1970 December 2} -format {%Y %B %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.132 {parse ccyymmdd} {
+ clock scan {1970 December ii} -format {%Y %B %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.133 {parse ccyymmdd} {
+ clock scan {1970 Dec 02} -format {%Y %h %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.134 {parse ccyymmdd} {
+ clock scan {1970 Dec ii} -format {%Y %h %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.135 {parse ccyymmdd} {
+ clock scan {1970 Dec 2} -format {%Y %h %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.136 {parse ccyymmdd} {
+ clock scan {1970 Dec ii} -format {%Y %h %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.137 {parse ccyymmdd} {
+ clock scan {1970 12 02} -format {%Y %m %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.138 {parse ccyymmdd} {
+ clock scan {1970 12 ii} -format {%Y %m %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.139 {parse ccyymmdd} {
+ clock scan {1970 12 2} -format {%Y %m %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.140 {parse ccyymmdd} {
+ clock scan {1970 12 ii} -format {%Y %m %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.141 {parse ccyymmdd} {
+ clock scan {1970 xii 02} -format {%Y %Om %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.142 {parse ccyymmdd} {
+ clock scan {1970 xii ii} -format {%Y %Om %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.143 {parse ccyymmdd} {
+ clock scan {1970 xii 2} -format {%Y %Om %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.144 {parse ccyymmdd} {
+ clock scan {1970 xii ii} -format {%Y %Om %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.145 {parse ccyymmdd} {
+ clock scan {1970 12 02} -format {%Y %N %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.146 {parse ccyymmdd} {
+ clock scan {1970 12 ii} -format {%Y %N %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.147 {parse ccyymmdd} {
+ clock scan {1970 12 2} -format {%Y %N %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.148 {parse ccyymmdd} {
+ clock scan {1970 12 ii} -format {%Y %N %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.149 {parse ccyymmdd} {
+ clock scan 12/02/1970 -format %x -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.150 {parse ccyymmdd} {
+ clock scan 12/02/1970 -format %D -locale en_US_roman -gmt 1
+} 28944000
+test clock-8.151 {parse ccyymmdd} {
+ clock scan {1970 Dec 31} -format {%C%y %b %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.152 {parse ccyymmdd} {
+ clock scan {1970 Dec xxxi} -format {%C%y %b %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.153 {parse ccyymmdd} {
+ clock scan {1970 Dec 31} -format {%C%y %b %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.154 {parse ccyymmdd} {
+ clock scan {1970 Dec xxxi} -format {%C%y %b %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.155 {parse ccyymmdd} {
+ clock scan {1970 December 31} -format {%C%y %B %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.156 {parse ccyymmdd} {
+ clock scan {1970 December xxxi} -format {%C%y %B %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.157 {parse ccyymmdd} {
+ clock scan {1970 December 31} -format {%C%y %B %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.158 {parse ccyymmdd} {
+ clock scan {1970 December xxxi} -format {%C%y %B %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.159 {parse ccyymmdd} {
+ clock scan {1970 Dec 31} -format {%C%y %h %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.160 {parse ccyymmdd} {
+ clock scan {1970 Dec xxxi} -format {%C%y %h %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.161 {parse ccyymmdd} {
+ clock scan {1970 Dec 31} -format {%C%y %h %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.162 {parse ccyymmdd} {
+ clock scan {1970 Dec xxxi} -format {%C%y %h %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.163 {parse ccyymmdd} {
+ clock scan {1970 12 31} -format {%C%y %m %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.164 {parse ccyymmdd} {
+ clock scan {1970 12 xxxi} -format {%C%y %m %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.165 {parse ccyymmdd} {
+ clock scan {1970 12 31} -format {%C%y %m %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.166 {parse ccyymmdd} {
+ clock scan {1970 12 xxxi} -format {%C%y %m %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.167 {parse ccyymmdd} {
+ clock scan {1970 xii 31} -format {%C%y %Om %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.168 {parse ccyymmdd} {
+ clock scan {1970 xii xxxi} -format {%C%y %Om %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.169 {parse ccyymmdd} {
+ clock scan {1970 xii 31} -format {%C%y %Om %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.170 {parse ccyymmdd} {
+ clock scan {1970 xii xxxi} -format {%C%y %Om %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.171 {parse ccyymmdd} {
+ clock scan {1970 12 31} -format {%C%y %N %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.172 {parse ccyymmdd} {
+ clock scan {1970 12 xxxi} -format {%C%y %N %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.173 {parse ccyymmdd} {
+ clock scan {1970 12 31} -format {%C%y %N %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.174 {parse ccyymmdd} {
+ clock scan {1970 12 xxxi} -format {%C%y %N %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.175 {parse ccyymmdd} {
+ clock scan {1970 Dec 31} -format {%Y %b %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.176 {parse ccyymmdd} {
+ clock scan {1970 Dec xxxi} -format {%Y %b %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.177 {parse ccyymmdd} {
+ clock scan {1970 Dec 31} -format {%Y %b %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.178 {parse ccyymmdd} {
+ clock scan {1970 Dec xxxi} -format {%Y %b %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.179 {parse ccyymmdd} {
+ clock scan {1970 December 31} -format {%Y %B %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.180 {parse ccyymmdd} {
+ clock scan {1970 December xxxi} -format {%Y %B %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.181 {parse ccyymmdd} {
+ clock scan {1970 December 31} -format {%Y %B %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.182 {parse ccyymmdd} {
+ clock scan {1970 December xxxi} -format {%Y %B %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.183 {parse ccyymmdd} {
+ clock scan {1970 Dec 31} -format {%Y %h %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.184 {parse ccyymmdd} {
+ clock scan {1970 Dec xxxi} -format {%Y %h %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.185 {parse ccyymmdd} {
+ clock scan {1970 Dec 31} -format {%Y %h %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.186 {parse ccyymmdd} {
+ clock scan {1970 Dec xxxi} -format {%Y %h %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.187 {parse ccyymmdd} {
+ clock scan {1970 12 31} -format {%Y %m %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.188 {parse ccyymmdd} {
+ clock scan {1970 12 xxxi} -format {%Y %m %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.189 {parse ccyymmdd} {
+ clock scan {1970 12 31} -format {%Y %m %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.190 {parse ccyymmdd} {
+ clock scan {1970 12 xxxi} -format {%Y %m %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.191 {parse ccyymmdd} {
+ clock scan {1970 xii 31} -format {%Y %Om %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.192 {parse ccyymmdd} {
+ clock scan {1970 xii xxxi} -format {%Y %Om %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.193 {parse ccyymmdd} {
+ clock scan {1970 xii 31} -format {%Y %Om %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.194 {parse ccyymmdd} {
+ clock scan {1970 xii xxxi} -format {%Y %Om %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.195 {parse ccyymmdd} {
+ clock scan {1970 12 31} -format {%Y %N %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.196 {parse ccyymmdd} {
+ clock scan {1970 12 xxxi} -format {%Y %N %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.197 {parse ccyymmdd} {
+ clock scan {1970 12 31} -format {%Y %N %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.198 {parse ccyymmdd} {
+ clock scan {1970 12 xxxi} -format {%Y %N %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.199 {parse ccyymmdd} {
+ clock scan 12/31/1970 -format %x -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.200 {parse ccyymmdd} {
+ clock scan 12/31/1970 -format %D -locale en_US_roman -gmt 1
+} 31449600
+test clock-8.201 {parse ccyymmdd} {
+ clock scan {1971 Jan 02} -format {%C%y %b %d} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.202 {parse ccyymmdd} {
+ clock scan {1971 Jan ii} -format {%C%y %b %Od} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.203 {parse ccyymmdd} {
+ clock scan {1971 Jan 2} -format {%C%y %b %e} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.204 {parse ccyymmdd} {
+ clock scan {1971 Jan ii} -format {%C%y %b %Oe} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.205 {parse ccyymmdd} {
+ clock scan {1971 January 02} -format {%C%y %B %d} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.206 {parse ccyymmdd} {
+ clock scan {1971 January ii} -format {%C%y %B %Od} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.207 {parse ccyymmdd} {
+ clock scan {1971 January 2} -format {%C%y %B %e} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.208 {parse ccyymmdd} {
+ clock scan {1971 January ii} -format {%C%y %B %Oe} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.209 {parse ccyymmdd} {
+ clock scan {1971 Jan 02} -format {%C%y %h %d} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.210 {parse ccyymmdd} {
+ clock scan {1971 Jan ii} -format {%C%y %h %Od} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.211 {parse ccyymmdd} {
+ clock scan {1971 Jan 2} -format {%C%y %h %e} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.212 {parse ccyymmdd} {
+ clock scan {1971 Jan ii} -format {%C%y %h %Oe} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.213 {parse ccyymmdd} {
+ clock scan {1971 01 02} -format {%C%y %m %d} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.214 {parse ccyymmdd} {
+ clock scan {1971 01 ii} -format {%C%y %m %Od} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.215 {parse ccyymmdd} {
+ clock scan {1971 01 2} -format {%C%y %m %e} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.216 {parse ccyymmdd} {
+ clock scan {1971 01 ii} -format {%C%y %m %Oe} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.217 {parse ccyymmdd} {
+ clock scan {1971 i 02} -format {%C%y %Om %d} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.218 {parse ccyymmdd} {
+ clock scan {1971 i ii} -format {%C%y %Om %Od} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.219 {parse ccyymmdd} {
+ clock scan {1971 i 2} -format {%C%y %Om %e} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.220 {parse ccyymmdd} {
+ clock scan {1971 i ii} -format {%C%y %Om %Oe} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.221 {parse ccyymmdd} {
+ clock scan {1971 1 02} -format {%C%y %N %d} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.222 {parse ccyymmdd} {
+ clock scan {1971 1 ii} -format {%C%y %N %Od} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.223 {parse ccyymmdd} {
+ clock scan {1971 1 2} -format {%C%y %N %e} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.224 {parse ccyymmdd} {
+ clock scan {1971 1 ii} -format {%C%y %N %Oe} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.225 {parse ccyymmdd} {
+ clock scan {1971 Jan 02} -format {%Y %b %d} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.226 {parse ccyymmdd} {
+ clock scan {1971 Jan ii} -format {%Y %b %Od} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.227 {parse ccyymmdd} {
+ clock scan {1971 Jan 2} -format {%Y %b %e} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.228 {parse ccyymmdd} {
+ clock scan {1971 Jan ii} -format {%Y %b %Oe} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.229 {parse ccyymmdd} {
+ clock scan {1971 January 02} -format {%Y %B %d} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.230 {parse ccyymmdd} {
+ clock scan {1971 January ii} -format {%Y %B %Od} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.231 {parse ccyymmdd} {
+ clock scan {1971 January 2} -format {%Y %B %e} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.232 {parse ccyymmdd} {
+ clock scan {1971 January ii} -format {%Y %B %Oe} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.233 {parse ccyymmdd} {
+ clock scan {1971 Jan 02} -format {%Y %h %d} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.234 {parse ccyymmdd} {
+ clock scan {1971 Jan ii} -format {%Y %h %Od} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.235 {parse ccyymmdd} {
+ clock scan {1971 Jan 2} -format {%Y %h %e} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.236 {parse ccyymmdd} {
+ clock scan {1971 Jan ii} -format {%Y %h %Oe} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.237 {parse ccyymmdd} {
+ clock scan {1971 01 02} -format {%Y %m %d} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.238 {parse ccyymmdd} {
+ clock scan {1971 01 ii} -format {%Y %m %Od} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.239 {parse ccyymmdd} {
+ clock scan {1971 01 2} -format {%Y %m %e} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.240 {parse ccyymmdd} {
+ clock scan {1971 01 ii} -format {%Y %m %Oe} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.241 {parse ccyymmdd} {
+ clock scan {1971 i 02} -format {%Y %Om %d} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.242 {parse ccyymmdd} {
+ clock scan {1971 i ii} -format {%Y %Om %Od} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.243 {parse ccyymmdd} {
+ clock scan {1971 i 2} -format {%Y %Om %e} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.244 {parse ccyymmdd} {
+ clock scan {1971 i ii} -format {%Y %Om %Oe} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.245 {parse ccyymmdd} {
+ clock scan {1971 1 02} -format {%Y %N %d} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.246 {parse ccyymmdd} {
+ clock scan {1971 1 ii} -format {%Y %N %Od} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.247 {parse ccyymmdd} {
+ clock scan {1971 1 2} -format {%Y %N %e} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.248 {parse ccyymmdd} {
+ clock scan {1971 1 ii} -format {%Y %N %Oe} -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.249 {parse ccyymmdd} {
+ clock scan 01/02/1971 -format %x -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.250 {parse ccyymmdd} {
+ clock scan 01/02/1971 -format %D -locale en_US_roman -gmt 1
+} 31622400
+test clock-8.251 {parse ccyymmdd} {
+ clock scan {1971 Jan 31} -format {%C%y %b %d} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.252 {parse ccyymmdd} {
+ clock scan {1971 Jan xxxi} -format {%C%y %b %Od} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.253 {parse ccyymmdd} {
+ clock scan {1971 Jan 31} -format {%C%y %b %e} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.254 {parse ccyymmdd} {
+ clock scan {1971 Jan xxxi} -format {%C%y %b %Oe} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.255 {parse ccyymmdd} {
+ clock scan {1971 January 31} -format {%C%y %B %d} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.256 {parse ccyymmdd} {
+ clock scan {1971 January xxxi} -format {%C%y %B %Od} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.257 {parse ccyymmdd} {
+ clock scan {1971 January 31} -format {%C%y %B %e} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.258 {parse ccyymmdd} {
+ clock scan {1971 January xxxi} -format {%C%y %B %Oe} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.259 {parse ccyymmdd} {
+ clock scan {1971 Jan 31} -format {%C%y %h %d} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.260 {parse ccyymmdd} {
+ clock scan {1971 Jan xxxi} -format {%C%y %h %Od} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.261 {parse ccyymmdd} {
+ clock scan {1971 Jan 31} -format {%C%y %h %e} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.262 {parse ccyymmdd} {
+ clock scan {1971 Jan xxxi} -format {%C%y %h %Oe} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.263 {parse ccyymmdd} {
+ clock scan {1971 01 31} -format {%C%y %m %d} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.264 {parse ccyymmdd} {
+ clock scan {1971 01 xxxi} -format {%C%y %m %Od} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.265 {parse ccyymmdd} {
+ clock scan {1971 01 31} -format {%C%y %m %e} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.266 {parse ccyymmdd} {
+ clock scan {1971 01 xxxi} -format {%C%y %m %Oe} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.267 {parse ccyymmdd} {
+ clock scan {1971 i 31} -format {%C%y %Om %d} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.268 {parse ccyymmdd} {
+ clock scan {1971 i xxxi} -format {%C%y %Om %Od} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.269 {parse ccyymmdd} {
+ clock scan {1971 i 31} -format {%C%y %Om %e} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.270 {parse ccyymmdd} {
+ clock scan {1971 i xxxi} -format {%C%y %Om %Oe} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.271 {parse ccyymmdd} {
+ clock scan {1971 1 31} -format {%C%y %N %d} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.272 {parse ccyymmdd} {
+ clock scan {1971 1 xxxi} -format {%C%y %N %Od} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.273 {parse ccyymmdd} {
+ clock scan {1971 1 31} -format {%C%y %N %e} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.274 {parse ccyymmdd} {
+ clock scan {1971 1 xxxi} -format {%C%y %N %Oe} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.275 {parse ccyymmdd} {
+ clock scan {1971 Jan 31} -format {%Y %b %d} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.276 {parse ccyymmdd} {
+ clock scan {1971 Jan xxxi} -format {%Y %b %Od} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.277 {parse ccyymmdd} {
+ clock scan {1971 Jan 31} -format {%Y %b %e} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.278 {parse ccyymmdd} {
+ clock scan {1971 Jan xxxi} -format {%Y %b %Oe} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.279 {parse ccyymmdd} {
+ clock scan {1971 January 31} -format {%Y %B %d} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.280 {parse ccyymmdd} {
+ clock scan {1971 January xxxi} -format {%Y %B %Od} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.281 {parse ccyymmdd} {
+ clock scan {1971 January 31} -format {%Y %B %e} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.282 {parse ccyymmdd} {
+ clock scan {1971 January xxxi} -format {%Y %B %Oe} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.283 {parse ccyymmdd} {
+ clock scan {1971 Jan 31} -format {%Y %h %d} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.284 {parse ccyymmdd} {
+ clock scan {1971 Jan xxxi} -format {%Y %h %Od} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.285 {parse ccyymmdd} {
+ clock scan {1971 Jan 31} -format {%Y %h %e} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.286 {parse ccyymmdd} {
+ clock scan {1971 Jan xxxi} -format {%Y %h %Oe} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.287 {parse ccyymmdd} {
+ clock scan {1971 01 31} -format {%Y %m %d} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.288 {parse ccyymmdd} {
+ clock scan {1971 01 xxxi} -format {%Y %m %Od} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.289 {parse ccyymmdd} {
+ clock scan {1971 01 31} -format {%Y %m %e} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.290 {parse ccyymmdd} {
+ clock scan {1971 01 xxxi} -format {%Y %m %Oe} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.291 {parse ccyymmdd} {
+ clock scan {1971 i 31} -format {%Y %Om %d} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.292 {parse ccyymmdd} {
+ clock scan {1971 i xxxi} -format {%Y %Om %Od} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.293 {parse ccyymmdd} {
+ clock scan {1971 i 31} -format {%Y %Om %e} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.294 {parse ccyymmdd} {
+ clock scan {1971 i xxxi} -format {%Y %Om %Oe} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.295 {parse ccyymmdd} {
+ clock scan {1971 1 31} -format {%Y %N %d} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.296 {parse ccyymmdd} {
+ clock scan {1971 1 xxxi} -format {%Y %N %Od} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.297 {parse ccyymmdd} {
+ clock scan {1971 1 31} -format {%Y %N %e} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.298 {parse ccyymmdd} {
+ clock scan {1971 1 xxxi} -format {%Y %N %Oe} -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.299 {parse ccyymmdd} {
+ clock scan 01/31/1971 -format %x -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.300 {parse ccyymmdd} {
+ clock scan 01/31/1971 -format %D -locale en_US_roman -gmt 1
+} 34128000
+test clock-8.301 {parse ccyymmdd} {
+ clock scan {1971 Dec 02} -format {%C%y %b %d} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.302 {parse ccyymmdd} {
+ clock scan {1971 Dec ii} -format {%C%y %b %Od} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.303 {parse ccyymmdd} {
+ clock scan {1971 Dec 2} -format {%C%y %b %e} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.304 {parse ccyymmdd} {
+ clock scan {1971 Dec ii} -format {%C%y %b %Oe} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.305 {parse ccyymmdd} {
+ clock scan {1971 December 02} -format {%C%y %B %d} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.306 {parse ccyymmdd} {
+ clock scan {1971 December ii} -format {%C%y %B %Od} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.307 {parse ccyymmdd} {
+ clock scan {1971 December 2} -format {%C%y %B %e} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.308 {parse ccyymmdd} {
+ clock scan {1971 December ii} -format {%C%y %B %Oe} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.309 {parse ccyymmdd} {
+ clock scan {1971 Dec 02} -format {%C%y %h %d} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.310 {parse ccyymmdd} {
+ clock scan {1971 Dec ii} -format {%C%y %h %Od} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.311 {parse ccyymmdd} {
+ clock scan {1971 Dec 2} -format {%C%y %h %e} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.312 {parse ccyymmdd} {
+ clock scan {1971 Dec ii} -format {%C%y %h %Oe} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.313 {parse ccyymmdd} {
+ clock scan {1971 12 02} -format {%C%y %m %d} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.314 {parse ccyymmdd} {
+ clock scan {1971 12 ii} -format {%C%y %m %Od} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.315 {parse ccyymmdd} {
+ clock scan {1971 12 2} -format {%C%y %m %e} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.316 {parse ccyymmdd} {
+ clock scan {1971 12 ii} -format {%C%y %m %Oe} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.317 {parse ccyymmdd} {
+ clock scan {1971 xii 02} -format {%C%y %Om %d} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.318 {parse ccyymmdd} {
+ clock scan {1971 xii ii} -format {%C%y %Om %Od} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.319 {parse ccyymmdd} {
+ clock scan {1971 xii 2} -format {%C%y %Om %e} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.320 {parse ccyymmdd} {
+ clock scan {1971 xii ii} -format {%C%y %Om %Oe} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.321 {parse ccyymmdd} {
+ clock scan {1971 12 02} -format {%C%y %N %d} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.322 {parse ccyymmdd} {
+ clock scan {1971 12 ii} -format {%C%y %N %Od} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.323 {parse ccyymmdd} {
+ clock scan {1971 12 2} -format {%C%y %N %e} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.324 {parse ccyymmdd} {
+ clock scan {1971 12 ii} -format {%C%y %N %Oe} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.325 {parse ccyymmdd} {
+ clock scan {1971 Dec 02} -format {%Y %b %d} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.326 {parse ccyymmdd} {
+ clock scan {1971 Dec ii} -format {%Y %b %Od} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.327 {parse ccyymmdd} {
+ clock scan {1971 Dec 2} -format {%Y %b %e} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.328 {parse ccyymmdd} {
+ clock scan {1971 Dec ii} -format {%Y %b %Oe} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.329 {parse ccyymmdd} {
+ clock scan {1971 December 02} -format {%Y %B %d} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.330 {parse ccyymmdd} {
+ clock scan {1971 December ii} -format {%Y %B %Od} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.331 {parse ccyymmdd} {
+ clock scan {1971 December 2} -format {%Y %B %e} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.332 {parse ccyymmdd} {
+ clock scan {1971 December ii} -format {%Y %B %Oe} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.333 {parse ccyymmdd} {
+ clock scan {1971 Dec 02} -format {%Y %h %d} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.334 {parse ccyymmdd} {
+ clock scan {1971 Dec ii} -format {%Y %h %Od} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.335 {parse ccyymmdd} {
+ clock scan {1971 Dec 2} -format {%Y %h %e} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.336 {parse ccyymmdd} {
+ clock scan {1971 Dec ii} -format {%Y %h %Oe} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.337 {parse ccyymmdd} {
+ clock scan {1971 12 02} -format {%Y %m %d} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.338 {parse ccyymmdd} {
+ clock scan {1971 12 ii} -format {%Y %m %Od} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.339 {parse ccyymmdd} {
+ clock scan {1971 12 2} -format {%Y %m %e} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.340 {parse ccyymmdd} {
+ clock scan {1971 12 ii} -format {%Y %m %Oe} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.341 {parse ccyymmdd} {
+ clock scan {1971 xii 02} -format {%Y %Om %d} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.342 {parse ccyymmdd} {
+ clock scan {1971 xii ii} -format {%Y %Om %Od} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.343 {parse ccyymmdd} {
+ clock scan {1971 xii 2} -format {%Y %Om %e} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.344 {parse ccyymmdd} {
+ clock scan {1971 xii ii} -format {%Y %Om %Oe} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.345 {parse ccyymmdd} {
+ clock scan {1971 12 02} -format {%Y %N %d} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.346 {parse ccyymmdd} {
+ clock scan {1971 12 ii} -format {%Y %N %Od} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.347 {parse ccyymmdd} {
+ clock scan {1971 12 2} -format {%Y %N %e} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.348 {parse ccyymmdd} {
+ clock scan {1971 12 ii} -format {%Y %N %Oe} -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.349 {parse ccyymmdd} {
+ clock scan 12/02/1971 -format %x -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.350 {parse ccyymmdd} {
+ clock scan 12/02/1971 -format %D -locale en_US_roman -gmt 1
+} 60480000
+test clock-8.351 {parse ccyymmdd} {
+ clock scan {1971 Dec 31} -format {%C%y %b %d} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.352 {parse ccyymmdd} {
+ clock scan {1971 Dec xxxi} -format {%C%y %b %Od} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.353 {parse ccyymmdd} {
+ clock scan {1971 Dec 31} -format {%C%y %b %e} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.354 {parse ccyymmdd} {
+ clock scan {1971 Dec xxxi} -format {%C%y %b %Oe} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.355 {parse ccyymmdd} {
+ clock scan {1971 December 31} -format {%C%y %B %d} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.356 {parse ccyymmdd} {
+ clock scan {1971 December xxxi} -format {%C%y %B %Od} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.357 {parse ccyymmdd} {
+ clock scan {1971 December 31} -format {%C%y %B %e} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.358 {parse ccyymmdd} {
+ clock scan {1971 December xxxi} -format {%C%y %B %Oe} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.359 {parse ccyymmdd} {
+ clock scan {1971 Dec 31} -format {%C%y %h %d} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.360 {parse ccyymmdd} {
+ clock scan {1971 Dec xxxi} -format {%C%y %h %Od} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.361 {parse ccyymmdd} {
+ clock scan {1971 Dec 31} -format {%C%y %h %e} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.362 {parse ccyymmdd} {
+ clock scan {1971 Dec xxxi} -format {%C%y %h %Oe} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.363 {parse ccyymmdd} {
+ clock scan {1971 12 31} -format {%C%y %m %d} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.364 {parse ccyymmdd} {
+ clock scan {1971 12 xxxi} -format {%C%y %m %Od} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.365 {parse ccyymmdd} {
+ clock scan {1971 12 31} -format {%C%y %m %e} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.366 {parse ccyymmdd} {
+ clock scan {1971 12 xxxi} -format {%C%y %m %Oe} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.367 {parse ccyymmdd} {
+ clock scan {1971 xii 31} -format {%C%y %Om %d} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.368 {parse ccyymmdd} {
+ clock scan {1971 xii xxxi} -format {%C%y %Om %Od} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.369 {parse ccyymmdd} {
+ clock scan {1971 xii 31} -format {%C%y %Om %e} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.370 {parse ccyymmdd} {
+ clock scan {1971 xii xxxi} -format {%C%y %Om %Oe} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.371 {parse ccyymmdd} {
+ clock scan {1971 12 31} -format {%C%y %N %d} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.372 {parse ccyymmdd} {
+ clock scan {1971 12 xxxi} -format {%C%y %N %Od} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.373 {parse ccyymmdd} {
+ clock scan {1971 12 31} -format {%C%y %N %e} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.374 {parse ccyymmdd} {
+ clock scan {1971 12 xxxi} -format {%C%y %N %Oe} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.375 {parse ccyymmdd} {
+ clock scan {1971 Dec 31} -format {%Y %b %d} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.376 {parse ccyymmdd} {
+ clock scan {1971 Dec xxxi} -format {%Y %b %Od} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.377 {parse ccyymmdd} {
+ clock scan {1971 Dec 31} -format {%Y %b %e} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.378 {parse ccyymmdd} {
+ clock scan {1971 Dec xxxi} -format {%Y %b %Oe} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.379 {parse ccyymmdd} {
+ clock scan {1971 December 31} -format {%Y %B %d} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.380 {parse ccyymmdd} {
+ clock scan {1971 December xxxi} -format {%Y %B %Od} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.381 {parse ccyymmdd} {
+ clock scan {1971 December 31} -format {%Y %B %e} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.382 {parse ccyymmdd} {
+ clock scan {1971 December xxxi} -format {%Y %B %Oe} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.383 {parse ccyymmdd} {
+ clock scan {1971 Dec 31} -format {%Y %h %d} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.384 {parse ccyymmdd} {
+ clock scan {1971 Dec xxxi} -format {%Y %h %Od} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.385 {parse ccyymmdd} {
+ clock scan {1971 Dec 31} -format {%Y %h %e} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.386 {parse ccyymmdd} {
+ clock scan {1971 Dec xxxi} -format {%Y %h %Oe} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.387 {parse ccyymmdd} {
+ clock scan {1971 12 31} -format {%Y %m %d} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.388 {parse ccyymmdd} {
+ clock scan {1971 12 xxxi} -format {%Y %m %Od} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.389 {parse ccyymmdd} {
+ clock scan {1971 12 31} -format {%Y %m %e} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.390 {parse ccyymmdd} {
+ clock scan {1971 12 xxxi} -format {%Y %m %Oe} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.391 {parse ccyymmdd} {
+ clock scan {1971 xii 31} -format {%Y %Om %d} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.392 {parse ccyymmdd} {
+ clock scan {1971 xii xxxi} -format {%Y %Om %Od} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.393 {parse ccyymmdd} {
+ clock scan {1971 xii 31} -format {%Y %Om %e} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.394 {parse ccyymmdd} {
+ clock scan {1971 xii xxxi} -format {%Y %Om %Oe} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.395 {parse ccyymmdd} {
+ clock scan {1971 12 31} -format {%Y %N %d} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.396 {parse ccyymmdd} {
+ clock scan {1971 12 xxxi} -format {%Y %N %Od} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.397 {parse ccyymmdd} {
+ clock scan {1971 12 31} -format {%Y %N %e} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.398 {parse ccyymmdd} {
+ clock scan {1971 12 xxxi} -format {%Y %N %Oe} -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.399 {parse ccyymmdd} {
+ clock scan 12/31/1971 -format %x -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.400 {parse ccyymmdd} {
+ clock scan 12/31/1971 -format %D -locale en_US_roman -gmt 1
+} 62985600
+test clock-8.401 {parse ccyymmdd} {
+ clock scan {2000 Jan 02} -format {%C%y %b %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.402 {parse ccyymmdd} {
+ clock scan {2000 Jan ii} -format {%C%y %b %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.403 {parse ccyymmdd} {
+ clock scan {2000 Jan 2} -format {%C%y %b %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.404 {parse ccyymmdd} {
+ clock scan {2000 Jan ii} -format {%C%y %b %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.405 {parse ccyymmdd} {
+ clock scan {2000 January 02} -format {%C%y %B %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.406 {parse ccyymmdd} {
+ clock scan {2000 January ii} -format {%C%y %B %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.407 {parse ccyymmdd} {
+ clock scan {2000 January 2} -format {%C%y %B %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.408 {parse ccyymmdd} {
+ clock scan {2000 January ii} -format {%C%y %B %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.409 {parse ccyymmdd} {
+ clock scan {2000 Jan 02} -format {%C%y %h %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.410 {parse ccyymmdd} {
+ clock scan {2000 Jan ii} -format {%C%y %h %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.411 {parse ccyymmdd} {
+ clock scan {2000 Jan 2} -format {%C%y %h %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.412 {parse ccyymmdd} {
+ clock scan {2000 Jan ii} -format {%C%y %h %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.413 {parse ccyymmdd} {
+ clock scan {2000 01 02} -format {%C%y %m %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.414 {parse ccyymmdd} {
+ clock scan {2000 01 ii} -format {%C%y %m %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.415 {parse ccyymmdd} {
+ clock scan {2000 01 2} -format {%C%y %m %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.416 {parse ccyymmdd} {
+ clock scan {2000 01 ii} -format {%C%y %m %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.417 {parse ccyymmdd} {
+ clock scan {2000 i 02} -format {%C%y %Om %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.418 {parse ccyymmdd} {
+ clock scan {2000 i ii} -format {%C%y %Om %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.419 {parse ccyymmdd} {
+ clock scan {2000 i 2} -format {%C%y %Om %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.420 {parse ccyymmdd} {
+ clock scan {2000 i ii} -format {%C%y %Om %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.421 {parse ccyymmdd} {
+ clock scan {2000 1 02} -format {%C%y %N %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.422 {parse ccyymmdd} {
+ clock scan {2000 1 ii} -format {%C%y %N %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.423 {parse ccyymmdd} {
+ clock scan {2000 1 2} -format {%C%y %N %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.424 {parse ccyymmdd} {
+ clock scan {2000 1 ii} -format {%C%y %N %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.425 {parse ccyymmdd} {
+ clock scan {2000 Jan 02} -format {%Y %b %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.426 {parse ccyymmdd} {
+ clock scan {2000 Jan ii} -format {%Y %b %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.427 {parse ccyymmdd} {
+ clock scan {2000 Jan 2} -format {%Y %b %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.428 {parse ccyymmdd} {
+ clock scan {2000 Jan ii} -format {%Y %b %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.429 {parse ccyymmdd} {
+ clock scan {2000 January 02} -format {%Y %B %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.430 {parse ccyymmdd} {
+ clock scan {2000 January ii} -format {%Y %B %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.431 {parse ccyymmdd} {
+ clock scan {2000 January 2} -format {%Y %B %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.432 {parse ccyymmdd} {
+ clock scan {2000 January ii} -format {%Y %B %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.433 {parse ccyymmdd} {
+ clock scan {2000 Jan 02} -format {%Y %h %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.434 {parse ccyymmdd} {
+ clock scan {2000 Jan ii} -format {%Y %h %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.435 {parse ccyymmdd} {
+ clock scan {2000 Jan 2} -format {%Y %h %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.436 {parse ccyymmdd} {
+ clock scan {2000 Jan ii} -format {%Y %h %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.437 {parse ccyymmdd} {
+ clock scan {2000 01 02} -format {%Y %m %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.438 {parse ccyymmdd} {
+ clock scan {2000 01 ii} -format {%Y %m %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.439 {parse ccyymmdd} {
+ clock scan {2000 01 2} -format {%Y %m %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.440 {parse ccyymmdd} {
+ clock scan {2000 01 ii} -format {%Y %m %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.441 {parse ccyymmdd} {
+ clock scan {2000 i 02} -format {%Y %Om %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.442 {parse ccyymmdd} {
+ clock scan {2000 i ii} -format {%Y %Om %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.443 {parse ccyymmdd} {
+ clock scan {2000 i 2} -format {%Y %Om %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.444 {parse ccyymmdd} {
+ clock scan {2000 i ii} -format {%Y %Om %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.445 {parse ccyymmdd} {
+ clock scan {2000 1 02} -format {%Y %N %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.446 {parse ccyymmdd} {
+ clock scan {2000 1 ii} -format {%Y %N %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.447 {parse ccyymmdd} {
+ clock scan {2000 1 2} -format {%Y %N %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.448 {parse ccyymmdd} {
+ clock scan {2000 1 ii} -format {%Y %N %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.449 {parse ccyymmdd} {
+ clock scan 01/02/2000 -format %x -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.450 {parse ccyymmdd} {
+ clock scan 01/02/2000 -format %D -locale en_US_roman -gmt 1
+} 946771200
+test clock-8.451 {parse ccyymmdd} {
+ clock scan {2000 Jan 31} -format {%C%y %b %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.452 {parse ccyymmdd} {
+ clock scan {2000 Jan xxxi} -format {%C%y %b %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.453 {parse ccyymmdd} {
+ clock scan {2000 Jan 31} -format {%C%y %b %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.454 {parse ccyymmdd} {
+ clock scan {2000 Jan xxxi} -format {%C%y %b %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.455 {parse ccyymmdd} {
+ clock scan {2000 January 31} -format {%C%y %B %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.456 {parse ccyymmdd} {
+ clock scan {2000 January xxxi} -format {%C%y %B %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.457 {parse ccyymmdd} {
+ clock scan {2000 January 31} -format {%C%y %B %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.458 {parse ccyymmdd} {
+ clock scan {2000 January xxxi} -format {%C%y %B %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.459 {parse ccyymmdd} {
+ clock scan {2000 Jan 31} -format {%C%y %h %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.460 {parse ccyymmdd} {
+ clock scan {2000 Jan xxxi} -format {%C%y %h %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.461 {parse ccyymmdd} {
+ clock scan {2000 Jan 31} -format {%C%y %h %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.462 {parse ccyymmdd} {
+ clock scan {2000 Jan xxxi} -format {%C%y %h %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.463 {parse ccyymmdd} {
+ clock scan {2000 01 31} -format {%C%y %m %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.464 {parse ccyymmdd} {
+ clock scan {2000 01 xxxi} -format {%C%y %m %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.465 {parse ccyymmdd} {
+ clock scan {2000 01 31} -format {%C%y %m %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.466 {parse ccyymmdd} {
+ clock scan {2000 01 xxxi} -format {%C%y %m %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.467 {parse ccyymmdd} {
+ clock scan {2000 i 31} -format {%C%y %Om %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.468 {parse ccyymmdd} {
+ clock scan {2000 i xxxi} -format {%C%y %Om %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.469 {parse ccyymmdd} {
+ clock scan {2000 i 31} -format {%C%y %Om %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.470 {parse ccyymmdd} {
+ clock scan {2000 i xxxi} -format {%C%y %Om %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.471 {parse ccyymmdd} {
+ clock scan {2000 1 31} -format {%C%y %N %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.472 {parse ccyymmdd} {
+ clock scan {2000 1 xxxi} -format {%C%y %N %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.473 {parse ccyymmdd} {
+ clock scan {2000 1 31} -format {%C%y %N %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.474 {parse ccyymmdd} {
+ clock scan {2000 1 xxxi} -format {%C%y %N %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.475 {parse ccyymmdd} {
+ clock scan {2000 Jan 31} -format {%Y %b %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.476 {parse ccyymmdd} {
+ clock scan {2000 Jan xxxi} -format {%Y %b %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.477 {parse ccyymmdd} {
+ clock scan {2000 Jan 31} -format {%Y %b %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.478 {parse ccyymmdd} {
+ clock scan {2000 Jan xxxi} -format {%Y %b %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.479 {parse ccyymmdd} {
+ clock scan {2000 January 31} -format {%Y %B %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.480 {parse ccyymmdd} {
+ clock scan {2000 January xxxi} -format {%Y %B %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.481 {parse ccyymmdd} {
+ clock scan {2000 January 31} -format {%Y %B %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.482 {parse ccyymmdd} {
+ clock scan {2000 January xxxi} -format {%Y %B %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.483 {parse ccyymmdd} {
+ clock scan {2000 Jan 31} -format {%Y %h %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.484 {parse ccyymmdd} {
+ clock scan {2000 Jan xxxi} -format {%Y %h %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.485 {parse ccyymmdd} {
+ clock scan {2000 Jan 31} -format {%Y %h %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.486 {parse ccyymmdd} {
+ clock scan {2000 Jan xxxi} -format {%Y %h %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.487 {parse ccyymmdd} {
+ clock scan {2000 01 31} -format {%Y %m %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.488 {parse ccyymmdd} {
+ clock scan {2000 01 xxxi} -format {%Y %m %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.489 {parse ccyymmdd} {
+ clock scan {2000 01 31} -format {%Y %m %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.490 {parse ccyymmdd} {
+ clock scan {2000 01 xxxi} -format {%Y %m %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.491 {parse ccyymmdd} {
+ clock scan {2000 i 31} -format {%Y %Om %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.492 {parse ccyymmdd} {
+ clock scan {2000 i xxxi} -format {%Y %Om %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.493 {parse ccyymmdd} {
+ clock scan {2000 i 31} -format {%Y %Om %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.494 {parse ccyymmdd} {
+ clock scan {2000 i xxxi} -format {%Y %Om %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.495 {parse ccyymmdd} {
+ clock scan {2000 1 31} -format {%Y %N %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.496 {parse ccyymmdd} {
+ clock scan {2000 1 xxxi} -format {%Y %N %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.497 {parse ccyymmdd} {
+ clock scan {2000 1 31} -format {%Y %N %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.498 {parse ccyymmdd} {
+ clock scan {2000 1 xxxi} -format {%Y %N %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.499 {parse ccyymmdd} {
+ clock scan 01/31/2000 -format %x -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.500 {parse ccyymmdd} {
+ clock scan 01/31/2000 -format %D -locale en_US_roman -gmt 1
+} 949276800
+test clock-8.501 {parse ccyymmdd} {
+ clock scan {2000 Dec 02} -format {%C%y %b %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.502 {parse ccyymmdd} {
+ clock scan {2000 Dec ii} -format {%C%y %b %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.503 {parse ccyymmdd} {
+ clock scan {2000 Dec 2} -format {%C%y %b %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.504 {parse ccyymmdd} {
+ clock scan {2000 Dec ii} -format {%C%y %b %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.505 {parse ccyymmdd} {
+ clock scan {2000 December 02} -format {%C%y %B %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.506 {parse ccyymmdd} {
+ clock scan {2000 December ii} -format {%C%y %B %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.507 {parse ccyymmdd} {
+ clock scan {2000 December 2} -format {%C%y %B %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.508 {parse ccyymmdd} {
+ clock scan {2000 December ii} -format {%C%y %B %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.509 {parse ccyymmdd} {
+ clock scan {2000 Dec 02} -format {%C%y %h %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.510 {parse ccyymmdd} {
+ clock scan {2000 Dec ii} -format {%C%y %h %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.511 {parse ccyymmdd} {
+ clock scan {2000 Dec 2} -format {%C%y %h %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.512 {parse ccyymmdd} {
+ clock scan {2000 Dec ii} -format {%C%y %h %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.513 {parse ccyymmdd} {
+ clock scan {2000 12 02} -format {%C%y %m %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.514 {parse ccyymmdd} {
+ clock scan {2000 12 ii} -format {%C%y %m %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.515 {parse ccyymmdd} {
+ clock scan {2000 12 2} -format {%C%y %m %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.516 {parse ccyymmdd} {
+ clock scan {2000 12 ii} -format {%C%y %m %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.517 {parse ccyymmdd} {
+ clock scan {2000 xii 02} -format {%C%y %Om %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.518 {parse ccyymmdd} {
+ clock scan {2000 xii ii} -format {%C%y %Om %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.519 {parse ccyymmdd} {
+ clock scan {2000 xii 2} -format {%C%y %Om %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.520 {parse ccyymmdd} {
+ clock scan {2000 xii ii} -format {%C%y %Om %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.521 {parse ccyymmdd} {
+ clock scan {2000 12 02} -format {%C%y %N %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.522 {parse ccyymmdd} {
+ clock scan {2000 12 ii} -format {%C%y %N %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.523 {parse ccyymmdd} {
+ clock scan {2000 12 2} -format {%C%y %N %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.524 {parse ccyymmdd} {
+ clock scan {2000 12 ii} -format {%C%y %N %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.525 {parse ccyymmdd} {
+ clock scan {2000 Dec 02} -format {%Y %b %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.526 {parse ccyymmdd} {
+ clock scan {2000 Dec ii} -format {%Y %b %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.527 {parse ccyymmdd} {
+ clock scan {2000 Dec 2} -format {%Y %b %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.528 {parse ccyymmdd} {
+ clock scan {2000 Dec ii} -format {%Y %b %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.529 {parse ccyymmdd} {
+ clock scan {2000 December 02} -format {%Y %B %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.530 {parse ccyymmdd} {
+ clock scan {2000 December ii} -format {%Y %B %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.531 {parse ccyymmdd} {
+ clock scan {2000 December 2} -format {%Y %B %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.532 {parse ccyymmdd} {
+ clock scan {2000 December ii} -format {%Y %B %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.533 {parse ccyymmdd} {
+ clock scan {2000 Dec 02} -format {%Y %h %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.534 {parse ccyymmdd} {
+ clock scan {2000 Dec ii} -format {%Y %h %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.535 {parse ccyymmdd} {
+ clock scan {2000 Dec 2} -format {%Y %h %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.536 {parse ccyymmdd} {
+ clock scan {2000 Dec ii} -format {%Y %h %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.537 {parse ccyymmdd} {
+ clock scan {2000 12 02} -format {%Y %m %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.538 {parse ccyymmdd} {
+ clock scan {2000 12 ii} -format {%Y %m %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.539 {parse ccyymmdd} {
+ clock scan {2000 12 2} -format {%Y %m %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.540 {parse ccyymmdd} {
+ clock scan {2000 12 ii} -format {%Y %m %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.541 {parse ccyymmdd} {
+ clock scan {2000 xii 02} -format {%Y %Om %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.542 {parse ccyymmdd} {
+ clock scan {2000 xii ii} -format {%Y %Om %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.543 {parse ccyymmdd} {
+ clock scan {2000 xii 2} -format {%Y %Om %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.544 {parse ccyymmdd} {
+ clock scan {2000 xii ii} -format {%Y %Om %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.545 {parse ccyymmdd} {
+ clock scan {2000 12 02} -format {%Y %N %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.546 {parse ccyymmdd} {
+ clock scan {2000 12 ii} -format {%Y %N %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.547 {parse ccyymmdd} {
+ clock scan {2000 12 2} -format {%Y %N %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.548 {parse ccyymmdd} {
+ clock scan {2000 12 ii} -format {%Y %N %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.549 {parse ccyymmdd} {
+ clock scan 12/02/2000 -format %x -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.550 {parse ccyymmdd} {
+ clock scan 12/02/2000 -format %D -locale en_US_roman -gmt 1
+} 975715200
+test clock-8.551 {parse ccyymmdd} {
+ clock scan {2000 Dec 31} -format {%C%y %b %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.552 {parse ccyymmdd} {
+ clock scan {2000 Dec xxxi} -format {%C%y %b %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.553 {parse ccyymmdd} {
+ clock scan {2000 Dec 31} -format {%C%y %b %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.554 {parse ccyymmdd} {
+ clock scan {2000 Dec xxxi} -format {%C%y %b %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.555 {parse ccyymmdd} {
+ clock scan {2000 December 31} -format {%C%y %B %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.556 {parse ccyymmdd} {
+ clock scan {2000 December xxxi} -format {%C%y %B %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.557 {parse ccyymmdd} {
+ clock scan {2000 December 31} -format {%C%y %B %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.558 {parse ccyymmdd} {
+ clock scan {2000 December xxxi} -format {%C%y %B %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.559 {parse ccyymmdd} {
+ clock scan {2000 Dec 31} -format {%C%y %h %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.560 {parse ccyymmdd} {
+ clock scan {2000 Dec xxxi} -format {%C%y %h %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.561 {parse ccyymmdd} {
+ clock scan {2000 Dec 31} -format {%C%y %h %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.562 {parse ccyymmdd} {
+ clock scan {2000 Dec xxxi} -format {%C%y %h %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.563 {parse ccyymmdd} {
+ clock scan {2000 12 31} -format {%C%y %m %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.564 {parse ccyymmdd} {
+ clock scan {2000 12 xxxi} -format {%C%y %m %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.565 {parse ccyymmdd} {
+ clock scan {2000 12 31} -format {%C%y %m %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.566 {parse ccyymmdd} {
+ clock scan {2000 12 xxxi} -format {%C%y %m %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.567 {parse ccyymmdd} {
+ clock scan {2000 xii 31} -format {%C%y %Om %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.568 {parse ccyymmdd} {
+ clock scan {2000 xii xxxi} -format {%C%y %Om %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.569 {parse ccyymmdd} {
+ clock scan {2000 xii 31} -format {%C%y %Om %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.570 {parse ccyymmdd} {
+ clock scan {2000 xii xxxi} -format {%C%y %Om %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.571 {parse ccyymmdd} {
+ clock scan {2000 12 31} -format {%C%y %N %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.572 {parse ccyymmdd} {
+ clock scan {2000 12 xxxi} -format {%C%y %N %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.573 {parse ccyymmdd} {
+ clock scan {2000 12 31} -format {%C%y %N %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.574 {parse ccyymmdd} {
+ clock scan {2000 12 xxxi} -format {%C%y %N %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.575 {parse ccyymmdd} {
+ clock scan {2000 Dec 31} -format {%Y %b %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.576 {parse ccyymmdd} {
+ clock scan {2000 Dec xxxi} -format {%Y %b %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.577 {parse ccyymmdd} {
+ clock scan {2000 Dec 31} -format {%Y %b %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.578 {parse ccyymmdd} {
+ clock scan {2000 Dec xxxi} -format {%Y %b %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.579 {parse ccyymmdd} {
+ clock scan {2000 December 31} -format {%Y %B %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.580 {parse ccyymmdd} {
+ clock scan {2000 December xxxi} -format {%Y %B %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.581 {parse ccyymmdd} {
+ clock scan {2000 December 31} -format {%Y %B %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.582 {parse ccyymmdd} {
+ clock scan {2000 December xxxi} -format {%Y %B %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.583 {parse ccyymmdd} {
+ clock scan {2000 Dec 31} -format {%Y %h %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.584 {parse ccyymmdd} {
+ clock scan {2000 Dec xxxi} -format {%Y %h %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.585 {parse ccyymmdd} {
+ clock scan {2000 Dec 31} -format {%Y %h %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.586 {parse ccyymmdd} {
+ clock scan {2000 Dec xxxi} -format {%Y %h %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.587 {parse ccyymmdd} {
+ clock scan {2000 12 31} -format {%Y %m %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.588 {parse ccyymmdd} {
+ clock scan {2000 12 xxxi} -format {%Y %m %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.589 {parse ccyymmdd} {
+ clock scan {2000 12 31} -format {%Y %m %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.590 {parse ccyymmdd} {
+ clock scan {2000 12 xxxi} -format {%Y %m %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.591 {parse ccyymmdd} {
+ clock scan {2000 xii 31} -format {%Y %Om %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.592 {parse ccyymmdd} {
+ clock scan {2000 xii xxxi} -format {%Y %Om %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.593 {parse ccyymmdd} {
+ clock scan {2000 xii 31} -format {%Y %Om %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.594 {parse ccyymmdd} {
+ clock scan {2000 xii xxxi} -format {%Y %Om %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.595 {parse ccyymmdd} {
+ clock scan {2000 12 31} -format {%Y %N %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.596 {parse ccyymmdd} {
+ clock scan {2000 12 xxxi} -format {%Y %N %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.597 {parse ccyymmdd} {
+ clock scan {2000 12 31} -format {%Y %N %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.598 {parse ccyymmdd} {
+ clock scan {2000 12 xxxi} -format {%Y %N %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.599 {parse ccyymmdd} {
+ clock scan 12/31/2000 -format %x -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.600 {parse ccyymmdd} {
+ clock scan 12/31/2000 -format %D -locale en_US_roman -gmt 1
+} 978220800
+test clock-8.601 {parse ccyymmdd} {
+ clock scan {2001 Jan 02} -format {%C%y %b %d} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.602 {parse ccyymmdd} {
+ clock scan {2001 Jan ii} -format {%C%y %b %Od} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.603 {parse ccyymmdd} {
+ clock scan {2001 Jan 2} -format {%C%y %b %e} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.604 {parse ccyymmdd} {
+ clock scan {2001 Jan ii} -format {%C%y %b %Oe} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.605 {parse ccyymmdd} {
+ clock scan {2001 January 02} -format {%C%y %B %d} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.606 {parse ccyymmdd} {
+ clock scan {2001 January ii} -format {%C%y %B %Od} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.607 {parse ccyymmdd} {
+ clock scan {2001 January 2} -format {%C%y %B %e} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.608 {parse ccyymmdd} {
+ clock scan {2001 January ii} -format {%C%y %B %Oe} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.609 {parse ccyymmdd} {
+ clock scan {2001 Jan 02} -format {%C%y %h %d} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.610 {parse ccyymmdd} {
+ clock scan {2001 Jan ii} -format {%C%y %h %Od} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.611 {parse ccyymmdd} {
+ clock scan {2001 Jan 2} -format {%C%y %h %e} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.612 {parse ccyymmdd} {
+ clock scan {2001 Jan ii} -format {%C%y %h %Oe} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.613 {parse ccyymmdd} {
+ clock scan {2001 01 02} -format {%C%y %m %d} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.614 {parse ccyymmdd} {
+ clock scan {2001 01 ii} -format {%C%y %m %Od} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.615 {parse ccyymmdd} {
+ clock scan {2001 01 2} -format {%C%y %m %e} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.616 {parse ccyymmdd} {
+ clock scan {2001 01 ii} -format {%C%y %m %Oe} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.617 {parse ccyymmdd} {
+ clock scan {2001 i 02} -format {%C%y %Om %d} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.618 {parse ccyymmdd} {
+ clock scan {2001 i ii} -format {%C%y %Om %Od} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.619 {parse ccyymmdd} {
+ clock scan {2001 i 2} -format {%C%y %Om %e} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.620 {parse ccyymmdd} {
+ clock scan {2001 i ii} -format {%C%y %Om %Oe} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.621 {parse ccyymmdd} {
+ clock scan {2001 1 02} -format {%C%y %N %d} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.622 {parse ccyymmdd} {
+ clock scan {2001 1 ii} -format {%C%y %N %Od} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.623 {parse ccyymmdd} {
+ clock scan {2001 1 2} -format {%C%y %N %e} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.624 {parse ccyymmdd} {
+ clock scan {2001 1 ii} -format {%C%y %N %Oe} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.625 {parse ccyymmdd} {
+ clock scan {2001 Jan 02} -format {%Y %b %d} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.626 {parse ccyymmdd} {
+ clock scan {2001 Jan ii} -format {%Y %b %Od} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.627 {parse ccyymmdd} {
+ clock scan {2001 Jan 2} -format {%Y %b %e} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.628 {parse ccyymmdd} {
+ clock scan {2001 Jan ii} -format {%Y %b %Oe} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.629 {parse ccyymmdd} {
+ clock scan {2001 January 02} -format {%Y %B %d} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.630 {parse ccyymmdd} {
+ clock scan {2001 January ii} -format {%Y %B %Od} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.631 {parse ccyymmdd} {
+ clock scan {2001 January 2} -format {%Y %B %e} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.632 {parse ccyymmdd} {
+ clock scan {2001 January ii} -format {%Y %B %Oe} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.633 {parse ccyymmdd} {
+ clock scan {2001 Jan 02} -format {%Y %h %d} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.634 {parse ccyymmdd} {
+ clock scan {2001 Jan ii} -format {%Y %h %Od} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.635 {parse ccyymmdd} {
+ clock scan {2001 Jan 2} -format {%Y %h %e} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.636 {parse ccyymmdd} {
+ clock scan {2001 Jan ii} -format {%Y %h %Oe} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.637 {parse ccyymmdd} {
+ clock scan {2001 01 02} -format {%Y %m %d} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.638 {parse ccyymmdd} {
+ clock scan {2001 01 ii} -format {%Y %m %Od} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.639 {parse ccyymmdd} {
+ clock scan {2001 01 2} -format {%Y %m %e} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.640 {parse ccyymmdd} {
+ clock scan {2001 01 ii} -format {%Y %m %Oe} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.641 {parse ccyymmdd} {
+ clock scan {2001 i 02} -format {%Y %Om %d} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.642 {parse ccyymmdd} {
+ clock scan {2001 i ii} -format {%Y %Om %Od} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.643 {parse ccyymmdd} {
+ clock scan {2001 i 2} -format {%Y %Om %e} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.644 {parse ccyymmdd} {
+ clock scan {2001 i ii} -format {%Y %Om %Oe} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.645 {parse ccyymmdd} {
+ clock scan {2001 1 02} -format {%Y %N %d} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.646 {parse ccyymmdd} {
+ clock scan {2001 1 ii} -format {%Y %N %Od} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.647 {parse ccyymmdd} {
+ clock scan {2001 1 2} -format {%Y %N %e} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.648 {parse ccyymmdd} {
+ clock scan {2001 1 ii} -format {%Y %N %Oe} -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.649 {parse ccyymmdd} {
+ clock scan 01/02/2001 -format %x -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.650 {parse ccyymmdd} {
+ clock scan 01/02/2001 -format %D -locale en_US_roman -gmt 1
+} 978393600
+test clock-8.651 {parse ccyymmdd} {
+ clock scan {2001 Jan 31} -format {%C%y %b %d} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.652 {parse ccyymmdd} {
+ clock scan {2001 Jan xxxi} -format {%C%y %b %Od} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.653 {parse ccyymmdd} {
+ clock scan {2001 Jan 31} -format {%C%y %b %e} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.654 {parse ccyymmdd} {
+ clock scan {2001 Jan xxxi} -format {%C%y %b %Oe} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.655 {parse ccyymmdd} {
+ clock scan {2001 January 31} -format {%C%y %B %d} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.656 {parse ccyymmdd} {
+ clock scan {2001 January xxxi} -format {%C%y %B %Od} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.657 {parse ccyymmdd} {
+ clock scan {2001 January 31} -format {%C%y %B %e} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.658 {parse ccyymmdd} {
+ clock scan {2001 January xxxi} -format {%C%y %B %Oe} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.659 {parse ccyymmdd} {
+ clock scan {2001 Jan 31} -format {%C%y %h %d} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.660 {parse ccyymmdd} {
+ clock scan {2001 Jan xxxi} -format {%C%y %h %Od} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.661 {parse ccyymmdd} {
+ clock scan {2001 Jan 31} -format {%C%y %h %e} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.662 {parse ccyymmdd} {
+ clock scan {2001 Jan xxxi} -format {%C%y %h %Oe} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.663 {parse ccyymmdd} {
+ clock scan {2001 01 31} -format {%C%y %m %d} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.664 {parse ccyymmdd} {
+ clock scan {2001 01 xxxi} -format {%C%y %m %Od} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.665 {parse ccyymmdd} {
+ clock scan {2001 01 31} -format {%C%y %m %e} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.666 {parse ccyymmdd} {
+ clock scan {2001 01 xxxi} -format {%C%y %m %Oe} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.667 {parse ccyymmdd} {
+ clock scan {2001 i 31} -format {%C%y %Om %d} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.668 {parse ccyymmdd} {
+ clock scan {2001 i xxxi} -format {%C%y %Om %Od} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.669 {parse ccyymmdd} {
+ clock scan {2001 i 31} -format {%C%y %Om %e} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.670 {parse ccyymmdd} {
+ clock scan {2001 i xxxi} -format {%C%y %Om %Oe} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.671 {parse ccyymmdd} {
+ clock scan {2001 1 31} -format {%C%y %N %d} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.672 {parse ccyymmdd} {
+ clock scan {2001 1 xxxi} -format {%C%y %N %Od} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.673 {parse ccyymmdd} {
+ clock scan {2001 1 31} -format {%C%y %N %e} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.674 {parse ccyymmdd} {
+ clock scan {2001 1 xxxi} -format {%C%y %N %Oe} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.675 {parse ccyymmdd} {
+ clock scan {2001 Jan 31} -format {%Y %b %d} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.676 {parse ccyymmdd} {
+ clock scan {2001 Jan xxxi} -format {%Y %b %Od} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.677 {parse ccyymmdd} {
+ clock scan {2001 Jan 31} -format {%Y %b %e} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.678 {parse ccyymmdd} {
+ clock scan {2001 Jan xxxi} -format {%Y %b %Oe} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.679 {parse ccyymmdd} {
+ clock scan {2001 January 31} -format {%Y %B %d} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.680 {parse ccyymmdd} {
+ clock scan {2001 January xxxi} -format {%Y %B %Od} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.681 {parse ccyymmdd} {
+ clock scan {2001 January 31} -format {%Y %B %e} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.682 {parse ccyymmdd} {
+ clock scan {2001 January xxxi} -format {%Y %B %Oe} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.683 {parse ccyymmdd} {
+ clock scan {2001 Jan 31} -format {%Y %h %d} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.684 {parse ccyymmdd} {
+ clock scan {2001 Jan xxxi} -format {%Y %h %Od} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.685 {parse ccyymmdd} {
+ clock scan {2001 Jan 31} -format {%Y %h %e} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.686 {parse ccyymmdd} {
+ clock scan {2001 Jan xxxi} -format {%Y %h %Oe} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.687 {parse ccyymmdd} {
+ clock scan {2001 01 31} -format {%Y %m %d} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.688 {parse ccyymmdd} {
+ clock scan {2001 01 xxxi} -format {%Y %m %Od} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.689 {parse ccyymmdd} {
+ clock scan {2001 01 31} -format {%Y %m %e} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.690 {parse ccyymmdd} {
+ clock scan {2001 01 xxxi} -format {%Y %m %Oe} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.691 {parse ccyymmdd} {
+ clock scan {2001 i 31} -format {%Y %Om %d} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.692 {parse ccyymmdd} {
+ clock scan {2001 i xxxi} -format {%Y %Om %Od} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.693 {parse ccyymmdd} {
+ clock scan {2001 i 31} -format {%Y %Om %e} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.694 {parse ccyymmdd} {
+ clock scan {2001 i xxxi} -format {%Y %Om %Oe} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.695 {parse ccyymmdd} {
+ clock scan {2001 1 31} -format {%Y %N %d} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.696 {parse ccyymmdd} {
+ clock scan {2001 1 xxxi} -format {%Y %N %Od} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.697 {parse ccyymmdd} {
+ clock scan {2001 1 31} -format {%Y %N %e} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.698 {parse ccyymmdd} {
+ clock scan {2001 1 xxxi} -format {%Y %N %Oe} -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.699 {parse ccyymmdd} {
+ clock scan 01/31/2001 -format %x -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.700 {parse ccyymmdd} {
+ clock scan 01/31/2001 -format %D -locale en_US_roman -gmt 1
+} 980899200
+test clock-8.701 {parse ccyymmdd} {
+ clock scan {2001 Dec 02} -format {%C%y %b %d} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.702 {parse ccyymmdd} {
+ clock scan {2001 Dec ii} -format {%C%y %b %Od} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.703 {parse ccyymmdd} {
+ clock scan {2001 Dec 2} -format {%C%y %b %e} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.704 {parse ccyymmdd} {
+ clock scan {2001 Dec ii} -format {%C%y %b %Oe} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.705 {parse ccyymmdd} {
+ clock scan {2001 December 02} -format {%C%y %B %d} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.706 {parse ccyymmdd} {
+ clock scan {2001 December ii} -format {%C%y %B %Od} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.707 {parse ccyymmdd} {
+ clock scan {2001 December 2} -format {%C%y %B %e} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.708 {parse ccyymmdd} {
+ clock scan {2001 December ii} -format {%C%y %B %Oe} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.709 {parse ccyymmdd} {
+ clock scan {2001 Dec 02} -format {%C%y %h %d} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.710 {parse ccyymmdd} {
+ clock scan {2001 Dec ii} -format {%C%y %h %Od} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.711 {parse ccyymmdd} {
+ clock scan {2001 Dec 2} -format {%C%y %h %e} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.712 {parse ccyymmdd} {
+ clock scan {2001 Dec ii} -format {%C%y %h %Oe} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.713 {parse ccyymmdd} {
+ clock scan {2001 12 02} -format {%C%y %m %d} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.714 {parse ccyymmdd} {
+ clock scan {2001 12 ii} -format {%C%y %m %Od} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.715 {parse ccyymmdd} {
+ clock scan {2001 12 2} -format {%C%y %m %e} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.716 {parse ccyymmdd} {
+ clock scan {2001 12 ii} -format {%C%y %m %Oe} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.717 {parse ccyymmdd} {
+ clock scan {2001 xii 02} -format {%C%y %Om %d} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.718 {parse ccyymmdd} {
+ clock scan {2001 xii ii} -format {%C%y %Om %Od} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.719 {parse ccyymmdd} {
+ clock scan {2001 xii 2} -format {%C%y %Om %e} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.720 {parse ccyymmdd} {
+ clock scan {2001 xii ii} -format {%C%y %Om %Oe} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.721 {parse ccyymmdd} {
+ clock scan {2001 12 02} -format {%C%y %N %d} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.722 {parse ccyymmdd} {
+ clock scan {2001 12 ii} -format {%C%y %N %Od} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.723 {parse ccyymmdd} {
+ clock scan {2001 12 2} -format {%C%y %N %e} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.724 {parse ccyymmdd} {
+ clock scan {2001 12 ii} -format {%C%y %N %Oe} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.725 {parse ccyymmdd} {
+ clock scan {2001 Dec 02} -format {%Y %b %d} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.726 {parse ccyymmdd} {
+ clock scan {2001 Dec ii} -format {%Y %b %Od} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.727 {parse ccyymmdd} {
+ clock scan {2001 Dec 2} -format {%Y %b %e} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.728 {parse ccyymmdd} {
+ clock scan {2001 Dec ii} -format {%Y %b %Oe} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.729 {parse ccyymmdd} {
+ clock scan {2001 December 02} -format {%Y %B %d} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.730 {parse ccyymmdd} {
+ clock scan {2001 December ii} -format {%Y %B %Od} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.731 {parse ccyymmdd} {
+ clock scan {2001 December 2} -format {%Y %B %e} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.732 {parse ccyymmdd} {
+ clock scan {2001 December ii} -format {%Y %B %Oe} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.733 {parse ccyymmdd} {
+ clock scan {2001 Dec 02} -format {%Y %h %d} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.734 {parse ccyymmdd} {
+ clock scan {2001 Dec ii} -format {%Y %h %Od} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.735 {parse ccyymmdd} {
+ clock scan {2001 Dec 2} -format {%Y %h %e} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.736 {parse ccyymmdd} {
+ clock scan {2001 Dec ii} -format {%Y %h %Oe} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.737 {parse ccyymmdd} {
+ clock scan {2001 12 02} -format {%Y %m %d} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.738 {parse ccyymmdd} {
+ clock scan {2001 12 ii} -format {%Y %m %Od} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.739 {parse ccyymmdd} {
+ clock scan {2001 12 2} -format {%Y %m %e} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.740 {parse ccyymmdd} {
+ clock scan {2001 12 ii} -format {%Y %m %Oe} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.741 {parse ccyymmdd} {
+ clock scan {2001 xii 02} -format {%Y %Om %d} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.742 {parse ccyymmdd} {
+ clock scan {2001 xii ii} -format {%Y %Om %Od} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.743 {parse ccyymmdd} {
+ clock scan {2001 xii 2} -format {%Y %Om %e} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.744 {parse ccyymmdd} {
+ clock scan {2001 xii ii} -format {%Y %Om %Oe} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.745 {parse ccyymmdd} {
+ clock scan {2001 12 02} -format {%Y %N %d} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.746 {parse ccyymmdd} {
+ clock scan {2001 12 ii} -format {%Y %N %Od} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.747 {parse ccyymmdd} {
+ clock scan {2001 12 2} -format {%Y %N %e} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.748 {parse ccyymmdd} {
+ clock scan {2001 12 ii} -format {%Y %N %Oe} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.749 {parse ccyymmdd} {
+ clock scan 12/02/2001 -format %x -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.750 {parse ccyymmdd} {
+ clock scan 12/02/2001 -format %D -locale en_US_roman -gmt 1
+} 1007251200
+test clock-8.751 {parse ccyymmdd} {
+ clock scan {2001 Dec 31} -format {%C%y %b %d} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.752 {parse ccyymmdd} {
+ clock scan {2001 Dec xxxi} -format {%C%y %b %Od} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.753 {parse ccyymmdd} {
+ clock scan {2001 Dec 31} -format {%C%y %b %e} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.754 {parse ccyymmdd} {
+ clock scan {2001 Dec xxxi} -format {%C%y %b %Oe} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.755 {parse ccyymmdd} {
+ clock scan {2001 December 31} -format {%C%y %B %d} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.756 {parse ccyymmdd} {
+ clock scan {2001 December xxxi} -format {%C%y %B %Od} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.757 {parse ccyymmdd} {
+ clock scan {2001 December 31} -format {%C%y %B %e} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.758 {parse ccyymmdd} {
+ clock scan {2001 December xxxi} -format {%C%y %B %Oe} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.759 {parse ccyymmdd} {
+ clock scan {2001 Dec 31} -format {%C%y %h %d} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.760 {parse ccyymmdd} {
+ clock scan {2001 Dec xxxi} -format {%C%y %h %Od} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.761 {parse ccyymmdd} {
+ clock scan {2001 Dec 31} -format {%C%y %h %e} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.762 {parse ccyymmdd} {
+ clock scan {2001 Dec xxxi} -format {%C%y %h %Oe} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.763 {parse ccyymmdd} {
+ clock scan {2001 12 31} -format {%C%y %m %d} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.764 {parse ccyymmdd} {
+ clock scan {2001 12 xxxi} -format {%C%y %m %Od} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.765 {parse ccyymmdd} {
+ clock scan {2001 12 31} -format {%C%y %m %e} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.766 {parse ccyymmdd} {
+ clock scan {2001 12 xxxi} -format {%C%y %m %Oe} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.767 {parse ccyymmdd} {
+ clock scan {2001 xii 31} -format {%C%y %Om %d} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.768 {parse ccyymmdd} {
+ clock scan {2001 xii xxxi} -format {%C%y %Om %Od} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.769 {parse ccyymmdd} {
+ clock scan {2001 xii 31} -format {%C%y %Om %e} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.770 {parse ccyymmdd} {
+ clock scan {2001 xii xxxi} -format {%C%y %Om %Oe} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.771 {parse ccyymmdd} {
+ clock scan {2001 12 31} -format {%C%y %N %d} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.772 {parse ccyymmdd} {
+ clock scan {2001 12 xxxi} -format {%C%y %N %Od} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.773 {parse ccyymmdd} {
+ clock scan {2001 12 31} -format {%C%y %N %e} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.774 {parse ccyymmdd} {
+ clock scan {2001 12 xxxi} -format {%C%y %N %Oe} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.775 {parse ccyymmdd} {
+ clock scan {2001 Dec 31} -format {%Y %b %d} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.776 {parse ccyymmdd} {
+ clock scan {2001 Dec xxxi} -format {%Y %b %Od} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.777 {parse ccyymmdd} {
+ clock scan {2001 Dec 31} -format {%Y %b %e} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.778 {parse ccyymmdd} {
+ clock scan {2001 Dec xxxi} -format {%Y %b %Oe} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.779 {parse ccyymmdd} {
+ clock scan {2001 December 31} -format {%Y %B %d} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.780 {parse ccyymmdd} {
+ clock scan {2001 December xxxi} -format {%Y %B %Od} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.781 {parse ccyymmdd} {
+ clock scan {2001 December 31} -format {%Y %B %e} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.782 {parse ccyymmdd} {
+ clock scan {2001 December xxxi} -format {%Y %B %Oe} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.783 {parse ccyymmdd} {
+ clock scan {2001 Dec 31} -format {%Y %h %d} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.784 {parse ccyymmdd} {
+ clock scan {2001 Dec xxxi} -format {%Y %h %Od} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.785 {parse ccyymmdd} {
+ clock scan {2001 Dec 31} -format {%Y %h %e} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.786 {parse ccyymmdd} {
+ clock scan {2001 Dec xxxi} -format {%Y %h %Oe} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.787 {parse ccyymmdd} {
+ clock scan {2001 12 31} -format {%Y %m %d} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.788 {parse ccyymmdd} {
+ clock scan {2001 12 xxxi} -format {%Y %m %Od} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.789 {parse ccyymmdd} {
+ clock scan {2001 12 31} -format {%Y %m %e} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.790 {parse ccyymmdd} {
+ clock scan {2001 12 xxxi} -format {%Y %m %Oe} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.791 {parse ccyymmdd} {
+ clock scan {2001 xii 31} -format {%Y %Om %d} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.792 {parse ccyymmdd} {
+ clock scan {2001 xii xxxi} -format {%Y %Om %Od} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.793 {parse ccyymmdd} {
+ clock scan {2001 xii 31} -format {%Y %Om %e} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.794 {parse ccyymmdd} {
+ clock scan {2001 xii xxxi} -format {%Y %Om %Oe} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.795 {parse ccyymmdd} {
+ clock scan {2001 12 31} -format {%Y %N %d} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.796 {parse ccyymmdd} {
+ clock scan {2001 12 xxxi} -format {%Y %N %Od} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.797 {parse ccyymmdd} {
+ clock scan {2001 12 31} -format {%Y %N %e} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.798 {parse ccyymmdd} {
+ clock scan {2001 12 xxxi} -format {%Y %N %Oe} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.799 {parse ccyymmdd} {
+ clock scan 12/31/2001 -format %x -locale en_US_roman -gmt 1
+} 1009756800
+test clock-8.800 {parse ccyymmdd} {
+ clock scan 12/31/2001 -format %D -locale en_US_roman -gmt 1
+} 1009756800
+# END testcases8
+
+test clock-9.1 {seconds take precedence over ccyymmdd} {
+ clock scan {0 20000101} -format {%s %Y%m%d} -gmt true
+} 0
+
+test clock-9.2 {Julian day takes precedence over ccyymmdd} {
+ clock scan {2440588 20000101} -format {%J %Y%m%d} -gmt true
+} 0
+
+# Test parsing of ccyyddd
+
+test clock-10.1 {parse ccyyddd} {
+ clock scan {1970 001} -format {%Y %j} -locale en_US_roman -gmt 1
+} 0
+test clock-10.2 {parse ccyyddd} {
+ clock scan {1970 365} -format {%Y %j} -locale en_US_roman -gmt 1
+} 31449600
+test clock-10.3 {parse ccyyddd} {
+ clock scan {1971 001} -format {%Y %j} -locale en_US_roman -gmt 1
+} 31536000
+test clock-10.4 {parse ccyyddd} {
+ clock scan {1971 365} -format {%Y %j} -locale en_US_roman -gmt 1
+} 62985600
+test clock-10.5 {parse ccyyddd} {
+ clock scan {2000 001} -format {%Y %j} -locale en_US_roman -gmt 1
+} 946684800
+test clock-10.6 {parse ccyyddd} {
+ clock scan {2000 365} -format {%Y %j} -locale en_US_roman -gmt 1
+} 978134400
+test clock-10.7 {parse ccyyddd} {
+ clock scan {2001 001} -format {%Y %j} -locale en_US_roman -gmt 1
+} 978307200
+test clock-10.8 {parse ccyyddd} {
+ clock scan {2001 365} -format {%Y %j} -locale en_US_roman -gmt 1
+} 1009756800
+
+
+test clock-10.9 {seconds take precedence over ccyyddd} {
+ list [clock scan {0 2000001} -format {%s %Y%j} -gmt true] \
+ [clock scan {2000001 0} -format {%Y%j %s} -gmt true]
+} {0 0}
+test clock-10.10 {julian day takes precedence over ccyyddd} {
+ list [clock scan {2440588 2000001} -format {%J %Y%j} -gmt true] \
+ [clock scan {2000001 2440588} -format {%Y%j %J} -gmt true]
+} {0 0}
+
+# BEGIN testcases11
+
+# Test precedence among yyyymmdd and yyyyddd
+
+test clock-11.1 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 19700101002 -format %Y%m%d%j -gmt 1
+} 86400
+test clock-11.2 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 01197001002 -format %m%Y%d%j -gmt 1
+} 86400
+test clock-11.3 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 01197001002 -format %d%Y%m%j -gmt 1
+} 86400
+test clock-11.4 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 00219700101 -format %j%Y%m%d -gmt 1
+} 0
+test clock-11.5 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 19700100201 -format %Y%m%j%d -gmt 1
+} 0
+test clock-11.6 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 01197000201 -format %m%Y%j%d -gmt 1
+} 0
+test clock-11.7 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 01197000201 -format %d%Y%j%m -gmt 1
+} 0
+test clock-11.8 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 00219700101 -format %j%Y%d%m -gmt 1
+} 0
+test clock-11.9 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 19700101002 -format %Y%d%m%j -gmt 1
+} 86400
+test clock-11.10 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 01011970002 -format %m%d%Y%j -gmt 1
+} 86400
+test clock-11.11 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 01011970002 -format %d%m%Y%j -gmt 1
+} 86400
+test clock-11.12 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 00201197001 -format %j%m%Y%d -gmt 1
+} 0
+test clock-11.13 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 19700100201 -format %Y%d%j%m -gmt 1
+} 0
+test clock-11.14 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 01010021970 -format %m%d%j%Y -gmt 1
+} 86400
+test clock-11.15 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 01010021970 -format %d%m%j%Y -gmt 1
+} 86400
+test clock-11.16 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 00201011970 -format %j%m%d%Y -gmt 1
+} 0
+test clock-11.17 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 19700020101 -format %Y%j%m%d -gmt 1
+} 0
+test clock-11.18 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 01002197001 -format %m%j%Y%d -gmt 1
+} 0
+test clock-11.19 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 01002197001 -format %d%j%Y%m -gmt 1
+} 0
+test clock-11.20 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 00201197001 -format %j%d%Y%m -gmt 1
+} 0
+test clock-11.21 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 19700020101 -format %Y%j%d%m -gmt 1
+} 0
+test clock-11.22 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 01002011970 -format %m%j%d%Y -gmt 1
+} 0
+test clock-11.23 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 01002011970 -format %d%j%m%Y -gmt 1
+} 0
+test clock-11.24 {precedence of ccyyddd and ccyymmdd} {
+ clock scan 00201011970 -format %j%d%m%Y -gmt 1
+} 0
+# END testcases11
+
+# BEGIN testcases12
+
+# Test parsing of ccyyWwwd
+
+test clock-12.1 {parse ccyyWwwd} {
+ clock scan {1970 W01 Fri} -format {%G W%V %a} -locale en_US_roman -gmt 1
+} 86400
+test clock-12.2 {parse ccyyWwwd} {
+ clock scan {1970 W01 Friday} -format {%G W%V %A} -locale en_US_roman -gmt 1
+} 86400
+test clock-12.3 {parse ccyyWwwd} {
+ clock scan {1970 W01 5} -format {%G W%V %u} -locale en_US_roman -gmt 1
+} 86400
+test clock-12.4 {parse ccyyWwwd} {
+ clock scan {1970 W01 5} -format {%G W%V %w} -locale en_US_roman -gmt 1
+} 86400
+test clock-12.5 {parse ccyyWwwd} {
+ clock scan {1970 W01 v} -format {%G W%V %Ou} -locale en_US_roman -gmt 1
+} 86400
+test clock-12.6 {parse ccyyWwwd} {
+ clock scan {1970 W01 v} -format {%G W%V %Ow} -locale en_US_roman -gmt 1
+} 86400
+test clock-12.7 {parse ccyyWwwd} {
+ clock scan {1970 W05 Sat} -format {%G W%V %a} -locale en_US_roman -gmt 1
+} 2592000
+test clock-12.8 {parse ccyyWwwd} {
+ clock scan {1970 W05 Saturday} -format {%G W%V %A} -locale en_US_roman -gmt 1
+} 2592000
+test clock-12.9 {parse ccyyWwwd} {
+ clock scan {1970 W05 6} -format {%G W%V %u} -locale en_US_roman -gmt 1
+} 2592000
+test clock-12.10 {parse ccyyWwwd} {
+ clock scan {1970 W05 6} -format {%G W%V %w} -locale en_US_roman -gmt 1
+} 2592000
+test clock-12.11 {parse ccyyWwwd} {
+ clock scan {1970 W05 vi} -format {%G W%V %Ou} -locale en_US_roman -gmt 1
+} 2592000
+test clock-12.12 {parse ccyyWwwd} {
+ clock scan {1970 W05 vi} -format {%G W%V %Ow} -locale en_US_roman -gmt 1
+} 2592000
+test clock-12.13 {parse ccyyWwwd} {
+ clock scan {1970 W49 Wed} -format {%G W%V %a} -locale en_US_roman -gmt 1
+} 28944000
+test clock-12.14 {parse ccyyWwwd} {
+ clock scan {1970 W49 Wednesday} -format {%G W%V %A} -locale en_US_roman -gmt 1
+} 28944000
+test clock-12.15 {parse ccyyWwwd} {
+ clock scan {1970 W49 3} -format {%G W%V %u} -locale en_US_roman -gmt 1
+} 28944000
+test clock-12.16 {parse ccyyWwwd} {
+ clock scan {1970 W49 3} -format {%G W%V %w} -locale en_US_roman -gmt 1
+} 28944000
+test clock-12.17 {parse ccyyWwwd} {
+ clock scan {1970 W49 iii} -format {%G W%V %Ou} -locale en_US_roman -gmt 1
+} 28944000
+test clock-12.18 {parse ccyyWwwd} {
+ clock scan {1970 W49 iii} -format {%G W%V %Ow} -locale en_US_roman -gmt 1
+} 28944000
+test clock-12.19 {parse ccyyWwwd} {
+ clock scan {1970 W53 Thu} -format {%G W%V %a} -locale en_US_roman -gmt 1
+} 31449600
+test clock-12.20 {parse ccyyWwwd} {
+ clock scan {1970 W53 Thursday} -format {%G W%V %A} -locale en_US_roman -gmt 1
+} 31449600
+test clock-12.21 {parse ccyyWwwd} {
+ clock scan {1970 W53 4} -format {%G W%V %u} -locale en_US_roman -gmt 1
+} 31449600
+test clock-12.22 {parse ccyyWwwd} {
+ clock scan {1970 W53 4} -format {%G W%V %w} -locale en_US_roman -gmt 1
+} 31449600
+test clock-12.23 {parse ccyyWwwd} {
+ clock scan {1970 W53 iv} -format {%G W%V %Ou} -locale en_US_roman -gmt 1
+} 31449600
+test clock-12.24 {parse ccyyWwwd} {
+ clock scan {1970 W53 iv} -format {%G W%V %Ow} -locale en_US_roman -gmt 1
+} 31449600
+test clock-12.25 {parse ccyyWwwd} {
+ clock scan {1970 W53 Sat} -format {%G W%V %a} -locale en_US_roman -gmt 1
+} 31622400
+test clock-12.26 {parse ccyyWwwd} {
+ clock scan {1970 W53 Saturday} -format {%G W%V %A} -locale en_US_roman -gmt 1
+} 31622400
+test clock-12.27 {parse ccyyWwwd} {
+ clock scan {1970 W53 6} -format {%G W%V %u} -locale en_US_roman -gmt 1
+} 31622400
+test clock-12.28 {parse ccyyWwwd} {
+ clock scan {1970 W53 6} -format {%G W%V %w} -locale en_US_roman -gmt 1
+} 31622400
+test clock-12.29 {parse ccyyWwwd} {
+ clock scan {1970 W53 vi} -format {%G W%V %Ou} -locale en_US_roman -gmt 1
+} 31622400
+test clock-12.30 {parse ccyyWwwd} {
+ clock scan {1970 W53 vi} -format {%G W%V %Ow} -locale en_US_roman -gmt 1
+} 31622400
+test clock-12.31 {parse ccyyWwwd} {
+ clock scan {1971 W04 Sun} -format {%G W%V %a} -locale en_US_roman -gmt 1
+} 34128000
+test clock-12.32 {parse ccyyWwwd} {
+ clock scan {1971 W04 Sunday} -format {%G W%V %A} -locale en_US_roman -gmt 1
+} 34128000
+test clock-12.33 {parse ccyyWwwd} {
+ clock scan {1971 W04 7} -format {%G W%V %u} -locale en_US_roman -gmt 1
+} 34128000
+test clock-12.34 {parse ccyyWwwd} {
+ clock scan {1971 W04 0} -format {%G W%V %w} -locale en_US_roman -gmt 1
+} 34128000
+test clock-12.35 {parse ccyyWwwd} {
+ clock scan {1971 W04 vii} -format {%G W%V %Ou} -locale en_US_roman -gmt 1
+} 34128000
+test clock-12.36 {parse ccyyWwwd} {
+ clock scan {1971 W04 ?} -format {%G W%V %Ow} -locale en_US_roman -gmt 1
+} 34128000
+test clock-12.37 {parse ccyyWwwd} {
+ clock scan {1971 W48 Thu} -format {%G W%V %a} -locale en_US_roman -gmt 1
+} 60480000
+test clock-12.38 {parse ccyyWwwd} {
+ clock scan {1971 W48 Thursday} -format {%G W%V %A} -locale en_US_roman -gmt 1
+} 60480000
+test clock-12.39 {parse ccyyWwwd} {
+ clock scan {1971 W48 4} -format {%G W%V %u} -locale en_US_roman -gmt 1
+} 60480000
+test clock-12.40 {parse ccyyWwwd} {
+ clock scan {1971 W48 4} -format {%G W%V %w} -locale en_US_roman -gmt 1
+} 60480000
+test clock-12.41 {parse ccyyWwwd} {
+ clock scan {1971 W48 iv} -format {%G W%V %Ou} -locale en_US_roman -gmt 1
+} 60480000
+test clock-12.42 {parse ccyyWwwd} {
+ clock scan {1971 W48 iv} -format {%G W%V %Ow} -locale en_US_roman -gmt 1
+} 60480000
+test clock-12.43 {parse ccyyWwwd} {
+ clock scan {1971 W52 Fri} -format {%G W%V %a} -locale en_US_roman -gmt 1
+} 62985600
+test clock-12.44 {parse ccyyWwwd} {
+ clock scan {1971 W52 Friday} -format {%G W%V %A} -locale en_US_roman -gmt 1
+} 62985600
+test clock-12.45 {parse ccyyWwwd} {
+ clock scan {1971 W52 5} -format {%G W%V %u} -locale en_US_roman -gmt 1
+} 62985600
+test clock-12.46 {parse ccyyWwwd} {
+ clock scan {1971 W52 5} -format {%G W%V %w} -locale en_US_roman -gmt 1
+} 62985600
+test clock-12.47 {parse ccyyWwwd} {
+ clock scan {1971 W52 v} -format {%G W%V %Ou} -locale en_US_roman -gmt 1
+} 62985600
+test clock-12.48 {parse ccyyWwwd} {
+ clock scan {1971 W52 v} -format {%G W%V %Ow} -locale en_US_roman -gmt 1
+} 62985600
+test clock-12.49 {parse ccyyWwwd} {
+ clock scan {1999 W52 Sun} -format {%G W%V %a} -locale en_US_roman -gmt 1
+} 946771200
+test clock-12.50 {parse ccyyWwwd} {
+ clock scan {1999 W52 Sunday} -format {%G W%V %A} -locale en_US_roman -gmt 1
+} 946771200
+test clock-12.51 {parse ccyyWwwd} {
+ clock scan {1999 W52 7} -format {%G W%V %u} -locale en_US_roman -gmt 1
+} 946771200
+test clock-12.52 {parse ccyyWwwd} {
+ clock scan {1999 W52 0} -format {%G W%V %w} -locale en_US_roman -gmt 1
+} 946771200
+test clock-12.53 {parse ccyyWwwd} {
+ clock scan {1999 W52 vii} -format {%G W%V %Ou} -locale en_US_roman -gmt 1
+} 946771200
+test clock-12.54 {parse ccyyWwwd} {
+ clock scan {1999 W52 ?} -format {%G W%V %Ow} -locale en_US_roman -gmt 1
+} 946771200
+test clock-12.55 {parse ccyyWwwd} {
+ clock scan {2000 W05 Mon} -format {%G W%V %a} -locale en_US_roman -gmt 1
+} 949276800
+test clock-12.56 {parse ccyyWwwd} {
+ clock scan {2000 W05 Monday} -format {%G W%V %A} -locale en_US_roman -gmt 1
+} 949276800
+test clock-12.57 {parse ccyyWwwd} {
+ clock scan {2000 W05 1} -format {%G W%V %u} -locale en_US_roman -gmt 1
+} 949276800
+test clock-12.58 {parse ccyyWwwd} {
+ clock scan {2000 W05 1} -format {%G W%V %w} -locale en_US_roman -gmt 1
+} 949276800
+test clock-12.59 {parse ccyyWwwd} {
+ clock scan {2000 W05 i} -format {%G W%V %Ou} -locale en_US_roman -gmt 1
+} 949276800
+test clock-12.60 {parse ccyyWwwd} {
+ clock scan {2000 W05 i} -format {%G W%V %Ow} -locale en_US_roman -gmt 1
+} 949276800
+test clock-12.61 {parse ccyyWwwd} {
+ clock scan {2000 W48 Sat} -format {%G W%V %a} -locale en_US_roman -gmt 1
+} 975715200
+test clock-12.62 {parse ccyyWwwd} {
+ clock scan {2000 W48 Saturday} -format {%G W%V %A} -locale en_US_roman -gmt 1
+} 975715200
+test clock-12.63 {parse ccyyWwwd} {
+ clock scan {2000 W48 6} -format {%G W%V %u} -locale en_US_roman -gmt 1
+} 975715200
+test clock-12.64 {parse ccyyWwwd} {
+ clock scan {2000 W48 6} -format {%G W%V %w} -locale en_US_roman -gmt 1
+} 975715200
+test clock-12.65 {parse ccyyWwwd} {
+ clock scan {2000 W48 vi} -format {%G W%V %Ou} -locale en_US_roman -gmt 1
+} 975715200
+test clock-12.66 {parse ccyyWwwd} {
+ clock scan {2000 W48 vi} -format {%G W%V %Ow} -locale en_US_roman -gmt 1
+} 975715200
+test clock-12.67 {parse ccyyWwwd} {
+ clock scan {2000 W52 Sun} -format {%G W%V %a} -locale en_US_roman -gmt 1
+} 978220800
+test clock-12.68 {parse ccyyWwwd} {
+ clock scan {2000 W52 Sunday} -format {%G W%V %A} -locale en_US_roman -gmt 1
+} 978220800
+test clock-12.69 {parse ccyyWwwd} {
+ clock scan {2000 W52 7} -format {%G W%V %u} -locale en_US_roman -gmt 1
+} 978220800
+test clock-12.70 {parse ccyyWwwd} {
+ clock scan {2000 W52 0} -format {%G W%V %w} -locale en_US_roman -gmt 1
+} 978220800
+test clock-12.71 {parse ccyyWwwd} {
+ clock scan {2000 W52 vii} -format {%G W%V %Ou} -locale en_US_roman -gmt 1
+} 978220800
+test clock-12.72 {parse ccyyWwwd} {
+ clock scan {2000 W52 ?} -format {%G W%V %Ow} -locale en_US_roman -gmt 1
+} 978220800
+test clock-12.73 {parse ccyyWwwd} {
+ clock scan {2001 W01 Tue} -format {%G W%V %a} -locale en_US_roman -gmt 1
+} 978393600
+test clock-12.74 {parse ccyyWwwd} {
+ clock scan {2001 W01 Tuesday} -format {%G W%V %A} -locale en_US_roman -gmt 1
+} 978393600
+test clock-12.75 {parse ccyyWwwd} {
+ clock scan {2001 W01 2} -format {%G W%V %u} -locale en_US_roman -gmt 1
+} 978393600
+test clock-12.76 {parse ccyyWwwd} {
+ clock scan {2001 W01 2} -format {%G W%V %w} -locale en_US_roman -gmt 1
+} 978393600
+test clock-12.77 {parse ccyyWwwd} {
+ clock scan {2001 W01 ii} -format {%G W%V %Ou} -locale en_US_roman -gmt 1
+} 978393600
+test clock-12.78 {parse ccyyWwwd} {
+ clock scan {2001 W01 ii} -format {%G W%V %Ow} -locale en_US_roman -gmt 1
+} 978393600
+test clock-12.79 {parse ccyyWwwd} {
+ clock scan {2001 W05 Wed} -format {%G W%V %a} -locale en_US_roman -gmt 1
+} 980899200
+test clock-12.80 {parse ccyyWwwd} {
+ clock scan {2001 W05 Wednesday} -format {%G W%V %A} -locale en_US_roman -gmt 1
+} 980899200
+test clock-12.81 {parse ccyyWwwd} {
+ clock scan {2001 W05 3} -format {%G W%V %u} -locale en_US_roman -gmt 1
+} 980899200
+test clock-12.82 {parse ccyyWwwd} {
+ clock scan {2001 W05 3} -format {%G W%V %w} -locale en_US_roman -gmt 1
+} 980899200
+test clock-12.83 {parse ccyyWwwd} {
+ clock scan {2001 W05 iii} -format {%G W%V %Ou} -locale en_US_roman -gmt 1
+} 980899200
+test clock-12.84 {parse ccyyWwwd} {
+ clock scan {2001 W05 iii} -format {%G W%V %Ow} -locale en_US_roman -gmt 1
+} 980899200
+test clock-12.85 {parse ccyyWwwd} {
+ clock scan {2001 W48 Sun} -format {%G W%V %a} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-12.86 {parse ccyyWwwd} {
+ clock scan {2001 W48 Sunday} -format {%G W%V %A} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-12.87 {parse ccyyWwwd} {
+ clock scan {2001 W48 7} -format {%G W%V %u} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-12.88 {parse ccyyWwwd} {
+ clock scan {2001 W48 0} -format {%G W%V %w} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-12.89 {parse ccyyWwwd} {
+ clock scan {2001 W48 vii} -format {%G W%V %Ou} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-12.90 {parse ccyyWwwd} {
+ clock scan {2001 W48 ?} -format {%G W%V %Ow} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-12.91 {parse ccyyWwwd} {
+ clock scan {2002 W01 Mon} -format {%G W%V %a} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-12.92 {parse ccyyWwwd} {
+ clock scan {2002 W01 Monday} -format {%G W%V %A} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-12.93 {parse ccyyWwwd} {
+ clock scan {2002 W01 1} -format {%G W%V %u} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-12.94 {parse ccyyWwwd} {
+ clock scan {2002 W01 1} -format {%G W%V %w} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-12.95 {parse ccyyWwwd} {
+ clock scan {2002 W01 i} -format {%G W%V %Ou} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-12.96 {parse ccyyWwwd} {
+ clock scan {2002 W01 i} -format {%G W%V %Ow} -locale en_US_roman -gmt 1
+} 1009756800
+# END testcases12
+
+test clock-13.1 {test that %s takes precedence over ccyyWwwd} {
+ list [clock scan {0 2000W011} -format {%s %GW%V%u} -gmt true] \
+ [clock scan {2000W011 0} -format {%GW%V%u %s} -gmt true]
+} {0 0}
+test clock-13.2 {test that %J takes precedence over ccyyWwwd} {
+ list [clock scan {2440588 2000W011} -format {%J %GW%V%u} -gmt true] \
+ [clock scan {2000W011 2440588} -format {%GW%V%u %J} -gmt true]
+} {0 0}
+test clock-13.3 {invalid weekday} {
+ catch {clock scan 2000W018 -format %GW%V%u -gmt true} result
+ list $result $::errorCode
+} {{day of week is greater than 7} {CLOCK badDayOfWeek}}
+test clock-13.4 {invalid weekday} {
+ catch {
+ clock scan {2000 W01 viii} \
+ -format {%G W%V %Ou} -gmt true -locale en_US_roman
+ } result
+ list $result $::errorCode
+} {{day of week is greater than 7} {CLOCK badDayOfWeek}}
+
+# BEGIN testcases14
+
+# Test parsing of yymmdd
+
+test clock-14.1 {parse yymmdd} {
+ clock scan {38 Jan 02} -format {%y %b %d} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.2 {parse yymmdd} {
+ clock scan {38 Jan ii} -format {%y %b %Od} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.3 {parse yymmdd} {
+ clock scan {38 Jan 2} -format {%y %b %e} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.4 {parse yymmdd} {
+ clock scan {38 Jan ii} -format {%y %b %Oe} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.5 {parse yymmdd} {
+ clock scan {38 January 02} -format {%y %B %d} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.6 {parse yymmdd} {
+ clock scan {38 January ii} -format {%y %B %Od} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.7 {parse yymmdd} {
+ clock scan {38 January 2} -format {%y %B %e} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.8 {parse yymmdd} {
+ clock scan {38 January ii} -format {%y %B %Oe} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.9 {parse yymmdd} {
+ clock scan {38 Jan 02} -format {%y %h %d} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.10 {parse yymmdd} {
+ clock scan {38 Jan ii} -format {%y %h %Od} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.11 {parse yymmdd} {
+ clock scan {38 Jan 2} -format {%y %h %e} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.12 {parse yymmdd} {
+ clock scan {38 Jan ii} -format {%y %h %Oe} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.13 {parse yymmdd} {
+ clock scan {38 01 02} -format {%y %m %d} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.14 {parse yymmdd} {
+ clock scan {38 01 ii} -format {%y %m %Od} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.15 {parse yymmdd} {
+ clock scan {38 01 2} -format {%y %m %e} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.16 {parse yymmdd} {
+ clock scan {38 01 ii} -format {%y %m %Oe} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.17 {parse yymmdd} {
+ clock scan {38 i 02} -format {%y %Om %d} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.18 {parse yymmdd} {
+ clock scan {38 i ii} -format {%y %Om %Od} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.19 {parse yymmdd} {
+ clock scan {38 i 2} -format {%y %Om %e} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.20 {parse yymmdd} {
+ clock scan {38 i ii} -format {%y %Om %Oe} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.21 {parse yymmdd} {
+ clock scan {38 1 02} -format {%y %N %d} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.22 {parse yymmdd} {
+ clock scan {38 1 ii} -format {%y %N %Od} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.23 {parse yymmdd} {
+ clock scan {38 1 2} -format {%y %N %e} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.24 {parse yymmdd} {
+ clock scan {38 1 ii} -format {%y %N %Oe} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.25 {parse yymmdd} {
+ clock scan {xxxviii Jan 02} -format {%Oy %b %d} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.26 {parse yymmdd} {
+ clock scan {xxxviii Jan ii} -format {%Oy %b %Od} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.27 {parse yymmdd} {
+ clock scan {xxxviii Jan 2} -format {%Oy %b %e} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.28 {parse yymmdd} {
+ clock scan {xxxviii Jan ii} -format {%Oy %b %Oe} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.29 {parse yymmdd} {
+ clock scan {xxxviii January 02} -format {%Oy %B %d} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.30 {parse yymmdd} {
+ clock scan {xxxviii January ii} -format {%Oy %B %Od} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.31 {parse yymmdd} {
+ clock scan {xxxviii January 2} -format {%Oy %B %e} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.32 {parse yymmdd} {
+ clock scan {xxxviii January ii} -format {%Oy %B %Oe} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.33 {parse yymmdd} {
+ clock scan {xxxviii Jan 02} -format {%Oy %h %d} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.34 {parse yymmdd} {
+ clock scan {xxxviii Jan ii} -format {%Oy %h %Od} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.35 {parse yymmdd} {
+ clock scan {xxxviii Jan 2} -format {%Oy %h %e} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.36 {parse yymmdd} {
+ clock scan {xxxviii Jan ii} -format {%Oy %h %Oe} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.37 {parse yymmdd} {
+ clock scan {xxxviii 01 02} -format {%Oy %m %d} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.38 {parse yymmdd} {
+ clock scan {xxxviii 01 ii} -format {%Oy %m %Od} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.39 {parse yymmdd} {
+ clock scan {xxxviii 01 2} -format {%Oy %m %e} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.40 {parse yymmdd} {
+ clock scan {xxxviii 01 ii} -format {%Oy %m %Oe} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.41 {parse yymmdd} {
+ clock scan {xxxviii i 02} -format {%Oy %Om %d} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.42 {parse yymmdd} {
+ clock scan {xxxviii i ii} -format {%Oy %Om %Od} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.43 {parse yymmdd} {
+ clock scan {xxxviii i 2} -format {%Oy %Om %e} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.44 {parse yymmdd} {
+ clock scan {xxxviii i ii} -format {%Oy %Om %Oe} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.45 {parse yymmdd} {
+ clock scan {xxxviii 1 02} -format {%Oy %N %d} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.46 {parse yymmdd} {
+ clock scan {xxxviii 1 ii} -format {%Oy %N %Od} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.47 {parse yymmdd} {
+ clock scan {xxxviii 1 2} -format {%Oy %N %e} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.48 {parse yymmdd} {
+ clock scan {xxxviii 1 ii} -format {%Oy %N %Oe} -locale en_US_roman -gmt 1
+} -1009756800
+test clock-14.49 {parse yymmdd} {
+ clock scan {38 Jan 31} -format {%y %b %d} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.50 {parse yymmdd} {
+ clock scan {38 Jan xxxi} -format {%y %b %Od} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.51 {parse yymmdd} {
+ clock scan {38 Jan 31} -format {%y %b %e} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.52 {parse yymmdd} {
+ clock scan {38 Jan xxxi} -format {%y %b %Oe} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.53 {parse yymmdd} {
+ clock scan {38 January 31} -format {%y %B %d} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.54 {parse yymmdd} {
+ clock scan {38 January xxxi} -format {%y %B %Od} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.55 {parse yymmdd} {
+ clock scan {38 January 31} -format {%y %B %e} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.56 {parse yymmdd} {
+ clock scan {38 January xxxi} -format {%y %B %Oe} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.57 {parse yymmdd} {
+ clock scan {38 Jan 31} -format {%y %h %d} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.58 {parse yymmdd} {
+ clock scan {38 Jan xxxi} -format {%y %h %Od} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.59 {parse yymmdd} {
+ clock scan {38 Jan 31} -format {%y %h %e} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.60 {parse yymmdd} {
+ clock scan {38 Jan xxxi} -format {%y %h %Oe} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.61 {parse yymmdd} {
+ clock scan {38 01 31} -format {%y %m %d} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.62 {parse yymmdd} {
+ clock scan {38 01 xxxi} -format {%y %m %Od} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.63 {parse yymmdd} {
+ clock scan {38 01 31} -format {%y %m %e} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.64 {parse yymmdd} {
+ clock scan {38 01 xxxi} -format {%y %m %Oe} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.65 {parse yymmdd} {
+ clock scan {38 i 31} -format {%y %Om %d} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.66 {parse yymmdd} {
+ clock scan {38 i xxxi} -format {%y %Om %Od} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.67 {parse yymmdd} {
+ clock scan {38 i 31} -format {%y %Om %e} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.68 {parse yymmdd} {
+ clock scan {38 i xxxi} -format {%y %Om %Oe} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.69 {parse yymmdd} {
+ clock scan {38 1 31} -format {%y %N %d} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.70 {parse yymmdd} {
+ clock scan {38 1 xxxi} -format {%y %N %Od} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.71 {parse yymmdd} {
+ clock scan {38 1 31} -format {%y %N %e} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.72 {parse yymmdd} {
+ clock scan {38 1 xxxi} -format {%y %N %Oe} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.73 {parse yymmdd} {
+ clock scan {xxxviii Jan 31} -format {%Oy %b %d} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.74 {parse yymmdd} {
+ clock scan {xxxviii Jan xxxi} -format {%Oy %b %Od} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.75 {parse yymmdd} {
+ clock scan {xxxviii Jan 31} -format {%Oy %b %e} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.76 {parse yymmdd} {
+ clock scan {xxxviii Jan xxxi} -format {%Oy %b %Oe} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.77 {parse yymmdd} {
+ clock scan {xxxviii January 31} -format {%Oy %B %d} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.78 {parse yymmdd} {
+ clock scan {xxxviii January xxxi} -format {%Oy %B %Od} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.79 {parse yymmdd} {
+ clock scan {xxxviii January 31} -format {%Oy %B %e} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.80 {parse yymmdd} {
+ clock scan {xxxviii January xxxi} -format {%Oy %B %Oe} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.81 {parse yymmdd} {
+ clock scan {xxxviii Jan 31} -format {%Oy %h %d} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.82 {parse yymmdd} {
+ clock scan {xxxviii Jan xxxi} -format {%Oy %h %Od} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.83 {parse yymmdd} {
+ clock scan {xxxviii Jan 31} -format {%Oy %h %e} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.84 {parse yymmdd} {
+ clock scan {xxxviii Jan xxxi} -format {%Oy %h %Oe} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.85 {parse yymmdd} {
+ clock scan {xxxviii 01 31} -format {%Oy %m %d} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.86 {parse yymmdd} {
+ clock scan {xxxviii 01 xxxi} -format {%Oy %m %Od} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.87 {parse yymmdd} {
+ clock scan {xxxviii 01 31} -format {%Oy %m %e} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.88 {parse yymmdd} {
+ clock scan {xxxviii 01 xxxi} -format {%Oy %m %Oe} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.89 {parse yymmdd} {
+ clock scan {xxxviii i 31} -format {%Oy %Om %d} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.90 {parse yymmdd} {
+ clock scan {xxxviii i xxxi} -format {%Oy %Om %Od} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.91 {parse yymmdd} {
+ clock scan {xxxviii i 31} -format {%Oy %Om %e} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.92 {parse yymmdd} {
+ clock scan {xxxviii i xxxi} -format {%Oy %Om %Oe} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.93 {parse yymmdd} {
+ clock scan {xxxviii 1 31} -format {%Oy %N %d} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.94 {parse yymmdd} {
+ clock scan {xxxviii 1 xxxi} -format {%Oy %N %Od} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.95 {parse yymmdd} {
+ clock scan {xxxviii 1 31} -format {%Oy %N %e} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.96 {parse yymmdd} {
+ clock scan {xxxviii 1 xxxi} -format {%Oy %N %Oe} -locale en_US_roman -gmt 1
+} -1007251200
+test clock-14.97 {parse yymmdd} {
+ clock scan {38 Dec 02} -format {%y %b %d} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.98 {parse yymmdd} {
+ clock scan {38 Dec ii} -format {%y %b %Od} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.99 {parse yymmdd} {
+ clock scan {38 Dec 2} -format {%y %b %e} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.100 {parse yymmdd} {
+ clock scan {38 Dec ii} -format {%y %b %Oe} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.101 {parse yymmdd} {
+ clock scan {38 December 02} -format {%y %B %d} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.102 {parse yymmdd} {
+ clock scan {38 December ii} -format {%y %B %Od} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.103 {parse yymmdd} {
+ clock scan {38 December 2} -format {%y %B %e} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.104 {parse yymmdd} {
+ clock scan {38 December ii} -format {%y %B %Oe} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.105 {parse yymmdd} {
+ clock scan {38 Dec 02} -format {%y %h %d} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.106 {parse yymmdd} {
+ clock scan {38 Dec ii} -format {%y %h %Od} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.107 {parse yymmdd} {
+ clock scan {38 Dec 2} -format {%y %h %e} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.108 {parse yymmdd} {
+ clock scan {38 Dec ii} -format {%y %h %Oe} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.109 {parse yymmdd} {
+ clock scan {38 12 02} -format {%y %m %d} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.110 {parse yymmdd} {
+ clock scan {38 12 ii} -format {%y %m %Od} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.111 {parse yymmdd} {
+ clock scan {38 12 2} -format {%y %m %e} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.112 {parse yymmdd} {
+ clock scan {38 12 ii} -format {%y %m %Oe} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.113 {parse yymmdd} {
+ clock scan {38 xii 02} -format {%y %Om %d} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.114 {parse yymmdd} {
+ clock scan {38 xii ii} -format {%y %Om %Od} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.115 {parse yymmdd} {
+ clock scan {38 xii 2} -format {%y %Om %e} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.116 {parse yymmdd} {
+ clock scan {38 xii ii} -format {%y %Om %Oe} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.117 {parse yymmdd} {
+ clock scan {38 12 02} -format {%y %N %d} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.118 {parse yymmdd} {
+ clock scan {38 12 ii} -format {%y %N %Od} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.119 {parse yymmdd} {
+ clock scan {38 12 2} -format {%y %N %e} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.120 {parse yymmdd} {
+ clock scan {38 12 ii} -format {%y %N %Oe} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.121 {parse yymmdd} {
+ clock scan {xxxviii Dec 02} -format {%Oy %b %d} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.122 {parse yymmdd} {
+ clock scan {xxxviii Dec ii} -format {%Oy %b %Od} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.123 {parse yymmdd} {
+ clock scan {xxxviii Dec 2} -format {%Oy %b %e} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.124 {parse yymmdd} {
+ clock scan {xxxviii Dec ii} -format {%Oy %b %Oe} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.125 {parse yymmdd} {
+ clock scan {xxxviii December 02} -format {%Oy %B %d} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.126 {parse yymmdd} {
+ clock scan {xxxviii December ii} -format {%Oy %B %Od} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.127 {parse yymmdd} {
+ clock scan {xxxviii December 2} -format {%Oy %B %e} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.128 {parse yymmdd} {
+ clock scan {xxxviii December ii} -format {%Oy %B %Oe} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.129 {parse yymmdd} {
+ clock scan {xxxviii Dec 02} -format {%Oy %h %d} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.130 {parse yymmdd} {
+ clock scan {xxxviii Dec ii} -format {%Oy %h %Od} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.131 {parse yymmdd} {
+ clock scan {xxxviii Dec 2} -format {%Oy %h %e} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.132 {parse yymmdd} {
+ clock scan {xxxviii Dec ii} -format {%Oy %h %Oe} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.133 {parse yymmdd} {
+ clock scan {xxxviii 12 02} -format {%Oy %m %d} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.134 {parse yymmdd} {
+ clock scan {xxxviii 12 ii} -format {%Oy %m %Od} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.135 {parse yymmdd} {
+ clock scan {xxxviii 12 2} -format {%Oy %m %e} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.136 {parse yymmdd} {
+ clock scan {xxxviii 12 ii} -format {%Oy %m %Oe} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.137 {parse yymmdd} {
+ clock scan {xxxviii xii 02} -format {%Oy %Om %d} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.138 {parse yymmdd} {
+ clock scan {xxxviii xii ii} -format {%Oy %Om %Od} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.139 {parse yymmdd} {
+ clock scan {xxxviii xii 2} -format {%Oy %Om %e} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.140 {parse yymmdd} {
+ clock scan {xxxviii xii ii} -format {%Oy %Om %Oe} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.141 {parse yymmdd} {
+ clock scan {xxxviii 12 02} -format {%Oy %N %d} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.142 {parse yymmdd} {
+ clock scan {xxxviii 12 ii} -format {%Oy %N %Od} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.143 {parse yymmdd} {
+ clock scan {xxxviii 12 2} -format {%Oy %N %e} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.144 {parse yymmdd} {
+ clock scan {xxxviii 12 ii} -format {%Oy %N %Oe} -locale en_US_roman -gmt 1
+} -980899200
+test clock-14.145 {parse yymmdd} {
+ clock scan {38 Dec 31} -format {%y %b %d} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.146 {parse yymmdd} {
+ clock scan {38 Dec xxxi} -format {%y %b %Od} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.147 {parse yymmdd} {
+ clock scan {38 Dec 31} -format {%y %b %e} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.148 {parse yymmdd} {
+ clock scan {38 Dec xxxi} -format {%y %b %Oe} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.149 {parse yymmdd} {
+ clock scan {38 December 31} -format {%y %B %d} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.150 {parse yymmdd} {
+ clock scan {38 December xxxi} -format {%y %B %Od} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.151 {parse yymmdd} {
+ clock scan {38 December 31} -format {%y %B %e} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.152 {parse yymmdd} {
+ clock scan {38 December xxxi} -format {%y %B %Oe} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.153 {parse yymmdd} {
+ clock scan {38 Dec 31} -format {%y %h %d} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.154 {parse yymmdd} {
+ clock scan {38 Dec xxxi} -format {%y %h %Od} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.155 {parse yymmdd} {
+ clock scan {38 Dec 31} -format {%y %h %e} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.156 {parse yymmdd} {
+ clock scan {38 Dec xxxi} -format {%y %h %Oe} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.157 {parse yymmdd} {
+ clock scan {38 12 31} -format {%y %m %d} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.158 {parse yymmdd} {
+ clock scan {38 12 xxxi} -format {%y %m %Od} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.159 {parse yymmdd} {
+ clock scan {38 12 31} -format {%y %m %e} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.160 {parse yymmdd} {
+ clock scan {38 12 xxxi} -format {%y %m %Oe} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.161 {parse yymmdd} {
+ clock scan {38 xii 31} -format {%y %Om %d} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.162 {parse yymmdd} {
+ clock scan {38 xii xxxi} -format {%y %Om %Od} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.163 {parse yymmdd} {
+ clock scan {38 xii 31} -format {%y %Om %e} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.164 {parse yymmdd} {
+ clock scan {38 xii xxxi} -format {%y %Om %Oe} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.165 {parse yymmdd} {
+ clock scan {38 12 31} -format {%y %N %d} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.166 {parse yymmdd} {
+ clock scan {38 12 xxxi} -format {%y %N %Od} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.167 {parse yymmdd} {
+ clock scan {38 12 31} -format {%y %N %e} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.168 {parse yymmdd} {
+ clock scan {38 12 xxxi} -format {%y %N %Oe} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.169 {parse yymmdd} {
+ clock scan {xxxviii Dec 31} -format {%Oy %b %d} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.170 {parse yymmdd} {
+ clock scan {xxxviii Dec xxxi} -format {%Oy %b %Od} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.171 {parse yymmdd} {
+ clock scan {xxxviii Dec 31} -format {%Oy %b %e} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.172 {parse yymmdd} {
+ clock scan {xxxviii Dec xxxi} -format {%Oy %b %Oe} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.173 {parse yymmdd} {
+ clock scan {xxxviii December 31} -format {%Oy %B %d} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.174 {parse yymmdd} {
+ clock scan {xxxviii December xxxi} -format {%Oy %B %Od} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.175 {parse yymmdd} {
+ clock scan {xxxviii December 31} -format {%Oy %B %e} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.176 {parse yymmdd} {
+ clock scan {xxxviii December xxxi} -format {%Oy %B %Oe} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.177 {parse yymmdd} {
+ clock scan {xxxviii Dec 31} -format {%Oy %h %d} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.178 {parse yymmdd} {
+ clock scan {xxxviii Dec xxxi} -format {%Oy %h %Od} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.179 {parse yymmdd} {
+ clock scan {xxxviii Dec 31} -format {%Oy %h %e} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.180 {parse yymmdd} {
+ clock scan {xxxviii Dec xxxi} -format {%Oy %h %Oe} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.181 {parse yymmdd} {
+ clock scan {xxxviii 12 31} -format {%Oy %m %d} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.182 {parse yymmdd} {
+ clock scan {xxxviii 12 xxxi} -format {%Oy %m %Od} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.183 {parse yymmdd} {
+ clock scan {xxxviii 12 31} -format {%Oy %m %e} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.184 {parse yymmdd} {
+ clock scan {xxxviii 12 xxxi} -format {%Oy %m %Oe} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.185 {parse yymmdd} {
+ clock scan {xxxviii xii 31} -format {%Oy %Om %d} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.186 {parse yymmdd} {
+ clock scan {xxxviii xii xxxi} -format {%Oy %Om %Od} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.187 {parse yymmdd} {
+ clock scan {xxxviii xii 31} -format {%Oy %Om %e} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.188 {parse yymmdd} {
+ clock scan {xxxviii xii xxxi} -format {%Oy %Om %Oe} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.189 {parse yymmdd} {
+ clock scan {xxxviii 12 31} -format {%Oy %N %d} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.190 {parse yymmdd} {
+ clock scan {xxxviii 12 xxxi} -format {%Oy %N %Od} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.191 {parse yymmdd} {
+ clock scan {xxxviii 12 31} -format {%Oy %N %e} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.192 {parse yymmdd} {
+ clock scan {xxxviii 12 xxxi} -format {%Oy %N %Oe} -locale en_US_roman -gmt 1
+} -978393600
+test clock-14.193 {parse yymmdd} {
+ clock scan {70 Jan 02} -format {%y %b %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.194 {parse yymmdd} {
+ clock scan {70 Jan ii} -format {%y %b %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.195 {parse yymmdd} {
+ clock scan {70 Jan 2} -format {%y %b %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.196 {parse yymmdd} {
+ clock scan {70 Jan ii} -format {%y %b %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.197 {parse yymmdd} {
+ clock scan {70 January 02} -format {%y %B %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.198 {parse yymmdd} {
+ clock scan {70 January ii} -format {%y %B %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.199 {parse yymmdd} {
+ clock scan {70 January 2} -format {%y %B %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.200 {parse yymmdd} {
+ clock scan {70 January ii} -format {%y %B %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.201 {parse yymmdd} {
+ clock scan {70 Jan 02} -format {%y %h %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.202 {parse yymmdd} {
+ clock scan {70 Jan ii} -format {%y %h %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.203 {parse yymmdd} {
+ clock scan {70 Jan 2} -format {%y %h %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.204 {parse yymmdd} {
+ clock scan {70 Jan ii} -format {%y %h %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.205 {parse yymmdd} {
+ clock scan {70 01 02} -format {%y %m %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.206 {parse yymmdd} {
+ clock scan {70 01 ii} -format {%y %m %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.207 {parse yymmdd} {
+ clock scan {70 01 2} -format {%y %m %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.208 {parse yymmdd} {
+ clock scan {70 01 ii} -format {%y %m %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.209 {parse yymmdd} {
+ clock scan {70 i 02} -format {%y %Om %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.210 {parse yymmdd} {
+ clock scan {70 i ii} -format {%y %Om %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.211 {parse yymmdd} {
+ clock scan {70 i 2} -format {%y %Om %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.212 {parse yymmdd} {
+ clock scan {70 i ii} -format {%y %Om %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.213 {parse yymmdd} {
+ clock scan {70 1 02} -format {%y %N %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.214 {parse yymmdd} {
+ clock scan {70 1 ii} -format {%y %N %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.215 {parse yymmdd} {
+ clock scan {70 1 2} -format {%y %N %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.216 {parse yymmdd} {
+ clock scan {70 1 ii} -format {%y %N %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.217 {parse yymmdd} {
+ clock scan {lxx Jan 02} -format {%Oy %b %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.218 {parse yymmdd} {
+ clock scan {lxx Jan ii} -format {%Oy %b %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.219 {parse yymmdd} {
+ clock scan {lxx Jan 2} -format {%Oy %b %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.220 {parse yymmdd} {
+ clock scan {lxx Jan ii} -format {%Oy %b %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.221 {parse yymmdd} {
+ clock scan {lxx January 02} -format {%Oy %B %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.222 {parse yymmdd} {
+ clock scan {lxx January ii} -format {%Oy %B %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.223 {parse yymmdd} {
+ clock scan {lxx January 2} -format {%Oy %B %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.224 {parse yymmdd} {
+ clock scan {lxx January ii} -format {%Oy %B %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.225 {parse yymmdd} {
+ clock scan {lxx Jan 02} -format {%Oy %h %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.226 {parse yymmdd} {
+ clock scan {lxx Jan ii} -format {%Oy %h %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.227 {parse yymmdd} {
+ clock scan {lxx Jan 2} -format {%Oy %h %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.228 {parse yymmdd} {
+ clock scan {lxx Jan ii} -format {%Oy %h %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.229 {parse yymmdd} {
+ clock scan {lxx 01 02} -format {%Oy %m %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.230 {parse yymmdd} {
+ clock scan {lxx 01 ii} -format {%Oy %m %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.231 {parse yymmdd} {
+ clock scan {lxx 01 2} -format {%Oy %m %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.232 {parse yymmdd} {
+ clock scan {lxx 01 ii} -format {%Oy %m %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.233 {parse yymmdd} {
+ clock scan {lxx i 02} -format {%Oy %Om %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.234 {parse yymmdd} {
+ clock scan {lxx i ii} -format {%Oy %Om %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.235 {parse yymmdd} {
+ clock scan {lxx i 2} -format {%Oy %Om %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.236 {parse yymmdd} {
+ clock scan {lxx i ii} -format {%Oy %Om %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.237 {parse yymmdd} {
+ clock scan {lxx 1 02} -format {%Oy %N %d} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.238 {parse yymmdd} {
+ clock scan {lxx 1 ii} -format {%Oy %N %Od} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.239 {parse yymmdd} {
+ clock scan {lxx 1 2} -format {%Oy %N %e} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.240 {parse yymmdd} {
+ clock scan {lxx 1 ii} -format {%Oy %N %Oe} -locale en_US_roman -gmt 1
+} 86400
+test clock-14.241 {parse yymmdd} {
+ clock scan {70 Jan 31} -format {%y %b %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.242 {parse yymmdd} {
+ clock scan {70 Jan xxxi} -format {%y %b %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.243 {parse yymmdd} {
+ clock scan {70 Jan 31} -format {%y %b %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.244 {parse yymmdd} {
+ clock scan {70 Jan xxxi} -format {%y %b %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.245 {parse yymmdd} {
+ clock scan {70 January 31} -format {%y %B %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.246 {parse yymmdd} {
+ clock scan {70 January xxxi} -format {%y %B %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.247 {parse yymmdd} {
+ clock scan {70 January 31} -format {%y %B %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.248 {parse yymmdd} {
+ clock scan {70 January xxxi} -format {%y %B %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.249 {parse yymmdd} {
+ clock scan {70 Jan 31} -format {%y %h %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.250 {parse yymmdd} {
+ clock scan {70 Jan xxxi} -format {%y %h %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.251 {parse yymmdd} {
+ clock scan {70 Jan 31} -format {%y %h %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.252 {parse yymmdd} {
+ clock scan {70 Jan xxxi} -format {%y %h %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.253 {parse yymmdd} {
+ clock scan {70 01 31} -format {%y %m %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.254 {parse yymmdd} {
+ clock scan {70 01 xxxi} -format {%y %m %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.255 {parse yymmdd} {
+ clock scan {70 01 31} -format {%y %m %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.256 {parse yymmdd} {
+ clock scan {70 01 xxxi} -format {%y %m %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.257 {parse yymmdd} {
+ clock scan {70 i 31} -format {%y %Om %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.258 {parse yymmdd} {
+ clock scan {70 i xxxi} -format {%y %Om %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.259 {parse yymmdd} {
+ clock scan {70 i 31} -format {%y %Om %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.260 {parse yymmdd} {
+ clock scan {70 i xxxi} -format {%y %Om %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.261 {parse yymmdd} {
+ clock scan {70 1 31} -format {%y %N %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.262 {parse yymmdd} {
+ clock scan {70 1 xxxi} -format {%y %N %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.263 {parse yymmdd} {
+ clock scan {70 1 31} -format {%y %N %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.264 {parse yymmdd} {
+ clock scan {70 1 xxxi} -format {%y %N %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.265 {parse yymmdd} {
+ clock scan {lxx Jan 31} -format {%Oy %b %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.266 {parse yymmdd} {
+ clock scan {lxx Jan xxxi} -format {%Oy %b %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.267 {parse yymmdd} {
+ clock scan {lxx Jan 31} -format {%Oy %b %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.268 {parse yymmdd} {
+ clock scan {lxx Jan xxxi} -format {%Oy %b %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.269 {parse yymmdd} {
+ clock scan {lxx January 31} -format {%Oy %B %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.270 {parse yymmdd} {
+ clock scan {lxx January xxxi} -format {%Oy %B %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.271 {parse yymmdd} {
+ clock scan {lxx January 31} -format {%Oy %B %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.272 {parse yymmdd} {
+ clock scan {lxx January xxxi} -format {%Oy %B %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.273 {parse yymmdd} {
+ clock scan {lxx Jan 31} -format {%Oy %h %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.274 {parse yymmdd} {
+ clock scan {lxx Jan xxxi} -format {%Oy %h %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.275 {parse yymmdd} {
+ clock scan {lxx Jan 31} -format {%Oy %h %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.276 {parse yymmdd} {
+ clock scan {lxx Jan xxxi} -format {%Oy %h %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.277 {parse yymmdd} {
+ clock scan {lxx 01 31} -format {%Oy %m %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.278 {parse yymmdd} {
+ clock scan {lxx 01 xxxi} -format {%Oy %m %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.279 {parse yymmdd} {
+ clock scan {lxx 01 31} -format {%Oy %m %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.280 {parse yymmdd} {
+ clock scan {lxx 01 xxxi} -format {%Oy %m %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.281 {parse yymmdd} {
+ clock scan {lxx i 31} -format {%Oy %Om %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.282 {parse yymmdd} {
+ clock scan {lxx i xxxi} -format {%Oy %Om %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.283 {parse yymmdd} {
+ clock scan {lxx i 31} -format {%Oy %Om %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.284 {parse yymmdd} {
+ clock scan {lxx i xxxi} -format {%Oy %Om %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.285 {parse yymmdd} {
+ clock scan {lxx 1 31} -format {%Oy %N %d} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.286 {parse yymmdd} {
+ clock scan {lxx 1 xxxi} -format {%Oy %N %Od} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.287 {parse yymmdd} {
+ clock scan {lxx 1 31} -format {%Oy %N %e} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.288 {parse yymmdd} {
+ clock scan {lxx 1 xxxi} -format {%Oy %N %Oe} -locale en_US_roman -gmt 1
+} 2592000
+test clock-14.289 {parse yymmdd} {
+ clock scan {70 Dec 02} -format {%y %b %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.290 {parse yymmdd} {
+ clock scan {70 Dec ii} -format {%y %b %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.291 {parse yymmdd} {
+ clock scan {70 Dec 2} -format {%y %b %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.292 {parse yymmdd} {
+ clock scan {70 Dec ii} -format {%y %b %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.293 {parse yymmdd} {
+ clock scan {70 December 02} -format {%y %B %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.294 {parse yymmdd} {
+ clock scan {70 December ii} -format {%y %B %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.295 {parse yymmdd} {
+ clock scan {70 December 2} -format {%y %B %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.296 {parse yymmdd} {
+ clock scan {70 December ii} -format {%y %B %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.297 {parse yymmdd} {
+ clock scan {70 Dec 02} -format {%y %h %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.298 {parse yymmdd} {
+ clock scan {70 Dec ii} -format {%y %h %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.299 {parse yymmdd} {
+ clock scan {70 Dec 2} -format {%y %h %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.300 {parse yymmdd} {
+ clock scan {70 Dec ii} -format {%y %h %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.301 {parse yymmdd} {
+ clock scan {70 12 02} -format {%y %m %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.302 {parse yymmdd} {
+ clock scan {70 12 ii} -format {%y %m %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.303 {parse yymmdd} {
+ clock scan {70 12 2} -format {%y %m %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.304 {parse yymmdd} {
+ clock scan {70 12 ii} -format {%y %m %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.305 {parse yymmdd} {
+ clock scan {70 xii 02} -format {%y %Om %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.306 {parse yymmdd} {
+ clock scan {70 xii ii} -format {%y %Om %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.307 {parse yymmdd} {
+ clock scan {70 xii 2} -format {%y %Om %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.308 {parse yymmdd} {
+ clock scan {70 xii ii} -format {%y %Om %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.309 {parse yymmdd} {
+ clock scan {70 12 02} -format {%y %N %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.310 {parse yymmdd} {
+ clock scan {70 12 ii} -format {%y %N %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.311 {parse yymmdd} {
+ clock scan {70 12 2} -format {%y %N %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.312 {parse yymmdd} {
+ clock scan {70 12 ii} -format {%y %N %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.313 {parse yymmdd} {
+ clock scan {lxx Dec 02} -format {%Oy %b %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.314 {parse yymmdd} {
+ clock scan {lxx Dec ii} -format {%Oy %b %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.315 {parse yymmdd} {
+ clock scan {lxx Dec 2} -format {%Oy %b %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.316 {parse yymmdd} {
+ clock scan {lxx Dec ii} -format {%Oy %b %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.317 {parse yymmdd} {
+ clock scan {lxx December 02} -format {%Oy %B %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.318 {parse yymmdd} {
+ clock scan {lxx December ii} -format {%Oy %B %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.319 {parse yymmdd} {
+ clock scan {lxx December 2} -format {%Oy %B %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.320 {parse yymmdd} {
+ clock scan {lxx December ii} -format {%Oy %B %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.321 {parse yymmdd} {
+ clock scan {lxx Dec 02} -format {%Oy %h %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.322 {parse yymmdd} {
+ clock scan {lxx Dec ii} -format {%Oy %h %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.323 {parse yymmdd} {
+ clock scan {lxx Dec 2} -format {%Oy %h %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.324 {parse yymmdd} {
+ clock scan {lxx Dec ii} -format {%Oy %h %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.325 {parse yymmdd} {
+ clock scan {lxx 12 02} -format {%Oy %m %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.326 {parse yymmdd} {
+ clock scan {lxx 12 ii} -format {%Oy %m %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.327 {parse yymmdd} {
+ clock scan {lxx 12 2} -format {%Oy %m %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.328 {parse yymmdd} {
+ clock scan {lxx 12 ii} -format {%Oy %m %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.329 {parse yymmdd} {
+ clock scan {lxx xii 02} -format {%Oy %Om %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.330 {parse yymmdd} {
+ clock scan {lxx xii ii} -format {%Oy %Om %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.331 {parse yymmdd} {
+ clock scan {lxx xii 2} -format {%Oy %Om %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.332 {parse yymmdd} {
+ clock scan {lxx xii ii} -format {%Oy %Om %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.333 {parse yymmdd} {
+ clock scan {lxx 12 02} -format {%Oy %N %d} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.334 {parse yymmdd} {
+ clock scan {lxx 12 ii} -format {%Oy %N %Od} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.335 {parse yymmdd} {
+ clock scan {lxx 12 2} -format {%Oy %N %e} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.336 {parse yymmdd} {
+ clock scan {lxx 12 ii} -format {%Oy %N %Oe} -locale en_US_roman -gmt 1
+} 28944000
+test clock-14.337 {parse yymmdd} {
+ clock scan {70 Dec 31} -format {%y %b %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.338 {parse yymmdd} {
+ clock scan {70 Dec xxxi} -format {%y %b %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.339 {parse yymmdd} {
+ clock scan {70 Dec 31} -format {%y %b %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.340 {parse yymmdd} {
+ clock scan {70 Dec xxxi} -format {%y %b %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.341 {parse yymmdd} {
+ clock scan {70 December 31} -format {%y %B %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.342 {parse yymmdd} {
+ clock scan {70 December xxxi} -format {%y %B %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.343 {parse yymmdd} {
+ clock scan {70 December 31} -format {%y %B %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.344 {parse yymmdd} {
+ clock scan {70 December xxxi} -format {%y %B %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.345 {parse yymmdd} {
+ clock scan {70 Dec 31} -format {%y %h %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.346 {parse yymmdd} {
+ clock scan {70 Dec xxxi} -format {%y %h %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.347 {parse yymmdd} {
+ clock scan {70 Dec 31} -format {%y %h %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.348 {parse yymmdd} {
+ clock scan {70 Dec xxxi} -format {%y %h %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.349 {parse yymmdd} {
+ clock scan {70 12 31} -format {%y %m %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.350 {parse yymmdd} {
+ clock scan {70 12 xxxi} -format {%y %m %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.351 {parse yymmdd} {
+ clock scan {70 12 31} -format {%y %m %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.352 {parse yymmdd} {
+ clock scan {70 12 xxxi} -format {%y %m %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.353 {parse yymmdd} {
+ clock scan {70 xii 31} -format {%y %Om %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.354 {parse yymmdd} {
+ clock scan {70 xii xxxi} -format {%y %Om %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.355 {parse yymmdd} {
+ clock scan {70 xii 31} -format {%y %Om %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.356 {parse yymmdd} {
+ clock scan {70 xii xxxi} -format {%y %Om %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.357 {parse yymmdd} {
+ clock scan {70 12 31} -format {%y %N %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.358 {parse yymmdd} {
+ clock scan {70 12 xxxi} -format {%y %N %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.359 {parse yymmdd} {
+ clock scan {70 12 31} -format {%y %N %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.360 {parse yymmdd} {
+ clock scan {70 12 xxxi} -format {%y %N %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.361 {parse yymmdd} {
+ clock scan {lxx Dec 31} -format {%Oy %b %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.362 {parse yymmdd} {
+ clock scan {lxx Dec xxxi} -format {%Oy %b %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.363 {parse yymmdd} {
+ clock scan {lxx Dec 31} -format {%Oy %b %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.364 {parse yymmdd} {
+ clock scan {lxx Dec xxxi} -format {%Oy %b %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.365 {parse yymmdd} {
+ clock scan {lxx December 31} -format {%Oy %B %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.366 {parse yymmdd} {
+ clock scan {lxx December xxxi} -format {%Oy %B %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.367 {parse yymmdd} {
+ clock scan {lxx December 31} -format {%Oy %B %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.368 {parse yymmdd} {
+ clock scan {lxx December xxxi} -format {%Oy %B %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.369 {parse yymmdd} {
+ clock scan {lxx Dec 31} -format {%Oy %h %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.370 {parse yymmdd} {
+ clock scan {lxx Dec xxxi} -format {%Oy %h %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.371 {parse yymmdd} {
+ clock scan {lxx Dec 31} -format {%Oy %h %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.372 {parse yymmdd} {
+ clock scan {lxx Dec xxxi} -format {%Oy %h %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.373 {parse yymmdd} {
+ clock scan {lxx 12 31} -format {%Oy %m %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.374 {parse yymmdd} {
+ clock scan {lxx 12 xxxi} -format {%Oy %m %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.375 {parse yymmdd} {
+ clock scan {lxx 12 31} -format {%Oy %m %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.376 {parse yymmdd} {
+ clock scan {lxx 12 xxxi} -format {%Oy %m %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.377 {parse yymmdd} {
+ clock scan {lxx xii 31} -format {%Oy %Om %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.378 {parse yymmdd} {
+ clock scan {lxx xii xxxi} -format {%Oy %Om %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.379 {parse yymmdd} {
+ clock scan {lxx xii 31} -format {%Oy %Om %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.380 {parse yymmdd} {
+ clock scan {lxx xii xxxi} -format {%Oy %Om %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.381 {parse yymmdd} {
+ clock scan {lxx 12 31} -format {%Oy %N %d} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.382 {parse yymmdd} {
+ clock scan {lxx 12 xxxi} -format {%Oy %N %Od} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.383 {parse yymmdd} {
+ clock scan {lxx 12 31} -format {%Oy %N %e} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.384 {parse yymmdd} {
+ clock scan {lxx 12 xxxi} -format {%Oy %N %Oe} -locale en_US_roman -gmt 1
+} 31449600
+test clock-14.385 {parse yymmdd} {
+ clock scan {00 Jan 02} -format {%y %b %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.386 {parse yymmdd} {
+ clock scan {00 Jan ii} -format {%y %b %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.387 {parse yymmdd} {
+ clock scan {00 Jan 2} -format {%y %b %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.388 {parse yymmdd} {
+ clock scan {00 Jan ii} -format {%y %b %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.389 {parse yymmdd} {
+ clock scan {00 January 02} -format {%y %B %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.390 {parse yymmdd} {
+ clock scan {00 January ii} -format {%y %B %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.391 {parse yymmdd} {
+ clock scan {00 January 2} -format {%y %B %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.392 {parse yymmdd} {
+ clock scan {00 January ii} -format {%y %B %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.393 {parse yymmdd} {
+ clock scan {00 Jan 02} -format {%y %h %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.394 {parse yymmdd} {
+ clock scan {00 Jan ii} -format {%y %h %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.395 {parse yymmdd} {
+ clock scan {00 Jan 2} -format {%y %h %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.396 {parse yymmdd} {
+ clock scan {00 Jan ii} -format {%y %h %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.397 {parse yymmdd} {
+ clock scan {00 01 02} -format {%y %m %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.398 {parse yymmdd} {
+ clock scan {00 01 ii} -format {%y %m %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.399 {parse yymmdd} {
+ clock scan {00 01 2} -format {%y %m %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.400 {parse yymmdd} {
+ clock scan {00 01 ii} -format {%y %m %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.401 {parse yymmdd} {
+ clock scan {00 i 02} -format {%y %Om %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.402 {parse yymmdd} {
+ clock scan {00 i ii} -format {%y %Om %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.403 {parse yymmdd} {
+ clock scan {00 i 2} -format {%y %Om %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.404 {parse yymmdd} {
+ clock scan {00 i ii} -format {%y %Om %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.405 {parse yymmdd} {
+ clock scan {00 1 02} -format {%y %N %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.406 {parse yymmdd} {
+ clock scan {00 1 ii} -format {%y %N %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.407 {parse yymmdd} {
+ clock scan {00 1 2} -format {%y %N %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.408 {parse yymmdd} {
+ clock scan {00 1 ii} -format {%y %N %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.409 {parse yymmdd} {
+ clock scan {? Jan 02} -format {%Oy %b %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.410 {parse yymmdd} {
+ clock scan {? Jan ii} -format {%Oy %b %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.411 {parse yymmdd} {
+ clock scan {? Jan 2} -format {%Oy %b %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.412 {parse yymmdd} {
+ clock scan {? Jan ii} -format {%Oy %b %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.413 {parse yymmdd} {
+ clock scan {? January 02} -format {%Oy %B %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.414 {parse yymmdd} {
+ clock scan {? January ii} -format {%Oy %B %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.415 {parse yymmdd} {
+ clock scan {? January 2} -format {%Oy %B %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.416 {parse yymmdd} {
+ clock scan {? January ii} -format {%Oy %B %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.417 {parse yymmdd} {
+ clock scan {? Jan 02} -format {%Oy %h %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.418 {parse yymmdd} {
+ clock scan {? Jan ii} -format {%Oy %h %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.419 {parse yymmdd} {
+ clock scan {? Jan 2} -format {%Oy %h %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.420 {parse yymmdd} {
+ clock scan {? Jan ii} -format {%Oy %h %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.421 {parse yymmdd} {
+ clock scan {? 01 02} -format {%Oy %m %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.422 {parse yymmdd} {
+ clock scan {? 01 ii} -format {%Oy %m %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.423 {parse yymmdd} {
+ clock scan {? 01 2} -format {%Oy %m %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.424 {parse yymmdd} {
+ clock scan {? 01 ii} -format {%Oy %m %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.425 {parse yymmdd} {
+ clock scan {? i 02} -format {%Oy %Om %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.426 {parse yymmdd} {
+ clock scan {? i ii} -format {%Oy %Om %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.427 {parse yymmdd} {
+ clock scan {? i 2} -format {%Oy %Om %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.428 {parse yymmdd} {
+ clock scan {? i ii} -format {%Oy %Om %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.429 {parse yymmdd} {
+ clock scan {? 1 02} -format {%Oy %N %d} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.430 {parse yymmdd} {
+ clock scan {? 1 ii} -format {%Oy %N %Od} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.431 {parse yymmdd} {
+ clock scan {? 1 2} -format {%Oy %N %e} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.432 {parse yymmdd} {
+ clock scan {? 1 ii} -format {%Oy %N %Oe} -locale en_US_roman -gmt 1
+} 946771200
+test clock-14.433 {parse yymmdd} {
+ clock scan {00 Jan 31} -format {%y %b %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.434 {parse yymmdd} {
+ clock scan {00 Jan xxxi} -format {%y %b %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.435 {parse yymmdd} {
+ clock scan {00 Jan 31} -format {%y %b %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.436 {parse yymmdd} {
+ clock scan {00 Jan xxxi} -format {%y %b %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.437 {parse yymmdd} {
+ clock scan {00 January 31} -format {%y %B %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.438 {parse yymmdd} {
+ clock scan {00 January xxxi} -format {%y %B %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.439 {parse yymmdd} {
+ clock scan {00 January 31} -format {%y %B %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.440 {parse yymmdd} {
+ clock scan {00 January xxxi} -format {%y %B %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.441 {parse yymmdd} {
+ clock scan {00 Jan 31} -format {%y %h %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.442 {parse yymmdd} {
+ clock scan {00 Jan xxxi} -format {%y %h %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.443 {parse yymmdd} {
+ clock scan {00 Jan 31} -format {%y %h %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.444 {parse yymmdd} {
+ clock scan {00 Jan xxxi} -format {%y %h %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.445 {parse yymmdd} {
+ clock scan {00 01 31} -format {%y %m %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.446 {parse yymmdd} {
+ clock scan {00 01 xxxi} -format {%y %m %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.447 {parse yymmdd} {
+ clock scan {00 01 31} -format {%y %m %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.448 {parse yymmdd} {
+ clock scan {00 01 xxxi} -format {%y %m %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.449 {parse yymmdd} {
+ clock scan {00 i 31} -format {%y %Om %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.450 {parse yymmdd} {
+ clock scan {00 i xxxi} -format {%y %Om %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.451 {parse yymmdd} {
+ clock scan {00 i 31} -format {%y %Om %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.452 {parse yymmdd} {
+ clock scan {00 i xxxi} -format {%y %Om %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.453 {parse yymmdd} {
+ clock scan {00 1 31} -format {%y %N %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.454 {parse yymmdd} {
+ clock scan {00 1 xxxi} -format {%y %N %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.455 {parse yymmdd} {
+ clock scan {00 1 31} -format {%y %N %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.456 {parse yymmdd} {
+ clock scan {00 1 xxxi} -format {%y %N %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.457 {parse yymmdd} {
+ clock scan {? Jan 31} -format {%Oy %b %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.458 {parse yymmdd} {
+ clock scan {? Jan xxxi} -format {%Oy %b %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.459 {parse yymmdd} {
+ clock scan {? Jan 31} -format {%Oy %b %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.460 {parse yymmdd} {
+ clock scan {? Jan xxxi} -format {%Oy %b %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.461 {parse yymmdd} {
+ clock scan {? January 31} -format {%Oy %B %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.462 {parse yymmdd} {
+ clock scan {? January xxxi} -format {%Oy %B %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.463 {parse yymmdd} {
+ clock scan {? January 31} -format {%Oy %B %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.464 {parse yymmdd} {
+ clock scan {? January xxxi} -format {%Oy %B %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.465 {parse yymmdd} {
+ clock scan {? Jan 31} -format {%Oy %h %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.466 {parse yymmdd} {
+ clock scan {? Jan xxxi} -format {%Oy %h %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.467 {parse yymmdd} {
+ clock scan {? Jan 31} -format {%Oy %h %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.468 {parse yymmdd} {
+ clock scan {? Jan xxxi} -format {%Oy %h %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.469 {parse yymmdd} {
+ clock scan {? 01 31} -format {%Oy %m %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.470 {parse yymmdd} {
+ clock scan {? 01 xxxi} -format {%Oy %m %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.471 {parse yymmdd} {
+ clock scan {? 01 31} -format {%Oy %m %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.472 {parse yymmdd} {
+ clock scan {? 01 xxxi} -format {%Oy %m %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.473 {parse yymmdd} {
+ clock scan {? i 31} -format {%Oy %Om %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.474 {parse yymmdd} {
+ clock scan {? i xxxi} -format {%Oy %Om %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.475 {parse yymmdd} {
+ clock scan {? i 31} -format {%Oy %Om %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.476 {parse yymmdd} {
+ clock scan {? i xxxi} -format {%Oy %Om %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.477 {parse yymmdd} {
+ clock scan {? 1 31} -format {%Oy %N %d} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.478 {parse yymmdd} {
+ clock scan {? 1 xxxi} -format {%Oy %N %Od} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.479 {parse yymmdd} {
+ clock scan {? 1 31} -format {%Oy %N %e} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.480 {parse yymmdd} {
+ clock scan {? 1 xxxi} -format {%Oy %N %Oe} -locale en_US_roman -gmt 1
+} 949276800
+test clock-14.481 {parse yymmdd} {
+ clock scan {00 Dec 02} -format {%y %b %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.482 {parse yymmdd} {
+ clock scan {00 Dec ii} -format {%y %b %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.483 {parse yymmdd} {
+ clock scan {00 Dec 2} -format {%y %b %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.484 {parse yymmdd} {
+ clock scan {00 Dec ii} -format {%y %b %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.485 {parse yymmdd} {
+ clock scan {00 December 02} -format {%y %B %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.486 {parse yymmdd} {
+ clock scan {00 December ii} -format {%y %B %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.487 {parse yymmdd} {
+ clock scan {00 December 2} -format {%y %B %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.488 {parse yymmdd} {
+ clock scan {00 December ii} -format {%y %B %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.489 {parse yymmdd} {
+ clock scan {00 Dec 02} -format {%y %h %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.490 {parse yymmdd} {
+ clock scan {00 Dec ii} -format {%y %h %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.491 {parse yymmdd} {
+ clock scan {00 Dec 2} -format {%y %h %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.492 {parse yymmdd} {
+ clock scan {00 Dec ii} -format {%y %h %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.493 {parse yymmdd} {
+ clock scan {00 12 02} -format {%y %m %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.494 {parse yymmdd} {
+ clock scan {00 12 ii} -format {%y %m %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.495 {parse yymmdd} {
+ clock scan {00 12 2} -format {%y %m %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.496 {parse yymmdd} {
+ clock scan {00 12 ii} -format {%y %m %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.497 {parse yymmdd} {
+ clock scan {00 xii 02} -format {%y %Om %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.498 {parse yymmdd} {
+ clock scan {00 xii ii} -format {%y %Om %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.499 {parse yymmdd} {
+ clock scan {00 xii 2} -format {%y %Om %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.500 {parse yymmdd} {
+ clock scan {00 xii ii} -format {%y %Om %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.501 {parse yymmdd} {
+ clock scan {00 12 02} -format {%y %N %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.502 {parse yymmdd} {
+ clock scan {00 12 ii} -format {%y %N %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.503 {parse yymmdd} {
+ clock scan {00 12 2} -format {%y %N %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.504 {parse yymmdd} {
+ clock scan {00 12 ii} -format {%y %N %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.505 {parse yymmdd} {
+ clock scan {? Dec 02} -format {%Oy %b %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.506 {parse yymmdd} {
+ clock scan {? Dec ii} -format {%Oy %b %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.507 {parse yymmdd} {
+ clock scan {? Dec 2} -format {%Oy %b %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.508 {parse yymmdd} {
+ clock scan {? Dec ii} -format {%Oy %b %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.509 {parse yymmdd} {
+ clock scan {? December 02} -format {%Oy %B %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.510 {parse yymmdd} {
+ clock scan {? December ii} -format {%Oy %B %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.511 {parse yymmdd} {
+ clock scan {? December 2} -format {%Oy %B %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.512 {parse yymmdd} {
+ clock scan {? December ii} -format {%Oy %B %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.513 {parse yymmdd} {
+ clock scan {? Dec 02} -format {%Oy %h %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.514 {parse yymmdd} {
+ clock scan {? Dec ii} -format {%Oy %h %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.515 {parse yymmdd} {
+ clock scan {? Dec 2} -format {%Oy %h %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.516 {parse yymmdd} {
+ clock scan {? Dec ii} -format {%Oy %h %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.517 {parse yymmdd} {
+ clock scan {? 12 02} -format {%Oy %m %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.518 {parse yymmdd} {
+ clock scan {? 12 ii} -format {%Oy %m %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.519 {parse yymmdd} {
+ clock scan {? 12 2} -format {%Oy %m %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.520 {parse yymmdd} {
+ clock scan {? 12 ii} -format {%Oy %m %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.521 {parse yymmdd} {
+ clock scan {? xii 02} -format {%Oy %Om %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.522 {parse yymmdd} {
+ clock scan {? xii ii} -format {%Oy %Om %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.523 {parse yymmdd} {
+ clock scan {? xii 2} -format {%Oy %Om %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.524 {parse yymmdd} {
+ clock scan {? xii ii} -format {%Oy %Om %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.525 {parse yymmdd} {
+ clock scan {? 12 02} -format {%Oy %N %d} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.526 {parse yymmdd} {
+ clock scan {? 12 ii} -format {%Oy %N %Od} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.527 {parse yymmdd} {
+ clock scan {? 12 2} -format {%Oy %N %e} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.528 {parse yymmdd} {
+ clock scan {? 12 ii} -format {%Oy %N %Oe} -locale en_US_roman -gmt 1
+} 975715200
+test clock-14.529 {parse yymmdd} {
+ clock scan {00 Dec 31} -format {%y %b %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.530 {parse yymmdd} {
+ clock scan {00 Dec xxxi} -format {%y %b %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.531 {parse yymmdd} {
+ clock scan {00 Dec 31} -format {%y %b %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.532 {parse yymmdd} {
+ clock scan {00 Dec xxxi} -format {%y %b %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.533 {parse yymmdd} {
+ clock scan {00 December 31} -format {%y %B %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.534 {parse yymmdd} {
+ clock scan {00 December xxxi} -format {%y %B %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.535 {parse yymmdd} {
+ clock scan {00 December 31} -format {%y %B %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.536 {parse yymmdd} {
+ clock scan {00 December xxxi} -format {%y %B %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.537 {parse yymmdd} {
+ clock scan {00 Dec 31} -format {%y %h %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.538 {parse yymmdd} {
+ clock scan {00 Dec xxxi} -format {%y %h %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.539 {parse yymmdd} {
+ clock scan {00 Dec 31} -format {%y %h %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.540 {parse yymmdd} {
+ clock scan {00 Dec xxxi} -format {%y %h %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.541 {parse yymmdd} {
+ clock scan {00 12 31} -format {%y %m %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.542 {parse yymmdd} {
+ clock scan {00 12 xxxi} -format {%y %m %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.543 {parse yymmdd} {
+ clock scan {00 12 31} -format {%y %m %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.544 {parse yymmdd} {
+ clock scan {00 12 xxxi} -format {%y %m %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.545 {parse yymmdd} {
+ clock scan {00 xii 31} -format {%y %Om %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.546 {parse yymmdd} {
+ clock scan {00 xii xxxi} -format {%y %Om %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.547 {parse yymmdd} {
+ clock scan {00 xii 31} -format {%y %Om %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.548 {parse yymmdd} {
+ clock scan {00 xii xxxi} -format {%y %Om %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.549 {parse yymmdd} {
+ clock scan {00 12 31} -format {%y %N %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.550 {parse yymmdd} {
+ clock scan {00 12 xxxi} -format {%y %N %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.551 {parse yymmdd} {
+ clock scan {00 12 31} -format {%y %N %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.552 {parse yymmdd} {
+ clock scan {00 12 xxxi} -format {%y %N %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.553 {parse yymmdd} {
+ clock scan {? Dec 31} -format {%Oy %b %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.554 {parse yymmdd} {
+ clock scan {? Dec xxxi} -format {%Oy %b %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.555 {parse yymmdd} {
+ clock scan {? Dec 31} -format {%Oy %b %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.556 {parse yymmdd} {
+ clock scan {? Dec xxxi} -format {%Oy %b %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.557 {parse yymmdd} {
+ clock scan {? December 31} -format {%Oy %B %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.558 {parse yymmdd} {
+ clock scan {? December xxxi} -format {%Oy %B %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.559 {parse yymmdd} {
+ clock scan {? December 31} -format {%Oy %B %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.560 {parse yymmdd} {
+ clock scan {? December xxxi} -format {%Oy %B %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.561 {parse yymmdd} {
+ clock scan {? Dec 31} -format {%Oy %h %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.562 {parse yymmdd} {
+ clock scan {? Dec xxxi} -format {%Oy %h %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.563 {parse yymmdd} {
+ clock scan {? Dec 31} -format {%Oy %h %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.564 {parse yymmdd} {
+ clock scan {? Dec xxxi} -format {%Oy %h %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.565 {parse yymmdd} {
+ clock scan {? 12 31} -format {%Oy %m %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.566 {parse yymmdd} {
+ clock scan {? 12 xxxi} -format {%Oy %m %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.567 {parse yymmdd} {
+ clock scan {? 12 31} -format {%Oy %m %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.568 {parse yymmdd} {
+ clock scan {? 12 xxxi} -format {%Oy %m %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.569 {parse yymmdd} {
+ clock scan {? xii 31} -format {%Oy %Om %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.570 {parse yymmdd} {
+ clock scan {? xii xxxi} -format {%Oy %Om %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.571 {parse yymmdd} {
+ clock scan {? xii 31} -format {%Oy %Om %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.572 {parse yymmdd} {
+ clock scan {? xii xxxi} -format {%Oy %Om %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.573 {parse yymmdd} {
+ clock scan {? 12 31} -format {%Oy %N %d} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.574 {parse yymmdd} {
+ clock scan {? 12 xxxi} -format {%Oy %N %Od} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.575 {parse yymmdd} {
+ clock scan {? 12 31} -format {%Oy %N %e} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.576 {parse yymmdd} {
+ clock scan {? 12 xxxi} -format {%Oy %N %Oe} -locale en_US_roman -gmt 1
+} 978220800
+test clock-14.577 {parse yymmdd} {
+ clock scan {37 Jan 02} -format {%y %b %d} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.578 {parse yymmdd} {
+ clock scan {37 Jan ii} -format {%y %b %Od} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.579 {parse yymmdd} {
+ clock scan {37 Jan 2} -format {%y %b %e} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.580 {parse yymmdd} {
+ clock scan {37 Jan ii} -format {%y %b %Oe} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.581 {parse yymmdd} {
+ clock scan {37 January 02} -format {%y %B %d} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.582 {parse yymmdd} {
+ clock scan {37 January ii} -format {%y %B %Od} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.583 {parse yymmdd} {
+ clock scan {37 January 2} -format {%y %B %e} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.584 {parse yymmdd} {
+ clock scan {37 January ii} -format {%y %B %Oe} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.585 {parse yymmdd} {
+ clock scan {37 Jan 02} -format {%y %h %d} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.586 {parse yymmdd} {
+ clock scan {37 Jan ii} -format {%y %h %Od} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.587 {parse yymmdd} {
+ clock scan {37 Jan 2} -format {%y %h %e} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.588 {parse yymmdd} {
+ clock scan {37 Jan ii} -format {%y %h %Oe} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.589 {parse yymmdd} {
+ clock scan {37 01 02} -format {%y %m %d} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.590 {parse yymmdd} {
+ clock scan {37 01 ii} -format {%y %m %Od} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.591 {parse yymmdd} {
+ clock scan {37 01 2} -format {%y %m %e} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.592 {parse yymmdd} {
+ clock scan {37 01 ii} -format {%y %m %Oe} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.593 {parse yymmdd} {
+ clock scan {37 i 02} -format {%y %Om %d} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.594 {parse yymmdd} {
+ clock scan {37 i ii} -format {%y %Om %Od} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.595 {parse yymmdd} {
+ clock scan {37 i 2} -format {%y %Om %e} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.596 {parse yymmdd} {
+ clock scan {37 i ii} -format {%y %Om %Oe} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.597 {parse yymmdd} {
+ clock scan {37 1 02} -format {%y %N %d} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.598 {parse yymmdd} {
+ clock scan {37 1 ii} -format {%y %N %Od} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.599 {parse yymmdd} {
+ clock scan {37 1 2} -format {%y %N %e} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.600 {parse yymmdd} {
+ clock scan {37 1 ii} -format {%y %N %Oe} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.601 {parse yymmdd} {
+ clock scan {xxxvii Jan 02} -format {%Oy %b %d} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.602 {parse yymmdd} {
+ clock scan {xxxvii Jan ii} -format {%Oy %b %Od} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.603 {parse yymmdd} {
+ clock scan {xxxvii Jan 2} -format {%Oy %b %e} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.604 {parse yymmdd} {
+ clock scan {xxxvii Jan ii} -format {%Oy %b %Oe} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.605 {parse yymmdd} {
+ clock scan {xxxvii January 02} -format {%Oy %B %d} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.606 {parse yymmdd} {
+ clock scan {xxxvii January ii} -format {%Oy %B %Od} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.607 {parse yymmdd} {
+ clock scan {xxxvii January 2} -format {%Oy %B %e} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.608 {parse yymmdd} {
+ clock scan {xxxvii January ii} -format {%Oy %B %Oe} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.609 {parse yymmdd} {
+ clock scan {xxxvii Jan 02} -format {%Oy %h %d} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.610 {parse yymmdd} {
+ clock scan {xxxvii Jan ii} -format {%Oy %h %Od} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.611 {parse yymmdd} {
+ clock scan {xxxvii Jan 2} -format {%Oy %h %e} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.612 {parse yymmdd} {
+ clock scan {xxxvii Jan ii} -format {%Oy %h %Oe} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.613 {parse yymmdd} {
+ clock scan {xxxvii 01 02} -format {%Oy %m %d} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.614 {parse yymmdd} {
+ clock scan {xxxvii 01 ii} -format {%Oy %m %Od} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.615 {parse yymmdd} {
+ clock scan {xxxvii 01 2} -format {%Oy %m %e} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.616 {parse yymmdd} {
+ clock scan {xxxvii 01 ii} -format {%Oy %m %Oe} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.617 {parse yymmdd} {
+ clock scan {xxxvii i 02} -format {%Oy %Om %d} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.618 {parse yymmdd} {
+ clock scan {xxxvii i ii} -format {%Oy %Om %Od} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.619 {parse yymmdd} {
+ clock scan {xxxvii i 2} -format {%Oy %Om %e} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.620 {parse yymmdd} {
+ clock scan {xxxvii i ii} -format {%Oy %Om %Oe} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.621 {parse yymmdd} {
+ clock scan {xxxvii 1 02} -format {%Oy %N %d} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.622 {parse yymmdd} {
+ clock scan {xxxvii 1 ii} -format {%Oy %N %Od} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.623 {parse yymmdd} {
+ clock scan {xxxvii 1 2} -format {%Oy %N %e} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.624 {parse yymmdd} {
+ clock scan {xxxvii 1 ii} -format {%Oy %N %Oe} -locale en_US_roman -gmt 1
+} 2114467200
+test clock-14.625 {parse yymmdd} {
+ clock scan {37 Jan 31} -format {%y %b %d} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.626 {parse yymmdd} {
+ clock scan {37 Jan xxxi} -format {%y %b %Od} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.627 {parse yymmdd} {
+ clock scan {37 Jan 31} -format {%y %b %e} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.628 {parse yymmdd} {
+ clock scan {37 Jan xxxi} -format {%y %b %Oe} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.629 {parse yymmdd} {
+ clock scan {37 January 31} -format {%y %B %d} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.630 {parse yymmdd} {
+ clock scan {37 January xxxi} -format {%y %B %Od} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.631 {parse yymmdd} {
+ clock scan {37 January 31} -format {%y %B %e} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.632 {parse yymmdd} {
+ clock scan {37 January xxxi} -format {%y %B %Oe} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.633 {parse yymmdd} {
+ clock scan {37 Jan 31} -format {%y %h %d} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.634 {parse yymmdd} {
+ clock scan {37 Jan xxxi} -format {%y %h %Od} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.635 {parse yymmdd} {
+ clock scan {37 Jan 31} -format {%y %h %e} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.636 {parse yymmdd} {
+ clock scan {37 Jan xxxi} -format {%y %h %Oe} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.637 {parse yymmdd} {
+ clock scan {37 01 31} -format {%y %m %d} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.638 {parse yymmdd} {
+ clock scan {37 01 xxxi} -format {%y %m %Od} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.639 {parse yymmdd} {
+ clock scan {37 01 31} -format {%y %m %e} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.640 {parse yymmdd} {
+ clock scan {37 01 xxxi} -format {%y %m %Oe} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.641 {parse yymmdd} {
+ clock scan {37 i 31} -format {%y %Om %d} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.642 {parse yymmdd} {
+ clock scan {37 i xxxi} -format {%y %Om %Od} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.643 {parse yymmdd} {
+ clock scan {37 i 31} -format {%y %Om %e} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.644 {parse yymmdd} {
+ clock scan {37 i xxxi} -format {%y %Om %Oe} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.645 {parse yymmdd} {
+ clock scan {37 1 31} -format {%y %N %d} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.646 {parse yymmdd} {
+ clock scan {37 1 xxxi} -format {%y %N %Od} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.647 {parse yymmdd} {
+ clock scan {37 1 31} -format {%y %N %e} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.648 {parse yymmdd} {
+ clock scan {37 1 xxxi} -format {%y %N %Oe} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.649 {parse yymmdd} {
+ clock scan {xxxvii Jan 31} -format {%Oy %b %d} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.650 {parse yymmdd} {
+ clock scan {xxxvii Jan xxxi} -format {%Oy %b %Od} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.651 {parse yymmdd} {
+ clock scan {xxxvii Jan 31} -format {%Oy %b %e} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.652 {parse yymmdd} {
+ clock scan {xxxvii Jan xxxi} -format {%Oy %b %Oe} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.653 {parse yymmdd} {
+ clock scan {xxxvii January 31} -format {%Oy %B %d} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.654 {parse yymmdd} {
+ clock scan {xxxvii January xxxi} -format {%Oy %B %Od} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.655 {parse yymmdd} {
+ clock scan {xxxvii January 31} -format {%Oy %B %e} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.656 {parse yymmdd} {
+ clock scan {xxxvii January xxxi} -format {%Oy %B %Oe} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.657 {parse yymmdd} {
+ clock scan {xxxvii Jan 31} -format {%Oy %h %d} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.658 {parse yymmdd} {
+ clock scan {xxxvii Jan xxxi} -format {%Oy %h %Od} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.659 {parse yymmdd} {
+ clock scan {xxxvii Jan 31} -format {%Oy %h %e} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.660 {parse yymmdd} {
+ clock scan {xxxvii Jan xxxi} -format {%Oy %h %Oe} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.661 {parse yymmdd} {
+ clock scan {xxxvii 01 31} -format {%Oy %m %d} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.662 {parse yymmdd} {
+ clock scan {xxxvii 01 xxxi} -format {%Oy %m %Od} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.663 {parse yymmdd} {
+ clock scan {xxxvii 01 31} -format {%Oy %m %e} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.664 {parse yymmdd} {
+ clock scan {xxxvii 01 xxxi} -format {%Oy %m %Oe} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.665 {parse yymmdd} {
+ clock scan {xxxvii i 31} -format {%Oy %Om %d} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.666 {parse yymmdd} {
+ clock scan {xxxvii i xxxi} -format {%Oy %Om %Od} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.667 {parse yymmdd} {
+ clock scan {xxxvii i 31} -format {%Oy %Om %e} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.668 {parse yymmdd} {
+ clock scan {xxxvii i xxxi} -format {%Oy %Om %Oe} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.669 {parse yymmdd} {
+ clock scan {xxxvii 1 31} -format {%Oy %N %d} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.670 {parse yymmdd} {
+ clock scan {xxxvii 1 xxxi} -format {%Oy %N %Od} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.671 {parse yymmdd} {
+ clock scan {xxxvii 1 31} -format {%Oy %N %e} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.672 {parse yymmdd} {
+ clock scan {xxxvii 1 xxxi} -format {%Oy %N %Oe} -locale en_US_roman -gmt 1
+} 2116972800
+test clock-14.673 {parse yymmdd} {
+ clock scan {37 Dec 02} -format {%y %b %d} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.674 {parse yymmdd} {
+ clock scan {37 Dec ii} -format {%y %b %Od} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.675 {parse yymmdd} {
+ clock scan {37 Dec 2} -format {%y %b %e} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.676 {parse yymmdd} {
+ clock scan {37 Dec ii} -format {%y %b %Oe} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.677 {parse yymmdd} {
+ clock scan {37 December 02} -format {%y %B %d} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.678 {parse yymmdd} {
+ clock scan {37 December ii} -format {%y %B %Od} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.679 {parse yymmdd} {
+ clock scan {37 December 2} -format {%y %B %e} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.680 {parse yymmdd} {
+ clock scan {37 December ii} -format {%y %B %Oe} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.681 {parse yymmdd} {
+ clock scan {37 Dec 02} -format {%y %h %d} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.682 {parse yymmdd} {
+ clock scan {37 Dec ii} -format {%y %h %Od} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.683 {parse yymmdd} {
+ clock scan {37 Dec 2} -format {%y %h %e} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.684 {parse yymmdd} {
+ clock scan {37 Dec ii} -format {%y %h %Oe} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.685 {parse yymmdd} {
+ clock scan {37 12 02} -format {%y %m %d} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.686 {parse yymmdd} {
+ clock scan {37 12 ii} -format {%y %m %Od} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.687 {parse yymmdd} {
+ clock scan {37 12 2} -format {%y %m %e} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.688 {parse yymmdd} {
+ clock scan {37 12 ii} -format {%y %m %Oe} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.689 {parse yymmdd} {
+ clock scan {37 xii 02} -format {%y %Om %d} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.690 {parse yymmdd} {
+ clock scan {37 xii ii} -format {%y %Om %Od} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.691 {parse yymmdd} {
+ clock scan {37 xii 2} -format {%y %Om %e} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.692 {parse yymmdd} {
+ clock scan {37 xii ii} -format {%y %Om %Oe} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.693 {parse yymmdd} {
+ clock scan {37 12 02} -format {%y %N %d} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.694 {parse yymmdd} {
+ clock scan {37 12 ii} -format {%y %N %Od} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.695 {parse yymmdd} {
+ clock scan {37 12 2} -format {%y %N %e} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.696 {parse yymmdd} {
+ clock scan {37 12 ii} -format {%y %N %Oe} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.697 {parse yymmdd} {
+ clock scan {xxxvii Dec 02} -format {%Oy %b %d} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.698 {parse yymmdd} {
+ clock scan {xxxvii Dec ii} -format {%Oy %b %Od} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.699 {parse yymmdd} {
+ clock scan {xxxvii Dec 2} -format {%Oy %b %e} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.700 {parse yymmdd} {
+ clock scan {xxxvii Dec ii} -format {%Oy %b %Oe} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.701 {parse yymmdd} {
+ clock scan {xxxvii December 02} -format {%Oy %B %d} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.702 {parse yymmdd} {
+ clock scan {xxxvii December ii} -format {%Oy %B %Od} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.703 {parse yymmdd} {
+ clock scan {xxxvii December 2} -format {%Oy %B %e} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.704 {parse yymmdd} {
+ clock scan {xxxvii December ii} -format {%Oy %B %Oe} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.705 {parse yymmdd} {
+ clock scan {xxxvii Dec 02} -format {%Oy %h %d} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.706 {parse yymmdd} {
+ clock scan {xxxvii Dec ii} -format {%Oy %h %Od} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.707 {parse yymmdd} {
+ clock scan {xxxvii Dec 2} -format {%Oy %h %e} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.708 {parse yymmdd} {
+ clock scan {xxxvii Dec ii} -format {%Oy %h %Oe} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.709 {parse yymmdd} {
+ clock scan {xxxvii 12 02} -format {%Oy %m %d} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.710 {parse yymmdd} {
+ clock scan {xxxvii 12 ii} -format {%Oy %m %Od} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.711 {parse yymmdd} {
+ clock scan {xxxvii 12 2} -format {%Oy %m %e} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.712 {parse yymmdd} {
+ clock scan {xxxvii 12 ii} -format {%Oy %m %Oe} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.713 {parse yymmdd} {
+ clock scan {xxxvii xii 02} -format {%Oy %Om %d} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.714 {parse yymmdd} {
+ clock scan {xxxvii xii ii} -format {%Oy %Om %Od} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.715 {parse yymmdd} {
+ clock scan {xxxvii xii 2} -format {%Oy %Om %e} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.716 {parse yymmdd} {
+ clock scan {xxxvii xii ii} -format {%Oy %Om %Oe} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.717 {parse yymmdd} {
+ clock scan {xxxvii 12 02} -format {%Oy %N %d} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.718 {parse yymmdd} {
+ clock scan {xxxvii 12 ii} -format {%Oy %N %Od} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.719 {parse yymmdd} {
+ clock scan {xxxvii 12 2} -format {%Oy %N %e} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.720 {parse yymmdd} {
+ clock scan {xxxvii 12 ii} -format {%Oy %N %Oe} -locale en_US_roman -gmt 1
+} 2143324800
+test clock-14.721 {parse yymmdd} {
+ clock scan {37 Dec 31} -format {%y %b %d} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.722 {parse yymmdd} {
+ clock scan {37 Dec xxxi} -format {%y %b %Od} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.723 {parse yymmdd} {
+ clock scan {37 Dec 31} -format {%y %b %e} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.724 {parse yymmdd} {
+ clock scan {37 Dec xxxi} -format {%y %b %Oe} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.725 {parse yymmdd} {
+ clock scan {37 December 31} -format {%y %B %d} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.726 {parse yymmdd} {
+ clock scan {37 December xxxi} -format {%y %B %Od} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.727 {parse yymmdd} {
+ clock scan {37 December 31} -format {%y %B %e} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.728 {parse yymmdd} {
+ clock scan {37 December xxxi} -format {%y %B %Oe} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.729 {parse yymmdd} {
+ clock scan {37 Dec 31} -format {%y %h %d} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.730 {parse yymmdd} {
+ clock scan {37 Dec xxxi} -format {%y %h %Od} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.731 {parse yymmdd} {
+ clock scan {37 Dec 31} -format {%y %h %e} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.732 {parse yymmdd} {
+ clock scan {37 Dec xxxi} -format {%y %h %Oe} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.733 {parse yymmdd} {
+ clock scan {37 12 31} -format {%y %m %d} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.734 {parse yymmdd} {
+ clock scan {37 12 xxxi} -format {%y %m %Od} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.735 {parse yymmdd} {
+ clock scan {37 12 31} -format {%y %m %e} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.736 {parse yymmdd} {
+ clock scan {37 12 xxxi} -format {%y %m %Oe} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.737 {parse yymmdd} {
+ clock scan {37 xii 31} -format {%y %Om %d} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.738 {parse yymmdd} {
+ clock scan {37 xii xxxi} -format {%y %Om %Od} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.739 {parse yymmdd} {
+ clock scan {37 xii 31} -format {%y %Om %e} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.740 {parse yymmdd} {
+ clock scan {37 xii xxxi} -format {%y %Om %Oe} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.741 {parse yymmdd} {
+ clock scan {37 12 31} -format {%y %N %d} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.742 {parse yymmdd} {
+ clock scan {37 12 xxxi} -format {%y %N %Od} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.743 {parse yymmdd} {
+ clock scan {37 12 31} -format {%y %N %e} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.744 {parse yymmdd} {
+ clock scan {37 12 xxxi} -format {%y %N %Oe} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.745 {parse yymmdd} {
+ clock scan {xxxvii Dec 31} -format {%Oy %b %d} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.746 {parse yymmdd} {
+ clock scan {xxxvii Dec xxxi} -format {%Oy %b %Od} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.747 {parse yymmdd} {
+ clock scan {xxxvii Dec 31} -format {%Oy %b %e} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.748 {parse yymmdd} {
+ clock scan {xxxvii Dec xxxi} -format {%Oy %b %Oe} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.749 {parse yymmdd} {
+ clock scan {xxxvii December 31} -format {%Oy %B %d} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.750 {parse yymmdd} {
+ clock scan {xxxvii December xxxi} -format {%Oy %B %Od} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.751 {parse yymmdd} {
+ clock scan {xxxvii December 31} -format {%Oy %B %e} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.752 {parse yymmdd} {
+ clock scan {xxxvii December xxxi} -format {%Oy %B %Oe} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.753 {parse yymmdd} {
+ clock scan {xxxvii Dec 31} -format {%Oy %h %d} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.754 {parse yymmdd} {
+ clock scan {xxxvii Dec xxxi} -format {%Oy %h %Od} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.755 {parse yymmdd} {
+ clock scan {xxxvii Dec 31} -format {%Oy %h %e} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.756 {parse yymmdd} {
+ clock scan {xxxvii Dec xxxi} -format {%Oy %h %Oe} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.757 {parse yymmdd} {
+ clock scan {xxxvii 12 31} -format {%Oy %m %d} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.758 {parse yymmdd} {
+ clock scan {xxxvii 12 xxxi} -format {%Oy %m %Od} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.759 {parse yymmdd} {
+ clock scan {xxxvii 12 31} -format {%Oy %m %e} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.760 {parse yymmdd} {
+ clock scan {xxxvii 12 xxxi} -format {%Oy %m %Oe} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.761 {parse yymmdd} {
+ clock scan {xxxvii xii 31} -format {%Oy %Om %d} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.762 {parse yymmdd} {
+ clock scan {xxxvii xii xxxi} -format {%Oy %Om %Od} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.763 {parse yymmdd} {
+ clock scan {xxxvii xii 31} -format {%Oy %Om %e} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.764 {parse yymmdd} {
+ clock scan {xxxvii xii xxxi} -format {%Oy %Om %Oe} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.765 {parse yymmdd} {
+ clock scan {xxxvii 12 31} -format {%Oy %N %d} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.766 {parse yymmdd} {
+ clock scan {xxxvii 12 xxxi} -format {%Oy %N %Od} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.767 {parse yymmdd} {
+ clock scan {xxxvii 12 31} -format {%Oy %N %e} -locale en_US_roman -gmt 1
+} 2145830400
+test clock-14.768 {parse yymmdd} {
+ clock scan {xxxvii 12 xxxi} -format {%Oy %N %Oe} -locale en_US_roman -gmt 1
+} 2145830400
+# END testcases14
+
+test clock-15.1 {yymmdd precedence below seconds} {
+ list [clock scan {0 000101} -format {%s %y%m%d} -gmt true] \
+ [clock scan {000101 0} -format {%y%m%d %s} -gmt true]
+} {0 0}
+
+test clock-15.2 {yymmdd precedence below julian day} {
+ list [clock scan {2440588 000101} -format {%J %y%m%d} -gmt true] \
+ [clock scan {000101 2440588} -format {%y%m%d %J} -gmt true]
+} {0 0}
+
+test clock-15.3 {yymmdd precedence below yyyyWwwd} {
+ list [clock scan {1970W014000101} -format {%GW%V%u%y%m%d} -gmt true] \
+ [clock scan {0001011970W014} -format {%y%m%d%GW%V%u} -gmt true]
+} {0 0}
+
+# Test parsing of yyddd
+
+test clock-16.1 {parse yyddd} {
+ clock scan {70 001} -format {%y %j} -locale en_US_roman -gmt 1
+} 0
+test clock-16.2 {parse yyddd} {
+ clock scan {70 365} -format {%y %j} -locale en_US_roman -gmt 1
+} 31449600
+test clock-16.3 {parse yyddd} {
+ clock scan {71 001} -format {%y %j} -locale en_US_roman -gmt 1
+} 31536000
+test clock-16.4 {parse yyddd} {
+ clock scan {71 365} -format {%y %j} -locale en_US_roman -gmt 1
+} 62985600
+test clock-16.5 {parse yyddd} {
+ clock scan {00 001} -format {%y %j} -locale en_US_roman -gmt 1
+} 946684800
+test clock-16.6 {parse yyddd} {
+ clock scan {00 365} -format {%y %j} -locale en_US_roman -gmt 1
+} 978134400
+test clock-16.7 {parse yyddd} {
+ clock scan {01 001} -format {%y %j} -locale en_US_roman -gmt 1
+} 978307200
+test clock-16.8 {parse yyddd} {
+ clock scan {01 365} -format {%y %j} -locale en_US_roman -gmt 1
+} 1009756800
+
+test clock-16.9 {seconds take precedence over yyddd} {
+ list [clock scan {0 00001} -format {%s %y%j} -gmt true] \
+ [clock scan {00001 0} -format {%y%j %s} -gmt true]
+} {0 0}
+test clock-16.10 {julian day takes precedence over yyddd} {
+ list [clock scan {2440588 00001} -format {%J %y%j} -gmt true] \
+ [clock scan {00001 2440588} -format {%Y%j %J} -gmt true]
+} {0 0}
+test clock-16.11 {yyddd precedence below yyyyWwwd} {
+ list [clock scan {1970W01400001} -format {%GW%V%u%y%j} -gmt true] \
+ [clock scan {000011970W014} -format {%y%j%GW%V%u} -gmt true]
+} {0 0}
+
+# BEGIN testcases17
+
+# Test parsing of yyWwwd
+
+test clock-17.1 {parse yyWwwd} {
+ clock scan {70 W01 Fri} -format {%g W%V %a} -locale en_US_roman -gmt 1
+} 86400
+test clock-17.2 {parse yyWwwd} {
+ clock scan {70 W01 Friday} -format {%g W%V %A} -locale en_US_roman -gmt 1
+} 86400
+test clock-17.3 {parse yyWwwd} {
+ clock scan {70 W01 5} -format {%g W%V %u} -locale en_US_roman -gmt 1
+} 86400
+test clock-17.4 {parse yyWwwd} {
+ clock scan {70 W01 5} -format {%g W%V %w} -locale en_US_roman -gmt 1
+} 86400
+test clock-17.5 {parse yyWwwd} {
+ clock scan {70 W01 v} -format {%g W%V %Ou} -locale en_US_roman -gmt 1
+} 86400
+test clock-17.6 {parse yyWwwd} {
+ clock scan {70 W01 v} -format {%g W%V %Ow} -locale en_US_roman -gmt 1
+} 86400
+test clock-17.7 {parse yyWwwd} {
+ clock scan {70 W05 Sat} -format {%g W%V %a} -locale en_US_roman -gmt 1
+} 2592000
+test clock-17.8 {parse yyWwwd} {
+ clock scan {70 W05 Saturday} -format {%g W%V %A} -locale en_US_roman -gmt 1
+} 2592000
+test clock-17.9 {parse yyWwwd} {
+ clock scan {70 W05 6} -format {%g W%V %u} -locale en_US_roman -gmt 1
+} 2592000
+test clock-17.10 {parse yyWwwd} {
+ clock scan {70 W05 6} -format {%g W%V %w} -locale en_US_roman -gmt 1
+} 2592000
+test clock-17.11 {parse yyWwwd} {
+ clock scan {70 W05 vi} -format {%g W%V %Ou} -locale en_US_roman -gmt 1
+} 2592000
+test clock-17.12 {parse yyWwwd} {
+ clock scan {70 W05 vi} -format {%g W%V %Ow} -locale en_US_roman -gmt 1
+} 2592000
+test clock-17.13 {parse yyWwwd} {
+ clock scan {70 W49 Wed} -format {%g W%V %a} -locale en_US_roman -gmt 1
+} 28944000
+test clock-17.14 {parse yyWwwd} {
+ clock scan {70 W49 Wednesday} -format {%g W%V %A} -locale en_US_roman -gmt 1
+} 28944000
+test clock-17.15 {parse yyWwwd} {
+ clock scan {70 W49 3} -format {%g W%V %u} -locale en_US_roman -gmt 1
+} 28944000
+test clock-17.16 {parse yyWwwd} {
+ clock scan {70 W49 3} -format {%g W%V %w} -locale en_US_roman -gmt 1
+} 28944000
+test clock-17.17 {parse yyWwwd} {
+ clock scan {70 W49 iii} -format {%g W%V %Ou} -locale en_US_roman -gmt 1
+} 28944000
+test clock-17.18 {parse yyWwwd} {
+ clock scan {70 W49 iii} -format {%g W%V %Ow} -locale en_US_roman -gmt 1
+} 28944000
+test clock-17.19 {parse yyWwwd} {
+ clock scan {70 W53 Thu} -format {%g W%V %a} -locale en_US_roman -gmt 1
+} 31449600
+test clock-17.20 {parse yyWwwd} {
+ clock scan {70 W53 Thursday} -format {%g W%V %A} -locale en_US_roman -gmt 1
+} 31449600
+test clock-17.21 {parse yyWwwd} {
+ clock scan {70 W53 4} -format {%g W%V %u} -locale en_US_roman -gmt 1
+} 31449600
+test clock-17.22 {parse yyWwwd} {
+ clock scan {70 W53 4} -format {%g W%V %w} -locale en_US_roman -gmt 1
+} 31449600
+test clock-17.23 {parse yyWwwd} {
+ clock scan {70 W53 iv} -format {%g W%V %Ou} -locale en_US_roman -gmt 1
+} 31449600
+test clock-17.24 {parse yyWwwd} {
+ clock scan {70 W53 iv} -format {%g W%V %Ow} -locale en_US_roman -gmt 1
+} 31449600
+test clock-17.25 {parse yyWwwd} {
+ clock scan {70 W53 Sat} -format {%g W%V %a} -locale en_US_roman -gmt 1
+} 31622400
+test clock-17.26 {parse yyWwwd} {
+ clock scan {70 W53 Saturday} -format {%g W%V %A} -locale en_US_roman -gmt 1
+} 31622400
+test clock-17.27 {parse yyWwwd} {
+ clock scan {70 W53 6} -format {%g W%V %u} -locale en_US_roman -gmt 1
+} 31622400
+test clock-17.28 {parse yyWwwd} {
+ clock scan {70 W53 6} -format {%g W%V %w} -locale en_US_roman -gmt 1
+} 31622400
+test clock-17.29 {parse yyWwwd} {
+ clock scan {70 W53 vi} -format {%g W%V %Ou} -locale en_US_roman -gmt 1
+} 31622400
+test clock-17.30 {parse yyWwwd} {
+ clock scan {70 W53 vi} -format {%g W%V %Ow} -locale en_US_roman -gmt 1
+} 31622400
+test clock-17.31 {parse yyWwwd} {
+ clock scan {71 W04 Sun} -format {%g W%V %a} -locale en_US_roman -gmt 1
+} 34128000
+test clock-17.32 {parse yyWwwd} {
+ clock scan {71 W04 Sunday} -format {%g W%V %A} -locale en_US_roman -gmt 1
+} 34128000
+test clock-17.33 {parse yyWwwd} {
+ clock scan {71 W04 7} -format {%g W%V %u} -locale en_US_roman -gmt 1
+} 34128000
+test clock-17.34 {parse yyWwwd} {
+ clock scan {71 W04 0} -format {%g W%V %w} -locale en_US_roman -gmt 1
+} 34128000
+test clock-17.35 {parse yyWwwd} {
+ clock scan {71 W04 vii} -format {%g W%V %Ou} -locale en_US_roman -gmt 1
+} 34128000
+test clock-17.36 {parse yyWwwd} {
+ clock scan {71 W04 ?} -format {%g W%V %Ow} -locale en_US_roman -gmt 1
+} 34128000
+test clock-17.37 {parse yyWwwd} {
+ clock scan {71 W48 Thu} -format {%g W%V %a} -locale en_US_roman -gmt 1
+} 60480000
+test clock-17.38 {parse yyWwwd} {
+ clock scan {71 W48 Thursday} -format {%g W%V %A} -locale en_US_roman -gmt 1
+} 60480000
+test clock-17.39 {parse yyWwwd} {
+ clock scan {71 W48 4} -format {%g W%V %u} -locale en_US_roman -gmt 1
+} 60480000
+test clock-17.40 {parse yyWwwd} {
+ clock scan {71 W48 4} -format {%g W%V %w} -locale en_US_roman -gmt 1
+} 60480000
+test clock-17.41 {parse yyWwwd} {
+ clock scan {71 W48 iv} -format {%g W%V %Ou} -locale en_US_roman -gmt 1
+} 60480000
+test clock-17.42 {parse yyWwwd} {
+ clock scan {71 W48 iv} -format {%g W%V %Ow} -locale en_US_roman -gmt 1
+} 60480000
+test clock-17.43 {parse yyWwwd} {
+ clock scan {71 W52 Fri} -format {%g W%V %a} -locale en_US_roman -gmt 1
+} 62985600
+test clock-17.44 {parse yyWwwd} {
+ clock scan {71 W52 Friday} -format {%g W%V %A} -locale en_US_roman -gmt 1
+} 62985600
+test clock-17.45 {parse yyWwwd} {
+ clock scan {71 W52 5} -format {%g W%V %u} -locale en_US_roman -gmt 1
+} 62985600
+test clock-17.46 {parse yyWwwd} {
+ clock scan {71 W52 5} -format {%g W%V %w} -locale en_US_roman -gmt 1
+} 62985600
+test clock-17.47 {parse yyWwwd} {
+ clock scan {71 W52 v} -format {%g W%V %Ou} -locale en_US_roman -gmt 1
+} 62985600
+test clock-17.48 {parse yyWwwd} {
+ clock scan {71 W52 v} -format {%g W%V %Ow} -locale en_US_roman -gmt 1
+} 62985600
+test clock-17.49 {parse yyWwwd} {
+ clock scan {99 W52 Sun} -format {%g W%V %a} -locale en_US_roman -gmt 1
+} 946771200
+test clock-17.50 {parse yyWwwd} {
+ clock scan {99 W52 Sunday} -format {%g W%V %A} -locale en_US_roman -gmt 1
+} 946771200
+test clock-17.51 {parse yyWwwd} {
+ clock scan {99 W52 7} -format {%g W%V %u} -locale en_US_roman -gmt 1
+} 946771200
+test clock-17.52 {parse yyWwwd} {
+ clock scan {99 W52 0} -format {%g W%V %w} -locale en_US_roman -gmt 1
+} 946771200
+test clock-17.53 {parse yyWwwd} {
+ clock scan {99 W52 vii} -format {%g W%V %Ou} -locale en_US_roman -gmt 1
+} 946771200
+test clock-17.54 {parse yyWwwd} {
+ clock scan {99 W52 ?} -format {%g W%V %Ow} -locale en_US_roman -gmt 1
+} 946771200
+test clock-17.55 {parse yyWwwd} {
+ clock scan {00 W05 Mon} -format {%g W%V %a} -locale en_US_roman -gmt 1
+} 949276800
+test clock-17.56 {parse yyWwwd} {
+ clock scan {00 W05 Monday} -format {%g W%V %A} -locale en_US_roman -gmt 1
+} 949276800
+test clock-17.57 {parse yyWwwd} {
+ clock scan {00 W05 1} -format {%g W%V %u} -locale en_US_roman -gmt 1
+} 949276800
+test clock-17.58 {parse yyWwwd} {
+ clock scan {00 W05 1} -format {%g W%V %w} -locale en_US_roman -gmt 1
+} 949276800
+test clock-17.59 {parse yyWwwd} {
+ clock scan {00 W05 i} -format {%g W%V %Ou} -locale en_US_roman -gmt 1
+} 949276800
+test clock-17.60 {parse yyWwwd} {
+ clock scan {00 W05 i} -format {%g W%V %Ow} -locale en_US_roman -gmt 1
+} 949276800
+test clock-17.61 {parse yyWwwd} {
+ clock scan {00 W48 Sat} -format {%g W%V %a} -locale en_US_roman -gmt 1
+} 975715200
+test clock-17.62 {parse yyWwwd} {
+ clock scan {00 W48 Saturday} -format {%g W%V %A} -locale en_US_roman -gmt 1
+} 975715200
+test clock-17.63 {parse yyWwwd} {
+ clock scan {00 W48 6} -format {%g W%V %u} -locale en_US_roman -gmt 1
+} 975715200
+test clock-17.64 {parse yyWwwd} {
+ clock scan {00 W48 6} -format {%g W%V %w} -locale en_US_roman -gmt 1
+} 975715200
+test clock-17.65 {parse yyWwwd} {
+ clock scan {00 W48 vi} -format {%g W%V %Ou} -locale en_US_roman -gmt 1
+} 975715200
+test clock-17.66 {parse yyWwwd} {
+ clock scan {00 W48 vi} -format {%g W%V %Ow} -locale en_US_roman -gmt 1
+} 975715200
+test clock-17.67 {parse yyWwwd} {
+ clock scan {00 W52 Sun} -format {%g W%V %a} -locale en_US_roman -gmt 1
+} 978220800
+test clock-17.68 {parse yyWwwd} {
+ clock scan {00 W52 Sunday} -format {%g W%V %A} -locale en_US_roman -gmt 1
+} 978220800
+test clock-17.69 {parse yyWwwd} {
+ clock scan {00 W52 7} -format {%g W%V %u} -locale en_US_roman -gmt 1
+} 978220800
+test clock-17.70 {parse yyWwwd} {
+ clock scan {00 W52 0} -format {%g W%V %w} -locale en_US_roman -gmt 1
+} 978220800
+test clock-17.71 {parse yyWwwd} {
+ clock scan {00 W52 vii} -format {%g W%V %Ou} -locale en_US_roman -gmt 1
+} 978220800
+test clock-17.72 {parse yyWwwd} {
+ clock scan {00 W52 ?} -format {%g W%V %Ow} -locale en_US_roman -gmt 1
+} 978220800
+test clock-17.73 {parse yyWwwd} {
+ clock scan {01 W01 Tue} -format {%g W%V %a} -locale en_US_roman -gmt 1
+} 978393600
+test clock-17.74 {parse yyWwwd} {
+ clock scan {01 W01 Tuesday} -format {%g W%V %A} -locale en_US_roman -gmt 1
+} 978393600
+test clock-17.75 {parse yyWwwd} {
+ clock scan {01 W01 2} -format {%g W%V %u} -locale en_US_roman -gmt 1
+} 978393600
+test clock-17.76 {parse yyWwwd} {
+ clock scan {01 W01 2} -format {%g W%V %w} -locale en_US_roman -gmt 1
+} 978393600
+test clock-17.77 {parse yyWwwd} {
+ clock scan {01 W01 ii} -format {%g W%V %Ou} -locale en_US_roman -gmt 1
+} 978393600
+test clock-17.78 {parse yyWwwd} {
+ clock scan {01 W01 ii} -format {%g W%V %Ow} -locale en_US_roman -gmt 1
+} 978393600
+test clock-17.79 {parse yyWwwd} {
+ clock scan {01 W05 Wed} -format {%g W%V %a} -locale en_US_roman -gmt 1
+} 980899200
+test clock-17.80 {parse yyWwwd} {
+ clock scan {01 W05 Wednesday} -format {%g W%V %A} -locale en_US_roman -gmt 1
+} 980899200
+test clock-17.81 {parse yyWwwd} {
+ clock scan {01 W05 3} -format {%g W%V %u} -locale en_US_roman -gmt 1
+} 980899200
+test clock-17.82 {parse yyWwwd} {
+ clock scan {01 W05 3} -format {%g W%V %w} -locale en_US_roman -gmt 1
+} 980899200
+test clock-17.83 {parse yyWwwd} {
+ clock scan {01 W05 iii} -format {%g W%V %Ou} -locale en_US_roman -gmt 1
+} 980899200
+test clock-17.84 {parse yyWwwd} {
+ clock scan {01 W05 iii} -format {%g W%V %Ow} -locale en_US_roman -gmt 1
+} 980899200
+test clock-17.85 {parse yyWwwd} {
+ clock scan {01 W48 Sun} -format {%g W%V %a} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-17.86 {parse yyWwwd} {
+ clock scan {01 W48 Sunday} -format {%g W%V %A} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-17.87 {parse yyWwwd} {
+ clock scan {01 W48 7} -format {%g W%V %u} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-17.88 {parse yyWwwd} {
+ clock scan {01 W48 0} -format {%g W%V %w} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-17.89 {parse yyWwwd} {
+ clock scan {01 W48 vii} -format {%g W%V %Ou} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-17.90 {parse yyWwwd} {
+ clock scan {01 W48 ?} -format {%g W%V %Ow} -locale en_US_roman -gmt 1
+} 1007251200
+test clock-17.91 {parse yyWwwd} {
+ clock scan {02 W01 Mon} -format {%g W%V %a} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-17.92 {parse yyWwwd} {
+ clock scan {02 W01 Monday} -format {%g W%V %A} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-17.93 {parse yyWwwd} {
+ clock scan {02 W01 1} -format {%g W%V %u} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-17.94 {parse yyWwwd} {
+ clock scan {02 W01 1} -format {%g W%V %w} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-17.95 {parse yyWwwd} {
+ clock scan {02 W01 i} -format {%g W%V %Ou} -locale en_US_roman -gmt 1
+} 1009756800
+test clock-17.96 {parse yyWwwd} {
+ clock scan {02 W01 i} -format {%g W%V %Ow} -locale en_US_roman -gmt 1
+} 1009756800
+# END testcases17
+
+# Test precedence of yyWwwd
+
+test clock-18.1 {seconds take precedence over yyWwwd} {
+ list [clock scan {0 00W014} -format {%s %gW%V%u} -gmt true] \
+ [clock scan {00W014 0} -format {%gW%V%u %s} -gmt true]
+} {0 0}
+test clock-18.2 {julian day takes precedence over yyddd} {
+ list [clock scan {2440588 00W014} -format {%J %gW%V%u} -gmt true] \
+ [clock scan {00W014 2440588} -format {%gW%V%u %J} -gmt true]
+} {0 0}
+test clock-18.3 {yyWwwd precedence below yyyymmdd} {
+ list [clock scan {19700101 00W014} -format {%Y%m%d %gW%V%u} -gmt true] \
+ [clock scan {00W014 19700101} -format {%gW%V%u %Y%m%d} -gmt true]
+} {0 0}
+test clock-18.4 {yyWwwd precedence below yyyyddd} {
+ list [clock scan {1970001 00W014} -format {%Y%j %gW%V%u} -gmt true] \
+ [clock scan {00W014 1970001} -format {%gW%V%u %Y%j} -gmt true]
+} {0 0}
+
+# BEGIN testcases19
+
+# Test parsing of mmdd
+
+test clock-19.1 {parse mmdd} {
+ clock scan {Jan 02} -format {%b %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.2 {parse mmdd} {
+ clock scan {Jan ii} -format {%b %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.3 {parse mmdd} {
+ clock scan {Jan 2} -format {%b %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.4 {parse mmdd} {
+ clock scan {Jan ii} -format {%b %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.5 {parse mmdd} {
+ clock scan {January 02} -format {%B %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.6 {parse mmdd} {
+ clock scan {January ii} -format {%B %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.7 {parse mmdd} {
+ clock scan {January 2} -format {%B %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.8 {parse mmdd} {
+ clock scan {January ii} -format {%B %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.9 {parse mmdd} {
+ clock scan {Jan 02} -format {%h %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.10 {parse mmdd} {
+ clock scan {Jan ii} -format {%h %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.11 {parse mmdd} {
+ clock scan {Jan 2} -format {%h %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.12 {parse mmdd} {
+ clock scan {Jan ii} -format {%h %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.13 {parse mmdd} {
+ clock scan {01 02} -format {%m %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.14 {parse mmdd} {
+ clock scan {01 ii} -format {%m %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.15 {parse mmdd} {
+ clock scan {01 2} -format {%m %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.16 {parse mmdd} {
+ clock scan {01 ii} -format {%m %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.17 {parse mmdd} {
+ clock scan {i 02} -format {%Om %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.18 {parse mmdd} {
+ clock scan {i ii} -format {%Om %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.19 {parse mmdd} {
+ clock scan {i 2} -format {%Om %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.20 {parse mmdd} {
+ clock scan {i ii} -format {%Om %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.21 {parse mmdd} {
+ clock scan { 1 02} -format {%N %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.22 {parse mmdd} {
+ clock scan { 1 ii} -format {%N %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.23 {parse mmdd} {
+ clock scan { 1 2} -format {%N %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.24 {parse mmdd} {
+ clock scan { 1 ii} -format {%N %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -1009756800
+test clock-19.25 {parse mmdd} {
+ clock scan {Jan 31} -format {%b %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.26 {parse mmdd} {
+ clock scan {Jan xxxi} -format {%b %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.27 {parse mmdd} {
+ clock scan {Jan 31} -format {%b %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.28 {parse mmdd} {
+ clock scan {Jan xxxi} -format {%b %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.29 {parse mmdd} {
+ clock scan {January 31} -format {%B %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.30 {parse mmdd} {
+ clock scan {January xxxi} -format {%B %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.31 {parse mmdd} {
+ clock scan {January 31} -format {%B %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.32 {parse mmdd} {
+ clock scan {January xxxi} -format {%B %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.33 {parse mmdd} {
+ clock scan {Jan 31} -format {%h %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.34 {parse mmdd} {
+ clock scan {Jan xxxi} -format {%h %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.35 {parse mmdd} {
+ clock scan {Jan 31} -format {%h %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.36 {parse mmdd} {
+ clock scan {Jan xxxi} -format {%h %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.37 {parse mmdd} {
+ clock scan {01 31} -format {%m %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.38 {parse mmdd} {
+ clock scan {01 xxxi} -format {%m %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.39 {parse mmdd} {
+ clock scan {01 31} -format {%m %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.40 {parse mmdd} {
+ clock scan {01 xxxi} -format {%m %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.41 {parse mmdd} {
+ clock scan {i 31} -format {%Om %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.42 {parse mmdd} {
+ clock scan {i xxxi} -format {%Om %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.43 {parse mmdd} {
+ clock scan {i 31} -format {%Om %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.44 {parse mmdd} {
+ clock scan {i xxxi} -format {%Om %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.45 {parse mmdd} {
+ clock scan { 1 31} -format {%N %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.46 {parse mmdd} {
+ clock scan { 1 xxxi} -format {%N %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.47 {parse mmdd} {
+ clock scan { 1 31} -format {%N %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.48 {parse mmdd} {
+ clock scan { 1 xxxi} -format {%N %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -1007251200
+test clock-19.49 {parse mmdd} {
+ clock scan {Dec 02} -format {%b %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.50 {parse mmdd} {
+ clock scan {Dec ii} -format {%b %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.51 {parse mmdd} {
+ clock scan {Dec 2} -format {%b %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.52 {parse mmdd} {
+ clock scan {Dec ii} -format {%b %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.53 {parse mmdd} {
+ clock scan {December 02} -format {%B %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.54 {parse mmdd} {
+ clock scan {December ii} -format {%B %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.55 {parse mmdd} {
+ clock scan {December 2} -format {%B %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.56 {parse mmdd} {
+ clock scan {December ii} -format {%B %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.57 {parse mmdd} {
+ clock scan {Dec 02} -format {%h %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.58 {parse mmdd} {
+ clock scan {Dec ii} -format {%h %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.59 {parse mmdd} {
+ clock scan {Dec 2} -format {%h %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.60 {parse mmdd} {
+ clock scan {Dec ii} -format {%h %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.61 {parse mmdd} {
+ clock scan {12 02} -format {%m %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.62 {parse mmdd} {
+ clock scan {12 ii} -format {%m %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.63 {parse mmdd} {
+ clock scan {12 2} -format {%m %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.64 {parse mmdd} {
+ clock scan {12 ii} -format {%m %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.65 {parse mmdd} {
+ clock scan {xii 02} -format {%Om %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.66 {parse mmdd} {
+ clock scan {xii ii} -format {%Om %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.67 {parse mmdd} {
+ clock scan {xii 2} -format {%Om %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.68 {parse mmdd} {
+ clock scan {xii ii} -format {%Om %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.69 {parse mmdd} {
+ clock scan {12 02} -format {%N %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.70 {parse mmdd} {
+ clock scan {12 ii} -format {%N %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.71 {parse mmdd} {
+ clock scan {12 2} -format {%N %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.72 {parse mmdd} {
+ clock scan {12 ii} -format {%N %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -980899200
+test clock-19.73 {parse mmdd} {
+ clock scan {Dec 31} -format {%b %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.74 {parse mmdd} {
+ clock scan {Dec xxxi} -format {%b %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.75 {parse mmdd} {
+ clock scan {Dec 31} -format {%b %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.76 {parse mmdd} {
+ clock scan {Dec xxxi} -format {%b %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.77 {parse mmdd} {
+ clock scan {December 31} -format {%B %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.78 {parse mmdd} {
+ clock scan {December xxxi} -format {%B %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.79 {parse mmdd} {
+ clock scan {December 31} -format {%B %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.80 {parse mmdd} {
+ clock scan {December xxxi} -format {%B %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.81 {parse mmdd} {
+ clock scan {Dec 31} -format {%h %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.82 {parse mmdd} {
+ clock scan {Dec xxxi} -format {%h %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.83 {parse mmdd} {
+ clock scan {Dec 31} -format {%h %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.84 {parse mmdd} {
+ clock scan {Dec xxxi} -format {%h %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.85 {parse mmdd} {
+ clock scan {12 31} -format {%m %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.86 {parse mmdd} {
+ clock scan {12 xxxi} -format {%m %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.87 {parse mmdd} {
+ clock scan {12 31} -format {%m %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.88 {parse mmdd} {
+ clock scan {12 xxxi} -format {%m %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.89 {parse mmdd} {
+ clock scan {xii 31} -format {%Om %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.90 {parse mmdd} {
+ clock scan {xii xxxi} -format {%Om %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.91 {parse mmdd} {
+ clock scan {xii 31} -format {%Om %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.92 {parse mmdd} {
+ clock scan {xii xxxi} -format {%Om %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.93 {parse mmdd} {
+ clock scan {12 31} -format {%N %d} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.94 {parse mmdd} {
+ clock scan {12 xxxi} -format {%N %Od} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.95 {parse mmdd} {
+ clock scan {12 31} -format {%N %e} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.96 {parse mmdd} {
+ clock scan {12 xxxi} -format {%N %Oe} -locale en_US_roman -base -1009843200 -gmt 1
+} -978393600
+test clock-19.97 {parse mmdd} {
+ clock scan {Jan 02} -format {%b %d} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.98 {parse mmdd} {
+ clock scan {Jan ii} -format {%b %Od} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.99 {parse mmdd} {
+ clock scan {Jan 2} -format {%b %e} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.100 {parse mmdd} {
+ clock scan {Jan ii} -format {%b %Oe} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.101 {parse mmdd} {
+ clock scan {January 02} -format {%B %d} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.102 {parse mmdd} {
+ clock scan {January ii} -format {%B %Od} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.103 {parse mmdd} {
+ clock scan {January 2} -format {%B %e} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.104 {parse mmdd} {
+ clock scan {January ii} -format {%B %Oe} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.105 {parse mmdd} {
+ clock scan {Jan 02} -format {%h %d} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.106 {parse mmdd} {
+ clock scan {Jan ii} -format {%h %Od} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.107 {parse mmdd} {
+ clock scan {Jan 2} -format {%h %e} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.108 {parse mmdd} {
+ clock scan {Jan ii} -format {%h %Oe} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.109 {parse mmdd} {
+ clock scan {01 02} -format {%m %d} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.110 {parse mmdd} {
+ clock scan {01 ii} -format {%m %Od} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.111 {parse mmdd} {
+ clock scan {01 2} -format {%m %e} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.112 {parse mmdd} {
+ clock scan {01 ii} -format {%m %Oe} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.113 {parse mmdd} {
+ clock scan {i 02} -format {%Om %d} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.114 {parse mmdd} {
+ clock scan {i ii} -format {%Om %Od} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.115 {parse mmdd} {
+ clock scan {i 2} -format {%Om %e} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.116 {parse mmdd} {
+ clock scan {i ii} -format {%Om %Oe} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.117 {parse mmdd} {
+ clock scan { 1 02} -format {%N %d} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.118 {parse mmdd} {
+ clock scan { 1 ii} -format {%N %Od} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.119 {parse mmdd} {
+ clock scan { 1 2} -format {%N %e} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.120 {parse mmdd} {
+ clock scan { 1 ii} -format {%N %Oe} -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-19.121 {parse mmdd} {
+ clock scan {Jan 31} -format {%b %d} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.122 {parse mmdd} {
+ clock scan {Jan xxxi} -format {%b %Od} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.123 {parse mmdd} {
+ clock scan {Jan 31} -format {%b %e} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.124 {parse mmdd} {
+ clock scan {Jan xxxi} -format {%b %Oe} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.125 {parse mmdd} {
+ clock scan {January 31} -format {%B %d} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.126 {parse mmdd} {
+ clock scan {January xxxi} -format {%B %Od} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.127 {parse mmdd} {
+ clock scan {January 31} -format {%B %e} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.128 {parse mmdd} {
+ clock scan {January xxxi} -format {%B %Oe} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.129 {parse mmdd} {
+ clock scan {Jan 31} -format {%h %d} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.130 {parse mmdd} {
+ clock scan {Jan xxxi} -format {%h %Od} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.131 {parse mmdd} {
+ clock scan {Jan 31} -format {%h %e} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.132 {parse mmdd} {
+ clock scan {Jan xxxi} -format {%h %Oe} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.133 {parse mmdd} {
+ clock scan {01 31} -format {%m %d} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.134 {parse mmdd} {
+ clock scan {01 xxxi} -format {%m %Od} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.135 {parse mmdd} {
+ clock scan {01 31} -format {%m %e} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.136 {parse mmdd} {
+ clock scan {01 xxxi} -format {%m %Oe} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.137 {parse mmdd} {
+ clock scan {i 31} -format {%Om %d} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.138 {parse mmdd} {
+ clock scan {i xxxi} -format {%Om %Od} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.139 {parse mmdd} {
+ clock scan {i 31} -format {%Om %e} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.140 {parse mmdd} {
+ clock scan {i xxxi} -format {%Om %Oe} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.141 {parse mmdd} {
+ clock scan { 1 31} -format {%N %d} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.142 {parse mmdd} {
+ clock scan { 1 xxxi} -format {%N %Od} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.143 {parse mmdd} {
+ clock scan { 1 31} -format {%N %e} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.144 {parse mmdd} {
+ clock scan { 1 xxxi} -format {%N %Oe} -locale en_US_roman -base 0 -gmt 1
+} 2592000
+test clock-19.145 {parse mmdd} {
+ clock scan {Dec 02} -format {%b %d} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.146 {parse mmdd} {
+ clock scan {Dec ii} -format {%b %Od} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.147 {parse mmdd} {
+ clock scan {Dec 2} -format {%b %e} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.148 {parse mmdd} {
+ clock scan {Dec ii} -format {%b %Oe} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.149 {parse mmdd} {
+ clock scan {December 02} -format {%B %d} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.150 {parse mmdd} {
+ clock scan {December ii} -format {%B %Od} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.151 {parse mmdd} {
+ clock scan {December 2} -format {%B %e} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.152 {parse mmdd} {
+ clock scan {December ii} -format {%B %Oe} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.153 {parse mmdd} {
+ clock scan {Dec 02} -format {%h %d} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.154 {parse mmdd} {
+ clock scan {Dec ii} -format {%h %Od} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.155 {parse mmdd} {
+ clock scan {Dec 2} -format {%h %e} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.156 {parse mmdd} {
+ clock scan {Dec ii} -format {%h %Oe} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.157 {parse mmdd} {
+ clock scan {12 02} -format {%m %d} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.158 {parse mmdd} {
+ clock scan {12 ii} -format {%m %Od} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.159 {parse mmdd} {
+ clock scan {12 2} -format {%m %e} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.160 {parse mmdd} {
+ clock scan {12 ii} -format {%m %Oe} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.161 {parse mmdd} {
+ clock scan {xii 02} -format {%Om %d} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.162 {parse mmdd} {
+ clock scan {xii ii} -format {%Om %Od} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.163 {parse mmdd} {
+ clock scan {xii 2} -format {%Om %e} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.164 {parse mmdd} {
+ clock scan {xii ii} -format {%Om %Oe} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.165 {parse mmdd} {
+ clock scan {12 02} -format {%N %d} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.166 {parse mmdd} {
+ clock scan {12 ii} -format {%N %Od} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.167 {parse mmdd} {
+ clock scan {12 2} -format {%N %e} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.168 {parse mmdd} {
+ clock scan {12 ii} -format {%N %Oe} -locale en_US_roman -base 0 -gmt 1
+} 28944000
+test clock-19.169 {parse mmdd} {
+ clock scan {Dec 31} -format {%b %d} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.170 {parse mmdd} {
+ clock scan {Dec xxxi} -format {%b %Od} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.171 {parse mmdd} {
+ clock scan {Dec 31} -format {%b %e} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.172 {parse mmdd} {
+ clock scan {Dec xxxi} -format {%b %Oe} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.173 {parse mmdd} {
+ clock scan {December 31} -format {%B %d} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.174 {parse mmdd} {
+ clock scan {December xxxi} -format {%B %Od} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.175 {parse mmdd} {
+ clock scan {December 31} -format {%B %e} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.176 {parse mmdd} {
+ clock scan {December xxxi} -format {%B %Oe} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.177 {parse mmdd} {
+ clock scan {Dec 31} -format {%h %d} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.178 {parse mmdd} {
+ clock scan {Dec xxxi} -format {%h %Od} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.179 {parse mmdd} {
+ clock scan {Dec 31} -format {%h %e} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.180 {parse mmdd} {
+ clock scan {Dec xxxi} -format {%h %Oe} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.181 {parse mmdd} {
+ clock scan {12 31} -format {%m %d} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.182 {parse mmdd} {
+ clock scan {12 xxxi} -format {%m %Od} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.183 {parse mmdd} {
+ clock scan {12 31} -format {%m %e} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.184 {parse mmdd} {
+ clock scan {12 xxxi} -format {%m %Oe} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.185 {parse mmdd} {
+ clock scan {xii 31} -format {%Om %d} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.186 {parse mmdd} {
+ clock scan {xii xxxi} -format {%Om %Od} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.187 {parse mmdd} {
+ clock scan {xii 31} -format {%Om %e} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.188 {parse mmdd} {
+ clock scan {xii xxxi} -format {%Om %Oe} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.189 {parse mmdd} {
+ clock scan {12 31} -format {%N %d} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.190 {parse mmdd} {
+ clock scan {12 xxxi} -format {%N %Od} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.191 {parse mmdd} {
+ clock scan {12 31} -format {%N %e} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.192 {parse mmdd} {
+ clock scan {12 xxxi} -format {%N %Oe} -locale en_US_roman -base 0 -gmt 1
+} 31449600
+test clock-19.193 {parse mmdd} {
+ clock scan {Jan 02} -format {%b %d} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.194 {parse mmdd} {
+ clock scan {Jan ii} -format {%b %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.195 {parse mmdd} {
+ clock scan {Jan 2} -format {%b %e} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.196 {parse mmdd} {
+ clock scan {Jan ii} -format {%b %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.197 {parse mmdd} {
+ clock scan {January 02} -format {%B %d} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.198 {parse mmdd} {
+ clock scan {January ii} -format {%B %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.199 {parse mmdd} {
+ clock scan {January 2} -format {%B %e} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.200 {parse mmdd} {
+ clock scan {January ii} -format {%B %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.201 {parse mmdd} {
+ clock scan {Jan 02} -format {%h %d} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.202 {parse mmdd} {
+ clock scan {Jan ii} -format {%h %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.203 {parse mmdd} {
+ clock scan {Jan 2} -format {%h %e} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.204 {parse mmdd} {
+ clock scan {Jan ii} -format {%h %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.205 {parse mmdd} {
+ clock scan {01 02} -format {%m %d} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.206 {parse mmdd} {
+ clock scan {01 ii} -format {%m %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.207 {parse mmdd} {
+ clock scan {01 2} -format {%m %e} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.208 {parse mmdd} {
+ clock scan {01 ii} -format {%m %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.209 {parse mmdd} {
+ clock scan {i 02} -format {%Om %d} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.210 {parse mmdd} {
+ clock scan {i ii} -format {%Om %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.211 {parse mmdd} {
+ clock scan {i 2} -format {%Om %e} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.212 {parse mmdd} {
+ clock scan {i ii} -format {%Om %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.213 {parse mmdd} {
+ clock scan { 1 02} -format {%N %d} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.214 {parse mmdd} {
+ clock scan { 1 ii} -format {%N %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.215 {parse mmdd} {
+ clock scan { 1 2} -format {%N %e} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.216 {parse mmdd} {
+ clock scan { 1 ii} -format {%N %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-19.217 {parse mmdd} {
+ clock scan {Jan 31} -format {%b %d} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.218 {parse mmdd} {
+ clock scan {Jan xxxi} -format {%b %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.219 {parse mmdd} {
+ clock scan {Jan 31} -format {%b %e} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.220 {parse mmdd} {
+ clock scan {Jan xxxi} -format {%b %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.221 {parse mmdd} {
+ clock scan {January 31} -format {%B %d} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.222 {parse mmdd} {
+ clock scan {January xxxi} -format {%B %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.223 {parse mmdd} {
+ clock scan {January 31} -format {%B %e} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.224 {parse mmdd} {
+ clock scan {January xxxi} -format {%B %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.225 {parse mmdd} {
+ clock scan {Jan 31} -format {%h %d} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.226 {parse mmdd} {
+ clock scan {Jan xxxi} -format {%h %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.227 {parse mmdd} {
+ clock scan {Jan 31} -format {%h %e} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.228 {parse mmdd} {
+ clock scan {Jan xxxi} -format {%h %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.229 {parse mmdd} {
+ clock scan {01 31} -format {%m %d} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.230 {parse mmdd} {
+ clock scan {01 xxxi} -format {%m %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.231 {parse mmdd} {
+ clock scan {01 31} -format {%m %e} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.232 {parse mmdd} {
+ clock scan {01 xxxi} -format {%m %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.233 {parse mmdd} {
+ clock scan {i 31} -format {%Om %d} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.234 {parse mmdd} {
+ clock scan {i xxxi} -format {%Om %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.235 {parse mmdd} {
+ clock scan {i 31} -format {%Om %e} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.236 {parse mmdd} {
+ clock scan {i xxxi} -format {%Om %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.237 {parse mmdd} {
+ clock scan { 1 31} -format {%N %d} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.238 {parse mmdd} {
+ clock scan { 1 xxxi} -format {%N %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.239 {parse mmdd} {
+ clock scan { 1 31} -format {%N %e} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.240 {parse mmdd} {
+ clock scan { 1 xxxi} -format {%N %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 949276800
+test clock-19.241 {parse mmdd} {
+ clock scan {Dec 02} -format {%b %d} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.242 {parse mmdd} {
+ clock scan {Dec ii} -format {%b %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.243 {parse mmdd} {
+ clock scan {Dec 2} -format {%b %e} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.244 {parse mmdd} {
+ clock scan {Dec ii} -format {%b %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.245 {parse mmdd} {
+ clock scan {December 02} -format {%B %d} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.246 {parse mmdd} {
+ clock scan {December ii} -format {%B %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.247 {parse mmdd} {
+ clock scan {December 2} -format {%B %e} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.248 {parse mmdd} {
+ clock scan {December ii} -format {%B %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.249 {parse mmdd} {
+ clock scan {Dec 02} -format {%h %d} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.250 {parse mmdd} {
+ clock scan {Dec ii} -format {%h %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.251 {parse mmdd} {
+ clock scan {Dec 2} -format {%h %e} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.252 {parse mmdd} {
+ clock scan {Dec ii} -format {%h %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.253 {parse mmdd} {
+ clock scan {12 02} -format {%m %d} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.254 {parse mmdd} {
+ clock scan {12 ii} -format {%m %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.255 {parse mmdd} {
+ clock scan {12 2} -format {%m %e} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.256 {parse mmdd} {
+ clock scan {12 ii} -format {%m %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.257 {parse mmdd} {
+ clock scan {xii 02} -format {%Om %d} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.258 {parse mmdd} {
+ clock scan {xii ii} -format {%Om %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.259 {parse mmdd} {
+ clock scan {xii 2} -format {%Om %e} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.260 {parse mmdd} {
+ clock scan {xii ii} -format {%Om %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.261 {parse mmdd} {
+ clock scan {12 02} -format {%N %d} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.262 {parse mmdd} {
+ clock scan {12 ii} -format {%N %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.263 {parse mmdd} {
+ clock scan {12 2} -format {%N %e} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.264 {parse mmdd} {
+ clock scan {12 ii} -format {%N %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 975715200
+test clock-19.265 {parse mmdd} {
+ clock scan {Dec 31} -format {%b %d} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.266 {parse mmdd} {
+ clock scan {Dec xxxi} -format {%b %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.267 {parse mmdd} {
+ clock scan {Dec 31} -format {%b %e} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.268 {parse mmdd} {
+ clock scan {Dec xxxi} -format {%b %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.269 {parse mmdd} {
+ clock scan {December 31} -format {%B %d} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.270 {parse mmdd} {
+ clock scan {December xxxi} -format {%B %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.271 {parse mmdd} {
+ clock scan {December 31} -format {%B %e} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.272 {parse mmdd} {
+ clock scan {December xxxi} -format {%B %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.273 {parse mmdd} {
+ clock scan {Dec 31} -format {%h %d} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.274 {parse mmdd} {
+ clock scan {Dec xxxi} -format {%h %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.275 {parse mmdd} {
+ clock scan {Dec 31} -format {%h %e} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.276 {parse mmdd} {
+ clock scan {Dec xxxi} -format {%h %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.277 {parse mmdd} {
+ clock scan {12 31} -format {%m %d} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.278 {parse mmdd} {
+ clock scan {12 xxxi} -format {%m %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.279 {parse mmdd} {
+ clock scan {12 31} -format {%m %e} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.280 {parse mmdd} {
+ clock scan {12 xxxi} -format {%m %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.281 {parse mmdd} {
+ clock scan {xii 31} -format {%Om %d} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.282 {parse mmdd} {
+ clock scan {xii xxxi} -format {%Om %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.283 {parse mmdd} {
+ clock scan {xii 31} -format {%Om %e} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.284 {parse mmdd} {
+ clock scan {xii xxxi} -format {%Om %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.285 {parse mmdd} {
+ clock scan {12 31} -format {%N %d} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.286 {parse mmdd} {
+ clock scan {12 xxxi} -format {%N %Od} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.287 {parse mmdd} {
+ clock scan {12 31} -format {%N %e} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.288 {parse mmdd} {
+ clock scan {12 xxxi} -format {%N %Oe} -locale en_US_roman -base 946684800 -gmt 1
+} 978220800
+test clock-19.289 {parse mmdd} {
+ clock scan {Jan 02} -format {%b %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.290 {parse mmdd} {
+ clock scan {Jan ii} -format {%b %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.291 {parse mmdd} {
+ clock scan {Jan 2} -format {%b %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.292 {parse mmdd} {
+ clock scan {Jan ii} -format {%b %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.293 {parse mmdd} {
+ clock scan {January 02} -format {%B %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.294 {parse mmdd} {
+ clock scan {January ii} -format {%B %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.295 {parse mmdd} {
+ clock scan {January 2} -format {%B %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.296 {parse mmdd} {
+ clock scan {January ii} -format {%B %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.297 {parse mmdd} {
+ clock scan {Jan 02} -format {%h %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.298 {parse mmdd} {
+ clock scan {Jan ii} -format {%h %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.299 {parse mmdd} {
+ clock scan {Jan 2} -format {%h %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.300 {parse mmdd} {
+ clock scan {Jan ii} -format {%h %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.301 {parse mmdd} {
+ clock scan {01 02} -format {%m %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.302 {parse mmdd} {
+ clock scan {01 ii} -format {%m %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.303 {parse mmdd} {
+ clock scan {01 2} -format {%m %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.304 {parse mmdd} {
+ clock scan {01 ii} -format {%m %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.305 {parse mmdd} {
+ clock scan {i 02} -format {%Om %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.306 {parse mmdd} {
+ clock scan {i ii} -format {%Om %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.307 {parse mmdd} {
+ clock scan {i 2} -format {%Om %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.308 {parse mmdd} {
+ clock scan {i ii} -format {%Om %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.309 {parse mmdd} {
+ clock scan { 1 02} -format {%N %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.310 {parse mmdd} {
+ clock scan { 1 ii} -format {%N %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.311 {parse mmdd} {
+ clock scan { 1 2} -format {%N %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.312 {parse mmdd} {
+ clock scan { 1 ii} -format {%N %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2114467200
+test clock-19.313 {parse mmdd} {
+ clock scan {Jan 31} -format {%b %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.314 {parse mmdd} {
+ clock scan {Jan xxxi} -format {%b %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.315 {parse mmdd} {
+ clock scan {Jan 31} -format {%b %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.316 {parse mmdd} {
+ clock scan {Jan xxxi} -format {%b %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.317 {parse mmdd} {
+ clock scan {January 31} -format {%B %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.318 {parse mmdd} {
+ clock scan {January xxxi} -format {%B %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.319 {parse mmdd} {
+ clock scan {January 31} -format {%B %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.320 {parse mmdd} {
+ clock scan {January xxxi} -format {%B %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.321 {parse mmdd} {
+ clock scan {Jan 31} -format {%h %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.322 {parse mmdd} {
+ clock scan {Jan xxxi} -format {%h %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.323 {parse mmdd} {
+ clock scan {Jan 31} -format {%h %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.324 {parse mmdd} {
+ clock scan {Jan xxxi} -format {%h %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.325 {parse mmdd} {
+ clock scan {01 31} -format {%m %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.326 {parse mmdd} {
+ clock scan {01 xxxi} -format {%m %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.327 {parse mmdd} {
+ clock scan {01 31} -format {%m %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.328 {parse mmdd} {
+ clock scan {01 xxxi} -format {%m %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.329 {parse mmdd} {
+ clock scan {i 31} -format {%Om %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.330 {parse mmdd} {
+ clock scan {i xxxi} -format {%Om %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.331 {parse mmdd} {
+ clock scan {i 31} -format {%Om %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.332 {parse mmdd} {
+ clock scan {i xxxi} -format {%Om %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.333 {parse mmdd} {
+ clock scan { 1 31} -format {%N %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.334 {parse mmdd} {
+ clock scan { 1 xxxi} -format {%N %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.335 {parse mmdd} {
+ clock scan { 1 31} -format {%N %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.336 {parse mmdd} {
+ clock scan { 1 xxxi} -format {%N %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2116972800
+test clock-19.337 {parse mmdd} {
+ clock scan {Dec 02} -format {%b %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.338 {parse mmdd} {
+ clock scan {Dec ii} -format {%b %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.339 {parse mmdd} {
+ clock scan {Dec 2} -format {%b %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.340 {parse mmdd} {
+ clock scan {Dec ii} -format {%b %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.341 {parse mmdd} {
+ clock scan {December 02} -format {%B %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.342 {parse mmdd} {
+ clock scan {December ii} -format {%B %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.343 {parse mmdd} {
+ clock scan {December 2} -format {%B %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.344 {parse mmdd} {
+ clock scan {December ii} -format {%B %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.345 {parse mmdd} {
+ clock scan {Dec 02} -format {%h %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.346 {parse mmdd} {
+ clock scan {Dec ii} -format {%h %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.347 {parse mmdd} {
+ clock scan {Dec 2} -format {%h %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.348 {parse mmdd} {
+ clock scan {Dec ii} -format {%h %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.349 {parse mmdd} {
+ clock scan {12 02} -format {%m %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.350 {parse mmdd} {
+ clock scan {12 ii} -format {%m %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.351 {parse mmdd} {
+ clock scan {12 2} -format {%m %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.352 {parse mmdd} {
+ clock scan {12 ii} -format {%m %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.353 {parse mmdd} {
+ clock scan {xii 02} -format {%Om %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.354 {parse mmdd} {
+ clock scan {xii ii} -format {%Om %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.355 {parse mmdd} {
+ clock scan {xii 2} -format {%Om %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.356 {parse mmdd} {
+ clock scan {xii ii} -format {%Om %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.357 {parse mmdd} {
+ clock scan {12 02} -format {%N %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.358 {parse mmdd} {
+ clock scan {12 ii} -format {%N %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.359 {parse mmdd} {
+ clock scan {12 2} -format {%N %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.360 {parse mmdd} {
+ clock scan {12 ii} -format {%N %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2143324800
+test clock-19.361 {parse mmdd} {
+ clock scan {Dec 31} -format {%b %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.362 {parse mmdd} {
+ clock scan {Dec xxxi} -format {%b %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.363 {parse mmdd} {
+ clock scan {Dec 31} -format {%b %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.364 {parse mmdd} {
+ clock scan {Dec xxxi} -format {%b %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.365 {parse mmdd} {
+ clock scan {December 31} -format {%B %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.366 {parse mmdd} {
+ clock scan {December xxxi} -format {%B %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.367 {parse mmdd} {
+ clock scan {December 31} -format {%B %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.368 {parse mmdd} {
+ clock scan {December xxxi} -format {%B %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.369 {parse mmdd} {
+ clock scan {Dec 31} -format {%h %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.370 {parse mmdd} {
+ clock scan {Dec xxxi} -format {%h %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.371 {parse mmdd} {
+ clock scan {Dec 31} -format {%h %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.372 {parse mmdd} {
+ clock scan {Dec xxxi} -format {%h %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.373 {parse mmdd} {
+ clock scan {12 31} -format {%m %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.374 {parse mmdd} {
+ clock scan {12 xxxi} -format {%m %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.375 {parse mmdd} {
+ clock scan {12 31} -format {%m %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.376 {parse mmdd} {
+ clock scan {12 xxxi} -format {%m %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.377 {parse mmdd} {
+ clock scan {xii 31} -format {%Om %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.378 {parse mmdd} {
+ clock scan {xii xxxi} -format {%Om %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.379 {parse mmdd} {
+ clock scan {xii 31} -format {%Om %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.380 {parse mmdd} {
+ clock scan {xii xxxi} -format {%Om %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.381 {parse mmdd} {
+ clock scan {12 31} -format {%N %d} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.382 {parse mmdd} {
+ clock scan {12 xxxi} -format {%N %Od} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.383 {parse mmdd} {
+ clock scan {12 31} -format {%N %e} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+test clock-19.384 {parse mmdd} {
+ clock scan {12 xxxi} -format {%N %Oe} -locale en_US_roman -base 2114380800 -gmt 1
+} 2145830400
+# END testcases19
+
+test clock-20.1 {seconds take precedence over mmdd} {
+ list [clock scan {0 0201} -format {%s %m%d} -gmt true -base 0] \
+ [clock scan {0201 0} -format {%m%d %s} -gmt true -base 0]
+} {0 0}
+test clock-20.2 {julian day takes precedence over yyddd} {
+ list [clock scan {2440588 0201} -format {%J %m%d} -gmt true -base 0] \
+ [clock scan {0201 2440588} -format {%m%d %J} -gmt true -base 0]
+} {0 0}
+test clock-20.3 {yyyyWwwd over mmdd} {
+ list [clock scan {1970W014 0201} -format {%GW%V%u %m%d} -gmt true -base 0] \
+ [clock scan {0201 1970W014} -format {%m%d %GW%V%u} -gmt true -base 0]
+} {0 0}
+test clock-20.4 {yyWwwd over mmdd} {
+ list [clock scan {70W014 0201} -format {%gW%V%u %m%d} -gmt true -base 0] \
+ [clock scan {0201 70W014} -format {%m%d %gW%V%u} -gmt true -base 0]
+} {0 0}
+
+# Test parsing of ddd
+
+test clock-21.1 {parse ddd} {
+ clock scan {001} -format {%j} -locale en_US_roman -gmt 1 -base 0
+} 0
+test clock-21.2 {parse ddd} {
+ clock scan {365} -format {%j} -locale en_US_roman -gmt 1 -base 0
+} 31449600
+test clock-21.3 {parse ddd} {
+ clock scan {001} -format {%j} -locale en_US_roman -gmt 1 -base 31536000
+} 31536000
+test clock-21.4 {parse ddd} {
+ clock scan {365} -format {%j} -locale en_US_roman -gmt 1 -base 31536000
+} 62985600
+test clock-21.5 {seconds take precedence over ddd} {
+ list [clock scan {0 002} -format {%s %j} -gmt true -base 0] \
+ [clock scan {002 0} -format {%j %s} -gmt true -base 0]
+} {0 0}
+test clock-21.6 {julian day takes precedence over yyddd} {
+ list [clock scan {2440588 002} -format {%J %j} -gmt true -base 0] \
+ [clock scan {002 2440588} -format {%j %J} -gmt true -base 0]
+} {0 0}
+test clock-21.7 {yyyyWwwd over ddd} {
+ list [clock scan {1970W014 002} -format {%GW%V%u %j} -gmt true -base 0] \
+ [clock scan {002 1970W014} -format {%j %GW%V%u} -gmt true -base 0]
+} {0 0}
+test clock-21.8 {yyWwwd over ddd} {
+ list [clock scan {70W014 002} -format {%gW%V%u %j} -gmt true -base 0] \
+ [clock scan {002 70W014} -format {%j %gW%V%u} -gmt true -base 0]
+} {0 0}
+
+# BEGIN testcases22
+
+# Test parsing of Wwwd
+
+test clock-22.1 {parse Wwwd} {
+ clock scan {W09 Sun} -format {W%V %a} -locale en_US_roman -gmt 1 -base 259200
+} 5097600
+test clock-22.2 {parse Wwwd} {
+ clock scan {W09 Sunday} -format {W%V %A} -locale en_US_roman -gmt 1 -base 259200
+} 5097600
+test clock-22.3 {parse Wwwd} {
+ clock scan {W09 7} -format {W%V %u} -locale en_US_roman -gmt 1 -base 259200
+} 5097600
+test clock-22.4 {parse Wwwd} {
+ clock scan {W09 0} -format {W%V %w} -locale en_US_roman -gmt 1 -base 259200
+} 5097600
+test clock-22.5 {parse Wwwd} {
+ clock scan {W09 vii} -format {W%V %Ou} -locale en_US_roman -gmt 1 -base 259200
+} 5097600
+test clock-22.6 {parse Wwwd} {
+ clock scan {W09 ?} -format {W%V %Ow} -locale en_US_roman -gmt 1 -base 259200
+} 5097600
+test clock-22.7 {parse Wwwd} {
+ clock scan {W14 Tue} -format {W%V %a} -locale en_US_roman -gmt 1 -base 259200
+} 7689600
+test clock-22.8 {parse Wwwd} {
+ clock scan {W14 Tuesday} -format {W%V %A} -locale en_US_roman -gmt 1 -base 259200
+} 7689600
+test clock-22.9 {parse Wwwd} {
+ clock scan {W14 2} -format {W%V %u} -locale en_US_roman -gmt 1 -base 259200
+} 7689600
+test clock-22.10 {parse Wwwd} {
+ clock scan {W14 2} -format {W%V %w} -locale en_US_roman -gmt 1 -base 259200
+} 7689600
+test clock-22.11 {parse Wwwd} {
+ clock scan {W14 ii} -format {W%V %Ou} -locale en_US_roman -gmt 1 -base 259200
+} 7689600
+test clock-22.12 {parse Wwwd} {
+ clock scan {W14 ii} -format {W%V %Ow} -locale en_US_roman -gmt 1 -base 259200
+} 7689600
+test clock-22.13 {parse Wwwd} {
+ clock scan {W40 Thu} -format {W%V %a} -locale en_US_roman -gmt 1 -base 259200
+} 23587200
+test clock-22.14 {parse Wwwd} {
+ clock scan {W40 Thursday} -format {W%V %A} -locale en_US_roman -gmt 1 -base 259200
+} 23587200
+test clock-22.15 {parse Wwwd} {
+ clock scan {W40 4} -format {W%V %u} -locale en_US_roman -gmt 1 -base 259200
+} 23587200
+test clock-22.16 {parse Wwwd} {
+ clock scan {W40 4} -format {W%V %w} -locale en_US_roman -gmt 1 -base 259200
+} 23587200
+test clock-22.17 {parse Wwwd} {
+ clock scan {W40 iv} -format {W%V %Ou} -locale en_US_roman -gmt 1 -base 259200
+} 23587200
+test clock-22.18 {parse Wwwd} {
+ clock scan {W40 iv} -format {W%V %Ow} -locale en_US_roman -gmt 1 -base 259200
+} 23587200
+test clock-22.19 {parse Wwwd} {
+ clock scan {W44 Sat} -format {W%V %a} -locale en_US_roman -gmt 1 -base 259200
+} 26179200
+test clock-22.20 {parse Wwwd} {
+ clock scan {W44 Saturday} -format {W%V %A} -locale en_US_roman -gmt 1 -base 259200
+} 26179200
+test clock-22.21 {parse Wwwd} {
+ clock scan {W44 6} -format {W%V %u} -locale en_US_roman -gmt 1 -base 259200
+} 26179200
+test clock-22.22 {parse Wwwd} {
+ clock scan {W44 6} -format {W%V %w} -locale en_US_roman -gmt 1 -base 259200
+} 26179200
+test clock-22.23 {parse Wwwd} {
+ clock scan {W44 vi} -format {W%V %Ou} -locale en_US_roman -gmt 1 -base 259200
+} 26179200
+test clock-22.24 {parse Wwwd} {
+ clock scan {W44 vi} -format {W%V %Ow} -locale en_US_roman -gmt 1 -base 259200
+} 26179200
+test clock-22.25 {parse Wwwd} {
+ clock scan {W09 Mon} -format {W%V %a} -locale en_US_roman -gmt 1 -base 31795200
+} 36633600
+test clock-22.26 {parse Wwwd} {
+ clock scan {W09 Monday} -format {W%V %A} -locale en_US_roman -gmt 1 -base 31795200
+} 36633600
+test clock-22.27 {parse Wwwd} {
+ clock scan {W09 1} -format {W%V %u} -locale en_US_roman -gmt 1 -base 31795200
+} 36633600
+test clock-22.28 {parse Wwwd} {
+ clock scan {W09 1} -format {W%V %w} -locale en_US_roman -gmt 1 -base 31795200
+} 36633600
+test clock-22.29 {parse Wwwd} {
+ clock scan {W09 i} -format {W%V %Ou} -locale en_US_roman -gmt 1 -base 31795200
+} 36633600
+test clock-22.30 {parse Wwwd} {
+ clock scan {W09 i} -format {W%V %Ow} -locale en_US_roman -gmt 1 -base 31795200
+} 36633600
+test clock-22.31 {parse Wwwd} {
+ clock scan {W13 Wed} -format {W%V %a} -locale en_US_roman -gmt 1 -base 31795200
+} 39225600
+test clock-22.32 {parse Wwwd} {
+ clock scan {W13 Wednesday} -format {W%V %A} -locale en_US_roman -gmt 1 -base 31795200
+} 39225600
+test clock-22.33 {parse Wwwd} {
+ clock scan {W13 3} -format {W%V %u} -locale en_US_roman -gmt 1 -base 31795200
+} 39225600
+test clock-22.34 {parse Wwwd} {
+ clock scan {W13 3} -format {W%V %w} -locale en_US_roman -gmt 1 -base 31795200
+} 39225600
+test clock-22.35 {parse Wwwd} {
+ clock scan {W13 iii} -format {W%V %Ou} -locale en_US_roman -gmt 1 -base 31795200
+} 39225600
+test clock-22.36 {parse Wwwd} {
+ clock scan {W13 iii} -format {W%V %Ow} -locale en_US_roman -gmt 1 -base 31795200
+} 39225600
+test clock-22.37 {parse Wwwd} {
+ clock scan {W39 Fri} -format {W%V %a} -locale en_US_roman -gmt 1 -base 31795200
+} 55123200
+test clock-22.38 {parse Wwwd} {
+ clock scan {W39 Friday} -format {W%V %A} -locale en_US_roman -gmt 1 -base 31795200
+} 55123200
+test clock-22.39 {parse Wwwd} {
+ clock scan {W39 5} -format {W%V %u} -locale en_US_roman -gmt 1 -base 31795200
+} 55123200
+test clock-22.40 {parse Wwwd} {
+ clock scan {W39 5} -format {W%V %w} -locale en_US_roman -gmt 1 -base 31795200
+} 55123200
+test clock-22.41 {parse Wwwd} {
+ clock scan {W39 v} -format {W%V %Ou} -locale en_US_roman -gmt 1 -base 31795200
+} 55123200
+test clock-22.42 {parse Wwwd} {
+ clock scan {W39 v} -format {W%V %Ow} -locale en_US_roman -gmt 1 -base 31795200
+} 55123200
+test clock-22.43 {parse Wwwd} {
+ clock scan {W43 Sun} -format {W%V %a} -locale en_US_roman -gmt 1 -base 31795200
+} 57715200
+test clock-22.44 {parse Wwwd} {
+ clock scan {W43 Sunday} -format {W%V %A} -locale en_US_roman -gmt 1 -base 31795200
+} 57715200
+test clock-22.45 {parse Wwwd} {
+ clock scan {W43 7} -format {W%V %u} -locale en_US_roman -gmt 1 -base 31795200
+} 57715200
+test clock-22.46 {parse Wwwd} {
+ clock scan {W43 0} -format {W%V %w} -locale en_US_roman -gmt 1 -base 31795200
+} 57715200
+test clock-22.47 {parse Wwwd} {
+ clock scan {W43 vii} -format {W%V %Ou} -locale en_US_roman -gmt 1 -base 31795200
+} 57715200
+test clock-22.48 {parse Wwwd} {
+ clock scan {W43 ?} -format {W%V %Ow} -locale en_US_roman -gmt 1 -base 31795200
+} 57715200
+test clock-22.49 {parse Wwwd} {
+ clock scan {W09 Wed} -format {W%V %a} -locale en_US_roman -gmt 1 -base 946944000
+} 951868800
+test clock-22.50 {parse Wwwd} {
+ clock scan {W09 Wednesday} -format {W%V %A} -locale en_US_roman -gmt 1 -base 946944000
+} 951868800
+test clock-22.51 {parse Wwwd} {
+ clock scan {W09 3} -format {W%V %u} -locale en_US_roman -gmt 1 -base 946944000
+} 951868800
+test clock-22.52 {parse Wwwd} {
+ clock scan {W09 3} -format {W%V %w} -locale en_US_roman -gmt 1 -base 946944000
+} 951868800
+test clock-22.53 {parse Wwwd} {
+ clock scan {W09 iii} -format {W%V %Ou} -locale en_US_roman -gmt 1 -base 946944000
+} 951868800
+test clock-22.54 {parse Wwwd} {
+ clock scan {W09 iii} -format {W%V %Ow} -locale en_US_roman -gmt 1 -base 946944000
+} 951868800
+test clock-22.55 {parse Wwwd} {
+ clock scan {W13 Fri} -format {W%V %a} -locale en_US_roman -gmt 1 -base 946944000
+} 954460800
+test clock-22.56 {parse Wwwd} {
+ clock scan {W13 Friday} -format {W%V %A} -locale en_US_roman -gmt 1 -base 946944000
+} 954460800
+test clock-22.57 {parse Wwwd} {
+ clock scan {W13 5} -format {W%V %u} -locale en_US_roman -gmt 1 -base 946944000
+} 954460800
+test clock-22.58 {parse Wwwd} {
+ clock scan {W13 5} -format {W%V %w} -locale en_US_roman -gmt 1 -base 946944000
+} 954460800
+test clock-22.59 {parse Wwwd} {
+ clock scan {W13 v} -format {W%V %Ou} -locale en_US_roman -gmt 1 -base 946944000
+} 954460800
+test clock-22.60 {parse Wwwd} {
+ clock scan {W13 v} -format {W%V %Ow} -locale en_US_roman -gmt 1 -base 946944000
+} 954460800
+test clock-22.61 {parse Wwwd} {
+ clock scan {W39 Sun} -format {W%V %a} -locale en_US_roman -gmt 1 -base 946944000
+} 970358400
+test clock-22.62 {parse Wwwd} {
+ clock scan {W39 Sunday} -format {W%V %A} -locale en_US_roman -gmt 1 -base 946944000
+} 970358400
+test clock-22.63 {parse Wwwd} {
+ clock scan {W39 7} -format {W%V %u} -locale en_US_roman -gmt 1 -base 946944000
+} 970358400
+test clock-22.64 {parse Wwwd} {
+ clock scan {W39 0} -format {W%V %w} -locale en_US_roman -gmt 1 -base 946944000
+} 970358400
+test clock-22.65 {parse Wwwd} {
+ clock scan {W39 vii} -format {W%V %Ou} -locale en_US_roman -gmt 1 -base 946944000
+} 970358400
+test clock-22.66 {parse Wwwd} {
+ clock scan {W39 ?} -format {W%V %Ow} -locale en_US_roman -gmt 1 -base 946944000
+} 970358400
+test clock-22.67 {parse Wwwd} {
+ clock scan {W44 Tue} -format {W%V %a} -locale en_US_roman -gmt 1 -base 946944000
+} 972950400
+test clock-22.68 {parse Wwwd} {
+ clock scan {W44 Tuesday} -format {W%V %A} -locale en_US_roman -gmt 1 -base 946944000
+} 972950400
+test clock-22.69 {parse Wwwd} {
+ clock scan {W44 2} -format {W%V %u} -locale en_US_roman -gmt 1 -base 946944000
+} 972950400
+test clock-22.70 {parse Wwwd} {
+ clock scan {W44 2} -format {W%V %w} -locale en_US_roman -gmt 1 -base 946944000
+} 972950400
+test clock-22.71 {parse Wwwd} {
+ clock scan {W44 ii} -format {W%V %Ou} -locale en_US_roman -gmt 1 -base 946944000
+} 972950400
+test clock-22.72 {parse Wwwd} {
+ clock scan {W44 ii} -format {W%V %Ow} -locale en_US_roman -gmt 1 -base 946944000
+} 972950400
+test clock-22.73 {parse Wwwd} {
+ clock scan {W09 Thu} -format {W%V %a} -locale en_US_roman -gmt 1 -base 978566400
+} 983404800
+test clock-22.74 {parse Wwwd} {
+ clock scan {W09 Thursday} -format {W%V %A} -locale en_US_roman -gmt 1 -base 978566400
+} 983404800
+test clock-22.75 {parse Wwwd} {
+ clock scan {W09 4} -format {W%V %u} -locale en_US_roman -gmt 1 -base 978566400
+} 983404800
+test clock-22.76 {parse Wwwd} {
+ clock scan {W09 4} -format {W%V %w} -locale en_US_roman -gmt 1 -base 978566400
+} 983404800
+test clock-22.77 {parse Wwwd} {
+ clock scan {W09 iv} -format {W%V %Ou} -locale en_US_roman -gmt 1 -base 978566400
+} 983404800
+test clock-22.78 {parse Wwwd} {
+ clock scan {W09 iv} -format {W%V %Ow} -locale en_US_roman -gmt 1 -base 978566400
+} 983404800
+test clock-22.79 {parse Wwwd} {
+ clock scan {W13 Sat} -format {W%V %a} -locale en_US_roman -gmt 1 -base 978566400
+} 985996800
+test clock-22.80 {parse Wwwd} {
+ clock scan {W13 Saturday} -format {W%V %A} -locale en_US_roman -gmt 1 -base 978566400
+} 985996800
+test clock-22.81 {parse Wwwd} {
+ clock scan {W13 6} -format {W%V %u} -locale en_US_roman -gmt 1 -base 978566400
+} 985996800
+test clock-22.82 {parse Wwwd} {
+ clock scan {W13 6} -format {W%V %w} -locale en_US_roman -gmt 1 -base 978566400
+} 985996800
+test clock-22.83 {parse Wwwd} {
+ clock scan {W13 vi} -format {W%V %Ou} -locale en_US_roman -gmt 1 -base 978566400
+} 985996800
+test clock-22.84 {parse Wwwd} {
+ clock scan {W13 vi} -format {W%V %Ow} -locale en_US_roman -gmt 1 -base 978566400
+} 985996800
+test clock-22.85 {parse Wwwd} {
+ clock scan {W40 Mon} -format {W%V %a} -locale en_US_roman -gmt 1 -base 978566400
+} 1001894400
+test clock-22.86 {parse Wwwd} {
+ clock scan {W40 Monday} -format {W%V %A} -locale en_US_roman -gmt 1 -base 978566400
+} 1001894400
+test clock-22.87 {parse Wwwd} {
+ clock scan {W40 1} -format {W%V %u} -locale en_US_roman -gmt 1 -base 978566400
+} 1001894400
+test clock-22.88 {parse Wwwd} {
+ clock scan {W40 1} -format {W%V %w} -locale en_US_roman -gmt 1 -base 978566400
+} 1001894400
+test clock-22.89 {parse Wwwd} {
+ clock scan {W40 i} -format {W%V %Ou} -locale en_US_roman -gmt 1 -base 978566400
+} 1001894400
+test clock-22.90 {parse Wwwd} {
+ clock scan {W40 i} -format {W%V %Ow} -locale en_US_roman -gmt 1 -base 978566400
+} 1001894400
+test clock-22.91 {parse Wwwd} {
+ clock scan {W44 Wed} -format {W%V %a} -locale en_US_roman -gmt 1 -base 978566400
+} 1004486400
+test clock-22.92 {parse Wwwd} {
+ clock scan {W44 Wednesday} -format {W%V %A} -locale en_US_roman -gmt 1 -base 978566400
+} 1004486400
+test clock-22.93 {parse Wwwd} {
+ clock scan {W44 3} -format {W%V %u} -locale en_US_roman -gmt 1 -base 978566400
+} 1004486400
+test clock-22.94 {parse Wwwd} {
+ clock scan {W44 3} -format {W%V %w} -locale en_US_roman -gmt 1 -base 978566400
+} 1004486400
+test clock-22.95 {parse Wwwd} {
+ clock scan {W44 iii} -format {W%V %Ou} -locale en_US_roman -gmt 1 -base 978566400
+} 1004486400
+test clock-22.96 {parse Wwwd} {
+ clock scan {W44 iii} -format {W%V %Ow} -locale en_US_roman -gmt 1 -base 978566400
+} 1004486400
+# END testcases22
+
+# Test precedence of Wwwd
+test clock-23.1 {seconds take precedence over Wwwd} {
+ list [clock scan {0 W024} -format {%s W%V%u} -gmt true -base 0] \
+ [clock scan {W024 0} -format {W%V%u %s} -gmt true -base 0]
+} {0 0}
+test clock-23.2 {julian day takes precedence over Wwwd} {
+ list [clock scan {2440588 W024} -format {%J W%V%u} -gmt true -base 0] \
+ [clock scan {W024 2440588} -format {W%V%u %J} -gmt true -base 0]
+} {0 0}
+test clock-23.3 {Wwwd precedence below yyyymmdd} {
+ list [clock scan {19700101 W014} -format {%Y%m%d W%V%u} -gmt true -base 0] \
+ [clock scan {W014 19700101} -format {W%V%u %Y%m%d} -gmt true -base 0]
+} {0 0}
+test clock-23.4 {Wwwd precedence below yyyyddd} {
+ list [clock scan {1970001 W014} -format {%Y%j W%V%u} -gmt true -base 0] \
+ [clock scan {W014 1970001} -format {W%V%u %Y%j} -gmt true -base 0]
+} {0 0}
+test clock-23.5 {Wwwd precedence below yymmdd} {
+ list [clock scan {700101 W014} -format {%y%m%d W%V%u} -gmt true -base 0] \
+ [clock scan {W014 700101} -format {W%V%u %y%m%d} -gmt true -base 0]
+} {0 0}
+test clock-23.6 {Wwwd precedence below yyddd} {
+ list [clock scan {70001 W014} -format {%y%j W%V%u} -gmt true -base 0] \
+ [clock scan {W014 70001} -format {W%V%u %y%j} -gmt true -base 0]
+} {0 0}
+
+# BEGIN testcases24
+
+# Test parsing of naked day-of-month
+
+test clock-24.1 {parse naked day of month} {
+ clock scan 02 -format %d -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-24.2 {parse naked day of month} {
+ clock scan ii -format %Od -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-24.3 {parse naked day of month} {
+ clock scan { 2} -format %e -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-24.4 {parse naked day of month} {
+ clock scan ii -format %Oe -locale en_US_roman -base 0 -gmt 1
+} 86400
+test clock-24.5 {parse naked day of month} {
+ clock scan 28 -format %d -locale en_US_roman -base 0 -gmt 1
+} 2332800
+test clock-24.6 {parse naked day of month} {
+ clock scan xxviii -format %Od -locale en_US_roman -base 0 -gmt 1
+} 2332800
+test clock-24.7 {parse naked day of month} {
+ clock scan 28 -format %e -locale en_US_roman -base 0 -gmt 1
+} 2332800
+test clock-24.8 {parse naked day of month} {
+ clock scan xxviii -format %Oe -locale en_US_roman -base 0 -gmt 1
+} 2332800
+test clock-24.9 {parse naked day of month} {
+ clock scan 02 -format %d -locale en_US_roman -base 28857600 -gmt 1
+} 28944000
+test clock-24.10 {parse naked day of month} {
+ clock scan ii -format %Od -locale en_US_roman -base 28857600 -gmt 1
+} 28944000
+test clock-24.11 {parse naked day of month} {
+ clock scan { 2} -format %e -locale en_US_roman -base 28857600 -gmt 1
+} 28944000
+test clock-24.12 {parse naked day of month} {
+ clock scan ii -format %Oe -locale en_US_roman -base 28857600 -gmt 1
+} 28944000
+test clock-24.13 {parse naked day of month} {
+ clock scan 28 -format %d -locale en_US_roman -base 28857600 -gmt 1
+} 31190400
+test clock-24.14 {parse naked day of month} {
+ clock scan xxviii -format %Od -locale en_US_roman -base 28857600 -gmt 1
+} 31190400
+test clock-24.15 {parse naked day of month} {
+ clock scan 28 -format %e -locale en_US_roman -base 28857600 -gmt 1
+} 31190400
+test clock-24.16 {parse naked day of month} {
+ clock scan xxviii -format %Oe -locale en_US_roman -base 28857600 -gmt 1
+} 31190400
+test clock-24.17 {parse naked day of month} {
+ clock scan 02 -format %d -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-24.18 {parse naked day of month} {
+ clock scan ii -format %Od -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-24.19 {parse naked day of month} {
+ clock scan { 2} -format %e -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-24.20 {parse naked day of month} {
+ clock scan ii -format %Oe -locale en_US_roman -base 946684800 -gmt 1
+} 946771200
+test clock-24.21 {parse naked day of month} {
+ clock scan 28 -format %d -locale en_US_roman -base 946684800 -gmt 1
+} 949017600
+test clock-24.22 {parse naked day of month} {
+ clock scan xxviii -format %Od -locale en_US_roman -base 946684800 -gmt 1
+} 949017600
+test clock-24.23 {parse naked day of month} {
+ clock scan 28 -format %e -locale en_US_roman -base 946684800 -gmt 1
+} 949017600
+test clock-24.24 {parse naked day of month} {
+ clock scan xxviii -format %Oe -locale en_US_roman -base 946684800 -gmt 1
+} 949017600
+test clock-24.25 {parse naked day of month} {
+ clock scan 02 -format %d -locale en_US_roman -base 975628800 -gmt 1
+} 975715200
+test clock-24.26 {parse naked day of month} {
+ clock scan ii -format %Od -locale en_US_roman -base 975628800 -gmt 1
+} 975715200
+test clock-24.27 {parse naked day of month} {
+ clock scan { 2} -format %e -locale en_US_roman -base 975628800 -gmt 1
+} 975715200
+test clock-24.28 {parse naked day of month} {
+ clock scan ii -format %Oe -locale en_US_roman -base 975628800 -gmt 1
+} 975715200
+test clock-24.29 {parse naked day of month} {
+ clock scan 28 -format %d -locale en_US_roman -base 975628800 -gmt 1
+} 977961600
+test clock-24.30 {parse naked day of month} {
+ clock scan xxviii -format %Od -locale en_US_roman -base 975628800 -gmt 1
+} 977961600
+test clock-24.31 {parse naked day of month} {
+ clock scan 28 -format %e -locale en_US_roman -base 975628800 -gmt 1
+} 977961600
+test clock-24.32 {parse naked day of month} {
+ clock scan xxviii -format %Oe -locale en_US_roman -base 975628800 -gmt 1
+} 977961600
+# END testcases24
+
+test clock-25.1 {seconds take precedence over dd} {
+ list [clock scan {0 02} -format {%s %d} -gmt true -base 0] \
+ [clock scan {02 0} -format {%d %s} -gmt true -base 0]
+} {0 0}
+test clock-25.2 {julian day takes precedence over dd} {
+ list [clock scan {2440588 02} -format {%J %d} -gmt true -base 0] \
+ [clock scan {02 2440588} -format {%d %J} -gmt true -base 0]
+} {0 0}
+test clock-25.3 {yyyyddd over dd} {
+ list [clock scan {1970001 02} -format {%Y%j %d} -gmt true -base 0] \
+ [clock scan {02 1970001} -format {%d %Y%j} -gmt true -base 0]
+} {0 0}
+test clock-25.4 {yyyyWwwd over dd} {
+ list [clock scan {1970W014 02} -format {%GW%V%u %d} -gmt true -base 0] \
+ [clock scan {02 1970W014} -format {%d %GW%V%u} -gmt true -base 0]
+} {0 0}
+test clock-25.5 {yyWwwd over dd} {
+ list [clock scan {70W014 02} -format {%gW%V%u %d} -gmt true -base 0] \
+ [clock scan {02 70W014} -format {%d %gW%V%u} -gmt true -base 0]
+} {0 0}
+test clock-25.6 {yyddd over dd} {
+ list [clock scan {70001 02} -format {%y%j %d} -gmt true -base 0] \
+ [clock scan {02 70001} -format {%d %y%j} -gmt true -base 0]
+} {0 0}
+test clock-25.7 {ddd over dd} {
+ list [clock scan {001 02} -format {%j %d} -gmt true -base 0] \
+ [clock scan {02 001} -format {%d %j} -gmt true -base 0]
+} {0 0}
+
+# BEGIN testcases26
+
+# Test parsing of naked day of week
+
+test clock-26.1 {parse naked day of week} {
+ clock scan Mon -format %a -locale en_US_roman -gmt 1 -base 0
+} -259200
+test clock-26.2 {parse naked day of week} {
+ clock scan Monday -format %A -locale en_US_roman -gmt 1 -base 0
+} -259200
+test clock-26.3 {parse naked day of week} {
+ clock scan 1 -format %u -locale en_US_roman -gmt 1 -base 0
+} -259200
+test clock-26.4 {parse naked day of week} {
+ clock scan 1 -format %w -locale en_US_roman -gmt 1 -base 0
+} -259200
+test clock-26.5 {parse naked day of week} {
+ clock scan i -format %Ou -locale en_US_roman -gmt 1 -base 0
+} -259200
+test clock-26.6 {parse naked day of week} {
+ clock scan i -format %Ow -locale en_US_roman -gmt 1 -base 0
+} -259200
+test clock-26.7 {parse naked day of week} {
+ clock scan Sun -format %a -locale en_US_roman -gmt 1 -base 0
+} 259200
+test clock-26.8 {parse naked day of week} {
+ clock scan Sunday -format %A -locale en_US_roman -gmt 1 -base 0
+} 259200
+test clock-26.9 {parse naked day of week} {
+ clock scan 7 -format %u -locale en_US_roman -gmt 1 -base 0
+} 259200
+test clock-26.10 {parse naked day of week} {
+ clock scan 0 -format %w -locale en_US_roman -gmt 1 -base 0
+} 259200
+test clock-26.11 {parse naked day of week} {
+ clock scan vii -format %Ou -locale en_US_roman -gmt 1 -base 0
+} 259200
+test clock-26.12 {parse naked day of week} {
+ clock scan ? -format %Ow -locale en_US_roman -gmt 1 -base 0
+} 259200
+test clock-26.13 {parse naked day of week} {
+ clock scan Mon -format %a -locale en_US_roman -gmt 1 -base 30844800
+} 30585600
+test clock-26.14 {parse naked day of week} {
+ clock scan Monday -format %A -locale en_US_roman -gmt 1 -base 30844800
+} 30585600
+test clock-26.15 {parse naked day of week} {
+ clock scan 1 -format %u -locale en_US_roman -gmt 1 -base 30844800
+} 30585600
+test clock-26.16 {parse naked day of week} {
+ clock scan 1 -format %w -locale en_US_roman -gmt 1 -base 30844800
+} 30585600
+test clock-26.17 {parse naked day of week} {
+ clock scan i -format %Ou -locale en_US_roman -gmt 1 -base 30844800
+} 30585600
+test clock-26.18 {parse naked day of week} {
+ clock scan i -format %Ow -locale en_US_roman -gmt 1 -base 30844800
+} 30585600
+test clock-26.19 {parse naked day of week} {
+ clock scan Sun -format %a -locale en_US_roman -gmt 1 -base 30844800
+} 31104000
+test clock-26.20 {parse naked day of week} {
+ clock scan Sunday -format %A -locale en_US_roman -gmt 1 -base 30844800
+} 31104000
+test clock-26.21 {parse naked day of week} {
+ clock scan 7 -format %u -locale en_US_roman -gmt 1 -base 30844800
+} 31104000
+test clock-26.22 {parse naked day of week} {
+ clock scan 0 -format %w -locale en_US_roman -gmt 1 -base 30844800
+} 31104000
+test clock-26.23 {parse naked day of week} {
+ clock scan vii -format %Ou -locale en_US_roman -gmt 1 -base 30844800
+} 31104000
+test clock-26.24 {parse naked day of week} {
+ clock scan ? -format %Ow -locale en_US_roman -gmt 1 -base 30844800
+} 31104000
+test clock-26.25 {parse naked day of week} {
+ clock scan Mon -format %a -locale en_US_roman -gmt 1 -base 978566400
+} 978307200
+test clock-26.26 {parse naked day of week} {
+ clock scan Monday -format %A -locale en_US_roman -gmt 1 -base 978566400
+} 978307200
+test clock-26.27 {parse naked day of week} {
+ clock scan 1 -format %u -locale en_US_roman -gmt 1 -base 978566400
+} 978307200
+test clock-26.28 {parse naked day of week} {
+ clock scan 1 -format %w -locale en_US_roman -gmt 1 -base 978566400
+} 978307200
+test clock-26.29 {parse naked day of week} {
+ clock scan i -format %Ou -locale en_US_roman -gmt 1 -base 978566400
+} 978307200
+test clock-26.30 {parse naked day of week} {
+ clock scan i -format %Ow -locale en_US_roman -gmt 1 -base 978566400
+} 978307200
+test clock-26.31 {parse naked day of week} {
+ clock scan Sun -format %a -locale en_US_roman -gmt 1 -base 978566400
+} 978825600
+test clock-26.32 {parse naked day of week} {
+ clock scan Sunday -format %A -locale en_US_roman -gmt 1 -base 978566400
+} 978825600
+test clock-26.33 {parse naked day of week} {
+ clock scan 7 -format %u -locale en_US_roman -gmt 1 -base 978566400
+} 978825600
+test clock-26.34 {parse naked day of week} {
+ clock scan 0 -format %w -locale en_US_roman -gmt 1 -base 978566400
+} 978825600
+test clock-26.35 {parse naked day of week} {
+ clock scan vii -format %Ou -locale en_US_roman -gmt 1 -base 978566400
+} 978825600
+test clock-26.36 {parse naked day of week} {
+ clock scan ? -format %Ow -locale en_US_roman -gmt 1 -base 978566400
+} 978825600
+test clock-26.37 {parse naked day of week} {
+ clock scan Mon -format %a -locale en_US_roman -gmt 1 -base 1009411200
+} 1009152000
+test clock-26.38 {parse naked day of week} {
+ clock scan Monday -format %A -locale en_US_roman -gmt 1 -base 1009411200
+} 1009152000
+test clock-26.39 {parse naked day of week} {
+ clock scan 1 -format %u -locale en_US_roman -gmt 1 -base 1009411200
+} 1009152000
+test clock-26.40 {parse naked day of week} {
+ clock scan 1 -format %w -locale en_US_roman -gmt 1 -base 1009411200
+} 1009152000
+test clock-26.41 {parse naked day of week} {
+ clock scan i -format %Ou -locale en_US_roman -gmt 1 -base 1009411200
+} 1009152000
+test clock-26.42 {parse naked day of week} {
+ clock scan i -format %Ow -locale en_US_roman -gmt 1 -base 1009411200
+} 1009152000
+test clock-26.43 {parse naked day of week} {
+ clock scan Sun -format %a -locale en_US_roman -gmt 1 -base 1009411200
+} 1009670400
+test clock-26.44 {parse naked day of week} {
+ clock scan Sunday -format %A -locale en_US_roman -gmt 1 -base 1009411200
+} 1009670400
+test clock-26.45 {parse naked day of week} {
+ clock scan 7 -format %u -locale en_US_roman -gmt 1 -base 1009411200
+} 1009670400
+test clock-26.46 {parse naked day of week} {
+ clock scan 0 -format %w -locale en_US_roman -gmt 1 -base 1009411200
+} 1009670400
+test clock-26.47 {parse naked day of week} {
+ clock scan vii -format %Ou -locale en_US_roman -gmt 1 -base 1009411200
+} 1009670400
+test clock-26.48 {parse naked day of week} {
+ clock scan ? -format %Ow -locale en_US_roman -gmt 1 -base 1009411200
+} 1009670400
+# END testcases26
+
+test clock-27.1 {seconds take precedence over naked weekday} {
+ list [clock scan {0 1} -format {%s %u} -gmt true -base 0] \
+ [clock scan {1 0} -format {%u %s} -gmt true -base 0]
+} {0 0}
+test clock-27.2 {julian day takes precedence over naked weekday} {
+ list [clock scan {2440588 1} -format {%J %u} -gmt true -base 0] \
+ [clock scan {1 2440588} -format {%u %J} -gmt true -base 0]
+} {0 0}
+test clock-27.3 {yyyymmdd over naked weekday} {
+ list [clock scan {19700101 1} -format {%Y%m%d %u} -gmt true -base 0] \
+ [clock scan {1 19700101} -format {%u %Y%m%d} -gmt true -base 0]
+} {0 0}
+test clock-27.4 {yyyyddd over naked weekday} {
+ list [clock scan {1970001 1} -format {%Y%j %u} -gmt true -base 0] \
+ [clock scan {1 1970001} -format {%u %Y%j} -gmt true -base 0]
+} {0 0}
+test clock-27.5 {yymmdd over naked weekday} {
+ list [clock scan {700101 1} -format {%y%m%d %u} -gmt true -base 0] \
+ [clock scan {1 700101} -format {%u %y%m%d} -gmt true -base 0]
+} {0 0}
+test clock-27.6 {yyddd over naked weekday} {
+ list [clock scan {70001 1} -format {%y%j %u} -gmt true -base 0] \
+ [clock scan {1 70001} -format {%u %y%j} -gmt true -base 0]
+} {0 0}
+test clock-27.7 {mmdd over naked weekday} {
+ list [clock scan {0101 1} -format {%m%d %u} -gmt true -base 0] \
+ [clock scan {1 0101} -format {%u %m%d} -gmt true -base 0]
+} {0 0}
+test clock-27.8 {ddd over naked weekday} {
+ list [clock scan {001 1} -format {%j %u} -gmt true -base 0] \
+ [clock scan {1 001} -format {%u %j} -gmt true -base 0]
+} {0 0}
+test clock-27.9 {naked day of month over naked weekday} {
+ list [clock scan {01 1} -format {%d %u} -gmt true -base 0] \
+ [clock scan {1 01} -format {%u %d} -gmt true -base 0]
+} {0 0}
+
+test clock-28.1 {base date} {
+ clock scan {} -format {} -gmt true -base 1234567890
+} 1234483200
+
+# BEGIN testcases29
+
+# Test parsing of time of day
+
+test clock-29.1 {time parsing} {
+ clock scan {2440588 00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H }
+} 0
+test clock-29.2 {time parsing} {
+ clock scan {2440588 00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M }
+} 0
+test clock-29.3 {time parsing} {
+ clock scan {2440588 00:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM }
+} 0
+test clock-29.4 {time parsing} {
+ clock scan {2440588 00:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 0
+test clock-29.5 {time parsing} {
+ clock scan {2440588 00:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 0
+test clock-29.6 {time parsing} {
+ clock scan {2440588 0 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k }
+} 0
+test clock-29.7 {time parsing} {
+ clock scan {2440588 0:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M }
+} 0
+test clock-29.8 {time parsing} {
+ clock scan {2440588 0:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM }
+} 0
+test clock-29.9 {time parsing} {
+ clock scan {2440588 0:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 0
+test clock-29.10 {time parsing} {
+ clock scan {2440588 0:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 0
+test clock-29.11 {time parsing} {
+ clock scan {2440588 ? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH }
+} 0
+test clock-29.12 {time parsing} {
+ clock scan {2440588 ?:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M }
+} 0
+test clock-29.13 {time parsing} {
+ clock scan {2440588 ?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM }
+} 0
+test clock-29.14 {time parsing} {
+ clock scan {2440588 ?:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 0
+test clock-29.15 {time parsing} {
+ clock scan {2440588 ?:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 0
+test clock-29.16 {time parsing} {
+ clock scan {2440588 ? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok }
+} 0
+test clock-29.17 {time parsing} {
+ clock scan {2440588 ?:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M }
+} 0
+test clock-29.18 {time parsing} {
+ clock scan {2440588 ?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM }
+} 0
+test clock-29.19 {time parsing} {
+ clock scan {2440588 ?:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 0
+test clock-29.20 {time parsing} {
+ clock scan {2440588 ?:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 0
+test clock-29.21 {time parsing} {
+ clock scan {2440588 12 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I %p}
+} 0
+test clock-29.22 {time parsing} {
+ clock scan {2440588 12:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %p}
+} 0
+test clock-29.23 {time parsing} {
+ clock scan {2440588 12:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %p}
+} 0
+test clock-29.24 {time parsing} {
+ clock scan {2440588 12:00:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 0
+test clock-29.25 {time parsing} {
+ clock scan {2440588 12:?:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 0
+test clock-29.26 {time parsing} {
+ clock scan {2440588 12 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l %p}
+} 0
+test clock-29.27 {time parsing} {
+ clock scan {2440588 12:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %p}
+} 0
+test clock-29.28 {time parsing} {
+ clock scan {2440588 12:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %p}
+} 0
+test clock-29.29 {time parsing} {
+ clock scan {2440588 12:00:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 0
+test clock-29.30 {time parsing} {
+ clock scan {2440588 12:?:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 0
+test clock-29.31 {time parsing} {
+ clock scan {2440588 xii AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI %p}
+} 0
+test clock-29.32 {time parsing} {
+ clock scan {2440588 xii:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %p}
+} 0
+test clock-29.33 {time parsing} {
+ clock scan {2440588 xii:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %p}
+} 0
+test clock-29.34 {time parsing} {
+ clock scan {2440588 xii:00:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 0
+test clock-29.35 {time parsing} {
+ clock scan {2440588 xii:?:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 0
+test clock-29.36 {time parsing} {
+ clock scan {2440588 xii AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol %p}
+} 0
+test clock-29.37 {time parsing} {
+ clock scan {2440588 xii:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %p}
+} 0
+test clock-29.38 {time parsing} {
+ clock scan {2440588 xii:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %p}
+} 0
+test clock-29.39 {time parsing} {
+ clock scan {2440588 xii:00:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 0
+test clock-29.40 {time parsing} {
+ clock scan {2440588 xii:?:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 0
+test clock-29.41 {time parsing} {
+ clock scan {2440588 12 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I %P}
+} 0
+test clock-29.42 {time parsing} {
+ clock scan {2440588 12:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %P}
+} 0
+test clock-29.43 {time parsing} {
+ clock scan {2440588 12:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %P}
+} 0
+test clock-29.44 {time parsing} {
+ clock scan {2440588 12:00:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 0
+test clock-29.45 {time parsing} {
+ clock scan {2440588 12:?:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 0
+test clock-29.46 {time parsing} {
+ clock scan {2440588 12 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l %P}
+} 0
+test clock-29.47 {time parsing} {
+ clock scan {2440588 12:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %P}
+} 0
+test clock-29.48 {time parsing} {
+ clock scan {2440588 12:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %P}
+} 0
+test clock-29.49 {time parsing} {
+ clock scan {2440588 12:00:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 0
+test clock-29.50 {time parsing} {
+ clock scan {2440588 12:?:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 0
+test clock-29.51 {time parsing} {
+ clock scan {2440588 xii am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI %P}
+} 0
+test clock-29.52 {time parsing} {
+ clock scan {2440588 xii:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %P}
+} 0
+test clock-29.53 {time parsing} {
+ clock scan {2440588 xii:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %P}
+} 0
+test clock-29.54 {time parsing} {
+ clock scan {2440588 xii:00:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 0
+test clock-29.55 {time parsing} {
+ clock scan {2440588 xii:?:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 0
+test clock-29.56 {time parsing} {
+ clock scan {2440588 xii am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol %P}
+} 0
+test clock-29.57 {time parsing} {
+ clock scan {2440588 xii:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %P}
+} 0
+test clock-29.58 {time parsing} {
+ clock scan {2440588 xii:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %P}
+} 0
+test clock-29.59 {time parsing} {
+ clock scan {2440588 xii:00:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 0
+test clock-29.60 {time parsing} {
+ clock scan {2440588 xii:?:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 0
+test clock-29.61 {time parsing} {
+ clock scan {2440588 00:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 1
+test clock-29.62 {time parsing} {
+ clock scan {2440588 00:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 1
+test clock-29.63 {time parsing} {
+ clock scan {2440588 0:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 1
+test clock-29.64 {time parsing} {
+ clock scan {2440588 0:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 1
+test clock-29.65 {time parsing} {
+ clock scan {2440588 ?:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 1
+test clock-29.66 {time parsing} {
+ clock scan {2440588 ?:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 1
+test clock-29.67 {time parsing} {
+ clock scan {2440588 ?:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 1
+test clock-29.68 {time parsing} {
+ clock scan {2440588 ?:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 1
+test clock-29.69 {time parsing} {
+ clock scan {2440588 12:00:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 1
+test clock-29.70 {time parsing} {
+ clock scan {2440588 12:?:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 1
+test clock-29.71 {time parsing} {
+ clock scan {2440588 12:00:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 1
+test clock-29.72 {time parsing} {
+ clock scan {2440588 12:?:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 1
+test clock-29.73 {time parsing} {
+ clock scan {2440588 xii:00:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 1
+test clock-29.74 {time parsing} {
+ clock scan {2440588 xii:?:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 1
+test clock-29.75 {time parsing} {
+ clock scan {2440588 xii:00:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 1
+test clock-29.76 {time parsing} {
+ clock scan {2440588 xii:?:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 1
+test clock-29.77 {time parsing} {
+ clock scan {2440588 12:00:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 1
+test clock-29.78 {time parsing} {
+ clock scan {2440588 12:?:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 1
+test clock-29.79 {time parsing} {
+ clock scan {2440588 12:00:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 1
+test clock-29.80 {time parsing} {
+ clock scan {2440588 12:?:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 1
+test clock-29.81 {time parsing} {
+ clock scan {2440588 xii:00:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 1
+test clock-29.82 {time parsing} {
+ clock scan {2440588 xii:?:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 1
+test clock-29.83 {time parsing} {
+ clock scan {2440588 xii:00:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 1
+test clock-29.84 {time parsing} {
+ clock scan {2440588 xii:?:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 1
+test clock-29.85 {time parsing} {
+ clock scan {2440588 00:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 59
+test clock-29.86 {time parsing} {
+ clock scan {2440588 00:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 59
+test clock-29.87 {time parsing} {
+ clock scan {2440588 0:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 59
+test clock-29.88 {time parsing} {
+ clock scan {2440588 0:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 59
+test clock-29.89 {time parsing} {
+ clock scan {2440588 ?:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 59
+test clock-29.90 {time parsing} {
+ clock scan {2440588 ?:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 59
+test clock-29.91 {time parsing} {
+ clock scan {2440588 ?:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 59
+test clock-29.92 {time parsing} {
+ clock scan {2440588 ?:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 59
+test clock-29.93 {time parsing} {
+ clock scan {2440588 12:00:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 59
+test clock-29.94 {time parsing} {
+ clock scan {2440588 12:?:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 59
+test clock-29.95 {time parsing} {
+ clock scan {2440588 12:00:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 59
+test clock-29.96 {time parsing} {
+ clock scan {2440588 12:?:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 59
+test clock-29.97 {time parsing} {
+ clock scan {2440588 xii:00:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 59
+test clock-29.98 {time parsing} {
+ clock scan {2440588 xii:?:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 59
+test clock-29.99 {time parsing} {
+ clock scan {2440588 xii:00:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 59
+test clock-29.100 {time parsing} {
+ clock scan {2440588 xii:?:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 59
+test clock-29.101 {time parsing} {
+ clock scan {2440588 12:00:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 59
+test clock-29.102 {time parsing} {
+ clock scan {2440588 12:?:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 59
+test clock-29.103 {time parsing} {
+ clock scan {2440588 12:00:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 59
+test clock-29.104 {time parsing} {
+ clock scan {2440588 12:?:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 59
+test clock-29.105 {time parsing} {
+ clock scan {2440588 xii:00:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 59
+test clock-29.106 {time parsing} {
+ clock scan {2440588 xii:?:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 59
+test clock-29.107 {time parsing} {
+ clock scan {2440588 xii:00:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 59
+test clock-29.108 {time parsing} {
+ clock scan {2440588 xii:?:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 59
+test clock-29.109 {time parsing} {
+ clock scan {2440588 00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M }
+} 60
+test clock-29.110 {time parsing} {
+ clock scan {2440588 00:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM }
+} 60
+test clock-29.111 {time parsing} {
+ clock scan {2440588 00:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 60
+test clock-29.112 {time parsing} {
+ clock scan {2440588 00:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 60
+test clock-29.113 {time parsing} {
+ clock scan {2440588 0:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M }
+} 60
+test clock-29.114 {time parsing} {
+ clock scan {2440588 0:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM }
+} 60
+test clock-29.115 {time parsing} {
+ clock scan {2440588 0:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 60
+test clock-29.116 {time parsing} {
+ clock scan {2440588 0:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 60
+test clock-29.117 {time parsing} {
+ clock scan {2440588 ?:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M }
+} 60
+test clock-29.118 {time parsing} {
+ clock scan {2440588 ?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM }
+} 60
+test clock-29.119 {time parsing} {
+ clock scan {2440588 ?:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 60
+test clock-29.120 {time parsing} {
+ clock scan {2440588 ?:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 60
+test clock-29.121 {time parsing} {
+ clock scan {2440588 ?:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M }
+} 60
+test clock-29.122 {time parsing} {
+ clock scan {2440588 ?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM }
+} 60
+test clock-29.123 {time parsing} {
+ clock scan {2440588 ?:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 60
+test clock-29.124 {time parsing} {
+ clock scan {2440588 ?:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 60
+test clock-29.125 {time parsing} {
+ clock scan {2440588 12:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %p}
+} 60
+test clock-29.126 {time parsing} {
+ clock scan {2440588 12:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %p}
+} 60
+test clock-29.127 {time parsing} {
+ clock scan {2440588 12:01:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 60
+test clock-29.128 {time parsing} {
+ clock scan {2440588 12:i:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 60
+test clock-29.129 {time parsing} {
+ clock scan {2440588 12:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %p}
+} 60
+test clock-29.130 {time parsing} {
+ clock scan {2440588 12:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %p}
+} 60
+test clock-29.131 {time parsing} {
+ clock scan {2440588 12:01:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 60
+test clock-29.132 {time parsing} {
+ clock scan {2440588 12:i:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 60
+test clock-29.133 {time parsing} {
+ clock scan {2440588 xii:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %p}
+} 60
+test clock-29.134 {time parsing} {
+ clock scan {2440588 xii:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %p}
+} 60
+test clock-29.135 {time parsing} {
+ clock scan {2440588 xii:01:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 60
+test clock-29.136 {time parsing} {
+ clock scan {2440588 xii:i:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 60
+test clock-29.137 {time parsing} {
+ clock scan {2440588 xii:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %p}
+} 60
+test clock-29.138 {time parsing} {
+ clock scan {2440588 xii:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %p}
+} 60
+test clock-29.139 {time parsing} {
+ clock scan {2440588 xii:01:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 60
+test clock-29.140 {time parsing} {
+ clock scan {2440588 xii:i:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 60
+test clock-29.141 {time parsing} {
+ clock scan {2440588 12:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %P}
+} 60
+test clock-29.142 {time parsing} {
+ clock scan {2440588 12:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %P}
+} 60
+test clock-29.143 {time parsing} {
+ clock scan {2440588 12:01:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 60
+test clock-29.144 {time parsing} {
+ clock scan {2440588 12:i:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 60
+test clock-29.145 {time parsing} {
+ clock scan {2440588 12:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %P}
+} 60
+test clock-29.146 {time parsing} {
+ clock scan {2440588 12:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %P}
+} 60
+test clock-29.147 {time parsing} {
+ clock scan {2440588 12:01:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 60
+test clock-29.148 {time parsing} {
+ clock scan {2440588 12:i:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 60
+test clock-29.149 {time parsing} {
+ clock scan {2440588 xii:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %P}
+} 60
+test clock-29.150 {time parsing} {
+ clock scan {2440588 xii:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %P}
+} 60
+test clock-29.151 {time parsing} {
+ clock scan {2440588 xii:01:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 60
+test clock-29.152 {time parsing} {
+ clock scan {2440588 xii:i:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 60
+test clock-29.153 {time parsing} {
+ clock scan {2440588 xii:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %P}
+} 60
+test clock-29.154 {time parsing} {
+ clock scan {2440588 xii:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %P}
+} 60
+test clock-29.155 {time parsing} {
+ clock scan {2440588 xii:01:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 60
+test clock-29.156 {time parsing} {
+ clock scan {2440588 xii:i:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 60
+test clock-29.157 {time parsing} {
+ clock scan {2440588 00:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 61
+test clock-29.158 {time parsing} {
+ clock scan {2440588 00:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 61
+test clock-29.159 {time parsing} {
+ clock scan {2440588 0:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 61
+test clock-29.160 {time parsing} {
+ clock scan {2440588 0:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 61
+test clock-29.161 {time parsing} {
+ clock scan {2440588 ?:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 61
+test clock-29.162 {time parsing} {
+ clock scan {2440588 ?:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 61
+test clock-29.163 {time parsing} {
+ clock scan {2440588 ?:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 61
+test clock-29.164 {time parsing} {
+ clock scan {2440588 ?:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 61
+test clock-29.165 {time parsing} {
+ clock scan {2440588 12:01:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 61
+test clock-29.166 {time parsing} {
+ clock scan {2440588 12:i:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 61
+test clock-29.167 {time parsing} {
+ clock scan {2440588 12:01:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 61
+test clock-29.168 {time parsing} {
+ clock scan {2440588 12:i:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 61
+test clock-29.169 {time parsing} {
+ clock scan {2440588 xii:01:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 61
+test clock-29.170 {time parsing} {
+ clock scan {2440588 xii:i:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 61
+test clock-29.171 {time parsing} {
+ clock scan {2440588 xii:01:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 61
+test clock-29.172 {time parsing} {
+ clock scan {2440588 xii:i:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 61
+test clock-29.173 {time parsing} {
+ clock scan {2440588 12:01:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 61
+test clock-29.174 {time parsing} {
+ clock scan {2440588 12:i:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 61
+test clock-29.175 {time parsing} {
+ clock scan {2440588 12:01:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 61
+test clock-29.176 {time parsing} {
+ clock scan {2440588 12:i:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 61
+test clock-29.177 {time parsing} {
+ clock scan {2440588 xii:01:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 61
+test clock-29.178 {time parsing} {
+ clock scan {2440588 xii:i:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 61
+test clock-29.179 {time parsing} {
+ clock scan {2440588 xii:01:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 61
+test clock-29.180 {time parsing} {
+ clock scan {2440588 xii:i:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 61
+test clock-29.181 {time parsing} {
+ clock scan {2440588 00:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 119
+test clock-29.182 {time parsing} {
+ clock scan {2440588 00:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 119
+test clock-29.183 {time parsing} {
+ clock scan {2440588 0:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 119
+test clock-29.184 {time parsing} {
+ clock scan {2440588 0:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 119
+test clock-29.185 {time parsing} {
+ clock scan {2440588 ?:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 119
+test clock-29.186 {time parsing} {
+ clock scan {2440588 ?:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 119
+test clock-29.187 {time parsing} {
+ clock scan {2440588 ?:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 119
+test clock-29.188 {time parsing} {
+ clock scan {2440588 ?:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 119
+test clock-29.189 {time parsing} {
+ clock scan {2440588 12:01:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 119
+test clock-29.190 {time parsing} {
+ clock scan {2440588 12:i:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 119
+test clock-29.191 {time parsing} {
+ clock scan {2440588 12:01:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 119
+test clock-29.192 {time parsing} {
+ clock scan {2440588 12:i:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 119
+test clock-29.193 {time parsing} {
+ clock scan {2440588 xii:01:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 119
+test clock-29.194 {time parsing} {
+ clock scan {2440588 xii:i:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 119
+test clock-29.195 {time parsing} {
+ clock scan {2440588 xii:01:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 119
+test clock-29.196 {time parsing} {
+ clock scan {2440588 xii:i:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 119
+test clock-29.197 {time parsing} {
+ clock scan {2440588 12:01:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 119
+test clock-29.198 {time parsing} {
+ clock scan {2440588 12:i:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 119
+test clock-29.199 {time parsing} {
+ clock scan {2440588 12:01:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 119
+test clock-29.200 {time parsing} {
+ clock scan {2440588 12:i:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 119
+test clock-29.201 {time parsing} {
+ clock scan {2440588 xii:01:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 119
+test clock-29.202 {time parsing} {
+ clock scan {2440588 xii:i:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 119
+test clock-29.203 {time parsing} {
+ clock scan {2440588 xii:01:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 119
+test clock-29.204 {time parsing} {
+ clock scan {2440588 xii:i:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 119
+test clock-29.205 {time parsing} {
+ clock scan {2440588 00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M }
+} 3540
+test clock-29.206 {time parsing} {
+ clock scan {2440588 00:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM }
+} 3540
+test clock-29.207 {time parsing} {
+ clock scan {2440588 00:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 3540
+test clock-29.208 {time parsing} {
+ clock scan {2440588 00:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 3540
+test clock-29.209 {time parsing} {
+ clock scan {2440588 0:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M }
+} 3540
+test clock-29.210 {time parsing} {
+ clock scan {2440588 0:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM }
+} 3540
+test clock-29.211 {time parsing} {
+ clock scan {2440588 0:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 3540
+test clock-29.212 {time parsing} {
+ clock scan {2440588 0:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 3540
+test clock-29.213 {time parsing} {
+ clock scan {2440588 ?:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M }
+} 3540
+test clock-29.214 {time parsing} {
+ clock scan {2440588 ?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM }
+} 3540
+test clock-29.215 {time parsing} {
+ clock scan {2440588 ?:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 3540
+test clock-29.216 {time parsing} {
+ clock scan {2440588 ?:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 3540
+test clock-29.217 {time parsing} {
+ clock scan {2440588 ?:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M }
+} 3540
+test clock-29.218 {time parsing} {
+ clock scan {2440588 ?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM }
+} 3540
+test clock-29.219 {time parsing} {
+ clock scan {2440588 ?:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 3540
+test clock-29.220 {time parsing} {
+ clock scan {2440588 ?:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 3540
+test clock-29.221 {time parsing} {
+ clock scan {2440588 12:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %p}
+} 3540
+test clock-29.222 {time parsing} {
+ clock scan {2440588 12:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %p}
+} 3540
+test clock-29.223 {time parsing} {
+ clock scan {2440588 12:59:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 3540
+test clock-29.224 {time parsing} {
+ clock scan {2440588 12:lix:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 3540
+test clock-29.225 {time parsing} {
+ clock scan {2440588 12:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %p}
+} 3540
+test clock-29.226 {time parsing} {
+ clock scan {2440588 12:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %p}
+} 3540
+test clock-29.227 {time parsing} {
+ clock scan {2440588 12:59:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 3540
+test clock-29.228 {time parsing} {
+ clock scan {2440588 12:lix:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 3540
+test clock-29.229 {time parsing} {
+ clock scan {2440588 xii:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %p}
+} 3540
+test clock-29.230 {time parsing} {
+ clock scan {2440588 xii:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %p}
+} 3540
+test clock-29.231 {time parsing} {
+ clock scan {2440588 xii:59:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 3540
+test clock-29.232 {time parsing} {
+ clock scan {2440588 xii:lix:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 3540
+test clock-29.233 {time parsing} {
+ clock scan {2440588 xii:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %p}
+} 3540
+test clock-29.234 {time parsing} {
+ clock scan {2440588 xii:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %p}
+} 3540
+test clock-29.235 {time parsing} {
+ clock scan {2440588 xii:59:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 3540
+test clock-29.236 {time parsing} {
+ clock scan {2440588 xii:lix:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 3540
+test clock-29.237 {time parsing} {
+ clock scan {2440588 12:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %P}
+} 3540
+test clock-29.238 {time parsing} {
+ clock scan {2440588 12:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %P}
+} 3540
+test clock-29.239 {time parsing} {
+ clock scan {2440588 12:59:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 3540
+test clock-29.240 {time parsing} {
+ clock scan {2440588 12:lix:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 3540
+test clock-29.241 {time parsing} {
+ clock scan {2440588 12:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %P}
+} 3540
+test clock-29.242 {time parsing} {
+ clock scan {2440588 12:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %P}
+} 3540
+test clock-29.243 {time parsing} {
+ clock scan {2440588 12:59:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 3540
+test clock-29.244 {time parsing} {
+ clock scan {2440588 12:lix:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 3540
+test clock-29.245 {time parsing} {
+ clock scan {2440588 xii:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %P}
+} 3540
+test clock-29.246 {time parsing} {
+ clock scan {2440588 xii:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %P}
+} 3540
+test clock-29.247 {time parsing} {
+ clock scan {2440588 xii:59:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 3540
+test clock-29.248 {time parsing} {
+ clock scan {2440588 xii:lix:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 3540
+test clock-29.249 {time parsing} {
+ clock scan {2440588 xii:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %P}
+} 3540
+test clock-29.250 {time parsing} {
+ clock scan {2440588 xii:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %P}
+} 3540
+test clock-29.251 {time parsing} {
+ clock scan {2440588 xii:59:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 3540
+test clock-29.252 {time parsing} {
+ clock scan {2440588 xii:lix:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 3540
+test clock-29.253 {time parsing} {
+ clock scan {2440588 00:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 3541
+test clock-29.254 {time parsing} {
+ clock scan {2440588 00:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 3541
+test clock-29.255 {time parsing} {
+ clock scan {2440588 0:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 3541
+test clock-29.256 {time parsing} {
+ clock scan {2440588 0:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 3541
+test clock-29.257 {time parsing} {
+ clock scan {2440588 ?:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 3541
+test clock-29.258 {time parsing} {
+ clock scan {2440588 ?:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 3541
+test clock-29.259 {time parsing} {
+ clock scan {2440588 ?:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 3541
+test clock-29.260 {time parsing} {
+ clock scan {2440588 ?:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 3541
+test clock-29.261 {time parsing} {
+ clock scan {2440588 12:59:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 3541
+test clock-29.262 {time parsing} {
+ clock scan {2440588 12:lix:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 3541
+test clock-29.263 {time parsing} {
+ clock scan {2440588 12:59:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 3541
+test clock-29.264 {time parsing} {
+ clock scan {2440588 12:lix:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 3541
+test clock-29.265 {time parsing} {
+ clock scan {2440588 xii:59:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 3541
+test clock-29.266 {time parsing} {
+ clock scan {2440588 xii:lix:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 3541
+test clock-29.267 {time parsing} {
+ clock scan {2440588 xii:59:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 3541
+test clock-29.268 {time parsing} {
+ clock scan {2440588 xii:lix:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 3541
+test clock-29.269 {time parsing} {
+ clock scan {2440588 12:59:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 3541
+test clock-29.270 {time parsing} {
+ clock scan {2440588 12:lix:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 3541
+test clock-29.271 {time parsing} {
+ clock scan {2440588 12:59:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 3541
+test clock-29.272 {time parsing} {
+ clock scan {2440588 12:lix:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 3541
+test clock-29.273 {time parsing} {
+ clock scan {2440588 xii:59:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 3541
+test clock-29.274 {time parsing} {
+ clock scan {2440588 xii:lix:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 3541
+test clock-29.275 {time parsing} {
+ clock scan {2440588 xii:59:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 3541
+test clock-29.276 {time parsing} {
+ clock scan {2440588 xii:lix:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 3541
+test clock-29.277 {time parsing} {
+ clock scan {2440588 00:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 3599
+test clock-29.278 {time parsing} {
+ clock scan {2440588 00:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 3599
+test clock-29.279 {time parsing} {
+ clock scan {2440588 0:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 3599
+test clock-29.280 {time parsing} {
+ clock scan {2440588 0:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 3599
+test clock-29.281 {time parsing} {
+ clock scan {2440588 ?:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 3599
+test clock-29.282 {time parsing} {
+ clock scan {2440588 ?:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 3599
+test clock-29.283 {time parsing} {
+ clock scan {2440588 ?:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 3599
+test clock-29.284 {time parsing} {
+ clock scan {2440588 ?:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 3599
+test clock-29.285 {time parsing} {
+ clock scan {2440588 12:59:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 3599
+test clock-29.286 {time parsing} {
+ clock scan {2440588 12:lix:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 3599
+test clock-29.287 {time parsing} {
+ clock scan {2440588 12:59:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 3599
+test clock-29.288 {time parsing} {
+ clock scan {2440588 12:lix:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 3599
+test clock-29.289 {time parsing} {
+ clock scan {2440588 xii:59:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 3599
+test clock-29.290 {time parsing} {
+ clock scan {2440588 xii:lix:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 3599
+test clock-29.291 {time parsing} {
+ clock scan {2440588 xii:59:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 3599
+test clock-29.292 {time parsing} {
+ clock scan {2440588 xii:lix:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 3599
+test clock-29.293 {time parsing} {
+ clock scan {2440588 12:59:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 3599
+test clock-29.294 {time parsing} {
+ clock scan {2440588 12:lix:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 3599
+test clock-29.295 {time parsing} {
+ clock scan {2440588 12:59:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 3599
+test clock-29.296 {time parsing} {
+ clock scan {2440588 12:lix:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 3599
+test clock-29.297 {time parsing} {
+ clock scan {2440588 xii:59:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 3599
+test clock-29.298 {time parsing} {
+ clock scan {2440588 xii:lix:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 3599
+test clock-29.299 {time parsing} {
+ clock scan {2440588 xii:59:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 3599
+test clock-29.300 {time parsing} {
+ clock scan {2440588 xii:lix:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 3599
+test clock-29.301 {time parsing} {
+ clock scan {2440588 01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H }
+} 3600
+test clock-29.302 {time parsing} {
+ clock scan {2440588 01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M }
+} 3600
+test clock-29.303 {time parsing} {
+ clock scan {2440588 01:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM }
+} 3600
+test clock-29.304 {time parsing} {
+ clock scan {2440588 01:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 3600
+test clock-29.305 {time parsing} {
+ clock scan {2440588 01:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 3600
+test clock-29.306 {time parsing} {
+ clock scan {2440588 1 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k }
+} 3600
+test clock-29.307 {time parsing} {
+ clock scan {2440588 1:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M }
+} 3600
+test clock-29.308 {time parsing} {
+ clock scan {2440588 1:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM }
+} 3600
+test clock-29.309 {time parsing} {
+ clock scan {2440588 1:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 3600
+test clock-29.310 {time parsing} {
+ clock scan {2440588 1:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 3600
+test clock-29.311 {time parsing} {
+ clock scan {2440588 i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH }
+} 3600
+test clock-29.312 {time parsing} {
+ clock scan {2440588 i:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M }
+} 3600
+test clock-29.313 {time parsing} {
+ clock scan {2440588 i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM }
+} 3600
+test clock-29.314 {time parsing} {
+ clock scan {2440588 i:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 3600
+test clock-29.315 {time parsing} {
+ clock scan {2440588 i:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 3600
+test clock-29.316 {time parsing} {
+ clock scan {2440588 i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok }
+} 3600
+test clock-29.317 {time parsing} {
+ clock scan {2440588 i:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M }
+} 3600
+test clock-29.318 {time parsing} {
+ clock scan {2440588 i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM }
+} 3600
+test clock-29.319 {time parsing} {
+ clock scan {2440588 i:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 3600
+test clock-29.320 {time parsing} {
+ clock scan {2440588 i:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 3600
+test clock-29.321 {time parsing} {
+ clock scan {2440588 01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I %p}
+} 3600
+test clock-29.322 {time parsing} {
+ clock scan {2440588 01:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %p}
+} 3600
+test clock-29.323 {time parsing} {
+ clock scan {2440588 01:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %p}
+} 3600
+test clock-29.324 {time parsing} {
+ clock scan {2440588 01:00:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 3600
+test clock-29.325 {time parsing} {
+ clock scan {2440588 01:?:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 3600
+test clock-29.326 {time parsing} {
+ clock scan {2440588 1 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l %p}
+} 3600
+test clock-29.327 {time parsing} {
+ clock scan {2440588 1:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %p}
+} 3600
+test clock-29.328 {time parsing} {
+ clock scan {2440588 1:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %p}
+} 3600
+test clock-29.329 {time parsing} {
+ clock scan {2440588 1:00:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 3600
+test clock-29.330 {time parsing} {
+ clock scan {2440588 1:?:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 3600
+test clock-29.331 {time parsing} {
+ clock scan {2440588 i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI %p}
+} 3600
+test clock-29.332 {time parsing} {
+ clock scan {2440588 i:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %p}
+} 3600
+test clock-29.333 {time parsing} {
+ clock scan {2440588 i:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %p}
+} 3600
+test clock-29.334 {time parsing} {
+ clock scan {2440588 i:00:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 3600
+test clock-29.335 {time parsing} {
+ clock scan {2440588 i:?:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 3600
+test clock-29.336 {time parsing} {
+ clock scan {2440588 i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol %p}
+} 3600
+test clock-29.337 {time parsing} {
+ clock scan {2440588 i:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %p}
+} 3600
+test clock-29.338 {time parsing} {
+ clock scan {2440588 i:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %p}
+} 3600
+test clock-29.339 {time parsing} {
+ clock scan {2440588 i:00:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 3600
+test clock-29.340 {time parsing} {
+ clock scan {2440588 i:?:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 3600
+test clock-29.341 {time parsing} {
+ clock scan {2440588 01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I %P}
+} 3600
+test clock-29.342 {time parsing} {
+ clock scan {2440588 01:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %P}
+} 3600
+test clock-29.343 {time parsing} {
+ clock scan {2440588 01:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %P}
+} 3600
+test clock-29.344 {time parsing} {
+ clock scan {2440588 01:00:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 3600
+test clock-29.345 {time parsing} {
+ clock scan {2440588 01:?:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 3600
+test clock-29.346 {time parsing} {
+ clock scan {2440588 1 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l %P}
+} 3600
+test clock-29.347 {time parsing} {
+ clock scan {2440588 1:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %P}
+} 3600
+test clock-29.348 {time parsing} {
+ clock scan {2440588 1:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %P}
+} 3600
+test clock-29.349 {time parsing} {
+ clock scan {2440588 1:00:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 3600
+test clock-29.350 {time parsing} {
+ clock scan {2440588 1:?:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 3600
+test clock-29.351 {time parsing} {
+ clock scan {2440588 i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI %P}
+} 3600
+test clock-29.352 {time parsing} {
+ clock scan {2440588 i:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %P}
+} 3600
+test clock-29.353 {time parsing} {
+ clock scan {2440588 i:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %P}
+} 3600
+test clock-29.354 {time parsing} {
+ clock scan {2440588 i:00:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 3600
+test clock-29.355 {time parsing} {
+ clock scan {2440588 i:?:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 3600
+test clock-29.356 {time parsing} {
+ clock scan {2440588 i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol %P}
+} 3600
+test clock-29.357 {time parsing} {
+ clock scan {2440588 i:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %P}
+} 3600
+test clock-29.358 {time parsing} {
+ clock scan {2440588 i:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %P}
+} 3600
+test clock-29.359 {time parsing} {
+ clock scan {2440588 i:00:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 3600
+test clock-29.360 {time parsing} {
+ clock scan {2440588 i:?:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 3600
+test clock-29.361 {time parsing} {
+ clock scan {2440588 01:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 3601
+test clock-29.362 {time parsing} {
+ clock scan {2440588 01:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 3601
+test clock-29.363 {time parsing} {
+ clock scan {2440588 1:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 3601
+test clock-29.364 {time parsing} {
+ clock scan {2440588 1:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 3601
+test clock-29.365 {time parsing} {
+ clock scan {2440588 i:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 3601
+test clock-29.366 {time parsing} {
+ clock scan {2440588 i:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 3601
+test clock-29.367 {time parsing} {
+ clock scan {2440588 i:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 3601
+test clock-29.368 {time parsing} {
+ clock scan {2440588 i:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 3601
+test clock-29.369 {time parsing} {
+ clock scan {2440588 01:00:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 3601
+test clock-29.370 {time parsing} {
+ clock scan {2440588 01:?:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 3601
+test clock-29.371 {time parsing} {
+ clock scan {2440588 1:00:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 3601
+test clock-29.372 {time parsing} {
+ clock scan {2440588 1:?:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 3601
+test clock-29.373 {time parsing} {
+ clock scan {2440588 i:00:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 3601
+test clock-29.374 {time parsing} {
+ clock scan {2440588 i:?:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 3601
+test clock-29.375 {time parsing} {
+ clock scan {2440588 i:00:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 3601
+test clock-29.376 {time parsing} {
+ clock scan {2440588 i:?:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 3601
+test clock-29.377 {time parsing} {
+ clock scan {2440588 01:00:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 3601
+test clock-29.378 {time parsing} {
+ clock scan {2440588 01:?:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 3601
+test clock-29.379 {time parsing} {
+ clock scan {2440588 1:00:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 3601
+test clock-29.380 {time parsing} {
+ clock scan {2440588 1:?:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 3601
+test clock-29.381 {time parsing} {
+ clock scan {2440588 i:00:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 3601
+test clock-29.382 {time parsing} {
+ clock scan {2440588 i:?:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 3601
+test clock-29.383 {time parsing} {
+ clock scan {2440588 i:00:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 3601
+test clock-29.384 {time parsing} {
+ clock scan {2440588 i:?:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 3601
+test clock-29.385 {time parsing} {
+ clock scan {2440588 01:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 3659
+test clock-29.386 {time parsing} {
+ clock scan {2440588 01:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 3659
+test clock-29.387 {time parsing} {
+ clock scan {2440588 1:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 3659
+test clock-29.388 {time parsing} {
+ clock scan {2440588 1:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 3659
+test clock-29.389 {time parsing} {
+ clock scan {2440588 i:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 3659
+test clock-29.390 {time parsing} {
+ clock scan {2440588 i:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 3659
+test clock-29.391 {time parsing} {
+ clock scan {2440588 i:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 3659
+test clock-29.392 {time parsing} {
+ clock scan {2440588 i:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 3659
+test clock-29.393 {time parsing} {
+ clock scan {2440588 01:00:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 3659
+test clock-29.394 {time parsing} {
+ clock scan {2440588 01:?:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 3659
+test clock-29.395 {time parsing} {
+ clock scan {2440588 1:00:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 3659
+test clock-29.396 {time parsing} {
+ clock scan {2440588 1:?:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 3659
+test clock-29.397 {time parsing} {
+ clock scan {2440588 i:00:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 3659
+test clock-29.398 {time parsing} {
+ clock scan {2440588 i:?:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 3659
+test clock-29.399 {time parsing} {
+ clock scan {2440588 i:00:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 3659
+test clock-29.400 {time parsing} {
+ clock scan {2440588 i:?:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 3659
+test clock-29.401 {time parsing} {
+ clock scan {2440588 01:00:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 3659
+test clock-29.402 {time parsing} {
+ clock scan {2440588 01:?:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 3659
+test clock-29.403 {time parsing} {
+ clock scan {2440588 1:00:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 3659
+test clock-29.404 {time parsing} {
+ clock scan {2440588 1:?:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 3659
+test clock-29.405 {time parsing} {
+ clock scan {2440588 i:00:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 3659
+test clock-29.406 {time parsing} {
+ clock scan {2440588 i:?:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 3659
+test clock-29.407 {time parsing} {
+ clock scan {2440588 i:00:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 3659
+test clock-29.408 {time parsing} {
+ clock scan {2440588 i:?:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 3659
+test clock-29.409 {time parsing} {
+ clock scan {2440588 01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M }
+} 3660
+test clock-29.410 {time parsing} {
+ clock scan {2440588 01:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM }
+} 3660
+test clock-29.411 {time parsing} {
+ clock scan {2440588 01:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 3660
+test clock-29.412 {time parsing} {
+ clock scan {2440588 01:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 3660
+test clock-29.413 {time parsing} {
+ clock scan {2440588 1:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M }
+} 3660
+test clock-29.414 {time parsing} {
+ clock scan {2440588 1:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM }
+} 3660
+test clock-29.415 {time parsing} {
+ clock scan {2440588 1:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 3660
+test clock-29.416 {time parsing} {
+ clock scan {2440588 1:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 3660
+test clock-29.417 {time parsing} {
+ clock scan {2440588 i:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M }
+} 3660
+test clock-29.418 {time parsing} {
+ clock scan {2440588 i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM }
+} 3660
+test clock-29.419 {time parsing} {
+ clock scan {2440588 i:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 3660
+test clock-29.420 {time parsing} {
+ clock scan {2440588 i:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 3660
+test clock-29.421 {time parsing} {
+ clock scan {2440588 i:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M }
+} 3660
+test clock-29.422 {time parsing} {
+ clock scan {2440588 i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM }
+} 3660
+test clock-29.423 {time parsing} {
+ clock scan {2440588 i:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 3660
+test clock-29.424 {time parsing} {
+ clock scan {2440588 i:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 3660
+test clock-29.425 {time parsing} {
+ clock scan {2440588 01:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %p}
+} 3660
+test clock-29.426 {time parsing} {
+ clock scan {2440588 01:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %p}
+} 3660
+test clock-29.427 {time parsing} {
+ clock scan {2440588 01:01:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 3660
+test clock-29.428 {time parsing} {
+ clock scan {2440588 01:i:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 3660
+test clock-29.429 {time parsing} {
+ clock scan {2440588 1:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %p}
+} 3660
+test clock-29.430 {time parsing} {
+ clock scan {2440588 1:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %p}
+} 3660
+test clock-29.431 {time parsing} {
+ clock scan {2440588 1:01:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 3660
+test clock-29.432 {time parsing} {
+ clock scan {2440588 1:i:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 3660
+test clock-29.433 {time parsing} {
+ clock scan {2440588 i:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %p}
+} 3660
+test clock-29.434 {time parsing} {
+ clock scan {2440588 i:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %p}
+} 3660
+test clock-29.435 {time parsing} {
+ clock scan {2440588 i:01:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 3660
+test clock-29.436 {time parsing} {
+ clock scan {2440588 i:i:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 3660
+test clock-29.437 {time parsing} {
+ clock scan {2440588 i:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %p}
+} 3660
+test clock-29.438 {time parsing} {
+ clock scan {2440588 i:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %p}
+} 3660
+test clock-29.439 {time parsing} {
+ clock scan {2440588 i:01:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 3660
+test clock-29.440 {time parsing} {
+ clock scan {2440588 i:i:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 3660
+test clock-29.441 {time parsing} {
+ clock scan {2440588 01:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %P}
+} 3660
+test clock-29.442 {time parsing} {
+ clock scan {2440588 01:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %P}
+} 3660
+test clock-29.443 {time parsing} {
+ clock scan {2440588 01:01:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 3660
+test clock-29.444 {time parsing} {
+ clock scan {2440588 01:i:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 3660
+test clock-29.445 {time parsing} {
+ clock scan {2440588 1:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %P}
+} 3660
+test clock-29.446 {time parsing} {
+ clock scan {2440588 1:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %P}
+} 3660
+test clock-29.447 {time parsing} {
+ clock scan {2440588 1:01:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 3660
+test clock-29.448 {time parsing} {
+ clock scan {2440588 1:i:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 3660
+test clock-29.449 {time parsing} {
+ clock scan {2440588 i:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %P}
+} 3660
+test clock-29.450 {time parsing} {
+ clock scan {2440588 i:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %P}
+} 3660
+test clock-29.451 {time parsing} {
+ clock scan {2440588 i:01:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 3660
+test clock-29.452 {time parsing} {
+ clock scan {2440588 i:i:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 3660
+test clock-29.453 {time parsing} {
+ clock scan {2440588 i:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %P}
+} 3660
+test clock-29.454 {time parsing} {
+ clock scan {2440588 i:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %P}
+} 3660
+test clock-29.455 {time parsing} {
+ clock scan {2440588 i:01:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 3660
+test clock-29.456 {time parsing} {
+ clock scan {2440588 i:i:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 3660
+test clock-29.457 {time parsing} {
+ clock scan {2440588 01:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 3661
+test clock-29.458 {time parsing} {
+ clock scan {2440588 01:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 3661
+test clock-29.459 {time parsing} {
+ clock scan {2440588 1:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 3661
+test clock-29.460 {time parsing} {
+ clock scan {2440588 1:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 3661
+test clock-29.461 {time parsing} {
+ clock scan {2440588 i:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 3661
+test clock-29.462 {time parsing} {
+ clock scan {2440588 i:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 3661
+test clock-29.463 {time parsing} {
+ clock scan {2440588 i:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 3661
+test clock-29.464 {time parsing} {
+ clock scan {2440588 i:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 3661
+test clock-29.465 {time parsing} {
+ clock scan {2440588 01:01:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 3661
+test clock-29.466 {time parsing} {
+ clock scan {2440588 01:i:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 3661
+test clock-29.467 {time parsing} {
+ clock scan {2440588 1:01:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 3661
+test clock-29.468 {time parsing} {
+ clock scan {2440588 1:i:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 3661
+test clock-29.469 {time parsing} {
+ clock scan {2440588 i:01:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 3661
+test clock-29.470 {time parsing} {
+ clock scan {2440588 i:i:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 3661
+test clock-29.471 {time parsing} {
+ clock scan {2440588 i:01:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 3661
+test clock-29.472 {time parsing} {
+ clock scan {2440588 i:i:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 3661
+test clock-29.473 {time parsing} {
+ clock scan {2440588 01:01:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 3661
+test clock-29.474 {time parsing} {
+ clock scan {2440588 01:i:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 3661
+test clock-29.475 {time parsing} {
+ clock scan {2440588 1:01:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 3661
+test clock-29.476 {time parsing} {
+ clock scan {2440588 1:i:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 3661
+test clock-29.477 {time parsing} {
+ clock scan {2440588 i:01:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 3661
+test clock-29.478 {time parsing} {
+ clock scan {2440588 i:i:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 3661
+test clock-29.479 {time parsing} {
+ clock scan {2440588 i:01:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 3661
+test clock-29.480 {time parsing} {
+ clock scan {2440588 i:i:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 3661
+test clock-29.481 {time parsing} {
+ clock scan {2440588 01:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 3719
+test clock-29.482 {time parsing} {
+ clock scan {2440588 01:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 3719
+test clock-29.483 {time parsing} {
+ clock scan {2440588 1:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 3719
+test clock-29.484 {time parsing} {
+ clock scan {2440588 1:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 3719
+test clock-29.485 {time parsing} {
+ clock scan {2440588 i:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 3719
+test clock-29.486 {time parsing} {
+ clock scan {2440588 i:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 3719
+test clock-29.487 {time parsing} {
+ clock scan {2440588 i:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 3719
+test clock-29.488 {time parsing} {
+ clock scan {2440588 i:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 3719
+test clock-29.489 {time parsing} {
+ clock scan {2440588 01:01:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 3719
+test clock-29.490 {time parsing} {
+ clock scan {2440588 01:i:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 3719
+test clock-29.491 {time parsing} {
+ clock scan {2440588 1:01:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 3719
+test clock-29.492 {time parsing} {
+ clock scan {2440588 1:i:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 3719
+test clock-29.493 {time parsing} {
+ clock scan {2440588 i:01:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 3719
+test clock-29.494 {time parsing} {
+ clock scan {2440588 i:i:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 3719
+test clock-29.495 {time parsing} {
+ clock scan {2440588 i:01:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 3719
+test clock-29.496 {time parsing} {
+ clock scan {2440588 i:i:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 3719
+test clock-29.497 {time parsing} {
+ clock scan {2440588 01:01:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 3719
+test clock-29.498 {time parsing} {
+ clock scan {2440588 01:i:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 3719
+test clock-29.499 {time parsing} {
+ clock scan {2440588 1:01:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 3719
+test clock-29.500 {time parsing} {
+ clock scan {2440588 1:i:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 3719
+test clock-29.501 {time parsing} {
+ clock scan {2440588 i:01:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 3719
+test clock-29.502 {time parsing} {
+ clock scan {2440588 i:i:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 3719
+test clock-29.503 {time parsing} {
+ clock scan {2440588 i:01:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 3719
+test clock-29.504 {time parsing} {
+ clock scan {2440588 i:i:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 3719
+test clock-29.505 {time parsing} {
+ clock scan {2440588 01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M }
+} 7140
+test clock-29.506 {time parsing} {
+ clock scan {2440588 01:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM }
+} 7140
+test clock-29.507 {time parsing} {
+ clock scan {2440588 01:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 7140
+test clock-29.508 {time parsing} {
+ clock scan {2440588 01:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 7140
+test clock-29.509 {time parsing} {
+ clock scan {2440588 1:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M }
+} 7140
+test clock-29.510 {time parsing} {
+ clock scan {2440588 1:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM }
+} 7140
+test clock-29.511 {time parsing} {
+ clock scan {2440588 1:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 7140
+test clock-29.512 {time parsing} {
+ clock scan {2440588 1:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 7140
+test clock-29.513 {time parsing} {
+ clock scan {2440588 i:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M }
+} 7140
+test clock-29.514 {time parsing} {
+ clock scan {2440588 i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM }
+} 7140
+test clock-29.515 {time parsing} {
+ clock scan {2440588 i:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 7140
+test clock-29.516 {time parsing} {
+ clock scan {2440588 i:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 7140
+test clock-29.517 {time parsing} {
+ clock scan {2440588 i:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M }
+} 7140
+test clock-29.518 {time parsing} {
+ clock scan {2440588 i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM }
+} 7140
+test clock-29.519 {time parsing} {
+ clock scan {2440588 i:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 7140
+test clock-29.520 {time parsing} {
+ clock scan {2440588 i:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 7140
+test clock-29.521 {time parsing} {
+ clock scan {2440588 01:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %p}
+} 7140
+test clock-29.522 {time parsing} {
+ clock scan {2440588 01:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %p}
+} 7140
+test clock-29.523 {time parsing} {
+ clock scan {2440588 01:59:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 7140
+test clock-29.524 {time parsing} {
+ clock scan {2440588 01:lix:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 7140
+test clock-29.525 {time parsing} {
+ clock scan {2440588 1:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %p}
+} 7140
+test clock-29.526 {time parsing} {
+ clock scan {2440588 1:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %p}
+} 7140
+test clock-29.527 {time parsing} {
+ clock scan {2440588 1:59:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 7140
+test clock-29.528 {time parsing} {
+ clock scan {2440588 1:lix:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 7140
+test clock-29.529 {time parsing} {
+ clock scan {2440588 i:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %p}
+} 7140
+test clock-29.530 {time parsing} {
+ clock scan {2440588 i:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %p}
+} 7140
+test clock-29.531 {time parsing} {
+ clock scan {2440588 i:59:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 7140
+test clock-29.532 {time parsing} {
+ clock scan {2440588 i:lix:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 7140
+test clock-29.533 {time parsing} {
+ clock scan {2440588 i:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %p}
+} 7140
+test clock-29.534 {time parsing} {
+ clock scan {2440588 i:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %p}
+} 7140
+test clock-29.535 {time parsing} {
+ clock scan {2440588 i:59:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 7140
+test clock-29.536 {time parsing} {
+ clock scan {2440588 i:lix:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 7140
+test clock-29.537 {time parsing} {
+ clock scan {2440588 01:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %P}
+} 7140
+test clock-29.538 {time parsing} {
+ clock scan {2440588 01:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %P}
+} 7140
+test clock-29.539 {time parsing} {
+ clock scan {2440588 01:59:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 7140
+test clock-29.540 {time parsing} {
+ clock scan {2440588 01:lix:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 7140
+test clock-29.541 {time parsing} {
+ clock scan {2440588 1:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %P}
+} 7140
+test clock-29.542 {time parsing} {
+ clock scan {2440588 1:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %P}
+} 7140
+test clock-29.543 {time parsing} {
+ clock scan {2440588 1:59:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 7140
+test clock-29.544 {time parsing} {
+ clock scan {2440588 1:lix:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 7140
+test clock-29.545 {time parsing} {
+ clock scan {2440588 i:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %P}
+} 7140
+test clock-29.546 {time parsing} {
+ clock scan {2440588 i:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %P}
+} 7140
+test clock-29.547 {time parsing} {
+ clock scan {2440588 i:59:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 7140
+test clock-29.548 {time parsing} {
+ clock scan {2440588 i:lix:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 7140
+test clock-29.549 {time parsing} {
+ clock scan {2440588 i:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %P}
+} 7140
+test clock-29.550 {time parsing} {
+ clock scan {2440588 i:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %P}
+} 7140
+test clock-29.551 {time parsing} {
+ clock scan {2440588 i:59:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 7140
+test clock-29.552 {time parsing} {
+ clock scan {2440588 i:lix:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 7140
+test clock-29.553 {time parsing} {
+ clock scan {2440588 01:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 7141
+test clock-29.554 {time parsing} {
+ clock scan {2440588 01:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 7141
+test clock-29.555 {time parsing} {
+ clock scan {2440588 1:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 7141
+test clock-29.556 {time parsing} {
+ clock scan {2440588 1:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 7141
+test clock-29.557 {time parsing} {
+ clock scan {2440588 i:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 7141
+test clock-29.558 {time parsing} {
+ clock scan {2440588 i:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 7141
+test clock-29.559 {time parsing} {
+ clock scan {2440588 i:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 7141
+test clock-29.560 {time parsing} {
+ clock scan {2440588 i:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 7141
+test clock-29.561 {time parsing} {
+ clock scan {2440588 01:59:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 7141
+test clock-29.562 {time parsing} {
+ clock scan {2440588 01:lix:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 7141
+test clock-29.563 {time parsing} {
+ clock scan {2440588 1:59:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 7141
+test clock-29.564 {time parsing} {
+ clock scan {2440588 1:lix:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 7141
+test clock-29.565 {time parsing} {
+ clock scan {2440588 i:59:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 7141
+test clock-29.566 {time parsing} {
+ clock scan {2440588 i:lix:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 7141
+test clock-29.567 {time parsing} {
+ clock scan {2440588 i:59:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 7141
+test clock-29.568 {time parsing} {
+ clock scan {2440588 i:lix:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 7141
+test clock-29.569 {time parsing} {
+ clock scan {2440588 01:59:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 7141
+test clock-29.570 {time parsing} {
+ clock scan {2440588 01:lix:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 7141
+test clock-29.571 {time parsing} {
+ clock scan {2440588 1:59:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 7141
+test clock-29.572 {time parsing} {
+ clock scan {2440588 1:lix:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 7141
+test clock-29.573 {time parsing} {
+ clock scan {2440588 i:59:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 7141
+test clock-29.574 {time parsing} {
+ clock scan {2440588 i:lix:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 7141
+test clock-29.575 {time parsing} {
+ clock scan {2440588 i:59:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 7141
+test clock-29.576 {time parsing} {
+ clock scan {2440588 i:lix:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 7141
+test clock-29.577 {time parsing} {
+ clock scan {2440588 01:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 7199
+test clock-29.578 {time parsing} {
+ clock scan {2440588 01:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 7199
+test clock-29.579 {time parsing} {
+ clock scan {2440588 1:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 7199
+test clock-29.580 {time parsing} {
+ clock scan {2440588 1:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 7199
+test clock-29.581 {time parsing} {
+ clock scan {2440588 i:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 7199
+test clock-29.582 {time parsing} {
+ clock scan {2440588 i:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 7199
+test clock-29.583 {time parsing} {
+ clock scan {2440588 i:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 7199
+test clock-29.584 {time parsing} {
+ clock scan {2440588 i:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 7199
+test clock-29.585 {time parsing} {
+ clock scan {2440588 01:59:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 7199
+test clock-29.586 {time parsing} {
+ clock scan {2440588 01:lix:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 7199
+test clock-29.587 {time parsing} {
+ clock scan {2440588 1:59:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 7199
+test clock-29.588 {time parsing} {
+ clock scan {2440588 1:lix:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 7199
+test clock-29.589 {time parsing} {
+ clock scan {2440588 i:59:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 7199
+test clock-29.590 {time parsing} {
+ clock scan {2440588 i:lix:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 7199
+test clock-29.591 {time parsing} {
+ clock scan {2440588 i:59:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 7199
+test clock-29.592 {time parsing} {
+ clock scan {2440588 i:lix:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 7199
+test clock-29.593 {time parsing} {
+ clock scan {2440588 01:59:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 7199
+test clock-29.594 {time parsing} {
+ clock scan {2440588 01:lix:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 7199
+test clock-29.595 {time parsing} {
+ clock scan {2440588 1:59:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 7199
+test clock-29.596 {time parsing} {
+ clock scan {2440588 1:lix:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 7199
+test clock-29.597 {time parsing} {
+ clock scan {2440588 i:59:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 7199
+test clock-29.598 {time parsing} {
+ clock scan {2440588 i:lix:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 7199
+test clock-29.599 {time parsing} {
+ clock scan {2440588 i:59:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 7199
+test clock-29.600 {time parsing} {
+ clock scan {2440588 i:lix:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 7199
+test clock-29.601 {time parsing} {
+ clock scan {2440588 11 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H }
+} 39600
+test clock-29.602 {time parsing} {
+ clock scan {2440588 11:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M }
+} 39600
+test clock-29.603 {time parsing} {
+ clock scan {2440588 11:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM }
+} 39600
+test clock-29.604 {time parsing} {
+ clock scan {2440588 11:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 39600
+test clock-29.605 {time parsing} {
+ clock scan {2440588 11:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 39600
+test clock-29.606 {time parsing} {
+ clock scan {2440588 11 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k }
+} 39600
+test clock-29.607 {time parsing} {
+ clock scan {2440588 11:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M }
+} 39600
+test clock-29.608 {time parsing} {
+ clock scan {2440588 11:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM }
+} 39600
+test clock-29.609 {time parsing} {
+ clock scan {2440588 11:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 39600
+test clock-29.610 {time parsing} {
+ clock scan {2440588 11:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 39600
+test clock-29.611 {time parsing} {
+ clock scan {2440588 xi } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH }
+} 39600
+test clock-29.612 {time parsing} {
+ clock scan {2440588 xi:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M }
+} 39600
+test clock-29.613 {time parsing} {
+ clock scan {2440588 xi:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM }
+} 39600
+test clock-29.614 {time parsing} {
+ clock scan {2440588 xi:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 39600
+test clock-29.615 {time parsing} {
+ clock scan {2440588 xi:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 39600
+test clock-29.616 {time parsing} {
+ clock scan {2440588 xi } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok }
+} 39600
+test clock-29.617 {time parsing} {
+ clock scan {2440588 xi:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M }
+} 39600
+test clock-29.618 {time parsing} {
+ clock scan {2440588 xi:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM }
+} 39600
+test clock-29.619 {time parsing} {
+ clock scan {2440588 xi:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 39600
+test clock-29.620 {time parsing} {
+ clock scan {2440588 xi:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 39600
+test clock-29.621 {time parsing} {
+ clock scan {2440588 11 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I %p}
+} 39600
+test clock-29.622 {time parsing} {
+ clock scan {2440588 11:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %p}
+} 39600
+test clock-29.623 {time parsing} {
+ clock scan {2440588 11:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %p}
+} 39600
+test clock-29.624 {time parsing} {
+ clock scan {2440588 11:00:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 39600
+test clock-29.625 {time parsing} {
+ clock scan {2440588 11:?:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 39600
+test clock-29.626 {time parsing} {
+ clock scan {2440588 11 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l %p}
+} 39600
+test clock-29.627 {time parsing} {
+ clock scan {2440588 11:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %p}
+} 39600
+test clock-29.628 {time parsing} {
+ clock scan {2440588 11:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %p}
+} 39600
+test clock-29.629 {time parsing} {
+ clock scan {2440588 11:00:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 39600
+test clock-29.630 {time parsing} {
+ clock scan {2440588 11:?:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 39600
+test clock-29.631 {time parsing} {
+ clock scan {2440588 xi AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI %p}
+} 39600
+test clock-29.632 {time parsing} {
+ clock scan {2440588 xi:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %p}
+} 39600
+test clock-29.633 {time parsing} {
+ clock scan {2440588 xi:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %p}
+} 39600
+test clock-29.634 {time parsing} {
+ clock scan {2440588 xi:00:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 39600
+test clock-29.635 {time parsing} {
+ clock scan {2440588 xi:?:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 39600
+test clock-29.636 {time parsing} {
+ clock scan {2440588 xi AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol %p}
+} 39600
+test clock-29.637 {time parsing} {
+ clock scan {2440588 xi:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %p}
+} 39600
+test clock-29.638 {time parsing} {
+ clock scan {2440588 xi:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %p}
+} 39600
+test clock-29.639 {time parsing} {
+ clock scan {2440588 xi:00:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 39600
+test clock-29.640 {time parsing} {
+ clock scan {2440588 xi:?:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 39600
+test clock-29.641 {time parsing} {
+ clock scan {2440588 11 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I %P}
+} 39600
+test clock-29.642 {time parsing} {
+ clock scan {2440588 11:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %P}
+} 39600
+test clock-29.643 {time parsing} {
+ clock scan {2440588 11:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %P}
+} 39600
+test clock-29.644 {time parsing} {
+ clock scan {2440588 11:00:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 39600
+test clock-29.645 {time parsing} {
+ clock scan {2440588 11:?:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 39600
+test clock-29.646 {time parsing} {
+ clock scan {2440588 11 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l %P}
+} 39600
+test clock-29.647 {time parsing} {
+ clock scan {2440588 11:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %P}
+} 39600
+test clock-29.648 {time parsing} {
+ clock scan {2440588 11:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %P}
+} 39600
+test clock-29.649 {time parsing} {
+ clock scan {2440588 11:00:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 39600
+test clock-29.650 {time parsing} {
+ clock scan {2440588 11:?:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 39600
+test clock-29.651 {time parsing} {
+ clock scan {2440588 xi am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI %P}
+} 39600
+test clock-29.652 {time parsing} {
+ clock scan {2440588 xi:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %P}
+} 39600
+test clock-29.653 {time parsing} {
+ clock scan {2440588 xi:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %P}
+} 39600
+test clock-29.654 {time parsing} {
+ clock scan {2440588 xi:00:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 39600
+test clock-29.655 {time parsing} {
+ clock scan {2440588 xi:?:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 39600
+test clock-29.656 {time parsing} {
+ clock scan {2440588 xi am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol %P}
+} 39600
+test clock-29.657 {time parsing} {
+ clock scan {2440588 xi:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %P}
+} 39600
+test clock-29.658 {time parsing} {
+ clock scan {2440588 xi:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %P}
+} 39600
+test clock-29.659 {time parsing} {
+ clock scan {2440588 xi:00:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 39600
+test clock-29.660 {time parsing} {
+ clock scan {2440588 xi:?:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 39600
+test clock-29.661 {time parsing} {
+ clock scan {2440588 11:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 39601
+test clock-29.662 {time parsing} {
+ clock scan {2440588 11:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 39601
+test clock-29.663 {time parsing} {
+ clock scan {2440588 11:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 39601
+test clock-29.664 {time parsing} {
+ clock scan {2440588 11:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 39601
+test clock-29.665 {time parsing} {
+ clock scan {2440588 xi:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 39601
+test clock-29.666 {time parsing} {
+ clock scan {2440588 xi:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 39601
+test clock-29.667 {time parsing} {
+ clock scan {2440588 xi:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 39601
+test clock-29.668 {time parsing} {
+ clock scan {2440588 xi:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 39601
+test clock-29.669 {time parsing} {
+ clock scan {2440588 11:00:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 39601
+test clock-29.670 {time parsing} {
+ clock scan {2440588 11:?:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 39601
+test clock-29.671 {time parsing} {
+ clock scan {2440588 11:00:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 39601
+test clock-29.672 {time parsing} {
+ clock scan {2440588 11:?:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 39601
+test clock-29.673 {time parsing} {
+ clock scan {2440588 xi:00:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 39601
+test clock-29.674 {time parsing} {
+ clock scan {2440588 xi:?:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 39601
+test clock-29.675 {time parsing} {
+ clock scan {2440588 xi:00:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 39601
+test clock-29.676 {time parsing} {
+ clock scan {2440588 xi:?:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 39601
+test clock-29.677 {time parsing} {
+ clock scan {2440588 11:00:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 39601
+test clock-29.678 {time parsing} {
+ clock scan {2440588 11:?:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 39601
+test clock-29.679 {time parsing} {
+ clock scan {2440588 11:00:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 39601
+test clock-29.680 {time parsing} {
+ clock scan {2440588 11:?:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 39601
+test clock-29.681 {time parsing} {
+ clock scan {2440588 xi:00:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 39601
+test clock-29.682 {time parsing} {
+ clock scan {2440588 xi:?:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 39601
+test clock-29.683 {time parsing} {
+ clock scan {2440588 xi:00:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 39601
+test clock-29.684 {time parsing} {
+ clock scan {2440588 xi:?:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 39601
+test clock-29.685 {time parsing} {
+ clock scan {2440588 11:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 39659
+test clock-29.686 {time parsing} {
+ clock scan {2440588 11:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 39659
+test clock-29.687 {time parsing} {
+ clock scan {2440588 11:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 39659
+test clock-29.688 {time parsing} {
+ clock scan {2440588 11:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 39659
+test clock-29.689 {time parsing} {
+ clock scan {2440588 xi:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 39659
+test clock-29.690 {time parsing} {
+ clock scan {2440588 xi:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 39659
+test clock-29.691 {time parsing} {
+ clock scan {2440588 xi:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 39659
+test clock-29.692 {time parsing} {
+ clock scan {2440588 xi:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 39659
+test clock-29.693 {time parsing} {
+ clock scan {2440588 11:00:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 39659
+test clock-29.694 {time parsing} {
+ clock scan {2440588 11:?:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 39659
+test clock-29.695 {time parsing} {
+ clock scan {2440588 11:00:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 39659
+test clock-29.696 {time parsing} {
+ clock scan {2440588 11:?:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 39659
+test clock-29.697 {time parsing} {
+ clock scan {2440588 xi:00:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 39659
+test clock-29.698 {time parsing} {
+ clock scan {2440588 xi:?:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 39659
+test clock-29.699 {time parsing} {
+ clock scan {2440588 xi:00:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 39659
+test clock-29.700 {time parsing} {
+ clock scan {2440588 xi:?:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 39659
+test clock-29.701 {time parsing} {
+ clock scan {2440588 11:00:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 39659
+test clock-29.702 {time parsing} {
+ clock scan {2440588 11:?:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 39659
+test clock-29.703 {time parsing} {
+ clock scan {2440588 11:00:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 39659
+test clock-29.704 {time parsing} {
+ clock scan {2440588 11:?:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 39659
+test clock-29.705 {time parsing} {
+ clock scan {2440588 xi:00:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 39659
+test clock-29.706 {time parsing} {
+ clock scan {2440588 xi:?:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 39659
+test clock-29.707 {time parsing} {
+ clock scan {2440588 xi:00:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 39659
+test clock-29.708 {time parsing} {
+ clock scan {2440588 xi:?:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 39659
+test clock-29.709 {time parsing} {
+ clock scan {2440588 11:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M }
+} 39660
+test clock-29.710 {time parsing} {
+ clock scan {2440588 11:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM }
+} 39660
+test clock-29.711 {time parsing} {
+ clock scan {2440588 11:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 39660
+test clock-29.712 {time parsing} {
+ clock scan {2440588 11:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 39660
+test clock-29.713 {time parsing} {
+ clock scan {2440588 11:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M }
+} 39660
+test clock-29.714 {time parsing} {
+ clock scan {2440588 11:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM }
+} 39660
+test clock-29.715 {time parsing} {
+ clock scan {2440588 11:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 39660
+test clock-29.716 {time parsing} {
+ clock scan {2440588 11:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 39660
+test clock-29.717 {time parsing} {
+ clock scan {2440588 xi:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M }
+} 39660
+test clock-29.718 {time parsing} {
+ clock scan {2440588 xi:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM }
+} 39660
+test clock-29.719 {time parsing} {
+ clock scan {2440588 xi:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 39660
+test clock-29.720 {time parsing} {
+ clock scan {2440588 xi:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 39660
+test clock-29.721 {time parsing} {
+ clock scan {2440588 xi:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M }
+} 39660
+test clock-29.722 {time parsing} {
+ clock scan {2440588 xi:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM }
+} 39660
+test clock-29.723 {time parsing} {
+ clock scan {2440588 xi:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 39660
+test clock-29.724 {time parsing} {
+ clock scan {2440588 xi:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 39660
+test clock-29.725 {time parsing} {
+ clock scan {2440588 11:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %p}
+} 39660
+test clock-29.726 {time parsing} {
+ clock scan {2440588 11:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %p}
+} 39660
+test clock-29.727 {time parsing} {
+ clock scan {2440588 11:01:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 39660
+test clock-29.728 {time parsing} {
+ clock scan {2440588 11:i:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 39660
+test clock-29.729 {time parsing} {
+ clock scan {2440588 11:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %p}
+} 39660
+test clock-29.730 {time parsing} {
+ clock scan {2440588 11:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %p}
+} 39660
+test clock-29.731 {time parsing} {
+ clock scan {2440588 11:01:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 39660
+test clock-29.732 {time parsing} {
+ clock scan {2440588 11:i:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 39660
+test clock-29.733 {time parsing} {
+ clock scan {2440588 xi:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %p}
+} 39660
+test clock-29.734 {time parsing} {
+ clock scan {2440588 xi:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %p}
+} 39660
+test clock-29.735 {time parsing} {
+ clock scan {2440588 xi:01:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 39660
+test clock-29.736 {time parsing} {
+ clock scan {2440588 xi:i:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 39660
+test clock-29.737 {time parsing} {
+ clock scan {2440588 xi:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %p}
+} 39660
+test clock-29.738 {time parsing} {
+ clock scan {2440588 xi:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %p}
+} 39660
+test clock-29.739 {time parsing} {
+ clock scan {2440588 xi:01:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 39660
+test clock-29.740 {time parsing} {
+ clock scan {2440588 xi:i:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 39660
+test clock-29.741 {time parsing} {
+ clock scan {2440588 11:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %P}
+} 39660
+test clock-29.742 {time parsing} {
+ clock scan {2440588 11:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %P}
+} 39660
+test clock-29.743 {time parsing} {
+ clock scan {2440588 11:01:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 39660
+test clock-29.744 {time parsing} {
+ clock scan {2440588 11:i:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 39660
+test clock-29.745 {time parsing} {
+ clock scan {2440588 11:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %P}
+} 39660
+test clock-29.746 {time parsing} {
+ clock scan {2440588 11:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %P}
+} 39660
+test clock-29.747 {time parsing} {
+ clock scan {2440588 11:01:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 39660
+test clock-29.748 {time parsing} {
+ clock scan {2440588 11:i:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 39660
+test clock-29.749 {time parsing} {
+ clock scan {2440588 xi:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %P}
+} 39660
+test clock-29.750 {time parsing} {
+ clock scan {2440588 xi:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %P}
+} 39660
+test clock-29.751 {time parsing} {
+ clock scan {2440588 xi:01:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 39660
+test clock-29.752 {time parsing} {
+ clock scan {2440588 xi:i:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 39660
+test clock-29.753 {time parsing} {
+ clock scan {2440588 xi:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %P}
+} 39660
+test clock-29.754 {time parsing} {
+ clock scan {2440588 xi:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %P}
+} 39660
+test clock-29.755 {time parsing} {
+ clock scan {2440588 xi:01:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 39660
+test clock-29.756 {time parsing} {
+ clock scan {2440588 xi:i:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 39660
+test clock-29.757 {time parsing} {
+ clock scan {2440588 11:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 39661
+test clock-29.758 {time parsing} {
+ clock scan {2440588 11:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 39661
+test clock-29.759 {time parsing} {
+ clock scan {2440588 11:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 39661
+test clock-29.760 {time parsing} {
+ clock scan {2440588 11:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 39661
+test clock-29.761 {time parsing} {
+ clock scan {2440588 xi:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 39661
+test clock-29.762 {time parsing} {
+ clock scan {2440588 xi:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 39661
+test clock-29.763 {time parsing} {
+ clock scan {2440588 xi:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 39661
+test clock-29.764 {time parsing} {
+ clock scan {2440588 xi:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 39661
+test clock-29.765 {time parsing} {
+ clock scan {2440588 11:01:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 39661
+test clock-29.766 {time parsing} {
+ clock scan {2440588 11:i:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 39661
+test clock-29.767 {time parsing} {
+ clock scan {2440588 11:01:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 39661
+test clock-29.768 {time parsing} {
+ clock scan {2440588 11:i:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 39661
+test clock-29.769 {time parsing} {
+ clock scan {2440588 xi:01:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 39661
+test clock-29.770 {time parsing} {
+ clock scan {2440588 xi:i:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 39661
+test clock-29.771 {time parsing} {
+ clock scan {2440588 xi:01:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 39661
+test clock-29.772 {time parsing} {
+ clock scan {2440588 xi:i:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 39661
+test clock-29.773 {time parsing} {
+ clock scan {2440588 11:01:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 39661
+test clock-29.774 {time parsing} {
+ clock scan {2440588 11:i:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 39661
+test clock-29.775 {time parsing} {
+ clock scan {2440588 11:01:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 39661
+test clock-29.776 {time parsing} {
+ clock scan {2440588 11:i:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 39661
+test clock-29.777 {time parsing} {
+ clock scan {2440588 xi:01:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 39661
+test clock-29.778 {time parsing} {
+ clock scan {2440588 xi:i:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 39661
+test clock-29.779 {time parsing} {
+ clock scan {2440588 xi:01:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 39661
+test clock-29.780 {time parsing} {
+ clock scan {2440588 xi:i:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 39661
+test clock-29.781 {time parsing} {
+ clock scan {2440588 11:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 39719
+test clock-29.782 {time parsing} {
+ clock scan {2440588 11:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 39719
+test clock-29.783 {time parsing} {
+ clock scan {2440588 11:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 39719
+test clock-29.784 {time parsing} {
+ clock scan {2440588 11:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 39719
+test clock-29.785 {time parsing} {
+ clock scan {2440588 xi:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 39719
+test clock-29.786 {time parsing} {
+ clock scan {2440588 xi:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 39719
+test clock-29.787 {time parsing} {
+ clock scan {2440588 xi:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 39719
+test clock-29.788 {time parsing} {
+ clock scan {2440588 xi:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 39719
+test clock-29.789 {time parsing} {
+ clock scan {2440588 11:01:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 39719
+test clock-29.790 {time parsing} {
+ clock scan {2440588 11:i:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 39719
+test clock-29.791 {time parsing} {
+ clock scan {2440588 11:01:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 39719
+test clock-29.792 {time parsing} {
+ clock scan {2440588 11:i:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 39719
+test clock-29.793 {time parsing} {
+ clock scan {2440588 xi:01:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 39719
+test clock-29.794 {time parsing} {
+ clock scan {2440588 xi:i:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 39719
+test clock-29.795 {time parsing} {
+ clock scan {2440588 xi:01:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 39719
+test clock-29.796 {time parsing} {
+ clock scan {2440588 xi:i:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 39719
+test clock-29.797 {time parsing} {
+ clock scan {2440588 11:01:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 39719
+test clock-29.798 {time parsing} {
+ clock scan {2440588 11:i:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 39719
+test clock-29.799 {time parsing} {
+ clock scan {2440588 11:01:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 39719
+test clock-29.800 {time parsing} {
+ clock scan {2440588 11:i:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 39719
+test clock-29.801 {time parsing} {
+ clock scan {2440588 xi:01:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 39719
+test clock-29.802 {time parsing} {
+ clock scan {2440588 xi:i:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 39719
+test clock-29.803 {time parsing} {
+ clock scan {2440588 xi:01:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 39719
+test clock-29.804 {time parsing} {
+ clock scan {2440588 xi:i:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 39719
+test clock-29.805 {time parsing} {
+ clock scan {2440588 11:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M }
+} 43140
+test clock-29.806 {time parsing} {
+ clock scan {2440588 11:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM }
+} 43140
+test clock-29.807 {time parsing} {
+ clock scan {2440588 11:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 43140
+test clock-29.808 {time parsing} {
+ clock scan {2440588 11:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 43140
+test clock-29.809 {time parsing} {
+ clock scan {2440588 11:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M }
+} 43140
+test clock-29.810 {time parsing} {
+ clock scan {2440588 11:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM }
+} 43140
+test clock-29.811 {time parsing} {
+ clock scan {2440588 11:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 43140
+test clock-29.812 {time parsing} {
+ clock scan {2440588 11:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 43140
+test clock-29.813 {time parsing} {
+ clock scan {2440588 xi:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M }
+} 43140
+test clock-29.814 {time parsing} {
+ clock scan {2440588 xi:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM }
+} 43140
+test clock-29.815 {time parsing} {
+ clock scan {2440588 xi:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 43140
+test clock-29.816 {time parsing} {
+ clock scan {2440588 xi:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 43140
+test clock-29.817 {time parsing} {
+ clock scan {2440588 xi:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M }
+} 43140
+test clock-29.818 {time parsing} {
+ clock scan {2440588 xi:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM }
+} 43140
+test clock-29.819 {time parsing} {
+ clock scan {2440588 xi:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 43140
+test clock-29.820 {time parsing} {
+ clock scan {2440588 xi:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 43140
+test clock-29.821 {time parsing} {
+ clock scan {2440588 11:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %p}
+} 43140
+test clock-29.822 {time parsing} {
+ clock scan {2440588 11:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %p}
+} 43140
+test clock-29.823 {time parsing} {
+ clock scan {2440588 11:59:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 43140
+test clock-29.824 {time parsing} {
+ clock scan {2440588 11:lix:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 43140
+test clock-29.825 {time parsing} {
+ clock scan {2440588 11:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %p}
+} 43140
+test clock-29.826 {time parsing} {
+ clock scan {2440588 11:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %p}
+} 43140
+test clock-29.827 {time parsing} {
+ clock scan {2440588 11:59:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 43140
+test clock-29.828 {time parsing} {
+ clock scan {2440588 11:lix:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 43140
+test clock-29.829 {time parsing} {
+ clock scan {2440588 xi:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %p}
+} 43140
+test clock-29.830 {time parsing} {
+ clock scan {2440588 xi:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %p}
+} 43140
+test clock-29.831 {time parsing} {
+ clock scan {2440588 xi:59:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 43140
+test clock-29.832 {time parsing} {
+ clock scan {2440588 xi:lix:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 43140
+test clock-29.833 {time parsing} {
+ clock scan {2440588 xi:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %p}
+} 43140
+test clock-29.834 {time parsing} {
+ clock scan {2440588 xi:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %p}
+} 43140
+test clock-29.835 {time parsing} {
+ clock scan {2440588 xi:59:00 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 43140
+test clock-29.836 {time parsing} {
+ clock scan {2440588 xi:lix:? AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 43140
+test clock-29.837 {time parsing} {
+ clock scan {2440588 11:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %P}
+} 43140
+test clock-29.838 {time parsing} {
+ clock scan {2440588 11:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %P}
+} 43140
+test clock-29.839 {time parsing} {
+ clock scan {2440588 11:59:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 43140
+test clock-29.840 {time parsing} {
+ clock scan {2440588 11:lix:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 43140
+test clock-29.841 {time parsing} {
+ clock scan {2440588 11:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %P}
+} 43140
+test clock-29.842 {time parsing} {
+ clock scan {2440588 11:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %P}
+} 43140
+test clock-29.843 {time parsing} {
+ clock scan {2440588 11:59:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 43140
+test clock-29.844 {time parsing} {
+ clock scan {2440588 11:lix:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 43140
+test clock-29.845 {time parsing} {
+ clock scan {2440588 xi:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %P}
+} 43140
+test clock-29.846 {time parsing} {
+ clock scan {2440588 xi:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %P}
+} 43140
+test clock-29.847 {time parsing} {
+ clock scan {2440588 xi:59:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 43140
+test clock-29.848 {time parsing} {
+ clock scan {2440588 xi:lix:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 43140
+test clock-29.849 {time parsing} {
+ clock scan {2440588 xi:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %P}
+} 43140
+test clock-29.850 {time parsing} {
+ clock scan {2440588 xi:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %P}
+} 43140
+test clock-29.851 {time parsing} {
+ clock scan {2440588 xi:59:00 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 43140
+test clock-29.852 {time parsing} {
+ clock scan {2440588 xi:lix:? am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 43140
+test clock-29.853 {time parsing} {
+ clock scan {2440588 11:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 43141
+test clock-29.854 {time parsing} {
+ clock scan {2440588 11:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 43141
+test clock-29.855 {time parsing} {
+ clock scan {2440588 11:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 43141
+test clock-29.856 {time parsing} {
+ clock scan {2440588 11:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 43141
+test clock-29.857 {time parsing} {
+ clock scan {2440588 xi:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 43141
+test clock-29.858 {time parsing} {
+ clock scan {2440588 xi:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 43141
+test clock-29.859 {time parsing} {
+ clock scan {2440588 xi:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 43141
+test clock-29.860 {time parsing} {
+ clock scan {2440588 xi:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 43141
+test clock-29.861 {time parsing} {
+ clock scan {2440588 11:59:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 43141
+test clock-29.862 {time parsing} {
+ clock scan {2440588 11:lix:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 43141
+test clock-29.863 {time parsing} {
+ clock scan {2440588 11:59:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 43141
+test clock-29.864 {time parsing} {
+ clock scan {2440588 11:lix:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 43141
+test clock-29.865 {time parsing} {
+ clock scan {2440588 xi:59:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 43141
+test clock-29.866 {time parsing} {
+ clock scan {2440588 xi:lix:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 43141
+test clock-29.867 {time parsing} {
+ clock scan {2440588 xi:59:01 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 43141
+test clock-29.868 {time parsing} {
+ clock scan {2440588 xi:lix:i AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 43141
+test clock-29.869 {time parsing} {
+ clock scan {2440588 11:59:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 43141
+test clock-29.870 {time parsing} {
+ clock scan {2440588 11:lix:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 43141
+test clock-29.871 {time parsing} {
+ clock scan {2440588 11:59:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 43141
+test clock-29.872 {time parsing} {
+ clock scan {2440588 11:lix:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 43141
+test clock-29.873 {time parsing} {
+ clock scan {2440588 xi:59:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 43141
+test clock-29.874 {time parsing} {
+ clock scan {2440588 xi:lix:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 43141
+test clock-29.875 {time parsing} {
+ clock scan {2440588 xi:59:01 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 43141
+test clock-29.876 {time parsing} {
+ clock scan {2440588 xi:lix:i am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 43141
+test clock-29.877 {time parsing} {
+ clock scan {2440588 11:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 43199
+test clock-29.878 {time parsing} {
+ clock scan {2440588 11:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 43199
+test clock-29.879 {time parsing} {
+ clock scan {2440588 11:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 43199
+test clock-29.880 {time parsing} {
+ clock scan {2440588 11:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 43199
+test clock-29.881 {time parsing} {
+ clock scan {2440588 xi:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 43199
+test clock-29.882 {time parsing} {
+ clock scan {2440588 xi:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 43199
+test clock-29.883 {time parsing} {
+ clock scan {2440588 xi:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 43199
+test clock-29.884 {time parsing} {
+ clock scan {2440588 xi:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 43199
+test clock-29.885 {time parsing} {
+ clock scan {2440588 11:59:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 43199
+test clock-29.886 {time parsing} {
+ clock scan {2440588 11:lix:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 43199
+test clock-29.887 {time parsing} {
+ clock scan {2440588 11:59:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 43199
+test clock-29.888 {time parsing} {
+ clock scan {2440588 11:lix:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 43199
+test clock-29.889 {time parsing} {
+ clock scan {2440588 xi:59:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 43199
+test clock-29.890 {time parsing} {
+ clock scan {2440588 xi:lix:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 43199
+test clock-29.891 {time parsing} {
+ clock scan {2440588 xi:59:59 AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 43199
+test clock-29.892 {time parsing} {
+ clock scan {2440588 xi:lix:lix AM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 43199
+test clock-29.893 {time parsing} {
+ clock scan {2440588 11:59:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 43199
+test clock-29.894 {time parsing} {
+ clock scan {2440588 11:lix:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 43199
+test clock-29.895 {time parsing} {
+ clock scan {2440588 11:59:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 43199
+test clock-29.896 {time parsing} {
+ clock scan {2440588 11:lix:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 43199
+test clock-29.897 {time parsing} {
+ clock scan {2440588 xi:59:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 43199
+test clock-29.898 {time parsing} {
+ clock scan {2440588 xi:lix:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 43199
+test clock-29.899 {time parsing} {
+ clock scan {2440588 xi:59:59 am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 43199
+test clock-29.900 {time parsing} {
+ clock scan {2440588 xi:lix:lix am} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 43199
+test clock-29.901 {time parsing} {
+ clock scan {2440588 12 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H }
+} 43200
+test clock-29.902 {time parsing} {
+ clock scan {2440588 12:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M }
+} 43200
+test clock-29.903 {time parsing} {
+ clock scan {2440588 12:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM }
+} 43200
+test clock-29.904 {time parsing} {
+ clock scan {2440588 12:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 43200
+test clock-29.905 {time parsing} {
+ clock scan {2440588 12:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 43200
+test clock-29.906 {time parsing} {
+ clock scan {2440588 12 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k }
+} 43200
+test clock-29.907 {time parsing} {
+ clock scan {2440588 12:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M }
+} 43200
+test clock-29.908 {time parsing} {
+ clock scan {2440588 12:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM }
+} 43200
+test clock-29.909 {time parsing} {
+ clock scan {2440588 12:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 43200
+test clock-29.910 {time parsing} {
+ clock scan {2440588 12:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 43200
+test clock-29.911 {time parsing} {
+ clock scan {2440588 xii } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH }
+} 43200
+test clock-29.912 {time parsing} {
+ clock scan {2440588 xii:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M }
+} 43200
+test clock-29.913 {time parsing} {
+ clock scan {2440588 xii:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM }
+} 43200
+test clock-29.914 {time parsing} {
+ clock scan {2440588 xii:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 43200
+test clock-29.915 {time parsing} {
+ clock scan {2440588 xii:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 43200
+test clock-29.916 {time parsing} {
+ clock scan {2440588 xii } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok }
+} 43200
+test clock-29.917 {time parsing} {
+ clock scan {2440588 xii:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M }
+} 43200
+test clock-29.918 {time parsing} {
+ clock scan {2440588 xii:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM }
+} 43200
+test clock-29.919 {time parsing} {
+ clock scan {2440588 xii:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 43200
+test clock-29.920 {time parsing} {
+ clock scan {2440588 xii:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 43200
+test clock-29.921 {time parsing} {
+ clock scan {2440588 12 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I %p}
+} 43200
+test clock-29.922 {time parsing} {
+ clock scan {2440588 12:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %p}
+} 43200
+test clock-29.923 {time parsing} {
+ clock scan {2440588 12:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %p}
+} 43200
+test clock-29.924 {time parsing} {
+ clock scan {2440588 12:00:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 43200
+test clock-29.925 {time parsing} {
+ clock scan {2440588 12:?:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 43200
+test clock-29.926 {time parsing} {
+ clock scan {2440588 12 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l %p}
+} 43200
+test clock-29.927 {time parsing} {
+ clock scan {2440588 12:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %p}
+} 43200
+test clock-29.928 {time parsing} {
+ clock scan {2440588 12:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %p}
+} 43200
+test clock-29.929 {time parsing} {
+ clock scan {2440588 12:00:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 43200
+test clock-29.930 {time parsing} {
+ clock scan {2440588 12:?:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 43200
+test clock-29.931 {time parsing} {
+ clock scan {2440588 xii PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI %p}
+} 43200
+test clock-29.932 {time parsing} {
+ clock scan {2440588 xii:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %p}
+} 43200
+test clock-29.933 {time parsing} {
+ clock scan {2440588 xii:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %p}
+} 43200
+test clock-29.934 {time parsing} {
+ clock scan {2440588 xii:00:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 43200
+test clock-29.935 {time parsing} {
+ clock scan {2440588 xii:?:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 43200
+test clock-29.936 {time parsing} {
+ clock scan {2440588 xii PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol %p}
+} 43200
+test clock-29.937 {time parsing} {
+ clock scan {2440588 xii:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %p}
+} 43200
+test clock-29.938 {time parsing} {
+ clock scan {2440588 xii:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %p}
+} 43200
+test clock-29.939 {time parsing} {
+ clock scan {2440588 xii:00:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 43200
+test clock-29.940 {time parsing} {
+ clock scan {2440588 xii:?:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 43200
+test clock-29.941 {time parsing} {
+ clock scan {2440588 12 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I %P}
+} 43200
+test clock-29.942 {time parsing} {
+ clock scan {2440588 12:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %P}
+} 43200
+test clock-29.943 {time parsing} {
+ clock scan {2440588 12:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %P}
+} 43200
+test clock-29.944 {time parsing} {
+ clock scan {2440588 12:00:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 43200
+test clock-29.945 {time parsing} {
+ clock scan {2440588 12:?:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 43200
+test clock-29.946 {time parsing} {
+ clock scan {2440588 12 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l %P}
+} 43200
+test clock-29.947 {time parsing} {
+ clock scan {2440588 12:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %P}
+} 43200
+test clock-29.948 {time parsing} {
+ clock scan {2440588 12:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %P}
+} 43200
+test clock-29.949 {time parsing} {
+ clock scan {2440588 12:00:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 43200
+test clock-29.950 {time parsing} {
+ clock scan {2440588 12:?:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 43200
+test clock-29.951 {time parsing} {
+ clock scan {2440588 xii pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI %P}
+} 43200
+test clock-29.952 {time parsing} {
+ clock scan {2440588 xii:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %P}
+} 43200
+test clock-29.953 {time parsing} {
+ clock scan {2440588 xii:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %P}
+} 43200
+test clock-29.954 {time parsing} {
+ clock scan {2440588 xii:00:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 43200
+test clock-29.955 {time parsing} {
+ clock scan {2440588 xii:?:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 43200
+test clock-29.956 {time parsing} {
+ clock scan {2440588 xii pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol %P}
+} 43200
+test clock-29.957 {time parsing} {
+ clock scan {2440588 xii:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %P}
+} 43200
+test clock-29.958 {time parsing} {
+ clock scan {2440588 xii:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %P}
+} 43200
+test clock-29.959 {time parsing} {
+ clock scan {2440588 xii:00:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 43200
+test clock-29.960 {time parsing} {
+ clock scan {2440588 xii:?:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 43200
+test clock-29.961 {time parsing} {
+ clock scan {2440588 12:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 43201
+test clock-29.962 {time parsing} {
+ clock scan {2440588 12:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 43201
+test clock-29.963 {time parsing} {
+ clock scan {2440588 12:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 43201
+test clock-29.964 {time parsing} {
+ clock scan {2440588 12:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 43201
+test clock-29.965 {time parsing} {
+ clock scan {2440588 xii:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 43201
+test clock-29.966 {time parsing} {
+ clock scan {2440588 xii:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 43201
+test clock-29.967 {time parsing} {
+ clock scan {2440588 xii:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 43201
+test clock-29.968 {time parsing} {
+ clock scan {2440588 xii:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 43201
+test clock-29.969 {time parsing} {
+ clock scan {2440588 12:00:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 43201
+test clock-29.970 {time parsing} {
+ clock scan {2440588 12:?:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 43201
+test clock-29.971 {time parsing} {
+ clock scan {2440588 12:00:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 43201
+test clock-29.972 {time parsing} {
+ clock scan {2440588 12:?:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 43201
+test clock-29.973 {time parsing} {
+ clock scan {2440588 xii:00:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 43201
+test clock-29.974 {time parsing} {
+ clock scan {2440588 xii:?:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 43201
+test clock-29.975 {time parsing} {
+ clock scan {2440588 xii:00:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 43201
+test clock-29.976 {time parsing} {
+ clock scan {2440588 xii:?:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 43201
+test clock-29.977 {time parsing} {
+ clock scan {2440588 12:00:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 43201
+test clock-29.978 {time parsing} {
+ clock scan {2440588 12:?:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 43201
+test clock-29.979 {time parsing} {
+ clock scan {2440588 12:00:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 43201
+test clock-29.980 {time parsing} {
+ clock scan {2440588 12:?:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 43201
+test clock-29.981 {time parsing} {
+ clock scan {2440588 xii:00:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 43201
+test clock-29.982 {time parsing} {
+ clock scan {2440588 xii:?:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 43201
+test clock-29.983 {time parsing} {
+ clock scan {2440588 xii:00:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 43201
+test clock-29.984 {time parsing} {
+ clock scan {2440588 xii:?:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 43201
+test clock-29.985 {time parsing} {
+ clock scan {2440588 12:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 43259
+test clock-29.986 {time parsing} {
+ clock scan {2440588 12:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 43259
+test clock-29.987 {time parsing} {
+ clock scan {2440588 12:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 43259
+test clock-29.988 {time parsing} {
+ clock scan {2440588 12:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 43259
+test clock-29.989 {time parsing} {
+ clock scan {2440588 xii:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 43259
+test clock-29.990 {time parsing} {
+ clock scan {2440588 xii:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 43259
+test clock-29.991 {time parsing} {
+ clock scan {2440588 xii:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 43259
+test clock-29.992 {time parsing} {
+ clock scan {2440588 xii:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 43259
+test clock-29.993 {time parsing} {
+ clock scan {2440588 12:00:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 43259
+test clock-29.994 {time parsing} {
+ clock scan {2440588 12:?:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 43259
+test clock-29.995 {time parsing} {
+ clock scan {2440588 12:00:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 43259
+test clock-29.996 {time parsing} {
+ clock scan {2440588 12:?:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 43259
+test clock-29.997 {time parsing} {
+ clock scan {2440588 xii:00:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 43259
+test clock-29.998 {time parsing} {
+ clock scan {2440588 xii:?:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 43259
+test clock-29.999 {time parsing} {
+ clock scan {2440588 xii:00:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 43259
+test clock-29.1000 {time parsing} {
+ clock scan {2440588 xii:?:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 43259
+test clock-29.1001 {time parsing} {
+ clock scan {2440588 12:00:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 43259
+test clock-29.1002 {time parsing} {
+ clock scan {2440588 12:?:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 43259
+test clock-29.1003 {time parsing} {
+ clock scan {2440588 12:00:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 43259
+test clock-29.1004 {time parsing} {
+ clock scan {2440588 12:?:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 43259
+test clock-29.1005 {time parsing} {
+ clock scan {2440588 xii:00:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 43259
+test clock-29.1006 {time parsing} {
+ clock scan {2440588 xii:?:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 43259
+test clock-29.1007 {time parsing} {
+ clock scan {2440588 xii:00:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 43259
+test clock-29.1008 {time parsing} {
+ clock scan {2440588 xii:?:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 43259
+test clock-29.1009 {time parsing} {
+ clock scan {2440588 12:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M }
+} 43260
+test clock-29.1010 {time parsing} {
+ clock scan {2440588 12:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM }
+} 43260
+test clock-29.1011 {time parsing} {
+ clock scan {2440588 12:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 43260
+test clock-29.1012 {time parsing} {
+ clock scan {2440588 12:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 43260
+test clock-29.1013 {time parsing} {
+ clock scan {2440588 12:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M }
+} 43260
+test clock-29.1014 {time parsing} {
+ clock scan {2440588 12:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM }
+} 43260
+test clock-29.1015 {time parsing} {
+ clock scan {2440588 12:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 43260
+test clock-29.1016 {time parsing} {
+ clock scan {2440588 12:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 43260
+test clock-29.1017 {time parsing} {
+ clock scan {2440588 xii:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M }
+} 43260
+test clock-29.1018 {time parsing} {
+ clock scan {2440588 xii:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM }
+} 43260
+test clock-29.1019 {time parsing} {
+ clock scan {2440588 xii:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 43260
+test clock-29.1020 {time parsing} {
+ clock scan {2440588 xii:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 43260
+test clock-29.1021 {time parsing} {
+ clock scan {2440588 xii:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M }
+} 43260
+test clock-29.1022 {time parsing} {
+ clock scan {2440588 xii:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM }
+} 43260
+test clock-29.1023 {time parsing} {
+ clock scan {2440588 xii:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 43260
+test clock-29.1024 {time parsing} {
+ clock scan {2440588 xii:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 43260
+test clock-29.1025 {time parsing} {
+ clock scan {2440588 12:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %p}
+} 43260
+test clock-29.1026 {time parsing} {
+ clock scan {2440588 12:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %p}
+} 43260
+test clock-29.1027 {time parsing} {
+ clock scan {2440588 12:01:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 43260
+test clock-29.1028 {time parsing} {
+ clock scan {2440588 12:i:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 43260
+test clock-29.1029 {time parsing} {
+ clock scan {2440588 12:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %p}
+} 43260
+test clock-29.1030 {time parsing} {
+ clock scan {2440588 12:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %p}
+} 43260
+test clock-29.1031 {time parsing} {
+ clock scan {2440588 12:01:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 43260
+test clock-29.1032 {time parsing} {
+ clock scan {2440588 12:i:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 43260
+test clock-29.1033 {time parsing} {
+ clock scan {2440588 xii:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %p}
+} 43260
+test clock-29.1034 {time parsing} {
+ clock scan {2440588 xii:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %p}
+} 43260
+test clock-29.1035 {time parsing} {
+ clock scan {2440588 xii:01:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 43260
+test clock-29.1036 {time parsing} {
+ clock scan {2440588 xii:i:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 43260
+test clock-29.1037 {time parsing} {
+ clock scan {2440588 xii:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %p}
+} 43260
+test clock-29.1038 {time parsing} {
+ clock scan {2440588 xii:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %p}
+} 43260
+test clock-29.1039 {time parsing} {
+ clock scan {2440588 xii:01:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 43260
+test clock-29.1040 {time parsing} {
+ clock scan {2440588 xii:i:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 43260
+test clock-29.1041 {time parsing} {
+ clock scan {2440588 12:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %P}
+} 43260
+test clock-29.1042 {time parsing} {
+ clock scan {2440588 12:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %P}
+} 43260
+test clock-29.1043 {time parsing} {
+ clock scan {2440588 12:01:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 43260
+test clock-29.1044 {time parsing} {
+ clock scan {2440588 12:i:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 43260
+test clock-29.1045 {time parsing} {
+ clock scan {2440588 12:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %P}
+} 43260
+test clock-29.1046 {time parsing} {
+ clock scan {2440588 12:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %P}
+} 43260
+test clock-29.1047 {time parsing} {
+ clock scan {2440588 12:01:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 43260
+test clock-29.1048 {time parsing} {
+ clock scan {2440588 12:i:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 43260
+test clock-29.1049 {time parsing} {
+ clock scan {2440588 xii:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %P}
+} 43260
+test clock-29.1050 {time parsing} {
+ clock scan {2440588 xii:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %P}
+} 43260
+test clock-29.1051 {time parsing} {
+ clock scan {2440588 xii:01:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 43260
+test clock-29.1052 {time parsing} {
+ clock scan {2440588 xii:i:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 43260
+test clock-29.1053 {time parsing} {
+ clock scan {2440588 xii:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %P}
+} 43260
+test clock-29.1054 {time parsing} {
+ clock scan {2440588 xii:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %P}
+} 43260
+test clock-29.1055 {time parsing} {
+ clock scan {2440588 xii:01:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 43260
+test clock-29.1056 {time parsing} {
+ clock scan {2440588 xii:i:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 43260
+test clock-29.1057 {time parsing} {
+ clock scan {2440588 12:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 43261
+test clock-29.1058 {time parsing} {
+ clock scan {2440588 12:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 43261
+test clock-29.1059 {time parsing} {
+ clock scan {2440588 12:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 43261
+test clock-29.1060 {time parsing} {
+ clock scan {2440588 12:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 43261
+test clock-29.1061 {time parsing} {
+ clock scan {2440588 xii:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 43261
+test clock-29.1062 {time parsing} {
+ clock scan {2440588 xii:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 43261
+test clock-29.1063 {time parsing} {
+ clock scan {2440588 xii:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 43261
+test clock-29.1064 {time parsing} {
+ clock scan {2440588 xii:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 43261
+test clock-29.1065 {time parsing} {
+ clock scan {2440588 12:01:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 43261
+test clock-29.1066 {time parsing} {
+ clock scan {2440588 12:i:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 43261
+test clock-29.1067 {time parsing} {
+ clock scan {2440588 12:01:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 43261
+test clock-29.1068 {time parsing} {
+ clock scan {2440588 12:i:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 43261
+test clock-29.1069 {time parsing} {
+ clock scan {2440588 xii:01:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 43261
+test clock-29.1070 {time parsing} {
+ clock scan {2440588 xii:i:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 43261
+test clock-29.1071 {time parsing} {
+ clock scan {2440588 xii:01:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 43261
+test clock-29.1072 {time parsing} {
+ clock scan {2440588 xii:i:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 43261
+test clock-29.1073 {time parsing} {
+ clock scan {2440588 12:01:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 43261
+test clock-29.1074 {time parsing} {
+ clock scan {2440588 12:i:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 43261
+test clock-29.1075 {time parsing} {
+ clock scan {2440588 12:01:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 43261
+test clock-29.1076 {time parsing} {
+ clock scan {2440588 12:i:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 43261
+test clock-29.1077 {time parsing} {
+ clock scan {2440588 xii:01:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 43261
+test clock-29.1078 {time parsing} {
+ clock scan {2440588 xii:i:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 43261
+test clock-29.1079 {time parsing} {
+ clock scan {2440588 xii:01:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 43261
+test clock-29.1080 {time parsing} {
+ clock scan {2440588 xii:i:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 43261
+test clock-29.1081 {time parsing} {
+ clock scan {2440588 12:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 43319
+test clock-29.1082 {time parsing} {
+ clock scan {2440588 12:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 43319
+test clock-29.1083 {time parsing} {
+ clock scan {2440588 12:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 43319
+test clock-29.1084 {time parsing} {
+ clock scan {2440588 12:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 43319
+test clock-29.1085 {time parsing} {
+ clock scan {2440588 xii:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 43319
+test clock-29.1086 {time parsing} {
+ clock scan {2440588 xii:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 43319
+test clock-29.1087 {time parsing} {
+ clock scan {2440588 xii:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 43319
+test clock-29.1088 {time parsing} {
+ clock scan {2440588 xii:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 43319
+test clock-29.1089 {time parsing} {
+ clock scan {2440588 12:01:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 43319
+test clock-29.1090 {time parsing} {
+ clock scan {2440588 12:i:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 43319
+test clock-29.1091 {time parsing} {
+ clock scan {2440588 12:01:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 43319
+test clock-29.1092 {time parsing} {
+ clock scan {2440588 12:i:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 43319
+test clock-29.1093 {time parsing} {
+ clock scan {2440588 xii:01:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 43319
+test clock-29.1094 {time parsing} {
+ clock scan {2440588 xii:i:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 43319
+test clock-29.1095 {time parsing} {
+ clock scan {2440588 xii:01:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 43319
+test clock-29.1096 {time parsing} {
+ clock scan {2440588 xii:i:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 43319
+test clock-29.1097 {time parsing} {
+ clock scan {2440588 12:01:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 43319
+test clock-29.1098 {time parsing} {
+ clock scan {2440588 12:i:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 43319
+test clock-29.1099 {time parsing} {
+ clock scan {2440588 12:01:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 43319
+test clock-29.1100 {time parsing} {
+ clock scan {2440588 12:i:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 43319
+test clock-29.1101 {time parsing} {
+ clock scan {2440588 xii:01:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 43319
+test clock-29.1102 {time parsing} {
+ clock scan {2440588 xii:i:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 43319
+test clock-29.1103 {time parsing} {
+ clock scan {2440588 xii:01:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 43319
+test clock-29.1104 {time parsing} {
+ clock scan {2440588 xii:i:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 43319
+test clock-29.1105 {time parsing} {
+ clock scan {2440588 12:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M }
+} 46740
+test clock-29.1106 {time parsing} {
+ clock scan {2440588 12:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM }
+} 46740
+test clock-29.1107 {time parsing} {
+ clock scan {2440588 12:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 46740
+test clock-29.1108 {time parsing} {
+ clock scan {2440588 12:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 46740
+test clock-29.1109 {time parsing} {
+ clock scan {2440588 12:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M }
+} 46740
+test clock-29.1110 {time parsing} {
+ clock scan {2440588 12:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM }
+} 46740
+test clock-29.1111 {time parsing} {
+ clock scan {2440588 12:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 46740
+test clock-29.1112 {time parsing} {
+ clock scan {2440588 12:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 46740
+test clock-29.1113 {time parsing} {
+ clock scan {2440588 xii:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M }
+} 46740
+test clock-29.1114 {time parsing} {
+ clock scan {2440588 xii:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM }
+} 46740
+test clock-29.1115 {time parsing} {
+ clock scan {2440588 xii:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 46740
+test clock-29.1116 {time parsing} {
+ clock scan {2440588 xii:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 46740
+test clock-29.1117 {time parsing} {
+ clock scan {2440588 xii:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M }
+} 46740
+test clock-29.1118 {time parsing} {
+ clock scan {2440588 xii:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM }
+} 46740
+test clock-29.1119 {time parsing} {
+ clock scan {2440588 xii:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 46740
+test clock-29.1120 {time parsing} {
+ clock scan {2440588 xii:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 46740
+test clock-29.1121 {time parsing} {
+ clock scan {2440588 12:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %p}
+} 46740
+test clock-29.1122 {time parsing} {
+ clock scan {2440588 12:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %p}
+} 46740
+test clock-29.1123 {time parsing} {
+ clock scan {2440588 12:59:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 46740
+test clock-29.1124 {time parsing} {
+ clock scan {2440588 12:lix:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 46740
+test clock-29.1125 {time parsing} {
+ clock scan {2440588 12:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %p}
+} 46740
+test clock-29.1126 {time parsing} {
+ clock scan {2440588 12:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %p}
+} 46740
+test clock-29.1127 {time parsing} {
+ clock scan {2440588 12:59:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 46740
+test clock-29.1128 {time parsing} {
+ clock scan {2440588 12:lix:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 46740
+test clock-29.1129 {time parsing} {
+ clock scan {2440588 xii:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %p}
+} 46740
+test clock-29.1130 {time parsing} {
+ clock scan {2440588 xii:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %p}
+} 46740
+test clock-29.1131 {time parsing} {
+ clock scan {2440588 xii:59:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 46740
+test clock-29.1132 {time parsing} {
+ clock scan {2440588 xii:lix:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 46740
+test clock-29.1133 {time parsing} {
+ clock scan {2440588 xii:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %p}
+} 46740
+test clock-29.1134 {time parsing} {
+ clock scan {2440588 xii:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %p}
+} 46740
+test clock-29.1135 {time parsing} {
+ clock scan {2440588 xii:59:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 46740
+test clock-29.1136 {time parsing} {
+ clock scan {2440588 xii:lix:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 46740
+test clock-29.1137 {time parsing} {
+ clock scan {2440588 12:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %P}
+} 46740
+test clock-29.1138 {time parsing} {
+ clock scan {2440588 12:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %P}
+} 46740
+test clock-29.1139 {time parsing} {
+ clock scan {2440588 12:59:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 46740
+test clock-29.1140 {time parsing} {
+ clock scan {2440588 12:lix:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 46740
+test clock-29.1141 {time parsing} {
+ clock scan {2440588 12:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %P}
+} 46740
+test clock-29.1142 {time parsing} {
+ clock scan {2440588 12:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %P}
+} 46740
+test clock-29.1143 {time parsing} {
+ clock scan {2440588 12:59:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 46740
+test clock-29.1144 {time parsing} {
+ clock scan {2440588 12:lix:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 46740
+test clock-29.1145 {time parsing} {
+ clock scan {2440588 xii:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %P}
+} 46740
+test clock-29.1146 {time parsing} {
+ clock scan {2440588 xii:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %P}
+} 46740
+test clock-29.1147 {time parsing} {
+ clock scan {2440588 xii:59:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 46740
+test clock-29.1148 {time parsing} {
+ clock scan {2440588 xii:lix:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 46740
+test clock-29.1149 {time parsing} {
+ clock scan {2440588 xii:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %P}
+} 46740
+test clock-29.1150 {time parsing} {
+ clock scan {2440588 xii:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %P}
+} 46740
+test clock-29.1151 {time parsing} {
+ clock scan {2440588 xii:59:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 46740
+test clock-29.1152 {time parsing} {
+ clock scan {2440588 xii:lix:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 46740
+test clock-29.1153 {time parsing} {
+ clock scan {2440588 12:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 46741
+test clock-29.1154 {time parsing} {
+ clock scan {2440588 12:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 46741
+test clock-29.1155 {time parsing} {
+ clock scan {2440588 12:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 46741
+test clock-29.1156 {time parsing} {
+ clock scan {2440588 12:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 46741
+test clock-29.1157 {time parsing} {
+ clock scan {2440588 xii:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 46741
+test clock-29.1158 {time parsing} {
+ clock scan {2440588 xii:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 46741
+test clock-29.1159 {time parsing} {
+ clock scan {2440588 xii:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 46741
+test clock-29.1160 {time parsing} {
+ clock scan {2440588 xii:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 46741
+test clock-29.1161 {time parsing} {
+ clock scan {2440588 12:59:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 46741
+test clock-29.1162 {time parsing} {
+ clock scan {2440588 12:lix:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 46741
+test clock-29.1163 {time parsing} {
+ clock scan {2440588 12:59:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 46741
+test clock-29.1164 {time parsing} {
+ clock scan {2440588 12:lix:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 46741
+test clock-29.1165 {time parsing} {
+ clock scan {2440588 xii:59:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 46741
+test clock-29.1166 {time parsing} {
+ clock scan {2440588 xii:lix:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 46741
+test clock-29.1167 {time parsing} {
+ clock scan {2440588 xii:59:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 46741
+test clock-29.1168 {time parsing} {
+ clock scan {2440588 xii:lix:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 46741
+test clock-29.1169 {time parsing} {
+ clock scan {2440588 12:59:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 46741
+test clock-29.1170 {time parsing} {
+ clock scan {2440588 12:lix:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 46741
+test clock-29.1171 {time parsing} {
+ clock scan {2440588 12:59:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 46741
+test clock-29.1172 {time parsing} {
+ clock scan {2440588 12:lix:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 46741
+test clock-29.1173 {time parsing} {
+ clock scan {2440588 xii:59:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 46741
+test clock-29.1174 {time parsing} {
+ clock scan {2440588 xii:lix:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 46741
+test clock-29.1175 {time parsing} {
+ clock scan {2440588 xii:59:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 46741
+test clock-29.1176 {time parsing} {
+ clock scan {2440588 xii:lix:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 46741
+test clock-29.1177 {time parsing} {
+ clock scan {2440588 12:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 46799
+test clock-29.1178 {time parsing} {
+ clock scan {2440588 12:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 46799
+test clock-29.1179 {time parsing} {
+ clock scan {2440588 12:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 46799
+test clock-29.1180 {time parsing} {
+ clock scan {2440588 12:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 46799
+test clock-29.1181 {time parsing} {
+ clock scan {2440588 xii:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 46799
+test clock-29.1182 {time parsing} {
+ clock scan {2440588 xii:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 46799
+test clock-29.1183 {time parsing} {
+ clock scan {2440588 xii:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 46799
+test clock-29.1184 {time parsing} {
+ clock scan {2440588 xii:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 46799
+test clock-29.1185 {time parsing} {
+ clock scan {2440588 12:59:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 46799
+test clock-29.1186 {time parsing} {
+ clock scan {2440588 12:lix:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 46799
+test clock-29.1187 {time parsing} {
+ clock scan {2440588 12:59:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 46799
+test clock-29.1188 {time parsing} {
+ clock scan {2440588 12:lix:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 46799
+test clock-29.1189 {time parsing} {
+ clock scan {2440588 xii:59:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 46799
+test clock-29.1190 {time parsing} {
+ clock scan {2440588 xii:lix:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 46799
+test clock-29.1191 {time parsing} {
+ clock scan {2440588 xii:59:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 46799
+test clock-29.1192 {time parsing} {
+ clock scan {2440588 xii:lix:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 46799
+test clock-29.1193 {time parsing} {
+ clock scan {2440588 12:59:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 46799
+test clock-29.1194 {time parsing} {
+ clock scan {2440588 12:lix:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 46799
+test clock-29.1195 {time parsing} {
+ clock scan {2440588 12:59:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 46799
+test clock-29.1196 {time parsing} {
+ clock scan {2440588 12:lix:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 46799
+test clock-29.1197 {time parsing} {
+ clock scan {2440588 xii:59:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 46799
+test clock-29.1198 {time parsing} {
+ clock scan {2440588 xii:lix:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 46799
+test clock-29.1199 {time parsing} {
+ clock scan {2440588 xii:59:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 46799
+test clock-29.1200 {time parsing} {
+ clock scan {2440588 xii:lix:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 46799
+test clock-29.1201 {time parsing} {
+ clock scan {2440588 13 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H }
+} 46800
+test clock-29.1202 {time parsing} {
+ clock scan {2440588 13:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M }
+} 46800
+test clock-29.1203 {time parsing} {
+ clock scan {2440588 13:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM }
+} 46800
+test clock-29.1204 {time parsing} {
+ clock scan {2440588 13:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 46800
+test clock-29.1205 {time parsing} {
+ clock scan {2440588 13:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 46800
+test clock-29.1206 {time parsing} {
+ clock scan {2440588 13 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k }
+} 46800
+test clock-29.1207 {time parsing} {
+ clock scan {2440588 13:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M }
+} 46800
+test clock-29.1208 {time parsing} {
+ clock scan {2440588 13:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM }
+} 46800
+test clock-29.1209 {time parsing} {
+ clock scan {2440588 13:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 46800
+test clock-29.1210 {time parsing} {
+ clock scan {2440588 13:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 46800
+test clock-29.1211 {time parsing} {
+ clock scan {2440588 xiii } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH }
+} 46800
+test clock-29.1212 {time parsing} {
+ clock scan {2440588 xiii:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M }
+} 46800
+test clock-29.1213 {time parsing} {
+ clock scan {2440588 xiii:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM }
+} 46800
+test clock-29.1214 {time parsing} {
+ clock scan {2440588 xiii:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 46800
+test clock-29.1215 {time parsing} {
+ clock scan {2440588 xiii:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 46800
+test clock-29.1216 {time parsing} {
+ clock scan {2440588 xiii } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok }
+} 46800
+test clock-29.1217 {time parsing} {
+ clock scan {2440588 xiii:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M }
+} 46800
+test clock-29.1218 {time parsing} {
+ clock scan {2440588 xiii:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM }
+} 46800
+test clock-29.1219 {time parsing} {
+ clock scan {2440588 xiii:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 46800
+test clock-29.1220 {time parsing} {
+ clock scan {2440588 xiii:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 46800
+test clock-29.1221 {time parsing} {
+ clock scan {2440588 01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I %p}
+} 46800
+test clock-29.1222 {time parsing} {
+ clock scan {2440588 01:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %p}
+} 46800
+test clock-29.1223 {time parsing} {
+ clock scan {2440588 01:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %p}
+} 46800
+test clock-29.1224 {time parsing} {
+ clock scan {2440588 01:00:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 46800
+test clock-29.1225 {time parsing} {
+ clock scan {2440588 01:?:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 46800
+test clock-29.1226 {time parsing} {
+ clock scan {2440588 1 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l %p}
+} 46800
+test clock-29.1227 {time parsing} {
+ clock scan {2440588 1:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %p}
+} 46800
+test clock-29.1228 {time parsing} {
+ clock scan {2440588 1:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %p}
+} 46800
+test clock-29.1229 {time parsing} {
+ clock scan {2440588 1:00:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 46800
+test clock-29.1230 {time parsing} {
+ clock scan {2440588 1:?:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 46800
+test clock-29.1231 {time parsing} {
+ clock scan {2440588 i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI %p}
+} 46800
+test clock-29.1232 {time parsing} {
+ clock scan {2440588 i:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %p}
+} 46800
+test clock-29.1233 {time parsing} {
+ clock scan {2440588 i:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %p}
+} 46800
+test clock-29.1234 {time parsing} {
+ clock scan {2440588 i:00:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 46800
+test clock-29.1235 {time parsing} {
+ clock scan {2440588 i:?:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 46800
+test clock-29.1236 {time parsing} {
+ clock scan {2440588 i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol %p}
+} 46800
+test clock-29.1237 {time parsing} {
+ clock scan {2440588 i:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %p}
+} 46800
+test clock-29.1238 {time parsing} {
+ clock scan {2440588 i:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %p}
+} 46800
+test clock-29.1239 {time parsing} {
+ clock scan {2440588 i:00:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 46800
+test clock-29.1240 {time parsing} {
+ clock scan {2440588 i:?:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 46800
+test clock-29.1241 {time parsing} {
+ clock scan {2440588 01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I %P}
+} 46800
+test clock-29.1242 {time parsing} {
+ clock scan {2440588 01:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %P}
+} 46800
+test clock-29.1243 {time parsing} {
+ clock scan {2440588 01:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %P}
+} 46800
+test clock-29.1244 {time parsing} {
+ clock scan {2440588 01:00:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 46800
+test clock-29.1245 {time parsing} {
+ clock scan {2440588 01:?:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 46800
+test clock-29.1246 {time parsing} {
+ clock scan {2440588 1 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l %P}
+} 46800
+test clock-29.1247 {time parsing} {
+ clock scan {2440588 1:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %P}
+} 46800
+test clock-29.1248 {time parsing} {
+ clock scan {2440588 1:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %P}
+} 46800
+test clock-29.1249 {time parsing} {
+ clock scan {2440588 1:00:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 46800
+test clock-29.1250 {time parsing} {
+ clock scan {2440588 1:?:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 46800
+test clock-29.1251 {time parsing} {
+ clock scan {2440588 i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI %P}
+} 46800
+test clock-29.1252 {time parsing} {
+ clock scan {2440588 i:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %P}
+} 46800
+test clock-29.1253 {time parsing} {
+ clock scan {2440588 i:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %P}
+} 46800
+test clock-29.1254 {time parsing} {
+ clock scan {2440588 i:00:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 46800
+test clock-29.1255 {time parsing} {
+ clock scan {2440588 i:?:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 46800
+test clock-29.1256 {time parsing} {
+ clock scan {2440588 i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol %P}
+} 46800
+test clock-29.1257 {time parsing} {
+ clock scan {2440588 i:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %P}
+} 46800
+test clock-29.1258 {time parsing} {
+ clock scan {2440588 i:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %P}
+} 46800
+test clock-29.1259 {time parsing} {
+ clock scan {2440588 i:00:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 46800
+test clock-29.1260 {time parsing} {
+ clock scan {2440588 i:?:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 46800
+test clock-29.1261 {time parsing} {
+ clock scan {2440588 13:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 46801
+test clock-29.1262 {time parsing} {
+ clock scan {2440588 13:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 46801
+test clock-29.1263 {time parsing} {
+ clock scan {2440588 13:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 46801
+test clock-29.1264 {time parsing} {
+ clock scan {2440588 13:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 46801
+test clock-29.1265 {time parsing} {
+ clock scan {2440588 xiii:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 46801
+test clock-29.1266 {time parsing} {
+ clock scan {2440588 xiii:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 46801
+test clock-29.1267 {time parsing} {
+ clock scan {2440588 xiii:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 46801
+test clock-29.1268 {time parsing} {
+ clock scan {2440588 xiii:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 46801
+test clock-29.1269 {time parsing} {
+ clock scan {2440588 01:00:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 46801
+test clock-29.1270 {time parsing} {
+ clock scan {2440588 01:?:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 46801
+test clock-29.1271 {time parsing} {
+ clock scan {2440588 1:00:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 46801
+test clock-29.1272 {time parsing} {
+ clock scan {2440588 1:?:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 46801
+test clock-29.1273 {time parsing} {
+ clock scan {2440588 i:00:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 46801
+test clock-29.1274 {time parsing} {
+ clock scan {2440588 i:?:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 46801
+test clock-29.1275 {time parsing} {
+ clock scan {2440588 i:00:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 46801
+test clock-29.1276 {time parsing} {
+ clock scan {2440588 i:?:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 46801
+test clock-29.1277 {time parsing} {
+ clock scan {2440588 01:00:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 46801
+test clock-29.1278 {time parsing} {
+ clock scan {2440588 01:?:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 46801
+test clock-29.1279 {time parsing} {
+ clock scan {2440588 1:00:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 46801
+test clock-29.1280 {time parsing} {
+ clock scan {2440588 1:?:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 46801
+test clock-29.1281 {time parsing} {
+ clock scan {2440588 i:00:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 46801
+test clock-29.1282 {time parsing} {
+ clock scan {2440588 i:?:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 46801
+test clock-29.1283 {time parsing} {
+ clock scan {2440588 i:00:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 46801
+test clock-29.1284 {time parsing} {
+ clock scan {2440588 i:?:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 46801
+test clock-29.1285 {time parsing} {
+ clock scan {2440588 13:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 46859
+test clock-29.1286 {time parsing} {
+ clock scan {2440588 13:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 46859
+test clock-29.1287 {time parsing} {
+ clock scan {2440588 13:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 46859
+test clock-29.1288 {time parsing} {
+ clock scan {2440588 13:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 46859
+test clock-29.1289 {time parsing} {
+ clock scan {2440588 xiii:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 46859
+test clock-29.1290 {time parsing} {
+ clock scan {2440588 xiii:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 46859
+test clock-29.1291 {time parsing} {
+ clock scan {2440588 xiii:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 46859
+test clock-29.1292 {time parsing} {
+ clock scan {2440588 xiii:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 46859
+test clock-29.1293 {time parsing} {
+ clock scan {2440588 01:00:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 46859
+test clock-29.1294 {time parsing} {
+ clock scan {2440588 01:?:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 46859
+test clock-29.1295 {time parsing} {
+ clock scan {2440588 1:00:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 46859
+test clock-29.1296 {time parsing} {
+ clock scan {2440588 1:?:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 46859
+test clock-29.1297 {time parsing} {
+ clock scan {2440588 i:00:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 46859
+test clock-29.1298 {time parsing} {
+ clock scan {2440588 i:?:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 46859
+test clock-29.1299 {time parsing} {
+ clock scan {2440588 i:00:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 46859
+test clock-29.1300 {time parsing} {
+ clock scan {2440588 i:?:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 46859
+test clock-29.1301 {time parsing} {
+ clock scan {2440588 01:00:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 46859
+test clock-29.1302 {time parsing} {
+ clock scan {2440588 01:?:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 46859
+test clock-29.1303 {time parsing} {
+ clock scan {2440588 1:00:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 46859
+test clock-29.1304 {time parsing} {
+ clock scan {2440588 1:?:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 46859
+test clock-29.1305 {time parsing} {
+ clock scan {2440588 i:00:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 46859
+test clock-29.1306 {time parsing} {
+ clock scan {2440588 i:?:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 46859
+test clock-29.1307 {time parsing} {
+ clock scan {2440588 i:00:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 46859
+test clock-29.1308 {time parsing} {
+ clock scan {2440588 i:?:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 46859
+test clock-29.1309 {time parsing} {
+ clock scan {2440588 13:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M }
+} 46860
+test clock-29.1310 {time parsing} {
+ clock scan {2440588 13:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM }
+} 46860
+test clock-29.1311 {time parsing} {
+ clock scan {2440588 13:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 46860
+test clock-29.1312 {time parsing} {
+ clock scan {2440588 13:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 46860
+test clock-29.1313 {time parsing} {
+ clock scan {2440588 13:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M }
+} 46860
+test clock-29.1314 {time parsing} {
+ clock scan {2440588 13:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM }
+} 46860
+test clock-29.1315 {time parsing} {
+ clock scan {2440588 13:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 46860
+test clock-29.1316 {time parsing} {
+ clock scan {2440588 13:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 46860
+test clock-29.1317 {time parsing} {
+ clock scan {2440588 xiii:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M }
+} 46860
+test clock-29.1318 {time parsing} {
+ clock scan {2440588 xiii:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM }
+} 46860
+test clock-29.1319 {time parsing} {
+ clock scan {2440588 xiii:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 46860
+test clock-29.1320 {time parsing} {
+ clock scan {2440588 xiii:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 46860
+test clock-29.1321 {time parsing} {
+ clock scan {2440588 xiii:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M }
+} 46860
+test clock-29.1322 {time parsing} {
+ clock scan {2440588 xiii:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM }
+} 46860
+test clock-29.1323 {time parsing} {
+ clock scan {2440588 xiii:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 46860
+test clock-29.1324 {time parsing} {
+ clock scan {2440588 xiii:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 46860
+test clock-29.1325 {time parsing} {
+ clock scan {2440588 01:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %p}
+} 46860
+test clock-29.1326 {time parsing} {
+ clock scan {2440588 01:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %p}
+} 46860
+test clock-29.1327 {time parsing} {
+ clock scan {2440588 01:01:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 46860
+test clock-29.1328 {time parsing} {
+ clock scan {2440588 01:i:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 46860
+test clock-29.1329 {time parsing} {
+ clock scan {2440588 1:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %p}
+} 46860
+test clock-29.1330 {time parsing} {
+ clock scan {2440588 1:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %p}
+} 46860
+test clock-29.1331 {time parsing} {
+ clock scan {2440588 1:01:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 46860
+test clock-29.1332 {time parsing} {
+ clock scan {2440588 1:i:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 46860
+test clock-29.1333 {time parsing} {
+ clock scan {2440588 i:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %p}
+} 46860
+test clock-29.1334 {time parsing} {
+ clock scan {2440588 i:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %p}
+} 46860
+test clock-29.1335 {time parsing} {
+ clock scan {2440588 i:01:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 46860
+test clock-29.1336 {time parsing} {
+ clock scan {2440588 i:i:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 46860
+test clock-29.1337 {time parsing} {
+ clock scan {2440588 i:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %p}
+} 46860
+test clock-29.1338 {time parsing} {
+ clock scan {2440588 i:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %p}
+} 46860
+test clock-29.1339 {time parsing} {
+ clock scan {2440588 i:01:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 46860
+test clock-29.1340 {time parsing} {
+ clock scan {2440588 i:i:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 46860
+test clock-29.1341 {time parsing} {
+ clock scan {2440588 01:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %P}
+} 46860
+test clock-29.1342 {time parsing} {
+ clock scan {2440588 01:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %P}
+} 46860
+test clock-29.1343 {time parsing} {
+ clock scan {2440588 01:01:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 46860
+test clock-29.1344 {time parsing} {
+ clock scan {2440588 01:i:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 46860
+test clock-29.1345 {time parsing} {
+ clock scan {2440588 1:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %P}
+} 46860
+test clock-29.1346 {time parsing} {
+ clock scan {2440588 1:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %P}
+} 46860
+test clock-29.1347 {time parsing} {
+ clock scan {2440588 1:01:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 46860
+test clock-29.1348 {time parsing} {
+ clock scan {2440588 1:i:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 46860
+test clock-29.1349 {time parsing} {
+ clock scan {2440588 i:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %P}
+} 46860
+test clock-29.1350 {time parsing} {
+ clock scan {2440588 i:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %P}
+} 46860
+test clock-29.1351 {time parsing} {
+ clock scan {2440588 i:01:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 46860
+test clock-29.1352 {time parsing} {
+ clock scan {2440588 i:i:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 46860
+test clock-29.1353 {time parsing} {
+ clock scan {2440588 i:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %P}
+} 46860
+test clock-29.1354 {time parsing} {
+ clock scan {2440588 i:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %P}
+} 46860
+test clock-29.1355 {time parsing} {
+ clock scan {2440588 i:01:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 46860
+test clock-29.1356 {time parsing} {
+ clock scan {2440588 i:i:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 46860
+test clock-29.1357 {time parsing} {
+ clock scan {2440588 13:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 46861
+test clock-29.1358 {time parsing} {
+ clock scan {2440588 13:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 46861
+test clock-29.1359 {time parsing} {
+ clock scan {2440588 13:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 46861
+test clock-29.1360 {time parsing} {
+ clock scan {2440588 13:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 46861
+test clock-29.1361 {time parsing} {
+ clock scan {2440588 xiii:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 46861
+test clock-29.1362 {time parsing} {
+ clock scan {2440588 xiii:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 46861
+test clock-29.1363 {time parsing} {
+ clock scan {2440588 xiii:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 46861
+test clock-29.1364 {time parsing} {
+ clock scan {2440588 xiii:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 46861
+test clock-29.1365 {time parsing} {
+ clock scan {2440588 01:01:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 46861
+test clock-29.1366 {time parsing} {
+ clock scan {2440588 01:i:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 46861
+test clock-29.1367 {time parsing} {
+ clock scan {2440588 1:01:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 46861
+test clock-29.1368 {time parsing} {
+ clock scan {2440588 1:i:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 46861
+test clock-29.1369 {time parsing} {
+ clock scan {2440588 i:01:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 46861
+test clock-29.1370 {time parsing} {
+ clock scan {2440588 i:i:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 46861
+test clock-29.1371 {time parsing} {
+ clock scan {2440588 i:01:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 46861
+test clock-29.1372 {time parsing} {
+ clock scan {2440588 i:i:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 46861
+test clock-29.1373 {time parsing} {
+ clock scan {2440588 01:01:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 46861
+test clock-29.1374 {time parsing} {
+ clock scan {2440588 01:i:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 46861
+test clock-29.1375 {time parsing} {
+ clock scan {2440588 1:01:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 46861
+test clock-29.1376 {time parsing} {
+ clock scan {2440588 1:i:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 46861
+test clock-29.1377 {time parsing} {
+ clock scan {2440588 i:01:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 46861
+test clock-29.1378 {time parsing} {
+ clock scan {2440588 i:i:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 46861
+test clock-29.1379 {time parsing} {
+ clock scan {2440588 i:01:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 46861
+test clock-29.1380 {time parsing} {
+ clock scan {2440588 i:i:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 46861
+test clock-29.1381 {time parsing} {
+ clock scan {2440588 13:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 46919
+test clock-29.1382 {time parsing} {
+ clock scan {2440588 13:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 46919
+test clock-29.1383 {time parsing} {
+ clock scan {2440588 13:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 46919
+test clock-29.1384 {time parsing} {
+ clock scan {2440588 13:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 46919
+test clock-29.1385 {time parsing} {
+ clock scan {2440588 xiii:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 46919
+test clock-29.1386 {time parsing} {
+ clock scan {2440588 xiii:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 46919
+test clock-29.1387 {time parsing} {
+ clock scan {2440588 xiii:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 46919
+test clock-29.1388 {time parsing} {
+ clock scan {2440588 xiii:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 46919
+test clock-29.1389 {time parsing} {
+ clock scan {2440588 01:01:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 46919
+test clock-29.1390 {time parsing} {
+ clock scan {2440588 01:i:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 46919
+test clock-29.1391 {time parsing} {
+ clock scan {2440588 1:01:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 46919
+test clock-29.1392 {time parsing} {
+ clock scan {2440588 1:i:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 46919
+test clock-29.1393 {time parsing} {
+ clock scan {2440588 i:01:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 46919
+test clock-29.1394 {time parsing} {
+ clock scan {2440588 i:i:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 46919
+test clock-29.1395 {time parsing} {
+ clock scan {2440588 i:01:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 46919
+test clock-29.1396 {time parsing} {
+ clock scan {2440588 i:i:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 46919
+test clock-29.1397 {time parsing} {
+ clock scan {2440588 01:01:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 46919
+test clock-29.1398 {time parsing} {
+ clock scan {2440588 01:i:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 46919
+test clock-29.1399 {time parsing} {
+ clock scan {2440588 1:01:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 46919
+test clock-29.1400 {time parsing} {
+ clock scan {2440588 1:i:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 46919
+test clock-29.1401 {time parsing} {
+ clock scan {2440588 i:01:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 46919
+test clock-29.1402 {time parsing} {
+ clock scan {2440588 i:i:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 46919
+test clock-29.1403 {time parsing} {
+ clock scan {2440588 i:01:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 46919
+test clock-29.1404 {time parsing} {
+ clock scan {2440588 i:i:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 46919
+test clock-29.1405 {time parsing} {
+ clock scan {2440588 13:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M }
+} 50340
+test clock-29.1406 {time parsing} {
+ clock scan {2440588 13:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM }
+} 50340
+test clock-29.1407 {time parsing} {
+ clock scan {2440588 13:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 50340
+test clock-29.1408 {time parsing} {
+ clock scan {2440588 13:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 50340
+test clock-29.1409 {time parsing} {
+ clock scan {2440588 13:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M }
+} 50340
+test clock-29.1410 {time parsing} {
+ clock scan {2440588 13:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM }
+} 50340
+test clock-29.1411 {time parsing} {
+ clock scan {2440588 13:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 50340
+test clock-29.1412 {time parsing} {
+ clock scan {2440588 13:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 50340
+test clock-29.1413 {time parsing} {
+ clock scan {2440588 xiii:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M }
+} 50340
+test clock-29.1414 {time parsing} {
+ clock scan {2440588 xiii:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM }
+} 50340
+test clock-29.1415 {time parsing} {
+ clock scan {2440588 xiii:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 50340
+test clock-29.1416 {time parsing} {
+ clock scan {2440588 xiii:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 50340
+test clock-29.1417 {time parsing} {
+ clock scan {2440588 xiii:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M }
+} 50340
+test clock-29.1418 {time parsing} {
+ clock scan {2440588 xiii:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM }
+} 50340
+test clock-29.1419 {time parsing} {
+ clock scan {2440588 xiii:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 50340
+test clock-29.1420 {time parsing} {
+ clock scan {2440588 xiii:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 50340
+test clock-29.1421 {time parsing} {
+ clock scan {2440588 01:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %p}
+} 50340
+test clock-29.1422 {time parsing} {
+ clock scan {2440588 01:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %p}
+} 50340
+test clock-29.1423 {time parsing} {
+ clock scan {2440588 01:59:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 50340
+test clock-29.1424 {time parsing} {
+ clock scan {2440588 01:lix:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 50340
+test clock-29.1425 {time parsing} {
+ clock scan {2440588 1:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %p}
+} 50340
+test clock-29.1426 {time parsing} {
+ clock scan {2440588 1:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %p}
+} 50340
+test clock-29.1427 {time parsing} {
+ clock scan {2440588 1:59:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 50340
+test clock-29.1428 {time parsing} {
+ clock scan {2440588 1:lix:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 50340
+test clock-29.1429 {time parsing} {
+ clock scan {2440588 i:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %p}
+} 50340
+test clock-29.1430 {time parsing} {
+ clock scan {2440588 i:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %p}
+} 50340
+test clock-29.1431 {time parsing} {
+ clock scan {2440588 i:59:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 50340
+test clock-29.1432 {time parsing} {
+ clock scan {2440588 i:lix:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 50340
+test clock-29.1433 {time parsing} {
+ clock scan {2440588 i:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %p}
+} 50340
+test clock-29.1434 {time parsing} {
+ clock scan {2440588 i:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %p}
+} 50340
+test clock-29.1435 {time parsing} {
+ clock scan {2440588 i:59:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 50340
+test clock-29.1436 {time parsing} {
+ clock scan {2440588 i:lix:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 50340
+test clock-29.1437 {time parsing} {
+ clock scan {2440588 01:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %P}
+} 50340
+test clock-29.1438 {time parsing} {
+ clock scan {2440588 01:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %P}
+} 50340
+test clock-29.1439 {time parsing} {
+ clock scan {2440588 01:59:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 50340
+test clock-29.1440 {time parsing} {
+ clock scan {2440588 01:lix:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 50340
+test clock-29.1441 {time parsing} {
+ clock scan {2440588 1:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %P}
+} 50340
+test clock-29.1442 {time parsing} {
+ clock scan {2440588 1:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %P}
+} 50340
+test clock-29.1443 {time parsing} {
+ clock scan {2440588 1:59:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 50340
+test clock-29.1444 {time parsing} {
+ clock scan {2440588 1:lix:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 50340
+test clock-29.1445 {time parsing} {
+ clock scan {2440588 i:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %P}
+} 50340
+test clock-29.1446 {time parsing} {
+ clock scan {2440588 i:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %P}
+} 50340
+test clock-29.1447 {time parsing} {
+ clock scan {2440588 i:59:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 50340
+test clock-29.1448 {time parsing} {
+ clock scan {2440588 i:lix:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 50340
+test clock-29.1449 {time parsing} {
+ clock scan {2440588 i:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %P}
+} 50340
+test clock-29.1450 {time parsing} {
+ clock scan {2440588 i:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %P}
+} 50340
+test clock-29.1451 {time parsing} {
+ clock scan {2440588 i:59:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 50340
+test clock-29.1452 {time parsing} {
+ clock scan {2440588 i:lix:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 50340
+test clock-29.1453 {time parsing} {
+ clock scan {2440588 13:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 50341
+test clock-29.1454 {time parsing} {
+ clock scan {2440588 13:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 50341
+test clock-29.1455 {time parsing} {
+ clock scan {2440588 13:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 50341
+test clock-29.1456 {time parsing} {
+ clock scan {2440588 13:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 50341
+test clock-29.1457 {time parsing} {
+ clock scan {2440588 xiii:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 50341
+test clock-29.1458 {time parsing} {
+ clock scan {2440588 xiii:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 50341
+test clock-29.1459 {time parsing} {
+ clock scan {2440588 xiii:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 50341
+test clock-29.1460 {time parsing} {
+ clock scan {2440588 xiii:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 50341
+test clock-29.1461 {time parsing} {
+ clock scan {2440588 01:59:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 50341
+test clock-29.1462 {time parsing} {
+ clock scan {2440588 01:lix:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 50341
+test clock-29.1463 {time parsing} {
+ clock scan {2440588 1:59:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 50341
+test clock-29.1464 {time parsing} {
+ clock scan {2440588 1:lix:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 50341
+test clock-29.1465 {time parsing} {
+ clock scan {2440588 i:59:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 50341
+test clock-29.1466 {time parsing} {
+ clock scan {2440588 i:lix:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 50341
+test clock-29.1467 {time parsing} {
+ clock scan {2440588 i:59:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 50341
+test clock-29.1468 {time parsing} {
+ clock scan {2440588 i:lix:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 50341
+test clock-29.1469 {time parsing} {
+ clock scan {2440588 01:59:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 50341
+test clock-29.1470 {time parsing} {
+ clock scan {2440588 01:lix:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 50341
+test clock-29.1471 {time parsing} {
+ clock scan {2440588 1:59:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 50341
+test clock-29.1472 {time parsing} {
+ clock scan {2440588 1:lix:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 50341
+test clock-29.1473 {time parsing} {
+ clock scan {2440588 i:59:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 50341
+test clock-29.1474 {time parsing} {
+ clock scan {2440588 i:lix:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 50341
+test clock-29.1475 {time parsing} {
+ clock scan {2440588 i:59:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 50341
+test clock-29.1476 {time parsing} {
+ clock scan {2440588 i:lix:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 50341
+test clock-29.1477 {time parsing} {
+ clock scan {2440588 13:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 50399
+test clock-29.1478 {time parsing} {
+ clock scan {2440588 13:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 50399
+test clock-29.1479 {time parsing} {
+ clock scan {2440588 13:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 50399
+test clock-29.1480 {time parsing} {
+ clock scan {2440588 13:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 50399
+test clock-29.1481 {time parsing} {
+ clock scan {2440588 xiii:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 50399
+test clock-29.1482 {time parsing} {
+ clock scan {2440588 xiii:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 50399
+test clock-29.1483 {time parsing} {
+ clock scan {2440588 xiii:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 50399
+test clock-29.1484 {time parsing} {
+ clock scan {2440588 xiii:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 50399
+test clock-29.1485 {time parsing} {
+ clock scan {2440588 01:59:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 50399
+test clock-29.1486 {time parsing} {
+ clock scan {2440588 01:lix:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 50399
+test clock-29.1487 {time parsing} {
+ clock scan {2440588 1:59:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 50399
+test clock-29.1488 {time parsing} {
+ clock scan {2440588 1:lix:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 50399
+test clock-29.1489 {time parsing} {
+ clock scan {2440588 i:59:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 50399
+test clock-29.1490 {time parsing} {
+ clock scan {2440588 i:lix:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 50399
+test clock-29.1491 {time parsing} {
+ clock scan {2440588 i:59:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 50399
+test clock-29.1492 {time parsing} {
+ clock scan {2440588 i:lix:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 50399
+test clock-29.1493 {time parsing} {
+ clock scan {2440588 01:59:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 50399
+test clock-29.1494 {time parsing} {
+ clock scan {2440588 01:lix:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 50399
+test clock-29.1495 {time parsing} {
+ clock scan {2440588 1:59:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 50399
+test clock-29.1496 {time parsing} {
+ clock scan {2440588 1:lix:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 50399
+test clock-29.1497 {time parsing} {
+ clock scan {2440588 i:59:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 50399
+test clock-29.1498 {time parsing} {
+ clock scan {2440588 i:lix:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 50399
+test clock-29.1499 {time parsing} {
+ clock scan {2440588 i:59:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 50399
+test clock-29.1500 {time parsing} {
+ clock scan {2440588 i:lix:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 50399
+test clock-29.1501 {time parsing} {
+ clock scan {2440588 23 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H }
+} 82800
+test clock-29.1502 {time parsing} {
+ clock scan {2440588 23:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M }
+} 82800
+test clock-29.1503 {time parsing} {
+ clock scan {2440588 23:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM }
+} 82800
+test clock-29.1504 {time parsing} {
+ clock scan {2440588 23:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 82800
+test clock-29.1505 {time parsing} {
+ clock scan {2440588 23:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 82800
+test clock-29.1506 {time parsing} {
+ clock scan {2440588 23 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k }
+} 82800
+test clock-29.1507 {time parsing} {
+ clock scan {2440588 23:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M }
+} 82800
+test clock-29.1508 {time parsing} {
+ clock scan {2440588 23:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM }
+} 82800
+test clock-29.1509 {time parsing} {
+ clock scan {2440588 23:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 82800
+test clock-29.1510 {time parsing} {
+ clock scan {2440588 23:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 82800
+test clock-29.1511 {time parsing} {
+ clock scan {2440588 xxiii } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH }
+} 82800
+test clock-29.1512 {time parsing} {
+ clock scan {2440588 xxiii:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M }
+} 82800
+test clock-29.1513 {time parsing} {
+ clock scan {2440588 xxiii:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM }
+} 82800
+test clock-29.1514 {time parsing} {
+ clock scan {2440588 xxiii:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 82800
+test clock-29.1515 {time parsing} {
+ clock scan {2440588 xxiii:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 82800
+test clock-29.1516 {time parsing} {
+ clock scan {2440588 xxiii } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok }
+} 82800
+test clock-29.1517 {time parsing} {
+ clock scan {2440588 xxiii:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M }
+} 82800
+test clock-29.1518 {time parsing} {
+ clock scan {2440588 xxiii:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM }
+} 82800
+test clock-29.1519 {time parsing} {
+ clock scan {2440588 xxiii:00:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 82800
+test clock-29.1520 {time parsing} {
+ clock scan {2440588 xxiii:?:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 82800
+test clock-29.1521 {time parsing} {
+ clock scan {2440588 11 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I %p}
+} 82800
+test clock-29.1522 {time parsing} {
+ clock scan {2440588 11:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %p}
+} 82800
+test clock-29.1523 {time parsing} {
+ clock scan {2440588 11:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %p}
+} 82800
+test clock-29.1524 {time parsing} {
+ clock scan {2440588 11:00:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 82800
+test clock-29.1525 {time parsing} {
+ clock scan {2440588 11:?:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 82800
+test clock-29.1526 {time parsing} {
+ clock scan {2440588 11 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l %p}
+} 82800
+test clock-29.1527 {time parsing} {
+ clock scan {2440588 11:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %p}
+} 82800
+test clock-29.1528 {time parsing} {
+ clock scan {2440588 11:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %p}
+} 82800
+test clock-29.1529 {time parsing} {
+ clock scan {2440588 11:00:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 82800
+test clock-29.1530 {time parsing} {
+ clock scan {2440588 11:?:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 82800
+test clock-29.1531 {time parsing} {
+ clock scan {2440588 xi PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI %p}
+} 82800
+test clock-29.1532 {time parsing} {
+ clock scan {2440588 xi:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %p}
+} 82800
+test clock-29.1533 {time parsing} {
+ clock scan {2440588 xi:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %p}
+} 82800
+test clock-29.1534 {time parsing} {
+ clock scan {2440588 xi:00:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 82800
+test clock-29.1535 {time parsing} {
+ clock scan {2440588 xi:?:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 82800
+test clock-29.1536 {time parsing} {
+ clock scan {2440588 xi PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol %p}
+} 82800
+test clock-29.1537 {time parsing} {
+ clock scan {2440588 xi:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %p}
+} 82800
+test clock-29.1538 {time parsing} {
+ clock scan {2440588 xi:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %p}
+} 82800
+test clock-29.1539 {time parsing} {
+ clock scan {2440588 xi:00:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 82800
+test clock-29.1540 {time parsing} {
+ clock scan {2440588 xi:?:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 82800
+test clock-29.1541 {time parsing} {
+ clock scan {2440588 11 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I %P}
+} 82800
+test clock-29.1542 {time parsing} {
+ clock scan {2440588 11:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %P}
+} 82800
+test clock-29.1543 {time parsing} {
+ clock scan {2440588 11:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %P}
+} 82800
+test clock-29.1544 {time parsing} {
+ clock scan {2440588 11:00:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 82800
+test clock-29.1545 {time parsing} {
+ clock scan {2440588 11:?:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 82800
+test clock-29.1546 {time parsing} {
+ clock scan {2440588 11 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l %P}
+} 82800
+test clock-29.1547 {time parsing} {
+ clock scan {2440588 11:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %P}
+} 82800
+test clock-29.1548 {time parsing} {
+ clock scan {2440588 11:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %P}
+} 82800
+test clock-29.1549 {time parsing} {
+ clock scan {2440588 11:00:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 82800
+test clock-29.1550 {time parsing} {
+ clock scan {2440588 11:?:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 82800
+test clock-29.1551 {time parsing} {
+ clock scan {2440588 xi pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI %P}
+} 82800
+test clock-29.1552 {time parsing} {
+ clock scan {2440588 xi:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %P}
+} 82800
+test clock-29.1553 {time parsing} {
+ clock scan {2440588 xi:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %P}
+} 82800
+test clock-29.1554 {time parsing} {
+ clock scan {2440588 xi:00:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 82800
+test clock-29.1555 {time parsing} {
+ clock scan {2440588 xi:?:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 82800
+test clock-29.1556 {time parsing} {
+ clock scan {2440588 xi pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol %P}
+} 82800
+test clock-29.1557 {time parsing} {
+ clock scan {2440588 xi:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %P}
+} 82800
+test clock-29.1558 {time parsing} {
+ clock scan {2440588 xi:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %P}
+} 82800
+test clock-29.1559 {time parsing} {
+ clock scan {2440588 xi:00:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 82800
+test clock-29.1560 {time parsing} {
+ clock scan {2440588 xi:?:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 82800
+test clock-29.1561 {time parsing} {
+ clock scan {2440588 23:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 82801
+test clock-29.1562 {time parsing} {
+ clock scan {2440588 23:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 82801
+test clock-29.1563 {time parsing} {
+ clock scan {2440588 23:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 82801
+test clock-29.1564 {time parsing} {
+ clock scan {2440588 23:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 82801
+test clock-29.1565 {time parsing} {
+ clock scan {2440588 xxiii:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 82801
+test clock-29.1566 {time parsing} {
+ clock scan {2440588 xxiii:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 82801
+test clock-29.1567 {time parsing} {
+ clock scan {2440588 xxiii:00:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 82801
+test clock-29.1568 {time parsing} {
+ clock scan {2440588 xxiii:?:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 82801
+test clock-29.1569 {time parsing} {
+ clock scan {2440588 11:00:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 82801
+test clock-29.1570 {time parsing} {
+ clock scan {2440588 11:?:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 82801
+test clock-29.1571 {time parsing} {
+ clock scan {2440588 11:00:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 82801
+test clock-29.1572 {time parsing} {
+ clock scan {2440588 11:?:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 82801
+test clock-29.1573 {time parsing} {
+ clock scan {2440588 xi:00:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 82801
+test clock-29.1574 {time parsing} {
+ clock scan {2440588 xi:?:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 82801
+test clock-29.1575 {time parsing} {
+ clock scan {2440588 xi:00:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 82801
+test clock-29.1576 {time parsing} {
+ clock scan {2440588 xi:?:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 82801
+test clock-29.1577 {time parsing} {
+ clock scan {2440588 11:00:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 82801
+test clock-29.1578 {time parsing} {
+ clock scan {2440588 11:?:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 82801
+test clock-29.1579 {time parsing} {
+ clock scan {2440588 11:00:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 82801
+test clock-29.1580 {time parsing} {
+ clock scan {2440588 11:?:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 82801
+test clock-29.1581 {time parsing} {
+ clock scan {2440588 xi:00:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 82801
+test clock-29.1582 {time parsing} {
+ clock scan {2440588 xi:?:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 82801
+test clock-29.1583 {time parsing} {
+ clock scan {2440588 xi:00:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 82801
+test clock-29.1584 {time parsing} {
+ clock scan {2440588 xi:?:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 82801
+test clock-29.1585 {time parsing} {
+ clock scan {2440588 23:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 82859
+test clock-29.1586 {time parsing} {
+ clock scan {2440588 23:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 82859
+test clock-29.1587 {time parsing} {
+ clock scan {2440588 23:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 82859
+test clock-29.1588 {time parsing} {
+ clock scan {2440588 23:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 82859
+test clock-29.1589 {time parsing} {
+ clock scan {2440588 xxiii:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 82859
+test clock-29.1590 {time parsing} {
+ clock scan {2440588 xxiii:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 82859
+test clock-29.1591 {time parsing} {
+ clock scan {2440588 xxiii:00:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 82859
+test clock-29.1592 {time parsing} {
+ clock scan {2440588 xxiii:?:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 82859
+test clock-29.1593 {time parsing} {
+ clock scan {2440588 11:00:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 82859
+test clock-29.1594 {time parsing} {
+ clock scan {2440588 11:?:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 82859
+test clock-29.1595 {time parsing} {
+ clock scan {2440588 11:00:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 82859
+test clock-29.1596 {time parsing} {
+ clock scan {2440588 11:?:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 82859
+test clock-29.1597 {time parsing} {
+ clock scan {2440588 xi:00:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 82859
+test clock-29.1598 {time parsing} {
+ clock scan {2440588 xi:?:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 82859
+test clock-29.1599 {time parsing} {
+ clock scan {2440588 xi:00:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 82859
+test clock-29.1600 {time parsing} {
+ clock scan {2440588 xi:?:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 82859
+test clock-29.1601 {time parsing} {
+ clock scan {2440588 11:00:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 82859
+test clock-29.1602 {time parsing} {
+ clock scan {2440588 11:?:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 82859
+test clock-29.1603 {time parsing} {
+ clock scan {2440588 11:00:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 82859
+test clock-29.1604 {time parsing} {
+ clock scan {2440588 11:?:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 82859
+test clock-29.1605 {time parsing} {
+ clock scan {2440588 xi:00:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 82859
+test clock-29.1606 {time parsing} {
+ clock scan {2440588 xi:?:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 82859
+test clock-29.1607 {time parsing} {
+ clock scan {2440588 xi:00:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 82859
+test clock-29.1608 {time parsing} {
+ clock scan {2440588 xi:?:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 82859
+test clock-29.1609 {time parsing} {
+ clock scan {2440588 23:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M }
+} 82860
+test clock-29.1610 {time parsing} {
+ clock scan {2440588 23:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM }
+} 82860
+test clock-29.1611 {time parsing} {
+ clock scan {2440588 23:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 82860
+test clock-29.1612 {time parsing} {
+ clock scan {2440588 23:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 82860
+test clock-29.1613 {time parsing} {
+ clock scan {2440588 23:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M }
+} 82860
+test clock-29.1614 {time parsing} {
+ clock scan {2440588 23:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM }
+} 82860
+test clock-29.1615 {time parsing} {
+ clock scan {2440588 23:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 82860
+test clock-29.1616 {time parsing} {
+ clock scan {2440588 23:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 82860
+test clock-29.1617 {time parsing} {
+ clock scan {2440588 xxiii:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M }
+} 82860
+test clock-29.1618 {time parsing} {
+ clock scan {2440588 xxiii:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM }
+} 82860
+test clock-29.1619 {time parsing} {
+ clock scan {2440588 xxiii:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 82860
+test clock-29.1620 {time parsing} {
+ clock scan {2440588 xxiii:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 82860
+test clock-29.1621 {time parsing} {
+ clock scan {2440588 xxiii:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M }
+} 82860
+test clock-29.1622 {time parsing} {
+ clock scan {2440588 xxiii:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM }
+} 82860
+test clock-29.1623 {time parsing} {
+ clock scan {2440588 xxiii:01:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 82860
+test clock-29.1624 {time parsing} {
+ clock scan {2440588 xxiii:i:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 82860
+test clock-29.1625 {time parsing} {
+ clock scan {2440588 11:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %p}
+} 82860
+test clock-29.1626 {time parsing} {
+ clock scan {2440588 11:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %p}
+} 82860
+test clock-29.1627 {time parsing} {
+ clock scan {2440588 11:01:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 82860
+test clock-29.1628 {time parsing} {
+ clock scan {2440588 11:i:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 82860
+test clock-29.1629 {time parsing} {
+ clock scan {2440588 11:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %p}
+} 82860
+test clock-29.1630 {time parsing} {
+ clock scan {2440588 11:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %p}
+} 82860
+test clock-29.1631 {time parsing} {
+ clock scan {2440588 11:01:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 82860
+test clock-29.1632 {time parsing} {
+ clock scan {2440588 11:i:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 82860
+test clock-29.1633 {time parsing} {
+ clock scan {2440588 xi:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %p}
+} 82860
+test clock-29.1634 {time parsing} {
+ clock scan {2440588 xi:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %p}
+} 82860
+test clock-29.1635 {time parsing} {
+ clock scan {2440588 xi:01:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 82860
+test clock-29.1636 {time parsing} {
+ clock scan {2440588 xi:i:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 82860
+test clock-29.1637 {time parsing} {
+ clock scan {2440588 xi:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %p}
+} 82860
+test clock-29.1638 {time parsing} {
+ clock scan {2440588 xi:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %p}
+} 82860
+test clock-29.1639 {time parsing} {
+ clock scan {2440588 xi:01:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 82860
+test clock-29.1640 {time parsing} {
+ clock scan {2440588 xi:i:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 82860
+test clock-29.1641 {time parsing} {
+ clock scan {2440588 11:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %P}
+} 82860
+test clock-29.1642 {time parsing} {
+ clock scan {2440588 11:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %P}
+} 82860
+test clock-29.1643 {time parsing} {
+ clock scan {2440588 11:01:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 82860
+test clock-29.1644 {time parsing} {
+ clock scan {2440588 11:i:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 82860
+test clock-29.1645 {time parsing} {
+ clock scan {2440588 11:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %P}
+} 82860
+test clock-29.1646 {time parsing} {
+ clock scan {2440588 11:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %P}
+} 82860
+test clock-29.1647 {time parsing} {
+ clock scan {2440588 11:01:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 82860
+test clock-29.1648 {time parsing} {
+ clock scan {2440588 11:i:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 82860
+test clock-29.1649 {time parsing} {
+ clock scan {2440588 xi:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %P}
+} 82860
+test clock-29.1650 {time parsing} {
+ clock scan {2440588 xi:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %P}
+} 82860
+test clock-29.1651 {time parsing} {
+ clock scan {2440588 xi:01:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 82860
+test clock-29.1652 {time parsing} {
+ clock scan {2440588 xi:i:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 82860
+test clock-29.1653 {time parsing} {
+ clock scan {2440588 xi:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %P}
+} 82860
+test clock-29.1654 {time parsing} {
+ clock scan {2440588 xi:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %P}
+} 82860
+test clock-29.1655 {time parsing} {
+ clock scan {2440588 xi:01:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 82860
+test clock-29.1656 {time parsing} {
+ clock scan {2440588 xi:i:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 82860
+test clock-29.1657 {time parsing} {
+ clock scan {2440588 23:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 82861
+test clock-29.1658 {time parsing} {
+ clock scan {2440588 23:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 82861
+test clock-29.1659 {time parsing} {
+ clock scan {2440588 23:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 82861
+test clock-29.1660 {time parsing} {
+ clock scan {2440588 23:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 82861
+test clock-29.1661 {time parsing} {
+ clock scan {2440588 xxiii:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 82861
+test clock-29.1662 {time parsing} {
+ clock scan {2440588 xxiii:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 82861
+test clock-29.1663 {time parsing} {
+ clock scan {2440588 xxiii:01:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 82861
+test clock-29.1664 {time parsing} {
+ clock scan {2440588 xxiii:i:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 82861
+test clock-29.1665 {time parsing} {
+ clock scan {2440588 11:01:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 82861
+test clock-29.1666 {time parsing} {
+ clock scan {2440588 11:i:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 82861
+test clock-29.1667 {time parsing} {
+ clock scan {2440588 11:01:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 82861
+test clock-29.1668 {time parsing} {
+ clock scan {2440588 11:i:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 82861
+test clock-29.1669 {time parsing} {
+ clock scan {2440588 xi:01:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 82861
+test clock-29.1670 {time parsing} {
+ clock scan {2440588 xi:i:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 82861
+test clock-29.1671 {time parsing} {
+ clock scan {2440588 xi:01:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 82861
+test clock-29.1672 {time parsing} {
+ clock scan {2440588 xi:i:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 82861
+test clock-29.1673 {time parsing} {
+ clock scan {2440588 11:01:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 82861
+test clock-29.1674 {time parsing} {
+ clock scan {2440588 11:i:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 82861
+test clock-29.1675 {time parsing} {
+ clock scan {2440588 11:01:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 82861
+test clock-29.1676 {time parsing} {
+ clock scan {2440588 11:i:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 82861
+test clock-29.1677 {time parsing} {
+ clock scan {2440588 xi:01:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 82861
+test clock-29.1678 {time parsing} {
+ clock scan {2440588 xi:i:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 82861
+test clock-29.1679 {time parsing} {
+ clock scan {2440588 xi:01:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 82861
+test clock-29.1680 {time parsing} {
+ clock scan {2440588 xi:i:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 82861
+test clock-29.1681 {time parsing} {
+ clock scan {2440588 23:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 82919
+test clock-29.1682 {time parsing} {
+ clock scan {2440588 23:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 82919
+test clock-29.1683 {time parsing} {
+ clock scan {2440588 23:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 82919
+test clock-29.1684 {time parsing} {
+ clock scan {2440588 23:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 82919
+test clock-29.1685 {time parsing} {
+ clock scan {2440588 xxiii:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 82919
+test clock-29.1686 {time parsing} {
+ clock scan {2440588 xxiii:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 82919
+test clock-29.1687 {time parsing} {
+ clock scan {2440588 xxiii:01:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 82919
+test clock-29.1688 {time parsing} {
+ clock scan {2440588 xxiii:i:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 82919
+test clock-29.1689 {time parsing} {
+ clock scan {2440588 11:01:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 82919
+test clock-29.1690 {time parsing} {
+ clock scan {2440588 11:i:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 82919
+test clock-29.1691 {time parsing} {
+ clock scan {2440588 11:01:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 82919
+test clock-29.1692 {time parsing} {
+ clock scan {2440588 11:i:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 82919
+test clock-29.1693 {time parsing} {
+ clock scan {2440588 xi:01:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 82919
+test clock-29.1694 {time parsing} {
+ clock scan {2440588 xi:i:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 82919
+test clock-29.1695 {time parsing} {
+ clock scan {2440588 xi:01:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 82919
+test clock-29.1696 {time parsing} {
+ clock scan {2440588 xi:i:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 82919
+test clock-29.1697 {time parsing} {
+ clock scan {2440588 11:01:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 82919
+test clock-29.1698 {time parsing} {
+ clock scan {2440588 11:i:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 82919
+test clock-29.1699 {time parsing} {
+ clock scan {2440588 11:01:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 82919
+test clock-29.1700 {time parsing} {
+ clock scan {2440588 11:i:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 82919
+test clock-29.1701 {time parsing} {
+ clock scan {2440588 xi:01:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 82919
+test clock-29.1702 {time parsing} {
+ clock scan {2440588 xi:i:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 82919
+test clock-29.1703 {time parsing} {
+ clock scan {2440588 xi:01:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 82919
+test clock-29.1704 {time parsing} {
+ clock scan {2440588 xi:i:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 82919
+test clock-29.1705 {time parsing} {
+ clock scan {2440588 23:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M }
+} 86340
+test clock-29.1706 {time parsing} {
+ clock scan {2440588 23:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM }
+} 86340
+test clock-29.1707 {time parsing} {
+ clock scan {2440588 23:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 86340
+test clock-29.1708 {time parsing} {
+ clock scan {2440588 23:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 86340
+test clock-29.1709 {time parsing} {
+ clock scan {2440588 23:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M }
+} 86340
+test clock-29.1710 {time parsing} {
+ clock scan {2440588 23:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM }
+} 86340
+test clock-29.1711 {time parsing} {
+ clock scan {2440588 23:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 86340
+test clock-29.1712 {time parsing} {
+ clock scan {2440588 23:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 86340
+test clock-29.1713 {time parsing} {
+ clock scan {2440588 xxiii:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M }
+} 86340
+test clock-29.1714 {time parsing} {
+ clock scan {2440588 xxiii:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM }
+} 86340
+test clock-29.1715 {time parsing} {
+ clock scan {2440588 xxiii:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 86340
+test clock-29.1716 {time parsing} {
+ clock scan {2440588 xxiii:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 86340
+test clock-29.1717 {time parsing} {
+ clock scan {2440588 xxiii:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M }
+} 86340
+test clock-29.1718 {time parsing} {
+ clock scan {2440588 xxiii:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM }
+} 86340
+test clock-29.1719 {time parsing} {
+ clock scan {2440588 xxiii:59:00 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 86340
+test clock-29.1720 {time parsing} {
+ clock scan {2440588 xxiii:lix:? } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 86340
+test clock-29.1721 {time parsing} {
+ clock scan {2440588 11:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %p}
+} 86340
+test clock-29.1722 {time parsing} {
+ clock scan {2440588 11:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %p}
+} 86340
+test clock-29.1723 {time parsing} {
+ clock scan {2440588 11:59:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 86340
+test clock-29.1724 {time parsing} {
+ clock scan {2440588 11:lix:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 86340
+test clock-29.1725 {time parsing} {
+ clock scan {2440588 11:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %p}
+} 86340
+test clock-29.1726 {time parsing} {
+ clock scan {2440588 11:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %p}
+} 86340
+test clock-29.1727 {time parsing} {
+ clock scan {2440588 11:59:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 86340
+test clock-29.1728 {time parsing} {
+ clock scan {2440588 11:lix:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 86340
+test clock-29.1729 {time parsing} {
+ clock scan {2440588 xi:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %p}
+} 86340
+test clock-29.1730 {time parsing} {
+ clock scan {2440588 xi:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %p}
+} 86340
+test clock-29.1731 {time parsing} {
+ clock scan {2440588 xi:59:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 86340
+test clock-29.1732 {time parsing} {
+ clock scan {2440588 xi:lix:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 86340
+test clock-29.1733 {time parsing} {
+ clock scan {2440588 xi:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %p}
+} 86340
+test clock-29.1734 {time parsing} {
+ clock scan {2440588 xi:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %p}
+} 86340
+test clock-29.1735 {time parsing} {
+ clock scan {2440588 xi:59:00 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 86340
+test clock-29.1736 {time parsing} {
+ clock scan {2440588 xi:lix:? PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 86340
+test clock-29.1737 {time parsing} {
+ clock scan {2440588 11:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M %P}
+} 86340
+test clock-29.1738 {time parsing} {
+ clock scan {2440588 11:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM %P}
+} 86340
+test clock-29.1739 {time parsing} {
+ clock scan {2440588 11:59:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 86340
+test clock-29.1740 {time parsing} {
+ clock scan {2440588 11:lix:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 86340
+test clock-29.1741 {time parsing} {
+ clock scan {2440588 11:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M %P}
+} 86340
+test clock-29.1742 {time parsing} {
+ clock scan {2440588 11:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM %P}
+} 86340
+test clock-29.1743 {time parsing} {
+ clock scan {2440588 11:59:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 86340
+test clock-29.1744 {time parsing} {
+ clock scan {2440588 11:lix:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 86340
+test clock-29.1745 {time parsing} {
+ clock scan {2440588 xi:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M %P}
+} 86340
+test clock-29.1746 {time parsing} {
+ clock scan {2440588 xi:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM %P}
+} 86340
+test clock-29.1747 {time parsing} {
+ clock scan {2440588 xi:59:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 86340
+test clock-29.1748 {time parsing} {
+ clock scan {2440588 xi:lix:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 86340
+test clock-29.1749 {time parsing} {
+ clock scan {2440588 xi:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M %P}
+} 86340
+test clock-29.1750 {time parsing} {
+ clock scan {2440588 xi:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM %P}
+} 86340
+test clock-29.1751 {time parsing} {
+ clock scan {2440588 xi:59:00 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 86340
+test clock-29.1752 {time parsing} {
+ clock scan {2440588 xi:lix:? pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 86340
+test clock-29.1753 {time parsing} {
+ clock scan {2440588 23:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 86341
+test clock-29.1754 {time parsing} {
+ clock scan {2440588 23:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 86341
+test clock-29.1755 {time parsing} {
+ clock scan {2440588 23:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 86341
+test clock-29.1756 {time parsing} {
+ clock scan {2440588 23:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 86341
+test clock-29.1757 {time parsing} {
+ clock scan {2440588 xxiii:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 86341
+test clock-29.1758 {time parsing} {
+ clock scan {2440588 xxiii:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 86341
+test clock-29.1759 {time parsing} {
+ clock scan {2440588 xxiii:59:01 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 86341
+test clock-29.1760 {time parsing} {
+ clock scan {2440588 xxiii:lix:i } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 86341
+test clock-29.1761 {time parsing} {
+ clock scan {2440588 11:59:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 86341
+test clock-29.1762 {time parsing} {
+ clock scan {2440588 11:lix:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 86341
+test clock-29.1763 {time parsing} {
+ clock scan {2440588 11:59:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 86341
+test clock-29.1764 {time parsing} {
+ clock scan {2440588 11:lix:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 86341
+test clock-29.1765 {time parsing} {
+ clock scan {2440588 xi:59:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 86341
+test clock-29.1766 {time parsing} {
+ clock scan {2440588 xi:lix:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 86341
+test clock-29.1767 {time parsing} {
+ clock scan {2440588 xi:59:01 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 86341
+test clock-29.1768 {time parsing} {
+ clock scan {2440588 xi:lix:i PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 86341
+test clock-29.1769 {time parsing} {
+ clock scan {2440588 11:59:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 86341
+test clock-29.1770 {time parsing} {
+ clock scan {2440588 11:lix:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 86341
+test clock-29.1771 {time parsing} {
+ clock scan {2440588 11:59:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 86341
+test clock-29.1772 {time parsing} {
+ clock scan {2440588 11:lix:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 86341
+test clock-29.1773 {time parsing} {
+ clock scan {2440588 xi:59:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 86341
+test clock-29.1774 {time parsing} {
+ clock scan {2440588 xi:lix:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 86341
+test clock-29.1775 {time parsing} {
+ clock scan {2440588 xi:59:01 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 86341
+test clock-29.1776 {time parsing} {
+ clock scan {2440588 xi:lix:i pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 86341
+test clock-29.1777 {time parsing} {
+ clock scan {2440588 23:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%M:%S }
+} 86399
+test clock-29.1778 {time parsing} {
+ clock scan {2440588 23:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %H:%OM:%OS }
+} 86399
+test clock-29.1779 {time parsing} {
+ clock scan {2440588 23:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%M:%S }
+} 86399
+test clock-29.1780 {time parsing} {
+ clock scan {2440588 23:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %k:%OM:%OS }
+} 86399
+test clock-29.1781 {time parsing} {
+ clock scan {2440588 xxiii:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%M:%S }
+} 86399
+test clock-29.1782 {time parsing} {
+ clock scan {2440588 xxiii:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %OH:%OM:%OS }
+} 86399
+test clock-29.1783 {time parsing} {
+ clock scan {2440588 xxiii:59:59 } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%M:%S }
+} 86399
+test clock-29.1784 {time parsing} {
+ clock scan {2440588 xxiii:lix:lix } \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ok:%OM:%OS }
+} 86399
+test clock-29.1785 {time parsing} {
+ clock scan {2440588 11:59:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %p}
+} 86399
+test clock-29.1786 {time parsing} {
+ clock scan {2440588 11:lix:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %p}
+} 86399
+test clock-29.1787 {time parsing} {
+ clock scan {2440588 11:59:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %p}
+} 86399
+test clock-29.1788 {time parsing} {
+ clock scan {2440588 11:lix:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %p}
+} 86399
+test clock-29.1789 {time parsing} {
+ clock scan {2440588 xi:59:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %p}
+} 86399
+test clock-29.1790 {time parsing} {
+ clock scan {2440588 xi:lix:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %p}
+} 86399
+test clock-29.1791 {time parsing} {
+ clock scan {2440588 xi:59:59 PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %p}
+} 86399
+test clock-29.1792 {time parsing} {
+ clock scan {2440588 xi:lix:lix PM} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %p}
+} 86399
+test clock-29.1793 {time parsing} {
+ clock scan {2440588 11:59:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%M:%S %P}
+} 86399
+test clock-29.1794 {time parsing} {
+ clock scan {2440588 11:lix:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %I:%OM:%OS %P}
+} 86399
+test clock-29.1795 {time parsing} {
+ clock scan {2440588 11:59:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%M:%S %P}
+} 86399
+test clock-29.1796 {time parsing} {
+ clock scan {2440588 11:lix:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %l:%OM:%OS %P}
+} 86399
+test clock-29.1797 {time parsing} {
+ clock scan {2440588 xi:59:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%M:%S %P}
+} 86399
+test clock-29.1798 {time parsing} {
+ clock scan {2440588 xi:lix:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %OI:%OM:%OS %P}
+} 86399
+test clock-29.1799 {time parsing} {
+ clock scan {2440588 xi:59:59 pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%M:%S %P}
+} 86399
+test clock-29.1800 {time parsing} {
+ clock scan {2440588 xi:lix:lix pm} \
+ -gmt true -locale en_US_roman \
+ -format {%J %Ol:%OM:%OS %P}
+} 86399
+# END testcases29
+
+test clock-30.1 {clock add years} {
+ set t [clock scan 2000-01-01 -format %Y-%m-%d -timezone :UTC]
+ set f [clock add $t 1 year -timezone :UTC]
+ clock format $f -format %Y-%m-%d -timezone :UTC
+} {2001-01-01}
+test clock-30.2 {clock add years - leap day} {
+ set t [clock scan 2000-02-29 -format %Y-%m-%d -timezone :UTC]
+ set f [clock add $t 1 years -timezone :UTC]
+ clock format $f -format %Y-%m-%d -timezone :UTC
+} {2001-02-28}
+test clock-30.3 {clock add months} {
+ set t [clock scan 2000-01-01 -format %Y-%m-%d -timezone :UTC]
+ set f [clock add $t 1 month -timezone :UTC]
+ clock format $f -format %Y-%m-%d -timezone :UTC
+} {2000-02-01}
+test clock-30.4 {clock add months, short month} {
+ set t [clock scan 2000-01-31 -format %Y-%m-%d -timezone :UTC]
+ set f [clock add $t 1 months -timezone :UTC]
+ clock format $f -format %Y-%m-%d -timezone :UTC
+} {2000-02-29}
+test clock-30.5 {clock add months, end of year} {
+ set t [clock scan 2000-12-01 -format %Y-%m-%d -timezone :UTC]
+ set f [clock add $t 1 month -timezone :UTC]
+ clock format $f -format %Y-%m-%d -timezone :UTC
+} {2001-01-01}
+test clock-30.6 {clock add months, one year one month vs 13 months} {
+ set t [clock scan 2000-02-29 -format %Y-%m-%d -timezone :UTC]
+ set f1 [clock add $t 1 year 1 month -timezone :UTC]
+ set f2 [clock add $t 13 months -timezone :UTC]
+ set x1 [clock format $f1 -format %Y-%m-%d -timezone :UTC]
+ set x2 [clock format $f2 -format %Y-%m-%d -timezone :UTC]
+ list $x1 $x2
+} {2001-03-28 2001-03-29}
+test clock-30.7 {clock add months, 1 year 1 month vs 1 month 1 year} {
+ set t [clock scan 2000-02-29 -format %Y-%m-%d -timezone :UTC]
+ set f1 [clock add $t 1 year 1 month -timezone :UTC]
+ set f2 [clock add $t 1 month 1 year -timezone :UTC]
+ set x1 [clock format $f1 -format %Y-%m-%d -timezone :UTC]
+ set x2 [clock format $f2 -format %Y-%m-%d -timezone :UTC]
+ list $x1 $x2
+} {2001-03-28 2001-03-29}
+test clock-30.8 {clock add months, negative} {
+ set t [clock scan 2000-03-31 -format %Y-%m-%d -timezone :UTC]
+ set f1 [clock add $t -1 month -timezone :UTC]
+ set f2 [clock add $t -2 month -timezone :UTC]
+ set f3 [clock add $t -3 month -timezone :UTC]
+ set f4 [clock add $t -4 month -timezone :UTC]
+ set x1 [clock format $f1 -format %Y-%m-%d -timezone :UTC]
+ set x2 [clock format $f2 -format %Y-%m-%d -timezone :UTC]
+ set x3 [clock format $f3 -format %Y-%m-%d -timezone :UTC]
+ set x4 [clock format $f4 -format %Y-%m-%d -timezone :UTC]
+ list $x1 $x2 $x3 $x4
+} {2000-02-29 2000-01-31 1999-12-31 1999-11-30}
+test clock-30.9 {clock add days} {
+ set t [clock scan {2000-01-01 12:34:56} -format {%Y-%m-%d %H:%M:%S} \
+ -timezone :UTC]
+ set f1 [clock add $t 1 day -timezone :UTC]
+ set f2 [clock add $t -1 day -timezone :UTC]
+ set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S} -timezone :UTC]
+ set x2 [clock format $f2 -format {%Y-%m-%d %H:%M:%S} -timezone :UTC]
+ list $x1 $x2
+} {{2000-01-02 12:34:56} {1999-12-31 12:34:56}}
+test clock-30.10 {clock add days, spring DST conversion, before} {
+ set t [clock scan {2004-04-03 01:59:59} -format {%Y-%m-%d %H:%M:%S} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set f1 [clock add $t 1 day \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set f2 [clock add $t 2 days \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set x2 [clock format $f2 -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ list $x1 $x2
+} {{2004-04-04 01:59:59 -0500} {2004-04-05 01:59:59 -0400}}
+test clock-30.11 {clock add days, spring DST conversion, bad case} {
+ set t [clock scan {2004-04-03 02:30:00} -format {%Y-%m-%d %H:%M:%S} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set f1 [clock add $t 1 day \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set f2 [clock add $t 2 day \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set x2 [clock format $f2 -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ list $x1 $x2
+} {{2004-04-04 03:30:00 -0400} {2004-04-05 02:30:00 -0400}}
+test clock-30.12 {clock add days, spring DST conversion, after} {
+ set t [clock scan {2004-04-03 03:00:00} -format {%Y-%m-%d %H:%M:%S} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set f1 [clock add $t 1 day -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set f2 [clock add $t 2 day -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set x2 [clock format $f2 -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ list $x1 $x2
+} {{2004-04-04 03:00:00 -0400} {2004-04-05 03:00:00 -0400}}
+test clock-30.13 {clock add days, fall DST conversion, before} {
+ set t [clock scan {2004-10-30 00:59:59} -format {%Y-%m-%d %H:%M:%S} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set f1 [clock add $t 1 day \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set f2 [clock add $t 2 day \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set x2 [clock format $f2 -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ list $x1 $x2
+} {{2004-10-31 00:59:59 -0400} {2004-11-01 00:59:59 -0500}}
+test clock-30.14 {clock add days, fall DST conversion, bad case} {
+ set t [clock scan {2004-10-30 01:30:00} -format {%Y-%m-%d %H:%M:%S} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set f1 [clock add $t 1 day \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set f2 [clock add $t 2 day \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set x2 [clock format $f2 -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ list $x1 $x2
+} {{2004-10-31 01:30:00 -0400} {2004-11-01 01:30:00 -0500}}
+test clock-30.15 {clock add days, fall DST conversion, after} {
+ set t [clock scan {2004-10-30 02:30:00} -format {%Y-%m-%d %H:%M:%S} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set f1 [clock add $t 1 day \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set f2 [clock add $t 2 day \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set x2 [clock format $f2 -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ list $x1 $x2
+} {{2004-10-31 02:30:00 -0500} {2004-11-01 02:30:00 -0500}}
+test clock-30.16 {clock add weeks} {
+ set t [clock scan {2000-01-01 12:34:56} -format {%Y-%m-%d %H:%M:%S} \
+ -timezone :UTC]
+ set f1 [clock add $t 1 week -timezone :UTC]
+ set f2 [clock add $t -1 weeks -timezone :UTC]
+ set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S} -timezone :UTC]
+ set x2 [clock format $f2 -format {%Y-%m-%d %H:%M:%S} -timezone :UTC]
+ list $x1 $x2
+} {{2000-01-08 12:34:56} {1999-12-25 12:34:56}}
+test clock-30.17 {clock add hours} {
+ set t [clock scan {2000-01-01 12:34:56} -format {%Y-%m-%d %H:%M:%S} \
+ -timezone :UTC]
+ set f1 [clock add $t 1 hour -timezone :UTC]
+ set f2 [clock add $t -1 hours -timezone :UTC]
+ set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S} -timezone :UTC]
+ set x2 [clock format $f2 -format {%Y-%m-%d %H:%M:%S} -timezone :UTC]
+ list $x1 $x2
+} {{2000-01-01 13:34:56} {2000-01-01 11:34:56}}
+test clock-30.18 {clock add hours at DST conversion} {
+ set t [clock scan {2004-04-04 01:00:00 -0500} \
+ -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set f1 [clock add $t 1 hour -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+} {2004-04-04 03:00:00 -0400}
+test clock-30.19 {clock add hours at DST conversion} {
+ set t [clock scan {2004-10-31 01:00:00 -0400} \
+ -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set f1 [clock add $t 1 hour \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+} {2004-10-31 01:00:00 -0500}
+test clock-30.20 {clock add minutes} {
+ set t [clock scan {2000-01-01 12:34:56} -format {%Y-%m-%d %H:%M:%S} \
+ -timezone :UTC]
+ set f1 [clock add $t 60 minute -timezone :UTC]
+ set f2 [clock add $t -60 minutes -timezone :UTC]
+ set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S} -timezone :UTC]
+ set x2 [clock format $f2 -format {%Y-%m-%d %H:%M:%S} -timezone :UTC]
+ list $x1 $x2
+} {{2000-01-01 13:34:56} {2000-01-01 11:34:56}}
+test clock-30.21 {clock add minutes at DST conversion} {
+ set t [clock scan {2004-04-04 01:00:00 -0500} \
+ -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set f1 [clock add $t 60 minutes \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+} {2004-04-04 03:00:00 -0400}
+test clock-30.22 {clock add minutes at DST conversion} {
+ set t [clock scan {2004-10-31 01:00:00 -0400} \
+ -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set f1 [clock add $t 60 minutes \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+} {2004-10-31 01:00:00 -0500}
+test clock-30.23 {clock add seconds} {
+ set t [clock scan {2000-01-01 12:34:56} -format {%Y-%m-%d %H:%M:%S} \
+ -timezone :UTC]
+ set f1 [clock add $t 3600 second -timezone :UTC]
+ set f2 [clock add $t -3600 seconds -timezone :UTC]
+ set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S} -timezone :UTC]
+ set x2 [clock format $f2 -format {%Y-%m-%d %H:%M:%S} -timezone :UTC]
+ list $x1 $x2
+} {{2000-01-01 13:34:56} {2000-01-01 11:34:56}}
+test clock-30.24 {clock add seconds at DST conversion} {
+ set t [clock scan {2004-04-04 01:00:00 -0500} \
+ -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set f1 [clock add $t 3600 seconds \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+} {2004-04-04 03:00:00 -0400}
+test clock-30.25 {clock add seconds at DST conversion} {
+ set t [clock scan {2004-10-31 01:00:00 -0400} \
+ -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set f1 [clock add $t 3600 seconds -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+ set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S %z} \
+ -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
+} {2004-10-31 01:00:00 -0500}
+
+test clock-31.1 {system locale} \
+ -constraints win \
+ -setup {
+ namespace eval ::tcl::clock {
+ namespace import -force ::testClock::registry
+ }
+ set noreg [info exists ::tcl::clock::NoRegistry]
+ if {$noreg} {unset ::tcl::clock::NoRegistry}
+ ::tcl::clock::ClearCaches
+ } \
+ -body {
+ clock format 0 -timezone :UTC -locale system -format %x
+ } \
+ -cleanup {
+ namespace eval ::tcl::clock {
+ rename registry {}
+ }
+ if {$noreg} {set ::tcl::clock::NoRegistry {}}
+ ::tcl::clock::ClearCaches
+ } \
+ -result [clock format 0 -timezone :UTC -locale current \
+ -format {%d-%b-%Y}]
+
+test clock-31.2 {system locale} \
+ -constraints win \
+ -setup {
+ namespace eval ::tcl::clock {
+ namespace import -force ::testClock::registry
+ }
+ set noreg [info exists ::tcl::clock::NoRegistry]
+ if {$noreg} {unset ::tcl::clock::NoRegistry}
+ ::tcl::clock::ClearCaches
+ } \
+ -body {
+ clock format 0 -timezone :UTC -locale system -format %Ex
+ } \
+ -cleanup {
+ namespace eval ::tcl::clock {
+ rename registry {}
+ }
+ if {$noreg} {set ::tcl::clock::NoRegistry {}}
+ ::tcl::clock::ClearCaches
+ } \
+ -result [clock format 0 -timezone :UTC -locale current \
+ -format {the %d' day of %B %Y}]
+
+test clock-31.3 {system locale} \
+ -constraints win \
+ -setup {
+ namespace eval ::tcl::clock {
+ namespace import -force ::testClock::registry
+ }
+ set noreg [info exists ::tcl::clock::NoRegistry]
+ if {$noreg} {unset ::tcl::clock::NoRegistry}
+ ::tcl::clock::ClearCaches
+ } \
+ -body {
+ clock format 0 -timezone :UTC -locale system -format %X
+ } \
+ -cleanup {
+ namespace eval ::tcl::clock {
+ rename registry {}
+ }
+ if {$noreg} {set ::tcl::clock::NoRegistry {}}
+ ::tcl::clock::ClearCaches
+ } \
+ -result [clock format 0 -timezone :UTC -locale current \
+ -format {%l:%M:%S %p}]
+
+test clock-31.4 {system locale} \
+ -constraints win \
+ -setup {
+ namespace eval ::tcl::clock {
+ namespace import -force ::testClock::registry
+ }
+ set noreg [info exists ::tcl::clock::NoRegistry]
+ if {$noreg} {unset ::tcl::clock::NoRegistry}
+ if { [info exists env(TZ)] } {
+ set oldTZ $env(TZ)
+ unset env(TZ)
+ }
+ if { [info exists env(TCL_TZ)] } {
+ set oldTclTZ $env(TCL_TZ)
+ unset env(TCL_TZ)
+ }
+ ::tcl::clock::ClearCaches
+ } \
+ -body {
+ clock format 0 -locale system -format %x
+ } \
+ -cleanup {
+ namespace eval ::tcl::clock {
+ rename registry {}
+ }
+ if { [info exists oldTclTZ] } {
+ set env(TCL_TZ) $oldTclTZ
+ }
+ if { [info exists oldTZ] } {
+ set env(TZ) $oldTZ
+ }
+ if {$noreg} {set ::tcl::clock::NoRegistry {}}
+ ::tcl::clock::ClearCaches
+ } \
+ -result [clock format 0 -locale current -timezone EST5 \
+ -format {%d-%b-%Y}]
+
+test clock-31.5 {system locale} \
+ -constraints win \
+ -setup {
+ namespace eval ::tcl::clock {
+ namespace import -force ::testClock::registry
+ }
+ set noreg [info exists ::tcl::clock::NoRegistry]
+ if {$noreg} {unset ::tcl::clock::NoRegistry}
+ if { [info exists env(TZ)] } {
+ set oldTZ $env(TZ)
+ unset env(TZ)
+ }
+ if { [info exists env(TCL_TZ)] } {
+ set oldTclTZ $env(TCL_TZ)
+ unset env(TCL_TZ)
+ }
+ ::tcl::clock::ClearCaches
+ } \
+ -body {
+ clock format 0 -locale system -format %Ex
+ } \
+ -cleanup {
+ namespace eval ::tcl::clock {
+ rename registry {}
+ }
+ if {$noreg} {set ::tcl::clock::NoRegistry {}}
+ if { [info exists oldTclTZ] } {
+ set env(TCL_TZ) $oldTclTZ
+ }
+ if { [info exists oldTZ] } {
+ set env(TZ) $oldTZ
+ }
+ ::tcl::clock::ClearCaches
+ } \
+ -result [clock format 0 -locale current -timezone EST5 \
+ -format {the %d' day of %B %Y}]
+
+test clock-31.6 {system locale} \
+ -constraints win \
+ -setup {
+ namespace eval ::tcl::clock {
+ namespace import -force ::testClock::registry
+ }
+ set noreg [info exists ::tcl::clock::NoRegistry]
+ if {$noreg} {unset ::tcl::clock::NoRegistry}
+ if { [info exists env(TZ)] } {
+ set oldTZ $env(TZ)
+ unset env(TZ)
+ }
+ if { [info exists env(TCL_TZ)] } {
+ set oldTclTZ $env(TCL_TZ)
+ unset env(TCL_TZ)
+ }
+ ::tcl::clock::ClearCaches
+ } \
+ -body {
+ clock format 0 -locale system -format "%X %Z"
+ } \
+ -cleanup {
+ namespace eval ::tcl::clock {
+ rename registry {}
+ }
+ if {$noreg} {set ::tcl::clock::NoRegistry {}}
+ if { [info exists oldTclTZ] } {
+ set env(TCL_TZ) $oldTclTZ
+ }
+ if { [info exists oldTZ] } {
+ set env(TZ) $oldTZ
+ }
+ ::tcl::clock::ClearCaches
+ } \
+ -result [clock format 0 -locale current -timezone EST5 \
+ -format {%l:%M:%S %p %Z}]
+
+test clock-32.1 {scan/format across the Gregorian change} {
+ set problems {}
+ set t [expr { wide(-6857395200) }]
+ foreach d { 1 2 14 15 16
+ 17 18 19 20 21 22 23
+ 24 25 26 27 28 29 30 } \
+ j { 245 246 258 259 260
+ 261 262 263 264 265 266 267
+ 268 269 270 271 272 273 274 } {
+ set u [format 1752-09-%02d $d]
+ set s [clock format $t -format %Y-%m-%d \
+ -locale en_US_roman -timezone :UTC]
+ if { $s ne $u } {
+ append problems "formatting $t: $s should be $u\n"
+ }
+ set v [clock scan $u -format %Y-%m-%d \
+ -locale en_US_roman -timezone :UTC]
+ if { $t ne $v } {
+ append problems "scanning $u: $t should be $v\n"
+ }
+ set u [format 1752-%03d $j]
+ set s [clock format $t -format %Y-%j \
+ -locale en_US_roman -timezone :UTC]
+ if { $s ne $u } {
+ append problems "formatting $t: $s should be $u\n"
+ }
+ set v [clock scan $u -format %Y-%j \
+ -locale en_US_roman -timezone :UTC]
+ if { $t ne $v } {
+ append problems "scanning $u: $t should be $v\n"
+ }
+ incr t 86400
+ }
+ set problems
+} {}
+
+# Legacy tests
# clock clicks
-test clock-2.1 {clock clicks tests} {
+test clock-33.1 {clock clicks tests} {
expr [clock clicks]+1
concat {}
} {}
-test clock-2.2 {clock clicks tests} {
+test clock-33.2 {clock clicks tests} {
set start [clock clicks]
after 10
set end [clock clicks]
expr "$end > $start"
} {1}
-test clock-2.3 {clock clicks tests} {
+test clock-33.3 {clock clicks tests} {
list [catch {clock clicks foo} msg] $msg
-} {1 {bad switch "foo": must be -milliseconds}}
-test clock-2.4 {clock clicks tests} {
+} {1 {bad option "foo": must be -milliseconds or -microseconds}}
+test clock-33.4 {clock clicks tests} {
expr [clock clicks -milliseconds]+1
concat {}
} {}
-test clock-2.5 {clock clicks tests, millisecond timing test} {
+test clock-33.4a {clock milliseconds} {
+ expr { [clock milliseconds] + 1 }
+ concat {}
+} {}
+test clock-33.5 {clock clicks tests, millisecond timing test} {
+ # This test can fail on a system that is so heavily loaded that
+ # the test takes >60 ms to run.
set start [clock clicks -milli]
after 10
set end [clock clicks -milli]
# 60 msecs seems to be the max time slice under Windows 95/98
- expr {($end > $start) && (($end - $start) <= 60)}
-} {1}
-test clock-2.6 {clock clicks, milli with too much abbreviation} {
- list [catch { clock clicks {} } msg] $msg
-} {1 {bad switch "": must be -milliseconds}}
-test clock-2.7 {clock clicks, milli with too much abbreviation} {
+ expr {
+ ($end > $start) && (($end - $start) <= 60) ?
+ "ok" :
+ "test should have taken 0-60 ms, actually took [expr $end - $start]"}
+} {ok}
+test clock-33.5a {clock tests, millisecond timing test} {
+ # This test can fail on a system that is so heavily loaded that
+ # the test takes >60 ms to run.
+ set start [clock milliseconds]
+ after 10
+ set end [clock milliseconds]
+ # 60 msecs seems to be the max time slice under Windows 95/98
+ expr {
+ ($end > $start) && (($end - $start) <= 60) ?
+ "ok" :
+ "test should have taken 0-60 ms, actually took [expr $end - $start]"}
+} {ok}
+test clock-33.6 {clock clicks, milli with too much abbreviation} {
+ list [catch { clock clicks ? } msg] $msg
+} {1 {bad option "?": must be -milliseconds or -microseconds}}
+test clock-33.7 {clock clicks, milli with too much abbreviation} {
list [catch { clock clicks - } msg] $msg
-} {1 {bad switch "-": must be -milliseconds}}
-
-# clock format
-test clock-3.1 {clock format tests} {unixOnly} {
- set clockval 657687766
- clock format $clockval -format {%a %b %d %I:%M:%S %p %Y} -gmt true
-} {Sun Nov 04 03:02:46 AM 1990}
-test clock-3.2 {clock format tests} \
- -body {
- # TCL_USE_TIMEZONE_VAR
-
- catch {set oldtz $env(TZ)}
- set env(TZ) PST
- set x {}
- append x [clock format 863800000 -format %Z -gmt 1]
- append x [set env(TZ)]
- catch {unset env(TZ); set env(TZ) $oldtz}
- set x
- } \
- -match regexp \
- -result {(?:GMT|UTC)PST}
-test clock-3.3 {clock format tests} {
- # tzset() under Borland doesn't seem to set up tzname[] for local
- # timezone, which caused "clock format" to think that %Z was an invalid
- # string. Don't care about answer, just that test runs w/o error.
-
- clock format 863800000 -format %Z
- set x {}
-} {}
-test clock-3.4 {clock format tests} \
- -body {
- # tzset() under Borland doesn't seem to set up tzname[] for gmt
- # timezone. tzset() under MSVC has the following weird observed
- # behavior:
- # First time we call "clock format [clock seconds] -format %Z -gmt 1"
- # we get "GMT", but on all subsequent calls we get the current time
- # zone string, even though env(TZ) is GMT and the variable _timezone
- # is 0.
- set x {}
- append x [clock format 863800000 -format %Z -gmt 1]
- append x [clock format 863800000 -format %Z -gmt 1]
- } \
- -match regexp \
- -result {GMTGMT|UTCUTC}
-test clock-3.5 {clock format tests} {
- list [catch {clock format} msg] $msg
-} {1 {wrong # args: should be "clock format clockval ?-format string? ?-gmt boolean?"}}
-test clock-3.6 {clock format tests} {
- list [catch {clock format foo} msg] $msg
-} {1 {expected integer but got "foo"}}
-test clock-3.7 {clock format tests} {unixOrPc} {
- set clockval 657687766
- clock format $clockval -format "%a %b %d %I:%M:%S %p %Y" -gmt true
-} "Sun Nov 04 03:02:46 AM 1990"
-test clock-3.8 {clock format tests} {
- list [catch {clock format a b c d e g} msg] $msg
-} {1 {wrong # args: should be "clock format clockval ?-format string? ?-gmt boolean?"}}
-test clock-3.9 {clock format tests} {unixOrPc nonPortable} {
- set clockval -1
- clock format $clockval -format "%a %b %d %I:%M:%S %p %Y" -gmt true
-} "Wed Dec 31 11:59:59 PM 1969"
-test clock-3.10 {clock format tests} {
- list [catch {clock format 123 -bad arg} msg] $msg
-} {1 {bad switch "-bad": must be -format or -gmt}}
-test clock-3.11 {clock format tests} {
- clock format 123 -format "x"
-} x
-test clock-3.12 {clock format tests} {
- clock format 123 -format ""
-} ""
-test clock-3.13 {clock format with non-ASCII character in the format string} {
- set oldenc [encoding system]
- encoding system iso8859-1
- set res [clock format 0 -format \u00c4]
- encoding system $oldenc
- unset oldenc
- set res
-} "\u00c4"
+} {1 {ambiguous option "-": must be -milliseconds or -microseconds}}
-# Bug 942078
+test clock-33.8 {clock clicks test, microsecond timing test} {
+ # This test can fail on a system that is so heavily loaded that
+ # the test takes >60 ms to run.
+ set start [clock clicks -micro]
+ after 10
+ set end [clock clicks -micro]
+ expr {($end > $start) && (($end - $start) <= 60000)}
+} {1}
+test clock-33.8a {clock test, microsecond timing test} {
+ # This test can fail on a system that is so heavily loaded that
+ # the test takes >60 ms to run.
+ set start [clock microseconds]
+ after 10
+ set end [clock microseconds]
+ expr {($end > $start) && (($end - $start) <= 60000)}
+} {1}
-test clock-3.14 {change of time zone} -setup {
- catch { unset oldTZ }
- if { [info exists env(TZ)] } {
- set oldTZ $env(TZ)
+test clock-33.9 {clock clicks test, millis align with seconds} {
+ set t1 [clock seconds]
+ while { 1 } {
+ set t2 [clock clicks -millis]
+ set t3 [clock seconds]
+ if { $t3 == $t1 } break
+ set t1 $t3
}
-} -body {
- set env(TZ) PST8PDT
- set s [clock format 0 -format %H%M]
- set env(TZ) GMT0
- append s -[clock format 0 -format %H%M]
-} -cleanup {
- if { [info exists oldTZ] } {
- set env(TZ) $oldTZ
- unset oldTZ
- } else {
- unset env(TZ)
+ expr { $t2 / 1000 == $t3 }
+} {1}
+test clock-33.9a {clock test, millis align with seconds} {
+ set t1 [clock seconds]
+ while { 1 } {
+ set t2 [clock milliseconds]
+ set t3 [clock seconds]
+ if { $t3 == $t1 } break
+ set t1 $t3
}
-} -result {1600-0000}
-
+ expr { $t2 / 1000 == $t3 }
+} {1}
+
+test clock-33.10 {clock clicks test, micros align with seconds} {
+ set t1 [clock seconds]
+ while { 1 } {
+ set t2 [clock clicks -micros]
+ set t3 [clock seconds]
+ if { $t3 == $t1 } break
+ set t1 $t3
+ }
+ expr { $t2 / 1000000 == $t3 }
+} {1}
+test clock-33.10a {clock test, micros align with seconds} {
+ set t1 [clock seconds]
+ while { 1 } {
+ set t2 [clock microseconds]
+ set t3 [clock seconds]
+ if { $t3 == $t1 } break
+ set t1 $t3
+ }
+ expr { $t2 / 1000000 == $t3 }
+} {1}
+
+test clock-33.11 {clock clicks test, millis align with micros} {
+ set t1 [clock clicks -millis]
+ while { 1 } {
+ set t2 [clock clicks -micros]
+ set t3 [clock clicks -millis]
+ if { $t3 == $t1 } break
+ set t1 $t3
+ }
+ expr { $t2 / 1000 == $t3 }
+} {1}
+test clock-33.11a {clock test, millis align with micros} {
+ set t1 [clock milliseconds]
+ while { 1 } {
+ set t2 [clock microseconds]
+ set t3 [clock milliseconds]
+ if { $t3 == $t1 } break
+ set t1 $t3
+ }
+ expr { $t2 / 1000 == $t3 }
+} {1}
# clock scan
-test clock-4.1 {clock scan tests} {
+test clock-34.1 {clock scan tests} {
list [catch {clock scan} msg] $msg
-} {1 {wrong # args: should be "clock scan dateString ?-base clockValue? ?-gmt boolean?"}}
-test clock-4.2 {clock scan tests} {
- list [catch {clock scan "bad-string"} msg] $msg
-} {1 {unable to convert date-time string "bad-string"}}
-test clock-4.3 {clock scan tests} {
+} {1 {wrong # args: should be "clock scan string ?-base seconds? ?-format string? ?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?"}}
+test clock-34.2 {clock scan tests} {*}{
+ -body {clock scan "bad-string"}
+ -returnCodes error
+ -match glob
+ -result {unable to convert date-time string "bad-string"*}
+}
+test clock-34.3 {clock scan tests} {
clock format [clock scan "14 Feb 92" -gmt true] \
-format {%m/%d/%y %I:%M:%S %p} -gmt true
} {02/14/92 12:00:00 AM}
-test clock-4.4 {clock scan tests} {
+test clock-34.4 {clock scan tests} {
clock format [clock scan "Feb 14, 1992 12:20 PM" -gmt true] \
-format {%m/%d/%y %I:%M:%S %p} -gmt true
} {02/14/92 12:20:00 PM}
-test clock-4.5 {clock scan tests} {
+test clock-34.5 {clock scan tests} {
clock format \
[clock scan "Feb 14, 1992 12:20 PM" -base 319363200 -gmt true] \
-format {%m/%d/%y %I:%M:%S %p} -gmt true
} {02/14/92 12:20:00 PM}
-test clock-4.6 {clock scan tests} {
+test clock-34.6 {clock scan tests} {
set time [clock scan "Oct 23,1992 15:00"]
clock format $time -format {%b %d,%Y %H:%M}
} {Oct 23,1992 15:00}
-test clock-4.7 {clock scan tests} {
+test clock-34.7 {clock scan tests} {
set time [clock scan "Oct 23,1992 15:00 GMT"]
clock format $time -format {%b %d,%Y %H:%M GMT} -gmt true
} {Oct 23,1992 15:00 GMT}
-test clock-4.8 {clock scan tests} {
+test clock-34.8 {clock scan tests} {
set time [clock scan "Oct 23,1992 15:00" -gmt true]
clock format $time -format {%b %d,%Y %H:%M GMT} -gmt true
} {Oct 23,1992 15:00 GMT}
-test clock-4.9 {clock scan tests} {
+test clock-34.9 {clock scan tests} {
list [catch {clock scan "Jan 12" -bad arg} msg] $msg
-} {1 {bad switch "-bad": must be -base or -gmt}}
+} {1 {bad switch "-bad", must be -base, -format, -gmt, -locale or -timezone}}
# The following two two tests test the two year date policy
-test clock-4.10 {clock scan tests} {
+test clock-34.10 {clock scan tests} {
set time [clock scan "1/1/71" -gmt true]
clock format $time -format {%b %d,%Y %H:%M GMT} -gmt true
} {Jan 01,1971 00:00 GMT}
-test clock-4.11 {clock scan tests} {
+test clock-34.11 {clock scan tests} {
set time [clock scan "1/1/37" -gmt true]
clock format $time -format {%b %d,%Y %H:%M GMT} -gmt true
} {Jan 01,2037 00:00 GMT}
-test clock-4.12 {clock scan, relative times} {
+test clock-34.12 {clock scan, relative times} {
set time [clock scan "Oct 23, 1992 -1 day"]
clock format $time -format {%b %d, %Y}
} "Oct 22, 1992"
-test clock-4.13 {clock scan, ISO 8601 base date format} {
+test clock-34.13 {clock scan, ISO 8601 base date format} {
set time [clock scan "19921023"]
clock format $time -format {%b %d, %Y}
} "Oct 23, 1992"
-test clock-4.14 {clock scan, ISO 8601 expanded date format} {
+test clock-34.14 {clock scan, ISO 8601 expanded date format} {
set time [clock scan "1992-10-23"]
clock format $time -format {%b %d, %Y}
} "Oct 23, 1992"
-test clock-4.15 {clock scan, DD-Mon-YYYY format} {
+test clock-34.15 {clock scan, DD-Mon-YYYY format} {
set time [clock scan "23-Oct-1992"]
clock format $time -format {%b %d, %Y}
} "Oct 23, 1992"
-test clock-4.16 {clock scan, ISO 8601 point in time format} {
+test clock-34.16 {clock scan, ISO 8601 point in time format} {
set time [clock scan "19921023T235959"]
clock format $time -format {%b %d, %Y %H:%M:%S}
} "Oct 23, 1992 23:59:59"
-test clock-4.17 {clock scan, ISO 8601 point in time format} {
+test clock-34.17 {clock scan, ISO 8601 point in time format} {
set time [clock scan "19921023 235959"]
clock format $time -format {%b %d, %Y %H:%M:%S}
} "Oct 23, 1992 23:59:59"
-test clock-4.18 {clock scan, ISO 8601 point in time format} {
+test clock-34.18 {clock scan, ISO 8601 point in time format} {
set time [clock scan "19921023T000000"]
clock format $time -format {%b %d, %Y %H:%M:%S}
} "Oct 23, 1992 00:00:00"
@@ -233,7 +35653,7 @@ test clock-4.18 {clock scan, ISO 8601 point in time format} {
# We use 5am PST, 31-12-1999 as the base for these scans because irrespective
# of your local timezone it should always give us times on December 31, 1999
set 5amPST 946645200
-test clock-4.19 {clock scan, number meridian} {
+test clock-34.19 {clock scan, number meridian} {
set t1 [clock scan "5 am" -base $5amPST -gmt true]
set t2 [clock scan "5 pm" -base $5amPST -gmt true]
set t3 [clock scan "5 a.m." -base $5amPST -gmt true]
@@ -245,86 +35665,86 @@ test clock-4.19 {clock scan, number meridian} {
[clock format $t4 -format {%b %d, %Y %H:%M:%S} -gmt true]
} [list "Dec 31, 1999 05:00:00" "Dec 31, 1999 17:00:00" \
"Dec 31, 1999 05:00:00" "Dec 31, 1999 17:00:00"]
-test clock-4.20 {clock scan, number:number meridian} {
+test clock-34.20 {clock scan, number:number meridian} {
clock format [clock scan "5:30 pm" -base $5amPST -gmt true] \
-format {%b %d, %Y %H:%M:%S} -gmt true
} "Dec 31, 1999 17:30:00"
-test clock-4.21 {clock scan, number:number-timezone} {
+test clock-34.21 {clock scan, number:number-timezone} {
clock format [clock scan "00:00-0800" -gmt true -base $5amPST] \
-format {%b %d, %Y %H:%M:%S} -gmt true
} "Dec 31, 1999 08:00:00"
-test clock-4.22 {clock scan, number:number:number o_merid} {
+test clock-34.22 {clock scan, number:number:number o_merid} {
clock format [clock scan "8:00:00" -gmt true -base $5amPST] \
-format {%b %d, %Y %H:%M:%S} -gmt true
} "Dec 31, 1999 08:00:00"
-test clock-4.23 {clock scan, number:number:number o_merid} {
+test clock-34.23 {clock scan, number:number:number o_merid} {
clock format [clock scan "8:00:00 am" -gmt true -base $5amPST] \
-format {%b %d, %Y %H:%M:%S} -gmt true
} "Dec 31, 1999 08:00:00"
-test clock-4.24 {clock scan, number:number:number o_merid} {
+test clock-34.24 {clock scan, number:number:number o_merid} {
clock format [clock scan "8:00:00 pm" -gmt true -base $5amPST] \
-format {%b %d, %Y %H:%M:%S} -gmt true
} "Dec 31, 1999 20:00:00"
-test clock-4.25 {clock scan, number:number:number-timezone} {
+test clock-34.25 {clock scan, number:number:number-timezone} {
clock format [clock scan "00:00:30-0800" -gmt true -base $5amPST] \
-format {%b %d, %Y %H:%M:%S} -gmt true
} "Dec 31, 1999 08:00:30"
-test clock-4.26 {clock scan, DST for days} {
+test clock-34.26 {clock scan, DST for days} {
clock scan "tomorrow" -base [clock scan "19991031 00:00:00"]
} [clock scan "19991101 00:00:00"]
-test clock-4.27 {clock scan, DST for days} {
+test clock-34.27 {clock scan, DST for days} {
clock scan "yesterday" -base [clock scan "19991101 00:00:00"]
} [clock scan "19991031 00:00:00"]
-test clock-4.28 {clock scan, day} knownBug {
+test clock-34.28 {clock scan, day} {
clock format [clock scan "Monday" -gmt true -base 946627200] \
-format {%b %d, %Y %H:%M:%S} -gmt true
} "Jan 03, 2000 00:00:00"
-test clock-4.29 {clock scan, number/number} {
+test clock-34.29 {clock scan, number/number} {
clock format [clock scan "1/1" -gmt true -base 946627200] \
-format {%b %d, %Y %H:%M:%S} -gmt true
} "Jan 01, 1999 00:00:00"
-test clock-4.30 {clock scan, number/number} {
+test clock-34.30 {clock scan, number/number} {
clock format [clock scan "1/1/1999" -gmt true -base 946627200] \
-format {%b %d, %Y %H:%M:%S} -gmt true
} "Jan 01, 1999 00:00:00"
-test clock-4.31 {clock scan, number/number} {
+test clock-34.31 {clock scan, number/number} {
clock format [clock scan "19990101" -gmt true -base 946627200] \
-format {%b %d, %Y %H:%M:%S} -gmt true
} "Jan 01, 1999 00:00:00"
-test clock-4.32 {clock scan, relative minutes} {
+test clock-34.32 {clock scan, relative minutes} {
clock scan "now + 1 minute" -base 946627200
} 946627260
-test clock-4.33 {clock scan, relative minutes} {
+test clock-34.33 {clock scan, relative minutes} {
clock scan "now +1 minute" -base 946627200
} 946627260
-test clock-4.34 {clock scan, relative minutes} {
+test clock-34.34 {clock scan, relative minutes} {
clock scan "now 1 minute" -base 946627200
} 946627260
-test clock-4.35 {clock scan, relative minutes} {
+test clock-34.35 {clock scan, relative minutes} {
clock scan "now - 1 minute" -base 946627200
} 946627140
-test clock-4.36 {clock scan, relative minutes} {
+test clock-34.36 {clock scan, relative minutes} {
clock scan "now -1 minute" -base 946627200
} 946627140
-test clock-4.37 {clock scan, day of week} {
+test clock-34.37 {clock scan, day of week} {
clock format [clock scan "wednesday" -base [clock scan 20000112]] \
-format {%b %d, %Y}
} "Jan 12, 2000"
-test clock-4.38 {clock scan, next day of week} {
+test clock-34.38 {clock scan, next day of week} {
clock format [clock scan "next wednesday" -base [clock scan 20000112]] \
-format {%b %d, %Y}
} "Jan 19, 2000"
-test clock-4.39 {clock scan, day of week} {
+test clock-34.39 {clock scan, day of week} {
clock format [clock scan "thursday" -base [clock scan 20000112]] \
-format {%b %d, %Y}
} "Jan 13, 2000"
-test clock-4.40 {clock scan, next day of week} {
+test clock-34.40 {clock scan, next day of week} {
clock format [clock scan "next thursday" -base [clock scan 20000112]] \
-format {%b %d, %Y}
} "Jan 20, 2000"
# weekday specification and base.
-test clock-4.41 {2nd monday in november} {
+test clock-34.41 {2nd monday in november} {
set res {}
foreach i {91 92 93 94 95 96} {
set nov8th [clock scan 11/8/$i]
@@ -333,7 +35753,7 @@ test clock-4.41 {2nd monday in november} {
}
set res
} {1991-11-11 1992-11-09 1993-11-08 1994-11-14 1995-11-13 1996-11-11}
-test clock-4.42 {2nd monday in november (2nd try)} {
+test clock-34.42 {2nd monday in november (2nd try)} {
set res {}
foreach i {91 92 93 94 95 96} {
set nov1th [clock scan 11/1/$i]
@@ -342,7 +35762,7 @@ test clock-4.42 {2nd monday in november (2nd try)} {
}
set res
} {1991-11-11 1992-11-09 1993-11-08 1994-11-14 1995-11-13 1996-11-11}
-test clock-4.43 {last monday in november} {
+test clock-34.43 {last monday in november} {
set res {}
foreach i {91 92 93 94 95 96} {
set dec1th [clock scan 12/1/$i]
@@ -352,7 +35772,7 @@ test clock-4.43 {last monday in november} {
set res
} {1991-11-25 1992-11-30 1993-11-29 1994-11-28 1995-11-27 1996-11-25}
-test clock-4.44 {2nd monday in november} knownBug {
+test clock-34.44 {2nd monday in november} {
set res {}
foreach i {91 92 93 94 95 96} {
set nov8th [clock scan 11/8/$i -gmt 1]
@@ -361,7 +35781,7 @@ test clock-4.44 {2nd monday in november} knownBug {
}
set res
} {1991-11-11 1992-11-09 1993-11-08 1994-11-14 1995-11-13 1996-11-11}
-test clock-4.45 {2nd monday in november (2nd try)} knownBug {
+test clock-34.45 {2nd monday in november (2nd try)} {
set res {}
foreach i {91 92 93 94 95 96} {
set nov1th [clock scan 11/1/$i -gmt 1]
@@ -370,7 +35790,7 @@ test clock-4.45 {2nd monday in november (2nd try)} knownBug {
}
set res
} {1991-11-11 1992-11-09 1993-11-08 1994-11-14 1995-11-13 1996-11-11}
-test clock-4.46 {last monday in november} knownBug {
+test clock-34.46 {last monday in november} {
set res {}
foreach i {91 92 93 94 95 96} {
set dec1th [clock scan 12/1/$i -gmt 1]
@@ -379,278 +35799,962 @@ test clock-4.46 {last monday in november} knownBug {
}
set res
} {1991-11-25 1992-11-30 1993-11-29 1994-11-28 1995-11-27 1996-11-25}
-test clock-4.47 {ago with multiple relative units} {
+test clock-34.47 {ago with multiple relative units} {
set base [clock scan "12/31/1999 00:00:00"]
set res [clock scan "2 days 2 hours ago" -base $base]
expr {$base - $res}
} 180000
+test clock-34.48 {more than one ToD} {*}{
+ -body {clock scan {10:00 11:00}}
+ -returnCodes error
+ -result {unable to convert date-time string "10:00 11:00": more than one time of day in string}
+}
+
+test clock-34.49 {more than one date} {*}{
+ -body {clock scan {1/1/2001 2/2/2002}}
+ -returnCodes error
+ -result {unable to convert date-time string "1/1/2001 2/2/2002": more than one date in string}
+}
+
+test clock-34.50 {more than one time zone} {*}{
+ -body {clock scan {10:00 EST CST}}
+ -returnCodes error
+ -result {unable to convert date-time string "10:00 EST CST": more than one time zone in string}
+}
+
+test clock-34.51 {more than one weekday} {*}{
+ -body {clock scan {Monday Tuesday}}
+ -returnCodes error
+ -result {unable to convert date-time string "Monday Tuesday": more than one weekday in string}
+}
+
+test clock-34.52 {more than one ordinal month} {*}{
+ -body {clock scan {next January next March}}
+ -returnCodes error
+ -result {unable to convert date-time string "next January next March": more than one ordinal month in string}
+}
+
+
+
# clock seconds
-test clock-5.1 {clock seconds tests} {
+test clock-35.1 {clock seconds tests} {
expr [clock seconds]+1
concat {}
} {}
-test clock-5.2 {clock seconds tests} {
+test clock-35.2 {clock seconds tests} {
list [catch {clock seconds foo} msg] $msg
} {1 {wrong # args: should be "clock seconds"}}
-test clock-5.3 {clock seconds tests} {
+test clock-35.3 {clock seconds tests} {
set start [clock seconds]
after 2000
set end [clock seconds]
expr "$end > $start"
} {1}
-# The following dates check certain roll over dates
-set day [expr 24 * 60 * 60]
-test clock-6.1 {clock roll over dates} {
- set time [clock scan "12/31/1998" -gmt true]
- clock format [expr $time + $day] -format {%b %d,%Y %H:%M GMT} -gmt true
-} {Jan 01,1999 00:00 GMT}
-test clock-6.2 {clock roll over dates} {
- set time [clock scan "12/31/1999" -gmt true]
- clock format [expr $time + $day] -format {%b %d,%Y %H:%M GMT} -gmt true
-} {Jan 01,2000 00:00 GMT}
-test clock-6.3 {clock roll over dates} {
- set time [clock scan "2/28/2000" -gmt true]
- clock format [expr $time + $day] -format {%b %d,%Y %H:%M GMT} -gmt true
-} {Feb 29,2000 00:00 GMT}
-test clock-6.4 {clock roll over dates} {
- set time [clock scan "2/29/2000" -gmt true]
- clock format [expr $time + $day] -format {%b %d,%Y %H:%M GMT} -gmt true
-} {Mar 01,2000 00:00 GMT}
-test clock-6.5 {clock roll over dates} {
- set time [clock scan "January 1, 2000" -gmt true]
- clock format $time -format %A -gmt true
-} {Saturday}
-test clock-6.6 {clock roll over dates} {
- set time [clock scan "January 1, 2000" -gmt true]
- clock format $time -format %j -gmt true
-} {001}
-test clock-6.7 {clock roll over dates} {
- set time [clock scan "February 29, 2000" -gmt true]
- clock format $time -format %A -gmt true
-} {Tuesday}
-test clock-6.8 {clock roll over dates} {
- set time [clock scan "February 29, 2000" -gmt true]
- clock format $time -format %j -gmt true
-} {060}
-test clock-6.9 {clock roll over dates} {
- set time [clock scan "March 1, 2000" -gmt true]
- clock format $time -format %A -gmt true
-} {Wednesday}
-test clock-6.10 {clock roll over dates} {
- set time [clock scan "March 1, 2000" -gmt true]
- clock format $time -format %j -gmt true
-} {061}
-test clock-6.11 {clock roll over dates} {
- set time [clock scan "March 1, 2001" -gmt true]
- clock format $time -format %j -gmt true
-} {060}
-
-test clock-7.1 {clock scan next monthname} {
+
+test clock-36.1 {clock scan next monthname} {
clock format [clock scan "next june" -base [clock scan "june 1, 2000"]] \
-format %m.%Y
} "06.2001"
-test clock-7.2 {clock scan next monthname} {
+test clock-36.2 {clock scan next monthname} {
clock format [clock scan "next july" -base [clock scan "june 1, 2000"]] \
-format %m.%Y
} "07.2000"
-test clock-7.3 {clock scan next monthname} {
+test clock-36.3 {clock scan next monthname} {
clock format [clock scan "next may" -base [clock scan "june 1, 2000"]] \
-format %m.%Y
} "05.2001"
-# We use 5am PST, 31-12-1999 as the base for these scans because irrespective
-# of your local timezone it should always give us times on December 31
-set 5amPST 946645200
-test clock-8.1 {clock scan midnight/gmt range bug 413397} {
- set fmt "%m/%d"
- list [clock format [clock scan year -base $5amPST -gmt 0] -format $fmt] \
- [clock format [clock scan year -base $5amPST -gmt 1] -format $fmt]
-} {12/31 12/31}
-
-::tcltest::testConstraint needPST [expr {
- [regexp {^(Pacific.*|P[DS]T)$} [clock format 1 -format %Z]]
- && ([clock format 1 -format %s] != "%s")
-}]
-
-test clock-9.1 {%s gmt testing} {needPST} {
-
- # Note that this test will fail if the strftime on the underlying
- # system doesn't support the %s format group. Systems that are known
- # to have trouble include the native C libraries on AIX and HP-UX
-
- # We need PST to guarantee the difference value below, and %s isn't
- # valid on all OSes (like Solaris).
- set s 100000
+test clock-37.1 {%s gmt testing} {
+ set s [clock seconds]
set a [clock format $s -format %s -gmt 0]
set b [clock format $s -format %s -gmt 1]
- # This should be the offset in seconds between current locale and GMT.
- # This didn't seem to be correctly on Windows until the fix for
- # Bug #559376, which fiddled with env(TZ) when -gmt 1 was used.
- # It's hard-coded to check P[SD]T now. (8 hours)
+ # %s, being the difference between local and Greenwich, does not
+ # depend on the time zone.
set c [expr {$b-$a}]
-} {28800}
-
-::tcltest::testConstraint percentG \
- [expr { ![catch { clock format 0 -format %G -gmt true } y1970]
- && $y1970 eq {1970} }]
-
-test clock-10.0 {Can strftime do %G?} {
- clock format 0 -format %G -gmt true
-} 1970
-test clock-10.1 {ISO week-based calendar 2000-W52-1} {percentG} {
- clock format 977702400 -format {%a %A %g %G %u %V %w} -gmt true; # 2000-12-25
-} {Mon Monday 00 2000 1 52 1}
-test clock-10.2 {ISO week-based calendar 2000-W52-7} {percentG} {
- clock format 978220800 -format {%a %A %g %G %u %V %w} -gmt true; # 2000-12-31
-} {Sun Sunday 00 2000 7 52 0}
-test clock-10.3 {ISO week-based calendar 2001-W01-1} {percentG} {
- clock format 978307200 -format {%a %A %g %G %u %V %w} -gmt true; # 2001-1-1
-} {Mon Monday 01 2001 1 01 1}
-test clock-10.4 {ISO week-based calendar 2001-W01-7} {percentG} {
- clock format 978825600 -format {%a %A %g %G %u %V %w} -gmt true; # 2001-1-7
-} {Sun Sunday 01 2001 7 01 0}
-test clock-10.5 {ISO week-based calendar 2001-W02-1} {percentG} {
- clock format 978912000 -format {%a %A %g %G %u %V %w} -gmt true; # 2001-1-8
-} {Mon Monday 01 2001 1 02 1}
-test clock-10.6 {ISO week-based calendar 2001-W52-1} {percentG} {
- clock format 1009152000 -format {%a %A %g %G %u %V %w} -gmt true; # 2001-12-24
-} {Mon Monday 01 2001 1 52 1}
-test clock-10.7 {ISO week-based calendar 2001-W52-7} {percentG} {
- clock format 1009670400 -format {%a %A %g %G %u %V %w} -gmt true; # 2001-12-30
-} {Sun Sunday 01 2001 7 52 0}
-test clock-10.8 {ISO week-based calendar 2002-W01-1} {percentG} {
- clock format 1009756800 -format {%a %A %g %G %u %V %w} -gmt true; # 2001-12-31
-} {Mon Monday 02 2002 1 01 1}
-test clock-10.9 {ISO week-based calendar 2002-W01-2} {percentG} {
- clock format 1009843200 -format {%a %A %g %G %u %V %w} -gmt true; # 2002-1-1
-} {Tue Tuesday 02 2002 2 01 2}
-test clock-10.10 {ISO week-based calendar 2002-W01-7} {percentG} {
- clock format 1010275200 -format {%a %A %g %G %u %V %w} -gmt true; # 2002-1-6
-} {Sun Sunday 02 2002 7 01 0}
-test clock-10.11 {ISO week-based calendar 2002-W02-1} {percentG} {
- clock format 1010361600 -format {%a %A %g %G %u %V %w} -gmt true; # 2002-1-7
-} {Mon Monday 02 2002 1 02 1}
-test clock-10.12 {ISO week-based calendar 2002-W52-1} {percentG} {
- clock format 1040601600 -format {%a %A %g %G %u %V %w} -gmt true; # 2002-12-23
-} {Mon Monday 02 2002 1 52 1}
-test clock-10.13 {ISO week-based calendar 2002-W52-7} {percentG} {
- clock format 1041120000 -format {%a %A %g %G %u %V %w} -gmt true; # 2002-12-29
-} {Sun Sunday 02 2002 7 52 0}
-test clock-10.14 {ISO week-based calendar 2003-W01-1} {percentG} {
- clock format 1041206400 -format {%a %A %g %G %u %V %w} -gmt true; # 2002-12-30
-} {Mon Monday 03 2003 1 01 1}
-test clock-10.15 {ISO week-based calendar 2003-W01-2} {percentG} {
- clock format 1041292800 -format {%a %A %g %G %u %V %w} -gmt true; # 2002-12-31
-} {Tue Tuesday 03 2003 2 01 2}
-test clock-10.16 {ISO week-based calendar 2003-W01-3} {percentG} {
- clock format 1041379200 -format {%a %A %g %G %u %V %w} -gmt true; # 2003-1-1
-} {Wed Wednesday 03 2003 3 01 3}
-test clock-10.17 {ISO week-based calendar 2003-W01-7} {percentG} {
- clock format 1041724800 -format {%a %A %g %G %u %V %w} -gmt true; # 2003-1-5
-} {Sun Sunday 03 2003 7 01 0}
-test clock-10.18 {ISO week-based calendar 2003-W02-1} {percentG} {
- clock format 1041811200 -format {%a %A %g %G %u %V %w} -gmt true; # 2003-1-6
-} {Mon Monday 03 2003 1 02 1}
-test clock-10.19 {ISO week-based calendar 2003-W52-1} {percentG} {
- clock format 1072051200 -format {%a %A %g %G %u %V %w} -gmt true; # 2003-12-22
-} {Mon Monday 03 2003 1 52 1}
-test clock-10.20 {ISO week-based calendar 2003-W52-7} {percentG} {
- clock format 1072569600 -format {%a %A %g %G %u %V %w} -gmt true; # 2003-12-28
-} {Sun Sunday 03 2003 7 52 0}
-test clock-10.21 {ISO week-based calendar 2004-W01-1} {percentG} {
- clock format 1072656000 -format {%a %A %g %G %u %V %w} -gmt true; # 2003-12-29
-} {Mon Monday 04 2004 1 01 1}
-test clock-10.22 {ISO week-based calendar 2004-W01-3} {percentG} {
- clock format 1072828800 -format {%a %A %g %G %u %V %w} -gmt true; # 2003-12-31
-} {Wed Wednesday 04 2004 3 01 3}
-test clock-10.23 {ISO week-based calendar 2004-W01-4} {percentG} {
- clock format 1072915200 -format {%a %A %g %G %u %V %w} -gmt true; # 2004-1-1
-} {Thu Thursday 04 2004 4 01 4}
-test clock-10.24 {ISO week-based calendar 2004-W01-7} {percentG} {
- clock format 1073174400 -format {%a %A %g %G %u %V %w} -gmt true; # 2004-1-4
-} {Sun Sunday 04 2004 7 01 0}
-test clock-10.25 {ISO week-based calendar 2004-W02-1} {percentG} {
- clock format 1073260800 -format {%a %A %g %G %u %V %w} -gmt true; # 2004-1-5
-} {Mon Monday 04 2004 1 02 1}
-test clock-10.26 {ISO week-based calendar 2004-W52-1} {percentG} {
- clock format 1103500800 -format {%a %A %g %G %u %V %w} -gmt true; # 2004-12-20
-} {Mon Monday 04 2004 1 52 1}
-test clock-10.27 {ISO week-based calendar 2004-W52-7} {percentG} {
- clock format 1104019200 -format {%a %A %g %G %u %V %w} -gmt true; # 2004-12-26
-} {Sun Sunday 04 2004 7 52 0}
-test clock-10.28 {ISO week-based calendar 2004-W53-1} {percentG} {
- clock format 1104105600 -format {%a %A %g %G %u %V %w} -gmt true; # 2004-12-27
-} {Mon Monday 04 2004 1 53 1}
-test clock-10.29 {ISO week-based calendar 2004-W53-5} {percentG} {
- clock format 1104451200 -format {%a %A %g %G %u %V %w} -gmt true; # 2004-12-31
-} {Fri Friday 04 2004 5 53 5}
-test clock-10.30 {ISO week-based calendar 2004-W53-6} {percentG} {
- clock format 1104537600 -format {%a %A %g %G %u %V %w} -gmt true; # 2005-1-1
-} {Sat Saturday 04 2004 6 53 6}
-test clock-10.31 {ISO week-based calendar 2004-W53-7} {percentG} {
- clock format 1104624000 -format {%a %A %g %G %u %V %w} -gmt true; # 2005-1-2
-} {Sun Sunday 04 2004 7 53 0}
-test clock-10.32 {ISO week-based calendar 2005-W01-1} {percentG} {
- clock format 1104710400 -format {%a %A %g %G %u %V %w} -gmt true; # 2005-1-3
-} {Mon Monday 05 2005 1 01 1}
-test clock-10.33 {ISO week-based calendar 2005-W01-7} {percentG} {
- clock format 1105228800 -format {%a %A %g %G %u %V %w} -gmt true; # 2005-1-9
-} {Sun Sunday 05 2005 7 01 0}
-test clock-10.34 {ISO week-based calendar 2005-W02-1} {percentG} {
- clock format 1105315200 -format {%a %A %g %G %u %V %w} -gmt true; # 2005-1-10
-} {Mon Monday 05 2005 1 02 1}
-test clock-10.35 {ISO week-based calendar 2005-W52-1} {percentG} {
- clock format 1135555200 -format {%a %A %g %G %u %V %w} -gmt true; # 2005-12-26
-} {Mon Monday 05 2005 1 52 1}
-test clock-10.36 {ISO week-based calendar 2005-W52-6} {percentG} {
- clock format 1135987200 -format {%a %A %g %G %u %V %w} -gmt true; # 2005-12-31
-} {Sat Saturday 05 2005 6 52 6}
-test clock-10.37 {ISO week-based calendar 2005-W52-7} {percentG} {
- clock format 1136073600 -format {%a %A %g %G %u %V %w} -gmt true; # 2006-1-1
-} {Sun Sunday 05 2005 7 52 0}
-test clock-10.38 {ISO week-based calendar 2006-W01-1} {percentG} {
- clock format 1136160000 -format {%a %A %g %G %u %V %w} -gmt true; # 2006-1-2
-} {Mon Monday 06 2006 1 01 1}
-test clock-10.39 {ISO week-based calendar 2006-W01-7} {percentG} {
- clock format 1136678400 -format {%a %A %g %G %u %V %w} -gmt true; # 2006-1-8
-} {Sun Sunday 06 2006 7 01 0}
-test clock-10.40 {ISO week-based calendar 2006-W02-1} {percentG} {
- clock format 1136764800 -format {%a %A %g %G %u %V %w} -gmt true; # 2006-1-9
-} {Mon Monday 06 2006 1 02 1}
-test clock-10.41 {ISO week-based calendar 2009-W52-1} {percentG} {
- clock format 1261353600 -format {%a %A %g %G %u %V %w} -gmt true; # 2009-12-21
-} {Mon Monday 09 2009 1 52 1}
-test clock-10.42 {ISO week-based calendar 2009-W52-7} {percentG} {
- clock format 1261872000 -format {%a %A %g %G %u %V %w} -gmt true; # 2009-12-27
-} {Sun Sunday 09 2009 7 52 0}
-test clock-10.43 {ISO week-based calendar 2009-W53-1} {percentG} {
- clock format 1261958400 -format {%a %A %g %G %u %V %w} -gmt true; # 2009-12-28
-} {Mon Monday 09 2009 1 53 1}
-test clock-10.44 {ISO week-based calendar 2009-W53-4} {percentG} {
- clock format 1262217600 -format {%a %A %g %G %u %V %w} -gmt true; # 2009-12-31
-} {Thu Thursday 09 2009 4 53 4}
-test clock-10.45 {ISO week-based calendar 2009-W53-5} {percentG} {
- clock format 1262304000 -format {%a %A %g %G %u %V %w} -gmt true; # 2010-1-1
-} {Fri Friday 09 2009 5 53 5}
-test clock-10.46 {ISO week-based calendar 2009-W53-7} {percentG} {
- clock format 1262476800 -format {%a %A %g %G %u %V %w} -gmt true; # 2010-1-3
-} {Sun Sunday 09 2009 7 53 0}
-test clock-10.47 {ISO week-based calendar 2010-W01-1} {percentG} {
- clock format 1262563200 -format {%a %A %g %G %u %V %w} -gmt true; # 2010-1-4
-} {Mon Monday 10 2010 1 01 1}
-test clock-10.48 {ISO week-based calendar 2010-W01-7} {percentG} {
- clock format 1263081600 -format {%a %A %g %G %u %V %w} -gmt true; # 2010-1-10
-} {Sun Sunday 10 2010 7 01 0}
-test clock-10.49 {ISO week-based calendar 2010-W02-1} {percentG} {
- clock format 1263168000 -format {%a %A %g %G %u %V %w} -gmt true; # 2010-1-11
-} {Mon Monday 10 2010 1 02 1}
+} {0}
+
+test clock-38.1 {regression - convertUTCToLocalViaC - east of Greenwich} \
+ -setup {
+ if { [info exists env(TZ)] } {
+ set oldTZ $env(TZ)
+ }
+ set env(TZ) CET-01:00CEST-02:00,M3.5.0/02:00,M10.5.0/03:00
+ } \
+ -body {
+ clock format 0 -format %H:%M:%S -timezone :localtime
+ } \
+ -cleanup {
+ if { [info exists oldTZ] } {
+ set env(TZ) $oldTZ
+ unset oldTZ
+ } else {
+ unset env(TZ)
+ }
+ } \
+ -result {01:00:00}
+
+test clock-39.1 {regression - synonym timezones} {
+ clock format 0 -format {%H:%M:%S} -timezone :US/Eastern
+} {19:00:00}
+
+test clock-40.1 {regression - bad month with -timezone :localtime} \
+ -setup {
+ if { [info exists env(TZ)] } {
+ set oldTZ $env(TZ)
+ }
+ set env(TZ) UTC0
+ } \
+ -body {
+ clock scan 2000-01-01T00:00:00 -timezone :localtime \
+ -format %Y-%m-%dT%H:%M:%S
+ } \
+ -cleanup {
+ if { [info exists oldTZ] } {
+ set env(TZ) $oldTZ
+ unset oldTZ
+ } else {
+ unset env(TZ)
+ }
+ } \
+ -result 946684800
test clock-41.1 {regression test - format group %k when hour is 0 } {
clock format 0 -format %k -gmt true
} { 0}
+test clock-42.1 {regression test - %z in :localtime when west of Greenwich } \
+ -setup {
+ if { [info exists env(TZ)] } {
+ set oldTZ $env(TZ)
+ }
+ set env(TZ) EST5
+ } \
+ -body {
+ clock format 0 -format %z -timezone :localtime
+ } \
+ -cleanup {
+ if { [info exists oldTZ] } {
+ set env(TZ) $oldTZ
+ unset oldTZ
+ } else {
+ unset env(TZ)
+ }
+ } \
+ -result {-0500}
+
+# 43.1 was a bad test - mktime returning -1 is an error according to posix.
+
+test clock-44.1 {regression test - time zone name containing hyphen } \
+ -setup {
+ if { [info exists env(TZ)] } {
+ set oldTZ $env(TZ)
+ }
+ set env(TZ) US/East-Indiana
+ } \
+ -body {
+ clock format 1098466496 -format %H:%M:%S%z -timezone US/East-Indiana
+ } \
+ -cleanup {
+ if { [info exists oldTZ] } {
+ set env(TZ) $oldTZ
+ unset oldTZ
+ } else {
+ unset env(TZ)
+ }
+ } \
+ -result {12:34:56-0500}
+
+test clock-45.1 {regression test - time zone containing only two digits} \
+ -body {
+ clock scan 1985-04-12T10:15:30+04 -format %Y-%m-%dT%H:%M:%S%Z
+ } \
+ -result 482134530
+
+test clock-46.1 {regression test - month zero} \
+ -body {
+ clock scan 2004-00-00 -format %Y-%m-%d
+ } -result [clock scan 2003-11-30 -format %Y-%m-%d]
+test clock-46.2 {regression test - month zero} \
+ -body {
+ clock scan 20040000
+ } -result [clock scan 2003-11-30 -format %Y-%m-%d]
+test clock-46.3 {regression test - month thirteen} \
+ -body {
+ clock scan 2004-13-01 -format %Y-%m-%d
+ } -result [clock scan 2005-01-01 -format %Y-%m-%d]
+test clock-46.4 {regression test - month thirteen} \
+ -body {
+ clock scan 20041301
+ } -result [clock scan 2005-01-01 -format %Y-%m-%d]
+
+test clock-47.1 {regression test - four-digit time} {
+ clock scan 0012
+} [clock scan 0012 -format %H%M]
+test clock-47.2 {regression test - four digit time} {
+ clock scan 0039
+} [clock scan 0039 -format %H%M]
+
+test clock-48.1 {Bug 1185933: 'i' destroyed by clock init} -setup {
+ interp create child
+} -body {
+ interp eval child {
+ set i 12345
+ clock format 0
+ list [catch { set i } result] $result
+ }
+} -cleanup {
+ interp delete child
+} -result {0 12345}
+
+test clock-49.1 {regression test - localtime with negative arg (Bug 1237907)} \
+ -body {
+ list [catch {
+ clock format -86400 -timezone :localtime -format %Y
+ } result] $result
+ } \
+ -match regexp \
+ -result {0 1969|1 {localtime failed \(clock value may be too large/small to represent\)}}
+
+test clock-49.2 {regression test - missing time zone file (Bug 1237907)} \
+ -constraints win \
+ -setup {
+ # override the registry so that the test takes place in New York time
+ namespace eval ::tcl::clock {
+ namespace import -force ::testClock::registry
+ }
+ set noreg [info exists ::tcl::clock::NoRegistry]
+ if {$noreg} {unset ::tcl::clock::NoRegistry}
+ if { [info exists env(TZ)] } {
+ set oldTZ $env(TZ)
+ unset env(TZ)
+ }
+ if { [info exists env(TCL_TZ)] } {
+ set oldTclTZ $env(TCL_TZ)
+ unset env(TCL_TZ)
+ }
+ # make it so New York time is a missing file
+ dict set ::tcl::clock::WinZoneInfo \
+ {-18000 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} \
+ :No/Such/File
+ ::tcl::clock::ClearCaches
+ } \
+ -body {
+ list [::tcl::clock::GuessWindowsTimeZone] \
+ [clock format 0 -locale system -format "%H:%M:%S %Z"] \
+ [clock format -86400 -format "%Y"]
+ } \
+ -cleanup {
+ # restore the registry and environment
+ namespace eval ::tcl::clock {
+ rename registry {}
+ }
+ if {$noreg} {set ::tcl::clock::NoRegistry {}}
+ if { [info exists oldTclTZ] } {
+ set env(TCL_TZ) $oldTclTZ
+ }
+ if { [info exists oldTZ] } {
+ set env(TZ) $oldTZ
+ }
+ # put New York back on the map
+ dict set ::tcl::clock::WinZoneInfo \
+ {-18000 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} \
+ :America/New_York
+ ::tcl::clock::ClearCaches
+ } \
+ -result {<-0500>+05:00:00<-0400>+04:00:00,M3.2.0/02:00:00,M11.1.0/02:00:00 {19:00:00 -0500} 1969}
+
+test clock-50.1 {format / scan -1 as a local time} {
+ if {[catch {
+ clock scan \
+ [clock format -1 -format %Y%m%d%H%M%S -timezone :localtime] \
+ -format %Y%m%d%H%M%S -timezone :localtime
+ } result]} {
+ if { [regexp " too large" $result] } {
+ set result -1
+ }
+ }
+ set result
+} -1
+test clock-50.2 {format / scan -2 as a local time} {
+ if {[catch {
+ clock scan \
+ [clock format -2 -format %Y%m%d%H%M%S -timezone :localtime] \
+ -format %Y%m%d%H%M%S -timezone :localtime
+ } result]} {
+ if { [regexp " too large" $result] } {
+ set result -2
+ }
+ }
+ set result
+} -2
+
+test clock-51.1 {correct conversion of times in Sydney} {
+ # Paul Mackerras reported a bug where DST rollover in New South Wales
+ # was miscalculated. The problem was that tclZIC.tcl had a
+ # typo in the switch case where DST begins/ends at a given time
+ # Standard Time (that is, winter time).
+ set result {}
+ foreach t {1130601599 1130601600 1130637599 1130637600} {
+ lappend result [clock format $t -format %H:%M:%S \
+ -timezone :Australia/Sydney]
+ }
+ set result
+} {01:59:59 03:00:00 12:59:59 13:00:00}
+
+test clock-52.1 {Posix timezone and conversion on last Sunday} {
+ # Martin Lemburg reported a bug where if tzdata is missing, then
+ # times are converted incorrectly in locales where DST conversion
+ # happens in the last (nominal 5th) week of a month.
+ set result {}
+ set timezone <MEZ>-01:00:00<MESZ>-02:00:00,M3.5.0/02:00:00,M10.5.0/01:00:00
+ foreach t {1143334799 1143334800} {
+ lappend result [clock format $t -format %H:%M:%S -timezone $timezone] \
+ [clock format $t -format %H:%M:%S -timezone :Europe/Berlin]
+ }
+ set result
+} {01:59:59 01:59:59 03:00:00 03:00:00}
+
+test clock-52.2 {correct conversion of times in Europe} {
+ # [Bug 2207436]
+ set result {}
+ foreach t [list 1206838799 1206838800 1224982799 1224982800] {
+ lappend result [clock format $t -format %H:%M:%S \
+ -timezone MET-1METDST]
+ lappend result [clock format $t -format %H:%M:%S \
+ -timezone MET0METDST]
+ }
+ set result
+} {01:59:59 00:59:59 03:00:00 02:00:00 02:59:59 01:59:59 02:00:00 01:00:00}
+
+test clock-52.3 {correct conversion of times in Russia} {
+ # [Bug 2207436]
+ set result {}
+ foreach t [list 1206799199 1206799200 1224943199 1224943200] {
+ lappend result [clock format $t -format %H:%M:%S \
+ -timezone WST-12WSTDST]
+ }
+ set result
+} {01:59:59 03:00:00 02:59:59 02:00:00}
+
+test clock-52.4 {correct conversion of times in USA} {
+ # [Bug 2207436]
+ set result {}
+ foreach t [list 1268549999 1268550000 1257055199 1257055200] {
+ lappend result [clock format $t -format %H:%M:%S \
+ -timezone EST5EDT]
+ }
+ set result
+} {01:59:59 03:00:00 01:59:59 01:00:00}
+
+# Regression test for Bug # 1505383
+
+test clock-53.1 {%EC %Ey} {
+ clock format 0 -gmt true -locale en_US_roman -format %EC%Ey
+} mcmlxx
+
+# Test that glob-special characters can be handled in [clock]
+
+test clock-54.1 {glob specials in [clock format]} \
+ -setup {
+ clock format 0 -gmt 1 -format %Y
+ } \
+ -body {
+ clock format 0 -gmt 1 -format {*[%Y%m%d]*}
+ } \
+ -result {*[19700101]*}
+test clock-54.2 {glob specials in [clock scan]} \
+ -setup {
+ clock scan 1970 -gmt 1 -format %Y
+ } \
+ -body {
+ clock scan {*[19700101]*} -format {*[%Y%m%d]*} -gmt 1
+ } \
+ -result 0
+
+test clock-55.1 {Common Era} {
+ clock format -62135769600 -gmt 1 -format {%d %m %Y %EE}
+} {01 01 0001 C.E.}
+test clock-55.2 {Common Era} {
+ clock format -62135769600 -gmt 1 -format {%d %m %Y %EE} -locale en_US_roman
+} {01 01 0001 Anno Domini}
+test clock-55.3 {Before the Common Era} {
+ clock format -62135769601 -gmt 1 -format {%d %m %Y %EE}
+} {31 12 0001 B.C.E.}
+test clock-55.4 {Before the Common Era} {
+ clock format -62135769601 -gmt 1 -format {%d %m %Y %EE} -locale en_US_roman
+} {31 12 0001 Before Christ}
+test clock-55.5 {Common Era} {
+ clock scan {01 01 0001 C.E.} \
+ -gmt 1 -format {%d %m %Y %EE} -locale en_US_roman
+} -62135769600
+test clock-55.6 {Common Era} {
+ clock scan {01 01 0001 A.D.} \
+ -gmt 1 -format {%d %m %Y %EE} -locale en_US_roman
+} -62135769600
+test clock-55.7 {Common Era} {
+ clock scan {01 01 0001 Anno Domini} \
+ -gmt 1 -format {%d %m %Y %EE} -locale en_US_roman
+} -62135769600
+test clock-55.8 {Before the Common Era} {
+ clock scan {31 12 0001 B.C.E.} \
+ -gmt 1 -format {%d %m %Y %EE} -locale en_US_roman
+} -62135856000
+test clock-55.9 {Common Era} {
+ clock scan {31 12 0001 B.C.} \
+ -gmt 1 -format {%d %m %Y %EE} -locale en_US_roman
+} -62135856000
+test clock-55.10 {Common Era} {
+ clock scan {31 12 0001 Before Christ} \
+ -gmt 1 -format {%d %m %Y %EE} -locale en_US_roman
+} -62135856000
+
+test clock-56.1 {use of zoneinfo, version 1} {*}{
+ -setup {
+ clock format [clock seconds]
+ set tzdir [makeDirectory zoneinfo]
+ set tzdir2 [makeDirectory Test $tzdir]
+ set tzfile [makeFile {} PhoenixOne $tzdir2]
+ set f [open $tzfile wb]
+ puts -nonewline $f [binary format c* {
+ 0x54 0x5a 0x69 0x66 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x03
+ 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x0a
+ 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x0c 0x9e 0xa6 0x3a 0x90
+ 0x9f 0xbb 0x07 0x80 0xa0 0x86 0x1c 0x90 0xa1 0x9a 0xe9 0x80
+ 0xcb 0x89 0x0c 0x90 0xcf 0x17 0xdf 0x1c 0xcf 0x8f 0xe5 0xac
+ 0xd0 0x81 0x1a 0x1c 0xfa 0xf8 0x75 0x10 0xfb 0xe8 0x58 0x00
+ 0x00 0x01 0x00 0x01 0x02 0x01 0x02 0x01 0x00 0x01 0xff 0xff
+ 0xab 0xa0 0x01 0x00 0xff 0xff 0x9d 0x90 0x00 0x04 0xff 0xff
+ 0xab 0xa0 0x01 0x08 0x4d 0x44 0x54 0x00 0x4d 0x53 0x54 0x00
+ 0x4d 0x57 0x54 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ }]
+ close $f
+ set ::tcl::clock::ZoneinfoPaths \
+ [linsert $::tcl::clock::ZoneinfoPaths 0 $tzdir]
+ ::tcl::clock::ClearCaches
+ }
+ -cleanup {
+ set ::tcl::clock::ZoneinfoPaths \
+ [lrange $::tcl::clock::ZoneinfoPaths 1 end]
+ ::tcl::clock::ClearCaches
+ removeFile PhoenixOne $tzdir2
+ removeDirectory Test $tzdir
+ removeDirectory zoneinfo
+ }
+ -body {
+ clock format 1072940400 -timezone :Test/PhoenixOne \
+ -format {%Y-%m-%d %H:%M:%S %Z}
+ }
+ -result {2004-01-01 00:00:00 MST}
+}
+
+test clock-56.2 {use of zoneinfo, version 2} {*}{
+ -setup {
+ clock format [clock seconds]
+ set tzdir [makeDirectory zoneinfo]
+ set tzdir2 [makeDirectory Test $tzdir]
+ set tzfile [makeFile {} PhoenixTwo $tzdir2]
+ set f [open $tzfile wb]
+ puts -nonewline $f [binary format c* {
+ 0x54 0x5a 0x69 0x66 0x32 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x03
+ 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x0a
+ 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x0c 0x9e 0xa6 0x3a 0x90
+ 0x9f 0xbb 0x07 0x80 0xa0 0x86 0x1c 0x90 0xa1 0x9a 0xe9 0x80
+ 0xcb 0x89 0x0c 0x90 0xcf 0x17 0xdf 0x1c 0xcf 0x8f 0xe5 0xac
+ 0xd0 0x81 0x1a 0x1c 0xfa 0xf8 0x75 0x10 0xfb 0xe8 0x58 0x00
+ 0x00 0x01 0x00 0x01 0x02 0x01 0x02 0x01 0x00 0x01 0xff 0xff
+ 0xab 0xa0 0x01 0x00 0xff 0xff 0x9d 0x90 0x00 0x04 0xff 0xff
+ 0xab 0xa0 0x01 0x08 0x4d 0x44 0x54 0x00 0x4d 0x53 0x54 0x00
+ 0x4d 0x57 0x54 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x54 0x5a
+ 0x69 0x66 0x32 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x04 0x00 0x00
+ 0x00 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x0b 0x00 0x00
+ 0x00 0x04 0x00 0x00 0x00 0x10 0xff 0xff 0xff 0xff 0x5e 0x04
+ 0x0c 0xb0 0xff 0xff 0xff 0xff 0x9e 0xa6 0x3a 0x90 0xff 0xff
+ 0xff 0xff 0x9f 0xbb 0x07 0x80 0xff 0xff 0xff 0xff 0xa0 0x86
+ 0x1c 0x90 0xff 0xff 0xff 0xff 0xa1 0x9a 0xe9 0x80 0xff 0xff
+ 0xff 0xff 0xcb 0x89 0x0c 0x90 0xff 0xff 0xff 0xff 0xcf 0x17
+ 0xdf 0x1c 0xff 0xff 0xff 0xff 0xcf 0x8f 0xe5 0xac 0xff 0xff
+ 0xff 0xff 0xd0 0x81 0x1a 0x1c 0xff 0xff 0xff 0xff 0xfa 0xf8
+ 0x75 0x10 0xff 0xff 0xff 0xff 0xfb 0xe8 0x58 0x00 0x02 0x01
+ 0x02 0x01 0x02 0x03 0x02 0x03 0x02 0x01 0x02 0xff 0xff 0x96
+ 0xee 0x00 0x00 0xff 0xff 0xab 0xa0 0x01 0x04 0xff 0xff 0x9d
+ 0x90 0x00 0x08 0xff 0xff 0xab 0xa0 0x01 0x0c 0x4c 0x4d 0x54
+ 0x00 0x4d 0x44 0x54 0x00 0x4d 0x53 0x54 0x00 0x4d 0x57 0x54
+ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x0a 0x4d 0x53
+ 0x54 0x37 0x0a
+ }]
+ close $f
+ set ::tcl::clock::ZoneinfoPaths \
+ [linsert $::tcl::clock::ZoneinfoPaths 0 $tzdir]
+ ::tcl::clock::ClearCaches
+ }
+ -cleanup {
+ set ::tcl::clock::ZoneinfoPaths \
+ [lrange $::tcl::clock::ZoneinfoPaths 1 end]
+ ::tcl::clock::ClearCaches
+ removeFile PhoenixTwo $tzdir2
+ removeDirectory Test $tzdir
+ removeDirectory zoneinfo
+ }
+ -body {
+ clock format 1072940400 -timezone :Test/PhoenixTwo \
+ -format {%Y-%m-%d %H:%M:%S %Z}
+ }
+ -result {2004-01-01 00:00:00 MST}
+}
+
+test clock-56.3 {use of zoneinfo, version 2, Y2038 compliance} {*}{
+ -setup {
+ clock format [clock seconds]
+ set tzdir [makeDirectory zoneinfo]
+ set tzdir2 [makeDirectory Test $tzdir]
+ set tzfile [makeFile {} TijuanaTwo $tzdir2]
+ set f [open $tzfile wb]
+ puts -nonewline $f [binary format c* {
+ 0x54 0x5a 0x69 0x66 0x32 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x06 0x00 0x00
+ 0x00 0x06 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x95 0x00 0x00 0x00
+ 0x06 0x00 0x00 0x00 0x18 0xa5 0xb6 0xf6 0x80 0xa9 0x79 0x4f 0x70
+ 0xaf 0xf2 0x7c 0xf0 0xb6 0x66 0x64 0x70 0xb7 0x1b 0x10 0x00 0xb8
+ 0x0a 0xf2 0xf0 0xcb 0xea 0x8d 0x80 0xd2 0x23 0xf4 0x70 0xd2 0x99
+ 0xba 0x70 0xd7 0x1b 0x59 0x00 0xd8 0x91 0xb4 0xf0 0xe2 0x7e 0x59
+ 0xa0 0xe3 0x49 0x52 0x90 0xe4 0x5e 0x3b 0xa0 0xe5 0x29 0x34 0x90
+ 0xe6 0x47 0x58 0x20 0xe7 0x12 0x51 0x10 0xe8 0x27 0x3a 0x20 0xe8
+ 0xf2 0x33 0x10 0xea 0x07 0x1c 0x20 0xea 0xd2 0x15 0x10 0xeb 0xe6
+ 0xfe 0x20 0xec 0xb1 0xf7 0x10 0xed 0xc6 0xe0 0x20 0xee 0x91 0xd9
+ 0x10 0x0b 0xe0 0xaf 0xa0 0x0c 0xd9 0xcd 0x10 0x0d 0xc0 0x91 0xa0
+ 0x0e 0xb9 0xaf 0x10 0x0f 0xa9 0xae 0x20 0x10 0x99 0x91 0x10 0x11
+ 0x89 0x90 0x20 0x12 0x79 0x73 0x10 0x13 0x69 0x72 0x20 0x14 0x59
+ 0x55 0x10 0x15 0x49 0x54 0x20 0x16 0x39 0x37 0x10 0x17 0x29 0x36
+ 0x20 0x18 0x22 0x53 0x90 0x19 0x09 0x18 0x20 0x1a 0x02 0x35 0x90
+ 0x1a 0xf2 0x34 0xa0 0x1b 0xe2 0x17 0x90 0x1c 0xd2 0x16 0xa0 0x1d
+ 0xc1 0xf9 0x90 0x1e 0xb1 0xf8 0xa0 0x1f 0xa1 0xdb 0x90 0x20 0x76
+ 0x2b 0x20 0x21 0x81 0xbd 0x90 0x22 0x56 0x0d 0x20 0x23 0x6a 0xda
+ 0x10 0x24 0x35 0xef 0x20 0x25 0x4a 0xbc 0x10 0x26 0x15 0xd1 0x20
+ 0x27 0x2a 0x9e 0x10 0x27 0xfe 0xed 0xa0 0x29 0x0a 0x80 0x10 0x29
+ 0xde 0xcf 0xa0 0x2a 0xea 0x62 0x10 0x2b 0xbe 0xb1 0xa0 0x2c 0xd3
+ 0x7e 0x90 0x2d 0x9e 0x93 0xa0 0x2e 0xb3 0x60 0x90 0x2f 0x7e 0x75
+ 0xa0 0x30 0x93 0x42 0x90 0x31 0x67 0x92 0x20 0x32 0x73 0x24 0x90
+ 0x33 0x47 0x74 0x20 0x34 0x53 0x06 0x90 0x35 0x27 0x56 0x20 0x36
+ 0x32 0xe8 0x90 0x37 0x07 0x38 0x20 0x38 0x1c 0x05 0x10 0x38 0xe7
+ 0x1a 0x20 0x39 0xfb 0xe7 0x10 0x3a 0xc6 0xfc 0x20 0x3b 0xdb 0xc9
+ 0x10 0x3c 0xb0 0x18 0xa0 0x3d 0xbb 0xab 0x10 0x3e 0x8f 0xfa 0xa0
+ 0x3f 0x9b 0x8d 0x10 0x40 0x6f 0xdc 0xa0 0x41 0x84 0xa9 0x90 0x42
+ 0x4f 0xbe 0xa0 0x43 0x64 0x8b 0x90 0x44 0x2f 0xa0 0xa0 0x45 0x44
+ 0x6d 0x90 0x46 0x0f 0x82 0xa0 0x47 0x24 0x4f 0x90 0x47 0xf8 0x9f
+ 0x20 0x49 0x04 0x31 0x90 0x49 0xd8 0x81 0x20 0x4a 0xe4 0x13 0x90
+ 0x4b 0xb8 0x63 0x20 0x4c 0xcd 0x30 0x10 0x4d 0x98 0x45 0x20 0x4e
+ 0xad 0x12 0x10 0x4f 0x78 0x27 0x20 0x50 0x8c 0xf4 0x10 0x51 0x61
+ 0x43 0xa0 0x52 0x6c 0xd6 0x10 0x53 0x41 0x25 0xa0 0x54 0x4c 0xb8
+ 0x10 0x55 0x21 0x07 0xa0 0x56 0x2c 0x9a 0x10 0x57 0x00 0xe9 0xa0
+ 0x58 0x15 0xb6 0x90 0x58 0xe0 0xcb 0xa0 0x59 0xf5 0x98 0x90 0x5a
+ 0xc0 0xad 0xa0 0x5b 0xd5 0x7a 0x90 0x5c 0xa9 0xca 0x20 0x5d 0xb5
+ 0x5c 0x90 0x5e 0x89 0xac 0x20 0x5f 0x95 0x3e 0x90 0x60 0x69 0x8e
+ 0x20 0x61 0x7e 0x5b 0x10 0x62 0x49 0x70 0x20 0x63 0x5e 0x3d 0x10
+ 0x64 0x29 0x52 0x20 0x65 0x3e 0x1f 0x10 0x66 0x12 0x6e 0xa0 0x67
+ 0x1e 0x01 0x10 0x67 0xf2 0x50 0xa0 0x68 0xfd 0xe3 0x10 0x69 0xd2
+ 0x32 0xa0 0x6a 0xdd 0xc5 0x10 0x6b 0xb2 0x14 0xa0 0x6c 0xc6 0xe1
+ 0x90 0x6d 0x91 0xf6 0xa0 0x6e 0xa6 0xc3 0x90 0x6f 0x71 0xd8 0xa0
+ 0x70 0x86 0xa5 0x90 0x71 0x5a 0xf5 0x20 0x72 0x66 0x87 0x90 0x73
+ 0x3a 0xd7 0x20 0x74 0x46 0x69 0x90 0x75 0x1a 0xb9 0x20 0x76 0x2f
+ 0x86 0x10 0x76 0xfa 0x9b 0x20 0x78 0x0f 0x68 0x10 0x78 0xda 0x7d
+ 0x20 0x79 0xef 0x4a 0x10 0x7a 0xba 0x5f 0x20 0x7b 0xcf 0x2c 0x10
+ 0x7c 0xa3 0x7b 0xa0 0x7d 0xaf 0x0e 0x10 0x7e 0x83 0x5d 0xa0 0x7f
+ 0x8e 0xf0 0x10 0x01 0x02 0x01 0x02 0x03 0x02 0x04 0x05 0x02 0x03
+ 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02
+ 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03
+ 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02
+ 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03
+ 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02
+ 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03
+ 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02
+ 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03
+ 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02
+ 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03
+ 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0xff 0xff 0x92 0x4c
+ 0x00 0x00 0xff 0xff 0x9d 0x90 0x00 0x04 0xff 0xff 0x8f 0x80 0x00
+ 0x08 0xff 0xff 0x9d 0x90 0x01 0x0c 0xff 0xff 0x9d 0x90 0x01 0x10
+ 0xff 0xff 0x9d 0x90 0x01 0x14 0x4c 0x4d 0x54 0x00 0x4d 0x53 0x54
+ 0x00 0x50 0x53 0x54 0x00 0x50 0x44 0x54 0x00 0x50 0x57 0x54 0x00
+ 0x50 0x50 0x54 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x00 0x00 0x00
+ 0x00 0x00 0x01 0x54 0x5a 0x69 0x66 0x32 0x00 0x00 0x00 0x00 0x00
+ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ 0x06 0x00 0x00 0x00 0x06 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x95
+ 0x00 0x00 0x00 0x06 0x00 0x00 0x00 0x18 0xff 0xff 0xff 0xff 0xa5
+ 0xb6 0xf6 0x80 0xff 0xff 0xff 0xff 0xa9 0x79 0x4f 0x70 0xff 0xff
+ 0xff 0xff 0xaf 0xf2 0x7c 0xf0 0xff 0xff 0xff 0xff 0xb6 0x66 0x64
+ 0x70 0xff 0xff 0xff 0xff 0xb7 0x1b 0x10 0x00 0xff 0xff 0xff 0xff
+ 0xb8 0x0a 0xf2 0xf0 0xff 0xff 0xff 0xff 0xcb 0xea 0x8d 0x80 0xff
+ 0xff 0xff 0xff 0xd2 0x23 0xf4 0x70 0xff 0xff 0xff 0xff 0xd2 0x99
+ 0xba 0x70 0xff 0xff 0xff 0xff 0xd7 0x1b 0x59 0x00 0xff 0xff 0xff
+ 0xff 0xd8 0x91 0xb4 0xf0 0xff 0xff 0xff 0xff 0xe2 0x7e 0x59 0xa0
+ 0xff 0xff 0xff 0xff 0xe3 0x49 0x52 0x90 0xff 0xff 0xff 0xff 0xe4
+ 0x5e 0x3b 0xa0 0xff 0xff 0xff 0xff 0xe5 0x29 0x34 0x90 0xff 0xff
+ 0xff 0xff 0xe6 0x47 0x58 0x20 0xff 0xff 0xff 0xff 0xe7 0x12 0x51
+ 0x10 0xff 0xff 0xff 0xff 0xe8 0x27 0x3a 0x20 0xff 0xff 0xff 0xff
+ 0xe8 0xf2 0x33 0x10 0xff 0xff 0xff 0xff 0xea 0x07 0x1c 0x20 0xff
+ 0xff 0xff 0xff 0xea 0xd2 0x15 0x10 0xff 0xff 0xff 0xff 0xeb 0xe6
+ 0xfe 0x20 0xff 0xff 0xff 0xff 0xec 0xb1 0xf7 0x10 0xff 0xff 0xff
+ 0xff 0xed 0xc6 0xe0 0x20 0xff 0xff 0xff 0xff 0xee 0x91 0xd9 0x10
+ 0x00 0x00 0x00 0x00 0x0b 0xe0 0xaf 0xa0 0x00 0x00 0x00 0x00 0x0c
+ 0xd9 0xcd 0x10 0x00 0x00 0x00 0x00 0x0d 0xc0 0x91 0xa0 0x00 0x00
+ 0x00 0x00 0x0e 0xb9 0xaf 0x10 0x00 0x00 0x00 0x00 0x0f 0xa9 0xae
+ 0x20 0x00 0x00 0x00 0x00 0x10 0x99 0x91 0x10 0x00 0x00 0x00 0x00
+ 0x11 0x89 0x90 0x20 0x00 0x00 0x00 0x00 0x12 0x79 0x73 0x10 0x00
+ 0x00 0x00 0x00 0x13 0x69 0x72 0x20 0x00 0x00 0x00 0x00 0x14 0x59
+ 0x55 0x10 0x00 0x00 0x00 0x00 0x15 0x49 0x54 0x20 0x00 0x00 0x00
+ 0x00 0x16 0x39 0x37 0x10 0x00 0x00 0x00 0x00 0x17 0x29 0x36 0x20
+ 0x00 0x00 0x00 0x00 0x18 0x22 0x53 0x90 0x00 0x00 0x00 0x00 0x19
+ 0x09 0x18 0x20 0x00 0x00 0x00 0x00 0x1a 0x02 0x35 0x90 0x00 0x00
+ 0x00 0x00 0x1a 0xf2 0x34 0xa0 0x00 0x00 0x00 0x00 0x1b 0xe2 0x17
+ 0x90 0x00 0x00 0x00 0x00 0x1c 0xd2 0x16 0xa0 0x00 0x00 0x00 0x00
+ 0x1d 0xc1 0xf9 0x90 0x00 0x00 0x00 0x00 0x1e 0xb1 0xf8 0xa0 0x00
+ 0x00 0x00 0x00 0x1f 0xa1 0xdb 0x90 0x00 0x00 0x00 0x00 0x20 0x76
+ 0x2b 0x20 0x00 0x00 0x00 0x00 0x21 0x81 0xbd 0x90 0x00 0x00 0x00
+ 0x00 0x22 0x56 0x0d 0x20 0x00 0x00 0x00 0x00 0x23 0x6a 0xda 0x10
+ 0x00 0x00 0x00 0x00 0x24 0x35 0xef 0x20 0x00 0x00 0x00 0x00 0x25
+ 0x4a 0xbc 0x10 0x00 0x00 0x00 0x00 0x26 0x15 0xd1 0x20 0x00 0x00
+ 0x00 0x00 0x27 0x2a 0x9e 0x10 0x00 0x00 0x00 0x00 0x27 0xfe 0xed
+ 0xa0 0x00 0x00 0x00 0x00 0x29 0x0a 0x80 0x10 0x00 0x00 0x00 0x00
+ 0x29 0xde 0xcf 0xa0 0x00 0x00 0x00 0x00 0x2a 0xea 0x62 0x10 0x00
+ 0x00 0x00 0x00 0x2b 0xbe 0xb1 0xa0 0x00 0x00 0x00 0x00 0x2c 0xd3
+ 0x7e 0x90 0x00 0x00 0x00 0x00 0x2d 0x9e 0x93 0xa0 0x00 0x00 0x00
+ 0x00 0x2e 0xb3 0x60 0x90 0x00 0x00 0x00 0x00 0x2f 0x7e 0x75 0xa0
+ 0x00 0x00 0x00 0x00 0x30 0x93 0x42 0x90 0x00 0x00 0x00 0x00 0x31
+ 0x67 0x92 0x20 0x00 0x00 0x00 0x00 0x32 0x73 0x24 0x90 0x00 0x00
+ 0x00 0x00 0x33 0x47 0x74 0x20 0x00 0x00 0x00 0x00 0x34 0x53 0x06
+ 0x90 0x00 0x00 0x00 0x00 0x35 0x27 0x56 0x20 0x00 0x00 0x00 0x00
+ 0x36 0x32 0xe8 0x90 0x00 0x00 0x00 0x00 0x37 0x07 0x38 0x20 0x00
+ 0x00 0x00 0x00 0x38 0x1c 0x05 0x10 0x00 0x00 0x00 0x00 0x38 0xe7
+ 0x1a 0x20 0x00 0x00 0x00 0x00 0x39 0xfb 0xe7 0x10 0x00 0x00 0x00
+ 0x00 0x3a 0xc6 0xfc 0x20 0x00 0x00 0x00 0x00 0x3b 0xdb 0xc9 0x10
+ 0x00 0x00 0x00 0x00 0x3c 0xb0 0x18 0xa0 0x00 0x00 0x00 0x00 0x3d
+ 0xbb 0xab 0x10 0x00 0x00 0x00 0x00 0x3e 0x8f 0xfa 0xa0 0x00 0x00
+ 0x00 0x00 0x3f 0x9b 0x8d 0x10 0x00 0x00 0x00 0x00 0x40 0x6f 0xdc
+ 0xa0 0x00 0x00 0x00 0x00 0x41 0x84 0xa9 0x90 0x00 0x00 0x00 0x00
+ 0x42 0x4f 0xbe 0xa0 0x00 0x00 0x00 0x00 0x43 0x64 0x8b 0x90 0x00
+ 0x00 0x00 0x00 0x44 0x2f 0xa0 0xa0 0x00 0x00 0x00 0x00 0x45 0x44
+ 0x6d 0x90 0x00 0x00 0x00 0x00 0x46 0x0f 0x82 0xa0 0x00 0x00 0x00
+ 0x00 0x47 0x24 0x4f 0x90 0x00 0x00 0x00 0x00 0x47 0xf8 0x9f 0x20
+ 0x00 0x00 0x00 0x00 0x49 0x04 0x31 0x90 0x00 0x00 0x00 0x00 0x49
+ 0xd8 0x81 0x20 0x00 0x00 0x00 0x00 0x4a 0xe4 0x13 0x90 0x00 0x00
+ 0x00 0x00 0x4b 0xb8 0x63 0x20 0x00 0x00 0x00 0x00 0x4c 0xcd 0x30
+ 0x10 0x00 0x00 0x00 0x00 0x4d 0x98 0x45 0x20 0x00 0x00 0x00 0x00
+ 0x4e 0xad 0x12 0x10 0x00 0x00 0x00 0x00 0x4f 0x78 0x27 0x20 0x00
+ 0x00 0x00 0x00 0x50 0x8c 0xf4 0x10 0x00 0x00 0x00 0x00 0x51 0x61
+ 0x43 0xa0 0x00 0x00 0x00 0x00 0x52 0x6c 0xd6 0x10 0x00 0x00 0x00
+ 0x00 0x53 0x41 0x25 0xa0 0x00 0x00 0x00 0x00 0x54 0x4c 0xb8 0x10
+ 0x00 0x00 0x00 0x00 0x55 0x21 0x07 0xa0 0x00 0x00 0x00 0x00 0x56
+ 0x2c 0x9a 0x10 0x00 0x00 0x00 0x00 0x57 0x00 0xe9 0xa0 0x00 0x00
+ 0x00 0x00 0x58 0x15 0xb6 0x90 0x00 0x00 0x00 0x00 0x58 0xe0 0xcb
+ 0xa0 0x00 0x00 0x00 0x00 0x59 0xf5 0x98 0x90 0x00 0x00 0x00 0x00
+ 0x5a 0xc0 0xad 0xa0 0x00 0x00 0x00 0x00 0x5b 0xd5 0x7a 0x90 0x00
+ 0x00 0x00 0x00 0x5c 0xa9 0xca 0x20 0x00 0x00 0x00 0x00 0x5d 0xb5
+ 0x5c 0x90 0x00 0x00 0x00 0x00 0x5e 0x89 0xac 0x20 0x00 0x00 0x00
+ 0x00 0x5f 0x95 0x3e 0x90 0x00 0x00 0x00 0x00 0x60 0x69 0x8e 0x20
+ 0x00 0x00 0x00 0x00 0x61 0x7e 0x5b 0x10 0x00 0x00 0x00 0x00 0x62
+ 0x49 0x70 0x20 0x00 0x00 0x00 0x00 0x63 0x5e 0x3d 0x10 0x00 0x00
+ 0x00 0x00 0x64 0x29 0x52 0x20 0x00 0x00 0x00 0x00 0x65 0x3e 0x1f
+ 0x10 0x00 0x00 0x00 0x00 0x66 0x12 0x6e 0xa0 0x00 0x00 0x00 0x00
+ 0x67 0x1e 0x01 0x10 0x00 0x00 0x00 0x00 0x67 0xf2 0x50 0xa0 0x00
+ 0x00 0x00 0x00 0x68 0xfd 0xe3 0x10 0x00 0x00 0x00 0x00 0x69 0xd2
+ 0x32 0xa0 0x00 0x00 0x00 0x00 0x6a 0xdd 0xc5 0x10 0x00 0x00 0x00
+ 0x00 0x6b 0xb2 0x14 0xa0 0x00 0x00 0x00 0x00 0x6c 0xc6 0xe1 0x90
+ 0x00 0x00 0x00 0x00 0x6d 0x91 0xf6 0xa0 0x00 0x00 0x00 0x00 0x6e
+ 0xa6 0xc3 0x90 0x00 0x00 0x00 0x00 0x6f 0x71 0xd8 0xa0 0x00 0x00
+ 0x00 0x00 0x70 0x86 0xa5 0x90 0x00 0x00 0x00 0x00 0x71 0x5a 0xf5
+ 0x20 0x00 0x00 0x00 0x00 0x72 0x66 0x87 0x90 0x00 0x00 0x00 0x00
+ 0x73 0x3a 0xd7 0x20 0x00 0x00 0x00 0x00 0x74 0x46 0x69 0x90 0x00
+ 0x00 0x00 0x00 0x75 0x1a 0xb9 0x20 0x00 0x00 0x00 0x00 0x76 0x2f
+ 0x86 0x10 0x00 0x00 0x00 0x00 0x76 0xfa 0x9b 0x20 0x00 0x00 0x00
+ 0x00 0x78 0x0f 0x68 0x10 0x00 0x00 0x00 0x00 0x78 0xda 0x7d 0x20
+ 0x00 0x00 0x00 0x00 0x79 0xef 0x4a 0x10 0x00 0x00 0x00 0x00 0x7a
+ 0xba 0x5f 0x20 0x00 0x00 0x00 0x00 0x7b 0xcf 0x2c 0x10 0x00 0x00
+ 0x00 0x00 0x7c 0xa3 0x7b 0xa0 0x00 0x00 0x00 0x00 0x7d 0xaf 0x0e
+ 0x10 0x00 0x00 0x00 0x00 0x7e 0x83 0x5d 0xa0 0x00 0x00 0x00 0x00
+ 0x7f 0x8e 0xf0 0x10 0x01 0x02 0x01 0x02 0x03 0x02 0x04 0x05 0x02
+ 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03
+ 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02
+ 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03
+ 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02
+ 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03
+ 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02
+ 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03
+ 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02
+ 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03
+ 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02
+ 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0x03 0x02 0xff 0xff 0x92
+ 0x4c 0x00 0x00 0xff 0xff 0x9d 0x90 0x00 0x04 0xff 0xff 0x8f 0x80
+ 0x00 0x08 0xff 0xff 0x9d 0x90 0x01 0x0c 0xff 0xff 0x9d 0x90 0x01
+ 0x10 0xff 0xff 0x9d 0x90 0x01 0x14 0x4c 0x4d 0x54 0x00 0x4d 0x53
+ 0x54 0x00 0x50 0x53 0x54 0x00 0x50 0x44 0x54 0x00 0x50 0x57 0x54
+ 0x00 0x50 0x50 0x54 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x00 0x00
+ 0x00 0x00 0x00 0x01 0x0a 0x50 0x53 0x54 0x38 0x50 0x44 0x54 0x2c
+ 0x4d 0x34 0x2e 0x31 0x2e 0x30 0x2c 0x4d 0x31 0x30 0x2e 0x35 0x2e
+ 0x30 0x0a
+ }]
+ close $f
+ set ::tcl::clock::ZoneinfoPaths \
+ [linsert $::tcl::clock::ZoneinfoPaths 0 $tzdir]
+ ::tcl::clock::ClearCaches
+ }
+ -cleanup {
+ set ::tcl::clock::ZoneinfoPaths \
+ [lrange $::tcl::clock::ZoneinfoPaths 1 end]
+ ::tcl::clock::ClearCaches
+ removeFile TijuanaTwo $tzdir2
+ removeDirectory Test $tzdir
+ removeDirectory zoneinfo
+ }
+ -body {
+ clock format 2224738800 -timezone :Test/TijuanaTwo \
+ -format {%Y-%m-%d %H:%M:%S %Z}
+ }
+ -result {2040-07-01 00:00:00 PDT}
+}
+
+test clock-57.1 {clock scan - abbreviated options} {
+ clock scan 1970-01-01 -f %Y-%m-%d -g true
+} 0
+
+test clock-58.1 {clock l10n - Japanese localisation} {*}{
+ -setup {
+ proc backslashify { string } {
+
+ set retval {}
+ foreach char [split $string {}] {
+ scan $char %c ccode
+ if { $ccode >= 0x0020 && $ccode < 0x007f
+ && $char ne "\{" && $char ne "\}" && $char ne "\["
+ && $char ne "\]" && $char ne "\\" && $char ne "\$" } {
+ append retval $char
+ } else {
+ append retval \\u [format %04x $ccode]
+ }
+ }
+ return $retval
+ }
+ }
+ -body {
+ set trouble {}
+ foreach {date jdate} [list \
+ 1872-12-31 \u897f\u66a61872\u5e7412\u670831\u65e5 \
+ 1873-01-01 \u660e\u6cbb06\u5e7401\u670801\u65e5 \
+ 1912-07-29 \u660e\u6cbb45\u5e7407\u670829\u65e5 \
+ 1912-07-30 \u5927\u6b6301\u5e7407\u670830\u65e5 \
+ 1926-12-24 \u5927\u6b6315\u5e7412\u670824\u65e5 \
+ 1926-12-25 \u662d\u548c01\u5e7412\u670825\u65e5 \
+ 1989-01-07 \u662d\u548c64\u5e7401\u670807\u65e5 \
+ 1989-01-08 \u5e73\u621001\u5e7401\u670808\u65e5 \
+ ] {
+ set status [catch {
+ set secs [clock scan $date \
+ -timezone +0900 \
+ -locale ja_JP \
+ -format %Y-%m-%d]
+ set jda [clock format $secs \
+ -timezone +0900 \
+ -locale ja_JP \
+ -format %Ex]
+ } result]
+ if {$status != 0} {
+ append trouble \n $date " gives error " $result
+ } elseif {$jda ne $jdate} {
+ append trouble \n $date " converts to " \
+ [backslashify $jda] " and should be " \
+ [backslashify $jdate]
+ }
+ # There is no code for scanning dates on the locale's
+ # alternative calendar.
+ continue
+ set status [catch {
+ set secs [clock scan $jdate \
+ -timezone +0900 \
+ -locale ja_JP \
+ -format %Ex]
+ set da [clock format $secs \
+ -timezone +0900 \
+ -locale ja_JP \
+ -format %Y-%m-%d]
+ } result]
+ if {$status != 0} {
+ append trouble \n [backslashify $jdate] " gives error " $result
+ } elseif {$da ne $date} {
+ append trouble \n [backslashify $jdate] " converts to " \
+ $da " and should be " $date
+ }
+ }
+ set trouble
+ }
+ -cleanup {
+ rename backslashify {}
+ }
+ -result {}
+}
+
+test clock-59.1 {military time zones} {
+ set hour 0
+ set base [clock scan "20000101 000000" -format "%Y%m%d %H%M%S" -gmt 1]
+ set trouble {}
+ foreach {pzone mzone} {
+ Z Z A N B O C P D Q E R F S G T H U I V K W L X M Y
+ } {
+ catch {clock scan "20000101 000000 $pzone" \
+ -format "%Y%m%d %H%M%S %Z"} ps1
+ catch {clock scan "20000101 000000 $pzone"} ps2
+ catch {clock scan "20000101 000000 $mzone" \
+ -format "%Y%m%d %H%M%S %Z"} ms1
+ catch {clock scan "20000101 000000 $mzone"} ms2
+ if {$ps1 != $base - 3600 * $hour} {
+ lappend trouble [list pzone $pzone hour $hour ps1 is $ps1]
+ }
+ if {$ps2 != $base - 3600 * $hour} {
+ lappend trouble [list pzone $pzone ps2 is $ps2]
+ }
+ if {$ms1 != $base + 3600 * $hour} {
+ lappend trouble [list mzone $mzone ms1 is $ms1]
+ }
+ if {$ms2 != $base + 3600 * $hour} {
+ lappend trouble [list mzone $mzone ms2 is $ms2]
+ }
+ incr hour
+ }
+ join $trouble \n
+} {}
+
+# case-insensitive matching of weekday and month names [Bug 1781282]
+
+test clock-60.1 {case insensitive weekday names} {
+ clock scan "2000-W01 monday" -gmt true -format "%G-W%V %a"
+} [clock scan "2000-W01-1" -gmt true -format "%G-W%V-%u"]
+test clock-60.2 {case insensitive weekday names} {
+ clock scan "2000-W01 Monday" -gmt true -format "%G-W%V %a"
+} [clock scan "2000-W01-1" -gmt true -format "%G-W%V-%u"]
+test clock-60.3 {case insensitive weekday names} {
+ clock scan "2000-W01 MONDAY" -gmt true -format "%G-W%V %a"
+} [clock scan "2000-W01-1" -gmt true -format "%G-W%V-%u"]
+test clock-60.4 {case insensitive weekday names} {
+ clock scan "2000-W01 friday" -gmt true -format "%G-W%V %a"
+} [clock scan "2000-W01-5" -gmt true -format "%G-W%V-%u"]
+test clock-60.5 {case insensitive weekday names} {
+ clock scan "2000-W01 Friday" -gmt true -format "%G-W%V %a"
+} [clock scan "2000-W01-5" -gmt true -format "%G-W%V-%u"]
+test clock-60.6 {case insensitive weekday names} {
+ clock scan "2000-W01 FRIDAY" -gmt true -format "%G-W%V %a"
+} [clock scan "2000-W01-5" -gmt true -format "%G-W%V-%u"]
+test clock-60.7 {case insensitive month names} {
+ clock scan "1 january 2000" -gmt true -format "%d %b %Y"
+} [clock scan "2000-01-01" -gmt true -format "%Y-%m-%d"]
+test clock-60.8 {case insensitive month names} {
+ clock scan "1 January 2000" -gmt true -format "%d %b %Y"
+} [clock scan "2000-01-01" -gmt true -format "%Y-%m-%d"]
+test clock-60.9 {case insensitive month names} {
+ clock scan "1 JANUARY 2000" -gmt true -format "%d %b %Y"
+} [clock scan "2000-01-01" -gmt true -format "%Y-%m-%d"]
+test clock-60.10 {case insensitive month names} {
+ clock scan "1 december 2000" -gmt true -format "%d %b %Y"
+} [clock scan "2000-12-01" -gmt true -format "%Y-%m-%d"]
+test clock-60.11 {case insensitive month names} {
+ clock scan "1 December 2000" -gmt true -format "%d %b %Y"
+} [clock scan "2000-12-01" -gmt true -format "%Y-%m-%d"]
+test clock-60.12 {case insensitive month names} {
+ clock scan "1 DECEMBER 2000" -gmt true -format "%d %b %Y"
+} [clock scan "2000-12-01" -gmt true -format "%Y-%m-%d"]
+
+test clock-61.1 {overflow of a wide integer on output} {*}{
+ -body {
+ clock format 0x8000000000000000 -format %s -gmt true
+ }
+ -result {integer value too large to represent}
+ -returnCodes error
+}
+test clock-61.2 {overflow of a wide integer on output} {*}{
+ -body {
+ clock format -0x8000000000000001 -format %s -gmt true
+ }
+ -result {integer value too large to represent}
+ -returnCodes error
+}
+test clock-61.3 {near-miss overflow of a wide integer on output} {
+ clock format 0x7fffffffffffffff -format %s -gmt true
+} [expr 0x7fffffffffffffff]
+test clock-61.4 {near-miss overflow of a wide integer on output} {
+ clock format -0x8000000000000000 -format %s -gmt true
+} [expr -0x8000000000000000]
+
+test clock-62.1 {Bug 1902423} {*}{
+ -setup {::tcl::clock::ClearCaches}
+ -body {
+ set s 1204049747
+ set f1 [clock format $s -format {%Y-%m-%d %T} -locale C]
+ set f2 [clock format $s -format {%Y-%m-%d %H:%M:%S} -locale C]
+ if {$f1 ne $f2} {
+ subst "$f2 is not $f1"
+ } else {
+ subst "ok"
+ }
+ }
+ -result ok
+}
+
+test clock-63.1 {Incorrect use of internal ConvertLocalToUTC command} {*}{
+ -body {
+ ::tcl::clock::ConvertLocalToUTC {immaterial stuff} {} 12345
+ }
+ -returnCodes error
+ -result {key "localseconds" not found in dictionary}
+}
+
+test clock-64.1 {:: in format string [Bug 2362156]} {*}{
+ -body {
+ clock scan 2001-02-03::04:05:06 -gmt 1 -format %Y-%m-%d::%H:%M:%S
+ }
+ -result 981173106
+}
+test clock-64.2 {:: in format string [Bug 2362156]} {*}{
+ -body {
+ clock format 981173106 -gmt 1 -format %Y-%m-%d::%H:%M:%S
+ }
+ -result 2001-02-03::04:05:06
+}
+
+test clock-65.1 {clock add, bad option [Bug 2481670]} {*}{
+ -body {
+ clock add 0 1 year -foo bar
+ }
+ -returnCodes error
+ -match glob
+ -result {bad switch "-foo"*}
+}
+
+test clock-66.1 {clock scan, no date, never-before-seen timezone} {*}{
+ -setup {
+ ::tcl::clock::ClearCaches
+ }
+ -body {
+ clock scan 1200 \
+ -timezone {<EST>+05:00:00<EDT>+04:00:00,M3.2.0/02:00:00,M11.1.0/02:00:00} \
+ -base 1256529600 \
+ -format %H%M
+ }
+ -result 1256572800
+}
+
+test clock-67.1 {clock format, %% with a letter following [Bug 2819334]} {
+ clock format [clock seconds] -format %%r
+} %r
+
# cleanup
+
+namespace delete ::testClock
+::tcl::clock::ClearCaches
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/cmdAH.test b/tests/cmdAH.test
index eb7d96a..2e94d7d 100644
--- a/tests/cmdAH.test
+++ b/tests/cmdAH.test
@@ -15,7 +15,14 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-tcltest::testConstraint testchmod [string equal testchmod [info commands testchmod]]
+testConstraint testchmod [llength [info commands testchmod]]
+testConstraint testsetplatform [llength [info commands testsetplatform]]
+testConstraint testvolumetype [llength [info commands testvolumetype]]
+testConstraint linkDirectory [expr {
+ ![testConstraint win] ||
+ ([string index $tcl_platform(osVersion) 0] >= 5
+ && [lindex [file system [temporaryDirectory]] 1] eq "NTFS")
+}]
global env
set cmdAHwd [pwd]
@@ -32,10 +39,13 @@ test cmdAH-0.2 {Tcl_BreakObjCmd, success} {
test cmdAH-1.1 {Tcl_CatchObjCmd, errors} {
list [catch {catch} msg] $msg
-} {1 {wrong # args: should be "catch command ?varName?"}}
+} {1 {wrong # args: should be "catch script ?resultVarName? ?optionVarName?"}}
test cmdAH-1.2 {Tcl_CatchObjCmd, errors} {
list [catch {catch foo bar baz} msg] $msg
-} {1 {wrong # args: should be "catch command ?varName?"}}
+} {0 1}
+test cmdAH-1.3 {Tcl_CatchObjCmd, errors} {
+ list [catch {catch foo bar baz spaz} msg] $msg
+} {1 {wrong # args: should be "catch script ?resultVarName? ?optionVarName?"}}
test cmdAH-2.1 {Tcl_CdObjCmd} {
list [catch {cd foo bar} msg] $msg
@@ -110,7 +120,7 @@ test cmdAH-4.1 {Tcl_EncodingObjCmd} {
} {1 {wrong # args: should be "encoding option ?arg ...?"}}
test cmdAH-4.2 {Tcl_EncodingObjCmd} {
list [catch {encoding foo} msg] $msg
-} {1 {bad option "foo": must be convertfrom, convertto, names, or system}}
+} {1 {bad option "foo": must be convertfrom, convertto, dirs, names, or system}}
test cmdAH-4.3 {Tcl_EncodingObjCmd} {
list [catch {encoding convertto} msg] $msg
} {1 {wrong # args: should be "encoding convertto ?encoding? data"}}
@@ -191,16 +201,16 @@ test cmdAH-6.2 {Tcl_FileObjCmd: volumes} {
set result 1
}
} {1}
-test cmdAH-6.3 {Tcl_FileObjCmd: volumes} {macOrUnix} {
+test cmdAH-6.3 {Tcl_FileObjCmd: volumes} {unix} {
set volumeList [file volumes]
catch [list glob -nocomplain [lindex $volumeList 0]*]
} {0}
-test cmdAH-6.4 {Tcl_FileObjCmd: volumes} winOnly {
+test cmdAH-6.4 {Tcl_FileObjCmd: volumes} win {
set volumeList [string tolower [file volumes]]
list [catch {lsearch $volumeList "c:/"} element] [expr $element != -1] [catch {list glob -nocomplain [lindex $volumeList $element]*}]
} {0 1 0}
-test cmdAH-6.5 {cd} {unixOnly nonPortable} {
+test cmdAH-6.5 {cd} {unix nonPortable} {
set dir [pwd]
cd /
set res [pwd]
@@ -222,179 +232,111 @@ test cmdAH-7.1 {Tcl_FileObjCmd - file attrs} {
# dirname
-if {[info commands testsetplatform] == {}} {
- puts "This application hasn't been compiled with the \"testsetplatform\""
- puts "command, so I can't test Tcl_FileObjCmd etc."
-} else {
-test cmdAH-8.1 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.1 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform unix
list [catch {file dirname a b} msg] $msg
} {1 {wrong # args: should be "file dirname name"}}
-test cmdAH-8.2 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.2 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform unix
file dirname /a/b
} /a
-test cmdAH-8.3 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.3 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform unix
file dirname {}
} .
-test cmdAH-8.4 {Tcl_FileObjCmd: dirname} {
- testsetplatform mac
- file dirname {}
-} :
-test cmdAH-8.5 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.5 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform win
file dirname {}
} .
-test cmdAH-8.6 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.6 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform unix
file dirname .def
} .
-test cmdAH-8.7 {Tcl_FileObjCmd: dirname} {
- testsetplatform mac
- file dirname a
-} :
-test cmdAH-8.8 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.8 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform win
file dirname a
} .
-test cmdAH-8.9 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.9 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform unix
file dirname a/b/c.d
} a/b
-test cmdAH-8.10 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.10 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform unix
file dirname a/b.c/d
} a/b.c
-test cmdAH-8.11 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.11 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform unix
file dirname /.
} /
-test cmdAH-8.12 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.12 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform unix
list [catch {file dirname /} msg] $msg
} {0 /}
-test cmdAH-8.13 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.13 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform unix
list [catch {file dirname /foo} msg] $msg
} {0 /}
-test cmdAH-8.14 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.14 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform unix
list [catch {file dirname //foo} msg] $msg
} {0 /}
-test cmdAH-8.15 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.15 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform unix
list [catch {file dirname //foo/bar} msg] $msg
} {0 /foo}
-test cmdAH-8.16 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.16 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform unix
list [catch {file dirname {//foo\/bar/baz}} msg] $msg
} {0 {/foo\/bar}}
-test cmdAH-8.17 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.17 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform unix
list [catch {file dirname {//foo\/bar/baz/blat}} msg] $msg
} {0 {/foo\/bar/baz}}
-test cmdAH-8.18 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.18 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform unix
list [catch {file dirname /foo//} msg] $msg
} {0 /}
-test cmdAH-8.19 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.19 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform unix
list [catch {file dirname ./a} msg] $msg
} {0 .}
-test cmdAH-8.20 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.20 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform unix
list [catch {file dirname a/.a} msg] $msg
} {0 a}
-test cmdAH-8.21 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.21 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform windows
list [catch {file dirname c:foo} msg] $msg
} {0 c:}
-test cmdAH-8.22 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.22 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform windows
list [catch {file dirname c:} msg] $msg
} {0 c:}
-test cmdAH-8.23 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.23 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform windows
list [catch {file dirname c:/} msg] $msg
} {0 c:/}
-test cmdAH-8.24 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.24 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform windows
list [catch {file dirname {c:\foo}} msg] $msg
} {0 c:/}
-test cmdAH-8.25 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.25 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform windows
list [catch {file dirname {//foo/bar/baz}} msg] $msg
} {0 //foo/bar}
-test cmdAH-8.26 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.26 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform windows
list [catch {file dirname {//foo/bar}} msg] $msg
} {0 //foo/bar}
-test cmdAH-8.27 {Tcl_FileObjCmd: dirname} {
- testsetplatform mac
- list [catch {file dirname :} msg] $msg
-} {0 :}
-test cmdAH-8.28 {Tcl_FileObjCmd: dirname} {
- testsetplatform mac
- list [catch {file dirname :Foo} msg] $msg
-} {0 :}
-test cmdAH-8.29 {Tcl_FileObjCmd: dirname} {
- testsetplatform mac
- list [catch {file dirname Foo:} msg] $msg
-} {0 Foo:}
-test cmdAH-8.30 {Tcl_FileObjCmd: dirname} {
- testsetplatform mac
- list [catch {file dirname Foo:bar} msg] $msg
-} {0 Foo:}
-test cmdAH-8.31 {Tcl_FileObjCmd: dirname} {
- testsetplatform mac
- list [catch {file dirname :Foo:bar} msg] $msg
-} {0 :Foo}
-test cmdAH-8.32 {Tcl_FileObjCmd: dirname} {
- testsetplatform mac
- list [catch {file dirname ::} msg] $msg
-} {0 :}
-test cmdAH-8.33 {Tcl_FileObjCmd: dirname} {
- testsetplatform mac
- list [catch {file dirname :::} msg] $msg
-} {0 ::}
-test cmdAH-8.34 {Tcl_FileObjCmd: dirname} {
- testsetplatform mac
- list [catch {file dirname /foo/bar/} msg] $msg
-} {0 foo:}
-test cmdAH-8.35 {Tcl_FileObjCmd: dirname} {
- testsetplatform mac
- list [catch {file dirname /foo/bar} msg] $msg
-} {0 foo:}
-test cmdAH-8.36 {Tcl_FileObjCmd: dirname} {
- testsetplatform mac
- list [catch {file dirname /foo} msg] $msg
-} {0 foo:}
-test cmdAH-8.37 {Tcl_FileObjCmd: dirname} {
- testsetplatform mac
- list [catch {file dirname foo} msg] $msg
-} {0 :}
-test cmdAH-8.38 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.38 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform unix
list [catch {file dirname ~/foo} msg] $msg
} {0 ~}
-test cmdAH-8.39 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.39 {Tcl_FileObjCmd: dirname} testsetplatform {
testsetplatform unix
list [catch {file dirname ~bar/foo} msg] $msg
} {0 ~bar}
-test cmdAH-8.40 {Tcl_FileObjCmd: dirname} {
- testsetplatform mac
- list [catch {file dirname ~bar/foo} msg] $msg
-} {0 ~bar:}
-test cmdAH-8.41 {Tcl_FileObjCmd: dirname} {
- testsetplatform mac
- list [catch {file dirname ~/foo} msg] $msg
-} {0 ~:}
-test cmdAH-8.42 {Tcl_FileObjCmd: dirname} {
- testsetplatform mac
- list [catch {file dirname ~:baz} msg] $msg
-} {0 ~:}
-test cmdAH-8.43 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.43 {Tcl_FileObjCmd: dirname} testsetplatform {
global env
set temp $env(HOME)
set env(HOME) "/homewontexist/test"
@@ -403,7 +345,7 @@ test cmdAH-8.43 {Tcl_FileObjCmd: dirname} {
set env(HOME) $temp
set result
} {0 /homewontexist}
-test cmdAH-8.44 {Tcl_FileObjCmd: dirname} {
+test cmdAH-8.44 {Tcl_FileObjCmd: dirname} testsetplatform {
global env
set temp $env(HOME)
set env(HOME) "~"
@@ -413,191 +355,133 @@ test cmdAH-8.44 {Tcl_FileObjCmd: dirname} {
set result
} {0 ~}
test cmdAH-8.45 {Tcl_FileObjCmd: dirname} {
- global env
- set temp $env(HOME)
- set env(HOME) "/homewontexist/test"
- testsetplatform windows
- set result [list [catch {file dirname ~} msg] $msg]
- set env(HOME) $temp
- set result
-} {0 /homewontexist}
+ -constraints {win testsetplatform}
+ -match regexp
+ -setup {
+ set temp $::env(HOME)
+ }
+ -body {
+ set ::env(HOME) "/homewontexist/test"
+ testsetplatform windows
+ file dirname ~
+ }
+ -cleanup {
+ set ::env(HOME) $temp
+ }
+ -result {([a-zA-Z]:?)/homewontexist}
+}
test cmdAH-8.46 {Tcl_FileObjCmd: dirname} {
- global env
- set temp $env(HOME)
- set env(HOME) "/home/test"
- testsetplatform mac
- set result [list [catch {file dirname ~} msg] $msg]
- set env(HOME) $temp
- set result
-} {0 home:}
+ set f [file normalize [info nameof]]
+ file exists $f
+ set res1 [file dirname [file join $f foo/bar]]
+ set res2 [file dirname "${f}/foo/bar"]
+ if {$res1 eq $res2} {
+ set res "ok"
+ } else {
+ set res "file dirname problem, $res1, $res2 not equal"
+ }
+ set res
+} {ok}
# tail
-test cmdAH-9.1 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.1 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform unix
list [catch {file tail a b} msg] $msg
} {1 {wrong # args: should be "file tail name"}}
-test cmdAH-9.2 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.2 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform unix
file tail /a/b
} b
-test cmdAH-9.3 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.3 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform unix
file tail {}
} {}
-test cmdAH-9.4 {Tcl_FileObjCmd: tail} {
- testsetplatform mac
- file tail {}
-} {}
-test cmdAH-9.5 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.5 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform win
file tail {}
} {}
-test cmdAH-9.6 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.6 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform unix
file tail .def
} .def
-test cmdAH-9.7 {Tcl_FileObjCmd: tail} {
- testsetplatform mac
- file tail a
-} a
-test cmdAH-9.8 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.8 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform win
file tail a
} a
-test cmdAH-9.9 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.9 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform unix
file ta a/b/c.d
} c.d
-test cmdAH-9.10 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.10 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform unix
file tail a/b.c/d
} d
-test cmdAH-9.11 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.11 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform unix
file tail /.
} .
-test cmdAH-9.12 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.12 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform unix
file tail /
} {}
-test cmdAH-9.13 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.13 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform unix
file tail /foo
} foo
-test cmdAH-9.14 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.14 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform unix
file tail //foo
} foo
-test cmdAH-9.15 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.15 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform unix
file tail //foo/bar
} bar
-test cmdAH-9.16 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.16 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform unix
file tail {//foo\/bar/baz}
} baz
-test cmdAH-9.17 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.17 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform unix
file tail {//foo\/bar/baz/blat}
} blat
-test cmdAH-9.18 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.18 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform unix
file tail /foo//
} foo
-test cmdAH-9.19 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.19 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform unix
file tail ./a
} a
-test cmdAH-9.20 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.20 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform unix
file tail a/.a
} .a
-test cmdAH-9.21 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.21 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform windows
file tail c:foo
} foo
-test cmdAH-9.22 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.22 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform windows
file tail c:
} {}
-test cmdAH-9.23 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.23 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform windows
file tail c:/
} {}
-test cmdAH-9.24 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.24 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform windows
file tail {c:\foo}
} foo
-test cmdAH-9.25 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.25 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform windows
file tail {//foo/bar/baz}
} baz
-test cmdAH-9.26 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.26 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform windows
file tail {//foo/bar}
} {}
-test cmdAH-9.27 {Tcl_FileObjCmd: tail} {
- testsetplatform mac
- file tail :
-} :
-test cmdAH-9.28 {Tcl_FileObjCmd: tail} {
- testsetplatform mac
- file tail :Foo
-} Foo
-test cmdAH-9.29 {Tcl_FileObjCmd: tail} {
- testsetplatform mac
- file tail Foo:
-} {}
-test cmdAH-9.30 {Tcl_FileObjCmd: tail} {
- testsetplatform mac
- file tail Foo:bar
-} bar
-test cmdAH-9.31 {Tcl_FileObjCmd: tail} {
- testsetplatform mac
- file tail :Foo:bar
-} bar
-test cmdAH-9.32 {Tcl_FileObjCmd: tail} {
- testsetplatform mac
- file tail ::
-} ::
-test cmdAH-9.33 {Tcl_FileObjCmd: tail} {
- testsetplatform mac
- file tail :::
-} ::
-test cmdAH-9.34 {Tcl_FileObjCmd: tail} {
- testsetplatform mac
- file tail /foo/bar/
-} bar
-test cmdAH-9.35 {Tcl_FileObjCmd: tail} {
- testsetplatform mac
- file tail /foo/bar
-} bar
-test cmdAH-9.36 {Tcl_FileObjCmd: tail} {
- testsetplatform mac
- file tail /foo
-} {}
-test cmdAH-9.37 {Tcl_FileObjCmd: tail} {
- testsetplatform mac
- file tail foo
-} foo
-test cmdAH-9.38 {Tcl_FileObjCmd: tail} {
- testsetplatform mac
- file tail ~:foo
-} foo
-test cmdAH-9.39 {Tcl_FileObjCmd: tail} {
- testsetplatform mac
- file tail ~bar:foo
-} foo
-test cmdAH-9.40 {Tcl_FileObjCmd: tail} {
- testsetplatform mac
- file tail ~bar/foo
-} foo
-test cmdAH-9.41 {Tcl_FileObjCmd: tail} {
- testsetplatform mac
- file tail ~/foo
-} foo
-test cmdAH-9.42 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.42 {Tcl_FileObjCmd: tail} testsetplatform {
global env
set temp $env(HOME)
set env(HOME) "/home/test"
@@ -606,7 +490,7 @@ test cmdAH-9.42 {Tcl_FileObjCmd: tail} {
set env(HOME) $temp
set result
} test
-test cmdAH-9.43 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.43 {Tcl_FileObjCmd: tail} testsetplatform {
global env
set temp $env(HOME)
set env(HOME) "~"
@@ -615,7 +499,7 @@ test cmdAH-9.43 {Tcl_FileObjCmd: tail} {
set env(HOME) $temp
set result
} {}
-test cmdAH-9.44 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.44 {Tcl_FileObjCmd: tail} testsetplatform {
global env
set temp $env(HOME)
set env(HOME) "/home/test"
@@ -624,332 +508,227 @@ test cmdAH-9.44 {Tcl_FileObjCmd: tail} {
set env(HOME) $temp
set result
} test
-test cmdAH-9.45 {Tcl_FileObjCmd: tail} {
- global env
- set temp $env(HOME)
- set env(HOME) "/home/test"
- testsetplatform mac
- set result [file tail ~]
- set env(HOME) $temp
- set result
-} test
-test cmdAH-9.46 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.46 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform unix
file tail {f.oo\bar/baz.bat}
} baz.bat
-test cmdAH-9.47 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.47 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform windows
file tail c:foo
} foo
-test cmdAH-9.48 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.48 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform windows
file tail c:
} {}
-test cmdAH-9.49 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.49 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform windows
file tail c:/foo
} foo
-test cmdAH-9.50 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.50 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform windows
file tail {c:/foo\bar}
} bar
-test cmdAH-9.51 {Tcl_FileObjCmd: tail} {
+test cmdAH-9.51 {Tcl_FileObjCmd: tail} testsetplatform {
testsetplatform windows
file tail {foo\bar}
} bar
# rootname
-test cmdAH-10.1 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.1 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform unix
list [catch {file rootname a b} msg] $msg
} {1 {wrong # args: should be "file rootname name"}}
-test cmdAH-10.2 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.2 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform unix
file rootname {}
} {}
-test cmdAH-10.3 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.3 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform unix
file ro foo
} foo
-test cmdAH-10.4 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.4 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform unix
file rootname foo.
} foo
-test cmdAH-10.5 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.5 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform unix
file rootname .foo
} {}
-test cmdAH-10.6 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.6 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform unix
file rootname abc.def
} abc
-test cmdAH-10.7 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.7 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform unix
file rootname abc.def.ghi
} abc.def
-test cmdAH-10.8 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.8 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform unix
file rootname a/b/c.d
} a/b/c
-test cmdAH-10.9 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.9 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform unix
file rootname a/b.c/d
} a/b.c/d
-test cmdAH-10.10 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.10 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform unix
file rootname a/b.c/
} a/b.c/
-test cmdAH-10.11 {Tcl_FileObjCmd: rootname} {
- testsetplatform mac
- file ro foo
-} foo
-test cmdAH-10.12 {Tcl_FileObjCmd: rootname} {
- testsetplatform mac
- file rootname {}
-} {}
-test cmdAH-10.13 {Tcl_FileObjCmd: rootname} {
- testsetplatform mac
- file rootname foo.
-} foo
-test cmdAH-10.14 {Tcl_FileObjCmd: rootname} {
- testsetplatform mac
- file rootname .foo
-} {}
-test cmdAH-10.15 {Tcl_FileObjCmd: rootname} {
- testsetplatform mac
- file rootname abc.def
-} abc
-test cmdAH-10.16 {Tcl_FileObjCmd: rootname} {
- testsetplatform mac
- file rootname abc.def.ghi
-} abc.def
-test cmdAH-10.17 {Tcl_FileObjCmd: rootname} {
- testsetplatform mac
- file rootname a:b:c.d
-} a:b:c
-test cmdAH-10.18 {Tcl_FileObjCmd: rootname} {
- testsetplatform mac
- file rootname a:b.c:d
-} a:b.c:d
-test cmdAH-10.19 {Tcl_FileObjCmd: rootname} {
- testsetplatform mac
- file rootname a/b/c.d
-} a/b/c
-test cmdAH-10.20 {Tcl_FileObjCmd: rootname} {
- testsetplatform mac
- file rootname a/b.c/d
-} a/b.c/d
-test cmdAH-10.21 {Tcl_FileObjCmd: rootname} {
- testsetplatform mac
- file rootname /a.b
-} /a
-test cmdAH-10.22 {Tcl_FileObjCmd: rootname} {
- testsetplatform mac
- file rootname foo.c:
-} foo.c:
-test cmdAH-10.23 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.23 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform windows
file rootname {}
} {}
-test cmdAH-10.24 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.24 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform windows
file ro foo
} foo
-test cmdAH-10.25 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.25 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform windows
file rootname foo.
} foo
-test cmdAH-10.26 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.26 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform windows
file rootname .foo
} {}
-test cmdAH-10.27 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.27 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform windows
file rootname abc.def
} abc
-test cmdAH-10.28 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.28 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform windows
file rootname abc.def.ghi
} abc.def
-test cmdAH-10.29 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.29 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform windows
file rootname a/b/c.d
} a/b/c
-test cmdAH-10.30 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.30 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform windows
file rootname a/b.c/d
} a/b.c/d
-test cmdAH-10.31 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.31 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform windows
file rootname a\\b.c\\
} a\\b.c\\
-test cmdAH-10.32 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.32 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform windows
file rootname a\\b\\c.d
} a\\b\\c
-test cmdAH-10.33 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.33 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform windows
file rootname a\\b.c\\d
} a\\b.c\\d
-test cmdAH-10.34 {Tcl_FileObjCmd: rootname} {
+test cmdAH-10.34 {Tcl_FileObjCmd: rootname} testsetplatform {
testsetplatform windows
file rootname a\\b.c\\
} a\\b.c\\
set num 35
foreach outer { {} a .a a. a.a } {
- foreach inner { {} a .a a. a.a } {
- set thing [format %s/%s $outer $inner]
-; test cmdAH-6.$num {Tcl_FileObjCmd: rootname and extension options} {
- testsetplatform unix
- format %s%s [file rootname $thing] [file ext $thing]
- } $thing
- set num [expr $num+1]
- }
+ foreach inner { {} a .a a. a.a } {
+ set thing [format %s/%s $outer $inner]
+ ;test cmdAH-10.$num {Tcl_FileObjCmd: rootname and extension options} testsetplatform "
+ testsetplatform unix
+ [list format %s%s [file rootname $thing] [file ext $thing]]
+ " $thing
+ incr num
+ }
}
# extension
-test cmdAH-11.1 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.1 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform unix
list [catch {file extension a b} msg] $msg
} {1 {wrong # args: should be "file extension name"}}
-test cmdAH-11.2 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.2 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform unix
file extension {}
} {}
-test cmdAH-11.3 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.3 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform unix
file ext foo
} {}
-test cmdAH-11.4 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.4 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform unix
file extension foo.
} .
-test cmdAH-11.5 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.5 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform unix
file extension .foo
} .foo
-test cmdAH-11.6 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.6 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform unix
file extension abc.def
} .def
-test cmdAH-11.7 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.7 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform unix
file extension abc.def.ghi
} .ghi
-test cmdAH-11.8 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.8 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform unix
file extension a/b/c.d
} .d
-test cmdAH-11.9 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.9 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform unix
file extension a/b.c/d
} {}
-test cmdAH-11.10 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.10 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform unix
file extension a/b.c/
} {}
-test cmdAH-11.11 {Tcl_FileObjCmd: extension} {
- testsetplatform mac
- file ext foo
-} {}
-test cmdAH-11.12 {Tcl_FileObjCmd: extension} {
- testsetplatform mac
- file extension {}
-} {}
-test cmdAH-11.13 {Tcl_FileObjCmd: extension} {
- testsetplatform mac
- file extension foo.
-} .
-test cmdAH-11.14 {Tcl_FileObjCmd: extension} {
- testsetplatform mac
- file extension .foo
-} .foo
-test cmdAH-11.15 {Tcl_FileObjCmd: extension} {
- testsetplatform mac
- file extension abc.def
-} .def
-test cmdAH-11.16 {Tcl_FileObjCmd: extension} {
- testsetplatform mac
- file extension abc.def.ghi
-} .ghi
-test cmdAH-11.17 {Tcl_FileObjCmd: extension} {
- testsetplatform mac
- file extension a:b:c.d
-} .d
-test cmdAH-11.18 {Tcl_FileObjCmd: extension} {
- testsetplatform mac
- file extension a:b.c:d
-} {}
-test cmdAH-11.19 {Tcl_FileObjCmd: extension} {
- testsetplatform mac
- file extension a/b/c.d
-} .d
-test cmdAH-11.20 {Tcl_FileObjCmd: extension} {
- testsetplatform mac
- file extension a/b.c/d
-} {}
-test cmdAH-11.21 {Tcl_FileObjCmd: extension} {
- testsetplatform mac
- file extension /a.b
-} .b
-test cmdAH-11.22 {Tcl_FileObjCmd: extension} {
- testsetplatform mac
- file extension foo.c:
-} {}
-test cmdAH-11.23 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.23 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform windows
file extension {}
} {}
-test cmdAH-11.24 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.24 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform windows
file ext foo
} {}
-test cmdAH-11.25 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.25 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform windows
file extension foo.
} .
-test cmdAH-11.26 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.26 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform windows
file extension .foo
} .foo
-test cmdAH-11.27 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.27 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform windows
file extension abc.def
} .def
-test cmdAH-11.28 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.28 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform windows
file extension abc.def.ghi
} .ghi
-test cmdAH-11.29 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.29 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform windows
file extension a/b/c.d
} .d
-test cmdAH-11.30 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.30 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform windows
file extension a/b.c/d
} {}
-test cmdAH-11.31 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.31 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform windows
file extension a\\b.c\\
} {}
-test cmdAH-11.32 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.32 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform windows
file extension a\\b\\c.d
} .d
-test cmdAH-11.33 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.33 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform windows
file extension a\\b.c\\d
} {}
-test cmdAH-11.34 {Tcl_FileObjCmd: extension} {
+test cmdAH-11.34 {Tcl_FileObjCmd: extension} testsetplatform {
testsetplatform windows
file extension a\\b.c\\
} {}
set num 35
foreach value {a..b a...b a.c..b ..b} result {.b .b .b .b} {
- foreach p {unix mac windows} {
-; test cmdAH-7.$num {Tcl_FileObjCmd: extension} "
+ foreach p {unix windows} {
+ ;test cmdAH-11.$num {Tcl_FileObjCmd: extension} testsetplatform "
testsetplatform $p
file extension $value
" $result
@@ -959,99 +738,104 @@ foreach value {a..b a...b a.c..b ..b} result {.b .b .b .b} {
# pathtype
-test cmdAH-12.1 {Tcl_FileObjCmd: pathtype} {
+test cmdAH-12.1 {Tcl_FileObjCmd: pathtype} testsetplatform {
testsetplatform unix
list [catch {file pathtype a b} msg] $msg
} {1 {wrong # args: should be "file pathtype name"}}
-test cmdAH-12.2 {Tcl_FileObjCmd: pathtype} {
+test cmdAH-12.2 {Tcl_FileObjCmd: pathtype} testsetplatform {
testsetplatform unix
file pathtype /a
} absolute
-test cmdAH-12.3 {Tcl_FileObjCmd: pathtype} {
+test cmdAH-12.3 {Tcl_FileObjCmd: pathtype} testsetplatform {
testsetplatform unix
file p a
} relative
-test cmdAH-12.4 {Tcl_FileObjCmd: pathtype} {
+test cmdAH-12.4 {Tcl_FileObjCmd: pathtype} testsetplatform {
testsetplatform windows
file pathtype c:a
} volumerelative
# split
-test cmdAH-13.1 {Tcl_FileObjCmd: split} {
+test cmdAH-13.1 {Tcl_FileObjCmd: split} testsetplatform {
testsetplatform unix
list [catch {file split a b} msg] $msg
} {1 {wrong # args: should be "file split name"}}
-test cmdAH-13.2 {Tcl_FileObjCmd: split} {
+test cmdAH-13.2 {Tcl_FileObjCmd: split} testsetplatform {
testsetplatform unix
file split a
} a
-test cmdAH-13.3 {Tcl_FileObjCmd: split} {
+test cmdAH-13.3 {Tcl_FileObjCmd: split} testsetplatform {
testsetplatform unix
file split a/b
} {a b}
# join
-test cmdAH-14.1 {Tcl_FileObjCmd: join} {
+test cmdAH-14.1 {Tcl_FileObjCmd: join} testsetplatform {
testsetplatform unix
file join a
} a
-test cmdAH-14.2 {Tcl_FileObjCmd: join} {
+test cmdAH-14.2 {Tcl_FileObjCmd: join} testsetplatform {
testsetplatform unix
file join a b
} a/b
-test cmdAH-14.3 {Tcl_FileObjCmd: join} {
+test cmdAH-14.3 {Tcl_FileObjCmd: join} testsetplatform {
testsetplatform unix
file join a b c d
} a/b/c/d
# error handling of Tcl_TranslateFileName
-test cmdAH-15.1 {Tcl_FileObjCmd} {
+test cmdAH-15.1 {Tcl_FileObjCmd} testsetplatform {
testsetplatform unix
list [catch {file atime ~_bad_user} msg] $msg
} {1 {user "_bad_user" doesn't exist}}
-testsetplatform $platform
-}
+catch {testsetplatform $platform}
# readable
set gorpfile [makeFile abcde gorp.file]
set dirfile [makeDirectory dir.file]
-if {[info commands testchmod] == {}} {
- puts "This application hasn't been compiled with the \"testchmod\""
- puts "command, so I can't test Tcl_FileObjCmd etc."
-} else {
-test cmdAH-16.1 {Tcl_FileObjCmd: readable} {testchmod} {
- list [catch {file readable a b} msg] $msg
-} {1 {wrong # args: should be "file readable name"}}
-testchmod 0444 $gorpfile
-test cmdAH-16.2 {Tcl_FileObjCmd: readable} {testchmod} {
- file readable $gorpfile
-} 1
-testchmod 0333 $gorpfile
-test cmdAH-16.3 {Tcl_FileObjCmd: readable} {unixOnly notRoot testchmod} {
- file reada $gorpfile
-} 0
+test cmdAH-16.1 {Tcl_FileObjCmd: readable} {
+ -body {list [catch {file readable a b} msg] $msg}
+ -result {1 {wrong # args: should be "file readable name"}}
+}
+test cmdAH-16.2 {Tcl_FileObjCmd: readable} {
+ -constraints testchmod
+ -setup {testchmod 0444 $gorpfile}
+ -body {file readable $gorpfile}
+ -result 1
+}
+test cmdAH-16.3 {Tcl_FileObjCmd: readable} {
+ -constraints {unix notRoot testchmod}
+ -setup {testchmod 0333 $gorpfile}
+ -body {file reada $gorpfile}
+ -result 0
+}
# writable
-test cmdAH-17.1 {Tcl_FileObjCmd: writable} {testchmod} {
- list [catch {file writable a b} msg] $msg
-} {1 {wrong # args: should be "file writable name"}}
-testchmod 0555 $gorpfile
-test cmdAH-17.2 {Tcl_FileObjCmd: writable} {notRoot testchmod} {
- file writable $gorpfile
-} 0
-testchmod 0222 $gorpfile
-test cmdAH-17.3 {Tcl_FileObjCmd: writable} {testchmod} {
- file writable $gorpfile
-} 1
+test cmdAH-17.1 {Tcl_FileObjCmd: writable} {
+ -body {list [catch {file writable a b} msg] $msg}
+ -result {1 {wrong # args: should be "file writable name"}}
+}
+test cmdAH-17.2 {Tcl_FileObjCmd: writable} {
+ -constraints {notRoot testchmod}
+ -setup {testchmod 0555 $gorpfile}
+ -body {file writable $gorpfile}
+ -result 0
+}
+test cmdAH-17.3 {Tcl_FileObjCmd: writable} {
+ -constraints testchmod
+ -setup {testchmod 0222 $gorpfile}
+ -body {file writable $gorpfile}
+ -result 1
}
+
# executable
removeFile $gorpfile
@@ -1059,13 +843,13 @@ removeDirectory $dirfile
set dirfile [makeDirectory dir.file]
set gorpfile [makeFile abcde gorp.file]
-test cmdAH-18.1 {Tcl_FileObjCmd: executable} {testchmod} {
+test cmdAH-18.1 {Tcl_FileObjCmd: executable} {} {
list [catch {file executable a b} msg] $msg
} {1 {wrong # args: should be "file executable name"}}
-test cmdAH-18.2 {Tcl_FileObjCmd: executable} {testchmod notRoot} {
+test cmdAH-18.2 {Tcl_FileObjCmd: executable} {notRoot} {
file executable $gorpfile
} 0
-test cmdAH-18.3 {Tcl_FileObjCmd: executable} {unixOnly testchmod} {
+test cmdAH-18.3 {Tcl_FileObjCmd: executable} {unix testchmod} {
# Only on unix will setting the execute bit on a regular file
# cause that file to be executable.
@@ -1073,23 +857,25 @@ test cmdAH-18.3 {Tcl_FileObjCmd: executable} {unixOnly testchmod} {
file exe $gorpfile
} 1
-test cmdAH-18.4 {Tcl_FileObjCmd: executable} {macOnly testchmod} {
- # On mac, the only executable files are of type APPL.
+test cmdAH-18.5 {Tcl_FileObjCmd: executable} {win} {
+ # On pc, must be a .exe, .com, etc.
set x [file exe $gorpfile]
- file attrib $gorpfile -type APPL
- lappend x [file exe $gorpfile]
+ set gorpexe [makeFile foo gorp.exe]
+ lappend x [file exe $gorpexe]
+ removeFile $gorpexe
+ set x
} {0 1}
-test cmdAH-18.5 {Tcl_FileObjCmd: executable} {winOnly testchmod} {
+test cmdAH-18.5.1 {Tcl_FileObjCmd: executable} {win} {
# On pc, must be a .exe, .com, etc.
set x [file exe $gorpfile]
set gorpexe [makeFile foo gorp.exe]
- lappend x [file exe $gorpexe]
+ lappend x [file exe [string toupper $gorpexe]]
removeFile $gorpexe
set x
} {0 1}
-test cmdAH-18.6 {Tcl_FileObjCmd: executable} {testchmod} {
+test cmdAH-18.6 {Tcl_FileObjCmd: executable} {} {
# Directories are always executable.
file exe $dirfile
@@ -1122,23 +908,14 @@ test cmdAH-19.5 {Tcl_FileObjCmd: exists} {
} 1
# nativename
-if {[info commands testsetplatform] == {}} {
- puts "This application hasn't been compiled with the \"testsetplatform\""
- puts "command, so I can't test Tcl_FileObjCmd etc."
-} else {
-test cmdAH-19.6 {Tcl_FileObjCmd: nativename} {
+test cmdAH-19.6 {Tcl_FileObjCmd: nativename} testsetplatform {
testsetplatform unix
list [catch {file nativename a/b} msg] $msg [testsetplatform $platform]
} {0 a/b {}}
-test cmdAH-19.7 {Tcl_FileObjCmd: nativename} {
+test cmdAH-19.7 {Tcl_FileObjCmd: nativename} testsetplatform {
testsetplatform windows
list [catch {file nativename a/b} msg] $msg [testsetplatform $platform]
} {0 {a\b} {}}
-test cmdAH-19.8 {Tcl_FileObjCmd: nativename} {
- testsetplatform mac
- list [catch {file nativename a/b} msg] $msg [testsetplatform $platform]
-} {0 :a:b {}}
-}
test cmdAH-19.9 {Tcl_FileObjCmd: ~ : exists} {
file exists ~nOsUcHuSeR
@@ -1152,7 +929,7 @@ test cmdAH-19.10 {Tcl_FileObjCmd: ~ : nativename} {
# directory in order to guarantee (?) a local file system: some
# NFS file systems won't do the stuff below correctly.
-test cmdAH-19.11 {Tcl_FileObjCmd: exists} {unixOnly notRoot} {
+test cmdAH-19.11 {Tcl_FileObjCmd: exists} {unix notRoot} {
file delete -force /tmp/tcl.foo.dir/file
file delete -force /tmp/tcl.foo.dir
makeDirectory /tmp/tcl.foo.dir
@@ -1176,7 +953,12 @@ catch {file attributes $gorpfile -permissions 0765}
# atime
-set file [makeFile "data" touch.me]
+# avoid problems with non-local filesystems
+if {[testConstraint unix] && [file exists /tmp]} {
+ set file [makeFile "data" touch.me /tmp]
+} else {
+ set file [makeFile "data" touch.me]
+}
test cmdAH-20.1 {Tcl_FileObjCmd: atime} {
list [catch {file atime a b c} msg] $msg
@@ -1194,18 +976,23 @@ test cmdAH-20.3 {Tcl_FileObjCmd: atime} {
test cmdAH-20.4 {Tcl_FileObjCmd: atime} {
list [catch {file atime $file notint} msg] $msg
} {1 {expected integer but got "notint"}}
-test cmdAH-20.5 {Tcl_FileObjCmd: atime touch} {unixOrPc} {
- if {[string equal $tcl_platform(platform) "windows"]} {
- set old [pwd]
- cd $::tcltest::temporaryDirectory
- if {![string equal "NTFS" [testvolumetype]]} {
- # Windows FAT doesn't understand atime, but NTFS does
- # May also fail for Windows on NFS mounted disks
- cd $old
- return 1
- }
+test cmdAH-20.5 {Tcl_FileObjCmd: atime touch} {unix} {
+ set atime [file atime $file]
+ after 1100; # pause a sec to notice change in atime
+ set newatime [clock seconds]
+ set modatime [file atime $file $newatime]
+ expr {$newatime == $modatime ? 1 : "$newatime != $modatime"}
+} 1
+test cmdAH-20.6 {Tcl_FileObjCmd: atime touch} {win testvolumetype} {
+ set old [pwd]
+ cd $::tcltest::temporaryDirectory
+ if {"NTFS" ne [testvolumetype]} {
+ # Windows FAT doesn't understand atime, but NTFS does
+ # May also fail for Windows on NFS mounted disks
cd $old
+ return 1
}
+ cd $old
set atime [file atime $file]
after 1100; # pause a sec to notice change in atime
set newatime [clock seconds]
@@ -1213,7 +1000,12 @@ test cmdAH-20.5 {Tcl_FileObjCmd: atime touch} {unixOrPc} {
expr {$newatime == $modatime ? 1 : "$newatime != $modatime"}
} 1
-removeFile touch.me
+if {[testConstraint unix] && [file exists /tmp]} {
+ removeFile touch.me /tmp
+} else {
+ removeFile touch.me
+}
+
# isdirectory
test cmdAH-21.1 {Tcl_FileObjCmd: isdirectory} {
@@ -1244,12 +1036,12 @@ test cmdAH-23.1 {Tcl_FileObjCmd: lstat} {
test cmdAH-23.2 {Tcl_FileObjCmd: lstat} {
list [catch {file lstat a b c} msg] $msg
} {1 {wrong # args: should be "file lstat name varName"}}
-test cmdAH-23.3 {Tcl_FileObjCmd: lstat} {unixOnly nonPortable} {
+test cmdAH-23.3 {Tcl_FileObjCmd: lstat} {unix nonPortable} {
catch {unset stat}
file lstat $linkfile stat
lsort [array names stat]
} {atime ctime dev gid ino mode mtime nlink size type uid}
-test cmdAH-23.4 {Tcl_FileObjCmd: lstat} {unixOnly nonPortable} {
+test cmdAH-23.4 {Tcl_FileObjCmd: lstat} {unix nonPortable} {
catch {unset stat}
file lstat $linkfile stat
list $stat(nlink) [expr $stat(mode)&0777] $stat(type)
@@ -1308,17 +1100,19 @@ proc waitForEvenSecondForFAT {} {
# timings. :^(
# This procedure based on work by Helmut Giese
- global tcl_platform
- if {$tcl_platform(platform) ne "windows"} {return}
- if {[lindex [file system [temporaryDirectory]] 1] == "NTFS"} {return}
- # Assume non-NTFS means FAT{12,16,32} and hence in need of special help
- set start [clock seconds]
- while {1} {
- set now [clock seconds]
- if {$now!=$start && !($now & 1)} {
- return
+ if {
+ [testConstraint win]
+ && [lindex [file system [temporaryDirectory]] 1] ne "NTFS"
+ } then {
+ # Assume non-NTFS means FAT{12,16,32} and hence in need of special help
+ set start [clock seconds]
+ while {1} {
+ set now [clock seconds]
+ if {$now!=$start && !($now & 1)} {
+ break
+ }
+ after 50
}
- after 50
}
}
set file [makeFile "data" touch.me]
@@ -1365,16 +1159,13 @@ test cmdAH-24.4 {Tcl_FileObjCmd: mtime} {
test cmdAH-24.5 {Tcl_FileObjCmd: mtime} {
# Under Unix, use a file in /tmp to avoid clock skew due to NFS.
# On other platforms, just use a file in the local directory.
-
- if {[string equal $tcl_platform(platform) "unix"]} {
+ if {[testConstraint unix]} {
set name /tmp/tcl.test.[pid]
} else {
set name [file join [temporaryDirectory] tf]
}
-
# Make sure that a new file's time is correct. 10 seconds variance
# is allowed used due to slow networks or clock skew on a network drive.
-
file delete -force $name
close [open $name w]
set a [expr abs([clock seconds]-[file mtime $name])<10]
@@ -1384,14 +1175,14 @@ test cmdAH-24.5 {Tcl_FileObjCmd: mtime} {
test cmdAH-24.7 {Tcl_FileObjCmd: mtime} {
list [catch {file mtime $file notint} msg] $msg
} {1 {expected integer but got "notint"}}
-test cmdAH-24.8 {Tcl_FileObjCmd: mtime touch} macOrUnix {
+test cmdAH-24.8 {Tcl_FileObjCmd: mtime touch} unix {
set mtime [file mtime $file]
after 1100; # pause a sec to notice change in mtime
set newmtime [clock seconds]
set modmtime [file mtime $file $newmtime]
expr {$newmtime == $modmtime ? 1 : "$newmtime != $modmtime"}
} 1
-test cmdAH-24.9 {Tcl_FileObjCmd: mtime touch with non-ascii chars} macOrUnix {
+test cmdAH-24.9 {Tcl_FileObjCmd: mtime touch with non-ascii chars} unix {
set oldfile $file
# introduce some non-ascii characters.
append file \u2022
@@ -1407,7 +1198,7 @@ test cmdAH-24.9 {Tcl_FileObjCmd: mtime touch with non-ascii chars} macOrUnix {
}
expr {$newmtime == $modmtime ? 1 : "$newmtime != $modmtime"}
} 1
-test cmdAH-24.10 {Tcl_FileObjCmd: mtime touch} winOnly {
+test cmdAH-24.10 {Tcl_FileObjCmd: mtime touch} win {
waitForEvenSecondForFAT
set mtime [file mtime $file]
after 2100; # pause two secs to notice change in mtime on FAT fs'es
@@ -1415,7 +1206,7 @@ test cmdAH-24.10 {Tcl_FileObjCmd: mtime touch} winOnly {
set modmtime [file mtime $file $newmtime]
expr {$newmtime == $modmtime ? 1 : "$newmtime != $modmtime"}
} 1
-test cmdAH-24.11 {Tcl_FileObjCmd: mtime touch with non-ascii chars} winOnly {
+test cmdAH-24.11 {Tcl_FileObjCmd: mtime touch with non-ascii chars} win {
waitForEvenSecondForFAT
set oldfile $file
# introduce some non-ascii characters.
@@ -1434,10 +1225,8 @@ test cmdAH-24.11 {Tcl_FileObjCmd: mtime touch with non-ascii chars} winOnly {
} 1
removeFile touch.me
rename waitForEvenSecondForFAT {}
-
test cmdAH-24.12 {Tcl_FileObjCmd: mtime and daylight savings} {
set name [file join [temporaryDirectory] clockchange]
-
file delete -force $name
close [open $name w]
set time [clock scan "21:00:00 October 30 2004 GMT"]
@@ -1446,31 +1235,37 @@ test cmdAH-24.12 {Tcl_FileObjCmd: mtime and daylight savings} {
file delete $name
expr {$newmtime == $time ? 1 : "$newmtime != $time"}
} {1}
-
# bug 1420432: setting mtime fails for directories on windows.
-test cmdAH-24.13 {Tcl_FileObjCmd: directory mtime} {
+test cmdAH-24.13 {Tcl_FileObjCmd: directory mtime} -setup {
set dirname [file join [temporaryDirectory] tmp[pid]]
file delete -force $dirname
+} -constraints tempNotWin -body {
file mkdir $dirname
- set res [catch {
- set old [file mtime $dirname]
- file mtime $dirname 0
- set new [file mtime $dirname]
- list $new [expr {$old != $new}]
- } err]
+ set old [file mtime $dirname]
+ file mtime $dirname 0
+ set new [file mtime $dirname]
+ list $new [expr {$old != $new}]
+} -cleanup {
file delete -force $dirname
- list $res $err
-} {0 {0 1}}
+} -result {0 1}
# owned
test cmdAH-25.1 {Tcl_FileObjCmd: owned} {
list [catch {file owned a b} msg] $msg
} {1 {wrong # args: should be "file owned name"}}
-test cmdAH-25.2 {Tcl_FileObjCmd: owned} {
+test cmdAH-25.2 {Tcl_FileObjCmd: owned} -constraints win -body {
file owned $gorpfile
-} 1
-test cmdAH-25.3 {Tcl_FileObjCmd: owned} {unixOnly notRoot} {
+} -result 1
+test cmdAH-25.2.1 {Tcl_FileObjCmd: owned} -constraints unix -setup {
+ # Avoid problems with AFS
+ set tmpfile [makeFile "data" touch.me /tmp]
+} -body {
+ file owned $tmpfile
+} -cleanup {
+ removeFile touch.me /tmp
+} -result 1
+test cmdAH-25.3 {Tcl_FileObjCmd: owned} {unix notRoot} {
file owned /
} 0
@@ -1479,18 +1274,14 @@ test cmdAH-25.3 {Tcl_FileObjCmd: owned} {unixOnly notRoot} {
test cmdAH-26.1 {Tcl_FileObjCmd: readlink} {
list [catch {file readlink a b} msg] $msg
} {1 {wrong # args: should be "file readlink name"}}
-test cmdAH-26.2 {Tcl_FileObjCmd: readlink} {unixOnly nonPortable} {
+test cmdAH-26.2 {Tcl_FileObjCmd: readlink} {unix nonPortable} {
file readlink $linkfile
} $gorpfile
-test cmdAH-26.3 {Tcl_FileObjCmd: readlink errors} {unixOnly nonPortable} {
+test cmdAH-26.3 {Tcl_FileObjCmd: readlink errors} {unix nonPortable} {
list [catch {file readlink _bogus_} msg] [string tolower $msg] \
[string tolower $errorCode]
} {1 {could not readlink "_bogus_": no such file or directory} {posix enoent {no such file or directory}}}
-test cmdAH-26.4 {Tcl_FileObjCmd: readlink errors} {macOnly nonPortable} {
- list [catch {file readlink _bogus_} msg] [string tolower $msg] \
- [string tolower $errorCode]
-} {1 {could not readlink "_bogus_": no such file or directory} {posix enoent {no such file or directory}}}
-test cmdAH-26.5 {Tcl_FileObjCmd: readlink errors} {winOnly nonPortable} {
+test cmdAH-26.5 {Tcl_FileObjCmd: readlink errors} {win nonPortable} {
list [catch {file readlink _bogus_} msg] [string tolower $msg] \
[string tolower $errorCode]
} {1 {could not readlink "_bogus_": invalid argument} {posix einval {invalid argument}}}
@@ -1528,7 +1319,9 @@ test cmdAH-28.2 {Tcl_FileObjCmd: stat} {
} {1 {wrong # args: should be "file stat name varName"} NONE}
test cmdAH-28.3 {Tcl_FileObjCmd: stat} {
catch {unset stat}
+ set stat(blocks) [set stat(blksize) {}]
file stat $gorpfile stat
+ unset stat(blocks) stat(blksize)
lsort [array names stat]
} {atime ctime dev gid ino mode mtime nlink size type uid}
test cmdAH-28.4 {Tcl_FileObjCmd: stat} {
@@ -1536,10 +1329,10 @@ test cmdAH-28.4 {Tcl_FileObjCmd: stat} {
file stat $gorpfile stat
list $stat(nlink) $stat(size) $stat(type)
} {1 12 file}
-test cmdAH-28.5 {Tcl_FileObjCmd: stat} {unixOnly} {
+test cmdAH-28.5 {Tcl_FileObjCmd: stat} {unix} {
catch {unset stat}
file stat $gorpfile stat
- expr $stat(mode)&0777
+ expr $stat(mode)&0o777
} {501}
test cmdAH-28.6 {Tcl_FileObjCmd: stat} {
string tolower [list [catch {file stat _bogus_ stat} msg] \
@@ -1559,7 +1352,7 @@ test cmdAH-28.8 {Tcl_FileObjCmd: stat} {
removeFile $filename
set x
} 1
-test cmdAH-28.9 {Tcl_FileObjCmd: stat} winOnly {
+test cmdAH-28.9 {Tcl_FileObjCmd: stat} win {
# stat of root directory was failing.
# don't care about answer, just that test runs.
@@ -1575,7 +1368,7 @@ test cmdAH-28.9 {Tcl_FileObjCmd: stat} winOnly {
file stat c:/ stat
file stat c:/. stat
} {}
-test cmdAH-28.10 {Tcl_FileObjCmd: stat} {winOnly nonPortable} {
+test cmdAH-28.10 {Tcl_FileObjCmd: stat} {win nonPortable} {
# stat of root directory was failing.
# don't care about answer, just that test runs.
@@ -1583,7 +1376,7 @@ test cmdAH-28.10 {Tcl_FileObjCmd: stat} {winOnly nonPortable} {
file stat //pop/$env(USERNAME)/ stat
file stat //pop/$env(USERNAME)/. stat
} {}
-test cmdAH-28.11 {Tcl_FileObjCmd: stat} {winOnly nonPortable} {
+test cmdAH-28.11 {Tcl_FileObjCmd: stat} {win nonPortable} {
# stat of network directory was returning id of current local drive.
set old [pwd]
@@ -1612,7 +1405,7 @@ test cmdAH-29.1 {Tcl_FileObjCmd: type} {
test cmdAH-29.2 {Tcl_FileObjCmd: type} {
file type $dirfile
} directory
-test cmdAH-29.3.0 {Tcl_FileObjCmd: delete removes link not file} {unixOnly nonPortable} {
+test cmdAH-29.3.0 {Tcl_FileObjCmd: delete removes link not file} {unix nonPortable} {
set exists [list [file exists $linkfile] [file exists $gorpfile]]
file delete $linkfile
set exists2 [list [file exists $linkfile] [file exists $gorpfile]]
@@ -1621,7 +1414,7 @@ test cmdAH-29.3.0 {Tcl_FileObjCmd: delete removes link not file} {unixOnly nonPo
test cmdAH-29.3 {Tcl_FileObjCmd: type} {
file type $gorpfile
} file
-test cmdAH-29.4 {Tcl_FileObjCmd: type} {unixOnly} {
+test cmdAH-29.4 {Tcl_FileObjCmd: type} {unix} {
catch {file delete $linkfile}
# Unlike [exec ln -s], [file link] requires an existing target
file link -symbolic $linkfile $gorpfile
@@ -1629,16 +1422,6 @@ test cmdAH-29.4 {Tcl_FileObjCmd: type} {unixOnly} {
file delete $linkfile
set result
} link
-if {[string equal $tcl_platform(platform) "windows"]} {
- if {[string index $tcl_platform(osVersion) 0] >= 5 \
- && ([lindex [file system [temporaryDirectory]] 1] == "NTFS")} {
- tcltest::testConstraint linkDirectory 1
- } else {
- tcltest::testConstraint linkDirectory 0
- }
-} else {
- tcltest::testConstraint linkDirectory 1
-}
test cmdAH-29.4.1 {Tcl_FileObjCmd: type} {linkDirectory} {
set tempdir [makeDirectory temp]
set linkdir [file join [temporaryDirectory] link.dir]
@@ -1769,3 +1552,7 @@ cd $cmdAHwd
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/cmdIL.test b/tests/cmdIL.test
index 1f0665a..aed4264 100644
--- a/tests/cmdIL.test
+++ b/tests/cmdIL.test
@@ -9,16 +9,19 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2
namespace import -force ::tcltest::*
}
+# Used for constraining memory leak tests
+testConstraint memory [llength [info commands memory]]
+
test cmdIL-1.1 {Tcl_LsortObjCmd procedure} {
list [catch {lsort} msg] $msg
} {1 {wrong # args: should be "lsort ?options? list"}}
test cmdIL-1.2 {Tcl_LsortObjCmd procedure} {
list [catch {lsort -foo {1 3 2 5}} msg] $msg
-} {1 {bad option "-foo": must be -ascii, -command, -decreasing, -dictionary, -increasing, -index, -integer, -real, or -unique}}
+} {1 {bad option "-foo": must be -ascii, -command, -decreasing, -dictionary, -increasing, -index, -indices, -integer, -nocase, -real, or -unique}}
test cmdIL-1.3 {Tcl_LsortObjCmd procedure, default options} {
lsort {d e c b a \{ d35 d300}
} {a b c d d300 d35 e \{}
@@ -28,12 +31,15 @@ test cmdIL-1.4 {Tcl_LsortObjCmd procedure, -ascii option} {
test cmdIL-1.5 {Tcl_LsortObjCmd procedure, -command option} {
list [catch {lsort -command {1 3 2 5}} msg] $msg
} {1 {"-command" option must be followed by comparison command}}
-test cmdIL-1.6 {Tcl_LsortObjCmd procedure, -command option} {
+test cmdIL-1.6 {Tcl_LsortObjCmd procedure, -command option} -setup {
proc cmp {a b} {
expr {[string match x* $b] - [string match x* $a]}
}
+} -body {
lsort -command cmp {x1 abc x2 def x3 x4}
-} {x1 x2 x3 x4 abc def}
+} -result {x1 x2 x3 x4 abc def} -cleanup {
+ rename cmp ""
+}
test cmdIL-1.7 {Tcl_LsortObjCmd procedure, -decreasing option} {
lsort -decreasing {d e c b a d35 d300}
} {e d35 d300 d c b a}
@@ -51,7 +57,7 @@ test cmdIL-1.11 {Tcl_LsortObjCmd procedure, -index option} {
} {1 {"-index" option must be followed by list index}}
test cmdIL-1.12 {Tcl_LsortObjCmd procedure, -index option} {
list [catch {lsort -index foo {1 3 2 5}} msg] $msg
-} {1 {bad index "foo": must be integer or end?-integer?}}
+} {1 {bad index "foo": must be integer?[+-]integer? or end?[+-]integer?}}
test cmdIL-1.13 {Tcl_LsortObjCmd procedure, -index option} {
lsort -index end -integer {{2 25} {10 20 50 100} {3 16 42} 1}
} {1 {2 25} {3 16 42} {10 20 50 100}}
@@ -80,44 +86,52 @@ test cmdIL-1.23 {Tcl_LsortObjCmd procedure, unique sort with index} {
# lsort -unique should return the last unique item
lsort -unique -index 0 {{a b} {c b} {a c} {d a}}
} {{a c} {c b} {d a}}
-test cmdIL-1.24 {Tcl_LsortObjCmd procedure, order of -index and -command} {
+test cmdIL-1.24 {Tcl_LsortObjCmd procedure, order of -index and -command} -setup {
catch {rename 1 ""}
proc testcmp {a b} {return [string compare $a $b]}
+} -body {
set l [list [list a b] [list c d]]
- set result [list [catch {lsort -command testcmp -index 1 $l} msg] $msg]
+ list [catch {lsort -command testcmp -index 1 $l} msg] $msg
+} -cleanup {
rename testcmp ""
- set result
-} [list 0 [list [list a b] [list c d]]]
-test cmdIL-1.25 {Tcl_LsortObjCmd procedure, order of -index and -command} {
+} -result [list 0 [list [list a b] [list c d]]]
+test cmdIL-1.25 {Tcl_LsortObjCmd procedure, order of -index and -command} -setup {
catch {rename 1 ""}
proc testcmp {a b} {return [string compare $a $b]}
+} -body {
set l [list [list a b] [list c d]]
- set result [list [catch {lsort -index 1 -command testcmp $l} msg] $msg]
+ list [catch {lsort -index 1 -command testcmp $l} msg] $msg
+} -cleanup {
rename testcmp ""
- set result
-} [list 0 [list [list a b] [list c d]]]
+} -result [list 0 [list [list a b] [list c d]]]
# Note that the required order only exists in the end-1'th element;
# indexing using the end element or any fixed offset from the start
# will not work...
test cmdIL-1.26 {Tcl_LsortObjCmd procedure, offset indexing from end} {
lsort -index end-1 {{a 1 e i} {b 2 3 f g} {c 4 5 6 d h}}
} {{c 4 5 6 d h} {a 1 e i} {b 2 3 f g}}
+test cmdIL-1.27 {Tcl_LsortObjCmd procedure, returning indices} {
+ lsort -indices {a c b}
+} {0 2 1}
+test cmdIL-1.28 {Tcl_LsortObjCmd procedure, returning indices} {
+ lsort -indices -unique -decreasing -real {1.2 34.5 34.5 5.6}
+} {2 3 0}
test cmdIL-1.29 {Tcl_LsortObjCmd procedure, loss of list rep during sorting} {
set l {1 2 3}
- proc testcmp args {string length $::l}
- string length [lsort -command testcmp $l]
+ string length [lsort -command {apply {args {string length $::l}}} $l]
} 5
# Can't think of any good tests for the MergeSort and MergeLists
# procedures, except a bunch of random lists to sort.
-test cmdIL-2.1 {MergeSort and MergeLists procedures} {
+test cmdIL-2.1 {MergeSort and MergeLists procedures} -setup {
set result {}
set r 1435753299
proc rand {} {
global r
set r [expr {(16807 * $r) % (0x7fffffff)}]
}
+} -body {
for {set i 0} {$i < 150} {incr i} {
set x {}
for {set j 0} {$j < $i} {incr j} {
@@ -134,18 +148,23 @@ test cmdIL-2.1 {MergeSort and MergeLists procedures} {
}
}
set result
-} {}
+} -cleanup {
+ rename rand ""
+} -result {}
-test cmdIL-3.1 {SortCompare procedure, skip comparisons after error} {
- set x 0
+test cmdIL-3.1 {SortCompare procedure, skip comparisons after error} -setup {
proc cmp {a b} {
global x
incr x
error "error #$x"
}
+} -body {
+ set x 0
list [catch {lsort -integer -command cmp {48 6 28 190 16 2 3 6 1}} msg] \
$msg $x
-} {1 {error #1} 1}
+} -cleanup {
+ rename cmp ""
+} -result {1 {error #1} 1}
test cmdIL-3.2 {SortCompare procedure, -index option} {
list [catch {lsort -integer -index 2 "\\\{ {30 40 50}"} msg] $msg
} {1 {unmatched open brace in list}}
@@ -154,6 +173,9 @@ test cmdIL-3.3 {SortCompare procedure, -index option} {
} {1 {element 2 missing from sublist "20 10"}}
test cmdIL-3.4 {SortCompare procedure, -index option} {
list [catch {lsort -integer -index 2 "{a b c} \\\{"} msg] $msg
+} {1 {expected integer but got "c"}}
+test cmdIL-3.4.1 {SortCompare procedure, -index option} {
+ list [catch {lsort -integer -index 2 "{1 2 3} \\\{"} msg] $msg
} {1 {unmatched open brace in list}}
test cmdIL-3.5 {SortCompare procedure, -index option} {
list [catch {lsort -integer -index 2 {{20 10 13} {15}}} msg] $msg
@@ -174,8 +196,8 @@ test cmdIL-3.10 {SortCompare procedure, -integer option} {
list [catch {lsort -integer {3 q}} msg] $msg
} {1 {expected integer but got "q"}}
test cmdIL-3.11 {SortCompare procedure, -integer option} {
- lsort -integer {35 21 0x20 30 023 100 8}
-} {8 023 21 30 0x20 35 100}
+ lsort -integer {35 21 0x20 30 0o23 100 8}
+} {8 0o23 21 30 0x20 35 100}
test cmdIL-3.12 {SortCompare procedure, -real option} {
list [catch {lsort -real {6...4 3}} msg] $msg
} {1 {expected floating-point number but got "6...4"}}
@@ -185,12 +207,14 @@ test cmdIL-3.13 {SortCompare procedure, -real option} {
test cmdIL-3.14 {SortCompare procedure, -real option} {
lsort -real {24 2.5e01 16.7 85e-1 10.004}
} {85e-1 10.004 16.7 24 2.5e01}
-test cmdIL-3.15 {SortCompare procedure, -command option} {
+test cmdIL-3.15 {SortCompare procedure, -command option} -body {
proc cmp {a b} {
error "comparison error"
}
- list [catch {lsort -command cmp {48 6}} msg] $msg $errorInfo
-} {1 {comparison error} {comparison error
+ list [catch {lsort -command cmp {48 6}} msg] $msg $::errorInfo
+} -cleanup {
+ rename cmp ""
+} -result {1 {comparison error} {comparison error
while executing
"error "comparison error""
(procedure "cmp" line 2)
@@ -199,27 +223,33 @@ test cmdIL-3.15 {SortCompare procedure, -command option} {
(-compare command)
invoked from within
"lsort -command cmp {48 6}"}}
-test cmdIL-3.16 {SortCompare procedure, -command option, long command} {
+test cmdIL-3.16 {SortCompare procedure, -command option, long command} -body {
proc cmp {dummy a b} {
string compare $a $b
}
lsort -command {cmp {this argument is very very long in order to make the dstring overflow its statically allocated space}} {{this first element is also long in order to help expand the dstring} {the second element, last but not least, is quite long also, in order to make absolutely sure that space is allocated dynamically for the dstring}}
-} {{the second element, last but not least, is quite long also, in order to make absolutely sure that space is allocated dynamically for the dstring} {this first element is also long in order to help expand the dstring}}
-test cmdIL-3.17 {SortCompare procedure, -command option, non-integer result} {
+} -cleanup {
+ rename cmp ""
+} -result {{the second element, last but not least, is quite long also, in order to make absolutely sure that space is allocated dynamically for the dstring} {this first element is also long in order to help expand the dstring}}
+test cmdIL-3.17 {SortCompare procedure, -command option, non-integer result} -body {
proc cmp {a b} {
return foow
}
list [catch {lsort -command cmp {48 6}} msg] $msg
-} {1 {-compare command returned non-integer result}}
-test cmdIL-3.18 {SortCompare procedure, -command option} {
+} -cleanup {
+ rename cmp ""
+} -result {1 {-compare command returned non-integer result}}
+test cmdIL-3.18 {SortCompare procedure, -command option} -body {
proc cmp {a b} {
expr {$b - $a}
}
lsort -command cmp {48 6 18 22 21 35 36}
-} {48 36 35 22 21 18 6}
+} -cleanup {
+ rename cmp ""
+} -result {48 36 35 22 21 18 6}
test cmdIL-3.19 {SortCompare procedure, -decreasing option} {
- lsort -decreasing -integer {35 21 0x20 30 023 100 8}
-} {100 35 0x20 30 21 023 8}
+ lsort -decreasing -integer {35 21 0x20 30 0o23 100 8}
+} {100 35 0x20 30 21 0o23 8}
test cmdIL-4.1 {DictionaryCompare procedure, numerics, leading zeros} {
lsort -dictionary {a003b a03b}
@@ -358,7 +388,391 @@ test cmdIL-4.32 {DictionaryCompare procedure, chars between Z and a in ASCII} {
test cmdIL-4.33 {DictionaryCompare procedure, chars between Z and a in ASCII} {
lsort -dictionary [list AA ! c CC `]
} [list ! ` AA c CC]
+test cmdIL-4.34 {SortCompare procedure, -ascii option with -nocase option} {
+ lsort -ascii -nocase {d e c b a d35 d300 100 20}
+} {100 20 a b c d d300 d35 e}
+test cmdIL-4.35 {SortCompare procedure, -ascii option with -nocase option} {
+ lsort -ascii -nocase {d E c B a D35 d300 100 20}
+} {100 20 a B c d d300 D35 E}
+
+test cmdIL-5.1 {lsort with list style index} {
+ lsort -ascii -decreasing -index {0 1} {
+ {{Jim Alpha} 20000410}
+ {{Joe Bravo} 19990320}
+ {{Jacky Charlie} 19390911}
+ }
+} {{{Jacky Charlie} 19390911} {{Joe Bravo} 19990320} {{Jim Alpha} 20000410}}
+test cmdIL-5.2 {lsort with list style index} {
+ lsort -decreasing -index {0 1} {
+ {{Jim Alpha} 20000410}
+ {{Joe Bravo} 19990320}
+ {{Jacky Charlie} 19390911}
+ }
+} {{{Jacky Charlie} 19390911} {{Joe Bravo} 19990320} {{Jim Alpha} 20000410}}
+test cmdIL-5.3 {lsort with list style index} {
+ lsort -integer -increasing -index {1 end} {
+ {{Jim Alpha} 20000410}
+ {{Joe Bravo} 19990320}
+ {{Jacky Charlie} 19390911}
+ }
+} {{{Jacky Charlie} 19390911} {{Joe Bravo} 19990320} {{Jim Alpha} 20000410}}
+test cmdIL-5.4 {lsort with list style index} {
+ lsort -integer -index {1 end-1} {
+ {the {0 1 2 3 4 5} quick}
+ {brown {0 1 2 3 4} fox}
+ {jumps {30 31 2 33} over}
+ {the {0 1 2} lazy}
+ {dogs {0 1}}
+ }
+} {{dogs {0 1}} {the {0 1 2} lazy} {jumps {30 31 2 33} over} {brown {0 1 2 3 4} fox} {the {0 1 2 3 4 5} quick}}
+test cmdIL-5.5 {lsort with list style index and sharing} -body {
+ proc test_lsort {l} {
+ set n $l
+ foreach e $l {lappend n [list [expr {rand()}] $e]}
+ lindex [lsort -real -index $l $n] 1 1
+ }
+ expr srand(1)
+ test_lsort 0
+} -result 0 -cleanup {
+ rename test_lsort ""
+}
+
+# Compiled version
+test cmdIL-6.1 {lassign command syntax} -body {
+ proc testLassign {} {
+ lassign
+ }
+ testLassign
+} -returnCodes 1 -cleanup {
+ rename testLassign {}
+} -result {wrong # args: should be "lassign list varName ?varName ...?"}
+test cmdIL-6.2 {lassign command syntax} -body {
+ proc testLassign {} {
+ lassign x
+ }
+ testLassign
+} -returnCodes 1 -cleanup {
+ rename testLassign {}
+} -result {wrong # args: should be "lassign list varName ?varName ...?"}
+test cmdIL-6.3 {lassign command} -body {
+ proc testLassign {} {
+ set x FAIL
+ list [lassign a x] $x
+ }
+ testLassign
+} -result {{} a} -cleanup {
+ rename testLassign {}
+}
+test cmdIL-6.4 {lassign command} -body {
+ proc testLassign {} {
+ set x FAIL
+ set y FAIL
+ list [lassign a x y] $x $y
+ }
+ testLassign
+} -result {{} a {}} -cleanup {
+ rename testLassign {}
+}
+test cmdIL-6.5 {lassign command} -body {
+ proc testLassign {} {
+ set x FAIL
+ set y FAIL
+ list [lassign {a b} x y] $x $y
+ }
+ testLassign
+} -result {{} a b} -cleanup {
+ rename testLassign {}
+}
+test cmdIL-6.6 {lassign command} -body {
+ proc testLassign {} {
+ set x FAIL
+ set y FAIL
+ list [lassign {a b c} x y] $x $y
+ }
+ testLassign
+} -result {c a b} -cleanup {
+ rename testLassign {}
+}
+test cmdIL-6.7 {lassign command} -body {
+ proc testLassign {} {
+ set x FAIL
+ set y FAIL
+ list [lassign {a b c d} x y] $x $y
+ }
+ testLassign
+} -result {{c d} a b} -cleanup {
+ rename testLassign {}
+}
+test cmdIL-6.8 {lassign command - list format error} -body {
+ proc testLassign {} {
+ set x FAIL
+ set y FAIL
+ list [catch {lassign {a {b}c d} x y} msg] $msg $x $y
+ }
+ testLassign
+} -result {1 {list element in braces followed by "c" instead of space} FAIL FAIL} -cleanup {
+ rename testLassign {}
+}
+test cmdIL-6.9 {lassign command - assignment to arrays} -body {
+ proc testLassign {} {
+ list [lassign {a b} x(x)] $x(x)
+ }
+ testLassign
+} -result {b a} -cleanup {
+ rename testLassign {}
+}
+test cmdIL-6.10 {lassign command - variable update error} -body {
+ proc testLassign {} {
+ set x(x) {}
+ lassign a x
+ }
+ testLassign
+} -returnCodes 1 -result {can't set "x": variable is array} -cleanup {
+ rename testLassign {}
+}
+test cmdIL-6.11 {lassign command - variable update error} -body {
+ proc testLassign {} {
+ set x(x) {}
+ set y FAIL
+ list [catch {lassign a y x} msg] $msg $y
+ }
+ testLassign
+} -result {1 {can't set "x": variable is array} a} -cleanup {
+ rename testLassign {}
+}
+test cmdIL-6.12 {lassign command - memory leak testing} -setup {
+ unset -nocomplain x y
+ set x(x) {}
+ set y FAIL
+ proc getbytes {} {
+ set lines [split [memory info] "\n"]
+ lindex [lindex $lines 3] 3
+ }
+ proc stress {} {
+ global x y
+ lassign {} y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y
+ catch {lassign {} y y y y y y y y y y y y y y y y y y y y y y y y y x}
+ catch {lassign {} x}
+ }
+} -constraints memory -body {
+ set end [getbytes]
+ for {set i 0} {$i < 5} {incr i} {
+ stress
+ set tmp $end
+ set end [getbytes]
+ }
+ expr {$end - $tmp}
+} -result 0 -cleanup {
+ unset -nocomplain x y i tmp end
+ rename getbytes {}
+ rename stress {}
+}
+# Force non-compiled version
+test cmdIL-6.13 {lassign command syntax} -body {
+ proc testLassign {} {
+ set lassign lassign
+ $lassign
+ }
+ testLassign
+} -returnCodes 1 -cleanup {
+ rename testLassign {}
+} -result {wrong # args: should be "lassign list varName ?varName ...?"}
+test cmdIL-6.14 {lassign command syntax} -body {
+ proc testLassign {} {
+ set lassign lassign
+ $lassign x
+ }
+ testLassign
+} -returnCodes 1 -cleanup {
+ rename testLassign {}
+} -result {wrong # args: should be "lassign list varName ?varName ...?"}
+test cmdIL-6.15 {lassign command} -body {
+ proc testLassign {} {
+ set lassign lassign
+ set x FAIL
+ list [$lassign a x] $x
+ }
+ testLassign
+} -result {{} a} -cleanup {
+ rename testLassign {}
+}
+test cmdIL-6.16 {lassign command} -body {
+ proc testLassign {} {
+ set lassign lassign
+ set x FAIL
+ set y FAIL
+ list [$lassign a x y] $x $y
+ }
+ testLassign
+} -result {{} a {}} -cleanup {
+ rename testLassign {}
+}
+test cmdIL-6.17 {lassign command} -body {
+ proc testLassign {} {
+ set lassign lassign
+ set x FAIL
+ set y FAIL
+ list [$lassign {a b} x y] $x $y
+ }
+ testLassign
+} -result {{} a b} -cleanup {
+ rename testLassign {}
+}
+test cmdIL-6.18 {lassign command} -body {
+ proc testLassign {} {
+ set lassign lassign
+ set x FAIL
+ set y FAIL
+ list [$lassign {a b c} x y] $x $y
+ }
+ testLassign
+} -result {c a b} -cleanup {
+ rename testLassign {}
+}
+test cmdIL-6.19 {lassign command} -body {
+ proc testLassign {} {
+ set lassign lassign
+ set x FAIL
+ set y FAIL
+ list [$lassign {a b c d} x y] $x $y
+ }
+ testLassign
+} -result {{c d} a b} -cleanup {
+ rename testLassign {}
+}
+test cmdIL-6.20 {lassign command - list format error} -body {
+ proc testLassign {} {
+ set lassign lassign
+ set x FAIL
+ set y FAIL
+ list [catch {$lassign {a {b}c d} x y} msg] $msg $x $y
+ }
+ testLassign
+} -result {1 {list element in braces followed by "c" instead of space} FAIL FAIL} -cleanup {
+ rename testLassign {}
+}
+test cmdIL-6.21 {lassign command - assignment to arrays} -body {
+ proc testLassign {} {
+ set lassign lassign
+ list [$lassign {a b} x(x)] $x(x)
+ }
+ testLassign
+} -result {b a} -cleanup {
+ rename testLassign {}
+}
+test cmdIL-6.22 {lassign command - variable update error} -body {
+ proc testLassign {} {
+ set lassign lassign
+ set x(x) {}
+ $lassign a x
+ }
+ testLassign
+} -returnCodes 1 -result {can't set "x": variable is array} -cleanup {
+ rename testLassign {}
+}
+test cmdIL-6.23 {lassign command - variable update error} -body {
+ proc testLassign {} {
+ set lassign lassign
+ set x(x) {}
+ set y FAIL
+ list [catch {$lassign a y x} msg] $msg $y
+ }
+ testLassign
+} -result {1 {can't set "x": variable is array} a} -cleanup {
+ rename testLassign {}
+}
+test cmdIL-6.24 {lassign command - memory leak testing} -setup {
+ set x(x) {}
+ set y FAIL
+ proc getbytes {} {
+ set lines [split [memory info] "\n"]
+ lindex [lindex $lines 3] 3
+ }
+ proc stress {} {
+ global x y
+ set lassign lassign
+ $lassign {} y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y
+ catch {$lassign {} y y y y y y y y y y y y y y y y y y y y y y y y y x}
+ catch {$lassign {} x}
+ }
+} -constraints memory -body {
+ set end [getbytes]
+ for {set i 0} {$i < 5} {incr i} {
+ stress
+ set tmp $end
+ set end [getbytes]
+ }
+ expr {$end - $tmp}
+} -result 0 -cleanup {
+ unset -nocomplain x y i tmp end
+ rename getbytes {}
+ rename stress {}
+}
+# Assorted shimmering problems
+test cmdIL-6.25 {lassign command - shimmering protection} -body {
+ proc testLassign {} {
+ set x {a b c}
+ list [lassign $x $x y] $x [set $x] $y
+ }
+ testLassign
+} -result {c {a b c} a b} -cleanup {
+ rename testLassign {}
+}
+test cmdIL-6.26 {lassign command - shimmering protection} -body {
+ proc testLassign {} {
+ set x {a b c}
+ set lassign lassign
+ list [$lassign $x $x y] $x [set $x] $y
+ }
+ testLassign
+} -result {c {a b c} a b} -cleanup {
+ rename testLassign {}
+}
+
+test cmdIL-7.1 {lreverse command} -body {
+ lreverse
+} -returnCodes error -result "wrong # args: should be \"lreverse list\""
+test cmdIL-7.2 {lreverse command} -body {
+ lreverse a b
+} -returnCodes error -result "wrong # args: should be \"lreverse list\""
+test cmdIL-7.3 {lreverse command} -body {
+ lreverse "not \{a list"
+} -returnCodes error -result {unmatched open brace in list}
+test cmdIL-7.4 {lreverse command - shared object} {
+ set x {a b {c d} e f}
+ lreverse $x
+} {f e {c d} b a}
+test cmdIL-7.5 {lreverse command - unshared object} {
+ lreverse [list a b {c d} e f]
+} {f e {c d} b a}
+test cmdIL-7.6 {lreverse command - unshared object [Bug 1672585]} {
+ lreverse [set x {1 2 3}][unset x]
+} {3 2 1}
+test cmdIL-7.7 {lreverse command - empty object [Bug 1876793]} {
+ lreverse [list]
+} {}
+
+testConstraint testobj [llength [info commands testobj]]
+test cmdIL-7.8 {lreverse command - shared intrep [Bug 1675044]} -setup {
+ teststringobj set 1 {1 2 3}
+ testobj convert 1 list
+ testobj duplicate 1 2
+ variable x [teststringobj get 1]
+ variable y [teststringobj get 2]
+ testobj freeallvars
+ proc K {a b} {return $a}
+} -constraints testobj -body {
+ lreverse [K $y [unset y]]
+ lindex $x 0
+} -cleanup {
+ unset -nocomplain x y
+ rename K {}
+} -result 1
# cleanup
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/cmdInfo.test b/tests/cmdInfo.test
index 611bba8..86aa6e1 100644
--- a/tests/cmdInfo.test
+++ b/tests/cmdInfo.test
@@ -18,10 +18,8 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-::tcltest::testConstraint testcmdinfo \
- [llength [info commands testcmdinfo]]
-::tcltest::testConstraint testcmdtoken \
- [llength [info commands testcmdtoken]]
+testConstraint testcmdinfo [llength [info commands testcmdinfo]]
+testConstraint testcmdtoken [llength [info commands testcmdtoken]]
test cmdinfo-1.1 {command procedure and clientData} {testcmdinfo} {
testcmdinfo create x1
@@ -69,7 +67,7 @@ test cmdinfo-4.1 {Tcl_GetCommandName/Tcl_GetCommandFullName procedures} \
rename x1 newName
set y [testcmdtoken name $x]
rename newName x1
- eval lappend y [testcmdtoken name $x]
+ lappend y {*}[testcmdtoken name $x]
} {newName ::newName x1 ::x1}
catch {rename newTestCmd {}}
@@ -86,7 +84,7 @@ test cmdinfo-5.1 {Names for commands created when inside namespaces} \
}]
set y [testcmdtoken name $x]
rename ::testCmd newTestCmd
- eval lappend y [testcmdtoken name $x]
+ lappend y {*}[testcmdtoken name $x]
} {testCmd ::testCmd newTestCmd ::newTestCmd}
test cmdinfo-6.1 {Names for commands created when outside namespaces} \
@@ -94,7 +92,7 @@ test cmdinfo-6.1 {Names for commands created when outside namespaces} \
set x [testcmdtoken create cmdInfoNs1::cmdInfoNs2::testCmd]
set y [testcmdtoken name $x]
rename cmdInfoNs1::cmdInfoNs2::testCmd newTestCmd2
- eval lappend y [testcmdtoken name $x]
+ lappend y {*}[testcmdtoken name $x]
} {testCmd ::cmdInfoNs1::cmdInfoNs2::testCmd newTestCmd2 ::newTestCmd2}
# cleanup
@@ -102,3 +100,7 @@ catch {namespace delete cmdInfoNs1::cmdInfoNs2 cmdInfoNs1}
catch {rename x1 ""}
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/cmdMZ.test b/tests/cmdMZ.test
index b4e91c6..7fe4fda 100644
--- a/tests/cmdMZ.test
+++ b/tests/cmdMZ.test
@@ -11,11 +11,19 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest 2.1
- namespace import -force ::tcltest::*
+if {[catch {package require tcltest 2.1}]} {
+ puts stderr "Skipping tests in [info script]. tcltest 2.1 required."
+ return
}
+namespace eval ::tcl::test::cmdMZ {
+ namespace import ::tcltest::cleanupTests
+ namespace import ::tcltest::customMatch
+ namespace import ::tcltest::makeFile
+ namespace import ::tcltest::removeFile
+ namespace import ::tcltest::temporaryDirectory
+ namespace import ::tcltest::test
+
# Tcl_PwdObjCmd
test cmdMZ-1.1 {Tcl_PwdObjCmd} {
@@ -27,7 +35,7 @@ test cmdMZ-1.2 {Tcl_PwdObjCmd: simple pwd} {
test cmdMZ-1.3 {Tcl_PwdObjCmd: simple pwd} {
expr [string length pwd]>0
} 1
-test cmdMZ-1.4 {Tcl_PwdObjCmd: failure} {unixOnly nonPortable} {
+test cmdMZ-1.4 {Tcl_PwdObjCmd: failure} {unix nonPortable} {
# This test fails on various unix platforms (eg Linux) where
# permissions caching causes this to fail. The caching is strictly
# incorrect, but we have no control over that.
@@ -48,10 +56,10 @@ test cmdMZ-1.4 {Tcl_PwdObjCmd: failure} {unixOnly nonPortable} {
# Tcl_RenameObjCmd
test cmdMZ-2.1 {Tcl_RenameObjCmd: error conditions} {
- list [catch {rename r1} msg] $msg $errorCode
+ list [catch {rename r1} msg] $msg $::errorCode
} {1 {wrong # args: should be "rename oldName newName"} NONE}
test cmdMZ-2.2 {Tcl_RenameObjCmd: error conditions} {
- list [catch {rename r1 r2 r3} msg] $msg $errorCode
+ list [catch {rename r1 r2 r3} msg] $msg $::errorCode
} {1 {wrong # args: should be "rename oldName newName"} NONE}
test cmdMZ-2.3 {Tcl_RenameObjCmd: success} {
catch {rename r2 {}}
@@ -65,47 +73,182 @@ test cmdMZ-2.4 {Tcl_RenameObjCmd: success} {
list [catch {r1} msg] $msg
} {1 {invalid command name "r1"}}
-# The tests for Tcl_ReturnObjCmd are in proc-old.test
+# Some tests for Tcl_ReturnObjCmd are in proc-old.test
+
+test cmdMZ-return-1.0 {return checks for bad option values} -body {
+ return -options foo
+} -returnCodes error -match glob -result {bad -options value:*}
+test cmdMZ-return-1.1 {return checks for bad option values} -body {
+ return -code foo
+} -returnCodes error -match glob -result {bad completion code*}
+test cmdMZ-return-1.2 {return checks for bad option values} -body {
+ return -code 0x100000000
+} -returnCodes error -match glob -result {bad completion code*}
+test cmdMZ-return-1.3 {return checks for bad option values} -body {
+ return -level foo
+} -returnCodes error -match glob -result {bad -level value:*}
+test cmdMZ-return-1.4 {return checks for bad option values} -body {
+ return -level -1
+} -returnCodes error -match glob -result {bad -level value:*}
+test cmdMZ-return-1.5 {return checks for bad option values} -body {
+ return -level 3.1415926
+} -returnCodes error -match glob -result {bad -level value:*}
+
+proc dictSort {d} {
+ foreach k [lsort [dict keys $d]] {
+ lappend result $k [dict get $d $k]
+ }
+ return $result
+}
+
+test cmdMZ-return-2.0 {return option handling} {
+ list [catch return -> foo] [dictSort $foo]
+} {2 {-code 0 -level 1}}
+test cmdMZ-return-2.1 {return option handling} {
+ list [catch {return -bar soom} -> foo] [dictSort $foo]
+} {2 {-bar soom -code 0 -level 1}}
+test cmdMZ-return-2.2 {return option handling} {
+ list [catch {return -code return} -> foo] [dictSort $foo]
+} {2 {-code 0 -level 2}}
+test cmdMZ-return-2.3 {return option handling} {
+ list [catch {return -code return -level 10} -> foo] [dictSort $foo]
+} {2 {-code 0 -level 11}}
+test cmdMZ-return-2.4 {return option handling} -body {
+ return -level 0 -code error
+} -returnCodes error -result {}
+test cmdMZ-return-2.5 {return option handling} -body {
+ return -level 0 -code return
+} -returnCodes return -result {}
+test cmdMZ-return-2.6 {return option handling} -body {
+ return -level 0 -code break
+} -returnCodes break -result {}
+test cmdMZ-return-2.7 {return option handling} -body {
+ return -level 0 -code continue
+} -returnCodes continue -result {}
+test cmdMZ-return-2.8 {return option handling} -body {
+ return -level 0 -code -1
+} -returnCodes -1 -result {}
+test cmdMZ-return-2.9 {return option handling} -body {
+ return -level 0 -code 10
+} -returnCodes 10 -result {}
+test cmdMZ-return-2.10 {return option handling} {
+ list [catch {return -level 0 -code error} -> foo] [dictSort $foo]
+} {1 {-code 1 -errorcode NONE -errorinfo {
+ while executing
+"return -level 0 -code error"} -errorline 1 -level 0}}
+test cmdMZ-return-2.11 {return option handling} {
+ list [catch {return -level 0 -code break} -> foo] [dictSort $foo]
+} {3 {-code 3 -level 0}}
+test cmdMZ-return-2.12 {return option handling} -body {
+ return -level 0 -code error -options {-code ok}
+} -returnCodes ok -result {}
+test cmdMZ-return-2.13 {return option handling} -body {
+ return -level 0 -code error -options {-code foo}
+} -returnCodes error -match glob -result {bad completion code*}
+test cmdMZ-return-2.14 {return option handling} -body {
+ return -level 0 -code error -options {-code foo -options {-code break}}
+} -returnCodes break -result {}
+
+test cmdMZ-return-2.15 {return opton handling} -setup {
+ proc p {} {
+ return -code error -errorcode {a b} c
+ }
+ } -body {
+ list [catch p result] $result $::errorCode
+ } -cleanup {
+ rename p {}
+ } -result {1 c {a b}}
+
+test cmdMZ-return-2.16 {return opton handling} -setup {
+ proc p {} {
+ return -code error -errorcode [list a b] c
+ }
+ } -body {
+ list [catch p result] $result $::errorCode
+ } -cleanup {
+ rename p {}
+ } -result {1 c {a b}}
+
+test cmdMZ-return-2.17 {return opton handling} -setup {
+ proc p {} {
+ return -code error -errorcode a\ b c
+ }
+ } -body {
+ list [catch p result] $result $::errorCode
+ } -cleanup {
+ rename p {}
+ } -result {1 c {a b}}
+
+
+# Check that the result of a [return -options $opts $result] is
+# indistinguishable from that of the originally caught script, no
+# matter what the script is/does. (TIP 90)
+set i 0
+foreach script {
+ {}
+ {format x}
+ {set}
+ {set a 1}
+ {error}
+ {error foo}
+ {error foo bar}
+ {error foo bar baz}
+ {return -level 0}
+ {return -code error}
+ {return -code error -errorinfo foo}
+ {return -code error -errorinfo foo -errorcode bar}
+ {return -code error -errorinfo foo -errorcode bar -errorline 10}
+ {return -options {x y z 2}}
+ {return -level 3 -code break sdf}
+} {
+ test cmdMZ-return-3.$i "check that return after a catch is same:\n$script" {
+ set one [list [catch $script foo bar] $foo [dictSort $bar] \
+ $::errorCode $::errorInfo]
+ set two [list [catch {return -options $bar $foo} foo2 bar2] \
+ $foo2 [dictSort $bar2] $::errorCode $::errorInfo]
+ string equal $one $two
+ } 1
+ incr i
+}
+
# The tests for Tcl_ScanObjCmd are in scan.test
# Tcl_SourceObjCmd
+# More tests of Tcl_SourceObjCmd are in source.test
-test cmdMZ-3.1 {Tcl_SourceObjCmd: error conditions} {macOnly} {
- list [catch {source} msg] $msg
-} {1 {wrong # args: should be "source fileName" or "source -rsrc name ?fileName?" or "source -rsrcid id ?fileName?"}}
-test cmdMZ-3.2 {Tcl_SourceObjCmd: error conditions} {macOnly} {
- list [catch {source a b} msg] $msg
-} {1 {bad argument: should be "source fileName" or "source -rsrc name ?fileName?" or "source -rsrcid id ?fileName?"}}
-test cmdMZ-3.3 {Tcl_SourceObjCmd: error conditions} {unixOrPc} {
+test cmdMZ-3.3 {Tcl_SourceObjCmd: error conditions} -constraints {
+ unixOrPc
+} -body {
list [catch {source} msg] $msg
-} {1 {wrong # args: should be "source fileName"}}
-test cmdMZ-3.4 {Tcl_SourceObjCmd: error conditions} {unixOrPc} {
+} -match glob -result {1 {wrong # args: should be "source*fileName"}}
+test cmdMZ-3.4 {Tcl_SourceObjCmd: error conditions} -constraints {
+ unixOrPc
+} -body {
list [catch {source a b} msg] $msg
-} {1 {wrong # args: should be "source fileName"}}
+} -match glob -result {1 {wrong # args: should be "source*fileName"}}
proc ListGlobMatch {expected actual} {
if {[llength $expected] != [llength $actual]} {
- return 0
+ return 0
}
foreach e $expected a $actual {
- if {![string match $e $a]} {
- return 0
- }
+ if {![string match $e $a]} {
+ return 0
+ }
}
return 1
}
-customMatch listGlob ListGlobMatch
+customMatch listGlob [namespace which ListGlobMatch]
-test cmdMZ-3.5 {Tcl_SourceObjCmd: error in script} -setup {
+test cmdMZ-3.5 {Tcl_SourceObjCmd: error in script} -body {
set file [makeFile {
set x 146
error "error in sourced file"
set y $x
} source.file]
-} -body {
- list [catch {source $file} msg] $msg $errorInfo
-} -cleanup {
+ set result [list [catch {source $file} msg] $msg $::errorInfo]
removeFile source.file
+ set result
} -match listGlob -result {1 {error in sourced file} {error in sourced file
while executing
"error "error in sourced file""
@@ -122,10 +265,10 @@ test cmdMZ-3.6 {Tcl_SourceObjCmd: simple script} {
# Tcl_SplitObjCmd
test cmdMZ-4.1 {Tcl_SplitObjCmd: split errors} {
- list [catch split msg] $msg $errorCode
+ list [catch split msg] $msg $::errorCode
} {1 {wrong # args: should be "split string ?splitChars?"} NONE}
test cmdMZ-4.2 {Tcl_SplitObjCmd: split errors} {
- list [catch {split a b c} msg] $msg $errorCode
+ list [catch {split a b c} msg] $msg $::errorCode
} {1 {wrong # args: should be "split string ?splitChars?"} NONE}
test cmdMZ-4.3 {Tcl_SplitObjCmd: basic split commands} {
split "a\n b\t\r c\n "
@@ -138,7 +281,7 @@ test cmdMZ-4.5 {Tcl_SplitObjCmd: basic split commands} {
} {1 2 3 4 5}
test cmdMZ-4.6 {Tcl_SplitObjCmd: basic split commands} {
split "a\}b\[c\{\]\$"
-} "a\\}b\\\[c\\{\\\]\\\$"
+} "a\\\}b\\\[c\\\{\\\]\\\$"
test cmdMZ-4.7 {Tcl_SplitObjCmd: basic split commands} {
split {} {}
} {}
@@ -204,9 +347,10 @@ test cmdMZ-5.7 {Tcl_TimeObjCmd: errors generate right trace} {
invoked from within
"time {error foo}"}}
-# The tests for Tcl_TraceObjCmd and TraceVarProc are in trace.test
# The tests for Tcl_WhileObjCmd are in while.test
# cleanup
-::tcltest::cleanupTests
+cleanupTests
+}
+namespace delete ::tcl::test::cmdMZ
return
diff --git a/tests/compExpr-old.test b/tests/compExpr-old.test
index fc33a3d..bb19151 100644
--- a/tests/compExpr-old.test
+++ b/tests/compExpr-old.test
@@ -13,18 +13,77 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2
namespace import -force ::tcltest::*
}
-if {([catch {expr T1()} msg] == 1) && ($msg == {unknown math function "T1"})} {
- set gotT1 0
- puts "This application hasn't been compiled with the \"T1\" and"
- puts "\"T2\" math functions, so I'll skip some of the expr tests."
+if {[catch {expr T1()} msg] && $msg eq {invalid command name "tcl::mathfunc::T1"}} {
+ testConstraint testmathfunctions 0
} else {
- set gotT1 1
+ testConstraint testmathfunctions 1
}
+# Big test for correct ordering of data in [expr]
+
+proc testIEEE {} {
+ variable ieeeValues
+ binary scan [binary format dd -1.0 1.0] c* c
+ switch -exact -- $c {
+ {0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
+ # little endian
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \
+ ieeeValues(-Infinity)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \
+ ieeeValues(-Normal)
+ binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
+ ieeeValues(-Subnormal)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
+ ieeeValues(-0)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+0)
+ binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
+ ieeeValues(+Subnormal)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \
+ ieeeValues(+Normal)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
+ ieeeValues(+Infinity)
+ binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
+ ieeeValues(NaN)
+ set ieeeValues(littleEndian) 1
+ return 1
+ }
+ {-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
+ binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Infinity)
+ binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Normal)
+ binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Subnormal)
+ binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-0)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+0)
+ binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Subnormal)
+ binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Normal)
+ binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Infinity)
+ binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(NaN)
+ set ieeeValues(littleEndian) 0
+ return 1
+ }
+ default {
+ return 0
+ }
+ }
+}
+testConstraint ieeeFloatingPoint [testIEEE]
+
+testConstraint longIs32bit [expr {int(0x80000000) < 0}]
+testConstraint longIs64bit [expr {int(0x8000000000000000) < 0}]
+
# procedures used below
proc put_hello_char {c} {
@@ -67,7 +126,9 @@ proc do_twelve_days {} {
global xxx
set xxx ""
12days 1 1 1
- string length $xxx
+ set result [string length $xxx]
+ unset xxx
+ return $result
}
# start of tests
@@ -130,60 +191,49 @@ test compExpr-old-1.14 {TclCompileExprCmd: second level of substitutions in expr
test compExpr-old-2.1 {TclCompileExpr: are builtin functions registered?} {
expr double(5*[llength "6 2"])
} 10.0
-test compExpr-old-2.2 {TclCompileExpr: error in expr} {
- catch {expr 2**3} msg
- set msg
-} {syntax error in expression "2**3": unexpected operator *}
-test compExpr-old-2.3 {TclCompileExpr: junk after legal expr} {
- catch {expr 7*[llength "a b"]foo} msg
- set msg
-} {syntax error in expression "7*2foo": extra tokens at end of expression}
+test compExpr-old-2.2 {TclCompileExpr: error in expr} -body {
+ expr 2***3
+} -returnCodes error -match glob -result *
+test compExpr-old-2.3 {TclCompileExpr: junk after legal expr} -body {
+ expr 7*[llength "a b"]foo
+} -returnCodes error -match glob -result *
test compExpr-old-2.4 {TclCompileExpr: numeric expr string rep == formatted int rep} {
expr {0001}
} 1
test compExpr-old-3.1 {CompileCondExpr: just lor expr} {expr 3||0} 1
-test compExpr-old-3.2 {CompileCondExpr: error in lor expr} {
- catch {expr x||3} msg
- set msg
-} {syntax error in expression "x||3": variable references require preceding $}
+test compExpr-old-3.2 {CompileCondExpr: error in lor expr} -body {
+ expr x||3
+} -returnCodes error -match glob -result *
test compExpr-old-3.3 {CompileCondExpr: test true arm} {expr 3>2?44:66} 44
-test compExpr-old-3.4 {CompileCondExpr: error compiling true arm} {
- catch {expr 3>2?2**3:66} msg
- set msg
-} {syntax error in expression "3>2?2**3:66": unexpected operator *}
+test compExpr-old-3.4 {CompileCondExpr: error compiling true arm} -body {
+ expr 3>2?2***3:66
+} -returnCodes error -match glob -result *
test compExpr-old-3.5 {CompileCondExpr: test false arm} {expr 2>3?44:66} 66
-test compExpr-old-3.6 {CompileCondExpr: error compiling false arm} {
- catch {expr 2>3?44:2**3} msg
- set msg
-} {syntax error in expression "2>3?44:2**3": unexpected operator *}
-test compExpr-old-3.7 {CompileCondExpr: long arms & nested cond exprs} {nonPortable} {
- puts "Note: doing test compExpr-old-3.7 which can take several minutes to run"
+test compExpr-old-3.6 {CompileCondExpr: error compiling false arm} -body {
+ expr 2>3?44:2***3
+} -returnCodes error -match glob -result *
+test compExpr-old-3.7 {CompileCondExpr: long arms & nested cond exprs} {
hello_world
} {Hello world}
-catch {unset xxx}
-test compExpr-old-3.8 {CompileCondExpr: long arms & nested cond exprs} {nonPortable} {
- puts "Note: doing test compExpr-old-3.8 which can take several minutes to run"
+test compExpr-old-3.8 {CompileCondExpr: long arms & nested cond exprs} unix {
+ # Fails with a stack overflow on threaded Windows builds
do_twelve_days
} 2358
-catch {unset xxx}
test compExpr-old-4.1 {CompileLorExpr: just land expr} {expr 1.3&&3.3} 1
-test compExpr-old-4.2 {CompileLorExpr: error in land expr} {
- catch {expr x&&3} msg
- set msg
-} {syntax error in expression "x&&3": variable references require preceding $}
+test compExpr-old-4.2 {CompileLorExpr: error in land expr} -body {
+ expr x&&3
+} -returnCodes error -match glob -result *
test compExpr-old-4.3 {CompileLorExpr: simple lor exprs} {expr 0||1.0} 1
test compExpr-old-4.4 {CompileLorExpr: simple lor exprs} {expr 3.0||0.0} 1
test compExpr-old-4.5 {CompileLorExpr: simple lor exprs} {expr 0||0||1} 1
-test compExpr-old-4.6 {CompileLorExpr: error compiling lor arm} {
- catch {expr 2**3||4.0} msg
- set msg
-} {syntax error in expression "2**3||4.0": unexpected operator *}
-test compExpr-old-4.7 {CompileLorExpr: error compiling lor arm} {
- catch {expr 1.3||2**3} msg
- set msg
-} {syntax error in expression "1.3||2**3": unexpected operator *}
+test compExpr-old-4.6 {CompileLorExpr: error compiling lor arm} -body {
+ expr 2***3||4.0
+} -returnCodes error -match glob -result *
+test compExpr-old-4.7 {CompileLorExpr: error compiling lor arm} -body {
+ expr 1.3||2***3
+} -returnCodes error -match glob -result *
test compExpr-old-4.8 {CompileLorExpr: error compiling lor arms} {
list [catch {expr {"a"||"b"}} msg] $msg
} {1 {expected boolean value but got "a"}}
@@ -194,22 +244,19 @@ test compExpr-old-4.9 {CompileLorExpr: long lor arm} {
} 1
test compExpr-old-5.1 {CompileLandExpr: just bitor expr} {expr 7|0x13} 23
-test compExpr-old-5.2 {CompileLandExpr: error in bitor expr} {
- catch {expr x|3} msg
- set msg
-} {syntax error in expression "x|3": variable references require preceding $}
+test compExpr-old-5.2 {CompileLandExpr: error in bitor expr} -body {
+ expr x|3
+} -returnCodes error -match glob -result *
test compExpr-old-5.3 {CompileLandExpr: simple land exprs} {expr 0&&1.0} 0
test compExpr-old-5.4 {CompileLandExpr: simple land exprs} {expr 0&&0} 0
test compExpr-old-5.5 {CompileLandExpr: simple land exprs} {expr 3.0&&1.2} 1
test compExpr-old-5.6 {CompileLandExpr: simple land exprs} {expr 1&&1&&2} 1
-test compExpr-old-5.7 {CompileLandExpr: error compiling land arm} {
- catch {expr 2**3&&4.0} msg
- set msg
-} {syntax error in expression "2**3&&4.0": unexpected operator *}
-test compExpr-old-5.8 {CompileLandExpr: error compiling land arm} {
- catch {expr 1.3&&2**3} msg
- set msg
-} {syntax error in expression "1.3&&2**3": unexpected operator *}
+test compExpr-old-5.7 {CompileLandExpr: error compiling land arm} -body {
+ expr 2***3&&4.0
+} -returnCodes error -match glob -result *
+test compExpr-old-5.8 {CompileLandExpr: error compiling land arm} -body {
+ expr 1.3&&2***3
+} -returnCodes error -match glob -result *
test compExpr-old-5.9 {CompileLandExpr: error compiling land arm} {
list [catch {expr {"a"&&"b"}} msg] $msg
} {1 {expected boolean value but got "a"}}
@@ -220,22 +267,19 @@ test compExpr-old-5.10 {CompileLandExpr: long land arms} {
} 1
test compExpr-old-6.1 {CompileBitXorExpr: just bitand expr} {expr 7&0x13} 3
-test compExpr-old-6.2 {CompileBitXorExpr: error in bitand expr} {
- catch {expr x|3} msg
- set msg
-} {syntax error in expression "x|3": variable references require preceding $}
+test compExpr-old-6.2 {CompileBitXorExpr: error in bitand expr} -body {
+ expr x|3
+} -returnCodes error -match glob -result *
test compExpr-old-6.3 {CompileBitXorExpr: simple bitxor exprs} {expr 7^0x13} 20
test compExpr-old-6.4 {CompileBitXorExpr: simple bitxor exprs} {expr 3^0x10} 19
test compExpr-old-6.5 {CompileBitXorExpr: simple bitxor exprs} {expr 0^7} 7
test compExpr-old-6.6 {CompileBitXorExpr: simple bitxor exprs} {expr -1^7} -8
-test compExpr-old-6.7 {CompileBitXorExpr: error compiling bitxor arm} {
- catch {expr 2**3|6} msg
- set msg
-} {syntax error in expression "2**3|6": unexpected operator *}
-test compExpr-old-6.8 {CompileBitXorExpr: error compiling bitxor arm} {
- catch {expr 2^x} msg
- set msg
-} {syntax error in expression "2^x": variable references require preceding $}
+test compExpr-old-6.7 {CompileBitXorExpr: error compiling bitxor arm} -body {
+ expr 2***3|6
+} -returnCodes error -match glob -result *
+test compExpr-old-6.8 {CompileBitXorExpr: error compiling bitxor arm} -body {
+ expr 2^x
+} -returnCodes error -match glob -result *
test compExpr-old-6.9 {CompileBitXorExpr: runtime error in bitxor arm} {
list [catch {expr {24.0^3}} msg] $msg
} {1 {can't use floating-point value as operand of "^"}}
@@ -247,22 +291,19 @@ test compExpr-old-7.1 {CompileBitAndExpr: just equality expr} {expr 3==2} 0
test compExpr-old-7.2 {CompileBitAndExpr: just equality expr} {expr 2.0==2} 1
test compExpr-old-7.3 {CompileBitAndExpr: just equality expr} {expr 3.2!=2.2} 1
test compExpr-old-7.4 {CompileBitAndExpr: just equality expr} {expr {"abc" == "abd"}} 0
-test compExpr-old-7.5 {CompileBitAndExpr: error in equality expr} {
- catch {expr x==3} msg
- set msg
-} {syntax error in expression "x==3": variable references require preceding $}
+test compExpr-old-7.5 {CompileBitAndExpr: error in equality expr} -body {
+ expr x==3
+} -returnCodes error -match glob -result *
test compExpr-old-7.6 {CompileBitAndExpr: simple bitand exprs} {expr 7&0x13} 3
test compExpr-old-7.7 {CompileBitAndExpr: simple bitand exprs} {expr 0xf2&0x53} 82
test compExpr-old-7.8 {CompileBitAndExpr: simple bitand exprs} {expr 3&6} 2
test compExpr-old-7.9 {CompileBitAndExpr: simple bitand exprs} {expr -1&-7} -7
-test compExpr-old-7.10 {CompileBitAndExpr: error compiling bitand arm} {
- catch {expr 2**3&6} msg
- set msg
-} {syntax error in expression "2**3&6": unexpected operator *}
-test compExpr-old-7.11 {CompileBitAndExpr: error compiling bitand arm} {
- catch {expr 2&x} msg
- set msg
-} {syntax error in expression "2&x": variable references require preceding $}
+test compExpr-old-7.10 {CompileBitAndExpr: error compiling bitand arm} -body {
+ expr 2***3&6
+} -returnCodes error -match glob -result *
+test compExpr-old-7.11 {CompileBitAndExpr: error compiling bitand arm} -body {
+ expr 2&x
+} -returnCodes error -match glob -result *
test compExpr-old-7.12 {CompileBitAndExpr: runtime error in bitand arm} {
list [catch {expr {24.0&3}} msg] $msg
} {1 {can't use floating-point value as operand of "&"}}
@@ -274,22 +315,19 @@ test compExpr-old-8.1 {CompileEqualityExpr: just relational expr} {expr 3>=2} 1
test compExpr-old-8.2 {CompileEqualityExpr: just relational expr} {expr 2<=2.1} 1
test compExpr-old-8.3 {CompileEqualityExpr: just relational expr} {expr 3.2>"2.2"} 1
test compExpr-old-8.4 {CompileEqualityExpr: just relational expr} {expr {"0y"<"0x12"}} 0
-test compExpr-old-8.5 {CompileEqualityExpr: error in relational expr} {
- catch {expr x>3} msg
- set msg
-} {syntax error in expression "x>3": variable references require preceding $}
+test compExpr-old-8.5 {CompileEqualityExpr: error in relational expr} -body {
+ expr x>3
+} -returnCodes error -match glob -result *
test compExpr-old-8.6 {CompileEqualityExpr: simple equality exprs} {expr 7==0x13} 0
test compExpr-old-8.7 {CompileEqualityExpr: simple equality exprs} {expr -0xf2!=0x53} 1
test compExpr-old-8.8 {CompileEqualityExpr: simple equality exprs} {expr {"12398712938788234-1298379" != ""}} 1
test compExpr-old-8.9 {CompileEqualityExpr: simple equality exprs} {expr -1!="abc"} 1
-test compExpr-old-8.10 {CompileEqualityExpr: error compiling equality arm} {
- catch {expr 2**3==6} msg
- set msg
-} {syntax error in expression "2**3==6": unexpected operator *}
-test compExpr-old-8.11 {CompileEqualityExpr: error compiling equality arm} {
- catch {expr 2!=x} msg
- set msg
-} {syntax error in expression "2!=x": variable references require preceding $}
+test compExpr-old-8.10 {CompileEqualityExpr: error compiling equality arm} -body {
+ expr 2***3==6
+} -returnCodes error -match glob -result *
+test compExpr-old-8.11 {CompileEqualityExpr: error compiling equality arm} -body {
+ expr 2!=x
+} -returnCodes error -match glob -result *
test compExpr-old-9.1 {CompileRelationalExpr: just shift expr} {expr 3<<2} 12
@@ -300,48 +338,40 @@ test compExpr-old-9.4 {CompileRelationalExpr: just shift expr} {expr {1<<3}} 8
# The following test is different for 32-bit versus 64-bit
# architectures because LONG_MIN is different
-if {0x80000000 > 0} {
- test compExpr-old-9.5 {CompileRelationalExpr: shift expr producing LONG_MIN} {nonPortable} {
- expr {1<<63}
- } -9223372036854775808
-} else {
- test compExpr-old-9.5 {CompileRelationalExpr: shift expr producing LONG_MIN} {nonPortable} {
- expr {1<<31}
- } -2147483648
-}
-test compExpr-old-9.6 {CompileRelationalExpr: error in shift expr} {
- catch {expr x>>3} msg
- set msg
-} {syntax error in expression "x>>3": variable references require preceding $}
+test compExpr-old-9.5a {CompileRelationalExpr: shift expr producing LONG_MIN} longIs64bit {
+ expr {int(1<<63)}
+} -9223372036854775808
+test compExpr-old-9.5b {CompileRelationalExpr: shift expr producing LONG_MIN} longIs32bit {
+ expr {int(1<<31)}
+} -2147483648
+
+test compExpr-old-9.6 {CompileRelationalExpr: error in shift expr} -body {
+ expr x>>3
+} -returnCodes error -match glob -result *
test compExpr-old-9.7 {CompileRelationalExpr: simple relational exprs} {expr 0xff>=+0x3} 1
test compExpr-old-9.8 {CompileRelationalExpr: simple relational exprs} {expr -0xf2<0x3} 1
-test compExpr-old-9.9 {CompileRelationalExpr: error compiling relational arm} {
- catch {expr 2**3>6} msg
- set msg
-} {syntax error in expression "2**3>6": unexpected operator *}
-test compExpr-old-9.10 {CompileRelationalExpr: error compiling relational arm} {
- catch {expr 2<x} msg
- set msg
-} {syntax error in expression "2<x": variable references require preceding $}
+test compExpr-old-9.9 {CompileRelationalExpr: error compiling relational arm} -body {
+ expr 2***3>6
+} -returnCodes error -match glob -result *
+test compExpr-old-9.10 {CompileRelationalExpr: error compiling relational arm} -body {
+ expr 2<x
+} -returnCodes error -match glob -result *
test compExpr-old-10.1 {CompileShiftExpr: just add expr} {expr 4+-2} 2
test compExpr-old-10.2 {CompileShiftExpr: just add expr} {expr 0xff-2} 253
test compExpr-old-10.3 {CompileShiftExpr: just add expr} {expr -1--2} 1
-test compExpr-old-10.4 {CompileShiftExpr: just add expr} {expr 1-0123} -82
-test compExpr-old-10.5 {CompileShiftExpr: error in add expr} {
- catch {expr x+3} msg
- set msg
-} {syntax error in expression "x+3": variable references require preceding $}
+test compExpr-old-10.4 {CompileShiftExpr: just add expr} {expr 1-0o123} -82
+test compExpr-old-10.5 {CompileShiftExpr: error in add expr} -body {
+ expr x+3
+} -returnCodes error -match glob -result *
test compExpr-old-10.6 {CompileShiftExpr: simple shift exprs} {expr 0xff>>0x3} 31
test compExpr-old-10.7 {CompileShiftExpr: simple shift exprs} {expr -0xf2<<0x3} -1936
-test compExpr-old-10.8 {CompileShiftExpr: error compiling shift arm} {
- catch {expr 2**3>>6} msg
- set msg
-} {syntax error in expression "2**3>>6": unexpected operator *}
-test compExpr-old-10.9 {CompileShiftExpr: error compiling shift arm} {
- catch {expr 2<<x} msg
- set msg
-} {syntax error in expression "2<<x": variable references require preceding $}
+test compExpr-old-10.8 {CompileShiftExpr: error compiling shift arm} -body {
+ expr 2***3>>6
+} -returnCodes error -match glob -result *
+test compExpr-old-10.9 {CompileShiftExpr: error compiling shift arm} -body {
+ expr 2<<x
+} -returnCodes error -match glob -result *
test compExpr-old-10.10 {CompileShiftExpr: runtime error} {
list [catch {expr {24.0>>43}} msg] $msg
} {1 {can't use floating-point value as operand of ">>"}}
@@ -352,21 +382,18 @@ test compExpr-old-10.11 {CompileShiftExpr: runtime error} {
test compExpr-old-11.1 {CompileAddExpr: just multiply expr} {expr 4*-2} -8
test compExpr-old-11.2 {CompileAddExpr: just multiply expr} {expr 0xff%2} 1
test compExpr-old-11.3 {CompileAddExpr: just multiply expr} {expr -1/2} -1
-test compExpr-old-11.4 {CompileAddExpr: just multiply expr} {expr 7891%0123} 6
-test compExpr-old-11.5 {CompileAddExpr: error in multiply expr} {
- catch {expr x*3} msg
- set msg
-} {syntax error in expression "x*3": variable references require preceding $}
+test compExpr-old-11.4 {CompileAddExpr: just multiply expr} {expr 7891%0o123} 6
+test compExpr-old-11.5 {CompileAddExpr: error in multiply expr} -body {
+ expr x*3
+} -returnCodes error -match glob -result *
test compExpr-old-11.6 {CompileAddExpr: simple add exprs} {expr 0xff++0x3} 258
test compExpr-old-11.7 {CompileAddExpr: simple add exprs} {expr -0xf2--0x3} -239
-test compExpr-old-11.8 {CompileAddExpr: error compiling add arm} {
- catch {expr 2**3+6} msg
- set msg
-} {syntax error in expression "2**3+6": unexpected operator *}
-test compExpr-old-11.9 {CompileAddExpr: error compiling add arm} {
- catch {expr 2-x} msg
- set msg
-} {syntax error in expression "2-x": variable references require preceding $}
+test compExpr-old-11.8 {CompileAddExpr: error compiling add arm} -body {
+ expr 2***3+6
+} -returnCodes error -match glob -result *
+test compExpr-old-11.9 {CompileAddExpr: error compiling add arm} -body {
+ expr 2-x
+} -returnCodes error -match glob -result *
test compExpr-old-11.10 {CompileAddExpr: runtime error} {
list [catch {expr {24.0+"xx"}} msg] $msg
} {1 {can't use non-numeric string as operand of "+"}}
@@ -376,7 +403,10 @@ test compExpr-old-11.11 {CompileAddExpr: runtime error} {
test compExpr-old-11.12 {CompileAddExpr: runtime error} {
list [catch {expr {3/0}} msg] $msg
} {1 {divide by zero}}
-test compExpr-old-11.13 {CompileAddExpr: runtime error} {
+test compExpr-old-11.13a {CompileAddExpr: runtime error} ieeeFloatingPoint {
+ list [catch {expr {2.3/0.0}} msg] $msg
+} {0 Inf}
+test compExpr-old-11.13b {CompileAddExpr: runtime error} !ieeeFloatingPoint {
list [catch {expr {2.3/0.0}} msg] $msg
} {1 {divide by zero}}
@@ -384,20 +414,17 @@ test compExpr-old-12.1 {CompileMultiplyExpr: just unary expr} {expr ~4} -5
test compExpr-old-12.2 {CompileMultiplyExpr: just unary expr} {expr --5} 5
test compExpr-old-12.3 {CompileMultiplyExpr: just unary expr} {expr !27} 0
test compExpr-old-12.4 {CompileMultiplyExpr: just unary expr} {expr ~0xff00ff} -16711936
-test compExpr-old-12.5 {CompileMultiplyExpr: error in unary expr} {
- catch {expr ~x} msg
- set msg
-} {syntax error in expression "~x": variable references require preceding $}
+test compExpr-old-12.5 {CompileMultiplyExpr: error in unary expr} -body {
+ expr ~x
+} -returnCodes error -match glob -result *
test compExpr-old-12.6 {CompileMultiplyExpr: simple multiply exprs} {expr 0xff*0x3} 765
test compExpr-old-12.7 {CompileMultiplyExpr: simple multiply exprs} {expr -0xf2%-0x3} -2
-test compExpr-old-12.8 {CompileMultiplyExpr: error compiling multiply arm} {
- catch {expr 2*3%%6} msg
- set msg
-} {syntax error in expression "2*3%%6": unexpected operator %}
-test compExpr-old-12.9 {CompileMultiplyExpr: error compiling multiply arm} {
- catch {expr 2*x} msg
- set msg
-} {syntax error in expression "2*x": variable references require preceding $}
+test compExpr-old-12.8 {CompileMultiplyExpr: error compiling multiply arm} -body {
+ expr 2*3%%6
+} -returnCodes error -match glob -result *
+test compExpr-old-12.9 {CompileMultiplyExpr: error compiling multiply arm} -body {
+ expr 2*x
+} -returnCodes error -match glob -result *
test compExpr-old-12.10 {CompileMultiplyExpr: runtime error} {
list [catch {expr {24.0*"xx"}} msg] $msg
} {1 {can't use non-numeric string as operand of "*"}}
@@ -406,20 +433,19 @@ test compExpr-old-12.11 {CompileMultiplyExpr: runtime error} {
} {1 {can't use non-numeric string as operand of "/"}}
test compExpr-old-13.1 {CompileUnaryExpr: unary exprs} {expr -0xff} -255
-test compExpr-old-13.2 {CompileUnaryExpr: unary exprs} {expr +000123} 83
+test compExpr-old-13.2 {CompileUnaryExpr: unary exprs} {expr +0o00123} 83
test compExpr-old-13.3 {CompileUnaryExpr: unary exprs} {expr +--++36} 36
test compExpr-old-13.4 {CompileUnaryExpr: unary exprs} {expr !2} 0
test compExpr-old-13.5 {CompileUnaryExpr: unary exprs} {expr +--+-62.0} -62.0
test compExpr-old-13.6 {CompileUnaryExpr: unary exprs} {expr !0.0} 1
test compExpr-old-13.7 {CompileUnaryExpr: unary exprs} {expr !0xef} 0
-test compExpr-old-13.8 {CompileUnaryExpr: error compiling unary expr} {
- catch {expr ~x} msg
+test compExpr-old-13.8 {CompileUnaryExpr: error compiling unary expr} -body {
+ expr ~x
+} -returnCodes error -match glob -result *
+test compExpr-old-13.9 {CompileUnaryExpr: error compiling unary expr} -body {
+ expr !1.x
set msg
-} {syntax error in expression "~x": variable references require preceding $}
-test compExpr-old-13.9 {CompileUnaryExpr: error compiling unary expr} {
- catch {expr !1.x} msg
- set msg
-} {syntax error in expression "!1.x": extra tokens at end of expression}
+} -returnCodes error -match glob -result *
test compExpr-old-13.10 {CompileUnaryExpr: runtime error} {
list [catch {expr {~"xx"}} msg] $msg
} {1 {can't use non-numeric string as operand of "~"}}
@@ -442,7 +468,7 @@ test compExpr-old-13.16 {CompileUnaryExpr: error in primary expr} {
test compExpr-old-14.1 {CompilePrimaryExpr: literal primary} {expr 1} 1
test compExpr-old-14.2 {CompilePrimaryExpr: literal primary} {expr 123} 123
test compExpr-old-14.3 {CompilePrimaryExpr: literal primary} {expr 0xff} 255
-test compExpr-old-14.4 {CompilePrimaryExpr: literal primary} {expr 00010} 8
+test compExpr-old-14.4 {CompilePrimaryExpr: literal primary} {expr 0o0010} 8
test compExpr-old-14.5 {CompilePrimaryExpr: literal primary} {expr 62.0} 62.0
test compExpr-old-14.6 {CompilePrimaryExpr: literal primary} {
expr 3.1400000
@@ -479,15 +505,12 @@ test compExpr-old-14.15 {CompilePrimaryExpr: var reference primary} {
catch {expr $i.2} msg
set msg
} 123.2
-test compExpr-old-14.16 {CompilePrimaryExpr: error compiling var reference primary} {
- catch {expr {$a(foo}} msg
- set errorInfo
-} {missing )
- while compiling
-"expr {$a(foo}"}
-test compExpr-old-14.17 {CompilePrimaryExpr: string primary that looks like var ref} {
+test compExpr-old-14.16 {CompilePrimaryExpr: error compiling var reference primary} -body {
+ expr {$a(foo}
+} -returnCodes error -match glob -result *
+test compExpr-old-14.17 {CompilePrimaryExpr: string primary that looks like var ref} -body {
expr $
-} $
+} -returnCodes error -match glob -result *
test compExpr-old-14.18 {CompilePrimaryExpr: quoted string primary} {
expr "21"
} 21
@@ -508,114 +531,89 @@ test compExpr-old-14.21 {CompilePrimaryExpr: error in quoted string primary} {
test compExpr-old-14.22 {CompilePrimaryExpr: subcommand primary} {
expr {[set i 123; set i]}
} 123
-test compExpr-old-14.23 {CompilePrimaryExpr: error in subcommand primary} {
+test compExpr-old-14.23 {CompilePrimaryExpr: error in subcommand primary} -body {
catch {expr {[set]}} msg
- set errorInfo
-} {wrong # args: should be "set varName ?newValue?"
- while compiling
-"set"
- while compiling
-"expr {[set]}"}
-test compExpr-old-14.24 {CompilePrimaryExpr: error in subcommand primary} {
- catch {expr {[set i}} msg
- set errorInfo
-} {missing close-bracket
- while compiling
-"expr {[set i}"}
+ set ::errorInfo
+} -match glob -result {wrong # args: should be "set varName ?newValue?"
+ while *ing
+"set"*}
+test compExpr-old-14.24 {CompilePrimaryExpr: error in subcommand primary} -body {
+ expr {[set i}
+} -returnCodes error -match glob -result *
test compExpr-old-14.25 {CompilePrimaryExpr: math function primary} {
format %.6g [expr exp(1.0)]
} 2.71828
test compExpr-old-14.26 {CompilePrimaryExpr: math function primary} {
format %.6g [expr pow(2.0+0.1,3.0+0.1)]
} 9.97424
-test compExpr-old-14.27 {CompilePrimaryExpr: error in math function primary} {
- catch {expr sinh::(2.0)} msg
- set errorInfo
-} {syntax error in expression "sinh::(2.0)": expected parenthesis enclosing function arguments
- while compiling
-"expr sinh::(2.0)"}
+test compExpr-old-14.27 {CompilePrimaryExpr: error in math function primary} -body {
+ expr sinh::(2.0)
+} -returnCodes error -match glob -result *
test compExpr-old-14.28 {CompilePrimaryExpr: subexpression primary} {
expr 2+(3*4)
} 14
-test compExpr-old-14.29 {CompilePrimaryExpr: error in subexpression primary} {
+test compExpr-old-14.29 {CompilePrimaryExpr: error in subexpression primary} -body {
catch {expr 2+(3*[set])} msg
- set errorInfo
-} {wrong # args: should be "set varName ?newValue?"
- while compiling
-"set"
- while compiling
-"expr 2+(3*[set])"}
-test compExpr-old-14.30 {CompilePrimaryExpr: missing paren in subexpression primary} {
- catch {expr 2+(3*(4+5)} msg
- set errorInfo
-} {syntax error in expression "2+(3*(4+5)": looking for close parenthesis
- while compiling
-"expr 2+(3*(4+5)"}
+ set ::errorInfo
+} -match glob -result {wrong # args: should be "set varName ?newValue?"
+ while *ing
+"set"*}
+test compExpr-old-14.30 {CompilePrimaryExpr: missing paren in subexpression primary} -body {
+ expr 2+(3*(4+5)
+} -returnCodes error -match glob -result *
test compExpr-old-14.31 {CompilePrimaryExpr: just var ref in subexpression primary} {
set i "5+10"
list "[expr $i] == 15" "[expr ($i)] == 15" "[eval expr ($i)] == 15"
} {{15 == 15} {15 == 15} {15 == 15}}
-test compExpr-old-14.32 {CompilePrimaryExpr: unexpected token} {
- catch {expr @} msg
- set errorInfo
-} {syntax error in expression "@": character not legal in expressions
- while compiling
-"expr @"}
-
-test compExpr-old-15.1 {CompileMathFuncCall: missing parenthesis} {
- catch {expr sinh2.0)} msg
- set errorInfo
-} {syntax error in expression "sinh2.0)": variable references require preceding $
- while compiling
-"expr sinh2.0)"}
-test compExpr-old-15.2 {CompileMathFuncCall: unknown math function} {
+test compExpr-old-14.32 {CompilePrimaryExpr: unexpected token} -body {
+ expr @
+} -returnCodes error -match glob -result *
+
+test compExpr-old-15.1 {CompileMathFuncCall: missing parenthesis} -body {
+ expr sinh2.0)
+} -returnCodes error -match glob -result *
+test compExpr-old-15.2 {CompileMathFuncCall: unknown math function} -body {
catch {expr whazzathuh(1)} msg
- set errorInfo
-} {unknown math function "whazzathuh"
- while compiling
+ set ::errorInfo
+} -match glob -result {* "*whazzathuh"
+ while *ing
"expr whazzathuh(1)"}
-test compExpr-old-15.3 {CompileMathFuncCall: too many arguments} {
+test compExpr-old-15.3 {CompileMathFuncCall: too many arguments} -body {
catch {expr sin(1,2,3)} msg
- set errorInfo
-} {too many arguments for math function
- while compiling
+ set ::errorInfo
+} -match glob -result {too many arguments for math function*
+ while *ing
"expr sin(1,2,3)"}
-test compExpr-old-15.4 {CompileMathFuncCall: ')' found before last required arg} {
+test compExpr-old-15.4 {CompileMathFuncCall: ')' found before last required arg} -body {
catch {expr sin()} msg
- set errorInfo
-} {too few arguments for math function
- while compiling
+ set ::errorInfo
+} -match glob -result {too few arguments for math function*
+ while *ing
"expr sin()"}
-test compExpr-old-15.5 {CompileMathFuncCall: too few arguments} {
+test compExpr-old-15.5 {CompileMathFuncCall: too few arguments} -body {
catch {expr pow(1)} msg
- set errorInfo
-} {too few arguments for math function
- while compiling
+ set ::errorInfo
+} -match glob -result {too few arguments for math function*
+ while *ing
"expr pow(1)"}
-test compExpr-old-15.6 {CompileMathFuncCall: missing ')'} {
- catch {expr sin(1} msg
- set errorInfo
-} {syntax error in expression "sin(1": missing close parenthesis at end of function call
- while compiling
-"expr sin(1"}
-if $gotT1 {
- test compExpr-old-15.7 {CompileMathFuncCall: call registered math function} {
- expr 2*T1()
- } 246
- test compExpr-old-15.8 {CompileMathFuncCall: call registered math function} {
- expr T2()*3
- } 1035
-
- test compExpr-old-15.9 {CompileMathFuncCall: call registered math function} {
- expr T3(21, 37)
- } 37
- test compExpr-old-15.10 {CompileMathFuncCall: call registered math function} {
- expr T3(21.2, 37)
- } 37.0
- test compExpr-old-15.11 {CompileMathFuncCall: call registered math function} {
- expr T3(-21.2, -17.5)
- } -17.5
-}
+test compExpr-old-15.6 {CompileMathFuncCall: missing ')'} -body {
+ expr sin(1
+} -returnCodes error -match glob -result *
+test compExpr-old-15.7 {CompileMathFuncCall: call registered math function} testmathfunctions {
+ expr 2*T1()
+} 246
+test compExpr-old-15.8 {CompileMathFuncCall: call registered math function} testmathfunctions {
+ expr T2()*3
+} 1035
+test compExpr-old-15.9 {CompileMathFuncCall: call registered math function} testmathfunctions {
+ expr T3(21, 37)
+} 37
+test compExpr-old-15.10 {CompileMathFuncCall: call registered math function} testmathfunctions {
+ expr T3(21.2, 37)
+} 37.0
+test compExpr-old-15.11 {CompileMathFuncCall: call registered math function} testmathfunctions {
+ expr T3(-21.2, -17.5)
+} -17.5
test compExpr-old-16.1 {GetToken: checks whether integer token starting with "0x" (e.g., "0x$") is invalid} {
catch {unset a}
diff --git a/tests/compExpr.test b/tests/compExpr.test
index e775b66..f02e999 100644
--- a/tests/compExpr.test
+++ b/tests/compExpr.test
@@ -9,31 +9,33 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest 2
+ package require tcltest
namespace import -force ::tcltest::*
}
-if {([catch {expr T1()} msg] == 1) && ($msg == {unknown math function "T1"})} {
- set gotT1 0
- puts "This application hasn't been compiled with the \"T1\" and"
- puts "\"T2\" math functions, so I'll skip some of the expr tests."
+if {[catch {expr T1()} msg] && $msg eq {invalid command name "tcl::mathfunc::T1"}} {
+ testConstraint testmathfunctions 0
} else {
- set gotT1 1
+ testConstraint testmathfunctions 1
}
+# Constrain memory leak tests
+testConstraint memory [llength [info commands memory]]
+
catch {unset a}
test compExpr-1.1 {TclCompileExpr procedure, successful expr parse and compile} {
expr 1+2
} 3
-test compExpr-1.2 {TclCompileExpr procedure, error parsing expr} {
- list [catch {expr 1+2+} msg] $msg
-} {1 {syntax error in expression "1+2+": premature end of expression}}
-test compExpr-1.3 {TclCompileExpr procedure, error compiling expr} {
+test compExpr-1.2 {TclCompileExpr procedure, error parsing expr} -body {
+ expr 1+2+
+} -returnCodes error -match glob -result *
+test compExpr-1.3 {TclCompileExpr procedure, error compiling expr} -body {
list [catch {expr "foo(123)"} msg] $msg
-} {1 {unknown math function "foo"}}
+} -match glob -result {1 {* "*foo"}}
+
test compExpr-1.4 {TclCompileExpr procedure, expr has no operators} {
- set a {000123}
+ set a {0o00123}
expr {$a}
} 83
@@ -42,9 +44,9 @@ test compExpr-2.1 {CompileSubExpr procedure, TCL_TOKEN_WORD parse token} {
set a 27
expr {"foo$a" < "bar"}
} 0
-test compExpr-2.2 {CompileSubExpr procedure, error compiling TCL_TOKEN_WORD parse token} {
- list [catch {expr {"00[expr 1+]" + 17}} msg] $msg
-} {1 {syntax error in expression "1+": premature end of expression}}
+test compExpr-2.2 {CompileSubExpr procedure, error compiling TCL_TOKEN_WORD parse token} -body {
+ expr {"00[expr 1+]" + 17}
+} -returnCodes error -match glob -result *
test compExpr-2.3 {CompileSubExpr procedure, TCL_TOKEN_TEXT parse token} {
expr {{12345}}
} 12345
@@ -61,9 +63,9 @@ test compExpr-2.6 {CompileSubExpr procedure, TCL_TOKEN_COMMAND parse token} {
test compExpr-2.7 {CompileSubExpr procedure, TCL_TOKEN_COMMAND parse token} {
expr {[]}
} {}
-test compExpr-2.8 {CompileSubExpr procedure, error in TCL_TOKEN_COMMAND parse token} {
- list [catch {expr {[foo "bar"xxx] + 17}} msg] $msg
-} {1 {extra characters after close-quote}}
+test compExpr-2.8 {CompileSubExpr procedure, error in TCL_TOKEN_COMMAND parse token} -body {
+ expr {[foo "bar"xxx] + 17}
+} -returnCodes error -match glob -result *
test compExpr-2.9 {CompileSubExpr procedure, TCL_TOKEN_VARIABLE parse token} {
catch {unset a}
set a 123
@@ -87,16 +89,16 @@ test compExpr-2.13 {CompileSubExpr procedure, error in TCL_TOKEN_SUB_EXPR parse
catch {unset a}
set a 15
list [catch {expr {27 || "$a[expr 1+]00"}} msg] $msg
-} {1 {syntax error in expression "1+": premature end of expression}}
+} {0 1}
test compExpr-2.14 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, op found} {
expr {5*6}
} 30
test compExpr-2.15 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, math function found} {
format %.6g [expr {sin(2.0)}]
} 0.909297
-test compExpr-2.16 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, math function not found} {
+test compExpr-2.16 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, math function not found} -body {
list [catch {expr {fred(2.0)}} msg] $msg
-} {1 {unknown math function "fred"}}
+} -match glob -result {1 {* "*fred"}}
test compExpr-2.17 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, normal operator} {
expr {4*2}
} 8
@@ -153,18 +155,18 @@ test compExpr-2.33 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, normal o
test compExpr-2.34 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, special operator} {
expr {+2}
} 2
-test compExpr-2.35 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, error in special operator} {
- list [catch {expr {+[expr 1+]}} msg] $msg
-} {1 {syntax error in expression "1+": premature end of expression}}
+test compExpr-2.35 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, error in special operator} -body {
+ expr {+[expr 1+]}
+} -returnCodes error -match glob -result *
test compExpr-2.36 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, special operator} {
expr {4+2}
} 6
-test compExpr-2.37 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, error in special operator} {
- list [catch {expr {[expr 1+]+5}} msg] $msg
-} {1 {syntax error in expression "1+": premature end of expression}}
-test compExpr-2.38 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, error in special operator} {
- list [catch {expr {5+[expr 1+]}} msg] $msg
-} {1 {syntax error in expression "1+": premature end of expression}}
+test compExpr-2.37 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, error in special operator} -body {
+ expr {[expr 1+]+5}
+} -returnCodes error -match glob -result *
+test compExpr-2.38 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, error in special operator} -body {
+ expr {5+[expr 1+]}
+} -returnCodes error -match glob -result *
test compExpr-2.39 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, special operator} {
expr {-2}
} -2
@@ -180,7 +182,7 @@ test compExpr-2.42 {CompileSubExpr procedure, error in TCL_TOKEN_SUB_EXPR parse
catch {unset a}
set a 15
list [catch {expr {27 || "$a[expr 1+]00"}} msg] $msg
-} {1 {syntax error in expression "1+": premature end of expression}}
+} {0 1}
test compExpr-2.43 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, special operator} {
catch {unset a}
set a false
@@ -195,7 +197,7 @@ test compExpr-2.45 {CompileSubExpr procedure, error in TCL_TOKEN_SUB_EXPR parse
catch {unset a}
set a 15
list [catch {expr {1? 54 : "$a[expr 1+]00"}} msg] $msg
-} {1 {syntax error in expression "1+": premature end of expression}}
+} {0 54}
test compExpr-3.1 {CompileLandOrLorExpr procedure, numeric 1st operand} {
catch {unset a}
@@ -207,9 +209,9 @@ test compExpr-3.2 {CompileLandOrLorExpr procedure, nonnumeric 1st operand} {
set a no
expr {$a&&1}
} 0
-test compExpr-3.3 {CompileSubExpr procedure, error in 1st operand} {
- list [catch {expr {[expr *2]||0}} msg] $msg
-} {1 {syntax error in expression "*2": unexpected operator *}}
+test compExpr-3.3 {CompileSubExpr procedure, error in 1st operand} -body {
+ expr {[expr *2]||0}
+} -returnCodes error -match glob -result *
test compExpr-3.4 {CompileLandOrLorExpr procedure, result is 1 or 0} {
catch {unset a}
catch {unset b}
@@ -237,9 +239,9 @@ test compExpr-3.8 {CompileLandOrLorExpr procedure, nonnumeric 2nd operand} {
set a no
expr {1&&$a}
} 0
-test compExpr-3.9 {CompileLandOrLorExpr procedure, error in 2nd operand} {
- list [catch {expr {0||[expr %2]}} msg] $msg
-} {1 {syntax error in expression "%2": unexpected operator %}}
+test compExpr-3.9 {CompileLandOrLorExpr procedure, error in 2nd operand} -body {
+ expr {0||[expr %2]}
+} -returnCodes error -match glob -result *
test compExpr-3.10 {CompileLandOrLorExpr procedure, long lor/land arm} {
set a "abcdefghijkl"
set i 7
@@ -256,9 +258,9 @@ test compExpr-4.2 {CompileCondExpr procedure, complex test, convert to numeric}
set a no
expr {[set a]? 27 : -54}
} -54
-test compExpr-4.3 {CompileCondExpr procedure, error in test} {
- list [catch {expr {[expr *2]? +1 : -1}} msg] $msg
-} {1 {syntax error in expression "*2": unexpected operator *}}
+test compExpr-4.3 {CompileCondExpr procedure, error in test} -body {
+ expr {[expr *2]? +1 : -1}
+} -returnCodes error -match glob -result *
test compExpr-4.4 {CompileCondExpr procedure, simple "true" clause} {
catch {unset a}
set a no
@@ -269,9 +271,9 @@ test compExpr-4.5 {CompileCondExpr procedure, convert "true" clause to numeric}
set a no
expr {1? $a : -54}
} no
-test compExpr-4.6 {CompileCondExpr procedure, error in "true" clause} {
- list [catch {expr {1? [expr *2] : -127}} msg] $msg
-} {1 {syntax error in expression "*2": unexpected operator *}}
+test compExpr-4.6 {CompileCondExpr procedure, error in "true" clause} -body {
+ expr {1? [expr *2] : -127}
+} -returnCodes error -match glob -result *
test compExpr-4.7 {CompileCondExpr procedure, simple "false" clause} {
catch {unset a}
set a no
@@ -279,50 +281,83 @@ test compExpr-4.7 {CompileCondExpr procedure, simple "false" clause} {
} nope
test compExpr-4.8 {CompileCondExpr procedure, convert "false" clause to numeric} {
catch {unset a}
- set a 00123
+ set a 0o0123
expr {0? 42 : $a}
} 83
test compExpr-4.9 {CompileCondExpr procedure, error in "false" clause} {
list [catch {expr {1? 15 : [expr *2]}} msg] $msg
-} {1 {syntax error in expression "*2": unexpected operator *}}
+} {0 15}
test compExpr-5.1 {CompileMathFuncCall procedure, math function found} {
format %.6g [expr atan2(1.0, 2.0)]
} 0.463648
-test compExpr-5.2 {CompileMathFuncCall procedure, math function not found} {
+test compExpr-5.2 {CompileMathFuncCall procedure, math function not found} -body {
list [catch {expr {do_it()}} msg] $msg
-} {1 {unknown math function "do_it"}}
-if $gotT1 {
- test compExpr-5.3 {CompileMathFuncCall: call registered math function} {
- expr 3*T1()-1
- } 368
- test compExpr-5.4 {CompileMathFuncCall: call registered math function} {
- expr T2()*3
- } 1035
-}
-test compExpr-5.5 {CompileMathFuncCall procedure, too few arguments} {
+} -match glob -result {1 {* "*do_it"}}
+test compExpr-5.3 {CompileMathFuncCall: call registered math function} testmathfunctions {
+ expr 3*T1()-1
+} 368
+test compExpr-5.4 {CompileMathFuncCall: call registered math function} testmathfunctions {
+ expr T2()*3
+} 1035
+test compExpr-5.5 {CompileMathFuncCall procedure, too few arguments} -body {
list [catch {expr {atan2(1.0)}} msg] $msg
-} {1 {too few arguments for math function}}
+} -match glob -result {1 {too few arguments for math function*}}
test compExpr-5.6 {CompileMathFuncCall procedure, complex argument} {
format %.6g [expr pow(2.1, 27.5-(24.4*(5%2)))]
} 9.97424
-test compExpr-5.7 {CompileMathFuncCall procedure, error in argument} {
- list [catch {expr {sinh(2.*)}} msg] $msg
-} {1 {syntax error in expression "sinh(2.*)": unexpected close parenthesis}}
-test compExpr-5.8 {CompileMathFuncCall procedure, too many arguments} {
+test compExpr-5.7 {CompileMathFuncCall procedure, error in argument} -body {
+ expr {sinh(2.*)}
+} -returnCodes error -match glob -result *
+test compExpr-5.8 {CompileMathFuncCall procedure, too many arguments} -body {
list [catch {expr {sinh(2.0, 3.0)}} msg] $msg
-} {1 {too many arguments for math function}}
-test compExpr-5.9 {CompileMathFuncCall procedure, too many arguments} {
+} -match glob -result {1 {too many arguments for math function*}}
+test compExpr-5.9 {CompileMathFuncCall procedure, too many arguments} -body {
list [catch {expr {0 <= rand(5.2)}} msg] $msg
-} {1 {too many arguments for math function}}
-test compExpr-5.10 {error return from unbraced math func call of unknown function} -body {
- expr {bogus()}
-} -returnCodes error -result {unknown math function "bogus"}
+} -match glob -result {1 {too many arguments for math function*}}
+
+test compExpr-6.1 {LogSyntaxError procedure, error in expr longer than 60 chars} -body {
+ expr {(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)/} -1 foo 3
+} -returnCodes error -match glob -result *
+test compExpr-7.1 {Memory Leak} -constraints memory -setup {
+ proc getbytes {} {
+ set lines [split [memory info] \n]
+ lindex $lines 3 3
+ }
+} -body {
+ set end [getbytes]
+ for {set i 0} {$i < 5} {incr i} {
+ interp create slave
+ slave eval expr 1+2+3+4+5+6+7+8+9+10+11+12+13
+ interp delete slave
+ set tmp $end
+ set end [getbytes]
+ }
+ set leakedBytes [expr {$end - $tmp}]
+} -cleanup {
+ unset end i tmp
+ rename getbytes {}
+} -result 0
-test compExpr-6.1 {LogSyntaxError procedure, error in expr longer than 60 chars} {
- list [catch {expr {(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)/} -1 foo 3} msg] $msg
-} {1 {syntax error in expression "(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+012...": extra tokens at end of expression}}
+test compExpr-7.2 {[Bug 1869989]: expr parser memleak} -constraints memory -setup {
+ proc getbytes {} {
+ set lines [split [memory info] \n]
+ lindex $lines 3 3
+ }
+} -body {
+ set i 5
+ set end [getbytes]
+ while {[incr i -1]} {
+ expr ${i}000
+ set tmp $end
+ set end [getbytes]
+ }
+ set leakedBytes [expr {$end - $tmp}]
+} -cleanup {
+ unset end i tmp
+ rename getbytes {}
+} -result 0
# cleanup
catch {unset a}
diff --git a/tests/compile.test b/tests/compile.test
index 9a5339c..7e9dcda 100644
--- a/tests/compile.test
+++ b/tests/compile.test
@@ -14,6 +14,10 @@
package require tcltest 2
namespace import -force ::tcltest::*
+testConstraint exec [llength [info commands exec]]
+testConstraint memory [llength [info commands memory]]
+testConstraint testevalex [llength [info commands testevalex]]
+
# The following tests are very incomplete, although the rest of the
# test suite covers this file fairly well.
@@ -112,7 +116,6 @@ test compile-3.4 {TclCompileCatchCmd: bcc'ed [return] is caught} {
}
foo
} {2}
-
test compile-3.5 {TclCompileCatchCmd: recover from error, [Bug 705406]} {
proc foo {} {
catch {
@@ -123,6 +126,36 @@ test compile-3.5 {TclCompileCatchCmd: recover from error, [Bug 705406]} {
}
list [catch foo msg] $msg
} {0 1}
+test compile-3.6 {TclCompileCatchCmd: error in storing result [Bug 3098302]} {*}{
+ -setup {
+ namespace eval catchtest {
+ variable result1 {}
+ }
+ trace add variable catchtest::result1 write catchtest::failtrace
+ proc catchtest::failtrace {n1 n2 op} {
+ return -code error "trace on $n1 fails by request"
+ }
+ }
+ -body {
+ proc catchtest::x {} {
+ variable result1
+ set count 0
+ for {set i 0} {$i < 10} {incr i} {
+ set status2 [catch {
+ set status1 [catch {
+ return -code error -level 0 "original failure"
+ } result1 options1]
+ } result2 options2]
+ incr count
+ }
+ list $count $result2
+ }
+ catchtest::x
+ }
+ -result {10 {can't set "result1": trace on result1 fails by request}}
+ -cleanup {namespace delete catchtest}
+}
+
test compile-4.1 {TclCompileForCmd: command substituted test expression} {
set i 0
@@ -231,35 +264,35 @@ test compile-11.1 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
lindex a bogus
}
list [catch {p} msg] $msg
-} {1 {bad index "bogus": must be integer or end?-integer?}}
+} {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}}
test compile-11.2 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
proc p {} { set r [list foobar] ; string index a bogus }
list [catch {p} msg] $msg
-} {1 {bad index "bogus": must be integer or end?-integer?}}
-test compile-11.3 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
- proc p {} { set r [list foobar] ; string index a 09 }
+} {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}}
+test compile-11.3 {Tcl_Append*: ensure Tcl_ResetResult is used properly} -body {
+ proc p {} { set r [list foobar] ; string index a 0o9 }
list [catch {p} msg] $msg
-} {1 {bad index "09": must be integer or end?-integer? (looks like invalid octal number)}}
+} -match glob -result {1 {*invalid octal number*}}
test compile-11.4 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
proc p {} { set r [list foobar] ; array set var {one two many} }
list [catch {p} msg] $msg
} {1 {list must have an even number of elements}}
test compile-11.5 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
- proc p {} { set r [list foobar] ; incr foo }
+ proc p {} { set r [list foobar] ; incr foo bar baz}
list [catch {p} msg] $msg
-} {1 {can't read "foo": no such variable}}
+} {1 {wrong # args: should be "incr varName ?increment?"}}
test compile-11.6 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
- proc p {} { set r [list foobar] ; incr foo bogus }
+ proc p {} { set r [list foobar] ; incr}
list [catch {p} msg] $msg
-} {1 {expected integer but got "bogus"}}
-test compile-11.7 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
+} {1 {wrong # args: should be "incr varName ?increment?"}}
+test compile-11.7 {Tcl_Append*: ensure Tcl_ResetResult is used properly} -body {
proc p {} { set r [list foobar] ; expr !a }
- list [catch {p} msg] $msg
-} {1 {syntax error in expression "!a": variable references require preceding $}}
-test compile-11.8 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
+ p
+} -returnCodes error -match glob -result *
+test compile-11.8 {Tcl_Append*: ensure Tcl_ResetResult is used properly} -body {
proc p {} { set r [list foobar] ; expr {!a} }
- list [catch {p} msg] $msg
-} {1 {syntax error in expression "!a": variable references require preceding $}}
+ p
+} -returnCodes error -match glob -result *
test compile-11.9 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
proc p {} { set r [list foobar] ; llength "\{" }
list [catch {p} msg] $msg
@@ -271,16 +304,13 @@ test compile-11.9 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
# TclReleaseLiteral. They are only effective when tcl is compiled
# with TCL_MEM_DEBUG
#
-# Special test for leak on interp delete [Bug 467523].
-::tcltest::testConstraint exec [llength [info commands exec]]
-::tcltest::testConstraint memDebug [llength [info commands memory]]
-
-test compile-12.1 {testing literal leak on interp delete} {memDebug} {
+# Special test for leak on interp delete [Bug 467523].
+test compile-12.1 {testing literal leak on interp delete} -setup {
proc getbytes {} {
set lines [split [memory info] "\n"]
- lindex [lindex $lines 3] 3
+ lindex $lines 3 3
}
-
+} -constraints memory -body {
set end [getbytes]
for {set i 0} {$i < 5} {incr i} {
interp create foo
@@ -290,36 +320,37 @@ test compile-12.1 {testing literal leak on interp delete} {memDebug} {
interp delete foo
set tmp $end
set end [getbytes]
- }
+ }
+ set leakedBytes [expr {$end - $tmp}]
+} -cleanup {
rename getbytes {}
- set leak [expr {$end - $tmp}]
-} 0
+ unset -nocomplain end i tmp leakedBytes
+} -result 0
# Special test for a memory error in a preliminary fix of [Bug 467523].
# It requires executing a helpfile. Presumably the child process is
# used because when this test fails, it crashes.
-test compile-12.2 {testing error on literal deletion} {memDebug exec} {
- makeFile {
+test compile-12.2 {testing error on literal deletion} -constraints {memory exec} -body {
+ set sourceFile [makeFile {
for {set i 0} {$i < 5} {incr i} {
namespace eval bar {}
namespace delete bar
}
puts 0
- } source.file
- set res [catch {
- exec [interpreter] source.file
- }]
- catch {removeFile source.file}
- set res
-} 0
+ } source.file]
+ exec [interpreter] $sourceFile
+} -cleanup {
+ catch {removeFile $sourceFile}
+} -result 0
# Test to catch buffer overrun in TclCompileTokens from buf 530320
-test compile-12.3 {check for a buffer overrun} {
+test compile-12.3 {check for a buffer overrun} -body {
proc crash {} {
puts $array([expr {a+2}])
}
- list [catch crash msg] $msg
-} {1 {syntax error in expression "a+2": variable references require preceding $}}
-
-test compile-12.4 {TclCleanupLiteralTable segfault} {
+ crash
+} -returnCodes error -cleanup {
+ rename crash {}
+} -match glob -result *
+test compile-12.4 {TclCleanupLiteralTable segfault} -body {
# Tcl Bug 1001997
# Here, we're trying to test a case that causes a crash in
# TclCleanupLiteralTable. The conditions that we're trying to
@@ -346,36 +377,37 @@ test compile-12.4 {TclCleanupLiteralTable segfault} {
# (c) Delete the interpreter to invoke TclCleanupLiteralTable
# and tickle the bug.
proc foo {} {
- set i [interp create]
- $i eval {
- namespace eval ::w {concat 4649; variable bugbug}
- namespace eval ::w {
- concat x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 \
- x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 \
- x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 \
- x31 x32 X33 X34 X35 X36 X37 X38 X39 X40 \
- x41 x42 x43 x44 x45 x46 x47 x48 x49 x50 \
- x51 x52 x53 x54 x55 x56 x57 x58 x59 x60 \
- x61 x62 x63 x64
- concat y1 y2 y3 y4 y5 y6 y7 y8 y9 y10 \
- y11 y12 y13 y14 y15 y16 y17 y18 y19 y20 \
- y21 y22 y23 y24 y25 y26 y27 y28 y29 y30 \
- y31 y32 Y33 Y34 Y35 Y36 Y37 Y38 Y39 Y40 \
- y41 y42 y43 y44 y45 y46 y47 y48 y49 y50 \
- y51 y52 y53 y54 y55 y56 y57 y58 y59 y60 \
- y61 y62 y63 y64
- concat z1 z2 z3 z4 z5 z6 z7 z8 z9 z10 \
- z11 z12 z13 z14 z15 z16 z17 z18 z19 z20 \
- z21 z22 z23 z24 z25 z26 z27 z28 z29 z30 \
- z31 z32
- }
- }
- interp delete $i; # must not crash
- return ok
+ set i [interp create]
+ $i eval {
+ namespace eval ::w {concat 4649; variable bugbug}
+ namespace eval ::w {
+ concat x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 \
+ x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 \
+ x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 \
+ x31 x32 X33 X34 X35 X36 X37 X38 X39 X40 \
+ x41 x42 x43 x44 x45 x46 x47 x48 x49 x50 \
+ x51 x52 x53 x54 x55 x56 x57 x58 x59 x60 \
+ x61 x62 x63 x64
+ concat y1 y2 y3 y4 y5 y6 y7 y8 y9 y10 \
+ y11 y12 y13 y14 y15 y16 y17 y18 y19 y20 \
+ y21 y22 y23 y24 y25 y26 y27 y28 y29 y30 \
+ y31 y32 Y33 Y34 Y35 Y36 Y37 Y38 Y39 Y40 \
+ y41 y42 y43 y44 y45 y46 y47 y48 y49 y50 \
+ y51 y52 y53 y54 y55 y56 y57 y58 y59 y60 \
+ y61 y62 y63 y64
+ concat z1 z2 z3 z4 z5 z6 z7 z8 z9 z10 \
+ z11 z12 z13 z14 z15 z16 z17 z18 z19 z20 \
+ z21 z22 z23 z24 z25 z26 z27 z28 z29 z30 \
+ z31 z32
+ }
+ }
+ interp delete $i; # must not crash
+ return ok
}
foo
-} ok
-
+} -cleanup {
+ rename foo {}
+} -result ok
# Special test for underestimating the maxStackSize required for a
# compiled command. A failure will cause a segfault in the child
@@ -398,7 +430,7 @@ test compile-14.1 {testing errors in element name; segfault?} {} {
list $msg1 $msg2
} {{wrong # args: should be "error message ?errorInfo? ?errorCode?"} {can't read "abba": no such variable}}
-# Next 4 tests cover Tcl Bug 633204
+# Tests compile-15.* cover Tcl Bug 633204
test compile-15.1 {proper TCL_RETURN code from [return]} {
proc p {} {catch return}
set result [p]
@@ -430,6 +462,174 @@ test compile-15.5 {proper TCL_RETURN code from [return]} {
set result
} ""
+for {set noComp 0} {$noComp <= 1} {incr noComp} {
+
+if $noComp {
+ interp alias {} run {} testevalex
+ set constraints testevalex
+} else {
+ interp alias {} run {} if 1
+ set constraints {}
+}
+
+test compile-16.1.$noComp {TclCompileScript: word expansion} $constraints {
+ run "list [string repeat {{*}a } 255]"
+} [lrepeat 255 a]
+test compile-16.2.$noComp {TclCompileScript: word expansion} $constraints {
+ run "list [string repeat {{*}a } 256]"
+} [lrepeat 256 a]
+test compile-16.3.$noComp {TclCompileScript: word expansion} $constraints {
+ run "list [string repeat {{*}a } 257]"
+} [lrepeat 257 a]
+test compile-16.4.$noComp {TclCompileScript: word expansion} $constraints {
+ run {{*}list}
+} {}
+test compile-16.5.$noComp {TclCompileScript: word expansion} $constraints {
+ run {{*}list {*}{x y z}}
+} {x y z}
+test compile-16.6.$noComp {TclCompileScript: word expansion} $constraints {
+ run {{*}list {*}[list x y z]}
+} {x y z}
+test compile-16.7.$noComp {TclCompileScript: word expansion} $constraints {
+ run {{*}list {*}[list x y z][list x y z]}
+} {x y zx y z}
+test compile-16.8.$noComp {TclCompileScript: word expansion} -body {
+ set l {x y z}
+ run {{*}list {*}$l}
+} -constraints $constraints -cleanup {
+ unset l
+} -result {x y z}
+test compile-16.9.$noComp {TclCompileScript: word expansion} -body {
+ set l {x y z}
+ run {{*}list {*}$l$l}
+} -constraints $constraints -cleanup {
+ unset l
+} -result {x y zx y z}
+test compile-16.10.$noComp {TclCompileScript: word expansion} -body {
+ run {{*}\{}
+} -constraints $constraints -returnCodes error \
+-result {unmatched open brace in list}
+test compile-16.11.$noComp {TclCompileScript: word expansion} -body {
+ proc badList {} {return \{}
+ run {{*}[badList]}
+} -constraints $constraints -cleanup {
+ rename badList {}
+} -returnCodes error -result {unmatched open brace in list}
+test compile-16.12.$noComp {TclCompileScript: word expansion} $constraints {
+ run {{*}list x y z}
+} {x y z}
+test compile-16.13.$noComp {TclCompileScript: word expansion} $constraints {
+ run {{*}list x y {*}z}
+} {x y z}
+test compile-16.14.$noComp {TclCompileScript: word expansion} $constraints {
+ run {{*}list x {*}y z}
+} {x y z}
+test compile-16.15.$noComp {TclCompileScript: word expansion} $constraints {
+ run {list x y {*}z}
+} {x y z}
+test compile-16.16.$noComp {TclCompileScript: word expansion} $constraints {
+ run {list x {*}y z}
+} {x y z}
+test compile-16.17.$noComp {TclCompileScript: word expansion} $constraints {
+ run {list {*}x y z}
+} {x y z}
+
+# These tests note that expansion can in theory cause the number of
+# arguments to a command to exceed INT_MAX, which is as big as objc
+# is allowed to get.
+#
+# In practice, it seems we will run out of memory before we confront
+# this issue. Note that compiled operations run out of memory at
+# smaller objc values than direct string evaluation.
+#
+# These tests are constrained as knownBug because they are likely
+# to cause memory allocation panics somewhere, and we don't want
+# panics in the test suite.
+#
+test compile-16.18.$noComp {TclCompileScript: word expansion} -body {
+ proc LongList {} {return [lrepeat [expr {1<<10}] x]}
+ llength [run "list [string repeat {{*}[LongList] } [expr {1<<10}]]"]
+} -constraints [linsert $constraints 0 knownBug] -cleanup {
+ rename LongList {}
+} -returnCodes ok -result [expr {1<<20}]
+test compile-16.19.$noComp {TclCompileScript: word expansion} -body {
+ proc LongList {} {return [lrepeat [expr {1<<11}] x]}
+ llength [run "list [string repeat {{*}[LongList] } [expr {1<<11}]]"]
+} -constraints [linsert $constraints 0 knownBug] -cleanup {
+ rename LongList {}
+} -returnCodes ok -result [expr {1<<22}]
+test compile-16.20.$noComp {TclCompileScript: word expansion} -body {
+ proc LongList {} {return [lrepeat [expr {1<<12}] x]}
+ llength [run "list [string repeat {{*}[LongList] } [expr {1<<12}]]"]
+} -constraints [linsert $constraints 0 knownBug] -cleanup {
+ rename LongList {}
+} -returnCodes ok -result [expr {1<<24}]
+# This is the one that should cause overflow
+test compile-16.21.$noComp {TclCompileScript: word expansion} -body {
+ proc LongList {} {return [lrepeat [expr {1<<16}] x]}
+ llength [run "list [string repeat {{*}[LongList] } [expr {1<<16}]]"]
+} -constraints [linsert $constraints 0 knownBug] -cleanup {
+ rename LongList {}
+} -returnCodes ok -result [expr {wide(1)<<32}]
+test compile-16.22.$noComp {
+ Bug 845412: TclCompileScript: word expansion not mandatory
+} -body {
+ # This test may crash and will fail unless Bug 845412 is fixed.
+ proc ReturnResults args {return $args}
+ run "ReturnResults [string repeat {x } 260]"
+} -constraints $constraints -cleanup {
+ rename ReturnResults {}
+} -returnCodes ok -result [string trim [string repeat {x } 260]]
+test compile-16.23.$noComp {
+ Bug 1032805: defer parse error until run time
+} -constraints $constraints -body {
+ namespace eval x {
+ run {
+ proc if {a b} {uplevel 1 [list set $a $b]}
+ if 1 {syntax {}{}}
+ }
+ }
+} -cleanup {
+ namespace delete x
+} -returnCodes ok -result {syntax {}{}}
+test compile-16.24.$noComp {
+ Bug 1638414: bad list constant as first expanded term
+} -constraints $constraints -body {
+ run "{*}\"\{foo bar\""
+} -returnCodes error -result {unmatched open brace in list}
+} ;# End of noComp loop
+
+# These tests are messy because it wrecks the interpreter it runs in!
+# They demonstrate issues arising from [FRQ 1101710]
+test compile-17.1 {Command interpretation binding for compiled code} -constraints knownBug -setup {
+ set i [interp create]
+} -body {
+ $i eval {
+ if 1 {
+ expr [
+ proc expr args {return substituted}
+ format {[subst compiled]}
+ ]
+ }
+ }
+} -cleanup {
+ interp delete $i
+} -result substituted
+test compile-17.2 {Command interpretation binding for non-compiled code} -setup {
+ set i [interp create]
+} -body {
+ $i eval {
+ if 1 {
+ [subst expr] [
+ proc expr args {return substituted}
+ format {[subst compiled]}
+ ]
+ }
+ }
+} -cleanup {
+ interp delete $i
+} -result substituted
+
# cleanup
catch {rename p ""}
catch {namespace delete test_ns_compile}
diff --git a/tests/concat.test b/tests/concat.test
index 82a8965..c95e116 100644
--- a/tests/concat.test
+++ b/tests/concat.test
@@ -50,15 +50,3 @@ test concat-4.3 {pruning off extra white space sets length correctly} {
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/config.test b/tests/config.test
new file mode 100644
index 0000000..c0a56b7
--- /dev/null
+++ b/tests/config.test
@@ -0,0 +1,60 @@
+# -*- tcl -*-
+# Commands covered: pkgconfig
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands. Sourcing this file into Tcl runs the tests and
+# generates output for errors. No output means no errors were found.
+#
+# Copyright (c) 1991-1993 The Regents of the University of California.
+# Copyright (c) 1994-1996 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.
+
+if {[lsearch [namespace children] ::tcltest] == -1} {
+ package require tcltest
+ namespace import -force ::tcltest::*
+}
+
+test pkgconfig-1.1 {query keys} {
+ lsort [::tcl::pkgconfig list]
+} {64bit bindir,install bindir,runtime compile_debug compile_stats debug docdir,install docdir,runtime includedir,install includedir,runtime libdir,install libdir,runtime mem_debug optimized profiled scriptdir,install scriptdir,runtime threaded}
+test pkgconfig-1.2 {query keys multiple times} {
+ string compare [::tcl::pkgconfig list] [::tcl::pkgconfig list]
+} 0
+test pkgconfig-1.3 {query value multiple times} {
+ string compare \
+ [::tcl::pkgconfig get bindir,install] \
+ [::tcl::pkgconfig get bindir,install]
+} 0
+
+
+test pkgconfig-2.0 {error: missing subcommand} {
+ catch {::tcl::pkgconfig} msg
+ set msg
+} {wrong # args: should be "::tcl::pkgconfig subcommand ?argument?"}
+test pkgconfig-2.1 {error: illegal subcommand} {
+ catch {::tcl::pkgconfig foo} msg
+ set msg
+} {bad subcommand "foo": must be get or list}
+test pkgconfig-2.2 {error: list with arguments} {
+ catch {::tcl::pkgconfig list foo} msg
+ set msg
+} {wrong # args: should be "::tcl::pkgconfig list"}
+test pkgconfig-2.3 {error: get without arguments} {
+ catch {::tcl::pkgconfig get} msg
+ set msg
+} {wrong # args: should be "::tcl::pkgconfig get key"}
+test pkgconfig-2.4 {error: query unknown key} {
+ catch {::tcl::pkgconfig get foo} msg
+ set msg
+} {key not known}
+test pkgconfig-2.5 {error: query with to many arguments} {
+ catch {::tcl::pkgconfig get foo bar} msg
+ set msg
+} {wrong # args: should be "::tcl::pkgconfig subcommand ?argument?"}
+
+# cleanup
+::tcltest::cleanupTests
+return
diff --git a/tests/dcall.test b/tests/dcall.test
index 4bbcfbe..8977c31 100644
--- a/tests/dcall.test
+++ b/tests/dcall.test
@@ -16,44 +16,27 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-if {[info commands testdcall] == {}} {
- puts "This application hasn't been compiled with the \"testdcall\""
- puts "command, so I can't test Tcl_CallWhenDeleted."
- ::tcltest::cleanupTests
- return
-}
+testConstraint testdcall [llength [info commands testdcall]]
-test dcall-1.1 {deletion callbacks} {
+test dcall-1.1 {deletion callbacks} testdcall {
lsort -increasing [testdcall 1 2 3]
} {1 2 3}
-test dcall-1.2 {deletion callbacks} {
+test dcall-1.2 {deletion callbacks} testdcall {
testdcall
} {}
-test dcall-1.3 {deletion callbacks} {
+test dcall-1.3 {deletion callbacks} testdcall {
lsort -increasing [testdcall 20 21 22 -22]
} {20 21}
-test dcall-1.4 {deletion callbacks} {
+test dcall-1.4 {deletion callbacks} testdcall {
lsort -increasing [testdcall 20 21 22 -20]
} {21 22}
-test dcall-1.5 {deletion callbacks} {
+test dcall-1.5 {deletion callbacks} testdcall {
lsort -increasing [testdcall 20 21 22 -21]
} {20 22}
-test dcall-1.6 {deletion callbacks} {
+test dcall-1.6 {deletion callbacks} testdcall {
lsort -increasing [testdcall 20 21 22 -21 -22 -20]
} {}
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/dict.test b/tests/dict.test
new file mode 100644
index 0000000..cfaf36d
--- /dev/null
+++ b/tests/dict.test
@@ -0,0 +1,1205 @@
+# This test file covers the dictionary object type and the dict
+# command used to work with values of that type.
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands. Sourcing this file into Tcl runs the tests and
+# generates output for errors. No output means no errors were found.
+#
+# Copyright (c) 2003 Donal K. Fellows
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+if {[lsearch [namespace children] ::tcltest] == -1} {
+ package require tcltest 2
+ namespace import -force ::tcltest::*
+}
+
+# Used for constraining memory leak tests
+testConstraint memory [llength [info commands memory]]
+if {[testConstraint memory]} {
+ proc memtest script {
+ set end [lindex [split [memory info] \n] 3 3]
+ for {set i 0} {$i < 5} {incr i} {
+ uplevel 1 $script
+ set tmp $end
+ set end [lindex [split [memory info] \n] 3 3]
+ }
+ expr {$end - $tmp}
+ }
+}
+
+# Procedure to help check the contents of a dictionary. Note that we
+# can't just compare the string version because the order of the
+# elements is (deliberately) not defined. This is because it is
+# dependent on the underlying hash table implementation and also
+# potentially on the history of the value itself. Net result: you
+# cannot safely assume anything about the ordering of values.
+proc getOrder {dictVal args} {
+ foreach key $args {
+ lappend result $key [dict get $dictVal $key]
+ }
+ lappend result [dict size $dictVal]
+ return $result
+}
+
+test dict-1.1 {dict command basic syntax} {
+ list [catch {dict} msg] $msg
+} {1 {wrong # args: should be "dict subcommand ?argument ...?"}}
+test dict-1.2 {dict command basic syntax} {
+ list [catch {dict ?} msg] $msg
+} {1 {unknown or ambiguous subcommand "?": must be append, create, exists, filter, for, get, incr, info, keys, lappend, merge, remove, replace, set, size, unset, update, values, or with}}
+
+test dict-2.1 {dict create command} {
+ dict create
+} {}
+test dict-2.2 {dict create command} {
+ dict create a b
+} {a b}
+test dict-2.3 {dict create command} {
+ set result {}
+ set dict [dict create a b c d]
+ # Can't compare directly as ordering of values is undefined
+ foreach key {a c} {
+ set idx [lsearch -exact $dict $key]
+ if {$idx & 1} {
+ error "found $key at odd index $idx in $dict"
+ }
+ lappend result [lindex $dict [expr {$idx+1}]]
+ }
+ set result
+} {b d}
+test dict-2.4 {dict create command} {
+ list [catch {dict create a} msg] $msg
+} {1 {wrong # args: should be "dict create ?key value ...?"}}
+test dict-2.5 {dict create command} {
+ list [catch {dict create a b c} msg] $msg
+} {1 {wrong # args: should be "dict create ?key value ...?"}}
+test dict-2.6 {dict create command - initialse refcount field!} {
+ # Bug 715751 will show up in memory debuggers like purify
+ for {set i 0} {$i<10} {incr i} {
+ set dictv [dict create a 0]
+ set share [dict values $dictv]
+ list [dict incr dictv a]
+ }
+} {}
+test dict-2.7 {dict create command - #-quoting in string rep} {
+ dict create # #comment
+} {{#} #comment}
+test dict-2.8 {dict create command - #-quoting in string rep} -body {
+ dict create #a x #b x
+} -match glob -result {{#?} x #? x}
+
+test dict-3.1 {dict get command} {dict get {a b} a} b
+test dict-3.2 {dict get command} {dict get {a b c d} a} b
+test dict-3.3 {dict get command} {dict get {a b c d} c} d
+test dict-3.4 {dict get command} {
+ list [catch {dict get {a b c d} b} msg] $msg
+} {1 {key "b" not known in dictionary}}
+test dict-3.5 {dict get command} {dict get {a {p q r s} b {u v x y}} a p} q
+test dict-3.6 {dict get command} {dict get {a {p q r s} b {u v x y}} a r} s
+test dict-3.7 {dict get command} {dict get {a {p q r s} b {u v x y}} b u} v
+test dict-3.8 {dict get command} {dict get {a {p q r s} b {u v x y}} b x} y
+test dict-3.9 {dict get command} {
+ list [catch {dict get {a {p q r s} b {u v x y}} a z} msg] $msg
+} {1 {key "z" not known in dictionary}}
+test dict-3.10 {dict get command} {
+ list [catch {dict get {a {p q r s} b {u v x y}} c z} msg] $msg
+} {1 {key "c" not known in dictionary}}
+test dict-3.11 {dict get command} {dict get [dict create a b c d] a} b
+test dict-3.12 {dict get command} {
+ list [catch {dict get} msg] $msg
+} {1 {wrong # args: should be "dict get dictionary ?key key ...?"}}
+test dict-3.13 {dict get command} {
+ set dict [dict get {a b c d}]
+ if {$dict eq "a b c d"} {
+ subst OK
+ } elseif {$dict eq "c d a b"} {
+ subst OK
+ } else {
+ set dict
+ }
+} OK
+test dict-3.14 {dict get command} {
+ list [catch {dict get {a b c d} a c} msg] $msg
+} {1 {missing value to go with key}}
+test dict-3.15 {compiled dict get error cleanliness - Bug 2431847} -body {
+ apply {{} {
+ dict set a(z) b c
+ dict get $a(z) d
+ }}
+} -returnCodes error -result {key "d" not known in dictionary}
+test dict-3.16 {dict/list shimmering - Bug 3004007} {set l [list p 1 p 2 q 3];dict get $l q;set l} {p 1 p 2 q 3}
+test dict-3.17 {dict/list shimmering - Bug 3004007} {set l [list p 1 p 2 q 3];dict get $l q;llength $l} 6
+
+test dict-4.1 {dict replace command} {
+ getOrder [dict replace {a b c d}] a c
+} {a b c d 2}
+test dict-4.2 {dict replace command} {
+ getOrder [dict replace {a b c d} e f] a c e
+} {a b c d e f 3}
+test dict-4.3 {dict replace command} {
+ getOrder [dict replace {a b c d} c f] a c
+} {a b c f 2}
+test dict-4.4 {dict replace command} {
+ getOrder [dict replace {a b c d} c x a y] a c
+} {a y c x 2}
+test dict-4.5 {dict replace command} {
+ list [catch {dict replace} msg] $msg
+} {1 {wrong # args: should be "dict replace dictionary ?key value ...?"}}
+test dict-4.6 {dict replace command} {
+ list [catch {dict replace {a a} a} msg] $msg
+} {1 {wrong # args: should be "dict replace dictionary ?key value ...?"}}
+test dict-4.7 {dict replace command} {
+ list [catch {dict replace {a a a} a b} msg] $msg
+} {1 {missing value to go with key}}
+test dict-4.8 {dict replace command} {
+ list [catch {dict replace [list a a a] a b} msg] $msg
+} {1 {missing value to go with key}}
+test dict-4.9 {dict replace command} {dict replace [list a a] a b} {a b}
+test dict-4.10 {dict replace command} {dict replace [list a a] a b a c} {a c}
+
+test dict-5.1 {dict remove command} {dict remove {a b c d} a} {c d}
+test dict-5.2 {dict remove command} {dict remove {a b c d} c} {a b}
+test dict-5.3 {dict remove command} {dict remove {a b c d} a c} {}
+test dict-5.4 {dict remove command} {dict remove {a b c d} c a} {}
+test dict-5.5 {dict remove command} {
+ getOrder [dict remove {a b c d}] a c
+} {a b c d 2}
+test dict-5.6 {dict remove command} {dict remove {a b} c} {a b}
+test dict-5.7 {dict remove command} {
+ list [catch {dict remove} msg] $msg
+} {1 {wrong # args: should be "dict remove dictionary ?key ...?"}}
+
+test dict-6.1 {dict keys command} {dict keys {a b}} a
+test dict-6.2 {dict keys command} {dict keys {c d}} c
+test dict-6.3 {dict keys command} {lsort [dict keys {a b c d}]} {a c}
+test dict-6.4 {dict keys command} {dict keys {a b c d} a} a
+test dict-6.5 {dict keys command} {dict keys {a b c d} c} c
+test dict-6.6 {dict keys command} {dict keys {a b c d} e} {}
+test dict-6.7 {dict keys command} {lsort [dict keys {a b c d ca da} c*]} {c ca}
+test dict-6.8 {dict keys command} {
+ list [catch {dict keys} msg] $msg
+} {1 {wrong # args: should be "dict keys dictionary ?pattern?"}}
+test dict-6.9 {dict keys command} {
+ list [catch {dict keys {} a b} msg] $msg
+} {1 {wrong # args: should be "dict keys dictionary ?pattern?"}}
+test dict-6.10 {dict keys command} {
+ list [catch {dict keys a} msg] $msg
+} {1 {missing value to go with key}}
+
+test dict-7.1 {dict values command} {dict values {a b}} b
+test dict-7.2 {dict values command} {dict values {c d}} d
+test dict-7.3 {dict values command} {lsort [dict values {a b c d}]} {b d}
+test dict-7.4 {dict values command} {dict values {a b c d} b} b
+test dict-7.5 {dict values command} {dict values {a b c d} d} d
+test dict-7.6 {dict values command} {dict values {a b c d} e} {}
+test dict-7.7 {dict values command} {lsort [dict values {a b c d ca da} d*]} {d da}
+test dict-7.8 {dict values command} {
+ list [catch {dict values} msg] $msg
+} {1 {wrong # args: should be "dict values dictionary ?pattern?"}}
+test dict-7.9 {dict values command} {
+ list [catch {dict values {} a b} msg] $msg
+} {1 {wrong # args: should be "dict values dictionary ?pattern?"}}
+test dict-7.10 {dict values command} {
+ list [catch {dict values a} msg] $msg
+} {1 {missing value to go with key}}
+
+test dict-8.1 {dict size command} {dict size {}} 0
+test dict-8.2 {dict size command} {dict size {a b}} 1
+test dict-8.3 {dict size command} {dict size {a b c d}} 2
+test dict-8.4 {dict size command} {
+ list [catch {dict size} msg] $msg
+} {1 {wrong # args: should be "dict size dictionary"}}
+test dict-8.5 {dict size command} {
+ list [catch {dict size a b} msg] $msg
+} {1 {wrong # args: should be "dict size dictionary"}}
+test dict-8.6 {dict size command} {
+ list [catch {dict size a} msg] $msg
+} {1 {missing value to go with key}}
+
+test dict-9.1 {dict exists command} {dict exists {a b} a} 1
+test dict-9.2 {dict exists command} {dict exists {a b} b} 0
+test dict-9.3 {dict exists command} {dict exists {a {b c}} a b} 1
+test dict-9.4 {dict exists command} {dict exists {a {b c}} a c} 0
+test dict-9.5 {dict exists command} {dict exists {a {b c}} b c} 0
+test dict-9.6 {dict exists command} {
+ list [catch {dict exists {a {b c d}} a c} msg] $msg
+} {1 {missing value to go with key}}
+test dict-9.7 {dict exists command} {
+ list [catch {dict exists} msg] $msg
+} {1 {wrong # args: should be "dict exists dictionary key ?key ...?"}}
+test dict-9.8 {dict exists command} {
+ list [catch {dict exists {}} msg] $msg
+} {1 {wrong # args: should be "dict exists dictionary key ?key ...?"}}
+
+test dict-10.1 {dict info command} {
+ # Actual string returned by this command is undefined; it is
+ # intended for human consumption and not for use by scripts.
+ dict info {}
+ subst {}
+} {}
+test dict-10.2 {dict info command} {
+ list [catch {dict info} msg] $msg
+} {1 {wrong # args: should be "dict info dictionary"}}
+test dict-10.3 {dict info command} {
+ list [catch {dict info {} x} msg] $msg
+} {1 {wrong # args: should be "dict info dictionary"}}
+test dict-10.4 {dict info command} {
+ list [catch {dict info x} msg] $msg
+} {1 {missing value to go with key}}
+
+test dict-11.1 {dict incr command: unshared value} {
+ set dictv [dict create \
+ a [string index "=0=" 1] \
+ b [expr {1+2}] \
+ c [expr {wide(0x80000000)+1}]]
+ getOrder [dict incr dictv a] a b c
+} {a 1 b 3 c 2147483649 3}
+test dict-11.2 {dict incr command: unshared value} {
+ set dictv [dict create \
+ a [string index "=0=" 1] \
+ b [expr {1+2}] \
+ c [expr {wide(0x80000000)+1}]]
+ getOrder [dict incr dictv b] a b c
+} {a 0 b 4 c 2147483649 3}
+test dict-11.3 {dict incr command: unshared value} {
+ set dictv [dict create \
+ a [string index "=0=" 1] \
+ b [expr {1+2}] \
+ c [expr {wide(0x80000000)+1}]]
+ getOrder [dict incr dictv c] a b c
+} {a 0 b 3 c 2147483650 3}
+test dict-11.4 {dict incr command: shared value} {
+ set dictv [dict create a 0 b [expr {1+2}] c [expr {wide(0x80000000)+1}]]
+ set sharing [dict values $dictv]
+ getOrder [dict incr dictv a] a b c
+} {a 1 b 3 c 2147483649 3}
+test dict-11.5 {dict incr command: shared value} {
+ set dictv [dict create a 0 b [expr {1+2}] c [expr {wide(0x80000000)+1}]]
+ set sharing [dict values $dictv]
+ getOrder [dict incr dictv b] a b c
+} {a 0 b 4 c 2147483649 3}
+test dict-11.6 {dict incr command: shared value} {
+ set dictv [dict create a 0 b [expr {1+2}] c [expr {wide(0x80000000)+1}]]
+ set sharing [dict values $dictv]
+ getOrder [dict incr dictv c] a b c
+} {a 0 b 3 c 2147483650 3}
+test dict-11.7 {dict incr command: unknown values} {
+ set dictv [dict create a 0 b [expr {1+2}] c [expr {wide(0x80000000)+1}]]
+ getOrder [dict incr dictv d] a b c d
+} {a 0 b 3 c 2147483649 d 1 4}
+test dict-11.8 {dict incr command} {
+ set dictv {a 1}
+ dict incr dictv a 2
+} {a 3}
+test dict-11.9 {dict incr command} {
+ set dictv {a dummy}
+ list [catch {dict incr dictv a} msg] $msg
+} {1 {expected integer but got "dummy"}}
+test dict-11.10 {dict incr command} {
+ set dictv {a 1}
+ list [catch {dict incr dictv a dummy} msg] $msg
+} {1 {expected integer but got "dummy"}}
+test dict-11.11 {dict incr command} {
+ catch {unset dictv}
+ dict incr dictv a
+} {a 1}
+test dict-11.12 {dict incr command} {
+ set dictv a
+ list [catch {dict incr dictv a} msg] $msg
+} {1 {missing value to go with key}}
+test dict-11.13 {dict incr command} {
+ set dictv a
+ list [catch {dict incr dictv a a a} msg] $msg
+} {1 {wrong # args: should be "dict incr varName key ?increment?"}}
+test dict-11.14 {dict incr command} {
+ set dictv a
+ list [catch {dict incr dictv} msg] $msg
+} {1 {wrong # args: should be "dict incr varName key ?increment?"}}
+test dict-11.15 {dict incr command: write failure} {
+ catch {unset dictVar}
+ set dictVar(block) {}
+ set result [list [catch {dict incr dictVar a} msg] $msg]
+ catch {unset dictVar}
+ set result
+} {1 {can't set "dictVar": variable is array}}
+test dict-11.16 {dict incr command: compilation} {
+ proc dicttest {} {
+ set v {a 0 b 0 c 0}
+ dict incr v a
+ dict incr v b 1
+ dict incr v c 2
+ dict incr v d 3
+ list [dict get $v a] [dict get $v b] [dict get $v c] [dict get $v d]
+ }
+ dicttest
+} {1 1 2 3}
+test dict-11.17 {dict incr command: compilation} {
+ proc dicttest {} {
+ set dictv {a 1}
+ dict incr dictv a 2
+ }
+ dicttest
+} {a 3}
+
+test dict-12.1 {dict lappend command} {
+ set dictv {a a}
+ dict lappend dictv a
+} {a a}
+test dict-12.2 {dict lappend command} {
+ set dictv {a a}
+ set sharing [dict values $dictv]
+ dict lappend dictv a b
+} {a {a b}}
+test dict-12.3 {dict lappend command} {
+ set dictv {a a}
+ dict lappend dictv a b c
+} {a {a b c}}
+test dict-12.2.1 {dict lappend command} {
+ set dictv [dict create a [string index =a= 1]]
+ dict lappend dictv a b
+} {a {a b}}
+test dict-12.4 {dict lappend command} {
+ set dictv {}
+ dict lappend dictv a x y z
+} {a {x y z}}
+test dict-12.5 {dict lappend command} {
+ catch {unset dictv}
+ dict lappend dictv a b
+} {a b}
+test dict-12.6 {dict lappend command} {
+ set dictv a
+ list [catch {dict lappend dictv a a} msg] $msg
+} {1 {missing value to go with key}}
+test dict-12.7 {dict lappend command} {
+ list [catch {dict lappend} msg] $msg
+} {1 {wrong # args: should be "dict lappend varName key ?value ...?"}}
+test dict-12.8 {dict lappend command} {
+ list [catch {dict lappend dictv} msg] $msg
+} {1 {wrong # args: should be "dict lappend varName key ?value ...?"}}
+test dict-12.9 {dict lappend command} {
+ set dictv [dict create a "\{"]
+ list [catch {dict lappend dictv a a} msg] $msg
+} {1 {unmatched open brace in list}}
+test dict-12.10 {dict lappend command: write failure} {
+ catch {unset dictVar}
+ set dictVar(block) {}
+ set result [list [catch {dict lappend dictVar a x} msg] $msg]
+ catch {unset dictVar}
+ set result
+} {1 {can't set "dictVar": variable is array}}
+
+test dict-13.1 {dict append command} {
+ set dictv {a a}
+ dict append dictv a
+} {a a}
+test dict-13.2 {dict append command} {
+ set dictv {a a}
+ set sharing [dict values $dictv]
+ dict append dictv a b
+} {a ab}
+test dict-13.3 {dict append command} {
+ set dictv {a a}
+ dict append dictv a b c
+} {a abc}
+test dict-13.2.1 {dict append command} {
+ set dictv [dict create a [string index =a= 1]]
+ dict append dictv a b
+} {a ab}
+test dict-13.4 {dict append command} {
+ set dictv {}
+ dict append dictv a x y z
+} {a xyz}
+test dict-13.5 {dict append command} {
+ catch {unset dictv}
+ dict append dictv a b
+} {a b}
+test dict-13.6 {dict append command} {
+ set dictv a
+ list [catch {dict append dictv a a} msg] $msg
+} {1 {missing value to go with key}}
+test dict-13.7 {dict append command} {
+ list [catch {dict append} msg] $msg
+} {1 {wrong # args: should be "dict append varName key ?value ...?"}}
+test dict-13.8 {dict append command} {
+ list [catch {dict append dictv} msg] $msg
+} {1 {wrong # args: should be "dict append varName key ?value ...?"}}
+test dict-13.9 {dict append command: write failure} {
+ catch {unset dictVar}
+ set dictVar(block) {}
+ set result [list [catch {dict append dictVar a x} msg] $msg]
+ catch {unset dictVar}
+ set result
+} {1 {can't set "dictVar": variable is array}}
+test dict-13.10 {compiled dict command: crash case} {
+ apply {{} {dict append dictVar a o k}}
+} {a ok}
+
+test dict-14.1 {dict for command: syntax} {
+ list [catch {dict for} msg] $msg
+} {1 {wrong # args: should be "dict for {keyVar valueVar} dictionary script"}}
+test dict-14.2 {dict for command: syntax} {
+ list [catch {dict for x} msg] $msg
+} {1 {wrong # args: should be "dict for {keyVar valueVar} dictionary script"}}
+test dict-14.3 {dict for command: syntax} {
+ list [catch {dict for x x} msg] $msg
+} {1 {wrong # args: should be "dict for {keyVar valueVar} dictionary script"}}
+test dict-14.4 {dict for command: syntax} {
+ list [catch {dict for x x x x} msg] $msg
+} {1 {wrong # args: should be "dict for {keyVar valueVar} dictionary script"}}
+test dict-14.5 {dict for command: syntax} {
+ list [catch {dict for x x x} msg] $msg
+} {1 {must have exactly two variable names}}
+test dict-14.6 {dict for command: syntax} {
+ list [catch {dict for {x x x} x x} msg] $msg
+} {1 {must have exactly two variable names}}
+test dict-14.7 {dict for command: syntax} {
+ list [catch {dict for "\{x" x x} msg] $msg
+} {1 {unmatched open brace in list}}
+test dict-14.8 {dict for command} {
+ # This test confirms that [dict keys], [dict values] and [dict for]
+ # all traverse a dictionary in the same order.
+ set dictv {a A b B c C}
+ set keys {}
+ set values {}
+ dict for {k v} $dictv {
+ lappend keys $k
+ lappend values $v
+ }
+ set result [expr {
+ $keys eq [dict keys $dictv] && $values eq [dict values $dictv]
+ }]
+ expr {$result ? "YES" : [list "NO" $dictv $keys $values]}
+} YES
+test dict-14.9 {dict for command} {
+ dict for {k v} {} {
+ error "unexpected execution of 'dict for' body"
+ }
+} {}
+test dict-14.10 {dict for command: script results} {
+ set times 0
+ dict for {k v} {a a b b} {
+ incr times
+ continue
+ error "shouldn't get here"
+ }
+ set times
+} 2
+test dict-14.11 {dict for command: script results} {
+ set times 0
+ dict for {k v} {a a b b} {
+ incr times
+ break
+ error "shouldn't get here"
+ }
+ set times
+} 1
+test dict-14.12 {dict for command: script results} {
+ set times 0
+ list [catch {
+ dict for {k v} {a a b b} {
+ incr times
+ error test
+ }
+ } msg] $msg $times $::errorInfo
+} {1 test 1 {test
+ while executing
+"error test"
+ ("dict for" body line 3)
+ invoked from within
+"dict for {k v} {a a b b} {
+ incr times
+ error test
+ }"}}
+test dict-14.13 {dict for command: script results} {
+ proc dicttest {} {
+ rename dicttest {}
+ dict for {k v} {a b} {
+ return ok,$k,$v
+ error "skipped return completely"
+ }
+ error "return didn't go far enough"
+ }
+ dicttest
+} ok,a,b
+test dict-14.14 {dict for command: handle representation loss} {
+ set dictVar {a b c d e f g h}
+ set keys {}
+ set values {}
+ dict for {k v} $dictVar {
+ if {[llength $dictVar]} {
+ lappend keys $k
+ lappend values $v
+ }
+ }
+ list [lsort $keys] [lsort $values]
+} {{a c e g} {b d f h}}
+test dict-14.15 {dict for command: keys are unique and iterated over once only} {
+ set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
+ catch {unset accum}
+ array set accum {}
+ dict for {k v} $dictVar {
+ append accum($k) $v,
+ }
+ set result [lsort [array names accum]]
+ lappend result :
+ foreach k $result {
+ catch {lappend result $accum($k)}
+ }
+ catch {unset accum}
+ set result
+} {a1 a2 b1 b2 bar foo : a, b, c, d, foo, bar,}
+test dict-14.16 {dict for command in compilation context} {
+ proc dicttest {} {
+ set res {x x x x x x}
+ dict for {k v} {a 0 b 1 c 2 d 3 e 4 f 5} {
+ lset res $v $k
+ continue
+ }
+ return $res
+ }
+ dicttest
+} {a b c d e f}
+test dict-14.17 {dict for command in compilation context} {
+ # Bug 1379349
+ proc dicttest {} {
+ set d [dict create a 1] ;# Dict must be unshared!
+ dict for {k v} $d {
+ dict set d $k 0 ;# Any modification will do
+ }
+ return $d
+ }
+ dicttest
+} {a 0}
+test dict-14.18 {dict for command in compilation context} {
+ # Bug 1382528
+ proc dicttest {} {
+ dict for {k v} {} {} ;# Note empty dict
+ catch { error foo } ;# Note compiled [catch]
+ }
+ dicttest
+} 1
+test dict-14.19 {dict for and invalid dicts: bug 1531184} -body {
+ di[list]ct for {k v} x {}
+} -returnCodes 1 -result {missing value to go with key}
+test dict-14.20 {dict for stack space compilation: bug 1903325} {
+ proc dicttest {x y args} {
+ dict for {a b} $x {}
+ concat "c=$y,$args"
+ }
+ dicttest {} 1 2 3
+} {c=1,2 3}
+# There's probably a lot more tests to add here. Really ought to use a
+# coverage tool for this job...
+
+test dict-15.1 {dict set command} {
+ set dictVar {}
+ dict set dictVar a x
+} {a x}
+test dict-15.2 {dict set command} {
+ set dictvar {a {}}
+ dict set dictvar a b x
+} {a {b x}}
+test dict-15.3 {dict set command} {
+ set dictvar {a {b {}}}
+ dict set dictvar a b c x
+} {a {b {c x}}}
+test dict-15.4 {dict set command} {
+ set dictVar {a y}
+ dict set dictVar a x
+} {a x}
+test dict-15.5 {dict set command} {
+ set dictVar {a {b y}}
+ dict set dictVar a b x
+} {a {b x}}
+test dict-15.6 {dict set command} {
+ set dictVar {a {b {c y}}}
+ dict set dictVar a b c x
+} {a {b {c x}}}
+test dict-15.7 {dict set command: path creation} {
+ set dictVar {}
+ dict set dictVar a b x
+} {a {b x}}
+test dict-15.8 {dict set command: creates variables} {
+ catch {unset dictVar}
+ dict set dictVar a x
+ set dictVar
+} {a x}
+test dict-15.9 {dict set command: write failure} {
+ catch {unset dictVar}
+ set dictVar(block) {}
+ set result [list [catch {dict set dictVar a x} msg] $msg]
+ catch {unset dictVar}
+ set result
+} {1 {can't set "dictVar": variable is array}}
+test dict-15.10 {dict set command: syntax} {
+ list [catch {dict set} msg] $msg
+} {1 {wrong # args: should be "dict set varName key ?key ...? value"}}
+test dict-15.11 {dict set command: syntax} {
+ list [catch {dict set a} msg] $msg
+} {1 {wrong # args: should be "dict set varName key ?key ...? value"}}
+test dict-15.12 {dict set command: syntax} {
+ list [catch {dict set a a} msg] $msg
+} {1 {wrong # args: should be "dict set varName key ?key ...? value"}}
+test dict-15.13 {dict set command} {
+ set dictVar a
+ list [catch {dict set dictVar b c} msg] $msg
+} {1 {missing value to go with key}}
+
+test dict-16.1 {dict unset command} {
+ set dictVar {a b c d}
+ dict unset dictVar a
+} {c d}
+test dict-16.2 {dict unset command} {
+ set dictVar {a b c d}
+ dict unset dictVar c
+} {a b}
+test dict-16.3 {dict unset command} {
+ set dictVar {a b}
+ dict unset dictVar c
+} {a b}
+test dict-16.4 {dict unset command} {
+ set dictVar {a {b c d e}}
+ dict unset dictVar a b
+} {a {d e}}
+test dict-16.5 {dict unset command} {
+ set dictVar a
+ list [catch {dict unset dictVar a} msg] $msg
+} {1 {missing value to go with key}}
+test dict-16.6 {dict unset command} {
+ set dictVar {a b}
+ list [catch {dict unset dictVar c d} msg] $msg
+} {1 {key "c" not known in dictionary}}
+test dict-16.7 {dict unset command} {
+ catch {unset dictVar}
+ list [info exists dictVar] [dict unset dictVar a] [info exists dictVar]
+} {0 {} 1}
+test dict-16.8 {dict unset command} {
+ list [catch {dict unset dictVar} msg] $msg
+} {1 {wrong # args: should be "dict unset varName key ?key ...?"}}
+test dict-16.9 {dict unset command: write failure} {
+ catch {unset dictVar}
+ set dictVar(block) {}
+ set result [list [catch {dict unset dictVar a} msg] $msg]
+ catch {unset dictVar}
+ set result
+} {1 {can't set "dictVar": variable is array}}
+
+test dict-17.1 {dict filter command: key} {
+ set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
+ dict filter $dictVar key a2
+} {a2 b}
+test dict-17.2 {dict filter command: key} {
+ set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
+ dict size [dict filter $dictVar key *]
+} 6
+test dict-17.3 {dict filter command: key} {
+ set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
+ getOrder [dict filter $dictVar key ???] bar foo
+} {bar foo foo bar 2}
+test dict-17.4 {dict filter command: key} {
+ list [catch {dict filter {} key} msg] $msg
+} {1 {wrong # args: should be "dict filter dictionary key globPattern"}}
+test dict-17.5 {dict filter command: key} {
+ list [catch {dict filter {} key a a} msg] $msg
+} {1 {wrong # args: should be "dict filter dictionary key globPattern"}}
+test dict-17.6 {dict filter command: value} {
+ set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
+ dict filter $dictVar value c
+} {b1 c}
+test dict-17.7 {dict filter command: value} {
+ set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
+ dict size [dict filter $dictVar value *]
+} 6
+test dict-17.8 {dict filter command: value} {
+ set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
+ getOrder [dict filter $dictVar value ???] bar foo
+} {bar foo foo bar 2}
+test dict-17.9 {dict filter command: value} {
+ list [catch {dict filter {} value} msg] $msg
+} {1 {wrong # args: should be "dict filter dictionary value globPattern"}}
+test dict-17.10 {dict filter command: value} {
+ list [catch {dict filter {} value a a} msg] $msg
+} {1 {wrong # args: should be "dict filter dictionary value globPattern"}}
+test dict-17.11 {dict filter command: script} {
+ set dictVar {a1 a a2 b b1 c b2 d foo bar bar foo}
+ set n 0
+ list [getOrder [dict filter $dictVar script {k v} {
+ incr n
+ expr {[string length $k] == [string length $v]}
+ }] bar foo] $n
+} {{bar foo foo bar 2} 6}
+test dict-17.12 {dict filter command: script} {
+ list [catch {dict filter {a b} script {k v} {concat $k $v}} msg] $msg
+} {1 {expected boolean value but got "a b"}}
+test dict-17.13 {dict filter command: script} {
+ list [catch {dict filter {a b} script {k v} {error x}} msg] $msg \
+ $::errorInfo
+} {1 x {x
+ while executing
+"error x"
+ ("dict filter" script line 1)
+ invoked from within
+"dict filter {a b} script {k v} {error x}"}}
+test dict-17.14 {dict filter command: script} {
+ set n 0
+ list [dict filter {a b c d} script {k v} {
+ incr n
+ break
+ error boom!
+ }] $n
+} {{} 1}
+test dict-17.15 {dict filter command: script} {
+ set n 0
+ list [dict filter {a b c d} script {k v} {
+ incr n
+ continue
+ error boom!
+ }] $n
+} {{} 2}
+test dict-17.16 {dict filter command: script} {
+ proc dicttest {} {
+ rename dicttest {}
+ dict filter {a b} script {k v} {
+ return ok,$k,$v
+ error "skipped return completely"
+ }
+ error "return didn't go far enough"
+ }
+ dicttest
+} ok,a,b
+test dict-17.17 {dict filter command: script} {
+ dict filter {a b} script {k k} {continue}
+ set k
+} b
+test dict-17.18 {dict filter command: script} {
+ list [catch {dict filter {a b} script {k k}} msg] $msg
+} {1 {wrong # args: should be "dict filter dictionary script {keyVar valueVar} filterScript"}}
+test dict-17.19 {dict filter command: script} {
+ list [catch {dict filter {a b} script k {continue}} msg] $msg
+} {1 {must have exactly two variable names}}
+test dict-17.20 {dict filter command: script} {
+ list [catch {dict filter {a b} script "\{k v" {continue}} msg] $msg
+} {1 {unmatched open brace in list}}
+test dict-17.21 {dict filter command} {
+ list [catch {dict filter {a b}} msg] $msg
+} {1 {wrong # args: should be "dict filter dictionary filterType ..."}}
+test dict-17.22 {dict filter command} {
+ list [catch {dict filter {a b} JUNK} msg] $msg
+} {1 {bad filterType "JUNK": must be key, script, or value}}
+test dict-17.23 {dict filter command} {
+ list [catch {dict filter a key *} msg] $msg
+} {1 {missing value to go with key}}
+
+test dict-18.1 {dict-list relationship} {
+ -body {
+ # Test that any internal conversion between list and dict
+ # does not change the object
+ set l [list 1 2 3 4 5 6 7 8 9 0 q w e r t y]
+ dict values $l
+ set l
+ }
+ -result {1 2 3 4 5 6 7 8 9 0 q w e r t y}
+}
+test dict-18.2 {dict-list relationship} {
+ -body {
+ # Test that the dictionary is a valid list
+ set d [dict create "abc def" 0 "a\{b" 1 "c\}d" 2]
+ for {set t 0} {$t < 5} {incr t} {
+ llength $d
+ dict lappend d "abc def" "\}\{"
+ dict append d "a\{b" "\}"
+ dict incr d "c\}d" 1
+ }
+ llength $d
+ }
+ -result 6
+}
+
+# This is a test for a specific bug.
+# It shows a bad ref counter when running with memdebug on.
+test dict-19.1 {memory bug} -setup {
+ proc xxx {} {
+ set successors [dict create x {c d}]
+ dict set successors x a b
+ dict get $successors x
+ }
+} -body {
+ xxx
+} -cleanup {
+ rename xxx {}
+} -result [dict create c d a b]
+test dict-19.2 {dict: testing for leaks} -setup {
+ # This test is made to stress object reference management
+ proc stress {} {
+ # A shared invalid dictinary
+ set apa {a {}b c d}
+ set bepa $apa
+ catch {dict replace $apa e f}
+ catch {dict remove $apa c d}
+ catch {dict incr apa a 5}
+ catch {dict lappend apa a 5}
+ catch {dict append apa a 5}
+ catch {dict set apa a 5}
+ catch {dict unset apa a}
+
+ # A shared valid dictionary, invalid incr
+ set apa {a b c d}
+ set bepa $apa
+ catch {dict incr bepa a 5}
+
+ # An error during write to an unshared object, incr
+ set apa {a 1 b 2}
+ set bepa [lrange $apa 0 end]
+ trace add variable bepa write {error hej}
+ catch {dict incr bepa a 5}
+ trace remove variable bepa write {error hej}
+ unset bepa
+
+ # An error during write to a shared object, incr
+ set apa {a 1 b 2}
+ set bepa $apa
+ trace add variable bepa write {error hej}
+ catch {dict incr bepa a 5}
+ trace remove variable bepa write {error hej}
+ unset bepa
+
+ # A shared valid dictionary, invalid lappend
+ set apa [list a {{}b} c d]
+ set bepa $apa
+ catch {dict lappend bepa a 5}
+
+ # An error during write to an unshared object, lappend
+ set apa {a 1 b 2}
+ set bepa [lrange $apa 0 end]
+ trace add variable bepa write {error hej}
+ catch {dict lappend bepa a 5}
+ trace remove variable bepa write {error hej}
+ unset bepa
+
+ # An error during write to a shared object, lappend
+ set apa {a 1 b 2}
+ set bepa $apa
+ trace add variable bepa write {error hej}
+ catch {dict lappend bepa a 5}
+ trace remove variable bepa write {error hej}
+ unset bepa
+
+ # An error during write to an unshared object, append
+ set apa {a 1 b 2}
+ set bepa [lrange $apa 0 end]
+ trace add variable bepa write {error hej}
+ catch {dict append bepa a 5}
+ trace remove variable bepa write {error hej}
+ unset bepa
+
+ # An error during write to a shared object, append
+ set apa {a 1 b 2}
+ set bepa $apa
+ trace add variable bepa write {error hej}
+ catch {dict append bepa a 5}
+ trace remove variable bepa write {error hej}
+ unset bepa
+
+ # An error during write to an unshared object, set
+ set apa {a 1 b 2}
+ set bepa [lrange $apa 0 end]
+ trace add variable bepa write {error hej}
+ catch {dict set bepa a 5}
+ trace remove variable bepa write {error hej}
+ unset bepa
+
+ # An error during write to a shared object, set
+ set apa {a 1 b 2}
+ set bepa $apa
+ trace add variable bepa write {error hej}
+ catch {dict set bepa a 5}
+ trace remove variable bepa write {error hej}
+ unset bepa
+
+ # An error during write to an unshared object, unset
+ set apa {a 1 b 2}
+ set bepa [lrange $apa 0 end]
+ trace add variable bepa write {error hej}
+ catch {dict unset bepa a}
+ trace remove variable bepa write {error hej}
+ unset bepa
+
+ # An error during write to a shared object, unset
+ set apa {a 1 b 2}
+ set bepa $apa
+ trace add variable bepa write {error hej}
+ catch {dict unset bepa a}
+ trace remove variable bepa write {error hej}
+ unset bepa
+ }
+} -constraints memory -body {
+ memtest {
+ stress
+ }
+} -cleanup {
+ rename stress {}
+} -result 0
+test dict-19.3 {testing for leaks - Bug 2874678} -constraints memory -body {
+ set d aDictVar; # Force interpreted [dict incr]
+ memtest {
+ dict incr $d aKey 0
+ unset $d
+ }
+} -cleanup {
+ unset d
+} -result 0
+
+test dict-20.1 {dict merge command} {
+ dict merge
+} {}
+test dict-20.2 {dict merge command} {
+ getOrder [dict merge {a b c d e f}] a c e
+} {a b c d e f 3}
+test dict-20.3 {dict merge command} -body {
+ dict merge {a b c d e}
+} -result {missing value to go with key} -returnCodes 1
+test dict-20.4 {dict merge command} {
+ getOrder [dict merge {a b c d} {e f g h}] a c e g
+} {a b c d e f g h 4}
+test dict-20.5 {dict merge command} -body {
+ dict merge {a b c d e} {e f g h}
+} -result {missing value to go with key} -returnCodes 1
+test dict-20.6 {dict merge command} -body {
+ dict merge {a b c d} {e f g h i}
+} -result {missing value to go with key} -returnCodes 1
+test dict-20.7 {dict merge command} {
+ getOrder [dict merge {a b c d e f} {e x g h}] a c e g
+} {a b c d e x g h 4}
+test dict-20.8 {dict merge command} {
+ getOrder [dict merge {a b c d} {a x c y}] a c
+} {a x c y 2}
+test dict-20.9 {dict merge command} {
+ getOrder [dict merge {a b c d} {a x c y}] a c
+} {a x c y 2}
+test dict-20.10 {dict merge command} {
+ getOrder [dict merge {a b c d e f} {a x 1 2 3 4} {a - 1 -}] a c e 1 3
+} {a - c d e f 1 - 3 4 5}
+
+test dict-21.1 {dict update command} -body {
+ dict update
+} -returnCodes 1 -result {wrong # args: should be "dict update varName key varName ?key varName ...? script"}
+test dict-21.2 {dict update command} -body {
+ dict update v
+} -returnCodes 1 -result {wrong # args: should be "dict update varName key varName ?key varName ...? script"}
+test dict-21.3 {dict update command} -body {
+ dict update v k
+} -returnCodes 1 -result {wrong # args: should be "dict update varName key varName ?key varName ...? script"}
+test dict-21.4 {dict update command} -body {
+ dict update v k v
+} -returnCodes 1 -result {wrong # args: should be "dict update varName key varName ?key varName ...? script"}
+test dict-21.5 {dict update command} {
+ set a {b c}
+ set result {}
+ set bb {}
+ dict update a b bb {
+ lappend result $a $bb
+ }
+ lappend result $a
+} {{b c} c {b c}}
+test dict-21.6 {dict update command} {
+ set a {b c}
+ set result {}
+ set bb {}
+ dict update a b bb {
+ lappend result $a $bb [set bb d]
+ }
+ lappend result $a
+} {{b c} c d {b d}}
+test dict-21.7 {dict update command} {
+ set a {b c}
+ set result {}
+ set bb {}
+ dict update a b bb {
+ lappend result $a $bb [unset bb]
+ }
+ lappend result $a
+} {{b c} c {} {}}
+test dict-21.8 {dict update command} {
+ set a {b c d e}
+ dict update a b v1 d v2 {
+ lassign "$v1 $v2" v2 v1
+ }
+ getOrder $a b d
+} {b e d c 2}
+test dict-21.9 {dict update command} {
+ set a {b c d e}
+ dict update a b v1 d v2 {unset a}
+ info exist a
+} 0
+test dict-21.10 {dict update command} {
+ set a {b {c d}}
+ dict update a b v1 {
+ dict update v1 c v2 {
+ set v2 foo
+ }
+ }
+ set a
+} {b {c foo}}
+test dict-21.11 {dict update command} {
+ set a {b c d e}
+ dict update a b v1 d v2 {
+ dict set a f g
+ }
+ getOrder $a b d f
+} {b c d e f g 3}
+test dict-21.12 {dict update command} {
+ set a {b c d e}
+ dict update a b v1 d v2 f v3 {
+ set v3 g
+ }
+ getOrder $a b d f
+} {b c d e f g 3}
+test dict-21.13 {dict update command: compilation} {
+ proc dicttest {d} {
+ while 1 {
+ dict update d a alpha b beta {
+ set beta $alpha
+ unset alpha
+ break
+ }
+ }
+ return $d
+ }
+ getOrder [dicttest {a 1 c 2}] b c
+} {b 1 c 2 2}
+test dict-21.14 {dict update command: compilation} {
+ proc dicttest x {
+ set indices {2 3}
+ trace add variable aa write "string length \$indices ;#"
+ dict update x k aa l bb {}
+ }
+ dicttest {k 1 l 2}
+} {}
+test dict-21.15 {dict update command: compilation} {
+ proc dicttest x {
+ set indices {2 3}
+ trace add variable aa read "string length \$indices ;#"
+ dict update x k aa l bb {}
+ }
+ dicttest {k 1 l 2}
+} {}
+test dict-21.16 {dict update command: no recursive structures [Bug 1786481]} {
+ set foo {a {b {c {d {e 1}}}}}
+ dict update foo a t {
+ dict update t b t {
+ dict update t c t {
+ dict update t d t {
+ dict incr t e
+ }
+ }
+ }
+ }
+ string range [append foo OK] end-1 end
+} OK
+test dict-21.17 {dict update command: no recursive structures [Bug 1786481]} {
+ proc dicttest {} {
+ set foo {a {b {c {d {e 1}}}}}
+ dict update foo a t {
+ dict update t b t {
+ dict update t c t {
+ dict update t d t {
+ dict incr t e
+ }
+ }
+ }
+ }
+ }
+ dicttest
+ string range [append foo OK] end-1 end
+} OK
+
+test dict-22.1 {dict with command} -body {
+ dict with
+} -returnCodes 1 -result {wrong # args: should be "dict with dictVar ?key ...? script"}
+test dict-22.2 {dict with command} -body {
+ dict with v
+} -returnCodes 1 -result {wrong # args: should be "dict with dictVar ?key ...? script"}
+test dict-22.3 {dict with command} -body {
+ unset -nocomplain v
+ dict with v {error "in body"}
+} -returnCodes 1 -result {can't read "v": no such variable}
+test dict-22.4 {dict with command} {
+ set a {b c d e}
+ unset -nocomplain b d
+ set result [list [info exist b] [info exist d]]
+ dict with a {
+ lappend result [info exist b] [info exist d] $b $d
+ }
+ set result
+} {0 0 1 1 c e}
+test dict-22.5 {dict with command} {
+ set a {b c d e}
+ dict with a {
+ lassign "$b $d" d b
+ }
+ getOrder $a b d
+} {b e d c 2}
+test dict-22.6 {dict with command} {
+ set a {b c d e}
+ dict with a {
+ unset b
+ # This *won't* go into the dict...
+ set f g
+ }
+ set a
+} {d e}
+test dict-22.7 {dict with command} {
+ set a {b c d e}
+ dict with a {
+ dict unset a b
+ }
+ getOrder $a b d
+} {b c d e 2}
+test dict-22.8 {dict with command} {
+ set a [dict create b c]
+ dict with a {
+ set b $a
+ }
+ set a
+} {b {b c}}
+test dict-22.9 {dict with command} {
+ set a {b {c d}}
+ dict with a b {
+ set c $c$c
+ }
+ set a
+} {b {c dd}}
+test dict-22.10 {dict with command: result handling tricky case} {
+ set a {b {c d}}
+ foreach i {0 1} {
+ if {$i} break
+ dict with a b {
+ set a {}
+ # We're checking to see if we lose this break
+ break
+ }
+ }
+ list $i $a
+} {0 {}}
+test dict-22.11 {dict with command: no recursive structures [Bug 1786481]} {
+ set foo {t {t {t {inner 1}}}}
+ dict with foo {
+ dict with t {
+ dict with t {
+ dict with t {
+ incr inner
+ }
+ }
+ }
+ }
+ string range [append foo OK] end-1 end
+} OK
+
+# cleanup
+::tcltest::cleanupTests
+return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/dstring.test b/tests/dstring.test
index c1a0063..95321ec 100644
--- a/tests/dstring.test
+++ b/tests/dstring.test
@@ -16,26 +16,21 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-if {[info commands testdstring] == {}} {
- puts "This application hasn't been compiled with the \"testdstring\""
- puts "command, so I can't test Tcl_DStringAppend et al."
- ::tcltest::cleanupTests
- return
-}
+testConstraint testdstring [llength [info commands testdstring]]
-test dstring-1.1 {appending and retrieving} {
+test dstring-1.1 {appending and retrieving} testdstring {
testdstring free
testdstring append "abc" -1
list [testdstring get] [testdstring length]
} {abc 3}
-test dstring-1.2 {appending and retrieving} {
+test dstring-1.2 {appending and retrieving} testdstring {
testdstring free
testdstring append "abc" -1
testdstring append " xyzzy" 3
testdstring append " 12345" -1
list [testdstring get] [testdstring length]
} {{abc xy 12345} 12}
-test dstring-1.3 {appending and retrieving} {
+test dstring-1.3 {appending and retrieving} testdstring {
testdstring free
foreach l {a b c d e f g h i j k l m n o p} {
testdstring append $l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l\n -1
@@ -59,27 +54,27 @@ ooooooooooooooooooooo
ppppppppppppppppppppp
} 352}
-test dstring-2.1 {appending list elements} {
+test dstring-2.1 {appending list elements} testdstring {
testdstring free
testdstring element "abc"
testdstring element "d e f"
list [testdstring get] [testdstring length]
} {{abc {d e f}} 11}
-test dstring-2.2 {appending list elements} {
+test dstring-2.2 {appending list elements} testdstring {
testdstring free
testdstring element "x"
testdstring element "\{"
testdstring element "ab\}"
testdstring get
} {x \{ ab\}}
-test dstring-2.3 {appending list elements} {
+test dstring-2.3 {appending list elements} testdstring {
testdstring free
foreach l {a b c d e f g h i j k l m n o p} {
testdstring element $l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l
}
testdstring get
} {aaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbb ccccccccccccccccccccc ddddddddddddddddddddd eeeeeeeeeeeeeeeeeeeee fffffffffffffffffffff ggggggggggggggggggggg hhhhhhhhhhhhhhhhhhhhh iiiiiiiiiiiiiiiiiiiii jjjjjjjjjjjjjjjjjjjjj kkkkkkkkkkkkkkkkkkkkk lllllllllllllllllllll mmmmmmmmmmmmmmmmmmmmm nnnnnnnnnnnnnnnnnnnnn ooooooooooooooooooooo ppppppppppppppppppppp}
-test dstring-2.4 {appending list elements} {
+test dstring-2.4 {appending list elements} testdstring {
testdstring free
testdstring append "a\{" -1
testdstring element abc
@@ -87,32 +82,63 @@ test dstring-2.4 {appending list elements} {
testdstring element xyzzy
testdstring get
} "a{ abc {xyzzy"
-test dstring-2.5 {appending list elements} {
+test dstring-2.5 {appending list elements} testdstring {
testdstring free
testdstring append " \{" -1
testdstring element abc
testdstring get
} " {abc"
-test dstring-2.6 {appending list elements} {
+test dstring-2.6 {appending list elements} testdstring {
testdstring free
testdstring append " " -1
testdstring element abc
testdstring get
} { abc}
-test dstring-2.7 {appending list elements} {
+test dstring-2.7 {appending list elements} testdstring {
testdstring free
testdstring append "\\ " -1
testdstring element abc
testdstring get
} "\\ abc"
-test dstring-2.8 {appending list elements} {
+test dstring-2.8 {appending list elements} testdstring {
testdstring free
testdstring append "x " -1
testdstring element abc
testdstring get
} {x abc}
+test dstring-2.9 {appending list elements} testdstring {
+ testdstring free
+ testdstring element #
+ testdstring get
+} {{#}}
+test dstring-2.10 {appending list elements} testdstring {
+ testdstring free
+ testdstring append " " -1
+ testdstring element #
+ testdstring get
+} { {#}}
+test dstring-2.11 {appending list elements} testdstring {
+ testdstring free
+ testdstring append \t -1
+ testdstring element #
+ testdstring get
+} \t{#}
+test dstring-2.12 {appending list elements} testdstring {
+ testdstring free
+ testdstring append x -1
+ testdstring element #
+ testdstring get
+} {x #}
+test dstring-2.13 {appending list elements} testdstring {
+ # This test shows lack of sophistication in Tcl_DStringAppendElement's
+ # decision about whether #-quoting can be disabled.
+ testdstring free
+ testdstring append "x " -1
+ testdstring element #
+ testdstring get
+} {x {#}}
-test dstring-3.1 {nested sublists} {
+test dstring-3.1 {nested sublists} testdstring {
testdstring free
testdstring start
testdstring element foo
@@ -121,7 +147,7 @@ test dstring-3.1 {nested sublists} {
testdstring element another
testdstring get
} {{foo bar} another}
-test dstring-3.2 {nested sublists} {
+test dstring-3.2 {nested sublists} testdstring {
testdstring free
testdstring start
testdstring start
@@ -132,7 +158,7 @@ test dstring-3.2 {nested sublists} {
testdstring element ghi
testdstring get
} {{{abc def}} ghi}
-test dstring-3.3 {nested sublists} {
+test dstring-3.3 {nested sublists} testdstring {
testdstring free
testdstring start
testdstring start
@@ -146,7 +172,7 @@ test dstring-3.3 {nested sublists} {
testdstring element foo4
testdstring get
} {{{{foo foo2}} foo3} foo4}
-test dstring-3.4 {nested sublists} {
+test dstring-3.4 {nested sublists} testdstring {
testdstring free
testdstring element before
testdstring start
@@ -156,7 +182,7 @@ test dstring-3.4 {nested sublists} {
testdstring element last
testdstring get
} {before {during more} last}
-test dstring-3.5 {nested sublists} {
+test dstring-3.5 {nested sublists} testdstring {
testdstring free
testdstring element "\{"
testdstring start
@@ -165,26 +191,72 @@ test dstring-3.5 {nested sublists} {
testdstring end
testdstring get
} {\{ {first second}}
+test dstring-3.6 {appending list elements} testdstring {
+ testdstring free
+ testdstring append x -1
+ testdstring start
+ testdstring element #
+ testdstring end
+ testdstring get
+} {x {{#}}}
+test dstring-3.7 {appending list elements} testdstring {
+ testdstring free
+ testdstring append x -1
+ testdstring start
+ testdstring append " " -1
+ testdstring element #
+ testdstring end
+ testdstring get
+} {x { {#}}}
+test dstring-3.8 {appending list elements} testdstring {
+ testdstring free
+ testdstring append x -1
+ testdstring start
+ testdstring append \t -1
+ testdstring element #
+ testdstring end
+ testdstring get
+} "x {\t{#}}"
+test dstring-3.9 {appending list elements} testdstring {
+ testdstring free
+ testdstring append x -1
+ testdstring start
+ testdstring append x -1
+ testdstring element #
+ testdstring end
+ testdstring get
+} {x {x #}}
+test dstring-3.10 {appending list elements} testdstring {
+ # This test shows lack of sophistication in Tcl_DStringAppendElement's
+ # decision about whether #-quoting can be disabled.
+ testdstring free
+ testdstring append x -1
+ testdstring start
+ testdstring append "x " -1
+ testdstring element #
+ testdstring end
+ testdstring get
+} {x {x {#}}}
-test dstring-4.1 {truncation} {
+test dstring-4.1 {truncation} testdstring {
testdstring free
testdstring append "abcdefg" -1
testdstring trunc 3
list [testdstring get] [testdstring length]
} {abc 3}
-test dstring-4.2 {truncation} {
+test dstring-4.2 {truncation} testdstring {
testdstring free
testdstring append "xyzzy" -1
testdstring trunc 0
list [testdstring get] [testdstring length]
} {{} 0}
-test dstring-5.1 {copying to result} {
+test dstring-5.1 {copying to result} testdstring {
testdstring free
testdstring append xyz -1
testdstring result
} xyz
-test dstring-5.2 {copying to result} {
+test dstring-5.2 {copying to result} testdstring {
testdstring free
catch {unset a}
foreach l {a b c d e f g h i j k l m n o p} {
@@ -211,18 +283,18 @@ ooooooooooooooooooooo
ppppppppppppppppppppp
} abc}
-test dstring-6.1 {Tcl_DStringGetResult} {
+test dstring-6.1 {Tcl_DStringGetResult} testdstring {
testdstring free
list [testdstring gresult staticsmall] [testdstring get]
} {{} short}
-test dstring-6.2 {Tcl_DStringGetResult} {
+test dstring-6.2 {Tcl_DStringGetResult} testdstring {
testdstring free
foreach l {a b c d e f g h i j k l m n o p} {
testdstring append $l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l$l\n -1
}
list [testdstring gresult staticsmall] [testdstring get]
} {{} short}
-test dstring-6.3 {Tcl_DStringGetResult} {
+test dstring-6.3 {Tcl_DStringGetResult} testdstring {
set result {}
lappend result [testdstring gresult staticlarge]
testdstring append x 1
@@ -235,13 +307,13 @@ fifth0 fifth1 fifth2 fifth3 fifth4 fifth5 fifth6 fifth7 fifth8 fifth9
sixth0 sixth1 sixth2 sixth3 sixth4 sixth5 sixth6 sixth7 sixth8 sixth9
seventh0 seventh1 seventh2 seventh3 seventh4 seventh5 seventh6 seventh7 seventh8 seventh9
x}}
-test dstring-6.4 {Tcl_DStringGetResult} {
+test dstring-6.4 {Tcl_DStringGetResult} testdstring {
set result {}
lappend result [testdstring gresult free]
testdstring append y 1
lappend result [testdstring get]
} {{} {This is a malloc-ed stringy}}
-test dstring-6.5 {Tcl_DStringGetResult} {
+test dstring-6.5 {Tcl_DStringGetResult} testdstring {
set result {}
lappend result [testdstring gresult special]
testdstring append z 1
@@ -249,18 +321,8 @@ test dstring-6.5 {Tcl_DStringGetResult} {
} {{} {This is a specially-allocated stringz}}
# cleanup
-testdstring free
+if {[testConstraint testdstring]} {
+ testdstring free
+}
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/encoding.test b/tests/encoding.test
index c4fa51d..836f277 100644
--- a/tests/encoding.test
+++ b/tests/encoding.test
@@ -9,17 +9,25 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
package require tcltest 2
+
+namespace eval ::tcl::test::encoding {
+ variable x
+
namespace import -force ::tcltest::*
proc toutf {args} {
- global x
+ variable x
lappend x "toutf $args"
}
proc fromutf {args} {
- global x
+ variable x
lappend x "fromutf $args"
}
+proc runtests {} {
+
+ variable x
+
# Some tests require the testencoding command
testConstraint testencoding [llength [info commands testencoding]]
testConstraint exec [llength [info commands exec]]
@@ -28,7 +36,7 @@ testConstraint exec [llength [info commands exec]]
# TclFinalizeEncodingSubsystem is not currently tested
test encoding-1.1 {Tcl_GetEncoding: system encoding} {testencoding} {
- testencoding create foo toutf fromutf
+ testencoding create foo [namespace origin toutf] [namespace origin fromutf]
set old [encoding system]
encoding system foo
set x {}
@@ -38,7 +46,7 @@ test encoding-1.1 {Tcl_GetEncoding: system encoding} {testencoding} {
set x
} {{fromutf }}
test encoding-1.2 {Tcl_GetEncoding: existing encoding} {testencoding} {
- testencoding create foo toutf fromutf
+ testencoding create foo [namespace origin toutf] [namespace origin fromutf]
set x {}
encoding convertto foo abcd
testencoding delete foo
@@ -54,14 +62,15 @@ test encoding-2.1 {Tcl_FreeEncoding: refcount == 0} {
} {8C}
test encoding-2.2 {Tcl_FreeEncoding: refcount != 0} {testencoding} {
set system [encoding system]
- set path [testencoding path]
+ set path [encoding dirs]
encoding system shiftjis ;# incr ref count
- testencoding path [list [pwd]]
+ encoding dirs [list [pwd]]
set x [encoding convertto shiftjis \u4e4e] ;# old one found
encoding system identity
+ llength shiftjis
lappend x [catch {encoding convertto shiftjis \u4e4e} msg] $msg
encoding system identity
- testencoding path $path
+ encoding dirs $path
encoding system $system
set x
} "\u008c\u00c1 1 {unknown encoding \"shiftjis\"}"
@@ -86,20 +95,20 @@ test encoding-4.1 {Tcl_GetEncodingNames} {testencoding} {
makeDirectory [file join tmp encoding]
makeFile {} [file join tmp encoding junk.enc]
makeFile {} [file join tmp encoding junk2.enc]
- set path [testencoding path]
- testencoding path {}
+ set path [encoding dirs]
+ encoding dirs {}
catch {unset encodings}
catch {unset x}
foreach encoding [encoding names] {
set encodings($encoding) 1
}
- testencoding path [list [pwd]]
+ encoding dirs [list [file join [pwd] encoding]]
foreach encoding [encoding names] {
if {![info exists encodings($encoding)]} {
lappend x $encoding
}
}
- testencoding path $path
+ encoding dirs $path
cd [workingDirectory]
removeFile [file join tmp encoding junk2.enc]
removeFile [file join tmp encoding junk.enc]
@@ -123,7 +132,8 @@ test encoding-5.2 {Tcl_SetSystemEncoding: test ref count} {
} {0}
test encoding-6.1 {Tcl_CreateEncoding: new} {testencoding} {
- testencoding create foo {toutf 1} {fromutf 2}
+ testencoding create foo [namespace code {toutf 1}] \
+ [namespace code {fromutf 2}]
set x {}
encoding convertfrom foo abcd
encoding convertto foo abcd
@@ -131,7 +141,8 @@ test encoding-6.1 {Tcl_CreateEncoding: new} {testencoding} {
set x
} {{toutf 1} {fromutf 2}}
test encoding-6.2 {Tcl_CreateEncoding: replace encoding} {testencoding} {
- testencoding create foo {toutf a} {fromutf b}
+ testencoding create foo [namespace code {toutf a}] \
+ [namespace code {fromutf b}]
set x {}
encoding convertfrom foo abcd
encoding convertto foo abcd
@@ -207,11 +218,12 @@ proc viewable {str} {
test encoding-11.1 {LoadEncodingFile: unknown encoding} {testencoding} {
set system [encoding system]
- set path [testencoding path]
+ set path [encoding dirs]
encoding system iso8859-1
- testencoding path {}
+ encoding dirs {}
+ llength jis0208
set x [list [catch {encoding convertto jis0208 \u4e4e} msg] $msg]
- testencoding path $path
+ encoding dirs $path
encoding system $system
lappend x [encoding convertto jis0208 \u4e4e]
} {1 {unknown encoding "jis0208"} 8C}
@@ -232,10 +244,10 @@ test encoding-11.5.1 {LoadEncodingFile: escape file} {
} [viewable "\x1b\$B8C\x1b(B"]
test encoding-11.6 {LoadEncodingFile: invalid file} {testencoding} {
set system [encoding system]
- set path [testencoding path]
+ set path [encoding dirs]
encoding system identity
cd [temporaryDirectory]
- testencoding path tmp
+ encoding dirs [file join tmp encoding]
makeDirectory tmp
makeDirectory [file join tmp encoding]
set f [open [file join tmp encoding splat.enc] w]
@@ -247,7 +259,7 @@ test encoding-11.6 {LoadEncodingFile: invalid file} {testencoding} {
removeDirectory [file join tmp encoding]
removeDirectory tmp
cd [workingDirectory]
- testencoding path $path
+ encoding dirs $path
encoding system $system
set x
} {1 {invalid encoding file "splat"}}
@@ -327,14 +339,14 @@ test encoding-21.1 {EscapeToUtfProc} {
test encoding-22.1 {EscapeFromUtfProc} {
} {}
-set ::iso2022encData "\u001b\$B;d\$I\$b\$G\$O!\"%A%C%W\$49XF~;~\$K\$4EPO?\$\$\$?\$@\$\$\$?\$4=;=j\$r%-%c%C%7%e%\"%&%H\$N:]\$N\u001b(B
+set iso2022encData "\u001b\$B;d\$I\$b\$G\$O!\"%A%C%W\$49XF~;~\$K\$4EPO?\$\$\$?\$@\$\$\$?\$4=;=j\$r%-%c%C%7%e%\"%&%H\$N:]\$N\u001b(B
\u001b\$B>.@Z<jAwIU@h\$H\$7\$F;HMQ\$7\$F\$*\$j\$^\$9!#62\$lF~\$j\$^\$9\$,!\"@5\$7\$\$=;=j\$r\$4EPO?\$7\$J\$*\u001b(B
\u001b\$B\$*4j\$\$\$\$\$?\$7\$^\$9!#\$^\$?!\"BgJQ62=L\$G\$9\$,!\"=;=jJQ99\$N\$\"\$H!\"F|K\\8l%5!<%S%9It!J\u001b(B
casino_japanese@___.com \u001b\$B!K\$^\$G\$4=;=jJQ99:Q\$NO\"Mm\$r\$\$\$?\$@\$1\$J\$\$\$G\u001b(B
\u001b\$B\$7\$g\$&\$+!)\u001b(B"
-set ::iso2022uniData [encoding convertfrom iso2022-jp $::iso2022encData]
-set ::iso2022uniData2 "\u79c1\u3069\u3082\u3067\u306f\u3001\u30c1\u30c3\u30d7\u3054\u8cfc\u5165\u6642\u306b\u3054\u767b\u9332\u3044\u305f\u3060\u3044\u305f\u3054\u4f4f\u6240\u3092\u30ad\u30e3\u30c3\u30b7\u30e5\u30a2\u30a6\u30c8\u306e\u969b\u306e
+set iso2022uniData [encoding convertfrom iso2022-jp $iso2022encData]
+set iso2022uniData2 "\u79c1\u3069\u3082\u3067\u306f\u3001\u30c1\u30c3\u30d7\u3054\u8cfc\u5165\u6642\u306b\u3054\u767b\u9332\u3044\u305f\u3060\u3044\u305f\u3054\u4f4f\u6240\u3092\u30ad\u30e3\u30c3\u30b7\u30e5\u30a2\u30a6\u30c8\u306e\u969b\u306e
\u5c0f\u5207\u624b\u9001\u4ed8\u5148\u3068\u3057\u3066\u4f7f\u7528\u3057\u3066\u304a\u308a\u307e\u3059\u3002\u6050\u308c\u5165\u308a\u307e\u3059\u304c\u3001\u6b63\u3057\u3044\u4f4f\u6240\u3092\u3054\u767b\u9332\u3057\u306a\u304a
\u304a\u9858\u3044\u3044\u305f\u3057\u307e\u3059\u3002\u307e\u305f\u3001\u5927\u5909\u6050\u7e2e\u3067\u3059\u304c\u3001\u4f4f\u6240\u5909\u66f4\u306e\u3042\u3068\u3001\u65e5\u672c\u8a9e\u30b5\u30fc\u30d3\u30b9\u90e8\uff08
\u0063\u0061\u0073\u0069\u006e\u006f\u005f\u006a\u0061\u0070\u0061\u006e\u0065\u0073\u0065\u0040\u005f\u005f\u005f\u002e\u0063\u006f\u006d\u0020\uff09\u307e\u3067\u3054\u4f4f\u6240\u5909\u66f4\u6e08\u306e\u9023\u7d61\u3092\u3044\u305f\u3060\u3051\u306a\u3044\u3067
@@ -343,11 +355,11 @@ set ::iso2022uniData2 "\u79c1\u3069\u3082\u3067\u306f\u3001\u30c1\u30c3\u30d7\u3
cd [temporaryDirectory]
set fid [open iso2022.txt w]
fconfigure $fid -encoding binary
-puts -nonewline $fid $::iso2022encData
+puts -nonewline $fid $iso2022encData
close $fid
test encoding-23.1 {iso2022-jp escape encoding test} {
- string equal $::iso2022uniData $::iso2022uniData2
+ string equal $iso2022uniData $iso2022uniData2
} 1
test encoding-23.2 {iso2022-jp escape encoding test} {
# This checks that 'gets' isn't resetting the encoding inappropriately.
@@ -365,11 +377,11 @@ test encoding-23.2 {iso2022-jp escape encoding test} {
incr count $num
}
close $fid
- if {[string compare $::iso2022uniData $out]} {
+ if {[string compare $iso2022uniData $out]} {
return -code error "iso2022-jp read in doesn't match original"
}
list $count $out
-} [list [string length $::iso2022uniData] $::iso2022uniData]
+} [list [string length $iso2022uniData] $iso2022uniData]
test encoding-23.3 {iso2022-jp escape encoding test} {
# read $fis <size> reads size in chars, not raw bytes.
set fid [open iso2022.txt r]
@@ -377,7 +389,7 @@ test encoding-23.3 {iso2022-jp escape encoding test} {
set data [read $fid 50]
close $fid
set data
-} [string range $::iso2022uniData 0 49] ; # 0 .. 49 inclusive == 50
+} [string range $iso2022uniData 0 49] ; # 0 .. 49 inclusive == 50
cd [workingDirectory]
test encoding-24.1 {EscapeFreeProc on open channels} -constraints {
@@ -535,16 +547,16 @@ foreach from {cp932 shiftjis euc-jp iso2022-jp} {
cd [temporaryDirectory]
set f [open $from.chars]
fconfigure $f -encoding $from
- set out [open $from.$to.out w]
+ set out [open $from.$to.tcltestout w]
fconfigure $out -encoding $to
puts -nonewline $out [read $f]
close $out
close $f
- # then compare $to.chars <=> $from.to.out as binary.
+ # then compare $to.chars <=> $from.to.tcltestout as binary.
set fa [open $to.chars]
fconfigure $fa -encoding binary
- set fb [open $from.$to.out]
+ set fb [open $from.$to.tcltestout]
fconfigure $fb -encoding binary
set diff [channel-diff $fa $fb]
close $fa
@@ -556,12 +568,30 @@ foreach from {cp932 shiftjis euc-jp iso2022-jp} {
}
}
-eval [list file delete] [glob -directory [temporaryDirectory] *.chars *.out]
+testConstraint testgetdefenc [llength [info commands testgetdefenc]]
+
+test encoding-26.0 {Tcl_GetDefaultEncodingDir} -constraints {
+ testgetdefenc
+} -setup {
+ set origDir [testgetdefenc]
+ testsetdefenc slappy
+} -body {
+ testgetdefenc
+} -cleanup {
+ testsetdefenc $origDir
+} -result slappy
+
+file delete {*}[glob -directory [temporaryDirectory] *.chars *.tcltestout]
# ===> Cut here <===
# EscapeFreeProc, GetTableEncoding, unilen
# are fully tested by the rest of this file
+}
+runtests
+
+}
# cleanup
+namespace delete ::tcl::test::encoding
::tcltest::cleanupTests
return
diff --git a/tests/env.test b/tests/env.test
index a4669d2..47ada47 100644
--- a/tests/env.test
+++ b/tests/env.test
@@ -11,8 +11,14 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-package require tcltest 2
-namespace import -force ::tcltest::*
+if {[lsearch [namespace children] ::tcltest] == -1} {
+ package require tcltest 2
+ namespace import -force ::tcltest::*
+}
+
+# Some tests require the "exec" command.
+# Skip them if exec is not defined.
+testConstraint exec [llength [info commands exec]]
#
# These tests will run on any platform (and indeed crashed
@@ -51,15 +57,10 @@ test env-1.3 {reflection of env by "array names"} {
expr {$ix >= 0}
} {1}
-
-# Some tests require the "exec" command.
-# Skip them if exec is not defined.
-testConstraint exec [llength [info commands exec]]
-
set printenvScript [makeFile {
proc lrem {listname name} {
upvar $listname list
- set i [lsearch $list $name]
+ set i [lsearch -nocase $list $name]
if {$i >= 0} {
set list [lreplace $list $i $i]
}
@@ -77,7 +78,7 @@ set printenvScript [makeFile {
TCL_LIBRARY PATH LD_LIBRARY_PATH LIBPATH PURE_PROG_NAME DISPLAY
SHLIB_PATH SYSTEMDRIVE SYSTEMROOT DYLD_LIBRARY_PATH DYLD_FRAMEWORK_PATH
DYLD_NEW_LOCAL_SHARED_REGIONS DYLD_NO_FIX_PREBINDING
- __CF_USER_TEXT_ENCODING SECURITYSESSIONID
+ __CF_USER_TEXT_ENCODING SECURITYSESSIONID LANG WINDIR TERM
} {
lrem names $name
}
@@ -101,20 +102,17 @@ proc getenv {} {
# Save the current environment variables at the start of the test.
foreach name [array names env] {
- set env2([string toupper $name]) $env($name)
- unset env($name)
-}
+ set env2($name) $env($name)
-# Added the following lines so that child tcltest can actually find its
-# library if the initial tcltest is run from a non-standard place.
-# ('saved' env vars)
-foreach name {
- TCL_LIBRARY PATH LD_LIBRARY_PATH LIBPATH DISPLAY SHLIB_PATH
- SYSTEMDRIVE SYSTEMROOT DYLD_LIBRARY_PATH DYLD_FRAMEWORK_PATH
- DYLD_NEW_LOCAL_SHARED_REGIONS DYLD_NO_FIX_PREBINDING
- SECURITYSESSIONID} {
- if {[info exists env2($name)]} {
- set env($name) $env2($name);
+ # Keep some environment variables that support operation of the
+ # tcltest package.
+ if {[string toupper $name] ni {
+ TCL_LIBRARY PATH LD_LIBRARY_PATH LIBPATH DISPLAY SHLIB_PATH
+ SYSTEMDRIVE SYSTEMROOT DYLD_LIBRARY_PATH DYLD_FRAMEWORK_PATH
+ DYLD_NEW_LOCAL_SHARED_REGIONS DYLD_NO_FIX_PREBINDING
+ SECURITYSESSIONID LANG WINDIR TERM
+ }} {
+ unset env($name)
}
}
@@ -233,7 +231,7 @@ test env-5.4 {corner cases - unset the env array} {} {
interp delete i
set result
} {1 a 1}
-test env-5.5 {corner cases - cannot have null entries on Windows} {pcOnly} {
+test env-5.5 {corner cases - cannot have null entries on Windows} {win} {
set env() a
catch {set env()}
} {1}
diff --git a/tests/error.test b/tests/error.test
index 8aa99d6..b989338 100644
--- a/tests/error.test
+++ b/tests/error.test
@@ -16,6 +16,7 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
+namespace eval ::tcl::test::error {
proc foo {} {
global errorInfo
set a [catch {format [error glorp2]} b]
@@ -41,7 +42,7 @@ test error-1.2 {simple errors from commands} {
test error-1.3 {simple errors from commands} {
catch {format [string index]} b
- set errorInfo
+ set ::errorInfo
# this used to return '... while executing ...', but
# string index is fully compiled as of 8.4a3
} {wrong # args: should be "string index string charIndex"
@@ -58,18 +59,22 @@ test error-1.5 {simple errors from commands} {
} glorp
test error-1.6 {simple errors from commands} {
- catch {catch a b c} b
+ catch {catch a b c d} b
} 1
test error-1.7 {simple errors from commands} {
- catch {catch a b c} b
+ catch {catch a b c d} b
set b
-} {wrong # args: should be "catch command ?varName?"}
+} {wrong # args: should be "catch script ?resultVarName? ?optionVarName?"}
-test error-1.8 {simple errors from commands} {nonPortable} {
+test error-1.8 {simple errors from commands} {
# This test is non-portable: it generates a memory fault on
# machines like DEC Alphas (infinite recursion overflows
# stack?)
+ #
+ # That claims sounds like a bug to be fixed rather than a portability
+ # problem. Anyhow, I believe it's out of date (bug's been fixed) so
+ # this test is re-enabled.
proc p {} {
uplevel 1 catch p error
@@ -91,7 +96,7 @@ test error-2.2 {errors in nested procedures} {
test error-2.3 {errors in nested procedures} {
catch foo b
- set errorInfo
+ set ::errorInfo
} {Human-generated
while executing
"error {Human-generated}"
@@ -110,7 +115,7 @@ test error-2.5 {errors in nested procedures} {
test error-2.6 {errors in nested procedures} {
catch foo2 b
- set errorInfo
+ set ::errorInfo
} {glorp2
while executing
"error glorp2"
@@ -122,10 +127,10 @@ test error-2.6 {errors in nested procedures} {
test error-3.1 {errors in catch command} {
list [catch {catch} msg] $msg
-} {1 {wrong # args: should be "catch command ?varName?"}}
+} {1 {wrong # args: should be "catch script ?resultVarName? ?optionVarName?"}}
test error-3.2 {errors in catch command} {
list [catch {catch a b c} msg] $msg
-} {1 {wrong # args: should be "catch command ?varName?"}}
+} {0 1}
test error-3.3 {errors in catch command} {
catch {unset a}
set a(0) 22
@@ -136,27 +141,27 @@ catch {unset a}
# More tests related to errorInfo and errorCode
test error-4.1 {errorInfo and errorCode variables} {
- list [catch {error msg1 msg2 msg3} msg] $msg $errorInfo $errorCode
+ list [catch {error msg1 msg2 msg3} msg] $msg $::errorInfo $::errorCode
} {1 msg1 msg2 msg3}
test error-4.2 {errorInfo and errorCode variables} {
- list [catch {error msg1 {} msg3} msg] $msg $errorInfo $errorCode
+ list [catch {error msg1 {} msg3} msg] $msg $::errorInfo $::errorCode
} {1 msg1 {msg1
while executing
"error msg1 {} msg3"} msg3}
test error-4.3 {errorInfo and errorCode variables} {
- list [catch {error msg1 {}} msg] $msg $errorInfo $errorCode
+ list [catch {error msg1 {}} msg] $msg $::errorInfo $::errorCode
} {1 msg1 {msg1
while executing
"error msg1 {}"} NONE}
test error-4.4 {errorInfo and errorCode variables} {
- set errorCode bogus
- list [catch {error msg1} msg] $msg $errorInfo $errorCode
+ set ::errorCode bogus
+ list [catch {error msg1} msg] $msg $::errorInfo $::errorCode
} {1 msg1 {msg1
while executing
"error msg1"} NONE}
test error-4.5 {errorInfo and errorCode variables} {
- set errorCode bogus
- list [catch {error msg1 msg2 {}} msg] $msg $errorInfo $errorCode
+ set ::errorCode bogus
+ list [catch {error msg1 msg2 {}} msg] $msg $::errorInfo $::errorCode
} {1 msg1 msg2 {}}
# Errors in error command itself
@@ -172,53 +177,66 @@ test error-5.2 {errors in error command} {
test error-6.1 {catch must reset error state} {
catch {error outer [catch {error inner inner.errorInfo inner.errorCode}]}
- list $errorCode $errorInfo
+ list $::errorCode $::errorInfo
+} {NONE 1}
+test error-6.2 {catch must reset error state} {
+ catch {error outer [catch {return -level 0 -code error -errorcode BUG}]}
+ list $::errorCode $::errorInfo
} {NONE 1}
test error-6.3 {catch must reset error state} {
- set errorCode BUG
+ set ::errorCode BUG
catch {error outer [catch set]}
- list $errorCode $errorInfo
+ list $::errorCode $::errorInfo
} {NONE 1}
test error-6.4 {catch must reset error state} {
catch {error [catch {error foo bar baz}] 1}
- list $errorCode $errorInfo
+ list $::errorCode $::errorInfo
+} {NONE 1}
+test error-6.5 {catch must reset error state} {
+ catch {error [catch {return -level 0 -code error -errorcode BUG}] 1}
+ list $::errorCode $::errorInfo
+} {NONE 1}
+test error-6.6 {catch must reset error state} {
+ catch {return -level 0 -code error -errorinfo [catch {error foo bar baz}]}
+ list $::errorCode $::errorInfo
} {NONE 1}
test error-6.7 {catch must reset error state} {
proc foo {} {
- return -code error -errorinfo [catch {error foo bar baz}]
+ return -code error -errorinfo [catch {error foo bar baz}]
}
catch foo
- list $errorCode
+ list $::errorCode
+} {NONE}
+test error-6.8 {catch must reset error state} {
+ catch {return -level 0 -code error [catch {error foo bar baz}]}
+ list $::errorCode
} {NONE}
test error-6.9 {catch must reset error state} {
proc foo {} {
- return -code error [catch {error foo bar baz}]
+ return -code error [catch {error foo bar baz}]
}
catch foo
- list $errorCode
+ list $::errorCode
} {NONE}
-namespace eval ::tcl::test::error {
test error-7.0 {Bug 1397843} -body {
- variable cmds
- proc EIWrite args {
- variable cmds
- lappend cmds [lindex [info level -2] 0]
- }
- proc BadProc {} {
- set i a
- incr i
- }
- trace add variable ::errorInfo write [namespace code EIWrite]
- catch BadProc
- trace remove variable ::errorInfo write [namespace code EIWrite]
- set cmds
+ variable cmds
+ proc EIWrite args {
+ variable cmds
+ lappend cmds [lindex [info level -2] 0]
+ }
+ proc BadProc {} {
+ set i a
+ incr i
+ }
+ trace add variable ::errorInfo write [namespace code EIWrite]
+ catch BadProc
+ trace remove variable ::errorInfo write [namespace code EIWrite]
+ set cmds
} -match glob -result {*BadProc*}
}
namespace delete ::tcl::test::error
-
-
# cleanup
catch {rename p ""}
::tcltest::cleanupTests
diff --git a/tests/eval.test b/tests/eval.test
index 97d5801..ff50997 100644
--- a/tests/eval.test
+++ b/tests/eval.test
@@ -45,7 +45,7 @@ test eval-2.5 {error in eval'ed command: setting errorInfo} {
set a 1
error "test error"
}} msg
- set errorInfo
+ set ::errorInfo
} "test error
while executing
\"error \"test error\"\"
@@ -56,18 +56,29 @@ test eval-2.5 {error in eval'ed command: setting errorInfo} {
error \"test error\"
}\""
+test eval-3.1 {eval and pure lists} {
+ eval [list list 1 2 3 4 5]
+} {1 2 3 4 5}
+test eval-3.2 {concatenating eval and pure lists} {
+ eval [list list 1] [list 2 3 4 5]
+} {1 2 3 4 5}
+test eval-3.3 {eval and canonical lists} {
+ set cmd [list list 1 2 3 4 5]
+ # Force existance of utf-8 rep
+ set dummy($cmd) $cmd
+ unset dummy
+ eval $cmd
+} {1 2 3 4 5}
+test eval-3.4 {concatenating eval and canonical lists} {
+ set cmd [list list 1]
+ set cmd2 [list 2 3 4 5]
+ # Force existance of utf-8 rep
+ set dummy($cmd) $cmd
+ set dummy($cmd2) $cmd2
+ unset dummy
+ eval $cmd $cmd2
+} {1 2 3 4 5}
+
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/event.test b/tests/event.test
index d2e77db..a7122f9 100644
--- a/tests/event.test
+++ b/tests/event.test
@@ -186,6 +186,86 @@ test event-5.2 {Tcl_BackgroundError, HandleBgErrors procedures} {
rename bgerror {}
set x
} {{a simple error}}
+test event-5.3 {HandleBgErrors: [Bug 1670155]} -setup {
+ variable x
+ proc demo args {variable x done}
+ variable target [list [namespace which demo] x]
+ proc trial args {variable target; string length $target}
+ trace add execution demo enter [namespace code trial]
+ variable save [interp bgerror {}]
+ interp bgerror {} $target
+} -body {
+ after 0 {error bar}
+ vwait [namespace which -variable x]
+} -cleanup {
+ interp bgerror {} $save
+ unset x target save
+ rename demo {}
+ rename trial {}
+} -result {}
+test event-5.3.1 {Default [interp bgerror] handler} -body {
+ ::tcl::Bgerror
+} -returnCodes error -match glob -result {*msg options*}
+test event-5.4 {Default [interp bgerror] handler} -body {
+ ::tcl::Bgerror {}
+} -returnCodes error -match glob -result {*msg options*}
+test event-5.5 {Default [interp bgerror] handler} -body {
+ ::tcl::Bgerror {} {} {}
+} -returnCodes error -match glob -result {*msg options*}
+test event-5.6 {Default [interp bgerror] handler} -body {
+ ::tcl::Bgerror {} {}
+} -returnCodes error -match glob -result {*-level*}
+test event-5.7 {Default [interp bgerror] handler} -body {
+ ::tcl::Bgerror {} {-level foo}
+} -returnCodes error -match glob -result {*expected integer*}
+test event-5.8 {Default [interp bgerror] handler} -body {
+ ::tcl::Bgerror {} {-level 0}
+} -returnCodes error -match glob -result {*-code*}
+test event-5.9 {Default [interp bgerror] handler} -body {
+ ::tcl::Bgerror {} {-level 0 -code ok}
+} -returnCodes error -match glob -result {*expected integer*}
+test event-5.10 {Default [interp bgerror] handler} {
+ proc bgerror {m} {append ::res $m}
+ set ::res {}
+ ::tcl::Bgerror {} {-level 0 -code 0}
+ rename bgerror {}
+ set ::res
+} {}
+test event-5.11 {Default [interp bgerror] handler} {
+ proc bgerror {m} {append ::res $m}
+ set ::res {}
+ ::tcl::Bgerror msg {-level 0 -code 1}
+ rename bgerror {}
+ set ::res
+} {msg}
+test event-5.12 {Default [interp bgerror] handler} {
+ proc bgerror {m} {append ::res $m}
+ set ::res {}
+ ::tcl::Bgerror msg {-level 0 -code 2}
+ rename bgerror {}
+ set ::res
+} {command returned bad code: 2}
+test event-5.13 {Default [interp bgerror] handler} {
+ proc bgerror {m} {append ::res $m}
+ set ::res {}
+ ::tcl::Bgerror msg {-level 0 -code 3}
+ rename bgerror {}
+ set ::res
+} {invoked "break" outside of a loop}
+test event-5.14 {Default [interp bgerror] handler} {
+ proc bgerror {m} {append ::res $m}
+ set ::res {}
+ ::tcl::Bgerror msg {-level 0 -code 4}
+ rename bgerror {}
+ set ::res
+} {invoked "continue" outside of a loop}
+test event-5.15 {Default [interp bgerror] handler} {
+ proc bgerror {m} {append ::res $m}
+ set ::res {}
+ ::tcl::Bgerror msg {-level 0 -code 5}
+ rename bgerror {}
+ set ::res
+} {command returned bad code: 5}
test event-6.1 {BgErrorDeleteProc procedure} {
catch {interp delete foo}
@@ -285,6 +365,45 @@ test event-7.5 {correct behaviour when there is no bgerror [Bug 219142]} {exec}
"error hello"
("after" script)}}
+test event-7.6 {safe hidden bgerror fallback} {
+ variable result {}
+ interp create -safe safe
+ safe alias puts puts
+ safe alias result ::append [namespace which -variable result]
+ safe eval {proc bgerror m {result $m\n$::errorCode\n$::errorInfo\n}}
+ safe hide bgerror
+ safe eval after 0 error foo
+ update
+ interp delete safe
+ set result
+} {foo
+NONE
+foo
+ while executing
+"error foo"
+ ("after" script)
+}
+
+test event-7.7 {safe hidden bgerror fallback} {
+ variable result {}
+ interp create -safe safe
+ safe alias puts puts
+ safe alias result ::append [namespace which -variable result]
+ safe eval {proc bgerror m {result $m\n$::errorCode\n$::errorInfo\n}}
+ safe hide bgerror
+ safe eval {proc bgerror m {error bar soom baz}}
+ safe eval after 0 error foo
+ update
+ interp delete safe
+ set result
+} {foo
+NONE
+foo
+ while executing
+"error foo"
+ ("after" script)
+}
+
# someday : add a test checking that
# when there is no bgerror, an error msg goes to stderr
@@ -363,8 +482,8 @@ test event-9.4 {Tcl_DeleteExitHandler procedure} {stdio testexithandler} {
test event-10.1 {Tcl_Exit procedure} {stdio} {
set child [open |[list [interpreter]] r+]
puts $child "exit 3"
- list [catch {close $child} msg] $msg [lindex $errorCode 0] \
- [lindex $errorCode 2]
+ list [catch {close $child} msg] $msg [lindex $::errorCode 0] \
+ [lindex $::errorCode 2]
} {1 {child process exited abnormally} CHILDSTATUS 3}
test event-11.1 {Tcl_VwaitCmd procedure} {
@@ -405,7 +524,7 @@ test event-11.5 {Tcl_VwaitCmd procedure: round robin scheduling, 2 sources} {soc
puts $s foobar
close $s
}
- catch {set s1 [socket -server accept 0]}
+ catch {set s1 [socket -server accept -myaddr 127.0.0.1 0]}
after 1000
catch {set s2 [socket 127.0.0.1 [lindex [fconfigure $s1 -sockname] 2]]}
close $s1
diff --git a/tests/exec.test b/tests/exec.test
index 8d36292..810dfa6 100644
--- a/tests/exec.test
+++ b/tests/exec.test
@@ -27,6 +27,12 @@ set path(echo) [makeFile {
exit
} echo]
+set path(echo2) [makeFile {
+ puts stdout [join $argv]
+ puts stderr [lindex $argv 1]
+ exit
+} echo2]
+
set path(cat) [makeFile {
if {$argv == {}} {
set argv -
@@ -79,6 +85,25 @@ set path(sh) [makeFile {
}
exit
} sh]
+set path(sh2) [makeFile {
+ if {[lindex $argv 0] != "-c"} {
+ error "sh: unexpected arguments $argv"
+ }
+ set cmd [lindex $argv 1]
+ lappend cmd ";"
+
+ set newcmd {}
+
+ foreach arg $cmd {
+ if {$arg == ";"} {
+ eval exec -ignorestderr >@stdout [list [info nameofexecutable]] $newcmd
+ set newcmd {}
+ continue
+ }
+ lappend newcmd $arg
+ }
+ exit
+} sh2]
set path(sleep) [makeFile {
after [expr $argv*1000]
@@ -215,8 +240,8 @@ test exec-4.5 {redirecting output and stderr to file} {exec} {
# I/O redirection: input from file.
-if { [set ::tcltest::testConstraints(exec)] } {
-exec [interpreter] $path(echo) "Just a few thoughts" > $path(gorp.file)
+if {[testConstraint exec]} {
+ exec [interpreter] $path(echo) "Just a few thoughts" > $path(gorp.file)
}
test exec-5.1 {redirecting input from file} {exec} {
exec [interpreter] $path(cat) < $path(gorp.file)
@@ -312,8 +337,8 @@ test exec-9.6 {commands returning errors} {exec} {
list [catch {exec [interpreter] "$path(sh)" -c "\"$path(echo)\" error msg 1>&2"} msg] $msg
} {1 {error msg}}
test exec-9.7 {commands returning errors} {exec stdio} {
- list [catch {exec [interpreter] "$path(sh)" -c "\"$path(echo)\" error msg 1>&2" \
- | [interpreter] "$path(sh)" -c "\"$path(echo)\" error msg 1>&2"} msg] $msg
+ list [catch {exec [interpreter] "$path(sh)" -c "\"$path(echo)\" error msg 1>&2 ; \"$path(sleep)\" 1" \
+ | [interpreter] "$path(sh)" -c "\"$path(echo)\" error msg 1>&2 ; \"$path(sleep)\" 1"} msg] $msg
} {1 {error msg
error msg}}
@@ -430,11 +455,11 @@ test exec-11.5 {commands in background} {exec} {
# Make sure that background commands are properly reaped when
# they eventually die.
-if { [set ::tcltest::testConstraints(exec)] } {
-exec [interpreter] $path(sleep) 3
+if {[testConstraint exec]} {
+ exec [interpreter] $path(sleep) 3
}
test exec-12.1 {reaping background processes} \
- {exec unixOnly nonPortable} {
+ {exec unix nonPortable} {
for {set i 0} {$i < 20} {incr i} {
exec echo foo > /dev/null &
}
@@ -443,7 +468,7 @@ test exec-12.1 {reaping background processes} \
lindex $msg 0
} 0
test exec-12.2 {reaping background processes} \
- {exec unixOnly nonPortable} {
+ {exec unix nonPortable} {
exec sleep 2 | sleep 2 | sleep 2 &
catch {exec ps | fgrep -i "sleep" | fgrep -i -v fgrep | wc} msg
set x [lindex $msg 0]
@@ -452,7 +477,7 @@ test exec-12.2 {reaping background processes} \
list $x [lindex $msg 0]
} {3 0}
test exec-12.3 {reaping background processes} \
- {exec unixOnly nonPortable} {
+ {exec unix nonPortable} {
exec sleep 1000 &
exec sleep 1000 &
set x [exec ps | fgrep "sleep" | fgrep -v fgrep]
@@ -520,7 +545,7 @@ test exec-13.5 {extended exit result codes: max value} {
test exec-13.6 {extended exit result codes: signalled} {
-constraints {win}
-setup {
- set tmp [makeFile {exit 0xffffffff} tmpfile.exec-13.6]
+ set tmp [makeFile {exit 0xC0000016} tmpfile.exec-13.6]
}
-body {
list [catch {exec [interpreter] $tmp} err]\
@@ -542,10 +567,14 @@ test exec-14.2 {-keepnewline switch} {exec} {
} {1 {wrong # args: should be "exec ?switches? arg ?arg ...?"}}
test exec-14.3 {unknown switch} {exec} {
list [catch {exec -gorp} msg] $msg
-} {1 {bad switch "-gorp": must be -keepnewline or --}}
+} {1 {bad switch "-gorp": must be -ignorestderr, -keepnewline, or --}}
test exec-14.4 {-- switch} {exec} {
list [catch {exec -- -gorp} msg] [string tolower $msg]
} {1 {couldn't execute "-gorp": no such file or directory}}
+test exec-14.5 {-ignorestderr switch} {exec} {
+ # Alas, the use of -ignorestderr is buried here :-(
+ exec [interpreter] $path(sh2) -c [list $path(echo2) foo bar] 2>@1
+} "foo bar\nbar"
# Redirecting standard error separately from standard output
@@ -677,7 +706,7 @@ test exec-19.1 {exec >> uses O_APPEND} {
# cleanup
-foreach file {script gorp.file gorp.file2 echo cat wc sh sleep exit err} {
+foreach file {script gorp.file gorp.file2 echo echo2 cat wc sh sh2 sleep exit err} {
removeFile $file
}
unset -nocomplain path
diff --git a/tests/execute.test b/tests/execute.test
index 1a95c44..b460cfe 100644
--- a/tests/execute.test
+++ b/tests/execute.test
@@ -19,22 +19,20 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-catch {eval namespace delete [namespace children :: test_ns_*]}
+catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {rename foo ""}
catch {unset x}
catch {unset y}
catch {unset msg}
-::tcltest::testConstraint testobj \
- [expr {[info commands testobj] != {} \
- && [info commands testdoubleobj] != {} \
- && [info commands teststringobj] != {} \
- && [info commands testobj] != {}}]
+testConstraint testobj [expr {
+ [llength [info commands testobj]]
+ && [llength [info commands testdoubleobj]]
+ && [llength [info commands teststringobj]]
+}]
-::tcltest::testConstraint longIs32bit \
- [expr {int(0x80000000) < 0}]
-::tcltest::testConstraint testexprlongobj \
- [llength [info commands testexprlongobj]]
+testConstraint longIs32bit [expr {int(0x80000000) < 0}]
+testConstraint testexprlongobj [llength [info commands testexprlongobj]]
# Tests for the omnibus TclExecuteByteCode function:
@@ -507,7 +505,7 @@ test execute-3.77 {TclExecuteByteCode, INST_TRY_CVT_TO_NUMERIC, op is non-numeri
# INST_PUSH_RETURN_CODE not tested
test execute-4.1 {Tcl_GetCommandFromObj, convert to tclCmdNameType} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {unset x}
catch {unset y}
namespace eval test_ns_1 {
@@ -525,7 +523,7 @@ test execute-4.1 {Tcl_GetCommandFromObj, convert to tclCmdNameType} {
[catch {namespace which -command ${x}${y}:cmd2} msg] $msg
} {::test_ns_1::test_ns_2::cmd1 0 {} 0 {}}
test execute-4.2 {Tcl_GetCommandFromObj, check if cached tclCmdNameType is invalid} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {rename foo ""}
catch {unset l}
proc foo {} {
@@ -547,7 +545,7 @@ test execute-4.2 {Tcl_GetCommandFromObj, check if cached tclCmdNameType is inval
set l
} {::foo ::test_ns_1::foo}
test execute-4.3 {Tcl_GetCommandFromObj, command never found} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {rename foo ""}
namespace eval test_ns_1 {
proc foo {} {
@@ -565,7 +563,7 @@ test execute-4.3 {Tcl_GetCommandFromObj, command never found} {
} {::test_ns_1::foo {} 0 {}}
test execute-5.1 {SetCmdNameFromAny, set cmd name to empty heap string if NULL} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {unset l}
proc {} {} {return {}}
{}
@@ -632,7 +630,7 @@ test execute-6.6 {TclCompEvalObj: proc-body bytecode invalid for script} {
test execute-6.7 {TclCompEvalObj: bytecode context validation} {
set script { llength {} }
namespace eval foo {
- proc llength {args} {return AHA!}
+ proc llength {args} {return AHA!}
}
set result {}
lappend result [if 1 $script]
@@ -645,7 +643,7 @@ test execute-6.8 {TclCompEvalObj: bytecode name resolution epoch validation} {
set result {}
lappend result [namespace eval foo $script]
namespace eval foo {
- proc llength {args} {return AHA!}
+ proc llength {args} {return AHA!}
}
lappend result [namespace eval foo $script]
namespace delete foo
@@ -695,7 +693,7 @@ test execute-6.12 {Tcl_ExprObj: exprcode interp validation} {
lappend result [e $e]
interp delete slave
interp create slave
- interp alias {} e slave expr
+ interp alias {} e slave expr
lappend result [e $e]
interp delete slave
set result
@@ -715,7 +713,7 @@ test execute-6.13 {Tcl_ExprObj: exprcode epoch validation} {
test execute-6.14 {Tcl_ExprObj: exprcode context validation} {
set e { [llength {}]+1 }
namespace eval foo {
- proc llength {args} {return 1}
+ proc llength {args} {return 1}
}
set result {}
lappend result [expr $e]
@@ -728,7 +726,7 @@ test execute-6.15 {Tcl_ExprObj: exprcode name resolution epoch validation} {
set result {}
lappend result [namespace eval foo {expr $e}]
namespace eval foo {
- proc llength {args} {return 1}
+ proc llength {args} {return 1}
}
lappend result [namespace eval foo {expr $e}]
namespace delete foo
@@ -768,125 +766,124 @@ test execute-6.18 {Tcl_ExprObj: exprcode context validation} {
set result
} {0 1}
-
-test execute-7.0 {Wide int handling in INST_JUMP_FALSE/LAND} {longIs32bit} {
+test execute-7.0 {Wide int handling in INST_JUMP_FALSE/LAND} {
set x 0x100000000
expr {$x && 1}
} 1
-test execute-7.1 {Wide int handling in INST_JUMP_FALSE/LAND} {longIs32bit} {
+test execute-7.1 {Wide int handling in INST_JUMP_FALSE/LAND} {
expr {0x100000000 && 1}
} 1
-test execute-7.2 {Wide int handling in INST_JUMP_FALSE/LAND} {longIs32bit} {
+test execute-7.2 {Wide int handling in INST_JUMP_FALSE/LAND} {
expr {1 && 0x100000000}
} 1
-test execute-7.3 {Wide int handling in INST_JUMP_FALSE/LAND} {longIs32bit} {
+test execute-7.3 {Wide int handling in INST_JUMP_FALSE/LAND} {
expr {wide(0x100000000) && 1}
} 1
-test execute-7.4 {Wide int handling in INST_JUMP_FALSE/LAND} {longIs32bit} {
+test execute-7.4 {Wide int handling in INST_JUMP_FALSE/LAND} {
expr {1 && wide(0x100000000)}
} 1
-test execute-7.5 {Wide int handling in INST_EQ} {longIs32bit} {
+test execute-7.5 {Wide int handling in INST_EQ} {
expr {4 == (wide(1)+wide(3))}
} 1
-test execute-7.6 {Wide int handling in INST_EQ and [incr]} {longIs32bit} {
+test execute-7.6 {Wide int handling in INST_EQ and [incr]} {
set x 399999999999
expr {400000000000 == [incr x]}
} 1
# wide ints have more bits of precision than doubles, but we convert anyway
-test execute-7.7 {Wide int handling in INST_EQ and [incr]} {longIs32bit} {
+test execute-7.7 {Wide int handling in INST_EQ and [incr]} {
set x [expr {wide(1)<<62}]
set y [expr {$x+1}]
expr {double($x) == double($y)}
} 1
-test execute-7.8 {Wide int conversions can change sign} {longIs32bit} {
+test execute-7.8 {Wide int conversions can change sign} longIs32bit {
set x 0x80000000
expr {int($x) < wide($x)}
} 1
-test execute-7.9 {Wide int handling in INST_MOD} {longIs32bit} {
+test execute-7.9 {Wide int handling in INST_MOD} {
expr {(wide(1)<<60) % ((wide(47)<<45)-1)}
} 316659348800185
-test execute-7.10 {Wide int handling in INST_MOD} {longIs32bit} {
+test execute-7.10 {Wide int handling in INST_MOD} {
expr {((wide(1)<<60)-1) % 0x400000000}
} 17179869183
-test execute-7.11 {Wide int handling in INST_LSHIFT} {longIs32bit} {
+test execute-7.11 {Wide int handling in INST_LSHIFT} {
expr wide(42)<<30
} 45097156608
-test execute-7.12 {Wide int handling in INST_LSHIFT} {longIs32bit} {
+test execute-7.12 {Wide int handling in INST_LSHIFT} {
expr 12345678901<<3
} 98765431208
-test execute-7.13 {Wide int handling in INST_RSHIFT} {longIs32bit} {
+test execute-7.13 {Wide int handling in INST_RSHIFT} {
expr 0x543210febcda9876>>7
} 47397893236700464
-test execute-7.14 {Wide int handling in INST_RSHIFT} {longIs32bit} {
- expr 0x9876543210febcda>>7
+test execute-7.14 {Wide int handling in INST_RSHIFT} {
+ expr wide(0x9876543210febcda)>>7
} -58286587177206407
-test execute-7.15 {Wide int handling in INST_BITOR} {longIs32bit} {
- expr 0x9876543210febcda | 0x543210febcda9876
+test execute-7.15 {Wide int handling in INST_BITOR} {
+ expr wide(0x9876543210febcda) | 0x543210febcda9876
} -2560765885044310786
-test execute-7.16 {Wide int handling in INST_BITXOR} {longIs32bit} {
- expr 0x9876543210febcda ^ 0x543210febcda9876
+test execute-7.16 {Wide int handling in INST_BITXOR} {
+ expr wide(0x9876543210febcda) ^ 0x543210febcda9876
} -3727778945703861076
-test execute-7.17 {Wide int handling in INST_BITAND} {longIs32bit} {
- expr 0x9876543210febcda & 0x543210febcda9876
+test execute-7.17 {Wide int handling in INST_BITAND} {
+ expr wide(0x9876543210febcda) & 0x543210febcda9876
} 1167013060659550290
-test execute-7.18 {Wide int handling in INST_ADD} {longIs32bit} {
+test execute-7.18 {Wide int handling in INST_ADD} {
expr wide(0x7fffffff)+wide(0x7fffffff)
} 4294967294
-test execute-7.19 {Wide int handling in INST_ADD} {longIs32bit} {
+test execute-7.19 {Wide int handling in INST_ADD} {
expr 0x7fffffff+wide(0x7fffffff)
} 4294967294
-test execute-7.20 {Wide int handling in INST_ADD} {longIs32bit} {
+test execute-7.20 {Wide int handling in INST_ADD} {
expr wide(0x7fffffff)+0x7fffffff
} 4294967294
-test execute-7.21 {Wide int handling in INST_ADD} {longIs32bit} {
+test execute-7.21 {Wide int handling in INST_ADD} {
expr double(0x7fffffff)+wide(0x7fffffff)
} 4294967294.0
-test execute-7.22 {Wide int handling in INST_ADD} {longIs32bit} {
+test execute-7.22 {Wide int handling in INST_ADD} {
expr wide(0x7fffffff)+double(0x7fffffff)
} 4294967294.0
-test execute-7.23 {Wide int handling in INST_SUB} {longIs32bit} {
+test execute-7.23 {Wide int handling in INST_SUB} {
expr 0x123456789a-0x20406080a
} 69530054800
-test execute-7.24 {Wide int handling in INST_MULT} {longIs32bit} {
+test execute-7.24 {Wide int handling in INST_MULT} {
expr 0x123456789a*193
} 15090186251290
-test execute-7.25 {Wide int handling in INST_DIV} {longIs32bit} {
+test execute-7.25 {Wide int handling in INST_DIV} {
expr 0x123456789a/193
} 405116546
-test execute-7.26 {Wide int handling in INST_UPLUS} {longIs32bit} {
+test execute-7.26 {Wide int handling in INST_UPLUS} {
set x 0x123456871234568
expr {+ $x}
} 81985533099853160
-test execute-7.27 {Wide int handling in INST_UMINUS} {longIs32bit} {
+test execute-7.27 {Wide int handling in INST_UMINUS} {
set x 0x123456871234568
expr {- $x}
} -81985533099853160
-test execute-7.28 {Wide int handling in INST_LNOT} {longIs32bit} {
+test execute-7.28 {Wide int handling in INST_LNOT} {
set x 0x123456871234568
expr {! $x}
} 0
-test execute-7.29 {Wide int handling in INST_BITNOT} {longIs32bit} {
+test execute-7.29 {Wide int handling in INST_BITNOT} {
set x 0x123456871234568
expr {~ $x}
} -81985533099853161
-test execute-7.30 {Wide int handling in function call} {longIs32bit} {
+test execute-7.30 {Wide int handling in function call} {
set x 0x12345687123456
incr x
expr {log($x) == log(double($x))}
} 1
-test execute-7.31 {Wide int handling in abs()} {longIs32bit} {
+test execute-7.31 {Wide int handling in abs()} {
set x 0xa23456871234568
incr x
set y 0x123456871234568
concat [expr {abs($x)}] [expr {abs($y)}]
} {730503879441204585 81985533099853160}
-test execute-7.32 {Wide int handling} {longIs32bit} {
- expr {1024 * 1024 * 1024 * 1024}
+test execute-7.32 {Wide int handling} longIs32bit {
+ expr {int(1024 * 1024 * 1024 * 1024)}
} 0
-test execute-7.33 {Wide int handling} {longIs32bit} {
- expr {0x1 * 1024 * 1024 * 1024 * 1024}
+test execute-7.33 {Wide int handling} longIs32bit {
+ expr {int(0x1 * 1024 * 1024 * 1024 * 1024)}
} 0
-test execute-7.34 {Wide int handling} {longIs32bit} {
+test execute-7.34 {Wide int handling} {
expr {wide(0x1) * 1024 * 1024 * 1024 * 1024}
} 1099511627776
@@ -902,6 +899,77 @@ test execute-8.1 {Stack protection} -setup {
rename whatever {}
} -returnCodes error -match glob -result *
+test execute-8.2 {Stack restoration} -body {
+ # Test for [Bug #816641], correct restoration
+ # of the stack top after the stack is grown
+ proc f {args} { f bee bop }
+ catch f msg
+ set msg
+ } -setup {
+ # Avoid crashes when system stack size is limited (thread-enabled!)
+ set limit [interp recursionlimit {}]
+ interp recursionlimit {} 100
+ } -cleanup {
+ interp recursionlimit {} $limit
+ } -result {too many nested evaluations (infinite loop?)}
+
+test execute-8.3 {Stack restoration} -body {
+ # Test for [Bug #1055676], correct restoration
+ # of the stack top after the epoch is bumped and
+ # the stack is grown in a call from a nested evaluation
+ set arglst [string repeat "a " 1000]
+ proc f {args} "f $arglst"
+ proc run {} {
+ # bump the interp's epoch
+ rename ::set ::dummy
+ rename ::dummy ::set
+ catch f msg
+ set msg
+ }
+ run
+ } -setup {
+ # Avoid crashes when system stack size is limited (thread-enabled!)
+ set limit [interp recursionlimit {}]
+ interp recursionlimit {} 100
+ } -cleanup {
+ interp recursionlimit {} $limit
+ } -result {too many nested evaluations (infinite loop?)}
+
+test execute-8.4 {Compile epoch bump effect on stack trace} -setup {
+ proc foo {} {
+ error bar
+ }
+ proc FOO {} {
+ catch {error bar} m o
+ rename ::set ::dummy
+ rename ::dummy ::set
+ return -options $o $m
+ }
+} -body {
+ catch foo m o
+ set stack1 [dict get $o -errorinfo]
+ catch FOO m o
+ set stack2 [string map {FOO foo} [dict get $o -errorinfo]]
+ expr {$stack1 eq $stack2 ? {} : "These differ:\n$stack1\n$stack2"}
+} -cleanup {
+ rename foo {}
+ rename FOO {}
+} -result {}
+
+test execute-9.1 {Interp result resetting [Bug 1522803]} {
+ set c 0
+ catch {
+ catch {set foo}
+ expr {1/$c}
+ }
+ if {[string match *foo* $::errorInfo]} {
+ set result "Bad errorInfo: $::errorInfo"
+ } else {
+ set result SUCCESS
+ }
+ set result
+} SUCCESS
+
test execute-10.2 {Bug 2802881} -setup {
interp create slave
} -body {
@@ -919,7 +987,7 @@ test execute-10.2 {Bug 2802881} -setup {
if {[info commands testobj] != {}} {
testobj freeallvars
}
-catch {eval namespace delete [namespace children :: test_ns_*]}
+catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {rename foo ""}
catch {rename p ""}
catch {rename {} ""}
@@ -929,3 +997,7 @@ catch {unset y}
catch {unset msg}
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/expr-old.test b/tests/expr-old.test
index 3f29341..c05a925 100644
--- a/tests/expr-old.test
+++ b/tests/expr-old.test
@@ -18,13 +18,74 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-if {([catch {expr T1()} msg] == 1) && ($msg == {unknown math function "T1"})} {
- set gotT1 0
- puts "This application hasn't been compiled with the \"T1\" and"
- puts "\"T2\" math functions, so I'll skip some of the expr tests."
+testConstraint testexprlong [llength [info commands testexprlong]]
+testConstraint testexprdouble [llength [info commands testexprdouble]]
+testConstraint testexprstring [llength [info commands testexprstring]]
+testConstraint longIs32bit [expr {int(0x80000000) < 0}]
+
+if {[catch {expr T1()} msg] && $msg eq {invalid command name "tcl::mathfunc::T1"}} {
+ testConstraint testmathfunctions 0
} else {
- set gotT1 1
+ testConstraint testmathfunctions 1
+}
+
+# Big test for correct ordering of data in [expr]
+
+proc testIEEE {} {
+ variable ieeeValues
+ binary scan [binary format dd -1.0 1.0] c* c
+ switch -exact -- $c {
+ {0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
+ # little endian
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \
+ ieeeValues(-Infinity)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \
+ ieeeValues(-Normal)
+ binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
+ ieeeValues(-Subnormal)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
+ ieeeValues(-0)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+0)
+ binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
+ ieeeValues(+Subnormal)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \
+ ieeeValues(+Normal)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
+ ieeeValues(+Infinity)
+ binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
+ ieeeValues(NaN)
+ set ieeeValues(littleEndian) 1
+ return 1
+ }
+ {-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
+ binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Infinity)
+ binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Normal)
+ binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Subnormal)
+ binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-0)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+0)
+ binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Subnormal)
+ binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Normal)
+ binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Infinity)
+ binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(NaN)
+ set ieeeValues(littleEndian) 0
+ return 1
+ }
+ default {
+ return 0
+ }
+ }
}
+testConstraint ieeeFloatingPoint [testIEEE]
# First, test all of the integer operators individually.
@@ -91,7 +152,7 @@ test expr-old-1.53 {integer operators} {
# automatic conversion to integers where needed.
test expr-old-2.1 {floating-point operators} {expr -4.2} -4.2
-test expr-old-2.2 {floating-point operators} {expr -(1.1+4.2)} -5.3
+test expr-old-2.2 {floating-point operators} {expr -(1.125+4.25)} -5.375
test expr-old-2.3 {floating-point operators} {expr +5.7} 5.7
test expr-old-2.4 {floating-point operators} {expr +--+-62.0} -62.0
test expr-old-2.5 {floating-point operators} {expr !2.1} 0
@@ -194,12 +255,8 @@ test expr-old-4.25 {string operators} {expr {"abd" ne ""}} 1
test expr-old-4.26 {string operators} {expr {"" ne ""}} 0
test expr-old-4.27 {string operators} {expr {"longerstring" eq "shorter"}} 0
test expr-old-4.28 {string operators} {expr {"longerstring" ne "shorter"}} 1
-
-# The following tests are non-portable because on some systems "+"
-# and "-" can be parsed as numbers.
-
-test expr-old-4.29 {string operators} {nonPortable} {expr {"0" == "+"}} 0
-test expr-old-4.30 {string operators} {nonPortable} {expr {"0" == "-"}} 0
+test expr-old-4.29 {string operators} {expr {"0" == "+"}} 0
+test expr-old-4.30 {string operators} {expr {"0" == "-"}} 0
test expr-old-4.31 {string operators} {expr {1?"foo":"bar"}} foo
test expr-old-4.32 {string operators} {expr {0?"foo":"bar"}} bar
@@ -406,7 +463,7 @@ test expr-old-23.8 {double quotes} {
# Numbers in various bases.
test expr-old-24.1 {numbers in different bases} {expr 0x20} 32
-test expr-old-24.2 {numbers in different bases} {expr 015} 13
+test expr-old-24.2 {numbers in different bases} {expr 0o15} 13
# Conversions between various data types.
@@ -428,7 +485,7 @@ test expr-old-25.15 {type conversions} {expr {24.1 > "24.1a"}} 0
test expr-old-25.16 {type conversions} {expr 2+2.5} 4.5
test expr-old-25.17 {type conversions} {expr 2+2.5} 4.5
test expr-old-25.18 {type conversions} {expr 2.0e2} 200.0
-test expr-old-25.19 {type conversions} {eformat} {expr 2.0e15} 2e+15
+test expr-old-25.19 {type conversions} {expr 2.0e15} 2000000000000000.0
test expr-old-25.20 {type conversions} {expr 10.0} 10.0
# Various error conditions.
@@ -436,12 +493,12 @@ test expr-old-25.20 {type conversions} {expr 10.0} 10.0
test expr-old-26.1 {error conditions} {
list [catch {expr 2+"a"} msg] $msg
} {1 {can't use non-numeric string as operand of "+"}}
-test expr-old-26.2 {error conditions} {
- list [catch {expr 2+4*} msg] $msg
-} {1 {syntax error in expression "2+4*": premature end of expression}}
-test expr-old-26.3 {error conditions} {
- list [catch {expr 2+4*(} msg] $msg
-} {1 {syntax error in expression "2+4*(": premature end of expression}}
+test expr-old-26.2 {error conditions} -body {
+ expr 2+4*
+} -returnCodes error -match glob -result *
+test expr-old-26.3 {error conditions} -body {
+ expr 2+4*(
+} -returnCodes error -match glob -result *
catch {unset _non_existent_}
test expr-old-26.4 {error conditions} {
list [catch {expr 2+$_non_existent_} msg] $msg
@@ -453,45 +510,48 @@ test expr-old-26.5 {error conditions} {
test expr-old-26.6 {error conditions} {
list [catch {expr {2+[set a]}} msg] $msg
} {1 {can't use non-numeric string as operand of "+"}}
-test expr-old-26.7 {error conditions} {
- list [catch {expr {2+(4}} msg] $msg
-} {1 {syntax error in expression "2+(4": looking for close parenthesis}}
+test expr-old-26.7 {error conditions} -body {
+ expr {2+(4}
+} -returnCodes error -match glob -result *
test expr-old-26.8 {error conditions} {
list [catch {expr 2/0} msg] $msg $errorCode
} {1 {divide by zero} {ARITH DIVZERO {divide by zero}}}
test expr-old-26.9 {error conditions} {
list [catch {expr 2%0} msg] $msg $errorCode
} {1 {divide by zero} {ARITH DIVZERO {divide by zero}}}
-test expr-old-26.10 {error conditions} {
+test expr-old-26.10a {error conditions} !ieeeFloatingPoint {
list [catch {expr 2.0/0.0} msg] $msg $errorCode
} {1 {divide by zero} {ARITH DIVZERO {divide by zero}}}
-test expr-old-26.11 {error conditions} {
- list [catch {expr 2#} msg] $msg
-} {1 {syntax error in expression "2#": extra tokens at end of expression}}
-test expr-old-26.12 {error conditions} {
- list [catch {expr a.b} msg] $msg
-} {1 {syntax error in expression "a.b": variable references require preceding $}}
+test expr-old-26.10b {error conditions} ieeeFloatingPoint {
+ list [catch {expr 2.0/0.0} msg] $msg
+} {0 Inf}
+test expr-old-26.11 {error conditions} -body {
+ expr 2#
+} -returnCodes error -match glob -result *
+test expr-old-26.12 {error conditions} -body {
+ expr a.b
+} -returnCodes error -match glob -result *
test expr-old-26.13 {error conditions} {
list [catch {expr {"a"/"b"}} msg] $msg
} {1 {can't use non-numeric string as operand of "/"}}
-test expr-old-26.14 {error conditions} {
- list [catch {expr 2:3} msg] $msg
-} {1 {syntax error in expression "2:3": extra tokens at end of expression}}
-test expr-old-26.15 {error conditions} {
- list [catch {expr a@b} msg] $msg
-} {1 {syntax error in expression "a@b": variable references require preceding $}}
+test expr-old-26.14 {error conditions} -body {
+ expr 2:3
+} -returnCodes error -match glob -result *
+test expr-old-26.15 {error conditions} -body {
+ expr a@b
+} -returnCodes error -match glob -result *
test expr-old-26.16 {error conditions} {
list [catch {expr a[b} msg] $msg
} {1 {missing close-bracket}}
-test expr-old-26.17 {error conditions} {
- list [catch {expr a`b} msg] $msg
-} {1 {syntax error in expression "a`b": variable references require preceding $}}
-test expr-old-26.18 {error conditions} {
- list [catch {expr \"a\"\{b} msg] $msg
-} {1 syntax\ error\ in\ expression\ \"\"a\"\{b\":\ extra\ tokens\ at\ end\ of\ expression}
-test expr-old-26.19 {error conditions} {
- list [catch {expr a} msg] $msg
-} {1 {syntax error in expression "a": variable references require preceding $}}
+test expr-old-26.17 {error conditions} -body {
+ expr a`b
+} -returnCodes error -match glob -result *
+test expr-old-26.18 {error conditions} -body {
+ expr \"a\"\{b
+} -returnCodes error -match glob -result *
+test expr-old-26.19 {error conditions} -body {
+ expr a
+} -returnCodes error -match glob -result *
test expr-old-26.20 {error conditions} {
list [catch expr msg] $msg
} {1 {wrong # args: should be "expr arg ?arg ...?"}}
@@ -539,12 +599,12 @@ test expr-old-27.10 {cancelled evaluation} {
set x -1.0
list [catch {expr {($x > 0) ? round(log($x)) : 0}} msg] $msg
} {0 0}
-test expr-old-27.11 {cancelled evaluation} {
- list [catch {expr {0 && foo}} msg] $msg
-} {1 {syntax error in expression "0 && foo": variable references require preceding $}}
-test expr-old-27.12 {cancelled evaluation} {
- list [catch {expr {0 ? 1 : foo}} msg] $msg
-} {1 {syntax error in expression "0 ? 1 : foo": variable references require preceding $}}
+test expr-old-27.11 {cancelled evaluation} -body {
+ expr {0 && foo}
+} -returnCodes error -match glob -result *
+test expr-old-27.12 {cancelled evaluation} -body {
+ expr {0 ? 1 : foo}
+} -returnCodes error -match glob -result *
# Tcl_ExprBool as used in "if" statements
@@ -616,12 +676,12 @@ test expr-old-28.14 {Tcl_ExprBool usage} {
# Operands enclosed in braces
test expr-old-29.1 {braces} {expr {{abc}}} abc
-test expr-old-29.2 {braces} {expr {{00010}}} 8
+test expr-old-29.2 {braces} {expr {{0o0010}}} 8
test expr-old-29.3 {braces} {expr {{3.1200000}}} 3.12
test expr-old-29.4 {braces} {expr {{a{b}{1 {2 3}}c}}} "a{b}{1 {2 3}}c"
-test expr-old-29.5 {braces} {
- list [catch {expr "\{abc"} msg] $msg
-} {1 {missing close-brace}}
+test expr-old-29.5 {braces} -body {
+ expr "\{abc"
+} -returnCodes error -match glob -result *
# Very long values
@@ -642,15 +702,15 @@ test expr-old-30.2 {long values} {
test expr-old-31.1 {multiple arguments to expr command} {
expr 4 + ( 6 *12) -3
} 73
-test expr-old-31.2 {multiple arguments to expr command} {
- list [catch {expr 2 + (3 + 4} msg] $msg
-} {1 {syntax error in expression "2 + (3 + 4": looking for close parenthesis}}
-test expr-old-31.3 {multiple arguments to expr command} {
- list [catch {expr 2 + 3 +} msg] $msg
-} {1 {syntax error in expression "2 + 3 +": premature end of expression}}
-test expr-old-31.4 {multiple arguments to expr command} {
- list [catch {expr 2 + 3 )} msg] $msg
-} {1 {syntax error in expression "2 + 3 )": extra tokens at end of expression}}
+test expr-old-31.2 {multiple arguments to expr command} -body {
+ expr 2 + (3 + 4
+} -returnCodes error -match glob -result *
+test expr-old-31.3 {multiple arguments to expr command} -body {
+ expr 2 + 3 +
+} -returnCodes error -match glob -result *
+test expr-old-31.4 {multiple arguments to expr command} -body {
+ expr 2 + 3 )
+} -returnCodes error -match glob -result *
# Math functions
@@ -727,17 +787,13 @@ test expr-old-32.24 {math functions in expressions} {
format %.6g [expr abs(66)]
} {66}
-# The following test is different for 32-bit versus 64-bit architectures.
+test expr-old-32.25a {math functions in expressions} {
+ expr abs(0x8000000000000000)
+} [expr 1<<63]
-if {0x80000000 > 0} {
- test expr-old-32.25 {math functions in expressions} {nonPortable} {
- list [catch {expr abs(0x8000000000000000)} msg] $msg
- } {1 {integer value too large to represent}}
-} else {
- test expr-old-32.25 {math functions in expressions} {nonPortable} {
- list [catch {expr abs(0x80000000)} msg] $msg
- } {1 {integer value too large to represent}}
-}
+test expr-old-32.25b {math functions in expressions} {
+ expr abs(0x80000000)
+} 2147483648
test expr-old-32.26 {math functions in expressions} {
expr double(1)
@@ -761,11 +817,11 @@ test expr-old-32.32 {math functions in expressions} {
expr int(-1.6)
} {-1}
test expr-old-32.33 {math functions in expressions} {
- list [catch {expr int(1e60)} msg] $msg
-} {1 {integer value too large to represent}}
+ expr int(1e60)
+} 0
test expr-old-32.34 {math functions in expressions} {
- list [catch {expr int(-1e60)} msg] $msg
-} {1 {integer value too large to represent}}
+ expr int(-1e60)
+} 0
test expr-old-32.35 {math functions in expressions} {
expr round(1.49)
} {1}
@@ -779,40 +835,38 @@ test expr-old-32.38 {math functions in expressions} {
expr round(-1.51)
} {-2}
test expr-old-32.39 {math functions in expressions} {
- list [catch {expr round(1e60)} msg] $msg
-} {1 {integer value too large to represent}}
+ expr round(1e60)
+} 999999999999999949387135297074018866963645011013410073083904
test expr-old-32.40 {math functions in expressions} {
- list [catch {expr round(-1e60)} msg] $msg
-} {1 {integer value too large to represent}}
+ expr round(-1e60)
+} -999999999999999949387135297074018866963645011013410073083904
test expr-old-32.41 {math functions in expressions} {
list [catch {expr pow(1.0 + 3.0 - 2, .8 * 5)} msg] $msg
} {0 16.0}
test expr-old-32.42 {math functions in expressions} {
list [catch {expr hypot(5*.8,3)} msg] $msg
} {0 5.0}
-if $gotT1 {
- test expr-old-32.43 {math functions in expressions} {
- expr 2*T1()
- } 246
- test expr-old-32.44 {math functions in expressions} {
- expr T2()*3
- } 1035
-}
+test expr-old-32.43 {math functions in expressions} testmathfunctions {
+ expr 2*T1()
+} 246
+test expr-old-32.44 {math functions in expressions} testmathfunctions {
+ expr T2()*3
+} 1035
test expr-old-32.45 {math functions in expressions} {
expr (0 <= rand()) && (rand() < 1)
} {1}
-test expr-old-32.46 {math functions in expressions} {
+test expr-old-32.46 {math functions in expressions} -body {
list [catch {expr rand(24)} msg] $msg
-} {1 {too many arguments for math function}}
-test expr-old-32.47 {math functions in expressions} {
+} -match glob -result {1 {too many arguments for math function*}}
+test expr-old-32.47 {math functions in expressions} -body {
list [catch {expr srand()} msg] $msg
-} {1 {too few arguments for math function}}
-test expr-old-32.48 {math functions in expressions} {
- list [catch {expr srand(3.79)} msg] $msg
-} {1 {expected integer but got "3.79"}}
-test expr-old-32.49 {math functions in expressions} {
- list [catch {expr srand("")} msg] $msg
-} {1 {argument to math function didn't have numeric value}}
+} -match glob -result {1 {too few arguments for math function*}}
+test expr-old-32.48 {math functions in expressions} -body {
+ expr srand(3.79)
+} -returnCodes error -match glob -result *
+test expr-old-32.49 {math functions in expressions} -body {
+ expr srand("")
+} -returnCodes error -match glob -result *
test expr-old-32.50 {math functions in expressions} {
set result [expr round(srand(12345) * 1000)]
for {set i 0} {$i < 10} {incr i} {
@@ -820,9 +874,9 @@ test expr-old-32.50 {math functions in expressions} {
}
set result
} {97 834 948 36 12 51 766 585 914 784 333}
-test expr-old-32.51 {math functions in expressions} {
- list [catch {expr {srand([lindex "6ty" 0])}} msg] $msg
-} {1 {argument to math function didn't have numeric value}}
+test expr-old-32.51 {math functions in expressions} -body {
+ expr {srand([lindex "6ty" 0])}
+} -returnCodes error -match glob -result *
test expr-old-32.52 {math functions in expressions} {
expr {srand(int(1<<37)) < 1}
} {1}
@@ -843,65 +897,70 @@ test expr-old-33.4 {conversions and fancy args to math functions} {
format %.6g [expr cos(acos(0.1))]
} 0.1
-test expr-old-34.1 {errors in math functions} {
+test expr-old-34.1 {errors in math functions} -body {
list [catch {expr func_2(1.0)} msg] $msg
-} {1 {unknown math function "func_2"}}
-test expr-old-34.2 {errors in math functions} {
- list [catch {expr func|(1.0)} msg] $msg
-} {1 {syntax error in expression "func|(1.0)": variable references require preceding $}}
+} -match glob -result {1 {* "*func_2"}}
+test expr-old-34.2 {errors in math functions} -body {
+ expr func|(1.0)
+} -returnCodes error -match glob -result *
test expr-old-34.3 {errors in math functions} {
list [catch {expr {hypot("a b", 2.0)}} msg] $msg
-} {1 {argument to math function didn't have numeric value}}
-test expr-old-34.4 {errors in math functions} {
- list [catch {expr hypot(1.0 2.0)} msg] $msg
-} {1 {syntax error in expression "hypot(1.0 2.0)": missing close parenthesis at end of function call}}
-test expr-old-34.5 {errors in math functions} {
- list [catch {expr hypot(1.0, 2.0} msg] $msg
-} {1 {syntax error in expression "hypot(1.0, 2.0": missing close parenthesis at end of function call}}
-test expr-old-34.6 {errors in math functions} {
- list [catch {expr hypot(1.0 ,} msg] $msg
-} {1 {syntax error in expression "hypot(1.0 ,": premature end of expression}}
-test expr-old-34.7 {errors in math functions} {
+} {1 {expected floating-point number but got "a b"}}
+test expr-old-34.4 {errors in math functions} -body {
+ expr hypot(1.0 2.0)
+} -returnCodes error -match glob -result *
+test expr-old-34.5 {errors in math functions} -body {
+ expr hypot(1.0, 2.0
+} -returnCodes error -match glob -result *
+test expr-old-34.6 {errors in math functions} -body {
+ expr hypot(1.0 ,
+} -returnCodes error -match glob -result *
+test expr-old-34.7 {errors in math functions} -body {
list [catch {expr hypot(1.0)} msg] $msg
-} {1 {too few arguments for math function}}
-test expr-old-34.8 {errors in math functions} {
+} -match glob -result {1 {too few arguments for math function*}}
+test expr-old-34.8 {errors in math functions} -body {
list [catch {expr hypot(1.0, 2.0, 3.0)} msg] $msg
-} {1 {too many arguments for math function}}
+} -match glob -result {1 {too many arguments for math function*}}
test expr-old-34.9 {errors in math functions} {
list [catch {expr acos(-2.0)} msg] $msg $errorCode
} {1 {domain error: argument not in valid range} {ARITH DOMAIN {domain error: argument not in valid range}}}
-test expr-old-34.10 {errors in math functions} {nonPortable} {
- list [catch {expr pow(-3, 1000001)} msg] $msg $errorCode
-} {1 {floating-point value too large to represent} {ARITH OVERFLOW {floating-point value too large to represent}}}
-test expr-old-34.11 {errors in math functions} {
+test expr-old-34.10 {errors in math functions} {
+ list [catch {expr pow(-3, 1000001)} msg] $msg
+} {0 -Inf}
+test expr-old-34.11a {errors in math functions} !ieeeFloatingPoint {
list [catch {expr pow(3, 1000001)} msg] $msg $errorCode
} {1 {floating-point value too large to represent} {ARITH OVERFLOW {floating-point value too large to represent}}}
-test expr-old-34.12 {errors in math functions} {
+test expr-old-34.11b {errors in math functions} ieeeFloatingPoint {
+ list [catch {expr pow(3, 1000001)} msg] $msg
+} {0 Inf}
+test expr-old-34.12a {errors in math functions} !ieeeFloatingPoint {
list [catch {expr -14.0*exp(100000)} msg] $msg $errorCode
} {1 {floating-point value too large to represent} {ARITH OVERFLOW {floating-point value too large to represent}}}
+test expr-old-34.12b {errors in math functions} ieeeFloatingPoint {
+ list [catch {expr -14.0*exp(100000)} msg] $msg
+} {0 -Inf}
test expr-old-34.13 {errors in math functions} {
- list [catch {expr int(1.0e30)} msg] $msg $errorCode
-} {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}}
+ expr wide(1.0e30)
+} 5076964154930102272
test expr-old-34.14 {errors in math functions} {
- list [catch {expr int(-1.0e30)} msg] $msg $errorCode
-} {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}}
+ expr wide(-1.0e30)
+} -5076964154930102272
test expr-old-34.15 {errors in math functions} {
- list [catch {expr round(1.0e30)} msg] $msg $errorCode
-} {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}}
+ expr round(1.0e30)
+} 1000000000000000019884624838656
test expr-old-34.16 {errors in math functions} {
- list [catch {expr round(-1.0e30)} msg] $msg $errorCode
-} {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}}
-if $gotT1 {
- test expr-old-34.17 {errors in math functions} {
- list [catch {expr T1(4)} msg] $msg
- } {1 {too many arguments for math function}}
-}
+ expr round(-1.0e30)
+} -1000000000000000019884624838656
+test expr-old-34.17 {errors in math functions} -constraints testmathfunctions \
+ -body {
+ list [catch {expr T1(4)} msg] $msg
+ } -match glob -result {1 {too many arguments for math function*}}
test expr-old-36.1 {ExprLooksLikeInt procedure} -body {
- expr 0289
+ expr 0o289
} -returnCodes error -match glob -result {*invalid octal number*}
test expr-old-36.2 {ExprLooksLikeInt procedure} {
- set x 0289
+ set x 0o289
list [catch {expr {$x+1}} msg] $msg
} {1 {can't use invalid octal number as operand of "+"}}
test expr-old-36.3 {ExprLooksLikeInt procedure} {
@@ -919,7 +978,7 @@ test expr-old-36.6 {ExprLooksLikeInt procedure} {
set x { -22}
list [catch {expr {$x+1}} msg] $msg
} {0 -21}
-test expr-old-36.7 {ExprLooksLikeInt procedure} {nonPortable unixOnly} {
+test expr-old-36.7 {ExprLooksLikeInt procedure} {
list [catch {expr nan} msg] $msg
} {1 {domain error: argument not in valid range}}
test expr-old-36.8 {ExprLooksLikeInt procedure} {
@@ -928,16 +987,16 @@ test expr-old-36.8 {ExprLooksLikeInt procedure} {
test expr-old-36.9 {ExprLooksLikeInt procedure} {
list [catch {expr 24E1} msg] $msg
} {0 240.0}
-test expr-old-36.10 {ExprLooksLikeInt procedure} {nonPortable unixOnly} {
- list [catch {expr 78e} msg] $msg
-} {1 {syntax error in expression "78e"}}
+test expr-old-36.10 {ExprLooksLikeInt procedure} -body {
+ expr 78e
+} -returnCodes error -match glob -result *
# test for [Bug #542588]
test expr-old-36.11 {ExprLooksLikeInt procedure} {
# define a "too large integer"; this one works also for 64bit arith
set x 665802003400000000000000
- list [catch {expr {$x+1}} msg] $msg
-} {1 {can't use integer value too large to represent as operand of "+"}}
+ expr {$x+1}
+} 665802003400000000000001
# tests for [Bug #587140]
test expr-old-36.12 {ExprLooksLikeInt procedure} {
@@ -950,35 +1009,128 @@ test expr-old-36.13 {ExprLooksLikeInt procedure} {
} {1 {can't use non-numeric string as operand of "+"}}
test expr-old-36.14 {ExprLooksLikeInt procedure} {
set x "123456789012345678901234567890 "
- list [catch {expr {$x+1}} msg] $msg
-} {1 {can't use integer value too large to represent as operand of "+"}}
+ expr {$x+1}
+} 123456789012345678901234567891
test expr-old-36.15 {ExprLooksLikeInt procedure} {
- set x "099 "
+ set x "0o99 "
list [catch {expr {$x+1}} msg] $msg
} {1 {can't use invalid octal number as operand of "+"}}
test expr-old-36.16 {ExprLooksLikeInt procedure} {
set x " 0xffffffffffffffffffffffffffffffffffffff "
- list [catch {expr {$x+1}} msg] $msg
-} {1 {can't use integer value too large to represent as operand of "+"}}
+ expr {$x+1}
+} [expr 0x100000000000000000000000000000000000000]
-if {[info commands testexprlong] == {}} {
- puts "This application hasn't been compiled with the \"testexprlong\""
- puts "command, so I can't test Tcl_ExprLong etc."
-} else {
-test expr-old-37.1 {Check that Tcl_ExprLong doesn't modify interpreter result if no error} {
- testexprlong
+test expr-old-37.1 {Check that Tcl_ExprLong doesn't modify interpreter result if no error} testexprlong {
+ testexprlong 4+1
} {This is a result: 5}
-}
-
-if {[info commands testexprstring] == {}} {
- puts "This application hasn't been compiled with the \"testexprstring\""
- puts "command, so I can't test Tcl_ExprString etc."
-} else {
-test expr-old-38.1 {Verify Tcl_ExprString's basic operation} {
+#Check for [Bug 1109484]
+test expr-old-37.2 {Tcl_ExprLong handles wide ints gracefully} testexprlong {
+ testexprlong wide(1)+2
+} {This is a result: 3}
+
+test expr-old-37.3 {Tcl_ExprLong on the empty string} testexprlong {
+ testexprlong ""
+} {This is a result: 0}
+test expr-old-37.4 {Tcl_ExprLong coerces doubles} testexprlong {
+ testexprlong 3+.14159
+} {This is a result: 3}
+test expr-old-37.5 {Tcl_ExprLong handles overflows} {testexprlong longIs32bit} {
+ testexprlong 0x80000000
+} {This is a result: -2147483648}
+test expr-old-37.6 {Tcl_ExprLong handles overflows} {testexprlong longIs32bit} {
+ testexprlong 0xffffffff
+} {This is a result: -1}
+test expr-old-37.7 {Tcl_ExprLong handles overflows} \
+ -constraints {testexprlong longIs32bit} \
+ -match glob \
+ -body {
+ list [catch {testexprlong 0x100000000} result] $result
+ } \
+ -result {1 {integer value too large to represent*}}
+test expr-old-37.8 {Tcl_ExprLong handles overflows} testexprlong {
+ testexprlong -0x80000000
+} {This is a result: -2147483648}
+test expr-old-37.9 {Tcl_ExprLong handles overflows} {testexprlong longIs32bit} {
+ testexprlong -0xffffffff
+} {This is a result: 1}
+test expr-old-37.10 {Tcl_ExprLong handles overflows} \
+ -constraints {testexprlong longIs32bit} \
+ -match glob \
+ -body {
+ list [catch {testexprlong -0x100000000} result] $result
+ } \
+ -result {1 {integer value too large to represent*}}
+test expr-old-37.11 {Tcl_ExprLong handles overflows} {testexprlong longIs32bit} {
+ testexprlong 2147483648.
+} {This is a result: -2147483648}
+test expr-old-37.12 {Tcl_ExprLong handles overflows} {testexprlong longIs32bit} {
+ testexprlong 4294967295.
+} {This is a result: -1}
+test expr-old-37.13 {Tcl_ExprLong handles overflows} \
+ -constraints {testexprlong longIs32bit} \
+ -match glob \
+ -body {
+ list [catch {testexprlong 4294967296.} result] $result
+ } \
+ -result {1 {integer value too large to represent*}}
+test expr-old-37.14 {Tcl_ExprLong handles overflows} testexprlong {
+ testexprlong -2147483648.
+} {This is a result: -2147483648}
+test expr-old-37.15 {Tcl_ExprLong handles overflows} {testexprlong longIs32bit} {
+ testexprlong -4294967295.
+} {This is a result: 1}
+test expr-old-37.16 {Tcl_ExprLong handles overflows} \
+ -constraints {testexprlong longIs32bit} \
+ -match glob \
+ -body {
+ list [catch {testexprlong 4294967296.} result] $result
+ } \
+ -result {1 {integer value too large to represent*}}
+
+test expr-old-37.17 {Check that Tcl_ExprDouble doesn't modify interpreter result if no error} testexprdouble {
+ testexprdouble 4.+1.
+} {This is a result: 5.0}
+#Check for [Bug 1109484]
+test expr-old-37.18 {Tcl_ExprDouble on the empty string} testexprdouble {
+ testexprdouble ""
+} {This is a result: 0.0}
+test expr-old-37.19 {Tcl_ExprDouble coerces wides} testexprdouble {
+ testexprdouble 1[string repeat 0 17]
+} {This is a result: 1e+17}
+test expr-old-37.20 {Tcl_ExprDouble coerces bignums} testexprdouble {
+ testexprdouble 1[string repeat 0 38]
+} {This is a result: 1e+38}
+test expr-old-37.21 {Tcl_ExprDouble handles overflows} testexprdouble {
+ testexprdouble 17976931348623157[string repeat 0 292].
+} {This is a result: 1.7976931348623157e+308}
+test expr-old-37.22 {Tcl_ExprDouble handles overflows that look like int} \
+ testexprdouble {
+ testexprdouble 17976931348623157[string repeat 0 292]
+ } {This is a result: 1.7976931348623157e+308}
+test expr-old-37.23 {Tcl_ExprDouble handles overflows} \
+ ieeeFloatingPoint&&testexprdouble {
+ testexprdouble 17976931348623165[string repeat 0 292].
+ } {This is a result: Inf}
+test expr-old-37.24 {Tcl_ExprDouble handles overflows that look like int} \
+ ieeeFloatingPoint&&testexprdouble {
+ testexprdouble 17976931348623165[string repeat 0 292]
+ } {This is a result: Inf}
+test expr-old-37.25 {Tcl_ExprDouble and NaN} \
+ {ieeeFloatingPoint testexprdouble} {
+ list [catch {testexprdouble 0.0/0.0} result] $result
+ } {1 {domain error: argument not in valid range}}
+
+test expr-old-38.1 {Verify Tcl_ExprString's basic operation} -constraints {testexprstring} -body {
list [testexprstring "1+4"] [testexprstring "2*3+4.2"] \
- [catch {testexprstring "1+"} msg] $msg
-} {5 10.2 1 {syntax error in expression "1+": premature end of expression}}
-}
+ [catch {testexprstring "1+"} msg] $msg
+} -match glob -result {5 10.2 1 *}
+test expr-old-38.2 {Tcl_ExprString} testexprstring {
+ # This one is "magical"
+ testexprstring {}
+} 0
+test expr-old-38.3 {Tcl_ExprString} -constraints testexprstring -body {
+ testexprstring { }
+} -returnCodes error -match glob -result *
#
# Test for bug #908375: rounding numbers that do not fit in a
@@ -995,6 +1147,48 @@ test expr-old-39.1 {Rounding with wide result} {
} {1 1}
unset -nocomplain x y
+#
+# TIP #255 min and max math functions
+#
+
+test expr-old-40.1 {min math function} -body {
+ expr {min(0)}
+} -result 0
+test expr-old-40.2 {min math function} -body {
+ expr {min(0.0)}
+} -result 0.0
+test expr-old-40.3 {min math function} -body {
+ list [catch {expr {min()}} msg] $msg
+} -result {1 {too few arguments to math function "min"}}
+test expr-old-40.4 {min math function} -body {
+ expr {min(wide(-1) << 30, 4.5, -10)}
+} -result [expr {wide(-1) << 30}]
+test expr-old-40.5 {min math function} -body {
+ expr {min("a", 0)}
+} -returnCodes error -match glob -result *
+test expr-old-40.6 {min math function} -body {
+ expr {min(300, "0xFF")}
+} -result 255
+
+test expr-old-41.1 {max math function} -body {
+ expr {max(0)}
+} -result 0
+test expr-old-41.2 {max math function} -body {
+ expr {max(0.0)}
+} -result 0.0
+test expr-old-41.3 {max math function} -body {
+ list [catch {expr {max()}} msg] $msg
+} -result {1 {too few arguments to math function "max"}}
+test expr-old-41.4 {max math function} -body {
+ expr {max(wide(1) << 30, 4.5, -10)}
+} -result [expr {wide(1) << 30}]
+test expr-old-41.5 {max math function} -body {
+ expr {max("a", 0)}
+} -returnCodes error -match glob -result *
+test expr-old-41.6 {max math function} -body {
+ expr {max(200, "0xFF")}
+} -result 255
+
# Special test for Pentium arithmetic bug of 1994:
if {(4195835.0 - (4195835.0/3145727.0)*3145727.0) == 256.0} {
@@ -1007,3 +1201,7 @@ if {(4195835.0 - (4195835.0/3145727.0)*3145727.0) == 256.0} {
# cleanup
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/expr.test b/tests/expr.test
index 053b33a..42d0c79 100644
--- a/tests/expr.test
+++ b/tests/expr.test
@@ -11,15 +11,84 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2.1
namespace import -force ::tcltest::*
}
-testConstraint registeredMathFuncs [expr {
- ([catch {expr T1()} msg] != 1) || ($msg ne {unknown math function "T1"})
+testConstraint testmathfunctions [expr {
+ ([catch {expr T1()} msg] != 1) || ($msg ne {invalid command name "tcl::mathfunc::T1"})
}]
-testConstraint wideIs64bit [expr {(0x80000000 > 0) && (0x8000000000000000 < 0)}]
+# Determine if "long int" type is a 32 bit number and if the wide
+# type is a 64 bit number on this machine.
+
+testConstraint longIs32bit [expr {int(0x80000000) < 0}]
+testConstraint longIs64bit [expr {int(0x8000000000000000) < 0}]
+testConstraint wideIs64bit \
+ [expr {(wide(0x80000000) > 0) && (wide(0x8000000000000000) < 0)}]
+
+# Big test for correct ordering of data in [expr]
+
+proc testIEEE {} {
+ variable ieeeValues
+ binary scan [binary format dd -1.0 1.0] c* c
+ switch -exact -- $c {
+ {0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
+ # little endian
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \
+ ieeeValues(-Infinity)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \
+ ieeeValues(-Normal)
+ binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
+ ieeeValues(-Subnormal)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
+ ieeeValues(-0)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+0)
+ binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
+ ieeeValues(+Subnormal)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \
+ ieeeValues(+Normal)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
+ ieeeValues(+Infinity)
+ binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
+ ieeeValues(NaN)
+ binary scan \x00\x00\x00\x00\x00\x00\xf8\xff d \
+ ieeeValues(-NaN)
+ set ieeeValues(littleEndian) 1
+ return 1
+ }
+ {-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
+ binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Infinity)
+ binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Normal)
+ binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Subnormal)
+ binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-0)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+0)
+ binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Subnormal)
+ binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Normal)
+ binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Infinity)
+ binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(NaN)
+ binary scan \xff\xf8\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-NaN)
+ set ieeeValues(littleEndian) 0
+ return 1
+ }
+ default {
+ return 0
+ }
+ }
+}
+
+testConstraint ieeeFloatingPoint [testIEEE]
# procedures used below
proc put_hello_char {c} {
@@ -62,7 +131,9 @@ proc do_twelve_days {} {
global xxx
set xxx ""
12days 1 1 1
- string length $xxx
+ set result [string length $xxx]
+ unset xxx
+ return $result
}
# start of tests
@@ -130,60 +201,49 @@ test expr-1.15 {TclCompileExprCmd: second level of substitutions in expr with co
test expr-2.1 {TclCompileExpr: are builtin functions registered?} {
expr double(5*[llength "6 2"])
} 10.0
-test expr-2.2 {TclCompileExpr: error in expr} {
- catch {expr 2**3} msg
- set msg
-} {syntax error in expression "2**3": unexpected operator *}
-test expr-2.3 {TclCompileExpr: junk after legal expr} {
- catch {expr 7*[llength "a b"]foo} msg
- set msg
-} {syntax error in expression "7*2foo": extra tokens at end of expression}
+test expr-2.2 {TclCompileExpr: error in expr} -body {
+ expr 2***3
+} -returnCodes error -match glob -result *
+test expr-2.3 {TclCompileExpr: junk after legal expr} -body {
+ expr 7*[llength "a b"]foo
+} -returnCodes error -match glob -result *
test expr-2.4 {TclCompileExpr: numeric expr string rep == formatted int rep} {
expr {0001}
} 1
test expr-3.1 {CompileCondExpr: just lor expr} {expr 3||0} 1
-test expr-3.2 {CompileCondExpr: error in lor expr} {
- catch {expr x||3} msg
- set msg
-} {syntax error in expression "x||3": variable references require preceding $}
+test expr-3.2 {CompileCondExpr: error in lor expr} -body {
+ expr x||3
+} -returnCodes error -match glob -result *
test expr-3.3 {CompileCondExpr: test true arm} {expr 3>2?44:66} 44
-test expr-3.4 {CompileCondExpr: error compiling true arm} {
- catch {expr 3>2?2**3:66} msg
- set msg
-} {syntax error in expression "3>2?2**3:66": unexpected operator *}
+test expr-3.4 {CompileCondExpr: error compiling true arm} -body {
+ expr 3>2?2***3:66
+} -returnCodes error -match glob -result *
test expr-3.5 {CompileCondExpr: test false arm} {expr 2>3?44:66} 66
-test expr-3.6 {CompileCondExpr: error compiling false arm} {
- catch {expr 2>3?44:2**3} msg
- set msg
-} {syntax error in expression "2>3?44:2**3": unexpected operator *}
-test expr-3.7 {CompileCondExpr: long arms & nested cond exprs} {unixOnly nonPortable} {
- puts "Note: doing test expr-3.7 which can take several minutes to run"
+test expr-3.6 {CompileCondExpr: error compiling false arm} -body {
+ expr 2>3?44:2***3
+} -returnCodes error -match glob -result *
+test expr-3.7 {CompileCondExpr: long arms & nested cond exprs} {
hello_world
} {Hello world}
-catch {unset xxx}
-test expr-3.8 {CompileCondExpr: long arms & nested cond exprs} {unixOnly nonPortable} {
- puts "Note: doing test expr-3.8 which can take several minutes to run"
+test expr-3.8 {CompileCondExpr: long arms & nested cond exprs} unix {
+ # Fails with a stack overflow on threaded Windows builds
do_twelve_days
} 2358
-catch {unset xxx}
test expr-4.1 {CompileLorExpr: just land expr} {expr 1.3&&3.3} 1
-test expr-4.2 {CompileLorExpr: error in land expr} {
- catch {expr x&&3} msg
- set msg
-} {syntax error in expression "x&&3": variable references require preceding $}
+test expr-4.2 {CompileLorExpr: error in land expr} -body {
+ expr x&&3
+} -returnCodes error -match glob -result *
test expr-4.3 {CompileLorExpr: simple lor exprs} {expr 0||1.0} 1
test expr-4.4 {CompileLorExpr: simple lor exprs} {expr 3.0||0.0} 1
test expr-4.5 {CompileLorExpr: simple lor exprs} {expr 0||0||1} 1
-test expr-4.6 {CompileLorExpr: error compiling lor arm} {
- catch {expr 2**3||4.0} msg
- set msg
-} {syntax error in expression "2**3||4.0": unexpected operator *}
-test expr-4.7 {CompileLorExpr: error compiling lor arm} {
- catch {expr 1.3||2**3} msg
- set msg
-} {syntax error in expression "1.3||2**3": unexpected operator *}
+test expr-4.6 {CompileLorExpr: error compiling lor arm} -body {
+ expr 2***3||4.0
+} -returnCodes error -match glob -result *
+test expr-4.7 {CompileLorExpr: error compiling lor arm} -body {
+ expr 1.3||2***3
+} -returnCodes error -match glob -result *
test expr-4.8 {CompileLorExpr: error compiling lor arms} {
list [catch {expr {"a"||"b"}} msg] $msg
} {1 {expected boolean value but got "a"}}
@@ -192,24 +252,30 @@ test expr-4.9 {CompileLorExpr: long lor arm} {
set i 7
expr {[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]}
} 1
+test expr-4.10 {CompileLorExpr: error compiling ! operand} {
+ list [catch {expr {!"a"}} msg] $msg
+} {1 {can't use non-numeric string as operand of "!"}}
+test expr-4.11 {CompileLorExpr: error compiling land arms} {
+ list [catch {expr {"a"||0}} msg] $msg
+} {1 {expected boolean value but got "a"}}
+test expr-4.12 {CompileLorExpr: error compiling land arms} {
+ list [catch {expr {0||"a"}} msg] $msg
+} {1 {expected boolean value but got "a"}}
test expr-5.1 {CompileLandExpr: just bitor expr} {expr 7|0x13} 23
-test expr-5.2 {CompileLandExpr: error in bitor expr} {
- catch {expr x|3} msg
- set msg
-} {syntax error in expression "x|3": variable references require preceding $}
+test expr-5.2 {CompileLandExpr: error in bitor expr} -body {
+ expr x|3
+} -returnCodes error -match glob -result *
test expr-5.3 {CompileLandExpr: simple land exprs} {expr 0&&1.0} 0
test expr-5.4 {CompileLandExpr: simple land exprs} {expr 0&&0} 0
test expr-5.5 {CompileLandExpr: simple land exprs} {expr 3.0&&1.2} 1
test expr-5.6 {CompileLandExpr: simple land exprs} {expr 1&&1&&2} 1
-test expr-5.7 {CompileLandExpr: error compiling land arm} {
- catch {expr 2**3&&4.0} msg
- set msg
-} {syntax error in expression "2**3&&4.0": unexpected operator *}
-test expr-5.8 {CompileLandExpr: error compiling land arm} {
- catch {expr 1.3&&2**3} msg
- set msg
-} {syntax error in expression "1.3&&2**3": unexpected operator *}
+test expr-5.7 {CompileLandExpr: error compiling land arm} -body {
+ expr 2***3&&4.0
+} -returnCodes error -match glob -result *
+test expr-5.8 {CompileLandExpr: error compiling land arm} -body {
+ expr 1.3&&2***3
+} -returnCodes error -match glob -result *
test expr-5.9 {CompileLandExpr: error compiling land arm} {
list [catch {expr {"a"&&"b"}} msg] $msg
} {1 {expected boolean value but got "a"}}
@@ -220,22 +286,19 @@ test expr-5.10 {CompileLandExpr: long land arms} {
} 1
test expr-6.1 {CompileBitXorExpr: just bitand expr} {expr 7&0x13} 3
-test expr-6.2 {CompileBitXorExpr: error in bitand expr} {
- catch {expr x|3} msg
- set msg
-} {syntax error in expression "x|3": variable references require preceding $}
+test expr-6.2 {CompileBitXorExpr: error in bitand expr} -body {
+ expr x|3
+} -returnCodes error -match glob -result *
test expr-6.3 {CompileBitXorExpr: simple bitxor exprs} {expr 7^0x13} 20
test expr-6.4 {CompileBitXorExpr: simple bitxor exprs} {expr 3^0x10} 19
test expr-6.5 {CompileBitXorExpr: simple bitxor exprs} {expr 0^7} 7
test expr-6.6 {CompileBitXorExpr: simple bitxor exprs} {expr -1^7} -8
-test expr-6.7 {CompileBitXorExpr: error compiling bitxor arm} {
- catch {expr 2**3|6} msg
- set msg
-} {syntax error in expression "2**3|6": unexpected operator *}
-test expr-6.8 {CompileBitXorExpr: error compiling bitxor arm} {
- catch {expr 2^x} msg
- set msg
-} {syntax error in expression "2^x": variable references require preceding $}
+test expr-6.7 {CompileBitXorExpr: error compiling bitxor arm} -body {
+ expr 2***3|6
+} -returnCodes error -match glob -result *
+test expr-6.8 {CompileBitXorExpr: error compiling bitxor arm} -body {
+ expr 2^x
+} -returnCodes error -match glob -result *
test expr-6.9 {CompileBitXorExpr: runtime error in bitxor arm} {
list [catch {expr {24.0^3}} msg] $msg
} {1 {can't use floating-point value as operand of "^"}}
@@ -247,22 +310,19 @@ test expr-7.1 {CompileBitAndExpr: just equality expr} {expr 3==2} 0
test expr-7.2 {CompileBitAndExpr: just equality expr} {expr 2.0==2} 1
test expr-7.3 {CompileBitAndExpr: just equality expr} {expr 3.2!=2.2} 1
test expr-7.4 {CompileBitAndExpr: just equality expr} {expr {"abc" == "abd"}} 0
-test expr-7.5 {CompileBitAndExpr: error in equality expr} {
- catch {expr x==3} msg
- set msg
-} {syntax error in expression "x==3": variable references require preceding $}
+test expr-7.5 {CompileBitAndExpr: error in equality expr} -body {
+ expr x==3
+} -returnCodes error -match glob -result *
test expr-7.6 {CompileBitAndExpr: simple bitand exprs} {expr 7&0x13} 3
test expr-7.7 {CompileBitAndExpr: simple bitand exprs} {expr 0xf2&0x53} 82
test expr-7.8 {CompileBitAndExpr: simple bitand exprs} {expr 3&6} 2
test expr-7.9 {CompileBitAndExpr: simple bitand exprs} {expr -1&-7} -7
-test expr-7.10 {CompileBitAndExpr: error compiling bitand arm} {
- catch {expr 2**3&6} msg
- set msg
-} {syntax error in expression "2**3&6": unexpected operator *}
-test expr-7.11 {CompileBitAndExpr: error compiling bitand arm} {
- catch {expr 2&x} msg
- set msg
-} {syntax error in expression "2&x": variable references require preceding $}
+test expr-7.10 {CompileBitAndExpr: error compiling bitand arm} -body {
+ expr 2***3&6
+} -returnCodes error -match glob -result *
+test expr-7.11 {CompileBitAndExpr: error compiling bitand arm} -body {
+ expr 2&x
+} -returnCodes error -match glob -result *
test expr-7.12 {CompileBitAndExpr: runtime error in bitand arm} {
list [catch {expr {24.0&3}} msg] $msg
} {1 {can't use floating-point value as operand of "&"}}
@@ -271,31 +331,27 @@ test expr-7.13 {CompileBitAndExpr: runtime error in bitand arm} {
} {1 {can't use non-numeric string as operand of "&"}}
test expr-7.14 {CompileBitAndExpr: equality expr} {expr 3eq2} 0
test expr-7.18 {CompileBitAndExpr: equality expr} {expr {"abc" eq "abd"}} 0
-test expr-7.20 {CompileBitAndExpr: error in equality expr} {
- catch {expr xne3} msg
- set msg
-} {syntax error in expression "xne3": variable references require preceding $}
+test expr-7.20 {CompileBitAndExpr: error in equality expr} -body {
+ expr xne3
+} -returnCodes error -match glob -result *
test expr-8.1 {CompileEqualityExpr: just relational expr} {expr 3>=2} 1
test expr-8.2 {CompileEqualityExpr: just relational expr} {expr 2<=2.1} 1
test expr-8.3 {CompileEqualityExpr: just relational expr} {expr 3.2>"2.2"} 1
test expr-8.4 {CompileEqualityExpr: just relational expr} {expr {"0y"<"0x12"}} 0
-test expr-8.5 {CompileEqualityExpr: error in relational expr} {
- catch {expr x>3} msg
- set msg
-} {syntax error in expression "x>3": variable references require preceding $}
+test expr-8.5 {CompileEqualityExpr: error in relational expr} -body {
+ expr x>3
+} -returnCodes error -match glob -result *
test expr-8.6 {CompileEqualityExpr: simple equality exprs} {expr 7==0x13} 0
test expr-8.7 {CompileEqualityExpr: simple equality exprs} {expr -0xf2!=0x53} 1
test expr-8.8 {CompileEqualityExpr: simple equality exprs} {expr {"12398712938788234-1298379" != ""}} 1
test expr-8.9 {CompileEqualityExpr: simple equality exprs} {expr -1!="abc"} 1
-test expr-8.10 {CompileEqualityExpr: error compiling equality arm} {
- catch {expr 2**3==6} msg
- set msg
-} {syntax error in expression "2**3==6": unexpected operator *}
-test expr-8.11 {CompileEqualityExpr: error compiling equality arm} {
- catch {expr 2!=x} msg
- set msg
-} {syntax error in expression "2!=x": variable references require preceding $}
+test expr-8.10 {CompileEqualityExpr: error compiling equality arm} -body {
+ expr 2***3==6
+} -returnCodes error -match glob -result *
+test expr-8.11 {CompileEqualityExpr: error compiling equality arm} -body {
+ expr 2!=x
+} -returnCodes error -match glob -result *
test expr-8.12 {CompileBitAndExpr: equality expr} {expr {"a"eq"a"}} 1
test expr-8.13 {CompileBitAndExpr: equality expr} {
set s \u00fc
@@ -307,66 +363,97 @@ test expr-8.16 {CompileBitAndExpr: equality expr} {expr 3.2ne2.2} 1
test expr-8.17 {CompileBitAndExpr: equality expr} {expr 01eq1} 0
test expr-8.18 {CompileBitAndExpr: equality expr} {expr {"abc" eq "abd"}} 0
test expr-8.19 {CompileBitAndExpr: equality expr} {expr {"abc" ne "abd"}} 1
-test expr-8.20 {CompileBitAndExpr: error in equality expr} {
- catch {expr x ne3} msg
- set msg
-} {syntax error in expression "x ne3": variable references require preceding $}
-test expr-8.21 {CompileBitAndExpr: error in equality expr} {
+test expr-8.20 {CompileBitAndExpr: error in equality expr} -body {
+ expr x ne3
+} -returnCodes error -match glob -result *
+test expr-8.21 {CompileBitAndExpr: error in equality expr} -body {
# These should be ""ed to avoid the error
- catch {expr a eq b} msg
- set msg
-} {syntax error in expression "a eq b": variable references require preceding $}
+ expr a eq b
+} -returnCodes error -match glob -result *
+test expr-8.22 {CompileBitAndExpr: error in equality expr} -body {
+ expr {false eqfalse}
+} -returnCodes error -match glob -result *
+test expr-8.23 {CompileBitAndExpr: error in equality expr} -body {
+ expr {false nefalse}
+} -returnCodes error -match glob -result *
+test expr-8.24 {CompileEqualityExpr: simple equality exprs} {
+ set x 12398712938788234
+ expr {$x == 100}
+} 0
+test expr-8.25 {CompileEqualityExpr: simple equality exprs} {
+ expr {"0x12 " == "0x12"}
+} 1
+test expr-8.26 {CompileEqualityExpr: simple equality exprs} {
+ expr {"0x12 " eq "0x12"}
+} 0
+test expr-8.27 {CompileEqualityExpr: simple equality exprs} {
+ expr {"1.0e100000000" == "0.0"}
+} 0
+test expr-8.28 {CompileEqualityExpr: just relational expr} {
+ expr {"0y" == "0x0"}
+} 0
+test expr-8.29 {CompileEqualityExpr: just relational expr} {
+ # Compare original strings from variables.
+ set v1 "0y"
+ set v2 "0x12"
+ expr {$v1 < $v2}
+} 0
+test expr-8.30 {CompileEqualityExpr: simple equality exprs} {
+ expr {"fake" != "bob"}
+} 1
+test expr-8.31 {expr edge cases} -body {
+ expr {1e}
+} -returnCodes error -match glob -result *
+test expr-8.32 {expr edge cases} -body {
+ expr {1E}
+} -returnCodes error -match glob -result *
+test expr-8.33 {expr edge cases} -body {
+ expr {1e+}
+} -returnCodes error -match glob -result *
+test expr-8.34 {expr edge cases} -body {
+ expr {1E+}
+} -returnCodes error -match glob -result *
+test expr-8.35 {expr edge cases} -body {
+ expr {1ea}
+} -returnCodes error -match glob -result *
test expr-9.1 {CompileRelationalExpr: just shift expr} {expr 3<<2} 12
test expr-9.2 {CompileRelationalExpr: just shift expr} {expr 0xff>>2} 63
test expr-9.3 {CompileRelationalExpr: just shift expr} {expr -1>>2} -1
test expr-9.4 {CompileRelationalExpr: just shift expr} {expr {1<<3}} 8
-
-# The following test is different for 32-bit versus 64-bit
-# architectures because LONG_MIN is different
-
-if {0x80000000 > 0} {
- test expr-9.5 {CompileRelationalExpr: shift expr producing LONG_MIN} {nonPortable} {
- expr {1<<63}
- } -9223372036854775808
-} else {
- test expr-9.5 {CompileRelationalExpr: shift expr producing LONG_MIN} {nonPortable} {
- expr {1<<31}
- } -2147483648
-}
-test expr-9.6 {CompileRelationalExpr: error in shift expr} {
- catch {expr x>>3} msg
- set msg
-} {syntax error in expression "x>>3": variable references require preceding $}
+test expr-9.5a {CompileRelationalExpr: shift expr producing LONG_MIN} longIs64bit {
+ expr {int(1<<63)}
+} -9223372036854775808
+test expr-9.5b {CompileRelationalExpr: shift expr producing LONG_MIN} longIs32bit {
+ expr {int(1<<31)}
+} -2147483648
+test expr-9.6 {CompileRelationalExpr: error in shift expr} -body {
+ expr x>>3
+} -returnCodes error -match glob -result *
test expr-9.7 {CompileRelationalExpr: simple relational exprs} {expr 0xff>=+0x3} 1
test expr-9.8 {CompileRelationalExpr: simple relational exprs} {expr -0xf2<0x3} 1
-test expr-9.9 {CompileRelationalExpr: error compiling relational arm} {
- catch {expr 2**3>6} msg
- set msg
-} {syntax error in expression "2**3>6": unexpected operator *}
-test expr-9.10 {CompileRelationalExpr: error compiling relational arm} {
- catch {expr 2<x} msg
- set msg
-} {syntax error in expression "2<x": variable references require preceding $}
+test expr-9.9 {CompileRelationalExpr: error compiling relational arm} -body {
+ expr 2***3>6
+} -returnCodes error -match glob -result *
+test expr-9.10 {CompileRelationalExpr: error compiling relational arm} -body {
+ expr 2<x
+} -returnCodes error -match glob -result *
test expr-10.1 {CompileShiftExpr: just add expr} {expr 4+-2} 2
test expr-10.2 {CompileShiftExpr: just add expr} {expr 0xff-2} 253
test expr-10.3 {CompileShiftExpr: just add expr} {expr -1--2} 1
-test expr-10.4 {CompileShiftExpr: just add expr} {expr 1-0123} -82
-test expr-10.5 {CompileShiftExpr: error in add expr} {
- catch {expr x+3} msg
- set msg
-} {syntax error in expression "x+3": variable references require preceding $}
+test expr-10.4 {CompileShiftExpr: just add expr} {expr 1-0o123} -82
+test expr-10.5 {CompileShiftExpr: error in add expr} -body {
+ expr x+3
+} -returnCodes error -match glob -result *
test expr-10.6 {CompileShiftExpr: simple shift exprs} {expr 0xff>>0x3} 31
test expr-10.7 {CompileShiftExpr: simple shift exprs} {expr -0xf2<<0x3} -1936
-test expr-10.8 {CompileShiftExpr: error compiling shift arm} {
- catch {expr 2**3>>6} msg
- set msg
-} {syntax error in expression "2**3>>6": unexpected operator *}
-test expr-10.9 {CompileShiftExpr: error compiling shift arm} {
- catch {expr 2<<x} msg
- set msg
-} {syntax error in expression "2<<x": variable references require preceding $}
+test expr-10.8 {CompileShiftExpr: error compiling shift arm} -body {
+ expr 2***3>>6
+} -returnCodes error -match glob -result *
+test expr-10.9 {CompileShiftExpr: error compiling shift arm} -body {
+ expr 2<<x
+} -returnCodes error -match glob -result *
test expr-10.10 {CompileShiftExpr: runtime error} {
list [catch {expr {24.0>>43}} msg] $msg
} {1 {can't use floating-point value as operand of ">>"}}
@@ -377,21 +464,18 @@ test expr-10.11 {CompileShiftExpr: runtime error} {
test expr-11.1 {CompileAddExpr: just multiply expr} {expr 4*-2} -8
test expr-11.2 {CompileAddExpr: just multiply expr} {expr 0xff%2} 1
test expr-11.3 {CompileAddExpr: just multiply expr} {expr -1/2} -1
-test expr-11.4 {CompileAddExpr: just multiply expr} {expr 7891%0123} 6
-test expr-11.5 {CompileAddExpr: error in multiply expr} {
- catch {expr x*3} msg
- set msg
-} {syntax error in expression "x*3": variable references require preceding $}
+test expr-11.4 {CompileAddExpr: just multiply expr} {expr 7891%0o123} 6
+test expr-11.5 {CompileAddExpr: error in multiply expr} -body {
+ expr x*3
+} -returnCodes error -match glob -result *
test expr-11.6 {CompileAddExpr: simple add exprs} {expr 0xff++0x3} 258
test expr-11.7 {CompileAddExpr: simple add exprs} {expr -0xf2--0x3} -239
-test expr-11.8 {CompileAddExpr: error compiling add arm} {
- catch {expr 2**3+6} msg
- set msg
-} {syntax error in expression "2**3+6": unexpected operator *}
-test expr-11.9 {CompileAddExpr: error compiling add arm} {
- catch {expr 2-x} msg
- set msg
-} {syntax error in expression "2-x": variable references require preceding $}
+test expr-11.8 {CompileAddExpr: error compiling add arm} -body {
+ expr 2***3+6
+} -returnCodes error -match glob -result *
+test expr-11.9 {CompileAddExpr: error compiling add arm} -body {
+ expr 2-x
+} -returnCodes error -match glob -result *
test expr-11.10 {CompileAddExpr: runtime error} {
list [catch {expr {24.0+"xx"}} msg] $msg
} {1 {can't use non-numeric string as operand of "+"}}
@@ -401,28 +485,28 @@ test expr-11.11 {CompileAddExpr: runtime error} {
test expr-11.12 {CompileAddExpr: runtime error} {
list [catch {expr {3/0}} msg] $msg
} {1 {divide by zero}}
-test expr-11.13 {CompileAddExpr: runtime error} {
+test expr-11.13a {CompileAddExpr: runtime error} !ieeeFloatingPoint {
list [catch {expr {2.3/0.0}} msg] $msg
} {1 {divide by zero}}
+test expr-11.13b {CompileAddExpr: runtime error} ieeeFloatingPoint {
+ list [catch {expr {2.3/0.0}} msg] $msg
+} {0 Inf}
test expr-12.1 {CompileMultiplyExpr: just unary expr} {expr ~4} -5
test expr-12.2 {CompileMultiplyExpr: just unary expr} {expr --5} 5
test expr-12.3 {CompileMultiplyExpr: just unary expr} {expr !27} 0
test expr-12.4 {CompileMultiplyExpr: just unary expr} {expr ~0xff00ff} -16711936
-test expr-12.5 {CompileMultiplyExpr: error in unary expr} {
- catch {expr ~x} msg
- set msg
-} {syntax error in expression "~x": variable references require preceding $}
+test expr-12.5 {CompileMultiplyExpr: error in unary expr} -body {
+ expr ~x
+} -returnCodes error -match glob -result *
test expr-12.6 {CompileMultiplyExpr: simple multiply exprs} {expr 0xff*0x3} 765
test expr-12.7 {CompileMultiplyExpr: simple multiply exprs} {expr -0xf2%-0x3} -2
-test expr-12.8 {CompileMultiplyExpr: error compiling multiply arm} {
- catch {expr 2*3%%6} msg
- set msg
-} {syntax error in expression "2*3%%6": unexpected operator %}
-test expr-12.9 {CompileMultiplyExpr: error compiling multiply arm} {
- catch {expr 2*x} msg
- set msg
-} {syntax error in expression "2*x": variable references require preceding $}
+test expr-12.8 {CompileMultiplyExpr: error compiling multiply arm} -body {
+ expr 2*3%%6
+} -returnCodes error -match glob -result *
+test expr-12.9 {CompileMultiplyExpr: error compiling multiply arm} -body {
+ expr 2*x
+} -returnCodes error -match glob -result *
test expr-12.10 {CompileMultiplyExpr: runtime error} {
list [catch {expr {24.0*"xx"}} msg] $msg
} {1 {can't use non-numeric string as operand of "*"}}
@@ -431,20 +515,18 @@ test expr-12.11 {CompileMultiplyExpr: runtime error} {
} {1 {can't use non-numeric string as operand of "/"}}
test expr-13.1 {CompileUnaryExpr: unary exprs} {expr -0xff} -255
-test expr-13.2 {CompileUnaryExpr: unary exprs} {expr +000123} 83
+test expr-13.2 {CompileUnaryExpr: unary exprs} {expr +0o00123} 83
test expr-13.3 {CompileUnaryExpr: unary exprs} {expr +--++36} 36
test expr-13.4 {CompileUnaryExpr: unary exprs} {expr !2} 0
test expr-13.5 {CompileUnaryExpr: unary exprs} {expr +--+-62.0} -62.0
test expr-13.6 {CompileUnaryExpr: unary exprs} {expr !0.0} 1
test expr-13.7 {CompileUnaryExpr: unary exprs} {expr !0xef} 0
-test expr-13.8 {CompileUnaryExpr: error compiling unary expr} {
- catch {expr ~x} msg
- set msg
-} {syntax error in expression "~x": variable references require preceding $}
-test expr-13.9 {CompileUnaryExpr: error compiling unary expr} {
- catch {expr !1.x} msg
- set msg
-} {syntax error in expression "!1.x": extra tokens at end of expression}
+test expr-13.8 {CompileUnaryExpr: error compiling unary expr} -body {
+ expr ~x
+} -returnCodes error -match glob -result *
+test expr-13.9 {CompileUnaryExpr: error compiling unary expr} -body {
+ expr !1.x
+} -returnCodes error -match glob -result *
test expr-13.10 {CompileUnaryExpr: runtime error} {
list [catch {expr {~"xx"}} msg] $msg
} {1 {can't use non-numeric string as operand of "~"}}
@@ -472,7 +554,7 @@ test expr-13.17 {CompileUnaryExpr: negating non-numeric boolean literals} {
test expr-14.1 {CompilePrimaryExpr: literal primary} {expr 1} 1
test expr-14.2 {CompilePrimaryExpr: literal primary} {expr 123} 123
test expr-14.3 {CompilePrimaryExpr: literal primary} {expr 0xff} 255
-test expr-14.4 {CompilePrimaryExpr: literal primary} {expr 00010} 8
+test expr-14.4 {CompilePrimaryExpr: literal primary} {expr 0o0010} 8
test expr-14.5 {CompilePrimaryExpr: literal primary} {expr 62.0} 62.0
test expr-14.6 {CompilePrimaryExpr: literal primary} {
expr 3.1400000
@@ -509,15 +591,12 @@ test expr-14.15 {CompilePrimaryExpr: var reference primary} {
catch {expr $i.2} msg
set msg
} 123.2
-test expr-14.16 {CompilePrimaryExpr: error compiling var reference primary} {
- catch {expr {$a(foo}} msg
- set errorInfo
-} {missing )
- while compiling
-"expr {$a(foo}"}
-test expr-14.17 {CompilePrimaryExpr: string primary that looks like var ref} {
+test expr-14.16 {CompilePrimaryExpr: error compiling var reference primary} -body {
+ expr {$a(foo}
+} -returnCodes error -match glob -result *
+test expr-14.17 {CompilePrimaryExpr: string primary that looks like var ref} -body {
expr $
-} $
+} -returnCodes error -match glob -result *
test expr-14.18 {CompilePrimaryExpr: quoted string primary} {
expr "21"
} 21
@@ -538,126 +617,110 @@ test expr-14.21 {CompilePrimaryExpr: error in quoted string primary} {
test expr-14.22 {CompilePrimaryExpr: subcommand primary} {
expr {[set i 123; set i]}
} 123
-test expr-14.23 {CompilePrimaryExpr: error in subcommand primary} {
+test expr-14.23 {CompilePrimaryExpr: error in subcommand primary} -body {
catch {expr {[set]}} msg
- set errorInfo
-} {wrong # args: should be "set varName ?newValue?"
- while compiling
-"set"
- while compiling
-"expr {[set]}"}
-test expr-14.24 {CompilePrimaryExpr: error in subcommand primary} {
- catch {expr {[set i}} msg
- set errorInfo
-} {missing close-bracket
- while compiling
-"expr {[set i}"}
+ set ::errorInfo
+} -match glob -result {wrong # args: should be "set varName ?newValue?"
+ while *ing
+"set"*}
+test expr-14.24 {CompilePrimaryExpr: error in subcommand primary} -body {
+ expr {[set i}
+} -returnCodes error -match glob -result *
test expr-14.25 {CompilePrimaryExpr: math function primary} {
format %.6g [expr exp(1.0)]
} 2.71828
test expr-14.26 {CompilePrimaryExpr: math function primary} {
format %.6g [expr pow(2.0+0.1,3.0+0.1)]
} 9.97424
-test expr-14.27 {CompilePrimaryExpr: error in math function primary} {
- catch {expr sinh::(2.0)} msg
- set errorInfo
-} {syntax error in expression "sinh::(2.0)": expected parenthesis enclosing function arguments
- while compiling
-"expr sinh::(2.0)"}
+test expr-14.27 {CompilePrimaryExpr: error in math function primary} -body {
+ expr sinh::(2.0)
+} -returnCodes error -match glob -result *
test expr-14.28 {CompilePrimaryExpr: subexpression primary} {
expr 2+(3*4)
} 14
-test expr-14.29 {CompilePrimaryExpr: error in subexpression primary} {
+test expr-14.29 {CompilePrimaryExpr: error in subexpression primary} -body {
catch {expr 2+(3*[set])} msg
- set errorInfo
-} {wrong # args: should be "set varName ?newValue?"
- while compiling
-"set"
- while compiling
-"expr 2+(3*[set])"}
-test expr-14.30 {CompilePrimaryExpr: missing paren in subexpression primary} {
- catch {expr 2+(3*(4+5)} msg
- set errorInfo
-} {syntax error in expression "2+(3*(4+5)": looking for close parenthesis
- while compiling
-"expr 2+(3*(4+5)"}
+ set ::errorInfo
+} -match glob -result {wrong # args: should be "set varName ?newValue?"
+ while *ing
+"set"*}
+test expr-14.30 {CompilePrimaryExpr: missing paren in subexpression primary} -body {
+ expr 2+(3*(4+5)
+} -returnCodes error -match glob -result *
test expr-14.31 {CompilePrimaryExpr: just var ref in subexpression primary} {
set i "5+10"
list "[expr $i] == 15" "[expr ($i)] == 15" "[eval expr ($i)] == 15"
} {{15 == 15} {15 == 15} {15 == 15}}
-test expr-14.32 {CompilePrimaryExpr: unexpected token} {
- catch {expr @} msg
- set errorInfo
-} {syntax error in expression "@": character not legal in expressions
- while compiling
-"expr @"}
-
-test expr-15.1 {CompileMathFuncCall: missing parenthesis} {
- catch {expr sinh2.0)} msg
- set errorInfo
-} {syntax error in expression "sinh2.0)": variable references require preceding $
- while compiling
-"expr sinh2.0)"}
-test expr-15.2 {CompileMathFuncCall: unknown math function} {
+test expr-14.32 {CompilePrimaryExpr: unexpected token} -body {
+ expr @
+} -returnCodes error -match glob -result *
+
+test expr-15.1 {CompileMathFuncCall: missing parenthesis} -body {
+ expr sinh2.0)
+} -returnCodes error -match glob -result *
+test expr-15.2 {CompileMathFuncCall: unknown math function} -body {
catch {expr whazzathuh(1)} msg
- set errorInfo
-} {unknown math function "whazzathuh"
- while compiling
+ set ::errorInfo
+} -match glob -result {* "*whazzathuh"
+ while *ing
"expr whazzathuh(1)"}
-test expr-15.3 {CompileMathFuncCall: too many arguments} {
+test expr-15.3 {CompileMathFuncCall: too many arguments} -body {
catch {expr sin(1,2,3)} msg
- set errorInfo
-} {too many arguments for math function
- while compiling
+ set ::errorInfo
+} -match glob -result {too many arguments for math function*
+ while *ing
"expr sin(1,2,3)"}
-test expr-15.4 {CompileMathFuncCall: ')' found before last required arg} {
+test expr-15.4 {CompileMathFuncCall: ')' found before last required arg} -body {
catch {expr sin()} msg
- set errorInfo
-} {too few arguments for math function
- while compiling
+ set ::errorInfo
+} -match glob -result {too few arguments for math function*
+ while *ing
"expr sin()"}
-test expr-15.5 {CompileMathFuncCall: too few arguments} {
+test expr-15.5 {CompileMathFuncCall: too few arguments} -body {
catch {expr pow(1)} msg
- set errorInfo
-} {too few arguments for math function
- while compiling
+ set ::errorInfo
+} -match glob -result {too few arguments for math function*
+ while *ing
"expr pow(1)"}
-test expr-15.6 {CompileMathFuncCall: missing ')'} {
- catch {expr sin(1} msg
- set errorInfo
-} {syntax error in expression "sin(1": missing close parenthesis at end of function call
- while compiling
-"expr sin(1"}
-test expr-15.7 {CompileMathFuncCall: call registered math function} {registeredMathFuncs} {
+test expr-15.6 {CompileMathFuncCall: missing ')'} -body {
+ expr sin(1
+} -returnCodes error -match glob -result *
+test expr-15.7 {CompileMathFuncCall: call registered math function} {testmathfunctions} {
expr 2*T1()
} 246
-test expr-15.8 {CompileMathFuncCall: call registered math function} {registeredMathFuncs} {
+test expr-15.8 {CompileMathFuncCall: call registered math function} {testmathfunctions} {
expr T2()*3
} 1035
-test expr-15.9 {CompileMathFuncCall: call registered math function} {registeredMathFuncs} {
+test expr-15.9 {CompileMathFuncCall: call registered math function} {testmathfunctions} {
expr T3(21, 37)
} 37
-test expr-15.10 {CompileMathFuncCall: call registered math function} {registeredMathFuncs} {
+test expr-15.10 {CompileMathFuncCall: call registered math function} {testmathfunctions} {
expr T3(21.2, 37)
} 37.0
-test expr-15.11 {CompileMathFuncCall: call registered math function} {registeredMathFuncs} {
+test expr-15.11 {CompileMathFuncCall: call registered math function} {testmathfunctions} {
expr T3(-21.2, -17.5)
} -17.5
-test expr-15.12 {ExprCallMathFunc: call registered math function} {registeredMathFuncs} {
+test expr-15.12 {ExprCallMathFunc: call registered math function} {testmathfunctions} {
expr T3(21, wide(37))
} 37
-test expr=15.13 {ExprCallMathFunc: call registered math function} {registeredMathFuncs} {
+test expr=15.13 {ExprCallMathFunc: call registered math function} {testmathfunctions} {
expr T3(wide(21), 37)
} 37
-test expr=15.14 {ExprCallMathFunc: call registered math function} {registeredMathFuncs} {
+test expr=15.14 {ExprCallMathFunc: call registered math function} {testmathfunctions} {
expr T3(wide(21), wide(37))
} 37
-test expr-15.15 {ExprCallMathFunc: call registered math function} {registeredMathFuncs} {
+test expr-15.15 {ExprCallMathFunc: call registered math function} {testmathfunctions} {
expr T3(21.0, wide(37))
} 37.0
-test expr=15.16 {ExprCallMathFunc: call registered math function} {registeredMathFuncs} {
+test expr-15.16 {ExprCallMathFunc: call registered math function} {testmathfunctions} {
expr T3(wide(21), 37.0)
} 37.0
+test expr-15.17 {ExprCallMathFunc: non-numeric arg} -constraints {
+ testmathfunctions
+} -body {
+ expr T3(0,"a")
+} -returnCodes error -result {argument to math function didn't have numeric value}
+
test expr-16.1 {GetToken: checks whether integer token starting with "0x" (e.g., "0x$") is invalid} {
catch {unset a}
@@ -725,7 +788,7 @@ test expr-20.1 {wrong brace matching} {
set cmd "expr $l$q|$q == $q$r$q$r"
list [catch $cmd a] $a
} {1 {extra characters after close-brace}}
-test expr-20.2 {double invocation of variable traces} {
+test expr-20.2 {double invocation of variable traces} -body {
set exprtracecounter 0
proc exprtraceproc {args} {
upvar #0 exprtracecounter counter
@@ -743,7 +806,7 @@ test expr-20.2 {double invocation of variable traces} {
list [catch {expr "$exprtracevar + 20"} a] $a \
[catch {expr "$exprtracevar + 20"} b] $b \
[unset exprtracevar exprtracecounter]
-} {1 {syntax error in expression "1 oops 10 + 20": extra tokens at end of expression} 0 32 {}}
+} -match glob -result {1 * 0 32 {}}
test expr-20.3 {broken substitution of integer digits} {
# fails with 8.0.x, but not 8.1b2
list [set a 000; expr 0x1$a] [set a 1; expr ${a}000]
@@ -776,56 +839,5834 @@ test expr-21.9 {non-numeric boolean literals} {expr !off } 1
test expr-21.10 {non-numeric boolean literals} {expr !on } 0
test expr-21.11 {non-numeric boolean literals} {expr !no } 1
test expr-21.12 {non-numeric boolean literals} {expr !yes } 0
+test expr-21.13 {non-numeric boolean literals} -body {
+ expr !truef
+} -returnCodes error -match glob -result *
+test expr-21.14 {non-numeric boolean literals} {
+ list [catch {expr !"truef"} err] $err
+} {1 {can't use non-numeric string as operand of "!"}}
+test expr-21.15 {non-numeric boolean variables} {
+ set v truef
+ list [catch {expr {!$v}} err] $err
+} {1 {can't use non-numeric string as operand of "!"}}
+test expr-21.16 {non-numeric boolean variables} {
+ set v "true "
+ list [catch {expr {!$v}} err] $err
+} {1 {can't use non-numeric string as operand of "!"}}
+test expr-21.17 {non-numeric boolean variables} {
+ set v "tru"
+ list [catch {expr {!$v}} err] $err
+} {0 0}
+test expr-21.18 {non-numeric boolean variables} {
+ set v "fal"
+ list [catch {expr {!$v}} err] $err
+} {0 1}
+test expr-21.19 {non-numeric boolean variables} {
+ set v "y"
+ list [catch {expr {!$v}} err] $err
+} {0 0}
+test expr-21.20 {non-numeric boolean variables} {
+ set v "of"
+ list [catch {expr {!$v}} err] $err
+} {0 1}
+test expr-21.21 {non-numeric boolean variables} {
+ set v "o"
+ list [catch {expr {!$v}} err] $err
+} {1 {can't use non-numeric string as operand of "!"}}
+test expr-21.22 {non-numeric boolean variables} {
+ set v ""
+ list [catch {expr {!$v}} err] $err
+} {1 {can't use empty string as operand of "!"}}
# Test for non-numeric float handling.
-#
-# These are non-portable because strtod()-support for "Inf" and "NaN"
-# is so wildly variable. This sucks...
-test expr-22.1 {non-numeric floats} nonPortable {
+test expr-22.1 {non-numeric floats} {
list [catch {expr {NaN + 1}} msg] $msg
} {1 {can't use non-numeric floating-point value as operand of "+"}}
-test expr-22.2 {non-numeric floats} nonPortable {
+test expr-22.2 {non-numeric floats} !ieeeFloatingPoint {
list [catch {expr {Inf + 1}} msg] $msg
} {1 {can't use infinite floating-point value as operand of "+"}}
-test expr-22.3 {non-numeric floats} nonPortable {
+test expr-22.3 {non-numeric floats} {
set nan NaN
list [catch {expr {$nan + 1}} msg] $msg
} {1 {can't use non-numeric floating-point value as operand of "+"}}
-test expr-22.4 {non-numeric floats} nonPortable {
+test expr-22.4 {non-numeric floats} !ieeeFloatingPoint {
set inf Inf
list [catch {expr {$inf + 1}} msg] $msg
} {1 {can't use infinite floating-point value as operand of "+"}}
-test expr-22.5 {non-numeric floats} nonPortable {
+test expr-22.5 {non-numeric floats} {
list [catch {expr NaN} msg] $msg
} {1 {domain error: argument not in valid range}}
-test expr-22.6 {non-numeric floats} nonPortable {
+test expr-22.6 {non-numeric floats} !ieeeFloatingPoint {
list [catch {expr Inf} msg] $msg
} {1 {floating-point value too large to represent}}
-test expr-22.7 {non-numeric floats} nonPortable {
+test expr-22.7 {non-numeric floats} {
list [catch {expr {1 / NaN}} msg] $msg
} {1 {can't use non-numeric floating-point value as operand of "/"}}
-test expr-22.8 {non-numeric floats} nonPortable {
+test expr-22.8 {non-numeric floats} !ieeeFloatingPoint {
list [catch {expr {1 / Inf}} msg] $msg
} {1 {can't use infinite floating-point value as operand of "/"}}
# Make sure [Bug 761471] stays fixed.
-test expr-22.9 {non-numeric floats: shared object equality and NaN} nonPortable {
+test expr-22.9 {non-numeric floats: shared object equality and NaN} {
set x NaN
expr {$x == $x}
} 0
+# Tests for exponentiation handling
+test expr-23.1 {CompileExponentialExpr: just exponential expr} {expr 4**2} 16
+test expr-23.2 {CompileExponentialExpr: just exponential expr} {expr 0xff**2} 65025
+test expr-23.3 {CompileExponentialExpr: just exponential expr} {expr -1**2} 1
+test expr-23.4 {CompileExponentialExpr: just exponential expr} {expr 18**07} 612220032
+test expr-23.5 {CompileExponentialExpr: error in exponential expr} -body {
+ expr x**3
+} -returnCodes error -match glob -result *
+test expr-23.6 {CompileExponentialExpr: simple expo exprs} {expr 0xff**0x3} 16581375
+test expr-23.7 {CompileExponentialExpr: error compiling expo arm} -body {
+ expr (-3-)**6
+} -returnCodes error -match glob -result *
+test expr-23.8 {CompileExponentialExpr: error compiling expo arm} -body {
+ expr 2**x
+} -returnCodes error -match glob -result *
+test expr-23.9 {CompileExponentialExpr: runtime error} {
+ list [catch {expr {24.0**"xx"}} msg] $msg
+} {1 {can't use non-numeric string as operand of "**"}}
+test expr-23.10 {CompileExponentialExpr: runtime error} {
+ list [catch {expr {"a"**2}} msg] $msg
+} {1 {can't use non-numeric string as operand of "**"}}
+test expr-23.11 {CompileExponentialExpr: runtime error} {
+ list [catch {expr {0**-1}} msg] $msg
+} {1 {exponentiation of zero by negative power}}
+test expr-23.12 {CompileExponentialExpr: runtime error} {
+ list [catch {expr {0.0**-1.0}} msg] $msg
+} {1 {exponentiation of zero by negative power}}
+test expr-23.13 {CompileExponentialExpr: runtime error} {
+ list [catch {expr {wide(0)**wide(-1)}} msg] $msg
+} {1 {exponentiation of zero by negative power}}
+test expr-23.14 {INST_EXPON: special cases} {expr {0**1}} 0
+test expr-23.15 {INST_EXPON: special cases} {expr {0**0}} 1
+test expr-23.16 {INST_EXPON: special cases} {expr {-2**-1}} 0
+test expr-23.17 {INST_EXPON: special cases} {expr {-2**0}} 1
+test expr-23.18 {INST_EXPON: special cases} {expr {-1**1}} -1
+test expr-23.19 {INST_EXPON: special cases} {expr {-1**0}} 1
+test expr-23.20 {INST_EXPON: special cases} {expr {-1**2}} 1
+test expr-23.21 {INST_EXPON: special cases} {expr {-1**-1}} -1
+test expr-23.22 {INST_EXPON: special cases} {expr {1**1234567}} 1
+test expr-23.23 {INST_EXPON: special cases} {expr {2**-2}} 0
+test expr-23.24 {INST_EXPON: special cases} {expr {wide(0)**wide(1)}} 0
+test expr-23.25 {INST_EXPON: special cases} {expr {wide(0)**wide(0)}} 1
+test expr-23.26 {INST_EXPON: special cases} {expr {wide(-2)**wide(-1)}} 0
+test expr-23.27 {INST_EXPON: special cases} {expr {wide(-2)**wide(0)}} 1
+test expr-23.28 {INST_EXPON: special cases} {expr {wide(-1)**wide(1)}} -1
+test expr-23.29 {INST_EXPON: special cases} {expr {wide(-1)**wide(0)}} 1
+test expr-23.30 {INST_EXPON: special cases} {expr {wide(-1)**wide(2)}} 1
+test expr-23.31 {INST_EXPON: special cases} {expr {wide(-1)**wide(-1)}} -1
+test expr-23.32 {INST_EXPON: special cases} {expr {wide(1)**wide(1234567)}} 1
+test expr-23.33 {INST_EXPON: special cases} {expr {wide(2)**wide(-2)}} 0
+test expr-23.34 {INST_EXPON: special cases} {expr {2**0}} 1
+test expr-23.35 {INST_EXPON: special cases} {expr {wide(2)**0}} 1
+test expr-23.36 {INST_EXPON: big integer} {expr {10**17}} 1[string repeat 0 17]
+test expr-23.37 {INST_EXPON: big integer} {expr {10**18}} 1[string repeat 0 18]
+test expr-23.38 {INST_EXPON: big integer} {expr {10**19}} 1[string repeat 0 19]
+test expr-23.39 {INST_EXPON: big integer} {
+ expr 1[string repeat 0 30]**2
+} 1[string repeat 0 60]
+test expr-23.40 {INST_EXPON: overflow to big integer} {expr {(-10)**3}} -1000
+test expr-23.41 {INST_EXPON: overflow to big integer} {expr 2**64} [expr 1<<64]
+test expr-23.42 {INST_EXPON: overflow to big integer} {expr 4**32} [expr 1<<64]
+test expr-23.43 {INST_EXPON: overflow to big integer} {expr 16**16} [expr 1<<64]
+test expr-23.44 {INST_EXPON: overflow to big integer} {expr 256**8} [expr 1<<64]
+test expr-23.45 {INST_EXPON: Bug 1555371} {expr 2**1} 2
+test expr-23.46 {INST_EXPON: Bug 1561260} -body {
+ expr 5**28
+} -match glob -result *5
+test expr-23.47 {INST_EXPON: Bug 1561260} {
+ expr 2**32*5**32
+} 1[string repeat 0 32]
+test expr-23.48 {INST_EXPON: TIP 274: right assoc} {
+expr 2**3**4
+} 2417851639229258349412352
+test expr-23.49 {INST_EXPON: optimize powers of 2} {
+ set trouble {test powers of 2}
+ for {set tval 0} {$tval <= 66} {incr tval} {
+ set is [expr {2 ** $tval}]
+ set sb [expr {1 << $tval}]
+ if {$is != $sb} {
+ append trouble \n "2**" $tval " is " $is " should be " $sb
+ }
+ if {$tval >= 1} {
+ set is [expr {-2 ** $tval}]
+ set sb [expr {1 << $tval}]
+ if {$tval & 1} {
+ set sb [expr {-$sb}]
+ }
+ if {$is != $sb} {
+ append trouble \n "-2**" $tval " is " $is " should be " $sb
+ }
+ }
+ }
+ set trouble
+} {test powers of 2}
+test expr-23.50 {INST_EXPON: small powers of 32-bit integers} {
+ set trouble {test small powers of 32-bit ints}
+ for {set base 3} {$base <= 45} {incr base} {
+ set sb $base
+ set sbm [expr {-$base}]
+ for {set expt 2} {$expt <= 8} {incr expt} {
+ set sb [expr {$sb * $base}]
+ set is [expr {$base ** $expt}]
+ if {$sb != $is} {
+ append trouble \n $base ** $expt " is " $is " should be " $sb
+ }
+ set sbm [expr {-$sbm * $base}]
+ set ism [expr {(-$base) ** $expt}]
+ if {$sbm != $ism} {
+ append trouble \n - $base ** $expt " is " $ism \
+ " should be " $sbm
+ }
+ }
+ }
+ set trouble
+} {test small powers of 32-bit ints}
+test expr-23.51 {INST_EXPON: intermediate powers of 32-bit integers} {
+ set trouble {test intermediate powers of 32-bit ints}
+ for {set base 3} {$base <= 11} {incr base} {
+ set sb [expr {$base ** 8}]
+ set sbm $sb
+ for {set expt 9} {$expt <= 21} {incr expt} {
+ set sb [expr {$sb * $base}]
+ set sbm [expr {$sbm * -$base}]
+ set is [expr {$base ** $expt}]
+ set ism [expr {-$base ** $expt}]
+ if {$sb != $is} {
+ append trouble \n $base ** $expt " is " $is " should be " $sb
+ }
+ if {$sbm != $ism} {
+ append trouble \n - $base ** $expt " is " $ism \
+ " should be " $sbm
+ }
+ }
+ }
+ set trouble
+} {test intermediate powers of 32-bit ints}
+test expr-23.52 {INST_EXPON: small integer powers with 64-bit results} {
+ set trouble {test small int powers with 64-bit results}
+ for {set exp 2} {$exp <= 16} {incr exp} {
+ set base [expr {entier(pow(double(0x7fffffffffffffff),(1.0/$exp)))}]
+ set sb 1
+ set sbm 1
+ for {set i 0} {$i < $exp} {incr i} {
+ set sb [expr {$sb * $base}]
+ set sbm [expr {$sbm * -$base}]
+ }
+ set is [expr {$base ** $exp}]
+ set ism [expr {-$base ** $exp}]
+ if {$sb != $is} {
+ append trouble \n $base ** $exp " is " $is " should be " $sb
+ }
+ if {$sbm != $ism} {
+ append trouble \n - $base ** $exp " is " $ism " should be " $sbm
+ }
+ incr base
+ set sb 1
+ set sbm 1
+ for {set i 0} {$i < $exp} {incr i} {
+ set sb [expr {$sb * $base}]
+ set sbm [expr {$sbm * -$base}]
+ }
+ set is [expr {$base ** $exp}]
+ set ism [expr {-$base ** $exp}]
+ if {$sb != $is} {
+ append trouble \n $base ** $exp " is " $is " should be " $sb
+ }
+ if {$sbm != $ism} {
+ append trouble \n - $base ** $exp " is " $ism " should be " $sbm
+ }
+ }
+ set trouble
+} {test small int powers with 64-bit results}
+test expr-23.53 {INST_EXPON: intermediate powers of 64-bit integers} {
+ set trouble {test intermediate powers of 64-bit ints}
+ for {set base 3} {$base <= 13} {incr base} {
+ set sb [expr {$base ** 15}]
+ set sbm [expr {-$sb}]
+ for {set expt 16} {$expt <= 39} {incr expt} {
+ set sb [expr {$sb * $base}]
+ set sbm [expr {$sbm * -$base}]
+ set is [expr {$base ** $expt}]
+ set ism [expr {-$base ** $expt}]
+ if {$sb != $is} {
+ append trouble \n $base ** $expt " is " $is " should be " $sb
+ }
+ if {$sbm != $ism} {
+ append trouble \n - $base ** $expt " is " $ism \
+ " should be " $sbm
+ }
+ }
+ }
+ set trouble
+} {test intermediate powers of 64-bit ints}
+test expr-23.54.0 {INST_EXPON: Bug 2798543} {
+ expr {3**9 == 3**65545}
+} 0
+test expr-23.54.1 {INST_EXPON: Bug 2798543} {
+ expr {3**10 == 3**65546}
+} 0
+test expr-23.54.2 {INST_EXPON: Bug 2798543} {
+ expr {3**11 == 3**65547}
+} 0
+test expr-23.54.3 {INST_EXPON: Bug 2798543} {
+ expr {3**12 == 3**65548}
+} 0
+test expr-23.54.4 {INST_EXPON: Bug 2798543} {
+ expr {3**13 == 3**65549}
+} 0
+test expr-23.54.5 {INST_EXPON: Bug 2798543} {
+ expr {3**14 == 3**65550}
+} 0
+test expr-23.54.6 {INST_EXPON: Bug 2798543} {
+ expr {3**15 == 3**65551}
+} 0
+test expr-23.54.7 {INST_EXPON: Bug 2798543} {
+ expr {3**16 == 3**65552}
+} 0
+test expr-23.54.8 {INST_EXPON: Bug 2798543} {
+ expr {3**17 == 3**65553}
+} 0
+test expr-23.54.9 {INST_EXPON: Bug 2798543} {
+ expr {3**18 == 3**65554}
+} 0
+test expr-23.54.10 {INST_EXPON: Bug 2798543} {
+ expr {3**19 == 3**65555}
+} 0
+test expr-23.54.11 {INST_EXPON: Bug 2798543} {
+ expr {3**9 == 3**131081}
+} 0
+test expr-23.54.12 {INST_EXPON: Bug 2798543} -body {
+ expr {3**9 == 3**268435465}
+} -returnCodes error -result {exponent too large}
+test expr-23.54.13 {INST_EXPON: Bug 2798543} {
+ expr {(-3)**9 == (-3)**65545}
+} 0
+test expr-23.55.0 {INST_EXPON: Bug 2798543} {
+ expr {4**9 == 4**65545}
+} 0
+test expr-23.55.1 {INST_EXPON: Bug 2798543} {
+ expr {4**15 == 4**65551}
+} 0
+test expr-23.55.2 {INST_EXPON: Bug 2798543} {
+ expr {4**9 == 4**131081}
+} 0
+test expr-23.55.3 {INST_EXPON: Bug 2798543} -body {
+ expr {4**9 == 4**268435465}
+} -returnCodes error -result {exponent too large}
+test expr-23.55.4 {INST_EXPON: Bug 2798543} {
+ expr {(-4)**9 == (-4)**65545}
+} 0
+test expr-23.56.0 {INST_EXPON: Bug 2798543} {
+ expr {5**9 == 5**65545}
+} 0
+test expr-23.56.1 {INST_EXPON: Bug 2798543} {
+ expr {5**13 == 5**65549}
+} 0
+test expr-23.56.2 {INST_EXPON: Bug 2798543} {
+ expr {5**9 == 5**131081}
+} 0
+test expr-23.56.3 {INST_EXPON: Bug 2798543} -body {
+ expr {5**9 == 5**268435465}
+} -returnCodes error -result {exponent too large}
+test expr-23.56.4 {INST_EXPON: Bug 2798543} {
+ expr {(-5)**9 == (-5)**65545}
+} 0
+test expr-23.57.0 {INST_EXPON: Bug 2798543} {
+ expr {6**9 == 6**65545}
+} 0
+test expr-23.57.1 {INST_EXPON: Bug 2798543} {
+ expr {6**11 == 6**65547}
+} 0
+test expr-23.57.2 {INST_EXPON: Bug 2798543} {
+ expr {6**9 == 6**131081}
+} 0
+test expr-23.57.3 {INST_EXPON: Bug 2798543} -body {
+ expr {6**9 == 6**268435465}
+} -returnCodes error -result {exponent too large}
+test expr-23.57.4 {INST_EXPON: Bug 2798543} {
+ expr {(-6)**9 == (-6)**65545}
+} 0
+test expr-23.58.0 {INST_EXPON: Bug 2798543} {
+ expr {7**9 == 7**65545}
+} 0
+test expr-23.58.1 {INST_EXPON: Bug 2798543} {
+ expr {7**11 == 7**65547}
+} 0
+test expr-23.58.2 {INST_EXPON: Bug 2798543} {
+ expr {7**9 == 7**131081}
+} 0
+test expr-23.58.3 {INST_EXPON: Bug 2798543} -body {
+ expr {7**9 == 7**268435465}
+} -returnCodes error -result {exponent too large}
+test expr-23.58.4 {INST_EXPON: Bug 2798543} {
+ expr {(-7)**9 == (-7)**65545}
+} 0
+test expr-23.59.0 {INST_EXPON: Bug 2798543} {
+ expr {8**9 == 8**65545}
+} 0
+test expr-23.59.1 {INST_EXPON: Bug 2798543} {
+ expr {8**10 == 8**65546}
+} 0
+test expr-23.59.2 {INST_EXPON: Bug 2798543} {
+ expr {8**9 == 8**131081}
+} 0
+test expr-23.59.3 {INST_EXPON: Bug 2798543} -body {
+ expr {8**9 == 8**268435465}
+} -returnCodes error -result {exponent too large}
+test expr-23.59.4 {INST_EXPON: Bug 2798543} {
+ expr {(-8)**9 == (-8)**65545}
+} 0
+test expr-23.60.0 {INST_EXPON: Bug 2798543} {
+ expr {9**9 == 9**65545}
+} 0
+test expr-23.60.1 {INST_EXPON: Bug 2798543} {
+ expr {9**9 == 9**131081}
+} 0
+test expr-23.60.2 {INST_EXPON: Bug 2798543} -body {
+ expr {9**9 == 9**268435465}
+} -returnCodes error -result {exponent too large}
+test expr-23.60.3 {INST_EXPON: Bug 2798543} {
+ expr {(-9)**9 == (-9)**65545}
+} 0
+test expr-23.61.0 {INST_EXPON: Bug 2798543} {
+ expr {10**9 == 10**65545}
+} 0
+test expr-23.61.1 {INST_EXPON: Bug 2798543} {
+ expr {10**9 == 10**131081}
+} 0
+test expr-23.61.2 {INST_EXPON: Bug 2798543} -body {
+ expr {10**9 == 10**268435465}
+} -returnCodes error -result {exponent too large}
+test expr-23.61.3 {INST_EXPON: Bug 2798543} {
+ expr {(-10)**9 == (-10)**65545}
+} 0
+test expr-23.62.0 {INST_EXPON: Bug 2798543} {
+ expr {11**9 == 11**65545}
+} 0
+test expr-23.62.1 {INST_EXPON: Bug 2798543} {
+ expr {11**9 == 11**131081}
+} 0
+test expr-23.62.2 {INST_EXPON: Bug 2798543} -body {
+ expr {11**9 == 11**268435465}
+} -returnCodes error -result {exponent too large}
+test expr-23.62.3 {INST_EXPON: Bug 2798543} {
+ expr {(-11)**9 == (-11)**65545}
+} 0
+test expr-23.63.0 {INST_EXPON: Bug 2798543} {
+ expr {3**20 == 3**65556}
+} 0
+test expr-23.63.1 {INST_EXPON: Bug 2798543} {
+ expr {3**39 == 3**65575}
+} 0
+test expr-23.63.2 {INST_EXPON: Bug 2798543} {
+ expr {3**20 == 3**131092}
+} 0
+test expr-23.63.3 {INST_EXPON: Bug 2798543} -body {
+ expr {3**20 == 3**268435476}
+} -returnCodes error -result {exponent too large}
+test expr-23.63.4 {INST_EXPON: Bug 2798543} {
+ expr {(-3)**20 == (-3)**65556}
+} 0
+test expr-23.64.0 {INST_EXPON: Bug 2798543} {
+ expr {4**17 == 4**65553}
+} 0
+test expr-23.64.1 {INST_EXPON: Bug 2798543} {
+ expr {4**31 == 4**65567}
+} 0
+test expr-23.64.2 {INST_EXPON: Bug 2798543} {
+ expr {4**17 == 4**131089}
+} 0
+test expr-23.64.3 {INST_EXPON: Bug 2798543} -body {
+ expr {4**17 == 4**268435473}
+} -returnCodes error -result {exponent too large}
+test expr-23.64.4 {INST_EXPON: Bug 2798543} {
+ expr {(-4)**17 == (-4)**65553}
+} 0
+test expr-23.65.0 {INST_EXPON: Bug 2798543} {
+ expr {5**17 == 5**65553}
+} 0
+test expr-23.65.1 {INST_EXPON: Bug 2798543} {
+ expr {5**27 == 5**65563}
+} 0
+test expr-23.65.2 {INST_EXPON: Bug 2798543} {
+ expr {5**17 == 5**131089}
+} 0
+test expr-23.65.3 {INST_EXPON: Bug 2798543} -body {
+ expr {5**17 == 5**268435473}
+} -returnCodes error -result {exponent too large}
+test expr-23.65.4 {INST_EXPON: Bug 2798543} {
+ expr {(-5)**17 == (-5)**65553}
+} 0
+test expr-23.66.0 {INST_EXPON: Bug 2798543} {
+ expr {6**17 == 6**65553}
+} 0
+test expr-23.66.1 {INST_EXPON: Bug 2798543} {
+ expr {6**24 == 6**65560}
+} 0
+test expr-23.66.2 {INST_EXPON: Bug 2798543} {
+ expr {6**17 == 6**131089}
+} 0
+test expr-23.66.3 {INST_EXPON: Bug 2798543} -body {
+ expr {6**17 == 6**268435473}
+} -returnCodes error -result {exponent too large}
+test expr-23.66.4 {INST_EXPON: Bug 2798543} {
+ expr {(-6)**17 == (-6)**65553}
+} 0
+test expr-23.67.0 {INST_EXPON: Bug 2798543} {
+ expr {7**17 == 7**65553}
+} 0
+test expr-23.67.1 {INST_EXPON: Bug 2798543} {
+ expr {7**22 == 7**65558}
+} 0
+test expr-23.67.2 {INST_EXPON: Bug 2798543} {
+ expr {7**17 == 7**131089}
+} 0
+test expr-23.67.3 {INST_EXPON: Bug 2798543} -body {
+ expr {7**17 == 7**268435473}
+} -returnCodes error -result {exponent too large}
+test expr-23.67.4 {INST_EXPON: Bug 2798543} {
+ expr {(-7)**17 == (-7)**65553}
+} 0
+test expr-23.68.0 {INST_EXPON: Bug 2798543} {
+ expr {8**17 == 8**65553}
+} 0
+test expr-23.68.1 {INST_EXPON: Bug 2798543} {
+ expr {8**20 == 8**65556}
+} 0
+test expr-23.68.2 {INST_EXPON: Bug 2798543} {
+ expr {8**17 == 8**131089}
+} 0
+test expr-23.68.3 {INST_EXPON: Bug 2798543} -body {
+ expr {8**17 == 8**268435473}
+} -returnCodes error -result {exponent too large}
+test expr-23.68.4 {INST_EXPON: Bug 2798543} {
+ expr {(-8)**17 == (-8)**65553}
+} 0
+test expr-23.69.0 {INST_EXPON: Bug 2798543} {
+ expr {9**17 == 9**65553}
+} 0
+test expr-23.69.1 {INST_EXPON: Bug 2798543} {
+ expr {9**19 == 9**65555}
+} 0
+test expr-23.69.2 {INST_EXPON: Bug 2798543} {
+ expr {9**17 == 9**131089}
+} 0
+test expr-23.69.3 {INST_EXPON: Bug 2798543} -body {
+ expr {9**17 == 9**268435473}
+} -returnCodes error -result {exponent too large}
+test expr-23.69.4 {INST_EXPON: Bug 2798543} {
+ expr {(-9)**17 == (-9)**65553}
+} 0
+test expr-23.70.0 {INST_EXPON: Bug 2798543} {
+ expr {10**17 == 10**65553}
+} 0
+test expr-23.70.1 {INST_EXPON: Bug 2798543} {
+ expr {10**18 == 10**65554}
+} 0
+test expr-23.70.2 {INST_EXPON: Bug 2798543} {
+ expr {10**17 == 10**131089}
+} 0
+test expr-23.70.3 {INST_EXPON: Bug 2798543} -body {
+ expr {10**17 == 10**268435473}
+} -returnCodes error -result {exponent too large}
+test expr-23.70.4 {INST_EXPON: Bug 2798543} {
+ expr {(-10)**17 == (-10)**65553}
+} 0
+test expr-23.71.0 {INST_EXPON: Bug 2798543} {
+ expr {11**17 == 11**65553}
+} 0
+test expr-23.71.1 {INST_EXPON: Bug 2798543} {
+ expr {11**18 == 11**65554}
+} 0
+test expr-23.71.2 {INST_EXPON: Bug 2798543} {
+ expr {11**17 == 11**131089}
+} 0
+test expr-23.71.3 {INST_EXPON: Bug 2798543} -body {
+ expr {11**17 == 11**268435473}
+} -returnCodes error -result {exponent too large}
+test expr-23.71.4 {INST_EXPON: Bug 2798543} {
+ expr {(-11)**17 == (-11)**65553}
+} 0
+test expr-23.72.0 {INST_EXPON: Bug 2798543} {
+ expr {12**17 == 12**65553}
+} 0
+test expr-23.72.1 {INST_EXPON: Bug 2798543} {
+ expr {12**17 == 12**131089}
+} 0
+test expr-23.72.2 {INST_EXPON: Bug 2798543} -body {
+ expr {12**17 == 12**268435473}
+} -returnCodes error -result {exponent too large}
+test expr-23.72.3 {INST_EXPON: Bug 2798543} {
+ expr {(-12)**17 == (-12)**65553}
+} 0
+test expr-23.73.0 {INST_EXPON: Bug 2798543} {
+ expr {13**17 == 13**65553}
+} 0
+test expr-23.73.1 {INST_EXPON: Bug 2798543} {
+ expr {13**17 == 13**131089}
+} 0
+test expr-23.73.2 {INST_EXPON: Bug 2798543} -body {
+ expr {13**17 == 13**268435473}
+} -returnCodes error -result {exponent too large}
+test expr-23.73.3 {INST_EXPON: Bug 2798543} {
+ expr {(-13)**17 == (-13)**65553}
+} 0
+test expr-23.74.0 {INST_EXPON: Bug 2798543} {
+ expr {14**17 == 14**65553}
+} 0
+test expr-23.74.1 {INST_EXPON: Bug 2798543} {
+ expr {14**17 == 14**131089}
+} 0
+test expr-23.74.2 {INST_EXPON: Bug 2798543} -body {
+ expr {14**17 == 14**268435473}
+} -returnCodes error -result {exponent too large}
+test expr-23.74.3 {INST_EXPON: Bug 2798543} {
+ expr {(-14)**17 == (-14)**65553}
+} 0
+
+
# Some compilers get this wrong; ensure that we work around it correctly
-test expr-24.1 {expr edge cases; shifting} {expr int(5)>>31} 0
+test expr-24.1 {expr edge cases; shifting} {expr int(5)>>32} 0
test expr-24.2 {expr edge cases; shifting} {expr int(5)>>63} 0
-test expr-24.3 {expr edge cases; shifting} {expr wide(5)>>31} 0
+test expr-24.3 {expr edge cases; shifting} {expr wide(5)>>32} 0
test expr-24.4 {expr edge cases; shifting} {expr wide(5)>>63} 0
-test expr-24.5 {expr edge cases; shifting} nonPortable {expr int(5)<<31} 0
-test expr-24.6 {expr edge cases; shifting} nonPortable {expr int(5)<<63} 0
-test expr-24.7 {expr edge cases; shifting} {expr wide(5)<<31} 10737418240
-test expr-24.8 {expr edge cases; shifting} nonPortable {expr wide(5)<<63} -9223372036854775808
+test expr-24.5 {expr edge cases; shifting} longIs32bit {expr int(5<<32)} 0
+test expr-24.6 {expr edge cases; shifting} longIs32bit {expr int(5<<63)} 0
+test expr-24.7 {expr edge cases; shifting} {expr wide(5)<<32} 21474836480
+test expr-24.8 {expr edge cases; shifting} {expr wide(10<<63)} 0
test expr-24.9 {expr edge cases; shifting} {expr 5>>32} 0
+test expr-24.10 {INST_LSHIFT: Bug 1567222} {expr 500000000000000<<28} 134217728000000000000000
+
+# List membership tests
+test expr-25.1 {'in' operator} {expr {"a" in "a b c"}} 1
+test expr-25.2 {'in' operator} {expr {"a" in "b a c"}} 1
+test expr-25.3 {'in' operator} {expr {"a" in "b c a"}} 1
+test expr-25.4 {'in' operator} {expr {"a" in ""}} 0
+test expr-25.5 {'in' operator} {expr {"" in {a b c ""}}} 1
+test expr-25.6 {'in' operator} {expr {"" in "a b c"}} 0
+test expr-25.7 {'in' operator} {expr {"" in ""}} 0
+
+test expr-26.1 {'ni' operator} {expr {"a" ni "a b c"}} 0
+test expr-26.2 {'ni' operator} {expr {"a" ni "b a c"}} 0
+test expr-26.3 {'ni' operator} {expr {"a" ni "b c a"}} 0
+test expr-26.4 {'ni' operator} {expr {"a" ni ""}} 1
+test expr-26.5 {'ni' operator} {expr {"" ni {a b c ""}}} 0
+test expr-26.6 {'ni' operator} {expr {"" ni "a b c"}} 1
+test expr-26.7 {'ni' operator} {expr {"" ni ""}} 1
+
+foreach op {< <= == != > >=} {
+ proc test$op {a b} [list expr "\$a $op \$b"]
+}
+
+test expr-27.1 {expr - correct ordering - not compiled} ieeeFloatingPoint {
+ set problems {}
+ # Ordering should be: -Infinity < -Normal < Subnormal < -0
+ # < +0 < +Subnormal < +Normal < +Infinity
+ # with equality within each class.
+ set names {
+ -Infinity -Normal -Subnormal -0 +0 +Subnormal +Normal +Infinity
+ }
+ set weights {
+ -3 -2 -1 0 0 1 2 3
+ }
+ foreach name1 $names weight1 $weights {
+ foreach name2 $names weight2 $weights {
+ foreach op {< <= == != >= >} {
+ set shouldBe [expr "$weight1 $op $weight2"]
+ set is [expr "\$ieeeValues($name1) $op \$ieeeValues($name2)"]
+ if { $is != $shouldBe } {
+ append problems $name1 { } $op { } $name2 \
+ ":result is " $is ", should be $shouldBe" \n
+ }
+ }
+ }
+ }
+ set problems
+} {}
+test expr-27.2 {expr - correct ordering - compiled} ieeeFloatingPoint {
+ set problems {}
+ # Ordering should be: -Infinity < -Normal < Subnormal < -0
+ # < +0 < +Subnormal < +Normal < +Infinity
+ # with equality within each class.
+ set names {
+ -Infinity -Normal -Subnormal -0 +0 +Subnormal +Normal +Infinity
+ }
+ set weights {
+ -3 -2 -1 0 0 1 2 3
+ }
+ foreach name1 $names weight1 $weights {
+ foreach name2 $names weight2 $weights {
+ foreach op {< <= == != >= >} {
+ set shouldBe [expr "$weight1 $op $weight2"]
+ set is [test$op $ieeeValues($name1) $ieeeValues($name2)]
+ if { $is != $shouldBe } {
+ append problems $name1 { } $op { } $name2 \
+ ":result is " $is ", should be $shouldBe" \n
+ }
+ }
+ }
+ }
+ set problems
+} {}
+test expr-27.3 {expr - NaN is unordered - not compiled} {
+ set problems {}
+ set names {
+ -Infinity -Normal -Subnormal -0 +0 +Subnormal +Normal +Infinity NaN
+ }
+ foreach name1 $names {
+ foreach op {< <= == != >= >} sb {0 0 0 1 0 0} {
+ if "(\$ieeeValues($name1) $op \$ieeeValues(NaN)) != $sb " {
+ append problems $name1 { } $op { } NaN \
+ ": result is 1, should be $sb" \n
+ }
+ if "(\$ieeeValues(NaN) $op \$ieeeValues($name1)) != $sb" {
+ append problems NaN { } $op { } $name1 \
+ ": result is 1, should be $sb" \n
+ }
+ }
+ }
+ set problems
+} {}
+test expr-27.4 {expr - NaN is unordered - compiled} {
+ set problems {}
+ set names {
+ -Infinity -Normal -Subnormal -0 +0 +Subnormal +Normal +Infinity NaN
+ }
+ foreach name1 $names {
+ foreach op {< <= == != >= >} sb {0 0 0 1 0 0} {
+ if { [test$op $ieeeValues($name1) $ieeeValues(NaN)] != $sb } {
+ append problems $ieeeValues($name1) { } $op { } $ieeeValues(NaN) \
+ ": result is 1, should be $sb" \n
+ }
+ if { [test$op $ieeeValues(NaN) $ieeeValues($name1)] != $sb } {
+ append problems NaN { } $op { } $ieeeValues($name1) \
+ ": result is 1, should be $sb" \n
+ }
+ }
+ }
+ set problems
+} {}
+
+proc convertToDouble { x } {
+ variable ieeeValues
+ binary scan [binary format d $x] c* bytes
+ set result 0x
+ if { $ieeeValues(littleEndian) } {
+ for { set i 7 } { $i >= 0 } { incr i -1 } {
+ append result [format %02x [expr { [lindex $bytes $i] & 0xff }]]
+ }
+ } else {
+ foreach byte $bytes {
+ append result [format %02x [expr { $byte & 0xff }]]
+ }
+ }
+ return $result
+}
+
+test expr-28.1 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d ALL 0 E0 OK 00000000000000 E-1023
+ convertToDouble 0E0
+} 0x0000000000000000
+test expr-28.2 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d ALL -0 E0 OK -0000000000000 E-1023
+ convertToDouble -0E0
+} 0x8000000000000000
+test expr-28.3 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d ALL 1 E0 OK 10000000000000 E0
+ convertToDouble 1E0
+} 0x3ff0000000000000
+test expr-28.4 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d ALL 15 E-1 OK 18000000000000 E0
+ convertToDouble 15E-1
+} 0x3ff8000000000000
+test expr-28.5 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d ALL 125 E-2 OK 14000000000000 E0
+ convertToDouble 125E-2
+} 0x3ff4000000000000
+test expr-28.6 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d ALL 1125 E-3 OK 12000000000000 E0
+ convertToDouble 1125E-3
+} 0x3ff2000000000000
+test expr-28.7 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d ALL 10625 E-4 OK 11000000000000 E0
+ convertToDouble 10625E-4
+} 0x3ff1000000000000
+test expr-28.8 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d ALL 103125 E-5 OK 10800000000000 E0
+ convertToDouble 103125E-5
+} 0x3ff0800000000000
+test expr-28.9 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d ALL 1015625 E-6 OK 10400000000000 E0
+ convertToDouble 1015625E-6
+} 0x3ff0400000000000
+test expr-28.10 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d ALL 10078125 E-7 OK 10200000000000 E0
+ convertToDouble 10078125E-7
+} 0x3ff0200000000000
+test expr-28.11 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d ALL 100390625 E-8 OK 10100000000000 E0
+ convertToDouble 100390625E-8
+} 0x3ff0100000000000
+test expr-28.12 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee ALL 1001953125 E-9 OK 10080000000000 E0
+ convertToDouble 1001953125E-9
+} 0x3ff0080000000000
+test expr-28.13 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee ALL 10009765625 E-10 OK 10040000000000 E0
+ convertToDouble 10009765625E-10
+} 0x3ff0040000000000
+test expr-28.14 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee ALL 100048828125 E-11 OK 10020000000000 E0
+ convertToDouble 100048828125E-11
+} 0x3ff0020000000000
+test expr-28.15 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee ALL 1000244140625 E-12 OK 10010000000000 E0
+ convertToDouble 1000244140625E-12
+} 0x3ff0010000000000
+test expr-28.16 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee ALL 10001220703125 E-13 OK 10008000000000 E0
+ convertToDouble 10001220703125E-13
+} 0x3ff0008000000000
+test expr-28.17 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee ALL 100006103515625 E-14 OK 10004000000000 E0
+ convertToDouble 100006103515625E-14
+} 0x3ff0004000000000
+test expr-28.18 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee ALL 1000030517578125 E-15 OK 10002000000000 E0
+ convertToDouble 1000030517578125E-15
+} 0x3ff0002000000000
+test expr-28.19 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee ALL 10000152587890625 E-16 OK 10001000000000 E0
+ convertToDouble 10000152587890625E-16
+} 0x3ff0001000000000
+test expr-28.20 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +8 E153 x 1317e5ef3ab327_0000000001& E511
+ convertToDouble +8E153
+} 0x5fe317e5ef3ab327
+test expr-28.21 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -1 E153 x -1317e5ef3ab327_0000000001& E508
+ convertToDouble -1E153
+} 0xdfb317e5ef3ab327
+test expr-28.22 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +9 E306 x 19a2028368022e_00000000001& E1019
+ convertToDouble +9E306
+} 0x7fa9a2028368022e
+test expr-28.23 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -2 E153 x -1317e5ef3ab327_0000000001& E509
+ convertToDouble -2E153
+} 0xdfc317e5ef3ab327
+test expr-28.24 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +7 E-304 x 1eb8e84fa0b278_00000000001& E-1008
+ convertToDouble +7E-304
+} 0x00feb8e84fa0b278
+test expr-28.25 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -3 E-49 x -1c0f92a6276c9d_000000001& E-162
+ convertToDouble -3E-49
+} 0xb5dc0f92a6276c9d
+test expr-28.26 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +7 E-303 x 13339131c46f8b_00000000001& E-1004
+ convertToDouble +7E-303
+} 0x0133339131c46f8b
+test expr-28.27 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -6 E-49 x -1c0f92a6276c9d_000000001& E-161
+ convertToDouble -6E-49
+} 0xb5ec0f92a6276c9d
+test expr-28.28 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +9 E43 x 102498ea6df0c3_11111111110& E146
+ convertToDouble +9E43
+} 0x49102498ea6df0c4
+test expr-28.29 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -9 E44 x -142dbf25096cf4_1111111110& E149
+ convertToDouble -9E44
+} 0xc9442dbf25096cf5
+test expr-28.30 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +8 E303 x 1754e31cd072d9_1111111110& E1009
+ convertToDouble +8E303
+} 0x7f0754e31cd072da
+test expr-28.31 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -1 E303 x -1754e31cd072d9_1111111110& E1006
+ convertToDouble -1E303
+} 0xfed754e31cd072da
+test expr-28.32 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +7 E-287 x 1551603777f798_111111110& E-951
+ convertToDouble +7E-287
+} 0x048551603777f799
+test expr-28.33 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -2 E-204 x -1410d9f9b2f7f2_11111110& E-677
+ convertToDouble -2E-204
+} 0x95a410d9f9b2f7f3
+test expr-28.34 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +2 E-205 x 100d7b2e28c65b_11111110& E-680
+ convertToDouble +2E-205
+} 0x15700d7b2e28c65c
+test expr-28.35 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -9 E-47 x -10711fed5b19a3_11111110& E-153
+ convertToDouble -9E-47
+} 0xb660711fed5b19a4
+test expr-28.36 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +34 E195 x 1d1c26db7d0dae_000000000001& E652
+ convertToDouble +34E195
+} 0x68bd1c26db7d0dae
+test expr-28.37 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -68 E195 x -1d1c26db7d0dae_000000000001& E653
+ convertToDouble -68E195
+} 0xe8cd1c26db7d0dae
+test expr-28.38 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +85 E194 x 1d1c26db7d0dae_000000000001& E650
+ convertToDouble +85E194
+} 0x689d1c26db7d0dae
+test expr-28.39 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -67 E97 x -139ac1ce2cc95f_000000000001& E328
+ convertToDouble -67E97
+} 0xd4739ac1ce2cc95f
+test expr-28.40 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +93 E-234 x 127b2e4f210075_0000000000000001& E-771
+ convertToDouble +93E-234
+} 0x0fc27b2e4f210075
+test expr-28.41 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -19 E-87 x -12e5f5dfa4fe9d_00000000000001& E-285
+ convertToDouble -19E-87
+} 0xae22e5f5dfa4fe9d
+test expr-28.42 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +38 E-87 x 12e5f5dfa4fe9d_00000000000001& E-284
+ convertToDouble +38E-87
+} 0x2e32e5f5dfa4fe9d
+test expr-28.43 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -38 E-88 x -1e3cbc9907fdc8_00000000000001& E-288
+ convertToDouble -38E-88
+} 0xadfe3cbc9907fdc8
+test expr-28.44 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -69 E220 x -1e8aa8823a5db3_11111111110& E736
+ convertToDouble -69E220
+} 0xedfe8aa8823a5db4
+test expr-28.45 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +18 E43 x 102498ea6df0c3_11111111110& E147
+ convertToDouble +18E43
+} 0x49202498ea6df0c4
+test expr-28.46 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -36 E43 x -102498ea6df0c3_11111111110& E148
+ convertToDouble -36E43
+} 0xc9302498ea6df0c4
+test expr-28.47 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +61 E-99 x 10ad836f269a16_11111111111110& E-323
+ convertToDouble +61E-99
+} 0x2bc0ad836f269a17
+test expr-28.48 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -43 E-92 x -1c0794d9d40e95_111111111111110& E-301
+ convertToDouble -43E-92
+} 0xad2c0794d9d40e96
+test expr-28.49 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +86 E-92 x 1c0794d9d40e95_111111111111110& E-300
+ convertToDouble +86E-92
+} 0x2d3c0794d9d40e96
+test expr-28.50 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -51 E-74 x -1cd5bee57763e5_1111111111111110& E-241
+ convertToDouble -51E-74
+} 0xb0ecd5bee57763e6
+test expr-28.51 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +283 E85 x 16c309024bab4b_00000000000000001& E290
+ convertToDouble +283E85
+} 0x5216c309024bab4b
+test expr-28.52 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -566 E85 x -16c309024bab4b_00000000000000001& E291
+ convertToDouble -566E85
+} 0xd226c309024bab4b
+test expr-28.53 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +589 E187 x 1526be9c22eb17_00000000000000001& E630
+ convertToDouble +589E187
+} 0x675526be9c22eb17
+test expr-28.54 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -839 E143 x -1ae03f245703e2_000000000000001& E484
+ convertToDouble -839E143
+} 0xde3ae03f245703e2
+test expr-28.55 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -744 E-234 x -127b2e4f210075_0000000000000001& E-768
+ convertToDouble -744E-234
+} 0x8ff27b2e4f210075
+test expr-28.56 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +930 E-235 x 127b2e4f210075_0000000000000001& E-771
+ convertToDouble +930E-235
+} 0x0fc27b2e4f210075
+test expr-28.57 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -186 E-234 x -127b2e4f210075_0000000000000001& E-770
+ convertToDouble -186E-234
+} 0x8fd27b2e4f210075
+test expr-28.58 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +604 E175 x 17d93193f78fc5_1111111111111111110& E590
+ convertToDouble +604E175
+} 0x64d7d93193f78fc6
+test expr-28.59 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -302 E175 x -17d93193f78fc5_1111111111111111110& E589
+ convertToDouble -302E175
+} 0xe4c7d93193f78fc6
+test expr-28.60 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +755 E174 x 17d93193f78fc5_1111111111111111110& E587
+ convertToDouble +755E174
+} 0x64a7d93193f78fc6
+test expr-28.61 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -151 E175 x -17d93193f78fc5_1111111111111111110& E588
+ convertToDouble -151E175
+} 0xe4b7d93193f78fc6
+test expr-28.62 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +662 E-213 x 1bdb90e62a8cbc_1111111111111110& E-699
+ convertToDouble +662E-213
+} 0x144bdb90e62a8cbd
+test expr-28.63 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -408 E-74 x -1cd5bee57763e5_1111111111111110& E-238
+ convertToDouble -408E-74
+} 0xb11cd5bee57763e6
+test expr-28.64 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +510 E-75 x 1cd5bee57763e5_1111111111111110& E-241
+ convertToDouble +510E-75
+} 0x30ecd5bee57763e6
+test expr-28.65 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +6782 E55 x 159bd3ad46e346_0000000000000000001& E195
+ convertToDouble +6782E55
+} 0x4c259bd3ad46e346
+test expr-28.66 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -2309 E92 x -1bac6f7d64d119_000000000000000001& E316
+ convertToDouble -2309E92
+} 0xd3bbac6f7d64d119
+test expr-28.67 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +7963 E34 x 1df4170f0fdecc_00000000000000000001& E125
+ convertToDouble +7963E34
+} 0x47cdf4170f0fdecc
+test expr-28.68 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -3391 E55 x -159bd3ad46e346_0000000000000000001& E194
+ convertToDouble -3391E55
+} 0xcc159bd3ad46e346
+test expr-28.69 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +7903 E-96 x 107c2d27a5b989_0000000000000000001& E-306
+ convertToDouble +7903E-96
+} 0x2cd07c2d27a5b989
+test expr-28.70 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -7611 E-226 x -119b8744033457_0000000000000000001& E-738
+ convertToDouble -7611E-226
+} 0x91d19b8744033457
+test expr-28.71 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +4907 E-196 x 11e90a8711440f_000000000000000001& E-639
+ convertToDouble +4907E-196
+} 0x1801e90a8711440f
+test expr-28.72 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -5547 E-311 x -13f190452a29f4_000000000000000001& E-1021
+ convertToDouble -5547E-311
+} 0x8023f190452a29f4
+test expr-28.73 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +5311 E241 x 1f1ce3c887c25f_11111111111111111110& E812
+ convertToDouble +5311E241
+} 0x72bf1ce3c887c260
+test expr-28.74 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -5311 E243 x -184e91f4aa0fda_11111111111111111110& E819
+ convertToDouble -5311E243
+} 0xf3284e91f4aa0fdb
+test expr-28.75 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +5311 E242 x 13720e5d54d97b_11111111111111111110& E816
+ convertToDouble +5311E242
+} 0x72f3720e5d54d97c
+test expr-28.76 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +9269 E-45 x 19d69455a53bd8_111111111111111111110& E-137
+ convertToDouble +9269E-45
+} 0x3769d69455a53bd9
+test expr-28.77 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -8559 E-289 x -104a81d35952fe_11111111111111111110& E-947
+ convertToDouble -8559E-289
+} 0x84c04a81d35952ff
+test expr-28.78 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +8699 E-276 x 12d2df246ecd2c_1111111111111111111110& E-904
+ convertToDouble +8699E-276
+} 0x0772d2df246ecd2d
+test expr-28.79 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -8085 E-64 x -14c98fce16152d_1111111111111111110& E-200
+ convertToDouble -8085E-64
+} 0xb374c98fce16152e
+test expr-28.80 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +74819 E201 x 1dd455061eb3f1_0000000000000000000001& E683
+ convertToDouble +74819E201
+} 0x6aadd455061eb3f1
+test expr-28.81 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -82081 E41 x -170105df3d47cb_000000000000000000000000001& E152
+ convertToDouble -82081E41
+} 0xc9770105df3d47cb
+test expr-28.82 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +51881 E37 x 17d2950dc76da4_000000000000000000001& E138
+ convertToDouble +51881E37
+} 0x4897d2950dc76da4
+test expr-28.83 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -55061 E157 x -1394fc0f33536c_000000000000000000001& E537
+ convertToDouble -55061E157
+} 0xe18394fc0f33536c
+test expr-28.84 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +77402 E-215 x 10492a4a8a37fd_0000000000000000000000001& E-698
+ convertToDouble +77402E-215
+} 0x1450492a4a8a37fd
+test expr-28.85 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -33891 E-92 x -1592f9932c06bd_00000000000000000000001& E-291
+ convertToDouble -33891E-92
+} 0xadc592f9932c06bd
+test expr-28.86 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +38701 E-215 x 10492a4a8a37fd_0000000000000000000000001& E-699
+ convertToDouble +38701E-215
+} 0x1440492a4a8a37fd
+test expr-28.87 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -82139 E-76 x -1d0681489839d5_00000000000000000000001& E-237
+ convertToDouble -82139E-76
+} 0xb12d0681489839d5
+test expr-28.88 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +75859 E25 x 132645e1ba93ef_11111111111111111111110& E99
+ convertToDouble +75859E25
+} 0x46232645e1ba93f0
+test expr-28.89 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +89509 E140 x 16f02bee68670c_1111111111111111111110& E481
+ convertToDouble +89509E140
+} 0x5e06f02bee68670d
+test expr-28.90 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -57533 E287 x -1272ed2307f569_1111111111111111111110& E969
+ convertToDouble -57533E287
+} 0xfc8272ed2307f56a
+test expr-28.91 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +46073 E-32 x 12405b773fbdf2_11111111111111111111110& E-91
+ convertToDouble +46073E-32
+} 0x3a42405b773fbdf3
+test expr-28.92 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -92146 E-32 x -12405b773fbdf2_11111111111111111111110& E-90
+ convertToDouble -92146E-32
+} 0xba52405b773fbdf3
+test expr-28.93 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +83771 E-74 x 17206bfc4ccabd_11111111111111111111110& E-230
+ convertToDouble +83771E-74
+} 0x3197206bfc4ccabe
+test expr-28.94 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -34796 E-276 x -12d2df246ecd2c_1111111111111111111110& E-902
+ convertToDouble -34796E-276
+} 0x8792d2df246ecd2d
+test expr-28.95 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +584169 E229 x 1d657059dc79aa_00000000000000000000000000001& E779
+ convertToDouble +584169E229
+} 0x70ad657059dc79aa
+test expr-28.96 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +164162 E41 x 170105df3d47cb_000000000000000000000000001& E153
+ convertToDouble +164162E41
+} 0x49870105df3d47cb
+test expr-28.97 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -328324 E41 x -170105df3d47cb_000000000000000000000000001& E154
+ convertToDouble -328324E41
+} 0xc9970105df3d47cb
+test expr-28.98 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +209901 E-11 x 119b96f36ec68b_00000000000000000000000001& E-19
+ convertToDouble +209901E-11
+} 0x3ec19b96f36ec68b
+test expr-28.99 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -419802 E-11 x -119b96f36ec68b_00000000000000000000000001& E-18
+ convertToDouble -419802E-11
+} 0xbed19b96f36ec68b
+test expr-28.100 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +940189 E-112 x 1b99d6240c1a28_00000000000000000000000001& E-353
+ convertToDouble +940189E-112
+} 0x29eb99d6240c1a28
+test expr-28.101 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -892771 E-213 x -125818c7294f27_0000000000000000000000000001& E-688
+ convertToDouble -892771E-213
+} 0x94f25818c7294f27
+test expr-28.102 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +757803 E120 x 11e968b555bb80_11111111111111111111111111110& E418
+ convertToDouble +757803E120
+} 0x5a11e968b555bb81
+test expr-28.103 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -252601 E120 x -17e1e0f1c7a4ab_11111111111111111111111111110& E416
+ convertToDouble -252601E120
+} 0xd9f7e1e0f1c7a4ac
+test expr-28.104 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +252601 E121 x 1dda592e398dd6_1111111111111111111111111110& E419
+ convertToDouble +252601E121
+} 0x5a2dda592e398dd7
+test expr-28.105 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -505202 E120 x -17e1e0f1c7a4ab_11111111111111111111111111110& E417
+ convertToDouble -505202E120
+} 0xda07e1e0f1c7a4ac
+test expr-28.106 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +970811 E-264 x 1dda6b965c9629_11111111111111111111111110& E-858
+ convertToDouble +970811E-264
+} 0x0a5dda6b965c962a
+test expr-28.107 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -654839 E-60 x -100e7db3b3f241_111111111111111111111111110& E-180
+ convertToDouble -654839E-60
+} 0xb4b00e7db3b3f242
+test expr-28.108 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +289767 E-178 x 1caad28f23a100_11111111111111111111111110& E-574
+ convertToDouble +289767E-178
+} 0x1c1caad28f23a101
+test expr-28.109 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -579534 E-178 x -1caad28f23a100_11111111111111111111111110& E-573
+ convertToDouble -579534E-178
+} 0x9c2caad28f23a101
+test expr-28.110 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -8823691 E130 x -1e597c0b94b7ae_00000000000000000000000000000001& E454
+ convertToDouble -8823691E130
+} 0xdc5e597c0b94b7ae
+test expr-28.111 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +9346704 E229 x 1d657059dc79aa_00000000000000000000000000001& E783
+ convertToDouble +9346704E229
+} 0x70ed657059dc79aa
+test expr-28.112 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -1168338 E229 x -1d657059dc79aa_00000000000000000000000000001& E780
+ convertToDouble -1168338E229
+} 0xf0bd657059dc79aa
+test expr-28.113 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -6063369 E-136 x -1ae6148e3902b3_000000000000000000000000000001& E-430
+ convertToDouble -6063369E-136
+} 0xa51ae6148e3902b3
+test expr-28.114 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +3865421 E-225 x 15d4fe53afec65_00000000000000000000000000001& E-726
+ convertToDouble +3865421E-225
+} 0x1295d4fe53afec65
+test expr-28.115 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -5783893 E-127 x -17e5902ce0e151_000000000000000000000000000000001& E-400
+ convertToDouble -5783893E-127
+} 0xa6f7e5902ce0e151
+test expr-28.116 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +2572231 E223 x 10f73be1dff9ac_111111111111111111111111111110& E762
+ convertToDouble +2572231E223
+} 0x6f90f73be1dff9ad
+test expr-28.117 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -5144462 E223 x -10f73be1dff9ac_111111111111111111111111111110& E763
+ convertToDouble -5144462E223
+} 0xefa0f73be1dff9ad
+test expr-28.118 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +1817623 E109 x 1d85f96f3fe659_11111111111111111111111111110& E382
+ convertToDouble +1817623E109
+} 0x57dd85f96f3fe65a
+test expr-28.119 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +6431543 E-97 x 14f6493f34a0bc_11111111111111111111111111110& E-300
+ convertToDouble +6431543E-97
+} 0x2d34f6493f34a0bd
+test expr-28.120 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -5444097 E-21 x -18849dd33c95ae_11111111111111111111111111110& E-48
+ convertToDouble -5444097E-21
+} 0xbcf8849dd33c95af
+test expr-28.121 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +8076999 E-121 x 1fd332f7e2e3b2_11111111111111111111111111110& E-380
+ convertToDouble +8076999E-121
+} 0x283fd332f7e2e3b3
+test expr-28.122 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -9997649 E-270 x -1425e9d29e558d_1111111111111111111111111110& E-874
+ convertToDouble -9997649E-270
+} 0x895425e9d29e558e
+test expr-28.123 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +50609263 E157 x 1193aff1f1c8e3_000000000000000000000000000000001& E547
+ convertToDouble +50609263E157
+} 0x622193aff1f1c8e3
+test expr-28.124 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +70589528 E130 x 1e597c0b94b7ae_00000000000000000000000000000001& E457
+ convertToDouble +70589528E130
+} 0x5c8e597c0b94b7ae
+test expr-28.125 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -88236910 E129 x -1e597c0b94b7ae_00000000000000000000000000000001& E454
+ convertToDouble -88236910E129
+} 0xdc5e597c0b94b7ae
+test expr-28.126 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +87575437 E-310 x 1805c19e680456_0000000000000000000000000000000000001& E-1004
+ convertToDouble +87575437E-310
+} 0x013805c19e680456
+test expr-28.127 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -23135572 E-127 x -17e5902ce0e151_000000000000000000000000000000001& E-398
+ convertToDouble -23135572E-127
+} 0xa717e5902ce0e151
+test expr-28.128 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +85900881 E177 x 14375b2214e1b4_111111111111111111111111111111110& E614
+ convertToDouble +85900881E177
+} 0x6654375b2214e1b5
+test expr-28.129 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -84863171 E113 x -1a4a8e56474b8b_111111111111111111111111111111110& E401
+ convertToDouble -84863171E113
+} 0xd90a4a8e56474b8c
+test expr-28.130 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +68761586 E232 x 1a662c350f37f2_1111111111111111111111111111110& E796
+ convertToDouble +68761586E232
+} 0x71ba662c350f37f3
+test expr-28.131 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -50464069 E286 x -1948dd06de561e_1111111111111111111111111111110& E975
+ convertToDouble -50464069E286
+} 0xfce948dd06de561f
+test expr-28.132 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +27869147 E-248 x 1dbbac6f83a820_111111111111111111111111111111111110& E-800
+ convertToDouble +27869147E-248
+} 0x0dfdbbac6f83a821
+test expr-28.133 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -55738294 E-248 x -1dbbac6f83a820_111111111111111111111111111111111110& E-799
+ convertToDouble -55738294E-248
+} 0x8e0dbbac6f83a821
+test expr-28.134 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +70176353 E-53 x 100683a21de854_1111111111111111111111111111111110& E-150
+ convertToDouble +70176353E-53
+} 0x36900683a21de855
+test expr-28.135 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -80555086 E-32 x -1f29ca0ff893b0_111111111111111111111111111111110& E-81
+ convertToDouble -80555086E-32
+} 0xbaef29ca0ff893b1
+test expr-28.136 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -491080654 E121 x -1c569e968e0944_00000000000000000000000000000000000000001& E430
+ convertToDouble -491080654E121
+} 0xdadc569e968e0944
+test expr-28.137 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +526250918 E287 x 14997a298b2f2e_0000000000000000000000000000000000001& E982
+ convertToDouble +526250918E287
+} 0x7d54997a298b2f2e
+test expr-28.138 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -245540327 E121 x -1c569e968e0944_00000000000000000000000000000000000000001& E429
+ convertToDouble -245540327E121
+} 0xdacc569e968e0944
+test expr-28.139 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -175150874 E-310 x -1805c19e680456_0000000000000000000000000000000000001& E-1003
+ convertToDouble -175150874E-310
+} 0x814805c19e680456
+test expr-28.140 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +350301748 E-310 x 1805c19e680456_0000000000000000000000000000000000001& E-1002
+ convertToDouble +350301748E-310
+} 0x015805c19e680456
+test expr-28.141 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -437877185 E-311 x -1805c19e680456_0000000000000000000000000000000000001& E-1005
+ convertToDouble -437877185E-311
+} 0x812805c19e680456
+test expr-28.142 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +458117166 E52 x 16ce94febdc7a4_1111111111111111111111111111111111110& E201
+ convertToDouble +458117166E52
+} 0x4c86ce94febdc7a5
+test expr-28.143 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -916234332 E52 x -16ce94febdc7a4_1111111111111111111111111111111111110& E202
+ convertToDouble -916234332E52
+} 0xcc96ce94febdc7a5
+test expr-28.144 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +229058583 E52 x 16ce94febdc7a4_1111111111111111111111111111111111110& E200
+ convertToDouble +229058583E52
+} 0x4c76ce94febdc7a5
+test expr-28.145 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -525789935 E98 x -16ecdc2a58fc64_11111111111111111111111111111111110& E354
+ convertToDouble -525789935E98
+} 0xd616ecdc2a58fc65
+test expr-28.146 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +282926897 E-227 x 1ff5a70d3d2fee_1111111111111111111111111111111111110& E-727
+ convertToDouble +282926897E-227
+} 0x128ff5a70d3d2fef
+test expr-28.147 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -565853794 E-227 x -1ff5a70d3d2fee_1111111111111111111111111111111111110& E-726
+ convertToDouble -565853794E-227
+} 0x929ff5a70d3d2fef
+test expr-28.148 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +667284113 E-240 x 109355f8050c01_111111111111111111111111111111111110& E-768
+ convertToDouble +667284113E-240
+} 0x0ff09355f8050c02
+test expr-28.149 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -971212611 E-126 x -1397d3c9745d2e_111111111111111111111111111111111111110& E-389
+ convertToDouble -971212611E-126
+} 0xa7a397d3c9745d2f
+test expr-28.150 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +9981396317 E-182 x 18afe10a2a66aa_0000000000000000000000000000000000000001& E-572
+ convertToDouble +9981396317E-182
+} 0x1c38afe10a2a66aa
+test expr-28.151 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -5035231965 E-156 x -101891fc4717fd_00000000000000000000000000000000000001& E-486
+ convertToDouble -5035231965E-156
+} 0xa1901891fc4717fd
+test expr-28.152 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +8336960483 E-153 x 1a06a1024b95e1_000000000000000000000000000000000000001& E-476
+ convertToDouble +8336960483E-153
+} 0x223a06a1024b95e1
+test expr-28.153 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -8056371144 E-155 x -101891fc4717fd_00000000000000000000000000000000000001& E-482
+ convertToDouble -8056371144E-155
+} 0xa1d01891fc4717fd
+test expr-28.154 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +6418488827 E79 x 1021f14ed7b3f9_11111111111111111111111111111111111111110& E295
+ convertToDouble +6418488827E79
+} 0x526021f14ed7b3fa
+test expr-28.155 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -3981006983 E252 x -102ebaf189d5f1_1111111111111111111111111111111111111110& E869
+ convertToDouble -3981006983E252
+} 0xf6402ebaf189d5f2
+test expr-28.156 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +7962013966 E252 x 102ebaf189d5f1_1111111111111111111111111111111111111110& E870
+ convertToDouble +7962013966E252
+} 0x76502ebaf189d5f2
+test expr-28.157 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -4713898551 E261 x -11d8813536e0df_11111111111111111111111111111111111110& E899
+ convertToDouble -4713898551E261
+} 0xf821d8813536e0e0
+test expr-28.158 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +8715380633 E-58 x 14614c3219891e_11111111111111111111111111111111111111110& E-160
+ convertToDouble +8715380633E-58
+} 0x35f4614c3219891f
+test expr-28.159 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -9078555839 E-109 x -1fc575867314ed_111111111111111111111111111111111111111111110& E-330
+ convertToDouble -9078555839E-109
+} 0xab5fc575867314ee
+test expr-28.160 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +9712126110 E-127 x 1397d3c9745d2e_111111111111111111111111111111111111110& E-389
+ convertToDouble +9712126110E-127
+} 0x27a397d3c9745d2f
+test expr-28.161 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +42333842451 E201 x 10189a26df575f_000000000000000000000000000000000000000000001& E703
+ convertToDouble +42333842451E201
+} 0x6be0189a26df575f
+test expr-28.162 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -84667684902 E201 x -10189a26df575f_000000000000000000000000000000000000000000001& E704
+ convertToDouble -84667684902E201
+} 0xebf0189a26df575f
+test expr-28.163 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +23792120709 E-315 x 10b517dc5d3212_00000000000000000000000000000000000000001& E-1012
+ convertToDouble +23792120709E-315
+} 0x00b0b517dc5d3212
+test expr-28.164 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -78564021519 E-227 x -1155515fd37265_00000000000000000000000000000000000000000001& E-718
+ convertToDouble -78564021519E-227
+} 0x931155515fd37265
+test expr-28.165 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +71812054883 E-188 x 1747b46d78c6fe_00000000000000000000000000000000000000001& E-589
+ convertToDouble +71812054883E-188
+} 0x1b2747b46d78c6fe
+test expr-28.166 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -30311163631 E-116 x -163ef6f560afe7_00000000000000000000000000000000000000001& E-351
+ convertToDouble -30311163631E-116
+} 0xaa063ef6f560afe7
+test expr-28.167 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +71803914657 E292 x 10c0c44cdc2c05_11111111111111111111111111111111111111111110& E1006
+ convertToDouble +71803914657E292
+} 0x7ed0c0c44cdc2c06
+test expr-28.168 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +36314223356 E-109 x 1fc575867314ed_111111111111111111111111111111111111111111110& E-328
+ convertToDouble +36314223356E-109
+} 0x2b7fc575867314ee
+test expr-28.169 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +18157111678 E-109 x 1fc575867314ed_111111111111111111111111111111111111111111110& E-329
+ convertToDouble +18157111678E-109
+} 0x2b6fc575867314ee
+test expr-28.170 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -45392779195 E-110 x -1fc575867314ed_111111111111111111111111111111111111111111110& E-331
+ convertToDouble -45392779195E-110
+} 0xab4fc575867314ee
+test expr-28.171 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +778380362293 E218 x 19ab8261990292_0000000000000000000000000000000000000000000000000001& E763
+ convertToDouble +778380362293E218
+} 0x6fa9ab8261990292
+test expr-28.172 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -685763015669 E280 x -15fd7aa44d9477_000000000000000000000000000000000000000000000001& E969
+ convertToDouble -685763015669E280
+} 0xfc85fd7aa44d9477
+test expr-28.173 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +952918668151 E70 x 14177a9915fbf8_00000000000000000000000000000000000000000000001& E272
+ convertToDouble +952918668151E70
+} 0x50f4177a9915fbf8
+test expr-28.174 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -548357443505 E32 x -13abde2775e9b5_0000000000000000000000000000000000000000000001& E145
+ convertToDouble -548357443505E32
+} 0xc903abde2775e9b5
+test expr-28.175 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +384865004907 E-285 x 1aa65b58639e69_00000000000000000000000000000000000000000000001& E-909
+ convertToDouble +384865004907E-285
+} 0x072aa65b58639e69
+test expr-28.176 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -769730009814 E-285 x -1aa65b58639e69_00000000000000000000000000000000000000000000001& E-908
+ convertToDouble -769730009814E-285
+} 0x873aa65b58639e69
+test expr-28.177 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +697015418417 E-93 x 152847dad80453_0000000000000000000000000000000000000000000001& E-270
+ convertToDouble +697015418417E-93
+} 0x2f152847dad80453
+test expr-28.178 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -915654049301 E-28 x -1a645598d05989_0000000000000000000000000000000000000000000001& E-54
+ convertToDouble -915654049301E-28
+} 0xbc9a645598d05989
+test expr-28.179 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +178548656339 E169 x 1b89d67c5b6d24_111111111111111111111111111111111111111111110& E598
+ convertToDouble +178548656339E169
+} 0x655b89d67c5b6d25
+test expr-28.180 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -742522891517 E259 x -1c1c352fc3c308_11111111111111111111111111111111111111111111110& E899
+ convertToDouble -742522891517E259
+} 0xf82c1c352fc3c309
+test expr-28.181 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +742522891517 E258 x 167cf7596968d3_11111111111111111111111111111111111111111111110& E896
+ convertToDouble +742522891517E258
+} 0x77f67cf7596968d4
+test expr-28.182 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -357097312678 E169 x -1b89d67c5b6d24_111111111111111111111111111111111111111111110& E599
+ convertToDouble -357097312678E169
+} 0xe56b89d67c5b6d25
+test expr-28.183 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -3113521449172 E218 x -19ab8261990292_0000000000000000000000000000000000000000000000000001& E765
+ convertToDouble -3113521449172E218
+} 0xefc9ab8261990292
+test expr-28.184 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +3891901811465 E217 x 19ab8261990292_0000000000000000000000000000000000000000000000000001& E762
+ convertToDouble +3891901811465E217
+} 0x6f99ab8261990292
+test expr-28.185 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -1556760724586 E218 x -19ab8261990292_0000000000000000000000000000000000000000000000000001& E764
+ convertToDouble -1556760724586E218
+} 0xefb9ab8261990292
+test expr-28.186 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +9997878507563 E-195 x 153db2fea1ea31_0000000000000000000000000000000000000000000000001& E-605
+ convertToDouble +9997878507563E-195
+} 0x1a253db2fea1ea31
+test expr-28.187 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -7247563029154 E-319 x -10493f056e9ef3_0000000000000000000000000000000000000000000000001& E-1017
+ convertToDouble -7247563029154E-319
+} 0x8060493f056e9ef3
+test expr-28.188 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +3623781514577 E-319 x 10493f056e9ef3_0000000000000000000000000000000000000000000000001& E-1018
+ convertToDouble +3623781514577E-319
+} 0x0050493f056e9ef3
+test expr-28.189 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -3092446298323 E-200 x -113918353bbc47_0000000000000000000000000000000000000000000000001& E-623
+ convertToDouble -3092446298323E-200
+} 0x99013918353bbc47
+test expr-28.190 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +6363857920591 E145 x 128a61cf9483b6_1111111111111111111111111111111111111111111111111110& E524
+ convertToDouble +6363857920591E145
+} 0x60b28a61cf9483b7
+test expr-28.191 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -8233559360849 E94 x -11f324d11d4861_1111111111111111111111111111111111111111111111110& E355
+ convertToDouble -8233559360849E94
+} 0xd621f324d11d4862
+test expr-28.192 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +2689845954547 E49 x 10bd2bfd34f98a_1111111111111111111111111111111111111111111111110& E204
+ convertToDouble +2689845954547E49
+} 0x4cb0bd2bfd34f98b
+test expr-28.193 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -5379691909094 E49 x -10bd2bfd34f98a_1111111111111111111111111111111111111111111111110& E205
+ convertToDouble -5379691909094E49
+} 0xccc0bd2bfd34f98b
+test expr-28.194 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +5560322501926 E-301 x 15acc2053064c1_11111111111111111111111111111111111111111111111110& E-958
+ convertToDouble +5560322501926E-301
+} 0x0415acc2053064c2
+test expr-28.195 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -7812878489261 E-179 x -126dae7bbeda74_11111111111111111111111111111111111111111111111111110& E-552
+ convertToDouble -7812878489261E-179
+} 0x9d726dae7bbeda75
+test expr-28.196 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +8439398533053 E-256 x 170cc285f2d209_1111111111111111111111111111111111111111111111110& E-808
+ convertToDouble +8439398533053E-256
+} 0x0d770cc285f2d20a
+test expr-28.197 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -2780161250963 E-301 x -15acc2053064c1_11111111111111111111111111111111111111111111111110& E-959
+ convertToDouble -2780161250963E-301
+} 0x8405acc2053064c2
+test expr-28.198 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -87605699161665 E155 x -12920f96e7f9ef_00000000000000000000000000000000000000000000000000001& E561
+ convertToDouble -87605699161665E155
+} 0xe302920f96e7f9ef
+test expr-28.199 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -17521139832333 E156 x -12920f96e7f9ef_00000000000000000000000000000000000000000000000000001& E562
+ convertToDouble -17521139832333E156
+} 0xe312920f96e7f9ef
+test expr-28.200 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -88218101363513 E-170 x -18395688592faf_0000000000000000000000000000000000000000000000000001& E-519
+ convertToDouble -88218101363513E-170
+} 0x9f88395688592faf
+test expr-28.201 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +38639244311627 E-115 x 114ef3e205c817_0000000000000000000000000000000000000000000000000001& E-337
+ convertToDouble +38639244311627E-115
+} 0x2ae14ef3e205c817
+test expr-28.202 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +35593959807306 E261 x 1072f3819c1320_11111111111111111111111111111111111111111111111111110& E912
+ convertToDouble +35593959807306E261
+} 0x78f072f3819c1321
+test expr-28.203 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -53390939710959 E260 x -13bd243521b08d_11111111111111111111111111111111111111111111111111110& E909
+ convertToDouble -53390939710959E260
+} 0xf8c3bd243521b08e
+test expr-28.204 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +71187919614612 E261 x 1072f3819c1320_11111111111111111111111111111111111111111111111111110& E913
+ convertToDouble +71187919614612E261
+} 0x790072f3819c1321
+test expr-28.205 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -88984899518265 E260 x -1072f3819c1320_11111111111111111111111111111111111111111111111111110& E910
+ convertToDouble -88984899518265E260
+} 0xf8d072f3819c1321
+test expr-28.206 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +77003665618895 E-73 x 18bf7e7fa6f029_111111111111111111111111111111111111111111111111111111110& E-197
+ convertToDouble +77003665618895E-73
+} 0x33a8bf7e7fa6f02a
+test expr-28.207 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -15400733123779 E-72 x -18bf7e7fa6f029_111111111111111111111111111111111111111111111111111111110& E-196
+ convertToDouble -15400733123779E-72
+} 0xb3b8bf7e7fa6f02a
+test expr-28.208 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +61602932495116 E-72 x 18bf7e7fa6f029_111111111111111111111111111111111111111111111111111111110& E-194
+ convertToDouble +61602932495116E-72
+} 0x33d8bf7e7fa6f02a
+test expr-28.209 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -30801466247558 E-72 x -18bf7e7fa6f029_111111111111111111111111111111111111111111111111111111110& E-195
+ convertToDouble -30801466247558E-72
+} 0xb3c8bf7e7fa6f02a
+test expr-28.210 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +834735494917063 E-300 x 1fc6c26f899dd1_0000000000000000000000000000000000000000000000000000000001& E-948
+ convertToDouble +834735494917063E-300
+} 0x04bfc6c26f899dd1
+test expr-28.211 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -589795149206434 E-151 x -15f2df5e675a0f_0000000000000000000000000000000000000000000000000000000001& E-453
+ convertToDouble -589795149206434E-151
+} 0xa3a5f2df5e675a0f
+test expr-28.212 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +475603213226859 E-42 x 12d73088f4050a_000000000000000000000000000000000000000000000000000000001& E-91
+ convertToDouble +475603213226859E-42
+} 0x3a42d73088f4050a
+test expr-28.213 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -294897574603217 E-151 x -15f2df5e675a0f_0000000000000000000000000000000000000000000000000000000001& E-454
+ convertToDouble -294897574603217E-151
+} 0xa395f2df5e675a0f
+test expr-28.214 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +850813008001913 E93 x 172f7a1831ad70_11111111111111111111111111111111111111111111111111111110& E358
+ convertToDouble +850813008001913E93
+} 0x56572f7a1831ad71
+test expr-28.215 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -203449172043339 E185 x -1102b47e4af987_11111111111111111111111111111111111111111111111111111110& E662
+ convertToDouble -203449172043339E185
+} 0xe95102b47e4af988
+test expr-28.216 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +406898344086678 E185 x 1102b47e4af987_11111111111111111111111111111111111111111111111111111110& E663
+ convertToDouble +406898344086678E185
+} 0x696102b47e4af988
+test expr-28.217 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -813796688173356 E185 x -1102b47e4af987_11111111111111111111111111111111111111111111111111111110& E664
+ convertToDouble -813796688173356E185
+} 0xe97102b47e4af988
+test expr-28.218 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +6045338514609393 E244 x 1f746182e6cd5d_00000000000000000000000000000000000000000000000000000000001& E862
+ convertToDouble +6045338514609393E244
+} 0x75df746182e6cd5d
+test expr-28.219 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -5145963778954906 E142 x -1dfc11fbf46087_00000000000000000000000000000000000000000000000000000000001& E523
+ convertToDouble -5145963778954906E142
+} 0xe0adfc11fbf46087
+test expr-28.220 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +2572981889477453 E142 x 1dfc11fbf46087_00000000000000000000000000000000000000000000000000000000001& E522
+ convertToDouble +2572981889477453E142
+} 0x609dfc11fbf46087
+test expr-28.221 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -6965949469487146 E74 x -15e2c10ad970b0_0000000000000000000000000000000000000000000000000000000001& E298
+ convertToDouble -6965949469487146E74
+} 0xd295e2c10ad970b0
+test expr-28.222 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +6182410494241627 E-119 x 11b96458445d07_0000000000000000000000000000000000000000000000000000000000001& E-343
+ convertToDouble +6182410494241627E-119
+} 0x2a81b96458445d07
+test expr-28.223 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -8510309498186985 E-277 x -1acc46749dccfe_000000000000000000000000000000000000000000000000000000000001& E-868
+ convertToDouble -8510309498186985E-277
+} 0x89bacc46749dccfe
+test expr-28.224 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +6647704637273331 E-212 x 13e07d2c0cb1e9_0000000000000000000000000000000000000000000000000000000000001& E-652
+ convertToDouble +6647704637273331E-212
+} 0x1733e07d2c0cb1e9
+test expr-28.225 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -2215901545757777 E-212 x -1a80a6e566428c_000000000000000000000000000000000000000000000000000000000001& E-654
+ convertToDouble -2215901545757777E-212
+} 0x971a80a6e566428c
+test expr-28.226 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +3771476185376383 E276 x 183010aba78a53_111111111111111111111111111111111111111111111111111111111110& E968
+ convertToDouble +3771476185376383E276
+} 0x7c783010aba78a54
+test expr-28.227 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -3729901848043846 E212 x -1f7d6721f7f143_111111111111111111111111111111111111111111111111111111111110& E755
+ convertToDouble -3729901848043846E212
+} 0xef2f7d6721f7f144
+test expr-28.228 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +3771476185376383 E277 x 1e3c14d6916ce8_111111111111111111111111111111111111111111111111111111111110& E971
+ convertToDouble +3771476185376383E277
+} 0x7cae3c14d6916ce9
+test expr-28.229 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -9977830465649166 E119 x -15f6de9d5d6b5a_111111111111111111111111111111111111111111111111111111111110& E448
+ convertToDouble -9977830465649166E119
+} 0xdbf5f6de9d5d6b5b
+test expr-28.230 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +8439928496349319 E-142 x 12483a0f125699_111111111111111111111111111111111111111111111111111111111110& E-419
+ convertToDouble +8439928496349319E-142
+} 0x25c2483a0f12569a
+test expr-28.231 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -8204230082070882 E-59 x -1d460f4fca1d36_1111111111111111111111111111111111111111111111111111111110& E-144
+ convertToDouble -8204230082070882E-59
+} 0xb6fd460f4fca1d37
+test expr-28.232 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +8853686434843997 E-244 x 157a340eb5d4f0_11111111111111111111111111111111111111111111111111111111110& E-758
+ convertToDouble +8853686434843997E-244
+} 0x10957a340eb5d4f1
+test expr-28.233 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -5553274272288559 E-104 x -1c47d20a19d1ed_1111111111111111111111111111111111111111111111111111111110& E-294
+ convertToDouble -5553274272288559E-104
+} 0xad9c47d20a19d1ee
+test expr-28.234 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +36149023611096162 E144 x 1491daad0ba280_0000000000000000000000000000000000000000000000000000000000000001& E533
+ convertToDouble +36149023611096162E144
+} 0x614491daad0ba280
+test expr-28.235 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -36149023611096162 E147 x -14166f8cfd5cb1_0000000000000000000000000000000000000000000000000000000000000001& E543
+ convertToDouble -36149023611096162E147
+} 0xe1e4166f8cfd5cb1
+test expr-28.236 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +18074511805548081 E146 x 1011f2d73116f4_0000000000000000000000000000000000000000000000000000000000000001& E539
+ convertToDouble +18074511805548081E146
+} 0x61a011f2d73116f4
+test expr-28.237 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -18074511805548081 E147 x -14166f8cfd5cb1_0000000000000000000000000000000000000000000000000000000000000001& E542
+ convertToDouble -18074511805548081E147
+} 0xe1d4166f8cfd5cb1
+test expr-28.238 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +97338774138954421 E-290 x 10d9b828199006_0000000000000000000000000000000000000000000000000000000000000001& E-907
+ convertToDouble +97338774138954421E-290
+} 0x0740d9b828199006
+test expr-28.239 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -88133809804950961 E-308 x -119710dc581911_000000000000000000000000000000000000000000000000000000000000001& E-967
+ convertToDouble -88133809804950961E-308
+} 0x83819710dc581911
+test expr-28.240 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +94080055902682397 E-243 x 11d467e94b856e_0000000000000000000000000000000000000000000000000000000000000001& E-751
+ convertToDouble +94080055902682397E-243
+} 0x1101d467e94b856e
+test expr-28.241 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -24691002732654881 E-115 x -159a2783ce70ab_000000000000000000000000000000000000000000000000000000000000001& E-328
+ convertToDouble -24691002732654881E-115
+} 0xab759a2783ce70ab
+test expr-28.242 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +52306490527514614 E49 x 13de005bd620de_111111111111111111111111111111111111111111111111111111111111111110& E218
+ convertToDouble +52306490527514614E49
+} 0x4d93de005bd620df
+test expr-28.243 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -26153245263757307 E49 x -13de005bd620de_111111111111111111111111111111111111111111111111111111111111111110& E217
+ convertToDouble -26153245263757307E49
+} 0xcd83de005bd620df
+test expr-28.244 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +55188692254193604 E165 x 1a999ddec72ac9_11111111111111111111111111111111111111111111111111111111111110& E603
+ convertToDouble +55188692254193604E165
+} 0x65aa999ddec72aca
+test expr-28.245 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -68985865317742005 E164 x -1a999ddec72ac9_11111111111111111111111111111111111111111111111111111111111110& E600
+ convertToDouble -68985865317742005E164
+} 0xe57a999ddec72aca
+test expr-28.246 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +27176258005319167 E-261 x 17c0747bd76fa0_11111111111111111111111111111111111111111111111111111111111111110& E-813
+ convertToDouble +27176258005319167E-261
+} 0x0d27c0747bd76fa1
+test expr-28.247 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -73169230107256116 E-248 x -122cea327fa99c_1111111111111111111111111111111111111111111111111111111111110& E-768
+ convertToDouble -73169230107256116E-248
+} 0x8ff22cea327fa99d
+test expr-28.248 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +91461537634070145 E-249 x 122cea327fa99c_1111111111111111111111111111111111111111111111111111111111110& E-771
+ convertToDouble +91461537634070145E-249
+} 0x0fc22cea327fa99d
+test expr-28.249 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -54352516010638334 E-261 x -17c0747bd76fa0_11111111111111111111111111111111111111111111111111111111111111110& E-812
+ convertToDouble -54352516010638334E-261
+} 0x8d37c0747bd76fa1
+test expr-28.250 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +586144289638535878 E280 x 11eccbd6f62709_0000000000000000000000000000000000000000000000000000000000000000001& E989
+ convertToDouble +586144289638535878E280
+} 0x7dc1eccbd6f62709
+test expr-28.251 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -601117006785295431 E245 x -1e8b3525b3737e_000000000000000000000000000000000000000000000000000000000000000001& E872
+ convertToDouble -601117006785295431E245
+} 0xf67e8b3525b3737e
+test expr-28.252 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +293072144819267939 E280 x 11eccbd6f62709_0000000000000000000000000000000000000000000000000000000000000000001& E988
+ convertToDouble +293072144819267939E280
+} 0x7db1eccbd6f62709
+test expr-28.253 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -953184713238516652 E272 x -138fd93f1f5342_00000000000000000000000000000000000000000000000000000000000000001& E963
+ convertToDouble -953184713238516652E272
+} 0xfc238fd93f1f5342
+test expr-28.254 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +902042358290366539 E-281 x 122dc01ca1cb8c_0000000000000000000000000000000000000000000000000000000000000000001& E-874
+ convertToDouble +902042358290366539E-281
+} 0x09522dc01ca1cb8c
+test expr-28.255 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -557035730189854663 E-294 x -13bfac6bc4767b_00000000000000000000000000000000000000000000000000000000000000000001& E-918
+ convertToDouble -557035730189854663E-294
+} 0x8693bfac6bc4767b
+test expr-28.256 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +902042358290366539 E-280 x 16b93023ca3e6f_0000000000000000000000000000000000000000000000000000000000000000001& E-871
+ convertToDouble +902042358290366539E-280
+} 0x0986b93023ca3e6f
+test expr-28.257 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -354944100507554393 E-238 x -19a91cece6ad07_000000000000000000000000000000000000000000000000000000000000000001& E-733
+ convertToDouble -354944100507554393E-238
+} 0x9229a91cece6ad07
+test expr-28.258 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +272104041512242479 E199 x 1f92bacb3cb40b_11111111111111111111111111111111111111111111111111111111111111111111110& E718
+ convertToDouble +272104041512242479E199
+} 0x6cdf92bacb3cb40c
+test expr-28.259 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -816312124536727437 E199 x -17ae0c186d8708_11111111111111111111111111111111111111111111111111111111111111111111110& E720
+ convertToDouble -816312124536727437E199
+} 0xecf7ae0c186d8709
+test expr-28.260 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +544208083024484958 E199 x 1f92bacb3cb40b_11111111111111111111111111111111111111111111111111111111111111111111110& E719
+ convertToDouble +544208083024484958E199
+} 0x6cef92bacb3cb40c
+test expr-28.261 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -792644927852378159 E78 x -17bff336d8ff05_111111111111111111111111111111111111111111111111111111111111111111110& E318
+ convertToDouble -792644927852378159E78
+} 0xd3d7bff336d8ff06
+test expr-28.262 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -679406450132979175 E-263 x -17c0747bd76fa0_11111111111111111111111111111111111111111111111111111111111111110& E-815
+ convertToDouble -679406450132979175E-263
+} 0x8d07c0747bd76fa1
+test expr-28.263 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +543525160106383340 E-262 x 17c0747bd76fa0_11111111111111111111111111111111111111111111111111111111111111110& E-812
+ convertToDouble +543525160106383340E-262
+} 0x0d37c0747bd76fa1
+test expr-28.264 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +7400253695682920196 E215 x 1dca94e3990085_00000000000000000000000000000000000000000000000000000000000000000000001& E776
+ convertToDouble +7400253695682920196E215
+} 0x707dca94e3990085
+test expr-28.265 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -1850063423920730049 E215 x -1dca94e3990085_00000000000000000000000000000000000000000000000000000000000000000000001& E774
+ convertToDouble -1850063423920730049E215
+} 0xf05dca94e3990085
+test expr-28.266 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +3700126847841460098 E215 x 1dca94e3990085_00000000000000000000000000000000000000000000000000000000000000000000001& E775
+ convertToDouble +3700126847841460098E215
+} 0x706dca94e3990085
+test expr-28.267 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -9250317119603650245 E214 x -1dca94e3990085_00000000000000000000000000000000000000000000000000000000000000000000001& E773
+ convertToDouble -9250317119603650245E214
+} 0xf04dca94e3990085
+test expr-28.268 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +8396094300569779681 E-252 x 1ab223efcee35a_0000000000000000000000000000000000000000000000000000000000000000000000001& E-775
+ convertToDouble +8396094300569779681E-252
+} 0x0f8ab223efcee35a
+test expr-28.269 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -3507665085003296281 E-75 x -160499b881ea50_00000000000000000000000000000000000000000000000000000000000000000000001& E-188
+ convertToDouble -3507665085003296281E-75
+} 0xb4360499b881ea50
+test expr-28.270 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +7015330170006592562 E-75 x 160499b881ea50_00000000000000000000000000000000000000000000000000000000000000000000001& E-187
+ convertToDouble +7015330170006592562E-75
+} 0x34460499b881ea50
+test expr-28.271 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -7015330170006592562 E-74 x -1b85c026a264e4_00000000000000000000000000000000000000000000000000000000000000000000001& E-184
+ convertToDouble -7015330170006592562E-74
+} 0xb47b85c026a264e4
+test expr-28.272 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +7185620434951919351 E205 x 18d92d2bcc7a80_1111111111111111111111111111111111111111111111111111111111111111111111110& E743
+ convertToDouble +7185620434951919351E205
+} 0x6e68d92d2bcc7a81
+test expr-28.273 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -1360520207561212395 E198 x -1f92bacb3cb40b_11111111111111111111111111111111111111111111111111111111111111111111110& E717
+ convertToDouble -1360520207561212395E198
+} 0xeccf92bacb3cb40c
+test expr-28.274 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +2178999185345151731 E-184 x 19b2c4d2a82335_1111111111111111111111111111111111111111111111111111111111111111111110& E-551
+ convertToDouble +2178999185345151731E-184
+} 0x1d89b2c4d2a82336
+test expr-28.275 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -8691089486201567102 E-218 x -1a9c42e5b6d89e_1111111111111111111111111111111111111111111111111111111111111111111110& E-662
+ convertToDouble -8691089486201567102E-218
+} 0x969a9c42e5b6d89f
+test expr-28.276 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +4345544743100783551 E-218 x 1a9c42e5b6d89e_1111111111111111111111111111111111111111111111111111111111111111111110& E-663
+ convertToDouble +4345544743100783551E-218
+} 0x168a9c42e5b6d89f
+test expr-28.277 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -4357998370690303462 E-184 x -19b2c4d2a82335_1111111111111111111111111111111111111111111111111111111111111111111110& E-550
+ convertToDouble -4357998370690303462E-184
+} 0x9d99b2c4d2a82336
+test expr-28.278 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +59825267349106892461 E177 x 199c476d7868df_000000000000000000000000000000000000000000000000000000000000000000000001& E653
+ convertToDouble +59825267349106892461E177
+} 0x68c99c476d7868df
+test expr-28.279 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -62259110684423957791 E47 x -1d8f2cfc20d6e8_0000000000000000000000000000000000000000000000000000000000000000000000001& E221
+ convertToDouble -62259110684423957791E47
+} 0xcdcd8f2cfc20d6e8
+test expr-28.280 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +58380168477038565599 E265 x 1f686e9efbe48d_00000000000000000000000000000000000000000000000000000000000000000000000001& E945
+ convertToDouble +58380168477038565599E265
+} 0x7b0f686e9efbe48d
+test expr-28.281 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -62259110684423957791 E48 x -12797c1d948651_0000000000000000000000000000000000000000000000000000000000000000000000001& E225
+ convertToDouble -62259110684423957791E48
+} 0xce02797c1d948651
+test expr-28.282 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -33584377202279118724 E-252 x -1ab223efcee35a_0000000000000000000000000000000000000000000000000000000000000000000000001& E-773
+ convertToDouble -33584377202279118724E-252
+} 0x8faab223efcee35a
+test expr-28.283 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -57484963479615354808 E205 x -18d92d2bcc7a80_1111111111111111111111111111111111111111111111111111111111111111111111110& E746
+ convertToDouble -57484963479615354808E205
+} 0xee98d92d2bcc7a81
+test expr-28.284 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +71856204349519193510 E204 x 18d92d2bcc7a80_1111111111111111111111111111111111111111111111111111111111111111111111110& E743
+ convertToDouble +71856204349519193510E204
+} 0x6e68d92d2bcc7a81
+test expr-28.285 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -14371240869903838702 E205 x -18d92d2bcc7a80_1111111111111111111111111111111111111111111111111111111111111111111111110& E744
+ convertToDouble -14371240869903838702E205
+} 0xee78d92d2bcc7a81
+test expr-28.286 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +36992084760177624177 E-318 x 18c5f9551c2f99_111111111111111111111111111111111111111111111111111111111111111111111110& E-992
+ convertToDouble +36992084760177624177E-318
+} 0x01f8c5f9551c2f9a
+test expr-28.287 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -73984169520355248354 E-318 x -18c5f9551c2f99_111111111111111111111111111111111111111111111111111111111111111111111110& E-991
+ convertToDouble -73984169520355248354E-318
+} 0x8208c5f9551c2f9a
+test expr-28.288 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +99257763227713890244 E-115 x 15338a554b9ce0_11111111111111111111111111111111111111111111111111111111111111111111110& E-316
+ convertToDouble +99257763227713890244E-115
+} 0x2c35338a554b9ce1
+test expr-28.289 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -87336362425182547697 E-280 x -1130304e7d9c32_11111111111111111111111111111111111111111111111111111111111111111111110& E-864
+ convertToDouble -87336362425182547697E-280
+} 0x89f130304e7d9c33
+test expr-28.290 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +7 E289 x 1cbb547777a284_10000000001& E962
+ convertToDouble +7E289
+} 0x7c1cbb547777a285
+test expr-28.291 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -3 E153 x -1ca3d8e6d80cba_100000001& E509
+ convertToDouble -3E153
+} 0xdfcca3d8e6d80cbb
+test expr-28.292 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +6 E153 x 1ca3d8e6d80cba_100000001& E510
+ convertToDouble +6E153
+} 0x5fdca3d8e6d80cbb
+test expr-28.293 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -5 E243 x -176ec98994f488_10000001& E809
+ convertToDouble -5E243
+} 0xf2876ec98994f489
+test expr-28.294 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +7 E-161 x 1f7e0db3799aa2_10000000001& E-533
+ convertToDouble +7E-161
+} 0x1eaf7e0db3799aa3
+test expr-28.295 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -7 E-172 x -15a4337446ef2a_1000000001& E-569
+ convertToDouble -7E-172
+} 0x9c65a4337446ef2b
+test expr-28.296 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +8 E-63 x 1a53fc9631d10c_10000001& E-207
+ convertToDouble +8E-63
+} 0x330a53fc9631d10d
+test expr-28.297 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -7 E-113 x -158c47e6eea282_10000001& E-373
+ convertToDouble -7E-113
+} 0xa8a58c47e6eea283
+test expr-28.298 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +8 E126 x 17a2ecc414a03f_0111111111110& E421
+ convertToDouble +8E126
+} 0x5a47a2ecc414a03f
+test expr-28.299 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -4 E126 x -17a2ecc414a03f_0111111111110& E420
+ convertToDouble -4E126
+} 0xda37a2ecc414a03f
+test expr-28.300 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +5 E125 x 17a2ecc414a03f_0111111111110& E417
+ convertToDouble +5E125
+} 0x5a07a2ecc414a03f
+test expr-28.301 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -1 E126 x -17a2ecc414a03f_0111111111110& E418
+ convertToDouble -1E126
+} 0xda17a2ecc414a03f
+test expr-28.302 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +8 E-163 x 1708d0f84d3de7_011111110& E-539
+ convertToDouble +8E-163
+} 0x1e4708d0f84d3de7
+test expr-28.303 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -1 E-163 x -1708d0f84d3de7_011111110& E-542
+ convertToDouble -1E-163
+} 0x9e1708d0f84d3de7
+test expr-28.304 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +2 E-163 x 1708d0f84d3de7_011111110& E-541
+ convertToDouble +2E-163
+} 0x1e2708d0f84d3de7
+test expr-28.305 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -4 E-163 x -1708d0f84d3de7_011111110& E-540
+ convertToDouble -4E-163
+} 0x9e3708d0f84d3de7
+test expr-28.306 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +51 E195 x 15d51d249dca42_1000000000001& E653
+ convertToDouble +51E195
+} 0x68c5d51d249dca43
+test expr-28.307 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -37 E46 x -1033d7eca0adee_100000000000001& E158
+ convertToDouble -37E46
+} 0xc9d033d7eca0adef
+test expr-28.308 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +74 E46 x 1033d7eca0adee_100000000000001& E159
+ convertToDouble +74E46
+} 0x49e033d7eca0adef
+test expr-28.309 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -56 E289 x -1cbb547777a284_10000000001& E965
+ convertToDouble -56E289
+} 0xfc4cbb547777a285
+test expr-28.310 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +69 E-145 x 158a41b31c9a9a_100000000001& E-476
+ convertToDouble +69E-145
+} 0x22358a41b31c9a9b
+test expr-28.311 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -70 E-162 x -1f7e0db3799aa2_10000000001& E-533
+ convertToDouble -70E-162
+} 0x9eaf7e0db3799aa3
+test expr-28.312 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +56 E-161 x 1f7e0db3799aa2_10000000001& E-530
+ convertToDouble +56E-161
+} 0x1edf7e0db3799aa3
+test expr-28.313 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -21 E-303 x -1ccd59caa6a750_10000000001& E-1003
+ convertToDouble -21E-303
+} 0x814ccd59caa6a751
+test expr-28.314 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +34 E-276 x 12d5a4350d30ff_011111111110& E-912
+ convertToDouble +34E-276
+} 0x06f2d5a4350d30ff
+test expr-28.315 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -68 E-276 x -12d5a4350d30ff_011111111110& E-911
+ convertToDouble -68E-276
+} 0x8702d5a4350d30ff
+test expr-28.316 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +85 E-277 x 12d5a4350d30ff_011111111110& E-914
+ convertToDouble +85E-277
+} 0x06d2d5a4350d30ff
+test expr-28.317 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -87 E-274 x -12d36cf48e7abd_011111111111110& E-904
+ convertToDouble -87E-274
+} 0x8772d36cf48e7abd
+test expr-28.318 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +829 E102 x 17221a79cdd1d8_1000000000000001& E348
+ convertToDouble +829E102
+} 0x55b7221a79cdd1d9
+test expr-28.319 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -623 E100 x -1640a62f3a83de_10000000000000000001& E341
+ convertToDouble -623E100
+} 0xd54640a62f3a83df
+test expr-28.320 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +723 E-162 x 145457ee24abd2_1000000000000001& E-529
+ convertToDouble +723E-162
+} 0x1ee45457ee24abd3
+test expr-28.321 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -457 E-102 x -1ffc81bc29f02a_100000000000000001& E-331
+ convertToDouble -457E-102
+} 0xab4ffc81bc29f02b
+test expr-28.322 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +914 E-102 x 1ffc81bc29f02a_100000000000000001& E-330
+ convertToDouble +914E-102
+} 0x2b5ffc81bc29f02b
+test expr-28.323 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -323 E-135 x -1d589ae4d70218_10000000000001& E-441
+ convertToDouble -323E-135
+} 0xa46d589ae4d70219
+test expr-28.324 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +151 E176 x 1dcf7df8f573b7_0111111111111111110& E591
+ convertToDouble +151E176
+} 0x64edcf7df8f573b7
+test expr-28.325 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -302 E176 x -1dcf7df8f573b7_0111111111111111110& E592
+ convertToDouble -302E176
+} 0xe4fdcf7df8f573b7
+test expr-28.326 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +921 E90 x 1c420a45fd70ff_0111111111111110& E308
+ convertToDouble +921E90
+} 0x533c420a45fd70ff
+test expr-28.327 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -604 E176 x -1dcf7df8f573b7_0111111111111111110& E593
+ convertToDouble -604E176
+} 0xe50dcf7df8f573b7
+test expr-28.328 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +823 E-206 x 14a48933c208ad_0111111111111110& E-675
+ convertToDouble +823E-206
+} 0x15c4a48933c208ad
+test expr-28.329 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -463 E-114 x -11d0c83f6378a5_011111111111110& E-370
+ convertToDouble -463E-114
+} 0xa8d1d0c83f6378a5
+test expr-28.330 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +348 E-274 x 12d36cf48e7abd_011111111111110& E-902
+ convertToDouble +348E-274
+} 0x0792d36cf48e7abd
+test expr-28.331 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +9968 E100 x 1640a62f3a83de_10000000000000000001& E345
+ convertToDouble +9968E100
+} 0x558640a62f3a83df
+test expr-28.332 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -6230 E99 x -1640a62f3a83de_10000000000000000001& E341
+ convertToDouble -6230E99
+} 0xd54640a62f3a83df
+test expr-28.333 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +1246 E100 x 1640a62f3a83de_10000000000000000001& E342
+ convertToDouble +1246E100
+} 0x555640a62f3a83df
+test expr-28.334 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +6676 E-296 x 15519ac5142aaa_1000000000000000000001& E-971
+ convertToDouble +6676E-296
+} 0x0345519ac5142aab
+test expr-28.335 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -8345 E-297 x -15519ac5142aaa_1000000000000000000001& E-974
+ convertToDouble -8345E-297
+} 0x8315519ac5142aab
+test expr-28.336 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +1669 E-296 x 15519ac5142aaa_1000000000000000000001& E-973
+ convertToDouble +1669E-296
+} 0x0325519ac5142aab
+test expr-28.337 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -3338 E-296 x -15519ac5142aaa_1000000000000000000001& E-972
+ convertToDouble -3338E-296
+} 0x8335519ac5142aab
+test expr-28.338 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +3257 E58 x 1444b34a6fb3eb_01111111111111111110& E204
+ convertToDouble +3257E58
+} 0x4cb444b34a6fb3eb
+test expr-28.339 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -6514 E58 x -1444b34a6fb3eb_01111111111111111110& E205
+ convertToDouble -6514E58
+} 0xccc444b34a6fb3eb
+test expr-28.340 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +2416 E176 x 1dcf7df8f573b7_0111111111111111110& E595
+ convertToDouble +2416E176
+} 0x652dcf7df8f573b7
+test expr-28.341 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +8085 E-63 x 19fbf3c19b9a79_0111111111111111110& E-197
+ convertToDouble +8085E-63
+} 0x33a9fbf3c19b9a79
+test expr-28.342 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -3234 E-62 x -19fbf3c19b9a79_0111111111111111110& E-195
+ convertToDouble -3234E-62
+} 0xb3c9fbf3c19b9a79
+test expr-28.343 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +1617 E-62 x 19fbf3c19b9a79_0111111111111111110& E-196
+ convertToDouble +1617E-62
+} 0x33b9fbf3c19b9a79
+test expr-28.344 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -6468 E-62 x -19fbf3c19b9a79_0111111111111111110& E-194
+ convertToDouble -6468E-62
+} 0xb3d9fbf3c19b9a79
+test expr-28.345 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +53418 E111 x 15b1051df943a8_1000000000000000000001& E384
+ convertToDouble +53418E111
+} 0x57f5b1051df943a9
+test expr-28.346 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -60513 E160 x -15043b64e56c72_1000000000000000000001& E547
+ convertToDouble -60513E160
+} 0xe225043b64e56c73
+test expr-28.347 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +26709 E111 x 15b1051df943a8_1000000000000000000001& E383
+ convertToDouble +26709E111
+} 0x57e5b1051df943a9
+test expr-28.348 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -99447 E166 x -10782189b336ae_1000000000000000000001& E568
+ convertToDouble -99447E166
+} 0xe370782189b336af
+test expr-28.349 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +12549 E48 x 10c52fe6dc6a1b_011111111111111111111110& E173
+ convertToDouble +12549E48
+} 0x4ac0c52fe6dc6a1b
+test expr-28.350 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -25098 E48 x -10c52fe6dc6a1b_011111111111111111111110& E174
+ convertToDouble -25098E48
+} 0xcad0c52fe6dc6a1b
+test expr-28.351 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +50196 E48 x 10c52fe6dc6a1b_011111111111111111111110& E175
+ convertToDouble +50196E48
+} 0x4ae0c52fe6dc6a1b
+test expr-28.352 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -62745 E47 x -10c52fe6dc6a1b_011111111111111111111110& E172
+ convertToDouble -62745E47
+} 0xcab0c52fe6dc6a1b
+test expr-28.353 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +83771 E-73 x 1ce886fb5ffd6d_0111111111111111111110& E-227
+ convertToDouble +83771E-73
+} 0x31cce886fb5ffd6d
+test expr-28.354 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -97451 E-167 x -1c0f220fb1c70d_01111111111111111111110& E-539
+ convertToDouble -97451E-167
+} 0x9e4c0f220fb1c70d
+test expr-28.355 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +86637 E-203 x 10943edb4e81db_0111111111111111111110& E-658
+ convertToDouble +86637E-203
+} 0x16d0943edb4e81db
+test expr-28.356 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -75569 E-254 x -15a462d91c6ab3_0111111111111111111111111110& E-828
+ convertToDouble -75569E-254
+} 0x8c35a462d91c6ab3
+test expr-28.357 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +473806 E83 x 17d15bf3186080_1000000000000000000000001& E294
+ convertToDouble +473806E83
+} 0x5257d15bf3186081
+test expr-28.358 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -947612 E83 x -17d15bf3186080_1000000000000000000000001& E295
+ convertToDouble -947612E83
+} 0xd267d15bf3186081
+test expr-28.359 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +292369 E76 x 18a85eb277e644_100000000000000000000000001& E270
+ convertToDouble +292369E76
+} 0x50d8a85eb277e645
+test expr-28.360 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -584738 E76 x -18a85eb277e644_100000000000000000000000001& E271
+ convertToDouble -584738E76
+} 0xd0e8a85eb277e645
+test expr-28.361 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +933587 E-140 x 1b248728b9c116_100000000000000000000000001& E-446
+ convertToDouble +933587E-140
+} 0x241b248728b9c117
+test expr-28.362 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -720919 E-14 x -1ef696965cbf04_10000000000000000000000001& E-28
+ convertToDouble -720919E-14
+} 0xbe3ef696965cbf05
+test expr-28.363 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +535001 E-149 x 10b38e07c745ae_1000000000000000000000001& E-476
+ convertToDouble +535001E-149
+} 0x2230b38e07c745af
+test expr-28.364 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -890521 E-235 x -114828ee39c852_1000000000000000000000001& E-761
+ convertToDouble -890521E-235
+} 0x90614828ee39c853
+test expr-28.365 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +548057 E81 x 11a1d9135cca53_0111111111111111111111110& E288
+ convertToDouble +548057E81
+} 0x51f1a1d9135cca53
+test expr-28.366 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -706181 E88 x -1b156ac4c2d1e5_0111111111111111111111110& E311
+ convertToDouble -706181E88
+} 0xd36b156ac4c2d1e5
+test expr-28.367 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +820997 E106 x 1b4f8b64fa125d_0111111111111111111111110& E371
+ convertToDouble +820997E106
+} 0x572b4f8b64fa125d
+test expr-28.368 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -320681 E63 x -17ca18a876c5ef_0111111111111111111111110& E227
+ convertToDouble -320681E63
+} 0xce27ca18a876c5ef
+test expr-28.369 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +928609 E-261 x 1be2dd66200bef_011111111111111111111111111110& E-848
+ convertToDouble +928609E-261
+} 0x0afbe2dd66200bef
+test expr-28.370 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -302276 E-254 x -15a462d91c6ab3_0111111111111111111111111110& E-826
+ convertToDouble -302276E-254
+} 0x8c55a462d91c6ab3
+test expr-28.371 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +151138 E-254 x 15a462d91c6ab3_0111111111111111111111111110& E-827
+ convertToDouble +151138E-254
+} 0x0c45a462d91c6ab3
+test expr-28.372 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +4691773 E45 x 19147b9330eaae_1000000000000000000000000001& E171
+ convertToDouble +4691773E45
+} 0x4aa9147b9330eaaf
+test expr-28.373 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -9383546 E45 x -19147b9330eaae_1000000000000000000000000001& E172
+ convertToDouble -9383546E45
+} 0xcab9147b9330eaaf
+test expr-28.374 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +3059949 E-243 x 13ecf22ea07862_10000000000000000000000000001& E-786
+ convertToDouble +3059949E-243
+} 0x0ed3ecf22ea07863
+test expr-28.375 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -6119898 E-243 x -13ecf22ea07862_10000000000000000000000000001& E-785
+ convertToDouble -6119898E-243
+} 0x8ee3ecf22ea07863
+test expr-28.376 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +5356626 E-213 x 1b84252abdf6ba_100000000000000000000000001& E-686
+ convertToDouble +5356626E-213
+} 0x151b84252abdf6bb
+test expr-28.377 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -4877378 E-199 x -11cd5cd90cb200_100000000000000000000000001& E-639
+ convertToDouble -4877378E-199
+} 0x9801cd5cd90cb201
+test expr-28.378 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +7716693 E223 x 1972d9d2cff683_01111111111111111111111111110& E763
+ convertToDouble +7716693E223
+} 0x6fa972d9d2cff683
+test expr-28.379 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -5452869 E109 x -16247b136fecc3_01111111111111111111111111110& E384
+ convertToDouble -5452869E109
+} 0xd7f6247b136fecc3
+test expr-28.380 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +4590831 E156 x 14689b4a5fa201_011111111111111111111111111110& E540
+ convertToDouble +4590831E156
+} 0x61b4689b4a5fa201
+test expr-28.381 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -9181662 E156 x -14689b4a5fa201_011111111111111111111111111110& E541
+ convertToDouble -9181662E156
+} 0xe1c4689b4a5fa201
+test expr-28.382 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -3714436 E-261 x -1be2dd66200bef_011111111111111111111111111110& E-846
+ convertToDouble -3714436E-261
+} 0x8b1be2dd66200bef
+test expr-28.383 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +4643045 E-262 x 1be2dd66200bef_011111111111111111111111111110& E-849
+ convertToDouble +4643045E-262
+} 0x0aebe2dd66200bef
+test expr-28.384 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -7428872 E-261 x -1be2dd66200bef_011111111111111111111111111110& E-845
+ convertToDouble -7428872E-261
+} 0x8b2be2dd66200bef
+test expr-28.385 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +52942146 E130 x 16c31d08af89c2_10000000000000000000000000000001& E457
+ convertToDouble +52942146E130
+} 0x5c86c31d08af89c3
+test expr-28.386 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -27966061 E145 x -155bcf72fd10f8_1000000000000000000000000000000001& E506
+ convertToDouble -27966061E145
+} 0xdf955bcf72fd10f9
+test expr-28.387 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +26471073 E130 x 16c31d08af89c2_10000000000000000000000000000001& E456
+ convertToDouble +26471073E130
+} 0x5c76c31d08af89c3
+test expr-28.388 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -55932122 E145 x -155bcf72fd10f8_1000000000000000000000000000000001& E507
+ convertToDouble -55932122E145
+} 0xdfa55bcf72fd10f9
+test expr-28.389 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +95412548 E-99 x 18e0bfb98864c8_100000000000000000000000000000001& E-303
+ convertToDouble +95412548E-99
+} 0x2d08e0bfb98864c9
+test expr-28.390 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -47706274 E-99 x -18e0bfb98864c8_100000000000000000000000000000001& E-304
+ convertToDouble -47706274E-99
+} 0xacf8e0bfb98864c9
+test expr-28.391 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +23853137 E-99 x 18e0bfb98864c8_100000000000000000000000000000001& E-305
+ convertToDouble +23853137E-99
+} 0x2ce8e0bfb98864c9
+test expr-28.392 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -78493654 E-301 x -140d76077b648e_10000000000000000000000000000001& E-974
+ convertToDouble -78493654E-301
+} 0x83140d76077b648f
+test expr-28.393 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +65346417 E29 x 13aa1ad778f23b_0111111111111111111111111111110& E122
+ convertToDouble +65346417E29
+} 0x4793aa1ad778f23b
+test expr-28.394 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -51083099 E167 x -14a75eb58df47b_0111111111111111111111111111110& E580
+ convertToDouble -51083099E167
+} 0xe434a75eb58df47b
+test expr-28.395 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +89396333 E264 x 1526f061ca9053_0111111111111111111111111111111110& E903
+ convertToDouble +89396333E264
+} 0x786526f061ca9053
+test expr-28.396 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -84863171 E114 x -106e98f5ec8f37_0111111111111111111111111111111110& E405
+ convertToDouble -84863171E114
+} 0xd9406e98f5ec8f37
+test expr-28.397 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +59540836 E-251 x 10430c2d075c07_011111111111111111111111111111110& E-808
+ convertToDouble +59540836E-251
+} 0x0d70430c2d075c07
+test expr-28.398 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -74426045 E-252 x -10430c2d075c07_011111111111111111111111111111110& E-811
+ convertToDouble -74426045E-252
+} 0x8d40430c2d075c07
+test expr-28.399 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +14885209 E-251 x 10430c2d075c07_011111111111111111111111111111110& E-810
+ convertToDouble +14885209E-251
+} 0x0d50430c2d075c07
+test expr-28.400 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -29770418 E-251 x -10430c2d075c07_011111111111111111111111111111110& E-809
+ convertToDouble -29770418E-251
+} 0x8d60430c2d075c07
+test expr-28.401 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +982161308 E122 x 11b6231e18c5ca_100000000000000000000000000000000000000001& E435
+ convertToDouble +982161308E122
+} 0x5b21b6231e18c5cb
+test expr-28.402 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -245540327 E122 x -11b6231e18c5ca_100000000000000000000000000000000000000001& E433
+ convertToDouble -245540327E122
+} 0xdb01b6231e18c5cb
+test expr-28.403 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +491080654 E122 x 11b6231e18c5ca_100000000000000000000000000000000000000001& E434
+ convertToDouble +491080654E122
+} 0x5b11b6231e18c5cb
+test expr-28.404 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +525452622 E-310 x 12045136ce0340_1000000000000000000000000000000000001& E-1001
+ convertToDouble +525452622E-310
+} 0x0162045136ce0341
+test expr-28.405 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -771837113 E-134 x -14e61f991c4ed0_100000000000000000000000000000000001& E-416
+ convertToDouble -771837113E-134
+} 0xa5f4e61f991c4ed1
+test expr-28.406 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +820858081 E-150 x 14050669985a86_10000000000000000000000000000000001& E-469
+ convertToDouble +820858081E-150
+} 0x22a4050669985a87
+test expr-28.407 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -262726311 E-310 x -12045136ce0340_1000000000000000000000000000000000001& E-1002
+ convertToDouble -262726311E-310
+} 0x8152045136ce0341
+test expr-28.408 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +923091487 E209 x 10bc60e6896717_011111111111111111111111111111111110& E724
+ convertToDouble +923091487E209
+} 0x6d30bc60e6896717
+test expr-28.409 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -653777767 E273 x -120223f2b3a881_0111111111111111111111111111111111111110& E936
+ convertToDouble -653777767E273
+} 0xfa720223f2b3a881
+test expr-28.410 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +842116236 E-53 x 1809c5732cdc7f_0111111111111111111111111111111110& E-147
+ convertToDouble +842116236E-53
+} 0x36c809c5732cdc7f
+test expr-28.411 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -741111169 E-202 x -15a3e1d1b73099_01111111111111111111111111111111110& E-642
+ convertToDouble -741111169E-202
+} 0x97d5a3e1d1b73099
+test expr-28.412 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +839507247 E-284 x 129a1effc50859_0111111111111111111111111111111110& E-914
+ convertToDouble +839507247E-284
+} 0x06d29a1effc50859
+test expr-28.413 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -951487269 E-264 x -1c92befccb5f59_0111111111111111111111111111111110& E-848
+ convertToDouble -951487269E-264
+} 0x8afc92befccb5f59
+test expr-28.414 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -9821613080 E121 x -11b6231e18c5ca_100000000000000000000000000000000000000001& E435
+ convertToDouble -9821613080E121
+} 0xdb21b6231e18c5cb
+test expr-28.415 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +6677856011 E-31 x 193a6d11077292_100000000000000000000000000000000000001& E-71
+ convertToDouble +6677856011E-31
+} 0x3b893a6d11077293
+test expr-28.416 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -3573796826 E-266 x -112be2041a79fc_100000000000000000000000000000000000001& E-852
+ convertToDouble -3573796826E-266
+} 0x8ab12be2041a79fd
+test expr-28.417 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +7147593652 E-266 x 112be2041a79fc_100000000000000000000000000000000000001& E-851
+ convertToDouble +7147593652E-266
+} 0x0ac12be2041a79fd
+test expr-28.418 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -9981396317 E-181 x -1edbd94cb50054_100000000000000000000000000000000000001& E-569
+ convertToDouble -9981396317E-181
+} 0x9c6edbd94cb50055
+test expr-28.419 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +3268888835 E272 x 120223f2b3a881_0111111111111111111111111111111111111110& E935
+ convertToDouble +3268888835E272
+} 0x7a620223f2b3a881
+test expr-28.420 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -2615111068 E273 x -120223f2b3a881_0111111111111111111111111111111111111110& E938
+ convertToDouble -2615111068E273
+} 0xfa920223f2b3a881
+test expr-28.421 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +1307555534 E273 x 120223f2b3a881_0111111111111111111111111111111111111110& E937
+ convertToDouble +1307555534E273
+} 0x7a820223f2b3a881
+test expr-28.422 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +2990671154 E-190 x 13db11ac608107_01111111111111111111111111111111111111110& E-600
+ convertToDouble +2990671154E-190
+} 0x1a73db11ac608107
+test expr-28.423 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -1495335577 E-190 x -13db11ac608107_01111111111111111111111111111111111111110& E-601
+ convertToDouble -1495335577E-190
+} 0x9a63db11ac608107
+test expr-28.424 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +5981342308 E-190 x 13db11ac608107_01111111111111111111111111111111111111110& E-599
+ convertToDouble +5981342308E-190
+} 0x1a83db11ac608107
+test expr-28.425 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -7476677885 E-191 x -13db11ac608107_01111111111111111111111111111111111111110& E-602
+ convertToDouble -7476677885E-191
+} 0x9a53db11ac608107
+test expr-28.426 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +82259684194 E-202 x 12c3e72d179606_1000000000000000000000000000000000000000001& E-635
+ convertToDouble +82259684194E-202
+} 0x1842c3e72d179607
+test expr-28.427 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -93227267727 E-49 x -1960fe08d5847e_100000000000000000000000000000000000000001& E-127
+ convertToDouble -93227267727E-49
+} 0xb80960fe08d5847f
+test expr-28.428 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +41129842097 E-202 x 12c3e72d179606_1000000000000000000000000000000000000000001& E-636
+ convertToDouble +41129842097E-202
+} 0x1832c3e72d179607
+test expr-28.429 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -47584241418 E-314 x -14e25dd3747e96_10000000000000000000000000000000000000001& E-1008
+ convertToDouble -47584241418E-314
+} 0x80f4e25dd3747e97
+test expr-28.430 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -79360293406 E92 x -1c58a00bb31863_01111111111111111111111111111111111111110& E341
+ convertToDouble -79360293406E92
+} 0xd54c58a00bb31863
+test expr-28.431 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +57332259349 E225 x 120811f528378b_01111111111111111111111111111111111111110& E783
+ convertToDouble +57332259349E225
+} 0x70e20811f528378b
+test expr-28.432 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -57202326162 E111 x -1626f1c480545b_01111111111111111111111111111111111111110& E404
+ convertToDouble -57202326162E111
+} 0xd93626f1c480545b
+test expr-28.433 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +86860597053 E-206 x 103b77d2b969d9_0111111111111111111111111111111111111111110& E-648
+ convertToDouble +86860597053E-206
+} 0x17703b77d2b969d9
+test expr-28.434 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -53827010643 E-200 x -132fa69a69bd6d_0111111111111111111111111111111111111111110& E-629
+ convertToDouble -53827010643E-200
+} 0x98a32fa69a69bd6d
+test expr-28.435 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +53587107423 E-61 x 100a19a3ffd981_011111111111111111111111111111111111111111110& E-167
+ convertToDouble +53587107423E-61
+} 0x35800a19a3ffd981
+test expr-28.436 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +635007636765 E200 x 1824e73a4f030e_100000000000000000000000000000000000000000001& E703
+ convertToDouble +635007636765E200
+} 0x6be824e73a4f030f
+test expr-28.437 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +508006109412 E201 x 1824e73a4f030e_100000000000000000000000000000000000000000001& E706
+ convertToDouble +508006109412E201
+} 0x6c1824e73a4f030f
+test expr-28.438 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -254003054706 E201 x -1824e73a4f030e_100000000000000000000000000000000000000000001& E705
+ convertToDouble -254003054706E201
+} 0xec0824e73a4f030f
+test expr-28.439 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +561029718715 E-72 x 1cd96a6972a14a_100000000000000000000000000000000000000000001& E-201
+ convertToDouble +561029718715E-72
+} 0x336cd96a6972a14b
+test expr-28.440 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -897647549944 E-71 x -1cd96a6972a14a_100000000000000000000000000000000000000000001& E-197
+ convertToDouble -897647549944E-71
+} 0xb3acd96a6972a14b
+test expr-28.441 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +112205943743 E-71 x 1cd96a6972a14a_100000000000000000000000000000000000000000001& E-200
+ convertToDouble +112205943743E-71
+} 0x337cd96a6972a14b
+test expr-28.442 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -873947086081 E-236 x -19e117541d04e6_1000000000000000000000000000000000000000000001& E-745
+ convertToDouble -873947086081E-236
+} 0x9169e117541d04e7
+test expr-28.443 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +809184709177 E116 x 1de27e59fb0679_011111111111111111111111111111111111111111110& E424
+ convertToDouble +809184709177E116
+} 0x5a7de27e59fb0679
+test expr-28.444 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -573112917422 E81 x -11958b36c5102b_01111111111111111111111111111111111111111111110& E308
+ convertToDouble -573112917422E81
+} 0xd331958b36c5102b
+test expr-28.445 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +286556458711 E81 x 11958b36c5102b_01111111111111111111111111111111111111111111110& E307
+ convertToDouble +286556458711E81
+} 0x5321958b36c5102b
+test expr-28.446 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +952805821491 E-259 x 1551767ef8a9a3_011111111111111111111111111111111111111111110& E-821
+ convertToDouble +952805821491E-259
+} 0x0ca551767ef8a9a3
+test expr-28.447 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -132189992873 E-44 x -1b746cf242410b_011111111111111111111111111111111111111111110& E-110
+ convertToDouble -132189992873E-44
+} 0xb91b746cf242410b
+test expr-28.448 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -173696038493 E-144 x -1f8fefbb3249d3_011111111111111111111111111111111111111111110& E-442
+ convertToDouble -173696038493E-144
+} 0xa45f8fefbb3249d3
+test expr-28.449 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +1831132757599 E-107 x 138e6edd48f2a2_1000000000000000000000000000000000000000000000001& E-315
+ convertToDouble +1831132757599E-107
+} 0x2c438e6edd48f2a3
+test expr-28.450 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -9155663787995 E-108 x -138e6edd48f2a2_1000000000000000000000000000000000000000000000001& E-316
+ convertToDouble -9155663787995E-108
+} 0xac338e6edd48f2a3
+test expr-28.451 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +7324531030396 E-107 x 138e6edd48f2a2_1000000000000000000000000000000000000000000000001& E-313
+ convertToDouble +7324531030396E-107
+} 0x2c638e6edd48f2a3
+test expr-28.452 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -9277338894969 E-200 x -19d5a44fd99a6a_1000000000000000000000000000000000000000000000001& E-622
+ convertToDouble -9277338894969E-200
+} 0x9919d5a44fd99a6b
+test expr-28.453 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +8188292423973 E287 x 1390273bf8f983_0111111111111111111111111111111111111111111111110& E996
+ convertToDouble +8188292423973E287
+} 0x7e3390273bf8f983
+test expr-28.454 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -5672557437938 E59 x -148c2bd60a1523_011111111111111111111111111111111111111111111110& E238
+ convertToDouble -5672557437938E59
+} 0xced48c2bd60a1523
+test expr-28.455 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +2836278718969 E59 x 148c2bd60a1523_011111111111111111111111111111111111111111111110& E237
+ convertToDouble +2836278718969E59
+} 0x4ec48c2bd60a1523
+test expr-28.456 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -9995153153494 E54 x -17ba37c4fbe993_01111111111111111111111111111111111111111111110& E222
+ convertToDouble -9995153153494E54
+} 0xcdd7ba37c4fbe993
+test expr-28.457 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +9224786422069 E-291 x 14ee5d56b32957_011111111111111111111111111111111111111111111111110& E-924
+ convertToDouble +9224786422069E-291
+} 0x0634ee5d56b32957
+test expr-28.458 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -3142213164987 E-294 x -1d3409dfbca26f_011111111111111111111111111111111111111111111111110& E-936
+ convertToDouble -3142213164987E-294
+} 0x857d3409dfbca26f
+test expr-28.459 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +6284426329974 E-294 x 1d3409dfbca26f_011111111111111111111111111111111111111111111111110& E-935
+ convertToDouble +6284426329974E-294
+} 0x058d3409dfbca26f
+test expr-28.460 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -8340483752889 E-301 x -10419183e44b91_01111111111111111111111111111111111111111111111110& E-957
+ convertToDouble -8340483752889E-301
+} 0x8420419183e44b91
+test expr-28.461 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +67039371486466 E89 x 17f203339c9628_10000000000000000000000000000000000000000000000000001& E341
+ convertToDouble +67039371486466E89
+} 0x5547f203339c9629
+test expr-28.462 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -62150786615239 E197 x -12e79a035b9714_1000000000000000000000000000000000000000000000000001& E700
+ convertToDouble -62150786615239E197
+} 0xebb2e79a035b9715
+test expr-28.463 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +33519685743233 E89 x 17f203339c9628_10000000000000000000000000000000000000000000000000001& E340
+ convertToDouble +33519685743233E89
+} 0x5537f203339c9629
+test expr-28.464 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -52563419496999 E156 x -1bdb17625bf6e6_1000000000000000000000000000000000000000000000000001& E563
+ convertToDouble -52563419496999E156
+} 0xe32bdb17625bf6e7
+test expr-28.465 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +32599460466991 E-65 x 1f395d4c779d8e_1000000000000000000000000000000000000000000000000001& E-172
+ convertToDouble +32599460466991E-65
+} 0x353f395d4c779d8f
+test expr-28.466 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -41010988798007 E-133 x -152e1c9e04ee06_100000000000000000000000000000000000000000000000001& E-397
+ convertToDouble -41010988798007E-133
+} 0xa7252e1c9e04ee07
+test expr-28.467 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +65198920933982 E-65 x 1f395d4c779d8e_1000000000000000000000000000000000000000000000000001& E-171
+ convertToDouble +65198920933982E-65
+} 0x354f395d4c779d8f
+test expr-28.468 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -82021977596014 E-133 x -152e1c9e04ee06_100000000000000000000000000000000000000000000000001& E-396
+ convertToDouble -82021977596014E-133
+} 0xa7352e1c9e04ee07
+test expr-28.469 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +80527976643809 E61 x 1c7c5aea080a49_0111111111111111111111111111111111111111111111111110& E248
+ convertToDouble +80527976643809E61
+} 0x4f7c7c5aea080a49
+test expr-28.470 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -74712611505209 E158 x -1eeebe9ea010f3_011111111111111111111111111111111111111111111111110& E570
+ convertToDouble -74712611505209E158
+} 0xe39eeebe9ea010f3
+test expr-28.471 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +53390939710959 E261 x 18ac6d426a1cb1_0111111111111111111111111111111111111111111111111110& E912
+ convertToDouble +53390939710959E261
+} 0x78f8ac6d426a1cb1
+test expr-28.472 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -69277302659155 E225 x -1547166a3a2b0f_011111111111111111111111111111111111111111111111110& E793
+ convertToDouble -69277302659155E225
+} 0xf18547166a3a2b0f
+test expr-28.473 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +46202199371337 E-72 x 128f9edfbd341f_0111111111111111111111111111111111111111111111111111111110& E-194
+ convertToDouble +46202199371337E-72
+} 0x33d28f9edfbd341f
+test expr-28.474 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -23438635467783 E-179 x -1ba485b99e47af_0111111111111111111111111111111111111111111111111110& E-551
+ convertToDouble -23438635467783E-179
+} 0x9d8ba485b99e47af
+test expr-28.475 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +41921560615349 E-67 x 19b2a5c4041e4b_0111111111111111111111111111111111111111111111111110& E-178
+ convertToDouble +41921560615349E-67
+} 0x34d9b2a5c4041e4b
+test expr-28.476 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -92404398742674 E-72 x -128f9edfbd341f_0111111111111111111111111111111111111111111111111111111110& E-193
+ convertToDouble -92404398742674E-72
+} 0xb3e28f9edfbd341f
+test expr-28.477 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +738545606647197 E124 x 13d8886a766a20_100000000000000000000000000000000000000000000000000001& E461
+ convertToDouble +738545606647197E124
+} 0x5cc3d8886a766a21
+test expr-28.478 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -972708181182949 E117 x -15ed1f039cebfe_1000000000000000000000000000000000000000000000000000001& E438
+ convertToDouble -972708181182949E117
+} 0xdb55ed1f039cebff
+test expr-28.479 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -837992143580825 E87 x -17f203339c9628_10000000000000000000000000000000000000000000000000001& E338
+ convertToDouble -837992143580825E87
+} 0xd517f203339c9629
+test expr-28.480 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +609610927149051 E-255 x 104273b18918b0_100000000000000000000000000000000000000000000000000000001& E-798
+ convertToDouble +609610927149051E-255
+} 0x0e104273b18918b1
+test expr-28.481 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -475603213226859 E-41 x -178cfcab31064c_10000000000000000000000000000000000000000000000000000001& E-88
+ convertToDouble -475603213226859E-41
+} 0xba778cfcab31064d
+test expr-28.482 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +563002800671023 E-177 x 1035e7b5183922_10000000000000000000000000000000000000000000000000000001& E-539
+ convertToDouble +563002800671023E-177
+} 0x1e4035e7b5183923
+test expr-28.483 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -951206426453718 E-41 x -178cfcab31064c_10000000000000000000000000000000000000000000000000000001& E-87
+ convertToDouble -951206426453718E-41
+} 0xba878cfcab31064d
+test expr-28.484 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +805416432656519 E202 x 175d226331d039_01111111111111111111111111111111111111111111111111111110& E720
+ convertToDouble +805416432656519E202
+} 0x6cf75d226331d039
+test expr-28.485 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -530658674694337 E159 x -112a13daa46fe3_0111111111111111111111111111111111111111111111111111110& E577
+ convertToDouble -530658674694337E159
+} 0xe4012a13daa46fe3
+test expr-28.486 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +946574173863918 E208 x 1a2fbffdb7580b_011111111111111111111111111111111111111111111111111110& E740
+ convertToDouble +946574173863918E208
+} 0x6e3a2fbffdb7580b
+test expr-28.487 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -318329953318553 E113 x -178358811cbc95_011111111111111111111111111111111111111111111111111110& E423
+ convertToDouble -318329953318553E113
+} 0xda678358811cbc95
+test expr-28.488 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -462021993713370 E-73 x -128f9edfbd341f_0111111111111111111111111111111111111111111111111111111110& E-194
+ convertToDouble -462021993713370E-73
+} 0xb3d28f9edfbd341f
+test expr-28.489 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +369617594970696 E-72 x 128f9edfbd341f_0111111111111111111111111111111111111111111111111111111110& E-191
+ convertToDouble +369617594970696E-72
+} 0x34028f9edfbd341f
+test expr-28.490 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +3666156212014994 E233 x 1a37935f3b71c8_100000000000000000000000000000000000000000000000000000001& E825
+ convertToDouble +3666156212014994E233
+} 0x738a37935f3b71c9
+test expr-28.491 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -1833078106007497 E233 x -1a37935f3b71c8_100000000000000000000000000000000000000000000000000000001& E824
+ convertToDouble -1833078106007497E233
+} 0xf37a37935f3b71c9
+test expr-28.492 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +8301790508624232 E174 x 1dcfee6690ffc6_100000000000000000000000000000000000000000000000000000001& E630
+ convertToDouble +8301790508624232E174
+} 0x675dcfee6690ffc7
+test expr-28.493 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -1037723813578029 E174 x -1dcfee6690ffc6_100000000000000000000000000000000000000000000000000000001& E627
+ convertToDouble -1037723813578029E174
+} 0xe72dcfee6690ffc7
+test expr-28.494 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +7297662880581139 E-286 x 18ac8c79e1ff18_1000000000000000000000000000000000000000000000000000000000001& E-898
+ convertToDouble +7297662880581139E-286
+} 0x07d8ac8c79e1ff19
+test expr-28.495 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -5106185698912191 E-276 x -141934d77659be_1000000000000000000000000000000000000000000000000000000000001& E-865
+ convertToDouble -5106185698912191E-276
+} 0x89e41934d77659bf
+test expr-28.496 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +7487252720986826 E-165 x 18823a57adbef8_100000000000000000000000000000000000000000000000000000000000001& E-496
+ convertToDouble +7487252720986826E-165
+} 0x20f8823a57adbef9
+test expr-28.497 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -3743626360493413 E-165 x -18823a57adbef8_100000000000000000000000000000000000000000000000000000000000001& E-497
+ convertToDouble -3743626360493413E-165
+} 0xa0e8823a57adbef9
+test expr-28.498 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +3773057430100257 E230 x 1ba10d818fdafd_0111111111111111111111111111111111111111111111111111111110& E815
+ convertToDouble +3773057430100257E230
+} 0x72eba10d818fdafd
+test expr-28.499 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -7546114860200514 E230 x -1ba10d818fdafd_0111111111111111111111111111111111111111111111111111111110& E816
+ convertToDouble -7546114860200514E230
+} 0xf2fba10d818fdafd
+test expr-28.500 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +4321222892463822 E58 x 18750ea732fdad_011111111111111111111111111111111111111111111111111111110& E244
+ convertToDouble +4321222892463822E58
+} 0x4f38750ea732fdad
+test expr-28.501 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -7793560217139653 E51 x -1280461b856ec5_0111111111111111111111111111111111111111111111111111111110& E222
+ convertToDouble -7793560217139653E51
+} 0xcdd280461b856ec5
+test expr-28.502 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +26525993941010681 E112 x 187dcbf6ad5cf8_10000000000000000000000000000000000000000000000000000000000001& E426
+ convertToDouble +26525993941010681E112
+} 0x5a987dcbf6ad5cf9
+test expr-28.503 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -53051987882021362 E112 x -187dcbf6ad5cf8_10000000000000000000000000000000000000000000000000000000000001& E427
+ convertToDouble -53051987882021362E112
+} 0xdaa87dcbf6ad5cf9
+test expr-28.504 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +72844871414247907 E77 x 1bf00baf60b70c_100000000000000000000000000000000000000000000000000000000001& E311
+ convertToDouble +72844871414247907E77
+} 0x536bf00baf60b70d
+test expr-28.505 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -88839359596763261 E105 x -1133b1a33a1108_100000000000000000000000000000000000000000000000000000000001& E405
+ convertToDouble -88839359596763261E105
+} 0xd94133b1a33a1109
+test expr-28.506 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +18718131802467065 E-166 x 18823a57adbef8_100000000000000000000000000000000000000000000000000000000000001& E-498
+ convertToDouble +18718131802467065E-166
+} 0x20d8823a57adbef9
+test expr-28.507 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -14974505441973652 E-165 x -18823a57adbef8_100000000000000000000000000000000000000000000000000000000000001& E-495
+ convertToDouble -14974505441973652E-165
+} 0xa108823a57adbef9
+test expr-28.508 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +73429396004640239 E106 x 11c5cb19ef3451_01111111111111111111111111111111111111111111111111111111111110& E408
+ convertToDouble +73429396004640239E106
+} 0x5971c5cb19ef3451
+test expr-28.509 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -58483921078398283 E57 x -108ce499519ce3_0111111111111111111111111111111111111111111111111111111111111110& E245
+ convertToDouble -58483921078398283E57
+} 0xcf408ce499519ce3
+test expr-28.510 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +41391519190645203 E165 x 13f33667156017_011111111111111111111111111111111111111111111111111111111111110& E603
+ convertToDouble +41391519190645203E165
+} 0x65a3f33667156017
+test expr-28.511 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -82783038381290406 E165 x -13f33667156017_011111111111111111111111111111111111111111111111111111111111110& E604
+ convertToDouble -82783038381290406E165
+} 0xe5b3f33667156017
+test expr-28.512 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +58767043776702677 E-163 x 12c92fee3a3867_0111111111111111111111111111111111111111111111111111111111110& E-486
+ convertToDouble +58767043776702677E-163
+} 0x2192c92fee3a3867
+test expr-28.513 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -90506231831231999 E-129 x -1bdc4114397ff3_01111111111111111111111111111111111111111111111111111111111110& E-373
+ convertToDouble -90506231831231999E-129
+} 0xa8abdc4114397ff3
+test expr-28.514 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +64409240769861689 E-159 x 192238f7987779_011111111111111111111111111111111111111111111111111111111111110& E-473
+ convertToDouble +64409240769861689E-159
+} 0x22692238f7987779
+test expr-28.515 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -77305427432277771 E-190 x -1e978b7780b613_0111111111111111111111111111111111111111111111111111111111110& E-576
+ convertToDouble -77305427432277771E-190
+} 0x9bfe978b7780b613
+test expr-28.516 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +476592356619258326 E273 x 1873cf8ee72812_10000000000000000000000000000000000000000000000000000000000000001& E965
+ convertToDouble +476592356619258326E273
+} 0x7c4873cf8ee72813
+test expr-28.517 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -953184713238516652 E273 x -1873cf8ee72812_10000000000000000000000000000000000000000000000000000000000000001& E966
+ convertToDouble -953184713238516652E273
+} 0xfc5873cf8ee72813
+test expr-28.518 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +899810892172646163 E283 x 1adf51fa055e02_100000000000000000000000000000000000000000000000000000000000000000001& E999
+ convertToDouble +899810892172646163E283
+} 0x7e6adf51fa055e03
+test expr-28.519 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -929167076892018333 E187 x -1da2c42fce2bc4_10000000000000000000000000000000000000000000000000000000000000000001& E680
+ convertToDouble -929167076892018333E187
+} 0xea7da2c42fce2bc5
+test expr-28.520 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +647761278967534239 E-312 x 1a7a2476ec0b3e_10000000000000000000000000000000000000000000000000000000000000001& E-978
+ convertToDouble +647761278967534239E-312
+} 0x02da7a2476ec0b3f
+test expr-28.521 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -644290479820542942 E-180 x -128d1407dfa832_10000000000000000000000000000000000000000000000000000000000000001& E-539
+ convertToDouble -644290479820542942E-180
+} 0x9e428d1407dfa833
+test expr-28.522 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +926145344610700019 E-225 x 1307a67f1f69fe_10000000000000000000000000000000000000000000000000000000000000000001& E-688
+ convertToDouble +926145344610700019E-225
+} 0x14f307a67f1f69ff
+test expr-28.523 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -958507931896511964 E-246 x -17406753df2f0c_10000000000000000000000000000000000000000000000000000000000000001& E-758
+ convertToDouble -958507931896511964E-246
+} 0x9097406753df2f0d
+test expr-28.524 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +272104041512242479 E200 x 13bbb4bf05f087_011111111111111111111111111111111111111111111111111111111111111111111110& E722
+ convertToDouble +272104041512242479E200
+} 0x6d13bbb4bf05f087
+test expr-28.525 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -792644927852378159 E79 x -1daff0048f3ec7_011111111111111111111111111111111111111111111111111111111111111111110& E321
+ convertToDouble -792644927852378159E79
+} 0xd40daff0048f3ec7
+test expr-28.526 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +544208083024484958 E200 x 13bbb4bf05f087_011111111111111111111111111111111111111111111111111111111111111111111110& E723
+ convertToDouble +544208083024484958E200
+} 0x6d23bbb4bf05f087
+test expr-28.527 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -929963218616126365 E290 x -108dcc0c505461_01111111111111111111111111111111111111111111111111111111111111110& E1023
+ convertToDouble -929963218616126365E290
+} 0xffe08dcc0c505461
+test expr-28.528 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +305574339166810102 E-219 x 17f399fe02c4b9_011111111111111111111111111111111111111111111111111111111111111110& E-670
+ convertToDouble +305574339166810102E-219
+} 0x1617f399fe02c4b9
+test expr-28.529 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -152787169583405051 E-219 x -17f399fe02c4b9_011111111111111111111111111111111111111111111111111111111111111110& E-671
+ convertToDouble -152787169583405051E-219
+} 0x9607f399fe02c4b9
+test expr-28.530 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +611148678333620204 E-219 x 17f399fe02c4b9_011111111111111111111111111111111111111111111111111111111111111110& E-669
+ convertToDouble +611148678333620204E-219
+} 0x1627f399fe02c4b9
+test expr-28.531 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -763935847917025255 E-220 x -17f399fe02c4b9_011111111111111111111111111111111111111111111111111111111111111110& E-672
+ convertToDouble -763935847917025255E-220
+} 0x95f7f399fe02c4b9
+test expr-28.532 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +7439550220920798612 E158 x 177fe14f40159a_10000000000000000000000000000000000000000000000000000000000000000000001& E587
+ convertToDouble +7439550220920798612E158
+} 0x64a77fe14f40159b
+test expr-28.533 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -3719775110460399306 E158 x -177fe14f40159a_10000000000000000000000000000000000000000000000000000000000000000000001& E586
+ convertToDouble -3719775110460399306E158
+} 0xe4977fe14f40159b
+test expr-28.534 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +9299437776150998265 E157 x 177fe14f40159a_10000000000000000000000000000000000000000000000000000000000000000000001& E584
+ convertToDouble +9299437776150998265E157
+} 0x64777fe14f40159b
+test expr-28.535 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -7120190517612959703 E120 x -13220dcd5899fc_1000000000000000000000000000000000000000000000000000000000000000000000001& E461
+ convertToDouble -7120190517612959703E120
+} 0xdcc3220dcd5899fd
+test expr-28.536 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +3507665085003296281 E-73 x 11339818257f0e_100000000000000000000000000000000000000000000000000000000000000000000001& E-181
+ convertToDouble +3507665085003296281E-73
+} 0x34a1339818257f0f
+test expr-28.537 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -7015330170006592562 E-73 x -11339818257f0e_100000000000000000000000000000000000000000000000000000000000000000000001& E-180
+ convertToDouble -7015330170006592562E-73
+} 0xb4b1339818257f0f
+test expr-28.538 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -6684428762278255956 E-294 x -1d9f82a1a6b1b8_10000000000000000000000000000000000000000000000000000000000000000001& E-915
+ convertToDouble -6684428762278255956E-294
+} 0x86cd9f82a1a6b1b9
+test expr-28.539 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -1088416166048969916 E200 x -13bbb4bf05f087_011111111111111111111111111111111111111111111111111111111111111111111110& E724
+ convertToDouble -1088416166048969916E200
+} 0xed33bbb4bf05f087
+test expr-28.540 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -8707329328391759328 E200 x -13bbb4bf05f087_011111111111111111111111111111111111111111111111111111111111111111111110& E727
+ convertToDouble -8707329328391759328E200
+} 0xed63bbb4bf05f087
+test expr-28.541 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +4439021781608558002 E-65 x 1038168b71e2c9_01111111111111111111111111111111111111111111111111111111111111111110& E-154
+ convertToDouble +4439021781608558002E-65
+} 0x365038168b71e2c9
+test expr-28.542 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -8878043563217116004 E-65 x -1038168b71e2c9_01111111111111111111111111111111111111111111111111111111111111111110& E-153
+ convertToDouble -8878043563217116004E-65
+} 0xb66038168b71e2c9
+test expr-28.543 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +2219510890804279001 E-65 x 1038168b71e2c9_01111111111111111111111111111111111111111111111111111111111111111110& E-155
+ convertToDouble +2219510890804279001E-65
+} 0x364038168b71e2c9
+test expr-28.544 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +33051223951904955802 E55 x 1762068a24fd54_1000000000000000000000000000000000000000000000000000000000000000000000001& E247
+ convertToDouble +33051223951904955802E55
+} 0x4f6762068a24fd55
+test expr-28.545 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -56961524140903677624 E120 x -13220dcd5899fc_1000000000000000000000000000000000000000000000000000000000000000000000001& E464
+ convertToDouble -56961524140903677624E120
+} 0xdcf3220dcd5899fd
+test expr-28.546 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +71201905176129597030 E119 x 13220dcd5899fc_1000000000000000000000000000000000000000000000000000000000000000000000001& E461
+ convertToDouble +71201905176129597030E119
+} 0x5cc3220dcd5899fd
+test expr-28.547 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +14030660340013185124 E-73 x 11339818257f0e_100000000000000000000000000000000000000000000000000000000000000000000001& E-179
+ convertToDouble +14030660340013185124E-73
+} 0x34c1339818257f0f
+test expr-28.548 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -17538325425016481405 E-74 x -11339818257f0e_100000000000000000000000000000000000000000000000000000000000000000000001& E-182
+ convertToDouble -17538325425016481405E-74
+} 0xb491339818257f0f
+test expr-28.549 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +67536228609141569109 E-133 x 10a1b35cf2a635_01111111111111111111111111111111111111111111111111111111111111111111110& E-376
+ convertToDouble +67536228609141569109E-133
+} 0x2870a1b35cf2a635
+test expr-28.550 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -35620497849450218807 E-306 x -15b22082529425_0111111111111111111111111111111111111111111111111111111111111111111111110& E-952
+ convertToDouble -35620497849450218807E-306
+} 0x8475b22082529425
+test expr-28.551 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN +66550376797582521751 E-126 x 13897c0ede6c69_01111111111111111111111111111111111111111111111111111111111111111111110& E-353
+ convertToDouble +66550376797582521751E-126
+} 0x29e3897c0ede6c69
+test expr-28.552 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b d UN -71240995698900437614 E-306 x -15b22082529425_0111111111111111111111111111111111111111111111111111111111111111111111110& E-951
+ convertToDouble -71240995698900437614E-306
+} 0x8485b22082529425
+test expr-28.553 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +3 E24 x 13da329b633647_0001& E81
+ convertToDouble +3E24
+} 0x4503da329b633647
+test expr-28.554 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -6 E24 x -13da329b633647_0001& E82
+ convertToDouble -6E24
+} 0xc513da329b633647
+test expr-28.555 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +6 E26 x 1f04ef12cb04cf_0001& E88
+ convertToDouble +6E26
+} 0x457f04ef12cb04cf
+test expr-28.556 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -7 E25 x -1cf389cd46047d_0000001& E85
+ convertToDouble -7E25
+} 0xc54cf389cd46047d
+test expr-28.557 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +1 E-14 x 16849b86a12b9b_00000001& E-47
+ convertToDouble +1E-14
+} 0x3d06849b86a12b9b
+test expr-28.558 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -2 E-14 x -16849b86a12b9b_00000001& E-46
+ convertToDouble -2E-14
+} 0xbd16849b86a12b9b
+test expr-28.559 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +4 E-14 x 16849b86a12b9b_00000001& E-45
+ convertToDouble +4E-14
+} 0x3d26849b86a12b9b
+test expr-28.560 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -8 E-14 x -16849b86a12b9b_00000001& E-44
+ convertToDouble -8E-14
+} 0xbd36849b86a12b9b
+test expr-28.561 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +5 E26 x 19d971e4fe8401_1110& E88
+ convertToDouble +5E26
+} 0x4579d971e4fe8402
+test expr-28.562 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -8 E27 x -19d971e4fe8401_1110& E92
+ convertToDouble -8E27
+} 0xc5b9d971e4fe8402
+test expr-28.563 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +1 E27 x 19d971e4fe8401_1110& E89
+ convertToDouble +1E27
+} 0x4589d971e4fe8402
+test expr-28.564 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -4 E27 x -19d971e4fe8401_1110& E91
+ convertToDouble -4E27
+} 0xc5a9d971e4fe8402
+test expr-28.565 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +9 E-13 x 1faa7ab552a551_111110& E-41
+ convertToDouble +9E-13
+} 0x3d6faa7ab552a552
+test expr-28.566 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -7 E-20 x -14a90ceafff9de_11110& E-64
+ convertToDouble -7E-20
+} 0xbbf4a90ceafff9df
+test expr-28.567 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +56 E25 x 1cf389cd46047d_0000001& E88
+ convertToDouble +56E25
+} 0x457cf389cd46047d
+test expr-28.568 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -70 E24 x -1cf389cd46047d_0000001& E85
+ convertToDouble -70E24
+} 0xc54cf389cd46047d
+test expr-28.569 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +51 E26 x 107a9f01fbda8e_0000001& E92
+ convertToDouble +51E26
+} 0x45b07a9f01fbda8e
+test expr-28.570 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +71 E-17 x 19949819f693d7_00000000001& E-51
+ convertToDouble +71E-17
+} 0x3cc9949819f693d7
+test expr-28.571 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -31 E-5 x -1450efdc9c4da9_00000000001& E-12
+ convertToDouble -31E-5
+} 0xbf3450efdc9c4da9
+test expr-28.572 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +62 E-5 x 1450efdc9c4da9_00000000001& E-11
+ convertToDouble +62E-5
+} 0x3f4450efdc9c4da9
+test expr-28.573 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -94 E-8 x -1f8a89dc374df5_0000000001& E-21
+ convertToDouble -94E-8
+} 0xbeaf8a89dc374df5
+test expr-28.574 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +67 E27 x 1b0fa33bba7231_11111110& E95
+ convertToDouble +67E27
+} 0x45eb0fa33bba7232
+test expr-28.575 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -81 E24 x -10c01ab31bb5cb_1111110& E86
+ convertToDouble -81E24
+} 0xc550c01ab31bb5cc
+test expr-28.576 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +54 E23 x 11ddfa58a6173f_111110& E82
+ convertToDouble +54E23
+} 0x4511ddfa58a61740
+test expr-28.577 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -54 E25 x -1bead72a838453_111110& E88
+ convertToDouble -54E25
+} 0xc57bead72a838454
+test expr-28.578 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +63 E-22 x 1dc03b8fd70169_11111111110& E-68
+ convertToDouble +63E-22
+} 0x3bbdc03b8fd7016a
+test expr-28.579 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -63 E-23 x -17ccfc73126787_11111111110& E-71
+ convertToDouble -63E-23
+} 0xbb87ccfc73126788
+test expr-28.580 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +43 E-4 x 119ce075f6fd21_111111110& E-8
+ convertToDouble +43E-4
+} 0x3f719ce075f6fd22
+test expr-28.581 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -86 E-4 x -119ce075f6fd21_111111110& E-7
+ convertToDouble -86E-4
+} 0xbf819ce075f6fd22
+test expr-28.582 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +942 E26 x 1306069e8681f3_00000000001& E96
+ convertToDouble +942E26
+} 0x45f306069e8681f3
+test expr-28.583 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -471 E25 x -1e700a973d9cb8_0000000001& E91
+ convertToDouble -471E25
+} 0xc5ae700a973d9cb8
+test expr-28.584 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +803 E24 x 14c1cee9cd666b_000000000001& E89
+ convertToDouble +803E24
+} 0x4584c1cee9cd666b
+test expr-28.585 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -471 E26 x -1306069e8681f3_00000000001& E95
+ convertToDouble -471E26
+} 0xc5e306069e8681f3
+test expr-28.586 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -409 E-21 x -1e2dcaa4115622_000000000001& E-62
+ convertToDouble -409E-21
+} 0xbc1e2dcaa4115622
+test expr-28.587 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +818 E-21 x 1e2dcaa4115622_000000000001& E-61
+ convertToDouble +818E-21
+} 0x3c2e2dcaa4115622
+test expr-28.588 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -867 E-8 x -122eabba029aba_000000000001& E-17
+ convertToDouble -867E-8
+} 0xbee22eabba029aba
+test expr-28.589 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +538 E27 x 1b297cad9f70b5_1111111111111110& E98
+ convertToDouble +538E27
+} 0x461b297cad9f70b6
+test expr-28.590 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -857 E24 x -16272678ba603b_11111111110& E89
+ convertToDouble -857E24
+} 0xc586272678ba603c
+test expr-28.591 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +269 E27 x 1b297cad9f70b5_1111111111111110& E97
+ convertToDouble +269E27
+} 0x460b297cad9f70b6
+test expr-28.592 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -403 E26 x -1046ec1e31dd85_1111111110& E95
+ convertToDouble -403E26
+} 0xc5e046ec1e31dd86
+test expr-28.593 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +959 E-7 x 1923bd746a3527_11111111111110& E-14
+ convertToDouble +959E-7
+} 0x3f1923bd746a3528
+test expr-28.594 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -959 E-6 x -1f6cacd184c271_1111111111110& E-11
+ convertToDouble -959E-6
+} 0xbf4f6cacd184c272
+test expr-28.595 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +373 E-27 x 1cdc06b20ef182_1111111111110& E-82
+ convertToDouble +373E-27
+} 0x3adcdc06b20ef183
+test expr-28.596 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -746 E-27 x -1cdc06b20ef182_1111111111110& E-81
+ convertToDouble -746E-27
+} 0xbaecdc06b20ef183
+test expr-28.597 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +4069 E24 x 1a4b9887fbfe7a_0000000000001& E91
+ convertToDouble +4069E24
+} 0x45aa4b9887fbfe7a
+test expr-28.598 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -4069 E23 x -150946d32ffec8_0000000000001& E88
+ convertToDouble -4069E23
+} 0xc5750946d32ffec8
+test expr-28.599 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -8138 E24 x -1a4b9887fbfe7a_0000000000001& E92
+ convertToDouble -8138E24
+} 0xc5ba4b9887fbfe7a
+test expr-28.600 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +8294 E-15 x 123d1b5eb1d778_000000000000000001& E-37
+ convertToDouble +8294E-15
+} 0x3da23d1b5eb1d778
+test expr-28.601 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -4147 E-14 x -16cc62365e4d56_00000000000000001& E-35
+ convertToDouble -4147E-14
+} 0xbdc6cc62365e4d56
+test expr-28.602 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +4147 E-15 x 123d1b5eb1d778_000000000000000001& E-38
+ convertToDouble +4147E-15
+} 0x3d923d1b5eb1d778
+test expr-28.603 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -8294 E-14 x -16cc62365e4d56_00000000000000001& E-34
+ convertToDouble -8294E-14
+} 0xbdd6cc62365e4d56
+test expr-28.604 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +538 E27 x 1b297cad9f70b5_1111111111111110& E98
+ convertToDouble +538E27
+} 0x461b297cad9f70b6
+test expr-28.605 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -2690 E26 x -1b297cad9f70b5_1111111111111110& E97
+ convertToDouble -2690E26
+} 0xc60b297cad9f70b6
+test expr-28.606 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +269 E27 x 1b297cad9f70b5_1111111111111110& E97
+ convertToDouble +269E27
+} 0x460b297cad9f70b6
+test expr-28.607 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -2152 E27 x -1b297cad9f70b5_1111111111111110& E100
+ convertToDouble -2152E27
+} 0xc63b297cad9f70b6
+test expr-28.608 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +1721 E-17 x 136071dcae4564_111111111111110& E-46
+ convertToDouble +1721E-17
+} 0x3d136071dcae4565
+test expr-28.609 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -7979 E-27 x -134ac304747faf_111111111111110& E-77
+ convertToDouble -7979E-27
+} 0xbb234ac304747fb0
+test expr-28.610 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +6884 E-17 x 136071dcae4564_111111111111110& E-44
+ convertToDouble +6884E-17
+} 0x3d336071dcae4565
+test expr-28.611 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -8605 E-18 x -136071dcae4564_111111111111110& E-47
+ convertToDouble -8605E-18
+} 0xbd036071dcae4565
+test expr-28.612 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +82854 E27 x 10570ed9e3cecc_00000000000000001& E106
+ convertToDouble +82854E27
+} 0x4690570ed9e3cecc
+test expr-28.613 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -55684 E24 x -167d9735144ae3_00000000000000001& E95
+ convertToDouble -55684E24
+} 0xc5e67d9735144ae3
+test expr-28.614 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +27842 E24 x 167d9735144ae3_00000000000000001& E94
+ convertToDouble +27842E24
+} 0x45d67d9735144ae3
+test expr-28.615 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -48959 E25 x -18b7cd6ca56f85_00000000000000001& E98
+ convertToDouble -48959E25
+} 0xc618b7cd6ca56f85
+test expr-28.616 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +81921 E-17 x 1cd2c9a6cdd003_000000000000000000001& E-41
+ convertToDouble +81921E-17
+} 0x3d6cd2c9a6cdd003
+test expr-28.617 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -76207 E-8 x -18f8b4dd16f1df_0000000000000000001& E-11
+ convertToDouble -76207E-8
+} 0xbf48f8b4dd16f1df
+test expr-28.618 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +4147 E-15 x 123d1b5eb1d778_000000000000000001& E-38
+ convertToDouble +4147E-15
+} 0x3d923d1b5eb1d778
+test expr-28.619 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -41470 E-16 x -123d1b5eb1d778_000000000000000001& E-38
+ convertToDouble -41470E-16
+} 0xbd923d1b5eb1d778
+test expr-28.620 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +89309 E24 x 12092ac5f2019e_1111111111111111110& E96
+ convertToDouble +89309E24
+} 0x45f2092ac5f2019f
+test expr-28.621 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +75859 E26 x 17efd75a2938eb_1111111111111111111110& E102
+ convertToDouble +75859E26
+} 0x4657efd75a2938ec
+test expr-28.622 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -75859 E25 x -132645e1ba93ef_1111111111111111111110& E99
+ convertToDouble -75859E25
+} 0xc6232645e1ba93f0
+test expr-28.623 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +14257 E-23 x 150a246ecd44f2_1111111111111111110& E-63
+ convertToDouble +14257E-23
+} 0x3c050a246ecd44f3
+test expr-28.624 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -28514 E-23 x -150a246ecd44f2_1111111111111111110& E-62
+ convertToDouble -28514E-23
+} 0xbc150a246ecd44f3
+test expr-28.625 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +57028 E-23 x 150a246ecd44f2_1111111111111111110& E-61
+ convertToDouble +57028E-23
+} 0x3c250a246ecd44f3
+test expr-28.626 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -71285 E-24 x -150a246ecd44f2_1111111111111111110& E-64
+ convertToDouble -71285E-24
+} 0xbbf50a246ecd44f3
+test expr-28.627 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +344863 E27 x 1100c873963d6d_00000000000000000001& E108
+ convertToDouble +344863E27
+} 0x46b100c873963d6d
+test expr-28.628 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -951735 E27 x -17764ad224e24a_000000000000000000001& E109
+ convertToDouble -951735E27
+} 0xc6c7764ad224e24a
+test expr-28.629 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +200677 E23 x 1035e73135b834_0000000000000000001& E94
+ convertToDouble +200677E23
+} 0x45d035e73135b834
+test expr-28.630 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -401354 E24 x -144360fd832641_0000000000000000001& E98
+ convertToDouble -401354E24
+} 0xc6144360fd832641
+test expr-28.631 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +839604 E-11 x 119b96f36ec68b_00000000000000000000000001& E-17
+ convertToDouble +839604E-11
+} 0x3ee19b96f36ec68b
+test expr-28.632 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -209901 E-11 x -119b96f36ec68b_00000000000000000000000001& E-19
+ convertToDouble -209901E-11
+} 0xbec19b96f36ec68b
+test expr-28.633 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +419802 E-11 x 119b96f36ec68b_00000000000000000000000001& E-18
+ convertToDouble +419802E-11
+} 0x3ed19b96f36ec68b
+test expr-28.634 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -537734 E-24 x -13d6c1088ae40e_0000000000000000000001& E-61
+ convertToDouble -537734E-24
+} 0xbc23d6c1088ae40e
+test expr-28.635 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +910308 E26 x 11f3e1839eeab0_11111111111111111111110& E106
+ convertToDouble +910308E26
+} 0x4691f3e1839eeab1
+test expr-28.636 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -227577 E26 x -11f3e1839eeab0_11111111111111111111110& E104
+ convertToDouble -227577E26
+} 0xc671f3e1839eeab1
+test expr-28.637 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +455154 E26 x 11f3e1839eeab0_11111111111111111111110& E105
+ convertToDouble +455154E26
+} 0x4681f3e1839eeab1
+test expr-28.638 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -531013 E25 x -10c17d25834171_11111111111111111111110& E102
+ convertToDouble -531013E25
+} 0xc650c17d25834172
+test expr-28.639 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +963019 E-21 x 11592429784914_11111111111111111111110& E-50
+ convertToDouble +963019E-21
+} 0x3cd1592429784915
+test expr-28.640 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -519827 E-13 x -1be872a8b30d7c_11111111111111111111110& E-25
+ convertToDouble -519827E-13
+} 0xbe6be872a8b30d7d
+test expr-28.641 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +623402 E-27 x 178d2c97bde2a0_11111111111111111111110& E-71
+ convertToDouble +623402E-27
+} 0x3b878d2c97bde2a1
+test expr-28.642 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -311701 E-27 x -178d2c97bde2a0_11111111111111111111110& E-72
+ convertToDouble -311701E-27
+} 0xbb778d2c97bde2a1
+test expr-28.643 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +9613651 E26 x 17b31116270d9b_000000000000000000000001& E109
+ convertToDouble +9613651E26
+} 0x46c7b31116270d9b
+test expr-28.644 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -9191316 E23 x -1733bfae0801fd_0000000000000000000001& E99
+ convertToDouble -9191316E23
+} 0xc62733bfae0801fd
+test expr-28.645 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +4595658 E23 x 1733bfae0801fd_0000000000000000000001& E98
+ convertToDouble +4595658E23
+} 0x461733bfae0801fd
+test expr-28.646 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -2297829 E23 x -1733bfae0801fd_0000000000000000000001& E97
+ convertToDouble -2297829E23
+} 0xc60733bfae0801fd
+test expr-28.647 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -1679208 E-11 x -119b96f36ec68b_00000000000000000000000001& E-16
+ convertToDouble -1679208E-11
+} 0xbef19b96f36ec68b
+test expr-28.648 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +3379223 E27 x 14d3794ce2fc25_1111111111111111111111110& E111
+ convertToDouble +3379223E27
+} 0x46e4d3794ce2fc26
+test expr-28.649 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -6758446 E27 x -14d3794ce2fc25_1111111111111111111111110& E112
+ convertToDouble -6758446E27
+} 0xc6f4d3794ce2fc26
+test expr-28.650 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +5444097 E-21 x 18849dd33c95ae_11111111111111111111111111110& E-48
+ convertToDouble +5444097E-21
+} 0x3cf8849dd33c95af
+test expr-28.651 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -8399969 E-27 x -13d5783e85fcf7_1111111111111111111111110& E-67
+ convertToDouble -8399969E-27
+} 0xbbc3d5783e85fcf8
+test expr-28.652 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +8366487 E-16 x 1cbf3d630403af_1111111111111111111111110& E-31
+ convertToDouble +8366487E-16
+} 0x3e0cbf3d630403b0
+test expr-28.653 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -8366487 E-15 x -11f7865de2824d_11111111111111111111111110& E-27
+ convertToDouble -8366487E-15
+} 0xbe41f7865de2824e
+test expr-28.654 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +65060671 E25 x 1009e7d474572a_0000000000000000000000000001& E109
+ convertToDouble +65060671E25
+} 0x46c009e7d474572a
+test expr-28.655 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +65212389 E23 x 1493d098d37657_000000000000000000000000001& E102
+ convertToDouble +65212389E23
+} 0x465493d098d37657
+test expr-28.656 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +55544957 E-13 x 174c1826f3010c_00000000000000000000000000001& E-18
+ convertToDouble +55544957E-13
+} 0x3ed74c1826f3010c
+test expr-28.657 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -51040905 E-20 x -11f55b23c8bf2d_0000000000000000000000000001& E-41
+ convertToDouble -51040905E-20
+} 0xbd61f55b23c8bf2d
+test expr-28.658 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +99585767 E-22 x 166cba8699f0f2_0000000000000000000000000001& E-47
+ convertToDouble +99585767E-22
+} 0x3d066cba8699f0f2
+test expr-28.659 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -99585767 E-23 x -11f095387b2728_0000000000000000000000000001& E-50
+ convertToDouble -99585767E-23
+} 0xbcd1f095387b2728
+test expr-28.660 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +40978393 E26 x 1941401cca2bfd_1111111111111111111111111110& E111
+ convertToDouble +40978393E26
+} 0x46e941401cca2bfe
+test expr-28.661 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -67488159 E24 x -1a9e90059d12db_11111111111111111111111111110& E105
+ convertToDouble -67488159E24
+} 0xc68a9e90059d12dc
+test expr-28.662 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +69005339 E23 x 15c634f6ef1f95_111111111111111111111111110& E102
+ convertToDouble +69005339E23
+} 0x4655c634f6ef1f96
+test expr-28.663 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -81956786 E26 x -1941401cca2bfd_1111111111111111111111111110& E112
+ convertToDouble -81956786E26
+} 0xc6f941401cca2bfe
+test expr-28.664 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -87105552 E-21 x -18849dd33c95ae_11111111111111111111111111110& E-44
+ convertToDouble -87105552E-21
+} 0xbd38849dd33c95af
+test expr-28.665 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +10888194 E-21 x 18849dd33c95ae_11111111111111111111111111110& E-47
+ convertToDouble +10888194E-21
+} 0x3d08849dd33c95af
+test expr-28.666 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -21776388 E-21 x -18849dd33c95ae_11111111111111111111111111110& E-46
+ convertToDouble -21776388E-21
+} 0xbd18849dd33c95af
+test expr-28.667 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +635806667 E27 x 1e9cec176c96f8_000000000000000000000000000000001& E118
+ convertToDouble +635806667E27
+} 0x475e9cec176c96f8
+test expr-28.668 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -670026614 E25 x -14a593f89f4194_00000000000000000000000000000001& E112
+ convertToDouble -670026614E25
+} 0xc6f4a593f89f4194
+test expr-28.669 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +335013307 E26 x 19cef8f6c711f9_0000000000000000000000000000001& E114
+ convertToDouble +335013307E26
+} 0x4719cef8f6c711f9
+test expr-28.670 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -335013307 E25 x -14a593f89f4194_00000000000000000000000000000001& E111
+ convertToDouble -335013307E25
+} 0xc6e4a593f89f4194
+test expr-28.671 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +371790617 E-24 x 1aca538c61ba9c_000000000000000000000000000000001& E-52
+ convertToDouble +371790617E-24
+} 0x3cbaca538c61ba9c
+test expr-28.672 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -371790617 E-25 x -156ea93d1afbb0_0000000000000000000000000000000001& E-55
+ convertToDouble -371790617E-25
+} 0xbc856ea93d1afbb0
+test expr-28.673 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +743581234 E-24 x 1aca538c61ba9c_000000000000000000000000000000001& E-51
+ convertToDouble +743581234E-24
+} 0x3ccaca538c61ba9c
+test expr-28.674 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -743581234 E-25 x -156ea93d1afbb0_0000000000000000000000000000000001& E-54
+ convertToDouble -743581234E-25
+} 0xbc956ea93d1afbb0
+test expr-28.675 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +202464477 E24 x 13f6ec0435ce24_111111111111111111111111111110& E107
+ convertToDouble +202464477E24
+} 0x46a3f6ec0435ce25
+test expr-28.676 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -404928954 E24 x -13f6ec0435ce24_111111111111111111111111111110& E108
+ convertToDouble -404928954E24
+} 0xc6b3f6ec0435ce25
+test expr-28.677 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +997853758 E27 x 1805bfa33b98fa_111111111111111111111111111110& E119
+ convertToDouble +997853758E27
+} 0x476805bfa33b98fb
+test expr-28.678 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -997853758 E26 x -1337cc829613fb_111111111111111111111111111110& E116
+ convertToDouble -997853758E26
+} 0xc73337cc829613fc
+test expr-28.679 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +405498418 E-17 x 116a8093df66a6_111111111111111111111111111111110& E-28
+ convertToDouble +405498418E-17
+} 0x3e316a8093df66a7
+test expr-28.680 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -582579084 E-14 x -186f653140a658_111111111111111111111111111111110& E-18
+ convertToDouble -582579084E-14
+} 0xbed86f653140a659
+test expr-28.681 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +608247627 E-18 x 14e633e4a5ae61_111111111111111111111111111111110& E-31
+ convertToDouble +608247627E-18
+} 0x3e04e633e4a5ae62
+test expr-28.682 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -291289542 E-14 x -186f653140a658_111111111111111111111111111111110& E-19
+ convertToDouble -291289542E-14
+} 0xbec86f653140a659
+test expr-28.683 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -9537100005 E26 x -16f5b11191713a_000000000000000000000000000000001& E119
+ convertToDouble -9537100005E26
+} 0xc766f5b11191713a
+test expr-28.684 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +6358066670 E27 x 1322138ea3de5b_000000000000000000000000000000001& E122
+ convertToDouble +6358066670E27
+} 0x479322138ea3de5b
+test expr-28.685 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -1271613334 E27 x -1e9cec176c96f8_000000000000000000000000000000001& E119
+ convertToDouble -1271613334E27
+} 0xc76e9cec176c96f8
+test expr-28.686 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +5229646999 E-16 x 118c3b89731f3d_000000000000000000000000000000000001& E-21
+ convertToDouble +5229646999E-16
+} 0x3ea18c3b89731f3d
+test expr-28.687 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +5229646999 E-17 x 1c13927584fec8_00000000000000000000000000000000001& E-25
+ convertToDouble +5229646999E-17
+} 0x3e6c13927584fec8
+test expr-28.688 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +4429943614 E24 x 1b4d37fa06864a_1111111111111111111111111111111110& E111
+ convertToDouble +4429943614E24
+} 0x46eb4d37fa06864b
+test expr-28.689 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -8859887228 E24 x -1b4d37fa06864a_1111111111111111111111111111111110& E112
+ convertToDouble -8859887228E24
+} 0xc6fb4d37fa06864b
+test expr-28.690 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +2214971807 E24 x 1b4d37fa06864a_1111111111111111111111111111111110& E110
+ convertToDouble +2214971807E24
+} 0x46db4d37fa06864b
+test expr-28.691 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -4176887093 E26 x -141c692c5bd07a_111111111111111111111111111111110& E118
+ convertToDouble -4176887093E26
+} 0xc7541c692c5bd07b
+test expr-28.692 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +4003495257 E-20 x 16026b2e07ec06_111111111111111111111111111111111110& E-35
+ convertToDouble +4003495257E-20
+} 0x3dc6026b2e07ec07
+test expr-28.693 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -4361901637 E-23 x -188e29a9d7c5b8_11111111111111111111111111111111110& E-45
+ convertToDouble -4361901637E-23
+} 0xbd288e29a9d7c5b9
+test expr-28.694 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +8723803274 E-23 x 188e29a9d7c5b8_11111111111111111111111111111111110& E-44
+ convertToDouble +8723803274E-23
+} 0x3d388e29a9d7c5b9
+test expr-28.695 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -8006990514 E-20 x -16026b2e07ec06_111111111111111111111111111111111110& E-34
+ convertToDouble -8006990514E-20
+} 0xbdd6026b2e07ec07
+test expr-28.696 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +72835110098 E27 x 1b65c41711fb6d_0000000000000000000000000000000000001& E125
+ convertToDouble +72835110098E27
+} 0x47cb65c41711fb6d
+test expr-28.697 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -36417555049 E27 x -1b65c41711fb6d_0000000000000000000000000000000000001& E124
+ convertToDouble -36417555049E27
+} 0xc7bb65c41711fb6d
+test expr-28.698 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +84279630104 E25 x 144a221b1cf62e_000000000000000000000000000000000001& E119
+ convertToDouble +84279630104E25
+} 0x47644a221b1cf62e
+test expr-28.699 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -84279630104 E24 x -103b4e7c172b58_000000000000000000000000000000000001& E116
+ convertToDouble -84279630104E24
+} 0xc7303b4e7c172b58
+test expr-28.700 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +21206176437 E-27 x 1872f563ae0cc9_0000000000000000000000000000000000001& E-56
+ convertToDouble +21206176437E-27
+} 0x3c7872f563ae0cc9
+test expr-28.701 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -66461566917 E-22 x -1d3ae83e4322b3_00000000000000000000000000000000000001& E-38
+ convertToDouble -66461566917E-22
+} 0xbd9d3ae83e4322b3
+test expr-28.702 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +64808355539 E-16 x 1b2ebe83265fbf_00000000000000000000000000000000000001& E-18
+ convertToDouble +64808355539E-16
+} 0x3edb2ebe83265fbf
+test expr-28.703 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -84932679673 E-19 x -123d39339f1bf6_00000000000000000000000000000000000001& E-27
+ convertToDouble -84932679673E-19
+} 0xbe423d39339f1bf6
+test expr-28.704 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +65205430094 E26 x 139f3e5d7fd76a_1111111111111111111111111111111111110& E122
+ convertToDouble +65205430094E26
+} 0x47939f3e5d7fd76b
+test expr-28.705 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -68384463429 E25 x -107684982f634e_1111111111111111111111111111111111111110& E119
+ convertToDouble -68384463429E25
+} 0xc7607684982f634f
+test expr-28.706 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +32602715047 E26 x 139f3e5d7fd76a_1111111111111111111111111111111111110& E121
+ convertToDouble +32602715047E26
+} 0x47839f3e5d7fd76b
+test expr-28.707 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -62662203426 E27 x -1792269424688d_111111111111111111111111111111111110& E125
+ convertToDouble -62662203426E27
+} 0xc7c792269424688e
+test expr-28.708 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +58784444678 E-18 x 1f8f45c64b4682_111111111111111111111111111111111111110& E-25
+ convertToDouble +58784444678E-18
+} 0x3e6f8f45c64b4683
+test expr-28.709 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -50980203373 E-21 x -1c06d366394440_11111111111111111111111111111111111111111110& E-35
+ convertToDouble -50980203373E-21
+} 0xbdcc06d366394441
+test expr-28.710 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +29392222339 E-18 x 1f8f45c64b4682_111111111111111111111111111111111111110& E-26
+ convertToDouble +29392222339E-18
+} 0x3e5f8f45c64b4683
+test expr-28.711 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -75529940323 E-27 x -15c5203c0aad52_1111111111111111111111111111111111111110& E-54
+ convertToDouble -75529940323E-27
+} 0xbc95c5203c0aad53
+test expr-28.712 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -937495906299 E26 x -11a1e0ebb6af11_000000000000000000000000000000000000000001& E126
+ convertToDouble -937495906299E26
+} 0xc7d1a1e0ebb6af11
+test expr-28.713 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +842642485799 E-20 x 121879decdd7cb_000000000000000000000000000000000000000001& E-27
+ convertToDouble +842642485799E-20
+} 0x3e421879decdd7cb
+test expr-28.714 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -387824150699 E-23 x -110e8302245571_00000000000000000000000000000000000000001& E-38
+ convertToDouble -387824150699E-23
+} 0xbd910e8302245571
+test expr-28.715 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +924948814726 E-27 x 10a992d1fc6ded_00000000000000000000000000000000000000001& E-50
+ convertToDouble +924948814726E-27
+} 0x3cd0a992d1fc6ded
+test expr-28.716 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -775648301398 E-23 x -110e8302245571_00000000000000000000000000000000000000001& E-37
+ convertToDouble -775648301398E-23
+} 0xbda10e8302245571
+test expr-28.717 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +547075707432 E25 x 107684982f634e_1111111111111111111111111111111111111110& E122
+ convertToDouble +547075707432E25
+} 0x47907684982f634f
+test expr-28.718 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +683844634290 E24 x 107684982f634e_1111111111111111111111111111111111111110& E119
+ convertToDouble +683844634290E24
+} 0x47607684982f634f
+test expr-28.719 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -136768926858 E25 x -107684982f634e_1111111111111111111111111111111111111110& E120
+ convertToDouble -136768926858E25
+} 0xc7707684982f634f
+test expr-28.720 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +509802033730 E-22 x 1c06d366394440_11111111111111111111111111111111111111111110& E-35
+ convertToDouble +509802033730E-22
+} 0x3dcc06d366394441
+test expr-28.721 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +101960406746 E-21 x 1c06d366394440_11111111111111111111111111111111111111111110& E-34
+ convertToDouble +101960406746E-21
+} 0x3ddc06d366394441
+test expr-28.722 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -815683253968 E-21 x -1c06d366394440_11111111111111111111111111111111111111111110& E-31
+ convertToDouble -815683253968E-21
+} 0xbe0c06d366394441
+test expr-28.723 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +7344124123524 E24 x 1619b519dd6833_00000000000000000000000000000000000000000001& E122
+ convertToDouble +7344124123524E24
+} 0x479619b519dd6833
+test expr-28.724 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -9180155154405 E23 x -1619b519dd6833_00000000000000000000000000000000000000000001& E119
+ convertToDouble -9180155154405E23
+} 0xc76619b519dd6833
+test expr-28.725 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +6479463327323 E27 x 130a9b3e9bd05e_00000000000000000000000000000000000000000001& E132
+ convertToDouble +6479463327323E27
+} 0x48330a9b3e9bd05e
+test expr-28.726 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -1836031030881 E24 x -1619b519dd6833_00000000000000000000000000000000000000000001& E120
+ convertToDouble -1836031030881E24
+} 0xc77619b519dd6833
+test expr-28.727 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +4337269293039 E-19 x 1d1b5f354c63d6_00000000000000000000000000000000000000000001& E-22
+ convertToDouble +4337269293039E-19
+} 0x3e9d1b5f354c63d6
+test expr-28.728 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -4599163554373 E-23 x -1948bf4d34088d_00000000000000000000000000000000000000000001& E-35
+ convertToDouble -4599163554373E-23
+} 0xbdc948bf4d34088d
+test expr-28.729 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +9198327108746 E-23 x 1948bf4d34088d_00000000000000000000000000000000000000000001& E-34
+ convertToDouble +9198327108746E-23
+} 0x3dd948bf4d34088d
+test expr-28.730 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +4812803938347 E27 x 1c4980a4ee94ce_111111111111111111111111111111111111111111110& E131
+ convertToDouble +4812803938347E27
+} 0x482c4980a4ee94cf
+test expr-28.731 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -8412030890011 E23 x -14405075e52db9_11111111111111111111111111111111111111111110& E119
+ convertToDouble -8412030890011E23
+} 0xc764405075e52dba
+test expr-28.732 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +9625607876694 E27 x 1c4980a4ee94ce_111111111111111111111111111111111111111111110& E132
+ convertToDouble +9625607876694E27
+} 0x483c4980a4ee94cf
+test expr-28.733 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -4739968828249 E24 x -1c87140cdf8a1d_1111111111111111111111111111111111111111110& E121
+ convertToDouble -4739968828249E24
+} 0xc78c87140cdf8a1e
+test expr-28.734 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +9697183891673 E-23 x 1aa7c959b6a666_11111111111111111111111111111111111111111111110& E-34
+ convertToDouble +9697183891673E-23
+} 0x3ddaa7c959b6a667
+test expr-28.735 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -7368108517543 E-20 x -13c7535bbd85a1_1111111111111111111111111111111111111111111110& E-24
+ convertToDouble -7368108517543E-20
+} 0xbe73c7535bbd85a2
+test expr-28.736 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +51461358161422 E25 x 18326f87d4cae0_0000000000000000000000000000000000000000000000001& E128
+ convertToDouble +51461358161422E25
+} 0x47f8326f87d4cae0
+test expr-28.737 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -77192037242133 E26 x -16af488f577e32_0000000000000000000000000000000000000000000000001& E132
+ convertToDouble -77192037242133E26
+} 0xc836af488f577e32
+test expr-28.738 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +77192037242133 E25 x 1225d3a5df9828_0000000000000000000000000000000000000000000000001& E129
+ convertToDouble +77192037242133E25
+} 0x480225d3a5df9828
+test expr-28.739 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -51461358161422 E27 x -12e767221e3e7f_0000000000000000000000000000000000000000000000001& E135
+ convertToDouble -51461358161422E27
+} 0xc862e767221e3e7f
+test expr-28.740 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +43999661561541 E-21 x 179f4476d372a3_0000000000000000000000000000000000000000000000001& E-25
+ convertToDouble +43999661561541E-21
+} 0x3e679f4476d372a3
+test expr-28.741 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -87999323123082 E-21 x -179f4476d372a3_0000000000000000000000000000000000000000000000001& E-24
+ convertToDouble -87999323123082E-21
+} 0xbe779f4476d372a3
+test expr-28.742 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +48374886826137 E-26 x 110538f23350d5_00000000000000000000000000000000000000000000001& E-41
+ convertToDouble +48374886826137E-26
+} 0x3d610538f23350d5
+test expr-28.743 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -57684246567111 E-23 x -13d1f5c1b8a912_00000000000000000000000000000000000000000000001& E-31
+ convertToDouble -57684246567111E-23
+} 0xbe03d1f5c1b8a912
+test expr-28.744 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +87192805957686 E23 x 1a3d16e55a9664_1111111111111111111111111111111111111111111110& E122
+ convertToDouble +87192805957686E23
+} 0x479a3d16e55a9665
+test expr-28.745 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -75108713005913 E24 x -1c40b4baa79655_11111111111111111111111111111111111111111111110& E125
+ convertToDouble -75108713005913E24
+} 0xc7cc40b4baa79656
+test expr-28.746 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +64233110587487 E27 x 179873e38669a6_1111111111111111111111111111111111111111111110& E135
+ convertToDouble +64233110587487E27
+} 0x48679873e38669a7
+test expr-28.747 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -77577471133384 E-23 x -1aa7c959b6a666_11111111111111111111111111111111111111111111110& E-31
+ convertToDouble -77577471133384E-23
+} 0xbe0aa7c959b6a667
+test expr-28.748 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +48485919458365 E-24 x 1aa7c959b6a666_11111111111111111111111111111111111111111111110& E-35
+ convertToDouble +48485919458365E-24
+} 0x3dcaa7c959b6a667
+test expr-28.749 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -56908598265713 E-26 x -1405deef4bdef5_111111111111111111111111111111111111111111111110& E-41
+ convertToDouble -56908598265713E-26
+} 0xbd6405deef4bdef6
+test expr-28.750 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +589722294620133 E23 x 162ed1b287caef_00000000000000000000000000000000000000000000000001& E125
+ convertToDouble +589722294620133E23
+} 0x47c62ed1b287caef
+test expr-28.751 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +652835804449289 E-22 x 118640e490b087_0000000000000000000000000000000000000000000000000001& E-24
+ convertToDouble +652835804449289E-22
+} 0x3e718640e490b087
+test expr-28.752 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -656415363936202 E-23 x -1c315cfe25d201_00000000000000000000000000000000000000000000000001& E-28
+ convertToDouble -656415363936202E-23
+} 0xbe3c315cfe25d201
+test expr-28.753 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +579336749585745 E-25 x 1fd9709d9aeb19_00000000000000000000000000000000000000000000000001& E-35
+ convertToDouble +579336749585745E-25
+} 0x3dcfd9709d9aeb19
+test expr-28.754 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -381292764980839 E-26 x -10c4f9921c3f8f_00000000000000000000000000000000000000000000000001& E-38
+ convertToDouble -381292764980839E-26
+} 0xbd90c4f9921c3f8f
+test expr-28.755 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +965265859649698 E23 x 12279607edcb0c_1111111111111111111111111111111111111111111111110& E126
+ convertToDouble +965265859649698E23
+} 0x47d2279607edcb0d
+test expr-28.756 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -848925235434882 E27 x -137d88ba4b43e3_1111111111111111111111111111111111111111111111111110& E139
+ convertToDouble -848925235434882E27
+} 0xc8a37d88ba4b43e4
+test expr-28.757 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +536177612222491 E23 x 142b33dd3acafd_11111111111111111111111111111111111111111111111110& E125
+ convertToDouble +536177612222491E23
+} 0x47c42b33dd3acafe
+test expr-28.758 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -424462617717441 E27 x -137d88ba4b43e3_1111111111111111111111111111111111111111111111111110& E138
+ convertToDouble -424462617717441E27
+} 0xc8937d88ba4b43e4
+test expr-28.759 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +276009279888989 E-27 x 136c242313c288_111111111111111111111111111111111111111111111111110& E-42
+ convertToDouble +276009279888989E-27
+} 0x3d536c242313c289
+test expr-28.760 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -608927158043691 E-26 x -1ac7e909c22f09_11111111111111111111111111111111111111111111111110& E-38
+ convertToDouble -608927158043691E-26
+} 0xbd9ac7e909c22f0a
+test expr-28.761 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +552018559777978 E-27 x 136c242313c288_111111111111111111111111111111111111111111111111110& E-41
+ convertToDouble +552018559777978E-27
+} 0x3d636c242313c289
+test expr-28.762 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -425678377667758 E-22 x -16da7aa49bdcd5_1111111111111111111111111111111111111111111111110& E-25
+ convertToDouble -425678377667758E-22
+} 0xbe66da7aa49bdcd6
+test expr-28.763 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +8013702726927119 E26 x 126607f8f1b29e_00000000000000000000000000000000000000000000000000001& E139
+ convertToDouble +8013702726927119E26
+} 0x48a26607f8f1b29e
+test expr-28.764 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +8862627962362001 E27 x 196f3b0e7787c2_00000000000000000000000000000000000000000000000000001& E142
+ convertToDouble +8862627962362001E27
+} 0x48d96f3b0e7787c2
+test expr-28.765 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -5068007907757162 E26 x -17456a27848397_00000000000000000000000000000000000000000000000000001& E138
+ convertToDouble -5068007907757162E26
+} 0xc897456a27848397
+test expr-28.766 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -7379714799828406 E-23 x -13cf4d2839e036_00000000000000000000000000000000000000000000000000001& E-24
+ convertToDouble -7379714799828406E-23
+} 0xbe73cf4d2839e036
+test expr-28.767 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +4114538064016107 E-27 x 12188eda98010c_0000000000000000000000000000000000000000000000000001& E-38
+ convertToDouble +4114538064016107E-27
+} 0x3d92188eda98010c
+test expr-28.768 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -3689857399914203 E-23 x -13cf4d2839e036_00000000000000000000000000000000000000000000000000001& E-25
+ convertToDouble -3689857399914203E-23
+} 0xbe63cf4d2839e036
+test expr-28.769 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +5575954851815478 E23 x 1a37cfbf2ffdb5_1111111111111111111111111111111111111111111111111110& E128
+ convertToDouble +5575954851815478E23
+} 0x47fa37cfbf2ffdb6
+test expr-28.770 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +3395700941739528 E27 x 137d88ba4b43e3_1111111111111111111111111111111111111111111111111110& E141
+ convertToDouble +3395700941739528E27
+} 0x48c37d88ba4b43e4
+test expr-28.771 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +4115535777581961 E-23 x 1618596be30fe4_111111111111111111111111111111111111111111111111111110& E-25
+ convertToDouble +4115535777581961E-23
+} 0x3e6618596be30fe5
+test expr-28.772 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -8231071555163922 E-23 x -1618596be30fe4_111111111111111111111111111111111111111111111111111110& E-24
+ convertToDouble -8231071555163922E-23
+} 0xbe7618596be30fe5
+test expr-28.773 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +6550246696190871 E-26 x 1201538b0f8c69_111111111111111111111111111111111111111111111111111110& E-34
+ convertToDouble +6550246696190871E-26
+} 0x3dd201538b0f8c6a
+test expr-28.774 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -68083046403986701 E27 x -186c70ba8ba28d_000000000000000000000000000000000000000000000000000000001& E145
+ convertToDouble -68083046403986701E27
+} 0xc9086c70ba8ba28d
+test expr-28.775 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +43566388595783643 E27 x 1f41e1bf48b03f_111111111111111111111111111111111111111111111111111111110& E144
+ convertToDouble +43566388595783643E27
+} 0x48ff41e1bf48b040
+test expr-28.776 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -87132777191567286 E27 x -1f41e1bf48b03f_111111111111111111111111111111111111111111111111111111110& E145
+ convertToDouble -87132777191567286E27
+} 0xc90f41e1bf48b040
+test expr-28.777 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +59644881059342141 E25 x 1b6338d9d8ae38_11111111111111111111111111111111111111111111111111111110& E138
+ convertToDouble +59644881059342141E25
+} 0x489b6338d9d8ae39
+test expr-28.778 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -83852770718576667 E23 x -18a4619ed6f442_111111111111111111111111111111111111111111111111111111110& E132
+ convertToDouble -83852770718576667E23
+} 0xc838a4619ed6f443
+test expr-28.779 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +99482967418206961 E-25 x 155d224bfed7ac_11111111111111111111111111111111111111111111111111111111110& E-27
+ convertToDouble +99482967418206961E-25
+} 0x3e455d224bfed7ad
+test expr-28.780 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -99482967418206961 E-26 x -11174ea3324623_11111111111111111111111111111111111111111111111111111111110& E-30
+ convertToDouble -99482967418206961E-26
+} 0xbe11174ea3324624
+test expr-28.781 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +87446669969994614 E-27 x 1809832942376d_11111111111111111111111111111111111111111111111111111110& E-34
+ convertToDouble +87446669969994614E-27
+} 0x3dd809832942376e
+test expr-28.782 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -43723334984997307 E-27 x -1809832942376d_11111111111111111111111111111111111111111111111111111110& E-35
+ convertToDouble -43723334984997307E-27
+} 0xbdc809832942376e
+test expr-28.783 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +5 E24 x 108b2a2c280290_1001& E82
+ convertToDouble +5E24
+} 0x45108b2a2c280291
+test expr-28.784 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -8 E25 x -108b2a2c280290_1001& E86
+ convertToDouble -8E25
+} 0xc5508b2a2c280291
+test expr-28.785 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +1 E25 x 108b2a2c280290_1001& E83
+ convertToDouble +1E25
+} 0x45208b2a2c280291
+test expr-28.786 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -4 E25 x -108b2a2c280290_1001& E85
+ convertToDouble -4E25
+} 0xc5408b2a2c280291
+test expr-28.787 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +2 E-5 x 14f8b588e368f0_100001& E-16
+ convertToDouble +2E-5
+} 0x3ef4f8b588e368f1
+test expr-28.788 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -5 E-6 x -14f8b588e368f0_100001& E-18
+ convertToDouble -5E-6
+} 0xbed4f8b588e368f1
+test expr-28.789 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +4 E-5 x 14f8b588e368f0_100001& E-15
+ convertToDouble +4E-5
+} 0x3f04f8b588e368f1
+test expr-28.790 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -3 E-20 x -11b578c96db19a_100001& E-65
+ convertToDouble -3E-20
+} 0xbbe1b578c96db19b
+test expr-28.791 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +3 E27 x 1363156bbee301_0110& E91
+ convertToDouble +3E27
+} 0x45a363156bbee301
+test expr-28.792 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -9 E26 x -1743b34e18439b_010& E89
+ convertToDouble -9E26
+} 0xc58743b34e18439b
+test expr-28.793 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +7 E25 x 1cf389cd46047d_00& E85
+ convertToDouble +7E25
+} 0x454cf389cd46047d
+test expr-28.794 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -6 E27 x -1363156bbee301_0110& E92
+ convertToDouble -6E27
+} 0xc5b363156bbee301
+test expr-28.795 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +2 E-21 x 12e3b40a0e9b4f_0111110& E-69
+ convertToDouble +2E-21
+} 0x3ba2e3b40a0e9b4f
+test expr-28.796 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -5 E-22 x -12e3b40a0e9b4f_0111110& E-71
+ convertToDouble -5E-22
+} 0xbb82e3b40a0e9b4f
+test expr-28.797 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -4 E-21 x -12e3b40a0e9b4f_0111110& E-68
+ convertToDouble -4E-21
+} 0xbbb2e3b40a0e9b4f
+test expr-28.798 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +87 E25 x 167d2d5406637c_10001& E89
+ convertToDouble +87E25
+} 0x45867d2d5406637d
+test expr-28.799 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -97 E24 x -140f232256e982_1000000001& E86
+ convertToDouble -97E24
+} 0xc5540f232256e983
+test expr-28.800 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +82 E-24 x 18c87154dff6c6_1000000001& E-74
+ convertToDouble +82E-24
+} 0x3b58c87154dff6c7
+test expr-28.801 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -41 E-24 x -18c87154dff6c6_1000000001& E-75
+ convertToDouble -41E-24
+} 0xbb48c87154dff6c7
+test expr-28.802 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +76 E-23 x 1cb644dc1633c0_10000001& E-71
+ convertToDouble +76E-23
+} 0x3b8cb644dc1633c1
+test expr-28.803 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +83 E25 x 15747ab143e353_011111111110& E89
+ convertToDouble +83E25
+} 0x4585747ab143e353
+test expr-28.804 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -50 E27 x -1431e0fae6d721_0111110& E95
+ convertToDouble -50E27
+} 0xc5e431e0fae6d721
+test expr-28.805 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +25 E27 x 1431e0fae6d721_0111110& E94
+ convertToDouble +25E27
+} 0x45d431e0fae6d721
+test expr-28.806 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -99 E27 x -13fe2e171cda19_011110& E96
+ convertToDouble -99E27
+} 0xc5f3fe2e171cda19
+test expr-28.807 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +97 E-10 x 14d4a1a3157dc7_011111110& E-27
+ convertToDouble +97E-10
+} 0x3e44d4a1a3157dc7
+test expr-28.808 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -57 E-20 x -15077f6f3242e7_011111110& E-61
+ convertToDouble -57E-20
+} 0xbc25077f6f3242e7
+test expr-28.809 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +997 E23 x 149e12f51c1a3c_10000000001& E86
+ convertToDouble +997E23
+} 0x45549e12f51c1a3d
+test expr-28.810 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +776 E24 x 140f232256e982_1000000001& E89
+ convertToDouble +776E24
+} 0x45840f232256e983
+test expr-28.811 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -388 E24 x -140f232256e982_1000000001& E88
+ convertToDouble -388E24
+} 0xc5740f232256e983
+test expr-28.812 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +521 E-10 x 1bf891c92c0890_100000000001& E-25
+ convertToDouble +521E-10
+} 0x3e6bf891c92c0891
+test expr-28.813 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -506 E-26 x -1877fa0260beb2_10000000001& E-78
+ convertToDouble -506E-26
+} 0xbb1877fa0260beb3
+test expr-28.814 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +739 E-10 x 13d65e8c76722c_10000000001& E-24
+ convertToDouble +739E-10
+} 0x3e73d65e8c76722d
+test expr-28.815 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -867 E-7 x -16ba56a8834168_100000000001& E-14
+ convertToDouble -867E-7
+} 0xbf16ba56a8834169
+test expr-28.816 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -415 E24 x -15747ab143e353_011111111110& E88
+ convertToDouble -415E24
+} 0xc575747ab143e353
+test expr-28.817 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +332 E25 x 15747ab143e353_011111111110& E91
+ convertToDouble +332E25
+} 0x45a5747ab143e353
+test expr-28.818 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -664 E25 x -15747ab143e353_011111111110& E92
+ convertToDouble -664E25
+} 0xc5b5747ab143e353
+test expr-28.819 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +291 E-13 x 1ffeebfc8b81b5_01111111111110& E-36
+ convertToDouble +291E-13
+} 0x3dbffeebfc8b81b5
+test expr-28.820 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -982 E-8 x -14981285e98e79_0111111111110& E-17
+ convertToDouble -982E-8
+} 0xbee4981285e98e79
+test expr-28.821 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +582 E-13 x 1ffeebfc8b81b5_01111111111110& E-35
+ convertToDouble +582E-13
+} 0x3dcffeebfc8b81b5
+test expr-28.822 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -491 E-8 x -14981285e98e79_0111111111110& E-18
+ convertToDouble -491E-8
+} 0xbed4981285e98e79
+test expr-28.823 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +4574 E26 x 1717c1a612f954_100000000001& E98
+ convertToDouble +4574E26
+} 0x461717c1a612f955
+test expr-28.824 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -8609 E26 x -15bb6f942546ee_1000000000001& E99
+ convertToDouble -8609E26
+} 0xc625bb6f942546ef
+test expr-28.825 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +2287 E26 x 1717c1a612f954_100000000001& E97
+ convertToDouble +2287E26
+} 0x460717c1a612f955
+test expr-28.826 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -4818 E24 x -1f22b65eb419a0_10000000001& E91
+ convertToDouble -4818E24
+} 0xc5af22b65eb419a1
+test expr-28.827 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +6529 E-8 x 111d89a8b5c142_100000000000001& E-14
+ convertToDouble +6529E-8
+} 0x3f111d89a8b5c143
+test expr-28.828 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -8151 E-21 x -12cb804b61b898_1000000000000001& E-57
+ convertToDouble -8151E-21
+} 0xbc62cb804b61b899
+test expr-28.829 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +1557 E-12 x 1abfc227ab1026_10000000000001& E-30
+ convertToDouble +1557E-12
+} 0x3e1abfc227ab1027
+test expr-28.830 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -2573 E-18 x -172cef1ebbca44_10000000000001& E-49
+ convertToDouble -2573E-18
+} 0xbce72cef1ebbca45
+test expr-28.831 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +4929 E-16 x 1157a604ed019f_0111111111111110& E-41
+ convertToDouble +4929E-16
+} 0x3d6157a604ed019f
+test expr-28.832 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -3053 E-22 x -1686f435fe6b6b_011111111111110& E-62
+ convertToDouble -3053E-22
+} 0xbc1686f435fe6b6b
+test expr-28.833 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +9858 E-16 x 1157a604ed019f_0111111111111110& E-40
+ convertToDouble +9858E-16
+} 0x3d7157a604ed019f
+test expr-28.834 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -7767 E-11 x -14d971170ed055_011111111111110& E-24
+ convertToDouble -7767E-11
+} 0xbe74d971170ed055
+test expr-28.835 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +54339 E26 x 1125782ec15cbe_100000000000000001& E102
+ convertToDouble +54339E26
+} 0x465125782ec15cbf
+test expr-28.836 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -62409 E25 x -1f822c980d4bb2_100000000000000001& E98
+ convertToDouble -62409E25
+} 0xc61f822c980d4bb3
+test expr-28.837 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +32819 E27 x 19e3be885fc16a_100000000000001& E104
+ convertToDouble +32819E27
+} 0x4679e3be885fc16b
+test expr-28.838 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -89849 E27 x -11b8371b6dda04_1000000000000001& E106
+ convertToDouble -89849E27
+} 0xc691b8371b6dda05
+test expr-28.839 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +63876 E-20 x 1703856844bdbe_1000000000000000000001& E-51
+ convertToDouble +63876E-20
+} 0x3cc703856844bdbf
+test expr-28.840 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -15969 E-20 x -1703856844bdbe_1000000000000000000001& E-53
+ convertToDouble -15969E-20
+} 0xbca703856844bdbf
+test expr-28.841 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +31938 E-20 x 1703856844bdbe_1000000000000000000001& E-52
+ convertToDouble +31938E-20
+} 0x3cb703856844bdbf
+test expr-28.842 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -79845 E-21 x -1703856844bdbe_1000000000000000000001& E-54
+ convertToDouble -79845E-21
+} 0xbc9703856844bdbf
+test expr-28.843 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +89306 E27 x 119cccff237e17_011111111111110& E106
+ convertToDouble +89306E27
+} 0x46919cccff237e17
+test expr-28.844 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -25487 E24 x -1496968ba07117_01111111111110& E94
+ convertToDouble -25487E24
+} 0xc5d496968ba07117
+test expr-28.845 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +79889 E24 x 10222a1c7e27d3_01111111111110& E96
+ convertToDouble +79889E24
+} 0x45f0222a1c7e27d3
+test expr-28.846 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -97379 E26 x -1eba3685911519_011111111111111110& E102
+ convertToDouble -97379E26
+} 0xc65eba3685911519
+test expr-28.847 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +81002 E-8 x 1a8af0b45d9531_0111111111111111110& E-11
+ convertToDouble +81002E-8
+} 0x3f4a8af0b45d9531
+test expr-28.848 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -43149 E-25 x -146064de6ecbed_011111111111111110& E-68
+ convertToDouble -43149E-25
+} 0xbbb46064de6ecbed
+test expr-28.849 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +40501 E-8 x 1a8af0b45d9531_0111111111111111110& E-12
+ convertToDouble +40501E-8
+} 0x3f3a8af0b45d9531
+test expr-28.850 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -60318 E-10 x -194c988f217e51_011111111111111110& E-18
+ convertToDouble -60318E-10
+} 0xbed94c988f217e51
+test expr-28.851 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -648299 E27 x -1ff6af0bf00100_10000000000000000001& E108
+ convertToDouble -648299E27
+} 0xc6bff6af0bf00101
+test expr-28.852 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +780649 E24 x 13b4d36f9edd18_10000000000000000001& E99
+ convertToDouble +780649E24
+} 0x4623b4d36f9edd19
+test expr-28.853 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +720919 E-14 x 1ef696965cbf04_10000000000000000000000001& E-28
+ convertToDouble +720919E-14
+} 0x3e3ef696965cbf05
+test expr-28.854 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -629703 E-11 x -1a69626d2629d0_1000000000000000000000001& E-18
+ convertToDouble -629703E-11
+} 0xbeda69626d2629d1
+test expr-28.855 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +557913 E24 x 1c2adb44b394bf_01111111111111111110& E98
+ convertToDouble +557913E24
+} 0x461c2adb44b394bf
+test expr-28.856 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -847899 E23 x -111f88fb93dce9_011111111111111111110& E96
+ convertToDouble -847899E23
+} 0xc5f11f88fb93dce9
+test expr-28.857 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +565445 E27 x 1be0eb55770d4d_0111111111111111110& E108
+ convertToDouble +565445E27
+} 0x46bbe0eb55770d4d
+test expr-28.858 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -736531 E24 x -1297b853d64ac7_01111111111111111110& E99
+ convertToDouble -736531E24
+} 0xc62297b853d64ac7
+test expr-28.859 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +680013 E-19 x 13240293e95c3b_01111111111111111111110& E-44
+ convertToDouble +680013E-19
+} 0x3d33240293e95c3b
+test expr-28.860 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -529981 E-10 x -1bc948d999ac11_011111111111111111110& E-15
+ convertToDouble -529981E-10
+} 0xbf0bc948d999ac11
+test expr-28.861 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +382923 E-23 x 11a8c1c10a1fc5_011111111111111111110& E-58
+ convertToDouble +382923E-23
+} 0x3c51a8c1c10a1fc5
+test expr-28.862 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -633614 E-18 x -164b166995a9b7_011111111111111111110& E-41
+ convertToDouble -633614E-18
+} 0xbd664b166995a9b7
+test expr-28.863 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +2165479 E27 x 1ab10c016c34b8_100000000000000000000001& E110
+ convertToDouble +2165479E27
+} 0x46dab10c016c34b9
+test expr-28.864 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -8661916 E27 x -1ab10c016c34b8_100000000000000000000001& E112
+ convertToDouble -8661916E27
+} 0xc6fab10c016c34b9
+test expr-28.865 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +4330958 E27 x 1ab10c016c34b8_100000000000000000000001& E111
+ convertToDouble +4330958E27
+} 0x46eab10c016c34b9
+test expr-28.866 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -9391993 E22 x -12f78bec748c98_1000000000000000000001& E96
+ convertToDouble -9391993E22
+} 0xc5f2f78bec748c99
+test expr-28.867 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -5767352 E-14 x -1ef696965cbf04_10000000000000000000000001& E-25
+ convertToDouble -5767352E-14
+} 0xbe6ef696965cbf05
+test expr-28.868 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +7209190 E-15 x 1ef696965cbf04_10000000000000000000000001& E-28
+ convertToDouble +7209190E-15
+} 0x3e3ef696965cbf05
+test expr-28.869 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -1441838 E-14 x -1ef696965cbf04_10000000000000000000000001& E-27
+ convertToDouble -1441838E-14
+} 0xbe4ef696965cbf05
+test expr-28.870 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +8478990 E22 x 111f88fb93dce9_011111111111111111110& E96
+ convertToDouble +8478990E22
+} 0x45f11f88fb93dce9
+test expr-28.871 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +1473062 E24 x 1297b853d64ac7_01111111111111111110& E100
+ convertToDouble +1473062E24
+} 0x463297b853d64ac7
+test expr-28.872 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +8366487 E-14 x 167567f55b22e1_0111111111111111111111110& E-24
+ convertToDouble +8366487E-14
+} 0x3e767567f55b22e1
+test expr-28.873 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -8399969 E-25 x -1efd8be1b15b43_011111111111111111111110& E-61
+ convertToDouble -8399969E-25
+} 0xbc2efd8be1b15b43
+test expr-28.874 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +9366737 E-12 x 13a4ba87ddc13f_011111111111111111111110& E-17
+ convertToDouble +9366737E-12
+} 0x3ee3a4ba87ddc13f
+test expr-28.875 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -9406141 E-13 x -1f8fd047c84d49_0111111111111111111111110& E-21
+ convertToDouble -9406141E-13
+} 0xbeaf8fd047c84d49
+test expr-28.876 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +65970979 E24 x 1a055dd68f3e3c_1000000000000000000000000001& E105
+ convertToDouble +65970979E24
+} 0x468a055dd68f3e3d
+test expr-28.877 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -65060671 E26 x -140c61c9916cf4_100000000000000000000000001& E112
+ convertToDouble -65060671E26
+} 0xc6f40c61c9916cf5
+test expr-28.878 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +54923002 E27 x 1527d37d8b38ea_10000000000000000000000001& E115
+ convertToDouble +54923002E27
+} 0x472527d37d8b38eb
+test expr-28.879 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -63846927 E25 x -1f7a9d79dad9b4_10000000000000000000000001& E108
+ convertToDouble -63846927E25
+} 0xc6bf7a9d79dad9b5
+test expr-28.880 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +99585767 E-21 x 1c07e928406d2e_100000000000000000000000001& E-44
+ convertToDouble +99585767E-21
+} 0x3d3c07e928406d2f
+test expr-28.881 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +67488159 E25 x 10a31a03822bc9_011111111111111111111111111110& E109
+ convertToDouble +67488159E25
+} 0x46c0a31a03822bc9
+test expr-28.882 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -69005339 E24 x -1b37c234aae77b_011111111111111111111111110& E105
+ convertToDouble -69005339E24
+} 0xc68b37c234aae77b
+test expr-28.883 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +81956786 E27 x 1f919023fcb6fd_0111111111111111111111111110& E115
+ convertToDouble +81956786E27
+} 0x472f919023fcb6fd
+test expr-28.884 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -40978393 E27 x -1f919023fcb6fd_0111111111111111111111111110& E114
+ convertToDouble -40978393E27
+} 0xc71f919023fcb6fd
+test expr-28.885 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +77505754 E-12 x 145152b6f85e09_0111111111111111111111111110& E-14
+ convertToDouble +77505754E-12
+} 0x3f145152b6f85e09
+test expr-28.886 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -38752877 E-12 x -145152b6f85e09_0111111111111111111111111110& E-15
+ convertToDouble -38752877E-12
+} 0xbf045152b6f85e09
+test expr-28.887 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +82772981 E-15 x 16381dae63505f_0111111111111111111111111111110& E-24
+ convertToDouble +82772981E-15
+} 0x3e76381dae63505f
+test expr-28.888 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -95593517 E-25 x -160ad862d8537d_0111111111111111111111111110& E-57
+ convertToDouble -95593517E-25
+} 0xbc660ad862d8537d
+test expr-28.889 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +200036989 E25 x 18a80dedbc575e_10000000000000000000000000001& E110
+ convertToDouble +200036989E25
+} 0x46d8a80dedbc575f
+test expr-28.890 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -772686455 E27 x -129a0c45ceca7a_1000000000000000000000000000001& E119
+ convertToDouble -772686455E27
+} 0xc7629a0c45ceca7b
+test expr-28.891 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +859139907 E23 x 10f18c4dd0ffe2_10000000000000000000000000001& E106
+ convertToDouble +859139907E23
+} 0x4690f18c4dd0ffe3
+test expr-28.892 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -400073978 E25 x -18a80dedbc575e_10000000000000000000000000001& E111
+ convertToDouble -400073978E25
+} 0xc6e8a80dedbc575f
+test expr-28.893 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +569014327 E-14 x 17ddbeac19d3b2_100000000000000000000000000001& E-18
+ convertToDouble +569014327E-14
+} 0x3ed7ddbeac19d3b3
+test expr-28.894 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -794263862 E-15 x -1aa6acb41dfc52_1000000000000000000000000000001& E-21
+ convertToDouble -794263862E-15
+} 0xbeaaa6acb41dfc53
+test expr-28.895 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +397131931 E-15 x 1aa6acb41dfc52_1000000000000000000000000000001& E-22
+ convertToDouble +397131931E-15
+} 0x3e9aa6acb41dfc53
+test expr-28.896 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -380398957 E-16 x -146c29d8331024_100000000000000000000000000001& E-25
+ convertToDouble -380398957E-16
+} 0xbe646c29d8331025
+test expr-28.897 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +567366773 E27 x 1b5155dd5417f9_0111111111111111111111111111110& E118
+ convertToDouble +567366773E27
+} 0x475b5155dd5417f9
+test expr-28.898 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -337440795 E24 x -10a31a03822bc9_011111111111111111111111111110& E108
+ convertToDouble -337440795E24
+} 0xc6b0a31a03822bc9
+test expr-28.899 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +134976318 E25 x 10a31a03822bc9_011111111111111111111111111110& E110
+ convertToDouble +134976318E25
+} 0x46d0a31a03822bc9
+test expr-28.900 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -269952636 E25 x -10a31a03822bc9_011111111111111111111111111110& E111
+ convertToDouble -269952636E25
+} 0xc6e0a31a03822bc9
+test expr-28.901 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +932080597 E-20 x 147f25b4941e5b_0111111111111111111111111111110& E-37
+ convertToDouble +932080597E-20
+} 0x3da47f25b4941e5b
+test expr-28.902 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -331091924 E-15 x -16381dae63505f_0111111111111111111111111111110& E-22
+ convertToDouble -331091924E-15
+} 0xbe96381dae63505f
+test expr-28.903 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -413864905 E-16 x -16381dae63505f_0111111111111111111111111111110& E-25
+ convertToDouble -413864905E-16
+} 0xbe66381dae63505f
+test expr-28.904 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +8539246247 E26 x 148eb7813eaeba_10000000000000000000000000000001& E119
+ convertToDouble +8539246247E26
+} 0x47648eb7813eaebb
+test expr-28.905 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -5859139791 E26 x -1c35f28719d478_10000000000000000000000000000001& E118
+ convertToDouble -5859139791E26
+} 0xc75c35f28719d479
+test expr-28.906 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +6105010149 E24 x 12d000fb2b138a_1000000000000000000000000000000001& E112
+ convertToDouble +6105010149E24
+} 0x46f2d000fb2b138b
+test expr-28.907 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -3090745820 E27 x -129a0c45ceca7a_1000000000000000000000000000001& E121
+ convertToDouble -3090745820E27
+} 0xc7829a0c45ceca7b
+test expr-28.908 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +3470877773 E-20 x 1314d381f2c31e_1000000000000000000000000000000001& E-35
+ convertToDouble +3470877773E-20
+} 0x3dc314d381f2c31f
+test expr-28.909 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -6136309089 E-27 x -1c4c799fab4328_1000000000000000000000000000000001& E-58
+ convertToDouble -6136309089E-27
+} 0xbc5c4c799fab4329
+test expr-28.910 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +8917758713 E-19 x 1ea424bda7d7f4_100000000000000000000000000000001& E-31
+ convertToDouble +8917758713E-19
+} 0x3e0ea424bda7d7f5
+test expr-28.911 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -6941755546 E-20 x -1314d381f2c31e_1000000000000000000000000000000001& E-34
+ convertToDouble -6941755546E-20
+} 0xbdd314d381f2c31f
+test expr-28.912 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +9194900535 E25 x 11b56f9c090dfb_011111111111111111111111111111111110& E116
+ convertToDouble +9194900535E25
+} 0x4731b56f9c090dfb
+test expr-28.913 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -1838980107 E26 x -11b56f9c090dfb_011111111111111111111111111111111110& E117
+ convertToDouble -1838980107E26
+} 0xc741b56f9c090dfb
+test expr-28.914 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +7355920428 E26 x 11b56f9c090dfb_011111111111111111111111111111111110& E119
+ convertToDouble +7355920428E26
+} 0x4761b56f9c090dfb
+test expr-28.915 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -3677960214 E26 x -11b56f9c090dfb_011111111111111111111111111111111110& E118
+ convertToDouble -3677960214E26
+} 0xc751b56f9c090dfb
+test expr-28.916 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +8473634343 E-17 x 16bf0984b232b7_0111111111111111111111111111111110& E-24
+ convertToDouble +8473634343E-17
+} 0x3e76bf0984b232b7
+test expr-28.917 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -8870766274 E-16 x -1dc3ee22137269_0111111111111111111111111111111110& E-21
+ convertToDouble -8870766274E-16
+} 0xbeadc3ee22137269
+test expr-28.918 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +4435383137 E-16 x 1dc3ee22137269_0111111111111111111111111111111110& E-22
+ convertToDouble +4435383137E-16
+} 0x3e9dc3ee22137269
+test expr-28.919 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -9598990129 E-15 x -14216b286031e7_01111111111111111111111111111111110& E-17
+ convertToDouble -9598990129E-15
+} 0xbee4216b286031e7
+test expr-28.920 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +71563496764 E26 x 15890d1ef6a0da_10000000000000000000000000000000000001& E122
+ convertToDouble +71563496764E26
+} 0x4795890d1ef6a0db
+test expr-28.921 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -89454370955 E25 x -15890d1ef6a0da_10000000000000000000000000000000000001& E119
+ convertToDouble -89454370955E25
+} 0xc765890d1ef6a0db
+test expr-28.922 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +17890874191 E26 x 15890d1ef6a0da_10000000000000000000000000000000000001& E120
+ convertToDouble +17890874191E26
+} 0x4775890d1ef6a0db
+test expr-28.923 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -35781748382 E26 x -15890d1ef6a0da_10000000000000000000000000000000000001& E121
+ convertToDouble -35781748382E26
+} 0xc785890d1ef6a0db
+test expr-28.924 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +57973447842 E-19 x 18e63f7cf5313c_1000000000000000000000000000000000000001& E-28
+ convertToDouble +57973447842E-19
+} 0x3e38e63f7cf5313d
+test expr-28.925 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -28986723921 E-19 x -18e63f7cf5313c_1000000000000000000000000000000000000001& E-29
+ convertToDouble -28986723921E-19
+} 0xbe28e63f7cf5313d
+test expr-28.926 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +76822711313 E-19 x 107f5f8b3bf818_100000000000000000000000000000000001& E-27
+ convertToDouble +76822711313E-19
+} 0x3e407f5f8b3bf819
+test expr-28.927 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -97699466874 E-20 x -10c8de34de806e_10000000000000000000000000000000001& E-30
+ convertToDouble -97699466874E-20
+} 0xbe10c8de34de806f
+test expr-28.928 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +67748656762 E27 x 197bf5559b31fd_01111111111111111111111111111111111110& E125
+ convertToDouble +67748656762E27
+} 0x47c97bf5559b31fd
+test expr-28.929 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -19394840991 E24 x -1de1ea791a6e7d_0111111111111111111111111111111111110& E113
+ convertToDouble -19394840991E24
+} 0xc70de1ea791a6e7d
+test expr-28.930 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +38789681982 E24 x 1de1ea791a6e7d_0111111111111111111111111111111111110& E114
+ convertToDouble +38789681982E24
+} 0x471de1ea791a6e7d
+test expr-28.931 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -33874328381 E27 x -197bf5559b31fd_01111111111111111111111111111111111110& E124
+ convertToDouble -33874328381E27
+} 0xc7b97bf5559b31fd
+test expr-28.932 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +54323763886 E-27 x 1f50c5c63e5441_0111111111111111111111111111111111110& E-55
+ convertToDouble +54323763886E-27
+} 0x3c8f50c5c63e5441
+test expr-28.933 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -58987193887 E-20 x -14449185a4c829_011111111111111111111111111111111111110& E-31
+ convertToDouble -58987193887E-20
+} 0xbe04449185a4c829
+test expr-28.934 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +27161881943 E-27 x 1f50c5c63e5441_0111111111111111111111111111111111110& E-56
+ convertToDouble +27161881943E-27
+} 0x3c7f50c5c63e5441
+test expr-28.935 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -93042648033 E-19 x -13fb12dc023fd3_0111111111111111111111111111111111110& E-27
+ convertToDouble -93042648033E-19
+} 0xbe43fb12dc023fd3
+test expr-28.936 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +520831059055 E27 x 187d469cb69dd0_10000000000000000000000000000000000000001& E128
+ convertToDouble +520831059055E27
+} 0x47f87d469cb69dd1
+test expr-28.937 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -768124264394 E25 x -171d6a019edae8_1000000000000000000000000000000000000001& E122
+ convertToDouble -768124264394E25
+} 0xc7971d6a019edae9
+test expr-28.938 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +384062132197 E25 x 171d6a019edae8_1000000000000000000000000000000000000001& E121
+ convertToDouble +384062132197E25
+} 0x47871d6a019edae9
+test expr-28.939 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +765337749889 E-25 x 158ad6f5d0a854_100000000000000000000000000000000000000001& E-44
+ convertToDouble +765337749889E-25
+} 0x3d358ad6f5d0a855
+test expr-28.940 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +794368912771 E25 x 17e79872f2f7ef_01111111111111111111111111111111111111110& E122
+ convertToDouble +794368912771E25
+} 0x4797e79872f2f7ef
+test expr-28.941 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -994162090146 E23 x -132598f85e658b_011111111111111111111111111111111111110& E116
+ convertToDouble -994162090146E23
+} 0xc7332598f85e658b
+test expr-28.942 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +781652779431 E26 x 1d670adf52038f_01111111111111111111111111111111111110& E125
+ convertToDouble +781652779431E26
+} 0x47cd670adf52038f
+test expr-28.943 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +910077190046 E-26 x 147e3ce1871d79_01111111111111111111111111111111111111110& E-47
+ convertToDouble +910077190046E-26
+} 0x3d047e3ce1871d79
+test expr-28.944 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -455038595023 E-26 x -147e3ce1871d79_01111111111111111111111111111111111111110& E-48
+ convertToDouble -455038595023E-26
+} 0xbcf47e3ce1871d79
+test expr-28.945 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +471897551096 E-20 x 14449185a4c829_011111111111111111111111111111111111110& E-28
+ convertToDouble +471897551096E-20
+} 0x3e34449185a4c829
+test expr-28.946 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -906698409911 E-21 x -1f27674f7d5745_0111111111111111111111111111111111111110& E-31
+ convertToDouble -906698409911E-21
+} 0xbe0f27674f7d5745
+test expr-28.947 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +8854128003935 E25 x 10a71b8948faac_100000000000000000000000000000000000000001& E126
+ convertToDouble +8854128003935E25
+} 0x47d0a71b8948faad
+test expr-28.948 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -8146122716299 E27 x -17f0762ac05654_1000000000000000000000000000000000000000001& E132
+ convertToDouble -8146122716299E27
+} 0xc837f0762ac05655
+test expr-28.949 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +7083302403148 E26 x 10a71b8948faac_100000000000000000000000000000000000000001& E129
+ convertToDouble +7083302403148E26
+} 0x4800a71b8948faad
+test expr-28.950 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -3541651201574 E26 x -10a71b8948faac_100000000000000000000000000000000000000001& E128
+ convertToDouble -3541651201574E26
+} 0xc7f0a71b8948faad
+test expr-28.951 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +8394920649291 E-25 x 1d8978e8c1cc78_100000000000000000000000000000000000000000001& E-41
+ convertToDouble +8394920649291E-25
+} 0x3d6d8978e8c1cc79
+test expr-28.952 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -7657975756753 E-22 x -1a5006d695fef0_1000000000000000000000000000000000000000000001& E-31
+ convertToDouble -7657975756753E-22
+} 0xbe0a5006d695fef1
+test expr-28.953 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +5473834002228 E-20 x 1d632e1f745624_100000000000000000000000000000000000000000001& E-25
+ convertToDouble +5473834002228E-20
+} 0x3e6d632e1f745625
+test expr-28.954 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -6842292502785 E-21 x -1d632e1f745624_100000000000000000000000000000000000000000001& E-28
+ convertToDouble -6842292502785E-21
+} 0xbe3d632e1f745625
+test expr-28.955 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -2109568884597 E25 x -1fbdc386609b13_011111111111111111111111111111111111111110& E123
+ convertToDouble -2109568884597E25
+} 0xc7afbdc386609b13
+test expr-28.956 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +8438275538388 E25 x 1fbdc386609b13_011111111111111111111111111111111111111110& E125
+ convertToDouble +8438275538388E25
+} 0x47cfbdc386609b13
+test expr-28.957 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -4219137769194 E25 x -1fbdc386609b13_011111111111111111111111111111111111111110& E124
+ convertToDouble -4219137769194E25
+} 0xc7bfbdc386609b13
+test expr-28.958 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +3200141789841 E-25 x 1684dcea3829f7_0111111111111111111111111111111111111111110& E-42
+ convertToDouble +3200141789841E-25
+} 0x3d5684dcea3829f7
+test expr-28.959 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -8655689322607 E-22 x -1dbd9ff5dc8991_011111111111111111111111111111111111111110& E-31
+ convertToDouble -8655689322607E-22
+} 0xbe0dbd9ff5dc8991
+test expr-28.960 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +6400283579682 E-25 x 1684dcea3829f7_0111111111111111111111111111111111111111110& E-41
+ convertToDouble +6400283579682E-25
+} 0x3d6684dcea3829f7
+test expr-28.961 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -8837719634493 E-21 x -12fa9676d2585b_011111111111111111111111111111111111111110& E-27
+ convertToDouble -8837719634493E-21
+} 0xbe42fa9676d2585b
+test expr-28.962 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +19428217075297 E24 x 1d3b7a1d154aba_10000000000000000000000000000000000000000000001& E123
+ convertToDouble +19428217075297E24
+} 0x47ad3b7a1d154abb
+test expr-28.963 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -38856434150594 E24 x -1d3b7a1d154aba_10000000000000000000000000000000000000000000001& E124
+ convertToDouble -38856434150594E24
+} 0xc7bd3b7a1d154abb
+test expr-28.964 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +77712868301188 E24 x 1d3b7a1d154aba_10000000000000000000000000000000000000000000001& E125
+ convertToDouble +77712868301188E24
+} 0x47cd3b7a1d154abb
+test expr-28.965 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -77192037242133 E27 x -1c5b1ab32d5dbe_1000000000000000000000000000000000000000000000001& E135
+ convertToDouble -77192037242133E27
+} 0xc86c5b1ab32d5dbf
+test expr-28.966 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +76579757567530 E-23 x 1a5006d695fef0_1000000000000000000000000000000000000000000001& E-31
+ convertToDouble +76579757567530E-23
+} 0x3e0a5006d695fef1
+test expr-28.967 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +15315951513506 E-22 x 1a5006d695fef0_1000000000000000000000000000000000000000000001& E-30
+ convertToDouble +15315951513506E-22
+} 0x3e1a5006d695fef1
+test expr-28.968 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -38289878783765 E-23 x -1a5006d695fef0_1000000000000000000000000000000000000000000001& E-32
+ convertToDouble -38289878783765E-23
+} 0xbdfa5006d695fef1
+test expr-28.969 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +49378033925202 E25 x 1737aa2567167b_0111111111111111111111111111111111111111111110& E128
+ convertToDouble +49378033925202E25
+} 0x47f737aa2567167b
+test expr-28.970 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -50940527102367 E24 x -132964f2944b05_0111111111111111111111111111111111111111111111110& E125
+ convertToDouble -50940527102367E24
+} 0xc7c32964f2944b05
+test expr-28.971 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +98756067850404 E25 x 1737aa2567167b_0111111111111111111111111111111111111111111110& E129
+ convertToDouble +98756067850404E25
+} 0x480737aa2567167b
+test expr-28.972 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -99589397544892 E26 x -1d4446075c4933_0111111111111111111111111111111111111111111110& E132
+ convertToDouble -99589397544892E26
+} 0xc83d4446075c4933
+test expr-28.973 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -56908598265713 E-25 x -190756ab1ed6b3_011111111111111111111111111111111111111111111110& E-38
+ convertToDouble -56908598265713E-25
+} 0xbd990756ab1ed6b3
+test expr-28.974 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +97470695699657 E-22 x 14ee821710e655_01111111111111111111111111111111111111111111110& E-27
+ convertToDouble +97470695699657E-22
+} 0x3e44ee821710e655
+test expr-28.975 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -35851901247343 E-25 x -1f8921657e1581_0111111111111111111111111111111111111111111110& E-39
+ convertToDouble -35851901247343E-25
+} 0xbd8f8921657e1581
+test expr-28.976 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +154384074484266 E27 x 1c5b1ab32d5dbe_1000000000000000000000000000000000000000000000001& E136
+ convertToDouble +154384074484266E27
+} 0x487c5b1ab32d5dbf
+test expr-28.977 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -308768148968532 E27 x -1c5b1ab32d5dbe_1000000000000000000000000000000000000000000000001& E137
+ convertToDouble -308768148968532E27
+} 0xc88c5b1ab32d5dbf
+test expr-28.978 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +910990389005985 E23 x 112242592ae54a_100000000000000000000000000000000000000000000001& E126
+ convertToDouble +910990389005985E23
+} 0x47d12242592ae54b
+test expr-28.979 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +271742424169201 E-27 x 131f46bcf7b452_10000000000000000000000000000000000000000000000001& E-42
+ convertToDouble +271742424169201E-27
+} 0x3d531f46bcf7b453
+test expr-28.980 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -543484848338402 E-27 x -131f46bcf7b452_10000000000000000000000000000000000000000000000001& E-41
+ convertToDouble -543484848338402E-27
+} 0xbd631f46bcf7b453
+test expr-28.981 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +162192083357563 E-26 x 1c887b68658760_1000000000000000000000000000000000000000000000001& E-40
+ convertToDouble +162192083357563E-26
+} 0x3d7c887b68658761
+test expr-28.982 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -869254552770081 E-23 x -12aac70665485e_1000000000000000000000000000000000000000000000000001& E-27
+ convertToDouble -869254552770081E-23
+} 0xbe42aac70665485f
+test expr-28.983 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +664831007626046 E24 x 1f429cb67eb075_011111111111111111111111111111111111111111111111110& E128
+ convertToDouble +664831007626046E24
+} 0x47ff429cb67eb075
+test expr-28.984 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -332415503813023 E24 x -1f429cb67eb075_011111111111111111111111111111111111111111111111110& E127
+ convertToDouble -332415503813023E24
+} 0xc7ef429cb67eb075
+test expr-28.985 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +943701829041427 E24 x 162fb2e38ee461_01111111111111111111111111111111111111111111111110& E129
+ convertToDouble +943701829041427E24
+} 0x48062fb2e38ee461
+test expr-28.986 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -101881054204734 E24 x -132964f2944b05_0111111111111111111111111111111111111111111111110& E126
+ convertToDouble -101881054204734E24
+} 0xc7d32964f2944b05
+test expr-28.987 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +828027839666967 E-27 x 1d2236349da3cd_011111111111111111111111111111111111111111111111110& E-41
+ convertToDouble +828027839666967E-27
+} 0x3d6d2236349da3cd
+test expr-28.988 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -280276135608777 E-27 x -13b901892fd0bf_0111111111111111111111111111111111111111111111110& E-42
+ convertToDouble -280276135608777E-27
+} 0xbd53b901892fd0bf
+test expr-28.989 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +212839188833879 E-21 x 1c91194dc2d40b_0111111111111111111111111111111111111111111111110& E-23
+ convertToDouble +212839188833879E-21
+} 0x3e8c91194dc2d40b
+test expr-28.990 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -113817196531426 E-25 x -190756ab1ed6b3_011111111111111111111111111111111111111111111110& E-37
+ convertToDouble -113817196531426E-25
+} 0xbda90756ab1ed6b3
+test expr-28.991 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +9711553197796883 E27 x 1bdeec25c0f03e_10000000000000000000000000000000000000000000000000001& E142
+ convertToDouble +9711553197796883E27
+} 0x48dbdeec25c0f03f
+test expr-28.992 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -2739849386524269 E26 x -19295ade212370_1000000000000000000000000000000000000000000000000001& E137
+ convertToDouble -2739849386524269E26
+} 0xc889295ade212371
+test expr-28.993 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +5479698773048538 E26 x 19295ade212370_1000000000000000000000000000000000000000000000000001& E138
+ convertToDouble +5479698773048538E26
+} 0x4899295ade212371
+test expr-28.994 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +6124568318523113 E-25 x 150b3a2e0aff14_1000000000000000000000000000000000000000000000000000001& E-31
+ convertToDouble +6124568318523113E-25
+} 0x3e050b3a2e0aff15
+test expr-28.995 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -1139777988171071 E-24 x -1394cbee428ea4_10000000000000000000000000000000000000000000000000001& E-30
+ convertToDouble -1139777988171071E-24
+} 0xbe1394cbee428ea5
+test expr-28.996 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +6322612303128019 E-27 x 1bcea0ec21e250_1000000000000000000000000000000000000000000000000000001& E-38
+ convertToDouble +6322612303128019E-27
+} 0x3d9bcea0ec21e251
+test expr-28.997 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -2955864564844617 E-25 x -1450030e26c6dc_10000000000000000000000000000000000000000000000000001& E-32
+ convertToDouble -2955864564844617E-25
+} 0xbdf450030e26c6dd
+test expr-28.998 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -9994029144998961 E25 x -125b2b7fed4a61_0111111111111111111111111111111111111111111111111110& E136
+ convertToDouble -9994029144998961E25
+} 0xc8725b2b7fed4a61
+test expr-28.999 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -2971238324022087 E27 x -110dd7a301db67_0111111111111111111111111111111111111111111111111110& E141
+ convertToDouble -2971238324022087E27
+} 0xc8c10dd7a301db67
+test expr-28.1000 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -1656055679333934 E-27 x -1d2236349da3cd_011111111111111111111111111111111111111111111111110& E-40
+ convertToDouble -1656055679333934E-27
+} 0xbd7d2236349da3cd
+test expr-28.1001 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -1445488709150234 E-26 x -1fc960c59526c7_0111111111111111111111111111111111111111111111110& E-37
+ convertToDouble -1445488709150234E-26
+} 0xbdafc960c59526c7
+test expr-28.1002 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +55824717499885172 E27 x 1406b0cd17fd56_1000000000000000000000000000000000000000000000000000000001& E145
+ convertToDouble +55824717499885172E27
+} 0x490406b0cd17fd57
+test expr-28.1003 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -69780896874856465 E26 x -1406b0cd17fd56_1000000000000000000000000000000000000000000000000000000001& E142
+ convertToDouble -69780896874856465E26
+} 0xc8d406b0cd17fd57
+test expr-28.1004 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +84161538867545199 E25 x 13529217bdce6c_10000000000000000000000000000000000000000000000000000000001& E139
+ convertToDouble +84161538867545199E25
+} 0x48a3529217bdce6d
+test expr-28.1005 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -27912358749942586 E27 x -1406b0cd17fd56_1000000000000000000000000000000000000000000000000000000001& E144
+ convertToDouble -27912358749942586E27
+} 0xc8f406b0cd17fd57
+test expr-28.1006 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +24711112462926331 E-25 x 153a07f6040d22_100000000000000000000000000000000000000000000000000000001& E-29
+ convertToDouble +24711112462926331E-25
+} 0x3e253a07f6040d23
+test expr-28.1007 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -12645224606256038 E-27 x -1bcea0ec21e250_1000000000000000000000000000000000000000000000000000001& E-37
+ convertToDouble -12645224606256038E-27
+} 0xbdabcea0ec21e251
+test expr-28.1008 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -12249136637046226 E-25 x -150b3a2e0aff14_1000000000000000000000000000000000000000000000000000001& E-30
+ convertToDouble -12249136637046226E-25
+} 0xbe150b3a2e0aff15
+test expr-28.1009 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +74874448287465757 E27 x 1adc21d1d50b09_01111111111111111111111111111111111111111111111111111110& E145
+ convertToDouble +74874448287465757E27
+} 0x490adc21d1d50b09
+test expr-28.1010 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -35642836832753303 E24 x -1a2fac2b421f53_0111111111111111111111111111111111111111111111111111110& E134
+ convertToDouble -35642836832753303E24
+} 0xc85a2fac2b421f53
+test expr-28.1011 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -71285673665506606 E24 x -1a2fac2b421f53_0111111111111111111111111111111111111111111111111111110& E135
+ convertToDouble -71285673665506606E24
+} 0xc86a2fac2b421f53
+test expr-28.1012 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +43723334984997307 E-26 x 1e0be3f392c549_01111111111111111111111111111111111111111111111111111110& E-32
+ convertToDouble +43723334984997307E-26
+} 0x3dfe0be3f392c549
+test expr-28.1013 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN +10182419849537963 E-24 x 15ddd831ebbe53_011111111111111111111111111111111111111111111111111110& E-27
+ convertToDouble +10182419849537963E-24
+} 0x3e45ddd831ebbe53
+test expr-28.1014 {input floating-point conversion} {ieeeFloatingPoint} {
+ # Ad2b dieee UN -93501703572661982 E-26 x -10103f97ea6e13_0111111111111111111111111111111111111111111111111110& E-30
+ convertToDouble -93501703572661982E-26
+} 0xbe10103f97ea6e13
+
+test expr-29.1 {smallest representible number} {ieeeFloatingPoint} {
+ list [catch {convertToDouble 4.9406564584124654e-324} result] \
+ $result \
+ [catch {convertToDouble 2.4703282292062327e-324} result] \
+ $result \
+ [catch {convertToDouble 2.47032822920623e-324} result] \
+ $result
+} {0 0x0000000000000001 0 0x0000000000000001 0 0x0000000000000000}
+test expr-29.2 {smallest representible number} {ieeeFloatingPoint} {
+ list [catch {convertToDouble -4.9406564584124654e-324} result] \
+ $result \
+ [catch {convertToDouble -2.4703282292062327e-324} result] \
+ $result \
+ [catch {convertToDouble -2.47032822920623e-324} result] \
+ $result
+} {0 0x8000000000000001 0 0x8000000000000001 0 0x8000000000000000}
+test expr-29.3 {silent underflow on input conversion} {ieeeFloatingPoint} {
+ set v ?
+ list [scan 2.47032822920623e-324 %g v] $v
+} {1 0.0}
+test expr-29.4 {silent underflow on input conversion} {ieeeFloatingPoint} {
+ set v ?
+ list [scan -2.47032822920623e-324 %g v] $v
+} {1 -0.0}
+
+test expr-30.1 {largest representible number} {ieeeFloatingPoint} {
+ list [catch {convertToDouble 1.7976931348623155e+308} result] \
+ $result \
+ [catch {convertToDouble 1.7976931348623157e+308} result] \
+ $result \
+ [catch {convertToDouble 1.7976931348623159e+308} result] \
+ $result
+} {0 0x7feffffffffffffe 0 0x7fefffffffffffff 0 0x7ff0000000000000}
+test expr-30.2 {largest representible number} {ieeeFloatingPoint} {
+ list [catch {convertToDouble -1.7976931348623155e+308} result] \
+ $result \
+ [catch {convertToDouble -1.7976931348623157e+308} result] \
+ $result \
+ [catch {convertToDouble -1.7976931348623159e+308} result] \
+ $result
+} {0 0xffeffffffffffffe 0 0xffefffffffffffff 0 0xfff0000000000000}
+test expr-30.3 {silent overflow on input conversion} {ieeeFloatingPoint} {
+ set v ?
+ list [scan 1.7976931348623159e+308 %f v] $v
+} {1 Inf}
+test expr-30.4 {silent overflow on input conversion} {ieeeFloatingPoint} {
+ set v ?
+ list [scan -1.7976931348623159e+308 %f v] $v
+} {1 -Inf}
+
+# bool() tests (TIP #182)
+set i 0
+foreach s {yes true on} {
+ test expr-31.$i.0 {boolean conversion} {expr bool($s)} 1
+ test expr-31.$i.1 {boolean conversion} {expr bool(!$s)} 0
+ test expr-31.$i.2 {boolean conversion} {expr bool("$s")} 1
+ test expr-31.$i.3 {boolean conversion} {expr bool(!"$s")} 0
+ set j 1
+ while {$j < [string length $s]-1} {
+ test expr-31.$i.4.$j {boolean conversion} {
+ expr bool([string range $s 0 $j])
+ } 1
+ test expr-31.$i.5.$j {boolean conversion} {
+ expr bool("[string range $s 0 $j]")
+ } 1
+ incr j
+ }
+ incr i
+}
+test expr-31.0.4.0 {boolean conversion} {expr bool(y)} 1
+test expr-31.0.5.0 {boolean conversion} {expr bool("y")} 1
+test expr-31.1.4.0 {boolean conversion} {expr bool(t)} 1
+test expr-31.1.5.0 {boolean conversion} {expr bool("t")} 1
+test expr-31.2.4.0 {boolean conversion} -body {
+ expr bool(o)
+} -returnCodes error -match glob -result *
+test expr-31.2.5.0 {boolean conversion} -body {
+ expr bool("o")
+} -returnCodes error -match glob -result *
+foreach s {no false off} {
+ test expr-31.$i.0 {boolean conversion} {expr bool($s)} 0
+ test expr-31.$i.1 {boolean conversion} {expr bool(!$s)} 1
+ test expr-31.$i.2 {boolean conversion} {expr bool("$s")} 0
+ test expr-31.$i.3 {boolean conversion} {expr bool(!"$s")} 1
+ set j 1
+ while {$j < [string length $s]-1} {
+ test expr-31.$i.4.$j {boolean conversion} {
+ expr bool([string range $s 0 $j])
+ } 0
+ test expr-31.$i.5.$j {boolean conversion} {
+ expr bool("[string range $s 0 $j]")
+ } 0
+ incr j
+ }
+ incr i
+}
+test expr-31.3.4.0 {boolean conversion} {expr bool(n)} 0
+test expr-31.3.5.0 {boolean conversion} {expr bool("n")} 0
+test expr-31.4.4.0 {boolean conversion} {expr bool(f)} 0
+test expr-31.4.5.0 {boolean conversion} {expr bool("f")} 0
+test expr-31.6 {boolean conversion} {expr bool(-1 + 1)} 0
+test expr-31.7 {boolean conversion} {expr bool(0 + 1)} 1
+test expr-31.8 {boolean conversion} {expr bool(0.0)} 0
+test expr-31.9 {boolean conversion} {expr bool(0x0)} 0
+test expr-31.10 {boolean conversion} {expr bool(wide(0))} 0
+test expr-31.11 {boolean conversion} {expr bool(5.0)} 1
+test expr-31.12 {boolean conversion} {expr bool(5)} 1
+test expr-31.13 {boolean conversion} {expr bool(0x5)} 1
+test expr-31.14 {boolean conversion} {expr bool(wide(5))} 1
+test expr-31.15 {boolean conversion} -body {
+ expr bool("fred")
+} -returnCodes error -match glob -result *
+
+test expr-32.1 {expr mod basics} {
+ set mod_nums [list \
+ {-3 1} {-3 2} {-3 3} {-3 4} {-3 5} \
+ {-3 -1} {-3 -2} {-3 -3} {-3 -4} {-3 -5} \
+ {-2 1} {-2 2} {-2 3} {-2 4} {-2 5} \
+ {-2 -1} {-2 -2} {-2 -3} {-2 -4} {-2 -5} \
+ {-1 1} {-1 2} {-1 3} {-1 4} {-1 5} \
+ {-1 -1} {-1 -2} {-1 -3} {-1 -4} {-1 -5} \
+ {0 -100} {0 -1} {0 1} {0 100} \
+ {1 1} {1 2} {1 3} {1 4} {1 5} \
+ {1 -1} {1 -2} {1 -3} {1 -4} {1 -5} \
+ {2 1} {2 2} {2 3} {2 4} {2 5} \
+ {2 -1} {2 -2} {2 -3} {2 -4} {2 -5} \
+ {3 1} {3 2} {3 3} {3 4} {3 5} \
+ {3 -1} {3 -2} {3 -3} {3 -4} {3 -5} \
+ ]
+ set results [list]
+ foreach pair $mod_nums {
+ set dividend [lindex $pair 0]
+ set divisor [lindex $pair 1]
+ lappend results [expr {$dividend % $divisor}]
+ }
+ set results
+} [list \
+ 0 1 0 1 2 \
+ 0 -1 0 -3 -3 \
+ 0 0 1 2 3 \
+ 0 0 -2 -2 -2 \
+ 0 1 2 3 4 \
+ 0 -1 -1 -1 -1 \
+ 0 0 0 0 \
+ 0 1 1 1 1 \
+ 0 -1 -2 -3 -4 \
+ 0 0 2 2 2 \
+ 0 0 -1 -2 -3 \
+ 0 1 0 3 3 \
+ 0 -1 0 -1 -2 \
+ ]
+
+test expr-32.2 {expr div basics} {
+ set mod_nums [list \
+ {-3 1} {-3 2} {-3 3} {-3 4} {-3 5} \
+ {-3 -1} {-3 -2} {-3 -3} {-3 -4} {-3 -5} \
+ {-2 1} {-2 2} {-2 3} {-2 4} {-2 5} \
+ {-2 -1} {-2 -2} {-2 -3} {-2 -4} {-2 -5} \
+ {-1 1} {-1 2} {-1 3} {-1 4} {-1 5} \
+ {-1 -1} {-1 -2} {-1 -3} {-1 -4} {-1 -5} \
+ {0 -100} {0 -1} {0 1} {0 100} \
+ {1 1} {1 2} {1 3} {1 4} {1 5} \
+ {1 -1} {1 -2} {1 -3} {1 -4} {1 -5} \
+ {2 1} {2 2} {2 3} {2 4} {2 5} \
+ {2 -1} {2 -2} {2 -3} {2 -4} {2 -5} \
+ {3 1} {3 2} {3 3} {3 4} {3 5} \
+ {3 -1} {3 -2} {3 -3} {3 -4} {3 -5} \
+ ]
+ set results [list]
+ foreach pair $mod_nums {
+ set dividend [lindex $pair 0]
+ set divisor [lindex $pair 1]
+ lappend results [expr {$dividend / $divisor}]
+ }
+ set results
+} [list \
+ -3 -2 -1 -1 -1 \
+ 3 1 1 0 0 \
+ -2 -1 -1 -1 -1 \
+ 2 1 0 0 0 \
+ -1 -1 -1 -1 -1 \
+ 1 0 0 0 0 \
+ 0 0 0 0 \
+ 1 0 0 0 0 \
+ -1 -1 -1 -1 -1 \
+ 2 1 0 0 0 \
+ -2 -1 -1 -1 -1 \
+ 3 1 1 0 0 \
+ -3 -2 -1 -1 -1 \
+ ]
+
+test expr-32.3 {Bug 1585704} {
+ expr 1%(1<<63)
+} 1
+test expr-32.4 {Bug 1585704} {
+ expr -1%(1<<63)
+} [expr (1<<63)-1]
+test expr-32.5 {Bug 1585704} {
+ expr (1<<32)%(1<<63)
+} [expr 1<<32]
+test expr-32.6 {Bug 1585704} {
+ expr -(1<<32)%(1<<63)
+} [expr (1<<63)-(1<<32)]
+
+test expr-33.1 {parse largest long value} longIs32bit {
+ set max_long_str 2147483647
+ set max_long_hex "0x7FFFFFFF "
+
+ # Convert to integer (long, not wide) internal rep
+ set max_long 2147483647
+ string is integer $max_long
+
+ list \
+ [expr {" $max_long_str "}] \
+ [expr {$max_long_str + 0}] \
+ [expr {$max_long + 0}] \
+ [expr {2147483647 + 0}] \
+ [expr {$max_long == $max_long_hex}] \
+ [expr {int(2147483647 + 1) < 0}] \
+
+} {2147483647 2147483647 2147483647 2147483647 1 1}
+test expr-33.2 {parse smallest long value} longIs32bit {
+ set min_long_str -2147483648
+ set min_long_hex "-0x80000000 "
+
+ set min_long -2147483648
+ # This will convert to integer (not wide) internal rep
+ string is integer $min_long
+
+ # Note: If the final expression returns 0 then the
+ # expression literal is being promoted to a wide type
+ # when it should be parsed as a long type.
+ list \
+ [expr {" $min_long_str "}] \
+ [expr {$min_long_str + 0}] \
+ [expr {$min_long + 0}] \
+ [expr {-2147483648 + 0}] \
+ [expr {$min_long == $min_long_hex}] \
+ [expr {int(-2147483648 - 1) == 0x7FFFFFFF}] \
+
+} {-2147483648 -2147483648 -2147483648 -2147483648 1 1}
+test expr-33.3 {parse largest wide value} wideIs64bit {
+ set max_wide_str 9223372036854775807
+ set max_wide_hex "0x7FFFFFFFFFFFFFFF "
+
+ # Convert to wide integer
+ set max_wide 9223372036854775807
+ string is integer $max_wide
+
+ list \
+ [expr {" $max_wide_str "}] \
+ [expr {$max_wide_str + 0}] \
+ [expr {$max_wide + 0}] \
+ [expr {9223372036854775807 + 0}] \
+ [expr {$max_wide == $max_wide_hex}] \
+ [expr {wide(9223372036854775807 + 1) < 0}] \
+
+} {9223372036854775807 9223372036854775807 9223372036854775807 9223372036854775807 1 1}
+test expr-33.4 {parse smallest wide value} wideIs64bit {
+ set min_wide_str -9223372036854775808
+ set min_wide_hex "-0x8000000000000000 "
+
+ set min_wide -9223372036854775808
+ # Convert to wide integer
+ string is integer $min_wide
+
+ # Note: If the final expression returns 0 then the
+ # wide integer is not being parsed correctly with
+ # the leading - sign.
+ list \
+ [expr {" $min_wide_str "}] \
+ [expr {$min_wide_str + 0}] \
+ [expr {$min_wide + 0}] \
+ [expr {-9223372036854775808 + 0}] \
+ [expr {$min_wide == $min_wide_hex}] \
+ [expr {wide(-9223372036854775808 - 1) == 0x7FFFFFFFFFFFFFFF}] \
+
+} {-9223372036854775808 -9223372036854775808 -9223372036854775808 -9223372036854775808 1 1}
+
+set min -2147483648
+set max 2147483647
+
+test expr-34.1 {expr edge cases} {
+ expr {$min / $min}
+} {1}
+test expr-34.2 {expr edge cases} {
+ expr {$min % $min}
+} {0}
+test expr-34.3 {expr edge cases} {
+ expr {$min / ($min + 1)}
+} {1}
+test expr-34.4 {expr edge cases} {
+ expr {$min % ($min + 1)}
+} {-1}
+test expr-34.5 {expr edge cases} {
+ expr {$min / ($min + 2)}
+} {1}
+test expr-34.6 {expr edge cases} {
+ expr {$min % ($min + 2)}
+} {-2}
+test expr-34.7 {expr edge cases} {
+ expr {$min / ($min + 3)}
+} {1}
+test expr-34.8 {expr edge cases} {
+ expr {$min % ($min + 3)}
+} {-3}
+test expr-34.9 {expr edge cases} {
+ expr {$min / -3}
+} {715827882}
+test expr-34.10 {expr edge cases} {
+ expr {$min % -3}
+} {-2}
+test expr-34.11 {expr edge cases} {
+ expr {$min / -2}
+} {1073741824}
+test expr-34.12 {expr edge cases} {
+ expr {$min % -2}
+} {0}
+test expr-34.13 {expr edge cases} longIs32bit {
+ expr {int($min / -1)}
+} {-2147483648}
+test expr-34.14 {expr edge cases} {
+ expr {$min % -1}
+} {0}
+test expr-34.15 {expr edge cases} longIs32bit {
+ expr {int($min * -1)}
+} $min
+test expr-34.16 {expr edge cases} longIs32bit {
+ expr {int(-$min)}
+} $min
+test expr-34.17 {expr edge cases} {
+ expr {$min / 1}
+} $min
+test expr-34.18 {expr edge cases} {
+ expr {$min % 1}
+} {0}
+test expr-34.19 {expr edge cases} {
+ expr {$min / 2}
+} {-1073741824}
+test expr-34.20 {expr edge cases} {
+ expr {$min % 2}
+} {0}
+test expr-34.21 {expr edge cases} {
+ expr {$min / 3}
+} {-715827883}
+test expr-34.22 {expr edge cases} {
+ expr {$min % 3}
+} {1}
+test expr-34.23 {expr edge cases} {
+ expr {$min / ($max - 3)}
+} {-2}
+test expr-34.24 {expr edge cases} {
+ expr {$min % ($max - 3)}
+} {2147483640}
+test expr-34.25 {expr edge cases} {
+ expr {$min / ($max - 2)}
+} {-2}
+test expr-34.26 {expr edge cases} {
+ expr {$min % ($max - 2)}
+} {2147483642}
+test expr-34.27 {expr edge cases} {
+ expr {$min / ($max - 1)}
+} {-2}
+test expr-34.28 {expr edge cases} {
+ expr {$min % ($max - 1)}
+} {2147483644}
+test expr-34.29 {expr edge cases} {
+ expr {$min / $max}
+} {-2}
+test expr-34.30 {expr edge cases} {
+ expr {$min % $max}
+} {2147483646}
+test expr-34.31 {expr edge cases} {
+ expr {$max / $max}
+} {1}
+test expr-34.32 {expr edge cases} {
+ expr {$max % $max}
+} {0}
+test expr-34.33 {expr edge cases} {
+ expr {$max / ($max - 1)}
+} {1}
+test expr-34.34 {expr edge cases} {
+ expr {$max % ($max - 1)}
+} {1}
+test expr-34.35 {expr edge cases} {
+ expr {$max / ($max - 2)}
+} {1}
+test expr-34.36 {expr edge cases} {
+ expr {$max % ($max - 2)}
+} {2}
+test expr-34.37 {expr edge cases} {
+ expr {$max / ($max - 3)}
+} {1}
+test expr-34.38 {expr edge cases} {
+ expr {$max % ($max - 3)}
+} {3}
+test expr-34.39 {expr edge cases} {
+ expr {$max / 3}
+} {715827882}
+test expr-34.40 {expr edge cases} {
+ expr {$max % 3}
+} {1}
+test expr-34.41 {expr edge cases} {
+ expr {$max / 2}
+} {1073741823}
+test expr-34.42 {expr edge cases} {
+ expr {$max % 2}
+} {1}
+test expr-34.43 {expr edge cases} {
+ expr {$max / 1}
+} $max
+test expr-34.44 {expr edge cases} {
+ expr {$max % 1}
+} {0}
+test expr-34.45 {expr edge cases} {
+ expr {$max / -1}
+} "-$max"
+test expr-34.46 {expr edge cases} {
+ expr {$max % -1}
+} {0}
+test expr-34.47 {expr edge cases} {
+ expr {$max / -2}
+} {-1073741824}
+test expr-34.48 {expr edge cases} {
+ expr {$max % -2}
+} {-1}
+test expr-34.49 {expr edge cases} {
+ expr {$max / -3}
+} {-715827883}
+test expr-34.50 {expr edge cases} {
+ expr {$max % -3}
+} {-2}
+test expr-34.51 {expr edge cases} {
+ expr {$max / ($min + 3)}
+} {-2}
+test expr-34.52 {expr edge cases} {
+ expr {$max % ($min + 3)}
+} {-2147483643}
+test expr-34.53 {expr edge cases} {
+ expr {$max / ($min + 2)}
+} {-2}
+test expr-34.54 {expr edge cases} {
+ expr {$max % ($min + 2)}
+} {-2147483645}
+test expr-34.55 {expr edge cases} {
+ expr {$max / ($min + 1)}
+} {-1}
+test expr-34.56 {expr edge cases} {
+ expr {$max % ($min + 1)}
+} {0}
+test expr-34.57 {expr edge cases} {
+ expr {$max / $min}
+} {-1}
+test expr-34.58 {expr edge cases} {
+ expr {$max % $min}
+} {-1}
+test expr-34.59 {expr edge cases} {
+ expr {($min + 1) / ($max - 1)}
+} {-2}
+test expr-34.60 {expr edge cases} {
+ expr {($min + 1) % ($max - 1)}
+} {2147483645}
+test expr-34.61 {expr edge cases} {
+ expr {($max - 1) / ($min + 1)}
+} {-1}
+test expr-34.62 {expr edge cases} {
+ expr {($max - 1) % ($min + 1)}
+} {-1}
+test expr-34.63 {expr edge cases} {
+ expr {($max - 1) / $min}
+} {-1}
+test expr-34.64 {expr edge cases} {
+ expr {($max - 1) % $min}
+} {-2}
+test expr-34.65 {expr edge cases} {
+ expr {($max - 2) / $min}
+} {-1}
+test expr-34.66 {expr edge cases} {
+ expr {($max - 2) % $min}
+} {-3}
+test expr-34.67 {expr edge cases} {
+ expr {($max - 3) / $min}
+} {-1}
+test expr-34.68 {expr edge cases} {
+ expr {($max - 3) % $min}
+} {-4}
+test expr-34.69 {expr edge cases} {
+ expr {-3 / $min}
+} {0}
+test expr-34.70 {expr edge cases} {
+ expr {-3 % $min}
+} {-3}
+test expr-34.71 {expr edge cases} {
+ expr {-2 / $min}
+} {0}
+test expr-34.72 {expr edge cases} {
+ expr {-2 % $min}
+} {-2}
+test expr-34.73 {expr edge cases} {
+ expr {-1 / $min}
+} {0}
+test expr-34.74 {expr edge cases} {
+ expr {-1 % $min}
+} {-1}
+test expr-34.75 {expr edge cases} {
+ expr {0 / $min}
+} {0}
+test expr-34.76 {expr edge cases} {
+ expr {0 % $min}
+} {0}
+test expr-34.77 {expr edge cases} {
+ expr {0 / ($min + 1)}
+} {0}
+test expr-34.78 {expr edge cases} {
+ expr {0 % ($min + 1)}
+} {0}
+test expr-34.79 {expr edge cases} {
+ expr {1 / $min}
+} {-1}
+test expr-34.80 {expr edge cases} {
+ expr {1 % $min}
+} {-2147483647}
+test expr-34.81 {expr edge cases} {
+ expr {1 / ($min + 1)}
+} {-1}
+test expr-34.82 {expr edge cases} {
+ expr {1 % ($min + 1)}
+} {-2147483646}
+test expr-34.83 {expr edge cases} {
+ expr {2 / $min}
+} {-1}
+test expr-34.84 {expr edge cases} {
+ expr {2 % $min}
+} {-2147483646}
+test expr-34.85 {expr edge cases} {
+ expr {2 / ($min + 1)}
+} {-1}
+test expr-34.86 {expr edge cases} {
+ expr {2 % ($min + 1)}
+} {-2147483645}
+test expr-34.87 {expr edge cases} {
+ expr {3 / $min}
+} {-1}
+test expr-34.88 {expr edge cases} {
+ expr {3 % $min}
+} {-2147483645}
+test expr-34.89 {expr edge cases} {
+ expr {3 / ($min + 1)}
+} {-1}
+test expr-34.90 {expr edge cases} {
+ expr {3 % ($min + 1)}
+} {-2147483644}
+
+# Euclidean property:
+# quotient * divisor + remainder = dividend
+
+test expr-35.1 {expr edge cases} {
+ set dividend $max
+ set divisor 2
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($divisor * $q) + $r}]
+} {1073741823 * 2 + 1 = 2147483647}
+test expr-35.2 {expr edge cases} {
+ set dividend [expr {$max - 1}]
+ set divisor 2
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {1073741823 * 2 + 0 = 2147483646}
+test expr-35.3 {expr edge cases} {
+ set dividend [expr {$max - 2}]
+ set divisor 2
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {1073741822 * 2 + 1 = 2147483645}
+test expr-35.4 {expr edge cases} {
+ set dividend $max
+ set divisor 3
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {715827882 * 3 + 1 = 2147483647}
+test expr-35.5 {expr edge cases} {
+ set dividend [expr {$max - 1}]
+ set divisor 3
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {715827882 * 3 + 0 = 2147483646}
+test expr-35.6 {expr edge cases} {
+ set dividend [expr {$max - 2}]
+ set divisor 3
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {715827881 * 3 + 2 = 2147483645}
+test expr-35.7 {expr edge cases} {
+ set dividend $min
+ set divisor 2
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {-1073741824 * 2 + 0 = -2147483648}
+test expr-35.8 {expr edge cases} {
+ set dividend [expr {$min + 1}]
+ set divisor 2
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {-1073741824 * 2 + 1 = -2147483647}
+test expr-35.9 {expr edge cases} {
+ set dividend [expr {$min + 2}]
+ set divisor 2
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {-1073741823 * 2 + 0 = -2147483646}
+test expr-35.10 {expr edge cases} {
+ # Two things could happen here. The multiplication
+ # could overflow a 32 bit type, so that when
+ # 1 is added it overflows again back to min.
+ # The multiplication could also use a wide type
+ # to hold ($min - 1) until 1 is added and
+ # the number becomes $min again.
+ set dividend $min
+ set divisor 3
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {-715827883 * 3 + 1 = -2147483648}
+test expr-35.11 {expr edge cases} {
+ set dividend $min
+ set divisor -3
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {715827882 * -3 + -2 = -2147483648}
+test expr-35.12 {expr edge cases} {
+ set dividend $min
+ set divisor $min
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {1 * -2147483648 + 0 = -2147483648}
+test expr-35.13 {expr edge cases} {
+ set dividend $min
+ set divisor [expr {$min + 1}]
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {1 * -2147483647 + -1 = -2147483648}
+test expr-35.14 {expr edge cases} {
+ set dividend $min
+ set divisor [expr {$min + 2}]
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {1 * -2147483646 + -2 = -2147483648}
+
+# 64bit wide integer checks
+
+set min -9223372036854775808
+set max 9223372036854775807
+
+test expr-36.1 {expr edge cases} {wideIs64bit} {
+ expr {$min / $min}
+} {1}
+test expr-36.2 {expr edge cases} {wideIs64bit} {
+ expr {$min % $min}
+} {0}
+test expr-36.3 {expr edge cases} {wideIs64bit} {
+ expr {$min / ($min + 1)}
+} {1}
+test expr-36.4 {expr edge cases} {wideIs64bit} {
+ expr {$min % ($min + 1)}
+} {-1}
+test expr-36.5 {expr edge cases} {wideIs64bit} {
+ expr {$min / ($min + 2)}
+} {1}
+test expr-36.6 {expr edge cases} {wideIs64bit} {
+ expr {$min % ($min + 2)}
+} {-2}
+test expr-36.7 {expr edge cases} {wideIs64bit} {
+ expr {$min / ($min + 3)}
+} {1}
+test expr-36.8 {expr edge cases} {wideIs64bit} {
+ expr {$min % ($min + 3)}
+} {-3}
+test expr-36.9 {expr edge cases} {wideIs64bit} {
+ expr {$min / -3}
+} {3074457345618258602}
+test expr-36.10 {expr edge cases} {wideIs64bit} {
+ expr {$min % -3}
+} {-2}
+test expr-36.11 {expr edge cases} {wideIs64bit} {
+ expr {$min / -2}
+} {4611686018427387904}
+test expr-36.12 {expr edge cases} {wideIs64bit} {
+ expr {$min % -2}
+} {0}
+test expr-36.13 {expr edge cases} wideIs64bit {
+ expr {wide($min / -1)}
+} $min
+test expr-36.14 {expr edge cases} {wideIs64bit} {
+ expr {$min % -1}
+} {0}
+test expr-36.15 {expr edge cases} wideIs64bit {
+ expr {wide($min * -1)}
+} $min
+test expr-36.16 {expr edge cases} wideIs64bit {
+ expr {wide(-$min)}
+} $min
+test expr-36.17 {expr edge cases} {wideIs64bit} {
+ expr {$min / 1}
+} $min
+test expr-36.18 {expr edge cases} {wideIs64bit} {
+ expr {$min % 1}
+} {0}
+test expr-36.19 {expr edge cases} {wideIs64bit} {
+ expr {$min / 2}
+} {-4611686018427387904}
+test expr-36.20 {expr edge cases} {wideIs64bit} {
+ expr {$min % 2}
+} {0}
+test expr-36.21 {expr edge cases} {wideIs64bit} {
+ expr {$min / 3}
+} {-3074457345618258603}
+test expr-36.22 {expr edge cases} {wideIs64bit} {
+ expr {$min % 3}
+} {1}
+test expr-36.23 {expr edge cases} {wideIs64bit} {
+ expr {$min / ($max - 3)}
+} {-2}
+test expr-36.24 {expr edge cases} {wideIs64bit} {
+ expr {$min % ($max - 3)}
+} {9223372036854775800}
+test expr-36.25 {expr edge cases} {wideIs64bit} {
+ expr {$min / ($max - 2)}
+} {-2}
+test expr-36.26 {expr edge cases} {wideIs64bit} {
+ expr {$min % ($max - 2)}
+} {9223372036854775802}
+test expr-36.27 {expr edge cases} {wideIs64bit} {
+ expr {$min / ($max - 1)}
+} {-2}
+test expr-36.28 {expr edge cases} {wideIs64bit} {
+ expr {$min % ($max - 1)}
+} {9223372036854775804}
+test expr-36.29 {expr edge cases} {wideIs64bit} {
+ expr {$min / $max}
+} {-2}
+test expr-36.30 {expr edge cases} {wideIs64bit} {
+ expr {$min % $max}
+} {9223372036854775806}
+test expr-36.31 {expr edge cases} {wideIs64bit} {
+ expr {$max / $max}
+} {1}
+test expr-36.32 {expr edge cases} {wideIs64bit} {
+ expr {$max % $max}
+} {0}
+test expr-36.33 {expr edge cases} {wideIs64bit} {
+ expr {$max / ($max - 1)}
+} {1}
+test expr-36.34 {expr edge cases} {wideIs64bit} {
+ expr {$max % ($max - 1)}
+} {1}
+test expr-36.35 {expr edge cases} {wideIs64bit} {
+ expr {$max / ($max - 2)}
+} {1}
+test expr-36.36 {expr edge cases} {wideIs64bit} {
+ expr {$max % ($max - 2)}
+} {2}
+test expr-36.37 {expr edge cases} {wideIs64bit} {
+ expr {$max / ($max - 3)}
+} {1}
+test expr-36.38 {expr edge cases} {wideIs64bit} {
+ expr {$max % ($max - 3)}
+} {3}
+test expr-36.39 {expr edge cases} {wideIs64bit} {
+ expr {$max / 3}
+} {3074457345618258602}
+test expr-36.40 {expr edge cases} {wideIs64bit} {
+ expr {$max % 3}
+} {1}
+test expr-36.41 {expr edge cases} {wideIs64bit} {
+ expr {$max / 2}
+} {4611686018427387903}
+test expr-36.42 {expr edge cases} {wideIs64bit} {
+ expr {$max % 2}
+} {1}
+test expr-36.43 {expr edge cases} {wideIs64bit} {
+ expr {$max / 1}
+} $max
+test expr-36.44 {expr edge cases} {wideIs64bit} {
+ expr {$max % 1}
+} {0}
+test expr-36.45 {expr edge cases} {wideIs64bit} {
+ expr {$max / -1}
+} "-$max"
+test expr-36.46 {expr edge cases} {wideIs64bit} {
+ expr {$max % -1}
+} {0}
+test expr-36.47 {expr edge cases} {wideIs64bit} {
+ expr {$max / -2}
+} {-4611686018427387904}
+test expr-36.48 {expr edge cases} {wideIs64bit} {
+ expr {$max % -2}
+} {-1}
+test expr-36.49 {expr edge cases} {wideIs64bit} {
+ expr {$max / -3}
+} {-3074457345618258603}
+test expr-36.50 {expr edge cases} {wideIs64bit} {
+ expr {$max % -3}
+} {-2}
+test expr-36.51 {expr edge cases} {wideIs64bit} {
+ expr {$max / ($min + 3)}
+} {-2}
+test expr-36.52 {expr edge cases} {wideIs64bit} {
+ expr {$max % ($min + 3)}
+} {-9223372036854775803}
+test expr-36.53 {expr edge cases} {wideIs64bit} {
+ expr {$max / ($min + 2)}
+} {-2}
+test expr-36.54 {expr edge cases} {wideIs64bit} {
+ expr {$max % ($min + 2)}
+} {-9223372036854775805}
+test expr-36.55 {expr edge cases} {wideIs64bit} {
+ expr {$max / ($min + 1)}
+} {-1}
+test expr-36.56 {expr edge cases} {wideIs64bit} {
+ expr {$max % ($min + 1)}
+} {0}
+test expr-36.57 {expr edge cases} {wideIs64bit} {
+ expr {$max / $min}
+} {-1}
+test expr-36.58 {expr edge cases} {wideIs64bit} {
+ expr {$max % $min}
+} {-1}
+test expr-36.59 {expr edge cases} {wideIs64bit} {
+ expr {($min + 1) / ($max - 1)}
+} {-2}
+test expr-36.60 {expr edge cases} {wideIs64bit} {
+ expr {($min + 1) % ($max - 1)}
+} {9223372036854775805}
+test expr-36.61 {expr edge cases} {wideIs64bit} {
+ expr {($max - 1) / ($min + 1)}
+} {-1}
+test expr-36.62 {expr edge cases} {wideIs64bit} {
+ expr {($max - 1) % ($min + 1)}
+} {-1}
+test expr-36.63 {expr edge cases} {wideIs64bit} {
+ expr {($max - 1) / $min}
+} {-1}
+test expr-36.64 {expr edge cases} {wideIs64bit} {
+ expr {($max - 1) % $min}
+} {-2}
+test expr-36.65 {expr edge cases} {wideIs64bit} {
+ expr {($max - 2) / $min}
+} {-1}
+test expr-36.66 {expr edge cases} {wideIs64bit} {
+ expr {($max - 2) % $min}
+} {-3}
+test expr-36.67 {expr edge cases} {wideIs64bit} {
+ expr {($max - 3) / $min}
+} {-1}
+test expr-36.68 {expr edge cases} {wideIs64bit} {
+ expr {($max - 3) % $min}
+} {-4}
+test expr-36.69 {expr edge cases} {wideIs64bit} {
+ expr {-3 / $min}
+} {0}
+test expr-36.70 {expr edge cases} {wideIs64bit} {
+ expr {-3 % $min}
+} {-3}
+test expr-36.71 {expr edge cases} {wideIs64bit} {
+ expr {-2 / $min}
+} {0}
+test expr-36.72 {expr edge cases} {wideIs64bit} {
+ expr {-2 % $min}
+} {-2}
+test expr-36.73 {expr edge cases} {wideIs64bit} {
+ expr {-1 / $min}
+} {0}
+test expr-36.74 {expr edge cases} {wideIs64bit} {
+ expr {-1 % $min}
+} {-1}
+test expr-36.75 {expr edge cases} {wideIs64bit} {
+ expr {0 / $min}
+} {0}
+test expr-36.76 {expr edge cases} {wideIs64bit} {
+ expr {0 % $min}
+} {0}
+test expr-36.77 {expr edge cases} {wideIs64bit} {
+ expr {0 / ($min + 1)}
+} {0}
+test expr-36.78 {expr edge cases} {wideIs64bit} {
+ expr {0 % ($min + 1)}
+} {0}
+test expr-36.79 {expr edge cases} {wideIs64bit} {
+ expr {1 / $min}
+} {-1}
+test expr-36.80 {expr edge cases} {wideIs64bit} {
+ expr {1 % $min}
+} {-9223372036854775807}
+test expr-36.81 {expr edge cases} {wideIs64bit} {
+ expr {1 / ($min + 1)}
+} {-1}
+test expr-36.82 {expr edge cases} {wideIs64bit} {
+ expr {1 % ($min + 1)}
+} {-9223372036854775806}
+test expr-36.83 {expr edge cases} {wideIs64bit} {
+ expr {2 / $min}
+} {-1}
+test expr-36.84 {expr edge cases} {wideIs64bit} {
+ expr {2 % $min}
+} {-9223372036854775806}
+test expr-36.85 {expr edge cases} {wideIs64bit} {
+ expr {2 / ($min + 1)}
+} {-1}
+test expr-36.86 {expr edge cases} {wideIs64bit} {
+ expr {2 % ($min + 1)}
+} {-9223372036854775805}
+test expr-36.87 {expr edge cases} {wideIs64bit} {
+ expr {3 / $min}
+} {-1}
+test expr-36.88 {expr edge cases} {wideIs64bit} {
+ expr {3 % $min}
+} {-9223372036854775805}
+test expr-36.89 {expr edge cases} {wideIs64bit} {
+ expr {3 / ($min + 1)}
+} {-1}
+test expr-36.90 {expr edge cases} {wideIs64bit} {
+ expr {3 % ($min + 1)}
+} {-9223372036854775804}
+
+test expr-37.1 {expr edge cases} {wideIs64bit} {
+ set dividend $max
+ set divisor 2
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($divisor * $q) + $r}]
+} {4611686018427387903 * 2 + 1 = 9223372036854775807}
+test expr-37.2 {expr edge cases} {wideIs64bit} {
+ set dividend [expr {$max - 1}]
+ set divisor 2
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {4611686018427387903 * 2 + 0 = 9223372036854775806}
+test expr-37.3 {expr edge cases} {wideIs64bit} {
+ set dividend [expr {$max - 2}]
+ set divisor 2
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {4611686018427387902 * 2 + 1 = 9223372036854775805}
+test expr-37.4 {expr edge cases} {wideIs64bit} {
+ set dividend $max
+ set divisor 3
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {3074457345618258602 * 3 + 1 = 9223372036854775807}
+test expr-37.5 {expr edge cases} {wideIs64bit} {
+ set dividend [expr {$max - 1}]
+ set divisor 3
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {3074457345618258602 * 3 + 0 = 9223372036854775806}
+test expr-37.6 {expr edge cases} {wideIs64bit} {
+ set dividend [expr {$max - 2}]
+ set divisor 3
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {3074457345618258601 * 3 + 2 = 9223372036854775805}
+test expr-37.7 {expr edge cases} {wideIs64bit} {
+ set dividend $min
+ set divisor 2
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {-4611686018427387904 * 2 + 0 = -9223372036854775808}
+test expr-37.8 {expr edge cases} {wideIs64bit} {
+ set dividend [expr {$min + 1}]
+ set divisor 2
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {-4611686018427387904 * 2 + 1 = -9223372036854775807}
+test expr-37.9 {expr edge cases} {wideIs64bit} {
+ set dividend [expr {$min + 2}]
+ set divisor 2
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {-4611686018427387903 * 2 + 0 = -9223372036854775806}
+test expr-37.10 {expr edge cases} {wideIs64bit} {
+ # Multiplication overflows 64 bit type here,
+ # so when the 1 is added it overflows
+ # again and we end up back at min.
+ set dividend $min
+ set divisor 3
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {-3074457345618258603 * 3 + 1 = -9223372036854775808}
+test expr-37.11 {expr edge cases} {wideIs64bit} {
+ set dividend $min
+ set divisor -3
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {3074457345618258602 * -3 + -2 = -9223372036854775808}
+test expr-37.12 {expr edge cases} {wideIs64bit} {
+ set dividend $min
+ set divisor $min
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {1 * -9223372036854775808 + 0 = -9223372036854775808}
+test expr-37.13 {expr edge cases} {wideIs64bit} {
+ set dividend $min
+ set divisor [expr {$min + 1}]
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {1 * -9223372036854775807 + -1 = -9223372036854775808}
+test expr-37.14 {expr edge cases} {wideIs64bit} {
+ set dividend $min
+ set divisor [expr {$min + 2}]
+ set q [expr {$dividend / $divisor}]
+ set r [expr {$dividend % $divisor}]
+ list $q * $divisor + $r = [expr {($q * $divisor) + $r}]
+} {1 * -9223372036854775806 + -2 = -9223372036854775808}
+
test expr-38.1 {abs of smallest 32-bit integer [Bug 1241572]} {wideIs64bit} {
- expr {abs(int(-2147483648))}
+ expr {abs(-2147483648)}
} 2147483648
test expr-38.2 {abs and -0 [Bug 1893815]} {
expr {abs(-0)}
@@ -833,14 +6674,271 @@ test expr-38.2 {abs and -0 [Bug 1893815]} {
test expr-38.3 {abs and -0 [Bug 1893815]} {
expr {abs(-0.0)}
} 0.0
-# tests 38.4 to 38.8 not backported
+test expr-38.4 {abs and -0 [Bug 1893815]} {
+ expr {abs(-1e-324)}
+} 0.0
+test expr-38.5 {abs and -0 [Bug 1893815]} {
+ ::tcl::mathfunc::abs -0
+} 0
+test expr-38.6 {abs and -0 [Bug 1893815]} {
+ ::tcl::mathfunc::abs -0.0
+} 0.0
+test expr-38.7 {abs and -0 [Bug 1893815]} {
+ ::tcl::mathfunc::abs -1e-324
+} 0.0
+test expr-38.8 {abs and 0.0 [Bug 2954959]} {
+ ::tcl::mathfunc::abs 0.0
+} 0.0
test expr-38.9 {abs and 0.0 [Bug 2954959]} {
expr {abs(0.0)}
} 0.0
test expr-38.10 {abs and -0x0 [Bug 2954959]} {
expr {abs(-0x0)}
} 0
-# tests 38.11 to 38.13 not backported
+test expr-38.11 {abs and 0x0 [Bug 2954959]} {
+ ::tcl::mathfunc::abs { 0x0}
+} { 0x0}
+test expr-38.12 {abs and -0x0 [Bug 2954959]} {
+ ::tcl::mathfunc::abs { -0x0}
+} 0
+test expr-38.13 {abs and 0.0 [Bug 2954959]} {
+ ::tcl::mathfunc::abs 1e-324
+} 1e-324
+
+testConstraint testexprlongobj [llength [info commands testexprlongobj]]
+testConstraint testexprdoubleobj [llength [info commands testexprdoubleobj]]
+
+test expr-39.1 {Check that Tcl_ExprLongObj doesn't modify interpreter result if no error} testexprlongobj {
+ testexprlongobj 4+1
+} {This is a result: 5}
+#Check for [Bug 1109484]
+test expr-39.2 {Tcl_ExprLongObj handles wide ints gracefully} testexprlongobj {
+ testexprlongobj wide(1)+2
+} {This is a result: 3}
+
+test expr-39.3 {Tcl_ExprLongObj on the empty string} \
+ -constraints {testexprlongobj}\
+ -body {testexprlongobj ""} \
+ -match glob \
+ -returnCodes error -result *
+test expr-39.4 {Tcl_ExprLongObj coerces doubles} testexprlongobj {
+ testexprlongobj 3+.14159
+} {This is a result: 3}
+test expr-39.5 {Tcl_ExprLongObj handles overflows} {testexprlongobj longIs32bit} {
+ testexprlongobj 0x80000000
+} {This is a result: -2147483648}
+test expr-39.6 {Tcl_ExprLongObj handles overflows} {testexprlongobj longIs32bit} {
+ testexprlongobj 0xffffffff
+} {This is a result: -1}
+test expr-39.7 {Tcl_ExprLongObj handles overflows} \
+ -constraints {testexprlongobj longIs32bit} \
+ -match glob \
+ -body {
+ list [catch {testexprlongobj 0x100000000} result] $result
+ } \
+ -result {1 {integer value too large to represent*}}
+test expr-39.8 {Tcl_ExprLongObj handles overflows} testexprlongobj {
+ testexprlongobj -0x80000000
+} {This is a result: -2147483648}
+test expr-39.9 {Tcl_ExprLongObj handles overflows} {testexprlongobj longIs32bit} {
+ testexprlongobj -0xffffffff
+} {This is a result: 1}
+test expr-39.10 {Tcl_ExprLongObj handles overflows} \
+ -constraints {testexprlongobj longIs32bit} \
+ -match glob \
+ -body {
+ list [catch {testexprlongobj -0x100000000} result] $result
+ } \
+ -result {1 {integer value too large to represent*}}
+test expr-39.11 {Tcl_ExprLongObj handles overflows} {testexprlongobj longIs32bit} {
+ testexprlongobj 2147483648.
+} {This is a result: -2147483648}
+test expr-39.12 {Tcl_ExprLongObj handles overflows} {testexprlongobj longIs32bit} {
+ testexprlongobj 4294967295.
+} {This is a result: -1}
+test expr-39.13 {Tcl_ExprLongObj handles overflows} \
+ -constraints {testexprlongobj longIs32bit} \
+ -match glob \
+ -body {
+ list [catch {testexprlongobj 4294967296.} result] $result
+ } \
+ -result {1 {integer value too large to represent*}}
+test expr-39.14 {Tcl_ExprLongObj handles overflows} testexprlongobj {
+ testexprlongobj -2147483648.
+} {This is a result: -2147483648}
+test expr-39.15 {Tcl_ExprLongObj handles overflows} {testexprlongobj longIs32bit} {
+ testexprlongobj -4294967295.
+} {This is a result: 1}
+test expr-39.16 {Tcl_ExprLongObj handles overflows} \
+ -constraints {testexprlongobj longIs32bit} \
+ -match glob \
+ -body {
+ list [catch {testexprlongobj 4294967296.} result] $result
+ } \
+ -result {1 {integer value too large to represent*}}
+
+test expr-39.17 {Check that Tcl_ExprDoubleObj doesn't modify interpreter result if no error} testexprdoubleobj {
+ testexprdoubleobj 4.+1.
+} {This is a result: 5.0}
+#Check for [Bug 1109484]
+test expr-39.18 {Tcl_ExprDoubleObj on the empty string} \
+ -constraints {testexprdoubleobj} \
+ -match glob \
+ -body {testexprdoubleobj ""} \
+ -returnCodes error -result *
+test expr-39.19 {Tcl_ExprDoubleObj coerces wides} testexprdoubleobj {
+ testexprdoubleobj 1[string repeat 0 17]
+} {This is a result: 1e+17}
+test expr-39.20 {Tcl_ExprDoubleObj coerces bignums} testexprdoubleobj {
+ testexprdoubleobj 1[string repeat 0 38]
+} {This is a result: 1e+38}
+test expr-39.21 {Tcl_ExprDoubleObj handles overflows} \
+ testexprdoubleobj&&ieeeFloatingPoint {
+ testexprdoubleobj 17976931348623157[string repeat 0 292].
+ } {This is a result: 1.7976931348623157e+308}
+test expr-39.22 {Tcl_ExprDoubleObj handles overflows that look like int} \
+ testexprdoubleobj&&ieeeFloatingPoint {
+ testexprdoubleobj 17976931348623157[string repeat 0 292]
+ } {This is a result: 1.7976931348623157e+308}
+test expr-39.23 {Tcl_ExprDoubleObj handles overflows} \
+ testexprdoubleobj&&ieeeFloatingPoint {
+ testexprdoubleobj 17976931348623165[string repeat 0 292].
+ } {This is a result: Inf}
+test expr-39.24 {Tcl_ExprDoubleObj handles overflows that look like int} \
+ testexprdoubleobj&&ieeeFloatingPoint {
+ testexprdoubleobj 17976931348623165[string repeat 0 292]
+ } {This is a result: Inf}
+test expr-39.25 {Tcl_ExprDoubleObj and NaN} \
+ {testexprdoubleobj ieeeFloatingPoint} {
+ list [catch {testexprdoubleobj 0.0/0.0} result] $result
+ } {1 {domain error: argument not in valid range}}
+
+test expr-40.1 {large octal shift} {
+ expr 0o100000000000000000000000000000000
+} [expr 0x1000000000000000000000000]
+test expr-40.2 {large octal shift} {
+ expr 0o100000000000000000000000000000001
+} [expr 0x1000000000000000000000001]
+
+test expr-41.1 {exponent overflow} {
+ expr 1.0e2147483630
+} Inf
+test expr-41.2 {exponent underflow} {
+ expr 1.0e-2147483630
+} 0.0
+
+test expr-42.1 {denormals} ieeeFloatingPoint {
+ expr 7e-324
+} 5e-324
+
+# TIP 114
+
+test expr-43.1 {0b notation} {
+ expr 0b0
+} 0
+test expr-43.2 {0b notation} {
+ expr 0b1
+} 1
+test expr-43.3 {0b notation} {
+ expr 0b10
+} 2
+test expr-43.4 {0b notation} {
+ expr 0b11
+} 3
+test expr-43.5 {0b notation} {
+ expr 0b100
+} 4
+test expr-43.6 {0b notation} {
+ expr 0b101
+} 5
+test expr-43.7 {0b notation} {
+ expr 0b1000
+} 8
+test expr-43.8 {0b notation} {
+ expr 0b1001
+} 9
+test expr-43.9 {0b notation} {
+ expr 0b1[string repeat 0 31]
+} 2147483648
+test expr-43.10 {0b notation} {
+ expr 0b1[string repeat 0 30]1
+} 2147483649
+test expr-43.11 {0b notation} {
+ expr 0b[string repeat 1 64]
+} 18446744073709551615
+test expr-43.12 {0b notation} {
+ expr 0b1[string repeat 0 64]
+} 18446744073709551616
+test expr-43.13 {0b notation} {
+ expr 0b1[string repeat 0 63]1
+} 18446744073709551617
+
+test expr-44.1 {0o notation} {
+ expr 0o0
+} 0
+test expr-44.2 {0o notation} {
+ expr 0o1
+} 1
+test expr-44.3 {0o notation} {
+ expr 0o7
+} 7
+test expr-44.4 {0o notation} {
+ expr 0o10
+} 8
+test expr-44.5 {0o notation} {
+ expr 0o11
+} 9
+test expr-44.6 {0o notation} {
+ expr 0o100
+} 64
+test expr-44.7 {0o notation} {
+ expr 0o101
+} 65
+test expr-44.8 {0o notation} {
+ expr 0o1000
+} 512
+test expr-44.9 {0o notation} {
+ expr 0o1001
+} 513
+test expr-44.10 {0o notation} {
+ expr 0o1[string repeat 7 21]
+} 18446744073709551615
+test expr-44.11 {0o notation} {
+ expr 0o2[string repeat 0 21]
+} 18446744073709551616
+test expr-44.12 {0o notation} {
+ expr 0o2[string repeat 0 20]1
+} 18446744073709551617
+
+# TIP 237 again
+
+test expr-45.1 {entier} {
+ expr entier(0)
+} 0
+test expr-45.2 {entier} {
+ expr entier(0.5)
+} 0
+test expr-45.3 {entier} {
+ expr entier(1.0)
+} 1
+test expr-45.4 {entier} {
+ expr entier(1.5)
+} 1
+test expr-45.5 {entier} {
+ expr entier(2.0)
+} 2
+test expr-45.6 {entier} {
+ expr entier(1e+22)
+} 10000000000000000000000
+test expr-45.7 {entier} {
+ list [catch {expr entier(Inf)} result] $result
+} {1 {integer value too large to represent}}
+test expr-45.8 {entier} ieeeFloatingPoint {
+ list [catch {expr {entier($ieeeValues(NaN))}} result] $result
+} {1 {floating point value is Not a Number}}
+test expr-45.9 {entier} ieeeFloatingPoint {
+ list [catch {expr {entier($ieeeValues(-NaN))}} result] $result
+} {1 {floating point value is Not a Number}}
test expr-46.1 {round() rounds to +-infinity} {
expr round(0.5)
@@ -855,15 +6953,15 @@ test expr-46.4 {round() rounds to +-infinity} {
expr round(-1.5)
} -2
test expr-46.5 {round() overflow} {
- list [catch {expr round(9.2233720368547758e+018)} result] $result
-} {1 {integer value too large to represent}}
+ expr round(9.2233720368547758e+018)
+} 9223372036854775808
test expr-46.6 {round() overflow} {
- list [catch {expr round(-9.2233720368547758e+018)} result] $result
-} {1 {integer value too large to represent}}
-test expr-46.7 {round() bad value} {
+ expr round(-9.2233720368547758e+018)
+} -9223372036854775808
+test expr-46.7 {round() bad value} -body {
set x trash
- list [catch {expr {round($x)}} result] $result
-} {1 {argument to math function didn't have numeric value}}
+ expr {round($x)}
+} -returnCodes error -match glob -result *
test expr-46.8 {round() already an integer} {
set x 123456789012
incr x
@@ -884,7 +6982,7 @@ test expr-46.10 {round() boundary case - 1/2 + 1 ulp} {
set x 0.75
set bit 0.125
while 1 {
- set newx [expr { $x - $bit }]
+ set newx [expr {$x - $bit}]
if { $newx == $x || $newx == 0.5 } break
set x $newx
set bit [expr { $bit / 2.0 }]
@@ -895,7 +6993,7 @@ test expr-46.11 {round() boundary case - -1/2 - 1 ulp} {
set x -0.75
set bit 0.125
while 1 {
- set newx [expr { $x + $bit }]
+ set newx [expr {$x + $bit}]
if { $newx == $x || $newx == -0.5 } break
set x $newx
set bit [expr { $bit / 2.0 }]
@@ -906,14 +7004,13 @@ test expr-46.12 {round() boundary case - -1/2 + 1 ulp} {
set x -0.25
set bit 0.125
while 1 {
- set newx [expr { $x - $bit }]
+ set newx [expr {$x - $bit}]
if { $newx == $x || $newx == -0.5 } break
set x $newx
set bit [expr { $bit / 2.0 }]
}
expr {round($x)}
} 0
-
test expr-46.13 {round() boundary case - round down} {
expr {round(2147483647 - 0.51)}
} 2147483646
@@ -937,9 +7034,146 @@ test expr-46.18 {round() boundary case - round down to wide} {
expr {round(-2147483648 - 0.50)}
} [expr {wide(-2147483648) - 1}]
+test expr-46.19 {round() handling of long/bignum boundary} {
+ expr {round(double(0x7fffffffffffffff))}
+} 9223372036854775808
+
+test expr-47.1 {isqrt() - arg count} {
+ list [catch {expr {isqrt(1,2)}} result] $result
+} {1 {too many arguments for math function "isqrt"}}
+
+test expr-47.2 {isqrt() - non-number} {
+ list [catch {expr {isqrt({rubbish})}} result] $result
+} {1 {expected number but got "rubbish"}}
+
+test expr-47.3 {isqrt() - NaN} ieeeFloatingPoint {
+ list [catch {expr {isqrt(NaN)}} result] $result
+} {1 {floating point value is Not a Number}}
+
+test expr-47.4 {isqrt() of negative floating point number} {
+ list [catch {expr {isqrt(-1.0)}} result] $result
+} {1 {square root of negative argument}}
+
+test expr-47.5 {isqrt() of floating point zero} {
+ expr isqrt(0.0)
+} 0
+
+test expr-47.6 {isqrt() of exact floating point numbers} {
+ set trouble {}
+ for {set i 0} {$i < 16} {incr i} {
+ set root [expr {1 << $i}]
+ set rm1 [expr {$root - 1}]
+ set arg [expr {pow(2., (2 * $i))}]
+ if {isqrt($arg-1) != $rm1} {
+ append trouble "i = " $i ": isqrt( " $arg "-1) != " $rm1 "\n"
+ }
+ if {isqrt($arg) != $root} {
+ append trouble "i = " $i ": isqrt( " $arg ") != " $root "\n"
+ }
+ if {isqrt($arg+1) != $root} {
+ append trouble "i = " $i ": isqrt( " $arg "+1) != " $root "\n"
+ }
+ }
+ set trouble
+} {}
+
+test expr-47.7 {isqrt() of exact floating point numbers} ieeeFloatingPoint {
+ set trouble {}
+ for {set i 17} {$i < 27} {incr i} {
+ set root [expr {1 << $i}]
+ set rm1 [expr {$root - 1}]
+ set arg [expr {pow(2., (2 * $i))}]
+ if {isqrt($arg-1.0) != $rm1} {
+ append trouble "i = " $i ": isqrt( " $arg "-1) != " $rm1 "\n"
+ }
+ if {isqrt($arg) != $root} {
+ append trouble "i = " $i ": isqrt( " $arg ") != " $root "\n"
+ }
+ if {isqrt($arg+1.0) != $root} {
+ append trouble "i = " $i ": isqrt( " $arg "+1) != " $root "\n"
+ }
+ }
+ set trouble
+} {}
+
+test expr-47.8 {isqrt of inexact floating point number} ieeeFloatingPoint {
+ expr isqrt(2[string repeat 0 34])
+} 141421356237309504
+
+test expr-47.9 {isqrt of negative int} {
+ list [catch {expr isqrt(-1)} result] $result
+} {1 {square root of negative argument}}
+
+test expr-47.10 {isqrt of negative bignum} {
+ list [catch {expr isqrt(-1[string repeat 0 1000])} result] $result
+} {1 {square root of negative argument}}
+
+test expr-47.11 {isqrt of zero} {
+ expr {isqrt(0)}
+} 0
+
+test expr-47.12 {isqrt of various sizes of integer} {
+ set faults 0
+ set trouble {}
+ for {set i 0} {$faults < 10 && $i <= 1024} {incr i} {
+ set root [expr {1 << $i}]
+ set rm1 [expr {$root - 1}]
+ set arg [expr {1 << (2 * $i)}]
+ set tval [expr {isqrt($arg-1)}]
+ if {$tval != $rm1} {
+ append trouble "i = " $i ": isqrt(" $arg "-1) == " $tval \
+ " != " $rm1 "\n"
+ incr faults
+ }
+ set tval [expr {isqrt($arg)}]
+ if {$tval != $root} {
+ append trouble "i = " $i ": isqrt(" $arg ") == " $tval \
+ " != " $root "\n"
+ incr faults
+ }
+ set tval [expr {isqrt($arg+1)}]
+ if {$tval != $root} {
+ append trouble "i = " $i ": isqrt(" $arg "+1) == " $tval \
+ " != " $root "\n"
+ incr faults
+ }
+ }
+ set trouble
+} {}
+
+test expr-47.13 {isqrt and floating point rounding (Bug 2143288)} {
+ set trouble {}
+ set faults 0
+ for {set i 0} {$i < 29 && $faults < 10} {incr i} {
+ for {set j 0} {$j <= $i} {incr j} {
+ set k [expr {isqrt((1<<56)+(1<<$i)+(1<<$j))}]
+ if {$k != (1<<28)} {
+ append trouble "i = $i, j = $j, k = $k\n"
+ incr faults
+ }
+ }
+ set k [expr {isqrt((1<<56)+(1<<29)+(1<<$i))}]
+ if {$k != (1<<28)+1} {
+ append trouble "i = $i, k = $k\n"
+ incr faults
+ }
+ }
+ set trouble
+} {}
+
+test expr-48.1 {Bug 1770224} {
+ expr {-0x8000000000000001 >> 0x8000000000000000}
+} -1
+
# cleanup
if {[info exists a]} {
unset a
}
+catch {unset min}
+catch {unset max}
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/fCmd.test b/tests/fCmd.test
index eff2f80..57aaa3c 100644
--- a/tests/fCmd.test
+++ b/tests/fCmd.test
@@ -1,38 +1,38 @@
# This file tests the tclFCmd.c file.
#
-# This file contains a collection of tests for one or more of the Tcl
-# built-in commands. Sourcing this file into Tcl runs the tests and
-# generates output for errors. No output means no errors were found.
+# This file contains a collection of tests for one or more of the Tcl built-in
+# commands. Sourcing this file into Tcl runs the tests and generates output
+# for errors. No output means no errors were found.
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
# Copyright (c) 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.
+# See the file "license.terms" for information on usage and redistribution of
+# this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest 2
namespace import -force ::tcltest::*
}
-tcltest::testConstraint testsetplatform [string equal testsetplatform [info commands testsetplatform]]
-tcltest::testConstraint testchmod [string equal testchmod [info commands testchmod]]
-tcltest::testConstraint notNetworkFilesystem 0
-testConstraint 95or98 [expr {[testConstraint 95] || [testConstraint 98]}]
-testConstraint 2000orNewer [expr {![testConstraint 95or98]}]
+testConstraint testsetplatform [llength [info commands testsetplatform]]
+testConstraint testchmod [llength [info commands testchmod]]
testConstraint winVista 0
testConstraint win2000orXP 0
testConstraint winOlderThan2000 0
+# Don't know how to determine this constraint correctly
+testConstraint notNetworkFilesystem 0
+testConstraint 95or98 [expr {[testConstraint 95] || [testConstraint 98]}]
+testConstraint 2000orNewer [expr {![testConstraint 95or98]}]
-# Several tests require need to match results against the unix username
-set user {}
-if {$tcl_platform(platform) == "unix"} {
- catch {set user [exec whoami]}
- if {$user == ""} {
- catch {regexp {^[^(]*\(([^)]*)\)} [exec id] dummy user}
- }
- if {$user == ""} {
- set user "root"
+# Find a group that exists on this Unix system, or else skip tests that
+# require Unix groups.
+testConstraint foundGroup [expr {![testConstraint unix]}]
+if {[testConstraint unix]} {
+ catch {
+ set groupList [exec groups]
+ set group [lindex $groupList 0]
+ testConstraint foundGroup 1
}
}
@@ -50,6 +50,33 @@ if {[testConstraint winOnly]} {
}
}
+testConstraint darwin9 [expr {[testConstraint unix] &&
+ $tcl_platform(os) eq "Darwin" &&
+ int([string range $tcl_platform(osVersion) 0 \
+ [string first . $tcl_platform(osVersion)]]) >= 9}]
+testConstraint notDarwin9 [expr {![testConstraint darwin9]}]
+
+testConstraint fileSharing 0
+testConstraint notFileSharing 1
+testConstraint linkFile 1
+testConstraint linkDirectory 1
+
+# Several tests require need to match results against the unix username
+set user {}
+if {[testConstraint unix]} {
+ catch {
+ set user [exec whoami]
+ }
+ if {$user eq ""} {
+ catch {
+ regexp {^[^(]*\(([^)]*)\)} [exec id] -> user
+ }
+ }
+ if {$user eq ""} {
+ set user "root"
+ }
+}
+
proc createfile {file {string a}} {
set f [open $file w]
puts -nonewline $f $string
@@ -57,17 +84,17 @@ proc createfile {file {string a}} {
return $string
}
-#
+#
# checkcontent --
#
-# Ensures that file "file" contains only the string "matchString"
-# returns 0 if the file does not exist, or has a different content
+# Ensures that file "file" contains only the string "matchString" returns 0
+# if the file does not exist, or has a different content
#
proc checkcontent {file matchString} {
if {[catch {
set f [open $file]
set fileString [read $f]
- close $f
+ close $f
}]} {
return 0
}
@@ -86,18 +113,17 @@ proc openup {path} {
}
proc cleanup {args} {
- if {$::tcl_platform(platform) == "macintosh"} {
- set wd [list :]
- } else {
- set wd [list .]
- }
+ set wd [list .]
foreach p [concat $wd $args] {
set x ""
catch {
set x [glob -directory $p tf* td*]
}
foreach file $x {
- if {[catch {file delete -force -- $file}]} {
+ if {
+ [catch {file delete -force -- $file}]
+ && [testConstraint testchmod]
+ } then {
catch {openup $file}
catch {file delete -force -- $file}
}
@@ -106,44 +132,25 @@ proc cleanup {args} {
}
proc contents {file} {
- set f [open $file r]
+ set f [open $file]
set r [read $f]
close $f
- set r
+ return $r
}
cd [temporaryDirectory]
-set ::tcltest::testConstraints(fileSharing) 0
-set ::tcltest::testConstraints(notFileSharing) 1
-
-if {$tcl_platform(platform) == "macintosh"} {
- catch {file delete -force foo.dir}
- file mkdir foo.dir
- if {[catch {file attributes foo.dir -readonly 1}] == 0} {
- set ::tcltest::testConstraints(fileSharing) 1
- set ::tcltest::testConstraints(notFileSharing) 0
- }
- file delete -force foo.dir
-}
-
-set ::tcltest::testConstraints(xdev) 0
-
-if {$tcl_platform(platform) == "unix"} {
- if {[catch {set m1 [exec df .]; set m2 [exec df /tmp]}] == 0} {
- set m1 [string range $m1 0 [expr [string first " " $m1]-1]]
- set m2 [string range $m2 0 [expr [string first " " $m2]-1]]
- if {$m1 != "" && $m2 != "" && $m1 != $m2 && [file exists $m1] && [file exists $m2]} {
- set ::tcltest::testConstraints(xdev) 1
- }
- }
+proc dev dir {
+ file stat $dir stat
+ return $stat(dev)
}
+testConstraint xdev [expr {[testConstraint unix] && ([dev .] != [dev /tmp])}]
set root [lindex [file split [pwd]] 0]
# A really long file name
-# length of long is 1216 chars, which should be greater than any static
-# buffer or allowable filename.
+# length of long is 1216 chars, which should be greater than any static buffer
+# or allowable filename.
set long "abcdefghihjllmnopqrstuvwxyz01234567890"
append long $long
@@ -166,44 +173,49 @@ test fCmd-2.1 {TclFileCopyCmd} {notRoot} {
lsort [glob tf*]
} {tf1 tf2}
-test fCmd-3.1 {FileCopyRename: FileForceOption fails} {notRoot} {
- list [catch {file rename -xyz} msg] $msg
-} {1 {bad option "-xyz": should be -force or --}}
-test fCmd-3.2 {FileCopyRename: not enough args} {notRoot} {
- list [catch {file rename xyz} msg] $msg
-} {1 {wrong # args: should be "file rename ?options? source ?source ...? target"}}
-test fCmd-3.3 {FileCopyRename: Tcl_TranslateFileName fails} {notRoot} {
- list [catch {file rename xyz ~_totally_bogus_user} msg] $msg
-} {1 {user "_totally_bogus_user" doesn't exist}}
-test fCmd-3.4 {FileCopyRename: Tcl_TranslateFileName passes} {notRoot} {
- cleanup
- list [catch {file copy tf1 ~} msg] $msg
-} {1 {error copying "tf1": no such file or directory}}
-test fCmd-3.5 {FileCopyRename: target doesn't exist: stat(target) != 0} {notRoot} {
- cleanup
- list [catch {file rename tf1 tf2 tf3} msg] $msg
-} {1 {error renaming: target "tf3" is not a directory}}
-test fCmd-3.6 {FileCopyRename: target tf3 is not a dir: !S_ISDIR(target)} \
- {notRoot} {
- cleanup
+test fCmd-3.1 {FileCopyRename: FileForceOption fails} -constraints {notRoot} -body {
+ file rename -xyz
+} -returnCodes error -result {bad option "-xyz": should be -force or --}
+test fCmd-3.2 {FileCopyRename: not enough args} -constraints {notRoot} -body {
+ file rename xyz
+} -returnCodes error -result {wrong # args: should be "file rename ?options? source ?source ...? target"}
+test fCmd-3.3 {FileCopyRename: Tcl_TranslateFileName fails} -constraints {notRoot} -body {
+ file rename xyz ~_totally_bogus_user
+} -returnCodes error -result {user "_totally_bogus_user" doesn't exist}
+test fCmd-3.4 {FileCopyRename: Tcl_TranslateFileName passes} -setup {
+ cleanup
+} -constraints {notRoot} -returnCodes error -body {
+ file copy tf1 ~
+} -result {error copying "tf1": no such file or directory}
+test fCmd-3.5 {FileCopyRename: target doesn't exist: stat(target) != 0} -setup {
+ cleanup
+} -constraints {notRoot} -returnCodes error -body {
+ file rename tf1 tf2 tf3
+} -result {error renaming: target "tf3" is not a directory}
+test fCmd-3.6 {FileCopyRename: target tf3 is not a dir: !S_ISDIR(target)} -setup {
+ cleanup
+} -constraints {notRoot} -returnCodes error -body {
createfile tf3
- list [catch {file rename tf1 tf2 tf3} msg] $msg
-} {1 {error renaming: target "tf3" is not a directory}}
-test fCmd-3.7 {FileCopyRename: target exists & is directory} {notRoot} {
+ file rename tf1 tf2 tf3
+} -result {error renaming: target "tf3" is not a directory}
+test fCmd-3.7 {FileCopyRename: target exists & is directory} -setup {
cleanup
+} -constraints {notRoot} -body {
file mkdir td1
createfile tf1 tf1
file rename tf1 td1
contents [file join td1 tf1]
-} {tf1}
-test fCmd-3.8 {FileCopyRename: too many arguments: argc - i > 2} {notRoot} {
+} -result {tf1}
+test fCmd-3.8 {FileCopyRename: too many arguments: argc - i > 2} -setup {
cleanup
- list [catch {file rename tf1 tf2 tf3} msg] $msg
-} {1 {error renaming: target "tf3" is not a directory}}
-test fCmd-3.9 {FileCopyRename: too many arguments: argc - i > 2} {notRoot} {
+} -constraints {notRoot} -returnCodes error -body {
+ file rename tf1 tf2 tf3
+} -result {error renaming: target "tf3" is not a directory}
+test fCmd-3.9 {FileCopyRename: too many arguments: argc - i > 2} -setup {
cleanup
- list [catch {file copy -force -- tf1 tf2 tf3} msg] $msg
-} {1 {error copying: target "tf3" is not a directory}}
+} -constraints {notRoot} -returnCodes error -body {
+ file copy -force -- tf1 tf2 tf3
+} -result {error copying: target "tf3" is not a directory}
test fCmd-3.10 {FileCopyRename: just 2 arguments} {notRoot} {
cleanup
createfile tf1 tf1
@@ -234,26 +246,29 @@ test fCmd-3.13 {FileCopyRename: move each source: multiple sources} {notRoot} {
list [contents [file join td1 tf1]] [contents [file join td1 tf2]] \
[contents [file join td1 tf3]] [contents [file join td1 tf4]]
} {tf1 tf2 tf3 tf4}
-test fCmd-3.14 {FileCopyRename: FileBasename fails} {notRoot} {
+test fCmd-3.14 {FileCopyRename: FileBasename fails} -setup {
cleanup
+} -constraints {notRoot} -returnCodes error -body {
file mkdir td1
- list [catch {file rename ~_totally_bogus_user td1} msg] $msg
-} {1 {user "_totally_bogus_user" doesn't exist}}
-test fCmd-3.15 {FileCopyRename: source[0] == '\0'} {notRoot unixOrPc} {
+ file rename ~_totally_bogus_user td1
+} -result {user "_totally_bogus_user" doesn't exist}
+test fCmd-3.15 {FileCopyRename: source[0] == '\0'} -setup {
cleanup
+} -constraints {notRoot unixOrPc} -returnCodes error -body {
file mkdir td1
- list [catch {file rename / td1} msg] $msg
-} {1 {error renaming "/" to "td1": file already exists}}
-test fCmd-3.16 {FileCopyRename: break on first error} {notRoot} {
- cleanup
- createfile tf1
- createfile tf2
- createfile tf3
- createfile tf4
+ file rename / td1
+} -result {error renaming "/" to "td1": file already exists}
+test fCmd-3.16 {FileCopyRename: break on first error} -setup {
+ cleanup
+} -constraints {notRoot} -returnCodes error -body {
+ createfile tf1
+ createfile tf2
+ createfile tf3
+ createfile tf4
file mkdir td1
createfile [file join td1 tf3]
- list [catch {file rename tf1 tf2 tf3 tf4 td1} msg] $msg
-} [subst {1 {error renaming "tf3" to "[file join td1 tf3]": file already exists}}]
+ file rename tf1 tf2 tf3 tf4 td1
+} -result [subst {error renaming "tf3" to "[file join td1 tf3]": file already exists}]
test fCmd-4.1 {TclFileMakeDirsCmd: make each dir: 1 dir} {notRoot} {
cleanup
@@ -271,15 +286,16 @@ test fCmd-4.3 {TclFileMakeDirsCmd: stops on first error} {notRoot} {
catch {file mkdir td1 td2 tf1 td3 td4}
glob td1 td2 tf1 td3 td4
} {td1 td2 tf1}
-test fCmd-4.4 {TclFileMakeDirsCmd: Tcl_TranslateFileName fails} {notRoot} {
+test fCmd-4.4 {TclFileMakeDirsCmd: Tcl_TranslateFileName fails} -setup {
cleanup
- list [catch {file mkdir ~_totally_bogus_user} msg] $msg
-} {1 {user "_totally_bogus_user" doesn't exist}}
-test fCmd-4.5 {TclFileMakeDirsCmd: Tcl_SplitPath returns 0: *name == '\0'} \
- {notRoot} {
+} -constraints {notRoot} -returnCodes error -body {
+ file mkdir ~_totally_bogus_user
+} -result {user "_totally_bogus_user" doesn't exist}
+test fCmd-4.5 {TclFileMakeDirsCmd: Tcl_SplitPath returns 0: *name == '\0'} -setup {
cleanup
- list [catch {file mkdir ""} msg] $msg
-} {1 {can't create directory "": no such file or directory}}
+} -constraints {notRoot} -returnCodes error -body {
+ file mkdir ""
+} -result {can't create directory "": no such file or directory}
test fCmd-4.6 {TclFileMakeDirsCmd: one level deep} {notRoot} {
cleanup
file mkdir td1
@@ -297,11 +313,12 @@ test fCmd-4.8 {TclFileMakeDirsCmd: already exist: lstat(target) == 0} {notRoot}
file mkdir td1
list $x [file exists td1]
} {1 1}
-test fCmd-4.9 {TclFileMakeDirsCmd: exists, not dir} {notRoot} {
+test fCmd-4.9 {TclFileMakeDirsCmd: exists, not dir} -setup {
cleanup
+} -constraints {notRoot} -returnCodes error -body {
createfile tf1
- list [catch {file mkdir tf1} msg] $msg
-} [subst {1 {can't create directory "[file join tf1]": file already exists}}]
+ file mkdir tf1
+} -result [subst {can't create directory "[file join tf1]": file already exists}]
test fCmd-4.10 {TclFileMakeDirsCmd: exists, is dir} {notRoot} {
cleanup
file mkdir td1
@@ -309,50 +326,45 @@ test fCmd-4.10 {TclFileMakeDirsCmd: exists, is dir} {notRoot} {
file mkdir td1
list $x [file exists td1]
} {1 1}
-test fCmd-4.11 {TclFileMakeDirsCmd: doesn't exist: errno != ENOENT} \
- {unixOnly notRoot testchmod} {
+test fCmd-4.11 {TclFileMakeDirsCmd: doesn't exist: errno != ENOENT} -setup {
cleanup
+} -constraints {unix notRoot testchmod} -returnCodes error -body {
file mkdir td1/td2/td3
testchmod 000 td1/td2
- set msg [list [catch {file mkdir td1/td2/td3/td4} msg] $msg]
+ file mkdir td1/td2/td3/td4
+} -cleanup {
testchmod 755 td1/td2
- set msg
-} {1 {can't create directory "td1/td2/td3": permission denied}}
-test fCmd-4.12 {TclFileMakeDirsCmd: doesn't exist: errno != ENOENT} {macOnly} {
cleanup
- list [catch {file mkdir nonexistentvolume:} msg] $msg
-} {1 {can't create directory "nonexistentvolume:": invalid argument}}
-test fCmd-4.13 {TclFileMakeDirsCmd: doesn't exist: errno == ENOENT} {notRoot} {
+} -result {can't create directory "td1/td2/td3": permission denied}
+test fCmd-4.13 {TclFileMakeDirsCmd: doesn't exist: errno == ENOENT} -setup {
cleanup
+} -constraints {notRoot} -body {
set x [file exists td1]
file mkdir td1
list $x [file exists td1]
-} {0 1}
-test fCmd-4.14 {TclFileMakeDirsCmd: TclpCreateDirectory fails} \
- {unixOnly notRoot} {
+} -result {0 1}
+test fCmd-4.14 {TclFileMakeDirsCmd: TclpCreateDirectory fails} -setup {
cleanup
file delete -force foo
+} -constraints {unix notRoot} -body {
file mkdir foo
file attr foo -perm 040000
- set result [list [catch {file mkdir foo/tf1} msg] $msg]
+ file mkdir foo/tf1
+} -returnCodes error -cleanup {
file delete -force foo
- set result
-} {1 {can't create directory "foo/tf1": permission denied}}
-test fCmd-4.15 {TclFileMakeDirsCmd: TclpCreateDirectory fails} {macOnly} {
- list [catch {file mkdir ${root}:} msg] $msg
-} [subst {1 {can't create directory "${root}:": no such file or directory}}]
+} -result {can't create directory "foo/tf1": permission denied}
test fCmd-4.16 {TclFileMakeDirsCmd: TclpCreateDirectory succeeds} {notRoot} {
cleanup
file mkdir tf1
file exists tf1
} {1}
-test fCmd-5.1 {TclFileDeleteCmd: FileForceOption fails} {notRoot} {
- list [catch {file delete -xyz} msg] $msg
-} {1 {bad option "-xyz": should be -force or --}}
-test fCmd-5.2 {TclFileDeleteCmd: not enough args} {notRoot} {
- list [catch {file delete -force -force} msg] $msg
-} {1 {wrong # args: should be "file delete ?options? file ?file ...?"}}
+test fCmd-5.1 {TclFileDeleteCmd: FileForceOption fails} -constraints {notRoot} -body {
+ file delete -xyz
+} -returnCodes error -result {bad option "-xyz": should be -force or --}
+test fCmd-5.2 {TclFileDeleteCmd: not enough args} -constraints {notRoot} -body {
+ file delete -force -force
+} -returnCodes error -result {wrong # args: should be "file delete ?options? file ?file ...?"}
test fCmd-5.3 {TclFileDeleteCmd: 1 file} {notRoot} {
cleanup
createfile tf1
@@ -378,9 +390,9 @@ test fCmd-5.5 {TclFileDeleteCmd: stop at first error} {notRoot unixOrPc} {
catch {file delete tf1 td1 $root tf2}
list [file exists tf1] [file exists tf2] [file exists td1]
} {0 1 0}
-test fCmd-5.6 {TclFileDeleteCmd: Tcl_TranslateFileName fails} {notRoot} {
- list [catch {file delete ~_totally_bogus_user} msg] $msg
-} {1 {user "_totally_bogus_user" doesn't exist}}
+test fCmd-5.6 {TclFileDeleteCmd: Tcl_TranslateFileName fails} -constraints {notRoot} -body {
+ file delete ~_totally_bogus_user
+} -returnCodes error -result {user "_totally_bogus_user" doesn't exist}
test fCmd-5.7 {TclFileDeleteCmd: Tcl_TranslateFileName succeeds} {notRoot} {
catch {file delete ~/tf1}
createfile ~/tf1
@@ -391,28 +403,32 @@ test fCmd-5.8 {TclFileDeleteCmd: file doesn't exist: lstat(name) != 0} {notRoot}
set x [file exists tf1]
file delete tf1
list $x [file exists tf1]
-} {0 0}
+} {0 0}
test fCmd-5.9 {TclFileDeleteCmd: is directory} {notRoot} {
cleanup
file mkdir td1
file delete td1
file exists td1
} {0}
-test fCmd-5.10 {TclFileDeleteCmd: TclpRemoveDirectory fails} {notRoot} {
+test fCmd-5.10 {TclFileDeleteCmd: TclpRemoveDirectory fails} -setup {
cleanup
+} -constraints {notRoot} -returnCodes error -body {
file mkdir [file join td1 td2]
- list [catch {file delete td1} msg] $msg
-} {1 {error deleting "td1": directory not empty}}
-test fCmd-5.11 {TclFileDeleteCmd: TclpRemoveDirectory with cwd inside} {notRoot} {
+ file delete td1
+} -result {error deleting "td1": directory not empty}
+test fCmd-5.11 {TclFileDeleteCmd: TclpRemoveDirectory with cwd inside} -setup {
cleanup
set dir [pwd]
+} -constraints {notRoot} -body {
file mkdir [file join td1 td2]
cd [file join td1 td2]
set res [list [catch {file delete -force [file dirname [pwd]]} msg]]
cd $dir
lappend res [file exists td1] $msg
-} {0 0 {}}
-test fCmd-5.12 {TclFileDeleteCmd: TclpRemoveDirectory with bad perms} {unixOnly} {
+} -cleanup {
+ cd $dir
+} -result {0 0 {}}
+test fCmd-5.12 {TclFileDeleteCmd: TclpRemoveDirectory with bad perms} {unix} {
cleanup
file mkdir [file join td1 td2]
#exec chmod u-rwx [file join td1 td2]
@@ -421,16 +437,17 @@ test fCmd-5.12 {TclFileDeleteCmd: TclpRemoveDirectory with bad perms} {unixOnly}
lappend res [file exists td1] $msg
} {0 0 {}}
-test fCmd-6.1 {CopyRenameOneFile: bad source} {notRoot} {
+test fCmd-6.1 {CopyRenameOneFile: bad source} {notRoot emptyTest} {
# can't test this, because it's caught by FileCopyRename
} {}
-test fCmd-6.2 {CopyRenameOneFile: bad target} {notRoot} {
+test fCmd-6.2 {CopyRenameOneFile: bad target} {notRoot emptyTest} {
# can't test this, because it's caught by FileCopyRename
} {}
-test fCmd-6.3 {CopyRenameOneFile: lstat(source) != 0} {notRoot} {
+test fCmd-6.3 {CopyRenameOneFile: lstat(source) != 0} -setup {
cleanup
- list [catch {file rename tf1 tf2} msg] $msg
-} {1 {error renaming "tf1": no such file or directory}}
+} -constraints {notRoot} -returnCodes error -body {
+ file rename tf1 tf2
+} -result {error renaming "tf1": no such file or directory}
test fCmd-6.4 {CopyRenameOneFile: lstat(source) == 0} {notRoot} {
cleanup
createfile tf1
@@ -443,43 +460,42 @@ test fCmd-6.5 {CopyRenameOneFile: lstat(target) != 0} {notRoot} {
file rename tf1 tf2
glob tf*
} {tf2}
-test fCmd-6.6 {CopyRenameOneFile: errno != ENOENT} {unixOnly notRoot testchmod} {
+test fCmd-6.6 {CopyRenameOneFile: errno != ENOENT} -setup {
cleanup
+} -constraints {unix notRoot testchmod} -body {
file mkdir td1
testchmod 000 td1
createfile tf1
- set msg [list [catch {file rename tf1 td1} msg] $msg]
+ file rename tf1 td1
+} -returnCodes error -cleanup {
testchmod 755 td1
- set msg
-} {1 {error renaming "tf1" to "td1/tf1": permission denied}}
-test fCmd-6.7 {CopyRenameOneFile: errno != ENOENT} {pcOnly 95} {
+} -result {error renaming "tf1" to "td1/tf1": permission denied}
+test fCmd-6.7 {CopyRenameOneFile: errno != ENOENT} -setup {
cleanup
+} -constraints {win 95} -returnCodes error -body {
createfile tf1
- list [catch {file rename tf1 $long} msg] $msg
-} [subst {1 {error renaming "tf1" to "$long": file name too long}}]
-test fCmd-6.8 {CopyRenameOneFile: errno != ENOENT} {macOnly} {
- cleanup
- createfile tf1
- list [catch {file rename tf1 $long} msg] $msg
-} [subst {1 {error renaming "tf1" to "$long": file name too long}}]
-test fCmd-6.9 {CopyRenameOneFile: errno == ENOENT} {unixOnly notRoot} {
+ file rename tf1 $long
+} -result [subst {error renaming "tf1" to "$long": file name too long}]
+test fCmd-6.9 {CopyRenameOneFile: errno == ENOENT} {unix notRoot} {
cleanup
createfile tf1
file rename tf1 tf2
glob tf*
} {tf2}
-test fCmd-6.10 {CopyRenameOneFile: lstat(target) == 0} {notRoot} {
+test fCmd-6.10 {CopyRenameOneFile: lstat(target) == 0} -setup {
cleanup
+} -constraints {notRoot} -returnCodes error -body {
createfile tf1
createfile tf2
- list [catch {file rename tf1 tf2} msg] $msg
-} {1 {error renaming "tf1" to "tf2": file already exists}}
-test fCmd-6.11 {CopyRenameOneFile: force == 0} {notRoot} {
+ file rename tf1 tf2
+} -result {error renaming "tf1" to "tf2": file already exists}
+test fCmd-6.11 {CopyRenameOneFile: force == 0} -setup {
cleanup
+} -constraints {notRoot} -returnCodes error -body {
createfile tf1
createfile tf2
- list [catch {file rename tf1 tf2} msg] $msg
-} {1 {error renaming "tf1" to "tf2": file already exists}}
+ file rename tf1 tf2
+} -result {error renaming "tf1" to "tf2": file already exists}
test fCmd-6.12 {CopyRenameOneFile: force != 0} {notRoot} {
cleanup
createfile tf1
@@ -487,176 +503,184 @@ test fCmd-6.12 {CopyRenameOneFile: force != 0} {notRoot} {
file rename -force tf1 tf2
glob tf*
} {tf2}
-test fCmd-6.13 {CopyRenameOneFile: source is dir, target is file} {notRoot} {
+test fCmd-6.13 {CopyRenameOneFile: source is dir, target is file} -setup {
cleanup
+} -constraints {notRoot} -returnCodes error -body {
file mkdir td1
file mkdir td2
createfile [file join td2 td1]
- list [catch {file rename -force td1 td2} msg] $msg
-} [subst {1 {can't overwrite file "[file join td2 td1]" with directory "td1"}}]
-test fCmd-6.14 {CopyRenameOneFile: source is file, target is dir} {notRoot} {
+ file rename -force td1 td2
+} -result [subst {can't overwrite file "[file join td2 td1]" with directory "td1"}]
+test fCmd-6.14 {CopyRenameOneFile: source is file, target is dir} -setup {
cleanup
+} -constraints {notRoot} -returnCodes error -body {
createfile tf1
file mkdir [file join td1 tf1]
- list [catch {file rename -force tf1 td1} msg] $msg
-} [subst {1 {can't overwrite directory "[file join td1 tf1]" with file "tf1"}}]
-test fCmd-6.15 {CopyRenameOneFile: TclpRenameFile succeeds} {notRoot notNetworkFilesystem} {
+ file rename -force tf1 td1
+} -result [subst {can't overwrite directory "[file join td1 tf1]" with file "tf1"}]
+test fCmd-6.15 {CopyRenameOneFile: TclpRenameFile succeeds} -setup {
cleanup
+} -constraints {notRoot notNetworkFilesystem} -body {
file mkdir [file join td1 td2]
file mkdir td2
createfile [file join td2 tf1]
file rename -force td2 td1
file exists [file join td1 td2 tf1]
-} {1}
-test fCmd-6.16 {CopyRenameOneFile: TclpCopyRenameOneFile fails} {notRoot} {
+} -result 1
+test fCmd-6.16 {CopyRenameOneFile: TclpCopyRenameOneFile fails} -setup {
cleanup
+} -constraints {notRoot} -body {
file mkdir [file join td1 td2]
createfile [file join td1 td2 tf1]
file mkdir td2
- list [catch {file rename -force td2 td1} msg] $msg
-} [subst {1 {error renaming "td2" to "[file join td1 td2]": file already exists}}]
-
-test fCmd-6.17 {CopyRenameOneFile: errno == EINVAL} {notRoot} {
+ file rename -force td2 td1
+} -returnCodes error -match glob -result \
+ [subst {error renaming "td2" to "[file join td1 td2]": file *}]
+test fCmd-6.17 {CopyRenameOneFile: errno == EINVAL} -setup {
cleanup
- list [catch {file rename -force $root tf1} msg] $msg
-} [subst {1 {error renaming "$root" to "tf1": trying to rename a volume or move a directory into itself}}]
-test fCmd-6.18 {CopyRenameOneFile: errno != EXDEV} {notRoot} {
+} -constraints {notRoot} -returnCodes error -body {
+ file rename -force $root tf1
+} -result [subst {error renaming "$root" to "tf1": trying to rename a volume or move a directory into itself}]
+test fCmd-6.18 {CopyRenameOneFile: errno != EXDEV} -setup {
cleanup
+} -constraints {notRoot} -body {
file mkdir [file join td1 td2]
createfile [file join td1 td2 tf1]
file mkdir td2
- list [catch {file rename -force td2 td1} msg] $msg
-} [subst {1 {error renaming "td2" to "[file join td1 td2]": file already exists}}]
-test fCmd-6.19 {CopyRenameOneFile: errno == EXDEV} {unixOnly notRoot} {
+ file rename -force td2 td1
+} -returnCodes error -match glob -result \
+ [subst {error renaming "td2" to "[file join td1 td2]": file *}]
+test fCmd-6.19 {CopyRenameOneFile: errno == EXDEV} {unix notRoot} {
cleanup /tmp
createfile tf1
file rename tf1 /tmp
- glob tf* /tmp/tf1
+ glob -nocomplain tf* /tmp/tf1
} {/tmp/tf1}
-test fCmd-6.20 {CopyRenameOneFile: errno == EXDEV} {pcOnly} {
+test fCmd-6.20 {CopyRenameOneFile: errno == EXDEV} -constraints {win} -setup {
catch {file delete -force c:/tcl8975@ d:/tcl8975@}
+} -body {
file mkdir c:/tcl8975@
- if [catch {file rename c:/tcl8975@ d:/}] {
- set msg d:/tcl8975@
- } else {
- set msg [glob c:/tcl8975@ d:/tcl8975@]
- file delete -force d:/tcl8975@
+ if {[catch {file rename c:/tcl8975@ d:/}]} {
+ return d:/tcl8975@
}
+ glob c:/tcl8975@ d:/tcl8975@
+} -cleanup {
file delete -force c:/tcl8975@
- set msg
-} {d:/tcl8975@}
+ catch {file delete -force d:/tcl8975@}
+} -result {d:/tcl8975@}
test fCmd-6.21 {CopyRenameOneFile: copy/rename: S_ISDIR(source)} \
- {unixOnly notRoot} {
+ {unix notRoot} {
cleanup /tmp
file mkdir td1
file rename td1 /tmp
- glob td* /tmp/td*
+ glob -nocomplain td* /tmp/td*
} {/tmp/td1}
test fCmd-6.22 {CopyRenameOneFile: copy/rename: !S_ISDIR(source)} \
- {unixOnly notRoot} {
+ {unix notRoot} {
cleanup /tmp
createfile tf1
file rename tf1 /tmp
- glob tf* /tmp/tf*
+ glob -nocomplain tf* /tmp/tf*
} {/tmp/tf1}
-test fCmd-6.23 {CopyRenameOneFile: TclpCopyDirectory failed} \
- {unixOnly notRoot xdev} {
+test fCmd-6.23 {CopyRenameOneFile: TclpCopyDirectory failed} -setup {
cleanup /tmp
+} -constraints {unix notRoot xdev} -body {
file mkdir td1/td2/td3
file attributes td1 -permissions 0000
- set msg [list [catch {file rename td1 /tmp} msg] $msg]
+ file rename td1 /tmp
+} -returnCodes error -cleanup {
file attributes td1 -permissions 0755
- set msg
-} {1 {error renaming "td1": permission denied}}
-test fCmd-6.24 {CopyRenameOneFile: error uses original name} \
- {unixOnly notRoot} {
+} -match regexp -result {^error renaming "td1"( to "/tmp/td1")?: permission denied$}
+test fCmd-6.24 {CopyRenameOneFile: error uses original name} -setup {
cleanup
+} -constraints {unix notRoot} -body {
file mkdir ~/td1/td2
set td1name [file join [file dirname ~] [file tail ~] td1]
file attributes $td1name -permissions 0000
- set msg [list [catch {file copy ~/td1 td1} msg] $msg]
+ file copy ~/td1 td1
+} -returnCodes error -cleanup {
file attributes $td1name -permissions 0755
file delete -force ~/td1
- set msg
-} {1 {error copying "~/td1": permission denied}}
-test fCmd-6.25 {CopyRenameOneFile: error uses original name} \
- {unixOnly notRoot} {
+} -result {error copying "~/td1": permission denied}
+test fCmd-6.25 {CopyRenameOneFile: error uses original name} -setup {
cleanup
+} -constraints {unix notRoot} -body {
file mkdir td2
file mkdir ~/td1
set td1name [file join [file dirname ~] [file tail ~] td1]
file attributes $td1name -permissions 0000
- set msg [list [catch {file copy td2 ~/td1} msg] $msg]
+ file copy td2 ~/td1
+} -returnCodes error -cleanup {
file attributes $td1name -permissions 0755
file delete -force ~/td1
- set msg
-} {1 {error copying "td2" to "~/td1/td2": permission denied}}
-test fCmd-6.26 {CopyRenameOneFile: doesn't use original name} \
- {unixOnly notRoot} {
+} -result {error copying "td2" to "~/td1/td2": permission denied}
+test fCmd-6.26 {CopyRenameOneFile: doesn't use original name} -setup {
cleanup
+} -constraints {unix notRoot} -body {
file mkdir ~/td1/td2
set td2name [file join [file dirname ~] [file tail ~] td1 td2]
file attributes $td2name -permissions 0000
- set msg [list [catch {file copy ~/td1 td1} msg] $msg]
+ file copy ~/td1 td1
+} -returnCodes error -cleanup {
file attributes $td2name -permissions 0755
file delete -force ~/td1
- set msg
-} "1 {error copying \"~/td1\" to \"td1\": \"[file join [file dirname ~] [file tail ~] td1 td2]\": permission denied}"
-test fCmd-6.27 {CopyRenameOneFile: TclpCopyDirectory failed} \
- {unixOnly notRoot xdev} {
+} -result "error copying \"~/td1\" to \"td1\": \"[file join $::env(HOME) td1 td2]\": permission denied"
+test fCmd-6.27 {CopyRenameOneFile: TclpCopyDirectory failed} -setup {
cleanup /tmp
+} -constraints {unix notRoot xdev} -returnCodes error -body {
file mkdir td1/td2/td3
file mkdir /tmp/td1
createfile /tmp/td1/tf1
- list [catch {file rename -force td1 /tmp} msg] $msg
-} {1 {error renaming "td1" to "/tmp/td1": file already exists}}
-test fCmd-6.28 {CopyRenameOneFile: TclpCopyDirectory failed} \
- {unixOnly notRoot xdev} {
+ file rename -force td1 /tmp
+} -result {error renaming "td1" to "/tmp/td1": file already exists}
+test fCmd-6.28 {CopyRenameOneFile: TclpCopyDirectory failed} -setup {
cleanup /tmp
+} -constraints {unix notRoot xdev} -body {
file mkdir td1/td2/td3
file attributes td1/td2/td3 -permissions 0000
- set msg [list [catch {file rename td1 /tmp} msg] $msg]
+ file rename td1 /tmp
+} -returnCodes error -cleanup {
file attributes td1/td2/td3 -permissions 0755
- set msg
-} {1 {error renaming "td1" to "/tmp/td1": "td1/td2/td3": permission denied}}
-test fCmd-6.29 {CopyRenameOneFile: TclpCopyDirectory passed} \
- {unixOnly notRoot xdev} {
+} -result {error renaming "td1" to "/tmp/td1": "td1/td2/td3": permission denied}
+test fCmd-6.29 {CopyRenameOneFile: TclpCopyDirectory passed} -setup {
cleanup /tmp
+} -constraints {unix notRoot xdev} -body {
file mkdir td1/td2/td3
file rename td1 /tmp
glob td* /tmp/td1/t*
-} {/tmp/td1/td2}
-test fCmd-6.30 {CopyRenameOneFile: TclpRemoveDirectory failed} \
- {unixOnly notRoot} {
+} -result {/tmp/td1/td2}
+test fCmd-6.30 {CopyRenameOneFile: TclpRemoveDirectory failed} -setup {
cleanup
+} -constraints {unix notRoot} -body {
file mkdir foo/bar
file attr foo -perm 040555
- set catchResult [catch {file rename foo/bar /tmp} msg]
- set msg [lindex [split $msg :] end]
+ file rename foo/bar /tmp
+} -returnCodes error -cleanup {
catch {file delete /tmp/bar}
catch {file attr foo -perm 040777}
catch {file delete -force foo}
- list $catchResult $msg
-} {1 { permission denied}}
-test fCmd-6.31 {CopyRenameOneFile: TclpDeleteFile passed} \
- {unixOnly notRoot xdev} {
+} -match glob -result {*: permission denied}
+test fCmd-6.31 {CopyRenameOneFile: TclpDeleteFile passed} -setup {
catch {cleanup /tmp}
+} -constraints {unix notRoot xdev} -body {
file mkdir /tmp/td1
createfile /tmp/td1/tf1
file rename /tmp/td1/tf1 tf1
list [file exists /tmp/td1/tf1] [file exists tf1]
-} {0 1}
-test fCmd-6.32 {CopyRenameOneFile: copy} {notRoot} {
+} -result {0 1}
+test fCmd-6.32 {CopyRenameOneFile: copy} -constraints {notRoot} -setup {
cleanup
- list [catch {file copy tf1 tf2} msg] $msg
-} {1 {error copying "tf1": no such file or directory}}
+} -returnCodes error -body {
+ file copy tf1 tf2
+} -result {error copying "tf1": no such file or directory}
catch {cleanup /tmp}
-test fCmd-7.1 {FileForceOption: none} {notRoot} {
+test fCmd-7.1 {FileForceOption: none} -constraints {notRoot} -setup {
cleanup
+} -returnCodes error -body {
file mkdir [file join tf1 tf2]
- list [catch {file delete tf1} msg] $msg
-} {1 {error deleting "tf1": directory not empty}}
+ file delete tf1
+} -result {error deleting "tf1": directory not empty}
test fCmd-7.2 {FileForceOption: -force} {notRoot} {
cleanup
file mkdir [file join tf1 tf2]
@@ -666,68 +690,77 @@ test fCmd-7.3 {FileForceOption: --} {notRoot} {
createfile -tf1
file delete -- -tf1
} {}
-test fCmd-7.4 {FileForceOption: bad option} {notRoot} {
+test fCmd-7.4 {FileForceOption: bad option} -constraints {notRoot} -setup {
createfile -tf1
- set msg [list [catch {file delete -tf1} msg] $msg]
+} -body {
+ file delete -tf1
+} -returnCodes error -cleanup {
file delete -- -tf1
- set msg
-} {1 {bad option "-tf1": should be -force or --}}
-test fCmd-7.5 {FileForceOption: multiple times through loop} {notRoot} {
+} -result {bad option "-tf1": should be -force or --}
+test fCmd-7.5 {FileForceOption: multiple times through loop} -setup {
+ cleanup
+} -constraints {notRoot} -returnCodes error -body {
createfile --
createfile -force
file delete -force -force -- -- -force
- list [catch {glob -- -- -force} msg] $msg
-} {1 {no files matched glob patterns "-- -force"}}
+ glob -- -- -force
+} -result {no files matched glob patterns "-- -force"}
test fCmd-8.1 {FileBasename: basename of ~user: argc == 1 && *path == ~} \
- {unixOnly notRoot knownBug} {
+ -constraints {unix notRoot knownBug} -body {
# Labelled knownBug because it is dangerous [Bug: 3881]
file mkdir td1
file attr td1 -perm 040000
- set result [list [catch {file rename ~$user td1} msg] $msg]
+ file rename ~$user td1
+} -returnCodes error -cleanup {
file delete -force td1
- set result
-} "1 {error renaming \"~$user\" to \"td1/[file tail ~$user]\": permission denied}"
-test fCmd-8.2 {FileBasename: basename of ~user: argc == 1 && *path == ~} {
+} -result "error renaming \"~$user\" to \"td1/[file tail ~$user]\": permission denied"
+test fCmd-8.2 {FileBasename: basename of ~user: argc == 1 && *path == ~} \
+ {unix notRoot} {
string equal [file tail ~$user] ~$user
} 0
-test fCmd-8.3 {file copy and path translation: ensure correct error} {
- list [catch {file copy ~ [file join this file doesnt exist]} res] $res
-} [list 1 \
- "error copying \"~\" to \"[file join this file doesnt exist]\":\
- no such file or directory"]
+test fCmd-8.3 {file copy and path translation: ensure correct error} -body {
+ file copy ~ [file join this file doesnt exist]
+} -returnCodes error -result [subst \
+ {error copying "~" to "[file join this file doesnt exist]": no such file or directory}]
-test fCmd-9.1 {file rename: comprehensive: EACCES} {unixOnly notRoot} {
+test fCmd-9.1 {file rename: comprehensive: EACCES} -setup {
cleanup
+} -constraints {unix notRoot} -body {
file mkdir td1
file mkdir td2
file attr td2 -perm 040000
- set result [list [catch {file rename td1 td2/} msg] $msg]
+ file rename td1 td2/
+} -returnCodes error -cleanup {
file delete -force td2
file delete -force td1
- set result
-} {1 {error renaming "td1" to "td2/td1": permission denied}}
-test fCmd-9.2 {file rename: comprehensive: source doesn't exist} {notRoot} {
+} -result {error renaming "td1" to "td2/td1": permission denied}
+test fCmd-9.2 {file rename: comprehensive: source doesn't exist} -setup {
cleanup
- list [catch {file rename tf1 tf2} msg] $msg
-} {1 {error renaming "tf1": no such file or directory}}
-test fCmd-9.3 {file rename: comprehensive: file to new name} {notRoot testchmod} {
+} -constraints {notRoot} -returnCodes error -body {
+ file rename tf1 tf2
+} -result {error renaming "tf1": no such file or directory}
+test fCmd-9.3 {file rename: comprehensive: file to new name} -setup {
cleanup
+} -constraints {notRoot testchmod} -body {
createfile tf1
createfile tf2
testchmod 444 tf2
file rename tf1 tf3
file rename tf2 tf4
list [lsort [glob tf*]] [file writable tf3] [file writable tf4]
-} {{tf3 tf4} 1 0}
-test fCmd-9.4 {file rename: comprehensive: dir to new name} {unixOrPc notRoot testchmod win2000orXP} {
+} -result {{tf3 tf4} 1 0}
+test fCmd-9.4 {file rename: comprehensive: dir to new name} -setup {
cleanup
+} -constraints {unixOrPc notRoot testchmod notDarwin9 win2000orXP} -body {
file mkdir td1 td2
testchmod 555 td2
file rename td1 td3
file rename td2 td4
list [lsort [glob td*]] [file writable td3] [file writable td4]
-} {{td3 td4} 1 0}
+} -cleanup {
+ cleanup
+} -result {{td3 td4} 1 0}
test fCmd-9.5 {file rename: comprehensive: file to self} {notRoot testchmod} {
cleanup
createfile tf1 tf1
@@ -736,18 +769,20 @@ test fCmd-9.5 {file rename: comprehensive: file to self} {notRoot testchmod} {
file rename -force tf1 tf1
file rename -force tf2 tf2
list [contents tf1] [contents tf2] [file writable tf1] [file writable tf2]
-} {tf1 tf2 1 0}
-test fCmd-9.6 {file rename: comprehensive: dir to self} {notRoot unixOrPc testchmod win2000orXP} {
+} {tf1 tf2 1 0}
+test fCmd-9.6 {file rename: comprehensive: dir to self} -setup {
cleanup
+} -constraints {notRoot unixOrPc testchmod win2000orXP} -body {
file mkdir td1
file mkdir td2
testchmod 555 td2
file rename -force td1 .
file rename -force td2 .
list [lsort [glob td*]] [file writable td1] [file writable td2]
-} {{td1 td2} 1 0}
-test fCmd-9.7 {file rename: comprehensive: file to existing file} {notRoot testchmod} {
+} -result {{td1 td2} 1 0}
+test fCmd-9.7 {file rename: comprehensive: file to existing file} -setup {
cleanup
+} -constraints {notRoot testchmod} -body {
createfile tf1
createfile tf2
createfile tfs1
@@ -767,13 +802,14 @@ test fCmd-9.7 {file rename: comprehensive: file to existing file} {notRoot testc
file rename -force tfs2 tfd2
file rename -force tfs3 tfd3
file rename -force tfs4 tfd4
- list [lsort [glob tf*]] $msg [file writable tfd1] [file writable tfd2] [file writable tfd3] [file writable tfd4]
-} {{tf1 tf2 tfd1 tfd2 tfd3 tfd4} {1 {error renaming "tf1" to "tf2": file already exists}} 1 1 0 0}
-test fCmd-9.8 {file rename: comprehensive: dir to empty dir} {notRoot testchmod notNetworkFilesystem} {
+ list [lsort [glob tf*]] $msg [file writable tfd1] [file writable tfd2] [file writable tfd3] [file writable tfd4]
+} -result {{tf1 tf2 tfd1 tfd2 tfd3 tfd4} {1 {error renaming "tf1" to "tf2": file already exists}} 1 1 0 0}
+test fCmd-9.8 {file rename: comprehensive: dir to empty dir} -setup {
+ cleanup
+} -constraints {notRoot testchmod notNetworkFilesystem} -body {
# Under unix, you can rename a read-only directory, but you can't
# move it into another directory.
- cleanup
file mkdir td1
file mkdir [file join td2 td1]
file mkdir tds1
@@ -784,47 +820,48 @@ test fCmd-9.8 {file rename: comprehensive: dir to empty dir} {notRoot testchmod
file mkdir [file join tdd2 tds2]
file mkdir [file join tdd3 tds3]
file mkdir [file join tdd4 tds4]
- if {$tcl_platform(platform) != "unix" && $tcl_platform(platform) != "macintosh"} {
+ if {![testConstraint unix]} {
testchmod 555 tds3
testchmod 555 tds4
}
- if {$tcl_platform(platform) != "macintosh"} {
- testchmod 555 [file join tdd2 tds2]
- testchmod 555 [file join tdd4 tds4]
- }
+ testchmod 555 [file join tdd2 tds2]
+ testchmod 555 [file join tdd4 tds4]
set msg [list [catch {file rename td1 td2} msg] $msg]
file rename -force tds1 tdd1
file rename -force tds2 tdd2
file rename -force tds3 tdd3
file rename -force tds4 tdd4
- if {$tcl_platform(platform) != "unix" && $tcl_platform(platform) != "macintosh"} {
- set w3 [file writable [file join tdd3 tds3]]
- set w4 [file writable [file join tdd4 tds4]]
- } else {
+ if {[testConstraint unix]} {
set w3 0
set w4 0
+ } else {
+ set w3 [file writable [file join tdd3 tds3]]
+ set w4 [file writable [file join tdd4 tds4]]
}
list [lsort [glob td*]] $msg [file writable [file join tdd1 tds1]] \
[file writable [file join tdd2 tds2]] $w3 $w4
-} [subst {{td1 td2 tdd1 tdd2 tdd3 tdd4} {1 {error renaming "td1" to "[file join td2 td1]": file already exists}} 1 1 0 0}]
-test fCmd-9.9 {file rename: comprehensive: dir to non-empty dir} {notRoot testchmod} {
+} -result [subst {{td1 td2 tdd1 tdd2 tdd3 tdd4} {1 {error renaming "td1" to "[file join td2 td1]": file already exists}} 1 1 0 0}]
+# Test can hit EEXIST or EBUSY, depending on underlying filesystem
+test fCmd-9.9 {file rename: comprehensive: dir to non-empty dir} -setup {
cleanup
+} -constraints {notRoot testchmod} -body {
file mkdir tds1
file mkdir tds2
file mkdir [file join tdd1 tds1 xxx]
file mkdir [file join tdd2 tds2 xxx]
- if {!([testConstraint unix] || [testConstraint winVista]) && $tcl_platform(platform) != "macintosh"} {
+ if {!([testConstraint unix] || [testConstraint winVista])} {
testchmod 555 tds2
}
set a1 [list [catch {file rename -force tds1 tdd1} msg] $msg]
set a2 [list [catch {file rename -force tds2 tdd2} msg] $msg]
- if {!([testConstraint unix] || [testConstraint winVista]) && $tcl_platform(platform) != "macintosh"} {
- set w2 [file writable tds2]
- } else {
+ if {[testConstraint unix] || [testConstraint winVista]} {
set w2 0
+ } else {
+ set w2 [file writable tds2]
}
list [lsort [glob td*]] $a1 $a2 [file writable tds1] $w2
-} [subst {{tdd1 tdd2 tds1 tds2} {1 {error renaming "tds1" to "[file join tdd1 tds1]": file already exists}} {1 {error renaming "tds2" to "[file join tdd2 tds2]": file already exists}} 1 0}]
+} -match glob -result \
+ [subst {{tdd1 tdd2 tds1 tds2} {1 {error renaming "tds1" to "[file join tdd1 tds1]": file *}} {1 {error renaming "tds2" to "[file join tdd2 tds2]": file *}} 1 0}]
test fCmd-9.10 {file rename: comprehensive: file to new name and dir} {notRoot testchmod} {
cleanup
createfile tf1
@@ -841,63 +878,93 @@ test fCmd-9.11 {file rename: comprehensive: dir to new name and dir} {notRoot te
file mkdir td1
file mkdir td2
file mkdir td3
- if {!([testConstraint unix] || [testConstraint winVista]) && $tcl_platform(platform) != "macintosh"} {
+ if {!([testConstraint unix] || [testConstraint winVista])} {
testchmod 555 td2
}
file rename td1 [file join td3 td3]
file rename td2 [file join td3 td4]
- if {!([testConstraint unix] || [testConstraint winVista]) && $tcl_platform(platform) != "macintosh"} {
- set w4 [file writable [file join td3 td4]]
- } else {
+ if {[testConstraint unix] || [testConstraint winVista]} {
set w4 0
+ } else {
+ set w4 [file writable [file join td3 td4]]
}
list [lsort [glob td*]] [lsort [glob -directory td3 t*]] \
[file writable [file join td3 td3]] $w4
} [subst {td3 {[file join td3 td3] [file join td3 td4]} 1 0}]
-test fCmd-9.12 {file rename: comprehensive: target exists} {notRoot testchmod notNetworkFilesystem} {
+test fCmd-9.12 {file rename: comprehensive: target exists} -setup {
cleanup
+} -constraints {notRoot testchmod notNetworkFilesystem} -body {
file mkdir [file join td1 td2] [file join td2 td1]
- if {$tcl_platform(platform) != "macintosh"} {
- testchmod 555 [file join td2 td1]
- }
+ testchmod 555 [file join td2 td1]
file mkdir [file join td3 td4] [file join td4 td3]
file rename -force td3 td4
- set msg [list [file exists td3] [file exists [file join td4 td3 td4]] \
- [catch {file rename td1 td2} msg] $msg]
- if {$tcl_platform(platform) != "macintosh"} {
- testchmod 755 [file join td2 td1]
- }
- set msg
-} [subst {0 1 1 {error renaming "td1" to "[file join td2 td1]": file already exists}}]
-test fCmd-9.13 {file rename: comprehensive: can't overwrite target} {notRoot} {
- cleanup
+ list [file exists td3] [file exists [file join td4 td3 td4]] \
+ [catch {file rename td1 td2} msg] $msg
+} -cleanup {
+ testchmod 755 [file join td2 td1]
+} -result [subst {0 1 1 {error renaming "td1" to "[file join td2 td1]": file already exists}}]
+# Test can hit EEXIST or EBUSY, depending on underlying filesystem
+test fCmd-9.13 {file rename: comprehensive: can't overwrite target} -setup {
+ cleanup
+} -constraints {notRoot} -body {
file mkdir [file join td1 td2] [file join td2 td1 td4]
- list [catch {file rename -force td1 td2} msg] $msg
-} [subst {1 {error renaming "td1" to "[file join td2 td1]": file already exists}}]
+ file rename -force td1 td2
+} -returnCodes error -match glob -result \
+ [subst {error renaming "td1" to "[file join td2 td1]": file *}]
test fCmd-9.14 {file rename: comprehensive: dir into self} {notRoot} {
cleanup
file mkdir td1
list [glob td*] [list [catch {file rename td1 td1} msg] $msg]
} [subst {td1 {1 {error renaming "td1" to "[file join td1 td1]": trying to rename a volume or move a directory into itself}}}]
-test fCmd-9.15 {file rename: comprehensive: source and target incompatible} \
- {notRoot} {
+test fCmd-9.14.1 {file rename: comprehensive: dir into self} {notRoot} {
+ cleanup
+ file mkdir td1
+ file rename td1 td1x
+ file rename td1x td1
+ set msg "ok"
+} {ok}
+test fCmd-9.14.2 {file rename: comprehensive: dir into self} -setup {
+ cleanup
+ set dir [pwd]
+} -constraints {nonPortable notRoot} -body {
+ file mkdir td1
+ cd td1
+ file rename [file join .. td1] [file join .. td1x]
+} -returnCodes error -cleanup {
+ cd $dir
+} -result [subst {error renaming "[file join .. td1]" to "[file join .. td1x]": permission denied}]
+test fCmd-9.14.3 {file rename: comprehensive: dir into self} -setup {
+ cleanup
+ set dir [pwd]
+} -constraints {notRoot} -body {
+ file mkdir td1
+ cd td1
+ file rename [file join .. td1] [file join .. td1 foo]
+} -returnCodes error -cleanup {
+ cd $dir
+} -result [subst {error renaming "[file join .. td1]" to "[file join .. td1 foo]": trying to rename a volume or move a directory into itself}]
+test fCmd-9.15 {file rename: comprehensive: source and target incompatible} -setup {
cleanup
+} -constraints {notRoot} -returnCodes error -body {
file mkdir td1
createfile tf1
- list [catch {file rename -force td1 tf1} msg] $msg
-} {1 {can't overwrite file "tf1" with directory "td1"}}
-test fCmd-9.16 {file rename: comprehensive: source and target incompatible} \
- {notRoot} {
+ file rename -force td1 tf1
+} -cleanup {
cleanup
+} -result {can't overwrite file "tf1" with directory "td1"}
+test fCmd-9.16 {file rename: comprehensive: source and target incompatible} -setup {
+ cleanup
+} -constraints {notRoot} -returnCodes error -body {
file mkdir td1/tf1
createfile tf1
- list [catch {file rename -force tf1 td1} msg] $msg
-} [subst {1 {can't overwrite directory "[file join td1 tf1]" with file "tf1"}}]
+ file rename -force tf1 td1
+} -result [subst {can't overwrite directory "[file join td1 tf1]" with file "tf1"}]
-test fCmd-10.1 {file copy: comprehensive: source doesn't exist} {notRoot} {
+test fCmd-10.1 {file copy: comprehensive: source doesn't exist} -setup {
cleanup
- list [catch {file copy tf1 tf2} msg] $msg
-} {1 {error copying "tf1": no such file or directory}}
+} -constraints {notRoot} -returnCodes error -body {
+ file copy tf1 tf2
+} -result {error copying "tf1": no such file or directory}
test fCmd-10.2 {file copy: comprehensive: file to new name} {notRoot testchmod} {
cleanup
createfile tf1 tf1
@@ -907,37 +974,38 @@ test fCmd-10.2 {file copy: comprehensive: file to new name} {notRoot testchmod}
file copy tf2 tf4
list [lsort [glob tf*]] [contents tf3] [contents tf4] [file writable tf3] [file writable tf4]
} {{tf1 tf2 tf3 tf4} tf1 tf2 1 0}
-test fCmd-10.3 {file copy: comprehensive: dir to new name} {notRoot unixOrPc 95or98 testchmod} {
+test fCmd-10.3 {file copy: comprehensive: dir to new name} -setup {
cleanup
+} -constraints {notRoot unixOrPc 95or98 testchmod} -body {
file mkdir [file join td1 tdx]
file mkdir [file join td2 tdy]
testchmod 555 td2
file copy td1 td3
file copy td2 td4
- set msg [list [lsort [glob td*]] [glob -directory td3 t*] \
- [glob -directory td4 t*] [file writable td3] [file writable td4]]
- if {$tcl_platform(platform) != "macintosh"} {
- testchmod 755 td2
- testchmod 755 td4
- }
- set msg
-} [subst {{td1 td2 td3 td4} [file join td3 tdx] [file join td4 tdy] 1 0}]
-test fCmd-10.3.1 {file copy: comprehensive: dir to new name} {notRoot pc 2000orNewer testchmod} {
- # On Windows with ACLs, copying a directory is defined like this
+ list [lsort [glob td*]] [glob -directory td3 t*] \
+ [glob -directory td4 t*] [file writable td3] [file writable td4]
+} -cleanup {
+ testchmod 755 td2
+ testchmod 755 td4
+} -result [list {td1 td2 td3 td4} [file join td3 tdx] [file join td4 tdy] 1 0]
+test fCmd-10.3.1 {file copy: comprehensive: dir to new name} -setup {
cleanup
+} -constraints {notRoot win 2000orNewer testchmod} -body {
+ # On Windows with ACLs, copying a directory is defined like this
file mkdir [file join td1 tdx]
file mkdir [file join td2 tdy]
testchmod 555 td2
file copy td1 td3
file copy td2 td4
- set msg [list [lsort [glob td*]] [glob -directory td3 t*] \
- [glob -directory td4 t*] [file writable td3] [file writable td4]]
+ list [lsort [glob td*]] [glob -directory td3 t*] \
+ [glob -directory td4 t*] [file writable td3] [file writable td4]
+} -cleanup {
testchmod 755 td2
testchmod 755 td4
- set msg
-} [subst {{td1 td2 td3 td4} [file join td3 tdx] [file join td4 tdy] 1 1}]
-test fCmd-10.4 {file copy: comprehensive: file to existing file} {notRoot testchmod} {
+} -result [list {td1 td2 td3 td4} [file join td3 tdx] [file join td4 tdy] 1 1]
+test fCmd-10.4 {file copy: comprehensive: file to existing file} -setup {
cleanup
+} -constraints {notRoot testchmod} -body {
createfile tf1
createfile tf2
createfile tfs1
@@ -957,10 +1025,11 @@ test fCmd-10.4 {file copy: comprehensive: file to existing file} {notRoot testch
file copy -force tfs2 tfd2
file copy -force tfs3 tfd3
file copy -force tfs4 tfd4
- list [lsort [glob tf*]] $msg [file writable tfd1] [file writable tfd2] [file writable tfd3] [file writable tfd4]
-} {{tf1 tf2 tfd1 tfd2 tfd3 tfd4 tfs1 tfs2 tfs3 tfs4} {1 {error copying "tf1" to "tf2": file already exists}} 1 1 0 0}
-test fCmd-10.5 {file copy: comprehensive: dir to empty dir} {notRoot testchmod} {
+ list [lsort [glob tf*]] $msg [file writable tfd1] [file writable tfd2] [file writable tfd3] [file writable tfd4]
+} -result {{tf1 tf2 tfd1 tfd2 tfd3 tfd4 tfs1 tfs2 tfs3 tfs4} {1 {error copying "tf1" to "tf2": file already exists}} 1 1 0 0}
+test fCmd-10.5 {file copy: comprehensive: dir to empty dir} -setup {
cleanup
+} -constraints {notRoot testchmod} -body {
file mkdir td1
file mkdir [file join td2 td1]
file mkdir tds1
@@ -971,22 +1040,20 @@ test fCmd-10.5 {file copy: comprehensive: dir to empty dir} {notRoot testchmod}
file mkdir [file join tdd2 tds2]
file mkdir [file join tdd3 tds3]
file mkdir [file join tdd4 tds4]
- if {$tcl_platform(platform) != "macintosh"} {
- testchmod 555 tds3
- testchmod 555 tds4
- testchmod 555 [file join tdd2 tds2]
- testchmod 555 [file join tdd4 tds4]
- }
+ testchmod 555 tds3
+ testchmod 555 tds4
+ testchmod 555 [file join tdd2 tds2]
+ testchmod 555 [file join tdd4 tds4]
set a1 [list [catch {file copy td1 td2} msg] $msg]
set a2 [list [catch {file copy -force tds1 tdd1} msg] $msg]
set a3 [catch {file copy -force tds2 tdd2}]
set a4 [catch {file copy -force tds3 tdd3}]
set a5 [catch {file copy -force tds4 tdd4}]
- list [lsort [glob td*]] $a1 $a2 $a3 $a4 $a5
-} [subst {{td1 td2 tdd1 tdd2 tdd3 tdd4 tds1 tds2 tds3 tds4} {1 {error copying "td1" to "[file join td2 td1]": file already exists}} {1 {error copying "tds1" to "[file join tdd1 tds1]": file already exists}} 1 1 1}]
-test fCmd-10.6 {file copy: comprehensive: dir to non-empty dir} \
- {notRoot unixOrPc testchmod} {
+ list [lsort [glob td*]] $a1 $a2 $a3 $a4 $a5
+} -result [subst {{td1 td2 tdd1 tdd2 tdd3 tdd4 tds1 tds2 tds3 tds4} {1 {error copying "td1" to "[file join td2 td1]": file already exists}} {1 {error copying "tds1" to "[file join tdd1 tds1]": file already exists}} 1 1 1}]
+test fCmd-10.6 {file copy: comprehensive: dir to non-empty dir} -setup {
cleanup
+} -constraints {notRoot unixOrPc testchmod} -body {
file mkdir tds1
file mkdir tds2
file mkdir [file join tdd1 tds1 xxx]
@@ -995,9 +1062,10 @@ test fCmd-10.6 {file copy: comprehensive: dir to non-empty dir} \
set a1 [list [catch {file copy -force tds1 tdd1} msg] $msg]
set a2 [list [catch {file copy -force tds2 tdd2} msg] $msg]
list [lsort [glob td*]] $a1 $a2 [file writable tds1] [file writable tds2]
-} [subst {{tdd1 tdd2 tds1 tds2} {1 {error copying "tds1" to "[file join tdd1 tds1]": file already exists}} {1 {error copying "tds2" to "[file join tdd2 tds2]": file already exists}} 1 0}]
-test fCmd-10.7 {file rename: comprehensive: file to new name and dir} {notRoot testchmod} {
+} -result [subst {{tdd1 tdd2 tds1 tds2} {1 {error copying "tds1" to "[file join tdd1 tds1]": file already exists}} {1 {error copying "tds2" to "[file join tdd2 tds2]": file already exists}} 1 0}]
+test fCmd-10.7 {file rename: comprehensive: file to new name and dir} -setup {
cleanup
+} -constraints {notRoot testchmod} -body {
createfile tf1
createfile tf2
file mkdir td1
@@ -1006,10 +1074,10 @@ test fCmd-10.7 {file rename: comprehensive: file to new name and dir} {notRoot t
file copy tf2 [file join td1 tf4]
list [lsort [glob tf*]] [lsort [glob -directory td1 t*]] \
[file writable [file join td1 tf3]] [file writable [file join td1 tf4]]
-} [subst {{tf1 tf2} {[file join td1 tf3] [file join td1 tf4]} 1 0}]
-test fCmd-10.8 {file rename: comprehensive: dir to new name and dir} \
- {notRoot unixOrPc 95or98 testchmod} {
+} -result [subst {{tf1 tf2} {[file join td1 tf3] [file join td1 tf4]} 1 0}]
+test fCmd-10.8 {file rename: comprehensive: dir to new name and dir} -setup {
cleanup
+} -constraints {notRoot unixOrPc 95or98 testchmod} -body {
file mkdir td1
file mkdir td2
file mkdir td3
@@ -1018,11 +1086,11 @@ test fCmd-10.8 {file rename: comprehensive: dir to new name and dir} \
file copy td2 [file join td3 td4]
list [lsort [glob td*]] [lsort [glob -directory td3 t*]] \
[file writable [file join td3 td3]] [file writable [file join td3 td4]]
-} [subst {{td1 td2 td3} {[file join td3 td3] [file join td3 td4]} 1 0}]
-test fCmd-10.8.1 {file rename: comprehensive: dir to new name and dir} \
- {notRoot pc 2000orNewer testchmod} {
- # On Windows with ACLs, copying a directory is defined like this
+} -result [subst {{td1 td2 td3} {[file join td3 td3] [file join td3 td4]} 1 0}]
+test fCmd-10.8.1 {file rename: comprehensive: dir to new name and dir} -setup {
cleanup
+} -constraints {notRoot win 2000orNewer testchmod} -body {
+ # On Windows with ACLs, copying a directory is defined like this
file mkdir td1
file mkdir td2
file mkdir td3
@@ -1031,605 +1099,577 @@ test fCmd-10.8.1 {file rename: comprehensive: dir to new name and dir} \
file copy td2 [file join td3 td4]
list [lsort [glob td*]] [lsort [glob -directory td3 t*]] \
[file writable [file join td3 td3]] [file writable [file join td3 td4]]
-} [subst {{td1 td2 td3} {[file join td3 td3] [file join td3 td4]} 1 1}]
-test fCmd-10.9 {file copy: comprehensive: source and target incompatible} \
- {notRoot} {
+} -result [subst {{td1 td2 td3} {[file join td3 td3] [file join td3 td4]} 1 1}]
+test fCmd-10.9 {file copy: comprehensive: source and target incompatible} -setup {
cleanup
+} -constraints {notRoot} -returnCodes error -body {
file mkdir td1
createfile tf1
- list [catch {file copy -force td1 tf1} msg] $msg
-} {1 {can't overwrite file "tf1" with directory "td1"}}
-test fCmd-10.10 {file copy: comprehensive: source and target incompatible} \
- {notRoot} {
+ file copy -force td1 tf1
+} -result {can't overwrite file "tf1" with directory "td1"}
+test fCmd-10.10 {file copy: comprehensive: source and target incompatible} -setup {
cleanup
+} -constraints {notRoot} -returnCodes error -body {
file mkdir [file join td1 tf1]
createfile tf1
- list [catch {file copy -force tf1 td1} msg] $msg
-} [subst {1 {can't overwrite directory "[file join td1 tf1]" with file "tf1"}}]
-test fCmd-10.11 {file copy: copy to empty file name} {
+ file copy -force tf1 td1
+} -result [subst {can't overwrite directory "[file join td1 tf1]" with file "tf1"}]
+test fCmd-10.11 {file copy: copy to empty file name} -setup {
cleanup
+} -returnCodes error -body {
createfile tf1
- list [catch {file copy tf1 ""} msg] $msg
-} {1 {error copying "tf1" to "": no such file or directory}}
-test fCmd-10.12 {file rename: rename to empty file name} {
+ file copy tf1 ""
+} -result {error copying "tf1" to "": no such file or directory}
+test fCmd-10.12 {file rename: rename to empty file name} -setup {
cleanup
+} -returnCodes error -body {
createfile tf1
- list [catch {file rename tf1 ""} msg] $msg
-} {1 {error renaming "tf1" to "": no such file or directory}}
-cleanup
+ file rename tf1 ""
+} -result {error renaming "tf1" to "": no such file or directory}
+cleanup
-# old tests
+# old tests
-test fCmd-11.1 {TclFileRenameCmd: -- option } {notRoot} {
+test fCmd-11.1 {TclFileRenameCmd: -- option } -constraints notRoot -setup {
catch {file delete -force -- -tfa1}
+} -body {
set s [createfile -tfa1]
file rename -- -tfa1 tfa2
- set result [expr [checkcontent tfa2 $s] && ![file exists -tfa1]]
+ list [checkcontent tfa2 $s] [file exists -tfa1]
+} -cleanup {
file delete tfa2
- set result
-} {1}
-
-test fCmd-11.2 {TclFileRenameCmd: bad option } {notRoot} {
+} -result {1 0}
+test fCmd-11.2 {TclFileRenameCmd: bad option } -constraints notRoot -setup {
catch {file delete -force -- tfa1}
+} -body {
set s [createfile tfa1]
- set r1 [catch {file rename -x tfa1 tfa2}]
- set result [expr $r1 && [checkcontent tfa1 $s] && ![file exists tfa2]]
+ list [catch {file rename -x tfa1 tfa2}] \
+ [checkcontent tfa1 $s] [file exists tfa2]
+} -cleanup {
file delete tfa1
- set result
-} {1}
-
+} -result {1 1 0}
test fCmd-11.3 {TclFileRenameCmd: bad \# args} {
catch {file rename -- }
} {1}
-
-test fCmd-11.4 {TclFileRenameCmd: target filename translation failing} {notRoot} {
- global env
- set temp $env(HOME)
- unset env(HOME)
- set result [catch {file rename tfa ~/foobar }]
- set env(HOME) $temp
- set result
- } {1}
-
-test fCmd-11.5 {TclFileRenameCmd: > 1 source & target is not a dir} {notRoot} {
+test fCmd-11.4 {TclFileRenameCmd: target filename translation failing} -setup {
+ set temp $::env(HOME)
+} -constraints notRoot -body {
+ global env
+ unset env(HOME)
+ catch { file rename tfa ~/foobar }
+} -cleanup {
+ set ::env(HOME) $temp
+} -result 1
+test fCmd-11.5 {TclFileRenameCmd: > 1 source & target is not a dir} -setup {
catch {file delete -force -- tfa1 tfa2 tfa3}
- createfile tfa1
- createfile tfa2
- createfile tfa3
- set result [catch {file rename tfa1 tfa2 tfa3}]
+} -constraints {notRoot} -body {
+ createfile tfa1
+ createfile tfa2
+ createfile tfa3
+ catch {file rename tfa1 tfa2 tfa3}
+} -cleanup {
file delete tfa1 tfa2 tfa3
- set result
-} {1}
-
-test fCmd-11.6 {TclFileRenameCmd: : single file into directory} {notRoot} {
+} -result {1}
+test fCmd-11.6 {TclFileRenameCmd: : single file into directory} -setup {
catch {file delete -force -- tfa1 tfad}
+} -constraints {notRoot} -body {
set s [createfile tfa1]
file mkdir tfad
file rename tfa1 tfad
- set result [expr [checkcontent tfad/tfa1 $s] && ![file exists tfa1]]
+ list [checkcontent tfad/tfa1 $s] [file exists tfa1]
+} -cleanup {
file delete -force tfad
- set result
-} {1}
-
-test fCmd-11.7 {TclFileRenameCmd: : multiple files into directory} {notRoot} {
+} -result {1 0}
+test fCmd-11.7 {TclFileRenameCmd: : multiple files into directory} -setup {
catch {file delete -force -- tfa1 tfa2 tfad}
- set s1 [createfile tfa1 ]
- set s2 [createfile tfa2 ]
+} -constraints {notRoot} -body {
+ set s1 [createfile tfa1]
+ set s2 [createfile tfa2]
file mkdir tfad
file rename tfa1 tfa2 tfad
- set r1 [checkcontent tfad/tfa1 $s1]
- set r2 [checkcontent tfad/tfa2 $s2]
-
- set result [expr $r1 && $r2 && ![file exists tfa1] && ![file exists tfa2]]
-
+ list [checkcontent tfad/tfa1 $s1] [checkcontent tfad/tfa2 $s2] \
+ [file exists tfa1] [file exists tfa2]
+} -cleanup {
file delete -force tfad
- set result
-} {1}
-
-test fCmd-11.8 {TclFileRenameCmd: error renaming file to directory} {notRoot} {
+} -result {1 1 0 0}
+test fCmd-11.8 {TclFileRenameCmd: error renaming file to directory} -setup {
catch {file delete -force -- tfa tfad}
- set s [createfile tfa ]
+} -constraints {notRoot} -body {
+ set s [createfile tfa]
file mkdir tfad
file mkdir tfad/tfa
- set r1 [catch {file rename tfa tfad}]
- set r2 [checkcontent tfa $s]
- set r3 [file isdir tfad]
- set result [expr $r1 && $r2 && $r3 ]
+ list [catch {file rename tfa tfad}] [checkcontent tfa $s] [file isdir tfad]
+} -cleanup {
file delete -force tfa tfad
- set result
-} {1}
+} -result {1 1 1}
#
# Coverage tests for renamefile() ;
#
-test fCmd-12.1 {renamefile: source filename translation failing} {notRoot} {
+test fCmd-12.1 {renamefile: source filename translation failing} -setup {
+ set temp $::env(HOME)
+} -constraints {notRoot} -body {
global env
- set temp $env(HOME)
unset env(HOME)
- set result [catch {file rename ~/tfa1 tfa2}]
- set env(HOME) $temp
- set result
-} {1}
-
-test fCmd-12.2 {renamefile: src filename translation failing} {notRoot} {
+ catch {file rename ~/tfa1 tfa2}
+} -cleanup {
+ set ::env(HOME) $temp
+} -result {1}
+test fCmd-12.2 {renamefile: src filename translation failing} -setup {
+ set temp $::env(HOME)
+} -constraints {notRoot} -body {
global env
- set temp $env(HOME)
unset env(HOME)
set s [createfile tfa1]
file mkdir tfad
- set result [catch {file rename tfa1 ~/tfa2 tfad}]
- set env(HOME) $temp
+ catch {file rename tfa1 ~/tfa2 tfad}
+} -cleanup {
+ set ::env(HOME) $temp
file delete -force tfad
- set result
-} {1}
-
-test fCmd-12.3 {renamefile: stat failing on source} {notRoot} {
+} -result {1}
+test fCmd-12.3 {renamefile: stat failing on source} -setup {
catch {file delete -force -- tfa1 tfa2}
- set r1 [catch {file rename tfa1 tfa2}]
- expr {$r1 && ![file exists tfa1] && ![file exists tfa2]}
-} {1}
-
-test fCmd-12.4 {renamefile: error renaming file to directory} {notRoot} {
+} -constraints {notRoot} -body {
+ list [catch {file rename tfa1 tfa2}] [file exists tfa1] [file exists tfa2]
+} -result {1 0 0}
+test fCmd-12.4 {renamefile: error renaming file to directory} -setup {
catch {file delete -force -- tfa tfad}
- set s1 [createfile tfa ]
+} -constraints {notRoot} -body {
+ set s1 [createfile tfa]
file mkdir tfad
file mkdir tfad/tfa
- set r1 [catch {file rename tfa tfad}]
- set r2 [checkcontent tfa $s1]
- set r3 [file isdir tfad/tfa]
- set result [expr $r1 && $r2 && $r3]
+ list [catch {file rename tfa tfad}] [checkcontent tfa $s1] \
+ [file isdir tfad/tfa]
+} -cleanup {
file delete -force tfa tfad
- set result
-} {1}
-
-test fCmd-12.5 {renamefile: error renaming directory to file} {notRoot} {
+} -result {1 1 1}
+test fCmd-12.5 {renamefile: error renaming directory to file} -setup {
catch {file delete -force -- tfa tfad}
+} -constraints {notRoot} -body {
file mkdir tfa
file mkdir tfad
set s [createfile tfad/tfa]
- set r1 [catch {file rename tfa tfad}]
- set r2 [checkcontent tfad/tfa $s]
- set r3 [file isdir tfad]
- set r4 [file isdir tfa]
- set result [expr $r1 && $r2 && $r3 && $r4 ]
+ list [catch {file rename tfa tfad}] [checkcontent tfad/tfa $s] \
+ [file isdir tfad] [file isdir tfa]
+} -cleanup {
file delete -force tfa tfad
- set result
-} {1}
-
-test fCmd-12.6 {renamefile: TclRenameFile succeeding} {notRoot} {
+} -result {1 1 1 1}
+test fCmd-12.6 {renamefile: TclRenameFile succeeding} -setup {
catch {file delete -force -- tfa1 tfa2}
+} -constraints {notRoot} -body {
set s [createfile tfa1]
file rename tfa1 tfa2
- set result [expr [checkcontent tfa2 $s] && ![file exists tfa1]]
+ list [checkcontent tfa2 $s] [file exists tfa1]
+} -cleanup {
file delete tfa2
- set result
-} {1}
-
-test fCmd-12.7 {renamefile: renaming directory into offspring} {notRoot} {
+} -result {1 0}
+test fCmd-12.7 {renamefile: renaming directory into offspring} -setup {
catch {file delete -force -- tfad}
+} -constraints {notRoot} -body {
file mkdir tfad
file mkdir tfad/dir
- set result [catch {file rename tfad tfad/dir}]
- file delete -force tfad
- set result
-} {1}
-
-test fCmd-12.8 {renamefile: generic error} {unixOnly notRoot} {
+ catch {file rename tfad tfad/dir}
+} -cleanup {
+ file delete -force tfad
+} -result {1}
+test fCmd-12.8 {renamefile: generic error} -setup {
catch {file delete -force -- tfa}
+} -constraints {unix notRoot} -body {
file mkdir tfa
file mkdir tfa/dir
file attributes tfa -permissions 0555
- set result [catch {file rename tfa/dir tfa2}]
- file attributes tfa -permissions 0777
+ catch {file rename tfa/dir tfa2}
+} -cleanup {
+ catch {file attributes tfa -permissions 0777}
file delete -force tfa
- set result
-} {1}
-
-
-test fCmd-12.9 {renamefile: moving a file across volumes} {unixOnly notRoot} {
+} -result {1}
+test fCmd-12.9 {renamefile: moving a file across volumes} -setup {
catch {file delete -force -- tfa /tmp/tfa}
- set s [createfile tfa ]
+} -constraints {unix notRoot} -body {
+ set s [createfile tfa]
file rename tfa /tmp
- set result [expr [checkcontent /tmp/tfa $s] && ![file exists tfa]]
+ list [checkcontent /tmp/tfa $s] [file exists tfa]
+} -cleanup {
file delete /tmp/tfa
- set result
-} {1}
-
-test fCmd-12.10 {renamefile: moving a directory across volumes } \
- {unixOnly notRoot} {
+} -result {1 0}
+test fCmd-12.10 {renamefile: moving a directory across volumes} -setup {
catch {file delete -force -- tfad /tmp/tfad}
+} -constraints {unix notRoot} -body {
file mkdir tfad
- set s [createfile tfad/a ]
+ set s [createfile tfad/a]
file rename tfad /tmp
- set restul [expr [checkcontent /tmp/tfad/a $s] && ![file exists tfad]]
+ list [checkcontent /tmp/tfad/a $s] [file exists tfad]
+} -cleanup {
file delete -force /tmp/tfad
- set result
-} {1}
+} -result {1 0}
#
# Coverage tests for TclCopyFilesCmd()
#
-test fCmd-13.1 {TclCopyFilesCmd: -force option} {notRoot} {
+test fCmd-13.1 {TclCopyFilesCmd: -force option} -constraints notRoot -setup {
catch {file delete -force -- tfa1}
+} -body {
set s [createfile tfa1]
file copy -force tfa1 tfa2
- set result [expr [checkcontent tfa2 $s] && [checkcontent tfa1 $s]]
+ list [checkcontent tfa2 $s] [checkcontent tfa1 $s]
+} -cleanup {
file delete tfa1 tfa2
- set result
-} {1}
-
-test fCmd-13.2 {TclCopyFilesCmd: -- option} {notRoot} {
+} -result {1 1}
+test fCmd-13.2 {TclCopyFilesCmd: -- option} -constraints {notRoot} -setup {
catch {file delete -force -- tfa1}
+} -body {
set s [createfile -tfa1]
file copy -- -tfa1 tfa2
- set result [expr [checkcontent tfa2 $s] && [checkcontent -tfa1 $s]]
+ list [checkcontent tfa2 $s] [checkcontent -tfa1 $s]
+} -cleanup {
file delete -- -tfa1 tfa2
- set result
-} {1}
-
-test fCmd-13.3 {TclCopyFilesCmd: bad option} {notRoot} {
+} -result {1 1}
+test fCmd-13.3 {TclCopyFilesCmd: bad option} -constraints {notRoot} -setup {
catch {file delete -force -- tfa1}
+} -body {
set s [createfile tfa1]
- set r1 [catch {file copy -x tfa1 tfa2}]
- set result [expr $r1 && [checkcontent tfa1 $s] && ![file exists tfa2]]
+ list [catch {file copy -x tfa1 tfa2}] \
+ [checkcontent tfa1 $s] [file exists tfa2]
+} -cleanup {
file delete tfa1
- set result
-} {1}
-
+} -result {1 1 0}
test fCmd-13.4 {TclCopyFilesCmd: bad \# args} {notRoot} {
catch {file copy -- }
} {1}
-
-test fCmd-13.5 {TclCopyFilesCmd: target filename translation failing} {
- global env
- set temp $env(HOME)
+test fCmd-13.5 {TclCopyFilesCmd: target filename translation failing} -setup {
+ set temp $::env(HOME)
+} -body {
+ global env
unset env(HOME)
- set result [catch {file copy tfa ~/foobar }]
- set env(HOME) $temp
- set result
- } {1}
-
-test fCmd-13.6 {TclCopyFilesCmd: > 1 source & target is not a dir} {notRoot} {
+ catch { file copy tfa ~/foobar }
+} -cleanup {
+ set ::env(HOME) $temp
+} -result {1}
+test fCmd-13.6 {TclCopyFilesCmd: > 1 source & target is not a dir} -setup {
catch {file delete -force -- tfa1 tfa2 tfa3}
- createfile tfa1
- createfile tfa2
- createfile tfa3
- set result [catch {file copy tfa1 tfa2 tfa3}]
+} -constraints {notRoot} -body {
+ createfile tfa1
+ createfile tfa2
+ createfile tfa3
+ catch {file copy tfa1 tfa2 tfa3}
+} -cleanup {
file delete tfa1 tfa2 tfa3
- set result
-} {1}
-
-test fCmd-13.7 {TclCopyFilesCmd: single file into directory} {notRoot} {
+} -result {1}
+test fCmd-13.7 {TclCopyFilesCmd: single file into directory} -setup {
catch {file delete -force -- tfa1 tfad}
+} -constraints {notRoot} -body {
set s [createfile tfa1]
file mkdir tfad
file copy tfa1 tfad
- set result [expr [checkcontent tfad/tfa1 $s] && [checkcontent tfa1 $s]]
+ list [checkcontent tfad/tfa1 $s] [checkcontent tfa1 $s]
+} -cleanup {
file delete -force tfad tfa1
- set result
-} {1}
-
-test fCmd-13.8 {TclCopyFilesCmd: multiple files into directory} {notRoot} {
+} -result {1 1}
+test fCmd-13.8 {TclCopyFilesCmd: multiple files into directory} -setup {
catch {file delete -force -- tfa1 tfa2 tfad}
+} -constraints {notRoot} -body {
set s1 [createfile tfa1 ]
set s2 [createfile tfa2 ]
file mkdir tfad
file copy tfa1 tfa2 tfad
- set r1 [checkcontent tfad/tfa1 $s1]
- set r2 [checkcontent tfad/tfa2 $s2]
- set r3 [checkcontent tfa1 $s1]
- set r4 [checkcontent tfa2 $s2]
- set result [expr $r1 && $r2 && $r3 && $r4 ]
-
+ list [checkcontent tfad/tfa1 $s1] [checkcontent tfad/tfa2 $s2] \
+ [checkcontent tfa1 $s1] [checkcontent tfa2 $s2]
+} -cleanup {
file delete -force tfad tfa1 tfa2
- set result
-} {1}
-
-test fCmd-13.9 {TclCopyFilesCmd: error copying file to directory} {notRoot} {
+} -result {1 1 1 1}
+test fCmd-13.9 {TclCopyFilesCmd: error copying file to directory} -setup {
catch {file delete -force -- tfa tfad}
- set s [createfile tfa ]
+} -constraints {notRoot} -body {
+ set s [createfile tfa]
file mkdir tfad
file mkdir tfad/tfa
- set r1 [catch {file copy tfa tfad}]
- set r2 [expr [checkcontent tfa $s] && [file isdir tfad/tfa]]
- set r3 [file isdir tfad]
- set result [expr $r1 && $r2 && $r3 ]
+ list [catch {file copy tfa tfad}] [checkcontent tfa $s] \
+ [file isdir tfad/tfa] [file isdir tfad]
+} -cleanup {
file delete -force tfa tfad
- set result
-} {1}
+} -result {1 1 1 1}
#
# Coverage tests for copyfile()
-#
-test fCmd-14.1 {copyfile: source filename translation failing} {notRoot} {
+#
+test fCmd-14.1 {copyfile: source filename translation failing} -setup {
+ set temp $::env(HOME)
+} -constraints {notRoot} -body {
global env
- set temp $env(HOME)
unset env(HOME)
- set result [catch {file copy ~/tfa1 tfa2}]
- set env(HOME) $temp
- set result
-} {1}
-
-test fCmd-14.2 {copyfile: dst filename translation failing} {notRoot} {
+ catch {file copy ~/tfa1 tfa2}
+} -cleanup {
+ set ::env(HOME) $temp
+} -result {1}
+test fCmd-14.2 {copyfile: dst filename translation failing} -setup {
+ set temp $::env(HOME)
+} -constraints {notRoot} -body {
global env
- set temp $env(HOME)
unset env(HOME)
set s [createfile tfa1]
file mkdir tfad
- set r1 [catch {file copy tfa1 ~/tfa2 tfad}]
- set result [expr $r1 && [checkcontent tfad/tfa1 $s]]
- set env(HOME) $temp
+ list [catch {file copy tfa1 ~/tfa2 tfad}] [checkcontent tfad/tfa1 $s]
+} -cleanup {
+ set ::env(HOME) $temp
file delete -force tfa1 tfad
- set result
-} {1}
-
-test fCmd-14.3 {copyfile: stat failing on source} {notRoot} {
+} -result {1 1}
+test fCmd-14.3 {copyfile: stat failing on source} -setup {
catch {file delete -force -- tfa1 tfa2}
- set r1 [catch {file copy tfa1 tfa2}]
- expr $r1 && ![file exists tfa1] && ![file exists tfa2]
-} {1}
-
-test fCmd-14.4 {copyfile: error copying file to directory} {notRoot} {
+} -constraints notRoot -body {
+ list [catch {file copy tfa1 tfa2}] [file exists tfa1] [file exists tfa2]
+} -result {1 0 0}
+test fCmd-14.4 {copyfile: error copying file to directory} -setup {
catch {file delete -force -- tfa tfad}
+} -constraints {notRoot} -body {
set s1 [createfile tfa ]
file mkdir tfad
file mkdir tfad/tfa
- set r1 [catch {file copy tfa tfad}]
- set r2 [checkcontent tfa $s1]
- set r3 [file isdir tfad]
- set r4 [file isdir tfad/tfa]
- set result [expr $r1 && $r2 && $r3 && $r4 ]
+ list [catch {file copy tfa tfad}] [checkcontent tfa $s1] \
+ [file isdir tfad] [file isdir tfad/tfa]
+} -cleanup {
file delete -force tfa tfad
- set result
-} {1}
-
- test fCmd-14.5 {copyfile: error copying directory to file} {notRoot} {
- catch {file delete -force -- tfa tfad}
- file mkdir tfa
- file mkdir tfad
- set s [createfile tfad/tfa]
- set r1 [catch {file copy tfa tfad}]
- set r2 [checkcontent tfad/tfa $s]
- set r3 [file isdir tfad]
- set r4 [file isdir tfa]
- set result [expr $r1 && $r2 && $r3 && $r4 ]
+} -result {1 1 1 1}
+test fCmd-14.5 {copyfile: error copying directory to file} -setup {
+ catch {file delete -force -- tfa tfad}
+} -constraints {notRoot} -body {
+ file mkdir tfa
+ file mkdir tfad
+ set s [createfile tfad/tfa]
+ list [catch {file copy tfa tfad}] [checkcontent tfad/tfa $s] \
+ [file isdir tfad] [file isdir tfa]
+} -cleanup {
file delete -force tfa tfad
- set result
-} {1}
-
-test fCmd-14.6 {copyfile: copy file succeeding} {notRoot} {
+} -result {1 1 1 1}
+test fCmd-14.6 {copyfile: copy file succeeding} -constraints notRoot -setup {
catch {file delete -force -- tfa tfa2}
+} -body {
set s [createfile tfa]
file copy tfa tfa2
- set result [expr [checkcontent tfa $s] && [checkcontent tfa2 $s]]
+ list [checkcontent tfa $s] [checkcontent tfa2 $s]
+} -cleanup {
file delete tfa tfa2
- set result
-} {1}
-
-test fCmd-14.7 {copyfile: copy directory succeeding} {notRoot} {
+} -result {1 1}
+test fCmd-14.7 {copyfile: copy directory succeeding} -setup {
catch {file delete -force -- tfa tfa2}
+} -constraints {notRoot} -body {
file mkdir tfa
set s [createfile tfa/file]
file copy tfa tfa2
- set result [expr [checkcontent tfa/file $s] && [checkcontent tfa2/file $s]]
+ list [checkcontent tfa/file $s] [checkcontent tfa2/file $s]
+} -cleanup {
file delete -force tfa tfa2
- set result
-} {1}
-
-test fCmd-14.8 {copyfile: copy directory failing} {unixOnly notRoot} {
+} -result {1 1}
+test fCmd-14.8 {copyfile: copy directory failing} -setup {
catch {file delete -force -- tfa}
+} -constraints {unix notRoot} -body {
file mkdir tfa/dir/a/b/c
file attributes tfa/dir -permissions 0000
- set r1 [catch {file copy tfa tfa2}]
+ catch {file copy tfa tfa2}
+} -cleanup {
file attributes tfa/dir -permissions 0777
- set result $r1
file delete -force tfa tfa2
- set result
-} {1}
+} -result {1}
#
# Coverage tests for TclMkdirCmd()
#
-test fCmd-15.1 {TclMakeDirsCmd: target filename translation failing} {notRoot} {
+test fCmd-15.1 {TclMakeDirsCmd: target filename translation failing} -setup {
+ set temp $::env(HOME)
+} -constraints {notRoot} -body {
global env
- set temp $env(HOME)
- unset env(HOME)
- set result [catch {file mkdir ~/tfa}]
- set env(HOME) $temp
- set result
-} {1}
+ unset env(HOME)
+ catch {file mkdir ~/tfa}
+} -cleanup {
+ set ::env(HOME) $temp
+} -result {1}
#
# Can Tcl_SplitPath return argc == 0? If so them we need a
# test for that code.
#
-test fCmd-15.2 {TclMakeDirsCmd - one directory } {notRoot} {
+test fCmd-15.2 {TclMakeDirsCmd - one directory } -setup {
catch {file delete -force -- tfa}
+} -constraints {notRoot} -body {
file mkdir tfa
- set result [file isdirectory tfa]
+ file isdirectory tfa
+} -cleanup {
file delete tfa
- set result
-} {1}
-
-test fCmd-15.3 {TclMakeDirsCmd: - two directories} {notRoot} {
+} -result {1}
+test fCmd-15.3 {TclMakeDirsCmd: - two directories} -setup {
catch {file delete -force -- tfa1 tfa2}
+} -constraints {notRoot} -body {
file mkdir tfa1 tfa2
- set result [expr [file isdirectory tfa1] && [file isdirectory tfa2]]
+ list [file isdirectory tfa1] [file isdirectory tfa2]
+} -cleanup {
file delete tfa1 tfa2
- set result
-} {1}
-
-test fCmd-15.4 {TclMakeDirsCmd - stat failing} {unixOnly notRoot} {
+} -result {1 1}
+test fCmd-15.4 {TclMakeDirsCmd - stat failing} -setup {
catch {file delete -force -- tfa}
+} -constraints {unix notRoot} -body {
file mkdir tfa
createfile tfa/file
file attributes tfa -permissions 0000
- set result [catch {file mkdir tfa/file}]
+ catch {file mkdir tfa/file}
+} -cleanup {
file attributes tfa -permissions 0777
file delete -force tfa
- set result
-} {1}
-
-test fCmd-15.5 {TclMakeDirsCmd: - making a directory several levels deep} \
- {notRoot} {
+} -result {1}
+test fCmd-15.5 {TclMakeDirsCmd: - making a directory several levels deep} -setup {
catch {file delete -force -- tfa}
+} -constraints {notRoot} -body {
file mkdir tfa/a/b/c
- set result [file isdir tfa/a/b/c]
+ file isdir tfa/a/b/c
+} -cleanup {
file delete -force tfa
- set result
-} {1}
-
-
-test fCmd-15.6 {TclMakeDirsCmd: - trying to overwrite a file} {notRoot} {
+} -result {1}
+test fCmd-15.6 {TclMakeDirsCmd: - trying to overwrite a file} -setup {
catch {file delete -force -- tfa}
+} -constraints {notRoot} -body {
set s [createfile tfa]
- set r1 [catch {file mkdir tfa}]
- set r2 [file isdir tfa]
- set r3 [file exists tfa]
- set result [expr $r1 && !$r2 && $r3 && [checkcontent tfa $s]]
+ list [catch {file mkdir tfa}] [file isdir tfa] [file exists tfa] \
+ [checkcontent tfa $s]
+} -cleanup {
file delete tfa
- set result
-} {1}
-
-test fCmd-15.7 {TclMakeDirsCmd - making several directories} {notRoot} {
+} -result {1 0 1 1}
+test fCmd-15.7 {TclMakeDirsCmd - making several directories} -setup {
catch {file delete -force -- tfa1 tfa2}
+} -constraints {notRoot} -body {
file mkdir tfa1 tfa2/a/b/c
- set result [expr [file isdir tfa1] && [file isdir tfa2/a/b/c]]
+ list [file isdir tfa1] [file isdir tfa2/a/b/c]
+} -cleanup {
file delete -force tfa1 tfa2
- set result
-} {1}
-
-test fCmd-15.8 {TclFileMakeDirsCmd: trying to create an existing dir} {notRoot} {
+} -result {1 1}
+test fCmd-15.8 {TclFileMakeDirsCmd: trying to create an existing dir} -body {
file mkdir tfa
file mkdir tfa
- set result [file isdir tfa]
+ file isdir tfa
+} -constraints {notRoot} -cleanup {
file delete tfa
- set result
-} {1}
-
+} -result {1}
# Coverage tests for TclDeleteFilesCommand()
-test fCmd-16.1 {test the -- argument} {notRoot} {
+test fCmd-16.1 {test the -- argument} -constraints {notRoot} -setup {
catch {file delete -force -- tfa}
+} -body {
createfile tfa
file delete -- tfa
file exists tfa
-} {0}
-
-test fCmd-16.2 {test the -force and -- arguments} {notRoot} {
+} -result 0
+test fCmd-16.2 {test the -force and -- arguments} -constraints notRoot -setup {
catch {file delete -force -- tfa}
+} -body {
createfile tfa
file delete -force -- tfa
file exists tfa
-} {0}
-
-test fCmd-16.3 {test bad option} {notRoot} {
+} -result 0
+test fCmd-16.3 {test bad option} -constraints {notRoot} -setup {
catch {file delete -force -- tfa}
+} -body {
createfile tfa
- set result [catch {file delete -dog tfa}]
+ catch {file delete -dog tfa}
+} -cleanup {
file delete tfa
- set result
-} {1}
-
-test fCmd-16.4 {test not enough args} {notRoot} {
- catch {file delete}
-} {1}
-
-test fCmd-16.5 {test not enough args with options} {notRoot} {
- catch {file delete --}
-} {1}
-
-test fCmd-16.6 {delete: source filename translation failing} {notRoot} {
+} -result {1}
+test fCmd-16.4 {test not enough args} -constraints {notRoot} -body {
+ file delete
+} -returnCodes error -match glob -result "wrong \# args: should be *"
+test fCmd-16.5 {test not enough args with options} -constraints {notRoot} -body {
+ file delete --
+} -returnCodes error -match glob -result "wrong \# args: should be *"
+test fCmd-16.6 {delete: source filename translation failing} -setup {
+ set temp $::env(HOME)
+} -constraints {notRoot} -body {
global env
- set temp $env(HOME)
unset env(HOME)
- set result [catch {file delete ~/tfa}]
- set env(HOME) $temp
- set result
-} {1}
-
-test fCmd-16.7 {remove a non-empty directory without -force } {notRoot} {
+ catch {file delete ~/tfa}
+} -cleanup {
+ set ::env(HOME) $temp
+} -result {1}
+test fCmd-16.7 {remove a non-empty directory without -force} -setup {
catch {file delete -force -- tfa}
+} -constraints {notRoot} -body {
file mkdir tfa
createfile tfa/a
- set result [catch {file delete tfa }]
+ catch {file delete tfa}
+} -cleanup {
file delete -force tfa
- set result
-} {1}
-
-test fCmd-16.8 {remove a normal file } {notRoot} {
+} -result {1}
+test fCmd-16.8 {remove a normal file} -constraints {notRoot} -setup {
catch {file delete -force -- tfa}
+} -body {
file mkdir tfa
createfile tfa/a
- set result [catch {file delete tfa }]
+ catch {file delete tfa}
+} -cleanup {
file delete -force tfa
- set result
-} {1}
-
-test fCmd-16.9 {error while deleting file } {unixOnly notRoot} {
+} -result {1}
+test fCmd-16.9 {error while deleting file} -setup {
catch {file delete -force -- tfa}
+} -constraints {unix notRoot} -body {
file mkdir tfa
createfile tfa/a
file attributes tfa -permissions 0555
- set result [catch {file delete tfa/a }]
+ catch {file delete tfa/a}
#######
- ####### If any directory in a tree that is being removed does not
- ####### have write permission, the process will fail!
- ####### This is also the case with "rm -rf"
+ ####### If any directory in a tree that is being removed does not have
+ ####### write permission, the process will fail! This is also the case
+ ####### with "rm -rf"
#######
+} -cleanup {
file attributes tfa -permissions 0777
file delete -force tfa
- set result
-} {1}
-
-test fCmd-16.10 {deleting multiple files} {notRoot} {
+} -result {1}
+test fCmd-16.10 {deleting multiple files} -constraints {notRoot} -setup {
catch {file delete -force -- tfa1 tfa2}
+} -body {
createfile tfa1
createfile tfa2
file delete tfa1 tfa2
- expr ![file exists tfa1] && ![file exists tfa2]
-} {1}
-
-test fCmd-16.11 {TclFileDeleteCmd: removing a nonexistant file} {notRoot} {
+ list [file exists tfa1] [file exists tfa2]
+} -result {0 0}
+test fCmd-16.11 {TclFileDeleteCmd: removing a nonexistant file} -setup {
catch {file delete -force -- tfa}
+} -constraints {notRoot} -body {
file delete tfa
- set result 1
-} {1}
+} -result {}
# More coverage tests for mkpath()
- test fCmd-17.1 {mkdir stat failing on target but not ENOENT} {unixOnly notRoot} {
+test fCmd-17.1 {mkdir stat failing on target but not ENOENT} -setup {
catch {file delete -force -- tfa1}
+} -constraints {unix notRoot} -body {
file mkdir tfa1
file attributes tfa1 -permissions 0555
- set result [catch {file mkdir tfa1/tfa2}]
+ catch {file mkdir tfa1/tfa2}
+} -cleanup {
file attributes tfa1 -permissions 0777
file delete -force tfa1
- set result
-} {1}
-
-test fCmd-17.2 {mkdir several levels deep - relative } {notRoot} {
+} -result {1}
+test fCmd-17.2 {mkdir several levels deep - relative} -setup {
catch {file delete -force -- tfa}
+} -constraints {notRoot} -body {
file mkdir tfa/a/b
- set result [file isdir tfa/a/b ]
+ file isdir tfa/a/b
+} -cleanup {
file delete tfa/a/b tfa/a tfa
- set result
-} {1}
-
-test fCmd-17.3 {mkdir several levels deep - absolute } {notRoot} {
+} -result 1
+test fCmd-17.3 {mkdir several levels deep - absolute} -setup {
catch {file delete -force -- tfa}
- set f [file join [pwd] tfa a ]
+} -constraints {notRoot} -body {
+ set f [file join [pwd] tfa a]
file mkdir $f
- set result [file isdir $f ]
+ file isdir $f
+} -cleanup {
file delete $f [file join [pwd] tfa]
- set result
-} {1}
+} -result {1}
#
# Functionality tests for TclFileRenameCmd()
#
test fCmd-18.1 {TclFileRenameCmd: rename (first form) in the same directory} \
- {notRoot} {
+ -setup {
catch {file delete -force -- tfad}
+ set savedDir [pwd]
+} -constraints {notRoot} -body {
file mkdir tfad/dir
cd tfad/dir
set s [createfile foo ]
@@ -1642,217 +1682,191 @@ test fCmd-18.1 {TclFileRenameCmd: rename (first form) in the same directory} \
file rename ../../tfad/dir/foo ../../tfad/dir/bar
file rename [file join [pwd] bar] foo
file rename foo [file join [pwd] bar]
- set result [expr [checkcontent bar $s] && ![file exists foo]]
- cd ../..
+ list [checkcontent bar $s] [file exists foo]
+} -cleanup {
+ cd $savedDir
file delete -force tfad
- set result
-} {1}
-
-test fCmd-18.2 {TclFileRenameCmd: single dir to nonexistant} {notRoot} {
+} -result {1 0}
+test fCmd-18.2 {TclFileRenameCmd: single dir to nonexistant} -setup {
catch {file delete -force -- tfa1 tfa2}
+} -constraints {notRoot} -body {
file mkdir tfa1
file rename tfa1 tfa2
- set result [expr [file exists tfa2] && ![file exists tfa1]]
+ list [file exists tfa2] [file exists tfa1]
+} -cleanup {
file delete tfa2
- set result
-} {1}
-
-test fCmd-18.3 {TclFileRenameCmd: mixed dirs and files into directory} {notRoot} {
+} -result {1 0}
+test fCmd-18.3 {TclFileRenameCmd: mixed dirs and files into directory} -setup {
catch {file delete -force -- tfa1 tfad1 tfad2}
- set s [createfile tfa1 ]
+} -constraints {notRoot} -body {
+ set s [createfile tfa1]
file mkdir tfad1 tfad2
file rename tfa1 tfad1 tfad2
- set r1 [checkcontent tfad2/tfa1 $s]
- set r2 [file isdir tfad2/tfad1]
- set result [expr $r1 && $r2 && ![file exists tfa1] && ![file exists tfad1]]
+ list [checkcontent tfad2/tfa1 $s] [file isdir tfad2/tfad1] \
+ [file exists tfa1] [file exists tfad1]
+} -cleanup {
file delete tfad2/tfa1
file delete -force tfad2
- set result
-} {1}
-
-test fCmd-18.4 {TclFileRenameCmd: attempt to replace non-dir with dir} {notRoot} {
+} -result {1 1 0 0}
+test fCmd-18.4 {TclFileRenameCmd: attempt to replace non-dir with dir} -setup {
catch {file delete -force -- tfa tfad}
- set s [createfile tfa ]
+} -constraints {notRoot} -body {
+ set s [createfile tfa]
file mkdir tfad
- set r1 [catch {file rename tfad tfa}]
- set r2 [checkcontent tfa $s]
- set r3 [file isdir tfad]
- set result [expr $r1 && $r2 && $r3 ]
+ list [catch {file rename tfad tfa}] [checkcontent tfa $s] [file isdir tfad]
+} -cleanup {
file delete tfa tfad
- set result
-} {1}
-
-test fCmd-18.5 {TclFileRenameCmd: attempt to replace dir with non-dir} {notRoot} {
+} -result {1 1 1}
+test fCmd-18.5 {TclFileRenameCmd: attempt to replace dir with non-dir} -setup {
catch {file delete -force -- tfa tfad}
- set s [createfile tfa ]
+} -constraints {notRoot} -body {
+ set s [createfile tfa]
file mkdir tfad/tfa
- set r1 [catch {file rename tfa tfad}]
- set r2 [checkcontent tfa $s]
- set r3 [file isdir tfad/tfa]
- set result [expr $r1 && $r2 && $r3 ]
- file delete -force tfa tfad
- set result
-} {1}
-
+ list [catch {file rename tfa tfad}] [checkcontent tfa $s] \
+ [file isdir tfad/tfa]
+} -cleanup {
+ file delete -force tfa tfad
+} -result {1 1 1}
#
# On Windows there is no easy way to determine if two files are the same
#
-test fCmd-18.6 {TclFileRenameCmd: rename a file to itself} {macOrUnix notRoot} {
+test fCmd-18.6 {TclFileRenameCmd: rename a file to itself} -setup {
catch {file delete -force -- tfa}
+} -constraints {unix notRoot} -body {
set s [createfile tfa]
- set r1 [catch {file rename tfa tfa}]
- set result [expr $r1 && [checkcontent tfa $s]]
+ list [catch {file rename tfa tfa}] [checkcontent tfa $s]
+} -cleanup {
file delete tfa
- set result
-} {1}
-
-test fCmd-18.7 {TclFileRenameCmd: rename dir on top of another empty dir w/o -force} \
- {notRoot} {
+} -result {1 1}
+test fCmd-18.7 {TclFileRenameCmd: rename dir on top of another empty dir w/o -force} -setup {
catch {file delete -force -- tfa tfad}
+} -constraints {notRoot} -body {
file mkdir tfa tfad/tfa
- set r1 [catch {file rename tfa tfad}]
- set result [expr $r1 && [file isdir tfa]]
+ list [catch {file rename tfa tfad}] [file isdir tfa]
+} -cleanup {
file delete -force tfa tfad
- set result
-} {1}
-
-test fCmd-18.8 {TclFileRenameCmd: rename dir on top of another empty dir w/ -force} \
- {notRoot notNetworkFilesystem} {
+} -result {1 1}
+test fCmd-18.8 {TclFileRenameCmd: rename dir on top of another empty dir w/ -force} -setup {
catch {file delete -force -- tfa tfad}
+} -constraints {notRoot notNetworkFilesystem} -body {
file mkdir tfa tfad/tfa
file rename -force tfa tfad
- set result [expr ![file isdir tfa]]
+ file isdir tfa
+} -cleanup {
file delete -force tfad
- set result
-} {1}
-
-test fCmd-18.9 {TclFileRenameCmd: rename dir on top of a non-empty dir w/o -force} \
- {notRoot} {
+} -result 0
+test fCmd-18.9 {TclFileRenameCmd: rename dir on top of a non-empty dir w/o -force} -setup {
catch {file delete -force -- tfa tfad}
+} -constraints {notRoot} -body {
file mkdir tfa tfad/tfa/file
- set r1 [catch {file rename tfa tfad}]
- set result [expr $r1 && [file isdir tfa] && [file isdir tfad/tfa/file]]
+ list [catch {file rename tfa tfad}] [file isdir tfa] \
+ [file isdir tfad/tfa/file]
+} -cleanup {
file delete -force tfa tfad
- set result
-} {1}
-
-test fCmd-18.10 {TclFileRenameCmd: rename dir on top of a non-empty dir w/ -force} \
- {notRoot notNetworkFilesystem} {
+} -result {1 1 1}
+test fCmd-18.10 {TclFileRenameCmd: rename dir on top of a non-empty dir w/ -force} -setup {
catch {file delete -force -- tfa tfad}
+} -constraints {notRoot notNetworkFilesystem} -body {
file mkdir tfa tfad/tfa/file
- set r1 [catch {file rename -force tfa tfad}]
- set result [expr $r1 && [file isdir tfa] && [file isdir tfad/tfa/file]]
+ list [catch {file rename -force tfa tfad}] [file isdir tfa] \
+ [file isdir tfad/tfa/file]
+} -cleanup {
file delete -force tfa tfad
- set result
-} {1}
-
-test fCmd-18.11 {TclFileRenameCmd: rename a non-existant file} {notRoot} {
+} -result {1 1 1}
+test fCmd-18.11 {TclFileRenameCmd: rename a non-existant file} -setup {
catch {file delete -force -- tfa1}
- set r1 [catch {file rename tfa1 tfa2}]
- set result [expr $r1 && ![file exists tfa1] && ![file exists tfa2]]
-} {1}
-
-test fCmd-18.12 {TclFileRenameCmd : rename a symbolic link to file} \
- {unixOnly notRoot} {
+} -constraints {notRoot} -body {
+ list [catch {file rename tfa1 tfa2}] [file exists tfa1] [file exists tfa2]
+} -result {1 0 0}
+test fCmd-18.12 {TclFileRenameCmd : rename a symbolic link to file} -setup {
catch {file delete -force -- tfa1 tfa2 tfa3}
-
+} -constraints {unix notRoot} -body {
set s [createfile tfa1]
file link -symbolic tfa2 tfa1
file rename tfa2 tfa3
- set t [file type tfa3]
- set result [expr {$t eq "link"}]
+ file type tfa3
+} -cleanup {
file delete tfa1 tfa3
- set result
-} {1}
-
-test fCmd-18.13 {TclFileRenameCmd : rename a symbolic link to dir} \
- {unixOnly notRoot} {
+} -result link
+test fCmd-18.13 {TclFileRenameCmd : rename a symbolic link to dir} -setup {
catch {file delete -force -- tfa1 tfa2 tfa3}
-
+} -constraints {unix notRoot} -body {
file mkdir tfa1
file link -symbolic tfa2 tfa1
file rename tfa2 tfa3
- set t [file type tfa3]
- set result [expr {$t eq "link"}]
+ file type tfa3
+} -cleanup {
file delete tfa1 tfa3
- set result
-} {1}
-
-test fCmd-18.14 {TclFileRenameCmd : rename a path with sym link} \
- {unixOnly notRoot} {
+} -result link
+test fCmd-18.14 {TclFileRenameCmd : rename a path with sym link} -setup {
catch {file delete -force -- tfa1 tfa2 tfa3}
-
+} -constraints {unix notRoot} -body {
file mkdir tfa1/a/b/c/d
file mkdir tfa2
- set f [file join [pwd] tfa1/a/b]
+ set f [file join [pwd] tfa1/a/b]
set f2 [file join [pwd] {tfa2/b alias}]
file link -symbolic $f2 $f
file rename {tfa2/b alias/c} tfa3
- set r1 [file isdir tfa3]
- set r2 [file exists tfa1/a/b/c]
- set result [expr $r1 && !$r2]
+ list [file isdir tfa3] [file exists tfa1/a/b/c]
+} -cleanup {
file delete -force tfa1 tfa2 tfa3
- set result
-} {1}
-
-test fCmd-18.15 {TclFileRenameCmd : rename a file to a symlink dir} \
- {unixOnly notRoot} {
+} -result {1 0}
+test fCmd-18.15 {TclFileRenameCmd : rename a file to a symlink dir} -setup {
catch {file delete -force -- tfa1 tfa2 tfalink}
-
+} -constraints {unix notRoot} -body {
file mkdir tfa1
set s [createfile tfa2]
file link -symbolic tfalink tfa1
file rename tfa2 tfalink
- set result [checkcontent tfa1/tfa2 $s ]
+ checkcontent tfa1/tfa2 $s
+} -cleanup {
file delete -force tfa1 tfalink
- set result
-} {1}
-
-test fCmd-18.16 {TclFileRenameCmd: rename a dangling symlink} {unixOnly notRoot} {
+} -result {1}
+test fCmd-18.16 {TclFileRenameCmd: rename a dangling symlink} -setup {
catch {file delete -force -- tfa1 tfalink}
-
+} -constraints {unix notRoot} -body {
file mkdir tfa1
file link -symbolic tfalink tfa1
- file delete tfa1
+ file delete tfa1
file rename tfalink tfa2
- set result [expr [string compare [file type tfa2] "link"] == 0]
+ file type tfa2
+} -cleanup {
file delete tfa2
- set result
-} {1}
-
+} -result link
#
# Coverage tests for TclUnixRmdir
#
-test fCmd-19.1 {remove empty directory} {notRoot} {
+test fCmd-19.1 {remove empty directory} -constraints {notRoot} -setup {
catch {file delete -force -- tfa}
+} -body {
file mkdir tfa
file delete tfa
file exists tfa
-} {0}
-
-test fCmd-19.2 {rmdir error besides EEXIST} {unixOnly notRoot} {
+} -result {0}
+test fCmd-19.2 {rmdir error besides EEXIST} -setup {
catch {file delete -force -- tfa}
+} -constraints {unix notRoot} -body {
file mkdir tfa
file mkdir tfa/a
file attributes tfa -permissions 0555
- set result [catch {file delete tfa/a}]
+ catch {file delete tfa/a}
+} -cleanup {
file attributes tfa -permissions 0777
file delete -force tfa
- set result
-} {1}
-
-test fCmd-19.3 {recursive remove} {notRoot} {
+} -result {1}
+test fCmd-19.3 {recursive remove} -constraints {notRoot} -setup {
catch {file delete -force -- tfa}
+} -body {
file mkdir tfa
file mkdir tfa/a
file delete -force tfa
file exists tfa
-} {0}
+} -result {0}
#
-# TclUnixDeleteFile and TraversalDelete are covered by tests from the
+# TclUnixDeleteFile and TraversalDelete are covered by tests from the
# TclDeleteFilesCmd suite
#
#
@@ -1861,235 +1875,229 @@ test fCmd-19.3 {recursive remove} {notRoot} {
# Coverage tests for TraverseUnixTree(), called from TclDeleteFilesCmd
#
-test fCmd-20.1 {TraverseUnixTree : failure opening a subdirectory directory } \
- {unixOnly notRoot} {
+test fCmd-20.1 {TraverseUnixTree : failure opening a subdirectory directory } -setup {
catch {file delete -force -- tfa}
+} -constraints {unix notRoot} -body {
file mkdir tfa
file mkdir tfa/a
file attributes tfa/a -permissions 0000
- set result [catch {file delete -force tfa}]
+ catch {file delete -force tfa}
+} -cleanup {
file attributes tfa/a -permissions 0777
file delete -force tfa
- set result
-} {1}
-
-test fCmd-20.2 {TraverseUnixTree : recursive delete of large directory: Bug 1034337} \
- {unix notRoot} {
+} -result {1}
+test fCmd-20.2 {TraverseUnixTree : recursive delete of large directory: Bug 1034337} -setup {
catch {file delete -force -- tfa}
+} -constraints {unix notRoot} -body {
file mkdir tfa
- for {set i 1} {$i <= 300} {incr i} {createfile tfa/testfile_$i}
- set result [catch {file delete -force tfa} msg]
+ for {set i 1} {$i <= 300} {incr i} {
+ createfile tfa/testfile_$i
+ }
+ file delete -force tfa
+} -cleanup {
while {[catch {file delete -force tfa}]} {}
- list $result $msg
-} {0 {}}
+} -result {}
#
# Feature testing for TclCopyFilesCmd
-#
-test fCmd-21.1 {copy : single file to nonexistant } {notRoot} {
+#
+test fCmd-21.1 {copy : single file to nonexistant} -setup {
catch {file delete -force -- tfa1 tfa2}
+} -constraints {notRoot} -body {
set s [createfile tfa1]
file copy tfa1 tfa2
- set result [expr [checkcontent tfa2 $s] && [checkcontent tfa1 $s]]
+ list [checkcontent tfa2 $s] [checkcontent tfa1 $s]
+} -cleanup {
file delete tfa1 tfa2
- set result
-} {1}
-
-test fCmd-21.2 {copy : single dir to nonexistant } {notRoot} {
+} -result {1 1}
+test fCmd-21.2 {copy : single dir to nonexistant} -setup {
catch {file delete -force -- tfa1 tfa2}
+} -constraints {notRoot} -body {
file mkdir tfa1
file copy tfa1 tfa2
- set result [expr [file isdir tfa2] && [file isdir tfa1]]
+ list [file isdir tfa2] [file isdir tfa1]
+} -cleanup {
file delete tfa1 tfa2
- set result
-} {1}
-
-test fCmd-21.3 {copy : single file into directory } {notRoot} {
+} -result {1 1}
+test fCmd-21.3 {copy : single file into directory} -setup {
catch {file delete -force -- tfa1 tfad}
+} -constraints {notRoot} -body {
set s [createfile tfa1]
file mkdir tfad
file copy tfa1 tfad
- set result [expr [checkcontent tfad/tfa1 $s] && [checkcontent tfa1 $s]]
+ list [checkcontent tfad/tfa1 $s] [checkcontent tfa1 $s]
+} -cleanup {
file delete -force tfa1 tfad
- set result
-} {1}
-
-test fCmd-21.4 {copy : more than one source and target is not a directory} \
- {notRoot} {
+} -result {1 1}
+test fCmd-21.4 {copy : more than one source and target is not a directory} -setup {
catch {file delete -force -- tfa1 tfa2 tfa3}
- createfile tfa1
- createfile tfa2
- createfile tfa3
- set result [catch {file copy tfa1 tfa2 tfa3}]
+} -constraints {notRoot} -body {
+ createfile tfa1
+ createfile tfa2
+ createfile tfa3
+ catch {file copy tfa1 tfa2 tfa3}
+} -cleanup {
file delete tfa1 tfa2 tfa3
- set result
-} {1}
-
-test fCmd-21.5 {copy : multiple files into directory } {notRoot} {
+} -result {1}
+test fCmd-21.5 {copy : multiple files into directory} -constraints {notRoot} -setup {
catch {file delete -force -- tfa1 tfa2 tfad}
- set s1 [createfile tfa1 ]
- set s2 [createfile tfa2 ]
+} -body {
+ set s1 [createfile tfa1]
+ set s2 [createfile tfa2]
file mkdir tfad
file copy tfa1 tfa2 tfad
- set r1 [checkcontent tfad/tfa1 $s1]
- set r2 [checkcontent tfad/tfa2 $s2]
- set r3 [checkcontent tfa1 $s1]
- set r4 [checkcontent tfa2 $s2]
- set result [expr $r1 && $r2 && $r3 && $r4]
+ list [checkcontent tfad/tfa1 $s1] [checkcontent tfad/tfa2 $s2] \
+ [checkcontent tfa1 $s1] [checkcontent tfa2 $s2]
+} -cleanup {
file delete -force tfa1 tfa2 tfad
- set result
-} {1}
-
-test fCmd-21.6 {copy: mixed dirs and files into directory} \
- {notRoot notFileSharing} {
+} -result {1 1 1 1}
+test fCmd-21.6 {copy: mixed dirs and files into directory} -setup {
catch {file delete -force -- tfa1 tfad1 tfad2}
- set s [createfile tfa1 ]
+} -constraints {notRoot notFileSharing} -body {
+ set s [createfile tfa1]
file mkdir tfad1 tfad2
file copy tfa1 tfad1 tfad2
- set r1 [checkcontent [file join tfad2 tfa1] $s]
- set r2 [file isdir [file join tfad2 tfad1]]
- set r3 [checkcontent tfa1 $s]
- set result [expr $r1 && $r2 && $r3 && [file isdir tfad1]]
+ list [checkcontent [file join tfad2 tfa1] $s] \
+ [file isdir [file join tfad2 tfad1]] \
+ [checkcontent tfa1 $s] [file isdir tfad1]
+} -cleanup {
file delete -force tfa1 tfad1 tfad2
- set result
-} {1}
-
-test fCmd-21.7.1 {TclCopyFilesCmd: copy a dangling link} {unixOnly notRoot dontCopyLinks} {
+} -result {1 1 1 1}
+test fCmd-21.7.1 {TclCopyFilesCmd: copy a dangling link} -setup {
+ catch {file delete -force tfad1 tfalink tfalink2}
+} -constraints {unix notRoot dontCopyLinks} -body {
file mkdir tfad1
file link -symbolic tfalink tfad1
file delete tfad1
- set result [list [catch {file copy tfalink tfalink2} msg] $msg]
- file delete -force tfalink tfalink2
- set result
-} {1 {error copying "tfalink": the target of this link doesn't exist}}
-test fCmd-21.7.2 {TclCopyFilesCmd: copy a dangling link} {unixOnly notRoot} {
+ file copy tfalink tfalink2
+} -returnCodes error -cleanup {
+ file delete -force tfalink tfalink2
+} -result {error copying "tfalink": the target of this link doesn't exist}
+test fCmd-21.7.2 {TclCopyFilesCmd: copy a dangling link} -setup {
+ catch {file delete -force tfad1 tfalink tfalink2}
+} -constraints {unix notRoot} -body {
file mkdir tfad1
file link -symbolic tfalink tfad1
file delete tfad1
file copy tfalink tfalink2
- set result [string match [file type tfalink2] link]
- file delete tfalink tfalink2
- set result
-} {1}
-
-test fCmd-21.8.1 {TclCopyFilesCmd: copy a link } {unixOnly notRoot dontCopyLinks} {
+ file type tfalink2
+} -cleanup {
+ file delete tfalink tfalink2
+} -result link
+test fCmd-21.8.1 {TclCopyFilesCmd: copy a link} -setup {
+ catch {file delete -force tfad1 tfalink tfalink2}
+} -constraints {unix notRoot dontCopyLinks} -body {
file mkdir tfad1
file link -symbolic tfalink tfad1
file copy tfalink tfalink2
- set r1 [file type tfalink]; # link
- set r2 [file type tfalink2]; # directory
- set r3 [file isdir tfad1]; # 1
- set result [expr {("$r1" == "link") && ("$r2" == "directory") && $r3}]
+ list [file type tfalink] [file type tfalink2] [file isdir tfad1]
+} -cleanup {
file delete -force tfad1 tfalink tfalink2
- set result
-} {1}
-test fCmd-21.8.2 {TclCopyFilesCmd: copy a link } {unixOnly notRoot} {
+} -result {link directory 1}
+test fCmd-21.8.2 {TclCopyFilesCmd: copy a link} -setup {
+ catch {file delete -force tfad1 tfalink tfalink2}
+} -constraints {unix notRoot} -body {
file mkdir tfad1
file link -symbolic tfalink tfad1
file copy tfalink tfalink2
- set r1 [file type tfalink]; # link
- set r2 [file type tfalink2]; # link
- set r3 [file isdir tfad1]; # 1
- set result [expr {("$r1" == "link") && ("$r2" == "link") && $r3}]
+ list [file type tfalink] [file type tfalink2] [file isdir tfad1]
+} -cleanup {
file delete -force tfad1 tfalink tfalink2
- set result
-} {1}
-
-test fCmd-21.9 {TclCopyFilesCmd: copy dir with a link in it} {unixOnly notRoot} {
+} -result {link link 1}
+test fCmd-21.9 {TclCopyFilesCmd: copy dir with a link in it} -setup {
+ catch {file delete -force tfad1 tfad2}
+} -constraints {unix notRoot} -body {
file mkdir tfad1
file link -symbolic tfad1/tfalink "[pwd]/tfad1"
file copy tfad1 tfad2
- set result [string match [file type tfad2/tfalink] link]
+ file type tfad2/tfalink
+} -cleanup {
file delete -force tfad1 tfad2
- set result
-} {1}
-
-test fCmd-21.10 {TclFileCopyCmd: copy dir on top of another empty dir w/o -force} \
- {notRoot} {
+} -result link
+test fCmd-21.10 {TclFileCopyCmd: copy dir on top of another empty dir w/o -force} -setup {
catch {file delete -force -- tfa tfad}
+} -constraints {notRoot} -body {
file mkdir tfa [file join tfad tfa]
- set r1 [catch {file copy tfa tfad}]
- set result [expr $r1 && [file isdir tfa]]
+ list [catch {file copy tfa tfad}] [file isdir tfa]
+} -cleanup {
file delete -force tfa tfad
- set result
-} {1}
-
-test fCmd-21.11 {TclFileCopyCmd: copy dir on top of a dir w/o -force} {notRoot} {
+} -result {1 1}
+test fCmd-21.11 {TclFileCopyCmd: copy dir on top of a dir w/o -force} -setup {
catch {file delete -force -- tfa tfad}
+} -constraints {notRoot} -body {
file mkdir tfa [file join tfad tfa file]
- set r1 [catch {file copy tfa tfad}]
- set result [expr $r1 && [file isdir tfa] && [file isdir [file join tfad tfa file]]]
+ list [catch {file copy tfa tfad}] [file isdir tfa] \
+ [file isdir [file join tfad tfa file]]
+} -cleanup {
file delete -force tfa tfad
- set result
-} {1}
-
-test fCmd-21.12 {TclFileCopyCmd: copy dir on top of a non-empty dir w/ -force} \
- {notRoot} {
+} -result {1 1 1}
+test fCmd-21.12 {TclFileCopyCmd: copy dir on top of a non-empty dir w/ -force} -setup {
catch {file delete -force -- tfa tfad}
+} -constraints {notRoot} -body {
file mkdir tfa [file join tfad tfa file]
- set r1 [catch {file copy -force tfa tfad}]
- set result [expr $r1 && [file isdir tfa] && [file isdir [file join tfad tfa file]]]
+ list [catch {file copy -force tfa tfad}] [file isdir tfa] \
+ [file isdir [file join tfad tfa file]]
+} -cleanup {
file delete -force tfa tfad
- set result
-} {1}
+} -result {1 1 1}
#
# Coverage testing for TclpRenameFile
#
-test fCmd-22.1 {TclpRenameFile: rename and overwrite in a single dir} {notRoot} {
+test fCmd-22.1 {TclpRenameFile: rename and overwrite in a single dir} -setup {
catch {file delete -force -- tfa1 tfa2}
+} -constraints {notRoot} -body {
set s [createfile tfa1]
set s2 [createfile tfa2 q]
-
- set r1 [catch {rename tfa1 tfa2}]
+
+ set result [catch {file rename tfa1 tfa2}]
file rename -force tfa1 tfa2
- set result [expr $r1 && [checkcontent tfa2 $s]]
+ lappend result [checkcontent tfa2 $s]
+} -cleanup {
file delete [glob tfa1 tfa2]
- set result
-} {1}
-
-test fCmd-22.2 {TclpRenameFile: attempt to overwrite itself} {macOrUnix notRoot} {
+} -result {1 1}
+test fCmd-22.2 {TclpRenameFile: attempt to overwrite itself} -setup {
catch {file delete -force -- tfa1}
- set s [createfile tfa1]
+} -constraints {unix notRoot} -body {
+ set s [createfile tfa1]
file rename -force tfa1 tfa1
- set result [checkcontent tfa1 $s]
- file delete tfa1
- set result
-} {1}
-
-test fCmd-22.3 {TclpRenameFile: rename dir to existing dir} {notRoot} {
+ checkcontent tfa1 $s
+} -cleanup {
+ file delete tfa1
+} -result {1}
+test fCmd-22.3 {TclpRenameFile: rename dir to existing dir} -setup {
catch {file delete -force -- d1 tfad}
+} -constraints {notRoot} -body {
file mkdir d1 [file join tfad d1]
- set r1 [catch {file rename d1 tfad}]
- set result [expr $r1 && [file isdir d1] && [file isdir [file join tfad d1]]]
+ list [catch {file rename d1 tfad}] [file isdir d1] \
+ [file isdir [file join tfad d1]]
+} -cleanup {
file delete -force d1 tfad
- set result
-} {1}
-
-test fCmd-22.4 {TclpRenameFile: rename dir to dir several levels deep} {notRoot} {
+} -result {1 1 1}
+test fCmd-22.4 {TclpRenameFile: rename dir to dir several levels deep} -setup {
catch {file delete -force -- d1 tfad}
+} -constraints {notRoot} -body {
file mkdir d1 [file join tfad a b c]
file rename d1 [file join tfad a b c d1]
- set result [expr ![file isdir d1] && [file isdir [file join tfad a b c d1]]]
+ list [file isdir d1] [file isdir [file join tfad a b c d1]]
+} -cleanup {
file delete -force [glob d1 tfad]
- set result
-} {1}
-
-
+} -result {0 1}
#
# TclMacCopyFile needs to be redone.
#
-test fCmd-22.5 {TclMacCopyFile: copy and overwrite in a single dir} {notRoot} {
+test fCmd-22.5 {TclMacCopyFile: copy and overwrite in a single dir} -setup {
catch {file delete -force -- tfa1 tfa2}
+} -constraints {notRoot} -body {
set s [createfile tfa1]
set s2 [createfile tfa2 q]
- set r1 [catch {file copy tfa1 tfa2}]
+ set result [catch {file copy tfa1 tfa2}]
file copy -force tfa1 tfa2
- set result [expr $r1 && [checkcontent tfa2 $s] && [checkcontent tfa1 $s]]
+ lappend result [checkcontent tfa2 $s] [checkcontent tfa1 $s]
+} -cleanup {
file delete tfa1 tfa2
- set result
-} {1}
+} -result {1 1 1}
#
# TclMacMkdir - basic cases are covered elsewhere.
@@ -2101,252 +2109,256 @@ test fCmd-22.5 {TclMacCopyFile: copy and overwrite in a single dir} {notRoot} {
# Error cases are not covered.
#
-test fCmd-23.1 {TclMacRmdir: trying to remove a nonempty directory} {notRoot} {
+test fCmd-23.1 {TclMacRmdir: trying to remove a nonempty directory} -setup {
catch {file delete -force -- tfad}
-
+} -constraints {notRoot} -body {
file mkdir [file join tfad dir]
-
- set result [catch {file delete tfad}]
- file delete -force tfad
- set result
-} {1}
+
+ list [catch {file delete tfad}] [file delete -force tfad]
+} -cleanup {
+ catch {file delete -force tfad}
+} -result {1 {}}
#
-# TclMacDeleteFile
+# TclMacDeleteFile
# Error cases are not covered.
#
-test fCmd-24.1 {TclMacDeleteFile: deleting a normal file} {notRoot} {
+test fCmd-24.1 {TclMacDeleteFile: deleting a normal file} -setup {
catch {file delete -force -- tfa1}
-
+} -constraints {notRoot} -body {
createfile tfa1
file delete tfa1
file exists tfa1
-} {0}
+} -cleanup {
+ catch {file delete -force tfa1}
+} -result {0}
#
# TclMacCopyDirectory
# Error cases are not covered.
#
-test fCmd-25.1 {TclMacCopyDirectory: copying a normal directory} {notRoot notFileSharing} {
+test fCmd-25.1 {TclMacCopyDirectory: copying a normal directory} -setup {
catch {file delete -force -- tfad1 tfad2}
-
+} -constraints {notRoot notFileSharing} -body {
file mkdir [file join tfad1 a b c]
file copy tfad1 tfad2
- set result [expr [file isdir [file join tfad1 a b c]] && [file isdir [file join tfad2 a b c]]]
+ list [file isdir [file join tfad1 a b c]] \
+ [file isdir [file join tfad2 a b c]]
+} -cleanup {
file delete -force tfad1 tfad2
- set result
-} {1}
-
-test fCmd-25.2 {TclMacCopyDirectory: copying a short path normal directory} {notRoot notFileSharing} {
+} -result {1 1}
+test fCmd-25.2 {TclMacCopyDirectory: copying a short path normal directory} -setup {
catch {file delete -force -- tfad1 tfad2}
-
+} -constraints {notRoot notFileSharing} -body {
file mkdir tfad1
file copy tfad1 tfad2
- set result [expr [file isdir tfad1] && [file isdir tfad2]]
+ list [file isdir tfad1] [file isdir tfad2]
+} -cleanup {
file delete tfad1 tfad2
- set result
-} {1}
-
-test fCmd-25.3 {TclMacCopyDirectory: copying dirs between different dirs} {notRoot notFileSharing} {
+} -result {1 1}
+test fCmd-25.3 {TclMacCopyDirectory: copying dirs between different dirs} -setup {
catch {file delete -force -- tfad1 tfad2}
-
+} -constraints {notRoot notFileSharing} -body {
file mkdir [file join tfad1 x y z]
file mkdir [file join tfad2 dir]
file copy tfad1 [file join tfad2 dir]
- set result [expr [file isdir [file join tfad1 x y z]] && [file isdir [file join tfad2 dir tfad1 x y z]]]
+ list [file isdir [file join tfad1 x y z]] \
+ [file isdir [file join tfad2 dir tfad1 x y z]]
+} -cleanup {
file delete -force tfad1 tfad2
- set result
-} {1}
+} -result {1 1}
#
# Functionality tests for TclDeleteFilesCmd
#
-test fCmd-26.1 {TclDeleteFilesCmd: delete symlink} {unixOnly notRoot} {
+test fCmd-26.1 {TclDeleteFilesCmd: delete symlink} -setup {
catch {file delete -force -- tfad1 tfad2}
-
+} -constraints {unix notRoot} -body {
file mkdir tfad1
file link -symbolic tfalink tfad1
file delete tfalink
- set r1 [file isdir tfad1]
- set r2 [file exists tfalink]
-
- set result [expr $r1 && !$r2]
+ list [file isdir tfad1] [file exists tfalink]
+} -cleanup {
file delete tfad1
- set result
-} {1}
-
-test fCmd-26.2 {TclDeleteFilesCmd: delete dir with symlink} {unixOnly notRoot} {
+ catch {file delete tfalink}
+} -result {1 0}
+test fCmd-26.2 {TclDeleteFilesCmd: delete dir with symlink} -setup {
catch {file delete -force -- tfad1 tfad2}
-
+} -constraints {unix notRoot} -body {
file mkdir tfad1
file mkdir tfad2
- file link -symbolic [file join tfad2 link] tfad1
+ file link -symbolic [file join tfad2 link] [file join .. tfad1]
file delete -force tfad2
- set r1 [file isdir tfad1]
- set r2 [file exists tfad2]
-
- set result [expr $r1 && !$r2]
+ list [file isdir tfad1] [file exists tfad2]
+} -cleanup {
file delete tfad1
- set result
-} {1}
-
-test fCmd-26.3 {TclDeleteFilesCmd: delete dangling symlink} {unixOnly notRoot} {
+} -result {1 0}
+test fCmd-26.3 {TclDeleteFilesCmd: delete dangling symlink} -setup {
catch {file delete -force -- tfad1 tfad2}
-
+} -constraints {unix notRoot} -body {
file mkdir tfad1
file link -symbolic tfad2 tfad1
file delete tfad1
file delete tfad2
- set r1 [file exists tfad1]
- set r2 [file exists tfad2]
-
- set result [expr !$r1 && !$r2]
- set result
-} {1}
+ list [file exists tfad1] [file exists tfad2]
+} -result {0 0}
-test fCmd-27.2 {TclFileAttrsCmd - Tcl_TranslateFileName fails} {testsetplatform} {
+test fCmd-27.2 {TclFileAttrsCmd - Tcl_TranslateFileName fails} -setup {
set platform [testgetplatform]
+} -constraints {testsetplatform} -body {
testsetplatform unix
- list [catch {file attributes ~_totally_bogus_user} msg] $msg [testsetplatform $platform]
-} {1 {user "_totally_bogus_user" doesn't exist} {}}
-test fCmd-27.3 {TclFileAttrsCmd - all attributes} {
+ file attributes ~_totally_bogus_user
+} -returnCodes error -cleanup {
+ testsetplatform $platform
+} -result {user "_totally_bogus_user" doesn't exist}
+test fCmd-27.3 {TclFileAttrsCmd - all attributes} -setup {
catch {file delete -force -- foo.tmp}
+} -body {
createfile foo.tmp
- list [catch {file attributes foo.tmp} msg] [expr {[llength $msg] > 0}] [file delete -force -- foo.tmp]
-} {0 1 {}}
-test fCmd-27.4 {TclFileAttrsCmd - getting one option} {
+ file attributes foo.tmp
+ # Must be non-empty result
+} -cleanup {
+ file delete -force -- foo.tmp
+} -match glob -result {?*}
+test fCmd-27.4 {TclFileAttrsCmd - getting one option} -setup {
catch {file delete -force -- foo.tmp}
+} -body {
createfile foo.tmp
set attrs [file attributes foo.tmp]
- list [catch {eval file attributes foo.tmp [lindex $attrs 0]}] [file delete -force -- foo.tmp]
-} {0 {}}
-
-# Find a group that exists on this Unix system, or else skip tests that
-# require Unix groups.
-if {$tcl_platform(platform) == "unix"} {
- ::tcltest::testConstraint foundGroup 0
- catch {
- set groupList [exec groups]
- set group [lindex $groupList 0]
- ::tcltest::testConstraint foundGroup 1
- }
-} else {
- ::tcltest::testConstraint foundGroup 1
-}
-
-test fCmd-27.5 {TclFileAttrsCmd - setting one option} {foundGroup} {
+ file attributes foo.tmp {*}[lindex $attrs 0]
+ # Any successful result will do
+} -cleanup {
+ file delete -force -- foo.tmp
+} -match glob -result *
+test fCmd-27.5 {TclFileAttrsCmd - setting one option} -setup {
catch {file delete -force -- foo.tmp}
+} -constraints {foundGroup} -body {
createfile foo.tmp
set attrs [file attributes foo.tmp]
- list [catch {eval file attributes foo.tmp [lrange $attrs 0 1]} msg] $msg [file delete -force -- foo.tmp]
-} {0 {} {}}
-test fCmd-27.6 {TclFileAttrsCmd - setting more than one option} {foundGroup} {
+ file attributes foo.tmp {*}[lrange $attrs 0 1]
+} -cleanup {
+ file delete -force -- foo.tmp
+} -result {}
+test fCmd-27.6 {TclFileAttrsCmd - setting more than one option} -setup {
catch {file delete -force -- foo.tmp}
+} -constraints {foundGroup} -body {
createfile foo.tmp
set attrs [file attributes foo.tmp]
- list [catch {eval file attributes foo.tmp [lrange $attrs 0 3]} msg] $msg [file delete -force -- foo.tmp]
-} {0 {} {}}
-
-if {[string equal $tcl_platform(platform) "windows"]} {
- if {[string index $tcl_platform(osVersion) 0] >= 5 \
- && ([lindex [file system [temporaryDirectory]] 1] == "NTFS")} {
- tcltest::testConstraint linkDirectory 1
- tcltest::testConstraint linkFile 1
- } else {
- tcltest::testConstraint linkDirectory 0
- tcltest::testConstraint linkFile 0
- }
-} else {
- tcltest::testConstraint linkFile 1
- tcltest::testConstraint linkDirectory 1
+ file attributes foo.tmp {*}[lrange $attrs 0 3]
+} -cleanup {
+ file delete -force -- foo.tmp
+} -result {}
+
+if {
+ [testConstraint win] &&
+ ([string index $tcl_platform(osVersion) 0] < 5
+ || [lindex [file system [temporaryDirectory]] 1] ne "NTFS")
+} then {
+ testConstraint linkDirectory 0
+ testConstraint linkFile 0
}
-test fCmd-28.1 {file link} {
- list [catch {file link} msg] $msg
-} {1 {wrong # args: should be "file link ?-linktype? linkname ?target?"}}
-
-test fCmd-28.2 {file link} {
- list [catch {file link a b c d} msg] $msg
-} {1 {wrong # args: should be "file link ?-linktype? linkname ?target?"}}
-
-test fCmd-28.3 {file link} {
- list [catch {file link abc b c} msg] $msg
-} {1 {bad switch "abc": must be -symbolic or -hard}}
-
-test fCmd-28.4 {file link} {
- list [catch {file link -abc b c} msg] $msg
-} {1 {bad switch "-abc": must be -symbolic or -hard}}
+test fCmd-28.1 {file link} -returnCodes error -body {
+ file link
+} -result {wrong # args: should be "file link ?-linktype? linkname ?target?"}
+test fCmd-28.2 {file link} -returnCodes error -body {
+ file link a b c d
+} -result {wrong # args: should be "file link ?-linktype? linkname ?target?"}
+test fCmd-28.3 {file link} -returnCodes error -body {
+ file link abc b c
+} -result {bad switch "abc": must be -symbolic or -hard}
+test fCmd-28.4 {file link} -returnCodes error -body {
+ file link -abc b c
+} -result {bad switch "-abc": must be -symbolic or -hard}
cd [workingDirectory]
-
makeDirectory abc.dir
makeDirectory abc2.dir
makeFile contents abc.file
makeFile contents abc2.file
-
cd [temporaryDirectory]
-test fCmd-28.5 {file link: source already exists} {linkDirectory} {
+test fCmd-28.5 {file link: source already exists} -setup {
cd [temporaryDirectory]
- set res [list [catch {file link abc.dir abc2.dir} msg] $msg]
+} -constraints {linkDirectory} -body {
+ file link abc.dir abc2.dir
+} -returnCodes error -cleanup {
cd [workingDirectory]
- set res
-} {1 {could not create new link "abc.dir": that path already exists}}
-
-test fCmd-28.6 {file link: unsupported operation} {linkDirectory macOrWin} {
+} -result {could not create new link "abc.dir": that path already exists}
+test fCmd-28.6 {file link: unsupported operation} -setup {
cd [temporaryDirectory]
- set res [list [catch {file link -hard abc.link abc.dir} msg] $msg]
+} -constraints {linkDirectory win} -body {
+ file link -hard abc.link abc.dir
+} -returnCodes error -cleanup {
cd [workingDirectory]
- set res
-} {1 {could not create new link "abc.link" pointing to "abc.dir": illegal operation on a directory}}
-
-test fCmd-28.7 {file link: source already exists} {linkFile} {
+} -result {could not create new link "abc.link" pointing to "abc.dir": illegal operation on a directory}
+test fCmd-28.7 {file link: source already exists} -setup {
cd [temporaryDirectory]
- set res [list [catch {file link abc.file abc2.file} msg] $msg]
+} -constraints {linkFile} -body {
+ file link abc.file abc2.file
+} -returnCodes error -cleanup {
cd [workingDirectory]
- set res
-} {1 {could not create new link "abc.file": that path already exists}}
-
-test fCmd-28.8 {file link} {linkFile winOnly} {
+} -result {could not create new link "abc.file": that path already exists}
+test fCmd-28.8 {file link} -constraints {linkFile win} -setup {
cd [temporaryDirectory]
- set res [list [catch {file link -symbolic abc.link abc.file} msg] $msg]
+} -body {
+ file link -symbolic abc.link abc.file
+} -returnCodes error -cleanup {
cd [workingDirectory]
- set res
-} {1 {could not create new link "abc.link" pointing to "abc.file": not a directory}}
-
-test fCmd-28.9 {file link: success with file} {linkFile} {
+} -result {could not create new link "abc.link" pointing to "abc.file": not a directory}
+test fCmd-28.9 {file link: success with file} -constraints {linkFile} -setup {
cd [temporaryDirectory]
file delete -force abc.link
- set res [list [catch {file link abc.link abc.file} msg] $msg]
+} -body {
+ file link abc.link abc.file
+} -cleanup {
cd [workingDirectory]
- set res
-} {0 abc.file}
-
+} -result abc.file
+test fCmd-28.9.1 {file link: success with file} -setup {
+ cd [temporaryDirectory]
+ file delete -force abc.link
+} -constraints {linkFile win} -body {
+ file stat abc.file arr
+ set res $arr(nlink)
+ lappend res [catch {file link abc.link abc.file} msg] $msg
+ file stat abc.file arr
+ lappend res $arr(nlink)
+} -cleanup {
+ cd [workingDirectory]
+} -result {1 0 abc.file 2}
cd [temporaryDirectory]
catch {file delete -force abc.link}
cd [workingDirectory]
-
-test fCmd-28.10 {file link: linking to nonexistent path} {linkDirectory} {
+test fCmd-28.10 {file link: linking to nonexistent path} -setup {
cd [temporaryDirectory]
file delete -force abc.link
- set res [list [catch {file link abc.link abc2.doesnt} msg] $msg]
+} -constraints {linkDirectory} -body {
+ file link abc.link abc2.doesnt
+} -returnCodes error -cleanup {
cd [workingDirectory]
- set res
-} {1 {could not create new link "abc.link" since target "abc2.doesnt" doesn't exist}}
-
-test fCmd-28.11 {file link: success with directory} {linkDirectory} {
+} -result {could not create new link "abc.link": target "abc2.doesnt" doesn't exist}
+test fCmd-28.10.1 {file link: linking to nonexistent path} -setup {
cd [temporaryDirectory]
file delete -force abc.link
- set res [list [catch {file link abc.link abc.dir} msg] $msg]
+} -constraints {linkDirectory} -body {
+ file link doesnt/abc.link abc.dir
+} -returnCodes error -cleanup {
cd [workingDirectory]
- set res
-} {0 abc.dir}
-
-test fCmd-28.12 {file link: cd into a link} {linkDirectory} {
+} -result {could not create new link "doesnt/abc.link": no such file or directory}
+test fCmd-28.11 {file link: success with directory} -setup {
cd [temporaryDirectory]
file delete -force abc.link
+} -constraints {linkDirectory} -body {
+ file link abc.link abc.dir
+} -cleanup {
+ cd [workingDirectory]
+} -result abc.dir
+test fCmd-28.12 {file link: cd into a link} -setup {
+ cd [temporaryDirectory]
+ file delete -force abc.link
+} -constraints {linkDirectory} -body {
file link abc.link abc.dir
set orig [pwd]
cd abc.link
@@ -2354,94 +2366,140 @@ test fCmd-28.12 {file link: cd into a link} {linkDirectory} {
cd ..
set up [pwd]
cd $orig
- # now '$up' should be either $orig or [file dirname abc.dir],
- # depending on whether 'cd' actually moves to the destination
- # of a link, or simply treats the link as a directory.
- # (on windows the former, on unix the latter, I believe)
- if {([file normalize $up] != [file normalize $orig]) \
- && ([file normalize $up] != [file normalize [file dirname abc.dir]])} {
- set res "wrong directory with 'cd $link ; cd ..'"
+ # now '$up' should be either $orig or [file dirname abc.dir], depending on
+ # whether 'cd' actually moves to the destination of a link, or simply
+ # treats the link as a directory. (On windows the former, on unix the
+ # latter, I believe)
+ if {
+ ([file normalize $up] ne [file normalize $orig]) &&
+ ([file normalize $up] ne [file normalize [file dirname abc.dir]])
+ } then {
+ return "wrong directory with 'cd abc.link ; cd ..': \
+ \"[file normalize $up]\" should be \"[file normalize $orig]\"\
+ or \"[file normalize [file dirname abc.dir]]\""
} else {
- set res "ok"
+ return "ok"
}
+} -cleanup {
cd [workingDirectory]
- set res
-} {ok}
-
-test fCmd-28.13 {file link} {linkDirectory} {
- # duplicate link throws error
+} -result ok
+test fCmd-28.13 {file link} -constraints {linkDirectory} -setup {
cd [temporaryDirectory]
- set res [list [catch {file link abc.link abc.dir} msg] $msg]
+} -body {
+ # duplicate link throws error
+ file link abc.link abc.dir
+} -returnCodes error -cleanup {
cd [workingDirectory]
- set res
-} {1 {could not create new link "abc.link": that path already exists}}
-
-test fCmd-28.14 {file link: deletes link not dir} {linkDirectory} {
+} -result {could not create new link "abc.link": that path already exists}
+test fCmd-28.14 {file link: deletes link not dir} -setup {
cd [temporaryDirectory]
+} -constraints {linkDirectory} -body {
file delete -force abc.link
- set res [list [file exists abc.link] [file exists abc.dir]]
+ list [file exists abc.link] [file exists abc.dir]
+} -cleanup {
cd [workingDirectory]
- set res
-} {0 1}
-
-test fCmd-28.15.1 {file link: copies link not dir} {linkDirectory dontCopyLinks} {
+} -result {0 1}
+test fCmd-28.15.1 {file link: copies link not dir} -setup {
cd [temporaryDirectory]
file delete -force abc.link
+} -constraints {linkDirectory dontCopyLinks} -body {
file link abc.link abc.dir
file copy abc.link abc2.link
- # abc2.linkdir was a copy of a link to a dir, so it should end up as
- # a directory, not a link (links trace to endpoint).
- set res [list [file type abc2.link] [file tail [file link abc.link]]]
+ # abc2.linkdir was a copy of a link to a dir, so it should end up as a
+ # directory, not a link (links trace to endpoint).
+ list [file type abc2.link] [file tail [file link abc.link]]
+} -cleanup {
cd [workingDirectory]
- set res
-} {directory abc.dir}
-test fCmd-28.15.2 {file link: copies link not dir} {linkDirectory} {
+} -result {directory abc.dir}
+test fCmd-28.15.2 {file link: copies link not dir} -setup {
cd [temporaryDirectory]
file delete -force abc.link
+} -constraints {linkDirectory} -body {
file link abc.link abc.dir
file copy abc.link abc2.link
- set res [list [file type abc2.link] [file tail [file link abc2.link]]]
+ list [file type abc2.link] [file tail [file link abc2.link]]
+} -cleanup {
cd [workingDirectory]
- set res
-} {link abc.dir}
-
+} -result {link abc.dir}
cd [temporaryDirectory]
file delete -force abc.link
file delete -force abc2.link
-
+cd abc.dir
+file delete -force abc.file
+file delete -force abc2.file
+cd ..
file copy abc.file abc.dir
file copy abc2.file abc.dir
cd [workingDirectory]
-
-test fCmd-28.16 {file link: glob inside link} {linkDirectory} {
+test fCmd-28.16 {file link: glob inside link} -setup {
cd [temporaryDirectory]
file delete -force abc.link
+} -constraints {linkDirectory} -body {
file link abc.link abc.dir
- set res [lsort [glob -dir abc.link -tails *]]
+ lsort [glob -dir abc.link -tails *]
+} -cleanup {
cd [workingDirectory]
- set res
-} [lsort [list abc.file abc2.file]]
-
-test fCmd-28.17 {file link: glob -type l} {linkDirectory} {
+} -result {abc.file abc2.file}
+test fCmd-28.17 {file link: glob -type l} -setup {
cd [temporaryDirectory]
- set res [glob -dir [pwd] -type l -tails abc*]
+} -constraints {linkDirectory} -body {
+ glob -dir [pwd] -type l -tails abc*
+} -cleanup {
cd [workingDirectory]
- set res
-} {abc.link}
-
-test fCmd-28.18 {file link: glob -type d} {linkDirectory} {
+} -result {abc.link}
+test fCmd-28.18 {file link: glob -type d} -constraints linkDirectory -setup {
+ cd [temporaryDirectory]
+} -body {
+ lsort [glob -dir [pwd] -type d -tails abc*]
+} -cleanup {
+ cd [workingDirectory]
+} -result [lsort [list abc.link abc.dir abc2.dir]]
+test fCmd-28.19 {file link: relative paths} -setup {
+ cd [temporaryDirectory]
+} -constraints {win linkDirectory} -body {
+ file mkdir d1/d2/d3
+ file link d1/l2 d1/d2
+} -cleanup {
+ catch {file delete -force d1}
+ cd [workingDirectory]
+} -result d1/d2
+test fCmd-28.20 {file link: relative paths} -setup {
+ cd [temporaryDirectory]
+} -constraints {unix linkDirectory} -body {
+ file mkdir d1/d2/d3
+ file link d1/l2 d1/d2
+} -returnCodes error -cleanup {
+ catch {file delete -force d1}
+ cd [workingDirectory]
+} -result {could not create new link "d1/l2": target "d1/d2" doesn't exist}
+test fCmd-28.21 {file link: relative paths} -setup {
+ cd [temporaryDirectory]
+} -constraints {unix linkDirectory} -body {
+ file mkdir d1/d2/d3
+ file link d1/l2 d2
+} -cleanup {
+ catch {file delete -force d1}
+ cd [workingDirectory]
+} -result d2
+test fCmd-28.22 {file link: relative paths} -setup {
cd [temporaryDirectory]
- set res [lsort [glob -dir [pwd] -type d -tails abc*]]
+} -constraints {unix linkDirectory} -body {
+ file mkdir d1/d2/d3
+ catch {file delete -force d1/l2}
+ file link d1/l2 d2/d3
+} -cleanup {
+ catch {file delete -force d1}
cd [workingDirectory]
- set res
-} [lsort [list abc.link abc.dir abc2.dir]]
+} -result d2/d3
-test fCmd-29.1 {weird memory corruption fault} {
- catch {set res [open [file join ~a_totally_bogus_user_id/foo bar]]}
-} 1
+test fCmd-29.1 {weird memory corruption fault} -body {
+ open [file join ~a_totally_bogus_user_id/foo bar]
+} -returnCodes error -match glob -result *
cd [temporaryDirectory]
file delete -force abc.link
+file delete -force d1/d2
+file delete -force d1
cd [workingDirectory]
removeFile abc2.file
@@ -2449,6 +2507,27 @@ removeFile abc.file
removeDirectory abc2.dir
removeDirectory abc.dir
+test fCmd-30.1 {file writable on 'My Documents'} -constraints {win 2000orNewer} -body {
+ set mydocsname "~/My Documents"
+ # Would be good to localise this name, since this test will only function
+ # on english-speaking windows otherwise
+ if {[file exists $mydocsname]} {
+ return [file writable $mydocsname]
+ }
+ return 1
+} -result {1}
+test fCmd-30.2 {file readable on 'NTUSER.DAT'} -constraints {win 2000orNewer knownBug} -body {
+ # Apparently the OS has this file open with exclusive permissions Windows
+ # doesn't provide any way to determine that fact without actually trying
+ # to open the file (open NTUSER.dat r), which fails. Hence this isn't
+ # really a knownBug in Tcl, but an OS limitation. But, perhaps in the
+ # future that limitation will be lifted.
+ if {[file exists "~/NTUSER.DAT"]} {
+ return [file readable "~/NTUSER.DAT"]
+ }
+ return 0
+} -result {0}
+
# cleanup
cleanup
::tcltest::cleanupTests
diff --git a/tests/fileName.test b/tests/fileName.test
index 6c80826..c613068 100644
--- a/tests/fileName.test
+++ b/tests/fileName.test
@@ -11,18 +11,35 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest 2
+ package require tcltest
namespace import -force ::tcltest::*
}
-tcltest::testConstraint testsetplatform [string equal testsetplatform [info commands testsetplatform]]
-tcltest::testConstraint testtranslatefilename [string equal testtranslatefilename [info commands testtranslatefilename]]
+testConstraint testsetplatform [llength [info commands testsetplatform]]
+testConstraint testtranslatefilename [llength [info commands testtranslatefilename]]
+testConstraint linkDirectory 1
+testConstraint symbolicLinkFile 1
+if {[testConstraint win]} {
+ if {[string index $tcl_platform(osVersion) 0] < 5 \
+ || [lindex [file system [temporaryDirectory]] 1] ne "NTFS"} {
+ testConstraint linkDirectory 0
+ }
+ testConstraint symbolicLinkFile 0
+}
global env
-if {[tcltest::testConstraint testsetplatform]} {
+if {[testConstraint testsetplatform]} {
set platform [testgetplatform]
}
+# Caution: when using 'testsetplatform' to test different file
+# name platform descriptions in this file, one must be very
+# careful not to combine such platform manipulation with
+# commands like 'cd', 'pwd'. That is because the latter commands
+# operate on the real filesystem but will potentially have their
+# logic routed through the wrong generic code paths if we've
+# used 'testsetplatform'. This can lead to serious problems,
+# even crashes.
test filename-1.1 {Tcl_GetPathType: unix} {testsetplatform} {
testsetplatform unix
file pathtype /
@@ -56,115 +73,6 @@ test filename-1.8 {Tcl_GetPathType: unix} {testsetplatform} {
file pathtype ./~foo
} relative
-test filename-2.1 {Tcl_GetPathType: mac, denerate names} {testsetplatform} {
- testsetplatform mac
- file pathtype /
-} relative
-test filename-2.2 {Tcl_GetPathType: mac, denerate names} {testsetplatform} {
- testsetplatform mac
- file pathtype /.
-} relative
-test filename-2.3 {Tcl_GetPathType: mac, denerate names} {testsetplatform} {
- testsetplatform mac
- file pathtype /..
-} relative
-test filename-2.4 {Tcl_GetPathType: mac, denerate names} {testsetplatform} {
- testsetplatform mac
- file pathtype //.//
-} relative
-test filename-2.5 {Tcl_GetPathType: mac, denerate names} {testsetplatform} {
- testsetplatform mac
- file pathtype //.//../.
-} relative
-test filename-2.6 {Tcl_GetPathType: mac, tilde names} {testsetplatform} {
- testsetplatform mac
- file pathtype ~
-} absolute
-test filename-2.7 {Tcl_GetPathType: mac, tilde names} {testsetplatform} {
- testsetplatform mac
- file pathtype ~:
-} absolute
-test filename-2.8 {Tcl_GetPathType: mac, tilde names} {testsetplatform} {
- testsetplatform mac
- file pathtype ~:foo
-} absolute
-test filename-2.9 {Tcl_GetPathType: mac, tilde names} {testsetplatform} {
- testsetplatform mac
- file pathtype ~/
-} absolute
-test filename-2.10 {Tcl_GetPathType: mac, tilde names} {testsetplatform} {
- testsetplatform mac
- file pathtype ~/foo
-} absolute
-test filename-2.11 {Tcl_GetPathType: mac, unix-style names} {testsetplatform} {
- testsetplatform mac
- file pathtype /foo
-} absolute
-test filename-2.12 {Tcl_GetPathType: mac, unix-style names} {testsetplatform} {
- testsetplatform mac
- file pathtype /./foo
-} absolute
-test filename-2.13 {Tcl_GetPathType: mac, unix-style names} {testsetplatform} {
- testsetplatform mac
- file pathtype /..//./foo
-} absolute
-test filename-2.14 {Tcl_GetPathType: mac, unix-style names} {testsetplatform} {
- testsetplatform mac
- file pathtype /foo/bar
-} absolute
-test filename-2.15 {Tcl_GetPathType: mac, unix-style names} {testsetplatform} {
- testsetplatform mac
- file pathtype foo/bar
-} relative
-test filename-2.16 {Tcl_GetPathType: mac, mac-style names} {testsetplatform} {
- testsetplatform mac
- file pathtype :
-} relative
-test filename-2.17 {Tcl_GetPathType: mac, mac-style names} {testsetplatform} {
- testsetplatform mac
- file pathtype :foo
-} relative
-test filename-2.18 {Tcl_GetPathType: mac, mac-style names} {testsetplatform} {
- testsetplatform mac
- file pathtype foo:
-} absolute
-test filename-2.19 {Tcl_GetPathType: mac, mac-style names} {testsetplatform} {
- testsetplatform mac
- file pathtype foo:bar
-} absolute
-test filename-2.20 {Tcl_GetPathType: mac, mac-style names} {testsetplatform} {
- testsetplatform mac
- file pathtype :foo:bar
-} relative
-test filename-2.21 {Tcl_GetPathType: mac, mac-style names} {testsetplatform} {
- testsetplatform mac
- file pathtype ::foo:bar
-} relative
-test filename-2.22 {Tcl_GetPathType: mac, mac-style names} {testsetplatform} {
- testsetplatform mac
- file pathtype ~foo
-} absolute
-test filename-2.23 {Tcl_GetPathType: mac, mac-style names} {testsetplatform} {
- testsetplatform mac
- file pathtype :~foo
-} relative
-test filename-2.24 {Tcl_GetPathType: mac, mac-style names} {testsetplatform} {
- testsetplatform mac
- file pathtype ~foo:
-} absolute
-test filename-2.25 {Tcl_GetPathType: mac, mac-style names} {testsetplatform} {
- testsetplatform mac
- file pathtype foo/bar:
-} absolute
-test filename-2.26 {Tcl_GetPathType: mac, mac-style names} {testsetplatform} {
- testsetplatform mac
- file pathtype /foo:
-} absolute
-test filename-2.27 {Tcl_GetPathType: mac, mac-style names} {testsetplatform} {
- testsetplatform mac
- file pathtype foo
-} relative
-
test filename-3.1 {Tcl_GetPathType: windows} {testsetplatform} {
testsetplatform windows
file pathtype /
@@ -303,7 +211,7 @@ test filename-4.18 {Tcl_SplitPath: unix} {testsetplatform} {
file split foo/bar~/baz
} {foo bar~ baz}
-if {[tcltest::testConstraint testsetplatform]} {
+if {[testConstraint testsetplatform]} {
testsetplatform $platform
}
@@ -333,211 +241,6 @@ test filename-4.19 {Tcl_SplitPath} {
list $res $err
} {0 tildetmp/~tilde}
-test filename-5.1 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split a:b
-} {a: b}
-test filename-5.2 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split a:b:c
-} {a: b c}
-test filename-5.3 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split a:b:c:
-} {a: b c}
-test filename-5.4 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split a:
-} {a:}
-test filename-5.5 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split a::
-} {a: ::}
-test filename-5.6 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split a:::
-} {a: :: ::}
-test filename-5.7 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split :a
-} {a}
-test filename-5.8 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split :a::
-} {a ::}
-test filename-5.9 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split :
-} {:}
-test filename-5.10 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split ::
-} {::}
-test filename-5.11 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split :::
-} {:: ::}
-test filename-5.12 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split a:::b
-} {a: :: :: b}
-test filename-5.13 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split /a:b
-} {/a: b}
-test filename-5.14 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split ~:
-} {~:}
-test filename-5.15 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split ~/:
-} {~/:}
-test filename-5.16 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split ~:foo
-} {~: foo}
-test filename-5.17 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split ~/foo
-} {~: foo}
-test filename-5.18 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split ~foo:
-} {~foo:}
-test filename-5.19 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split a:~foo
-} {a: :~foo}
-test filename-5.20 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split /
-} {:/}
-test filename-5.21 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split a:b/c
-} {a: :b/c}
-test filename-5.22 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split /foo
-} {foo:}
-test filename-5.23 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split /a/b
-} {a: b}
-test filename-5.24 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split /a/b/foo
-} {a: b foo}
-test filename-5.25 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split a/b
-} {a b}
-test filename-5.26 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split ./foo/bar
-} {: foo bar}
-test filename-5.27 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split ../foo/bar
-} {:: foo bar}
-test filename-5.28 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split {}
-} {}
-test filename-5.29 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split .
-} {:}
-test filename-5.30 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split ././
-} {: :}
-test filename-5.31 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split ././.
-} {: : :}
-test filename-5.32 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split ../
-} {::}
-test filename-5.33 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split ..
-} {::}
-test filename-5.34 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split ../..
-} {:: ::}
-test filename-5.35 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split //foo
-} {foo:}
-test filename-5.36 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split foo//bar
-} {foo bar}
-test filename-5.37 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split ~foo
-} {~foo:}
-test filename-5.38 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split ~
-} {~:}
-test filename-5.39 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split foo
-} {foo}
-test filename-5.40 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split ~/
-} {~:}
-test filename-5.41 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split ~foo/~bar
-} {~foo: :~bar}
-test filename-5.42 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split ~foo/~bar/~baz
-} {~foo: :~bar :~baz}
-test filename-5.43 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split foo/bar~/baz
-} {foo bar~ baz}
-test filename-5.44 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split a/../b
-} {a :: b}
-test filename-5.45 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split a/../../b
-} {a :: :: b}
-test filename-5.46 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split a/.././../b
-} {a :: : :: b}
-test filename-5.47 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split /../bar
-} {bar:}
-test filename-5.48 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split /./bar
-} {bar:}
-test filename-5.49 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split //.//.././bar
-} {bar:}
-test filename-5.50 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split /..
-} {:/..}
-test filename-5.51 {Tcl_SplitPath: mac} {testsetplatform} {
- testsetplatform mac
- file split //.//.././
-} {://.//.././}
-
test filename-6.1 {Tcl_SplitPath: win} {testsetplatform} {
testsetplatform win
file split /
@@ -732,94 +435,6 @@ test filename-7.18 {Tcl_JoinPath: unix} {testsetplatform} {
file join /// a b
} {/a/b}
-test filename-8.1 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join a b
-} {:a:b}
-test filename-8.2 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join :a b
-} {:a:b}
-test filename-8.3 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join a b:
-} {b:}
-test filename-8.4 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join a: :b
-} {a:b}
-test filename-8.5 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join a: :b:
-} {a:b}
-test filename-8.6 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join a :: b
-} {:a::b}
-test filename-8.7 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join a :: :: b
-} {:a:::b}
-test filename-8.8 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join a ::: b
-} {:a:::b}
-test filename-8.9 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join a: b:
-} {b:}
-test filename-8.10 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join /a/b
-} {a:b}
-test filename-8.11 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join /a/b c/d
-} {a:b:c:d}
-test filename-8.12 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join /a/b :c:d
-} {a:b:c:d}
-test filename-8.13 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join ~ foo
-} {~:foo}
-test filename-8.14 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join :: ::
-} {:::}
-test filename-8.15 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join a: ::
-} {a::}
-test filename-8.16 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join a {} b
-} {:a:b}
-test filename-8.17 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join a::: b
-} {a:::b}
-test filename-8.18 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join a : : :
-} {:a}
-test filename-8.19 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join :
-} {:}
-test filename-8.20 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join : a
-} {:a}
-test filename-8.21 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join a: :b/c
-} {a:b/c}
-test filename-8.22 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- file join :a :b/c
-} {:a:b/c}
test filename-9.1 {Tcl_JoinPath: win} {testsetplatform} {
testsetplatform win
@@ -909,14 +524,18 @@ test filename-9.19.1 {Tcl_JoinPath: win} {testsetplatform} {
[file join C:/blah {foo\bar}] \
[file join C:/blah C:/blah {foo\bar}]
} {foo/bar C:/blah/foo/bar C:/blah/foo/bar}
-test filename-9.19.2 {Tcl_JoinPath: win} {testsetplatform winOnly} {
+test filename-9.19.2 {Tcl_JoinPath: win} {testsetplatform win} {
testsetplatform win
set res {}
lappend res \
[file join {foo\bar}] \
[file join [pwd] {foo\bar}] \
[file join [pwd] [pwd] {foo\bar}]
- string map [list [pwd] pwd] $res
+ set nres {}
+ foreach elt $res {
+ lappend nres [string map [list [pwd] pwd] $elt]
+ }
+ set nres
} {foo/bar pwd/foo/bar pwd/foo/bar}
test filename-9.20 {Tcl_JoinPath: unix} {testsetplatform} {
testsetplatform unix
@@ -926,22 +545,6 @@ test filename-9.20 {Tcl_JoinPath: unix} {testsetplatform} {
[file join /x {/foo/bar}] \
[file join /x /x {/foo/bar}]
} {/foo/bar /foo/bar /foo/bar}
-test filename-9.21 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- set res {}
- lappend res \
- [file join {/foo/bar}] \
- [file join drive: {/foo/bar}] \
- [file join drive: drive: {/foo/bar}]
-} {foo:bar foo:bar foo:bar}
-test filename-9.22 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- set res {}
- lappend res \
- [file join {foo:bar}] \
- [file join drive: {foo:bar}] \
- [file join drive: drive: {foo:bar}]
-} {foo:bar foo:bar foo:bar}
test filename-9.23 {Tcl_JoinPath: win} {testsetplatform} {
testsetplatform win
set res {}
@@ -960,24 +563,6 @@ test filename-9.24 {Tcl_JoinPath: unix} {testsetplatform} {
[file join /x /x {foo/bar}]
string map [list /x ""] $res
} {foo/bar /foo/bar /foo/bar}
-test filename-9.25 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- set res {}
- lappend res \
- [file join {foo/bar}] \
- [file join drive: {foo/bar}] \
- [file join drive: drive: {foo/bar}]
- string map [list drive: ""] $res
-} {:foo:bar foo:bar foo:bar}
-test filename-9.26 {Tcl_JoinPath: mac} {testsetplatform} {
- testsetplatform mac
- set res {}
- lappend res \
- [file join {:foo:bar}] \
- [file join drive: {:foo:bar}] \
- [file join drive: drive: {:foo:bar}]
- string map [list drive: ""] $res
-} {:foo:bar foo:bar foo:bar}
test filename-10.1 {Tcl_TranslateFileName} {testsetplatform} {
testsetplatform unix
@@ -991,14 +576,10 @@ test filename-10.3 {Tcl_TranslateFileName} {testsetplatform} {
testsetplatform windows
list [catch {testtranslatefilename {c:/\\foo/}} msg] $msg
} {0 {c:\foo}}
-test filename-10.4 {Tcl_TranslateFileName} {testsetplatform} {
- testsetplatform mac
- list [catch {testtranslatefilename foo} msg] $msg
-} {0 :foo}
-test filename-10.5 {Tcl_TranslateFileName} {testsetplatform} {
- testsetplatform mac
- list [catch {testtranslatefilename :~foo} msg] $msg
-} {0 :~foo}
+test filename-10.3.1 {Tcl_TranslateFileName} {testsetplatform} {
+ testsetplatform windows
+ list [catch {testtranslatefilename {c://///}} msg] $msg
+} {0 c:\\}
test filename-10.6 {Tcl_TranslateFileName} {testsetplatform} {
global env
set temp $env(HOME)
@@ -1044,60 +625,6 @@ test filename-10.10 {Tcl_TranslateFileName} {testsetplatform} {
set env(HOME) $temp
set result
} {0 /home/test/foo}
-test filename-10.11 {Tcl_TranslateFileName} {testsetplatform} {
- global env
- set temp $env(HOME)
- set env(HOME) "Root:"
- testsetplatform mac
- set result [list [catch {testtranslatefilename ~/foo} msg] $msg]
- set env(HOME) $temp
- set result
-} {0 Root:foo}
-test filename-10.12 {Tcl_TranslateFileName} {testsetplatform} {
- global env
- set temp $env(HOME)
- set env(HOME) "Root:home"
- testsetplatform mac
- set result [list [catch {testtranslatefilename ~/foo} msg] $msg]
- set env(HOME) $temp
- set result
-} {0 Root:home:foo}
-test filename-10.13 {Tcl_TranslateFileName} {testsetplatform} {
- global env
- set temp $env(HOME)
- set env(HOME) "Root:home"
- testsetplatform mac
- set result [list [catch {testtranslatefilename ~::foo} msg] $msg]
- set env(HOME) $temp
- set result
-} {0 Root:home::foo}
-test filename-10.14 {Tcl_TranslateFileName} {testsetplatform} {
- global env
- set temp $env(HOME)
- set env(HOME) "Root:home"
- testsetplatform mac
- set result [list [catch {testtranslatefilename ~} msg] $msg]
- set env(HOME) $temp
- set result
-} {0 Root:home}
-test filename-10.15 {Tcl_TranslateFileName} {testsetplatform} {
- global env
- set temp $env(HOME)
- set env(HOME) "Root:home:"
- testsetplatform mac
- set result [list [catch {testtranslatefilename ~::foo} msg] $msg]
- set env(HOME) $temp
- set result
-} {0 Root:home::foo}
-test filename-10.16 {Tcl_TranslateFileName} {testsetplatform} {
- global env
- set temp $env(HOME)
- set env(HOME) "Root:home::"
- testsetplatform mac
- set result [list [catch {testtranslatefilename ~::foo} msg] $msg]
- set env(HOME) $temp
- set result
-} {0 Root:home:::foo}
test filename-10.17 {Tcl_TranslateFileName} {testsetplatform} {
global env
set temp $env(HOME)
@@ -1142,15 +669,15 @@ test filename-10.22 {Tcl_TranslateFileName} {testsetplatform} {
list [catch {testtranslatefilename foo//bar} msg] $msg
} {0 {foo\bar}}
-if {[tcltest::testConstraint testsetplatform]} {
+if {[testConstraint testsetplatform]} {
testsetplatform $platform
}
-test filename-10.23 {Tcl_TranslateFileName} {unixOnly nonPortable} {
+test filename-10.23 {Tcl_TranslateFileName} {nonPortable} {
# this test fails if ~ouster is not /home/ouster
list [catch {testtranslatefilename ~ouster} msg] $msg
} {0 /home/ouster}
-test filename-10.24 {Tcl_TranslateFileName} {unixOnly nonPortable} {
+test filename-10.24 {Tcl_TranslateFileName} {nonPortable} {
# this test fails if ~ouster is not /home/ouster
list [catch {testtranslatefilename ~ouster/foo} msg] $msg
} {0 /home/ouster/foo}
@@ -1169,8 +696,8 @@ test filename-11.4 {Tcl_GlobCmd} {
list [catch {glob -nocomplain} msg] $msg
} {1 {wrong # args: should be "glob ?switches? name ?name ...?"}}
test filename-11.5 {Tcl_GlobCmd} {
- list [catch {glob -nocomplain ~xyqrszzz} msg] $msg
-} {0 {}}
+ list [catch {glob -nocomplain * ~xyqrszzz} msg] $msg
+} {1 {user "xyqrszzz" doesn't exist}}
test filename-11.6 {Tcl_GlobCmd} {
list [catch {glob ~xyqrszzz} msg] $msg
} {1 {user "xyqrszzz" doesn't exist}}
@@ -1187,7 +714,7 @@ test filename-11.9 {Tcl_GlobCmd} {testsetplatform} {
test filename-11.10 {Tcl_GlobCmd} {testsetplatform} {
testsetplatform unix
list [catch {glob -nocomplain ~\\xyqrszzz/bar} msg] $msg
-} {0 {}}
+} {1 {user "\xyqrszzz" doesn't exist}}
test filename-11.11 {Tcl_GlobCmd} {testsetplatform} {
testsetplatform unix
list [catch {glob ~xyqrszzz\\/\\bar} msg] $msg
@@ -1201,7 +728,7 @@ test filename-11.12 {Tcl_GlobCmd} {testsetplatform} {
set x
} {1 {couldn't find HOME environment variable to expand path}}
-if {[tcltest::testConstraint testsetplatform]} {
+if {[testConstraint testsetplatform]} {
testsetplatform $platform
}
@@ -1241,7 +768,7 @@ test filename-11.16 {Tcl_GlobCmd} {
set globname "globTest"
set horribleglobname "glob\[\{Test"
-test filename-11.17 {Tcl_GlobCmd} {unixOnly} {
+test filename-11.17 {Tcl_GlobCmd} {unix} {
list [catch {lsort [glob -directory $globname *]} msg] $msg
} [list 0 [lsort [list [file join $globname a1] [file join $globname a2]\
[file join $globname a3]\
@@ -1249,7 +776,7 @@ test filename-11.17 {Tcl_GlobCmd} {unixOnly} {
[file join $globname x,z1.c]\
[file join $globname x1.c]\
[file join $globname y1.c] [file join $globname z1.c]]]]
-test filename-11.17.1 {Tcl_GlobCmd} {pcOnly macOnly} {
+test filename-11.17.1 {Tcl_GlobCmd} {win} {
list [catch {lsort [glob -directory $globname *]} msg] $msg
} [list 0 [lsort [list [file join $globname a1] [file join $globname a2]\
[file join $globname .1]\
@@ -1258,21 +785,6 @@ test filename-11.17.1 {Tcl_GlobCmd} {pcOnly macOnly} {
[file join $globname x,z1.c]\
[file join $globname x1.c]\
[file join $globname y1.c] [file join $globname z1.c]]]]
-if {[string equal $tcl_platform(platform) "windows"]} {
- if {[string index $tcl_platform(osVersion) 0] >= 5 \
- && ([lindex [file system [temporaryDirectory]] 1] == "NTFS")} {
- tcltest::testConstraint linkDirectory 1
- } else {
- tcltest::testConstraint linkDirectory 0
- }
-} else {
- tcltest::testConstraint linkDirectory 1
-}
-if {[string equal $tcl_platform(platform) "windows"]} {
- tcltest::testConstraint symbolicLinkFile 0
-} else {
- tcltest::testConstraint symbolicLinkFile 1
-}
test filename-11.17.2 {Tcl_GlobCmd} {notRoot linkDirectory} {
set dir [pwd]
set ret "error in test"
@@ -1371,7 +883,7 @@ test filename-11.17.8 {Tcl_GlobCmd: broken link and glob -l} {symbolicLinkFile}
file delete [file join $globname link]
set ret
} [list 0 [list [file join $globname link]]]
-test filename-11.18 {Tcl_GlobCmd} {unixOnly} {
+test filename-11.18 {Tcl_GlobCmd} {unix} {
list [catch {lsort [glob -path $globname/ *]} msg] $msg
} [list 0 [lsort [list [file join $globname a1] [file join $globname a2]\
[file join $globname a3]\
@@ -1379,7 +891,7 @@ test filename-11.18 {Tcl_GlobCmd} {unixOnly} {
[file join $globname x,z1.c]\
[file join $globname x1.c]\
[file join $globname y1.c] [file join $globname z1.c]]]]
-test filename-11.18.1 {Tcl_GlobCmd} {pcOnly macOnly} {
+test filename-11.18.1 {Tcl_GlobCmd} {win} {
list [catch {lsort [glob -path $globname/ *]} msg] $msg
} [list 0 [lsort [list [file join $globname a1] [file join $globname a2]\
[file join $globname .1]\
@@ -1388,7 +900,7 @@ test filename-11.18.1 {Tcl_GlobCmd} {pcOnly macOnly} {
[file join $globname x,z1.c]\
[file join $globname x1.c]\
[file join $globname y1.c] [file join $globname z1.c]]]]
-test filename-11.19 {Tcl_GlobCmd} {unixOnly} {
+test filename-11.19 {Tcl_GlobCmd} {unix} {
list [catch {lsort [glob -join -path \
[string range $globname 0 5] * *]} msg] $msg
} [list 0 [lsort [list [file join $globname a1] [file join $globname a2]\
@@ -1397,7 +909,7 @@ test filename-11.19 {Tcl_GlobCmd} {unixOnly} {
[file join $globname x,z1.c]\
[file join $globname x1.c]\
[file join $globname y1.c] [file join $globname z1.c]]]]
-test filename-11.19.1 {Tcl_GlobCmd} {pcOnly macOnly} {
+test filename-11.19.1 {Tcl_GlobCmd} {win} {
list [catch {lsort [glob -join -path \
[string range $globname 0 5] * *]} msg] $msg
} [list 0 [lsort [list [file join $globname a1] [file join $globname a2]\
@@ -1431,7 +943,7 @@ if {[file exists $horribleglobname]} {
file rename globTest $horribleglobname
set globname $horribleglobname
-test filename-11.22 {Tcl_GlobCmd} {unixOnly} {
+test filename-11.22 {Tcl_GlobCmd} {unix} {
list [catch {lsort [glob -dir $globname *]} msg] $msg
} [list 0 [lsort [list [file join $globname a1] [file join $globname a2]\
[file join $globname a3]\
@@ -1439,7 +951,7 @@ test filename-11.22 {Tcl_GlobCmd} {unixOnly} {
[file join $globname x,z1.c]\
[file join $globname x1.c]\
[file join $globname y1.c] [file join $globname z1.c]]]]
-test filename-11.22.1 {Tcl_GlobCmd} {pcOnly macOnly} {
+test filename-11.22.1 {Tcl_GlobCmd} {win} {
list [catch {lsort [glob -dir $globname *]} msg] $msg
} [list 0 [lsort [list [file join $globname a1] [file join $globname a2]\
[file join $globname .1]\
@@ -1448,7 +960,7 @@ test filename-11.22.1 {Tcl_GlobCmd} {pcOnly macOnly} {
[file join $globname x,z1.c]\
[file join $globname x1.c]\
[file join $globname y1.c] [file join $globname z1.c]]]]
-test filename-11.23 {Tcl_GlobCmd} {unixOnly} {
+test filename-11.23 {Tcl_GlobCmd} {unix} {
list [catch {lsort [glob -path $globname/ *]} msg] $msg
} [list 0 [lsort [list [file join $globname a1] [file join $globname a2]\
[file join $globname a3]\
@@ -1456,7 +968,7 @@ test filename-11.23 {Tcl_GlobCmd} {unixOnly} {
[file join $globname x,z1.c]\
[file join $globname x1.c]\
[file join $globname y1.c] [file join $globname z1.c]]]]
-test filename-11.23.1 {Tcl_GlobCmd} {pcOnly macOnly} {
+test filename-11.23.1 {Tcl_GlobCmd} {win} {
list [catch {lsort [glob -path $globname/ *]} msg] $msg
} [list 0 [lsort [list [file join $globname a1] [file join $globname a2]\
[file join $globname .1]\
@@ -1465,7 +977,7 @@ test filename-11.23.1 {Tcl_GlobCmd} {pcOnly macOnly} {
[file join $globname x,z1.c]\
[file join $globname x1.c]\
[file join $globname y1.c] [file join $globname z1.c]]]]
-test filename-11.24 {Tcl_GlobCmd} {unixOnly} {
+test filename-11.24 {Tcl_GlobCmd} {unix} {
list [catch {lsort [glob -join -path \
[string range $globname 0 5] * *]} msg] $msg
} [list 0 [lsort [list [file join $globname a1] [file join $globname a2]\
@@ -1474,7 +986,7 @@ test filename-11.24 {Tcl_GlobCmd} {unixOnly} {
[file join $globname x,z1.c]\
[file join $globname x1.c]\
[file join $globname y1.c] [file join $globname z1.c]]]]
-test filename-11.24.1 {Tcl_GlobCmd} {pcOnly macOnly} {
+test filename-11.24.1 {Tcl_GlobCmd} {win} {
list [catch {lsort [glob -join -path \
[string range $globname 0 5] * *]} msg] $msg
} [list 0 [lsort [list [file join $globname a1] [file join $globname a2]\
@@ -1574,7 +1086,11 @@ test filename-11.45 {Tcl_GlobCmd on root volume} {
set res2 [glob *]
cd $tmpd
}
- expr {$res1 == $res2}
+ set res [expr {$res1 == $res2}]
+ if {!$res} {
+ lappend res $res1 $res2
+ }
+ set res
} {1}
test filename-11.46 {Tcl_GlobCmd} {
list [catch {glob -types abcde -dir foo *} msg] $msg
@@ -1602,39 +1118,23 @@ test filename-12.1.1 {simple globbing} {unixOrPc} {
test filename-12.1.2 {simple globbing} {unixOrPc} {
list [catch {glob -types d {}} msg] $msg
} {0 .}
-test filename-12.1.3 {simple globbing} {unixOnly} {
+test filename-12.1.3 {simple globbing} {unix} {
list [catch {glob -types hidden {}} msg] $msg
} {0 .}
-test filename-12.1.4 {simple globbing} {pcOnly} {
+test filename-12.1.4 {simple globbing} {win} {
list [catch {glob -types hidden {}} msg] $msg
} {1 {no files matched glob pattern ""}}
-test filename-12.1.5 {simple globbing} {pcOnly} {
+test filename-12.1.5 {simple globbing} {win} {
list [catch {glob -types hidden c:/} msg] $msg
} {1 {no files matched glob pattern "c:/"}}
-test filename-12.1.6 {simple globbing} {pcOnly} {
+test filename-12.1.6 {simple globbing} {win} {
list [catch {glob c:/} msg] $msg
} {0 c:/}
-test filename-12.2 {simple globbing} {macOnly} {
- list [catch {glob {}} msg] $msg
-} {0 :}
-test filename-12.2.1 {simple globbing} {macOnly} {
- list [catch {glob -types f {}} msg] $msg
-} {1 {no files matched glob pattern ""}}
-test filename-12.2.2 {simple globbing} {macOnly} {
- list [catch {glob -types d {}} msg] $msg
-} {0 :}
-test filename-12.2.3 {simple globbing} {macOnly} {
- list [catch {glob -types hidden {}} msg] $msg
-} {1 {no files matched glob pattern ""}}
test filename-12.3 {simple globbing} {
list [catch {glob -nocomplain \{a1,a2\}} msg] $msg
} {0 {}}
-if {$tcl_platform(platform) == "macintosh"} {
- set globPreResult :globTest:
-} else {
- set globPreResult globTest/
-}
+set globPreResult globTest/
set x1 x1.c
set y1 y1.c
test filename-12.4 {simple globbing} {unixOrPc} {
@@ -1646,7 +1146,7 @@ test filename-12.5 {simple globbing} {
test filename-12.6 {simple globbing} {
list [catch {glob globTest\\/\\x1.c} msg] $msg
} "0 $globPreResult$x1"
-test filename-12.7 {globbing at filesystem root} {unixOnly} {
+test filename-12.7 {globbing at filesystem root} {unix} {
set res1 [glob -nocomplain /*]
set res2 [glob -path / *]
set equal [string equal $res1 $res2]
@@ -1655,7 +1155,7 @@ test filename-12.7 {globbing at filesystem root} {unixOnly} {
}
set equal
} {1}
-test filename-12.8 {globbing at filesystem root} {unixOnly} {
+test filename-12.8 {globbing at filesystem root} {unix} {
set dir [lindex [glob -type d /*] 0]
set first [string range $dir 0 1]
set res1 [glob -nocomplain ${first}*]
@@ -1666,7 +1166,7 @@ test filename-12.8 {globbing at filesystem root} {unixOnly} {
}
set equal
} {1}
-test filename-12.9 {globbing at filesystem root} {winOnly} {
+test filename-12.9 {globbing at filesystem root} {win} {
# Can't grab just anything from 'file volumes' because we need a dir
# that has subdirs - assume that C:/ exists across Windows machines.
set dir [lindex [glob -type d C:/*] 0]
@@ -1680,6 +1180,20 @@ test filename-12.9 {globbing at filesystem root} {winOnly} {
set equal
} {1}
+test filename-12.10 {globbing with volume relative paths} {win} {
+ set dir [lindex [glob -type d C:/*] 0]
+ set pwd [pwd]
+ cd C:/
+ set res1 [glob -nocomplain [string range $dir 2 end]]
+ cd $pwd
+ set res2 [list $dir]
+ set equal [string equal $res1 $res2]
+ if {!$equal} {
+ lappend equal "not equal" $res1 $res2
+ }
+ set equal
+} {1}
+
test filename-13.1 {globbing with brace substitution} {
list [catch {glob globTest/\{\}} msg] $msg
} "0 $globPreResult"
@@ -1713,36 +1227,21 @@ test filename-13.10 {globbing with brace substitution} {
test filename-13.11 {globbing with brace substitution} {unixOrPc} {
list [lsort [catch {glob globTest/\{x,x\\,z,z\}1.c} msg]] $msg
} {0 {globTest/x1.c globTest/x,z1.c globTest/z1.c}}
-test filename-13.12 {globbing with brace substitution} {macOnly} {
- list [lsort [catch {glob globTest/\{x,x\\,z,z\}1.c} msg]] $msg
-} {0 {:globTest:x1.c :globTest:x,z1.c :globTest:z1.c}}
test filename-13.13 {globbing with brace substitution} {
lsort [glob globTest/{a,b,x,y}1.c]
} [list $globPreResult$x1 $globPreResult$y1]
test filename-13.14 {globbing with brace substitution} {unixOrPc} {
lsort [glob {globTest/{x1,y2,weird name}.c}]
} {{globTest/weird name.c} globTest/x1.c}
-test filename-13.15 {globbing with brace substitution} {macOnly} {
- lsort [glob {globTest/{x1,y2,weird name}.c}]
-} {{:globTest:weird name.c} :globTest:x1.c}
test filename-13.16 {globbing with brace substitution} {unixOrPc} {
lsort [glob globTest/{x1.c,a1/*}]
} {globTest/a1/b1 globTest/a1/b2 globTest/x1.c}
-test filename-13.17 {globbing with brace substitution} {macOnly} {
- lsort [glob globTest/{x1.c,a1/*}]
-} {:globTest:a1:b1 :globTest:a1:b2 :globTest:x1.c}
test filename-13.18 {globbing with brace substitution} {unixOrPc} {
lsort [glob globTest/{x1.c,{a},a1/*}]
} {globTest/a1/b1 globTest/a1/b2 globTest/x1.c}
-test filename-13.19 {globbing with brace substitution} {macOnly} {
- lsort [glob globTest/{x1.c,{a},a1/*}]
-} {:globTest:a1:b1 :globTest:a1:b2 :globTest:x1.c}
test filename-13.20 {globbing with brace substitution} {unixOrPc} {
lsort [glob globTest/{a,x}1/*/{x,y}*]
} {globTest/a1/b1/x2.c globTest/a1/b2/y2.c}
-test filename-13.21 {globbing with brace substitution} {macOnly} {
- lsort [glob globTest/{a,x}1/*/{x,y}*]
-} {:globTest:a1:b1:x2.c :globTest:a1:b2:y2.c}
test filename-13.22 {globbing with brace substitution} {
list [catch {glob globTest/\{a,x\}1/*/\{} msg] $msg
} {1 {unmatched open-brace in file name}}
@@ -1750,15 +1249,9 @@ test filename-13.22 {globbing with brace substitution} {
test filename-14.1 {asterisks, question marks, and brackets} {unixOrPc} {
lsort [glob glo*/*.c]
} {{globTest/weird name.c} globTest/x,z1.c globTest/x1.c globTest/y1.c globTest/z1.c}
-test filename-14.2 {asterisks, question marks, and brackets} {macOnly} {
- lsort [glob glo*/*.c]
-} {{:globTest:weird name.c} :globTest:x,z1.c :globTest:x1.c :globTest:y1.c :globTest:z1.c}
test filename-14.3 {asterisks, question marks, and brackets} {unixOrPc} {
lsort [glob globTest/?1.c]
} {globTest/x1.c globTest/y1.c globTest/z1.c}
-test filename-14.4 {asterisks, question marks, and brackets} {macOnly} {
- lsort [glob globTest/?1.c]
-} {:globTest:x1.c :globTest:y1.c :globTest:z1.c}
# The current directory could be anywhere; do this to stop spurious matches
file mkdir globTestContext
@@ -1769,48 +1262,30 @@ cd globTestContext
test filename-14.5 {asterisks, question marks, and brackets} {unixOrPc} {
lsort [glob */*/*/*.c]
} {globTest/a1/b1/x2.c globTest/a1/b2/y2.c}
-test filename-14.6 {asterisks, question marks, and brackets} {macOnly} {
- lsort [glob */*/*/*.c]
-} {:globTest:a1:b1:x2.c :globTest:a1:b2:y2.c}
# Reset to where we were
cd $savepwd
file rename [file join globTestContext globTest] globTest
file delete globTestContext
-test filename-14.7 {asterisks, question marks, and brackets} {unixOnly} {
+test filename-14.7 {asterisks, question marks, and brackets} {unix} {
lsort [glob globTest/*]
} {globTest/a1 globTest/a2 globTest/a3 {globTest/weird name.c} globTest/x,z1.c globTest/x1.c globTest/y1.c globTest/z1.c}
-test filename-14.7.1 {asterisks, question marks, and brackets} {pcOnly} {
+test filename-14.7.1 {asterisks, question marks, and brackets} {win} {
lsort [glob globTest/*]
} {globTest/.1 globTest/a1 globTest/a2 globTest/a3 {globTest/weird name.c} globTest/x,z1.c globTest/x1.c globTest/y1.c globTest/z1.c}
-test filename-14.8 {asterisks, question marks, and brackets} {macOnly} {
- lsort [glob globTest/*]
-} {:globTest:.1 :globTest:a1 :globTest:a2 :globTest:a3 {:globTest:weird name.c} :globTest:x,z1.c :globTest:x1.c :globTest:y1.c :globTest:z1.c}
test filename-14.9 {asterisks, question marks, and brackets} {unixOrPc} {
lsort [glob globTest/.*]
} {globTest/. globTest/.. globTest/.1}
-test filename-14.10 {asterisks, question marks, and brackets} {macOnly} {
- lsort [glob globTest/.*]
-} {:globTest:.1}
test filename-14.11 {asterisks, question marks, and brackets} {unixOrPc} {
lsort [glob globTest/*/*]
} {globTest/a1/b1 globTest/a1/b2 globTest/a2/b3}
-test filename-14.12 {asterisks, question marks, and brackets} {macOnly} {
- lsort [glob globTest/*/*]
-} {:globTest:a1:b1 :globTest:a1:b2 :globTest:a2:b3}
test filename-14.13 {asterisks, question marks, and brackets} {unixOrPc} {
lsort [glob {globTest/[xyab]1.*}]
} {globTest/x1.c globTest/y1.c}
-test filename-14.14 {asterisks, question marks, and brackets} {macOnly} {
- lsort [glob {globTest/[xyab]1.*}]
-} {:globTest:x1.c :globTest:y1.c}
test filename-14.15 {asterisks, question marks, and brackets} {unixOrPc} {
lsort [glob globTest/*/]
} {globTest/a1/ globTest/a2/ globTest/a3/}
-test filename-14.16 {asterisks, question marks, and brackets} {macOnly} {
- lsort [glob globTest/*/]
-} {:globTest:a1: :globTest:a2: :globTest:a3:}
test filename-14.17 {asterisks, question marks, and brackets} {
global env
set temp $env(HOME)
@@ -1822,9 +1297,6 @@ test filename-14.17 {asterisks, question marks, and brackets} {
test filename-14.18 {asterisks, question marks, and brackets} {unixOrPc} {
list [catch {lsort [glob globTest/*.c goo/*]} msg] $msg
} {0 {{globTest/weird name.c} globTest/x,z1.c globTest/x1.c globTest/y1.c globTest/z1.c}}
-test filename-14.19 {asterisks, question marks, and brackets} {macOnly} {
- list [catch {lsort [glob globTest/*.c goo/*]} msg] $msg
-} {0 {{:globTest:weird name.c} :globTest:x,z1.c :globTest:x1.c :globTest:y1.c :globTest:z1.c}}
test filename-14.20 {asterisks, question marks, and brackets} {
list [catch {glob -nocomplain goo/*} msg] $msg
} {0 {}}
@@ -1834,20 +1306,23 @@ test filename-14.21 {asterisks, question marks, and brackets} {
test filename-14.22 {asterisks, question marks, and brackets} {
list [catch {glob goo/* x*z foo?q} msg] $msg
} {1 {no files matched glob patterns "goo/* x*z foo?q"}}
-test filename-14.23 {slash globbing} {unixOrPc} {
+test filename-14.23 {slash globbing} {unix} {
glob /
} /
-test filename-14.24 {slash globbing} {pcOnly} {
+test filename-14.23.2 {slash globbing} {win} {
+ glob /
+} [file norm /]
+test filename-14.24 {slash globbing} {win} {
glob {\\}
-} /
-test filename-14.25 {type specific globbing} {unixOnly} {
+} [file norm /]
+test filename-14.25 {type specific globbing} {unix} {
list [catch {lsort [glob -dir globTest -types f *]} msg] $msg
} [list 0 [lsort [list \
[file join $globname "weird name.c"]\
[file join $globname x,z1.c]\
[file join $globname x1.c]\
[file join $globname y1.c] [file join $globname z1.c]]]]
-test filename-14.25.1 {type specific globbing} {pcOnly macOnly} {
+test filename-14.25.1 {type specific globbing} {win} {
list [catch {lsort [glob -dir globTest -types f *]} msg] $msg
} [list 0 [lsort [list \
[file join $globname .1]\
@@ -1876,8 +1351,8 @@ test filename-14.31 {Bug 2918610} -setup {
makeFile {} bar.soom $d
} -body {
foreach fn [glob $d/bar.soom] {
- set root [file rootname $fn]
- close [open $root {WRONLY CREAT}]
+ set root [file rootname $fn]
+ close [open $root {WRONLY CREAT}]
}
llength [glob -directory $d *]
} -cleanup {
@@ -1893,14 +1368,14 @@ unset globname
# access by owner, so the following test is not portable.
catch {file attributes globTest/a1 -permissions 0000}
-test filename-15.1 {unix specific globbing} {unixOnly nonPortable} {
+test filename-15.1 {unix specific globbing} {unix nonPortable} {
string tolower [list [catch {glob globTest/a1/*} msg] $msg $errorCode]
} {1 {couldn't read directory "globtest/a1": permission denied} {posix eacces {permission denied}}}
-test filename-15.2 {unix specific no complain: no errors} {unixOnly nonPortable} {
+test filename-15.2 {unix specific no complain: no errors} {unix nonPortable} {
glob -nocomplain globTest/a1/*
} {}
test filename-15.3 {unix specific no complain: no errors, good result} \
- {unixOnly nonPortable} {
+ {unix nonPortable} {
# test fails because if an error occur , the interp's result
# is reset...
glob -nocomplain globTest/a2 globTest/a1/* globTest/a3
@@ -1908,23 +1383,32 @@ test filename-15.3 {unix specific no complain: no errors, good result} \
catch {file attributes globTest/a1 -permissions 0755}
test filename-15.4 {unix specific no complain: no errors, good result} \
- {unixOnly nonPortable} {
+ {unix nonPortable} {
# test fails because if an error occurs, the interp's result
# is reset... or you don't run at scriptics where the
# outser and welch users exists
glob -nocomplain ~ouster ~foo ~welch
} {/home/ouster /home/welch}
-test filename-15.4.1 {no complain: no errors, good result} {
+test filename-15.4.1 {no complain: errors, sequencing} {
+ # test used to fail because if an error occurs, the interp's result
+ # is reset... But, the sequence means we throw a different error
+ # first.
+ concat \
+ [list [catch {glob -nocomplain ~wontexist ~blahxyz ~} res1] $res1] \
+ [list [catch {glob -nocomplain ~ ~blahxyz ~wontexist} res2] $res2]
+} {1 {user "wontexist" doesn't exist} 1 {user "blahxyz" doesn't exist}}
+test filename-15.4.2 {no complain: errors, sequencing} {
# test used to fail because if an error occurs, the interp's result
# is reset...
- string equal [glob -nocomplain ~wontexist ~blah ~] \
- [glob -nocomplain ~ ~blah ~wontexist]
+ string equal \
+ [list [catch {glob -nocomplain ~wontexist *} res1] $res1] \
+ [list [catch {glob -nocomplain * ~wontexist} res2] $res2]
} {1}
-test filename-15.5 {unix specific globbing} {unixOnly nonPortable} {
+test filename-15.5 {unix specific globbing} {unix nonPortable} {
glob ~ouster/.csh*
} "/home/ouster/.cshrc"
-catch {close [open globTest/odd\\\[\]*?\{\}name w]}
-test filename-15.6 {unix specific globbing} {unixOnly} {
+catch {close [open globTest/odd\\\[\]*?\{\}name w]}
+test filename-15.6 {unix specific globbing} {unix} {
global env
set temp $env(HOME)
set env(HOME) $env(HOME)/globTest/odd\\\[\]*?\{\}name
@@ -1933,10 +1417,27 @@ test filename-15.6 {unix specific globbing} {unixOnly} {
set result
} [list 0 [list [lindex [glob ~] 0]/globTest/odd\\\[\]*?\{\}name]]
catch {file delete -force globTest/odd\\\[\]*?\{\}name}
+test filename-15.7 {win specific globbing} {win} {
+ if {[string index [glob ~] end] == "/"} {
+ set res "glob ~ is [glob ~] but shouldn't end in a separator"
+ } else {
+ set res "ok"
+ }
+} {ok}
+test filename-15.8 {win and unix specific globbing} {unixOrWin} {
+ global env
+ set temp $env(HOME)
+ catch {close [open $env(HOME)/globTest/anyname w]} err
+ set env(HOME) $env(HOME)/globTest/anyname
+ set result [list [catch {glob ~} msg] $msg]
+ set env(HOME) $temp
+ catch {file delete -force $env(HOME)/globTest/anyname}
+ set result
+} [list 0 [list [lindex [glob ~] 0]/globTest/anyname]]
# The following tests are only valid for Windows systems.
set oldDir [pwd]
-if {$::tcltest::testConstraints(pcOnly)} {
+if {[testConstraint win]} {
cd c:/
file delete -force globTest
file mkdir globTest
@@ -1945,67 +1446,89 @@ if {$::tcltest::testConstraints(pcOnly)} {
close [open globTest/z1.bat w]
}
-test filename-16.1 {windows specific globbing} {pcOnly} {
+test filename-16.1 {windows specific globbing} {win} {
lsort [glob globTest/*.bat]
} {globTest/x1.BAT globTest/y1.Bat globTest/z1.bat}
-test filename-16.2 {windows specific globbing} {pcOnly} {
- glob c:
-} c:
-test filename-16.3 {windows specific globbing} {pcOnly} {
- glob c:\\\\
+test filename-16.2 {windows specific globbing} {win} {
+ list [catch {glob c:} res] $res
+} {0 c:}
+test filename-16.2.1 {windows specific globbing} {win} {
+ set dir [pwd]
+ cd C:/
+ set res [list [catch {glob c:} err] $err]
+ cd $dir
+ set res
+} {0 c:}
+test filename-16.3 {windows specific globbing} {win} {
+ glob -nocomplain c:\\\\
} c:/
-test filename-16.4 {windows specific globbing} {pcOnly} {
- glob c:/
+test filename-16.4 {windows specific globbing} {win} {
+ glob -nocomplain c:/
} c:/
-test filename-16.5 {windows specific globbing} {pcOnly} {
- glob c:*bTest
+test filename-16.5 {windows specific globbing} {win} {
+ glob -nocomplain c:*bTest
} c:globTest
-test filename-16.6 {windows specific globbing} {pcOnly} {
- glob c:\\\\*bTest
+test filename-16.6 {windows specific globbing} {win} {
+ glob -nocomplain c:\\\\*bTest
} c:/globTest
-test filename-16.7 {windows specific globbing} {pcOnly} {
- glob c:/*bTest
+test filename-16.7 {windows specific globbing} {win} {
+ glob -nocomplain c:/*bTest
} c:/globTest
-test filename-16.8 {windows specific globbing} {pcOnly} {
- lsort [glob c:globTest/*.bat]
+test filename-16.8 {windows specific globbing} {win} {
+ lsort [glob -nocomplain c:globTest/*.bat]
} {c:globTest/x1.BAT c:globTest/y1.Bat c:globTest/z1.bat}
-test filename-16.9 {windows specific globbing} {pcOnly} {
- lsort [glob c:/globTest/*.bat]
+test filename-16.9 {windows specific globbing} {win} {
+ lsort [glob -nocomplain c:/globTest/*.bat]
} {c:/globTest/x1.BAT c:/globTest/y1.Bat c:/globTest/z1.bat}
-test filename-16.10 {windows specific globbing} {pcOnly} {
- lsort [glob c:globTest\\\\*.bat]
+test filename-16.10 {windows specific globbing} {win} {
+ lsort [glob -nocomplain c:globTest\\\\*.bat]
} {c:globTest/x1.BAT c:globTest/y1.Bat c:globTest/z1.bat}
-test filename-16.11 {windows specific globbing} {pcOnly} {
- lsort [glob c:\\\\globTest\\\\*.bat]
+test filename-16.11 {windows specific globbing} {win} {
+ lsort [glob -nocomplain c:\\\\globTest\\\\*.bat]
} {c:/globTest/x1.BAT c:/globTest/y1.Bat c:/globTest/z1.bat}
# some tests require a shared C drive
-if {[catch {cd //[info hostname]/c}]} {
- set ::tcltest::testConstraints(sharedCdrive) 0
-} else {
- set ::tcltest::testConstraints(sharedCdrive) 1
+if {[testConstraint win]} {
+ testConstraint sharedCdrive [expr {![catch {cd //[info hostname]/c}]}]
}
-test filename-16.12 {windows specific globbing} {pcOnly sharedCdrive} {
+test filename-16.12 {windows specific globbing} {win sharedCdrive} {
cd //[info hostname]/c
glob //[info hostname]/c/*Test
} //[info hostname]/c/globTest
-test filename-16.13 {windows specific globbing} {pcOnly sharedCdrive} {
+test filename-16.13 {windows specific globbing} {win sharedCdrive} {
cd //[info hostname]/c
glob "\\\\\\\\[info hostname]\\\\c\\\\*Test"
} //[info hostname]/c/globTest
-test filename-16.14 {windows specific globbing} {pcOnly} {
+test filename-16.14 {windows specific globbing} {win} {
cd [lindex [glob -types d -dir C:/ *] 0]
expr {[lsearch -exact [glob {{.,*}*}] ".."] != -1}
} {1}
-test filename-16.15 {windows specific globbing} {pcOnly} {
+test filename-16.15 {windows specific globbing} {win} {
cd [lindex [glob -types d -dir C:/ *] 0]
glob ..
} {..}
-test filename-16.16 {windows specific globbing} {pcOnly} {
- file tail [lindex [glob "[lindex [glob -types d -dir C:/ *] 0]/.."] 0]
+test filename-16.16 {windows specific globbing} {win} {
+ file tail [lindex [glob -nocomplain "[lindex [glob -types d -dir C:/ *] 0]/.."] 0]
} {..}
+test filename-16.17 {windows specific globbing} {win} {
+ cd C:/
+ # Ensure correct trimming of tails with absolute and
+ # volume relative globbing.
+ set res1 [glob -nocomplain -tails -dir C:/ *]
+ set res2 [glob -nocomplain -tails -dir C: *]
+ if {$res1 eq $res2} {
+ concat ok
+ } else {
+ concat $res1 ne $res2
+ }
+} {ok}
+
+# Put the working directory back now that we're done with globbing in C:/
+if {[testConstraint win]} {
+ cd $oldDir
+}
test filename-17.1 {windows specific special files} {testsetplatform} {
testsetplatform win
@@ -2013,8 +1536,11 @@ test filename-17.1 {windows specific special files} {testsetplatform} {
[file pathtype prn] [file pathtype nul] [file pathtype aux] \
[file pathtype foo]
} {absolute absolute absolute absolute absolute absolute relative}
+if {[testConstraint testsetplatform]} {
+ testsetplatform $platform
+}
-test filename-17.2 {windows specific glob with executable} {winOnly} {
+test filename-17.2 {windows specific glob with executable} {win} {
makeDirectory execglob
makeFile contents execglob/abc.exe
makeFile contents execglob/abc.notexecutable
@@ -2032,14 +1558,18 @@ test filename-17.3 {Bug 2571597} win {
file pathtype $p
} volumerelative
-
-test fileName-18.1 {windows - split ADS name correctly} {winOnly} {
+test fileName-18.1 {windows - split ADS name correctly} {win} {
# bug 1194458
set x [file split c:/c:d]
set y [eval [linsert $x 0 file join]]
list $x $y
} {{c:/ ./c:d} c:/c:d}
+test fileName-19.1 {ensure that [Bug 1325099] stays fixed} {
+ # Any non-crashing result is OK
+ list [file exists ~//.nonexistant_file] [file exists ~///.nonexistant_file]
+} {0 0}
+
test fileName-20.1 {Bug 1750300} -setup {
set d [makeDirectory foo]
makeFile {} TAGS $d
@@ -2110,6 +1640,8 @@ test fileName-20.6 {Bug 2837800} -setup {
} -result {}
test fileName-20.7 {Bug 2806250} -setup {
+ set savewd [pwd]
+ cd [temporaryDirectory]
set d [makeDirectory isolate]
makeFile {} ./~test $d
} -body {
@@ -2117,9 +1649,12 @@ test fileName-20.7 {Bug 2806250} -setup {
} -cleanup {
removeFile ./~test $d
removeDirectory isolate
+ cd $savewd
} -result 1
test fileName-20.8 {Bug 2806250} -setup {
+ set savewd [pwd]
+ cd [temporaryDirectory]
set d [makeDirectory isolate]
makeFile {} ./~test $d
} -body {
@@ -2127,6 +1662,7 @@ test fileName-20.8 {Bug 2806250} -setup {
} -cleanup {
removeFile ./~test $d
removeDirectory isolate
+ cd $savewd
} -result ./~test
test fileName-20.9 {} -setup {
@@ -2140,9 +1676,7 @@ test fileName-20.9 {} -setup {
cd $savewd
removeDirectory isolate
removeFile test ~
-} -result [file normalize ~/test]
-# The normalized result here is arguably buggy, but consistent
-# with (some?) 8.4.* releases.
+} -result ~/test
test fileName-20.10 {} -setup {
set s [makeDirectory sub ~]
@@ -2157,9 +1691,7 @@ test fileName-20.10 {} -setup {
removeDirectory isolate
removeFile fileName-20.10 $s
removeDirectory sub ~
-} -result [file normalize ~/sub/fileName-20.10]
-# The normalized result here is arguably buggy, but consistent
-# with (some?) 8.4.* releases.
+} -result ~/sub/fileName-20.10
# cleanup
catch {file delete -force C:/globTest}
@@ -2167,7 +1699,7 @@ cd [temporaryDirectory]
file delete -force globTest
cd $oldpwd
set env(HOME) $oldhome
-if {[tcltest::testConstraint testsetplatform]} {
+if {[testConstraint testsetplatform]} {
testsetplatform $platform
catch {unset platform}
}
diff --git a/tests/fileSystem.test b/tests/fileSystem.test
index f42e776..2acdbd2 100644
--- a/tests/fileSystem.test
+++ b/tests/fileSystem.test
@@ -11,106 +11,135 @@
package require tcltest 2
namespace eval ::tcl::test::fileSystem {
+ namespace import ::tcltest::*
catch {
- namespace import ::tcltest::cleanupTests
- namespace import ::tcltest::makeDirectory
- namespace import ::tcltest::makeFile
- namespace import ::tcltest::removeDirectory
- namespace import ::tcltest::removeFile
- namespace import ::tcltest::test
- }
-
- catch {
file delete -force link.file
file delete -force dir.link
- file delete -force [file join dir.file linkinside.file]
+ file delete -force [file join dir.dir linkinside.file]
}
+# Test for commands defined in Tcltest executable
+testConstraint testfilesystem [llength [info commands ::testfilesystem]]
+testConstraint testsetplatform [llength [info commands ::testsetplatform]]
+testConstraint testsimplefilesystem [llength [info commands ::testsimplefilesystem]]
+
cd [tcltest::temporaryDirectory]
makeFile "test file" gorp.file
-makeDirectory dir.file
-makeFile "test file in directory" [file join dir.file inside.file]
+makeDirectory dir.dir
+makeDirectory [file join dir.dir dirinside.dir]
+makeFile "test file in directory" [file join dir.dir inside.file]
+
+testConstraint unusedDrive 0
+set drive {}
+if {[testConstraint win]} {
+ set vols [string map [list :/ {}] [file volumes]]
+ for {set i 0} {$i < 26} {incr i} {
+ set drive [format %c [expr {$i + 65}]]
+ if {[lsearch -exact $vols $drive] == -1} {
+ testConstraint unusedDrive 1
+ break
+ }
+ }
+ unset i vols
+ # The variable 'drive' will be used below
+}
-if {[catch {
- file link link.file gorp.file
- file link \
- [file join dir.file linkinside.file] \
- [file join dir.file inside.file]
- file link dir.link dir.file
-}]} {
- tcltest::testConstraint hasLinks 0
-} else {
- tcltest::testConstraint hasLinks 1
+testConstraint moreThanOneDrive 0
+set drives [list]
+if {[testConstraint win]} {
+ set dir [pwd]
+ foreach vol [file volumes] {
+ if {![catch {cd $vol}]} {
+ lappend drives $vol
+ }
+ }
+ if {[llength $drives] > 1} {
+ testConstraint moreThanOneDrive 1
+ }
+ # The variable 'drives' will be used below
+ unset vol
+ cd $dir
+ unset dir
}
-tcltest::testConstraint testsimplefilesystem \
- [string equal testsimplefilesystem [info commands testsimplefilesystem]]
+proc testPathEqual {one two} {
+ if {$one eq $two} {
+ return 1
+ } else {
+ return "not equal: $one $two"
+ }
+}
+
+testConstraint hasLinks [expr {![catch {
+ file link link.file gorp.file
+ cd dir.dir
+ file link \
+ [file join linkinside.file] \
+ [file join inside.file]
+ cd ..
+ file link dir.link dir.dir
+ cd dir.dir
+ file link [file join dirinside.link] \
+ [file join dirinside.dir]
+ cd ..
+}]}]
+
+if {[testConstraint testsetplatform]} {
+ set platform [testgetplatform]
+}
test filesystem-1.0 {link normalisation} {hasLinks} {
string equal [file normalize gorp.file] [file normalize link.file]
} {0}
-
test filesystem-1.1 {link normalisation} {hasLinks} {
- string equal [file normalize dir.file] [file normalize dir.link]
+ string equal [file normalize dir.dir] [file normalize dir.link]
} {0}
-
-test filesystem-1.2 {link normalisation} {hasLinks macOrUnix} {
- string equal [file normalize [file join gorp.file foo]] \
- [file normalize [file join link.file foo]]
+test filesystem-1.2 {link normalisation} {hasLinks unix} {
+ testPathEqual [file normalize [file join gorp.file foo]] \
+ [file normalize [file join link.file foo]]
} {1}
-
test filesystem-1.3 {link normalisation} {hasLinks} {
- string equal [file normalize [file join dir.file foo]] \
- [file normalize [file join dir.link foo]]
+ testPathEqual [file normalize [file join dir.dir foo]] \
+ [file normalize [file join dir.link foo]]
} {1}
-
test filesystem-1.4 {link normalisation} {hasLinks} {
- string equal [file normalize [file join dir.file inside.file]] \
- [file normalize [file join dir.link inside.file]]
+ testPathEqual [file normalize [file join dir.dir inside.file]] \
+ [file normalize [file join dir.link inside.file]]
} {1}
-
test filesystem-1.5 {link normalisation} {hasLinks} {
- string equal [file normalize [file join dir.file linkinside.file]] \
- [file normalize [file join dir.file linkinside.file]]
+ testPathEqual [file normalize [file join dir.dir linkinside.file]] \
+ [file normalize [file join dir.dir linkinside.file]]
} {1}
-
test filesystem-1.6 {link normalisation} {hasLinks} {
- string equal [file normalize [file join dir.file linkinside.file]] \
+ string equal [file normalize [file join dir.dir linkinside.file]] \
[file normalize [file join dir.link inside.file]]
} {0}
-
-test filesystem-1.7 {link normalisation} {hasLinks macOrUnix} {
- string equal [file normalize [file join dir.link linkinside.file foo]] \
- [file normalize [file join dir.file inside.file foo]]
+test filesystem-1.7 {link normalisation} {hasLinks unix} {
+ testPathEqual [file normalize [file join dir.link linkinside.file foo]] \
+ [file normalize [file join dir.dir inside.file foo]]
} {1}
-
test filesystem-1.8 {link normalisation} {hasLinks} {
- string equal [file normalize [file join dir.file linkinside.filefoo]] \
- [file normalize [file join dir.link inside.filefoo]]
+ string equal [file normalize [file join dir.dir linkinside.filefoo]] \
+ [file normalize [file join dir.link inside.filefoo]]
} {0}
-
-test filesystem-1.9 {link normalisation} {macOrUnix hasLinks} {
+test filesystem-1.9 {link normalisation} {unix hasLinks} {
file delete -force dir.link
- file link dir.link [file nativename dir.file]
- string equal [file normalize [file join dir.file linkinside.file foo]] \
- [file normalize [file join dir.link inside.file foo]]
+ file link dir.link [file nativename dir.dir]
+ testPathEqual [file normalize [file join dir.dir linkinside.file foo]] \
+ [file normalize [file join dir.link inside.file foo]]
} {1}
-
-test filesystem-1.10 {link normalisation: double link} {macOrUnix hasLinks} {
+test filesystem-1.10 {link normalisation: double link} {unix hasLinks} {
file link dir2.link dir.link
- string equal [file normalize [file join dir.file linkinside.file foo]] \
- [file normalize [file join dir2.link inside.file foo]]
+ testPathEqual [file normalize [file join dir.dir linkinside.file foo]] \
+ [file normalize [file join dir2.link inside.file foo]]
} {1}
-
makeDirectory dir2.file
-
-test filesystem-1.11 {link normalisation: double link, back in tree} {macOrUnix hasLinks} {
- file link [file join dir2.file dir2.link] dir2.link
- string equal [file normalize [file join dir.file linkinside.file foo]] \
- [file normalize [file join dir2.file dir2.link inside.file foo]]
+test filesystem-1.11 {link normalisation: double link, back in tree} {unix hasLinks} {
+ file link [file join dir2.file dir2.link] [file join .. dir2.link]
+ testPathEqual [file normalize [file join dir.dir linkinside.file foo]] \
+ [file normalize [file join dir2.file dir2.link inside.file foo]]
} {1}
-
test filesystem-1.12 {file new native path} {} {
for {set i 0} {$i < 10} {incr i} {
foreach f [lsort [glob -nocomplain -type l *]] {
@@ -120,24 +149,352 @@ test filesystem-1.12 {file new native path} {} {
# If we reach here we've succeeded. We used to crash above.
expr 1
} {1}
-
-test filesystem-1.13 {file normalisation} {winOnly} {
+test filesystem-1.13 {file normalisation} {win} {
# This used to be broken
file normalize C:/thislongnamedoesntexist
} {C:/thislongnamedoesntexist}
-
-test filesystem-1.14 {file normalisation} {winOnly} {
+test filesystem-1.14 {file normalisation} {win} {
# This used to be broken
file normalize c:/
} {C:/}
-
+test filesystem-1.15 {file normalisation} {win} {
+ file normalize c:/../
+} {C:/}
+test filesystem-1.16 {file normalisation} {win} {
+ file normalize c:/.
+} {C:/}
+test filesystem-1.17 {file normalisation} {win} {
+ file normalize c:/..
+} {C:/}
+test filesystem-1.17.1 {file normalisation} {win} {
+ file normalize c:\\..
+} {C:/}
+test filesystem-1.18 {file normalisation} {win} {
+ file normalize c:/./
+} {C:/}
+test filesystem-1.19 {file normalisation} {win unusedDrive} {
+ file normalize ${drive}:/./../../..
+} "${drive}:/"
+test filesystem-1.20 {file normalisation} {win} {
+ file normalize //name/foo/../
+} {//name/foo}
+test filesystem-1.21 {file normalisation} {win} {
+ file normalize C:///foo/./
+} {C:/foo}
+test filesystem-1.22 {file normalisation} {win} {
+ file normalize //name/foo/.
+} {//name/foo}
+test filesystem-1.23 {file normalisation} {win} {
+ file normalize c:/./foo
+} {C:/foo}
+test filesystem-1.24 {file normalisation} {win unusedDrive} {
+ file normalize ${drive}:/./../../../a
+} "${drive}:/a"
+test filesystem-1.25 {file normalisation} {win unusedDrive} {
+ file normalize ${drive}:/./.././../../a
+} "${drive}:/a"
+test filesystem-1.25.1 {file normalisation} {win unusedDrive} {
+ file normalize ${drive}:/./.././..\\..\\a\\bb
+} "${drive}:/a/bb"
+test filesystem-1.26 {link normalisation: link and ..} {hasLinks} {
+ file delete -force dir2.link
+ set dir [file join dir2 foo bar]
+ file mkdir $dir
+ file link dir2.link [file join dir2 foo bar]
+ set res [list [file normalize [file join dir2 foo x]] \
+ [file normalize [file join dir2.link .. x]]]
+ if {![string equal [lindex $res 0] [lindex $res 1]]} {
+ set res "$res not equal"
+ } else {
+ set res "ok"
+ }
+} {ok}
+test filesystem-1.27 {file normalisation: up and down with ..} {
+ set dir [file join dir2 foo bar]
+ file mkdir $dir
+ set dir2 [file join dir2 .. dir2 foo .. foo bar]
+ set res [list [file normalize $dir] [file normalize $dir2]]
+ set res2 [list [file exists $dir] [file exists $dir2]]
+ if {![string equal [lindex $res 0] [lindex $res 1]]} {
+ set res "exists: $res2, $res not equal"
+ } else {
+ set res "ok: $res2"
+ }
+} {ok: 1 1}
+test filesystem-1.28 {link normalisation: link with .. and ..} {hasLinks} {
+ file delete -force dir2.link
+ set dir [file join dir2 foo bar]
+ file mkdir $dir
+ set to [file join dir2 .. dir2 foo .. foo bar]
+ file link dir2.link $to
+ set res [list [file normalize [file join dir2 foo x]] \
+ [file normalize [file join dir2.link .. x]]]
+ if {![string equal [lindex $res 0] [lindex $res 1]]} {
+ set res "$res not equal"
+ } else {
+ set res "ok"
+ }
+} {ok}
+test filesystem-1.29 {link normalisation: link with ..} {hasLinks} {
+ file delete -force dir2.link
+ set dir [file join dir2 foo bar]
+ file mkdir $dir
+ set to [file join dir2 .. dir2 foo .. foo bar]
+ file link dir2.link $to
+ set res [file normalize [file join dir2.link x yyy z]]
+ if {[string first ".." $res] != -1} {
+ set res "$res must not contain '..'"
+ } else {
+ set res "ok"
+ }
+} {ok}
+test filesystem-1.29.1 {link normalisation with two consecutive links} {hasLinks} {
+ testPathEqual [file normalize [file join dir.link dirinside.link abc]] \
+ [file normalize [file join dir.dir dirinside.dir abc]]
+} {1}
file delete -force dir2.file
file delete -force dir2.link
file delete -force link.file dir.link
-removeFile [file join dir.file inside.file]
-removeDirectory dir.file
+file delete -force dir2
+file delete -force [file join dir.dir dirinside.link]
+removeFile [file join dir.dir inside.file]
+removeDirectory [file join dir.dir dirinside.dir]
+removeDirectory dir.dir
+test filesystem-1.30 {normalisation of nonexistent user} {
+ list [catch {file normalize ~noonewiththisname} err] $err
+} {1 {user "noonewiththisname" doesn't exist}}
+test filesystem-1.31 {link normalisation: link near filesystem root} {testsetplatform} {
+ testsetplatform unix
+ file normalize /foo/../bar
+} {/bar}
+test filesystem-1.32 {link normalisation: link near filesystem root} {testsetplatform} {
+ testsetplatform unix
+ file normalize /../bar
+} {/bar}
+test filesystem-1.33 {link normalisation: link near filesystem root} {testsetplatform} {
+ testsetplatform windows
+ set res [file normalize C:/../bar]
+ if {[testConstraint unix]} {
+ # Some unices go further in normalizing this -- not really
+ # a problem since this is a Windows test
+ regexp {C:/bar$} $res res
+ }
+ set res
+} {C:/bar}
+if {[testConstraint testsetplatform]} {
+ testsetplatform $platform
+}
+test filesystem-1.34 {file normalisation with '/./'} {
+ set res [file normalize /foo/bar/anc/./.tml]
+ if {[string first "/./" $res] != -1} {
+ set res "normalization of /foo/bar/anc/./.tml is: $res"
+ } else {
+ set res "ok"
+ }
+ set res
+} {ok}
+test filesystem-1.35 {file normalisation with '/./'} {
+ set res [file normalize /ffo/bar/anc/./foo/.tml]
+ if {[string first "/./" $res] != -1 || ([regsub -all "foo" $res "" reg] == 2)} {
+ set res "normalization of /ffo/bar/anc/./foo/.tml is: $res"
+ } else {
+ set res "ok"
+ }
+ set res
+} {ok}
+test filesystem-1.36 {file normalisation with '/./'} {
+ set res [file normalize /foo/bar/anc/././asdasd/.tml]
+ if {[string first "/./" $res] != -1 || ([regsub -all "asdasd" $res "" reg] == 2) } {
+ set res "normalization of /foo/bar/anc/././asdasd/.tml is: $res"
+ } else {
+ set res "ok"
+ }
+ set res
+} {ok}
+test filesystem-1.37 {file normalisation with '/./'} {
+ set fname "/abc/./def/./ghi/./asda/.././.././asd/x/../../../../....."
+ set res [file norm $fname]
+ if {[string first "//" $res] != -1} {
+ set res "normalization of $fname is: $res"
+ } else {
+ set res "ok"
+ }
+ set res
+} {ok}
+test filesystem-1.38 {file normalisation with volume relative} \
+ {win moreThanOneDrive} {
+ set path "[string range [lindex $drives 0] 0 1]foo"
+ set dir [pwd]
+ cd [lindex $drives 1]
+ set res [file norm $path]
+ cd $dir
+ set res
+} "[lindex $drives 0]foo"
+test filesystem-1.39 {file normalisation with volume relative} {win} {
+ set drv C:/
+ set dir [lindex [glob -type d -dir $drv *] 0]
+ set old [pwd]
+ cd $dir
+ set res [file norm [string range $drv 0 1]]
+ cd $old
+ if {[string index $res end] eq "/"} {
+ set res "Bad normalized path: $res"
+ } else {
+ set res "ok"
+ }
+} {ok}
+test filesystem-1.40 {file normalisation with repeated separators} {
+ set a [file norm foo////bar]
+ set b [file norm foo/bar]
+
+ if {![string equal $a $b]} {
+ set res "Paths should be equal: $a , $b"
+ } else {
+ set res "ok"
+ }
+} {ok}
+test filesystem-1.41 {file normalisation with repeated separators} {win} {
+ set a [file norm foo\\\\\\bar]
+ set b [file norm foo/bar]
+
+ if {![string equal $a $b]} {
+ set res "Paths should be equal: $a , $b"
+ } else {
+ set res "ok"
+ }
+} {ok}
+test filesystem-1.42 {file normalisation .. beyond root (Bug 1379287)} {
+ set a [file norm /xxx/..]
+ set b [file norm /]
+
+ if {![string equal $a $b]} {
+ set res "Paths should be equal: $a , $b"
+ } else {
+ set res "ok"
+ }
+} {ok}
+test filesystem-1.42.1 {file normalisation .. beyond root (Bug 1379287)} {
+ set a [file norm /xxx/../]
+ set b [file norm /]
+
+ if {![string equal $a $b]} {
+ set res "Paths should be equal: $a , $b"
+ } else {
+ set res "ok"
+ }
+} {ok}
+test filesystem-1.43 {file normalisation .. beyond root (Bug 1379287)} {
+ set a [file norm /xxx/foo/../..]
+ set b [file norm /]
+
+ if {![string equal $a $b]} {
+ set res "Paths should be equal: $a , $b"
+ } else {
+ set res "ok"
+ }
+} {ok}
+test filesystem-1.43.1 {file normalisation .. beyond root (Bug 1379287)} {
+ set a [file norm /xxx/foo/../../]
+ set b [file norm /]
+
+ if {![string equal $a $b]} {
+ set res "Paths should be equal: $a , $b"
+ } else {
+ set res "ok"
+ }
+} {ok}
+test filesystem-1.44 {file normalisation .. beyond root (Bug 1379287)} {
+ set a [file norm /xxx/foo/../../bar]
+ set b [file norm /bar]
+
+ if {![string equal $a $b]} {
+ set res "Paths should be equal: $a , $b"
+ } else {
+ set res "ok"
+ }
+} {ok}
+test filesystem-1.45 {file normalisation .. beyond root (Bug 1379287)} {
+ set a [file norm /xxx/../../bar]
+ set b [file norm /bar]
+
+ if {![string equal $a $b]} {
+ set res "Paths should be equal: $a , $b"
+ } else {
+ set res "ok"
+ }
+} {ok}
+test filesystem-1.46 {file normalisation .. beyond root (Bug 1379287)} {
+ set a [file norm /xxx/../bar]
+ set b [file norm /bar]
+
+ if {![string equal $a $b]} {
+ set res "Paths should be equal: $a , $b"
+ } else {
+ set res "ok"
+ }
+} {ok}
+test filesystem-1.47 {file normalisation .. beyond root (Bug 1379287)} {
+ set a [file norm /..]
+ set b [file norm /]
+
+ if {![string equal $a $b]} {
+ set res "Paths should be equal: $a , $b"
+ } else {
+ set res "ok"
+ }
+} {ok}
+test filesystem-1.48 {file normalisation .. beyond root (Bug 1379287)} {
+ set a [file norm /../]
+ set b [file norm /]
+
+ if {![string equal $a $b]} {
+ set res "Paths should be equal: $a , $b"
+ } else {
+ set res "ok"
+ }
+} {ok}
+test filesystem-1.49 {file normalisation .. beyond root (Bug 1379287)} {
+ set a [file norm /.]
+ set b [file norm /]
+
+ if {![string equal $a $b]} {
+ set res "Paths should be equal: $a , $b"
+ } else {
+ set res "ok"
+ }
+} {ok}
+test filesystem-1.50 {file normalisation .. beyond root (Bug 1379287)} {
+ set a [file norm /./]
+ set b [file norm /]
+
+ if {![string equal $a $b]} {
+ set res "Paths should be equal: $a , $b"
+ } else {
+ set res "ok"
+ }
+} {ok}
+test filesystem-1.51 {file normalisation .. beyond root (Bug 1379287)} {
+ set a [file norm /../..]
+ set b [file norm /]
+
+ if {![string equal $a $b]} {
+ set res "Paths should be equal: $a , $b"
+ } else {
+ set res "ok"
+ }
+} {ok}
+test filesystem-1.51.1 {file normalisation .. beyond root (Bug 1379287)} {
+ set a [file norm /../../]
+ set b [file norm /]
+
+ if {![string equal $a $b]} {
+ set res "Paths should be equal: $a , $b"
+ } else {
+ set res "ok"
+ }
+} {ok}
-test filesystem-2.0 {new native path} {unixOnly} {
+test filesystem-2.0 {new native path} {unix} {
foreach f [lsort [glob -nocomplain /usr/bin/c*]] {
catch {file readlink $f}
}
@@ -145,52 +502,37 @@ test filesystem-2.0 {new native path} {unixOnly} {
expr 1
} {1}
-if {[catch {package require tcltest 2}]} {
- puts stderr "Skipping tests filesystem-{3,4}.*: tcltest 2 required."
-} else {
- namespace import ::tcltest::testConstraint
-
- # Is the Tcltest package loaded?
- # - that is, the special C-coded testing commands in tclTest.c
- # - tests use testing commands introduced in Tcltest 8.4
- testConstraint Tcltest [expr {
- [llength [package provide Tcltest]]
- && [package vsatisfies [package provide Tcltest] 8.4]}]
-
# Make sure the testfilesystem hasn't been registered.
-while {![catch {testfilesystem 0}]} {}
+if {[testConstraint testfilesystem]} {
+ while {![catch {testfilesystem 0}]} {}
+}
-test filesystem-3.0 {Tcl_FSRegister} Tcltest {
+test filesystem-3.0 {Tcl_FSRegister} testfilesystem {
testfilesystem 1
} {registered}
-
-test filesystem-3.1 {Tcl_FSUnregister} Tcltest {
+test filesystem-3.1 {Tcl_FSUnregister} testfilesystem {
testfilesystem 0
} {unregistered}
-
-test filesystem-3.2 {Tcl_FSUnregister} Tcltest {
+test filesystem-3.2 {Tcl_FSUnregister} testfilesystem {
list [catch {testfilesystem 0} err] $err
} {1 failed}
-
-test filesystem-3.3 {Tcl_FSRegister} Tcltest {
+test filesystem-3.3 {Tcl_FSRegister} testfilesystem {
testfilesystem 1
testfilesystem 1
testfilesystem 0
testfilesystem 0
} {unregistered}
-
-test filesystem-3.4 {Tcl_FSRegister} Tcltest {
+test filesystem-3.4 {Tcl_FSRegister} testfilesystem {
testfilesystem 1
file system bar
} {reporting}
-
-test filesystem-3.5 {Tcl_FSUnregister} Tcltest {
+test filesystem-3.5 {Tcl_FSUnregister} testfilesystem {
testfilesystem 0
lindex [file system bar] 0
} {native}
test filesystem-4.0 {testfilesystem} {
- -constraints Tcltest
+ -constraints testfilesystem
-match glob
-body {
testfilesystem 1
@@ -199,11 +541,10 @@ test filesystem-4.0 {testfilesystem} {
testfilesystem 0
set filesystemReport
}
- -result {* {access foo}}
+ -result {*{access foo}}
}
-
test filesystem-4.1 {testfilesystem} {
- -constraints Tcltest
+ -constraints testfilesystem
-match glob
-body {
testfilesystem 1
@@ -212,11 +553,10 @@ test filesystem-4.1 {testfilesystem} {
testfilesystem 0
set filesystemReport
}
- -result {* {stat foo}}
+ -result {*{stat foo}}
}
-
test filesystem-4.2 {testfilesystem} {
- -constraints Tcltest
+ -constraints testfilesystem
-match glob
-body {
testfilesystem 1
@@ -225,11 +565,10 @@ test filesystem-4.2 {testfilesystem} {
testfilesystem 0
set filesystemReport
}
- -result {* {lstat foo}}
+ -result {*{lstat foo}}
}
-
test filesystem-4.3 {testfilesystem} {
- -constraints Tcltest
+ -constraints testfilesystem
-match glob
-body {
testfilesystem 1
@@ -238,14 +577,14 @@ test filesystem-4.3 {testfilesystem} {
testfilesystem 0
set filesystemReport
}
- -result {* {matchindirectory *}*}
+ -result {*{matchindirectory *}*}
}
test filesystem-5.1 {cache and ~} {
- -constraints Tcltest
+ -constraints testfilesystem
-match regexp
-body {
- set orig $env(HOME)
+ set orig $::env(HOME)
set ::env(HOME) /foo/bar/blah
set testdir ~
set res1 "Parent of ~ (/foo/bar/blah) is [file dirname $testdir]"
@@ -254,143 +593,112 @@ test filesystem-5.1 {cache and ~} {
set ::env(HOME) $orig
list $res1 $res2
}
- -result {{Parent of ~ \(/foo/bar/blah\) is (/foo/bar|foo:bar)} {Parent of ~ \(/a/b/c\) is (/a/b|a:b)}}
+ -result {{Parent of ~ \(/foo/bar/blah\) is ([a-zA-Z]:)?(/foo/bar|foo:bar)} {Parent of ~ \(/a/b/c\) is ([a-zA-Z]:)?(/a/b|a:b)}}
}
test filesystem-6.1 {empty file name} {
list [catch {open ""} msg] $msg
} {1 {couldn't open "": no such file or directory}}
-
test filesystem-6.2 {empty file name} {
list [catch {file stat "" arr} msg] $msg
} {1 {could not read "": no such file or directory}}
-
test filesystem-6.3 {empty file name} {
list [catch {file atime ""} msg] $msg
} {1 {could not read "": no such file or directory}}
-
test filesystem-6.4 {empty file name} {
list [catch {file attributes ""} msg] $msg
} {1 {could not read "": no such file or directory}}
-
test filesystem-6.5 {empty file name} {
list [catch {file copy "" ""} msg] $msg
} {1 {error copying "": no such file or directory}}
-
test filesystem-6.6 {empty file name} {
list [catch {file delete ""} msg] $msg
} {0 {}}
-
test filesystem-6.7 {empty file name} {
list [catch {file dirname ""} msg] $msg
} {0 .}
-
test filesystem-6.8 {empty file name} {
list [catch {file executable ""} msg] $msg
} {0 0}
-
test filesystem-6.9 {empty file name} {
list [catch {file exists ""} msg] $msg
} {0 0}
-
test filesystem-6.10 {empty file name} {
list [catch {file extension ""} msg] $msg
} {0 {}}
-
test filesystem-6.11 {empty file name} {
list [catch {file isdirectory ""} msg] $msg
} {0 0}
-
test filesystem-6.12 {empty file name} {
list [catch {file isfile ""} msg] $msg
} {0 0}
-
test filesystem-6.13 {empty file name} {
list [catch {file join ""} msg] $msg
} {0 {}}
-
test filesystem-6.14 {empty file name} {
list [catch {file link ""} msg] $msg
} {1 {could not read link "": no such file or directory}}
-
test filesystem-6.15 {empty file name} {
list [catch {file lstat "" arr} msg] $msg
} {1 {could not read "": no such file or directory}}
-
test filesystem-6.16 {empty file name} {
list [catch {file mtime ""} msg] $msg
} {1 {could not read "": no such file or directory}}
-
test filesystem-6.17 {empty file name} {
list [catch {file mtime "" 0} msg] $msg
} {1 {could not read "": no such file or directory}}
-
test filesystem-6.18 {empty file name} {
list [catch {file mkdir ""} msg] $msg
} {1 {can't create directory "": no such file or directory}}
-
test filesystem-6.19 {empty file name} {
list [catch {file nativename ""} msg] $msg
} {0 {}}
-
test filesystem-6.20 {empty file name} {
list [catch {file normalize ""} msg] $msg
} {0 {}}
-
test filesystem-6.21 {empty file name} {
list [catch {file owned ""} msg] $msg
} {0 0}
-
test filesystem-6.22 {empty file name} {
list [catch {file pathtype ""} msg] $msg
} {0 relative}
-
test filesystem-6.23 {empty file name} {
list [catch {file readable ""} msg] $msg
} {0 0}
-
test filesystem-6.24 {empty file name} {
list [catch {file readlink ""} msg] $msg
} {1 {could not readlink "": no such file or directory}}
-
test filesystem-6.25 {empty file name} {
list [catch {file rename "" ""} msg] $msg
} {1 {error renaming "": no such file or directory}}
-
test filesystem-6.26 {empty file name} {
list [catch {file rootname ""} msg] $msg
} {0 {}}
-
test filesystem-6.27 {empty file name} {
list [catch {file separator ""} msg] $msg
} {1 {Unrecognised path}}
-
test filesystem-6.28 {empty file name} {
list [catch {file size ""} msg] $msg
} {1 {could not read "": no such file or directory}}
-
test filesystem-6.29 {empty file name} {
list [catch {file split ""} msg] $msg
} {0 {}}
-
test filesystem-6.30 {empty file name} {
list [catch {file system ""} msg] $msg
} {1 {Unrecognised path}}
-
test filesystem-6.31 {empty file name} {
list [catch {file tail ""} msg] $msg
} {0 {}}
-
test filesystem-6.32 {empty file name} {
list [catch {file type ""} msg] $msg
} {1 {could not read "": no such file or directory}}
-
test filesystem-6.33 {empty file name} {
list [catch {file writable ""} msg] $msg
} {0 0}
# Make sure the testfilesystem hasn't been registered.
-while {![catch {testfilesystem 0}]} {}
+if {[testConstraint testfilesystem]} {
+ while {![catch {testfilesystem 0}]} {}
}
test filesystem-7.1 {load from vfs} {win testsimplefilesystem} {
@@ -406,24 +714,205 @@ test filesystem-7.1 {load from vfs} {win testsimplefilesystem} {
set res "ok"
# The real result of this test is what happens when Tcl exits.
} {ok}
-
test filesystem-7.2 {cross-filesystem copy from vfs maintains mtime} \
{testsimplefilesystem} {
set dir [pwd]
cd [tcltest::temporaryDirectory]
# We created this file several tests ago.
set origtime [file mtime gorp.file]
+ set res [file exists gorp.file]
+ if {[catch {
+ testsimplefilesystem 1
+ file delete -force theCopy
+ file copy simplefs:/gorp.file theCopy
+ testsimplefilesystem 0
+ set newtime [file mtime theCopy]
+ file delete theCopy
+ } err]} {
+ lappend res $err
+ set newtime ""
+ }
+ cd $dir
+ lappend res [expr {$origtime == $newtime}]
+} {1 1}
+test filesystem-7.3 {glob in simplefs} testsimplefilesystem {
+ set dir [pwd]
+ cd [tcltest::temporaryDirectory]
+ file mkdir simpledir
+ close [open [file join simpledir simplefile] w]
testsimplefilesystem 1
- file delete -force theCopy
- file copy simplefs:/gorp.file theCopy
+ set res [glob -nocomplain -dir simplefs:/simpledir *]
testsimplefilesystem 0
- set newtime [file mtime theCopy]
- file delete theCopy
+ file delete -force simpledir
cd $dir
- expr {$origtime == $newtime}
-} {1}
-
+ set res
+} {simplefs:/simpledir/simplefile}
+test filesystem-7.3.1 {glob in simplefs: no path/dir} testsimplefilesystem {
+ set dir [pwd]
+ cd [tcltest::temporaryDirectory]
+ file mkdir simpledir
+ close [open [file join simpledir simplefile] w]
+ testsimplefilesystem 1
+ set res [glob -nocomplain simplefs:/simpledir/*]
+ eval lappend res [glob -nocomplain simplefs:/simpledir]
+ testsimplefilesystem 0
+ file delete -force simpledir
+ cd $dir
+ set res
+} {simplefs:/simpledir/simplefile simplefs:/simpledir}
+test filesystem-7.3.2 {glob in simplefs: no path/dir, no subdirectory} testsimplefilesystem {
+ set dir [pwd]
+ cd [tcltest::temporaryDirectory]
+ file mkdir simpledir
+ close [open [file join simpledir simplefile] w]
+ testsimplefilesystem 1
+ set res [glob -nocomplain simplefs:/s*]
+ testsimplefilesystem 0
+ file delete -force simpledir
+ cd $dir
+ if {[llength $res] > 0} {
+ set res "ok"
+ } else {
+ set res "no files found with 'glob -nocomplain simplefs:/s*'"
+ }
+} {ok}
+test filesystem-7.3.3 {glob in simplefs: pattern is a volume} testsimplefilesystem {
+ set dir [pwd]
+ cd [tcltest::temporaryDirectory]
+ file mkdir simpledir
+ close [open [file join simpledir simplefile] w]
+ testsimplefilesystem 1
+ set res [glob -nocomplain simplefs:/*]
+ testsimplefilesystem 0
+ file delete -force simpledir
+ cd $dir
+ if {[llength $res] > 0} {
+ set res "ok"
+ } else {
+ set res "no files found with 'glob -nocomplain simplefs:/*'"
+ }
+} {ok}
+test filesystem-7.4 {cross-filesystem file copy with -force} testsimplefilesystem {
+ set dir [pwd]
+ cd [tcltest::temporaryDirectory]
+ set fout [open [file join simplefile] w]
+ puts -nonewline $fout "1234567890"
+ close $fout
+ testsimplefilesystem 1
+ # First copy should succeed
+ set res [catch {file copy simplefs:/simplefile file2} err]
+ lappend res $err
+ # Second copy should fail (no -force)
+ lappend res [catch {file copy simplefs:/simplefile file2} err]
+ lappend res $err
+ # Third copy should succeed (-force)
+ lappend res [catch {file copy -force simplefs:/simplefile file2} err]
+ lappend res $err
+ lappend res [file exists file2]
+ testsimplefilesystem 0
+ file delete -force simplefile
+ file delete -force file2
+ cd $dir
+ set res
+} {0 10 1 {error copying "simplefs:/simplefile" to "file2": file already exists} 0 10 1}
+test filesystem-7.5 {cross-filesystem file copy with -force} {testsimplefilesystem unix} {
+ set dir [pwd]
+ cd [tcltest::temporaryDirectory]
+ set fout [open [file join simplefile] w]
+ puts -nonewline $fout "1234567890"
+ close $fout
+ testsimplefilesystem 1
+ # First copy should succeed
+ set res [catch {file copy simplefs:/simplefile file2} err]
+ lappend res $err
+ file attributes file2 -permissions 0000
+ # Second copy should fail (no -force)
+ lappend res [catch {file copy simplefs:/simplefile file2} err]
+ lappend res $err
+ # Third copy should succeed (-force)
+ lappend res [catch {file copy -force simplefs:/simplefile file2} err]
+ lappend res $err
+ lappend res [file exists file2]
+ testsimplefilesystem 0
+ file delete -force simplefile
+ file delete -force file2
+ cd $dir
+ set res
+} {0 10 1 {error copying "simplefs:/simplefile" to "file2": file already exists} 0 10 1}
+test filesystem-7.6 {cross-filesystem dir copy with -force} testsimplefilesystem {
+ set dir [pwd]
+ cd [tcltest::temporaryDirectory]
+ file delete -force simpledir
+ file mkdir simpledir
+ file mkdir dir2
+ set fout [open [file join simpledir simplefile] w]
+ puts -nonewline $fout "1234567890"
+ close $fout
+ testsimplefilesystem 1
+ # First copy should succeed
+ set res [catch {file copy simplefs:/simpledir dir2} err]
+ lappend res $err
+ # Second copy should fail (no -force)
+ lappend res [catch {file copy simplefs:/simpledir dir2} err]
+ lappend res $err
+ # Third copy should succeed (-force)
+ lappend res [catch {file copy -force simplefs:/simpledir dir2} err]
+ lappend res $err
+ lappend res [file exists [file join dir2 simpledir]] \
+ [file exists [file join dir2 simpledir simplefile]]
+ testsimplefilesystem 0
+ file delete -force simpledir
+ file delete -force dir2
+ cd $dir
+ set res
+} {0 {} 1 {error copying "simplefs:/simpledir" to "dir2/simpledir": file already exists} 0 {} 1 1}
+test filesystem-7.7 {cross-filesystem dir copy with -force} {testsimplefilesystem unix} {
+ set dir [pwd]
+ cd [tcltest::temporaryDirectory]
+ file delete -force simpledir
+ file mkdir simpledir
+ file mkdir dir2
+ set fout [open [file join simpledir simplefile] w]
+ puts -nonewline $fout "1234567890"
+ close $fout
+ testsimplefilesystem 1
+ # First copy should succeed
+ set res [catch {file copy simplefs:/simpledir dir2} err]
+ lappend res $err
+ # Second copy should fail (no -force)
+ lappend res [catch {file copy simplefs:/simpledir dir2} err]
+ lappend res $err
+ # Third copy should succeed (-force)
+ # I've noticed on some Unices that this only succeeds
+ # intermittently (some runs work, some fail). This needs
+ # examining further.
+ lappend res [catch {file copy -force simplefs:/simpledir dir2} err]
+ lappend res $err
+ lappend res [file exists [file join dir2 simpledir]] \
+ [file exists [file join dir2 simpledir simplefile]]
+ testsimplefilesystem 0
+ file delete -force simpledir
+ file delete -force dir2
+ cd $dir
+ set res
+} {0 {} 1 {error copying "simplefs:/simpledir" to "dir2/simpledir": file already exists} 0 {} 1 1}
removeFile gorp.file
+test filesystem-7.8 {vfs cd} testsimplefilesystem {
+ set dir [pwd]
+ cd [tcltest::temporaryDirectory]
+ file delete -force simpledir
+ file mkdir simpledir
+ testsimplefilesystem 1
+ # This can variously cause an infinite loop or simply have
+ # no effect at all (before certain bugs were fixed, of course).
+ cd simplefs:/simpledir
+ set res [pwd]
+ cd [tcltest::temporaryDirectory]
+ testsimplefilesystem 0
+ file delete -force simpledir
+ cd $dir
+ set res
+} {simplefs:/simpledir}
test filesystem-8.1 {relative path objects and caching of pwd} {
set dir [pwd]
@@ -448,7 +937,6 @@ test filesystem-8.1 {relative path objects and caching of pwd} {
cd $dir
set res
} {1 1 0 0}
-
test filesystem-8.2 {relative path objects and use of pwd} {
set origdir [pwd]
cd [tcltest::temporaryDirectory]
@@ -463,12 +951,10 @@ test filesystem-8.2 {relative path objects and use of pwd} {
cd $origdir
set res
} {1}
-
test filesystem-8.3 {path objects and empty string} {
set anchor ""
set dst foo
set res $dst
-
set yyy [file split $anchor]
set dst [file join $anchor $dst]
lappend res $dst $yyy
@@ -500,7 +986,6 @@ test filesystem-9.1 {path objects and join and object rep} {
cd $origdir
set res
} {{a/b/./c found: 1} {is dir a dir? 1} {a/b/./c found: 1}}
-
test filesystem-9.2 {path objects and join and object rep} {
set origdir [pwd]
cd [tcltest::temporaryDirectory]
@@ -510,7 +995,6 @@ test filesystem-9.2 {path objects and join and object rep} {
cd $origdir
set res
} {{a/b/./c found: 1} {is dir a dir? 1} {a/b/./c found: 1}}
-
test filesystem-9.2.1 {path objects and join and object rep} {
set origdir [pwd]
cd [tcltest::temporaryDirectory]
@@ -520,7 +1004,6 @@ test filesystem-9.2.1 {path objects and join and object rep} {
cd $origdir
set res
} {{a/b/. found: 1} {is dir a dir? 1} {a/b/. found: 1}}
-
test filesystem-9.3 {path objects and join and object rep} {
set origdir [pwd]
cd [tcltest::temporaryDirectory]
@@ -530,7 +1013,6 @@ test filesystem-9.3 {path objects and join and object rep} {
cd $origdir
set res
} {{a/b/../b/c found: 1} {is dir a dir? 1} {a/b/../b/c found: 1}}
-
test filesystem-9.4 {path objects and join and object rep} {
set origdir [pwd]
cd [tcltest::temporaryDirectory]
@@ -540,7 +1022,6 @@ test filesystem-9.4 {path objects and join and object rep} {
cd $origdir
set res
} {{a/b/../b/c found: 1} {is dir a dir? 1} {a/b/../b/c found: 1}}
-
test filesystem-9.5 {path objects and file tail and object rep} {
set origdir [pwd]
cd [tcltest::temporaryDirectory]
@@ -554,15 +1035,13 @@ test filesystem-9.5 {path objects and file tail and object rep} {
cd $origdir
set res
} {test test}
-
-test filesystem-9.6 {path objects and file join and object rep} {winOnly} {
+test filesystem-9.6 {path objects and file tail and object rep} win {
set res {}
set p "C:\\toto"
lappend res [file join $p toto]
file isdirectory $p
lappend res [file join $p toto]
} {C:/toto/toto C:/toto/toto}
-
test filesystem-9.7 {path objects and glob and file tail and tilde} {
set res {}
set origdir [pwd]
@@ -616,6 +1095,7 @@ test filesystem-9.9 {path objects and glob and file tail and tilde} {
} {0 0 0 0 1}
cleanupTests
+unset -nocomplain drive
}
namespace delete ::tcl::test::fileSystem
return
diff --git a/tests/for-old.test b/tests/for-old.test
index 5750ad0..a11a791 100644
--- a/tests/for-old.test
+++ b/tests/for-old.test
@@ -69,15 +69,3 @@ test for-old-1.9 {for tests} {
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/for.test b/tests/for.test
index c227994..8f19e9f 100644
--- a/tests/for.test
+++ b/tests/for.test
@@ -10,7 +10,7 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2
namespace import -force ::tcltest::*
}
@@ -19,21 +19,21 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
test for-1.1 {TclCompileForCmd: missing initial command} {
list [catch {for} msg] $msg
} {1 {wrong # args: should be "for start test next command"}}
-test for-1.2 {TclCompileForCmd: error in initial command} {
- list [catch {for {set}} msg] $msg $errorInfo
-} {1 {wrong # args: should be "for start test next command"} {wrong # args: should be "for start test next command"
- while compiling
+test for-1.2 {TclCompileForCmd: error in initial command} -body {
+ list [catch {for {set}} msg] $msg $::errorInfo
+} -match glob -result {1 {wrong # args: should be "for start test next command"} {wrong # args: should be "for start test next command"
+ while *ing
"for {set}"}}
catch {unset i}
test for-1.3 {TclCompileForCmd: missing test expression} {
catch {for {set i 0}} msg
set msg
} {wrong # args: should be "for start test next command"}
-test for-1.4 {TclCompileForCmd: error in test expression} {
+test for-1.4 {TclCompileForCmd: error in test expression} -body {
catch {for {set i 0} {$i<}} msg
- set errorInfo
-} {wrong # args: should be "for start test next command"
- while compiling
+ set ::errorInfo
+} -match glob -result {wrong # args: should be "for start test next command"
+ while *ing
"for {set i 0} {$i<}"}
test for-1.5 {TclCompileForCmd: test expression is enclosed in quotes} {
set i 0
@@ -47,15 +47,12 @@ test for-1.7 {TclCompileForCmd: missing command body} {
catch {for {set i 0} {$i < 5} {incr i}} msg
set msg
} {wrong # args: should be "for start test next command"}
-test for-1.8 {TclCompileForCmd: error compiling command body} {
+test for-1.8 {TclCompileForCmd: error compiling command body} -body {
catch {for {set i 0} {$i < 5} {incr i} {set}} msg
- set errorInfo
-} {wrong # args: should be "set varName ?newValue?"
- while compiling
-"set"
- ("for" body line 1)
- while compiling
-"for {set i 0} {$i < 5} {incr i} {set}"}
+ set ::errorInfo
+} -match glob -result {wrong # args: should be "set varName ?newValue?"
+ while *ing
+"set"*}
catch {unset a}
test for-1.9 {TclCompileForCmd: simple command body} {
set a {}
@@ -81,15 +78,12 @@ test for-1.11 {TclCompileForCmd: computed command body} {
for {set i 1} {$i<6} {set i [expr $i+1]} $x1$bb$x2
set a
} {x1}
-test for-1.12 {TclCompileForCmd: error in "next" command} {
- catch {for {set i 0} {$i < 5} {set} {puts $i}} msg
- set errorInfo
-} {wrong # args: should be "set varName ?newValue?"
- while compiling
-"set"
- ("for" loop-end command)
- while compiling
-"for {set i 0} {$i < 5} {set} {puts $i}"}
+test for-1.12 {TclCompileForCmd: error in "next" command} -body {
+ catch {for {set i 0} {$i < 5} {set} {format $i}} msg
+ set ::errorInfo
+} -match glob -result {wrong # args: should be "set varName ?newValue?"
+ while *ing
+"set"*}
test for-1.13 {TclCompileForCmd: long command body} {
set a {}
for {set i 1} {$i<6} {set i [expr $i+1]} {
@@ -654,33 +648,32 @@ test for-6.5 {Tcl_ForObjCmd: number of args} {
catch {$z {set i 0} {$i < 5} {incr i} {body} extra} msg
set msg
} {wrong # args: should be "for start test next command"}
-test for-6.6 {Tcl_ForObjCmd: error in initial command} {
+test for-6.6 {Tcl_ForObjCmd: error in initial command} -body {
set z for
- list [catch {$z {set} {$i < 5} {incr i} {body}} msg] $msg $errorInfo
-} {1 {wrong # args: should be "set varName ?newValue?"} {wrong # args: should be "set varName ?newValue?"
- while compiling
+ list [catch {$z {set} {$i < 5} {incr i} {body}} msg] $msg $::errorInfo
+} -match glob -result {1 {wrong # args: should be "set varName ?newValue?"} {wrong # args: should be "set varName ?newValue?"
+ while *ing
"set"
("for" initial command)
invoked from within
"$z {set} {$i < 5} {incr i} {body}"}}
-test for-6.7 {Tcl_ForObjCmd: error in test expression} {
+test for-6.7 {Tcl_ForObjCmd: error in test expression} -body {
set z for
- list [catch {$z {set i 0} {i < 5} {incr i} {body}} msg] $msg $errorInfo
-} {1 {syntax error in expression "i < 5": variable references require preceding $} {syntax error in expression "i < 5": variable references require preceding $
- while executing
-"$z {set i 0} {i < 5} {incr i} {body}"}}
+ catch {$z {set i 0} {i < 5} {incr i} {body}}
+ set ::errorInfo
+} -match glob -result {*"$z {set i 0} {i < 5} {incr i} {body}"}
test for-6.8 {Tcl_ForObjCmd: test expression is enclosed in quotes} {
set z for
set i 0
$z {set i 6} "$i > 5" {incr i} {set y $i}
set i
} 6
-test for-6.9 {Tcl_ForObjCmd: error executing command body} {
+test for-6.9 {Tcl_ForObjCmd: error executing command body} -body {
set z for
catch {$z {set i 0} {$i < 5} {incr i} {set}} msg
- set errorInfo
-} {wrong # args: should be "set varName ?newValue?"
- while compiling
+ set ::errorInfo
+} -match glob -result {wrong # args: should be "set varName ?newValue?"
+ while *ing
"set"
("for" body line 1)
invoked from within
@@ -712,12 +705,12 @@ test for-6.12 {Tcl_ForObjCmd: computed command body} {
$z {set i 1} {$i<6} {set i [expr $i+1]} $x1$bb$x2
set a
} {x1}
-test for-6.13 {Tcl_ForObjCmd: error in "next" command} {
+test for-6.13 {Tcl_ForObjCmd: error in "next" command} -body {
set z for
catch {$z {set i 0} {$i < 5} {set} {set j 4}} msg
- set errorInfo
-} {wrong # args: should be "set varName ?newValue?"
- while compiling
+ set ::errorInfo
+} -match glob -result {wrong # args: should be "set varName ?newValue?"
+ while *ing
"set"
("for" loop-end command)
invoked from within
@@ -767,7 +760,56 @@ test for-6.16 {Tcl_ForObjCmd: for command result} {
set a [$z {set i 0} {$i < 5} {incr i} {if $i==3 break}]
set a
} {}
-
+test for-6.17 {Tcl_ForObjCmd: for command result} {
+ list \
+ [catch {for {break} {1} {} {}} err] $err \
+ [catch {for {continue} {1} {} {}} err] $err \
+ [catch {for {} {[break]} {} {}} err] $err \
+ [catch {for {} {[continue]} {} {}} err] $err \
+ [catch {for {} {1} {break} {}} err] $err \
+ [catch {for {} {1} {continue} {}} err] $err \
+} [list \
+ 3 {} \
+ 4 {} \
+ 3 {} \
+ 4 {} \
+ 0 {} \
+ 4 {} \
+ ]
+test for-6.18 {Tcl_ForObjCmd: for command result} {
+ proc p6181 {} {
+ for {break} {1} {} {}
+ }
+ proc p6182 {} {
+ for {continue} {1} {} {}
+ }
+ proc p6183 {} {
+ for {} {[break]} {} {}
+ }
+ proc p6184 {} {
+ for {} {[continue]} {} {}
+ }
+ proc p6185 {} {
+ for {} {1} {break} {}
+ }
+ proc p6186 {} {
+ for {} {1} {continue} {}
+ }
+ list \
+ [catch {p6181} err] $err \
+ [catch {p6182} err] $err \
+ [catch {p6183} err] $err \
+ [catch {p6184} err] $err \
+ [catch {p6185} err] $err \
+ [catch {p6186} err] $err
+} [list \
+ 1 {invoked "break" outside of a loop} \
+ 1 {invoked "continue" outside of a loop} \
+ 1 {invoked "break" outside of a loop} \
+ 1 {invoked "continue" outside of a loop} \
+ 0 {} \
+ 1 {invoked "continue" outside of a loop} \
+ ]
# cleanup
diff --git a/tests/foreach.test b/tests/foreach.test
index f353ffd..7df7481 100644
--- a/tests/foreach.test
+++ b/tests/foreach.test
@@ -71,8 +71,11 @@ catch {unset a}
test foreach-1.14 {foreach errors} {
catch {unset a}
set a(0) 44
- list [catch {foreach a {1 2 3} {}} msg] $msg
-} {1 {couldn't set loop variable: "a"}}
+ list [catch {foreach a {1 2 3} {}} msg o] $msg $::errorInfo
+} {1 {can't set "a": variable is array} {can't set "a": variable is array
+ (setting foreach loop variable "a")
+ invoked from within
+"foreach a {1 2 3} {}"}}
test foreach-1.15 {foreach errors} {
list [catch {foreach {} {} {}} msg] $msg
} {1 {foreach varlist is empty}}
@@ -161,7 +164,7 @@ test foreach-3.1 {compiled foreach backward jump works correctly} {
test foreach-4.1 {noncompiled foreach and shared variable or value list objects that are converted to another type} {
catch {unset x}
foreach {12.0} {a b c} {
- set x 12.0
+ set x 12.0
set x [expr $x + 1]
}
set x
@@ -208,7 +211,7 @@ test foreach-6.4 {break tests} {
catch {break foo} msg
set msg
} {wrong # args: should be "break"}
-# Check for bug #406709
+# Check for bug #406709
test foreach-6.5 {break tests} {
proc a {} {
set a 1
@@ -219,7 +222,6 @@ test foreach-6.5 {break tests} {
} {2}
# Test for incorrect "double evaluation" semantics
-
test foreach-7.1 {delayed substitution of body} {
proc foo {} {
set a 0
@@ -231,6 +233,17 @@ test foreach-7.1 {delayed substitution of body} {
foo
} {0}
+# Test for [Bug 1189274]; crash on failure
+test foreach-8.1 {empty list handling} {
+ proc crash {} {
+ rename crash {}
+ set a "x y z"
+ set b ""
+ foreach aa $a bb $b { set x "aa = $aa bb = $bb" }
+ }
+ crash
+} {}
+
# [Bug 1671138]; infinite loop with empty var list in bytecompiled version
test foreach-9.1 {compiled empty var list} {
proc foo {} {
@@ -243,9 +256,9 @@ test foreach-9.1 {compiled empty var list} {
test foreach-10.1 {foreach: [Bug 1671087]} -setup {
proc demo {} {
- set vals {1 2 3 4}
- trace add variable x write {string length $vals ;# }
- foreach {x y} $vals {format $y}
+ set vals {1 2 3 4}
+ trace add variable x write {string length $vals ;# }
+ foreach {x y} $vals {format $y}
}
} -body {
demo
diff --git a/tests/format.test b/tests/format.test
index c440603..d43b7eb 100644
--- a/tests/format.test
+++ b/tests/format.test
@@ -15,26 +15,25 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-# The following code is needed because some versions of SCO Unix have
-# a round-off error in sprintf which would cause some of the tests to
-# fail. Someday I hope this code shouldn't be necessary (code added
-# 9/9/91).
-
-set ::tcltest::testConstraints(roundOffBug) \
- [expr {"[format %7.1e 68.514]" != "6.8e+01"}]
+# %u output depends on word length, so this test is not portable.
+testConstraint longIs32bit [expr {int(0x80000000) < 0}]
+testConstraint longIs64bit [expr {int(0x8000000000000000) < 0}]
+testConstraint wideIs64bit \
+ [expr {(wide(0x80000000) > 0) && (wide(0x8000000000000000) < 0)}]
+testConstraint wideBiggerThanInt [expr {wide(0x80000000) != int(0x80000000)}]
test format-1.1 {integer formatting} {
format "%*d %d %d %d" 6 34 16923 -12 -1
} { 34 16923 -12 -1}
-test format-1.2 {integer formatting} {nonPortable} {
+test format-1.2 {integer formatting} {
format "%4d %4d %4d %4d %d %#x %#X" 6 34 16923 -12 -1 14 12
} { 6 34 16923 -12 -1 0xe 0XC}
-
-# %u output depends on word length, so this test is not portable.
-
-test format-1.3 {integer formatting} {nonPortable} {
+test format-1.3 {integer formatting} longIs32bit {
format "%4u %4u %4u %4u %d %#o" 6 34 16923 -12 -1 0
} { 6 34 16923 4294967284 -1 0}
+test format-1.3.1 {integer formatting} longIs64bit {
+ format "%4u %4u %4u %4u %d %#o" 6 34 16923 -12 -1 0
+} { 6 34 16923 18446744073709551604 -1 0}
test format-1.4 {integer formatting} {
format "%-4d %-4i %-4d %-4ld" 6 34 16923 -12 -1
} {6 34 16923 -12 }
@@ -44,25 +43,38 @@ test format-1.5 {integer formatting} {
test format-1.6 {integer formatting} {
format "%00*d" 6 34
} {000034}
-
# Printing negative numbers in hex or octal format depends on word
# length, so these tests are not portable.
-
-test format-1.7 {integer formatting} {nonPortable} {
+test format-1.7 {integer formatting} longIs32bit {
format "%4x %4x %4x %4x" 6 34 16923 -12 -1
} { 6 22 421b fffffff4}
-test format-1.8 {integer formatting} {nonPortable} {
+test format-1.7.1 {integer formatting} longIs64bit {
+ format "%4x %4x %4x %4x" 6 34 16923 -12 -1
+} { 6 22 421b fffffffffffffff4}
+test format-1.8 {integer formatting} longIs32bit {
format "%#x %#X %#X %#x" 6 34 16923 -12 -1
} {0x6 0X22 0X421B 0xfffffff4}
-test format-1.9 {integer formatting} {nonPortable} {
+test format-1.8.1 {integer formatting} longIs64bit {
+ format "%#x %#X %#X %#x" 6 34 16923 -12 -1
+} {0x6 0X22 0X421B 0xfffffffffffffff4}
+test format-1.9 {integer formatting} longIs32bit {
format "%#20x %#20x %#20x %#20x" 6 34 16923 -12 -1
} { 0x6 0x22 0x421b 0xfffffff4}
-test format-1.10 {integer formatting} {nonPortable} {
+test format-1.9.1 {integer formatting} longIs64bit {
+ format "%#20x %#20x %#20x %#20x" 6 34 16923 -12 -1
+} { 0x6 0x22 0x421b 0xfffffffffffffff4}
+test format-1.10 {integer formatting} longIs32bit {
format "%-#20x %-#20x %-#20x %-#20x" 6 34 16923 -12 -1
} {0x6 0x22 0x421b 0xfffffff4 }
-test format-1.11 {integer formatting} {nonPortable} {
+test format-1.10.1 {integer formatting} longIs64bit {
+ format "%-#20x %-#20x %-#20x %-#20x" 6 34 16923 -12 -1
+} {0x6 0x22 0x421b 0xfffffffffffffff4 }
+test format-1.11 {integer formatting} longIs32bit {
format "%-#20o %#-20o %#-20o %#-20o" 6 34 16923 -12 -1
} {06 042 041033 037777777764 }
+test format-1.11.1 {integer formatting} longIs64bit {
+ format "%-#20o %#-20o %#-20o %#-20o" 6 34 16923 -12 -1
+} {06 042 041033 01777777777777777777764}
test format-2.1 {string formatting} {
format "%s %s %c %s" abcd {This is a very long test string.} 120 x
@@ -129,19 +141,19 @@ test format-4.1 {e and f formats} {eformat} {
test format-4.2 {e and f formats} {eformat} {
format "%20e %20e %20e %20e" 34.2e12 68.514 -.125 -16000. .000053
} { 3.420000e+13 6.851400e+01 -1.250000e-01 -1.600000e+04}
-test format-4.3 {e and f formats} {eformat roundOffBug} {
+test format-4.3 {e and f formats} {eformat} {
format "%.1e %.1e %.1e %.1e" 34.2e12 68.514 -.126 -16000. .000053
} {3.4e+13 6.9e+01 -1.3e-01 -1.6e+04}
-test format-4.4 {e and f formats} {eformat roundOffBug} {
+test format-4.4 {e and f formats} {eformat} {
format "%020e %020e %020e %020e" 34.2e12 68.514 -.126 -16000. .000053
} {000000003.420000e+13 000000006.851400e+01 -00000001.260000e-01 -00000001.600000e+04}
-test format-4.5 {e and f formats} {eformat roundOffBug} {
+test format-4.5 {e and f formats} {eformat} {
format "%7.1e %7.1e %7.1e %7.1e" 34.2e12 68.514 -.126 -16000. .000053
} {3.4e+13 6.9e+01 -1.3e-01 -1.6e+04}
-test format-4.6 {e and f formats roundOffBug} {
+test format-4.6 {e and f formats} {
format "%f %f %f %f" 34.2e12 68.514 -.125 -16000. .000053
} {34200000000000.000000 68.514000 -0.125000 -16000.000000}
-test format-4.7 {e and f formats} {nonPortable} {
+test format-4.7 {e and f formats} {
format "%.4f %.4f %.4f %.4f %.4f" 34.2e12 68.514 -.125 -16000. .000053
} {34200000000000.0000 68.5140 -0.1250 -16000.0000 0.0001}
test format-4.8 {e and f formats} {eformat} {
@@ -354,13 +366,13 @@ test format-9.1 {long result} {
format {1111 2222 3333 4444 5555 6666 7777 8888 9999 aaaa bbbb cccc dddd eeee ffff gggg hhhh iiii jjjj kkkk llll mmmm nnnn oooo pppp qqqq rrrr ssss tttt uuuu vvvv wwww xxxx yyyy zzzz AAAA BBBB CCCC DDDD EEEE FFFF GGGG %s %s} $a $a
} {1111 2222 3333 4444 5555 6666 7777 8888 9999 aaaa bbbb cccc dddd eeee ffff gggg hhhh iiii jjjj kkkk llll mmmm nnnn oooo pppp qqqq rrrr ssss tttt uuuu vvvv wwww xxxx yyyy zzzz AAAA BBBB CCCC DDDD EEEE FFFF GGGG 1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z}
-test format-10.1 {"h" format specifier} {nonPortable} {
+test format-10.1 {"h" format specifier} {
format %hd 0xffff
} -1
-test format-10.2 {"h" format specifier} {nonPortable} {
+test format-10.2 {"h" format specifier} {
format %hx 0x10fff
} fff
-test format-10.3 {"h" format specifier} {nonPortable} {
+test format-10.3 {"h" format specifier} {
format %hd 0x10000
} 0
test format-10.4 {"h" format specifier} {
@@ -412,6 +424,7 @@ test format-11.12 {XPG3 %$n specifiers} {
test format-12.1 {negative width specifiers} {
format "%*d" -47 25
} {25 }
+
test format-13.1 {tcl_precision fuzzy comparison} {
catch {unset a}
catch {unset b}
@@ -461,6 +474,7 @@ test format-13.5 {tcl_precision fuzzy comparison} {
set c [expr $a + $b]
format {%0.10f %0.12f %0.15f} $c $c $c
} {1.4444444444 1.444444444444 1.444444444443990}
+
test format-14.1 {testing MAX_FLOAT_SIZE for 0 and 1} {
format {%s} ""
} {}
@@ -480,6 +494,12 @@ test format-15.3 {testing %0..s 0 padding for chars/strings} {
test format-15.4 {testing %0..s 0 padding for chars/strings} {
format %05c 61
} {0000=}
+test format-15.5 {testing %d space padding for integers} {
+ format "(% 1d) (% 1d)" 10 -10
+} {( 10) (-10)}
+test format-15.6 {testing %d plus padding for integers} {
+ format "(%+1d) (%+1d)" 10 -10
+} {(+10) (-10)}
set a "0123456789"
set b ""
@@ -488,35 +508,23 @@ for {set i 0} {$i < 290} {incr i} {
}
for {set i 290} {$i < 400} {incr i} {
test format-16.[expr $i -289] {testing MAX_FLOAT_SIZE} {
- format {%s} $b
+ format {%s} $b
} $b
append b "x"
}
-::tcltest::testConstraint 64bitInts \
- [expr {0x80000000 > 0}]
-::tcltest::testConstraint wideIntExpressions \
- [expr {wide(0x80000000) != int(0x80000000)}]
-
-test format-17.1 {testing %d with wide} {64bitInts wideIntExpressions} {
+test format-17.1 {testing %d with wide} {wideIs64bit wideBiggerThanInt} {
format %d 7810179016327718216
} 1819043144
-test format-17.2 {testing %ld with wide} {64bitInts} {
+test format-17.2 {testing %ld with wide} {wideIs64bit} {
format %ld 7810179016327718216
} 7810179016327718216
-test format-17.3 {testing %ld with non-wide} {64bitInts} {
+test format-17.3 {testing %ld with non-wide} {wideIs64bit} {
format %ld 42
} 42
test format-17.4 {testing %l with non-integer} {
format %lf 1
} 1.000000
-test format-17.5 {type conversions with wides} {
- set a 0xAAAAAAAA ;# NB: Careful to make separate objects here!
- set b 0xAAAAAAA; append b A
- set result [expr {$a == $b}]
- format %x $a
- lappend result [expr {$a == $b}]
-} {1 1}
test format-18.1 {do not demote existing numeric values} {
set a 0xaaaaaaaa
@@ -535,7 +543,7 @@ test format-18.1 {do not demote existing numeric values} {
format %08x $b
lappend result [expr {$a == $b}]
} {1 1 1 1}
-test format-18.2 {do not demote existing numeric values} {wideIntExpressions} {
+test format-18.2 {do not demote existing numeric values} {wideBiggerThanInt} {
set a [expr {0xaaaaaaaaaa + 1}]
set b 0xaaaaaaaaab
list [format %08x $a] [expr {$a == $b}]
@@ -549,6 +557,14 @@ test format-19.1 {
list [expr { ~ $x }] [format %08x [expr { ~$x }]]
} -match regexp -result {-2414724693 f*701239ab}
+test format-19.2 {Bug 1867855} {
+ format %llx 0
+} 0
+
+test format-19.3 {Bug 2830354} {
+ string length [format %340f 0]
+} 340
+
# cleanup
catch {unset a}
catch {unset b}
@@ -556,3 +572,7 @@ catch {unset c}
catch {unset d}
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/get.test b/tests/get.test
index d35c19b..40ec98f 100644
--- a/tests/get.test
+++ b/tests/get.test
@@ -15,69 +15,52 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-test get-1.1 {Tcl_GetInt procedure} {
- set x 44
- incr x { 22}
+testConstraint testgetint [llength [info commands testgetint]]
+testConstraint longIs32bit [expr {int(0x80000000) < 0}]
+testConstraint longIs64bit [expr {int(0x8000000000000000) < 0}]
+
+test get-1.1 {Tcl_GetInt procedure} testgetint {
+ testgetint 44 { 22}
} {66}
-test get-1.2 {Tcl_GetInt procedure} {
- set x 44
- incr x -3
+test get-1.2 {Tcl_GetInt procedure} testgetint {
+ testgetint 44 -3
} {41}
-test get-1.3 {Tcl_GetInt procedure} {
- set x 44
- incr x +8
+test get-1.3 {Tcl_GetInt procedure} testgetint {
+ testgetint 44 +8
} {52}
-test get-1.4 {Tcl_GetInt procedure} {
- set x 44
- list [catch {incr x foo} msg] $msg
+test get-1.4 {Tcl_GetInt procedure} testgetint {
+ list [catch {testgetint 44 foo} msg] $msg
} {1 {expected integer but got "foo"}}
-test get-1.5 {Tcl_GetInt procedure} {
- set x 44
- list [catch {incr x {16 }} msg] $msg
+test get-1.5 {Tcl_GetInt procedure} testgetint {
+ list [catch {testgetint 44 {16 }} msg] $msg
} {0 60}
-test get-1.6 {Tcl_GetInt procedure} {
- set x 44
- list [catch {incr x {16 x}} msg] $msg
+test get-1.6 {Tcl_GetInt procedure} testgetint {
+ list [catch {testgetint 44 {16 x}} msg] $msg
} {1 {expected integer but got "16 x"}}
-
-# The following tests are non-portable because they depend on
-# word size.
-
-if {wide(0x80000000) > wide(0)} {
- test get-1.7 {Tcl_GetInt procedure} {
- set x 44
- list [catch {eval incr x 18446744073709551616} msg] $msg $errorCode
- } {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}}
- test get-1.8 {Tcl_GetInt procedure} {
- set x 0
- list [catch {incr x 18446744073709551614} msg] $msg
- } {0 -2}
- test get-1.9 {Tcl_GetInt procedure} {
- set x 0
- list [catch {incr x +18446744073709551614} msg] $msg
- } {0 -2}
- test get-1.10 {Tcl_GetInt procedure} {
- set x 0
- list [catch {incr x -18446744073709551614} msg] $msg
- } {0 2}
-} else {
- test get-1.11 {Tcl_GetInt procedure} {
- set x 44
- list [catch {incr x 4294967296} msg] $msg $errorCode
- } {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}}
- test get-1.12 {Tcl_GetInt procedure} {
- set x 0
- list [catch {incr x 4294967294} msg] $msg
- } {0 -2}
- test get-1.13 {Tcl_GetInt procedure} {
- set x 0
- list [catch {incr x +4294967294} msg] $msg
- } {0 -2}
- test get-1.14 {Tcl_GetInt procedure} {
- set x 0
- list [catch {incr x -4294967294} msg] $msg
- } {0 2}
-}
+test get-1.7 {Tcl_GetInt procedure} {testgetint longIs64bit} {
+ list [catch {testgetint 44 18446744073709551616} msg] $msg $errorCode
+} {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}}
+test get-1.8 {Tcl_GetInt procedure} {testgetint longIs64bit} {
+ list [catch {testgetint 18446744073709551614} msg] $msg
+} {0 -2}
+test get-1.9 {Tcl_GetInt procedure} {testgetint longIs64bit} {
+ list [catch {testgetint +18446744073709551614} msg] $msg
+} {0 -2}
+test get-1.10 {Tcl_GetInt procedure} {testgetint longIs64bit} {
+ list [catch {testgetint -18446744073709551614} msg] $msg
+} {0 2}
+test get-1.11 {Tcl_GetInt procedure} {testgetint longIs32bit} {
+ list [catch {testgetint 44 4294967296} msg] $msg $errorCode
+} {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}}
+test get-1.12 {Tcl_GetInt procedure} {testgetint longIs32bit} {
+ list [catch {testgetint 4294967294} msg] $msg
+} {0 -2}
+test get-1.13 {Tcl_GetInt procedure} {testgetint longIs32bit} {
+ list [catch {testgetint +4294967294} msg] $msg
+} {0 -2}
+test get-1.14 {Tcl_GetInt procedure} {testgetint longIs32bit} {
+ list [catch {testgetint -4294967294} msg] $msg
+} {0 2}
test get-2.1 {Tcl_GetInt procedure} {
format %g 1.23
@@ -88,9 +71,9 @@ test get-2.2 {Tcl_GetInt procedure} {
test get-2.3 {Tcl_GetInt procedure} {
list [catch {format %g clip} msg] $msg
} {1 {expected floating-point number but got "clip"}}
-test get-2.4 {Tcl_GetInt procedure} {nonPortable} {
- list [catch {format %g .000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001} msg] $msg $errorCode
-} {1 {floating-point value too small to represent} {ARITH UNDERFLOW {floating-point value too small to represent}}}
+test get-2.4 {Tcl_GetInt procedure} {
+ format %g .000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
+} 0
test get-3.1 {Tcl_GetInt(FromObj), bad numbers} {
# SF bug #634856
@@ -113,15 +96,3 @@ test get-3.2 {Tcl_GetDouble(FromObj), bad numbers} {
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/history.test b/tests/history.test
index 898d009..49116be 100644
--- a/tests/history.test
+++ b/tests/history.test
@@ -16,127 +16,150 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
+# The history command might be autoloaded...
if {[catch {history}]} {
- puts stdout "This version of Tcl was built without the history command;\n"
- puts stdout "history tests will be skipped.\n"
- ::tcltest::cleanupTests
- return
+ testConstraint history 0
+} else {
+ testConstraint history 1
}
-set num [history nextid]
-history keep 3
-history add {set a 12345}
-history add {set b [format {A test %s} string]}
-history add {Another test}
+if {[testConstraint history]} {
+ set num [history nextid]
+ history keep 3
+ history add {set a 12345}
+ history add {set b [format {A test %s} string]}
+ history add {Another test}
+} else {
+ # Dummy value, must be numeric
+ set num 0
+}
# "history event"
-test history-1.1 {event option} {history event -1} \
+test history-1.1 {event option} history {history event -1} \
{set b [format {A test %s} string]}
-test history-1.2 {event option} {history event $num} \
+test history-1.2 {event option} history {history event $num} \
{set a 12345}
-test history-1.3 {event option} {history event [expr $num+2]} \
+test history-1.3 {event option} history {history event [expr $num+2]} \
{Another test}
-test history-1.4 {event option} {history event set} \
+test history-1.4 {event option} history {history event set} \
{set b [format {A test %s} string]}
-test history-1.5 {event option} {history e "* a*"} \
+test history-1.5 {event option} history {history e "* a*"} \
{set a 12345}
-test history-1.6 {event option} {catch {history event *gorp} msg} 1
-test history-1.7 {event option} {
+test history-1.6 {event option} history {catch {history event *gorp} msg} 1
+test history-1.7 {event option} history {
catch {history event *gorp} msg
set msg
} {no event matches "*gorp"}
-test history-1.8 {event option} {history event} \
+test history-1.8 {event option} history {history event} \
{set b [format {A test %s} string]}
-test history-1.9 {event option} {catch {history event 123 456} msg} 1
-test history-1.10 {event option} {
+test history-1.9 {event option} history {catch {history event 123 456} msg} 1
+test history-1.10 {event option} history {
catch {history event 123 456} msg
set msg
} {wrong # args: should be "history event ?event?"}
# "history redo"
-set a 0
-history redo -2
-test history-2.1 {redo option} {set a} 12345
-set b 0
-history redo
-test history-2.2 {redo option} {set b} {A test string}
-test history-2.3 {redo option} {catch {history redo -3 -4}} 1
-test history-2.4 {redo option} {
+if {[testConstraint history]} {
+ set a 0
+ history redo -2
+}
+test history-2.1 {redo option} history {set a} 12345
+if {[testConstraint history]} {
+ set b 0
+ history redo
+}
+test history-2.2 {redo option} history {set b} {A test string}
+test history-2.3 {redo option} history {catch {history redo -3 -4}} 1
+test history-2.4 {redo option} history {
catch {history redo -3 -4} msg
set msg
} {wrong # args: should be "history redo ?event?"}
# "history add"
-history add "set a 444" exec
-test history-3.1 {add option} {set a} 444
-test history-3.2 {add option} {catch {history add "set a 444" execGorp}} 1
-test history-3.3 {add option} {
+if {[testConstraint history]} {
+ history add "set a 444" exec
+}
+test history-3.1 {add option} history {set a} 444
+test history-3.2 {add option} history {catch {history add "set a 444" execGorp}} 1
+test history-3.3 {add option} history {
catch {history add "set a 444" execGorp} msg
set msg
} {bad argument "execGorp": should be "exec"}
-test history-3.4 {add option} {catch {history add "set a 444" a} msg} 1
-test history-3.5 {add option} {
+test history-3.4 {add option} history {catch {history add "set a 444" a} msg} 1
+test history-3.5 {add option} history {
catch {history add "set a 444" a} msg
set msg
} {bad argument "a": should be "exec"}
-history add "set a 555" e
-test history-3.6 {add option} {set a} 555
-history add "set a 666"
-test history-3.7 {add option} {set a} 555
-test history-3.8 {add option} {catch {history add "set a 666" e f} msg} 1
-test history-3.9 {add option} {
+if {[testConstraint history]} {
+ history add "set a 555" e
+}
+test history-3.6 {add option} history {set a} 555
+if {[testConstraint history]} {
+ history add "set a 666"
+}
+test history-3.7 {add option} history {set a} 555
+test history-3.8 {add option} history {catch {history add "set a 666" e f} msg} 1
+test history-3.9 {add option} history {
catch {history add "set a 666" e f} msg
set msg
} {wrong # args: should be "history add event ?exec?"}
# "history change"
-history change "A test value"
-test history-4.1 {change option} {history event [expr {[history n]-1}]} \
+if {[testConstraint history]} {
+ history change "A test value"
+}
+test history-4.1 {change option} history {history event [expr {[history n]-1}]} \
"A test value"
-history ch "Another test" -1
-test history-4.2 {change option} {history e} "Another test"
-test history-4.3 {change option} {history event [expr {[history n]-1}]} \
+if {[testConstraint history]} {
+ history ch "Another test" -1
+}
+test history-4.2 {change option} history {history e} "Another test"
+test history-4.3 {change option} history {history event [expr {[history n]-1}]} \
"A test value"
-test history-4.4 {change option} {catch {history change Foo 4 10}} 1
-test history-4.5 {change option} {
+test history-4.4 {change option} history {catch {history change Foo 4 10}} 1
+test history-4.5 {change option} history {
catch {history change Foo 4 10} msg
set msg
} {wrong # args: should be "history change newValue ?event?"}
-test history-4.6 {change option} {
+test history-4.6 {change option} history {
catch {history change Foo [expr {[history n]-4}]}
} 1
-set num [expr {[history n]-4}]
-test history-4.7 {change option} {
+if {[testConstraint history]} {
+ set num [expr {[history n]-4}]
+}
+test history-4.7 {change option} history {
catch {history change Foo $num} msg
set msg
} "event \"$num\" is too far in the past"
# "history info"
-set num [history n]
-history add set\ a\ {b\nc\ d\ e}
-history add {set b 1234}
-history add set\ c\ {a\nb\nc}
-test history-5.1 {info option} {history info} [format {%6d set a {b
+if {[testConstraint history]} {
+ set num [history n]
+ history add set\ a\ {b\nc\ d\ e}
+ history add {set b 1234}
+ history add set\ c\ {a\nb\nc}
+}
+test history-5.1 {info option} history {history info} [format {%6d set a {b
c d e}
%6d set b 1234
%6d set c {a
b
c}} $num [expr $num+1] [expr $num+2]]
-test history-5.2 {info option} {history i 2} [format {%6d set b 1234
+test history-5.2 {info option} history {history i 2} [format {%6d set b 1234
%6d set c {a
b
c}} [expr $num+1] [expr $num+2]]
-test history-5.3 {info option} {catch {history i 2 3}} 1
-test history-5.4 {info option} {
+test history-5.3 {info option} history {catch {history i 2 3}} 1
+test history-5.4 {info option} history {
catch {history i 2 3} msg
set msg
} {wrong # args: should be "history info ?count?"}
-test history-5.5 {info option} {history} [format {%6d set a {b
+test history-5.5 {info option} history {history} [format {%6d set a {b
c d e}
%6d set b 1234
%6d set c {a
@@ -145,69 +168,79 @@ test history-5.5 {info option} {history} [format {%6d set a {b
# "history keep"
-history add "foo1"
-history add "foo2"
-history add "foo3"
-history keep 2
-test history-6.1 {keep option} {history event [expr [history n]-1]} foo3
-test history-6.2 {keep option} {history event -1} foo2
-test history-6.3 {keep option} {catch {history event -3}} 1
-test history-6.4 {keep option} {
+if {[testConstraint history]} {
+ history add "foo1"
+ history add "foo2"
+ history add "foo3"
+ history keep 2
+}
+test history-6.1 {keep option} history {history event [expr [history n]-1]} foo3
+test history-6.2 {keep option} history {history event -1} foo2
+test history-6.3 {keep option} history {catch {history event -3}} 1
+test history-6.4 {keep option} history {
catch {history event -3} msg
set msg
} {event "-3" is too far in the past}
-history k 5
-test history-6.5 {keep option} {history event -1} foo2
-test history-6.6 {keep option} {history event -2} {}
-test history-6.7 {keep option} {history event -3} {}
-test history-6.8 {keep option} {history event -4} {}
-test history-6.9 {keep option} {catch {history event -5}} 1
-test history-6.10 {keep option} {catch {history keep 4 6}} 1
-test history-6.11 {keep option} {
+if {[testConstraint history]} {
+ history k 5
+}
+test history-6.5 {keep option} history {history event -1} foo2
+test history-6.6 {keep option} history {history event -2} {}
+test history-6.7 {keep option} history {history event -3} {}
+test history-6.8 {keep option} history {history event -4} {}
+test history-6.9 {keep option} history {catch {history event -5}} 1
+test history-6.10 {keep option} history {catch {history keep 4 6}} 1
+test history-6.11 {keep option} history {
catch {history keep 4 6} msg
set msg
} {wrong # args: should be "history keep ?count?"}
-test history-6.12 {keep option} {catch {history keep}} 0
-test history-6.13 {keep option} {
+test history-6.12 {keep option} history {catch {history keep}} 0
+test history-6.13 {keep option} history {
history keep
} {5}
-test history-6.14 {keep option} {catch {history keep -3}} 1
-test history-6.15 {keep option} {
+test history-6.14 {keep option} history {catch {history keep -3}} 1
+test history-6.15 {keep option} history {
catch {history keep -3} msg
set msg
} {illegal keep count "-3"}
-test history-6.16 {keep option} {
+test history-6.16 {keep option} history {
catch {history keep butter} msg
set msg
} {illegal keep count "butter"}
# "history nextid"
-set num [history n]
-history add "Testing"
-history add "Testing2"
-test history-7.1 {nextid option} {history event} "Testing"
-test history-7.2 {nextid option} {history next} [expr $num+2]
-test history-7.3 {nextid option} {catch {history nextid garbage}} 1
-test history-7.4 {nextid option} {
+if {[testConstraint history]} {
+ set num [history n]
+ history add "Testing"
+ history add "Testing2"
+}
+test history-7.1 {nextid option} history {history event} "Testing"
+test history-7.2 {nextid option} history {history next} [expr $num+2]
+test history-7.3 {nextid option} history {catch {history nextid garbage}} 1
+test history-7.4 {nextid option} history {
catch {history nextid garbage} msg
set msg
} {wrong # args: should be "history nextid"}
# "history clear"
-set num [history n]
-history add "Testing"
-history add "Testing2"
-test history-8.1 {clear option} {catch {history clear junk}} 1
-test history-8.2 {clear option} {history clear} {}
-history add "Testing"
-test history-8.3 {clear option} {history} { 1 Testing}
+if {[testConstraint history]} {
+ set num [history n]
+ history add "Testing"
+ history add "Testing2"
+}
+test history-8.1 {clear option} history {catch {history clear junk}} 1
+test history-8.2 {clear option} history {history clear} {}
+if {[testConstraint history]} {
+ history add "Testing"
+}
+test history-8.3 {clear option} history {history} { 1 Testing}
# miscellaneous
-test history-9.1 {miscellaneous} {catch {history gorp} msg} 1
-test history-9.2 {miscellaneous} {
+test history-9.1 {miscellaneous} history {catch {history gorp} msg} 1
+test history-9.2 {miscellaneous} history {
catch {history gorp} msg
set msg
} {bad option "gorp": must be add, change, clear, event, info, keep, nextid, or redo}
@@ -215,15 +248,3 @@ test history-9.2 {miscellaneous} {
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/http.test b/tests/http.test
index f8a79be..602047f 100644
--- a/tests/http.test
+++ b/tests/http.test
@@ -94,7 +94,7 @@ test http-1.4 {http::config} {
-proxyfilter myFilter -useragent "Tcl Test Suite" \
-urlencoding iso8859-1
set x [http::config]
- eval http::config $savedconf
+ http::config {*}$savedconf
set x
} {-accept */* -proxyfilter myFilter -proxyhost nowhere.come -proxyport 8080 -urlencoding iso8859-1 -useragent {Tcl Test Suite}}
test http-1.5 {http::config} {
@@ -114,7 +114,7 @@ test http-2.1 {http::reset} {
test http-3.1 {http::geturl} {
list [catch {http::geturl -bogus flag} msg] $msg
-} {1 {Unknown option flag, can be: -binary, -blocksize, -channel, -command, -handler, -headers, -progress, -query, -queryblocksize, -querychannel, -queryprogress, -validate, -timeout, -type}}
+} {1 {Unknown option flag, can be: -binary, -blocksize, -channel, -command, -handler, -headers, -keepalive, -method, -myaddr, -progress, -protocol, -query, -queryblocksize, -querychannel, -queryprogress, -strict, -timeout, -type, -validate}}
test http-3.2 {http::geturl} {
catch {http::geturl http:junk} err
set err
@@ -134,8 +134,6 @@ set fullurl http://user:pass@[info hostname]:$port/a/b/c
set binurl //[info hostname]:$port/binary
set posturl //[info hostname]:$port/post
set badposturl //[info hostname]:$port/droppost
-set badcharurl //%user@[info hostname]:$port/a/^b/c
-
test http-3.4 {http::geturl} {
set token [http::geturl $url]
http::data $token
@@ -204,7 +202,7 @@ test http-3.10 {http::geturl queryprogress} {
lappend postProgress $y
}
set postProgress {}
- set t [http::geturl $posturl -query $query \
+ set t [http::geturl $posturl -keepalive 0 -query $query \
-queryprogress postProgress -queryblocksize 16384]
http::wait $t
list [http::status $t] [string length $query] $postProgress [http::data $t]
@@ -279,7 +277,7 @@ test http-3.12 {http::geturl querychannel with aborted request} {nonPortable} {
http::wait $t
upvar #0 $t state
} err]} {
- puts $errorInfo
+ puts $::errorInfo
error $err
}
@@ -312,40 +310,29 @@ test http-3.18 {http::geturl parse failures} -body {
http::geturl http://somewhere:123456789/
} -returnCodes error -result {Invalid port number: 123456789}
test http-3.19 {http::geturl parse failures} -body {
- set ::http::strict 1
http::geturl http://{user}@somewhere
} -returnCodes error -result {Illegal characters in URL user}
test http-3.20 {http::geturl parse failures} -body {
- set ::http::strict 1
http::geturl http://%user@somewhere
} -returnCodes error -result {Illegal encoding character usage "%us" in URL user}
test http-3.21 {http::geturl parse failures} -body {
- set ::http::strict 1
http::geturl http://somewhere/{path}
} -returnCodes error -result {Illegal characters in URL path}
test http-3.22 {http::geturl parse failures} -body {
- set ::http::strict 1
http::geturl http://somewhere/%path
} -returnCodes error -result {Illegal encoding character usage "%pa" in URL path}
test http-3.23 {http::geturl parse failures} -body {
- set ::http::strict 1
http::geturl http://somewhere/path?{query}
} -returnCodes error -result {Illegal characters in URL path}
test http-3.24 {http::geturl parse failures} -body {
- set ::http::strict 1
http::geturl http://somewhere/path?%query
} -returnCodes error -result {Illegal encoding character usage "%qu" in URL path}
-test http-3.25 {http::geturl parse failures} -body {
- set ::http::strict 0
- set token [http::geturl $badcharurl]
- http::cleanup $token
-} -returnCodes ok -result {}
test http-4.1 {http::Event} {
- set token [http::geturl $url]
+ set token [http::geturl $url -keepalive 0]
upvar #0 $token data
array set meta $data(meta)
- expr ($data(totalsize) == $meta(Content-Length))
+ expr {($data(totalsize) == $meta(Content-Length))}
} 1
test http-4.2 {http::Event} {
set token [http::geturl $url]
@@ -374,11 +361,12 @@ test http-4.4 {http::Event} {
test http-4.5 {http::Event} {
set testfile [makeFile "" testfile]
set out [open $testfile w]
+ fconfigure $out -translation lf
set token [http::geturl $url -channel $out]
close $out
upvar #0 $token data
removeFile $testfile
- expr $data(currentsize) == $data(totalsize)
+ expr {$data(currentsize) == $data(totalsize)}
} 1
test http-4.6 {http::Event} {
set testfile [makeFile "" testfile]
@@ -408,7 +396,7 @@ if 0 {
} {111 111}
}
test http-4.7 {http::Event} {
- set token [http::geturl $url -progress myProgress]
+ set token [http::geturl $url -keepalive 0 -progress myProgress]
set progress
} {111 111}
test http-4.8 {http::Event} {
@@ -427,49 +415,43 @@ test http-4.10 {http::Event} {
# Short timeout to working server (the test server). This lets us try a
# reset during the connection.
test http-4.11 {http::Event} {
- set token [http::geturl $url -timeout 1 -command {#}]
+ set token [http::geturl $url -timeout 1 -keepalive 0 -command {#}]
http::reset $token
http::status $token
} {reset}
# Longer timeout with reset.
test http-4.12 {http::Event} {
- set token [http::geturl $url/?timeout=10 -command {#}]
+ set token [http::geturl $url/?timeout=10 -keepalive 0 -command {#}]
http::reset $token
http::status $token
} {reset}
# Medium timeout to working server that waits even longer. The timeout
# hits while waiting for a reply.
test http-4.13 {http::Event} {
- set token [http::geturl $url?timeout=30 -timeout 10 -command {#}]
+ set token [http::geturl $url?timeout=30 -keepalive 0 -timeout 10 -command {#}]
http::wait $token
http::status $token
} {timeout}
# Longer timeout to good host, bad port, gets an error after the
# connection "completes" but the socket is bad.
-test http-4.14 {http::Event} {
- set code [catch {
- set token [http::geturl $badurl/?timeout=10 -timeout 10000 -command {#}]
- if {[string length $token] == 0} {
- error "bogus return from http::geturl"
- }
- http::wait $token
- http::status $token
- } err]
+test http-4.14 {http::Event} -body {
+ set token [http::geturl $badurl/?timeout=10 -timeout 10000 -command \#]
+ if {$token eq ""} {
+ error "bogus return from http::geturl"
+ }
+ http::wait $token
+ http::status $token
# error code varies among platforms.
- list $code [regexp {(connect failed|couldn't open socket)} $err]
-} {1 1}
+} -returnCodes 1 -match regexp -result {(connect failed|couldn't open socket)}
# Bogus host
-test http-4.15 {http::Event} {
- # This test may fail if you use a proxy server. That is to be
+test http-4.15 {http::Event} -body {
+ # This test may fail if you use a proxy server. That is to be
# expected and is not a problem with Tcl.
- set code [catch {
- set token [http::geturl //not_a_host.tcl.tk -timeout 1000 -command {#}]
- http::wait $token
- http::status $token
- } err]
- # error code varies among platforms.
- list $code [string match "couldn't open socket*" $err]
-} {1 1}
+ set token [http::geturl //not_a_host.tcl.tk -timeout 1000 -command \#]
+ http::wait $token
+ http::status $token
+ # error codes vary among platforms.
+} -returnCodes 1 -match glob -result "couldn't open socket*"
test http-5.1 {http::formatQuery} {
http::formatQuery name1 value1 name2 "value two"
diff --git a/tests/httpd b/tests/httpd
index 3ea8024..5272385 100644
--- a/tests/httpd
+++ b/tests/httpd
@@ -1,3 +1,4 @@
+# -*- tcl -*-
#
# The httpd_ procedures implement a stub http server.
#
@@ -25,7 +26,7 @@ array set httpdErrors {
404 {Not Found}
503 {Service Unavailable}
504 {Service Temporarily Unavailable}
- }
+}
proc httpdError {sock code args} {
global httpdErrors
@@ -54,8 +55,8 @@ proc httpdRead { sock } {
# Read the protocol line and parse out the URL and query
set readCount [gets $sock line]
- if [regexp {(POST|GET|HEAD) ([^?]+)\??([^ ]*) HTTP/(1.[01])} \
- $line x data(proto) data(url) data(query) data(httpversion)] {
+ if {[regexp {(POST|GET|HEAD) ([^?]+)\??([^ ]*) HTTP/(1.[01])} $line \
+ -> data(proto) data(url) data(query) data(httpversion)]} {
set data(state) mime
httpd_log $sock Query $line
} else {
@@ -69,6 +70,10 @@ proc httpdRead { sock } {
# Read the HTTP headers
set readCount [gets $sock line]
+ if {[regexp {^([^:]+):(.*)$} $line -> key val]} {
+ lappend data(meta) $key [string trim $val]
+ }
+
} elseif {$data(state) == "query"} {
# Read the query data
@@ -94,7 +99,7 @@ proc httpdRead { sock } {
}
0,mime,HEAD -
0,mime,GET -
- 0,query,POST {
+ 0,query,POST {
# Empty line at end of headers,
# or eof after query data
httpdRespond $sock
@@ -190,18 +195,27 @@ proc httpdRespond { sock } {
append html </body></html>
}
}
-
- # Catch errors from premature client closes
+ # Catch errors from premature client closes
+
catch {
if {$data(proto) == "HEAD"} {
puts $sock "HTTP/1.0 200 OK"
} else {
- puts $sock "HTTP/1.0 200 Data follows"
+ # Split the response to test for [Bug 26245326]
+ puts -nonewline $sock "HT"
+ flush $sock
+ puts $sock "TP/1.0 200 Data follows"
}
- puts $sock "Date: [clock format [clock clicks]]"
+ puts $sock "Date: [clock format [clock seconds] \
+ -format {%a, %d %b %Y %H:%M:%S %Z}]"
puts $sock "Content-Type: $type"
puts $sock "Content-Length: [string length $html]"
+ foreach {key val} $data(meta) {
+ if {[string match "X-*" $key]} {
+ puts $sock "$key: $val"
+ }
+ }
puts $sock ""
flush $sock
if {$data(proto) != "HEAD"} {
@@ -212,5 +226,3 @@ proc httpdRespond { sock } {
httpd_log $sock Done ""
httpdSockDone $sock
}
-
-
diff --git a/tests/httpold.test b/tests/httpold.test
index b54a929..aeba311 100644
--- a/tests/httpold.test
+++ b/tests/httpold.test
@@ -291,15 +291,3 @@ catch {unset data}
close $listen
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/if.test b/tests/if.test
index e9da6d5..f941d54 100644
--- a/tests/if.test
+++ b/tests/if.test
@@ -11,7 +11,7 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2
namespace import -force ::tcltest::*
}
@@ -24,12 +24,9 @@ test if-1.1 {TclCompileIfCmd: missing if/elseif test} {
test if-1.2 {TclCompileIfCmd: error in if/elseif test} {
list [catch {if {[error "error in condition"]} foo} msg] $msg
} {1 {error in condition}}
-test if-1.3 {TclCompileIfCmd: error in if/elseif test} {
- list [catch {if {1+}} msg] $msg $errorInfo
-} {1 {syntax error in expression "1+": premature end of expression} {syntax error in expression "1+": premature end of expression
- ("if" test expression)
- while compiling
-"if {1+}"}}
+test if-1.3 {TclCompileIfCmd: error in if/elseif test} -body {
+ list [catch {if {1+}} msg] $msg $::errorInfo
+} -match glob -result {1 * {*"if {1+}"}}
test if-1.4 {TclCompileIfCmd: if/elseif test in braces} {
set a {}
if {1<2} {set a 1}
@@ -61,15 +58,12 @@ test if-1.9 {TclCompileIfCmd: missing "then" body} {
catch {if 1<2 then} msg
set msg
} {wrong # args: no script following "then" argument}
-test if-1.10 {TclCompileIfCmd: error in "then" body} {
+test if-1.10 {TclCompileIfCmd: error in "then" body} -body {
set a {}
- list [catch {if {$a!="xxx"} then {set}} msg] $msg $errorInfo
-} {1 {wrong # args: should be "set varName ?newValue?"} {wrong # args: should be "set varName ?newValue?"
- while compiling
-"set"
- ("if" then script line 1)
- while compiling
-"if {$a!="xxx"} then {set}"}}
+ list [catch {if {$a!="xxx"} then {set}} msg] $msg $::errorInfo
+} -match glob -result {1 {wrong # args: should be "set varName ?newValue?"} {wrong # args: should be "set varName ?newValue?"
+ while *ing
+"set"*}}
test if-1.11 {TclCompileIfCmd: error in "then" body} {
list [catch {if 2 then {[error "error in then clause"]}} msg] $msg
} {1 {error in then clause}}
@@ -175,13 +169,10 @@ test if-2.3 {TclCompileIfCmd: missing expression after "elseif"} {
catch {if 1<2 {set a 1} elseif} msg
set msg
} {wrong # args: no expression after "elseif" argument}
-test if-2.4 {TclCompileIfCmd: error in expression after "elseif"} {
+test if-2.4 {TclCompileIfCmd: error in expression after "elseif"} -body {
set a {}
- list [catch {if 3>4 {set a 1} elseif {1>}} msg] $msg $errorInfo
-} {1 {syntax error in expression "1>": premature end of expression} {syntax error in expression "1>": premature end of expression
- ("if" test expression)
- while compiling
-"if 3>4 {set a 1} elseif {1>}"}}
+ list [catch {if 3>4 {set a 1} elseif {1>}} msg] $msg $::errorInfo
+} -match glob -result {1 * {*"if 3>4 {set a 1} elseif {1>}"}}
test if-2.5 {TclCompileIfCmd: test jumpFalse instruction replacement after long "elseif" body} {
catch {unset i}
set a {}
@@ -302,16 +293,13 @@ test if-3.3 {TclCompileIfCmd: missing body after "else"} {
catch {if 2<1 {set a 1} else} msg
set msg
} {wrong # args: no script following "else" argument}
-test if-3.4 {TclCompileIfCmd: error compiling body after "else"} {
+test if-3.4 {TclCompileIfCmd: error compiling body after "else"} -body {
set a {}
catch {if 2<1 {set a 1} else {set}} msg
- set errorInfo
-} {wrong # args: should be "set varName ?newValue?"
- while compiling
-"set"
- ("if" else script line 1)
- while compiling
-"if 2<1 {set a 1} else {set}"}
+ set ::errorInfo
+} -match glob -result {wrong # args: should be "set varName ?newValue?"
+ while *ing
+"set"*}
test if-3.5 {TclCompileIfCmd: extra arguments after "else" argument} {
set a {}
catch {if 2<1 {set a 1} else {set a 2} or something} msg
@@ -507,12 +495,10 @@ test if-5.2 {if cmd with computed command names: error in if/elseif test} {
set z if
list [catch {$z {[error "error in condition"]} foo} msg] $msg
} {1 {error in condition}}
-test if-5.3 {if cmd with computed command names: error in if/elseif test} {
+test if-5.3 {if cmd with computed command names: error in if/elseif test} -body {
set z if
- list [catch {$z {1+}} msg] $msg $errorInfo
-} {1 {syntax error in expression "1+": premature end of expression} {syntax error in expression "1+": premature end of expression
- while executing
-"$z {1+}"}}
+ list [catch {$z {1+}} msg] $msg $::errorInfo
+} -match glob -result {1 * {*"$z {1+}"}}
test if-5.4 {if cmd with computed command names: if/elseif test in braces} {
set z if
set a {}
@@ -550,12 +536,12 @@ test if-5.9 {if cmd with computed command names: missing "then" body} {
catch {$z 1<2 then} msg
set msg
} {wrong # args: no script following "then" argument}
-test if-5.10 {if cmd with computed command names: error in "then" body} {
+test if-5.10 {if cmd with computed command names: error in "then" body} -body {
set z if
set a {}
- list [catch {$z {$a!="xxx"} then {set}} msg] $msg $errorInfo
-} {1 {wrong # args: should be "set varName ?newValue?"} {wrong # args: should be "set varName ?newValue?"
- while compiling
+ list [catch {$z {$a!="xxx"} then {set}} msg] $msg $::errorInfo
+} -match glob -result {1 {wrong # args: should be "set varName ?newValue?"} {wrong # args: should be "set varName ?newValue?"
+ while *ing
"set"
invoked from within
"$z {$a!="xxx"} then {set}"}}
@@ -674,13 +660,11 @@ test if-6.3 {if cmd with computed command names: missing expression after "elsei
catch {$z 1<2 {set a 1} elseif} msg
set msg
} {wrong # args: no expression after "elseif" argument}
-test if-6.4 {if cmd with computed command names: error in expression after "elseif"} {
+test if-6.4 {if cmd with computed command names: error in expression after "elseif"} -body {
set z if
set a {}
- list [catch {$z 3>4 {set a 1} elseif {1>}} msg] $msg $errorInfo
-} {1 {syntax error in expression "1>": premature end of expression} {syntax error in expression "1>": premature end of expression
- while executing
-"$z 3>4 {set a 1} elseif {1>}"}}
+ list [catch {$z 3>4 {set a 1} elseif {1>}} msg] $msg $::errorInfo
+} -match glob -result {1 * {*"$z 3>4 {set a 1} elseif {1>}"}}
test if-6.5 {if cmd with computed command names: test jumpFalse instruction replacement after long "elseif" body} {
set z if
catch {unset i}
@@ -805,13 +789,13 @@ test if-7.3 {if cmd with computed command names: missing body after "else"} {
catch {$z 2<1 {set a 1} else} msg
set msg
} {wrong # args: no script following "else" argument}
-test if-7.4 {if cmd with computed command names: error compiling body after "else"} {
+test if-7.4 {if cmd with computed command names: error compiling body after "else"} -body {
set z if
set a {}
catch {$z 2<1 {set a 1} else {set}} msg
- set errorInfo
-} {wrong # args: should be "set varName ?newValue?"
- while compiling
+ set ::errorInfo
+} -match glob -result {wrong # args: should be "set varName ?newValue?"
+ while *ing
"set"
invoked from within
"$z 2<1 {set a 1} else {set}"}
@@ -1088,7 +1072,7 @@ test if-10.5 {substituted control words} {
set elseif elseif; proc elseif {} {return badelseif}
list [catch {if 1 $then {if 0 {} $elseif 1 {if 0 {} $else {list ok}}}} a] $a
} {0 ok}
-test if-10.6 {double invocation of variable traces} {
+test if-10.6 {double invocation of variable traces} -body {
set iftracecounter 0
proc iftraceproc {args} {
upvar #0 iftracecounter counter
@@ -1106,7 +1090,7 @@ test if-10.6 {double invocation of variable traces} {
list [catch {if "$iftracevar + 20" {}} a] $a \
[catch {if "$iftracevar + 20" {}} b] $b \
[unset iftracevar iftracecounter]
-} {1 {syntax error in expression "1 oops 10 + 20": extra tokens at end of expression} 0 {} {}}
+} -match glob -result {1 {*} 0 {} {}}
# cleanup
::tcltest::cleanupTests
diff --git a/tests/incr-old.test b/tests/incr-old.test
index 7068254..ed457cf 100644
--- a/tests/incr-old.test
+++ b/tests/incr-old.test
@@ -14,7 +14,7 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2
namespace import -force ::tcltest::*
}
@@ -45,31 +45,29 @@ test incr-old-2.2 {incr errors} {
} {1 {wrong # args: should be "incr varName ?increment?"}}
test incr-old-2.3 {incr errors} {
catch {unset x}
- list [catch {incr x} msg] $msg $errorInfo
-} {1 {can't read "x": no such variable} {can't read "x": no such variable
- (reading value of variable to increment)
- invoked from within
-"incr x"}}
+ incr x
+} 1
test incr-old-2.4 {incr errors} {
set x abc
- list [catch {incr x} msg] $msg $errorInfo
+ list [catch {incr x} msg] $msg $::errorInfo
} {1 {expected integer but got "abc"} {expected integer but got "abc"
while executing
"incr x"}}
test incr-old-2.5 {incr errors} {
set x 123
- list [catch {incr x 1a} msg] $msg $errorInfo
+ list [catch {incr x 1a} msg] $msg $::errorInfo
} {1 {expected integer but got "1a"} {expected integer but got "1a"
(reading increment)
invoked from within
"incr x 1a"}}
-test incr-old-2.6 {incr errors} {
+test incr-old-2.6 {incr errors} -body {
proc readonly args {error "variable is read-only"}
set x 123
trace var x w readonly
- list [catch {incr x 1} msg] $msg $errorInfo
-} {1 {can't set "x": variable is read-only} {can't set "x": variable is read-only
+ list [catch {incr x 1} msg] $msg $::errorInfo
+} -match glob -result {1 {can't set "x": variable is read-only} {*variable is read-only
while executing
+*
"incr x 1"}}
catch {unset x}
test incr-old-2.7 {incr errors} {
diff --git a/tests/incr.test b/tests/incr.test
index 7ed9824..253cb1d 100644
--- a/tests/incr.test
+++ b/tests/incr.test
@@ -11,7 +11,7 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2
namespace import -force ::tcltest::*
}
@@ -85,9 +85,8 @@ test incr-1.13 {TclCompileIncrCmd: simple but new (unknown) local name} {
proc p {} {
incr bar
}
- catch {p} msg
- set msg
-} {can't read "bar": no such variable}
+ p
+} 1
test incr-1.14 {TclCompileIncrCmd: simple local name, >255 locals} {
proc 260locals {} {
# create 260 locals
@@ -172,15 +171,13 @@ test incr-1.18 {TclCompileIncrCmd: increment given, simple int} {
set i 5
incr i -100
} -95
-test incr-1.19 {TclCompileIncrCmd: increment given, but erroneous} {
+test incr-1.19 {TclCompileIncrCmd: increment given, but erroneous} -body {
set i 5
catch {incr i [set]} msg
- set errorInfo
-} {wrong # args: should be "set varName ?newValue?"
- while compiling
-"set"
- while compiling
-"incr i [set]"}
+ set ::errorInfo
+} -match glob -result {wrong # args: should be "set varName ?newValue?"
+ while *ing
+"set"*}
test incr-1.20 {TclCompileIncrCmd: increment given, in quotes} {
set i 25
incr i "-100"
@@ -195,7 +192,7 @@ test incr-1.22 {TclCompileIncrCmd: increment given, large int} {
} 200005
test incr-1.23 {TclCompileIncrCmd: increment given, formatted int != int} {
set i 25
- incr i 000012345 ;# an octal literal
+ incr i 0o00012345 ;# an octal literal
} 5374
test incr-1.24 {TclCompileIncrCmd: increment given, formatted int != int} {
set i 25
@@ -211,25 +208,22 @@ test incr-1.25 {TclCompileIncrCmd: too many arguments} {
test incr-1.26 {TclCompileIncrCmd: runtime error, bad variable name} {
- list [catch {incr {"foo}} msg] $msg $errorInfo
-} {1 {can't read ""foo": no such variable} {can't read ""foo": no such variable
- (reading value of variable to increment)
- invoked from within
-"incr {"foo}"}}
-test incr-1.27 {TclCompileIncrCmd: runtime error, bad variable name} {
- list [catch {incr [set]} msg] $msg $errorInfo
-} {1 {wrong # args: should be "set varName ?newValue?"} {wrong # args: should be "set varName ?newValue?"
- while compiling
-"set"
- while compiling
-"incr [set]"}}
-test incr-1.28 {TclCompileIncrCmd: runtime error, readonly variable} {
+ unset -nocomplain {"foo}
+ incr {"foo}
+} 1
+test incr-1.27 {TclCompileIncrCmd: runtime error, bad variable name} -body {
+ list [catch {incr [set]} msg] $msg $::errorInfo
+} -match glob -result {1 {wrong # args: should be "set varName ?newValue?"} {wrong # args: should be "set varName ?newValue?"
+ while *ing
+"set"*}}
+test incr-1.28 {TclCompileIncrCmd: runtime error, readonly variable} -body {
proc readonly args {error "variable is read-only"}
set x 123
trace var x w readonly
- list [catch {incr x 1} msg] $msg $errorInfo
-} {1 {can't set "x": variable is read-only} {can't set "x": variable is read-only
+ list [catch {incr x 1} msg] $msg $::errorInfo
+} -match glob -result {1 {can't set "x": variable is read-only} {*variable is read-only
while executing
+*
"incr x 1"}}
catch {unset x}
test incr-1.29 {TclCompileIncrCmd: runtime error, bad variable value} {
@@ -332,9 +326,8 @@ test incr-2.13 {incr command (not compiled): simple but new (unknown) local name
set z incr
$z bar
}
- catch {p} msg
- set msg
-} {can't read "bar": no such variable}
+ p
+} 1
test incr-2.14 {incr command (not compiled): simple local name, >255 locals} {
proc 260locals {} {
set z incr
@@ -424,16 +417,14 @@ test incr-2.18 {incr command (not compiled): increment given, simple int} {
set i 5
$z i -100
} -95
-test incr-2.19 {incr command (not compiled): increment given, but erroneous} {
+test incr-2.19 {incr command (not compiled): increment given, but erroneous} -body {
set z incr
set i 5
catch {$z i [set]} msg
- set errorInfo
-} {wrong # args: should be "set varName ?newValue?"
- while compiling
-"set"
- while compiling
-"$z i [set]"}
+ set ::errorInfo
+} -match glob -result {wrong # args: should be "set varName ?newValue?"
+ while *ing
+"set"*}
test incr-2.20 {incr command (not compiled): increment given, in quotes} {
set z incr
set i 25
@@ -452,7 +443,7 @@ test incr-2.22 {incr command (not compiled): increment given, large int} {
test incr-2.23 {incr command (not compiled): increment given, formatted int != int} {
set z incr
set i 25
- $z i 000012345 ;# an octal literal
+ $z i 0o00012345 ;# an octal literal
} 5374
test incr-2.24 {incr command (not compiled): increment given, formatted int != int} {
set z incr
@@ -470,28 +461,25 @@ test incr-2.25 {incr command (not compiled): too many arguments} {
test incr-2.26 {incr command (not compiled): runtime error, bad variable name} {
+ unset -nocomplain {"foo}
set z incr
- list [catch {$z {"foo}} msg] $msg $errorInfo
-} {1 {can't read ""foo": no such variable} {can't read ""foo": no such variable
- (reading value of variable to increment)
- invoked from within
-"$z {"foo}"}}
-test incr-2.27 {incr command (not compiled): runtime error, bad variable name} {
+ $z {"foo}
+} 1
+test incr-2.27 {incr command (not compiled): runtime error, bad variable name} -body {
set z incr
- list [catch {$z [set]} msg] $msg $errorInfo
-} {1 {wrong # args: should be "set varName ?newValue?"} {wrong # args: should be "set varName ?newValue?"
- while compiling
-"set"
- while compiling
-"$z [set]"}}
-test incr-2.28 {incr command (not compiled): runtime error, readonly variable} {
+ list [catch {$z [set]} msg] $msg $::errorInfo
+} -match glob -result {1 {wrong # args: should be "set varName ?newValue?"} {wrong # args: should be "set varName ?newValue?"
+ while *ing
+"set"*}}
+test incr-2.28 {incr command (not compiled): runtime error, readonly variable} -body {
set z incr
proc readonly args {error "variable is read-only"}
set x 123
trace var x w readonly
- list [catch {$z x 1} msg] $msg $errorInfo
-} {1 {can't set "x": variable is read-only} {can't set "x": variable is read-only
+ list [catch {$z x 1} msg] $msg $::errorInfo
+} -match glob -result {1 {can't set "x": variable is read-only} {*variable is read-only
while executing
+*
"$z x 1"}}
catch {unset x}
test incr-2.29 {incr command (not compiled): runtime error, bad variable value} {
@@ -502,30 +490,35 @@ test incr-2.29 {incr command (not compiled): runtime error, bad variable value}
test incr-2.30 {incr command (not compiled): bad increment} {
set z incr
set x 0
- list [catch {$z x 1a} msg] $msg $errorInfo
+ list [catch {$z x 1a} msg] $msg $::errorInfo
} {1 {expected integer but got "1a"} {expected integer but got "1a"
(reading increment)
invoked from within
"$z x 1a"}}
test incr-2.31 {incr command (compiled): bad increment} {
- list [catch {incr x 1a} msg] $msg $errorInfo
+ list [catch {incr x 1a} msg] $msg $::errorInfo
} {1 {expected integer but got "1a"} {expected integer but got "1a"
(reading increment)
invoked from within
"incr x 1a"}}
+test incr-3.1 {increment by wide amount: bytecode route} {
+ set x 0
+ incr x 123123123123
+} 123123123123
+test incr-3.2 {increment by wide amount: command route} {
+ set z incr
+ set x 0
+ $z x 123123123123
+} 123123123123
+
+test incr-4.1 {increment non-existing array element [Bug 1445454]} -body {
+ proc x {} {incr a(1)}
+ x
+} -cleanup {
+ rename x {}
+} -result 1
+
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/indexObj.test b/tests/indexObj.test
index 414901f..bff20a2 100644
--- a/tests/indexObj.test
+++ b/tests/indexObj.test
@@ -13,66 +13,61 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-if {[info commands testindexobj] == {}} {
- puts "This application hasn't been compiled with the \"testindexobj\""
- puts "command, so I can't test Tcl_GetIndexFromObj etc."
- ::tcltest::cleanupTests
- return
-}
+testConstraint testindexobj [llength [info commands testindexobj]]
-test indexObj-1.1 {exact match} {
+test indexObj-1.1 {exact match} testindexobj {
testindexobj 1 1 xyz abc def xyz alm
} {2}
-test indexObj-1.2 {exact match} {
+test indexObj-1.2 {exact match} testindexobj {
testindexobj 1 1 abc abc def xyz alm
} {0}
-test indexObj-1.3 {exact match} {
+test indexObj-1.3 {exact match} testindexobj {
testindexobj 1 1 alm abc def xyz alm
} {3}
-test indexObj-1.4 {unique abbreviation} {
+test indexObj-1.4 {unique abbreviation} testindexobj {
testindexobj 1 1 xy abc def xalb xyz alm
} {3}
-test indexObj-1.5 {multiple abbreviations and exact match} {
+test indexObj-1.5 {multiple abbreviations and exact match} testindexobj {
testindexobj 1 1 x abc def xalb xyz alm x
} {5}
-test indexObj-1.6 {forced exact match} {
+test indexObj-1.6 {forced exact match} testindexobj {
testindexobj 1 0 xy abc def xalb xy alm
} {3}
-test indexObj-1.7 {forced exact match} {
+test indexObj-1.7 {forced exact match} testindexobj {
testindexobj 1 0 x abc def xalb xyz alm x
} {5}
-test indexObj-1.8 {exact match of empty values} {
+test indexObj-1.8 {exact match of empty values} testindexobj {
testindexobj 1 1 {} a aa aaa {} b bb bbb
} 3
-test indexObj-1.9 {exact match of empty values} {
+test indexObj-1.9 {exact match of empty values} testindexobj {
testindexobj 1 0 {} a aa aaa {} b bb bbb
} 3
-test indexObj-2.1 {no match} {
+test indexObj-2.1 {no match} testindexobj {
list [catch {testindexobj 1 1 dddd abc def xalb xyz alm x} msg] $msg
} {1 {bad token "dddd": must be abc, def, xalb, xyz, alm, or x}}
-test indexObj-2.2 {no match} {
+test indexObj-2.2 {no match} testindexobj {
list [catch {testindexobj 1 1 dddd abc} msg] $msg
} {1 {bad token "dddd": must be abc}}
-test indexObj-2.3 {no match: no abbreviations} {
+test indexObj-2.3 {no match: no abbreviations} testindexobj {
list [catch {testindexobj 1 0 xy abc def xalb xyz alm} msg] $msg
} {1 {bad token "xy": must be abc, def, xalb, xyz, or alm}}
-test indexObj-2.4 {ambiguous value} {
+test indexObj-2.4 {ambiguous value} testindexobj {
list [catch {testindexobj 1 1 d dumb daughter a c} msg] $msg
} {1 {ambiguous token "d": must be dumb, daughter, a, or c}}
-test indexObj-2.5 {omit error message} {
+test indexObj-2.5 {omit error message} testindexobj {
list [catch {testindexobj 0 1 d x} msg] $msg
} {1 {}}
-test indexObj-2.6 {TCL_EXACT => no "ambiguous" error message} {
+test indexObj-2.6 {TCL_EXACT => no "ambiguous" error message} testindexobj {
list [catch {testindexobj 1 0 d dumb daughter a c} msg] $msg
} {1 {bad token "d": must be dumb, daughter, a, or c}}
-test indexObj-2.7 {exact match of empty values} {
+test indexObj-2.7 {exact match of empty values} testindexobj {
list [catch {testindexobj 1 1 {} a b c} msg] $msg
} {1 {ambiguous token "": must be a, b, or c}}
-test indexObj-2.8 {exact match of empty values: singleton case} {
+test indexObj-2.8 {exact match of empty values: singleton case} testindexobj {
list [catch {testindexobj 1 0 {} a} msg] $msg
} {1 {bad token "": must be a}}
-test indexObj-2.9 {non-exact match of empty values: singleton case} {
+test indexObj-2.9 {non-exact match of empty values: singleton case} testindexobj {
# NOTE this is a special case. Although the empty string is a
# unique prefix, we have an established history of rejecting
# empty lookup keys, requiring any unique prefix match to have
@@ -80,32 +75,32 @@ test indexObj-2.9 {non-exact match of empty values: singleton case} {
list [catch {testindexobj 1 1 {} a} msg] $msg
} {1 {bad token "": must be a}}
-test indexObj-3.1 {cache result to skip next lookup} {
+test indexObj-3.1 {cache result to skip next lookup} testindexobj {
testindexobj check 42
} {42}
-test indexObj-4.1 {free old internal representation} {
+test indexObj-4.1 {free old internal representation} testindexobj {
set x {a b}
lindex $x 1
testindexobj 1 1 $x abc def {a b} zzz
} {2}
-test indexObj-5.1 {Tcl_WrongNumArgs} {
+test indexObj-5.1 {Tcl_WrongNumArgs} testindexobj {
testwrongnumargs 1 "?option?" mycmd
} "wrong # args: should be \"mycmd ?option?\""
-test indexObj-5.2 {Tcl_WrongNumArgs} {
+test indexObj-5.2 {Tcl_WrongNumArgs} testindexobj {
testwrongnumargs 2 "bar" mycmd foo
} "wrong # args: should be \"mycmd foo bar\""
-test indexObj-5.3 {Tcl_WrongNumArgs} {
+test indexObj-5.3 {Tcl_WrongNumArgs} testindexobj {
testwrongnumargs 0 "bar" mycmd foo
} "wrong # args: should be \"bar\""
-test indexObj-5.4 {Tcl_WrongNumArgs} {
+test indexObj-5.4 {Tcl_WrongNumArgs} testindexobj {
testwrongnumargs 0 "" mycmd foo
} "wrong # args: should be \"\""
-test indexObj-5.5 {Tcl_WrongNumArgs} {
+test indexObj-5.5 {Tcl_WrongNumArgs} testindexobj {
testwrongnumargs 1 "" mycmd foo
} "wrong # args: should be \"mycmd\""
-test indexObj-5.6 {Tcl_WrongNumArgs} {
+test indexObj-5.6 {Tcl_WrongNumArgs} testindexobj {
testwrongnumargs 2 "" mycmd foo
} "wrong # args: should be \"mycmd foo\""
# Contrast this with test proc-3.6; they have to be like this because
@@ -114,20 +109,20 @@ test indexObj-5.7 {Tcl_WrongNumArgs} testindexobj {
testwrongnumargs 2 "fee fi" "fo fum" foo bar
} "wrong # args: should be \"fo fum foo fee fi\""
-test indexObj-6.1 {Tcl_GetIndexFromObjStruct} {
+test indexObj-6.1 {Tcl_GetIndexFromObjStruct} testindexobj {
set x a
testgetindexfromobjstruct $x 0
} "wrong # args: should be \"testgetindexfromobjstruct a 0\""
-test indexObj-6.2 {Tcl_GetIndexFromObjStruct} {
+test indexObj-6.2 {Tcl_GetIndexFromObjStruct} testindexobj {
set x a
testgetindexfromobjstruct $x 0
testgetindexfromobjstruct $x 0
} "wrong # args: should be \"testgetindexfromobjstruct a 0\""
-test indexObj-6.3 {Tcl_GetIndexFromObjStruct} {
+test indexObj-6.3 {Tcl_GetIndexFromObjStruct} testindexobj {
set x c
testgetindexfromobjstruct $x 1
} "wrong # args: should be \"testgetindexfromobjstruct c 1\""
-test indexObj-6.4 {Tcl_GetIndexFromObjStruct} {
+test indexObj-6.4 {Tcl_GetIndexFromObjStruct} testindexobj {
set x c
testgetindexfromobjstruct $x 1
testgetindexfromobjstruct $x 1
@@ -136,3 +131,7 @@ test indexObj-6.4 {Tcl_GetIndexFromObjStruct} {
# cleanup
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/info.test b/tests/info.test
index 5816da3..937da8c 100644
--- a/tests/info.test
+++ b/tests/info.test
@@ -13,7 +13,7 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# DO NOT DELETE THIS LINE. Keep line numbers correct for testing 'info frame'.
+# DO NOT DELETE THIS LINE
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest 2
@@ -31,10 +31,6 @@ namespace eval test_ns_info1 {
proc q {{y 27} {z {}}} {return "y=$y"}
}
-testConstraint tip280 [info exists tcl_platform(tip,280)]
-testConstraint !tip280 [expr {![info exists tcl_platform(tip,280)]}]
-
-
test info-1.1 {info args option} {
proc t1 {a bbb c} {return foo}
info args t1
@@ -47,13 +43,13 @@ test info-1.3 {info args option} {
proc t1 "" {return foo}
info args t1
} {}
-test info-1.4 {info args option} {
+test info-1.4 {info args option} -body {
catch {rename t1 {}}
- list [catch {info args t1} msg] $msg
-} {1 {"t1" isn't a procedure}}
-test info-1.5 {info args option} {
- list [catch {info args set} msg] $msg
-} {1 {"set" isn't a procedure}}
+ info args t1
+} -returnCodes error -result {"t1" isn't a procedure}
+test info-1.5 {info args option} -body {
+ info args set
+} -returnCodes error -result {"set" isn't a procedure}
test info-1.6 {info args option} {
proc t1 {a b} {set c 123; set d $c}
t1 1 2
@@ -71,12 +67,12 @@ test info-2.1 {info body option} {
proc t1 {} {body of t1}
info body t1
} {body of t1}
-test info-2.2 {info body option} {
- list [catch {info body set} msg] $msg
-} {1 {"set" isn't a procedure}}
-test info-2.3 {info body option} {
- list [catch {info args set 1} msg] $msg
-} {1 {wrong # args: should be "info args procname"}}
+test info-2.2 {info body option} -body {
+ info body set
+} -returnCodes error -result {"set" isn't a procedure}
+test info-2.3 {info body option} -body {
+ info args set 1
+} -returnCodes error -result {wrong # args: should be "info args procname"}
test info-2.4 {info body option} {
catch {namespace delete test_ns_info2}
namespace eval test_ns_info2 {
@@ -108,10 +104,6 @@ test info-2.6 {info body option, returning list bodies} {
[foo; string bytelength [info body foo]]
} {9 9}
-# "info cmdcount" is no longer accurate for compiled commands!
-# The expected result for info-3.1 used to be "3" and is now "1"
-# since the "set"s have been compiled away. info-3.2 was corrected
-# in 8.3 because the eval'ed body won't be compiled.
proc testinfocmdcount {} {
set x [info cmdcount]
set y 12345
@@ -120,17 +112,17 @@ proc testinfocmdcount {} {
}
test info-3.1 {info cmdcount compiled} {
testinfocmdcount
-} 1
+} 4
test info-3.2 {info cmdcount evaled} {
set x [info cmdcount]
set y 12345
set z [info cm]
expr $z-$x
-} 3
-test info-3.3 {info cmdcount evaled} [info body testinfocmdcount] 3
-test info-3.4 {info cmdcount option} {
- list [catch {info cmdcount 1} msg] $msg
-} {1 {wrong # args: should be "info cmdcount"}}
+} 4
+test info-3.3 {info cmdcount evaled} [info body testinfocmdcount] 4
+test info-3.4 {info cmdcount option} -body {
+ info cmdcount 1
+} -returnCodes error -result {wrong # args: should be "info cmdcount"}
test info-4.1 {info commands option} {
proc t1 {} {}
@@ -157,13 +149,14 @@ test info-4.4 {info commands option} {
} {_t1_ _t2_}
catch {rename _t1_ {}}
catch {rename _t2_ {}}
-test info-4.5 {info commands option} {
- list [catch {info commands a b} msg] $msg
-} {1 {wrong # args: should be "info commands ?pattern?"}}
-
-test info-5.1 {info complete option} {
- list [catch {info complete} msg] $msg
-} {1 {wrong # args: should be "info complete command"}}
+test info-4.5 {info commands option} -returnCodes error -body {
+ info commands a b
+} -result {wrong # args: should be "info commands ?pattern?"}
+# Also some tests in namespace.test
+
+test info-5.1 {info complete option} -body {
+ info complete
+} -returnCodes error -result {wrong # args: should be "info complete command"}
test info-5.2 {info complete option} {
info complete abc
} 1
@@ -206,28 +199,30 @@ test info-6.5 {info default option} {
set x [info default t1 e value]
list $x $value
} {1 {long default value}}
-test info-6.6 {info default option} {
- list [catch {info default a b} msg] $msg
-} {1 {wrong # args: should be "info default procname arg varname"}}
-test info-6.7 {info default option} {
- list [catch {info default _nonexistent_ a b} msg] $msg
-} {1 {"_nonexistent_" isn't a procedure}}
-test info-6.8 {info default option} {
+test info-6.6 {info default option} -returnCodes error -body {
+ info default a b
+} -result {wrong # args: should be "info default procname arg varname"}
+test info-6.7 {info default option} -returnCodes error -body {
+ info default _nonexistent_ a b
+} -result {"_nonexistent_" isn't a procedure}
+test info-6.8 {info default option} -returnCodes error -body {
proc t1 {a b} {}
- list [catch {info default t1 x value} msg] $msg
-} {1 {procedure "t1" doesn't have an argument "x"}}
-test info-6.9 {info default option} {
+ info default t1 x value
+} -result {procedure "t1" doesn't have an argument "x"}
+test info-6.9 {info default option} -returnCodes error -setup {
catch {unset a}
+} -body {
set a(0) 88
proc t1 {a b} {}
- list [catch {info default t1 a a} msg] $msg
-} {1 {couldn't store default value in variable "a"}}
-test info-6.10 {info default option} {
+ info default t1 a a
+} -returnCodes error -result {couldn't store default value in variable "a"}
+test info-6.10 {info default option} -setup {
catch {unset a}
+} -body {
set a(0) 88
proc t1 {{a 18} b} {}
- list [catch {info default t1 a a} msg] $msg
-} {1 {couldn't store default value in variable "a"}}
+ info default t1 a a
+} -returnCodes error -result {couldn't store default value in variable "a"}
test info-6.11 {info default option} {
catch {namespace delete test_ns_info2}
namespace eval test_ns_info2 {
@@ -267,18 +262,19 @@ test info-7.6 {info exists option} {
proc t1 {x} {return [info exists value]}
t1 2
} 0
-test info-7.7 {info exists option} {
+test info-7.7 {info exists option} -setup {
catch {unset x}
+} -body {
set x(2) 44
list [info exists x] [info exists x(1)] [info exists x(2)]
-} {1 0 1}
+} -result {1 0 1}
catch {unset x}
-test info-7.8 {info exists option} {
- list [catch {info exists} msg] $msg
-} {1 {wrong # args: should be "info exists varName"}}
-test info-7.9 {info exists option} {
- list [catch {info exists 1 2} msg] $msg
-} {1 {wrong # args: should be "info exists varName"}}
+test info-7.8 {info exists option} -body {
+ info exists
+} -returnCodes error -result {wrong # args: should be "info exists varName"}
+test info-7.9 {info exists option} -body {
+ info exists 1 2
+} -returnCodes error -result {wrong # args: should be "info exists varName"}
test info-8.1 {info globals option} {
set x 1
@@ -293,9 +289,9 @@ test info-8.2 {info globals option} {
set _xxx2 2
lsort [info g _xxx*]
} {_xxx1 _xxx2}
-test info-8.3 {info globals option} {
- list [catch {info globals 1 2} msg] $msg
-} {1 {wrong # args: should be "info globals ?pattern?"}}
+test info-8.3 {info globals option} -returnCodes error -body {
+ info globals 1 2
+} -result {wrong # args: should be "info globals ?pattern?"}
test info-8.4 {info globals option: may have leading namespace qualifiers} {
set x 0
list [info globals x] [info globals :x] [info globals ::x] [info globals :::x] [info globals ::::x]
@@ -343,46 +339,64 @@ test info-9.4 {info level option} {
}
t1
} {1 t1}
-test info-9.5 {info level option} {
- list [catch {info level 1 2} msg] $msg
-} {1 {wrong # args: should be "info level ?number?"}}
-test info-9.6 {info level option} {
- list [catch {info level 123a} msg] $msg
-} {1 {expected integer but got "123a"}}
-test info-9.7 {info level option} {
- list [catch {info level 0} msg] $msg
-} {1 {bad level "0"}}
-test info-9.8 {info level option} {
+test info-9.5 {info level option} -body {
+ info level 1 2
+} -returnCodes error -result {wrong # args: should be "info level ?number?"}
+test info-9.6 {info level option} -body {
+ info level 123a
+} -returnCodes error -result {expected integer but got "123a"}
+test info-9.7 {info level option} -body {
+ info level 0
+} -returnCodes error -result {bad level "0"}
+test info-9.8 {info level option} -body {
proc t1 {} {info level -1}
- list [catch {t1} msg] $msg
-} {1 {bad level "-1"}}
-test info-9.9 {info level option} {
+ t1
+} -returnCodes error -result {bad level "-1"}
+test info-9.9 {info level option} -body {
proc t1 {x} {info level $x}
- list [catch {t1 -3} msg] $msg
-} {1 {bad level "-3"}}
+ t1 -3
+} -returnCodes error -result {bad level "-3"}
test info-9.10 {info level option, namespaces} {
set msg [namespace eval t {info level 0}]
namespace delete t
set msg
} {namespace eval t {info level 0}}
+test info-9.11 {info level option, aliases} -constraints knownBug -setup {
+ proc w {x y z} {info level 0}
+ interp alias {} a {} w a b
+} -body {
+ a c
+} -cleanup {
+ rename a {}
+ rename w {}
+} -result {a c}
+test info-9.12 {info level option, ensembles} -constraints knownBug -setup {
+ proc w {x y z} {info level 0}
+ namespace ensemble create -command a -map {foo ::w}
+} -body {
+ a foo 1 2 3
+} -cleanup {
+ rename a {}
+ rename w {}
+} -result {a foo 1 2 3}
set savedLibrary $tcl_library
-test info-10.1 {info library option} {
- list [catch {info library x} msg] $msg
-} {1 {wrong # args: should be "info library"}}
+test info-10.1 {info library option} -body {
+ info library x
+} -returnCodes error -result {wrong # args: should be "info library"}
test info-10.2 {info library option} {
set tcl_library 12345
info library
} {12345}
-test info-10.3 {info library option} {
+test info-10.3 {info library option} -body {
unset tcl_library
- list [catch {info library} msg] $msg
-} {1 {no library has been specified for Tcl}}
+ info library
+} -returnCodes error -result {no library has been specified for Tcl}
set tcl_library $savedLibrary
-test info-11.1 {info loaded option} {
- list [catch {info loaded a b} msg] $msg
-} {1 {wrong # args: should be "info loaded ?interp?"}}
+test info-11.1 {info loaded option} -body {
+ info loaded a b
+} -returnCodes error -result {wrong # args: should be "info loaded ?interp?"}
test info-11.2 {info loaded option} {
list [catch {info loaded {}}] [catch {info loaded gorp} msg] $msg
} {0 1 {could not find interpreter "gorp"}}
@@ -408,9 +422,9 @@ test info-12.2 {info locals option} {
}
lsort [t1 2 3]
} {x xx1 xx2}
-test info-12.3 {info locals option} {
- list [catch {info locals 1 2} msg] $msg
-} {1 {wrong # args: should be "info locals ?pattern?"}}
+test info-12.3 {info locals option} -body {
+ info locals 1 2
+} -returnCodes error -result {wrong # args: should be "info locals ?pattern?"}
test info-12.4 {info locals option} {
info locals
} {}
@@ -434,24 +448,25 @@ test info-12.7 {info locals with temporary variables} {
t1
} {a}
-test info-13.1 {info nameofexecutable option} {
- list [catch {info nameofexecutable foo} msg] $msg
-} {1 {wrong # args: should be "info nameofexecutable"}}
+test info-13.1 {info nameofexecutable option} -returnCodes error -body {
+ info nameofexecutable foo
+} -result {wrong # args: should be "info nameofexecutable"}
test info-14.1 {info patchlevel option} {
set a [info patchlevel]
regexp {[0-9]+\.[0-9]+([p[0-9]+)?} $a
} 1
-test info-14.2 {info patchlevel option} {
- list [catch {info patchlevel a} msg] $msg
-} {1 {wrong # args: should be "info patchlevel"}}
-test info-14.3 {info patchlevel option} {
+test info-14.2 {info patchlevel option} -returnCodes error -body {
+ info patchlevel a
+} -result {wrong # args: should be "info patchlevel"}
+test info-14.3 {info patchlevel option} -setup {
set t $tcl_patchLevel
+} -body {
unset tcl_patchLevel
- set result [list [catch {info patchlevel} msg] $msg]
+ info patchlevel
+} -cleanup {
set tcl_patchLevel $t
- set result
-} {1 {can't read "tcl_patchLevel": no such variable}}
+} -returnCodes error -result {can't read "tcl_patchLevel": no such variable}
test info-15.1 {info procs option} {
proc t1 {} {}
@@ -467,19 +482,21 @@ test info-15.2 {info procs option} {
} {_tt1 _tt2}
catch {rename _tt1 {}}
catch {rename _tt2 {}}
-test info-15.3 {info procs option} {
- list [catch {info procs 2 3} msg] $msg
-} {1 {wrong # args: should be "info procs ?pattern?"}}
-test info-15.4 {info procs option} {
+test info-15.3 {info procs option} -body {
+ info procs 2 3
+} -returnCodes error -result {wrong # args: should be "info procs ?pattern?"}
+test info-15.4 {info procs option} -setup {
catch {namespace delete test_ns_info2}
+} -body {
namespace eval test_ns_info2 {
namespace import ::test_ns_info1::*
proc r {} {}
list [info procs] [info procs p*]
}
-} {{p q r} p}
-test info-15.5 {info procs option with a proc in a namespace} {
+} -result {{p q r} p}
+test info-15.5 {info procs option with a proc in a namespace} -setup {
catch {namespace delete test_ns_info2}
+} -body {
namespace eval test_ns_info2 {
proc p1 { arg } {
puts cmd
@@ -489,9 +506,10 @@ test info-15.5 {info procs option with a proc in a namespace} {
}
}
info procs ::test_ns_info2::p1
-} {::test_ns_info2::p1}
-test info-15.6 {info procs option with a pattern in a namespace} {
+} -result {::test_ns_info2::p1}
+test info-15.6 {info procs option with a pattern in a namespace} -setup {
catch {namespace delete test_ns_info2}
+} -body {
namespace eval test_ns_info2 {
proc p1 { arg } {
puts cmd
@@ -501,9 +519,10 @@ test info-15.6 {info procs option with a pattern in a namespace} {
}
}
lsort [info procs ::test_ns_info2::p*]
-} [lsort [list ::test_ns_info2::p1 ::test_ns_info2::p2]]
-test info-15.7 {info procs option with a global shadowing proc} {
+} -result [lsort [list ::test_ns_info2::p1 ::test_ns_info2::p2]]
+test info-15.7 {info procs option with a global shadowing proc} -setup {
catch {namespace delete test_ns_info2}
+} -body {
proc string_cmd { arg } {
puts cmd
}
@@ -513,13 +532,13 @@ test info-15.7 {info procs option with a global shadowing proc} {
}
}
info procs test_ns_info2::string*
-} {::test_ns_info2::string_cmd}
+} -result {::test_ns_info2::string_cmd}
# This regression test is currently commented out because it requires
# that the implementation of "info procs" looks into the global namespace,
# which it does not (in contrast to "info commands")
-if {0} {
-test info-15.8 {info procs option with a global shadowing proc} {
+test info-15.8 {info procs option with a global shadowing proc} -setup {
catch {namespace delete test_ns_info2}
+} -constraints knownBug -body {
proc string_cmd { arg } {
puts cmd
}
@@ -534,12 +553,11 @@ test info-15.8 {info procs option with a global shadowing proc} {
namespace eval test_ns_info2 {
lsort [info procs string*]
}
-} [lsort [list string_cmd string_cmd2]]
-}
+} -result [lsort [list string_cmd string_cmd2]]
-test info-16.1 {info script option} {
- list [catch {info script x x} msg] $msg
-} {1 {wrong # args: should be "info script ?filename?"}}
+test info-16.1 {info script option} -returnCodes error -body {
+ info script x x
+} -result {wrong # args: should be "info script ?filename?"}
test info-16.2 {info script option} {
file tail [info sc]
} "info.test"
@@ -574,24 +592,24 @@ test info-16.8 {info script option} {
} [list [list $gorpfile foo.bar] info.test]
removeFile gorp.info
-test info-17.1 {info sharedlibextension option} {
- list [catch {info sharedlibextension foo} msg] $msg
-} {1 {wrong # args: should be "info sharedlibextension"}}
+test info-17.1 {info sharedlibextension option} -returnCodes error -body {
+ info sharedlibextension foo
+} -result {wrong # args: should be "info sharedlibextension"}
test info-18.1 {info tclversion option} {
- set x [info tclversion]
- scan $x "%d.%d%c" a b c
+ scan [info tclversion] "%d.%d%c" a b c
} 2
-test info-18.2 {info tclversion option} {
- list [catch {info t 2} msg] $msg
-} {1 {wrong # args: should be "info tclversion"}}
-test info-18.3 {info tclversion option} {
- set t $tcl_version
+test info-18.2 {info tclversion option} -body {
+ info t 2
+} -returnCodes error -result {wrong # args: should be "info tclversion"}
+test info-18.3 {info tclversion option} -body {
unset tcl_version
- set result [list [catch {info tclversion} msg] $msg]
+ info tclversion
+} -returnCodes error -setup {
+ set t $tcl_version
+} -cleanup {
set tcl_version $t
- set result
-} {1 {can't read "tcl_version": no such variable}}
+} -result {can't read "tcl_version": no such variable}
test info-19.1 {info vars option} {
set a 1
@@ -616,9 +634,9 @@ test info-19.2 {info vars option} {
test info-19.3 {info vars option} {
lsort [info vars]
} [lsort [info globals]]
-test info-19.4 {info vars option} {
- list [catch {info vars a b} msg] $msg
-} {1 {wrong # args: should be "info vars ?pattern?"}}
+test info-19.4 {info vars option} -returnCodes error -body {
+ info vars a b
+} -result {wrong # args: should be "info vars ?pattern?"}
test info-19.5 {info vars with temporary variables} {
proc t1 {} {
foreach a {b c} {}
@@ -635,11 +653,10 @@ test info-19.6 {info vars: Bug 1072654} -setup {
namespace delete x
} -result {}
+set functions {abs acos asin atan atan2 bool ceil cos cosh double entier exp floor fmod hypot int isqrt log log10 max min pow rand round sin sinh sqrt srand tan tanh wide}
# Check whether the extra testing functions are defined...
-if {([catch {expr T1()} msg] == 1) && ($msg == {unknown math function "T1"})} {
- set functions {abs acos asin atan atan2 ceil cos cosh double exp floor fmod hypot int log log10 pow rand round sin sinh sqrt srand tan tanh wide}
-} else {
- set functions {T1 T2 T3 abs acos asin atan atan2 ceil cos cosh double exp floor fmod hypot int log log10 pow rand round sin sinh sqrt srand tan tanh wide}
+if {!([catch {expr T1()} msg] && ($msg eq {invalid command name "tcl::mathfunc::T1"}))} {
+ set functions "T1 T2 T3 $functions" ;# A lazy way of prepending!
}
test info-20.1 {info functions option} {info functions sin} sin
test info-20.2 {info functions option} {lsort [info functions]} $functions
@@ -649,42 +666,29 @@ test info-20.3 {info functions option} {
test info-20.4 {info functions option} {
lsort [info functions *tan*]
} {atan atan2 tan tanh}
-test info-20.5 {info functions option} {
- list [catch {info functions raise an error} msg] $msg
-} {1 {wrong # args: should be "info functions ?pattern?"}}
-
-test info-21.1 {miscellaneous error conditions} {
- list [catch {info} msg] $msg
-} {1 {wrong # args: should be "info option ?arg arg ...?"}}
-test info-21.2 {miscellaneous error conditions} !tip280 {
- list [catch {info gorp} msg] $msg
-} {1 {bad option "gorp": must be args, body, cmdcount, commands, complete, default, exists, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, patchlevel, procs, script, sharedlibextension, tclversion, or vars}}
-test info-21.2-280 {miscellaneous error conditions} tip280 {
- list [catch {info gorp} msg] $msg
-} {1 {bad option "gorp": must be args, body, cmdcount, commands, complete, default, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, patchlevel, procs, script, sharedlibextension, tclversion, or vars}}
-test info-21.3 {miscellaneous error conditions} !tip280 {
- list [catch {info c} msg] $msg
-} {1 {ambiguous option "c": must be args, body, cmdcount, commands, complete, default, exists, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, patchlevel, procs, script, sharedlibextension, tclversion, or vars}}
-test info-21.3-280 {miscellaneous error conditions} tip280 {
- list [catch {info c} msg] $msg
-} {1 {ambiguous option "c": must be args, body, cmdcount, commands, complete, default, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, patchlevel, procs, script, sharedlibextension, tclversion, or vars}}
-test info-21.4 {miscellaneous error conditions} !tip280 {
- list [catch {info l} msg] $msg
-} {1 {ambiguous option "l": must be args, body, cmdcount, commands, complete, default, exists, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, patchlevel, procs, script, sharedlibextension, tclversion, or vars}}
-test info-21.4-280 {miscellaneous error conditions} tip280 {
- list [catch {info l} msg] $msg
-} {1 {ambiguous option "l": must be args, body, cmdcount, commands, complete, default, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, patchlevel, procs, script, sharedlibextension, tclversion, or vars}}
-test info-21.5 {miscellaneous error conditions} !tip280 {
- list [catch {info s} msg] $msg
-} {1 {ambiguous option "s": must be args, body, cmdcount, commands, complete, default, exists, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, patchlevel, procs, script, sharedlibextension, tclversion, or vars}}
-test info-21.5-280 {miscellaneous error conditions} tip280 {
- list [catch {info s} msg] $msg
-} {1 {ambiguous option "s": must be args, body, cmdcount, commands, complete, default, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, patchlevel, procs, script, sharedlibextension, tclversion, or vars}}
+test info-20.5 {info functions option} -returnCodes error -body {
+ info functions raise an error
+} -result {wrong # args: should be "info functions ?pattern?"}
+
+test info-21.1 {miscellaneous error conditions} -returnCodes error -body {
+ info
+} -result {wrong # args: should be "info subcommand ?argument ...?"}
+test info-21.2 {miscellaneous error conditions} -returnCodes error -body {
+ info gorp
+} -result {unknown or ambiguous subcommand "gorp": must be args, body, cmdcount, commands, complete, default, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
+test info-21.3 {miscellaneous error conditions} -returnCodes error -body {
+ info c
+} -result {unknown or ambiguous subcommand "c": must be args, body, cmdcount, commands, complete, default, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
+test info-21.4 {miscellaneous error conditions} -returnCodes error -body {
+ info l
+} -result {unknown or ambiguous subcommand "l": must be args, body, cmdcount, commands, complete, default, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
+test info-21.5 {miscellaneous error conditions} -returnCodes error -body {
+ info s
+} -result {unknown or ambiguous subcommand "s": must be args, body, cmdcount, commands, complete, default, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
##
# ### ### ### ######### ######### #########
## info frame
-
## Helper
# For the more complex results we cut the file name down to remove
# path dependencies, and we use only part of the first line of the
@@ -692,13 +696,12 @@ test info-21.5-280 {miscellaneous error conditions} tip280 {
# test case may appear in some results, but the result is part of the
# testcase. An infinite string would be required to describe that. The
# cutting-down breaks this.
-
proc reduce {frame} {
- set pos [lsearch -exact $frame cmd]
+ set pos [lsearch -exact $frame cmd]
incr pos
- set cmd [lindex $frame $pos]
+ set cmd [lindex $frame $pos]
if {[regexp \n $cmd]} {
- set first [lindex [split $cmd \n] 0] ; set first [expr {[string length $first] > 11 ? [string range $first 0 end-11] : [string range $first 0 end-4]}]
+ set first [string range [lindex [split $cmd \n] 0] 0 end-4]
set frame [lreplace $frame $pos $pos $first]
}
set pos [lsearch -exact $frame file]
@@ -709,7 +712,9 @@ proc reduce {frame} {
}
set frame
}
-
+proc subinterp {} { interp create sub ; interp debug sub -frame 1;
+ interp eval sub [list proc reduce [info args reduce] [info body reduce]]
+}
## Helper
# Generate a stacktrace from the current location to top. This code
# not only depends on the exact location of things, but also on the
@@ -728,114 +733,81 @@ proc etrace {} {
##
-test info-22.0.0 {info frame, levels} {tip280 && !singleTestInterp} {
+test info-22.0 {info frame, levels} {!singleTestInterp} {
info frame
} 7
-test info-22.0.1 {info frame, levels} {tip280 && singleTestInterp} {
- info frame
-} 10
-
-test info-22.1.0 {info frame, bad level relative} {tip280 && !singleTestInterp} {
+test info-22.1 {info frame, bad level relative} {!singleTestInterp} {
# catch is another level!, i.e. we have 8, not 7
catch {info frame -8} msg
set msg
} {bad level "-8"}
-test info-22.1.1 {info frame, bad level relative} {tip280 && singleTestInterp} {
- # catch is another level!, i.e. we have 11, not 10
- catch {info frame -11} msg
- set msg
-} {bad level "-11"}
-
-test info-22.2.0 {info frame, bad level absolute} {tip280 && !singleTestInterp} {
+test info-22.2 {info frame, bad level absolute} {!singleTestInterp} {
# catch is another level!, i.e. we have 8, not 7
catch {info frame 9} msg
set msg
} {bad level "9"}
-test info-22.2.1 {info frame, bad level absolute} {tip280 && singleTestInterp} {
- # catch is another level!, i.e. we have 12, not 10
- catch {info frame 12} msg
- set msg
-} {bad level "12"}
-
-test info-22.3 {info frame, current, relative} -constraints tip280 -match glob -body {
+test info-22.3 {info frame, current, relative} -match glob -body {
info frame 0
-} -result {type source line 761 file * cmd {info frame 0} proc ::tcltest::RunTest}
-
-test info-22.4 {info frame, current, relative, nested} -constraints tip280 -match glob -body {
+} -result {type source line 750 file * cmd {info frame 0} proc ::tcltest::RunTest}
+test info-22.4 {info frame, current, relative, nested} -match glob -body {
set res [info frame 0]
-} -result {type source line 765 file * cmd {info frame 0} proc ::tcltest::RunTest}
-
-test info-22.5.0 {info frame, current, absolute} -constraints {tip280 && !singleTestInterp} -match glob -body {
+} -result {type source line 753 file * cmd {info frame 0} proc ::tcltest::RunTest}
+test info-22.5 {info frame, current, absolute} -constraints {!singleTestInterp} -match glob -body {
reduce [info frame 7]
-} -result {type source line 769 file * cmd {info frame 7} proc ::tcltest::RunTest}
-test info-22.5.1 {info frame, current, absolute} -constraints {tip280 && singleTestInterp} -match glob -body {
- reduce [info frame 10]
-} -result {type source line 772 file * cmd {info frame 10} proc ::tcltest::RunTest}
-
-test info-22.6.0 {info frame, global, relative} {tip280 && !singleTestInterp} {
- reduce [info frame -6]
-} {type source line 775 file info.test cmd test\ info-22.6.0\ \{info\ frame,\ global,\ relative\}\ \{tip280\ &&\ !singleTe}
-test info-22.6.1 {info frame, global, relative} {tip280 && singleTestInterp} {
+} -result {type source line 756 file * cmd {info frame 7} proc ::tcltest::RunTest}
+test info-22.6 {info frame, global, relative} {!singleTestInterp} {
reduce [info frame -6]
-} {type source line 778 file info.test cmd test\ info-22.6.1\ \{info\ frame,\ global,\ relative\}\ \{tip280\ &&\ singleTe proc ::tcltest::runAllTests}
-
-test info-22.7.0 {info frame, global, absolute} {tip280 && !singleTestInterp} {
+} {type source line 758 file info.test cmd test\ info-22.6\ \{info\ frame,\ global,\ relative\}\ \{!singleTestInter level 0}
+test info-22.7 {info frame, global, absolute} {!singleTestInterp} {
reduce [info frame 1]
-} {type source line 782 file info.test cmd test\ info-22.7.0\ \{info\ frame,\ global,\ absolute\}\ \{tip280\ &&\ !singleTe}
-test info-22.7.1 {info frame, global, absolute} {tip280 && singleTestInterp} {
- reduce [info frame 4]
-} {type source line 785 file info.test cmd test\ info-22.7.1\ \{info\ frame,\ global,\ absolute\}\ \{tip280\ &&\ singleTe proc ::tcltest::runAllTests}
+} {type source line 761 file info.test cmd test\ info-22.7\ \{info\ frame,\ global,\ absolute\}\ \{!singleTestInter level 0}
+test info-22.8 {info frame, basic trace} -constraints {!singleTestInterp} -match glob -body {
+ join [lrange [etrace] 0 2] \n
+} -result {* {type source line 728 file info.test cmd {info frame $level} proc ::etrace level 0}
+* {type source line 765 file info.test cmd etrace proc ::tcltest::RunTest}
+* {type source line * file tcltest* cmd {uplevel 1 $script} proc ::tcltest::RunTest}}
+
+
+
+
-test info-22.8 {info frame, basic trace} -constraints {tip280} -match glob -body {
- join [lrange [etrace] 0 1] \n
-} -result {* {type source line 723 file info.test cmd {info frame $level} proc ::etrace level 0}
-* {type source line 790 file info.test cmd etrace proc ::tcltest::RunTest}}
-test info-23.0.0 {eval'd info frame} {tip280 && !singleTestInterp} {
+## The line 1967 is off by 5 from the true value of 1972. This is a knownBug, see testcase 30.0
+test info-23.0 {eval'd info frame} {!singleTestInterp} {
eval {info frame}
} 8
-test info-23.0.1 {eval'd info frame} {tip280 && singleTestInterp} {
- eval {info frame}
-} 11
-
-test info-23.1.0 {eval'd info frame, semi-dynamic} {tip280 && !singleTestInterp} {
+test info-23.1 {eval'd info frame, semi-dynamic} {!singleTestInterp} {
eval info frame
} 8
-test info-23.1.1 {eval'd info frame, semi-dynamic} {tip280 && singleTestInterp} {
- eval info frame
-} 11
-
-test info-23.2.0 {eval'd info frame, dynamic} {tip280 && !singleTestInterp} {
+test info-23.2 {eval'd info frame, dynamic} {!singleTestInterp} {
set script {info frame}
eval $script
} 8
-test info-23.2.1 {eval'd info frame, dynamic} {tip280 && singleTestInterp} {
- set script {info frame}
- eval $script
-} 11
-
-test info-23.3 {eval'd info frame, literal} -constraints tip280 -match glob -body {
+test info-23.3 {eval'd info frame, literal} -match glob -body {
eval {
info frame 0
}
-} -result {type source line 819 file *info.test cmd {info frame 0} proc ::tcltest::RunTest}
-
-test info-23.4 {eval'd info frame, semi-dynamic} tip280 {
+} -result {type source line 788 file * cmd {info frame 0} proc ::tcltest::RunTest}
+test info-23.4 {eval'd info frame, semi-dynamic} {
eval info frame 0
} {type eval line 1 cmd {info frame 0} proc ::tcltest::RunTest}
-
-test info-23.5 {eval'd info frame, dynamic} tip280 {
+test info-23.5 {eval'd info frame, dynamic} {
set script {info frame 0}
eval $script
} {type eval line 1 cmd {info frame 0} proc ::tcltest::RunTest}
-
-test info-23.6 {eval'd info frame, trace} -constraints {tip280} -match glob -body {
+test info-23.6 {eval'd info frame, trace} -constraints {!singleTestInterp} -match glob -body {
set script {etrace}
join [lrange [eval $script] 0 2] \n
-} -result {* {type source line 723 file info.test cmd {info frame $level} proc ::etrace level 0}
+} -result {* {type source line 728 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type eval line 1 cmd etrace proc ::tcltest::RunTest}
-* {type source line 834 file info.test cmd {eval $script} proc ::tcltest::RunTest}}
+* {type source line 800 file info.test cmd {eval $script} proc ::tcltest::RunTest}}
+
+
+
+
+
+## The line 1967 is off by 5 from the true value of 1972. This is a knownBug, see testcase 30.0
# -------------------------------------------------------------------------
# Procedures defined in scripts which are arguments to control
@@ -846,17 +818,19 @@ test info-23.6 {eval'd info frame, trace} -constraints {tip280} -match glob -bod
# causes the connection to the context to be lost. Currently only
# procedure bodies are able to remember their context.
+# NOTE THAT THESE DO NOT USE THE -setup OPTION TO [test]
+
# -------------------------------------------------------------------------
namespace eval foo {
proc bar {} {info frame 0}
}
-test info-24.0 {info frame, interaction, namespace eval} tip280 {
+test info-24.0 {info frame, interaction, namespace eval} -body {
reduce [foo::bar]
-} {type source line 852 file info.test cmd {info frame 0} proc ::foo::bar level 0}
-
-namespace delete foo
+} -cleanup {
+ namespace delete foo
+} -result {type source line 826 file info.test cmd {info frame 0} proc ::foo::bar level 0}
# -------------------------------------------------------------------------
@@ -866,11 +840,11 @@ if {$flag} {
proc ::foo::bar {} {info frame 0}
}
-test info-24.1 {info frame, interaction, if} tip280 {
+test info-24.1 {info frame, interaction, if} -body {
reduce [foo::bar]
-} {type source line 866 file info.test cmd {info frame 0} proc ::foo::bar level 0}
-
-namespace delete foo
+} -cleanup {
+ namespace delete foo
+} -result {type source line 840 file info.test cmd {info frame 0} proc ::foo::bar level 0}
# -------------------------------------------------------------------------
@@ -881,11 +855,11 @@ while {$flag} {
set flag 0
}
-test info-24.2 {info frame, interaction, while} tip280 {
+test info-24.2 {info frame, interaction, while} -body {
reduce [foo::bar]
-} {type source line 880 file info.test cmd {info frame 0} proc ::foo::bar level 0}
-
-namespace delete foo
+} -cleanup {
+ namespace delete foo
+} -result {type source line 854 file info.test cmd {info frame 0} proc ::foo::bar level 0}
# -------------------------------------------------------------------------
@@ -894,11 +868,11 @@ catch {
proc ::foo::bar {} {info frame 0}
}
-test info-24.3 {info frame, interaction, catch} tip280 {
+test info-24.3 {info frame, interaction, catch} -body {
reduce [foo::bar]
-} {type source line 894 file info.test cmd {info frame 0} proc ::foo::bar level 0}
-
-namespace delete foo
+} -cleanup {
+ namespace delete foo
+} -result {type source line 868 file info.test cmd {info frame 0} proc ::foo::bar level 0}
# -------------------------------------------------------------------------
@@ -908,11 +882,11 @@ foreach var val {
break
}
-test info-24.4 {info frame, interaction, foreach} tip280 {
+test info-24.4 {info frame, interaction, foreach} -body {
reduce [foo::bar]
-} {type source line 907 file info.test cmd {info frame 0} proc ::foo::bar level 0}
-
-namespace delete foo
+} -cleanup {
+ namespace delete foo
+} -result {type source line 881 file info.test cmd {info frame 0} proc ::foo::bar level 0}
# -------------------------------------------------------------------------
@@ -922,11 +896,101 @@ for {} {1} {} {
break
}
-test info-24.5 {info frame, interaction, for} tip280 {
+test info-24.5 {info frame, interaction, for} -body {
+ reduce [foo::bar]
+} -cleanup {
+ namespace delete foo
+} -result {type source line 895 file info.test cmd {info frame 0} proc ::foo::bar level 0}
+
+# -------------------------------------------------------------------------
+
+namespace eval foo {}
+set x foo
+switch -exact -- $x {
+ foo {
+ proc ::foo::bar {} {info frame 0}
+ }
+}
+
+test info-24.6.0 {info frame, interaction, switch, list body} -body {
+ reduce [foo::bar]
+} -cleanup {
+ namespace delete foo
+ unset x
+} -result {type source line 911 file info.test cmd {info frame 0} proc ::foo::bar level 0}
+
+# -------------------------------------------------------------------------
+
+namespace eval foo {}
+set x foo
+switch -exact -- $x foo {
+ proc ::foo::bar {} {info frame 0}
+}
+
+test info-24.6.1 {info frame, interaction, switch, multi-body} -body {
+ reduce [foo::bar]
+} -cleanup {
+ namespace delete foo
+ unset x
+} -result {type source line 927 file info.test cmd {info frame 0} proc ::foo::bar level 0}
+
+# -------------------------------------------------------------------------
+
+namespace eval foo {}
+set x foo
+switch -exact -- $x [list foo {
+ proc ::foo::bar {} {info frame 0}
+}]
+
+test info-24.6.2 {info frame, interaction, switch, list body, dynamic} -body {
reduce [foo::bar]
-} {type source line 921 file info.test cmd {info frame 0} proc ::foo::bar level 0}
+} -cleanup {
+ namespace delete foo
+ unset x
+} -result {type proc line 1 cmd {info frame 0} proc ::foo::bar level 0}
+
+# -------------------------------------------------------------------------
+
+namespace eval foo {}
+dict for {k v} {foo bar} {
+ proc ::foo::bar {} {info frame 0}
+}
+
+test info-24.7 {info frame, interaction, dict for} {
+ reduce [foo::bar]
+} {type source line 956 file info.test cmd {info frame 0} proc ::foo::bar level 0}
+
+namespace delete foo
+
+# -------------------------------------------------------------------------
+
+namespace eval foo {}
+set thedict {foo bar}
+dict with thedict {
+ proc ::foo::bar {} {info frame 0}
+}
+
+test info-24.8 {info frame, interaction, dict with} {
+ reduce [foo::bar]
+} {type source line 970 file info.test cmd {info frame 0} proc ::foo::bar level 0}
namespace delete foo
+unset thedict
+
+# -------------------------------------------------------------------------
+
+namespace eval foo {}
+dict filter {foo bar} script {k v} {
+ proc ::foo::bar {} {info frame 0}
+ set x 1
+}
+
+test info-24.9 {info frame, interaction, dict filter} {
+ reduce [foo::bar]
+} {type source line 984 file info.test cmd {info frame 0} proc ::foo::bar level 0}
+
+namespace delete foo
+unset x
# -------------------------------------------------------------------------
@@ -934,22 +998,25 @@ eval {
proc bar {} {info frame 0}
}
-test info-25.0 {info frame, proc in eval} tip280 {
+test info-25.0 {info frame, proc in eval} {
reduce [bar]
-} {type source line 934 file info.test cmd {info frame 0} proc ::bar level 0}
+} {type source line 998 file info.test cmd {info frame 0} proc ::bar level 0}
+# Don't need to clean up yet...
proc bar {} {info frame 0}
-test info-25.1 {info frame, regular proc} tip280 {
+
+test info-25.1 {info frame, regular proc} {
reduce [bar]
-} {type source line 941 file info.test cmd {info frame 0} proc ::bar level 0}
-rename bar {}
+} {type source line 1006 file info.test cmd {info frame 0} proc ::bar level 0}
+rename bar {}
+# -------------------------------------------------------------------------
# More info-30.x test cases at the end of the file.
-test info-30.0 {bs+nl in literal words} {tip280} {
+test info-30.0 {bs+nl in literal words} {
if {1} {
set res \
- [reduce [info frame 0]];# line 952
+ [reduce [info frame 0]];# 1019
}
set res
# This was reporting line 3 instead of the correct 4 because the
@@ -958,9 +1025,7 @@ test info-30.0 {bs+nl in literal words} {tip280} {
# offsets of all bs+nl sequences in literal words, then using the
# information in the bcc and other places to bump line numbers when
# parsing over the location. Also affected: testcases 22.8 and 23.6.
-} {type source line 952 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
-
-
+} {type source line 1019 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
# -------------------------------------------------------------------------
# See 24.0 - 24.5 for similar situations, using literal scripts.
@@ -969,26 +1034,23 @@ set body {set flag 0
set a c
set res [info frame 0]} ;# line 3!
-test info-31.0 {ns eval, script in variable} tip280 {set res {}
+test info-31.0 {ns eval, script in variable} {set res {}
namespace eval foo $body
set res
} {type eval line 3 cmd {info frame 0} level 0}
catch {namespace delete foo}
-
-test info-31.1 {if, script in variable} tip280 {
+test info-31.1 {if, script in variable} {
if 1 $body
set res
} {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}
-test info-31.1a {if, script in variable} tip280 {
+test info-31.1a {if, script in variable} {
if 1 then $body
set res
} {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}
-
-
-test info-31.2 {while, script in variable} tip280 {
+test info-31.2 {while, script in variable} {
set flag 1
while {$flag} $body
set res
@@ -996,106 +1058,250 @@ test info-31.2 {while, script in variable} tip280 {
# .3 - proc - scoping prevent return of result ...
-test info-31.4 {foreach, script in variable} tip280 {
+test info-31.4 {foreach, script in variable} {
foreach var val $body
set res
} {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}
-test info-31.5 {for, script in variable} tip280 {
+test info-31.5 {for, script in variable} {
set flag 1
for {} {$flag} {} $body
set res
} {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}
-test info-31.6 {eval, script in variable} tip280 {
+test info-31.6 {eval, script in variable} {
eval $body
set res
} {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}
# -------------------------------------------------------------------------
-namespace eval foo {}
-set x foo
-switch -exact -- $x {
+set body {
foo {
proc ::foo::bar {} {info frame 0}
}
}
-test info-24.6.0 {info frame, interaction, switch, list body} tip280 {
+namespace eval foo {}
+set x foo
+switch -exact -- $x $body
+
+test info-31.7 {info frame, interaction, switch, dynamic} -body {
reduce [foo::bar]
-} {type source line 1021 file info.test cmd {info frame 0} proc ::foo::bar level 0}
+} -cleanup {
+ namespace delete foo
+ unset x
+} -result {type proc line 1 cmd {info frame 0} proc ::foo::bar level 0}
-namespace delete foo
-unset x
+# -------------------------------------------------------------------------
+
+set body {
+ proc ::foo::bar {} {info frame 0}
+}
+
+namespace eval foo {}
+eval $body
+
+test info-32.0 {info frame, dynamic procedure} -body {
+ reduce [foo::bar]
+} -cleanup {
+ namespace delete foo
+} -result {type proc line 1 cmd {info frame 0} proc ::foo::bar level 0}
+
+# -------------------------------------------------------------------------
+
+namespace {*}{
+ eval
+ foo
+ {proc bar {} {info frame 0}}
+}
+test info-33.0 {{*}, literal, direct} -body {
+ reduce [foo::bar]
+} -cleanup {
+ namespace delete foo
+} -result {type source line 1116 file info.test cmd {info frame 0} proc ::foo::bar level 0}
# -------------------------------------------------------------------------
namespace eval foo {}
-set x foo
-switch -exact -- $x foo {
- proc ::foo::bar {} {info frame 0}
+proc foo::bar {} {
+ set flag 1
+ if {*}{
+ {$flag}
+ {info frame 0}
+ }
}
+test info-33.1 {{*}, literal, simple, bytecompiled} -body {
+ reduce [foo::bar]
+} -cleanup {
+ namespace delete foo
+} -result {type source line 1131 file info.test cmd {info frame 0} proc ::foo::bar level 0}
+
+# -------------------------------------------------------------------------
-test info-24.6.1 {info frame, interaction, switch, multi-body} tip280 {
+namespace {*}"
+ eval
+ foo
+ {proc bar {} {info frame 0}}
+"
+test info-33.2 {{*}, literal, direct} {
reduce [foo::bar]
-} {type source line 1037 file info.test cmd {info frame 0} proc ::foo::bar level 0}
+} {type source line 1145 file info.test cmd {info frame 0} proc ::foo::bar level 0}
namespace delete foo
-unset x
# -------------------------------------------------------------------------
-namespace eval foo {}
-set x foo
-switch -exact -- $x [list foo {
- proc ::foo::bar {} {info frame 0}
-}]
+namespace {*}"eval\nfoo\n{proc bar {} {info frame 0}}\n"
-test info-24.6.2 {info frame, interaction, switch, list body, dynamic} tip280 {
+test info-33.2a {{*}, literal, not simple, direct} {
reduce [foo::bar]
} {type proc line 1 cmd {info frame 0} proc ::foo::bar level 0}
namespace delete foo
-unset x
# -------------------------------------------------------------------------
-set body {
- foo {
- proc ::foo::bar {} {info frame 0}
- }
+namespace eval foo {}
+proc foo::bar {} {
+ set flag 1
+ if {*}"
+ {1}
+ {info frame 0}
+ "
}
+test info-33.3 {{*}, literal, simple, bytecompiled} {
+ reduce [foo::bar]
+} {type source line 1170 file info.test cmd {info frame 0} proc ::foo::bar level 0}
+
+namespace delete foo
+
+# -------------------------------------------------------------------------
namespace eval foo {}
-set x foo
-switch -exact -- $x $body
+proc foo::bar {} {
+ set flag 1
+ if {*}"\n{1}\n{info frame 0}"
+}
+test info-33.3a {{*}, literal, not simple, bytecompiled} {
+ reduce [foo::bar]
+} {type eval line 1 cmd {info frame 0} proc ::foo::bar level 0}
+
+namespace delete foo
-test info-31.7 {info frame, interaction, switch, dynamic} tip280 {
+# -------------------------------------------------------------------------
+
+set body {
+ eval
+ foo
+ {proc bar {} {
+ info frame 0
+ }}
+}
+namespace {*}$body
+test info-34.0 {{*}, dynamic, direct} {
reduce [foo::bar]
-} {type proc line 1 cmd {info frame 0} proc ::foo::bar level 0}
+} {type proc line 2 cmd {info frame 0} proc ::foo::bar level 0}
+unset body
namespace delete foo
-unset x
# -------------------------------------------------------------------------
+namespace eval foo {}
set body {
- proc ::foo::bar {} {info frame 0}
+ {$flag}
+ {info frame 0}
+}
+proc foo::bar {} {
+ global body ; set flag 1
+ if {*}$body
}
+test info-34.1 {{*}, literal, bytecompiled} {
+ reduce [foo::bar]
+} {type eval line 1 cmd {info frame 0} proc ::foo::bar level 0}
+
+unset body
+namespace delete foo
+
+# -------------------------------------------------------------------------
+
+proc foo {} {
+ apply {
+ {x y}
+ {info frame 0}
+ } 0 0
+}
+test info-35.0 {apply, literal} {
+ reduce [foo]
+} {type source line 1232 file info.test cmd {info frame 0} lambda {
+ {x y}
+ {info frame 0}
+ } level 0}
+rename foo {}
+
+set lambda {
+ {x y}
+ {info frame 0}
+}
+test info-35.1 {apply, dynamic} {
+ reduce [apply $lambda 0 0]
+} {type proc line 1 cmd {info frame 0} lambda {
+ {x y}
+ {info frame 0}
+} level 0}
+unset lambda
+
+# -------------------------------------------------------------------------
namespace eval foo {}
-eval $body
+proc foo::bar {} {
+ dict for {k v} {foo bar} {
+ set x [info frame 0]
+ }
+ set x
+}
+test info-36.0 {info frame, dict for, bcc} {
+ reduce [foo::bar]
+} {type source line 1260 file info.test cmd {info frame 0} proc ::foo::bar level 0}
-test info-32.0 {info frame, dynamic procedure} tip280 {
+namespace delete foo
+
+# -------------------------------------------------------------------------
+
+namespace eval foo {}
+proc foo::bar {} {
+ set x foo
+ switch -exact -- $x {
+ foo {set y [info frame 0]}
+ }
+ set y
+}
+
+test info-36.1.0 {switch, list literal, bcc} {
reduce [foo::bar]
-} {type proc line 1 cmd {info frame 0} proc ::foo::bar level 0}
+} {type source line 1276 file info.test cmd {info frame 0} proc ::foo::bar level 0}
+
+namespace delete foo
+
+# -------------------------------------------------------------------------
+
+namespace eval foo {}
+proc foo::bar {} {
+ set x foo
+ switch -exact -- $x foo {set y [info frame 0]}
+ set y
+}
+
+test info-36.1.1 {switch, multi-body literals, bcc} {
+ reduce [foo::bar]
+} {type source line 1292 file info.test cmd {info frame 0} proc ::foo::bar level 0}
namespace delete foo
# -------------------------------------------------------------------------
-test info-34.0 {eval pure list, single line} -constraints {tip280} -match glob -body {
+test info-37.0 {eval pure list, single line} -constraints {!singleTestInterp} -match glob -body {
# Basically, counting the newline in the word seen through $foo
# doesn't really make sense. It makes a bit of sense if the word
# would have been a string literal in the command list.
@@ -1113,7 +1319,7 @@ test info-34.0 {eval pure list, single line} -constraints {tip280} -match glob -
}]
eval $cmd
set res
-} -result {* {type source line 723 file info.test cmd {info frame $level} proc ::etrace level 0}
+} -result {* {type source line 728 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type eval line 2 cmd etrace proc ::tcltest::RunTest}
* {type eval line 1 cmd foreac proc ::tcltest::RunTest}}
@@ -1148,66 +1354,66 @@ proc datav {} {
control y $script
}
-test info-38.1 {location information for uplevel, dv, direct-var} -constraints tip280 -match glob -body {
+test info-38.1 {location information for uplevel, dv, direct-var} -match glob -body {
set script {
set y DV.
etrace
}
join [lrange [uplevel \#0 $script] 0 2] \n
-} -result {* {type source line 723 file info.test cmd {info frame $level} proc ::etrace level 0}
+} -result {* {type source line 728 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type eval line 3 cmd etrace proc ::tcltest::RunTest}
-* {type source line 1156 file info.test cmd {uplevel \\#0 $script} proc ::tcltest::RunTest}}
+* {type source line 1362 file info.test cmd {uplevel \\#0 $script} proc ::tcltest::RunTest}}
+
+# 38.2 moved to bottom to not disturb other tests with the necessary changes to this one.
-test info-38.2 {location information for uplevel, dl, direct-literal} -constraints tip280 -match glob -body {
- join [lrange [uplevel \#0 {
- set y DL.
- etrace
- }] 0 2] \n
-} -result {* {type source line 723 file info.test cmd {info frame $level} proc ::etrace level 0}
-* {type source line 1164 file info.test cmd etrace proc ::tcltest::RunTest}
-* {type source line 1162 file info.test cmd up proc ::tcltest::RunTest}}
-test info-38.3 {location information for uplevel, dpv, direct-proc-var} -constraints tip280 -match glob -body {
+
+
+
+
+
+
+test info-38.3 {location information for uplevel, dpv, direct-proc-var} -match glob -body {
set script {
set y DPV
etrace
}
join [lrange [control y $script] 0 3] \n
-} -result {* {type source line 723 file info.test cmd {info frame $level} proc ::etrace level 0}
+} -result {* {type source line 728 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type eval line 3 cmd etrace proc ::control}
-* {type source line 1133 file info.test cmd {uplevel 1 $script} proc ::control}
-* {type source line 1175 file info.test cmd {control y $script} proc ::tcltest::RunTest}}
+* {type source line 1339 file info.test cmd {uplevel 1 $script} proc ::control}
+* {type source line 1381 file info.test cmd {control y $script} proc ::tcltest::RunTest}}
+
+# 38.4 moved to bottom to not disturb other tests with the necessary changes to this one.
+
+
-test info-38.4 {location information for uplevel, dpv, direct-proc-literal} -constraints tip280 -match glob -body {
- join [lrange [control y {
- set y DPL
- etrace
- }] 0 3] \n
-} -result {* {type source line 723 file info.test cmd {info frame $level} proc ::etrace level 0}
-* {type source line 1184 file info.test cmd etrace proc ::control}
-* {type source line 1133 file info.test cmd {uplevel 1 $script} proc ::control}
-* {type source line 1182 file info.test cmd control proc ::tcltest::RunTest}}
-test info-38.5 {location information for uplevel, ppv, proc-proc-var} -constraints tip280 -match glob -body {
+
+
+
+
+
+test info-38.5 {location information for uplevel, ppv, proc-proc-var} -match glob -body {
join [lrange [datav] 0 4] \n
-} -result {* {type source line 723 file info.test cmd {info frame $level} proc ::etrace level 0}
+} -result {* {type source line 728 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type eval line 3 cmd etrace proc ::control}
-* {type source line 1133 file info.test cmd {uplevel 1 $script} proc ::control}
-* {type source line 1148 file info.test cmd {control y $script} proc ::datav level 1}
-* {type source line 1192 file info.test cmd datav proc ::tcltest::RunTest}}
-
-test info-38.6 {location information for uplevel, ppl, proc-proc-literal} -constraints tip280 -match glob -body {
- join [lrange [datal] 0 4] \n
-} -result {* {type source line 723 file info.test cmd {info frame $level} proc ::etrace level 0}
-* {type source line 1139 file info.test cmd etrace proc ::control}
-* {type source line 1133 file info.test cmd {uplevel 1 $script} proc ::control}
-* {type source line 1137 file info.test cmd control proc ::datal level 1}
-* {type source line 1200 file info.test cmd datal proc ::tcltest::RunTest}}
+* {type source line 1339 file info.test cmd {uplevel 1 $script} proc ::control}
+* {type source line 1354 file info.test cmd {control y $script} proc ::datav level 1}
+* {type source line 1398 file info.test cmd datav proc ::tcltest::RunTest}}
+
+# 38.6 moved to bottom to not disturb other tests with the necessary changes to this one.
+
+
+
+
+
+
# -------------------------------------------------------------------------
# literal sharing
-test info-39.0 {location information not confused by literal sharing} -constraints tip280 -body {
+test info-39.0 {location information not confused by literal sharing} -body {
namespace eval ::foo {}
proc ::foo::bar {} {
lappend res {}
@@ -1219,146 +1425,146 @@ test info-39.0 {location information not confused by literal sharing} -constrain
namespace delete ::foo
join $res \n
} -result {
-type source line 1214 file info.test cmd {info frame 0} proc ::foo::bar level 0
-type source line 1215 file info.test cmd {info frame 0} proc ::foo::bar level 0}
+type source line 1420 file info.test cmd {info frame 0} proc ::foo::bar level 0
+type source line 1421 file info.test cmd {info frame 0} proc ::foo::bar level 0}
# -------------------------------------------------------------------------
# Additional tests for info-30.*, handling of continuation lines (bs+nl sequences).
-test info-30.1 {bs+nl in literal words, procedure body, compiled} {tip280} {
+test info-30.1 {bs+nl in literal words, procedure body, compiled} {
proc abra {} {
if {1} \
{
return \
- [reduce [info frame 0]];# line 1233
+ [reduce [info frame 0]];# line 1439
}
}
set res [abra]
rename abra {}
set res
-} {type source line 1233 file info.test cmd {info frame 0} proc ::abra level 0}
+} {type source line 1439 file info.test cmd {info frame 0} proc ::abra level 0}
-test info-30.2 {bs+nl in literal words, namespace script} {tip280} {
+test info-30.2 {bs+nl in literal words, namespace script} {
namespace eval xxx {
set res \
- [reduce [info frame 0]];# line 1244
+ [reduce [info frame 0]];# line 1450
}
set res
-} {type source line 1244 file info.test cmd {info frame 0} level 0}
+} {type source line 1450 file info.test cmd {info frame 0} level 0}
-test info-30.3 {bs+nl in literal words, namespace multi-word script} {tip280} {
+test info-30.3 {bs+nl in literal words, namespace multi-word script} {
namespace eval xxx set res \
- [list [reduce [info frame 0]]];# line 1251
+ [list [reduce [info frame 0]]];# line 1457
set res
-} {type source line 1251 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
+} {type source line 1457 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
-test info-30.4 {bs+nl in literal words, eval script} {tip280} {
+test info-30.4 {bs+nl in literal words, eval script} {
eval {
set ::res \
- [reduce [info frame 0]];# line 1258
+ [reduce [info frame 0]];# line 1464
}
set res
-} {type source line 1258 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
+} {type source line 1464 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
-test info-30.5 {bs+nl in literal words, eval script, with nested words} {tip280} {
+test info-30.5 {bs+nl in literal words, eval script, with nested words} {
eval {
if {1} \
{
set ::res \
- [reduce [info frame 0]];# line 1268
+ [reduce [info frame 0]];# line 1474
}
}
set res
-} {type source line 1268 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
+} {type source line 1474 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
-test info-30.6 {bs+nl in computed word} {tip280} {
+test info-30.6 {bs+nl in computed word} {
set res "\
-[reduce [info frame 0]]";# line 1276
-} { type source line 1276 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
+[reduce [info frame 0]]";# line 1482
+} { type source line 1482 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
-test info-30.7 {bs+nl in computed word, in proc} {tip280} {
+test info-30.7 {bs+nl in computed word, in proc} {
proc abra {} {
return "\
-[reduce [info frame 0]]";# line 1282
+[reduce [info frame 0]]";# line 1488
}
set res [abra]
rename abra {}
set res
-} { type source line 1282 file info.test cmd {info frame 0} proc ::abra level 0}
+} { type source line 1488 file info.test cmd {info frame 0} proc ::abra level 0}
-test info-30.8 {bs+nl in computed word, nested eval} {tip280} {
+test info-30.8 {bs+nl in computed word, nested eval} {
eval {
set \
res "\
-[reduce [info frame 0]]";# line 1293
+[reduce [info frame 0]]";# line 1499
}
-} { type source line 1293 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
+} { type source line 1499 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
-test info-30.9 {bs+nl in computed word, nested eval} {tip280} {
+test info-30.9 {bs+nl in computed word, nested eval} {
eval {
set \
res "\
[reduce \
- [info frame 0]]";# line 1302
+ [info frame 0]]";# line 1508
}
-} { type source line 1302 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
+} { type source line 1508 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
-test info-30.10 {bs+nl in computed word, key to array} {tip280} {
+test info-30.10 {bs+nl in computed word, key to array} {
set tmp([set \
res "\
[reduce \
- [info frame 0]]"]) x ; #1310
+ [info frame 0]]"]) x ; #1516
unset tmp
set res
-} { type source line 1310 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
+} { type source line 1516 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
-test info-30.11 {bs+nl in subst arguments, no true counting} {tip280} {
+test info-30.11 {bs+nl in subst arguments, no true counting} {
subst {[set \
res "\
[reduce \
[info frame 0]]"]}
-} { type eval line 2 cmd {info frame 0} proc ::tcltest::RunTest}
+} { type eval line 1 cmd {info frame 0} proc ::tcltest::RunTest}
-test info-30.12 {bs+nl in computed word, nested eval} {tip280} {
+test info-30.12 {bs+nl in computed word, nested eval} {
eval {
set \
res "\
[set x {}] \
[reduce \
- [info frame 0]]";# line 1328
+ [info frame 0]]";# line 1534
}
-} { type source line 1328 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
+} { type source line 1534 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
-test info-30.13 {bs+nl in literal words, uplevel script, with nested words} {tip280} {
- uplevel #0 {
+test info-30.13 {bs+nl in literal words, uplevel script, with nested words} {
+ subinterp ; set res [interp eval sub { uplevel #0 {
if {1} \
{
set ::res \
- [reduce [info frame 0]];# line 1337
+ [reduce [info frame 0]];# line 1543
}
}
- set res
-} {type source line 1337 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
+ set res }] ; interp delete sub ; set res
+} {type source line 1543 file info.test cmd {info frame 0} level 0}
-test info-30.14 {bs+nl, literal word, uplevel through proc} {tip280} {
- proc abra {script} {
+test info-30.14 {bs+nl, literal word, uplevel through proc} {
+ subinterp ; set res [interp eval sub { proc abra {script} {
uplevel 1 $script
}
set res [abra {
return "\
-[reduce [info frame 0]]";# line 1349
+ [reduce [info frame 0]]";# line 1555
}]
rename abra {}
- set res
-} { type source line 1349 file info.test cmd {info frame 0} proc ::abra}
+ set res }] ; interp delete sub ; set res
+} { type source line 1555 file info.test cmd {info frame 0} proc ::abra}
-test info-30.15 {bs+nl in literal words, nested proc body, compiled} {tip280} {
+test info-30.15 {bs+nl in literal words, nested proc body, compiled} {
proc a {} {
proc b {} {
if {1} \
{
return \
- [reduce [info frame 0]];# line 1361
+ [reduce [info frame 0]];# line 1567
}
}
}
@@ -1366,45 +1572,45 @@ test info-30.15 {bs+nl in literal words, nested proc body, compiled} {tip280} {
rename a {}
rename b {}
set res
-} {type source line 1361 file info.test cmd {info frame 0} proc ::b level 0}
+} {type source line 1567 file info.test cmd {info frame 0} proc ::b level 0}
-test info-30.16 {bs+nl in multi-body switch, compiled} {tip280} {
+test info-30.16 {bs+nl in multi-body switch, compiled} {
proc a {value} {
switch -regexp -- $value \
- ^key { info frame 0; # 1374 } \
- \t { info frame 0; # 1375 } \
- {[0-9]*} { info frame 0; # 1376 }
+ ^key { info frame 0; # 1580 } \
+ \t### { info frame 0; # 1581 } \
+ {[0-9]*} { info frame 0; # 1582 }
}
set res {}
lappend res [reduce [a {key }]]
lappend res [reduce [a {1alpha}]]
set res "\n[join $res \n]"
} {
-type source line 1374 file info.test cmd {info frame 0} proc ::a level 0
-type source line 1376 file info.test cmd {info frame 0} proc ::a level 0}
+type source line 1580 file info.test cmd {info frame 0} proc ::a level 0
+type source line 1582 file info.test cmd {info frame 0} proc ::a level 0}
-test info-30.17 {bs+nl in multi-body switch, direct} {tip280} {
+test info-30.17 {bs+nl in multi-body switch, direct} {
switch -regexp -- {key } \
- ^key { reduce [info frame 0] ;# 1388 } \
+ ^key { reduce [info frame 0] ;# 1594 } \
\t### { } \
{[0-9]*} { }
-} {type source line 1388 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
+} {type source line 1594 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
-test info-30.18 {bs+nl, literal word, uplevel through proc, appended, loss of primary tracking data} {tip280} {
+test info-30.18 {bs+nl, literal word, uplevel through proc, appended, loss of primary tracking data} {
proc abra {script} {
append script "\n# end of script"
uplevel 1 $script
}
set res [abra {
return "\
-[reduce [info frame 0]]";# line 1400, still line of 3 appended script
+[reduce [info frame 0]]";# line 1606, still line of 3 appended script
}]
rename abra {}
set res
} { type eval line 3 cmd {info frame 0} proc ::abra}
-# { type source line 1400 file info.test cmd {info frame 0} proc ::abra}
+# { type source line 1606 file info.test cmd {info frame 0} proc ::abra}
-test info-30.19 {bs+nl in single-body switch, compiled} {tip280} {
+test info-30.19 {bs+nl in single-body switch, compiled} {
proc a {value} {
switch -regexp -- $value {
^key { reduce \
@@ -1420,20 +1626,20 @@ test info-30.19 {bs+nl in single-body switch, compiled} {tip280} {
lappend res [a {1alpha}]
set res "\n[join $res \n]"
} {
-type source line 1411 file info.test cmd {info frame 0} proc ::a level 0
-type source line 1415 file info.test cmd {info frame 0} proc ::a level 0}
+type source line 1617 file info.test cmd {info frame 0} proc ::a level 0
+type source line 1621 file info.test cmd {info frame 0} proc ::a level 0}
-test info-30.20 {bs+nl in single-body switch, direct} {tip280} {
+test info-30.20 {bs+nl in single-body switch, direct} {
switch -regexp -- {key } { \
^key { reduce \
[info frame 0] }
- \t { }
+ \t### { }
{[0-9]*} { }
}
-} {type source line 1430 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
+} {type source line 1636 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
-test info-30.21 {bs+nl in if, full compiled} {tip280} {
+test info-30.21 {bs+nl in if, full compiled} {
proc a {value} {
if {$value} \
{info frame 0} \
@@ -1444,24 +1650,173 @@ test info-30.21 {bs+nl in if, full compiled} {tip280} {
lappend res [reduce [a 0]]
set res "\n[join $res \n]"
} {
-type source line 1439 file info.test cmd {info frame 0} proc ::a level 0
-type source line 1440 file info.test cmd {info frame 0} proc ::a level 0}
+type source line 1645 file info.test cmd {info frame 0} proc ::a level 0
+type source line 1646 file info.test cmd {info frame 0} proc ::a level 0}
-test info-30.22 {bs+nl in computed word, key to array, compiled} {tip280} {
+test info-30.22 {bs+nl in computed word, key to array, compiled} {
proc a {} {
set tmp([set \
res "\
[reduce \
- [info frame 0]]"]) x ; #1454
+ [info frame 0]]"]) x ; #1661
unset tmp
set res
}
set res [a]
rename a {}
set res
-} { type source line 1455 file info.test cmd {info frame 0} proc ::a level 0}
+} { type source line 1661 file info.test cmd {info frame 0} proc ::a level 0}
+
+test info-30.23 {bs+nl in multi-body switch, full compiled} {
+ proc a {value} {
+ switch -exact -- $value \
+ key { info frame 0; # 1673 } \
+ xxx { info frame 0; # 1674 } \
+ 000 { info frame 0; # 1675 }
+ }
+ set res {}
+ lappend res [reduce [a key]]
+ lappend res [reduce [a 000]]
+ set res "\n[join $res \n]"
+} {
+type source line 1673 file info.test cmd {info frame 0} proc ::a level 0
+type source line 1675 file info.test cmd {info frame 0} proc ::a level 0}
+
+test info-30.24 {bs+nl in single-body switch, full compiled} {
+ proc a {value} {
+ switch -exact -- $value {
+ key { reduce \
+ [info frame 0] }
+ xxx { reduce \
+ [info frame 0] }
+ 000 { reduce \
+ [info frame 0] }
+ }
+ }
+ set res {}
+ lappend res [a key]
+ lappend res [a 000]
+ set res "\n[join $res \n]"
+} {
+type source line 1689 file info.test cmd {info frame 0} proc ::a level 0
+type source line 1693 file info.test cmd {info frame 0} proc ::a level 0}
# -------------------------------------------------------------------------
+# literal sharing 2, bug 2933089
+
+test info-39.1 {location information not confused by literal sharing, bug 2933089} -setup {
+ set result {}
+
+ proc print_one {} {}
+ proc test_info_frame {} {
+ set x 1
+ set y x
+
+ if "$x != 1" {
+ } else {
+ print_one
+ } ;#line 1717^
+
+ if "$$y != 1" {
+ } else {
+ print_one
+ } ;#line 1722^
+ # Do not put the comments listing the line numbers into the
+ # branches. We need shared literals, and the comments would
+ # make them different, thus unshared.
+ }
+
+ proc get_frame_info { cmd_str op } {
+ lappend ::result [reduce [eval {info frame -3}]]
+ }
+ trace add execution print_one enter get_frame_info
+} -body {
+ test_info_frame;
+ join $result \n
+} -cleanup {
+ trace remove execution print_one enter get_frame_info
+ rename get_frame_info {}
+ rename test_info_frame {}
+ rename print_one {}
+} -result {type source line 1717 file info.test cmd print_one proc ::test_info_frame level 1
+type source line 1722 file info.test cmd print_one proc ::test_info_frame level 1}
+
+# -------------------------------------------------------------------------
+# Tests moved to the end to not disturb other tests and their locations.
+
+test info-38.6 {location information for uplevel, ppl, proc-proc-literal} -match glob -setup {subinterp} -body {
+ interp eval sub {
+ proc etrace {} {
+ set res {}
+ set level [info frame]
+ while {$level} {
+ lappend res [list $level [reduce [info frame $level]]]
+ incr level -1
+ }
+ return $res
+ }
+ proc control {vv script} {
+ upvar 1 $vv var
+ return [uplevel 1 $script]
+ }
+ proc datal {} {
+ control y {
+ set y PPL
+ etrace
+ }
+ }
+ join [lrange [datal] 0 4] \n
+ }
+} -result {* {type source line 1753 file info.test cmd {info frame $level} proc ::etrace level 0}
+* {type source line 1765 file info.test cmd etrace proc ::control}
+* {type source line 1760 file info.test cmd {uplevel 1 $script} proc ::control}
+* {type source line 1763 file info.test cmd control proc ::datal level 1}
+* {type source line 1768 file info.test cmd datal level 2}} -cleanup {interp delete sub}
+
+test info-38.4 {location information for uplevel, dpv, direct-proc-literal} -match glob -setup {subinterp} -body {
+ interp eval sub {
+ proc etrace {} {
+ set res {}
+ set level [info frame]
+ while {$level} {
+ lappend res [list $level [reduce [info frame $level]]]
+ incr level -1
+ }
+ return $res
+ }
+ proc control {vv script} {
+ upvar 1 $vv var
+ return [uplevel 1 $script]
+ }
+ join [lrange [control y {
+ set y DPL
+ etrace
+ }] 0 3] \n
+ }
+} -result {* {type source line 1782 file info.test cmd {info frame $level} proc ::etrace level 0}
+* {type source line 1793 file info.test cmd etrace proc ::control}
+* {type source line 1789 file info.test cmd {uplevel 1 $script} proc ::control}
+* {type source line 1791 file info.test cmd control level 1}} -cleanup {interp delete sub}
+
+test info-38.2 {location information for uplevel, dl, direct-literal} -match glob -setup {subinterp} -body {
+ interp eval sub {
+ proc etrace {} {
+ set res {}
+ set level [info frame]
+ while {$level} {
+ lappend res [list $level [reduce [info frame $level]]]
+ incr level -1
+ }
+ return $res
+ }
+ join [lrange [uplevel \#0 {
+ set y DL.
+ etrace
+ }] 0 2] \n
+ }
+} -result {* {type source line 1807 file info.test cmd {info frame $level} proc ::etrace level 0}
+* {type source line 1814 file info.test cmd etrace level 1}
+* {type source line 1812 file info.test cmd uplevel\\ \\\\ level 1}} -cleanup {interp delete sub}
# cleanup
catch {namespace delete test_ns_info1 test_ns_info2}
diff --git a/tests/init.test b/tests/init.test
index 79142c4..0af94ea 100644
--- a/tests/init.test
+++ b/tests/init.test
@@ -11,12 +11,12 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2.3.3
namespace import -force ::tcltest::*
}
# Clear out any namespaces called test_ns_*
-catch {eval namespace delete [namespace children :: test_ns_*]}
+catch {namespace delete {*}[namespace children :: test_ns_*]}
# Six cases - white box testing
@@ -53,21 +53,18 @@ test init-1.7 {auto_qualify - multiples colons 1} {
test init-1.8 {auto_qualify - multiple colons 2} {
auto_qualify :::foo ::bar
} foo
-
+
# we use a sub interp and auto_reset and double the tests because there is 2
# places where auto_loading occur (before loading the indexes files and after)
set testInterp [interp create]
-interp eval $testInterp [list set argv $argv]
-interp eval $testInterp [list package require tcltest]
-interp eval $testInterp [list namespace import -force ::tcltest::*]
-
+tcltest::loadIntoSlaveInterpreter $testInterp {*}$argv
interp eval $testInterp {
-
-auto_reset
-catch {rename parray {}}
-
+ namespace import -force ::tcltest::*
+ auto_reset
+ catch {rename parray {}}
+
test init-2.0 {load parray - stage 1} {
set ret [catch {parray} error]
rename parray {} ; # remove it, for the next test - that should not fail.
@@ -148,12 +145,12 @@ test init-3.0 {random stuff in the auto_index, should still work} {
set count 0
foreach arg [subst -nocommands -novariables {
- c
- {argument
+ c
+ {argument
which spans
multiple lines}
- {argument which is all on one line but which is of such great length that the Tcl C library will truncate it when appending it onto the global error stack}
- {argument which spans multiple lines
+ {argument which is all on one line but which is of such great length that the Tcl C library will truncate it when appending it onto the global error stack}
+ {argument which spans multiple lines
and is long enough to be truncated and
" <- includes a false lead in the prune point search
and must be longer still to force truncation}
@@ -162,13 +159,13 @@ foreach arg [subst -nocommands -novariables {
error stack cannot be uniquely determined.
foo bar foo
"}
- {contrived example: rare circumstance
+ {contrived example: rare circumstance
where the point at which to prune the
error stack cannot be uniquely determined.
foo bar
"}
- {argument that contains non-ASCII character, \u20ac, and which is of such great length that it will be longer than 150 bytes so it will be truncated by the Tcl C library}
- }] {
+ {argument that contains non-ASCII character, \u20ac, and which is of such great length that it will be longer than 150 bytes so it will be truncated by the Tcl C library}
+ }] { ;# emacs needs -> "
test init-4.$count.0 {::errorInfo produced by [unknown]} {
auto_reset
@@ -194,6 +191,19 @@ foreach arg [subst -nocommands -novariables {
incr count
}
+test init-5.0 {return options passed through ::unknown} -setup {
+ catch {rename xxx {}}
+ set ::auto_index(::xxx) {proc ::xxx {} {
+ return -code error -level 2 xxx
+ }}
+} -body {
+ set code [catch {::xxx} foo bar]
+ set code2 [catch {::xxx} foo2 bar2]
+ list $code $foo $bar $code2 $foo2 $bar2
+} -cleanup {
+ unset ::auto_index(::xxx)
+} -result {2 xxx {-errorcode NONE -code 1 -level 1} 2 xxx {-code 1 -level 1 -errorcode NONE}}
+
cleanupTests
} ;# End of [interp eval $testInterp]
diff --git a/tests/interp.test b/tests/interp.test
index ff38301..5e6d6b0 100644
--- a/tests/interp.test
+++ b/tests/interp.test
@@ -15,27 +15,21 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-# The set of hidden commands is platform dependent:
+testConstraint testinterpdelete [llength [info commands testinterpdelete]]
-if {"$tcl_platform(platform)" == "macintosh"} {
- set hidden_cmds {beep cd echo encoding exit fconfigure file glob load ls open pwd socket source}
-} else {
- set hidden_cmds {cd encoding exec exit fconfigure file glob load open pwd socket source}
-}
+set hidden_cmds {cd encoding exec exit fconfigure file glob load open pwd socket source unload}
foreach i [interp slaves] {
interp delete $i
}
-proc equiv {x} {return $x}
-
# Part 0: Check out options for interp command
test interp-1.1 {options for interp command} {
list [catch {interp} msg] $msg
} {1 {wrong # args: should be "interp cmd ?arg ...?"}}
test interp-1.2 {options for interp command} {
list [catch {interp frobox} msg] $msg
-} {1 {bad option "frobox": must be alias, aliases, create, delete, eval, exists, expose, hide, hidden, issafe, invokehidden, marktrusted, recursionlimit, slaves, share, target, or transfer}}
+} {1 {bad option "frobox": must be alias, aliases, bgerror, create, debug, delete, eval, exists, expose, hide, hidden, issafe, invokehidden, limit, marktrusted, recursionlimit, slaves, share, target, or transfer}}
test interp-1.3 {options for interp command} {
interp delete
} ""
@@ -53,13 +47,13 @@ test interp-1.6 {options for interp command} {
} {1 {wrong # args: should be "interp slaves ?path?"}}
test interp-1.7 {options for interp command} {
list [catch {interp hello} msg] $msg
-} {1 {bad option "hello": must be alias, aliases, create, delete, eval, exists, expose, hide, hidden, issafe, invokehidden, marktrusted, recursionlimit, slaves, share, target, or transfer}}
+} {1 {bad option "hello": must be alias, aliases, bgerror, create, debug, delete, eval, exists, expose, hide, hidden, issafe, invokehidden, limit, marktrusted, recursionlimit, slaves, share, target, or transfer}}
test interp-1.8 {options for interp command} {
list [catch {interp -froboz} msg] $msg
-} {1 {bad option "-froboz": must be alias, aliases, create, delete, eval, exists, expose, hide, hidden, issafe, invokehidden, marktrusted, recursionlimit, slaves, share, target, or transfer}}
+} {1 {bad option "-froboz": must be alias, aliases, bgerror, create, debug, delete, eval, exists, expose, hide, hidden, issafe, invokehidden, limit, marktrusted, recursionlimit, slaves, share, target, or transfer}}
test interp-1.9 {options for interp command} {
list [catch {interp -froboz -safe} msg] $msg
-} {1 {bad option "-froboz": must be alias, aliases, create, delete, eval, exists, expose, hide, hidden, issafe, invokehidden, marktrusted, recursionlimit, slaves, share, target, or transfer}}
+} {1 {bad option "-froboz": must be alias, aliases, bgerror, create, debug, delete, eval, exists, expose, hide, hidden, issafe, invokehidden, limit, marktrusted, recursionlimit, slaves, share, target, or transfer}}
test interp-1.10 {options for interp command} {
list [catch {interp target} msg] $msg
} {1 {wrong # args: should be "interp target path alias"}}
@@ -381,7 +375,7 @@ test interp-10.7 {testing aliases between interpreters} {
set x [foo 33]
a eval {rename zoppo {}}
interp alias "" foo a {}
- equiv $x
+ return $x
} {33 33 33}
# Part 10: Testing "interp target"
@@ -437,74 +431,170 @@ test interp-11.7 {testing interp target} {
test interp-12.1 {testing interp issafe} {
interp issafe
} 0
-test interp-12.2 {testing interp issafe} {
+test interp-12.2 {testing interp issafe} -setup {
catch {interp delete a}
+} -body {
interp create a
interp issafe a
-} 0
-test interp-12.3 {testing interp issafe} {
+} -result 0
+test interp-12.3 {testing interp issafe} -setup {
catch {interp delete a}
+} -body {
interp create a
interp create {a x3} -safe
interp issafe {a x3}
-} 1
-test interp-12.4 {testing interp issafe} {
+} -result 1
+test interp-12.4 {testing interp issafe} -setup {
catch {interp delete a}
+} -body {
interp create a
interp create {a x3} -safe
interp create {a x3 foo}
interp issafe {a x3 foo}
-} 1
+} -result 1
# Part 12: testing interpreter object command "issafe" sub-command
-test interp-13.1 {testing foo issafe} {
+test interp-13.1 {testing foo issafe} -setup {
catch {interp delete a}
+} -body {
interp create a
a issafe
-} 0
-test interp-13.2 {testing foo issafe} {
+} -result 0
+test interp-13.2 {testing foo issafe} -setup {
catch {interp delete a}
+} -body {
interp create a
interp create {a x3} -safe
a eval x3 issafe
-} 1
-test interp-13.3 {testing foo issafe} {
+} -result 1
+test interp-13.3 {testing foo issafe} -setup {
catch {interp delete a}
+} -body {
interp create a
interp create {a x3} -safe
interp create {a x3 foo}
a eval x3 eval foo issafe
-} 1
-test interp-13.4 {testing issafe arg checking} {
+} -result 1
+test interp-13.4 {testing issafe arg checking} -body {
catch {interp create a}
- list [catch {a issafe too many args} msg] $msg
-} {1 {wrong # args: should be "a issafe"}}
+ a issafe too many args
+} -returnCodes error -result {wrong # args: should be "a issafe"}
# part 14: testing interp aliases
test interp-14.1 {testing interp aliases} {
interp aliases
} ""
-test interp-14.2 {testing interp aliases} {
+test interp-14.2 {testing interp aliases} -setup {
catch {interp delete a}
+} -body {
interp create a
a alias a1 puts
a alias a2 puts
a alias a3 puts
lsort [interp aliases a]
-} {a1 a2 a3}
-test interp-14.3 {testing interp aliases} {
+} -result {a1 a2 a3}
+test interp-14.3 {testing interp aliases} -setup {
catch {interp delete a}
+} -body {
interp create a
interp create {a x3}
interp alias {a x3} froboz "" puts
interp aliases {a x3}
-} froboz
-test interp-14.4 {testing interp alias - alias over master} {
- # SF Bug 641195
+} -result froboz
+test interp-14.4 {testing interp alias - alias over master} -setup {
catch {interp delete a}
+} -body {
+ # SF Bug 641195
interp create a
list [catch {interp alias "" a a eval} msg] $msg [info commands a]
-} {1 {cannot define or rename alias "a": interpreter deleted} {}}
+} -result {1 {cannot define or rename alias "a": interpreter deleted} {}}
+test interp-14.5 {testing interp-alias: wrong # args} -body {
+ proc setx x {set x}
+ interp alias {} a {} setx
+ catch {a 1 2}
+ set ::errorInfo
+} -cleanup {
+ rename setx {}
+ rename a {}
+} -result {wrong # args: should be "a x"
+ while executing
+"a 1 2"}
+test interp-14.6 {testing interp-alias: wrong # args} -setup {
+ proc setx x {set x}
+ catch {interp delete a}
+ interp create a
+} -body {
+ interp alias a a {} setx
+ catch {a eval a 1 2}
+ set ::errorInfo
+} -cleanup {
+ rename setx {}
+ interp delete a
+} -result {wrong # args: should be "a x"
+ invoked from within
+"a 1 2"
+ invoked from within
+"a eval a 1 2"}
+test interp-14.7 {testing interp-alias: wrong # args} -setup {
+ proc setx x {set x}
+ catch {interp delete a}
+ interp create a
+} -body {
+ interp alias a a {} setx
+ a eval {
+ catch {a 1 2}
+ set ::errorInfo
+ }
+} -cleanup {
+ rename setx {}
+ interp delete a
+} -result {wrong # args: should be "a x"
+ invoked from within
+"a 1 2"}
+test interp-14.8 {testing interp-alias: error messages} -body {
+ proc setx x {return -code error x}
+ interp alias {} a {} setx
+ catch {a 1}
+ set ::errorInfo
+} -cleanup {
+ rename setx {}
+ rename a {}
+} -result {x
+ while executing
+"a 1"}
+test interp-14.9 {testing interp-alias: error messages} -setup {
+ proc setx x {return -code error x}
+ catch {interp delete a}
+ interp create a
+} -body {
+ interp alias a a {} setx
+ catch {a eval a 1}
+ set ::errorInfo
+} -cleanup {
+ rename setx {}
+ interp delete a
+} -result {x
+ invoked from within
+"a 1"
+ invoked from within
+"a eval a 1"}
+test interp-14.10 {testing interp-alias: error messages} -setup {
+ proc setx x {return -code error x}
+ catch {interp delete a}
+ interp create a
+} -body {
+ interp alias a a {} setx
+ a eval {
+ catch {a 1}
+ set ::errorInfo
+ }
+} -cleanup {
+ rename setx {}
+ interp delete a
+} -result {x
+ invoked from within
+"a 1"}
+
# part 15: testing file sharing
test interp-15.1 {testing file sharing} {
@@ -664,14 +754,21 @@ test interp-17.4 {alias loop prevention} {
interp create x
interp alias x b x a
list [catch {x eval rename b a} msg] $msg
-} {1 {cannot define or rename alias "b": would create a loop}}
+} {1 {cannot define or rename alias "a": would create a loop}}
test interp-17.5 {alias loop prevention} {
catch {interp delete x}
interp create x
x alias z l1
interp alias {} l2 x z
list [catch {rename l2 l1} msg] $msg
-} {1 {cannot define or rename alias "l2": would create a loop}}
+} {1 {cannot define or rename alias "l1": would create a loop}}
+test interp-17.6 {alias loop prevention} {
+ catch {interp delete x}
+ interp create x
+ interp alias x a x b
+ x eval rename a c
+ list [catch {x eval rename c b} msg] $msg
+} {1 {cannot define or rename alias "b": would create a loop}}
#
# Test robustness of Tcl_DeleteInterp when applied to a slave interpreter.
@@ -679,86 +776,81 @@ test interp-17.5 {alias loop prevention} {
# the bugs as a core dump.
#
-if {[info commands testinterpdelete] == ""} {
- puts "This application hasn't been compiled with the \"testinterpdelete\""
- puts "command, so I can't test slave delete calls"
-} else {
- test interp-18.1 {testing Tcl_DeleteInterp vs slaves} {
- list [catch {testinterpdelete} msg] $msg
- } {1 {wrong # args: should be "testinterpdelete path"}}
- test interp-18.2 {testing Tcl_DeleteInterp vs slaves} {
- catch {interp delete a}
- interp create a
- testinterpdelete a
- } ""
- test interp-18.3 {testing Tcl_DeleteInterp vs slaves} {
- catch {interp delete a}
- interp create a
- interp create {a b}
- testinterpdelete {a b}
- } ""
- test interp-18.4 {testing Tcl_DeleteInterp vs slaves} {
- catch {interp delete a}
- interp create a
- interp create {a b}
- testinterpdelete a
- } ""
- test interp-18.5 {testing Tcl_DeleteInterp vs slaves} {
- catch {interp delete a}
- interp create a
- interp create {a b}
- interp alias {a b} dodel {} dodel
- proc dodel {x} {testinterpdelete $x}
- list [catch {interp eval {a b} {dodel {a b}}} msg] $msg
- } {0 {}}
- test interp-18.6 {testing Tcl_DeleteInterp vs slaves} {
- catch {interp delete a}
- interp create a
- interp create {a b}
- interp alias {a b} dodel {} dodel
- proc dodel {x} {testinterpdelete $x}
- list [catch {interp eval {a b} {dodel a}} msg] $msg
- } {0 {}}
- test interp-18.7 {eval in deleted interp} {
- catch {interp delete a}
- interp create a
- a eval {
+test interp-18.1 {testing Tcl_DeleteInterp vs slaves} testinterpdelete {
+ list [catch {testinterpdelete} msg] $msg
+} {1 {wrong # args: should be "testinterpdelete path"}}
+test interp-18.2 {testing Tcl_DeleteInterp vs slaves} testinterpdelete {
+ catch {interp delete a}
+ interp create a
+ testinterpdelete a
+} ""
+test interp-18.3 {testing Tcl_DeleteInterp vs slaves} testinterpdelete {
+ catch {interp delete a}
+ interp create a
+ interp create {a b}
+ testinterpdelete {a b}
+} ""
+test interp-18.4 {testing Tcl_DeleteInterp vs slaves} testinterpdelete {
+ catch {interp delete a}
+ interp create a
+ interp create {a b}
+ testinterpdelete a
+} ""
+test interp-18.5 {testing Tcl_DeleteInterp vs slaves} testinterpdelete {
+ catch {interp delete a}
+ interp create a
+ interp create {a b}
+ interp alias {a b} dodel {} dodel
+ proc dodel {x} {testinterpdelete $x}
+ list [catch {interp eval {a b} {dodel {a b}}} msg] $msg
+} {0 {}}
+test interp-18.6 {testing Tcl_DeleteInterp vs slaves} testinterpdelete {
+ catch {interp delete a}
+ interp create a
+ interp create {a b}
+ interp alias {a b} dodel {} dodel
+ proc dodel {x} {testinterpdelete $x}
+ list [catch {interp eval {a b} {dodel a}} msg] $msg
+} {0 {}}
+test interp-18.7 {eval in deleted interp} {
+ catch {interp delete a}
+ interp create a
+ a eval {
+ proc dodel {} {
+ delme
+ dosomething else
+ }
+ proc dosomething args {
+ puts "I should not have been called!!"
+ }
+ }
+ a alias delme dela
+ proc dela {} {interp delete a}
+ list [catch {a eval dodel} msg] $msg
+} {1 {attempt to call eval in deleted interpreter}}
+test interp-18.8 {eval in deleted interp} {
+ catch {interp delete a}
+ interp create a
+ a eval {
+ interp create b
+ b eval {
proc dodel {} {
- delme
- dosomething else
- }
- proc dosomething args {
- puts "I should not have been called!!"
+ dela
}
}
- a alias delme dela
- proc dela {} {interp delete a}
- list [catch {a eval dodel} msg] $msg
- } {1 {attempt to call eval in deleted interpreter}}
- test interp-18.8 {eval in deleted interp} {
- catch {interp delete a}
- interp create a
- a eval {
- interp create b
- b eval {
- proc dodel {} {
- dela
- }
- }
- proc foo {} {
- b eval dela
- dosomething else
- }
- proc dosomething args {
- puts "I should not have been called!!"
- }
+ proc foo {} {
+ b eval dela
+ dosomething else
}
- interp alias {a b} dela {} dela
- proc dela {} {interp delete a}
- list [catch {a eval foo} msg] $msg
- } {1 {attempt to call eval in deleted interpreter}}
-}
-test interp-18.9 {eval in deleted interp, bug 495830} {knownBug} {
+ proc dosomething args {
+ puts "I should not have been called!!"
+ }
+ }
+ interp alias {a b} dela {} dela
+ proc dela {} {interp delete a}
+ list [catch {a eval foo} msg] $msg
+} {1 {attempt to call eval in deleted interpreter}}
+test interp-18.9 {eval in deleted interp, bug 495830} {
interp create tst
interp alias tst suicide {} interp delete tst
list [catch {tst eval {suicide; set a 5}} msg] $msg
@@ -795,7 +887,7 @@ test interp-19.3 {alias deletion} {
catch {interp eval a foo} msg
interp delete a
set msg
-} {invalid command name "zop"}
+} {invalid command name "bar"}
test interp-19.4 {alias deletion} {
catch {interp delete a}
interp create a
@@ -824,7 +916,7 @@ test interp-19.6 {alias deletion} {
set s [interp aliases a]
interp delete a
set s
-} foo
+} {::foo foo}
test interp-19.7 {alias deletion, renaming} {
catch {interp delete a}
interp create a
@@ -860,196 +952,153 @@ test interp-19.9 {alias deletion, renaming} {
} 1156
test interp-20.1 {interp hide, interp expose and interp invokehidden} {
- catch {interp delete a}
- interp create a
- a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
- a eval {proc foo {} {}}
- a hide foo
- catch {a eval foo something} msg
- interp delete a
+ set a [interp create]
+ $a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
+ $a eval {proc foo {} {}}
+ $a hide foo
+ catch {$a eval foo something} msg
+ interp delete $a
set msg
} {invalid command name "foo"}
test interp-20.2 {interp hide, interp expose and interp invokehidden} {
- catch {interp delete a}
- interp create a
- a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
- a hide list
+ set a [interp create]
+ $a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
+ $a hide list
set l ""
- lappend l [catch {a eval {list 1 2 3}} msg]
- lappend l $msg
- a expose list
- lappend l [catch {a eval {list 1 2 3}} msg]
- lappend l $msg
- interp delete a
+ lappend l [catch {$a eval {list 1 2 3}} msg] $msg
+ $a expose list
+ lappend l [catch {$a eval {list 1 2 3}} msg] $msg
+ interp delete $a
set l
} {1 {invalid command name "list"} 0 {1 2 3}}
test interp-20.3 {interp hide, interp expose and interp invokehidden} {
- catch {interp delete a}
- interp create a
- a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
- a hide list
+ set a [interp create]
+ $a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
+ $a hide list
set l ""
- lappend l [catch {a eval {list 1 2 3}} msg]
- lappend l $msg
- lappend l [catch {a invokehidden list 1 2 3} msg]
- lappend l $msg
- a expose list
- lappend l [catch {a eval {list 1 2 3}} msg]
- lappend l $msg
- interp delete a
+ lappend l [catch { $a eval {list 1 2 3} } msg] $msg
+ lappend l [catch { $a invokehidden list 1 2 3 } msg] $msg
+ $a expose list
+ lappend l [catch { $a eval {list 1 2 3} } msg] $msg
+ interp delete $a
set l
} {1 {invalid command name "list"} 0 {1 2 3} 0 {1 2 3}}
test interp-20.4 {interp hide, interp expose and interp invokehidden -- passing {}} {
- catch {interp delete a}
- interp create a
- a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
- a hide list
+ set a [interp create]
+ $a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
+ $a hide list
set l ""
- lappend l [catch {a eval {list 1 2 3}} msg]
- lappend l $msg
- lappend l [catch {a invokehidden list {"" 1 2 3}} msg]
- lappend l $msg
- a expose list
- lappend l [catch {a eval {list 1 2 3}} msg]
- lappend l $msg
- interp delete a
+ lappend l [catch { $a eval {list 1 2 3} } msg] $msg
+ lappend l [catch { $a invokehidden list {"" 1 2 3} } msg] $msg
+ $a expose list
+ lappend l [catch { $a eval {list 1 2 3} } msg] $msg
+ interp delete $a
set l
} {1 {invalid command name "list"} 0 {{"" 1 2 3}} 0 {1 2 3}}
test interp-20.5 {interp hide, interp expose and interp invokehidden -- passing {}} {
- catch {interp delete a}
- interp create a
- a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
- a hide list
+ set a [interp create]
+ $a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
+ $a hide list
set l ""
- lappend l [catch {a eval {list 1 2 3}} msg]
- lappend l $msg
- lappend l [catch {a invokehidden list {{} 1 2 3}} msg]
- lappend l $msg
- a expose list
- lappend l [catch {a eval {list 1 2 3}} msg]
- lappend l $msg
- interp delete a
+ lappend l [catch { $a eval {list 1 2 3} } msg] $msg
+ lappend l [catch { $a invokehidden list {{} 1 2 3} } msg] $msg
+ $a expose list
+ lappend l [catch { $a eval {list 1 2 3} } msg] $msg
+ interp delete $a
set l
} {1 {invalid command name "list"} 0 {{{} 1 2 3}} 0 {1 2 3}}
test interp-20.6 {interp invokehidden -- eval args} {
- catch {interp delete a}
- interp create a
- a hide list
+ set a [interp create]
+ $a hide list
set l ""
set z 45
- lappend l [catch {a invokehidden list $z 1 2 3} msg]
- lappend l $msg
- a expose list
- lappend l [catch {a eval list $z 1 2 3} msg]
- lappend l $msg
- interp delete a
+ lappend l [catch { $a invokehidden list $z 1 2 3 } msg] $msg
+ $a expose list
+ lappend l [catch { $a eval list $z 1 2 3 } msg] $msg
+ interp delete $a
set l
} {0 {45 1 2 3} 0 {45 1 2 3}}
test interp-20.7 {interp invokehidden vs variable eval} {
- catch {interp delete a}
- interp create a
- a hide list
+ set a [interp create]
+ $a hide list
set z 45
- set l ""
- lappend l [catch {a invokehidden list {$z a b c}} msg]
- lappend l $msg
- interp delete a
+ set l [list [catch {$a invokehidden list {$z a b c}} msg] $msg]
+ interp delete $a
set l
} {0 {{$z a b c}}}
test interp-20.8 {interp invokehidden vs variable eval} {
- catch {interp delete a}
- interp create a
- a hide list
- a eval set z 89
+ set a [interp create]
+ $a hide list
+ $a eval set z 89
set z 45
- set l ""
- lappend l [catch {a invokehidden list {$z a b c}} msg]
- lappend l $msg
- interp delete a
+ set l [list [catch {$a invokehidden list {$z a b c}} msg] $msg]
+ interp delete $a
set l
} {0 {{$z a b c}}}
test interp-20.9 {interp invokehidden vs variable eval} {
- catch {interp delete a}
- interp create a
- a hide list
- a eval set z 89
+ set a [interp create]
+ $a hide list
+ $a eval set z 89
set z 45
set l ""
- lappend l [catch {a invokehidden list $z {$z a b c}} msg]
- lappend l $msg
- interp delete a
+ lappend l [catch {$a invokehidden list $z {$z a b c}} msg] $msg
+ interp delete $a
set l
} {0 {45 {$z a b c}}}
test interp-20.10 {interp hide, interp expose and interp invokehidden} {
- catch {interp delete a}
- interp create a
- a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
- a eval {proc foo {} {}}
- interp hide a foo
- catch {interp eval a foo something} msg
- interp delete a
+ set a [interp create]
+ $a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
+ $a eval {proc foo {} {}}
+ interp hide $a foo
+ catch {interp eval $a foo something} msg
+ interp delete $a
set msg
} {invalid command name "foo"}
test interp-20.11 {interp hide, interp expose and interp invokehidden} {
- catch {interp delete a}
- interp create a
- a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
- interp hide a list
+ set a [interp create]
+ $a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
+ interp hide $a list
set l ""
- lappend l [catch {interp eval a {list 1 2 3}} msg]
- lappend l $msg
- interp expose a list
- lappend l [catch {interp eval a {list 1 2 3}} msg]
- lappend l $msg
- interp delete a
+ lappend l [catch {interp eval $a {list 1 2 3}} msg] $msg
+ interp expose $a list
+ lappend l [catch {interp eval $a {list 1 2 3}} msg] $msg
+ interp delete $a
set l
} {1 {invalid command name "list"} 0 {1 2 3}}
test interp-20.12 {interp hide, interp expose and interp invokehidden} {
- catch {interp delete a}
- interp create a
- a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
- interp hide a list
+ set a [interp create]
+ $a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
+ interp hide $a list
set l ""
- lappend l [catch {interp eval a {list 1 2 3}} msg]
- lappend l $msg
- lappend l [catch {interp invokehidden a list 1 2 3} msg]
- lappend l $msg
- interp expose a list
- lappend l [catch {interp eval a {list 1 2 3}} msg]
- lappend l $msg
- interp delete a
+ lappend l [catch {interp eval $a {list 1 2 3} } msg] $msg
+ lappend l [catch {interp invokehidden $a list 1 2 3} msg] $msg
+ interp expose $a list
+ lappend l [catch {interp eval $a {list 1 2 3} } msg] $msg
+ interp delete $a
set l
} {1 {invalid command name "list"} 0 {1 2 3} 0 {1 2 3}}
test interp-20.13 {interp hide, interp expose, interp invokehidden -- passing {}} {
- catch {interp delete a}
- interp create a
- a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
- interp hide a list
+ set a [interp create]
+ $a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
+ interp hide $a list
set l ""
- lappend l [catch {interp eval a {list 1 2 3}} msg]
- lappend l $msg
- lappend l [catch {interp invokehidden a list {"" 1 2 3}} msg]
- lappend l $msg
- interp expose a list
- lappend l [catch {interp eval a {list 1 2 3}} msg]
- lappend l $msg
- interp delete a
+ lappend l [catch {interp eval $a {list 1 2 3} } msg] $msg
+ lappend l [catch {interp invokehidden $a list {"" 1 2 3}} msg] $msg
+ interp expose $a list
+ lappend l [catch {interp eval $a {list 1 2 3} } msg] $msg
+ interp delete $a
set l
} {1 {invalid command name "list"} 0 {{"" 1 2 3}} 0 {1 2 3}}
test interp-20.14 {interp hide, interp expose, interp invokehidden -- passing {}} {
- catch {interp delete a}
- interp create a
- a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
- interp hide a list
+ set a [interp create]
+ $a eval {proc unknown {x args} {error "invalid command name \"$x\""}}
+ interp hide $a list
set l ""
- lappend l [catch {interp eval a {list 1 2 3}} msg]
- lappend l $msg
- lappend l [catch {interp invokehidden a list {{} 1 2 3}} msg]
- lappend l $msg
- interp expose a list
- lappend l [catch {a eval {list 1 2 3}} msg]
- lappend l $msg
- interp delete a
+ lappend l [catch {interp eval $a {list 1 2 3} } msg] $msg
+ lappend l [catch {interp invokehidden $a list {{} 1 2 3}} msg] $msg
+ interp expose $a list
+ lappend l [catch {$a eval {list 1 2 3} } msg] $msg
+ interp delete $a
set l
} {1 {invalid command name "list"} 0 {{{} 1 2 3}} 0 {1 2 3}}
test interp-20.15 {interp invokehidden -- eval args} {
@@ -1540,6 +1589,19 @@ test interp-20.48 {interp hide vs namespaces} {
interp delete a
set l
} {1 {cannot use namespace qualifiers in hidden command token (rename)}}
+test interp-20.49 {interp invokehidden -namespace} -setup {
+ set script [makeFile {
+ set x [namespace current]
+ } script]
+ interp create -safe slave
+} -body {
+ slave invokehidden -namespace ::foo source $script
+ slave eval {set ::foo::x}
+} -cleanup {
+ interp delete slave
+ removeFile script
+} -result ::foo
+
test interp-21.1 {interp hidden} {
interp hidden {}
@@ -1730,35 +1792,17 @@ test interp-23.2 {testing hiding vs aliases} {unixOrPc} {
set l ""
lappend l [lsort [interp hidden a]]
a alias bar bar
- lappend l [interp aliases a]
- lappend l [lsort [interp hidden a]]
- a hide bar
- lappend l [interp aliases a]
- lappend l [lsort [interp hidden a]]
- a alias bar {}
- lappend l [interp aliases a]
- lappend l [lsort [interp hidden a]]
- interp delete a
- set l
-} {{cd encoding exec exit fconfigure file glob load open pwd socket source} bar {cd encoding exec exit fconfigure file glob load open pwd socket source} bar {bar cd encoding exec exit fconfigure file glob load open pwd socket source} {} {cd encoding exec exit fconfigure file glob load open pwd socket source}}
-
-test interp-23.3 {testing hiding vs aliases} {macOnly} {
- catch {interp delete a}
- interp create a -safe
- set l ""
- lappend l [lsort [interp hidden a]]
- a alias bar bar
- lappend l [interp aliases a]
+ lappend l [lsort [interp aliases a]]
lappend l [lsort [interp hidden a]]
a hide bar
- lappend l [interp aliases a]
+ lappend l [lsort [interp aliases a]]
lappend l [lsort [interp hidden a]]
a alias bar {}
- lappend l [interp aliases a]
+ lappend l [lsort [interp aliases a]]
lappend l [lsort [interp hidden a]]
interp delete a
set l
-} {{beep cd echo encoding exit fconfigure file glob load ls open pwd socket source} bar {beep cd echo encoding exit fconfigure file glob load ls open pwd socket source} bar {bar beep cd echo encoding exit fconfigure file glob load ls open pwd socket source} {} {beep cd echo encoding exit fconfigure file glob load ls open pwd socket source}}
+} {{cd encoding exec exit fconfigure file glob load open pwd socket source unload} {::tcl::mathfunc::max ::tcl::mathfunc::min bar clock} {cd encoding exec exit fconfigure file glob load open pwd socket source unload} {::tcl::mathfunc::max ::tcl::mathfunc::min bar clock} {bar cd encoding exec exit fconfigure file glob load open pwd socket source unload} {::tcl::mathfunc::max ::tcl::mathfunc::min clock} {cd encoding exec exit fconfigure file glob load open pwd socket source unload}}
test interp-24.1 {result resetting on error} {
catch {interp delete a}
@@ -1774,6 +1818,7 @@ test interp-24.1 {result resetting on error} {
set l
}]
interp delete a
+ rename foo {}
set l
} {1 {1 2 3} 1 {3 4 5}}
test interp-24.2 {result resetting on error} {
@@ -1790,6 +1835,7 @@ test interp-24.2 {result resetting on error} {
set l
}]
interp delete a
+ rename foo {}
set l
} {1 {1 2 3} 1 {3 4 5}}
test interp-24.3 {result resetting on error} {
@@ -2083,7 +2129,7 @@ test interp-26.6 {result code transmission: all combined--bug 1637} \
proc MyTestAlias {interp args} {
global aliasTrace;
lappend aliasTrace $args;
- eval interp invokehidden [list $interp] $args
+ interp invokehidden $interp {*}$args
}
foreach c {return} {
interp hide $interp $c;
@@ -2113,7 +2159,7 @@ test interp-26.7 {errorInfo transmission: regular interps} {
MyError "some secret"
}
interp alias $interp test {} MyTestAlias $interp;
- set res [interp eval $interp {catch test;set errorInfo}]
+ set res [interp eval $interp {catch test;set ::errorInfo}]
interp delete $interp;
set res
} {msg
@@ -2136,7 +2182,7 @@ test interp-26.8 {errorInfo transmission: safe interps--bug 1637} {knownBug} {
MyError "some secret"
}
interp alias $interp test {} MyTestAlias $interp;
- set res [interp eval $interp {catch test;set errorInfo}]
+ set res [interp eval $interp {catch test;set ::errorInfo}]
interp delete $interp;
set res
} {msg
@@ -2321,6 +2367,23 @@ test interp-28.1 {getting fooled by slave's namespace ?} {
set r
} {}
+test interp-28.2 {master's nsName cache should not cross} {
+ set i [interp create]
+ set res [$i eval {
+ set x {namespace children ::}
+ set y [list namespace children ::]
+ namespace delete [{*}$y]
+ set j [interp create]
+ $j eval {namespace delete {*}[namespace children ::]}
+ namespace eval foo {}
+ set res [list [eval $x] [eval $y] [$j eval $x] [$j eval $y]]
+ interp delete $j
+ set res
+ }]
+ interp delete $i
+ set res
+} {::foo ::foo {} {}}
+
# Part 29: recursion limit
# 29.1.* Argument checking
# 29.2.* Reading and setting the recursion limit
@@ -2908,8 +2971,7 @@ test interp-31.1 {alias invocation scope} {
set result
} ok
-test interp-32.1 { parent's working directory should
- be inherited by a child interp } {
+test interp-32.1 {parent's working directory should be inherited by a child interp} {
cd [temporaryDirectory]
set parent [pwd]
set i [interp create]
@@ -2935,12 +2997,556 @@ test interp-33.1 {refCounting for target words of alias [Bug 730244]} {
# Note: interp names are simple words by default
trace add execution testHelper enter "interp alias $i alias {} ;#"
interp alias $i alias {} testHelper this
- $i eval alias
+ $i eval alias
} this
+test interp-34.1 {basic test of limits - calling commands} -body {
+ set i [interp create]
+ $i eval {
+ proc foobar {} {
+ for {set x 0} {$x<1000000} {incr x} {
+ # Calls to this are not bytecoded away
+ pid
+ }
+ }
+ }
+ $i limit command -value 1000
+ $i eval foobar
+} -returnCodes error -result {command count limit exceeded} -cleanup {
+ interp delete $i
+}
+test interp-34.2 {basic test of limits - bytecoded commands} -body {
+ set i [interp create]
+ $i eval {
+ proc foobar {} {
+ for {set x 0} {$x<1000000} {incr x} {
+ # Calls to this *are* bytecoded away
+ expr {1+2+3}
+ }
+ }
+ }
+ $i limit command -value 1000
+ $i eval foobar
+} -returnCodes error -result {command count limit exceeded} -cleanup {
+ interp delete $i
+}
+test interp-34.3 {basic test of limits - pure bytecode loop} -body {
+ set i [interp create]
+ $i eval {
+ proc foobar {} {
+ while {1} {
+ # No bytecode at all here...
+ }
+ }
+ }
+ # We use a time limit here; command limits don't trap this case
+ $i limit time -seconds [expr {[clock seconds]+2}]
+ $i eval foobar
+} -returnCodes error -result {time limit exceeded} -cleanup {
+ interp delete $i
+}
+test interp-34.3.1 {basic test of limits - pure inside-command loop} -body {
+ set i [interp create]
+ $i eval {
+ proc foobar {} {
+ set while while
+ $while {1} {
+ # No bytecode at all here...
+ }
+ }
+ }
+ # We use a time limit here; command limits don't trap this case
+ $i limit time -seconds [expr {[clock seconds]+2}]
+ $i eval foobar
+} -returnCodes error -result {time limit exceeded} -cleanup {
+ interp delete $i
+}
+test interp-34.4 {limits with callbacks: extending limits} -setup {
+ set i [interp create]
+ set a 0
+ set b 0
+ set c a
+ proc cb1 {} {
+ global c
+ incr ::$c
+ }
+ proc cb2 {newlimit args} {
+ global c i
+ set c b
+ $i limit command -value $newlimit
+ }
+} -body {
+ interp alias $i foo {} cb1
+ set curlim [$i eval info cmdcount]
+ $i limit command -command "cb2 [expr $curlim+100]" \
+ -value [expr {$curlim+10}]
+ $i eval {for {set i 0} {$i<10} {incr i} {foo}}
+ list $a $b $c
+} -result {6 4 b} -cleanup {
+ interp delete $i
+ rename cb1 {}
+ rename cb2 {}
+}
+# The next three tests exercise all the three ways that limit handlers
+# can be deleted. Fully verifying this requires additional source
+# code instrumentation.
+test interp-34.5 {limits with callbacks: removing limits} -setup {
+ set i [interp create]
+ set a 0
+ set b 0
+ set c a
+ proc cb1 {} {
+ global c
+ incr ::$c
+ }
+ proc cb2 {newlimit args} {
+ global c i
+ set c b
+ $i limit command -value $newlimit
+ }
+} -body {
+ interp alias $i foo {} cb1
+ set curlim [$i eval info cmdcount]
+ $i limit command -command "cb2 {}" -value [expr {$curlim+10}]
+ $i eval {for {set i 0} {$i<10} {incr i} {foo}}
+ list $a $b $c
+} -result {6 4 b} -cleanup {
+ interp delete $i
+ rename cb1 {}
+ rename cb2 {}
+}
+test interp-34.6 {limits with callbacks: removing limits and handlers} -setup {
+ set i [interp create]
+ set a 0
+ set b 0
+ set c a
+ proc cb1 {} {
+ global c
+ incr ::$c
+ }
+ proc cb2 {args} {
+ global c i
+ set c b
+ $i limit command -value {} -command {}
+ }
+} -body {
+ interp alias $i foo {} cb1
+ set curlim [$i eval info cmdcount]
+ $i limit command -command cb2 -value [expr {$curlim+10}]
+ $i eval {for {set i 0} {$i<10} {incr i} {foo}}
+ list $a $b $c
+} -result {6 4 b} -cleanup {
+ interp delete $i
+ rename cb1 {}
+ rename cb2 {}
+}
+test interp-34.7 {limits with callbacks: deleting the handler interp} -setup {
+ set i [interp create]
+ $i eval {
+ set i [interp create]
+ proc cb1 {} {
+ global c
+ incr ::$c
+ }
+ proc cb2 {args} {
+ global c i curlim
+ set c b
+ $i limit command -value [expr {$curlim+1000}]
+ trapToParent
+ }
+ }
+ proc cb3 {} {
+ global i subi
+ interp alias [list $i $subi] foo {} cb4
+ interp delete $i
+ }
+ proc cb4 {} {
+ global n
+ incr n
+ }
+} -body {
+ set subi [$i eval set i]
+ interp alias $i trapToParent {} cb3
+ set n 0
+ $i eval {
+ set a 0
+ set b 0
+ set c a
+ interp alias $i foo {} cb1
+ set curlim [$i eval info cmdcount]
+ $i limit command -command cb2 -value [expr {$curlim+10}]
+ }
+ $i eval {
+ $i eval {
+ for {set i 0} {$i<10} {incr i} {foo}
+ }
+ }
+ list $n [interp exists $i]
+} -result {4 0} -cleanup {
+ rename cb3 {}
+ rename cb4 {}
+}
+# Bug 1085023
+test interp-34.8 {time limits trigger in vwaits} -body {
+ set i [interp create]
+ interp limit $i time -seconds [expr {[clock seconds]+1}] -granularity 1
+ $i eval {
+ set x {}
+ vwait x
+ }
+} -cleanup {
+ interp delete $i
+} -returnCodes error -result {limit exceeded}
+test interp-34.9 {time limits trigger in blocking after} {
+ set i [interp create]
+ set t0 [clock seconds]
+ interp limit $i time -seconds [expr {$t0 + 1}] -granularity 1
+ set code [catch {
+ $i eval {after 10000}
+ } msg]
+ set t1 [clock seconds]
+ interp delete $i
+ list $code $msg [expr {($t1-$t0) < 3 ? "OK" : $t1-$t0}]
+} {1 {time limit exceeded} OK}
+test interp-34.10 {time limits trigger in vwaits: Bug 1221395} -body {
+ set i [interp create]
+ # Assume someone hasn't set the clock to early 1970!
+ $i limit time -seconds 1 -granularity 4
+ interp alias $i log {} lappend result
+ set result {}
+ catch {
+ $i eval {
+ log 1
+ after 100
+ log 2
+ }
+ } msg
+ interp delete $i
+ lappend result $msg
+} -result {1 {time limit exceeded}}
+test interp-34.11 {time limit extension in callbacks} -setup {
+ proc cb1 {i t} {
+ global result
+ lappend result cb1
+ $i limit time -seconds $t -command cb2
+ }
+ proc cb2 {} {
+ global result
+ lappend result cb2
+ }
+} -body {
+ set i [interp create]
+ set t0 [clock seconds]
+ $i limit time -seconds [expr {$t0+1}] -granularity 1 \
+ -command "cb1 $i [expr {$t0+2}]"
+ set ::result {}
+ lappend ::result [catch {
+ $i eval {
+ for {set i 0} {$i<30} {incr i} {
+ after 100
+ }
+ }
+ } msg] $msg
+ set t1 [clock seconds]
+ lappend ::result [expr {$t1-$t0>=2 ? "ok" : "$t0,$t1"}]
+ interp delete $i
+ return $::result
+} -result {cb1 cb2 1 {time limit exceeded} ok} -cleanup {
+ rename cb1 {}
+ rename cb2 {}
+}
+test interp-34.12 {time limit extension in callbacks} -setup {
+ proc cb1 {i} {
+ global result times
+ lappend result cb1
+ set times [lassign $times t]
+ $i limit time -seconds $t
+ }
+} -body {
+ set i [interp create]
+ set t0 [clock seconds]
+ set ::times "[expr {$t0+2}] [expr {$t0+100}]"
+ $i limit time -seconds [expr {$t0+1}] -granularity 1 -command "cb1 $i"
+ set ::result {}
+ lappend ::result [catch {
+ $i eval {
+ for {set i 0} {$i<30} {incr i} {
+ after 100
+ }
+ }
+ } msg] $msg
+ set t1 [clock seconds]
+ lappend ::result [expr {$t1-$t0>=2 ? "ok" : "$t0,$t1"}]
+ interp delete $i
+ return $::result
+} -result {cb1 cb1 0 {} ok} -cleanup {
+ rename cb1 {}
+}
+test interp-34.13 {time limit granularity and vwait: Bug 2891362} -setup {
+ set i [interp create -safe]
+} -body {
+ $i limit time -seconds [clock add [clock seconds] 1 second]
+ $i eval {
+ after 2000 set x timeout
+ vwait x
+ return $x
+ }
+} -cleanup {
+ interp delete $i
+} -returnCodes error -result {limit exceeded}
+
+test interp-35.1 {interp limit syntax} -body {
+ interp limit
+} -returnCodes error -result {wrong # args: should be "interp limit path limitType ?options?"}
+test interp-35.2 {interp limit syntax} -body {
+ interp limit {}
+} -returnCodes error -result {wrong # args: should be "interp limit path limitType ?options?"}
+test interp-35.3 {interp limit syntax} -body {
+ interp limit {} foo
+} -returnCodes error -result {bad limit type "foo": must be commands or time}
+test interp-35.4 {interp limit syntax} -body {
+ set i [interp create]
+ set dict [interp limit $i commands]
+ set result {}
+ foreach key [lsort [dict keys $dict]] {
+ lappend result $key [dict get $dict $key]
+ }
+ set result
+} -cleanup {
+ interp delete $i
+} -result {-command {} -granularity 1 -value {}}
+test interp-35.5 {interp limit syntax} -body {
+ set i [interp create]
+ interp limit $i commands -granularity
+} -cleanup {
+ interp delete $i
+} -result 1
+test interp-35.6 {interp limit syntax} -body {
+ set i [interp create]
+ interp limit $i commands -granularity 2
+} -cleanup {
+ interp delete $i
+} -result {}
+test interp-35.7 {interp limit syntax} -body {
+ set i [interp create]
+ interp limit $i commands -foobar
+} -cleanup {
+ interp delete $i
+} -returnCodes error -result {bad option "-foobar": must be -command, -granularity, or -value}
+test interp-35.8 {interp limit syntax} -body {
+ set i [interp create]
+ interp limit $i commands -granularity foobar
+} -cleanup {
+ interp delete $i
+} -returnCodes error -result {expected integer but got "foobar"}
+test interp-35.9 {interp limit syntax} -body {
+ set i [interp create]
+ interp limit $i commands -granularity 0
+} -cleanup {
+ interp delete $i
+} -returnCodes error -result {granularity must be at least 1}
+test interp-35.10 {interp limit syntax} -body {
+ set i [interp create]
+ interp limit $i commands -value foobar
+} -cleanup {
+ interp delete $i
+} -returnCodes error -result {expected integer but got "foobar"}
+test interp-35.11 {interp limit syntax} -body {
+ set i [interp create]
+ interp limit $i commands -value -1
+} -cleanup {
+ interp delete $i
+} -returnCodes error -result {command limit value must be at least 0}
+test interp-35.12 {interp limit syntax} -body {
+ set i [interp create]
+ set dict [interp limit $i time]
+ set result {}
+ foreach key [lsort [dict keys $dict]] {
+ lappend result $key [dict get $dict $key]
+ }
+ set result
+} -cleanup {
+ interp delete $i
+} -result {-command {} -granularity 10 -milliseconds {} -seconds {}}
+test interp-35.13 {interp limit syntax} -body {
+ set i [interp create]
+ interp limit $i time -granularity
+} -cleanup {
+ interp delete $i
+} -result 10
+test interp-35.14 {interp limit syntax} -body {
+ set i [interp create]
+ interp limit $i time -granularity 2
+} -cleanup {
+ interp delete $i
+} -result {}
+test interp-35.15 {interp limit syntax} -body {
+ set i [interp create]
+ interp limit $i time -foobar
+} -cleanup {
+ interp delete $i
+} -returnCodes error -result {bad option "-foobar": must be -command, -granularity, -milliseconds, or -seconds}
+test interp-35.16 {interp limit syntax} -body {
+ set i [interp create]
+ interp limit $i time -granularity foobar
+} -cleanup {
+ interp delete $i
+} -returnCodes error -result {expected integer but got "foobar"}
+test interp-35.17 {interp limit syntax} -body {
+ set i [interp create]
+ interp limit $i time -granularity 0
+} -cleanup {
+ interp delete $i
+} -returnCodes error -result {granularity must be at least 1}
+test interp-35.18 {interp limit syntax} -body {
+ set i [interp create]
+ interp limit $i time -seconds foobar
+} -cleanup {
+ interp delete $i
+} -returnCodes error -result {expected integer but got "foobar"}
+test interp-35.19 {interp limit syntax} -body {
+ set i [interp create]
+ interp limit $i time -seconds -1
+} -cleanup {
+ interp delete $i
+} -returnCodes error -result {seconds must be at least 0}
+test interp-35.20 {interp limit syntax} -body {
+ set i [interp create]
+ interp limit $i time -millis foobar
+} -cleanup {
+ interp delete $i
+} -returnCodes error -result {expected integer but got "foobar"}
+test interp-35.21 {interp limit syntax} -body {
+ set i [interp create]
+ interp limit $i time -millis -1
+} -cleanup {
+ interp delete $i
+} -returnCodes error -result {milliseconds must be at least 0}
+test interp-35.22 {interp time limits normalize milliseconds} -body {
+ set i [interp create]
+ interp limit $i time -seconds 1 -millis 1500
+ list [$i limit time -seconds] [$i limit time -millis]
+} -cleanup {
+ interp delete $i
+} -result {2 500}
+
+test interp-36.1 {interp bgerror syntax} -body {
+ interp bgerror
+} -returnCodes error -result {wrong # args: should be "interp bgerror path ?cmdPrefix?"}
+test interp-36.2 {interp bgerror syntax} -body {
+ interp bgerror x y z
+} -returnCodes error -result {wrong # args: should be "interp bgerror path ?cmdPrefix?"}
+test interp-36.3 {interp bgerror syntax} -setup {
+ interp create slave
+} -body {
+ slave bgerror x y
+} -cleanup {
+ interp delete slave
+} -returnCodes error -result {wrong # args: should be "slave bgerror ?cmdPrefix?"}
+test interp-36.4 {SlaveBgerror syntax} -setup {
+ interp create slave
+} -body {
+ slave bgerror \{
+} -cleanup {
+ interp delete slave
+} -returnCodes error -result {cmdPrefix must be list of length >= 1}
+test interp-36.5 {SlaveBgerror syntax} -setup {
+ interp create slave
+} -body {
+ slave bgerror {}
+} -cleanup {
+ interp delete slave
+} -returnCodes error -result {cmdPrefix must be list of length >= 1}
+test interp-36.6 {SlaveBgerror returns handler} -setup {
+ interp create slave
+} -body {
+ slave bgerror {foo bar soom}
+} -cleanup {
+ interp delete slave
+} -result {foo bar soom}
+
+test interp-36.7 {SlaveBgerror sets error handler of slave [1999035]} -setup {
+ interp create slave
+ slave alias handler handler
+ slave bgerror handler
+ variable result {untouched}
+ proc handler {args} {
+ variable result
+ set result [lindex $args 0]
+ }
+} -body {
+ slave eval {
+ variable done {}
+ after 0 error foo
+ after 10 [list ::set [namespace which -variable done] {}]
+ vwait [namespace which -variable done]
+ }
+ set result
+} -cleanup {
+ variable result {}
+ unset result
+ interp delete slave
+} -result foo
+
+test interp-37.1 {safe interps and min() and max(): Bug 2895741} -setup {
+ catch {interp delete a}
+ interp create a
+ set result {}
+} -body {
+ interp create {a b} -safe
+ lappend result [interp eval a {expr min(5,2,3)*max(7,13,11)}]
+ lappend result [interp eval {a b} {expr min(5,2,3)*max(7,13,11)}]
+} -cleanup {
+ unset result
+ interp delete a
+} -result {26 26}
+
+test interp-38.1 {interp debug one-way switch} -setup {
+ catch {interp delete a}
+ interp create a
+ interp debug a -frame 1
+} -body {
+ # TIP #3xx interp debug frame is a one-way switch
+ interp debug a -frame 0
+} -cleanup {
+ interp delete a
+} -result {1}
+test interp-38.2 {interp debug env var} -setup {
+ catch {interp delete a}
+ set ::env(TCL_INTERP_DEBUG_FRAME) 1
+ interp create a
+} -body {
+ interp debug a
+} -cleanup {
+ unset ::env(TCL_INTERP_DEBUG_FRAME)
+ interp delete a
+} -result {-frame 1}
+test interp-38.3 {interp debug wrong args} -body {
+ interp debug
+} -returnCodes {
+ error
+} -result {wrong # args: should be "interp debug path ?-frame ?bool??"}
+test interp-38.4 {interp debug basic setup} -body {
+ interp debug {}
+} -result {-frame 0}
+test interp-38.5 {interp debug basic setup} -body {
+ interp debug {} -f
+} -result {0}
+test interp-38.6 {interp debug basic setup} -body {
+ interp debug -frames
+} -returnCodes error -result {could not find interpreter "-frames"}
+test interp-38.7 {interp debug basic setup} -body {
+ interp debug {} -frames
+} -returnCodes error -result {bad debug option "-frames": must be -frame}
+test interp-38.8 {interp debug basic setup} -body {
+ interp debug {} -frame 0 bogus
+} -returnCodes {
+ error
+} -result {wrong # args: should be "interp debug path ?-frame ?bool??"}
+
# cleanup
foreach i [interp slaves] {
- interp delete $i
+ interp delete $i
}
::tcltest::cleanupTests
return
diff --git a/tests/io.test b/tests/io.test
index ed2619a..129d741 100644
--- a/tests/io.test
+++ b/tests/io.test
@@ -18,25 +18,38 @@ if {[catch {package require tcltest 2}]} {
return
}
namespace eval ::tcl::test::io {
-
- namespace import ::tcltest::cleanupTests
- namespace import ::tcltest::interpreter
- namespace import ::tcltest::makeFile
- namespace import ::tcltest::removeFile
- namespace import ::tcltest::test
- namespace import ::tcltest::testConstraint
- namespace import ::tcltest::viewFile
-
-testConstraint testchannel [llength [info commands testchannel]]
-testConstraint exec [llength [info commands exec]]
-testConstraint openpipe 1
-testConstraint fileevent [llength [info commands fileevent]]
-testConstraint fcopy [llength [info commands fcopy]]
+ namespace import ::tcltest::*
+
+ variable umaskValue
+ variable path
+ variable f
+ variable i
+ variable n
+ variable v
+ variable msg
+ variable expected
+
+testConstraint testchannel [llength [info commands testchannel]]
+testConstraint exec [llength [info commands exec]]
+testConstraint openpipe 1
+testConstraint fileevent [llength [info commands fileevent]]
+testConstraint fcopy [llength [info commands fcopy]]
+testConstraint testfevent [llength [info commands testfevent]]
+testConstraint testchannelevent [llength [info commands testchannelevent]]
+testConstraint testmainthread [llength [info commands testmainthread]]
+testConstraint testthread [llength [info commands testthread]]
# You need a *very* special environment to do some tests. In
# particular, many file systems do not support large-files...
testConstraint largefileSupport 0
+# some tests can only be run is umask is 2
+# if "umask" cannot be run, the tests will be skipped.
+set umaskValue 0
+testConstraint umask [expr {![catch {set umaskValue [scan [exec /bin/sh -c umask] %o]}]}]
+
+testConstraint makeFileInHome [expr {![file exists ~/_test_] && [file writable ~]}]
+
# set up a long data file for some of the following tests
set path(longfile) [makeFile {} longfile]
@@ -81,9 +94,7 @@ proc contents {file} {
test io-1.5 {Tcl_WriteChars: CheckChannelErrors} {emptyTest} {
# no test, need to cause an async error.
} {}
-
set path(test1) [makeFile {} test1]
-
test io-1.6 {Tcl_WriteChars: WriteBytes} {
set f [open $path(test1) w]
fconfigure $f -encoding binary
@@ -98,9 +109,7 @@ test io-1.7 {Tcl_WriteChars: WriteChars} {
close $f
contents $path(test1)
} "a\x93\xe1\x00"
-
set path(test2) [makeFile {} test2]
-
test io-1.8 {Tcl_WriteChars: WriteChars} {
# This test written for SF bug #506297.
#
@@ -414,7 +423,7 @@ test io-6.1 {Tcl_GetsObj: working} {
close $f
set x
} {foo}
-test io-6.2 {Tcl_GetsObj: CheckChannelErrors() != 0} {
+test io-6.2 {Tcl_GetsObj: CheckChannelErrors() != 0} emptyTest {
# no test, need to cause an async error.
} {}
test io-6.3 {Tcl_GetsObj: how many have we used?} {
@@ -498,9 +507,7 @@ test io-6.9 {Tcl_GetsObj: remember if EOF is seen} {
close $f
set x
} {11 abcdefghijk 3 wom}
-
# Comprehensive tests
-
test io-6.10 {Tcl_GetsObj: lf mode: no chars} {
set f [open $path(test1) w]
close $f
@@ -1228,12 +1235,11 @@ test io-8.7 {PeekAhead: cleanup} {stdio testchannel openpipe fileevent} {
close $f
set x
} {15 abcdefghijklmno 1 -1 {}}
-
-test io-9.1 {CommonGetsCleanup} {
+test io-9.1 {CommonGetsCleanup} emptyTest {
} {}
-test io-10.1 {Tcl_ReadChars: CheckChannelErrors} {
+test io-10.1 {Tcl_ReadChars: CheckChannelErrors} emptyTest {
# no test, need to cause an async error.
} {}
test io-10.2 {Tcl_ReadChars: loop until enough copied} {
@@ -1343,7 +1349,7 @@ test io-11.4 {ReadBytes: EOF char found} {
close $f
set x
} [list "abcdefghijkl" 1 "" 1]
-
+
test io-12.1 {ReadChars: want to read a lot} {
# ((unsigned) toRead > (unsigned) srcLen)
@@ -1603,17 +1609,13 @@ test io-13.12 {TranslateInputEOL: find EOF char in src} {
close $f
set x
} "\n\n\nab\n\nd"
-
+
# Test standard handle management. The functions tested are
# Tcl_SetStdChannel and Tcl_GetStdChannel. Incidentally we are
# also testing channel table management.
if {[info commands testchannel] != ""} {
- if {$tcl_platform(platform) == "macintosh"} {
- set consoleFileNames [list console0 console1 console2]
- } else {
- set consoleFileNames [lsort [testchannel open]]
- }
+ set consoleFileNames [lsort [testchannel open]]
} else {
# just to avoid an error
set consoleFileNames [list]
@@ -1636,9 +1638,7 @@ test io-14.2 {Tcl_SetStdChannel and Tcl_GetStdChannel} {
interp delete x
set l
} {line line none}
-
set path(test3) [makeFile {} test3]
-
test io-14.3 {Tcl_SetStdChannel & Tcl_GetStdChannel} {exec openpipe} {
set f [open $path(test1) w]
puts -nonewline $f {
@@ -1669,7 +1669,7 @@ out
} {err
}}
# This test relies on the fact that the smallest available fd is used first.
-test io-14.4 {Tcl_SetStdChannel & Tcl_GetStdChannel} {exec unixOnly} {
+test io-14.4 {Tcl_SetStdChannel & Tcl_GetStdChannel} {exec unix} {
set f [open $path(test1) w]
puts -nonewline $f { close stdin
close stdout
@@ -1728,9 +1728,7 @@ test io-14.7 {Tcl_GetChannel: stdio name translation} {
interp delete z
set result
} {{} {} {can not find channel named "stderr"}}
-
set path(script) [makeFile {} script]
-
test io-14.8 {reuse of stdio special channels} {stdio openpipe} {
file delete $path(script)
file delete $path(test1)
@@ -1753,7 +1751,6 @@ test io-14.8 {reuse of stdio special channels} {stdio openpipe} {
close $f
set c
} hello
-
test io-14.9 {reuse of stdio special channels} {stdio openpipe fileevent} {
file delete $path(script)
file delete $path(test1)
@@ -1780,10 +1777,10 @@ test io-14.9 {reuse of stdio special channels} {stdio openpipe fileevent} {
set c
} hello
-test io-15.1 {Tcl_CreateCloseHandler} {
+test io-15.1 {Tcl_CreateCloseHandler} emptyTest {
} {}
-test io-16.1 {Tcl_DeleteCloseHandler} {
+test io-16.1 {Tcl_DeleteCloseHandler} emptyTest {
} {}
# Test channel table management. The functions tested are
@@ -1831,7 +1828,7 @@ test io-17.3 {GetChannelTable, DeleteChannelTable on std handles} {testchannel}
} {0 1 0}
test io-18.1 {Tcl_RegisterChannel, Tcl_UnregisterChannel} {testchannel} {
- file delete $path(test1)
+ file delete -force $path(test1)
set l ""
set f [open $path(test1) w]
lappend l [lindex [testchannel info $f] 15]
@@ -1845,7 +1842,7 @@ test io-18.1 {Tcl_RegisterChannel, Tcl_UnregisterChannel} {testchannel} {
[list 1 [format "can not find channel named \"%s\"" $f]]
} 0
test io-18.2 {Tcl_RegisterChannel, Tcl_UnregisterChannel} {testchannel} {
- file delete $path(test1)
+ file delete -force $path(test1)
set l ""
set f [open $path(test1) w]
lappend l [lindex [testchannel info $f] 15]
@@ -1924,27 +1921,19 @@ test io-20.1 {Tcl_CreateChannel: initial settings} {
close $a
set x
} {ascii}
-test io-20.2 {Tcl_CreateChannel: initial settings} {pcOnly} {
+test io-20.2 {Tcl_CreateChannel: initial settings} {win} {
set f [open $path(test1) w+]
set x [list [fconfigure $f -eofchar] [fconfigure $f -translation]]
close $f
set x
} [list [list \x1a ""] {auto crlf}]
-test io-20.3 {Tcl_CreateChannel: initial settings} {unixOnly} {
+test io-20.3 {Tcl_CreateChannel: initial settings} {unix} {
set f [open $path(test1) w+]
set x [list [fconfigure $f -eofchar] [fconfigure $f -translation]]
close $f
set x
} {{{} {}} {auto lf}}
-test io-20.4 {Tcl_CreateChannel: initial settings} {macOnly} {
- set f [open $path(test1) w+]
- set x [list [fconfigure $f -eofchar] [fconfigure $f -translation]]
- close $f
- set x
-} {{{} {}} {auto cr}}
-
set path(stdout) [makeFile {} stdout]
-
test io-20.5 {Tcl_CreateChannel: install channel in empty slot} {stdio openpipe} {
set f [open $path(script) w]
puts -nonewline $f {
@@ -1960,17 +1949,17 @@ test io-20.5 {Tcl_CreateChannel: install channel in empty slot} {stdio openpipe}
catch {close $f} msg
set msg
} {777}
-
-test io-21.1 {CloseChannelsOnExit} {
+
+test io-21.1 {CloseChannelsOnExit} emptyTest {
} {}
-
+
# Test management of attributes associated with a channel, such as
# its default translation, its name and type, etc. The functions
# tested in this group are Tcl_GetChannelName,
# Tcl_GetChannelType and Tcl_GetChannelFile. Tcl_GetChannelInstanceData
# not tested because files do not use the instance data.
-test io-22.1 {Tcl_GetChannelMode} {
+test io-22.1 {Tcl_GetChannelMode} emptyTest {
# Not used anywhere in Tcl.
} {}
@@ -2093,10 +2082,8 @@ test io-27.5 {FlushChannel, implicit flush when buffer fills and on close} \
lappend l [file size $path(test1)]
set l
} {0 60 72}
-
set path(pipe) [makeFile {} pipe]
set path(output) [makeFile {} output]
-
test io-27.6 {FlushChannel, async flushing, async close} \
{stdio asyncPipeClose openpipe} {
file delete $path(pipe)
@@ -2124,9 +2111,8 @@ test io-27.6 {FlushChannel, async flushing, async close} \
close $f
set counter 0
while {([file size $path(output)] < 65536) && ($counter < 1000)} {
- incr counter
- after 20
- update
+ after 20 [list incr [namespace which -variable counter]]
+ vwait [namespace which -variable counter]
}
if {$counter == 1000} {
set result "file size only [file size $path(output)]"
@@ -2201,9 +2187,8 @@ test io-28.3 {CloseChannel, not called before output queue is empty} \
close $f
set counter 0
while {([file size $path(output)] < 20480) && ($counter < 1000)} {
- incr counter
- after 20
- update
+ after 20 [list incr [namespace which -variable counter]]
+ vwait [namespace which -variable counter]
}
if {$counter == 1000} {
set result probably_broken
@@ -2220,11 +2205,11 @@ test io-28.4 {Tcl_Close} {testchannel} {
close $f
lappend l [lsort [testchannel open]]
set x [list $consoleFileNames \
- [lsort [eval list $consoleFileNames $f]] \
+ [lsort [list {*}$consoleFileNames $f]] \
$consoleFileNames]
string compare $l $x
} 0
-test io-28.5 {Tcl_Close vs standard handles} {stdio unixOnly testchannel openpipe} {
+test io-28.5 {Tcl_Close vs standard handles} {stdio unix testchannel openpipe} {
file delete $path(script)
set f [open $path(script) w]
puts $f {
@@ -2299,7 +2284,6 @@ test io-29.6 {Tcl_WriteChars, buffering in no buffering mode} {testchannel} {
close $f
set l
} {0 5 0 11}
-
test io-29.7 {Tcl_Flush, full buffering} {testchannel} {
file delete $path(test1)
set f [open $path(test1) w]
@@ -2622,11 +2606,11 @@ test io-29.27 {Tcl_Flush on closed pipeline} {stdio openpipe} {
# you disable the debugger's signal interception.
#
if {[catch {flush $f} msg]} {
- set x [list 1 $msg $errorCode]
+ set x [list 1 $msg $::errorCode]
catch {close $f}
} else {
if {[catch {close $f} msg]} {
- set x [list 1 $msg $errorCode]
+ set x [list 1 $msg $::errorCode]
} else {
set x {this was supposed to fail and did not}
}
@@ -2686,15 +2670,19 @@ test io-29.31 {Tcl_WriteChars, background flush} {stdio openpipe} {
close $f
set counter 0
while {([file size $path(output)] < 65536) && ($counter < 1000)} {
- incr counter
- after 5
- update
+ after 10 [list incr [namespace which -variable counter]]
+ vwait [namespace which -variable counter]
}
if {$counter == 1000} {
set result "file size only [file size $path(output)]"
} else {
set result ok
}
+ # allow a little time for the background process to close.
+ # otherwise, the following test fails on the [file delete $path(output)
+ # on Windows because a process still has the file open.
+ after 100 set v 1; vwait v
+ set result
} ok
test io-29.32 {Tcl_WriteChars, background flush to slow reader} \
{stdio asyncPipeClose openpipe} {
@@ -2724,9 +2712,8 @@ test io-29.32 {Tcl_WriteChars, background flush to slow reader} \
close $f
set counter 0
while {([file size $path(output)] < 65536) && ($counter < 1000)} {
- incr counter
- after 20
- update
+ after 20 [list incr [namespace which -variable counter]]
+ vwait [namespace which -variable counter]
}
if {$counter == 1000} {
set result "file size only [file size $path(output)]"
@@ -2768,7 +2755,7 @@ test io-29.34 {Tcl_Close, async flush on close, using sockets} {socket tempNotMa
variable c
variable x
set l [gets $s]
-
+
if {[eof $s]} {
close $s
set x done
@@ -2776,8 +2763,8 @@ test io-29.34 {Tcl_Close, async flush on close, using sockets} {socket tempNotMa
incr c
}
}
- set ss [socket -server [namespace code accept] 0]
- set cs [socket [info hostname] [lindex [fconfigure $ss -sockname] 2]]
+ set ss [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
+ set cs [socket 127.0.0.1 [lindex [fconfigure $ss -sockname] 2]]
vwait [namespace which -variable x]
fconfigure $cs -blocking off
writelots $cs $l
@@ -2787,19 +2774,19 @@ test io-29.34 {Tcl_Close, async flush on close, using sockets} {socket tempNotMa
set c
} 2000
test io-29.35 {Tcl_Close vs fileevent vs multiple interpreters} {socket tempNotMac fileevent} {
- # On Mac, this test screws up sockets such that subsequent tests using port 2828
+ # On Mac, this test screws up sockets such that subsequent tests using port 2828
# either cause errors or panic().
-
+
catch {interp delete x}
catch {interp delete y}
interp create x
interp create y
- set s [socket -server [namespace code accept] 0]
+ set s [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
proc accept {s a p} {
puts $s hello
close $s
}
- set c [socket [info hostname] [lindex [fconfigure $s -sockname] 2]]
+ set c [socket 127.0.0.1 [lindex [fconfigure $s -sockname] 2]]
interp share {} $c x
interp share {} $c y
close $c
@@ -2986,7 +2973,6 @@ there
and
here
} auto}
-
test io-30.13 {Tcl_Write crlf on block boundary, Tcl_Read auto} {
file delete $path(test1)
set f [open $path(test1) w]
@@ -3003,7 +2989,6 @@ test io-30.13 {Tcl_Write crlf on block boundary, Tcl_Read auto} {
close $f
string length $c
} [expr 700*15+1]
-
test io-30.14 {Tcl_Write crlf on block boundary, Tcl_Read crlf} {
file delete $path(test1)
set f [open $path(test1) w]
@@ -3020,7 +3005,6 @@ test io-30.14 {Tcl_Write crlf on block boundary, Tcl_Read crlf} {
close $f
string length $c
} [expr 700*15+1]
-
test io-30.15 {Tcl_Write mixed, Tcl_Read auto} {
file delete $path(test1)
set f [open $path(test1) w]
@@ -3053,7 +3037,7 @@ there
and
here
}
-test io-30.17 {Tcl_Write, implicit ^Z at end, Tcl_Read auto} {pcOnly} {
+test io-30.17 {Tcl_Write, implicit ^Z at end, Tcl_Read auto} {win} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -eofchar \x1a -translation lf
@@ -3859,7 +3843,6 @@ test io-31.32 {Tcl_Write crlf on block boundary, Tcl_Gets auto} {
string length $c
} [expr 700*15+1]
-
# Test Tcl_Read and buffering.
test io-32.1 {Tcl_Read, channel not readable} {
@@ -3873,7 +3856,7 @@ test io-32.3 {Tcl_Read, negative byte count} {
set l [list [catch {read $f -1} msg] $msg]
close $f
set l
-} {1 {bad argument "-1": should be "nonewline"}}
+} {1 {expected non-negative integer but got "-1"}}
test io-32.4 {Tcl_Read, positive byte count} {
set f [open $path(longfile) r]
set x [read $f 1024]
@@ -4289,9 +4272,7 @@ test io-34.9 {Tcl_Seek, testing buffered input flushing} {
close $f
set x
} {a d a l Y {} b}
-
set path(test3) [makeFile {} test3]
-
test io-34.10 {Tcl_Seek testing flushing of buffered input} {
set f [open $path(test3) w]
fconfigure $f -translation lf
@@ -4369,7 +4350,7 @@ test io-34.15 {Tcl_Tell combined with seeking} {
close $f1
list $c1 $c2
} {10 20}
-test io-34.16 {Tcl_tell on pipe: always -1} {stdio openpipe} {
+test io-34.16 {Tcl_Tell on pipe: always -1} {stdio openpipe} {
set f1 [open "|[list [interpreter]]" r+]
set c [tell $f1]
close $f1
@@ -4876,7 +4857,6 @@ test io-38.2 {Tcl_SetChannelBufferSize, Tcl_GetChannelBufferSize} {
close $f
set l
} {4096 10000 1 1 1 100000 1048576}
-
test io-38.3 {Tcl_SetChannelBufferSize, changing buffersize between reads} {
# This test crashes the interp if Bug #427196 is not fixed
@@ -5114,11 +5094,10 @@ test io-39.17 {Tcl_SetChannelOption: -encoding, clearing CHANNEL_NEED_MORE_DATA}
close $f
set x
} "{} timeout {} timeout \xe7 timeout"
-
test io-39.18 {Tcl_SetChannelOption, setting read mode independently} \
{socket} {
proc accept {s a p} {close $s}
- set s1 [socket -server [namespace code accept] 0]
+ set s1 [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
set port [lindex [fconfigure $s1 -sockname] 2]
set s2 [socket 127.0.0.1 $port]
update
@@ -5131,7 +5110,7 @@ test io-39.18 {Tcl_SetChannelOption, setting read mode independently} \
test io-39.19 {Tcl_SetChannelOption, setting read mode independently} \
{socket} {
proc accept {s a p} {close $s}
- set s1 [socket -server [namespace code accept] 0]
+ set s1 [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
set port [lindex [fconfigure $s1 -sockname] 2]
set s2 [socket 127.0.0.1 $port]
update
@@ -5144,7 +5123,7 @@ test io-39.19 {Tcl_SetChannelOption, setting read mode independently} \
test io-39.20 {Tcl_SetChannelOption, setting read mode independently} \
{socket} {
proc accept {s a p} {close $s}
- set s1 [socket -server [namespace code accept] 0]
+ set s1 [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
set port [lindex [fconfigure $s1 -sockname] 2]
set s2 [socket 127.0.0.1 $port]
update
@@ -5157,7 +5136,7 @@ test io-39.20 {Tcl_SetChannelOption, setting read mode independently} \
test io-39.21 {Tcl_SetChannelOption, setting read mode independently} \
{socket} {
proc accept {s a p} {close $s}
- set s1 [socket -server [namespace code accept] 0]
+ set s1 [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
set port [lindex [fconfigure $s1 -sockname] 2]
set s2 [socket 127.0.0.1 $port]
update
@@ -5167,8 +5146,7 @@ test io-39.21 {Tcl_SetChannelOption, setting read mode independently} \
close $s2
set modes
} {auto crlf}
-
-test io-39.22 {Tcl_SetChannelOption, invariance} {unixOnly} {
+test io-39.22 {Tcl_SetChannelOption, invariance} {unix} {
file delete $path(test1)
set f1 [open $path(test1) w+]
set l ""
@@ -5180,7 +5158,6 @@ test io-39.22 {Tcl_SetChannelOption, invariance} {unixOnly} {
close $f1
set l
} {{{} {}} {O G} {D D}}
-
test io-39.22a {Tcl_SetChannelOption, invariance} {
file delete $path(test1)
set f1 [open $path(test1) w+]
@@ -5193,12 +5170,10 @@ test io-39.22a {Tcl_SetChannelOption, invariance} {
close $f1
set l
} {{O G} {D D} {1 {bad value for -eofchar: should be a list of zero, one, or two elements}}}
-
-
test io-39.23 {Tcl_GetChannelOption, server socket is not readable or
writeable, it should still have valid -eofchar and -translation options } {
set l [list]
- set sock [socket -server [namespace code accept] 0]
+ set sock [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
lappend l [fconfigure $sock -eofchar] [fconfigure $sock -translation]
close $sock
set l
@@ -5206,7 +5181,7 @@ test io-39.23 {Tcl_GetChannelOption, server socket is not readable or
test io-39.24 {Tcl_SetChannelOption, server socket is not readable or
writable so we can't change -eofchar or -translation } {
set l [list]
- set sock [socket -server [namespace code accept] 0]
+ set sock [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
fconfigure $sock -eofchar D -translation lf
lappend l [fconfigure $sock -eofchar] [fconfigure $sock -translation]
close $sock
@@ -5228,11 +5203,11 @@ test io-40.1 {POSIX open access modes: RDWR} {
close $f
set x
} {zzy abzzy}
-test io-40.2 {POSIX open access modes: CREAT} {unixOnly} {
+test io-40.2 {POSIX open access modes: CREAT} {unix} {
file delete $path(test3)
set f [open $path(test3) {WRONLY CREAT} 0600]
file stat $path(test3) stats
- set x [format "0%o" [expr $stats(mode)&0777]]
+ set x [format "0%o" [expr $stats(mode)&0o777]]
puts $f "line 1"
close $f
set f [open $path(test3) r]
@@ -5240,19 +5215,14 @@ test io-40.2 {POSIX open access modes: CREAT} {unixOnly} {
close $f
set x
} {0600 {line 1}}
-
-# some tests can only be run is umask is 2
-# if "umask" cannot be run, the tests will be skipped.
-catch {testConstraint umask2 [expr {[exec umask] == 2}]}
-
-test io-40.3 {POSIX open access modes: CREAT} {unixOnly umask2} {
+test io-40.3 {POSIX open access modes: CREAT} {unix umask} {
# This test only works if your umask is 2, like ouster's.
file delete $path(test3)
set f [open $path(test3) {WRONLY CREAT}]
close $f
- file stat test3 stats
- format "0%o" [expr $stats(mode)&0777]
-} 0664
+ file stat $path(test3) stats
+ format "0%o" [expr $stats(mode)&0o777]
+} [format %04o [expr {0o666 & ~ $umaskValue}]]
test io-40.4 {POSIX open access modes: CREAT} {
file delete $path(test3)
set f [open $path(test3) w]
@@ -5317,7 +5287,7 @@ test io-40.8 {POSIX open access modes: TRUNC} {
close $f
set x
} abc
-test io-40.9 {POSIX open access modes: NONBLOCK} {nonPortable macOrUnix} {
+test io-40.9 {POSIX open access modes: NONBLOCK} {nonPortable unix} {
file delete $path(test3)
set f [open $path(test3) {WRONLY NONBLOCK CREAT}]
puts $f "NONBLOCK test"
@@ -5372,20 +5342,18 @@ test io-40.15 {POSIX open access modes: RDWR} {
close $f
lappend x [viewFile test3]
} {zzy abzzy}
-if {![file exists ~/_test_] && [file writable ~]} {
- test io-40.16 {tilde substitution in open} -setup {
- makeFile {Some text} _test_ ~
- } -body {
- file exists [file join $env(HOME) _test_]
- } -cleanup {
- removeFile _test_ ~
- } -result 1
-}
+test io-40.16 {tilde substitution in open} -constraints makeFileInHome -setup {
+ makeFile {Some text} _test_ ~
+} -body {
+ file exists [file join $::env(HOME) _test_]
+} -cleanup {
+ removeFile _test_ ~
+} -result 1
test io-40.17 {tilde substitution in open} {
- set home $env(HOME)
- unset env(HOME)
+ set home $::env(HOME)
+ unset ::env(HOME)
set x [list [catch {open ~/foo} msg] $msg]
- set env(HOME) $home
+ set ::env(HOME) $home
set x
} {1 {couldn't find HOME environment variable to expand path}}
@@ -5438,6 +5406,7 @@ test io-42.3 {Tcl_FileeventCmd: replacing, with NULL chars in script} {fileevent
lappend result [fileevent $f readable]
} {13 11 12 {}}
+
test io-43.1 {Tcl_FileeventCmd: creating, deleting, querying} {stdio unixExecs fileevent} {
set result {}
fileevent $f readable "script 1"
@@ -5485,18 +5454,24 @@ test io-44.1 {FileEventProc procedure: normal read event} -setup {
catch {close $f2}
catch {close $f3}
} -result {text}
-test io-44.2 {FileEventProc procedure: error in read event} -setup {
+test io-44.2 {FileEventProc procedure: error in read event} -constraints {
+ stdio unixExecs fileevent openpipe
+} -setup {
set f2 [open "|[list cat -u]" r+]
set f3 [open "|[list cat -u]" r+]
-} -constraints {stdio unixExecs fileevent openpipe} -body {
- proc ::bgerror args "set [namespace which -variable x] \$args"
+ proc myHandler {msg options} {
+ variable x $msg
+ }
+ set handler [interp bgerror {}]
+ interp bgerror {} [namespace which myHandler]
+} -body {
fileevent $f2 readable {error bogus}
puts $f2 text; flush $f2
variable x initial
vwait [namespace which -variable x]
- rename ::bgerror {}
list $x [fileevent $f2 readable]
} -cleanup {
+ interp bgerror {} $handler
catch {close $f2}
catch {close $f3}
} -result {bogus {}}
@@ -5521,17 +5496,23 @@ test io-44.3 {FileEventProc procedure: normal write event} -setup {
catch {close $f2}
catch {close $f3}
} -result {initial triggered triggered triggered}
-test io-44.4 {FileEventProc procedure: eror in write event} -setup {
+test io-44.4 {FileEventProc procedure: eror in write event} -constraints {
+ stdio unixExecs fileevent openpipe
+} -setup {
set f2 [open "|[list cat -u]" r+]
set f3 [open "|[list cat -u]" r+]
-} -constraints {stdio unixExecs fileevent openpipe} -body {
- proc ::bgerror args "set [namespace which -variable x] \$args"
+ proc myHandler {msg options} {
+ variable x $msg
+ }
+ set handler [interp bgerror {}]
+ interp bgerror {} [namespace which myHandler]
+} -body {
fileevent $f2 writable {error bad-write}
variable x initial
vwait [namespace which -variable x]
- rename ::bgerror {}
list $x [fileevent $f2 writable]
} -cleanup {
+ interp bgerror {} $handler
catch {close $f2}
catch {close $f3}
} -result {bad-write {}}
@@ -5552,9 +5533,9 @@ test io-44.5 {FileEventProc procedure: end of file} {stdio unixExecs openpipe fi
set x
} {initial foo eof}
-
close $f
makeFile "foo bar" foo
+
test io-45.1 {DeleteFileEvent, cleanup on close} {fileevent} {
set f [open $path(foo) r]
fileevent $f readable [namespace code {
@@ -5608,7 +5589,6 @@ test io-45.3 {DeleteFileEvent, cleanup on close} {fileevent} {
} {0 {f script} 1 0 {f3 script} 0 {f script} 1 1 1 1 1}
# Execute these tests only if the "testfevent" command is present.
-testConstraint testfevent [llength [info commands testfevent]]
test io-46.1 {Tcl event loop vs multiple interpreters} {testfevent fileevent} {
testfevent create
@@ -5808,10 +5788,8 @@ test io-48.2 {testing readability conditions} {nonBlockFiles fileevent} {
vwait [namespace which -variable x]
list $x $l
} {done {called called called called called called called}}
-
set path(my_script) [makeFile {} my_script]
-
-test io-48.3 {testing readability conditions} {stdio unixOnly nonBlockFiles openpipe fileevent} {
+test io-48.3 {testing readability conditions} {stdio unix nonBlockFiles openpipe fileevent} {
set f [open $path(bar) w]
puts $f abcdefg
puts $f abcdefg
@@ -6305,8 +6283,7 @@ test io-49.5 {testing crlf reading, leftover cr disgorgment} {
close $f
set l
} [list 7 a\rb\rc 7 {} 7 1]
-
-testConstraint testchannelevent [llength [info commands testchannelevent]]
+
test io-50.1 {testing handler deletion} {testchannelevent} {
file delete $path(test1)
set f [open $path(test1) w]
@@ -6385,8 +6362,8 @@ test io-50.4 {testing handler deletion vs reentrant calls} {testchannelevent} {
update
}
}
- set u toplevel
- set z ""
+ variable u toplevel
+ variable z ""
update
close $f
string compare [string tolower $z] \
@@ -6481,27 +6458,29 @@ test io-51.1 {Test old socket deletion on Macintosh} {socket} {
close $s
set wait done
}
- set ss [socket -server [namespace code accept] 0]
+ set ss [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
+ set port [lindex [fconfigure $ss -sockname] 2]
+
variable wait ""
- set cs [socket [info hostname] [lindex [fconfigure $ss -sockname] 2]]
+ set cs [socket 127.0.0.1 $port]
vwait [namespace which -variable wait]
lappend result [gets $cs]
close $cs
set wait ""
- set cs [socket [info hostname] [lindex [fconfigure $ss -sockname] 2]]
+ set cs [socket 127.0.0.1 $port]
vwait [namespace which -variable wait]
lappend result [gets $cs]
close $cs
set wait ""
- set cs [socket [info hostname] [lindex [fconfigure $ss -sockname] 2]]
+ set cs [socket 127.0.0.1 $port]
vwait [namespace which -variable wait]
lappend result [gets $cs]
close $cs
set wait ""
- set cs [socket [info hostname] [lindex [fconfigure $ss -sockname] 2]]
+ set cs [socket 127.0.0.1 $port]
vwait [namespace which -variable wait]
lappend result [gets $cs]
close $cs
@@ -6594,7 +6573,7 @@ test io-52.5a {TclCopyChannel, all, other negative value} {fcopy} {
}
set result
} {0 0 ok}
-test io-52.5b {TclCopyChannel, all, wrap to negative value} {fcopy} {
+test io-52.5b {TclCopyChannel, all, wrapped to negative value} {fcopy} {
file delete $path(test1)
set f1 [open $thisScript]
set f2 [open $path(test1) w]
@@ -6671,18 +6650,15 @@ test io-52.8 {TclCopyChannel} {stdio openpipe fcopy} {
close $f2
list $s0 [file size $path(test1)]
} {40 40}
-
# Empty files, to register them with the test facility
set path(kyrillic.txt) [makeFile {} kyrillic.txt]
set path(utf8-fcopy.txt) [makeFile {} utf8-fcopy.txt]
set path(utf8-rp.txt) [makeFile {} utf8-rp.txt]
-
# Create kyrillic file, use lf translation to avoid os eol issues
set out [open $path(kyrillic.txt) w]
fconfigure $out -encoding koi8-r -translation lf
puts $out "\u0410\u0410"
close $out
-
test io-52.9 {TclCopyChannel & encodings} {fcopy} {
# Copy kyrillic to UTF-8, using fcopy.
@@ -6713,7 +6689,6 @@ test io-52.9 {TclCopyChannel & encodings} {fcopy} {
[file size $path(utf8-fcopy.txt)] \
[file size $path(utf8-rp.txt)]
} {3 5 5}
-
test io-52.10 {TclCopyChannel & encodings} {fcopy} {
# encoding to binary (=> implies that the
# internal utf-8 is written)
@@ -6731,7 +6706,6 @@ test io-52.10 {TclCopyChannel & encodings} {fcopy} {
file size $path(utf8-fcopy.txt)
} 5
-
test io-52.11 {TclCopyChannel & encodings} {fcopy} {
# binary to encoding => the input has to be
# in utf-8 to make sense to the encoder
@@ -6781,7 +6755,7 @@ test io-53.2 {CopyData} {fcopy} {
}
set result
} {0 0 ok}
-test io-53.3 {CopyData: background read underflow} {stdio unixOnly openpipe fcopy} {
+test io-53.3 {CopyData: background read underflow} {stdio unix openpipe fcopy} {
file delete $path(test1)
file delete $path(pipe)
set f1 [open $path(pipe) w]
@@ -6813,7 +6787,7 @@ test io-53.3 {CopyData: background read underflow} {stdio unixOnly openpipe fcop
close $f
set result
} "ready line1 line2 {done\n}"
-test io-53.4 {CopyData: background write overflow} {stdio unixOnly openpipe fileevent fcopy} {
+test io-53.4 {CopyData: background write overflow} {stdio unix openpipe fileevent fcopy} {
set big bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n
variable x
for {set x 0} {$x < 12} {incr x} {
@@ -6851,7 +6825,6 @@ test io-53.4 {CopyData: background write overflow} {stdio unixOnly openpipe file
set x
} done
set result {}
-
proc FcopyTestAccept {sock args} {
after 1000 "close $sock"
}
@@ -6863,10 +6836,9 @@ proc FcopyTestDone {bytes {error {}}} {
set fcopyTestDone 0
}
}
-
test io-53.5 {CopyData: error during fcopy} {socket fcopy} {
variable fcopyTestDone
- set listen [socket -server [namespace code FcopyTestAccept] 0]
+ set listen [socket -server [namespace code FcopyTestAccept] -myaddr 127.0.0.1 0]
set in [open $thisScript] ;# 126 K
set out [socket 127.0.0.1 [lindex [fconfigure $listen -sockname] 2]]
catch {unset fcopyTestDone}
@@ -6899,24 +6871,20 @@ test io-53.6 {CopyData: error during fcopy} {stdio openpipe fcopy} {
close $out
set fcopyTestDone ;# 0 for plain end of file
} {0}
-
proc doFcopy {in out {bytes 0} {error {}}} {
variable fcopyTestDone
variable fcopyTestCount
incr fcopyTestCount $bytes
if {[string length $error]} {
- set fcopyTestDone 1
+ set fcopyTestDone 1
} elseif {[eof $in]} {
- set fcopyTestDone 0
+ set fcopyTestDone 0
} else {
# Delay next fcopy to wait for size>0 input bytes
- after 100 [list
- fcopy $in $out -size 1000 \
- -command [namespace code [list doFcopy $in $out]]
- ]
+ after 100 [list fcopy $in $out -size 1000 \
+ -command [namespace code [list doFcopy $in $out]]]
}
}
-
test io-53.7 {CopyData: Flooding fcopy from pipe} {stdio openpipe fcopy} {
variable fcopyTestDone
file delete $path(pipe)
@@ -7037,6 +7005,44 @@ test io-53.8a {CopyData: async callback and error handling, Bug 1932639, at eof}
removeFile foo
removeFile bar
} -result {1 sync/OK {CMD 0}}
+test io-53.8b {CopyData: async callback and -size 0} -setup {
+ # copy progress callback. errors out intentionally
+ proc ::cmd args {
+ lappend ::RES "CMD $args"
+ set ::forever has-been-reached
+ return
+ }
+ # Files we use for our channels
+ set foo [makeFile ashgdfashdgfasdhgfasdhgf foo]
+ set bar [makeFile {} bar]
+ # Channels to copy between
+ set f [open $foo r] ; fconfigure $f -translation binary
+ set g [open $bar w] ; fconfigure $g -translation binary -buffering none
+} -constraints {stdio openpipe fcopy} -body {
+ set ::RES {}
+ # Run the copy. Should not invoke -command now.
+ fcopy $f $g -size 0 -command ::cmd
+ # Check that -command was not called synchronously
+ lappend ::RES [expr {([llength $::RES] > 1) ? "sync/FAIL" : "sync/OK"}]
+ # Now let the async part happen. Should capture the eof in cmd
+ # If not break the event loop via timer.
+ set token [after 1000 {
+ lappend ::RES {cmd/FAIL timeout}
+ set ::forever has-been-reached
+ }]
+ vwait ::forever
+ catch {after cancel $token}
+ # Report
+ set ::RES
+} -cleanup {
+ close $f
+ close $g
+ catch {unset ::RES}
+ catch {unset ::forever}
+ rename ::cmd {}
+ removeFile foo
+ removeFile bar
+} -result {sync/OK {CMD 0}}
test io-53.9 {CopyData: -size and event interaction, Bug 780533} -setup {
set out [makeFile {} out]
set err [makeFile {} err]
@@ -7080,10 +7086,10 @@ test io-53.9 {CopyData: -size and event interaction, Bug 780533} -setup {
} -cleanup {
close $pipe
rename ::done {}
- after 1000 ;# Give Windows time to kill the process
+ after 1000; # Give Windows time to kill the process
catch {close $out}
- removeFile out
- removeFile err
+ catch {removeFile out}
+ catch {removeFile err}
catch {unset ::forever}
} -result OK
test io-53.10 {Bug 1350564, multi-directional fcopy} -setup {
@@ -7209,14 +7215,14 @@ test io-54.1 {Recursive channel events} {socket fileevent} {
}
incr x
}
- set ss [socket -server [namespace code accept] 0]
+ set ss [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
# We need to delay on some systems until the creation of the
# server socket completes.
set done 0
for {set i 0} {$i < 10} {incr i} {
- if {![catch {set cs [socket [info hostname] [lindex [fconfigure $ss -sockname] 2]]}]} {
+ if {![catch {set cs [socket 127.0.0.1 [lindex [fconfigure $ss -sockname] 2]]}]} {
set done 1
break
}
@@ -7245,7 +7251,7 @@ test io-54.1 {Recursive channel events} {socket fileevent} {
test io-54.2 {Testing for busy-wait in recursive channel events} {socket fileevent} {
set accept {}
set after {}
- variable s [socket -server [namespace code accept] 0]
+ variable s [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
proc accept {s a p} {
variable counter
variable accept
@@ -7304,7 +7310,9 @@ test io-54.2 {Testing for busy-wait in recursive channel events} {socket fileeve
set path(fooBar) [makeFile {} fooBar]
-test io-55.1 {ChannelEventScriptInvoker: deletion} {fileevent} {
+test io-55.1 {ChannelEventScriptInvoker: deletion} -constraints {
+ fileevent
+} -setup {
variable x
proc eventScript {fd} {
variable x
@@ -7312,13 +7320,20 @@ test io-55.1 {ChannelEventScriptInvoker: deletion} {fileevent} {
error "planned error"
set x whoops
}
- proc ::bgerror {args} "set [namespace which -variable x] got_error"
+ proc myHandler args {
+ variable x got_error
+ }
+ set handler [interp bgerror {}]
+ interp bgerror {} [namespace which myHandler]
+} -body {
set f [open $path(fooBar) w]
fileevent $f writable [namespace code [list eventScript $f]]
variable x not_done
vwait [namespace which -variable x]
set x
-} {got_error}
+} -cleanup {
+ interp bgerror {} $handler
+} -result {got_error}
test io-56.1 {ChannelTimerProc} {testchannelevent} {
set f [open $path(fooBar) w]
@@ -7346,7 +7361,7 @@ test io-57.1 {buffered data and file events, gets} {fileevent} {
variable s2
set s2 $sock
}
- set server [socket -server [namespace code accept] 0]
+ set server [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
set s [socket 127.0.0.1 [lindex [fconfigure $server -sockname] 2]]
variable s2
vwait [namespace which -variable s2]
@@ -7369,7 +7384,7 @@ test io-57.2 {buffered data and file events, read} {fileevent} {
variable s2
set s2 $sock
}
- set server [socket -server [namespace code accept] 0]
+ set server [socket -server [namespace code accept] -myaddr 127.0.0.1 0]
set s [socket 127.0.0.1 [lindex [fconfigure $server -sockname] 2]]
variable s2
vwait [namespace which -variable s2]
@@ -7387,7 +7402,7 @@ test io-57.2 {buffered data and file events, read} {fileevent} {
close $server
set result
} {1 readable 234567890 timer}
-
+
test io-58.1 {Tcl_NotifyChannel and error when closing} {stdio unixOrPc openpipe fileevent} {
set out [open $path(script) w]
puts $out {
@@ -7415,8 +7430,6 @@ test io-58.1 {Tcl_NotifyChannel and error when closing} {stdio unixOrPc openpipe
list $x $result
} {1 {gets {normal message from pipe} gets {} catch {error message from pipe}}}
-
-testConstraint testmainthread [llength [info commands testmainthread]]
test io-59.1 {Thread reference of channels} {testmainthread testchannel} {
# TIP #10
# More complicated tests (like that the reference changes as a
@@ -7430,7 +7443,6 @@ test io-59.1 {Thread reference of channels} {testmainthread testchannel} {
string equal $result [testmainthread]
} {1}
-
test io-60.1 {writing illegal utf sequences} {openpipe fileevent} {
# This test will hang in older revisions of the core.
@@ -7489,6 +7501,279 @@ test io-61.1 {Reset eof state after changing the eof char} -setup {
removeFile eofchar
} -result {77 = 23431}
+
+# Test the cutting and splicing of channels, this is incidentially the
+# attach/detach facility of package Thread, but __without any
+# safeguards__. It can also be used to emulate transfer of channels
+# between threads, and is used for that here.
+
+test io-70.0 {Cutting & Splicing channels} {testchannel} {
+ set f [makeFile {... dummy ...} cutsplice]
+ set c [open $f r]
+
+ set res {}
+ lappend res [catch {seek $c 0 start}]
+ testchannel cut $c
+
+ lappend res [catch {seek $c 0 start}]
+ testchannel splice $c
+
+ lappend res [catch {seek $c 0 start}]
+ close $c
+
+ removeFile cutsplice
+
+ set res
+} {0 1 0}
+
+
+# Duplicate of code in "thread.test". Find a better way of doing this
+# without duplication. Maybe placement into a proc which transforms to
+# nop after the first call, and placement of its defintion in a
+# central location.
+
+if {[testConstraint testthread]} {
+ testthread errorproc ThreadError
+
+ proc ThreadError {id info} {
+ global threadError
+ set threadError $info
+ }
+
+ proc ThreadNullError {id info} {
+ # ignore
+ }
+}
+
+test io-70.1 {Transfer channel} {testchannel testthread} {
+ set f [makeFile {... dummy ...} cutsplice]
+ set c [open $f r]
+
+ set res {}
+ lappend res [catch {seek $c 0 start}]
+ testchannel cut $c
+ lappend res [catch {seek $c 0 start}]
+
+ set tid [testthread create]
+ testthread send $tid [list set c $c]
+ lappend res [testthread send $tid {
+ testchannel splice $c
+ set res [catch {seek $c 0 start}]
+ close $c
+ set res
+ }]
+
+ tcltest::threadReap
+ removeFile cutsplice
+
+ set res
+} {0 1 0}
+
+# ### ### ### ######### ######### #########
+
+foreach {n msg expected} {
+ 0 {} {}
+ 1 {{message only}} {{message only}}
+ 2 {-options x} {-options x}
+ 3 {-options {x y} {the message}} {-options {x y} {the message}}
+
+ 4 {-code 1 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 5 {-code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 6 {-code 1 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 7 {-code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 8 {-code error -level 0 -f ba snarf} {-code error -level 0 -f ba snarf}
+ 9 {-code ok -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 10 {-code error -level 5 -f ba snarf} {-code error -level 0 -f ba snarf}
+ 11 {-code ok -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 12 {-code boss -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 13 {-code boss -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 14 {-code 1 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 15 {-code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 16 {-code 1 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 17 {-code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 18 {-code error -level 0 -f ba} {-code error -level 0 -f ba}
+ 19 {-code ok -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 20 {-code error -level 5 -f ba} {-code error -level 0 -f ba}
+ 21 {-code ok -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 22 {-code boss -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 23 {-code boss -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 24 {-code 1 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 25 {-code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 26 {-code error -level X -f ba snarf} {-code error -level 0 -f ba snarf}
+ 27 {-code ok -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 28 {-code boss -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 29 {-code 1 -level X -f ba} {-code 1 -level 0 -f ba}
+ 30 {-code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ 31 {-code error -level X -f ba} {-code error -level 0 -f ba}
+ 32 {-code ok -level X -f ba} {-code 1 -level 0 -f ba}
+ 33 {-code boss -level X -f ba} {-code 1 -level 0 -f ba}
+
+ 34 {-code 1 -code 1 -level 0 -f ba snarf} {-code 1 -code 1 -level 0 -f ba snarf}
+ 35 {-code 1 -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 36 {-code 1 -code 1 -level 5 -f ba snarf} {-code 1 -code 1 -level 0 -f ba snarf}
+ 37 {-code 1 -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 38 {-code 1 -code error -level 0 -f ba snarf} {-code 1 -code error -level 0 -f ba snarf}
+ 39 {-code 1 -code ok -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 40 {-code 1 -code error -level 5 -f ba snarf} {-code 1 -code error -level 0 -f ba snarf}
+ 41 {-code 1 -code ok -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 42 {-code 1 -code boss -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 43 {-code 1 -code boss -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 44 {-code 1 -code 1 -level 0 -f ba} {-code 1 -code 1 -level 0 -f ba}
+ 45 {-code 1 -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 46 {-code 1 -code 1 -level 5 -f ba} {-code 1 -code 1 -level 0 -f ba}
+ 47 {-code 1 -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 48 {-code 1 -code error -level 0 -f ba} {-code 1 -code error -level 0 -f ba}
+ 49 {-code 1 -code ok -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 50 {-code 1 -code error -level 5 -f ba} {-code 1 -code error -level 0 -f ba}
+ 51 {-code 1 -code ok -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 52 {-code 1 -code boss -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 53 {-code 1 -code boss -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 54 {-code 1 -code 1 -level X -f ba snarf} {-code 1 -code 1 -level 0 -f ba snarf}
+ 55 {-code 1 -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 56 {-code 1 -code error -level X -f ba snarf} {-code 1 -code error -level 0 -f ba snarf}
+ 57 {-code 1 -code ok -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 58 {-code 1 -code boss -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 59 {-code 1 -code 1 -level X -f ba} {-code 1 -code 1 -level 0 -f ba}
+ 60 {-code 1 -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ 61 {-code 1 -code error -level X -f ba} {-code 1 -code error -level 0 -f ba}
+ 62 {-code 1 -code ok -level X -f ba} {-code 1 -level 0 -f ba}
+ 63 {-code 1 -code boss -level X -f ba} {-code 1 -level 0 -f ba}
+
+ 64 {-code 0 -code 1 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 65 {-code 0 -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 66 {-code 0 -code 1 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 67 {-code 0 -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 68 {-code 0 -code error -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 69 {-code 0 -code ok -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 70 {-code 0 -code error -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 71 {-code 0 -code ok -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 72 {-code 0 -code boss -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 73 {-code 0 -code boss -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 74 {-code 0 -code 1 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 75 {-code 0 -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 76 {-code 0 -code 1 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 77 {-code 0 -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 78 {-code 0 -code error -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 79 {-code 0 -code ok -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 80 {-code 0 -code error -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 81 {-code 0 -code ok -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 82 {-code 0 -code boss -level 0 -f ba} {-code 1 -level 0 -f ba}
+ 83 {-code 0 -code boss -level 5 -f ba} {-code 1 -level 0 -f ba}
+ 84 {-code 0 -code 1 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 85 {-code 0 -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 86 {-code 0 -code error -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 87 {-code 0 -code ok -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 88 {-code 0 -code boss -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 89 {-code 0 -code 1 -level X -f ba} {-code 1 -level 0 -f ba}
+ 90 {-code 0 -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ 91 {-code 0 -code error -level X -f ba} {-code 1 -level 0 -f ba}
+ 92 {-code 0 -code ok -level X -f ba} {-code 1 -level 0 -f ba}
+ 93 {-code 0 -code boss -level X -f ba} {-code 1 -level 0 -f ba}
+
+ 94 {-code 1 -code 1 -level 0 -f ba snarf} {-code 1 -code 1 -level 0 -f ba snarf}
+ 95 {-code 0 -code 1 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 96 {-code 1 -code 1 -level 5 -f ba snarf} {-code 1 -code 1 -level 0 -f ba snarf}
+ 97 {-code 0 -code 1 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ 98 {-code error -code 1 -level 0 -f ba snarf} {-code error -code 1 -level 0 -f ba snarf}
+ 99 {-code ok -code 1 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ a0 {-code error -code 1 -level 5 -f ba snarf} {-code error -code 1 -level 0 -f ba snarf}
+ a1 {-code ok -code 1 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ a2 {-code boss -code 1 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ a3 {-code boss -code 1 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ a4 {-code 1 -code 1 -level 0 -f ba} {-code 1 -code 1 -level 0 -f ba}
+ a5 {-code 0 -code 1 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ a6 {-code 1 -code 1 -level 5 -f ba} {-code 1 -code 1 -level 0 -f ba}
+ a7 {-code 0 -code 1 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ a8 {-code error -code 1 -level 0 -f ba} {-code error -code 1 -level 0 -f ba}
+ a9 {-code ok -code 1 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ b0 {-code error -code 1 -level 5 -f ba} {-code error -code 1 -level 0 -f ba}
+ b1 {-code ok -code 1 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ b2 {-code boss -code 1 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ b3 {-code boss -code 1 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ b4 {-code 1 -code 1 -level X -f ba snarf} {-code 1 -code 1 -level 0 -f ba snarf}
+ b5 {-code 0 -code 1 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ b6 {-code error -code 1 -level X -f ba snarf} {-code error -code 1 -level 0 -f ba snarf}
+ b7 {-code ok -code 1 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ b8 {-code boss -code 1 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ b9 {-code 1 -code 1 -level X -f ba} {-code 1 -code 1 -level 0 -f ba}
+ c0 {-code 0 -code 1 -level X -f ba} {-code 1 -level 0 -f ba}
+ c1 {-code error -code 1 -level X -f ba} {-code error -code 1 -level 0 -f ba}
+ c2 {-code ok -code 1 -level X -f ba} {-code 1 -level 0 -f ba}
+ c3 {-code boss -code 1 -level X -f ba} {-code 1 -level 0 -f ba}
+
+ c4 {-code 1 -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ c5 {-code 0 -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ c6 {-code 1 -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ c7 {-code 0 -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ c8 {-code error -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ c9 {-code ok -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ d0 {-code error -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ d1 {-code ok -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ d2 {-code boss -code 0 -level 0 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ d3 {-code boss -code 0 -level 5 -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ d4 {-code 1 -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ d5 {-code 0 -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ d6 {-code 1 -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ d7 {-code 0 -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ d8 {-code error -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ d9 {-code ok -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ e0 {-code error -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ e1 {-code ok -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ e2 {-code boss -code 0 -level 0 -f ba} {-code 1 -level 0 -f ba}
+ e3 {-code boss -code 0 -level 5 -f ba} {-code 1 -level 0 -f ba}
+ e4 {-code 1 -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ e5 {-code 0 -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ e6 {-code error -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ e7 {-code ok -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ e8 {-code boss -code 0 -level X -f ba snarf} {-code 1 -level 0 -f ba snarf}
+ e9 {-code 1 -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ f0 {-code 0 -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ f1 {-code error -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ f2 {-code ok -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+ f3 {-code boss -code 0 -level X -f ba} {-code 1 -level 0 -f ba}
+} {
+ test io-71.$n {Tcl_SetChannelError} {testchannel} {
+
+ set f [makeFile {... dummy ...} cutsplice]
+ set c [open $f r]
+
+ set res [testchannel setchannelerror $c [lrange $msg 0 end]]
+ close $c
+ removeFile cutsplice
+
+ set res
+ } [lrange $expected 0 end]
+
+ test io-72.$n {Tcl_SetChannelErrorInterp} {testchannel} {
+
+ set f [makeFile {... dummy ...} cutsplice]
+ set c [open $f r]
+
+ set res [testchannel setchannelerrorinterp $c [lrange $msg 0 end]]
+ close $c
+ removeFile cutsplice
+
+ set res
+ } [lrange $expected 0 end]
+}
+
+test io-73.1 {channel Tcl_Obj SetChannelFromAny} {} {
+ # Test for Bug 1847044 - don't spoil type unless we have a valid channel
+ catch {close [lreplace [list a] 0 end]}
+} {1}
+
+test io-73.2 {channel Tcl_Obj SetChannelFromAny, bug 2407783} {} {
+ # Invalidate intrep of 'channel' Tcl_Obj when transiting between interpreters.
+ interp create foo
+ set f [open [info script] r]
+ seek $f 0
+ set code [catch {interp eval foo [list seek $f 0]} msg]
+ # The string map converts the changing channel handle to a fixed string
+ list $code [string map [list $f @@] $msg]
+} {1 {can not find channel named "@@"}}
+
+# ### ### ### ######### ######### #########
+
# cleanup
foreach file [list fooBar longfile script output test1 pipe my_script \
test2 test3 cat stdout kyrillic.txt utf8-fcopy.txt utf8-rp.txt] {
diff --git a/tests/ioCmd.test b/tests/ioCmd.test
index 2d17d76..768a748 100644
--- a/tests/ioCmd.test
+++ b/tests/ioCmd.test
@@ -14,11 +14,16 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2
namespace import -force ::tcltest::*
}
-testConstraint fcopy [llength [info commands fcopy]]
+# Custom constraints used in this file
+testConstraint fcopy [llength [info commands fcopy]]
+testConstraint testchannel [llength [info commands testchannel]]
+testConstraint testthread [llength [info commands testthread]]
+
+#----------------------------------------------------------------------
test iocmd-1.1 {puts command} {
list [catch {puts} msg] $msg
@@ -28,7 +33,7 @@ test iocmd-1.2 {puts command} {
} {1 {wrong # args: should be "puts ?-nonewline? ?channelId? string"}}
test iocmd-1.3 {puts command} {
list [catch {puts froboz -nonewline kablooie} msg] $msg
-} {1 {bad argument "kablooie": should be "nonewline"}}
+} {1 {wrong # args: should be "puts ?-nonewline? ?channelId? string"}}
test iocmd-1.4 {puts command} {
list [catch {puts froboz hello} msg] $msg
} {1 {can not find channel named "froboz"}}
@@ -60,7 +65,6 @@ test iocmd-1.8 {puts command} {
file size $path(test1)
} 9
-
test iocmd-2.1 {flush command} {
list [catch {flush} msg] $msg
} {1 {wrong # args: should be "flush channelId"}}
@@ -111,8 +115,8 @@ test iocmd-4.4 {read command} {
list [catch {read -nonewline} msg] $msg
} {1 {wrong # args: should be "read channelId ?numChars?" or "read ?-nonewline? channelId"}}
test iocmd-4.5 {read command} {
- list [catch {read -nonew file4} msg] $msg $errorCode
-} {1 {can not find channel named "-nonew"} NONE}
+ list [catch {read -nonew file4} msg] $msg $::errorCode
+} {1 {can not find channel named "-nonew"} {TCL LOOKUP CHANNEL -nonew}}
test iocmd-4.6 {read command} {
list [catch {read stdout} msg] $msg
} {1 {channel "stdout" wasn't opened for reading}}
@@ -126,32 +130,30 @@ test iocmd-4.8 {read command with incorrect combination of arguments} {
puts $f "and this one"
close $f
set f [open $path(test1)]
- set x [list [catch {read -nonewline $f 20 z} msg] $msg $errorCode]
+ set x [list [catch {read -nonewline $f 20 z} msg] $msg $::errorCode]
close $f
set x
} {1 {wrong # args: should be "read channelId ?numChars?" or "read ?-nonewline? channelId"} NONE}
test iocmd-4.9 {read command} {
- list [catch {read stdin foo} msg] $msg $errorCode
-} {1 {bad argument "foo": should be "nonewline"} NONE}
+ list [catch {read stdin foo} msg] $msg $::errorCode
+} {1 {expected integer but got "foo"} {TCL VALUE NUMBER}}
test iocmd-4.10 {read command} {
- list [catch {read file107} msg] $msg $errorCode
-} {1 {can not find channel named "file107"} NONE}
-
+ list [catch {read file107} msg] $msg $::errorCode
+} {1 {can not find channel named "file107"} {TCL LOOKUP CHANNEL file107}}
set path(test3) [makeFile {} test3]
-
test iocmd-4.11 {read command} {
set f [open $path(test3) w]
- set x [list [catch {read $f} msg] $msg $errorCode]
+ set x [list [catch {read $f} msg] $msg $::errorCode]
close $f
string compare [string tolower $x] \
[list 1 [format "channel \"%s\" wasn't opened for reading" $f] none]
} 0
test iocmd-4.12 {read command} {
set f [open $path(test1)]
- set x [list [catch {read $f 12z} msg] $msg $errorCode]
+ set x [list [catch {read $f 12z} msg] $msg $::errorCode]
close $f
set x
-} {1 {expected integer but got "12z"} NONE}
+} {1 {expected integer but got "12z"} {TCL VALUE NUMBER}}
test iocmd-5.1 {seek command} {
list [catch {seek} msg] $msg
@@ -239,108 +241,109 @@ test iocmd-8.9 {fconfigure command} {
test iocmd-8.10 {fconfigure command} {
list [catch {fconfigure a b} msg] $msg
} {1 {can not find channel named "a"}}
-
set path(fconfigure.dummy) [makeFile {} fconfigure.dummy]
-
test iocmd-8.11 {fconfigure command} {
set chan [open $path(fconfigure.dummy) r]
set res [list [catch {fconfigure $chan -froboz blarfo} msg] $msg]
close $chan
set res
} {1 {bad option "-froboz": should be one of -blocking, -buffering, -buffersize, -encoding, -eofchar, or -translation}}
-
test iocmd-8.12 {fconfigure command} {
set chan [open $path(fconfigure.dummy) r]
set res [list [catch {fconfigure $chan -b blarfo} msg] $msg]
close $chan
set res
} {1 {bad option "-b": should be one of -blocking, -buffering, -buffersize, -encoding, -eofchar, or -translation}}
-
test iocmd-8.13 {fconfigure command} {
set chan [open $path(fconfigure.dummy) r]
set res [list [catch {fconfigure $chan -buffer blarfo} msg] $msg]
close $chan
set res
} {1 {bad option "-buffer": should be one of -blocking, -buffering, -buffersize, -encoding, -eofchar, or -translation}}
-
removeFile fconfigure.dummy
-
test iocmd-8.14 {fconfigure command} {
fconfigure stdin -buffers
} 4096
-
-proc iocmdSSETUP {} {
- uplevel {
- set srv [socket -server iocmdSRV 0]
- set port [lindex [fconfigure $srv -sockname] 2]
- proc iocmdSRV {sock ip port} {close $sock}
- set cli [socket 127.0.0.1 $port]
+test iocmd-8.15.1 {fconfigure command / tcp channel} -constraints {socket unixOrPc} -setup {
+ set srv [socket -server iocmdSRV -myaddr 127.0.0.1 0]
+ set port [lindex [fconfigure $srv -sockname] 2]
+ proc iocmdSRV {sock ip port} {close $sock}
+ set cli [socket 127.0.0.1 $port]
+} -body {
+ fconfigure $cli -blah
+} -cleanup {
+ close $cli
+ close $srv
+ unset cli srv port
+ rename iocmdSRV {}
+} -returnCodes error -result {bad option "-blah": should be one of -blocking, -buffering, -buffersize, -encoding, -eofchar, -translation, -peername, or -sockname}
+test iocmd-8.16 {fconfigure command / tcp channel} -constraints socket -setup {
+ set srv [socket -server iocmdSRV -myaddr 127.0.0.1 0]
+ set port [lindex [fconfigure $srv -sockname] 2]
+ proc iocmdSRV {sock ip port} {close $sock}
+ set cli [socket 127.0.0.1 $port]
+} -body {
+ expr {[lindex [fconfigure $cli -peername] 2] == $port}
+} -cleanup {
+ close $cli
+ close $srv
+ unset cli srv port
+ rename iocmdSRV {}
+} -result 1
+test iocmd-8.17 {fconfigure command / tcp channel} -constraints nonPortable -setup {
+ set srv [socket -server iocmdSRV -myaddr 127.0.0.1 0]
+ set port [lindex [fconfigure $srv -sockname] 2]
+ proc iocmdSRV {sock ip port} {close $sock}
+ set cli [socket 127.0.0.1 $port]
+} -body {
+ # It is possible that you don't get the connection reset by peer
+ # error but rather a valid answer. Depends on the tcp implementation
+ update
+ puts $cli "blah"
+ flush $cli; # that flush could/should fail too
+ update
+ regsub -all {can([^:])+: } [catch {fconfigure $cli -peername} msg] {}
+} -cleanup {
+ close $cli
+ close $srv
+ unset cli srv port
+ rename iocmdSRV {}
+} -result 1
+test iocmd-8.18 {fconfigure command / unix tty channel} -constraints {nonPortable unix} -setup {
+ set tty ""
+} -body {
+ # might fail if /dev/ttya is unavailable
+ set tty [open /dev/ttya]
+ fconfigure $tty -blah blih
+} -cleanup {
+ if {$tty ne ""} {
+ close $tty
}
-}
-proc iocmdSSHTDWN {} {
- uplevel {
- close $cli
- close $srv
- unset cli srv port
- rename iocmdSRV {}
+} -returnCodes error -result {bad option "-blah": should be one of -blocking, -buffering, -buffersize, -encoding, -eofchar, -translation, or -mode}
+test iocmd-8.19 {fconfigure command / win tty channel} -constraints {nonPortable win} -setup {
+ set tty ""
+} -body {
+ # might fail early if com1 is unavailable
+ set tty [open com1]
+ fconfigure $tty -blah blih
+} -cleanup {
+ if {$tty ne ""} {
+ close $tty
}
-}
-
-test iocmd-8.15.0 {fconfigure command / tcp channel} {socket macOnly} {
- iocmdSSETUP
- set r [list [catch {fconfigure $cli -blah} msg] $msg]
- iocmdSSHTDWN
- set r
-} {1 {bad option "-blah": should be one of -blocking, -buffering, -buffersize, -encoding, -eofchar, -translation, -error, -peername, or -sockname}}
-test iocmd-8.15.1 {fconfigure command / tcp channel} {socket unixOrPc} {
- iocmdSSETUP
- set r [list [catch {fconfigure $cli -blah} msg] $msg]
- iocmdSSHTDWN
- set r
-} {1 {bad option "-blah": should be one of -blocking, -buffering, -buffersize, -encoding, -eofchar, -translation, -peername, or -sockname}}
-test iocmd-8.16 {fconfigure command / tcp channel} {socket} {
- iocmdSSETUP
- set r [expr [lindex [fconfigure $cli -peername] 2]==$port]
- iocmdSSHTDWN
- set r
-} 1
-test iocmd-8.17 {fconfigure command / tcp channel} {nonPortable} {
- # It is possible that you don't get the connection reset by peer
- # error but rather a valid answer. depends of the tcp implementation
- iocmdSSETUP
- update;
- puts $cli "blah"; flush $cli; # that flush could/should fail too
- update;
- set r [catch {fconfigure $cli -peername} msg]
- iocmdSSHTDWN
- regsub -all {can([^:])+: } $r {} r;
- set r
-} 1
-test iocmd-8.18 {fconfigure command / unix tty channel} {nonPortable unixOnly} {
- # might fail if /dev/ttya is unavailable
- set tty [open /dev/ttya]
- set r [list [catch {fconfigure $tty -blah blih} msg] $msg];
- close $tty;
- set r;
-} {1 {bad option "-blah": should be one of -blocking, -buffering, -buffersize, -encoding, -eofchar, -translation, or -mode}}
-test iocmd-8.19 {fconfigure command / win tty channel} {nonPortable pcOnly} {
- # might fail if com1 is unavailable
- set tty [open com1]
- set r [list [catch {fconfigure $tty -blah blih} msg] $msg];
- close $tty;
- set r;
-} {1 {bad option "-blah": should be one of -blocking, -buffering, -buffersize, -encoding, -eofchar, -translation, -mode, or -pollinterval}}
+} -returnCodes error -result {bad option "-blah": should be one of -blocking, -buffering, -buffersize, -encoding, -eofchar, -translation, -mode, -handshake, -pollinterval, -sysbuffer, -timeout, -ttycontrol, or -xchar}
+# TODO: Test parsing of serial channel options (nonportable, since requires an
+# open channel to work with).
test iocmd-9.1 {eof command} {
- list [catch {eof} msg] $msg $errorCode
+ list [catch {eof} msg] $msg $::errorCode
} {1 {wrong # args: should be "eof channelId"} NONE}
test iocmd-9.2 {eof command} {
- list [catch {eof a b} msg] $msg $errorCode
+ list [catch {eof a b} msg] $msg $::errorCode
} {1 {wrong # args: should be "eof channelId"} NONE}
test iocmd-9.3 {eof command} {
catch {close file100}
- list [catch {eof file100} msg] $msg $errorCode
-} {1 {can not find channel named "file100"} NONE}
+ list [catch {eof file100} msg] $msg $::errorCode
+} {1 {can not find channel named "file100"} {TCL LOOKUP CHANNEL file100}}
# The tests for Tcl_ExecObjCmd are in exec.test
@@ -367,14 +370,17 @@ file delete $path(test5)
test iocmd-11.1 {I/O to command pipelines} {unixOrPc unixExecs} {
set f [open $path(test4) w]
close $f
- list [catch {open "| cat < $path(test4) > $path(test5)" w} msg] $msg $errorCode
+ list [catch {open "| cat < \"$path(test4)\" > \"$path(test5)\"" w} msg] $msg $::errorCode
} {1 {can't write input to command: standard input was redirected} NONE}
test iocmd-11.2 {I/O to command pipelines} {unixOrPc unixExecs} {
- list [catch {open "| echo > $path(test5)" r} msg] $msg $errorCode
+ list [catch {open "| echo > \"$path(test5)\"" r} msg] $msg $::errorCode
} {1 {can't read output from command: standard output was redirected} NONE}
test iocmd-11.3 {I/O to command pipelines} {unixOrPc unixExecs} {
- list [catch {open "| echo > $path(test5)" r+} msg] $msg $errorCode
+ list [catch {open "| echo > \"$path(test5)\"" r+} msg] $msg $::errorCode
} {1 {can't read output from command: standard output was redirected} NONE}
+test iocmd-11.4 {I/O to command pipelines} unixOrPc {
+ list [catch {open "| no_such_command_exists" rb} msg] $msg $::errorCode
+} {1 {couldn't execute "no_such_command_exists": no such file or directory} {POSIX ENOENT {no such file or directory}}}
test iocmd-12.1 {POSIX open access modes: RDONLY} {
file delete $path(test1)
@@ -399,7 +405,7 @@ test iocmd-12.3 {POSIX open access modes: WRONLY} -match regexp -body {
#
# Test 13.4 relies on assigning the same channel name twice.
#
-test iocmd-12.4 {POSIX open access modes: WRONLY} {unixOnly} {
+test iocmd-12.4 {POSIX open access modes: WRONLY} {unix} {
file delete $path(test3)
set f [open $path(test3) w]
fconfigure $f -eofchar {}
@@ -423,7 +429,7 @@ test iocmd-12.5 {POSIX open access modes: RDWR} -match regexp -body {
open $path(test3) RDWR
} -returnCodes error -result {(?i)couldn't open ".*test3": no such file or directory}
test iocmd-12.6 {POSIX open access modes: errors} {
- concat [catch {open $path(test3) "FOO \{BAR BAZ"} msg] $msg\n$errorInfo
+ concat [catch {open $path(test3) "FOO \{BAR BAZ"} msg] $msg\n$::errorInfo
} "1 unmatched open brace in list
unmatched open brace in list
while processing open access modes \"FOO {BAR BAZ\"
@@ -431,11 +437,36 @@ unmatched open brace in list
\"open \$path(test3) \"FOO \\{BAR BAZ\"\""
test iocmd-12.7 {POSIX open access modes: errors} {
list [catch {open $path(test3) {FOO BAR BAZ}} msg] $msg
-} {1 {invalid access mode "FOO": must be RDONLY, WRONLY, RDWR, APPEND, CREAT EXCL, NOCTTY, NONBLOCK, or TRUNC}}
+} {1 {invalid access mode "FOO": must be RDONLY, WRONLY, RDWR, APPEND, BINARY, CREAT, EXCL, NOCTTY, NONBLOCK, or TRUNC}}
test iocmd-12.8 {POSIX open access modes: errors} {
list [catch {open $path(test3) {TRUNC CREAT}} msg] $msg
} {1 {access mode must include either RDONLY, WRONLY, or RDWR}}
close [open $path(test3) w]
+test iocmd-12.9 {POSIX open access modes: BINARY} {
+ list [catch {open $path(test1) BINARY} msg] $msg
+} {1 {access mode must include either RDONLY, WRONLY, or RDWR}}
+test iocmd-12.10 {POSIX open access modes: BINARY} {
+ set f [open $path(test1) {WRONLY BINARY TRUNC}]
+ puts $f a
+ puts $f b
+ puts -nonewline $f c ;# contents are now 5 bytes: a\nb\nc
+ close $f
+ set f [open $path(test1) r]
+ fconfigure $f -translation binary
+ set result [string length [read $f]]
+ close $f
+ set result
+} 5
+test iocmd-12.11 {POSIX open access modes: BINARY} {
+ set f [open $path(test1) {WRONLY BINARY TRUNC}]
+ puts $f \u0248 ;# gets truncated to \u0048
+ close $f
+ set f [open $path(test1) r]
+ fconfigure $f -translation binary
+ set result [read -nonewline $f]
+ close $f
+ set result
+} \u0048
test iocmd-13.1 {errors in open command} {
list [catch {open} msg] $msg
@@ -453,13 +484,20 @@ test iocmd-13.5 {errors in open command} {
list [catch {open $path(test1) r+1} msg] $msg
} {1 {illegal access mode "r+1"}}
test iocmd-13.6 {errors in open command} {
- set msg [list [catch {open _non_existent_} msg] $msg $errorCode]
+ set msg [list [catch {open _non_existent_} msg] $msg $::errorCode]
regsub [file join {} _non_existent_] $msg "_non_existent_" msg
- string tolower $msg
+ string tolower $msg
} {1 {couldn't open "_non_existent_": no such file or directory} {posix enoent {no such file or directory}}}
-
-
-test iocmd-13.7.1 {open for append, a mode} -setup {
+test iocmd-13.7 {errors in open command} {
+ list [catch {open $path(test1) b} msg] $msg
+} {1 {illegal access mode "b"}}
+test iocmd-13.8 {errors in open command} {
+ list [catch {open $path(test1) rbb} msg] $msg
+} {1 {illegal access mode "rbb"}}
+test iocmd-13.9 {errors in open command} {
+ list [catch {open $path(test1) r++} msg] $msg
+} {1 {illegal access mode "r++"}}
+test iocmd-13.10.1 {open for append, a mode} -setup {
set log [makeFile {} out]
set chans {}
} -body {
@@ -474,8 +512,7 @@ test iocmd-13.7.1 {open for append, a mode} -setup {
# Ensure that channels are gone, even if body failed to do so
foreach ch $chans {catch {close $ch}}
} -result {0 1 2 3 4 5 6 7 8 9}
-
-test iocmd-13.7.2 {open for append, O_APPEND} -setup {
+test iocmd-13.10.2 {open for append, O_APPEND} -setup {
set log [makeFile {} out]
set chans {}
} -body {
@@ -491,12 +528,9 @@ test iocmd-13.7.2 {open for append, O_APPEND} -setup {
foreach ch $chans {catch {close $ch}}
} -result {0 1 2 3 4 5 6 7 8 9}
-
-
-
test iocmd-14.1 {file id parsing errors} {
- list [catch {eof gorp} msg] $msg $errorCode
-} {1 {can not find channel named "gorp"} NONE}
+ list [catch {eof gorp} msg] $msg $::errorCode
+} {1 {can not find channel named "gorp"} {TCL LOOKUP CHANNEL gorp}}
test iocmd-14.2 {file id parsing errors} {
list [catch {eof filex} msg] $msg
} {1 {can not find channel named "filex"}}
@@ -547,10 +581,8 @@ test iocmd-15.5 {Tcl_FcopyObjCmd} {fcopy} {
} {1 {wrong # args: should be "fcopy input output ?-size size? ?-command callback?"}}
set path(test2) [makeFile {} test2]
-
set f [open $path(test1) w]
close $f
-
set rfile [open $path(test1) r]
set wfile [open $path(test2) w]
@@ -576,10 +608,2938 @@ test iocmd-15.12 {Tcl_FcopyObjCmd} {fcopy} {
list [catch {fcopy $rfile $wfile -command bar -size foo} msg] $msg
} {1 {expected integer but got "foo"}}
-
close $rfile
close $wfile
+# ### ### ### ######### ######### #########
+## Testing the reflected channel.
+
+test iocmd-20.0 {chan, wrong#args} {
+ catch {chan} msg
+ set msg
+} {wrong # args: should be "chan subcommand ?argument ...?"}
+test iocmd-20.1 {chan, unknown method} {
+ catch {chan foo} msg
+ set msg
+} {unknown or ambiguous subcommand "foo": must be blocked, close, configure, copy, create, eof, event, flush, gets, names, pending, postevent, puts, read, seek, tell, or truncate}
+
+# --- --- --- --------- --------- ---------
+# chan create, and method "initalize"
+
+test iocmd-21.0 {chan create, wrong#args, not enough} {
+ catch {chan create} msg
+ set msg
+} {wrong # args: should be "chan create mode cmdprefix"}
+test iocmd-21.1 {chan create, wrong#args, too many} {
+ catch {chan create a b c} msg
+ set msg
+} {wrong # args: should be "chan create mode cmdprefix"}
+test iocmd-21.2 {chan create, invalid r/w mode, empty} {
+ proc foo {} {}
+ catch {chan create {} foo} msg
+ rename foo {}
+ set msg
+} {bad mode list: is empty}
+test iocmd-21.3 {chan create, invalid r/w mode, bad string} {
+ proc foo {} {}
+ catch {chan create {c} foo} msg
+ rename foo {}
+ set msg
+} {bad mode "c": must be read or write}
+test iocmd-21.4 {chan create, bad handler, not a list} {
+ catch {chan create {r w} "foo \{"} msg
+ set msg
+} {unmatched open brace in list}
+test iocmd-21.5 {chan create, bad handler, not a command} {
+ catch {chan create {r w} foo} msg
+ set msg
+} {invalid command name "foo"}
+test iocmd-21.6 {chan create, initialize failed, bad signature} {
+ proc foo {} {}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} {wrong # args: should be "foo"}
+test iocmd-21.7 {chan create, initialize failed, bad signature} {
+ proc foo {} {}
+ catch {chan create {r w} ::foo} msg
+ rename foo {}
+ set msg
+} {wrong # args: should be "::foo"}
+test iocmd-21.8 {chan create, initialize failed, bad result, not a list} -body {
+ proc foo {args} {return "\{"}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set ::errorInfo
+} -match glob -result {chan handler "foo initialize" returned non-list: *}
+test iocmd-21.9 {chan create, initialize failed, bad result, not a list} -body {
+ proc foo {args} {return \{\{\}}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} -match glob -result {chan handler "foo initialize" returned non-list: *}
+test iocmd-21.10 {chan create, initialize failed, bad result, empty list} -body {
+ proc foo {args} {}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} -match glob -result {*all required methods*}
+test iocmd-21.11 {chan create, initialize failed, bad result, bogus method name} -body {
+ proc foo {args} {return 1}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} -match glob -result {*bad method "1": must be *}
+test iocmd-21.12 {chan create, initialize failed, bad result, bogus method name} -body {
+ proc foo {args} {return {a b c}}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} -match glob -result {*bad method "c": must be *}
+test iocmd-21.13 {chan create, initialize failed, bad result, required methods missing} -body {
+ proc foo {args} {return {initialize finalize}}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} -match glob -result {*all required methods*}
+test iocmd-21.14 {chan create, initialize failed, bad result, mode/handler mismatch} -body {
+ proc foo {args} {return {initialize finalize watch read}}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} -match glob -result {*lacks a "write" method}
+test iocmd-21.15 {chan create, initialize failed, bad result, mode/handler mismatch} -body {
+ proc foo {args} {return {initialize finalize watch write}}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} -match glob -result {*lacks a "read" method}
+test iocmd-21.16 {chan create, initialize failed, bad result, cget(all) mismatch} -body {
+ proc foo {args} {return {initialize finalize watch cget write read}}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} -match glob -result {*supports "cget" but not "cgetall"}
+test iocmd-21.17 {chan create, initialize failed, bad result, cget(all) mismatch} -body {
+ proc foo {args} {return {initialize finalize watch cgetall read write}}
+ catch {chan create {r w} foo} msg
+ rename foo {}
+ set msg
+} -match glob -result {*supports "cgetall" but not "cget"}
+test iocmd-21.18 {chan create, initialize ok, creates channel} -match glob -body {
+ proc foo {args} {
+ global res
+ lappend res $args
+ if {[lindex $args 0] ne "initialize"} {return}
+ return {initialize finalize watch read write}
+ }
+ set res {}
+ lappend res [file channel rc*]
+ lappend res [chan create {r w} foo]
+ lappend res [close [lindex $res end]]
+ lappend res [file channel rc*]
+ rename foo {}
+ set res
+} -result {{} {initialize rc* {read write}} rc* {finalize rc*} {} {}}
+test iocmd-21.19 {chan create, init failure -> no channel, no finalize} -match glob -body {
+ proc foo {args} {
+ global res
+ lappend res $args
+ return {}
+ }
+ set res {}
+ lappend res [file channel rc*]
+ lappend res [catch {chan create {r w} foo} msg]
+ lappend res $msg
+ lappend res [file channel rc*]
+ rename foo {}
+ set res
+} -result {{} {initialize rc* {read write}} 1 {*all required methods*} {}}
+
+# --- --- --- --------- --------- ---------
+# Helper commands to record the arguments to handler methods.
+
+# Stored in a script so that the threads and interpreters needing this
+# code do not need their own copy but can access this variable.
+
+set helperscript {
+
+proc note {item} {global res; lappend res $item; return}
+proc track {} {upvar args item; note $item; return}
+proc notes {items} {foreach i $items {note $i}}
+# This forces the return options to be in the order that the test expects!
+proc noteOpts opts {global res; lappend res [dict merge {
+ -code !?! -level !?! -errorcode !?! -errorline !?! -errorinfo !?!
+} $opts]; return}
+
+# Helper command, canned result for 'initialize' method.
+# Gets the optional methods as arguments. Use return features
+# to post the result higher up.
+
+proc init {args} {
+ lappend args initialize finalize watch read write
+ return -code return $args
+}
+proc oninit {args} {
+ upvar args hargs
+ if {[lindex $hargs 0] ne "initialize"} {return}
+ lappend args initialize finalize watch read write
+ return -code return $args
+}
+proc onfinal {} {
+ upvar args hargs
+ if {[lindex $hargs 0] ne "finalize"} {return}
+ return -code return ""
+}
+}
+
+# Set everything up in the main thread.
+eval $helperscript
+
+# --- --- --- --------- --------- ---------
+# method finalize
+
+test iocmd-22.1 {chan finalize, handler destruction has no effect on channel} -match glob -body {
+ set res {}
+ proc foo {args} {track; oninit; return}
+ note [set c [chan create {r w} foo]]
+ rename foo {}
+ note [file channels rc*]
+ note [catch {close $c} msg]; note $msg
+ note [file channels rc*]
+ set res
+} -result {{initialize rc* {read write}} rc* rc* 1 {invalid command name "foo"} {}}
+test iocmd-22.2 {chan finalize, for close} -match glob -body {
+ set res {}
+ proc foo {args} {track; oninit; return {}}
+ note [set c [chan create {r w} foo]]
+ close $c
+ # Close deleted the channel.
+ note [file channels rc*]
+ # Channel destruction does not kill handler command!
+ note [info command foo]
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} {} foo}
+test iocmd-22.3 {chan finalize, for close, error, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track; oninit; return -code error 5}
+ note [set c [chan create {r w} foo]]
+ note [catch {close $c} msg]; note $msg
+ # Channel is gone despite error.
+ note [file channels rc*]
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 5 {}}
+test iocmd-22.4 {chan finalize, for close, error, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track; oninit; error FOO}
+ note [set c [chan create {r w} foo]]
+ note [catch {close $c} msg]; note $msg; note $::errorInfo
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 FOO {FOO
+*"close $c"}}
+test iocmd-22.5 {chan finalize, for close, arbitrary result, ignored} -match glob -body {
+ set res {}
+ proc foo {args} {track; oninit; return SOMETHING}
+ note [set c [chan create {r w} foo]]
+ note [catch {close $c} msg]; note $msg
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 0 {}}
+test iocmd-22.6 {chan finalize, for close, break, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track; oninit; return -code 3}
+ note [set c [chan create {r w} foo]]
+ note [catch {close $c} msg]; note $msg
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 *bad code*}
+test iocmd-22.7 {chan finalize, for close, continue, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track; oninit; return -code 4}
+ note [set c [chan create {r w} foo]]
+ note [catch {close $c} msg]; note $msg
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 *bad code*}
+test iocmd-22.8 {chan finalize, for close, custom code, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track; oninit; return -code 777 BANG}
+ note [set c [chan create {r w} foo]]
+ note [catch {close $c} msg]; note $msg
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 *bad code*}
+test iocmd-22.9 {chan finalize, for close, ignore level, close error} -match glob -setup {
+ set res {}
+} -body {
+ proc foo {args} {track; oninit; return -level 5 -code 777 BANG}
+ note [set c [chan create {r w} foo]]
+ note [catch {close $c} msg opt]; note $msg; noteOpts $opt
+ return $res
+} -cleanup {
+ rename foo {}
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 *bad code* {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo *bad code*subcommand "finalize"*}}
+
+# --- === *** ###########################
+# method read
+
+test iocmd-23.1 {chan read, regular data return} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ return snarf
+ }
+ set c [chan create {r w} foo]
+ note [read $c 10]
+ close $c
+ rename foo {}
+ set res
+} -result {{read rc* 4096} {read rc* 4096} snarfsnarf}
+test iocmd-23.2 {chan read, bad data return, to much} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ return [string repeat snarf 1000]
+ }
+ set c [chan create {r w} foo]
+ note [catch {read $c 2} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 {read delivered more than requested}}
+test iocmd-23.3 {chan read, for non-readable channel} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track; note MUST_NOT_HAPPEN
+ }
+ set c [chan create {w} foo]
+ note [catch {read $c 2} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {1 {channel "rc*" wasn't opened for reading}}
+test iocmd-23.4 {chan read, error return} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ return -code error BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {read $c 2} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 BOOM!}
+test iocmd-23.5 {chan read, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ return -code break BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {read $c 2} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 *bad code*}
+test iocmd-23.6 {chan read, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ return -code continue BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {read $c 2} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 *bad code*}
+test iocmd-23.7 {chan read, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ return -code 777 BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {read $c 2} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 *bad code*}
+test iocmd-23.8 {chan read, level is squashed} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ return -level 55 -code 777 BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {read $c 2} msg opt]; note $msg; noteOpts $opt
+ close $c
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 *bad code* {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo *bad code*subcommand "read"*}}
+test iocmd-23.9 {chan read, no data means eof} -match glob -setup {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ return ""
+ }
+ set c [chan create {r w} foo]
+} -body {
+ note [read $c 2]
+ note [eof $c]
+ set res
+} -cleanup {
+ close $c
+ rename foo {}
+ unset res
+} -result {{read rc* 4096} {} 1}
+test iocmd-23.10 {chan read, EAGAIN means no data, yet no eof either} -match glob -setup {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ error EAGAIN
+ }
+ set c [chan create {r w} foo]
+} -body {
+ note [read $c 2]
+ note [eof $c]
+ set res
+} -cleanup {
+ close $c
+ rename foo {}
+ unset res
+} -result {{read rc* 4096} {} 0}
+
+# --- === *** ###########################
+# method write
+
+test iocmd-24.1 {chan write, regular write} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ set written [string length [lindex $args 2]]
+ note $written
+ return $written
+ }
+ set c [chan create {r w} foo]
+ puts -nonewline $c snarf; flush $c
+ close $c
+ rename foo {}
+ set res
+} -result {{write rc* snarf} 5}
+test iocmd-24.2 {chan write, partial write is ok} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ set written [string length [lindex $args 2]]
+ if {$written > 10} {set written [expr {$written / 2}]}
+ note $written
+ return $written
+ }
+ set c [chan create {r w} foo]
+ puts -nonewline $c snarfsnarfsnarf; flush $c
+ close $c
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 7 {write rc* arfsnarf} 8}
+test iocmd-24.3 {chan write, failed write} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; note -1; return -1}
+ set c [chan create {r w} foo]
+ puts -nonewline $c snarfsnarfsnarf; flush $c
+ close $c
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} -1}
+test iocmd-24.4 {chan write, non-writable channel} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; note MUST_NOT_HAPPEN; return}
+ set c [chan create {r} foo]
+ note [catch {puts -nonewline $c snarfsnarfsnarf; flush $c} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {1 {channel "rc*" wasn't opened for writing}}
+test iocmd-24.5 {chan write, bad result, more written than data} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return 10000}
+ set c [chan create {r w} foo]
+ note [catch {puts -nonewline $c snarf; flush $c} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{write rc* snarf} 1 {write wrote more than requested}}
+test iocmd-24.6 {chan write, bad result, zero-length write} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return 0}
+ set c [chan create {r w} foo]
+ note [catch {puts -nonewline $c snarf; flush $c} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{write rc* snarf} 1 {write wrote nothing}}
+test iocmd-24.7 {chan write, failed write, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return -code error BOOM!}
+ set c [chan create {r w} foo]
+ note [catch {puts -nonewline $c snarfsnarfsnarf; flush $c} msg]
+ note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 BOOM!}
+test iocmd-24.8 {chan write, failed write, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; error BOOM!}
+ set c [chan create {r w} foo]
+ notes [catch {puts -nonewline $c snarfsnarfsnarf; flush $c} msg]
+ note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 BOOM!}
+test iocmd-24.9 {chan write, failed write, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return -code break BOOM!}
+ set c [chan create {r w} foo]
+ note [catch {puts -nonewline $c snarfsnarfsnarf; flush $c} msg]
+ note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 *bad code*}
+test iocmd-24.10 {chan write, failed write, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return -code continue BOOM!}
+ set c [chan create {r w} foo]
+ note [catch {puts -nonewline $c snarfsnarfsnarf; flush $c} msg]
+ note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 *bad code*}
+test iocmd-24.11 {chan write, failed write, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return -code 777 BOOM!}
+ set c [chan create {r w} foo]
+ note [catch {puts -nonewline $c snarfsnarfsnarf; flush $c} msg]
+ note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 *bad code*}
+test iocmd-24.12 {chan write, failed write, non-numeric return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return BANG}
+ set c [chan create {r w} foo]
+ note [catch {puts -nonewline $c snarfsnarfsnarf; flush $c} msg]
+ note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 {expected integer but got "BANG"}}
+test iocmd-24.13 {chan write, failed write, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return -level 55 -code 777 BOOM!}
+ set c [chan create {r w} foo]
+ note [catch {puts -nonewline $c snarfsnarfsnarf; flush $c} msg opt]
+ note $msg
+ noteOpts $opt
+ close $c
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 *bad code* {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo *bad code*subcommand "write"*}}
+test iocmd-24.14 {chan write, no EAGAIN means that writing is allowed at this time, bug 2936225} -match glob -setup {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ return 3
+ }
+ set c [chan create {r w} foo]
+} -body {
+ note [puts -nonewline $c ABC ; flush $c]
+ set res
+} -cleanup {
+ close $c
+ rename foo {}
+ unset res
+} -result {{write rc* ABC} {}}
+test iocmd-24.15 {chan write, EAGAIN means that writing is not allowed at this time, bug 2936225} -match glob -setup {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ # Note: The EAGAIN signals that the channel cannot accept
+ # write requests right now, this in turn causes the IO core to
+ # request the generation of writable events (see expected
+ # result below, and compare to case 24.14 above).
+ error EAGAIN
+ }
+ set c [chan create {r w} foo]
+} -body {
+ note [puts -nonewline $c ABC ; flush $c]
+ set res
+} -cleanup {
+ close $c
+ rename foo {}
+ unset res
+} -result {{write rc* ABC} {watch rc* write} {}}
+
+# --- === *** ###########################
+# method cgetall
+
+test iocmd-25.1 {chan configure, cgetall, standard options} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; note MUST_NOT_HAPPEN; return}
+ set c [chan create {r w} foo]
+ note [fconfigure $c]
+ close $c
+ rename foo {}
+ set res
+} -result {{-blocking 1 -buffering full -buffersize 4096 -encoding * -eofchar {{} {}} -translation {auto *}}}
+test iocmd-25.2 {chan configure, cgetall, no options} -match glob -body {
+ set res {}
+ proc foo {args} {oninit cget cgetall; onfinal; track; return ""}
+ set c [chan create {r w} foo]
+ note [fconfigure $c]
+ close $c
+ rename foo {}
+ set res
+} -result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * -eofchar {{} {}} -translation {auto *}}}
+test iocmd-25.3 {chan configure, cgetall, regular result} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return "-bar foo -snarf x"
+ }
+ set c [chan create {r w} foo]
+ note [fconfigure $c]
+ close $c
+ rename foo {}
+ set res
+} -result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * -eofchar {{} {}} -translation {auto *} -bar foo -snarf x}}
+test iocmd-25.4 {chan configure, cgetall, bad result, list of uneven length} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return "-bar"
+ }
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 {Expected list with even number of elements, got 1 element instead}}
+test iocmd-25.5 {chan configure, cgetall, bad result, not a list} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return "\{"
+ }
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 {unmatched open brace in list}}
+test iocmd-25.6 {chan configure, cgetall, error return} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return -code error BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 BOOM!}
+test iocmd-25.7 {chan configure, cgetall, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return -code break BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 *bad code*}
+test iocmd-25.8 {chan configure, cgetall, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return -code continue BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 *bad code*}
+test iocmd-25.9 {chan configure, cgetall, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return -code 777 BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 *bad code*}
+test iocmd-25.10 {chan configure, cgetall, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return -level 55 -code 777 BANG
+ }
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c} msg opt]; note $msg; noteOpts $opt
+ close $c
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 *bad code* {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo *bad code*subcommand "cgetall"*}}
+
+# --- === *** ###########################
+# method configure
+
+test iocmd-26.1 {chan configure, set standard option} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure; onfinal; track; note MUST_NOT_HAPPEN; return
+ }
+ set c [chan create {r w} foo]
+ note [fconfigure $c -translation lf]
+ close $c
+ rename foo {}
+ set res
+} -result {{}}
+test iocmd-26.2 {chan configure, set option, error return} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure; onfinal; track
+ return -code error BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c -rc-foo bar} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{configure rc* -rc-foo bar} 1 BOOM!}
+test iocmd-26.3 {chan configure, set option, ok return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit configure; onfinal; track; return}
+ set c [chan create {r w} foo]
+ note [fconfigure $c -rc-foo bar]
+ close $c
+ rename foo {}
+ set res
+} -result {{configure rc* -rc-foo bar} {}}
+test iocmd-26.4 {chan configure, set option, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure; onfinal; track
+ return -code break BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c -rc-foo bar} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{configure rc* -rc-foo bar} 1 *bad code*}
+test iocmd-26.5 {chan configure, set option, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure; onfinal; track
+ return -code continue BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c -rc-foo bar} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{configure rc* -rc-foo bar} 1 *bad code*}
+test iocmd-26.6 {chan configure, set option, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure; onfinal; track
+ return -code 444 BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c -rc-foo bar} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{configure rc* -rc-foo bar} 1 *bad code*}
+test iocmd-26.7 {chan configure, set option, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure; onfinal; track
+ return -level 55 -code 444 BANG
+ }
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c -rc-foo bar} msg opt]; note $msg; noteOpts $opt
+ close $c
+ rename foo {}
+ set res
+} -result {{configure rc* -rc-foo bar} 1 *bad code* {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo *bad code*subcommand "configure"*}}
+
+# --- === *** ###########################
+# method cget
+
+test iocmd-27.1 {chan configure, get option, ok return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit cget cgetall; onfinal; track; return foo}
+ set c [chan create {r w} foo]
+ note [fconfigure $c -rc-foo]
+ close $c
+ rename foo {}
+ set res
+} -result {{cget rc* -rc-foo} foo}
+test iocmd-27.2 {chan configure, get option, error return} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return -code error BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c -rc-foo} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{cget rc* -rc-foo} 1 BOOM!}
+test iocmd-27.3 {chan configure, get option, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return -code error BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c -rc-foo} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{cget rc* -rc-foo} 1 BOOM!}
+test iocmd-27.4 {chan configure, get option, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return -code continue BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c -rc-foo} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{cget rc* -rc-foo} 1 *bad code*}
+test iocmd-27.5 {chan configure, get option, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return -code 333 BOOM!
+ }
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c -rc-foo} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{cget rc* -rc-foo} 1 *bad code*}
+test iocmd-27.6 {chan configure, get option, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return -level 77 -code 333 BANG
+ }
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c -rc-foo} msg opt]; note $msg; noteOpts $opt
+ close $c
+ rename foo {}
+ set res
+} -result {{cget rc* -rc-foo} 1 *bad code* {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo *bad code*subcommand "cget"*}}
+
+# --- === *** ###########################
+# method seek
+
+test iocmd-28.1 {chan tell, not supported by handler} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; note MUST_NOT_HAPPEN; return}
+ set c [chan create {r w} foo]
+ note [tell $c]
+ close $c
+ rename foo {}
+ set res
+} -result {-1}
+test iocmd-28.2 {chan tell, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -code error BOOM!}
+ set c [chan create {r w} foo]
+ note [catch {tell $c} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 BOOM!}
+test iocmd-28.3 {chan tell, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -code break BOOM!}
+ set c [chan create {r w} foo]
+ note [catch {tell $c} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 *bad code*}
+test iocmd-28.4 {chan tell, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -code continue BOOM!}
+ set c [chan create {r w} foo]
+ note [catch {tell $c} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 *bad code*}
+test iocmd-28.5 {chan tell, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -code 222 BOOM!}
+ set c [chan create {r w} foo]
+ note [catch {tell $c} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 *bad code*}
+test iocmd-28.6 {chan tell, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -level 11 -code 222 BANG}
+ set c [chan create {r w} foo]
+ note [catch {tell $c} msg opt]; note $msg; noteOpts $opt
+ close $c
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 *bad code* {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo *bad code*subcommand "seek"*}}
+test iocmd-28.7 {chan tell, regular return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return 88}
+ set c [chan create {r w} foo]
+ note [tell $c]
+ close $c
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 88}
+test iocmd-28.8 {chan tell, negative return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -1}
+ set c [chan create {r w} foo]
+ note [catch {tell $c} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 {Tried to seek before origin}}
+test iocmd-28.9 {chan tell, string return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return BOGUS}
+ set c [chan create {r w} foo]
+ note [catch {tell $c} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 {expected integer but got "BOGUS"}}
+test iocmd-28.10 {chan seek, not supported by handler} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; note MUST_NOT_HAPPEN; return}
+ set c [chan create {r w} foo]
+ note [catch {seek $c 0 start} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {1 {error during seek on "rc*": invalid argument}}
+test iocmd-28.11 {chan seek, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -code error BOOM!}
+ set c [chan create {r w} foo]
+ note [catch {seek $c 0 start} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 BOOM!}
+test iocmd-28.12 {chan seek, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -code break BOOM!}
+ set c [chan create {r w} foo]
+ note [catch {seek $c 0 start} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 *bad code*}
+test iocmd-28.13 {chan seek, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -code continue BOOM!}
+ set c [chan create {r w} foo]
+ note [catch {seek $c 0 start} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 *bad code*}
+test iocmd-28.14 {chan seek, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -code 99 BOOM!}
+ set c [chan create {r w} foo]
+ note [catch {seek $c 0 start} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 *bad code*}
+test iocmd-28.15 {chan seek, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -level 33 -code 99 BANG}
+ set c [chan create {r w} foo]
+ note [catch {seek $c 0 start} msg opt]; note $msg; noteOpts $opt
+ close $c
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 *bad code* {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo *bad code*subcommand "seek"*}}
+test iocmd-28.16 {chan seek, bogus return, negative location} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -45}
+ set c [chan create {r w} foo]
+ note [catch {seek $c 0 start} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 {Tried to seek before origin}}
+test iocmd-28.17 {chan seek, bogus return, string return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return BOGUS}
+ set c [chan create {r w} foo]
+ note [catch {seek $c 0 start} msg]; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 {expected integer but got "BOGUS"}}
+test iocmd-28.18 {chan seek, ok result} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return 23}
+ set c [chan create {r w} foo]
+ note [seek $c 0 current]
+ close $c
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} {}}
+foreach {testname code} {
+ iocmd-28.19.0 start
+ iocmd-28.19.1 current
+ iocmd-28.19.2 end
+} {
+ test $testname "chan seek, base conversion, $code" -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return 0}
+ set c [chan create {r w} foo]
+ note [seek $c 0 $code]
+ close $c
+ rename foo {}
+ set res
+ } -result [list [list seek rc* 0 $code] {}]
+}
+
+# --- === *** ###########################
+# method blocking
+
+test iocmd-29.1 {chan blocking, no handler support} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; note MUST_NOT_HAPPEN; return}
+ set c [chan create {r w} foo]
+ note [fconfigure $c -blocking]
+ close $c
+ rename foo {}
+ set res
+} -result {1}
+test iocmd-29.2 {chan blocking, no handler support} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; note MUST_NOT_HAPPEN; return}
+ set c [chan create {r w} foo]
+ note [fconfigure $c -blocking 0]
+ note [fconfigure $c -blocking]
+ close $c
+ rename foo {}
+ set res
+} -result {{} 0}
+test iocmd-29.3 {chan blocking, retrieval, handler support} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking; onfinal; track; note MUST_NOT_HAPPEN; return}
+ set c [chan create {r w} foo]
+ note [fconfigure $c -blocking]
+ close $c
+ rename foo {}
+ set res
+} -result {1}
+test iocmd-29.4 {chan blocking, resetting, handler support} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking; onfinal; track; return}
+ set c [chan create {r w} foo]
+ note [fconfigure $c -blocking 0]
+ note [fconfigure $c -blocking]
+ close $c
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} {} 0}
+test iocmd-29.5 {chan blocking, setting, handler support} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking; onfinal; track; return}
+ set c [chan create {r w} foo]
+ note [fconfigure $c -blocking 1]
+ note [fconfigure $c -blocking]
+ close $c
+ rename foo {}
+ set res
+} -result {{blocking rc* 1} {} 1}
+test iocmd-29.6 {chan blocking, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking; onfinal; track; error BOOM!}
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c -blocking 0} msg]; note $msg
+ # Catch the close. It changes blocking mode internally, and runs into the error result.
+ catch {close $c}
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 1 BOOM!}
+test iocmd-29.7 {chan blocking, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking; onfinal; track; return -code break BOOM!}
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c -blocking 0} msg]; note $msg
+ catch {close $c}
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 1 *bad code*}
+test iocmd-29.8 {chan blocking, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking; onfinal; track; return -code continue BOOM!}
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c -blocking 0} msg]; note $msg
+ catch {close $c}
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 1 *bad code*}
+test iocmd-29.9 {chan blocking, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking; onfinal; track; return -code 44 BOOM!}
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c -blocking 0} msg]; note $msg
+ catch {close $c}
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 1 *bad code*}
+test iocmd-29.10 {chan blocking, level is ignored} -match glob -setup {
+ set res {}
+} -body {
+ proc foo {args} {oninit blocking; onfinal; track; return -level 99 -code 44 BANG}
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c -blocking 0} msg opt]; note $msg; noteOpts $opt
+ catch {close $c}
+ return $res
+} -cleanup {
+ rename foo {}
+} -result {{blocking rc* 0} 1 *bad code* {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo *bad code*subcommand "blocking"*}}
+test iocmd-29.11 {chan blocking, regular return ok, value ignored} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking; onfinal; track; return BOGUS}
+ set c [chan create {r w} foo]
+ note [catch {fconfigure $c -blocking 0} msg]; note $msg
+ catch {close $c}
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 0 {}}
+
+# --- === *** ###########################
+# method watch
+
+test iocmd-30.1 {chan watch, read interest, some return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return IGNORED}
+ set c [chan create {r w} foo]
+ note [fileevent $c readable {set tick $tick}]
+ close $c ;# 2nd watch, interest zero.
+ rename foo {}
+ set res
+} -result {{watch rc* read} {} {watch rc* {}}}
+test iocmd-30.2 {chan watch, write interest, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return -code error BOOM!_IGNORED}
+ set c [chan create {r w} foo]
+ note [fileevent $c writable {set tick $tick}]
+ note [fileevent $c writable {}]
+ close $c
+ rename foo {}
+ set res
+} -result {{watch rc* write} {} {watch rc* {}} {}}
+test iocmd-30.3 {chan watch, accumulated interests} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return}
+ set c [chan create {r w} foo]
+ note [fileevent $c writable {set tick $tick}]
+ note [fileevent $c readable {set tick $tick}]
+ note [fileevent $c writable {}]
+ note [fileevent $c readable {}]
+ close $c
+ rename foo {}
+ set res
+} -result {{watch rc* write} {} {watch rc* {read write}} {} {watch rc* read} {} {watch rc* {}} {}}
+test iocmd-30.4 {chan watch, unchanged interest not forwarded} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return}
+ set c [chan create {r w} foo]
+ note [fileevent $c writable {set tick $tick}]
+ note [fileevent $c readable {set tick $tick}] ;# Script is changing,
+ note [fileevent $c readable {set tock $tock}] ;# interest does not.
+ close $c ;# 3rd and 4th watch, removing the event handlers.
+ rename foo {}
+ set res
+} -result {{watch rc* write} {} {watch rc* {read write}} {} {} {watch rc* write} {watch rc* {}}}
+
+# --- === *** ###########################
+# chan postevent
+
+test iocmd-31.1 {chan postevent, restricted to reflected channels} -match glob -body {
+ set c [open [makeFile {} goo] r]
+ catch {chan postevent $c {r w}} msg
+ close $c
+ removeFile goo
+ set msg
+} -result {can not find reflected channel named "file*"}
+test iocmd-31.2 {chan postevent, unwanted events} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return}
+ set c [chan create {r w} foo]
+ catch {chan postevent $c {r w}} msg; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{tried to post events channel "rc*" is not interested in}}
+test iocmd-31.3 {chan postevent, bad input, empty list} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return}
+ set c [chan create {r w} foo]
+ catch {chan postevent $c {}} msg; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{bad event list: is empty}}
+test iocmd-31.4 {chan postevent, bad input, illlegal keyword} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return}
+ set c [chan create {r w} foo]
+ catch {chan postevent $c goo} msg; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{bad event "goo": must be read or write}}
+test iocmd-31.5 {chan postevent, bad input, not a list} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return}
+ set c [chan create {r w} foo]
+ catch {chan postevent $c "\{"} msg; note $msg
+ close $c
+ rename foo {}
+ set res
+} -result {{unmatched open brace in list}}
+test iocmd-31.6 {chan postevent, posted events do happen} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return}
+ set c [chan create {r w} foo]
+ note [fileevent $c readable {note TOCK}]
+ set stop [after 10000 {note TIMEOUT}]
+ after 1000 {note [chan postevent $c r]}
+ vwait ::res
+ catch {after cancel $stop}
+ close $c
+ rename foo {}
+ set res
+} -result {{watch rc* read} {} TOCK {} {watch rc* {}}}
+test iocmd-31.7 {chan postevent, posted events do happen} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return}
+ set c [chan create {r w} foo]
+ note [fileevent $c writable {note TOCK}]
+ set stop [after 10000 {note TIMEOUT}]
+ after 1000 {note [chan postevent $c w]}
+ vwait ::res
+ catch {after cancel $stop}
+ close $c
+ rename foo {}
+ set res
+} -result {{watch rc* write} {} TOCK {} {watch rc* {}}}
+test iocmd-31.8 {chan postevent after close throws error} -match glob -setup {
+ proc foo {args} {oninit; onfinal; track; return}
+ proc dummy args { return }
+ set c [chan create {r w} foo]
+ fileevent $c readable dummy
+} -body {
+ close $c
+ chan postevent $c read
+} -cleanup {
+ rename foo {}
+ rename dummy {}
+} -returnCodes error -result {can not find reflected channel named "rc*"}
+
+# --- === *** ###########################
+# 'Pull the rug' tests. Create channel in a interpreter A, move to
+# other interpreter B, destroy the origin interpreter (A) before or
+# during access from B. Must not crash, must return proper errors.
+
+test iocmd-32.0 {origin interpreter of moved channel gone} -match glob -body {
+
+ set ida [interp create];#puts <<$ida>>
+ set idb [interp create];#puts <<$idb>>
+
+ # Magic to get the test* commands in the slaves
+ load {} Tcltest $ida
+ load {} Tcltest $idb
+
+ # Set up channel in interpreter
+ interp eval $ida $helperscript
+ set chan [interp eval $ida {
+ proc foo {args} {oninit seek; onfinal; track; return}
+ set chan [chan create {r w} foo]
+ fconfigure $chan -buffering none
+ set chan
+ }]
+
+ # Move channel to 2nd interpreter.
+ interp eval $ida [list testchannel cut $chan]
+ interp eval $idb [list testchannel splice $chan]
+
+ # Kill origin interpreter, then access channel from 2nd interpreter.
+ interp delete $ida
+
+ set res {}
+ lappend res [catch {interp eval $idb [list puts $chan shoo]} msg] $msg
+ lappend res [catch {interp eval $idb [list tell $chan]} msg] $msg
+ lappend res [catch {interp eval $idb [list seek $chan 1]} msg] $msg
+ lappend res [catch {interp eval $idb [list gets $chan]} msg] $msg
+ lappend res [catch {interp eval $idb [list close $chan]} msg] $msg
+ set res
+
+} -constraints {testchannel} \
+ -result {1 {Owner lost} 1 {Owner lost} 1 {Owner lost} 1 {Owner lost} 1 {Owner lost}}
+
+test iocmd-32.1 {origin interpreter of moved channel destroyed during access} -match glob -body {
+
+ set ida [interp create];#puts <<$ida>>
+ set idb [interp create];#puts <<$idb>>
+
+ # Magic to get the test* commands in the slaves
+ load {} Tcltest $ida
+ load {} Tcltest $idb
+
+ # Set up channel in thread
+ set chan [interp eval $ida $helperscript]
+ set chan [interp eval $ida {
+ proc foo {args} {
+ oninit; onfinal; track;
+ # destroy interpreter during channel access
+ # Actually not possible for an interp to destroy itself.
+ interp delete {}
+ return}
+ set chan [chan create {r w} foo]
+ fconfigure $chan -buffering none
+ set chan
+ }]
+
+ # Move channel to 2nd thread.
+ interp eval $ida [list testchannel cut $chan]
+ interp eval $idb [list testchannel splice $chan]
+
+ # Run access from interpreter B, this will give us a synchronous
+ # response.
+
+ interp eval $idb [list set chan $chan]
+ interp eval $idb [list set mid $tcltest::mainThread]
+ set res [interp eval $idb {
+ # wait a bit, give the main thread the time to start its event
+ # loop to wait for the response from B
+ after 2000
+ catch { puts $chan shoo } res
+ set res
+ }]
+ set res
+} -constraints {testchannel impossible} \
+ -result {Owner lost}
+
+test iocmd-32.2 {delete interp of reflected chan} {
+ # Bug 3034840
+ # Run this test in an interp with memory debugging to panic
+ # on the double free
+ interp create slave
+ slave eval {
+ proc no-op args {}
+ proc driver {sub args} {return {initialize finalize watch read}}
+ chan event [chan create read driver] readable no-op
+ }
+ interp delete slave
+} {}
+
+# ### ### ### ######### ######### #########
+## Same tests as above, but exercising the code forwarding and
+## receiving driver operations to the originator thread.
+
+# -*- tcl -*-
+# ### ### ### ######### ######### #########
+## Testing the reflected channel (Thread forwarding).
+#
+## The id numbers refer to the original test without thread
+## forwarding, and gaps due to tests not applicable to forwarding are
+## left to keep this asociation.
+
+# Duplicate of code in "thread.test". Find a better way of doing this
+# without duplication. Maybe placement into a proc which transforms to
+# nop after the first call, and placement of its defintion in a
+# central location.
+
+if {[testConstraint testthread]} {
+ testthread errorproc ThreadError
+
+ proc ThreadError {id info} {
+ global threadError
+ set threadError $info
+ }
+ proc ThreadNullError {id info} {
+ # ignore
+ }
+}
+
+# ### ### ### ######### ######### #########
+## Helper command. Runs a script in a separate thread and returns the
+## result. A channel is transfered into the thread as well, and list of
+## configuation variables
+
+proc inthread {chan script args} {
+ # Test thread.
+
+ set tid [testthread create]
+
+ # Init thread configuration.
+ # - Listed variables
+ # - Id of main thread
+ # - A number of helper commands
+
+ foreach v $args {
+ upvar 1 $v x
+ testthread send $tid [list set $v $x]
+ }
+ testthread send $tid [list set mid $tcltest::mainThread]
+ testthread send $tid {
+ proc note {item} {global notes; lappend notes $item}
+ proc notes {} {global notes; return $notes}
+ proc noteOpts opts {global notes; lappend notes [dict merge {
+ -code !?! -level !?! -errorcode !?! -errorline !?! -errorinfo !?!
+ } $opts]}
+ }
+ testthread send $tid [list proc s {} [list uplevel 1 $script]]; # (*)
+
+ # Transfer channel (cut/splice aka detach/attach)
+
+ testchannel cut $chan
+ testthread send $tid [list testchannel splice $chan]
+
+ # Run test script, also run local event loop!
+ # The local event loop waits for the result to come back.
+ # It is also necessary for the execution of forwarded channel
+ # operations.
+
+ set ::tres ""
+ testthread send -async $tid {
+ after 500
+ catch {s} res; # This runs the script, 's' was defined at (*)
+ testthread send -async $mid [list set ::tres $res]
+ }
+ vwait ::tres
+ # Remove test thread, and return the captured result.
+
+ tcltest::threadReap
+ return $::tres
+}
+
+# ### ### ### ######### ######### #########
+
+# ### ### ### ######### ######### #########
+
+test iocmd.tf-22.2 {chan finalize, for close} -match glob -body {
+ set res {}
+ proc foo {args} {track; oninit; return {}}
+ note [set c [chan create {r w} foo]]
+ note [inthread $c {
+ close $c
+ # Close the deleted the channel.
+ file channels rc*
+ } c]
+ # Channel destruction does not kill handler command!
+ note [info command foo]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{initialize rc* {read write}} rc* {finalize rc*} {} foo}
+test iocmd.tf-22.3 {chan finalize, for close, error, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track; oninit; return -code error 5}
+ note [set c [chan create {r w} foo]]
+ notes [inthread $c {
+ note [catch {close $c} msg]; note $msg
+ # Channel is gone despite error.
+ note [file channels rc*]
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 5 {}}
+test iocmd.tf-22.4 {chan finalize, for close, error, close errror} -match glob -body {
+ set res {}
+ proc foo {args} {track; oninit; error FOO}
+ note [set c [chan create {r w} foo]]
+ notes [inthread $c {
+ note [catch {close $c} msg]; note $msg
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 FOO}
+test iocmd.tf-22.5 {chan finalize, for close, arbitrary result} -match glob -body {
+ set res {}
+ proc foo {args} {track; oninit; return SOMETHING}
+ note [set c [chan create {r w} foo]]
+ notes [inthread $c {
+ note [catch {close $c} msg]; note $msg
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{initialize rc* {read write}} rc* {finalize rc*} 0 {}}
+test iocmd.tf-22.6 {chan finalize, for close, break, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track; oninit; return -code 3}
+ note [set c [chan create {r w} foo]]
+ notes [inthread $c {
+ note [catch {close $c} msg]; note $msg
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-22.7 {chan finalize, for close, continue, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track; oninit; return -code 4}
+ note [set c [chan create {r w} foo]]
+ notes [inthread $c {
+ note [catch {close $c} msg]; note $msg
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-22.8 {chan finalize, for close, custom code, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track; oninit; return -code 777 BANG}
+ note [set c [chan create {r w} foo]]
+ notes [inthread $c {
+ note [catch {close $c} msg]; note $msg
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-22.9 {chan finalize, for close, ignore level, close error} -match glob -body {
+ set res {}
+ proc foo {args} {track; oninit; return -level 5 -code 777 BANG}
+ note [set c [chan create {r w} foo]]
+ notes [inthread $c {
+ note [catch {close $c} msg opt]; note $msg; noteOpts $opt
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{initialize rc* {read write}} rc* {finalize rc*} 1 *bad code* {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo *bad code*subcommand "finalize"*}} \
+ -constraints {testchannel testthread}
+
+# --- === *** ###########################
+# method read
+
+test iocmd.tf-23.1 {chan read, regular data return} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ return snarf
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [read $c 10]
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{read rc* 4096} {read rc* 4096} snarfsnarf}
+test iocmd.tf-23.2 {chan read, bad data return, to much} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ return [string repeat snarf 1000]
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {[read $c 2]} msg]; note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{read rc* 4096} 1 {read delivered more than requested}}
+test iocmd.tf-23.3 {chan read, for non-readable channel} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track; note MUST_NOT_HAPPEN
+ }
+ set c [chan create {w} foo]
+ notes [inthread $c {
+ note [catch {[read $c 2]} msg]; note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {1 {channel "rc*" wasn't opened for reading}}
+test iocmd.tf-23.4 {chan read, error return} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ return -code error BOOM!
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {read $c 2} msg]; note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 BOOM!} \
+ -constraints {testchannel testthread}
+test iocmd.tf-23.5 {chan read, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ return -code break BOOM!
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {read $c 2} msg]; note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-23.6 {chan read, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ return -code continue BOOM!
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {read $c 2} msg]; note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-23.7 {chan read, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ return -code 777 BOOM!
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {read $c 2} msg]; note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-23.8 {chan read, level is squashed} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ return -level 55 -code 777 BOOM!
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {read $c 2} msg opt]; note $msg; noteOpts $opt
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{read rc* 4096} 1 *bad code* {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo *bad code*subcommand "read"*}} \
+ -constraints {testchannel testthread}
+test iocmd.tf-23.9 {chan read, no data means eof} -match glob -setup {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ return ""
+ }
+ set c [chan create {r w} foo]
+} -body {
+ notes [inthread $c {
+ note [read $c 2]
+ note [eof $c]
+ close $c
+ notes
+ } c]
+ set res
+} -cleanup {
+ rename foo {}
+ unset res
+} -result {{read rc* 4096} {} 1} \
+ -constraints {testchannel testthread}
+test iocmd.tf-23.10 {chan read, EAGAIN means no data, yet no eof either} -match glob -setup {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ error EAGAIN
+ }
+ set c [chan create {r w} foo]
+} -body {
+ notes [inthread $c {
+ note [read $c 2]
+ note [eof $c]
+ close $c
+ notes
+ } c]
+ set res
+} -cleanup {
+ rename foo {}
+ unset res
+} -result {{read rc* 4096} {} 0} \
+ -constraints {testchannel testthread}
+
+# --- === *** ###########################
+# method write
+
+test iocmd.tf-24.1 {chan write, regular write} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ set written [string length [lindex $args 2]]
+ note $written
+ return $written
+ }
+ set c [chan create {r w} foo]
+ inthread $c {
+ puts -nonewline $c snarf; flush $c
+ close $c
+ } c
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{write rc* snarf} 5}
+test iocmd.tf-24.2 {chan write, ack partial writes} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ set written [string length [lindex $args 2]]
+ if {$written > 10} {set written [expr {$written / 2}]}
+ note $written
+ return $written
+ }
+ set c [chan create {r w} foo]
+ inthread $c {
+ puts -nonewline $c snarfsnarfsnarf; flush $c
+ close $c
+ } c
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{write rc* snarfsnarfsnarf} 7 {write rc* arfsnarf} 8}
+test iocmd.tf-24.3 {chan write, failed write} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; note -1; return -1}
+ set c [chan create {r w} foo]
+ inthread $c {
+ puts -nonewline $c snarfsnarfsnarf; flush $c
+ close $c
+ } c
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{write rc* snarfsnarfsnarf} -1}
+test iocmd.tf-24.4 {chan write, non-writable channel} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; note MUST_NOT_HAPPEN; return}
+ set c [chan create {r} foo]
+ notes [inthread $c {
+ note [catch {puts -nonewline $c snarfsnarfsnarf; flush $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {1 {channel "rc*" wasn't opened for writing}}
+test iocmd.tf-24.5 {chan write, bad result, more written than data} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return 10000}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {puts -nonewline $c snarf; flush $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{write rc* snarf} 1 {write wrote more than requested}}
+test iocmd.tf-24.6 {chan write, zero writes} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return 0}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {puts -nonewline $c snarf; flush $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{write rc* snarf} 1 {write wrote more than requested}}
+test iocmd.tf-24.7 {chan write, failed write, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return -code error BOOM!}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {puts -nonewline $c snarfsnarfsnarf; flush $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 BOOM!} \
+ -constraints {testchannel testthread}
+test iocmd.tf-24.8 {chan write, failed write, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; error BOOM!}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {puts -nonewline $c snarfsnarfsnarf; flush $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 BOOM!} \
+ -constraints {testchannel testthread}
+test iocmd.tf-24.9 {chan write, failed write, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return -code break BOOM!}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {puts -nonewline $c snarfsnarfsnarf; flush $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-24.10 {chan write, failed write, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return -code continue BOOM!}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {puts -nonewline $c snarfsnarfsnarf; flush $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-24.11 {chan write, failed write, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return -code 777 BOOM!}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {puts -nonewline $c snarfsnarfsnarf; flush $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-24.12 {chan write, failed write, non-numeric return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return BANG}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {puts -nonewline $c snarfsnarfsnarf; flush $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 {expected integer but got "BANG"}} \
+ -constraints {testchannel testthread}
+test iocmd.tf-24.13 {chan write, failed write, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return -level 55 -code 777 BOOM!}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {puts -nonewline $c snarfsnarfsnarf; flush $c} msg opt]
+ note $msg
+ noteOpts $opt
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{write rc* snarfsnarfsnarf} 1 *bad code* {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo *bad code*subcommand "write"*}} \
+ -constraints {testchannel testthread}
+test iocmd.tf-24.14 {chan write, no EAGAIN means that writing is allowed at this time, bug 2936225} -match glob -setup {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ return 3
+ }
+ set c [chan create {r w} foo]
+} -body {
+ notes [inthread $c {
+ note [puts -nonewline $c ABC ; flush $c]
+ close $c
+ notes
+ } c]
+ set res
+} -cleanup {
+ rename foo {}
+ unset res
+} -result {{write rc* ABC} {}} \
+ -constraints {testchannel testthread}
+test iocmd.tf-24.15 {chan write, EAGAIN means that writing is not allowed at this time, bug 2936225} -match glob -setup {
+ set res {}
+ proc foo {args} {
+ oninit; onfinal; track
+ # Note: The EAGAIN signals that the channel cannot accept
+ # write requests right now, this in turn causes the IO core to
+ # request the generation of writable events (see expected
+ # result below, and compare to case 24.14 above).
+ error EAGAIN
+ }
+ set c [chan create {r w} foo]
+} -body {
+ notes [inthread $c {
+ note [puts -nonewline $c ABC ; flush $c]
+ close $c
+ notes
+ } c]
+ set res
+} -cleanup {
+ rename foo {}
+ unset res
+} -result {{write rc* ABC} {watch rc* write} {}} \
+ -constraints {testchannel testthread}
+
+# --- === *** ###########################
+# method cgetall
+
+test iocmd.tf-25.1 {chan configure, cgetall, standard options} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; note MUST_NOT_HAPPEN; return}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [fconfigure $c]
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} \
+ -result {{-blocking 1 -buffering full -buffersize 4096 -encoding * -eofchar {{} {}} -translation {auto *}}}
+test iocmd.tf-25.2 {chan configure, cgetall, no options} -match glob -body {
+ set res {}
+ proc foo {args} {oninit cget cgetall; onfinal; track; return ""}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [fconfigure $c]
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} \
+ -result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * -eofchar {{} {}} -translation {auto *}}}
+test iocmd.tf-25.3 {chan configure, cgetall, regular result} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return "-bar foo -snarf x"
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [fconfigure $c]
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} \
+ -result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * -eofchar {{} {}} -translation {auto *} -bar foo -snarf x}}
+test iocmd.tf-25.4 {chan configure, cgetall, bad result, list of uneven length} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return "-bar"
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{cgetall rc*} 1 {Expected list with even number of elements, got 1 element instead}}
+test iocmd.tf-25.5 {chan configure, cgetall, bad result, not a list} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return "\{"
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{cgetall rc*} 1 {unmatched open brace in list}}
+test iocmd.tf-25.6 {chan configure, cgetall, error return} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return -code error BOOM!
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{cgetall rc*} 1 BOOM!}
+test iocmd.tf-25.7 {chan configure, cgetall, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return -code break BOOM!
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-25.8 {chan configure, cgetall, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return -code continue BOOM!
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-25.9 {chan configure, cgetall, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return -code 777 BOOM!
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-25.10 {chan configure, cgetall, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return -level 55 -code 777 BANG
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c} msg opt]
+ note $msg
+ noteOpts $opt
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{cgetall rc*} 1 *bad code* {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo *bad code*subcommand "cgetall"*}} \
+ -constraints {testchannel testthread}
+
+# --- === *** ###########################
+# method configure
+
+test iocmd.tf-26.1 {chan configure, set standard option} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure; onfinal; track; note MUST_NOT_HAPPEN; return
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [fconfigure $c -translation lf]
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{}}
+test iocmd.tf-26.2 {chan configure, set option, error return} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure; onfinal; track
+ return -code error BOOM!
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c -rc-foo bar} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{configure rc* -rc-foo bar} 1 BOOM!}
+test iocmd.tf-26.3 {chan configure, set option, ok return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit configure; onfinal; track; return}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [fconfigure $c -rc-foo bar]
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{configure rc* -rc-foo bar} {}}
+test iocmd.tf-26.4 {chan configure, set option, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure; onfinal; track
+ return -code break BOOM!
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c -rc-foo bar} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{configure rc* -rc-foo bar} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-26.5 {chan configure, set option, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure; onfinal; track
+ return -code continue BOOM!
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c -rc-foo bar} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{configure rc* -rc-foo bar} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-26.6 {chan configure, set option, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure; onfinal; track
+ return -code 444 BOOM!
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c -rc-foo bar} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{configure rc* -rc-foo bar} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-26.7 {chan configure, set option, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit configure; onfinal; track
+ return -level 55 -code 444 BANG
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c -rc-foo bar} msg opt]
+ note $msg
+ noteOpts $opt
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{configure rc* -rc-foo bar} 1 *bad code* {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo *bad code*subcommand "configure"*}} \
+ -constraints {testchannel testthread}
+
+# --- === *** ###########################
+# method cget
+
+test iocmd.tf-27.1 {chan configure, get option, ok return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit cget cgetall; onfinal; track; return foo}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [fconfigure $c -rc-foo]
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{cget rc* -rc-foo} foo}
+test iocmd.tf-27.2 {chan configure, get option, error return} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return -code error BOOM!
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c -rc-foo} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{cget rc* -rc-foo} 1 BOOM!}
+test iocmd.tf-27.3 {chan configure, get option, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return -code error BOOM!
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c -rc-foo} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{cget rc* -rc-foo} 1 BOOM!} \
+ -constraints {testchannel testthread}
+test iocmd.tf-27.4 {chan configure, get option, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return -code continue BOOM!
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c -rc-foo} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{cget rc* -rc-foo} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-27.5 {chan configure, get option, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return -code 333 BOOM!
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c -rc-foo} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{cget rc* -rc-foo} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-27.6 {chan configure, get option, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {
+ oninit cget cgetall; onfinal; track
+ return -level 77 -code 333 BANG
+ }
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c -rc-foo} msg opt]
+ note $msg
+ noteOpts $opt
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{cget rc* -rc-foo} 1 *bad code* {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo *bad code*subcommand "cget"*}} \
+ -constraints {testchannel testthread}
+
+# --- === *** ###########################
+# method seek
+
+test iocmd.tf-28.1 {chan tell, not supported by handler} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; note MUST_NOT_HAPPEN; return}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [tell $c]
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {-1} \
+ -constraints {testchannel testthread}
+test iocmd.tf-28.2 {chan tell, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -code error BOOM!}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {tell $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 BOOM!} \
+ -constraints {testchannel testthread}
+test iocmd.tf-28.3 {chan tell, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -code break BOOM!}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {tell $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-28.4 {chan tell, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -code continue BOOM!}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {tell $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-28.5 {chan tell, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -code 222 BOOM!}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {tell $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-28.6 {chan tell, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -level 11 -code 222 BANG}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {tell $c} msg opt]
+ note $msg
+ noteOpts $opt
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 *bad code* {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo *bad code*subcommand "seek"*}} \
+ -constraints {testchannel testthread}
+test iocmd.tf-28.7 {chan tell, regular return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return 88}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [tell $c]
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 88} \
+ -constraints {testchannel testthread}
+test iocmd.tf-28.8 {chan tell, negative return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -1}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {tell $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 {Tried to seek before origin}} \
+ -constraints {testchannel testthread}
+test iocmd.tf-28.9 {chan tell, string return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return BOGUS}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {tell $c} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} 1 {expected integer but got "BOGUS"}} \
+ -constraints {testchannel testthread}
+test iocmd.tf-28.10 {chan seek, not supported by handler} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; note MUST_NOT_HAPPEN; return}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {seek $c 0 start} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {1 {error during seek on "rc*": invalid argument}} \
+ -constraints {testchannel testthread}
+test iocmd.tf-28.11 {chan seek, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -code error BOOM!}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {seek $c 0 start} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 BOOM!} \
+ -constraints {testchannel testthread}
+test iocmd.tf-28.12 {chan seek, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -code break BOOM!}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {seek $c 0 start} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-28.13 {chan seek, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -code continue BOOM!}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {seek $c 0 start} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-28.14 {chan seek, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -code 99 BOOM!}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {seek $c 0 start} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-28.15 {chan seek, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -level 33 -code 99 BANG}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {seek $c 0 start} msg opt]
+ note $msg
+ noteOpts $opt
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 *bad code* {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo *bad code*subcommand "seek"*}} \
+ -constraints {testchannel testthread}
+test iocmd.tf-28.16 {chan seek, bogus return, negative location} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return -45}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {seek $c 0 start} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 {Tried to seek before origin}} \
+ -constraints {testchannel testthread}
+test iocmd.tf-28.17 {chan seek, bogus return, string return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return BOGUS}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {seek $c 0 start} msg]
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{seek rc* 0 start} 1 {expected integer but got "BOGUS"}} \
+ -constraints {testchannel testthread}
+test iocmd.tf-28.18 {chan seek, ok result} -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return 23}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [seek $c 0 current]
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{seek rc* 0 current} {}} \
+ -constraints {testchannel testthread}
+foreach {testname code} {
+ iocmd.tf-28.19.0 start
+ iocmd.tf-28.19.1 current
+ iocmd.tf-28.19.2 end
+} {
+ test $testname "chan seek, base conversion, $code" -match glob -body {
+ set res {}
+ proc foo {args} {oninit seek; onfinal; track; return 0}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [seek $c 0 $code]
+ close $c
+ notes
+ } c code]
+ rename foo {}
+ set res
+ } -result [list [list seek rc* 0 $code] {}] \
+ -constraints {testchannel testthread}
+}
+
+# --- === *** ###########################
+# method blocking
+
+test iocmd.tf-29.1 {chan blocking, no handler support} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; note MUST_NOT_HAPPEN; return}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [fconfigure $c -blocking]
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {1} \
+ -constraints {testchannel testthread}
+test iocmd.tf-29.2 {chan blocking, no handler support} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; note MUST_NOT_HAPPEN; return}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [fconfigure $c -blocking 0]
+ note [fconfigure $c -blocking]
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{} 0} \
+ -constraints {testchannel testthread}
+test iocmd.tf-29.3 {chan blocking, retrieval, handler support} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking; onfinal; track; note MUST_NOT_HAPPEN; return}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [fconfigure $c -blocking]
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {1} \
+ -constraints {testchannel testthread}
+test iocmd.tf-29.4 {chan blocking, resetting, handler support} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking; onfinal; track; return}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [fconfigure $c -blocking 0]
+ note [fconfigure $c -blocking]
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} {} 0} \
+ -constraints {testchannel testthread}
+test iocmd.tf-29.5 {chan blocking, setting, handler support} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking; onfinal; track; return}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [fconfigure $c -blocking 1]
+ note [fconfigure $c -blocking]
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{blocking rc* 1} {} 1} \
+ -constraints {testchannel testthread}
+test iocmd.tf-29.6 {chan blocking, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking; onfinal; track; error BOOM!}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c -blocking 0} msg]
+ note $msg
+ # Catch the close. It changes blocking mode internally, and runs into the error result.
+ catch {close $c}
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 1 BOOM!} \
+ -constraints {testchannel testthread}
+test iocmd.tf-29.7 {chan blocking, break return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking; onfinal; track; return -code break BOOM!}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c -blocking 0} msg]
+ note $msg
+ catch {close $c}
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-29.8 {chan blocking, continue return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking; onfinal; track; return -code continue BOOM!}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c -blocking 0} msg]
+ note $msg
+ catch {close $c}
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-29.9 {chan blocking, custom return is error} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking; onfinal; track; return -code 44 BOOM!}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c -blocking 0} msg]
+ note $msg
+ catch {close $c}
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 1 *bad code*} \
+ -constraints {testchannel testthread}
+test iocmd.tf-29.10 {chan blocking, level is ignored} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking; onfinal; track; return -level 99 -code 44 BANG}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c -blocking 0} msg opt]
+ note $msg
+ noteOpts $opt
+ catch {close $c}
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 1 *bad code* {-code 1 -level 0 -errorcode NONE -errorline 1 -errorinfo *bad code*subcommand "blocking"*}} \
+ -constraints {testchannel testthread}
+test iocmd.tf-29.11 {chan blocking, regular return ok, value ignored} -match glob -body {
+ set res {}
+ proc foo {args} {oninit blocking; onfinal; track; return BOGUS}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [catch {fconfigure $c -blocking 0} msg]
+ note $msg
+ catch {close $c}
+ notes
+ } c]
+ rename foo {}
+ set res
+} -result {{blocking rc* 0} 0 {}} \
+ -constraints {testchannel testthread}
+
+# --- === *** ###########################
+# method watch
+
+test iocmd.tf-30.1 {chan watch, read interest, some return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return IGNORED}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [fileevent $c readable {set tick $tick}]
+ close $c ;# 2nd watch, interest zero.
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{watch rc* read} {watch rc* {}} {}}
+test iocmd.tf-30.2 {chan watch, write interest, error return} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return -code error BOOM!_IGNORED}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [fileevent $c writable {set tick $tick}]
+ note [fileevent $c writable {}]
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} -result {{watch rc* write} {watch rc* {}} {} {}}
+test iocmd.tf-30.3 {chan watch, accumulated interests} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [fileevent $c writable {set tick $tick}]
+ note [fileevent $c readable {set tick $tick}]
+ note [fileevent $c writable {}]
+ note [fileevent $c readable {}]
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} \
+ -result {{watch rc* write} {watch rc* {read write}} {watch rc* read} {watch rc* {}} {} {} {} {}}
+test iocmd.tf-30.4 {chan watch, unchanged interest not forwarded} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ note [fileevent $c writable {set tick $tick}]
+ note [fileevent $c readable {set tick $tick}] ;# Script is changing,
+ note [fileevent $c readable {set tock $tock}] ;# interest does not.
+ close $c ;# 3rd and 4th watch, removing the event handlers.
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} \
+ -result {{watch rc* write} {watch rc* {read write}} {watch rc* write} {watch rc* {}} {} {} {}}
+
+# --- === *** ###########################
+# postevent
+# Not possible from a thread not containing the command handler.
+# Check that this is rejected.
+
+test iocmd.tf-31.8 {chan postevent, bad input} -match glob -body {
+ set res {}
+ proc foo {args} {oninit; onfinal; track; return}
+ set c [chan create {r w} foo]
+ notes [inthread $c {
+ catch {chan postevent $c r} msg
+ note $msg
+ close $c
+ notes
+ } c]
+ rename foo {}
+ set res
+} -constraints {testchannel testthread} \
+ -result {{can not find reflected channel named "rc*"}}
+
+# --- === *** ###########################
+# 'Pull the rug' tests. Create channel in a thread A, move to other
+# thread B, destroy the origin thread (A) before or during access from
+# B. Must not crash, must return proper errors.
+
+test iocmd.tf-32.0 {origin thread of moved channel gone} -match glob -body {
+
+ #puts <<$tcltest::mainThread>>main
+ set tida [testthread create];#puts <<$tida>>
+ set tidb [testthread create];#puts <<$tidb>>
+
+ # Set up channel in thread
+ testthread send $tida $helperscript
+ set chan [testthread send $tida {
+ proc foo {args} {oninit seek; onfinal; track; return}
+ set chan [chan create {r w} foo]
+ fconfigure $chan -buffering none
+ set chan
+ }]
+
+ # Move channel to 2nd thread.
+ testthread send $tida [list testchannel cut $chan]
+ testthread send $tidb [list testchannel splice $chan]
+
+ # Kill origin thread, then access channel from 2nd thread.
+ testthread send -async $tida {testthread exit}
+ after 100
+
+ set res {}
+ lappend res [catch {testthread send $tidb [list puts $chan shoo]} msg] $msg
+
+ lappend res [catch {testthread send $tidb [list tell $chan]} msg] $msg
+ lappend res [catch {testthread send $tidb [list seek $chan 1]} msg] $msg
+ lappend res [catch {testthread send $tidb [list gets $chan]} msg] $msg
+ lappend res [catch {testthread send $tidb [list close $chan]} msg] $msg
+ tcltest::threadReap
+ set res
+
+} -constraints {testchannel testthread} \
+ -result {1 {Owner lost} 1 {Owner lost} 1 {Owner lost} 1 {Owner lost} 1 {Owner lost}}
+
+test iocmd.tf-32.1 {origin thread of moved channel destroyed during access} -match glob -body {
+
+ #puts <<$tcltest::mainThread>>main
+ set tida [testthread create];#puts <<$tida>>
+ set tidb [testthread create];#puts <<$tidb>>
+
+ # Set up channel in thread
+ set chan [testthread send $tida $helperscript]
+ set chan [testthread send $tida {
+ proc foo {args} {
+ oninit; onfinal; track;
+ # destroy thread during channel access
+ testthread exit
+ return}
+ set chan [chan create {r w} foo]
+ fconfigure $chan -buffering none
+ set chan
+ }]
+
+ # Move channel to 2nd thread.
+ testthread send $tida [list testchannel cut $chan]
+ testthread send $tidb [list testchannel splice $chan]
+
+ # Run access from thread B, wait for response from A (A is not
+ # using event loop at this point, so the event pile up in the
+ # queue.
+
+ testthread send $tidb [list set chan $chan]
+ testthread send $tidb [list set mid $tcltest::mainThread]
+ testthread send -async $tidb {
+ # wait a bit, give the main thread the time to start its event
+ # loop to wait for the response from B
+ after 2000
+ catch { puts $chan shoo } res
+ testthread send -async $mid [list set ::res $res]
+ }
+ vwait ::res
+
+ tcltest::threadReap
+ set res
+} -constraints {testchannel testthread} \
+ -result {Owner lost}
+
+# ### ### ### ######### ######### #########
+
+# ### ### ### ######### ######### #########
+
+rename track {}
# cleanup
foreach file [list test1 test2 test3 test4] {
removeFile $file
diff --git a/tests/ioUtil.test b/tests/ioUtil.test
index efdaef0..7e8687e 100644
--- a/tests/ioUtil.test
+++ b/tests/ioUtil.test
@@ -1,24 +1,22 @@
# This file (ioUtil.test) tests the hookable TclStat(), TclAccess(),
# and Tcl_OpenFileChannel, routines in the file generic/tclIOUtils.c.
# Sourcing this file into Tcl runs the tests and generates output for
-# errors. No output means no errors were found.
-#
-# 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.
-
+# errors. No output means no errors were found.
+#
+# 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.
+
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest 2
namespace import -force ::tcltest::*
}
-::tcltest::testConstraint testopenfilechannelproc \
+testConstraint testopenfilechannelproc \
[llength [info commands testopenfilechannelproc]]
-::tcltest::testConstraint testaccessproc \
- [llength [info commands testaccessproc]]
-::tcltest::testConstraint teststatproc \
- [llength [info commands teststatproc]]
+testConstraint testaccessproc [llength [info commands testaccessproc]]
+testConstraint teststatproc [llength [info commands teststatproc]]
set unsetScript {
catch {unset testStat1(size)}
@@ -189,7 +187,7 @@ set oldpwd [pwd]
cd [temporaryDirectory]
test ioUtil-3.1 {TclOpenFileChannel: Check that none of the test procs are there.} {testopenfilechannelproc} {
- catch {eval [list file delete -force] [glob *testOpenFileChannel*]}
+ catch {file delete -force {*}[glob *testOpenFileChannel*]}
catch {file exists testOpenFileChannel1%.fil} err1
catch {file exists testOpenFileChannel2%.fil} err2
catch {file exists testOpenFileChannel3%.fil} err3
@@ -303,18 +301,18 @@ test ioUtil-3.8 {TclOpenFileChannelDeleteProc: Verify that all procs have been d
test ioUtil-4.1 {open ... a+ must not use O_APPEND: Bug 1773127} -setup {
set f [tcltest::makeFile {} ioutil41.tmp]
- set fid [open $f w]
+ set fid [open $f wb]
puts -nonewline $fid 123
close $fid
} -body {
- set fid [open $f a+]
+ set fid [open $f ab+]
puts -nonewline $fid 456
seek $fid 2
set d [read $fid 2]
seek $fid 4
puts -nonewline $fid x
close $fid
- set fid [open $f r]
+ set fid [open $f rb]
append d [read $fid]
close $fid
return $d
@@ -327,3 +325,7 @@ cd $oldpwd
# cleanup
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/iogt.test b/tests/iogt.test
index 04da3eb..3882ecc 100644
--- a/tests/iogt.test
+++ b/tests/iogt.test
@@ -15,14 +15,9 @@ if {[catch {package require tcltest 2.1}]} {
return
}
namespace eval ::tcl::test::iogt {
+ namespace import ::tcltest::*
- namespace import ::tcltest::cleanupTests
- namespace import ::tcltest::makeFile
- namespace import ::tcltest::removeFile
- namespace import ::tcltest::test
- namespace import ::tcltest::testConstraint
-
- testConstraint testchannel [llength [info commands testchannel]]
+testConstraint testchannel [llength [info commands testchannel]]
set path(dummy) [makeFile {abcdefghijklmnopqrstuvwxyz0123456789,./?><;'\|":[]\}\{`~!@#$%^&*()_+-=
} dummy]
@@ -129,7 +124,7 @@ proc echoPut {c sock} {
#fileevent stdin readable {exit ;#cut}
# main
-socket -server newconn $port
+socket -server newconn -myaddr 127.0.0.1 $port
vwait forever
} __echo_srv__.tcl]
@@ -145,8 +140,8 @@ proc fevent {fdelay idelay blocks script data} {
# fixed port, not so good. lets hope for the best, for now.
set port 4000
- eval exec tclsh __echo_srv__.tcl \
- $port $fdelay $idelay $blocks >@stdout &
+ exec tclsh __echo_srv__.tcl \
+ $port $fdelay $idelay {*}$blocks >@stdout &
after 500
@@ -487,7 +482,7 @@ test iogt-2.0 {basic I/O going through transform} testchannel {
} {1 71 71}
-test iogt-2.1 {basic I/O, operation trail} {testchannel unixOnly} {
+test iogt-2.1 {basic I/O, operation trail} {testchannel unix} {
set fin [open $path(dummy) r]
set fout [open $path(dummyout) w]
@@ -537,7 +532,7 @@ write
flush/write
delete/write}
-test iogt-2.2 {basic I/O, data trail} {testchannel unixOnly} {
+test iogt-2.2 {basic I/O, data trail} {testchannel unix} {
set fin [open $path(dummy) r]
set fout [open $path(dummyout) w]
@@ -592,7 +587,7 @@ flush/write {} {}
delete/write {} *ignored*}
-test iogt-2.3 {basic I/O, mixed trail} {testchannel unixOnly} {
+test iogt-2.3 {basic I/O, mixed trail} {testchannel unix} {
set fin [open $path(dummy) r]
set fout [open $path(dummyout) w]
@@ -880,10 +875,6 @@ delete/read {} *ignored*
flush/write {} {}
delete/write {} *ignored*}
-
-
-
-
proc constX {op data} {
# replace anything coming in with a same-length string of x'es.
switch -- $op {
diff --git a/tests/join.test b/tests/join.test
index 99b6eb5..133b7f1 100644
--- a/tests/join.test
+++ b/tests/join.test
@@ -50,15 +50,3 @@ test join-3.2 {join is binary ok} {
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/lindex.test b/tests/lindex.test
index 1c04330..fee9f48 100644
--- a/tests/lindex.test
+++ b/tests/lindex.test
@@ -13,74 +13,65 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2.2
namespace import -force ::tcltest::*
}
-set lindex lindex
set minus -
+testConstraint testevalex [llength [info commands testevalex]]
# Tests of Tcl_LindexObjCmd, NOT COMPILED
-test lindex-1.1 {wrong # args} {
- list [catch {eval $lindex} result] $result
+test lindex-1.1 {wrong # args} testevalex {
+ list [catch {testevalex lindex} result] $result
} "1 {wrong # args: should be \"lindex list ?index...?\"}"
# Indices that are lists or convertible to lists
-test lindex-2.1 {empty index list} {
+test lindex-2.1 {empty index list} testevalex {
set x {}
- list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+ list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {{a b c} {a b c}}
-
-test lindex-2.2 {singleton index list} {
+test lindex-2.2 {singleton index list} testevalex {
set x { 1 }
- list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+ list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {b b}
-
-test lindex-2.3 {multiple indices in list} {
+test lindex-2.3 {multiple indices in list} testevalex {
set x {1 2}
- list [eval [list $lindex {{a b c} {d e f}} $x]] \
- [eval [list $lindex {{a b c} {d e f}} $x]]
+ list [testevalex {lindex {{a b c} {d e f}} $x}] \
+ [testevalex {lindex {{a b c} {d e f}} $x}]
} {f f}
-
-test lindex-2.4 {malformed index list} {
+test lindex-2.4 {malformed index list} testevalex {
set x \{
- list [catch { eval [list $lindex {a b c} $x] } result] $result
-} {1 bad\ index\ \"\{\":\ must\ be\ integer\ or\ end?-integer?}
+ list [catch { testevalex {lindex {a b c} $x} } result] $result
+} {1 bad\ index\ \"\{\":\ must\ be\ integer?\[+-\]integer?\ or\ end?\[+-\]integer?}
# Indices that are integers or convertible to integers
-test lindex-3.1 {integer -1} {
+test lindex-3.1 {integer -1} testevalex {
set x ${minus}1
- list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+ list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {{} {}}
-
-test lindex-3.2 {integer 0} {
+test lindex-3.2 {integer 0} testevalex {
set x [string range 00 0 0]
- list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+ list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {a a}
-
-test lindex-3.3 {integer 2} {
+test lindex-3.3 {integer 2} testevalex {
set x [string range 22 0 0]
- list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+ list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {c c}
-
-test lindex-3.4 {integer 3} {
+test lindex-3.4 {integer 3} testevalex {
set x [string range 33 0 0]
- list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+ list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {{} {}}
-
-test lindex-3.5 {bad octal} {
- set x 08
- list [catch { eval [list $lindex {a b c} $x] } result] $result
-} "1 {bad index \"08\": must be integer or end?-integer? (looks like invalid octal number)}"
-
-test lindex-3.6 {bad octal} {
- set x -09
- list [catch { eval [list $lindex {a b c} $x] } result] $result
-} "1 {bad index \"-09\": must be integer or end?-integer? (looks like invalid octal number)}"
-
+test lindex-3.5 {bad octal} -constraints testevalex -body {
+ set x 0o8
+ list [catch { testevalex {lindex {a b c} $x} } result] $result
+} -match glob -result {1 {*invalid octal number*}}
+test lindex-3.6 {bad octal} -constraints testevalex -body {
+ set x -0o9
+ list [catch { testevalex {lindex {a b c} $x} } result] $result
+} -match glob -result {1 {*invalid octal number*}}
test lindex-3.7 {indexes don't shimmer wide ints} {
set x [expr {(wide(1)<<31) - 2}]
list $x [lindex {1 2 3} $x] [incr x] [incr x]
@@ -88,122 +79,107 @@ test lindex-3.7 {indexes don't shimmer wide ints} {
# Indices relative to end
-test lindex-4.1 {index = end} {
+test lindex-4.1 {index = end} testevalex {
set x end
- list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+ list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {c c}
-
-test lindex-4.2 {index = end--1} {
+test lindex-4.2 {index = end--1} testevalex {
set x end--1
- list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+ list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {{} {}}
-
-test lindex-4.3 {index = end-0} {
+test lindex-4.3 {index = end-0} testevalex {
set x end-0
- list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+ list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {c c}
-
-test lindex-4.4 {index = end-2} {
+test lindex-4.4 {index = end-2} testevalex {
set x end-2
- list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+ list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {a a}
-
-test lindex-4.5 {index = end-3} {
+test lindex-4.5 {index = end-3} testevalex {
set x end-3
- list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+ list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {{} {}}
-
-test lindex-4.6 {bad octal} {
- set x end-08
- list [catch { eval [list $lindex {a b c} $x] } result] $result
-} "1 {bad index \"end-08\": must be integer or end?-integer? (looks like invalid octal number)}"
-
-test lindex-4.7 {bad octal} {
- set x end--09
- list [catch { eval [list $lindex {a b c} $x] } result] $result
-} "1 {bad index \"end--09\": must be integer or end?-integer?}"
-
-test lindex-4.8 {bad integer, not octal} {
+test lindex-4.6 {bad octal} -constraints testevalex -body {
+ set x end-0o8
+ list [catch { testevalex {lindex {a b c} $x} } result] $result
+} -match glob -result {1 {*invalid octal number*}}
+test lindex-4.7 {bad octal} -constraints testevalex -body {
+ set x end--0o9
+ list [catch { testevalex {lindex {a b c} $x} } result] $result
+} -match glob -result {1 {*invalid octal number*}}
+test lindex-4.8 {bad integer, not octal} testevalex {
set x end-0a2
- list [catch { eval [list $lindex {a b c} $x] } result] $result
-} "1 {bad index \"end-0a2\": must be integer or end?-integer?}"
-
-test lindex-4.9 {incomplete end} {
- set x en
- list [eval [list $lindex {a b c} $x]] [eval [list $lindex {a b c} $x]]
+ list [catch { testevalex {lindex {a b c} $x} } result] $result
+} {1 {bad index "end-0a2": must be integer?[+-]integer? or end?[+-]integer?}}
+test lindex-4.9 {obsolete test} testevalex {
+ set x end
+ list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {c c}
-
-test lindex-4.10 {incomplete end-} {
+test lindex-4.10 {incomplete end-} testevalex {
set x end-
- list [catch { eval [list $lindex {a b c} $x] } result] $result
-} "1 {bad index \"end-\": must be integer or end?-integer?}"
-
-test lindex-5.1 {bad second index} {
- list [catch { eval [list $lindex {a b c} 0 0a2] } result] $result
-} "1 {bad index \"0a2\": must be integer or end?-integer?}"
-
-test lindex-5.2 {good second index} {
- eval [list $lindex {{a b c} {d e f} {g h i}} 1 2]
+ list [catch { testevalex {lindex {a b c} $x} } result] $result
+} {1 {bad index "end-": must be integer?[+-]integer? or end?[+-]integer?}}
+
+test lindex-5.1 {bad second index} testevalex {
+ list [catch { testevalex {lindex {a b c} 0 0a2} } result] $result
+} {1 {bad index "0a2": must be integer?[+-]integer? or end?[+-]integer?}}
+test lindex-5.2 {good second index} testevalex {
+ testevalex {lindex {{a b c} {d e f} {g h i}} 1 2}
} f
-
-test lindex-5.3 {three indices} {
- eval [list $lindex {{{a b} {c d}} {{e f} {g h}}} 1 0 1]
+test lindex-5.3 {three indices} testevalex {
+ testevalex {lindex {{{a b} {c d}} {{e f} {g h}}} 1 0 1}
} f
-test lindex-6.1 {error conditions in parsing list} {
- list [catch {eval [list $lindex "a \{" 2]} msg] $msg
+
+test lindex-6.1 {error conditions in parsing list} testevalex {
+ list [catch {testevalex {lindex "a \{" 2}} msg] $msg
} {1 {unmatched open brace in list}}
-test lindex-6.2 {error conditions in parsing list} {
- list [catch {eval [list $lindex {a {b c}d e} 2]} msg] $msg
+test lindex-6.2 {error conditions in parsing list} testevalex {
+ list [catch {testevalex {lindex {a {b c}d e} 2}} msg] $msg
} {1 {list element in braces followed by "d" instead of space}}
-test lindex-6.3 {error conditions in parsing list} {
- list [catch {eval [list $lindex {a "b c"def ghi} 2]} msg] $msg
+test lindex-6.3 {error conditions in parsing list} testevalex {
+ list [catch {testevalex {lindex {a "b c"def ghi} 2}} msg] $msg
} {1 {list element in quotes followed by "def" instead of space}}
-test lindex-7.1 {quoted elements} {
- eval [list $lindex {a "b c" d} 1]
+test lindex-7.1 {quoted elements} testevalex {
+ testevalex {lindex {a "b c" d} 1}
} {b c}
-test lindex-7.2 {quoted elements} {
- eval [list $lindex {"{}" b c} 0]
+test lindex-7.2 {quoted elements} testevalex {
+ testevalex {lindex {"{}" b c} 0}
} {{}}
-test lindex-7.3 {quoted elements} {
- eval [list $lindex {ab "c d \" x" y} 1]
+test lindex-7.3 {quoted elements} testevalex {
+ testevalex {lindex {ab "c d \" x" y} 1}
} {c d " x}
test lindex-7.4 {quoted elements} {
lindex {a b {c d "e} {f g"}} 2
} {c d "e}
-test lindex-8.1 {data reuse} {
+test lindex-8.1 {data reuse} testevalex {
set x 0
- eval [list $lindex $x $x]
+ testevalex {lindex $x $x}
} {0}
-
-test lindex-8.2 {data reuse} {
+test lindex-8.2 {data reuse} testevalex {
set a 0
- eval [list $lindex $a $a $a]
+ testevalex {lindex $a $a $a}
} 0
-test lindex-8.3 {data reuse} {
+test lindex-8.3 {data reuse} testevalex {
set a 1
- eval [list $lindex $a $a $a]
+ testevalex {lindex $a $a $a}
} {}
-
-test lindex-8.4 {data reuse} {
+test lindex-8.4 {data reuse} testevalex {
set x [list 0 0]
- eval [list $lindex $x $x]
+ testevalex {lindex $x $x}
} {0}
-
-test lindex-8.5 {data reuse} {
+test lindex-8.5 {data reuse} testevalex {
set x 0
- eval [list $lindex $x [list $x $x]]
+ testevalex {lindex $x [list $x $x]}
} {0}
-
-test lindex-8.6 {data reuse} {
+test lindex-8.6 {data reuse} testevalex {
set x [list 1 1]
- eval [list $lindex $x $x]
+ testevalex {lindex $x $x}
} {}
-
-test lindex-8.7 {data reuse} {
+test lindex-8.7 {data reuse} testevalex {
set x 1
- eval [list lindex $x [list $x $x]]
+ testevalex {lindex $x [list $x $x]}
} {}
#----------------------------------------------------------------------
@@ -213,6 +189,13 @@ test lindex-8.7 {data reuse} {
test lindex-9.1 {wrong # args} {
list [catch {lindex} result] $result
} "1 {wrong # args: should be \"lindex list ?index...?\"}"
+test lindex-9.2 {ensure that compilation works in the right order} {
+ proc foo {} {
+ rename foo {}
+ lindex 1 0
+ }
+ foo
+} 1
# Indices that are lists or convertible to lists
@@ -223,7 +206,6 @@ test lindex-10.1 {empty index list} {
} result
set result
} {{a b c} {a b c}}
-
test lindex-10.2 {singleton index list} {
set x { 1 }
catch {
@@ -231,7 +213,6 @@ test lindex-10.2 {singleton index list} {
} result
set result
} {b b}
-
test lindex-10.3 {multiple indices in list} {
set x {1 2}
catch {
@@ -239,11 +220,10 @@ test lindex-10.3 {multiple indices in list} {
} result
set result
} {f f}
-
test lindex-10.4 {malformed index list} {
set x \{
list [catch { lindex {a b c} $x } result] $result
-} {1 bad\ index\ \"\{\":\ must\ be\ integer\ or\ end?-integer?}
+} {1 bad\ index\ \"\{\":\ must\ be\ integer?\[+-\]integer?\ or\ end?\[+-\]integer?}
# Indices that are integers or convertible to integers
@@ -254,7 +234,6 @@ test lindex-11.1 {integer -1} {
} result
set result
} {{} {}}
-
test lindex-11.2 {integer 0} {
set x [string range 00 0 0]
catch {
@@ -262,7 +241,6 @@ test lindex-11.2 {integer 0} {
} result
set result
} {a a}
-
test lindex-11.3 {integer 2} {
set x [string range 22 0 0]
catch {
@@ -270,7 +248,6 @@ test lindex-11.3 {integer 2} {
} result
set result
} {c c}
-
test lindex-11.4 {integer 3} {
set x [string range 33 0 0]
catch {
@@ -278,16 +255,14 @@ test lindex-11.4 {integer 3} {
} result
set result
} {{} {}}
-
-test lindex-11.5 {bad octal} {
- set x 08
+test lindex-11.5 {bad octal} -body {
+ set x 0o8
list [catch { lindex {a b c} $x } result] $result
-} "1 {bad index \"08\": must be integer or end?-integer? (looks like invalid octal number)}"
-
-test lindex-11.6 {bad octal} {
- set x -09
+} -match glob -result {1 {*invalid octal number*}}
+test lindex-11.6 {bad octal} -body {
+ set x -0o9
list [catch { lindex {a b c} $x } result] $result
-} "1 {bad index \"-09\": must be integer or end?-integer? (looks like invalid octal number)}"
+} -match glob -result {1 {*invalid octal number*}}
# Indices relative to end
@@ -298,7 +273,6 @@ test lindex-12.1 {index = end} {
} result
set result
} {c c}
-
test lindex-12.2 {index = end--1} {
set x end--1
catch {
@@ -306,7 +280,6 @@ test lindex-12.2 {index = end--1} {
} result
set result
} {{} {}}
-
test lindex-12.3 {index = end-0} {
set x end-0
catch {
@@ -314,7 +287,6 @@ test lindex-12.3 {index = end-0} {
} result
set result
} {c c}
-
test lindex-12.4 {index = end-2} {
set x end-2
catch {
@@ -322,7 +294,6 @@ test lindex-12.4 {index = end-2} {
} result
set result
} {a a}
-
test lindex-12.5 {index = end-3} {
set x end-3
catch {
@@ -330,46 +301,39 @@ test lindex-12.5 {index = end-3} {
} result
set result
} {{} {}}
-
-test lindex-12.6 {bad octal} {
- set x end-08
+test lindex-12.6 {bad octal} -body {
+ set x end-0o8
list [catch { lindex {a b c} $x } result] $result
-} "1 {bad index \"end-08\": must be integer or end?-integer? (looks like invalid octal number)}"
-
-test lindex-12.7 {bad octal} {
- set x end--09
+} -match glob -result {1 {*invalid octal number*}}
+test lindex-12.7 {bad octal} -body {
+ set x end--0o9
list [catch { lindex {a b c} $x } result] $result
-} "1 {bad index \"end--09\": must be integer or end?-integer?}"
-
+} -match glob -result {1 {*invalid octal number*}}
test lindex-12.8 {bad integer, not octal} {
set x end-0a2
list [catch { lindex {a b c} $x } result] $result
-} "1 {bad index \"end-0a2\": must be integer or end?-integer?}"
-
-test lindex-12.9 {incomplete end} {
- set x en
+} {1 {bad index "end-0a2": must be integer?[+-]integer? or end?[+-]integer?}}
+test lindex-12.9 {obsolete test} {
+ set x end
catch {
list [lindex {a b c} $x] [lindex {a b c} $x]
} result
set result
} {c c}
-
test lindex-12.10 {incomplete end-} {
set x end-
list [catch { lindex {a b c} $x } result] $result
-} "1 {bad index \"end-\": must be integer or end?-integer?}"
+} {1 {bad index "end-": must be integer?[+-]integer? or end?[+-]integer?}}
test lindex-13.1 {bad second index} {
list [catch { lindex {a b c} 0 0a2 } result] $result
-} "1 {bad index \"0a2\": must be integer or end?-integer?}"
-
+} {1 {bad index "0a2": must be integer?[+-]integer? or end?[+-]integer?}}
test lindex-13.2 {good second index} {
catch {
lindex {{a b c} {d e f} {g h i}} 1 2
} result
set result
} f
-
test lindex-13.3 {three indices} {
catch {
lindex {{{a b} {c d}} {{e f} {g h}}} 1 0 1
@@ -419,7 +383,6 @@ test lindex-16.1 {data reuse} {
} result
set result
} {0}
-
test lindex-16.2 {data reuse} {
set a 0
catch {
@@ -434,7 +397,6 @@ test lindex-16.3 {data reuse} {
} result
set result
} {}
-
test lindex-16.4 {data reuse} {
set x [list 0 0]
catch {
@@ -442,7 +404,6 @@ test lindex-16.4 {data reuse} {
} result
set result
} {0}
-
test lindex-16.5 {data reuse} {
set x 0
catch {
@@ -450,7 +411,6 @@ test lindex-16.5 {data reuse} {
} result
set result
} {0}
-
test lindex-16.6 {data reuse} {
set x [list 1 1]
catch {
@@ -458,7 +418,6 @@ test lindex-16.6 {data reuse} {
} result
set result
} {}
-
test lindex-16.7 {data reuse} {
set x 1
catch {
@@ -467,9 +426,30 @@ test lindex-16.7 {data reuse} {
set result
} {}
-catch { unset lindex}
+test lindex-17.0 {Bug 1718580} {*}{
+ -body {
+ lindex {} end foo
+ }
+ -match glob
+ -result {bad index "foo"*}
+ -returnCodes 1
+}
+
+test lindex-17.1 {Bug 1718580} {*}{
+ -body {
+ lindex a end foo
+ }
+ -match glob
+ -result {bad index "foo"*}
+ -returnCodes 1
+}
+
catch { unset minus }
# cleanup
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/link.test b/tests/link.test
index 672185c..3b423ec 100644
--- a/tests/link.test
+++ b/tests/link.test
@@ -16,65 +16,73 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-::tcltest::testConstraint testlink \
- [expr {[info commands testlink] != {}}]
+testConstraint testlink [llength [info commands testlink]]
foreach i {int real bool string} {
catch {unset $i}
}
test link-1.1 {reading C variables from Tcl} {testlink} {
testlink delete
- testlink set 43 1.23 4 - 12341234
- testlink create 1 1 1 1 1
+ testlink set 43 1.23 4 - 12341234 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
+ testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
list $int $real $bool $string $wide
} {43 1.23 1 NULL 12341234}
test link-1.2 {reading C variables from Tcl} {testlink} {
testlink delete
- testlink create 1 1 1 1 1
- testlink set -3 2 0 "A long string with spaces" 43214321
+ testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ testlink set -3 2 0 "A long string with spaces" 43214321 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
list $int $real $bool $string $wide $int $real $bool $string $wide
} {-3 2.0 0 {A long string with spaces} 43214321 -3 2.0 0 {A long string with spaces} 43214321}
test link-2.1 {writing C variables from Tcl} {testlink} {
testlink delete
- testlink set 43 1.21 4 - 56785678
- testlink create 1 1 1 1 1
- set int "00721"
+ testlink set 43 1.21 4 - 56785678 64 250 30000 60000 0xbaadbeef 12321 32123 3.25 1231231234
+ testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ set int "0o0721"
set real -10.5
set bool true
set string abcdef
set wide 135135
- concat [testlink get] $int $real $bool $string $wide
-} {465 -10.5 1 abcdef 135135 00721 -10.5 true abcdef 135135}
+ set char 79
+ set uchar 161
+ set short 8000
+ set ushort 40000
+ set uint 0xc001babe
+ set long 34543
+ set ulong 567890
+ set float 1.0987654321
+ set uwide 357357357357
+ concat [testlink get] | $int $real $bool $string $wide $char $uchar $short $ushort $uint $long $ulong $float $uwide
+} {465 -10.5 1 abcdef 135135 79 161 8000 40000 -1073628482 34543 567890 1.0987653732299805 357357357357 | 0o0721 -10.5 true abcdef 135135 79 161 8000 40000 0xc001babe 34543 567890 1.0987654321 357357357357}
test link-2.2 {writing bad values into variables} {testlink} {
testlink delete
- testlink set 43 1.23 4 - 56785678
- testlink create 1 1 1 1 1
+ testlink set 43 1.23 4 - 56785678 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
+ testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
list [catch {set int 09a} msg] $msg $int
} {1 {can't set "int": variable must have integer value} 43}
test link-2.3 {writing bad values into variables} {testlink} {
testlink delete
- testlink set 43 1.23 4 - 56785678
- testlink create 1 1 1 1 1
+ testlink set 43 1.23 4 - 56785678 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
+ testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
list [catch {set real 1.x3} msg] $msg $real
} {1 {can't set "real": variable must have real value} 1.23}
test link-2.4 {writing bad values into variables} {testlink} {
testlink delete
- testlink set 43 1.23 4 - 56785678
- testlink create 1 1 1 1 1
+ testlink set 43 1.23 4 - 56785678 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
+ testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
list [catch {set bool gorp} msg] $msg $bool
} {1 {can't set "bool": variable must have boolean value} 1}
test link-2.5 {writing bad values into variables} {testlink} {
testlink delete
- testlink set 43 1.23 4 - 56785678
- testlink create 1 1 1 1 1
+ testlink set 43 1.23 4 - 56785678 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
+ testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
list [catch {set wide gorp} msg] $msg $bool
} {1 {can't set "wide": variable must have integer value} 1}
test link-3.1 {read-only variables} {testlink} {
testlink delete
- testlink set 43 1.23 4 - 56785678
- testlink create 0 1 1 0 0
+ testlink set 43 1.23 4 - 56785678 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
+ testlink create 0 1 1 0 0 0 0 0 0 0 0 0 0 0
list [catch {set int 4} msg] $msg $int \
[catch {set real 10.6} msg] $msg $real \
[catch {set bool no} msg] $msg $bool \
@@ -83,8 +91,8 @@ test link-3.1 {read-only variables} {testlink} {
} {1 {can't set "int": linked variable is read-only} 43 0 10.6 10.6 0 no no 1 {can't set "string": linked variable is read-only} NULL 1 {can't set "wide": linked variable is read-only} 56785678}
test link-3.2 {read-only variables} {testlink} {
testlink delete
- testlink set 43 1.23 4 - 56785678
- testlink create 1 0 0 1 1
+ testlink set 43 1.23 4 - 56785678 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
+ testlink create 1 0 0 1 1 0 0 0 0 0 0 0 0 0
list [catch {set int 4} msg] $msg $int \
[catch {set real 10.6} msg] $msg $real \
[catch {set bool no} msg] $msg $bool \
@@ -94,8 +102,8 @@ test link-3.2 {read-only variables} {testlink} {
test link-4.1 {unsetting linked variables} {testlink} {
testlink delete
- testlink set -6 -2.5 0 stringValue 13579
- testlink create 1 1 1 1 1
+ testlink set -6 -2.5 0 stringValue 13579 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
+ testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
unset int real bool string wide
list [catch {set int} msg] $msg [catch {set real} msg] $msg \
[catch {set bool} msg] $msg [catch {set string} msg] $msg \
@@ -103,42 +111,51 @@ test link-4.1 {unsetting linked variables} {testlink} {
} {0 -6 0 -2.5 0 0 0 stringValue 0 13579}
test link-4.2 {unsetting linked variables} {testlink} {
testlink delete
- testlink set -6 -2.1 0 stringValue 97531
- testlink create 1 1 1 1 1
+ testlink set -6 -2.1 0 stringValue 97531 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
+ testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
unset int real bool string wide
set int 102
set real 16
set bool true
set string newValue
set wide 333555
- testlink get
+ lrange [testlink get] 0 4
} {102 16.0 1 newValue 333555}
test link-5.1 {unlinking variables} {testlink} {
testlink delete
- testlink set -6 -2.25 0 stringValue 13579
+ testlink set -6 -2.25 0 stringValue 13579 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
testlink delete
set int xx1
set real qrst
set bool bogus
set string 12345
set wide 875421
+ set char skjdf
+ set uchar dslfjk
+ set short slkf
+ set ushort skrh
+ set uint sfdkfkh
+ set long srkjh
+ set ulong sjkg
+ set float dskjfbjfd
+ set uwide isdfsngs
testlink get
-} {-6 -2.25 0 stringValue 13579}
+} {-6 -2.25 0 stringValue 13579 64 250 30000 60000 -1091585346 12321 32123 3.25 1231231234}
test link-5.2 {unlinking variables} {testlink} {
testlink delete
- testlink set -6 -2.25 0 stringValue 97531
- testlink create 1 1 1 1 1
+ testlink set -6 -2.25 0 stringValue 97531 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
+ testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
testlink delete
- testlink set 25 14.7 7 - 999999
- list $int $real $bool $string $wide
-} {-6 -2.25 0 stringValue 97531}
+ testlink set 25 14.7 7 - 999999 65 251 30001 60001 0xbabebeef 12322 32124 3.125 12312312340
+ list $int $real $bool $string $wide $char $uchar $short $ushort $uint $long $ulong $float $uwide
+} {-6 -2.25 0 stringValue 97531 64 250 30000 60000 3203381950 12321 32123 3.25 1231231234}
test link-6.1 {errors in setting up link} {testlink} {
testlink delete
catch {unset int}
set int(44) 1
- list [catch {testlink create 1 1 1 1 1} msg] $msg
+ list [catch {testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1} msg] $msg
} {1 {can't set "int": variable is array}}
catch {unset int}
@@ -148,8 +165,8 @@ test link-7.1 {access to linked variables via upvar} {testlink} {
unset y
}
testlink delete
- testlink create 1 0 0 0 0
- testlink set 14 {} {} {} {}
+ testlink create 1 0 0 0 0 0 0 0 0 0 0 0 0 0
+ testlink set 14 {} {} {} {} {} {} {} {} {} {} {} {} {}
x
list [catch {set int} msg] $msg
} {0 14}
@@ -159,10 +176,10 @@ test link-7.2 {access to linked variables via upvar} {testlink} {
return [set y]
}
testlink delete
- testlink create 1 0 0 0 0
- testlink set 0 {} {} {} {}
+ testlink create 1 0 0 0 0 0 0 0 0 0 0 0 0 0
+ testlink set 0 {} {} {} {} {} {} {} {} {} {} {} {} {}
set int
- testlink set 23 {} {} {} {}
+ testlink set 23 {} {} {} {} {} {} {} {} {} {} {} {} {}
x
list [x] $int
} {23 23}
@@ -172,8 +189,8 @@ test link-7.3 {access to linked variables via upvar} {testlink} {
set y 44
}
testlink delete
- testlink create 0 0 0 0 0
- testlink set 11 {} {} {} {}
+ testlink create 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ testlink set 11 {} {} {} {} {} {} {} {} {} {} {} {} {}
list [catch x msg] $msg $int
} {1 {can't set "y": linked variable is read-only} 11}
test link-7.4 {access to linked variables via upvar} {testlink} {
@@ -182,8 +199,8 @@ test link-7.4 {access to linked variables via upvar} {testlink} {
set y abc
}
testlink delete
- testlink create 1 1 1 1 1
- testlink set -4 {} {} {} {}
+ testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ testlink set -4 {} {} {} {} {} {} {} {} {} {} {} {} {}
list [catch x msg] $msg $int
} {1 {can't set "y": variable must have integer value} -4}
test link-7.5 {access to linked variables via upvar} {testlink} {
@@ -192,8 +209,8 @@ test link-7.5 {access to linked variables via upvar} {testlink} {
set y abc
}
testlink delete
- testlink create 1 1 1 1 1
- testlink set -4 16.75 {} {} {}
+ testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ testlink set -4 16.75 {} {} {} {} {} {} {} {} {} {} {} {}
list [catch x msg] $msg $real
} {1 {can't set "y": variable must have real value} 16.75}
test link-7.6 {access to linked variables via upvar} {testlink} {
@@ -202,8 +219,8 @@ test link-7.6 {access to linked variables via upvar} {testlink} {
set y abc
}
testlink delete
- testlink create 1 1 1 1 1
- testlink set -4 16.3 1 {} {}
+ testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ testlink set -4 16.3 1 {} {} {} {} {} {} {} {} {} {} {}
list [catch x msg] $msg $bool
} {1 {can't set "y": variable must have boolean value} 1}
test link-7.7 {access to linked variables via upvar} {testlink} {
@@ -212,8 +229,8 @@ test link-7.7 {access to linked variables via upvar} {testlink} {
set y abc
}
testlink delete
- testlink create 1 1 1 1 1
- testlink set -4 16.3 1 {} 778899
+ testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ testlink set -4 16.3 1 {} 778899 {} {} {} {} {} {} {} {} {}
list [catch x msg] $msg $wide
} {1 {can't set "y": variable must have integer value} 778899}
@@ -223,10 +240,10 @@ test link-8.1 {Tcl_UpdateLinkedVar procedure} {testlink} {
lappend x $args $int $real $bool $string $wide
}
set x {}
- testlink create 1 1 1 1 1
- testlink set 14 -2.0 0 xyzzy 995511
+ testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ testlink set 14 -2.0 0 xyzzy 995511 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
trace var int w x
- testlink update 32 4.0 3 abcd 113355
+ testlink update 32 4.0 3 abcd 113355 65 251 30001 60001 0xbabebeef 12322 32124 3.125 12312312340
trace vdelete int w x
set x
} {{int {} w} 32 -2.0 0 xyzzy 995511}
@@ -236,20 +253,22 @@ test link-8.2 {Tcl_UpdateLinkedVar procedure} {testlink} {
lappend x $args $int $real $bool $string $wide
}
set x {}
- testlink create 1 1 1 1 1
- testlink set 14 -2.0 0 xyzzy 995511
+ testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ testlink set 14 -2.0 0 xyzzy 995511 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
testlink delete
trace var int w x
- testlink update 32 4.0 6 abcd 113355
+ testlink update 32 4.0 6 abcd 113355 65 251 30001 60001 0xbabebeef 12322 32124 3.125 12312312340
trace vdelete int w x
set x
} {}
test link-8.3 {Tcl_UpdateLinkedVar procedure, read-only variable} {testlink} {
- testlink create 0 0 0 0 0
- list [catch {testlink update 47 {} {} {} {}} msg] $msg $int
+ testlink create 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ list [catch {
+ testlink update 47 {} {} {} {} {} {} {} {} {} {} {} {} {}
+ } msg] $msg $int
} {0 {} 47}
-catch {testlink set 0 0 0 - 0}
+catch {testlink set 0 0 0 - 0 0 0 0 0 0 0 0 0 0}
catch {testlink delete}
foreach i {int real bool string wide} {
catch {unset $i}
diff --git a/tests/linsert.test b/tests/linsert.test
index 7a1af4f..9262812 100644
--- a/tests/linsert.test
+++ b/tests/linsert.test
@@ -88,7 +88,7 @@ test linsert-2.2 {linsert errors} {
} {1 {wrong # args: should be "linsert list index element ?element ...?"}}
test linsert-2.3 {linsert errors} {
list [catch {linsert a 12x 2} msg] $msg
-} {1 {bad index "12x": must be integer or end?-integer?}}
+} {1 {bad index "12x": must be integer?[+-]integer? or end?[+-]integer?}}
test linsert-2.4 {linsert errors} {
list [catch {linsert \{ 12 2} msg] $msg
} {1 {unmatched open brace in list}}
diff --git a/tests/list.test b/tests/list.test
index 6ab9e8a..5a002a9 100644
--- a/tests/list.test
+++ b/tests/list.test
@@ -42,6 +42,8 @@ test list-1.21 {basic tests} {list a b c\\\nd} "a b c\\\\\\nd"
test list-1.22 {basic tests} {list "{ab}\\"} \\{ab\\}\\\\
test list-1.23 {basic tests} {list \{} "\\{"
test list-1.24 {basic tests} {list} {}
+test list-1.25 {basic tests} {list # #} {{#} #}
+test list-1.26 {basic tests} {list #\{ #\{} {\#\{ #\{}
# For the next round of tests create a list and then pick it apart
# with "index" to make sure that we get back exactly what went in.
@@ -103,6 +105,10 @@ test list-3.1 {SetListFromAny and lrange/concat results} {
slowsort {fred julie alex carol bill annie}
} {alex annie bill carol fred julie}
+test list-4.1 {Bug 3173086} {
+ string is list "{[list \\\\\}]}"
+} 1
+
# cleanup
::tcltest::cleanupTests
return
diff --git a/tests/listObj.test b/tests/listObj.test
index aa319bb..53017b1 100644
--- a/tests/listObj.test
+++ b/tests/listObj.test
@@ -16,19 +16,13 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-if {[info commands testobj] == {}} {
- puts "This application hasn't been compiled with the \"testobj\""
- puts "command, so I can't test the Tcl type and object support."
- ::tcltest::cleanupTests
- return
-}
+testConstraint testobj [llength [info commands testobj]]
catch {unset x}
-test listobj-1.1 {Tcl_GetListObjType} {
- set t [testobj types]
- set first [string first "list" $t]
- set result [expr {$first != -1}]
-} {1}
+test listobj-1.1 {Tcl_GetListObjType} emptyTest {
+ # Test removed; tested an internal detail
+ # that's no longer correct, and duplicated test obj-1.1
+} {}
test listobj-2.1 {Tcl_SetListObj, use in lappend} {
catch {unset x}
@@ -181,18 +175,28 @@ test listobj-9.1 {UpdateStringOfList} {
string length [list foo\x00help]
} 8
+test listobj-10.1 {Bug [2971669]} {*}{
+ -constraints testobj
+ -setup {
+ testobj freeallvars
+ }
+ -body {
+ set result {}
+ lappend result \
+ [testlistobj set 1 a b c d e] \
+ [testlistobj replace 1 0x7fffffff 0x7fffffff f] \
+ [testlistobj get 1]
+ }
+ -cleanup {
+ testobj freeallvars
+ }
+ -result {{a b c d e} {} {a b c d e f}}
+}
+
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/llength.test b/tests/llength.test
index aee532d..169c7ca 100644
--- a/tests/llength.test
+++ b/tests/llength.test
@@ -39,15 +39,3 @@ test llength-2.3 {error conditions} {
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/load.test b/tests/load.test
index 4794bd1..f5c08e9 100644
--- a/tests/load.test
+++ b/tests/load.test
@@ -17,38 +17,30 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
# Figure out what extension is used for shared libraries on this
# platform.
-
-if {$tcl_platform(platform) == "macintosh"} {
- puts "can't run dynamic library tests on macintosh machines"
- ::tcltest::cleanupTests
- return
+if {![info exists ext]} {
+ set ext [info sharedlibextension]
}
-
# Tests require the existence of one of the DLLs in the dltest directory.
-set ext [info sharedlibextension]
set testDir [file join [file dirname [info nameofexecutable]] dltest]
set x [file join $testDir pkga$ext]
set dll "[file tail $x]Required"
-::tcltest::testConstraint $dll [file readable $x]
+testConstraint $dll [file readable $x]
# Tests also require that this DLL has not already been loaded.
set loaded "[file tail $x]Loaded"
set alreadyLoaded [info loaded]
-::tcltest::testConstraint $loaded \
- [expr {![string match *pkga* $alreadyLoaded]}]
+testConstraint $loaded [expr {![string match *pkga* $alreadyLoaded]}]
set alreadyTotalLoaded [info loaded]
# Certain tests require the 'teststaticpkg' command from tcltest
-::tcltest::testConstraint teststaticpkg \
- [string compare {} [info commands teststaticpkg]]
+testConstraint teststaticpkg [llength [info commands teststaticpkg]]
# Test load-10.1 requires the 'testsimplefilesystem' command from tcltest
-::tcltest::testConstraint testsimplefilesystem \
- [string compare {} [info commands testsimplefilesystem]]
-
+testConstraint testsimplefilesystem \
+ [llength [info commands testsimplefilesystem]]
test load-1.1 {basic errors} {} {
list [catch {load} msg] $msg
@@ -92,7 +84,7 @@ test load-2.4 {loading with no _SafeInit procedure} [list $dll $loaded] {
test load-3.1 {error in _Init procedure, same interpreter} \
[list $dll $loaded] {
list [catch {load [file join $testDir pkge$ext] pkge} msg] \
- $msg $errorInfo $errorCode
+ $msg $::errorInfo $::errorCode
} {1 {couldn't open "non_existent": no such file or directory} {couldn't open "non_existent": no such file or directory
while executing
"open non_existent"
@@ -104,10 +96,10 @@ test load-3.2 {error in _Init procedure, slave interpreter} \
[list $dll $loaded] {
catch {interp delete x}
interp create x
- set errorCode foo
- set errorInfo bar
+ set ::errorCode foo
+ set ::errorInfo bar
set result [list [catch {load [file join $testDir pkge$ext] pkge x} msg] \
- $msg $errorInfo $errorCode]
+ $msg $::errorInfo $::errorCode]
interp delete x
set result
} {1 {couldn't open "non_existent": no such file or directory} {couldn't open "non_existent": no such file or directory
@@ -138,8 +130,10 @@ test load-5.1 {file name not specified and no static package: pick default} \
# On some platforms, like SunOS 4.1.3, these tests can't be run because
# they cause the process to exit.
+#
+# As of 2005, such ancient broken systems no longer matter.
-test load-6.1 {errors loading file} [list $dll $loaded nonPortable] {
+test load-6.1 {errors loading file} [list $dll $loaded] {
catch {load foo foo}
} {1}
@@ -212,5 +206,6 @@ test load-10.1 {load from vfs} \
-cleanup {testsimplefilesystem 0; cd $dir; unset dir}
# cleanup
+unset ext
::tcltest::cleanupTests
return
diff --git a/tests/lrange.test b/tests/lrange.test
index 80523fb..ec5936d 100644
--- a/tests/lrange.test
+++ b/tests/lrange.test
@@ -41,7 +41,7 @@ test lrange-1.8 {range of list elements} {
lrange {a b c d e} -2 -1
} {}
test lrange-1.9 {range of list elements} {
- lrange {a b c d e} -2 e
+ lrange {a b c d e} -2 end
} {a b c d e}
test lrange-1.10 {range of list elements} {
lrange "a b\{c d" 1 2
@@ -53,7 +53,7 @@ test lrange-1.12 {range of list elements} {
lrange "a b c d" end 100000
} d
test lrange-1.13 {range of list elements} {
- lrange "a b c d" e 3
+ lrange "a b c d" end 3
} d
test lrange-1.14 {range of list elements} {
lrange "a b c d" end 2
@@ -73,10 +73,10 @@ test lrange-2.2 {error conditions} {
} {1 {wrong # args: should be "lrange list first last"}}
test lrange-2.3 {error conditions} {
list [catch {lrange a b 6} msg] $msg
-} {1 {bad index "b": must be integer or end?-integer?}}
+} {1 {bad index "b": must be integer?[+-]integer? or end?[+-]integer?}}
test lrange-2.4 {error conditions} {
list [catch {lrange a 0 enigma} msg] $msg
-} {1 {bad index "enigma": must be integer or end?-integer?}}
+} {1 {bad index "enigma": must be integer?[+-]integer? or end?[+-]integer?}}
test lrange-2.5 {error conditions} {
list [catch {lrange "a \{b c" 3 4} msg] $msg
} {1 {unmatched open brace in list}}
diff --git a/tests/lrepeat.test b/tests/lrepeat.test
new file mode 100644
index 0000000..5e9d70f
--- /dev/null
+++ b/tests/lrepeat.test
@@ -0,0 +1,77 @@
+# Commands covered: lrepeat
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands. Sourcing this file into Tcl runs the tests and
+# generates output for errors. No output means no errors were found.
+#
+# Copyright (c) 2003 by Simon Geard.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+if {[lsearch [namespace children] ::tcltest] == -1} {
+ package require tcltest 2
+ namespace import -force ::tcltest::*
+}
+
+## Arg errors
+test lrepeat-1.1 {error cases} {
+ -body {
+ lrepeat
+ }
+ -returnCodes 1
+ -result {wrong # args: should be "lrepeat positiveCount value ?value ...?"}
+}
+test lrepeat-1.2 {error cases} {
+ -body {
+ lrepeat 1
+ }
+ -returnCodes 1
+ -result {wrong # args: should be "lrepeat positiveCount value ?value ...?"}
+}
+test lrepeat-1.3 {error cases} {
+ -body {
+ lrepeat a 1
+ }
+ -returnCodes 1
+ -result {expected integer but got "a"}
+}
+test lrepeat-1.4 {error cases} {
+ -body {
+ lrepeat -3 1
+ }
+ -returnCodes 1
+ -result {must have a count of at least 1}
+}
+test lrepeat-1.5 {error cases} {
+ -body {
+ lrepeat 0
+ }
+ -returnCodes 1
+ -result {wrong # args: should be "lrepeat positiveCount value ?value ...?"}
+}
+test lrepeat-1.6 {error cases} {
+ -body {
+ lrepeat 3.5 1
+ }
+ -returnCodes 1
+ -result {expected integer but got "3.5"}
+}
+
+## Okay
+test lrepeat-2.1 {normal cases} {
+ lrepeat 10 a
+} {a a a a a a a a a a}
+test lrepeat-2.2 {normal cases} {
+ lrepeat 3 [lrepeat 3 0]
+} {{0 0 0} {0 0 0} {0 0 0}}
+test lrepeat-2.3 {normal cases} {
+ lrepeat 3 a b c
+} {a b c a b c a b c}
+test lrepeat-2.4 {normal cases} {
+ lrepeat 3 [lrepeat 2 a] b c
+} {{a a} b c {a a} b c {a a} b c}
+
+# cleanup
+::tcltest::cleanupTests
+return
diff --git a/tests/lreplace.test b/tests/lreplace.test
index 5fc11a2..55bad37 100644
--- a/tests/lreplace.test
+++ b/tests/lreplace.test
@@ -108,13 +108,13 @@ test lreplace-2.2 {lreplace errors} {
} {1 {wrong # args: should be "lreplace list first last ?element element ...?"}}
test lreplace-2.3 {lreplace errors} {
list [catch {lreplace x a 10} msg] $msg
-} {1 {bad index "a": must be integer or end?-integer?}}
+} {1 {bad index "a": must be integer?[+-]integer? or end?[+-]integer?}}
test lreplace-2.4 {lreplace errors} {
list [catch {lreplace x 10 x} msg] $msg
-} {1 {bad index "x": must be integer or end?-integer?}}
+} {1 {bad index "x": must be integer?[+-]integer? or end?[+-]integer?}}
test lreplace-2.5 {lreplace errors} {
list [catch {lreplace x 10 1x} msg] $msg
-} {1 {bad index "1x": must be integer or end?-integer?}}
+} {1 {bad index "1x": must be integer?[+-]integer? or end?[+-]integer?}}
test lreplace-2.6 {lreplace errors} {
list [catch {lreplace x 3 2} msg] $msg
} {1 {list doesn't contain element 3}}
diff --git a/tests/lsearch.test b/tests/lsearch.test
index a0899c4..36bf389 100644
--- a/tests/lsearch.test
+++ b/tests/lsearch.test
@@ -59,7 +59,25 @@ test lsearch-2.9 {search modes} {
} 1
test lsearch-2.10 {search modes} {
list [catch {lsearch -glib {b.x bx xy bcx} b.x} msg] $msg
-} {1 {bad option "-glib": must be -all, -ascii, -decreasing, -dictionary, -exact, -glob, -increasing, -inline, -integer, -not, -real, -regexp, -sorted, or -start}}
+} {1 {bad option "-glib": must be -all, -ascii, -decreasing, -dictionary, -exact, -glob, -increasing, -index, -inline, -integer, -nocase, -not, -real, -regexp, -sorted, -start, or -subindices}}
+test lsearch-2.11 {search modes with -nocase} {
+ lsearch -exact -nocase {a b c A B C} A
+} 0
+test lsearch-2.12 {search modes with -nocase} {
+ lsearch -glob -nocase {a b c A B C} A*
+} 0
+test lsearch-2.13 {search modes with -nocase} {
+ lsearch -regexp -nocase {a b c A B C} ^A\$
+} 0
+test lsearch-2.14 {search modes without -nocase} {
+ lsearch -exact {a b c A B C} A
+} 3
+test lsearch-2.15 {search modes without -nocase} {
+ lsearch -glob {a b c A B C} A*
+} 3
+test lsearch-2.16 {search modes without -nocase} {
+ lsearch -regexp {a b c A B C} ^A\$
+} 3
test lsearch-3.1 {lsearch errors} {
list [catch lsearch msg] $msg
@@ -69,13 +87,19 @@ test lsearch-3.2 {lsearch errors} {
} {1 {wrong # args: should be "lsearch ?options? list pattern"}}
test lsearch-3.3 {lsearch errors} {
list [catch {lsearch a b c} msg] $msg
-} {1 {bad option "a": must be -all, -ascii, -decreasing, -dictionary, -exact, -glob, -increasing, -inline, -integer, -not, -real, -regexp, -sorted, or -start}}
+} {1 {bad option "a": must be -all, -ascii, -decreasing, -dictionary, -exact, -glob, -increasing, -index, -inline, -integer, -nocase, -not, -real, -regexp, -sorted, -start, or -subindices}}
test lsearch-3.4 {lsearch errors} {
list [catch {lsearch a b c d} msg] $msg
-} {1 {bad option "a": must be -all, -ascii, -decreasing, -dictionary, -exact, -glob, -increasing, -inline, -integer, -not, -real, -regexp, -sorted, or -start}}
+} {1 {bad option "a": must be -all, -ascii, -decreasing, -dictionary, -exact, -glob, -increasing, -index, -inline, -integer, -nocase, -not, -real, -regexp, -sorted, -start, or -subindices}}
test lsearch-3.5 {lsearch errors} {
list [catch {lsearch "\{" b} msg] $msg
} {1 {unmatched open brace in list}}
+test lsearch-3.6 {lsearch errors} {
+ list [catch {lsearch -index a b} msg] $msg
+} {1 {"-index" option must be followed by list index}}
+test lsearch-3.7 {lsearch errors} {
+ list [catch {lsearch -subindices -exact a b} msg] $msg
+} {1 {-subindices cannot be used without -index option}}
test lsearch-4.1 {binary data} {
lsearch -exact [list foo one\000two bar] bar
@@ -276,7 +300,7 @@ test lsearch-10.3 {offset searching} {
} 3
test lsearch-10.4 {offset searching} {
list [catch {lsearch -start foobar {a b c a b c} a} msg] $msg
-} {1 {bad index "foobar": must be integer or end?-integer?}}
+} {1 {bad index "foobar": must be integer?[+-]integer? or end?[+-]integer?}}
test lsearch-10.5 {offset searching} {
list [catch {lsearch -start 1 2} msg] $msg
} {1 {missing starting index}}
@@ -324,6 +348,15 @@ test lsearch-13.1 {search for all matches} {
test lsearch-13.2 {search for all matches} {
lsearch -all {a b a c a d} a
} {0 2 4}
+test lsearch-13.3 {search for all matches with -nocase} {
+ lsearch -all -exact -nocase {a b c A B C} A
+} {0 3}
+test lsearch-13.4 {search for all matches with -nocase} {
+ lsearch -all -glob -nocase {a b c A B C} A*
+} {0 3}
+test lsearch-13.5 {search for all matches with -nocase} {
+ lsearch -all -regexp -nocase {a b c A B C} ^A\$
+} {0 3}
test lsearch-14.1 {combinations: -all and -inline} {
lsearch -all -inline -glob {a1 b2 a3 c4 a5 d6} a*
@@ -364,6 +397,70 @@ test lsearch-16.2 {lsearch -regexp allows internal backrefs} {
lsearch -regexp {a aa b} {(.)\1}
} 1
+test lsearch-17.1 {lsearch -index option, basic functionality} {
+ lsearch -index 1 {{a c} {a b} {a a}} a
+} 2
+test lsearch-17.2 {lsearch -index option, basic functionality} {
+ lsearch -index 1 -exact {{a c} {a b} {a a}} a
+} 2
+test lsearch-17.3 {lsearch -index option, basic functionality} {
+ lsearch -index 1 -glob {{ab cb} {ab bb} {ab ab}} b*
+} 1
+test lsearch-17.4 {lsearch -index option, basic functionality} {
+ lsearch -index 1 -regexp {{ab cb} {ab bb} {ab ab}} {[cb]b}
+} 0
+test lsearch-17.5 {lsearch -index option, basic functionality} {
+ lsearch -all -index 0 -exact {{a c} {a b} {d a}} a
+} {0 1}
+test lsearch-17.6 {lsearch -index option, basic functionality} {
+ lsearch -all -index 1 -glob {{ab cb} {ab bb} {db bx}} b*
+} {1 2}
+test lsearch-17.7 {lsearch -index option, basic functionality} {
+ lsearch -all -index 1 -regexp {{ab cb} {ab bb} {ab ab}} {[cb]b}
+} {0 1}
+
+test lsearch-18.1 {lsearch -index option, list as index basic functionality} {
+ lsearch -index {0 0} {{{x x} {x b} {a d}} {{a c} {a b} {a a}}} a
+} 1
+test lsearch-18.2 {lsearch -index option, list as index basic functionality} {
+ lsearch -index {2 0} -exact {{{x x} {x b} {a d}} {{a c} {a b} {a a}}} a
+} 0
+test lsearch-18.3 {lsearch -index option, list as index basic functionality} {
+ lsearch -index {1 1} -glob {{{ab cb} {ab bb} {ab ab}} {{ab cb} {ab bb} {ab ab}}} b*
+} 0
+test lsearch-18.4 {lsearch -index option, list as index basic functionality} {
+ lsearch -index {0 1} -regexp {{{ab cb} {ab bb} {ab ab}} {{ab cb} {ab bb} {ab ab}}} {[cb]b}
+} 0
+test lsearch-18.5 {lsearch -index option, list as index basic functionality} {
+ lsearch -all -index {0 0} -exact {{{a c} {a b} {d a}} {{a c} {a b} {d a}}} a
+} {0 1}
+
+test lsearch-19.1 {lsearch -sunindices option} {
+ lsearch -subindices -index {0 0} {{{x x} {x b} {a d}} {{a c} {a b} {a a}}} a
+} {1 0 0}
+test lsearch-19.2 {lsearch -sunindices option} {
+ lsearch -subindices -index {2 0} -exact {{{x x} {x b} {a d}} {{a c} {a b} {a a}}} a
+} {0 2 0}
+test lsearch-19.3 {lsearch -sunindices option} {
+ lsearch -subindices -index {1 1} -glob {{{ab cb} {ab bb} {ab ab}} {{ab cb} {ab bb} {ab ab}}} b*
+} {0 1 1}
+test lsearch-19.4 {lsearch -sunindices option} {
+ lsearch -subindices -index {0 1} -regexp {{{ab cb} {ab bb} {ab ab}} {{ab cb} {ab bb} {ab ab}}} {[cb]b}
+} {0 0 1}
+test lsearch-19.5 {lsearch -sunindices option} {
+ lsearch -subindices -all -index {0 0} -exact {{{a c} {a b} {d a}} {{a c} {a b} {d a}}} a
+} {{0 0 0} {1 0 0}}
+
+test lsearch-20.1 {lsearch -index option, index larger than sublists} {
+ list [catch {lsearch -index 2 {{a c} {a b} {a a}} a} msg] $msg
+} {1 {element 2 missing from sublist "a c"}}
+test lsearch-20.2 {lsearch -index option, malformed index} {
+ list [catch {lsearch -index foo {{a c} {a b} {a a}} a} msg] $msg
+} {1 {bad index "foo": must be integer?[+-]integer? or end?[+-]integer?}}
+test lsearch-20.3 {lsearch -index option, malformed index} {
+ list [catch {lsearch -index \{ {{a c} {a b} {a a}} a} msg] $msg
+} {1 {unmatched open brace in list}}
+
test lsearch-21.1 {lsearch shimmering crash} {
set x 0
lsearch -exact -integer $x $x
diff --git a/tests/lset.test b/tests/lset.test
index e38f12f..cc1c00b 100644
--- a/tests/lset.test
+++ b/tests/lset.test
@@ -20,430 +20,391 @@ proc failTrace {name1 name2 op} {
error "trace failed"
}
-set lset lset
+testConstraint testevalex [llength [info commands testevalex]]
set noRead {}
trace add variable noRead read failTrace
set noWrite {a b c}
trace add variable noWrite write failTrace
-test lset-1.1 {lset, not compiled, arg count} {
- list [catch {eval $lset} msg] $msg
-} "1 {wrong \# args: should be \"lset listVar index ?index...? value\"}"
-
-test lset-1.2 {lset, not compiled, no such var} {
- list [catch {eval [list $lset noSuchVar 0 {}]} msg] $msg
+test lset-1.1 {lset, not compiled, arg count} testevalex {
+ list [catch {testevalex lset} msg] $msg
+} "1 {wrong \# args: should be \"lset listVar ?index? ?index...? value\"}"
+test lset-1.2 {lset, not compiled, no such var} testevalex {
+ list [catch {testevalex {lset noSuchVar 0 {}}} msg] $msg
} "1 {can't read \"noSuchVar\": no such variable}"
-
-test lset-1.3 {lset, not compiled, var not readable} {
- list [catch {eval [list $lset noRead 0 {}]} msg] $msg
+test lset-1.3 {lset, not compiled, var not readable} testevalex {
+ list [catch {testevalex {lset noRead 0 {}}} msg] $msg
} "1 {can't read \"noRead\": trace failed}"
-test lset-2.1 {lset, not compiled, 3 args, second arg a plain index} {
+test lset-2.1 {lset, not compiled, 3 args, second arg a plain index} testevalex {
set x {0 1 2}
- list [eval [list $lset x 0 3]] $x
+ list [testevalex {lset x 0 3}] $x
} {{3 1 2} {3 1 2}}
-
-test lset-2.2 {lset, not compiled, 3 args, second arg neither index nor list} {
+test lset-2.2 {lset, not compiled, 3 args, second arg neither index nor list} testevalex {
set x {0 1 2}
list [catch {
- eval [list $lset x {{bad}1} 3]
+ testevalex {lset x {{bad}1} 3}
} msg] $msg
-} "1 {bad index \"{bad}1\": must be integer or end?-integer?}"
+} {1 {bad index "{bad}1": must be integer?[+-]integer? or end?[+-]integer?}}
-test lset-3.1 {lset, not compiled, 3 args, data duplicated} {
+test lset-3.1 {lset, not compiled, 3 args, data duplicated} testevalex {
set x {0 1 2}
- list [eval [list $lset x 0 $x]] $x
+ list [testevalex {lset x 0 $x}] $x
} {{{0 1 2} 1 2} {{0 1 2} 1 2}}
-
-test lset-3.2 {lset, not compiled, 3 args, data duplicated} {
+test lset-3.2 {lset, not compiled, 3 args, data duplicated} testevalex {
set x {0 1}
set y $x
- list [eval [list $lset x 0 2]] $x $y
+ list [testevalex {lset x 0 2}] $x $y
} {{2 1} {2 1} {0 1}}
-
-test lset-3.3 {lset, not compiled, 3 args, data duplicated} {
+test lset-3.3 {lset, not compiled, 3 args, data duplicated} testevalex {
set x {0 1}
set y $x
- list [eval [list $lset x 0 $x]] $x $y
+ list [testevalex {lset x 0 $x}] $x $y
} {{{0 1} 1} {{0 1} 1} {0 1}}
-
-test lset-3.4 {lset, not compiled, 3 args, data duplicated} {
+test lset-3.4 {lset, not compiled, 3 args, data duplicated} testevalex {
set x {0 1 2}
- list [eval [list $lset x [list 0] $x]] $x
+ list [testevalex {lset x [list 0] $x}] $x
} {{{0 1 2} 1 2} {{0 1 2} 1 2}}
-
-test lset-3.5 {lset, not compiled, 3 args, data duplicated} {
+test lset-3.5 {lset, not compiled, 3 args, data duplicated} testevalex {
set x {0 1}
set y $x
- list [eval [list $lset x [list 0] 2]] $x $y
+ list [testevalex {lset x [list 0] 2}] $x $y
} {{2 1} {2 1} {0 1}}
-
-test lset-3.6 {lset, not compiled, 3 args, data duplicated} {
+test lset-3.6 {lset, not compiled, 3 args, data duplicated} testevalex {
set x {0 1}
set y $x
- list [eval [list $lset x [list 0] $x]] $x $y
+ list [testevalex {lset x [list 0] $x}] $x $y
} {{{0 1} 1} {{0 1} 1} {0 1}}
-test lset-4.1 {lset, not compiled, 3 args, not a list} {
+test lset-4.1 {lset, not compiled, 3 args, not a list} testevalex {
set a "x \{"
list [catch {
- eval [list $lset a [list 0] y]
+ testevalex {lset a [list 0] y}
} msg] $msg
} {1 {unmatched open brace in list}}
-
-test lset-4.2 {lset, not compiled, 3 args, bad index} {
+test lset-4.2 {lset, not compiled, 3 args, bad index} testevalex {
set a {x y z}
list [catch {
- eval [list $lset a [list 2a2] w]
+ testevalex {lset a [list 2a2] w}
} msg] $msg
-} {1 {bad index "2a2": must be integer or end?-integer?}}
-
-test lset-4.3 {lset, not compiled, 3 args, index out of range} {
+} {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}}
+test lset-4.3 {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
- eval [list $lset a [list -1] w]
+ testevalex {lset a [list -1] w}
} msg] $msg
} {1 {list index out of range}}
-
-test lset-4.4 {lset, not compiled, 3 args, index out of range} {
+test lset-4.4 {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
- eval [list $lset a [list 3] w]
+ testevalex {lset a [list 3] w}
} msg] $msg
} {1 {list index out of range}}
-
-test lset-4.5 {lset, not compiled, 3 args, index out of range} {
+test lset-4.5 {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
- eval [list $lset a [list end--1] w]
+ testevalex {lset a [list end--1] w}
} msg] $msg
} {1 {list index out of range}}
-
-test lset-4.6 {lset, not compiled, 3 args, index out of range} {
+test lset-4.6 {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
- eval [list $lset a [list end-3] w]
+ testevalex {lset a [list end-3] w}
} msg] $msg
} {1 {list index out of range}}
-
-test lset-4.7 {lset, not compiled, 3 args, not a list} {
+test lset-4.7 {lset, not compiled, 3 args, not a list} testevalex {
set a "x \{"
list [catch {
- eval [list $lset a 0 y]
+ testevalex {lset a 0 y}
} msg] $msg
} {1 {unmatched open brace in list}}
-
-test lset-4.8 {lset, not compiled, 3 args, bad index} {
+test lset-4.8 {lset, not compiled, 3 args, bad index} testevalex {
set a {x y z}
list [catch {
- eval [list $lset a 2a2 w]
+ testevalex {lset a 2a2 w}
} msg] $msg
-} {1 {bad index "2a2": must be integer or end?-integer?}}
-
-test lset-4.9 {lset, not compiled, 3 args, index out of range} {
+} {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}}
+test lset-4.9 {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
- eval [list $lset a -1 w]
+ testevalex {lset a -1 w}
} msg] $msg
} {1 {list index out of range}}
-
-test lset-4.10 {lset, not compiled, 3 args, index out of range} {
+test lset-4.10 {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
- eval [list $lset a 3 w]
+ testevalex {lset a 3 w}
} msg] $msg
} {1 {list index out of range}}
-
-test lset-4.11 {lset, not compiled, 3 args, index out of range} {
+test lset-4.11 {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
- eval [list $lset a end--1 w]
+ testevalex {lset a end--1 w}
} msg] $msg
} {1 {list index out of range}}
-
-test lset-4.12 {lset, not compiled, 3 args, index out of range} {
+test lset-4.12 {lset, not compiled, 3 args, index out of range} testevalex {
set a {x y z}
list [catch {
- eval [list $lset a end-3 w]
+ testevalex {lset a end-3 w}
} msg] $msg
} {1 {list index out of range}}
-test lset-5.1 {lset, not compiled, 3 args, can't set variable} {
+test lset-5.1 {lset, not compiled, 3 args, can't set variable} testevalex {
list [catch {
- eval [list $lset noWrite 0 d]
+ testevalex {lset noWrite 0 d}
} msg] $msg $noWrite
} {1 {can't set "noWrite": trace failed} {d b c}}
-
-test lset-5.2 {lset, not compiled, 3 args, can't set variable} {
+test lset-5.2 {lset, not compiled, 3 args, can't set variable} testevalex {
list [catch {
- eval [list $lset noWrite [list 0] d]
+ testevalex {lset noWrite [list 0] d}
} msg] $msg $noWrite
} {1 {can't set "noWrite": trace failed} {d b c}}
-test lset-6.1 {lset, not compiled, 3 args, 1-d list basics} {
+test lset-6.1 {lset, not compiled, 3 args, 1-d list basics} testevalex {
set a {x y z}
- list [eval [list $lset a 0 a]] $a
+ list [testevalex {lset a 0 a}] $a
} {{a y z} {a y z}}
-
-test lset-6.2 {lset, not compiled, 3 args, 1-d list basics} {
+test lset-6.2 {lset, not compiled, 3 args, 1-d list basics} testevalex {
set a {x y z}
- list [eval [list $lset a [list 0] a]] $a
+ list [testevalex {lset a [list 0] a}] $a
} {{a y z} {a y z}}
-
-test lset-6.3 {lset, not compiled, 1-d list basics} {
+test lset-6.3 {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
- list [eval [list $lset a 2 a]] $a
+ list [testevalex {lset a 2 a}] $a
} {{x y a} {x y a}}
-
-test lset-6.4 {lset, not compiled, 1-d list basics} {
+test lset-6.4 {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
- list [eval [list $lset a [list 2] a]] $a
+ list [testevalex {lset a [list 2] a}] $a
} {{x y a} {x y a}}
-
-test lset-6.5 {lset, not compiled, 1-d list basics} {
+test lset-6.5 {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
- list [eval [list $lset a end a]] $a
+ list [testevalex {lset a end a}] $a
} {{x y a} {x y a}}
-
-test lset-6.6 {lset, not compiled, 1-d list basics} {
+test lset-6.6 {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
- list [eval [list $lset a [list end] a]] $a
+ list [testevalex {lset a [list end] a}] $a
} {{x y a} {x y a}}
-
-test lset-6.7 {lset, not compiled, 1-d list basics} {
+test lset-6.7 {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
- list [eval [list $lset a end-0 a]] $a
+ list [testevalex {lset a end-0 a}] $a
} {{x y a} {x y a}}
-
-test lset-6.8 {lset, not compiled, 1-d list basics} {
+test lset-6.8 {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
- list [eval [list $lset a [list end-0] a]] $a
+ list [testevalex {lset a [list end-0] a}] $a
} {{x y a} {x y a}}
-
-test lset-6.9 {lset, not compiled, 1-d list basics} {
+test lset-6.9 {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
- list [eval [list $lset a end-2 a]] $a
+ list [testevalex {lset a end-2 a}] $a
} {{a y z} {a y z}}
-
-test lset-6.10 {lset, not compiled, 1-d list basics} {
+test lset-6.10 {lset, not compiled, 1-d list basics} testevalex {
set a {x y z}
- list [eval [list $lset a [list end-2] a]] $a
+ list [testevalex {lset a [list end-2] a}] $a
} {{a y z} {a y z}}
-test lset-7.1 {lset, not compiled, data sharing} {
+test lset-7.1 {lset, not compiled, data sharing} testevalex {
set a 0
- list [eval [list $lset a $a {gag me}]] $a
+ list [testevalex {lset a $a {gag me}}] $a
} {{{gag me}} {{gag me}}}
-
-test lset-7.2 {lset, not compiled, data sharing} {
+test lset-7.2 {lset, not compiled, data sharing} testevalex {
set a [list 0]
- list [eval [list $lset a $a {gag me}]] $a
+ list [testevalex {lset a $a {gag me}}] $a
} {{{gag me}} {{gag me}}}
-
-test lset-7.3 {lset, not compiled, data sharing} {
+test lset-7.3 {lset, not compiled, data sharing} testevalex {
set a {x y}
- list [eval [list $lset a 0 $a]] $a
+ list [testevalex {lset a 0 $a}] $a
} {{{x y} y} {{x y} y}}
-
-test lset-7.4 {lset, not compiled, data sharing} {
+test lset-7.4 {lset, not compiled, data sharing} testevalex {
set a {x y}
- list [eval [list $lset a [list 0] $a]] $a
+ list [testevalex {lset a [list 0] $a}] $a
} {{{x y} y} {{x y} y}}
-
-test lset-7.5 {lset, not compiled, data sharing} {
+test lset-7.5 {lset, not compiled, data sharing} testevalex {
set n 0
set a {x y}
- list [eval [list $lset a $n $n]] $a $n
+ list [testevalex {lset a $n $n}] $a $n
} {{0 y} {0 y} 0}
-
-test lset-7.6 {lset, not compiled, data sharing} {
+test lset-7.6 {lset, not compiled, data sharing} testevalex {
set n [list 0]
set a {x y}
- list [eval [list $lset a $n $n]] $a $n
+ list [testevalex {lset a $n $n}] $a $n
} {{0 y} {0 y} 0}
-
-test lset-7.7 {lset, not compiled, data sharing} {
+test lset-7.7 {lset, not compiled, data sharing} testevalex {
set n 0
set a [list $n $n]
- list [eval [list $lset a $n 1]] $a $n
+ list [testevalex {lset a $n 1}] $a $n
} {{1 0} {1 0} 0}
-
-test lset-7.8 {lset, not compiled, data sharing} {
+test lset-7.8 {lset, not compiled, data sharing} testevalex {
set n [list 0]
set a [list $n $n]
- list [eval [list $lset a $n 1]] $a $n
+ list [testevalex {lset a $n 1}] $a $n
} {{1 0} {1 0} 0}
-
-test lset-7.9 {lset, not compiled, data sharing} {
+test lset-7.9 {lset, not compiled, data sharing} testevalex {
set a 0
- list [eval [list $lset a $a $a]] $a
+ list [testevalex {lset a $a $a}] $a
} {0 0}
-
-test lset-7.10 {lset, not compiled, data sharing} {
+test lset-7.10 {lset, not compiled, data sharing} testevalex {
set a [list 0]
- list [eval [list $lset a $a $a]] $a
+ list [testevalex {lset a $a $a}] $a
} {0 0}
-test lset-8.1 {lset, not compiled, malformed sublist} {
+test lset-8.1 {lset, not compiled, malformed sublist} testevalex {
set a [list "a \{" b]
- list [catch {eval [list $lset a 0 1 c]} msg] $msg
+ list [catch {testevalex {lset a 0 1 c}} msg] $msg
} {1 {unmatched open brace in list}}
-
-test lset-8.2 {lset, not compiled, malformed sublist} {
+test lset-8.2 {lset, not compiled, malformed sublist} testevalex {
set a [list "a \{" b]
- list [catch {eval [list $lset a {0 1} c]} msg] $msg
+ list [catch {testevalex {lset a {0 1} c}} msg] $msg
} {1 {unmatched open brace in list}}
-
-test lset-8.3 {lset, not compiled, bad second index} {
+test lset-8.3 {lset, not compiled, bad second index} testevalex {
set a {{b c} {d e}}
- list [catch {eval [list $lset a 0 2a2 f]} msg] $msg
-} {1 {bad index "2a2": must be integer or end?-integer?}}
-
-test lset-8.4 {lset, not compiled, bad second index} {
+ list [catch {testevalex {lset a 0 2a2 f}} msg] $msg
+} {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}}
+test lset-8.4 {lset, not compiled, bad second index} testevalex {
set a {{b c} {d e}}
- list [catch {eval [list $lset a {0 2a2} f]} msg] $msg
-} {1 {bad index "2a2": must be integer or end?-integer?}}
-
-test lset-8.5 {lset, not compiled, second index out of range} {
+ list [catch {testevalex {lset a {0 2a2} f}} msg] $msg
+} {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}}
+test lset-8.5 {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
- list [catch {eval [list $lset a 2 -1 h]} msg] $msg
+ list [catch {testevalex {lset a 2 -1 h}} msg] $msg
} {1 {list index out of range}}
-
-test lset-8.6 {lset, not compiled, second index out of range} {
+test lset-8.6 {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
- list [catch {eval [list $lset a {2 -1} h]} msg] $msg
+ list [catch {testevalex {lset a {2 -1} h}} msg] $msg
} {1 {list index out of range}}
-
-test lset-8.7 {lset, not compiled, second index out of range} {
+test lset-8.7 {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
- list [catch {eval [list $lset a 2 2 h]} msg] $msg
+ list [catch {testevalex {lset a 2 2 h}} msg] $msg
} {1 {list index out of range}}
-
-test lset-8.8 {lset, not compiled, second index out of range} {
+test lset-8.8 {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
- list [catch {eval [list $lset a {2 2} h]} msg] $msg
+ list [catch {testevalex {lset a {2 2} h}} msg] $msg
} {1 {list index out of range}}
-
-test lset-8.9 {lset, not compiled, second index out of range} {
+test lset-8.9 {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
- list [catch {eval [list $lset a 2 end--1 h]} msg] $msg
+ list [catch {testevalex {lset a 2 end--1 h}} msg] $msg
} {1 {list index out of range}}
-
-test lset-8.10 {lset, not compiled, second index out of range} {
+test lset-8.10 {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
- list [catch {eval [list $lset a {2 end--1} h]} msg] $msg
+ list [catch {testevalex {lset a {2 end--1} h}} msg] $msg
} {1 {list index out of range}}
-
-test lset-8.11 {lset, not compiled, second index out of range} {
+test lset-8.11 {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
- list [catch {eval [list $lset a 2 end-2 h]} msg] $msg
+ list [catch {testevalex {lset a 2 end-2 h}} msg] $msg
} {1 {list index out of range}}
-
-test lset-8.12 {lset, not compiled, second index out of range} {
+test lset-8.12 {lset, not compiled, second index out of range} testevalex {
set a {{b c} {d e} {f g}}
- list [catch {eval [list $lset a {2 end-2} h]} msg] $msg
+ list [catch {testevalex {lset a {2 end-2} h}} msg] $msg
} {1 {list index out of range}}
-test lset-9.1 {lset, not compiled, entire variable} {
+test lset-9.1 {lset, not compiled, entire variable} testevalex {
set a x
- list [eval [list $lset a y]] $a
+ list [testevalex {lset a y}] $a
} {y y}
-
-test lset-9.2 {lset, not compiled, entire variable} {
+test lset-9.2 {lset, not compiled, entire variable} testevalex {
set a x
- list [eval [list $lset a {} y]] $a
+ list [testevalex {lset a {} y}] $a
} {y y}
-test lset-10.1 {lset, not compiled, shared data} {
+test lset-10.1 {lset, not compiled, shared data} testevalex {
set row {p q}
set a [list $row $row]
- list [eval [list $lset a 0 0 x]] $a
+ list [testevalex {lset a 0 0 x}] $a
} {{{x q} {p q}} {{x q} {p q}}}
-
-test lset-10.2 {lset, not compiled, shared data} {
+test lset-10.2 {lset, not compiled, shared data} testevalex {
set row {p q}
set a [list $row $row]
- list [eval [list $lset a {0 0} x]] $a
+ list [testevalex {lset a {0 0} x}] $a
} {{{x q} {p q}} {{x q} {p q}}}
+test lset-10.3 {lset, not compiled, shared data, [Bug 1333036]} testevalex {
+ set a [list [list p q] [list r s]]
+ set b $a
+ list [testevalex {lset b {0 0} x}] $a
+} {{{x q} {r s}} {{p q} {r s}}}
-test lset-11.1 {lset, not compiled, 2-d basics} {
+test lset-11.1 {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
- list [eval [list $lset a 0 0 f]] $a
+ list [testevalex {lset a 0 0 f}] $a
} {{{f c} {d e}} {{f c} {d e}}}
-
-test lset-11.2 {lset, not compiled, 2-d basics} {
+test lset-11.2 {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
- list [eval [list $lset a {0 0} f]] $a
+ list [testevalex {lset a {0 0} f}] $a
} {{{f c} {d e}} {{f c} {d e}}}
-
-test lset-11.3 {lset, not compiled, 2-d basics} {
+test lset-11.3 {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
- list [eval [list $lset a 0 1 f]] $a
+ list [testevalex {lset a 0 1 f}] $a
} {{{b f} {d e}} {{b f} {d e}}}
-
-test lset-11.4 {lset, not compiled, 2-d basics} {
+test lset-11.4 {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
- list [eval [list $lset a {0 1} f]] $a
+ list [testevalex {lset a {0 1} f}] $a
} {{{b f} {d e}} {{b f} {d e}}}
-
-test lset-11.5 {lset, not compiled, 2-d basics} {
+test lset-11.5 {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
- list [eval [list $lset a 1 0 f]] $a
+ list [testevalex {lset a 1 0 f}] $a
} {{{b c} {f e}} {{b c} {f e}}}
-
-test lset-11.6 {lset, not compiled, 2-d basics} {
+test lset-11.6 {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
- list [eval [list $lset a {1 0} f]] $a
+ list [testevalex {lset a {1 0} f}] $a
} {{{b c} {f e}} {{b c} {f e}}}
-
-test lset-11.7 {lset, not compiled, 2-d basics} {
+test lset-11.7 {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
- list [eval [list $lset a 1 1 f]] $a
+ list [testevalex {lset a 1 1 f}] $a
} {{{b c} {d f}} {{b c} {d f}}}
-
-test lset-11.8 {lset, not compiled, 2-d basics} {
+test lset-11.8 {lset, not compiled, 2-d basics} testevalex {
set a {{b c} {d e}}
- list [eval [list $lset a {1 1} f]] $a
+ list [testevalex {lset a {1 1} f}] $a
} {{{b c} {d f}} {{b c} {d f}}}
-test lset-12.0 {lset, not compiled, typical sharing pattern} {
+test lset-12.0 {lset, not compiled, typical sharing pattern} testevalex {
set zero 0
set row [list $zero $zero $zero $zero]
set ident [list $row $row $row $row]
for { set i 0 } { $i < 4 } { incr i } {
- eval [list $lset ident $i $i 1]
+ testevalex {lset ident $i $i 1}
}
set ident
} {{1 0 0 0} {0 1 0 0} {0 0 1 0} {0 0 0 1}}
-test lset-13.0 {lset, not compiled, shimmering hell} {
+test lset-13.0 {lset, not compiled, shimmering hell} testevalex {
set a 0
- list [eval [list $lset a $a $a $a $a {gag me}]] $a
+ list [testevalex {lset a $a $a $a $a {gag me}}] $a
} {{{{{{gag me}}}}} {{{{{gag me}}}}}}
-
-test lset-13.1 {lset, not compiled, shimmering hell} {
+test lset-13.1 {lset, not compiled, shimmering hell} testevalex {
set a [list 0]
- list [eval [list $lset a $a $a $a $a {gag me}]] $a
+ list [testevalex {lset a $a $a $a $a {gag me}}] $a
} {{{{{{gag me}}}}} {{{{{gag me}}}}}}
-
-test lset-13.2 {lset, not compiled, shimmering hell} {
+test lset-13.2 {lset, not compiled, shimmering hell} testevalex {
set a [list 0 0 0 0]
- list [eval [list $lset a $a {gag me}]] $a
+ list [testevalex {lset a $a {gag me}}] $a
} {{{{{{gag me}}}} 0 0 0} {{{{{gag me}}}} 0 0 0}}
-test lset-14.1 {lset, not compiled, list args, is string rep preserved?} {
+test lset-14.1 {lset, not compiled, list args, is string rep preserved?} testevalex {
set a { { 1 2 } { 3 4 } }
- catch { eval [list $lset a {1 5} 5] }
+ catch { testevalex {lset a {1 5} 5} }
list $a [lindex $a 1]
} "{ { 1 2 } { 3 4 } } { 3 4 }"
-
-test lset-14.2 {lset, not compiled, flat args, is string rep preserved?} {
+test lset-14.2 {lset, not compiled, flat args, is string rep preserved?} testevalex {
set a { { 1 2 } { 3 4 } }
- catch { eval [list $lset a 1 5 5] }
+ catch { testevalex {lset a 1 5 5} }
list $a [lindex $a 1]
} "{ { 1 2 } { 3 4 } } { 3 4 }"
+testConstraint testobj [llength [info commands testobj]]
+test lset-15.1 {lset: shared intrep [Bug 1677512]} -setup {
+ teststringobj set 1 {{1 2} 3}
+ testobj convert 1 list
+ testobj duplicate 1 2
+ variable x [teststringobj get 1]
+ variable y [teststringobj get 2]
+ testobj freeallvars
+ set l [list $y z]
+ unset y
+} -constraints testobj -body {
+ lset l 0 0 0 5
+ lindex $x 0 0
+} -cleanup {
+ unset -nocomplain x l
+} -result 1
+
catch {unset noRead}
catch {unset noWrite}
catch {rename failTrace {}}
diff --git a/tests/lsetComp.test b/tests/lsetComp.test
index f7b6cf7..2b89a47 100755..100644
--- a/tests/lsetComp.test
+++ b/tests/lsetComp.test
@@ -34,7 +34,7 @@ test lsetComp-1.1 {lset, compiled, wrong \# args} {
evalInProc {
lset
}
-} "1 {wrong \# args: should be \"lset listVar index ?index...? value\"}"
+} "1 {wrong \# args: should be \"lset listVar ?index? ?index...? value\"}"
test lsetComp-2.1 {lset, compiled, list of args, not a simple var name} {
evalInProc {
diff --git a/tests/macFCmd.test b/tests/macFCmd.test
deleted file mode 100644
index c35b793..0000000
--- a/tests/macFCmd.test
+++ /dev/null
@@ -1,200 +0,0 @@
-# This file tests the tclfCmd.c file.
-#
-# This file contains a collection of tests for one or more of the Tcl
-# built-in commands. Sourcing this file into Tcl runs the tests and
-# generates output for errors. No output means no errors were found.
-#
-# Copyright (c) 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.
-
-if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
- namespace import -force ::tcltest::*
-}
-
-# These tests really need to be run from a writable directory, which
-# it is assumed [temporaryDirectory] is.
-set oldcwd [pwd]
-cd [temporaryDirectory]
-
-catch {file delete -force foo.dir}
-file mkdir foo.dir
-if {[catch {file attributes foo.dir -readonly 1}]} {
- set ::tcltest::testConstraints(fileSharing) 0
- set ::tcltest::testConstraints(notFileSharing) 1
-} else {
- set ::tcltest::testConstraints(fileSharing) 1
- set ::tcltest::testConstraints(notFileSharing) 0
-}
-file delete -force foo.dir
-
-test macFCmd-1.1 {GetFileFinderAttributes - no file} {macOnly} {
- catch {file delete -force foo.file}
- list [catch {file attributes foo.file -creator} msg] $msg
-} {1 {could not read "foo.file": no such file or directory}}
-test macFCmd-1.2 {GetFileFinderAttributes - creator} {macOnly} {
- catch {file delete -force foo.file}
- catch {close [open foo.file w]}
- list [catch {file attributes foo.file -creator} msg] \
- [regexp {MPW |CWIE} $msg] [file delete -force foo.file]
-} {0 1 {}}
-test macFCmd-1.3 {GetFileFinderAttributes - type} {macOnly} {
- catch {file delete -force foo.file}
- catch {close [open foo.file w]}
- list [catch {file attributes foo.file -type} msg] $msg \
- [file delete -force foo.file]
-} {0 TEXT {}}
-test macFCmd-1.4 {GetFileFinderAttributes - not hidden} {macOnly} {
- catch {file delete -force foo.file}
- catch {close [open foo.file w]}
- list [catch {file attributes foo.file -hidden} msg] $msg \
- [file delete -force foo.file]
-} {0 0 {}}
-test macFCmd-1.5 {GetFileFinderAttributes - hidden} {macOnly} {
- catch {file delete -force foo.file}
- catch {close [open foo.file w]}
- file attributes foo.file -hidden 1
- list [catch {file attributes foo.file -hidden} msg] $msg \
- [file delete -force foo.file]
-} {0 1 {}}
-test macFCmd-1.6 {GetFileFinderAttributes - folder creator} {macOnly} {
- catch {file delete -force foo.dir}
- file mkdir foo.dir
- list [catch {file attributes foo.dir -creator} msg] $msg \
- [file delete -force foo.dir]
-} {0 Fldr {}}
-test macFCmd-1.7 {GetFileFinderAttributes - folder type} {macOnly} {
- catch {file delete -force foo.dir}
- file mkdir foo.dir
- list [catch {file attributes foo.dir -type} msg] $msg \
- [file delete -force foo.dir]
-} {0 Fldr {}}
-test macFCmd-1.8 {GetFileFinderAttributes - folder hidden} {macOnly} {
- catch {file delete -force foo.dir}
- file mkdir foo.dir
- list [catch {file attributes foo.dir -hidden} msg] $msg \
- [file delete -force foo.dir]
-} {0 0 {}}
-
-test macFCmd-2.1 {GetFileReadOnly - bad file} {macOnly} {
- catch {file delete -force foo.file}
- list [catch {file attributes foo.file -readonly} msg] $msg
-} {1 {could not read "foo.file": no such file or directory}}
-test macFCmd-2.2 {GetFileReadOnly - file not read only} {macOnly} {
- catch {file delete -force foo.file}
- close [open foo.file w]
- list [catch {file attributes foo.file -readonly} msg] $msg \
- [file delete -force foo.file]
-} {0 0 {}}
-test macFCmd-2.3 {GetFileReadOnly - file read only} {macOnly} {
- catch {file delete -force foo.file}
- close [open foo.file w]
- file attributes foo.file -readonly 1
- list [catch {file attributes foo.file -readonly} msg] $msg \
- [file delete -force foo.file]
-} {0 1 {}}
-test macFCmd-2.4 {GetFileReadOnly - directory not read only} {macOnly} {
- catch {file delete -force foo.dir}
- file mkdir foo.dir
- list [catch {file attributes foo.dir -readonly} msg] $msg \
- [file delete -force foo.dir]
-} {0 0 {}}
-test macFCmd-2.5 {GetFileReadOnly - directory read only} {macOnly fileSharing} {
- catch {file delete -force foo.dir}
- file mkdir foo.dir
- file attributes foo.dir -readonly 1
- list [catch {file attributes foo.dir -readonly} msg] $msg \
- [file delete -force foo.dir]
-} {0 1 {}}
-
-test macFCmd-3.1 {SetFileFinderAttributes - bad file} {macOnly} {
- catch {file delete -force foo.file}
- list [catch {file attributes foo.file -creator FOOO} msg] $msg
-} {1 {could not read "foo.file": no such file or directory}}
-test macFCmd-3.2 {SetFileFinderAttributes - creator} {macOnly} {
- catch {file delete -force foo.file}
- close [open foo.file w]
- list [catch {file attributes foo.file -creator FOOO} msg] $msg \
- [file attributes foo.file -creator] [file delete -force foo.file]
-} {0 {} FOOO {}}
-test macFCmd-3.3 {SetFileFinderAttributes - bad creator} {macOnly} {
- catch {file delete -force foo.file}
- close [open foo.file w]
- list [catch {file attributes foo.file -creator 0} msg] $msg \
- [file delete -force foo.file]
-} {1 {expected Macintosh OS type but got "0"} {}}
-test macFCmd-3.4 {SetFileFinderAttributes - hidden} {macOnly} {
- catch {file delete -force foo.file}
- close [open foo.file w]
- list [catch {file attributes foo.file -hidden 1} msg] $msg \
- [file attributes foo.file -hidden] [file delete -force foo.file]
-} {0 {} 1 {}}
-test macFCmd-3.5 {SetFileFinderAttributes - type} {macOnly} {
- catch {file delete -force foo.file}
- close [open foo.file w]
- list [catch {file attributes foo.file -type FOOO} msg] $msg \
- [file attributes foo.file -type] [file delete -force foo.file]
-} {0 {} FOOO {}}
-test macFCmd-3.6 {SetFileFinderAttributes - bad type} {macOnly} {
- catch {file delete -force foo.file}
- close [open foo.file w]
- list [catch {file attributes foo.file -type 0} msg] $msg \
- [file delete -force foo.file]
-} {1 {expected Macintosh OS type but got "0"} {}}
-test macFCmd-3.7 {SetFileFinderAttributes - directory} {macOnly} {
- catch {file delete -force foo.dir}
- file mkdir foo.dir
- list [catch {file attributes foo.dir -creator FOOO} msg] \
- $msg [file delete -force foo.dir]
-} {1 {cannot set -creator: "foo.dir" is a directory} {}}
-
-test macFCmd-4.1 {SetFileReadOnly - bad file} {macOnly} {
- catch {file delete -force foo.file}
- list [catch {file attributes foo.file -readonly 1} msg] $msg
-} {1 {could not read "foo.file": no such file or directory}}
-test macFCmd-4.2 {SetFileReadOnly - file not readonly} {macOnly} {
- catch {file delete -force foo.file}
- close [open foo.file w]
- list [catch {file attributes foo.file -readonly 0} msg] \
- $msg [file attributes foo.file -readonly] [file delete -force foo.file]
-} {0 {} 0 {}}
-test macFCmd-4.3 {SetFileReadOnly - file readonly} {macOnly} {
- catch {file delete -force foo.file}
- close [open foo.file w]
- list [catch {file attributes foo.file -readonly 1} msg] \
- $msg [file attributes foo.file -readonly] [file delete -force foo.file]
-} {0 {} 1 {}}
-test macFCmd-4.4 {SetFileReadOnly - directory not readonly} \
- {macOnly fileSharing} {
- catch {file delete -force foo.dir}
- file mkdir foo.dir
- list [catch {file attributes foo.dir -readonly 0} msg] \
- $msg [file attributes foo.dir -readonly] [file delete -force foo.dir]
-} {0 {} 0 {}}
-test macFCmd-4.5 {SetFileReadOnly - directory not readonly} \
- {macOnly notFileSharing} {
- catch {file delete -force foo.dir}
- file mkdir foo.dir
- list [catch {file attributes foo.dir -readonly 0} msg] $msg \
- [file delete -force foo.dir]
-} {1 {cannot set a directory to read-only when File Sharing is turned off} {}}
-test macFCmd-4.6 {SetFileReadOnly - directory readonly} {macOnly fileSharing} {
- catch {file delete -force foo.dir}
- file mkdir foo.dir
- list [catch {file attributes foo.dir -readonly 1} msg] $msg \
- [file attributes foo.dir -readonly] [file delete -force foo.dir]
-} {0 {} 1 {}}
-test macFCmd-4.7 {SetFileReadOnly - directory readonly} {macOnly notFileSharing} {
- catch {file delete -force foo.dir}
- file mkdir foo.dir
- list [catch {file attributes foo.dir -readonly 1} msg] $msg \
- [file delete -force foo.dir]
-} {1 {cannot set a directory to read-only when File Sharing is turned off} {}}
-
-# cleanup
-cd $oldcwd
-::tcltest::cleanupTests
-return
diff --git a/tests/macOSXFCmd.test b/tests/macOSXFCmd.test
new file mode 100644
index 0000000..071f11b
--- /dev/null
+++ b/tests/macOSXFCmd.test
@@ -0,0 +1,181 @@
+# This file tests the tclMacOSXFCmd.c file.
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands. Sourcing this file into Tcl runs the tests and
+# generates output for errors. No output means no errors were found.
+#
+# Copyright (c) 2003 Tcl Core Team.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+if {[lsearch [namespace children] ::tcltest] == -1} {
+ package require tcltest
+ namespace import -force ::tcltest::*
+}
+
+# These tests really need to be run from a writable directory, which
+# it is assumed [temporaryDirectory] is.
+set oldcwd [pwd]
+cd [temporaryDirectory]
+
+# check whether macosx file attributes are supported
+testConstraint macosxFileAttr 0
+if {[testConstraint unix] && $tcl_platform(os) eq "Darwin"} {
+ catch {file delete -force -- foo.test}
+ close [open foo.test w]
+ catch {
+ file attributes foo.test -creator
+ testConstraint macosxFileAttr 1
+ }
+ file delete -force -- foo.test
+}
+
+test macOSXFCmd-1.1 {MacOSXGetFileAttribute - file not found} {macosxFileAttr notRoot} {
+ catch {file delete -force -- foo.test}
+ list [catch {file attributes foo.test -creator} msg] $msg
+} {1 {could not read "foo.test": no such file or directory}}
+test macOSXFCmd-1.2 {MacOSXGetFileAttribute - creator} {macosxFileAttr notRoot} {
+ catch {file delete -force -- foo.test}
+ close [open foo.test w]
+ list [catch {file attributes foo.test -creator} msg] $msg \
+ [file delete -force -- foo.test]
+} {0 {} {}}
+test macOSXFCmd-1.3 {MacOSXGetFileAttribute - type} {macosxFileAttr notRoot} {
+ catch {file delete -force -- foo.test}
+ close [open foo.test w]
+ list [catch {file attributes foo.test -type} msg] $msg \
+ [file delete -force -- foo.test]
+} {0 {} {}}
+test macOSXFCmd-1.4 {MacOSXGetFileAttribute - hidden} {macosxFileAttr notRoot} {
+ catch {file delete -force -- foo.test}
+ close [open foo.test w]
+ list [catch {file attributes foo.test -hidden} msg] $msg \
+ [file delete -force -- foo.test]
+} {0 0 {}}
+test macOSXFCmd-1.5 {MacOSXGetFileAttribute - rsrclength} {macosxFileAttr notRoot} {
+ catch {file delete -force -- foo.test}
+ close [open foo.test w]
+ list [catch {file attributes foo.test -rsrclength} msg] $msg \
+ [file delete -force -- foo.test]
+} {0 0 {}}
+
+test macOSXFCmd-2.1 {MacOSXSetFileAttribute - file not found} {macosxFileAttr notRoot} {
+ catch {file delete -force -- foo.test}
+ list [catch {file attributes foo.test -creator FOOC} msg] $msg
+} {1 {could not read "foo.test": no such file or directory}}
+test macOSXFCmd-2.2 {MacOSXSetFileAttribute - creator} {macosxFileAttr notRoot} {
+ catch {file delete -force -- foo.test}
+ close [open foo.test w]
+ list [catch {file attributes foo.test -creator FOOC} msg] $msg \
+ [catch {file attributes foo.test -creator} msg] $msg \
+ [file delete -force -- foo.test]
+} {0 {} 0 FOOC {}}
+test macOSXFCmd-2.3 {MacOSXSetFileAttribute - empty creator} {macosxFileAttr notRoot} {
+ catch {file delete -force -- foo.test}
+ close [open foo.test w]
+ list [catch {file attributes foo.test -creator {}} msg] $msg \
+ [catch {file attributes foo.test -creator} msg] $msg \
+ [file delete -force -- foo.test]
+} {0 {} 0 {} {}}
+test macOSXFCmd-2.4 {MacOSXSetFileAttribute - type} {macosxFileAttr notRoot} {
+ catch {file delete -force -- foo.test}
+ close [open foo.test w]
+ list [catch {file attributes foo.test -type FOOT} msg] $msg \
+ [catch {file attributes foo.test -type} msg] $msg \
+ [file delete -force -- foo.test]
+} {0 {} 0 FOOT {}}
+test macOSXFCmd-2.5 {MacOSXSetFileAttribute - empty type} {macosxFileAttr notRoot} {
+ catch {file delete -force -- foo.test}
+ close [open foo.test w]
+ list [catch {file attributes foo.test -type {}} msg] $msg \
+ [catch {file attributes foo.test -type} msg] $msg \
+ [file delete -force -- foo.test]
+} {0 {} 0 {} {}}
+test macOSXFCmd-2.6 {MacOSXSetFileAttribute - hidden} {macosxFileAttr notRoot} {
+ catch {file delete -force -- foo.test}
+ close [open foo.test w]
+ list [catch {file attributes foo.test -hidden 1} msg] $msg \
+ [catch {file attributes foo.test -hidden} msg] $msg \
+ [file delete -force -- foo.test]
+} {0 {} 0 1 {}}
+test macOSXFCmd-2.7 {MacOSXSetFileAttribute - rsrclength} {macosxFileAttr notRoot} {
+ catch {file delete -force -- foo.test}
+ close [open foo.test w]
+ catch {
+ set f [open foo.test/..namedfork/rsrc w]
+ fconfigure $f -translation lf -eofchar {}
+ puts -nonewline $f "foo"
+ close $f
+ }
+ list [catch {file attributes foo.test -rsrclength} msg] $msg \
+ [catch {file attributes foo.test -rsrclength 0} msg] $msg \
+ [catch {file attributes foo.test -rsrclength} msg] $msg \
+ [file delete -force -- foo.test]
+} {0 3 0 {} 0 0 {}}
+
+test macOSXFCmd-3.1 {MacOSXCopyFileAttributes} {macosxFileAttr notRoot} {
+ catch {file delete -force -- foo.test}
+ catch {file delete -force -- bar.test}
+ close [open foo.test w]
+ catch {
+ file attributes foo.test -creator FOOC -type FOOT -hidden 1
+ set f [open foo.test/..namedfork/rsrc w]
+ fconfigure $f -translation lf -eofchar {}
+ puts -nonewline $f "foo"
+ close $f
+ file copy foo.test bar.test
+ }
+ list [catch {file attributes bar.test -creator} msg] $msg \
+ [catch {file attributes bar.test -type} msg] $msg \
+ [catch {file attributes bar.test -hidden} msg] $msg \
+ [catch {file attributes bar.test -rsrclength} msg] $msg \
+ [file delete -force -- foo.test bar.test]
+} {0 FOOC 0 FOOT 0 1 0 3 {}}
+
+test macOSXFCmd-4.1 {TclMacOSXMatchType} {macosxFileAttr notRoot} {
+ file mkdir globtest
+ cd globtest
+ foreach f {bar baz foo inv inw .nv reg} {
+ catch {file delete -force -- $f.test}
+ close [open $f.test w]
+ }
+ catch {file delete -force -- dir.test}
+ file mkdir dir.test
+ catch {
+ file attributes bar.test -type FOOT
+ file attributes baz.test -creator FOOC -type FOOT
+ file attributes foo.test -creator FOOC
+ file attributes inv.test -hidden 1
+ file attributes inw.test -hidden 1 -type FOOT
+ file attributes dir.test -hidden 1
+ }
+ set res [list \
+ [catch {glob *.test} msg] $msg \
+ [catch {glob -types FOOT *.test} msg] $msg \
+ [catch {glob -types {{macintosh type FOOT}} *.test} msg] $msg \
+ [catch {glob -types FOOTT *.test} msg] $msg \
+ [catch {glob -types {{macintosh type FOOTT}} *.test} msg] $msg \
+ [catch {glob -types {{macintosh type {}}} *.test} msg] $msg \
+ [catch {glob -types {{macintosh creator FOOC}} *.test} msg] $msg \
+ [catch {glob -types {{macintosh creator FOOC} {macintosh type FOOT}} *.test} msg] $msg \
+ [catch {glob -types hidden *.test} msg] $msg \
+ [catch {glob -types {hidden FOOT} *.test} msg] $msg \
+ ]
+ cd ..
+ file delete -force globtest
+ set res
+} [list \
+ 0 {bar.test baz.test dir.test foo.test inv.test inw.test reg.test} \
+ 0 {bar.test baz.test inw.test} 0 {bar.test baz.test inw.test} \
+ 1 {bad argument to "-types": FOOTT} \
+ 1 {expected Macintosh OS type but got "FOOTT": } \
+ 0 {foo.test inv.test reg.test} 0 {baz.test foo.test} \
+ 0 baz.test 0 {.nv.test dir.test inv.test inw.test} \
+ 0 inw.test
+]
+
+# cleanup
+cd $oldcwd
+::tcltest::cleanupTests
+return
diff --git a/tests/macOSXLoad.test b/tests/macOSXLoad.test
new file mode 100644
index 0000000..12c77e0
--- /dev/null
+++ b/tests/macOSXLoad.test
@@ -0,0 +1,33 @@
+# Commands covered: load unload
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands. Sourcing this file into Tcl runs the tests and
+# generates output for errors. No output means no errors were found.
+#
+# Copyright (c) 1995 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.
+
+if {[lsearch [namespace children] ::tcltest] == -1} {
+ package require tcltest 2
+ namespace import -force ::tcltest::*
+}
+set oldTSF $::tcltest::testSingleFile
+set ::tcltest::testSingleFile false
+
+if {[testConstraint unix] && $tcl_platform(os) eq "Darwin" &&
+ ![string match *pkga* [info loaded]]} {
+ # On Darwin, test .bundle (un)loading in addition to .dylib
+ set ext .bundle
+ source [file join [file dirname [info script]] load.test]
+ set ext .bundle
+ source [file join [file dirname [info script]] unload.test]
+ unset -nocomplain ext
+}
+
+set ::tcltest::testSingleFile $oldTSF
+unset oldTSF
+::tcltest::cleanupTests
+return
diff --git a/tests/main.test b/tests/main.test
index 40c0453..cdd3b17 100644
--- a/tests/main.test
+++ b/tests/main.test
@@ -6,15 +6,7 @@ if {[catch {package require tcltest 2.0.2}]} {
}
namespace eval ::tcl::test::main {
-
- namespace import ::tcltest::test
- namespace import ::tcltest::testConstraint
- namespace import ::tcltest::interpreter
- namespace import ::tcltest::cleanupTests
- namespace import ::tcltest::makeFile
- namespace import ::tcltest::removeFile
- namespace import ::tcltest::temporaryDirectory
- namespace import ::tcltest::workingDirectory
+ namespace import ::tcltest::*
# Is [exec] defined?
testConstraint exec [llength [info commands exec]]
@@ -137,6 +129,72 @@ namespace eval ::tcl::test::main {
} -result [list [list [encoding convertfrom [encoding system] \
[encoding convertto [encoding system] \u20ac]]] {} 0]\n
+ test Tcl_Main-1.7 {
+ Tcl_Main: startup script - -encoding option
+ } -constraints {
+ stdio
+ } -setup {
+ set script [makeFile {} script]
+ file delete $script
+ set f [open $script w]
+ fconfigure $f -encoding utf-8
+ puts $f {puts [list $argv0 $argv $tcl_interactive]}
+ puts -nonewline $f {puts [string equal \u20ac }
+ puts $f "\u20ac]"
+ close $f
+ catch {set f [open "|[list [interpreter] -encoding utf-8 script]" r]}
+ } -body {
+ read $f
+ } -cleanup {
+ close $f
+ removeFile script
+ } -result [list script {} 0]\n1\n
+
+ test Tcl_Main-1.8 {
+ Tcl_Main: startup script - -encoding option - mismatched encodings
+ } -constraints {
+ stdio
+ } -setup {
+ set script [makeFile {} script]
+ file delete $script
+ set f [open $script w]
+ fconfigure $f -encoding utf-8
+ puts $f {puts [list $argv0 $argv $tcl_interactive]}
+ puts -nonewline $f {puts [string equal \u20ac }
+ puts $f "\u20ac]"
+ close $f
+ catch {set f [open "|[list [interpreter] -encoding ascii script]" r]}
+ } -body {
+ read $f
+ } -cleanup {
+ close $f
+ removeFile script
+ } -result [list script {} 0]\n0\n
+
+ test Tcl_Main-1.9 {
+ Tcl_Main: startup script - -encoding option - no abbrevation
+ } -constraints {
+ stdio
+ } -setup {
+ set script [makeFile {} script]
+ file delete $script
+ set f [open $script w]
+ fconfigure $f -encoding utf-8
+ puts $f {puts [list $argv0 $argv $tcl_interactive]}
+ puts -nonewline $f {puts [string equal \u20ac }
+ puts $f "\u20ac]"
+ close $f
+ catch {set f [open "|[list [interpreter] -enc utf-8 script]" r+]}
+ } -body {
+ type $f {
+ puts $argv
+ }
+ list [catch {gets $f} line] $line
+ } -cleanup {
+ close $f
+ removeFile script
+ } -result {0 {-enc utf-8 script}}
+
# Tests Tcl_Main-2.*: application-initialization procedure
test Tcl_Main-2.1 {
@@ -498,24 +556,24 @@ namespace eval ::tcl::test::main {
\nExit MainLoop\nIn exit\neven 0\n"
test Tcl_Main-4.5 {
- Tcl_Main: Bug 1481986
+ Tcl_Main: Bug 1481986
} -constraints {
- exec Tcltest
+ exec Tcltest
} -setup {
- set rc [makeFile {
- testsetmainloop
- after 0 {puts "Event callback"}
- } rc]
+ set rc [makeFile {
+ testsetmainloop
+ after 0 {puts "Event callback"}
+ } rc]
} -body {
- set f [open "|[list [interpreter] -appinitprocsetrcfile $rc]" w+]
- after 1000
- type $f {puts {Interactive output}
- exit
- }
- read $f
+ set f [open "|[list [interpreter] -appinitprocsetrcfile $rc]" w+]
+ after 1000
+ type $f {puts {Interactive output}
+ exit
+ }
+ read $f
} -cleanup {
- catch {close $f}
- removeFile rc
+ catch {close $f}
+ removeFile rc
} -result "Event callback\nInteractive output\n"
# Tests Tcl_Main-5.*: interactive operations
@@ -568,8 +626,7 @@ namespace eval ::tcl::test::main {
after cancel $id
set wait
} -cleanup {
- if {[string equal timeout $wait]
- && [string equal unix $::tcl_platform(platform)]} {
+ if {[string equal timeout $wait] && [testConstraint unix]} {
exec kill [pid $f]
}
close $f
@@ -592,8 +649,7 @@ namespace eval ::tcl::test::main {
after cancel $id
set wait
} -cleanup {
- if {[string equal timeout $wait]
- && [string equal unix $::tcl_platform(platform)]} {
+ if {[string equal timeout $wait] && [testConstraint unix]} {
exec kill [pid $f]
}
close $f
@@ -761,6 +817,20 @@ namespace eval ::tcl::test::main {
file delete result
} -result "Exit MainLoop\nIn exit\neven 0\n"
+ test Tcl_Main-5.13 {
+ Bug 1775878
+ } -constraints {
+ exec
+ } -setup {
+ catch {set f [open "|[list [interpreter]]" w+]}
+ } -body {
+ type $f "puts \\"
+ type $f return
+ list [catch {gets $f} line] $line
+ } -cleanup {
+ close $f
+ } -result [list 0 return]
+
# Tests Tcl_Main-6.*: interactive operations with prompts
test Tcl_Main-6.1 {
@@ -1144,6 +1214,21 @@ namespace eval ::tcl::test::main {
file delete result
} -result "1\nExit MainLoop\n"
+ test Tcl_Main-8.13 {
+ Bug 1775878
+ } -constraints {
+ exec Tcltest
+ } -setup {
+ catch {set f [open "|[list [interpreter]]" w+]}
+ } -body {
+ exec [interpreter] << "testsetmainloop\nputs \\\npwd\ntestexitmainloop" >& result
+ set f [open result]
+ read $f
+ } -cleanup {
+ close $f
+ file delete result
+ } -result "pwd\nExit MainLoop\n"
+
# Tests Tcl_Main-9.*: Prompt operations
test Tcl_Main-9.1 {
diff --git a/tests/mathop.test b/tests/mathop.test
new file mode 100644
index 0000000..61a106e
--- /dev/null
+++ b/tests/mathop.test
@@ -0,0 +1,1338 @@
+# Commands covered: ::tcl::mathop::...
+#
+# This file contains a collection of tests for one or more of the Tcl built-in
+# commands. Sourcing this file into Tcl runs the tests and generates output
+# for errors. No output means no errors were found.
+#
+# Copyright (c) 2006 Donal K. Fellows
+# Copyright (c) 2006 Peter Spjuth
+#
+# See the file "license.terms" for information on usage and redistribution of
+# this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+if {[lsearch [namespace children] ::tcltest] == -1} {
+ package require tcltest 2.1
+ namespace import -force ::tcltest::*
+}
+
+# A namespace to test that operators are exported and that they
+# work when imported
+namespace eval ::testmathop2 {
+ namespace import ::tcl::mathop::*
+}
+
+# Helper to test math ops.
+# Test different invokation variants and see that they do the same thing.
+# Byte compiled / non byte compiled version
+# Shared / unshared arguments
+# Original / imported
+proc TestOp {op args} {
+ set results {}
+
+ # Non byte compiled version, shared args
+ if {[catch {::tcl::mathop::$op {*}$args} res]} {
+ append res " $::errorCode"
+ }
+ lappend results $res
+
+ # Non byte compiled version, unshared args
+ set cmd ::tcl::mathop::\$op
+ foreach arg $args {
+ append cmd " \[format %s [list $arg]\]"
+ }
+ if {[catch $cmd res]} {
+ append res " $::errorCode"
+ }
+ lappend results $res
+
+ # Non byte compiled imported
+ if {[catch {::testmathop2::$op {*}$args} res]} {
+ append res " $::errorCode"
+ }
+ lappend results [string map {testmathop2 tcl::mathop} $res]
+
+ # BC version
+ set argList1 {}
+ set argList2 {}
+ set argList3 {}
+ for {set t 0} {$t < [llength $args]} {incr t} {
+ lappend argList1 a$t
+ lappend argList2 \$a$t
+ lappend argList3 "\[format %s \$a$t\]"
+ }
+ # Shared args
+ proc _TestOp $argList1 "::tcl::mathop::$op [join $argList2]"
+ # Unshared args
+ proc _TestOp2 $argList1 "::tcl::mathop::$op [join $argList3]"
+ # Imported
+ proc _TestOp3 $argList1 "::testmathop2::$op [join $argList2]"
+
+ set ::tcl_traceCompile 0 ;# Set to 2 to help with debug
+ if {[catch {_TestOp {*}$args} res]} {
+ append res " $::errorCode"
+ }
+ set ::tcl_traceCompile 0
+ lappend results $res
+
+ if {[catch {_TestOp2 {*}$args} res]} {
+ append res " $::errorCode"
+ }
+ lappend results $res
+
+ if {[catch {_TestOp3 {*}$args} res]} {
+ append res " $::errorCode"
+ }
+ lappend results [string map {testmathop2 tcl::mathop} $res]
+
+ # Check that they do the same
+ set len [llength $results]
+ for {set i 0} {$i < ($len - 1)} {incr i} {
+ set res1 [lindex $results $i]
+ set res2 [lindex $results $i+1]
+ if {$res1 ne $res2} {
+ return "$i:($res1 != $res2)"
+ }
+ }
+ return [lindex $results 0]
+}
+
+# start of tests
+
+namespace eval ::testmathop {
+ namespace path ::tcl::mathop
+ variable op ;# stop surprises!
+
+ test mathop-1.1 {compiled +} { + } 0
+ test mathop-1.2 {compiled +} { + 1 } 1
+ test mathop-1.3 {compiled +} { + 1 2 } 3
+ test mathop-1.4 {compiled +} { + 1 2 3 } 6
+ test mathop-1.5 {compiled +} { + 1.0 2 3 } 6.0
+ test mathop-1.6 {compiled +} { + 1 2 3.0 } 6.0
+ test mathop-1.7 {compiled +} { + 100000000000 2 3 } 100000000005
+ test mathop-1.8 {compiled +} { + 1 2 300000000000 } 300000000003
+ test mathop-1.9 {compiled +} { + 1000000000000000000000 2 3 } 1000000000000000000005
+ test mathop-1.10 {compiled +} { + 1 2 3000000000000000000000 } 3000000000000000000003
+ test mathop-1.11 {compiled +: errors} -returnCodes error -body {
+ + x 0
+ } -result {can't use non-numeric string as operand of "+"}
+ test mathop-1.12 {compiled +: errors} -returnCodes error -body {
+ + nan 0
+ } -result {can't use non-numeric floating-point value as operand of "+"}
+ test mathop-1.13 {compiled +: errors} -returnCodes error -body {
+ + 0 x
+ } -result {can't use non-numeric string as operand of "+"}
+ test mathop-1.14 {compiled +: errors} -returnCodes error -body {
+ + 0 nan
+ } -result {can't use non-numeric floating-point value as operand of "+"}
+ test mathop-1.15 {compiled +: errors} -returnCodes error -body {
+ + 0o8 0
+ } -result {can't use invalid octal number as operand of "+"}
+ test mathop-1.16 {compiled +: errors} -returnCodes error -body {
+ + 0 0o8
+ } -result {can't use invalid octal number as operand of "+"}
+ test mathop-1.17 {compiled +: errors} -returnCodes error -body {
+ + 0 [error expectedError]
+ } -result expectedError
+ test mathop-1.18 {compiled +: argument processing order} -body {
+ # Bytecode compilation known hard for 3+ arguments
+ list [catch {
+ + [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
+ } msg] $msg $x
+ } -result {1 expected 2}
+ set op +
+ test mathop-1.19 {interpreted +} { $op } 0
+ test mathop-1.20 {interpreted +} { $op 1 } 1
+ test mathop-1.21 {interpreted +} { $op 1 2 } 3
+ test mathop-1.22 {interpreted +} { $op 1 2 3 } 6
+ test mathop-1.23 {interpreted +} { $op 1.0 2 3 } 6.0
+ test mathop-1.24 {interpreted +} { $op 1 2 3.0 } 6.0
+ test mathop-1.25 {interpreted +} { $op 100000000000 2 3 } 100000000005
+ test mathop-1.26 {interpreted +} { $op 1 2 300000000000 } 300000000003
+ test mathop-1.27 {interpreted +} { $op 1000000000000000000000 2 3 } 1000000000000000000005
+ test mathop-1.28 {interpreted +} { $op 1 2 3000000000000000000000 } 3000000000000000000003
+ test mathop-1.29 {interpreted +: errors} -returnCodes error -body {
+ $op x 0
+ } -result {can't use non-numeric string as operand of "+"}
+ test mathop-1.30 {interpreted +: errors} -returnCodes error -body {
+ $op nan 0
+ } -result {can't use non-numeric floating-point value as operand of "+"}
+ test mathop-1.31 {interpreted +: errors} -returnCodes error -body {
+ $op 0 x
+ } -result {can't use non-numeric string as operand of "+"}
+ test mathop-1.32 {interpreted +: errors} -returnCodes error -body {
+ $op 0 nan
+ } -result {can't use non-numeric floating-point value as operand of "+"}
+ test mathop-1.33 {interpreted +: errors} -returnCodes error -body {
+ $op 0o8 0
+ } -result {can't use invalid octal number as operand of "+"}
+ test mathop-1.34 {interpreted +: errors} -returnCodes error -body {
+ $op 0 0o8
+ } -result {can't use invalid octal number as operand of "+"}
+ test mathop-1.35 {interpreted +: errors} -returnCodes error -body {
+ $op 0 [error expectedError]
+ } -result expectedError
+ test mathop-1.36 {interpreted +: argument processing order} -body {
+ list [catch {
+ $op [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
+ } msg] $msg $x
+ } -result {1 expected 2}
+
+ test mathop-2.1 {compiled *} { * } 1
+ test mathop-2.2 {compiled *} { * 2 } 2
+ test mathop-2.3 {compiled *} { * 2 3 } 6
+ test mathop-2.4 {compiled *} { * 2 3 4 } 24
+ test mathop-2.5 {compiled *} { * 1.0 2 3 } 6.0
+ test mathop-2.6 {compiled *} { * 1 2 3.0 } 6.0
+ test mathop-2.7 {compiled *} { * 100000000000 2 3 } 600000000000
+ test mathop-2.8 {compiled *} { * 1 2 300000000000 } 600000000000
+ test mathop-2.9 {compiled *} { * 1000000000000000000000 2 3 } 6000000000000000000000
+ test mathop-2.10 {compiled *} { * 1 2 3000000000000000000000 } 6000000000000000000000
+ test mathop-2.11 {compiled *: errors} -returnCodes error -body {
+ * x 0
+ } -result {can't use non-numeric string as operand of "*"}
+ test mathop-2.12 {compiled *: errors} -returnCodes error -body {
+ * nan 0
+ } -result {can't use non-numeric floating-point value as operand of "*"}
+ test mathop-2.13 {compiled *: errors} -returnCodes error -body {
+ * 0 x
+ } -result {can't use non-numeric string as operand of "*"}
+ test mathop-2.14 {compiled *: errors} -returnCodes error -body {
+ * 0 nan
+ } -result {can't use non-numeric floating-point value as operand of "*"}
+ test mathop-2.15 {compiled *: errors} -returnCodes error -body {
+ * 0o8 0
+ } -result {can't use invalid octal number as operand of "*"}
+ test mathop-2.16 {compiled *: errors} -returnCodes error -body {
+ * 0 0o8
+ } -result {can't use invalid octal number as operand of "*"}
+ test mathop-2.17 {compiled *: errors} -returnCodes error -body {
+ * 0 [error expectedError]
+ } -result expectedError
+ test mathop-2.18 {compiled *: argument processing order} -body {
+ # Bytecode compilation known hard for 3+ arguments
+ list [catch {
+ * [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
+ } msg] $msg $x
+ } -result {1 expected 2}
+ set op *
+ test mathop-2.19 {interpreted *} { $op } 1
+ test mathop-2.20 {interpreted *} { $op 2 } 2
+ test mathop-2.21 {interpreted *} { $op 2 3 } 6
+ test mathop-2.22 {interpreted *} { $op 2 3 4 } 24
+ test mathop-2.23 {interpreted *} { $op 1.0 2 3 } 6.0
+ test mathop-2.24 {interpreted *} { $op 1 2 3.0 } 6.0
+ test mathop-2.25 {interpreted *} { $op 100000000000 2 3 } 600000000000
+ test mathop-2.26 {interpreted *} { $op 1 2 300000000000 } 600000000000
+ test mathop-2.27 {interpreted *} { $op 1000000000000000000000 2 3 } 6000000000000000000000
+ test mathop-2.28 {interpreted *} { $op 1 2 3000000000000000000000 } 6000000000000000000000
+ test mathop-2.29 {interpreted *: errors} -returnCodes error -body {
+ $op x 0
+ } -result {can't use non-numeric string as operand of "*"}
+ test mathop-2.30 {interpreted *: errors} -returnCodes error -body {
+ $op nan 0
+ } -result {can't use non-numeric floating-point value as operand of "*"}
+ test mathop-2.31 {interpreted *: errors} -returnCodes error -body {
+ $op 0 x
+ } -result {can't use non-numeric string as operand of "*"}
+ test mathop-2.32 {interpreted *: errors} -returnCodes error -body {
+ $op 0 nan
+ } -result {can't use non-numeric floating-point value as operand of "*"}
+ test mathop-2.33 {interpreted *: errors} -returnCodes error -body {
+ $op 0o8 0
+ } -result {can't use invalid octal number as operand of "*"}
+ test mathop-2.34 {interpreted *: errors} -returnCodes error -body {
+ $op 0 0o8
+ } -result {can't use invalid octal number as operand of "*"}
+ test mathop-2.35 {interpreted *: errors} -returnCodes error -body {
+ $op 0 [error expectedError]
+ } -result expectedError
+ test mathop-2.36 {interpreted *: argument processing order} -body {
+ list [catch {
+ $op [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
+ } msg] $msg $x
+ } -result {1 expected 2}
+
+ test mathop-3.1 {compiled !} {! 0} 1
+ test mathop-3.2 {compiled !} {! 1} 0
+ test mathop-3.3 {compiled !} {! false} 1
+ test mathop-3.4 {compiled !} {! true} 0
+ test mathop-3.5 {compiled !} {! 0.0} 1
+ test mathop-3.6 {compiled !} {! 10000000000} 0
+ test mathop-3.7 {compiled !} {! 10000000000000000000000000} 0
+ test mathop-3.8 {compiled !: errors} -body {
+ ! foobar
+ } -returnCodes error -result {can't use non-numeric string as operand of "!"}
+ test mathop-3.9 {compiled !: errors} -body {
+ ! 0 0
+ } -returnCodes error -result "wrong # args: should be \"! boolean\""
+ test mathop-3.10 {compiled !: errors} -body {
+ !
+ } -returnCodes error -result "wrong # args: should be \"! boolean\""
+ set op !
+ test mathop-3.11 {interpreted !} {$op 0} 1
+ test mathop-3.12 {interpreted !} {$op 1} 0
+ test mathop-3.13 {interpreted !} {$op false} 1
+ test mathop-3.14 {interpreted !} {$op true} 0
+ test mathop-3.15 {interpreted !} {$op 0.0} 1
+ test mathop-3.16 {interpreted !} {$op 10000000000} 0
+ test mathop-3.17 {interpreted !} {$op 10000000000000000000000000} 0
+ test mathop-3.18 {interpreted !: errors} -body {
+ $op foobar
+ } -returnCodes error -result {can't use non-numeric string as operand of "!"}
+ test mathop-3.19 {interpreted !: errors} -body {
+ $op 0 0
+ } -returnCodes error -result "wrong # args: should be \"! boolean\""
+ test mathop-3.20 {interpreted !: errors} -body {
+ $op
+ } -returnCodes error -result "wrong # args: should be \"! boolean\""
+ test mathop-3.21 {compiled !: error} -returnCodes error -body {
+ ! NaN
+ } -result {can't use non-numeric floating-point value as operand of "!"}
+ test mathop-3.22 {interpreted !: error} -returnCodes error -body {
+ $op NaN
+ } -result {can't use non-numeric floating-point value as operand of "!"}
+
+ test mathop-4.1 {compiled ~} {~ 0} -1
+ test mathop-4.2 {compiled ~} {~ 1} -2
+ test mathop-4.3 {compiled ~} {~ 31} -32
+ test mathop-4.4 {compiled ~} {~ -127} 126
+ test mathop-4.5 {compiled ~} {~ -0} -1
+ test mathop-4.6 {compiled ~} {~ 10000000000} -10000000001
+ test mathop-4.7 {compiled ~} {~ 10000000000000000000000000} -10000000000000000000000001
+ test mathop-4.8 {compiled ~: errors} -body {
+ ~ foobar
+ } -returnCodes error -result {can't use non-numeric string as operand of "~"}
+ test mathop-4.9 {compiled ~: errors} -body {
+ ~ 0 0
+ } -returnCodes error -result "wrong # args: should be \"~ integer\""
+ test mathop-4.10 {compiled ~: errors} -body {
+ ~
+ } -returnCodes error -result "wrong # args: should be \"~ integer\""
+ test mathop-4.11 {compiled ~: errors} -returnCodes error -body {
+ ~ 0.0
+ } -result {can't use floating-point value as operand of "~"}
+ test mathop-4.12 {compiled ~: errors} -returnCodes error -body {
+ ~ NaN
+ } -result {can't use non-numeric floating-point value as operand of "~"}
+ set op ~
+ test mathop-4.13 {interpreted ~} {$op 0} -1
+ test mathop-4.14 {interpreted ~} {$op 1} -2
+ test mathop-4.15 {interpreted ~} {$op 31} -32
+ test mathop-4.16 {interpreted ~} {$op -127} 126
+ test mathop-4.17 {interpreted ~} {$op -0} -1
+ test mathop-4.18 {interpreted ~} {$op 10000000000} -10000000001
+ test mathop-4.19 {interpreted ~} {$op 10000000000000000000000000} -10000000000000000000000001
+ test mathop-4.20 {interpreted ~: errors} -body {
+ $op foobar
+ } -returnCodes error -result {can't use non-numeric string as operand of "~"}
+ test mathop-4.21 {interpreted ~: errors} -body {
+ $op 0 0
+ } -returnCodes error -result "wrong # args: should be \"~ integer\""
+ test mathop-4.22 {interpreted ~: errors} -body {
+ $op
+ } -returnCodes error -result "wrong # args: should be \"~ integer\""
+ test mathop-4.23 {interpreted ~: errors} -returnCodes error -body {
+ $op 0.0
+ } -result {can't use floating-point value as operand of "~"}
+ test mathop-4.24 {interpreted ~: errors} -returnCodes error -body {
+ $op NaN
+ } -result {can't use non-numeric floating-point value as operand of "~"}
+
+ test mathop-5.1 {compiled eq} {eq {} a} 0
+ test mathop-5.2 {compiled eq} {eq a a} 1
+ test mathop-5.3 {compiled eq} {eq a {}} 0
+ test mathop-5.4 {compiled eq} {eq a b} 0
+ test mathop-5.5 {compiled eq} { eq } 1
+ test mathop-5.6 {compiled eq} {eq a} 1
+ test mathop-5.7 {compiled eq} {eq a a a} 1
+ test mathop-5.8 {compiled eq} {eq a a b} 0
+ test mathop-5.9 {compiled eq} -body {
+ eq a b [error foobar]
+ } -returnCodes error -result foobar
+ test mathop-5.10 {compiled eq} {eq NaN Na NaN} 0
+ set op eq
+ test mathop-5.11 {interpreted eq} {$op {} a} 0
+ test mathop-5.12 {interpreted eq} {$op a a} 1
+ test mathop-5.13 {interpreted eq} {$op a {}} 0
+ test mathop-5.14 {interpreted eq} {$op a b} 0
+ test mathop-5.15 {interpreted eq} { $op } 1
+ test mathop-5.16 {interpreted eq} {$op a} 1
+ test mathop-5.17 {interpreted eq} {$op a a a} 1
+ test mathop-5.18 {interpreted eq} {$op a a b} 0
+ test mathop-5.19 {interpreted eq} -body {
+ $op a b [error foobar]
+ } -returnCodes error -result foobar
+ test mathop-5.20 {interpreted eq} {$op NaN Na NaN} 0
+
+ variable big1 12135435435354435435342423948763867876
+ variable big2 2746237174783836746262564892918327847
+ variable wide1 12345678912345
+ variable wide2 87321847232215
+ variable small1 87345
+ variable small2 16753
+
+ test mathop-6.1 {compiled &} { & } -1
+ test mathop-6.2 {compiled &} { & 1 } 1
+ test mathop-6.3 {compiled &} { & 1 2 } 0
+ test mathop-6.4 {compiled &} { & 3 7 6 } 2
+ test mathop-6.5 {compiled &} -returnCodes error -body {
+ & 1.0 2 3
+ } -result {can't use floating-point value as operand of "&"}
+ test mathop-6.6 {compiled &} -returnCodes error -body {
+ & 1 2 3.0
+ } -result {can't use floating-point value as operand of "&"}
+ test mathop-6.7 {compiled &} { & 100000000002 18 -126 } 2
+ test mathop-6.8 {compiled &} { & 0xff 0o377 333333333333 } 85
+ test mathop-6.9 {compiled &} { & 1000000000000000000002 18 -126 } 2
+ test mathop-6.10 {compiled &} { & 0xff 0o377 3333333333333333333333 } 85
+ test mathop-6.11 {compiled &: errors} -returnCodes error -body {
+ & x 0
+ } -result {can't use non-numeric string as operand of "&"}
+ test mathop-6.12 {compiled &: errors} -returnCodes error -body {
+ & nan 0
+ } -result {can't use non-numeric floating-point value as operand of "&"}
+ test mathop-6.13 {compiled &: errors} -returnCodes error -body {
+ & 0 x
+ } -result {can't use non-numeric string as operand of "&"}
+ test mathop-6.14 {compiled &: errors} -returnCodes error -body {
+ & 0 nan
+ } -result {can't use non-numeric floating-point value as operand of "&"}
+ test mathop-6.15 {compiled &: errors} -returnCodes error -body {
+ & 0o8 0
+ } -result {can't use invalid octal number as operand of "&"}
+ test mathop-6.16 {compiled &: errors} -returnCodes error -body {
+ & 0 0o8
+ } -result {can't use invalid octal number as operand of "&"}
+ test mathop-6.17 {compiled &: errors} -returnCodes error -body {
+ & 0 [error expectedError]
+ } -result expectedError
+ test mathop-6.18 {compiled &: argument processing order} -body {
+ # Bytecode compilation known hard for 3+ arguments
+ list [catch {
+ & [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
+ } msg] $msg $x
+ } -result {1 expected 2}
+ set op &
+ test mathop-6.19 {interpreted &} { $op } -1
+ test mathop-6.20 {interpreted &} { $op 1 } 1
+ test mathop-6.21 {interpreted &} { $op 1 2 } 0
+ test mathop-6.22 {interpreted &} { $op 3 7 6 } 2
+ test mathop-6.23 {interpreted &} -returnCodes error -body {
+ $op 1.0 2 3
+ } -result {can't use floating-point value as operand of "&"}
+ test mathop-6.24 {interpreted &} -returnCodes error -body {
+ $op 1 2 3.0
+ } -result {can't use floating-point value as operand of "&"}
+ test mathop-6.25 {interpreted &} { $op 100000000002 18 -126 } 2
+ test mathop-6.26 {interpreted &} { $op 0xff 0o377 333333333333 } 85
+ test mathop-6.27 {interpreted &} { $op 1000000000000000000002 18 -126 } 2
+ test mathop-6.28 {interpreted &} { $op 0xff 0o377 3333333333333333333333 } 85
+ test mathop-6.29 {interpreted &: errors} -returnCodes error -body {
+ $op x 0
+ } -result {can't use non-numeric string as operand of "&"}
+ test mathop-6.30 {interpreted &: errors} -returnCodes error -body {
+ $op nan 0
+ } -result {can't use non-numeric floating-point value as operand of "&"}
+ test mathop-6.31 {interpreted &: errors} -returnCodes error -body {
+ $op 0 x
+ } -result {can't use non-numeric string as operand of "&"}
+ test mathop-6.32 {interpreted &: errors} -returnCodes error -body {
+ $op 0 nan
+ } -result {can't use non-numeric floating-point value as operand of "&"}
+ test mathop-6.33 {interpreted &: errors} -returnCodes error -body {
+ $op 0o8 0
+ } -result {can't use invalid octal number as operand of "&"}
+ test mathop-6.34 {interpreted &: errors} -returnCodes error -body {
+ $op 0 0o8
+ } -result {can't use invalid octal number as operand of "&"}
+ test mathop-6.35 {interpreted &: errors} -returnCodes error -body {
+ $op 0 [error expectedError]
+ } -result expectedError
+ test mathop-6.36 {interpreted &: argument processing order} -body {
+ list [catch {
+ $op [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
+ } msg] $msg $x
+ } -result {1 expected 2}
+ test mathop-6.37 {& and bignums} {
+ list [& $big1 $big2] [$op $big1 $big2]
+ } {712439449294653815890598856501796 712439449294653815890598856501796}
+ test mathop-6.38 {& and bignums} {
+ list [& $big1 $wide2] [$op $big1 $wide2]
+ } {78521450111684 78521450111684}
+ test mathop-6.39 {& and bignums} {
+ list [& $big1 $small2] [$op $big1 $small2]
+ } {96 96}
+ test mathop-6.40 {& and bignums} {
+ list [& $wide1 $big2] [$op $wide1 $big2]
+ } {2371422390785 2371422390785}
+ test mathop-6.41 {& and bignums} {
+ list [& $wide1 $wide2] [$op $wide1 $wide2]
+ } {12275881497169 12275881497169}
+ test mathop-6.42 {& and bignums} {
+ list [& $wide1 $small2] [$op $wide1 $small2]
+ } {16721 16721}
+ test mathop-6.43 {& and bignums} {
+ list [& $small1 $big2] [$op $small1 $big2]
+ } {33 33}
+ test mathop-6.44 {& and bignums} {
+ list [& $small1 $wide2] [$op $small1 $wide2]
+ } {87057 87057}
+ test mathop-6.45 {& and bignums} {
+ list [& $small1 $small2] [$op $small1 $small2]
+ } {16689 16689}
+
+ test mathop-7.1 {compiled |} { | } 0
+ test mathop-7.2 {compiled |} { | 1 } 1
+ test mathop-7.3 {compiled |} { | 1 2 } 3
+ test mathop-7.4 {compiled |} { | 3 7 6 } 7
+ test mathop-7.5 {compiled |} -returnCodes error -body {
+ | 1.0 2 3
+ } -result {can't use floating-point value as operand of "|"}
+ test mathop-7.6 {compiled |} -returnCodes error -body {
+ | 1 2 3.0
+ } -result {can't use floating-point value as operand of "|"}
+ test mathop-7.7 {compiled |} { | 100000000002 18 -126 } -110
+ test mathop-7.8 {compiled |} { | 0xff 0o377 333333333333 } 333333333503
+ test mathop-7.9 {compiled |} { | 1000000000000000000002 18 -126 } -110
+ test mathop-7.10 {compiled |} { | 0xff 0o377 3333333333333333333333 } 3333333333333333333503
+ test mathop-7.11 {compiled |: errors} -returnCodes error -body {
+ | x 0
+ } -result {can't use non-numeric string as operand of "|"}
+ test mathop-7.12 {compiled |: errors} -returnCodes error -body {
+ | nan 0
+ } -result {can't use non-numeric floating-point value as operand of "|"}
+ test mathop-7.13 {compiled |: errors} -returnCodes error -body {
+ | 0 x
+ } -result {can't use non-numeric string as operand of "|"}
+ test mathop-7.14 {compiled |: errors} -returnCodes error -body {
+ | 0 nan
+ } -result {can't use non-numeric floating-point value as operand of "|"}
+ test mathop-7.15 {compiled |: errors} -returnCodes error -body {
+ | 0o8 0
+ } -result {can't use invalid octal number as operand of "|"}
+ test mathop-7.16 {compiled |: errors} -returnCodes error -body {
+ | 0 0o8
+ } -result {can't use invalid octal number as operand of "|"}
+ test mathop-7.17 {compiled |: errors} -returnCodes error -body {
+ | 0 [error expectedError]
+ } -result expectedError
+ test mathop-7.18 {compiled |: argument processing order} -body {
+ # Bytecode compilation known hard for 3+ arguments
+ list [catch {
+ | [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
+ } msg] $msg $x
+ } -result {1 expected 2}
+ set op |
+ test mathop-7.19 {interpreted |} { $op } 0
+ test mathop-7.20 {interpreted |} { $op 1 } 1
+ test mathop-7.21 {interpreted |} { $op 1 2 } 3
+ test mathop-7.22 {interpreted |} { $op 3 7 6 } 7
+ test mathop-7.23 {interpreted |} -returnCodes error -body {
+ $op 1.0 2 3
+ } -result {can't use floating-point value as operand of "|"}
+ test mathop-7.24 {interpreted |} -returnCodes error -body {
+ $op 1 2 3.0
+ } -result {can't use floating-point value as operand of "|"}
+ test mathop-7.25 {interpreted |} { $op 100000000002 18 -126 } -110
+ test mathop-7.26 {interpreted |} { $op 0xff 0o377 333333333333 } 333333333503
+ test mathop-7.27 {interpreted |} { $op 1000000000000000000002 18 -126 } -110
+ test mathop-7.28 {interpreted |} { $op 0xff 0o377 3333333333333333333333 } 3333333333333333333503
+ test mathop-7.29 {interpreted |: errors} -returnCodes error -body {
+ $op x 0
+ } -result {can't use non-numeric string as operand of "|"}
+ test mathop-7.30 {interpreted |: errors} -returnCodes error -body {
+ $op nan 0
+ } -result {can't use non-numeric floating-point value as operand of "|"}
+ test mathop-7.31 {interpreted |: errors} -returnCodes error -body {
+ $op 0 x
+ } -result {can't use non-numeric string as operand of "|"}
+ test mathop-7.32 {interpreted |: errors} -returnCodes error -body {
+ $op 0 nan
+ } -result {can't use non-numeric floating-point value as operand of "|"}
+ test mathop-7.33 {interpreted |: errors} -returnCodes error -body {
+ $op 0o8 0
+ } -result {can't use invalid octal number as operand of "|"}
+ test mathop-7.34 {interpreted |: errors} -returnCodes error -body {
+ $op 0 0o8
+ } -result {can't use invalid octal number as operand of "|"}
+ test mathop-7.35 {interpreted |: errors} -returnCodes error -body {
+ $op 0 [error expectedError]
+ } -result expectedError
+ test mathop-7.36 {interpreted |: argument processing order} -body {
+ list [catch {
+ $op [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
+ } msg] $msg $x
+ } -result {1 expected 2}
+ test mathop-7.37 {| and bignums} {
+ list [| $big1 $big2] [$op $big1 $big2]
+ } {14880960170688977527789098242825693927 14880960170688977527789098242825693927}
+ test mathop-7.38 {| and bignums} {
+ list [| $big1 $wide2] [$op $big1 $wide2]
+ } {12135435435354435435342432749160988407 12135435435354435435342432749160988407}
+ test mathop-7.39 {| and bignums} {
+ list [| $big1 $small2] [$op $big1 $small2]
+ } {12135435435354435435342423948763884533 12135435435354435435342423948763884533}
+ test mathop-7.40 {| and bignums} {
+ list [| $wide1 $big2] [$op $wide1 $big2]
+ } {2746237174783836746262574867174849407 2746237174783836746262574867174849407}
+ test mathop-7.41 {| and bignums} {
+ list [| $wide1 $wide2] [$op $wide1 $wide2]
+ } {87391644647391 87391644647391}
+ test mathop-7.42 {| and bignums} {
+ list [| $wide1 $small2] [$op $wide1 $small2]
+ } {12345678912377 12345678912377}
+ test mathop-7.43 {| and bignums} {
+ list [| $small1 $big2] [$op $small1 $big2]
+ } {2746237174783836746262564892918415159 2746237174783836746262564892918415159}
+ test mathop-7.44 {| and bignums} {
+ list [| $small1 $wide2] [$op $small1 $wide2]
+ } {87321847232503 87321847232503}
+ test mathop-7.45 {| and bignums} {
+ list [| $small1 $small2] [$op $small1 $small2]
+ } {87409 87409}
+
+ test mathop-8.1 {compiled ^} { ^ } 0
+ test mathop-8.2 {compiled ^} { ^ 1 } 1
+ test mathop-8.3 {compiled ^} { ^ 1 2 } 3
+ test mathop-8.4 {compiled ^} { ^ 3 7 6 } 2
+ test mathop-8.5 {compiled ^} -returnCodes error -body {
+ ^ 1.0 2 3
+ } -result {can't use floating-point value as operand of "^"}
+ test mathop-8.6 {compiled ^} -returnCodes error -body {
+ ^ 1 2 3.0
+ } -result {can't use floating-point value as operand of "^"}
+ test mathop-8.7 {compiled ^} { ^ 100000000002 18 -126 } -100000000110
+ test mathop-8.8 {compiled ^} { ^ 0xff 0o377 333333333333 } 333333333333
+ test mathop-8.9 {compiled ^} { ^ 1000000000000000000002 18 -126 } -1000000000000000000110
+ test mathop-8.10 {compiled ^} { ^ 0xff 0o377 3333333333333333333333 } 3333333333333333333333
+ test mathop-8.11 {compiled ^: errors} -returnCodes error -body {
+ ^ x 0
+ } -result {can't use non-numeric string as operand of "^"}
+ test mathop-8.12 {compiled ^: errors} -returnCodes error -body {
+ ^ nan 0
+ } -result {can't use non-numeric floating-point value as operand of "^"}
+ test mathop-8.13 {compiled ^: errors} -returnCodes error -body {
+ ^ 0 x
+ } -result {can't use non-numeric string as operand of "^"}
+ test mathop-8.14 {compiled ^: errors} -returnCodes error -body {
+ ^ 0 nan
+ } -result {can't use non-numeric floating-point value as operand of "^"}
+ test mathop-8.15 {compiled ^: errors} -returnCodes error -body {
+ ^ 0o8 0
+ } -result {can't use invalid octal number as operand of "^"}
+ test mathop-8.16 {compiled ^: errors} -returnCodes error -body {
+ ^ 0 0o8
+ } -result {can't use invalid octal number as operand of "^"}
+ test mathop-8.17 {compiled ^: errors} -returnCodes error -body {
+ ^ 0 [error expectedError]
+ } -result expectedError
+ test mathop-8.18 {compiled ^: argument processing order} -body {
+ # Bytecode compilation known hard for 3+ arguments
+ list [catch {
+ ^ [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
+ } msg] $msg $x
+ } -result {1 expected 2}
+ set op ^
+ test mathop-8.19 {interpreted ^} { $op } 0
+ test mathop-8.20 {interpreted ^} { $op 1 } 1
+ test mathop-8.21 {interpreted ^} { $op 1 2 } 3
+ test mathop-8.22 {interpreted ^} { $op 3 7 6 } 2
+ test mathop-8.23 {interpreted ^} -returnCodes error -body {
+ $op 1.0 2 3
+ } -result {can't use floating-point value as operand of "^"}
+ test mathop-8.24 {interpreted ^} -returnCodes error -body {
+ $op 1 2 3.0
+ } -result {can't use floating-point value as operand of "^"}
+ test mathop-8.25 {interpreted ^} { $op 100000000002 18 -126 } -100000000110
+ test mathop-8.26 {interpreted ^} { $op 0xff 0o377 333333333333 } 333333333333
+ test mathop-8.27 {interpreted ^} { $op 1000000000000000000002 18 -126 } -1000000000000000000110
+ test mathop-8.28 {interpreted ^} { $op 0xff 0o377 3333333333333333333333 } 3333333333333333333333
+ test mathop-8.29 {interpreted ^: errors} -returnCodes error -body {
+ $op x 0
+ } -result {can't use non-numeric string as operand of "^"}
+ test mathop-8.30 {interpreted ^: errors} -returnCodes error -body {
+ $op nan 0
+ } -result {can't use non-numeric floating-point value as operand of "^"}
+ test mathop-8.31 {interpreted ^: errors} -returnCodes error -body {
+ $op 0 x
+ } -result {can't use non-numeric string as operand of "^"}
+ test mathop-8.32 {interpreted ^: errors} -returnCodes error -body {
+ $op 0 nan
+ } -result {can't use non-numeric floating-point value as operand of "^"}
+ test mathop-8.33 {interpreted ^: errors} -returnCodes error -body {
+ $op 0o8 0
+ } -result {can't use invalid octal number as operand of "^"}
+ test mathop-8.34 {interpreted ^: errors} -returnCodes error -body {
+ $op 0 0o8
+ } -result {can't use invalid octal number as operand of "^"}
+ test mathop-8.35 {interpreted ^: errors} -returnCodes error -body {
+ $op 0 [error expectedError]
+ } -result expectedError
+ test mathop-8.36 {interpreted ^: argument processing order} -body {
+ list [catch {
+ $op [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
+ } msg] $msg $x
+ } -result {1 expected 2}
+ test mathop-8.37 {^ and bignums} {
+ list [^ $big1 $big2] [$op $big1 $big2]
+ } {14880247731239682873973207643969192131 14880247731239682873973207643969192131}
+ test mathop-8.38 {^ and bignums} {
+ list [^ $big1 $wide2] [$op $big1 $wide2]
+ } {12135435435354435435342354227710876723 12135435435354435435342354227710876723}
+ test mathop-8.39 {^ and bignums} {
+ list [^ $big1 $small2] [$op $big1 $small2]
+ } {12135435435354435435342423948763884437 12135435435354435435342423948763884437}
+ test mathop-8.40 {^ and bignums} {
+ list [^ $wide1 $big2] [$op $wide1 $big2]
+ } {2746237174783836746262572495752458622 2746237174783836746262572495752458622}
+ test mathop-8.41 {^ and bignums} {
+ list [^ $wide1 $wide2] [$op $wide1 $wide2]
+ } {75115763150222 75115763150222}
+ test mathop-8.42 {^ and bignums} {
+ list [^ $wide1 $small2] [$op $wide1 $small2]
+ } {12345678895656 12345678895656}
+ test mathop-8.43 {^ and bignums} {
+ list [^ $small1 $big2] [$op $small1 $big2]
+ } {2746237174783836746262564892918415126 2746237174783836746262564892918415126}
+ test mathop-8.44 {^ and bignums} {
+ list [^ $small1 $wide2] [$op $small1 $wide2]
+ } {87321847145446 87321847145446}
+ test mathop-8.45 {^ and bignums} {
+ list [^ $small1 $small2] [$op $small1 $small2]
+ } {70720 70720}
+
+ # TODO: % ** << >> - / == != < <= > >= ne in ni
+
+ test mathop-13.100 {compiled -: argument processing order} -body {
+ # Bytecode compilation known hard for 3+ arguments
+ list [catch {
+ - [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
+ } msg] $msg $x
+ } -result {1 expected 2}
+
+ test mathop-14.100 {compiled /: argument processing order} -body {
+ # Bytecode compilation known hard for 3+ arguments
+ list [catch {
+ / [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
+ } msg] $msg $x
+ } -result {1 expected 2}
+}
+
+test mathop-20.1 { zero args, return unit } {
+ set res {}
+ foreach op {+ * & ^ | ** < <= > >= == eq} {
+ lappend res [TestOp $op]
+ }
+ set res
+} {0 1 -1 0 0 1 1 1 1 1 1 1}
+test mathop-20.2 { zero args, not allowed } {
+ set exp {}
+ foreach op {~ ! << >> % != ne in ni - /} {
+ set res [TestOp $op]
+ if {[string match "wrong # args* NONE" $res]} {
+ lappend exp 0
+ } else {
+ lappend exp $res
+ }
+ }
+ set exp
+} {0 0 0 0 0 0 0 0 0 0 0}
+test mathop-20.3 { one arg } {
+ set res {}
+ foreach val {7 8.3} {
+ foreach op {+ ** - * / < <= > >= == eq !} {
+ lappend res [TestOp $op $val]
+ }
+ }
+ set res
+} [list 7 7 -7 7 [expr {1.0/7.0}] 1 1 1 1 1 1 0 \
+ 8.3 8.3 -8.3 8.3 [expr {1.0/8.3}] 1 1 1 1 1 1 0]
+test mathop-20.4 { one arg, integer only ops } {
+ set res {}
+ foreach val {23} {
+ foreach op {& | ^ ~} {
+ lappend res [TestOp $op $val]
+ }
+ }
+ set res
+} [list 23 23 23 -24]
+test mathop-20.5 { one arg, not allowed } {
+ set exp {}
+ foreach op {% != ne in ni << >>} {
+ set res [TestOp $op 1]
+ if {[string match "wrong # args* NONE" $res]} {
+ lappend exp 0
+ } else {
+ lappend exp $res
+ }
+ }
+ set exp
+} {0 0 0 0 0 0 0}
+test mathop-20.6 { one arg, error } {
+ set res {}
+ set exp {}
+ foreach vals {x {1 x} {1 1 x} {1 x 1}} {
+ # skipping - for now, knownbug...
+ foreach op {+ * / & | ^ **} {
+ lappend res [TestOp $op {*}$vals]
+ lappend exp "can't use non-numeric string as operand of \"$op\" ARITH DOMAIN {non-numeric string}"
+ }
+ }
+ foreach op {+ * / & | ^ **} {
+ lappend res [TestOp $op NaN 1]
+ lappend exp "can't use non-numeric floating-point value as operand of \"$op\" ARITH DOMAIN {non-numeric floating-point value}"
+ }
+ expr {$res eq $exp ? 0 : $res}
+} 0
+test mathop-20.7 { multi arg } {
+ set res {}
+ foreach vals {{1 2} {3 4 5} {4 3 2 1}} {
+ foreach op {+ - * /} {
+ lappend res [TestOp $op {*}$vals]
+ }
+ }
+ set res
+} [list 3 -1 2 0 12 -6 60 0 10 -2 24 0]
+test mathop-20.8 { multi arg, double } {
+ set res {}
+ foreach vals {{1.0 2} {3.0 4 5} {4 3.0 2 1}
+ {1.0 -1.0 1e-18} {1.0 1.0 1e-18}} {
+ foreach op {+ - * /} {
+ lappend res [TestOp $op {*}$vals]
+ }
+ }
+ set res
+} [list 3.0 -1.0 2.0 0.5 12.0 -6.0 60.0 0.15 10.0 -2.0 24.0 [expr {2.0/3}] 1e-18 2.0 -1e-18 [expr {-1.0/1e-18}] 2.0 -1e-18 1e-18 [expr {1.0/1e-18}]]
+
+test mathop-21.1 { unary ops, bitnot } {
+ set res {}
+ lappend res [TestOp ~ 7]
+ lappend res [TestOp ~ -5]
+ lappend res [TestOp ~ 354657483923456]
+ lappend res [TestOp ~ 123456789123456789123456789]
+ set res
+} [list -8 4 -354657483923457 -123456789123456789123456790]
+test mathop-21.2 { unary ops, logical not } {
+ set res {}
+ lappend res [TestOp ! 0]
+ lappend res [TestOp ! 1]
+ lappend res [TestOp ! true]
+ lappend res [TestOp ! false]
+ lappend res [TestOp ! 37]
+ lappend res [TestOp ! 8.5]
+ set res
+} [list 1 0 0 1 0 0]
+test mathop-21.3 { unary ops, negation } {
+ set res {}
+ lappend res [TestOp - 7.2]
+ lappend res [TestOp - -5]
+ lappend res [TestOp - -2147483648] ;# -2**31
+ lappend res [TestOp - -9223372036854775808] ;# -2**63
+ lappend res [TestOp - 354657483923456] ;# wide
+ lappend res [TestOp - 123456789123456789123456789] ;# big
+ set res
+} [list -7.2 5 2147483648 9223372036854775808 -354657483923456 \
+ -123456789123456789123456789]
+test mathop-21.4 { unary ops, inversion } {
+ set res {}
+ lappend res [TestOp / 1]
+ lappend res [TestOp / 5]
+ lappend res [TestOp / 5.6]
+ lappend res [TestOp / -8]
+ lappend res [TestOp / 354657483923456] ;# wide
+ lappend res [TestOp / 123456789123456789123456789] ;# big
+ set res
+} [list 1.0 0.2 0.17857142857142858 -0.125 \
+ 2.8196218755553604e-15 8.10000006561e-27]
+test mathop-21.5 { unary ops, bad values } {
+ set res {}
+ set exp {}
+ lappend res [TestOp / x]
+ lappend exp "can't use non-numeric string as operand of \"/\" ARITH DOMAIN {non-numeric string}"
+ lappend res [TestOp - x]
+ lappend exp "can't use non-numeric string as operand of \"-\" ARITH DOMAIN {non-numeric string}"
+ lappend res [TestOp ~ x]
+ lappend exp "can't use non-numeric string as operand of \"~\" ARITH DOMAIN {non-numeric string}"
+ lappend res [TestOp ! x]
+ lappend exp "can't use non-numeric string as operand of \"!\" ARITH DOMAIN {non-numeric string}"
+ lappend res [TestOp ~ 5.0]
+ lappend exp "can't use floating-point value as operand of \"~\" ARITH DOMAIN {floating-point value}"
+ expr {$res eq $exp ? 0 : $res}
+} 0
+test mathop-21.6 { unary ops, too many } {
+ set exp {}
+ foreach op {~ !} {
+ set res [TestOp $op 7 8]
+ if {[string match "wrong # args* NONE" $res]} {
+ lappend exp 0
+ } else {
+ lappend exp $res
+ }
+ }
+ set exp
+} {0 0}
+
+test mathop-22.1 { bitwise ops } {
+ set res {}
+ foreach vals {5 {1 6} {1 2 3} {1 2 3 4}} {
+ foreach op {& | ^} {
+ lappend res [TestOp $op {*}$vals]
+ }
+ }
+ set res
+} [list 5 5 5 0 7 7 0 3 0 0 7 4]
+test mathop-22.2 { bitwise ops on bignums } {
+ set dig 50
+ set a 0x[string repeat 5 $dig]
+ set b 0x[string repeat 7 $dig]
+ set c 0x[string repeat 9 $dig]
+ set bn [expr {~$b}]
+ set cn [expr {~$c}]
+
+ set res {}
+ foreach vals [list [list $a $b] [list $a $c] [list $b $c] \
+ [list $a $bn] [list $bn $c] [list $bn $cn]] {
+ foreach op {& | ^} {
+ lappend res [TestOp $op {*}$vals]
+ }
+ }
+ set exp {}
+ foreach d {5 7 2 1 D C 1 F E 0 -D -D 8 -9 -1 -0 -E E} {
+ if {[string match "-*" $d]} {
+ set d [format %X [expr 15-0x[string range $d 1 end]]]
+ set val [expr -0x[string repeat $d $dig]-1]
+ } else {
+ set val [expr 0x[string repeat $d $dig]]
+ }
+ lappend exp $val
+ }
+ expr {$exp eq $res ? 1 : "($res != $exp"}
+} 1
+test mathop-22.3 { bitwise ops } {
+ set big1 12135435435354435435342423948763867876
+ set big2 2746237174783836746262564892918327847
+ set wide1 12345678912345
+ set wide2 87321847232215
+ set small1 87345
+ set small2 16753
+
+ set res {}
+ foreach op {& | ^} {
+ lappend res [TestOp $op $big1 $big2]
+ lappend res [TestOp $op $big1 $wide2]
+ lappend res [TestOp $op $big1 $small2]
+ lappend res [TestOp $op $wide1 $big2]
+ lappend res [TestOp $op $wide1 $wide2]
+ lappend res [TestOp $op $wide1 $small2]
+ lappend res [TestOp $op $small1 $big2]
+ lappend res [TestOp $op $small1 $wide2]
+ lappend res [TestOp $op $small1 $small2]
+ }
+ set res
+} [list \
+ 712439449294653815890598856501796 \
+ 78521450111684 \
+ 96 \
+ 2371422390785 \
+ 12275881497169 \
+ 16721 \
+ 33 \
+ 87057 \
+ 16689 \
+ 14880960170688977527789098242825693927 \
+ 12135435435354435435342432749160988407 \
+ 12135435435354435435342423948763884533 \
+ 2746237174783836746262574867174849407 \
+ 87391644647391 \
+ 12345678912377 \
+ 2746237174783836746262564892918415159 \
+ 87321847232503 \
+ 87409 \
+ 14880247731239682873973207643969192131 \
+ 12135435435354435435342354227710876723 \
+ 12135435435354435435342423948763884437 \
+ 2746237174783836746262572495752458622 \
+ 75115763150222 \
+ 12345678895656 \
+ 2746237174783836746262564892918415126 \
+ 87321847145446 \
+ 70720 \
+ ]
+test mathop-22.4 { unary ops, bad values } {
+ set res {}
+ set exp {}
+ foreach op {& | ^} {
+ lappend res [TestOp $op x 5]
+ lappend exp "can't use non-numeric string as operand of \"$op\" ARITH DOMAIN {non-numeric string}"
+ lappend res [TestOp $op 5 x]
+ lappend exp "can't use non-numeric string as operand of \"$op\" ARITH DOMAIN {non-numeric string}"
+ }
+ expr {$res eq $exp ? 0 : $res}
+} 0
+
+test mathop-23.1 { comparison ops, numerical } {
+ set res {}
+ set todo {5 {1 6} {1 2 2 3} {4 3 2 1} {5.0 5.0} {6 3 3 1} {5.0 5}}
+ lappend todo [list 2342476234762482734623842342 234827463876473 3434]
+ lappend todo [list 2653 453735910264536 453735910264537 2384762472634982746239847637]
+ lappend todo [list 2653 2384762472634982746239847637]
+ lappend todo [list 2653 -2384762472634982746239847637]
+ lappend todo [list 3789253678212653 -2384762472634982746239847637]
+ lappend todo [list 5.0 6 7.0 8 1e13 1945628567352654 1.1e20 \
+ 6734253647589123456784564378 2.3e50]
+ set a 7
+ lappend todo [list $a $a] ;# Same object
+ foreach vals $todo {
+ foreach op {< <= > >= == eq} {
+ lappend res [TestOp $op {*}$vals]
+ }
+ }
+ set res
+} [list 1 1 1 1 1 1 \
+ 1 1 0 0 0 0 \
+ 0 1 0 0 0 0 \
+ 0 0 1 1 0 0 \
+ 0 1 0 1 1 1 \
+ 0 0 0 1 0 0 \
+ 0 1 0 1 1 0 \
+ 0 0 1 1 0 0 \
+ 1 1 0 0 0 0 \
+ 1 1 0 0 0 0 \
+ 0 0 1 1 0 0 \
+ 0 0 1 1 0 0 \
+ 1 1 0 0 0 0 \
+ 0 1 0 1 1 1 \
+ ]
+test mathop-23.2 { comparison ops, string } {
+ set res {}
+ set todo {a {a b} {5 b b c} {d c b a} {xy xy} {gy ef ef ab}}
+ set a x
+ lappend todo [list $a $a]
+ foreach vals $todo {
+ foreach op {< <= > >= == eq} {
+ lappend res [TestOp $op {*}$vals]
+ }
+ }
+ set res
+} [list 1 1 1 1 1 1 \
+ 1 1 0 0 0 0 \
+ 0 1 0 0 0 0 \
+ 0 0 1 1 0 0 \
+ 0 1 0 1 1 1 \
+ 0 0 0 1 0 0 \
+ 0 1 0 1 1 1 \
+ ]
+test mathop-23.3 { comparison ops, nonequal} {
+ set res {}
+ foreach vals {{a b} {17.0 0x11} {foo foo} {10 10}} {
+ foreach op {!= ne} {
+ lappend res [TestOp $op {*}$vals]
+ }
+ }
+ set res
+} [list 1 1 0 1 0 0 0 0 ]
+
+test mathop-24.1 { binary ops } {
+ set res {}
+ foreach vals {{3 5} {17 7} {199 5} {293234675763434238476239486 17} \
+ {5 1} {0 7}} {
+ foreach op {% << >> in ni} {
+ lappend res [TestOp $op {*}$vals]
+ }
+ }
+ set res
+} [list 3 96 0 0 1 3 2176 0 0 1 4 6368 6 0 1 \
+ 14 38434855421664852505557661908992 2237203031642412097749 0 1 \
+ 0 10 2 0 1 0 0 0 0 1]
+test mathop-24.2 { binary ops, modulo } {
+ # Test different combinations to get all code paths
+ set res {}
+
+ set bigbig 14372423674564535234543545248972634923869
+ set big 12135435435354435435342423948763867876
+ set wide 12345678912345
+ set negwide -12345678912345
+ set small 5
+ set neg -5
+
+ lappend res [TestOp % $bigbig $big]
+ lappend res [TestOp % $wide $big]
+ lappend res [TestOp % $negwide $big]
+ lappend res [TestOp % $small $big]
+ lappend res [TestOp % $neg $big]
+ lappend res [TestOp % $small $wide]
+ lappend res [TestOp % $neg $wide]
+ lappend res [TestOp % $wide $small]
+ set res
+} [list 4068119104883679098115293636215358685 \
+ 12345678912345 \
+ 12135435435354435435342411603084955531 \
+ 5 \
+ 12135435435354435435342423948763867871 \
+ 5 \
+ 12345678912340 \
+ 0 \
+ ]
+test mathop-24.3 { binary ops, bad values } {
+ set res {}
+ set exp {}
+ foreach op {% << >>} {
+ lappend res [TestOp $op x 1]
+ lappend exp "can't use non-numeric string as operand of \"$op\" ARITH DOMAIN {non-numeric string}"
+ lappend res [TestOp $op 1 x]
+ lappend exp "can't use non-numeric string as operand of \"$op\" ARITH DOMAIN {non-numeric string}"
+ }
+ foreach op {% << >>} {
+ lappend res [TestOp $op 5.0 1]
+ lappend exp "can't use floating-point value as operand of \"$op\" ARITH DOMAIN {floating-point value}"
+ lappend res [TestOp $op 1 5.0]
+ lappend exp "can't use floating-point value as operand of \"$op\" ARITH DOMAIN {floating-point value}"
+ }
+ foreach op {in ni} {
+ lappend res [TestOp $op 5 "a b \{ c"]
+ lappend exp "unmatched open brace in list NONE"
+ }
+ lappend res [TestOp % 5 0]
+ lappend exp "divide by zero ARITH DIVZERO {divide by zero}"
+ lappend res [TestOp % 9838923468297346238478737647637375 0]
+ lappend exp "divide by zero ARITH DIVZERO {divide by zero}"
+ lappend res [TestOp / 5 0]
+ lappend exp "divide by zero ARITH DIVZERO {divide by zero}"
+ lappend res [TestOp / 9838923468297346238478737647637375 0]
+ lappend exp "divide by zero ARITH DIVZERO {divide by zero}"
+ expr {$res eq $exp ? 0 : $res}
+} 0
+test mathop-24.4 { binary ops, negative shift } {
+ set res {}
+
+ set big -12135435435354435435342423948763867876
+ set wide -12345678912345
+ set small -1
+
+ lappend res [TestOp << 10 $big]
+ lappend res [TestOp << 10 $wide]
+ lappend res [TestOp << 10 $small]
+ lappend res [TestOp >> 10 $big]
+ lappend res [TestOp >> 10 $wide]
+ lappend res [TestOp >> 10 $small]
+
+ set exp [lrepeat 6 "negative shift argument NONE"]
+ expr {$res eq $exp ? 0 : $res}
+} 0
+test mathop-24.5 { binary ops, large shift } {
+ set res {}
+ set exp {}
+
+ set big 12135435435354435435342423948763867876
+ set wide 12345678912345
+ set small 1
+
+ lappend res [TestOp << 1 2147483648]
+ lappend exp "integer value too large to represent NONE"
+ lappend res [TestOp << 1 4294967296]
+ lappend exp "integer value too large to represent NONE"
+ lappend res [TestOp << $small $wide]
+ lappend exp "integer value too large to represent NONE"
+ lappend res [TestOp << $small $big]
+ lappend exp "integer value too large to represent NONE"
+ lappend res [TestOp >> $big $wide]
+ lappend exp 0
+ lappend res [TestOp >> $big $big]
+ lappend exp 0
+ lappend res [TestOp >> $small 70]
+ lappend exp 0
+ lappend res [TestOp >> $wide 70]
+ lappend exp 0
+ lappend res [TestOp >> -$big $wide]
+ lappend exp -1
+ lappend res [TestOp >> -$wide $wide]
+ lappend exp -1
+ lappend res [TestOp >> -$small $wide]
+ lappend exp -1
+ lappend res [TestOp >> -$small 70]
+ lappend exp -1
+ lappend res [TestOp >> -$wide 70]
+ lappend exp -1
+
+ expr {$res eq $exp ? 0 : $res}
+} 0
+test mathop-24.6 { binary ops, shift } {
+ # Test different combinations to get all code paths
+ set res {}
+
+ set bigbig 14372423674564535234543545248972634923869
+ set big 12135435435354435435342423948763867876
+ set wide 12345678912345
+ set negwide -12345678912345
+ set small 5
+ set neg -5
+
+ lappend res [TestOp << $wide $small]
+ lappend res [TestOp >> $wide $small]
+ set res
+} [list 395061725195040 \
+ 385802466010 \
+ ]
+test mathop-24.7 { binary ops, list search } {
+ set res {}
+
+ foreach op {in ni} {
+ lappend res [TestOp $op 5 {7 5 8}]
+ lappend res [TestOp $op hej {foo bar hej}]
+ lappend res [TestOp $op 5 {7 0x5 8}]
+ }
+ set res
+} [list 1 1 0 0 0 1]
+test mathop-24.8 { binary ops, too many } {
+ set exp {}
+ foreach op {<< >> % != ne in ni ~ !} {
+ set res [TestOp $op 7 8 9]
+ if {[string match "wrong # args* NONE" $res]} {
+ lappend exp 0
+ } else {
+ lappend exp $res
+ }
+ }
+ set exp
+} {0 0 0 0 0 0 0 0 0}
+
+test mathop-25.1 { exp operator } {TestOp ** } 1
+test mathop-25.2 { exp operator } {TestOp ** 0 } 0
+test mathop-25.3 { exp operator } {TestOp ** 0 5} 0
+test mathop-25.4 { exp operator } {TestOp ** 7.5 } 7.5
+test mathop-25.5 { exp operator } {TestOp ** 1 5} 1
+test mathop-25.6 { exp operator } {TestOp ** 5 1} 5
+test mathop-25.7 { exp operator } {TestOp ** 4 3 2 1} 262144
+test mathop-25.8 { exp operator } {TestOp ** 5.5 4} 915.0625
+test mathop-25.9 { exp operator } {TestOp ** 16 3.5} 16384.0
+test mathop-25.10 { exp operator } {TestOp ** 3.5 0} 1.0
+test mathop-25.11 { exp operator } {TestOp ** 378 0} 1
+test mathop-25.12 { exp operator } {TestOp ** 7.8 1} 7.8
+test mathop-25.13 { exp operator } {TestOp ** 748 1} 748
+test mathop-25.14 { exp operator } {TestOp ** 1.6 -1} 0.625
+test mathop-25.15 { exp operator } {TestOp ** 683 -1} 0
+test mathop-25.16 { exp operator } {TestOp ** 1 -1} 1
+test mathop-25.17 { exp operator } {TestOp ** -1 -1} -1
+test mathop-25.18 { exp operator } {TestOp ** -1 -2} 1
+test mathop-25.19 { exp operator } {TestOp ** -1 3} -1
+test mathop-25.20 { exp operator } {TestOp ** -1 4} 1
+test mathop-25.21 { exp operator } {TestOp ** 2 63} 9223372036854775808
+test mathop-25.22 { exp operator } {TestOp ** 83756485763458746358734658473567847567473 2} 7015148907444467657897585474493757781161998914521537835809623408157343003287605729
+test mathop-25.23 { exp operator errors } {
+ set res {}
+ set exp {}
+
+ set huge [string repeat 145782 1000]
+ set big 12135435435354435435342423948763867876
+ set wide 12345678912345
+ set small 2
+
+ lappend res [TestOp ** 0 -5]
+ lappend exp "exponentiation of zero by negative power ARITH DOMAIN {exponentiation of zero by negative power}"
+ lappend res [TestOp ** 0.0 -5.0]
+ lappend exp "exponentiation of zero by negative power ARITH DOMAIN {exponentiation of zero by negative power}"
+ lappend res [TestOp ** $small $wide]
+ lappend exp "exponent too large NONE"
+ lappend res [TestOp ** 2 $big]
+ lappend exp "exponent too large NONE"
+ lappend res [TestOp ** $huge 2.1]
+ lappend exp "Inf"
+ lappend res [TestOp ** 2 foo]
+ lappend exp "can't use non-numeric string as operand of \"**\" ARITH DOMAIN {non-numeric string}"
+ lappend res [TestOp ** foo 2]
+ lappend exp "can't use non-numeric string as operand of \"**\" ARITH DOMAIN {non-numeric string}"
+
+ expr {$res eq $exp ? 0 : $res}
+} 0
+
+test mathop-26.1 { misc ops, size combinations } {
+ set big1 12135435435354435435342423948763867876
+ set big2 2746237174783836746262564892918327847
+ set wide1 87321847232215
+ set wide2 12345678912345
+ set small1 87345
+ set small2 16753
+
+ set res {}
+ foreach op {+ * - /} {
+ lappend res [TestOp $op $big1 $big2]
+ lappend res [TestOp $op $big1 $wide2]
+ lappend res [TestOp $op $big1 $small2]
+ lappend res [TestOp $op $wide1 $big2]
+ lappend res [TestOp $op $wide1 $wide2]
+ lappend res [TestOp $op $wide1 $small2]
+ lappend res [TestOp $op $small1 $big2]
+ lappend res [TestOp $op $small1 $wide2]
+ lappend res [TestOp $op $small1 $small2]
+ }
+ set res
+} [list \
+ 14881672610138272181604988841682195723 \
+ 12135435435354435435342436294442780221 \
+ 12135435435354435435342423948763884629 \
+ 2746237174783836746262652214765560062 \
+ 99667526144560 \
+ 87321847248968 \
+ 2746237174783836746262564892918415192 \
+ 12345678999690 \
+ 104098 \
+ 33326783924759424684447891401270222910405366244661685890993770489959542972 \
+ 149820189346379518024969783068410988366610965329220 \
+ 203304949848492856848291628413641078526628 \
+ 239806503039903915972546163440347114360602909991105 \
+ 1078047487961768329845194175 \
+ 1462902906681297895 \
+ 239870086031494220602303730571951345796215 \
+ 1078333324598774025 \
+ 1463290785 \
+ 9389198260570598689079859055845540029 \
+ 12135435435354435435342411603084955531 \
+ 12135435435354435435342423948763851123 \
+ -2746237174783836746262477571071095632 \
+ 74976168319870 \
+ 87321847215462 \
+ -2746237174783836746262564892918240502 \
+ -12345678825000 \
+ 70592 \
+ 4 \
+ 982970278225822587257201 \
+ 724373869477373332259441529801460 \
+ 0 \
+ 7 \
+ 5212311062 \
+ 0 \
+ 0 \
+ 5 \
+ ]
+test mathop-26.2 { misc ops, corner cases } {
+ set res {}
+ lappend res [TestOp - 0 -2147483648] ;# -2**31
+ lappend res [TestOp - 0 -9223372036854775808] ;# -2**63
+ lappend res [TestOp / -9223372036854775808 -1]
+ lappend res [TestOp * 2147483648 2]
+ lappend res [TestOp * 9223372036854775808 2]
+ set res
+} [list 2147483648 9223372036854775808 9223372036854775808 4294967296 18446744073709551616]
+
+if 0 {
+ # Compare ops to expr bytecodes
+ namespace import ::tcl::mathop::*
+ proc _X {a b c} {
+ set x [+ $a [- $b $c]]
+ set y [expr {$a + ($b - $c)}]
+ set z [< $a $b $c]
+ }
+ set ::tcl_traceCompile 2
+ _X 3 4 5
+ set ::tcl_traceCompile 0
+}
+
+# cleanup
+namespace delete ::testmathop
+namespace delete ::testmathop2
+::tcltest::cleanupTests
+return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/misc.test b/tests/misc.test
index 9894e27..fe19ebe 100644
--- a/tests/misc.test
+++ b/tests/misc.test
@@ -17,6 +17,8 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
+testConstraint testhashsystemhash [llength [info commands testhashsystemhash]]
+
test misc-1.1 {error in variable ref. in command in array reference} {
proc tstProc {} {
global a
@@ -49,33 +51,26 @@ test misc-1.2 {error in variable ref. in command in array reference} {
# this is a bogus comment
"
set msg {}
- join [list [catch tstProc msg] $msg $errorInfo] \n
+ join [list [catch tstProc msg] $msg $::errorInfo] \n
} [subst -novariables -nocommands {1
missing close-brace for variable name
missing close-brace for variable name
- while compiling
+ while executing
"set tst $a([winfo name $\{zz)
# this is a bogus comment
# this is a bogus comment
# this is a bogus comment
# this is a bogus comment
# this is a ..."
- (compiling body of proc "tstProc", line 4)
+ (procedure "tstProc" line 4)
invoked from within
"tstProc"}]
+for {set i 1} {$i<300} {incr i} {
+ test misc-2.$i {hash table with sys-alloc} testhashsystemhash \
+ "testhashsystemhash $i" OK
+}
+
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/msgcat.test b/tests/msgcat.test
index 53b7c52..0669810 100644
--- a/tests/msgcat.test
+++ b/tests/msgcat.test
@@ -17,8 +17,8 @@ if {[catch {package require tcltest 2}]} {
puts stderr "Skipping tests in [info script]. tcltest 2 required."
return
}
-if {[catch {package require msgcat 1.3.4}]} {
- puts stderr "Skipping tests in [info script]. No msgcat 1.3.4 found to test."
+if {[catch {package require msgcat 1.4.2}]} {
+ puts stderr "Skipping tests in [info script]. No msgcat 1.4.2 found to test."
return
}
@@ -53,7 +53,8 @@ namespace eval ::msgcat::test {
set result [string tolower [lindex $setVars 0]]
if {[string length $result] == 0} {
if {[info exists ::tcl::mac::locale]} {
- set result [string tolower $::tcl::mac::locale]
+ set result [string tolower \
+ [msgcat::ConvertLocale $::tcl::mac::locale]]
} else {
set result c
}
@@ -113,7 +114,7 @@ namespace eval ::msgcat::test {
mclocale $locale
} -body {
mcpreferences
- } -result en
+ } -result {en {}}
test msgcat-1.6 {mclocale set, two elements} -setup {
variable locale [mclocale]
@@ -139,7 +140,7 @@ namespace eval ::msgcat::test {
mclocale $locale
} -body {
mcpreferences
- } -result {en_us en}
+ } -result {en_us en {}}
test msgcat-1.9 {mclocale set, three elements} -setup {
variable locale [mclocale]
@@ -165,7 +166,7 @@ namespace eval ::msgcat::test {
mclocale $locale
} -body {
mcpreferences
- } -result {en_us_funky en_us en}
+ } -result {en_us_funky en_us en {}}
test msgcat-1.12 {mclocale set, reject evil input} -setup {
variable locale [mclocale]
@@ -264,12 +265,13 @@ namespace eval ::msgcat::test {
# (e.g. en_UK) will search less specific locales
# (e.g. en) for translation strings.
#
- # Do this for the 12 permutations of
+ # Do this for the 15 permutations of
# locales: {foo foo_BAR foo_BAR_baz}
- # strings: {ov1 ov2 ov3 ov4}
- # locale foo defines ov1, ov2, ov3
- # locale foo_BAR defines ov2, ov3
- # locale foo_BAR_BAZ defines ov3
+ # strings: {ov0 ov1 ov2 ov3 ov4}
+ # locale ROOT defines ov0, ov1, ov2, ov3
+ # locale foo defines ov1, ov2, ov3
+ # locale foo_BAR defines ov2, ov3
+ # locale foo_BAR_BAZ defines ov3
# (ov4 is defined in none)
# So,
# ov3 should be resolved in foo, foo_BAR, foo_BAR_baz
@@ -282,16 +284,23 @@ namespace eval ::msgcat::test {
variable count 2
variable result
array set result {
- foo,ov1 ov1_foo foo,ov2 ov2_foo foo,ov3 ov3_foo foo,ov4 ov4
- foo_BAR,ov1 ov1_foo foo_BAR,ov2 ov2_foo_BAR foo_BAR,ov3 ov3_foo_BAR
- foo_BAR,ov4 ov4 foo_BAR_baz,ov1 ov1_foo foo_BAR_baz,ov2 ov2_foo_BAR
+ foo,ov0 ov0_ROOT foo,ov1 ov1_foo foo,ov2 ov2_foo
+ foo,ov3 ov3_foo foo,ov4 ov4
+ foo_BAR,ov0 ov0_ROOT foo_BAR,ov1 ov1_foo foo_BAR,ov2 ov2_foo_BAR
+ foo_BAR,ov3 ov3_foo_BAR foo_BAR,ov4 ov4
+ foo_BAR_baz,ov0 ov0_ROOT foo_BAR_baz,ov1 ov1_foo
+ foo_BAR_baz,ov2 ov2_foo_BAR
foo_BAR_baz,ov3 ov3_foo_BAR_baz foo_BAR_baz,ov4 ov4
}
variable loc
variable string
foreach loc {foo foo_BAR foo_BAR_baz} {
- foreach string {ov1 ov2 ov3 ov4} {
+ foreach string {ov0 ov1 ov2 ov3 ov4} {
test msgcat-3.$count {mcset, overlap} -setup {
+ mcset {} ov0 ov0_ROOT
+ mcset {} ov1 ov1_ROOT
+ mcset {} ov2 ov2_ROOT
+ mcset {} ov3 ov3_ROOT
mcset foo ov1 ov1_foo
mcset foo ov2 ov2_foo
mcset foo ov3 ov3_foo
@@ -382,11 +391,15 @@ namespace eval ::msgcat::test {
# Tests msgcat-5.*: [mcload]
- variable locales {foo foo_BAR foo_BAR_baz}
- makeDirectory msgdir
+ variable locales {{} foo foo_BAR foo_BAR_baz}
+ set msgdir [makeDirectory msgdir]
foreach loc $locales {
- makeFile "::msgcat::mcset $loc abc abc-$loc" \
- [string tolower [file join msgdir $loc.msg]]
+ if { $loc eq {} } {
+ set msg ROOT
+ } else {
+ set msg [string tolower $loc]
+ }
+ makeFile [list ::msgcat::mcset $loc abc abc-$loc] $msg.msg $msgdir
}
variable count 1
foreach loc {foo foo_BAR foo_BAR_baz} {
@@ -396,21 +409,21 @@ namespace eval ::msgcat::test {
} -cleanup {
mclocale $locale
} -body {
- mcload [file join [temporaryDirectory] msgdir]
- } -result $count
+ mcload $msgdir
+ } -result [expr { $count+1 }]
incr count
}
# Even though foo_BAR_notexist does not exist,
- # foo_BAR and foo should be loaded.
+ # foo_BAR, foo and the root should be loaded.
test msgcat-5.4 {mcload} -setup {
variable locale [mclocale]
mclocale foo_BAR_notexist
} -cleanup {
mclocale $locale
} -body {
- mcload [file join [temporaryDirectory] msgdir]
- } -result 2
+ mcload $msgdir
+ } -result 3
test msgcat-5.5 {mcload} -setup {
variable locale [mclocale]
@@ -418,12 +431,13 @@ namespace eval ::msgcat::test {
} -cleanup {
mclocale $locale
} -body {
- mcload [file join [temporaryDirectory] msgdir]
- } -result 0
+ mcload $msgdir
+ } -result 1
test msgcat-5.6 {mcload} -setup {
variable locale [mclocale]
mclocale foo
+ mcload $msgdir
} -cleanup {
mclocale $locale
} -body {
@@ -433,6 +447,7 @@ namespace eval ::msgcat::test {
test msgcat-5.7 {mcload} -setup {
variable locale [mclocale]
mclocale foo_BAR
+ mcload $msgdir
} -cleanup {
mclocale $locale
} -body {
@@ -442,6 +457,7 @@ namespace eval ::msgcat::test {
test msgcat-5.8 {mcload} -setup {
variable locale [mclocale]
mclocale foo_BAR_baz
+ mcload $msgdir
} -cleanup {
mclocale $locale
} -body {
@@ -449,23 +465,38 @@ namespace eval ::msgcat::test {
} -result abc-foo_BAR_baz
test msgcat-5.9 {mcload} -setup {
+ variable locale [mclocale]
+ mclocale no_FI_notexist
+ mcload $msgdir
+ } -cleanup {
+ mclocale $locale
+ } -body {
+ mc abc
+ } -result abc-
+
+ test msgcat-5.10 {mcload} -setup {
rename ::msgcat::mcunknown SavedMcunknown
proc ::msgcat::mcunknown {dom s} {
return unknown:$dom:$s
}
variable locale [mclocale]
mclocale no_FI_notexist
+ mcload $msgdir
} -cleanup {
mclocale $locale
rename ::msgcat::mcunknown {}
rename SavedMcunknown ::msgcat::mcunknown
} -body {
- mc abc
- } -result unknown:no_fi_notexist:abc
-
+ mc def
+ } -result unknown:no_fi_notexist:def
foreach loc $locales {
- removeFile [string tolower [file join msgdir $loc.msg]]
+ if { $loc eq {} } {
+ set msg ROOT
+ } else {
+ set msg [string tolower $loc]
+ }
+ removeFile $msg.msg $msgdir
}
removeDirectory msgdir
diff --git a/tests/namespace-old.test b/tests/namespace-old.test
index 5f394b5..5ffb25b 100644
--- a/tests/namespace-old.test
+++ b/tests/namespace-old.test
@@ -15,12 +15,12 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2.2
namespace import -force ::tcltest::*
}
# Clear out any namespaces called test_ns_*
-catch {eval namespace delete [namespace children :: test_ns_*]}
+catch {namespace delete {*}[namespace children :: test_ns_*]}
test namespace-old-1.1 {usage for "namespace" command} {
list [catch {namespace} msg] $msg
@@ -249,8 +249,8 @@ test namespace-old-4.3 {command "namespace delete" doesn't support patterns} {
test namespace-old-4.4 {command "namespace delete" handles multiple args} {
set cmd {
namespace eval test_ns_delete {
- eval namespace delete \
- [namespace children [namespace current] ns?]
+ namespace delete \
+ {*}[namespace children [namespace current] ns?]
}
}
list [catch $cmd msg] $msg [namespace children test_ns_delete]
@@ -334,9 +334,9 @@ test namespace-old-5.9 {usage for "namespace children"} {
list [catch {namespace children test_ns_hier1 y z} msg] $msg
} {1 {wrong # args: should be "namespace children ?name? ?pattern?"}}
-test namespace-old-5.10 {command "namespace children" must get valid namespace} {
- list [catch {namespace children xyzzy} msg] $msg
-} {1 {unknown namespace "xyzzy" in namespace children command}}
+test namespace-old-5.10 {command "namespace children" must get valid namespace} -body {
+ namespace children xyzzy
+} -returnCodes error -result {namespace "xyzzy" not found in "::"}
test namespace-old-5.11 {querying namespace children} {
lsort [namespace children :: test_ns_hier*]
@@ -370,9 +370,9 @@ test namespace-old-5.18 {usage for "namespace parent"} {
list [catch {namespace parent x y} msg] $msg
} {1 {wrong # args: should be "namespace parent ?name?"}}
-test namespace-old-5.19 {command "namespace parent" must get valid namespace} {
- list [catch {namespace parent xyzzy} msg] $msg
-} {1 {unknown namespace "xyzzy" in namespace parent command}}
+test namespace-old-5.19 {command "namespace parent" must get valid namespace} -body {
+ namespace parent xyzzy
+} -returnCodes error -result {namespace "xyzzy" not found in "::"}
test namespace-old-5.20 {querying namespace parent} {
list [namespace eval :: {namespace parent}] \
@@ -525,11 +525,12 @@ test namespace-old-6.16 {public variables affect all parent namespaces} {
} {{cache2 version} {cache2 version}}
test namespace-old-6.17 {usage for "namespace which"} {
- list [catch "namespace which -baz" msg] $msg
+ list [catch "namespace which -baz x" msg] $msg
} {1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}}
test namespace-old-6.18 {usage for "namespace which"} {
- list [catch "namespace which -command" msg] $msg
-} {1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}}
+ # Presume no imported command called -command ;^)
+ namespace which -command
+} {}
test namespace-old-6.19 {querying: namespace which -command} {
proc test_ns_cache1::test_ns_cache_cmd {} {
@@ -681,12 +682,8 @@ test namespace-old-9.4 {check export status} {
} {::test_ns_import::cmd1 ::test_ns_import::cmd2 ::test_ns_import::cmd3}
test namespace-old-9.5 {empty import list in "namespace import" command} {
- namespace import
-} {}
-
-test namespace-old-9.6 {empty import list for "namespace import" command} {
- namespace import
-} {}
+ lsort [namespace import]
+} {bytestring cleanupTests configure customMatch debug errorChannel errorFile getMatchingFiles interpreter limitConstraints loadFile loadScript loadTestedCommands mainThread makeDirectory makeFile match matchDirectories matchFiles normalizeMsg normalizePath outputChannel outputFile preserveCore removeDirectory removeFile restoreState runAllTests saveState singleProcess skip skipDirectories skipFiles temporaryDirectory test testConstraint testsDirectory threadReap verbose viewFile workingDirectory}
test namespace-old-9.7 {empty forget list for "namespace forget" command} {
namespace forget
@@ -848,15 +845,3 @@ eval namespace delete [namespace children :: test_ns_*]
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/namespace.test b/tests/namespace.test
index 166ff00..2be4cfc 100644
--- a/tests/namespace.test
+++ b/tests/namespace.test
@@ -16,8 +16,19 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
+#
+# REMARK: the tests for 'namespace upvar' are not done here. They are to be
+# found in the file 'upvar.test'.
+#
+
# Clear out any namespaces called test_ns_*
-catch {eval namespace delete [namespace children :: test_ns_*]}
+catch {namespace delete {*}[namespace children :: test_ns_*]}
+
+proc fq {ns} {
+ if {[string match ::* $ns]} {return $ns}
+ set current [uplevel 1 {namespace current}]
+ return [string trimright $current :]::[string trimleft $ns :]
+}
test namespace-1.1 {TclInitNamespaces, GetNamespaceFromObj, NamespaceChildrenCmd} {
namespace children :: test_ns_*
@@ -77,7 +88,7 @@ test namespace-5.2 {Tcl_PopCallFrame, local vars must be deleted} {
} {123}
test namespace-6.1 {Tcl_CreateNamespace} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
list [lsort [namespace children :: test_ns_*]] \
[namespace eval test_ns_1 {namespace current}] \
[namespace eval test_ns_2 {namespace current}] \
@@ -96,7 +107,7 @@ test namespace-6.3 {Tcl_CreateNamespace, trailing ::s in ns name are ignored} {
list [catch {namespace eval test_ns_7::: {namespace current}} msg] $msg
} {0 ::test_ns_7}
test namespace-6.4 {Tcl_CreateNamespace, trailing ::s in ns name are ignored} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_1:: {
namespace eval test_ns_2:: {}
namespace eval test_ns_3:: {}
@@ -114,7 +125,7 @@ test namespace-6.5 {Tcl_CreateNamespace, relative ns names now only looked up in
} {::test_ns_1::test_ns_2 ::test_ns_1::test_ns_2}
test namespace-7.1 {Tcl_DeleteNamespace, active call frames in ns} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_1 {
proc p {} {
namespace delete [namespace current]
@@ -163,6 +174,24 @@ test namespace-7.6 {recursive Tcl_DeleteNamespace, no active call frames in ns}
}
namespace delete test_ns_2
} {}
+test namespace-7.7 {Bug 1655305} -setup {
+ interp create slave
+ # Can't invoke through the ensemble, since deleting the global namespace
+ # (indirectly, via deleting ::tcl) deletes the ensemble.
+ slave eval {rename ::tcl::info::commands ::infocommands}
+ slave hide infocommands
+ slave eval {
+ proc foo {} {
+ namespace delete ::
+ }
+ }
+} -body {
+ slave eval foo
+ slave invokehidden infocommands
+} -cleanup {
+ interp delete slave
+} -result {}
+
test namespace-8.1 {TclTeardownNamespace, delete global namespace} {
catch {interp delete test_interp}
@@ -191,7 +220,7 @@ test namespace-8.1 {TclTeardownNamespace, delete global namespace} {
[interp delete test_interp]
} {{::test_ns_1 27} {} 1 {invalid command name "set"} {}}
test namespace-8.2 {TclTeardownNamespace, remove deleted ns from parent} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_1::test_ns_2::test_ns_3a {proc p {} {}}
namespace eval test_ns_1::test_ns_2::test_ns_3b {proc q {} {}}
list [namespace children test_ns_1] \
@@ -199,7 +228,7 @@ test namespace-8.2 {TclTeardownNamespace, remove deleted ns from parent} {
[namespace children test_ns_1]
} {::test_ns_1::test_ns_2 {} {}}
test namespace-8.3 {TclTeardownNamespace, delete child namespaces} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_1::test_ns_2::test_ns_3a {proc p {} {}}
namespace eval test_ns_1::test_ns_2::test_ns_3b {proc q {} {}}
list [namespace children test_ns_1] \
@@ -207,9 +236,9 @@ test namespace-8.3 {TclTeardownNamespace, delete child namespaces} {
[namespace children test_ns_1] \
[catch {namespace children test_ns_1::test_ns_2} msg] $msg \
[info commands test_ns_1::test_ns_2::test_ns_3a::*]
-} {::test_ns_1::test_ns_2 {} {} 1 {unknown namespace "test_ns_1::test_ns_2" in namespace children command} {}}
+} {::test_ns_1::test_ns_2 {} {} 1 {namespace "test_ns_1::test_ns_2" not found in "::"} {}}
test namespace-8.4 {TclTeardownNamespace, cmds imported from deleted ns go away} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_export {
namespace export cmd1 cmd2
proc cmd1 {args} {return "cmd1: $args"}
@@ -233,7 +262,7 @@ test namespace-8.5 {TclTeardownNamespace: preserve errorInfo; errorCode values}
invoked from within
"slave eval error foo bar baz"}
test namespace-8.6 {TclTeardownNamespace: preserve errorInfo; errorCode values} {
- interp create slave
+ interp create slave
slave eval {trace add variable errorCode write {namespace delete :: ;#}}
catch {slave eval error foo bar baz}
interp delete slave
@@ -241,16 +270,16 @@ test namespace-8.6 {TclTeardownNamespace: preserve errorInfo; errorCode values}
} {bar
invoked from within
"slave eval error foo bar baz"}
-test namespace-8.7 {TclTeardownNamespace: preserve errorInfo; errorCode values} {
+test namespace-8.7 {TclTeardownNamespace: preserve errorInfo; errorCode values} {
interp create slave
slave eval {trace add execution error leave {namespace delete :: ;#}}
catch {slave eval error foo bar baz}
interp delete slave
- set ::errorCode
+ set ::errorCode
} baz
test namespace-9.1 {Tcl_Import, empty import pattern} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
list [catch {namespace eval test_ns_import {namespace import {}}} msg] $msg
} {1 {empty import pattern}}
test namespace-9.2 {Tcl_Import, unknown namespace in import pattern} {
@@ -260,7 +289,7 @@ test namespace-9.3 {Tcl_Import, import ns == export ns} {
list [catch {namespace eval test_ns_import {namespace import ::test_ns_import::puts}} msg] $msg
} {1 {import pattern "::test_ns_import::puts" tries to import from namespace "test_ns_import" into itself}}
test namespace-9.4 {Tcl_Import, simple import} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_export {
namespace export cmd1
proc cmd1 {args} {return "cmd1: $args"}
@@ -282,7 +311,7 @@ test namespace-9.6 {Tcl_Import, cmd redefinition ok if allowOverwrite!=0} {
}
} {cmd1: 555}
test namespace-9.7 {Tcl_Import, links are preserved if cmd is redefined} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_export {
namespace export cmd1
proc cmd1 {args} {return "cmd1: $args"}
@@ -344,7 +373,7 @@ test namespace-9.9 {Tcl_Import: Bug 1017299} -setup {
} -returnCodes error -match glob -result {import pattern * would create a loop*}
test namespace-10.1 {Tcl_ForgetImport, check for valid namespaces} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
list [catch {namespace forget xyzzy::*} msg] $msg
} {1 {unknown namespace in namespace forget pattern "xyzzy::*"}}
test namespace-10.2 {Tcl_ForgetImport, ignores patterns that don't match} {
@@ -484,7 +513,7 @@ test namespace-10.9 {Tcl_ForgetImport: Bug 560297} -setup {
} -returnCodes error -match glob -result *
test namespace-11.1 {TclGetOriginalCommand, check if not imported cmd} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_export {
namespace export cmd1
proc cmd1 {args} {return "cmd1: $args"}
@@ -508,7 +537,7 @@ test namespace-11.3 {TclGetOriginalCommand, indirectly imported cmd} {
} {{cmd1: 123} ::test_ns_export::cmd1}
test namespace-12.1 {InvokeImportedCmd} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_export {
namespace export cmd1
proc cmd1 {args} {namespace current}
@@ -529,7 +558,7 @@ test namespace-13.1 {DeleteImportedCmd, deletes imported cmds} {
} {::test_ns_import::cmd1 {}}
test namespace-14.1 {TclGetNamespaceForQualName, absolute names} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
variable v 10
namespace eval test_ns_1::test_ns_2 {
variable v 20
@@ -547,7 +576,7 @@ test namespace-14.2 {TclGetNamespaceForQualName, invalid absolute names} {
list [catch {set ::test_ns_777::v} msg] $msg \
[catch {namespace children test_ns_777} msg] $msg
}
-} {1 {can't read "::test_ns_777::v": no such variable} 1 {unknown namespace "test_ns_777" in namespace children command}}
+} {1 {can't read "::test_ns_777::v": no such variable} 1 {namespace "test_ns_777" not found in "::test_ns_1"}}
test namespace-14.3 {TclGetNamespaceForQualName, relative names} {
namespace eval test_ns_1 {
list $v $test_ns_2::v
@@ -561,7 +590,7 @@ test namespace-14.4 {TclGetNamespaceForQualName, relative ns names looked up onl
list [namespace children test_ns_2] \
[catch {namespace children test_ns_1} msg] $msg
}
-} {::test_ns_1::test_ns_2::foo 1 {unknown namespace "test_ns_1" in namespace children command}}
+} {::test_ns_1::test_ns_2::foo 1 {namespace "test_ns_1" not found in "::test_ns_1"}}
test namespace-14.5 {TclGetNamespaceForQualName, relative ns names looked up only in current ns} {
namespace eval ::test_ns_2 {
namespace eval bar {}
@@ -579,7 +608,7 @@ test namespace-14.6 {TclGetNamespaceForQualName, relative ns names looked up onl
list [namespace children test_ns_2] \
[catch {namespace children test_ns_1} msg] $msg
}
-} {::test_ns_1::test_ns_2::foo 1 {unknown namespace "test_ns_1" in namespace children command}}
+} {::test_ns_1::test_ns_2::foo 1 {namespace "test_ns_1" not found in "::test_ns_1"}}
test namespace-14.7 {TclGetNamespaceForQualName, ignore extra :s if ns} {
namespace children test_ns_1:::
} {::test_ns_1::test_ns_2}
@@ -607,7 +636,7 @@ test namespace-14.11 {TclGetNamespaceForQualName, extra ::s are significant for
lappend l [test_ns_1::test_ns_2:: hello]
} {1 {invalid command name "test_ns_1::test_ns_2::"} {{}: hello}}
test namespace-14.12 {TclGetNamespaceForQualName, extra ::s are significant for vars} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_1 {
variable {}
set test_ns_1::(x) y
@@ -615,12 +644,12 @@ test namespace-14.12 {TclGetNamespaceForQualName, extra ::s are significant for
set test_ns_1::(x)
} y
test namespace-14.13 {TclGetNamespaceForQualName, namespace other than global ns can't have empty name} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
list [catch {namespace eval test_ns_1 {proc {} {} {}; namespace eval {} {}; {}}} msg] $msg
} {1 {can't create namespace "": only global namespace can have empty name}}
test namespace-15.1 {Tcl_FindNamespace, absolute name found} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_delete {
namespace eval test_ns_delete2 {}
proc cmd {args} {namespace current}
@@ -647,7 +676,7 @@ test namespace-15.4 {Tcl_FindNamespace, relative name not found} {
} {1 {unknown namespace "test_ns_delete2" in namespace delete command}}
test namespace-16.1 {Tcl_FindCommand, absolute name found} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_1 {
proc cmd {args} {return "[namespace current]::cmd: $args"}
variable v "::test_ns_1::cmd"
@@ -715,7 +744,7 @@ test namespace-16.11 {Tcl_FindCommand, relative name not found} {
catch {unset x}
test namespace-17.1 {Tcl_FindNamespaceVar, absolute name found} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
set x 314159
namespace eval test_ns_1 {
set ::x
@@ -773,12 +802,26 @@ test namespace-17.9 {Tcl_FindNamespaceVar, relative name and TCL_GLOBAL_ONLY} {
}
set test_ns_1::a
} {hello}
+test namespace-17.10 {Tcl_FindNamespaceVar, interference with cached varNames} {
+ namespace eval test_ns_1 {}
+ proc test_ns {} {
+ set ::test_ns_1::a 0
+ }
+ test_ns
+ rename test_ns {}
+ namespace eval test_ns_1 unset a
+ set a 0
+ namespace eval test_ns_1 set a 1
+ namespace delete test_ns_1
+ set a
+} 1
+catch {unset a}
catch {unset x}
catch {unset l}
catch {rename foo {}}
test namespace-18.1 {TclResetShadowedCmdRefs, one-level check for command shadowing} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
proc foo {} {return "global foo"}
namespace eval test_ns_1 {
proc trigger {} {
@@ -819,7 +862,7 @@ catch {unset l}
catch {rename foo {}}
test namespace-19.1 {GetNamespaceFromObj, global name found} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_1::test_ns_2 {}
namespace children ::test_ns_1
} {::test_ns_1::test_ns_2}
@@ -828,11 +871,11 @@ test namespace-19.2 {GetNamespaceFromObj, relative name found} {
namespace children test_ns_2
}
} {}
-test namespace-19.3 {GetNamespaceFromObj, name not found} {
+test namespace-19.3 {GetNamespaceFromObj, name not found} -body {
namespace eval test_ns_1 {
- list [catch {namespace children test_ns_99} msg] $msg
+ namespace children test_ns_99
}
-} {1 {unknown namespace "test_ns_99" in namespace children command}}
+} -returnCodes error -result {namespace "test_ns_99" not found in "::test_ns_1"}
test namespace-19.4 {GetNamespaceFromObj, invalidation of cached ns refs} {
namespace eval test_ns_1 {
proc foo {} {
@@ -849,18 +892,18 @@ test namespace-19.4 {GetNamespaceFromObj, invalidation of cached ns refs} {
} {{} ::test_ns_1::test_ns_2::test_ns_3}
test namespace-20.1 {Tcl_NamespaceObjCmd, bad subcommand} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
list [catch {namespace} msg] $msg
} {1 {wrong # args: should be "namespace subcommand ?arg ...?"}}
-test namespace-20.2 {Tcl_NamespaceObjCmd, bad subcommand} {
- list [catch {namespace wombat {}} msg] $msg
-} {1 {bad option "wombat": must be children, code, current, delete, eval, exists, export, forget, import, inscope, origin, parent, qualifiers, tail, or which}}
+test namespace-20.2 {Tcl_NamespaceObjCmd, bad subcommand} -body {
+ namespace wombat {}
+} -returnCodes error -match glob -result {bad option "wombat": must be *}
test namespace-20.3 {Tcl_NamespaceObjCmd, abbreviations are okay} {
namespace ch :: test_ns_*
} {}
test namespace-21.1 {NamespaceChildrenCmd, no args} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_1::test_ns_2 {}
expr {[string first ::test_ns_1 [namespace children]] != -1}
} {1}
@@ -890,9 +933,13 @@ test namespace-21.7 {NamespaceChildrenCmd, glob-style pattern given} {
namespace eval test_ns_1::test_ns_foo {}
lsort [namespace children test_ns_1 test*]
} [lsort {::test_ns_1::test_ns_2 ::test_ns_1::test_ns_foo}]
+test namespace-21.8 {NamespaceChildrenCmd, trivial pattern starting with ::} {
+ namespace eval test_ns_1 {}
+ namespace children [namespace current] [fq test_ns_1]
+} [fq test_ns_1]
test namespace-22.1 {NamespaceCodeCmd, bad args} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
list [catch {namespace code} msg] $msg \
[catch {namespace code xxx yyy} msg] $msg
} {1 {wrong # args: should be "namespace code arg"} 1 {wrong # args: should be "namespace code arg"}}
@@ -900,11 +947,11 @@ test namespace-22.2 {NamespaceCodeCmd, arg is already scoped value} {
namespace eval test_ns_1 {
proc cmd {} {return "test_ns_1::cmd"}
}
- namespace code {namespace inscope ::test_ns_1 cmd}
-} {namespace inscope ::test_ns_1 cmd}
+ namespace code {::namespace inscope ::test_ns_1 cmd}
+} {::namespace inscope ::test_ns_1 cmd}
test namespace-22.3 {NamespaceCodeCmd, arg is already scoped value} {
namespace code {namespace inscope ::test_ns_1 cmd}
-} {namespace inscope ::test_ns_1 cmd}
+} {::namespace inscope :: {namespace inscope ::test_ns_1 cmd}}
test namespace-22.4 {NamespaceCodeCmd, in :: namespace} {
namespace code unknown
} {::namespace inscope :: unknown}
@@ -924,9 +971,15 @@ test namespace-22.6 {NamespaceCodeCmd, in other namespace} {
namespace code {set v}
}]
} {42}
+test namespace-22.7 {NamespaceCodeCmd, Bug 3202171} {
+ namespace eval demo {
+ proc namespace args {puts $args}
+ ::namespace code {namespace inscope foo}
+ }
+} [list ::namespace inscope [fq demo] {namespace inscope foo}]
test namespace-23.1 {NamespaceCurrentCmd, bad args} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
list [catch {namespace current xxx} msg] $msg \
[catch {namespace current xxx yyy} msg] $msg
} {1 {wrong # args: should be "namespace current"} 1 {wrong # args: should be "namespace current"}}
@@ -940,7 +993,7 @@ test namespace-23.3 {NamespaceCurrentCmd, in nested ns} {
} {::test_ns_1::test_ns_2}
test namespace-24.1 {NamespaceDeleteCmd, no args} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace delete
} {}
test namespace-24.2 {NamespaceDeleteCmd, one arg} {
@@ -956,12 +1009,12 @@ test namespace-24.4 {NamespaceDeleteCmd, unknown ns} {
} {1 {unknown namespace "::test_ns_foo" in namespace delete command}}
test namespace-25.1 {NamespaceEvalCmd, bad args} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
list [catch {namespace eval} msg] $msg
} {1 {wrong # args: should be "namespace eval name arg ?arg...?"}}
-test namespace-25.2 {NamespaceEvalCmd, bad args} {
- list [catch {namespace test_ns_1} msg] $msg
-} {1 {bad option "test_ns_1": must be children, code, current, delete, eval, exists, export, forget, import, inscope, origin, parent, qualifiers, tail, or which}}
+test namespace-25.2 {NamespaceEvalCmd, bad args} -body {
+ namespace test_ns_1
+} -returnCodes error -match glob -result {bad option "test_ns_1": must be *}
catch {unset v}
test namespace-25.3 {NamespaceEvalCmd, new namespace} {
set v 123
@@ -984,7 +1037,7 @@ test namespace-25.5 {NamespaceEvalCmd, multiple args} {
namespace eval test_ns_1 "set" "v"
} {314159}
test namespace-25.6 {NamespaceEvalCmd, error in eval'd script} {
- list [catch {namespace eval test_ns_1 {xxxx}} msg] $msg $errorInfo
+ list [catch {namespace eval test_ns_1 {xxxx}} msg] $msg $::errorInfo
} {1 {invalid command name "xxxx"} {invalid command name "xxxx"
while executing
"xxxx"
@@ -992,13 +1045,13 @@ test namespace-25.6 {NamespaceEvalCmd, error in eval'd script} {
invoked from within
"namespace eval test_ns_1 {xxxx}"}}
test namespace-25.7 {NamespaceEvalCmd, error in eval'd script} {
- list [catch {namespace eval test_ns_1 {error foo bar baz}} msg] $msg $errorInfo
+ list [catch {namespace eval test_ns_1 {error foo bar baz}} msg] $msg $::errorInfo
} {1 foo {bar
(in namespace eval "::test_ns_1" script line 1)
invoked from within
"namespace eval test_ns_1 {error foo bar baz}"}}
-test namespace-25.8 {NamespaceEvalCmd, error in eval'd script} knownBug {
- list [catch {namespace eval test_ns_1 error foo bar baz} msg] $msg $errorInfo
+test namespace-25.8 {NamespaceEvalCmd, error in eval'd script} {
+ list [catch {namespace eval test_ns_1 error foo bar baz} msg] $msg $::errorInfo
} {1 foo {bar
(in namespace eval "::test_ns_1" script line 1)
invoked from within
@@ -1009,7 +1062,7 @@ test namespace-25.9 {NamespaceEvalCmd, 545325} {
} {namespace eval test_ns_1 info level 0}
test namespace-26.1 {NamespaceExportCmd, no args and new ns} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace export
} {}
test namespace-26.2 {NamespaceExportCmd, just -clear arg} {
@@ -1058,7 +1111,7 @@ test namespace-26.7 {NamespaceExportCmd, -clear resets export list} {
} [list [lsort {::test_ns_2::cmd4 ::test_ns_2::cmd1 ::test_ns_2::cmd3}] {cmd4: hello}]
test namespace-27.1 {NamespaceForgetCmd, no args} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace forget
} {}
test namespace-27.2 {NamespaceForgetCmd, args must be valid namespaces} {
@@ -1078,9 +1131,9 @@ test namespace-27.3 {NamespaceForgetCmd, arg is forgotten} {
} {::test_ns_2::cmd2}
test namespace-28.1 {NamespaceImportCmd, no args} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
- namespace import
-} {}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
+ lsort [namespace import]
+} {bytestring cleanupTests configure customMatch debug errorChannel errorFile getMatchingFiles interpreter limitConstraints loadFile loadScript loadTestedCommands mainThread makeDirectory makeFile match matchDirectories matchFiles normalizeMsg normalizePath outputChannel outputFile preserveCore removeDirectory removeFile restoreState runAllTests saveState singleProcess skip skipDirectories skipFiles temporaryDirectory test testConstraint testsDirectory threadReap verbose viewFile workingDirectory}
test namespace-28.2 {NamespaceImportCmd, no args and just "-force"} {
namespace import -force
} {}
@@ -1098,15 +1151,15 @@ test namespace-28.3 {NamespaceImportCmd, arg is imported} {
} {::test_ns_2::cmd2}
test namespace-29.1 {NamespaceInscopeCmd, bad args} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
list [catch {namespace inscope} msg] $msg
} {1 {wrong # args: should be "namespace inscope name arg ?arg...?"}}
test namespace-29.2 {NamespaceInscopeCmd, bad args} {
list [catch {namespace inscope ::} msg] $msg
} {1 {wrong # args: should be "namespace inscope name arg ?arg...?"}}
-test namespace-29.3 {NamespaceInscopeCmd, specified ns must exist} {
- list [catch {namespace inscope test_ns_1 {set v}} msg] $msg
-} {1 {unknown namespace "test_ns_1" in inscope namespace command}}
+test namespace-29.3 {NamespaceInscopeCmd, specified ns must exist} -body {
+ namespace inscope test_ns_1 {set v}
+} -returnCodes error -result {namespace "test_ns_1" not found in "::"}
test namespace-29.4 {NamespaceInscopeCmd, simple case} {
namespace eval test_ns_1 {
variable v 747
@@ -1121,13 +1174,13 @@ test namespace-29.5 {NamespaceInscopeCmd, has lappend semantics} {
list [namespace inscope test_ns_1 cmd x y z] \
[namespace eval test_ns_1 [concat cmd [list x y z]]]
} {{::test_ns_1::cmd: v=747, args=x y z} {::test_ns_1::cmd: v=747, args=x y z}}
-test namespace-29.6 {NamespaceInscopeCmd, 1400572} knownBug {
+test namespace-29.6 {NamespaceInscopeCmd, 1400572} {
namespace inscope test_ns_1 {info level 0}
} {namespace inscope test_ns_1 {info level 0}}
test namespace-30.1 {NamespaceOriginCmd, bad args} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
list [catch {namespace origin} msg] $msg
} {1 {wrong # args: should be "namespace origin name"}}
test namespace-30.2 {NamespaceOriginCmd, bad args} {
@@ -1160,7 +1213,7 @@ test namespace-30.5 {NamespaceOriginCmd, imported command} {
} {::foreach ::test_ns_2::p ::test_ns_1::cmd1 ::test_ns_1::cmd2}
test namespace-31.1 {NamespaceParentCmd, bad args} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
list [catch {namespace parent a b} msg] $msg
} {1 {wrong # args: should be "namespace parent ?name?"}}
test namespace-31.2 {NamespaceParentCmd, no args} {
@@ -1176,12 +1229,12 @@ test namespace-31.3 {NamespaceParentCmd, namespace specified} {
[namespace parent test_ns_1::test_ns_2] \
[namespace eval test_ns_1::test_ns_2::test_ns_3 {namespace parent ::test_ns_1::test_ns_2}]
} {{} ::test_ns_1 ::test_ns_1}
-test namespace-31.4 {NamespaceParentCmd, bad namespace specified} {
- list [catch {namespace parent test_ns_1::test_ns_foo} msg] $msg
-} {1 {unknown namespace "test_ns_1::test_ns_foo" in namespace parent command}}
+test namespace-31.4 {NamespaceParentCmd, bad namespace specified} -body {
+ namespace parent test_ns_1::test_ns_foo
+} -returnCodes error -result {namespace "test_ns_1::test_ns_foo" not found in "::"}
test namespace-32.1 {NamespaceQualifiersCmd, bad args} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
list [catch {namespace qualifiers} msg] $msg
} {1 {wrong # args: should be "namespace qualifiers string"}}
test namespace-32.2 {NamespaceQualifiersCmd, bad args} {
@@ -1207,7 +1260,7 @@ test namespace-32.8 {NamespaceQualifiersCmd, odd number of :s} {
} {foo}
test namespace-33.1 {NamespaceTailCmd, bad args} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
list [catch {namespace tail} msg] $msg
} {1 {wrong # args: should be "namespace tail string"}}
test namespace-33.2 {NamespaceTailCmd, bad args} {
@@ -1233,15 +1286,15 @@ test namespace-33.8 {NamespaceTailCmd, odd number of :s} {
} {}
test namespace-34.1 {NamespaceWhichCmd, bad args} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
list [catch {namespace which} msg] $msg
} {1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}}
test namespace-34.2 {NamespaceWhichCmd, bad args} {
- list [catch {namespace which -fred} msg] $msg
-} {1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}}
-test namespace-34.3 {NamespaceWhichCmd, bad args} {
- list [catch {namespace which -command} msg] $msg
+ list [catch {namespace which -fred x} msg] $msg
} {1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}}
+test namespace-34.3 {NamespaceWhichCmd, single arg is always command name} {
+ namespace which -command
+} {}
test namespace-34.4 {NamespaceWhichCmd, bad args} {
list [catch {namespace which a b} msg] $msg
} {1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}}
@@ -1286,7 +1339,7 @@ test namespace-34.7 {NamespaceWhichCmd, variable lookup} {
} {::env ::test_ns_3::v3 ::test_ns_2::v2 0 {}}
test namespace-35.1 {FreeNsNameInternalRep, resulting ref count > 0} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_1 {
proc p {} {
namespace delete [namespace current]
@@ -1309,7 +1362,7 @@ test namespace-35.2 {FreeNsNameInternalRep, resulting ref count == 0} {
catch {unset x}
catch {unset y}
test namespace-36.1 {DupNsNameInternalRep} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_1 {}
set x "::test_ns_1"
list [namespace parent $x] [set y $x] [namespace parent $y]
@@ -1318,27 +1371,27 @@ catch {unset x}
catch {unset y}
test namespace-37.1 {SetNsNameFromAny, ns name found} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_1::test_ns_2 {}
namespace eval test_ns_1 {
namespace children ::test_ns_1
}
} {::test_ns_1::test_ns_2}
-test namespace-37.2 {SetNsNameFromAny, ns name not found} {
+test namespace-37.2 {SetNsNameFromAny, ns name not found} -body {
namespace eval test_ns_1 {
- list [catch {namespace children ::test_ns_1::test_ns_foo} msg] $msg
+ namespace children ::test_ns_1::test_ns_foo
}
-} {1 {unknown namespace "::test_ns_1::test_ns_foo" in namespace children command}}
+} -returnCodes error -result {namespace "::test_ns_1::test_ns_foo" not found}
test namespace-38.1 {UpdateStringOfNsName} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
;# Tcl_NamespaceObjCmd calls UpdateStringOfNsName to get subcmd name
list [namespace eval {} {namespace current}] \
[namespace eval {} {namespace current}]
} {:: ::}
test namespace-39.1 {NamespaceExistsCmd} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval ::test_ns_z::test_me { variable foo }
list [namespace exists ::] \
[namespace exists ::bogus_namespace] \
@@ -1399,7 +1452,7 @@ test namespace-41.2 {Shadowing byte-compiled commands, Bug: 231259} {
set res
} {New proc is called}
-test namespace-41.3 {Shadowing byte-compiled commands, Bug: 231259} {knownBug} {
+test namespace-41.3 {Shadowing byte-compiled commands, Bugs: 231259, 729692} {
set res {}
namespace eval ns {
variable b 0
@@ -1416,23 +1469,1200 @@ test namespace-41.3 {Shadowing byte-compiled commands, Bug: 231259} {knownBug} {
set res
} {{New proc is called} 0}
-# cleanup
-catch {rename cmd1 {}}
-catch {unset l}
-catch {unset msg}
-catch {unset trigger}
-eval namespace delete [namespace children :: test_ns_*]
-::tcltest::cleanupTests
-return
+# Ensembles (TIP#112)
+test namespace-42.1 {ensembles: basic} {
+ namespace eval ns {
+ namespace export x
+ proc x {} {format 1}
+ namespace ensemble create
+ }
+ list [info command ns] [ns x] [namespace delete ns] [info command ns]
+} {ns 1 {} {}}
+test namespace-42.2 {ensembles: basic} {
+ namespace eval ns {
+ namespace export x
+ proc x {} {format 1}
+ namespace ensemble create
+ }
+ rename ns foo
+ list [info command foo] [foo x] [namespace delete ns] [info command foo]
+} {foo 1 {} {}}
+test namespace-42.3 {ensembles: basic} {
+ namespace eval ns {
+ namespace export x*
+ proc x1 {} {format 1}
+ proc x2 {} {format 2}
+ namespace ensemble create
+ }
+ set result [list [ns x1] [ns x2]]
+ lappend result [catch {ns x} msg] $msg
+ rename ns {}
+ lappend result [info command ns::x1]
+ namespace delete ns
+ lappend result [info command ns::x1]
+} {1 2 1 {unknown or ambiguous subcommand "x": must be x1, or x2} ::ns::x1 {}}
+test namespace-42.4 {ensembles: basic} {
+ namespace eval ns {
+ namespace export y*
+ proc x1 {} {format 1}
+ proc x2 {} {format 2}
+ namespace ensemble create
+ }
+ set result [list [catch {ns x} msg] $msg]
+ namespace delete ns
+ set result
+} {1 {unknown subcommand "x": namespace ::ns does not export any commands}}
+test namespace-42.5 {ensembles: basic} {
+ namespace eval ns {
+ namespace export x*
+ proc x1 {} {format 1}
+ proc x2 {} {format 2}
+ proc x3 {} {format 3}
+ namespace ensemble create
+ }
+ set result [list [catch {ns x} msg] $msg]
+ namespace delete ns
+ set result
+} {1 {unknown or ambiguous subcommand "x": must be x1, x2, or x3}}
+test namespace-42.6 {ensembles: nested} {
+ namespace eval ns {
+ namespace export x*
+ namespace eval x0 {
+ proc z {} {format 0}
+ namespace export z
+ namespace ensemble create
+ }
+ proc x1 {} {format 1}
+ proc x2 {} {format 2}
+ proc x3 {} {format 3}
+ namespace ensemble create
+ }
+ set result [list [ns x0 z] [ns x1] [ns x2] [ns x3]]
+ namespace delete ns
+ set result
+} {0 1 2 3}
+test namespace-42.7 {ensembles: nested} {
+ namespace eval ns {
+ namespace export x*
+ namespace eval x0 {
+ proc z {} {list [info level] [info level 1]}
+ namespace export z
+ namespace ensemble create
+ }
+ proc x1 {} {format 1}
+ proc x2 {} {format 2}
+ proc x3 {} {format 3}
+ namespace ensemble create
+ }
+ set result [list [ns x0 z] [ns x1] [ns x2] [ns x3]]
+ namespace delete ns
+ set result
+} {{1 ::ns::x0::z} 1 2 3}
+test namespace-42.8 {ensembles: [Bug 1670091]} -setup {
+ proc demo args {}
+ variable target [list [namespace which demo] x]
+ proc trial args {variable target; string length $target}
+ trace add execution demo enter [namespace code trial]
+ namespace ensemble create -command foo -map [list bar $target]
+} -body {
+ foo bar
+} -cleanup {
+ unset target
+ rename demo {}
+ rename trial {}
+ rename foo {}
+} -result {}
+test namespace-43.1 {ensembles: dict-driven} {
+ namespace eval ns {
+ namespace export x*
+ proc x1 {} {format 1}
+ proc x2 {} {format 2}
+ namespace ensemble create -map {a x1 b x2}
+ }
+ set result [list [catch {ns c} msg] $msg [namespace ensemble exists ns]]
+ rename ns {}
+ lappend result [namespace ensemble exists ns]
+} {1 {unknown or ambiguous subcommand "c": must be a, or b} 1 0}
+test namespace-43.2 {ensembles: dict-driven} {
+ namespace eval ns {
+ namespace export x*
+ proc x1 {args} {list 1 $args}
+ proc x2 {args} {list 2 [llength $args]}
+ namespace ensemble create -map {
+ a ::ns::x1 b ::ns::x2 c {::ns::x1 .} d {::ns::x2 .}
+ }
+ }
+ set result [list [ns a] [ns b] [ns c] [ns c foo] [ns d] [ns d foo]]
+ namespace delete ns
+ set result
+} {{1 {}} {2 0} {1 .} {1 {. foo}} {2 1} {2 2}}
+set SETUP {
+ namespace eval ns {
+ namespace export a b
+ proc a args {format 1,[llength $args]}
+ proc b args {format 2,[llength $args]}
+ proc c args {format 3,[llength $args]}
+ proc d args {format 4,[llength $args]}
+ namespace ensemble create -subcommands {b c}
+ }
+}
+test namespace-43.3 {ensembles: list-driven} -setup $SETUP -body {
+ namespace delete ns
+} -result {}
+test namespace-43.4 {ensembles: list-driven} -setup $SETUP -body {
+ ns a foo bar boo spong wibble
+} -cleanup {namespace delete ns} -returnCodes error -result {unknown or ambiguous subcommand "a": must be b, or c}
+test namespace-43.5 {ensembles: list-driven} -setup $SETUP -body {
+ ns b foo bar boo spong wibble
+} -cleanup {namespace delete ns} -result 2,5
+test namespace-43.6 {ensembles: list-driven} -setup $SETUP -body {
+ ns c foo bar boo spong wibble
+} -cleanup {namespace delete ns} -result 3,5
+test namespace-43.7 {ensembles: list-driven} -setup $SETUP -body {
+ ns d foo bar boo spong wibble
+} -cleanup {namespace delete ns} -returnCodes error -result {unknown or ambiguous subcommand "d": must be b, or c}
+set SETUP {
+ namespace eval ns {
+ namespace export a b
+ proc a args {format 1,[llength $args]}
+ proc b args {format 2,[llength $args]}
+ proc c args {format 3,[llength $args]}
+ proc d args {format 4,[llength $args]}
+ namespace ensemble create -subcommands {b c} -map {c ::ns::d}
+ }
+}
+test namespace-43.8 {ensembles: list-and-map-driven} -setup $SETUP -body {
+ namespace delete ns
+} -result {}
+test namespace-43.9 {ensembles: list-and-map-driven} -setup $SETUP -body {
+ ns a foo bar boo spong wibble
+} -cleanup {namespace delete ns} -returnCodes error -result {unknown or ambiguous subcommand "a": must be b, or c}
+test namespace-43.10 {ensembles: list-and-map-driven} -setup $SETUP -body {
+ ns b foo bar boo spong wibble
+} -cleanup {namespace delete ns} -result 2,5
+test namespace-43.11 {ensembles: list-and-map-driven} -setup $SETUP -body {
+ ns c foo bar boo spong wibble
+} -cleanup {namespace delete ns} -result 4,5
+test namespace-43.12 {ensembles: list-and-map-driven} -setup $SETUP -body {
+ ns d foo bar boo spong wibble
+} -cleanup {namespace delete ns} -returnCodes error -result {unknown or ambiguous subcommand "d": must be b, or c}
+set SETUP {
+ namespace eval ns {
+ namespace export *
+ proc foo args {format bar}
+ proc spong args {format wibble}
+ namespace ensemble create -prefixes off
+ }
+}
+test namespace-43.13 {ensembles: turn off prefixes} -setup $SETUP -body {
+ namespace delete ns
+} -result {}
+test namespace-43.14 {ensembles: turn off prefixes} -setup $SETUP -body {
+ ns fo
+} -cleanup {namespace delete ns} -returnCodes error -result {unknown subcommand "fo": must be foo, or spong}
+test namespace-43.15 {ensembles: turn off prefixes} -setup $SETUP -body {
+ ns foo
+} -cleanup {namespace delete ns} -result bar
+test namespace-43.16 {ensembles: turn off prefixes} -setup $SETUP -body {
+ ns s
+} -cleanup {namespace delete ns} -returnCodes error -result {unknown subcommand "s": must be foo, or spong}
+test namespace-43.17 {ensembles: turn off prefixes} -setup $SETUP -body {
+ ns spong
+} -cleanup {namespace delete ns} -result wibble
+
+test namespace-44.1 {ensemble: errors} {
+ list [catch {namespace ensemble} msg] $msg
+} {1 {wrong # args: should be "namespace ensemble subcommand ?arg ...?"}}
+test namespace-44.2 {ensemble: errors} {
+ list [catch {namespace ensemble ?} msg] $msg
+} {1 {bad subcommand "?": must be configure, create, or exists}}
+test namespace-44.3 {ensemble: errors} {
+ namespace eval ns {
+ list [catch {namespace ensemble create -map x} msg] $msg
+ }
+} {1 {missing value to go with key}}
+test namespace-44.4 {ensemble: errors} {
+ namespace eval ns {
+ list [catch {namespace ensemble create -map {x {}}} msg] $msg
+ }
+} {1 {ensemble subcommand implementations must be non-empty lists}}
+test namespace-44.5 {ensemble: errors} -setup {
+ namespace ensemble create -command foobar -subcommands {foobarcget foobarconfigure}
+} -body {
+ foobar foobarcon
+} -cleanup {
+ rename foobar {}
+} -returnCodes error -result {invalid command name "::foobarconfigure"}
+test namespace-45.1 {ensemble: introspection} {
+ namespace eval ns {
+ namespace export x
+ proc x {} {}
+ namespace ensemble create
+ set ::result [namespace ensemble configure ::ns]
+ }
+ namespace delete ns
+ set result
+} {-map {} -namespace ::ns -prefixes 1 -subcommands {} -unknown {}}
+test namespace-45.2 {ensemble: introspection} {
+ namespace eval ns {
+ namespace export x
+ proc x {} {}
+ namespace ensemble create -map {A x}
+ set ::result [namespace ensemble configure ::ns -map]
+ }
+ namespace delete ns
+ set result
+} {A ::ns::x}
+test namespace-46.1 {ensemble: modification} {
+ namespace eval ns {
+ namespace export x
+ proc x {} {format 123}
+ # Ensemble maps A->x
+ namespace ensemble create -command ns -map {A ::ns::x}
+ set ::result [list [namespace ensemble configure ns -map] [ns A]]
+ # Ensemble maps B->x
+ namespace ensemble configure ns -map {B ::ns::x}
+ lappend ::result [namespace ensemble configure ns -map] [ns B]
+ # Ensemble maps x->x
+ namespace ensemble configure ns -map {}
+ lappend ::result [namespace ensemble configure ns -map] [ns x]
+ }
+ namespace delete ns
+ set result
+} {{A ::ns::x} 123 {B ::ns::x} 123 {} 123}
+test namespace-46.2 {ensemble: ensembles really use current export list} {
+ namespace eval ns {
+ namespace export x1
+ proc x1 {} {format 1}
+ proc x2 {} {format 1}
+ namespace ensemble create
+ }
+ catch {ns ?} msg; set result [list $msg]
+ namespace eval ns {namespace export x*}
+ catch {ns ?} msg; lappend result $msg
+ rename ns::x1 {}
+ catch {ns ?} msg; lappend result $msg
+ namespace delete ns
+ set result
+} {{unknown or ambiguous subcommand "?": must be x1} {unknown or ambiguous subcommand "?": must be x1, or x2} {unknown or ambiguous subcommand "?": must be x2}}
+test namespace-46.3 {ensemble: implementation errors} {
+ namespace eval ns {
+ variable count 0
+ namespace ensemble create -map {
+ a {::lappend ::result}
+ b {::incr ::ns::count}
+ }
+ }
+ set result {}
+ lappend result [catch { ns } msg] $msg
+ ns a [ns b 10]
+ catch {rename p {}}
+ rename ns p
+ p a [p b 3000]
+ lappend result $ns::count
+ namespace delete ns
+ lappend result [info command p]
+} {1 {wrong # args: should be "ns subcommand ?argument ...?"} 10 3010 3010 {}}
+test namespace-46.4 {ensemble: implementation errors} {
+ namespace eval ns {
+ namespace ensemble create
+ }
+ set result [info command ns]
+ lappend result [catch {ns ?} msg] $msg
+ namespace delete ns
+ set result
+} {ns 1 {unknown subcommand "?": namespace ::ns does not export any commands}}
+test namespace-46.5 {ensemble: implementation errors} {
+ namespace eval ns {
+ namespace ensemble create -map {makeError ::error}
+ }
+ list [catch {ns makeError "an error happened"} msg] $msg $::errorInfo [namespace delete ns]
+} {1 {an error happened} {an error happened
+ while executing
+"ns makeError "an error happened""} {}}
+test namespace-46.6 {ensemble: implementation renames/deletes itself} {
+ namespace eval ns {
+ namespace ensemble create -map {to ::rename}
+ }
+ ns to ns foo
+ foo to foo bar
+ bar to bar spong
+ spong to spong {}
+ namespace delete ns
+} {}
+test namespace-46.7 {ensemble: implementation deletes its namespace} {
+ namespace eval ns {
+ namespace ensemble create -map {kill {::namespace delete}}
+ }
+ ns kill ns
+} {}
+test namespace-46.8 {ensemble: implementation deletes its namespace} {
+ namespace eval ns {
+ namespace export *
+ proc foo {} {
+ variable x 1
+ bar
+ # Tricky; what is the correct return value anyway?
+ info exist x
+ }
+ proc bar {} {
+ namespace delete [namespace current]
+ }
+ namespace ensemble create
+ }
+ list [ns foo] [info exist ns::x]
+} {1 0}
+test namespace-46.9 {ensemble: configuring really configures things} {
+ namespace eval ns {
+ namespace ensemble create -map {a a} -prefixes 0
+ }
+ set result [list [catch {ns x} msg] $msg]
+ namespace ensemble configure ns -map {b b}
+ lappend result [catch {ns x} msg] $msg
+ namespace delete ns
+ set result
+} {1 {unknown subcommand "x": must be a} 1 {unknown subcommand "x": must be b}}
+test namespace-47.1 {ensemble: unknown handler} {
+ set log {}
+ namespace eval ns {
+ namespace export {[a-z]*}
+ proc Magic {ensemble subcmd args} {
+ global log
+ if {[string match {[a-z]*} $subcmd]} {
+ lappend log "making $subcmd"
+ proc $subcmd args {
+ global log
+ lappend log "running [info level 0]"
+ llength $args
+ }
+ } else {
+ lappend log "unknown $subcmd - args = $args"
+ return -code error \
+ "unknown or protected subcommand \"$subcmd\""
+ }
+ }
+ namespace ensemble create -unknown ::ns::Magic
+ }
+ set result {}
+ lappend result [catch {ns a b c} msg] $msg
+ lappend result [catch {ns a b c} msg] $msg
+ lappend result [catch {ns b c d} msg] $msg
+ lappend result [catch {ns c d e} msg] $msg
+ lappend result [catch {ns Magic foo bar spong wibble} msg] $msg
+ list $result [lsort [info commands ::ns::*]] $log [namespace delete ns]
+} {{0 2 0 2 0 2 0 2 1 {unknown or protected subcommand "Magic"}} {::ns::Magic ::ns::a ::ns::b ::ns::c} {{making a} {running ::ns::a b c} {running ::ns::a b c} {making b} {running ::ns::b c d} {making c} {running ::ns::c d e} {unknown Magic - args = foo bar spong wibble}} {}}
+test namespace-47.2 {ensemble: unknown handler} {
+ namespace eval ns {
+ namespace export {[a-z]*}
+ proc Magic {ensemble subcmd args} {
+ error foobar
+ }
+ namespace ensemble create -unknown ::ns::Magic
+ }
+ list [catch {ns spong} msg] $msg $::errorInfo [namespace delete ns]
+} {1 foobar {foobar
+ while executing
+"error foobar"
+ (procedure "::ns::Magic" line 2)
+ invoked from within
+"::ns::Magic ::ns spong"
+ (ensemble unknown subcommand handler)
+ invoked from within
+"ns spong"} {}}
+test namespace-47.3 {ensemble: unknown handler} {
+ namespace eval ns {
+ variable count 0
+ namespace export {[a-z]*}
+ proc a {} {}
+ proc c {} {}
+ proc Magic {ensemble subcmd args} {
+ variable count
+ incr count
+ proc b {} {}
+ }
+ namespace ensemble create -unknown ::ns::Magic
+ }
+ list [catch {ns spong} msg] $msg $ns::count [namespace delete ns]
+} {1 {unknown or ambiguous subcommand "spong": must be a, b, or c} 1 {}}
+test namespace-47.4 {ensemble: unknown handler} {
+ namespace eval ns {
+ namespace export {[a-z]*}
+ proc Magic {ensemble subcmd args} {
+ return -code break
+ }
+ namespace ensemble create -unknown ::ns::Magic
+ }
+ list [catch {ns spong} msg] $msg $::errorInfo [namespace delete ns]
+} {1 {unknown subcommand handler returned bad code: break} {unknown subcommand handler returned bad code: break
+ result of ensemble unknown subcommand handler: ::ns::Magic ::ns spong
+ invoked from within
+"ns spong"} {}}
+test namespace-47.5 {ensemble: unknown handler} {
+ namespace ensemble create -command foo -unknown bar
+ proc bar {args} {
+ global result target
+ lappend result "LOG $args"
+ return $target
+ }
+ set result {}
+ set target {}
+ lappend result [catch {foo bar} msg] $msg
+ set target {lappend result boo hoo}
+ lappend result [catch {foo bar} msg] $msg [namespace ensemble config foo]
+ rename foo {}
+ set result
+} {{LOG ::foo bar} 1 {unknown subcommand "bar": namespace :: does not export any commands} {LOG ::foo bar} boo hoo 0 {{LOG ::foo bar} 1 {unknown subcommand "bar": namespace :: does not export any commands} {LOG ::foo bar} boo hoo} {-map {} -namespace :: -prefixes 1 -subcommands {} -unknown bar}}
+test namespace-47.6 {ensemble: unknown handler} {
+ namespace ensemble create -command foo -unknown bar
+ proc bar {args} {
+ return "\{"
+ }
+ set result [list [catch {foo bar} msg] $msg $::errorInfo]
+ rename foo {}
+ set result
+} {1 {unmatched open brace in list} {unmatched open brace in list
+ while parsing result of ensemble unknown subcommand handler
+ invoked from within
+"foo bar"}}
+test namespace-47.7 {ensemble: unknown handler, commands with spaces} {
+ namespace ensemble create -command foo -unknown bar
+ proc bar {args} {
+ list ::set ::x [join $args |]
+ }
+ set result [foo {one two three}]
+ rename foo {}
+ set result
+} {::foo|one two three}
+test namespace-47.8 {ensemble: unknown handler, commands with spaces} {
+ namespace ensemble create -command foo -unknown {bar boo}
+ proc bar {args} {
+ list ::set ::x [join $args |]
+ }
+ set result [foo {one two three}]
+ rename foo {}
+ set result
+} {boo|::foo|one two three}
+
+test namespace-48.1 {ensembles and namespace import: unknown handler} {
+ namespace eval foo {
+ namespace export bar
+ namespace ensemble create -command bar -unknown ::foo::u -subcomm x
+ proc u {ens args} {
+ global result
+ lappend result $ens $args
+ namespace ensemble config $ens -subcommand {x y}
+ }
+ proc u2 {ens args} {
+ global result
+ lappend result $ens $args
+ namespace ensemble config ::bar -subcommand {x y z}
+ }
+ proc x args {
+ global result
+ lappend result XXX $args
+ }
+ proc y args {
+ global result
+ lappend result YYY $args
+ }
+ proc z args {
+ global result
+ lappend result ZZZ $args
+ }
+ }
+ namespace import -force foo::bar
+ set result [list [namespace ensemble config bar]]
+ bar x 123
+ bar y 456
+ namespace ensemble config bar -unknown ::foo::u2
+ bar z 789
+ namespace delete foo
+ set result
+} {{-map {} -namespace ::foo -prefixes 1 -subcommands x -unknown ::foo::u} XXX 123 ::foo::bar {y 456} YYY 456 ::foo::bar {z 789} ZZZ 789}
+test namespace-48.2 {ensembles and namespace import: exists} {
+ namespace eval foo {
+ namespace ensemble create -command ::foo::bar
+ namespace export bar
+ }
+ set result [namespace ensemble exist foo::bar]
+ lappend result [namespace ensemble exist bar]
+ namespace import foo::bar
+ lappend result [namespace ensemble exist bar]
+ rename foo::bar foo::bar2
+ lappend result [namespace ensemble exist bar] \
+ [namespace ensemble exist spong]
+ rename bar spong
+ lappend result [namespace ensemble exist bar] \
+ [namespace ensemble exist spong]
+ rename foo::bar2 {}
+ lappend result [namespace ensemble exist spong]
+ namespace delete foo
+ set result
+} {1 0 1 1 0 0 1 0}
+test namespace-48.3 {ensembles and namespace import: config} {
+ catch {rename spong {}}
+ namespace eval foo {
+ namespace ensemble create -command ::foo::bar
+ namespace export bar boo
+ proc boo {} {}
+ }
+ namespace import foo::bar foo::boo
+ set result [namespace ensemble config bar -namespace]
+ lappend result [catch {namespace ensemble config boo} msg] $msg
+ lappend result [catch {namespace ensemble config spong} msg] $msg
+ namespace delete foo
+ set result
+} {::foo 1 {"boo" is not an ensemble command} 1 {unknown command "spong"}}
+
+test namespace-49.1 {ensemble subcommand caching} -body {
+ namespace ens cre -command a -map {b {lappend result 1}}
+ namespace ens cre -command c -map {b {lappend result 2}}
+ proc x {} {a b; c b; a b; c b}
+ x
+} -result {1 2 1 2} -cleanup {
+ rename a {}
+ rename c {}
+ rename x {}
+}
+test namespace-49.2 {strange delete crash} -body {
+ namespace eval foo {namespace ensemble create -command ::bar}
+ trace add command ::bar delete DeleteTrace
+ proc DeleteTrace {old new op} {
+ trace remove command ::bar delete DeleteTrace
+ rename $old ""
+ # This next line caused a bus error in [Bug 1220058]
+ namespace delete foo
+ }
+ rename ::bar ""
+} -result "" -cleanup {
+ rename DeleteTrace ""
+}
+test namespace-50.1 {ensembles affect proc arguments error messages} -body {
+ namespace ens cre -command a -map {b {bb foo}}
+ proc bb {c d {e f} args} {list $c $args}
+ a b
+} -returnCodes error -result "wrong # args: should be \"a b d ?e? ...\"" -cleanup {
+ rename a {}
+ rename bb {}
+}
+test namespace-50.2 {ensembles affect WrongNumArgs error messages} -body {
+ namespace ens cre -command a -map {b {string is}}
+ a b boolean
+} -returnCodes error -result "wrong # args: should be \"a b class ?-strict? ?-failindex var? str\"" -cleanup {
+ rename a {}
+}
+test namespace-50.3 {chained ensembles affect error messages} -body {
+ namespace ens cre -command a -map {b c}
+ namespace ens cre -command c -map {d e}
+ proc e f {}
+ a b d
+} -returnCodes error -result "wrong # args: should be \"a b d f\"" -cleanup {
+ rename a {}
+}
+test namespace-50.4 {chained ensembles affect error messages} -body {
+ namespace ens cre -command a -map {b {c d}}
+ namespace ens cre -command c -map {d {e f}}
+ proc e f {}
+ a b d
+} -returnCodes error -result "wrong # args: should be \"a b\"" -cleanup {
+ rename a {}
+}
+test namespace-51.1 {name resolution path control} -body {
+ namespace eval ::test_ns_1 {
+ namespace eval test_ns_2 {
+ proc pathtestA {} {
+ ::return [pathtestB],[pathtestC],[pathtestD],[namespace path]
+ }
+ proc pathtestC {} {
+ ::return 2
+ }
+ }
+ proc pathtestB {} {
+ return 1
+ }
+ proc pathtestC {} {
+ return 1
+ }
+ namespace path ::test_ns_1
+ }
+ proc ::pathtestB {} {
+ return global
+ }
+ proc ::pathtestD {} {
+ return global
+ }
+ test_ns_1::test_ns_2::pathtestA
+} -result "global,2,global," -cleanup {
+ namespace delete ::test_ns_1
+ catch {rename ::pathtestB {}}
+ catch {rename ::pathtestD {}}
+}
+test namespace-51.2 {name resolution path control} -body {
+ namespace eval ::test_ns_1 {
+ namespace eval test_ns_2 {
+ namespace path ::test_ns_1
+ proc pathtestA {} {
+ ::return [pathtestB],[pathtestC],[pathtestD],[namespace path]
+ }
+ proc pathtestC {} {
+ ::return 2
+ }
+ }
+ proc pathtestB {} {
+ return 1
+ }
+ proc pathtestC {} {
+ return 1
+ }
+ }
+ proc ::pathtestB {} {
+ return global
+ }
+ proc ::pathtestD {} {
+ return global
+ }
+ ::test_ns_1::test_ns_2::pathtestA
+} -result "1,2,global,::test_ns_1" -cleanup {
+ namespace delete ::test_ns_1
+ catch {rename ::pathtestB {}}
+ catch {rename ::pathtestD {}}
+}
+test namespace-51.3 {name resolution path control} -body {
+ namespace eval ::test_ns_1 {
+ namespace eval test_ns_2 {
+ proc pathtestA {} {
+ ::return [pathtestB],[pathtestC],[pathtestD],[namespace path]
+ }
+ proc pathtestC {} {
+ ::return 2
+ }
+ }
+ proc pathtestB {} {
+ return 1
+ }
+ proc pathtestC {} {
+ return 1
+ }
+ }
+ proc ::pathtestB {} {
+ return global
+ }
+ proc ::pathtestD {} {
+ return global
+ }
+ set result [::test_ns_1::test_ns_2::pathtestA]
+ namespace eval ::test_ns_1::test_ns_2 {
+ namespace path ::test_ns_1
+ }
+ lappend result [::test_ns_1::test_ns_2::pathtestA]
+ rename ::test_ns_1::pathtestB {}
+ lappend result [::test_ns_1::test_ns_2::pathtestA]
+} -result "global,2,global, 1,2,global,::test_ns_1 global,2,global,::test_ns_1" -cleanup {
+ namespace delete ::test_ns_1
+ catch {rename ::pathtestB {}}
+ catch {rename ::pathtestD {}}
+}
+test namespace-51.4 {name resolution path control} -body {
+ namespace eval ::test_ns_1 {
+ namespace eval test_ns_2 {
+ proc pathtestA {} {
+ ::return [pathtestB],[pathtestC],[pathtestD],[namespace path]
+ }
+ proc pathtestC {} {
+ ::return 2
+ }
+ }
+ proc pathtestB {} {
+ return 1
+ }
+ proc pathtestC {} {
+ return 1
+ }
+ }
+ proc ::pathtestB {} {
+ return global
+ }
+ proc ::pathtestD {} {
+ return global
+ }
+ set result [::test_ns_1::test_ns_2::pathtestA]
+ namespace eval ::test_ns_1::test_ns_2 {
+ namespace path ::test_ns_1
+ }
+ lappend result [::test_ns_1::test_ns_2::pathtestA]
+ namespace eval ::test_ns_1::test_ns_2 {
+ namespace path {}
+ }
+ lappend result [::test_ns_1::test_ns_2::pathtestA]
+} -result "global,2,global, 1,2,global,::test_ns_1 global,2,global," -cleanup {
+ namespace delete ::test_ns_1
+ catch {rename ::pathtestB {}}
+ catch {rename ::pathtestD {}}
+}
+test namespace-51.5 {name resolution path control} -body {
+ namespace eval ::test_ns_1 {
+ namespace eval test_ns_2 {
+ proc pathtestA {} {
+ ::return [pathtestB],[pathtestC],[pathtestD],[namespace path]
+ }
+ proc pathtestC {} {
+ ::return 2
+ }
+ namespace path ::test_ns_1
+ }
+ proc pathtestB {} {
+ return 1
+ }
+ proc pathtestC {} {
+ return 1
+ }
+ proc pathtestD {} {
+ return 1
+ }
+ }
+ proc ::pathtestB {} {
+ return global
+ }
+ proc ::pathtestD {} {
+ return global
+ }
+ set result [::test_ns_1::test_ns_2::pathtestA]
+ namespace eval ::test_ns_1::test_ns_2 {
+ namespace path {:: ::test_ns_1}
+ }
+ lappend result [::test_ns_1::test_ns_2::pathtestA]
+ rename ::test_ns_1::test_ns_2::pathtestC {}
+ lappend result [::test_ns_1::test_ns_2::pathtestA]
+} -result "1,2,1,::test_ns_1 {global,2,global,:: ::test_ns_1} {global,1,global,:: ::test_ns_1}" -cleanup {
+ namespace delete ::test_ns_1
+ catch {rename ::pathtestB {}}
+ catch {rename ::pathtestD {}}
+}
+test namespace-51.6 {name resolution path control} -body {
+ namespace eval ::test_ns_1 {
+ namespace eval test_ns_2 {
+ proc pathtestA {} {
+ ::return [pathtestB],[pathtestC],[pathtestD],[namespace path]
+ }
+ proc pathtestC {} {
+ ::return 2
+ }
+ namespace path ::test_ns_1
+ }
+ proc pathtestB {} {
+ return 1
+ }
+ proc pathtestC {} {
+ return 1
+ }
+ proc pathtestD {} {
+ return 1
+ }
+ }
+ proc ::pathtestB {} {
+ return global
+ }
+ proc ::pathtestD {} {
+ return global
+ }
+ set result [::test_ns_1::test_ns_2::pathtestA]
+ namespace eval ::test_ns_1::test_ns_2 {
+ namespace path {:: ::test_ns_1}
+ }
+ lappend result [::test_ns_1::test_ns_2::pathtestA]
+ rename ::test_ns_1::test_ns_2::pathtestC {}
+ lappend result [::test_ns_1::test_ns_2::pathtestA]
+ proc ::pathtestC {} {
+ return global
+ }
+ lappend result [::test_ns_1::test_ns_2::pathtestA]
+} -result "1,2,1,::test_ns_1 {global,2,global,:: ::test_ns_1} {global,1,global,:: ::test_ns_1} {global,global,global,:: ::test_ns_1}" -cleanup {
+ namespace delete ::test_ns_1
+ catch {rename ::pathtestB {}}
+ catch {rename ::pathtestD {}}
+}
+test namespace-51.7 {name resolution path control} -body {
+ namespace eval ::test_ns_1 {
+ }
+ namespace eval ::test_ns_2 {
+ namespace path ::test_ns_1
+ proc getpath {} {namespace path}
+ }
+ list [::test_ns_2::getpath] [namespace delete ::test_ns_1] [::test_ns_2::getpath]
+} -result {::test_ns_1 {} {}} -cleanup {
+ catch {namespace delete ::test_ns_1}
+ namespace delete ::test_ns_2
+}
+test namespace-51.8 {name resolution path control} -body {
+ namespace eval ::test_ns_1 {
+ }
+ namespace eval ::test_ns_2 {
+ }
+ namespace eval ::test_ns_3 {
+ }
+ namespace eval ::test_ns_4 {
+ namespace path {::test_ns_1 ::test_ns_2 ::test_ns_3}
+ proc getpath {} {namespace path}
+ }
+ list [::test_ns_4::getpath] [namespace delete ::test_ns_2] [::test_ns_4::getpath]
+} -result {{::test_ns_1 ::test_ns_2 ::test_ns_3} {} {::test_ns_1 ::test_ns_3}} -cleanup {
+ catch {namespace delete ::test_ns_1}
+ catch {namespace delete ::test_ns_2}
+ catch {namespace delete ::test_ns_3}
+ catch {namespace delete ::test_ns_4}
+}
+test namespace-51.9 {name resolution path control} -body {
+ namespace eval ::test_ns_1 {
+ }
+ namespace eval ::test_ns_2 {
+ }
+ namespace eval ::test_ns_3 {
+ }
+ namespace eval ::test_ns_4 {
+ namespace path {::test_ns_1 ::test_ns_2 ::test_ns_3}
+ proc getpath {} {namespace path}
+ }
+ list [::test_ns_4::getpath] [namespace delete ::test_ns_2] [namespace eval ::test_ns_2 {}] [::test_ns_4::getpath]
+} -result {{::test_ns_1 ::test_ns_2 ::test_ns_3} {} {} {::test_ns_1 ::test_ns_3}} -cleanup {
+ catch {namespace delete ::test_ns_1}
+ catch {namespace delete ::test_ns_2}
+ catch {namespace delete ::test_ns_3}
+ catch {namespace delete ::test_ns_4}
+}
+test namespace-51.10 {name resolution path control} -body {
+ namespace eval ::test_ns_1 {
+ namespace path does::not::exist
+ }
+} -returnCodes error -result {namespace "does::not::exist" not found in "::test_ns_1"} -cleanup {
+ catch {namespace delete ::test_ns_1}
+}
+test namespace-51.11 {name resolution path control} -body {
+ namespace eval ::test_ns_1 {
+ proc foo {} {return 1}
+ }
+ namespace eval ::test_ns_2 {
+ proc foo {} {return 2}
+ }
+ namespace eval ::test_ns_3 {
+ namespace path ::test_ns_1
+ }
+ namespace eval ::test_ns_4 {
+ namespace path {::test_ns_3 ::test_ns_2}
+ foo
+ }
+} -result 2 -cleanup {
+ catch {namespace delete ::test_ns_1}
+ catch {namespace delete ::test_ns_2}
+ catch {namespace delete ::test_ns_3}
+ catch {namespace delete ::test_ns_4}
+}
+test namespace-51.12 {name resolution path control} -body {
+ namespace eval ::test_ns_1 {
+ proc foo {} {return 1}
+ }
+ namespace eval ::test_ns_2 {
+ proc foo {} {return 2}
+ }
+ namespace eval ::test_ns_3 {
+ namespace path ::test_ns_1
+ }
+ namespace eval ::test_ns_4 {
+ namespace path {::test_ns_3 ::test_ns_2}
+ list [foo] [namespace delete ::test_ns_3] [foo]
+ }
+} -result {2 {} 2} -cleanup {
+ catch {namespace delete ::test_ns_1}
+ catch {namespace delete ::test_ns_2}
+ catch {namespace delete ::test_ns_3}
+ catch {namespace delete ::test_ns_4}
+}
+test namespace-51.13 {name resolution path control} -body {
+ set ::result {}
+ namespace eval ::test_ns_1 {
+ proc foo {} {lappend ::result 1}
+ }
+ namespace eval ::test_ns_2 {
+ proc foo {} {lappend ::result 2}
+ trace add command foo delete {namespace eval ::test_ns_3 foo;#}
+ }
+ namespace eval ::test_ns_3 {
+ proc foo {} {
+ lappend ::result 3
+ namespace delete [namespace current]
+ ::test_ns_4::bar
+ }
+ }
+ namespace eval ::test_ns_4 {
+ namespace path {::test_ns_2 ::test_ns_3 ::test_ns_1}
+ proc bar {} {
+ list [foo] [namespace delete ::test_ns_2] [foo]
+ }
+ bar
+ }
+ # Should the result be "2 {} {2 3 2 1}" instead?
+} -result {2 {} {2 3 1 1}} -cleanup {
+ catch {namespace delete ::test_ns_1}
+ catch {namespace delete ::test_ns_2}
+ catch {namespace delete ::test_ns_3}
+ catch {namespace delete ::test_ns_4}
+}
+test namespace-51.14 {name resolution path control} -body {
+ foreach cmd [info commands foo*] {
+ rename $cmd {}
+ }
+ proc foo0 {} {}
+ namespace eval ::test_ns_1 {
+ proc foo1 {} {}
+ }
+ namespace eval ::test_ns_2 {
+ proc foo2 {} {}
+ }
+ namespace eval ::test_ns_3 {
+ variable result {}
+ lappend result [info commands foo*]
+ namespace path {::test_ns_1 ::test_ns_2}
+ lappend result [info commands foo*]
+ proc foo2 {} {}
+ lappend result [info commands foo*]
+ rename foo2 {}
+ lappend result [info commands foo*]
+ namespace delete ::test_ns_1
+ lappend result [info commands foo*]
+ }
+} -result {foo0 {foo1 foo2 foo0} {foo2 foo1 foo0} {foo1 foo2 foo0} {foo2 foo0}} -cleanup {
+ catch {namespace delete ::test_ns_1}
+ catch {namespace delete ::test_ns_2}
+ catch {namespace delete ::test_ns_3}
+}
+test namespace-51.15 {namespace resolution path control} -body {
+ namespace eval ::test_ns_2 {
+ proc foo {} {return 2}
+ }
+ namespace eval ::test_ns_1 {
+ namespace eval test_ns_2 {
+ proc foo {} {return 1_2}
+ }
+ namespace eval test_ns_3 {
+ namespace path ::test_ns_1
+ test_ns_2::foo
+ }
+ }
+} -result 1_2 -cleanup {
+ namespace delete ::test_ns_1
+ namespace delete ::test_ns_2
+}
+test namespace-51.16 {Bug 1566526} {
+ interp create slave
+ slave eval namespace eval demo namespace path ::
+ interp delete slave
+} {}
+test namespace-51.17 {Bug 3185407} -setup {
+ namespace eval ::test_ns_1 {}
+} -body {
+ namespace eval ::test_ns_1 {
+ variable result {}
+ namespace eval ns {proc foo {} {}}
+ namespace eval ns2 {proc foo {} {}}
+ namespace path {ns ns2}
+ variable x foo
+ lappend result [namespace which $x]
+ proc foo {} {}
+ lappend result [namespace which $x]
+ }
+} -cleanup {
+ namespace delete ::test_ns_1
+} -result {::test_ns_1::ns::foo ::test_ns_1::foo}
+
+# TIP 181 - namespace unknown tests
+test namespace-52.1 {unknown: default handler ::unknown} {
+ set result [list [namespace eval foobar { namespace unknown }]]
+ lappend result [namespace eval :: { namespace unknown }]
+ namespace delete foobar
+ set result
+} {{} ::unknown}
+test namespace-52.2 {unknown: default resolution global} {
+ proc ::foo {} { return "GLOBAL" }
+ namespace eval ::bar { proc foo {} { return "NAMESPACE" } }
+ namespace eval ::bar::jim { proc test {} { foo } }
+ set result [::bar::jim::test]
+ namespace delete ::bar
+ rename ::foo {}
+ set result
+} {GLOBAL}
+test namespace-52.3 {unknown: default resolution local} {
+ proc ::foo {} { return "GLOBAL" }
+ namespace eval ::bar {
+ proc foo {} { return "NAMESPACE" }
+ proc test {} { foo }
+ }
+ set result [::bar::test]
+ namespace delete ::bar
+ rename ::foo {}
+ set result
+} {NAMESPACE}
+test namespace-52.4 {unknown: set handler} {
+ namespace eval foo {
+ namespace unknown [list dispatch]
+ proc dispatch {args} { return $args }
+ proc test {} {
+ UnknownCmd a b c
+ }
+ }
+ set result [foo::test]
+ namespace delete foo
+ set result
+} {UnknownCmd a b c}
+test namespace-52.5 {unknown: search path before unknown is unaltered} {
+ proc ::test2 {args} { return "TEST2: $args" }
+ namespace eval foo {
+ namespace unknown [list dispatch]
+ proc dispatch {args} { return "UNKNOWN: $args" }
+ proc test1 {args} { return "TEST1: $args" }
+ proc test {} {
+ set result [list [test1 a b c]]
+ lappend result [test2 a b c]
+ lappend result [test3 a b c]
+ return $result
+ }
+ }
+ set result [foo::test]
+ namespace delete foo
+ rename ::test2 {}
+ set result
+} {{TEST1: a b c} {TEST2: a b c} {UNKNOWN: test3 a b c}}
+test namespace-52.6 {unknown: deleting handler restores default} {
+ rename ::unknown ::_unknown_orig
+ proc ::unknown {args} { return "DEFAULT: $args" }
+ namespace eval foo {
+ namespace unknown dummy
+ namespace unknown {}
+ }
+ set result [namespace eval foo { dummy a b c }]
+ rename ::unknown {}
+ rename ::_unknown_orig ::unknown
+ namespace delete foo
+ set result
+} {DEFAULT: dummy a b c}
+test namespace-52.7 {unknown: setting global unknown handler} {
+ proc ::myunknown {args} { return "MYUNKNOWN: $args" }
+ namespace eval :: { namespace unknown ::myunknown }
+ set result [namespace eval foo { dummy a b c }]
+ namespace eval :: { namespace unknown {} }
+ rename ::myunknown {}
+ namespace delete foo
+ set result
+} {MYUNKNOWN: dummy a b c}
+test namespace-52.8 {unknown: destroying and redefining global namespace} {
+ set i [interp create]
+ $i hide proc
+ $i hide namespace
+ $i hide return
+ $i invokehidden namespace delete ::
+ $i expose return
+ $i invokehidden proc unknown args { return "FINE" }
+ $i eval { foo bar bob }
+} {FINE}
+test namespace-52.9 {unknown: refcounting} -setup {
+ proc this args {
+ unset args ;# stop sharing
+ set copy [namespace unknown]
+ string length $copy ;# shimmer away list rep
+ info level 0
+ }
+ set handler [namespace unknown]
+ namespace unknown {this is a test}
+ catch {rename noSuchCommand {}}
+} -body {
+ noSuchCommand
+} -cleanup {
+ namespace unknown $handler
+ rename this {}
+} -result {this is a test noSuchCommand}
+testConstraint testevalobjv [llength [info commands testevalobjv]]
+test namespace-52.10 {unknown: with TCL_EVAL_GLOBAL} -constraints {
+ testevalobjv
+} -setup {
+ rename ::unknown unknown.save
+ proc ::unknown args {
+ set caller [uplevel 1 {namespace current}]
+ namespace eval $caller {
+ variable foo
+ return $foo
+ }
+ }
+ catch {rename ::noSuchCommand {}}
+} -body {
+ namespace eval :: {
+ variable foo SUCCESS
+ }
+ namespace eval test_ns_1 {
+ variable foo FAIL
+ testevalobjv 1 noSuchCommand
+ }
+} -cleanup {
+ unset -nocomplain ::foo
+ namespace delete test_ns_1
+ rename ::unknown {}
+ rename unknown.save ::unknown
+} -result SUCCESS
+test namespace-52.11 {unknown: with TCL_EVAL_INVOKE} -setup {
+ set handler [namespace eval :: {namespace unknown}]
+ namespace eval :: {namespace unknown unknown}
+ rename ::unknown unknown.save
+ namespace eval :: {
+ proc unknown args {
+ return SUCCESS
+ }
+ }
+ catch {rename ::noSuchCommand {}}
+ set ::slave [interp create]
+} -body {
+ $::slave alias bar noSuchCommand
+ namespace eval test_ns_1 {
+ namespace unknown unknown
+ proc unknown args {
+ return FAIL
+ }
+ $::slave eval bar
+ }
+} -cleanup {
+ interp delete $::slave
+ unset ::slave
+ namespace delete test_ns_1
+ rename ::unknown {}
+ rename unknown.save ::unknown
+ namespace eval :: [list namespace unknown $handler]
+} -result SUCCESS
+test namespace-52.12 {unknown: error case must not reset handler} -body {
+ namespace eval foo {
+ namespace unknown ok
+ catch {namespace unknown {{}{}{}}}
+ namespace unknown
+ }
+} -cleanup {
+ namespace delete foo
+} -result ok
+
+# cleanup
+catch {rename cmd1 {}}
+catch {unset l}
+catch {unset msg}
+catch {unset trigger}
+namespace delete {*}[namespace children :: test_ns_*]
+::tcltest::cleanupTests
+return
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/notify.test b/tests/notify.test
index ba52c50..ba52c50 100755..100644
--- a/tests/notify.test
+++ b/tests/notify.test
diff --git a/tests/obj.test b/tests/obj.test
index a6ed2d1..126d5ca 100644
--- a/tests/obj.test
+++ b/tests/obj.test
@@ -16,54 +16,20 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-if {[info commands testobj] == {}} {
- puts "This application hasn't been compiled with the \"testobj\""
- puts "command, so I can't test the Tcl type and object support."
- ::tcltest::cleanupTests
- return
-}
-
-# Procedure to determine the integer range of the machine
-
-proc int_range {} {
- for { set MIN_INT 1 } { $MIN_INT > 0 } {} {
- set MIN_INT [expr { $MIN_INT << 1 }]
- }
- set MAX_INT [expr { ~ $MIN_INT }]
- return [list $MIN_INT $MAX_INT]
-}
-
-# Procedure to determine the range of wide integers on the machine.
-
-proc wide_range {} {
- for { set MIN_WIDE [expr { wide(1) }] } { $MIN_WIDE > wide(0) } {} {
- set MIN_WIDE [expr { $MIN_WIDE << 1 }]
- }
- set MAX_WIDE [expr { ~ $MIN_WIDE }]
- return [list $MIN_WIDE $MAX_WIDE]
-}
+testConstraint testobj [llength [info commands testobj]]
+testConstraint longIs32bit [expr {int(0x80000000) < 0}]
+testConstraint wideBiggerThanInt [expr {wide(0x80000000) != int(0x80000000)}]
-foreach { MIN_INT MAX_INT } [int_range] break
-foreach { MIN_WIDE MAX_WIDE } [wide_range] break
-::tcltest::testConstraint 32bit \
- [expr { $MAX_INT == 0x7fffffff }]
-::tcltest::testConstraint wideBiggerThanInt \
- [expr { $MAX_WIDE > wide($MAX_INT) }]
-
-test obj-1.1 {Tcl_AppendAllObjTypes, and InitTypeTable, Tcl_RegisterObjType} {
+test obj-1.1 {Tcl_AppendAllObjTypes, and InitTypeTable, Tcl_RegisterObjType} testobj {
set r 1
foreach {t} {
{array search}
- boolean
bytearray
bytecode
- double
+ cmdName
+ dict
end-offset
- index
- int
- list
- nsName
- procbody
+ regexp
string
} {
set first [string first $t [testobj types]]
@@ -72,26 +38,28 @@ test obj-1.1 {Tcl_AppendAllObjTypes, and InitTypeTable, Tcl_RegisterObjType} {
set result $r
} {1}
-test obj-2.1 {Tcl_GetObjType error} {
+test obj-2.1 {Tcl_GetObjType error} testobj {
list [testintobj set 1 0] [catch {testobj convert 1 foo} msg] $msg
} {0 1 {no type foo found}}
-test obj-2.2 {Tcl_GetObjType and Tcl_ConvertToType} {
+test obj-2.2 {Tcl_GetObjType and Tcl_ConvertToType} testobj {
set result ""
lappend result [testobj freeallvars]
lappend result [testintobj set 1 12]
- lappend result [testobj convert 1 double]
+ lappend result [testobj convert 1 bytearray]
lappend result [testobj type 1]
lappend result [testobj refcount 1]
-} {{} 12 12 double 3}
+} {{} 12 12 bytearray 3}
-test obj-3.1 {Tcl_ConvertToType error} {
- list [testdoubleobj set 1 12.34] [catch {testobj convert 1 int} msg] $msg
-} {12.34 1 {expected integer but got "12.34"}}
-test obj-3.2 {Tcl_ConvertToType error, "empty string" object} {
- list [testobj newobj 1] [catch {testobj convert 1 int} msg] $msg
-} {{} 1 {expected integer but got ""}}
+test obj-3.1 {Tcl_ConvertToType error} testobj {
+ list [testdoubleobj set 1 12.34] \
+ [catch {testobj convert 1 end-offset} msg] \
+ $msg
+} {12.34 1 {bad index "12.34": must be end?[+-]integer?}}
+test obj-3.2 {Tcl_ConvertToType error, "empty string" object} testobj {
+ list [testobj newobj 1] [catch {testobj convert 1 end-offset} msg] $msg
+} {{} 1 {bad index "": must be end?[+-]integer?}}
-test obj-4.1 {Tcl_NewObj and AllocateFreeObjects} {
+test obj-4.1 {Tcl_NewObj and AllocateFreeObjects} testobj {
set result ""
lappend result [testobj freeallvars]
lappend result [testobj newobj 1]
@@ -99,7 +67,7 @@ test obj-4.1 {Tcl_NewObj and AllocateFreeObjects} {
lappend result [testobj refcount 1]
} {{} {} string 2}
-test obj-5.1 {Tcl_FreeObj} {
+test obj-5.1 {Tcl_FreeObj} testobj {
set result ""
lappend result [testintobj set 1 12345]
lappend result [testobj freeallvars]
@@ -107,7 +75,7 @@ test obj-5.1 {Tcl_FreeObj} {
lappend result $msg
} {12345 {} 1 {variable 1 is unset (NULL)}}
-test obj-6.1 {Tcl_DuplicateObj, object has internal rep} {
+test obj-6.1 {Tcl_DuplicateObj, object has internal rep} testobj {
set result ""
lappend result [testobj freeallvars]
lappend result [testintobj set 1 47]
@@ -116,7 +84,7 @@ test obj-6.1 {Tcl_DuplicateObj, object has internal rep} {
lappend result [testobj refcount 1]
lappend result [testobj refcount 2]
} {{} 47 47 47 2 3}
-test obj-6.2 {Tcl_DuplicateObj, "empty string" object} {
+test obj-6.2 {Tcl_DuplicateObj, "empty string" object} testobj {
set result ""
lappend result [testobj freeallvars]
lappend result [testobj newobj 1]
@@ -126,182 +94,184 @@ test obj-6.2 {Tcl_DuplicateObj, "empty string" object} {
lappend result [testobj refcount 2]
} {{} {} {} {} 2 3}
-test obj-7.1 {Tcl_GetString, return existing string rep} {
+# We assume that testobj is an indicator for test*obj as well
+
+test obj-7.1 {Tcl_GetString, return existing string rep} testobj {
set result ""
lappend result [testintobj set 1 47]
lappend result [testintobj get2 1]
} {47 47}
-test obj-7.2 {Tcl_GetString, "empty string" object} {
+test obj-7.2 {Tcl_GetString, "empty string" object} testobj {
set result ""
lappend result [testobj newobj 1]
lappend result [teststringobj append 1 abc -1]
lappend result [teststringobj get2 1]
} {{} abc abc}
-test obj-7.3 {Tcl_GetString, returns string internal rep (DString)} {
+test obj-7.3 {Tcl_GetString, returns string internal rep (DString)} testobj {
set result ""
lappend result [teststringobj set 1 xyz]
lappend result [teststringobj append 1 abc -1]
lappend result [teststringobj get2 1]
} {xyz xyzabc xyzabc}
-test obj-7.4 {Tcl_GetString, recompute string rep from internal rep} {
+test obj-7.4 {Tcl_GetString, recompute string rep from internal rep} testobj {
set result ""
lappend result [testintobj set 1 77]
lappend result [testintobj mult10 1]
lappend result [teststringobj get2 1]
} {77 770 770}
-test obj-8.1 {Tcl_GetStringFromObj, return existing string rep} {
+test obj-8.1 {Tcl_GetStringFromObj, return existing string rep} testobj {
set result ""
lappend result [testintobj set 1 47]
lappend result [testintobj get 1]
} {47 47}
-test obj-8.2 {Tcl_GetStringFromObj, "empty string" object} {
+test obj-8.2 {Tcl_GetStringFromObj, "empty string" object} testobj {
set result ""
lappend result [testobj newobj 1]
lappend result [teststringobj append 1 abc -1]
lappend result [teststringobj get 1]
} {{} abc abc}
-test obj-8.3 {Tcl_GetStringFromObj, returns string internal rep (DString)} {
+test obj-8.3 {Tcl_GetStringFromObj, returns string internal rep (DString)} testobj {
set result ""
lappend result [teststringobj set 1 xyz]
lappend result [teststringobj append 1 abc -1]
lappend result [teststringobj get 1]
} {xyz xyzabc xyzabc}
-test obj-8.4 {Tcl_GetStringFromObj, recompute string rep from internal rep} {
+test obj-8.4 {Tcl_GetStringFromObj, recompute string rep from internal rep} testobj {
set result ""
lappend result [testintobj set 1 77]
lappend result [testintobj mult10 1]
lappend result [teststringobj get 1]
} {77 770 770}
-test obj-9.1 {Tcl_NewBooleanObj} {
+test obj-9.1 {Tcl_NewBooleanObj} testobj {
set result ""
lappend result [testobj freeallvars]
lappend result [testbooleanobj set 1 0]
lappend result [testobj type 1]
lappend result [testobj refcount 1]
-} {{} 0 boolean 2}
+} {{} 0 int 2}
-test obj-10.1 {Tcl_SetBooleanObj, existing "empty string" object} {
+test obj-10.1 {Tcl_SetBooleanObj, existing "empty string" object} testobj {
set result ""
lappend result [testobj freeallvars]
lappend result [testobj newobj 1]
lappend result [testbooleanobj set 1 0] ;# makes existing obj boolean
lappend result [testobj type 1]
lappend result [testobj refcount 1]
-} {{} {} 0 boolean 2}
-test obj-10.2 {Tcl_SetBooleanObj, existing non-"empty string" object} {
+} {{} {} 0 int 2}
+test obj-10.2 {Tcl_SetBooleanObj, existing non-"empty string" object} testobj {
set result ""
lappend result [testobj freeallvars]
lappend result [testintobj set 1 98765]
lappend result [testbooleanobj set 1 1] ;# makes existing obj boolean
lappend result [testobj type 1]
lappend result [testobj refcount 1]
-} {{} 98765 1 boolean 2}
+} {{} 98765 1 int 2}
-test obj-11.1 {Tcl_GetBooleanFromObj, existing boolean object} {
+test obj-11.1 {Tcl_GetBooleanFromObj, existing boolean object} testobj {
set result ""
lappend result [testbooleanobj set 1 1]
lappend result [testbooleanobj not 1] ;# gets existing boolean rep
} {1 0}
-test obj-11.2 {Tcl_GetBooleanFromObj, convert to boolean} {
+test obj-11.2 {Tcl_GetBooleanFromObj, convert to boolean} testobj {
set result ""
lappend result [testintobj set 1 47]
lappend result [testbooleanobj not 1] ;# must convert to bool
lappend result [testobj type 1]
-} {47 0 boolean}
-test obj-11.3 {Tcl_GetBooleanFromObj, error converting to boolean} {
+} {47 0 int}
+test obj-11.3 {Tcl_GetBooleanFromObj, error converting to boolean} testobj {
set result ""
lappend result [teststringobj set 1 abc]
lappend result [catch {testbooleanobj not 1} msg]
lappend result $msg
} {abc 1 {expected boolean value but got "abc"}}
-test obj-11.4 {Tcl_GetBooleanFromObj, error converting from "empty string"} {
+test obj-11.4 {Tcl_GetBooleanFromObj, error converting from "empty string"} testobj {
set result ""
lappend result [testobj newobj 1]
lappend result [catch {testbooleanobj not 1} msg]
lappend result $msg
} {{} 1 {expected boolean value but got ""}}
-test obj-11.5 {Tcl_GetBooleanFromObj, convert hex to boolean} {
+test obj-11.5 {Tcl_GetBooleanFromObj, convert hex to boolean} testobj {
set result ""
lappend result [teststringobj set 1 0xac]
lappend result [testbooleanobj not 1]
lappend result [testobj type 1]
-} {0xac 0 boolean}
-test obj-11.6 {Tcl_GetBooleanFromObj, convert float to boolean} {
+} {0xac 0 int}
+test obj-11.6 {Tcl_GetBooleanFromObj, convert float to boolean} testobj {
set result ""
lappend result [teststringobj set 1 5.42]
lappend result [testbooleanobj not 1]
lappend result [testobj type 1]
-} {5.42 0 boolean}
+} {5.42 0 int}
-test obj-12.1 {DupBooleanInternalRep} {
+test obj-12.1 {DupBooleanInternalRep} testobj {
set result ""
lappend result [testbooleanobj set 1 1]
lappend result [testobj duplicate 1 2] ;# uses DupBooleanInternalRep
lappend result [testbooleanobj get 2]
} {1 1 1}
-test obj-13.1 {SetBooleanFromAny, int to boolean special case} {
+test obj-13.1 {SetBooleanFromAny, int to boolean special case} testobj {
set result ""
lappend result [testintobj set 1 1234]
lappend result [testbooleanobj not 1] ;# converts with SetBooleanFromAny
lappend result [testobj type 1]
-} {1234 0 boolean}
-test obj-13.2 {SetBooleanFromAny, double to boolean special case} {
+} {1234 0 int}
+test obj-13.2 {SetBooleanFromAny, double to boolean special case} testobj {
set result ""
lappend result [testdoubleobj set 1 3.14159]
lappend result [testbooleanobj not 1] ;# converts with SetBooleanFromAny
lappend result [testobj type 1]
-} {3.14159 0 boolean}
-test obj-13.3 {SetBooleanFromAny, special case strings representing booleans} {
+} {3.14159 0 int}
+test obj-13.3 {SetBooleanFromAny, special case strings representing booleans} testobj {
set result ""
foreach s {yes no true false on off} {
teststringobj set 1 $s
lappend result [testbooleanobj not 1]
}
lappend result [testobj type 1]
-} {0 1 0 1 0 1 boolean}
-test obj-13.4 {SetBooleanFromAny, recompute string rep then parse it} {
+} {0 1 0 1 0 1 int}
+test obj-13.4 {SetBooleanFromAny, recompute string rep then parse it} testobj {
set result ""
lappend result [testintobj set 1 456]
lappend result [testintobj div10 1]
lappend result [testbooleanobj not 1] ;# converts with SetBooleanFromAny
lappend result [testobj type 1]
-} {456 45 0 boolean}
-test obj-13.5 {SetBooleanFromAny, error parsing string} {
+} {456 45 0 int}
+test obj-13.5 {SetBooleanFromAny, error parsing string} testobj {
set result ""
lappend result [teststringobj set 1 abc]
lappend result [catch {testbooleanobj not 1} msg]
lappend result $msg
} {abc 1 {expected boolean value but got "abc"}}
-test obj-13.6 {SetBooleanFromAny, error parsing string} {
+test obj-13.6 {SetBooleanFromAny, error parsing string} testobj {
set result ""
lappend result [teststringobj set 1 x1.0]
lappend result [catch {testbooleanobj not 1} msg]
lappend result $msg
} {x1.0 1 {expected boolean value but got "x1.0"}}
-test obj-13.7 {SetBooleanFromAny, error converting from "empty string"} {
+test obj-13.7 {SetBooleanFromAny, error converting from "empty string"} testobj {
set result ""
lappend result [testobj newobj 1]
lappend result [catch {testbooleanobj not 1} msg]
lappend result $msg
} {{} 1 {expected boolean value but got ""}}
-test obj-13.8 {SetBooleanFromAny, unicode strings} {
+test obj-13.8 {SetBooleanFromAny, unicode strings} testobj {
set result ""
lappend result [teststringobj set 1 1\u7777]
lappend result [catch {testbooleanobj not 1} msg]
lappend result $msg
} "1\u7777 1 {expected boolean value but got \"1\u7777\"}"
-test obj-14.1 {UpdateStringOfBoolean} {
+test obj-14.1 {UpdateStringOfBoolean} testobj {
set result ""
lappend result [testbooleanobj set 1 0]
lappend result [testbooleanobj not 1]
lappend result [testbooleanobj get 1] ;# must update string rep
} {0 1 1}
-test obj-15.1 {Tcl_NewDoubleObj} {
+test obj-15.1 {Tcl_NewDoubleObj} testobj {
set result ""
lappend result [testobj freeallvars]
lappend result [testdoubleobj set 1 3.1459]
@@ -309,7 +279,7 @@ test obj-15.1 {Tcl_NewDoubleObj} {
lappend result [testobj refcount 1]
} {{} 3.1459 double 2}
-test obj-16.1 {Tcl_SetDoubleObj, existing "empty string" object} {
+test obj-16.1 {Tcl_SetDoubleObj, existing "empty string" object} testobj {
set result ""
lappend result [testobj freeallvars]
lappend result [testobj newobj 1]
@@ -317,7 +287,7 @@ test obj-16.1 {Tcl_SetDoubleObj, existing "empty string" object} {
lappend result [testobj type 1]
lappend result [testobj refcount 1]
} {{} {} 0.123 double 2}
-test obj-16.2 {Tcl_SetDoubleObj, existing non-"empty string" object} {
+test obj-16.2 {Tcl_SetDoubleObj, existing non-"empty string" object} testobj {
set result ""
lappend result [testobj freeallvars]
lappend result [testintobj set 1 98765]
@@ -326,83 +296,83 @@ test obj-16.2 {Tcl_SetDoubleObj, existing non-"empty string" object} {
lappend result [testobj refcount 1]
} {{} 98765 27.56 double 2}
-test obj-17.1 {Tcl_GetDoubleFromObj, existing double object} {
+test obj-17.1 {Tcl_GetDoubleFromObj, existing double object} testobj {
set result ""
lappend result [testdoubleobj set 1 16.1]
lappend result [testdoubleobj mult10 1] ;# gets existing double rep
} {16.1 161.0}
-test obj-17.2 {Tcl_GetDoubleFromObj, convert to double} {
+test obj-17.2 {Tcl_GetDoubleFromObj, convert to double} testobj {
set result ""
lappend result [testintobj set 1 477]
lappend result [testdoubleobj div10 1] ;# must convert to bool
lappend result [testobj type 1]
} {477 47.7 double}
-test obj-17.3 {Tcl_GetDoubleFromObj, error converting to double} {
+test obj-17.3 {Tcl_GetDoubleFromObj, error converting to double} testobj {
set result ""
lappend result [teststringobj set 1 abc]
lappend result [catch {testdoubleobj mult10 1} msg]
lappend result $msg
} {abc 1 {expected floating-point number but got "abc"}}
-test obj-17.4 {Tcl_GetDoubleFromObj, error converting from "empty string"} {
+test obj-17.4 {Tcl_GetDoubleFromObj, error converting from "empty string"} testobj {
set result ""
lappend result [testobj newobj 1]
lappend result [catch {testdoubleobj div10 1} msg]
lappend result $msg
} {{} 1 {expected floating-point number but got ""}}
-test obj-18.1 {DupDoubleInternalRep} {
+test obj-18.1 {DupDoubleInternalRep} testobj {
set result ""
lappend result [testdoubleobj set 1 17.1]
lappend result [testobj duplicate 1 2] ;# uses DupDoubleInternalRep
lappend result [testdoubleobj get 2]
} {17.1 17.1 17.1}
-test obj-19.1 {SetDoubleFromAny, int to double special case} {
+test obj-19.1 {SetDoubleFromAny, int to double special case} testobj {
set result ""
lappend result [testintobj set 1 1234]
lappend result [testdoubleobj mult10 1] ;# converts with SetDoubleFromAny
lappend result [testobj type 1]
} {1234 12340.0 double}
-test obj-19.2 {SetDoubleFromAny, boolean to double special case} {
+test obj-19.2 {SetDoubleFromAny, boolean to double special case} testobj {
set result ""
lappend result [testbooleanobj set 1 1]
lappend result [testdoubleobj mult10 1] ;# converts with SetDoubleFromAny
lappend result [testobj type 1]
} {1 10.0 double}
-test obj-19.3 {SetDoubleFromAny, recompute string rep then parse it} {
+test obj-19.3 {SetDoubleFromAny, recompute string rep then parse it} testobj {
set result ""
lappend result [testintobj set 1 456]
lappend result [testintobj div10 1]
lappend result [testdoubleobj mult10 1] ;# converts with SetDoubleFromAny
lappend result [testobj type 1]
} {456 45 450.0 double}
-test obj-19.4 {SetDoubleFromAny, error parsing string} {
+test obj-19.4 {SetDoubleFromAny, error parsing string} testobj {
set result ""
lappend result [teststringobj set 1 abc]
lappend result [catch {testdoubleobj mult10 1} msg]
lappend result $msg
} {abc 1 {expected floating-point number but got "abc"}}
-test obj-19.5 {SetDoubleFromAny, error parsing string} {
+test obj-19.5 {SetDoubleFromAny, error parsing string} testobj {
set result ""
lappend result [teststringobj set 1 x1.0]
lappend result [catch {testdoubleobj mult10 1} msg]
lappend result $msg
} {x1.0 1 {expected floating-point number but got "x1.0"}}
-test obj-19.6 {SetDoubleFromAny, error converting from "empty string"} {
+test obj-19.6 {SetDoubleFromAny, error converting from "empty string"} testobj {
set result ""
lappend result [testobj newobj 1]
lappend result [catch {testdoubleobj div10 1} msg]
lappend result $msg
} {{} 1 {expected floating-point number but got ""}}
-test obj-20.1 {UpdateStringOfDouble} {
+test obj-20.1 {UpdateStringOfDouble} testobj {
set result ""
lappend result [testdoubleobj set 1 3.14159]
lappend result [testdoubleobj mult10 1]
lappend result [testdoubleobj get 1] ;# must update string rep
} {3.14159 31.4159 31.4159}
-test obj-21.1 {Tcl_NewIntObj} {
+test obj-21.1 {Tcl_NewIntObj} testobj {
set result ""
lappend result [testobj freeallvars]
lappend result [testintobj set 1 55]
@@ -410,7 +380,7 @@ test obj-21.1 {Tcl_NewIntObj} {
lappend result [testobj refcount 1]
} {{} 55 int 2}
-test obj-22.1 {Tcl_SetIntObj, existing "empty string" object} {
+test obj-22.1 {Tcl_SetIntObj, existing "empty string" object} testobj {
set result ""
lappend result [testobj freeallvars]
lappend result [testobj newobj 1]
@@ -418,7 +388,7 @@ test obj-22.1 {Tcl_SetIntObj, existing "empty string" object} {
lappend result [testobj type 1]
lappend result [testobj refcount 1]
} {{} {} 77 int 2}
-test obj-22.2 {Tcl_SetIntObj, existing non-"empty string" object} {
+test obj-22.2 {Tcl_SetIntObj, existing non-"empty string" object} testobj {
set result ""
lappend result [testobj freeallvars]
lappend result [testdoubleobj set 1 12.34]
@@ -427,94 +397,94 @@ test obj-22.2 {Tcl_SetIntObj, existing non-"empty string" object} {
lappend result [testobj refcount 1]
} {{} 12.34 77 int 2}
-test obj-23.1 {Tcl_GetIntFromObj, existing int object} {
+test obj-23.1 {Tcl_GetIntFromObj, existing int object} testobj {
set result ""
lappend result [testintobj set 1 22]
lappend result [testintobj mult10 1] ;# gets existing int rep
} {22 220}
-test obj-23.2 {Tcl_GetIntFromObj, convert to int} {
+test obj-23.2 {Tcl_GetIntFromObj, convert to int} testobj {
set result ""
lappend result [testintobj set 1 477]
lappend result [testintobj div10 1] ;# must convert to bool
lappend result [testobj type 1]
} {477 47 int}
-test obj-23.3 {Tcl_GetIntFromObj, error converting to int} {
+test obj-23.3 {Tcl_GetIntFromObj, error converting to int} testobj {
set result ""
lappend result [teststringobj set 1 abc]
lappend result [catch {testintobj mult10 1} msg]
lappend result $msg
} {abc 1 {expected integer but got "abc"}}
-test obj-23.4 {Tcl_GetIntFromObj, error converting from "empty string"} {
+test obj-23.4 {Tcl_GetIntFromObj, error converting from "empty string"} testobj {
set result ""
lappend result [testobj newobj 1]
lappend result [catch {testintobj div10 1} msg]
lappend result $msg
} {{} 1 {expected integer but got ""}}
-test obj-23.5 {Tcl_GetIntFromObj, integer too large to represent as non-long error} {nonPortable} {
+test obj-23.5 {Tcl_GetIntFromObj, integer too large to represent as non-long error} {testobj} {
set result ""
lappend result [testobj newobj 1]
lappend result [testintobj inttoobigtest 1]
} {{} 1}
-test obj-24.1 {DupIntInternalRep} {
+test obj-24.1 {DupIntInternalRep} testobj {
set result ""
lappend result [testintobj set 1 23]
lappend result [testobj duplicate 1 2] ;# uses DupIntInternalRep
lappend result [testintobj get 2]
} {23 23 23}
-test obj-25.1 {SetIntFromAny, int to int special case} {
+test obj-25.1 {SetIntFromAny, int to int special case} testobj {
set result ""
lappend result [testintobj set 1 1234]
lappend result [testintobj mult10 1] ;# converts with SetIntFromAny
lappend result [testobj type 1]
} {1234 12340 int}
-test obj-25.2 {SetIntFromAny, boolean to int special case} {
+test obj-25.2 {SetIntFromAny, boolean to int special case} testobj {
set result ""
lappend result [testbooleanobj set 1 1]
lappend result [testintobj mult10 1] ;# converts with SetIntFromAny
lappend result [testobj type 1]
} {1 10 int}
-test obj-25.3 {SetIntFromAny, recompute string rep then parse it} {
+test obj-25.3 {SetIntFromAny, recompute string rep then parse it} testobj {
set result ""
lappend result [testintobj set 1 456]
lappend result [testintobj div10 1]
lappend result [testintobj mult10 1] ;# converts with SetIntFromAny
lappend result [testobj type 1]
} {456 45 450 int}
-test obj-25.4 {SetIntFromAny, error parsing string} {
+test obj-25.4 {SetIntFromAny, error parsing string} testobj {
set result ""
lappend result [teststringobj set 1 abc]
lappend result [catch {testintobj mult10 1} msg]
lappend result $msg
} {abc 1 {expected integer but got "abc"}}
-test obj-25.5 {SetIntFromAny, error parsing string} {
+test obj-25.5 {SetIntFromAny, error parsing string} testobj {
set result ""
lappend result [teststringobj set 1 x17]
lappend result [catch {testintobj mult10 1} msg]
lappend result $msg
} {x17 1 {expected integer but got "x17"}}
-test obj-25.6 {SetIntFromAny, integer too large} {nonPortable} {
+test obj-25.6 {SetIntFromAny, integer too large} {testobj} {
set result ""
lappend result [teststringobj set 1 123456789012345678901]
lappend result [catch {testintobj mult10 1} msg]
lappend result $msg
} {123456789012345678901 1 {integer value too large to represent}}
-test obj-25.7 {SetIntFromAny, error converting from "empty string"} {
+test obj-25.7 {SetIntFromAny, error converting from "empty string"} testobj {
set result ""
lappend result [testobj newobj 1]
lappend result [catch {testintobj div10 1} msg]
lappend result $msg
} {{} 1 {expected integer but got ""}}
-test obj-26.1 {UpdateStringOfInt} {
+test obj-26.1 {UpdateStringOfInt} testobj {
set result ""
lappend result [testintobj set 1 512]
lappend result [testintobj mult10 1]
lappend result [testintobj get 1] ;# must update string rep
} {512 5120 5120}
-test obj-27.1 {Tcl_NewLongObj} {
+test obj-27.1 {Tcl_NewLongObj} testobj {
set result ""
lappend result [testobj freeallvars]
testintobj setmaxlong 1
@@ -523,7 +493,7 @@ test obj-27.1 {Tcl_NewLongObj} {
lappend result [testobj refcount 1]
} {{} 1 int 1}
-test obj-28.1 {Tcl_SetLongObj, existing "empty string" object} {
+test obj-28.1 {Tcl_SetLongObj, existing "empty string" object} testobj {
set result ""
lappend result [testobj freeallvars]
lappend result [testobj newobj 1]
@@ -531,7 +501,7 @@ test obj-28.1 {Tcl_SetLongObj, existing "empty string" object} {
lappend result [testobj type 1]
lappend result [testobj refcount 1]
} {{} {} 77 int 2}
-test obj-28.2 {Tcl_SetLongObj, existing non-"empty string" object} {
+test obj-28.2 {Tcl_SetLongObj, existing non-"empty string" object} testobj {
set result ""
lappend result [testobj freeallvars]
lappend result [testdoubleobj set 1 12.34]
@@ -540,31 +510,31 @@ test obj-28.2 {Tcl_SetLongObj, existing non-"empty string" object} {
lappend result [testobj refcount 1]
} {{} 12.34 77 int 2}
-test obj-29.1 {Tcl_GetLongFromObj, existing long integer object} {
+test obj-29.1 {Tcl_GetLongFromObj, existing long integer object} testobj {
set result ""
lappend result [testintobj setlong 1 22]
lappend result [testintobj mult10 1] ;# gets existing long int rep
} {22 220}
-test obj-29.2 {Tcl_GetLongFromObj, convert to long} {
+test obj-29.2 {Tcl_GetLongFromObj, convert to long} testobj {
set result ""
lappend result [testintobj setlong 1 477]
lappend result [testintobj div10 1] ;# must convert to bool
lappend result [testobj type 1]
} {477 47 int}
-test obj-29.3 {Tcl_GetLongFromObj, error converting to long integer} {
+test obj-29.3 {Tcl_GetLongFromObj, error converting to long integer} testobj {
set result ""
lappend result [teststringobj set 1 abc]
lappend result [catch {testintobj ismaxlong 1} msg] ;# cvts to long int
lappend result $msg
} {abc 1 {expected integer but got "abc"}}
-test obj-29.4 {Tcl_GetLongFromObj, error converting from "empty string"} {
+test obj-29.4 {Tcl_GetLongFromObj, error converting from "empty string"} testobj {
set result ""
lappend result [testobj newobj 1]
lappend result [catch {testintobj ismaxlong 1} msg] ;# cvts to long int
lappend result $msg
} {{} 1 {expected integer but got ""}}
-test obj-30.1 {Ref counting and object deletion, simple types} {
+test obj-30.1 {Ref counting and object deletion, simple types} testobj {
set result ""
lappend result [testobj freeallvars]
lappend result [testintobj set 1 1024]
@@ -576,93 +546,87 @@ test obj-30.1 {Ref counting and object deletion, simple types} {
lappend result [testobj type 2]
lappend result [testobj refcount 1]
lappend result [testobj refcount 2]
-} {{} 1024 1024 int 4 4 0 boolean 3 2}
+} {{} 1024 1024 int 4 4 0 int 3 2}
-test obj-31.1 {regenerate string rep of "end"} {
+test obj-31.1 {regenerate string rep of "end"} testobj {
testobj freeallvars
teststringobj set 1 end
testobj convert 1 end-offset
testobj invalidateStringRep 1
} end
-
-test obj-31.2 {regenerate string rep of "end-1"} {
+test obj-31.2 {regenerate string rep of "end-1"} testobj {
testobj freeallvars
teststringobj set 1 end-0x1
testobj convert 1 end-offset
testobj invalidateStringRep 1
} end-1
-
-test obj-31.3 {regenerate string rep of "end--1"} {
+test obj-31.3 {regenerate string rep of "end--1"} testobj {
testobj freeallvars
teststringobj set 1 end--0x1
testobj convert 1 end-offset
testobj invalidateStringRep 1
} end--1
-
-test obj-31.4 {regenerate string rep of "end-bigInteger"} {
+test obj-31.4 {regenerate string rep of "end-bigInteger"} testobj {
testobj freeallvars
teststringobj set 1 end-0x7fffffff
testobj convert 1 end-offset
testobj invalidateStringRep 1
} end-2147483647
-
-test obj-31.5 {regenerate string rep of "end--bigInteger"} {
+test obj-31.5 {regenerate string rep of "end--bigInteger"} testobj {
testobj freeallvars
teststringobj set 1 end--0x7fffffff
testobj convert 1 end-offset
testobj invalidateStringRep 1
} end--2147483647
-
-
-test obj-31.6 {regenerate string rep of "end--bigInteger"} {nonPortable} {
+test obj-31.6 {regenerate string rep of "end--bigInteger"} {testobj longIs32bit} {
testobj freeallvars
teststringobj set 1 end--0x80000000
testobj convert 1 end-offset
testobj invalidateStringRep 1
} end--2147483648
-test obj-32.1 {integer overflow on input} {32bit wideBiggerThanInt} {
+test obj-32.1 {freeing very large object trees} {
+ set x {}
+ for {set i 0} {$i<100000} {incr i} {
+ set x [list $x {}]
+ }
+ unset x
+} {}
+
+test obj-33.1 {integer overflow on input} {longIs32bit wideBiggerThanInt} {
set x 0x8000; append x 0000
list [string is integer $x] [expr { wide($x) }]
} {1 2147483648}
-
-test obj-32.2 {integer overflow on input} {32bit wideBiggerThanInt} {
+test obj-33.2 {integer overflow on input} {longIs32bit wideBiggerThanInt} {
set x 0xffff; append x ffff
list [string is integer $x] [expr { wide($x) }]
} {1 4294967295}
-
-test obj-32.3 {integer overflow on input} {32bit wideBiggerThanInt} {
+test obj-33.3 {integer overflow on input} {longIs32bit wideBiggerThanInt} {
set x 0x10000; append x 0000
list [string is integer $x] [expr { wide($x) }]
} {0 4294967296}
-
-test obj-32.4 {integer overflow on input} {32bit wideBiggerThanInt} {
+test obj-33.4 {integer overflow on input} {longIs32bit wideBiggerThanInt} {
set x -0x8000; append x 0000
list [string is integer $x] [expr { wide($x) }]
} {1 -2147483648}
-
-test obj-32.5 {integer overflow on input} {32bit wideBiggerThanInt} {
+test obj-33.5 {integer overflow on input} {longIs32bit wideBiggerThanInt} {
set x -0x8000; append x 0001
list [string is integer $x] [expr { wide($x) }]
} {1 -2147483649}
-
-test obj-32.6 {integer overflow on input} {32bit wideBiggerThanInt} {
+test obj-33.6 {integer overflow on input} {longIs32bit wideBiggerThanInt} {
set x -0xffff; append x ffff
list [string is integer $x] [expr { wide($x) }]
} {1 -4294967295}
-
-test obj-32.7 {integer overflow on input} {32bit wideBiggerThanInt} {
+test obj-33.7 {integer overflow on input} {longIs32bit wideBiggerThanInt} {
set x -0x10000; append x 0000
list [string is integer $x] [expr { wide($x) }]
} {0 -4294967296}
-testobj freeallvars
+if {[testConstraint testobj]} {
+ testobj freeallvars
+}
# cleanup
::tcltest::cleanupTests
return
-
-# Local Variables:
-# mode: tcl
-# End:
diff --git a/tests/opt.test b/tests/opt.test
index b3aba91..ba59f6c 100644
--- a/tests/opt.test
+++ b/tests/opt.test
@@ -37,7 +37,6 @@ test opt-2.1 {OptKeyDelete} {
[info exists ::tcl::OptDesc(testkey)]
} {testkey 1 {} 0}
-
test opt-3.1 {OptParse / temp key is removed} {
set n $::tcl::OptDescN
set prev [array names ::tcl::OptDesc]
@@ -48,8 +47,6 @@ test opt-3.1 {OptParse / temp key is removed} {
[info exists ::tcl::OptDesc($n)]\
[expr {"[lsort $prev]"=="[lsort [array names ::tcl::OptDesc]]"}]
} {1 {} {} 0 1}
-
-
test opt-3.2 {OptParse / temp key is removed even on errors} {
set n $::tcl::OptDescN
catch {::tcl::OptKeyDelete $n}
@@ -63,7 +60,6 @@ test opt-4.1 {OptProc} {
::tcl::OptKeyDelete optTest
} {}
-
test opt-5.1 {OptProcArgGiven} {
::tcl::OptProc optTest {{-foo}} {
if {[::tcl::OptProcArgGiven "-foo"]} {
@@ -83,7 +79,6 @@ test opt-6.1 {OptKeyParse} {
------------ ---- ----- ----
( -help gives this help )}}
-
test opt-7.1 {OptCheckType} {
list \
[::tcl::OptCheckType 23 int] \
@@ -100,7 +95,6 @@ test opt-7.1 {OptCheckType} {
[catch {::tcl::OptCheckType foo choice {x y Foo z}}]
} {23 23.0 1 -blah {a b c} maYbe 1 1 1 1 1 1}
-
test opt-8.1 {List utilities} {
::tcl::Lempty {}
} 1
@@ -110,37 +104,32 @@ test opt-8.2 {List utilities} {
test opt-8.3 {List utilities} {
::tcl::Lget {a {b c d} e} {1 2}
} d
-
test opt-8.4 {List utilities} {
set l {a {b c d e} f}
::tcl::Lvarset l {1 2} D
set l
} {a {b c D e} f}
-
test opt-8.5 {List utilities} {
set l {a b c}
::tcl::Lvarset1 l 6 X
set l
} {a b c {} {} {} X}
-
test opt-8.6 {List utilities} {
set l {a {b c 7 e} f}
::tcl::Lvarincr l {1 2}
set l
} {a {b c 8 e} f}
-
test opt-8.7 {List utilities} {
set l {a {b c 7 e} f}
::tcl::Lvarincr l {1 2} -9
set l
} {a {b c -2 e} f}
-
+# 8.8 and 8.9 missing?
test opt-8.10 {List utilities} {
set l {a {b c 7 e} f}
::tcl::Lvarpop l
set l
} {{b c 7 e} f}
-
test opt-8.11 {List utilities} {
catch {unset x}
set l {a {b c 7 e} f}
@@ -155,7 +144,6 @@ test opt-9.1 {Misc utilities} {
::tcl::SetMax v 6
set v
} 7
-
test opt-9.2 {Misc utilities} {
catch {unset v}
::tcl::SetMin v 3
@@ -174,21 +162,18 @@ test opt-10.1 {ambigous flags} {
-fla boolflag (false)
-flag2xyz boolflag (false)
-flag3xyz boolflag (false) }
-
test opt-10.2 {non ambigous flags} {
::tcl::OptProc optTest {{-flag1xyz} {-other} {-flag2xyz} {-flag3xyz}} {
return $flag2xyz
}
optTest -fLaG2
} 1
-
test opt-10.3 {non ambigous flags because of exact match} {
::tcl::OptProc optTest {{-flag1x} {-other} {-flag1} {-flag1xy}} {
return $flag1
}
optTest -flAg1
} 1
-
test opt-10.4 {ambigous flags, not exact match} {
::tcl::OptProc optTest {{-flag1xy} {-other} {-flag1} {-flag1xyz}} {
return $flag1
@@ -199,8 +184,6 @@ test opt-10.4 {ambigous flags, not exact match} {
-flag1xy boolflag (false)
-flag1xyz boolflag (false) }
-
-
# medium size overall test example: (defined once)
::tcl::OptProc optTest {
{cmd -choice {print save delete} "sub command to choose"}
@@ -216,8 +199,6 @@ test opt-10.5 {medium size overall test} {
list [catch {optTest} msg] $msg
} {1 {no value given for parameter "cmd" (use -help for full usage) :
cmd choice (print save delete) sub command to choose}}
-
-
test opt-10.6 {medium size overall test} {
list [catch {optTest -help} msg] $msg
} {1 {Usage information:
@@ -229,19 +210,15 @@ test opt-10.6 {medium size overall test} {
arg2 string () this is help
?arg3? int (7) optional number
-moreflags boolflag (false) }}
-
test opt-10.7 {medium size overall test} {
optTest save tst
} {save 1 tst 7 0}
-
test opt-10.8 {medium size overall test} {
optTest save -allowBoing false -- 8
} {save 0 8 7 0}
-
test opt-10.9 {medium size overall test} {
optTest save tst -m --
} {save 1 tst 7 1}
-
test opt-10.10 {medium size overall test} {
list [catch {optTest save tst foo} msg] [lindex [split $msg "\n"] 0]
} {1 {too many arguments (unexpected argument(s): foo), usage:}}
@@ -266,15 +243,3 @@ test opt-11.2 {default value for args} {
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/osa.test b/tests/osa.test
deleted file mode 100644
index 0fc722c..0000000
--- a/tests/osa.test
+++ /dev/null
@@ -1,46 +0,0 @@
-# Commands covered: AppleScript
-#
-# This file contains a collection of tests for one or more of the Tcl
-# built-in commands. Sourcing this file into Tcl runs the tests and
-# generates output for errors. No output means no errors were found.
-#
-# Copyright (c) 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.
-
-if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
- namespace import -force ::tcltest::*
-}
-
-# Only run the test if we can load the AppleScript command
-set ::tcltest::testConstraints(appleScript) [expr {[info commands AppleScript] != ""}]
-
-test osa-1.1 {Tcl_OSAComponentCmd} {macOnly appleScript} {
- list [catch AppleScript msg] $msg
-} {1 {wrong # args: should be "AppleScript option ?arg ...?"}}
-test osa-1.2 {Tcl_OSAComponentCmd} {macOnly appleScript} {
- list [catch {AppleScript x} msg] $msg
-} {1 {bad option "x": should be compile, decompile, delete, execute, info, load, run or store}}
-
-test osa-1.3 {TclOSACompileCmd} {macOnly appleScript} {
- list [catch {AppleScript compile} msg] $msg
-} {1 {wrong # args: should be "AppleScript compile ?options? code"}}
-
-# cleanup
-::tcltest::cleanupTests
-return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/parse.test b/tests/parse.test
index 3118cf8..37c44d5 100644
--- a/tests/parse.test
+++ b/tests/parse.test
@@ -8,166 +8,258 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest 2
- namespace import -force ::tcltest::*
+if {[catch {package require tcltest 2.0.2}]} {
+ puts stderr "Skipping tests in [info script]. tcltest 2.0.2 required."
+ return
}
-if {[info commands testparser] == {}} {
- puts "This application hasn't been compiled with the \"testparser\""
- puts "command, so I can't test the Tcl parser."
- ::tcltest::cleanupTests
- return
-}
+namespace eval ::tcl::test::parse {
+ namespace import ::tcltest::*
-test parse-1.1 {Tcl_ParseCommand procedure, computing string length} {
+testConstraint testparser [llength [info commands testparser]]
+testConstraint testevalobjv [llength [info commands testevalobjv]]
+testConstraint testevalex [llength [info commands testevalex]]
+testConstraint testparsevarname [llength [info commands testparsevarname]]
+testConstraint testparsevar [llength [info commands testparsevar]]
+testConstraint testasync [llength [info commands testasync]]
+testConstraint testcmdtrace [llength [info commands testcmdtrace]]
+
+test parse-1.1 {Tcl_ParseCommand procedure, computing string length} testparser {
testparser [bytestring "foo\0 bar"] -1
} {- foo 1 simple foo 1 text foo 0 {}}
-test parse-1.2 {Tcl_ParseCommand procedure, computing string length} {
+test parse-1.2 {Tcl_ParseCommand procedure, computing string length} testparser {
testparser "foo bar" -1
} {- {foo bar} 2 simple foo 1 text foo 0 simple bar 1 text bar 0 {}}
-test parse-1.3 {Tcl_ParseCommand procedure, leading space} {
+test parse-1.3 {Tcl_ParseCommand procedure, leading space} testparser {
testparser " \n\t foo" 0
} {- foo 1 simple foo 1 text foo 0 {}}
-test parse-1.4 {Tcl_ParseCommand procedure, leading space} {
+test parse-1.4 {Tcl_ParseCommand procedure, leading space} testparser {
testparser "\f\r\vfoo" 0
} {- foo 1 simple foo 1 text foo 0 {}}
-test parse-1.5 {Tcl_ParseCommand procedure, backslash-newline in leading space} {
+test parse-1.5 {Tcl_ParseCommand procedure, backslash-newline in leading space} testparser {
testparser " \\\n foo" 0
} {- foo 1 simple foo 1 text foo 0 {}}
-test parse-1.6 {Tcl_ParseCommand procedure, backslash-newline in leading space} {
+test parse-1.6 {Tcl_ParseCommand procedure, backslash-newline in leading space} testparser {
testparser { \a foo} 0
} {- {\a foo} 2 word {\a} 1 backslash {\a} 0 simple foo 1 text foo 0 {}}
-test parse-1.7 {Tcl_ParseCommand procedure, missing continuation line in leading space} {
+test parse-1.7 {Tcl_ParseCommand procedure, missing continuation line in leading space} testparser {
testparser " \\\n" 0
} {- {} 0 {}}
-test parse-1.8 {Tcl_ParseCommand procedure, eof in leading space} {
+test parse-1.8 {Tcl_ParseCommand procedure, eof in leading space} testparser {
testparser " foo" 3
} {- {} 0 { foo}}
+test parse-1.9 {Tcl_ParseCommand procedure, backslash newline + newline} testparser {
+ testparser "cmd1\\\n\ncmd2" 0
+} {- cmd1\\\n\n 1 simple cmd1 1 text cmd1 0 cmd2}
+test parse-1.10 {Tcl_ParseCommand procedure, backslash newline + newline} testparser {
+ testparser "list \\\nA B\\\n\nlist C D" 0
+} {- list\ \\\nA\ B\\\n\n 3 simple list 1 text list 0 simple A 1 text A 0 simple B 1 text B 0 {list C D}}
-test parse-2.1 {Tcl_ParseCommand procedure, comments} {
+test parse-2.1 {Tcl_ParseCommand procedure, comments} testparser {
testparser "# foo bar\n foo" 0
} {{# foo bar
} foo 1 simple foo 1 text foo 0 {}}
-test parse-2.2 {Tcl_ParseCommand procedure, several comments} {
+test parse-2.2 {Tcl_ParseCommand procedure, several comments} testparser {
testparser " # foo bar\n # another comment\n\n foo" 0
} {{# foo bar
# another comment
} foo 1 simple foo 1 text foo 0 {}}
-test parse-2.3 {Tcl_ParseCommand procedure, backslash-newline in comments} {
+test parse-2.3 {Tcl_ParseCommand procedure, backslash-newline in comments} testparser {
testparser " # foo bar\\\ncomment on continuation line\nfoo" 0
-} {#\ foo\ bar\\\ncomment\ on\ continuation\ line\n foo 1 simple foo 1 text foo 0 {}}
-test parse-2.4 {Tcl_ParseCommand procedure, missing continuation line in comment} {
+} {\#\ foo\ bar\\\ncomment\ on\ continuation\ line\n foo 1 simple foo 1 text foo 0 {}}
+test parse-2.4 {Tcl_ParseCommand procedure, missing continuation line in comment} testparser {
testparser "# \\\n" 0
-} {#\ \ \ \\\n {} 0 {}}
-test parse-2.5 {Tcl_ParseCommand procedure, eof in comment} {
+} {\#\ \ \ \\\n {} 0 {}}
+test parse-2.5 {Tcl_ParseCommand procedure, eof in comment} testparser {
testparser " # foo bar\nfoo" 8
} {{# foo b} {} 0 {ar
foo}}
-test parse-3.1 {Tcl_ParseCommand procedure, parsing words, skipping space} {
+test parse-3.1 {Tcl_ParseCommand procedure, parsing words, skipping space} testparser {
testparser "foo bar\t\tx" 0
} {- {foo bar x} 3 simple foo 1 text foo 0 simple bar 1 text bar 0 simple x 1 text x 0 {}}
-test parse-3.2 {Tcl_ParseCommand procedure, missing continuation line in leading space} {
+test parse-3.2 {Tcl_ParseCommand procedure, missing continuation line in leading space} testparser {
testparser "abc \\\n" 0
} {- abc\ \ \\\n 1 simple abc 1 text abc 0 {}}
-test parse-3.3 {Tcl_ParseCommand procedure, parsing words, command ends in space} {
+test parse-3.3 {Tcl_ParseCommand procedure, parsing words, command ends in space} testparser {
testparser "foo ; bar x" 0
} {- {foo ;} 1 simple foo 1 text foo 0 { bar x}}
-test parse-3.4 {Tcl_ParseCommand procedure, parsing words, command ends in space} {
+test parse-3.4 {Tcl_ParseCommand procedure, parsing words, command ends in space} testparser {
testparser "foo " 5
} {- {foo } 1 simple foo 1 text foo 0 { }}
-test parse-3.5 {Tcl_ParseCommand procedure, quoted words} {
+test parse-3.5 {Tcl_ParseCommand procedure, quoted words} testparser {
testparser {foo "a b c" d "efg";} 0
} {- {foo "a b c" d "efg";} 4 simple foo 1 text foo 0 simple {"a b c"} 1 text {a b c} 0 simple d 1 text d 0 simple {"efg"} 1 text efg 0 {}}
-test parse-3.6 {Tcl_ParseCommand procedure, words in braces} {
+test parse-3.6 {Tcl_ParseCommand procedure, words in braces} testparser {
testparser {foo {a $b [concat foo]} {c d}} 0
} {- {foo {a $b [concat foo]} {c d}} 3 simple foo 1 text foo 0 simple {{a $b [concat foo]}} 1 text {a $b [concat foo]} 0 simple {{c d}} 1 text {c d} 0 {}}
-test parse-3.7 {Tcl_ParseCommand procedure, error in unquoted word} {
- list [catch {testparser "foo \$\{abc" 0} msg] $msg $errorInfo
+test parse-3.7 {Tcl_ParseCommand procedure, error in unquoted word} testparser {
+ list [catch {testparser "foo \$\{abc" 0} msg] $msg $::errorInfo
} {1 {missing close-brace for variable name} missing\ close-brace\ for\ variable\ name\n\ \ \ \ (remainder\ of\ script:\ \"\{abc\")\n\ \ \ \ invoked\ from\ within\n\"testparser\ \"foo\ \\\$\\\{abc\"\ 0\"}
-test parse-4.1 {Tcl_ParseCommand procedure, simple words} {
+test parse-4.1 {Tcl_ParseCommand procedure, simple words} testparser {
testparser {foo} 0
} {- foo 1 simple foo 1 text foo 0 {}}
-test parse-4.2 {Tcl_ParseCommand procedure, simple words} {
+test parse-4.2 {Tcl_ParseCommand procedure, simple words} testparser {
testparser {{abc}} 0
} {- {{abc}} 1 simple {{abc}} 1 text abc 0 {}}
-test parse-4.3 {Tcl_ParseCommand procedure, simple words} {
+test parse-4.3 {Tcl_ParseCommand procedure, simple words} testparser {
testparser {"c d"} 0
} {- {"c d"} 1 simple {"c d"} 1 text {c d} 0 {}}
-test parse-4.4 {Tcl_ParseCommand procedure, simple words} {
+test parse-4.4 {Tcl_ParseCommand procedure, simple words} testparser {
testparser {x$d} 0
} {- {x$d} 1 word {x$d} 3 text x 0 variable {$d} 1 text d 0 {}}
-test parse-4.5 {Tcl_ParseCommand procedure, simple words} {
+test parse-4.5 {Tcl_ParseCommand procedure, simple words} testparser {
testparser {"a [foo] b"} 0
} {- {"a [foo] b"} 1 word {"a [foo] b"} 3 text {a } 0 command {[foo]} 0 text { b} 0 {}}
-test parse-4.6 {Tcl_ParseCommand procedure, simple words} {
+test parse-4.6 {Tcl_ParseCommand procedure, simple words} testparser {
testparser {$x} 0
} {- {$x} 1 word {$x} 2 variable {$x} 1 text x 0 {}}
-test parse-5.1 {Tcl_ParseCommand procedure, backslash-newline terminates word} {
+test parse-5.1 {Tcl_ParseCommand procedure, backslash-newline terminates word} testparser {
testparser "{abc}\\\n" 0
} {- \{abc\}\\\n 1 simple {{abc}} 1 text abc 0 {}}
-test parse-5.2 {Tcl_ParseCommand procedure, backslash-newline terminates word} {
+test parse-5.2 {Tcl_ParseCommand procedure, backslash-newline terminates word} testparser {
testparser "foo\\\nbar" 0
} {- foo\\\nbar 2 simple foo 1 text foo 0 simple bar 1 text bar 0 {}}
-test parse-5.3 {Tcl_ParseCommand procedure, word terminator is command terminator} {
+test parse-5.3 {Tcl_ParseCommand procedure, word terminator is command terminator} testparser {
testparser "foo\n bar" 0
} {- {foo
} 1 simple foo 1 text foo 0 { bar}}
-test parse-5.4 {Tcl_ParseCommand procedure, word terminator is command terminator} {
+test parse-5.4 {Tcl_ParseCommand procedure, word terminator is command terminator} testparser {
testparser "foo; bar" 0
} {- {foo;} 1 simple foo 1 text foo 0 { bar}}
-test parse-5.5 {Tcl_ParseCommand procedure, word terminator is end of string} {
+test parse-5.5 {Tcl_ParseCommand procedure, word terminator is end of string} testparser {
testparser "\"foo\" bar" 5
} {- {"foo"} 1 simple {"foo"} 1 text foo 0 { bar}}
-test parse-5.6 {Tcl_ParseCommand procedure, junk after close quote} {
- list [catch {testparser {foo "bar"x} 0} msg] $msg $errorInfo
+test parse-5.6 {Tcl_ParseCommand procedure, junk after close quote} testparser {
+ list [catch {testparser {foo "bar"x} 0} msg] $msg $::errorInfo
} {1 {extra characters after close-quote} {extra characters after close-quote
(remainder of script: "x")
invoked from within
"testparser {foo "bar"x} 0"}}
-test parse-5.7 {Tcl_ParseCommand procedure, backslash-newline after close quote} {
+test parse-5.7 {Tcl_ParseCommand procedure, backslash-newline after close quote} testparser {
testparser "foo \"bar\"\\\nx" 0
} {- foo\ \"bar\"\\\nx 3 simple foo 1 text foo 0 simple {"bar"} 1 text bar 0 simple x 1 text x 0 {}}
-test parse-5.8 {Tcl_ParseCommand procedure, junk after close brace} {
- list [catch {testparser {foo {bar}x} 0} msg] $msg $errorInfo
+test parse-5.8 {Tcl_ParseCommand procedure, junk after close brace} testparser {
+ list [catch {testparser {foo {bar}x} 0} msg] $msg $::errorInfo
} {1 {extra characters after close-brace} {extra characters after close-brace
(remainder of script: "x")
invoked from within
"testparser {foo {bar}x} 0"}}
-test parse-5.9 {Tcl_ParseCommand procedure, backslash-newline after close brace} {
+test parse-5.9 {Tcl_ParseCommand procedure, backslash-newline after close brace} testparser {
testparser "foo {bar}\\\nx" 0
} {- foo\ \{bar\}\\\nx 3 simple foo 1 text foo 0 simple {{bar}} 1 text bar 0 simple x 1 text x 0 {}}
-test parse-5.10 {Tcl_ParseCommand procedure, multiple deletion of non-static buffer} {
+test parse-5.10 {Tcl_ParseCommand procedure, multiple deletion of non-static buffer} testparser {
# This test is designed to catch bug 1681.
- list [catch {testparser "a \"\\1\\2\\3\\4\\5\\6\\7\\8\\9\\1\\2\\3\\4\\5\\6\\7\\8" 0} msg] $msg $errorInfo
+ list [catch {testparser "a \"\\1\\2\\3\\4\\5\\6\\7\\8\\9\\1\\2\\3\\4\\5\\6\\7\\8" 0} msg] $msg $::errorInfo
} "1 {missing \"} {missing \"
(remainder of script: \"\"\\1\\2\\3\\4\\5\\6\\7\\8\\9\\1\\2\\3\\4\\5\\6\\7\\8\")
invoked from within
\"testparser \"a \\\"\\\\1\\\\2\\\\3\\\\4\\\\5\\\\6\\\\7\\\\8\\\\9\\\\1\\\\2\\\\3\\\\4\\\\5\\\\6\\\\7\\\\8\" 0\"}"
-test parse-6.1 {ParseTokens procedure, empty word} {
+test parse-5.11 {Tcl_ParseCommand: {*} parsing} testparser {
+ testparser {{expan}} 0
+} {- {{expan}} 1 simple {{expan}} 1 text expan 0 {}}
+test parse-5.12 {Tcl_ParseCommand: {*} parsing} -constraints {
+ testparser
+} -body {
+ testparser {{expan}x} 0
+} -returnCodes error -result {extra characters after close-brace}
+test parse-5.13 {Tcl_ParseCommand: {*} parsing} testparser {
+ testparser {{**}} 0
+} {- {{**}} 1 simple {{**}} 1 text ** 0 {}}
+test parse-5.14 {Tcl_ParseCommand: {*} parsing} -constraints {
+ testparser
+} -body {
+ testparser {{**}x} 0
+} -returnCodes error -result {extra characters after close-brace}
+test parse-5.15 {Tcl_ParseCommand: {*} parsing} -constraints {
+ testparser
+} -body {
+ testparser {{*}{123456}x} 0
+} -returnCodes error -result {extra characters after close-brace}
+test parse-5.16 {Tcl_ParseCommand: {*} parsing} testparser {
+ testparser {{123456\
+ }} 0
+} {- {{123456 }} 1 simple {{123456 }} 1 text {123456 } 0 {}}
+test parse-5.17 {Tcl_ParseCommand: {*} parsing} -constraints {
+ testparser
+} -body {
+ testparser {{123456\
+ }x} 0
+} -returnCodes error -result {extra characters after close-brace}
+test parse-5.18 {Tcl_ParseCommand: {*} parsing} testparser {
+ testparser {{*\
+ }} 0
+} {- {{* }} 1 simple {{* }} 1 text {* } 0 {}}
+test parse-5.19 {Tcl_ParseCommand: {*} parsing} -constraints {
+ testparser
+} -body {
+ testparser {{*\
+ }x} 0
+} -returnCodes error -result {extra characters after close-brace}
+test parse-5.20 {Tcl_ParseCommand: {*} parsing} testparser {
+ testparser {{123456}} 0
+} {- {{123456}} 1 simple {{123456}} 1 text 123456 0 {}}
+test parse-5.21 {Tcl_ParseCommand: {*} parsing} -constraints {
+ testparser
+} -body {
+ testparser {{123456}x} 0
+} -returnCodes error -result {extra characters after close-brace}
+test parse-5.22 {Tcl_ParseCommand: {*} parsing} testparser {
+ testparser {{*}} 0
+} {- {{*}} 1 simple {{*}} 1 text * 0 {}}
+test parse-5.23 {Tcl_ParseCommand: {*} parsing} testparser {
+ testparser {{*} } 0
+} {- {{*} } 1 simple {{*}} 1 text * 0 {}}
+test parse-5.24 {Tcl_ParseCommand: {*} parsing} testparser {
+ testparser {{*}x} 0
+} {- {{*}x} 1 simple x 1 text x 0 {}}
+test parse-5.25 {Tcl_ParseCommand: {*} parsing} testparser {
+ testparser {{*}
+} 0
+} {- {{*}
+} 1 simple {{*}} 1 text * 0 {}}
+test parse-5.26 {Tcl_ParseCommand: {*} parsing} testparser {
+ testparser {{*};} 0
+} {- {{*};} 1 simple {{*}} 1 text * 0 {}}
+test parse-5.27 {Tcl_ParseCommand: {*} parsing} testparser {
+ testparser "{*}\\\n foo bar" 0
+} {- \{*\}\\\n\ foo\ bar 3 simple {{*}} 1 text * 0 simple foo 1 text foo 0 simple bar 1 text bar 0 {}}
+test parse-5.28 {Tcl_ParseCommand: {*} parsing, expanded literals} testparser {
+ testparser {{*}{a b}} 0
+} {- {{*}{a b}} 2 simple a 1 text a 0 simple b 1 text b 0 {}}
+test parse-5.29 {Tcl_ParseCommand: {*} parsing, expanded literals, naked backslashes} testparser {
+ testparser {{*}{a \n b}} 0
+} {- {{*}{a \n b}} 1 expand {{*}{a \n b}} 1 text {a \n b} 0 {}}
+test parse-5.30 {Tcl_ParseCommand: {*} parsing, expanded literals} testparser {
+ testparser {{*}"a b"} 0
+} {- {{*}"a b"} 2 simple a 1 text a 0 simple b 1 text b 0 {}}
+test parse-5.31 {Tcl_ParseCommand: {*} parsing, expanded literals, naked backslashes} testparser {
+ testparser {{*}"a \n b"} 0
+} {- {{*}"a \n b"} 1 expand {{*}"a \n b"} 3 text {a } 0 backslash {\n} 0 text { b} 0 {}}
+
+test parse-6.1 {ParseTokens procedure, empty word} testparser {
testparser {""} 0
} {- {""} 1 simple {""} 1 text {} 0 {}}
-test parse-6.2 {ParseTokens procedure, simple range} {
+test parse-6.2 {ParseTokens procedure, simple range} testparser {
testparser {"abc$x.e"} 0
} {- {"abc$x.e"} 1 word {"abc$x.e"} 4 text abc 0 variable {$x} 1 text x 0 text .e 0 {}}
-test parse-6.3 {ParseTokens procedure, variable reference} {
+test parse-6.3 {ParseTokens procedure, variable reference} testparser {
testparser {abc$x.e $y(z)} 0
} {- {abc$x.e $y(z)} 2 word {abc$x.e} 4 text abc 0 variable {$x} 1 text x 0 text .e 0 word {$y(z)} 3 variable {$y(z)} 2 text y 0 text z 0 {}}
-test parse-6.4 {ParseTokens procedure, variable reference} {
+test parse-6.4 {ParseTokens procedure, variable reference} testparser {
list [catch {testparser {$x([a )} 0} msg] $msg
} {1 {missing close-bracket}}
-test parse-6.5 {ParseTokens procedure, command substitution} {
+test parse-6.5 {ParseTokens procedure, command substitution} testparser {
testparser {[foo $x bar]z} 0
} {- {[foo $x bar]z} 1 word {[foo $x bar]z} 2 command {[foo $x bar]} 0 text z 0 {}}
-test parse-6.6 {ParseTokens procedure, command substitution} {
+test parse-6.6 {ParseTokens procedure, command substitution} testparser {
testparser {[foo \] [a b]]} 0
} {- {[foo \] [a b]]} 1 word {[foo \] [a b]]} 1 command {[foo \] [a b]]} 0 {}}
-test parse-6.7 {ParseTokens procedure, error in command substitution} {
- list [catch {testparser {a [b {}c d] e} 0} msg] $msg $errorInfo
+test parse-6.7 {ParseTokens procedure, error in command substitution} testparser {
+ list [catch {testparser {a [b {}c d] e} 0} msg] $msg $::errorInfo
} {1 {extra characters after close-brace} {extra characters after close-brace
(remainder of script: "c d] e")
invoked from within
@@ -183,87 +275,94 @@ test parse-6.10 {ParseTokens procedure, incomplete sub-command} {
expr 1+1
#this is a comment ]}
} {0}
-test parse-6.11 {ParseTokens procedure, memory allocation for big nested command} {
+test parse-6.11 {ParseTokens procedure, memory allocation for big nested command} testparser {
testparser {[$a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b)]} 0
} {- {[$a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b)]} 1 word {[$a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b)]} 1 command {[$a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b)]} 0 {}}
-test parse-6.12 {ParseTokens procedure, missing close bracket} {
- list [catch {testparser {[foo $x bar} 0} msg] $msg $errorInfo
+test parse-6.12 {ParseTokens procedure, missing close bracket} testparser {
+ list [catch {testparser {[foo $x bar} 0} msg] $msg $::errorInfo
} {1 {missing close-bracket} {missing close-bracket
(remainder of script: "[foo $x bar")
invoked from within
"testparser {[foo $x bar} 0"}}
-test parse-6.13 {ParseTokens procedure, backslash-newline without continuation line} {
- list [catch {testparser "\"a b\\\n" 0} msg] $msg $errorInfo
+test parse-6.13 {ParseTokens procedure, backslash-newline without continuation line} testparser {
+ list [catch {testparser "\"a b\\\n" 0} msg] $msg $::errorInfo
} {1 {missing "} missing\ \"\n\ \ \ \ (remainder\ of\ script:\ \"\"a\ b\\\n\")\n\ \ \ \ invoked\ from\ within\n\"testparser\ \"\\\"a\ b\\\\\\n\"\ 0\"}
-test parse-6.14 {ParseTokens procedure, backslash-newline} {
+test parse-6.14 {ParseTokens procedure, backslash-newline} testparser {
testparser "b\\\nc" 0
} {- b\\\nc 2 simple b 1 text b 0 simple c 1 text c 0 {}}
-test parse-6.15 {ParseTokens procedure, backslash-newline} {
+test parse-6.15 {ParseTokens procedure, backslash-newline} testparser {
testparser "\"b\\\nc\"" 0
} {- \"b\\\nc\" 1 word \"b\\\nc\" 3 text b 0 backslash \\\n 0 text c 0 {}}
-test parse-6.16 {ParseTokens procedure, backslash substitution} {
+test parse-6.16 {ParseTokens procedure, backslash substitution} testparser {
testparser {\n\a\x7f} 0
} {- {\n\a\x7f} 1 word {\n\a\x7f} 3 backslash {\n} 0 backslash {\a} 0 backslash {\x7f} 0 {}}
-test parse-6.17 {ParseTokens procedure, null characters} {
+test parse-6.17 {ParseTokens procedure, null characters} testparser {
testparser [bytestring "foo\0zz"] 0
} "- [bytestring foo\0zz] 1 word [bytestring foo\0zz] 3 text foo 0 text [bytestring \0] 0 text zz 0 {}"
-test parse-6.18 {ParseTokens procedure, seek past numBytes for close-bracket} {
+test parse-6.18 {ParseTokens procedure, seek past numBytes for close-bracket} testparser {
# Test for Bug 681841
list [catch {testparser {[a]} 2} msg] $msg
} {1 {missing close-bracket}}
-test parse-7.1 {Tcl_FreeParse and ExpandTokenArray procedures} {
+test parse-7.1 {Tcl_FreeParse and ExpandTokenArray procedures} testparser {
testparser {$a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) } 0
} {- {$a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) $a(b) } 16 word {$a(b)} 3 variable {$a(b)} 2 text a 0 text b 0 word {$a(b)} 3 variable {$a(b)} 2 text a 0 text b 0 word {$a(b)} 3 variable {$a(b)} 2 text a 0 text b 0 word {$a(b)} 3 variable {$a(b)} 2 text a 0 text b 0 word {$a(b)} 3 variable {$a(b)} 2 text a 0 text b 0 word {$a(b)} 3 variable {$a(b)} 2 text a 0 text b 0 word {$a(b)} 3 variable {$a(b)} 2 text a 0 text b 0 word {$a(b)} 3 variable {$a(b)} 2 text a 0 text b 0 word {$a(b)} 3 variable {$a(b)} 2 text a 0 text b 0 word {$a(b)} 3 variable {$a(b)} 2 text a 0 text b 0 word {$a(b)} 3 variable {$a(b)} 2 text a 0 text b 0 word {$a(b)} 3 variable {$a(b)} 2 text a 0 text b 0 word {$a(b)} 3 variable {$a(b)} 2 text a 0 text b 0 word {$a(b)} 3 variable {$a(b)} 2 text a 0 text b 0 word {$a(b)} 3 variable {$a(b)} 2 text a 0 text b 0 word {$a(b)} 3 variable {$a(b)} 2 text a 0 text b 0 {}}
-testConstraint testevalobjv [llength [info commands testevalobjv]]
-testConstraint testevalex [llength [info commands testevalex]]
test parse-8.1 {Tcl_EvalObjv procedure} testevalobjv {
testevalobjv 0 concat this is a test
} {this is a test}
test parse-8.2 {Tcl_EvalObjv procedure, unknown commands} testevalobjv {
- rename unknown unknown.old
+ rename ::unknown unknown.old
set x [catch {testevalobjv 10 asdf poiu} msg]
- rename unknown.old unknown
+ rename unknown.old ::unknown
list $x $msg
} {1 {invalid command name "asdf"}}
test parse-8.3 {Tcl_EvalObjv procedure, unknown commands} testevalobjv {
- rename unknown unknown.old
- proc unknown args {
+ rename ::unknown unknown.old
+ proc ::unknown args {
return "unknown $args"
}
set x [catch {testevalobjv 0 asdf poiu} msg]
- rename unknown {}
- rename unknown.old unknown
+ rename ::unknown {}
+ rename unknown.old ::unknown
list $x $msg
} {0 {unknown asdf poiu}}
test parse-8.4 {Tcl_EvalObjv procedure, unknown commands} testevalobjv {
- rename unknown unknown.old
- proc unknown args {
+ rename ::unknown unknown.old
+ proc ::unknown args {
error "I don't like that command"
}
set x [catch {testevalobjv 0 asdf poiu} msg]
- rename unknown {}
- rename unknown.old unknown
+ rename ::unknown {}
+ rename unknown.old ::unknown
list $x $msg
} {1 {I don't like that command}}
-test parse-8.5 {Tcl_EvalObjv procedure, command traces} testevalobjv {
+test parse-8.5 {Tcl_EvalObjv procedure, command traces} {testevalobjv testcmdtrace} {
testevalobjv 0 set x 123
testcmdtrace tracetest {testevalobjv 0 set x $x}
} {{testevalobjv 0 set x $x} {testevalobjv 0 set x 123} {set x 123} {set x 123}}
-test parse-8.7 {Tcl_EvalObjv procedure, TCL_EVAL_GLOBAL flag} testevalobjv {
+test parse-8.7 {Tcl_EvalObjv procedure, TCL_EVAL_GLOBAL flag} -constraints {
+ testevalobjv
+} -setup {
proc x {} {
set y 23
set z [testevalobjv 1 set y]
return [list $z $y]
}
- catch {unset y}
- set y 16
+ set ::y 16
+} -cleanup {
+ unset ::y
+} -body {
x
-} {16 23}
-test parse-8.8 {Tcl_EvalObjv procedure, async handlers} testevalobjv {
+} -result {16 23}
+test parse-8.8 {Tcl_EvalObjv procedure, async handlers} -constraints {
+ testevalobjv testasync
+} -setup {
+ variable ::aresult
+ variable ::acode
proc async1 {result code} {
- global aresult acode
+ variable ::aresult
+ variable ::acode
set aresult $result
set acode $code
return "new result"
@@ -271,10 +370,11 @@ test parse-8.8 {Tcl_EvalObjv procedure, async handlers} testevalobjv {
set handler1 [testasync create async1]
set aresult xxx
set acode yyy
- set x [list [catch [list testevalobjv 0 testasync mark $handler1 original 0] msg] $msg $acode $aresult]
+} -cleanup {
testasync delete
- set x
-} {0 {new result} 0 original}
+} -body {
+ list [testevalobjv 0 testasync mark $handler1 original 0] $acode $aresult
+} -result {{new result} 0 original}
test parse-8.9 {Tcl_EvalObjv procedure, exceptional return} testevalobjv {
list [catch {testevalobjv 0 error message} msg] $msg
} {1 message}
@@ -284,8 +384,8 @@ test parse-8.10 {Tcl_EvalObjv procedure, TCL_EVAL_GLOBAL} testevalobjv {
catch {rename ::noSuchCommand {}}
set ::info {}
namespace eval test_ns_1 {
- testevalobjv 1 noSuchCommand
- uplevel #0 noSuchCommand
+ testevalobjv 1 noSuchCommand
+ uplevel #0 noSuchCommand
}
namespace delete test_ns_1
rename ::unknown {}
@@ -301,10 +401,10 @@ test parse-8.11 {Tcl_EvalObjv procedure, TCL_EVAL_INVOKE} testevalobjv {
$::slave alias bar noSuchCommand
set ::info {}
namespace eval test_ns_1 {
- proc foo args {lappend ::info namespace}
- $::slave eval bar
- testevalobjv 1 [list $::slave eval bar]
- uplevel #0 [list $::slave eval bar]
+ proc foo args {lappend ::info namespace}
+ $::slave eval bar
+ testevalobjv 1 [list $::slave eval bar]
+ uplevel #0 [list $::slave eval bar]
}
namespace delete test_ns_1
rename ::foo {}
@@ -314,18 +414,18 @@ test parse-8.11 {Tcl_EvalObjv procedure, TCL_EVAL_INVOKE} testevalobjv {
} [subst {[set level 2; incr level [info level]] global 1 global 1 global}]
test parse-8.12 {Tcl_EvalObjv procedure, TCL_EVAL_INVOKE} {
set ::auto_index(noSuchCommand) {
- proc noSuchCommand {} {lappend ::info global}
+ proc noSuchCommand {} {lappend ::info global}
}
set ::auto_index(::[string trimleft [namespace current]::test_ns_1::noSuchCommand :]) [list \
- proc [namespace current]::test_ns_1::noSuchCommand {} {
- lappend ::info ns
- }]
+ proc [namespace current]::test_ns_1::noSuchCommand {} {
+ lappend ::info ns
+ }]
catch {rename ::noSuchCommand {}}
set ::slave [interp create]
$::slave alias bar noSuchCommand
set ::info {}
namespace eval test_ns_1 {
- $::slave eval bar
+ $::slave eval bar
}
namespace delete test_ns_1
interp delete $::slave
@@ -333,14 +433,15 @@ test parse-8.12 {Tcl_EvalObjv procedure, TCL_EVAL_INVOKE} {
set ::info
} global
-test parse-9.1 {Tcl_LogCommandInfo, line numbers} {
+
+test parse-9.1 {Tcl_LogCommandInfo, line numbers} testevalex {
catch {unset x}
list [catch {testevalex {for {} 1 {} {
# asdf
set x
- }}}] $errorInfo
+ }}}] $::errorInfo
} {1 {can't read "x": no such variable
while executing
"set x"
@@ -360,264 +461,268 @@ test parse-9.1 {Tcl_LogCommandInfo, line numbers} {
set x
}}"}}
test parse-9.2 {Tcl_LogCommandInfo, truncating long commands} {
- list [testevalex {catch {set a b 111111111 222222222 333333333 444444444 555555555 666666666 777777777 888888888 999999999 000000000 aaaaaaaaa bbbbbbbbb ccccccccc ddddddddd eeeeeeeee fffffffff ggggggggg}}] $errorInfo
+ list [catch {set a b 111111111 222222222 333333333 444444444 555555555 666666666 777777777 888888888 999999999 000000000 aaaaaaaaa bbbbbbbbb ccccccccc ddddddddd eeeeeeeee fffffffff ggggggggg}] $::errorInfo
} {1 {wrong # args: should be "set varName ?newValue?"
while executing
"set a b 111111111 222222222 333333333 444444444 555555555 666666666 777777777 888888888 999999999 000000000 aaaaaaaaa bbbbbbbbb ccccccccc ddddddddd ee..."}}
-test parse-10.1 {Tcl_EvalTokens, simple text} {
+test parse-10.1 {Tcl_EvalTokens, simple text} testevalex {
testevalex {concat test}
} {test}
-test parse-10.2 {Tcl_EvalTokens, backslash sequences} {
+test parse-10.2 {Tcl_EvalTokens, backslash sequences} testevalex {
testevalex {concat test\063\062test}
} {test32test}
-test parse-10.3 {Tcl_EvalTokens, nested commands} {
+test parse-10.3 {Tcl_EvalTokens, nested commands} testevalex {
testevalex {concat [expr 2 + 6]}
} {8}
-test parse-10.4 {Tcl_EvalTokens, nested commands} {
+test parse-10.4 {Tcl_EvalTokens, nested commands} testevalex {
catch {unset a}
list [catch {testevalex {concat xxx[expr $a]}} msg] $msg
} {1 {can't read "a": no such variable}}
-test parse-10.5 {Tcl_EvalTokens, simple variables} {
+test parse-10.5 {Tcl_EvalTokens, simple variables} testevalex {
set a hello
testevalex {concat $a}
} {hello}
-test parse-10.6 {Tcl_EvalTokens, array variables} {
+test parse-10.6 {Tcl_EvalTokens, array variables} testevalex {
catch {unset a}
set a(12) 46
testevalex {concat $a(12)}
} {46}
-test parse-10.7 {Tcl_EvalTokens, array variables} {
+test parse-10.7 {Tcl_EvalTokens, array variables} testevalex {
catch {unset a}
set a(12) 46
testevalex {concat $a(1[expr 3 - 1])}
} {46}
-test parse-10.8 {Tcl_EvalTokens, array variables} {
+test parse-10.8 {Tcl_EvalTokens, array variables} testevalex {
catch {unset a}
list [catch {testevalex {concat $x($a)}} msg] $msg
} {1 {can't read "a": no such variable}}
-test parse-10.9 {Tcl_EvalTokens, array variables} {
+test parse-10.9 {Tcl_EvalTokens, array variables} testevalex {
catch {unset a}
list [catch {testevalex {concat xyz$a(1)}} msg] $msg
} {1 {can't read "a(1)": no such variable}}
-test parse-10.10 {Tcl_EvalTokens, object values} {
+test parse-10.10 {Tcl_EvalTokens, object values} testevalex {
set a 123
testevalex {concat $a}
} {123}
-test parse-10.11 {Tcl_EvalTokens, object values} {
+test parse-10.11 {Tcl_EvalTokens, object values} testevalex {
set a 123
testevalex {concat $a$a$a}
} {123123123}
-test parse-10.12 {Tcl_EvalTokens, object values} {
+test parse-10.12 {Tcl_EvalTokens, object values} testevalex {
testevalex {concat [expr 2][expr 4][expr 6]}
} {246}
-test parse-10.13 {Tcl_EvalTokens, string values} {
+test parse-10.13 {Tcl_EvalTokens, string values} testevalex {
testevalex {concat {a" b"}}
} {a" b"}
-test parse-10.14 {Tcl_EvalTokens, string values} {
+test parse-10.14 {Tcl_EvalTokens, string values} testevalex {
set a 111
testevalex {concat x$a.$a.$a}
} {x111.111.111}
-test parse-11.1 {Tcl_EvalEx, TCL_EVAL_GLOBAL flag} {
+test parse-11.1 {Tcl_EvalEx, TCL_EVAL_GLOBAL flag} -constraints {
+ testevalex
+} -setup {
proc x {} {
set y 777
set z [testevalex "set y" global]
return [list $z $y]
}
- catch {unset y}
- set y 321
+ set ::y 321
+} -cleanup {
+ unset ::y
+} -body {
x
-} {321 777}
-test parse-11.2 {Tcl_EvalEx, error while parsing} {
+} -result {321 777}
+test parse-11.2 {Tcl_EvalEx, error while parsing} testevalex {
list [catch {testevalex {concat "abc}} msg] $msg
} {1 {missing "}}
-test parse-11.3 {Tcl_EvalEx, error while collecting words} {
+test parse-11.3 {Tcl_EvalEx, error while collecting words} testevalex {
catch {unset a}
list [catch {testevalex {concat xyz $a}} msg] $msg
} {1 {can't read "a": no such variable}}
-test parse-11.4 {Tcl_EvalEx, error in Tcl_EvalObjv call} {
+test parse-11.4 {Tcl_EvalEx, error in Tcl_EvalObjv call} testevalex {
catch {unset a}
list [catch {testevalex {_bogus_ a b c d}} msg] $msg
} {1 {invalid command name "_bogus_"}}
-test parse-11.5 {Tcl_EvalEx, exceptional return} {
+test parse-11.5 {Tcl_EvalEx, exceptional return} testevalex {
list [catch {testevalex {break}} msg] $msg
} {3 {}}
-test parse-11.6 {Tcl_EvalEx, freeing memory} {
+test parse-11.6 {Tcl_EvalEx, freeing memory} testevalex {
testevalex {concat a b c d e f g h i j k l m n o p q r s t u v w x y z}
} {a b c d e f g h i j k l m n o p q r s t u v w x y z}
-test parse-11.7 {Tcl_EvalEx, multiple commands in script} {
+test parse-11.7 {Tcl_EvalEx, multiple commands in script} testevalex {
list [testevalex {set a b; set c d}] $a $c
} {d b d}
-test parse-11.8 {Tcl_EvalEx, multiple commands in script} {
+test parse-11.8 {Tcl_EvalEx, multiple commands in script} testevalex {
list [testevalex {
set a b
set c d
}] $a $c
} {d b d}
-test parse-11.9 {Tcl_EvalEx, freeing memory after error} {
+test parse-11.9 {Tcl_EvalEx, freeing memory after error} testevalex {
catch {unset a}
list [catch {testevalex {concat a b c d e f g h i j k l m n o p q r s t u v w x y z $a}} msg] $msg
} {1 {can't read "a": no such variable}}
-test parse-11.10 {Tcl_EvalTokens, empty commands} {
+test parse-11.10 {Tcl_EvalTokens, empty commands} testevalex {
testevalex {concat xyz; }
} {xyz}
-test parse-11.11 {Tcl_EvalTokens, empty commands} {
+test parse-11.11 {Tcl_EvalTokens, empty commands} testevalex {
testevalex "concat abc; ; # this is a comment\n"
} {abc}
-test parse-11.12 {Tcl_EvalTokens, empty commands} {
+test parse-11.12 {Tcl_EvalTokens, empty commands} testevalex {
testevalex {}
} {}
-test parse-12.1 {Tcl_ParseVarName procedure, initialization} {
+test parse-12.1 {Tcl_ParseVarName procedure, initialization} testparsevarname {
list [catch {testparsevarname {$a([first second])} 8 0} msg] $msg
} {1 {missing close-bracket}}
-test parse-12.2 {Tcl_ParseVarName procedure, initialization} {
+test parse-12.2 {Tcl_ParseVarName procedure, initialization} testparsevarname {
testparsevarname {$a([first second])} 0 0
} {- {} 0 variable {$a([first second])} 2 text a 0 command {[first second]} 0 {}}
-test parse-12.3 {Tcl_ParseVarName procedure, initialization} {
+test parse-12.3 {Tcl_ParseVarName procedure, initialization} testparsevarname {
list [catch {testparsevarname {$abcd} 3 0} msg] $msg
} {0 {- {} 0 variable {$ab} 1 text ab 0 cd}}
-test parse-12.4 {Tcl_ParseVarName procedure, initialization} {
+test parse-12.4 {Tcl_ParseVarName procedure, initialization} testparsevarname {
testparsevarname {$abcd} 0 0
} {- {} 0 variable {$abcd} 1 text abcd 0 {}}
-test parse-12.5 {Tcl_ParseVarName procedure, just a dollar sign} {
+test parse-12.5 {Tcl_ParseVarName procedure, just a dollar sign} testparsevarname {
testparsevarname {$abcd} 1 0
} {- {} 0 text {$} 0 abcd}
-test parse-12.6 {Tcl_ParseVarName procedure, braced variable name} {
+test parse-12.6 {Tcl_ParseVarName procedure, braced variable name} testparser {
testparser {${..[]b}cd} 0
} {- {${..[]b}cd} 1 word {${..[]b}cd} 3 variable {${..[]b}} 1 text {..[]b} 0 text cd 0 {}}
-test parse-12.7 {Tcl_ParseVarName procedure, braced variable name} {
+test parse-12.7 {Tcl_ParseVarName procedure, braced variable name} testparser {
testparser "\$\{\{\} " 0
} {- \$\{\{\}\ 1 word \$\{\{\} 2 variable \$\{\{\} 1 text \{ 0 {}}
-test parse-12.8 {Tcl_ParseVarName procedure, missing close brace} {
- list [catch {testparser "$\{abc" 0} msg] $msg $errorInfo
+test parse-12.8 {Tcl_ParseVarName procedure, missing close brace} testparser {
+ list [catch {testparser "$\{abc" 0} msg] $msg $::errorInfo
} {1 {missing close-brace for variable name} missing\ close-brace\ for\ variable\ name\n\ \ \ \ (remainder\ of\ script:\ \"\{abc\")\n\ \ \ \ invoked\ from\ within\n\"testparser\ \"\$\\\{abc\"\ 0\"}
-test parse-12.9 {Tcl_ParseVarName procedure, missing close brace} {
+test parse-12.9 {Tcl_ParseVarName procedure, missing close brace} testparsevarname {
list [catch {testparsevarname {${bcd}} 4 0} msg] $msg
} {1 {missing close-brace for variable name}}
-test parse-12.10 {Tcl_ParseVarName procedure, missing close brace} {
+test parse-12.10 {Tcl_ParseVarName procedure, missing close brace} testparsevarname {
list [catch {testparsevarname {${bc}} 4 0} msg] $msg
} {1 {missing close-brace for variable name}}
-test parse-12.11 {Tcl_ParseVarName procedure, simple variable name} {
+test parse-12.11 {Tcl_ParseVarName procedure, simple variable name} testparser {
testparser {$az_AZ.} 0
} {- {$az_AZ.} 1 word {$az_AZ.} 3 variable {$az_AZ} 1 text az_AZ 0 text . 0 {}}
-test parse-12.12 {Tcl_ParseVarName procedure, simple variable name} {
+test parse-12.12 {Tcl_ParseVarName procedure, simple variable name} testparser {
testparser {$abcdefg} 4
} {- {$abc} 1 word {$abc} 2 variable {$abc} 1 text abc 0 defg}
-test parse-12.13 {Tcl_ParseVarName procedure, simple variable name with ::} {
+test parse-12.13 {Tcl_ParseVarName procedure, simple variable name with ::} testparser {
testparser {$xyz::ab:c} 0
} {- {$xyz::ab:c} 1 word {$xyz::ab:c} 3 variable {$xyz::ab} 1 text xyz::ab 0 text :c 0 {}}
-test parse-12.14 {Tcl_ParseVarName procedure, variable names with many colons} {
+test parse-12.14 {Tcl_ParseVarName procedure, variable names with many colons} testparser {
testparser {$xyz:::::c} 0
} {- {$xyz:::::c} 1 word {$xyz:::::c} 2 variable {$xyz:::::c} 1 text xyz:::::c 0 {}}
-test parse-12.15 {Tcl_ParseVarName procedure, : vs. ::} {
+test parse-12.15 {Tcl_ParseVarName procedure, : vs. ::} testparsevarname {
testparsevarname {$ab:cd} 0 0
} {- {} 0 variable {$ab} 1 text ab 0 :cd}
-test parse-12.16 {Tcl_ParseVarName procedure, eof in ::} {
+test parse-12.16 {Tcl_ParseVarName procedure, eof in ::} testparsevarname {
testparsevarname {$ab::cd} 4 0
} {- {} 0 variable {$ab} 1 text ab 0 ::cd}
-test parse-12.17 {Tcl_ParseVarName procedure, eof in ::} {
+test parse-12.17 {Tcl_ParseVarName procedure, eof in ::} testparsevarname {
testparsevarname {$ab:::cd} 5 0
} {- {} 0 variable {$ab::} 1 text ab:: 0 :cd}
-test parse-12.18 {Tcl_ParseVarName procedure, no variable name} {
+test parse-12.18 {Tcl_ParseVarName procedure, no variable name} testparser {
testparser {$$ $.} 0
} {- {$$ $.} 2 word {$$} 2 text {$} 0 text {$} 0 word {$.} 2 text {$} 0 text . 0 {}}
-test parse-12.19 {Tcl_ParseVarName procedure, EOF before (} {
+test parse-12.19 {Tcl_ParseVarName procedure, EOF before (} testparsevarname {
testparsevarname {$ab(cd)} 3 0
} {- {} 0 variable {$ab} 1 text ab 0 (cd)}
-test parse-12.20 {Tcl_ParseVarName procedure, array reference} {
+test parse-12.20 {Tcl_ParseVarName procedure, array reference} testparser {
testparser {$x(abc)} 0
} {- {$x(abc)} 1 word {$x(abc)} 3 variable {$x(abc)} 2 text x 0 text abc 0 {}}
-test parse-12.21 {Tcl_ParseVarName procedure, array reference} {
+test parse-12.21 {Tcl_ParseVarName procedure, array reference} testparser {
testparser {$x(ab$cde[foo bar])} 0
} {- {$x(ab$cde[foo bar])} 1 word {$x(ab$cde[foo bar])} 6 variable {$x(ab$cde[foo bar])} 5 text x 0 text ab 0 variable {$cde} 1 text cde 0 command {[foo bar]} 0 {}}
-test parse-12.22 {Tcl_ParseVarName procedure, array reference} {
+test parse-12.22 {Tcl_ParseVarName procedure, array reference} testparser {
testparser {$x([cmd arg]zz)} 0
} {- {$x([cmd arg]zz)} 1 word {$x([cmd arg]zz)} 4 variable {$x([cmd arg]zz)} 3 text x 0 command {[cmd arg]} 0 text zz 0 {}}
-test parse-12.23 {Tcl_ParseVarName procedure, missing close paren in array reference} {
- list [catch {testparser {$x(poiu} 0} msg] $msg $errorInfo
+test parse-12.23 {Tcl_ParseVarName procedure, missing close paren in array reference} testparser {
+ list [catch {testparser {$x(poiu} 0} msg] $msg $::errorInfo
} {1 {missing )} {missing )
(remainder of script: "(poiu")
invoked from within
"testparser {$x(poiu} 0"}}
-test parse-12.24 {Tcl_ParseVarName procedure, missing close paren in array reference} {
- list [catch {testparsevarname {$ab(cd)} 6 0} msg] $msg $errorInfo
+test parse-12.24 {Tcl_ParseVarName procedure, missing close paren in array reference} testparsevarname {
+ list [catch {testparsevarname {$ab(cd)} 6 0} msg] $msg $::errorInfo
} {1 {missing )} {missing )
(remainder of script: "(cd)")
invoked from within
"testparsevarname {$ab(cd)} 6 0"}}
-test parse-12.25 {Tcl_ParseVarName procedure, nested array reference} {
+test parse-12.25 {Tcl_ParseVarName procedure, nested array reference} testparser {
testparser {$x(a$y(b$z))} 0
} {- {$x(a$y(b$z))} 1 word {$x(a$y(b$z))} 8 variable {$x(a$y(b$z))} 7 text x 0 text a 0 variable {$y(b$z)} 4 text y 0 text b 0 variable {$z} 1 text z 0 {}}
-test parse-13.1 {Tcl_ParseVar procedure} {
+test parse-13.1 {Tcl_ParseVar procedure} testparsevar {
set abc 24
testparsevar {$abc.fg}
} {24 .fg}
-test parse-13.2 {Tcl_ParseVar procedure, no variable name} {
+test parse-13.2 {Tcl_ParseVar procedure, no variable name} testparsevar {
testparsevar {$}
} {{$} {}}
-test parse-13.3 {Tcl_ParseVar procedure, no variable name} {
+test parse-13.3 {Tcl_ParseVar procedure, no variable name} testparsevar {
testparsevar {$.123}
} {{$} .123}
-test parse-13.4 {Tcl_ParseVar procedure, error looking up variable} {
+test parse-13.4 {Tcl_ParseVar procedure, error looking up variable} testparsevar {
catch {unset abc}
list [catch {testparsevar {$abc}} msg] $msg
} {1 {can't read "abc": no such variable}}
-test parse-13.5 {Tcl_ParseVar procedure, error looking up variable} {
+test parse-13.5 {Tcl_ParseVar procedure, error looking up variable} testparsevar {
catch {unset abc}
list [catch {testparsevar {$abc([bogus x y z])}} msg] $msg
} {1 {invalid command name "bogus"}}
-test parse-14.1 {Tcl_ParseBraces procedure, computing string length} {
+test parse-14.1 {Tcl_ParseBraces procedure, computing string length} testparser {
testparser [bytestring "foo\0 bar"] -1
} {- foo 1 simple foo 1 text foo 0 {}}
-test parse-14.2 {Tcl_ParseBraces procedure, computing string length} {
+test parse-14.2 {Tcl_ParseBraces procedure, computing string length} testparser {
testparser "foo bar" -1
} {- {foo bar} 2 simple foo 1 text foo 0 simple bar 1 text bar 0 {}}
-test parse-14.3 {Tcl_ParseBraces procedure, words in braces} {
+test parse-14.3 {Tcl_ParseBraces procedure, words in braces} testparser {
testparser {foo {a $b [concat foo]} {c d}} 0
} {- {foo {a $b [concat foo]} {c d}} 3 simple foo 1 text foo 0 simple {{a $b [concat foo]}} 1 text {a $b [concat foo]} 0 simple {{c d}} 1 text {c d} 0 {}}
-test parse-14.4 {Tcl_ParseBraces procedure, empty nested braces} {
+test parse-14.4 {Tcl_ParseBraces procedure, empty nested braces} testparser {
testparser {foo {{}}} 0
} {- {foo {{}}} 2 simple foo 1 text foo 0 simple {{{}}} 1 text {{}} 0 {}}
-test parse-14.5 {Tcl_ParseBraces procedure, nested braces} {
+test parse-14.5 {Tcl_ParseBraces procedure, nested braces} testparser {
testparser {foo {{a {b} c} {} {d e}}} 0
} {- {foo {{a {b} c} {} {d e}}} 2 simple foo 1 text foo 0 simple {{{a {b} c} {} {d e}}} 1 text {{a {b} c} {} {d e}} 0 {}}
-test parse-14.6 {Tcl_ParseBraces procedure, backslashes in words in braces} {
+test parse-14.6 {Tcl_ParseBraces procedure, backslashes in words in braces} testparser {
testparser "foo {a \\n\\\{}" 0
} {- {foo {a \n\{}} 2 simple foo 1 text foo 0 simple {{a \n\{}} 1 text {a \n\{} 0 {}}
-test parse-14.7 {Tcl_ParseBraces procedure, missing continuation line in braces} {
- list [catch {testparser "\{abc\\\n" 0} msg] $msg $errorInfo
+test parse-14.7 {Tcl_ParseBraces procedure, missing continuation line in braces} testparser {
+ list [catch {testparser "\{abc\\\n" 0} msg] $msg $::errorInfo
} {1 {missing close-brace} missing\ close-brace\n\ \ \ \ (remainder\ of\ script:\ \"\{abc\\\n\")\n\ \ \ \ invoked\ from\ within\n\"testparser\ \"\\\{abc\\\\\\n\"\ 0\"}
-test parse-14.8 {Tcl_ParseBraces procedure, backslash-newline in braces} {
+test parse-14.8 {Tcl_ParseBraces procedure, backslash-newline in braces} testparser {
testparser "foo {\\\nx}" 0
} {- foo\ \{\\\nx\} 2 simple foo 1 text foo 0 word \{\\\nx\} 2 backslash \\\n 0 text x 0 {}}
-test parse-14.9 {Tcl_ParseBraces procedure, backslash-newline in braces} {
+test parse-14.9 {Tcl_ParseBraces procedure, backslash-newline in braces} testparser {
testparser "foo {a \\\n b}" 0
} {- foo\ \{a\ \\\n\ \ \ b\} 2 simple foo 1 text foo 0 word \{a\ \\\n\ \ \ b\} 3 text {a } 0 backslash \\\n\ \ \ 0 text b 0 {}}
-test parse-14.10 {Tcl_ParseBraces procedure, backslash-newline in braces} {
+test parse-14.10 {Tcl_ParseBraces procedure, backslash-newline in braces} testparser {
testparser "foo {xyz\\\n }" 0
} {- foo\ \{xyz\\\n\ \} 2 simple foo 1 text foo 0 word \{xyz\\\n\ \} 2 text xyz 0 backslash \\\n\ 0 {}}
-test parse-14.11 {Tcl_ParseBraces procedure, empty braced string} {
+test parse-14.11 {Tcl_ParseBraces procedure, empty braced string} testparser {
testparser {foo {}} 0
} {- {foo {}} 2 simple foo 1 text foo 0 simple {{}} 1 text {} 0 {}}
-test parse-14.12 {Tcl_ParseBraces procedure, missing close brace} {
- list [catch {testparser "foo \{xy\\\nz" 0} msg] $msg $errorInfo
+test parse-14.12 {Tcl_ParseBraces procedure, missing close brace} testparser {
+ list [catch {testparser "foo \{xy\\\nz" 0} msg] $msg $::errorInfo
} {1 {missing close-brace} missing\ close-brace\n\ \ \ \ (remainder\ of\ script:\ \"\{xy\\\nz\")\n\ \ \ \ invoked\ from\ within\n\"testparser\ \"foo\ \\\{xy\\\\\\nz\"\ 0\"}
-test parse-15.1 {Tcl_ParseQuotedString procedure, computing string length} {
+test parse-15.1 {Tcl_ParseQuotedString procedure, computing string length} testparser {
testparser [bytestring "foo\0 bar"] -1
} {- foo 1 simple foo 1 text foo 0 {}}
-test parse-15.2 {Tcl_ParseQuotedString procedure, computing string length} {
+test parse-15.2 {Tcl_ParseQuotedString procedure, computing string length} testparser {
testparser "foo bar" -1
} {- {foo bar} 2 simple foo 1 text foo 0 simple bar 1 text bar 0 {}}
-test parse-15.3 {Tcl_ParseQuotedString procedure, word is quoted string} {
+test parse-15.3 {Tcl_ParseQuotedString procedure, word is quoted string} testparser {
testparser {foo "a b c" d "efg";} 0
} {- {foo "a b c" d "efg";} 4 simple foo 1 text foo 0 simple {"a b c"} 1 text {a b c} 0 simple d 1 text d 0 simple {"efg"} 1 text efg 0 {}}
-test parse-15.4 {Tcl_ParseQuotedString procedure, garbage after quoted string} {
- list [catch {testparser {foo "a b c"d} 0} msg] $msg $errorInfo
+test parse-15.4 {Tcl_ParseQuotedString procedure, garbage after quoted string} testparser {
+ list [catch {testparser {foo "a b c"d} 0} msg] $msg $::errorInfo
} {1 {extra characters after close-quote} {extra characters after close-quote
(remainder of script: "d")
invoked from within
@@ -762,16 +867,16 @@ test parse-15.50 {CommandComplete procedure} {
info complete "abc\\\n"
} 0
test parse-15.51 {CommandComplete procedure} "
- info complete \"\\{abc\\}\\{\"
+ info complete \"\\\{abc\\\}\\\{\"
" 1
test parse-15.52 {CommandComplete procedure} {
info complete "\"abc\"("
} 1
test parse-15.53 {CommandComplete procedure} "
- info complete \" # {\"
+ info complete \" # \{\"
" 1
test parse-15.54 {CommandComplete procedure} "
- info complete \"foo bar;# {\"
+ info complete \"foo bar;# \{\"
" 1
test parse-15.55 {CommandComplete procedure} {
info complete "set x [bytestring \0]; puts hi"
@@ -789,6 +894,10 @@ test parse-15.59 {CommandComplete procedure} {
# Test for Tcl Bug 684744
info complete [encoding convertfrom identity "\x00;if 1 \{"]
} 0
+test parse-15.60 {CommandComplete procedure} {
+ # Test for Tcl Bug 1968882
+ info complete \\\n
+} 0
test parse-16.1 {Tcl_EvalEx, check termOffset is set correctly for non TCL_OK cases, bug 2535} {
subst {[eval {return foo}]bar}
@@ -798,6 +907,115 @@ test parse-17.1 {Correct return codes from errors during substitution} {
catch {eval {w[continue]}}
} 4
+test parse-18.1 {Tcl_SubstObj, ParseTokens flags} {
+ subst {foo\t$::tcl_library\t[set ::tcl_library]}
+} "foo $::tcl_library $::tcl_library"
+test parse-18.2 {Tcl_SubstObj, ParseTokens flags} {
+ subst -nocommands {foo\t$::tcl_library\t[set ::tcl_library]}
+} "foo $::tcl_library \[set ::tcl_library]"
+test parse-18.3 {Tcl_SubstObj, ParseTokens flags} {
+ subst -novariables {foo\t$::tcl_library\t[set ::tcl_library]}
+} "foo \$::tcl_library $::tcl_library"
+test parse-18.4 {Tcl_SubstObj, ParseTokens flags} {
+ subst -nobackslashes {foo\t$::tcl_library\t[set ::tcl_library]}
+} "foo\\t$::tcl_library\\t$::tcl_library"
+test parse-18.5 {Tcl_SubstObj, ParseTokens flags} {
+ subst -novariables -nobackslashes {foo\t$::tcl_library\t[set ::tcl_library]}
+} "foo\\t\$::tcl_library\\t$::tcl_library"
+test parse-18.6 {Tcl_SubstObj, ParseTokens flags} {
+ subst -nocommands -nobackslashes {foo\t$::tcl_library\t[set ::tcl_library]}
+} "foo\\t$::tcl_library\\t\[set ::tcl_library]"
+test parse-18.7 {Tcl_SubstObj, ParseTokens flags} {
+ subst -nocommands -novariables {foo\t$::tcl_library\t[set ::tcl_library]}
+} "foo \$::tcl_library \[set ::tcl_library]"
+test parse-18.8 {Tcl_SubstObj, ParseTokens flags} {
+ subst -nocommands -novariables -nobackslashes \
+ {foo\t$::tcl_library\t[set ::tcl_library]}
+} "foo\\t\$::tcl_library\\t\[set ::tcl_library]"
+
+test parse-18.9 {Tcl_SubstObj, parse errors} {
+ list [catch "subst foo\$\{foo" msg] $msg
+} [list 1 "missing close-brace for variable name"]
+test parse-18.10 {Tcl_SubstObj, parse errors} {
+ list [catch "subst foo\[set \$\{foo]" msg] $msg
+} [list 1 "missing close-brace for variable name"]
+test parse-18.11 {Tcl_SubstObj, parse errors} {
+ list [catch "subst foo\$array(\$\{foo)" msg] $msg
+} [list 1 "missing close-brace for variable name"]
+test parse-18.12 {Tcl_SubstObj, parse errors} {
+ list [catch "subst foo\$(\$\{foo)" msg] $msg
+} [list 1 "missing close-brace for variable name"]
+test parse-18.13 {Tcl_SubstObj, parse errors} {
+ list [catch "subst \[" msg] $msg
+} [list 1 "missing close-bracket"]
+
+test parse-18.14 {Tcl_SubstObj, exception handling} {
+ subst {abc,[break],def}
+} {abc,}
+test parse-18.15 {Tcl_SubstObj, exception handling} {
+ subst {abc,[continue; expr 1+2],def}
+} {abc,,def}
+test parse-18.16 {Tcl_SubstObj, exception handling} {
+ subst {abc,[return foo; expr 1+2],def}
+} {abc,foo,def}
+test parse-18.17 {Tcl_SubstObj, exception handling} {
+ subst {abc,[return -code 10 foo; expr 1+2],def}
+} {abc,foo,def}
+test parse-18.18 {Tcl_SubstObj, exception handling} {
+ subst {abc,[break; set {} {}{}],def}
+} {abc,}
+test parse-18.19 {Tcl_SubstObj, exception handling} {
+ list [catch {subst {abc,[continue; expr 1+2; set {} {}{}],def}} msg] $msg
+} [list 1 "extra characters after close-brace"]
+test parse-18.20 {Tcl_SubstObj, exception handling} {
+ list [catch {subst {abc,[return foo; expr 1+2; set {} {}{}],def}} msg] $msg
+} [list 1 "extra characters after close-brace"]
+test parse-18.21 {Tcl_SubstObj, exception handling} {
+ list [catch {
+ subst {abc,[return -code 10 foo; expr 1+2; set {} {}{}],def}
+ } msg] $msg
+} [list 1 "extra characters after close-brace"]
+
+test parse-18.22 {Tcl_SubstObj, side effects} {
+ set a 0
+ list [subst {foo[incr a]bar}] $a
+} [list foo1bar 1]
+test parse-18.23 {Tcl_SubstObj, side effects} {
+ set a 0
+ list [subst {foo[incr a; incr a]bar}] $a
+} [list foo2bar 2]
+test parse-18.24 {Tcl_SubstObj, side effects} {
+ set a 0
+ list [subst {foo[incr a; break; incr a]bar}] $a
+} [list foo 1]
+test parse-18.25 {Tcl_SubstObj, side effects} {
+ set a 0
+ list [subst {foo[incr a; continue; incr a]bar}] $a
+} [list foobar 1]
+test parse-18.26 {Tcl_SubstObj, side effects} {
+ set a 0
+ list [subst {foo[incr a; return; incr a]bar}] $a
+} [list foobar 1]
+test parse-18.27 {Tcl_SubstObj, side effects} {
+ set a 0
+ list [subst {foo[incr a; return -code 10; incr a]bar}] $a
+} [list foobar 1]
+test parse-18.28 {Tcl_SubstObj, side effects} {
+ set a 0
+ catch {subst {foo[incr a; parse error {}{}; incr a]bar}}
+ set a
+} 1
+test parse-18.29 {Tcl_SubstObj, side effects} {
+ set a 0
+ catch {subst {foo[incr a; incr a; parse error {}{}]bar}}
+ set a
+} 2
+test parse-18.30 {Tcl_SubstObj, side effects} {
+ set a 0
+ catch {subst {foo[incr a; incr a parse error {}{}]bar}}
+ set a
+} 1
+
test parse-19.1 {Bug 1115904: recursion limit in Tcl_EvalEx} -constraints {
testevalex
} -setup {
@@ -844,45 +1062,46 @@ test parse-19.4 {Bug 1115904: recursion limit in Tcl_EvalEx} -setup {
interp delete i
} -returnCodes error -match glob -result {too many nested*}
-test parse-20.1 {TclParseBackslash: truncated escape} {
+test parse-20.1 {TclParseBackslash: truncated escape} testparser {
testparser {\u12345} 1
} {- \\ 1 simple \\ 1 text \\ 0 u12345}
-test parse-20.2 {TclParseBackslash: truncated escape} {
+test parse-20.2 {TclParseBackslash: truncated escape} testparser {
testparser {\u12345} 2
} {- {\u} 1 word {\u} 1 backslash {\u} 0 12345}
-test parse-20.3 {TclParseBackslash: truncated escape} {
+test parse-20.3 {TclParseBackslash: truncated escape} testparser {
testparser {\u12345} 3
} {- {\u1} 1 word {\u1} 1 backslash {\u1} 0 2345}
-test parse-20.4 {TclParseBackslash: truncated escape} {
+test parse-20.4 {TclParseBackslash: truncated escape} testparser {
testparser {\u12345} 4
} {- {\u12} 1 word {\u12} 1 backslash {\u12} 0 345}
-test parse-20.5 {TclParseBackslash: truncated escape} {
+test parse-20.5 {TclParseBackslash: truncated escape} testparser {
testparser {\u12345} 5
} {- {\u123} 1 word {\u123} 1 backslash {\u123} 0 45}
-test parse-20.6 {TclParseBackslash: truncated escape} {
+test parse-20.6 {TclParseBackslash: truncated escape} testparser {
testparser {\u12345} 6
} {- {\u1234} 1 word {\u1234} 1 backslash {\u1234} 0 5}
-test parse-20.7 {TclParseBackslash: truncated escape} {
+test parse-20.7 {TclParseBackslash: truncated escape} testparser {
testparser {\u12345} 7
} {- {\u12345} 1 word {\u12345} 2 backslash {\u1234} 0 text 5 0 {}}
-test parse-20.8 {TclParseBackslash: truncated escape} {
+test parse-20.8 {TclParseBackslash: truncated escape} testparser {
testparser {\x12X} 1
} {- \\ 1 simple \\ 1 text \\ 0 x12X}
-test parse-20.9 {TclParseBackslash: truncated escape} {
+test parse-20.9 {TclParseBackslash: truncated escape} testparser {
testparser {\x12X} 2
} {- {\x} 1 word {\x} 1 backslash {\x} 0 12X}
-test parse-20.10 {TclParseBackslash: truncated escape} {
+test parse-20.10 {TclParseBackslash: truncated escape} testparser {
testparser {\x12X} 3
} {- {\x1} 1 word {\x1} 1 backslash {\x1} 0 2X}
-test parse-20.11 {TclParseBackslash: truncated escape} {
+test parse-20.11 {TclParseBackslash: truncated escape} testparser {
testparser {\x12X} 4
} {- {\x12} 1 word {\x12} 1 backslash {\x12} 0 X}
-test parse-20.12 {TclParseBackslash: truncated escape} {
+test parse-20.12 {TclParseBackslash: truncated escape} testparser {
testparser {\x12X} 5
} {- {\x12X} 1 word {\x12X} 2 backslash {\x12} 0 text X 0 {}}
-# cleanup
-catch {unset a}
-::tcltest::cleanupTests
+cleanupTests
+}
+
+namespace delete ::tcl::test::parse
return
diff --git a/tests/parseExpr.test b/tests/parseExpr.test
index 156a2cc..7673dbe 100644
--- a/tests/parseExpr.test
+++ b/tests/parseExpr.test
@@ -1,5 +1,5 @@
# This file contains a collection of tests for the procedures in the
-# file tclParseExpr.c. Sourcing this file into Tcl runs the tests and
+# file tclCompExpr.c. Sourcing this file into Tcl runs the tests and
# generates output for errors. No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
@@ -13,638 +13,989 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-# Note that the Tcl expression parser (tclParseExpr.c) does not check
+# Note that the Tcl expression parser (tclCompExpr.c) does not check
# the semantic validity of the expressions it parses. It does not check,
# for example, that a math function actually exists, or that the operands
# of "<<" are integers.
-if {[info commands testexprparser] == {}} {
- puts "This application hasn't been compiled with the \"testexprparser\""
- puts "command, so I can't test the Tcl expression parser."
- ::tcltest::cleanupTests
- return
+testConstraint testexprparser [llength [info commands testexprparser]]
+
+# Big test for correct ordering of data in [expr]
+
+proc testIEEE {} {
+ variable ieeeValues
+ binary scan [binary format dd -1.0 1.0] c* c
+ switch -exact -- $c {
+ {0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
+ # little endian
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \
+ ieeeValues(-Infinity)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \
+ ieeeValues(-Normal)
+ binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
+ ieeeValues(-Subnormal)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
+ ieeeValues(-0)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+0)
+ binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
+ ieeeValues(+Subnormal)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \
+ ieeeValues(+Normal)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
+ ieeeValues(+Infinity)
+ binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
+ ieeeValues(NaN)
+ set ieeeValues(littleEndian) 1
+ return 1
+ }
+ {-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
+ binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Infinity)
+ binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Normal)
+ binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Subnormal)
+ binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-0)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+0)
+ binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Subnormal)
+ binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Normal)
+ binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Infinity)
+ binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(NaN)
+ set ieeeValues(littleEndian) 0
+ return 1
+ }
+ default {
+ return 0
+ }
+ }
}
+testConstraint ieeeFloatingPoint [testIEEE]
-# Some tests only work if wide integers (>32bit) are not found to be
-# integers at all.
-set ::tcltest::testConstraints(wideIntegerUnparsed) \
- [expr {-1 == 0xffffffff}]
+######################################################################
-test parseExpr-1.1 {Tcl_ParseExpr procedure, computing string length} {
+test parseExpr-1.1 {Tcl_ParseExpr procedure, computing string length} testexprparser {
testexprparser [bytestring "1+2\0 +3"] -1
} {- {} 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
-test parseExpr-1.2 {Tcl_ParseExpr procedure, computing string length} {
+test parseExpr-1.2 {Tcl_ParseExpr procedure, computing string length} testexprparser {
testexprparser "1 + 2" -1
} {- {} 0 subexpr {1 + 2} 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
-test parseExpr-1.3 {Tcl_ParseExpr procedure, error getting initial lexeme} {wideIntegerUnparsed} {
- list [catch {testexprparser {12345678901234567890} -1} msg] $msg
-} {1 {integer value too large to represent}}
-test parseExpr-1.4 {Tcl_ParseExpr procedure, error in conditional expression} {
- list [catch {testexprparser {foo+} -1} msg] $msg
-} {1 {syntax error in expression "foo+": variable references require preceding $}}
-test parseExpr-1.5 {Tcl_ParseExpr procedure, lexemes after the expression} {
- list [catch {testexprparser {1+2 345} -1} msg] $msg
-} {1 {syntax error in expression "1+2 345": extra tokens at end of expression}}
+test parseExpr-1.3 {Tcl_ParseExpr procedure, error getting initial lexeme} testexprparser {
+ testexprparser 12345678901234567890 -1
+} {- {} 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
+test parseExpr-1.4 {Tcl_ParseExpr procedure, error in conditional expression} \
+ -constraints testexprparser -body {
+ testexprparser {foo+} -1
+ } -match glob -returnCodes error -result *
+test parseExpr-1.5 {Tcl_ParseExpr procedure, lexemes after the expression} -constraints testexprparser -body {
+ testexprparser {1+2 345} -1
+} -returnCodes error -match glob -result *
-test parseExpr-2.1 {ParseCondExpr procedure, valid test subexpr} {
+test parseExpr-2.1 {ParseCondExpr procedure, valid test subexpr} testexprparser {
testexprparser {2>3? 1 : 0} -1
} {- {} 0 subexpr {2>3? 1 : 0} 11 operator ? 0 subexpr 2>3 5 operator > 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
-test parseExpr-2.2 {ParseCondExpr procedure, error in test subexpr} {
- list [catch {testexprparser {0 || foo} -1} msg] $msg
-} {1 {syntax error in expression "0 || foo": variable references require preceding $}}
-test parseExpr-2.3 {ParseCondExpr procedure, next lexeme isn't "?"} {
+test parseExpr-2.2 {ParseCondExpr procedure, error in test subexpr} \
+ -constraints testexprparser -body {
+ testexprparser {0 || foo} -1
+ } -match glob -returnCodes error -result *
+test parseExpr-2.3 {ParseCondExpr procedure, next lexeme isn't "?"} testexprparser {
testexprparser {1+2} -1
} {- {} 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
-test parseExpr-2.4 {ParseCondExpr procedure, next lexeme is "?"} {
+test parseExpr-2.4 {ParseCondExpr procedure, next lexeme is "?"} testexprparser {
testexprparser {1+2 ? 3 : 4} -1
} {- {} 0 subexpr {1+2 ? 3 : 4} 11 operator ? 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
-test parseExpr-2.5 {ParseCondExpr procedure, bad lexeme after "?"} {wideIntegerUnparsed} {
- list [catch {testexprparser {1+2 ? 12345678901234567890} -1} msg] $msg
-} {1 {integer value too large to represent}}
-test parseExpr-2.6 {ParseCondExpr procedure, valid "then" subexpression} {
+test parseExpr-2.5 {ParseCondExpr procedure, bad lexeme after "?"} testexprparser {
+ testexprparser {1+2 ? 12345678901234567890 : 0} -1
+} {- {} 0 subexpr {1+2 ? 12345678901234567890 : 0} 11 operator ? 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 subexpr 0 1 text 0 0 {}}
+test parseExpr-2.6 {ParseCondExpr procedure, valid "then" subexpression} testexprparser {
testexprparser {1? 3 : 4} -1
} {- {} 0 subexpr {1? 3 : 4} 7 operator ? 0 subexpr 1 1 text 1 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
-test parseExpr-2.7 {ParseCondExpr procedure, error in "then" subexpression} {
- list [catch {testexprparser {1? fred : martha} -1} msg] $msg
-} {1 {syntax error in expression "1? fred : martha": variable references require preceding $}}
-test parseExpr-2.8 {ParseCondExpr procedure, lexeme after "then" subexpr isn't ":"} {
- list [catch {testexprparser {1? 2 martha 3} -1} msg] $msg
-} {1 {syntax error in expression "1? 2 martha 3": missing colon from ternary conditional}}
-test parseExpr-2.9 {ParseCondExpr procedure, valid "else" subexpression} {
+test parseExpr-2.7 {ParseCondExpr procedure, error in "then" subexpression} \
+ -constraints testexprparser -body {
+ testexprparser {1? fred : martha} -1
+ } -match glob -returnCodes error -result *
+test parseExpr-2.8 {ParseCondExpr procedure, lexeme after "then" subexpr isn't ":"} -constraints testexprparser -body {
+ testexprparser {1? 2 martha 3} -1
+} -returnCodes error -match glob -result *
+test parseExpr-2.9 {ParseCondExpr procedure, valid "else" subexpression} testexprparser {
testexprparser {27||3? 3 : 4&&9} -1
} {- {} 0 subexpr {27||3? 3 : 4&&9} 15 operator ? 0 subexpr 27||3 5 operator || 0 subexpr 27 1 text 27 0 subexpr 3 1 text 3 0 subexpr 3 1 text 3 0 subexpr 4&&9 5 operator && 0 subexpr 4 1 text 4 0 subexpr 9 1 text 9 0 {}}
-test parseExpr-2.10 {ParseCondExpr procedure, error in "else" subexpression} {
- list [catch {testexprparser {1? 2 : martha} -1} msg] $msg
-} {1 {syntax error in expression "1? 2 : martha": variable references require preceding $}}
+test parseExpr-2.10 {ParseCondExpr procedure, error in "else" subexpression} \
+ -constraints testexprparser -body {
+ testexprparser {1? 2 : martha} -1
+ } -match glob -returnCodes error -result *
-test parseExpr-3.1 {ParseLorExpr procedure, valid logical and subexpr} {
+test parseExpr-3.1 {ParseLorExpr procedure, valid logical and subexpr} testexprparser {
testexprparser {1&&2 || 3} -1
} {- {} 0 subexpr {1&&2 || 3} 9 operator || 0 subexpr 1&&2 5 operator && 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-3.2 {ParseLorExpr procedure, error in logical and subexpr} {
- list [catch {testexprparser {1&&foo || 3} -1} msg] $msg
-} {1 {syntax error in expression "1&&foo || 3": variable references require preceding $}}
-test parseExpr-3.3 {ParseLorExpr procedure, next lexeme isn't "||"} {
+test parseExpr-3.2 {ParseLorExpr procedure, error in logical and subexpr} \
+ -constraints testexprparser -body {
+ testexprparser {1&&foo || 3} -1
+ } -match glob -returnCodes error -result *
+test parseExpr-3.3 {ParseLorExpr procedure, next lexeme isn't "||"} testexprparser {
testexprparser {1&&2? 1 : 0} -1
} {- {} 0 subexpr {1&&2? 1 : 0} 11 operator ? 0 subexpr 1&&2 5 operator && 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
-test parseExpr-3.4 {ParseLorExpr procedure, next lexeme is "||"} {
+test parseExpr-3.4 {ParseLorExpr procedure, next lexeme is "||"} testexprparser {
testexprparser {1&&2 || 3} -1
} {- {} 0 subexpr {1&&2 || 3} 9 operator || 0 subexpr 1&&2 5 operator && 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-3.5 {ParseLorExpr procedure, bad lexeme after "||"} {wideIntegerUnparsed} {
- list [catch {testexprparser {1&&2 || 12345678901234567890} -1} msg] $msg
-} {1 {integer value too large to represent}}
-test parseExpr-3.6 {ParseLorExpr procedure, valid RHS subexpression} {
+test parseExpr-3.5 {ParseLorExpr procedure, bad lexeme after "||"} testexprparser {
+ testexprparser {1&&2 || 12345678901234567890} -1
+} {- {} 0 subexpr {1&&2 || 12345678901234567890} 9 operator || 0 subexpr 1&&2 5 operator && 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
+test parseExpr-3.6 {ParseLorExpr procedure, valid RHS subexpression} testexprparser {
testexprparser {1&&2 || 3 || 4} -1
} {- {} 0 subexpr {1&&2 || 3 || 4} 13 operator || 0 subexpr {1&&2 || 3} 9 operator || 0 subexpr 1&&2 5 operator && 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
-test parseExpr-3.7 {ParseLorExpr procedure, error in RHS subexpression} {
- list [catch {testexprparser {1&&2 || 3 || martha} -1} msg] $msg
-} {1 {syntax error in expression "1&&2 || 3 || martha": variable references require preceding $}}
+test parseExpr-3.7 {ParseLorExpr procedure, error in RHS subexpression} \
+ -constraints testexprparser -body {
+ testexprparser {1&&2 || 3 || martha} -1
+ } -match glob -returnCodes error -result *
-test parseExpr-4.1 {ParseLandExpr procedure, valid LHS "|" subexpr} {
+test parseExpr-4.1 {ParseLandExpr procedure, valid LHS "|" subexpr} testexprparser {
testexprparser {1|2 && 3} -1
} {- {} 0 subexpr {1|2 && 3} 9 operator && 0 subexpr 1|2 5 operator | 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-4.2 {ParseLandExpr procedure, error in LHS "|" subexpr} {
- list [catch {testexprparser {1&&foo && 3} -1} msg] $msg
-} {1 {syntax error in expression "1&&foo && 3": variable references require preceding $}}
-test parseExpr-4.3 {ParseLandExpr procedure, next lexeme isn't "&&"} {
+test parseExpr-4.2 {ParseLandExpr procedure, error in LHS "|" subexpr} \
+ -constraints testexprparser -body {
+ testexprparser {1&&foo && 3} -1
+ } -match glob -returnCodes error -result *
+test parseExpr-4.3 {ParseLandExpr procedure, next lexeme isn't "&&"} testexprparser {
testexprparser {1|2? 1 : 0} -1
} {- {} 0 subexpr {1|2? 1 : 0} 11 operator ? 0 subexpr 1|2 5 operator | 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
-test parseExpr-4.4 {ParseLandExpr procedure, next lexeme is "&&"} {
+test parseExpr-4.4 {ParseLandExpr procedure, next lexeme is "&&"} testexprparser {
testexprparser {1|2 && 3} -1
} {- {} 0 subexpr {1|2 && 3} 9 operator && 0 subexpr 1|2 5 operator | 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-4.5 {ParseLandExpr procedure, bad lexeme after "&&"} {wideIntegerUnparsed} {
- list [catch {testexprparser {1|2 && 12345678901234567890} -1} msg] $msg
-} {1 {integer value too large to represent}}
-test parseExpr-4.6 {ParseLandExpr procedure, valid RHS subexpression} {
+test parseExpr-4.5 {ParseLandExpr procedure, bad lexeme after "&&"} testexprparser {
+ testexprparser {1|2 && 12345678901234567890} -1
+} {- {} 0 subexpr {1|2 && 12345678901234567890} 9 operator && 0 subexpr 1|2 5 operator | 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
+test parseExpr-4.6 {ParseLandExpr procedure, valid RHS subexpression} testexprparser {
testexprparser {1|2 && 3 && 4} -1
} {- {} 0 subexpr {1|2 && 3 && 4} 13 operator && 0 subexpr {1|2 && 3} 9 operator && 0 subexpr 1|2 5 operator | 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
-test parseExpr-4.7 {ParseLandExpr procedure, error in RHS subexpression} {
- list [catch {testexprparser {1|2 && 3 && martha} -1} msg] $msg
-} {1 {syntax error in expression "1|2 && 3 && martha": variable references require preceding $}}
+test parseExpr-4.7 {ParseLandExpr procedure, error in RHS subexpression} \
+ -constraints testexprparser -body {
+ testexprparser {1|2 && 3 && martha} -1
+ } -match glob -returnCodes error -result *
-test parseExpr-5.1 {ParseBitOrExpr procedure, valid LHS "^" subexpr} {
+test parseExpr-5.1 {ParseBitOrExpr procedure, valid LHS "^" subexpr} testexprparser {
testexprparser {1^2 | 3} -1
} {- {} 0 subexpr {1^2 | 3} 9 operator | 0 subexpr 1^2 5 operator ^ 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-5.2 {ParseBitOrExpr procedure, error in LHS "^" subexpr} {
- list [catch {testexprparser {1|foo | 3} -1} msg] $msg
-} {1 {syntax error in expression "1|foo | 3": variable references require preceding $}}
-test parseExpr-5.3 {ParseBitOrExpr procedure, next lexeme isn't "|"} {
+test parseExpr-5.2 {ParseBitOrExpr procedure, error in LHS "^" subexpr} \
+ -constraints testexprparser -body {
+ testexprparser {1|foo | 3} -1
+ } -match glob -returnCodes error -result *
+test parseExpr-5.3 {ParseBitOrExpr procedure, next lexeme isn't "|"} testexprparser {
testexprparser {1^2? 1 : 0} -1
} {- {} 0 subexpr {1^2? 1 : 0} 11 operator ? 0 subexpr 1^2 5 operator ^ 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
-test parseExpr-5.4 {ParseBitOrExpr procedure, next lexeme is "|"} {
+test parseExpr-5.4 {ParseBitOrExpr procedure, next lexeme is "|"} testexprparser {
testexprparser {1^2 | 3} -1
} {- {} 0 subexpr {1^2 | 3} 9 operator | 0 subexpr 1^2 5 operator ^ 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-5.5 {ParseBitOrExpr procedure, bad lexeme after "|"} {wideIntegerUnparsed} {
- list [catch {testexprparser {1^2 | 12345678901234567890} -1} msg] $msg
-} {1 {integer value too large to represent}}
-test parseExpr-5.6 {ParseBitOrExpr procedure, valid RHS subexpression} {
+test parseExpr-5.5 {ParseBitOrExpr procedure, bad lexeme after "|"} testexprparser {
+ testexprparser {1^2 | 12345678901234567890} -1
+} {- {} 0 subexpr {1^2 | 12345678901234567890} 9 operator | 0 subexpr 1^2 5 operator ^ 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
+test parseExpr-5.6 {ParseBitOrExpr procedure, valid RHS subexpression} testexprparser {
testexprparser {1^2 | 3 | 4} -1
} {- {} 0 subexpr {1^2 | 3 | 4} 13 operator | 0 subexpr {1^2 | 3} 9 operator | 0 subexpr 1^2 5 operator ^ 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
-test parseExpr-5.7 {ParseBitOrExpr procedure, error in RHS subexpression} {
- list [catch {testexprparser {1^2 | 3 | martha} -1} msg] $msg
-} {1 {syntax error in expression "1^2 | 3 | martha": variable references require preceding $}}
+test parseExpr-5.7 {ParseBitOrExpr procedure, error in RHS subexpression} \
+ -constraints testexprparser -body {
+ testexprparser {1^2 | 3 | martha} -1
+ } -match glob -returnCodes error -result *
-test parseExpr-6.1 {ParseBitXorExpr procedure, valid LHS "&" subexpr} {
+test parseExpr-6.1 {ParseBitXorExpr procedure, valid LHS "&" subexpr} testexprparser {
testexprparser {1&2 ^ 3} -1
} {- {} 0 subexpr {1&2 ^ 3} 9 operator ^ 0 subexpr 1&2 5 operator & 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-6.2 {ParseBitXorExpr procedure, error in LHS "&" subexpr} {
- list [catch {testexprparser {1^foo ^ 3} -1} msg] $msg
-} {1 {syntax error in expression "1^foo ^ 3": variable references require preceding $}}
-test parseExpr-6.3 {ParseBitXorExpr procedure, next lexeme isn't "^"} {
+test parseExpr-6.2 {ParseBitXorExpr procedure, error in LHS "&" subexpr} \
+ -constraints testexprparser -body {
+ testexprparser {1^foo ^ 3} -1
+ } -match glob -returnCodes error -result *
+test parseExpr-6.3 {ParseBitXorExpr procedure, next lexeme isn't "^"} testexprparser {
testexprparser {1&2? 1 : 0} -1
} {- {} 0 subexpr {1&2? 1 : 0} 11 operator ? 0 subexpr 1&2 5 operator & 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
-test parseExpr-6.4 {ParseBitXorExpr procedure, next lexeme is "^"} {
+test parseExpr-6.4 {ParseBitXorExpr procedure, next lexeme is "^"} testexprparser {
testexprparser {1&2 ^ 3} -1
} {- {} 0 subexpr {1&2 ^ 3} 9 operator ^ 0 subexpr 1&2 5 operator & 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-6.5 {ParseBitXorExpr procedure, bad lexeme after "^"} {wideIntegerUnparsed} {
- list [catch {testexprparser {1&2 ^ 12345678901234567890} -1} msg] $msg
-} {1 {integer value too large to represent}}
-test parseExpr-6.6 {ParseBitXorExpr procedure, valid RHS subexpression} {
+test parseExpr-6.5 {ParseBitXorExpr procedure, bad lexeme after "^"} testexprparser {
+ testexprparser {1&2 ^ 12345678901234567890} -1
+} {- {} 0 subexpr {1&2 ^ 12345678901234567890} 9 operator ^ 0 subexpr 1&2 5 operator & 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
+test parseExpr-6.6 {ParseBitXorExpr procedure, valid RHS subexpression} testexprparser {
testexprparser {1&2 ^ 3 ^ 4} -1
} {- {} 0 subexpr {1&2 ^ 3 ^ 4} 13 operator ^ 0 subexpr {1&2 ^ 3} 9 operator ^ 0 subexpr 1&2 5 operator & 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
-test parseExpr-6.7 {ParseBitXorExpr procedure, error in RHS subexpression} {
- list [catch {testexprparser {1&2 ^ 3 ^ martha} -1} msg] $msg
-} {1 {syntax error in expression "1&2 ^ 3 ^ martha": variable references require preceding $}}
+test parseExpr-6.7 {ParseBitXorExpr procedure, error in RHS subexpression} \
+ -constraints testexprparser -body {
+ testexprparser {1&2 ^ 3 ^ martha} -1
+ } -match glob -returnCodes error -result *
-test parseExpr-7.1 {ParseBitAndExpr procedure, valid LHS equality subexpr} {
+test parseExpr-7.1 {ParseBitAndExpr procedure, valid LHS equality subexpr} testexprparser {
testexprparser {1==2 & 3} -1
} {- {} 0 subexpr {1==2 & 3} 9 operator & 0 subexpr 1==2 5 operator == 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-7.2 {ParseBitAndExpr procedure, error in LHS equality subexpr} {
- list [catch {testexprparser {1!=foo & 3} -1} msg] $msg
-} {1 {syntax error in expression "1!=foo & 3": variable references require preceding $}}
-test parseExpr-7.3 {ParseBitAndExpr procedure, next lexeme isn't "&"} {
+test parseExpr-7.2 {ParseBitAndExpr procedure, error in LHS equality subexpr} \
+ -constraints testexprparser -body {
+ testexprparser {1!=foo & 3} -1
+ } -match glob -returnCodes error -result *
+test parseExpr-7.3 {ParseBitAndExpr procedure, next lexeme isn't "&"} testexprparser {
testexprparser {1==2? 1 : 0} -1
} {- {} 0 subexpr {1==2? 1 : 0} 11 operator ? 0 subexpr 1==2 5 operator == 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
-test parseExpr-7.4 {ParseBitAndExpr procedure, next lexeme is "&"} {
+test parseExpr-7.4 {ParseBitAndExpr procedure, next lexeme is "&"} testexprparser {
testexprparser {1>2 & 3} -1
} {- {} 0 subexpr {1>2 & 3} 9 operator & 0 subexpr 1>2 5 operator > 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-7.5 {ParseBitAndExpr procedure, bad lexeme after "&"} {wideIntegerUnparsed} {
- list [catch {testexprparser {1==2 & 12345678901234567890} -1} msg] $msg
-} {1 {integer value too large to represent}}
-test parseExpr-7.6 {ParseBitAndExpr procedure, valid RHS subexpression} {
+test parseExpr-7.5 {ParseBitAndExpr procedure, bad lexeme after "&"} {testexprparser} {
+ testexprparser {1==2 & 12345678901234567890} -1
+} {- {} 0 subexpr {1==2 & 12345678901234567890} 9 operator & 0 subexpr 1==2 5 operator == 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
+test parseExpr-7.6 {ParseBitAndExpr procedure, valid RHS subexpression} testexprparser {
testexprparser {1<2 & 3 & 4} -1
} {- {} 0 subexpr {1<2 & 3 & 4} 13 operator & 0 subexpr {1<2 & 3} 9 operator & 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
-test parseExpr-7.7 {ParseBitAndExpr procedure, error in RHS subexpression} {
- list [catch {testexprparser {1==2 & 3>2 & martha} -1} msg] $msg
-} {1 {syntax error in expression "1==2 & 3>2 & martha": variable references require preceding $}}
+test parseExpr-7.7 {ParseBitAndExpr procedure, error in RHS subexpression} \
+ -constraints testexprparser -body {
+ testexprparser {1==2 & 3>2 & martha} -1
+ } -match glob -returnCodes error -result *
-test parseExpr-8.1 {ParseEqualityExpr procedure, valid LHS relational subexpr} {
+test parseExpr-8.1 {ParseEqualityExpr procedure, valid LHS relational subexpr} testexprparser {
testexprparser {1<2 == 3} -1
} {- {} 0 subexpr {1<2 == 3} 9 operator == 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-8.2 {ParseEqualityExpr procedure, error in LHS relational subexpr} {
- list [catch {testexprparser {1>=foo == 3} -1} msg] $msg
-} {1 {syntax error in expression "1>=foo == 3": variable references require preceding $}}
-test parseExpr-8.3 {ParseEqualityExpr procedure, next lexeme isn't "==" or "!="} {
+test parseExpr-8.2 {ParseEqualityExpr procedure, error in LHS relational subexpr} \
+ -constraints testexprparser -body {
+ testexprparser {1>=foo == 3} -1
+ } -match glob -returnCodes error -result *
+test parseExpr-8.3 {ParseEqualityExpr procedure, next lexeme isn't "==" or "!="} testexprparser {
testexprparser {1<2? 1 : 0} -1
} {- {} 0 subexpr {1<2? 1 : 0} 11 operator ? 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
-test parseExpr-8.4 {ParseEqualityExpr procedure, next lexeme is "==" or "!="} {
+test parseExpr-8.4 {ParseEqualityExpr procedure, next lexeme is "==" or "!="} testexprparser {
testexprparser {1<2 == 3} -1
} {- {} 0 subexpr {1<2 == 3} 9 operator == 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-8.5 {ParseEqualityExpr procedure, next lexeme is "==" or "!="} {
+test parseExpr-8.5 {ParseEqualityExpr procedure, next lexeme is "==" or "!="} testexprparser {
testexprparser {1<2 != 3} -1
} {- {} 0 subexpr {1<2 != 3} 9 operator != 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-8.6 {ParseEqualityExpr procedure, bad lexeme after "==" or "!="} {wideIntegerUnparsed} {
- list [catch {testexprparser {1<2 == 12345678901234567890} -1} msg] $msg
-} {1 {integer value too large to represent}}
-test parseExpr-8.7 {ParseEqualityExpr procedure, valid RHS subexpression} {
+test parseExpr-8.6 {ParseEqualityExpr procedure, bad lexeme after "==" or "!="} testexprparser {
+ testexprparser {1<2 == 12345678901234567890} -1
+} {- {} 0 subexpr {1<2 == 12345678901234567890} 9 operator == 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
+test parseExpr-8.7 {ParseEqualityExpr procedure, valid RHS subexpression} testexprparser {
testexprparser {1<2 == 3 == 4} -1
} {- {} 0 subexpr {1<2 == 3 == 4} 13 operator == 0 subexpr {1<2 == 3} 9 operator == 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
-test parseExpr-8.8 {ParseEqualityExpr procedure, error in RHS subexpression} {
- list [catch {testexprparser {1<2 == 3 != martha} -1} msg] $msg
-} {1 {syntax error in expression "1<2 == 3 != martha": variable references require preceding $}}
+test parseExpr-8.8 {ParseEqualityExpr procedure, error in RHS subexpression} \
+ -constraints testexprparser -body {
+ testexprparser {1<2 == 3 != martha} -1
+ } -match glob -returnCodes error -result *
-test parseExpr-9.1 {ParseRelationalExpr procedure, valid LHS shift subexpr} {
+test parseExpr-9.1 {ParseRelationalExpr procedure, valid LHS shift subexpr} testexprparser {
testexprparser {1<<2 < 3} -1
} {- {} 0 subexpr {1<<2 < 3} 9 operator < 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-9.2 {ParseRelationalExpr procedure, error in LHS shift subexpr} {
- list [catch {testexprparser {1>=foo < 3} -1} msg] $msg
-} {1 {syntax error in expression "1>=foo < 3": variable references require preceding $}}
-test parseExpr-9.3 {ParseRelationalExpr procedure, next lexeme isn't relational op} {
+test parseExpr-9.2 {ParseRelationalExpr procedure, error in LHS shift subexpr} \
+ -constraints testexprparser -body {
+ testexprparser {1>=foo < 3} -1
+ } -match glob -returnCodes error -result *
+test parseExpr-9.3 {ParseRelationalExpr procedure, next lexeme isn't relational op} testexprparser {
testexprparser {1<<2? 1 : 0} -1
} {- {} 0 subexpr {1<<2? 1 : 0} 11 operator ? 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
-test parseExpr-9.4 {ParseRelationalExpr procedure, next lexeme is relational op} {
+test parseExpr-9.4 {ParseRelationalExpr procedure, next lexeme is relational op} testexprparser {
testexprparser {1<<2 < 3} -1
} {- {} 0 subexpr {1<<2 < 3} 9 operator < 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-9.5 {ParseRelationalExpr procedure, next lexeme is relational op} {
+test parseExpr-9.5 {ParseRelationalExpr procedure, next lexeme is relational op} testexprparser {
testexprparser {1>>2 > 3} -1
} {- {} 0 subexpr {1>>2 > 3} 9 operator > 0 subexpr 1>>2 5 operator >> 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-9.6 {ParseRelationalExpr procedure, next lexeme is relational op} {
+test parseExpr-9.6 {ParseRelationalExpr procedure, next lexeme is relational op} testexprparser {
testexprparser {1<<2 <= 3} -1
} {- {} 0 subexpr {1<<2 <= 3} 9 operator <= 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-9.7 {ParseRelationalExpr procedure, next lexeme is relational op} {
+test parseExpr-9.7 {ParseRelationalExpr procedure, next lexeme is relational op} testexprparser {
testexprparser {1<<2 >= 3} -1
} {- {} 0 subexpr {1<<2 >= 3} 9 operator >= 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-9.8 {ParseRelationalExpr procedure, bad lexeme after relational op} {wideIntegerUnparsed} {
- list [catch {testexprparser {1<<2 < 12345678901234567890} -1} msg] $msg
-} {1 {integer value too large to represent}}
-test parseExpr-9.9 {ParseRelationalExpr procedure, valid RHS subexpression} {
+test parseExpr-9.8 {ParseRelationalExpr procedure, bad lexeme after relational op} testexprparser {
+ testexprparser {1<<2 < 12345678901234567890} -1
+} {- {} 0 subexpr {1<<2 < 12345678901234567890} 9 operator < 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
+test parseExpr-9.9 {ParseRelationalExpr procedure, valid RHS subexpression} testexprparser {
testexprparser {1<<2 < 3 < 4} -1
} {- {} 0 subexpr {1<<2 < 3 < 4} 13 operator < 0 subexpr {1<<2 < 3} 9 operator < 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
-test parseExpr-9.10 {ParseRelationalExpr procedure, error in RHS subexpression} {
- list [catch {testexprparser {1<<2 < 3 > martha} -1} msg] $msg
-} {1 {syntax error in expression "1<<2 < 3 > martha": variable references require preceding $}}
+test parseExpr-9.10 {ParseRelationalExpr procedure, error in RHS subexpression} \
+ -constraints testexprparser -body {
+ testexprparser {1<<2 < 3 > martha} -1
+ } -match glob -returnCodes error -result *
-test parseExpr-10.1 {ParseShiftExpr procedure, valid LHS add subexpr} {
+test parseExpr-10.1 {ParseShiftExpr procedure, valid LHS add subexpr} testexprparser {
testexprparser {1+2 << 3} -1
} {- {} 0 subexpr {1+2 << 3} 9 operator << 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-10.2 {ParseShiftExpr procedure, error in LHS add subexpr} {
- list [catch {testexprparser {1-foo << 3} -1} msg] $msg
-} {1 {syntax error in expression "1-foo << 3": variable references require preceding $}}
-test parseExpr-10.3 {ParseShiftExpr procedure, next lexeme isn't "<<" or ">>"} {
+test parseExpr-10.2 {ParseShiftExpr procedure, error in LHS add subexpr} \
+ -constraints testexprparser -body {
+ testexprparser {1-foo << 3} -1
+ } -match glob -returnCodes error -result *
+test parseExpr-10.3 {ParseShiftExpr procedure, next lexeme isn't "<<" or ">>"} testexprparser {
testexprparser {1+2? 1 : 0} -1
} {- {} 0 subexpr {1+2? 1 : 0} 11 operator ? 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
-test parseExpr-10.4 {ParseShiftExpr procedure, next lexeme is "<<" or ">>"} {
+test parseExpr-10.4 {ParseShiftExpr procedure, next lexeme is "<<" or ">>"} testexprparser {
testexprparser {1+2 << 3} -1
} {- {} 0 subexpr {1+2 << 3} 9 operator << 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-10.5 {ParseShiftExpr procedure, next lexeme is "<<" or ">>"} {
+test parseExpr-10.5 {ParseShiftExpr procedure, next lexeme is "<<" or ">>"} testexprparser {
testexprparser {1+2 >> 3} -1
} {- {} 0 subexpr {1+2 >> 3} 9 operator >> 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-10.6 {ParseShiftExpr procedure, bad lexeme after "<<" or ">>"} {wideIntegerUnparsed} {
- list [catch {testexprparser {1+2 << 12345678901234567890} -1} msg] $msg
-} {1 {integer value too large to represent}}
-test parseExpr-10.7 {ParseShiftExpr procedure, valid RHS subexpression} {
+test parseExpr-10.6 {ParseShiftExpr procedure, bad lexeme after "<<" or ">>"} testexprparser {
+ testexprparser {1+2 << 12345678901234567890} -1
+} {- {} 0 subexpr {1+2 << 12345678901234567890} 9 operator << 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
+test parseExpr-10.7 {ParseShiftExpr procedure, valid RHS subexpression} testexprparser {
testexprparser {1+2 << 3 << 4} -1
} {- {} 0 subexpr {1+2 << 3 << 4} 13 operator << 0 subexpr {1+2 << 3} 9 operator << 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
-test parseExpr-10.8 {ParseShiftExpr procedure, error in RHS subexpression} {
- list [catch {testexprparser {1+2 << 3 >> martha} -1} msg] $msg
-} {1 {syntax error in expression "1+2 << 3 >> martha": variable references require preceding $}}
+test parseExpr-10.8 {ParseShiftExpr procedure, error in RHS subexpression} \
+ -constraints testexprparser -body {
+ testexprparser {1+2 << 3 >> martha} -1
+ } -match glob -returnCodes error -result *
-test parseExpr-11.1 {ParseAddExpr procedure, valid LHS multiply subexpr} {
+test parseExpr-11.1 {ParseAddExpr procedure, valid LHS multiply subexpr} testexprparser {
testexprparser {1*2 + 3} -1
} {- {} 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-11.2 {ParseAddExpr procedure, error in LHS multiply subexpr} {
- list [catch {testexprparser {1/foo + 3} -1} msg] $msg
-} {1 {syntax error in expression "1/foo + 3": variable references require preceding $}}
-test parseExpr-11.3 {ParseAddExpr procedure, next lexeme isn't "+" or "-"} {
+test parseExpr-11.2 {ParseAddExpr procedure, error in LHS multiply subexpr} \
+ -constraints testexprparser -body {
+ testexprparser {1/foo + 3} -1
+ } -match glob -returnCodes error -result *
+test parseExpr-11.3 {ParseAddExpr procedure, next lexeme isn't "+" or "-"} testexprparser {
testexprparser {1*2? 1 : 0} -1
} {- {} 0 subexpr {1*2? 1 : 0} 11 operator ? 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
-test parseExpr-11.4 {ParseAddExpr procedure, next lexeme is "+" or "-"} {
+test parseExpr-11.4 {ParseAddExpr procedure, next lexeme is "+" or "-"} testexprparser {
testexprparser {1*2 + 3} -1
} {- {} 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-11.5 {ParseAddExpr procedure, next lexeme is "+" or "-"} {
+test parseExpr-11.5 {ParseAddExpr procedure, next lexeme is "+" or "-"} testexprparser {
testexprparser {1*2 - 3} -1
} {- {} 0 subexpr {1*2 - 3} 9 operator - 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-11.6 {ParseAddExpr procedure, bad lexeme after "+" or "-"} {wideIntegerUnparsed} {
- list [catch {testexprparser {1*2 + 12345678901234567890} -1} msg] $msg
-} {1 {integer value too large to represent}}
-test parseExpr-11.7 {ParseAddExpr procedure, valid RHS subexpression} {
+test parseExpr-11.6 {ParseAddExpr procedure, bad lexeme after "+" or "-"} testexprparser {
+ testexprparser {1*2 + 12345678901234567890} -1
+} {- {} 0 subexpr {1*2 + 12345678901234567890} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
+test parseExpr-11.7 {ParseAddExpr procedure, valid RHS subexpression} testexprparser {
testexprparser {1*2 + 3 + 4} -1
} {- {} 0 subexpr {1*2 + 3 + 4} 13 operator + 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
-test parseExpr-11.8 {ParseAddExpr procedure, error in RHS subexpression} {
- list [catch {testexprparser {1*2 + 3 - martha} -1} msg] $msg
-} {1 {syntax error in expression "1*2 + 3 - martha": variable references require preceding $}}
+test parseExpr-11.8 {ParseAddExpr procedure, error in RHS subexpression} \
+ -constraints testexprparser -body {
+ testexprparser {1*2 + 3 - martha} -1
+ } -match glob -returnCodes error -result *
-test parseExpr-12.1 {ParseAddExpr procedure, valid LHS multiply subexpr} {
+test parseExpr-12.1 {ParseAddExpr procedure, valid LHS multiply subexpr} testexprparser {
testexprparser {1*2 + 3} -1
} {- {} 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-12.2 {ParseAddExpr procedure, error in LHS multiply subexpr} {
- list [catch {testexprparser {1/foo + 3} -1} msg] $msg
-} {1 {syntax error in expression "1/foo + 3": variable references require preceding $}}
-test parseExpr-12.3 {ParseAddExpr procedure, next lexeme isn't "+" or "-"} {
+test parseExpr-12.2 {ParseAddExpr procedure, error in LHS multiply subexpr} \
+ -constraints testexprparser -body {
+ testexprparser {1/foo + 3} -1
+ } -match glob -returnCodes error -result *
+test parseExpr-12.3 {ParseAddExpr procedure, next lexeme isn't "+" or "-"} testexprparser {
testexprparser {1*2? 1 : 0} -1
} {- {} 0 subexpr {1*2? 1 : 0} 11 operator ? 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
-test parseExpr-12.4 {ParseAddExpr procedure, next lexeme is "+" or "-"} {
+test parseExpr-12.4 {ParseAddExpr procedure, next lexeme is "+" or "-"} testexprparser {
testexprparser {1*2 + 3} -1
} {- {} 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-12.5 {ParseAddExpr procedure, next lexeme is "+" or "-"} {
+test parseExpr-12.5 {ParseAddExpr procedure, next lexeme is "+" or "-"} testexprparser {
testexprparser {1*2 - 3} -1
} {- {} 0 subexpr {1*2 - 3} 9 operator - 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-12.6 {ParseAddExpr procedure, bad lexeme after "+" or "-"} {wideIntegerUnparsed} {
- list [catch {testexprparser {1*2 + 12345678901234567890} -1} msg] $msg
-} {1 {integer value too large to represent}}
-test parseExpr-12.7 {ParseAddExpr procedure, valid RHS subexpression} {
+test parseExpr-12.6 {ParseAddExpr procedure, bad lexeme after "+" or "-"} testexprparser {
+ testexprparser {1*2 + 12345678901234567890} -1
+} {- {} 0 subexpr {1*2 + 12345678901234567890} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
+test parseExpr-12.7 {ParseAddExpr procedure, valid RHS subexpression} testexprparser {
testexprparser {1*2 + 3 + 4} -1
} {- {} 0 subexpr {1*2 + 3 + 4} 13 operator + 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
-test parseExpr-12.8 {ParseAddExpr procedure, error in RHS subexpression} {
- list [catch {testexprparser {1*2 + 3 - martha} -1} msg] $msg
-} {1 {syntax error in expression "1*2 + 3 - martha": variable references require preceding $}}
+test parseExpr-12.8 {ParseAddExpr procedure, error in RHS subexpression} \
+ -constraints testexprparser -body {
+ testexprparser {1*2 + 3 - martha} -1
+ } -match glob -returnCodes error -result *
-test parseExpr-13.1 {ParseMultiplyExpr procedure, valid LHS unary subexpr} {
+test parseExpr-13.1 {ParseMultiplyExpr procedure, valid LHS unary subexpr} testexprparser {
testexprparser {+2 * 3} -1
} {- {} 0 subexpr {+2 * 3} 7 operator * 0 subexpr +2 3 operator + 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-13.2 {ParseMultiplyExpr procedure, error in LHS unary subexpr} {wideIntegerUnparsed} {
- list [catch {testexprparser {-12345678901234567890 * 3} -1} msg] $msg
-} {1 {integer value too large to represent}}
-test parseExpr-13.3 {ParseMultiplyExpr procedure, next lexeme isn't "*", "/", or "%"} {
+test parseExpr-13.2 {ParseMultiplyExpr procedure, error in LHS unary subexpr} testexprparser {
+ testexprparser {-12345678901234567890 * 3} -1
+} {- {} 0 subexpr {-12345678901234567890 * 3} 7 operator * 0 subexpr -12345678901234567890 3 operator - 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 subexpr 3 1 text 3 0 {}}
+test parseExpr-13.3 {ParseMultiplyExpr procedure, next lexeme isn't "*", "/", or "%"} testexprparser {
testexprparser {+2? 1 : 0} -1
} {- {} 0 subexpr {+2? 1 : 0} 9 operator ? 0 subexpr +2 3 operator + 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
-test parseExpr-13.4 {ParseMultiplyExpr procedure, next lexeme is "*", "/", or "%"} {
+test parseExpr-13.4 {ParseMultiplyExpr procedure, next lexeme is "*", "/", or "%"} testexprparser {
testexprparser {-123 * 3} -1
} {- {} 0 subexpr {-123 * 3} 7 operator * 0 subexpr -123 3 operator - 0 subexpr 123 1 text 123 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-13.5 {ParseMultiplyExpr procedure, next lexeme is "*", "/", or "%"} {
+test parseExpr-13.5 {ParseMultiplyExpr procedure, next lexeme is "*", "/", or "%"} testexprparser {
testexprparser {+-456 / 3} -1
} {- {} 0 subexpr {+-456 / 3} 9 operator / 0 subexpr +-456 5 operator + 0 subexpr -456 3 operator - 0 subexpr 456 1 text 456 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-13.6 {ParseMultiplyExpr procedure, next lexeme is "*", "/", or "%"} {
+test parseExpr-13.6 {ParseMultiplyExpr procedure, next lexeme is "*", "/", or "%"} testexprparser {
testexprparser {+-456 % 3} -1
} {- {} 0 subexpr {+-456 % 3} 9 operator % 0 subexpr +-456 5 operator + 0 subexpr -456 3 operator - 0 subexpr 456 1 text 456 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-13.7 {ParseMultiplyExpr procedure, bad lexeme after "*", "/", or "%"} {wideIntegerUnparsed} {
- list [catch {testexprparser {--++5 / 12345678901234567890} -1} msg] $msg
-} {1 {integer value too large to represent}}
-test parseExpr-13.8 {ParseMultiplyExpr procedure, valid RHS subexpression} {
+test parseExpr-13.7 {ParseMultiplyExpr procedure, bad lexeme after "*", "/", or "%"} testexprparser {
+ testexprparser {--++5 / 12345678901234567890} -1
+} {- {} 0 subexpr {--++5 / 12345678901234567890} 13 operator / 0 subexpr --++5 9 operator - 0 subexpr -++5 7 operator - 0 subexpr ++5 5 operator + 0 subexpr +5 3 operator + 0 subexpr 5 1 text 5 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
+test parseExpr-13.8 {ParseMultiplyExpr procedure, valid RHS subexpression} testexprparser {
testexprparser {-2 / 3 % 4} -1
} {- {} 0 subexpr {-2 / 3 % 4} 11 operator % 0 subexpr {-2 / 3} 7 operator / 0 subexpr -2 3 operator - 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
-test parseExpr-13.9 {ParseMultiplyExpr procedure, error in RHS subexpression} {
- list [catch {testexprparser {++2 / 3 * martha} -1} msg] $msg
-} {1 {syntax error in expression "++2 / 3 * martha": variable references require preceding $}}
+test parseExpr-13.9 {ParseMultiplyExpr procedure, error in RHS subexpression} \
+ -constraints testexprparser -body {
+ testexprparser {++2 / 3 * martha} -1
+ } -match glob -returnCodes error -result *
-test parseExpr-14.1 {ParseUnaryExpr procedure, first token is unary operator} {
+test parseExpr-14.1 {ParseUnaryExpr procedure, first token is unary operator} testexprparser {
testexprparser {+2} -1
} {- {} 0 subexpr +2 3 operator + 0 subexpr 2 1 text 2 0 {}}
-test parseExpr-14.2 {ParseUnaryExpr procedure, first token is unary operator} {
+test parseExpr-14.2 {ParseUnaryExpr procedure, first token is unary operator} testexprparser {
testexprparser {-2} -1
} {- {} 0 subexpr -2 3 operator - 0 subexpr 2 1 text 2 0 {}}
-test parseExpr-14.3 {ParseUnaryExpr procedure, first token is unary operator} {
+test parseExpr-14.3 {ParseUnaryExpr procedure, first token is unary operator} testexprparser {
testexprparser {~2} -1
} {- {} 0 subexpr ~2 3 operator ~ 0 subexpr 2 1 text 2 0 {}}
-test parseExpr-14.4 {ParseUnaryExpr procedure, first token is unary operator} {
+test parseExpr-14.4 {ParseUnaryExpr procedure, first token is unary operator} testexprparser {
testexprparser {!2} -1
} {- {} 0 subexpr !2 3 operator ! 0 subexpr 2 1 text 2 0 {}}
-test parseExpr-14.5 {ParseUnaryExpr procedure, error in lexeme after unary op} {wideIntegerUnparsed} {
- list [catch {testexprparser {-12345678901234567890} -1} msg] $msg
-} {1 {integer value too large to represent}}
-test parseExpr-14.6 {ParseUnaryExpr procedure, simple unary expr after unary op} {
+test parseExpr-14.5 {ParseUnaryExpr procedure, error in lexeme after unary op} testexprparser {
+ testexprparser {-12345678901234567890} -1
+} {- {} 0 subexpr -12345678901234567890 3 operator - 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
+test parseExpr-14.6 {ParseUnaryExpr procedure, simple unary expr after unary op} testexprparser {
testexprparser {+"1234"} -1
} {- {} 0 subexpr +\"1234\" 3 operator + 0 subexpr {"1234"} 1 text 1234 0 {}}
-test parseExpr-14.7 {ParseUnaryExpr procedure, another unary expr after unary op} {
+test parseExpr-14.7 {ParseUnaryExpr procedure, another unary expr after unary op} testexprparser {
testexprparser {~!{fred}} -1
} {- {} 0 subexpr ~!{fred} 5 operator ~ 0 subexpr !{fred} 3 operator ! 0 subexpr {{fred}} 1 text fred 0 {}}
-test parseExpr-14.8 {ParseUnaryExpr procedure, error in unary expr after unary op} {
- list [catch {testexprparser {+-||27} -1} msg] $msg
-} {1 {syntax error in expression "+-||27": unexpected operator ||}}
-test parseExpr-14.9 {ParseUnaryExpr procedure, error in unary expr after unary op} {
- list [catch {testexprparser {+-||27} -1} msg] $msg
-} {1 {syntax error in expression "+-||27": unexpected operator ||}}
-test parseExpr-14.10 {ParseUnaryExpr procedure, first token is not unary op} {
+test parseExpr-14.8 {ParseUnaryExpr procedure, error in unary expr after unary op} -constraints testexprparser -body {
+ testexprparser {+-||27} -1
+} -returnCodes error -match glob -result *
+test parseExpr-14.9 {ParseUnaryExpr procedure, error in unary expr after unary op} -constraints testexprparser -body {
+ testexprparser {+-||27} -1
+} -returnCodes error -match glob -result *
+test parseExpr-14.10 {ParseUnaryExpr procedure, first token is not unary op} testexprparser {
testexprparser {123} -1
} {- {} 0 subexpr 123 1 text 123 0 {}}
-test parseExpr-14.11 {ParseUnaryExpr procedure, not unary expr, complex primary expr} {
+test parseExpr-14.11 {ParseUnaryExpr procedure, not unary expr, complex primary expr} testexprparser {
testexprparser {(1+2)} -1
} {- {} 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
-test parseExpr-14.12 {ParseUnaryExpr procedure, not unary expr, error in primary expr} {wideIntegerUnparsed} {
- list [catch {testexprparser {(12345678901234567890)} -1} msg] $msg
-} {1 {integer value too large to represent}}
+test parseExpr-14.12 {ParseUnaryExpr procedure, not unary expr, error in primary expr} testexprparser {
+ testexprparser {(12345678901234567890)} -1
+} {- {} 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
-test parseExpr-15.1 {ParsePrimaryExpr procedure, just parenthesized subexpr} {
+test parseExpr-15.1 {ParsePrimaryExpr procedure, just parenthesized subexpr} testexprparser {
testexprparser {({abc}/{def})} -1
} {- {} 0 subexpr {{abc}/{def}} 5 operator / 0 subexpr {{abc}} 1 text abc 0 subexpr {{def}} 1 text def 0 {}}
-test parseExpr-15.2 {ParsePrimaryExpr procedure, bad lexeme after "("} {wideIntegerUnparsed} {
- list [catch {testexprparser {(12345678901234567890)} -1} msg] $msg
-} {1 {integer value too large to represent}}
-test parseExpr-15.3 {ParsePrimaryExpr procedure, valid parenthesized subexpr} {
+test parseExpr-15.2 {ParsePrimaryExpr procedure, bad lexeme after "("} {testexprparser} {
+ testexprparser {(12345678901234567890)} -1
+} {- {} 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
+test parseExpr-15.3 {ParsePrimaryExpr procedure, valid parenthesized subexpr} testexprparser {
testexprparser {({abc}? 2*4 : -6)} -1
} {- {} 0 subexpr {{abc}? 2*4 : -6} 13 operator ? 0 subexpr {{abc}} 1 text abc 0 subexpr 2*4 5 operator * 0 subexpr 2 1 text 2 0 subexpr 4 1 text 4 0 subexpr -6 3 operator - 0 subexpr 6 1 text 6 0 {}}
-test parseExpr-15.4 {ParsePrimaryExpr procedure, error in parenthesized subexpr} {
- list [catch {testexprparser {(? 123 : 456)} -1} msg] $msg
-} {1 {syntax error in expression "(? 123 : 456)": unexpected ternary 'then' separator}}
-test parseExpr-15.5 {ParsePrimaryExpr procedure, missing ")" after in parenthesized subexpr} {
- list [catch {testexprparser {({abc}/{def}} -1} msg] $msg
-} {1 {syntax error in expression "({abc}/{def}": looking for close parenthesis}}
-test parseExpr-15.6 {ParsePrimaryExpr procedure, primary is literal} {
+test parseExpr-15.4 {ParsePrimaryExpr procedure, error in parenthesized subexpr} -constraints testexprparser -body {
+ testexprparser {(? 123 : 456)} -1
+} -returnCodes error -match glob -result *
+test parseExpr-15.5 {ParsePrimaryExpr procedure, missing ")" after in parenthesized subexpr} -constraints testexprparser -body {
+ testexprparser {({abc}/{def}} -1
+} -returnCodes error -match glob -result *
+test parseExpr-15.6 {ParsePrimaryExpr procedure, primary is literal} testexprparser {
testexprparser {12345} -1
} {- {} 0 subexpr 12345 1 text 12345 0 {}}
-test parseExpr-15.7 {ParsePrimaryExpr procedure, primary is literal} {
+test parseExpr-15.7 {ParsePrimaryExpr procedure, primary is literal} testexprparser {
testexprparser {12345.6789} -1
} {- {} 0 subexpr 12345.6789 1 text 12345.6789 0 {}}
-test parseExpr-15.8 {ParsePrimaryExpr procedure, primary is var reference} {
+test parseExpr-15.8 {ParsePrimaryExpr procedure, primary is var reference} testexprparser {
testexprparser {$a} -1
} {- {} 0 subexpr {$a} 2 variable {$a} 1 text a 0 {}}
-test parseExpr-15.9 {ParsePrimaryExpr procedure, primary is var reference} {
+test parseExpr-15.9 {ParsePrimaryExpr procedure, primary is var reference} testexprparser {
testexprparser {$a(hello$there)} -1
} {- {} 0 subexpr {$a(hello$there)} 5 variable {$a(hello$there)} 4 text a 0 text hello 0 variable {$there} 1 text there 0 {}}
-test parseExpr-15.10 {ParsePrimaryExpr procedure, primary is var reference} {
+test parseExpr-15.10 {ParsePrimaryExpr procedure, primary is var reference} testexprparser {
testexprparser {$a()} -1
} {- {} 0 subexpr {$a()} 3 variable {$a()} 2 text a 0 text {} 0 {}}
-test parseExpr-15.11 {ParsePrimaryExpr procedure, error in var reference} {
- list [catch {testexprparser {$a(} -1} msg] $msg
-} {1 {missing )}}
-test parseExpr-15.12 {ParsePrimaryExpr procedure, primary is quoted string} {
+test parseExpr-15.11 {ParsePrimaryExpr procedure, error in var reference} -constraints testexprparser -body {
+ testexprparser {$a(} -1
+} -returnCodes error -match glob -result *
+test parseExpr-15.12 {ParsePrimaryExpr procedure, primary is quoted string} testexprparser {
testexprparser {"abc $xyz def"} -1
} {- {} 0 subexpr {"abc $xyz def"} 5 word {"abc $xyz def"} 4 text {abc } 0 variable {$xyz} 1 text xyz 0 text { def} 0 {}}
-test parseExpr-15.13 {ParsePrimaryExpr procedure, error in quoted string} {
- list [catch {testexprparser {"$a(12"} -1} msg] $msg
-} {1 {missing )}}
-test parseExpr-15.14 {ParsePrimaryExpr procedure, quoted string has multiple tokens} {
+test parseExpr-15.13 {ParsePrimaryExpr procedure, error in quoted string} -constraints testexprparser -body {
+ testexprparser {"$a(12"} -1
+} -returnCodes error -match glob -result *
+test parseExpr-15.14 {ParsePrimaryExpr procedure, quoted string has multiple tokens} testexprparser {
testexprparser {"abc [xyz] $def"} -1
} {- {} 0 subexpr {"abc [xyz] $def"} 6 word {"abc [xyz] $def"} 5 text {abc } 0 command {[xyz]} 0 text { } 0 variable {$def} 1 text def 0 {}}
-test parseExpr-15.15 {ParsePrimaryExpr procedure, primary is command} {
+test parseExpr-15.15 {ParsePrimaryExpr procedure, primary is command} testexprparser {
testexprparser {[def]} -1
} {- {} 0 subexpr {[def]} 1 command {[def]} 0 {}}
-test parseExpr-15.16 {ParsePrimaryExpr procedure, primary is multiple commands} {
+test parseExpr-15.16 {ParsePrimaryExpr procedure, primary is multiple commands} testexprparser {
testexprparser {[one; two; three; four;]} -1
} {- {} 0 subexpr {[one; two; three; four;]} 1 command {[one; two; three; four;]} 0 {}}
-test parseExpr-15.17 {ParsePrimaryExpr procedure, primary is multiple commands} {
+test parseExpr-15.17 {ParsePrimaryExpr procedure, primary is multiple commands} testexprparser {
testexprparser {[one; two; three; four;]} -1
} {- {} 0 subexpr {[one; two; three; four;]} 1 command {[one; two; three; four;]} 0 {}}
-test parseExpr-15.18 {ParsePrimaryExpr procedure, missing close bracket} {
- list [catch {testexprparser {[one} -1} msg] $msg
-} {1 {missing close-bracket}}
-test parseExpr-15.19 {ParsePrimaryExpr procedure, primary is braced string} {
+test parseExpr-15.18 {ParsePrimaryExpr procedure, missing close bracket} -constraints testexprparser -body {
+ testexprparser {[one} -1
+} -returnCodes error -match glob -result *
+test parseExpr-15.19 {ParsePrimaryExpr procedure, primary is braced string} testexprparser {
testexprparser {{hello world}} -1
} {- {} 0 subexpr {{hello world}} 1 text {hello world} 0 {}}
-test parseExpr-15.20 {ParsePrimaryExpr procedure, error in primary, which is braced string} {
- list [catch {testexprparser "\{abc\\\n" -1} msg] $msg
-} {1 {missing close-brace}}
-test parseExpr-15.21 {ParsePrimaryExpr procedure, primary is braced string with multiple tokens} {
+test parseExpr-15.20 {ParsePrimaryExpr procedure, error in primary, which is braced string} -constraints testexprparser -body {
+ testexprparser "\{abc\\\n" -1
+} -returnCodes error -match glob -result *
+test parseExpr-15.21 {ParsePrimaryExpr procedure, primary is braced string with multiple tokens} testexprparser {
testexprparser "\{ \\
+123 \}" -1
} {- {} 0 subexpr \{\ \ \\\n\ +123\ \} 4 word \{\ \ \\\n\ +123\ \} 3 text { } 0 backslash \\\n\ 0 text {+123 } 0 {}}
-test parseExpr-15.22 {ParsePrimaryExpr procedure, primary is function call} {
+test parseExpr-15.22 {ParsePrimaryExpr procedure, primary is function call} testexprparser {
testexprparser {foo(123)} -1
} {- {} 0 subexpr foo(123) 3 operator foo 0 subexpr 123 1 text 123 0 {}}
-test parseExpr-15.23 {ParsePrimaryExpr procedure, bad lexeme after function name} {wideIntegerUnparsed} {
- list [catch {testexprparser {foo 12345678901234567890 123)} -1} msg] $msg
-} {1 {integer value too large to represent}}
-test parseExpr-15.24 {ParsePrimaryExpr procedure, lexeme after function name isn't "("} {
- list [catch {testexprparser {foo 27.4 123)} -1} msg] $msg
-} {1 {syntax error in expression "foo 27.4 123)": variable references require preceding $}}
-test parseExpr-15.25 {ParsePrimaryExpr procedure, bad lexeme after "("} {wideIntegerUnparsed} {
- list [catch {testexprparser {foo(12345678901234567890)} -1} msg] $msg
-} {1 {integer value too large to represent}}
-test parseExpr-15.26 {ParsePrimaryExpr procedure, function call, one arg} {
+test parseExpr-15.23 {ParsePrimaryExpr procedure, bad lexeme after function name} -constraints testexprparser -body {
+ testexprparser {foo 12345678901234567890 123)} -1
+} -returnCodes error -match glob -result *
+test parseExpr-15.24 {ParsePrimaryExpr procedure, lexeme after function name isn't "("} \
+ -constraints testexprparser -body {
+ testexprparser {foo 27.4 123)} -1
+ } -match glob -returnCodes error -result *
+test parseExpr-15.25 {ParsePrimaryExpr procedure, bad lexeme after "("} testexprparser {
+ testexprparser {foo(12345678901234567890)} -1
+} {- {} 0 subexpr foo(12345678901234567890) 3 operator foo 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
+test parseExpr-15.26 {ParsePrimaryExpr procedure, function call, one arg} testexprparser {
testexprparser {foo(27*4)} -1
} {- {} 0 subexpr foo(27*4) 7 operator foo 0 subexpr 27*4 5 operator * 0 subexpr 27 1 text 27 0 subexpr 4 1 text 4 0 {}}
-test parseExpr-15.27 {ParsePrimaryExpr procedure, error in function arg} {
- list [catch {testexprparser {foo(*1-2)} -1} msg] $msg
-} {1 {syntax error in expression "foo(*1-2)": unexpected operator *}}
-test parseExpr-15.28 {ParsePrimaryExpr procedure, error in function arg} {
- list [catch {testexprparser {foo(*1-2)} -1} msg] $msg
-} {1 {syntax error in expression "foo(*1-2)": unexpected operator *}}
-test parseExpr-15.29 {ParsePrimaryExpr procedure, function call, comma after arg} {
+test parseExpr-15.27 {ParsePrimaryExpr procedure, error in function arg} -constraints testexprparser -body {
+ testexprparser {foo(*1-2)} -1
+} -returnCodes error -match glob -result *
+test parseExpr-15.28 {ParsePrimaryExpr procedure, error in function arg} -constraints testexprparser -body {
+ testexprparser {foo(*1-2)} -1
+} -returnCodes error -match glob -result *
+test parseExpr-15.29 {ParsePrimaryExpr procedure, function call, comma after arg} testexprparser {
testexprparser {foo(27-2, (-2*[foo]))} -1
} {- {} 0 subexpr {foo(27-2, (-2*[foo]))} 15 operator foo 0 subexpr 27-2 5 operator - 0 subexpr 27 1 text 27 0 subexpr 2 1 text 2 0 subexpr {-2*[foo]} 7 operator * 0 subexpr -2 3 operator - 0 subexpr 2 1 text 2 0 subexpr {[foo]} 1 command {[foo]} 0 {}}
-test parseExpr-15.30 {ParsePrimaryExpr procedure, bad lexeme after comma} {wideIntegerUnparsed} {
- list [catch {testexprparser {foo(123, 12345678901234567890)} -1} msg] $msg
-} {1 {integer value too large to represent}}
-test parseExpr-15.31 {ParsePrimaryExpr procedure, lexeme not "," or ")" after arg} {
- list [catch {testexprparser {foo(123 [foo])} -1} msg] $msg
-} {1 {syntax error in expression "foo(123 [foo])": missing close parenthesis at end of function call}}
-test parseExpr-15.32 {ParsePrimaryExpr procedure, bad lexeme after primary} {wideIntegerUnparsed} {
- list [catch {testexprparser {123 12345678901234567890} -1} msg] $msg
-} {1 {integer value too large to represent}}
-test parseExpr-15.33 {ParsePrimaryExpr procedure, comma-specific message} {
- list [catch {testexprparser {123+,456} -1} msg] $msg
-} {1 {syntax error in expression "123+,456": commas can only separate function arguments}}
-test parseExpr-15.34 {ParsePrimaryExpr procedure, single equal-specific message} {
- list [catch {testexprparser {123+=456} -1} msg] $msg
-} {1 {syntax error in expression "123+=456": single equality character not legal in expressions}}
-test parseExpr-15.35 {ParsePrimaryExpr procedure, error in parenthesized subexpr} {
- list [catch {testexprparser {(: 123 : 456)} -1} msg] $msg
-} {1 {syntax error in expression "(: 123 : 456)": unexpected ternary 'else' separator}}
-test parseExpr-15.36 {ParsePrimaryExpr procedure, missing close-bracket} {
+test parseExpr-15.30 {ParsePrimaryExpr procedure, bad lexeme after comma} testexprparser {
+ testexprparser {foo(123, 12345678901234567890)} -1
+} {- {} 0 subexpr {foo(123, 12345678901234567890)} 5 operator foo 0 subexpr 123 1 text 123 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
+test parseExpr-15.31 {ParsePrimaryExpr procedure, lexeme not "," or ")" after arg} -constraints testexprparser -body {
+ testexprparser {foo(123 [foo])} -1
+} -returnCodes error -match glob -result *
+test parseExpr-15.32 {ParsePrimaryExpr procedure, bad lexeme after primary} -constraints testexprparser -body {
+ testexprparser {123 12345678901234567890} -1
+} -returnCodes error -match glob -result *
+test parseExpr-15.33 {ParsePrimaryExpr procedure, comma-specific message} -constraints testexprparser -body {
+ testexprparser {123+,456} -1
+} -returnCodes error -match glob -result *
+test parseExpr-15.34 {ParsePrimaryExpr procedure, single equal-specific message} -constraints testexprparser -body {
+ testexprparser {123+=456} -1
+} -returnCodes error -match glob -result *
+test parseExpr-15.35 {ParsePrimaryExpr procedure, error in parenthesized subexpr} -constraints testexprparser -body {
+ testexprparser {(: 123 : 456)} -1
+} -returnCodes error -match glob -result *
+test parseExpr-15.36 {ParsePrimaryExpr procedure, missing close-bracket} -constraints testexprparser -body {
# Test for Bug 681841
- list [catch {testexprparser {[set a [format bc]} -1} msg] $msg
-} {1 {missing close-bracket}}
+ testexprparser {[set a [format bc]} -1
+} -returnCodes error -match glob -result *
-test parseExpr-16.1 {GetLexeme procedure, whitespace before lexeme} {
+test parseExpr-16.1 {GetLexeme procedure, whitespace before lexeme} testexprparser {
testexprparser { 123} -1
} {- {} 0 subexpr 123 1 text 123 0 {}}
-test parseExpr-16.2 {GetLexeme procedure, whitespace before lexeme} {
+test parseExpr-16.2 {GetLexeme procedure, whitespace before lexeme} testexprparser {
testexprparser { \
456} -1
} {- {} 0 subexpr 456 1 text 456 0 {}}
-test parseExpr-16.3 {GetLexeme procedure, no lexeme after whitespace} {
+test parseExpr-16.3 {GetLexeme procedure, no lexeme after whitespace} testexprparser {
testexprparser { 123 \
} -1
} {- {} 0 subexpr 123 1 text 123 0 {}}
-test parseExpr-16.4 {GetLexeme procedure, integer lexeme} {
+test parseExpr-16.4 {GetLexeme procedure, integer lexeme} testexprparser {
testexprparser {000} -1
} {- {} 0 subexpr 000 1 text 000 0 {}}
-test parseExpr-16.5 {GetLexeme procedure, integer lexeme too big} {wideIntegerUnparsed} {
- list [catch {testexprparser {12345678901234567890} -1} msg] $msg
-} {1 {integer value too large to represent}}
-
-test parseExpr-16.6 {GetLexeme procedure, bad integer lexeme} -body {
- testexprparser {0999} -1
+test parseExpr-16.5 {GetLexeme procedure, integer lexeme too big} testexprparser {
+ testexprparser {12345678901234567890} -1
+} {- {} 0 subexpr 12345678901234567890 1 text 12345678901234567890 0 {}}
+test parseExpr-16.6 {GetLexeme procedure, bad integer lexeme} -constraints testexprparser -body {
+ testexprparser {0o999} -1
} -returnCodes error -match glob -result {*invalid octal number*}
-
-test parseExpr-16.7 {GetLexeme procedure, double lexeme} {
+test parseExpr-16.7 {GetLexeme procedure, double lexeme} testexprparser {
testexprparser {0.999} -1
} {- {} 0 subexpr 0.999 1 text 0.999 0 {}}
-test parseExpr-16.8 {GetLexeme procedure, double lexeme} {
+test parseExpr-16.8 {GetLexeme procedure, double lexeme} testexprparser {
testexprparser {.123} -1
} {- {} 0 subexpr .123 1 text .123 0 {}}
-test parseExpr-16.9 {GetLexeme procedure, double lexeme} {nonPortable unixOnly} {
+test parseExpr-16.9 {GetLexeme procedure, double lexeme} {testexprparser unix} {
testexprparser {nan} -1
} {- {} 0 subexpr nan 1 text nan 0 {}}
-test parseExpr-16.10 {GetLexeme procedure, double lexeme} {nonPortable unixOnly} {
+test parseExpr-16.10 {GetLexeme procedure, double lexeme} {testexprparser unix} {
testexprparser {NaN} -1
} {- {} 0 subexpr NaN 1 text NaN 0 {}}
-test parseExpr-16.11 {GetLexeme procedure, bad double lexeme too big} {
+test parseExpr-16.11a {GetLexeme procedure, bad double lexeme too big} {testexprparser && !ieeeFloatingPoint} {
list [catch {testexprparser {123.e+99999999999999} -1} msg] $msg
} {1 {floating-point value too large to represent}}
-test parseExpr-16.12 {GetLexeme procedure, bad double lexeme} {
- list [catch {testexprparser {123.4x56} -1} msg] $msg
-} {1 {syntax error in expression "123.4x56": extra tokens at end of expression}}
-test parseExpr-16.13 {GetLexeme procedure, lexeme is "["} {
+test parseExpr-16.11b {GetLexeme procedure, bad double lexeme too big} {testexprparser && ieeeFloatingPoint} {
+ list [catch {testexprparser {123.e+99999999999999} -1} msg] $msg
+} {0 {- {} 0 subexpr 123.e+99999999999999 1 text 123.e+99999999999999 0 {}}}
+test parseExpr-16.12 {GetLexeme procedure, bad double lexeme} -constraints testexprparser -body {
+ testexprparser {123.4x56} -1
+} -returnCodes error -match glob -result *
+test parseExpr-16.13 {GetLexeme procedure, lexeme is "["} testexprparser {
testexprparser {[foo]} -1
} {- {} 0 subexpr {[foo]} 1 command {[foo]} 0 {}}
-test parseExpr-16.14 {GetLexeme procedure, lexeme is open brace} {
+test parseExpr-16.14 {GetLexeme procedure, lexeme is open brace} testexprparser {
testexprparser {{bar}} -1
} {- {} 0 subexpr {{bar}} 1 text bar 0 {}}
-test parseExpr-16.15 {GetLexeme procedure, lexeme is "("} {
+test parseExpr-16.15 {GetLexeme procedure, lexeme is "("} testexprparser {
testexprparser {(123)} -1
} {- {} 0 subexpr 123 1 text 123 0 {}}
-test parseExpr-16.16 {GetLexeme procedure, lexeme is ")"} {
+test parseExpr-16.16 {GetLexeme procedure, lexeme is ")"} testexprparser {
testexprparser {(2*3)} -1
} {- {} 0 subexpr 2*3 5 operator * 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-16.17 {GetLexeme procedure, lexeme is "$"} {
+test parseExpr-16.17 {GetLexeme procedure, lexeme is "$"} testexprparser {
testexprparser {$wombat} -1
} {- {} 0 subexpr {$wombat} 2 variable {$wombat} 1 text wombat 0 {}}
-test parseExpr-16.18 "GetLexeme procedure, lexeme is '\"'" {
+test parseExpr-16.18 "GetLexeme procedure, lexeme is '\"'" testexprparser {
testexprparser {"fred"} -1
} {- {} 0 subexpr {"fred"} 1 text fred 0 {}}
-test parseExpr-16.19 {GetLexeme procedure, lexeme is ","} {
+test parseExpr-16.19 {GetLexeme procedure, lexeme is ","} testexprparser {
testexprparser {foo(1,2)} -1
} {- {} 0 subexpr foo(1,2) 5 operator foo 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
-test parseExpr-16.20 {GetLexeme procedure, lexeme is "*"} {
+test parseExpr-16.20 {GetLexeme procedure, lexeme is "*"} testexprparser {
testexprparser {$a*$b} -1
} {- {} 0 subexpr {$a*$b} 7 operator * 0 subexpr {$a} 2 variable {$a} 1 text a 0 subexpr {$b} 2 variable {$b} 1 text b 0 {}}
-test parseExpr-16.21 {GetLexeme procedure, lexeme is "/"} {
+test parseExpr-16.21 {GetLexeme procedure, lexeme is "/"} testexprparser {
testexprparser {5/6} -1
} {- {} 0 subexpr 5/6 5 operator / 0 subexpr 5 1 text 5 0 subexpr 6 1 text 6 0 {}}
-test parseExpr-16.22 {GetLexeme procedure, lexeme is "%"} {
+test parseExpr-16.22 {GetLexeme procedure, lexeme is "%"} testexprparser {
testexprparser {5%[xxx]} -1
} {- {} 0 subexpr {5%[xxx]} 5 operator % 0 subexpr 5 1 text 5 0 subexpr {[xxx]} 1 command {[xxx]} 0 {}}
-test parseExpr-16.23 {GetLexeme procedure, lexeme is "+"} {
+test parseExpr-16.23 {GetLexeme procedure, lexeme is "+"} testexprparser {
testexprparser {1+2} -1
} {- {} 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
-test parseExpr-16.24 {GetLexeme procedure, lexeme is "-"} {
+test parseExpr-16.24 {GetLexeme procedure, lexeme is "-"} testexprparser {
testexprparser {.12-0e27} -1
} {- {} 0 subexpr .12-0e27 5 operator - 0 subexpr .12 1 text .12 0 subexpr 0e27 1 text 0e27 0 {}}
-test parseExpr-16.25 {GetLexeme procedure, lexeme is "?" or ":"} {
+test parseExpr-16.25 {GetLexeme procedure, lexeme is "?" or ":"} testexprparser {
testexprparser {$b? 1 : 0} -1
} {- {} 0 subexpr {$b? 1 : 0} 8 operator ? 0 subexpr {$b} 2 variable {$b} 1 text b 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
-test parseExpr-16.26 {GetLexeme procedure, lexeme is "<"} {
+test parseExpr-16.26 {GetLexeme procedure, lexeme is "<"} testexprparser {
testexprparser {2<3} -1
} {- {} 0 subexpr 2<3 5 operator < 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-16.27 {GetLexeme procedure, lexeme is "<<"} {
+test parseExpr-16.27 {GetLexeme procedure, lexeme is "<<"} testexprparser {
testexprparser {2<<3} -1
} {- {} 0 subexpr 2<<3 5 operator << 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-16.28 {GetLexeme procedure, lexeme is "<="} {
+test parseExpr-16.28 {GetLexeme procedure, lexeme is "<="} testexprparser {
testexprparser {2<=3} -1
} {- {} 0 subexpr 2<=3 5 operator <= 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-16.29 {GetLexeme procedure, lexeme is ">"} {
+test parseExpr-16.29 {GetLexeme procedure, lexeme is ">"} testexprparser {
testexprparser {2>3} -1
} {- {} 0 subexpr 2>3 5 operator > 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-16.30 {GetLexeme procedure, lexeme is ">>"} {
+test parseExpr-16.30 {GetLexeme procedure, lexeme is ">>"} testexprparser {
testexprparser {2>>3} -1
} {- {} 0 subexpr 2>>3 5 operator >> 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-16.31 {GetLexeme procedure, lexeme is ">="} {
+test parseExpr-16.31 {GetLexeme procedure, lexeme is ">="} testexprparser {
testexprparser {2>=3} -1
} {- {} 0 subexpr 2>=3 5 operator >= 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-16.32 {GetLexeme procedure, lexeme is "=="} {
+test parseExpr-16.32 {GetLexeme procedure, lexeme is "=="} testexprparser {
testexprparser {2==3} -1
} {- {} 0 subexpr 2==3 5 operator == 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-16.33 {GetLexeme procedure, bad lexeme starting with "="} {
- list [catch {testexprparser {2=+3} -1} msg] $msg
-} {1 {syntax error in expression "2=+3": extra tokens at end of expression}}
-test parseExpr-16.34 {GetLexeme procedure, lexeme is "!="} {
+test parseExpr-16.33 {GetLexeme procedure, bad lexeme starting with "="} -constraints testexprparser -body {
+ testexprparser {2=+3} -1
+} -returnCodes error -match glob -result *
+test parseExpr-16.34 {GetLexeme procedure, lexeme is "!="} testexprparser {
testexprparser {2!=3} -1
} {- {} 0 subexpr 2!=3 5 operator != 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-16.35 {GetLexeme procedure, lexeme is "!"} {
+test parseExpr-16.35 {GetLexeme procedure, lexeme is "!"} testexprparser {
testexprparser {!2} -1
} {- {} 0 subexpr !2 3 operator ! 0 subexpr 2 1 text 2 0 {}}
-test parseExpr-16.36 {GetLexeme procedure, lexeme is "&&"} {
+test parseExpr-16.36 {GetLexeme procedure, lexeme is "&&"} testexprparser {
testexprparser {2&&3} -1
} {- {} 0 subexpr 2&&3 5 operator && 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-16.37 {GetLexeme procedure, lexeme is "&"} {
+test parseExpr-16.37 {GetLexeme procedure, lexeme is "&"} testexprparser {
testexprparser {1&2} -1
} {- {} 0 subexpr 1&2 5 operator & 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
-test parseExpr-16.38 {GetLexeme procedure, lexeme is "^"} {
+test parseExpr-16.38 {GetLexeme procedure, lexeme is "^"} testexprparser {
testexprparser {1^2} -1
} {- {} 0 subexpr 1^2 5 operator ^ 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
-test parseExpr-16.39 {GetLexeme procedure, lexeme is "||"} {
+test parseExpr-16.39 {GetLexeme procedure, lexeme is "||"} testexprparser {
testexprparser {2||3} -1
} {- {} 0 subexpr 2||3 5 operator || 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-16.40 {GetLexeme procedure, lexeme is "|"} {
+test parseExpr-16.40 {GetLexeme procedure, lexeme is "|"} testexprparser {
testexprparser {1|2} -1
} {- {} 0 subexpr 1|2 5 operator | 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
-test parseExpr-16.41 {GetLexeme procedure, lexeme is "~"} {
+test parseExpr-16.41 {GetLexeme procedure, lexeme is "~"} testexprparser {
testexprparser {~2} -1
} {- {} 0 subexpr ~2 3 operator ~ 0 subexpr 2 1 text 2 0 {}}
-test parseExpr-16.42 {GetLexeme procedure, lexeme is func name} {
+test parseExpr-16.42 {GetLexeme procedure, lexeme is func name} testexprparser {
testexprparser {george()} -1
} {- {} 0 subexpr george() 1 operator george 0 {}}
-test parseExpr-16.43 {GetLexeme procedure, lexeme is func name} {
+test parseExpr-16.43 {GetLexeme procedure, lexeme is func name} testexprparser {
testexprparser {harmonic_ratio(2,3)} -1
} {- {} 0 subexpr harmonic_ratio(2,3) 5 operator harmonic_ratio 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
-test parseExpr-16.44 {GetLexeme procedure, unknown lexeme} {
- list [catch {testexprparser {@27} -1} msg] $msg
-} {1 {syntax error in expression "@27": character not legal in expressions}}
+test parseExpr-16.44 {GetLexeme procedure, unknown lexeme} -constraints testexprparser -body {
+ testexprparser {@27} -1
+} -returnCodes error -match glob -result *
-test parseExpr-17.1 {PrependSubExprTokens procedure, expand token array} {
+test parseExpr-17.1 {PrependSubExprTokens procedure, expand token array} testexprparser {
testexprparser {[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]} -1
} {- {} 0 subexpr {[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]} 13 operator && 0 subexpr {[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]} 9 operator && 0 subexpr {[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]} 5 operator && 0 subexpr {[string compare [format %c $i] [string index $a $i]]} 1 command {[string compare [format %c $i] [string index $a $i]]} 0 subexpr {[string compare [format %c $i] [string index $a $i]]} 1 command {[string compare [format %c $i] [string index $a $i]]} 0 subexpr {[string compare [format %c $i] [string index $a $i]]} 1 command {[string compare [format %c $i] [string index $a $i]]} 0 subexpr {[string compare [format %c $i] [string index $a $i]]} 1 command {[string compare [format %c $i] [string index $a $i]]} 0 {}}
-test parseExpr-18.1 {LogSyntaxError procedure, error in expr longer than 60 chars} {
- list [catch {testexprparser {(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)/} -1} msg] $msg
-} {1 {syntax error in expression "(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+012...": premature end of expression}}
+test parseExpr-18.1 {LogSyntaxError procedure, error in expr longer than 60 chars} -constraints testexprparser -body {
+ testexprparser {(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)/} -1
+} -returnCodes error -match glob -result *
-test parseExpr-19.1 {TclParseInteger: [Bug 648441]} {
+test parseExpr-19.1 {TclParseInteger: [Bug 648441]} -body {
# Should see this as integer "0" followed by incomplete function "x"
# Thus, syntax error.
# If Bug 648441 is not fixed, "0x" will be seen as floating point 0.0
- list [catch {expr 0x} result] $result
-} [list 1 {syntax error in expression "0x": extra tokens at end of expression}]
+ expr 0x
+} -returnCodes error -match glob -result *
+
+test parseExpr-20.1 {Bug 1451233} {
+ expr 1000000000000000000042
+} 1000000000000000000042
+test parseExpr-20.2 {Bug 1451233} {
+ expr 10000000000000000000420000000042
+} 10000000000000000000420000000042
+test parseExpr-20.3 {Bug 1451233} {
+ expr 10000000000000000000020000000002
+} 10000000000000000000020000000002
+
+test parseExpr-21.1 {error messages} -body {
+ expr @
+} -returnCodes error -result {invalid character "@"
+in expression "@"}
+test parseExpr-21.2 {error messages} -body {
+ expr =
+} -returnCodes error -result {incomplete operator "="
+in expression "="}
+test parseExpr-21.3 {error messages} -body {
+ expr x
+} -returnCodes error -result {invalid bareword "x"
+in expression "x";
+should be "$x" or "{x}" or "x(...)" or ...}
+test parseExpr-21.4 {error messages} -body {
+ expr abcdefghijklmnopqrstuvwxyz
+} -returnCodes error -result {invalid bareword "abcdefghijklmnopqrstuv..."
+in expression "abcdefghijklmnopqrstuv...";
+should be "$abcdefghijklmnopqrstuv..." or "{abcdefghijklmnopqrstuv...}" or "abcdefghijklmnopqrstuv...(...)" or ...}
+test parseExpr-21.5 {error messages} -body {
+ expr {[][]}
+} -returnCodes error -result {missing operator at _@_
+in expression "[]_@_[]"}
+test parseExpr-21.6 {error messages} -body {
+ expr {0 0}
+} -returnCodes error -result {missing operator at _@_
+in expression "0 _@_0"}
+test parseExpr-21.7 {error messages} -body {
+ expr {0o8}
+} -returnCodes error -match glob -result {*invalid octal number*}
+test parseExpr-21.8 {error messages} -body {
+ expr {0o8x}
+} -returnCodes error -match glob -result {*invalid octal number*}
+test parseExpr-21.9 {error messages} -body {
+ expr {"}
+} -returnCodes error -result {missing "
+in expression """}
+test parseExpr-21.10 {error messages} -body {
+ expr \{
+} -returnCodes error -result "missing close-brace
+in expression \"\{\""
+test parseExpr-21.11 {error messages} -body {
+ expr $
+} -returnCodes error -result {invalid character "$"
+in expression "$"}
+test parseExpr-21.12 {error messages} -body {
+ expr {$(}
+} -returnCodes error -result {missing )
+in expression "$("}
+test parseExpr-21.13 {error messages} -body {
+ expr {[""x]}
+} -returnCodes error -result {extra characters after close-quote
+in expression "[""x]"}
+test parseExpr-21.14 {error messages} -body {
+ expr {[}
+} -returnCodes error -result {missing close-bracket
+in expression "["}
+test parseExpr-21.15 {error messages} -body {
+ expr 0~0
+} -returnCodes error -result {missing operator at _@_
+in expression "0_@_~0"}
+test parseExpr-21.16 {error messages} -body {
+ expr ()
+} -returnCodes error -result {empty subexpression at _@_
+in expression "(_@_)"}
+test parseExpr-21.17 {error messages} -body {
+ expr (
+} -returnCodes error -result {unbalanced open paren
+in expression "("}
+test parseExpr-21.18 {error messages} -body {
+ expr a(0,)
+} -returnCodes error -result {missing function argument at _@_
+in expression "a(0,_@_)"}
+test parseExpr-21.19 {error messages} -body {
+ expr {}
+} -returnCodes error -result {empty expression
+in expression ""}
+test parseExpr-21.20 {error messages} -body {
+ expr )
+} -returnCodes error -result {unbalanced close paren
+in expression ")"}
+test parseExpr-21.21 {error messages} -body {
+ expr a(,0)
+} -returnCodes error -result {missing function argument at _@_
+in expression "a(_@_,0)"}
+test parseExpr-21.22 {error messages} -body {
+ expr 0&|0
+} -returnCodes error -result {missing operand at _@_
+in expression "0&_@_|0"}
+test parseExpr-21.23 {error messages} -body {
+ expr 0^^0
+} -returnCodes error -result {missing operand at _@_
+in expression "0^_@_^0"}
+test parseExpr-21.24 {error messages} -body {
+ expr 0|&0
+} -returnCodes error -result {missing operand at _@_
+in expression "0|_@_&0"}
+test parseExpr-21.25 {error messages} -body {
+ expr a(1+,0)
+} -returnCodes error -result {missing operand at _@_
+in expression "a(1+_@_,0)"}
+test parseExpr-21.26 {error messages} -body {
+ expr (0
+} -returnCodes error -result {unbalanced open paren
+in expression "(0"}
+test parseExpr-21.27 {error messages} -body {
+ expr 0?0
+} -returnCodes error -result {missing operator ":" at _@_
+in expression "0?0_@_"}
+test parseExpr-21.28 {error messages} -body {
+ expr 0:0
+} -returnCodes error -result {unexpected operator ":" without preceding "?"
+in expression "0:0"}
+test parseExpr-21.29 {error messages} -body {
+ expr 0)
+} -returnCodes error -result {unbalanced close paren
+in expression "0)"}
+test parseExpr-21.30 {error messages} -body {
+ expr 0,
+} -returnCodes error -result {unexpected "," outside function argument list
+in expression "0,"}
+test parseExpr-21.31 {error messages} -body {
+ expr 0,0
+} -returnCodes error -result {unexpected "," outside function argument list
+in expression "0,0"}
+test parseExpr-21.32 {error messages} -body {
+ expr (0,0)
+} -returnCodes error -result {unexpected "," outside function argument list
+in expression "(0,0)"}
+test parseExpr-21.33 {error messages} -body {
+ expr a(0:0,0)
+} -returnCodes error -result {unexpected operator ":" without preceding "?"
+in expression "a(0:0,0)"}
+test parseExpr-21.34 {error messages} -body {
+ expr {"abcdefghijklmnopqrstuvwxyz"@0}
+} -returnCodes error -result {invalid character "@"
+in expression "...fghijklmnopqrstuvwxyz"@0"}
+test parseExpr-21.35 {error messages} -body {
+ expr {0@"abcdefghijklmnopqrstuvwxyz"}
+} -returnCodes error -result {invalid character "@"
+in expression "0@"abcdefghijklmnopqrstu..."}
+test parseExpr-21.36 {error messages} -body {
+ expr {"abcdefghijklmnopqrstuvwxyz"@"abcdefghijklmnopqrstuvwxyz"}
+} -returnCodes error -result {invalid character "@"
+in expression "...fghijklmnopqrstuvwxyz"@"abcdefghijklmnopqrstu..."}
+test parseExpr-21.37 {error messages} -body {
+ expr [format {"%s" @ 0} [string repeat \u00a7 25]]
+} -returnCodes error -result [format {invalid character "@"
+in expression "...%s" @ 0"} [string repeat \u00a7 10]]
+test parseExpr-21.38 {error messages} -body {
+ expr [format {0 @ "%s"} [string repeat \u00a7 25]]
+} -returnCodes error -result [format {invalid character "@"
+in expression "0 @ "%s..."} [string repeat \u00a7 10]]
+test parseExpr-21.39 {error messages} -body {
+ expr [format {"%s" @ "%s"} [string repeat \u00a7 25] [string repeat \u00a7 25]]
+} -returnCodes error -result [format {invalid character "@"
+in expression "...%s" @ "%s..."} [string repeat \u00a7 10] [string repeat \u00a7 10]]
+test parseExpr-21.40 {error messages} -body {
+ catch {expr {"abcdefghijklmnopqrstuvwxyz"@0}} m o
+ dict get $o -errorinfo
+} -result {invalid character "@"
+in expression "...fghijklmnopqrstuvwxyz"@0"
+ (parsing expression ""abcdefghijklmnopqrstu...")
+ invoked from within
+"expr {"abcdefghijklmnopqrstuvwxyz"@0}"}
+test parseExpr-21.41 {error messages} -body {
+ catch {expr [format {"%s" @ 0} [string repeat \u00a7 25]]} m o
+ dict get $o -errorinfo
+} -result [format {invalid character "@"
+in expression "...%s" @ 0"
+ (parsing expression ""%s...")
+ invoked from within
+"expr [format {"%%s" @ 0} [string repeat \u00a7 25]]"} [string repeat \u00a7 10] [string repeat \u00a7 10]]
+test parseExpr-21.42 {error message} -body {
+ expr {123456789012345678901234567890*"abcdefghijklmnopqrstuvwxyz}
+} -returnCodes error -result {missing "
+in expression "...012345678901234567890*"abcdefghijklmnopqrstuv..."}
+test parseExpr-21.43 {error message} -body {
+ expr "123456789012345678901234567890*\"foobar\$\{abcdefghijklmnopqrstuvwxyz\""
+} -returnCodes error -result "missing close-brace for variable name
+in expression \"...8901234567890*\"foobar\$\{abcdefghijklmnopqrstuv...\""
+test parseExpr-21.44 {error message} -body {
+ expr {123456789012345678901234567890*"foo$bar(abcdefghijklmnopqrstuvwxyz"}
+} -returnCodes error -result {missing )
+in expression "...8901234567890*"foo$bar(abcdefghijklmnopqrstuv..."}
+test parseExpr-21.45 {error message} -body {
+ expr {123456789012345678901234567890*"foo$bar([{}abcdefghijklmnopqrstuvwxyz])"}
+} -returnCodes error -result {extra characters after close-brace
+in expression "...234567890*"foo$bar([{}abcdefghijklmnopqrstuv..."}
+test parseExpr-21.46 {error message} -body {
+ expr {123456789012345678901234567890*"foo$bar([""abcdefghijklmnopqrstuvwxyz])"}
+} -returnCodes error -result {extra characters after close-quote
+in expression "...234567890*"foo$bar([""abcdefghijklmnopqrstuv..."}
+test parseExpr-21.47 {error message} -body {
+ expr {123456789012345678901234567890*"foo$bar([abcdefghijklmnopqrstuvwxyz)"}
+} -returnCodes error -result {missing close-bracket
+in expression "...901234567890*"foo$bar([abcdefghijklmnopqrstuv..."}
+test parseExpr-21.48 {error message} -body {
+ expr "123456789012345678901234567890*\"foo\$bar(\[\{abcdefghijklmnopqrstuvwxyz])\""
+} -returnCodes error -result "missing close-brace
+in expression \"...01234567890*\"foo\$bar(\[\{abcdefghijklmnopqrstuv...\""
+
+test parseExpr-21.49 {error message} -body {
+ expr "123456789012345678901234567890*\{abcdefghijklmnopqrstuvwxyz"
+} -returnCodes error -result "missing close-brace
+in expression \"...012345678901234567890*\{abcdefghijklmnopqrstuv...\""
+
+test parseExpr-21.50 {error message} -body {
+ expr {123456789012345678901234567890*$foo(["abcdefghijklmnopqrstuvwxyz])}
+} -returnCodes error -result {missing "
+in expression "...678901234567890*$foo(["abcdefghijklmnopqrstuv..."}
+test parseExpr-21.51 {error message} -body {
+ expr "123456789012345678901234567890*\$\{abcdefghijklmnopqrstuvwxyz"
+} -returnCodes error -result "missing close-brace for variable name
+in expression \"...12345678901234567890*\$\{abcdefghijklmnopqrstuv...\""
+test parseExpr-21.52 {error message} -body {
+ expr {123456789012345678901234567890*$bar(abcdefghijklmnopqrstuvwxyz}
+} -returnCodes error -result {missing )
+in expression "...45678901234567890*$bar(abcdefghijklmnopqrstuv..."}
+test parseExpr-21.53 {error message} -body {
+ expr {123456789012345678901234567890*$bar([{}abcdefghijklmnopqrstuvwxyz])"}
+} -returnCodes error -result {extra characters after close-brace
+in expression "...8901234567890*$bar([{}abcdefghijklmnopqrstuv..."}
+test parseExpr-21.54 {error message} -body {
+ expr {123456789012345678901234567890*$bar([""abcdefghijklmnopqrstuvwxyz])"}
+} -returnCodes error -result {extra characters after close-quote
+in expression "...8901234567890*$bar([""abcdefghijklmnopqrstuv..."}
+test parseExpr-21.55 {error message} -body {
+ expr {123456789012345678901234567890*$bar([abcdefghijklmnopqrstuvwxyz)"}
+} -returnCodes error -result {missing close-bracket
+in expression "...5678901234567890*$bar([abcdefghijklmnopqrstuv..."}
+test parseExpr-21.56 {error message} -body {
+ expr "123456789012345678901234567890*\$bar(\[\{abcdefghijklmnopqrstuvwxyz])"
+} -returnCodes error -result "missing close-brace
+in expression \"...678901234567890*\$bar(\[\{abcdefghijklmnopqrstuv...\""
+
+test parseExpr-21.57 {error message} -body {
+ expr {123456789012345678901234567890*["abcdefghijklmnopqrstuvwxyz]}
+} -returnCodes error -result {missing "
+in expression "...12345678901234567890*["abcdefghijklmnopqrstuv..."}
+test parseExpr-21.58 {error message} -body {
+ expr "123456789012345678901234567890*\[\$\{abcdefghijklmnopqrstuvwxyz]"
+} -returnCodes error -result "missing close-brace for variable name
+in expression \"...2345678901234567890*\[\$\{abcdefghijklmnopqrstuv...\""
+test parseExpr-21.59 {error message} -body {
+ expr {123456789012345678901234567890*[$bar(abcdefghijklmnopqrstuvwxyz]}
+} -returnCodes error -result {missing )
+in expression "...5678901234567890*[$bar(abcdefghijklmnopqrstuv..."}
+test parseExpr-21.60 {error message} -body {
+ expr {123456789012345678901234567890*[{}abcdefghijklmnopqrstuvwxyz]"}
+} -returnCodes error -result {extra characters after close-brace
+in expression "...345678901234567890*[{}abcdefghijklmnopqrstuv..."}
+test parseExpr-21.61 {error message} -body {
+ expr {123456789012345678901234567890*[""abcdefghijklmnopqrstuvwxyz]"}
+} -returnCodes error -result {extra characters after close-quote
+in expression "...345678901234567890*[""abcdefghijklmnopqrstuv..."}
+test parseExpr-21.62 {error message} -body {
+ expr {123456789012345678901234567890*[abcdefghijklmnopqrstuvwxyz"}
+} -returnCodes error -result {missing close-bracket
+in expression "...012345678901234567890*[abcdefghijklmnopqrstuv..."}
+test parseExpr-21.63 {error message} -body {
+ expr "123456789012345678901234567890*\[\{abcdefghijklmnopqrstuvwxyz]"
+} -returnCodes error -result "missing close-brace
+in expression \"...12345678901234567890*\[\{abcdefghijklmnopqrstuv...\""
# cleanup
::tcltest::cleanupTests
diff --git a/tests/parseOld.test b/tests/parseOld.test
index 27978e2..132481c 100644
--- a/tests/parseOld.test
+++ b/tests/parseOld.test
@@ -18,8 +18,7 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-tcltest::testConstraint testwordend \
- [string equal "testwordend" [info commands testwordend]]
+testConstraint testwordend [llength [info commands testwordend]]
# Save the argv value for restoration later
set savedArgv $argv
@@ -351,7 +350,7 @@ test parseOld-10.13 {syntax errors} {
# since MetroWerks may some day fix this.
test parseOld-10.14 {syntax errors} {
- list [catch {eval \$x[format "%01000d" 0](} msg] $msg $errorInfo
+ list [catch {eval \$x[format "%01000d" 0](} msg] $msg $::errorInfo
} {1 {missing )} {missing )
while executing
"$x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000..."
@@ -466,7 +465,7 @@ test parseOld-14.3 {TclWordEnd procedure} {testwordend} {
test parseOld-14.4 {TclWordEnd procedure} {testwordend} {
testwordend {"abc"}
} {"}
-#" Emacs formatting >:^(
+#" Emacs formatting :^(
test parseOld-14.5 {TclWordEnd procedure} {testwordend} {
testwordend {{xyz}}
} \}
@@ -512,7 +511,7 @@ test parseOld-14.18 {TclWordEnd procedure} {testwordend} {
test parseOld-14.19 {TclWordEnd procedure} {testwordend} {
testwordend \"a\000\"
} {"}
-#" Emacs formatting >:^(
+#" Emacs formatting :^(
test parseOld-14.20 {TclWordEnd procedure} {testwordend} {
testwordend a{\000}b
} {b}
diff --git a/tests/pid.test b/tests/pid.test
index d149df6..d21dbaa 100644
--- a/tests/pid.test
+++ b/tests/pid.test
@@ -16,18 +16,12 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-# If pid is not defined just return with no error
-# Some platforms may not have the pid command implemented
-if {[info commands pid] == ""} {
- puts "pid is not implemented for this machine"
- ::tcltest::cleanupTests
- return
-}
+testConstraint pidDefined [llength [info commands pid]]
-test pid-1.1 {pid command} {
+test pid-1.1 {pid command} pidDefined {
regexp {(^[0-9]+$)|(^0x[0-9a-fA-F]+$)} [pid]
} 1
-test pid-1.2 {pid command} -constraints {unixOrPc unixExecs} -setup {
+test pid-1.2 {pid command} -constraints {unixOrPc unixExecs pidDefined} -setup {
set path(test1) [makeFile {} test1]
file delete $path(test1)
} -body {
@@ -40,7 +34,7 @@ test pid-1.2 {pid command} -constraints {unixOrPc unixExecs} -setup {
} -cleanup {
removeFile test1
} -result {2 1 1 0}
-test pid-1.3 {pid command} -setup {
+test pid-1.3 {pid command} -constraints pidDefined -setup {
set path(test1) [makeFile {} test1]
file delete $path(test1)
} -body {
@@ -51,25 +45,13 @@ test pid-1.3 {pid command} -setup {
} -cleanup {
removeFile test1
} -result {}
-test pid-1.4 {pid command} {
+test pid-1.4 {pid command} pidDefined {
list [catch {pid a b} msg] $msg
} {1 {wrong # args: should be "pid ?channelId?"}}
-test pid-1.5 {pid command} {
+test pid-1.5 {pid command} pidDefined {
list [catch {pid gorp} msg] $msg
} {1 {can not find channel named "gorp"}}
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/pkg.test b/tests/pkg.test
index 68d2a92..a073d25 100644
--- a/tests/pkg.test
+++ b/tests/pkg.test
@@ -1,3 +1,4 @@
+# -*- tcl -*-
# Commands covered: pkg
#
# This file contains a collection of tests for one or more of the Tcl
@@ -11,27 +12,23 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest 2
+ package require tcltest 2.3.3
namespace import -force ::tcltest::*
}
# Do all this in a slave interp to avoid garbaging the
# package list
set i [interp create]
-interp eval $i [list set argv $argv]
-interp eval $i [list package require tcltest 2]
-interp eval $i [list namespace import -force ::tcltest::*]
-interp eval $i {
+tcltest::loadIntoSlaveInterpreter $i {*}$argv
-eval package forget [package names]
+interp eval $i {
+namespace import -force ::tcltest::*
+package forget {*}[package names]
set oldPkgUnknown [package unknown]
package unknown {}
set oldPath $auto_path
set auto_path ""
-testConstraint tip268 [info exists tcl_platform(tip,268)]
-testConstraint !tip268 [expr {![info exists tcl_platform(tip,268)]}]
-
test pkg-1.1 {Tcl_PkgProvide procedure} {
package forget t
package provide t 2.3
@@ -57,7 +54,7 @@ test pkg-1.5 {Tcl_PkgProvide procedure} {
package provide t 2.3
} {}
-test pkg-1.6 {Tcl_PkgProvide procedure} tip268 {
+test pkg-1.6 {Tcl_PkgProvide procedure} {
package forget t
package provide t 2.3a1
} {}
@@ -67,7 +64,7 @@ foreach v {
2.3k1 2a3a2 2ab3 2.a4 2.b4 2b.4 2a.4 2ba4 2a4b1
2b4a1 2b3b2
} {
- test pkg-1.7.$n {Tcl_PkgProvide procedure} tip268 {
+ test pkg-1.7.$n {Tcl_PkgProvide procedure} {
package forget t
list [catch {package provide t $v} msg] $msg
} [list 1 "expected version number but got \"$v\""]
@@ -135,24 +132,14 @@ test pkg-2.7 {Tcl_PkgRequire procedure, can't find suitable version} {
}
list [catch {package require t 4.1} msg] $msg
} {1 {can't find package t 4.1}}
-test pkg-2.8 {Tcl_PkgRequire procedure, can't find suitable version} !tip268 {
- package forget t
- package unknown {}
- foreach i {1.4 3.4 2.3 2.4 2.2} {
- package ifneeded t $i "set x $i"
- }
- list [catch {package require -exact t 1.3} msg] $msg
-
-} {1 {can't find package t 1.3}}
-test pkg-2.8-268 {Tcl_PkgRequire procedure, can't find suitable version} tip268 {
+test pkg-2.8 {Tcl_PkgRequire procedure, can't find suitable version} {
package forget t
package unknown {}
foreach i {1.4 3.4 2.3 2.4 2.2} {
package ifneeded t $i "set x $i"
}
list [catch {package require -exact t 1.3} msg] $msg
-
-} {1 {can't find package t 1.3}}
+} {1 {can't find package t exactly 1.3}}
test pkg-2.9 {Tcl_PkgRequire procedure, can't find suitable version} {
package forget t
package unknown {}
@@ -161,7 +148,7 @@ test pkg-2.9 {Tcl_PkgRequire procedure, can't find suitable version} {
test pkg-2.10 {Tcl_PkgRequire procedure, error in ifneeded script} -body {
package forget t
package ifneeded t 2.1 {package provide t 2.1; error "ifneeded test"}
- list [catch {package require t 2.1} msg] $msg $errorInfo
+ list [catch {package require t 2.1} msg] $msg $::errorInfo
} -match glob -result {1 {ifneeded test} {ifneeded test
while executing
"error "ifneeded test""
@@ -181,24 +168,7 @@ test pkg-2.12 {Tcl_PkgRequire procedure, self-deleting script} {
package require t 1.2
set x
} {1.2}
-test pkg-2.13-!268 {Tcl_PkgRequire procedure, "package unknown" support} !tip268 {
- proc pkgUnknown args {
- global x
- set x $args
- package provide [lindex $args 0] [lindex $args 1]
- }
- package forget t
- foreach i {1.4 3.4 2.3 2.4 2.2} {
- package ifneeded t $i "set x $i"
- }
- package unknown pkgUnknown
- set x xxx
- package require -exact t 1.5
- package unknown {}
- set x
-} {t 1.5 -exact}
-
-test pkg-2.13-268 {Tcl_PkgRequire procedure, "package unknown" support} tip268 {
+test pkg-2.13 {Tcl_PkgRequire procedure, "package unknown" support} {
proc pkgUnknown args {
# args = name requirement
# requirement = v-v (for exact version)
@@ -216,7 +186,6 @@ test pkg-2.13-268 {Tcl_PkgRequire procedure, "package unknown" support} tip268 {
package unknown {}
set x
} {t 1.5-1.5}
-
test pkg-2.14 {Tcl_PkgRequire procedure, "package unknown" support} {
proc pkgUnknown args {
package ifneeded t 1.2 "set x loaded; package provide t 1.2"
@@ -228,20 +197,7 @@ test pkg-2.14 {Tcl_PkgRequire procedure, "package unknown" support} {
package unknown {}
set result
} {1.2 loaded}
-test pkg-2.15 {Tcl_PkgRequire procedure, "package unknown" support} !tip268 {
- proc pkgUnknown args {
- global x
- set x $args
- package provide [lindex $args 0] 2.0
- }
- package forget {a b}
- package unknown pkgUnknown
- set x xxx
- package require {a b}
- package unknown {}
- set x
-} {{a b} {}}
-test pkg-2.15-268 {Tcl_PkgRequire procedure, "package unknown" support} tip268 {
+test pkg-2.15 {Tcl_PkgRequire procedure, "package unknown" support} {
proc pkgUnknown args {
global x
set x $args
@@ -254,31 +210,13 @@ test pkg-2.15-268 {Tcl_PkgRequire procedure, "package unknown" support} tip268 {
package unknown {}
set x
} {{a b} 0-}
-test pkg-2.16 {Tcl_PkgRequire procedure, "package unknown" error} !tip268 {
- proc pkgUnknown args {
- error "testing package unknown"
- }
- package forget t
- package unknown pkgUnknown
- set result [list [catch {package require t} msg] $msg $errorInfo]
- package unknown {}
- set result
-} {1 {testing package unknown} {testing package unknown
- while executing
-"error "testing package unknown""
- (procedure "pkgUnknown" line 2)
- invoked from within
-"pkgUnknown t {}"
- ("package unknown" script)
- invoked from within
-"package require t"}}
-test pkg-2.16-268 {Tcl_PkgRequire procedure, "package unknown" error} tip268 {
+test pkg-2.16 {Tcl_PkgRequire procedure, "package unknown" error} {
proc pkgUnknown args {
error "testing package unknown"
}
package forget t
package unknown pkgUnknown
- set result [list [catch {package require t} msg] $msg $errorInfo]
+ set result [list [catch {package require t} msg] $msg $::errorInfo]
package unknown {}
set result
} {1 {testing package unknown} {testing package unknown
@@ -290,22 +228,7 @@ test pkg-2.16-268 {Tcl_PkgRequire procedure, "package unknown" error} tip268 {
("package unknown" script)
invoked from within
"package require t"}}
-test pkg-2.17 {Tcl_PkgRequire procedure, "package unknown" doesn't load package} !tip268 {
- proc pkgUnknown args {
- global x
- set x $args
- }
- package forget t
- foreach i {1.4 3.4 2.3 2.4 2.2} {
- package ifneeded t $i "set x $i"
- }
- package unknown pkgUnknown
- set x xxx
- set result [list [catch {package require -exact t 1.5} msg] $msg $x]
- package unknown {}
- set result
-} {1 {can't find package t 1.5} {t 1.5 -exact}}
-test pkg-2.17-268 {Tcl_PkgRequire procedure, "package unknown" doesn't load package} tip268 {
+test pkg-2.17 {Tcl_PkgRequire procedure, "package unknown" doesn't load package} {
proc pkgUnknown args {
global x
set x $args
@@ -319,7 +242,7 @@ test pkg-2.17-268 {Tcl_PkgRequire procedure, "package unknown" doesn't load pack
set result [list [catch {package require -exact t 1.5} msg] $msg $x]
package unknown {}
set result
-} {1 {can't find package t 1.5} {t 1.5-1.5}}
+} {1 {can't find package t exactly 1.5} {t 1.5-1.5}}
test pkg-2.18 {Tcl_PkgRequire procedure, version checks} {
package forget t
package provide t 2.3
@@ -350,28 +273,23 @@ test pkg-2.23 {Tcl_PkgRequire procedure, version checks} {
package provide t 2.3
package require -exact t 2.3
} {2.3}
-test pkg-2.24 {Tcl_PkgRequire procedure, version checks} !tip268 {
+test pkg-2.24 {Tcl_PkgRequire procedure, version checks} {
package forget t
package provide t 2.3
list [catch {package require -exact t 2.2} msg] $msg
-} {1 {version conflict for package "t": have 2.3, need 2.2}}
-test pkg-2.24-268 {Tcl_PkgRequire procedure, version checks} tip268 {
- package forget t
- package provide t 2.3
- list [catch {package require -exact t 2.2} msg] $msg
-} {1 {version conflict for package "t": have 2.3, need 2.2}}
+} {1 {version conflict for package "t": have 2.3, need exactly 2.2}}
test pkg-2.25 {Tcl_PkgRequire procedure, error in ifneeded script} -body {
package forget t
package ifneeded t 2.1 {package provide t 2.1; error "ifneeded test" EI}
- list [catch {package require t 2.1} msg] $msg $errorInfo
+ list [catch {package require t 2.1} msg] $msg $::errorInfo
} -match glob -result {1 {ifneeded test} {EI
("package ifneeded*" script)
invoked from within
-"package require t 2.1"}} -constraints knownBug
+"package require t 2.1"}}
test pkg-2.26 {Tcl_PkgRequire procedure, error in ifneeded script} -body {
package forget t
package ifneeded t 2.1 {package provide t 2.1; foreach x 1 {error "ifneeded test" EI}}
- list [catch {package require t 2.1} msg] $msg $errorInfo
+ list [catch {package require t 2.1} msg] $msg $::errorInfo
} -match glob -result {1 {ifneeded test} {EI
("foreach" body line 1)
invoked from within
@@ -450,7 +368,7 @@ test pkg-2.34 {Tcl_PkgRequire: consistent return values (1162286)} -setup {
package require foo 1
} -cleanup {
package forget foo
-} -result 1.1
+} -returnCodes error -match glob -result {attempt to provide package * failed:*}
test pkg-2.34.1 {Tcl_PkgRequire: consistent return values (1162286)} -setup {
package forget foo
} -body {
@@ -458,7 +376,7 @@ test pkg-2.34.1 {Tcl_PkgRequire: consistent return values (1162286)} -setup {
package require foo 1
} -cleanup {
package forget foo
-} -result 1
+} -returnCodes error -match glob -result {attempt to provide package * failed:*}
test pkg-2.34.2 {Tcl_PkgRequire: consistent return values (1162286)} -setup {
package forget foo
} -body {
@@ -505,10 +423,9 @@ test pkg-2.37 {Tcl_PkgRequire: consistent return values (1162286)} -setup {
test pkg-2.38 {Tcl_PkgRequire: consistent return values (1162286)} -setup {
package forget foo
} -body {
- package ifneeded foo 1 {proc x {} {return -code 10}; x}
+ package ifneeded foo 1 {return -level 0 -code 10}
package require foo 1
} -cleanup {
- rename x {}
package forget foo
} -returnCodes error -match glob \
-result {attempt to provide package * failed: bad return code:*}
@@ -555,19 +472,23 @@ test pkg-2.42 {Tcl_PkgRequire: consistent return values (1162286)} -setup {
test pkg-2.43 {Tcl_PkgRequire: consistent return values (1162286)} -setup {
package forget foo
set saveUnknown [package unknown]
- proc x args {return -code 10}
- package unknown x
+ package unknown {return -level 0 -code 10 ;#}
} -body {
package require foo 1
} -cleanup {
- rename x {}
package forget foo
package unknown $saveUnknown
} -returnCodes error -match glob -result {bad return code:*}
+test pkg-2.44 {Tcl_PkgRequire: exact version matching (1578344)} -setup {
+ package provide demo 1.2.3
+} -body {
+ package require -exact demo 1.2
+} -cleanup {
+ package forget demo
+} -returnCodes error -result {version conflict for package "demo": have 1.2.3, need exactly 1.2}
-
-test pkg-2.50 {Tcl_PkgRequire procedure, picking best stable version} tip268 {
+test pkg-2.50 {Tcl_PkgRequire procedure, picking best stable version} {
package forget t
foreach i {1.4 3.4 4.0a1 2.3 2.4 2.2} {
package ifneeded t $i "set x $i; package provide t $i"
@@ -577,7 +498,7 @@ test pkg-2.50 {Tcl_PkgRequire procedure, picking best stable version} tip268 {
set x
} {3.4}
-test pkg-2.51 {Tcl_PkgRequire procedure, picking best stable version} tip268 {
+test pkg-2.51 {Tcl_PkgRequire procedure, picking best stable version} {
package forget t
foreach i {1.2b1 1.2 1.3a2 1.3} {
package ifneeded t $i "set x $i; package provide t $i"
@@ -587,7 +508,7 @@ test pkg-2.51 {Tcl_PkgRequire procedure, picking best stable version} tip268 {
set x
} {1.3}
-test pkg-2.52 {Tcl_PkgRequire procedure, picking best stable version} tip268 {
+test pkg-2.52 {Tcl_PkgRequire procedure, picking best stable version} {
package forget t
foreach i {1.2b1 1.2 1.3 1.3a2} {
package ifneeded t $i "set x $i; package provide t $i"
@@ -722,42 +643,26 @@ test pkg-3.21 {Tcl_PackageCmd procedure, "provide" option} {
package forget t
list [catch {package provide t a.b} msg] $msg
} {1 {expected version number but got "a.b"}}
-test pkg-3.22 {Tcl_PackageCmd procedure, "require" option} !tip268 {
- list [catch {package require} msg] $msg
-} {1 {wrong # args: should be "package require ?-exact? package ?version?"}}
-test pkg-3.22-268 {Tcl_PackageCmd procedure, "require" option} tip268 {
+test pkg-3.22 {Tcl_PackageCmd procedure, "require" option} {
list [catch {package require} msg] $msg
} {1 {wrong # args: should be "package require ?-exact? package ?requirement...?"}}
-test pkg-3.23 {Tcl_PackageCmd procedure, "require" option} !tip268 {
- list [catch {package require a b c} msg] $msg
-} {1 {wrong # args: should be "package require ?-exact? package ?version?"}}
-test pkg-3.24 {Tcl_PackageCmd procedure, "require" option} !tip268 {
- list [catch {package require -exact a b c} msg] $msg
-} {1 {wrong # args: should be "package require ?-exact? package ?version?"}}
-test pkg-3.24-268 {Tcl_PackageCmd procedure, "require" option} tip268 {
+
+test pkg-3.24 {Tcl_PackageCmd procedure, "require" option} {
list [catch {package require -exact a b c} msg] $msg
# Exact syntax: -exact name version
# name ?requirement...?
} {1 {wrong # args: should be "package require ?-exact? package ?requirement...?"}}
-test pkg-3.25 {Tcl_PackageCmd procedure, "require" option} !tip268 {
- list [catch {package require -bs a b} msg] $msg
-} {1 {wrong # args: should be "package require ?-exact? package ?version?"}}
+
test pkg-3.26 {Tcl_PackageCmd procedure, "require" option} {
list [catch {package require x a.b} msg] $msg
} {1 {expected version number but got "a.b"}}
test pkg-3.27 {Tcl_PackageCmd procedure, "require" option} {
list [catch {package require -exact x a.b} msg] $msg
} {1 {expected version number but got "a.b"}}
-test pkg-3.28 {Tcl_PackageCmd procedure, "require" option} !tip268 {
- list [catch {package require -exact x} msg] $msg
-} {1 {wrong # args: should be "package require ?-exact? package ?version?"}}
-test pkg-3.28-268 {Tcl_PackageCmd procedure, "require" option} tip268 {
+test pkg-3.28 {Tcl_PackageCmd procedure, "require" option} {
list [catch {package require -exact x} msg] $msg
} {1 {wrong # args: should be "package require ?-exact? package ?requirement...?"}}
-test pkg-3.29 {Tcl_PackageCmd procedure, "require" option} !tip268 {
- list [catch {package require -exact} msg] $msg
-} {1 {wrong # args: should be "package require ?-exact? package ?version?"}}
-test pkg-3.29-268 {Tcl_PackageCmd procedure, "require" option} tip268 {
+test pkg-3.29 {Tcl_PackageCmd procedure, "require" option} {
list [catch {package require -exact} msg] $msg
} {1 {wrong # args: should be "package require ?-exact? package ?requirement...?"}}
test pkg-3.30 {Tcl_PackageCmd procedure, "require" option} {
@@ -825,15 +730,10 @@ test pkg-3.46 {Tcl_PackageCmd procedure, "versions" option} {
package ifneeded t 2.4 y
package versions t
} {2.3 2.4}
-test pkg-3.47 {Tcl_PackageCmd procedure, "vsatisfies" option} !tip268 {
- list [catch {package vsatisfies a} msg] $msg
-} {1 {wrong # args: should be "package vsatisfies version1 version2"}}
-test pkg-3.47-268 {Tcl_PackageCmd procedure, "vsatisfies" option} tip268 {
+test pkg-3.47 {Tcl_PackageCmd procedure, "vsatisfies" option} {
list [catch {package vsatisfies a} msg] $msg
} {1 {wrong # args: should be "package vsatisfies version requirement requirement..."}}
-test pkg-3.48 {Tcl_PackageCmd procedure, "vsatisfies" option} !tip268 {
- list [catch {package vsatisfies a b c} msg] $msg
-} {1 {wrong # args: should be "package vsatisfies version1 version2"}}
+
test pkg-3.49 {Tcl_PackageCmd procedure, "vsatisfies" option} {
list [catch {package vsatisfies x.y 3.4} msg] $msg
} {1 {expected version number but got "x.y"}}
@@ -846,25 +746,23 @@ test pkg-3.51 {Tcl_PackageCmd procedure, "vsatisfies" option} {
test pkg-3.52 {Tcl_PackageCmd procedure, "vsatisfies" option} {
package vs 2.3 1.2
} {0}
-test pkg-3.53 {Tcl_PackageCmd procedure, "versions" option} !tip268 {
- list [catch {package foo} msg] $msg
-} {1 {bad option "foo": must be forget, ifneeded, names, present, provide, require, unknown, vcompare, versions, or vsatisfies}}
-test pkg-3.53-268 {Tcl_PackageCmd procedure, "versions" option} tip268 {
+test pkg-3.53 {Tcl_PackageCmd procedure, "versions" option} {
list [catch {package foo} msg] $msg
} {1 {bad option "foo": must be forget, ifneeded, names, prefer, present, provide, require, unknown, vcompare, versions, or vsatisfies}}
-test pkg-3.54 {Tcl_PackageCmd procedure, "vsatisfies" option} tip268 {
+test pkg-3.54 {Tcl_PackageCmd procedure, "vsatisfies" option} {
list [catch {package vsatisfies 2.1 2.1-3.2-4.5} msg] $msg
} {1 {expected versionMin-versionMax but got "2.1-3.2-4.5"}}
-test pkg-3.55 {Tcl_PackageCmd procedure, "vsatisfies" option} tip268 {
+test pkg-3.55 {Tcl_PackageCmd procedure, "vsatisfies" option} {
list [catch {package vsatisfies 2.1 3.2-x.y} msg] $msg
} {1 {expected version number but got "x.y"}}
-test pkg-3.56 {Tcl_PackageCmd procedure, "vsatisfies" option} tip268 {
+test pkg-3.56 {Tcl_PackageCmd procedure, "vsatisfies" option} {
list [catch {package vsatisfies 2.1 x.y-3.2} msg] $msg
} {1 {expected version number but got "x.y"}}
+
# No tests for FindPackage; can't think up anything detectable
# errors.
@@ -972,7 +870,7 @@ test pkg-7.7 {Tcl_PkgPresent procedure, not exact version} {
package forget t
package provide t 2.4
list [catch {package present -exact t 2.3} msg] $msg
-} {1 {version conflict for package "t": have 2.4, need 2.3}}
+} {1 {version conflict for package "t": have 2.4, need exactly 2.3}}
test pkg-7.8 {Tcl_PkgPresent procedure, unknown package} {
package forget t
list [catch {package present t} msg] $msg
@@ -985,50 +883,36 @@ test pkg-7.10 {Tcl_PkgPresent procedure, unknown package} {
package forget t
list [catch {package present -exact t 2.4} msg] $msg
} {1 {package t 2.4 is not present}}
-test pkg-7.11 {Tcl_PackageCmd procedure, "present" option} !tip268 {
+test pkg-7.11 {Tcl_PackageCmd procedure, "present" option} {
list [catch {package present} msg] $msg
-} {1 {wrong # args: should be "package present ?-exact? package ?version?"}}
-test pkg-7.12 {Tcl_PackageCmd procedure, "present" option} !tip268 {
+} {1 {wrong # args: should be "package present ?-exact? package ?requirement...?"}}
+test pkg-7.12 {Tcl_PackageCmd procedure, "present" option} {
list [catch {package present a b c} msg] $msg
-} {1 {wrong # args: should be "package present ?-exact? package ?version?"}}
-test pkg-7.13 {Tcl_PackageCmd procedure, "present" option} !tip268 {
+} {1 {expected version number but got "b"}}
+test pkg-7.13 {Tcl_PackageCmd procedure, "present" option} {
list [catch {package present -exact a b c} msg] $msg
-} {1 {wrong # args: should be "package present ?-exact? package ?version?"}}
-test pkg-7.14 {Tcl_PackageCmd procedure, "present" option} !tip268 {
+} {1 {wrong # args: should be "package present ?-exact? package ?requirement...?"}}
+test pkg-7.14 {Tcl_PackageCmd procedure, "present" option} {
list [catch {package present -bs a b} msg] $msg
-} {1 {wrong # args: should be "package present ?-exact? package ?version?"}}
+} {1 {expected version number but got "a"}}
test pkg-7.15 {Tcl_PackageCmd procedure, "present" option} {
list [catch {package present x a.b} msg] $msg
} {1 {expected version number but got "a.b"}}
test pkg-7.16 {Tcl_PackageCmd procedure, "present" option} {
list [catch {package present -exact x a.b} msg] $msg
} {1 {expected version number but got "a.b"}}
-test pkg-7.17 {Tcl_PackageCmd procedure, "present" option} !tip268 {
+test pkg-7.17 {Tcl_PackageCmd procedure, "present" option} {
list [catch {package present -exact x} msg] $msg
-} {1 {wrong # args: should be "package present ?-exact? package ?version?"}}
-test pkg-7.18 {Tcl_PackageCmd procedure, "present" option} !tip268 {
+} {1 {wrong # args: should be "package present ?-exact? package ?requirement...?"}}
+test pkg-7.18 {Tcl_PackageCmd procedure, "present" option} {
list [catch {package present -exact} msg] $msg
-} {1 {wrong # args: should be "package present ?-exact? package ?version?"}}
+} {1 {wrong # args: should be "package present ?-exact? package ?requirement...?"}}
-# Note: It is correct that the result of the very first test,
-# i.e. "5.0 5.0a0" is 1, i.e. that version 5.0a0 satisfies a 5.0
-# requirement.
-# The requirement "5.0" internally translates first to "5.0-6", and
-# then to its final form of "5.0a0-6a0". These translations are
-# explicitly specified by the TIP (Search for "padded/extended
-# internally with 'a0'"). This was done intentionally for exactly the
-# tested case, that an alpha package can satisfy a requirement for the
-# regular package. An example would be a package FOO requiring Tcl 8.X
-# for its operation. It can be used with Tcl 8.Xa0. Without our
-# translation that would not be possible.
set n 0
foreach {r p vs vc} {
- 5.0 5.0a0 1 1
- 5.0a0 5.0 1 -1
-
8.5a0 8.5a5 1 -1
8.5a0 8.5b1 1 -1
8.5a0 8.5.1 1 -1
@@ -1065,20 +949,43 @@ foreach {r p vs vc} {
8.5.0 8.6a0 1 -1
8.5.0 8.6b0 1 -1
8.5.0 8.6.0 1 -1
+ 10 8 0 1
+ 8 10 0 -1
+ 0.0.1.2 0.1.2 1 -1
} {
- test package-vsatisfies-1.$n {package vsatisfies} tip268 {
+ test package-vsatisfies-1.$n {package vsatisfies} {
package vsatisfies $p $r
} $vs
- test package-vcompare-1.$n {package vcompare} tip268 {
+ test package-vcompare-1.$n {package vcompare} {
package vcompare $r $p
} $vc
incr n
}
+test package-vcompare-2.0 {package vcompare at 32bit boundary} {
+ package vcompare [expr {1<<31}] [expr {(1<<31)-1}]
+} 1
+
+# Note: It is correct that the result of the very first test,
+# i.e. "5.0 5.0a0" is 1, i.e. that version 5.0a0 satisfies a 5.0
+# requirement.
+
+# The requirement "5.0" internally translates first to "5.0-6", and
+# then to its final form of "5.0a0-6a0". These translations are
+# explicitly specified by the TIP (Search for "padded/extended
+# internally with 'a0'"). This was done intentionally for exactly the
+# tested case, that an alpha package can satisfy a requirement for the
+# regular package. An example would be a package FOO requiring Tcl 8.X
+# for its operation. It can be used with Tcl 8.Xa0. Without our
+# translation that would not be possible.
+
set n 0
foreach {required provided satisfied} {
+ 5.0 5.0a0 1
+ 5.0a0 5.0 1
+
8.5a0- 8.5a5 1
8.5a0- 8.5b1 1
8.5a0- 8.5.1 1
@@ -1218,28 +1125,28 @@ foreach {required provided satisfied} {
8.5a0-8.5.0 8.5 0
} {
- test package-vsatisfies-2.$n "package vsatisfies $provided $required" tip268 {
+ test package-vsatisfies-2.$n "package vsatisfies $provided $required" {
package vsatisfies $provided $required
} $satisfied
incr n
}
-test package-vsatisfies-3.0 "package vsatisfies multiple" tip268 {
+test package-vsatisfies-3.0 "package vsatisfies multiple" {
# yes no
package vsatisfies 8.4 8.4 7.3
} 1
-test package-vsatisfies-3.1 "package vsatisfies multiple" tip268 {
+test package-vsatisfies-3.1 "package vsatisfies multiple" {
# no yes
package vsatisfies 8.4 7.3 8.4
} 1
-test package-vsatisfies-3.2 "package vsatisfies multiple" tip268 {
+test package-vsatisfies-3.2 "package vsatisfies multiple" {
# yes yes
package vsatisfies 8.4.2 8.4 8.4.1
} 1
-test package-vsatisfies-3.3 "package vsatisfies multiple" tip268 {
+test package-vsatisfies-3.3 "package vsatisfies multiple" {
# no no
package vsatisfies 8.4 7.3 6.1
} 0
@@ -1255,44 +1162,44 @@ proc prefer {args} {
return $res
}
-test package-prefer-1.0 {default} tip268 {
+test package-prefer-1.0 {default} {
prefer
} stable
-test package-prefer-1.1 {default} tip268 {
+test package-prefer-1.1 {default} {
set ::env(TCL_PKG_PREFER_LATEST) stable ; # value not relevant!
set res [prefer]
unset ::env(TCL_PKG_PREFER_LATEST)
set res
} latest
-test package-prefer-2.0 {wrong\#args} tip268 {
+test package-prefer-2.0 {wrong\#args} {
catch {package prefer foo bar} msg
set msg
} {wrong # args: should be "package prefer ?latest|stable?"}
-test package-prefer-2.1 {bogus argument} tip268 {
+test package-prefer-2.1 {bogus argument} {
catch {package prefer foo} msg
set msg
} {bad preference "foo": must be latest or stable}
-test package-prefer-3.0 {set, keep} tip268 {
+test package-prefer-3.0 {set, keep} {
package prefer stable
} stable
-test package-prefer-3.1 {set stable, keep} tip268 {
+test package-prefer-3.1 {set stable, keep} {
prefer stable
} {stable stable}
-test package-prefer-3.2 {set latest, change} tip268 {
+test package-prefer-3.2 {set latest, change} {
prefer latest
} {stable latest}
-test package-prefer-3.3 {set latest, keep} tip268 {
+test package-prefer-3.3 {set latest, keep} {
prefer latest latest
} {stable latest latest}
-test package-prefer-3.4 {set stable, rejected} tip268 {
+test package-prefer-3.4 {set stable, rejected} {
prefer latest stable
} {stable latest latest}
diff --git a/tests/pkgMkIndex.test b/tests/pkgMkIndex.test
index 9f3b8fa..663a6b2 100644
--- a/tests/pkgMkIndex.test
+++ b/tests/pkgMkIndex.test
@@ -87,7 +87,7 @@ proc pkgtest::parseIndex { filePath } {
set ver [lindex $args 2]
set ::PKGS($pkg:$ver) [lindex $args 3]
} else {
- return [eval package_original $args]
+ return [package_original {*}$args]
}
}
array set ::PKGS {}
@@ -146,7 +146,7 @@ proc pkgtest::parseIndex { filePath } {
# 1: the error result if element 0 was 1
proc pkgtest::createIndex { args } {
- set parsed [eval parseArgs $args]
+ set parsed [parseArgs {*}$args]
set options [lindex $parsed 0]
set dirPath [lindex $parsed 1]
set patternList [lindex $parsed 2]
@@ -155,7 +155,7 @@ proc pkgtest::createIndex { args } {
if {[catch {
file delete [file join $dirPath pkgIndex.tcl]
- eval pkg_mkIndex $options [list $dirPath] $patternList
+ pkg_mkIndex {*}$options $dirPath {*}$patternList
} err]} {
return [list 1 $err]
}
@@ -229,7 +229,7 @@ proc makePkgList { inList } {
proc pkgtest::runCreatedIndex {rv args} {
if {[lindex $rv 0] == 0} {
- set parsed [eval parseArgs $args]
+ set parsed [parseArgs {*}$args]
set dirPath [lindex $parsed 1]
set idxFile [file join $dirPath pkgIndex.tcl]
@@ -246,8 +246,8 @@ proc pkgtest::runCreatedIndex {rv args} {
return $result
}
proc pkgtest::runIndex { args } {
- set rv [eval createIndex $args]
- return [eval [list runCreatedIndex $rv] $args]
+ set rv [createIndex {*}$args]
+ return [runCreatedIndex $rv {*}$args]
}
# If there is no match to the patterns, make sure the directory hasn't
@@ -560,17 +560,17 @@ removeFile [file join pkg circ3.tcl]
set x [file join [file dirname [info nameofexecutable]] dltest \
pkga[info sharedlibextension]]
set dll "[file tail $x]Required"
-::tcltest::testConstraint $dll [file exists $x]
+testConstraint $dll [file exists $x]
if {[testConstraint $dll]} {
-makeFile {
+ makeFile {
# This package provides Pkga, which is also provided by a DLL.
package provide Pkga 1.0
proc pkga_neq { x } {
return [expr {! [pkgq_eq $x]}]
}
} [file join pkg pkga.tcl]
-file copy -force $x $fullPkgPath
+ file copy -force $x $fullPkgPath
}
testConstraint exec [llength [info commands ::exec]]
@@ -596,8 +596,8 @@ test pkgMkIndex-10.2 {package in DLL hidden by -load} [list exec $dll] {
} {0 {}}
if {[testConstraint $dll]} {
-file delete -force [file join $fullPkgPath [file tail $x]]
-removeFile [file join pkg pkga.tcl]
+ file delete -force [file join $fullPkgPath [file tail $x]]
+ removeFile [file join pkg pkga.tcl]
}
# Tolerate "namespace import" at the global scope
@@ -671,24 +671,24 @@ test pkgMkIndex-13.1 {proc names with embedded spaces} {
removeFile [file join pkg spacename.tcl]
-# Test the pkg_compareExtension helper function
-test pkgMkIndex-14.1 {pkg_compareExtension} {unixOnly} {
- pkg_compareExtension foo.so .so
+# Test the tcl::Pkg::CompareExtension helper function
+test pkgMkIndex-14.1 {tcl::Pkg::CompareExtension} {unix} {
+ tcl::Pkg::CompareExtension foo.so .so
} 1
-test pkgMkIndex-14.2 {pkg_compareExtension} {unixOnly} {
- pkg_compareExtension foo.so.bar .so
+test pkgMkIndex-14.2 {tcl::Pkg::CompareExtension} {unix} {
+ tcl::Pkg::CompareExtension foo.so.bar .so
} 0
-test pkgMkIndex-14.3 {pkg_compareExtension} {unixOnly} {
- pkg_compareExtension foo.so.1 .so
+test pkgMkIndex-14.3 {tcl::Pkg::CompareExtension} {unix} {
+ tcl::Pkg::CompareExtension foo.so.1 .so
} 1
-test pkgMkIndex-14.4 {pkg_compareExtension} {unixOnly} {
- pkg_compareExtension foo.so.1.2 .so
+test pkgMkIndex-14.4 {tcl::Pkg::CompareExtension} {unix} {
+ tcl::Pkg::CompareExtension foo.so.1.2 .so
} 1
-test pkgMkIndex-14.5 {pkg_compareExtension} {unixOnly} {
- pkg_compareExtension foo .so
+test pkgMkIndex-14.5 {tcl::Pkg::CompareExtension} {unix} {
+ tcl::Pkg::CompareExtension foo .so
} 0
-test pkgMkIndex-14.6 {pkg_compareExtension} {unixOnly} {
- pkg_compareExtension foo.so.1.2.bar .so
+test pkgMkIndex-14.6 {tcl::Pkg::CompareExtension} {unix} {
+ tcl::Pkg::CompareExtension foo.so.1.2.bar .so
} 0
# cleanup
diff --git a/tests/platform.test b/tests/platform.test
index d4816d2..9d88f98 100644
--- a/tests/platform.test
+++ b/tests/platform.test
@@ -20,22 +20,20 @@ test platform-1.1 {TclpSetVariables: tcl_platform} {
interp create i
i eval {catch {unset tcl_platform(debug)}}
i eval {catch {unset tcl_platform(threaded)}}
- i eval {catch {unset tcl_platform(tip,268)}}
- i eval {catch {unset tcl_platform(tip,280)}}
set result [i eval {lsort [array names tcl_platform]}]
interp delete i
set result
-} {byteOrder machine os osVersion platform user wordSize}
+} {byteOrder machine os osVersion platform pointerSize user wordSize}
# Test assumes twos-complement arithmetic, which is true of virtually
# everything these days. Note that this does *not* use wide(), and
# this is intentional since that could make Tcl's numbers wider than
# the machine-integer on some platforms...
test platform-2.1 {tcl_platform(wordSize) indicates size of native word} {
- set result [expr {1 << (8 * $tcl_platform(wordSize) - 1)}]
+ set result [expr {int(1 << (8 * $tcl_platform(wordSize) - 1))}]
# Result must be the largest bit in a machine word, which this checks
# without assuming how wide the word really is
- list [expr {$result < 0}] [expr {$result ^ ($result - 1)}]
+ list [expr {$result < 0}] [expr {$result ^ int($result - 1)}]
} {1 -1}
# On Windows, test that the CPU ID works
diff --git a/tests/proc-old.test b/tests/proc-old.test
index 71558cf..5aec4f7 100644
--- a/tests/proc-old.test
+++ b/tests/proc-old.test
@@ -231,7 +231,7 @@ test proc-old-30.12 {arguments and defaults} {
return [list $x $y $args]
}
list [catch {tproc} msg] $msg
-} {1 {wrong # args: should be "tproc x ?y? args"}}
+} {1 {wrong # args: should be "tproc x ?y? ..."}}
test proc-old-4.1 {variable numbers of arguments} {
proc tproc args {return $args}
@@ -256,7 +256,7 @@ test proc-old-4.5 {variable numbers of arguments} {
test proc-old-4.6 {variable numbers of arguments} {
proc tproc {x missing args} {return $args}
list [catch {tproc 1} msg] $msg
-} {1 {wrong # args: should be "tproc x missing args"}}
+} {1 {wrong # args: should be "tproc x missing ..."}}
test proc-old-5.1 {error conditions} {
list [catch {proc} msg] $msg
@@ -272,10 +272,10 @@ test proc-old-5.4 {error conditions} {
} {1 {unmatched open brace in list}}
test proc-old-5.5 {error conditions} {
list [catch {proc tproc {{} y} {return foo}} msg] $msg
-} {1 {procedure "tproc" has argument with no name}}
+} {1 {argument with no name}}
test proc-old-5.6 {error conditions} {
list [catch {proc tproc {{} y} {return foo}} msg] $msg
-} {1 {procedure "tproc" has argument with no name}}
+} {1 {argument with no name}}
test proc-old-5.7 {error conditions} {
list [catch {proc tproc {{x 1 2} y} {return foo}} msg] $msg
} {1 {too many fields in argument specifier "x 1 2"}}
@@ -314,7 +314,7 @@ test proc-old-5.13 {error conditions} {
return
}
catch tproc msg
- set errorInfo
+ set ::errorInfo
} {error in procedure
while executing
"error "error in procedure""
@@ -328,7 +328,7 @@ test proc-old-5.14 {error conditions} {
return
}
catch tproc msg
- set errorInfo
+ set ::errorInfo
} {invoked "break" outside of a loop
(procedure "tproc" line 1)
invoked from within
@@ -340,7 +340,7 @@ test proc-old-5.15 {error conditions} {
return
}
catch tproc msg
- set errorInfo
+ set ::errorInfo
} {invoked "continue" outside of a loop
(procedure "tproc" line 1)
invoked from within
@@ -358,7 +358,7 @@ test proc-old-5.16 {error conditions} {
}
}
set fooMsg "foo not called"
- list [catch tproc msg] $msg $errorInfo $fooMsg
+ list [catch tproc msg] $msg $::errorInfo $fooMsg
} {1 {Nested error} {Nested error
while executing
"error "Nested error""
@@ -393,7 +393,7 @@ test proc-old-7.1 {return with special completion code} {
list [catch {tproc ok} msg] $msg
} {0 abc}
test proc-old-7.2 {return with special completion code} {
- list [catch {tproc error} msg] $msg $errorInfo $errorCode
+ list [catch {tproc error} msg] $msg $::errorInfo $::errorCode
} {1 abc {abc
while executing
"tproc error"} NONE}
@@ -433,7 +433,7 @@ test proc-old-7.11 {return with special completion code} {
catch {open _bad_file_name r} msg
return -code error -errorinfo $errorInfo -errorcode $errorCode $msg
}
- set msg [list [catch tproc2 msg] $msg $errorInfo $errorCode]
+ set msg [list [catch tproc2 msg] $msg $::errorInfo $::errorCode]
regsub -all [file join {} _bad_file_name] $msg "_bad_file_name" msg
normalizeMsg $msg
} {1 {couldn't open "_bad_file_name": no such file or directory} {couldn't open "_bad_file_name": no such file or directory
@@ -447,7 +447,7 @@ test proc-old-7.12 {return with special completion code} {
catch {open _bad_file_name r} msg
return -code error -errorcode $errorCode $msg
}
- set msg [list [catch tproc2 msg] $msg $errorInfo $errorCode]
+ set msg [list [catch tproc2 msg] $msg $::errorInfo $::errorCode]
regsub -all [file join {} _bad_file_name] $msg "_bad_file_name" msg
normalizeMsg $msg
} {1 {couldn't open "_bad_file_name": no such file or directory} {couldn't open "_bad_file_name": no such file or directory
@@ -459,7 +459,7 @@ test proc-old-7.13 {return with special completion code} {
catch {open _bad_file_name r} msg
return -code error -errorinfo $errorInfo $msg
}
- set msg [list [catch tproc2 msg] $msg $errorInfo $errorCode]
+ set msg [list [catch tproc2 msg] $msg $::errorInfo $::errorCode]
regsub -all [file join {} _bad_file_name] $msg "_bad_file_name" msg
normalizeMsg $msg
} {1 {couldn't open "_bad_file_name": no such file or directory} {couldn't open "_bad_file_name": no such file or directory
@@ -473,7 +473,7 @@ test proc-old-7.14 {return with special completion code} {
catch {open _bad_file_name r} msg
return -code error $msg
}
- set msg [list [catch tproc2 msg] $msg $errorInfo $errorCode]
+ set msg [list [catch tproc2 msg] $msg $::errorInfo $::errorCode]
regsub -all [file join {} _bad_file_name] $msg "_bad_file_name" msg
normalizeMsg $msg
} {1 {couldn't open "_bad_file_name": no such file or directory} {couldn't open "_bad_file_name": no such file or directory
@@ -481,7 +481,7 @@ test proc-old-7.14 {return with special completion code} {
"tproc2"} none}
test proc-old-7.15 {return with special completion code} {
list [catch {return -badOption foo message} msg] $msg
-} {1 {bad option "-badOption": must be -code, -errorcode, or -errorinfo}}
+} {2 message}
test proc-old-8.1 {unset and undefined local arrays} {
proc t1 {} {
@@ -518,15 +518,3 @@ catch {rename t1 ""}
catch {rename foo ""}
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/proc.test b/tests/proc.test
index 8974663..5673caa 100644
--- a/tests/proc.test
+++ b/tests/proc.test
@@ -18,15 +18,21 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
+if {[catch {package require procbodytest}]} {
+ testConstraint procbodytest 0
+} else {
+ testConstraint procbodytest 1
+}
+
testConstraint memory [llength [info commands memory]]
-catch {eval namespace delete [namespace children :: test_ns_*]}
+catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {rename p ""}
catch {rename {} ""}
catch {unset msg}
test proc-1.1 {Tcl_ProcObjCmd, put proc in namespace specified in name, if any} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_1 {
namespace eval baz {}
}
@@ -38,11 +44,11 @@ test proc-1.1 {Tcl_ProcObjCmd, put proc in namespace specified in name, if any}
[info commands test_ns_1::baz::*]
} {{p in ::test_ns_1::baz} {p in ::test_ns_1::baz} ::test_ns_1::baz::p}
test proc-1.2 {Tcl_ProcObjCmd, namespace specified in proc name must exist} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
list [catch {proc test_ns_1::baz::p {} {}} msg] $msg
} {1 {can't create procedure "test_ns_1::baz::p": unknown namespace}}
test proc-1.3 {Tcl_ProcObjCmd, empty proc name} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
proc :: {} {
return "empty called"
}
@@ -52,7 +58,7 @@ test proc-1.3 {Tcl_ProcObjCmd, empty proc name} {
return "empty called"
}}
test proc-1.4 {Tcl_ProcObjCmd, simple proc name and proc defined in namespace} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_1 {
namespace eval baz {
proc p {} {
@@ -64,7 +70,7 @@ test proc-1.4 {Tcl_ProcObjCmd, simple proc name and proc defined in namespace} {
[info commands test_ns_1::baz::*]
} {{p in ::test_ns_1::baz} ::test_ns_1::baz::p}
test proc-1.5 {Tcl_ProcObjCmd, qualified proc name and proc defined in namespace} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_1::baz {}
namespace eval test_ns_1 {
proc baz::p {} {
@@ -76,7 +82,7 @@ test proc-1.5 {Tcl_ProcObjCmd, qualified proc name and proc defined in namespace
[namespace eval test_ns_1::baz {namespace which p}]
} {{p in ::test_ns_1::baz} ::test_ns_1::baz::p ::test_ns_1::baz::p}
test proc-1.6 {Tcl_ProcObjCmd, namespace code ignores single ":"s in middle or end of command names} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_1 {
proc q: {} {return "q:"}
proc value:at: {} {return "value:at:"}
@@ -95,21 +101,21 @@ test proc-1.7 {Tcl_ProcObjCmd, check that formal parameter names are not array e
set z [expr $a(1)+$a(2)]
puts "$z=z, $a(1)=$a(1)"
}} msg] $msg
-} {1 {procedure "p" has formal parameter "a(1)" that is an array element}}
+} {1 {formal parameter "a(1)" is an array element}}
test proc-1.8 {Tcl_ProcObjCmd, check that formal parameter names are simple names} {
catch {rename p ""}
list [catch {proc p {b:a b::a} {
}} msg] $msg
-} {1 {procedure "p" has formal parameter "b::a" that is not a simple name}}
+} {1 {formal parameter "b::a" is not a simple name}}
test proc-2.1 {TclFindProc, simple proc name and proc not in namespace} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {rename p ""}
proc p {} {return "p in [namespace current]"}
info body p
} {return "p in [namespace current]"}
test proc-2.2 {TclFindProc, simple proc name and proc defined in namespace} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_1 {
namespace eval baz {
proc p {} {return "p in [namespace current]"}
@@ -118,7 +124,7 @@ test proc-2.2 {TclFindProc, simple proc name and proc defined in namespace} {
namespace eval test_ns_1::baz {info body p}
} {return "p in [namespace current]"}
test proc-2.3 {TclFindProc, qualified proc name and proc defined in namespace} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_1::baz {}
namespace eval test_ns_1 {
proc baz::p {} {return "p in [namespace current]"}
@@ -126,26 +132,26 @@ test proc-2.3 {TclFindProc, qualified proc name and proc defined in namespace} {
namespace eval test_ns_1 {info body baz::p}
} {return "p in [namespace current]"}
test proc-2.4 {TclFindProc, global proc and executing in namespace} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {rename p ""}
proc p {} {return "global p"}
namespace eval test_ns_1::baz {info body p}
} {return "global p"}
test proc-3.1 {TclObjInterpProc, proc defined and executing in same namespace} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
proc p {} {return "p in [namespace current]"}
p
} {p in ::}
test proc-3.2 {TclObjInterpProc, proc defined and executing in same namespace} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
namespace eval test_ns_1::baz {
proc p {} {return "p in [namespace current]"}
p
}
} {p in ::test_ns_1::baz}
test proc-3.3 {TclObjInterpProc, proc defined and executing in different namespaces} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {rename p ""}
proc p {} {return "p in [namespace current]"}
namespace eval test_ns_1::baz {
@@ -153,7 +159,7 @@ test proc-3.3 {TclObjInterpProc, proc defined and executing in different namespa
}
} {p in ::}
test proc-3.4 {TclObjInterpProc, procs execute in the namespace in which they were defined unless renamed into new namespace} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {rename p ""}
namespace eval test_ns_1::baz {
proc p {} {return "p in [namespace current]"}
@@ -176,19 +182,12 @@ test proc-3.7 {TclObjInterpProc, wrong num args, Bug 3366265} {
list [catch {{}} msg] $msg
} {1 {wrong # args: should be "{} x"}}
-catch {eval namespace delete [namespace children :: test_ns_*]}
+catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {rename p ""}
catch {rename {} ""}
catch {rename {a b c} {}}
catch {unset msg}
-if {[catch {package require procbodytest}]} {
- puts "This application couldn't load the \"procbodytest\" package, so I"
- puts "can't test creation of procs whose bodies have type \"procbody\"."
- ::tcltest::cleanupTests
- return
-}
-
catch {rename p ""}
catch {rename t ""}
@@ -197,7 +196,7 @@ catch {rename t ""}
# is executed, so that the Proc struct is populated correctly (CompiledLocals
# are added at compile time).
-test proc-4.1 {TclCreateProc, procbody obj} {
+test proc-4.1 {TclCreateProc, procbody obj} procbodytest {
catch {
proc p x {return "$x:$x"}
set rv [p P]
@@ -209,8 +208,7 @@ test proc-4.1 {TclCreateProc, procbody obj} {
catch {rename t ""}
set result
} {P:P T:T}
-
-test proc-4.2 {TclCreateProc, procbody obj, use compiled locals} {
+test proc-4.2 {TclCreateProc, procbody obj, use compiled locals} procbodytest {
catch {
proc p x {
set y [string tolower $x]
@@ -225,8 +223,7 @@ test proc-4.2 {TclCreateProc, procbody obj, use compiled locals} {
catch {rename t ""}
set result
} {P:p T:t}
-
-test proc-4.3 {TclCreateProc, procbody obj, too many args} {
+test proc-4.3 {TclCreateProc, procbody obj, too many args} procbodytest {
catch {
proc p x {
set y [string tolower $x]
@@ -241,8 +238,7 @@ test proc-4.3 {TclCreateProc, procbody obj, too many args} {
catch {rename t ""}
set result
} {procedure "t": arg list contains 3 entries, precompiled header expects 1}
-
-test proc-4.4 {TclCreateProc, procbody obj, inconsistent arg name} {
+test proc-4.4 {TclCreateProc, procbody obj, inconsistent arg name} procbodytest {
catch {
proc p {x y z} {
set v [join [list $x $y $z]]
@@ -258,8 +254,7 @@ test proc-4.4 {TclCreateProc, procbody obj, inconsistent arg name} {
catch {rename t ""}
set result
} {procedure "t": formal parameter 1 is inconsistent with precompiled body}
-
-test proc-4.5 {TclCreateProc, procbody obj, inconsistent arg default type} {
+test proc-4.5 {TclCreateProc, procbody obj, inconsistent arg default type} procbodytest {
catch {
proc p {x y {z Z}} {
set v [join [list $x $y $z]]
@@ -275,8 +270,7 @@ test proc-4.5 {TclCreateProc, procbody obj, inconsistent arg default type} {
catch {rename t ""}
set result
} {procedure "t": formal parameter 2 is inconsistent with precompiled body}
-
-test proc-4.6 {TclCreateProc, procbody obj, inconsistent arg default type} {
+test proc-4.6 {TclCreateProc, procbody obj, inconsistent arg default type} procbodytest {
catch {
proc p {x y z} {
set v [join [list $x $y $z]]
@@ -292,8 +286,7 @@ test proc-4.6 {TclCreateProc, procbody obj, inconsistent arg default type} {
catch {rename t ""}
set result
} {procedure "t": formal parameter 2 is inconsistent with precompiled body}
-
-test proc-4.7 {TclCreateProc, procbody obj, inconsistent arg default value} {
+test proc-4.7 {TclCreateProc, procbody obj, inconsistent arg default value} procbodytest {
catch {
proc p {x y {z Z}} {
set v [join [list $x $y $z]]
@@ -309,7 +302,6 @@ test proc-4.7 {TclCreateProc, procbody obj, inconsistent arg default value} {
catch {rename t ""}
set result
} {procedure "t": formal parameter "z" has default value inconsistent with precompiled body}
-
test proc-4.8 {TclCreateProc, procbody obj, no leak on multiple iterations} -setup {
proc getbytes {} {
set lines [split [memory info] "\n"]
@@ -320,7 +312,8 @@ test proc-4.8 {TclCreateProc, procbody obj, no leak on multiple iterations} -set
return "$x:$y"
}
px x
-} -constraints memory -body {
+} -constraints {procbodytest memory} -body {
+
set end [getbytes]
for {set i 0} {$i < 5} {incr i} {
@@ -332,6 +325,7 @@ test proc-4.8 {TclCreateProc, procbody obj, no leak on multiple iterations} -set
set leakedBytes [expr {$end - $tmp}]
} -cleanup {
rename getbytes {}
+ unset -nocomplain end i tmp leakedBytes
} -result 0
test proc-5.1 {Bytecompiling noop; test for correct argument substitution} {
@@ -360,20 +354,47 @@ test proc-6.1 {ProcessProcResultCode: Bug 647307 (negative return code)} {
set result
} -5
+test proc-7.1 {Redefining a compiled cmd: Bug 729692} {
+ proc bar args {}
+ proc foo {} {
+ proc bar args {return bar}
+ bar
+ }
+ foo
+} bar
+
+test proc-7.2 {Shadowing a compiled cmd: Bug 729692} {
+ namespace eval ugly {}
+ proc ugly::foo {} {
+ proc set args {return bar}
+ set x 1
+ }
+ set res [list [catch {ugly::foo} msg] $msg]
+ namespace delete ugly
+ set res
+} {0 bar}
+
+test proc-7.3 {Returning loop exception from redefined cmd: Bug 729692} {
+ namespace eval ugly {}
+ proc ugly::foo {} {
+ set i 0
+ while { 1 } {
+ if { [incr i] > 3 } {
+ proc continue {} {return -code break}
+ }
+ continue
+ }
+ return $i
+ }
+ set res [list [catch {ugly::foo} msg] $msg]
+ namespace delete ugly
+ set res
+} {0 4}
+
+
+
# cleanup
catch {rename p ""}
catch {rename t ""}
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/pwd.test b/tests/pwd.test
index 58612d9..175c852 100644
--- a/tests/pwd.test
+++ b/tests/pwd.test
@@ -12,29 +12,20 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2
namespace import -force ::tcltest::*
}
test pwd-1.1 {simple pwd} {
- catch pwd
+ catch pwd
} 0
test pwd-1.2 {simple pwd} {
- expr [string length pwd]>0
+ expr [string length pwd]>0
} 1
+test pwd-1.3 {pwd takes no args} -body {
+ pwd foobar
+} -returnCodes error -result "wrong \# args: should be \"pwd\""
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/reg.test b/tests/reg.test
index 4b09c06..d92339f 100644
--- a/tests/reg.test
+++ b/tests/reg.test
@@ -11,40 +11,40 @@
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest 2
- namespace import -force ::tcltest::*
}
# All tests require the testregexp command, return if this
# command doesn't exist
-::tcltest::testConstraint testregexp \
- [expr {[info commands testregexp] != {}}]
+::tcltest::testConstraint testregexp [llength [info commands testregexp]]
::tcltest::testConstraint localeRegexp 0
# This file uses some custom procedures, defined below, for regexp regression
# testing. The name of the procedure indicates the general nature of the
# test:
-# e compile error expected
-# f match failure expected
-# m successful match
-# i successful match with -indices (used in checking things like
-# nonparticipating subexpressions)
-# p unsuccessful match with -indices (!!) (used in checking
-# partial-match reporting)
+# expectError compile error expected
+# expectNomatch match failure expected
+# expectMatch successful match
+# expectIndices successful match with -indices (used in checking things
+# like nonparticipating subexpressions)
+# expectPartial unsuccessful match with -indices (!!) (used in checking
+# partial-match reporting)
# There is also "doing" which sets up title and major test number for each
# block of tests.
-# The first 3 arguments are constant: a minor number (which often gets
-# a letter or two suffixed to it internally), some flags, and the RE itself.
-# For e, the remaining argument is the name of the compile error expected,
-# less the leading "REG_". For the rest, the next argument is the string
-# to try the match against. Remaining arguments are the substring expected
-# to be matched, and any substrings expected to be matched by subexpressions.
-# (For f, these arguments are optional, and if present are ignored except
-# that they indicate how many subexpressions should be present in the RE.)
-# It is an error for the number of subexpression arguments to be wrong.
-# Cases involving nonparticipating subexpressions, checking where empty
-# substrings are located, etc. should be done using i and p.
+# The first 3 arguments are constant: a minor number (which often gets
+# a letter or two suffixed to it internally), some flags, and the RE
+# itself. For expectError, the remaining argument is the name of the
+# compile error expected, less the leading "REG_". For the rest, the
+# next argument is the string to try the match against. Remaining
+# arguments are the substring expected to be matched, and any
+# substrings expected to be matched by subexpressions. (For
+# expectNomatch, these arguments are optional, and if present are
+# ignored except that they indicate how many subexpressions should be
+# present in the RE.) It is an error for the number of subexpression
+# arguments to be wrong. Cases involving nonparticipating
+# subexpressions, checking where empty substrings are located,
+# etc. should be done using expectIndices and expectPartial.
# The flag characters are complex and a bit eclectic. Generally speaking,
# lowercase letters are compile options, uppercase are expected re_info
@@ -96,68 +96,55 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
# the moment, but this is a historical accident which should be fixed.
-
# test procedures and related
+namespace eval RETest {
+ namespace export doing expect* knownBug
+
+ variable regBug 0
+
+ # re_info abbreviation mapping table
+ variable infonames
+ array set infonames {
+ A REG_UBSALNUM
+ B REG_UBRACES
+ E REG_UBBS
+ H REG_ULOOKAHEAD
+ I REG_UIMPOSSIBLE
+ L REG_ULOCALE
+ M REG_UUNPORT
+ N REG_UEMPTYMATCH
+ P REG_UNONPOSIX
+ Q REG_UBOUNDS
+ R REG_UBACKREF
+ S REG_UUNSPEC
+ T REG_USHORTEST
+ U REG_UPBOTCH
+ }
+ variable infonameorder "RHQBAUEPSMLNIT" ;# must match bit order, lsb first
-set ask "about"
-set xflags "xflags"
-set testbypassed 0
-
-# re_info abbreviation mapping table
-set infonames(A) "REG_UBSALNUM"
-set infonames(B) "REG_UBRACES"
-set infonames(E) "REG_UBBS"
-set infonames(H) "REG_ULOOKAHEAD"
-set infonames(I) "REG_UIMPOSSIBLE"
-set infonames(L) "REG_ULOCALE"
-set infonames(M) "REG_UUNPORT"
-set infonames(N) "REG_UEMPTYMATCH"
-set infonames(P) "REG_UNONPOSIX"
-set infonames(Q) "REG_UBOUNDS"
-set infonames(R) "REG_UBACKREF"
-set infonames(S) "REG_UUNSPEC"
-set infonames(T) "REG_USHORTEST"
-set infonames(U) "REG_UPBOTCH"
-set infonameorder "RHQBAUEPSMLNIT" ;# must match bit order, lsb first
-
-# set major test number and description
-proc doing {major desc} {
- global prefix description testbypassed
-
- if {$testbypassed != 0} {
- puts stdout "!!! bypassed $testbypassed tests in\
- $prefix, `$description'"
- }
-
- set prefix reg-$major
- set description "reg $desc"
- set testbypassed 0
-}
-
-# build test number (internal)
-proc tno {testid} {
- return [join $testid .]
-}
+ # build test number (internal)
+ proc TestNum {args} {
+ return reg-[join [concat $args] .]
+ }
-# build description, with possible modifiers (internal)
-proc desc {testid} {
- global description
+ # build description, with possible modifiers (internal)
+ proc TestDesc {args} {
+ variable description
+ set testid [concat $args]
set d $description
if {[llength $testid] > 1} {
- set d "([lreplace $testid 0 0]) $d"
+ set d "$d ([lrange $testid 1 end])"
}
return $d
-}
-
-# build trailing options and flags argument from a flags string (internal)
-proc flags {fl} {
- global xflags
+ }
+ # build trailing options and flags argument from a flags string (internal)
+ proc TestFlags {fl} {
set args [list]
set flags ""
foreach f [split $fl ""] {
- switch -exact -- $f {
+ switch -exact -- $f {
"i" { lappend args "-nocase" }
"x" { lappend args "-expanded" }
"n" { lappend args "-line" }
@@ -165,825 +152,786 @@ proc flags {fl} {
"w" { lappend args "-lineanchor" }
"-" { }
default { append flags $f }
- }
+ }
}
- if {[string compare $flags ""] != 0} {
- lappend args -$xflags $flags
+ if {$flags ne ""} {
+ lappend args -xflags $flags
}
return $args
-}
+ }
-# build info-flags list from a flags string (internal)
-proc infoflags {fl} {
- global infonames infonameorder
+ # build info-flags list from a flags string (internal)
+ proc TestInfoFlags {fl} {
+ variable infonames
+ variable infonameorder
set ret [list]
foreach f [split $infonameorder ""] {
- if {[string first $f $fl] >= 0} {
- lappend ret $infonames($f)
- }
+ if {[string match *$f* $fl]} {
+ lappend ret $infonames($f)
+ }
}
return $ret
-}
+ }
-# compilation error expected
-proc e {testid flags re err} {
- global prefix ask errorCode
+ # match expected, internal routine that does the work
+ # parameters like the "real" routines except they don't have "opts",
+ # which is a possibly-empty list of switches for the regexp match attempt
+ # The ! flag is used to indicate expected match failure (for REG_EXPECT,
+ # which wants argument testing even in the event of failure).
+ proc MatchExpected {opts testid flags re target args} {
+ variable regBug
- # Tcl locale stuff doesn't do the ch/xy test fakery yet
- if {[string first "+" $flags] >= 0} {
- # This will register as a skipped test
- test $prefix.[tno $testid] [desc $testid] localeRegexp {} {}
+ # if &, test as both BRE and ARE
+ if {[string match *&* $flags]} {
+ set f [string map {& {}} $flags]
+ MatchExpected $opts "$testid ARE" ${f} $re $target {*}$args
+ MatchExpected $opts "$testid BRE" ${f}b $re $target {*}$args
return
}
- # if &, test as both ARE and BRE
- set amp [string first "&" $flags]
- if {$amp >= 0} {
- set f [string range $flags 0 [expr $amp - 1]]
- append f [string range $flags [expr $amp + 1] end]
- e [linsert $testid end ARE] ${f} $re $err
- e [linsert $testid end BRE] ${f}b $re $err
- return
- }
-
- set cmd [concat [list testregexp -$ask] [flags $flags] [list $re]]
- set run "list \[catch \{$cmd\}\] \[lindex \$errorCode 1\]"
- test $prefix.[tno $testid] [desc $testid] \
- {testregexp} $run [list 1 REG_$err]
-}
+ set constraints [list testregexp]
-# match failure expected
-proc f {testid flags re target args} {
- global prefix description ask
+ if {$regBug} {
+ # This will register as a skipped test
+ lappend constraints knownBug
+ }
# Tcl locale stuff doesn't do the ch/xy test fakery yet
- if {[string first "+" $flags] >= 0} {
+ if {[string match *+* $flags]} {
# This will register as a skipped test
- test $prefix.[tno $testid] [desc $testid] localeRegexp {} {}
- return
+ lappend constraints localeRegexp
}
- # if &, test as both ARE and BRE
- set amp [string first "&" $flags]
- if {$amp >= 0} {
- set f [string range $flags 0 [expr $amp - 1]]
- append f [string range $flags [expr $amp + 1] end]
- eval [linsert $args 0 f [linsert $testid end ARE] ${f} $re \
- $target]
- eval [linsert $args 0 f [linsert $testid end BRE] ${f}b $re \
- $target]
- return
- }
+ set f [TestFlags $flags]
+ set infoflags [TestInfoFlags $flags]
+ set ccmd [list testregexp -about {*}$f $re]
+ set ecmd [list testregexp {*}$opts {*}$f $re $target]
- set f [flags $flags]
- set infoflags [infoflags $flags]
- set ccmd [concat [list testregexp -$ask] $f [list $re]]
- set nsub [expr [llength $args] - 1]
- if {$nsub == -1} {
- # didn't tell us number of subexps
- set ccmd "lreplace \[$ccmd\] 0 0"
- set info [list $infoflags]
- } else {
- set info [list $nsub $infoflags]
+ set nsub [expr {[llength $args] - 1}]
+ set names [list]
+ set refs ""
+ for {set i 0} {$i < [llength $args]} {incr i} {
+ if {$i == 0} {
+ set name match
+ } else {
+ set name sub$i
+ }
+ lappend names $name
+ append refs " \$$name"
+ set $name ""
+ }
+ if {[string match *o* $flags]} { ;# REG_NOSUB kludge
+ set nsub 0 ;# unsigned value cannot be -1
}
- lappend testid "compile"
- test $prefix.[tno $testid] [desc $testid] {testregexp} $ccmd $info
+ if {[string match *t* $flags]} { ;# REG_EXPECT
+ incr nsub -1 ;# the extra does not count
+ }
+ set erun "list \[[concat $ecmd $names]\] $refs"
+ set result [list [expr {![string match *!* $flags]}] {*}$args]
+ set info [list $nsub $infoflags]
- set testid [lreplace $testid end end "execute"]
- set ecmd [concat [list testregexp] $f [list $re $target]]
- test $prefix.[tno $testid] [desc $testid] {testregexp} $ecmd 0
-}
+ ::tcltest::test [TestNum $testid compile] [TestDesc $testid compile] \
+ -constraints $constraints -body $ccmd -result $info
+ ::tcltest::test [TestNum $testid execute] [TestDesc $testid execute] \
+ -constraints $constraints -body $erun -result $result
+ }
-# match expected, internal routine that does the work
-# parameters like the "real" routines except they don't have "opts",
-# which is a possibly-empty list of switches for the regexp match attempt
-# The ! flag is used to indicate expected match failure (for REG_EXPECT,
-# which wants argument testing even in the event of failure).
-proc matchexpected {opts testid flags re target args} {
- global prefix description ask regBug
-
- if {[info exists regBug] && $regBug} {
- # This will register as a skipped test
- test $prefix.[tno $testid] [desc $testid] knownBug {format 0} {1}
- return
+ # set major test number and description
+ proc doing {major desc} {
+ variable description "RE engine $desc"
}
- # Tcl locale stuff doesn't do the ch/xy test fakery yet
- if {[string first "+" $flags] >= 0} {
- # This will register as a skipped test
- test $prefix.[tno $testid] [desc $testid] localeRegexp {} {}
+ # compilation error expected
+ proc expectError {testid flags re err} {
+ # if &, test as both ARE and BRE
+ if {[string match *&* $flags]} {
+ set f [string map {& {}} $flags]
+ expectError "$testid ARE" ${f} $re $err
+ expectError "$testid BRE" ${f}b $re $err
return
}
- # if &, test as both BRE and ARE
- set amp [string first "&" $flags]
- if {$amp >= 0} {
- set f [string range $flags 0 [expr $amp - 1]]
- append f [string range $flags [expr $amp + 1] end]
- eval [concat [list matchexpected $opts \
- [linsert $testid end ARE] ${f} $re $target] $args]
- eval [concat [list matchexpected $opts \
- [linsert $testid end BRE] ${f}b $re $target] $args]
- return
+ set constraints [list testregexp]
+
+ # Tcl locale stuff doesn't do the ch/xy test fakery yet
+ if {[string match *+* $flags]} {
+ # This will register as a skipped test
+ lappend constraints localeRegexp
}
- set f [flags $flags]
- set infoflags [infoflags $flags]
- set ccmd [concat [list testregexp -$ask] $f [list $re]]
- set ecmd [concat [list testregexp] $opts $f [list $re $target]]
+ set cmd [list testregexp -about {*}[TestFlags $flags] $re]
+ ::tcltest::test [TestNum $testid error] [TestDesc $testid error] \
+ -constraints $constraints -result [list 1 REG_$err] -body \
+ "list \[catch \{$cmd\}\] \[lindex \$::errorCode 1\]"
+ }
- set nsub [expr [llength $args] - 1]
- set names [list]
- set refs ""
- for {set i 0} {$i <= $nsub} {incr i} {
- if {$i == 0} {
- set name match
- } else {
- set name sub$i
- }
- lappend names $name
- append refs " \$$name"
- set $name ""
- }
- if {[string first "o" $flags] >= 0} { ;# REG_NOSUB kludge
- set nsub 0 ;# unsigned value cannot be -1
- }
- if {[string first "t" $flags] >= 0} { ;# REG_EXPECT
- incr nsub -1 ;# the extra does not count
- }
- set ecmd [concat $ecmd $names]
- set erun "list \[$ecmd\] $refs"
- set retcode [list 1]
- if {[string first "!" $flags] >= 0} {
- set retcode [list 0]
+ # match failure expected
+ proc expectNomatch {testid flags re target args} {
+ # if &, test as both ARE and BRE
+ if {[string match *&* $flags]} {
+ set f [string map {& {}} $flags]
+ expectNomatch "$testid ARE" ${f} $re $target {*}$args
+ expectNomatch "$testid BRE" ${f}b $re $target {*}$args
+ return
}
- set result [concat $retcode $args]
-
- set info [list $nsub $infoflags]
- lappend testid "compile"
- test $prefix.[tno $testid] [desc $testid] {testregexp} $ccmd $info
- set testid [lreplace $testid end end "execute"]
- test $prefix.[tno $testid] [desc $testid] {testregexp} $erun $result
-}
-# match expected (no missing, empty, or ambiguous submatches)
-# m testno flags re target mat submat ...
-proc m {args} {
- eval matchexpected [linsert $args 0 [list]]
-}
+ set constraints [list testregexp]
-# match expected (full fanciness)
-# i testno flags re target mat submat ...
-proc i {args} {
- eval matchexpected [linsert $args 0 [list "-indices"]]
-}
+ # Tcl locale stuff doesn't do the ch/xy test fakery yet
+ if {[string match *+* $flags]} {
+ # This will register as a skipped test
+ lappend constraints localeRegexp
+ }
-# partial match expected
-# p testno flags re target mat "" ...
-# Quirk: number of ""s must be one more than number of subREs.
-proc p {args} {
- set f [lindex $args 1] ;# add ! flag
- set args [lreplace $args 1 1 "!$f"]
- eval matchexpected [linsert $args 0 [list "-indices"]]
-}
+ set f [TestFlags $flags]
+ set infoflags [TestInfoFlags $flags]
+ set ccmd [list testregexp -about {*}$f $re]
+ set nsub [expr {[llength $args] - 1}]
+ if {$nsub == -1} {
+ # didn't tell us number of subexps
+ set ccmd "lreplace \[$ccmd\] 0 0"
+ set info [list $infoflags]
+ } else {
+ set info [list $nsub $infoflags]
+ }
+ set ecmd [list testregexp {*}$f $re $target]
-# test is a knownBug
-proc knownBug {args} {
- set ::regBug 1
- uplevel #0 $args
- set ::regBug 0
-}
+ ::tcltest::test [TestNum $testid compile] [TestDesc $testid compile] \
+ -constraints $constraints -body $ccmd -result $info
+ ::tcltest::test [TestNum $testid execute] [TestDesc $testid execute] \
+ -constraints $constraints -body $ecmd -result 0
+ }
+ # match expected (no missing, empty, or ambiguous submatches)
+ # expectMatch testno flags re target mat submat ...
+ proc expectMatch {args} {
+ MatchExpected {} {*}$args
+ }
+ # match expected (full fanciness)
+ # expectIndices testno flags re target mat submat ...
+ proc expectIndices {args} {
+ MatchExpected -indices {*}$args
+ }
-# the tests themselves
+ # partial match expected
+ # expectPartial testno flags re target mat "" ...
+ # Quirk: number of ""s must be one more than number of subREs.
+ proc expectPartial {args} {
+ lset args 1 ![lindex $args 1] ;# add ! flag
+ MatchExpected -indices {*}$args
+ }
+ # test is a knownBug
+ proc knownBug {args} {
+ variable regBug 1
+ uplevel \#0 $args
+ set regBug 0
+ }
+}
+namespace import RETest::*
+######## the tests themselves ########
# support functions and preliminary misc.
# This is sensitive to changes in message wording, but we really have to
# test the code->message expansion at least once.
-test reg-0.1 "regexp error reporting" {
- list [catch {regexp (*) ign} msg] $msg
+::tcltest::test reg-0.1 "regexp error reporting" {
+ list [catch {regexp (*) ign} msg] $msg
} {1 {couldn't compile regular expression pattern: quantifier operand invalid}}
-
doing 1 "basic sanity checks"
-m 1 & abc abc abc
-f 2 & abc def
-m 3 & abc xyabxabce abc
-
+expectMatch 1.1 & abc abc abc
+expectNomatch 1.2 & abc def
+expectMatch 1.3 & abc xyabxabce abc
doing 2 "invalid option combinations"
-e 1 qe a INVARG
-e 2 qa a INVARG
-e 3 qx a INVARG
-e 4 qn a INVARG
-e 5 ba a INVARG
-
+expectError 2.1 qe a INVARG
+expectError 2.2 qa a INVARG
+expectError 2.3 qx a INVARG
+expectError 2.4 qn a INVARG
+expectError 2.5 ba a INVARG
doing 3 "basic syntax"
-i 1 &NS "" a {0 -1}
-m 2 NS a| a a
-m 3 - a|b a a
-m 4 - a|b b b
-m 5 NS a||b b b
-m 6 & ab ab ab
-
+expectIndices 3.1 &NS "" a {0 -1}
+expectMatch 3.2 NS a| a a
+expectMatch 3.3 - a|b a a
+expectMatch 3.4 - a|b b b
+expectMatch 3.5 NS a||b b b
+expectMatch 3.6 & ab ab ab
doing 4 "parentheses"
-m 1 - (a)e ae ae a
-m 2 o (a)e ae
-m 3 b {\(a\)b} ab ab a
-m 4 - a((b)c) abc abc bc b
-m 5 - a(b)(c) abc abc b c
-e 6 - a(b EPAREN
-e 7 b {a\(b} EPAREN
+expectMatch 4.1 - (a)e ae ae a
+expectMatch 4.2 o (a)e ae
+expectMatch 4.3 b {\(a\)b} ab ab a
+expectMatch 4.4 - a((b)c) abc abc bc b
+expectMatch 4.5 - a(b)(c) abc abc b c
+expectError 4.6 - a(b EPAREN
+expectError 4.7 b {a\(b} EPAREN
# sigh, we blew it on the specs here... someday this will be fixed in POSIX,
# but meanwhile, it's fixed in AREs
-m 8 eU a)b a)b a)b
-e 9 - a)b EPAREN
-e 10 b {a\)b} EPAREN
-m 11 P a(?:b)c abc abc
-e 12 e a(?:b)c BADRPT
-i 13 S a()b ab {0 1} {1 0}
-m 14 SP a(?:)b ab ab
-i 15 S a(|b)c ac {0 1} {1 0}
-m 16 S a(b|)c abc abc b
-
+expectMatch 4.8 eU a)b a)b a)b
+expectError 4.9 - a)b EPAREN
+expectError 4.10 b {a\)b} EPAREN
+expectMatch 4.11 P a(?:b)c abc abc
+expectError 4.12 e a(?:b)c BADRPT
+expectIndices 4.13 S a()b ab {0 1} {1 0}
+expectMatch 4.14 SP a(?:)b ab ab
+expectIndices 4.15 S a(|b)c ac {0 1} {1 0}
+expectMatch 4.16 S a(b|)c abc abc b
doing 5 "simple one-char matching"
# general case of brackets done later
-m 1 & a.b axb axb
-f 2 &n "a.b" "a\nb"
-m 3 & {a[bc]d} abd abd
-m 4 & {a[bc]d} acd acd
-f 5 & {a[bc]d} aed
-f 6 & {a[^bc]d} abd
-m 7 & {a[^bc]d} aed aed
-f 8 &p "a\[^bc]d" "a\nd"
-
+expectMatch 5.1 & a.b axb axb
+expectNomatch 5.2 &n "a.b" "a\nb"
+expectMatch 5.3 & {a[bc]d} abd abd
+expectMatch 5.4 & {a[bc]d} acd acd
+expectNomatch 5.5 & {a[bc]d} aed
+expectNomatch 5.6 & {a[^bc]d} abd
+expectMatch 5.7 & {a[^bc]d} aed aed
+expectNomatch 5.8 &p "a\[^bc]d" "a\nd"
doing 6 "context-dependent syntax"
# plus odds and ends
-e 1 - * BADRPT
-m 2 b * * *
-m 3 b {\(*\)} * * *
-e 4 - (*) BADRPT
-m 5 b ^* * *
-e 6 - ^* BADRPT
-f 7 & ^b ^b
-m 8 b x^ x^ x^
-f 9 I x^ x
-m 10 n "\n^" "x\nb" "\n"
-f 11 bS {\(^b\)} ^b
-m 12 - (^b) b b b
-m 13 & {x$} x x
-m 14 bS {\(x$\)} x x x
-m 15 - {(x$)} x x x
-m 16 b {x$y} "x\$y" "x\$y"
-f 17 I {x$y} xy
-m 18 n "x\$\n" "x\n" "x\n"
-e 19 - + BADRPT
-e 20 - ? BADRPT
-
+expectError 6.1 - * BADRPT
+expectMatch 6.2 b * * *
+expectMatch 6.3 b {\(*\)} * * *
+expectError 6.4 - (*) BADRPT
+expectMatch 6.5 b ^* * *
+expectError 6.6 - ^* BADRPT
+expectNomatch 6.7 & ^b ^b
+expectMatch 6.8 b x^ x^ x^
+expectNomatch 6.9 I x^ x
+expectMatch 6.10 n "\n^" "x\nb" "\n"
+expectNomatch 6.11 bS {\(^b\)} ^b
+expectMatch 6.12 - (^b) b b b
+expectMatch 6.13 & {x$} x x
+expectMatch 6.14 bS {\(x$\)} x x x
+expectMatch 6.15 - {(x$)} x x x
+expectMatch 6.16 b {x$y} "x\$y" "x\$y"
+expectNomatch 6.17 I {x$y} xy
+expectMatch 6.18 n "x\$\n" "x\n" "x\n"
+expectError 6.19 - + BADRPT
+expectError 6.20 - ? BADRPT
doing 7 "simple quantifiers"
-m 1 &N a* aa aa
-i 2 &N a* b {0 -1}
-m 3 - a+ aa aa
-m 4 - a?b ab ab
-m 5 - a?b b b
-e 6 - ** BADRPT
-m 7 bN ** *** ***
-e 8 & a** BADRPT
-e 9 & a**b BADRPT
-e 10 & *** BADRPT
-e 11 - a++ BADRPT
-e 12 - a?+ BADRPT
-e 13 - a?* BADRPT
-e 14 - a+* BADRPT
-e 15 - a*+ BADRPT
-
+expectMatch 7.1 &N a* aa aa
+expectIndices 7.2 &N a* b {0 -1}
+expectMatch 7.3 - a+ aa aa
+expectMatch 7.4 - a?b ab ab
+expectMatch 7.5 - a?b b b
+expectError 7.6 - ** BADRPT
+expectMatch 7.7 bN ** *** ***
+expectError 7.8 & a** BADRPT
+expectError 7.9 & a**b BADRPT
+expectError 7.10 & *** BADRPT
+expectError 7.11 - a++ BADRPT
+expectError 7.12 - a?+ BADRPT
+expectError 7.13 - a?* BADRPT
+expectError 7.14 - a+* BADRPT
+expectError 7.15 - a*+ BADRPT
doing 8 "braces"
-m 1 NQ "a{0,1}" "" ""
-m 2 NQ "a{0,1}" ac a
-e 3 - "a{1,0}" BADBR
-e 4 - "a{1,2,3}" BADBR
-e 5 - "a{257}" BADBR
-e 6 - "a{1000}" BADBR
-e 7 - "a{1" EBRACE
-e 8 - "a{1n}" BADBR
-m 9 BS "a{b" "a\{b" "a\{b"
-m 10 BS "a{" "a\{" "a\{"
-m 11 bQ "a\\{0,1\\}b" cb b
-e 12 b "a\\{0,1" EBRACE
-e 13 - "a{0,1\\" BADBR
-m 14 Q "a{0}b" ab b
-m 15 Q "a{0,0}b" ab b
-m 16 Q "a{0,1}b" ab ab
-m 17 Q "a{0,2}b" b b
-m 18 Q "a{0,2}b" aab aab
-m 19 Q "a{0,}b" aab aab
-m 20 Q "a{1,1}b" aab ab
-m 21 Q "a{1,3}b" aaaab aaab
-f 22 Q "a{1,3}b" b
-m 23 Q "a{1,}b" aab aab
-f 24 Q "a{2,3}b" ab
-m 25 Q "a{2,3}b" aaaab aaab
-f 26 Q "a{2,}b" ab
-m 27 Q "a{2,}b" aaaab aaaab
-
+expectMatch 8.1 NQ "a{0,1}" "" ""
+expectMatch 8.2 NQ "a{0,1}" ac a
+expectError 8.3 - "a{1,0}" BADBR
+expectError 8.4 - "a{1,2,3}" BADBR
+expectError 8.5 - "a{257}" BADBR
+expectError 8.6 - "a{1000}" BADBR
+expectError 8.7 - "a{1" EBRACE
+expectError 8.8 - "a{1n}" BADBR
+expectMatch 8.9 BS "a{b" "a\{b" "a\{b"
+expectMatch 8.10 BS "a{" "a\{" "a\{"
+expectMatch 8.11 bQ "a\\{0,1\\}b" cb b
+expectError 8.12 b "a\\{0,1" EBRACE
+expectError 8.13 - "a{0,1\\" BADBR
+expectMatch 8.14 Q "a{0}b" ab b
+expectMatch 8.15 Q "a{0,0}b" ab b
+expectMatch 8.16 Q "a{0,1}b" ab ab
+expectMatch 8.17 Q "a{0,2}b" b b
+expectMatch 8.18 Q "a{0,2}b" aab aab
+expectMatch 8.19 Q "a{0,}b" aab aab
+expectMatch 8.20 Q "a{1,1}b" aab ab
+expectMatch 8.21 Q "a{1,3}b" aaaab aaab
+expectNomatch 8.22 Q "a{1,3}b" b
+expectMatch 8.23 Q "a{1,}b" aab aab
+expectNomatch 8.24 Q "a{2,3}b" ab
+expectMatch 8.25 Q "a{2,3}b" aaaab aaab
+expectNomatch 8.26 Q "a{2,}b" ab
+expectMatch 8.27 Q "a{2,}b" aaaab aaaab
doing 9 "brackets"
-m 1 & {a[bc]} ac ac
-m 2 & {a[-]} a- a-
-m 3 & {a[[.-.]]} a- a-
-m 4 &L {a[[.zero.]]} a0 a0
-m 5 &LM {a[[.zero.]-9]} a2 a2
-m 6 &M {a[0-[.9.]]} a2 a2
-m 7 &+L {a[[=x=]]} ax ax
-m 8 &+L {a[[=x=]]} ay ay
-f 9 &+L {a[[=x=]]} az
-e 10 & {a[0-[=x=]]} ERANGE
-m 11 &L {a[[:digit:]]} a0 a0
-e 12 & {a[[:woopsie:]]} ECTYPE
-f 13 &L {a[[:digit:]]} ab
-e 14 & {a[0-[:digit:]]} ERANGE
-m 15 &LP {[[:<:]]a} a a
-m 16 &LP {a[[:>:]]} a a
-e 17 & {a[[..]]b} ECOLLATE
-e 18 & {a[[==]]b} ECOLLATE
-e 19 & {a[[::]]b} ECTYPE
-e 20 & {a[[.a} EBRACK
-e 21 & {a[[=a} EBRACK
-e 22 & {a[[:a} EBRACK
-e 23 & {a[} EBRACK
-e 24 & {a[b} EBRACK
-e 25 & {a[b-} EBRACK
-e 26 & {a[b-c} EBRACK
-m 27 &M {a[b-c]} ab ab
-m 28 & {a[b-b]} ab ab
-m 29 &M {a[1-2]} a2 a2
-e 30 & {a[c-b]} ERANGE
-e 31 & {a[a-b-c]} ERANGE
-m 32 &M {a[--?]b} a?b a?b
-m 33 & {a[---]b} a-b a-b
-m 34 & {a[]b]c} a]c a]c
-m 35 EP {a[\]]b} a]b a]b
-f 36 bE {a[\]]b} a]b
-m 37 bE {a[\]]b} "a\\]b" "a\\]b"
-m 38 eE {a[\]]b} "a\\]b" "a\\]b"
-m 39 EP {a[\\]b} "a\\b" "a\\b"
-m 40 eE {a[\\]b} "a\\b" "a\\b"
-m 41 bE {a[\\]b} "a\\b" "a\\b"
-e 42 - {a[\Z]b} EESCAPE
-m 43 & {a[[b]c} "a\[c" "a\[c"
-m 44 EMP* {a[\u00fe-\u0507][\u00ff-\u0300]b} \
- "a\u0102\u02ffb" "a\u0102\u02ffb"
-
+expectMatch 9.1 & {a[bc]} ac ac
+expectMatch 9.2 & {a[-]} a- a-
+expectMatch 9.3 & {a[[.-.]]} a- a-
+expectMatch 9.4 &L {a[[.zero.]]} a0 a0
+expectMatch 9.5 &LM {a[[.zero.]-9]} a2 a2
+expectMatch 9.6 &M {a[0-[.9.]]} a2 a2
+expectMatch 9.7 &+L {a[[=x=]]} ax ax
+expectMatch 9.8 &+L {a[[=x=]]} ay ay
+expectNomatch 9.9 &+L {a[[=x=]]} az
+expectError 9.10 & {a[0-[=x=]]} ERANGE
+expectMatch 9.11 &L {a[[:digit:]]} a0 a0
+expectError 9.12 & {a[[:woopsie:]]} ECTYPE
+expectNomatch 9.13 &L {a[[:digit:]]} ab
+expectError 9.14 & {a[0-[:digit:]]} ERANGE
+expectMatch 9.15 &LP {[[:<:]]a} a a
+expectMatch 9.16 &LP {a[[:>:]]} a a
+expectError 9.17 & {a[[..]]b} ECOLLATE
+expectError 9.18 & {a[[==]]b} ECOLLATE
+expectError 9.19 & {a[[::]]b} ECTYPE
+expectError 9.20 & {a[[.a} EBRACK
+expectError 9.21 & {a[[=a} EBRACK
+expectError 9.22 & {a[[:a} EBRACK
+expectError 9.23 & {a[} EBRACK
+expectError 9.24 & {a[b} EBRACK
+expectError 9.25 & {a[b-} EBRACK
+expectError 9.26 & {a[b-c} EBRACK
+expectMatch 9.27 &M {a[b-c]} ab ab
+expectMatch 9.28 & {a[b-b]} ab ab
+expectMatch 9.29 &M {a[1-2]} a2 a2
+expectError 9.30 & {a[c-b]} ERANGE
+expectError 9.31 & {a[a-b-c]} ERANGE
+expectMatch 9.32 &M {a[--?]b} a?b a?b
+expectMatch 9.33 & {a[---]b} a-b a-b
+expectMatch 9.34 & {a[]b]c} a]c a]c
+expectMatch 9.35 EP {a[\]]b} a]b a]b
+expectNomatch 9.36 bE {a[\]]b} a]b
+expectMatch 9.37 bE {a[\]]b} "a\\]b" "a\\]b"
+expectMatch 9.38 eE {a[\]]b} "a\\]b" "a\\]b"
+expectMatch 9.39 EP {a[\\]b} "a\\b" "a\\b"
+expectMatch 9.40 eE {a[\\]b} "a\\b" "a\\b"
+expectMatch 9.41 bE {a[\\]b} "a\\b" "a\\b"
+expectError 9.42 - {a[\Z]b} EESCAPE
+expectMatch 9.43 & {a[[b]c} "a\[c" "a\[c"
+expectMatch 9.44 EMP* {a[\u00fe-\u0507][\u00ff-\u0300]b} \
+ "a\u0102\u02ffb" "a\u0102\u02ffb"
doing 10 "anchors and newlines"
-m 1 & ^a a a
-f 2 &^ ^a a
-i 3 &N ^ a {0 -1}
-i 4 & {a$} aba {2 2}
-f 5 {&$} {a$} a
-i 6 &N {$} ab {2 1}
-m 7 &n ^a a a
-m 8 &n "^a" "b\na" "a"
-i 9 &w "^a" "a\na" {0 0}
-i 10 &n^ "^a" "a\na" {2 2}
-m 11 &n {a$} a a
-m 12 &n "a\$" "a\nb" "a"
-i 13 &n "a\$" "a\na" {0 0}
-i 14 N ^^ a {0 -1}
-m 15 b ^^ ^ ^
-i 16 N {$$} a {1 0}
-m 17 b {$$} "\$" "\$"
-m 18 &N {^$} "" ""
-f 19 &N {^$} a
-i 20 &nN "^\$" "a\n\nb" {2 1}
-m 21 N {$^} "" ""
-m 22 b {$^} "\$^" "\$^"
-m 23 P {\Aa} a a
-m 24 ^P {\Aa} a a
-f 25 ^nP {\Aa} "b\na"
-m 26 P {a\Z} a a
-m 27 {$P} {a\Z} a a
-f 28 {$nP} {a\Z} "a\nb"
-e 29 - ^* BADRPT
-e 30 - {$*} BADRPT
-e 31 - {\A*} BADRPT
-e 32 - {\Z*} BADRPT
-
+expectMatch 10.1 & ^a a a
+expectNomatch 10.2 &^ ^a a
+expectIndices 10.3 &N ^ a {0 -1}
+expectIndices 10.4 & {a$} aba {2 2}
+expectNomatch 10.5 {&$} {a$} a
+expectIndices 10.6 &N {$} ab {2 1}
+expectMatch 10.7 &n ^a a a
+expectMatch 10.8 &n "^a" "b\na" "a"
+expectIndices 10.9 &w "^a" "a\na" {0 0}
+expectIndices 10.10 &n^ "^a" "a\na" {2 2}
+expectMatch 10.11 &n {a$} a a
+expectMatch 10.12 &n "a\$" "a\nb" "a"
+expectIndices 10.13 &n "a\$" "a\na" {0 0}
+expectIndices 10.14 N ^^ a {0 -1}
+expectMatch 10.15 b ^^ ^ ^
+expectIndices 10.16 N {$$} a {1 0}
+expectMatch 10.17 b {$$} "\$" "\$"
+expectMatch 10.18 &N {^$} "" ""
+expectNomatch 10.19 &N {^$} a
+expectIndices 10.20 &nN "^\$" a\n\nb {2 1}
+expectMatch 10.21 N {$^} "" ""
+expectMatch 10.22 b {$^} "\$^" "\$^"
+expectMatch 10.23 P {\Aa} a a
+expectMatch 10.24 ^P {\Aa} a a
+expectNomatch 10.25 ^nP {\Aa} "b\na"
+expectMatch 10.26 P {a\Z} a a
+expectMatch 10.27 \$P {a\Z} a a
+expectNomatch 10.28 \$nP {a\Z} "a\nb"
+expectError 10.29 - ^* BADRPT
+expectError 10.30 - {$*} BADRPT
+expectError 10.31 - {\A*} BADRPT
+expectError 10.32 - {\Z*} BADRPT
doing 11 "boundary constraints"
-m 1 &LP {[[:<:]]a} a a
-m 2 &LP {[[:<:]]a} -a a
-f 3 &LP {[[:<:]]a} ba
-m 4 &LP {a[[:>:]]} a a
-m 5 &LP {a[[:>:]]} a- a
-f 6 &LP {a[[:>:]]} ab
-m 7 bLP {\<a} a a
-f 8 bLP {\<a} ba
-m 9 bLP {a\>} a a
-f 10 bLP {a\>} ab
-m 11 LP {\ya} a a
-f 12 LP {\ya} ba
-m 13 LP {a\y} a a
-f 14 LP {a\y} ab
-m 15 LP {a\Y} ab a
-f 16 LP {a\Y} a-
-f 17 LP {a\Y} a
-f 18 LP {-\Y} -a
-m 19 LP {-\Y} -% -
-f 20 LP {\Y-} a-
-e 21 - {[[:<:]]*} BADRPT
-e 22 - {[[:>:]]*} BADRPT
-e 23 b {\<*} BADRPT
-e 24 b {\>*} BADRPT
-e 25 - {\y*} BADRPT
-e 26 - {\Y*} BADRPT
-m 27 LP {\ma} a a
-f 28 LP {\ma} ba
-m 29 LP {a\M} a a
-f 30 LP {a\M} ab
-f 31 ILP {\Ma} a
-f 32 ILP {a\m} a
-
+expectMatch 11.1 &LP {[[:<:]]a} a a
+expectMatch 11.2 &LP {[[:<:]]a} -a a
+expectNomatch 11.3 &LP {[[:<:]]a} ba
+expectMatch 11.4 &LP {a[[:>:]]} a a
+expectMatch 11.5 &LP {a[[:>:]]} a- a
+expectNomatch 11.6 &LP {a[[:>:]]} ab
+expectMatch 11.7 bLP {\<a} a a
+expectNomatch 11.8 bLP {\<a} ba
+expectMatch 11.9 bLP {a\>} a a
+expectNomatch 11.10 bLP {a\>} ab
+expectMatch 11.11 LP {\ya} a a
+expectNomatch 11.12 LP {\ya} ba
+expectMatch 11.13 LP {a\y} a a
+expectNomatch 11.14 LP {a\y} ab
+expectMatch 11.15 LP {a\Y} ab a
+expectNomatch 11.16 LP {a\Y} a-
+expectNomatch 11.17 LP {a\Y} a
+expectNomatch 11.18 LP {-\Y} -a
+expectMatch 11.19 LP {-\Y} -% -
+expectNomatch 11.20 LP {\Y-} a-
+expectError 11.21 - {[[:<:]]*} BADRPT
+expectError 11.22 - {[[:>:]]*} BADRPT
+expectError 11.23 b {\<*} BADRPT
+expectError 11.24 b {\>*} BADRPT
+expectError 11.25 - {\y*} BADRPT
+expectError 11.26 - {\Y*} BADRPT
+expectMatch 11.27 LP {\ma} a a
+expectNomatch 11.28 LP {\ma} ba
+expectMatch 11.29 LP {a\M} a a
+expectNomatch 11.30 LP {a\M} ab
+expectNomatch 11.31 ILP {\Ma} a
+expectNomatch 11.32 ILP {a\m} a
doing 12 "character classes"
-m 1 LP {a\db} a0b a0b
-f 2 LP {a\db} axb
-f 3 LP {a\Db} a0b
-m 4 LP {a\Db} axb axb
-m 5 LP "a\\sb" "a b" "a b"
-m 6 LP "a\\sb" "a\tb" "a\tb"
-m 7 LP "a\\sb" "a\nb" "a\nb"
-f 8 LP {a\sb} axb
-m 9 LP {a\Sb} axb axb
-f 10 LP "a\\Sb" "a b"
-m 11 LP {a\wb} axb axb
-f 12 LP {a\wb} a-b
-f 13 LP {a\Wb} axb
-m 14 LP {a\Wb} a-b a-b
-m 15 LP {\y\w+z\y} adze-guz guz
-m 16 LPE {a[\d]b} a1b a1b
-m 17 LPE "a\[\\s]b" "a b" "a b"
-m 18 LPE {a[\w]b} axb axb
-
+expectMatch 12.1 LP {a\db} a0b a0b
+expectNomatch 12.2 LP {a\db} axb
+expectNomatch 12.3 LP {a\Db} a0b
+expectMatch 12.4 LP {a\Db} axb axb
+expectMatch 12.5 LP "a\\sb" "a b" "a b"
+expectMatch 12.6 LP "a\\sb" "a\tb" "a\tb"
+expectMatch 12.7 LP "a\\sb" "a\nb" "a\nb"
+expectNomatch 12.8 LP {a\sb} axb
+expectMatch 12.9 LP {a\Sb} axb axb
+expectNomatch 12.10 LP "a\\Sb" "a b"
+expectMatch 12.11 LP {a\wb} axb axb
+expectNomatch 12.12 LP {a\wb} a-b
+expectNomatch 12.13 LP {a\Wb} axb
+expectMatch 12.14 LP {a\Wb} a-b a-b
+expectMatch 12.15 LP {\y\w+z\y} adze-guz guz
+expectMatch 12.16 LPE {a[\d]b} a1b a1b
+expectMatch 12.17 LPE "a\[\\s]b" "a b" "a b"
+expectMatch 12.18 LPE {a[\w]b} axb axb
doing 13 "escapes"
-e 1 & "a\\" EESCAPE
-m 2 - {a\<b} a<b a<b
-m 3 e {a\<b} a<b a<b
-m 4 bAS {a\wb} awb awb
-m 5 eAS {a\wb} awb awb
-m 6 PL "a\\ab" "a\007b" "a\007b"
-m 7 P "a\\bb" "a\bb" "a\bb"
-m 8 P {a\Bb} "a\\b" "a\\b"
-m 9 MP "a\\chb" "a\bb" "a\bb"
-m 10 MP "a\\cHb" "a\bb" "a\bb"
-m 11 LMP "a\\e" "a\033" "a\033"
-m 12 P "a\\fb" "a\fb" "a\fb"
-m 13 P "a\\nb" "a\nb" "a\nb"
-m 14 P "a\\rb" "a\rb" "a\rb"
-m 15 P "a\\tb" "a\tb" "a\tb"
-m 16 P "a\\u0008x" "a\bx" "a\bx"
-e 17 - {a\u008x} EESCAPE
-m 18 P "a\\u00088x" "a\b8x" "a\b8x"
-m 19 P "a\\U00000008x" "a\bx" "a\bx"
-e 20 - {a\U0000008x} EESCAPE
-m 21 P "a\\vb" "a\vb" "a\vb"
-m 22 MP "a\\x08x" "a\bx" "a\bx"
-e 23 - {a\xq} EESCAPE
-m 24 MP "a\\x0008x" "a\bx" "a\bx"
-e 25 - {a\z} EESCAPE
-m 26 MP "a\\010b" "a\bb" "a\bb"
-
+expectError 13.1 & "a\\" EESCAPE
+expectMatch 13.2 - {a\<b} a<b a<b
+expectMatch 13.3 e {a\<b} a<b a<b
+expectMatch 13.4 bAS {a\wb} awb awb
+expectMatch 13.5 eAS {a\wb} awb awb
+expectMatch 13.6 PL "a\\ab" "a\007b" "a\007b"
+expectMatch 13.7 P "a\\bb" "a\bb" "a\bb"
+expectMatch 13.8 P {a\Bb} "a\\b" "a\\b"
+expectMatch 13.9 MP "a\\chb" "a\bb" "a\bb"
+expectMatch 13.10 MP "a\\cHb" "a\bb" "a\bb"
+expectMatch 13.11 LMP "a\\e" "a\033" "a\033"
+expectMatch 13.12 P "a\\fb" "a\fb" "a\fb"
+expectMatch 13.13 P "a\\nb" "a\nb" "a\nb"
+expectMatch 13.14 P "a\\rb" "a\rb" "a\rb"
+expectMatch 13.15 P "a\\tb" "a\tb" "a\tb"
+expectMatch 13.16 P "a\\u0008x" "a\bx" "a\bx"
+expectError 13.17 - {a\u008x} EESCAPE
+expectMatch 13.18 P "a\\u00088x" "a\b8x" "a\b8x"
+expectMatch 13.19 P "a\\U00000008x" "a\bx" "a\bx"
+expectError 13.20 - {a\U0000008x} EESCAPE
+expectMatch 13.21 P "a\\vb" "a\vb" "a\vb"
+expectMatch 13.22 MP "a\\x08x" "a\bx" "a\bx"
+expectError 13.23 - {a\xq} EESCAPE
+expectMatch 13.24 MP "a\\x0008x" "a\bx" "a\bx"
+expectError 13.25 - {a\z} EESCAPE
+expectMatch 13.26 MP "a\\010b" "a\bb" "a\bb"
doing 14 "back references"
# ugh
-m 1 RP {a(b*)c\1} abbcbb abbcbb bb
-m 2 RP {a(b*)c\1} ac ac ""
-f 3 RP {a(b*)c\1} abbcb
-m 4 RP {a(b*)\1} abbcbb abb b
-m 5 RP {a(b|bb)\1} abbcbb abb b
-m 6 RP {a([bc])\1} abb abb b
-f 7 RP {a([bc])\1} abc
-m 8 RP {a([bc])\1} abcabb abb b
-f 9 RP {a([bc])*\1} abc
-f 10 RP {a([bc])\1} abB
-m 11 iRP {a([bc])\1} abB abB b
-m 12 RP {a([bc])\1+} abbb abbb b
-m 13 QRP "a(\[bc])\\1{3,4}" abbbb abbbb b
-f 14 QRP "a(\[bc])\\1{3,4}" abbb
-m 15 RP {a([bc])\1*} abbb abbb b
-m 16 RP {a([bc])\1*} ab ab b
-m 17 RP {a([bc])(\1*)} ab ab b ""
-e 18 - {a((b)\1)} ESUBREG
-e 19 - {a(b)c\2} ESUBREG
-m 20 bR {a\(b*\)c\1} abbcbb abbcbb bb
-
+expectMatch 14.1 RP {a(b*)c\1} abbcbb abbcbb bb
+expectMatch 14.2 RP {a(b*)c\1} ac ac ""
+expectNomatch 14.3 RP {a(b*)c\1} abbcb
+expectMatch 14.4 RP {a(b*)\1} abbcbb abb b
+expectMatch 14.5 RP {a(b|bb)\1} abbcbb abb b
+expectMatch 14.6 RP {a([bc])\1} abb abb b
+expectNomatch 14.7 RP {a([bc])\1} abc
+expectMatch 14.8 RP {a([bc])\1} abcabb abb b
+expectNomatch 14.9 RP {a([bc])*\1} abc
+expectNomatch 14.10 RP {a([bc])\1} abB
+expectMatch 14.11 iRP {a([bc])\1} abB abB b
+expectMatch 14.12 RP {a([bc])\1+} abbb abbb b
+expectMatch 14.13 QRP "a(\[bc])\\1{3,4}" abbbb abbbb b
+expectNomatch 14.14 QRP "a(\[bc])\\1{3,4}" abbb
+expectMatch 14.15 RP {a([bc])\1*} abbb abbb b
+expectMatch 14.16 RP {a([bc])\1*} ab ab b
+expectMatch 14.17 RP {a([bc])(\1*)} ab ab b ""
+expectError 14.18 - {a((b)\1)} ESUBREG
+expectError 14.19 - {a(b)c\2} ESUBREG
+expectMatch 14.20 bR {a\(b*\)c\1} abbcbb abbcbb bb
doing 15 "octal escapes vs back references"
# initial zero is always octal
-m 1 MP "a\\010b" "a\bb" "a\bb"
-m 2 MP "a\\0070b" "a\0070b" "a\0070b"
-m 3 MP "a\\07b" "a\007b" "a\007b"
-m 4 MP "a(b)(b)(b)(b)(b)(b)(b)(b)(b)(b)\\07c" "abbbbbbbbbb\007c" \
- "abbbbbbbbbb\007c" "b" "b" "b" "b" "b" "b" \
- "b" "b" "b" "b"
+expectMatch 15.1 MP "a\\010b" "a\bb" "a\bb"
+expectMatch 15.2 MP "a\\0070b" "a\0070b" "a\0070b"
+expectMatch 15.3 MP "a\\07b" "a\007b" "a\007b"
+expectMatch 15.4 MP "a(b)(b)(b)(b)(b)(b)(b)(b)(b)(b)\\07c" \
+ "abbbbbbbbbb\007c" abbbbbbbbbb\007c b b b b b b b b b b
# a single digit is always a backref
-e 5 - {a\7b} ESUBREG
+expectError 15.5 - {a\7b} ESUBREG
# otherwise it's a backref only if within range (barf!)
-m 6 MP "a\\10b" "a\bb" "a\bb"
-m 7 MP {a\101b} aAb aAb
-m 8 RP {a(b)(b)(b)(b)(b)(b)(b)(b)(b)(b)\10c} abbbbbbbbbbbc \
- abbbbbbbbbbbc b b b b b b b \
- b b b
+expectMatch 15.6 MP "a\\10b" "a\bb" "a\bb"
+expectMatch 15.7 MP {a\101b} aAb aAb
+expectMatch 15.8 RP {a(b)(b)(b)(b)(b)(b)(b)(b)(b)(b)\10c} \
+ "abbbbbbbbbbbc" abbbbbbbbbbbc b b b b b b b b b b
# but we're fussy about border cases -- guys who want octal should use the zero
-e 9 - {a((((((((((b\10))))))))))c} ESUBREG
+expectError 15.9 - {a((((((((((b\10))))))))))c} ESUBREG
# BREs don't have octal, EREs don't have backrefs
-m 10 MP "a\\12b" "a\nb" "a\nb"
-e 11 b {a\12b} ESUBREG
-m 12 eAS {a\12b} a12b a12b
-
+expectMatch 15.10 MP "a\\12b" "a\nb" "a\nb"
+expectError 15.11 b {a\12b} ESUBREG
+expectMatch 15.12 eAS {a\12b} a12b a12b
doing 16 "expanded syntax"
-m 1 xP "a b c" "abc" "abc"
-m 2 xP "a b #oops\nc\td" "abcd" "abcd"
-m 3 x "a\\ b\\\tc" "a b\tc" "a b\tc"
-m 4 xP "a b\\#c" "ab#c" "ab#c"
-m 5 xP "a b\[c d]e" "ab e" "ab e"
-m 6 xP "a b\[c#d]e" "ab#e" "ab#e"
-m 7 xP "a b\[c#d]e" "abde" "abde"
-m 8 xSPB "ab{ d" "ab\{d" "ab\{d"
-m 9 xPQ "ab{ 1 , 2 }c" "abc" "abc"
-
+expectMatch 16.1 xP "a b c" "abc" "abc"
+expectMatch 16.2 xP "a b #oops\nc\td" "abcd" "abcd"
+expectMatch 16.3 x "a\\ b\\\tc" "a b\tc" "a b\tc"
+expectMatch 16.4 xP "a b\\#c" "ab#c" "ab#c"
+expectMatch 16.5 xP "a b\[c d]e" "ab e" "ab e"
+expectMatch 16.6 xP "a b\[c#d]e" "ab#e" "ab#e"
+expectMatch 16.7 xP "a b\[c#d]e" "abde" "abde"
+expectMatch 16.8 xSPB "ab{ d" "ab\{d" "ab\{d"
+expectMatch 16.9 xPQ "ab{ 1 , 2 }c" "abc" "abc"
doing 17 "misc syntax"
-m 1 P a(?#comment)b ab ab
-
+expectMatch 17.1 P a(?#comment)b ab ab
doing 18 "unmatchable REs"
-f 1 I a^b ab
-
+expectNomatch 18.1 I a^b ab
doing 19 "case independence"
-m 1 &i ab Ab Ab
-m 2 &i {a[bc]} aC aC
-f 3 &i {a[^bc]} aB
-m 4 &iM {a[b-d]} aC aC
-f 5 &iM {a[^b-d]} aC
-
+expectMatch 19.1 &i ab Ab Ab
+expectMatch 19.2 &i {a[bc]} aC aC
+expectNomatch 19.3 &i {a[^bc]} aB
+expectMatch 19.4 &iM {a[b-d]} aC aC
+expectNomatch 19.5 &iM {a[^b-d]} aC
doing 20 "directors and embedded options"
-e 1 & ***? BADPAT
-m 2 q ***? ***? ***?
-m 3 &P ***=a*b a*b a*b
-m 4 q ***=a*b ***=a*b ***=a*b
-m 5 bLP {***:\w+} ab ab
-m 6 eLP {***:\w+} ab ab
-e 7 & ***:***=a*b BADRPT
-m 8 &P ***:(?b)a+b a+b a+b
-m 9 P (?b)a+b a+b a+b
-e 10 e {(?b)\w+} BADRPT
-m 11 bAS {(?b)\w+} (?b)w+ (?b)w+
-m 12 iP (?c)a a a
-f 13 iP (?c)a A
-m 14 APS {(?e)\W+} WW WW
-m 15 P (?i)a+ Aa Aa
-f 16 P "(?m)a.b" "a\nb"
-m 17 P "(?m)^b" "a\nb" "b"
-f 18 P "(?n)a.b" "a\nb"
-m 19 P "(?n)^b" "a\nb" "b"
-f 20 P "(?p)a.b" "a\nb"
-f 21 P "(?p)^b" "a\nb"
-m 22 P (?q)a+b a+b a+b
-m 23 nP "(?s)a.b" "a\nb" "a\nb"
-m 24 xP "(?t)a b" "a b" "a b"
-m 25 P "(?w)a.b" "a\nb" "a\nb"
-m 26 P "(?w)^b" "a\nb" "b"
-m 27 P "(?x)a b" "ab" "ab"
-e 28 - (?z)ab BADOPT
-m 29 P (?ici)a+ Aa Aa
-e 30 P (?i)(?q)a+ BADRPT
-m 31 P (?q)(?i)a+ (?i)a+ (?i)a+
-m 32 P (?qe)a+ a a
-m 33 xP "(?q)a b" "a b" "a b"
-m 34 P "(?qx)a b" "a b" "a b"
-m 35 P (?qi)ab Ab Ab
-
+expectError 20.1 & ***? BADPAT
+expectMatch 20.2 q ***? ***? ***?
+expectMatch 20.3 &P ***=a*b a*b a*b
+expectMatch 20.4 q ***=a*b ***=a*b ***=a*b
+expectMatch 20.5 bLP {***:\w+} ab ab
+expectMatch 20.6 eLP {***:\w+} ab ab
+expectError 20.7 & ***:***=a*b BADRPT
+expectMatch 20.8 &P ***:(?b)a+b a+b a+b
+expectMatch 20.9 P (?b)a+b a+b a+b
+expectError 20.10 e {(?b)\w+} BADRPT
+expectMatch 20.11 bAS {(?b)\w+} (?b)w+ (?b)w+
+expectMatch 20.12 iP (?c)a a a
+expectNomatch 20.13 iP (?c)a A
+expectMatch 20.14 APS {(?e)\W+} WW WW
+expectMatch 20.15 P (?i)a+ Aa Aa
+expectNomatch 20.16 P "(?m)a.b" "a\nb"
+expectMatch 20.17 P "(?m)^b" "a\nb" "b"
+expectNomatch 20.18 P "(?n)a.b" "a\nb"
+expectMatch 20.19 P "(?n)^b" "a\nb" "b"
+expectNomatch 20.20 P "(?p)a.b" "a\nb"
+expectNomatch 20.21 P "(?p)^b" "a\nb"
+expectMatch 20.22 P (?q)a+b a+b a+b
+expectMatch 20.23 nP "(?s)a.b" "a\nb" "a\nb"
+expectMatch 20.24 xP "(?t)a b" "a b" "a b"
+expectMatch 20.25 P "(?w)a.b" "a\nb" "a\nb"
+expectMatch 20.26 P "(?w)^b" "a\nb" "b"
+expectMatch 20.27 P "(?x)a b" "ab" "ab"
+expectError 20.28 - (?z)ab BADOPT
+expectMatch 20.29 P (?ici)a+ Aa Aa
+expectError 20.30 P (?i)(?q)a+ BADRPT
+expectMatch 20.31 P (?q)(?i)a+ (?i)a+ (?i)a+
+expectMatch 20.32 P (?qe)a+ a a
+expectMatch 20.33 xP "(?q)a b" "a b" "a b"
+expectMatch 20.34 P "(?qx)a b" "a b" "a b"
+expectMatch 20.35 P (?qi)ab Ab Ab
doing 21 "capturing"
-m 1 - a(b)c abc abc b
-m 2 P a(?:b)c xabc abc
-m 3 - a((b))c xabcy abc b b
-m 4 P a(?:(b))c abcy abc b
-m 5 P a((?:b))c abc abc b
-m 6 P a(?:(?:b))c abc abc
-i 7 Q "a(b){0}c" ac {0 1} {-1 -1}
-m 8 - a(b)c(d)e abcde abcde b d
-m 9 - (b)c(d)e bcde bcde b d
-m 10 - a(b)(d)e abde abde b d
-m 11 - a(b)c(d) abcd abcd b d
-m 12 - (ab)(cd) xabcdy abcd ab cd
-m 13 - a(b)?c xabcy abc b
-i 14 - a(b)?c xacy {1 2} {-1 -1}
-m 15 - a(b)?c(d)?e xabcdey abcde b d
-i 16 - a(b)?c(d)?e xacdey {1 4} {-1 -1} {3 3}
-i 17 - a(b)?c(d)?e xabcey {1 4} {2 2} {-1 -1}
-i 18 - a(b)?c(d)?e xacey {1 3} {-1 -1} {-1 -1}
-m 19 - a(b)*c xabcy abc b
-i 20 - a(b)*c xabbbcy {1 5} {4 4}
-i 21 - a(b)*c xacy {1 2} {-1 -1}
-m 22 - a(b*)c xabbbcy abbbc bbb
-m 23 - a(b*)c xacy ac ""
-f 24 - a(b)+c xacy
-m 25 - a(b)+c xabcy abc b
-i 26 - a(b)+c xabbbcy {1 5} {4 4}
-m 27 - a(b+)c xabbbcy abbbc bbb
-i 28 Q "a(b){2,3}c" xabbbcy {1 5} {4 4}
-i 29 Q "a(b){2,3}c" xabbcy {1 4} {3 3}
-f 30 Q "a(b){2,3}c" xabcy
-m 31 LP "\\y(\\w+)\\y" "-- abc-" "abc" "abc"
-m 32 - a((b|c)d+)+ abacdbd acdbd bd b
-m 33 N (.*).* abc abc abc
-m 34 N (a*)* bc "" ""
-
+expectMatch 21.1 - a(b)c abc abc b
+expectMatch 21.2 P a(?:b)c xabc abc
+expectMatch 21.3 - a((b))c xabcy abc b b
+expectMatch 21.4 P a(?:(b))c abcy abc b
+expectMatch 21.5 P a((?:b))c abc abc b
+expectMatch 21.6 P a(?:(?:b))c abc abc
+expectIndices 21.7 Q "a(b){0}c" ac {0 1} {-1 -1}
+expectMatch 21.8 - a(b)c(d)e abcde abcde b d
+expectMatch 21.9 - (b)c(d)e bcde bcde b d
+expectMatch 21.10 - a(b)(d)e abde abde b d
+expectMatch 21.11 - a(b)c(d) abcd abcd b d
+expectMatch 21.12 - (ab)(cd) xabcdy abcd ab cd
+expectMatch 21.13 - a(b)?c xabcy abc b
+expectIndices 21.14 - a(b)?c xacy {1 2} {-1 -1}
+expectMatch 21.15 - a(b)?c(d)?e xabcdey abcde b d
+expectIndices 21.16 - a(b)?c(d)?e xacdey {1 4} {-1 -1} {3 3}
+expectIndices 21.17 - a(b)?c(d)?e xabcey {1 4} {2 2} {-1 -1}
+expectIndices 21.18 - a(b)?c(d)?e xacey {1 3} {-1 -1} {-1 -1}
+expectMatch 21.19 - a(b)*c xabcy abc b
+expectIndices 21.20 - a(b)*c xabbbcy {1 5} {4 4}
+expectIndices 21.21 - a(b)*c xacy {1 2} {-1 -1}
+expectMatch 21.22 - a(b*)c xabbbcy abbbc bbb
+expectMatch 21.23 - a(b*)c xacy ac ""
+expectNomatch 21.24 - a(b)+c xacy
+expectMatch 21.25 - a(b)+c xabcy abc b
+expectIndices 21.26 - a(b)+c xabbbcy {1 5} {4 4}
+expectMatch 21.27 - a(b+)c xabbbcy abbbc bbb
+expectIndices 21.28 Q "a(b){2,3}c" xabbbcy {1 5} {4 4}
+expectIndices 21.29 Q "a(b){2,3}c" xabbcy {1 4} {3 3}
+expectNomatch 21.30 Q "a(b){2,3}c" xabcy
+expectMatch 21.31 LP "\\y(\\w+)\\y" "-- abc-" "abc" "abc"
+expectMatch 21.32 - a((b|c)d+)+ abacdbd acdbd bd b
+expectMatch 21.33 N (.*).* abc abc abc
+expectMatch 21.34 N (a*)* bc "" ""
doing 22 "multicharacter collating elements"
# again ugh
-m 1 &+L {a[c]e} ace ace
-f 2 &+IL {a[c]h} ach
-m 3 &+L {a[[.ch.]]} ach ach
-f 4 &+L {a[[.ch.]]} ace
-m 5 &+L {a[c[.ch.]]} ac ac
-m 6 &+L {a[c[.ch.]]} ace ac
-m 7 &+L {a[c[.ch.]]} ache ach
-f 8 &+L {a[^c]e} ace
-m 9 &+L {a[^c]e} abe abe
-m 10 &+L {a[^c]e} ache ache
-f 11 &+L {a[^[.ch.]]} ach
-m 12 &+L {a[^[.ch.]]} ace ac
-m 13 &+L {a[^[.ch.]]} ac ac
-m 14 &+L {a[^[.ch.]]} abe ab
-f 15 &+L {a[^c[.ch.]]} ach
-f 16 &+L {a[^c[.ch.]]} ace
-f 17 &+L {a[^c[.ch.]]} ac
-m 18 &+L {a[^c[.ch.]]} abe ab
-m 19 &+L {a[^b]} ac ac
-m 20 &+L {a[^b]} ace ac
-m 21 &+L {a[^b]} ach ach
-f 22 &+L {a[^b]} abe
-
+expectMatch 22.1 &+L {a[c]e} ace ace
+expectNomatch 22.2 &+IL {a[c]h} ach
+expectMatch 22.3 &+L {a[[.ch.]]} ach ach
+expectNomatch 22.4 &+L {a[[.ch.]]} ace
+expectMatch 22.5 &+L {a[c[.ch.]]} ac ac
+expectMatch 22.6 &+L {a[c[.ch.]]} ace ac
+expectMatch 22.7 &+L {a[c[.ch.]]} ache ach
+expectNomatch 22.8 &+L {a[^c]e} ace
+expectMatch 22.9 &+L {a[^c]e} abe abe
+expectMatch 22.10 &+L {a[^c]e} ache ache
+expectNomatch 22.11 &+L {a[^[.ch.]]} ach
+expectMatch 22.12 &+L {a[^[.ch.]]} ace ac
+expectMatch 22.13 &+L {a[^[.ch.]]} ac ac
+expectMatch 22.14 &+L {a[^[.ch.]]} abe ab
+expectNomatch 22.15 &+L {a[^c[.ch.]]} ach
+expectNomatch 22.16 &+L {a[^c[.ch.]]} ace
+expectNomatch 22.17 &+L {a[^c[.ch.]]} ac
+expectMatch 22.18 &+L {a[^c[.ch.]]} abe ab
+expectMatch 22.19 &+L {a[^b]} ac ac
+expectMatch 22.20 &+L {a[^b]} ace ac
+expectMatch 22.21 &+L {a[^b]} ach ach
+expectNomatch 22.22 &+L {a[^b]} abe
doing 23 "lookahead constraints"
-m 1 HP a(?=b)b* ab ab
-f 2 HP a(?=b)b* a
-m 3 HP a(?=b)b*(?=c)c* abc abc
-f 4 HP a(?=b)b*(?=c)c* ab
-f 5 HP a(?!b)b* ab
-m 6 HP a(?!b)b* a a
-m 7 HP (?=b)b b b
-f 8 HP (?=b)b a
-
+expectMatch 23.1 HP a(?=b)b* ab ab
+expectNomatch 23.2 HP a(?=b)b* a
+expectMatch 23.3 HP a(?=b)b*(?=c)c* abc abc
+expectNomatch 23.4 HP a(?=b)b*(?=c)c* ab
+expectNomatch 23.5 HP a(?!b)b* ab
+expectMatch 23.6 HP a(?!b)b* a a
+expectMatch 23.7 HP (?=b)b b b
+expectNomatch 23.8 HP (?=b)b a
doing 24 "non-greedy quantifiers"
-m 1 PT ab+? abb ab
-m 2 PT ab+?c abbc abbc
-m 3 PT ab*? abb a
-m 4 PT ab*?c abbc abbc
-m 5 PT ab?? ab a
-m 6 PT ab??c abc abc
-m 7 PQT "ab{2,4}?" abbbb abb
-m 8 PQT "ab{2,4}?c" abbbbc abbbbc
-m 9 - 3z* 123zzzz456 3zzzz
-m 10 PT 3z*? 123zzzz456 3
-m 11 - z*4 123zzzz456 zzzz4
-m 12 PT z*?4 123zzzz456 zzzz4
-
+expectMatch 24.1 PT ab+? abb ab
+expectMatch 24.2 PT ab+?c abbc abbc
+expectMatch 24.3 PT ab*? abb a
+expectMatch 24.4 PT ab*?c abbc abbc
+expectMatch 24.5 PT ab?? ab a
+expectMatch 24.6 PT ab??c abc abc
+expectMatch 24.7 PQT "ab{2,4}?" abbbb abb
+expectMatch 24.8 PQT "ab{2,4}?c" abbbbc abbbbc
+expectMatch 24.9 - 3z* 123zzzz456 3zzzz
+expectMatch 24.10 PT 3z*? 123zzzz456 3
+expectMatch 24.11 - z*4 123zzzz456 zzzz4
+expectMatch 24.12 PT z*?4 123zzzz456 zzzz4
doing 25 "mixed quantifiers"
# this is very incomplete as yet
# should include |
-m 1 PNT {^(.*?)(a*)$} xyza xyza xyz a
-m 2 PNT {^(.*?)(a*)$} xyzaa xyzaa xyz aa
-m 3 PNT {^(.*?)(a*)$} xyz xyz xyz ""
-
+expectMatch 25.1 PNT {^(.*?)(a*)$} "xyza" xyza xyz a
+expectMatch 25.2 PNT {^(.*?)(a*)$} "xyzaa" xyzaa xyz aa
+expectMatch 25.3 PNT {^(.*?)(a*)$} "xyz" xyz xyz ""
doing 26 "tricky cases"
# attempts to trick the matcher into accepting a short match
-m 1 - (week|wee)(night|knights) weeknights weeknights \
- wee knights
-m 2 RP {a(bc*).*\1} abccbccb abccbccb b
-m 3 - {a(b.[bc]*)+} abcbd abcbd bd
-
+expectMatch 26.1 - (week|wee)(night|knights) \
+ "weeknights" weeknights wee knights
+expectMatch 26.2 RP {a(bc*).*\1} abccbccb abccbccb b
+expectMatch 26.3 - {a(b.[bc]*)+} abcbd abcbd bd
doing 27 "implementation misc."
# duplicate arcs are suppressed
-m 1 P a(?:b|b)c abc abc
+expectMatch 27.1 P a(?:b|b)c abc abc
# make color/subcolor relationship go back and forth
-m 2 & {[ab][ab][ab]} aba aba
-m 3 & {[ab][ab][ab][ab][ab][ab][ab]} abababa abababa
-
+expectMatch 27.2 & {[ab][ab][ab]} aba aba
+expectMatch 27.3 & {[ab][ab][ab][ab][ab][ab][ab]} \
+ "abababa" abababa
doing 28 "boundary busters etc."
# color-descriptor allocation changes at 10
-m 1 & abcdefghijkl abcdefghijkl abcdefghijkl
+expectMatch 28.1 & abcdefghijkl "abcdefghijkl" abcdefghijkl
# so does arc allocation
-m 2 P a(?:b|c|d|e|f|g|h|i|j|k|l|m)n agn agn
+expectMatch 28.2 P a(?:b|c|d|e|f|g|h|i|j|k|l|m)n "agn" agn
# subexpression tracking also at 10
-m 3 - a(((((((((((((b)))))))))))))c abc abc b b b b b b b b b b b b b
+expectMatch 28.3 - a(((((((((((((b)))))))))))))c \
+ "abc" abc b b b b b b b b b b b b b
# state-set handling changes slightly at unsigned size (might be 64...)
# (also stresses arc allocation)
-m 4 Q "ab{1,100}c" abbc abbc
-m 5 Q "ab{1,100}c" abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc \
+expectMatch 28.4 Q "ab{1,100}c" abbc abbc
+expectMatch 28.5 Q "ab{1,100}c" \
+ "abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc" \
abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc
-m 6 Q "ab{1,100}c" \
- abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc \
+expectMatch 28.6 Q "ab{1,100}c" \
+ "abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc"\
abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc
# force small cache and bust it, several ways
-m 7 LP {\w+abcdefgh} xyzabcdefgh xyzabcdefgh
-m 8 %LP {\w+abcdefgh} xyzabcdefgh xyzabcdefgh
-m 9 %LP {\w+abcdefghijklmnopqrst} xyzabcdefghijklmnopqrst \
- xyzabcdefghijklmnopqrst
-i 10 %LP {\w+(abcdefgh)?} xyz {0 2} {-1 -1}
-i 11 %LP {\w+(abcdefgh)?} xyzabcdefg {0 9} {-1 -1}
-i 12 %LP {\w+(abcdefghijklmnopqrst)?} xyzabcdefghijklmnopqrs \
- {0 21} {-1 -1}
-
+expectMatch 28.7 LP {\w+abcdefgh} xyzabcdefgh xyzabcdefgh
+expectMatch 28.8 %LP {\w+abcdefgh} xyzabcdefgh xyzabcdefgh
+expectMatch 28.9 %LP {\w+abcdefghijklmnopqrst} \
+ "xyzabcdefghijklmnopqrst" xyzabcdefghijklmnopqrst
+expectIndices 28.10 %LP {\w+(abcdefgh)?} xyz {0 2} {-1 -1}
+expectIndices 28.11 %LP {\w+(abcdefgh)?} xyzabcdefg {0 9} {-1 -1}
+expectIndices 28.12 %LP {\w+(abcdefghijklmnopqrst)?} \
+ "xyzabcdefghijklmnopqrs" {0 21} {-1 -1}
doing 29 "incomplete matches"
-p 1 t def abc {3 2} ""
-p 2 t bcd abc {1 2} ""
-p 3 t abc abab {0 3} ""
-p 4 t abc abdab {3 4} ""
-i 5 t abc abc {0 2} {0 2}
-i 6 t abc xyabc {2 4} {2 4}
-p 7 t abc+ xyab {2 3} ""
-i 8 t abc+ xyabc {2 4} {2 4}
-knownBug i 9 t abc+ xyabcd {2 4} {6 5}
-i 10 t abc+ xyabcdd {2 4} {7 6}
-p 11 tPT abc+? xyab {2 3} ""
+expectPartial 29.1 t def abc {3 2} ""
+expectPartial 29.2 t bcd abc {1 2} ""
+expectPartial 29.3 t abc abab {0 3} ""
+expectPartial 29.4 t abc abdab {3 4} ""
+expectIndices 29.5 t abc abc {0 2} {0 2}
+expectIndices 29.6 t abc xyabc {2 4} {2 4}
+expectPartial 29.7 t abc+ xyab {2 3} ""
+expectIndices 29.8 t abc+ xyabc {2 4} {2 4}
+knownBug expectIndices 29.9 t abc+ xyabcd {2 4} {6 5}
+expectIndices 29.10 t abc+ xyabcdd {2 4} {7 6}
+expectPartial 29.11 tPT abc+? xyab {2 3} ""
# the retain numbers in these two may look wrong, but they aren't
-i 12 tPT abc+? xyabc {2 4} {5 4}
-i 13 tPT abc+? xyabcc {2 4} {6 5}
-i 14 tPT abc+? xyabcd {2 4} {6 5}
-i 15 tPT abc+? xyabcdd {2 4} {7 6}
-i 16 t abcd|bc xyabc {3 4} {2 4}
-p 17 tn .*k "xx\nyyy" {3 5} ""
+expectIndices 29.12 tPT abc+? xyabc {2 4} {5 4}
+expectIndices 29.13 tPT abc+? xyabcc {2 4} {6 5}
+expectIndices 29.14 tPT abc+? xyabcd {2 4} {6 5}
+expectIndices 29.15 tPT abc+? xyabcdd {2 4} {7 6}
+expectIndices 29.16 t abcd|bc xyabc {3 4} {2 4}
+expectPartial 29.17 tn .*k "xx\nyyy" {3 5} ""
doing 30 "misc. oddities and old bugs"
-e 1 & *** BADRPT
-m 2 N a?b* abb abb
-m 3 N a?b* bb bb
-m 4 & a*b aab aab
-m 5 & ^a*b aaaab aaaab
-m 6 &M {[0-6][1-2][0-3][0-6][1-6][0-6]} 010010 010010
+expectError 30.1 & *** BADRPT
+expectMatch 30.2 N a?b* abb abb
+expectMatch 30.3 N a?b* bb bb
+expectMatch 30.4 & a*b aab aab
+expectMatch 30.5 & ^a*b aaaab aaaab
+expectMatch 30.6 &M {[0-6][1-2][0-3][0-6][1-6][0-6]} \
+ "010010" 010010
# temporary REG_BOSONLY kludge
-m 7 s abc abcd abc
-f 8 s abc xabcd
+expectMatch 30.7 s abc abcd abc
+expectNomatch 30.8 s abc xabcd
# back to normal stuff
-m 9 HLP {(?n)^(?![t#])\S+} "tk\n\n#\n#\nit0" it0
+expectMatch 30.9 HLP {(?n)^(?![t#])\S+} \
+ "tk\n\n#\n#\nit0" it0
+
+# Now for tests *not* written by Henry Spencer
-# flush any leftover complaints
-doing 0 "flush"
+namespace import -force ::tcltest::test
# Tests resulting from bugs reported by users
test reg-31.1 {[[:xdigit:]] behaves correctly when followed by [[:space:]]} {
@@ -1000,15 +948,13 @@ test reg-32.1 {canmatch functionality -- at end} testregexp {
set res [testregexp -xflags -- c $pat $line resvar]
lappend res $resvar
} {0 7}
-
test reg-32.2 {canmatch functionality -- at end} testregexp {
set pat {s%$}
set line "asd asd"
# can only match after the end of the string
- set res [testregexp -xflags -- c $pat $line resvar]
+ set res [testregexp -xflags -- c $pat $line resvar]
lappend res $resvar
} {0 7}
-
test reg-32.3 {canmatch functionality -- not last char} testregexp {
set pat {[^d]%$}
set line "asd asd"
@@ -1016,7 +962,6 @@ test reg-32.3 {canmatch functionality -- not last char} testregexp {
set res [testregexp -xflags -- c $pat $line resvar]
lappend res $resvar
} {0 7}
-
test reg-32.3.1 {canmatch functionality -- no match} testregexp {
set pat {\Zx}
set line "asd asd"
@@ -1024,56 +969,49 @@ test reg-32.3.1 {canmatch functionality -- no match} testregexp {
set res [testregexp -xflags -- c $pat $line resvar]
lappend res $resvar
} {0 -1}
-
-test reg-32.4 {canmatch functionality -- last char} {knownBug} {
+test reg-32.4 {canmatch functionality -- last char} {knownBug testregexp} {
set pat {.x}
set line "asd asd"
# can match the last char, if followed by x
set res [testregexp -xflags -- c $pat $line resvar]
lappend res $resvar
} {0 6}
-
-test reg-32.4.1 {canmatch functionality -- last char} {knownBug} {
+test reg-32.4.1 {canmatch functionality -- last char} {knownBug testregexp} {
set pat {.x$}
set line "asd asd"
# can match the last char, if followed by x
set res [testregexp -xflags -- c $pat $line resvar]
lappend res $resvar
} {0 6}
-
-test reg-32.5 {canmatch functionality -- last char} {knownBug} {
+test reg-32.5 {canmatch functionality -- last char} {knownBug testregexp} {
set pat {.[^d]x$}
set line "asd asd"
# can match the last char, if followed by not-d and x.
set res [testregexp -xflags -- c $pat $line resvar]
lappend res $resvar
} {0 6}
-
-test reg-32.6 {canmatch functionality -- last char} {knownBug} {
+test reg-32.6 {canmatch functionality -- last char} {knownBug testregexp} {
set pat {[^a]%[^\r\n]*$}
set line "asd asd"
# can match at the final d, if '%' follows
set res [testregexp -xflags -- c $pat $line resvar]
lappend res $resvar
} {0 6}
-
-test reg-32.7 {canmatch functionality -- last char} {knownBug} {
+test reg-32.7 {canmatch functionality -- last char} {knownBug testregexp} {
set pat {[^a]%$}
set line "asd asd"
# can match at the final d, if '%' follows
set res [testregexp -xflags -- c $pat $line resvar]
lappend res $resvar
} {0 6}
-
-test reg-32.8 {canmatch functionality -- last char} {knownBug} {
+test reg-32.8 {canmatch functionality -- last char} {knownBug testregexp} {
set pat {[^x]%$}
set line "asd asd"
# can match at the final d, if '%' follows
set res [testregexp -xflags -- c $pat $line resvar]
lappend res $resvar
} {0 6}
-
-test reg-32.9 {canmatch functionality -- more complex case} {knownBug} {
+test reg-32.9 {canmatch functionality -- more complex case} {knownBug testregexp} {
set pat {((\B\B|\Bh+line)[ \t]*|[^\B]%[^\r\n]*)$}
set line "asd asd"
# can match at the final d, if '%' follows
@@ -1086,60 +1024,51 @@ test reg-32.9 {canmatch functionality -- more complex case} {knownBug} {
test reg-33.1 {Bug 230589} {
regexp {[ ]*(^|[^%])%V} "*%V2" m s
} 1
-
test reg-33.2 {Bug 504785} {
regexp -inline {([^_.]*)([^.]*)\.(..)(.).*} bbcos_001_c01.q1la
} {bbcos_001_c01.q1la bbcos _001_c01 q1 l}
-
test reg-33.3 {Bug 505048} {
regexp {\A\s*[^<]*\s*<([^>]+)>} a<a>
} 1
-
test reg-33.4 {Bug 505048} {
regexp {\A\s*([^b]*)b} ab
} 1
-
test reg-33.5 {Bug 505048} {
regexp {\A\s*[^b]*(b)} ab
} 1
-
test reg-33.6 {Bug 505048} {
regexp {\A(\s*)[^b]*(b)} ab
} 1
-
test reg-33.7 {Bug 505048} {
regexp {\A\s*[^b]*b} ab
} 1
-
test reg-33.8 {Bug 505048} {
regexp -inline {\A\s*[^b]*b} ab
} ab
-
test reg-33.9 {Bug 505048} {
regexp -indices -inline {\A\s*[^b]*b} ab
} {{0 1}}
-
-test reg-33.10 {Bug 840258} {
+test reg-33.10 {Bug 840258} -body {
regsub {(^|\n)+\.*b} \n.b {} tmp
-} 1
-
-test reg-33.11 {Bug 840258} {
+} -cleanup {
+ unset tmp
+} -result 1
+test reg-33.11 {Bug 840258} -body {
regsub {(^|[\n\r]+)\.*\?<.*?(\n|\r)+} \
- "TQ\r\n.?<5000267>Test already stopped\r\n" {} tmp
-} 1
-
+ "TQ\r\n.?<5000267>Test already stopped\r\n" {} tmp
+} -cleanup {
+ unset tmp
+} -result 1
test reg-33.12 {Bug 1810264 - bad read} {
regexp {\3161573148} {\3161573148}
} 0
test reg-33.13 {Bug 1810264 - infinite loop} {
regexp {($|^)*} {x}
} 1
-test reg-33.14 {Bug 1810264 - super-expensive expression} {
- set start [clock seconds]
- regexp {(x{100}){100}$y} {x}
- set time [expr {[clock seconds] - $start}]
- expr {$time < 5 ? "ok" : "Complex RE took $time seconds - bad!"}
-} ok
+# Some environments have small default stack sizes. [Bug 1905562]
+test reg-33.14 {Bug 1810264 - super-expensive expression} nonPortable {
+ regexp {(x{200}){200}$y} {x}
+} 0
# cleanup
::tcltest::cleanupTests
diff --git a/tests/regexp.test b/tests/regexp.test
index 70ee47e..b20349f 100644
--- a/tests/regexp.test
+++ b/tests/regexp.test
@@ -16,6 +16,8 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
+testConstraint exec [llength [info commands exec]]
+
catch {unset foo}
test regexp-1.1 {basic regexp operation} {
regexp ab*c abbbc
@@ -42,6 +44,31 @@ test regexp-1.7 {regexp utf compliance} {
list [string compare $foo $bar] [regexp 4 $bar]
} {0 0}
+test regexp-1.8 {regexp ***= metasyntax} {
+ regexp -- "***=o" "aeiou"
+} 1
+test regexp-1.9 {regexp ***= metasyntax} {
+ set string "aeiou"
+ regexp -- "***=o" $string
+} 1
+test regexp-1.10 {regexp ***= metasyntax} {
+ set string "aeiou"
+ set re "***=o"
+ regexp -- $re $string
+} 1
+test regexp-1.11 {regexp ***= metasyntax} {
+ regexp -- "***=y" "aeiou"
+} 0
+test regexp-1.12 {regexp ***= metasyntax} {
+ set string "aeiou"
+ regexp -- "***=y" $string
+} 0
+test regexp-1.13 {regexp ***= metasyntax} {
+ set string "aeiou"
+ set re "***=y"
+ regexp -- $re $string
+} 0
+
test regexp-2.1 {getting substrings back from regexp} {
set foo {}
list [regexp ab*c abbbbc foo] $foo
@@ -218,7 +245,7 @@ test regexp-6.8 {regexp errors} {
} {1 {couldn't set variable "f1(f2)"}}
test regexp-6.9 {regexp errors, -start bad int check} {
list [catch {regexp -start bogus {^$} {}} msg] $msg
-} {1 {expected integer but got "bogus"}}
+} {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}}
test regexp-7.1 {basic regsub operation} {
list [regsub aa+ xaxaaaxaa 111&222 foo] $foo
@@ -375,7 +402,7 @@ test regexp-11.7 {regsub errors} {
} {1 {couldn't set variable "f1(f2)"}}
test regexp-11.8 {regsub errors, -start bad int check} {
list [catch {regsub -start bogus pattern string rep var} msg] $msg
-} {1 {expected integer but got "bogus"}}
+} {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}}
test regexp-11.9 {regsub without final variable name returns value} {
regsub b abaca X
} {aXaca}
@@ -430,8 +457,6 @@ test regexp-14.2 {CompileRegexp: regexp cache, different flags} {
append x *a
regexp -nocase $x bbba
} 1
-
-testConstraint exec [llength [info commands exec]]
test regexp-14.3 {CompileRegexp: regexp cache, empty regexp and empty cache} -constraints {
exec
} -setup {
@@ -465,6 +490,20 @@ test regexp-15.5 {regexp -start, over end of string} {
test regexp-15.6 {regexp -start, loss of ^$ behavior} {
list [regexp -start 2 {^$} {}]
} {0}
+test regexp-15.7 {regexp -start, double option} {
+ regexp -start 2 -start 0 a abc
+} 1
+test regexp-15.8 {regexp -start, double option} {
+ regexp -start 0 -start 2 a abc
+} 0
+test regexp-15.9 {regexp -start, end relative index} {
+ catch {unset x}
+ list [regexp -start end {\d} 1abc2de3 x] [info exists x]
+} {0 0}
+test regexp-15.10 {regexp -start, end relative index} {
+ catch {unset x}
+ list [regexp -start end-1 {\d} 1abc2de3 x] [info exists x] $x
+} {1 1 3}
test regexp-16.1 {regsub -start} {
catch {unset x}
@@ -483,6 +522,18 @@ test regexp-16.4 {regsub -start, \A behavior} {
lappend out [regsub -start 0 -all {\A(\w)} {abcde} {/\1} x] $x
lappend out [regsub -start 2 -all {\A(\w)} {abcde} {/\1} x] $x
} {5 /a/b/c/d/e 3 ab/c/d/e}
+test regexp-16.5 {regsub -start, double option} {
+ list [regsub -start 2 -start 0 a abc c x] $x
+} {1 cbc}
+test regexp-16.6 {regsub -start, double option} {
+ list [regsub -start 0 -start 2 a abc c x] $x
+} {0 abc}
+test regexp-16.7 {regexp -start, end relative index} {
+ list [regsub -start end a aaa b x] $x
+} {0 aaa}
+test regexp-16.8 {regexp -start, end relative index} {
+ list [regsub -start end-1 a aaa b x] $x
+} {1 aab}
test regexp-17.1 {regexp -inline} {
regexp -inline b ababa
@@ -569,7 +620,7 @@ test regexp-20.1 {regsub shared object shimmering} {
set c abcdefghijklmnopqurstuvwxyz0123456789
regsub $a $c $b d
list $d [string length $d] [string bytelength $d]
-} [list abcdefghijklmnopqurstuvwxyz0123456789 37 37]
+} {abcdefghijklmnopqurstuvwxyz0123456789 37 37}
test regexp-20.2 {regsub shared object shimmering with -about} {
eval regexp -about abc
} {0 {}}
@@ -577,60 +628,291 @@ test regexp-20.2 {regsub shared object shimmering with -about} {
test regexp-21.1 {regsub works with empty string} {
regsub -- ^ {} foo
} {foo}
-
test regexp-21.2 {regsub works with empty string} {
regsub -- \$ {} foo
} {foo}
-
test regexp-21.3 {regsub works with empty string offset} {
regsub -start 0 -- ^ {} foo
} {foo}
-
test regexp-21.4 {regsub works with empty string offset} {
regsub -start 0 -- \$ {} foo
} {foo}
-
test regexp-21.5 {regsub works with empty string offset} {
regsub -start 3 -- \$ {123} foo
} {123foo}
-
test regexp-21.6 {regexp works with empty string} {
regexp -- ^ {}
} {1}
-
test regexp-21.7 {regexp works with empty string} {
regexp -start 0 -- ^ {}
} {1}
-
test regexp-21.8 {regexp works with empty string offset} {
regexp -start 3 -- ^ {123}
} {0}
-
test regexp-21.9 {regexp works with empty string offset} {
regexp -start 3 -- \$ {123}
} {1}
-
test regexp-21.10 {multiple matches handle newlines} {
regsub -all -lineanchor -- {^#[^\n]*\n} "#one\n#two\n#three\n" foo\n
} "foo\nfoo\nfoo\n"
-
test regexp-21.11 {multiple matches handle newlines} {
regsub -all -line -- ^ "a\nb\nc" \#
} "\#a\n\#b\n\#c"
-
test regexp-21.12 {multiple matches handle newlines} {
regsub -all -line -- ^ "\n\n" \#
} "\#\n\#\n\#"
-
test regexp-21.13 {multiple matches handle newlines} {
regexp -all -inline -indices -line -- ^ "a\nb\nc"
} {{0 -1} {2 1} {4 3}}
-
test regexp-22.1 {Bug 1810038} {
regexp ($|^X)* {}
} 1
+test regexp-22.2 {regexp compile and backrefs, Bug 1857126} {
+ regexp -- {([bc])\1} bb
+} 1
+test regexp-23.1 {regexp -all and -line} {
+ set string ""
+ list \
+ [regexp -all -inline -indices -line -- {^} $string] \
+ [regexp -all -inline -indices -line -- {^$} $string] \
+ [regexp -all -inline -indices -line -- {$} $string]
+} {{{0 -1}} {{0 -1}} {{0 -1}}}
+test regexp-23.2 {regexp -all and -line} {
+ set string "\n"
+ list \
+ [regexp -all -inline -indices -line -- {^} $string] \
+ [regexp -all -inline -indices -line -- {^$} $string] \
+ [regexp -all -inline -indices -line -- {$} $string]
+} {{{0 -1}} {{0 -1}} {{0 -1}}}
+test regexp-23.3 {regexp -all and -line} {
+ set string "\n\n"
+ list \
+ [regexp -all -inline -indices -line -- {^} $string] \
+ [regexp -all -inline -indices -line -- {^$} $string] \
+ [regexp -all -inline -indices -line -- {$} $string]
+} {{{0 -1} {1 0}} {{0 -1} {1 0}} {{0 -1} {1 0}}}
+test regexp-23.4 {regexp -all and -line} {
+ set string "a"
+ list \
+ [regexp -all -inline -indices -line -- {^} $string] \
+ [regexp -all -inline -indices -line -- {^.*$} $string] \
+ [regexp -all -inline -indices -line -- {$} $string]
+} {{{0 -1}} {{0 0}} {{1 0}}}
+test regexp-23.5 {regexp -all and -line} {knownBug} {
+ set string "a\n"
+ list \
+ [regexp -all -inline -indices -line -- {^} $string] \
+ [regexp -all -inline -indices -line -- {^.*$} $string] \
+ [regexp -all -inline -indices -line -- {$} $string]
+} {{{0 -1} {2 1}} {{0 0} {2 1}} {{1 0} {2 1}}}
+test regexp-23.6 {regexp -all and -line} {
+ set string "\na"
+ list \
+ [regexp -all -inline -indices -line -- {^} $string] \
+ [regexp -all -inline -indices -line -- {^.*$} $string] \
+ [regexp -all -inline -indices -line -- {$} $string]
+} {{{0 -1} {1 0}} {{0 -1} {1 1}} {{0 -1} {2 1}}}
+test regexp-23.7 {regexp -all and -line} {knownBug} {
+ set string "ab\n"
+ list \
+ [regexp -all -inline -indices -line -- {^} $string] \
+ [regexp -all -inline -indices -line -- {^.*$} $string] \
+ [regexp -all -inline -indices -line -- {$} $string]
+} {{{0 -1} {3 2}} {{0 1} {3 2}} {{2 1} {3 2}}}
+test regexp-23.8 {regexp -all and -line} {
+ set string "a\nb"
+ list \
+ [regexp -all -inline -indices -line -- {^} $string] \
+ [regexp -all -inline -indices -line -- {^.*$} $string] \
+ [regexp -all -inline -indices -line -- {$} $string]
+} {{{0 -1} {2 1}} {{0 0} {2 2}} {{1 0} {3 2}}}
+test regexp-23.9 {regexp -all and -line} {knownBug} {
+ set string "a\nb\n"
+ list \
+ [regexp -all -inline -indices -line -- {^} $string] \
+ [regexp -all -inline -indices -line -- {^.*$} $string] \
+ [regexp -all -inline -indices -line -- {$} $string]
+} {{{0 -1} {2 1} {4 3}} {{0 0} {2 2} {4 3}} {{1 0} {3 2} {4 3}}}
+test regexp-23.10 {regexp -all and -line} {
+ set string "a\nb\nc"
+ list \
+ [regexp -all -inline -indices -line -- {^} $string] \
+ [regexp -all -inline -indices -line -- {^.*$} $string] \
+ [regexp -all -inline -indices -line -- {$} $string]
+} {{{0 -1} {2 1} {4 3}} {{0 0} {2 2} {4 4}} {{1 0} {3 2} {5 4}}}
+test regexp-23.11 {regexp -all and -line} {
+ regexp -all -inline -indices -line -- {b} "abb\nb"
+} {{1 1} {2 2} {4 4}}
+
+test regexp-24.1 {regsub -all and -line} {
+ foreach {v1 v2 v3} {{} {} {}} {}
+ set string ""
+ list \
+ [regsub -line -all {^} $string {<&>} v1] $v1 \
+ [regsub -line -all {^$} $string {<&>} v2] $v2 \
+ [regsub -line -all {$} $string {<&>} v3] $v3
+} {1 <> 1 <> 1 <>}
+test regexp-24.2 {regsub -all and -line} {
+ foreach {v1 v2 v3} {{} {} {}} {}
+ set string "\n"
+ list \
+ [regsub -line -all {^} $string {<&>} v1] $v1 \
+ [regsub -line -all {^$} $string {<&>} v2] $v2 \
+ [regsub -line -all {$} $string {<&>} v3] $v3
+} "2 {<>\n<>} 2 {<>\n<>} 2 {<>\n<>}"
+test regexp-24.3 {regsub -all and -line} {
+ foreach {v1 v2 v3} {{} {} {}} {}
+ set string "\n\n"
+ list \
+ [regsub -line -all {^} $string {<&>} v1] $v1 \
+ [regsub -line -all {^$} $string {<&>} v2] $v2 \
+ [regsub -line -all {$} $string {<&>} v3] $v3
+} "3 {<>\n<>\n<>} 3 {<>\n<>\n<>} 3 {<>\n<>\n<>}"
+test regexp-24.4 {regsub -all and -line} {
+ foreach {v1 v2 v3} {{} {} {}} {}
+ set string "a"
+ list \
+ [regsub -line -all {^} $string {<&>} v1] $v1 \
+ [regsub -line -all {^.*$} $string {<&>} v2] $v2 \
+ [regsub -line -all {$} $string {<&>} v3] $v3
+} {1 <>a 1 <a> 1 a<>}
+test regexp-24.5 {regsub -all and -line} {
+ foreach {v1 v2 v3} {{} {} {}} {}
+ set string "a\n"
+ list \
+ [regsub -line -all {^} $string {<&>} v1] $v1 \
+ [regsub -line -all {^.*$} $string {<&>} v2] $v2 \
+ [regsub -line -all {$} $string {<&>} v3] $v3
+} "2 {<>a\n<>} 2 {<a>\n<>} 2 {a<>\n<>}"
+test regexp-24.6 {regsub -all and -line} {
+ foreach {v1 v2 v3} {{} {} {}} {}
+ set string "\na"
+ list \
+ [regsub -line -all {^} $string {<&>} v1] $v1 \
+ [regsub -line -all {^.*$} $string {<&>} v2] $v2 \
+ [regsub -line -all {$} $string {<&>} v3] $v3
+} "2 {<>\n<>a} 2 {<>\n<a>} 2 {<>\na<>}"
+test regexp-24.7 {regsub -all and -line} {
+ foreach {v1 v2 v3} {{} {} {}} {}
+ set string "ab\n"
+ list \
+ [regsub -line -all {^} $string {<&>} v1] $v1 \
+ [regsub -line -all {^.*$} $string {<&>} v2] $v2 \
+ [regsub -line -all {$} $string {<&>} v3] $v3
+} "2 {<>ab\n<>} 2 {<ab>\n<>} 2 {ab<>\n<>}"
+test regexp-24.8 {regsub -all and -line} {
+ foreach {v1 v2 v3} {{} {} {}} {}
+ set string "a\nb"
+ list \
+ [regsub -line -all {^} $string {<&>} v1] $v1 \
+ [regsub -line -all {^.*$} $string {<&>} v2] $v2 \
+ [regsub -line -all {$} $string {<&>} v3] $v3
+} "2 {<>a\n<>b} 2 {<a>\n<b>} 2 {a<>\nb<>}"
+test regexp-24.9 {regsub -all and -line} {
+ foreach {v1 v2 v3} {{} {} {}} {}
+ set string "a\nb\n"
+ list \
+ [regsub -line -all {^} $string {<&>} v1] $v1 \
+ [regsub -line -all {^.*$} $string {<&>} v2] $v2 \
+ [regsub -line -all {$} $string {<&>} v3] $v3
+} "3 {<>a\n<>b\n<>} 3 {<a>\n<b>\n<>} 3 {a<>\nb<>\n<>}"
+test regexp-24.10 {regsub -all and -line} {
+ foreach {v1 v2 v3} {{} {} {}} {}
+ set string "a\nb\nc"
+ list \
+ [regsub -line -all {^} $string {<&>} v1] $v1 \
+ [regsub -line -all {^.*$} $string {<&>} v2] $v2 \
+ [regsub -line -all {$} $string {<&>} v3] $v3
+} "3 {<>a\n<>b\n<>c} 3 {<a>\n<b>\n<c>} 3 {a<>\nb<>\nc<>}"
+test regexp-24.11 {regsub -all and -line} {
+ regsub -line -all {b} "abb\nb" {<&>}
+} "a<b><b>\n<b>"
+
+test regexp-25.1 {regexp without -line option} {
+ set foo ""
+ list [regexp {a.*b} "dabc\naxyb\n" foo] $foo
+} "1 {abc\naxyb}"
+test regexp-25.2 {regexp without -line option} {
+ set foo ""
+ list [regexp {^a.*b$} "dabc\naxyb\n" foo] $foo
+} {0 {}}
+test regexp-25.3 {regexp with -line option} {
+ set foo ""
+ list [regexp -line {^a.*b$} "dabc\naxyb\n" foo] $foo
+} {1 axyb}
+test regexp-25.4 {regexp with -line option} {
+ set foo ""
+ list [regexp -line {^a.*b$} "dabc\naxyb\nxb" foo] $foo
+} {1 axyb}
+test regexp-25.5 {regexp without -line option} {
+ set foo ""
+ list [regexp {^a.*b$} "dabc\naxyb\nxb" foo] $foo
+} {0 {}}
+test regexp-25.6 {regexp without -line option} {
+ set foo ""
+ list [regexp {a.*b$} "dabc\naxyb\nxb" foo] $foo
+} "1 {abc\naxyb\nxb}"
+test regexp-25.7 {regexp with -lineanchor option} {
+ set foo ""
+ list [regexp -lineanchor {^a.*b$} "dabc\naxyb\nxb" foo] $foo
+} "1 {axyb\nxb}"
+test regexp-25.8 {regexp with -lineanchor and -linestop option} {
+ set foo ""
+ list [regexp -lineanchor -linestop {^a.*b$} "dabc\naxyb\nxb" foo] $foo
+} {1 axyb}
+test regexp-25.9 {regexp with -linestop option} {
+ set foo ""
+ list [regexp -linestop {a.*b} "ab\naxyb\nxb" foo] $foo
+} {1 ab}
+
+test regexp-26.1 {matches start of line 1 time} {
+ regexp -all -inline -- {^a+} "aab\naaa"
+} {aa}
+test regexp-26.2 {matches start of line(s) 2 times} {
+ regexp -all -inline -line -- {^a+} "aab\naaa"
+} {aa aaa}
+test regexp-26.3 {effect of -line -all and -start} {
+ list \
+ [regexp -all -inline -line -start 0 -- {^a+} "aab\naaa"] \
+ [regexp -all -inline -line -start 1 -- {^a+} "aab\naaa"] \
+ [regexp -all -inline -line -start 3 -- {^a+} "aab\naaa"] \
+ [regexp -all -inline -line -start 4 -- {^a+} "aab\naaa"] \
+} {{aa aaa} aaa aaa aaa}
+test regexp-26.5 {match length 0, match length 1} {
+ regexp -all -inline -line -- {^b*} "a\nb"
+} {{} b}
+test regexp-26.6 {non reporting capture group} {
+ regexp -all -inline -line -- {^(?:a+|b)} "aab\naaa"
+} {aa aaa}
+test regexp-26.7 {Tcl bug 2826551: -line sensitive regexp and -start} {
+ set match1 {}
+ set match2 {}
+ list \
+ [regexp -start 0 -indices -line {^a} "\nab" match1] $match1 \
+ [regexp -start 1 -indices -line {^a} "\nab" match2] $match2
+} {1 {1 1} 1 {1 1}}
+test regexp-26.8 {Tcl bug 2826551: diff regexp with -line option} {
+ set data "@1\n2\n+3\n@4\n-5\n+6\n7\n@8\n9\n"
+ regexp -all -inline -line {^@.*\n(?:[^@].*\n?)*} $data
+} "{@1\n2\n+3\n} {@4\n-5\n+6\n7\n} {@8\n9\n}"
+test regexp-26.9 {Tcl bug 2826551: diff regexp with embedded -line option} {
+ set data "@1\n2\n+3\n@4\n-5\n+6\n7\n@8\n9\n"
+ regexp -all -inline {(?n)^@.*\n(?:[^@].*\n?)*} $data
+} "{@1\n2\n+3\n} {@4\n-5\n+6\n7\n} {@8\n9\n}"
+test regexp-26.10 {regexp with -line option} {
+ regexp -all -inline -line -- {a*} "a\n"
+} {a {}}
+test regexp-26.11 {regexp without -line option} {
+ regexp -all -inline -- {a*} "a\n"
+} {a {}}
+test regexp-26.12 {regexp with -line option} {
+ regexp -all -inline -line -- {a*} "b\n"
+} {{} {}}
+test regexp-26.13 {regexp without -line option} {
+ regexp -all -inline -- {a*} "b\n"
+} {{} {}}
# cleanup
::tcltest::cleanupTests
diff --git a/tests/regexpComp.test b/tests/regexpComp.test
index c8ad004..e927ca2 100644
--- a/tests/regexpComp.test
+++ b/tests/regexpComp.test
@@ -41,7 +41,7 @@ test regexpComp-1.2 {basic regexp operation} {
}
} 1
test regexpComp-1.3 {basic regexp operation} {
- evalInProc {
+ evalInProc {
regexp ab*c ab
}
} 0
@@ -67,6 +67,64 @@ test regexpComp-1.7 {regexp utf compliance} {
}
} {0 0}
+test regexpComp-1.8 {regexp ***= metasyntax} {
+ evalInProc {
+ regexp -- "***=o" "aeiou"
+ }
+} 1
+test regexpComp-1.9 {regexp ***= metasyntax} {
+ evalInProc {
+ set string "aeiou"
+ regexp -- "***=o" $string
+ }
+} 1
+test regexpComp-1.10 {regexp ***= metasyntax} {
+ evalInProc {
+ set string "aeiou"
+ set re "***=o"
+ regexp -- $re $string
+ }
+} 1
+test regexpComp-1.11 {regexp ***= metasyntax} {
+ evalInProc {
+ regexp -- "***=y" "aeiou"
+ }
+} 0
+test regexpComp-1.12 {regexp ***= metasyntax} {
+ evalInProc {
+ set string "aeiou"
+ regexp -- "***=y" $string
+ }
+} 0
+test regexpComp-1.13 {regexp ***= metasyntax} {
+ evalInProc {
+ set string "aeiou"
+ set re "***=y"
+ regexp -- $re $string
+ }
+} 0
+test regexpComp-1.14 {regexp ***= metasyntax} {
+ evalInProc {
+ set string "aeiou"
+ set re "***=e*o"
+ regexp -- $re $string
+ }
+} 0
+test regexpComp-1.15 {regexp ***= metasyntax} {
+ evalInProc {
+ set string "ae*ou"
+ set re "***=e*o"
+ regexp -- $re $string
+ }
+} 1
+test regexpComp-1.16 {regexp ***= metasyntax} {
+ evalInProc {
+ set string {ae*[o]?ua}
+ set re {***=e*[o]?u}
+ regexp -- $re $string
+ }
+} 1
+
test regexpComp-2.1 {getting substrings back from regexp} {
evalInProc {
set foo {}
@@ -299,7 +357,7 @@ test regexpComp-6.9 {regexp errors, -start bad int check} {
evalInProc {
list [catch {regexp -start bogus {^$} {}} msg] $msg
}
-} {1 {expected integer but got "bogus"}}
+} {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}}
test regexpComp-7.1 {basic regsub operation} {
evalInProc {
@@ -540,7 +598,7 @@ test regexpComp-11.8 {regsub errors, -start bad int check} {
evalInProc {
list [catch {regsub -start bogus pattern string rep var} msg] $msg
}
-} {1 {expected integer but got "bogus"}}
+} {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}}
# This test crashes on the Mac unless you increase the Stack Space to about 1
# Meg. This is probably bigger than most users want...
@@ -800,6 +858,18 @@ test regexpComp-21.11 {regexp command compiling tests} {
}
} {0 {}}
+test regexpComp-22.0.1 {Bug 1810038} {
+ evalInProc {
+ regexp ($|^X)* {}
+ }
+} 1
+
+test regexpComp-22.0.2 {regexp compile and backrefs, Bug 1857126} {
+ evalInProc {
+ regexp -- {([bc])\1} bb
+ }
+} 1
+
set i 0
foreach {str exp result} {
foo ^foo 1
@@ -820,6 +890,98 @@ foreach {str exp result} {
[subst {evalInProc {set a "$str"; regexp {$exp} \$a}}] $result
}
+set i 0
+foreach {str exp result} {
+ foo ^foo 1
+ foobar ^foobar$ 1
+ foobar bar$ 1
+ foobar ^$ 0
+ "" ^$ 1
+ anything $ 1
+ anything ^.*$ 1
+ anything ^.*a$ 0
+ anything ^.*a.*$ 1
+ anything ^.*.*$ 1
+ anything ^.*..*$ 1
+ anything ^.*b$ 0
+ anything ^a.*$ 1
+} {
+ test regexpComp-23.[incr i] {regexp command compiling tests INST_REGEXP} \
+ [subst {evalInProc {set a "$str"; set re "$exp"; regexp \$re \$a}}] $result
+}
+
+test regexpComp-24.1 {regexp command compiling tests} {
+ evalInProc {
+ set re foo
+ regexp -nocase $re bar
+ }
+} 0
+test regexpComp-24.2 {regexp command compiling tests} {
+ evalInProc {
+ set re {^foo$}
+ regexp $re dogfood
+ }
+} 0
+test regexpComp-24.3 {regexp command compiling tests} {
+ evalInProc {
+ set a foo
+ set re {^foo$}
+ regexp $re $a
+ }
+} 1
+test regexpComp-24.4 {regexp command compiling tests} {
+ evalInProc {
+ set re foo
+ regexp $re dogfood
+ }
+} 1
+test regexpComp-24.5 {regexp command compiling tests} {
+ evalInProc {
+ set re FOO
+ regexp -nocase $re dogfod
+ }
+} 0
+test regexpComp-24.6 {regexp command compiling tests} {
+ evalInProc {
+ set re foo
+ regexp -n $re dogfoOd
+ }
+} 1
+test regexpComp-24.7 {regexp command compiling tests} {
+ evalInProc {
+ set re FoO
+ regexp -no -- $re dogfood
+ }
+} 1
+test regexpComp-24.8 {regexp command compiling tests} {
+ evalInProc {
+ set re foo
+ regexp -- $re dogfod
+ }
+} 0
+test regexpComp-24.9 {regexp command compiling tests} {
+ evalInProc {
+ set re "("
+ list [catch {regexp -- $re dogfod} msg] $msg
+ }
+} {1 {couldn't compile regular expression pattern: parentheses () not balanced}}
+test regexpComp-24.10 {regexp command compiling tests} {
+ # Bug 1902436 - last * escaped
+ evalInProc {
+ set text {this is *bold* !}
+ set re {\*bold\*}
+ regexp -- $re $text
+ }
+} 1
+test regexpComp-24.11 {regexp command compiling tests} {
+ # Bug 1902436 - last * escaped
+ evalInProc {
+ set text {this is *bold* !}
+ set re {\*bold\*.*!}
+ regexp -- $re $text
+ }
+} 1
+
# cleanup
::tcltest::cleanupTests
return
diff --git a/tests/registry.test b/tests/registry.test
index 85b4f42..2a38f2a 100644
--- a/tests/registry.test
+++ b/tests/registry.test
@@ -15,137 +15,138 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-if {$tcl_platform(platform) == "windows"} {
- if [catch {
- set lib [lindex [glob -directory [file join [pwd] [file dirname \
- [info nameofexecutable]]] tclreg*.dll] 0]
- load $lib registry
- }] {
- puts "Unable to find the registry package. Skipping registry tests."
- return
+testConstraint reg 0
+if {[testConstraint win]} {
+ catch {
+ # Is the registry extension already static to this shell?
+ if [catch {load {} Registry; set ::reglib {}}] {
+ # try the location given to use on the commandline to tcltest
+ ::tcltest::loadTestedCommands
+ load $::reglib Registry
+ }
+ testConstraint reg 1
}
}
# determine the current locale
-testConstraint english [expr {[llength [info commands testlocale]]
- && [string equal [testlocale all ""] "English_United States.1252"]
+testConstraint english [expr {
+ [llength [info commands testlocale]]
+ && [string match "English*" [testlocale all ""]]
}]
-set hostname [info hostname]
-
-test registry-1.1 {argument parsing for registry command} {pcOnly} {
+test registry-1.1 {argument parsing for registry command} {win reg} {
list [catch {registry} msg] $msg
} {1 {wrong # args: should be "registry option ?arg arg ...?"}}
-test registry-1.2 {argument parsing for registry command} {pcOnly} {
+test registry-1.2 {argument parsing for registry command} {win reg} {
list [catch {registry foo} msg] $msg
} {1 {bad option "foo": must be broadcast, delete, get, keys, set, type, or values}}
-test registry-1.3 {argument parsing for registry command} {pcOnly} {
+test registry-1.3 {argument parsing for registry command} {win reg} {
list [catch {registry d} msg] $msg
} {1 {wrong # args: should be "registry delete keyName ?valueName?"}}
-test registry-1.4 {argument parsing for registry command} {pcOnly} {
+test registry-1.4 {argument parsing for registry command} {win reg} {
list [catch {registry delete} msg] $msg
} {1 {wrong # args: should be "registry delete keyName ?valueName?"}}
-test registry-1.5 {argument parsing for registry command} {pcOnly} {
+test registry-1.5 {argument parsing for registry command} {win reg} {
list [catch {registry delete foo bar baz} msg] $msg
} {1 {wrong # args: should be "registry delete keyName ?valueName?"}}
-test registry-1.6 {argument parsing for registry command} {pcOnly} {
+test registry-1.6 {argument parsing for registry command} {win reg} {
list [catch {registry g} msg] $msg
} {1 {wrong # args: should be "registry get keyName valueName"}}
-test registry-1.7 {argument parsing for registry command} {pcOnly} {
+test registry-1.7 {argument parsing for registry command} {win reg} {
list [catch {registry get} msg] $msg
} {1 {wrong # args: should be "registry get keyName valueName"}}
-test registry-1.8 {argument parsing for registry command} {pcOnly} {
+test registry-1.8 {argument parsing for registry command} {win reg} {
list [catch {registry get foo} msg] $msg
} {1 {wrong # args: should be "registry get keyName valueName"}}
-test registry-1.9 {argument parsing for registry command} {pcOnly} {
+test registry-1.9 {argument parsing for registry command} {win reg} {
list [catch {registry get foo bar baz} msg] $msg
} {1 {wrong # args: should be "registry get keyName valueName"}}
-test registry-1.10 {argument parsing for registry command} {pcOnly} {
+test registry-1.10 {argument parsing for registry command} {win reg} {
list [catch {registry k} msg] $msg
} {1 {wrong # args: should be "registry keys keyName ?pattern?"}}
-test registry-1.11 {argument parsing for registry command} {pcOnly} {
+test registry-1.11 {argument parsing for registry command} {win reg} {
list [catch {registry keys} msg] $msg
} {1 {wrong # args: should be "registry keys keyName ?pattern?"}}
-test registry-1.12 {argument parsing for registry command} {pcOnly} {
+test registry-1.12 {argument parsing for registry command} {win reg} {
list [catch {registry keys foo bar baz} msg] $msg
} {1 {wrong # args: should be "registry keys keyName ?pattern?"}}
-test registry-1.13 {argument parsing for registry command} {pcOnly} {
+test registry-1.13 {argument parsing for registry command} {win reg} {
list [catch {registry s} msg] $msg
} {1 {wrong # args: should be "registry set keyName ?valueName data ?type??"}}
-test registry-1.14 {argument parsing for registry command} {pcOnly} {
+test registry-1.14 {argument parsing for registry command} {win reg} {
list [catch {registry set} msg] $msg
} {1 {wrong # args: should be "registry set keyName ?valueName data ?type??"}}
-test registry-1.15 {argument parsing for registry command} {pcOnly} {
+test registry-1.15 {argument parsing for registry command} {win reg} {
list [catch {registry set foo bar} msg] $msg
} {1 {wrong # args: should be "registry set keyName ?valueName data ?type??"}}
-test registry-1.16 {argument parsing for registry command} {pcOnly} {
+test registry-1.16 {argument parsing for registry command} {win reg} {
list [catch {registry set foo bar baz blat gorp} msg] $msg
} {1 {wrong # args: should be "registry set keyName ?valueName data ?type??"}}
-test registry-1.17 {argument parsing for registry command} {pcOnly} {
+test registry-1.17 {argument parsing for registry command} {win reg} {
list [catch {registry t} msg] $msg
} {1 {wrong # args: should be "registry type keyName valueName"}}
-test registry-1.18 {argument parsing for registry command} {pcOnly} {
+test registry-1.18 {argument parsing for registry command} {win reg} {
list [catch {registry type} msg] $msg
} {1 {wrong # args: should be "registry type keyName valueName"}}
-test registry-1.19 {argument parsing for registry command} {pcOnly} {
+test registry-1.19 {argument parsing for registry command} {win reg} {
list [catch {registry type foo} msg] $msg
} {1 {wrong # args: should be "registry type keyName valueName"}}
-test registry-1.20 {argument parsing for registry command} {pcOnly} {
+test registry-1.20 {argument parsing for registry command} {win reg} {
list [catch {registry type foo bar baz} msg] $msg
} {1 {wrong # args: should be "registry type keyName valueName"}}
-test registry-1.21 {argument parsing for registry command} {pcOnly} {
+test registry-1.21 {argument parsing for registry command} {win reg} {
list [catch {registry v} msg] $msg
} {1 {wrong # args: should be "registry values keyName ?pattern?"}}
-test registry-1.22 {argument parsing for registry command} {pcOnly} {
+test registry-1.22 {argument parsing for registry command} {win reg} {
list [catch {registry values} msg] $msg
} {1 {wrong # args: should be "registry values keyName ?pattern?"}}
-test registry-1.23 {argument parsing for registry command} {pcOnly} {
+test registry-1.23 {argument parsing for registry command} {win reg} {
list [catch {registry values foo bar baz} msg] $msg
} {1 {wrong # args: should be "registry values keyName ?pattern?"}}
-test registry-2.1 {DeleteKey: bad key} {pcOnly} {
+test registry-2.1 {DeleteKey: bad key} {win reg} {
list [catch {registry delete foo} msg] $msg
} {1 {bad root name "foo": must be HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, or HKEY_DYN_DATA}}
-test registry-2.2 {DeleteKey: bad key} {pcOnly} {
- list [catch {registry delete HKEY_CLASSES_ROOT} msg] $msg
+test registry-2.2 {DeleteKey: bad key} {win reg} {
+ list [catch {registry delete HKEY_CURRENT_USER} msg] $msg
} {1 {bad key: cannot delete root keys}}
-test registry-2.3 {DeleteKey: bad key} {pcOnly} {
- list [catch {registry delete HKEY_CLASSES_ROOT\\} msg] $msg
+test registry-2.3 {DeleteKey: bad key} {win reg} {
+ list [catch {registry delete HKEY_CURRENT_USER\\} msg] $msg
} {1 {bad key: cannot delete root keys}}
-test registry-2.4 {DeleteKey: subkey at root level} {pcOnly} {
+test registry-2.4 {DeleteKey: subkey at root level} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar
registry delete HKEY_CURRENT_USER\\TclFoobar
registry keys HKEY_CURRENT_USER TclFoobar
} {}
-test registry-2.5 {DeleteKey: subkey below root level} {pcOnly} {
+test registry-2.5 {DeleteKey: subkey below root level} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar\\test
registry delete HKEY_CURRENT_USER\\TclFoobar\\test
set result [registry keys HKEY_CURRENT_USER TclFoobar\\test]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} {}
-test registry-2.6 {DeleteKey: recursive delete} {pcOnly} {
+test registry-2.6 {DeleteKey: recursive delete} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar\\test1
registry set HKEY_CURRENT_USER\\TclFoobar\\test2\\test3
registry delete HKEY_CURRENT_USER\\TclFoobar
set result [registry keys HKEY_CURRENT_USER TclFoobar]
set result
} {}
-test registry-2.7 {DeleteKey: trailing backslashes} {pcOnly english} {
+test registry-2.7 {DeleteKey: trailing backslashes} {win reg english} {
registry set HKEY_CURRENT_USER\\TclFoobar\\baz
list [catch {registry delete HKEY_CURRENT_USER\\TclFoobar\\} msg] $msg
} {1 {unable to delete key: The configuration registry key is invalid.}}
-test registry-2.8 {DeleteKey: failure} {pcOnly} {
+test registry-2.8 {DeleteKey: failure} {win reg} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry delete HKEY_CURRENT_USER\\TclFoobar
} {}
-test registry-2.9 {DeleteKey: unicode} {pcOnly} {
+test registry-2.9 {DeleteKey: unicode} {win reg} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry set HKEY_CURRENT_USER\\TclFoobar\\test\u00c7bar\\a
registry set HKEY_CURRENT_USER\\TclFoobar\\test\u00c7bar\\b
@@ -155,7 +156,7 @@ test registry-2.9 {DeleteKey: unicode} {pcOnly} {
set result
} {}
-test registry-3.1 {DeleteValue} {pcOnly} {
+test registry-3.1 {DeleteValue} {win reg} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry set HKEY_CURRENT_USER\\TclFoobar\\baz test1 blort
registry set HKEY_CURRENT_USER\\TclFoobar\\baz test2 blat
@@ -164,18 +165,18 @@ test registry-3.1 {DeleteValue} {pcOnly} {
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} test2
-test registry-3.2 {DeleteValue: bad key} {pcOnly english} {
+test registry-3.2 {DeleteValue: bad key} {win reg english} {
registry delete HKEY_CURRENT_USER\\TclFoobar
list [catch {registry delete HKEY_CURRENT_USER\\TclFoobar test} msg] $msg
} {1 {unable to open key: The system cannot find the file specified.}}
-test registry-3.3 {DeleteValue: bad value} {pcOnly english} {
+test registry-3.3 {DeleteValue: bad value} {win reg english} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry set HKEY_CURRENT_USER\\TclFoobar\\baz test2 blort
set result [list [catch {registry delete HKEY_CURRENT_USER\\TclFoobar test1} msg] $msg]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} {1 {unable to delete value "test1" from key "HKEY_CURRENT_USER\TclFoobar": The system cannot find the file specified.}}
-test registry-3.4 {DeleteValue: Unicode} {pcOnly} {
+test registry-3.4 {DeleteValue: Unicode} {win reg} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry set HKEY_CURRENT_USER\\TclFoobar\\\u00c7baz \u00c7test1 blort
registry set HKEY_CURRENT_USER\\TclFoobar\\\u00c7baz test2 blat
@@ -185,31 +186,32 @@ test registry-3.4 {DeleteValue: Unicode} {pcOnly} {
set result
} test2
-test registry-4.1 {GetKeyNames: bad key} {pcOnly english} {
+test registry-4.1 {GetKeyNames: bad key} {win reg english} {
registry delete HKEY_CURRENT_USER\\TclFoobar
list [catch {registry keys HKEY_CURRENT_USER\\TclFoobar} msg] $msg
} {1 {unable to open key: The system cannot find the file specified.}}
-test registry-4.2 {GetKeyNames} {pcOnly} {
+test registry-4.2 {GetKeyNames} {win reg} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry set HKEY_CURRENT_USER\\TclFoobar\\baz
set result [registry keys HKEY_CURRENT_USER\\TclFoobar]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} {baz}
-test registry-4.3 {GetKeyNames: remote key} {pcOnly nonPortable english} {
+test registry-4.3 {GetKeyNames: remote key} {win reg nonPortable english} {
+ set hostname [info hostname]
registry set \\\\$hostname\\HKEY_CURRENT_USER\\TclFoobar\\baz
set result [registry keys \\\\gaspode\\HKEY_CURRENT_USER\\TclFoobar]
registry delete \\\\$hostname\\HKEY_CURRENT_USER\\TclFoobar
set result
} {baz}
-test registry-4.4 {GetKeyNames: empty key} {pcOnly} {
+test registry-4.4 {GetKeyNames: empty key} {win reg} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry set HKEY_CURRENT_USER\\TclFoobar
set result [registry keys HKEY_CURRENT_USER\\TclFoobar]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} {}
-test registry-4.5 {GetKeyNames: patterns} {pcOnly} {
+test registry-4.5 {GetKeyNames: patterns} {win reg} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry set HKEY_CURRENT_USER\\TclFoobar\\baz
registry set HKEY_CURRENT_USER\\TclFoobar\\blat
@@ -218,7 +220,7 @@ test registry-4.5 {GetKeyNames: patterns} {pcOnly} {
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} {baz blat}
-test registry-4.6 {GetKeyNames: names with spaces} {pcOnly} {
+test registry-4.6 {GetKeyNames: names with spaces} {win reg} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry set HKEY_CURRENT_USER\\TclFoobar\\baz\ bar
registry set HKEY_CURRENT_USER\\TclFoobar\\blat
@@ -227,7 +229,7 @@ test registry-4.6 {GetKeyNames: names with spaces} {pcOnly} {
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} {{baz bar} blat}
-test registry-4.7 {GetKeyNames: Unicode} {pcOnly english} {
+test registry-4.7 {GetKeyNames: Unicode} {win reg english} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry set HKEY_CURRENT_USER\\TclFoobar\\baz\u00c7bar
registry set HKEY_CURRENT_USER\\TclFoobar\\blat
@@ -236,7 +238,7 @@ test registry-4.7 {GetKeyNames: Unicode} {pcOnly english} {
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} "baz\u00c7bar blat"
-test registry-4.8 {GetKeyNames: Unicode} {pcOnly} {
+test registry-4.8 {GetKeyNames: Unicode} {win reg nt} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry set HKEY_CURRENT_USER\\TclFoobar\\baz\u30b7bar
registry set HKEY_CURRENT_USER\\TclFoobar\\blat
@@ -245,232 +247,232 @@ test registry-4.8 {GetKeyNames: Unicode} {pcOnly} {
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} "baz\u30b7bar blat"
-test registry-4.9 {GetKeyNames: very long key [Bug 1682211]} \
- -constraints {pcOnly} \
+test registry-4.9 {GetKeyNames: very long key [Bug 1682211]} {*}{
+ -constraints {win reg}
-setup {
registry set HKEY_CURRENT_USER\\TclFoobar\\a
registry set HKEY_CURRENT_USER\\TclFoobar\\b[string repeat x 254]
registry set HKEY_CURRENT_USER\\TclFoobar\\c
- } \
+ }
-body {
lsort [registry keys HKEY_CURRENT_USER\\TclFoobar]
- } \
+ }
-cleanup {
registry delete HKEY_CURRENT_USER\\TclFoobar
- } \
+ }} \
-result [list a b[string repeat x 254] c]
-test registry-5.1 {GetType} {pcOnly english} {
+test registry-5.1 {GetType} {win reg english} {
registry delete HKEY_CURRENT_USER\\TclFoobar
list [catch {registry type HKEY_CURRENT_USER\\TclFoobar val1} msg] $msg
} {1 {unable to open key: The system cannot find the file specified.}}
-test registry-5.2 {GetType} {pcOnly english} {
+test registry-5.2 {GetType} {win reg english} {
registry set HKEY_CURRENT_USER\\TclFoobar
list [catch {registry type HKEY_CURRENT_USER\\TclFoobar val1} msg] $msg
} {1 {unable to get type of value "val1" from key "HKEY_CURRENT_USER\TclFoobar": The system cannot find the file specified.}}
-test registry-5.3 {GetType} {pcOnly} {
+test registry-5.3 {GetType} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 foobar none
set result [registry type HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} none
-test registry-5.4 {GetType} {pcOnly} {
+test registry-5.4 {GetType} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 foobar
set result [registry type HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} sz
-test registry-5.5 {GetType} {pcOnly} {
+test registry-5.5 {GetType} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 foobar sz
set result [registry type HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} sz
-test registry-5.6 {GetType} {pcOnly} {
+test registry-5.6 {GetType} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 foobar expand_sz
set result [registry type HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} expand_sz
-test registry-5.7 {GetType} {pcOnly} {
+test registry-5.7 {GetType} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 1 binary
set result [registry type HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} binary
-test registry-5.8 {GetType} {pcOnly} {
+test registry-5.8 {GetType} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 1 dword
set result [registry type HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} dword
-test registry-5.9 {GetType} {pcOnly} {
+test registry-5.9 {GetType} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 1 dword_big_endian
set result [registry type HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} dword_big_endian
-test registry-5.10 {GetType} {pcOnly} {
+test registry-5.10 {GetType} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 1 link
set result [registry type HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} link
-test registry-5.11 {GetType} {pcOnly} {
+test registry-5.11 {GetType} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 foobar multi_sz
set result [registry type HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} multi_sz
-test registry-5.12 {GetType} {pcOnly} {
+test registry-5.12 {GetType} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 1 resource_list
set result [registry type HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} resource_list
-test registry-5.13 {GetType: unknown types} {pcOnly} {
+test registry-5.13 {GetType: unknown types} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 1 24
set result [registry type HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} 24
-test registry-5.14 {GetType: Unicode} {pcOnly} {
+test registry-5.14 {GetType: Unicode} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar va\u00c7l1 1 24
set result [registry type HKEY_CURRENT_USER\\TclFoobar va\u00c7l1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} 24
-test registry-6.1 {GetValue} {pcOnly english} {
+test registry-6.1 {GetValue} {win reg english} {
registry delete HKEY_CURRENT_USER\\TclFoobar
list [catch {registry get HKEY_CURRENT_USER\\TclFoobar val1} msg] $msg
} {1 {unable to open key: The system cannot find the file specified.}}
-test registry-6.2 {GetValue} {pcOnly english} {
+test registry-6.2 {GetValue} {win reg english} {
registry set HKEY_CURRENT_USER\\TclFoobar
list [catch {registry get HKEY_CURRENT_USER\\TclFoobar val1} msg] $msg
} {1 {unable to get value "val1" from key "HKEY_CURRENT_USER\TclFoobar": The system cannot find the file specified.}}
-test registry-6.3 {GetValue} {pcOnly} {
+test registry-6.3 {GetValue} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 foobar none
set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} foobar
-test registry-6.4 {GetValue} {pcOnly} {
+test registry-6.4 {GetValue} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 foobar
set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} foobar
-test registry-6.5 {GetValue} {pcOnly} {
+test registry-6.5 {GetValue} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 foobar sz
set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} foobar
-test registry-6.6 {GetValue} {pcOnly} {
+test registry-6.6 {GetValue} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 foobar expand_sz
set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} foobar
-test registry-6.7 {GetValue} {pcOnly} {
+test registry-6.7 {GetValue} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 1 binary
set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} 1
-test registry-6.8 {GetValue} {pcOnly} {
+test registry-6.8 {GetValue} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 0x20 dword
set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} 32
-test registry-6.9 {GetValue} {pcOnly} {
+test registry-6.9 {GetValue} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 0x20 dword_big_endian
set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} 32
-test registry-6.10 {GetValue} {pcOnly} {
+test registry-6.10 {GetValue} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 1 link
set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} 1
-test registry-6.11 {GetValue} {pcOnly} {
+test registry-6.11 {GetValue} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 foobar multi_sz
set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} foobar
-test registry-6.12 {GetValue} {pcOnly} {
+test registry-6.12 {GetValue} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 {foo\ bar baz} multi_sz
set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} {{foo bar} baz}
-test registry-6.13 {GetValue} {pcOnly} {
+test registry-6.13 {GetValue} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 {} multi_sz
set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} {}
test registry-6.14 {GetValue: truncation of multivalues with null elements} \
- {pcOnly} {
+ {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 {a {} b} multi_sz
set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} a
-test registry-6.15 {GetValue} {pcOnly} {
+test registry-6.15 {GetValue} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 1 resource_list
set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} 1
-test registry-6.16 {GetValue: unknown types} {pcOnly} {
+test registry-6.16 {GetValue: unknown types} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 1 24
set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} 1
-test registry-6.17 {GetValue: Unicode value names} {pcOnly} {
+test registry-6.17 {GetValue: Unicode value names} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val\u00c71 foobar multi_sz
set result [registry get HKEY_CURRENT_USER\\TclFoobar val\u00c71]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} foobar
-test registry-6.18 {GetValue: values with Unicode strings} {pcOnly} {
+test registry-6.18 {GetValue: values with Unicode strings} {win reg nt} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 {foo ba\u30b7r baz} multi_sz
set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} "foo ba\u30b7r baz"
-test registry-6.19 {GetValue: values with Unicode strings} {pcOnly english} {
+test registry-6.19 {GetValue: values with Unicode strings} {win reg english} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 {foo ba\u00c7r baz} multi_sz
set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} "foo ba\u00c7r baz"
-test registry-6.20 {GetValue: values with Unicode strings with embedded nulls} {pcOnly} {
+test registry-6.20 {GetValue: values with Unicode strings with embedded nulls} {win reg} {
registry set HKEY_CURRENT_USER\\TclFoobar val1 {foo ba\u0000r baz} multi_sz
set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} "foo ba r baz"
-test registry-7.1 {GetValueNames: bad key} {pcOnly english} {
+test registry-7.1 {GetValueNames: bad key} {win reg english} {
registry delete HKEY_CURRENT_USER\\TclFoobar
list [catch {registry values HKEY_CURRENT_USER\\TclFoobar} msg] $msg
} {1 {unable to open key: The system cannot find the file specified.}}
-test registry-7.2 {GetValueNames} {pcOnly} {
+test registry-7.2 {GetValueNames} {win reg} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry set HKEY_CURRENT_USER\\TclFoobar baz foobar
set result [registry values HKEY_CURRENT_USER\\TclFoobar]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} baz
-test registry-7.3 {GetValueNames} {pcOnly} {
+test registry-7.3 {GetValueNames} {win reg} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry set HKEY_CURRENT_USER\\TclFoobar baz foobar1
registry set HKEY_CURRENT_USER\\TclFoobar blat foobar2
@@ -479,20 +481,21 @@ test registry-7.3 {GetValueNames} {pcOnly} {
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} {{} baz blat}
-test registry-7.4 {GetValueNames: remote key} {pcOnly nonPortable english} {
+test registry-7.4 {GetValueNames: remote key} {win reg nonPortable english} {
+ set hostname [info hostname]
registry set \\\\$hostname\\HKEY_CURRENT_USER\\TclFoobar baz blat
set result [registry values \\\\$hostname\\HKEY_CURRENT_USER\\TclFoobar]
registry delete \\\\$hostname\\HKEY_CURRENT_USER\\TclFoobar
set result
} baz
-test registry-7.5 {GetValueNames: empty key} {pcOnly} {
+test registry-7.5 {GetValueNames: empty key} {win reg} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry set HKEY_CURRENT_USER\\TclFoobar
set result [registry values HKEY_CURRENT_USER\\TclFoobar]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} {}
-test registry-7.6 {GetValueNames: patterns} {pcOnly} {
+test registry-7.6 {GetValueNames: patterns} {win reg} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry set HKEY_CURRENT_USER\\TclFoobar baz foobar1
registry set HKEY_CURRENT_USER\\TclFoobar blat foobar2
@@ -501,7 +504,7 @@ test registry-7.6 {GetValueNames: patterns} {pcOnly} {
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} {baz blat}
-test registry-7.7 {GetValueNames: names with spaces} {pcOnly} {
+test registry-7.7 {GetValueNames: names with spaces} {win reg} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry set HKEY_CURRENT_USER\\TclFoobar baz\ bar foobar1
registry set HKEY_CURRENT_USER\\TclFoobar blat foobar2
@@ -511,52 +514,52 @@ test registry-7.7 {GetValueNames: names with spaces} {pcOnly} {
set result
} {{baz bar} blat}
-test registry-8.1 {OpenSubKey} {pcOnly nonPortable english} {
+test registry-8.1 {OpenSubKey} {win reg nonPortable english} {
# This test will only succeed if the current user does not have registry
# access on the specified machine.
list [catch {registry keys {\\mom\HKEY_LOCAL_MACHINE}} msg] $msg
} {1 {unable to open key: Access is denied.}}
-test registry-8.2 {OpenSubKey} {pcOnly} {
+test registry-8.2 {OpenSubKey} {win reg} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry set HKEY_CURRENT_USER\\TclFoobar
set result [registry keys HKEY_CURRENT_USER TclFoobar]
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} TclFoobar
-test registry-8.3 {OpenSubKey} {pcOnly english} {
+test registry-8.3 {OpenSubKey} {win reg english} {
registry delete HKEY_CURRENT_USER\\TclFoobar
list [catch {registry keys HKEY_CURRENT_USER\\TclFoobar} msg] $msg
} {1 {unable to open key: The system cannot find the file specified.}}
-test registry-9.1 {ParseKeyName: bad keys} {pcOnly} {
+test registry-9.1 {ParseKeyName: bad keys} {win reg} {
list [catch {registry values \\} msg] $msg
} "1 {bad key \"\\\": must start with a valid root}"
-test registry-9.2 {ParseKeyName: bad keys} {pcOnly} {
+test registry-9.2 {ParseKeyName: bad keys} {win reg} {
list [catch {registry values \\foobar} msg] $msg
} {1 {bad key "\foobar": must start with a valid root}}
-test registry-9.3 {ParseKeyName: bad keys} {pcOnly} {
+test registry-9.3 {ParseKeyName: bad keys} {win reg} {
list [catch {registry values \\\\} msg] $msg
} {1 {bad root name "": must be HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, or HKEY_DYN_DATA}}
-test registry-9.4 {ParseKeyName: bad keys} {pcOnly} {
+test registry-9.4 {ParseKeyName: bad keys} {win reg} {
list [catch {registry values \\\\\\} msg] $msg
} {1 {bad root name "": must be HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, or HKEY_DYN_DATA}}
-test registry-9.5 {ParseKeyName: bad keys} {pcOnly english} {
- list [catch {registry values \\\\\\HKEY_CLASSES_ROOT} msg] $msg
+test registry-9.5 {ParseKeyName: bad keys} {win reg english nt} {
+ list [catch {registry values \\\\\\HKEY_CURRENT_USER} msg] $msg
} {1 {unable to open key: The network address is invalid.}}
-test registry-9.6 {ParseKeyName: bad keys} {pcOnly} {
+test registry-9.6 {ParseKeyName: bad keys} {win reg} {
list [catch {registry values \\\\gaspode} msg] $msg
} {1 {bad root name "": must be HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, or HKEY_DYN_DATA}}
-test registry-9.7 {ParseKeyName: bad keys} {pcOnly} {
+test registry-9.7 {ParseKeyName: bad keys} {win reg} {
list [catch {registry values foobar} msg] $msg
} {1 {bad root name "foobar": must be HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, or HKEY_DYN_DATA}}
-test registry-9.8 {ParseKeyName: null keys} {pcOnly} {
+test registry-9.8 {ParseKeyName: null keys} {win reg} {
list [catch {registry delete HKEY_CURRENT_USER\\} msg] $msg
} {1 {bad key: cannot delete root keys}}
-test registry-9.9 {ParseKeyName: null keys} {pcOnly english} {
+test registry-9.9 {ParseKeyName: null keys} {win reg english} {
list [catch {registry keys HKEY_CURRENT_USER\\TclFoobar\\baz} msg] $msg
} {1 {unable to open key: The system cannot find the file specified.}}
-test registry-10.1 {RecursiveDeleteKey} {pcOnly} {
+test registry-10.1 {RecursiveDeleteKey} {win reg} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry set HKEY_CURRENT_USER\\TclFoobar\\test1
registry set HKEY_CURRENT_USER\\TclFoobar\\test2\\test3
@@ -564,7 +567,7 @@ test registry-10.1 {RecursiveDeleteKey} {pcOnly} {
set result [registry keys HKEY_CURRENT_USER TclFoobar]
set result
} {}
-test registry-10.2 {RecursiveDeleteKey} {pcOnly} {
+test registry-10.2 {RecursiveDeleteKey} {win reg} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry set HKEY_CURRENT_USER\\TclFoobar\\test1
registry set HKEY_CURRENT_USER\\TclFoobar\\test2\\test3
@@ -573,41 +576,40 @@ test registry-10.2 {RecursiveDeleteKey} {pcOnly} {
set result
} {}
-test registry-11.1 {SetValue: recursive creation} {pcOnly} {
+test registry-11.1 {SetValue: recursive creation} {win reg} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry set HKEY_CURRENT_USER\\TclFoobar\\baz blat foobar
set result [registry get HKEY_CURRENT_USER\\TclFoobar\\baz blat]
} foobar
-test registry-11.2 {SetValue: modification} {pcOnly} {
+test registry-11.2 {SetValue: modification} {win reg} {
registry delete HKEY_CURRENT_USER\\TclFoobar
registry set HKEY_CURRENT_USER\\TclFoobar\\baz blat foobar
registry set HKEY_CURRENT_USER\\TclFoobar\\baz blat frob
set result [registry get HKEY_CURRENT_USER\\TclFoobar\\baz blat]
} frob
-test registry-11.3 {SetValue: failure} {pcOnly nonPortable english} {
+test registry-11.3 {SetValue: failure} {win reg nonPortable english} {
# This test will only succeed if the current user does not have registry
# access on the specified machine.
list [catch {registry set {\\mom\HKEY_CURRENT_USER\TclFoobar} bar foobar} msg] $msg
} {1 {unable to open key: Access is denied.}}
-test registry-12.1 {BroadcastValue} {pcOnly} {
+test registry-12.1 {BroadcastValue} {win reg} {
list [catch {registry broadcast} msg] $msg
} {1 {wrong # args: should be "registry broadcast keyName ?-timeout millisecs?"}}
-test registry-12.2 {BroadcastValue} {pcOnly} {
+test registry-12.2 {BroadcastValue} {win reg} {
list [catch {registry broadcast "" -time} msg] $msg
} {1 {wrong # args: should be "registry broadcast keyName ?-timeout millisecs?"}}
-test registry-12.3 {BroadcastValue} {pcOnly} {
+test registry-12.3 {BroadcastValue} {win reg} {
list [catch {registry broadcast "" - 500} msg] $msg
} {1 {wrong # args: should be "registry broadcast keyName ?-timeout millisecs?"}}
-test registry-12.4 {BroadcastValue} {pcOnly} {
+test registry-12.4 {BroadcastValue} {win reg} {
list [catch {registry broadcast {Environment}} msg] $msg
} {0 {1 0}}
-test registry-12.5 {BroadcastValue} {pcOnly} {
+test registry-12.5 {BroadcastValue} {win reg} {
list [catch {registry b {}} msg] $msg
} {0 {1 0}}
# cleanup
-unset hostname
::tcltest::cleanupTests
return
diff --git a/tests/rename.test b/tests/rename.test
index aa5f900..bd14578 100644
--- a/tests/rename.test
+++ b/tests/rename.test
@@ -16,6 +16,8 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
+testConstraint testdel [llength [info commands testdel]]
+
# Must eliminate the "unknown" command while the test is running,
# especially if the test is being run in a program with its
# own special-purpose unknown command.
@@ -75,65 +77,63 @@ catch {rename unknown {}}
catch {rename unknown.old unknown}
catch {rename bar {}}
-if {[info command testdel] == "testdel"} {
- test rename-4.1 {reentrancy issues with command deletion and renaming} {
- set x {}
- testdel {} foo {lappend x deleted; rename bar {}; lappend x [info command bar]}
- rename foo bar
- lappend x |
- rename bar {}
- set x
- } {| deleted {}}
- test rename-4.2 {reentrancy issues with command deletion and renaming} {
- set x {}
- testdel {} foo {lappend x deleted; rename foo bar}
- rename foo {}
- set x
- } {deleted}
- test rename-4.3 {reentrancy issues with command deletion and renaming} {
- set x {}
- testdel {} foo {lappend x deleted; testdel {} foo {lappend x deleted2}}
- rename foo {}
- lappend x |
- rename foo {}
- set x
- } {deleted | deleted2}
- test rename-4.4 {reentrancy issues with command deletion and renaming} {
- set x {}
- testdel {} foo {lappend x deleted; rename foo bar}
- rename foo {}
- lappend x | [info command bar]
- } {deleted | {}}
- test rename-4.5 {reentrancy issues with command deletion and renaming} {
- set env(value) before
- interp create foo
- testdel foo cmd {set env(value) deleted}
+test rename-4.1 {reentrancy issues with command deletion and renaming} testdel {
+ set x {}
+ testdel {} foo {lappend x deleted; rename bar {}; lappend x [info command bar]}
+ rename foo bar
+ lappend x |
+ rename bar {}
+ set x
+} {| deleted {}}
+test rename-4.2 {reentrancy issues with command deletion and renaming} testdel {
+ set x {}
+ testdel {} foo {lappend x deleted; rename foo bar}
+ rename foo {}
+ set x
+} {deleted}
+test rename-4.3 {reentrancy issues with command deletion and renaming} testdel {
+ set x {}
+ testdel {} foo {lappend x deleted; testdel {} foo {lappend x deleted2}}
+ rename foo {}
+ lappend x |
+ rename foo {}
+ set x
+} {deleted | deleted2}
+test rename-4.4 {reentrancy issues with command deletion and renaming} testdel {
+ set x {}
+ testdel {} foo {lappend x deleted; rename foo bar}
+ rename foo {}
+ lappend x | [info command bar]
+} {deleted | {}}
+test rename-4.5 {reentrancy issues with command deletion and renaming} testdel {
+ set env(value) before
+ interp create foo
+ testdel foo cmd {set env(value) deleted}
+ interp delete foo
+ set env(value)
+} {deleted}
+test rename-4.6 {reentrancy issues with command deletion and renaming} testdel {
+ proc kill args {
+ interp delete foo
+ }
+ set env(value) before
+ interp create foo
+ foo alias kill kill
+ testdel foo cmd {set env(value) deleted; kill}
+ list [catch {foo eval {rename cmd {}}} msg] $msg $env(value)
+} {0 {} deleted}
+test rename-4.7 {reentrancy issues with command deletion and renaming} testdel {
+ proc kill args {
interp delete foo
- set env(value)
- } {deleted}
- test rename-4.6 {reentrancy issues with command deletion and renaming} {
- proc kill args {
- interp delete foo
- }
- set env(value) before
- interp create foo
- foo alias kill kill
- testdel foo cmd {set env(value) deleted; kill}
- list [catch {foo eval {rename cmd {}}} msg] $msg $env(value)
- } {0 {} deleted}
- test rename-4.7 {reentrancy issues with command deletion and renaming} {
- proc kill args {
- interp delete foo
- }
- set env(value) before
- interp create foo
- foo alias kill kill
- testdel foo cmd {set env(value) deleted; kill}
- list [catch {interp delete foo} msg] $msg $env(value)
- } {0 {} deleted}
- if {[info exists env(value)]} {
- unset env(value)
}
+ set env(value) before
+ interp create foo
+ foo alias kill kill
+ testdel foo cmd {set env(value) deleted; kill}
+ list [catch {interp delete foo} msg] $msg $env(value)
+} {0 {} deleted}
+if {[info exists env(value)]} {
+ unset env(value)
}
# Save the unknown procedure which is modified by the following test.
@@ -158,7 +158,7 @@ catch {rename unknown.old unknown}
test rename-6.1 {old code invalidated (epoch incremented) when cmd with compile proc is renamed } {
- proc x {} {
+ proc x {} {
set a 123
set b [incr a]
}
@@ -166,6 +166,8 @@ test rename-6.1 {old code invalidated (epoch incremented) when cmd with compile
rename incr incr.old
proc incr {} {puts "new incr called!"}
catch {x} msg
+ rename incr {}
+ rename incr.old incr
set msg
} {wrong # args: should be "incr"}
diff --git a/tests/resource.test b/tests/resource.test
deleted file mode 100644
index 3ae24e2..0000000
--- a/tests/resource.test
+++ /dev/null
@@ -1,363 +0,0 @@
-# Commands covered: resource
-#
-# This file contains a collection of tests for one or more of the Tcl
-# built-in commands. Sourcing this file into Tcl runs the tests and
-# generates output for errors. No output means no errors were found.
-#
-# Copyright (c) 1996-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.
-
-if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
- namespace import -force ::tcltest::*
-}
-
-test resource-1.1 {resource tests} {macOnly} {
- list [catch {resource} msg] $msg
-} {1 {wrong # args: should be "resource option ?arg ...?"}}
-test resource-1.2 {resource tests} {macOnly} {
- list [catch {resource _bad_} msg] $msg
-} {1 {bad option "_bad_": must be close, delete, files, list, open, read, types, or write}}
-
-# resource open & close tests
-test resource-2.1 {resource open & close tests} {macOnly} {
- list [catch {resource open} msg] $msg
-} {1 {wrong # args: should be "resource open fileName ?permissions?"}}
-test resource-2.2 {resource open & close tests} {macOnly} {
- list [catch {resource open resource.test r extraArg} msg] $msg
-} {1 {wrong # args: should be "resource open fileName ?permissions?"}}
-test resource-2.3 {resource open & close tests} {macOnly} {
- list [catch {resource open resource.test bad_perms} msg] $msg
-} {1 {illegal access mode "bad_perms"}}
-test resource-2.4 {resource open & close tests} {macOnly} {
- list [catch {resource open _bad_file_} msg] $msg
-} {1 {file does not exist}}
-test resource-2.5 {resource open & close tests} {macOnly} {
- testWriteTextResource -rsrc fileRsrcName -file rsrc.file {error "don't source me"}
- set id [resource open rsrc.file]
- resource close $id
- file delete rsrc.file
-} {}
-test resource-2.6 {resource open & close tests} {macOnly} {
- catch {file delete rsrc.file}
- testWriteTextResource -rsrc fileRsrcName -file rsrc.file {A test string}
- set id [resource open rsrc.file]
- set result [string compare [resource open rsrc.file] $id]
- lappend result [resource read TEXT fileRsrcName $id]
- resource close $id
- file delete rsrc.file
- set result
-} {0 {A test string}}
-test resource-2.7 {resource open & close tests} {macOnly} {
- catch {file delete rsrc.file}
- testWriteTextResource -rsrc fileRsrcName -file rsrc.file {error "don't source me"}
- set id [resource open rsrc.file r]
- set result [catch {resource open rsrc.file w} mssg]
- resource close $id
- file delete rsrc.file
- lappend result $mssg
- set result
-} {1 {Resource already open with different permissions.}}
-test resource-2.8 {resource open & close tests} {macOnly} {
- list [catch {resource close} msg] $msg
-} {1 {wrong # args: should be "resource close resourceRef"}}
-test resource-2.9 {resource open & close tests} {macOnly} {
- list [catch {resource close foo bar} msg] $msg
-} {1 {wrong # args: should be "resource close resourceRef"}}
-test resource-2.10 {resource open & close tests} {macOnly} {
- list [catch {resource close _bad_resource_} msg] $msg
-} {1 {invalid resource file reference "_bad_resource_"}}
-test resource-2.11 {resource open & close tests} {macOnly} {
- set result [catch {resource close System} mssg]
- lappend result $mssg
-} {1 {can't close "System" resource file}}
-test resource-2.12 {resource open & close tests} {macOnly} {
- set result [catch {resource close application} mssg]
- lappend result $mssg
-} {1 {can't close "application" resource file}}
-
-# Tests for listing resources
-test resource-3.1 {resource list tests} {macOnly} {
- list [catch {resource list} msg] $msg
-} {1 {wrong # args: should be "resource list resourceType ?resourceRef?"}}
-test resource-3.2 {resource list tests} {macOnly} {
- list [catch {resource list _bad_type_} msg] $msg
-} {1 {expected Macintosh OS type but got "_bad_type_"}}
-test resource-3.3 {resource list tests} {macOnly} {
- list [catch {resource list TEXT _bad_ref_} msg] $msg
-} {1 {invalid resource file reference "_bad_ref_"}}
-test resource-3.4 {resource list tests} {macOnly} {
- list [catch {resource list TEXT _bad_ref_ extraArg} msg] $msg
-} {1 {wrong # args: should be "resource list resourceType ?resourceRef?"}}
-test resource-3.5 {resource list tests} {macOnly} {
- catch {file delete rsrc.file}
- testWriteTextResource -rsrc fileRsrcName -file rsrc.file {error "don't source me"}
- set id [resource open rsrc.file]
- catch "resource list TEXT $id" result
- resource close $id
- set result
-} {fileRsrcName}
-test resource-3.6 {resource list tests} {macOnly} {
- # There should not be any resource of this type
- resource list XXXX
-} {}
-test resource-3.7 {resource list tests} {macOnly} {
- set resourceList [resource list STR#]
- if {[lsearch $resourceList {Tcl Environment Variables}] == -1} {
- set result {couldn't find resource that should exist}
- } else {
- set result ok
- }
-} {ok}
-
-# Tests for reading resources
-test resource-4.1 {resource read tests} {macOnly} {
- list [catch {resource read} msg] $msg
-} {1 {wrong # args: should be "resource read resourceType resourceId ?resourceRef?"}}
-test resource-4.2 {resource read tests} {macOnly} {
- list [catch {resource read TEXT} msg] $msg
-} {1 {wrong # args: should be "resource read resourceType resourceId ?resourceRef?"}}
-test resource-4.3 {resource read tests} {macOnly} {
- list [catch {resource read STR# {_non_existant_resource_}} msg] $msg
-} {1 {could not load resource}}
-test resource-4.4 {resource read tests} {macOnly} {
- # The following resource should exist and load OK without error
- catch {resource read STR# {Tcl Environment Variables}}
-} {0}
-
-# Tests for getting resource types
-test resource-5.1 {resource types tests} {macOnly} {
- list [catch {resource types _bad_ref_} msg] $msg
-} {1 {invalid resource file reference "_bad_ref_"}}
-test resource-5.2 {resource types tests} {macOnly} {
- list [catch {resource types _bad_ref_ extraArg} msg] $msg
-} {1 {wrong # args: should be "resource types ?resourceRef?"}}
-test resource-5.3 {resource types tests} {macOnly} {
- # This should never cause an error
- catch {resource types}
-} {0}
-test resource-5.4 {resource types tests} {macOnly} {
- testWriteTextResource -rsrc fileRsrcName -file rsrc.file {error "don't source me"}
- set id [resource open rsrc.file]
- set result [resource types $id]
- resource close $id
- set result
-} {TEXT}
-
-# resource write tests
-test resource-6.1 {resource write tests} {macOnly} {
- list [catch {resource write} msg] $msg
-} {1 {wrong # args: should be "resource write ?-id resourceId? ?-name resourceName? ?-file resourceRef? ?-force? resourceType data"}}
-test resource-6.2 {resource write tests} {macOnly} {
- list [catch {resource write _bad_type_ data} msg] $msg
-} {1 {expected Macintosh OS type but got "_bad_type_"}}
-test resource-6.3 {resource write tests} {macOnly} {
- catch {file delete rsrc2.file}
- set id [resource open rsrc2.file w]
- resource close $id
- set id [resource open rsrc2.file r]
- set result [catch {resource write -file $id -name Hello TEXT foo} errMsg]
- lappend result [string compare $errMsg "cannot write to resource file \"$id\", it was opened read only"]
- lappend result [lsearch [resource list TEXT $id] Hello]
- resource close $id
- file delete rsrc2.file
- set result
-} {1 0 -1}
-test resource-6.4 {resource write tests} {macOnly} {
- catch {file delete rsrc2.file}
- set id [resource open rsrc2.file w]
- resource write -file $id -name Hello TEXT {set x "our test data"}
- source -rsrc Hello rsrc2.file
- resource close $id
- file delete rsrc2.file
- set x
-} {our test data}
-test resource-6.5 {resource write tests} {macOnly} {
- catch {file delete rsrc2.file}
- set id [resource open rsrc2.file w]
- resource write -file $id -id 256 TEXT {HAHAHAHAHAHAHA}
- set result [catch {resource write -file $id -id 256 TEXT {HOHOHOHOHOHO}} mssg]
- resource close $id
- file delete rsrc2.file
- lappend result $mssg
-} {1 {the resource 256 already exists, use "-force" to overwrite it.}}
-test resource-6.6 {resource write tests} {macOnly} {
- catch {file delete rsrc2.file}
- testWriteTextResource -rsrc fileRsrcName -rsrcid 256 -file rsrc2.file -protected {error "don't tread on me"}
- set id [resource open rsrc2.file w]
- set result [catch {resource write -id 256 -force -file $id TEXT {NAHNAHNANAHNAH}} mssg]
- resource close $id
- file delete rsrc2.file
- lappend result $mssg
-} {1 {could not write resource id 256 of type TEXT, it was protected.}}
-test resource-6.7 {resource write tests} {macOnly} {
- catch {file delete rsrc2.file}
- set id [resource open rsrc2.file w]
- resource write -file $id -id 256 -name FOO TEXT {set x [list "our first test data"]}
- resource write -file $id -id 256 -name BAR -force TEXT {set x [list "our second test data"]}
- source -rsrcid 256 rsrc2.file
- lappend x [resource list TEXT $id]
- resource close $id
- file delete rsrc2.file
- set x
-} {{our second test data} BAR}
-
-#Tests for listing open resource files
-test resource-7.1 {resource file tests} {macOnly} {
- catch {resource files foo bar} mssg
- set mssg
-} {wrong # args: should be "resource files ?resourceId?"}
-test resource-7.2 {resource file tests} {macOnly} {
- catch {file delete rsrc2.file}
- set rsrcFiles [resource files]
- set id [resource open rsrc2.file w]
- set result [string compare $rsrcFiles [lrange [resource files] 1 end]]
- lappend result [string compare $id [lrange [resource files] 0 0]]
- resource close $id
- file delete rsrc2.file
- set result
-} {0 0}
-test resource-7.3 {resource file tests} {macOnly} {
- set result 0
- foreach file [resource files] {
- if {[catch {resource types $file}] != 0} {
- set result 1
- }
- }
- set result
-} {0}
-test resource-7.4 {resource file tests} {macOnly} {
- catch {resource files __NO_SUCH_RESOURCE__} mssg
- set mssg
-} {invalid resource file reference "__NO_SUCH_RESOURCE__"}
-test resource-7.5 {resource file tests} {macOnly} {
- set sys [resource files System]
- string compare $sys [file join $env(SYS_FOLDER) System]
-} {0}
-test resource-7.6 {resource file tests} {macOnly} {
- set app [resource files application]
- string compare $app [info nameofexecutable]
-} {0}
-
-#Tests for the resource delete command
-test resource-8.1 {resource delete tests} {macOnly} {
- list [catch {resource delete} msg] $msg
-} {1 {wrong # args: should be "resource delete ?-id resourceId? ?-name resourceName? ?-file resourceRef? resourceType"}}
-test resource-8.2 {resource delete tests} {macOnly} {
- list [catch {resource delete TEXT} msg] $msg
-} {1 {you must specify either "-id" or "-name" or both to "resource delete"}}
-test resource-8.3 {resource delete tests} {macOnly} {
- set result [catch {resource delete -file ffffff -id 128 TEXT} mssg]
- lappend result $mssg
-} {1 {invalid resource file reference "ffffff"}}
-test resource-8.4 {resource delete tests} {macOnly} {
- catch {file delete rsrc2.file}
- testWriteTextResource -rsrc fileRsrcName -rsrcid 128 -file rsrc2.file {Some stuff}
- set id [resource open rsrc2.file r]
- set result [catch {resource delete -id 128 -file $id TEXT} mssg]
- resource close $id
- file delete rsrc2.file
- lappend result [string compare $mssg "cannot delete from resource file \"$id\", it was opened read only"]
-} {1 0}
-test resource-8.5 {resource delete tests} {macOnly} {
- catch {file delete rsrc2.file}
- testWriteTextResource -rsrc fileRsrcName -rsrcid 128 -file rsrc2.file {Some stuff}
- set id [resource open rsrc2.file w]
- set result [catch {resource delete -id 128 -file $id _bad_type_} mssg]
- resource close $id
- file delete rsrc2.file
- lappend result $mssg
-} {1 {expected Macintosh OS type but got "_bad_type_"}}
-test resource-8.5.1 {resource delete tests} {macOnly} {
- catch {file delete rsrc2.file}
- set id [resource open rsrc2.file w]
- set result [catch {resource delete -id 128 -file $id TEXT} mssg]
- resource close $id
- file delete rsrc2.file
- lappend result $mssg
-} {1 {resource not found}}
-test resource-8.6 {resource delete tests} {macOnly} {
- catch {file delete rsrc2.file}
- set id [resource open rsrc2.file w]
- set result [catch {resource delete -name foo -file $id TEXT} mssg]
- resource close $id
- file delete rsrc2.file
- lappend result $mssg
-} {1 {resource not found}}
-test resource-8.7 {resource delete tests} {macOnly} {
- catch {file delete rsrc2.file}
- set id [resource open rsrc2.file w]
- resource write -file $id -name foo -id 128 TEXT {some stuff}
- resource write -file $id -name bar -id 129 TEXT {some stuff}
- set result [catch {resource delete -name foo -id 129 -file $id TEXT} mssg]
- resource close $id
- file delete rsrc2.file
- lappend result $mssg
-} {1 {"-id" and "-name" values do not point to the same resource}}
-test resource-8.8 {resource delete tests} {macOnly} {
- catch {file delete rsrc2.file}
- testWriteTextResource -rsrc fileRsrcName -rsrcid 256 -file rsrc2.file -protected {error "don't tread on me"}
- set id [resource open rsrc2.file w]
- set result [catch {resource delete -id 256 -file $id TEXT } mssg]
- resource close $id
- file delete rsrc2.file
- lappend result $mssg
-} {1 {resource cannot be deleted: it is protected.}}
-test resource-8.9 {resource delete tests} {macOnly} {
- catch {file delete rsrc2.file}
- testWriteTextResource -rsrc fileRsrcName -rsrcid 128 -file rsrc2.file {Some stuff}
- set id [resource open rsrc2.file w]
- set result [resource list TEXT $id]
- resource delete -id 128 -file $id TEXT
- lappend result [resource list TEXT $id]
- resource close $id
- file delete rsrc2.file
- set result
-} {fileRsrcName {}}
-
-# Tests for the Mac version of the source command
-catch {file delete rsrc.file}
-test resource-9.1 {source command} {macOnly} {
- testWriteTextResource -rsrc fileRsrcName -rsrcid 128 \
- -file rsrc.file {set rsrc_foo 1}
- catch {unset rsrc_foo}
- source -rsrc fileRsrcName rsrc.file
- list [catch {set rsrc_foo} msg] $msg
-} {0 1}
-test resource-9.2 {source command} {macOnly} {
- catch {unset rsrc_foo}
- list [catch {source -rsrc no_resource rsrc.file} msg] $msg
-} {1 {The resource "no_resource" could not be loaded from rsrc.file.}}
-test resource-9.3 {source command} {macOnly} {
- catch {unset rsrc_foo}
- source -rsrcid 128 rsrc.file
- list [catch {set rsrc_foo} msg] $msg
-} {0 1}
-test resource-9.4 {source command} {macOnly} {
- catch {unset rsrc_foo}
- list [catch {source -rsrcid bad_int rsrc.file} msg] $msg
-} {1 {expected integer but got "bad_int"}}
-test resource-9.5 {source command} {macOnly} {
- catch {unset rsrc_foo}
- list [catch {source -rsrcid 100 rsrc.file} msg] $msg
-} {1 {The resource "ID=100" could not be loaded from rsrc.file.}}
-
-# cleanup
-catch {file delete rsrc.file}
-::tcltest::cleanupTests
-return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/result.test b/tests/result.test
index 0e61575..3ee803e 100644
--- a/tests/result.test
+++ b/tests/result.test
@@ -17,8 +17,10 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
# Some tests require the testsaveresult command
-::tcltest::testConstraint testsaveresult \
- [expr {[info commands testsaveresult] != {}}]
+testConstraint testsaveresult [llength [info commands testsaveresult]]
+testConstraint testsetobjerrorcode [llength [info commands testsetobjerrorcode]]
+testConstraint testseterrorcode [llength [info commands testseterrorcode]]
+testConstraint testreturn [llength [info commands testreturn]]
test result-1.1 {Tcl_SaveInterpResult} {testsaveresult} {
testsaveresult small {set x 42} 0
@@ -63,9 +65,6 @@ test result-3.2 {Tcl_DiscardInterpResult} {testsaveresult} {
testsaveresult free {set x 42} 1
} {42}
-::tcltest::testConstraint testsetobjerrorcode \
- [expr {[info commands testsetobjerrorcode] != {}}]
-
test result-4.1 {Tcl_SetObjErrorCode - one arg} {testsetobjerrorcode} {
catch {testsetobjerrorcode 1}
list [set errorCode]
@@ -87,9 +86,6 @@ test result-4.5 {Tcl_SetObjErrorCode - five args} {testsetobjerrorcode} {
list [set errorCode]
} {{1 2 3 4 5}}
-::tcltest::testConstraint testseterrorcode \
- [expr {[info commands testseterrorcode] != {}}]
-
test result-5.1 {Tcl_SetErrorCode - one arg} testseterrorcode {
catch {testseterrorcode 1}
set errorCode
@@ -107,6 +103,18 @@ test result-5.4 {Tcl_SetErrorCode - two args, list quoting} testseterrorcode {
set errorCode
} {{a b} c}
+test result-6.0 {Bug 1209759} -constraints testreturn -body {
+ # Might panic if bug is not fixed.
+ proc foo {} {testreturn}
+ foo
+} -returnCodes ok -result {}
+test result-6.1 {Bug 1209759} -constraints testreturn -body {
+ # Might panic if bug is not fixed.
+ proc foo {} {catch {return -level 2}; testreturn}
+ foo
+} -cleanup {
+ rename foo {}
+} -returnCodes ok -result {}
test result-6.2 {Bug 1649062} -setup {
proc foo {} {
if {[catch {
@@ -122,19 +130,10 @@ test result-6.2 {Bug 1649062} -setup {
} -cleanup {
rename foo {}
} -result {foo {} {}}
-
+test result-6.3 {Bug 2383005} {
+ catch {return -code error -errorcode {{}a} eek} m
+ set m
+} {bad -errorcode value: expected a list but got "{}a"}
# cleanup
-::tcltest::cleanupTests
+cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/safe.test b/tests/safe.test
index a3def0a..fbcb2a1 100644
--- a/tests/safe.test
+++ b/tests/safe.test
@@ -10,13 +10,15 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+package require Tcl 8.5
+
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2
namespace import -force ::tcltest::*
}
foreach i [interp slaves] {
- interp delete $i
+ interp delete $i
}
set saveAutoPath $::auto_path
@@ -33,7 +35,6 @@ test safe-1.1 {safe::interpConfigure syntax} {
list [catch {safe::interpConfigure} msg] $msg;
} {1 {no value given for parameter "slave" (use -help for full usage) :
slave name () name of the slave}}
-
test safe-1.2 {safe::interpCreate syntax} {
list [catch {safe::interpCreate -help} msg] $msg;
} {1 {Usage information:
@@ -47,15 +48,15 @@ test safe-1.2 {safe::interpCreate syntax} {
-nestedLoadOk boolflag (false) allow nested loading
-nested boolean (false) nested loading
-deleteHook script () delete hook}}
-
test safe-1.3 {safe::interpInit syntax} {
list [catch {safe::interpInit -noStatics} msg] $msg;
} {1 {bad value "-noStatics" for parameter
slave name () name of the slave}}
-test safe-2.1 {creating interpreters, should have no aliases} {
- interp aliases
+test safe-2.1 {creating interpreters, should have no aliases} emptyTest {
+ # Disabled this test. It tests nothing sensible. [Bug 999612]
+ # interp aliases
} ""
test safe-2.2 {creating interpreters, should have no aliases} {
catch {safe::interpDelete a}
@@ -64,13 +65,13 @@ test safe-2.2 {creating interpreters, should have no aliases} {
safe::interpDelete a
set l
} ""
-test safe-2.3 {creating safe interpreters, should have no aliases} {
+test safe-2.3 {creating safe interpreters, should have no unexpected aliases} {
catch {safe::interpDelete a}
interp create a -safe
set l [a aliases]
interp delete a
- set l
-} ""
+ lsort $l
+} {::tcl::mathfunc::max ::tcl::mathfunc::min clock}
test safe-3.1 {calling safe::interpInit is safe} {
catch {safe::interpDelete a}
@@ -86,7 +87,7 @@ test safe-3.2 {calling safe::interpCreate on trusted interp} {
set l [lsort [a aliases]]
safe::interpDelete a
set l
-} {encoding exit file load source}
+} {::tcl::info::nameofexecutable clock encoding exit file glob load source}
test safe-3.3 {calling safe::interpCreate on trusted interp} {
catch {safe::interpDelete a}
safe::interpCreate a
@@ -114,25 +115,6 @@ test safe-4.2 {safe::interpDelete, indirectly} {
a alias exit safe::interpDelete a
a eval exit
} ""
-test safe-4.3 {safe::interpDelete, state array (not a public api)} {
- catch {safe::interpDelete a}
- namespace eval safe {set [InterpStateName a](foo) 33}
- # not an error anymore to call it if interp is already
- # deleted, to make trhings smooth if it's called twice...
- catch {safe::interpDelete a} m1
- catch {namespace eval safe {set [InterpStateName a](foo)}} m2
- list $m1 $m2
-} "{}\
- {can't read \"[safe::InterpStateName a](foo)\": no such variable}"
-
-
-test safe-4.4 {safe::interpDelete, state array, indirectly (not a public api)} {
- catch {safe::interpDelete a}
- safe::interpCreate a
- namespace eval safe {set [InterpStateName a](foo) 33}
- a eval exit
- catch {namespace eval safe {set [InterpStateName a](foo)}} msg
-} 1
test safe-4.5 {safe::interpDelete} {
catch {safe::interpDelete a}
@@ -158,43 +140,33 @@ test safe-5.1 {test auto-loading in safe interpreters} {
} {0 -1}
# test safe interps 'information leak'
-proc SI {} {
- global I
- set I [interp create -safe];
-}
-proc DI {} {
- global I;
- interp delete $I;
+proc SafeEval {script} {
+ # Helper procedure that ensures the safe interp is cleaned up even if
+ # there is a failure in the script.
+ set SafeInterp [interp create -safe]
+ catch {$SafeInterp eval $script} msg opts
+ interp delete $SafeInterp
+ return -options $opts $msg
}
+
test safe-6.1 {test safe interpreters knowledge of the world} {
- SI; set r [lsort [$I eval {info globals}]]; DI; set r
+ lsort [SafeEval {info globals}]
} {tcl_interactive tcl_patchLevel tcl_platform tcl_version}
test safe-6.2 {test safe interpreters knowledge of the world} {
- SI; set r [$I eval {info script}]; DI; set r
+ SafeEval {info script}
} {}
test safe-6.3 {test safe interpreters knowledge of the world} {
- SI
- set r [lsort [$I eval {array names tcl_platform}]]
- DI
+ set r [lsort [SafeEval {array names tcl_platform}]]
# If running a windows-debug shell, remove the "debug" element from r.
- if {$tcl_platform(platform) == "windows" && \
- [lsearch $r "debug"] != -1} {
+ if {[testConstraint win] && ("debug" in $r)} {
set r [lreplace $r 1 1]
}
set threaded [lsearch $r "threaded"]
if {$threaded != -1} {
set r [lreplace $r $threaded $threaded]
}
- set tip [lsearch $r "tip,268"]
- if {$tip != -1} {
- set r [lreplace $r $tip $tip]
- }
- set tip [lsearch $r "tip,280"]
- if {$tip != -1} {
- set r [lreplace $r $tip $tip]
- }
set r
-} {byteOrder platform wordSize}
+} {byteOrder platform pointerSize wordSize}
# more test should be added to check that hostname, nameofexecutable,
# aren't leaking infos, but they still do...
@@ -211,8 +183,7 @@ test safe-7.1 {tests that everything works at high level} {
safe::interpDelete $i
set v
} 1.0
-
-test safe-7.2 {tests specific path and interpFind/AddToAccessPath} {
+test safe-7.2 {tests specific path and interpFind/AddToAccessPath} -body {
set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]];
# should not add anything (p0)
set token1 [safe::interpAddToAccessPath $i [info library]]
@@ -224,7 +195,7 @@ test safe-7.2 {tests specific path and interpFind/AddToAccessPath} {
[catch {interp eval $i {package require http 1}} msg] $msg \
[safe::interpConfigure $i]\
[safe::interpDelete $i]
-} "{\$p(:0:)} {\$p(:1:)} 1 {can't find package http 1} {-accessPath {[list $tcl_library /dummy/unixlike/test/path]} -statics 0 -nested 1 -deleteHook {}} {}"
+} -match glob -result "{\$p(:0:)} {\$p(:*:)} 1 {can't find package http 1} {-accessPath {[list $tcl_library */dummy/unixlike/test/path]} -statics 0 -nested 1 -deleteHook {}} {}"
# test source control on file name
@@ -235,9 +206,7 @@ test safe-8.1 {safe source control on file} {
list [catch {$i eval {source}} msg] \
$msg \
[safe::interpDelete $i] ;
-} {1 {wrong # args: should be "source fileName"} {}}
-
-# test source control on file name
+} {1 {wrong # args: should be "source ?-encoding E? fileName"} {}}
test safe-8.2 {safe source control on file} {
set i "a";
catch {safe::interpDelete $i}
@@ -245,8 +214,7 @@ test safe-8.2 {safe source control on file} {
list [catch {$i eval {source}} msg] \
$msg \
[safe::interpDelete $i] ;
-} {1 {wrong # args: should be "source fileName"} {}}
-
+} {1 {wrong # args: should be "source ?-encoding E? fileName"} {}}
test safe-8.3 {safe source control on file} {
set i "a";
catch {safe::interpDelete $i}
@@ -261,8 +229,6 @@ test safe-8.3 {safe source control on file} {
[safe::setLogCmd $prevlog; unset log] \
[safe::interpDelete $i] ;
} {1 {permission denied} {{ERROR for slave a : ".": is a directory}} {} {}}
-
-
test safe-8.4 {safe source control on file} {
set i "a";
catch {safe::interpDelete $i}
@@ -277,8 +243,6 @@ test safe-8.4 {safe source control on file} {
[safe::setLogCmd $prevlog; unset log] \
[safe::interpDelete $i] ;
} {1 {permission denied} {{ERROR for slave a : "/abc/def": not in access_path}} {} {}}
-
-
test safe-8.5 {safe source control on file} {
# This tested filename == *.tcl or tclIndex, but that restriction
# was removed in 8.4a4 - hobbs
@@ -295,8 +259,6 @@ test safe-8.5 {safe source control on file} {
[safe::setLogCmd $prevlog; unset log] \
[safe::interpDelete $i] ;
} [list 1 {no such file or directory} [list "ERROR for slave a : [file join [info library] blah]:no such file or directory"] {} {}]
-
-
test safe-8.6 {safe source control on file} {
set i "a";
catch {safe::interpDelete $i}
@@ -311,8 +273,6 @@ test safe-8.6 {safe source control on file} {
[safe::setLogCmd $prevlog; unset log] \
[safe::interpDelete $i] ;
} [list 1 {no such file or directory} [list "ERROR for slave a : [file join [info library] blah.tcl]:no such file or directory"] {} {}]
-
-
test safe-8.7 {safe source control on file} {
# This tested length of filename, but that restriction
# was removed in 8.4a4 - hobbs
@@ -330,7 +290,6 @@ test safe-8.7 {safe source control on file} {
[safe::setLogCmd $prevlog; unset log] \
[safe::interpDelete $i] ;
} [list 1 {no such file or directory} [list "ERROR for slave a : [file join [info library] xxxxxxxxxxx.tcl]:no such file or directory"] {} {}]
-
test safe-8.8 {safe source forbids -rsrc} {
set i "a";
catch {safe::interpDelete $i}
@@ -338,8 +297,18 @@ test safe-8.8 {safe source forbids -rsrc} {
list [catch {$i eval {source -rsrc Init}} msg] \
$msg \
[safe::interpDelete $i] ;
-} {1 {wrong # args: should be "source fileName"} {}}
-
+} {1 {wrong # args: should be "source ?-encoding E? fileName"} {}}
+test safe-8.9 {safe source and return} -setup {
+ set returnScript [makeFile {return "ok"} return.tcl]
+ catch {safe::interpDelete $i}
+} -body {
+ safe::interpCreate $i
+ set token [safe::interpAddToAccessPath $i [file dirname $returnScript]]
+ $i eval [list source $token/[file tail $returnScript]]
+} -cleanup {
+ catch {safe::interpDelete $i}
+ removeFile $returnScript
+} -result ok
test safe-9.1 {safe interps' deleteHook} {
set i "a";
@@ -355,7 +324,6 @@ test safe-9.1 {safe interps' deleteHook} {
safe::interpCreate $i -deleteHook "testDelHook arg1 arg2";
list [interp eval $i exit] $res
} {{} {arg1 arg2 a}}
-
test safe-9.2 {safe interps' error in deleteHook} {
set i "a";
catch {safe::interpDelete $i}
@@ -378,22 +346,18 @@ test safe-9.2 {safe interps' error in deleteHook} {
$log \
[safe::setLogCmd $prevlog; unset log];
} {{} {arg1 arg2 a} {{NOTICE for slave a : About to delete} {ERROR for slave a : Delete hook error (being catched)} {NOTICE for slave a : Deleted}} {}}
-
-
test safe-9.3 {dual specification of statics} {
list [catch {safe::interpCreate -stat true -nostat} msg] $msg
} {1 {conflicting values given for -statics and -noStatics}}
-
test safe-9.4 {dual specification of statics} {
# no error shall occur
safe::interpDelete [safe::interpCreate -stat false -nostat]
} {}
-
test safe-9.5 {dual specification of nested} {
list [catch {safe::interpCreate -nested 0 -nestedload} msg] $msg
} {1 {conflicting values given for -nested and -nestedLoadOk}}
-test safe-9.6 {interpConfigure widget like behaviour} {
+test safe-9.6 {interpConfigure widget like behaviour} -body {
# this test shall work, don't try to "fix it" unless
# you *really* know what you are doing (ie you are me :p) -- dl
list [set i [safe::interpCreate \
@@ -410,47 +374,40 @@ test safe-9.6 {interpConfigure widget like behaviour} {
safe::interpConfigure $i]\
[safe::interpConfigure $i -deleteHook toto -nosta -nested 0;
safe::interpConfigure $i]
-} {{-accessPath /foo/bar -statics 0 -nested 1 -deleteHook {foo bar}} {-accessPath /foo/bar} {-nested 1} {-statics 0} {-deleteHook {foo bar}} {-accessPath /blah -statics 1 -nested 1 -deleteHook {foo bar}} {-accessPath /blah -statics 0 -nested 0 -deleteHook toto}}
-
+} -match glob -result {{-accessPath * -statics 0 -nested 1 -deleteHook {foo bar}} {-accessPath *} {-nested 1} {-statics 0} {-deleteHook {foo bar}} {-accessPath * -statics 1 -nested 1 -deleteHook {foo bar}} {-accessPath * -statics 0 -nested 0 -deleteHook toto}}
# testing that nested and statics do what is advertised
# (we use a static package : Tcltest)
if {[catch {package require Tcltest} msg]} {
- puts "This application hasn't been compiled with Tcltest"
- puts "skipping remining safe test that relies on it."
+ testConstraint TcltestPackage 0
} else {
-
+ testConstraint TcltestPackage 1
# we use the Tcltest package , which has no Safe_Init
+}
-test safe-10.1 {testing statics loading} {
+test safe-10.1 {testing statics loading} TcltestPackage {
set i [safe::interpCreate]
list \
[catch {interp eval $i {load {} Tcltest}} msg] \
$msg \
[safe::interpDelete $i];
} {1 {can't use package in a safe interpreter: no Tcltest_SafeInit procedure} {}}
-
-test safe-10.2 {testing statics loading / -nostatics} {
+test safe-10.2 {testing statics loading / -nostatics} TcltestPackage {
set i [safe::interpCreate -nostatics]
list \
[catch {interp eval $i {load {} Tcltest}} msg] \
$msg \
[safe::interpDelete $i];
} {1 {permission denied (static package)} {}}
-
-
-
-test safe-10.3 {testing nested statics loading / no nested by default} {
+test safe-10.3 {testing nested statics loading / no nested by default} TcltestPackage {
set i [safe::interpCreate]
list \
[catch {interp eval $i {interp create x; load {} Tcltest x}} msg] \
$msg \
[safe::interpDelete $i];
} {1 {permission denied (nested load)} {}}
-
-
-test safe-10.4 {testing nested statics loading / -nestedloadok} {
+test safe-10.4 {testing nested statics loading / -nestedloadok} TcltestPackage {
set i [safe::interpCreate -nestedloadok]
list \
[catch {interp eval $i {interp create x; load {} Tcltest x}} msg] \
@@ -458,17 +415,13 @@ test safe-10.4 {testing nested statics loading / -nestedloadok} {
[safe::interpDelete $i];
} {1 {can't use package in a safe interpreter: no Tcltest_SafeInit procedure} {}}
-
-}
-
test safe-11.1 {testing safe encoding} {
set i [safe::interpCreate]
list \
[catch {interp eval $i encoding} msg] \
$msg \
[safe::interpDelete $i];
-} {1 {wrong # args: should be "encoding option ?arg ...?"} {}}
-
+} {1 {wrong # args: should be "encoding option ..."} {}}
test safe-11.2 {testing safe encoding} {
set i [safe::interpCreate]
list \
@@ -476,7 +429,6 @@ test safe-11.2 {testing safe encoding} {
$msg \
[safe::interpDelete $i];
} {1 {wrong # args: should be "encoding system"} {}}
-
test safe-11.3 {testing safe encoding} {
set i [safe::interpCreate]
set result [catch {
@@ -484,7 +436,6 @@ test safe-11.3 {testing safe encoding} {
} msg]
list $result $msg [safe::interpDelete $i]
} {0 1 {}}
-
test safe-11.4 {testing safe encoding} {
set i [safe::interpCreate]
set result [catch {
@@ -492,7 +443,6 @@ test safe-11.4 {testing safe encoding} {
} msg]
list $result $msg [safe::interpDelete $i]
} {0 1 {}}
-
test safe-11.5 {testing safe encoding} {
set i [safe::interpCreate]
list \
@@ -500,8 +450,6 @@ test safe-11.5 {testing safe encoding} {
$msg \
[safe::interpDelete $i];
} {0 foobar {}}
-
-
test safe-11.6 {testing safe encoding} {
set i [safe::interpCreate]
list \
@@ -509,7 +457,6 @@ test safe-11.6 {testing safe encoding} {
$msg \
[safe::interpDelete $i];
} {0 foobar {}}
-
test safe-11.7 {testing safe encoding} {
set i [safe::interpCreate]
list \
@@ -517,8 +464,6 @@ test safe-11.7 {testing safe encoding} {
$msg \
[safe::interpDelete $i];
} {1 {wrong # args: should be "encoding convertfrom ?encoding? data"} {}}
-
-
test safe-11.8 {testing safe encoding} {
set i [safe::interpCreate]
list \
@@ -527,6 +472,48 @@ test safe-11.8 {testing safe encoding} {
[safe::interpDelete $i];
} {1 {wrong # args: should be "encoding convertto ?encoding? data"} {}}
+test safe-12.1 {glob is restricted [Bug 2906841]} -setup {
+ set i [safe::interpCreate]
+} -body {
+ $i eval glob ../*
+} -returnCodes error -cleanup {
+ safe::interpDelete $i
+} -result "permission denied"
+test safe-12.2 {glob is restricted [Bug 2906841]} -setup {
+ set i [safe::interpCreate]
+} -body {
+ $i eval glob -directory .. *
+} -returnCodes error -cleanup {
+ safe::interpDelete $i
+} -result "permission denied"
+test safe-12.3 {glob is restricted [Bug 2906841]} -setup {
+ set i [safe::interpCreate]
+} -body {
+ $i eval glob -join .. *
+} -returnCodes error -cleanup {
+ safe::interpDelete $i
+} -result "permission denied"
+test safe-12.4 {glob is restricted [Bug 2906841]} -setup {
+ set i [safe::interpCreate]
+} -body {
+ $i eval glob -nocomplain ../*
+} -cleanup {
+ safe::interpDelete $i
+} -result {}
+test safe-12.5 {glob is restricted [Bug 2906841]} -setup {
+ set i [safe::interpCreate]
+} -body {
+ $i eval glob -directory .. -nocomplain *
+} -cleanup {
+ safe::interpDelete $i
+} -result {}
+test safe-12.6 {glob is restricted [Bug 2906841]} -setup {
+ set i [safe::interpCreate]
+} -body {
+ $i eval glob -nocomplain -join .. *
+} -cleanup {
+ safe::interpDelete $i
+} -result {}
set ::auto_path $saveAutoPath
# cleanup
diff --git a/tests/scan.test b/tests/scan.test
index 0a70b0f..b37ce0c 100644
--- a/tests/scan.test
+++ b/tests/scan.test
@@ -16,7 +16,8 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-::tcltest::testConstraint 64bitInts [expr {0x80000000 > 0}]
+testConstraint wideIs64bit \
+ [expr {(wide(0x80000000) > 0) && (wide(0x8000000000000000) < 0)}]
test scan-1.1 {BuildCharSet, CharInSet} {
list [scan foo {%[^o]} x] $x
@@ -338,9 +339,10 @@ test scan-4.61 {Tcl_ScanObjCmd, set errors} {
# procedure that returns the range of integers
proc int_range {} {
- for { set MIN_INT 1 } { $MIN_INT > 0 } {} {
+ for { set MIN_INT 1 } { int($MIN_INT) > 0 } {} {
set MIN_INT [expr { $MIN_INT << 1 }]
}
+ set MIN_INT [expr {int($MIN_INT)}]
set MAX_INT [expr { ~ $MIN_INT }]
return [list $MIN_INT $MAX_INT]
}
@@ -415,7 +417,7 @@ test scan-5.11 {integer scanning} {nonPortable} {
list [scan "4294967280 4294967280" "%u %d" a b] $a \
[expr {$b == -16 || $b == 0x7fffffff}]
} {2 4294967280 1}
-test scan-5.12 {integer scanning} {64bitInts} {
+test scan-5.12 {integer scanning} {wideIs64bit} {
set a {}; set b {}; set c {}
list [scan "7810179016327718216,6c63546f6c6c6548,661432506755433062510" \
%ld,%lx,%lo a b c] $a $b $c
@@ -425,6 +427,10 @@ test scan-5.13 {integer scanning and overflow} {
scan {300000000 3000000000 30000000000} {%ld %ld %ld}
} {300000000 3000000000 30000000000}
+test scan-5.14 {integer scanning} {
+ scan 0xff %u
+} 0
+
test scan-6.1 {floating-point scanning} {
set a {}; set b {}; set c {}; set d {}
list [scan "2.1 -3.0e8 .99962 a" "%f%g%e%f" a b c d] $a $b $c $d
@@ -449,10 +455,10 @@ test scan-6.5 {floating-point scanning} {
set a {}; set b {}; set c {}; set d {}
list [scan "4.6 99999.7 876.43e-1 118" "%f %f %f %e" a b c d] $a $b $c $d
} {4 4.6 99999.7 87.643 118.0}
-test scan-6.6 {floating-point scanning} {eformat} {
+test scan-6.6 {floating-point scanning} {
set a {}; set b {}; set c {}; set d {}
list [scan "1.2345 697.0e-3 124 .00005" "%f %e %f %e" a b c d] $a $b $c $d
-} {4 1.2345 0.697 124.0 5e-05}
+} {4 1.2345 0.697 124.0 5e-5}
test scan-6.7 {floating-point scanning} {
set a {}; set b {}; set c {}; set d {}
list [scan "4.6abc" "%f %f %f %f" a b c d] $a $b $c $d
@@ -602,6 +608,12 @@ test scan-10.5 {miscellaneous tests} {
set arr(2) {}
list [catch {scan ab%c14 ab%%c%d arr(2)} msg] $msg $arr(2)
} {0 1 14}
+test scan-10.6 {miscellaneous tests} {
+ scan 5a {%i%[a]}
+} {5 a}
+test scan-10.7 {miscellaneous tests} {
+ scan {5 a} {%i%[a]}
+} {5 {}}
test scan-11.1 {alignment in results array (TCL_ALIGN)} {
scan "123 13.6" "%s %f" a b
@@ -676,6 +688,82 @@ test scan-13.8 {Tcl_ScanObjCmd, inline XPG case lots of arguments} {
list [llength $msg] [lindex $msg 99] [lindex $msg 4] [lindex $msg 199]
} {200 10 20 30}
+# Big test for correct ordering of data in [expr]
+
+proc testIEEE {} {
+ variable ieeeValues
+ binary scan [binary format dd -1.0 1.0] c* c
+ switch -exact -- $c {
+ {0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
+ # little endian
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \
+ ieeeValues(-Infinity)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \
+ ieeeValues(-Normal)
+ binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
+ ieeeValues(-Subnormal)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
+ ieeeValues(-0)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+0)
+ binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
+ ieeeValues(+Subnormal)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \
+ ieeeValues(+Normal)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
+ ieeeValues(+Infinity)
+ binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
+ ieeeValues(NaN)
+ set ieeeValues(littleEndian) 1
+ return 1
+ }
+ {-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
+ binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Infinity)
+ binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Normal)
+ binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Subnormal)
+ binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-0)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+0)
+ binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Subnormal)
+ binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Normal)
+ binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Infinity)
+ binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(NaN)
+ set ieeeValues(littleEndian) 0
+ return 1
+ }
+ default {
+ return 0
+ }
+ }
+}
+
+testConstraint ieeeFloatingPoint [testIEEE]
+
+# scan infinities - not working
+
+test scan-14.1 {infinity} ieeeFloatingPoint {
+ scan Inf %g d
+ set d
+} Inf
+test scan-14.2 {infinity} ieeeFloatingPoint {
+ scan -Inf %g d
+ set d
+} -Inf
+
+# TODO - also need to scan NaN's
+
# cleanup
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/security.test b/tests/security.test
index 26e7ec8..4a73160 100644
--- a/tests/security.test
+++ b/tests/security.test
@@ -18,7 +18,7 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
# If this proc becomes invoked, then there is a bug
proc BUG {args} {
- set ::BUG 1
+ set ::BUG 1
}
# Check and Clear the bug flag (to do before each test)
@@ -31,7 +31,7 @@ proc CB {} {
}
-test sec-1.1 {tcl_endOfPreviousWord} {
+test security-1.1 {tcl_endOfPreviousWord} {
catch {tcl_startOfPreviousWord x {[BUG]}}
CB
} 0
@@ -39,14 +39,3 @@ test sec-1.1 {tcl_endOfPreviousWord} {
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/set-old.test b/tests/set-old.test
index 29e0002..2ef4019 100644
--- a/tests/set-old.test
+++ b/tests/set-old.test
@@ -548,7 +548,7 @@ test set-old-8.38.6 {array command, set with non-existent namespace} {
} {1 {can't set "bogusnamespace::var": parent namespace doesn't exist}}
test set-old-8.38.7 {array command, set with non-existent namespace} {
list [catch {array set bogusnamespace::var(0) {a b}} msg] $msg
-} {1 {can't set "bogusnamespace::var(0)": variable isn't array}}
+} {1 {can't set "bogusnamespace::var(0)": parent namespace doesn't exist}}
test set-old-8.39 {array command, size option} {
catch {unset a}
array size a
diff --git a/tests/set.test b/tests/set.test
index 8bfa9d2..9e0ddc0 100644
--- a/tests/set.test
+++ b/tests/set.test
@@ -11,10 +11,12 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2
namespace import -force ::tcltest::*
}
+testConstraint testset2 [llength [info commands testset2]]
+
catch {unset x}
catch {unset i}
@@ -188,9 +190,9 @@ test set-1.22 {TclCompileSetCmd: doing assignment, large int} {
} 200000
test set-1.23 {TclCompileSetCmd: doing assignment, formatted int != int} {
set i 25
- set i 000012345 ;# an octal literal == 5349 decimal
+ set i 0o00012345 ;# an octal literal == 5349 decimal
list $i [incr i]
-} {000012345 5350}
+} {0o00012345 5350}
test set-1.24 {TclCompileSetCmd: too many arguments} {
set i 10
@@ -231,7 +233,8 @@ test set-1.26 {TclCompileSetCmd: various array constructs} {
{b c} foo 51}]; # " just a matching end quote
test set-2.1 {set command: runtime error, bad variable name} {
- list [catch {set {"foo}} msg] $msg $errorInfo
+ unset -nocomplain {"foo}
+ list [catch {set {"foo}} msg] $msg $::errorInfo
} {1 {can't read ""foo": no such variable} {can't read ""foo": no such variable
while executing
"set {"foo}"}}
@@ -245,13 +248,14 @@ test set-2.3 {set command: runtime error, errors in reading variables} {
set a(6) 44
list [catch {set a(18)} msg] $msg
} {1 {can't read "a(18)": no such element in array}}
-test set-2.4 {set command: runtime error, readonly variable} {
+test set-2.4 {set command: runtime error, readonly variable} -body {
proc readonly args {error "variable is read-only"}
set x 123
trace var x w readonly
- list [catch {set x 1} msg] $msg $errorInfo
-} {1 {can't set "x": variable is read-only} {can't set "x": variable is read-only
+ list [catch {set x 1} msg] $msg $::errorInfo
+} -match glob -result {1 {can't set "x": variable is read-only} {*variable is read-only
while executing
+*
"set x 1"}}
test set-2.5 {set command: runtime error, basic array operations} {
list [catch {set a(other)} msg] $msg
@@ -461,9 +465,9 @@ test set-3.22 {uncompiled set command: doing assignment, large int} {
test set-3.23 {uncompiled set command: doing assignment, formatted int != int} {
set z set
$z i 25
- $z i 000012345 ;# an octal literal == 5349 decimal
+ $z i 0o00012345 ;# an octal literal == 5349 decimal
list $i [incr i]
-} {000012345 5350}
+} {0o00012345 5350}
test set-3.24 {uncompiled set command: too many arguments} {
set z set
@@ -473,8 +477,9 @@ test set-3.24 {uncompiled set command: too many arguments} {
} {wrong # args: should be "set varName ?newValue?"}
test set-4.1 {uncompiled set command: runtime error, bad variable name} {
+ unset -nocomplain {"foo}
set z set
- list [catch {$z {"foo}} msg] $msg $errorInfo
+ list [catch {$z {"foo}} msg] $msg $::errorInfo
} {1 {can't read ""foo": no such variable} {can't read ""foo": no such variable
while executing
"$z {"foo}"}}
@@ -490,14 +495,15 @@ test set-4.3 {uncompiled set command: runtime error, errors in reading variables
$z a(6) 44
list [catch {$z a(18)} msg] $msg
} {1 {can't read "a(18)": no such element in array}}
-test set-4.4 {uncompiled set command: runtime error, readonly variable} {
+test set-4.4 {uncompiled set command: runtime error, readonly variable} -body {
set z set
proc readonly args {error "variable is read-only"}
$z x 123
trace var x w readonly
- list [catch {$z x 1} msg] $msg $errorInfo
-} {1 {can't set "x": variable is read-only} {can't set "x": variable is read-only
+ list [catch {$z x 1} msg] $msg $::errorInfo
+} -match glob -result {1 {can't set "x": variable is read-only} {*variable is read-only
while executing
+*
"$z x 1"}}
test set-4.5 {uncompiled set command: runtime error, basic array operations} {
set z set
@@ -508,6 +514,13 @@ test set-4.6 {set command: runtime error, basic array operations} {
list [catch {$z a} msg] $msg
} {1 {can't read "a": variable is array}}
+test set-5.1 {error on malformed array name} testset2 {
+ unset -nocomplain z
+ catch {testset2 z(a) b} msg
+ catch {testset2 z(b) a} msg1
+ list $msg $msg1
+} {{can't read "z(a)(b)": variable isn't array} {can't read "z(b)(a)": variable isn't array}}
+
# cleanup
catch {unset a}
catch {unset b}
diff --git a/tests/socket.test b/tests/socket.test
index 96b81b8..0ae5abd 100644
--- a/tests/socket.test
+++ b/tests/socket.test
@@ -12,46 +12,46 @@
# Running socket tests with a remote server:
# ------------------------------------------
-#
+#
# Some tests in socket.test depend on the existence of a remote server to
# which they connect. The remote server must be an instance of tcltest and it
# must run the script found in the file "remote.tcl" in this directory. You
# can start the remote server on any machine reachable from the machine on
# which you want to run the socket tests, by issuing:
-#
+#
# tcltest remote.tcl -port 2048 # Or choose another port number.
-#
+#
# If the machine you are running the remote server on has several IP
# interfaces, you can choose which interface the server listens on for
# connections by specifying the -address command line flag, so:
-#
+#
# tcltest remote.tcl -address your.machine.com
-#
+#
# These options can also be set by environment variables. On Unix, you can
# type these commands to the shell from which the remote server is started:
-#
+#
# shell% setenv serverPort 2048
# shell% setenv serverAddress your.machine.com
-#
+#
# and subsequently you can start the remote server with:
-#
+#
# tcltest remote.tcl
-#
+#
# to have it listen on port 2048 on the interface your.machine.com.
-#
+#
# When the server starts, it prints out a detailed message containing its
# configuration information, and it will block until killed with a Ctrl-C.
# Once the remote server exists, you can run the tests in socket.test with
# the server by setting two Tcl variables:
-#
+#
# % set remoteServerIP <name or address of machine on which server runs>
# % set remoteServerPort 2048
-#
+#
# These variables are also settable from the environment. On Unix, you can:
-#
+#
# shell% setenv remoteServerIP machine.where.server.runs
# shell% senetv remoteServerPort 2048
-#
+#
# The preamble of the socket.test file checks to see if the variables are set
# either in Tcl or in the environment; if they are, it attempts to connect to
# the server. If the connection is successful, the tests using the remote
@@ -91,7 +91,7 @@ if {![info exists remoteServerPort]} {
#
set doTestsWithRemoteServer 1
-if {![info exists remoteServerIP] && ($tcl_platform(platform) != "macintosh")} {
+if {![info exists remoteServerIP]} {
set remoteServerIP 127.0.0.1
}
if {($doTestsWithRemoteServer == 1) && (![info exists remoteServerPort])} {
@@ -109,45 +109,43 @@ set remoteProcChan ""
set commandSocket ""
if {$doTestsWithRemoteServer} {
catch {close $commandSocket}
- if {[catch {set commandSocket [socket $remoteServerIP \
- $remoteServerPort]}] != 0} {
- if {[info commands exec] == ""} {
- set noRemoteTestReason "can't exec"
- set doTestsWithRemoteServer 0
- } else {
- set remoteServerIP 127.0.0.1
- # Be *extra* careful in case this file is sourced from
- # a directory other than the current one...
- set remoteFile [file join [pwd] [file dirname [info script]] \
- remote.tcl]
- if {[catch {set remoteProcChan \
- [open "|[list [interpreter] $remoteFile \
- -serverIsSilent \
- -port $remoteServerPort \
- -address $remoteServerIP]" \
- w+]} \
- msg] == 0} {
- after 1000
- if {[catch {set commandSocket [socket $remoteServerIP \
- $remoteServerPort]} msg] == 0} {
- fconfigure $commandSocket -translation crlf -buffering line
- } else {
- set noRemoteTestReason $msg
- set doTestsWithRemoteServer 0
- }
+ if {![catch {
+ set commandSocket [socket $remoteServerIP $remoteServerPort]
+ }]} then {
+ fconfigure $commandSocket -translation crlf -buffering line
+ } elseif {![testConstraint exec]} {
+ set noRemoteTestReason "can't exec"
+ set doTestsWithRemoteServer 0
+ } else {
+ set remoteServerIP 127.0.0.1
+ # Be *extra* careful in case this file is sourced from
+ # a directory other than the current one...
+ set remoteFile [file join [pwd] [file dirname [info script]] \
+ remote.tcl]
+ if {![catch {
+ set remoteProcChan [open "|[list \
+ [interpreter] $remoteFile -serverIsSilent \
+ -port $remoteServerPort -address $remoteServerIP]" w+]
+ } msg]} then {
+ after 1000
+ if {[catch {
+ set commandSocket [socket $remoteServerIP $remoteServerPort]
+ } msg] == 0} then {
+ fconfigure $commandSocket -translation crlf -buffering line
} else {
- set noRemoteTestReason "$msg [interpreter]"
+ set noRemoteTestReason $msg
set doTestsWithRemoteServer 0
}
+ } else {
+ set noRemoteTestReason "$msg [interpreter]"
+ set doTestsWithRemoteServer 0
}
- } else {
- fconfigure $commandSocket -translation crlf -buffering line
}
}
# Some tests are run only if we are doing testing against a remote server.
-set ::tcltest::testConstraints(doTestsWithRemoteServer) $doTestsWithRemoteServer
-if {$doTestsWithRemoteServer == 0} {
+testConstraint doTestsWithRemoteServer $doTestsWithRemoteServer
+if {!$doTestsWithRemoteServer} {
if {[string first s $::tcltest::verbose] != -1} {
puts "Skipping tests with remote server. See tests/socket.test for"
puts "information on how to run remote server."
@@ -160,14 +158,13 @@ if {$doTestsWithRemoteServer == 0} {
# remote server.
#
-if {$doTestsWithRemoteServer == 1} {
+if {[testConstraint doTestsWithRemoteServer]} {
proc sendCommand {c} {
global commandSocket
if {[eof $commandSocket]} {
error "remote server disappeared"
}
-
if {[catch {puts $commandSocket $c} msg]} {
error "remote server disappaered: $msg"
}
@@ -199,17 +196,13 @@ test socket-1.1 {arg parsing for socket command} {socket} {
} {1 {no argument given for -server option}}
test socket-1.2 {arg parsing for socket command} {socket} {
list [catch {socket -server foo} msg] $msg
-} {1 {wrong # args: should be either:
-socket ?-myaddr addr? ?-myport myport? ?-async? host port
-socket -server command ?-myaddr addr? port}}
+} {1 {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}}
test socket-1.3 {arg parsing for socket command} {socket} {
list [catch {socket -myaddr} msg] $msg
} {1 {no argument given for -myaddr option}}
test socket-1.4 {arg parsing for socket command} {socket} {
list [catch {socket -myaddr 127.0.0.1} msg] $msg
-} {1 {wrong # args: should be either:
-socket ?-myaddr addr? ?-myport myport? ?-async? host port
-socket -server command ?-myaddr addr? port}}
+} {1 {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}}
test socket-1.5 {arg parsing for socket command} {socket} {
list [catch {socket -myport} msg] $msg
} {1 {no argument given for -myport option}}
@@ -218,25 +211,19 @@ test socket-1.6 {arg parsing for socket command} {socket} {
} {1 {expected integer but got "xxxx"}}
test socket-1.7 {arg parsing for socket command} {socket} {
list [catch {socket -myport 2522} msg] $msg
-} {1 {wrong # args: should be either:
-socket ?-myaddr addr? ?-myport myport? ?-async? host port
-socket -server command ?-myaddr addr? port}}
+} {1 {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}}
test socket-1.8 {arg parsing for socket command} {socket} {
list [catch {socket -froboz} msg] $msg
} {1 {bad option "-froboz": must be -async, -myaddr, -myport, or -server}}
test socket-1.9 {arg parsing for socket command} {socket} {
list [catch {socket -server foo -myport 2521 3333} msg] $msg
-} {1 {Option -myport is not valid for servers}}
+} {1 {option -myport is not valid for servers}}
test socket-1.10 {arg parsing for socket command} {socket} {
list [catch {socket host 2528 -junk} msg] $msg
-} {1 {wrong # args: should be either:
-socket ?-myaddr addr? ?-myport myport? ?-async? host port
-socket -server command ?-myaddr addr? port}}
+} {1 {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}}
test socket-1.11 {arg parsing for socket command} {socket} {
list [catch {socket -server callback 2520 --} msg] $msg
-} {1 {wrong # args: should be either:
-socket ?-myaddr addr? ?-myport myport? ?-async? host port
-socket -server command ?-myaddr addr? port}}
+} {1 {wrong # args: should be "socket ?-myaddr addr? ?-myport myport? ?-async? host port" or "socket -server command ?-myaddr addr? port"}}
test socket-1.12 {arg parsing for socket command} {socket} {
list [catch {socket foo badport} msg] $msg
} {1 {expected integer but got "badport"}}
@@ -284,7 +271,7 @@ test socket-2.1 {tcp connection} {socket stdio} {
if [info exists port] {
incr port
-} else {
+} else {
set port [expr 2048 + [pid]%1024]
}
test socket-2.2 {tcp connection with client port specified} {socket stdio} {
@@ -486,7 +473,7 @@ test socket-2.8 {echo server, loop 50 times, single connection} -constraints {so
global x
close $s
set x done
- } else {
+ } else {
incr i
puts $s $l
}
@@ -577,6 +564,7 @@ test socket-2.11 {detecting new data} {socket} {
fconfigure $sock -blocking 1
puts $s2 two
flush $s2
+ after 500
fconfigure $sock -blocking 0
lappend result c:[gets $sock]
fconfigure $sock -blocking 1
@@ -591,7 +579,7 @@ test socket-3.1 {socket conflict} {socket stdio} {
file delete $path(script)
set f [open $path(script) w]
puts $f {
- set f [socket -server accept 0]
+ set f [socket -server accept -myaddr 127.0.0.1 0]
puts ready
puts [lindex [fconfigure $f -sockname] 2]
gets stdin
@@ -601,7 +589,7 @@ test socket-3.1 {socket conflict} {socket stdio} {
set f [open "|[list [interpreter] $path(script)]" r+]
gets $f
gets $f listen
- set x [list [catch {socket -server accept $listen} msg] \
+ set x [list [catch {socket -server accept -myaddr 127.0.0.1 $listen} msg] \
$msg]
puts $f bye
close $f
@@ -615,7 +603,7 @@ test socket-3.2 {server with several clients} {socket stdio} {
set t2 [after 31000 "set x timed_out"]
set t3 [after 32000 "set x timed_out"]
set counter 0
- set s [socket -server accept 0]
+ set s [socket -server accept -myaddr 127.0.0.1 0]
proc accept {s a p} {
fileevent $s readable [list echo $s]
fconfigure $s -buffering line
@@ -706,7 +694,7 @@ test socket-4.1 {server with several clients} {socket stdio} {
set t1 [after 30000 "set x timed_out"]
set t2 [after 31000 "set x timed_out"]
set t3 [after 32000 "set x timed_out"]
- set s [socket -server accept 0]
+ set s [socket -server accept -myaddr 127.0.0.1 0]
set listen [lindex [fconfigure $s -sockname] 2]
puts $p1 $listen
puts $p2 $listen
@@ -732,7 +720,7 @@ test socket-4.1 {server with several clients} {socket stdio} {
} {{p1 bye done} {p2 bye done} {p3 bye done}}
test socket-4.2 {byte order problems, socket numbers, htons} {socket} {
set x ok
- if {[catch {socket -server dodo 0x3000} msg]} {
+ if {[catch {socket -server dodo -myaddr 127.0.0.1 0x3000} msg]} {
set x $msg
} else {
close $msg
@@ -741,7 +729,7 @@ test socket-4.2 {byte order problems, socket numbers, htons} {socket} {
} ok
test socket-5.1 {byte order problems, socket numbers, htons} \
- {socket unixOnly notRoot} {
+ {socket unix notRoot} {
set x {couldn't open socket: not owner}
if {![catch {socket -server dodo 0x1} msg]} {
set x {htons problem, should be disallowed, are you running as SU?}
@@ -758,7 +746,7 @@ test socket-5.2 {byte order problems, socket numbers, htons} {socket} {
set x
} {couldn't open socket: port number too high}
test socket-5.3 {byte order problems, socket numbers, htons} \
- {socket unixOnly notRoot} {
+ {socket unix notRoot} {
set x {couldn't open socket: not owner}
if {![catch {socket -server dodo 21} msg]} {
set x {htons problem, should be disallowed, are you running as SU?}
@@ -767,8 +755,14 @@ test socket-5.3 {byte order problems, socket numbers, htons} \
set x
} {couldn't open socket: not owner}
-test socket-6.1 {accept callback error} {socket stdio} {
+test socket-6.1 {accept callback error} -constraints {socket stdio} -setup {
+ proc myHandler {msg options} {
+ variable x $msg
+ }
+ set handler [interp bgerror {}]
+ interp bgerror {} [namespace which myHandler]
file delete $path(script)
+} -body {
set f [open $path(script) w]
puts $f {
gets stdin port
@@ -776,21 +770,18 @@ test socket-6.1 {accept callback error} {socket stdio} {
}
close $f
set f [open "|[list [interpreter] $path(script)]" r+]
- proc bgerror args {
- global x
- set x $args
- }
proc accept {s a p} {expr 10 / 0}
- set s [socket -server accept 0]
+ set s [socket -server accept -myaddr 127.0.0.1 0]
puts $f [lindex [fconfigure $s -sockname] 2]
close $f
set timer [after 10000 "set x timed_out"]
vwait x
after cancel $timer
close $s
- rename bgerror {}
set x
-} {{divide by zero}}
+} -cleanup {
+ interp bgerror {} $handler
+} -result {divide by zero}
test socket-7.1 {testing socket specific options} {socket stdio} {
file delete $path(script)
@@ -848,21 +839,21 @@ test socket-7.2 {testing socket specific options} {socket stdio} {
[expr {[lindex $p 2] == $listen}]
} {3 1 0}
test socket-7.3 {testing socket specific options} {socket} {
- set s [socket -server accept 0]
+ set s [socket -server accept -myaddr 127.0.0.1 0]
set l [fconfigure $s]
close $s
update
llength $l
} 14
test socket-7.4 {testing socket specific options} {socket} {
- set s [socket -server accept 0]
+ set s [socket -server accept -myaddr 127.0.0.1 0]
proc accept {s a p} {
global x
set x [fconfigure $s -sockname]
close $s
}
set listen [lindex [fconfigure $s -sockname] 2]
- set s1 [socket [info hostname] $listen]
+ set s1 [socket 127.0.0.1 $listen]
set timer [after 10000 "set x timed_out"]
vwait x
after cancel $timer
@@ -904,14 +895,14 @@ test socket-8.1 {testing -async flag on sockets} {socket} {
# problem, please email jyl@eng.sun.com. We have not observed this
# failure on Solaris 2.5, so another option (instead of installing
# these patches) is to upgrade to Solaris 2.5.
- set s [socket -server accept 0]
+ set s [socket -server accept -myaddr 127.0.0.1 0]
proc accept {s a p} {
global x
puts $s bye
close $s
set x done
}
- set s1 [socket -async [info hostname] [lindex [fconfigure $s -sockname] 2]]
+ set s1 [socket -async 127.0.0.1 [lindex [fconfigure $s -sockname] 2]]
vwait x
set z [gets $s1]
close $s
@@ -941,8 +932,8 @@ test socket-9.1 {testing spurious events} {socket} {
fconfigure $s -buffering none -blocking off
fileevent $s readable [list readlittle $s]
}
- set s [socket -server accept 0]
- set c [socket [info hostname] [lindex [fconfigure $s -sockname] 2]]
+ set s [socket -server accept -myaddr 127.0.0.1 0]
+ set c [socket 127.0.0.1 [lindex [fconfigure $s -sockname] 2]]
puts -nonewline $c 01234567890123456789012345678901234567890123456789
close $c
set timer [after 10000 "set done timed_out"]
@@ -958,7 +949,7 @@ test socket-9.2 {testing async write, fileevents, flush on close} {socket} {
for {set i 0} {$i < 16} {incr i} {
set secondblock "b$secondblock$secondblock"
}
- set l [socket -server accept 0]
+ set l [socket -server accept -myaddr 127.0.0.1 0]
proc accept {s a p} {
fconfigure $s -blocking 0 -translation lf -buffersize 16384 \
-buffering line
@@ -979,7 +970,7 @@ test socket-9.2 {testing async write, fileevents, flush on close} {socket} {
puts -nonewline $s $secondblock
close $s
}
- set s [socket [info hostname] [lindex [fconfigure $l -sockname] 2]]
+ set s [socket 127.0.0.1 [lindex [fconfigure $l -sockname] 2]]
fconfigure $s -blocking 0 -trans lf -buffering line
set count 0
puts $s hello
@@ -1018,7 +1009,7 @@ test socket-9.3 {testing EOF stickyness} {socket} {
set done true
set count {timer went off, eof is not sticky}
close $c
- }
+ }
set count 0
set done false
proc write_then_close {s} {
@@ -1029,8 +1020,8 @@ test socket-9.3 {testing EOF stickyness} {socket} {
fconfigure $s -buffering line -translation lf
fileevent $s writable "write_then_close $s"
}
- set s [socket -server accept 0]
- set c [socket [info hostname] [lindex [fconfigure $s -sockname] 2]]
+ set s [socket -server accept -myaddr 127.0.0.1 0]
+ set c [socket 127.0.0.1 [lindex [fconfigure $s -sockname] 2]]
fconfigure $c -blocking off -buffering line -translation lf
fileevent $c readable "count_to_eof $c"
set timer [after 1000 timerproc]
@@ -1041,17 +1032,26 @@ test socket-9.3 {testing EOF stickyness} {socket} {
removeFile script
-test socket-10.1 {testing socket accept callback error handling} {socket} {
- set goterror 0
- proc bgerror args {global goterror; set goterror 1}
- set s [socket -server accept 0]
+test socket-10.1 {testing socket accept callback error handling} -constraints {
+ socket
+} -setup {
+ variable goterror 0
+ proc myHandler {msg options} {
+ variable goterror 1
+ }
+ set handler [interp bgerror {}]
+ interp bgerror {} [namespace which myHandler]
+} -body {
+ set s [socket -server accept -myaddr 127.0.0.1 0]
proc accept {s a p} {close $s; error}
set c [socket 127.0.0.1 [lindex [fconfigure $s -sockname] 2]]
vwait goterror
close $s
close $c
set goterror
-} 1
+} -cleanup {
+ interp bgerror {} $handler
+} -result 1
test socket-11.1 {tcp connection} {socket doTestsWithRemoteServer} {
sendCommand {
@@ -1153,15 +1153,9 @@ test socket-11.5 {remote echo, 50 lines} {socket doTestsWithRemoteServer} {
sendCommand {close $socket10_7_test_server}
set cnt
} 50
-# Macintosh sockets can have more than one server per port
-if {$tcl_platform(platform) == "macintosh"} {
- set conflictResult {0 2836}
-} else {
- set conflictResult {1 {couldn't open socket: address already in use}}
-}
test socket-11.6 {socket conflict} {socket doTestsWithRemoteServer} {
- set s1 [socket -server accept 2836]
- if {[catch {set s2 [socket -server accept 2836]} msg]} {
+ set s1 [socket -server accept -myaddr 127.0.0.1 2836]
+ if {[catch {set s2 [socket -server accept -myaddr 127.0.0.1 2836]} msg]} {
set result [list 1 $msg]
} else {
set result [list 0 [lindex [fconfigure $s2 -sockname] 2]]
@@ -1169,7 +1163,7 @@ test socket-11.6 {socket conflict} {socket doTestsWithRemoteServer} {
}
close $s1
set result
-} $conflictResult
+} {1 {couldn't open socket: address already in use}}
test socket-11.7 {server with several clients} {socket doTestsWithRemoteServer} {
sendCommand {
set socket10_9_test_server [socket -server accept 2836]
@@ -1205,7 +1199,7 @@ test socket-11.7 {server with several clients} {socket doTestsWithRemoteServer}
close $s3
sendCommand {close $socket10_9_test_server}
set i
-} 100
+} 100
test socket-11.8 {client with several servers} {socket doTestsWithRemoteServer} {
sendCommand {
set s1 [socket -server "accept 4003" 4003]
@@ -1232,13 +1226,17 @@ test socket-11.8 {client with several servers} {socket doTestsWithRemoteServer}
}
set l
} {4003 {} 1 4004 {} 1 4005 {} 1}
-test socket-11.9 {accept callback error} {socket doTestsWithRemoteServer} {
+test socket-11.9 {accept callback error} -constraints {
+ socket doTestsWithRemoteServer
+} -setup {
+ proc myHandler {msg options} {
+ variable x $msg
+ }
+ set handler [interp bgerror {}]
+ interp bgerror {} [namespace which myHandler]
+} -body {
set s [socket -server accept 2836]
proc accept {s a p} {expr 10 / 0}
- proc bgerror args {
- global x
- set x $args
- }
if {[catch {sendCommand {
set peername [fconfigure $callerSocket -peername]
set s [socket [lindex $peername 0] 2836]
@@ -1251,9 +1249,10 @@ test socket-11.9 {accept callback error} {socket doTestsWithRemoteServer} {
vwait x
after cancel $timer
close $s
- rename bgerror {}
set x
-} {{divide by zero}}
+} -cleanup {
+ interp bgerror {} $handler
+} -result {divide by zero}
test socket-11.10 {testing socket specific options} {socket doTestsWithRemoteServer} {
sendCommand {
set socket10_12_test_server [socket -server accept 2836]
@@ -1307,7 +1306,6 @@ test socket-11.11 {testing spurious events} {socket doTestsWithRemoteServer} {
sendCommand {close $socket10_13_test_server}
list $spurious $len $done
} {0 2690 1}
-
test socket-11.12 {testing EOF stickyness} {socket doTestsWithRemoteServer} {
set counter 0
set done 0
@@ -1341,7 +1339,6 @@ test socket-11.12 {testing EOF stickyness} {socket doTestsWithRemoteServer} {
sendCommand {close $socket10_14_test_server}
set done
} {EOF is sticky}
-
test socket-11.13 {testing async write, async flush, async close} \
{socket doTestsWithRemoteServer} {
proc readit {s} {
@@ -1420,7 +1417,7 @@ test socket-12.1 {testing inheritance of server sockets} {socket stdio exec} {
set f [open $path(script2) w]
puts $f [list set tcltest [interpreter]]
puts -nonewline $f {
- set f [socket -server accept 0]
+ set f [socket -server accept -myaddr 127.0.0.1 0]
puts [lindex [fconfigure $f -sockname] 2]
proc accept { file addr port } {
close $file
@@ -1433,7 +1430,7 @@ test socket-12.1 {testing inheritance of server sockets} {socket stdio exec} {
vwait forever
}
close $f
-
+
# Launch script2 and wait 5 seconds
### exec [interpreter] script2 &
@@ -1490,7 +1487,7 @@ test socket-12.2 {testing inheritance of client sockets} {socket stdio exec} {
# Create the server socket
- set server [socket -server accept 0]
+ set server [socket -server accept -myaddr 127.0.0.1 0]
proc accept { file host port } {
# When the client connects, establish the read handler
global server
@@ -1556,7 +1553,7 @@ test socket-12.3 {testing inheritance of accepted sockets} {socket stdio exec} {
set f [open $path(script2) w]
puts $f [list set tcltest [interpreter]]
puts -nonewline $f {
- set server [socket -server accept 0]
+ set server [socket -server accept -myaddr 127.0.0.1 0]
puts stdout [lindex [fconfigure $server -sockname] 2]
proc accept { file host port } }
puts $f \{
@@ -1568,7 +1565,7 @@ test socket-12.3 {testing inheritance of accepted sockets} {socket stdio exec} {
puts $f {
after 1000 exit
}
- puts $f \}
+ puts $f \}
puts $f {
vwait forever
}
@@ -1617,7 +1614,7 @@ test socket-12.3 {testing inheritance of accepted sockets} {socket stdio exec} {
}
return
}
-
+
vwait x
close $p
@@ -1625,37 +1622,33 @@ test socket-12.3 {testing inheritance of accepted sockets} {socket stdio exec} {
} {accepted socket was not inherited}
test socket-13.1 {Testing use of shared socket between two threads} \
- -constraints {socket testthread} -setup {
-
+ -constraints {socket testthread} -setup {
threadReap
-
set path(script) [makeFile {
- set f [socket -server accept 0]
- set listen [lindex [fconfigure $f -sockname] 2]
- proc accept {s a p} {
+ set f [socket -server accept -myaddr 127.0.0.1 0]
+ set listen [lindex [fconfigure $f -sockname] 2]
+ proc accept {s a p} {
fileevent $s readable [list echo $s]
fconfigure $s -buffering line
}
- proc echo {s} {
- global i
+ proc echo {s} {
+ global i
set l [gets $s]
if {[eof $s]} {
global x
close $s
set x done
- } else {
- incr i
+ } else {
+ incr i
puts $s $l
}
- }
- set i 0
- vwait x
- close $f
-
- # thread cleans itself up.
- testthread exit
+ }
+ set i 0
+ vwait x
+ close $f
+ # thread cleans itself up.
+ testthread exit
} script]
-
} -body {
# create a thread
set serverthread [testthread create [list source $path(script) ] ]
@@ -1668,8 +1661,8 @@ test socket-13.1 {Testing use of shared socket between two threads} \
fconfigure $s -buffering line
catch {
- puts $s "hello"
- gets $s result
+ puts $s "hello"
+ gets $s result
}
close $s
update
diff --git a/tests/source.test b/tests/source.test
index 3a1454c..9162e8e 100644
--- a/tests/source.test
+++ b/tests/source.test
@@ -18,12 +18,7 @@ if {[catch {package require tcltest 2.1}]} {
}
namespace eval ::tcl::test::source {
- namespace import ::tcltest::test
- namespace import ::tcltest::testConstraint
- namespace import ::tcltest::cleanupTests
- namespace import ::tcltest::makeFile
- namespace import ::tcltest::removeFile
- namespace import ::tcltest::customMatch
+ namespace import ::tcltest::*
test source-1.1 {source command} -setup {
set x "old x value"
@@ -40,7 +35,6 @@ test source-1.1 {source command} -setup {
} -cleanup {
removeFile source.file
} -result {22 33 44}
-
test source-1.2 {source command} -setup {
set sourcefile [makeFile {list result} source.file]
} -body {
@@ -48,7 +42,6 @@ test source-1.2 {source command} -setup {
} -cleanup {
removeFile source.file
} -result result
-
test source-1.3 {source command} -setup {
set sourcefile [makeFile {} source.file]
set fd [open $sourcefile w]
@@ -92,7 +85,6 @@ test source-2.3 {source error conditions} -setup {
(file "*source.file" line 3)
invoked from within
"source $sourcefile"}]
-
test source-2.4 {source error conditions} -setup {
set sourcefile [makeFile {break} source.file]
} -body {
@@ -100,7 +92,6 @@ test source-2.4 {source error conditions} -setup {
} -cleanup {
removeFile source.file
} -returnCodes break
-
test source-2.5 {source error conditions} -setup {
set sourcefile [makeFile {continue} source.file]
} -body {
@@ -108,7 +99,6 @@ test source-2.5 {source error conditions} -setup {
} -cleanup {
removeFile source.file
} -returnCodes continue
-
test source-2.6 {source error conditions} -setup {
set sourcefile [makeFile {} _non_existent_]
removeFile _non_existent_
@@ -118,7 +108,6 @@ test source-2.6 {source error conditions} -setup {
{couldn't read file "*_non_existent_": no such file or directory} \
{POSIX ENOENT {no such file or directory}}]
-
test source-3.1 {return in middle of source file} -setup {
set sourcefile [makeFile {
set x new-x
@@ -133,7 +122,6 @@ test source-3.1 {return in middle of source file} -setup {
} -cleanup {
removeFile source.file
} -result {new-x old-y allDone}
-
test source-3.2 {return with special code etc.} -setup {
set sourcefile [makeFile {
set x new-x
@@ -145,7 +133,6 @@ test source-3.2 {return with special code etc.} -setup {
} -cleanup {
removeFile source.file
} -returnCodes break -result {Silly result}
-
test source-3.3 {return with special code etc.} -setup {
set sourcefile [makeFile {
set x new-x
@@ -159,7 +146,6 @@ test source-3.3 {return with special code etc.} -setup {
} -result {1 {Simulated error} {Simulated error
while executing
"source $sourcefile"} NONE}
-
test source-3.4 {return with special code etc.} -setup {
set sourcefile [makeFile {
set x new-x
@@ -173,7 +159,6 @@ test source-3.4 {return with special code etc.} -setup {
} -result {1 {} {Simulated errorInfo stuff
invoked from within
"source $sourcefile"} NONE}
-
test source-3.5 {return with special code etc.} -setup {
set sourcefile [makeFile {
set x new-x
@@ -189,110 +174,6 @@ test source-3.5 {return with special code etc.} -setup {
invoked from within
"source $sourcefile"} {a b c}}
-
-# Test for the Macintosh specfic features of the source command
-test source-4.1 {source error conditions} -constraints macOnly -body {
- source -rsrc _no_exist_
-} -result {The resource "_no_exist_" could not be loaded from application.} \
- -returnCodes error
-
-test source-4.2 {source error conditions} -constraints macOnly -body {
- source -rsrcid bad_id
-} -returnCodes error -result {expected integer but got "bad_id"}
-
-test source-4.3 {source error conditions} -constraints macOnly -body {
- source -rsrc rsrcName fileName extra
-} -returnCodes error -result {wrong # args: should be "source fileName" or "source -rsrc name ?fileName?" or "source -rsrcid id ?fileName?" or "source -encoding name fileName"}
-
-test source-4.4 {source error conditions} -constraints macOnly -body {
- source non_switch rsrcName
-} -returnCodes error -result {bad argument: should be "source fileName" or "source -rsrc name ?fileName?" or "source -rsrcid id ?fileName?" or "source -encoding name fileName"}
-
-test source-4.5 {source error conditions} -constraints macOnly -body {
- source -bad_switch argument
-} -returnCodes error -result {bad argument: should be "source fileName" or "source -rsrc name ?fileName?" or "source -rsrcid id ?fileName?" or "source -encoding name fileName"}
-
-
-testConstraint testWriteTextResource \
- [llength [info commands testWriteTextResource]]
-
-test source-5.1 {source resource files} -constraints macOnly -setup {
- set sourcefile [makeFile {} bad_file]
- removeFile bad_file
-} -body {
- source -rsrc rsrcName $sourcefile
-} -returnCodes error -match glob -result {Error finding the file: "*bad_file".}
-
-test source-5.2 {source resource files} -constraints macOnly -setup {
- set sourcefile [makeFile {return} source.file]
-} -body {
- source -rsrc rsrcName $sourcefile
-} -cleanup {
- removeFile source.file
-} -returnCodes error -match glob \
- -result {Error reading the file: "*source.file".}
-
-test source-5.3 {source resource files} -constraints {
- macOnly testWriteTextResource
-} -setup {
- set msg2 unset
- set rsrcFile [makeFile {} rsrc.file]
- removeFile rsrc.file
- testWriteTextResource -rsrc rsrcName -file $rsrc.file {set msg2 ok; return}
-} -body {
- set result [catch {source -rsrc rsrcName rsrc.file} msg]
- list $msg2 $result $msg
-} -cleanup {
- removeFile rsrc.file
-} -result [list ok 0 {}]
-
-test source-5.4 {source resource files} -constraints {
- macOnly testWriteTextResource
-} -setup {
- set msg2 unset
- set rsrsFile [makeFile {} rsrc.file]
- removeFile rsrc.file
- testWriteTextResource -rsrc fileRsrcName \
- -file $rsrcFile {set msg2 ok; return}
-} -body {
- source -rsrc fileRsrcName $rsrcFile
- set result [catch {source -rsrc fileRsrcName} msg]
- list $msg2 $result $msg
-} -cleanup {
- removeFile rsrc.file
-} -result [list ok 1 {The resource "fileRsrcName" could not be loaded from application.}]
-
-test source-5.5 {source resource files} -constraints {
- macOnly testWriteTextResource
-} -setup {
- set msg2 unset
- set rsrcFile [makeFile {} rsrc.file]
- removeFile rsrc.file
- testWriteTextResource -rsrcid 200 \
- -file $rsrcFile {set msg2 hello; set msg3 bye}
-} -body {
- set result [catch {source -rsrcid 200 $rsrcFile} msg]
- list $msg2 $result $msg
-} -cleanup {
- removeFile rsrc.file
-} -result [list hello 0 bye]
-
-test source-5.6 {source resource files} -constraints {
- macOnly testWriteTextResource
-} -setup {
- set msg2 unset
- set rsrcFile [makeFile {} rsrc.file]
- removeFile rsrc.file
- testWriteTextResource -rsrcid 200 \
- -file $rsrcFile {set msg2 hello; error bad; set msg3 bye}
-} -body {
- set result [catch {source -rsrcid 200 rsrc.file} msg]
- list $msg2 $result $msg
-} -cleanup {
- removeFile rsrc.file
-} -result [list hello 1 bad]
-
-
test source-6.1 {source is binary ok} -setup {
# Note [makeFile] writes in the system encoding.
# [source] defaults to reading in the system encoding.
@@ -304,7 +185,6 @@ test source-6.1 {source is binary ok} -setup {
} -cleanup {
removeFile source.file
} -result 5
-
test source-6.2 {source skips everything after Ctrl-Z: Bug 2040} -setup {
set sourcefile [makeFile "set x ab\32c" source.file]
} -body {
@@ -315,6 +195,78 @@ test source-6.2 {source skips everything after Ctrl-Z: Bug 2040} -setup {
removeFile source.file
} -result 2
+test source-7.1 {source -encoding test} -setup {
+ set sourcefile [makeFile {} source.file]
+ file delete $sourcefile
+ set f [open $sourcefile w]
+ fconfigure $f -encoding utf-8
+ puts $f "set symbol(square-root) \u221A; set x correct"
+ close $f
+} -body {
+ set x unset
+ source -encoding utf-8 $sourcefile
+ set x
+} -cleanup {
+ removeFile source.file
+} -result correct
+test source-7.2 {source -encoding test} -setup {
+ # This tests for bad interactions between [source -encoding]
+ # and use of the Control-Z character (\u001A) as a cross-platform
+ # EOF character by [source]. Here we write out and the [source] a
+ # file that contains the byte \x1A, although not the character \u001A in
+ # the indicated encoding.
+ set sourcefile [makeFile {} source.file]
+ file delete $sourcefile
+ set f [open $sourcefile w]
+ fconfigure $f -encoding unicode
+ puts $f "set symbol(square-root) \u221A; set x correct"
+ close $f
+} -body {
+ set x unset
+ source -encoding unicode $sourcefile
+ set x
+} -cleanup {
+ removeFile source.file
+} -result correct
+test source-7.3 {source -encoding: syntax} -body {
+ # Have to spell out the -encoding option
+ source -e utf-8 no_file
+} -returnCodes 1 -match glob -result {bad option*}
+test source-7.4 {source -encoding: syntax} -setup {
+ set sourcefile [makeFile {} source.file]
+} -body {
+ source -encoding no-such-encoding $sourcefile
+} -cleanup {
+ removeFile source.file
+} -returnCodes 1 -match glob -result {unknown encoding*}
+test source-7.5 {source -encoding: correct operation} -setup {
+ set sourcefile [makeFile {} source.file]
+ file delete $sourcefile
+ set f [open $sourcefile w]
+ fconfigure $f -encoding utf-8
+ puts $f "proc \u20ac {} {return foo}"
+ close $f
+} -body {
+ source -encoding utf-8 $sourcefile
+ \u20ac
+} -cleanup {
+ removeFile source.file
+ rename \u20ac {}
+} -result foo
+test source-7.6 {source -encoding: mismatch encoding error} -setup {
+ set sourcefile [makeFile {} source.file]
+ file delete $sourcefile
+ set f [open $sourcefile w]
+ fconfigure $f -encoding utf-8
+ puts $f "proc \u20ac {} {return foo}"
+ close $f
+} -body {
+ source -encoding ascii $sourcefile
+ \u20ac
+} -cleanup {
+ removeFile source.file
+} -returnCodes error -match glob -result {invalid command name*}
+
cleanupTests
}
namespace delete ::tcl::test::source
diff --git a/tests/split.test b/tests/split.test
index 5e168dd..f18f333 100644
--- a/tests/split.test
+++ b/tests/split.test
@@ -82,15 +82,3 @@ test split-2.2 {split errors} {
catch {rename foo {}}
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/stack.test b/tests/stack.test
index e029bbd..96bcb98 100644
--- a/tests/stack.test
+++ b/tests/stack.test
@@ -21,46 +21,60 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
# This doesn't catch all cases, for example threads of lower stacksize
# can still squeak through. A core check is really needed. -- JH
-if {[string equal $::tcl_platform(platform) "unix"]} {
+testConstraint minStack2034 1
+if {[testConstraint unix]} {
set stackSize [exec /bin/sh -c "ulimit -s"]
- if {[string is integer $stackSize] && ($stackSize < 2400)} {
+ if {[string is integer $stackSize] && ($stackSize < 2034)} {
puts stderr "WARNING: the default application stacksize of $stackSize\
may cause Tcl to\ncrash due to stack overflow before the\
- recursion limit is reached.\nA minimum stacksize of 2400\
+ recursion limit is reached.\nA minimum stacksize of 2034\
kbytes is recommended.\nSkipping infinite recursion test."
- ::tcltest::testConstraint minStack2400 0
- } else {
- ::tcltest::testConstraint minStack2400 1
+ testConstraint minStack2034 0
}
-} else {
- ::tcltest::testConstraint minStack2400 1
}
-test stack-1.1 {maxNestingDepth reached on infinite recursion} {minStack2400} {
- proc recurse {} { return [recurse] }
- catch {recurse} rv
- rename recurse {}
- set rv
-} {too many nested evaluations (infinite loop?)}
+#
+# Custom match to detect a stack overflow independently of the mechanism that
+# triggered the error.
+#
-test stack-2.1 {maxNestingDepth reached on infinite recursion} {minStack2400} {
- # do this in a slave to not mess with parent
- set slave stack-2.1
- interp create $slave
- $slave eval { interp alias {} unknown {} notaknownproc }
- set msg [$slave eval { catch {foo} msg ; set msg }]
- interp delete $slave
- set msg
-} {too many nested evaluations (infinite loop?)}
+customMatch stackOverflow StackOverflow
+proc StackOverflow {- res} {
+ set msgList [list \
+ "too many nested evaluations (infinite loop?)"\
+ "out of stack space (infinite loop?)"]
+ expr {$res in $msgList}
+}
-# Make sure that there is enough stack to run regexp even if we're
-# close to the recursion limit. [Bug 947070]
+test stack-1.1 {maxNestingDepth reached on infinite recursion} -constraints {
+ minStack2034
+} -body {
+ # do this in a sub process in case it segfaults
+ exec [interpreter] << {
+ proc recurse {} { recurse }
+ catch { recurse } rv
+ puts $rv
+ }
+} -match stackOverflow
-test stack-3.1 {enough room for regexp near recursion limit} \
- -constraints { win } \
- -setup {
- set ::limit [interp recursionlimit {} 10000]
- set ::depth 0
+test stack-2.1 {maxNestingDepth reached on infinite recursion} -constraints {
+ minStack2034
+} -body {
+ # do this in a sub process in case it segfaults
+ exec [interpreter] << {
+ interp alias {} unknown {} notaknownproc
+ catch { unknown } msg
+ puts $msg
+ }
+} -match stackOverflow
+
+# Make sure that there is enough stack to run regexp even if we're
+# close to the recursion limit. [Bug 947070] [Patch 746378]
+test stack-3.1 {enough room for regexp near recursion limit} -body {
+ # do this in a sub process in case it segfaults
+ exec [interpreter] << {
+ interp recursionlimit {} 10000
+ set depth 0
proc a { max } {
if { [info level] < $max } {
set ::depth [info level]
@@ -69,15 +83,11 @@ test stack-3.1 {enough room for regexp near recursion limit} \
regexp {^ ?} x
}
}
- list [catch { a 10001 }]
- incr depth -3
+ catch { a 10001 }
set depth2 $depth
- } -body {
- list [catch { a $::depth } result] \
- $result [expr { $::depth2 - $::depth }]
- } -cleanup {
- interp recursionlimit {} $::limit
- } -result {0 1 1}
+ puts [list [a $depth] [expr { $depth2 - $depth }]]
+ }
+} -result {1 1}
# cleanup
::tcltest::cleanupTests
diff --git a/tests/string.test b/tests/string.test
index 555e5ce..c3cfc3c 100644
--- a/tests/string.test
+++ b/tests/string.test
@@ -19,17 +19,15 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
# Some tests require the testobj command
-set ::tcltest::testConstraints(testobj) \
- [expr {[info commands testobj] != {}}]
-set ::tcltest::testConstraints(testindexobj) \
- [expr {[info commands testindexobj] != {}}]
+testConstraint testobj [expr {[info commands testobj] != {}}]
+testConstraint testindexobj [expr {[info commands testindexobj] != {}}]
test string-1.1 {error conditions} {
list [catch {string gorp a b} msg] $msg
-} {1 {bad option "gorp": must be bytelength, compare, equal, first, index, is, last, length, map, match, range, repeat, replace, tolower, toupper, totitle, trim, trimleft, trimright, wordend, or wordstart}}
+} {1 {unknown or ambiguous subcommand "gorp": must be bytelength, compare, equal, first, index, is, last, length, map, match, range, repeat, replace, reverse, tolower, totitle, toupper, trim, trimleft, trimright, wordend, or wordstart}}
test string-1.2 {error conditions} {
list [catch {string} msg] $msg
-} {1 {wrong # args: should be "string option arg ?arg ...?"}}
+} {1 {wrong # args: should be "string subcommand ?argument ...?"}}
test string-2.1 {string compare, too few args} {
list [catch {string compare a} msg] $msg
@@ -173,13 +171,13 @@ test string-3.8 {string equal with length, unequal strings} {
test string-4.1 {string first, too few args} {
list [catch {string first a} msg] $msg
-} {1 {wrong # args: should be "string first subString string ?startIndex?"}}
+} {1 {wrong # args: should be "string first needleString haystackString ?startIndex?"}}
test string-4.2 {string first, bad args} {
list [catch {string first a b c} msg] $msg
-} {1 {bad index "c": must be integer or end?-integer?}}
+} {1 {bad index "c": must be integer?[+-]integer? or end?[+-]integer?}}
test string-4.3 {string first, too many args} {
list [catch {string first a b 5 d} msg] $msg
-} {1 {wrong # args: should be "string first subString string ?startIndex?"}}
+} {1 {wrong # args: should be "string first needleString haystackString ?startIndex?"}}
test string-4.4 {string first} {
string first bq abcdefgbcefgbqrs
} 12
@@ -241,7 +239,7 @@ test string-5.6 {string index} {
} {0 {}}
test string-5.7 {string index} {
list [catch {string index a xyz} msg] $msg
-} {1 {bad index "xyz": must be integer or end?-integer?}}
+} {1 {bad index "xyz": must be integer?[+-]integer? or end?[+-]integer?}}
test string-5.8 {string index} {
string index abc end
} c
@@ -274,12 +272,12 @@ test string-5.16 {string index, bytearray object with string obj shimmering} {
binary scan $str H* dump
string compare [string index $str 10] \x00
} 0
-test string-5.17 {string index, bad integer} {
- list [catch {string index "abc" 08} msg] $msg
-} {1 {bad index "08": must be integer or end?-integer? (looks like invalid octal number)}}
-test string-5.18 {string index, bad integer} {
- list [catch {string index "abc" end-00289} msg] $msg
-} {1 {bad index "end-00289": must be integer or end?-integer? (looks like invalid octal number)}}
+test string-5.17 {string index, bad integer} -body {
+ list [catch {string index "abc" 0o8} msg] $msg
+} -match glob -result {1 {*invalid octal number*}}
+test string-5.18 {string index, bad integer} -body {
+ list [catch {string index "abc" end-0o0289} msg] $msg
+} -match glob -result {1 {*invalid octal number*}}
test string-5.19 {string index, bytearray object out of bounds} {
string index [binary format I* {0x50515253 0x52}] -1
} {}
@@ -293,7 +291,7 @@ proc largest_int {} {
# so we can test for overflow properly below on >32 bit systems
set int 1
set exp 7; # assume we get at least 8 bits
- while {$int > 0} { set int [expr {wide(1) << [incr exp]}] }
+ while {wide($int) > 0} { set int [expr {wide(1) << [incr exp]}] }
return [expr {$int-1}]
}
@@ -311,10 +309,10 @@ test string-6.4 {string is, too many args} {
} {1 {wrong # args: should be "string is class ?-strict? ?-failindex var? str"}}
test string-6.5 {string is, class check} {
list [catch {string is bogus str} msg] $msg
-} {1 {bad class "bogus": must be alnum, alpha, ascii, control, boolean, digit, double, false, graph, integer, lower, print, punct, space, true, upper, wordchar, or xdigit}}
+} {1 {bad class "bogus": must be alnum, alpha, ascii, control, boolean, digit, double, false, graph, integer, list, lower, print, punct, space, true, upper, wideinteger, wordchar, or xdigit}}
test string-6.6 {string is, ambiguous class} {
list [catch {string is al str} msg] $msg
-} {1 {ambiguous class "al": must be alnum, alpha, ascii, control, boolean, digit, double, false, graph, integer, lower, print, punct, space, true, upper, wordchar, or xdigit}}
+} {1 {ambiguous class "al": must be alnum, alpha, ascii, control, boolean, digit, double, false, graph, integer, list, lower, print, punct, space, true, upper, wideinteger, wordchar, or xdigit}}
test string-6.7 {string is alpha, all ok} {
string is alpha -strict -failindex var abc
} 1
@@ -338,7 +336,7 @@ test string-6.13 {string is alnum, false} {
list [string is alnum -failindex var abc1.23] $var
} {0 4}
test string-6.14 {string is alnum, unicode} {
- string is alnum abcü
+ string is alnum abc\u00fc
} 1
test string-6.15 {string is alpha, true} {
string is alpha abc
@@ -350,11 +348,11 @@ test string-6.17 {string is alpha, unicode} {
string is alpha abc\374
} 1
test string-6.18 {string is ascii, true} {
- string is ascii abc\u007Fend
+ string is ascii abc\u007Fend\u0000
} 1
test string-6.19 {string is ascii, false} {
- list [string is ascii -fail var abcdef\u0080more] $var
-} {0 6}
+ list [string is ascii -fail var abc\u0000def\u0080more] $var
+} {0 7}
test string-6.20 {string is boolean, true} {
string is boolean true
} 1
@@ -371,7 +369,7 @@ test string-6.24 {string is digit, true} {
string is digit 0123456789
} 1
test string-6.25 {string is digit, false} {
- list [string is digit -fail var 0123Ü567] $var
+ list [string is digit -fail var 0123\u00dc567] $var
} {0 4}
test string-6.26 {string is digit, false} {
list [string is digit -fail var +123567] $var
@@ -408,16 +406,18 @@ test string-6.36 {string is double, false} {
} {0 0}
test string-6.37 {string is double, false on int overflow} {
# Make it the largest int recognizable, with one more digit for overflow
+ # Since bignums arrived in Tcl 8.5, the sense of this test changed.
+ # Now integer values that exceed native limits become bignums, and
+ # bignums can convert to doubles without error.
list [string is double -fail var [largest_int]0] $var
-} {0 -1}
-test string-6.38 {string is double, false on underflow} {
- catch {unset var}
- list [string is double -fail var 123e-9999] $var
-} {0 -1}
-test string-6.39 {string is double, false} {nonPortable} {
+} {1 0}
+# string-6.38 removed, underflow on input is no longer an error.
+test string-6.39 {string is double, false} {
# This test is non-portable because IRIX thinks
# that .e1 is a valid double - this is really a bug
# on IRIX as .e1 should NOT be a valid double
+ #
+ # Portable now. Tcl 8.5 does its own double parsing.
list [string is double -fail var .e1] $var
} {0 0}
@@ -478,8 +478,11 @@ test string-6.57 {string is integer, false} {
list [string is integer -fail var " "] $var
} {0 0}
test string-6.58 {string is integer, false on bad octal} {
- list [string is integer -fail var 036963] $var
-} {0 3}
+ list [string is integer -fail var 0o36963] $var
+} {0 4}
+test string-6.58.1 {string is integer, false on bad octal} {
+ list [string is integer -fail var 0o36963] $var
+} {0 4}
test string-6.59 {string is integer, false on bad hex} {
list [string is integer -fail var 0X345XYZ] $var
} {0 5}
@@ -487,7 +490,7 @@ test string-6.60 {string is lower, true} {
string is lower abc
} 1
test string-6.61 {string is lower, unicode true} {
- string is lower abcüue
+ string is lower abc\u00fcue
} 1
test string-6.62 {string is lower, false} {
list [string is lower -fail var aBc] $var
@@ -496,7 +499,7 @@ test string-6.63 {string is lower, false} {
list [string is lower -fail var abc1] $var
} {0 3}
test string-6.64 {string is lower, unicode false} {
- list [string is lower -fail var abÜUE] $var
+ list [string is lower -fail var ab\u00dcUE] $var
} {0 2}
test string-6.65 {string is space, true} {
string is space " \t\n\v\f"
@@ -534,7 +537,7 @@ test string-6.75 {string is upper, true} {
string is upper ABC
} 1
test string-6.76 {string is upper, unicode true} {
- string is upper ABCÜUE
+ string is upper ABC\u00dcUE
} 1
test string-6.77 {string is upper, false} {
list [string is upper -fail var AbC] $var
@@ -543,13 +546,13 @@ test string-6.78 {string is upper, false} {
list [string is upper -fail var AB2C] $var
} {0 2}
test string-6.79 {string is upper, unicode false} {
- list [string is upper -fail var ABCüue] $var
+ list [string is upper -fail var ABC\u00fcue] $var
} {0 3}
test string-6.80 {string is wordchar, true} {
string is wordchar abc_123
} 1
test string-6.81 {string is wordchar, unicode true} {
- string is wordchar abcüabÜAB\u5001
+ string is wordchar abc\u00fcab\u00dcAB\u5001
} 1
test string-6.82 {string is wordchar, false} {
list [string is wordchar -fail var abcd.ef] $var
@@ -614,18 +617,74 @@ test string-6.94 {string is integer, 32-bit overflow} {
set x 0x100000000
list [string is integer -failindex var [expr {$x}]] $var
} {0 -1}
+test string-6.95 {string is wideinteger, true} {
+ string is wideinteger +1234567890
+} 1
+test string-6.96 {string is wideinteger, true on type} {
+ string is wideinteger [expr wide(50.0)]
+} 1
+test string-6.97 {string is wideinteger, true} {
+ string is wideinteger [list -10]
+} 1
+test string-6.98 {string is wideinteger, true as hex} {
+ string is wideinteger 0xabcdef
+} 1
+test string-6.99 {string is wideinteger, true as octal} {
+ string is wideinteger 0123456
+} 1
+test string-6.100 {string is wideinteger, true with whitespace} {
+ string is wideinteger " \n1234\v"
+} 1
+test string-6.101 {string is wideinteger, false} {
+ list [string is wideinteger -fail var 123abc] $var
+} {0 3}
+test string-6.102 {string is wideinteger, false on overflow} {
+ list [string is wideinteger -fail var +[largest_int]0] $var
+} {0 -1}
+test string-6.103 {string is wideinteger, false} {
+ list [string is wideinteger -fail var [expr double(1)]] $var
+} {0 1}
+test string-6.104 {string is wideinteger, false} {
+ list [string is wideinteger -fail var " "] $var
+} {0 0}
+test string-6.105 {string is wideinteger, false on bad octal} {
+ list [string is wideinteger -fail var 0o36963] $var
+} {0 4}
+test string-6.105.1 {string is wideinteger, false on bad octal} {
+ list [string is wideinteger -fail var 0o36963] $var
+} {0 4}
+test string-6.106 {string is wideinteger, false on bad hex} {
+ list [string is wideinteger -fail var 0X345XYZ] $var
+} {0 5}
+test string-6.107 {string is integer, bad integers} {
+ # SF bug #634856
+ set result ""
+ set numbers [list 1 +1 ++1 +-1 -+1 -1 --1 "- +1"]
+ foreach num $numbers {
+ lappend result [string is wideinteger -strict $num]
+ }
+ set result
+} {1 1 0 0 0 1 0 0}
+test string-6.108 {string is double, Bug 1382287} {
+ set x 2turtledoves
+ string is double $x
+ string is double $x
+} 0
+test string-6.109 {string is double, Bug 1360532} {
+ string is double 1\u00a0
+} 0
catch {rename largest_int {}}
test string-7.1 {string last, too few args} {
list [catch {string last a} msg] $msg
-} {1 {wrong # args: should be "string last subString string ?startIndex?"}}
+} {1 {wrong # args: should be "string last needleString haystackString ?startIndex?"}}
test string-7.2 {string last, bad args} {
list [catch {string last a b c} msg] $msg
-} {1 {bad index "c": must be integer or end?-integer?}}
+} {1 {bad index "c": must be integer?[+-]integer? or end?[+-]integer?}}
test string-7.3 {string last, too many args} {
list [catch {string last a b c d} msg] $msg
-} {1 {wrong # args: should be "string last subString string ?startIndex?"}}
+} {1 {wrong # args: should be "string last needleString haystackString ?startIndex?"}}
test string-7.4 {string last} {
string la xxx xxxx123xx345x678
} 1
@@ -760,10 +819,10 @@ test string-10.18 {string map, empty argument} {
test string-10.19 {string map, empty arguments} {
string map -nocase {{} abc f bar {} def} foo
} baroo
-test string-10.20 {string map, nasty sharing crash from [Bug 1018562]} {
- set a {a b}
- string map $a $a
-} {b b}
+test string-10.20 {string map, dictionaries don't alter map ordering} {
+ set map {aa X a Y}
+ list [string map [dict create aa X a Y] aaa] [string map $map aaa] [dict size $map] [string map $map aaa]
+} {XY XY 2 XY}
test string-10.21 {string map, ABR checks} {
string map {longstring foob} long
} long
@@ -794,6 +853,10 @@ test string-10.29 {string map, ABR checks} {
test string-10.30 {string map, ABR checks} {
string map {lon foob longstring bar} longlon
} foobgfoob
+test string-10.31 {string map, nasty sharing crash from [Bug 1018562]} {
+ set a {a b}
+ string map $a $a
+} {b b}
test string-11.1 {string match, too few args} {
list [catch {string match a} msg] $msg
@@ -822,9 +885,54 @@ test string-11.8 {string match} {
test string-11.9 {string match} {
string match *3*6*9 0123456789
} 1
+test string-11.9.1 {string match} {
+ string match *3*6*89 0123456789
+} 1
+test string-11.9.2 {string match} {
+ string match *3*456*89 0123456789
+} 1
+test string-11.9.3 {string match} {
+ string match *3*6* 0123456789
+} 1
+test string-11.9.4 {string match} {
+ string match *3*56* 0123456789
+} 1
+test string-11.9.5 {string match} {
+ string match *3*456*** 0123456789
+} 1
+test string-11.9.6 {string match} {
+ string match **3*456** 0123456789
+} 1
+test string-11.9.7 {string match} {
+ string match *3***456* 0123456789
+} 1
+test string-11.9.8 {string match} {
+ string match *3***\[456]* 0123456789
+} 1
+test string-11.9.9 {string match} {
+ string match *3***\[4-6]* 0123456789
+} 1
+test string-11.9.10 {string match} {
+ string match *3***\[4-6] 0123456789
+} 0
+test string-11.9.11 {string match} {
+ string match *3***\[4-6] 0123456
+} 1
test string-11.10 {string match} {
string match *3*6*9 01234567890
} 0
+test string-11.10.1 {string match} {
+ string match *3*6*89 01234567890
+} 0
+test string-11.10.2 {string match} {
+ string match *3*456*89 01234567890
+} 0
+test string-11.10.3 {string match} {
+ string match **3*456*89 01234567890
+} 0
+test string-11.10.4 {string match} {
+ string match *3*456***89 01234567890
+} 0
test string-11.11 {string match} {
string match a?c abc
} 1
@@ -915,6 +1023,21 @@ test string-11.38 {string match case, reverse range} {
test string-11.39 {string match, *\ case} {
string match {*\abc} abc
} 1
+test string-11.39.1 {string match, *\ case} {
+ string match {*ab\c} abc
+} 1
+test string-11.39.2 {string match, *\ case} {
+ string match {*ab\*} ab*
+} 1
+test string-11.39.3 {string match, *\ case} {
+ string match {*ab\*} abc
+} 0
+test string-11.39.4 {string match, *\ case} {
+ string match {*ab\\*} {ab\c}
+} 1
+test string-11.39.5 {string match, *\ case} {
+ string match {*ab\\*} {ab\*}
+} 1
test string-11.40 {string match, *special case} {
string match {*[ab]} abc
} 0
@@ -1003,7 +1126,7 @@ test string-12.5 {string range, last > length} {
string range abcdefghijklmnop 7 1000
} {hijklmnop}
test string-12.6 {string range} {
- string range abcdefghijklmnop 10 e
+ string range abcdefghijklmnop 10 end
} {klmnop}
test string-12.7 {string range, last < first} {
string range abcdefghijklmnop 10 9
@@ -1022,15 +1145,15 @@ test string-12.11 {string range} {
} {abcdefghijklmnop}
test string-12.12 {string range} {
list [catch {string range abc abc 1} msg] $msg
-} {1 {bad index "abc": must be integer or end?-integer?}}
+} {1 {bad index "abc": must be integer?[+-]integer? or end?[+-]integer?}}
test string-12.13 {string range} {
list [catch {string range abc 1 eof} msg] $msg
-} {1 {bad index "eof": must be integer or end?-integer?}}
+} {1 {bad index "eof": must be integer?[+-]integer? or end?[+-]integer?}}
test string-12.14 {string range} {
string range abcdefghijklmnop end-1 end
} {op}
test string-12.15 {string range} {
- string range abcdefghijklmnop e 1000
+ string range abcdefghijklmnop end 1000
} {p}
test string-12.16 {string range} {
string range abcdefghijklmnop end end-1
@@ -1050,6 +1173,7 @@ test string-12.19 {string range, bytearray object} {
test string-12.20 {string range, out of bounds indices} {
string range \u00ff 0 1
} \u00ff
+# Bug 1410553
test string-12.21 {string range, regenerates correct reps, bug 1410553} {
set bytes "\x00 \x03 \x41"
set rxBuffer {}
@@ -1065,6 +1189,11 @@ test string-12.21 {string range, regenerates correct reps, bug 1410553} {
binary scan $rxCRC "H*" rxCRC_hex
list $input_hex $rxBuffer_hex $rxCRC_hex
} {000341 000341 0341}
+test string-12.22 {string range, shimmering binary/index} {
+ set s 0000000001
+ binary scan $s a* x
+ string range $s $s end
+} 000000001
test string-13.1 {string repeat} {
list [catch {string repeat} msg] $msg
@@ -1128,7 +1257,7 @@ test string-14.6 {string replace} {
string replace abcdefghijklmnop 7 1000
} {abcdefg}
test string-14.7 {string replace} {
- string replace abcdefghijklmnop 10 e
+ string replace abcdefghijklmnop 10 end
} {abcdefghij}
test string-14.8 {string replace} {
string replace abcdefghijklmnop 10 9
@@ -1147,15 +1276,15 @@ test string-14.12 {string replace} {
} {}
test string-14.13 {string replace} {
list [catch {string replace abc abc 1} msg] $msg
-} {1 {bad index "abc": must be integer or end?-integer?}}
+} {1 {bad index "abc": must be integer?[+-]integer? or end?[+-]integer?}}
test string-14.14 {string replace} {
list [catch {string replace abc 1 eof} msg] $msg
-} {1 {bad index "eof": must be integer or end?-integer?}}
+} {1 {bad index "eof": must be integer?[+-]integer? or end?[+-]integer?}}
test string-14.15 {string replace} {
string replace abcdefghijklmnop end-10 end-2 NEW
} {abcdeNEWop}
test string-14.16 {string replace} {
- string replace abcdefghijklmnop 0 e foo
+ string replace abcdefghijklmnop 0 end foo
} {foo}
test string-14.17 {string replace} {
string replace abcdefghijklmnop end end-1
@@ -1166,7 +1295,7 @@ test string-15.1 {string tolower too few args} {
} {1 {wrong # args: should be "string tolower string ?first? ?last?"}}
test string-15.2 {string tolower bad args} {
list [catch {string tolower a b} msg] $msg
-} {1 {bad index "b": must be integer or end?-integer?}}
+} {1 {bad index "b": must be integer?[+-]integer? or end?[+-]integer?}}
test string-15.3 {string tolower too many args} {
list [catch {string tolower ABC 1 end oops} msg] $msg
} {1 {wrong # args: should be "string tolower string ?first? ?last?"}}
@@ -1197,7 +1326,7 @@ test string-16.1 {string toupper} {
} {1 {wrong # args: should be "string toupper string ?first? ?last?"}}
test string-16.2 {string toupper} {
list [catch {string toupper a b} msg] $msg
-} {1 {bad index "b": must be integer or end?-integer?}}
+} {1 {bad index "b": must be integer?[+-]integer? or end?[+-]integer?}}
test string-16.3 {string toupper} {
list [catch {string toupper a 1 end oops} msg] $msg
} {1 {wrong # args: should be "string toupper string ?first? ?last?"}}
@@ -1228,7 +1357,7 @@ test string-17.1 {string totitle} {
} {1 {wrong # args: should be "string totitle string ?first? ?last?"}}
test string-17.2 {string totitle} {
list [catch {string totitle a b} msg] $msg
-} {1 {bad index "b": must be integer or end?-integer?}}
+} {1 {bad index "b": must be integer?[+-]integer? or end?[+-]integer?}}
test string-17.3 {string totitle} {
string totitle abCDEf
} {Abcdef}
@@ -1291,7 +1420,7 @@ test string-20.1 {string trimright errors} {
} {1 {wrong # args: should be "string trimright string ?chars?"}}
test string-20.2 {string trimright errors} {
list [catch {string trimg a} msg] $msg
-} {1 {bad option "trimg": must be bytelength, compare, equal, first, index, is, last, length, map, match, range, repeat, replace, tolower, toupper, totitle, trim, trimleft, trimright, wordend, or wordstart}}
+} {1 {unknown or ambiguous subcommand "trimg": must be bytelength, compare, equal, first, index, is, last, length, map, match, range, repeat, replace, reverse, tolower, totitle, toupper, trim, trimleft, trimright, wordend, or wordstart}}
test string-20.3 {string trimright} {
string trimright " XYZ "
} { XYZ}
@@ -1310,7 +1439,7 @@ test string-21.2 {string wordend} {
} {1 {wrong # args: should be "string wordend string index"}}
test string-21.3 {string wordend} {
list [catch {string wordend a gorp} msg] $msg
-} {1 {bad index "gorp": must be integer or end?-integer?}}
+} {1 {bad index "gorp": must be integer?[+-]integer? or end?[+-]integer?}}
test string-21.4 {string wordend} {
string wordend abc. -1
} 3
@@ -1347,7 +1476,7 @@ test string-21.14 {string wordend, unicode} {
test string-22.1 {string wordstart} {
list [catch {string word a} msg] $msg
-} {1 {ambiguous option "word": must be bytelength, compare, equal, first, index, is, last, length, map, match, range, repeat, replace, tolower, toupper, totitle, trim, trimleft, trimright, wordend, or wordstart}}
+} {1 {unknown or ambiguous subcommand "word": must be bytelength, compare, equal, first, index, is, last, length, map, match, range, repeat, replace, reverse, tolower, totitle, toupper, trim, trimleft, trimright, wordend, or wordstart}}
test string-22.2 {string wordstart} {
list [catch {string wordstart a} msg] $msg
} {1 {wrong # args: should be "string wordstart string index"}}
@@ -1356,7 +1485,7 @@ test string-22.3 {string wordstart} {
} {1 {wrong # args: should be "string wordstart string index"}}
test string-22.4 {string wordstart} {
list [catch {string wordstart a gorp} msg] $msg
-} {1 {bad index "gorp": must be integer or end?-integer?}}
+} {1 {bad index "gorp": must be integer?[+-]integer? or end?[+-]integer?}}
test string-22.5 {string wordstart} {
string wordstart "one two three_words" 400
} 8
@@ -1390,8 +1519,154 @@ test string-23.0 {string is boolean, Bug 1187123} testindexobj {
catch {testindexobj $x foo bar soom}
string is boolean $x
} 0
+test string-23.1 {string is command with empty string} {
+ set s ""
+ list \
+ [string is alnum $s] \
+ [string is alpha $s] \
+ [string is ascii $s] \
+ [string is control $s] \
+ [string is boolean $s] \
+ [string is digit $s] \
+ [string is double $s] \
+ [string is false $s] \
+ [string is graph $s] \
+ [string is integer $s] \
+ [string is lower $s] \
+ [string is print $s] \
+ [string is punct $s] \
+ [string is space $s] \
+ [string is true $s] \
+ [string is upper $s] \
+ [string is wordchar $s] \
+ [string is xdigit $s] \
+} {1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1}
+test string-23.2 {string is command with empty string} {
+ set s ""
+ list \
+ [string is alnum -strict $s] \
+ [string is alpha -strict $s] \
+ [string is ascii -strict $s] \
+ [string is control -strict $s] \
+ [string is boolean -strict $s] \
+ [string is digit -strict $s] \
+ [string is double -strict $s] \
+ [string is false -strict $s] \
+ [string is graph -strict $s] \
+ [string is integer -strict $s] \
+ [string is lower -strict $s] \
+ [string is print -strict $s] \
+ [string is punct -strict $s] \
+ [string is space -strict $s] \
+ [string is true -strict $s] \
+ [string is upper -strict $s] \
+ [string is wordchar -strict $s] \
+ [string is xdigit -strict $s] \
+
+} {0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}
+
+test string-24.1 {string reverse command} -body {
+ string reverse
+} -returnCodes error -result "wrong # args: should be \"string reverse string\""
+test string-24.2 {string reverse command} -body {
+ string reverse a b
+} -returnCodes error -result "wrong # args: should be \"string reverse string\""
+test string-24.3 {string reverse command - shared string} {
+ set x abcde
+ string reverse $x
+} edcba
+test string-24.4 {string reverse command - unshared string} {
+ set x abc
+ set y de
+ string reverse $x$y
+} edcba
+test string-24.5 {string reverse command - shared unicode string} {
+ set x abcde\udead
+ string reverse $x
+} \udeadedcba
+test string-24.6 {string reverse command - unshared string} {
+ set x abc
+ set y de\udead
+ string reverse $x$y
+} \udeadedcba
+test string-24.7 {string reverse command - simple case} {
+ string reverse a
+} a
+test string-24.8 {string reverse command - simple case} {
+ string reverse \udead
+} \udead
+test string-24.9 {string reverse command - simple case} {
+ string reverse {}
+} {}
+test string-24.10 {string reverse command - corner case} {
+ set x \ubeef\udead
+ string reverse $x
+} \udead\ubeef
+test string-24.11 {string reverse command - corner case} {
+ set x \ubeef
+ set y \udead
+ string reverse $x$y
+} \udead\ubeef
+test string-24.12 {string reverse command - corner case} {
+ set x \ubeef
+ set y \udead
+ string is ascii [string reverse $x$y]
+} 0
+
+test string-25.1 {string is list} {
+ string is list {a b c}
+} 1
+test string-25.2 {string is list} {
+ string is list "a \{b c"
+} 0
+test string-25.3 {string is list} {
+ string is list {a {b c}d e}
+} 0
+test string-25.4 {string is list} {
+ string is list {}
+} 1
+test string-25.5 {string is list} {
+ string is list -strict {a b c}
+} 1
+test string-25.6 {string is list} {
+ string is list -strict "a \{b c"
+} 0
+test string-25.7 {string is list} {
+ string is list -strict {a {b c}d e}
+} 0
+test string-25.8 {string is list} {
+ string is list -strict {}
+} 1
+test string-25.9 {string is list} {
+ set x {}
+ list [string is list -failindex x {a b c}] $x
+} {1 {}}
+test string-25.10 {string is list} {
+ set x {}
+ list [string is list -failindex x "a \{b c"] $x
+} {0 2}
+test string-25.11 {string is list} {
+ set x {}
+ list [string is list -failindex x {a b {b c}d e}] $x
+} {0 4}
+test string-25.12 {string is list} {
+ set x {}
+ list [string is list -failindex x {}] $x
+} {1 {}}
+test string-25.13 {string is list} {
+ set x {}
+ list [string is list -failindex x { {b c}d e}] $x
+} {0 2}
+test string-25.14 {string is list} {
+ set x {}
+ list [string is list -failindex x "\uabcd {b c}d e"] $x
+} {0 2}
# cleanup
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/stringComp.test b/tests/stringComp.test
index 3c13581..2ce2010 100644
--- a/tests/stringComp.test
+++ b/tests/stringComp.test
@@ -22,17 +22,16 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
# Some tests require the testobj command
-set ::tcltest::testConstraints(testobj) \
- [expr {[info commands testobj] != {}}]
+testConstraint testobj [expr {[info commands testobj] != {}}]
test stringComp-1.1 {error conditions} {
proc foo {} {string gorp a b}
list [catch {foo} msg] $msg
-} {1 {bad option "gorp": must be bytelength, compare, equal, first, index, is, last, length, map, match, range, repeat, replace, tolower, toupper, totitle, trim, trimleft, trimright, wordend, or wordstart}}
+} {1 {unknown or ambiguous subcommand "gorp": must be bytelength, compare, equal, first, index, is, last, length, map, match, range, repeat, replace, reverse, tolower, totitle, toupper, trim, trimleft, trimright, wordend, or wordstart}}
test stringComp-1.2 {error conditions} {
proc foo {} {string}
list [catch {foo} msg] $msg
-} {1 {wrong # args: should be "string option arg ?arg ...?"}}
+} {1 {wrong # args: should be "string subcommand ?argument ...?"}}
test stringComp-1.3 {error condition - undefined method during compile} {
# We don't want this to complain about 'never' because it may never
# be called, or string may get redefined. This must compile OK.
@@ -221,15 +220,15 @@ test stringComp-3.8 {string equal with length, unequal strings} {
test stringComp-4.1 {string first, too few args} {
proc foo {} {string first a}
list [catch {foo} msg] $msg
-} {1 {wrong # args: should be "string first subString string ?startIndex?"}}
+} {1 {wrong # args: should be "string first needleString haystackString ?startIndex?"}}
test stringComp-4.2 {string first, bad args} {
proc foo {} {string first a b c}
list [catch {foo} msg] $msg
-} {1 {bad index "c": must be integer or end?-integer?}}
+} {1 {bad index "c": must be integer?[+-]integer? or end?[+-]integer?}}
test stringComp-4.3 {string first, too many args} {
proc foo {} {string first a b 5 d}
list [catch {foo} msg] $msg
-} {1 {wrong # args: should be "string first subString string ?startIndex?"}}
+} {1 {wrong # args: should be "string first needleString haystackString ?startIndex?"}}
test stringComp-4.4 {string first} {
proc foo {} {string first bq abcdefgbcefgbqrs}
foo
@@ -302,7 +301,7 @@ test stringComp-5.6 {string index} {
test stringComp-5.7 {string index} {
proc foo {} {string index a xyz}
list [catch {foo} msg] $msg
-} {1 {bad index "xyz": must be integer or end?-integer?}}
+} {1 {bad index "xyz": must be integer?[+-]integer? or end?[+-]integer?}}
test stringComp-5.8 {string index} {
proc foo {} {string index abc end}
foo
@@ -348,14 +347,14 @@ test stringComp-5.16 {string index, bytearray object with string obj shimmering}
}
foo
} 0
-test stringComp-5.17 {string index, bad integer} {
- proc foo {} {string index "abc" 08}
+test stringComp-5.17 {string index, bad integer} -body {
+ proc foo {} {string index "abc" 0o8}
list [catch {foo} msg] $msg
-} {1 {bad index "08": must be integer or end?-integer? (looks like invalid octal number)}}
-test stringComp-5.18 {string index, bad integer} {
- proc foo {} {string index "abc" end-00289}
+} -match glob -result {1 {*invalid octal number*}}
+test stringComp-5.18 {string index, bad integer} -body {
+ proc foo {} {string index "abc" end-0o0289}
list [catch {foo} msg] $msg
-} {1 {bad index "end-00289": must be integer or end?-integer? (looks like invalid octal number)}}
+} -match glob -result {1 {*invalid octal number*}}
test stringComp-5.19 {string index, bytearray object out of bounds} {
proc foo {} {string index [binary format I* {0x50515253 0x52}] -1}
foo
diff --git a/tests/stringObj.test b/tests/stringObj.test
index 991b256..5c8f88b 100644
--- a/tests/stringObj.test
+++ b/tests/stringObj.test
@@ -17,20 +17,15 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-if {[info commands testobj] == {}} {
- puts "This application hasn't been compiled with the \"testobj\""
- puts "command, so I can't test the Tcl type and object support."
- ::tcltest::cleanupTests
- return
-}
+testConstraint testobj [llength [info commands testobj]]
-test stringObj-1.1 {string type registration} {
+test stringObj-1.1 {string type registration} testobj {
set t [testobj types]
set first [string first "string" $t]
set result [expr {$first != -1}]
} {1}
-test stringObj-2.1 {Tcl_NewStringObj} {
+test stringObj-2.1 {Tcl_NewStringObj} testobj {
set result ""
lappend result [testobj freeallvars]
lappend result [teststringobj set 1 abcd]
@@ -38,7 +33,7 @@ test stringObj-2.1 {Tcl_NewStringObj} {
lappend result [testobj refcount 1]
} {{} abcd string 2}
-test stringObj-3.1 {Tcl_SetStringObj, existing "empty string" object} {
+test stringObj-3.1 {Tcl_SetStringObj, existing "empty string" object} testobj {
set result ""
lappend result [testobj freeallvars]
lappend result [testobj newobj 1]
@@ -46,7 +41,7 @@ test stringObj-3.1 {Tcl_SetStringObj, existing "empty string" object} {
lappend result [testobj type 1]
lappend result [testobj refcount 1]
} {{} {} xyz string 2}
-test stringObj-3.2 {Tcl_SetStringObj, existing non-"empty string" object} {
+test stringObj-3.2 {Tcl_SetStringObj, existing non-"empty string" object} testobj {
set result ""
lappend result [testobj freeallvars]
lappend result [testintobj set 1 512]
@@ -55,47 +50,47 @@ test stringObj-3.2 {Tcl_SetStringObj, existing non-"empty string" object} {
lappend result [testobj refcount 1]
} {{} 512 foo string 2}
-test stringObj-4.1 {Tcl_SetObjLength procedure, string gets shorter} {
+test stringObj-4.1 {Tcl_SetObjLength procedure, string gets shorter} testobj {
testobj freeallvars
teststringobj set 1 test
teststringobj setlength 1 3
list [teststringobj length 1] [teststringobj length2 1] \
[teststringobj get 1]
} {3 4 tes}
-test stringObj-4.2 {Tcl_SetObjLength procedure, string gets longer} {
+test stringObj-4.2 {Tcl_SetObjLength procedure, string gets longer} testobj {
testobj freeallvars
teststringobj set 1 abcdef
teststringobj setlength 1 10
list [teststringobj length 1] [teststringobj length2 1]
} {10 10}
-test stringObj-4.3 {Tcl_SetObjLength procedure, string gets longer} {
+test stringObj-4.3 {Tcl_SetObjLength procedure, string gets longer} testobj {
testobj freeallvars
teststringobj set 1 abcdef
teststringobj append 1 xyzq -1
list [teststringobj length 1] [teststringobj length2 1] \
[teststringobj get 1]
} {10 20 abcdefxyzq}
-test stringObj-4.4 {Tcl_SetObjLength procedure, "expty string", length 0} {
+test stringObj-4.4 {Tcl_SetObjLength procedure, "expty string", length 0} testobj {
testobj freeallvars
testobj newobj 1
teststringobj setlength 1 0
list [teststringobj length2 1] [teststringobj get 1]
} {0 {}}
-test stringObj-5.1 {Tcl_AppendToObj procedure, type conversion} {
+test stringObj-5.1 {Tcl_AppendToObj procedure, type conversion} testobj {
testobj freeallvars
testintobj set2 1 43
teststringobj append 1 xyz -1
teststringobj get 1
} {43xyz}
-test stringObj-5.2 {Tcl_AppendToObj procedure, length calculation} {
+test stringObj-5.2 {Tcl_AppendToObj procedure, length calculation} testobj {
testobj freeallvars
teststringobj set 1 {x y }
teststringobj append 1 bbCCddEE 4
teststringobj append 1 123 -1
teststringobj get 1
} {x y bbCC123}
-test stringObj-5.3 {Tcl_AppendToObj procedure, reallocating space} {
+test stringObj-5.3 {Tcl_AppendToObj procedure, reallocating space} testobj {
testobj freeallvars
teststringobj set 1 xyz
teststringobj setlength 1 15
@@ -109,37 +104,37 @@ test stringObj-5.3 {Tcl_AppendToObj procedure, reallocating space} {
[teststringobj get 1]
} {15 15 16 32 xy12345678abcdef}
-test stringObj-6.1 {Tcl_AppendStringsToObj procedure, type conversion} {
+test stringObj-6.1 {Tcl_AppendStringsToObj procedure, type conversion} testobj {
testobj freeallvars
teststringobj set2 1 [list a b]
teststringobj appendstrings 1 xyz { 1234 } foo
teststringobj get 1
} {a bxyz 1234 foo}
-test stringObj-6.2 {Tcl_AppendStringsToObj procedure, counting space} {
+test stringObj-6.2 {Tcl_AppendStringsToObj procedure, counting space} testobj {
testobj freeallvars
teststringobj set 1 abc
teststringobj appendstrings 1
list [teststringobj length 1] [teststringobj get 1]
} {3 abc}
-test stringObj-6.3 {Tcl_AppendStringsToObj procedure, counting space} {
+test stringObj-6.3 {Tcl_AppendStringsToObj procedure, counting space} testobj {
testobj freeallvars
teststringobj set 1 abc
teststringobj appendstrings 1 {} {} {} {}
list [teststringobj length 1] [teststringobj get 1]
} {3 abc}
-test stringObj-6.4 {Tcl_AppendStringsToObj procedure, counting space} {
+test stringObj-6.4 {Tcl_AppendStringsToObj procedure, counting space} testobj {
testobj freeallvars
teststringobj set 1 abc
teststringobj appendstrings 1 { 123 } abcdefg
list [teststringobj length 1] [teststringobj get 1]
} {15 {abc 123 abcdefg}}
-test stringObj-6.5 {Tcl_AppendStringsToObj procedure, don't double space if initial string empty} {
+test stringObj-6.5 {Tcl_AppendStringsToObj procedure, don't double space if initial string empty} testobj {
testobj freeallvars
testobj newobj 1
teststringobj appendstrings 1 123 abcdefg
list [teststringobj length 1] [teststringobj length2 1] [teststringobj get 1]
} {10 10 123abcdefg}
-test stringObj-6.6 {Tcl_AppendStringsToObj procedure, space reallocation} {
+test stringObj-6.6 {Tcl_AppendStringsToObj procedure, space reallocation} testobj {
testobj freeallvars
teststringobj set 1 abc
teststringobj setlength 1 10
@@ -148,7 +143,7 @@ test stringObj-6.6 {Tcl_AppendStringsToObj procedure, space reallocation} {
list [teststringobj length 1] [teststringobj length2 1] \
[teststringobj get 1]
} {10 10 ab34567890}
-test stringObj-6.7 {Tcl_AppendStringsToObj procedure, space reallocation} {
+test stringObj-6.7 {Tcl_AppendStringsToObj procedure, space reallocation} testobj {
testobj freeallvars
teststringobj set 1 abc
teststringobj setlength 1 10
@@ -157,7 +152,7 @@ test stringObj-6.7 {Tcl_AppendStringsToObj procedure, space reallocation} {
list [teststringobj length 1] [teststringobj length2 1] \
[teststringobj get 1]
} {11 22 ab34567890x}
-test stringObj-6.8 {Tcl_AppendStringsToObj procedure, object totally empty} {
+test stringObj-6.8 {Tcl_AppendStringsToObj procedure, object totally empty} testobj {
testobj freeallvars
testobj newobj 1
teststringobj appendstrings 1 {}
@@ -170,32 +165,32 @@ test stringObj-6.9 {Tcl_AppendStringToObj, pure unicode} {
teststringobj get 1
} adcfoobarsoom
-test stringObj-7.1 {SetStringFromAny procedure} {
+test stringObj-7.1 {SetStringFromAny procedure} testobj {
testobj freeallvars
teststringobj set2 1 [list a b]
teststringobj append 1 x -1
list [teststringobj length 1] [teststringobj length2 1] \
[teststringobj get 1]
} {4 8 {a bx}}
-test stringObj-7.2 {SetStringFromAny procedure, null object} {
+test stringObj-7.2 {SetStringFromAny procedure, null object} testobj {
testobj freeallvars
testobj newobj 1
teststringobj appendstrings 1 {}
list [teststringobj length 1] [teststringobj length2 1] \
[teststringobj get 1]
} {0 0 {}}
-test stringObj-7.3 {SetStringFromAny called with non-string obj} {
+test stringObj-7.3 {SetStringFromAny called with non-string obj} testobj {
set x 2345
list [incr x] [testobj objtype $x] [string index $x end] \
[testobj objtype $x]
} {2346 int 6 string}
-test stringObj-7.4 {SetStringFromAny called with string obj} {
+test stringObj-7.4 {SetStringFromAny called with string obj} testobj {
set x "abcdef"
list [string length $x] [testobj objtype $x] \
[string length $x] [testobj objtype $x]
} {6 string 6 string}
-test stringObj-8.1 {DupStringInternalRep procedure} {
+test stringObj-8.1 {DupStringInternalRep procedure} testobj {
testobj freeallvars
teststringobj set 1 {}
teststringobj append 1 abcde -1
@@ -205,28 +200,28 @@ test stringObj-8.1 {DupStringInternalRep procedure} {
[teststringobj length 2] [teststringobj length2 2] \
[teststringobj ualloc 2] [teststringobj get 2]
} {5 10 0 abcde 5 5 0 abcde}
-test stringObj-8.2 {DupUnicodeInternalRep, mixed width chars} {
+test stringObj-8.2 {DupUnicodeInternalRep, mixed width chars} testobj {
set x abcï¿®ghi
string length $x
set y $x
list [testobj objtype $x] [testobj objtype $y] [append x "®¿ï"] \
[set y] [testobj objtype $x] [testobj objtype $y]
} {string string abcï¿®ghi®¿ï abcï¿®ghi string string}
-test stringObj-8.3 {DupUnicodeInternalRep, mixed width chars} {
+test stringObj-8.3 {DupUnicodeInternalRep, mixed width chars} testobj {
set x abcï¿®ghi
set y $x
string length $x
list [testobj objtype $x] [testobj objtype $y] [append x "®¿ï"] \
[set y] [testobj objtype $x] [testobj objtype $y]
} {string string abcï¿®ghi®¿ï abcï¿®ghi string string}
-test stringObj-8.4 {DupUnicodeInternalRep, all byte-size chars} {
+test stringObj-8.4 {DupUnicodeInternalRep, all byte-size chars} testobj {
set x abcdefghi
string length $x
set y $x
list [testobj objtype $x] [testobj objtype $y] [append x jkl] \
[set y] [testobj objtype $x] [testobj objtype $y]
} {string string abcdefghijkl abcdefghi string string}
-test stringObj-8.5 {DupUnicodeInternalRep, all byte-size chars} {
+test stringObj-8.5 {DupUnicodeInternalRep, all byte-size chars} testobj {
set x abcdefghi
set y $x
string length $x
@@ -234,14 +229,14 @@ test stringObj-8.5 {DupUnicodeInternalRep, all byte-size chars} {
[set y] [testobj objtype $x] [testobj objtype $y]
} {string string abcdefghijkl abcdefghi string string}
-test stringObj-9.1 {TclAppendObjToObj, mixed src & dest} {
+test stringObj-9.1 {TclAppendObjToObj, mixed src & dest} testobj {
set x abcï¿®ghi
set y ®¿ï
string length $x
list [testobj objtype $x] [testobj objtype $y] [append x $y] \
[set y] [testobj objtype $x] [testobj objtype $y]
} {string none abcï¿®ghi®¿ï ®¿ï string none}
-test stringObj-9.2 {TclAppendObjToObj, mixed src & dest} {
+test stringObj-9.2 {TclAppendObjToObj, mixed src & dest} testobj {
set x abcï¿®ghi
string length $x
list [testobj objtype $x] [append x $x] [testobj objtype $x] \
@@ -249,61 +244,61 @@ test stringObj-9.2 {TclAppendObjToObj, mixed src & dest} {
} {string abcï¿®ghiabcï¿®ghi string\
abcï¿®ghiabcï¿®ghiabcï¿®ghiabcï¿®ghi\
string}
-test stringObj-9.3 {TclAppendObjToObj, mixed src & 1-byte dest} {
+test stringObj-9.3 {TclAppendObjToObj, mixed src & 1-byte dest} testobj {
set x abcdefghi
set y ®¿ï
string length $x
list [testobj objtype $x] [testobj objtype $y] [append x $y] \
[set y] [testobj objtype $x] [testobj objtype $y]
} {string none abcdefghi®¿ï ®¿ï string none}
-test stringObj-9.4 {TclAppendObjToObj, 1-byte src & dest} {
+test stringObj-9.4 {TclAppendObjToObj, 1-byte src & dest} testobj {
set x abcdefghi
set y jkl
string length $x
list [testobj objtype $x] [testobj objtype $y] [append x $y] \
[set y] [testobj objtype $x] [testobj objtype $y]
} {string none abcdefghijkl jkl string none}
-test stringObj-9.5 {TclAppendObjToObj, 1-byte src & dest} {
+test stringObj-9.5 {TclAppendObjToObj, 1-byte src & dest} testobj {
set x abcdefghi
string length $x
list [testobj objtype $x] [append x $x] [testobj objtype $x] \
[append x $x] [testobj objtype $x]
} {string abcdefghiabcdefghi string abcdefghiabcdefghiabcdefghiabcdefghi\
string}
-test stringObj-9.6 {TclAppendObjToObj, 1-byte src & mixed dest} {
+test stringObj-9.6 {TclAppendObjToObj, 1-byte src & mixed dest} testobj {
set x abcï¿®ghi
set y jkl
string length $x
list [testobj objtype $x] [testobj objtype $y] [append x $y] \
[set y] [testobj objtype $x] [testobj objtype $y]
} {string none abcï¿®ghijkl jkl string none}
-test stringObj-9.7 {TclAppendObjToObj, integer src & dest} {
+test stringObj-9.7 {TclAppendObjToObj, integer src & dest} testobj {
set x [expr {4 * 5}]
set y [expr {4 + 5}]
list [testobj objtype $x] [testobj objtype $y] [append x $y] \
[testobj objtype $x] [append x $y] [testobj objtype $x] \
[testobj objtype $y]
} {int int 209 string 2099 string int}
-test stringObj-9.8 {TclAppendObjToObj, integer src & dest} {
+test stringObj-9.8 {TclAppendObjToObj, integer src & dest} testobj {
set x [expr {4 * 5}]
list [testobj objtype $x] [append x $x] [testobj objtype $x] \
[append x $x] [testobj objtype $x]
} {int 2020 string 20202020 string}
-test stringObj-9.9 {TclAppendObjToObj, integer src & 1-byte dest} {
+test stringObj-9.9 {TclAppendObjToObj, integer src & 1-byte dest} testobj {
set x abcdefghi
set y [expr {4 + 5}]
string length $x
list [testobj objtype $x] [testobj objtype $y] [append x $y] \
[set y] [testobj objtype $x] [testobj objtype $y]
} {string int abcdefghi9 9 string int}
-test stringObj-9.10 {TclAppendObjToObj, integer src & mixed dest} {
+test stringObj-9.10 {TclAppendObjToObj, integer src & mixed dest} testobj {
set x abcï¿®ghi
set y [expr {4 + 5}]
string length $x
list [testobj objtype $x] [testobj objtype $y] [append x $y] \
[set y] [testobj objtype $x] [testobj objtype $y]
} {string int abcï¿®ghi9 9 string int}
-test stringObj-9.11 {TclAppendObjToObj, mixed src & 1-byte dest index check} {
+test stringObj-9.11 {TclAppendObjToObj, mixed src & 1-byte dest index check} testobj {
# bug 2678, in <=8.2.0, the second obj (the one to append) in
# Tcl_AppendObjToObj was not correctly checked to see if it was
# all one byte chars, so a unicode string would be added as one
@@ -321,12 +316,12 @@ test stringObj-9.11 {TclAppendObjToObj, mixed src & 1-byte dest index check} {
set q
} {a b c d e f a ü b å c ï}
-test stringObj-10.1 {Tcl_GetRange with all byte-size chars} {
+test stringObj-10.1 {Tcl_GetRange with all byte-size chars} testobj {
set x "abcdef"
list [testobj objtype $x] [set y [string range $x 1 end-1]] \
[testobj objtype $x] [testobj objtype $y]
} [list none bcde string string]
-test stringObj-10.2 {Tcl_GetRange with some mixed width chars} {
+test stringObj-10.2 {Tcl_GetRange with some mixed width chars} testobj {
# Because this test does not use \uXXXX notation below instead of
# hardcoding the values, it may fail in multibyte locales. However,
# we need to test that the parser produces untyped objects even when there
@@ -336,7 +331,7 @@ test stringObj-10.2 {Tcl_GetRange with some mixed width chars} {
list [testobj objtype $x] [set y [string range $x 1 end-1]] \
[testobj objtype $x] [testobj objtype $y]
} [list none "bc\u00EF\u00EFde" string string]
-test stringObj-10.3 {Tcl_GetRange with some mixed width chars} {
+test stringObj-10.3 {Tcl_GetRange with some mixed width chars} testobj {
# set x "abcïïdef"
# Use \uXXXX notation below instead of hardcoding the values, otherwise
# the test will fail in multibyte locales.
@@ -345,7 +340,7 @@ test stringObj-10.3 {Tcl_GetRange with some mixed width chars} {
list [testobj objtype $x] [set y [string range $x 1 end-1]] \
[testobj objtype $x] [testobj objtype $y]
} [list string "bc\u00EF\u00EFde" string string]
-test stringObj-10.4 {Tcl_GetRange with some mixed width chars} {
+test stringObj-10.4 {Tcl_GetRange with some mixed width chars} testobj {
# set a "ïa¿b®cï¿d®"
# Use \uXXXX notation below instead of hardcoding the values, otherwise
# the test will fail in multibyte locales.
@@ -362,71 +357,71 @@ test stringObj-10.4 {Tcl_GetRange with some mixed width chars} {
\u00AEc \
{}]
-test stringObj-11.1 {UpdateStringOfString} {
+test stringObj-11.1 {UpdateStringOfString} testobj {
set x 2345
list [string index $x end] [testobj objtype $x] [incr x] \
[testobj objtype $x]
} {5 string 2346 int}
-test stringObj-12.1 {Tcl_GetUniChar with byte-size chars} {
+test stringObj-12.1 {Tcl_GetUniChar with byte-size chars} testobj {
set x "abcdefghi"
list [string index $x 0] [string index $x 1]
} {a b}
-test stringObj-12.2 {Tcl_GetUniChar with byte-size chars} {
+test stringObj-12.2 {Tcl_GetUniChar with byte-size chars} testobj {
set x "abcdefghi"
list [string index $x 3] [string index $x end]
} {d i}
-test stringObj-12.3 {Tcl_GetUniChar with byte-size chars} {
+test stringObj-12.3 {Tcl_GetUniChar with byte-size chars} testobj {
set x "abcdefghi"
list [string index $x end] [string index $x end-1]
} {i h}
-test stringObj-12.4 {Tcl_GetUniChar with mixed width chars} {
+test stringObj-12.4 {Tcl_GetUniChar with mixed width chars} testobj {
string index "ïa¿b®c®¿dï" 0
} "ï"
-test stringObj-12.5 {Tcl_GetUniChar} {
+test stringObj-12.5 {Tcl_GetUniChar} testobj {
set x "ïa¿b®c®¿dï"
list [string index $x 4] [string index $x 0]
} {® ï}
-test stringObj-12.6 {Tcl_GetUniChar} {
+test stringObj-12.6 {Tcl_GetUniChar} testobj {
string index "ïa¿b®cï¿d®" end
} "®"
-test stringObj-13.1 {Tcl_GetCharLength with byte-size chars} {
+test stringObj-13.1 {Tcl_GetCharLength with byte-size chars} testobj {
set a ""
list [string length $a] [string length $a]
} {0 0}
-test stringObj-13.2 {Tcl_GetCharLength with byte-size chars} {
+test stringObj-13.2 {Tcl_GetCharLength with byte-size chars} testobj {
string length "a"
} 1
-test stringObj-13.3 {Tcl_GetCharLength with byte-size chars} {
+test stringObj-13.3 {Tcl_GetCharLength with byte-size chars} testobj {
set a "abcdef"
list [string length $a] [string length $a]
} {6 6}
-test stringObj-13.4 {Tcl_GetCharLength with mixed width chars} {
+test stringObj-13.4 {Tcl_GetCharLength with mixed width chars} testobj {
string length "®"
} 1
-test stringObj-13.5 {Tcl_GetCharLength with mixed width chars} {
+test stringObj-13.5 {Tcl_GetCharLength with mixed width chars} testobj {
# string length "○○"
# Use \uXXXX notation below instead of hardcoding the values, otherwise
# the test will fail in multibyte locales.
string length "\u00EF\u00BF\u00AE\u00EF\u00BF\u00AE"
} 6
-test stringObj-13.6 {Tcl_GetCharLength with mixed width chars} {
+test stringObj-13.6 {Tcl_GetCharLength with mixed width chars} testobj {
# set a "ïa¿b®cï¿d®"
# Use \uXXXX notation below instead of hardcoding the values, otherwise
# the test will fail in multibyte locales.
set a "\u00EFa\u00BFb\u00AEc\u00EF\u00BFd\u00AE"
list [string length $a] [string length $a]
} {10 10}
-test stringObj-13.7 {Tcl_GetCharLength with identity nulls} {
+test stringObj-13.7 {Tcl_GetCharLength with identity nulls} testobj {
# SF bug #684699
string length [encoding convertfrom identity \x00]
} 1
-test stringObj-13.8 {Tcl_GetCharLength with identity nulls} {
+test stringObj-13.8 {Tcl_GetCharLength with identity nulls} testobj {
string length [encoding convertfrom identity \x01\x00\x02]
} 3
-test stringObj-14.1 {Tcl_SetObjLength on pure unicode object} {
+test stringObj-14.1 {Tcl_SetObjLength on pure unicode object} testobj {
teststringobj set 1 foo
teststringobj getunicode 1
teststringobj append 1 bar -1
@@ -470,7 +465,9 @@ test stringObj-15.8 {Tcl_Append*ToObj: self appends} {
teststringobj appendself2 1 3
} foo
-testobj freeallvars
+if {[testConstraint testobj]} {
+ testobj freeallvars
+}
# cleanup
::tcltest::cleanupTests
diff --git a/tests/subst.test b/tests/subst.test
index 77a3df7..933b1c6 100644
--- a/tests/subst.test
+++ b/tests/subst.test
@@ -12,7 +12,7 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2.1
namespace import -force ::tcltest::*
}
@@ -160,12 +160,12 @@ test subst-8.5 {return in a subst} {
test subst-8.6 {return in a subst} {
list [catch {subst {foo [return {x}; bogus code bar}} msg] $msg
} {1 {missing close-bracket}}
-test subst-8.7 {return in a subst, parse error} {
+test subst-8.7 {return in a subst, parse error} -body {
subst {foo [return {x} ; set a {}" ; stuff] bar}
-} {foo xset a {}" ; stuff] bar}
-test subst-8.8 {return in a subst, parse error} {
+} -returnCodes error -result {extra characters after close-brace}
+test subst-8.8 {return in a subst, parse error} -body {
subst {foo [return {x} ; set bar baz ; set a {}" ; stuff] bar}
-} {foo xset bar baz ; set a {}" ; stuff] bar}
+} -returnCodes error -result {extra characters after close-brace}
test subst-8.9 {return in a variable subst} {
subst {foo $var([return {x}]) bar}
} {foo x bar}
@@ -208,12 +208,12 @@ test subst-11.2 {continue in a subst} {
test subst-11.3 {continue in a subst} {
subst {foo [if 1 { continue; bogus code}] bar}
} {foo bar}
-test subst-11.4 {continue in a subst, parse error} {
+test subst-11.4 {continue in a subst, parse error} -body {
subst {foo [continue ; set a {}{} ; stuff] bar}
-} {foo set a {}{} ; stuff] bar}
-test subst-11.5 {continue in a subst, parse error} {
+} -returnCodes error -result {extra characters after close-brace}
+test subst-11.5 {continue in a subst, parse error} -body {
subst {foo [continue ;set bar baz ;set a {}{} ; stuff] bar}
-} {foo set bar baz ;set a {}{} ; stuff] bar}
+} -returnCodes error -result {extra characters after close-brace}
test subst-11.6 {continue in a variable subst} {
subst {foo $var([continue]) bar}
} {foo bar}
@@ -235,24 +235,24 @@ test subst-12.2 {nasty case, Bug 1036649} {
test subst-12.3 {nasty case, Bug 1036649} {
set x 0
for {set i 0} {$i < 10} {incr i} {
- set res [list [catch {subst "\[incr x;"} msg] $msg]
- if {$msg ne "missing close-bracket"} break
+ set res [list [catch {subst "\[incr x;"} msg] $msg]
+ if {$msg ne "missing close-bracket"} break
}
list $res $x
} {{1 {missing close-bracket}} 10}
test subst-12.4 {nasty case, Bug 1036649} {
set x 0
for {set i 0} {$i < 10} {incr i} {
- set res [list [catch {subst "\[incr x; "} msg] $msg]
- if {$msg ne "missing close-bracket"} break
+ set res [list [catch {subst "\[incr x; "} msg] $msg]
+ if {$msg ne "missing close-bracket"} break
}
list $res $x
} {{1 {missing close-bracket}} 10}
test subst-12.5 {nasty case, Bug 1036649} {
set x 0
for {set i 0} {$i < 10} {incr i} {
- set res [list [catch {subst "\[incr x"} msg] $msg]
- if {$msg ne "missing close-bracket"} break
+ set res [list [catch {subst "\[incr x"} msg] $msg]
+ if {$msg ne "missing close-bracket"} break
}
list $res $x
} {{1 {missing close-bracket}} 0}
diff --git a/tests/switch.test b/tests/switch.test
index 007456f..5ee7216 100644
--- a/tests/switch.test
+++ b/tests/switch.test
@@ -12,104 +12,173 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2
namespace import -force ::tcltest::*
}
test switch-1.1 {simple patterns} {
- switch a a {format 1} b {format 2} c {format 3} default {format 4}
+ switch a a {subst 1} b {subst 2} c {subst 3} default {subst 4}
} 1
test switch-1.2 {simple patterns} {
- switch b a {format 1} b {format 2} c {format 3} default {format 4}
+ switch b a {subst 1} b {subst 2} c {subst 3} default {subst 4}
} 2
test switch-1.3 {simple patterns} {
- switch x a {format 1} b {format 2} c {format 3} default {format 4}
+ switch x a {subst 1} b {subst 2} c {subst 3} default {subst 4}
} 4
test switch-1.4 {simple patterns} {
- switch x a {format 1} b {format 2} c {format 3}
+ switch x a {subst 1} b {subst 2} c {subst 3}
} {}
test switch-1.5 {simple pattern matches many times} {
- switch b a {format 1} b {format 2} b {format 3} b {format 4}
+ switch b a {subst 1} b {subst 2} b {subst 3} b {subst 4}
} 2
test switch-1.6 {simple patterns} {
- switch default a {format 1} default {format 2} c {format 3} default {format 4}
+ switch default a {subst 1} default {subst 2} c {subst 3} default {subst 4}
} 2
test switch-1.7 {simple patterns} {
- switch x a {format 1} default {format 2} c {format 3} default {format 4}
+ switch x a {subst 1} default {subst 2} c {subst 3} default {subst 4}
+} 4
+test switch-1.8 {simple patterns with -nocase} {
+ switch -nocase b a {subst 1} b {subst 2} c {subst 3} default {subst 4}
+} 2
+test switch-1.9 {simple patterns with -nocase} {
+ switch -nocase B a {subst 1} b {subst 2} c {subst 3} default {subst 4}
+} 2
+test switch-1.10 {simple patterns with -nocase} {
+ switch -nocase b a {subst 1} B {subst 2} c {subst 3} default {subst 4}
+} 2
+test switch-1.11 {simple patterns with -nocase} {
+ switch -nocase x a {subst 1} default {subst 2} c {subst 3} default {subst 4}
} 4
test switch-2.1 {single-argument form for pattern/command pairs} {
switch b {
- a {format 1}
- b {format 2}
- default {format 6}
+ a {subst 1}
+ b {subst 2}
+ default {subst 6}
}
} {2}
-test switch-2.2 {single-argument form for pattern/command pairs} {
- list [catch {switch z {a 2 b}} msg] $msg
-} {1 {extra switch pattern with no body}}
+test switch-2.2 {single-argument form for pattern/command pairs} -body {
+ switch z {a 2 b}
+} -returnCodes error -result {extra switch pattern with no body}
test switch-3.1 {-exact vs. -glob vs. -regexp} {
switch -exact aaaab {
- ^a*b$ {concat regexp}
- *b {concat glob}
- aaaab {concat exact}
- default {concat none}
+ ^a*b$ {subst regexp}
+ *b {subst glob}
+ aaaab {subst exact}
+ default {subst none}
}
} exact
test switch-3.2 {-exact vs. -glob vs. -regexp} {
switch -regexp aaaab {
- ^a*b$ {concat regexp}
- *b {concat glob}
- aaaab {concat exact}
- default {concat none}
+ ^a*b$ {subst regexp}
+ *b {subst glob}
+ aaaab {subst exact}
+ default {subst none}
}
} regexp
test switch-3.3 {-exact vs. -glob vs. -regexp} {
switch -glob aaaab {
- ^a*b$ {concat regexp}
- *b {concat glob}
- aaaab {concat exact}
- default {concat none}
+ ^a*b$ {subst regexp}
+ *b {subst glob}
+ aaaab {subst exact}
+ default {subst none}
}
} glob
test switch-3.4 {-exact vs. -glob vs. -regexp} {
- switch aaaab {^a*b$} {concat regexp} *b {concat glob} \
- aaaab {concat exact} default {concat none}
+ switch aaaab {^a*b$} {subst regexp} *b {subst glob} \
+ aaaab {subst exact} default {subst none}
} exact
test switch-3.5 {-exact vs. -glob vs. -regexp} {
switch -- -glob {
- ^g.*b$ {concat regexp}
- -* {concat glob}
- -glob {concat exact}
- default {concat none}
+ ^g.*b$ {subst regexp}
+ -* {subst glob}
+ -glob {subst exact}
+ default {subst none}
+ }
+} exact
+test switch-3.6 {-exact vs. -glob vs. -regexp} -body {
+ switch -foo a b c
+} -returnCodes error -result {bad option "-foo": must be -exact, -glob, -indexvar, -matchvar, -nocase, -regexp, or --}
+test switch-3.7 {-exact vs. -glob vs. -regexp with -nocase} {
+ switch -exact -nocase aaaab {
+ ^a*b$ {subst regexp}
+ *b {subst glob}
+ aaaab {subst exact}
+ default {subst none}
+ }
+} exact
+test switch-3.8 {-exact vs. -glob vs. -regexp with -nocase} {
+ switch -regexp -nocase aaaab {
+ ^a*b$ {subst regexp}
+ *b {subst glob}
+ aaaab {subst exact}
+ default {subst none}
+ }
+} regexp
+test switch-3.9 {-exact vs. -glob vs. -regexp with -nocase} {
+ switch -glob -nocase aaaab {
+ ^a*b$ {subst regexp}
+ *b {subst glob}
+ aaaab {subst exact}
+ default {subst none}
}
+} glob
+test switch-3.10 {-exact vs. -glob vs. -regexp with -nocase} {
+ switch -nocase aaaab {^a*b$} {subst regexp} *b {subst glob} \
+ aaaab {subst exact} default {subst none}
} exact
-test switch-3.6 {-exact vs. -glob vs. -regexp} {
- list [catch {switch -foo a b c} msg] $msg
-} {1 {bad option "-foo": must be -exact, -glob, -regexp, or --}}
+test switch-3.11 {-exact vs. -glob vs. -regexp with -nocase} {
+ switch -nocase -- -glob {
+ ^g.*b$ {subst regexp}
+ -* {subst glob}
+ -glob {subst exact}
+ default {subst none}
+ }
+} exact
+test switch-3.12 {-exact vs. -glob vs. -regexp} {
+ switch -exa Foo Foo {set result OK}
+} OK
+test switch-3.13 {-exact vs. -glob vs. -regexp} {
+ switch -gl Foo Fo? {set result OK}
+} OK
+test switch-3.14 {-exact vs. -glob vs. -regexp} {
+ switch -re Foo Fo. {set result OK}
+} OK
+test switch-3.15 {-exact vs. -glob vs. -regexp} -body {
+ switch -exact -exact Foo Foo {set result OK}
+} -returnCodes error -result {bad option "-exact": -exact option already found}
+test switch-3.16 {-exact vs. -glob vs. -regexp} -body {
+ switch -exact -glob Foo Foo {set result OK}
+} -returnCodes error -result {bad option "-glob": -exact option already found}
+test switch-3.17 {-exact vs. -glob vs. -regexp} -body {
+ switch -glob -regexp Foo Foo {set result OK}
+} -returnCodes error -result {bad option "-regexp": -glob option already found}
+test switch-3.18 {-exact vs. -glob vs. -regexp} -body {
+ switch -regexp -glob Foo Foo {set result OK}
+} -returnCodes error -result {bad option "-glob": -regexp option already found}
test switch-4.1 {error in executed command} {
- list [catch {switch a a {error "Just a test"} default {format 1}} msg] \
- $msg $errorInfo
+ list [catch {switch a a {error "Just a test"} default {subst 1}} msg] \
+ $msg $::errorInfo
} {1 {Just a test} {Just a test
while executing
"error "Just a test""
("a" arm line 1)
invoked from within
-"switch a a {error "Just a test"} default {format 1}"}}
-test switch-4.2 {error: not enough args} {
- list [catch {switch} msg] $msg
-} {1 {wrong # args: should be "switch ?switches? string pattern body ... ?default body?"}}
-test switch-4.3 {error: pattern with no body} {
- list [catch {switch a b} msg] $msg
-} {1 {extra switch pattern with no body}}
-test switch-4.4 {error: pattern with no body} {
- list [catch {switch a b {format 1} c} msg] $msg
-} {1 {extra switch pattern with no body}}
+"switch a a {error "Just a test"} default {subst 1}"}}
+test switch-4.2 {error: not enough args} -returnCodes error -body {
+ switch
+} -result {wrong # args: should be "switch ?switches? string pattern body ... ?default body?"}
+test switch-4.3 {error: pattern with no body} -body {
+ switch a b
+} -returnCodes error -result {extra switch pattern with no body}
+test switch-4.4 {error: pattern with no body} -body {
+ switch a b {subst 1} c
+} -returnCodes error -result {extra switch pattern with no body}
test switch-4.5 {error in default command} {
list [catch {switch foo a {error switch1} b {error switch 3} \
- default {error switch2}} msg] $msg $errorInfo
+ default {error switch2}} msg] $msg $::errorInfo
} {1 switch2 {switch2
while executing
"error switch2"
@@ -117,30 +186,30 @@ test switch-4.5 {error in default command} {
invoked from within
"switch foo a {error switch1} b {error switch 3} default {error switch2}"}}
-test switch-5.1 {errors in -regexp matching} {
- list [catch {switch -regexp aaaab {
- *b {concat glob}
- aaaab {concat exact}
- default {concat none}
- }} msg] $msg
-} {1 {couldn't compile regular expression pattern: quantifier operand invalid}}
+test switch-5.1 {errors in -regexp matching} -returnCodes error -body {
+ switch -regexp aaaab {
+ *b {subst glob}
+ aaaab {subst exact}
+ default {subst none}
+ }
+} -result {couldn't compile regular expression pattern: quantifier operand invalid}
test switch-6.1 {backslashes in patterns} {
switch -exact {\a\$\.\[} {
- \a\$\.\[ {concat first}
- \a\\$\.\\[ {concat second}
- \\a\\$\\.\\[ {concat third}
- {\a\\$\.\\[} {concat fourth}
- {\\a\\$\\.\\[} {concat fifth}
- default {concat none}
+ \a\$\.\[ {subst first}
+ \a\\$\.\\[ {subst second}
+ \\a\\$\\.\\[ {subst third}
+ {\a\\$\.\\[} {subst fourth}
+ {\\a\\$\\.\\[} {subst fifth}
+ default {subst none}
}
} third
test switch-6.2 {backslashes in patterns} {
switch -exact {\a\$\.\[} {
- \a\$\.\[ {concat first}
- {\a\$\.\[} {concat second}
- {{\a\$\.\[}} {concat third}
- default {concat none}
+ \a\$\.\[ {subst first}
+ {\a\$\.\[} {subst second}
+ {{\a\$\.\[}} {subst third}
+ default {subst none}
}
} second
@@ -148,28 +217,31 @@ test switch-7.1 {"-" bodies} {
switch a {
a -
b -
- c {concat 1}
- default {concat 2}
+ c {subst 1}
+ default {subst 2}
}
} 1
-test switch-7.2 {"-" bodies} {
- list [catch {
- switch a {
- a -
- b -
- c -
- }
- } msg] $msg
-} {1 {no body specified for pattern "c"}}
-test switch-7.3 {"-" bodies} {
- list [catch {
- switch a {
- a -
- b -foo
- c -
- }
- } msg] $msg
-} {1 {no body specified for pattern "c"}}
+test switch-7.2 {"-" bodies} -body {
+ switch a {
+ a -
+ b -
+ c -
+ }
+} -returnCodes error -result {no body specified for pattern "c"}
+test switch-7.3 {"-" bodies} -body {
+ switch a {
+ a -
+ b -foo
+ c -
+ }
+} -returnCodes error -result {no body specified for pattern "c"}
+test switch-7.4 {"-" bodies} -body {
+ switch a {
+ a -
+ b -foo
+ c {}
+ }
+} -returnCodes error -result {invalid command name "-foo"}
test switch-8.1 {empty body} {
set msg {}
@@ -179,38 +251,495 @@ test switch-8.1 {empty body} {
default {set msg 2}
}
} {}
+proc test_switch_body {} {
+ return "INVOKED"
+}
+test switch-8.2 {weird body text, variable} {
+ set cmd {test_switch_body}
+ switch Foo {
+ Foo $cmd
+ }
+} {INVOKED}
+test switch-8.3 {weird body text, variable} {
+ set cmd {test_switch_body}
+ switch Foo {
+ Foo {$cmd}
+ }
+} {INVOKED}
+
+test switch-9.1 {empty pattern/body list} -returnCodes error -body {
+ switch x
+} -result {wrong # args: should be "switch ?switches? string pattern body ... ?default body?"}
+test switch-9.2 {unpaired pattern} -returnCodes error -body {
+ switch -- x
+} -result {extra switch pattern with no body}
+test switch-9.3 {empty pattern/body list} -body {
+ switch x {}
+} -returnCodes error -result {wrong # args: should be "switch ?switches? string {pattern body ... ?default body?}"}
+test switch-9.4 {empty pattern/body list} -body {
+ switch -- x {}
+} -returnCodes error -result {wrong # args: should be "switch ?switches? string {pattern body ... ?default body?}"}
+test switch-9.5 {unpaired pattern} -body {
+ switch x a {} b
+} -returnCodes error -result {extra switch pattern with no body}
+test switch-9.6 {unpaired pattern} -body {
+ switch x {a {} b}
+} -returnCodes error -result {extra switch pattern with no body}
+test switch-9.7 {unpaired pattern} -body {
+ switch x a {} # comment b
+} -returnCodes error -result {extra switch pattern with no body}
+test switch-9.8 {unpaired pattern} -returnCodes error -body {
+ switch x {a {} # comment b}
+} -result {extra switch pattern with no body, this may be due to a comment incorrectly placed outside of a switch body - see the "switch" documentation}
+test switch-9.9 {unpaired pattern} -body {
+ switch x a {} x {} # comment b
+} -returnCodes error -result {extra switch pattern with no body}
+test switch-9.10 {unpaired pattern} -returnCodes error -body {
+ switch x {a {} x {} # comment b}
+} -result {extra switch pattern with no body, this may be due to a comment incorrectly placed outside of a switch body - see the "switch" documentation}
+
+test switch-10.1 {compiled -exact switch} {
+ if 1 {switch -exact -- a {a {subst 1} b {subst 2}}}
+} 1
+test switch-10.1a {compiled -exact switch} {
+ if 1 {switch -exact a {a {subst 1} b {subst 2}}}
+} 1
+test switch-10.2 {compiled -exact switch} {
+ if 1 {switch -exact -- b {a {subst 1} b {subst 2}}}
+} 2
+test switch-10.2a {compiled -exact switch} {
+ if 1 {switch -exact b {a {subst 1} b {subst 2}}}
+} 2
+test switch-10.3 {compiled -exact switch} {
+ if 1 {switch -exact -- c {a {subst 1} b {subst 2}}}
+} {}
+test switch-10.3a {compiled -exact switch} {
+ if 1 {switch -exact c {a {subst 1} b {subst 2}}}
+} {}
+test switch-10.4 {compiled -exact switch} {
+ if 1 {
+ set x 0
+ switch -exact -- c {a {subst 1} b {subst 2}}
+ }
+} {}
+test switch-10.5 {compiled -exact switch} {
+ if 1 {switch -exact -- a {a - aa {subst 1} b {subst 2}}}
+} 1
+test switch-10.6 {compiled -exact switch} {
+ if 1 {switch -exact -- b {a {
+ set x 1;set x 1;set x 1;set x 1;set x 1;set x 1;set x 1;set x 1
+ set x 1;set x 1;set x 1;set x 1;set x 1;set x 1;set x 1;set x 1
+ set x 1;set x 1;set x 1;set x 1;set x 1;set x 1;set x 1;set x 1
+ set x 1;set x 1;set x 1;set x 1;set x 1;set x 1;set x 1;set x 1
+ set x 1;set x 1;set x 1;set x 1;set x 1;set x 1;set x 1;set x 1
+ set x 1;set x 1;set x 1;set x 1;set x 1;set x 1;set x 1;set x 1
+ set x 1;set x 1;set x 1;set x 1;set x 1;set x 1;set x 1;set x 1
+ set x 1;set x 1;set x 1;set x 1;set x 1;set x 1;set x 1;set x 1
+ } b {subst 2}}}
+} 2
+
+# Command variants are:
+# c* are compiled switches, i* are interpreted
+# *-glob use glob matching, *-exact use exact matching
+# *2* include a default clause (different results too.)
+proc cswtest-glob s {
+ set x 0; set y 0
+ foreach c [split $s {}] {
+ switch -glob $c {
+ a {incr x}
+ b {incr y}
+ }
+ }
+ set x [expr {$x*100}]; set y [expr {$y*100}]
+ foreach c [split $s {}] {
+ switch -glob -- $c a {incr x} b {incr y}
+ }
+ return $x,$y
+}
+proc iswtest-glob s {
+ set x 0; set y 0; set switch switch
+ foreach c [split $s {}] {
+ $switch -glob $c {
+ a {incr x}
+ b {incr y}
+ }
+ }
+ set x [expr {$x*100}]; set y [expr {$y*100}]
+ foreach c [split $s {}] {
+ $switch -glob -- $c a {incr x} b {incr y}
+ }
+ return $x,$y
+}
+proc cswtest-exact s {
+ set x 0; set y 0
+ foreach c [split $s {}] {
+ switch -exact $c {
+ a {incr x}
+ b {incr y}
+ }
+ }
+ set x [expr {$x*100}]; set y [expr {$y*100}]
+ foreach c [split $s {}] {
+ switch -exact -- $c a {incr x} b {incr y}
+ }
+ return $x,$y
+}
+proc iswtest-exact s {
+ set x 0; set y 0; set switch switch
+ foreach c [split $s {}] {
+ $switch -exact $c {
+ a {incr x}
+ b {incr y}
+ }
+ }
+ set x [expr {$x*100}]; set y [expr {$y*100}]
+ foreach c [split $s {}] {
+ $switch -exact -- $c a {incr x} b {incr y}
+ }
+ return $x,$y
+}
+proc cswtest2-glob s {
+ set x 0; set y 0; set z 0
+ foreach c [split $s {}] {
+ switch -glob $c {
+ a {incr x}
+ b {incr y}
+ default {incr z}
+ }
+ }
+ set x [expr {$x*100}]; set y [expr {$y*100}]; set z [expr {$z*100}]
+ foreach c [split $s {}] {
+ switch -glob -- $c a {incr x} b {incr y} default {incr z}
+ }
+ return $x,$y,$z
+}
+proc iswtest2-glob s {
+ set x 0; set y 0; set z 0; set switch switch
+ foreach c [split $s {}] {
+ $switch -glob $c {
+ a {incr x}
+ b {incr y}
+ default {incr z}
+ }
+ }
+ set x [expr {$x*100}]; set y [expr {$y*100}]; set z [expr {$z*100}]
+ foreach c [split $s {}] {
+ $switch -glob -- $c a {incr x} b {incr y} default {incr z}
+ }
+ return $x,$y,$z
+}
+proc cswtest2-exact s {
+ set x 0; set y 0; set z 0
+ foreach c [split $s {}] {
+ switch -exact $c {
+ a {incr x}
+ b {incr y}
+ default {incr z}
+ }
+ }
+ set x [expr {$x*100}]; set y [expr {$y*100}]; set z [expr {$z*100}]
+ foreach c [split $s {}] {
+ switch -exact -- $c a {incr x} b {incr y} default {incr z}
+ }
+ return $x,$y,$z
+}
+proc iswtest2-exact s {
+ set x 0; set y 0; set z 0; set switch switch
+ foreach c [split $s {}] {
+ $switch -exact $c {
+ a {incr x}
+ b {incr y}
+ default {incr z}
+ }
+ }
+ set x [expr {$x*100}]; set y [expr {$y*100}]; set z [expr {$z*100}]
+ foreach c [split $s {}] {
+ $switch -exact -- $c a {incr x} b {incr y} default {incr z}
+ }
+ return $x,$y,$z
+}
-test switch-9.1 {empty pattern/body list} {
- list [catch {switch x} msg] $msg
-} {1 {wrong # args: should be "switch ?switches? string pattern body ... ?default body?"}}
-test switch-9.2 {empty pattern/body list} {
- list [catch {switch -- x} msg] $msg
-} {1 {wrong # args: should be "switch ?switches? string pattern body ... ?default body?"}}
-test switch-9.3 {empty pattern/body list} {
- list [catch {switch x {}} msg] $msg
-} {1 {wrong # args: should be "switch ?switches? string {pattern body ... ?default body?}"}}
-test switch-9.4 {empty pattern/body list} {
- list [catch {switch -- x {}} msg] $msg
-} {1 {wrong # args: should be "switch ?switches? string {pattern body ... ?default body?}"}}
-test switch-9.5 {unpaired pattern} {
- list [catch {switch x a {} b} msg] $msg
-} {1 {extra switch pattern with no body}}
-test switch-9.6 {unpaired pattern} {
- list [catch {switch x {a {} b}} msg] $msg
-} {1 {extra switch pattern with no body}}
-test switch-9.7 {unpaired pattern} {
- list [catch {switch x a {} # comment b} msg] $msg
-} {1 {extra switch pattern with no body}}
-test switch-9.8 {unpaired pattern} {
- list [catch {switch x {a {} # comment b}} msg] $msg
-} {1 {extra switch pattern with no body, this may be due to a comment incorrectly placed outside of a switch body - see the "switch" documentation}}
-test switch-9.9 {unpaired pattern} {
- list [catch {switch x a {} x {} # comment b} msg] $msg
-} {1 {extra switch pattern with no body}}
-test switch-9.10 {unpaired pattern} {
- list [catch {switch x {a {} x {} # comment b}} msg] $msg
-} {1 {extra switch pattern with no body, this may be due to a comment incorrectly placed outside of a switch body - see the "switch" documentation}}
+test switch-10.7 {comparison of compiled and interpreted behaviour of switch, exact matching} {
+ cswtest-exact abcb
+} [iswtest-exact abcb]
+test switch-10.8 {comparison of compiled and interpreted behaviour of switch, glob matching} {
+ cswtest-glob abcb
+} [iswtest-glob abcb]
+test switch-10.9 {comparison of compiled and interpreted behaviour of switch, exact matching with default} {
+ cswtest2-exact abcb
+} [iswtest2-exact abcb]
+test switch-10.10 {comparison of compiled and interpreted behaviour of switch, glob matching with default} {
+ cswtest2-glob abcb
+} [iswtest2-glob abcb]
+proc cswtest-default-exact {x} {
+ switch -- $x {
+ a* {return b}
+ aa {return c}
+ default {return d}
+ }
+}
+test switch-10.11 {default to exact matching when compiled} {
+ cswtest-default-exact a
+} d
+test switch-10.12 {default to exact matching when compiled} {
+ cswtest-default-exact aa
+} c
+test switch-10.13 {default to exact matching when compiled} {
+ cswtest-default-exact a*
+} b
+test switch-10.14 {default to exact matching when compiled} {
+ cswtest-default-exact a**
+} d
+rename cswtest-default-exact {}
+rename cswtest-glob {}
+rename iswtest-glob {}
+rename cswtest2-glob {}
+rename iswtest2-glob {}
+rename cswtest-exact {}
+rename iswtest-exact {}
+rename cswtest2-exact {}
+rename iswtest2-exact {}
+# Bug 1891827
+test switch-10.15 {(not) compiled exact nocase regression} {
+ apply {{} {
+ switch -nocase -- A { a {return yes} default {return no} }
+ }}
+} yes
+
+# Added due to TIP#75
+test switch-11.1 {regexp matching with -matchvar} {
+ switch -regexp -matchvar x -- abc {.(.). {set x}}
+} {abc b}
+test switch-11.2 {regexp matching with -matchvar} {
+ set x GOOD
+ switch -regexp -matchvar x -- abc {.(.).. {list $x z}}
+ set x
+} GOOD
+test switch-11.3 {regexp matching with -matchvar} {
+ switch -regexp -matchvar x -- "a b c" {.(.). {set x}}
+} {{a b} { }}
+test switch-11.4 {regexp matching with -matchvar} {
+ set x BAD
+ switch -regexp -matchvar x -- "a b c" {
+ bc {list $x YES}
+ default {list $x NO}
+ }
+} {{} NO}
+test switch-11.5 {-matchvar without -regexp} {
+ set x {}
+ list [catch {switch -glob -matchvar x -- abc . {set x}} msg] $x $msg
+} {1 {} {-matchvar option requires -regexp option}}
+test switch-11.6 {-matchvar unwritable} {
+ set x {}
+ list [catch {switch -regexp -matchvar x(x) -- abc . {set x}} msg] $x $msg
+} {1 {} {can't set "x(x)": variable isn't array}}
+
+test switch-12.1 {regexp matching with -indexvar} {
+ switch -regexp -indexvar x -- abc {.(.). {set x}}
+} {{0 3} {1 2}}
+test switch-12.2 {regexp matching with -indexvar} {
+ set x GOOD
+ switch -regexp -indexvar x -- abc {.(.).. {list $x z}}
+ set x
+} GOOD
+test switch-12.3 {regexp matching with -indexvar} {
+ switch -regexp -indexvar x -- "a b c" {.(.). {set x}}
+} {{0 3} {1 2}}
+test switch-12.4 {regexp matching with -indexvar} {
+ set x BAD
+ switch -regexp -indexvar x -- "a b c" {
+ bc {list $x YES}
+ default {list $x NO}
+ }
+} {{} NO}
+test switch-12.5 {-indexvar without -regexp} {
+ set x {}
+ list [catch {switch -glob -indexvar x -- abc . {set x}} msg] $x $msg
+} {1 {} {-indexvar option requires -regexp option}}
+test switch-12.6 {-indexvar unwritable} {
+ set x {}
+ list [catch {switch -regexp -indexvar x(x) -- abc . {set x}} msg] $x $msg
+} {1 {} {can't set "x(x)": variable isn't array}}
+
+test switch-13.1 {-indexvar -matchvar combinations} {
+ switch -regexp -indexvar x -matchvar y abc {
+ . {list $x $y}
+ }
+} {{{0 1}} a}
+test switch-13.2 {-indexvar -matchvar combinations} {
+ switch -regexp -indexvar x -matchvar y abc {
+ .$ {list $x $y}
+ }
+} {{{2 3}} c}
+test switch-13.3 {-indexvar -matchvar combinations} {
+ switch -regexp -indexvar x -matchvar y abc {
+ (.)(.)(.) {list $x $y}
+ }
+} {{{0 3} {0 1} {1 2} {2 3}} {abc a b c}}
+test switch-13.4 {-indexvar -matchvar combinations} {
+ set x -
+ set y -
+ switch -regexp -indexvar x -matchvar y abc {
+ (.)(.)(.). -
+ default {list $x $y}
+ }
+} {{} {}}
+test switch-13.5 {-indexvar -matchvar combinations} {
+ set x -
+ set y -
+ list [catch {
+ switch -regexp -indexvar x(x) -matchvar y abc {. {list $x $y}}
+ } msg] $x $y $msg
+} {1 - - {can't set "x(x)": variable isn't array}}
+test switch-13.6 {-indexvar -matchvar combinations} {
+ set x -
+ set y -
+ list [catch {
+ switch -regexp -indexvar x -matchvar y(y) abc {. {list $x $y}}
+ } msg] $x $y $msg
+} {1 {{0 1}} - {can't set "y(y)": variable isn't array}}
+
+test switch-14.1 {-regexp -- compilation [Bug 1854399]} {
+ switch -regexp -- 0 {
+ {[0-9]+} {return yes}
+ default {return no}
+ }
+ foo
+} yes
+test switch-14.2 {-regexp -- compilation [Bug 1854399]} {
+ proc foo {} {
+ switch -regexp -- 0 {
+ {[0-9]+} {return yes}
+ default {return no}
+ }
+ }
+ foo
+} yes
+test switch-14.3 {-regexp -- compilation [Bug 1854399]} {
+ proc foo {} {
+ switch -regexp -- 0 {
+ {\d+} {return yes}
+ default {return no}
+ }
+ }
+ foo
+} yes
+test switch-14.4 {-regexp -- compilation [Bug 1854399]} {
+ proc foo {} {
+ switch -regexp -- 0 {
+ {0} {return yes}
+ default {return no}
+ }
+ }
+ foo
+} yes
+test switch-14.5 {switch -regexp compilation} {
+ apply {{} {
+ switch -regexp -- 0 {
+ {0|1|2} {return yes}
+ default {return no}
+ }
+ }}
+} yes
+test switch-14.6 {switch -regexp compilation} {
+ apply {{} {
+ switch -regexp -- 0 {
+ {0|11|222} {return yes}
+ default {return no}
+ }
+ }}
+} yes
+test switch-14.7 {switch -regexp compilation} {
+ apply {{} {
+ switch -regexp -- 0 {
+ {[012]} {return yes}
+ default {return no}
+ }
+ }}
+} yes
+test switch-14.8 {switch -regexp compilation} {
+ apply {{} {
+ switch -regexp -- x {
+ {0|1|2} {return yes}
+ default {return no}
+ }
+ }}
+} no
+test switch-14.9 {switch -regexp compilation} {
+ apply {{} {
+ switch -regexp -- x {
+ {0|11|222} {return yes}
+ default {return no}
+ }
+ }}
+} no
+test switch-14.10 {switch -regexp compilation} {
+ apply {{} {
+ switch -regexp -- x {
+ {[012]} {return yes}
+ default {return no}
+ }
+ }}
+} no
+test switch-14.11 {switch -regexp compilation} {
+ apply {{} {
+ switch -regexp -- x {
+ {0|1|2} {return yes}
+ .+ {return yes2}
+ default {return no}
+ }
+ }}
+} yes2
+test switch-14.12 {switch -regexp compilation} {
+ apply {{} {
+ switch -regexp -- x {
+ {0|11|222} {return yes}
+ .+ {return yes2}
+ default {return no}
+ }
+ }}
+} yes2
+test switch-14.13 {switch -regexp compilation} {
+ apply {{} {
+ switch -regexp -- x {
+ {[012]} {return yes}
+ .+ {return yes2}
+ default {return no}
+ }
+ }}
+} yes2
+test switch-14.14 {switch -regexp compilation} {
+ apply {{} {
+ switch -regexp -- {} {
+ {0|1|2} {return yes}
+ .+ {return yes2}
+ default {return no}
+ }
+ }}
+} no
+test switch-14.15 {switch -regexp compilation} {
+ apply {{} {
+ switch -regexp -- {} {
+ {0|11|222} {return yes}
+ .+ {return yes2}
+ default {return no}
+ }
+ }}
+} no
+test switch-14.16 {switch -regexp compilation} {
+ apply {{} {
+ switch -regexp -- {} {
+ {[012]} {return yes}
+ .+ {return yes2}
+ default {return no}
+ }
+ }}
+} no
# cleanup
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/tcltest.test b/tests/tcltest.test
index 97a2863..86aca6f 100755..100644
--- a/tests/tcltest.test
+++ b/tests/tcltest.test
@@ -2,11 +2,11 @@
# built-in commands. Sourcing this file into Tcl runs the tests and
# generates output for errors. No output means no errors were found.
#
-# Copyright (c) 1998-1999 by Scriptics Corporation.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2000 by Ajuba Solutions
# All rights reserved.
-# Note that there are several places where the value of
+# Note that there are several places where the value of
# tcltest::currentFailure is stored/reset in the -setup/-cleanup
# of a test that has a body that runs [test] that will fail.
# This is a workaround of using the same tcltest code that we are
@@ -14,7 +14,7 @@
#
# It would be better to have the -body of the tests run the tcltest
# commands in a slave interp so the [test] being tested would not
-# interfere with the [test] doing the testing.
+# interfere with the [test] doing the testing.
#
if {[catch {package require tcltest 2.1}]} {
@@ -51,7 +51,7 @@ testConstraint exec [llength [info commands exec]]
test tcltest-1.1 {tcltest -help} {exec} {
set result [catch {exec [interpreter] test.tcl -help} msg]
list $result [regexp Usage $msg]
-} {1 1}
+} {1 1}
test tcltest-1.2 {tcltest -help -something} {exec} {
set result [catch {exec [interpreter] test.tcl -help -something} msg]
list $result [regexp Usage $msg]
@@ -59,7 +59,7 @@ test tcltest-1.2 {tcltest -help -something} {exec} {
test tcltest-1.3 {tcltest -h} {exec} {
set result [catch {exec [interpreter] test.tcl -h} msg]
list $result [regexp Usage $msg]
-} {1 0}
+} {1 0}
# -verbose, implicit & explicit testing of [verbose]
proc slave {msgVar args} {
@@ -437,7 +437,7 @@ test tcltest-6.7 {tcltest::outputChannel - retrieval} {
}
-result {stdout}
-cleanup {
- set tcltest::outputChannel $of
+ set ::tcltest::outputChannel $of
}
}
@@ -526,30 +526,29 @@ set normaldirectory [makeDirectory normaldirectory]
normalizePath normaldirectory
# -tmpdir, [temporaryDirectory]
-test tcltest-8.1 {tcltest a.tcl -tmpdir a} {unixOrPc} {
+test tcltest-8.1 {tcltest a.tcl -tmpdir a} -constraints unixOrPc -setup {
file delete -force thisdirectorydoesnotexist
+} -body {
slave msg $a -tmpdir thisdirectorydoesnotexist
- list [file exists [file join thisdirectorydoesnotexist a.tmp]] \
- [file delete -force thisdirectorydoesnotexist]
-} {1 {}}
+ file exists [file join thisdirectorydoesnotexist a.tmp]
+} -cleanup {
+ file delete -force thisdirectorydoesnotexist
+} -result 1
test tcltest-8.2 {tcltest a.tcl -tmpdir thisdirectoryisafile} {
-constraints unixOrPc
-body {
slave msg $a -tmpdir $tdiaf
- set msg
+ return $msg
}
-result {*not a directory*}
-match glob
}
-
# Test non-writeable directories, non-readable directories with directory flags
set notReadableDir [file join [temporaryDirectory] notreadable]
set notWriteableDir [file join [temporaryDirectory] notwriteable]
-
makeDirectory notreadable
makeDirectory notwriteable
-
-switch $tcl_platform(platform) {
+switch -- $::tcl_platform(platform) {
"unix" {
file attributes $notReadableDir -permissions 00333
file attributes $notWriteableDir -permissions 00555
@@ -559,25 +558,44 @@ switch $tcl_platform(platform) {
catch {testchmod 000 $notWriteableDir}
}
}
-
-test tcltest-8.3 {tcltest a.tcl -tmpdir notReadableDir} {unix notRoot} {
- slave msg $a -tmpdir $notReadableDir
- string match {*not readable*} $msg
-} {1}
-
-test tcltest-8.4 {tcltest a.tcl -tmpdir notWriteableDir} {unixOrPc notRoot} {
- slave msg $a -tmpdir $notWriteableDir
- string match {*not writeable*} $msg
-} {1}
-
-test tcltest-8.5 {tcltest a.tcl -tmpdir normaldirectory} {unixOrPc} {
- slave msg $a -tmpdir $normaldirectory
- # The join is necessary because the message can be split on multiple lines
- list [file exists [file join $normaldirectory a.tmp]] \
- [file delete [file join $normaldirectory a.tmp]]
-} {1 {}}
+test tcltest-8.3 {tcltest a.tcl -tmpdir notReadableDir} {
+ -constraints {unix notRoot}
+ -body {
+ slave msg $a -tmpdir $notReadableDir
+ return $msg
+ }
+ -result {*not readable*}
+ -match glob
+}
+# This constraint doesn't go at the top of the file so that it doesn't
+# interfere with tcltest-5.5
+testConstraint notFAT [expr {
+ ![string match "FAT*" [lindex [file system $notWriteableDir] 1]]
+}]
+# FAT permissions are fairly hopeless; ignore this test if that FS is used
+test tcltest-8.4 {tcltest a.tcl -tmpdir notWriteableDir} {
+ -constraints {unixOrPc notRoot notFAT}
+ -body {
+ slave msg $a -tmpdir $notWriteableDir
+ return $msg
+ }
+ -result {*not writeable*}
+ -match glob
+}
+test tcltest-8.5 {tcltest a.tcl -tmpdir normaldirectory} {
+ -constraints unixOrPc
+ -body {
+ slave msg $a -tmpdir $normaldirectory
+ # The join is necessary because the message can be split on multiple
+ # lines
+ file exists [file join $normaldirectory a.tmp]
+ }
+ -cleanup {
+ catch {file delete [file join $normaldirectory a.tmp]}
+ }
+ -result 1
+}
cd [workingDirectory]
-
test tcltest-8.6 {temporaryDirectory} {
-setup {
set old $::tcltest::temporaryDirectory
@@ -594,7 +612,6 @@ test tcltest-8.6 {temporaryDirectory} {
set ::tcltest::temporaryDirectory $old
}
}
-
test tcltest-8.6a {temporaryDirectory - test format 2} -setup {
set old $::tcltest::temporaryDirectory
set ::tcltest::temporaryDirectory $normaldirectory
@@ -606,35 +623,53 @@ test tcltest-8.6a {temporaryDirectory - test format 2} -setup {
} -cleanup {
set ::tcltest::temporaryDirectory $old
} -result [list $normaldirectory [workingDirectory] [workingDirectory]]
-
cd [temporaryDirectory]
# -testdir, [testsDirectory]
-test tcltest-8.10 {tcltest a.tcl -testdir thisdirectorydoesnotexist} {unixOrPc} {
- file delete -force thisdirectorydoesnotexist
- slave msg $a -testdir thisdirectorydoesnotexist
- string match "*does not exist*" $msg
-} {1}
-
-test tcltest-8.11 {tcltest a.tcl -testdir thisdirectoryisafile} {unixOrPc} {
- slave msg $a -testdir $tdiaf
- string match "*not a directory*" $msg
-} {1}
-
-test tcltest-8.12 {tcltest a.tcl -testdir notReadableDir} {unix notRoot} {
- slave msg $a -testdir $notReadableDir
- string match {*not readable*} $msg
-} {1}
-
-
-test tcltest-8.13 {tcltest a.tcl -testdir normaldirectory} {unixOrPc} {
- slave msg $a -testdir $normaldirectory
- # The join is necessary because the message can be split on multiple lines
- list [string first "testdir: $normaldirectory" [join $msg]] \
- [file exists [file join [temporaryDirectory] a.tmp]] \
- [file delete [file join [temporaryDirectory] a.tmp]]
-} {0 1 {}}
+test tcltest-8.10 {tcltest a.tcl -testdir thisdirectorydoesnotexist} {
+ -constraints unixOrPc
+ -setup {
+ file delete -force thisdirectorydoesnotexist
+ }
+ -body {
+ slave msg $a -testdir thisdirectorydoesnotexist
+ return $msg
+ }
+ -match glob
+ -result {*does not exist*}
+}
+test tcltest-8.11 {tcltest a.tcl -testdir thisdirectoryisafile} {
+ -constraints unixOrPc
+ -body {
+ slave msg $a -testdir $tdiaf
+ return $msg
+ }
+ -match glob
+ -result {*not a directory*}
+}
+test tcltest-8.12 {tcltest a.tcl -testdir notReadableDir} {
+ -constraints {unix notRoot}
+ -body {
+ slave msg $a -testdir $notReadableDir
+ return $msg
+ }
+ -match glob
+ -result {*not readable*}
+}
+test tcltest-8.13 {tcltest a.tcl -testdir normaldirectory} {
+ -constraints unixOrPc
+ -body {
+ slave msg $a -testdir $normaldirectory
+ # The join is necessary because the message can be split on multiple
+ # lines
+ list [string first "testdir: $normaldirectory" [join $msg]] \
+ [file exists [file join [temporaryDirectory] a.tmp]]
+ }
+ -cleanup {
+ file delete [file join [temporaryDirectory] a.tmp]
+ }
+ -result {0 1}
+}
cd [workingDirectory]
-
set current [pwd]
test tcltest-8.14 {testsDirectory} {
-setup {
@@ -652,7 +687,6 @@ test tcltest-8.14 {testsDirectory} {
set ::tcltest::testsDirectory $old
}
}
-
# [workingDirectory]
test tcltest-8.60 {::workingDirectory} {
-setup {
@@ -665,7 +699,7 @@ test tcltest-8.60 {::workingDirectory} {
set f1 [workingDirectory]
set f2 [pwd]
set f3 [workingDirectory $current]
- set f4 [pwd]
+ set f4 [pwd]
set f5 [workingDirectory]
list $f1 $f2 $f3 $f4 $f5
}
@@ -682,7 +716,7 @@ test tcltest-8.60 {::workingDirectory} {
# clean up from directory testing
-switch $tcl_platform(platform) {
+switch $::tcl_platform(platform) {
"unix" {
file attributes $notReadableDir -permissions 777
file attributes $notWriteableDir -permissions 777
@@ -704,7 +738,7 @@ test tcltest-9.1 {-file d*.tcl} -constraints {unixOrPc} -setup {
testsDirectory [file dirname [info script]]
} -body {
slave msg [file join [testsDirectory] all.tcl] -file d*.test
- set msg
+ return $msg
} -cleanup {
testsDirectory $old
} -match regexp -result {dstring\.test}
@@ -813,17 +847,17 @@ test tcltest-10.4 {-preservecore 3} {unixOrPc} {
removeFile makecore.tcl
# -load, -loadfile, [loadScript], [loadFile]
-set contents {
+set contents {
package require tcltest
namespace import tcltest::*
puts [outputChannel] $::tcltest::loadScript
exit
-}
+}
set loadfile [makeFile $contents load.tcl]
test tcltest-12.1 {-load xxx} {unixOrPc} {
slave msg $loadfile -load xxx
- set msg
+ return $msg
} {xxx}
# Using child process because of -debug usage.
@@ -914,7 +948,7 @@ test tcltest-14.1 {-singleproc - single process} {
-constraints {unixOrPc}
-body {
slave msg $allfile -singleproc 0 -tmpdir [temporaryDirectory]
- set msg
+ return $msg
}
-result {Test file error: can't unset .foo.: no such variable}
-match regexp
@@ -924,7 +958,7 @@ test tcltest-14.2 {-singleproc - multiple process} {
-constraints {unixOrPc}
-body {
slave msg $allfile -singleproc 1 -tmpdir [temporaryDirectory]
- set msg
+ return $msg
}
-result {single1.test.*single2.test.*all\-single.tcl:.*Total.*0.*Passed.*0.*Skipped.*0.*Failed.*0}
-match regexp
@@ -1758,7 +1792,7 @@ test tcltest-25.3 {
test tcltest-26.1 {Bug/RFE 1017151} -setup {
makeFile {
package require tcltest
- set errorInfo "Should never see this"
+ set ::errorInfo "Should never see this"
tcltest::test tcltest-26.1.0 {
no errorInfo when only return code mismatch
} -body {
@@ -1768,7 +1802,7 @@ test tcltest-26.1 {Bug/RFE 1017151} -setup {
} test.tcl
} -body {
slave msg [file join [temporaryDirectory] test.tcl]
- set msg
+ return $msg
} -cleanup {
removeFile test.tcl
} -match glob -result {*
@@ -1778,7 +1812,7 @@ test tcltest-26.1 {Bug/RFE 1017151} -setup {
test tcltest-26.2 {Bug/RFE 1017151} -setup {
makeFile {
package require tcltest
- set errorInfo "Should never see this"
+ set ::errorInfo "Should never see this"
tcltest::test tcltest-26.2.0 {do not mask body errorInfo} -body {
error "body error"
} -cleanup {
@@ -1788,7 +1822,7 @@ test tcltest-26.2 {Bug/RFE 1017151} -setup {
} test.tcl
} -body {
slave msg [file join [temporaryDirectory] test.tcl]
- set msg
+ return $msg
} -cleanup {
removeFile test.tcl
} -match glob -result {*
diff --git a/tests/thread.test b/tests/thread.test
index 0edddd2..bfef91c 100644
--- a/tests/thread.test
+++ b/tests/thread.test
@@ -17,11 +17,9 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
# Some tests require the testthread command
-set ::tcltest::testConstraints(testthread) \
- [expr {[info commands testthread] != {}}]
-
-if {$::tcltest::testConstraints(testthread)} {
+testConstraint testthread [expr {[info commands testthread] != {}}]
+if {[testConstraint testthread]} {
testthread errorproc ThreadError
proc ThreadError {id info} {
@@ -38,15 +36,12 @@ if {$::tcltest::testConstraints(testthread)} {
test thread-1.1 {Tcl_ThreadObjCmd: no args} {testthread} {
list [catch {testthread} msg] $msg
} {1 {wrong # args: should be "testthread option ?args?"}}
-
test thread-1.2 {Tcl_ThreadObjCmd: bad option} {testthread} {
list [catch {testthread foo} msg] $msg
} {1 {bad option "foo": must be create, exit, id, join, names, send, wait, or errorproc}}
-
test thread-1.3 {Tcl_ThreadObjCmd: initial thread list} {testthread} {
list [threadReap] [llength [testthread names]]
} {1 1}
-
test thread-1.4 {Tcl_ThreadObjCmd: thread create } {testthread} {
threadReap
set serverthread [testthread create]
@@ -55,7 +50,6 @@ test thread-1.4 {Tcl_ThreadObjCmd: thread create } {testthread} {
threadReap
set numthreads
} {2}
-
test thread-1.5 {Tcl_ThreadObjCmd: thread create one shot} {testthread} {
threadReap
testthread create {set x 5}
@@ -71,7 +65,6 @@ test thread-1.5 {Tcl_ThreadObjCmd: thread create one shot} {testthread} {
threadReap
set l
} {1}
-
test thread-1.6 {Tcl_ThreadObjCmd: thread exit} {testthread} {
threadReap
testthread create {testthread exit}
@@ -81,35 +74,28 @@ test thread-1.6 {Tcl_ThreadObjCmd: thread exit} {testthread} {
threadReap
set result
} {1}
-
test thread-1.7 {Tcl_ThreadObjCmd: thread id args} {testthread} {
set x [catch {testthread id x} msg]
list $x $msg
} {1 {wrong # args: should be "testthread id"}}
-
test thread-1.8 {Tcl_ThreadObjCmd: thread id} {testthread} {
string compare [testthread id] $::tcltest::mainThread
} {0}
-
test thread-1.9 {Tcl_ThreadObjCmd: thread names args} {testthread} {
set x [catch {testthread names x} msg]
list $x $msg
} {1 {wrong # args: should be "testthread names"}}
-
test thread-1.10 {Tcl_ThreadObjCmd: thread id} {testthread} {
string compare [testthread names] $::tcltest::mainThread
} {0}
-
test thread-1.11 {Tcl_ThreadObjCmd: send args} {testthread} {
set x [catch {testthread send} msg]
list $x $msg
} {1 {wrong # args: should be "testthread send ?-async? id script"}}
-
test thread-1.12 {Tcl_ThreadObjCmd: send nonint} {testthread} {
set x [catch {testthread send abc command} msg]
list $x $msg
} {1 {expected integer but got "abc"}}
-
test thread-1.13 {Tcl_ThreadObjCmd: send args} {testthread} {
threadReap
set serverthread [testthread create]
@@ -117,13 +103,11 @@ test thread-1.13 {Tcl_ThreadObjCmd: send args} {testthread} {
threadReap
set five
} 5
-
test thread-1.14 {Tcl_ThreadObjCmd: send bad id} {testthread} {
set tid [expr $::tcltest::mainThread + 10]
set x [catch {testthread send $tid {set x 5}} msg]
list $x $msg
} {1 {invalid thread id}}
-
test thread-1.15 {Tcl_ThreadObjCmd: wait} {testthread} {
threadReap
set serverthread [testthread create {set z 5 ; testthread wait}]
@@ -131,12 +115,10 @@ test thread-1.15 {Tcl_ThreadObjCmd: wait} {testthread} {
threadReap
set five
} 5
-
test thread-1.16 {Tcl_ThreadObjCmd: errorproc args} {testthread} {
set x [catch {testthread errorproc foo bar} msg]
list $x $msg
} {1 {wrong # args: should be "testthread errorproc proc"}}
-
test thread-1.17 {Tcl_ThreadObjCmd: errorproc change} {testthread} {
testthread errorproc foo
testthread errorproc ThreadError
@@ -181,7 +163,6 @@ test thread-4.1 {TclThreadSend to self} {testthread} {
}
set x
} {4}
-
test thread-4.2 {TclThreadSend -async} {testthread} {
threadReap
set len [llength [testthread names]]
@@ -196,13 +177,12 @@ test thread-4.2 {TclThreadSend -async} {testthread} {
threadReap
list $len [llength [testthread names]] $two
} {1 1 2}
-
test thread-4.3 {TclThreadSend preserve errorInfo} {testthread} {
threadReap
set len [llength [testthread names]]
set serverthread [testthread create]
set x [catch {testthread send $serverthread {set undef}} msg]
- set savedErrorInfo $errorInfo
+ set savedErrorInfo $::errorInfo
threadReap
list $len $x $msg $savedErrorInfo
} {1 1 {can't read "undef": no such variable} {can't read "undef": no such variable
@@ -210,23 +190,22 @@ test thread-4.3 {TclThreadSend preserve errorInfo} {testthread} {
"set undef"
invoked from within
"testthread send $serverthread {set undef}"}}
-
test thread-4.4 {TclThreadSend preserve code} {testthread} {
threadReap
set len [llength [testthread names]]
set serverthread [testthread create]
- set x [catch {testthread send $serverthread {break}} msg]
- set savedErrorInfo $errorInfo
+ set ::errorInfo {}
+ set x [catch {testthread send $serverthread {set ::errorInfo {}; break}} msg]
+ set savedErrorInfo $::errorInfo
threadReap
list $len $x $msg $savedErrorInfo
} {1 3 {} {}}
-
test thread-4.5 {TclThreadSend preserve errorCode} {testthread} {
threadReap
set ::tcltest::mainThread [testthread names]
set serverthread [testthread create]
set x [catch {testthread send $serverthread {error ERR INFO CODE}} msg]
- set savedErrorCode $errorCode
+ set savedErrorCode $::errorCode
threadReap
list $x $msg $savedErrorCode
} {1 ERR CODE}
@@ -240,7 +219,6 @@ test thread-5.0 {Joining threads} {testthread} {
threadReap
set res
} {0}
-
test thread-5.1 {Joining threads after the fact} {testthread} {
threadReap
set serverthread [testthread create -joinable]
@@ -250,7 +228,6 @@ test thread-5.1 {Joining threads after the fact} {testthread} {
threadReap
set res
} {0}
-
test thread-5.2 {Try to join a detached thread} {testthread} {
threadReap
set serverthread [testthread create]
@@ -260,6 +237,23 @@ test thread-5.2 {Try to join a detached thread} {testthread} {
lrange $msg 0 2
} {cannot join thread}
+test thread-6.1 {freeing very large object trees in a thread} testthread {
+ # conceptual duplicate of obj-32.1
+ threadReap
+ set serverthread [testthread create -joinable]
+ testthread send -async $serverthread {
+ set x {}
+ for {set i 0} {$i<100000} {incr i} {
+ set x [list $x {}]
+ }
+ unset x
+ testthread exit
+ }
+ catch {set res [testthread join $serverthread]} msg
+ threadReap
+ set res
+} {0}
+
# cleanup
::tcltest::cleanupTests
return
diff --git a/tests/timer.test b/tests/timer.test
index 3dd140e..db508e5 100644
--- a/tests/timer.test
+++ b/tests/timer.test
@@ -14,7 +14,7 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest 2
+ package require tcltest
namespace import -force ::tcltest::*
}
@@ -26,8 +26,8 @@ test timer-1.1 {Tcl_CreateTimerHandler procedure} {
foreach i {100 200 1000 50 150} {
after $i lappend x $i
}
- after 200
- update
+ after 200 set done 1
+ vwait done
set x
} {50 100 150 200}
@@ -36,13 +36,13 @@ test timer-2.1 {Tcl_DeleteTimerHandler procedure} {
after cancel $i
}
set x ""
- foreach i {100 200 300 50 150} {
+ foreach i {100 200 1000 50 150} {
after $i lappend x $i
}
after cancel lappend x 150
after cancel lappend x 50
- after 200
- update
+ after 200 set done 1
+ vwait done
set x
} {100 200}
@@ -175,10 +175,10 @@ test timer-6.1 {Tcl_AfterCmd procedure, basics} {
} {1 {wrong # args: should be "after option ?arg arg ...?"}}
test timer-6.2 {Tcl_AfterCmd procedure, basics} {
list [catch {after 2x} msg] $msg
-} {1 {expected integer but got "2x"}}
+} {1 {bad argument "2x": must be cancel, idle, info, or an integer}}
test timer-6.3 {Tcl_AfterCmd procedure, basics} {
list [catch {after gorp} msg] $msg
-} {1 {bad argument "gorp": must be cancel, idle, info, or a number}}
+} {1 {bad argument "gorp": must be cancel, idle, info, or an integer}}
test timer-6.4 {Tcl_AfterCmd procedure, ms argument} {
set x before
after 400 {set x after}
@@ -453,20 +453,22 @@ test timer-8.1 {AfterProc procedure} {
}
list [foo] $x
} {untouched after}
-test timer-8.2 {AfterProc procedure} {
- catch {rename bgerror {}}
- proc bgerror msg {
- global x errorInfo
- set x [list $msg $errorInfo]
+test timer-8.2 {AfterProc procedure} -setup {
+ variable x empty
+ proc myHandler {msg options} {
+ variable x [list $msg [dict get $options -errorinfo]]
}
- set x empty
+ set handler [interp bgerror {}]
+ interp bgerror {} [namespace which myHandler]
+} -body {
after 100 {error "After error"}
after 200
set y $x
update
- catch {rename bgerror {}}
list $y $x
-} {empty {{After error} {After error
+} -cleanup {
+ interp bgerror {} $handler
+} -result {empty {{After error} {After error
while executing
"error "After error""
("after" script)}}}
@@ -535,6 +537,7 @@ test timer-9.1 {AfterCleanupProc procedure} {
update
set x
} {before after2 after4}
+
test timer-10.1 {Bug 1016167: [after] overwrites imports} -setup {
interp create slave
slave eval namespace export after
@@ -547,6 +550,19 @@ test timer-10.1 {Bug 1016167: [after] overwrites imports} -setup {
interp delete slave
} -result ::after
+test timer-11.1 {Bug 1350291: [after] overflowing 32-bit field} \
+ -body {
+ set b ok
+ set a [after 0x100000001 {set b "after fired early"}]
+ after 100 set done 1
+ vwait done
+ set b
+ } \
+ -cleanup {
+ catch {after cancel $a}
+ } \
+ -result ok
+
test timer-11.2 {Bug 1350293: [after] negative argument} \
-body {
set l {}
@@ -557,6 +573,11 @@ test timer-11.2 {Bug 1350293: [after] negative argument} \
} \
-result {-1 100}
+
# cleanup
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/tm.test b/tests/tm.test
new file mode 100644
index 0000000..f6c9a68
--- /dev/null
+++ b/tests/tm.test
@@ -0,0 +1,245 @@
+# This file contains tests for the ::tcl::tm::* commands.
+#
+# Sourcing this file into Tcl runs the tests and generates output for
+# errors. No output means no errors were found.
+#
+# Copyright (c) 2004 by Donal K. Fellows.
+# All rights reserved.
+
+package require Tcl 8.5
+if {"::tcltest" ni [namespace children]} {
+ package require tcltest 2
+ namespace import -force ::tcltest::*
+}
+
+test tm-1.1 {tm: path command exists} {
+ catch { ::tcl::tm::path }
+ info commands ::tcl::tm::path
+} ::tcl::tm::path
+test tm-1.2 {tm: path command syntax} -returnCodes error -body {
+ ::tcl::tm::path foo
+} -result {unknown or ambiguous subcommand "foo": must be add, list, or remove}
+test tm-1.3 {tm: path command syntax} -returnCodes error -body {
+ ::tcl::tm::path add
+} -result "wrong # args: should be \"::tcl::tm::path add path ...\""
+test tm-1.4 {tm: path command syntax} -returnCodes error -body {
+ ::tcl::tm::path remove
+} -result "wrong # args: should be \"::tcl::tm::path remove path ...\""
+test tm-1.5 {tm: path command syntax} -returnCodes error -body {
+ ::tcl::tm::path list foobar
+} -result "wrong # args: should be \"::tcl::tm::path list\""
+
+test tm-2.1 {tm: roots command exists} {
+ catch { ::tcl::tm::roots }
+ info commands ::tcl::tm::roots
+} ::tcl::tm::roots
+test tm-2.2 {tm: roots command syntax} -returnCodes error -body {
+ ::tcl::tm::roots
+} -result "wrong # args: should be \"::tcl::tm::roots paths\""
+test tm-2.3 {tm: roots command syntax} -returnCodes error -body {
+ ::tcl::tm::roots foo bar
+} -result "wrong # args: should be \"::tcl::tm::roots paths\""
+
+
+test tm-3.1 {tm: module path management, input validation} -setup {
+ # Save and clear the list
+ set defaults [::tcl::tm::path list]
+ foreach p $defaults {::tcl::tm::path remove $p}
+} -cleanup {
+ # Restore old contents of path list.
+ foreach p [::tcl::tm::path list] {::tcl::tm::path remove $p}
+ foreach p $defaults {::tcl::tm::path add $p}
+} -returnCodes error -body {
+ ::tcl::tm::path add foo/bar
+ ::tcl::tm::path add foo
+} -result {foo is ancestor of existing module path foo/bar.}
+
+test tm-3.2 {tm: module path management, input validation} -setup {
+ # Save and clear the list
+ set defaults [::tcl::tm::path list]
+ foreach p $defaults {::tcl::tm::path remove $p}
+} -cleanup {
+ # Restore old contents of path list.
+ foreach p [::tcl::tm::path list] {::tcl::tm::path remove $p}
+ foreach p $defaults {::tcl::tm::path add $p}
+} -returnCodes error -body {
+ ::tcl::tm::path add foo
+ ::tcl::tm::path add foo/bar
+} -result {foo/bar is subdirectory of existing module path foo.}
+
+test tm-3.3 {tm: module path management, add/list interaction} -setup {
+ # Save and clear the list
+ set defaults [::tcl::tm::path list]
+ foreach p $defaults {::tcl::tm::path remove $p}
+} -cleanup {
+ # Restore old contents of path list.
+ foreach p [::tcl::tm::path list] {::tcl::tm::path remove $p}
+ foreach p $defaults {::tcl::tm::path add $p}
+} -body {
+ ::tcl::tm::path add foo
+ ::tcl::tm::path add bar
+ ::tcl::tm::path list
+} -result {bar foo}
+
+test tm-3.4 {tm: module path management, add/list interaction} -setup {
+ # Save and clear the list
+ set defaults [::tcl::tm::path list]
+ foreach p $defaults {::tcl::tm::path remove $p}
+} -cleanup {
+ # Restore old contents of path list.
+ foreach p [::tcl::tm::path list] {::tcl::tm::path remove $p}
+ foreach p $defaults {::tcl::tm::path add $p}
+} -body {
+ ::tcl::tm::path add foo bar baz
+ ::tcl::tm::path list
+} -result {baz bar foo}
+
+test tm-3.5 {tm: module path management, input validation/list interaction} -setup {
+ # Save and clear the list
+ set defaults [::tcl::tm::path list]
+ foreach p $defaults {::tcl::tm::path remove $p}
+} -cleanup {
+ # Restore old contents of path list.
+ foreach p [::tcl::tm::path list] {::tcl::tm::path remove $p}
+ foreach p $defaults {::tcl::tm::path add $p}
+} -body {
+ catch {::tcl::tm::path add snarf foo geode foo/bar}
+ # Nothing is added if a problem was found.
+ ::tcl::tm::path list
+} -result {}
+
+test tm-3.6 {tm: module path management, input validation/list interaction} -setup {
+ # Save and clear the list
+ set defaults [::tcl::tm::path list]
+ foreach p $defaults {::tcl::tm::path remove $p}
+} -cleanup {
+ # Restore old contents of path list.
+ foreach p [::tcl::tm::path list] {::tcl::tm::path remove $p}
+ foreach p $defaults {::tcl::tm::path add $p}
+} -body {
+ catch {::tcl::tm::path add snarf foo/bar geode foo}
+ # Nothing is added if a problem was found.
+ ::tcl::tm::path list
+} -result {}
+
+test tm-3.7 {tm: module path management, input validation/list interaction} -setup {
+ # Save and clear the list
+ set defaults [::tcl::tm::path list]
+ foreach p $defaults {::tcl::tm::path remove $p}
+} -cleanup {
+ # Restore old contents of path list.
+ foreach p [::tcl::tm::path list] {::tcl::tm::path remove $p}
+ foreach p $defaults {::tcl::tm::path add $p}
+} -body {
+ catch {
+ ::tcl::tm::path add foo/bar
+ ::tcl::tm::path add snarf geode foo
+ }
+ # Nothing is added if a problem was found.
+ ::tcl::tm::path list
+} -result {foo/bar}
+
+test tm-3.8 {tm: module path management, input validation, ignore duplicates} -setup {
+ # Save and clear the list
+ set defaults [::tcl::tm::path list]
+ foreach p $defaults {::tcl::tm::path remove $p}
+} -cleanup {
+ # Restore old contents of path list.
+ foreach p [::tcl::tm::path list] {::tcl::tm::path remove $p}
+ foreach p $defaults {::tcl::tm::path add $p}
+} -body {
+ # Ignore path if present
+ ::tcl::tm::path add foo
+ ::tcl::tm::path add snarf geode foo
+ ::tcl::tm::path list
+} -result {geode snarf foo}
+
+test tm-3.9 {tm: module path management, input validation, ignore duplicates} -setup {
+ # Save and clear the list
+ set defaults [::tcl::tm::path list]
+ foreach p $defaults {::tcl::tm::path remove $p}
+} -cleanup {
+ # Restore old contents of path list.
+ foreach p [::tcl::tm::path list] {::tcl::tm::path remove $p}
+ foreach p $defaults {::tcl::tm::path add $p}
+} -body {
+ # Ignore path if present
+ ::tcl::tm::path add foo snarf geode foo
+ ::tcl::tm::path list
+} -result {geode snarf foo}
+
+test tm-3.10 {tm: module path management, remove} -setup {
+ # Save and clear the list
+ set defaults [::tcl::tm::path list]
+ foreach p $defaults {::tcl::tm::path remove $p}
+} -cleanup {
+ # Restore old contents of path list.
+ foreach p [::tcl::tm::path list] {::tcl::tm::path remove $p}
+ foreach p $defaults {::tcl::tm::path add $p}
+} -body {
+ ::tcl::tm::path add snarf geode foo
+ ::tcl::tm::path remove foo
+ ::tcl::tm::path list
+} -result {geode snarf}
+
+test tm-3.11 {tm: module path management, remove ignores unknown path} -setup {
+ # Save and clear the list
+ set defaults [::tcl::tm::path list]
+ foreach p $defaults {::tcl::tm::path remove $p}
+} -cleanup {
+ # Restore old contents of path list.
+ foreach p [::tcl::tm::path list] {::tcl::tm::path remove $p}
+ foreach p $defaults {::tcl::tm::path add $p}
+} -body {
+ ::tcl::tm::path add foo snarf geode
+ ::tcl::tm::path remove fox
+ ::tcl::tm::path list
+} -result {geode snarf foo}
+
+
+proc genpaths {base} {
+ # Normalizing picks up drive letters on windows [Bug 1053568]
+ set base [file normalize $base]
+ foreach {major minor} [split [info tclversion] .] break
+ set results {}
+ set base [file join $base tcl$major]
+ lappend results [file join $base site-tcl]
+ for {set i 0} {$i <= $minor} {incr i} {
+ lappend results [file join $base ${major}.$i]
+ }
+ return $results
+}
+
+test tm-3.12 {tm: module path management, roots} -setup {
+ # Save and clear the list
+ set defaults [::tcl::tm::path list]
+ foreach p $defaults {::tcl::tm::path remove $p}
+} -cleanup {
+ # Restore old contents of path list.
+ foreach p [::tcl::tm::path list] {::tcl::tm::path remove $p}
+ foreach p $defaults {::tcl::tm::path add $p}
+} -body {
+ ::tcl::tm::roots /FOO
+ ::tcl::tm::path list
+} -result [genpaths /FOO]
+
+test tm-3.13 {tm: module path management, roots} -setup {
+ # Save and clear the list
+ set defaults [::tcl::tm::path list]
+ foreach p $defaults {::tcl::tm::path remove $p}
+} -cleanup {
+ # Restore old contents of path list.
+ foreach p [::tcl::tm::path list] {::tcl::tm::path remove $p}
+ foreach p $defaults {::tcl::tm::path add $p}
+} -body {
+ ::tcl::tm::roots [list /FOO /BAR]
+ ::tcl::tm::path list
+} -result [concat [genpaths /BAR] [genpaths /FOO]]
+
+rename genpaths {}
+::tcltest::cleanupTests
+return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/trace.test b/tests/trace.test
index 1555d63..c2a760d 100644
--- a/tests/trace.test
+++ b/tests/trace.test
@@ -16,11 +16,12 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
+testConstraint testcmdtrace [llength [info commands testcmdtrace]]
+testConstraint testevalobjv [llength [info commands testevalobjv]]
+
# Used for constraining memory leak tests
testConstraint memory [llength [info commands memory]]
-testConstraint testevalobjv [llength [info commands testevalobjv]]
-
proc getbytes {} {
set lines [split [memory info] "\n"]
lindex [lindex $lines 3] 3
@@ -237,8 +238,8 @@ test trace-2.6 {trace variable writes on compiled local} {
catch {unset x}
set info {}
proc p {} {
- trace add variable x write traceArray
- set x(X) willy
+ trace add variable x write traceArray
+ set x(X) willy
}
p
set info
@@ -255,6 +256,8 @@ test trace-2.7 {trace variable writes on errorInfo} -body {
unset ::errorInfo
} -result {::errorInfo {} write}
+
+
# append no longer triggers read traces when fetching the old values of
# variables before doing the append operation. However, lappend _does_
# still trigger these read traces. Also lappend triggers only one write
@@ -768,6 +771,7 @@ test trace-13.1 {delete one trace from another} {
set x
set info
} {5 1}
+
test trace-13.2 {leak when unsetting traced variable} \
-constraints memory -body {
set end [getbytes]
@@ -860,7 +864,7 @@ test trace-14.3 "trace command, wrong # args errors" {
} [list 1 "wrong # args: should be \"trace remove type ?arg arg ...?\""]
test trace-14.4 "trace command, wrong # args errors" {
list [catch {trace info} msg] $msg
-} [list 1 "wrong # args: should be \"trace info type ?arg arg ...?\""]
+} [list 1 "wrong # args: should be \"trace info type name\""]
test trace-14.5 {trace command, invalid option} {
list [catch {trace gorp} msg] $msg
@@ -1444,7 +1448,7 @@ test trace-20.7 {trace add command delete in subinterp while being deleted} {
} {}
proc traceDelete {cmd old new op} {
- eval trace remove command $cmd [lindex [trace info command $cmd] 0]
+ trace remove command $cmd {*}[lindex [trace info command $cmd] 0]
global info
set info [list $old $new $op]
}
@@ -1528,6 +1532,7 @@ test trace-20.16 {delete trace discards error result [Bug 1355342]} {
rename foo {}
} {}
+
proc foo {b} { set a $b }
@@ -1623,15 +1628,15 @@ test trace-21.9 {trace execution: TCL_EVAL_GLOBAL} testevalobjv {
namespace eval test_ns_1 {
proc soom args {lappend ::info FAIL [info level]}
# [testevalobjv 1 ...] ought to produce the same
- # results as [uplevel #0 ...].
+ # results as [uplevel #0 ...].
testevalobjv 1 foo x
- uplevel #0 foo x
+ uplevel #0 foo x
}
namespace delete test_ns_1
trace remove execution foo enter soom
set ::info
} {SUCCESS 1 SUCCESS 1}
-
+
test trace-21.10 {trace execution: TCL_EVAL_GLOBAL} testevalobjv {
trace add execution foo leave soom
proc ::soom args {lappend ::info SUCCESS [info level]}
@@ -1639,9 +1644,9 @@ test trace-21.10 {trace execution: TCL_EVAL_GLOBAL} testevalobjv {
namespace eval test_ns_1 {
proc soom args {lappend ::info FAIL [info level]}
# [testevalobjv 1 ...] ought to produce the same
- # results as [uplevel #0 ...].
+ # results as [uplevel #0 ...].
testevalobjv 1 foo x
- uplevel #0 foo x
+ uplevel #0 foo x
}
namespace delete test_ns_1
trace remove execution foo leave soom
@@ -1771,7 +1776,7 @@ test trace-23.3 {recursive(3) trace execution: enter, leave, enterstep, leaveste
{factorial 3} 0 6 leave}
proc traceDelete {cmd args} {
- eval trace remove execution $cmd [lindex [trace info execution $cmd] 0]
+ trace remove execution $cmd {*}[lindex [trace info execution $cmd] 0]
global info
set info $args
}
@@ -2265,8 +2270,75 @@ test trace-28.10 {exec trace info nonsense} {
list [catch {trace remove execution} res] $res
} {1 {wrong # args: should be "trace remove execution name opList command"}}
-# Missing test number to keep in sync with the 8.5 branch
-# (want to backport those tests?)
+test trace-29.1 {Tcl_CreateTrace, correct command and argc/argv arguments of trace proc} {testcmdtrace} {
+ testcmdtrace tracetest {set stuff [expr 14 + 16]}
+} {{expr 14 + 16} {expr 14 + 16} {set stuff [expr 14 + 16]} {set stuff 30}}
+test trace-29.2 {Tcl_CreateTrace, correct command and argc/argv arguments of trace proc} {testcmdtrace} {
+ testcmdtrace tracetest {set stuff [info tclversion]}
+} [concat {{info tclversion} {info tclversion} ::tcl::info::tclversion {::tcl::info::tclversion} {set stuff [info tclversion]}} [list "set stuff [info tclversion]"]]
+test trace-29.3 {Tcl_CreateTrace, correct command and argc/argv arguments of trace proc} {testcmdtrace} {
+ testcmdtrace deletetest {set stuff [info tclversion]}
+} [info tclversion]
+test trace-29.4 {Tcl_CreateTrace, check that tracing doesn't cause memory faults} {testcmdtrace} {
+ # Note that the proc call is the same as the variable name, and that
+ # the call can be direct or indirect by way of another procedure
+ proc tracer {args} {}
+ proc tracedLoop {level} {
+ incr level
+ tracer
+ foreach tracer [expr {$level==1 ? {1 2} : {}}] {tracedLoop $level}
+ }
+ testcmdtrace tracetest {tracedLoop 0}
+} {{tracedLoop 0} {tracedLoop 0} {incr level} {incr level} tracer {tracer} {expr {$level==1 ? {1 2} : {}}} {expr {$level==1 ? {1 2} : {}}} {foreach tracer [expr {$level==1 ? {1 2} : {}}] {tracedLoop $level}} {foreach tracer {1 2} {tracedLoop $level}} {tracedLoop $level} {tracedLoop 1} {incr level} {incr level} tracer {tracer} {expr {$level==1 ? {1 2} : {}}} {expr {$level==1 ? {1 2} : {}}} {foreach tracer [expr {$level==1 ? {1 2} : {}}] {tracedLoop $level}} {foreach tracer {} {tracedLoop $level}} {tracedLoop $level} {tracedLoop 1} {incr level} {incr level} tracer {tracer} {expr {$level==1 ? {1 2} : {}}} {expr {$level==1 ? {1 2} : {}}} {foreach tracer [expr {$level==1 ? {1 2} : {}}] {tracedLoop $level}} {foreach tracer {} {tracedLoop $level}}}
+catch {rename tracer {}}
+catch {rename tracedLoop {}}
+
+test trace-29.5 {Tcl_CreateObjTrace, status return TCL_ERROR} {testcmdtrace} {
+ proc Error { args } { error "Shouldn't get here" }
+ set x 1;
+ list [catch {testcmdtrace resulttest {Error $x}} result] [set result]
+} {1 {Error $x}}
+
+test trace-29.6 {Tcl_CreateObjTrace, status return TCL_RETURN} {testcmdtrace} {
+ proc Return { args } { error "Shouldn't get here" }
+ set x 1;
+ list [catch {testcmdtrace resulttest {Return $x}} result] [set result]
+} {2 {}}
+
+test trace-29.7 {Tcl_CreateObjTrace, status return TCL_BREAK} {testcmdtrace} {
+ proc Break { args } { error "Shouldn't get here" }
+ set x 1;
+ list [catch {testcmdtrace resulttest {Break $x}} result] [set result]
+} {3 {}}
+
+test trace-29.8 {Tcl_CreateObjTrace, status return TCL_CONTINUE} {testcmdtrace} {
+ proc Continue { args } { error "Shouldn't get here" }
+ set x 1;
+ list [catch {testcmdtrace resulttest {Continue $x}} result] [set result]
+} {4 {}}
+
+test trace-29.9 {Tcl_CreateObjTrace, status return unknown} {testcmdtrace} {
+ proc OtherStatus { args } { error "Shouldn't get here" }
+ set x 1;
+ list [catch {testcmdtrace resulttest {OtherStatus $x}} result] [set result]
+} {6 {}}
+
+test trace-29.10 {Tcl_CreateTrace, correct level interpretation} {testcmdtrace} {
+ proc foo {} {uplevel 1 bar}
+ proc bar {} {uplevel 1 grok}
+ proc grok {} {uplevel 1 spock}
+ proc spock {} {uplevel 1 fascinating}
+ proc fascinating {} {}
+ testcmdtrace leveltest {foo}
+} {foo {foo} {uplevel 1 bar} {uplevel 1 bar} bar {bar} {uplevel 1 grok} {uplevel 1 grok}}
+
+test trace-29.11 {Tcl_CreateTrace, multiple traces} {testcmdtrace} {
+ testcmdtrace doubletest {format xx}
+} {{format xx} {format xx}}
+
+test trace-30.1 {Tcl_DeleteTrace} {emptyTest} {
+ # the above tests have tested Tcl_DeleteTrace
+} {}
test trace-31.1 {command and execution traces shared struct} {
# Tcl Bug 807243
@@ -2314,12 +2386,12 @@ test trace-34.1 {Bug 1201035} {
set ::x [list]
proc foo {} {lappend ::x foo}
proc bar args {
- lappend ::x $args
- trace remove execution foo leavestep bar
- trace remove execution foo enterstep bar
- trace add execution foo leavestep bar
- trace add execution foo enterstep bar
- lappend ::x done
+ lappend ::x $args
+ trace remove execution foo leavestep bar
+ trace remove execution foo enterstep bar
+ trace add execution foo leavestep bar
+ trace add execution foo enterstep bar
+ lappend ::x done
}
trace add execution foo leavestep bar
trace add execution foo enterstep bar
@@ -2370,19 +2442,19 @@ test trace-34.5 {Bug 1047286} {
test trace-34.6 {Bug 1458266} -setup {
proc dummy {} {}
proc stepTraceHandler {cmdString args} {
- variable log
- append log "[expr {[info level] - 1}]: [lindex [split $cmdString] 0]\n"
- dummy
- isTracedInside_2
+ variable log
+ append log "[expr {[info level] - 1}]: [lindex [split $cmdString] 0]\n"
+ dummy
+ isTracedInside_2
}
proc cmdTraceHandler {cmdString args} {
- # silent
+ # silent
}
proc isTracedInside_1 {} {
- isTracedInside_2
+ isTracedInside_2
}
proc isTracedInside_2 {} {
- set x 2
+ set x 2
}
} -body {
variable log {}
@@ -2404,14 +2476,102 @@ test trace-34.6 {Bug 1458266} -setup {
rename isTracedInside_2 {}
} -result ok
+test trace-35.1 {527164: Keep -errorinfo of traces} -setup {
+ unset -nocomplain x y
+} -body {
+ trace add variable x write {error foo;#}
+ trace add variable y write {set x 2;#}
+ list [catch {set y 1} msg opts] $msg [dict get $opts -errorinfo]
+} -cleanup {
+ unset -nocomplain x y
+} -result {1 {can't set "y": can't set "x": foo} {foo
+ while executing
+"error foo"
+ (write trace on "x")
+ invoked from within
+"set x 2"
+ (write trace on "y")
+ invoked from within
+"set y 1"}}
+
+
+#
+# Test for the correct(?) dynamics of execution traces. This test insures that
+# the dynamics of the original implementation remain valid; note that
+# these aspects are neither documented nor do they appear in TIP 62
+
+proc traceproc {tracevar args} {
+ append ::$tracevar *
+}
+proc untraced {type} {
+ trace add execution untraced $type {traceproc tracevar}
+ append ::tracevar -
+}
+proc runbase {results base} {
+ set tt {enter leave enterstep leavestep}
+ foreach n {1 2 3 4} t $tt r $results {
+ eval [subst $base]
+ }
+}
+set base {
+ test trace-36.$n {dynamic trace creation: $t} -setup {
+ set ::tracevar {}
+ } -cleanup {
+ unset ::tracevar
+ trace remove execution untraced $t {traceproc tracevar}
+ } -body {
+ untraced $t
+ set ::tracevar
+ } -result {$r}
+}
+runbase {- - - -} $base
+
+set base {
+ test trace-37.$n {dynamic trace addition: $t} -setup {
+ set ::tracevar {}
+ set ::tracevar2 {}
+ trace add execution untraced enter {traceproc tracevar2}
+ } -cleanup {
+ trace remove execution untraced $t {traceproc tracevar}
+ trace remove execution untraced enter {traceproc tracevar2}
+ unset ::tracevar ::tracevar2
+ } -body {
+ untraced $t
+ list \$::tracevar \$::tracevar2
+ } -result {$r}
+}
+runbase {{- *} {-* *} {- *} {- *}} $base
+
+set base {
+ test trace-38.$n {dynamic trace addition: $t} -setup {
+ set ::tracevar {}
+ set ::tracevar2 {}
+ trace add execution untraced leave {traceproc tracevar2}
+ } -cleanup {
+ trace remove execution untraced $t {traceproc tracevar}
+ trace remove execution untraced leave {traceproc tracevar2}
+ unset ::tracevar ::tracevar2
+ } -body {
+ untraced $t
+ list \$::tracevar \$::tracevar2
+ } -result {$r}
+}
+runbase {{- *} {-* *} {- *} {- *}} $base
+
+
+
# Delete procedures when done, so we don't clash with other tests
# (e.g. foobar will clash with 'unknown' tests).
catch {rename foobar {}}
catch {rename foo {}}
catch {rename bar {}}
+catch {rename untraced {}}
+catch {rename traceproc {}}
+catch {rename runbase {}}
-# Unset the varaible when done
+# Unset the variable when done
catch {unset info}
+catch {unset base}
# cleanup
::tcltest::cleanupTests
diff --git a/tests/unixFCmd.test b/tests/unixFCmd.test
index fcb5e69..f60e04c 100644
--- a/tests/unixFCmd.test
+++ b/tests/unixFCmd.test
@@ -14,6 +14,8 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
+testConstraint testchmod [llength [info commands testchmod]]
+
# These tests really need to be run from a writable directory, which
# it is assumed [temporaryDirectory] is.
set oldcwd [pwd]
@@ -21,7 +23,7 @@ cd [temporaryDirectory]
# Several tests require need to match results against the unix username
set user {}
-if {$tcl_platform(platform) == "unix"} {
+if {[testConstraint unix]} {
catch {set user [exec whoami]}
if {$user == ""} {
catch {regexp {^[^(]*\(([^)]*)\)} [exec id] dummy user}
@@ -31,6 +33,28 @@ if {$tcl_platform(platform) == "unix"} {
}
}
+# Find a group that exists on this system, or else skip tests that require
+# groups
+testConstraint foundGroup 0
+if {[testConstraint unix]} {
+ catch {
+ set groupList [exec groups]
+ set group [lindex $groupList 0]
+ testConstraint foundGroup 1
+ }
+}
+
+# check whether -readonly attribute is supported
+testConstraint readonlyAttr 0
+if {[testConstraint unix]} {
+ set f [makeFile "whatever" probe]
+ catch {
+ file attributes $f -readonly
+ testConstraint readonlyAttr 1
+ }
+ removeFile probe
+}
+
proc openup {path} {
testchmod 777 $path
if {[file isdirectory $path]} {
@@ -49,7 +73,10 @@ proc cleanup {args} {
set x [glob -directory $p tf* td*]
}
foreach file $x {
- if {[catch {file delete -force -- $file}]} {
+ if {
+ [catch {file delete -force -- $file}]
+ && [testConstraint testchmod]
+ } then {
openup $file
file delete -force -- $file
}
@@ -57,7 +84,7 @@ proc cleanup {args} {
}
}
-test unixFCmd-1.1 {TclpRenameFile: EACCES} {unixOnly notRoot} {
+test unixFCmd-1.1 {TclpRenameFile: EACCES} {unix notRoot} {
cleanup
file mkdir td1/td2/td3
file attributes td1/td2 -permissions 0000
@@ -65,29 +92,29 @@ test unixFCmd-1.1 {TclpRenameFile: EACCES} {unixOnly notRoot} {
file attributes td1/td2 -permissions 0755
set msg
} {1 {error renaming "td1/td2/td3": permission denied}}
-test unixFCmd-1.2 {TclpRenameFile: EEXIST} {unixOnly notRoot} {
+test unixFCmd-1.2 {TclpRenameFile: EEXIST} {unix notRoot} {
cleanup
file mkdir td1/td2
file mkdir td2
list [catch {file rename td2 td1} msg] $msg
} {1 {error renaming "td2" to "td1/td2": file already exists}}
-test unixFCmd-1.3 {TclpRenameFile: EINVAL} {unixOnly notRoot} {
+test unixFCmd-1.3 {TclpRenameFile: EINVAL} {unix notRoot} {
cleanup
file mkdir td1
list [catch {file rename td1 td1} msg] $msg
} {1 {error renaming "td1" to "td1/td1": trying to rename a volume or move a directory into itself}}
-test unixFCmd-1.4 {TclpRenameFile: EISDIR} {emptyTest unixOnly notRoot} {
+test unixFCmd-1.4 {TclpRenameFile: EISDIR} {emptyTest unix notRoot} {
# can't make it happen
} {}
-test unixFCmd-1.5 {TclpRenameFile: ENOENT} {unixOnly notRoot} {
+test unixFCmd-1.5 {TclpRenameFile: ENOENT} {unix notRoot} {
cleanup
file mkdir td1
list [catch {file rename td2 td1} msg] $msg
} {1 {error renaming "td2": no such file or directory}}
-test unixFCmd-1.6 {TclpRenameFile: ENOTDIR} {emptyTest unixOnly notRoot} {
+test unixFCmd-1.6 {TclpRenameFile: ENOTDIR} {emptyTest unix notRoot} {
# can't make it happen
} {}
-test unixFCmd-1.7 {TclpRenameFile: EXDEV} {unixOnly notRoot} {
+test unixFCmd-1.7 {TclpRenameFile: EXDEV} {unix notRoot} {
cleanup
file mkdir foo/bar
file attr foo -perm 040555
@@ -98,12 +125,12 @@ test unixFCmd-1.7 {TclpRenameFile: EXDEV} {unixOnly notRoot} {
catch {file delete -force foo}
list $catchResult $msg
} {1 { permission denied}}
-test unixFCmd-1.8 {Checking EINTR Bug} {unixOnly notRoot nonPortable} {
+test unixFCmd-1.8 {Checking EINTR Bug} {unix notRoot nonPortable} {
testalarm
after 2000
list [testgotsig] [testgotsig]
} {1 0}
-test unixFCmd-1.9 {Checking EINTR Bug} {unixOnly notRoot nonPortable} {
+test unixFCmd-1.9 {Checking EINTR Bug} {unix notRoot nonPortable} {
cleanup
set f [open tfalarm w]
puts $f {
@@ -118,14 +145,15 @@ test unixFCmd-1.9 {Checking EINTR Bug} {unixOnly notRoot nonPortable} {
catch {close $pipe}
list $line [testgotsig]
} {h 1}
+
test unixFCmd-2.1 {TclpCopyFile: target exists: lstat(dst) == 0} \
- {unixOnly notRoot} {
+ {unix notRoot} {
cleanup
close [open tf1 a]
close [open tf2 a]
file copy -force tf1 tf2
} {}
-test unixFCmd-2.2.1 {TclpCopyFile: src is symlink} {unixOnly notRoot dontCopyLinks} {
+test unixFCmd-2.2.1 {TclpCopyFile: src is symlink} {unix notRoot dontCopyLinks} {
# copying links should end up with real files
cleanup
close [open tf1 a]
@@ -133,7 +161,7 @@ test unixFCmd-2.2.1 {TclpCopyFile: src is symlink} {unixOnly notRoot dontCopyLin
file copy tf2 tf3
file type tf3
} {file}
-test unixFCmd-2.2.2 {TclpCopyFile: src is symlink} {unixOnly notRoot} {
+test unixFCmd-2.2.2 {TclpCopyFile: src is symlink} {unix notRoot} {
# copying links should end up with the links copied
cleanup
close [open tf1 a]
@@ -141,7 +169,7 @@ test unixFCmd-2.2.2 {TclpCopyFile: src is symlink} {unixOnly notRoot} {
file copy tf2 tf3
file type tf3
} {link}
-test unixFCmd-2.3 {TclpCopyFile: src is block} {unixOnly notRoot} {
+test unixFCmd-2.3 {TclpCopyFile: src is block} {unix notRoot} {
cleanup
set null "/dev/null"
while {[file type $null] != "characterSpecial"} {
@@ -149,7 +177,7 @@ test unixFCmd-2.3 {TclpCopyFile: src is block} {unixOnly notRoot} {
}
# file copy $null tf1
} {}
-test unixFCmd-2.4 {TclpCopyFile: src is fifo} {unixOnly notRoot} {
+test unixFCmd-2.4 {TclpCopyFile: src is fifo} {unix notRoot} {
cleanup
if [catch {exec mknod tf1 p}] {
list 1
@@ -158,7 +186,7 @@ test unixFCmd-2.4 {TclpCopyFile: src is fifo} {unixOnly notRoot} {
expr {"[file type tf1]" == "[file type tf2]"}
}
} {1}
-test unixFCmd-2.5 {TclpCopyFile: copy attributes} {unixOnly notRoot} {
+test unixFCmd-2.5 {TclpCopyFile: copy attributes} {unix notRoot} {
cleanup
close [open tf1 a]
file attributes tf1 -permissions 0472
@@ -166,124 +194,113 @@ test unixFCmd-2.5 {TclpCopyFile: copy attributes} {unixOnly notRoot} {
file attributes tf2 -permissions
} 00472 ;# i.e. perms field of [exec ls -l tf2] is -r--rwx-w-
-test unixFCmd-3.1 {CopyFile not done} {emptyTest unixOnly notRoot} {
+test unixFCmd-3.1 {CopyFile not done} {emptyTest unix notRoot} {
} {}
-test unixFCmd-4.1 {TclpDeleteFile not done} {emptyTest unixOnly notRoot} {
+test unixFCmd-4.1 {TclpDeleteFile not done} {emptyTest unix notRoot} {
} {}
-test unixFCmd-5.1 {TclpCreateDirectory not done} {emptyTest unixOnly notRoot} {
+test unixFCmd-5.1 {TclpCreateDirectory not done} {emptyTest unix notRoot} {
} {}
-test unixFCmd-6.1 {TclpCopyDirectory not done} {emptyTest unixOnly notRoot} {
+test unixFCmd-6.1 {TclpCopyDirectory not done} {emptyTest unix notRoot} {
} {}
-test unixFCmd-7.1 {TclpRemoveDirectory not done} {emptyTest unixOnly notRoot} {
+test unixFCmd-7.1 {TclpRemoveDirectory not done} {emptyTest unix notRoot} {
} {}
-test unixFCmd-8.1 {TraverseUnixTree not done} {emptyTest unixOnly notRoot} {
+test unixFCmd-8.1 {TraverseUnixTree not done} {emptyTest unix notRoot} {
} {}
-test unixFCmd-9.1 {TraversalCopy not done} {emptyTest unixOnly notRoot} {
+test unixFCmd-9.1 {TraversalCopy not done} {emptyTest unix notRoot} {
} {}
-test unixFCmd-10.1 {TraversalDelete not done} {emptyTest unixOnly notRoot} {
+test unixFCmd-10.1 {TraversalDelete not done} {emptyTest unix notRoot} {
} {}
-test unixFCmd-11.1 {CopyFileAttrs not done} {emptyTest unixOnly notRoot} {
+test unixFCmd-11.1 {CopyFileAttrs not done} {emptyTest unix notRoot} {
} {}
-test unixFCmd-12.1 {GetGroupAttribute - file not found} {unixOnly notRoot} {
+test unixFCmd-12.1 {GetGroupAttribute - file not found} {unix notRoot} {
catch {file delete -force -- foo.test}
list [catch {file attributes foo.test -group} msg] $msg
} {1 {could not read "foo.test": no such file or directory}}
-test unixFCmd-12.2 {GetGroupAttribute - file found} {unixOnly notRoot} {
+test unixFCmd-12.2 {GetGroupAttribute - file found} {unix notRoot} {
catch {file delete -force -- foo.test}
close [open foo.test w]
list [catch {file attributes foo.test -group}] [file delete -force -- foo.test]
} {0 {}}
-test unixFCmd-13.1 {GetOwnerAttribute - file not found} {unixOnly notRoot} {
+test unixFCmd-13.1 {GetOwnerAttribute - file not found} {unix notRoot} {
catch {file delete -force -- foo.test}
list [catch {file attributes foo.test -group} msg] $msg
} {1 {could not read "foo.test": no such file or directory}}
-test unixFCmd-13.2 {GetOwnerAttribute} {unixOnly notRoot} {
+test unixFCmd-13.2 {GetOwnerAttribute} {unix notRoot} {
catch {file delete -force -- foo.test}
close [open foo.test w]
list [catch {file attributes foo.test -owner} msg] \
[string compare $msg $user] [file delete -force -- foo.test]
} {0 0 {}}
-test unixFCmd-14.1 {GetPermissionsAttribute - file not found} {unixOnly notRoot} {
+test unixFCmd-14.1 {GetPermissionsAttribute - file not found} {unix notRoot} {
catch {file delete -force -- foo.test}
list [catch {file attributes foo.test -permissions} msg] $msg
} {1 {could not read "foo.test": no such file or directory}}
-test unixFCmd-14.2 {GetPermissionsAttribute} {unixOnly notRoot} {
+test unixFCmd-14.2 {GetPermissionsAttribute} {unix notRoot} {
catch {file delete -force -- foo.test}
close [open foo.test w]
list [catch {file attribute foo.test -permissions}] \
[file delete -force -- foo.test]
} {0 {}}
-# Find a group that exists on this system, or else skip tests that require
-# groups
-set ::tcltest::testConstraints(foundGroup) 0
-if {$tcl_platform(platform) == "unix"} {
- catch {
- set groupList [exec groups]
- set group [lindex $groupList 0]
- set ::tcltest::testConstraints(foundGroup) 1
- }
-}
-
#groups hard to test
-test unixFCmd-15.1 {SetGroupAttribute - invalid group} {unixOnly notRoot} {
+test unixFCmd-15.1 {SetGroupAttribute - invalid group} {unix notRoot} {
catch {file delete -force -- foo.test}
list [catch {file attributes foo.test -group foozzz} msg] \
$msg [file delete -force -- foo.test]
} {1 {could not set group for file "foo.test": group "foozzz" does not exist} {}}
test unixFCmd-15.2 {SetGroupAttribute - invalid file} \
- {unixOnly notRoot foundGroup} {
+ {unix notRoot foundGroup} {
catch {file delete -force -- foo.test}
list [catch {file attributes foo.test -group $group} msg] $msg
} {1 {could not set group for file "foo.test": no such file or directory}}
#changing owners hard to do
-test unixFCmd-16.1 {SetOwnerAttribute - current owner} {unixOnly notRoot} {
+test unixFCmd-16.1 {SetOwnerAttribute - current owner} {unix notRoot} {
catch {file delete -force -- foo.test}
close [open foo.test w]
list [catch {file attributes foo.test -owner $user} msg] \
$msg [string compare [file attributes foo.test -owner] $user] \
[file delete -force -- foo.test]
} {0 {} 0 {}}
-test unixFCmd-16.2 {SetOwnerAttribute - invalid file} {unixOnly notRoot} {
+test unixFCmd-16.2 {SetOwnerAttribute - invalid file} {unix notRoot} {
catch {file delete -force -- foo.test}
list [catch {file attributes foo.test -owner $user} msg] $msg
} {1 {could not set owner for file "foo.test": no such file or directory}}
-test unixFCmd-16.3 {SetOwnerAttribute - invalid owner} {unixOnly notRoot} {
+test unixFCmd-16.3 {SetOwnerAttribute - invalid owner} {unix notRoot} {
catch {file delete -force -- foo.test}
list [catch {file attributes foo.test -owner foozzz} msg] $msg
} {1 {could not set owner for file "foo.test": user "foozzz" does not exist}}
-test unixFCmd-17.1 {SetPermissionsAttribute} {unixOnly notRoot} {
+test unixFCmd-17.1 {SetPermissionsAttribute} {unix notRoot} {
catch {file delete -force -- foo.test}
close [open foo.test w]
list [catch {file attributes foo.test -permissions 0000} msg] \
$msg [file attributes foo.test -permissions] \
[file delete -force -- foo.test]
} {0 {} 00000 {}}
-test unixFCmd-17.2 {SetPermissionsAttribute} {unixOnly notRoot} {
+test unixFCmd-17.2 {SetPermissionsAttribute} {unix notRoot} {
catch {file delete -force -- foo.test}
list [catch {file attributes foo.test -permissions 0000} msg] $msg
} {1 {could not set permissions for file "foo.test": no such file or directory}}
-test unixFCmd-17.3 {SetPermissionsAttribute} {unixOnly notRoot} {
+test unixFCmd-17.3 {SetPermissionsAttribute} {unix notRoot} {
catch {file delete -force -- foo.test}
close [open foo.test w]
list [catch {file attributes foo.test -permissions foo} msg] $msg \
[file delete -force -- foo.test]
} {1 {unknown permission string format "foo"} {}}
-test unixFCmd-17.4 {SetPermissionsAttribute} {unixOnly notRoot} {
+test unixFCmd-17.4 {SetPermissionsAttribute} {unix notRoot} {
catch {file delete -force -- foo.test}
close [open foo.test w]
list [catch {file attributes foo.test -permissions ---rwx} msg] $msg \
@@ -293,7 +310,7 @@ test unixFCmd-17.4 {SetPermissionsAttribute} {unixOnly notRoot} {
close [open foo.test w]
set ::i 4
proc permcheck {testnum permstr expected} {
- test $testnum {SetPermissionsAttribute} {unixOnly notRoot} {
+ test $testnum {SetPermissionsAttribute} {unix notRoot} {
file attributes foo.test -permissions $permstr
file attributes foo.test -permissions
} $expected
@@ -308,7 +325,7 @@ permcheck unixFCmd-17.11 --x--x--x 00111
permcheck unixFCmd-17.12 a+rwx 00777
file delete -force -- foo.test
-test unixFCmd-18.1 {Unix pwd} {nonPortable unixOnly notRoot} {
+test unixFCmd-18.1 {Unix pwd} {nonPortable unix notRoot} {
# This test is nonportable because SunOS generates a weird error
# message when the current directory isn't readable.
set cd [pwd]
@@ -323,8 +340,38 @@ test unixFCmd-18.1 {Unix pwd} {nonPortable unixOnly notRoot} {
set r
} {1 {error getting working directory name:}}
+test unixFCmd-19.1 {GetReadOnlyAttribute - file not found} {unix notRoot readonlyAttr} {
+ catch {file delete -force -- foo.test}
+ list [catch {file attributes foo.test -readonly} msg] $msg
+} {1 {could not read "foo.test": no such file or directory}}
+test unixFCmd-19.2 {GetReadOnlyAttribute} {unix notRoot readonlyAttr} {
+ catch {file delete -force -- foo.test}
+ close [open foo.test w]
+ list [catch {file attribute foo.test -readonly} msg] $msg \
+ [file delete -force -- foo.test]
+} {0 0 {}}
+
+test unixFCmd-20.1 {SetReadOnlyAttribute} {unix notRoot readonlyAttr} {
+ catch {file delete -force -- foo.test}
+ close [open foo.test w]
+ list [catch {file attributes foo.test -readonly 1} msg] $msg \
+ [catch {file attribute foo.test -readonly} msg] $msg \
+ [catch {file delete -force -- foo.test}] \
+ [catch {file attributes foo.test -readonly 0} msg] $msg \
+ [catch {file attribute foo.test -readonly} msg] $msg \
+ [file delete -force -- foo.test]
+} {0 {} 0 1 1 0 {} 0 0 {}}
+test unixFCmd-20.2 {SetReadOnlyAttribute} {unix notRoot readonlyAttr} {
+ catch {file delete -force -- foo.test}
+ list [catch {file attributes foo.test -readonly 1} msg] $msg
+} {1 {could not read "foo.test": no such file or directory}}
+
# cleanup
cleanup
cd $oldcwd
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/unixFile.test b/tests/unixFile.test
index 14fc533..0ea0ec1 100644
--- a/tests/unixFile.test
+++ b/tests/unixFile.test
@@ -14,12 +14,7 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-if {[info commands testobj] == {}} {
- puts "This application hasn't been compiled with the \"testfindexecutable\""
- puts "command, so I can't test the Tcl_FindExecutable function"
- ::tcltest::cleanupTests
- return
-}
+testConstraint testfindexecutable [llength [info commands testfindexecutable]]
set oldpwd [pwd]
cd [temporaryDirectory]
@@ -30,31 +25,31 @@ catch {
}
set absPath [file join [temporaryDirectory] junk]
-test unixFile-1.1 {Tcl_FindExecutable} {unixOnly} {
+test unixFile-1.1 {Tcl_FindExecutable} {testfindexecutable unix} {
set env(PATH) ""
testfindexecutable junk
} $absPath
-test unixFile-1.2 {Tcl_FindExecutable} {unixOnly} {
+test unixFile-1.2 {Tcl_FindExecutable} {testfindexecutable unix} {
set env(PATH) "/dummy"
testfindexecutable junk
} {}
-test unixFile-1.3 {Tcl_FindExecutable} {unixOnly} {
+test unixFile-1.3 {Tcl_FindExecutable} {testfindexecutable unix} {
set env(PATH) "/dummy:[pwd]"
testfindexecutable junk
} $absPath
-test unixFile-1.4 {Tcl_FindExecutable} {unixOnly} {
+test unixFile-1.4 {Tcl_FindExecutable} {testfindexecutable unix} {
set env(PATH) "/dummy:"
testfindexecutable junk
} $absPath
-test unixFile-1.5 {Tcl_FindExecutable} {unixOnly} {
+test unixFile-1.5 {Tcl_FindExecutable} {testfindexecutable unix} {
set env(PATH) "/dummy:/dummy"
testfindexecutable junk
} {}
-test unixFile-1.6 {Tcl_FindExecutable} {unixOnly} {
+test unixFile-1.6 {Tcl_FindExecutable} {testfindexecutable unix} {
set env(PATH) "/dummy::/dummy"
testfindexecutable junk
} $absPath
-test unixFile-1.7 {Tcl_FindExecutable} {unixOnly} {
+test unixFile-1.7 {Tcl_FindExecutable} {testfindexecutable unix} {
set env(PATH) ":/dummy"
testfindexecutable junk
} $absPath
diff --git a/tests/unixInit.test b/tests/unixInit.test
index a4a9249..003dd00 100644
--- a/tests/unixInit.test
+++ b/tests/unixInit.test
@@ -10,43 +10,34 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-package require tcltest 2
+package require tcltest 2.2
namespace import -force ::tcltest::*
unset -nocomplain path
-if {[info exists env(TCL_LIBRARY)]} {
- set oldlibrary $env(TCL_LIBRARY)
- unset env(TCL_LIBRARY)
-}
catch {set oldlang $env(LANG)}
set env(LANG) C
-test unixInit-1.1 {TclpInitPlatform: ignore SIGPIPE} {unixOnly stdio} {
+test unixInit-1.1 {TclpInitPlatform: ignore SIGPIPE} {unix stdio} {
set x {}
-
# Watch out for a race condition here. If tcltest is too slow to start
# then we'll kill it before it has a chance to set up its signal handler.
-
set f [open "|[list [interpreter]]" w+]
puts $f "puts hi"
flush $f
gets $f
exec kill -PIPE [pid $f]
lappend x [catch {close $f}]
-
set f [open "|[list [interpreter]]" w+]
puts $f "puts hi"
flush $f
gets $f
exec kill [pid $f]
lappend x [catch {close $f}]
-
set x
} {0 1}
-
# This test is really a test of code in tclUnixChan.c, but the
# channels are set up as part of initialisation of the interpreter so
# the test seems to me to fit here as well as anywhere else.
-test unixInit-1.2 {initialisation: standard channel type deduction} {unixOnly stdio} {
+test unixInit-1.2 {initialisation: standard channel type deduction} {unix stdio} {
# pipe1 is a connection to a server that reports what port it
# starts on, and delivers a constant string to the first client to
# connect to that port before exiting.
@@ -57,7 +48,7 @@ test unixInit-1.2 {initialisation: standard channel type deduction} {unixOnly st
close $channel
exit
}
- puts [fconfigure [socket -server accept 0] -sockname]
+ puts [fconfigure [socket -server accept -myaddr 127.0.0.1 0] -sockname]
vwait forever \
}
# Note the backslash above; this is important to make sure that the
@@ -72,16 +63,13 @@ test unixInit-1.2 {initialisation: standard channel type deduction} {unixOnly st
# as a socket. Which is what this test is all about.
set pipe2 [open "|[list [interpreter] <@$sock]" r]
set result [gets $pipe2]
-
# Clear any pending data; stops certain kinds of (non-important) errors
fconfigure $pipe1 -blocking 0; gets $pipe1
fconfigure $pipe2 -blocking 0; gets $pipe2
-
# Close the pipes and the socket.
close $pipe2
close $pipe1
catch {close $sock}
-
# Can't use normal comparison, as hostname varies due to some
# installations having a messed up /etc/hosts file.
if {
@@ -94,76 +82,100 @@ test unixInit-1.2 {initialisation: standard channel type deduction} {unixOnly st
}
} {OK}
-proc getlibpath [list [list program [interpreter]]] {
- set f [open "|[list $program]" w+]
- fconfigure $f -buffering none
- puts $f {puts $tcl_libPath; exit}
- set path [gets $f]
- close $f
- return $path
-}
+# The unixInit-2.* tests were written to test the internal routine,
+# TclpInitLibraryPath. That routine no longer does the things it used
+# to do so those tests are obsolete. Skip them.
-# Some tests require the testgetdefenc command
+skip [concat [skip] unixInit-2.*]
-testConstraint testgetdefenc [llength [info commands testgetdefenc]]
-
-test unixInit-2.0 {TclpInitLibraryPath: setting tclDefaultEncodingDir} \
- {unixOnly testgetdefenc} {
+test unixInit-2.0 {TclpInitLibraryPath: setting tclDefaultEncodingDir} {
set origDir [testgetdefenc]
testsetdefenc slappy
set path [testgetdefenc]
testsetdefenc $origDir
set path
} {slappy}
-test unixInit-2.1 {TclpInitLibraryPath: value of installLib, developLib} \
- {unixOnly stdio} {
+test unixInit-2.1 {TclpInitLibraryPath: value of installLib, developLib} -setup {
+ unset -nocomplain oldlibrary
+ if {[info exists env(TCL_LIBRARY)]} {
+ set oldlibrary $env(TCL_LIBRARY)
+ unset env(TCL_LIBRARY)
+ }
+} -body {
set path [getlibpath]
-
set installLib lib/tcl[info tclversion]
set developLib tcl[info patchlevel]/library
set prefix [file dirname [file dirname [interpreter]]]
-
set x {}
lappend x [string compare [lindex $path 0] $prefix/$installLib]
lappend x [string compare [lindex $path 4] [file dirname $prefix]/$developLib]
set x
-} {0 0}
-test unixInit-2.2 {TclpInitLibraryPath: TCL_LIBRARY} {unixOnly stdio} {
- # ((str != NULL) && (str[0] != '\0'))
-
+} -cleanup {
+ if {[info exists oldlibrary]} {
+ set env(TCL_LIBRARY) $oldlibrary
+ unset oldlibrary
+ }
+} -result {0 0}
+test unixInit-2.2 {TclpInitLibraryPath: TCL_LIBRARY} -setup {
+ unset -nocomplain oldlibrary
+ if {[info exists env(TCL_LIBRARY)]} {
+ set oldlibrary $env(TCL_LIBRARY)
+ }
+} -body {
+ # ((str != NULL) && (str[0] != '\0'))
set env(TCL_LIBRARY) sparkly
set path [getlibpath]
unset env(TCL_LIBRARY)
-
lindex $path 0
-} "sparkly"
-test unixInit-2.3 {TclpInitLibraryPath: TCL_LIBRARY wrong version} \
- {unixOnly stdio} {
+} -cleanup {
+ if {[info exists oldlibrary]} {
+ set env(TCL_LIBRARY) $oldlibrary
+ unset oldlibrary
+ }
+} -result "sparkly"
+test unixInit-2.3 {TclpInitLibraryPath: TCL_LIBRARY wrong version} -setup {
+ unset -nocomplain oldlibrary
+ if {[info exists env(TCL_LIBRARY)]} {
+ set oldlibrary $env(TCL_LIBRARY)
+ }
+} -body {
# ((pathc > 0) && (strcasecmp(installLib + 4, pathv[pathc - 1]) != 0))
-
set env(TCL_LIBRARY) /a/b/tcl1.7
set path [getlibpath]
unset env(TCL_LIBRARY)
-
lrange $path 0 1
-} [list /a/b/tcl1.7 /a/b/tcl[info tclversion]]
-test unixInit-2.4 {TclpInitLibraryPath: TCL_LIBRARY: INTL} \
- {unixOnly stdio} {
+} -cleanup {
+ if {[info exists oldlibrary]} {
+ set env(TCL_LIBRARY) $oldlibrary
+ unset oldlibrary
+ }
+} -result [list /a/b/tcl1.7 /a/b/tcl[info tclversion]]
+test unixInit-2.4 {TclpInitLibraryPath: TCL_LIBRARY: INTL} -setup {
+ if {[info exists env(TCL_LIBRARY)]} {
+ set oldlibrary $env(TCL_LIBRARY)
+ }
+} -body {
# Child process translates env variable from native encoding.
-
set env(TCL_LIBRARY) "\xa7"
set x [lindex [getlibpath] 0]
unset env(TCL_LIBRARY)
unset env(LANG)
-
set x
-} "\xa7"
-test unixInit-2.5 {TclpInitLibraryPath: compiled-in library path} \
- {emptyTest unixOnly} {
+} -cleanup {
+ if {[info exists oldlibrary]} {
+ set env(TCL_LIBRARY) $oldlibrary
+ unset oldlibrary
+ }
+} -result "\xa7"
+test unixInit-2.5 {TclpInitLibraryPath: compiled-in library path} {
# cannot test
} {}
-test unixInit-2.6 {TclpInitLibraryPath: executable relative} \
- {unixOnly stdio} {
+test unixInit-2.6 {TclpInitLibraryPath: executable relative} -setup {
+ unset -nocomplain oldlibrary
+ if {[info exists env(TCL_LIBRARY)]} {
+ set oldlibrary $env(TCL_LIBRARY)
+ }
+ set env(TCL_LIBRARY) [info library]
makeDirectory tmp
makeDirectory [file join tmp sparkly]
makeDirectory [file join tmp sparkly bin]
@@ -172,19 +184,23 @@ test unixInit-2.6 {TclpInitLibraryPath: executable relative} \
makeDirectory [file join tmp sparkly lib]
makeDirectory [file join tmp sparkly lib tcl[info tclversion]]
makeFile {} [file join tmp sparkly lib tcl[info tclversion] init.tcl]
-
- set x [lrange [getlibpath [file join [temporaryDirectory] tmp sparkly \
- bin tcltest]] 0 1]
+} -body {
+ lrange [getlibpath [file join [temporaryDirectory] tmp sparkly \
+ bin tcltest]] 1 2
+} -cleanup {
removeFile [file join tmp sparkly lib tcl[info tclversion] init.tcl]
removeDirectory [file join tmp sparkly lib tcl[info tclversion]]
removeDirectory [file join tmp sparkly lib]
removeDirectory [file join tmp sparkly bin]
removeDirectory [file join tmp sparkly]
removeDirectory tmp
- set x
-} [list [temporaryDirectory]/tmp/sparkly/lib/tcl[info tclversion] [temporaryDirectory]/tmp/lib/tcl[info tclversion]]
-test unixInit-2.7 {TclpInitLibraryPath: compiled-in library path} \
- {emptyTest unixOnly} {
+ unset env(TCL_LIBRARY)
+ if {[info exists oldlibrary]} {
+ set env(TCL_LIBRARY) $oldlibrary
+ unset oldlibrary
+ }
+} -result [list [temporaryDirectory]/tmp/sparkly/lib/tcl[info tclversion] [temporaryDirectory]/tmp/lib/tcl[info tclversion]]
+test unixInit-2.7 {TclpInitLibraryPath: compiled-in library path} {
# would need test command to get defaultLibDir and compare it to
# [lindex $auto_path end]
} {}
@@ -194,10 +210,12 @@ test unixInit-2.7 {TclpInitLibraryPath: compiled-in library path} \
# these tests need paths near the "root" of the file system to present
# themselves.
#
-testConstraint noSparkly [expr {![file exists [file join /tmp sparkly]]}]
-testConstraint noTmpInstall [expr {![file exists \
- [file join /tmp lib tcl[info tclversion]]]}]
-test unixInit-2.8 {TclpInitLibraryPath: all absolute pathtype} {unix noSparkly noTmpInstall} {
+test unixInit-2.8 {TclpInitLibraryPath: all absolute pathtype} -setup {
+ unset -nocomplain oldlibrary
+ if {[info exists env(TCL_LIBRARY)]} {
+ set oldlibrary $env(TCL_LIBRARY)
+ }
+ set env(TCL_LIBRARY) [info library]
# Checking for Bug 219416
# When a program that embeds the Tcl library, like tcltest, is
# installed near the "root" of the file system, there was a problem
@@ -217,7 +235,6 @@ test unixInit-2.8 {TclpInitLibraryPath: all absolute pathtype} {unix noSparkly n
file delete -force /tmp/lib/tcl[info tclversion]
file mkdir /tmp/sparkly
file copy [interpreter] /tmp/sparkly/tcltest
-
# Keep any existing /tmp/lib directory
set deletelib 1
if {[file exists /tmp/lib]} {
@@ -227,47 +244,60 @@ test unixInit-2.8 {TclpInitLibraryPath: all absolute pathtype} {unix noSparkly n
file delete -force /tmp/lib
}
}
-
# For a successful Tcl_Init, we need a [source]-able init.tcl in
# ../lib/tcl$version relative to the executable.
file mkdir /tmp/lib/tcl[info tclversion]
close [open /tmp/lib/tcl[info tclversion]/init.tcl w]
-
+} -body {
# Check that all directories in the library path are absolute pathnames
set allAbsolute 1
foreach dir [getlibpath /tmp/sparkly/tcltest] {
set allAbsolute [expr {$allAbsolute \
&& [string equal absolute [file pathtype $dir]]}]
}
-
+ set allAbsolute
+} -cleanup {
# Clean up temporary installation
file delete -force /tmp/sparkly
file delete -force /tmp/lib/tcl[info tclversion]
if {$deletelib} {file delete -force /tmp/lib}
- set allAbsolute
-} 1
-testConstraint noTmpBuild [expr {![file exists [file join /tmp library]]}]
-test unixInit-2.9 {TclpInitLibraryPath: paths relative to executable} {unix noSparkly noTmpBuild} {
+ unset env(TCL_LIBRARY)
+ if {[info exists oldlibrary]} {
+ set env(TCL_LIBRARY) $oldlibrary
+ unset oldlibrary
+ }
+} -result 1
+test unixInit-2.9 {TclpInitLibraryPath: paths relative to executable} -setup {
# Checking for Bug 438014
+ unset -nocomplain oldlibrary
+ if {[info exists env(TCL_LIBRARY)]} {
+ set oldlibrary $env(TCL_LIBRARY)
+ }
+ set env(TCL_LIBRARY) [info library]
file delete -force /tmp/sparkly
file delete -force /tmp/library
file mkdir /tmp/sparkly
file copy [interpreter] /tmp/sparkly/tcltest
-
file mkdir /tmp/library/
close [open /tmp/library/init.tcl w]
-
- set x [lrange [getlibpath /tmp/sparkly/tcltest] 0 4]
-
+} -body {
+ lrange [getlibpath /tmp/sparkly/tcltest] 1 5
+} -cleanup {
file delete -force /tmp/sparkly
file delete -force /tmp/library
- set x
-} [list /tmp/lib/tcl[info tclversion] /lib/tcl[info tclversion] \
+ unset env(TCL_LIBRARY)
+ if {[info exists oldlibrary]} {
+ set env(TCL_LIBRARY) $oldlibrary
+ unset oldlibrary
+ }
+} -result [list /tmp/lib/tcl[info tclversion] /lib/tcl[info tclversion] \
/tmp/library /library /tcl[info patchlevel]/library]
-
-test unixInit-2.10 {TclpInitLibraryPath: executable relative} -constraints {
- unixOnly stdio
-} -setup {
+test unixInit-2.10 {TclpInitLibraryPath: executable relative} -setup {
+ unset -nocomplain oldlibrary
+ if {[info exists env(TCL_LIBRARY)]} {
+ set oldlibrary $env(TCL_LIBRARY)
+ }
+ set env(TCL_LIBRARY) [info library]
set tmpDir [makeDirectory tmp]
set sparklyDir [makeDirectory sparkly $tmpDir]
set execPath [file join [makeDirectory bin $sparklyDir] tcltest]
@@ -279,9 +309,9 @@ test unixInit-2.10 {TclpInitLibraryPath: executable relative} -constraints {
cd $libDir
} -body {
# Checking for Bug 832657
- set x [lrange [getlibpath [file join .. bin tcltest]] 2 3]
+ set x [lrange [getlibpath [file join .. bin tcltest]] 3 4]
foreach p $x {
- lappend y [file normalize $p]
+ lappend y [file normalize $p]
}
set y
} -cleanup {
@@ -300,30 +330,31 @@ test unixInit-2.10 {TclpInitLibraryPath: executable relative} -constraints {
unset tmpDir
removeDirectory tmp
unset x p y
+ unset env(TCL_LIBRARY)
+ if {[info exists oldlibrary]} {
+ set env(TCL_LIBRARY) $oldlibrary
+ unset oldlibrary
+ }
} -result [list [file join [temporaryDirectory] tmp sparkly library] \
[file join [temporaryDirectory] tmp library] ]
test unixInit-3.1 {TclpSetInitialEncodings} -constraints {
- unixOnly stdio
+ unix stdio
} -body {
set env(LANG) C
-
set f [open "|[list [interpreter]]" w+]
fconfigure $f -buffering none
puts $f {puts [encoding system]; exit}
set enc [gets $f]
close $f
unset env(LANG)
-
set enc
} -match regexp -result [expr {
($tcl_platform(os) eq "Darwin") ? "^utf-8$" : "^iso8859-15?$"}]
-
-test unixInit-3.2 {TclpSetInitialEncodings} {unixOnly stdio} {
+test unixInit-3.2 {TclpSetInitialEncodings} {unix stdio} {
set env(LANG) japanese
catch {set oldlc_all $env(LC_ALL)}
set env(LC_ALL) japanese
-
set f [open "|[list [interpreter]]" w+]
fconfigure $f -buffering none
puts $f {puts [encoding system]; exit}
@@ -332,7 +363,6 @@ test unixInit-3.2 {TclpSetInitialEncodings} {unixOnly stdio} {
unset env(LANG)
unset env(LC_ALL)
catch {set env(LC_ALL) $oldlc_all}
-
set validEncodings [list euc-jp]
if {[string match HP-UX $tcl_platform(os)]} {
# Some older HP-UX systems need us to accept this as valid
@@ -343,23 +373,22 @@ test unixInit-3.2 {TclpSetInitialEncodings} {unixOnly stdio} {
expr {[lsearch -exact $validEncodings $enc] < 0}
} 0
-test unixInit-4.1 {TclpSetVariables} {unixOnly} {
+test unixInit-4.1 {TclpSetVariables} {unix} {
# just make sure they exist
-
set a [list $tcl_library $tcl_pkgPath $tcl_platform(os)]
set a [list $tcl_platform(osVersion) $tcl_platform(machine)]
set tcl_platform(platform)
} "unix"
-test unixInit-5.1 {Tcl_Init} {emptyTest unixOnly} {
+test unixInit-5.1 {Tcl_Init} {emptyTest unix} {
# test initScript
} {}
-test unixInit-6.1 {Tcl_SourceRCFile} {emptyTest unixOnly} {
+test unixInit-6.1 {Tcl_SourceRCFile} {emptyTest unix} {
} {}
test unixInit-7.1 {closed standard channel: Bug 772288} -constraints {
- unixOnly stdio
+ unix stdio
} -body {
set tclsh [interpreter]
set crash [makeFile {puts [open /dev/null]} crash.tcl]
@@ -374,11 +403,9 @@ test unixInit-7.1 {closed standard channel: Bug 772288} -constraints {
} -returnCodes 0
# cleanup
-if {[info exists oldlibrary]} {
- set env(TCL_LIBRARY) $oldlibrary
-}
catch {unset env(LANG)}
catch {set env(LANG) $oldlang}
unset -nocomplain path
::tcltest::cleanupTests
return
+
diff --git a/tests/unixNotfy.test b/tests/unixNotfy.test
index 8308055..8af8a21 100644
--- a/tests/unixNotfy.test
+++ b/tests/unixNotfy.test
@@ -19,14 +19,9 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-if {[info exists tk_version]} {
- puts "When run in a Tk shell, these tests run hang. Skipping tests ..."
- ::tcltest::cleanupTests
- return
-}
-
-set ::tcltest::testConstraints(testthread) \
- [expr {[info commands testthread] != {}}]
+# When run in a Tk shell, these tests hang.
+testConstraint noTk [expr {![info exists tk_version]}]
+testConstraint testthread [expr {[info commands testthread] != {}}]
# Darwin always uses a threaded notifier
testConstraint unthreaded [expr {
(![info exist tcl_platform(threaded)] || !$tcl_platform(threaded))
@@ -36,56 +31,46 @@ testConstraint unthreaded [expr {
# The next two tests will hang if threads are enabled because the notifier
# will not necessarily wait for ever in this case, so it does not generate
# an error.
-
-test unixNotfy-1.1 {Tcl_DeleteFileHandler} \
- -constraints {unixOnly && unthreaded} \
- -body {
- catch {vwait x}
- set f [open [makeFile "" foo] w]
- fileevent $f writable {set x 1}
- vwait x
- close $f
- list [catch {vwait x} msg] $msg
- } \
- -result {1 {can't wait for variable "x": would wait forever}} \
- -cleanup {
- catch { close $f }
- catch { removeFile foo }
- }
-
-test unixNotfy-1.2 {Tcl_DeleteFileHandler} \
- -constraints {unixOnly && unthreaded} \
- -body {
- catch {vwait x}
- set f1 [open [makeFile "" foo] w]
- set f2 [open [makeFile "" foo2] w]
- fileevent $f1 writable {set x 1}
- fileevent $f2 writable {set y 1}
- vwait x
- close $f1
- vwait y
- close $f2
- list [catch {vwait x} msg] $msg
- } \
- -result {1 {can't wait for variable "x": would wait forever}} \
- -cleanup {
- catch { close $f1 }
- catch { close $f2 }
- catch { removeFile foo }
- catch { removeFile foo2 }
- }
+test unixNotfy-1.1 {Tcl_DeleteFileHandler} -constraints {noTk unix unthreaded} -body {
+ catch {vwait x}
+ set f [open [makeFile "" foo] w]
+ fileevent $f writable {set x 1}
+ vwait x
+ close $f
+ list [catch {vwait x} msg] $msg
+} -result {1 {can't wait for variable "x": would wait forever}} -cleanup {
+ catch { close $f }
+ catch { removeFile foo }
+}
+test unixNotfy-1.2 {Tcl_DeleteFileHandler} -constraints {noTk unix unthreaded} -body {
+ catch {vwait x}
+ set f1 [open [makeFile "" foo] w]
+ set f2 [open [makeFile "" foo2] w]
+ fileevent $f1 writable {set x 1}
+ fileevent $f2 writable {set y 1}
+ vwait x
+ close $f1
+ vwait y
+ close $f2
+ list [catch {vwait x} msg] $msg
+} -result {1 {can't wait for variable "x": would wait forever}} -cleanup {
+ catch { close $f1 }
+ catch { close $f2 }
+ catch { removeFile foo }
+ catch { removeFile foo2 }
+}
test unixNotfy-2.1 {Tcl_DeleteFileHandler} \
- -constraints {unixOnly testthread} \
+ -constraints {noTk unix testthread} \
-body {
update
set f [open [makeFile "" foo] w]
fileevent $f writable {set x 1}
vwait x
close $f
- testthread create "testthread send [testthread id] {set x ok}"
+ testthread create "testthread send [testthread id] {set x ok}"
vwait x
- threadReap
+ threadReap
set x
} \
-result {ok} \
@@ -93,9 +78,8 @@ test unixNotfy-2.1 {Tcl_DeleteFileHandler} \
catch { close $f }
catch { removeFile foo }
}
-
test unixNotfy-2.2 {Tcl_DeleteFileHandler} \
- -constraints {unixOnly testthread} \
+ -constraints {noTk unix testthread} \
-body {
update
set f1 [open [makeFile "" foo] w]
@@ -106,9 +90,9 @@ test unixNotfy-2.2 {Tcl_DeleteFileHandler} \
close $f1
vwait y
close $f2
- testthread create "testthread send [testthread id] {set x ok}"
+ testthread create "testthread send [testthread id] {set x ok}"
vwait x
- threadReap
+ threadReap
set x
} \
-result {ok} \
diff --git a/tests/unknown.test b/tests/unknown.test
index 6e95a2b..69a468f 100644
--- a/tests/unknown.test
+++ b/tests/unknown.test
@@ -63,15 +63,3 @@ catch {rename unknown {}}
catch {rename unknown.old unknown}
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/unload.test b/tests/unload.test
new file mode 100644
index 0000000..9e34bce
--- /dev/null
+++ b/tests/unload.test
@@ -0,0 +1,219 @@
+# Commands covered: unload
+#
+# This file contains a collection of tests for one or more of the Tcl
+# built-in commands. Sourcing this file into Tcl runs the tests and
+# generates output for errors. No output means no errors were found.
+#
+# Copyright (c) 1995 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# Copyright (c) 2003-2004 by Georgios Petasis
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+if {[lsearch [namespace children] ::tcltest] == -1} {
+ package require tcltest 2
+ namespace import -force ::tcltest::*
+}
+
+# Figure out what extension is used for shared libraries on this
+# platform.
+if {![info exists ext]} {
+ set ext [info sharedlibextension]
+}
+
+# Tests require the existence of one of the DLLs in the dltest directory.
+set testDir [file join [file dirname [info nameofexecutable]] dltest]
+set x [file join $testDir pkgua$ext]
+set dll "[file tail $x]Required"
+testConstraint $dll [file readable $x]
+
+# Tests also require that this DLL has not already been loaded.
+set loaded "[file tail $x]Loaded"
+set alreadyLoaded [info loaded]
+testConstraint $loaded [expr {![string match *pkgua* $alreadyLoaded]}]
+
+set alreadyTotalLoaded [info loaded]
+
+# Certain tests require the 'teststaticpkg' command from tcltest
+testConstraint teststaticpkg [llength [info commands teststaticpkg]]
+
+# Basic tests: parameter testing...
+test unload-1.1 {basic errors} {} {
+ list [catch {unload} msg] $msg
+} "1 {wrong \# args: should be \"unload ?switches? fileName ?packageName? ?interp?\"}"
+test unload-1.2 {basic errors} {} {
+ list [catch {unload a b c d} msg] $msg
+} "1 {wrong \# args: should be \"unload ?switches? fileName ?packageName? ?interp?\"}"
+test unload-1.3 {basic errors} {} {
+ list [catch {unload a b foobar} msg] $msg
+} {1 {could not find interpreter "foobar"}}
+test unload-1.4 {basic errors} {} {
+ list [catch {unload {}} msg] $msg
+} {1 {must specify either file name or package name}}
+test unload-1.5 {basic errors} {} {
+ list [catch {unload {} {}} msg] $msg
+} {1 {must specify either file name or package name}}
+test unload-1.6 {basic errors} {} {
+ list [catch {unload {} Unknown} msg] $msg
+} {1 {package "Unknown" is loaded statically and cannot be unloaded}}
+test unload-1.7 {-nocomplain switch} {} {
+ list [unload -nocomplain {} Unknown]
+} {{}}
+
+set pkgua_loaded {}
+set pkgua_detached {}
+set pkgua_unloaded {}
+# Tests for loading/unloading in trusted (non-safe) interpreters...
+test unload-2.1 {basic loading of non-unloadable package, with guess for package name} [list $dll $loaded] {
+ load [file join $testDir pkga$ext]
+ list [pkga_eq abc def] [lsort [info commands pkga_*]]
+} {0 {pkga_eq pkga_quote}}
+test unload-2.2 {basic loading of unloadable package, with guess for package name} [list $dll $loaded] {
+ list $pkgua_loaded $pkgua_detached $pkgua_unloaded \
+ [load [file join $testDir pkgua$ext]] \
+ [pkgua_eq abc def] [lsort [info commands pkgua_*]] \
+ $pkgua_loaded $pkgua_detached $pkgua_unloaded
+} {{} {} {} {} 0 {pkgua_eq pkgua_quote} . {} {}}
+test unload-2.3 {basic unloading of non-unloadable package, with guess for package name} [list $dll $loaded] {
+ list [catch {unload [file join $testDir pkga$ext]} msg] \
+ [string map [list [file join $testDir pkga$ext] file] $msg]
+} {1 {file "file" cannot be unloaded under a trusted interpreter}}
+test unload-2.4 {basic unloading of unloadable package, with guess for package name} [list $dll $loaded] {
+ list $pkgua_loaded $pkgua_detached $pkgua_unloaded \
+ [unload [file join $testDir pkgua$ext]] \
+ [info commands pkgua_*] \
+ $pkgua_loaded $pkgua_detached $pkgua_unloaded
+} {. {} {} {} {} . . .}
+test unload-2.5 {reloading of unloaded package, with guess for package name} [list $dll $loaded] {
+ list $pkgua_loaded $pkgua_detached $pkgua_unloaded \
+ [load [file join $testDir pkgua$ext]] \
+ [pkgua_eq abc def] [lsort [info commands pkgua_*]] \
+ $pkgua_loaded $pkgua_detached $pkgua_unloaded
+} {. . . {} 0 {pkgua_eq pkgua_quote} .. . .}
+test unload-2.6 {basic unloading of re-loaded package, with guess for package name} [list $dll $loaded] {
+ list $pkgua_loaded $pkgua_detached $pkgua_unloaded \
+ [unload [file join $testDir pkgua$ext]] \
+ [info commands pkgua_*] \
+ $pkgua_loaded $pkgua_detached $pkgua_unloaded
+} {.. . . {} {} .. .. ..}
+
+# Tests for loading/unloading in safe interpreters...
+interp create -safe child
+child eval {
+ set pkgua_loaded {}
+ set pkgua_detached {}
+ set pkgua_unloaded {}
+}
+test unload-3.1 {basic loading of non-unloadable package in a safe interpreter, with package name conversion} \
+ [list $dll $loaded] {
+ catch {rename pkgb_sub {}}
+ load [file join $testDir pkgb$ext] pKgB child
+ list [child eval pkgb_sub 44 13] [catch {child eval pkgb_unsafe} msg] $msg \
+ [catch {pkgb_sub 12 10} msg2] $msg2
+} {31 1 {invalid command name "pkgb_unsafe"} 1 {invalid command name "pkgb_sub"}}
+test unload-3.2 {basic loading of unloadable package in a safe interpreter, with package name conversion} \
+ [list $dll $loaded] {
+ list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
+ [load [file join $testDir pkgua$ext] pKgUA child] \
+ [child eval pkgua_eq abc def] \
+ [lsort [child eval info commands pkgua_*]] \
+ [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
+} {{{} {} {}} {} 0 {pkgua_eq pkgua_quote} {. {} {}}}
+test unload-3.3 {unloading of a package that has never been loaded from a safe interpreter} \
+ [list $dll $loaded] {
+ list [catch {unload [file join $testDir pkga$ext] {} child} msg] \
+ [string map [list [file join $testDir pkga$ext] file] $msg]
+} {1 {file "file" has never been loaded in this interpreter}}
+test unload-3.4 {basic unloading of a non-unloadable package from a safe interpreter, with guess for package name} \
+ [list $dll $loaded] {
+ list [catch {unload [file join $testDir pkgb$ext] {} child} msg] \
+ [string map [list [file join $testDir pkgb$ext] file] $msg]
+} {1 {file "file" cannot be unloaded under a safe interpreter}}
+test unload-3.5 {basic unloading of an unloadable package from a safe interpreter, with guess for package name} \
+ [list $dll $loaded] {
+ list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
+ [unload [file join $testDir pkgua$ext] {} child] \
+ [child eval info commands pkgua_*] \
+ [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
+} {{. {} {}} {} {} {. . .}}
+test unload-3.6 {reloading of unloaded package in a safe interpreter, with guess for package name} \
+ [list $dll $loaded] {
+ list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
+ [load [file join $testDir pkgua$ext] {} child] \
+ [child eval pkgua_eq abc def] \
+ [lsort [child eval info commands pkgua_*]] \
+ [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
+} {{. . .} {} 0 {pkgua_eq pkgua_quote} {.. . .}}
+test unload-3.7 {basic unloading of re-loaded package from a safe interpreter, with package name conversion} \
+ [list $dll $loaded] {
+ list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
+ [unload [file join $testDir pkgua$ext] pKgUa child] \
+ [child eval info commands pkgua_*] \
+ [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
+} {{.. . .} {} {} {.. .. ..}}
+
+# Tests for loading/unloading of a package among multiple interpreters...
+interp create child-trusted
+child-trusted eval {
+ set pkgua_loaded {}
+ set pkgua_detached {}
+ set pkgua_unloaded {}
+}
+## Load package in main trusted interpreter...
+test unload-4.1 {loading of unloadable package in trusted interpreter, with guess for package name} \
+ [list $dll $loaded] {
+ list [list $pkgua_loaded $pkgua_detached $pkgua_unloaded] \
+ [load [file join $testDir pkgua$ext]] \
+ [pkgua_eq abc def] [lsort [info commands pkgua_*]] \
+ [list $pkgua_loaded $pkgua_detached $pkgua_unloaded]
+} {{.. .. ..} {} 0 {pkgua_eq pkgua_quote} {... .. ..}}
+## Load package in child-safe interpreter...
+test unload-4.2 {basic loading of unloadable package in a safe interpreter, with package name conversion} \
+ [list $dll $loaded] {
+ list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
+ [load [file join $testDir pkgua$ext] pKgUA child] \
+ [child eval pkgua_eq abc def] \
+ [lsort [child eval info commands pkgua_*]] \
+ [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
+} {{.. .. ..} {} 0 {pkgua_eq pkgua_quote} {... .. ..}}
+## Load package in child-trusted interpreter...
+test unload-4.3 {basic loading of unloadable package in a second trusted interpreter, with package name conversion} \
+ [list $dll $loaded] {
+ list [child-trusted eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
+ [load [file join $testDir pkgua$ext] pkguA child-trusted] \
+ [child-trusted eval pkgua_eq abc def] \
+ [lsort [child-trusted eval info commands pkgua_*]] \
+ [child-trusted eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
+} {{{} {} {}} {} 0 {pkgua_eq pkgua_quote} {. {} {}}}
+## Unload the package from the main trusted interpreter...
+test unload-4.4 {basic unloading of unloadable package from trusted interpreter, with guess for package name} \
+ [list $dll $loaded] {
+ list [list $pkgua_loaded $pkgua_detached $pkgua_unloaded] \
+ [unload [file join $testDir pkgua$ext]] \
+ [info commands pkgua_*] \
+ [list $pkgua_loaded $pkgua_detached $pkgua_unloaded]
+} {{... .. ..} {} {} {... ... ..}}
+## Unload the package from the child safe interpreter...
+test unload-4.5 {basic unloading of unloadable package from a safe interpreter, with guess for package name} \
+ [list $dll $loaded] {
+ list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
+ [unload [file join $testDir pkgua$ext] {} child] \
+ [child eval info commands pkgua_*] \
+ [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
+} {{... .. ..} {} {} {... ... ..}}
+## Unload the package from the child trusted interpreter...
+test unload-4.6 {basic unloading of unloadable package from a safe interpreter, with guess for package name} \
+ [list $dll $loaded] {
+ list [child-trusted eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
+ [unload [file join $testDir pkgua$ext] {} child-trusted] \
+ [child-trusted eval info commands pkgua_*] \
+ [child-trusted eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}]
+} {{. {} {}} {} {} {. . .}}
+
+# cleanup
+interp delete child
+interp delete child-trusted
+unset ext
+::tcltest::cleanupTests
+return
diff --git a/tests/uplevel.test b/tests/uplevel.test
index 4670369..cfe4b72 100644
--- a/tests/uplevel.test
+++ b/tests/uplevel.test
@@ -128,15 +128,3 @@ test uplevel-6.1 {uplevel and shadowed cmds} {
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/upvar.test b/tests/upvar.test
index 1301338..457c9f8 100644
--- a/tests/upvar.test
+++ b/tests/upvar.test
@@ -1,4 +1,4 @@
-# Commands covered: upvar
+# Commands covered: 'upvar', 'namespace upvar'
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands. Sourcing this file into Tcl runs the tests and
@@ -12,10 +12,12 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2
namespace import -force ::tcltest::*
}
+testConstraint testupvar [llength [info commands testupvar]]
+
test upvar-1.1 {reading variables with upvar} {
proc p1 {a b} {set c 22; set d 33; p2}
proc p2 {} {upvar a x1 b x2 c x3 d x4; set a abc; list $x1 $x2 $x3 $x4 $a}
@@ -312,13 +314,15 @@ test upvar-8.7 {errors in upvar command} {
proc p1 {} {trace variable a w foo; upvar b a}
list [catch p1 msg] $msg
} {1 {variable "a" has traces: can't use for upvar}}
-test upvar-8.8 {create nested array with upvar} {
+test upvar-8.8 {create nested array with upvar} -body {
proc p1 {} {upvar x(a) b; set b(2) 44}
catch {unset x}
list [catch p1 msg] $msg
-} {1 {can't set "b(2)": variable isn't array}}
+} -cleanup {
+ unset x
+} -result {1 {can't set "b(2)": variable isn't array}}
test upvar-8.9 {upvar won't create namespace variable that refers to procedure variable} {
- catch {eval namespace delete [namespace children :: test_ns_*]}
+ catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {rename MakeLink ""}
namespace eval ::test_ns_1 {}
proc MakeLink {a} {
@@ -334,82 +338,211 @@ test upvar-8.10 {upvar will create element alias for new array element} {
array set upvarArray {}
catch {upvar 0 upvarArray(elem) upvarArrayElemAlias}
} {0}
+test upvar-8.11 {upvar will not create a variable that looks like an array} -body {
+ catch {unset upvarArray}
+ array set upvarArray {}
+ upvar 0 upvarArray(elem) upvarArrayElemAlias(elem)
+} -returnCodes 1 -match glob -result *
-if {[info commands testupvar] != {}} {
- test upvar-9.1 {Tcl_UpVar2 procedure} {
- list [catch {testupvar xyz a {} x global} msg] $msg
- } {1 {bad level "xyz"}}
- test upvar-9.2 {Tcl_UpVar2 procedure} {
- catch {unset a}
- catch {unset x}
- set a 44
- list [catch {testupvar #0 a 1 x global} msg] $msg
- } {1 {can't access "a(1)": variable isn't array}}
- test upvar-9.3 {Tcl_UpVar2 procedure} {
- proc foo {} {
- testupvar 1 a {} x local
- set x
- }
- catch {unset a}
- catch {unset x}
- set a 44
- foo
- } {44}
- test upvar-9.4 {Tcl_UpVar2 procedure} {
- proc foo {} {
- testupvar 1 a {} _up_ global
- list [catch {set x} msg] $msg
- }
- catch {unset a}
- catch {unset _up_}
- set a 44
- concat [foo] $_up_
- } {1 {can't read "x": no such variable} 44}
- test upvar-9.5 {Tcl_UpVar2 procedure} {
- proc foo {} {
- testupvar 1 a b x local
- set x
- }
- catch {unset a}
- catch {unset x}
- set a(b) 1234
- foo
- } {1234}
- test upvar-9.6 {Tcl_UpVar procedure} {
- proc foo {} {
- testupvar 1 a x local
- set x
- }
- catch {unset a}
- catch {unset x}
- set a xyzzy
- foo
- } {xyzzy}
- test upvar-9.7 {Tcl_UpVar procedure} {
- proc foo {} {
- testupvar #0 a(b) x local
- set x
- }
- catch {unset a}
- catch {unset x}
- set a(b) 1234
- foo
- } {1234}
-}
+test upvar-9.1 {Tcl_UpVar2 procedure} testupvar {
+ list [catch {testupvar xyz a {} x global} msg] $msg
+} {1 {bad level "xyz"}}
+test upvar-9.2 {Tcl_UpVar2 procedure} testupvar {
+ catch {unset a}
+ catch {unset x}
+ set a 44
+ list [catch "testupvar #0 a 1 x global" msg] $msg
+} {1 {can't access "a(1)": variable isn't array}}
+test upvar-9.3 {Tcl_UpVar2 procedure} testupvar {
+ proc foo {} {
+ testupvar 1 a {} x local
+ set x
+ }
+ catch {unset a}
+ catch {unset x}
+ set a 44
+ foo
+} {44}
+test upvar-9.4 {Tcl_UpVar2 procedure} testupvar {
+ proc foo {} {
+ testupvar 1 a {} _up_ global
+ list [catch {set x} msg] $msg
+ }
+ catch {unset a}
+ catch {unset _up_}
+ set a 44
+ concat [foo] $_up_
+} {1 {can't read "x": no such variable} 44}
+test upvar-9.5 {Tcl_UpVar2 procedure} testupvar {
+ proc foo {} {
+ testupvar 1 a b x local
+ set x
+ }
+ catch {unset a}
+ catch {unset x}
+ set a(b) 1234
+ foo
+} {1234}
+test upvar-9.6 {Tcl_UpVar procedure} testupvar {
+ proc foo {} {
+ testupvar 1 a x local
+ set x
+ }
+ catch {unset a}
+ catch {unset x}
+ set a xyzzy
+ foo
+} {xyzzy}
+test upvar-9.7 {Tcl_UpVar procedure} testupvar {
+ proc foo {} {
+ testupvar #0 a(b) x local
+ set x
+ }
+ catch {unset a}
+ catch {unset x}
+ set a(b) 1234
+ foo
+} {1234}
catch {unset a}
-# cleanup
-::tcltest::cleanupTests
-return
+#
+# Tests for 'namespace upvar'. As the implementation is essentially the same as
+# for 'upvar', we only test that the variables are linked correctly. Ie, we
+# assume that the behaviour of variables once the link is established has
+# already been tested above.
+#
+#
+
+# Clear out any namespaces called test_ns_*
+catch {namespace delete {*}[namespace children :: test_ns_*]}
+namespace eval test_ns_0 {
+ variable x test_ns_0
+}
+
+set x test_global
+test upvar-NS-1.1 {nsupvar links to correct variable} \
+ -body {
+ namespace eval test_ns_1 {
+ namespace upvar ::test_ns_0 x w
+ set w
+ }
+ } \
+ -result {test_ns_0} \
+ -cleanup {namespace delete test_ns_1}
+
+test upvar-NS-1.2 {nsupvar links to correct variable} \
+ -body {
+ namespace eval test_ns_1 {
+ proc a {} {
+ namespace upvar ::test_ns_0 x w
+ set w
+ }
+ return [a]
+ }
+ } \
+ -result {test_ns_0} \
+ -cleanup {namespace delete test_ns_1}
+test upvar-NS-1.3 {nsupvar links to correct variable} \
+ -body {
+ namespace eval test_ns_1 {
+ namespace upvar test_ns_0 x w
+ set w
+ }
+ } \
+ -result {namespace "test_ns_0" not found in "::test_ns_1"} \
+ -returnCodes error \
+ -cleanup {namespace delete test_ns_1}
+test upvar-NS-1.4 {nsupvar links to correct variable} \
+ -body {
+ namespace eval test_ns_1 {
+ proc a {} {
+ namespace upvar test_ns_0 x w
+ set w
+ }
+ return [a]
+ }
+ } \
+ -result {namespace "test_ns_0" not found in "::test_ns_1"} \
+ -returnCodes error \
+ -cleanup {namespace delete test_ns_1}
+test upvar-NS-1.5 {nsupvar links to correct variable} \
+ -body {
+ namespace eval test_ns_1 {
+ namespace eval test_ns_0 {}
+ namespace upvar test_ns_0 x w
+ set w
+ }
+ } \
+ -result {can't read "w": no such variable} \
+ -returnCodes error \
+ -cleanup {namespace delete test_ns_1}
+test upvar-NS-1.6 {nsupvar links to correct variable} \
+ -body {
+ namespace eval test_ns_1 {
+ namespace eval test_ns_0 {}
+ proc a {} {
+ namespace upvar test_ns_0 x w
+ set w
+ }
+ return [a]
+ }
+ } \
+ -result {can't read "w": no such variable} \
+ -returnCodes error \
+ -cleanup {namespace delete test_ns_1}
+test upvar-NS-1.7 {nsupvar links to correct variable} \
+ -body {
+ namespace eval test_ns_1 {
+ namespace eval test_ns_0 {
+ variable x test_ns_1::test_ns_0
+ }
+ namespace upvar test_ns_0 x w
+ set w
+ }
+ } \
+ -result {test_ns_1::test_ns_0} \
+ -cleanup {namespace delete test_ns_1}
+test upvar-NS-1.8 {nsupvar links to correct variable} \
+ -body {
+ namespace eval test_ns_1 {
+ namespace eval test_ns_0 {
+ variable x test_ns_1::test_ns_0
+ }
+ proc a {} {
+ namespace upvar test_ns_0 x w
+ set w
+ }
+ return [a]
+ }
+ } \
+ -result {test_ns_1::test_ns_0} \
+ -cleanup {namespace delete test_ns_1}
+test upvar-NS-1.9 {nsupvar links to correct variable} \
+ -body {
+ namespace eval test_ns_1 {
+ variable x test_ns_1
+ proc a {} {
+ namespace upvar test_ns_0 x w
+ set w
+ }
+ return [a]
+ }
+ } \
+ -result {namespace "test_ns_0" not found in "::test_ns_1"} \
+ -returnCodes error \
+ -cleanup {namespace delete test_ns_1}
+# cleanup
+::tcltest::cleanupTests
+return
diff --git a/tests/utf.test b/tests/utf.test
index 63be814..d319f6e 100644
--- a/tests/utf.test
+++ b/tests/utf.test
@@ -318,39 +318,72 @@ test utf-24.4 {unicode space char in regc_locale.c} {
testConstraint teststringobj [llength [info commands teststringobj]]
-test utf-25.1 {Tcl_UniCharNcasecmp} teststringobj {
- testobj freeallvars
- teststringobj set 1 a
- teststringobj set 2 b
- teststringobj getunicode 1
- teststringobj getunicode 2
- string compare -nocase [teststringobj get 1] [teststringobj get 2]
-} -1
-test utf-25.2 {Tcl_UniCharNcasecmp} teststringobj {
- testobj freeallvars
- teststringobj set 1 b
- teststringobj set 2 a
- teststringobj getunicode 1
- teststringobj getunicode 2
- string compare -nocase [teststringobj get 1] [teststringobj get 2]
-} 1
-test utf-25.3 {Tcl_UniCharNcasecmp} teststringobj {
- testobj freeallvars
- teststringobj set 1 B
- teststringobj set 2 a
- teststringobj getunicode 1
- teststringobj getunicode 2
- string compare -nocase [teststringobj get 1] [teststringobj get 2]
-} 1
-test utf-25.4 {Tcl_UniCharNcasecmp} teststringobj {
- testobj freeallvars
- teststringobj set 1 aBcB
- teststringobj set 2 abca
- teststringobj getunicode 1
- teststringobj getunicode 2
- string compare -nocase [teststringobj get 1] [teststringobj get 2]
-} 1
+test utf-25.1 {Tcl_UniCharNcasecmp} -constraints teststringobj \
+ -setup {
+ testobj freeallvars
+ } \
+ -body {
+ teststringobj set 1 a
+ teststringobj set 2 b
+ teststringobj getunicode 1
+ teststringobj getunicode 2
+ string compare -nocase [teststringobj get 1] [teststringobj get 2]
+ } \
+ -cleanup {
+ testobj freeallvars
+ } \
+ -result -1
+test utf-25.2 {Tcl_UniCharNcasecmp} -constraints teststringobj \
+ -setup {
+ testobj freeallvars
+ } \
+ -body {
+ teststringobj set 1 b
+ teststringobj set 2 a
+ teststringobj getunicode 1
+ teststringobj getunicode 2
+ string compare -nocase [teststringobj get 1] [teststringobj get 2]
+ } \
+ -cleanup {
+ testobj freeallvars
+ } \
+ -result 1
+test utf-25.3 {Tcl_UniCharNcasecmp} -constraints teststringobj \
+ -setup {
+ testobj freeallvars
+ } \
+ -body {
+ teststringobj set 1 B
+ teststringobj set 2 a
+ teststringobj getunicode 1
+ teststringobj getunicode 2
+ string compare -nocase [teststringobj get 1] [teststringobj get 2]
+ } \
+ -cleanup {
+ testobj freeallvars
+ } \
+ -result 1
+
+test utf-25.4 {Tcl_UniCharNcasecmp} -constraints teststringobj \
+ -setup {
+ testobj freeallvars
+ } \
+ -body {
+ teststringobj set 1 aBcB
+ teststringobj set 2 abca
+ teststringobj getunicode 1
+ teststringobj getunicode 2
+ string compare -nocase [teststringobj get 1] [teststringobj get 2]
+ } \
+ -cleanup {
+ testobj freeallvars
+ } \
+ -result 1
# cleanup
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/util.test b/tests/util.test
index da42f61..c910b43 100644
--- a/tests/util.test
+++ b/tests/util.test
@@ -12,6 +12,110 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
+testConstraint testdstring [llength [info commands testdstring]]
+testConstraint testconcatobj [llength [info commands testconcatobj]]
+
+# Big test for correct ordering of data in [expr]
+
+proc testIEEE {} {
+ variable ieeeValues
+ binary scan [binary format dd -1.0 1.0] c* c
+ switch -exact -- $c {
+ {0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
+ # little endian
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \
+ ieeeValues(-Infinity)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \
+ ieeeValues(-Normal)
+ binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
+ ieeeValues(-Subnormal)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
+ ieeeValues(-0)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+0)
+ binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
+ ieeeValues(+Subnormal)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \
+ ieeeValues(+Normal)
+ binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
+ ieeeValues(+Infinity)
+ binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
+ ieeeValues(NaN)
+ binary scan \x00\x00\x00\x00\x00\x00\xf8\xff d \
+ ieeeValues(-NaN)
+ binary scan \xef\xcd\xab\x89\x67\x45\xfb\xff d \
+ ieeeValues(-NaN(3456789abcdef))
+ set ieeeValues(littleEndian) 1
+ return 1
+ }
+ {-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
+ binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Infinity)
+ binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Normal)
+ binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-Subnormal)
+ binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-0)
+ binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+0)
+ binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Subnormal)
+ binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Normal)
+ binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(+Infinity)
+ binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(NaN)
+ binary scan \xff\xf8\x00\x00\x00\x00\x00\x00 d \
+ ieeeValues(-NaN)
+ binary scan \xff\xfb\x45\x67\x89\xab\xcd\xef d \
+ ieeeValues(-NaN(3456789abcdef))
+ set ieeeValues(littleEndian) 0
+ return 1
+ }
+ default {
+ return 0
+ }
+ }
+}
+testConstraint ieeeFloatingPoint [testIEEE]
+
+proc convertDouble { x } {
+ variable ieeeValues
+ if { $ieeeValues(littleEndian) } {
+ binary scan [binary format w $x] d result
+ } else {
+ binary scan [binary format W $x] d result
+ }
+ return $result
+}
+
+proc verdonk_test {sig binexp shouldbe exp} {
+ regexp {([-+]?)([0-9a-f]+)} $sig -> signum sig
+ scan $sig %llx sig
+ if {$signum eq {-}} {
+ set signum [expr 1<<63]
+ } else {
+ set signum 0
+ }
+ regexp {E([-+]?[0-9]+)} $binexp -> binexp
+ set word [expr {$signum | (($binexp + 0x3ff)<<52)|($sig & ~(1<<52))}]
+ binary scan [binary format w $word] q double
+ regexp {([-+])(\d+)_(\d+)\&} $shouldbe -> signum digits1 digits2
+ regexp {E([-+]\d+)} $exp -> decexp
+ incr decexp [expr {[string length $digits1] - 1}]
+ lassign [testdoubledigits $double [string length $digits1] e] \
+ outdigits decpt outsign
+ if {[string index $digits2 0] >= 5} {
+ incr digits1
+ }
+ if {$outsign != $signum || $outdigits != $digits1 || $decpt != $decexp} {
+ return -code error "result is ${outsign}0.${outdigits}E$decpt\
+ should be ${signum}0.${digits1}E$decexp"
+ }
+}
+
test util-1.1 {TclFindElement procedure - binary element in middle of list} {
lindex {0 foo\x00help 1} 1
} "foo\x00help"
@@ -32,11 +136,50 @@ test util-3.1 {Tcl_ScanCountedElement procedure - don't leave unmatched braces}
# have the property that it can be enclosing in curly braces to make
# an embedded sub-list. If this property doesn't hold, then
# Tcl_DStringStartSublist doesn't work.
-
set x {}
- lappend x " \\\{ \\"
+ lappend x "# \\\{ \\"
concat $x [llength "{$x}"]
-} {\ \\\{\ \\ 1}
+} {\#\ \\\{\ \\ 1}
+test util-3.2 {Tcl_ConverCountedElement procedure - quote leading '#'} {
+ list # # a
+} {{#} # a}
+test util-3.3 {Tcl_ConverCountedElement procedure - quote leading '#'} {
+ list #\{ # a
+} {\#\{ # a}
+test util-3.4 {Tcl_ConverCountedElement procedure - quote leading '#'} {
+ proc # {} {return #}
+ set result [eval [list #]]
+ rename # {}
+ set result
+} {#}
+test util-3.4.1 {Tcl_ConverCountedElement procedure - quote leading '#'} {
+ proc # {} {return #}
+ set cmd [list #]
+ append cmd "" ;# force string rep generation
+ set result [eval $cmd]
+ rename # {}
+ set result
+} {#}
+test util-3.5 {Tcl_ConverCountedElement procedure - quote leading '#'} {
+ proc #\{ {} {return #}
+ set result [eval [list #\{]]
+ rename #\{ {}
+ set result
+} {#}
+test util-3.5.1 {Tcl_ConverCountedElement procedure - quote leading '#'} {
+ proc #\{ {} {return #}
+ set cmd [list #\{]
+ append cmd "" ;# force string rep generation
+ set result [eval $cmd]
+ rename #\{ {}
+ set result
+} {#}
+test util-3.6 {Tcl_ConvertElement, Bug 3371644} {
+ interp create #\\
+ interp alias {} x #\\ concat
+ interp target {} x ;# Crash if bug not fixed
+ interp delete #\\
+} {}
test util-4.1 {Tcl_ConcatObj - backslash-space at end of argument} {
concat a {b\ } c
@@ -57,6 +200,11 @@ test util-4.6 {Tcl_ConcatObj - utf-8 sequence with "whitespace" char} {
# Check for Bug #227512. If this violates C isspace, then it returns \xc3.
concat \xe0
} \xe0
+test util-4.7 {Tcl_ConcatObj - refCount safety} testconcatobj {
+ # Check for Bug #1447328 (actually, bugs in its original "fix"). One of the
+ # symptoms was Bug #2055782.
+ testconcatobj
+} {}
proc Wrapper_Tcl_StringMatch {pattern string} {
# Forces use of Tcl_StringMatch, not Tcl_UniCharCaseMatch
@@ -88,7 +236,6 @@ test util-5.8 {Tcl_StringMatch} {
} 1
test util-5.9 {Tcl_StringMatch: UTF-8} {
# skip one character in string
-
Wrapper_Tcl_StringMatch a?c a\u4e4fc
} 1
test util-5.10 {Tcl_StringMatch} {
@@ -102,19 +249,16 @@ test util-5.12 {Tcl_StringMatch} {
} 1
test util-5.13 {Tcl_StringMatch: UTF-8} {
# string += Tcl_UtfToUniChar(string, &ch);
-
Wrapper_Tcl_StringMatch "\[\u4e4fxy\]bc" "\u4e4fbc"
} 1
test util-5.14 {Tcl_StringMatch} {
# if ((*pattern == ']') || (*pattern == '\0'))
# badly formed pattern
-
Wrapper_Tcl_StringMatch {[]} {[]}
} 0
test util-5.15 {Tcl_StringMatch} {
# if ((*pattern == ']') || (*pattern == '\0'))
# badly formed pattern
-
Wrapper_Tcl_StringMatch {[} {[}
} 0
test util-5.16 {Tcl_StringMatch} {
@@ -123,19 +267,16 @@ test util-5.16 {Tcl_StringMatch} {
test util-5.17 {Tcl_StringMatch: UTF-8} {
# pattern += Tcl_UtfToUniChar(pattern, &endChar);
# get 1 UTF-8 character
-
Wrapper_Tcl_StringMatch "a\[a\u4e4fc]c" "a\u4e4fc"
} 1
test util-5.18 {Tcl_StringMatch: UTF-8} {
# pattern += Tcl_UtfToUniChar(pattern, &endChar);
# proper advance: wrong answer would match on UTF trail byte of \u4e4f
-
Wrapper_Tcl_StringMatch {a[a\u4e4fc]c} [bytestring a\u008fc]
} 0
test util-5.19 {Tcl_StringMatch: UTF-8} {
# pattern += Tcl_UtfToUniChar(pattern, &endChar);
# proper advance.
-
Wrapper_Tcl_StringMatch {a[a\u4e4fc]c} "acc"
} 1
test util-5.20 {Tcl_StringMatch} {
@@ -216,7 +357,6 @@ test util-5.44 {Tcl_StringMatch: skip correct number of ']'} {
test util-5.45 {Tcl_StringMatch} {
# if (*pattern == '\0')
# badly formed pattern, still treats as a set
-
Wrapper_Tcl_StringMatch {[a} a
} 1
test util-5.46 {Tcl_StringMatch} {
@@ -238,42 +378,70 @@ test util-5.51 {Tcl_StringMatch} {
Wrapper_Tcl_StringMatch "" ""
} 1
-test util-6.1 {Tcl_PrintDouble - using tcl_precision} {
+test util-6.1 {Tcl_PrintDouble - using tcl_precision} -setup {
+ set old_precision $::tcl_precision
+ set ::tcl_precision 12
+} -body {
concat x[expr 1.4]
-} {x1.4}
-test util-6.2 {Tcl_PrintDouble - using tcl_precision} {
+} -cleanup {
+ set ::tcl_precision $old_precision
+} -result {x1.4}
+test util-6.2 {Tcl_PrintDouble - using tcl_precision} -setup {
+ set old_precision $::tcl_precision
+ set ::tcl_precision 12
+} -body {
concat x[expr 1.39999999999]
-} {x1.39999999999}
-test util-6.3 {Tcl_PrintDouble - using tcl_precision} {
+} -cleanup {
+ set ::tcl_precision $old_precision
+} -result {x1.39999999999}
+test util-6.3 {Tcl_PrintDouble - using tcl_precision} -setup {
+ set old_precision $::tcl_precision
+ set ::tcl_precision 12
+} -body {
concat x[expr 1.399999999999]
-} {x1.4}
-test util-6.4 {Tcl_PrintDouble - using tcl_precision} {
- set tcl_precision 5
+} -cleanup {
+ set ::tcl_precision $old_precision
+} -result {x1.4}
+test util-6.4 {Tcl_PrintDouble - using tcl_precision} -setup {
+ set old_precision $::tcl_precision
+ set ::tcl_precision 5
+} -body {
concat x[expr 1.123412341234]
-} {x1.1234}
-set tcl_precision 12
+} -cleanup {
+ set tcl_precision $old_precision
+} -result {x1.1234}
test util-6.5 {Tcl_PrintDouble - make sure there's a decimal point} {
concat x[expr 2.0]
} {x2.0}
-test util-6.6 {Tcl_PrintDouble - make sure there's a decimal point} {eformat} {
+test util-6.6 {Tcl_PrintDouble - make sure there's a decimal point} {
concat x[expr 3.0e98]
} {x3e+98}
-test util-7.1 {TclPrecTraceProc - unset callbacks} {
+test util-7.1 {TclPrecTraceProc - unset callbacks} -setup {
+ set old_precision $::tcl_precision
+} -body {
set tcl_precision 7
set x $tcl_precision
unset tcl_precision
list $x $tcl_precision
-} {7 7}
-test util-7.2 {TclPrecTraceProc - read traces, sharing among interpreters} {
+} -cleanup {
+ set ::tcl_precision $old_precision
+} -result {7 7}
+test util-7.2 {TclPrecTraceProc - read traces, sharing among interpreters} -setup {
+ set old_precision $::tcl_precision
+} -body {
set tcl_precision 12
interp create child
set x [child eval set tcl_precision]
child eval {set tcl_precision 6}
interp delete child
list $x $tcl_precision
-} {12 6}
-test util-7.3 {TclPrecTraceProc - write traces, safe interpreters} {
+} -cleanup {
+ set ::tcl_precision $old_precision
+} -result {12 6}
+test util-7.3 {TclPrecTraceProc - write traces, safe interpreters} -setup {
+ set old_precision $::tcl_precision
+} -body {
set tcl_precision 12
interp create -safe child
set x [child eval {
@@ -281,13 +449,17 @@ test util-7.3 {TclPrecTraceProc - write traces, safe interpreters} {
}]
interp delete child
list $x $tcl_precision
-} {{1 {can't set "tcl_precision": can't modify precision from a safe interpreter}} 12}
-test util-7.4 {TclPrecTraceProc - write traces, bogus values} {
+} -cleanup {
+ set ::tcl_precision $old_precision
+} -result {{1 {can't set "tcl_precision": can't modify precision from a safe interpreter}} 12}
+test util-7.4 {TclPrecTraceProc - write traces, bogus values} -setup {
+ set old_precision $::tcl_precision
+} -body {
set tcl_precision 12
list [catch {set tcl_precision abc} msg] $msg $tcl_precision
-} {1 {can't set "tcl_precision": improper value for precision} 12}
-
-set tcl_precision 12
+} -cleanup {
+ set ::tcl_precision $old_precision
+} -result {1 {can't set "tcl_precision": improper value for precision} 12}
# This test always succeeded in the C locale anyway...
test util-8.1 {TclNeedSpace - correct UTF8 handling} {
@@ -304,9 +476,6 @@ test util-8.1 {TclNeedSpace - correct UTF8 handling} {
interp delete \u5420
set result
} "\u5420 foo"
-
-tcltest::testConstraint testdstring [expr {[info commands testdstring] != {}}]
-
test util-8.2 {TclNeedSpace - correct UTF8 handling} testdstring {
# Bug 411825
# This tests the same bug as the previous test, but
@@ -353,6 +522,3377 @@ test util-8.6 {TclNeedSpace - correct UTF8 handling} testdstring {
list [llength [testdstring get]] [string length [testdstring get]]
} {2 9}
+test util-9.0.0 {TclGetIntForIndex} {
+ string index abcd 0
+} a
+test util-9.0.1 {TclGetIntForIndex} {
+ string index abcd 0x0
+} a
+test util-9.0.2 {TclGetIntForIndex} {
+ string index abcd -0x0
+} a
+test util-9.0.3 {TclGetIntForIndex} {
+ string index abcd { 0 }
+} a
+test util-9.0.4 {TclGetIntForIndex} {
+ string index abcd { 0x0 }
+} a
+test util-9.0.5 {TclGetIntForIndex} {
+ string index abcd { -0x0 }
+} a
+test util-9.0.6 {TclGetIntForIndex} {
+ string index abcd 01
+} b
+test util-9.0.7 {TclGetIntForIndex} {
+ string index abcd { 01 }
+} b
+test util-9.1.0 {TclGetIntForIndex} {
+ string index abcd 3
+} d
+test util-9.1.1 {TclGetIntForIndex} {
+ string index abcd { 3 }
+} d
+test util-9.1.2 {TclGetIntForIndex} {
+ string index abcdefghijk 0xa
+} k
+test util-9.1.3 {TclGetIntForIndex} {
+ string index abcdefghijk { 0xa }
+} k
+test util-9.2.0 {TclGetIntForIndex} {
+ string index abcd end
+} d
+test util-9.2.1 {TclGetIntForIndex} -body {
+ string index abcd { end}
+} -returnCodes error -match glob -result *
+test util-9.2.2 {TclGetIntForIndex} -body {
+ string index abcd {end }
+} -returnCodes error -match glob -result *
+test util-9.3 {TclGetIntForIndex} {
+ # Deprecated
+ string index abcd en
+} d
+test util-9.4 {TclGetIntForIndex} {
+ # Deprecated
+ string index abcd e
+} d
+test util-9.5.0 {TclGetIntForIndex} {
+ string index abcd end-1
+} c
+test util-9.5.1 {TclGetIntForIndex} {
+ string index abcd {end-1 }
+} c
+test util-9.5.2 {TclGetIntForIndex} -body {
+ string index abcd { end-1}
+} -returnCodes error -match glob -result *
+test util-9.6 {TclGetIntForIndex} {
+ string index abcd end+-1
+} c
+test util-9.7 {TclGetIntForIndex} {
+ string index abcd end+1
+} {}
+test util-9.8 {TclGetIntForIndex} {
+ string index abcd end--1
+} {}
+test util-9.9.0 {TclGetIntForIndex} {
+ string index abcd 0+0
+} a
+test util-9.9.1 {TclGetIntForIndex} {
+ string index abcd { 0+0 }
+} a
+test util-9.10 {TclGetIntForIndex} {
+ string index abcd 0-0
+} a
+test util-9.11 {TclGetIntForIndex} {
+ string index abcd 1+0
+} b
+test util-9.12 {TclGetIntForIndex} {
+ string index abcd 1-0
+} b
+test util-9.13 {TclGetIntForIndex} {
+ string index abcd 1+1
+} c
+test util-9.14 {TclGetIntForIndex} {
+ string index abcd 1-1
+} a
+test util-9.15 {TclGetIntForIndex} {
+ string index abcd -1+2
+} b
+test util-9.16 {TclGetIntForIndex} {
+ string index abcd -1--2
+} b
+test util-9.17 {TclGetIntForIndex} {
+ string index abcd { -1+2 }
+} b
+test util-9.18 {TclGetIntForIndex} {
+ string index abcd { -1--2 }
+} b
+test util-9.19 {TclGetIntForIndex} -body {
+ string index a {}
+} -returnCodes error -match glob -result *
+test util-9.20 {TclGetIntForIndex} -body {
+ string index a { }
+} -returnCodes error -match glob -result *
+test util-9.21 {TclGetIntForIndex} -body {
+ string index a " \r\t\n"
+} -returnCodes error -match glob -result *
+test util-9.22 {TclGetIntForIndex} -body {
+ string index a +
+} -returnCodes error -match glob -result *
+test util-9.23 {TclGetIntForIndex} -body {
+ string index a -
+} -returnCodes error -match glob -result *
+test util-9.24 {TclGetIntForIndex} -body {
+ string index a x
+} -returnCodes error -match glob -result *
+test util-9.25 {TclGetIntForIndex} -body {
+ string index a +x
+} -returnCodes error -match glob -result *
+test util-9.26 {TclGetIntForIndex} -body {
+ string index a -x
+} -returnCodes error -match glob -result *
+test util-9.27 {TclGetIntForIndex} -body {
+ string index a 0y
+} -returnCodes error -match glob -result *
+test util-9.28 {TclGetIntForIndex} -body {
+ string index a 1*
+} -returnCodes error -match glob -result *
+test util-9.29 {TclGetIntForIndex} -body {
+ string index a 0+
+} -returnCodes error -match glob -result *
+test util-9.30 {TclGetIntForIndex} -body {
+ string index a {0+ }
+} -returnCodes error -match glob -result *
+test util-9.31 {TclGetIntForIndex} -body {
+ string index a 0x
+} -returnCodes error -match glob -result *
+test util-9.32 {TclGetIntForIndex} -body {
+ string index a 0x1FFFFFFFF+0
+} -returnCodes error -match glob -result *
+test util-9.33 {TclGetIntForIndex} -body {
+ string index a 100000000000+0
+} -returnCodes error -match glob -result *
+test util-9.34 {TclGetIntForIndex} -body {
+ string index a 1.0
+} -returnCodes error -match glob -result *
+test util-9.35 {TclGetIntForIndex} -body {
+ string index a 1e23
+} -returnCodes error -match glob -result *
+test util-9.36 {TclGetIntForIndex} -body {
+ string index a 1.5e2
+} -returnCodes error -match glob -result *
+test util-9.37 {TclGetIntForIndex} -body {
+ string index a 0+x
+} -returnCodes error -match glob -result *
+test util-9.38 {TclGetIntForIndex} -body {
+ string index a 0+0x
+} -returnCodes error -match glob -result *
+test util-9.39 {TclGetIntForIndex} -body {
+ string index a 0+0xg
+} -returnCodes error -match glob -result *
+test util-9.40 {TclGetIntForIndex} -body {
+ string index a 0+0xg
+} -returnCodes error -match glob -result *
+test util-9.41 {TclGetIntForIndex} -body {
+ string index a 0+1.0
+} -returnCodes error -match glob -result *
+test util-9.42 {TclGetIntForIndex} -body {
+ string index a 0+1e2
+} -returnCodes error -match glob -result *
+test util-9.43 {TclGetIntForIndex} -body {
+ string index a 0+1.5e1
+} -returnCodes error -match glob -result *
+test util-9.44 {TclGetIntForIndex} -body {
+ string index a 0+1000000000000
+} -returnCodes error -match glob -result *
+
+test util-10.1 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x0000000000000000
+} {0.0}
+test util-10.2 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x8000000000000000
+} {-0.0}
+test util-10.3 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x7ef754e31cd072da
+} {4e+303}
+test util-10.4 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xd08afcef51f0fb5f
+} {-1e+80}
+test util-10.5 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x7ed754e31cd072da
+} {1e+303}
+test util-10.6 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xfee754e31cd072da
+} {-2e+303}
+test util-10.7 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x0afe07b27dd78b14
+} {1e-255}
+test util-10.8 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x93ae29e9c56687fe
+} {-7e-214}
+test util-10.9 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x376be03d0bf225c7
+} {1e-41}
+test util-10.10 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xa0ca2fe76a3f9475
+} {-1e-150}
+test util-10.11 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x7fa9a2028368022e
+} {9e+306}
+test util-10.12 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xdfc317e5ef3ab327
+} {-2e+153}
+test util-10.13 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x5fd317e5ef3ab327
+} {4e+153}
+test util-10.14 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xdfe317e5ef3ab327
+} {-8e+153}
+test util-10.15 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x00feb8e84fa0b278
+} {7e-304}
+test util-10.16 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x8133339131c46f8b
+} {-7e-303}
+test util-10.17 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x35dc0f92a6276c9d
+} {3e-49}
+test util-10.18 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xa445ce1f143d7ad2
+} {-6e-134}
+test util-10.19 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x2d2c0794d9d40e96
+} {4.3e-91}
+test util-10.20 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xad3c0794d9d40e96
+} {-8.6e-91}
+test util-10.21 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x30ecd5bee57763e6
+} {5.1e-73}
+test util-10.22 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x68ad1c26db7d0dae
+} {1.7e+196}
+test util-10.23 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xbfa3f7ced916872b
+} {-0.039}
+test util-10.24 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x64b7d93193f78fc6
+} {1.51e+177}
+test util-10.25 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x98ea82a1631eeb30
+} {-1.19e-188}
+test util-10.26 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xd216c309024bab4b
+} {-2.83e+87}
+test util-10.27 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x0dfdbbac6f83a821
+} {2.7869147e-241}
+test util-10.28 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xdadc569e968e0944
+} {-4.91080654e+129}
+test util-10.29 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x5acc569e968e0944
+} {2.45540327e+129}
+test util-10.30 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xab5fc575867314ee
+} {-9.078555839e-100}
+test util-10.31 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xdabc569e968e0944
+} {-1.227701635e+129}
+test util-10.32 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x2b6fc575867314ee
+} {1.8157111678e-99}
+test util-10.33 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xb3b8bf7e7fa6f02a
+} {-1.5400733123779e-59}
+test util-10.34 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xcd83de005bd620df
+} {-2.6153245263757307e+65}
+test util-10.35 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x6cdf92bacb3cb40c
+} {2.7210404151224248e+216}
+test util-10.36 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xecef92bacb3cb40c
+} {-5.4420808302448496e+216}
+test util-10.37 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x49342dbf25096cf5
+} {4.5e+44}
+test util-10.38 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xd06afcef51f0fb5f
+} {-2.5e+79}
+test util-10.39 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x49002498ea6df0c4
+} {4.5e+43}
+test util-10.40 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xfeb754e31cd072da
+} {-2.5e+302}
+test util-10.41 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x1d22deac01e2b4f7
+} {2.5e-168}
+test util-10.42 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xaccb1df536c13eee
+} {-6.5e-93}
+test util-10.43 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x3650711fed5b19a4
+} {4.5e-47}
+test util-10.44 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xb6848d67e8b1e00d
+} {-4.5e-46}
+test util-10.45 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x4bac8c574c0c6be7
+} {3.5e+56}
+test util-10.46 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xccd756183c147514
+} {-1.5e+62}
+test util-10.47 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x4ca2ab469676c410
+} {1.5e+61}
+test util-10.48 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xcf5539684e774b48
+} {-1.5e+74}
+test util-10.49 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x2e12e5f5dfa4fe9d
+} {9.5e-87}
+test util-10.50 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x8b9bdc2417bf7787
+} {-9.5e-253}
+test util-10.51 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x00eeb8e84fa0b278
+} {3.5e-304}
+test util-10.52 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xadde3cbc9907fdc8
+} {-9.5e-88}
+test util-10.53 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x2bb0ad836f269a17
+} {3.05e-98}
+test util-10.54 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x950b39ae1909c31b
+} {-2.65e-207}
+test util-10.55 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x1bfb2ab18615fcc6
+} {6.865e-174}
+test util-10.56 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x98f3e1f90a573064
+} {-1.785e-188}
+test util-10.57 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x5206c309024bab4b
+} {1.415e+87}
+test util-10.58 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xcc059bd3ad46e346
+} {-1.6955e+58}
+test util-10.59 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x47bdf4170f0fdecc
+} {3.9815e+37}
+test util-10.60 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x59e7e1e0f1c7a4ac
+} {1.263005e+125}
+test util-10.61 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xda1dda592e398dd7
+} {-1.263005e+126}
+test util-10.62 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xdc4e597c0b94b7ae
+} {-4.4118455e+136}
+test util-10.63 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x5aac569e968e0944
+} {6.138508175e+128}
+test util-10.64 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xdabc569e968e0944
+} {-1.227701635e+129}
+test util-10.65 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x6ce7ae0c186d8709
+} {4.081560622683637e+216}
+test util-10.66 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x44b52d02c7e14af7
+} {1.0000000000000001e+23}
+test util-10.67 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xc589d971e4fe8402
+} {-1e+27}
+test util-10.68 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x4599d971e4fe8402
+} {2e+27}
+test util-10.69 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xc5a9d971e4fe8402
+} {-4e+27}
+test util-10.70 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x3e45798ee2308c3a
+} {1e-8}
+test util-10.71 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xbe55798ee2308c3a
+} {-2e-8}
+test util-10.72 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x3e65798ee2308c3a
+} {4e-8}
+test util-10.73 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xbabef2d0f5da7dd9
+} {-1e-25}
+test util-10.74 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x44da784379d99db4
+} {5e+23}
+test util-10.75 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xc4fa784379d99db4
+} {-2e+24}
+test util-10.76 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x4503da329b633647
+} {3e+24}
+test util-10.77 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xc54cf389cd46047d
+} {-7e+25}
+test util-10.78 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x3fc999999999999a
+} {0.2}
+test util-10.79 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xbfd3333333333333
+} {-0.3}
+test util-10.80 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x3cf6849b86a12b9b
+} {5e-15}
+test util-10.81 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xbd16849b86a12b9b
+} {-2e-14}
+test util-10.82 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x3b87ccfc73126788
+} {6.3e-22}
+test util-10.83 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xbbbdc03b8fd7016a
+} {-6.3e-21}
+test util-10.84 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x3fa3f7ced916872b
+} {0.039}
+test util-10.85 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x460b297cad9f70b6
+} {2.69e+29}
+test util-10.86 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xc61b297cad9f70b6
+} {-5.38e+29}
+test util-10.87 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x3adcdc06b20ef183
+} {3.73e-25}
+test util-10.88 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x45fb297cad9f70b6
+} {1.345e+29}
+test util-10.89 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xc60b297cad9f70b6
+} {-2.69e+29}
+test util-10.90 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xbc050a246ecd44f3
+} {-1.4257e-19}
+test util-10.91 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xbec19b96f36ec68b
+} {-2.09901e-6}
+test util-10.92 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x3dcc06d366394441
+} {5.0980203373e-11}
+test util-10.93 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xc79f58ac4db68c90
+} {-1.04166211811e+37}
+test util-10.94 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x4569d971e4fe8402
+} {2.5e+26}
+test util-10.95 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xc50dc74be914d16b
+} {-4.5e+24}
+test util-10.96 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x4534adf4b7320335
+} {2.5e+25}
+test util-10.97 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xc54ae22487c1042b
+} {-6.5e+25}
+test util-10.98 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x3c987fe49aab41e0
+} {8.5e-17}
+test util-10.99 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xbc2f5c05e4b23fd7
+} {-8.5e-19}
+test util-10.100 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x3d5faa7ab552a552
+} {4.5e-13}
+test util-10.101 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xbdbb7cdfd9d7bdbb
+} {-2.5e-11}
+test util-10.102 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x44f3da329b633647
+} {1.5e+24}
+test util-10.103 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xc53cf389cd46047d
+} {-3.5e+25}
+test util-10.104 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x454f04ef12cb04cf
+} {7.5e+25}
+test util-10.105 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xc55f04ef12cb04cf
+} {-1.5e+26}
+test util-10.106 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x3fc3333333333333
+} {0.15}
+test util-10.107 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xbdb07e1fe91b0b70
+} {-1.5e-11}
+test util-10.108 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x3de49da7e361ce4c
+} {1.5e-10}
+test util-10.109 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xbe19c511dc3a41df
+} {-1.5e-9}
+test util-10.110 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xc5caa83d74267822
+} {-1.65e+28}
+test util-10.111 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x4588f1d5969453de
+} {9.65e+26}
+test util-10.112 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x3b91d9bd564dcda6
+} {9.45e-22}
+test util-10.113 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xbcfa58973ecbede6
+} {-5.85e-15}
+test util-10.114 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x45eb297cad9f70b6
+} {6.725e+28}
+test util-10.115 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xc5fb297cad9f70b6
+} {-1.345e+29}
+test util-10.116 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x3accdc06b20ef183
+} {1.865e-25}
+test util-10.117 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xbd036071dcae4565
+} {-8.605e-15}
+test util-10.118 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x462cb968d297dde8
+} {1.137885e+30}
+test util-10.119 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0xc661f3e1839eeab1
+} {-1.137885e+31}
+test util-10.120 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x474e9cec176c96f8
+} {3.179033335e+35}
+test util-10.121 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x3dbc06d366394441
+} {2.54901016865e-11}
+test util-10.122 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
+ convertDouble 0x478f58ac4db68c90
+} {5.20831059055e+36}
+
+test util-11.1 {Tcl_PrintDouble - scaling} {
+ expr 1.1e-5
+} {1.1e-5}
+test util-11.2 {Tcl_PrintDouble - scaling} {
+ expr 1.1e-4
+} {0.00011}
+test util-11.3 {Tcl_PrintDouble - scaling} {
+ expr 1.1e-3
+} {0.0011}
+test util-11.4 {Tcl_PrintDouble - scaling} {
+ expr 1.1e-2
+} {0.011}
+test util-11.5 {Tcl_PrintDouble - scaling} {
+ expr 1.1e-1
+} {0.11}
+test util-11.6 {Tcl_PrintDouble - scaling} {
+ expr 1.1e0
+} {1.1}
+test util-11.7 {Tcl_PrintDouble - scaling} {
+ expr 1.1e1
+} {11.0}
+test util-11.8 {Tcl_PrintDouble - scaling} {
+ expr 1.1e2
+} {110.0}
+test util-11.9 {Tcl_PrintDouble - scaling} {
+ expr 1.1e3
+} {1100.0}
+test util-11.10 {Tcl_PrintDouble - scaling} {
+ expr 1.1e4
+} {11000.0}
+test util-11.11 {Tcl_PrintDouble - scaling} {
+ expr 1.1e5
+} {110000.0}
+test util-11.12 {Tcl_PrintDouble - scaling} {
+ expr 1.1e6
+} {1100000.0}
+test util-11.13 {Tcl_PrintDouble - scaling} {
+ expr 1.1e7
+} {11000000.0}
+test util-11.14 {Tcl_PrintDouble - scaling} {
+ expr 1.1e8
+} {110000000.0}
+test util-11.15 {Tcl_PrintDouble - scaling} {
+ expr 1.1e9
+} {1100000000.0}
+test util-11.16 {Tcl_PrintDouble - scaling} {
+ expr 1.1e10
+} {11000000000.0}
+test util-11.17 {Tcl_PrintDouble - scaling} {
+ expr 1.1e11
+} {110000000000.0}
+test util-11.18 {Tcl_PrintDouble - scaling} {
+ expr 1.1e12
+} {1100000000000.0}
+test util-11.19 {Tcl_PrintDouble - scaling} {
+ expr 1.1e13
+} {11000000000000.0}
+test util-11.20 {Tcl_PrintDouble - scaling} {
+ expr 1.1e14
+} {110000000000000.0}
+test util-11.21 {Tcl_PrintDouble - scaling} {
+ expr 1.1e15
+} {1100000000000000.0}
+test util-11.22 {Tcl_PrintDouble - scaling} {
+ expr 1.1e16
+} {11000000000000000.0}
+test util-11.23 {Tcl_PrintDouble - scaling} {
+ expr 1.1e17
+} {1.1e+17}
+
+test util-12.1 {Tcl_DoubleDigits - Inf} ieeeFloatingPoint {
+ testdoubledigits Inf -1 shortest
+} {Infinity 9999 +}
+test util-12.2 {Tcl_DoubleDigits - -Inf} ieeeFloatingPoint {
+ testdoubledigits -Inf -1 shortest
+} {Infinity 9999 -}
+test util-12.3 {Tcl_DoubleDigits - NaN} ieeeFloatingPoint {
+ testdoubledigits $ieeeValues(NaN) -1 shortest
+} {NaN 9999 +}
+test util-12.4 {Tcl_DoubleDigits - NaN} ieeeFloatingPoint {
+ testdoubledigits -NaN -1 shortest
+} {NaN 9999 -}
+test util-12.5 {Tcl_DoubleDigits - 0} {
+ testdoubledigits 0.0 -1 shortest
+} {0 0 +}
+test util-12.6 {Tcl_DoubleDigits - -0} {
+ testdoubledigits -0.0 -1 shortest
+} {0 0 -}
+
+# Verdonk test vectors
+
+test util-13.1 {just over exact - 1 digits} {*}{
+ -body {
+ verdonk_test 1754e31cd072da E+1008 +4_000000000000000000& E+303
+ }
+ -result {}
+}
+test util-13.2 {just over exact - 1 digits} {*}{
+ -body {
+ verdonk_test -1afcef51f0fb5f E+265 -1_000000000000000000& E+80
+ }
+ -result {}
+}
+test util-13.3 {just over exact - 1 digits} {*}{
+ -body {
+ verdonk_test 1754e31cd072da E+1006 +1_000000000000000000& E+303
+ }
+ -result {}
+}
+test util-13.4 {just over exact - 1 digits} {*}{
+ -body {
+ verdonk_test -1754e31cd072da E+1007 -2_000000000000000000& E+303
+ }
+ -result {}
+}
+test util-13.5 {just over exact - 1 digits} {*}{
+ -body {
+ verdonk_test 1e07b27dd78b14 E-848 +1_00000000000000000& E-255
+ }
+ -result {}
+}
+test util-13.6 {just over exact - 1 digits} {*}{
+ -body {
+ verdonk_test -1e29e9c56687fe E-709 -7_00000000000000000& E-214
+ }
+ -result {}
+}
+test util-13.7 {just over exact - 1 digits} {*}{
+ -body {
+ verdonk_test 1be03d0bf225c7 E-137 +1_00000000000000000& E-41
+ }
+ -result {}
+}
+test util-13.8 {just over exact - 1 digits} {*}{
+ -body {
+ verdonk_test -1a2fe76a3f9475 E-499 -1_00000000000000000& E-150
+ }
+ -result {}
+}
+test util-13.9 {just under exact - 1 digits} {*}{
+ -body {
+ verdonk_test 19a2028368022e E+1019 +8_999999999999999999& E+306
+ }
+ -result {}
+}
+test util-13.10 {just under exact - 1 digits} {*}{
+ -body {
+ verdonk_test -1317e5ef3ab327 E+509 -1_999999999999999999& E+153
+ }
+ -result {}
+}
+test util-13.11 {just under exact - 1 digits} {*}{
+ -body {
+ verdonk_test 1317e5ef3ab327 E+510 +3_99999999999999999& E+153
+ }
+ -result {}
+}
+test util-13.12 {just under exact - 1 digits} {*}{
+ -body {
+ verdonk_test -1317e5ef3ab327 E+511 -7_99999999999999999& E+153
+ }
+ -result {}
+}
+test util-13.13 {just under exact - 1 digits} {*}{
+ -body {
+ verdonk_test 1eb8e84fa0b278 E-1008 +6_999999999999999999& E-304
+ }
+ -result {}
+}
+test util-13.14 {just under exact - 1 digits} {*}{
+ -body {
+ verdonk_test -13339131c46f8b E-1004 -6_999999999999999999& E-303
+ }
+ -result {}
+}
+test util-13.15 {just under exact - 1 digits} {*}{
+ -body {
+ verdonk_test 1c0f92a6276c9d E-162 +2_999999999999999999& E-49
+ }
+ -result {}
+}
+test util-13.16 {just under exact - 1 digits} {*}{
+ -body {
+ verdonk_test -15ce1f143d7ad2 E-443 -5_99999999999999999& E-134
+ }
+ -result {}
+}
+test util-13.17 {just over exact - 2 digits} {*}{
+ -body {
+ verdonk_test 1c0794d9d40e96 E-301 +43_000000000000000000& E-92
+ }
+ -result {}
+}
+test util-13.18 {just over exact - 2 digits} {*}{
+ -body {
+ verdonk_test -1c0794d9d40e96 E-300 -86_000000000000000000& E-92
+ }
+ -result {}
+}
+test util-13.19 {just over exact - 2 digits} {*}{
+ -body {
+ verdonk_test 1cd5bee57763e6 E-241 +51_000000000000000000& E-74
+ }
+ -result {}
+}
+test util-13.20 {just under exact - 2 digits} {*}{
+ -body {
+ verdonk_test 1d1c26db7d0dae E+651 +16_999999999999999999& E+195
+ }
+ -result {}
+}
+test util-13.21 {just under exact - 2 digits} {*}{
+ -body {
+ verdonk_test -13f7ced916872b E-5 -38_999999999999999999& E-3
+ }
+ -result {}
+}
+test util-13.22 {just over exact - 3 digits} {*}{
+ -body {
+ verdonk_test 17d93193f78fc6 E+588 +151_0000000000000000000& E+175
+ }
+ -result {}
+}
+test util-13.23 {just over exact - 3 digits} {*}{
+ -body {
+ verdonk_test -1a82a1631eeb30 E-625 -119_000000000000000000& E-190
+ }
+ -result {}
+}
+test util-13.24 {just under exact - 3 digits} {*}{
+ -body {
+ verdonk_test -16c309024bab4b E+290 -282_999999999999999999& E+85
+ }
+ -result {}
+}
+test util-13.25 {just over exact - 8 digits} {*}{
+ -body {
+ verdonk_test 1dbbac6f83a821 E-800 +27869147_0000000000000000000& E-248
+ }
+ -result {}
+}
+test util-13.26 {just under exact - 9 digits} {*}{
+ -body {
+ verdonk_test -1c569e968e0944 E+430 -491080653_9999999999999999999& E+121
+ }
+ -result {}
+}
+test util-13.27 {just under exact - 9 digits} {*}{
+ -body {
+ verdonk_test 1c569e968e0944 E+429 +245540326_9999999999999999999& E+121
+ }
+ -result {}
+}
+test util-13.28 {just over exact - 10 digits} {*}{
+ -body {
+ verdonk_test -1fc575867314ee E-330 -9078555839_0000000000000000000& E-109
+ }
+ -result {}
+}
+test util-13.29 {just under exact - 10 digits} {*}{
+ -body {
+ verdonk_test -1c569e968e0944 E+428 -1227701634_9999999999999999999& E+120
+ }
+ -result {}
+}
+test util-13.30 {just over exact - 11 digits} {*}{
+ -body {
+ verdonk_test 1fc575867314ee E-329 +18157111678_0000000000000000000& E-109
+ }
+ -result {}
+}
+test util-13.31 {just over exact - 14 digits} {*}{
+ -body {
+ verdonk_test -18bf7e7fa6f02a E-196 -15400733123779_0000000000000000000& E-72
+ }
+ -result {}
+}
+test util-13.32 {just over exact - 17 digits} {*}{
+ -body {
+ verdonk_test -13de005bd620df E+217 -26153245263757307_0000000000000000000& E+49
+ }
+ -result {}
+}
+test util-13.33 {just over exact - 18 digits} {*}{
+ -body {
+ verdonk_test 1f92bacb3cb40c E+718 +272104041512242479_0000000000000000000& E+199
+ }
+ -result {}
+}
+test util-13.34 {just over exact - 18 digits} {*}{
+ -body {
+ verdonk_test -1f92bacb3cb40c E+719 -544208083024484958_0000000000000000000& E+199
+ }
+ -result {}
+}
+test util-13.35 {just over half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test 142dbf25096cf5 E+148 +4_500000000000000000& E+44
+ }
+ -result {}
+}
+test util-13.36 {just over half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test -1afcef51f0fb5f E+263 -2_500000000000000000& E+79
+ }
+ -result {}
+}
+test util-13.37 {just over half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test 102498ea6df0c4 E+145 +4_500000000000000000& E+43
+ }
+ -result {}
+}
+test util-13.38 {just over half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test -1754e31cd072da E+1004 -2_500000000000000000& E+302
+ }
+ -result {}
+}
+test util-13.39 {just over half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test 12deac01e2b4f7 E-557 +2_50000000000000000& E-168
+ }
+ -result {}
+}
+test util-13.40 {just over half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test -1b1df536c13eee E-307 -6_50000000000000000& E-93
+ }
+ -result {}
+}
+test util-13.41 {just over half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test 10711fed5b19a4 E-154 +4_50000000000000000& E-47
+ }
+ -result {}
+}
+test util-13.42 {just over half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test -148d67e8b1e00d E-151 -4_50000000000000000& E-46
+ }
+ -result {}
+}
+test util-13.43 {just under half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test 1c8c574c0c6be7 E+187 +3_49999999999999999& E+56
+ }
+ -result {}
+}
+test util-13.44 {just under half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test -1756183c147514 E+206 -1_49999999999999999& E+62
+ }
+ -result {}
+}
+test util-13.45 {just under half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test 12ab469676c410 E+203 +1_49999999999999999& E+61
+ }
+ -result {}
+}
+test util-13.46 {just under half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test -1539684e774b48 E+246 -1_49999999999999999& E+74
+ }
+ -result {}
+}
+test util-13.47 {just under half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test 12e5f5dfa4fe9d E-286 +9_499999999999999999& E-87
+ }
+ -result {}
+}
+test util-13.48 {just under half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test -1bdc2417bf7787 E-838 -9_499999999999999999& E-253
+ }
+ -result {}
+}
+test util-13.49 {just under half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test 1eb8e84fa0b278 E-1009 +3_499999999999999999& E-304
+ }
+ -result {}
+}
+test util-13.50 {just under half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test -1e3cbc9907fdc8 E-290 -9_499999999999999999& E-88
+ }
+ -result {}
+}
+test util-13.51 {just over half ulp - 2 digits} {*}{
+ -body {
+ verdonk_test 10ad836f269a17 E-324 +30_500000000000000000& E-99
+ }
+ -result {}
+}
+test util-13.52 {just over half ulp - 2 digits} {*}{
+ -body {
+ verdonk_test -1b39ae1909c31b E-687 -26_500000000000000000& E-208
+ }
+ -result {}
+}
+test util-13.53 {just over half ulp - 3 digits} {*}{
+ -body {
+ verdonk_test 1b2ab18615fcc6 E-576 +686_500000000000000000& E-176
+ }
+ -result {}
+}
+test util-13.54 {just over half ulp - 3 digits} {*}{
+ -body {
+ verdonk_test -13e1f90a573064 E-624 -178_500000000000000000& E-190
+ }
+ -result {}
+}
+test util-13.55 {just under half ulp - 3 digits} {*}{
+ -body {
+ verdonk_test 16c309024bab4b E+289 +141_499999999999999999& E+85
+ }
+ -result {}
+}
+test util-13.56 {just under half ulp - 4 digits} {*}{
+ -body {
+ verdonk_test -159bd3ad46e346 E+193 -1695_499999999999999999& E+55
+ }
+ -result {}
+}
+test util-13.57 {just under half ulp - 4 digits} {*}{
+ -body {
+ verdonk_test 1df4170f0fdecc E+124 +3981_499999999999999999& E+34
+ }
+ -result {}
+}
+test util-13.58 {just over half ulp - 6 digits} {*}{
+ -body {
+ verdonk_test 17e1e0f1c7a4ac E+415 +126300_5000000000000000000& E+120
+ }
+ -result {}
+}
+test util-13.59 {just over half ulp - 6 digits} {*}{
+ -body {
+ verdonk_test -1dda592e398dd7 E+418 -126300_5000000000000000000& E+121
+ }
+ -result {}
+}
+test util-13.60 {just under half ulp - 7 digits} {*}{
+ -body {
+ verdonk_test -1e597c0b94b7ae E+453 -4411845_499999999999999999& E+130
+ }
+ -result {}
+}
+test util-13.61 {just under half ulp - 9 digits} {*}{
+ -body {
+ verdonk_test 1c569e968e0944 E+427 +613850817_4999999999999999999& E+120
+ }
+ -result {}
+}
+test util-13.62 {just under half ulp - 9 digits} {*}{
+ -body {
+ verdonk_test -1c569e968e0944 E+428 -122770163_49999999999999999999& E+121
+ }
+ -result {}
+}
+test util-13.63 {just over half ulp - 18 digits} {*}{
+ -body {
+ verdonk_test 17ae0c186d8709 E+719 +408156062268363718_5000000000000000000& E+199
+ }
+ -result {}
+}
+test util-13.64 {just over exact - 1 digits} {*}{
+ -body {
+ verdonk_test 152d02c7e14af7 E+76 +1_0000000000000000& E+23
+ }
+ -result {}
+}
+test util-13.65 {just over exact - 1 digits} {*}{
+ -body {
+ verdonk_test -19d971e4fe8402 E+89 -1_0000000000000000& E+27
+ }
+ -result {}
+}
+test util-13.66 {just over exact - 1 digits} {*}{
+ -body {
+ verdonk_test 19d971e4fe8402 E+90 +2_0000000000000000& E+27
+ }
+ -result {}
+}
+test util-13.67 {just over exact - 1 digits} {*}{
+ -body {
+ verdonk_test -19d971e4fe8402 E+91 -4_0000000000000000& E+27
+ }
+ -result {}
+}
+test util-13.68 {just over exact - 1 digits} {*}{
+ -body {
+ verdonk_test 15798ee2308c3a E-27 +1_0000000000000000& E-8
+ }
+ -result {}
+}
+test util-13.69 {just over exact - 1 digits} {*}{
+ -body {
+ verdonk_test -15798ee2308c3a E-26 -2_0000000000000000& E-8
+ }
+ -result {}
+}
+test util-13.70 {just over exact - 1 digits} {*}{
+ -body {
+ verdonk_test 15798ee2308c3a E-25 +4_0000000000000000& E-8
+ }
+ -result {}
+}
+test util-13.71 {just over exact - 1 digits} {*}{
+ -body {
+ verdonk_test -1ef2d0f5da7dd9 E-84 -1_0000000000000000& E-25
+ }
+ -result {}
+}
+test util-13.72 {just under exact - 1 digits} {*}{
+ -body {
+ verdonk_test 1a784379d99db4 E+78 +4_9999999999999999& E+23
+ }
+ -result {}
+}
+test util-13.73 {just under exact - 1 digits} {*}{
+ -body {
+ verdonk_test -1a784379d99db4 E+80 -1_9999999999999999& E+24
+ }
+ -result {}
+}
+test util-13.74 {just under exact - 1 digits} {*}{
+ -body {
+ verdonk_test 13da329b633647 E+81 +2_9999999999999999& E+24
+ }
+ -result {}
+}
+test util-13.75 {just under exact - 1 digits} {*}{
+ -body {
+ verdonk_test -1cf389cd46047d E+85 -6_9999999999999999& E+25
+ }
+ -result {}
+}
+test util-13.76 {just under exact - 1 digits} {*}{
+ -body {
+ verdonk_test 19999999999999 E-3 +1_99999999999999999& E-1
+ }
+ -result {}
+}
+test util-13.77 {just under exact - 1 digits} {*}{
+ -body {
+ verdonk_test -13333333333333 E-2 -2_99999999999999999& E-1
+ }
+ -result {}
+}
+test util-13.78 {just under exact - 1 digits} {*}{
+ -body {
+ verdonk_test 16849b86a12b9b E-48 +4_99999999999999999& E-15
+ }
+ -result {}
+}
+test util-13.79 {just under exact - 1 digits} {*}{
+ -body {
+ verdonk_test -16849b86a12b9b E-46 -1_99999999999999999& E-14
+ }
+ -result {}
+}
+test util-13.80 {just over exact - 2 digits} {*}{
+ -body {
+ verdonk_test 17ccfc73126788 E-71 +63_00000000000000000& E-23
+ }
+ -result {}
+}
+test util-13.81 {just over exact - 2 digits} {*}{
+ -body {
+ verdonk_test -1dc03b8fd7016a E-68 -63_00000000000000000& E-22
+ }
+ -result {}
+}
+test util-13.82 {just under exact - 2 digits} {*}{
+ -body {
+ verdonk_test 13f7ced916872b E-5 +38_999999999999999999& E-3
+ }
+ -result {}
+}
+test util-13.83 {just over exact - 3 digits} {*}{
+ -body {
+ verdonk_test 1b297cad9f70b6 E+97 +269_000000000000000000& E+27
+ }
+ -result {}
+}
+test util-13.84 {just over exact - 3 digits} {*}{
+ -body {
+ verdonk_test -1b297cad9f70b6 E+98 -538_00000000000000000& E+27
+ }
+ -result {}
+}
+test util-13.85 {just over exact - 3 digits} {*}{
+ -body {
+ verdonk_test 1cdc06b20ef183 E-82 +373_00000000000000000& E-27
+ }
+ -result {}
+}
+test util-13.86 {just over exact - 4 digits} {*}{
+ -body {
+ verdonk_test 1b297cad9f70b6 E+96 +1345_00000000000000000& E+26
+ }
+ -result {}
+}
+# this one is not 4 digits, it is 3, and it is covered above.
+test util-13.87 {just over exact - 4 digits} {*}{
+ -constraints knownBadTest
+ -body {
+ verdonk_test -1b297cad9f70b6 E+97 -2690_00000000000000000& E+26
+ }
+ -result {}
+}
+test util-13.88 {just over exact - 5 digits} {*}{
+ -body {
+ verdonk_test -150a246ecd44f3 E-63 -14257_00000000000000000& E-23
+ }
+ -result {}
+}
+test util-13.89 {just under exact - 6 digits} {*}{
+ -body {
+ verdonk_test -119b96f36ec68b E-19 -209900_999999999999999999& E-11
+ }
+ -result {}
+}
+test util-13.90 {just over exact - 11 digits} {*}{
+ -body {
+ verdonk_test 1c06d366394441 E-35 +50980203373_000000000000000000& E-21
+ }
+ -result {}
+}
+test util-13.91 {just under exact - 12 digits} {*}{
+ -body {
+ verdonk_test -1f58ac4db68c90 E+122 -104166211810_99999999999999999& E+26
+ }
+ -result {}
+}
+test util-13.92 {just over half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test 19d971e4fe8402 E+87 +2_5000000000000000& E+26
+ }
+ -result {}
+}
+test util-13.93 {just over half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test -1dc74be914d16b E+81 -4_500000000000000& E+24
+ }
+ -result {}
+}
+test util-13.94 {just over half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test 14adf4b7320335 E+84 +2_500000000000000& E+25
+ }
+ -result {}
+}
+test util-13.95 {just over half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test -1ae22487c1042b E+85 -6_5000000000000000& E+25
+ }
+ -result {}
+}
+test util-13.96 {just over half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test 187fe49aab41e0 E-54 +8_5000000000000000& E-17
+ }
+ -result {}
+}
+test util-13.97 {just over half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test -1f5c05e4b23fd7 E-61 -8_5000000000000000& E-19
+ }
+ -result {}
+}
+test util-13.98 {just over half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test 1faa7ab552a552 E-42 +4_5000000000000000& E-13
+ }
+ -result {}
+}
+test util-13.99 {just over half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test -1b7cdfd9d7bdbb E-36 -2_5000000000000000& E-11
+ }
+ -result {}
+}
+test util-13.100 {just under half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test 13da329b633647 E+80 +1_4999999999999999& E+24
+ }
+ -result {}
+}
+test util-13.101 {just under half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test -1cf389cd46047d E+84 -3_49999999999999999& E+25
+ }
+ -result {}
+}
+test util-13.102 {just under half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test 1f04ef12cb04cf E+85 +7_4999999999999999& E+25
+ }
+ -result {}
+}
+test util-13.103 {just under half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test -1f04ef12cb04cf E+86 -1_4999999999999999& E+26
+ }
+ -result {}
+}
+test util-13.104 {just under half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test 13333333333333 E-3 +1_49999999999999999& E-1
+ }
+ -result {}
+}
+test util-13.105 {just under half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test -107e1fe91b0b70 E-36 -1_49999999999999999& E-11
+ }
+ -result {}
+}
+test util-13.106 {just under half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test 149da7e361ce4c E-33 +1_49999999999999999& E-10
+ }
+ -result {}
+}
+test util-13.107 {just under half ulp - 1 digits} {*}{
+ -body {
+ verdonk_test -19c511dc3a41df E-30 -1_49999999999999999& E-9
+ }
+ -result {}
+}
+test util-13.108 {just over half ulp - 2 digits} {*}{
+ -body {
+ verdonk_test -1aa83d74267822 E+93 -16_5000000000000000& E+27
+ }
+ -result {}
+}
+test util-13.109 {just over half ulp - 2 digits} {*}{
+ -body {
+ verdonk_test 18f1d5969453de E+89 +96_5000000000000000& E+25
+ }
+ -result {}
+}
+test util-13.110 {just over half ulp - 2 digits} {*}{
+ -body {
+ verdonk_test 11d9bd564dcda6 E-70 +94_50000000000000000& E-23
+ }
+ -result {}
+}
+test util-13.111 {just over half ulp - 2 digits} {*}{
+ -body {
+ verdonk_test -1a58973ecbede6 E-48 -58_50000000000000000& E-16
+ }
+ -result {}
+}
+test util-13.112 {just over half ulp - 3 digits} {*}{
+ -body {
+ verdonk_test 1b297cad9f70b6 E+95 +672_50000000000000000& E+26
+ }
+ -result {}
+}
+test util-13.113 {just over half ulp - 3 digits} {*}{
+ -body {
+ verdonk_test -1b297cad9f70b6 E+96 -134_500000000000000000& E+27
+ }
+ -result {}
+}
+test util-13.114 {just over half ulp - 3 digits} {*}{
+ -body {
+ verdonk_test 1cdc06b20ef183 E-83 +186_50000000000000000& E-27
+ }
+ -result {}
+}
+test util-13.115 {just over half ulp - 3 digits} {*}{
+ -body {
+ verdonk_test -136071dcae4565 E-47 -860_50000000000000000& E-17
+ }
+ -result {}
+}
+test util-13.116 {just over half ulp - 6 digits} {*}{
+ -body {
+ verdonk_test 1cb968d297dde8 E+99 +113788_50000000000000000& E+25
+ }
+ -result {}
+}
+test util-13.117 {just over half ulp - 6 digits} {*}{
+ -body {
+ verdonk_test -11f3e1839eeab1 E+103 -113788_50000000000000000& E+26
+ }
+ -result {}
+}
+test util-13.118 {just under half ulp - 9 digits} {*}{
+ -body {
+ verdonk_test 1e9cec176c96f8 E+117 +317903333_49999999999999999& E+27
+ }
+ -result {}
+}
+test util-13.119 {just over half ulp - 11 digits} {*}{
+ -body {
+ verdonk_test 1c06d366394441 E-36 +25490101686_500000000000000000& E-21
+ }
+ -result {}
+}
+test util-13.120 {just under half ulp - 11 digits} {*}{
+ -body {
+ verdonk_test 1f58ac4db68c90 E+121 +52083105905_49999999999999999& E+26
+ }
+ -result {}
+}
+
+test util-14.1 {funky NaN} {*}{
+ -constraints ieeeFloatingPoint
+ -body {
+ set ieeeValues(-NaN)
+ }
+ -result -NaN
+}
+
+test util-14.2 {funky NaN} {*}{
+ -constraints ieeeFloatingPoint
+ -body {
+ set ieeeValues(-NaN(3456789abcdef))
+ }
+ -result -NaN(3456789abcdef)
+}
+
+test util-15.1 {largest subnormal} {*}{
+ -body {
+ binary scan [binary format w 0x000fffffffffffff] q x
+ set x
+ }
+ -result 2.225073858507201e-308
+ -cleanup {
+ unset x
+ }
+}
+
+test util-15.2 {largest subnormal} {*}{
+ -body {
+ binary scan [binary format w 0x800fffffffffffff] q x
+ set x
+ }
+ -result -2.225073858507201e-308
+ -cleanup {
+ unset x
+ }
+}
+
+test util-15.3 {largest subnormal} {*}{
+ -body {
+ binary scan [binary format q 2.225073858507201e-308] w x
+ format %#lx $x
+ }
+ -result 0xfffffffffffff
+ -cleanup {
+ unset x
+ }
+}
+
+test util-15.4 {largest subnormal} {*}{
+ -body {
+ binary scan [binary format q -2.225073858507201e-308] w x
+ format %#lx $x
+ }
+ -result 0x800fffffffffffff
+ -cleanup {
+ unset x
+ }
+}
+
+test util-15.5 {smallest normal} {*}{
+ -body {
+ binary scan [binary format w 0x0010000000000000] q x
+ set x
+ }
+ -result 2.2250738585072014e-308
+ -cleanup {
+ unset x
+ }
+}
+
+test util-15.6 {smallest normal} {*}{
+ -body {
+ binary scan [binary format w 0x8010000000000000] q x
+ set x
+ }
+ -result -2.2250738585072014e-308
+ -cleanup {
+ unset x
+ }
+}
+
+test util-15.7 {smallest normal} {*}{
+ -body {
+ binary scan [binary format q 2.2250738585072014e-308] w x
+ format %#lx $x
+ }
+ -result 0x10000000000000
+ -cleanup {
+ unset x
+ }
+}
+
+test util-15.8 {smallest normal} {*}{
+ -body {
+ binary scan [binary format q -2.2250738585072014e-308] w x
+ format %#lx $x
+ }
+ -result 0x8010000000000000
+ -cleanup {
+ unset x
+ }
+}
+
+set saved_precision $::tcl_precision
+foreach ::tcl_precision {0 12} {
+ for {set e -312} {$e < -9} {incr e} {
+ test util-16.1.$::tcl_precision.$e {shortening of numbers} \
+ "expr 1.1e$e" 1.1e$e
+ }
+}
+set tcl_precision 0
+for {set e -9} {$e < -4} {incr e} {
+ test util-16.1.$::tcl_precision.$e {shortening of numbers} \
+ "expr 1.1e$e" 1.1e$e
+}
+set tcl_precision 12
+for {set e -9} {$e < -4} {incr e} {
+ test util-16.1.$::tcl_precision.$e {8.4 compatible formatting of doubles} \
+ "expr 1.1e$e" 1.1e[format %+03d $e]
+}
+foreach ::tcl_precision {0 12} {
+ test util-16.1.$::tcl_precision.-4 {shortening of numbers} \
+ {expr 1.1e-4} \
+ 0.00011
+ test util-16.1.$::tcl_precision.-3 {shortening of numbers} \
+ {expr 1.1e-3} \
+ 0.0011
+ test util-16.1.$::tcl_precision.-2 {shortening of numbers} \
+ {expr 1.1e-2} \
+ 0.011
+ test util-16.1.$::tcl_precision.-1 {shortening of numbers} \
+ {expr 1.1e-1} \
+ 0.11
+ test util-16.1.$::tcl_precision.0 {shortening of numbers} \
+ {expr 1.1} \
+ 1.1
+ for {set e 1} {$e < 17} {incr e} {
+ test util-16.1.$::tcl_precision.$e {shortening of numbers} \
+ "expr 11[string repeat 0 [expr {$e-1}]].0" \
+ 11[string repeat 0 [expr {$e-1}]].0
+ }
+ for {set e 17} {$e < 309} {incr e} {
+ test util-16.1.$::tcl_precision.$e {shortening of numbers} \
+ "expr 1.1e$e" 1.1e+$e
+ }
+}
+set tcl_precision 17
+test util-16.1.17.-300 {8.4 compatible formatting of doubles} \
+ {expr 1e-300} \
+ 1e-300
+test util-16.1.17.-299 {8.4 compatible formatting of doubles} \
+ {expr 1e-299} \
+ 9.9999999999999999e-300
+test util-16.1.17.-298 {8.4 compatible formatting of doubles} \
+ {expr 1e-298} \
+ 9.9999999999999991e-299
+test util-16.1.17.-297 {8.4 compatible formatting of doubles} \
+ {expr 1e-297} \
+ 1e-297
+test util-16.1.17.-296 {8.4 compatible formatting of doubles} \
+ {expr 1e-296} \
+ 1e-296
+test util-16.1.17.-295 {8.4 compatible formatting of doubles} \
+ {expr 1e-295} \
+ 1.0000000000000001e-295
+test util-16.1.17.-294 {8.4 compatible formatting of doubles} \
+ {expr 1e-294} \
+ 1e-294
+test util-16.1.17.-293 {8.4 compatible formatting of doubles} \
+ {expr 1e-293} \
+ 1.0000000000000001e-293
+test util-16.1.17.-292 {8.4 compatible formatting of doubles} \
+ {expr 1e-292} \
+ 1.0000000000000001e-292
+test util-16.1.17.-291 {8.4 compatible formatting of doubles} \
+ {expr 1e-291} \
+ 9.9999999999999996e-292
+test util-16.1.17.-290 {8.4 compatible formatting of doubles} \
+ {expr 1e-290} \
+ 1.0000000000000001e-290
+test util-16.1.17.-289 {8.4 compatible formatting of doubles} \
+ {expr 1e-289} \
+ 1e-289
+test util-16.1.17.-288 {8.4 compatible formatting of doubles} \
+ {expr 1e-288} \
+ 1.0000000000000001e-288
+test util-16.1.17.-287 {8.4 compatible formatting of doubles} \
+ {expr 1e-287} \
+ 1e-287
+test util-16.1.17.-286 {8.4 compatible formatting of doubles} \
+ {expr 1e-286} \
+ 1.0000000000000001e-286
+test util-16.1.17.-285 {8.4 compatible formatting of doubles} \
+ {expr 1e-285} \
+ 1.0000000000000001e-285
+test util-16.1.17.-284 {8.4 compatible formatting of doubles} \
+ {expr 1e-284} \
+ 1e-284
+test util-16.1.17.-283 {8.4 compatible formatting of doubles} \
+ {expr 1e-283} \
+ 9.9999999999999995e-284
+test util-16.1.17.-282 {8.4 compatible formatting of doubles} \
+ {expr 1e-282} \
+ 1e-282
+test util-16.1.17.-281 {8.4 compatible formatting of doubles} \
+ {expr 1e-281} \
+ 1e-281
+test util-16.1.17.-280 {8.4 compatible formatting of doubles} \
+ {expr 1e-280} \
+ 9.9999999999999996e-281
+test util-16.1.17.-279 {8.4 compatible formatting of doubles} \
+ {expr 1e-279} \
+ 1.0000000000000001e-279
+test util-16.1.17.-278 {8.4 compatible formatting of doubles} \
+ {expr 1e-278} \
+ 9.9999999999999994e-279
+test util-16.1.17.-277 {8.4 compatible formatting of doubles} \
+ {expr 1e-277} \
+ 9.9999999999999997e-278
+test util-16.1.17.-276 {8.4 compatible formatting of doubles} \
+ {expr 1e-276} \
+ 1.0000000000000001e-276
+test util-16.1.17.-275 {8.4 compatible formatting of doubles} \
+ {expr 1e-275} \
+ 9.9999999999999993e-276
+test util-16.1.17.-274 {8.4 compatible formatting of doubles} \
+ {expr 1e-274} \
+ 9.9999999999999997e-275
+test util-16.1.17.-273 {8.4 compatible formatting of doubles} \
+ {expr 1e-273} \
+ 1.0000000000000001e-273
+test util-16.1.17.-272 {8.4 compatible formatting of doubles} \
+ {expr 1e-272} \
+ 9.9999999999999993e-273
+test util-16.1.17.-271 {8.4 compatible formatting of doubles} \
+ {expr 1e-271} \
+ 9.9999999999999996e-272
+test util-16.1.17.-270 {8.4 compatible formatting of doubles} \
+ {expr 1e-270} \
+ 1e-270
+test util-16.1.17.-269 {8.4 compatible formatting of doubles} \
+ {expr 1e-269} \
+ 9.9999999999999996e-270
+test util-16.1.17.-268 {8.4 compatible formatting of doubles} \
+ {expr 1e-268} \
+ 9.9999999999999996e-269
+test util-16.1.17.-267 {8.4 compatible formatting of doubles} \
+ {expr 1e-267} \
+ 9.9999999999999998e-268
+test util-16.1.17.-266 {8.4 compatible formatting of doubles} \
+ {expr 1e-266} \
+ 9.9999999999999998e-267
+test util-16.1.17.-265 {8.4 compatible formatting of doubles} \
+ {expr 1e-265} \
+ 9.9999999999999998e-266
+test util-16.1.17.-264 {8.4 compatible formatting of doubles} \
+ {expr 1e-264} \
+ 1e-264
+test util-16.1.17.-263 {8.4 compatible formatting of doubles} \
+ {expr 1e-263} \
+ 1e-263
+test util-16.1.17.-262 {8.4 compatible formatting of doubles} \
+ {expr 1e-262} \
+ 1e-262
+test util-16.1.17.-261 {8.4 compatible formatting of doubles} \
+ {expr 1e-261} \
+ 9.9999999999999998e-262
+test util-16.1.17.-260 {8.4 compatible formatting of doubles} \
+ {expr 1e-260} \
+ 9.9999999999999996e-261
+test util-16.1.17.-259 {8.4 compatible formatting of doubles} \
+ {expr 1e-259} \
+ 1.0000000000000001e-259
+test util-16.1.17.-258 {8.4 compatible formatting of doubles} \
+ {expr 1e-258} \
+ 9.9999999999999995e-259
+test util-16.1.17.-257 {8.4 compatible formatting of doubles} \
+ {expr 1e-257} \
+ 9.9999999999999998e-258
+test util-16.1.17.-256 {8.4 compatible formatting of doubles} \
+ {expr 1e-256} \
+ 9.9999999999999998e-257
+test util-16.1.17.-255 {8.4 compatible formatting of doubles} \
+ {expr 1e-255} \
+ 1e-255
+test util-16.1.17.-254 {8.4 compatible formatting of doubles} \
+ {expr 1e-254} \
+ 9.9999999999999991e-255
+test util-16.1.17.-253 {8.4 compatible formatting of doubles} \
+ {expr 1e-253} \
+ 1.0000000000000001e-253
+test util-16.1.17.-252 {8.4 compatible formatting of doubles} \
+ {expr 1e-252} \
+ 9.9999999999999994e-253
+test util-16.1.17.-251 {8.4 compatible formatting of doubles} \
+ {expr 1e-251} \
+ 1e-251
+test util-16.1.17.-250 {8.4 compatible formatting of doubles} \
+ {expr 1e-250} \
+ 1.0000000000000001e-250
+test util-16.1.17.-249 {8.4 compatible formatting of doubles} \
+ {expr 1e-249} \
+ 1.0000000000000001e-249
+test util-16.1.17.-248 {8.4 compatible formatting of doubles} \
+ {expr 1e-248} \
+ 9.9999999999999998e-249
+test util-16.1.17.-247 {8.4 compatible formatting of doubles} \
+ {expr 1e-247} \
+ 1e-247
+test util-16.1.17.-246 {8.4 compatible formatting of doubles} \
+ {expr 1e-246} \
+ 9.9999999999999996e-247
+test util-16.1.17.-245 {8.4 compatible formatting of doubles} \
+ {expr 1e-245} \
+ 9.9999999999999993e-246
+test util-16.1.17.-244 {8.4 compatible formatting of doubles} \
+ {expr 1e-244} \
+ 9.9999999999999993e-245
+test util-16.1.17.-243 {8.4 compatible formatting of doubles} \
+ {expr 1e-243} \
+ 1e-243
+test util-16.1.17.-242 {8.4 compatible formatting of doubles} \
+ {expr 1e-242} \
+ 9.9999999999999997e-243
+test util-16.1.17.-241 {8.4 compatible formatting of doubles} \
+ {expr 1e-241} \
+ 9.9999999999999997e-242
+test util-16.1.17.-240 {8.4 compatible formatting of doubles} \
+ {expr 1e-240} \
+ 9.9999999999999997e-241
+test util-16.1.17.-239 {8.4 compatible formatting of doubles} \
+ {expr 1e-239} \
+ 1.0000000000000001e-239
+test util-16.1.17.-238 {8.4 compatible formatting of doubles} \
+ {expr 1e-238} \
+ 9.9999999999999999e-239
+test util-16.1.17.-237 {8.4 compatible formatting of doubles} \
+ {expr 1e-237} \
+ 9.9999999999999999e-238
+test util-16.1.17.-236 {8.4 compatible formatting of doubles} \
+ {expr 1e-236} \
+ 1e-236
+test util-16.1.17.-235 {8.4 compatible formatting of doubles} \
+ {expr 1e-235} \
+ 9.9999999999999996e-236
+test util-16.1.17.-234 {8.4 compatible formatting of doubles} \
+ {expr 1e-234} \
+ 9.9999999999999996e-235
+test util-16.1.17.-233 {8.4 compatible formatting of doubles} \
+ {expr 1e-233} \
+ 9.9999999999999996e-234
+test util-16.1.17.-232 {8.4 compatible formatting of doubles} \
+ {expr 1e-232} \
+ 1e-232
+test util-16.1.17.-231 {8.4 compatible formatting of doubles} \
+ {expr 1e-231} \
+ 9.9999999999999999e-232
+test util-16.1.17.-230 {8.4 compatible formatting of doubles} \
+ {expr 1e-230} \
+ 1e-230
+test util-16.1.17.-229 {8.4 compatible formatting of doubles} \
+ {expr 1e-229} \
+ 1.0000000000000001e-229
+test util-16.1.17.-228 {8.4 compatible formatting of doubles} \
+ {expr 1e-228} \
+ 1e-228
+test util-16.1.17.-227 {8.4 compatible formatting of doubles} \
+ {expr 1e-227} \
+ 9.9999999999999994e-228
+test util-16.1.17.-226 {8.4 compatible formatting of doubles} \
+ {expr 1e-226} \
+ 9.9999999999999992e-227
+test util-16.1.17.-225 {8.4 compatible formatting of doubles} \
+ {expr 1e-225} \
+ 9.9999999999999996e-226
+test util-16.1.17.-224 {8.4 compatible formatting of doubles} \
+ {expr 1e-224} \
+ 1e-224
+test util-16.1.17.-223 {8.4 compatible formatting of doubles} \
+ {expr 1e-223} \
+ 9.9999999999999997e-224
+test util-16.1.17.-222 {8.4 compatible formatting of doubles} \
+ {expr 1e-222} \
+ 1e-222
+test util-16.1.17.-221 {8.4 compatible formatting of doubles} \
+ {expr 1e-221} \
+ 1e-221
+test util-16.1.17.-220 {8.4 compatible formatting of doubles} \
+ {expr 1e-220} \
+ 9.9999999999999999e-221
+test util-16.1.17.-219 {8.4 compatible formatting of doubles} \
+ {expr 1e-219} \
+ 1e-219
+test util-16.1.17.-218 {8.4 compatible formatting of doubles} \
+ {expr 1e-218} \
+ 1e-218
+test util-16.1.17.-217 {8.4 compatible formatting of doubles} \
+ {expr 1e-217} \
+ 1.0000000000000001e-217
+test util-16.1.17.-216 {8.4 compatible formatting of doubles} \
+ {expr 1e-216} \
+ 1e-216
+test util-16.1.17.-215 {8.4 compatible formatting of doubles} \
+ {expr 1e-215} \
+ 1e-215
+test util-16.1.17.-214 {8.4 compatible formatting of doubles} \
+ {expr 1e-214} \
+ 9.9999999999999991e-215
+test util-16.1.17.-213 {8.4 compatible formatting of doubles} \
+ {expr 1e-213} \
+ 9.9999999999999995e-214
+test util-16.1.17.-212 {8.4 compatible formatting of doubles} \
+ {expr 1e-212} \
+ 9.9999999999999995e-213
+test util-16.1.17.-211 {8.4 compatible formatting of doubles} \
+ {expr 1e-211} \
+ 1.0000000000000001e-211
+test util-16.1.17.-210 {8.4 compatible formatting of doubles} \
+ {expr 1e-210} \
+ 1e-210
+test util-16.1.17.-209 {8.4 compatible formatting of doubles} \
+ {expr 1e-209} \
+ 1e-209
+test util-16.1.17.-208 {8.4 compatible formatting of doubles} \
+ {expr 1e-208} \
+ 1.0000000000000001e-208
+test util-16.1.17.-207 {8.4 compatible formatting of doubles} \
+ {expr 1e-207} \
+ 9.9999999999999993e-208
+test util-16.1.17.-206 {8.4 compatible formatting of doubles} \
+ {expr 1e-206} \
+ 1e-206
+test util-16.1.17.-205 {8.4 compatible formatting of doubles} \
+ {expr 1e-205} \
+ 1e-205
+test util-16.1.17.-204 {8.4 compatible formatting of doubles} \
+ {expr 1e-204} \
+ 1e-204
+test util-16.1.17.-203 {8.4 compatible formatting of doubles} \
+ {expr 1e-203} \
+ 1e-203
+test util-16.1.17.-202 {8.4 compatible formatting of doubles} \
+ {expr 1e-202} \
+ 1e-202
+test util-16.1.17.-201 {8.4 compatible formatting of doubles} \
+ {expr 1e-201} \
+ 9.9999999999999995e-202
+test util-16.1.17.-200 {8.4 compatible formatting of doubles} \
+ {expr 1e-200} \
+ 9.9999999999999998e-201
+test util-16.1.17.-199 {8.4 compatible formatting of doubles} \
+ {expr 1e-199} \
+ 9.9999999999999998e-200
+test util-16.1.17.-198 {8.4 compatible formatting of doubles} \
+ {expr 1e-198} \
+ 9.9999999999999991e-199
+test util-16.1.17.-197 {8.4 compatible formatting of doubles} \
+ {expr 1e-197} \
+ 9.9999999999999999e-198
+test util-16.1.17.-196 {8.4 compatible formatting of doubles} \
+ {expr 1e-196} \
+ 1e-196
+test util-16.1.17.-195 {8.4 compatible formatting of doubles} \
+ {expr 1e-195} \
+ 1.0000000000000001e-195
+test util-16.1.17.-194 {8.4 compatible formatting of doubles} \
+ {expr 1e-194} \
+ 1e-194
+test util-16.1.17.-193 {8.4 compatible formatting of doubles} \
+ {expr 1e-193} \
+ 1e-193
+test util-16.1.17.-192 {8.4 compatible formatting of doubles} \
+ {expr 1e-192} \
+ 1.0000000000000001e-192
+test util-16.1.17.-191 {8.4 compatible formatting of doubles} \
+ {expr 1e-191} \
+ 1e-191
+test util-16.1.17.-190 {8.4 compatible formatting of doubles} \
+ {expr 1e-190} \
+ 1e-190
+test util-16.1.17.-189 {8.4 compatible formatting of doubles} \
+ {expr 1e-189} \
+ 1.0000000000000001e-189
+test util-16.1.17.-188 {8.4 compatible formatting of doubles} \
+ {expr 1e-188} \
+ 9.9999999999999995e-189
+test util-16.1.17.-187 {8.4 compatible formatting of doubles} \
+ {expr 1e-187} \
+ 1e-187
+test util-16.1.17.-186 {8.4 compatible formatting of doubles} \
+ {expr 1e-186} \
+ 9.9999999999999991e-187
+test util-16.1.17.-185 {8.4 compatible formatting of doubles} \
+ {expr 1e-185} \
+ 9.9999999999999999e-186
+test util-16.1.17.-184 {8.4 compatible formatting of doubles} \
+ {expr 1e-184} \
+ 1.0000000000000001e-184
+test util-16.1.17.-183 {8.4 compatible formatting of doubles} \
+ {expr 1e-183} \
+ 1e-183
+test util-16.1.17.-182 {8.4 compatible formatting of doubles} \
+ {expr 1e-182} \
+ 1e-182
+test util-16.1.17.-181 {8.4 compatible formatting of doubles} \
+ {expr 1e-181} \
+ 1e-181
+test util-16.1.17.-180 {8.4 compatible formatting of doubles} \
+ {expr 1e-180} \
+ 1e-180
+test util-16.1.17.-179 {8.4 compatible formatting of doubles} \
+ {expr 1e-179} \
+ 1e-179
+test util-16.1.17.-178 {8.4 compatible formatting of doubles} \
+ {expr 1e-178} \
+ 9.9999999999999995e-179
+test util-16.1.17.-177 {8.4 compatible formatting of doubles} \
+ {expr 1e-177} \
+ 9.9999999999999995e-178
+test util-16.1.17.-176 {8.4 compatible formatting of doubles} \
+ {expr 1e-176} \
+ 1e-176
+test util-16.1.17.-175 {8.4 compatible formatting of doubles} \
+ {expr 1e-175} \
+ 1e-175
+test util-16.1.17.-174 {8.4 compatible formatting of doubles} \
+ {expr 1e-174} \
+ 1e-174
+test util-16.1.17.-173 {8.4 compatible formatting of doubles} \
+ {expr 1e-173} \
+ 1e-173
+test util-16.1.17.-172 {8.4 compatible formatting of doubles} \
+ {expr 1e-172} \
+ 1e-172
+test util-16.1.17.-171 {8.4 compatible formatting of doubles} \
+ {expr 1e-171} \
+ 9.9999999999999998e-172
+test util-16.1.17.-170 {8.4 compatible formatting of doubles} \
+ {expr 1e-170} \
+ 9.9999999999999998e-171
+test util-16.1.17.-169 {8.4 compatible formatting of doubles} \
+ {expr 1e-169} \
+ 1e-169
+test util-16.1.17.-168 {8.4 compatible formatting of doubles} \
+ {expr 1e-168} \
+ 1e-168
+test util-16.1.17.-167 {8.4 compatible formatting of doubles} \
+ {expr 1e-167} \
+ 1e-167
+test util-16.1.17.-166 {8.4 compatible formatting of doubles} \
+ {expr 1e-166} \
+ 1e-166
+test util-16.1.17.-165 {8.4 compatible formatting of doubles} \
+ {expr 1e-165} \
+ 1e-165
+test util-16.1.17.-164 {8.4 compatible formatting of doubles} \
+ {expr 1e-164} \
+ 9.9999999999999996e-165
+test util-16.1.17.-163 {8.4 compatible formatting of doubles} \
+ {expr 1e-163} \
+ 9.9999999999999992e-164
+test util-16.1.17.-162 {8.4 compatible formatting of doubles} \
+ {expr 1e-162} \
+ 9.9999999999999995e-163
+test util-16.1.17.-161 {8.4 compatible formatting of doubles} \
+ {expr 1e-161} \
+ 1e-161
+test util-16.1.17.-160 {8.4 compatible formatting of doubles} \
+ {expr 1e-160} \
+ 9.9999999999999999e-161
+test util-16.1.17.-159 {8.4 compatible formatting of doubles} \
+ {expr 1e-159} \
+ 9.9999999999999999e-160
+test util-16.1.17.-158 {8.4 compatible formatting of doubles} \
+ {expr 1e-158} \
+ 1.0000000000000001e-158
+test util-16.1.17.-157 {8.4 compatible formatting of doubles} \
+ {expr 1e-157} \
+ 9.9999999999999994e-158
+test util-16.1.17.-156 {8.4 compatible formatting of doubles} \
+ {expr 1e-156} \
+ 1e-156
+test util-16.1.17.-155 {8.4 compatible formatting of doubles} \
+ {expr 1e-155} \
+ 1e-155
+test util-16.1.17.-154 {8.4 compatible formatting of doubles} \
+ {expr 1e-154} \
+ 9.9999999999999997e-155
+test util-16.1.17.-153 {8.4 compatible formatting of doubles} \
+ {expr 1e-153} \
+ 1e-153
+test util-16.1.17.-152 {8.4 compatible formatting of doubles} \
+ {expr 1e-152} \
+ 1.0000000000000001e-152
+test util-16.1.17.-151 {8.4 compatible formatting of doubles} \
+ {expr 1e-151} \
+ 9.9999999999999994e-152
+test util-16.1.17.-150 {8.4 compatible formatting of doubles} \
+ {expr 1e-150} \
+ 1e-150
+test util-16.1.17.-149 {8.4 compatible formatting of doubles} \
+ {expr 1e-149} \
+ 9.9999999999999998e-150
+test util-16.1.17.-148 {8.4 compatible formatting of doubles} \
+ {expr 1e-148} \
+ 9.9999999999999994e-149
+test util-16.1.17.-147 {8.4 compatible formatting of doubles} \
+ {expr 1e-147} \
+ 9.9999999999999997e-148
+test util-16.1.17.-146 {8.4 compatible formatting of doubles} \
+ {expr 1e-146} \
+ 1e-146
+test util-16.1.17.-145 {8.4 compatible formatting of doubles} \
+ {expr 1e-145} \
+ 9.9999999999999991e-146
+test util-16.1.17.-144 {8.4 compatible formatting of doubles} \
+ {expr 1e-144} \
+ 9.9999999999999995e-145
+test util-16.1.17.-143 {8.4 compatible formatting of doubles} \
+ {expr 1e-143} \
+ 9.9999999999999995e-144
+test util-16.1.17.-142 {8.4 compatible formatting of doubles} \
+ {expr 1e-142} \
+ 1e-142
+test util-16.1.17.-141 {8.4 compatible formatting of doubles} \
+ {expr 1e-141} \
+ 1e-141
+test util-16.1.17.-140 {8.4 compatible formatting of doubles} \
+ {expr 1e-140} \
+ 9.9999999999999998e-141
+test util-16.1.17.-139 {8.4 compatible formatting of doubles} \
+ {expr 1e-139} \
+ 1e-139
+test util-16.1.17.-138 {8.4 compatible formatting of doubles} \
+ {expr 1e-138} \
+ 1.0000000000000001e-138
+test util-16.1.17.-137 {8.4 compatible formatting of doubles} \
+ {expr 1e-137} \
+ 9.9999999999999998e-138
+test util-16.1.17.-136 {8.4 compatible formatting of doubles} \
+ {expr 1e-136} \
+ 1e-136
+test util-16.1.17.-135 {8.4 compatible formatting of doubles} \
+ {expr 1e-135} \
+ 1e-135
+test util-16.1.17.-134 {8.4 compatible formatting of doubles} \
+ {expr 1e-134} \
+ 1e-134
+test util-16.1.17.-133 {8.4 compatible formatting of doubles} \
+ {expr 1e-133} \
+ 1.0000000000000001e-133
+test util-16.1.17.-132 {8.4 compatible formatting of doubles} \
+ {expr 1e-132} \
+ 9.9999999999999999e-133
+test util-16.1.17.-131 {8.4 compatible formatting of doubles} \
+ {expr 1e-131} \
+ 9.9999999999999999e-132
+test util-16.1.17.-130 {8.4 compatible formatting of doubles} \
+ {expr 1e-130} \
+ 1.0000000000000001e-130
+test util-16.1.17.-129 {8.4 compatible formatting of doubles} \
+ {expr 1e-129} \
+ 9.9999999999999993e-130
+test util-16.1.17.-128 {8.4 compatible formatting of doubles} \
+ {expr 1e-128} \
+ 1.0000000000000001e-128
+test util-16.1.17.-127 {8.4 compatible formatting of doubles} \
+ {expr 1e-127} \
+ 1e-127
+test util-16.1.17.-126 {8.4 compatible formatting of doubles} \
+ {expr 1e-126} \
+ 9.9999999999999995e-127
+test util-16.1.17.-125 {8.4 compatible formatting of doubles} \
+ {expr 1e-125} \
+ 1e-125
+test util-16.1.17.-124 {8.4 compatible formatting of doubles} \
+ {expr 1e-124} \
+ 9.9999999999999993e-125
+test util-16.1.17.-123 {8.4 compatible formatting of doubles} \
+ {expr 1e-123} \
+ 1.0000000000000001e-123
+test util-16.1.17.-122 {8.4 compatible formatting of doubles} \
+ {expr 1e-122} \
+ 1.0000000000000001e-122
+test util-16.1.17.-121 {8.4 compatible formatting of doubles} \
+ {expr 1e-121} \
+ 9.9999999999999998e-122
+test util-16.1.17.-120 {8.4 compatible formatting of doubles} \
+ {expr 1e-120} \
+ 9.9999999999999998e-121
+test util-16.1.17.-119 {8.4 compatible formatting of doubles} \
+ {expr 1e-119} \
+ 1e-119
+test util-16.1.17.-118 {8.4 compatible formatting of doubles} \
+ {expr 1e-118} \
+ 9.9999999999999999e-119
+test util-16.1.17.-117 {8.4 compatible formatting of doubles} \
+ {expr 1e-117} \
+ 1e-117
+test util-16.1.17.-116 {8.4 compatible formatting of doubles} \
+ {expr 1e-116} \
+ 9.9999999999999999e-117
+test util-16.1.17.-115 {8.4 compatible formatting of doubles} \
+ {expr 1e-115} \
+ 1.0000000000000001e-115
+test util-16.1.17.-114 {8.4 compatible formatting of doubles} \
+ {expr 1e-114} \
+ 1.0000000000000001e-114
+test util-16.1.17.-113 {8.4 compatible formatting of doubles} \
+ {expr 1e-113} \
+ 9.9999999999999998e-114
+test util-16.1.17.-112 {8.4 compatible formatting of doubles} \
+ {expr 1e-112} \
+ 9.9999999999999995e-113
+test util-16.1.17.-111 {8.4 compatible formatting of doubles} \
+ {expr 1e-111} \
+ 1.0000000000000001e-111
+test util-16.1.17.-110 {8.4 compatible formatting of doubles} \
+ {expr 1e-110} \
+ 1.0000000000000001e-110
+test util-16.1.17.-109 {8.4 compatible formatting of doubles} \
+ {expr 1e-109} \
+ 9.9999999999999999e-110
+test util-16.1.17.-108 {8.4 compatible formatting of doubles} \
+ {expr 1e-108} \
+ 1e-108
+test util-16.1.17.-107 {8.4 compatible formatting of doubles} \
+ {expr 1e-107} \
+ 1e-107
+test util-16.1.17.-106 {8.4 compatible formatting of doubles} \
+ {expr 1e-106} \
+ 9.9999999999999994e-107
+test util-16.1.17.-105 {8.4 compatible formatting of doubles} \
+ {expr 1e-105} \
+ 9.9999999999999997e-106
+test util-16.1.17.-104 {8.4 compatible formatting of doubles} \
+ {expr 1e-104} \
+ 9.9999999999999993e-105
+test util-16.1.17.-103 {8.4 compatible formatting of doubles} \
+ {expr 1e-103} \
+ 9.9999999999999996e-104
+test util-16.1.17.-102 {8.4 compatible formatting of doubles} \
+ {expr 1e-102} \
+ 9.9999999999999993e-103
+test util-16.1.17.-101 {8.4 compatible formatting of doubles} \
+ {expr 1e-101} \
+ 1.0000000000000001e-101
+test util-16.1.17.-100 {8.4 compatible formatting of doubles} \
+ {expr 1e-100} \
+ 1e-100
+test util-16.1.17.-99 {8.4 compatible formatting of doubles} \
+ {expr 1e-99} \
+ 1e-99
+test util-16.1.17.-98 {8.4 compatible formatting of doubles} \
+ {expr 1e-98} \
+ 9.9999999999999994e-99
+test util-16.1.17.-97 {8.4 compatible formatting of doubles} \
+ {expr 1e-97} \
+ 1e-97
+test util-16.1.17.-96 {8.4 compatible formatting of doubles} \
+ {expr 1e-96} \
+ 9.9999999999999991e-97
+test util-16.1.17.-95 {8.4 compatible formatting of doubles} \
+ {expr 1e-95} \
+ 9.9999999999999999e-96
+test util-16.1.17.-94 {8.4 compatible formatting of doubles} \
+ {expr 1e-94} \
+ 9.9999999999999996e-95
+test util-16.1.17.-93 {8.4 compatible formatting of doubles} \
+ {expr 1e-93} \
+ 9.999999999999999e-94
+test util-16.1.17.-92 {8.4 compatible formatting of doubles} \
+ {expr 1e-92} \
+ 9.9999999999999999e-93
+test util-16.1.17.-91 {8.4 compatible formatting of doubles} \
+ {expr 1e-91} \
+ 1e-91
+test util-16.1.17.-90 {8.4 compatible formatting of doubles} \
+ {expr 1e-90} \
+ 9.9999999999999999e-91
+test util-16.1.17.-89 {8.4 compatible formatting of doubles} \
+ {expr 1e-89} \
+ 1e-89
+test util-16.1.17.-88 {8.4 compatible formatting of doubles} \
+ {expr 1e-88} \
+ 9.9999999999999993e-89
+test util-16.1.17.-87 {8.4 compatible formatting of doubles} \
+ {expr 1e-87} \
+ 1e-87
+test util-16.1.17.-86 {8.4 compatible formatting of doubles} \
+ {expr 1e-86} \
+ 1.0000000000000001e-86
+test util-16.1.17.-85 {8.4 compatible formatting of doubles} \
+ {expr 1e-85} \
+ 9.9999999999999998e-86
+test util-16.1.17.-84 {8.4 compatible formatting of doubles} \
+ {expr 1e-84} \
+ 1e-84
+test util-16.1.17.-83 {8.4 compatible formatting of doubles} \
+ {expr 1e-83} \
+ 1e-83
+test util-16.1.17.-82 {8.4 compatible formatting of doubles} \
+ {expr 1e-82} \
+ 9.9999999999999996e-83
+test util-16.1.17.-81 {8.4 compatible formatting of doubles} \
+ {expr 1e-81} \
+ 9.9999999999999996e-82
+test util-16.1.17.-80 {8.4 compatible formatting of doubles} \
+ {expr 1e-80} \
+ 9.9999999999999996e-81
+test util-16.1.17.-79 {8.4 compatible formatting of doubles} \
+ {expr 1e-79} \
+ 1e-79
+test util-16.1.17.-78 {8.4 compatible formatting of doubles} \
+ {expr 1e-78} \
+ 1e-78
+test util-16.1.17.-77 {8.4 compatible formatting of doubles} \
+ {expr 1e-77} \
+ 9.9999999999999993e-78
+test util-16.1.17.-76 {8.4 compatible formatting of doubles} \
+ {expr 1e-76} \
+ 9.9999999999999993e-77
+test util-16.1.17.-75 {8.4 compatible formatting of doubles} \
+ {expr 1e-75} \
+ 9.9999999999999996e-76
+test util-16.1.17.-74 {8.4 compatible formatting of doubles} \
+ {expr 1e-74} \
+ 9.9999999999999996e-75
+test util-16.1.17.-73 {8.4 compatible formatting of doubles} \
+ {expr 1e-73} \
+ 1e-73
+test util-16.1.17.-72 {8.4 compatible formatting of doubles} \
+ {expr 1e-72} \
+ 9.9999999999999997e-73
+test util-16.1.17.-71 {8.4 compatible formatting of doubles} \
+ {expr 1e-71} \
+ 9.9999999999999992e-72
+test util-16.1.17.-70 {8.4 compatible formatting of doubles} \
+ {expr 1e-70} \
+ 1e-70
+test util-16.1.17.-69 {8.4 compatible formatting of doubles} \
+ {expr 1e-69} \
+ 9.9999999999999996e-70
+test util-16.1.17.-68 {8.4 compatible formatting of doubles} \
+ {expr 1e-68} \
+ 1.0000000000000001e-68
+test util-16.1.17.-67 {8.4 compatible formatting of doubles} \
+ {expr 1e-67} \
+ 9.9999999999999994e-68
+test util-16.1.17.-66 {8.4 compatible formatting of doubles} \
+ {expr 1e-66} \
+ 9.9999999999999998e-67
+test util-16.1.17.-65 {8.4 compatible formatting of doubles} \
+ {expr 1e-65} \
+ 9.9999999999999992e-66
+test util-16.1.17.-64 {8.4 compatible formatting of doubles} \
+ {expr 1e-64} \
+ 9.9999999999999997e-65
+test util-16.1.17.-63 {8.4 compatible formatting of doubles} \
+ {expr 1e-63} \
+ 1.0000000000000001e-63
+test util-16.1.17.-62 {8.4 compatible formatting of doubles} \
+ {expr 1e-62} \
+ 1e-62
+test util-16.1.17.-61 {8.4 compatible formatting of doubles} \
+ {expr 1e-61} \
+ 1e-61
+test util-16.1.17.-60 {8.4 compatible formatting of doubles} \
+ {expr 1e-60} \
+ 9.9999999999999997e-61
+test util-16.1.17.-59 {8.4 compatible formatting of doubles} \
+ {expr 1e-59} \
+ 1e-59
+test util-16.1.17.-58 {8.4 compatible formatting of doubles} \
+ {expr 1e-58} \
+ 1e-58
+test util-16.1.17.-57 {8.4 compatible formatting of doubles} \
+ {expr 1e-57} \
+ 9.9999999999999995e-58
+test util-16.1.17.-56 {8.4 compatible formatting of doubles} \
+ {expr 1e-56} \
+ 1e-56
+test util-16.1.17.-55 {8.4 compatible formatting of doubles} \
+ {expr 1e-55} \
+ 9.9999999999999999e-56
+test util-16.1.17.-54 {8.4 compatible formatting of doubles} \
+ {expr 1e-54} \
+ 1e-54
+test util-16.1.17.-53 {8.4 compatible formatting of doubles} \
+ {expr 1e-53} \
+ 1e-53
+test util-16.1.17.-52 {8.4 compatible formatting of doubles} \
+ {expr 1e-52} \
+ 1e-52
+test util-16.1.17.-51 {8.4 compatible formatting of doubles} \
+ {expr 1e-51} \
+ 1e-51
+test util-16.1.17.-50 {8.4 compatible formatting of doubles} \
+ {expr 1e-50} \
+ 1e-50
+test util-16.1.17.-49 {8.4 compatible formatting of doubles} \
+ {expr 1e-49} \
+ 9.9999999999999994e-50
+test util-16.1.17.-48 {8.4 compatible formatting of doubles} \
+ {expr 1e-48} \
+ 9.9999999999999997e-49
+test util-16.1.17.-47 {8.4 compatible formatting of doubles} \
+ {expr 1e-47} \
+ 9.9999999999999997e-48
+test util-16.1.17.-46 {8.4 compatible formatting of doubles} \
+ {expr 1e-46} \
+ 1e-46
+test util-16.1.17.-45 {8.4 compatible formatting of doubles} \
+ {expr 1e-45} \
+ 9.9999999999999998e-46
+test util-16.1.17.-44 {8.4 compatible formatting of doubles} \
+ {expr 1e-44} \
+ 9.9999999999999995e-45
+test util-16.1.17.-43 {8.4 compatible formatting of doubles} \
+ {expr 1e-43} \
+ 1.0000000000000001e-43
+test util-16.1.17.-42 {8.4 compatible formatting of doubles} \
+ {expr 1e-42} \
+ 1e-42
+test util-16.1.17.-41 {8.4 compatible formatting of doubles} \
+ {expr 1e-41} \
+ 1e-41
+test util-16.1.17.-40 {8.4 compatible formatting of doubles} \
+ {expr 1e-40} \
+ 9.9999999999999993e-41
+test util-16.1.17.-39 {8.4 compatible formatting of doubles} \
+ {expr 1e-39} \
+ 9.9999999999999993e-40
+test util-16.1.17.-38 {8.4 compatible formatting of doubles} \
+ {expr 1e-38} \
+ 9.9999999999999996e-39
+test util-16.1.17.-37 {8.4 compatible formatting of doubles} \
+ {expr 1e-37} \
+ 1.0000000000000001e-37
+test util-16.1.17.-36 {8.4 compatible formatting of doubles} \
+ {expr 1e-36} \
+ 9.9999999999999994e-37
+test util-16.1.17.-35 {8.4 compatible formatting of doubles} \
+ {expr 1e-35} \
+ 1e-35
+test util-16.1.17.-34 {8.4 compatible formatting of doubles} \
+ {expr 1e-34} \
+ 9.9999999999999993e-35
+test util-16.1.17.-33 {8.4 compatible formatting of doubles} \
+ {expr 1e-33} \
+ 1.0000000000000001e-33
+test util-16.1.17.-32 {8.4 compatible formatting of doubles} \
+ {expr 1e-32} \
+ 1.0000000000000001e-32
+test util-16.1.17.-31 {8.4 compatible formatting of doubles} \
+ {expr 1e-31} \
+ 1.0000000000000001e-31
+test util-16.1.17.-30 {8.4 compatible formatting of doubles} \
+ {expr 1e-30} \
+ 1.0000000000000001e-30
+test util-16.1.17.-29 {8.4 compatible formatting of doubles} \
+ {expr 1e-29} \
+ 9.9999999999999994e-30
+test util-16.1.17.-28 {8.4 compatible formatting of doubles} \
+ {expr 1e-28} \
+ 9.9999999999999997e-29
+test util-16.1.17.-27 {8.4 compatible formatting of doubles} \
+ {expr 1e-27} \
+ 1e-27
+test util-16.1.17.-26 {8.4 compatible formatting of doubles} \
+ {expr 1e-26} \
+ 1e-26
+test util-16.1.17.-25 {8.4 compatible formatting of doubles} \
+ {expr 1e-25} \
+ 1e-25
+test util-16.1.17.-24 {8.4 compatible formatting of doubles} \
+ {expr 1e-24} \
+ 9.9999999999999992e-25
+test util-16.1.17.-23 {8.4 compatible formatting of doubles} \
+ {expr 1e-23} \
+ 9.9999999999999996e-24
+test util-16.1.17.-22 {8.4 compatible formatting of doubles} \
+ {expr 1e-22} \
+ 1e-22
+test util-16.1.17.-21 {8.4 compatible formatting of doubles} \
+ {expr 1e-21} \
+ 9.9999999999999991e-22
+test util-16.1.17.-20 {8.4 compatible formatting of doubles} \
+ {expr 1e-20} \
+ 9.9999999999999995e-21
+test util-16.1.17.-19 {8.4 compatible formatting of doubles} \
+ {expr 1e-19} \
+ 9.9999999999999998e-20
+test util-16.1.17.-18 {8.4 compatible formatting of doubles} \
+ {expr 1e-18} \
+ 1.0000000000000001e-18
+test util-16.1.17.-17 {8.4 compatible formatting of doubles} \
+ {expr 1e-17} \
+ 1.0000000000000001e-17
+test util-16.1.17.-16 {8.4 compatible formatting of doubles} \
+ {expr 1e-16} \
+ 9.9999999999999998e-17
+test util-16.1.17.-15 {8.4 compatible formatting of doubles} \
+ {expr 1e-15} \
+ 1.0000000000000001e-15
+test util-16.1.17.-14 {8.4 compatible formatting of doubles} \
+ {expr 1e-14} \
+ 1e-14
+test util-16.1.17.-13 {8.4 compatible formatting of doubles} \
+ {expr 1e-13} \
+ 1e-13
+test util-16.1.17.-12 {8.4 compatible formatting of doubles} \
+ {expr 1e-12} \
+ 9.9999999999999998e-13
+test util-16.1.17.-11 {8.4 compatible formatting of doubles} \
+ {expr 1e-11} \
+ 9.9999999999999994e-12
+test util-16.1.17.-10 {8.4 compatible formatting of doubles} \
+ {expr 1e-10} \
+ 1e-10
+test util-16.1.17.-9 {8.4 compatible formatting of doubles} \
+ {expr 1e-9} \
+ 1.0000000000000001e-09
+test util-16.1.17.-8 {8.4 compatible formatting of doubles} \
+ {expr 1e-8} \
+ 1e-08
+test util-16.1.17.-7 {8.4 compatible formatting of doubles} \
+ {expr 1e-7} \
+ 9.9999999999999995e-08
+test util-16.1.17.-6 {8.4 compatible formatting of doubles} \
+ {expr 1e-6} \
+ 9.9999999999999995e-07
+test util-16.1.17.-5 {8.4 compatible formatting of doubles} \
+ {expr 1e-5} \
+ 1.0000000000000001e-05
+test util-16.1.17.-4 {8.4 compatible formatting of doubles} \
+ {expr 1e-4} \
+ 0.0001
+test util-16.1.17.-3 {8.4 compatible formatting of doubles} \
+ {expr 1e-3} \
+ 0.001
+test util-16.1.17.-2 {8.4 compatible formatting of doubles} \
+ {expr 1e-2} \
+ 0.01
+test util-16.1.17.-1 {8.4 compatible formatting of doubles} \
+ {expr 1e-1} \
+ 0.10000000000000001
+test util-16.1.17.0 {8.4 compatible formatting of doubles} \
+ {expr 1e0} \
+ 1.0
+test util-16.1.17.1 {8.4 compatible formatting of doubles} \
+ {expr 1e1} \
+ 10.0
+test util-16.1.17.2 {8.4 compatible formatting of doubles} \
+ {expr 1e2} \
+ 100.0
+test util-16.1.17.3 {8.4 compatible formatting of doubles} \
+ {expr 1e3} \
+ 1000.0
+test util-16.1.17.4 {8.4 compatible formatting of doubles} \
+ {expr 1e4} \
+ 10000.0
+test util-16.1.17.5 {8.4 compatible formatting of doubles} \
+ {expr 1e5} \
+ 100000.0
+test util-16.1.17.6 {8.4 compatible formatting of doubles} \
+ {expr 1e6} \
+ 1000000.0
+test util-16.1.17.7 {8.4 compatible formatting of doubles} \
+ {expr 1e7} \
+ 10000000.0
+test util-16.1.17.8 {8.4 compatible formatting of doubles} \
+ {expr 1e8} \
+ 100000000.0
+test util-16.1.17.9 {8.4 compatible formatting of doubles} \
+ {expr 1e9} \
+ 1000000000.0
+test util-16.1.17.10 {8.4 compatible formatting of doubles} \
+ {expr 1e10} \
+ 10000000000.0
+test util-16.1.17.11 {8.4 compatible formatting of doubles} \
+ {expr 1e11} \
+ 100000000000.0
+test util-16.1.17.12 {8.4 compatible formatting of doubles} \
+ {expr 1e12} \
+ 1000000000000.0
+test util-16.1.17.13 {8.4 compatible formatting of doubles} \
+ {expr 1e13} \
+ 10000000000000.0
+test util-16.1.17.14 {8.4 compatible formatting of doubles} \
+ {expr 1e14} \
+ 100000000000000.0
+test util-16.1.17.15 {8.4 compatible formatting of doubles} \
+ {expr 1e15} \
+ 1000000000000000.0
+test util-16.1.17.16 {8.4 compatible formatting of doubles} \
+ {expr 1e16} \
+ 10000000000000000.0
+test util-16.1.17.17 {8.4 compatible formatting of doubles} \
+ {expr 1e17} \
+ 1e+17
+test util-16.1.17.18 {8.4 compatible formatting of doubles} \
+ {expr 1e18} \
+ 1e+18
+test util-16.1.17.19 {8.4 compatible formatting of doubles} \
+ {expr 1e19} \
+ 1e+19
+test util-16.1.17.20 {8.4 compatible formatting of doubles} \
+ {expr 1e20} \
+ 1e+20
+test util-16.1.17.21 {8.4 compatible formatting of doubles} \
+ {expr 1e21} \
+ 1e+21
+test util-16.1.17.22 {8.4 compatible formatting of doubles} \
+ {expr 1e22} \
+ 1e+22
+test util-16.1.17.23 {8.4 compatible formatting of doubles} \
+ {expr 1e23} \
+ 9.9999999999999992e+22
+test util-16.1.17.24 {8.4 compatible formatting of doubles} \
+ {expr 1e24} \
+ 9.9999999999999998e+23
+test util-16.1.17.25 {8.4 compatible formatting of doubles} \
+ {expr 1e25} \
+ 1.0000000000000001e+25
+test util-16.1.17.26 {8.4 compatible formatting of doubles} \
+ {expr 1e26} \
+ 1e+26
+test util-16.1.17.27 {8.4 compatible formatting of doubles} \
+ {expr 1e27} \
+ 1e+27
+test util-16.1.17.28 {8.4 compatible formatting of doubles} \
+ {expr 1e28} \
+ 9.9999999999999996e+27
+test util-16.1.17.29 {8.4 compatible formatting of doubles} \
+ {expr 1e29} \
+ 9.9999999999999991e+28
+test util-16.1.17.30 {8.4 compatible formatting of doubles} \
+ {expr 1e30} \
+ 1e+30
+test util-16.1.17.31 {8.4 compatible formatting of doubles} \
+ {expr 1e31} \
+ 9.9999999999999996e+30
+test util-16.1.17.32 {8.4 compatible formatting of doubles} \
+ {expr 1e32} \
+ 1.0000000000000001e+32
+test util-16.1.17.33 {8.4 compatible formatting of doubles} \
+ {expr 1e33} \
+ 9.9999999999999995e+32
+test util-16.1.17.34 {8.4 compatible formatting of doubles} \
+ {expr 1e34} \
+ 9.9999999999999995e+33
+test util-16.1.17.35 {8.4 compatible formatting of doubles} \
+ {expr 1e35} \
+ 9.9999999999999997e+34
+test util-16.1.17.36 {8.4 compatible formatting of doubles} \
+ {expr 1e36} \
+ 1e+36
+test util-16.1.17.37 {8.4 compatible formatting of doubles} \
+ {expr 1e37} \
+ 9.9999999999999995e+36
+test util-16.1.17.38 {8.4 compatible formatting of doubles} \
+ {expr 1e38} \
+ 9.9999999999999998e+37
+test util-16.1.17.39 {8.4 compatible formatting of doubles} \
+ {expr 1e39} \
+ 9.9999999999999994e+38
+test util-16.1.17.40 {8.4 compatible formatting of doubles} \
+ {expr 1e40} \
+ 1e+40
+test util-16.1.17.41 {8.4 compatible formatting of doubles} \
+ {expr 1e41} \
+ 1e+41
+test util-16.1.17.42 {8.4 compatible formatting of doubles} \
+ {expr 1e42} \
+ 1e+42
+test util-16.1.17.43 {8.4 compatible formatting of doubles} \
+ {expr 1e43} \
+ 1e+43
+test util-16.1.17.44 {8.4 compatible formatting of doubles} \
+ {expr 1e44} \
+ 1.0000000000000001e+44
+test util-16.1.17.45 {8.4 compatible formatting of doubles} \
+ {expr 1e45} \
+ 9.9999999999999993e+44
+test util-16.1.17.46 {8.4 compatible formatting of doubles} \
+ {expr 1e46} \
+ 9.9999999999999999e+45
+test util-16.1.17.47 {8.4 compatible formatting of doubles} \
+ {expr 1e47} \
+ 1e+47
+test util-16.1.17.48 {8.4 compatible formatting of doubles} \
+ {expr 1e48} \
+ 1e+48
+test util-16.1.17.49 {8.4 compatible formatting of doubles} \
+ {expr 1e49} \
+ 9.9999999999999995e+48
+test util-16.1.17.50 {8.4 compatible formatting of doubles} \
+ {expr 1e50} \
+ 1.0000000000000001e+50
+test util-16.1.17.51 {8.4 compatible formatting of doubles} \
+ {expr 1e51} \
+ 9.9999999999999999e+50
+test util-16.1.17.52 {8.4 compatible formatting of doubles} \
+ {expr 1e52} \
+ 9.9999999999999999e+51
+test util-16.1.17.53 {8.4 compatible formatting of doubles} \
+ {expr 1e53} \
+ 9.9999999999999999e+52
+test util-16.1.17.54 {8.4 compatible formatting of doubles} \
+ {expr 1e54} \
+ 1.0000000000000001e+54
+test util-16.1.17.55 {8.4 compatible formatting of doubles} \
+ {expr 1e55} \
+ 1e+55
+test util-16.1.17.56 {8.4 compatible formatting of doubles} \
+ {expr 1e56} \
+ 1.0000000000000001e+56
+test util-16.1.17.57 {8.4 compatible formatting of doubles} \
+ {expr 1e57} \
+ 1e+57
+test util-16.1.17.58 {8.4 compatible formatting of doubles} \
+ {expr 1e58} \
+ 9.9999999999999994e+57
+test util-16.1.17.59 {8.4 compatible formatting of doubles} \
+ {expr 1e59} \
+ 9.9999999999999997e+58
+test util-16.1.17.60 {8.4 compatible formatting of doubles} \
+ {expr 1e60} \
+ 9.9999999999999995e+59
+test util-16.1.17.61 {8.4 compatible formatting of doubles} \
+ {expr 1e61} \
+ 9.9999999999999995e+60
+test util-16.1.17.62 {8.4 compatible formatting of doubles} \
+ {expr 1e62} \
+ 1e+62
+test util-16.1.17.63 {8.4 compatible formatting of doubles} \
+ {expr 1e63} \
+ 1.0000000000000001e+63
+test util-16.1.17.64 {8.4 compatible formatting of doubles} \
+ {expr 1e64} \
+ 1e+64
+test util-16.1.17.65 {8.4 compatible formatting of doubles} \
+ {expr 1e65} \
+ 9.9999999999999999e+64
+test util-16.1.17.66 {8.4 compatible formatting of doubles} \
+ {expr 1e66} \
+ 9.9999999999999995e+65
+test util-16.1.17.67 {8.4 compatible formatting of doubles} \
+ {expr 1e67} \
+ 9.9999999999999998e+66
+test util-16.1.17.68 {8.4 compatible formatting of doubles} \
+ {expr 1e68} \
+ 9.9999999999999995e+67
+test util-16.1.17.69 {8.4 compatible formatting of doubles} \
+ {expr 1e69} \
+ 1.0000000000000001e+69
+test util-16.1.17.70 {8.4 compatible formatting of doubles} \
+ {expr 1e70} \
+ 1.0000000000000001e+70
+test util-16.1.17.71 {8.4 compatible formatting of doubles} \
+ {expr 1e71} \
+ 1e+71
+test util-16.1.17.72 {8.4 compatible formatting of doubles} \
+ {expr 1e72} \
+ 9.9999999999999994e+71
+test util-16.1.17.73 {8.4 compatible formatting of doubles} \
+ {expr 1e73} \
+ 9.9999999999999998e+72
+test util-16.1.17.74 {8.4 compatible formatting of doubles} \
+ {expr 1e74} \
+ 9.9999999999999995e+73
+test util-16.1.17.75 {8.4 compatible formatting of doubles} \
+ {expr 1e75} \
+ 9.9999999999999993e+74
+test util-16.1.17.76 {8.4 compatible formatting of doubles} \
+ {expr 1e76} \
+ 1e+76
+test util-16.1.17.77 {8.4 compatible formatting of doubles} \
+ {expr 1e77} \
+ 9.9999999999999998e+76
+test util-16.1.17.78 {8.4 compatible formatting of doubles} \
+ {expr 1e78} \
+ 1e+78
+test util-16.1.17.79 {8.4 compatible formatting of doubles} \
+ {expr 1e79} \
+ 9.9999999999999997e+78
+test util-16.1.17.80 {8.4 compatible formatting of doubles} \
+ {expr 1e80} \
+ 1e+80
+test util-16.1.17.81 {8.4 compatible formatting of doubles} \
+ {expr 1e81} \
+ 9.9999999999999992e+80
+test util-16.1.17.82 {8.4 compatible formatting of doubles} \
+ {expr 1e82} \
+ 9.9999999999999996e+81
+test util-16.1.17.83 {8.4 compatible formatting of doubles} \
+ {expr 1e83} \
+ 1e+83
+test util-16.1.17.84 {8.4 compatible formatting of doubles} \
+ {expr 1e84} \
+ 1.0000000000000001e+84
+test util-16.1.17.85 {8.4 compatible formatting of doubles} \
+ {expr 1e85} \
+ 1e+85
+test util-16.1.17.86 {8.4 compatible formatting of doubles} \
+ {expr 1e86} \
+ 1e+86
+test util-16.1.17.87 {8.4 compatible formatting of doubles} \
+ {expr 1e87} \
+ 9.9999999999999996e+86
+test util-16.1.17.88 {8.4 compatible formatting of doubles} \
+ {expr 1e88} \
+ 9.9999999999999996e+87
+test util-16.1.17.89 {8.4 compatible formatting of doubles} \
+ {expr 1e89} \
+ 9.9999999999999999e+88
+test util-16.1.17.90 {8.4 compatible formatting of doubles} \
+ {expr 1e90} \
+ 9.9999999999999997e+89
+test util-16.1.17.91 {8.4 compatible formatting of doubles} \
+ {expr 1e91} \
+ 1.0000000000000001e+91
+test util-16.1.17.92 {8.4 compatible formatting of doubles} \
+ {expr 1e92} \
+ 1e+92
+test util-16.1.17.93 {8.4 compatible formatting of doubles} \
+ {expr 1e93} \
+ 1e+93
+test util-16.1.17.94 {8.4 compatible formatting of doubles} \
+ {expr 1e94} \
+ 1e+94
+test util-16.1.17.95 {8.4 compatible formatting of doubles} \
+ {expr 1e95} \
+ 1e+95
+test util-16.1.17.96 {8.4 compatible formatting of doubles} \
+ {expr 1e96} \
+ 1e+96
+test util-16.1.17.97 {8.4 compatible formatting of doubles} \
+ {expr 1e97} \
+ 1.0000000000000001e+97
+test util-16.1.17.98 {8.4 compatible formatting of doubles} \
+ {expr 1e98} \
+ 1e+98
+test util-16.1.17.99 {8.4 compatible formatting of doubles} \
+ {expr 1e99} \
+ 9.9999999999999997e+98
+test util-16.1.17.100 {8.4 compatible formatting of doubles} \
+ {expr 1e100} \
+ 1e+100
+test util-16.1.17.101 {8.4 compatible formatting of doubles} \
+ {expr 1e101} \
+ 9.9999999999999998e+100
+test util-16.1.17.102 {8.4 compatible formatting of doubles} \
+ {expr 1e102} \
+ 9.9999999999999998e+101
+test util-16.1.17.103 {8.4 compatible formatting of doubles} \
+ {expr 1e103} \
+ 1e+103
+test util-16.1.17.104 {8.4 compatible formatting of doubles} \
+ {expr 1e104} \
+ 1e+104
+test util-16.1.17.105 {8.4 compatible formatting of doubles} \
+ {expr 1e105} \
+ 9.9999999999999994e+104
+test util-16.1.17.106 {8.4 compatible formatting of doubles} \
+ {expr 1e106} \
+ 1.0000000000000001e+106
+test util-16.1.17.107 {8.4 compatible formatting of doubles} \
+ {expr 1e107} \
+ 9.9999999999999997e+106
+test util-16.1.17.108 {8.4 compatible formatting of doubles} \
+ {expr 1e108} \
+ 1e+108
+test util-16.1.17.109 {8.4 compatible formatting of doubles} \
+ {expr 1e109} \
+ 9.9999999999999998e+108
+test util-16.1.17.110 {8.4 compatible formatting of doubles} \
+ {expr 1e110} \
+ 1e+110
+test util-16.1.17.111 {8.4 compatible formatting of doubles} \
+ {expr 1e111} \
+ 9.9999999999999996e+110
+test util-16.1.17.112 {8.4 compatible formatting of doubles} \
+ {expr 1e112} \
+ 9.9999999999999993e+111
+test util-16.1.17.113 {8.4 compatible formatting of doubles} \
+ {expr 1e113} \
+ 1e+113
+test util-16.1.17.114 {8.4 compatible formatting of doubles} \
+ {expr 1e114} \
+ 1e+114
+test util-16.1.17.115 {8.4 compatible formatting of doubles} \
+ {expr 1e115} \
+ 1e+115
+test util-16.1.17.116 {8.4 compatible formatting of doubles} \
+ {expr 1e116} \
+ 1e+116
+test util-16.1.17.117 {8.4 compatible formatting of doubles} \
+ {expr 1e117} \
+ 1.0000000000000001e+117
+test util-16.1.17.118 {8.4 compatible formatting of doubles} \
+ {expr 1e118} \
+ 9.9999999999999997e+117
+test util-16.1.17.119 {8.4 compatible formatting of doubles} \
+ {expr 1e119} \
+ 9.9999999999999994e+118
+test util-16.1.17.120 {8.4 compatible formatting of doubles} \
+ {expr 1e120} \
+ 9.9999999999999998e+119
+test util-16.1.17.121 {8.4 compatible formatting of doubles} \
+ {expr 1e121} \
+ 1e+121
+test util-16.1.17.122 {8.4 compatible formatting of doubles} \
+ {expr 1e122} \
+ 1e+122
+test util-16.1.17.123 {8.4 compatible formatting of doubles} \
+ {expr 1e123} \
+ 9.9999999999999998e+122
+test util-16.1.17.124 {8.4 compatible formatting of doubles} \
+ {expr 1e124} \
+ 9.9999999999999995e+123
+test util-16.1.17.125 {8.4 compatible formatting of doubles} \
+ {expr 1e125} \
+ 9.9999999999999992e+124
+test util-16.1.17.126 {8.4 compatible formatting of doubles} \
+ {expr 1e126} \
+ 9.9999999999999992e+125
+test util-16.1.17.127 {8.4 compatible formatting of doubles} \
+ {expr 1e127} \
+ 9.9999999999999995e+126
+test util-16.1.17.128 {8.4 compatible formatting of doubles} \
+ {expr 1e128} \
+ 1.0000000000000001e+128
+test util-16.1.17.129 {8.4 compatible formatting of doubles} \
+ {expr 1e129} \
+ 1e+129
+test util-16.1.17.130 {8.4 compatible formatting of doubles} \
+ {expr 1e130} \
+ 1.0000000000000001e+130
+test util-16.1.17.131 {8.4 compatible formatting of doubles} \
+ {expr 1e131} \
+ 9.9999999999999991e+130
+test util-16.1.17.132 {8.4 compatible formatting of doubles} \
+ {expr 1e132} \
+ 9.9999999999999999e+131
+test util-16.1.17.133 {8.4 compatible formatting of doubles} \
+ {expr 1e133} \
+ 1e+133
+test util-16.1.17.134 {8.4 compatible formatting of doubles} \
+ {expr 1e134} \
+ 9.9999999999999992e+133
+test util-16.1.17.135 {8.4 compatible formatting of doubles} \
+ {expr 1e135} \
+ 9.9999999999999996e+134
+test util-16.1.17.136 {8.4 compatible formatting of doubles} \
+ {expr 1e136} \
+ 1.0000000000000001e+136
+test util-16.1.17.137 {8.4 compatible formatting of doubles} \
+ {expr 1e137} \
+ 1e+137
+test util-16.1.17.138 {8.4 compatible formatting of doubles} \
+ {expr 1e138} \
+ 1e+138
+test util-16.1.17.139 {8.4 compatible formatting of doubles} \
+ {expr 1e139} \
+ 1e+139
+test util-16.1.17.140 {8.4 compatible formatting of doubles} \
+ {expr 1e140} \
+ 1.0000000000000001e+140
+test util-16.1.17.141 {8.4 compatible formatting of doubles} \
+ {expr 1e141} \
+ 1e+141
+test util-16.1.17.142 {8.4 compatible formatting of doubles} \
+ {expr 1e142} \
+ 1.0000000000000001e+142
+test util-16.1.17.143 {8.4 compatible formatting of doubles} \
+ {expr 1e143} \
+ 1e+143
+test util-16.1.17.144 {8.4 compatible formatting of doubles} \
+ {expr 1e144} \
+ 1e+144
+test util-16.1.17.145 {8.4 compatible formatting of doubles} \
+ {expr 1e145} \
+ 9.9999999999999999e+144
+test util-16.1.17.146 {8.4 compatible formatting of doubles} \
+ {expr 1e146} \
+ 9.9999999999999993e+145
+test util-16.1.17.147 {8.4 compatible formatting of doubles} \
+ {expr 1e147} \
+ 9.9999999999999998e+146
+test util-16.1.17.148 {8.4 compatible formatting of doubles} \
+ {expr 1e148} \
+ 1e+148
+test util-16.1.17.149 {8.4 compatible formatting of doubles} \
+ {expr 1e149} \
+ 1e+149
+test util-16.1.17.150 {8.4 compatible formatting of doubles} \
+ {expr 1e150} \
+ 9.9999999999999998e+149
+test util-16.1.17.151 {8.4 compatible formatting of doubles} \
+ {expr 1e151} \
+ 1e+151
+test util-16.1.17.152 {8.4 compatible formatting of doubles} \
+ {expr 1e152} \
+ 1e+152
+test util-16.1.17.153 {8.4 compatible formatting of doubles} \
+ {expr 1e153} \
+ 1e+153
+test util-16.1.17.154 {8.4 compatible formatting of doubles} \
+ {expr 1e154} \
+ 1e+154
+test util-16.1.17.155 {8.4 compatible formatting of doubles} \
+ {expr 1e155} \
+ 1e+155
+test util-16.1.17.156 {8.4 compatible formatting of doubles} \
+ {expr 1e156} \
+ 9.9999999999999998e+155
+test util-16.1.17.157 {8.4 compatible formatting of doubles} \
+ {expr 1e157} \
+ 9.9999999999999998e+156
+test util-16.1.17.158 {8.4 compatible formatting of doubles} \
+ {expr 1e158} \
+ 9.9999999999999995e+157
+test util-16.1.17.159 {8.4 compatible formatting of doubles} \
+ {expr 1e159} \
+ 9.9999999999999993e+158
+test util-16.1.17.160 {8.4 compatible formatting of doubles} \
+ {expr 1e160} \
+ 1e+160
+test util-16.1.17.161 {8.4 compatible formatting of doubles} \
+ {expr 1e161} \
+ 1e+161
+test util-16.1.17.162 {8.4 compatible formatting of doubles} \
+ {expr 1e162} \
+ 9.9999999999999994e+161
+test util-16.1.17.163 {8.4 compatible formatting of doubles} \
+ {expr 1e163} \
+ 9.9999999999999994e+162
+test util-16.1.17.164 {8.4 compatible formatting of doubles} \
+ {expr 1e164} \
+ 1e+164
+test util-16.1.17.165 {8.4 compatible formatting of doubles} \
+ {expr 1e165} \
+ 9.999999999999999e+164
+test util-16.1.17.166 {8.4 compatible formatting of doubles} \
+ {expr 1e166} \
+ 9.9999999999999994e+165
+test util-16.1.17.167 {8.4 compatible formatting of doubles} \
+ {expr 1e167} \
+ 1e+167
+test util-16.1.17.168 {8.4 compatible formatting of doubles} \
+ {expr 1e168} \
+ 9.9999999999999993e+167
+test util-16.1.17.169 {8.4 compatible formatting of doubles} \
+ {expr 1e169} \
+ 9.9999999999999993e+168
+test util-16.1.17.170 {8.4 compatible formatting of doubles} \
+ {expr 1e170} \
+ 1e+170
+test util-16.1.17.171 {8.4 compatible formatting of doubles} \
+ {expr 1e171} \
+ 9.9999999999999995e+170
+test util-16.1.17.172 {8.4 compatible formatting of doubles} \
+ {expr 1e172} \
+ 1.0000000000000001e+172
+test util-16.1.17.173 {8.4 compatible formatting of doubles} \
+ {expr 1e173} \
+ 1e+173
+test util-16.1.17.174 {8.4 compatible formatting of doubles} \
+ {expr 1e174} \
+ 1.0000000000000001e+174
+test util-16.1.17.175 {8.4 compatible formatting of doubles} \
+ {expr 1e175} \
+ 9.9999999999999994e+174
+test util-16.1.17.176 {8.4 compatible formatting of doubles} \
+ {expr 1e176} \
+ 1e+176
+test util-16.1.17.177 {8.4 compatible formatting of doubles} \
+ {expr 1e177} \
+ 1e+177
+test util-16.1.17.178 {8.4 compatible formatting of doubles} \
+ {expr 1e178} \
+ 1.0000000000000001e+178
+test util-16.1.17.179 {8.4 compatible formatting of doubles} \
+ {expr 1e179} \
+ 9.9999999999999998e+178
+test util-16.1.17.180 {8.4 compatible formatting of doubles} \
+ {expr 1e180} \
+ 1e+180
+test util-16.1.17.181 {8.4 compatible formatting of doubles} \
+ {expr 1e181} \
+ 9.9999999999999992e+180
+test util-16.1.17.182 {8.4 compatible formatting of doubles} \
+ {expr 1e182} \
+ 1.0000000000000001e+182
+test util-16.1.17.183 {8.4 compatible formatting of doubles} \
+ {expr 1e183} \
+ 9.9999999999999995e+182
+test util-16.1.17.184 {8.4 compatible formatting of doubles} \
+ {expr 1e184} \
+ 1e+184
+test util-16.1.17.185 {8.4 compatible formatting of doubles} \
+ {expr 1e185} \
+ 9.9999999999999998e+184
+test util-16.1.17.186 {8.4 compatible formatting of doubles} \
+ {expr 1e186} \
+ 9.9999999999999998e+185
+test util-16.1.17.187 {8.4 compatible formatting of doubles} \
+ {expr 1e187} \
+ 9.9999999999999991e+186
+test util-16.1.17.188 {8.4 compatible formatting of doubles} \
+ {expr 1e188} \
+ 1e+188
+test util-16.1.17.189 {8.4 compatible formatting of doubles} \
+ {expr 1e189} \
+ 1e+189
+test util-16.1.17.190 {8.4 compatible formatting of doubles} \
+ {expr 1e190} \
+ 1.0000000000000001e+190
+test util-16.1.17.191 {8.4 compatible formatting of doubles} \
+ {expr 1e191} \
+ 1.0000000000000001e+191
+test util-16.1.17.192 {8.4 compatible formatting of doubles} \
+ {expr 1e192} \
+ 1e+192
+test util-16.1.17.193 {8.4 compatible formatting of doubles} \
+ {expr 1e193} \
+ 1.0000000000000001e+193
+test util-16.1.17.194 {8.4 compatible formatting of doubles} \
+ {expr 1e194} \
+ 9.9999999999999994e+193
+test util-16.1.17.195 {8.4 compatible formatting of doubles} \
+ {expr 1e195} \
+ 9.9999999999999998e+194
+test util-16.1.17.196 {8.4 compatible formatting of doubles} \
+ {expr 1e196} \
+ 9.9999999999999995e+195
+test util-16.1.17.197 {8.4 compatible formatting of doubles} \
+ {expr 1e197} \
+ 9.9999999999999995e+196
+test util-16.1.17.198 {8.4 compatible formatting of doubles} \
+ {expr 1e198} \
+ 1e+198
+test util-16.1.17.199 {8.4 compatible formatting of doubles} \
+ {expr 1e199} \
+ 1.0000000000000001e+199
+test util-16.1.17.200 {8.4 compatible formatting of doubles} \
+ {expr 1e200} \
+ 9.9999999999999997e+199
+test util-16.1.17.201 {8.4 compatible formatting of doubles} \
+ {expr 1e201} \
+ 1e+201
+test util-16.1.17.202 {8.4 compatible formatting of doubles} \
+ {expr 1e202} \
+ 9.999999999999999e+201
+test util-16.1.17.203 {8.4 compatible formatting of doubles} \
+ {expr 1e203} \
+ 9.9999999999999999e+202
+test util-16.1.17.204 {8.4 compatible formatting of doubles} \
+ {expr 1e204} \
+ 9.9999999999999999e+203
+test util-16.1.17.205 {8.4 compatible formatting of doubles} \
+ {expr 1e205} \
+ 1e+205
+test util-16.1.17.206 {8.4 compatible formatting of doubles} \
+ {expr 1e206} \
+ 1e+206
+test util-16.1.17.207 {8.4 compatible formatting of doubles} \
+ {expr 1e207} \
+ 1e+207
+test util-16.1.17.208 {8.4 compatible formatting of doubles} \
+ {expr 1e208} \
+ 9.9999999999999998e+207
+test util-16.1.17.209 {8.4 compatible formatting of doubles} \
+ {expr 1e209} \
+ 1.0000000000000001e+209
+test util-16.1.17.210 {8.4 compatible formatting of doubles} \
+ {expr 1e210} \
+ 9.9999999999999993e+209
+test util-16.1.17.211 {8.4 compatible formatting of doubles} \
+ {expr 1e211} \
+ 9.9999999999999996e+210
+test util-16.1.17.212 {8.4 compatible formatting of doubles} \
+ {expr 1e212} \
+ 9.9999999999999991e+211
+test util-16.1.17.213 {8.4 compatible formatting of doubles} \
+ {expr 1e213} \
+ 9.9999999999999998e+212
+test util-16.1.17.214 {8.4 compatible formatting of doubles} \
+ {expr 1e214} \
+ 9.9999999999999995e+213
+test util-16.1.17.215 {8.4 compatible formatting of doubles} \
+ {expr 1e215} \
+ 9.9999999999999991e+214
+test util-16.1.17.216 {8.4 compatible formatting of doubles} \
+ {expr 1e216} \
+ 1e+216
+test util-16.1.17.217 {8.4 compatible formatting of doubles} \
+ {expr 1e217} \
+ 9.9999999999999996e+216
+test util-16.1.17.218 {8.4 compatible formatting of doubles} \
+ {expr 1e218} \
+ 1.0000000000000001e+218
+test util-16.1.17.219 {8.4 compatible formatting of doubles} \
+ {expr 1e219} \
+ 9.9999999999999997e+218
+test util-16.1.17.220 {8.4 compatible formatting of doubles} \
+ {expr 1e220} \
+ 1e+220
+test util-16.1.17.221 {8.4 compatible formatting of doubles} \
+ {expr 1e221} \
+ 1e+221
+test util-16.1.17.222 {8.4 compatible formatting of doubles} \
+ {expr 1e222} \
+ 1e+222
+test util-16.1.17.223 {8.4 compatible formatting of doubles} \
+ {expr 1e223} \
+ 1e+223
+test util-16.1.17.224 {8.4 compatible formatting of doubles} \
+ {expr 1e224} \
+ 9.9999999999999997e+223
+test util-16.1.17.225 {8.4 compatible formatting of doubles} \
+ {expr 1e225} \
+ 9.9999999999999993e+224
+test util-16.1.17.226 {8.4 compatible formatting of doubles} \
+ {expr 1e226} \
+ 9.9999999999999996e+225
+test util-16.1.17.227 {8.4 compatible formatting of doubles} \
+ {expr 1e227} \
+ 1.0000000000000001e+227
+test util-16.1.17.228 {8.4 compatible formatting of doubles} \
+ {expr 1e228} \
+ 9.9999999999999992e+227
+test util-16.1.17.229 {8.4 compatible formatting of doubles} \
+ {expr 1e229} \
+ 9.9999999999999999e+228
+test util-16.1.17.230 {8.4 compatible formatting of doubles} \
+ {expr 1e230} \
+ 1.0000000000000001e+230
+test util-16.1.17.231 {8.4 compatible formatting of doubles} \
+ {expr 1e231} \
+ 1.0000000000000001e+231
+test util-16.1.17.232 {8.4 compatible formatting of doubles} \
+ {expr 1e232} \
+ 1.0000000000000001e+232
+test util-16.1.17.233 {8.4 compatible formatting of doubles} \
+ {expr 1e233} \
+ 9.9999999999999997e+232
+test util-16.1.17.234 {8.4 compatible formatting of doubles} \
+ {expr 1e234} \
+ 1e+234
+test util-16.1.17.235 {8.4 compatible formatting of doubles} \
+ {expr 1e235} \
+ 1.0000000000000001e+235
+test util-16.1.17.236 {8.4 compatible formatting of doubles} \
+ {expr 1e236} \
+ 1.0000000000000001e+236
+test util-16.1.17.237 {8.4 compatible formatting of doubles} \
+ {expr 1e237} \
+ 9.9999999999999994e+236
+test util-16.1.17.238 {8.4 compatible formatting of doubles} \
+ {expr 1e238} \
+ 1e+238
+test util-16.1.17.239 {8.4 compatible formatting of doubles} \
+ {expr 1e239} \
+ 9.9999999999999999e+238
+test util-16.1.17.240 {8.4 compatible formatting of doubles} \
+ {expr 1e240} \
+ 1e+240
+test util-16.1.17.241 {8.4 compatible formatting of doubles} \
+ {expr 1e241} \
+ 1.0000000000000001e+241
+test util-16.1.17.242 {8.4 compatible formatting of doubles} \
+ {expr 1e242} \
+ 1.0000000000000001e+242
+test util-16.1.17.243 {8.4 compatible formatting of doubles} \
+ {expr 1e243} \
+ 1.0000000000000001e+243
+test util-16.1.17.244 {8.4 compatible formatting of doubles} \
+ {expr 1e244} \
+ 1.0000000000000001e+244
+test util-16.1.17.245 {8.4 compatible formatting of doubles} \
+ {expr 1e245} \
+ 1e+245
+test util-16.1.17.246 {8.4 compatible formatting of doubles} \
+ {expr 1e246} \
+ 1.0000000000000001e+246
+test util-16.1.17.247 {8.4 compatible formatting of doubles} \
+ {expr 1e247} \
+ 9.9999999999999995e+246
+test util-16.1.17.248 {8.4 compatible formatting of doubles} \
+ {expr 1e248} \
+ 1e+248
+test util-16.1.17.249 {8.4 compatible formatting of doubles} \
+ {expr 1e249} \
+ 9.9999999999999992e+248
+test util-16.1.17.250 {8.4 compatible formatting of doubles} \
+ {expr 1e250} \
+ 9.9999999999999992e+249
+test util-16.1.17.251 {8.4 compatible formatting of doubles} \
+ {expr 1e251} \
+ 1e+251
+test util-16.1.17.252 {8.4 compatible formatting of doubles} \
+ {expr 1e252} \
+ 1.0000000000000001e+252
+test util-16.1.17.253 {8.4 compatible formatting of doubles} \
+ {expr 1e253} \
+ 9.9999999999999994e+252
+test util-16.1.17.254 {8.4 compatible formatting of doubles} \
+ {expr 1e254} \
+ 9.9999999999999994e+253
+test util-16.1.17.255 {8.4 compatible formatting of doubles} \
+ {expr 1e255} \
+ 9.9999999999999999e+254
+test util-16.1.17.256 {8.4 compatible formatting of doubles} \
+ {expr 1e256} \
+ 1e+256
+test util-16.1.17.257 {8.4 compatible formatting of doubles} \
+ {expr 1e257} \
+ 1e+257
+test util-16.1.17.258 {8.4 compatible formatting of doubles} \
+ {expr 1e258} \
+ 1.0000000000000001e+258
+test util-16.1.17.259 {8.4 compatible formatting of doubles} \
+ {expr 1e259} \
+ 9.9999999999999993e+258
+test util-16.1.17.260 {8.4 compatible formatting of doubles} \
+ {expr 1e260} \
+ 1.0000000000000001e+260
+test util-16.1.17.261 {8.4 compatible formatting of doubles} \
+ {expr 1e261} \
+ 9.9999999999999993e+260
+test util-16.1.17.262 {8.4 compatible formatting of doubles} \
+ {expr 1e262} \
+ 1e+262
+test util-16.1.17.263 {8.4 compatible formatting of doubles} \
+ {expr 1e263} \
+ 1e+263
+test util-16.1.17.264 {8.4 compatible formatting of doubles} \
+ {expr 1e264} \
+ 1e+264
+test util-16.1.17.265 {8.4 compatible formatting of doubles} \
+ {expr 1e265} \
+ 1.0000000000000001e+265
+test util-16.1.17.266 {8.4 compatible formatting of doubles} \
+ {expr 1e266} \
+ 1e+266
+test util-16.1.17.267 {8.4 compatible formatting of doubles} \
+ {expr 1e267} \
+ 9.9999999999999997e+266
+test util-16.1.17.268 {8.4 compatible formatting of doubles} \
+ {expr 1e268} \
+ 9.9999999999999997e+267
+test util-16.1.17.269 {8.4 compatible formatting of doubles} \
+ {expr 1e269} \
+ 1e+269
+test util-16.1.17.270 {8.4 compatible formatting of doubles} \
+ {expr 1e270} \
+ 1e+270
+test util-16.1.17.271 {8.4 compatible formatting of doubles} \
+ {expr 1e271} \
+ 9.9999999999999995e+270
+test util-16.1.17.272 {8.4 compatible formatting of doubles} \
+ {expr 1e272} \
+ 1.0000000000000001e+272
+test util-16.1.17.273 {8.4 compatible formatting of doubles} \
+ {expr 1e273} \
+ 9.9999999999999995e+272
+test util-16.1.17.274 {8.4 compatible formatting of doubles} \
+ {expr 1e274} \
+ 9.9999999999999992e+273
+test util-16.1.17.275 {8.4 compatible formatting of doubles} \
+ {expr 1e275} \
+ 9.9999999999999996e+274
+test util-16.1.17.276 {8.4 compatible formatting of doubles} \
+ {expr 1e276} \
+ 1.0000000000000001e+276
+test util-16.1.17.277 {8.4 compatible formatting of doubles} \
+ {expr 1e277} \
+ 1e+277
+test util-16.1.17.278 {8.4 compatible formatting of doubles} \
+ {expr 1e278} \
+ 9.9999999999999996e+277
+test util-16.1.17.279 {8.4 compatible formatting of doubles} \
+ {expr 1e279} \
+ 1.0000000000000001e+279
+test util-16.1.17.280 {8.4 compatible formatting of doubles} \
+ {expr 1e280} \
+ 1e+280
+test util-16.1.17.281 {8.4 compatible formatting of doubles} \
+ {expr 1e281} \
+ 1e+281
+test util-16.1.17.282 {8.4 compatible formatting of doubles} \
+ {expr 1e282} \
+ 1e+282
+test util-16.1.17.283 {8.4 compatible formatting of doubles} \
+ {expr 1e283} \
+ 9.9999999999999996e+282
+test util-16.1.17.284 {8.4 compatible formatting of doubles} \
+ {expr 1e284} \
+ 1.0000000000000001e+284
+test util-16.1.17.285 {8.4 compatible formatting of doubles} \
+ {expr 1e285} \
+ 9.9999999999999998e+284
+test util-16.1.17.286 {8.4 compatible formatting of doubles} \
+ {expr 1e286} \
+ 1e+286
+test util-16.1.17.287 {8.4 compatible formatting of doubles} \
+ {expr 1e287} \
+ 1.0000000000000001e+287
+test util-16.1.17.288 {8.4 compatible formatting of doubles} \
+ {expr 1e288} \
+ 1e+288
+test util-16.1.17.289 {8.4 compatible formatting of doubles} \
+ {expr 1e289} \
+ 1.0000000000000001e+289
+test util-16.1.17.290 {8.4 compatible formatting of doubles} \
+ {expr 1e290} \
+ 1.0000000000000001e+290
+test util-16.1.17.291 {8.4 compatible formatting of doubles} \
+ {expr 1e291} \
+ 9.9999999999999996e+290
+test util-16.1.17.292 {8.4 compatible formatting of doubles} \
+ {expr 1e292} \
+ 1e+292
+test util-16.1.17.293 {8.4 compatible formatting of doubles} \
+ {expr 1e293} \
+ 9.9999999999999992e+292
+test util-16.1.17.294 {8.4 compatible formatting of doubles} \
+ {expr 1e294} \
+ 1.0000000000000001e+294
+test util-16.1.17.295 {8.4 compatible formatting of doubles} \
+ {expr 1e295} \
+ 9.9999999999999998e+294
+test util-16.1.17.296 {8.4 compatible formatting of doubles} \
+ {expr 1e296} \
+ 9.9999999999999998e+295
+test util-16.1.17.297 {8.4 compatible formatting of doubles} \
+ {expr 1e297} \
+ 1e+297
+test util-16.1.17.298 {8.4 compatible formatting of doubles} \
+ {expr 1e298} \
+ 9.9999999999999996e+297
+test util-16.1.17.299 {8.4 compatible formatting of doubles} \
+ {expr 1e299} \
+ 1.0000000000000001e+299
+test util-16.1.17.300 {8.4 compatible formatting of doubles} \
+ {expr 1e300} \
+ 1.0000000000000001e+300
+test util-16.1.17.301 {8.4 compatible formatting of doubles} \
+ {expr 1e301} \
+ 1.0000000000000001e+301
+test util-16.1.17.302 {8.4 compatible formatting of doubles} \
+ {expr 1e302} \
+ 1.0000000000000001e+302
+test util-16.1.17.303 {8.4 compatible formatting of doubles} \
+ {expr 1e303} \
+ 1e+303
+test util-16.1.17.304 {8.4 compatible formatting of doubles} \
+ {expr 1e304} \
+ 9.9999999999999994e+303
+test util-16.1.17.305 {8.4 compatible formatting of doubles} \
+ {expr 1e305} \
+ 9.9999999999999994e+304
+test util-16.1.17.306 {8.4 compatible formatting of doubles} \
+ {expr 1e306} \
+ 1e+306
+test util-16.1.17.307 {8.4 compatible formatting of doubles} \
+ {expr 1e307} \
+ 9.9999999999999999e+306
+
+test util-17.1 {bankers' rounding [Bug 3349507]} {ieeeFloatingPoint} {
+ set r {}
+ foreach {input} {
+ 0x1ffffffffffffc000
+ 0x1ffffffffffffc800
+ 0x1ffffffffffffd000
+ 0x1ffffffffffffd800
+ 0x1ffffffffffffe000
+ 0x1ffffffffffffe800
+ 0x1fffffffffffff000
+ 0x1fffffffffffff800
+ } {
+ binary scan [binary format q [expr double($input)]] wu x
+ lappend r [format %#llx $x]
+ binary scan [binary format q [expr double(-$input)]] wu x
+ lappend r [format %#llx $x]
+ }
+ set r
+} [list {*}{
+ 0x43fffffffffffffc 0xc3fffffffffffffc
+ 0x43fffffffffffffc 0xc3fffffffffffffc
+ 0x43fffffffffffffd 0xc3fffffffffffffd
+ 0x43fffffffffffffe 0xc3fffffffffffffe
+ 0x43fffffffffffffe 0xc3fffffffffffffe
+ 0x43fffffffffffffe 0xc3fffffffffffffe
+ 0x43ffffffffffffff 0xc3ffffffffffffff
+ 0x4400000000000000 0xc400000000000000
+}]
+
+set ::tcl_precision $saved_precision
# cleanup
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/var.test b/tests/var.test
index af3d22c..45b7207 100644
--- a/tests/var.test
+++ b/tests/var.test
@@ -19,6 +19,10 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
+testConstraint testupvar [llength [info commands testupvar]]
+testConstraint testgetvarfullname [llength [info commands testgetvarfullname]]
+testConstraint testsetnoerr [llength [info commands testsetnoerr]]
+
catch {rename p ""}
catch {namespace delete test_ns_var}
catch {unset xx}
@@ -27,7 +31,7 @@ catch {unset y}
catch {unset i}
catch {unset a}
catch {unset arr}
-
+
test var-1.1 {TclLookupVar, Array handling} {
catch {unset a}
set x "incr" ;# force no compilation and runtime call to Tcl_IncrCmd
@@ -199,30 +203,28 @@ test var-3.2 {MakeUpvar, other var has TCL_NAMESPACE_ONLY specified} {
p
}
} {1998}
-if {[info commands testupvar] != {}} {
- test var-3.3 {MakeUpvar, my var has TCL_GLOBAL_ONLY specified} {
- catch {unset a}
- set a 123321
- proc p {} {
- # create global xx linked to global a
- testupvar 1 a {} xx global
+test var-3.3 {MakeUpvar, my var has TCL_GLOBAL_ONLY specified} testupvar {
+ catch {unset a}
+ set a 123321
+ proc p {} {
+ # create global xx linked to global a
+ testupvar 1 a {} xx global
+ }
+ list [p] $xx [set xx 789] $a
+} {{} 123321 789 789}
+test var-3.4 {MakeUpvar, my var has TCL_NAMESPACE_ONLY specified} testupvar {
+ catch {unset a}
+ set a 456
+ namespace eval test_ns_var {
+ catch {unset ::test_ns_var::vv}
+ proc p {} {
+ # create namespace var vv linked to global a
+ testupvar 1 a {} vv namespace
}
- list [p] $xx [set xx 789] $a
- } {{} 123321 789 789}
- test var-3.4 {MakeUpvar, my var has TCL_NAMESPACE_ONLY specified} {
- catch {unset a}
- set a 456
- namespace eval test_ns_var {
- catch {unset ::test_ns_var::vv}
- proc p {} {
- # create namespace var vv linked to global a
- testupvar 1 a {} vv namespace
- }
- p
- }
- list $test_ns_var::vv [set test_ns_var::vv 123] $a
- } {456 123 123}
-}
+ p
+ }
+ list $test_ns_var::vv [set test_ns_var::vv 123] $a
+} {456 123 123}
test var-3.5 {MakeUpvar, no call frame so my var will be in global :: ns} {
catch {unset aaaaa}
catch {unset xxxxx}
@@ -269,25 +271,28 @@ test var-3.10 {MakeUpvar, } {
set msg
}
} {1 1}
+test var-3.11 {MakeUpvar, my var looks like array elem} -body {
+ catch {unset aaaaa}
+ set aaaaa 789789
+ upvar #0 aaaaa foo(bar)
+} -returnCodes 1 -result {bad variable name "foo(bar)": upvar won't create a scalar variable that looks like an array element}
-if {[info commands testgetvarfullname] != {}} {
- test var-4.1 {Tcl_GetVariableName, global variable} {
- catch {unset a}
- set a 123
- testgetvarfullname a global
- } ::a
- test var-4.2 {Tcl_GetVariableName, namespace variable} {
- namespace eval test_ns_var {
- variable george
- testgetvarfullname george namespace
- }
- } ::test_ns_var::george
- test var-4.3 {Tcl_GetVariableName, variable can't be array element} {
- catch {unset a}
- set a(1) foo
- list [catch {testgetvarfullname a(1) global} msg] $msg
- } {1 {unknown variable "a(1)"}}
-}
+test var-4.1 {Tcl_GetVariableName, global variable} testgetvarfullname {
+ catch {unset a}
+ set a 123
+ testgetvarfullname a global
+} ::a
+test var-4.2 {Tcl_GetVariableName, namespace variable} testgetvarfullname {
+ namespace eval test_ns_var {
+ variable george
+ testgetvarfullname george namespace
+ }
+} ::test_ns_var::george
+test var-4.3 {Tcl_GetVariableName, variable can't be array element} testgetvarfullname {
+ catch {unset a}
+ set a(1) foo
+ list [catch {testgetvarfullname a(1) global} msg] $msg
+} {1 {unknown variable "a(1)"}}
test var-5.1 {Tcl_GetVariableFullName, global variable} {
catch {unset a}
@@ -519,11 +524,23 @@ test var-8.1 {TclDeleteVars, "unset" traces are called with fully-qualified var
list [unset test_ns_var::v] $test_ns_var::info
} {{} {test_ns_var::v {} u}}
-if {[info commands testsetnoerr] == {}} {
- puts "This application hasn't been compiled with the \"testsetnoerr\""
- puts "command, so I can't test TclSetVar etc."
-} else {
-test var-9.1 {behaviour of TclGet/SetVar simple get/set} {
+test var-8.2 {TclDeleteNamespaceVars, "unset" traces on ns delete are called with fully-qualified var names} {
+ catch {namespace delete test_ns_var}
+ catch {unset a}
+ set info ""
+ namespace eval test_ns_var {
+ variable v 123 1
+ trace var v u ::traceUnset
+ }
+
+ proc traceUnset {name1 name2 op} {
+ set ::info [concat $::info [list $name1 $name2 $op]]
+ }
+
+ list [namespace delete test_ns_var] $::info
+} {{} {::test_ns_var::v {} u}}
+
+test var-9.1 {behaviour of TclGet/SetVar simple get/set} testsetnoerr {
catch {unset u}; catch {unset v}
list \
[set u a; testsetnoerr u] \
@@ -531,7 +548,7 @@ test var-9.1 {behaviour of TclGet/SetVar simple get/set} {
[testseterr u] \
[unset v; testseterr v b]
} [list {before get a} {before set b} {before get a} {before set b}]
-test var-9.2 {behaviour of TclGet/SetVar namespace get/set} {
+test var-9.2 {behaviour of TclGet/SetVar namespace get/set} testsetnoerr {
catch {namespace delete ns}
namespace eval ns {variable u a; variable v}
list \
@@ -540,46 +557,46 @@ test var-9.2 {behaviour of TclGet/SetVar namespace get/set} {
[testseterr ns::u] \
[unset ns::v; testseterr ns::v b]
} [list {before get a} {before set b} {before get a} {before set b}]
-test var-9.3 {behaviour of TclGetVar no variable} {
+test var-9.3 {behaviour of TclGetVar no variable} testsetnoerr {
catch {unset u}
list \
[catch {testsetnoerr u} res] $res \
[catch {testseterr u} res] $res
} {1 {before get} 1 {can't read "u": no such variable}}
-test var-9.4 {behaviour of TclGetVar no namespace variable} {
+test var-9.4 {behaviour of TclGetVar no namespace variable} testsetnoerr {
catch {namespace delete ns}
namespace eval ns {}
list \
[catch {testsetnoerr ns::w} res] $res \
[catch {testseterr ns::w} res] $res
} {1 {before get} 1 {can't read "ns::w": no such variable}}
-test var-9.5 {behaviour of TclGetVar no namespace} {
+test var-9.5 {behaviour of TclGetVar no namespace} testsetnoerr {
catch {namespace delete ns}
list \
[catch {testsetnoerr ns::u} res] $res \
[catch {testseterr ns::v} res] $res
} {1 {before get} 1 {can't read "ns::v": no such variable}}
-test var-9.6 {behaviour of TclSetVar no namespace} {
+test var-9.6 {behaviour of TclSetVar no namespace} testsetnoerr {
catch {namespace delete ns}
list \
[catch {testsetnoerr ns::v 1} res] $res \
[catch {testseterr ns::v 1} res] $res
} {1 {before set} 1 {can't set "ns::v": parent namespace doesn't exist}}
-test var-9.7 {behaviour of TclGetVar array variable} {
+test var-9.7 {behaviour of TclGetVar array variable} testsetnoerr {
catch {unset arr}
set arr(1) 1;
list \
[catch {testsetnoerr arr} res] $res \
[catch {testseterr arr} res] $res
} {1 {before get} 1 {can't read "arr": variable is array}}
-test var-9.8 {behaviour of TclSetVar array variable} {
+test var-9.8 {behaviour of TclSetVar array variable} testsetnoerr {
catch {unset arr}
set arr(1) 1
list \
[catch {testsetnoerr arr 2} res] $res \
[catch {testseterr arr 2} res] $res
} {1 {before set} 1 {can't set "arr": variable is array}}
-test var-9.9 {behaviour of TclGetVar read trace success} {
+test var-9.9 {behaviour of TclGetVar read trace success} testsetnoerr {
proc resetvar {val name elem op} {upvar 1 $name v; set v $val}
catch {unset u}; catch {unset v}
set u 10
@@ -589,7 +606,7 @@ test var-9.9 {behaviour of TclGetVar read trace success} {
[testsetnoerr u] \
[testseterr v]
} {{before get 1} {before get 2}}
-test var-9.10 {behaviour of TclGetVar read trace error} {
+test var-9.10 {behaviour of TclGetVar read trace error} testsetnoerr {
proc writeonly args {error "write-only"}
set v 456
trace var v r writeonly
@@ -597,7 +614,7 @@ test var-9.10 {behaviour of TclGetVar read trace error} {
[catch {testsetnoerr v} msg] $msg \
[catch {testseterr v} msg] $msg
} {1 {before get} 1 {can't read "v": write-only}}
-test var-9.11 {behaviour of TclSetVar write trace success} {
+test var-9.11 {behaviour of TclSetVar write trace success} testsetnoerr {
proc doubleval {name elem op} {upvar 1 $name v; set v [expr {2 * $v}]}
catch {unset u}; catch {unset v}
set v 1
@@ -607,7 +624,7 @@ test var-9.11 {behaviour of TclSetVar write trace success} {
[testsetnoerr u 2] \
[testseterr v 3]
} {{before set 4} {before set 6}}
-test var-9.12 {behaviour of TclSetVar write trace error} {
+test var-9.12 {behaviour of TclSetVar write trace error} testsetnoerr {
proc readonly args {error "read-only"}
set v 456
trace var v w readonly
@@ -615,12 +632,11 @@ test var-9.12 {behaviour of TclSetVar write trace error} {
[catch {testsetnoerr v 2} msg] $msg $v \
[catch {testseterr v 3} msg] $msg $v
} {1 {before set} 2 1 {can't set "v": read-only} 3}
-}
+
test var-10.1 {can't nest arrays with array set} {
catch {unset arr}
list [catch {array set arr(x) {a 1 b 2}} res] $res
} {1 {can't set "arr(x)": variable isn't array}}
-
test var-10.2 {can't nest arrays with array set} {
catch {unset arr}
list [catch {array set arr(x) {}} res] $res
@@ -677,6 +693,10 @@ test var-14.1 {array names syntax} -body {
array names foo bar baz snafu
} -returnCodes 1 -match glob -result *
+test var-14.2 {array names -glob} -body {
+ array names tcl_platform -glob os
+} -returnCodes 0 -match exact -result os
+
test var-15.1 {segfault in [unset], [Bug 735335]} {
proc A { name } {
upvar $name var
@@ -691,25 +711,53 @@ test var-15.1 {segfault in [unset], [Bug 735335]} {
namespace eval test unset useSomeUnlikelyNameHere
} {}
-test var-16.1 {CallVarTraces: save/restore interp error state: 1038021} {
- trace add variable errorCode write { ;#}
+
+test var-16.1 {CallVarTraces: save/restore interp error state} {
+ trace add variable ::errorCode write " ;#"
catch {error foo bar baz}
- trace remove variable errorCode write { ;#}
- set errorInfo
+ trace remove variable ::errorCode write " ;#"
+ set ::errorInfo
} bar
test var-17.1 {TclArraySet [Bug 1669489]} -setup {
unset -nocomplain ::a
} -body {
namespace eval :: {
- set elements {1 2 3 4}
- trace add variable a write {string length $elements ;#}
- array set a $elements
+ set elements {1 2 3 4}
+ trace add variable a write "string length \$elements ;#"
+ array set a $elements
}
} -cleanup {
unset -nocomplain ::a ::elements
} -result {}
+test var-18.1 {array unset and unset traces: Bug 2939073} -setup {
+ set already 0
+ unset x
+} -body {
+ array set x {e 1 i 1}
+ trace add variable x unset {apply {args {
+ global already x
+ if {!$already} {
+ set already 1
+ unset x(i)
+ }
+ }}}
+ # The next command would crash reliably with memory debugging prior to the
+ # bug fix.
+ array unset x *
+ array size x
+} -cleanup {
+ unset x already
+} -result 0
+
+
+test var-19.1 {crash when freeing locals hashtable: Bug 3037525} {
+ proc foo {} { catch {upvar 0 dummy \$index} }
+ foo ; # This crashes without the fix for the bug
+ rename foo {}
+} {}
+
catch {namespace delete ns}
catch {unset arr}
catch {unset v}
@@ -728,3 +776,7 @@ catch {unset aaaaa}
# cleanup
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/while-old.test b/tests/while-old.test
index 980b9d4..ee17d0b 100644
--- a/tests/while-old.test
+++ b/tests/while-old.test
@@ -101,7 +101,7 @@ test while-old-4.5 {errors in while loops} {
} {1 {expected boolean value but got "foo"}}
test while-old-4.6 {errors in while loops} {
set err [catch {while {1} {error "loop aborted"}} msg]
- list $err $msg $errorInfo
+ list $err $msg $::errorInfo
} {1 {loop aborted} {loop aborted
while executing
"error "loop aborted""}}
@@ -117,15 +117,3 @@ test while-old-5.2 {while return result} {
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/while.test b/tests/while.test
index bf86419..4ad966e 100644
--- a/tests/while.test
+++ b/tests/while.test
@@ -11,7 +11,7 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2
namespace import -force ::tcltest::*
}
@@ -24,14 +24,11 @@ test while-1.1 {TclCompileWhileCmd: missing test expression} {
catch {while } msg
set msg
} {wrong # args: should be "while test command"}
-test while-1.2 {TclCompileWhileCmd: error in test expression} {
+test while-1.2 {TclCompileWhileCmd: error in test expression} -body {
set i 0
catch {while {$i<} break} msg
- set errorInfo
-} {syntax error in expression "$i<": premature end of expression
- ("while" test expression)
- while compiling
-"while {$i<} break"}
+ set ::errorInfo
+} -match glob -result {*"while {$i<} break"}
test while-1.3 {TclCompileWhileCmd: error in test expression} {
set err [catch {while {"a"+"b"} {error "loop aborted"}} msg]
list $err $msg
@@ -64,16 +61,13 @@ test while-1.7 {TclCompileWhileCmd: missing command body} {
catch {while {$i < 5} } msg
set msg
} {wrong # args: should be "while test command"}
-test while-1.8 {TclCompileWhileCmd: error compiling command body} {
+test while-1.8 {TclCompileWhileCmd: error compiling command body} -body {
set i 0
catch {while {$i < 5} {set}} msg
- set errorInfo
-} {wrong # args: should be "set varName ?newValue?"
- while compiling
-"set"
- ("while" body line 1)
- while compiling
-"while {$i < 5} {set}"}
+ set ::errorInfo
+} -match glob -result {wrong # args: should be "set varName ?newValue?"
+ while *ing
+"set"*}
test while-1.9 {TclCompileWhileCmd: simple command body} {
set a {}
set i 1
@@ -303,14 +297,12 @@ test while-4.2 {while (not compiled): missing test expression} {
catch {$z } msg
set msg
} {wrong # args: should be "while test command"}
-test while-4.3 {while (not compiled): error in test expression} {
+test while-4.3 {while (not compiled): error in test expression} -body {
set i 0
set z while
catch {$z {$i<} {set x 1}} msg
- set errorInfo
-} {syntax error in expression "$i<": premature end of expression
- while executing
-"$z {$i<} {set x 1}"}
+ set ::errorInfo
+} -match glob -result {*"$z {$i<} {set x 1}"}
test while-4.4 {while (not compiled): error in test expression} {
set z while
set err [catch {$z {"a"+"b"} {error "loop aborted"}} msg]
@@ -348,13 +340,13 @@ test while-4.8 {while (not compiled): missing command body} {
catch {$z {$i < 5} } msg
set msg
} {wrong # args: should be "while test command"}
-test while-4.9 {while (not compiled): error compiling command body} {
+test while-4.9 {while (not compiled): error compiling command body} -body {
set i 0
set z while
catch {$z {$i < 5} {set}} msg
- set errorInfo
-} {wrong # args: should be "set varName ?newValue?"
- while compiling
+ set ::errorInfo
+} -match glob -result {wrong # args: should be "set varName ?newValue?"
+ while *ing
"set"
("while" body line 1)
invoked from within
diff --git a/tests/winConsole.test b/tests/winConsole.test
index a8a664c..fdde41c 100644
--- a/tests/winConsole.test
+++ b/tests/winConsole.test
@@ -15,9 +15,7 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
}
-test winConsole-1.1 {Console file channel: non-blocking gets} \
- {pcOnly interactive} {
-
+test winConsole-1.1 {Console file channel: non-blocking gets} {win interactive} {
set oldmode [fconfigure stdin]
puts stdout "Enter abcdef<return> now: " nonewline
@@ -37,7 +35,7 @@ test winConsole-1.1 {Console file channel: non-blocking gets} \
#cleanup the fileevent
fileevent stdin readable {}
- eval fconfigure stdin $oldmode
+ fconfigure stdin {*}$oldmode
set result
diff --git a/tests/winDde.test b/tests/winDde.test
index 85fb5a6..9c777c3 100644
--- a/tests/winDde.test
+++ b/tests/winDde.test
@@ -2,7 +2,7 @@
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands. Sourcing this file into Tcl runs the tests and
-# generates output for errors. No output means no errors were found.
+# generates output for errors. No output means no errors were found.
#
# Copyright (c) 1999 by Scriptics Corporation.
#
@@ -10,172 +10,438 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
+ package require tcltest 2
+ #tcltest::configure -verbose {pass start}
namespace import -force ::tcltest::*
}
-if {$tcl_platform(platform) == "windows"} {
+if {[testConstraint win]} {
if [catch {
- set lib [lindex [glob -directory [file join [pwd] [file dirname \
- [info nameofexecutable]]] tcldde*.dll] 0]
- load $lib dde
+ # Is the dde extension already static to this shell?
+ if [catch {load {} Dde; set ::ddelib {}}] {
+ # try the location given to use on the commandline to tcltest
+ ::tcltest::loadTestedCommands
+ load $::ddelib Dde
+ }
+ testConstraint dde 1
}] {
- puts "WARNING: Unable to find the dde package. Skipping dde tests."
- ::tcltest::cleanupTests
- return
+ testConstraint dde 0
}
}
-set scriptName script1.tcl
-proc createChildProcess { ddeServerName } {
+# -------------------------------------------------------------------------
+# Setup a script for a test server
+#
+
+set scriptName [makeFile {} script1.tcl]
+
+proc createChildProcess { ddeServerName {handler {}}} {
file delete -force $::scriptName
set f [open $::scriptName w+]
+ puts $f [list set ddeServerName $ddeServerName]
+ if {$::ddelib != ""} {
+ puts $f [list load $::ddelib Dde]
+ }
puts $f {
+ # DDE child server -
+ #
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
namespace import -force ::tcltest::*
}
- if [catch {
- set lib [lindex [glob -directory \
- [file join [pwd] [file dirname [info nameofexecutable]]] \
- tcldde*.dll] 0]
- load $lib dde
- }] {
- puts "Unable to find the dde package. Skipping dde tests."
- ::tcltest::cleanupTests
- return
- }
+
+ # If an error occurs during the tests, this process may end up not
+ # being closed down. To deal with this we create a 30s timeout.
+ proc ::DoTimeout {} {
+ global done ddeServerName
+ set done 1
+ puts "winDde.test child process $ddeServerName timed out."
+ flush stdout
+ }
+ set timeout [after 30000 ::DoTimeout]
+
+ # Define a restricted handler.
+ proc Handler1 {cmd} {
+ if {$cmd eq "stop"} {set ::done 1}
+ puts $cmd ; flush stdout
+ return
+ }
+ proc Handler2 {cmd} {
+ if {$cmd eq "stop"} {set ::done 1}
+ puts [uplevel \#0 $cmd] ; flush stdout
+ return
+ }
+ proc Handler3 {prefix cmd} {
+ if {$cmd eq "stop"} {set ::done 1}
+ puts [list $prefix $cmd] ; flush stdout
+ return
+ }
}
- puts $f [list dde servername $ddeServerName]
+ # set the dde server name to the supplied argument.
+ if {$handler == {}} {
+ puts $f [list dde servername $ddeServerName]
+ } else {
+ puts $f [list dde servername -handler $handler -- $ddeServerName]
+ }
puts $f {
- after 200 {set ready 1}
- vwait ready
+ # run the server and handle final cleanup.
+ after 200;# give dde a chance to get going.
puts ready
+ flush stdout
vwait done
- after 200 {set final 1}
- vwait final
+ # allow enough time for the calling process to
+ # claim all results, to avoid spurious "server did
+ # not respond"
+ after 200 { set reallyDone 1 }
+ vwait reallyDone
exit
}
close $f
+ # run the child server script.
set f [open |[list [interpreter] $::scriptName] r]
- fconfigure $f -buffering line -blocking 1
- gets $f
+ fconfigure $f -buffering line
+ gets $f line
return $f
}
-test winDde-1.1 {Settings the server's topic name} {pcOnly} {
+# -------------------------------------------------------------------------
+
+test winDde-1.1 {Settings the server's topic name} {win dde} {
list [dde servername foobar] [dde servername] [dde servername self]
} {foobar foobar self}
-test winDde-2.1 {Checking for other services} {pcOnly} {
+test winDde-2.1 {Checking for other services} {win dde} {
expr [llength [dde services {} {}]] >= 0
} 1
-
test winDde-2.2 {Checking for existence, with service and topic specified} \
- {pcOnly} {
+ {win dde} {
llength [dde services TclEval self]
} 1
-
test winDde-2.3 {Checking for existence, with only the service specified} \
- {pcOnly} {
+ {win dde} {
expr [llength [dde services TclEval {}]] >= 1
} 1
+test winDde-2.4 {Checking for existence, with only the topic specified} \
+ {win dde} {
+ expr [llength [dde services {} self]] >= 1
+} 1
-test winDde-3.1 {DDE execute locally} {pcOnly} {
+# -------------------------------------------------------------------------
+
+test winDde-3.1 {DDE execute locally} {win dde} {
set a ""
dde execute TclEval self {set a "foo"}
set a
} foo
-
-test winDde-3.2 {DDE execute -async locally} {pcOnly} {
+test winDde-3.2 {DDE execute -async locally} {win dde} {
set a ""
dde execute -async TclEval self {set a "foo"}
update
set a
} foo
-
-test winDde-3.3 {DDE request locally} {pcOnly} {
+test winDde-3.3 {DDE request locally} {win dde} {
set a ""
dde execute TclEval self {set a "foo"}
dde request TclEval self a
} foo
-
-test winDde-3.4 {DDE eval locally} {pcOnly} {
+test winDde-3.4 {DDE eval locally} {win dde} {
set a ""
dde eval self set a "foo"
} foo
-
-test winDde-3.5 {DDE request locally} {pcOnly} {
+test winDde-3.5 {DDE request locally} {win dde} {
set a ""
dde execute TclEval self {set a "foo"}
dde request -binary TclEval self a
} "foo\x00"
-test winDde-4.1 {DDE execute remotely} {stdio pcOnly} {
- list [catch {
- set a ""
- set child [createChildProcess child]
- dde execute TclEval child {set a "foo"}
- dde execute TclEval child {set done 1}
- set a
- } err] $err
-} [list 0 ""]
-
-test winDde-4.2 {DDE execute remotely} {stdio pcOnly} {
- list [catch {
- set a ""
- set child [createChildProcess child]
- dde execute -async TclEval child {set a "foo"}
- after 400 {set ::_dde_forever 1} ; vwait ::_dde_forever; #update
- dde execute TclEval child {set done 1}
- set a
- } err] $err
-} [list 0 ""]
-
-test winDde-4.3 {DDE request locally} {stdio pcOnly} {
- list [catch {
- set a ""
- set child [createChildProcess child]
- dde execute TclEval child {set a "foo"}
- set a [dde request TclEval child a]
- dde execute TclEval child {set done 1}
- set a
- } err] $err
-} [list 0 foo]
-
-test winDde-4.4 {DDE eval locally} {stdio pcOnly} {
- list [catch {
- set a ""
- set child [createChildProcess child]
- set a [dde eval child set a "foo"]
- dde execute TclEval child {set done 1}
- set a
- } err] $err
-} [list 0 foo]
-
-test winDde-5.1 {check for bad arguments} {pcOnly} {
- catch {dde execute "" "" "" ""} result
- set result
-} {wrong # args: should be "dde execute ?-async? serviceName topicName value"}
-
-test winDde-5.2 {check for bad arguments} {pcOnly} {
- catch {dde execute "" "" ""} result
- set result
-} {cannot execute null data}
-
-test winDde-5.3 {check for bad arguments} {pcOnly} {
- catch {dde execute -foo "" "" ""} result
- set result
-} {wrong # args: should be "dde execute ?-async? serviceName topicName value"}
-
-test winDde-5.4 {DDE eval bad arguments} {pcOnly} {
- list [catch {dde eval "" "foo"} msg] $msg
-} {1 {invalid service name ""}}
+# -------------------------------------------------------------------------
+
+test winDde-4.1 {DDE execute remotely} {stdio win dde} {
+ set a ""
+ set name child-4.1
+ set child [createChildProcess $name]
+ dde execute TclEval $name {set a "foo"}
+ dde execute TclEval $name {set done 1}
+ update
+ set a
+} ""
+test winDde-4.2 {DDE execute async remotely} {stdio win dde} {
+ set a ""
+ set name child-4.2
+ set child [createChildProcess $name]
+ dde execute -async TclEval $name {set a "foo"}
+ update
+ dde execute TclEval $name {set done 1}
+ update
+ set a
+} ""
+test winDde-4.3 {DDE request remotely} {stdio win dde} {
+ set a ""
+ set name chile-4.3
+ set child [createChildProcess $name]
+ dde execute TclEval $name {set a "foo"}
+ set a [dde request TclEval $name a]
+ dde execute TclEval $name {set done 1}
+ update
+ set a
+} foo
+test winDde-4.4 {DDE eval remotely} {stdio win dde} {
+ set a ""
+ set name child-4.4
+ set child [createChildProcess $name]
+ set a [dde eval $name set a "foo"]
+ dde execute TclEval $name {set done 1}
+ update
+ set a
+} foo
+
+# -------------------------------------------------------------------------
+
+test winDde-5.1 {check for bad arguments} -constraints {win dde} -body {
+ dde execute "" "" "" ""
+} -returnCodes error -result {wrong # args: should be "dde execute ?-async? serviceName topicName value"}
+test winDde-5.2 {check for bad arguments} -constraints {win dde} -body {
+ dde execute "" "" ""
+} -returnCodes error -result {cannot execute null data}
+test winDde-5.3 {check for bad arguments} -constraints {win dde} -body {
+ dde execute -foo "" "" ""
+} -returnCodes error -result {wrong # args: should be "dde execute ?-async? serviceName topicName value"}
+test winDde-5.4 {DDE eval bad arguments} -constraints {win dde} -body {
+ dde eval "" "foo"
+} -returnCodes error -result {invalid service name ""}
+
+# -------------------------------------------------------------------------
+
+test winDde-6.1 {DDE servername bad arguments} -constraints {win dde} -body {
+ dde servername -z -z -z
+} -returnCodes error -result {bad option "-z": must be -force, -handler, or --}
+test winDde-6.2 {DDE servername set name} -constraints {win dde} -body {
+ dde servername -- winDde-6.2
+} -result {winDde-6.2}
+test winDde-6.3 {DDE servername set exact name} -constraints {win dde} -body {
+ dde servername -force winDde-6.3
+} -result {winDde-6.3}
+test winDde-6.4 {DDE servername set exact name} -constraints {win dde} -body {
+ dde servername -force -- winDde-6.4
+} -result {winDde-6.4}
+test winDde-6.5 {DDE remote servername collision} -constraints {stdio win dde} -setup {
+ set name child-6.5
+ set child [createChildProcess $name]
+} -body {
+ dde servername -- $name
+} -cleanup {
+ dde execute TclEval $name {set done 1}
+ update
+} -result "child-6.5 #2"
+test winDde-6.6 {DDE remote servername collision force} -constraints {stdio win dde} -setup {
+ set name child-6.6
+ set child [createChildProcess $name]
+} -body {
+ dde servername -force -- $name
+} -cleanup {
+ dde execute TclEval $name {set done 1}
+ update
+} -result {child-6.6}
+
+# -------------------------------------------------------------------------
+
+test winDde-7.1 {Load DDE in slave interpreter } -constraints {win dde} -setup {
+ interp create slave
+} -body {
+ slave eval [list load $::ddelib Dde]
+ slave eval [list dde servername -- dde-interp-7.1]
+} -cleanup {
+ interp delete slave
+} -result {dde-interp-7.1}
+test winDde-7.2 {DDE slave cleanup} -constraints {win dde} -setup {
+ interp create slave
+ slave eval [list load $::ddelib Dde]
+ slave eval [list dde servername -- dde-interp-7.5]
+ interp delete slave
+} -body {
+ dde services TclEval {}
+ set s [dde services TclEval {}]
+ set m [list [list TclEval dde-interp-7.5]]
+ if {[lsearch -exact $s $m] != -1} {
+ set s
+ }
+} -result {}
+test winDde-7.3 {DDE present in slave interp} -constraints {win dde} -setup {
+ interp create slave
+ slave eval [list load $::ddelib Dde]
+ slave eval [list dde servername -- dde-interp-7.3]
+} -body {
+ dde services TclEval dde-interp-7.3
+} -cleanup {
+ interp delete slave
+} -result {{TclEval dde-interp-7.3}}
+test winDde-7.4 {interp name collision with -force} -constraints {win dde} -setup {
+ interp create slave
+ slave eval [list load $::ddelib Dde]
+ slave eval [list dde servername -- dde-interp-7.4]
+} -body {
+ dde servername -force -- dde-interp-7.4
+} -cleanup {
+ interp delete slave
+} -result {dde-interp-7.4}
+test winDde-7.5 {interp name collision without -force} -constraints {win dde} -setup {
+ interp create slave
+ slave eval [list load $::ddelib Dde]
+ slave eval [list dde servername -- dde-interp-7.5]
+} -body {
+ dde servername -- dde-interp-7.5
+} -cleanup {
+ interp delete slave
+} -result "dde-interp-7.5 #2"
+
+# -------------------------------------------------------------------------
+
+test winDde-8.1 {Safe DDE load} -constraints {win dde} -setup {
+ interp create -safe slave
+ slave invokehidden load $::ddelib Dde
+} -body {
+ slave eval dde servername slave
+} -cleanup {
+ interp delete slave
+} -returnCodes error -result {invalid command name "dde"}
+test winDde-8.2 {Safe DDE set servername} -constraints {win dde} -setup {
+ interp create -safe slave
+ slave invokehidden load $::ddelib Dde
+} -body {
+ slave invokehidden dde servername slave
+} -cleanup {interp delete slave} -result {slave}
+test winDde-8.3 {Safe DDE check handler required for eval} -constraints {win dde} -setup {
+ interp create -safe slave
+ slave invokehidden load $::ddelib Dde
+ slave invokehidden dde servername slave
+} -body {
+ catch {dde eval slave set a 1} msg
+} -cleanup {interp delete slave} -result {1}
+test winDde-8.4 {Safe DDE check that execute is denied} -constraints {win dde} -setup {
+ interp create -safe slave
+ slave invokehidden load $::ddelib Dde
+ slave invokehidden dde servername slave
+} -body {
+ slave eval set a 1
+ dde execute TclEval slave {set a 2}
+ slave eval set a
+} -cleanup {interp delete slave} -result 1
+test winDde-8.5 {Safe DDE check that request is denied} -constraints {win dde} -setup {
+ interp create -safe slave
+ slave invokehidden load $::ddelib Dde
+ slave invokehidden dde servername slave
+} -body {
+ slave eval set a 1
+ dde request TclEval slave a
+} -cleanup {
+ interp delete slave
+} -returnCodes error -result {remote server cannot handle this command}
+test winDde-8.6 {Safe DDE assign handler procedure} -constraints {win dde} -setup {
+ interp create -safe slave
+ slave invokehidden load $::ddelib Dde
+ slave eval {proc DDEACCEPT {cmd} {set ::DDECMD $cmd}}
+} -body {
+ slave invokehidden dde servername -handler DDEACCEPT slave
+} -cleanup {interp delete slave} -result slave
+test winDde-8.7 {Safe DDE check simple command} -constraints {win dde} -setup {
+ interp create -safe slave
+ slave invokehidden load $::ddelib Dde
+ slave eval {proc DDEACCEPT {cmd} {set ::DDECMD $cmd}}
+ slave invokehidden dde servername -handler DDEACCEPT slave
+} -body {
+ dde eval slave set x 1
+} -cleanup {interp delete slave} -result {set x 1}
+test winDde-8.8 {Safe DDE check non-list command} -constraints {win dde} -setup {
+ interp create -safe slave
+ slave invokehidden load $::ddelib Dde
+ slave eval {proc DDEACCEPT {cmd} {set ::DDECMD $cmd}}
+ slave invokehidden dde servername -handler DDEACCEPT slave
+} -body {
+ set s "c:\\Program Files\\Microsoft Visual Studio\\"
+ dde eval slave $s
+ string equal [slave eval set DDECMD] $s
+} -cleanup {interp delete slave} -result 1
+test winDde-8.9 {Safe DDE check command evaluation} -constraints {win dde} -setup {
+ interp create -safe slave
+ slave invokehidden load $::ddelib Dde
+ slave eval {proc DDEACCEPT {cmd} {set ::DDECMD [uplevel \#0 $cmd]}}
+ slave invokehidden dde servername -handler DDEACCEPT slave
+} -body {
+ dde eval slave set x 1
+ slave eval set x
+} -cleanup {interp delete slave} -result 1
+test winDde-8.10 {Safe DDE check command evaluation (2)} -constraints {win dde} -setup {
+ interp create -safe slave
+ slave invokehidden load $::ddelib Dde
+ slave eval {proc DDEACCEPT {cmd} {set ::DDECMD [uplevel \#0 $cmd]}}
+ slave invokehidden dde servername -handler DDEACCEPT slave
+} -body {
+ dde eval slave [list set x 1]
+ slave eval set x
+} -cleanup {interp delete slave} -result 1
+test winDde-8.11 {Safe DDE check command evaluation (3)} -constraints {win dde} -setup {
+ interp create -safe slave
+ slave invokehidden load $::ddelib Dde
+ slave eval {proc DDEACCEPT {cmd} {set ::DDECMD [uplevel \#0 $cmd]}}
+ slave invokehidden dde servername -handler DDEACCEPT slave
+} -body {
+ dde eval slave [list [list set x 1]]
+ slave eval set x
+} -cleanup {interp delete slave} -returnCodes error -result {invalid command name "set x 1"}
+
+# -------------------------------------------------------------------------
+
+test winDde-9.1 {External safe DDE check string passing} -constraints {win dde stdio} -setup {
+ set name child-9.1
+ set child [createChildProcess $name Handler1]
+ file copy -force script1.tcl dde-script.tcl
+} -body {
+ dde eval $name set x 1
+ gets $child line
+ set line
+} -cleanup {
+ dde execute TclEval $name stop
+ update
+ file delete -force -- dde-script.tcl
+} -result {set x 1}
+test winDde-9.2 {External safe DDE check command evaluation} -constraints {win dde stdio} -setup {
+ set name child-9.2
+ set child [createChildProcess $name Handler2]
+ file copy -force script1.tcl dde-script.tcl
+} -body {
+ dde eval $name set x 1
+ gets $child line
+ set line
+} -cleanup {
+ dde execute TclEval $name stop
+ update
+ file delete -force -- dde-script.tcl
+} -result 1
+test winDde-9.3 {External safe DDE check prefixed arguments} -constraints {win dde stdio} -setup {
+ set name child-9.3
+ set child [createChildProcess $name [list Handler3 ARG]]
+ file copy -force script1.tcl dde-script.tcl
+} -body {
+ dde eval $name set x 1
+ gets $child line
+ set line
+} -cleanup {
+ dde execute TclEval $name stop
+ update
+ file delete -force -- dde-script.tcl
+} -result {ARG {set x 1}}
+
+# -------------------------------------------------------------------------
#cleanup
+#catch {interp delete $slave}; # ensure we clean up the slave.
file delete -force $::scriptName
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/winFCmd.test b/tests/winFCmd.test
index 6461693..58a1b11 100644
--- a/tests/winFCmd.test
+++ b/tests/winFCmd.test
@@ -15,6 +15,17 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
+# Initialise the test constraints
+
+testConstraint win2000orXP 0
+testConstraint winOlderThan2000 0
+testConstraint testvolumetype [llength [info commands testvolumetype]]
+testConstraint testfile [llength [info commands testfile]]
+testConstraint testchmod [llength [info commands testchmod]]
+testConstraint cdrom 0
+testConstraint exdev 0
+testConstraint longFileNames 0
+
proc createfile {file {string a}} {
set f [open $file w]
puts -nonewline $f $string
@@ -36,46 +47,29 @@ proc cleanup {args} {
set x [glob -directory $p tf* td*]
}
if {$x != ""} {
- catch {eval file delete -force -- $x}
+ catch {file delete -force -- {*}$x}
}
}
}
-if {[string equal $tcl_platform(platform) "windows"]} {
- if {[string equal $tcl_platform(os) "Windows NT"] \
- && [string equal [string index $tcl_platform(osVersion) 0] "5"]} {
- tcltest::testConstraint win2000orXP 1
- tcltest::testConstraint winOlderThan2000 0
+if {[testConstraint winOnly]} {
+ if {[testConstraint nt] && [string index $tcl_platform(osVersion) 0]==5} {
+ # Warning: Win 6 will break this!
+ testConstraint win2000orXP 1
} else {
- tcltest::testConstraint win2000orXP 0
- tcltest::testConstraint winOlderThan2000 1
+ testConstraint winOlderThan2000 1
}
-} else {
- tcltest::testConstraint win2000orXP 0
- tcltest::testConstraint winOlderThan2000 0
}
-set ::tcltest::testConstraints(cdrom) 0
-set ::tcltest::testConstraints(exdev) 0
-
# find a CD-ROM so we can test read-only filesystems.
-set cdrom {}
-if { [info commands ::testvolumetype] ne {} } {
- foreach p {d e f g h i j k l m n o p q r s t u v w x y z} {
- if { ! [catch { testvolumetype ${p}: } result] && $result eq {CDFS} } {
- set cdrom ${p}:
- }
- }
-}
-
proc findfile {dir} {
- foreach p [glob $dir/*] {
+ foreach p [glob -directory $dir *] {
if {[file type $p] == "file"} {
return $p
}
}
- foreach p [glob $dir/*] {
+ foreach p [glob -directory $dir *] {
if {[file type $p] == "directory"} {
set f [findfile $p]
if {$f != ""} {
@@ -86,26 +80,30 @@ proc findfile {dir} {
return ""
}
-if {$cdrom != ""} {
- set ::tcltest::testConstraints(cdrom) 1
- set cdfile [findfile $cdrom]
+if {[testConstraint testvolumetype]} {
+ foreach p {d e f g h i j k l m n o p q r s t u v w x y z} {
+ if {![catch {testvolumetype ${p}:} result] && $result eq "CDFS"} {
+ set cdrom ${p}:
+ set cdfile [findfile $cdrom]
+ testConstraint cdrom 1
+ break
+ }
+ }
}
+# NB: filename is chosen to be short but unlikely to clash with other apps
if {[file exists c:/] && [file exists d:/]} {
- catch {file delete d:/tf1}
- if {[catch {close [open d:/tf1 w]}] == 0} {
- file delete d:/tf1
- set ::tcltest::testConstraints(exdev) 1
+ catch {file delete d:/TclTmpF.1}
+ if {[catch {close [open d:/TclTmpF.1 w]}] == 0} {
+ file delete d:/TclTmpF.1
+ testConstraint exdev 1
}
}
file delete -force -- td1
-set foo [catch {open td1 w} testfile]
-if {$foo} {
- set ::tcltest::testConstraints(longFileNames) 0
-} else {
+if {![catch {open td1 w} testfile]} {
close $testfile
- set ::tcltest::testConstraints(longFileNames) 1
+ testConstraint longFileNames 1
file delete -force -- td1
}
@@ -125,64 +123,64 @@ append longname $longname
# it can be difficult to actually forward "insane" arguments to the
# low-level posix emulation layer.
-test winFCmd-1.1 {TclpRenameFile: errno: EACCES} {pcOnly cdrom} {
+test winFCmd-1.1 {TclpRenameFile: errno: EACCES} {win cdrom testfile} {
list [catch {testfile mv $cdfile $cdrom/dummy~~.fil} msg] $msg
} {1 EACCES}
-test winFCmd-1.2 {TclpRenameFile: errno: EEXIST} {pcOnly} {
+test winFCmd-1.2 {TclpRenameFile: errno: EEXIST} {win testfile} {
cleanup
file mkdir td1/td2/td3
file mkdir td2
list [catch {testfile mv td2 td1/td2} msg] $msg
} {1 EEXIST}
-test winFCmd-1.3 {TclpRenameFile: errno: EINVAL} {pcOnly} {
+test winFCmd-1.3 {TclpRenameFile: errno: EINVAL} {win testfile} {
cleanup
list [catch {testfile mv / td1} msg] $msg
} {1 EINVAL}
-test winFCmd-1.4 {TclpRenameFile: errno: EINVAL} {pcOnly} {
+test winFCmd-1.4 {TclpRenameFile: errno: EINVAL} {win testfile} {
cleanup
file mkdir td1
list [catch {testfile mv td1 td1/td2} msg] $msg
} {1 EINVAL}
-test winFCmd-1.5 {TclpRenameFile: errno: EISDIR} {pcOnly} {
+test winFCmd-1.5 {TclpRenameFile: errno: EISDIR} {win testfile} {
cleanup
file mkdir td1
createfile tf1
list [catch {testfile mv tf1 td1} msg] $msg
} {1 EISDIR}
-test winFCmd-1.6 {TclpRenameFile: errno: ENOENT} {pcOnly} {
+test winFCmd-1.6 {TclpRenameFile: errno: ENOENT} {win testfile} {
cleanup
list [catch {testfile mv tf1 tf2} msg] $msg
} {1 ENOENT}
-test winFCmd-1.7 {TclpRenameFile: errno: ENOENT} {pcOnly} {
+test winFCmd-1.7 {TclpRenameFile: errno: ENOENT} {win testfile} {
cleanup
list [catch {testfile mv "" tf2} msg] $msg
} {1 ENOENT}
-test winFCmd-1.8 {TclpRenameFile: errno: ENOENT} {pcOnly} {
+test winFCmd-1.8 {TclpRenameFile: errno: ENOENT} {win testfile} {
cleanup
createfile tf1
list [catch {testfile mv tf1 ""} msg] $msg
} {1 ENOENT}
-test winFCmd-1.9 {TclpRenameFile: errno: ENOTDIR} {pcOnly} {
+test winFCmd-1.9 {TclpRenameFile: errno: ENOTDIR} {win testfile} {
cleanup
file mkdir td1
createfile tf1
list [catch {testfile mv td1 tf1} msg] $msg
} {1 ENOTDIR}
-test winFCmd-1.10 {TclpRenameFile: errno: EXDEV} {pcOnly exdev} {
+test winFCmd-1.10 {TclpRenameFile: errno: EXDEV} {win exdev testfile} {
file delete -force d:/tf1
file mkdir c:/tf1
set msg [list [catch {testfile mv c:/tf1 d:/tf1} msg] $msg]
file delete -force c:/tf1
set msg
} {1 EXDEV}
-test winFCmd-1.11 {TclpRenameFile: errno: EACCES} {pcOnly} {
+test winFCmd-1.11 {TclpRenameFile: errno: EACCES} {win testfile} {
cleanup
set fd [open tf1 w]
set msg [list [catch {testfile mv tf1 tf2} msg] $msg]
close $fd
set msg
} {1 EACCES}
-test winFCmd-1.12 {TclpRenameFile: errno: EACCES} {pcOnly} {
+test winFCmd-1.12 {TclpRenameFile: errno: EACCES} {win testfile} {
cleanup
createfile tf1
set fd [open tf2 w]
@@ -190,113 +188,121 @@ test winFCmd-1.12 {TclpRenameFile: errno: EACCES} {pcOnly} {
close $fd
set msg
} {1 EACCES}
-test winFCmd-1.13 {TclpRenameFile: errno: EACCES} {pcOnly win2000orXP} {
+test winFCmd-1.13 {TclpRenameFile: errno: EACCES} {win win2000orXP testfile} {
cleanup
list [catch {testfile mv nul tf1} msg] $msg
} {1 EINVAL}
-test winFCmd-1.13.1 {TclpRenameFile: errno: EACCES} {pcOnly winOlderThan2000} {
+test winFCmd-1.13.1 {TclpRenameFile: errno: EACCES} {win nt winOlderThan2000 testfile} {
cleanup
list [catch {testfile mv nul tf1} msg] $msg
} {1 EACCES}
-test winFCmd-1.14 {TclpRenameFile: errno: EACCES} {pcOnly 95} {
+test winFCmd-1.13.2 {TclpRenameFile: errno: ENOENT} {win 95 testfile} {
+ cleanup
+ list [catch {testfile mv nul tf1} msg] $msg
+} {1 ENOENT}
+test winFCmd-1.14 {TclpRenameFile: errno: EACCES} {win 95 testfile} {
cleanup
createfile tf1
list [catch {testfile mv tf1 nul} msg] $msg
} {1 EACCES}
-test winFCmd-1.15 {TclpRenameFile: errno: EEXIST} {pcOnly nt} {
+test winFCmd-1.15 {TclpRenameFile: errno: EEXIST} {win nt testfile} {
cleanup
createfile tf1
list [catch {testfile mv tf1 nul} msg] $msg
} {1 EEXIST}
-test winFCmd-1.16 {TclpRenameFile: MoveFile() != FALSE} {pcOnly} {
+test winFCmd-1.16 {TclpRenameFile: MoveFile() != FALSE} {win testfile} {
cleanup
createfile tf1 tf1
testfile mv tf1 tf2
list [file exists tf1] [contents tf2]
} {0 tf1}
-test winFCmd-1.17 {TclpRenameFile: MoveFile() == FALSE} {pcOnly} {
+test winFCmd-1.17 {TclpRenameFile: MoveFile() == FALSE} {win testfile} {
cleanup
list [catch {testfile mv tf1 tf2} msg] $msg
} {1 ENOENT}
-test winFCmd-1.18 {TclpRenameFile: srcAttr == -1} {pcOnly} {
+test winFCmd-1.18 {TclpRenameFile: srcAttr == -1} {win testfile} {
cleanup
list [catch {testfile mv tf1 tf2} msg] $msg
} {1 ENOENT}
-test winFCmd-1.19 {TclpRenameFile: errno == EACCES} {pcOnly win2000orXP} {
+test winFCmd-1.19 {TclpRenameFile: errno == EACCES} {win win2000orXP testfile} {
cleanup
list [catch {testfile mv nul tf1} msg] $msg
} {1 EINVAL}
-test winFCmd-1.19.1 {TclpRenameFile: errno == EACCES} {pcOnly winOlderThan2000} {
+test winFCmd-1.19.1 {TclpRenameFile: errno == EACCES} {win nt winOlderThan2000 testfile} {
cleanup
list [catch {testfile mv nul tf1} msg] $msg
} {1 EACCES}
-test winFCmd-1.20 {TclpRenameFile: src is dir} {pcOnly nt} {
+test winFCmd-1.19.2 {TclpRenameFile: errno == ENOENT} {win 95 testfile} {
+ cleanup
+ list [catch {testfile mv nul tf1} msg] $msg
+} {1 ENOENT}
+test winFCmd-1.20 {TclpRenameFile: src is dir} {win nt testfile} {
# under 95, this would actually succeed and move the current dir out from
# under the current process!
cleanup
file delete /tf1
list [catch {testfile mv [pwd] /tf1} msg] $msg
} {1 EACCES}
-test winFCmd-1.21 {TclpRenameFile: long src} {pcOnly} {
+test winFCmd-1.21 {TclpRenameFile: long src} {win testfile} {
cleanup
list [catch {testfile mv $longname tf1} msg] $msg
} {1 ENAMETOOLONG}
-test winFCmd-1.22 {TclpRenameFile: long dst} {pcOnly} {
+test winFCmd-1.22 {TclpRenameFile: long dst} {win testfile} {
cleanup
createfile tf1
list [catch {testfile mv tf1 $longname} msg] $msg
} {1 ENAMETOOLONG}
-test winFCmd-1.23 {TclpRenameFile: move dir into self} {pcOnly} {
+test winFCmd-1.23 {TclpRenameFile: move dir into self} {win testfile} {
cleanup
file mkdir td1
list [catch {testfile mv [pwd]/td1 td1/td2} msg] $msg
} {1 EINVAL}
-test winFCmd-1.24 {TclpRenameFile: move a root dir} {pcOnly} {
+test winFCmd-1.24 {TclpRenameFile: move a root dir} {win testfile} {
cleanup
list [catch {testfile mv / c:/} msg] $msg
} {1 EINVAL}
-test winFCmd-1.25 {TclpRenameFile: cross file systems} {pcOnly cdrom} {
+test winFCmd-1.25 {TclpRenameFile: cross file systems} {win cdrom testfile} {
cleanup
file mkdir td1
list [catch {testfile mv td1 $cdrom/td1} msg] $msg
} {1 EXDEV}
-test winFCmd-1.26 {TclpRenameFile: readonly fs} {pcOnly cdrom} {
+test winFCmd-1.26 {TclpRenameFile: readonly fs} {win cdrom testfile} {
cleanup
list [catch {testfile mv $cdfile $cdrom/dummy~~.fil} msg] $msg
} {1 EACCES}
-test winFCmd-1.27 {TclpRenameFile: open file} {pcOnly} {
+test winFCmd-1.27 {TclpRenameFile: open file} {win testfile} {
cleanup
set fd [open tf1 w]
set msg [list [catch {testfile mv tf1 tf2} msg] $msg]
close $fd
set msg
} {1 EACCES}
-test winFCmd-1.28 {TclpRenameFile: errno == EEXIST} {pcOnly} {
+test winFCmd-1.28 {TclpRenameFile: errno == EEXIST} {win testfile} {
cleanup
createfile tf1
createfile tf2
testfile mv tf1 tf2
list [file exists tf1] [file exists tf2]
} {0 1}
-test winFCmd-1.29 {TclpRenameFile: src is dir} {pcOnly} {
+test winFCmd-1.29 {TclpRenameFile: src is dir} {win testfile} {
cleanup
file mkdir td1
createfile tf1
list [catch {testfile mv td1 tf1} msg] $msg
} {1 ENOTDIR}
-test winFCmd-1.30 {TclpRenameFile: dst is dir} {pcOnly} {
+test winFCmd-1.30 {TclpRenameFile: dst is dir} {win testfile} {
cleanup
file mkdir td1
file mkdir td2/td2
list [catch {testfile mv td1 td2} msg] $msg
} {1 EEXIST}
-test winFCmd-1.31 {TclpRenameFile: TclpRemoveDirectory fails} {pcOnly} {
+test winFCmd-1.31 {TclpRenameFile: TclpRemoveDirectory fails} {win testfile} {
cleanup
file mkdir td1
file mkdir td2/td2
list [catch {testfile mv td1 td2} msg] $msg
} {1 EEXIST}
-test winFCmd-1.32 {TclpRenameFile: TclpRemoveDirectory succeeds} {pcOnly} {
+test winFCmd-1.32 {TclpRenameFile: TclpRemoveDirectory succeeds} {win testfile} {
cleanup
file mkdir td1/td2
file mkdir td2
@@ -304,7 +310,7 @@ test winFCmd-1.32 {TclpRenameFile: TclpRemoveDirectory succeeds} {pcOnly} {
list [file exists td1] [file exists td2] [file exists td2/td2]
} {0 1 1}
test winFCmd-1.33 {TclpRenameFile: After removing dst dir, MoveFile fails} \
- {pcOnly exdev} {
+ {win exdev testfile testchmod} {
file mkdir d:/td1
testchmod 000 d:/td1
file mkdir c:/tf1
@@ -314,56 +320,56 @@ test winFCmd-1.33 {TclpRenameFile: After removing dst dir, MoveFile fails} \
file delete -force c:/tf1
set msg
} {1 EXDEV 0}
-test winFCmd-1.34 {TclpRenameFile: src is dir, dst is not} {pcOnly} {
+test winFCmd-1.34 {TclpRenameFile: src is dir, dst is not} {win testfile} {
file mkdir td1
createfile tf1
list [catch {testfile mv td1 tf1} msg] $msg
} {1 ENOTDIR}
-test winFCmd-1.35 {TclpRenameFile: src is not dir, dst is} {pcOnly} {
+test winFCmd-1.35 {TclpRenameFile: src is not dir, dst is} {win testfile} {
file mkdir td1
createfile tf1
list [catch {testfile mv tf1 td1} msg] $msg
} {1 EISDIR}
-test winFCmd-1.36 {TclpRenameFile: src and dst not dir} {pcOnly} {
+test winFCmd-1.36 {TclpRenameFile: src and dst not dir} {win testfile} {
createfile tf1 tf1
createfile tf2 tf2
testfile mv tf1 tf2
contents tf2
} {tf1}
-test winFCmd-1.37 {TclpRenameFile: need to restore temp file} {pcOnly} {
+test winFCmd-1.37 {TclpRenameFile: need to restore temp file} {win emptyTest} {
# Can't figure out how to cause this.
# Need a file that can't be copied.
} {}
-test winFCmd-2.1 {TclpCopyFile: errno: EACCES} {pcOnly cdrom} {
+test winFCmd-2.1 {TclpCopyFile: errno: EACCES} {win cdrom testfile} {
cleanup
list [catch {testfile cp $cdfile $cdrom/dummy~~.fil} msg] $msg
} {1 EACCES}
-test winFCmd-2.2 {TclpCopyFile: errno: EISDIR} {pcOnly} {
+test winFCmd-2.2 {TclpCopyFile: errno: EISDIR} {win testfile} {
cleanup
file mkdir td1
list [catch {testfile cp td1 tf1} msg] $msg
} {1 EISDIR}
-test winFCmd-2.3 {TclpCopyFile: errno: EISDIR} {pcOnly} {
+test winFCmd-2.3 {TclpCopyFile: errno: EISDIR} {win testfile} {
cleanup
createfile tf1
file mkdir td1
list [catch {testfile cp tf1 td1} msg] $msg
} {1 EISDIR}
-test winFCmd-2.4 {TclpCopyFile: errno: ENOENT} {pcOnly} {
+test winFCmd-2.4 {TclpCopyFile: errno: ENOENT} {win testfile} {
cleanup
list [catch {testfile cp tf1 tf2} msg] $msg
} {1 ENOENT}
-test winFCmd-2.5 {TclpCopyFile: errno: ENOENT} {pcOnly} {
+test winFCmd-2.5 {TclpCopyFile: errno: ENOENT} {win testfile} {
cleanup
list [catch {testfile cp "" tf2} msg] $msg
} {1 ENOENT}
-test winFCmd-2.6 {TclpCopyFile: errno: ENOENT} {pcOnly} {
+test winFCmd-2.6 {TclpCopyFile: errno: ENOENT} {win testfile} {
cleanup
createfile tf1
list [catch {testfile cp tf1 ""} msg] $msg
} {1 ENOENT}
-test winFCmd-2.7 {TclpCopyFile: errno: EACCES} {pcOnly 95} {
+test winFCmd-2.7 {TclpCopyFile: errno: EACCES} {win 95 testfile} {
cleanup
createfile tf1
set fd [open tf2 w]
@@ -371,61 +377,61 @@ test winFCmd-2.7 {TclpCopyFile: errno: EACCES} {pcOnly 95} {
close $fd
set msg
} {1 EACCES}
-test winFCmd-2.8 {TclpCopyFile: errno: EACCES} {pcOnly win2000orXP} {
+test winFCmd-2.8 {TclpCopyFile: errno: EACCES} {win win2000orXP testfile} {
cleanup
list [catch {testfile cp nul tf1} msg] $msg
} {1 EINVAL}
-test winFCmd-2.8.1 {TclpCopyFile: errno: EACCES} {pcOnly nt winOlderThan2000} {
+test winFCmd-2.8.1 {TclpCopyFile: errno: EACCES} {win nt winOlderThan2000 testfile} {
cleanup
list [catch {testfile cp nul tf1} msg] $msg
} {1 EACCES}
-test winFCmd-2.9 {TclpCopyFile: errno: ENOENT} {pcOnly 95} {
+test winFCmd-2.9 {TclpCopyFile: errno: ENOENT} {win 95 testfile} {
cleanup
list [catch {testfile cp nul tf1} msg] $msg
} {1 ENOENT}
-test winFCmd-2.10 {TclpCopyFile: CopyFile succeeds} {pcOnly} {
+test winFCmd-2.10 {TclpCopyFile: CopyFile succeeds} {win testfile} {
cleanup
createfile tf1 tf1
testfile cp tf1 tf2
list [contents tf1] [contents tf2]
} {tf1 tf1}
-test winFCmd-2.11 {TclpCopyFile: CopyFile succeeds} {pcOnly} {
+test winFCmd-2.11 {TclpCopyFile: CopyFile succeeds} {win testfile} {
cleanup
createfile tf1 tf1
createfile tf2 tf2
testfile cp tf1 tf2
list [contents tf1] [contents tf2]
} {tf1 tf1}
-test winFCmd-2.12 {TclpCopyFile: CopyFile succeeds} {pcOnly} {
+test winFCmd-2.12 {TclpCopyFile: CopyFile succeeds} {win testfile} {
cleanup
createfile tf1 tf1
testchmod 000 tf1
testfile cp tf1 tf2
list [contents tf2] [file writable tf2]
} {tf1 0}
-test winFCmd-2.13 {TclpCopyFile: CopyFile fails} {pcOnly} {
+test winFCmd-2.13 {TclpCopyFile: CopyFile fails} {win testfile} {
cleanup
createfile tf1
file mkdir td1
list [catch {testfile cp tf1 td1} msg] $msg
} {1 EISDIR}
-test winFCmd-2.14 {TclpCopyFile: errno == EACCES} {pcOnly} {
+test winFCmd-2.14 {TclpCopyFile: errno == EACCES} {win testfile} {
cleanup
file mkdir td1
list [catch {testfile cp td1 tf1} msg] $msg
} {1 EISDIR}
-test winFCmd-2.15 {TclpCopyFile: src is directory} {pcOnly} {
+test winFCmd-2.15 {TclpCopyFile: src is directory} {win testfile} {
cleanup
file mkdir td1
list [catch {testfile cp td1 tf1} msg] $msg
} {1 EISDIR}
-test winFCmd-2.16 {TclpCopyFile: dst is directory} {pcOnly} {
+test winFCmd-2.16 {TclpCopyFile: dst is directory} {win testfile} {
cleanup
createfile tf1
file mkdir td1
list [catch {testfile cp tf1 td1} msg] $msg
} {1 EISDIR}
-test winFCmd-2.17 {TclpCopyFile: dst is readonly} {pcOnly} {
+test winFCmd-2.17 {TclpCopyFile: dst is readonly} {win testfile testchmod} {
cleanup
createfile tf1 tf1
createfile tf2 tf2
@@ -433,7 +439,7 @@ test winFCmd-2.17 {TclpCopyFile: dst is readonly} {pcOnly} {
testfile cp tf1 tf2
list [file writable tf2] [contents tf2]
} {1 tf1}
-test winFCmd-2.18 {TclpCopyFile: still can't copy onto dst} {pcOnly 95} {
+test winFCmd-2.18 {TclpCopyFile: still can't copy onto dst} {win 95 testfile testchmod} {
cleanup
createfile tf1
createfile tf2
@@ -444,59 +450,59 @@ test winFCmd-2.18 {TclpCopyFile: still can't copy onto dst} {pcOnly 95} {
set msg "$msg [file writable tf2]"
} {1 EACCES 0}
-test winFCmd-3.1 {TclpDeleteFile: errno: EACCES} {pcOnly cdrom} {
+test winFCmd-3.1 {TclpDeleteFile: errno: EACCES} {win cdrom testfile} {
list [catch {testfile rm $cdfile $cdrom/dummy~~.fil} msg] $msg
} {1 EACCES}
-test winFCmd-3.2 {TclpDeleteFile: errno: EISDIR} {pcOnly} {
+test winFCmd-3.2 {TclpDeleteFile: errno: EISDIR} {win testfile} {
cleanup
file mkdir td1
list [catch {testfile rm td1} msg] $msg
} {1 EISDIR}
-test winFCmd-3.3 {TclpDeleteFile: errno: ENOENT} {pcOnly} {
+test winFCmd-3.3 {TclpDeleteFile: errno: ENOENT} {win testfile} {
cleanup
list [catch {testfile rm tf1} msg] $msg
} {1 ENOENT}
-test winFCmd-3.4 {TclpDeleteFile: errno: ENOENT} {pcOnly} {
+test winFCmd-3.4 {TclpDeleteFile: errno: ENOENT} {win testfile} {
cleanup
list [catch {testfile rm ""} msg] $msg
} {1 ENOENT}
-test winFCmd-3.5 {TclpDeleteFile: errno: EACCES} {pcOnly} {
+test winFCmd-3.5 {TclpDeleteFile: errno: EACCES} {win testfile} {
cleanup
set fd [open tf1 w]
set msg [list [catch {testfile rm tf1} msg] $msg]
close $fd
set msg
} {1 EACCES}
-test winFCmd-3.6 {TclpDeleteFile: errno: EACCES} {pcOnly} {
+test winFCmd-3.6 {TclpDeleteFile: errno: EACCES} {win testfile} {
cleanup
list [catch {testfile rm nul} msg] $msg
} {1 EACCES}
-test winFCmd-3.7 {TclpDeleteFile: DeleteFile succeeds} {pcOnly} {
+test winFCmd-3.7 {TclpDeleteFile: DeleteFile succeeds} {win testfile} {
cleanup
createfile tf1
testfile rm tf1
file exists tf1
} {0}
-test winFCmd-3.8 {TclpDeleteFile: DeleteFile fails} {pcOnly} {
+test winFCmd-3.8 {TclpDeleteFile: DeleteFile fails} {win testfile} {
cleanup
file mkdir td1
list [catch {testfile rm td1} msg] $msg
} {1 EISDIR}
-test winFCmd-3.9 {TclpDeleteFile: errno == EACCES} {pcOnly} {
+test winFCmd-3.9 {TclpDeleteFile: errno == EACCES} {win testfile} {
cleanup
set fd [open tf1 w]
set msg [list [catch {testfile rm tf1} msg] $msg]
close $fd
set msg
} {1 EACCES}
-test winFCmd-3.10 {TclpDeleteFile: path is readonly} {pcOnly} {
+test winFCmd-3.10 {TclpDeleteFile: path is readonly} {win testfile testchmod} {
cleanup
createfile tf1
testchmod 000 tf1
testfile rm tf1
file exists tf1
} {0}
-test winFCmd-3.11 {TclpDeleteFile: still can't remove path} {pcOnly} {
+test winFCmd-3.11 {TclpDeleteFile: still can't remove path} {win testfile testchmod} {
cleanup
set fd [open tf1 w]
testchmod 000 tf1
@@ -505,35 +511,35 @@ test winFCmd-3.11 {TclpDeleteFile: still can't remove path} {pcOnly} {
set msg
} {1 EACCES}
-test winFCmd-4.1 {TclpCreateDirectory: errno: EACCES} {pcOnly nt cdrom} {
+test winFCmd-4.1 {TclpCreateDirectory: errno: EACCES} {win nt cdrom testfile} {
list [catch {testfile mkdir $cdrom/dummy~~.dir} msg] $msg
} {1 EACCES}
-test winFCmd-4.2 {TclpCreateDirectory: errno: EACCES} {pcOnly 95 cdrom} {
+test winFCmd-4.2 {TclpCreateDirectory: errno: EACCES} {win 95 cdrom testfile} {
list [catch {testfile mkdir $cdrom/dummy~~.dir} msg] $msg
} {1 ENOSPC}
-test winFCmd-4.3 {TclpCreateDirectory: errno: EEXIST} {pcOnly} {
+test winFCmd-4.3 {TclpCreateDirectory: errno: EEXIST} {win testfile} {
cleanup
file mkdir td1
list [catch {testfile mkdir td1} msg] $msg
} {1 EEXIST}
-test winFCmd-4.4 {TclpCreateDirectory: errno: ENOENT} {pcOnly} {
+test winFCmd-4.4 {TclpCreateDirectory: errno: ENOENT} {win testfile} {
cleanup
list [catch {testfile mkdir td1/td2} msg] $msg
} {1 ENOENT}
-test winFCmd-4.5 {TclpCreateDirectory: CreateDirectory succeeds} {pcOnly} {
+test winFCmd-4.5 {TclpCreateDirectory: CreateDirectory succeeds} {win testfile} {
cleanup
testfile mkdir td1
file type td1
} {directory}
-test winFCmd-5.1 {TclpCopyDirectory: calls TraverseWinTree} {pcOnly} {
+test winFCmd-5.1 {TclpCopyDirectory: calls TraverseWinTree} {win testfile} {
cleanup
file mkdir td1
testfile cpdir td1 td2
list [file type td1] [file type td2]
} {directory directory}
-test winFCmd-6.1 {TclpRemoveDirectory: errno: EACCES} {pcOnly} {
+test winFCmd-6.1 {TclpRemoveDirectory: errno: EACCES} {win testfile testchmod} {
cleanup
file mkdir td1
testchmod 000 td1
@@ -547,40 +553,40 @@ test winFCmd-6.1 {TclpRemoveDirectory: errno: EACCES} {pcOnly} {
}
set r
} {0}
-test winFCmd-6.2 {TclpRemoveDirectory: errno: EEXIST} {pcOnly} {
+test winFCmd-6.2 {TclpRemoveDirectory: errno: EEXIST} {win testfile} {
cleanup
file mkdir td1/td2
list [catch {testfile rmdir td1} msg] [file tail $msg]
} {1 {td1 EEXIST}}
-test winFCmd-6.3 {TclpRemoveDirectory: errno: EACCES} {pcOnly} {
+test winFCmd-6.3 {TclpRemoveDirectory: errno: EACCES} {win emptyTest} {
# can't test this w/o removing everything on your hard disk first!
# testfile rmdir /
} {}
-test winFCmd-6.4 {TclpRemoveDirectory: errno: ENOENT} {pcOnly} {
+test winFCmd-6.4 {TclpRemoveDirectory: errno: ENOENT} {win testfile} {
cleanup
list [catch {testfile rmdir td1} msg] [file tail $msg]
} {1 {td1 ENOENT}}
-test winFCmd-6.5 {TclpRemoveDirectory: errno: ENOENT} {pcOnly} {
+test winFCmd-6.5 {TclpRemoveDirectory: errno: ENOENT} {win testfile} {
cleanup
list [catch {testfile rmdir ""} msg] $msg
} {1 ENOENT}
-test winFCmd-6.6 {TclpRemoveDirectory: errno: ENOTDIR} {pcOnly} {
+test winFCmd-6.6 {TclpRemoveDirectory: errno: ENOTDIR} {win testfile} {
cleanup
createfile tf1
list [catch {testfile rmdir tf1} msg] [file tail $msg]
} {1 {tf1 ENOTDIR}}
-test winFCmd-6.7 {TclpRemoveDirectory: RemoveDirectory succeeds} {pcOnly} {
+test winFCmd-6.7 {TclpRemoveDirectory: RemoveDirectory succeeds} {win testfile} {
cleanup
file mkdir td1
testfile rmdir td1
file exists td1
} {0}
-test winFCmd-6.8 {TclpRemoveDirectory: RemoveDirectory fails} {pcOnly} {
+test winFCmd-6.8 {TclpRemoveDirectory: RemoveDirectory fails} {win testfile} {
cleanup
createfile tf1
list [catch {testfile rmdir tf1} msg] [file tail $msg]
} {1 {tf1 ENOTDIR}}
-test winFCmd-6.9 {TclpRemoveDirectory: errno == EACCES} {pcOnly} {
+test winFCmd-6.9 {TclpRemoveDirectory: errno == EACCES} {win testfile testchmod} {
cleanup
file mkdir td1
testchmod 000 td1
@@ -594,25 +600,26 @@ test winFCmd-6.9 {TclpRemoveDirectory: errno == EACCES} {pcOnly} {
}
set r
} {0}
-test winFCmd-6.10 {TclpRemoveDirectory: attr == -1} {pcOnly 95} {
+test winFCmd-6.10 {TclpRemoveDirectory: attr == -1} {win 95 testfile} {
cleanup
list [catch {testfile rmdir nul} msg] $msg
} {1 {nul EACCES}}
-test winFCmd-6.11 {TclpRemoveDirectory: attr == -1} {pcOnly nt} {
+test winFCmd-6.11 {TclpRemoveDirectory: attr == -1} {win nt testfile} {
cleanup
set res [list [catch {testfile rmdir /} msg] $msg]
# WinXP returns EEXIST, WinNT seems to return EACCES. No policy
# decision has been made as to which is correct.
- regsub {E(ACCES|EXIST)} $res "EACCES or EEXIST" res
- # Don't mind which drive we're on
- regsub {[A-Z]:} $res ""
-} {1 {/ EACCES or EEXIST}}
-test winFCmd-6.12 {TclpRemoveDirectory: errno == EACCES} {pcOnly 95} {
+ regsub {E(ACCES|EXIST)} $res "EACCES or EEXIST"
+} [list 1 [list / EACCES or EEXIST]]
+test winFCmd-6.12 {TclpRemoveDirectory: errno == EACCES} {win 95 testfile} {
cleanup
createfile tf1
- list [catch {testfile rmdir tf1} msg] $msg
+ set res [catch {testfile rmdir tf1} msg]
+ # get rid of path
+ set msg [list [file tail [lindex $msg 0]] [lindex $msg 1]]
+ list $res $msg
} {1 {tf1 ENOTDIR}}
-test winFCmd-6.13 {TclpRemoveDirectory: write-protected} {pcOnly} {
+test winFCmd-6.13 {TclpRemoveDirectory: write-protected} {win testfile testchmod} {
cleanup
file mkdir td1
testchmod 000 td1
@@ -626,84 +633,87 @@ test winFCmd-6.13 {TclpRemoveDirectory: write-protected} {pcOnly} {
}
set r
} {0}
-test winFCmd-6.14 {TclpRemoveDirectory: check if empty dir} {pcOnly 95} {
+test winFCmd-6.14 {TclpRemoveDirectory: check if empty dir} {win 95 testfile} {
cleanup
file mkdir td1/td2
- list [catch {testfile rmdir td1} msg] $msg
+ set res [catch {testfile rmdir td1} msg]
+ # get rid of path
+ set msg [list [file tail [lindex $msg 0]] [lindex $msg 1]]
+ list $res $msg
} {1 {td1 EEXIST}}
-test winFCmd-6.15 {TclpRemoveDirectory: !recursive} {pcOnly} {
+test winFCmd-6.15 {TclpRemoveDirectory: !recursive} {win testfile} {
cleanup
file mkdir td1/td2
list [catch {testfile rmdir td1} msg] [file tail $msg]
} {1 {td1 EEXIST}}
-test winFCmd-6.16 {TclpRemoveDirectory: recursive, but errno != EEXIST} {pcOnly} {
+test winFCmd-6.16 {TclpRemoveDirectory: recursive, but errno != EEXIST} {win testfile} {
cleanup
createfile tf1
list [catch {testfile rmdir -force tf1} msg] $msg
} {1 {tf1 ENOTDIR}}
-test winFCmd-6.17 {TclpRemoveDirectory: calls TraverseWinTree} {pcOnly} {
+test winFCmd-6.17 {TclpRemoveDirectory: calls TraverseWinTree} {win testfile} {
cleanup
file mkdir td1/td2
testfile rmdir -force td1
file exists td1
} {0}
-test winFCmd-7.1 {TraverseWinTree: targetPtr == NULL} {pcOnly} {
+test winFCmd-7.1 {TraverseWinTree: targetPtr == NULL} {win testfile} {
cleanup
file mkdir td1/td2/td3
testfile rmdir -force td1
file exists td1
} {0}
-test winFCmd-7.2 {TraverseWinTree: targetPtr != NULL} {pcOnly} {
+test winFCmd-7.2 {TraverseWinTree: targetPtr != NULL} {win testfile} {
cleanup
file mkdir td1/td2/td3
testfile cpdir td1 td2
list [file exists td1] [file exists td2]
} {1 1}
-test winFCmd-7.3 {TraverseWinTree: sourceAttr == -1} {pcOnly} {
+test winFCmd-7.3 {TraverseWinTree: sourceAttr == -1} {win testfile} {
cleanup
list [catch {testfile cpdir td1 td2} msg] $msg
} {1 {td1 ENOENT}}
-test winFCmd-7.4 {TraverseWinTree: source isn't directory} {pcOnly} {
+test winFCmd-7.4 {TraverseWinTree: source isn't directory} {win testfile} {
cleanup
file mkdir td1
createfile td1/tf1 tf1
testfile cpdir td1 td2
contents td2/tf1
} {tf1}
-test winFCmd-7.5 {TraverseWinTree: call TraversalCopy: DOTREE_F} {pcOnly} {
+test winFCmd-7.5 {TraverseWinTree: call TraversalCopy: DOTREE_F} {win testfile} {
cleanup
file mkdir td1
createfile td1/tf1 tf1
testfile cpdir td1 td2
contents td2/tf1
} {tf1}
-test winFCmd-7.6 {TraverseWinTree: call TraversalDelete: DOTREE_F} {pcOnly} {
+test winFCmd-7.6 {TraverseWinTree: call TraversalDelete: DOTREE_F} {win testfile} {
cleanup
file mkdir td1
createfile td1/tf1 tf1
testfile rmdir -force td1
file exists td1
} {0}
-test winFCmd-7.7 {TraverseWinTree: append \ to source if necessary} {pcOnly} {
+test winFCmd-7.7 {TraverseWinTree: append \ to source if necessary} {win testfile} {
cleanup
file mkdir td1
createfile td1/tf1 tf1
testfile cpdir td1 td2
contents td2/tf1
} {tf1}
-test winFCmd-7.8 {TraverseWinTree: append \ to source if necessary} {pcOnly 95 cdrom} {
+test winFCmd-7.8 {TraverseWinTree: append \ to source if necessary} {win 95 cdrom testfile} {
# cdrom can return either d:\ or D:/, but we only care about the errcode
list [catch {testfile rmdir $cdrom/} msg] [lindex $msg 1]
-} {1 EEXIST}
-test winFCmd-7.9 {TraverseWinTree: append \ to source if necessary} {pcOnly nt cdrom} {
+} {1 EACCES} ; # was EEXIST, but changed for win98.
+test winFCmd-7.9 {TraverseWinTree: append \ to source if necessary} {win nt cdrom testfile} {
list [catch {testfile rmdir $cdrom/} msg] [lindex $msg 1]
} {1 EACCES}
test winFCmd-7.10 {TraverseWinTree: can't read directory: handle == INVALID} \
- {pcOnly} {
+ {win emptyTest} {
# can't make it happen
} {}
-test winFCmd-7.11 {TraverseWinTree: call TraversalCopy: DOTREE_PRED} {pcOnly} {
+test winFCmd-7.11 {TraverseWinTree: call TraversalCopy: DOTREE_PRED} {win testfile testchmod} {
cleanup
file mkdir td1
createfile td1/tf1 tf1
@@ -718,36 +728,36 @@ test winFCmd-7.11 {TraverseWinTree: call TraversalCopy: DOTREE_PRED} {pcOnly} {
}
set r
} {1 1}
-test winFCmd-7.12 {TraverseWinTree: call TraversalDelete: DOTREE_PRED} {pcOnly} {
+test winFCmd-7.12 {TraverseWinTree: call TraversalDelete: DOTREE_PRED} {win testfile} {
cleanup
file mkdir td1
createfile td1/tf1 tf1
testfile rmdir -force td1
file exists td1
} {0}
-test winFCmd-7.13 {TraverseWinTree: append \ to target if necessary} {pcOnly} {
+test winFCmd-7.13 {TraverseWinTree: append \ to target if necessary} {win testfile} {
cleanup
file mkdir td1
createfile td1/tf1 tf1
testfile cpdir td1 td2
contents td2/tf1
} {tf1}
-test winFCmd-7.14 {TraverseWinTree: append \ to target if necessary} {pcOnly 95} {
+test winFCmd-7.14 {TraverseWinTree: append \ to target if necessary} {win 95 testfile} {
cleanup
file mkdir td1
list [catch {testfile cpdir td1 /} msg] $msg
} {1 {/ EEXIST}}
-test winFCmd-7.15 {TraverseWinTree: append \ to target if necessary} {pcOnly nt} {
+test winFCmd-7.15 {TraverseWinTree: append \ to target if necessary} {win nt testfile} {
cleanup
file mkdir td1
list [catch {testfile cpdir td1 /} msg] $msg
} {1 {/ EACCES}}
-test winFCmd-7.16 {TraverseWinTree: recurse on files: no files} {pcOnly} {
+test winFCmd-7.16 {TraverseWinTree: recurse on files: no files} {win testfile} {
cleanup
file mkdir td1
testfile cpdir td1 td2
} {}
-test winFCmd-7.17 {TraverseWinTree: recurse on files: one file} {pcOnly} {
+test winFCmd-7.17 {TraverseWinTree: recurse on files: one file} {win testfile} {
cleanup
file mkdir td1
createfile td1/td2
@@ -755,7 +765,7 @@ test winFCmd-7.17 {TraverseWinTree: recurse on files: one file} {pcOnly} {
glob td2/*
} {td2/td2}
test winFCmd-7.18 {TraverseWinTree: recurse on files: several files and dir} \
- {pcOnly} {
+ {win testfile} {
cleanup
file mkdir td1
createfile td1/tf1
@@ -766,7 +776,7 @@ test winFCmd-7.18 {TraverseWinTree: recurse on files: several files and dir} \
testfile cpdir td1 td2
lsort [glob td2/*]
} {td2/td2 td2/tf1 td2/tf2 td2/tf3 td2/tf4}
-test winFCmd-7.19 {TraverseWinTree: call TraversalCopy: DOTREE_POSTD} {pcOnly} {
+test winFCmd-7.19 {TraverseWinTree: call TraversalCopy: DOTREE_POSTD} {win testfile testchmod} {
cleanup
file mkdir td1
createfile td1/tf1 tf1
@@ -782,24 +792,24 @@ test winFCmd-7.19 {TraverseWinTree: call TraversalCopy: DOTREE_POSTD} {pcOnly} {
set r
} {1 1}
test winFCmd-7.20 {TraverseWinTree: call TraversalDelete: DOTREE_POSTD} \
- {pcOnly} {
+ {win testfile} {
cleanup
file mkdir td1
createfile td1/tf1 tf1
testfile rmdir -force td1
file exists td1
} {0}
-test winFCmd-7.21 {TraverseWinTree: fill errorPtr} {pcOnly} {
+test winFCmd-7.21 {TraverseWinTree: fill errorPtr} {win testfile} {
cleanup
list [catch {testfile cpdir td1 td2} msg] $msg
} {1 {td1 ENOENT}}
-test winFCmd-8.1 {TraversalCopy: DOTREE_F} {pcOnly} {
+test winFCmd-8.1 {TraversalCopy: DOTREE_F} {win testfile} {
cleanup
file mkdir td1
list [catch {testfile cpdir td1 td1} msg] $msg
} {1 {td1 EEXIST}}
-test winFCmd-8.2 {TraversalCopy: DOTREE_PRED} {pcOnly} {
+test winFCmd-8.2 {TraversalCopy: DOTREE_PRED} {win testfile testchmod} {
cleanup
file mkdir td1/td2
testchmod 000 td1
@@ -813,19 +823,19 @@ test winFCmd-8.2 {TraversalCopy: DOTREE_PRED} {pcOnly} {
}
set r
} {0 1}
-test winFCmd-8.3 {TraversalCopy: DOTREE_POSTD} {pcOnly} {
+test winFCmd-8.3 {TraversalCopy: DOTREE_POSTD} {win testfile} {
cleanup
file mkdir td1
testfile cpdir td1 td2
} {}
-test winFCmd-9.1 {TraversalDelete: DOTREE_F} {pcOnly} {
+test winFCmd-9.1 {TraversalDelete: DOTREE_F} {win testfile} {
cleanup
file mkdir td1
createfile td1/tf1
testfile rmdir -force td1
} {}
-test winFCmd-9.2 {TraversalDelete: DOTREE_F} {pcOnly 95} {
+test winFCmd-9.2 {TraversalDelete: DOTREE_F} {win 95 testfile} {
cleanup
file mkdir td1
set fd [open td1/tf1 w]
@@ -833,7 +843,7 @@ test winFCmd-9.2 {TraversalDelete: DOTREE_F} {pcOnly 95} {
close $fd
set msg
} {1 {td1\tf1 EACCES}}
-test winFCmd-9.3 {TraversalDelete: DOTREE_PRED} {pcOnly} {
+test winFCmd-9.3 {TraversalDelete: DOTREE_PRED} {win testfile testchmod} {
cleanup
file mkdir td1/td2
testchmod 000 td1
@@ -847,42 +857,42 @@ test winFCmd-9.3 {TraversalDelete: DOTREE_PRED} {pcOnly} {
}
set r
} {0}
-test winFCmd-9.4 {TraversalDelete: DOTREE_POSTD} {pcOnly} {
+test winFCmd-9.4 {TraversalDelete: DOTREE_POSTD} {win testfile} {
cleanup
file mkdir td1/td1/td3/td4/td5
testfile rmdir -force td1
} {}
-test winFCmd-10.1 {AttributesPosixError - get} {pcOnly} {
+test winFCmd-10.1 {AttributesPosixError - get} {win} {
cleanup
list [catch {file attributes td1 -archive} msg] $msg
} {1 {could not read "td1": no such file or directory}}
-test winFCmd-10.2 {AttributesPosixError - set} {pcOnly} {
+test winFCmd-10.2 {AttributesPosixError - set} {win} {
cleanup
list [catch {file attributes td1 -archive 0} msg] $msg
} {1 {could not read "td1": no such file or directory}}
-test winFCmd-11.1 {GetWinFileAttributes} {pcOnly} {
+test winFCmd-11.1 {GetWinFileAttributes} {win} {
cleanup
close [open td1 w]
list [catch {file attributes td1 -archive} msg] $msg [cleanup]
} {0 1 {}}
-test winFCmd-11.2 {GetWinFileAttributes} {pcOnly} {
+test winFCmd-11.2 {GetWinFileAttributes} {win} {
cleanup
close [open td1 w]
list [catch {file attributes td1 -readonly} msg] $msg [cleanup]
} {0 0 {}}
-test winFCmd-11.3 {GetWinFileAttributes} {pcOnly} {
+test winFCmd-11.3 {GetWinFileAttributes} {win} {
cleanup
close [open td1 w]
list [catch {file attributes td1 -hidden} msg] $msg [cleanup]
} {0 0 {}}
-test winFCmd-11.4 {GetWinFileAttributes} {pcOnly} {
+test winFCmd-11.4 {GetWinFileAttributes} {win} {
cleanup
close [open td1 w]
list [catch {file attributes td1 -system} msg] $msg [cleanup]
} {0 0 {}}
-test winFCmd-11.5 {GetWinFileAttributes} {pcOnly} {
+test winFCmd-11.5 {GetWinFileAttributes} {win} {
# attr of relative paths that resolve to root was failing
# don't care about answer, just that test runs.
@@ -893,124 +903,124 @@ test winFCmd-11.5 {GetWinFileAttributes} {pcOnly} {
file attr .
cd $old
} {}
-test winFCmd-11.6 {GetWinFileAttributes} {pcOnly} {
+test winFCmd-11.6 {GetWinFileAttributes} {win} {
file attr c:/ -hidden
} {0}
-test winFCmd-12.1 {ConvertFileNameFormat} {pcOnly} {
+test winFCmd-12.1 {ConvertFileNameFormat} {win} {
cleanup
close [open td1 w]
list [catch {string tolower [file attributes td1 -longname]} msg] $msg [cleanup]
} {0 td1 {}}
-test winFCmd-12.2 {ConvertFileNameFormat} {pcOnly} {
+test winFCmd-12.2 {ConvertFileNameFormat} {win} {
cleanup
file mkdir td1
close [open td1/td1 w]
list [catch {string tolower [file attributes td1/td1 -longname]} msg] $msg [cleanup]
} {0 td1/td1 {}}
-test winFCmd-12.3 {ConvertFileNameFormat} {pcOnly} {
+test winFCmd-12.3 {ConvertFileNameFormat} {win} {
cleanup
file mkdir td1
file mkdir td1/td2
close [open td1/td3 w]
list [catch {string tolower [file attributes td1/td2/../td3 -longname]} msg] $msg [cleanup]
} {0 td1/td2/../td3 {}}
-test winFCmd-12.4 {ConvertFileNameFormat} {pcOnly} {
+test winFCmd-12.4 {ConvertFileNameFormat} {win} {
cleanup
close [open td1 w]
list [catch {string tolower [file attributes ./td1 -longname]} msg] $msg [cleanup]
} {0 ./td1 {}}
-test winFCmd-12.5 {ConvertFileNameFormat: absolute path} {pcOnly} {
+test winFCmd-12.5 {ConvertFileNameFormat: absolute path} {win} {
list [file attributes / -longname] [file attributes \\ -longname]
} {/ /}
-test winFCmd-12.6 {ConvertFileNameFormat: absolute path with drive} {pcOnly} {
+test winFCmd-12.6 {ConvertFileNameFormat: absolute path with drive} {win} {
catch {file delete -force -- c:/td1}
close [open c:/td1 w]
list [catch {string tolower [file attributes c:/td1 -longname]} msg] $msg [file delete -force -- c:/td1]
} {0 c:/td1 {}}
-test winFCmd-12.7 {ConvertFileNameFormat} {nonPortable pcOnly} {
+test winFCmd-12.7 {ConvertFileNameFormat} {nonPortable win} {
string tolower [file attributes //bisque/tcl/ws -longname]
} {//bisque/tcl/ws}
-test winFCmd-12.8 {ConvertFileNameFormat} {pcOnly longFileNames} {
+test winFCmd-12.8 {ConvertFileNameFormat} {win longFileNames} {
cleanup
close [open td1 w]
list [catch {string tolower [file attributes td1 -longname]} msg] $msg [cleanup]
} {0 td1 {}}
-test winFCmd-12.10 {ConvertFileNameFormat} {longFileNames pcOnly} {
+test winFCmd-12.10 {ConvertFileNameFormat} {longFileNames win} {
cleanup
close [open td1td1td1 w]
list [catch {file attributes td1td1td1 -shortname}] [cleanup]
} {0 {}}
-test winFCmd-12.11 {ConvertFileNameFormat} {longFileNames pcOnly} {
+test winFCmd-12.11 {ConvertFileNameFormat} {longFileNames win} {
cleanup
close [open td1 w]
list [catch {string tolower [file attributes td1 -shortname]} msg] $msg [cleanup]
} {0 td1 {}}
-test winFCmd-13.1 {GetWinFileLongName} {pcOnly} {
+test winFCmd-13.1 {GetWinFileLongName} {win} {
cleanup
close [open td1 w]
list [catch {string tolower [file attributes td1 -longname]} msg] $msg [cleanup]
} {0 td1 {}}
-test winFCmd-14.1 {GetWinFileShortName} {pcOnly} {
+test winFCmd-14.1 {GetWinFileShortName} {win} {
cleanup
close [open td1 w]
list [catch {string tolower [file attributes td1 -shortname]} msg] $msg [cleanup]
} {0 td1 {}}
-test winFCmd-15.1 {SetWinFileAttributes} {pcOnly} {
+test winFCmd-15.1 {SetWinFileAttributes} {win} {
cleanup
list [catch {file attributes td1 -archive 0} msg] $msg
} {1 {could not read "td1": no such file or directory}}
-test winFCmd-15.2 {SetWinFileAttributes - archive} {pcOnly} {
+test winFCmd-15.2 {SetWinFileAttributes - archive} {win} {
cleanup
close [open td1 w]
list [catch {file attributes td1 -archive 1} msg] $msg [file attributes td1 -archive] [cleanup]
} {0 {} 1 {}}
-test winFCmd-15.3 {SetWinFileAttributes - archive} {pcOnly} {
+test winFCmd-15.3 {SetWinFileAttributes - archive} {win} {
cleanup
close [open td1 w]
list [catch {file attributes td1 -archive 0} msg] $msg [file attributes td1 -archive] [cleanup]
} {0 {} 0 {}}
-test winFCmd-15.4 {SetWinFileAttributes - hidden} {pcOnly} {
+test winFCmd-15.4 {SetWinFileAttributes - hidden} {win} {
cleanup
close [open td1 w]
list [catch {file attributes td1 -hidden 1} msg] $msg [file attributes td1 -hidden] [file attributes td1 -hidden 0] [cleanup]
} {0 {} 1 {} {}}
-test winFCmd-15.5 {SetWinFileAttributes - hidden} {pcOnly} {
+test winFCmd-15.5 {SetWinFileAttributes - hidden} {win} {
cleanup
close [open td1 w]
list [catch {file attributes td1 -hidden 0} msg] $msg [file attributes td1 -hidden] [cleanup]
} {0 {} 0 {}}
-test winFCmd-15.6 {SetWinFileAttributes - readonly} {pcOnly} {
+test winFCmd-15.6 {SetWinFileAttributes - readonly} {win} {
cleanup
close [open td1 w]
list [catch {file attributes td1 -readonly 1} msg] $msg [file attributes td1 -readonly] [cleanup]
} {0 {} 1 {}}
-test winFCmd-15.7 {SetWinFileAttributes - readonly} {pcOnly} {
+test winFCmd-15.7 {SetWinFileAttributes - readonly} {win} {
cleanup
close [open td1 w]
list [catch {file attributes td1 -readonly 0} msg] $msg [file attributes td1 -readonly] [cleanup]
} {0 {} 0 {}}
-test winFCmd-15.8 {SetWinFileAttributes - system} {pcOnly} {
+test winFCmd-15.8 {SetWinFileAttributes - system} {win} {
cleanup
close [open td1 w]
list [catch {file attributes td1 -system 1} msg] $msg [file attributes td1 -system] [cleanup]
} {0 {} 1 {}}
-test winFCmd-15.9 {SetWinFileAttributes - system} {pcOnly} {
+test winFCmd-15.9 {SetWinFileAttributes - system} {win} {
cleanup
close [open td1 w]
list [catch {file attributes td1 -system 0} msg] $msg [file attributes td1 -system] [cleanup]
} {0 {} 0 {}}
-test winFCmd-15.10 {SetWinFileAttributes - failing} {pcOnly cdrom} {
+test winFCmd-15.10 {SetWinFileAttributes - failing} {win cdrom} {
cleanup
catch {file attributes $cdfile -archive 1}
} {1}
-test winFCmd-16.1 {Windows file normalization} {pcOnly} {
+test winFCmd-16.1 {Windows file normalization} {win} {
list [file normalize c:/] [file normalize C:/]
} {C:/ C:/}
-test winFCmd-16.2 {Windows file normalization} {pcOnly} {
+test winFCmd-16.2 {Windows file normalization} {win} {
close [open td1... w]
set res [file tail [file normalize td1]]
file delete td1...
@@ -1020,48 +1030,113 @@ test winFCmd-16.2 {Windows file normalization} {pcOnly} {
set pwd [pwd]
set d [string index $pwd 0]
-test winFCmd-16.3 {Windows file normalization} {pcOnly} {
+test winFCmd-16.3 {Windows file normalization} {win} {
file norm ${d}:foo
} [file join $pwd foo]
-test winFCmd-16.4 {Windows file normalization} {pcOnly} {
+test winFCmd-16.4 {Windows file normalization} {win} {
file norm [string tolower ${d}]:foo
} [file join $pwd foo]
-test winFCmd-16.5 {Windows file normalization} {pcOnly} {
+test winFCmd-16.5 {Windows file normalization} {win} {
file norm ${d}:foo/bar
} [file join $pwd foo/bar]
-test winFCmd-16.6 {Windows file normalization} {pcOnly} {
+test winFCmd-16.6 {Windows file normalization} {win} {
file norm ${d}:foo\\bar
} [file join $pwd foo/bar]
-test winFCmd-16.7 {Windows file normalization} {pcOnly} {
+test winFCmd-16.7 {Windows file normalization} {win} {
file norm /bar
} "${d}:/bar"
-test winFCmd-16.8 {Windows file normalization} {pcOnly} {
+test winFCmd-16.8 {Windows file normalization} {win} {
file norm ///bar
} "${d}:/bar"
-test winFCmd-16.9 {Windows file normalization} {pcOnly} {
+test winFCmd-16.9 {Windows file normalization} {win} {
file norm /bar/foo
} "${d}:/bar/foo"
if {$d eq "C"} { set dd "D" } else { set dd "C" }
-test winFCmd-16.10 {Windows file normalization} {pcOnly} {
+test winFCmd-16.10 {Windows file normalization} {win} {
file norm ${dd}:foo
} "${dd}:/foo"
-test winFCmd-16.11 {Windows file normalization} {pcOnly cdrom} {
+test winFCmd-16.11 {Windows file normalization} -constraints {win cdrom} \
+-body {
cd ${d}:
cd $cdrom
cd ${d}:
cd $cdrom
# Must not crash
set result "no crash"
-} {no crash}
-test winFCmd-16.12 {Windows file normalization} {pcOnly} {
+} -cleanup {
+ cd $pwd
+} -result {no crash}
+
+test winFCmd-16.12 {Windows file normalization - no crash} \
+ -constraints win -setup {
set oldhome ""
catch {set oldhome $::env(HOME)}
+} -body {
+ set expectedResult [file normalize ${d}:]
set ::env(HOME) ${d}:
cd
+ # At one point this led to an infinite recursion in Tcl
set result [pwd]; # <- Must not crash
+ set result "no crash"
+} -cleanup {
+ set ::env(HOME) $oldhome
+ cd $pwd
+} -result {no crash}
+
+test winFCmd-16.13 {Windows file normalization} -constraints win -setup {
+ set oldhome ""
+ catch {set oldhome $::env(HOME)}
+} -body {
+ # Test 'cd' normalization when HOME is absolute
+ set expectedResult [file normalize ${d}:/]
+ set ::env(HOME) ${d}:/
+ cd
+ set result [pwd]
+ if { [string equal $result $expectedResult] } {
+ concat ok
+ } else {
+ list $result != $expectedResult
+ }
+} -cleanup {
+ set ::env(HOME) $oldhome
+ cd $pwd
+} -result ok
+
+test winFCmd-16.14 {Windows file normalization} -constraints win -setup {
+ set oldhome ""
+ catch {set oldhome $::env(HOME)}
+} -body {
+ # Test 'cd' normalization when HOME is relative
+ set ::env(HOME) ${d}:
+ cd
+ set result [pwd]
+ if { [string equal $result $pwd] } {
+ concat ok
+ } else {
+ list $result != $pwd
+ }
+} -cleanup {
set ::env(HOME) $oldhome
- set result
-} ${d}:/
+ cd $pwd
+} -result ok
+
+test winFCmd-17.1 {Windows bad permissions cd} -constraints win -body {
+ set d {}
+ foreach dd {c:/ d:/ e:/} {
+ eval lappend d [glob -nocomplain \
+ -types hidden -dir $dd "System Volume Information"]
+ }
+ # Old versions of Tcl gave a misleading error that the
+ # directory in question didn't exist.
+ if {[llength $d] && [catch {cd [lindex $d 0]} err]} {
+ regsub ".*: " $err "" err
+ set err
+ } else {
+ set err "permission denied"
+ }
+} -cleanup {
+ cd $pwd
+} -result "permission denied"
cd $pwd
unset d dd pwd
@@ -1122,6 +1197,87 @@ test winFCmd-18.8 {Windows reserved path names} -constraints win -body {
file normalize cOm1:
} -result COM1
+
+test winFCmd-19.1 {Windows extended path names} -constraints nt -body {
+ file normalize //?/c:/windows/win.ini
+} -result //?/c:/windows/win.ini
+
+test winFCmd-19.2 {Windows extended path names} -constraints nt -body {
+ file normalize //?/c:/windows/../windows/win.ini
+} -result //?/c:/windows/win.ini
+
+test winFCmd-19.3 {Windows extended path names} -constraints nt -setup {
+ set tmpfile [file join $::env(TEMP) tcl[string repeat x 20].tmp]
+ set tmpfile [file normalize $tmpfile]
+} -body {
+ list [catch {
+ set f [open $tmpfile [list WRONLY CREAT]]
+ close $f
+ } res] $res
+} -cleanup {
+ catch {file delete $tmpfile}
+} -result [list 0 {}]
+
+test winFCmd-19.4 {Windows extended path names} -constraints nt -setup {
+ set tmpfile [file join $::env(TEMP) tcl[string repeat x 20].tmp]
+ set tmpfile //?/[file normalize $tmpfile]
+} -body {
+ list [catch {
+ set f [open $tmpfile [list WRONLY CREAT]]
+ close $f
+ } res] $res
+} -cleanup {
+ catch {file delete $tmpfile}
+} -result [list 0 {}]
+
+test winFCmd-19.5 {Windows extended path names} -constraints nt -setup {
+ set tmpfile [file join $::env(TEMP) tcl[string repeat x 248].tmp]
+ set tmpfile [file normalize $tmpfile]
+} -body {
+ list [catch {
+ set f [open $tmpfile [list WRONLY CREAT]]
+ close $f
+ } res] errormsg ;#$res
+} -cleanup {
+ catch {file delete $tmpfile}
+} -result [list 1 errormsg]
+
+test winFCmd-19.6 {Windows extended path names} -constraints nt -setup {
+ set tmpfile [file join $::env(TEMP) tcl[string repeat x 248].tmp]
+ set tmpfile //?/[file normalize $tmpfile]
+} -body {
+ list [catch {
+ set f [open $tmpfile [list WRONLY CREAT]]
+ close $f
+ } res] $res
+} -cleanup {
+ catch {file delete $tmpfile}
+} -result [list 0 {}]
+
+test winFCmd-19.7 {Windows extended path names} -constraints nt -setup {
+ set tmpfile [file join $::env(TEMP) "tcl[pid].tmp "]
+ set tmpfile [file normalize $tmpfile]
+} -body {
+ list [catch {
+ set f [open $tmpfile [list WRONLY CREAT]]
+ close $f
+ } res] $res [glob -directory $::env(TEMP) -tails tcl[pid].*]
+} -cleanup {
+ catch {file delete $tmpfile}
+} -result [list 0 {} [list tcl[pid].tmp]]
+
+test winFCmd-19.8 {Windows extended path names} -constraints nt -setup {
+ set tmpfile [file join $::env(TEMP) "tcl[pid].tmp "]
+ set tmpfile //?/[file normalize $tmpfile]
+} -body {
+ list [catch {
+ set f [open $tmpfile [list WRONLY CREAT]]
+ close $f
+ } res] $res [glob -directory $::env(TEMP) -tails tcl[pid].*]
+} -cleanup {
+ catch {file delete $tmpfile}
+} -result [list 0 {} [list "tcl[pid].tmp "]]
+
# This block of code used to occur after the "return" call, so I'm
# commenting it out and assuming that this code is still under construction.
#foreach source {tef ted tnf tnd "" nul com1} {
@@ -1153,3 +1309,7 @@ test winFCmd-18.8 {Windows reserved path names} -constraints win -body {
cleanup
::tcltest::cleanupTests
return
+
+# Local Variables:
+# mode: tcl
+# End:
diff --git a/tests/winFile.test b/tests/winFile.test
index 756144e..bfba9cf 100644
--- a/tests/winFile.test
+++ b/tests/winFile.test
@@ -1,29 +1,41 @@
# This file tests the tclWinFile.c file.
#
-# This file contains a collection of tests for one or more of the Tcl
-# built-in commands. Sourcing this file into Tcl runs the tests and
-# generates output for errors. No output means no errors were found.
+# This file contains a collection of tests for one or more of the Tcl built-in
+# commands. Sourcing this file into Tcl runs the tests and generates output
+# for errors. No output means no errors were found.
#
# Copyright (c) 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.
+# See the file "license.terms" for information on usage and redistribution of
+# this file, and for a DISCLAIMER OF ALL WARRANTIES.
-if {[lsearch [namespace children] ::tcltest] == -1} {
- package require tcltest
- namespace import -force ::tcltest::*
+if {[catch {package require tcltest 2.0.2}]} {
+ puts stderr "Skipping tests in [info script]. tcltest 2.0.2 required."
+ return
}
+namespace import -force ::tcltest::*
-test winFile-1.1 {TclpGetUserHome} {pcOnly} {
+testConstraint testvolumetype [llength [info commands testvolumetype]]
+testConstraint notNTFS 0
+testConstraint win2000 0
+
+if {[testConstraint testvolumetype]} {
+ testConstraint notNTFS [expr {[testvolumetype] eq "NTFS"}]
+}
+if {[testConstraint nt] && $::tcl_platform(osVersion) >= 5.0} {
+ testConstraint win2000 1
+}
+
+test winFile-1.1 {TclpGetUserHome} {win} {
list [catch {glob ~nosuchuser} msg] $msg
} {1 {user "nosuchuser" doesn't exist}}
-test winFile-1.2 {TclpGetUserHome} {pcOnly nt nonPortable} {
+test winFile-1.2 {TclpGetUserHome} {win nt nonPortable} {
# The administrator account should always exist.
catch {glob ~administrator}
} {0}
-test winFile-1.3 {TclpGetUserHome} {pcOnly 95} {
+test winFile-1.3 {TclpGetUserHome} {win 95} {
# Find some user in system.ini and then see if they have a home.
set f [open $::env(windir)/system.ini]
@@ -42,25 +54,24 @@ test winFile-1.3 {TclpGetUserHome} {pcOnly 95} {
close $f
set x
} {0}
-test winFile-1.4 {TclpGetUserHome} {pcOnly nt nonPortable} {
+test winFile-1.4 {TclpGetUserHome} {win nt nonPortable} {
catch {glob ~stanton@workgroup}
} {0}
-test winFile-2.1 {TclpMatchFiles: case sensitivity} {pcOnly} {
+test winFile-2.1 {TclpMatchFiles: case sensitivity} {win} {
makeFile {} GlobCapS
set result [list [glob -nocomplain GlobC*] [glob -nocomplain globc*]]
removeFile GlobCapS
set result
} {GlobCapS GlobCapS}
-
-test winFile-2.2 {TclpMatchFiles: case sensitivity} {pcOnly} {
+test winFile-2.2 {TclpMatchFiles: case sensitivity} {win} {
makeFile {} globlower
set result [list [glob -nocomplain globl*] [glob -nocomplain gLOBl*]]
removeFile globlower
set result
} {globlower globlower}
-test winFile-3.1 {file system} {pcOnly} {
+test winFile-3.1 {file system} {win testvolumetype} {
set res "volume types ok"
foreach vol [file volumes] {
# Have to catch in case there is a removable drive (CDROM, floppy)
@@ -76,18 +87,157 @@ test winFile-3.1 {file system} {pcOnly} {
set res
} {volume types ok}
-# cleanup
-::tcltest::cleanupTests
-return
-
-
-
-
-
+proc cacls {fname args} {
+ string trim [eval [list exec cacls [file nativename $fname]] $args <<y]
+}
+# dir/q output:
+# 2003-11-03 20:36 598 OCTAVIAN\benny filename.txt
+# Note this output from a german win2k machine:
+# 14.12.2007 14:26 30 VORDEFINIERT\Administratest.dat
+#
+# Modified to cope with Msys environment and use ls -l.
+proc getuser {fname} {
+ global env
+ set tryname $fname
+ if {[file isdirectory $fname]} {
+ set tryname [file dirname $fname]
+ }
+ set owner ""
+ set tail [file tail $tryname]
+ if {[info exists env(OSTYPE)] && [string equal $env(OSTYPE) "msys"]} {
+ set dirtext [exec ls -l $fname]
+ foreach line [split $dirtext "\n"] {
+ set owner [lindex $line 2]
+ }
+ } else {
+ set dirtext [exec cmd /c dir /q [file nativename $fname]]
+ foreach line [split $dirtext "\n"] {
+ if {[string match -nocase "*$tail" $line]} {
+ set attrs [string range $line \
+ 0 end-[string length $tail]]
+ regexp { [^ \\]+\\.*$} $attrs owner
+ set owner [string trim $owner]
+ }
+ }
+ }
+ if {[string length $owner] == 0} {
+ error "getuser: Owner not found in output of dir/q"
+ }
+ return $owner
+}
+proc test_read {fname} {
+ if {[catch {set ifs [open $fname r]}]} {
+ return 0
+ }
+ set readfailed [catch {read $ifs}]
+ return [expr {![catch {close $ifs}] && !$readfailed}]
+}
+proc test_writ {fname} {
+ if {[catch {set ofs [open $fname w]}]} {
+ return 0
+ }
+ set writefailed [catch {puts $ofs "Hello"}]
+ return [expr {![catch {close $ofs}] && !$writefailed}]
+}
+proc test_access {fname read writ} {
+ set problem {}
+ foreach type {read writ} {
+ if {[set $type] != [file ${type}able $fname]} {
+ lappend problem "[set $type] != \[file ${type}able $fname\]"
+ }
+ if {[set $type] != [test_${type} $fname]} {
+ lappend problem "[set $type] != \[test_${type} $fname\]"
+ }
+ }
+ if {[llength $problem]} {
+ return "Problem [join $problem \n]\nActual rights are: [cacls $fname]"
+ } else {
+ return ""
+ }
+}
+if {[testConstraint win]} {
+ # Create the test file
+ # NOTE: [tcltest::makeFile] not used. Presumably to force file
+ # creation in a particular filesystem? If not, try [makeFile]
+ # in a -setup script.
+ set fname test.dat
+ file delete $fname
+ close [open $fname w]
+}
+test winFile-4.0 {
+ Enhanced NTFS user/group permissions: test no acccess
+} -constraints {
+ win nt notNTFS win2000
+} -setup {
+ set owner [getuser $fname]
+ set user $::env(USERDOMAIN)\\$::env(USERNAME)
+} -body {
+ # Clean out all well-known ACLs
+ catch {cacls $fname /E /R "Everyone"} result
+ catch {cacls $fname /E /R $user} result
+ catch {cacls $fname /E /R $owner} result
+ cacls $fname /E /P $user:N
+ test_access $fname 0 0
+} -result {}
+test winFile-4.1 {
+ Enhanced NTFS user/group permissions: test readable only
+} -constraints {
+ win nt notNTFS
+} -setup {
+ set user $::env(USERDOMAIN)\\$::env(USERNAME)
+} -body {
+ cacls $fname /E /P $user:N
+ cacls $fname /E /G $user:R
+ test_access $fname 1 0
+} -result {}
+test winFile-4.2 {
+ Enhanced NTFS user/group permissions: test writable only
+} -constraints {
+ win nt notNTFS
+} -setup {
+ set user $::env(USERDOMAIN)\\$::env(USERNAME)
+} -body {
+ catch {cacls $fname /E /R $user} result
+ cacls $fname /E /P $user:N
+ cacls $fname /E /G $user:W
+ test_access $fname 0 1
+} -result {}
+test winFile-4.3 {
+ Enhanced NTFS user/group permissions: test read+write
+} -constraints {
+ win nt notNTFS
+} -setup {
+ set user $::env(USERDOMAIN)\\$::env(USERNAME)
+} -body {
+ catch {cacls $fname /E /R $user} result
+ cacls $fname /E /P $user:N
+ cacls $fname /E /G $user:R
+ cacls $fname /E /G $user:W
+ test_access $fname 1 1
+} -result {}
+test winFile-4.4 {
+ Enhanced NTFS user/group permissions: test full access
+} -constraints {
+ win nt notNTFS
+} -setup {
+ set user $::env(USERDOMAIN)\\$::env(USERNAME)
+} -body {
+ catch {cacls $fname /E /R $user} result
+ cacls $fname /E /P $user:N
+ cacls $fname /E /G $user:F
+ test_access $fname 1 1
+} -result {}
+
+if {[testConstraint win]} {
+ file delete $fname
+}
+# cleanup
+cleanupTests
+return
diff --git a/tests/winNotify.test b/tests/winNotify.test
index c237bd3..f9c75a3 100644
--- a/tests/winNotify.test
+++ b/tests/winNotify.test
@@ -15,18 +15,17 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
namespace import -force ::tcltest::*
}
-set ::tcltest::testConstraints(testeventloop) \
- [expr {[info commands testeventloop] != {}}]
+testConstraint testeventloop [expr {[info commands testeventloop] != {}}]
# There is no explicit test for InitNotifier or NotifierExitHandler
-test winNotify-1.1 {Tcl_SetTimer: positive timeout} {pcOnly} {
+test winNotify-1.1 {Tcl_SetTimer: positive timeout} {win} {
set done 0
after 1000 { set done 1 }
vwait done
set done
} 1
-test winNotify-1.2 {Tcl_SetTimer: positive timeout, message pending} {pcOnly} {
+test winNotify-1.2 {Tcl_SetTimer: positive timeout, message pending} {win} {
set x 0
set y 1
set a1 [after 0 { incr y }]
@@ -35,7 +34,7 @@ test winNotify-1.2 {Tcl_SetTimer: positive timeout, message pending} {pcOnly} {
vwait x
list $x $y
} {1 1}
-test winNotify-1.3 {Tcl_SetTimer: cancelling positive timeout} {pcOnly} {
+test winNotify-1.3 {Tcl_SetTimer: cancelling positive timeout} {win} {
set x 0
set y 1
set id [after 10000 { incr y }]
@@ -44,7 +43,7 @@ test winNotify-1.3 {Tcl_SetTimer: cancelling positive timeout} {pcOnly} {
after cancel $id
list $x $y
} {1 1}
-test winNotify-1.4 {Tcl_SetTimer: null timeout, message pending} {pcOnly} {
+test winNotify-1.4 {Tcl_SetTimer: null timeout, message pending} {win} {
set x 0
set y 1
after 0 { incr x }
@@ -53,14 +52,14 @@ test winNotify-1.4 {Tcl_SetTimer: null timeout, message pending} {pcOnly} {
list $x $y
} {1 2}
-test winNotify-2.1 {Tcl_ResetIdleTimer} {pcOnly} {
+test winNotify-2.1 {Tcl_ResetIdleTimer} {win} {
set x 0
update
after idle { incr x }
vwait x
set x
} 1
-test winNotify-2.2 {Tcl_ResetIdleTimer: message pending} {pcOnly} {
+test winNotify-2.2 {Tcl_ResetIdleTimer: message pending} {win} {
set x 0
set y 1
update
@@ -70,7 +69,7 @@ test winNotify-2.2 {Tcl_ResetIdleTimer: message pending} {pcOnly} {
list $x $y
} {1 2}
-test winNotify-3.1 {NotifierProc: non-modal normal timer} {pcOnly testeventloop} {
+test winNotify-3.1 {NotifierProc: non-modal normal timer} {win testeventloop} {
update
set x 0
foreach i [after info] {
@@ -80,7 +79,7 @@ test winNotify-3.1 {NotifierProc: non-modal normal timer} {pcOnly testeventloop}
testeventloop wait
set x
} 1
-test winNotify-3.2 {NotifierProc: non-modal normal timer, rescheduled} {pcOnly testeventloop} {
+test winNotify-3.2 {NotifierProc: non-modal normal timer, rescheduled} {win testeventloop} {
update
set x 0
foreach i [after info] {
@@ -90,7 +89,7 @@ test winNotify-3.2 {NotifierProc: non-modal normal timer, rescheduled} {pcOnly t
testeventloop wait
set x
} 2
-test winNotify-3.3 {NotifierProc: modal normal timer} {pcOnly} {
+test winNotify-3.3 {NotifierProc: modal normal timer} {win} {
update
set x 0
foreach i [after info] {
@@ -100,7 +99,7 @@ test winNotify-3.3 {NotifierProc: modal normal timer} {pcOnly} {
vwait x
set x
} 1
-test winNotify-3.4 {NotifierProc: modal normal timer, rescheduled} {pcOnly} {
+test winNotify-3.4 {NotifierProc: modal normal timer, rescheduled} {win} {
update
set x 0
foreach i [after info] {
@@ -111,7 +110,7 @@ test winNotify-3.4 {NotifierProc: modal normal timer, rescheduled} {pcOnly} {
vwait x
list $x $y
} {1 1}
-test winNotify-3.5 {NotifierProc: non-modal idle timer} {pcOnly testeventloop} {
+test winNotify-3.5 {NotifierProc: non-modal idle timer} {win testeventloop} {
update
set x 0
foreach i [after info] {
@@ -121,7 +120,7 @@ test winNotify-3.5 {NotifierProc: non-modal idle timer} {pcOnly testeventloop} {
testeventloop wait
set x
} 1
-test winNotify-3.6 {NotifierProc: non-modal idle timer, rescheduled} {pcOnly testeventloop} {
+test winNotify-3.6 {NotifierProc: non-modal idle timer, rescheduled} {win testeventloop} {
update
set x 0
foreach i [after info] {
@@ -131,7 +130,7 @@ test winNotify-3.6 {NotifierProc: non-modal idle timer, rescheduled} {pcOnly tes
testeventloop wait
set x
} 2
-test winNotify-3.7 {NotifierProc: modal idle timer} {pcOnly} {
+test winNotify-3.7 {NotifierProc: modal idle timer} {win} {
update
set x 0
foreach i [after info] {
@@ -141,7 +140,7 @@ test winNotify-3.7 {NotifierProc: modal idle timer} {pcOnly} {
vwait x
set x
} 1
-test winNotify-3.8 {NotifierProc: modal idle timer, rescheduled} {pcOnly} {
+test winNotify-3.8 {NotifierProc: modal idle timer, rescheduled} {win} {
update
set x 0
foreach i [after info] {
@@ -158,15 +157,3 @@ test winNotify-3.8 {NotifierProc: modal idle timer, rescheduled} {pcOnly} {
# cleanup
::tcltest::cleanupTests
return
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/winPipe.test b/tests/winPipe.test
index e2687ea..3f983e1 100644
--- a/tests/winPipe.test
+++ b/tests/winPipe.test
@@ -1,10 +1,10 @@
-#
+#
# winPipe.test --
#
# This file contains a collection of tests for tclWinPipe.c
#
-# Sourcing this file into Tcl runs the tests and generates output for
-# errors. No output means no errors were found.
+# Sourcing this file into Tcl runs the tests and generates output for errors.
+# No output (except for one message) means no errors were found.
#
# Copyright (c) 1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
@@ -16,18 +16,14 @@ package require tcltest
namespace import -force ::tcltest::*
unset -nocomplain path
-testConstraint exec [llength [info commands exec]]
set bindir [file join [pwd] [file dirname [info nameofexecutable]]]
set cat32 [file join $bindir cat32.exe]
-set ::tcltest::testConstraints(cat32) [file exists $cat32]
-
-if {[catch {puts console1 ""}]} {
- set ::tcltest::testConstraints(AllocConsole) 1
-} else {
- set ::tcltest::testConstraints(.console) 1
-}
+testConstraint exec [llength [info commands exec]]
+testConstraint cat32 [file exists $cat32]
+testConstraint AllocConsole [catch {puts console1 ""}]
+testConstraint RealConsole [expr {![testConstraint AllocConsole]}]
set big bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n
append big $big
@@ -63,90 +59,90 @@ set path(more) [makeFile {
set path(stdout) [makeFile {} stdout]
set path(stderr) [makeFile {} stderr]
-test winpipe-1.1 {32 bit comprehensive tests: from little file} {pcOnly exec cat32} {
+test winpipe-1.1 {32 bit comprehensive tests: from little file} {win exec cat32} {
exec $cat32 < $path(little) > $path(stdout) 2> $path(stderr)
list [contents $path(stdout)] [contents $path(stderr)]
} {little stderr32}
-test winpipe-1.2 {32 bit comprehensive tests: from big file} {pcOnly exec cat32} {
+test winpipe-1.2 {32 bit comprehensive tests: from big file} {win exec cat32} {
exec $cat32 < $path(big) > $path(stdout) 2> $path(stderr)
list [contents $path(stdout)] [contents $path(stderr)]
} "{$big} stderr32"
-test winpipe-1.3 {32 bit comprehensive tests: a little from pipe} {pcOnly nt exec cat32} {
+test winpipe-1.3 {32 bit comprehensive tests: a little from pipe} {win nt exec cat32} {
exec [interpreter] more < little | $cat32 > $path(stdout) 2> $path(stderr)
list [contents $path(stdout)] [contents $path(stderr)]
} {little stderr32}
-test winpipe-1.4 {32 bit comprehensive tests: a lot from pipe} {pcOnly nt exec cat32} {
+test winpipe-1.4 {32 bit comprehensive tests: a lot from pipe} {win nt exec cat32} {
exec [interpreter] more < big | $cat32 > $path(stdout) 2> $path(stderr)
list [contents $path(stdout)] [contents $path(stderr)]
} "{$big} stderr32"
-test winpipe-1.5 {32 bit comprehensive tests: a lot from pipe} {pcOnly 95 exec cat32} {
+test winpipe-1.5 {32 bit comprehensive tests: a lot from pipe} {win 95 exec cat32} {
exec command /c type big |& $cat32 > $path(stdout) 2> $path(stderr)
list [contents $path(stdout)] [contents $path(stderr)]
} "{$big} stderr32"
test winpipe-1.6 {32 bit comprehensive tests: from console} \
- {pcOnly cat32 AllocConsole} {
+ {win cat32 AllocConsole} {
# would block waiting for human input
} {}
-test winpipe-1.7 {32 bit comprehensive tests: from NUL} {pcOnly exec cat32} {
+test winpipe-1.7 {32 bit comprehensive tests: from NUL} {win exec cat32} {
exec $cat32 < nul > $path(stdout) 2> $path(stderr)
list [contents $path(stdout)] [contents $path(stderr)]
} {{} stderr32}
-test winpipe-1.8 {32 bit comprehensive tests: from socket} {pcOnly cat32} {
+test winpipe-1.8 {32 bit comprehensive tests: from socket} {win cat32} {
# doesn't work
} {}
test winpipe-1.9 {32 bit comprehensive tests: from nowhere} \
- {pcOnly exec cat32 .console} {
+ {win exec cat32 RealConsole} {
exec $cat32 > $path(stdout) 2> $path(stderr)
list [contents $path(stdout)] [contents $path(stderr)]
} {{} stderr32}
test winpipe-1.10 {32 bit comprehensive tests: from file handle} \
- {pcOnly exec cat32} {
+ {win exec cat32} {
set f [open $path(little) r]
exec $cat32 <@$f > $path(stdout) 2> $path(stderr)
close $f
list [contents $path(stdout)] [contents $path(stderr)]
} {little stderr32}
test winpipe-1.11 {32 bit comprehensive tests: read from application} \
- {pcOnly exec cat32} {
- set f [open "|[list $cat32] < $path(little)" r]
+ {win exec cat32} {
+ set f [open "|[list $cat32] < [list $path(little)]" r]
gets $f line
catch {close $f} msg
list $line $msg
} {little stderr32}
test winpipe-1.12 {32 bit comprehensive tests: a little to file} \
- {pcOnly exec cat32} {
+ {win exec cat32} {
exec $cat32 < $path(little) > $path(stdout) 2> $path(stderr)
list [contents $path(stdout)] [contents $path(stderr)]
} {little stderr32}
test winpipe-1.13 {32 bit comprehensive tests: a lot to file} \
- {pcOnly exec cat32} {
+ {win exec cat32} {
exec $cat32 < $path(big) > $path(stdout) 2> $path(stderr)
list [contents $path(stdout)] [contents $path(stderr)]
} "{$big} stderr32"
test winpipe-1.14 {32 bit comprehensive tests: a little to pipe} \
- {pcOnly exec stdio cat32} {
+ {win exec stdio cat32} {
exec $cat32 < $path(little) | [interpreter] $path(more) > $path(stdout) 2> $path(stderr)
list [contents $path(stdout)] [contents $path(stderr)]
} {little stderr32}
test winpipe-1.15 {32 bit comprehensive tests: a lot to pipe} \
- {pcOnly exec stdio cat32} {
+ {win exec stdio cat32} {
exec $cat32 < $path(big) | [interpreter] $path(more) > $path(stdout) 2> $path(stderr)
list [contents $path(stdout)] [contents $path(stderr)]
} "{$big} stderr32"
-test winpipe-1.16 {32 bit comprehensive tests: to console} {pcOnly exec cat32} {
+test winpipe-1.16 {32 bit comprehensive tests: to console} {win exec cat32} {
catch {exec $cat32 << "You should see this\n" >@stdout} msg
set msg
} stderr32
-test winpipe-1.17 {32 bit comprehensive tests: to NUL} {pcOnly exec cat32} {
+test winpipe-1.17 {32 bit comprehensive tests: to NUL} {win exec cat32} {
# some apps hang when sending a large amount to NUL. $cat32 isn't one.
catch {exec $cat32 < $path(big) > nul} msg
set msg
} stderr32
test winpipe-1.18 {32 bit comprehensive tests: to nowhere} \
- {pcOnly exec cat32 .console} {
- exec $cat32 < $path(big) >&@stdout
+ {win exec cat32 RealConsole} {
+ exec $cat32 < $path(big) >&@stdout
} {}
-test winpipe-1.19 {32 bit comprehensive tests: to file handle} {pcOnly exec cat32} {
+test winpipe-1.19 {32 bit comprehensive tests: to file handle} {win exec cat32} {
set f1 [open $path(stdout) w]
set f2 [open $path(stderr) w]
exec $cat32 < $path(little) >@$f1 2>@$f2
@@ -155,14 +151,14 @@ test winpipe-1.19 {32 bit comprehensive tests: to file handle} {pcOnly exec cat3
list [contents $path(stdout)] [contents $path(stderr)]
} {little stderr32}
test winpipe-1.20 {32 bit comprehensive tests: write to application} \
- {pcOnly exec cat32} {
+ {win exec cat32} {
set f [open |[list $cat32 >$path(stdout)] w]
puts -nonewline $f "foo"
catch {close $f} msg
list [contents $path(stdout)] $msg
} {foo stderr32}
test winpipe-1.21 {32 bit comprehensive tests: read/write application} \
- {pcOnly exec cat32} {
+ {win exec cat32} {
set f [open "|[list $cat32]" r+]
puts $f $big
puts $f \032
@@ -171,13 +167,13 @@ test winpipe-1.21 {32 bit comprehensive tests: read/write application} \
catch {close $f}
set r
} "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
-test winpipe-1.22 {Checking command.com for Win95/98 hanging} {pcOnly 95 exec} {
+test winpipe-1.22 {Checking command.com for Win95/98 hanging} {win 95 exec} {
exec command.com /c dir /b
set result 1
} 1
file delete more
-test winpipe-4.1 {Tcl_WaitPid} {pcOnly nt exec cat32} {
+test winpipe-4.1 {Tcl_WaitPid} {win nt exec cat32} {
proc readResults {f} {
global x result
if { [eof $f] } {
@@ -197,29 +193,29 @@ test winpipe-4.1 {Tcl_WaitPid} {pcOnly nt exec cat32} {
vwait x
list $result $x [contents $path(stderr)]
} "{$big} 1 stderr32"
-test winpipe-4.2 {Tcl_WaitPid: return of exception codes, SIGFPE} {pcOnly exec} {
- set f [open "|[tcltest::interpreter]" w+]
+test winpipe-4.2 {Tcl_WaitPid: return of exception codes, SIGFPE} {win exec} {
+ set f [open "|[list [interpreter]]" w+]
set pid [pid $f]
puts $f "testexcept float_underflow"
set status [catch {close $f}]
list $status [expr {$pid == [lindex $::errorCode 1]}] [lindex $::errorCode 2]
} {1 1 SIGFPE}
-test winpipe-4.3 {Tcl_WaitPid: return of exception codes, SIGSEGV} {pcOnly exec} {
- set f [open "|[tcltest::interpreter]" w+]
+test winpipe-4.3 {Tcl_WaitPid: return of exception codes, SIGSEGV} {win exec} {
+ set f [open "|[list [interpreter]]" w+]
set pid [pid $f]
puts $f "testexcept access_violation"
set status [catch {close $f}]
list $status [expr {$pid == [lindex $::errorCode 1]}] [lindex $::errorCode 2]
} {1 1 SIGSEGV}
-test winpipe-4.4 {Tcl_WaitPid: return of exception codes, SIGILL} {pcOnly exec} {
- set f [open "|[tcltest::interpreter]" w+]
+test winpipe-4.4 {Tcl_WaitPid: return of exception codes, SIGILL} {win exec} {
+ set f [open "|[list [interpreter]]" w+]
set pid [pid $f]
puts $f "testexcept illegal_instruction"
set status [catch {close $f}]
list $status [expr {$pid == [lindex $::errorCode 1]}] [lindex $::errorCode 2]
} {1 1 SIGILL}
-test winpipe-4.5 {Tcl_WaitPid: return of exception codes, SIGINT} {pcOnly exec} {
- set f [open "|[tcltest::interpreter]" w+]
+test winpipe-4.5 {Tcl_WaitPid: return of exception codes, SIGINT} {win exec} {
+ set f [open "|[list [interpreter]]" w+]
set pid [pid $f]
puts $f "testexcept ctrl+c"
set status [catch {close $f}]
@@ -235,7 +231,7 @@ catch {set env_temp $env(TEMP)}
set env(TMP) c:/
set env(TEMP) c:/
-test winpipe-5.1 {TclpCreateTempFile: cleanup temp files} {pcOnly exec} {
+test winpipe-5.1 {TclpCreateTempFile: cleanup temp files} {win exec} {
set x {}
set existing [glob -nocomplain c:/tcl*.tmp]
exec [interpreter] < nothing
@@ -246,7 +242,7 @@ test winpipe-5.1 {TclpCreateTempFile: cleanup temp files} {pcOnly exec} {
}
set x
} {}
-test winpipe-5.2 {TclpCreateTempFile: TMP and TEMP not defined} {pcOnly exec} {
+test winpipe-5.2 {TclpCreateTempFile: TMP and TEMP not defined} {win exec} {
set tmp $env(TMP)
set temp $env(TEMP)
unset env(TMP)
@@ -257,7 +253,7 @@ test winpipe-5.2 {TclpCreateTempFile: TMP and TEMP not defined} {pcOnly exec} {
set x {}
} {}
test winpipe-5.3 {TclpCreateTempFile: TMP specifies non-existent directory} \
- {pcOnly exec } {
+ {win exec } {
set tmp $env(TMP)
set env(TMP) snarky
exec [interpreter] < nothing
@@ -265,7 +261,7 @@ test winpipe-5.3 {TclpCreateTempFile: TMP specifies non-existent directory} \
set x {}
} {}
test winpipe-5.4 {TclpCreateTempFile: TEMP specifies non-existent directory} \
- {pcOnly exec} {
+ {win exec} {
set tmp $env(TMP)
set temp $env(TEMP)
unset env(TMP)
@@ -277,7 +273,7 @@ test winpipe-5.4 {TclpCreateTempFile: TEMP specifies non-existent directory} \
} {}
test winpipe-6.1 {PipeSetupProc & PipeCheckProc: read threads} \
- {pcOnly exec cat32} {
+ {win exec cat32} {
set f [open "|[list $cat32]" r+]
fconfigure $f -blocking 0
fileevent $f writable { set x writable }
@@ -298,7 +294,7 @@ test winpipe-6.1 {PipeSetupProc & PipeCheckProc: read threads} \
} {writable timeout readable {foobar
} timeout 1 stderr32}
test winpipe-6.2 {PipeSetupProc & PipeCheckProc: write threads} \
- {pcOnly exec cat32} {
+ {win exec cat32} {
set f [open "|[list $cat32]" r+]
fconfigure $f -blocking 0
fileevent $f writable { set x writable }
@@ -315,120 +311,121 @@ set path(echoArgs.tcl) [makeFile {
puts "[list $argv0 $argv]"
} echoArgs.tcl]
+
### validate the raw output of BuildCommandLine().
###
-test winpipe-7.1 {BuildCommandLine: null arguments} {pcOnly exec} {
+test winpipe-7.1 {BuildCommandLine: null arguments} {win exec} {
exec $env(COMSPEC) /c echo foo "" bar
} {foo "" bar}
-test winpipe-7.2 {BuildCommandLine: null arguments} {pcOnly exec} {
+test winpipe-7.2 {BuildCommandLine: null arguments} {win exec} {
exec $env(COMSPEC) /c echo foo {} bar
} {foo "" bar}
-test winpipe-7.3 {BuildCommandLine: dbl quote quoting #1} {pcOnly exec} {
- exec $env(COMSPEC) /c echo foo {"} bar
+test winpipe-7.3 {BuildCommandLine: dbl quote quoting #1} {win exec} {
+ exec $env(COMSPEC) /c echo foo "\"" bar
} {foo \" bar}
-test winpipe-7.4 {BuildCommandLine: dbl quote quoting #2} {pcOnly exec} {
+test winpipe-7.4 {BuildCommandLine: dbl quote quoting #2} {win exec} {
exec $env(COMSPEC) /c echo foo {""} bar
} {foo \"\" bar}
-test winpipe-7.5 {BuildCommandLine: dbl quote quoting #3} {pcOnly exec} {
- exec $env(COMSPEC) /c echo foo {" } bar
+test winpipe-7.5 {BuildCommandLine: dbl quote quoting #3} {win exec} {
+ exec $env(COMSPEC) /c echo foo "\" " bar
} {foo "\" " bar}
-test winpipe-7.6 {BuildCommandLine: dbl quote quoting #4} {pcOnly exec} {
+test winpipe-7.6 {BuildCommandLine: dbl quote quoting #4} {win exec} {
exec $env(COMSPEC) /c echo foo {a="b"} bar
} {foo a=\"b\" bar}
-test winpipe-7.7 {BuildCommandLine: dbl quote quoting #5} {pcOnly exec} {
+test winpipe-7.7 {BuildCommandLine: dbl quote quoting #5} {win exec} {
exec $env(COMSPEC) /c echo foo {a = "b"} bar
} {foo "a = \"b\"" bar}
-test winpipe-7.8 {BuildCommandLine: dbl quote quoting #6} {pcOnly exec} {
- exec $env(COMSPEC) /c echo {"hello"} {""hello""} {"""hello"""} {"\"hello\""} {he llo} {he " llo}
+test winpipe-7.8 {BuildCommandLine: dbl quote quoting #6} {win exec} {
+ exec $env(COMSPEC) /c echo {"hello"} {""hello""} {"""hello"""} {"\"hello\""} {he llo} "he \" llo"
} {\"hello\" \"\"hello\"\" \"\"\"hello\"\"\" \"\\\"hello\\\"\" "he llo" "he \" llo"}
-test winpipe-7.9 {BuildCommandLine: N backslashes followed a quote rule #1} {pcOnly exec} {
+test winpipe-7.9 {BuildCommandLine: N backslashes followed a quote rule #1} {win exec} {
exec $env(COMSPEC) /c echo foo \\ bar
} {foo \ bar}
-test winpipe-7.10 {BuildCommandLine: N backslashes followed a quote rule #2} {pcOnly exec} {
+test winpipe-7.10 {BuildCommandLine: N backslashes followed a quote rule #2} {win exec} {
exec $env(COMSPEC) /c echo foo \\\\ bar
} {foo \\ bar}
-test winpipe-7.11 {BuildCommandLine: N backslashes followed a quote rule #3} {pcOnly exec} {
+test winpipe-7.11 {BuildCommandLine: N backslashes followed a quote rule #3} {win exec} {
exec $env(COMSPEC) /c echo foo \\\ \\ bar
} {foo "\ \\" bar}
-test winpipe-7.12 {BuildCommandLine: N backslashes followed a quote rule #4} {pcOnly exec} {
+test winpipe-7.12 {BuildCommandLine: N backslashes followed a quote rule #4} {win exec} {
exec $env(COMSPEC) /c echo foo \\\ \\\\ bar
} {foo "\ \\\\" bar}
-test winpipe-7.13 {BuildCommandLine: N backslashes followed a quote rule #5} {pcOnly exec} {
+test winpipe-7.13 {BuildCommandLine: N backslashes followed a quote rule #5} {win exec} {
exec $env(COMSPEC) /c echo foo \\\ \\\\\\ bar
} {foo "\ \\\\\\" bar}
-test winpipe-7.14 {BuildCommandLine: N backslashes followed a quote rule #6} {pcOnly exec} {
+test winpipe-7.14 {BuildCommandLine: N backslashes followed a quote rule #6} {win exec} {
exec $env(COMSPEC) /c echo foo \\\ \\\" bar
} {foo "\ \\\"" bar}
-test winpipe-7.15 {BuildCommandLine: N backslashes followed a quote rule #7} {pcOnly exec} {
+test winpipe-7.15 {BuildCommandLine: N backslashes followed a quote rule #7} {win exec} {
exec $env(COMSPEC) /c echo foo \\\ \\\\\" bar
} {foo "\ \\\\\"" bar}
-test winpipe-7.16 {BuildCommandLine: N backslashes followed a quote rule #8} {pcOnly exec} {
+test winpipe-7.16 {BuildCommandLine: N backslashes followed a quote rule #8} {win exec} {
exec $env(COMSPEC) /c echo foo \\\ \\\\\\\" bar
} {foo "\ \\\\\\\"" bar}
-test winpipe-7.17 {BuildCommandLine: special chars #4} {pcOnly exec} {
+test winpipe-7.17 {BuildCommandLine: special chars #4} {win exec} {
exec $env(COMSPEC) /c echo foo \{ bar
} "foo \{ bar"
-test winpipe-7.18 {BuildCommandLine: special chars #5} {pcOnly exec} {
+test winpipe-7.18 {BuildCommandLine: special chars #5} {win exec} {
exec $env(COMSPEC) /c echo foo \} bar
} "foo \} bar"
### validate the pass-thru from BuildCommandLine() to the crt's parse_cmdline().
###
-test winpipe-8.1 {BuildCommandLine/parse_cmdline pass-thru: null arguments} {pcOnly exec} {
+test winpipe-8.1 {BuildCommandLine/parse_cmdline pass-thru: null arguments} {win exec} {
exec [interpreter] $path(echoArgs.tcl) foo "" bar
} [list $path(echoArgs.tcl) [list foo {} bar]]
-test winpipe-8.2 {BuildCommandLine/parse_cmdline pass-thru: null arguments} {pcOnly exec} {
+test winpipe-8.2 {BuildCommandLine/parse_cmdline pass-thru: null arguments} {win exec} {
exec [interpreter] $path(echoArgs.tcl) foo {} bar
} [list $path(echoArgs.tcl) [list foo {} bar]]
-test winpipe-8.3 {BuildCommandLine/parse_cmdline pass-thru: dbl quote quoting #1} {pcOnly exec} {
- exec [interpreter] $path(echoArgs.tcl) foo {"} bar
-} [list $path(echoArgs.tcl) [list foo {"} bar]]
-test winpipe-8.4 {BuildCommandLine/parse_cmdline pass-thru: dbl quote quoting #2} {pcOnly exec} {
+test winpipe-8.3 {BuildCommandLine/parse_cmdline pass-thru: dbl quote quoting #1} {win exec} {
+ exec [interpreter] $path(echoArgs.tcl) foo "\"" bar
+} [list $path(echoArgs.tcl) [list foo "\"" bar]]
+test winpipe-8.4 {BuildCommandLine/parse_cmdline pass-thru: dbl quote quoting #2} {win exec} {
exec [interpreter] $path(echoArgs.tcl) foo {""} bar
} [list $path(echoArgs.tcl) [list foo {""} bar]]
-test winpipe-8.5 {BuildCommandLine/parse_cmdline pass-thru: dbl quote quoting #3} {pcOnly exec} {
- exec [interpreter] $path(echoArgs.tcl) foo {" } bar
-} [list $path(echoArgs.tcl) [list foo {" } bar]]
-test winpipe-8.6 {BuildCommandLine/parse_cmdline pass-thru: dbl quote quoting #4} {pcOnly exec} {
+test winpipe-8.5 {BuildCommandLine/parse_cmdline pass-thru: dbl quote quoting #3} {win exec} {
+ exec [interpreter] $path(echoArgs.tcl) foo "\" " bar
+} [list $path(echoArgs.tcl) [list foo "\" " bar]]
+test winpipe-8.6 {BuildCommandLine/parse_cmdline pass-thru: dbl quote quoting #4} {win exec} {
exec [interpreter] $path(echoArgs.tcl) foo {a="b"} bar
} [list $path(echoArgs.tcl) [list foo {a="b"} bar]]
-test winpipe-8.7 {BuildCommandLine/parse_cmdline pass-thru: dbl quote quoting #5} {pcOnly exec} {
+test winpipe-8.7 {BuildCommandLine/parse_cmdline pass-thru: dbl quote quoting #5} {win exec} {
exec [interpreter] $path(echoArgs.tcl) foo {a = "b"} bar
} [list $path(echoArgs.tcl) [list foo {a = "b"} bar]]
-test winpipe-8.8 {BuildCommandLine/parse_cmdline pass-thru: dbl quote quoting #6} {pcOnly exec} {
+test winpipe-8.8 {BuildCommandLine/parse_cmdline pass-thru: dbl quote quoting #6} {win exec} {
exec [interpreter] $path(echoArgs.tcl) {"hello"} {""hello""} {"""hello"""} {"\"hello\""} {he llo} {he " llo}
} [list $path(echoArgs.tcl) [list {"hello"} {""hello""} {"""hello"""} {"\"hello\""} {he llo} {he " llo}]]
-test winpipe-8.9 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #1} {pcOnly exec} {
+test winpipe-8.9 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #1} {win exec} {
exec [interpreter] $path(echoArgs.tcl) foo \\ bar
} [list $path(echoArgs.tcl) [list foo \\ bar]]
-test winpipe-8.10 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #2} {pcOnly exec} {
+test winpipe-8.10 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #2} {win exec} {
exec [interpreter] $path(echoArgs.tcl) foo \\\\ bar
} [list $path(echoArgs.tcl) [list foo \\\\ bar]]
-test winpipe-8.11 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #3} {pcOnly exec} {
+test winpipe-8.11 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #3} {win exec} {
exec [interpreter] $path(echoArgs.tcl) foo \\\ \\ bar
} [list $path(echoArgs.tcl) [list foo \\\ \\ bar]]
-test winpipe-8.12 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #4} {pcOnly exec} {
+test winpipe-8.12 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #4} {win exec} {
exec [interpreter] $path(echoArgs.tcl) foo \\\ \\\\ bar
} [list $path(echoArgs.tcl) [list foo \\\ \\\\ bar]]
-test winpipe-8.13 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #5} {pcOnly exec} {
+test winpipe-8.13 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #5} {win exec} {
exec [interpreter] $path(echoArgs.tcl) foo \\\ \\\\\\ bar
} [list $path(echoArgs.tcl) [list foo \\\ \\\\\\ bar]]
-test winpipe-8.14 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #6} {pcOnly exec} {
+test winpipe-8.14 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #6} {win exec} {
exec [interpreter] $path(echoArgs.tcl) foo \\\ \\\" bar
} [list $path(echoArgs.tcl) [list foo \\\ \\\" bar]]
-test winpipe-8.15 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #7} {pcOnly exec} {
+test winpipe-8.15 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #7} {win exec} {
exec [interpreter] $path(echoArgs.tcl) foo \\\ \\\\\" bar
} [list $path(echoArgs.tcl) [list foo \\\ \\\\\" bar]]
-test winpipe-8.16 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #8} {pcOnly exec} {
+test winpipe-8.16 {BuildCommandLine/parse_cmdline pass-thru: N backslashes followed a quote rule #8} {win exec} {
exec [interpreter] $path(echoArgs.tcl) foo \\\ \\\\\\\" bar
} [list $path(echoArgs.tcl) [list foo \\\ \\\\\\\" bar]]
-test winpipe-8.17 {BuildCommandLine/parse_cmdline pass-thru: special chars #1} {pcOnly exec} {
+test winpipe-8.17 {BuildCommandLine/parse_cmdline pass-thru: special chars #1} {win exec} {
exec [interpreter] $path(echoArgs.tcl) foo \{ bar
} [list $path(echoArgs.tcl) [list foo \{ bar]]
-test winpipe-8.18 {BuildCommandLine/parse_cmdline pass-thru: special chars #2} {pcOnly exec} {
+test winpipe-8.18 {BuildCommandLine/parse_cmdline pass-thru: special chars #2} {win exec} {
exec [interpreter] $path(echoArgs.tcl) foo \} bar
} [list $path(echoArgs.tcl) [list foo \} bar]]
-test winpipe-8.19 {ensure parse_cmdline isn't doing wildcard replacement} {pcOnly exec} {
+test winpipe-8.19 {ensure parse_cmdline isn't doing wildcard replacement} {win exec} {
exec [interpreter] $path(echoArgs.tcl) foo * makefile.?c bar
} [list $path(echoArgs.tcl) [list foo * makefile.?c bar]]
diff --git a/tests/winTime.test b/tests/winTime.test
index 9ce6b12..278db32 100644
--- a/tests/winTime.test
+++ b/tests/winTime.test
@@ -20,13 +20,13 @@ testConstraint testwinclock [llength [info commands testwinclock]]
# The next two tests will crash on Windows if the check for negative
# clock values is not done properly.
-test winTime-1.1 {TclpGetDate} {pcOnly} {
+test winTime-1.1 {TclpGetDate} {win} {
set ::env(TZ) JST-9
set result [clock format -1 -format %Y]
unset ::env(TZ)
set result
} {1970}
-test winTime-1.2 {TclpGetDate} {pcOnly} {
+test winTime-1.2 {TclpGetDate} {win} {
set ::env(TZ) PST8
set result [clock format 1 -format %Y]
unset ::env(TZ)
diff --git a/tools/checkLibraryDoc.tcl b/tools/checkLibraryDoc.tcl
index cd08c2a..cd08c2a 100755..100644
--- a/tools/checkLibraryDoc.tcl
+++ b/tools/checkLibraryDoc.tcl
diff --git a/tools/configure b/tools/configure
index 209d394..98b5867 100755..100644
--- a/tools/configure
+++ b/tools/configure
@@ -1,28 +1,288 @@
#! /bin/sh
-
# Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.13
-# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+# Generated by GNU Autoconf 2.59.
#
+# Copyright (C) 2003 Free Software Foundation, Inc.
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
-# Defaults:
-ac_help=
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
ac_default_prefix=/usr/local
-# Any additions from configure.in:
-ac_help="$ac_help
- --with-tcl=DIR use Tcl $DEF_VER binaries from DIR"
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete. It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="man2tcl.c"
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS TCL_WIN_VERSION CC TCL_VERSION TCL_PATCH_LEVEL TCL_SRC_DIR TCL_BIN_DIR LIBOBJS LTLIBOBJS'
+ac_subst_files=''
# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
# The variables have the same names as the options, with
# dashes changed to underlines.
-build=NONE
-cache_file=./config.cache
+cache_file=/dev/null
exec_prefix=NONE
-host=NONE
no_create=
-nonopt=NONE
no_recursion=
prefix=NONE
program_prefix=NONE
@@ -31,10 +291,15 @@ program_transform_name=s,x,x,
silent=
site=
srcdir=
-target=NONE
verbose=
x_includes=NONE
x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
bindir='${exec_prefix}/bin'
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
@@ -48,17 +313,9 @@ oldincludedir='/usr/include'
infodir='${prefix}/info'
mandir='${prefix}/man'
-# Initialize some other variables.
-subdirs=
-MFLAGS= MAKEFLAGS=
-SHELL=${CONFIG_SHELL-/bin/sh}
-# Maximum number of lines to put in a shell here document.
-ac_max_here_lines=12
-
ac_prev=
for ac_option
do
-
# If the previous option needs an argument, assign it.
if test -n "$ac_prev"; then
eval "$ac_prev=\$ac_option"
@@ -66,59 +323,59 @@ do
continue
fi
- case "$ac_option" in
- -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
- *) ac_optarg= ;;
- esac
+ ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
# Accept the important Cygnus configure options, so we can diagnose typos.
- case "$ac_option" in
+ case $ac_option in
-bindir | --bindir | --bindi | --bind | --bin | --bi)
ac_prev=bindir ;;
-bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
- bindir="$ac_optarg" ;;
+ bindir=$ac_optarg ;;
-build | --build | --buil | --bui | --bu)
- ac_prev=build ;;
+ ac_prev=build_alias ;;
-build=* | --build=* | --buil=* | --bui=* | --bu=*)
- build="$ac_optarg" ;;
+ build_alias=$ac_optarg ;;
-cache-file | --cache-file | --cache-fil | --cache-fi \
| --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
ac_prev=cache_file ;;
-cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
| --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
- cache_file="$ac_optarg" ;;
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
-datadir | --datadir | --datadi | --datad | --data | --dat | --da)
ac_prev=datadir ;;
-datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
| --da=*)
- datadir="$ac_optarg" ;;
+ datadir=$ac_optarg ;;
-disable-* | --disable-*)
- ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
- if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
- { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
- fi
- ac_feature=`echo $ac_feature| sed 's/-/_/g'`
- eval "enable_${ac_feature}=no" ;;
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ eval "enable_$ac_feature=no" ;;
-enable-* | --enable-*)
- ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
- if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
- { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
- fi
- ac_feature=`echo $ac_feature| sed 's/-/_/g'`
- case "$ac_option" in
- *=*) ;;
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
*) ac_optarg=yes ;;
esac
- eval "enable_${ac_feature}='$ac_optarg'" ;;
+ eval "enable_$ac_feature='$ac_optarg'" ;;
-exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
| --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
@@ -127,95 +384,47 @@ do
-exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
| --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
| --exec=* | --exe=* | --ex=*)
- exec_prefix="$ac_optarg" ;;
+ exec_prefix=$ac_optarg ;;
-gas | --gas | --ga | --g)
# Obsolete; use --with-gas.
with_gas=yes ;;
- -help | --help | --hel | --he)
- # Omit some internal or obsolete options to make the list less imposing.
- # This message is too long to be a string in the A/UX 3.1 sh.
- cat << EOF
-Usage: configure [options] [host]
-Options: [defaults in brackets after descriptions]
-Configuration:
- --cache-file=FILE cache test results in FILE
- --help print this message
- --no-create do not create output files
- --quiet, --silent do not print \`checking...' messages
- --version print the version of autoconf that created configure
-Directory and file names:
- --prefix=PREFIX install architecture-independent files in PREFIX
- [$ac_default_prefix]
- --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
- [same as prefix]
- --bindir=DIR user executables in DIR [EPREFIX/bin]
- --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
- --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
- --datadir=DIR read-only architecture-independent data in DIR
- [PREFIX/share]
- --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
- --sharedstatedir=DIR modifiable architecture-independent data in DIR
- [PREFIX/com]
- --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
- --libdir=DIR object code libraries in DIR [EPREFIX/lib]
- --includedir=DIR C header files in DIR [PREFIX/include]
- --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
- --infodir=DIR info documentation in DIR [PREFIX/info]
- --mandir=DIR man documentation in DIR [PREFIX/man]
- --srcdir=DIR find the sources in DIR [configure dir or ..]
- --program-prefix=PREFIX prepend PREFIX to installed program names
- --program-suffix=SUFFIX append SUFFIX to installed program names
- --program-transform-name=PROGRAM
- run sed PROGRAM on installed program names
-EOF
- cat << EOF
-Host type:
- --build=BUILD configure for building on BUILD [BUILD=HOST]
- --host=HOST configure for HOST [guessed]
- --target=TARGET configure for TARGET [TARGET=HOST]
-Features and packages:
- --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
- --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
- --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
- --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
- --x-includes=DIR X include files are in DIR
- --x-libraries=DIR X library files are in DIR
-EOF
- if test -n "$ac_help"; then
- echo "--enable and --with options recognized:$ac_help"
- fi
- exit 0 ;;
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
-host | --host | --hos | --ho)
- ac_prev=host ;;
+ ac_prev=host_alias ;;
-host=* | --host=* | --hos=* | --ho=*)
- host="$ac_optarg" ;;
+ host_alias=$ac_optarg ;;
-includedir | --includedir | --includedi | --included | --include \
| --includ | --inclu | --incl | --inc)
ac_prev=includedir ;;
-includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
| --includ=* | --inclu=* | --incl=* | --inc=*)
- includedir="$ac_optarg" ;;
+ includedir=$ac_optarg ;;
-infodir | --infodir | --infodi | --infod | --info | --inf)
ac_prev=infodir ;;
-infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
- infodir="$ac_optarg" ;;
+ infodir=$ac_optarg ;;
-libdir | --libdir | --libdi | --libd)
ac_prev=libdir ;;
-libdir=* | --libdir=* | --libdi=* | --libd=*)
- libdir="$ac_optarg" ;;
+ libdir=$ac_optarg ;;
-libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
| --libexe | --libex | --libe)
ac_prev=libexecdir ;;
-libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
| --libexe=* | --libex=* | --libe=*)
- libexecdir="$ac_optarg" ;;
+ libexecdir=$ac_optarg ;;
-localstatedir | --localstatedir | --localstatedi | --localstated \
| --localstate | --localstat | --localsta | --localst \
@@ -224,19 +433,19 @@ EOF
-localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
| --localstate=* | --localstat=* | --localsta=* | --localst=* \
| --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
- localstatedir="$ac_optarg" ;;
+ localstatedir=$ac_optarg ;;
-mandir | --mandir | --mandi | --mand | --man | --ma | --m)
ac_prev=mandir ;;
-mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
- mandir="$ac_optarg" ;;
+ mandir=$ac_optarg ;;
-nfp | --nfp | --nf)
# Obsolete; use --without-fp.
with_fp=no ;;
-no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c)
+ | --no-cr | --no-c | -n)
no_create=yes ;;
-no-recursion | --no-recursion | --no-recursio | --no-recursi \
@@ -250,26 +459,26 @@ EOF
-oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
| --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
| --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
- oldincludedir="$ac_optarg" ;;
+ oldincludedir=$ac_optarg ;;
-prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
ac_prev=prefix ;;
-prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
- prefix="$ac_optarg" ;;
+ prefix=$ac_optarg ;;
-program-prefix | --program-prefix | --program-prefi | --program-pref \
| --program-pre | --program-pr | --program-p)
ac_prev=program_prefix ;;
-program-prefix=* | --program-prefix=* | --program-prefi=* \
| --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
- program_prefix="$ac_optarg" ;;
+ program_prefix=$ac_optarg ;;
-program-suffix | --program-suffix | --program-suffi | --program-suff \
| --program-suf | --program-su | --program-s)
ac_prev=program_suffix ;;
-program-suffix=* | --program-suffix=* | --program-suffi=* \
| --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
- program_suffix="$ac_optarg" ;;
+ program_suffix=$ac_optarg ;;
-program-transform-name | --program-transform-name \
| --program-transform-nam | --program-transform-na \
@@ -286,7 +495,7 @@ EOF
| --program-transfo=* | --program-transf=* \
| --program-trans=* | --program-tran=* \
| --progr-tra=* | --program-tr=* | --program-t=*)
- program_transform_name="$ac_optarg" ;;
+ program_transform_name=$ac_optarg ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil)
@@ -296,7 +505,7 @@ EOF
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
| --sbi=* | --sb=*)
- sbindir="$ac_optarg" ;;
+ sbindir=$ac_optarg ;;
-sharedstatedir | --sharedstatedir | --sharedstatedi \
| --sharedstated | --sharedstate | --sharedstat | --sharedsta \
@@ -307,58 +516,57 @@ EOF
| --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
| --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
| --sha=* | --sh=*)
- sharedstatedir="$ac_optarg" ;;
+ sharedstatedir=$ac_optarg ;;
-site | --site | --sit)
ac_prev=site ;;
-site=* | --site=* | --sit=*)
- site="$ac_optarg" ;;
+ site=$ac_optarg ;;
-srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
ac_prev=srcdir ;;
-srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
- srcdir="$ac_optarg" ;;
+ srcdir=$ac_optarg ;;
-sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
| --syscon | --sysco | --sysc | --sys | --sy)
ac_prev=sysconfdir ;;
-sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
| --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
- sysconfdir="$ac_optarg" ;;
+ sysconfdir=$ac_optarg ;;
-target | --target | --targe | --targ | --tar | --ta | --t)
- ac_prev=target ;;
+ ac_prev=target_alias ;;
-target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
- target="$ac_optarg" ;;
+ target_alias=$ac_optarg ;;
-v | -verbose | --verbose | --verbos | --verbo | --verb)
verbose=yes ;;
- -version | --version | --versio | --versi | --vers)
- echo "configure generated by autoconf version 2.13"
- exit 0 ;;
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
-with-* | --with-*)
- ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
- if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
- { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
- fi
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
ac_package=`echo $ac_package| sed 's/-/_/g'`
- case "$ac_option" in
- *=*) ;;
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
*) ac_optarg=yes ;;
esac
- eval "with_${ac_package}='$ac_optarg'" ;;
+ eval "with_$ac_package='$ac_optarg'" ;;
-without-* | --without-*)
- ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
- if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
- { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
- fi
- ac_package=`echo $ac_package| sed 's/-/_/g'`
- eval "with_${ac_package}=no" ;;
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/-/_/g'`
+ eval "with_$ac_package=no" ;;
--x)
# Obsolete; use --with-x.
@@ -369,99 +577,110 @@ EOF
ac_prev=x_includes ;;
-x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
| --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
- x_includes="$ac_optarg" ;;
+ x_includes=$ac_optarg ;;
-x-libraries | --x-libraries | --x-librarie | --x-librari \
| --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
ac_prev=x_libraries ;;
-x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
| --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
- x_libraries="$ac_optarg" ;;
+ x_libraries=$ac_optarg ;;
- -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
;;
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+ eval "$ac_envvar='$ac_optarg'"
+ export $ac_envvar ;;
+
*)
- if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
- echo "configure: warning: $ac_option: invalid host type" 1>&2
- fi
- if test "x$nonopt" != xNONE; then
- { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
- fi
- nonopt="$ac_option"
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
;;
esac
done
if test -n "$ac_prev"; then
- { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
-fi
-
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
-
-# File descriptor usage:
-# 0 standard input
-# 1 file creation
-# 2 errors and warnings
-# 3 some systems may open it to /dev/tty
-# 4 used on the Kubota Titan
-# 6 checking for... messages and results
-# 5 compiler messages saved in config.log
-if test "$silent" = yes; then
- exec 6>/dev/null
-else
- exec 6>&1
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
fi
-exec 5>./config.log
-echo "\
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-" 1>&5
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
-# Strip out --no-create and --no-recursion so they do not pile up.
-# Also quote any args containing shell metacharacters.
-ac_configure_args=
-for ac_arg
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+ localstatedir libdir includedir oldincludedir infodir mandir
do
- case "$ac_arg" in
- -no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c) ;;
- -no-recursion | --no-recursion | --no-recursio | --no-recursi \
- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
- *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
- ac_configure_args="$ac_configure_args '$ac_arg'" ;;
- *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
esac
done
-# NLS nuisances.
-# Only set these to C if already set. These must not be set unconditionally
-# because not all systems understand e.g. LANG=C (notably SCO).
-# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
-# Non-C LC_CTYPE values break the ctype check.
-if test "${LANG+set}" = set; then LANG=C; export LANG; fi
-if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
-if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
-if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
-# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -rf conftest* confdefs.h
-# AIX cpp loses on an empty file, so make sure it contains at least a newline.
-echo > confdefs.h
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
-# A filename unique to this package, relative to the directory that
-# configure is in, which we can look for to find out if srcdir is correct.
-ac_unique_file=man2tcl.c
# Find the source files, if location was not specified.
if test -z "$srcdir"; then
ac_srcdir_defaulted=yes
# Try the directory containing this script, then its parent.
- ac_prog=$0
- ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
- test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
srcdir=$ac_confdir
if test ! -r $srcdir/$ac_unique_file; then
srcdir=..
@@ -471,13 +690,427 @@ else
fi
if test ! -r $srcdir/$ac_unique_file; then
if test "$ac_srcdir_defaulted" = yes; then
- { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+ { (exit 1); exit 1; }; }
else
- { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
fi
fi
-srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+ { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+ { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+ cat <<_ACEOF
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --infodir=DIR info documentation [PREFIX/info]
+ --mandir=DIR man documentation [PREFIX/man]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-tcl=DIR use Tcl $DEF_VER binaries from DIR
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ ac_popdir=`pwd`
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d $ac_dir || continue
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+ cd $ac_dir
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f $ac_srcdir/configure.gnu; then
+ echo
+ $SHELL $ac_srcdir/configure.gnu --help=recursive
+ elif test -f $ac_srcdir/configure; then
+ echo
+ $SHELL $ac_srcdir/configure --help=recursive
+ elif test -f $ac_srcdir/configure.ac ||
+ test -f $ac_srcdir/configure.in; then
+ echo
+ $ac_configure --help
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi
+ cd $ac_popdir
+ done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+ cat <<\_ACEOF
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo = `(hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+ # Get rid of the leading space.
+ ac_sep=" "
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+{
+ (set) 2>&1 |
+ case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ sed -n \
+ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+ ;;
+ *)
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+}
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ sed "/^$/d" confdefs.h | sort
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core &&
+ rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+ ' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
# Prefer explicitly selected file to automatically selected ones.
if test -z "$CONFIG_SITE"; then
if test "x$prefix" != xNONE; then
@@ -488,40 +1121,106 @@ if test -z "$CONFIG_SITE"; then
fi
for ac_site_file in $CONFIG_SITE; do
if test -r "$ac_site_file"; then
- echo "loading site script $ac_site_file"
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file"
fi
done
if test -r "$cache_file"; then
- echo "loading cache $cache_file"
- . $cache_file
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . $cache_file;;
+ *) . ./$cache_file;;
+ esac
+ fi
else
- echo "creating cache $cache_file"
- > $cache_file
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
fi
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-ac_exeext=
-ac_objext=o
-if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
- # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
- if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
- ac_n= ac_c='
-' ac_t=' '
- else
- ac_n=-n ac_c= ac_t=
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+ sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+ eval ac_new_val="\$ac_env_${ac_var}_value"
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
fi
-else
- ac_n= ac_c='\c' ac_t=
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# Recover information that Tcl computed with its configure script.
@@ -530,7 +1229,8 @@ fi
# not, assume that its top-level directory is a sibling of ours.
#--------------------------------------------------------------------
-DEF_VER=8.4
+DEF_VER=8.5
+
# Check whether --with-tcl or --without-tcl was given.
if test "${with_tcl+set}" = set; then
@@ -538,13 +1238,16 @@ if test "${with_tcl+set}" = set; then
TCL_BIN_DIR=$withval
else
TCL_BIN_DIR=`cd ../../tcl$DEF_VER$TCL_PATCH_LEVEL/unix; pwd`
-fi
-
+fi;
if test ! -d $TCL_BIN_DIR; then
- { echo "configure: error: Tcl directory $TCL_BIN_DIR doesn't exist" 1>&2; exit 1; }
+ { { echo "$as_me:$LINENO: error: Tcl directory $TCL_BIN_DIR doesn't exist" >&5
+echo "$as_me: error: Tcl directory $TCL_BIN_DIR doesn't exist" >&2;}
+ { (exit 1); exit 1; }; }
fi
if test ! -f $TCL_BIN_DIR/tclConfig.sh; then
- { echo "configure: error: There's no tclConfig.sh in $TCL_BIN_DIR; perhaps you didn't specify the Tcl *build* directory (not the toplevel Tcl directory) or you forgot to configure Tcl?" 1>&2; exit 1; }
+ { { echo "$as_me:$LINENO: error: There's no tclConfig.sh in $TCL_BIN_DIR; perhaps you didn't specify the Tcl *build* directory (not the toplevel Tcl directory) or you forgot to configure Tcl?" >&5
+echo "$as_me: error: There's no tclConfig.sh in $TCL_BIN_DIR; perhaps you didn't specify the Tcl *build* directory (not the toplevel Tcl directory) or you forgot to configure Tcl?" >&2;}
+ { (exit 1); exit 1; }; }
fi
. $TCL_BIN_DIR/tclConfig.sh
@@ -558,260 +1261,910 @@ CC=$TCL_CC
-trap '' 1 2 15
-cat > confcache <<\EOF
+ ac_config_files="$ac_config_files Makefile tcl.hpj"
+cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
-# scripts and configure runs. It is not useful on other systems.
-# If it contains results you don't want to keep, you may remove or edit it.
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
#
-# By default, configure uses ./config.cache as the cache file,
-# creating it if it does not exist already. You can give configure
-# the --cache-file=FILE option to use a different cache file; that is
-# what configure does when it calls configure scripts in
-# subdirectories, so they share the cache.
-# Giving --cache-file=/dev/null disables caching, for debugging configure.
-# config.status only pays attention to the cache file if you give it the
-# --recheck option to rerun configure.
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
#
-EOF
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
# The following way of writing the cache mishandles newlines in values,
# but we know of no workaround that is simple, portable, and efficient.
# So, don't put newlines in cache variables' values.
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
-(set) 2>&1 |
- case `(ac_space=' '; set | grep ac_space) 2>&1` in
- *ac_space=\ *)
- # `set' does not quote correctly, so add quotes (double-quote substitution
- # turns \\\\ into \\, and sed turns \\ into \).
- sed -n \
- -e "s/'/'\\\\''/g" \
- -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
- ;;
- *)
- # `set' quotes correctly as required by POSIX, so do not add quotes.
- sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
- ;;
- esac >> confcache
-if cmp -s $cache_file confcache; then
- :
-else
+{
+ (set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+} |
+ sed '
+ t clear
+ : clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
if test -w $cache_file; then
- echo "updating cache $cache_file"
- cat confcache > $cache_file
+ test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+ cat confcache >$cache_file
else
echo "not updating unwritable cache $cache_file"
fi
fi
rm -f confcache
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
-
test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-# Any assignment to VPATH causes Sun make to only execute
-# the first set of double-colon rules, so remove it if not needed.
-# If there is a colon in the path, we need to keep it.
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
if test "x$srcdir" = x.; then
- ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[ ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[ ]*$//;
+}'
fi
-trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
-
# Transform confdefs.h into DEFS.
# Protect against shell expansion while executing Makefile rules.
# Protect against Makefile macro expansion.
-cat > conftest.defs <<\EOF
-s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
-s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
-s%\[%\\&%g
-s%\]%\\&%g
-s%\$%$$%g
-EOF
-DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
-rm -f conftest.defs
-
-
-# Without the "./", some shells look in PATH for config.status.
-: ${CONFIG_STATUS=./config.status}
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then we branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+cat >confdef2opt.sed <<\_ACEOF
+t clear
+: clear
+s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g
+t quote
+s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g
+t quote
+d
+: quote
+s,[ `~#$^&*(){}\\|;'"<>?],\\&,g
+s,\[,\\&,g
+s,\],\\&,g
+s,\$,$$,g
+p
+_ACEOF
+# We use echo to avoid assuming a particular line-breaking character.
+# The extra dot is to prevent the shell from consuming trailing
+# line-breaks from the sub-command output. A line-break within
+# single-quotes doesn't work because, if this script is created in a
+# platform that uses two characters for line-breaks (e.g., DOS), tr
+# would break.
+ac_LF_and_DOT=`echo; echo .`
+DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
+rm -f confdef2opt.sed
+
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_i=`echo "$ac_i" |
+ sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+ # 2. Add them.
+ ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
-echo creating $CONFIG_STATUS
-rm -f $CONFIG_STATUS
-cat > $CONFIG_STATUS <<EOF
-#! /bin/sh
-# Generated automatically by configure.
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
# Run this file to recreate the current configuration.
-# This directory was configured as follows,
-# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-#
-# $0 $ac_configure_args
-#
# Compiler output produced by configure, useful for debugging
-# configure, is in ./config.log if it exists.
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
-ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
-for ac_option
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
do
- case "\$ac_option" in
- -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
- echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
- exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
- -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
- echo "$CONFIG_STATUS generated by autoconf version 2.13"
- exit 0 ;;
- -help | --help | --hel | --he | --h)
- echo "\$ac_cs_usage"; exit 0 ;;
- *) echo "\$ac_cs_usage"; exit 1 ;;
- esac
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
done
-ac_given_srcdir=$srcdir
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
-trap 'rm -fr `echo "Makefile tcl.hpj" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
-EOF
-cat >> $CONFIG_STATUS <<EOF
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
-# Protect against being on the right side of a sed subst in config.status.
-sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
- s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
-$ac_vpsub
-$extrasub
-s%@SHELL@%$SHELL%g
-s%@CFLAGS@%$CFLAGS%g
-s%@CPPFLAGS@%$CPPFLAGS%g
-s%@CXXFLAGS@%$CXXFLAGS%g
-s%@FFLAGS@%$FFLAGS%g
-s%@DEFS@%$DEFS%g
-s%@LDFLAGS@%$LDFLAGS%g
-s%@LIBS@%$LIBS%g
-s%@exec_prefix@%$exec_prefix%g
-s%@prefix@%$prefix%g
-s%@program_transform_name@%$program_transform_name%g
-s%@bindir@%$bindir%g
-s%@sbindir@%$sbindir%g
-s%@libexecdir@%$libexecdir%g
-s%@datadir@%$datadir%g
-s%@sysconfdir@%$sysconfdir%g
-s%@sharedstatedir@%$sharedstatedir%g
-s%@localstatedir@%$localstatedir%g
-s%@libdir@%$libdir%g
-s%@includedir@%$includedir%g
-s%@oldincludedir@%$oldincludedir%g
-s%@infodir@%$infodir%g
-s%@mandir@%$mandir%g
-s%@TCL_WIN_VERSION@%$TCL_WIN_VERSION%g
-s%@CC@%$CC%g
-s%@TCL_VERSION@%$TCL_VERSION%g
-s%@TCL_PATCH_LEVEL@%$TCL_PATCH_LEVEL%g
-s%@TCL_SRC_DIR@%$TCL_SRC_DIR%g
-s%@TCL_BIN_DIR@%$TCL_BIN_DIR%g
-CEOF
-EOF
-
-cat >> $CONFIG_STATUS <<\EOF
-
-# Split the substitutions into bite-sized pieces for seds with
-# small command number limits, like on Digital OSF/1 and HP-UX.
-ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
-ac_file=1 # Number of current file.
-ac_beg=1 # First line for current file.
-ac_end=$ac_max_sed_cmds # Line after last line for current file.
-ac_more_lines=:
-ac_sed_cmds=""
-while $ac_more_lines; do
- if test $ac_beg -gt 1; then
- sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
- else
- sed "${ac_end}q" conftest.subs > conftest.s$ac_file
- fi
- if test ! -s conftest.s$ac_file; then
- ac_more_lines=false
- rm -f conftest.s$ac_file
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
else
- if test -z "$ac_sed_cmds"; then
- ac_sed_cmds="sed -f conftest.s$ac_file"
- else
- ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
- fi
- ac_file=`expr $ac_file + 1`
- ac_beg=$ac_end
- ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ PATH_SEPARATOR=:
fi
-done
-if test -z "$ac_sed_cmds"; then
- ac_sed_cmds=cat
+ rm -f conf$$.sh
fi
-EOF
-cat >> $CONFIG_STATUS <<EOF
-CONFIG_FILES=\${CONFIG_FILES-"Makefile tcl.hpj"}
-EOF
-cat >> $CONFIG_STATUS <<\EOF
-for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
- # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
- case "$ac_file" in
- *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
- ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
- *) ac_file_in="${ac_file}.in" ;;
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
esac
- # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
- # Remove last slash and all that follows it. Not all systems have dirname.
- ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
- if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
- # The file is in a subdirectory.
- test ! -d "$ac_dir" && mkdir "$ac_dir"
- ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
- # A "../" for each directory in $ac_dir_suffix.
- ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
else
- ac_dir_suffix= ac_dots=
+ as_ln_s='ln -s'
fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
- case "$ac_given_srcdir" in
- .) srcdir=.
- if test -z "$ac_dots"; then top_srcdir=.
- else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
- /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
- *) # Relative path.
- srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
- top_srcdir="$ac_dots$ac_given_srcdir" ;;
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling. Logging --version etc. is OK.
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+ echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+ echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+ echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+ echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.59,
+ with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "x$1" : 'x\([^=]*\)='`
+ ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ -*)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ *) # This is not an option, so the user has probably given explicit
+ # arguments.
+ ac_option=$1
+ ac_need_defaults=false;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --vers* | -V )
+ echo "$ac_cs_version"; exit 0 ;;
+ --he | --h)
+ # Conflict between --help and --header
+ { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit 0 ;;
+ --debug | --d* | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1" ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+ case "$ac_config_target" in
+ # Handling of arguments.
+ "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "tcl.hpj" ) CONFIG_FILES="$CONFIG_FILES tcl.hpj" ;;
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+ trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./confstat$$-$RANDOM
+ (umask 077 && mkdir $tmp)
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+ # Protect against being on the right side of a sed subst in config.status.
+ sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+ s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@TCL_WIN_VERSION@,$TCL_WIN_VERSION,;t t
+s,@CC@,$CC,;t t
+s,@TCL_VERSION@,$TCL_VERSION,;t t
+s,@TCL_PATCH_LEVEL@,$TCL_PATCH_LEVEL,;t t
+s,@TCL_SRC_DIR@,$TCL_SRC_DIR,;t t
+s,@TCL_BIN_DIR@,$TCL_BIN_DIR,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
- echo creating "$ac_file"
- rm -f "$ac_file"
- configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
- case "$ac_file" in
- *Makefile*) ac_comsub="1i\\
-# $configure_input" ;;
- *) ac_comsub= ;;
+_ACEOF
+
+ cat >>$CONFIG_STATUS <<\_ACEOF
+ # Split the substitutions into bite-sized pieces for seds with
+ # small command number limits, like on Digital OSF/1 and HP-UX.
+ ac_max_sed_lines=48
+ ac_sed_frag=1 # Number of current file.
+ ac_beg=1 # First line for current file.
+ ac_end=$ac_max_sed_lines # Line after last line for current file.
+ ac_more_lines=:
+ ac_sed_cmds=
+ while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ else
+ sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ fi
+ if test ! -s $tmp/subs.frag; then
+ ac_more_lines=false
+ else
+ # The purpose of the label and of the branching condition is to
+ # speed up the sed processing (if there are no `@' at all, there
+ # is no need to browse any of the substitutions).
+ # These are the two extra sed commands mentioned above.
+ (echo ':t
+ /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+ fi
+ ac_sed_frag=`expr $ac_sed_frag + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_lines`
+ fi
+ done
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+ fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
esac
- ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
- sed -e "$ac_comsub
-s%@configure_input@%$configure_input%g
-s%@srcdir@%$srcdir%g
-s%@top_srcdir@%$top_srcdir%g
-" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
-fi; done
-rm -f conftest.s*
+ # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
-EOF
-cat >> $CONFIG_STATUS <<EOF
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+
+
+ if test x"$ac_file" != x-; then
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ rm -f "$ac_file"
+ fi
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ if test x"$ac_file" = x-; then
+ configure_input=
+ else
+ configure_input="$ac_file. "
+ fi
+ configure_input=$configure_input"Generated from `echo $ac_file_in |
+ sed 's,.*/,,'` by configure."
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ echo "$f";;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo "$f"
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo "$srcdir/$f"
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+ rm -f $tmp/stdin
+ if test x"$ac_file" != x-; then
+ mv $tmp/out $ac_file
+ else
+ cat $tmp/out
+ rm -f $tmp/out
+ fi
-EOF
-cat >> $CONFIG_STATUS <<\EOF
+done
+_ACEOF
-exit 0
-EOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
chmod +x $CONFIG_STATUS
-rm -fr confdefs* $ac_clean_files
-test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
diff --git a/tools/configure.in b/tools/configure.in
index fe0c59b..542c1d3 100644
--- a/tools/configure.in
+++ b/tools/configure.in
@@ -2,6 +2,7 @@ dnl This file is an input file used by the GNU "autoconf" program to
dnl generate the file "configure", which is run to configure the
dnl Makefile in this directory.
AC_INIT(man2tcl.c)
+AC_PREREQ(2.57)
# Recover information that Tcl computed with its configure script.
@@ -10,7 +11,7 @@ AC_INIT(man2tcl.c)
# not, assume that its top-level directory is a sibling of ours.
#--------------------------------------------------------------------
-DEF_VER=8.4
+DEF_VER=8.5
AC_ARG_WITH(tcl, [ --with-tcl=DIR use Tcl $DEF_VER binaries from DIR], TCL_BIN_DIR=$withval, TCL_BIN_DIR=`cd ../../tcl$DEF_VER$TCL_PATCH_LEVEL/unix; pwd`)
if test ! -d $TCL_BIN_DIR; then
diff --git a/tools/cvtEOL.tcl b/tools/cvtEOL.tcl
deleted file mode 100644
index 8fa5441..0000000
--- a/tools/cvtEOL.tcl
+++ /dev/null
@@ -1,32 +0,0 @@
-# cvtEOL.tcl --
-#
-# This file contains a script to parse a Tcl/Tk distribution and
-# convert the EOL from \n to \r on all text files.
-#
-# Copyright (c) 1996-1997 by Sun Microsystems, Inc.
-
-#
-# Convert files in the distribution to Mac style
-#
-
-set distDir [lindex $argv 0]
-
-set dirs {unix mac generic win library compat tests unix/dltest \
- library/demos library/demos/images bitmaps xlib xlib/X11 .}
-set files {*.c *.y *.h *.r *.tcl *.test *.rc *.bc *.vc *.bmp *.html \
- *.in *.notes *.terms all defs \
- README ToDo changes tclIndex configure install-sh mkLinks \
- square widget rmt ixset hello browse rolodex tcolor timer}
-
-foreach x $dirs {
- if [catch {cd $distDir/$x}] continue
- puts "Working on $x..."
- foreach y [eval glob $files] {
- exec chmod 666 $y
- exec cp $y $y.tmp
- exec tr \012 \015 < $y.tmp > $y
- exec chmod 444 $y
- exec rm $y.tmp
- }
-}
-
diff --git a/tools/findBadExternals.tcl b/tools/findBadExternals.tcl
new file mode 100755
index 0000000..7592f17
--- /dev/null
+++ b/tools/findBadExternals.tcl
@@ -0,0 +1,53 @@
+# findBadExternals.tcl --
+#
+# This script scans the Tcl load library for exported symbols
+# that do not begin with 'Tcl' or 'tcl'. It reports them on the
+# standard output. It is used to make sure that the library does
+# not inadvertently export externals that may be in conflict with
+# other code.
+#
+# Usage:
+#
+# tclsh findBadExternals.tcl /path/to/tclXX.so-or-.dll
+#
+# Copyright (c) 2005 George Peter Staplin and Kevin Kenny
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#----------------------------------------------------------------------
+
+proc main {argc argv} {
+
+ if {$argc != 1} {
+ puts stderr "syntax is: [info script] libtcl"
+ return 1
+ }
+
+
+ switch -exact -- $::tcl_platform(platform) {
+ unix -
+ macosx {
+ set status [catch {
+ exec nm --extern-only --defined-only [lindex $argv 0]
+ } result]
+ }
+ windows {
+ set status [catch {
+ exec dumpbin /exports [lindex $argv 0]
+ } result]
+ }
+ }
+ if {$status != 0 && $::errorCode ne "NONE"} {
+ puts $result
+ return 1
+ }
+
+ foreach line [split $result \n] {
+ if {! [string match {* [Tt]cl*} $line]} {
+ puts $line
+ }
+ }
+
+ return 0
+}
+exit [main $::argc $::argv]
diff --git a/tools/fix_tommath_h.tcl b/tools/fix_tommath_h.tcl
new file mode 100755
index 0000000..f92b7ac
--- /dev/null
+++ b/tools/fix_tommath_h.tcl
@@ -0,0 +1,98 @@
+# fixtommath.tcl --
+#
+# Changes to 'tommath.h' to make it conform with Tcl's linking
+# conventions.
+#
+# Copyright (c) 2005 by Kevin B. Kenny. All rights reserved.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#----------------------------------------------------------------------
+
+set f [open [lindex $argv 0] r]
+set data [read $f]
+close $f
+
+set eat_endif 0
+set eat_semi 0
+set def_count 0
+foreach line [split $data \n] {
+ if { !$eat_semi && !$eat_endif } {
+ switch -regexp -- $line {
+ {#define BN_H_} {
+ puts $line
+ puts {}
+ puts "\#include <tclTomMathDecls.h>"
+ puts "\#ifndef MODULE_SCOPE"
+ puts "\#define MODULE_SCOPE extern"
+ puts "\#endif"
+ }
+ {typedef\s+unsigned long\s+mp_digit;} {
+ # change the second 'typedef unsigned long mp
+ incr def_count
+ puts "\#ifndef MP_DIGIT_DECLARED"
+ if {$def_count == 2} {
+ puts [string map {long int} $line]
+ } else {
+ puts $line
+ }
+ puts "\#define MP_DIGIT_DECLARED"
+ puts "\#endif"
+ }
+ {typedef.*mp_digit;} {
+ puts "\#ifndef MP_DIGIT_DECLARED"
+ puts $line
+ puts "\#define MP_DIGIT_DECLARED"
+ puts "\#endif"
+ }
+ {typedef struct} {
+ puts "\#ifndef MP_INT_DECLARED"
+ puts "\#define MP_INT_DECLARED"
+ puts "typedef struct mp_int mp_int;"
+ puts "\#endif"
+ puts "struct mp_int \{"
+ }
+ \}\ mp_int\; {
+ puts "\};"
+ }
+ {^(char|int|void)} {
+ puts "/*"
+ puts $line
+ set eat_semi 1
+ set after_semi "*/"
+ }
+ {^extern (int|const)} {
+ puts "\#if defined(BUILD_tcl) || !defined(_WIN32)"
+ puts [regsub {^extern} $line "MODULE_SCOPE"]
+ set eat_semi 1
+ set after_semi "\#endif"
+ }
+ {define heap macros} {
+ puts $line
+ puts "\#if 0 /* these are macros in tclTomMathDecls.h */"
+ set eat_endif 1
+ }
+ {__x86_64__} {
+ puts "[string map {__x86_64__ NEVER} $line]\
+ /* 128-bit ints fail in too many places */"
+ }
+ default {
+ puts $line
+ }
+ }
+ } else {
+ puts $line
+ }
+ if {$eat_semi} {
+ if {[regexp {; *$} $line]} {
+ puts $after_semi
+ set eat_semi 0
+ }
+ }
+ if {$eat_endif} {
+ if {[regexp {^\#endif} $line]} {
+ puts "\#endif"
+ set eat_endif 0
+ }
+ }
+}
diff --git a/tools/genStubs.tcl b/tools/genStubs.tcl
index 8e8cbfd..464ba50 100644
--- a/tools/genStubs.tcl
+++ b/tools/genStubs.tcl
@@ -1,20 +1,22 @@
# genStubs.tcl --
#
# This script generates a set of stub files for a given
-# interface.
-#
+# interface.
+#
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
+# Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
+#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-package require Tcl 8
+package require Tcl 8.4
namespace eval genStubs {
# libraryName --
#
# The name of the entire library. This value is used to compute
- # the USE_*_STUB_PROCS macro and the name of the init file.
+ # the USE_*_STUBS macro and the name of the init file.
variable libraryName "UNKNOWN"
@@ -120,7 +122,7 @@ proc genStubs::hooks {names} {
# Arguments:
# index The index number of the interface.
# platform The platform the interface belongs to. Should be one
-# of generic, win, unix, or mac, or macosx or aqua or x11.
+# of generic, win, unix, or macosx or aqua or x11.
# decl The C function declaration, or {} for an undefined
# entry.
#
@@ -131,10 +133,15 @@ proc genStubs::declare {args} {
variable stubs
variable curName
- if {[llength $args] != 3} {
+ if {[llength $args] == 2} {
+ lassign $args index decl
+ set platformList generic
+ } elseif {[llength $args] == 3} {
+ lassign $args index platformList decl
+ } else {
puts stderr "wrong # args: declare $args"
+ return
}
- lassign $args index platformList decl
# Check for duplicate declarations, then add the declaration and
# bump the lastNum counter if necessary.
@@ -144,6 +151,8 @@ proc genStubs::declare {args} {
puts stderr "Duplicate entry: declare $args"
}
}
+ regsub -all const $decl CONST decl
+ regsub -all _XCONST $decl _Xconst decl
regsub -all "\[ \t\n\]+" [string trim $decl] " " decl
set decl [parseDecl $decl]
@@ -159,6 +168,25 @@ proc genStubs::declare {args} {
return
}
+# genStubs::export --
+#
+# This function is used in the declarations file to declare a symbol
+# that is exported from the library but is not in the stubs table.
+#
+# Arguments:
+# decl The C function declaration, or {} for an undefined
+# entry.
+#
+# Results:
+# None.
+
+proc genStubs::export {args} {
+ if {[llength $args] != 1} {
+ puts stderr "wrong # args: export $args"
+ }
+ return
+}
+
# genStubs::rewriteFile --
#
# This function replaces the machine generated portion of the
@@ -182,7 +210,7 @@ proc genStubs::rewriteFile {file text} {
while {![eof $in]} {
set line [gets $in]
- if {[regexp {!BEGIN!} $line]} {
+ if {[string match "*!BEGIN!*" $line]} {
break
}
puts $out $line
@@ -191,7 +219,7 @@ proc genStubs::rewriteFile {file text} {
puts $out $text
while {![eof $in]} {
set line [gets $in]
- if {[regexp {!END!} $line]} {
+ if {[string match "*!END!*" $line]} {
break
}
}
@@ -213,28 +241,51 @@ proc genStubs::rewriteFile {file text} {
# Results:
# Returns the original text inside an appropriate #ifdef.
-proc genStubs::addPlatformGuard {plat text} {
+proc genStubs::addPlatformGuard {plat iftxt {eltxt {}}} {
+ set text ""
switch $plat {
win {
- return "#ifdef __WIN32__\n${text}#endif /* __WIN32__ */\n"
+ append text "#ifdef __WIN32__ /* WIN */\n${iftxt}"
+ if {$eltxt ne ""} {
+ append text "#else /* WIN */\n${eltxt}"
+ }
+ append text "#endif /* WIN */\n"
}
unix {
- return "#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */\n${text}#endif /* UNIX */\n"
- }
- mac {
- return "#ifdef MAC_TCL\n${text}#endif /* MAC_TCL */\n"
+ append text "#if !defined(__WIN32__) && !defined(MAC_OSX_TCL)\
+ /* UNIX */\n${iftxt}"
+ if {$eltxt ne ""} {
+ append text "#else /* UNIX */\n${eltxt}"
+ }
+ append text "#endif /* UNIX */\n"
}
macosx {
- return "#ifdef MAC_OSX_TCL\n${text}#endif /* MAC_OSX_TCL */\n"
+ append text "#ifdef MAC_OSX_TCL /* MACOSX */\n${iftxt}"
+ if {$eltxt ne ""} {
+ append text "#else /* MACOSX */\n${eltxt}"
+ }
+ append text "#endif /* MACOSX */\n"
}
aqua {
- return "#ifdef MAC_OSX_TK\n${text}#endif /* MAC_OSX_TK */\n"
+ append text "#ifdef MAC_OSX_TK /* AQUA */\n${iftxt}"
+ if {$eltxt ne ""} {
+ append text "#else /* AQUA */\n${eltxt}"
+ }
+ append text "#endif /* AQUA */\n"
}
x11 {
- return "#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) /* X11 */\n${text}#endif /* X11 */\n"
+ append text "#if !(defined(__WIN32__) || defined(MAC_OSX_TK))\
+ /* X11 */\n${iftxt}"
+ if {$eltxt ne ""} {
+ append text "#else /* X11 */\n${eltxt}"
+ }
+ append text "#endif /* X11 */\n"
+ }
+ default {
+ append text "${iftxt}${eltxt}"
}
}
- return "$text"
+ return $text
}
# genStubs::emitSlots --
@@ -251,10 +302,9 @@ proc genStubs::addPlatformGuard {plat text} {
# None.
proc genStubs::emitSlots {name textVar} {
- variable stubs
upvar $textVar text
- forAllStubs $name makeSlot 1 text {" void *reserved$i;\n"}
+ forAllStubs $name makeSlot 1 text {" VOID *reserved$i;\n"}
return
}
@@ -273,8 +323,8 @@ proc genStubs::emitSlots {name textVar} {
proc genStubs::parseDecl {decl} {
if {![regexp {^(.*)\((.*)\)$} $decl all prefix args]} {
- puts stderr "Malformed declaration: $decl"
- return
+ set prefix $decl
+ set args {}
}
set prefix [string trim $prefix]
if {![regexp {^(.+[ ][*]*)([^ *]+)$} $prefix all rtype fname]} {
@@ -282,19 +332,23 @@ proc genStubs::parseDecl {decl} {
return
}
set rtype [string trim $rtype]
+ if {$args == ""} {
+ return [list $rtype $fname {}]
+ }
foreach arg [split $args ,] {
lappend argList [string trim $arg]
}
if {![string compare [lindex $argList end] "..."]} {
- if {[llength $argList] != 2} {
- puts stderr "Only one argument is allowed in varargs form: $decl"
- }
- set arg [parseArg [lindex $argList 0]]
- if {$arg == "" || ([llength $arg] != 2)} {
- puts stderr "Bad argument: '[lindex $argList 0]' in '$decl'"
- return
+ set args TCL_VARARGS
+ foreach arg [lrange $argList 0 end-1] {
+ set argInfo [parseArg $arg]
+ if {[llength $argInfo] == 2 || [llength $argInfo] == 3} {
+ lappend args $argInfo
+ } else {
+ puts stderr "Bad argument: '$arg' in '$decl'"
+ return
+ }
}
- set args [list TCL_VARARGS $arg]
} else {
set args {}
foreach arg $argList {
@@ -355,6 +409,9 @@ proc genStubs::makeDecl {name decl index} {
lassign $decl rtype fname args
append text "/* $index */\n"
+ if {$rtype != "void"} {
+ regsub -all void $rtype VOID rtype
+ }
set line "EXTERN $rtype"
set count [expr {2 - ([string length $line] / 8)}]
append line [string range "\t\t\t" 0 $count]
@@ -363,27 +420,54 @@ proc genStubs::makeDecl {name decl index} {
append line " "
set pad 0
}
- append line "$fname _ANSI_ARGS_("
+ if {$args == ""} {
+ append line $fname
+ append text $line
+ append text ";\n"
+ return $text
+ }
+ append line $fname
+ regsub -all void $args VOID args
set arg1 [lindex $args 0]
switch -exact $arg1 {
- void {
+ VOID {
append line "(void)"
}
TCL_VARARGS {
- set arg [lindex $args 1]
- append line "TCL_VARARGS([lindex $arg 0],[lindex $arg 1])"
+ set sep "("
+ foreach arg [lrange $args 1 end] {
+ append line $sep
+ set next {}
+ append next [lindex $arg 0]
+ if {[string index $next end] ne "*"} {
+ append next " "
+ }
+ append next [lindex $arg 1] [lindex $arg 2]
+ if {[string length $line] + [string length $next] \
+ + $pad > 76} {
+ append text [string trimright $line] \n
+ set line "\t\t\t\t"
+ set pad 28
+ }
+ append line $next
+ set sep ", "
+ }
+ append line ", ...)"
}
default {
set sep "("
foreach arg $args {
append line $sep
set next {}
- append next [lindex $arg 0] " " [lindex $arg 1] \
- [lindex $arg 2]
+ append next [lindex $arg 0]
+ if {[string index $next end] ne "*"} {
+ append next " "
+ }
+ append next [lindex $arg 1] [lindex $arg 2]
if {[string length $line] + [string length $next] \
+ $pad > 76} {
- append text $line \n
+ append text [string trimright $line] \n
set line "\t\t\t\t"
set pad 28
}
@@ -393,10 +477,9 @@ proc genStubs::makeDecl {name decl index} {
append line ")"
}
}
- append text $line
-
- append text ");\n"
- return $text
+ append text $line ";"
+ format "#ifndef %s_TCL_DECLARED\n#define %s_TCL_DECLARED\n%s\n#endif\n" \
+ $fname $fname $text
}
# genStubs::makeMacro --
@@ -417,94 +500,15 @@ proc genStubs::makeMacro {name decl index} {
set lfname [string tolower [string index $fname 0]]
append lfname [string range $fname 1 end]
- set text "#ifndef $fname\n#define $fname"
- set arg1 [lindex $args 0]
- set argList ""
- switch -exact $arg1 {
- void {
- set argList "()"
- }
- TCL_VARARGS {
- }
- default {
- set sep "("
- foreach arg $args {
- append argList $sep [lindex $arg 1]
- set sep ", "
- }
- append argList ")"
- }
+ set text "#ifndef $fname\n#define $fname \\\n\t("
+ if {$args == ""} {
+ append text "*"
}
- append text " \\\n\t(${name}StubsPtr->$lfname)"
+ append text "${name}StubsPtr->$lfname)"
append text " /* $index */\n#endif\n"
return $text
}
-# genStubs::makeStub --
-#
-# Emits a stub function definition.
-#
-# Arguments:
-# name The interface name.
-# decl The function declaration.
-# index The slot index for this function.
-#
-# Results:
-# Returns the formatted stub function definition.
-
-proc genStubs::makeStub {name decl index} {
- lassign $decl rtype fname args
-
- set lfname [string tolower [string index $fname 0]]
- append lfname [string range $fname 1 end]
-
- append text "/* Slot $index */\n" $rtype "\n" $fname
-
- set arg1 [lindex $args 0]
-
- if {![string compare $arg1 "TCL_VARARGS"]} {
- lassign [lindex $args 1] type argName
- append text " TCL_VARARGS_DEF($type,$argName)\n\{\n"
- append text " " $type " var;\n va_list argList;\n"
- if {[string compare $rtype "void"]} {
- append text " " $rtype " resultValue;\n"
- }
- append text "\n var = (" $type ") TCL_VARARGS_START(" \
- $type "," $argName ",argList);\n\n "
- if {[string compare $rtype "void"]} {
- append text "resultValue = "
- }
- append text "(" $name "StubsPtr->" $lfname "VA)(var, argList);\n"
- append text " va_end(argList);\n"
- if {[string compare $rtype "void"]} {
- append text "return resultValue;\n"
- }
- append text "\}\n\n"
- return $text
- }
-
- if {![string compare $arg1 "void"]} {
- set argList "()"
- set argDecls ""
- } else {
- set argList ""
- set sep "("
- foreach arg $args {
- append argList $sep [lindex $arg 1]
- append argDecls " " [lindex $arg 0] " " \
- [lindex $arg 1] [lindex $arg 2] ";\n"
- set sep ", "
- }
- append argList ")"
- }
- append text $argList "\n" $argDecls "{\n "
- if {[string compare $rtype "void"]} {
- append text "return "
- }
- append text "(" $name "StubsPtr->" $lfname ")" $argList ";\n}\n\n"
- return $text
-}
-
# genStubs::makeSlot --
#
# Generate the stub table entry for a function.
@@ -524,29 +528,51 @@ proc genStubs::makeSlot {name decl index} {
append lfname [string range $fname 1 end]
set text " "
- append text $rtype " (*" $lfname ") _ANSI_ARGS_("
-
+ if {$rtype != "void"} {
+ regsub -all void $rtype VOID rtype
+ }
+ if {$args == ""} {
+ append text $rtype " *" $lfname "; /* $index */\n"
+ return $text
+ }
+ if {[string range $rtype end-7 end] == "CALLBACK"} {
+ append text [string trim [string range $rtype 0 end-8]] " (CALLBACK *" $lfname ") "
+ } else {
+ append text $rtype " (*" $lfname ") "
+ }
+ regsub -all void $args VOID args
set arg1 [lindex $args 0]
switch -exact $arg1 {
- void {
+ VOID {
append text "(void)"
}
TCL_VARARGS {
- set arg [lindex $args 1]
- append text "TCL_VARARGS([lindex $arg 0],[lindex $arg 1])"
+ set sep "("
+ foreach arg [lrange $args 1 end] {
+ append text $sep [lindex $arg 0]
+ if {[string index $text end] ne "*"} {
+ append text " "
+ }
+ append text [lindex $arg 1] [lindex $arg 2]
+ set sep ", "
+ }
+ append text ", ...)"
}
default {
set sep "("
foreach arg $args {
- append text $sep [lindex $arg 0] " " [lindex $arg 1] \
- [lindex $arg 2]
+ append text $sep [lindex $arg 0]
+ if {[string index $text end] ne "*"} {
+ append text " "
+ }
+ append text [lindex $arg 1] [lindex $arg 2]
set sep ", "
}
append text ")"
}
}
-
- append text "); /* $index */\n"
+
+ append text "; /* $index */\n"
return $text
}
@@ -563,7 +589,11 @@ proc genStubs::makeSlot {name decl index} {
# Returns the formatted declaration string.
proc genStubs::makeInit {name decl index} {
- append text " " [lindex $decl 1] ", /* " $index " */\n"
+ if {[lindex $decl 2] == ""} {
+ append text " &" [lindex $decl 1] ", /* " $index " */\n"
+ } else {
+ append text " " [lindex $decl 1] ", /* " $index " */\n"
+ }
return $text
}
@@ -588,7 +618,7 @@ proc genStubs::makeInit {name decl index} {
# Results:
# None.
-proc genStubs::forAllStubs {name slotProc onAll textVar \
+proc genStubs::forAllStubs {name slotProc onAll textVar
{skipString {"/* Slot $i is reserved */\n"}}} {
variable stubs
upvar $textVar text
@@ -607,109 +637,231 @@ proc genStubs::forAllStubs {name slotProc onAll textVar \
set emit 0
if {[info exists stubs($name,generic,$i)]} {
if {[llength $slots] > 1} {
- puts stderr "platform entry duplicates generic entry: $i"
+ puts stderr "conflicting generic and platform entries:\
+ $name $i"
}
append text [$slotProc $name $stubs($name,generic,$i) $i]
set emit 1
} elseif {[llength $slots] > 0} {
- foreach plat {unix win mac} {
- if {[info exists stubs($name,$plat,$i)]} {
- append text [addPlatformGuard $plat \
- [$slotProc $name $stubs($name,$plat,$i) $i]]
- set emit 1
+ array set slot {unix 0 x11 0 win 0 macosx 0 aqua 0}
+ foreach s $slots {
+ set slot([lindex [split $s ,] 1]) 1
+ }
+ # "aqua", "macosx" and "x11" are special cases:
+ # "macosx" implies "unix", "aqua" implies "macosx" and "x11"
+ # implies "unix", so we need to be careful not to emit
+ # duplicate stubs entries:
+ if {($slot(unix) && $slot(macosx)) || (
+ ($slot(unix) || $slot(macosx)) &&
+ ($slot(x11) || $slot(aqua)))} {
+ puts stderr "conflicting platform entries: $name $i"
+ }
+ ## unix ##
+ set temp {}
+ set plat unix
+ if {!$slot(aqua) && !$slot(x11)} {
+ if {$slot($plat)} {
+ append temp [$slotProc $name $stubs($name,$plat,$i) $i]
} elseif {$onAll} {
- append text [eval {addPlatformGuard $plat} $skipString]
- set emit 1
+ eval {append temp} $skipString
}
}
- #
- # "aqua" and "macosx" and "x11" are special cases,
- # since "macosx" always implies "unix" and "aqua",
- # "macosx", so we need to be careful not to
- # emit duplicate stubs entries for the two.
- #
- if {[info exists stubs($name,aqua,$i)]
- && ![info exists stubs($name,macosx,$i)]} {
- append text [addPlatformGuard aqua \
- [$slotProc $name $stubs($name,aqua,$i) $i]]
+ if {$temp ne ""} {
+ append text [addPlatformGuard $plat $temp]
+ set emit 1
+ }
+ ## x11 ##
+ set temp {}
+ set plat x11
+ if {!$slot(unix) && !$slot(macosx)} {
+ if {$slot($plat)} {
+ append temp [$slotProc $name $stubs($name,$plat,$i) $i]
+ } elseif {$onAll} {
+ eval {append temp} $skipString
+ }
+ }
+ if {$temp ne ""} {
+ append text [addPlatformGuard $plat $temp]
+ set emit 1
+ }
+ ## win ##
+ set temp {}
+ set plat win
+ if {$slot($plat)} {
+ append temp [$slotProc $name $stubs($name,$plat,$i) $i]
+ } elseif {$onAll} {
+ eval {append temp} $skipString
+ }
+ if {$temp ne ""} {
+ append text [addPlatformGuard $plat $temp]
set emit 1
}
- if {[info exists stubs($name,macosx,$i)]
- && ![info exists stubs($name,unix,$i)]} {
- append text [addPlatformGuard macosx \
- [$slotProc $name $stubs($name,macosx,$i) $i]]
+ ## macosx ##
+ set temp {}
+ set plat macosx
+ if {!$slot(aqua) && !$slot(x11)} {
+ if {$slot($plat)} {
+ append temp [$slotProc $name $stubs($name,$plat,$i) $i]
+ } elseif {$slot(unix)} {
+ append temp [$slotProc $name $stubs($name,unix,$i) $i]
+ } elseif {$onAll} {
+ eval {append temp} $skipString
+ }
+ }
+ if {$temp ne ""} {
+ append text [addPlatformGuard $plat $temp]
set emit 1
}
- if {[info exists stubs($name,x11,$i)]
- && ![info exists stubs($name,unix,$i)]} {
- append text [addPlatformGuard x11 \
- [$slotProc $name $stubs($name,x11,$i) $i]]
+ ## aqua ##
+ set temp {}
+ set plat aqua
+ if {!$slot(unix) && !$slot(macosx)} {
+ if {[string range $skipString 1 2] ne "/*"} {
+ # genStubs.tcl previously had a bug here causing it to
+ # erroneously generate both a unix entry and an aqua
+ # entry for a given stubs table slot. To preserve
+ # backwards compatibility, generate a dummy stubs entry
+ # before every aqua entry (note that this breaks the
+ # correspondence between emitted entry number and
+ # actual position of the entry in the stubs table, e.g.
+ # TkIntStubs entry 113 for aqua is in fact at position
+ # 114 in the table, entry 114 at position 116 etc).
+ eval {append temp} $skipString
+ set temp "[string range $temp 0 end-1] /*\
+ Dummy entry for stubs table backwards\
+ compatibility */\n"
+ }
+ if {$slot($plat)} {
+ append temp [$slotProc $name $stubs($name,$plat,$i) $i]
+ } elseif {$onAll} {
+ eval {append temp} $skipString
+ }
+ }
+ if {$temp ne ""} {
+ append text [addPlatformGuard $plat $temp]
set emit 1
}
}
- if {$emit == 0} {
+ if {!$emit} {
eval {append text} $skipString
}
}
-
} else {
# Emit separate stubs blocks per platform
- foreach plat {unix win mac} {
- if {[info exists stubs($name,$plat,lastNum)]} {
- set lastNum $stubs($name,$plat,lastNum)
- set temp {}
- for {set i 0} {$i <= $lastNum} {incr i} {
- if {![info exists stubs($name,$plat,$i)]} {
- eval {append temp} $skipString
- } else {
- append temp [$slotProc $name $stubs($name,$plat,$i) $i]
- }
+ array set block {unix 0 x11 0 win 0 macosx 0 aqua 0}
+ foreach s [array names stubs $name,*,lastNum] {
+ set block([lindex [split $s ,] 1]) 1
+ }
+ ## unix ##
+ if {$block(unix) && !$block(x11)} {
+ set temp {}
+ set plat unix
+ set lastNum $stubs($name,$plat,lastNum)
+ for {set i 0} {$i <= $lastNum} {incr i} {
+ if {[info exists stubs($name,$plat,$i)]} {
+ append temp [$slotProc $name $stubs($name,$plat,$i) $i]
+ } else {
+ eval {append temp} $skipString
}
- append text [addPlatformGuard $plat $temp]
}
+ append text [addPlatformGuard $plat $temp]
}
- # Again, make sure you don't duplicate entries for macosx & aqua.
- if {[info exists stubs($name,aqua,lastNum)]
- && ![info exists stubs($name,macosx,lastNum)]} {
- set lastNum $stubs($name,aqua,lastNum)
+ ## win ##
+ if {$block(win)} {
set temp {}
+ set plat win
+ set lastNum $stubs($name,$plat,lastNum)
for {set i 0} {$i <= $lastNum} {incr i} {
- if {![info exists stubs($name,aqua,$i)]} {
- eval {append temp} $skipString
+ if {[info exists stubs($name,$plat,$i)]} {
+ append temp [$slotProc $name $stubs($name,$plat,$i) $i]
} else {
- append temp [$slotProc $name $stubs($name,aqua,$i) $i]
- }
+ eval {append temp} $skipString
}
- append text [addPlatformGuard aqua $temp]
}
- # Again, make sure you don't duplicate entries for macosx & unix.
- if {[info exists stubs($name,macosx,lastNum)]
- && ![info exists stubs($name,unix,lastNum)]} {
- set lastNum $stubs($name,macosx,lastNum)
+ append text [addPlatformGuard $plat $temp]
+ }
+ ## macosx ##
+ if {$block(macosx) && !$block(aqua) && !$block(x11)} {
set temp {}
+ set lastNum -1
+ foreach plat {unix macosx} {
+ if {$block($plat)} {
+ set lastNum [expr {$lastNum > $stubs($name,$plat,lastNum)
+ ? $lastNum : $stubs($name,$plat,lastNum)}]
+ }
+ }
for {set i 0} {$i <= $lastNum} {incr i} {
- if {![info exists stubs($name,macosx,$i)]} {
- eval {append temp} $skipString
- } else {
- append temp [$slotProc $name $stubs($name,macosx,$i) $i]
+ set emit 0
+ foreach plat {unix macosx} {
+ if {[info exists stubs($name,$plat,$i)]} {
+ append temp [$slotProc $name $stubs($name,$plat,$i) $i]
+ set emit 1
+ break
}
}
- append text [addPlatformGuard macosx $temp]
+ if {!$emit} {
+ eval {append temp} $skipString
+ }
}
- # Again, make sure you don't duplicate entries for x11 & unix.
- if {[info exists stubs($name,x11,lastNum)]
- && ![info exists stubs($name,unix,lastNum)]} {
- set lastNum $stubs($name,x11,lastNum)
+ append text [addPlatformGuard macosx $temp]
+ }
+ ## aqua ##
+ if {$block(aqua)} {
set temp {}
+ set lastNum -1
+ foreach plat {unix macosx aqua} {
+ if {$block($plat)} {
+ set lastNum [expr {$lastNum > $stubs($name,$plat,lastNum)
+ ? $lastNum : $stubs($name,$plat,lastNum)}]
+ }
+ }
for {set i 0} {$i <= $lastNum} {incr i} {
- if {![info exists stubs($name,x11,$i)]} {
+ set emit 0
+ foreach plat {unix macosx aqua} {
+ if {[info exists stubs($name,$plat,$i)]} {
+ append temp [$slotProc $name $stubs($name,$plat,$i) $i]
+ set emit 1
+ break
+ }
+ }
+ if {!$emit} {
eval {append temp} $skipString
- } else {
- append temp [$slotProc $name $stubs($name,x11,$i) $i]
+ }
+ }
+ append text [addPlatformGuard aqua $temp]
+ }
+ ## x11 ##
+ if {$block(x11)} {
+ set temp {}
+ set lastNum -1
+ foreach plat {unix macosx x11} {
+ if {$block($plat)} {
+ set lastNum [expr {$lastNum > $stubs($name,$plat,lastNum)
+ ? $lastNum : $stubs($name,$plat,lastNum)}]
+ }
+ }
+ for {set i 0} {$i <= $lastNum} {incr i} {
+ set emit 0
+ foreach plat {unix macosx x11} {
+ if {[info exists stubs($name,$plat,$i)]} {
+ if {$plat ne "macosx"} {
+ append temp [$slotProc $name \
+ $stubs($name,$plat,$i) $i]
+ } else {
+ eval {set etxt} $skipString
+ append temp [addPlatformGuard $plat [$slotProc \
+ $name $stubs($name,$plat,$i) $i] $etxt]
+ }
+ set emit 1
+ break
}
}
- append text [addPlatformGuard x11 $temp]
+ if {!$emit} {
+ eval {append temp} $skipString
+ }
}
+ append text [addPlatformGuard x11 $temp]
+ }
}
}
@@ -725,7 +877,6 @@ proc genStubs::forAllStubs {name slotProc onAll textVar \
# None.
proc genStubs::emitDeclarations {name textVar} {
- variable stubs
upvar $textVar text
append text "\n/*\n * Exported function declarations:\n */\n\n"
@@ -745,17 +896,18 @@ proc genStubs::emitDeclarations {name textVar} {
# None.
proc genStubs::emitMacros {name textVar} {
- variable stubs
variable libraryName
upvar $textVar text
set upName [string toupper $libraryName]
- append text "\n#if defined(USE_${upName}_STUBS) && !defined(USE_${upName}_STUB_PROCS)\n"
+ append text "\n#if defined(USE_${upName}_STUBS) &&\
+ !defined(USE_${upName}_STUB_PROCS)\n"
append text "\n/*\n * Inline function declarations:\n */\n\n"
-
+
forAllStubs $name makeMacro 0 text
- append text "\n#endif /* defined(USE_${upName}_STUBS) && !defined(USE_${upName}_STUB_PROCS) */\n"
+ append text "\n#endif /* defined(USE_${upName}_STUBS) &&\
+ !defined(USE_${upName}_STUB_PROCS) */\n"
return
}
@@ -806,27 +958,6 @@ proc genStubs::emitHeader {name} {
return
}
-# genStubs::emitStubs --
-#
-# This function emits the body of the <name>Stubs.c file for
-# the specified interface.
-#
-# Arguments:
-# name The name of the interface being emitted.
-#
-# Results:
-# None.
-
-proc genStubs::emitStubs {name} {
- variable outDir
-
- append text "\n/*\n * Exported stub functions:\n */\n\n"
- forAllStubs $name makeStub 0 text
-
- rewriteFile [file join $outDir ${name}Stubs.c] $text
- return
-}
-
# genStubs::emitInit --
#
# Generate the table initializers for an interface.
@@ -847,7 +978,7 @@ proc genStubs::emitInit {name textVar} {
append capName [string range $name 1 end]
if {[info exists hooks($name)]} {
- append text "\nstatic ${capName}StubHooks ${name}StubHooks = \{\n"
+ append text "\nstatic ${capName}StubHooks ${name}StubHooks = \{\n"
set sep " "
foreach sub $hooks($name) {
append text $sep "&${sub}Stubs"
@@ -862,7 +993,7 @@ proc genStubs::emitInit {name textVar} {
} else {
append text " NULL,\n"
}
-
+
forAllStubs $name makeInit 1 text {" NULL, /* $i */\n"}
append text "\};\n"
@@ -953,13 +1084,14 @@ proc genStubs::init {} {
# Results:
# Returns any values that were not assigned to variables.
-proc lassign {valueList args} {
- if {[llength $args] == 0} {
- error "wrong # args: lassign list varname ?varname..?"
- }
-
- uplevel [list foreach $args $valueList {break}]
- return [lrange $valueList [llength $args] end]
+if {[string length [namespace which lassign]] == 0} {
+ proc lassign {valueList args} {
+ if {[llength $args] == 0} {
+ error "wrong # args: should be \"lassign list varName ?varName ...?\""
+ }
+ uplevel [list foreach $args $valueList {break}]
+ return [lrange $valueList [llength $args] end]
+ }
}
genStubs::init
diff --git a/tools/genWinImage.tcl b/tools/genWinImage.tcl
deleted file mode 100644
index f923df8..0000000
--- a/tools/genWinImage.tcl
+++ /dev/null
@@ -1,155 +0,0 @@
-# genWinImage.tcl --
-#
-# This script generates the Windows installer.
-#
-# Copyright (c) 1999 by Scriptics Corporation.
-# All rights reserved.
-
-
-# This file is insensitive to the directory from which it is invoked.
-
-namespace eval genWinImage {
- # toolsDir --
- #
- # This variable points to the platform specific tools directory.
-
- variable toolsDir
-
- # tclBuildDir --
- #
- # This variable points to the directory containing the Tcl built tree.
-
- variable tclBuildDir
-
- # tkBuildDir --
- #
- # This variable points to the directory containing the Tk built tree.
-
- variable tkBuildDir
-
- # our script name at runtime
- variable script [info script]
-}
-
-# genWinImage::init --
-#
-# This is the main entry point.
-#
-# Arguments:
-# None.
-#
-# Results:
-# None.
-
-proc genWinImage::init {} {
- global tcl_platform argv argv0
- variable tclBuildDir
- variable tkBuildDir
- variable toolsDir
- variable script
-
- puts "\n--- $script started: \
- [clock format [clock seconds] -format "%Y%m%d-%H:%M"] --\n"
-
- if {$tcl_platform(platform) != "windows"} {
- puts stderr "ERROR: Cannot build TCL.EXE on Unix systems"
- exit 1
- }
-
- if {[llength $argv] != 3} {
- puts stderr "usage: $argv0 <tclBuildDir> <tkBuildDir> <toolsDir>"
- exit 0
- }
-
- set tclBuildDir [lindex $argv 0]
- set tkBuildDir [lindex $argv 1]
- set toolsDir [lindex $argv 2]
-
- generateInstallers
-
- puts "\n--- $script finished: \
- [clock format [clock seconds] -format "%Y%m%d-%H:%M"] --\n\n"
-}
-
-# genWinImage::makeTextFile --
-#
-# Convert the input file into a CRLF terminated text file.
-#
-# Arguments:
-# infile The input file to convert.
-# outfile The location where the text file should be stored.
-#
-# Results:
-# None.
-
-proc genWinImage::makeTextFile {infile outfile} {
- set f [open $infile r]
- set text [read $f]
- close $f
- set f [open $outfile w]
- fconfigure $f -translation crlf
- puts -nonewline $f $text
- close $f
-}
-
-# genWinImage::generateInstallers --
-#
-# Perform substitutions on the pro.wse.in file and then
-# invoke the WSE script twice; once for CD and once for web.
-#
-# Arguments:
-# None.
-#
-# Results:
-# Leaves proweb.exe and procd.exe sitting in the curent directory.
-
-proc genWinImage::generateInstallers {} {
- variable toolsDir
- variable tclBuildDir
- variable tkBuildDir
-
- # Now read the "pro/srcs/install/pro.wse.in" file, have Tcl make
- # appropriate substitutions, write out the resulting file in a
- # current-working-directory. Use this new file to perform installation
- # image creation. Note that we have to use this technique to set
- # the value of _WISE_ because wise32 won't use a /d switch for this
- # variable.
-
- set __TCLBASEDIR__ [file native $tclBuildDir]
- set __TKBASEDIR__ [file native $tkBuildDir]
- set __WISE__ [file native [file join $toolsDir wise]]
-
- set f [open [file join $__TCLBASEDIR__ generic/tcl.h] r]
- set s [read $f]
- close $f
- regexp {TCL_PATCH_LEVEL\s*\"([^\"]*)\"} $s dummy __TCL_PATCH_LEVEL__
-
- set f [open tcl.wse.in r]
- set s [read $f]
- close $f
- set s [subst -nocommands -nobackslashes $s]
- set f [open tcl.wse w]
- puts $f $s
- close $f
-
- # Ensure the text files are CRLF terminated
-
- makeTextFile [file join $tclBuildDir win/README.binary] \
- [file join $tclBuildDir win/readme.txt]
- makeTextFile [file join $tclBuildDir license.terms] \
- [file join $tclBuildDir license.txt]
-
- set wise32ProgFilePath [file native [file join $__WISE__ wise32.exe]]
-
- # Run the Wise installer to create the Windows install images.
-
- if {[catch {exec [file native $wise32ProgFilePath] /c tcl.wse} errMsg]} {
- puts stderr "ERROR: $errMsg"
- } else {
- puts "\"TCL.EXE\" created."
- }
-
- return
-}
-
-genWinImage::init
diff --git a/tools/index.tcl b/tools/index.tcl
index b986012..7b11e3f 100644
--- a/tools/index.tcl
+++ b/tools/index.tcl
@@ -130,7 +130,7 @@ proc text string {
proc macro {name args} {
switch $name {
- SH {
+ SH - SS {
global state
switch $args {
diff --git a/tools/installData.tcl b/tools/installData.tcl
new file mode 100644
index 0000000..4b43f1e
--- /dev/null
+++ b/tools/installData.tcl
@@ -0,0 +1,50 @@
+#!/bin/sh
+#\
+exec tclsh "$0" ${1+"$@"}
+
+#----------------------------------------------------------------------
+#
+# installData.tcl --
+#
+# This file installs a hierarchy of data found in the directory
+# specified by its first argument into the directory specified
+# by its second.
+#
+#----------------------------------------------------------------------
+#
+# Copyright (c) 2004 by Kevin B. Kenny. All rights reserved.
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#----------------------------------------------------------------------
+
+proc copyDir {d1 d2} {
+
+ puts [format {%*sCreating %s} [expr {4 * [info level]}] {} \
+ [file tail $d2]]
+
+ file delete -force -- $d2
+ file mkdir $d2
+
+ foreach ftail [glob -directory $d1 -nocomplain -tails *] {
+ set f [file join $d1 $ftail]
+ if {[file isdirectory $f] && [string compare CVS $ftail]} {
+ copyDir $f [file join $d2 $ftail]
+ } elseif {[file isfile $f]} {
+ file copy -force $f [file join $d2 $ftail]
+ if {$::tcl_platform(platform) eq {unix}} {
+ file attributes [file join $d2 $ftail] -permissions 0644
+ } else {
+ file attributes [file join $d2 $ftail] -readonly 1
+ }
+ }
+ }
+
+ if {$::tcl_platform(platform) eq {unix}} {
+ file attributes $d2 -permissions 0755
+ } else {
+ file attributes $d2 -readonly 1
+ }
+
+}
+
+copyDir [file normalize [lindex $argv 0]] [file normalize [lindex $argv 1]]
diff --git a/tools/loadICU.tcl b/tools/loadICU.tcl
new file mode 100755
index 0000000..5b09e2c
--- /dev/null
+++ b/tools/loadICU.tcl
@@ -0,0 +1,619 @@
+#----------------------------------------------------------------------
+#
+# loadICU,tcl --
+#
+# Extracts locale strings from a distribution of ICU
+# (http://oss.software.ibm.com/developerworks/opensource/icu/project/)
+# and makes Tcl message catalogs for the 'clock' command.
+#
+# Usage:
+# loadICU.tcl sourceDir destDir
+#
+# Parameters:
+# sourceDir -- Path name of the 'data' directory of your ICU4C
+# distribution.
+# destDir -- Directory into which the Tcl message catalogs should go.
+#
+# Results:
+# None.
+#
+# Side effects:
+# Creates the message catalogs.
+#
+#----------------------------------------------------------------------
+#
+# Copyright (c) 2004 by Kevin B. Kenny. All rights reserved.
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#----------------------------------------------------------------------
+
+# Calculate the Chinese numerals from zero to ninety-nine.
+
+set zhDigits [list {} \u4e00 \u4e8c \u4e09 \u56db \
+ \u4e94 \u516d \u4e03 \u516b \u4e5d]
+set t 0
+foreach zt $zhDigits {
+ if { $t == 0 } {
+ set zt {}
+ } elseif { $t == 10 } {
+ set zt \u5341
+ } else {
+ append zt \u5341
+ }
+ set d 0
+ foreach zd $zhDigits {
+ if { $t == 0 && $d == 0 } {
+ set zd \u3007
+ } elseif { $t == 20 && $d != 0 } {
+ set zt \u5eff
+ } elseif { $t == 30 && $d != 0 } {
+ set zt \u5345
+ }
+ lappend zhNumbers $zt$zd
+ incr d
+ }
+ incr t 10
+}
+
+# Set format overrides for various locales.
+
+set format(zh,LOCALE_NUMERALS) $zhNumbers
+set format(ja,LOCALE_ERAS) [list \
+ [list -9223372036854775808 \u897f\u66a6 0 ] \
+ [list -3061011600 \u660e\u6cbb 1867] \
+ [list -1812186000 \u5927\u6b63 1911] \
+ [list -1357635600 \u662d\u548c 1925] \
+ [list 600220800 \u5e73\u6210 1988]]
+set format(zh,LOCALE_DATE_FORMAT) "\u516c\u5143%Y\u5e74%B%Od\u65E5"
+set format(ja,LOCALE_DATE_FORMAT) "%EY\u5e74%m\u6708%d\u65E5"
+set format(ko,LOCALE_DATE_FORMAT) "%Y\ub144%B%Od\uc77c"
+set format(zh,LOCALE_TIME_FORMAT) "%OH\u65f6%OM\u5206%OS\u79d2"
+set format(ja,LOCALE_TIME_FORMAT) "%H\u6642%M\u5206%S\u79d2"
+set format(ko,LOCALE_TIME_FORMAT) "%H\uc2dc%M\ubd84%S\ucd08"
+set format(zh,LOCALE_DATE_TIME_FORMAT) "%A %Y\u5e74%B%Od\u65E5%OH\u65f6%OM\u5206%OS\u79d2 %z"
+set format(ja,LOCALE_DATE_TIME_FORMAT) "%EY\u5e74%m\u6708%d\u65E5 (%a) %H\u6642%M\u5206%S\u79d2 %z"
+set format(ko,LOCALE_DATE_TIME_FORMAT) "%A %Y\ub144%B%Od\uc77c%H\uc2dc%M\ubd84%S\ucd08 %z"
+set format(ja,TIME_FORMAT_12) {%P %I:%M:%S}
+
+# The next set of format overrides were obtained from the glibc
+# localization strings.
+
+set format(cs_CZ,DATE_FORMAT) %d.%m.%Y
+set format(cs_CZ,DATE_TIME_FORMAT) {%a %e. %B %Y, %H:%M:%S %z}
+set format(cs_CZ,TIME_FORMAT) %H:%M:%S
+set format(cs_CZ,TIME_FORMAT_12) %I:%M:%S
+set format(da_DK,DATE_FORMAT) %d-%m-%Y
+set format(da_DK,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(da_DK,TIME_FORMAT) %T
+set format(da_DK,TIME_FORMAT_12) %T
+set format(de_AT,DATE_FORMAT) %Y-%m-%d
+set format(de_AT,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(de_AT,TIME_FORMAT) %T
+set format(de_AT,TIME_FORMAT_12) %T
+set format(de_BE,DATE_FORMAT) %Y-%m-%d
+set format(de_BE,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(de_BE,TIME_FORMAT) %T
+set format(de_BE,TIME_FORMAT_12) %T
+set format(de_CH,DATE_FORMAT) %Y-%m-%d
+set format(de_CH,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(de_CH,TIME_FORMAT) %T
+set format(de_CH,TIME_FORMAT_12) %T
+set format(de_DE,DATE_FORMAT) %Y-%m-%d
+set format(de_DE,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(de_DE,TIME_FORMAT) %T
+set format(de_DE,TIME_FORMAT_12) %T
+set format(de_LU,DATE_FORMAT) %Y-%m-%d
+set format(de_LU,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(de_LU,TIME_FORMAT) %T
+set format(de_LU,TIME_FORMAT_12) %T
+set format(en_CA,DATE_FORMAT) %d/%m/%y
+set format(en_CA,DATE_TIME_FORMAT) {%a %d %b %Y %r %z}
+set format(en_CA,TIME_FORMAT) %r
+set format(en_CA,TIME_FORMAT_12) {%I:%M:%S %p}
+set format(en_DK,DATE_FORMAT) %Y-%m-%d
+set format(en_DK,DATE_TIME_FORMAT) {%Y-%m-%dT%T %z}
+set format(en_DK,TIME_FORMAT) %T
+set format(en_DK,TIME_FORMAT_12) %T
+set format(en_GB,DATE_FORMAT) %d/%m/%y
+set format(en_GB,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(en_GB,TIME_FORMAT) %T
+set format(en_GB,TIME_FORMAT_12) %T
+set format(en_IE,DATE_FORMAT) %d/%m/%y
+set format(en_IE,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(en_IE,TIME_FORMAT) %T
+set format(en_IE,TIME_FORMAT_12) %T
+set format(en_US,DATE_FORMAT) %m/%d/%y
+set format(en_US,DATE_TIME_FORMAT) {%a %d %b %Y %r %z}
+set format(en_US,TIME_FORMAT) %r
+set format(en_US,TIME_FORMAT_12) {%I:%M:%S %p}
+set format(es_ES,DATE_FORMAT) %d/%m/%y
+set format(es_ES,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(es_ES,TIME_FORMAT) %T
+set format(es_ES,TIME_FORMAT_12) %T
+set format(et_EE,DATE_FORMAT) %d.%m.%Y
+set format(et_EE,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(et_EE,TIME_FORMAT) %T
+set format(et_EE,TIME_FORMAT_12) %T
+set format(eu_ES,DATE_FORMAT) {%a, %Yeko %bren %da}
+set format(eu_ES,DATE_TIME_FORMAT) {%y-%m-%d %T %z}
+set format(eu_ES,TIME_FORMAT) %T
+set format(eu_ES,TIME_FORMAT_12) %T
+set format(fi_FI,DATE_FORMAT) %d.%m.%Y
+set format(fi_FI,DATE_TIME_FORMAT) {%a %e %B %Y %T}
+set format(fi_FI,TIME_FORMAT) %T
+set format(fi_FI,TIME_FORMAT_12) %T
+set format(fo_FO,DATE_FORMAT) %d/%m-%Y
+set format(fo_FO,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(fo_FO,TIME_FORMAT) %T
+set format(fo_FO,TIME_FORMAT_12) %T
+set format(fr_BE,DATE_FORMAT) %d/%m/%y
+set format(fr_BE,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(fr_BE,TIME_FORMAT) %T
+set format(fr_BE,TIME_FORMAT_12) %T
+set format(fr_CA,DATE_FORMAT) %Y-%m-%d
+set format(fr_CA,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(fr_CA,TIME_FORMAT) %T
+set format(fr_CA,TIME_FORMAT_12) %T
+set format(fr_CH,DATE_FORMAT) {%d. %m. %y}
+set format(fr_CH,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(fr_CH,TIME_FORMAT) %T
+set format(fr_CH,TIME_FORMAT_12) %T
+set format(fr_FR,DATE_FORMAT) %d.%m.%Y
+set format(fr_FR,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(fr_FR,TIME_FORMAT) %T
+set format(fr_FR,TIME_FORMAT_12) %T
+set format(fr_LU,DATE_FORMAT) %d.%m.%Y
+set format(fr_LU,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(fr_LU,TIME_FORMAT) %T
+set format(fr_LU,TIME_FORMAT_12) %T
+set format(ga_IE,DATE_FORMAT) %d.%m.%y
+set format(ga_IE,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(ga_IE,TIME_FORMAT) %T
+set format(ga_IE,TIME_FORMAT_12) %T
+set format(gr_GR,DATE_FORMAT) %d/%m/%Y
+set format(gr_GR,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(gr_GR,TIME_FORMAT) %T
+set format(gr_GR,TIME_FORMAT_12) %T
+set format(hr_HR,DATE_FORMAT) %d.%m.%y
+set format(hr_HR,DATE_TIME_FORMAT) {%a %d %b %Y %T}
+set format(hr_HR,TIME_FORMAT) %T
+set format(hr_HR,TIME_FORMAT_12) %T
+set format(hu_HU,DATE_FORMAT) %Y-%m-%d
+set format(hu_HU,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(hu_HU,TIME_FORMAT) %T
+set format(hu_HU,TIME_FORMAT_12) %T
+set format(is_IS,DATE_FORMAT) {%a %e.%b %Y}
+set format(is_IS,DATE_TIME_FORMAT) {%a %e.%b %Y, %T %z}
+set format(is_IS,TIME_FORMAT) %T
+set format(is_IS,TIME_FORMAT_12) %T
+set format(it_IT,DATE_FORMAT) %d/%m/%Y
+set format(it_IT,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(it_IT,TIME_FORMAT) %T
+set format(it_IT,TIME_FORMAT_12) %T
+set format(iw_IL,DATE_FORMAT) %d/%m/%y
+set format(iw_IL,DATE_TIME_FORMAT) {%z %H:%M:%S %Y %b %d %a}
+set format(iw_IL,TIME_FORMAT) %H:%M:%S
+set format(iw_IL,TIME_FORMAT_12) {%I:%M:%S %P}
+set format(kl_GL,DATE_FORMAT) {%d %b %Y}
+set format(kl_GL,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(kl_GL,TIME_FORMAT) %T
+set format(kl_GL,TIME_FORMAT_12) %T
+set format(lt_LT,DATE_FORMAT) %Y.%m.%d
+set format(lt_LT,DATE_TIME_FORMAT) {%Y m. %B %d d. %T}
+set format(lt_LT,TIME_FORMAT) %T
+set format(lt_LT,TIME_FORMAT_12) %T
+set format(lv_LV,DATE_FORMAT) %Y.%m.%d.
+set format(lv_LV,DATE_TIME_FORMAT) {%A, %Y. gada %e. %B, plkst. %H un %M}
+set format(lv_LV,TIME_FORMAT) %T
+set format(lv_LV,TIME_FORMAT_12) %T
+set format(nl_BE,DATE_FORMAT) %d-%m-%y
+set format(nl_BE,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(nl_BE,TIME_FORMAT) %T
+set format(nl_BE,TIME_FORMAT_12) %T
+set format(nl_NL,DATE_FORMAT) %d-%m-%y
+set format(nl_NL,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(nl_NL,TIME_FORMAT) %T
+set format(nl_NL,TIME_FORMAT_12) %T
+set format(no_NO,DATE_FORMAT) %d-%m-%Y
+set format(no_NO,DATE_TIME_FORMAT) {%a %d-%m-%Y %T %z}
+set format(no_NO,TIME_FORMAT) %T
+set format(no_NO,TIME_FORMAT_12) %T
+set format(pl_PL,DATE_FORMAT) %Y-%m-%d
+set format(pl_PL,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(pl_PL,TIME_FORMAT) %T
+set format(pl_PL,TIME_FORMAT_12) %T
+set format(pt_BR,DATE_FORMAT) %d-%m-%Y
+set format(pt_BR,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(pt_BR,TIME_FORMAT) %T
+set format(pt_BR,TIME_FORMAT_12) %T
+set format(pt_PT,DATE_FORMAT) %d-%m-%Y
+set format(pt_PT,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(pt_PT,TIME_FORMAT) %T
+set format(pt_PT,TIME_FORMAT_12) %T
+set format(ro_RO,DATE_FORMAT) %Y-%m-%d
+set format(ro_RO,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(ro_RO,TIME_FORMAT) %T
+set format(ro_RO,TIME_FORMAT_12) %T
+set format(ru_RU,DATE_FORMAT) %d.%m.%Y
+set format(ru_RU,DATE_TIME_FORMAT) {%a %d %b %Y %T}
+set format(ru_RU,TIME_FORMAT) %T
+set format(ru_RU,TIME_FORMAT_12) %T
+set format(sl_SI,DATE_FORMAT) %d.%m.%Y
+set format(sl_SI,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(sl_SI,TIME_FORMAT) %T
+set format(sl_SI,TIME_FORMAT_12) %T
+set format(sv_FI,DATE_FORMAT) %Y-%m-%d
+set format(sv_FI,DATE_TIME_FORMAT) {%a %e %b %Y %H.%M.%S}
+set format(sv_FI,TIME_FORMAT) %H.%M.%S
+set format(sv_FI,TIME_FORMAT_12) %H.%M.%S
+set format(sv_SE,DATE_FORMAT) %Y-%m-%d
+set format(sv_SE,DATE_TIME_FORMAT) {%a %e %b %Y %H.%M.%S}
+set format(sv_SE,TIME_FORMAT) %H.%M.%S
+set format(sv_SE,TIME_FORMAT_12) %H.%M.%S
+set format(tr_TR,DATE_FORMAT) %Y-%m-%d
+set format(tr_TR,DATE_TIME_FORMAT) {%a %d %b %Y %T %z}
+set format(tr_TR,TIME_FORMAT) %T
+set format(tr_TR,TIME_FORMAT_12) %T
+
+#----------------------------------------------------------------------
+#
+# handleLocaleFile --
+#
+# Extracts strings from an ICU locale definition.
+#
+# Parameters:
+# localeName - Name of the locale (e.g., de_AT_euro)
+# fileName - Name of the file containing the data
+# msgFileName - Name of the file containing the Tcl message catalog
+#
+# Results:
+# None.
+#
+# Side effects:
+# Writes the Tcl message catalog.
+#
+#----------------------------------------------------------------------
+
+proc handleLocaleFile { localeName fileName msgFileName } {
+ variable format
+
+ # Get the content of the ICU file
+
+ set f [open $fileName r]
+ fconfigure $f -encoding utf-8
+ set data [read $f]
+ close $f
+
+ # Parse the ICU data
+
+ set state {}
+ foreach line [split $data \n] {
+ switch -exact -- $state {
+ {} {
+
+ # Look for the beginnings of data blocks
+
+ switch -regexp -- $line {
+ {^[[:space:]]*AmPmMarkers[[:space:]]+[\{]} {
+ set state data
+ set key AmPmMarkers
+ }
+ {^[[:space:]]*DateTimePatterns[[:space:]]+[\{]} {
+ set state data
+ set key DateTimePatterns
+ }
+ {^[[:space:]]*DayAbbreviations[[:space:]]+[\{]} {
+ set state data
+ set key DayAbbreviations
+ }
+ {^[[:space:]]*DayNames[[:space:]]+[\{]} {
+ set state data
+ set key DayNames
+ }
+ {^[[:space:]]*Eras[[:space:]]+[\{]} {
+ set state data
+ set key Eras
+ }
+ {^[[:space:]]*MonthAbbreviations[[:space:]]+[\{]} {
+ set state data
+ set key MonthAbbreviations
+ }
+ {^[[:space:]]*MonthNames[[:space:]]+[\{]} {
+ set state data
+ set key MonthNames
+ }
+ }
+ }
+ data {
+
+
+ # Inside a data block, collect the strings, doing backslash
+ # expansion to pick up the Unicodes
+
+ if { [regexp {"(.*)",} $line -> item] } {
+ lappend items($key) [subst -nocommands -novariables $item]
+ } elseif { [regexp {^[[:space:]]*[\}][[:space:]]*$} $line] } {
+ set state {}
+ }
+ }
+ }
+ }
+
+ # Skip locales that don't change time strings.
+
+ if {![array exists items]} return
+
+ # Write the Tcl message catalog
+
+ set f [open $msgFileName w]
+
+ # Write a header
+
+ puts $f "\# created by $::argv0 -- do not edit"
+ puts $f "namespace eval ::tcl::clock \{"
+
+ # Do ordinary sets of strings (weekday and month names)
+
+ foreach key {
+ DayAbbreviations DayNames MonthAbbreviations MonthNames
+ } tkey {
+ DAYS_OF_WEEK_ABBREV DAYS_OF_WEEK_FULL
+ MONTHS_ABBREV MONTHS_FULL
+ } {
+ if { [info exists items($key)] } {
+ set itemList $items($key)
+ set cmd1 " ::msgcat::mcset "
+ append cmd1 $localeName " " $tkey " \[list "
+ foreach item $itemList {
+ append cmd1 \\\n { } \" [backslashify $item] \"
+ }
+ append cmd1 \]
+ puts $f $cmd1
+ }
+ }
+
+ # Do the eras, B.C.E., and C.E.
+
+ if { [info exists items(Eras)] } {
+ foreach { bce ce } $items(Eras) break
+ set cmd " ::msgcat::mcset "
+ append cmd $localeName " " BCE " \"" [backslashify $bce] \"
+ puts $f $cmd
+ set cmd " ::msgcat::mcset "
+ append cmd $localeName " " CE " \"" [backslashify $ce] \"
+ puts $f $cmd
+ }
+
+ # Do the AM and PM markers
+
+ if { [info exists items(AmPmMarkers)] } {
+ foreach { am pm } $items(AmPmMarkers) break
+ set cmd " ::msgcat::mcset "
+ append cmd $localeName " " AM " \"" [backslashify $am] \"
+ puts $f $cmd
+ set cmd " ::msgcat::mcset "
+ append cmd $localeName " " PM " \"" [backslashify $pm] \"
+ puts $f $cmd
+ }
+
+ # Do the date/time patterns. First date...
+
+ if { [info exists format($localeName,DATE_FORMAT)]
+ || [info exists items(DateTimePatterns)] } {
+
+ # Find the shortest date format that includes a 4-digit year.
+
+ if { ![info exists format($localeName,DATE_FORMAT)] } {
+ for { set i 7 } { $i >= 4 } { incr i -1 } {
+ if { [regexp yyyy [lindex $items(DateTimePatterns) $i]] } {
+ break
+ }
+ }
+ set fmt \
+ [backslashify \
+ [percentify [lindex $items(DateTimePatterns) $i]]]
+ set format($localeName,DATE_FORMAT) $fmt
+ }
+
+ # Put it to the message catalog
+
+ set cmd " ::msgcat::mcset "
+ append cmd $localeName " DATE_FORMAT \"" \
+ $format($localeName,DATE_FORMAT) "\""
+ puts $f $cmd
+ }
+
+ # Time
+
+ if { [info exists format($localeName,TIME_FORMAT)]
+ || [info exists items(DateTimePatterns)] } {
+
+ # Find the shortest time pattern that includes the seconds
+
+ if { ![info exists format($localeName,TIME_FORMAT)] } {
+ for { set i 3 } { $i >= 0 } { incr i -1 } {
+ if { [regexp H [lindex $items(DateTimePatterns) $i]]
+ && [regexp s [lindex $items(DateTimePatterns) $i]] } {
+ break
+ }
+ }
+ if { $i >= 0 } {
+ set fmt \
+ [backslashify \
+ [percentify [lindex $items(DateTimePatterns) $i]]]
+ regsub { %Z} $fmt {} format($localeName,TIME_FORMAT)
+ }
+ }
+
+ # Put it to the message catalog
+
+ if { [info exists format($localeName,TIME_FORMAT)] } {
+ set cmd " ::msgcat::mcset "
+ append cmd $localeName " TIME_FORMAT \"" \
+ $format($localeName,TIME_FORMAT) "\""
+ puts $f $cmd
+ }
+ }
+
+ # 12-hour time...
+
+ if { [info exists format($localeName,TIME_FORMAT_12)]
+ || [info exists items(DateTimePatterns)] } {
+
+ # Shortest patterm with 12-hour time that includes seconds
+
+ if { ![info exists format($localeName,TIME_FORMAT_12)] } {
+ for { set i 3 } { $i >= 0 } { incr i -1 } {
+ if { [regexp h [lindex $items(DateTimePatterns) $i]]
+ && [regexp s [lindex $items(DateTimePatterns) $i]] } {
+ break
+ }
+ }
+ if { $i >= 0 } {
+ set fmt \
+ [backslashify \
+ [percentify [lindex $items(DateTimePatterns) $i]]]
+ regsub { %Z} $fmt {} format($localeName,TIME_FORMAT_12)
+ }
+ }
+
+ # Put it to the catalog
+
+ if { [info exists format($localeName,TIME_FORMAT_12)] } {
+ set cmd " ::msgcat::mcset "
+ append cmd $localeName " TIME_FORMAT_12 \"" \
+ $format($localeName,TIME_FORMAT_12) "\""
+ puts $f $cmd
+ }
+ }
+
+ # Date and time... Prefer 24-hour format to 12-hour format.
+
+ if { ![info exists format($localeName,DATE_TIME_FORMAT)]
+ && [info exists format($localeName,DATE_FORMAT)]
+ && [info exists format($localeName,TIME_FORMAT)]} {
+ set format($localeName,DATE_TIME_FORMAT) \
+ $format($localeName,DATE_FORMAT)
+ append format($localeName,DATE_TIME_FORMAT) \
+ " " $format($localeName,TIME_FORMAT) " %z"
+ }
+ if { ![info exists format($localeName,DATE_TIME_FORMAT)]
+ && [info exists format($localeName,DATE_FORMAT)]
+ && [info exists format($localeName,TIME_FORMAT_12)]} {
+ set format($localeName,DATE_TIME_FORMAT) \
+ $format($localeName,DATE_FORMAT)
+ append format($localeName,DATE_TIME_FORMAT) \
+ " " $format($localeName,TIME_FORMAT_12) " %z"
+ }
+
+ # Write date/time format to the file
+
+ if { [info exists format($localeName,DATE_TIME_FORMAT)] } {
+ set cmd " ::msgcat::mcset "
+ append cmd $localeName " DATE_TIME_FORMAT \"" \
+ $format($localeName,DATE_TIME_FORMAT) "\""
+ puts $f $cmd
+ }
+
+ # Write the string sets to the file.
+
+ foreach key {
+ LOCALE_NUMERALS LOCALE_DATE_FORMAT LOCALE_TIME_FORMAT
+ LOCALE_DATE_TIME_FORMAT LOCALE_ERAS LOCALE_YEAR_FORMAT
+ } {
+ if { [info exists format($localeName,$key)] } {
+ set cmd " ::msgcat::mcset "
+ append cmd $localeName " " $key " \"" \
+ [backslashify $format($localeName,$key)] "\""
+ puts $f $cmd
+ }
+ }
+
+ # Footer
+
+ puts $f "\}"
+ close $f
+}
+
+#----------------------------------------------------------------------
+#
+# percentify --
+#
+# Converts a Java/ICU-style time format to a C/Tcl style one.
+#
+# Parameters:
+# string -- Format to convert
+#
+# Results:
+# Returns the converted format.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc percentify { string } {
+ set retval {}
+ foreach { unquoted quoted } [split $string '] {
+ append retval [string map {
+ EEEE %A MMMM %B yyyy %Y
+ MMM %b EEE %a
+ dd %d hh %I HH %H mm %M MM %m ss %S yy %y
+ a %P d %e h %l H %k M %m z %z
+ } $unquoted]
+ append retval $quoted
+ }
+ return $retval
+}
+
+#----------------------------------------------------------------------
+#
+# backslashify --
+#
+# Converts a UTF-8 string to a plain ASCII one with escapes.
+#
+# Parameters:
+# string -- String to convert
+#
+# Results:
+# Returns the converted string
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc backslashify { string } {
+
+ set retval {}
+ foreach char [split $string {}] {
+ scan $char %c ccode
+ if { $ccode >= 0x0020 && $ccode < 0x007f && $char ne "\""
+ && $char ne "\{" && $char ne "\}" && $char ne "\["
+ && $char ne "\]" && $char ne "\\" && $char ne "\$" } {
+ append retval $char
+ } else {
+ append retval \\u [format %04x $ccode]
+ }
+ }
+ return $retval
+}
+
+#----------------------------------------------------------------------
+#
+# MAIN PROGRAM
+#
+#----------------------------------------------------------------------
+
+# Extract directories from command line
+
+foreach { icudir msgdir } $argv break
+
+# Walk the ICU files and create corresponding Tcl message catalogs
+
+foreach fileName [glob -directory $icudir *.txt] {
+ set n [file rootname [file tail $fileName]]
+ if { [regexp {^[a-z]{2,3}(_[A-Z]{2,3}(_.*)?)?$} $n] } {
+ handleLocaleFile $n $fileName [file join $msgdir [string tolower $n].msg]
+ }
+}
diff --git a/tools/makeTestCases.tcl b/tools/makeTestCases.tcl
new file mode 100755
index 0000000..d96a221
--- /dev/null
+++ b/tools/makeTestCases.tcl
@@ -0,0 +1,1180 @@
+# TODO - When integrating this with the Core, path names will need to be
+# swizzled here.
+
+package require msgcat
+set d [file dirname [file dirname [info script]]]
+puts "getting transition data from [file join $d library tzdata America Detroit]"
+source [file join $d library/tzdata/America/Detroit]
+
+namespace eval ::tcl::clock {
+ ::msgcat::mcmset en_US_roman {
+ LOCALE_ERAS {
+ {-62164627200 {} 0}
+ {-59008867200 c 100}
+ {-55853107200 cc 200}
+ {-52697347200 ccc 300}
+ {-49541587200 cd 400}
+ {-46385827200 d 500}
+ {-43230067200 dc 600}
+ {-40074307200 dcc 700}
+ {-36918547200 dccc 800}
+ {-33762787200 cm 900}
+ {-30607027200 m 1000}
+ {-27451267200 mc 1100}
+ {-24295507200 mcc 1200}
+ {-21139747200 mccc 1300}
+ {-17983987200 mcd 1400}
+ {-14828227200 md 1500}
+ {-11672467200 mdc 1600}
+ {-8516707200 mdcc 1700}
+ {-5364662400 mdccc 1800}
+ {-2208988800 mcm 1900}
+ {946684800 mm 2000}
+ }
+ LOCALE_NUMERALS {
+ ? i ii iii iv v vi vii viii ix
+ x xi xii xiii xiv xv xvi xvii xviii xix
+ xx xxi xxii xxiii xxiv xxv xxvi xxvii xxviii xxix
+ xxx xxxi xxxii xxxiii xxxiv xxxv xxxvi xxxvii xxxviii xxxix
+ xl xli xlii xliii xliv xlv xlvi xlvii xlviii xlix
+ l li lii liii liv lv lvi lvii lviii lix
+ lx lxi lxii lxiii lxiv lxv lxvi lxvii lxviii lxix
+ lxx lxxi lxxii lxxiii lxxiv lxxv lxxvi lxxvii lxxviii lxxix
+ lxxx lxxxi lxxxii lxxxiii lxxxiv lxxxv lxxxvi lxxxvii lxxxviii
+ lxxxix
+ xc xci xcii xciii xciv xcv xcvi xcvii xcviii xcix
+ c
+ }
+ DATE_FORMAT {%m/%d/%Y}
+ TIME_FORMAT {%H:%M:%S}
+ DATE_TIME_FORMAT {%x %X}
+ LOCALE_DATE_FORMAT {die %Od mensis %Om annoque %EY}
+ LOCALE_TIME_FORMAT {%OH h %OM m %OS s}
+ LOCALE_DATE_TIME_FORMAT {%Ex %EX}
+ }
+}
+
+#----------------------------------------------------------------------
+#
+# listYears --
+#
+# List the years to test in the common clock test cases.
+#
+# Parameters:
+# startOfYearArray - Name of an array in caller's scope that will
+# be initialized as
+# Results:
+# None
+#
+# Side effects:
+# Determines the year numbers of one common year, one leap year, one year
+# following a common year, and one year following a leap year -- starting
+# on each day of the week -- in the XIXth, XXth and XXIth centuries.
+# Initializes the given array to have keys equal to the year numbers and
+# values equal to [clock seconds] at the start of the corresponding
+# years.
+#
+#----------------------------------------------------------------------
+
+proc listYears { startOfYearArray } {
+
+ upvar 1 $startOfYearArray startOfYear
+
+ # List years after 1970
+
+ set y 1970
+ set s 0
+ set dw 4 ;# Thursday
+ while { $y < 2100 } {
+ if { $y % 4 == 0 && $y % 100 != 0 || $y % 400 == 0 } {
+ set l 1
+ incr dw 366
+ set s2 [expr { $s + wide( 366 * 86400 ) }]
+ } else {
+ set l 0
+ incr dw 365
+ set s2 [expr { $s + wide( 365 * 86400 ) }]
+ }
+ set x [expr { $y >= 2037 }]
+ set dw [expr {$dw % 7}]
+ set c [expr { $y / 100 }]
+ if { ![info exists do($x$c$dw$l)] } {
+ set do($x$c$dw$l) $y
+ set startOfYear($y) $s
+ set startOfYear([expr {$y + 1}]) $s2
+ }
+ set s $s2
+ incr y
+ }
+
+ # List years before 1970
+
+ set y 1970
+ set s 0
+ set dw 4; # Thursday
+ while { $y >= 1801 } {
+ set s0 $s
+ incr dw 371
+ incr y -1
+ if { $y % 4 == 0 && $y % 100 != 0 || $y % 400 == 0 } {
+ set l 1
+ incr dw -366
+ set s [expr { $s - wide(366 * 86400) }]
+ } else {
+ set l 0
+ incr dw -365
+ set s [expr { $s - wide(365 * 86400) }]
+ }
+ set dw [expr {$dw % 7}]
+ set c [expr { $y / 100 }]
+ if { ![info exists do($c$dw$l)] } {
+ set do($c$dw$l) $y
+ set startOfYear($y) $s
+ set startOfYear([expr {$y + 1}]) $s0
+ }
+ }
+
+}
+
+#----------------------------------------------------------------------
+#
+# processFile -
+#
+# Processes the 'clock.test' file, updating the test cases in it.
+#
+# Parameters:
+# None.
+#
+# Side effects:
+# Replaces the file with a new copy, constructing needed test cases.
+#
+#----------------------------------------------------------------------
+
+proc processFile {d} {
+
+ # Open two files
+
+ set f1 [open [file join $d tests/clock.test] r]
+ set f2 [open [file join $d tests/clock.new] w]
+
+ # Copy leading portion of the test file
+
+ set state {}
+ while { [gets $f1 line] >= 0 } {
+ switch -exact -- $state {
+ {} {
+ puts $f2 $line
+ if { [regexp "^\# BEGIN (.*)" $line -> cases]
+ && [string compare {} [info commands $cases]] } {
+ set state inCaseSet
+ $cases $f2
+ }
+ }
+ inCaseSet {
+ if { [regexp "^\#\ END $cases\$" $line] } {
+ puts $f2 $line
+ set state {}
+ }
+ }
+ }
+ }
+
+ # Rotate the files
+
+ close $f1
+ close $f2
+ file delete -force [file join $d tests/clock.bak]
+ file rename -force [file join $d tests/clock.test] \
+ [file join $d tests/clock.bak]
+ file rename [file join $d tests/clock.new] [file join $d tests/clock.test]
+
+}
+
+#----------------------------------------------------------------------
+#
+# testcases2 --
+#
+# Outputs the 'clock-2.x' test cases.
+#
+# Parameters:
+# f2 -- Channel handle to the output file
+#
+# Results:
+# None.
+#
+# Side effects:
+# Test cases for formatting in Gregorian calendar are written to the
+# output file.
+#
+#----------------------------------------------------------------------
+
+proc testcases2 { f2 } {
+
+ listYears startOfYear
+
+ # Define the roman numerals
+
+ set roman {
+ ? i ii iii iv v vi vii viii ix
+ x xi xii xiii xiv xv xvi xvii xviii xix
+ xx xxi xxii xxiii xxiv xxv xxvi xxvii xxviii xxix
+ xxx xxxi xxxii xxxiii xxxiv xxxv xxxvi xxxvii xxxviii xxxix
+ xl xli xlii xliii xliv xlv xlvi xlvii xlviii xlix
+ l li lii liii liv lv lvi lvii lviii lix
+ lx lxi lxii lxiii lxiv lxv lxvi lxvii lxviii lxix
+ lxx lxxi lxxii lxxiii lxxiv lxxv lxxvi lxxvii lxxviii lxxix
+ lxxx lxxxi lxxxii lxxxiii lxxxiv lxxxv lxxxvi lxxxvii lxxxviii lxxxix
+ xc xci xcii xciii xciv xcv xcvi xcvii xcviii xcix
+ c
+ }
+ set romanc {
+ ? c cc ccc cd d dc dcc dccc cm
+ m mc mcc mccc mcd md mdc mdcc mdccc mcm
+ mm mmc mmcc mmccc mmcd mmd mmdc mmdcc mmdccc mmcm
+ mmm mmmc mmmcc mmmccc mmmcd mmmd mmmdc mmmdcc mmmdccc mmmcm
+ }
+
+ # Names of the months
+
+ set short {{} Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec}
+ set long {
+ {} January February March April May June July August September
+ October November December
+ }
+
+ # Put out a header describing the tests
+
+ puts $f2 ""
+ puts $f2 "\# Test formatting of Gregorian year, month, day, all formats"
+ puts $f2 "\# Formats tested: %b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y %EY"
+ puts $f2 ""
+
+ # Generate the test cases for the first and last day of every month
+ # from 1896 to 2045
+
+ set n 0
+ foreach { y } [lsort -integer [array names startOfYear]] {
+ set s [expr { $startOfYear($y) + wide(12*3600 + 34*60 + 56) }]
+ set m 0
+ set yd 1
+ foreach hath { 31 28 31 30 31 30 31 31 30 31 30 31 } {
+ incr m
+ if { $m == 2 && ( $y%4 == 0 && $y%100 != 0 || $y%400 == 0 ) } {
+ incr hath
+ }
+
+ set b [lindex $short $m]
+ set B [lindex $long $m]
+ set C [format %02d [expr { $y / 100 }]]
+ set h $b
+ set j [format %03d $yd]
+ set mm [format %02d $m]
+ set N [format %2d $m]
+ set yy [format %02d [expr { $y % 100 }]]
+
+ set J [expr { ( $s / 86400 ) + 2440588 }]
+
+ set dt $y-$mm-01
+ set result ""
+ append result $b " " $B " " \
+ $mm /01/ $y " 12:34:56 " \
+ "die i mensis " [lindex $roman $m] " annoque " \
+ [lindex $romanc [expr { $y / 100 }]] \
+ [lindex $roman [expr { $y % 100 }]] " " \
+ [lindex $roman 12] " h " [lindex $roman 34] " m " \
+ [lindex $roman 56] " s " \
+ $C " " [lindex $romanc [expr { $y / 100 }]] \
+ " 01 i 1 i " \
+ $h " " $j " " $J " " $mm " " [lindex $roman $m] " " $N \
+ " " $mm "/01/" $y \
+ " die i mensis " [lindex $roman $m] " annoque " \
+ [lindex $romanc [expr { $y / 100 }]] \
+ [lindex $roman [expr { $y % 100 }]] \
+ " " $yy " " [lindex $roman [expr { $y % 100 }]] " " $y
+ puts $f2 "test clock-2.[incr n] {conversion of $dt} {"
+ puts $f2 " clock format $s \\"
+ puts $f2 "\t-format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \\"
+ puts $f2 "\t-gmt true -locale en_US_roman"
+ puts $f2 "} {$result}"
+
+ set hm1 [expr { $hath - 1 }]
+ incr s [expr { 86400 * ( $hath - 1 ) }]
+ incr yd $hm1
+
+ set dd [format %02d $hath]
+ set ee [format %2d $hath]
+ set j [format %03d $yd]
+
+ set J [expr { ( $s / 86400 ) + 2440588 }]
+
+ set dt $y-$mm-$dd
+ set result ""
+ append result $b " " $B " " \
+ $mm / $dd / $y " 12:34:56 " \
+ "die " [lindex $roman $hath] " mensis " [lindex $roman $m] \
+ " annoque " \
+ [lindex $romanc [expr { $y / 100 }]] \
+ [lindex $roman [expr { $y % 100 }]] " " \
+ [lindex $roman 12] " h " [lindex $roman 34] " m " \
+ [lindex $roman 56] " s " \
+ $C " " [lindex $romanc [expr { $y / 100 }]] \
+ " " $dd " " [lindex $roman $hath] " " \
+ $ee " " [lindex $roman $hath] " "\
+ $h " " $j " " $J " " $mm " " [lindex $roman $m] " " $N \
+ " " $mm "/" $dd "/" $y \
+ " die " [lindex $roman $hath] " mensis " [lindex $roman $m] \
+ " annoque " \
+ [lindex $romanc [expr { $y / 100 }]] \
+ [lindex $roman [expr { $y % 100 }]] \
+ " " $yy " " [lindex $roman [expr { $y % 100 }]] " " $y
+ puts $f2 "test clock-2.[incr n] {conversion of $dt} {"
+ puts $f2 " clock format $s \\"
+ puts $f2 "\t-format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \\"
+ puts $f2 "\t-gmt true -locale en_US_roman"
+ puts $f2 "} {$result}"
+
+ incr s 86400
+ incr yd
+ }
+ }
+ puts "testcases2: $n test cases"
+}
+
+#----------------------------------------------------------------------
+#
+# testcases3 --
+#
+# Generate test cases for ISO8601 calendar.
+#
+# Parameters:
+# f2 - Channel handle to the output file
+#
+# Results:
+# None
+#
+# Side effects:
+# Makes a test case for the first and last day of weeks 51, 52, and 1
+# plus the first and last day of a year. Does so for each possible
+# weekday on which a Common Year or Leap Year can begin.
+#
+#----------------------------------------------------------------------
+
+proc testcases3 { f2 } {
+
+ listYears startOfYear
+
+ set case 0
+ foreach { y } [lsort -integer [array names startOfYear]] {
+ set secs $startOfYear($y)
+ set ym1 [expr { $y - 1 }]
+ set dow [expr { ( $secs / 86400 + 4 ) % 7}]
+ switch -exact $dow {
+ 0 {
+ # Year starts on a Sunday.
+ # Prior year started on a Friday or Saturday, and was
+ # a 52-week year.
+ # 1 January is ISO week 52 of the prior year. 2 January
+ # begins ISO week 1 of the current year.
+ # 1 January is week 1 according to %U. According to %W,
+ # week 1 begins on 2 January
+ testISO $f2 $ym1 52 1 [expr { $secs - 6*86400 }]
+ testISO $f2 $ym1 52 6 [expr { $secs - 86400 }]
+ testISO $f2 $ym1 52 7 $secs
+ testISO $f2 $y 1 1 [expr { $secs + 86400 }]
+ testISO $f2 $y 1 6 [expr { $secs + 6*86400}]
+ testISO $f2 $y 1 7 [expr { $secs + 7*86400 }]
+ testISO $f2 $y 2 1 [expr { $secs + 8*86400 }]
+ }
+ 1 {
+ # Year starts on a Monday.
+ # Previous year started on a Saturday or Sunday, and was
+ # a 52-week year.
+ # 1 January is ISO week 1 of the current year
+ # According to %U, it's week 0 until 7 January
+ # 1 January is week 1 according to %W
+ testISO $f2 $ym1 52 1 [expr { $secs - 7*86400 }]
+ testISO $f2 $ym1 52 6 [expr {$secs - 2*86400}]
+ testISO $f2 $ym1 52 7 [expr { $secs - 86400 }]
+ testISO $f2 $y 1 1 $secs
+ testISO $f2 $y 1 6 [expr {$secs + 5*86400}]
+ testISO $f2 $y 1 7 [expr { $secs + 6*86400 }]
+ testISO $f2 $y 2 1 [expr { $secs + 7*86400 }]
+ }
+ 2 {
+ # Year starts on a Tuesday.
+ testISO $f2 $ym1 52 1 [expr { $secs - 8*86400 }]
+ testISO $f2 $ym1 52 6 [expr {$secs - 3*86400}]
+ testISO $f2 $ym1 52 7 [expr { $secs - 2*86400 }]
+ testISO $f2 $y 1 1 [expr { $secs - 86400 }]
+ testISO $f2 $y 1 2 $secs
+ testISO $f2 $y 1 6 [expr {$secs + 4*86400}]
+ testISO $f2 $y 1 7 [expr { $secs + 5*86400 }]
+ testISO $f2 $y 2 1 [expr { $secs + 6*86400 }]
+ }
+ 3 {
+ testISO $f2 $ym1 52 1 [expr { $secs - 9*86400 }]
+ testISO $f2 $ym1 52 6 [expr {$secs - 4*86400}]
+ testISO $f2 $ym1 52 7 [expr { $secs - 3*86400 }]
+ testISO $f2 $y 1 1 [expr { $secs - 2*86400 }]
+ testISO $f2 $y 1 3 $secs
+ testISO $f2 $y 1 6 [expr {$secs + 3*86400}]
+ testISO $f2 $y 1 7 [expr { $secs + 4*86400 }]
+ testISO $f2 $y 2 1 [expr { $secs + 5*86400 }]
+ }
+ 4 {
+ testISO $f2 $ym1 52 1 [expr { $secs - 10*86400 }]
+ testISO $f2 $ym1 52 6 [expr {$secs - 5*86400}]
+ testISO $f2 $ym1 52 7 [expr { $secs - 4*86400 }]
+ testISO $f2 $y 1 1 [expr { $secs - 3*86400 }]
+ testISO $f2 $y 1 4 $secs
+ testISO $f2 $y 1 6 [expr {$secs + 2*86400}]
+ testISO $f2 $y 1 7 [expr { $secs + 3*86400 }]
+ testISO $f2 $y 2 1 [expr { $secs + 4*86400 }]
+ }
+ 5 {
+ testISO $f2 $ym1 53 1 [expr { $secs - 4*86400 }]
+ testISO $f2 $ym1 53 5 $secs
+ testISO $f2 $ym1 53 6 [expr {$secs + 86400}]
+ testISO $f2 $ym1 53 7 [expr { $secs + 2*86400 }]
+ testISO $f2 $y 1 1 [expr { $secs + 3*86400 }]
+ testISO $f2 $y 1 6 [expr {$secs + 8*86400}]
+ testISO $f2 $y 1 7 [expr { $secs + 9*86400 }]
+ testISO $f2 $y 2 1 [expr { $secs + 10*86400 }]
+ }
+ 6 {
+ # messy case because previous year may have had 52 or 53 weeks
+ if { $y%4 == 1 } {
+ testISO $f2 $ym1 53 1 [expr { $secs - 5*86400 }]
+ testISO $f2 $ym1 53 6 $secs
+ testISO $f2 $ym1 53 7 [expr { $secs + 86400 }]
+ } else {
+ testISO $f2 $ym1 52 1 [expr { $secs - 5*86400 }]
+ testISO $f2 $ym1 52 6 $secs
+ testISO $f2 $ym1 52 7 [expr { $secs + 86400 }]
+ }
+ testISO $f2 $y 1 1 [expr { $secs + 2*86400 }]
+ testISO $f2 $y 1 6 [expr { $secs + 7*86400 }]
+ testISO $f2 $y 1 7 [expr { $secs + 8*86400 }]
+ testISO $f2 $y 2 1 [expr { $secs + 9*86400 }]
+ }
+ }
+ }
+ puts "testcases3: $case test cases."
+
+}
+
+proc testISO { f2 G V u secs } {
+
+ upvar 1 case case
+
+ set longdays {Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday}
+ set shortdays {Sun Mon Tue Wed Thu Fri Sat Sun}
+
+ puts $f2 "test clock-3.[incr case] {ISO week-based calendar [format %04d-W%02d-%d $G $V $u]} {"
+ puts $f2 " clock format $secs -format {%a %A %g %G %u %U %V %w %W} -gmt true; \# $G-W[format %02d $V]-$u"
+ puts $f2 "} {[lindex $shortdays $u] [lindex $longdays $u]\
+ [format %02d [expr { $G % 100 }]] $G\
+ $u\
+ [clock format $secs -format %U -gmt true]\
+ [format %02d $V] [expr { $u % 7 }]\
+ [clock format $secs -format %W -gmt true]}"
+
+}
+
+#----------------------------------------------------------------------
+#
+# testcases4 --
+#
+# Makes the test cases that test formatting of time of day.
+#
+# Parameters:
+# f2 - Channel handle to the output file
+#
+# Results:
+# None.
+#
+# Side effects:
+# Writes test cases to the output.
+#
+#----------------------------------------------------------------------
+
+proc testcases4 { f2 } {
+
+ puts $f2 {}
+ puts $f2 "\# Test formatting of time of day"
+ puts $f2 "\# Format groups tested: %H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+"
+ puts $f2 {}
+
+ set i 0
+ set fmt "%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+"
+ foreach { h romanH I romanI am } {
+ 0 ? 12 xii AM
+ 1 i 1 i AM
+ 11 xi 11 xi AM
+ 12 xii 12 xii PM
+ 13 xiii 1 i PM
+ 23 xxiii 11 xi PM
+ } {
+ set hh [format %02d $h]
+ set II [format %02d $I]
+ set hs [format %2d $h]
+ set Is [format %2d $I]
+ foreach { m romanM } { 0 ? 1 i 58 lviii 59 lix } {
+ set mm [format %02d $m]
+ foreach { s romanS } { 0 ? 1 i 58 lviii 59 lix } {
+ set ss [format %02d $s]
+ set x [expr { ( $h * 60 + $m ) * 60 + $s }]
+ set result ""
+ append result $hh " " $romanH " " $II " " $romanI " " \
+ $hs " " $romanH " " $Is " " $romanI " " $mm " " $romanM " " \
+ $am " " [string tolower $am] " " \
+ $II ":" $mm ":" $ss " " [string tolower $am] " " \
+ $hh ":" $mm " " \
+ $ss " " $romanS " " \
+ $hh ":" $mm ":" $ss " " \
+ $hh ":" $mm ":" $ss " " \
+ $romanH " h " $romanM " m " $romanS " s " \
+ "Thu Jan 1 " $hh : $mm : $ss " GMT 1970"
+ puts $f2 "test clock-4.[incr i] { format time of day $hh:$mm:$ss } {"
+ puts $f2 " clock format $x \\"
+ puts $f2 " -format [list $fmt] \\"
+ puts $f2 " -locale en_US_roman \\"
+ puts $f2 " -gmt true"
+ puts $f2 "} {$result}"
+ }
+ }
+ }
+
+ puts "testcases4: $i test cases."
+}
+
+#----------------------------------------------------------------------
+#
+# testcases5 --
+#
+# Generates the test cases for Daylight Saving Time
+#
+# Parameters:
+# f2 - Channel handle for the input file
+#
+# Results:
+# None.
+#
+# Side effects:
+# Makes test cases for each known or anticipated time change
+# in Detroit.
+#
+#----------------------------------------------------------------------
+
+proc testcases5 { f2 } {
+ variable TZData
+
+ puts $f2 {}
+ puts $f2 "\# Test formatting of Daylight Saving Time"
+ puts $f2 {}
+
+ set fmt {%H:%M:%S %z %Z}
+
+ set i 0
+ puts $f2 "test clock-5.[incr i] {does Detroit exist} {"
+ puts $f2 " clock format 0 -format {} -timezone :America/Detroit"
+ puts $f2 " concat"
+ puts $f2 "} {}"
+ puts $f2 "test clock-5.[incr i] {does Detroit have a Y2038 problem} detroit {"
+ puts $f2 " if { \[clock format 2158894800 -format %z -timezone :America/Detroit\] ne {-0400} } {"
+ puts $f2 " concat {y2038 problem}"
+ puts $f2 " } else {"
+ puts $f2 " concat {ok}"
+ puts $f2 " }"
+ puts $f2 "} ok"
+
+ foreach row $TZData(:America/Detroit) {
+ foreach { t offset isdst tzname } $row break
+ if { $t > -4000000000000 } {
+ set conds [list detroit]
+ if { $t > wide(0x7fffffff) } {
+ set conds [list detroit y2038]
+ }
+ incr t -1
+ set x [clock format $t -format {%Y-%m-%d %H:%M:%S} \
+ -timezone :America/Detroit]
+ set r [clock format $t -format $fmt \
+ -timezone :America/Detroit]
+ puts $f2 "test clock-5.[incr i] {time zone boundary case $x} [list $conds] {"
+ puts $f2 " clock format $t -format [list $fmt] \\"
+ puts $f2 " -timezone :America/Detroit"
+ puts $f2 "} [list $r]"
+ incr t
+ set x [clock format $t -format {%Y-%m-%d %H:%M:%S} \
+ -timezone :America/Detroit]
+ set r [clock format $t -format $fmt \
+ -timezone :America/Detroit]
+ puts $f2 "test clock-5.[incr i] {time zone boundary case $x} [list $conds] {"
+ puts $f2 " clock format $t -format [list $fmt] \\"
+ puts $f2 " -timezone :America/Detroit"
+ puts $f2 "} [list $r]"
+ incr t
+ set x [clock format $t -format {%Y-%m-%d %H:%M:%S} \
+ -timezone :America/Detroit]
+ set r [clock format $t -format $fmt \
+ -timezone :America/Detroit]
+ puts $f2 "test clock-5.[incr i] {time zone boundary case $x} [list $conds] {"
+ puts $f2 " clock format $t -format [list $fmt] \\"
+ puts $f2 " -timezone :America/Detroit"
+ puts $f2 "} [list $r]"
+ }
+ }
+ puts "testcases5: $i test cases"
+}
+
+#----------------------------------------------------------------------
+#
+# testcases8 --
+#
+# Outputs the 'clock-8.x' test cases.
+#
+# Parameters:
+# f2 -- Channel handle to the output file
+#
+# Results:
+# None.
+#
+# Side effects:
+# Test cases for parsing dates in ccyymmdd format are written to the
+# output file.
+#
+#----------------------------------------------------------------------
+
+proc testcases8 { f2 } {
+
+ # Put out a header describing the tests
+
+ puts $f2 ""
+ puts $f2 "\# Test parsing of ccyymmdd"
+ puts $f2 ""
+
+ set n 0
+ foreach year {1970 1971 2000 2001} {
+ foreach month {01 12} {
+ foreach day {02 31} {
+ set scanned [clock scan $year$month$day -gmt true]
+ foreach ccyy {%C%y %Y} {
+ foreach mm {%b %B %h %m %Om %N} {
+ foreach dd {%d %Od %e %Oe} {
+ set string [clock format $scanned \
+ -format "$ccyy $mm $dd" \
+ -locale en_US_roman \
+ -gmt true]
+ puts $f2 "test clock-8.[incr n] {parse ccyymmdd} {"
+ puts $f2 " [list clock scan $string -format [list $ccyy $mm $dd] -locale en_US_roman -gmt 1]"
+ puts $f2 "} $scanned"
+ }
+ }
+ }
+ foreach fmt {%x %D} {
+ set string [clock format $scanned \
+ -format $fmt \
+ -locale en_US_roman \
+ -gmt true]
+ puts $f2 "test clock-8.[incr n] {parse ccyymmdd} {"
+ puts $f2 " [list clock scan $string -format $fmt -locale en_US_roman -gmt 1]"
+ puts $f2 "} $scanned"
+ }
+ }
+ }
+ }
+
+ puts "testcases8: $n test cases"
+}
+
+#----------------------------------------------------------------------
+#
+# testcases11 --
+#
+# Outputs the 'clock-11.x' test cases.
+#
+# Parameters:
+# f2 -- Channel handle to the output file
+#
+# Results:
+# None.
+#
+# Side effects:
+# Test cases for precedence among YYYYMMDD and YYYYDDD are written
+# to f2.
+#
+#----------------------------------------------------------------------
+
+proc testcases11 { f2 } {
+
+ # Put out a header describing the tests
+
+ puts $f2 ""
+ puts $f2 "\# Test precedence among yyyymmdd and yyyyddd"
+ puts $f2 ""
+
+ array set v {
+ Y 1970
+ m 01
+ d 01
+ j 002
+ }
+
+ set n 0
+
+ foreach {a b c d} {
+ Y m d j m Y d j d Y m j j Y m d
+ Y m j d m Y j d d Y j m j Y d m
+ Y d m j m d Y j d m Y j j m Y d
+ Y d j m m d j Y d m j Y j m d Y
+ Y j m d m j Y d d j Y m j d Y m
+ Y j d m m j d Y d j m Y j d m Y
+ } {
+ foreach x [list $a $b $c $d] {
+ switch -exact -- $x {
+ m - d {
+ set value 0
+ }
+ j {
+ set value 86400
+ }
+ }
+ }
+ set format "%$a%$b%$c%$d"
+ set string "$v($a)$v($b)$v($c)$v($d)"
+ puts $f2 "test clock-11.[incr n] {precedence of ccyyddd and ccyymmdd} {"
+ puts $f2 " [list clock scan $string -format $format -gmt 1]"
+ puts $f2 "} $value"
+ }
+
+ puts "testcases11: $n test cases"
+}
+
+#----------------------------------------------------------------------
+#
+# testcases12 --
+#
+# Outputs the 'clock-12.x' test cases, parsing CCyyWwwd
+#
+# Parameters:
+# f2 -- Channel handle to the output file
+#
+# Results:
+# None.
+#
+# Side effects:
+# Test cases for parsing dates in Gregorian calendar are written to the
+# output file.
+#
+#----------------------------------------------------------------------
+
+proc testcases12 { f2 } {
+
+ # Put out a header describing the tests
+
+ puts $f2 ""
+ puts $f2 "\# Test parsing of ccyyWwwd"
+ puts $f2 ""
+
+ set n 0
+ foreach year {1970 1971 2000 2001} {
+ foreach month {01 12} {
+ foreach day {02 31} {
+ set scanned [clock scan $year$month$day -gmt true]
+ foreach d {%a %A %u %w %Ou %Ow} {
+ set string [clock format $scanned \
+ -format "%G W%V $d" \
+ -locale en_US_roman \
+ -gmt true]
+ puts $f2 "test clock-12.[incr n] {parse ccyyWwwd} {"
+ puts $f2 " [list clock scan $string -format [list %G W%V $d] -locale en_US_roman -gmt 1]"
+ puts $f2 "} $scanned"
+ }
+ }
+ }
+ }
+
+ puts "testcases12: $n test cases"
+}
+
+#----------------------------------------------------------------------
+#
+# testcases14 --
+#
+# Outputs the 'clock-14.x' test cases.
+#
+# Parameters:
+# f2 -- Channel handle to the output file
+#
+# Results:
+# None.
+#
+# Side effects:
+# Test cases for parsing yymmdd dates are output.
+#
+#----------------------------------------------------------------------
+
+proc testcases14 { f2 } {
+
+ # Put out a header describing the tests
+
+ puts $f2 ""
+ puts $f2 "\# Test parsing of yymmdd"
+ puts $f2 ""
+
+ set n 0
+ foreach year {1938 1970 2000 2037} {
+ foreach month {01 12} {
+ foreach day {02 31} {
+ set scanned [clock scan $year$month$day -gmt true]
+ foreach yy {%y %Oy} {
+ foreach mm {%b %B %h %m %Om %N} {
+ foreach dd {%d %Od %e %Oe} {
+ set string [clock format $scanned \
+ -format "$yy $mm $dd" \
+ -locale en_US_roman \
+ -gmt true]
+ puts $f2 "test clock-14.[incr n] {parse yymmdd} {"
+ puts $f2 " [list clock scan $string -format [list $yy $mm $dd] -locale en_US_roman -gmt 1]"
+ puts $f2 "} $scanned"
+ }
+ }
+ }
+ }
+ }
+ }
+
+ puts "testcases14: $n test cases"
+}
+
+#----------------------------------------------------------------------
+#
+# testcases17 --
+#
+# Outputs the 'clock-17.x' test cases, parsing yyWwwd
+#
+# Parameters:
+# f2 -- Channel handle to the output file
+#
+# Results:
+# None.
+#
+# Side effects:
+# Test cases for parsing dates in Gregorian calendar are written to the
+# output file.
+#
+#----------------------------------------------------------------------
+
+proc testcases17 { f2 } {
+
+ # Put out a header describing the tests
+
+ puts $f2 ""
+ puts $f2 "\# Test parsing of yyWwwd"
+ puts $f2 ""
+
+ set n 0
+ foreach year {1970 1971 2000 2001} {
+ foreach month {01 12} {
+ foreach day {02 31} {
+ set scanned [clock scan $year$month$day -gmt true]
+ foreach d {%a %A %u %w %Ou %Ow} {
+ set string [clock format $scanned \
+ -format "%g W%V $d" \
+ -locale en_US_roman \
+ -gmt true]
+ puts $f2 "test clock-17.[incr n] {parse yyWwwd} {"
+ puts $f2 " [list clock scan $string -format [list %g W%V $d] -locale en_US_roman -gmt 1]"
+ puts $f2 "} $scanned"
+ }
+ }
+ }
+ }
+
+ puts "testcases17: $n test cases"
+}
+
+#----------------------------------------------------------------------
+#
+# testcases19 --
+#
+# Outputs the 'clock-19.x' test cases.
+#
+# Parameters:
+# f2 -- Channel handle to the output file
+#
+# Results:
+# None.
+#
+# Side effects:
+# Test cases for parsing mmdd dates are output.
+#
+#----------------------------------------------------------------------
+
+proc testcases19 { f2 } {
+
+ # Put out a header describing the tests
+
+ puts $f2 ""
+ puts $f2 "\# Test parsing of mmdd"
+ puts $f2 ""
+
+ set n 0
+ foreach year {1938 1970 2000 2037} {
+ set base [clock scan ${year}0101 -gmt true]
+ foreach month {01 12} {
+ foreach day {02 31} {
+ set scanned [clock scan $year$month$day -gmt true]
+ foreach mm {%b %B %h %m %Om %N} {
+ foreach dd {%d %Od %e %Oe} {
+ set string [clock format $scanned \
+ -format "$mm $dd" \
+ -locale en_US_roman \
+ -gmt true]
+ puts $f2 "test clock-19.[incr n] {parse mmdd} {"
+ puts $f2 " [list clock scan $string -format [list $mm $dd] -locale en_US_roman -base $base -gmt 1]"
+ puts $f2 "} $scanned"
+ }
+ }
+ }
+ }
+ }
+
+ puts "testcases19: $n test cases"
+}
+
+#----------------------------------------------------------------------
+#
+# testcases21 --
+#
+# Outputs the 'clock-21.x' test cases, parsing Wwwd
+#
+# Parameters:
+# f2 -- Channel handle to the output file
+#
+# Results:
+# None.
+#
+# Side effects:
+# Test cases for parsing dates in Gregorian calendar are written to the
+# output file.
+#
+#----------------------------------------------------------------------
+
+proc testcases22 { f2 } {
+
+ # Put out a header describing the tests
+
+ puts $f2 ""
+ puts $f2 "\# Test parsing of Wwwd"
+ puts $f2 ""
+
+ set n 0
+ foreach year {1970 1971 2000 2001} {
+ set base [clock scan ${year}0104 -gmt true]
+ foreach month {03 10} {
+ foreach day {01 31} {
+ set scanned [clock scan $year$month$day -gmt true]
+ foreach d {%a %A %u %w %Ou %Ow} {
+ set string [clock format $scanned \
+ -format "W%V $d" \
+ -locale en_US_roman \
+ -gmt true]
+ puts $f2 "test clock-22.[incr n] {parse Wwwd} {"
+ puts $f2 " [list clock scan $string -format [list W%V $d] -locale en_US_roman -gmt 1] -base $base"
+ puts $f2 "} $scanned"
+ }
+ }
+ }
+ }
+
+ puts "testcases22: $n test cases"
+}
+
+#----------------------------------------------------------------------
+#
+# testcases24 --
+#
+# Outputs the 'clock-24.x' test cases.
+#
+# Parameters:
+# f2 -- Channel handle to the output file
+#
+# Results:
+# None.
+#
+# Side effects:
+# Test cases for parsing naked day of the month are output.
+#
+#----------------------------------------------------------------------
+
+proc testcases24 { f2 } {
+
+ # Put out a header describing the tests
+
+ puts $f2 ""
+ puts $f2 "\# Test parsing of naked day-of-month"
+ puts $f2 ""
+
+ set n 0
+ foreach year {1970 2000} {
+ foreach month {01 12} {
+ set base [clock scan ${year}${month}01 -gmt true]
+ foreach day {02 28} {
+ set scanned [clock scan $year$month$day -gmt true]
+ foreach dd {%d %Od %e %Oe} {
+ set string [clock format $scanned \
+ -format "$dd" \
+ -locale en_US_roman \
+ -gmt true]
+ puts $f2 "test clock-24.[incr n] {parse naked day of month} {"
+ puts $f2 " [list clock scan $string -format $dd -locale en_US_roman -base $base -gmt 1]"
+ puts $f2 "} $scanned"
+ }
+ }
+ }
+ }
+
+ puts "testcases24: $n test cases"
+}
+
+#----------------------------------------------------------------------
+#
+# testcases26 --
+#
+# Outputs the 'clock-26.x' test cases, parsing naked day of week
+#
+# Parameters:
+# f2 -- Channel handle to the output file
+#
+# Results:
+# None.
+#
+# Side effects:
+# Test cases for parsing dates in Gregorian calendar are written to the
+# output file.
+#
+#----------------------------------------------------------------------
+
+proc testcases26 { f2 } {
+
+ # Put out a header describing the tests
+
+ puts $f2 ""
+ puts $f2 "\# Test parsing of naked day of week"
+ puts $f2 ""
+
+ set n 0
+ foreach year {1970 2001} {
+ foreach week {01 52} {
+ set base [clock scan ${year}W${week}4 \
+ -format %GW%V%u -gmt true]
+ foreach day {1 7} {
+ set scanned [clock scan ${year}W${week}${day} \
+ -format %GW%V%u -gmt true]
+ foreach d {%a %A %u %w %Ou %Ow} {
+ set string [clock format $scanned \
+ -format "$d" \
+ -locale en_US_roman \
+ -gmt true]
+ puts $f2 "test clock-26.[incr n] {parse naked day of week} {"
+ puts $f2 " [list clock scan $string -format $d -locale en_US_roman -gmt 1] -base $base"
+ puts $f2 "} $scanned"
+ }
+ }
+ }
+ }
+
+ puts "testcases26: $n test cases"
+}
+
+#----------------------------------------------------------------------
+#
+# testcases29 --
+#
+# Makes test cases for parsing of time of day.
+#
+# Parameters:
+# f2 -- Channel where tests are to be written
+#
+# Results:
+# None.
+#
+# Side effects:
+# Writes the tests.
+#
+#----------------------------------------------------------------------
+
+proc testcases29 { f2 } {
+
+ # Put out a header describing the tests
+
+ puts $f2 ""
+ puts $f2 "\# Test parsing of time of day"
+ puts $f2 ""
+
+ set n 0
+ foreach hour {0 1 11 12 13 23} \
+ hampm {12 1 11 12 1 11} \
+ lhour {? i xi xii xiii xxiii} \
+ lhampm {xii i xi xii i xi} \
+ ampmind {am am am pm pm pm} {
+ set sphr [format %2d $hour]
+ set 2dhr [format %02d $hour]
+ set sphampm [format %2d $hampm]
+ set 2dhampm [format %02d $hampm]
+ set AMPMind [string toupper $ampmind]
+ foreach minute {00 01 59} lminute {? i lix} {
+ foreach second {00 01 59} lsecond {? i lix} {
+ set time [expr { ( 60 * $hour + $minute ) * 60 + $second }]
+ foreach {hfmt afmt} [list \
+ %H {} %k {} %OH {} %Ok {} \
+ %I %p %l %p \
+ %OI %p %Ol %p \
+ %I %P %l %P \
+ %OI %P %Ol %P] \
+ {hfld afld} [list \
+ $2dhr {} $sphr {} $lhour {} $lhour {} \
+ $2dhampm $AMPMind $sphampm $AMPMind \
+ $lhampm $AMPMind $lhampm $AMPMind \
+ $2dhampm $ampmind $sphampm $ampmind \
+ $lhampm $ampmind $lhampm $ampmind] \
+ {
+ if { $second eq "00" } {
+ if { $minute eq "00" } {
+ puts $f2 "test clock-29.[incr n] {time parsing} {"
+ puts $f2 " clock scan {2440588 $hfld $afld} \\"
+ puts $f2 " -gmt true -locale en_US_roman \\"
+ puts $f2 " -format {%J $hfmt $afmt}"
+ puts $f2 "} $time"
+ }
+ puts $f2 "test clock-29.[incr n] {time parsing} {"
+ puts $f2 " clock scan {2440588 $hfld:$minute $afld} \\"
+ puts $f2 " -gmt true -locale en_US_roman \\"
+ puts $f2 " -format {%J $hfmt:%M $afmt}"
+ puts $f2 "} $time"
+ puts $f2 "test clock-29.[incr n] {time parsing} {"
+ puts $f2 " clock scan {2440588 $hfld:$lminute $afld} \\"
+ puts $f2 " -gmt true -locale en_US_roman \\"
+ puts $f2 " -format {%J $hfmt:%OM $afmt}"
+ puts $f2 "} $time"
+ }
+ puts $f2 "test clock-29.[incr n] {time parsing} {"
+ puts $f2 " clock scan {2440588 $hfld:$minute:$second $afld} \\"
+ puts $f2 " -gmt true -locale en_US_roman \\"
+ puts $f2 " -format {%J $hfmt:%M:%S $afmt}"
+ puts $f2 "} $time"
+ puts $f2 "test clock-29.[incr n] {time parsing} {"
+ puts $f2 " clock scan {2440588 $hfld:$lminute:$lsecond $afld} \\"
+ puts $f2 " -gmt true -locale en_US_roman \\"
+ puts $f2 " -format {%J $hfmt:%OM:%OS $afmt}"
+ puts $f2 "} $time"
+ }
+ }
+ }
+
+ }
+ puts "testcases29: $n test cases"
+}
+
+processFile $d
diff --git a/tools/man2help.tcl b/tools/man2help.tcl
index 6c8356c..018fa84 100644
--- a/tools/man2help.tcl
+++ b/tools/man2help.tcl
@@ -10,7 +10,8 @@
# PASS 1
#
-set man2tclprog [file join [file dirname [info script]] man2tcl.exe]
+set man2tclprog [file join [file dirname [info script]] \
+ man2tcl[file extension [info nameofexecutable]]]
proc generateContents {basename version files} {
global curID topics
@@ -26,10 +27,10 @@ proc generateContents {basename version files} {
foreach package [getPackages] {
foreach section [getSections $package] {
if {![info exists lastSection]} {
- set lastSection {}
+ set lastSection {}
}
if {[string compare $lastSection $section]} {
- puts $fd "1 $section"
+ puts $fd "1 $section"
}
set lastSection $section
set lastTopic {}
diff --git a/tools/man2help2.tcl b/tools/man2help2.tcl
index d5c0b93..75f4249 100644
--- a/tools/man2help2.tcl
+++ b/tools/man2help2.tcl
@@ -157,6 +157,7 @@ proc text {string} {
"\t" {\tab } \
'' "\\rdblquote " \
`` "\\ldblquote " \
+ "\u00b7" "\\bullet " \
] $string]
# Check if this is the beginning of an international character string.
@@ -375,6 +376,9 @@ proc macro {name args} {
SH {
SHmacro $args
}
+ SS {
+ SHmacro $args subsection
+ }
SO {
SHmacro "STANDARD OPTIONS"
set state(nestingLevel) 0
@@ -418,6 +422,21 @@ proc macro {name args} {
}
VE {}
VS {}
+ QW {
+ formattedText "``[lindex $args 0]''[lindex $args 1] "
+ }
+ MT {
+ text "``'' "
+ }
+ PQ {
+ formattedText \
+ "(``[lindex $args 0]''[lindex $args 1])[lindex $args 2] "
+ }
+ QR {
+ formattedText "``[lindex $args 0]"
+ dash
+ formattedText "[lindex $args 1]''[lindex $args 2] "
+ }
default {
puts stderr "Unknown macro: .$name [join $args " "]"
}
@@ -509,13 +528,12 @@ proc formattedText {text} {
dash
set text [string range $text [expr {$index+2}] end]
}
- | {
+ & - | {
set text [string range $text [expr {$index+2}] end]
}
- o {
- text "\\'"
- regexp {'([^']*)'(.*)} $text all ch text
- text $chars($ch)
+ ( {
+ char [string range $text $index [expr {$index+3}]]
+ set text [string range $text [expr {$index+4}] end]
}
default {
puts stderr "Unknown sequence: \\$c"
@@ -564,22 +582,32 @@ proc tab {} {
# This procedure handles the ".ta" macro, which sets tab stops.
#
# Arguments:
-# tabList - List of tab stops, each consisting of a number
-# followed by "i" (inch) or "c" (cm).
+# tabList - List of tab stops in *roff format
proc setTabs {tabList} {
global file state
set state(tabs) {}
foreach arg $tabList {
- set distance [expr {$state(leftMargin) \
- + ($state(offset) * $state(nestingLevel)) + [getTwips $arg]}]
- lappend state(tabs) [expr {round($distance)}]
+ if {[string match +* $arg]} {
+ set relativeTo [lindex $state(tabs) end]
+ set arg [string range $arg 1 end]
+ } else {
+ # Local left margin
+ set relativeTo [expr {$state(leftMargin) \
+ + ($state(offset) * $state(nestingLevel))}]
+ }
+ if {[regexp {^\\w'([^']*)'u$} $arg -> submatch]} {
+ # Magic factor!
+ set distance [expr {[string length $submatch] * 86.4}]
+ } else {
+ set distance [getTwips $arg]
+ }
+ lappend state(tabs) [expr {round($distance + $relativeTo)}]
}
}
-
# lineBreak --
#
# Generates a line break in the HTML output.
@@ -648,31 +676,50 @@ proc char {name} {
global file state
switch -exact $name {
- \\o {
+ {\o} {
set state(intl) 1
}
- \\\ {
+ {\ } {
textSetup
puts -nonewline $file " "
}
- \\0 {
+ {\0} {
textSetup
puts -nonewline $file " \\emspace "
}
- \\\\ {
+ {\\} - {\e} {
textSetup
puts -nonewline $file "\\\\"
}
- \\(+- {
+ {\(+-} {
textSetup
puts -nonewline $file "\\'b1 "
}
- \\% -
- \\| {
+ {\%} - {\|} {
+ }
+ {\(->} {
+ textSetup
+ puts -nonewline $file "->"
+ }
+ {\(bu} {
+ textSetup
+ puts -nonewline $file "\\bullet "
+ }
+ {\(co} {
+ textSetup
+ puts -nonewline $file "\\'a9 "
+ }
+ {\(mu} {
+ textSetup
+ puts -nonewline $file "\\'d7 "
}
- \\(bu {
+ {\(em} {
textSetup
- puts -nonewline $file "·"
+ puts -nonewline $file "-"
+ }
+ {\(fm} {
+ textSetup
+ puts -nonewline $file "\\'27 "
}
default {
puts stderr "Unknown character: $name"
@@ -699,12 +746,12 @@ proc macro2 {name args} {
# SHmacro --
#
-# Subsection head; handles the .SH macro.
+# Subsection head; handles the .SH and .SS macros.
#
# Arguments:
# name - Section name.
-proc SHmacro {argList} {
+proc SHmacro {argList {style section}} {
global file state
set args [join $argList " "]
@@ -729,26 +776,28 @@ proc SHmacro {argList} {
set state(breakPending) 0
}
set state(noFill) 0
- nextPara 0i
+ if {[string compare "subsection" $style] == 0} {
+ nextPara .25i
+ } else {
+ nextPara 0i
+ }
font B
text $args
font R
nextPara .5i
}
-
-
# IPmacro --
#
# This procedure is invoked to handle ".IP" macros, which may take any
# of the following forms:
#
-# .IP [1] Translate to a "1Step" state(paragraph).
+# .IP [1] Translate to a "1Step" state(paragraph).
# .IP [x] (x > 1) Translate to a "Step" state(paragraph).
-# .IP Translate to a "Bullet" state(paragraph).
+# .IP Translate to a "Bullet" state(paragraph).
# .IP text count Translate to a FirstBody state(paragraph) with special
-# indent and tab stop based on "count", and tab after
-# "text".
+# indent and tab stop based on "count", and tab after
+# "text".
#
# Arguments:
# argList - List of arguments to the .IP macro.
@@ -759,31 +808,28 @@ proc IPmacro {argList} {
global file state
set length [llength $argList]
- if {$length == 0} {
- newPara 0.5i
- return
+ foreach {text indent} $argList break
+ if {$length > 2} {
+ puts stderr "Bad .IP macro: .IP [join $argList " "]"
}
- if {$length == 1} {
- newPara 0.5i -0.5i
- set state(sb) 80
- setTabs 0.5i
- formattedText [lindex $argList 0]
- tab
- return
+
+ if {$length == 0} {
+ set text {\(bu}
+ set indent 5
+ } elseif {$length == 1} {
+ set indent 5
}
- if {$length == 2} {
- set count [lindex $argList 1]
- set tab [expr $count * 0.1]i
- newPara $tab -$tab
- set state(sb) 80
- setTabs $tab
- formattedText [lindex $argList 0]
- tab
- return
+ if {$text == {\(bu}} {
+ set text "\u00b7"
}
- puts stderr "Bad .IP macro: .IP [join $argList " "]"
-}
+ set tab [expr $indent * 0.1]i
+ newPara $tab -$tab
+ set state(sb) 80
+ setTabs $tab
+ formattedText $text
+ tab
+}
# TPmacro --
#
@@ -927,6 +973,10 @@ proc getTwips {arg} {
puts stderr "bad distance \"$arg\""
return 0
}
+ if {[string length $units] > 1} {
+ puts stderr "additional characters after unit \"$arg\""
+ set units [string index $units 0]
+ }
switch -- $units {
c {
set distance [expr {$distance * 567}]
@@ -936,7 +986,7 @@ proc getTwips {arg} {
}
default {
puts stderr "bad units in distance \"$arg\""
- continue
+ return 0
}
}
return $distance
@@ -977,4 +1027,3 @@ proc decrNestingLevel {} {
incr state(nestingLevel) -1
}
}
-
diff --git a/tools/man2html.tcl b/tools/man2html.tcl
index 2d14047..fa57b03 100644
--- a/tools/man2html.tcl
+++ b/tools/man2html.tcl
@@ -1,6 +1,8 @@
-#!/proj/tcl/install/5.x-sparc/bin/tclsh7.5
+#!/bin/sh
+# \
+exec tclsh "$0" ${1+"$@"}
-if [catch {
+package require Tcl 8.4
# man2html.tcl --
#
@@ -9,7 +11,6 @@ if [catch {
#
# Copyright (c) 1996 by Sun Microsystems, Inc.
-set homeDir /home/rjohnson/Projects/tools/generic
# sarray -
#
@@ -23,7 +24,7 @@ proc sarray {file args} {
set file [open $file w]
foreach a $args {
upvar $a array
- if ![array exists array] {
+ if {![array exists array]} {
puts "sarray: \"$a\" isn't an array"
break
}
@@ -37,13 +38,12 @@ proc sarray {file args} {
}
-
# footer --
#
# Builds footer info for HTML pages
#
# Arguments:
-# None
+# packages - List of packages to link to.
proc footer {packages} {
lappend f "<HR>"
@@ -61,8 +61,6 @@ proc footer {packages} {
}
-
-
# doDir --
#
# Given a directory as argument, translate all the man pages in
@@ -78,101 +76,112 @@ proc doDir dir {
}
-if {$argc < 2} {
- puts stderr "usage: $argv0 html_dir tcl_dir packages..."
- puts stderr "usage: $argv0 -clean html_dir"
- exit 1
-}
-
-if {[lindex $argv 0] == "-clean"} {
- set html_dir [lindex $argv 1]
- puts -nonewline "recursively remove: $html_dir? "
- flush stdout
- if {[gets stdin] == "y"} {
- puts "removing: $html_dir"
- exec rm -r $html_dir
- }
- exit 0
-}
-
-set html_dir [lindex $argv 0]
-set tcl_dir [lindex $argv 1]
-set packages [lrange $argv 2 end]
-
-#### need to add glob capability to packages ####
+# main --
+#
+# Main code for converting Tcl manual pages to HTML.
+#
+# Arguments:
+# argv - List of arguments to this script.
-# make sure there are doc directories for each package
+proc main {argv} {
+ global html_dir
+ # Global vars used in man2html1.tcl and man2html2.tcl
+ global NAME_file KEY_file lib state curFile file inDT textState nestStk
+ global curFont fontStart fontEnd noFillCount footer
-foreach i $packages {
- if ![file exists $tcl_dir/$i/doc] {
- puts stderr "Error: doc directory for package $i is missing"
+ if {[llength $argv] < 2} {
+ puts stderr "usage: $::argv0 html_dir tcl_dir packages..."
+ puts stderr "usage: $::argv0 -clean html_dir"
exit 1
}
- if ![file isdirectory $tcl_dir/$i/doc] {
- puts stderr "Error: $tcl_dir/$i/doc is not a directory"
- exit 1
+
+ if {[lindex $argv 0] eq "-clean"} {
+ set html_dir [lindex $argv 1]
+ puts -nonewline "recursively remove: $html_dir? "
+ flush stdout
+ if {[gets stdin] eq "y"} {
+ puts "removing: $html_dir"
+ file delete -force $html_dir
+ }
+ exit 0
}
-}
+ set html_dir [lindex $argv 0]
+ set tcl_dir [lindex $argv 1]
+ set packages [lrange $argv 2 end]
+ set homeDir [file dirname [info script]]
-# we want to start with a clean sheet
+ #### need to add glob capability to packages ####
-if [file exists $html_dir] {
- puts stderr "Error: HTML directory already exists"
- exit 1
-} else {
- exec mkdir $html_dir
-}
+ # make sure there are doc directories for each package
+
+ foreach i $packages {
+ if {![file exists $tcl_dir/$i/doc]} {
+ puts stderr "Error: doc directory for package $i is missing"
+ exit 1
+ }
+ if {![file isdirectory $tcl_dir/$i/doc]} {
+ puts stderr "Error: $tcl_dir/$i/doc is not a directory"
+ exit 1
+ }
+ }
+
+ # we want to start with a clean sheet
-set footer [footer $packages]
+ if {[file exists $html_dir]} {
+ puts stderr "Error: HTML directory already exists"
+ exit 1
+ } else {
+ file mkdir $html_dir
+ }
+ set footer [footer $packages]
-# make the hyperlink arrays and contents.html for all packages
-
-foreach package $packages {
- global homeDir
- exec mkdir $html_dir/$package
+ # make the hyperlink arrays and contents.html for all packages
+
+ foreach package $packages {
+ file mkdir $html_dir/$package
- # build hyperlink database arrays: NAME_file and KEY_file
- #
- puts "\nScanning man pages in $tcl_dir/$package/doc..."
- source $homeDir/man2html1.tcl
+ # build hyperlink database arrays: NAME_file and KEY_file
+ #
+ puts "\nScanning man pages in $tcl_dir/$package/doc..."
+ uplevel \#0 [list source $homeDir/man2html1.tcl]
- doDir $tcl_dir/$package/doc
-
- # clean up the NAME_file and KEY_file database arrays
- #
- catch {unset KEY_file()}
- foreach name [lsort [array names NAME_file]] {
- set file_name $NAME_file($name)
- if {[llength $file_name] > 1} {
- set file_name [lsort $file_name]
- puts stdout "Warning: '$name' multiply defined in: $file_name; using last"
- set NAME_file($name) [lindex $file_name end]
+ doDir $tcl_dir/$package/doc
+
+ # clean up the NAME_file and KEY_file database arrays
+ #
+ catch {unset KEY_file()}
+ foreach name [lsort [array names NAME_file]] {
+ set file_name $NAME_file($name)
+ if {[llength $file_name] > 1} {
+ set file_name [lsort $file_name]
+ puts "Warning: '$name' multiply defined in: $file_name;\
+ using last"
+ set NAME_file($name) [lindex $file_name end]
+ }
}
- }
-# sarray $html_dir/$package/xref.tcl NAME_file KEY_file
+ # sarray $html_dir/$package/xref.tcl NAME_file KEY_file
- # build the contents file from NAME_file
- #
- puts "\nGenerating contents.html for $package"
- doContents $html_dir/$package/contents.html $lib ;# defined in man2html1.tcl
+ # build the contents file from NAME_file
+ #
+ puts "\nGenerating contents.html for $package"
+ doContents $html_dir/$package/contents.html $lib ;# defined in man2html1.tcl
- # now translate the man pages to HTML pages
- #
- source $homeDir/man2html2.tcl
- puts "\nBuilding html pages from man pages in $tcl_dir/$package/doc..."
- doDir $tcl_dir/$package/doc
+ # now translate the man pages to HTML pages
+ #
+ uplevel \#0 [list source $homeDir/man2html2.tcl]
+ puts "\nBuilding html pages from man pages in $tcl_dir/$package/doc..."
+ doDir $tcl_dir/$package/doc
- unset NAME_file
+ unset NAME_file
+ }
}
-
-} result] {
+if [catch { main $argv } result] {
global errorInfo
puts stderr $result
puts stderr "in"
puts stderr $errorInfo
}
-
diff --git a/tools/man2html1.tcl b/tools/man2html1.tcl
index be969f9..f2b2e43 100644
--- a/tools/man2html1.tcl
+++ b/tools/man2html1.tcl
@@ -5,6 +5,8 @@
#
# Copyright (c) 1996 by Sun Microsystems, Inc.
+package require Tcl 8.4
+
# Global variables used by these scripts:
#
# state - state variable that controls action of text proc.
@@ -24,7 +26,6 @@
# inDT - in dictionary term.
-
# text --
#
# This procedure adds entries to the hypertext arrays NAME_file
@@ -36,7 +37,6 @@
# Arguments:
# string - Text to index.
-
proc text string {
global state curFile NAME_file KEY_file inDT
@@ -72,12 +72,12 @@ proc text string {
proc macro {name args} {
switch $name {
- SH {
+ SH - SS {
global state
switch $args {
NAME {
- if {$state == "INIT" } {
+ if {$state eq "INIT"} {
set state NAME
}
}
@@ -97,8 +97,8 @@ proc macro {name args} {
set inDT 0
set state INIT
if {[llength $args] != 5} {
- set args [join $args " "]
- puts stderr "Bad .TH macro: .$name $args"
+ set args [join $args " "]
+ puts stderr "Bad .TH macro: .$name $args"
}
set lib [lindex $args 3] ;# Tcl or Tk
}
@@ -106,7 +106,6 @@ proc macro {name args} {
}
-
# dash --
#
# This procedure is invoked to handle dash characters ("\-" in
@@ -117,13 +116,12 @@ proc macro {name args} {
proc dash {} {
global state
- if {$state == "NAME"} {
+ if {$state eq "NAME"} {
set state DASH
}
}
-
# newline --
#
# This procedure is invoked to handle newlines in the troff input.
@@ -138,8 +136,6 @@ proc newline {} {
}
-
-
# initGlobals, tab, font, char, macro2 --
#
# These procedures do nothing during the first pass.
@@ -181,14 +177,14 @@ proc doListing {file pattern} {
return
}
incr max_len
- set ncols [expr 90/$max_len]
- set nrows [expr int( ceil( [llength $type] / $ncols. ) ) ]
+ set ncols [expr {90/$max_len}]
+ set nrows [expr {int(ceil([llength $type] / double($ncols)))} ]
# ? max_len ncols nrows
set index 0
foreach f $type {
- lappend row([expr $index % $nrows]) $f
+ lappend row([expr {$index % $nrows}]) $f
incr index
}
@@ -212,8 +208,9 @@ proc doListing {file pattern} {
#
# Arguments:
# file - name of the contents file.
-# packageName - string used in the title and sub-heads of the HTML page. Normally
-# name of the package without version numbers.
+# packageName - string used in the title and sub-heads of the HTML
+# page. Normally name of the package without version
+# numbers.
proc doContents {file packageName} {
global footer
@@ -236,8 +233,6 @@ proc doContents {file packageName} {
}
-
-
# do --
#
# This is the toplevel procedure that searches a man page
@@ -263,4 +258,3 @@ proc do fileName {
exit 1
}
}
-
diff --git a/tools/man2html2.tcl b/tools/man2html2.tcl
index aee1da3..163196e 100644
--- a/tools/man2html2.tcl
+++ b/tools/man2html2.tcl
@@ -1,26 +1,28 @@
+##############################################################################
# man2html2.tcl --
#
-# This file defines procedures that are used during the second pass of the
-# man page to html conversion process. It is sourced by man2html.tcl.
+# This file defines procedures that are used during the second pass of the man
+# page to html conversion process. It is sourced by man2html.tcl.
#
# Copyright (c) 1996 by Sun Microsystems, Inc.
+package require Tcl 8.4
+
# Global variables used by these scripts:
#
-# NAME_file - array indexed by NAME and containing file names used
-# for hyperlinks.
+# NAME_file - array indexed by NAME and containing file names used for
+# hyperlinks.
#
# textState - state variable defining action of 'text' proc.
#
-# nestStk - stack oriented list containing currently active
-# HTML tags (UL, OL, DL). Local to 'nest' proc.
+# nestStk - stack oriented list containing currently active HTML tags (UL,
+# OL, DL). Local to 'nest' proc.
#
-# inDT - set by 'TPmacro', cleared by 'newline'. Used to insert
-# the <DT> tag while in a dictionary list <DL>.
+# inDT - set by 'TPmacro', cleared by 'newline'. Used to insert the
+# tag while in a dictionary list <DL>.
#
-# curFont - Name of special font that is currently in
-# use. Null means the default paragraph font
-# is being used.
+# curFont - Name of special font that is currently in use. Null means the
+# default paragraph font is being used.
#
# file - Where to output the generated HTML.
#
@@ -28,28 +30,29 @@
#
# fontEnd - Array to map font names to ending sequences.
#
-# noFillCount - Non-zero means don't fill the next $noFillCount
-# lines: force a line break at each newline. Zero
-# means filling is enabled, so don't output line
-# breaks for each newline.
+# noFillCount - Non-zero means don't fill the next $noFillCount lines: force a
+# line break at each newline. Zero means filling is enabled, so
+# don't output line breaks for each newline.
#
-# footer - info inserted at bottom of each page. Normally read
-# from the xref.tcl file
-
+# footer - info inserted at bottom of each page. Normally read from the
+# xref.tcl file
+
+##############################################################################
# initGlobals --
#
-# This procedure is invoked to set the initial values of all of the
-# global variables, before processing a man page.
+# This procedure is invoked to set the initial values of all of the global
+# variables, before processing a man page.
#
# Arguments:
# None.
proc initGlobals {} {
global file noFillCount textState
- global fontStart fontEnd curFont inPRE charCnt
+ global fontStart fontEnd curFont inPRE charCnt inTable
nest init
set inPRE 0
+ set inTable 0
set textState 0
set curFont ""
set fontStart(Code) "<B>"
@@ -60,12 +63,12 @@ proc initGlobals {} {
set charCnt 0
setTabs 0.5i
}
-
-
+
+##############################################################################
# beginFont --
#
-# Arranges for future text to use a special font, rather than
-# the default paragraph font.
+# Arranges for future text to use a special font, rather than the default
+# paragraph font.
#
# Arguments:
# font - Name of new font to use.
@@ -73,7 +76,7 @@ proc initGlobals {} {
proc beginFont font {
global curFont file fontStart
- if {$curFont == $font} {
+ if {$curFont eq $font} {
return
}
endFont
@@ -81,7 +84,7 @@ proc beginFont font {
set curFont $font
}
-
+##############################################################################
# endFont --
#
# Reverts to the default font for the paragraph type.
@@ -92,86 +95,92 @@ proc beginFont font {
proc endFont {} {
global curFont file fontEnd
- if {$curFont != ""} {
- puts -nonewline $file $fontEnd($curFont)
- set curFont ""
+ if {$curFont ne ""} {
+ puts -nonewline $file $fontEnd($curFont)
+ set curFont ""
}
}
-
-
-
+
+##############################################################################
# text --
#
-# This procedure adds text to the current paragraph. If this is
-# the first text in the paragraph then header information for the
-# paragraph is output before the text.
+# This procedure adds text to the current paragraph. If this is the first text
+# in the paragraph then header information for the paragraph is output before
+# the text.
#
# Arguments:
# string - Text to output in the paragraph.
proc text string {
- global file textState inDT charCnt
+ global file textState inDT charCnt inTable
set pos [string first "\t" $string]
if {$pos >= 0} {
text [string range $string 0 [expr $pos-1]]
tab
text [string range $string [expr $pos+1] end]
- return
+ return
+ }
+ if {$inTable} {
+ if {$inTable == 1} {
+ puts -nonewline $file <TR>
+ set inTable 2
+ }
+ puts -nonewline $file <TD>
}
incr charCnt [string length $string]
regsub -all {&} $string {\&amp;} string
regsub -all {<} $string {\&lt;} string
regsub -all {>} $string {\&gt;} string
- regsub -all {"} $string {\&quot;} string
- switch $textState {
- REF {
- if {$inDT == {}} {
+ regsub -all \" $string {\&quot;} string
+ switch -exact -- $textState {
+ REF {
+ if {$inDT eq ""} {
set string [insertRef $string]
}
}
- SEE {
+ SEE {
global NAME_file
foreach i [split $string] {
- if ![regexp -nocase {^[a-z_]+} [string trim $i] i ] {
+ if {![regexp -nocase {^[a-z_]+} [string trim $i] i]} {
# puts "Warning: $i in SEE ALSO not found"
continue
}
- if ![catch {set ref $NAME_file($i)} ] {
+ if {![catch { set ref $NAME_file($i) }]} {
regsub $i $string "<A HREF=\"$ref.html\">$i</A>" string
}
}
}
}
puts -nonewline $file "$string"
+ if {$inTable} {
+ puts -nonewline $file </TD>
+ }
}
-
-
+##############################################################################
# insertRef --
#
-#
# Arguments:
# string - Text to output in the paragraph.
proc insertRef string {
global NAME_file self
set path {}
- if ![catch {set ref $NAME_file([string trim $string])} ] {
- if {"$ref.html" != $self} {
+ if {![catch { set ref $NAME_file([string trim $string]) }]} {
+ if {"$ref.html" ne $self} {
set string "<A HREF=\"${path}$ref.html\">$string</A>"
# puts "insertRef: $self $ref.html ---$string--"
}
}
return $string
}
-
-
-
+
+##############################################################################
# macro --
#
-# This procedure is invoked to process macro invocations that start
-# with "." (instead of ').
+# This procedure is invoked to process macro invocations that start with "."
+# (instead of ').
#
# Arguments:
# name - The name of the macro (without the ".").
@@ -195,7 +204,7 @@ proc macro {name args} {
}
AS {} ;# next page and previous page
br {
- lineBreak
+ lineBreak
}
BS {}
BE {}
@@ -210,16 +219,16 @@ proc macro {name args} {
set inPRE 1
}
DE {
- global file noFillCount inPRE
- puts $file </PRE></BLOCKQUOTE>
- set inPRE 0
+ global file noFillCount inTable
+ puts $file </TABLE></BLOCKQUOTE>
+ set inTable 0
set noFillCount 0
}
DS {
- global file noFillCount inPRE
- puts -nonewline $file <BLOCKQUOTE><PRE>
+ global file noFillCount inTable
+ puts -nonewline $file {<BLOCKQUOTE><TABLE BORDER="0">}
set noFillCount 10000000
- set inPRE 1
+ set inTable 1
}
fi {
global noFillCount
@@ -240,13 +249,13 @@ proc macro {name args} {
set noFillCount 1000000
}
OP {
- global inDT file inPRE
+ global inDT file inPRE
if {[llength $args] != 3} {
puts stderr "Bad .OP macro: .$name [join $args " "]"
}
nest para DL DT
set inPRE 1
- puts -nonewline $file <PRE>
+ puts -nonewline $file <PRE>
setTabs 4c
text "Command-Line Name:"
tab
@@ -267,8 +276,8 @@ proc macro {name args} {
font B
text [lindex $args 2]
font R
- puts -nonewline $file </PRE>
- set inDT "\n<DD>" ;# next newline writes inDT
+ puts -nonewline $file </PRE>
+ set inDT "\n<DD>" ;# next newline writes inDT
set inPRE 0
newline
}
@@ -278,7 +287,7 @@ proc macro {name args} {
newPara
}
RE {
- nest decr
+ nest decr
}
RS {
nest incr
@@ -296,7 +305,11 @@ proc macro {name args} {
font B
set temp $textState
set textState REF
- text options
+ if {[llength $args] > 0} {
+ text [lindex $args 0]
+ } else {
+ text options
+ }
set textState $temp
font R
text " manual entry for detailed descriptions of the above options."
@@ -304,6 +317,9 @@ proc macro {name args} {
SH {
SHmacro $args
}
+ SS {
+ SHmacro $args subsection
+ }
SO {
global noFillCount inPRE file
@@ -315,12 +331,12 @@ proc macro {name args} {
font B
}
so {
- if {$args != "man.macros"} {
+ if {$args ne "man.macros"} {
puts stderr "Unknown macro: .$name [join $args " "]"
}
}
sp { ;# needs work
- if {$args == ""} {
+ if {$args eq ""} {
set count 1
} else {
set count [lindex $args 0]
@@ -359,6 +375,43 @@ proc macro {name args} {
# }
# puts -nonewline $file "<FONT COLOR=\"GREEN\">"
}
+ QW {
+ puts -nonewline $file "&\#147;"
+ text [lindex $args 0]
+ puts -nonewline $file "&\#148;"
+ if {[llength $args] > 1} {
+ text [lindex $args 1]
+ }
+ }
+ PQ {
+ puts -nonewline $file "(&\#147;"
+ if {[lindex $args 0] eq {\N'34'}} {
+ puts -nonewline $file \"
+ } else {
+ text [lindex $args 0]
+ }
+ puts -nonewline $file "&\#148;"
+ if {[llength $args] > 1} {
+ text [lindex $args 1]
+ }
+ puts -nonewline $file ")"
+ if {[llength $args] > 2} {
+ text [lindex $args 2]
+ }
+ }
+ QR {
+ puts -nonewline $file "&\#147;"
+ text [lindex $args 0]
+ puts -nonewline $file "&\#148;&\#150;&\#147;"
+ text [lindex $args 1]
+ puts -nonewline $file "&\#148;"
+ if {[llength $args] > 2} {
+ text [lindex $args 2]
+ }
+ }
+ MT {
+ puts -nonewline $file "&\#147;&\#148;"
+ }
default {
puts stderr "Unknown macro: .$name [join $args " "]"
}
@@ -367,12 +420,11 @@ proc macro {name args} {
# global nestStk; puts "$name [format "%-20s" $args] $nestStk"
# flush stdout; flush stderr
}
-
-
+
+##############################################################################
# font --
#
-# This procedure is invoked to handle font changes in the text
-# being output.
+# This procedure is invoked to handle font changes in the text being output.
#
# Arguments:
# type - Type of font: R, I, B, or S.
@@ -383,13 +435,13 @@ proc font type {
P -
R {
endFont
- if {$textState == "REF"} {
+ if {$textState eq "REF"} {
set textState INSERT
}
}
B {
beginFont Code
- if {$textState == "INSERT"} {
+ if {$textState eq "INSERT"} {
set textState REF
}
}
@@ -403,20 +455,19 @@ proc font type {
}
}
}
-
-
-
+
+##############################################################################
# formattedText --
#
-# Insert a text string that may also have \fB-style font changes
-# and a few other backslash sequences in it.
+# Insert a text string that may also have \fB-style font changes and a few
+# other backslash sequences in it.
#
# Arguments:
# text - Text to insert.
proc formattedText text {
# puts "formattedText: $text"
- while {$text != ""} {
+ while {$text ne ""} {
set index [string first \\ $text]
if {$index < 0} {
text $text
@@ -447,37 +498,35 @@ proc formattedText text {
}
}
}
-
-
-
+
+##############################################################################
# dash --
#
-# This procedure is invoked to handle dash characters ("\-" in
-# troff). It outputs a special dash character.
+# This procedure is invoked to handle dash characters ("\-" in troff). It
+# outputs a special dash character.
#
# Arguments:
# None.
proc dash {} {
global textState charCnt
- if {$textState == "NAME"} {
+ if {$textState eq "NAME"} {
set textState 0
}
incr charCnt
text "-"
}
-
-
+
+##############################################################################
# tab --
#
# This procedure is invoked to handle tabs in the troff input.
-# Right now it does nothing.
#
# Arguments:
# None.
proc tab {} {
- global inPRE charCnt tabString
+ global inPRE charCnt tabString file
# ? charCnt
if {$inPRE == 1} {
set pos [expr $charCnt % [string length $tabString] ]
@@ -488,7 +537,7 @@ proc tab {} {
}
}
-
+##############################################################################
# setTabs --
#
# This procedure handles the ".ta" macro, which sets tab stops.
@@ -500,38 +549,52 @@ proc tab {} {
proc setTabs {tabList} {
global file breakPending tabString
-# puts "setTabs: --$tabList--"
+ # puts "setTabs: --$tabList--"
set last 0
set tabString {}
set charsPerInch 14.
set numTabs [llength $tabList]
foreach arg $tabList {
- if {[scan $arg "%f%s" distance units] != 2} {
- puts stderr "bad distance \"$arg\""
- return 0
- }
- switch -- $units {
- c {
- set distance [expr $distance * $charsPerInch / 2.54 ]
- }
- i {
- set distance [expr $distance * $charsPerInch]
+ if {[string match +* $arg]} {
+ set relative 1
+ set arg [string range $arg 1 end]
+ } else {
+ set relative 0
+ }
+ # Always operate in relative mode for "measurement" mode
+ if {[regexp {^\\w'(.*)'u$} $arg content]} {
+ set distance [string length $content]
+ } else {
+ if {[scan $arg "%f%s" distance units] != 2} {
+ puts stderr "bad distance \"$arg\""
+ return 0
}
- default {
- puts stderr "bad units in distance \"$arg\""
- continue
+ switch -- $units {
+ c {
+ set distance [expr {$distance * $charsPerInch / 2.54}]
+ }
+ i {
+ set distance [expr {$distance * $charsPerInch}]
+ }
+ default {
+ puts stderr "bad units in distance \"$arg\""
+ continue
+ }
}
- }
-# ? distance
- lappend tabString [format "%*s1" [expr round($distance-$last-1)] " "]
- set last $distance
+ }
+ # ? distance
+ if {$relative} {
+ append tabString [format "%*s1" [expr {round($distance-1)}] " "]
+ set last [expr {$last + $distance}]
+ } else {
+ append tabString [format "%*s1" [expr {round($distance-$last-1)}] " "]
+ set last $distance
+ }
}
- set tabString [join $tabString {}]
-# puts "setTabs: --$tabString--"
+ # puts "setTabs: --$tabString--"
}
-
-
-
+
+##############################################################################
# lineBreak --
#
# Generates a line break in the HTML output.
@@ -544,23 +607,26 @@ proc lineBreak {} {
puts $file "<BR>"
}
-
-
+##############################################################################
# newline --
#
-# This procedure is invoked to handle newlines in the troff input.
-# It outputs either a space character or a newline character, depending
-# on fill mode.
+# This procedure is invoked to handle newlines in the troff input. It outputs
+# either a space character or a newline character, depending on fill mode.
#
# Arguments:
# None.
proc newline {} {
- global noFillCount file inDT inPRE charCnt
+ global noFillCount file inDT inPRE charCnt inTable
- if {$inDT != {} } {
+ if {$inDT ne ""} {
puts $file "\n$inDT"
set inDT {}
+ } elseif {$inTable} {
+ if {$inTable > 1} {
+ puts $file </tr>
+ set inTable 1
+ }
} elseif {$noFillCount == 0 || $inPRE == 1} {
puts $file {}
} else {
@@ -569,9 +635,8 @@ proc newline {} {
}
set charCnt 0
}
-
-
-
+
+##############################################################################
# char --
#
# This procedure is called to handle a special character.
@@ -602,13 +667,12 @@ proc char name {
}
}
}
-
-
+
+##############################################################################
# macro2 --
#
-# This procedure handles macros that are invoked with a leading "'"
-# character instead of space. Right now it just generates an
-# error diagnostic.
+# This procedure handles macros that are invoked with a leading "'" character
+# instead of space. Right now it just generates an error diagnostic.
#
# Arguments:
# name - The name of the macro (without the ".").
@@ -617,17 +681,17 @@ proc char name {
proc macro2 {name args} {
puts stderr "Unknown macro: '$name [join $args " "]"
}
-
-
-
+
+##############################################################################
# SHmacro --
#
-# Subsection head; handles the .SH macro.
+# Subsection head; handles the .SH and .SS macros.
#
# Arguments:
# name - Section name.
+# style - Type of section (optional)
-proc SHmacro argList {
+proc SHmacro {argList {style section}} {
global file noFillCount textState charCnt
set args [join $argList " "]
@@ -638,14 +702,18 @@ proc SHmacro argList {
set noFillCount 0
nest reset
- puts -nonewline $file "<H3>"
+ set tag H3
+ if {$style eq "subsection"} {
+ set tag H4
+ }
+ puts -nonewline $file "<$tag>"
text $args
- puts $file "</H3>"
+ puts $file "</$tag>"
# ? args textState
# control what the text proc does with text
-
+
switch $args {
NAME {set textState NAME}
DESCRIPTION {set textState INSERT}
@@ -656,20 +724,20 @@ proc SHmacro argList {
}
set charCnt 0
}
-
-
-
+
+##############################################################################
# IPmacro --
#
-# This procedure is invoked to handle ".IP" macros, which may take any
-# of the following forms:
+# This procedure is invoked to handle ".IP" macros, which may take any of the
+# following forms:
#
# .IP [1] Translate to a "1Step" paragraph.
-# .IP [x] (x > 1) Translate to a "Step" paragraph.
+# .IP [x] (x > 1) Translate to a "Step" paragraph.
# .IP Translate to a "Bullet" paragraph.
-# .IP text count Translate to a FirstBody paragraph with special
-# indent and tab stop based on "count", and tab after
-# "text".
+# .IP \(bu Translate to a "Bullet" paragraph.
+# .IP text count Translate to a FirstBody paragraph with
+# special indent and tab stop based on "count",
+# and tab after "text".
#
# Arguments:
# argList - List of arguments to the .IP macro.
@@ -685,50 +753,49 @@ proc IPmacro argList {
nest para UL LI
return
}
- if {$length == 1} {
+ # Special case for alternative mechanism for declaring bullets
+ if {[lindex $argList 0] eq "\\(bu"} {
+ nest para UL LI
+ return
+ }
+ if {[regexp {^\[\d+\]$} [lindex $argList 0]]} {
nest para OL LI
- return
- }
- if {$length > 1} {
- nest para DL DT
- formattedText [lindex $argList 0]
- puts $file "\n<DD>"
- return
+ return
}
- puts stderr "Bad .IP macro: .IP [join $argList " "]"
+ nest para DL DT
+ formattedText [lindex $argList 0]
+ puts $file "\n<DD>"
+ return
}
-
-
+
+##############################################################################
# TPmacro --
#
-# This procedure is invoked to handle ".TP" macros, which may take any
-# of the following forms:
+# This procedure is invoked to handle ".TP" macros, which may take any of the
+# following forms:
#
-# .TP x Translate to an indented paragraph with the
-# specified indent (in 100 twip units).
-# .TP Translate to an indented paragraph with
-# default indent.
+# .TP x Translate to an indented paragraph with the specified indent
+# (in 100 twip units).
+# .TP Translate to an indented paragraph with default indent.
#
# Arguments:
# argList - List of arguments to the .IP macro.
#
# HTML limitations: 'x' in '.TP x' is ignored.
-
proc TPmacro {argList} {
global inDT
nest para DL DT
- set inDT "\n<DD>" ;# next newline writes inDT
+ set inDT "\n<DD>" ;# next newline writes inDT
setTabs 0.5i
}
-
-
-
+
+##############################################################################
# THmacro --
#
-# This procedure handles the .TH macro. It generates the non-scrolling
-# header section for a given man page, and enters information into the
-# table of contents. The .TH macro has the following form:
+# This procedure handles the .TH macro. It generates the non-scrolling header
+# section for a given man page, and enters information into the table of
+# contents. The .TH macro has the following form:
#
# .TH name section date footer header
#
@@ -751,54 +818,52 @@ proc THmacro {argList} {
puts -nonewline $file "<HTML><HEAD><TITLE>"
text "$lib - $name ($page)"
puts $file "</TITLE></HEAD><BODY>\n"
-
+
puts -nonewline $file "<H1><CENTER>"
text $pname
puts $file "</CENTER></H1>\n"
}
-
-
-
+
+##############################################################################
# newPara --
#
-# This procedure sets the left and hanging indents for a line.
-# Indents are specified in units of inches or centimeters, and are
-# relative to the current nesting level and left margin.
+# This procedure sets the left and hanging indents for a line. Indents are
+# specified in units of inches or centimeters, and are relative to the current
+# nesting level and left margin.
#
# Arguments:
# None
proc newPara {} {
global file nestStk
-
- if {[lindex $nestStk end] != "NEW" } {
- nest decr
+
+ if {[lindex $nestStk end] ne "NEW"} {
+ nest decr
}
puts -nonewline $file "<P>"
}
-
-
-
+
+##############################################################################
# nest --
#
-# This procedure takes care of inserting the tags associated with the
-# IP, TP, RS, RE, LP and PP macros. Only 'nest para' takes arguments.
+# This procedure takes care of inserting the tags associated with the IP, TP,
+# RS, RE, LP and PP macros. Only 'nest para' takes arguments.
#
# Arguments:
# op - operation: para, incr, decr, reset, init
# listStart - begin list tag: OL, UL, DL.
# listItem - item tag: LI, LI, DT.
-proc nest {op {listStart "NEW"} {listItem {} } } {
+proc nest {op {listStart "NEW"} {listItem ""} } {
global file nestStk inDT charCnt
# puts "nest: $op $listStart $listItem"
switch $op {
para {
set top [lindex $nestStk end]
- if {$top == "NEW" } {
+ if {$top eq "NEW"} {
set nestStk [lreplace $nestStk end end $listStart]
puts $file "<$listStart>"
- } elseif {$top != $listStart} {
+ } elseif {$top ne $listStart} {
puts stderr "nest para: bad stack"
exit 1
}
@@ -814,7 +879,7 @@ proc nest {op {listStart "NEW"} {listItem {} } } {
set nestStk NEW
}
set tag [lindex $nestStk end]
- if {$tag != "NEW"} {
+ if {$tag ne "NEW"} {
puts $file "</$tag>"
}
set nestStk [lreplace $nestStk end end]
@@ -832,14 +897,13 @@ proc nest {op {listStart "NEW"} {listItem {} } } {
}
set charCnt 0
}
-
-
-
+
+##############################################################################
# do --
#
-# This is the toplevel procedure that translates a man page
-# to Frame. It runs the man2tcl program to turn the man page
-# into a script, then it evals that script.
+# This is the toplevel procedure that translates a man page to HTML. It runs
+# the man2tcl program to turn the man page into a script, then it evals that
+# script.
#
# Arguments:
# fileName - Name of the file to translate.
@@ -851,7 +915,7 @@ proc do fileName {
puts " Pass 2 -- $fileName"
flush stdout
initGlobals
- if [catch {eval [exec man2tcl [glob $fileName]]} msg] {
+ if {[catch { eval [exec man2tcl [glob $fileName]] } msg]} {
global errorInfo
puts stderr $msg
puts "in"
@@ -863,6 +927,3 @@ proc do fileName {
puts $file "</BODY></HTML>"
close $file
}
-
-
-
diff --git a/tools/man2tcl.c b/tools/man2tcl.c
index 464bb34..8e59bea 100644
--- a/tools/man2tcl.c
+++ b/tools/man2tcl.c
@@ -1,11 +1,10 @@
-/*
+/*
* man2tcl.c --
*
- * This file contains a program that turns a man page of the
- * form used for Tcl and Tk into a Tcl script that invokes
- * a Tcl command for each construct in the man page. The
- * script can then be eval'ed to translate the manual entry
- * into some other format such as MIF or HTML.
+ * This file contains a program that turns a man page of the form used
+ * for Tcl and Tk into a Tcl script that invokes a Tcl command for each
+ * construct in the man page. The script can then be eval'ed to translate
+ * the manual entry into some other format such as MIF or HTML.
*
* Usage:
*
@@ -13,28 +12,27 @@
*
* Copyright (c) 1995 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
static char sccsid[] = "@(#) man2tcl.c 1.3 95/08/12 17:34:08";
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-#ifndef NO_ERRNO_H
#include <errno.h>
-#endif
/*
* Imported things that aren't defined in header files:
*/
/*
- * Some <errno.h> define errno to be something complex and
- * thread-aware; in that case we definitely do not want to declare
- * errno ourselves!
+ * Some <errno.h> define errno to be something complex and thread-aware; in
+ * that case we definitely do not want to declare errno ourselves!
*/
+
#ifndef errno
extern int errno;
#endif
@@ -46,22 +44,25 @@ extern int errno;
static int lineNumber;
/*
- * The variable below is set to 1 if an error occurs anywhere
- * while reading in the file.
+ * The variable below is set to 1 if an error occurs anywhere while reading in
+ * the file.
*/
static int status;
/*
- * The variable below is set to 1 if output should be generated.
- * If it's 0, it means we're doing a pre-pass to make sure that
- * the file can be properly parsed.
+ * The variable below is set to 1 if output should be generated. If it's 0, it
+ * means we're doing a pre-pass to make sure that the file can be properly
+ * parsed.
*/
static int writeOutput;
+#define PRINT(args) if (writeOutput) { printf args; }
+#define PRINTC(chr) if (writeOutput) { putc((chr), stdout); }
+
/*
- * Prototypes for procedures defined in this file:
+ * Prototypes for functions defined in this file:
*/
static void DoMacro(char *line);
@@ -73,27 +74,27 @@ static void QuoteText(char *string, int count);
*
* main --
*
- * This procedure is the main program, which does all of the work
- * of the program.
+ * This function is the main program, which does all of the work of the
+ * program.
*
* Results:
- * None: exits with a 0 return status to indicate success, or
- * 1 to indicate that there were problems in the translation.
+ * None: exits with a 0 return status to indicate success, or 1 to
+ * indicate that there were problems in the translation.
*
* Side effects:
- * A Tcl script is output to standard output. Error messages may
- * be output on standard error.
+ * A Tcl script is output to standard output. Error messages may be
+ * output on standard error.
*
*----------------------------------------------------------------------
*/
int
-main(argc, argv)
- int argc; /* Number of command-line arguments. */
- char **argv; /* Values of command-line arguments. */
+main(
+ int argc, /* Number of command-line arguments. */
+ char **argv) /* Values of command-line arguments. */
{
FILE *f;
-#define MAX_LINE_SIZE 1000
+#define MAX_LINE_SIZE 4000
char line[MAX_LINE_SIZE];
char *p;
@@ -115,10 +116,10 @@ main(argc, argv)
}
/*
- * Make two passes over the file. In the first pass, just check
- * to make sure we can handle everything. If there are problems,
- * generate output and stop. If everything is OK, make a second
- * pass to actually generate output.
+ * Make two passes over the file. In the first pass, just check to make
+ * sure we can handle everything. If there are problems, generate output
+ * and stop. If everything is OK, make a second pass to actually generate
+ * output.
*/
for (writeOutput = 0; writeOutput < 2; writeOutput++) {
@@ -132,15 +133,15 @@ main(argc, argv)
}
}
lineNumber++;
-
- if ((line[0] == '\'') && (line[1] == '\\') && (line[2] == '\"')) {
- /*
- * This line is a comment. Ignore it.
+
+ if (((line[0] == '.') || (line[0] == '\'')) && (line[1] == '\\') && (line[2] == '\"')) {
+ /*
+ * This line is a comment. Ignore it.
*/
-
+
continue;
}
-
+
if (strlen(line) >= MAX_LINE_SIZE -1) {
fprintf(stderr, "Too long line. Max is %d chars.\n",
MAX_LINE_SIZE - 1);
@@ -151,14 +152,14 @@ main(argc, argv)
/*
* This line is a macro invocation.
*/
-
+
DoMacro(line);
} else {
/*
* This line is text, possibly with formatting characters
* embedded in it.
*/
-
+
DoText(line);
}
}
@@ -175,9 +176,9 @@ main(argc, argv)
*
* DoMacro --
*
- * This procedure is called to handle a macro invocation.
- * It parses the arguments to the macro and generates a
- * Tcl command to handle the invocation.
+ * This function is called to handle a macro invocation. It parses the
+ * arguments to the macro and generates a Tcl command to handle the
+ * invocation.
*
* Results:
* None.
@@ -189,11 +190,12 @@ main(argc, argv)
*/
static void
-DoMacro(line)
- char *line; /* The line of text that contains the
- * macro invocation. */
+DoMacro(
+ char *line) /* The line of text that contains the macro
+ * invocation. */
{
char *p, *end;
+ int quote;
/*
* If there is no macro name, then just skip the whole line.
@@ -203,13 +205,9 @@ DoMacro(line)
return;
}
- if (writeOutput) {
- printf("macro");
- }
+ PRINT(("macro"));
if (*line != '.') {
- if (writeOutput) {
- printf("2");
- }
+ PRINT(("2"));
}
/*
@@ -218,10 +216,8 @@ DoMacro(line)
p = line+1;
while (1) {
- if (writeOutput) {
- putc(' ', stdout);
- }
- if (*p == '"') {
+ PRINTC(' ');
+ if (*p == '"') {
/*
* The argument is delimited by quotes.
*/
@@ -229,16 +225,19 @@ DoMacro(line)
for (end = p+1; *end != '"'; end++) {
if (*end == 0) {
fprintf(stderr,
- "Unclosed quote in macro call on line %d.\n",
- lineNumber);
+ "Unclosed quote in macro call on line %d.\n",
+ lineNumber);
status = 1;
break;
}
}
QuoteText(p+1, (end-(p+1)));
} else {
- for (end = p+1; (*end != 0) && !isspace(*end); end++) {
- /* Empty loop body. */
+ quote = 0;
+ for (end = p+1; (*end != 0) && (quote || !isspace(*end)); end++) {
+ if (*end == '\'') {
+ quote = !quote;
+ }
}
QuoteText(p, end-p);
}
@@ -257,9 +256,7 @@ DoMacro(line)
break;
}
}
- if (writeOutput) {
- putc('\n', stdout);
- }
+ PRINTC('\n');
}
/*
@@ -267,9 +264,9 @@ DoMacro(line)
*
* DoText --
*
- * This procedure is called to handle a line of troff text.
- * It parses the text, generating Tcl commands for text and
- * for formatting stuff such as font changes.
+ * This function is called to handle a line of troff text. It parses the
+ * text, generating Tcl commands for text and for formatting stuff such
+ * as font changes.
*
* Results:
* None.
@@ -281,22 +278,20 @@ DoMacro(line)
*/
static void
-DoText(line)
- char *line; /* The line of text. */
+DoText(
+ char *line) /* The line of text. */
{
char *p, *end;
/*
- * Divide the line up into pieces consisting of backslash sequences,
- * tabs, and other text.
+ * Divide the line up into pieces consisting of backslash sequences, tabs,
+ * and other text.
*/
p = line;
while (*p != 0) {
if (*p == '\t') {
- if (writeOutput) {
- printf("tab\n");
- }
+ PRINT(("tab\n"));
p++;
} else if (*p != '\\') {
/*
@@ -306,19 +301,15 @@ DoText(line)
for (end = p+1; (*end != '\\') && (*end != 0); end++) {
/* Empty loop body. */
}
- if (writeOutput) {
- printf("text ");
- }
+ PRINT(("text "));
QuoteText(p, end-p);
- if (writeOutput) {
- putc('\n', stdout);
- }
+ PRINTC('\n');
p = end;
} else {
/*
- * A backslash sequence. There are particular ones
- * that we understand; output an error message for
- * anything else and just ignore the backslash.
+ * A backslash sequence. There are particular ones that we
+ * understand; output an error message for anything else and just
+ * ignore the backslash.
*/
p++;
@@ -327,49 +318,46 @@ DoText(line)
* Font change.
*/
- if (writeOutput) {
- printf("font %c\n", p[1]);
- }
+ PRINT(("font %c\n", p[1]));
p += 2;
} else if (*p == '-') {
- if (writeOutput) {
- printf("dash\n");
- }
+ PRINT(("dash\n"));
p++;
} else if (*p == 'e') {
- if (writeOutput) {
- printf("text \\\\\n");
- }
+ PRINT(("text \\\\\n"));
p++;
} else if (*p == '.') {
- if (writeOutput) {
- printf("text .\n");
- }
+ PRINT(("text .\n"));
p++;
} else if (*p == '&') {
p++;
+ } else if (*p == '0') {
+ PRINT(("text { }\n"));
+ p++;
} else if (*p == '(') {
if ((p[1] == 0) || (p[2] == 0)) {
fprintf(stderr, "Bad \\( sequence on line %d.\n",
lineNumber);
status = 1;
} else {
- if (writeOutput) {
- printf("char {\\(%c%c}\n", p[1], p[2]);
- }
+ PRINT(("char {\\(%c%c}\n", p[1], p[2]));
p += 3;
}
+ } else if (*p == 'N' && *(p+1) == '\'') {
+ int ch;
+
+ p += 2;
+ sscanf(p,"%d",&ch);
+ PRINT(("text \\u%04x\n", ch));
+ while(*p&&*p!='\'') p++;
+ p++;
} else if (*p != 0) {
- if (writeOutput) {
- printf("char {\\%c}\n", *p);
- }
+ PRINT(("char {\\%c}\n", *p));
p++;
}
}
}
- if (writeOutput) {
- printf("newline\n");
- }
+ PRINT(("newline\n"));
}
/*
@@ -377,9 +365,9 @@ DoText(line)
*
* QuoteText --
*
- * Copy the "string" argument to stdout, adding quote characters
- * around any special Tcl characters so that they'll just be treated
- * as ordinary text.
+ * Copy the "string" argument to stdout, adding quote characters around
+ * any special Tcl characters so that they'll just be treated as ordinary
+ * text.
*
* Results:
* None.
@@ -391,26 +379,46 @@ DoText(line)
*/
static void
-QuoteText(string, count)
- char *string; /* The line of text. */
- int count; /* Number of characters to write from string. */
+QuoteText(
+ char *string, /* The line of text. */
+ int count) /* Number of characters to write from
+ * string. */
{
if (count == 0) {
- if (writeOutput) {
- printf("{}");
- }
+ PRINT(("{}"));
return;
}
for ( ; count > 0; string++, count--) {
- if ((*string == '$') || (*string == '[') || (*string == '{')
- || (*string == ' ') || (*string == ';') || (*string == '\\')
- || (*string == '"') || (*string == '\t')) {
- if (writeOutput) {
- putc('\\', stdout);
+ switch (*string) {
+ case '\\':
+ if (*(string+1) == 'N' && *(string+2) == '\'') {
+ int ch;
+
+ string += 3;
+ count -= 3;
+ sscanf(string,"%d",&ch);
+ PRINT(("\\u%04x", ch));
+ while(count>0&&*string!='\'') {string++;count--;}
+ continue;
+ } else if (*(string+1) == '0') {
+ PRINT(("\\ "));
+ string++;
+ count--;
+ continue;
}
- }
- if (writeOutput) {
- putc(*string, stdout);
+ case '$': case '[': case '{': case ' ': case ';':
+ case '"': case '\t':
+ PRINTC('\\');
+ default:
+ PRINTC(*string);
}
}
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/tools/mkdepend.tcl b/tools/mkdepend.tcl
new file mode 100644
index 0000000..de5fdba
--- /dev/null
+++ b/tools/mkdepend.tcl
@@ -0,0 +1,420 @@
+#==============================================================================
+#
+# mkdepend : generate dependency information from C/C++ files
+#
+# Copyright (c) 1998, Nat Pryce
+#
+# Permission is hereby granted, without written agreement and without
+# license or royalty fees, to use, copy, modify, and distribute this
+# software and its documentation for any purpose, provided that the
+# above copyright notice and the following two paragraphs appear in
+# all copies of this software.
+#
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+# SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
+# THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHOR HAS BEEN ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
+# BASIS, AND THE AUTHOR HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
+# UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+#==============================================================================
+#
+# Modified heavily by David Gravereaux <davygrvy@pobox.com> about 9/17/2006.
+# Original can be found @
+# http://web.archive.org/web/20070616205924/http://www.doc.ic.ac.uk/~np2/software/mkdepend.html
+#==============================================================================
+
+array set mode_data {}
+set mode_data(vc32) {cl -nologo -E}
+
+set source_extensions [list .c .cpp .cxx .cc]
+
+set excludes [list]
+if [info exists env(INCLUDE)] {
+ set rawExcludes [split [string trim $env(INCLUDE) ";"] ";"]
+ foreach exclude $rawExcludes {
+ lappend excludes [file normalize $exclude]
+ }
+}
+
+
+# openOutput --
+#
+# Opens the output file.
+#
+# Arguments:
+# file The file to open
+#
+# Results:
+# None.
+
+proc openOutput {file} {
+ global output
+ set output [open $file w]
+ puts $output "# Automatically generated at [clock format [clock seconds] -format "%Y-%m-%dT%H:%M:%S"] by [info script]\n"
+}
+
+# closeOutput --
+#
+# Closes output file.
+#
+# Arguments:
+# none
+#
+# Results:
+# None.
+
+proc closeOutput {} {
+ global output
+ if {[string match stdout $output] != 0} {
+ close $output
+ }
+}
+
+# readDepends --
+#
+# Read off CCP pipe for #line references.
+#
+# Arguments:
+# chan The pipe channel we are reading in.
+#
+# Results:
+# Raw dependency list pairs.
+
+proc readDepends {chan} {
+ set line ""
+ array set depends {}
+
+ while {[gets $chan line] != -1} {
+ if {[regexp {^#line [0-9]+ \"(.*)\"$} $line dummy fname] != 0} {
+ set fname [file normalize $fname]
+ if {![info exists target]} {
+ # this is ourself
+ set target $fname
+ puts stderr "processing [file tail $fname]"
+ } else {
+ # don't include ourselves as a dependency of ourself.
+ if {![string compare $fname $target]} {continue}
+ # store in an array so multiple occurances are not counted.
+ set depends($target|$fname) ""
+ }
+ }
+ }
+
+ set result {}
+ foreach n [array names depends] {
+ set pair [split $n "|"]
+ lappend result [list [lindex $pair 0] [lindex $pair 1]]
+ }
+
+ return $result
+}
+
+# writeDepends --
+#
+# Write the processed list out to the file.
+#
+# Arguments:
+# out The channel to write to.
+# depends The list of dependency pairs
+#
+# Results:
+# None.
+
+proc writeDepends {out depends} {
+ foreach pair $depends {
+ puts $out "[lindex $pair 0] : \\\n\t[join [lindex $pair 1] " \\\n\t"]"
+ }
+}
+
+# stringStartsWith --
+#
+# Compares second string to the beginning of the first.
+#
+# Arguments:
+# str The string to test the beginning of.
+# prefix The string to test against
+#
+# Results:
+# the result of the comparison.
+
+proc stringStartsWith {str prefix} {
+ set front [string range $str 0 [expr {[string length $prefix] - 1}]]
+ return [expr {[string compare [string tolower $prefix] \
+ [string tolower $front]] == 0}]
+}
+
+# filterExcludes --
+#
+# Remove non-project header files.
+#
+# Arguments:
+# depends List of dependency pairs.
+# excludes List of directories that should be removed
+#
+# Results:
+# the processed dependency list.
+
+proc filterExcludes {depends excludes} {
+ set filtered {}
+
+ foreach pair $depends {
+ set excluded 0
+ set file [lindex $pair 1]
+
+ foreach dir $excludes {
+ if [stringStartsWith $file $dir] {
+ set excluded 1
+ break;
+ }
+ }
+
+ if {!$excluded} {
+ lappend filtered $pair
+ }
+ }
+
+ return $filtered
+}
+
+# replacePrefix --
+#
+# Take the normalized search path and put back the
+# macro name for it.
+#
+# Arguments:
+# file filename.
+#
+# Results:
+# filename properly replaced with macro for it.
+
+proc replacePrefix {file} {
+ global srcPathList srcPathReplaceList
+
+ foreach was $srcPathList is $srcPathReplaceList {
+ regsub $was $file $is file
+ }
+ return $file
+}
+
+# rebaseFiles --
+#
+# Replaces normalized paths with original macro names.
+#
+# Arguments:
+# depends Dependency pair list.
+#
+# Results:
+# The processed dependency pair list.
+
+proc rebaseFiles {depends} {
+ set rebased {}
+ foreach pair $depends {
+ lappend rebased [list \
+ [replacePrefix [lindex $pair 0]] \
+ [replacePrefix [lindex $pair 1]]]
+
+ }
+ return $rebased
+}
+
+# compressDeps --
+#
+# Compresses same named tragets into one pair with
+# multiple deps.
+#
+# Arguments:
+# depends Dependency pair list.
+#
+# Results:
+# The processed list.
+
+proc compressDeps {depends} {
+ array set compressed [list]
+
+ foreach pair $depends {
+ lappend compressed([lindex $pair 0]) [lindex $pair 1]
+ }
+
+ set result [list]
+ foreach n [array names compressed] {
+ lappend result [list $n [lsort $compressed($n)]]
+ }
+
+ return $result
+}
+
+# addSearchPath --
+#
+# Adds a new set of path and replacement string to the global list.
+#
+# Arguments:
+# newPathInfo comma seperated path and replacement string
+#
+# Results:
+# None.
+
+proc addSearchPath {newPathInfo} {
+ global srcPathList srcPathReplaceList
+
+ set infoList [split $newPathInfo ,]
+ lappend srcPathList [file normalize [lindex $infoList 0]]
+ lappend srcPathReplaceList [lindex $infoList 1]
+}
+
+
+# displayUsage --
+#
+# Displays usage to stderr
+#
+# Arguments:
+# none.
+#
+# Results:
+# None.
+
+proc displayUsage {} {
+ puts stderr "mkdepend.tcl \[options\] genericDir,macroName compatDir,macroName platformDir,macroName"
+}
+
+# readInputListFile --
+#
+# Open and read the object file list.
+#
+# Arguments:
+# objectListFile - name of the file to open.
+#
+# Results:
+# None.
+
+proc readInputListFile {objectListFile} {
+ global srcFileList srcPathList source_extensions
+ set f [open $objectListFile r]
+ set fl [read $f]
+ close $f
+
+ # fix native path seperator so it isn't treated as an escape.
+ regsub -all {\\} $fl {/} fl
+
+ # Treat the string as a list so filenames between double quotes are
+ # treated as list elements.
+ foreach fname $fl {
+ # Compiled .res resource files should be ignored.
+ if {[file extension $fname] ne ".obj"} {continue}
+
+ # Just filename without path or extension because the path is
+ # the build directory, not where the source files are located.
+ set baseName [file rootname [file tail $fname]]
+
+ set found 0
+ foreach path $srcPathList {
+ foreach ext $source_extensions {
+ set test [file join $path ${baseName}${ext}]
+ if {[file exist $test]} {
+ lappend srcFileList $test
+ set found 1
+ break
+ }
+ }
+ if {$found} break
+ }
+ }
+}
+
+# main --
+#
+# The main procedure of this script.
+#
+# Arguments:
+# none.
+#
+# Results:
+# None.
+
+proc main {} {
+ global argc argv mode mode_data srcFileList srcPathList excludes
+ global remove_prefix target_prefix output env
+
+ set srcPathList [list]
+ set srcFileList [list]
+
+ if {$argc == 1} {displayUsage}
+
+ # Parse mkdepend input
+ for {set i 0} {$i < [llength $argv]} {incr i} {
+ switch -glob -- [set arg [lindex $argv $i]] {
+ -vc32 {
+ set mode vc32
+ }
+ -bc32 {
+ set mode bc32
+ }
+ -wc32 {
+ set mode wc32
+ }
+ -lc32 {
+ set mode lc32
+ }
+ -mgw32 {
+ set mode mgw32
+ }
+ -passthru:* {
+ set passthru [string range $arg 10 end]
+ regsub -all {"} $passthru {\"} passthru
+ regsub -all {\\} $passthru {/} passthru
+ }
+ -out:* {
+ openOutput [string range $arg 5 end]
+ }
+ @* {
+ set objfile [string range $arg 1 end]
+ regsub -all {\\} $objfile {/} objfile
+ readInputListFile $objfile
+ }
+ -? - -help - --help {
+ displayUsage
+ exit 1
+ }
+ default {
+ if {![info exist mode]} {
+ puts stderr "mode not set"
+ displayUsage
+ }
+ addSearchPath $arg
+ }
+ }
+ }
+
+ # Execute the CPP command and parse output
+
+ foreach srcFile $srcFileList {
+ if {[catch {
+ set command "$mode_data($mode) $passthru \"$srcFile\""
+ set input [open |$command r]
+ set depends [readDepends $input]
+ set status [catch {close $input} result]
+ if {$status == 1 && [lindex $::errorCode 0] eq "CHILDSTATUS"} {
+ foreach { - pid code } $::errorCode break
+ if {$code == 2} {
+ # preprocessor died a cruel death.
+ error $result
+ }
+ }
+ } err]} {
+ puts stderr "error ocurred: $err\n"
+ continue
+ }
+ set depends [filterExcludes $depends $excludes]
+ set depends [rebaseFiles $depends]
+ set depends [compressDeps $depends]
+ writeDepends $output $depends
+ }
+
+ closeOutput
+}
+
+# kick it up.
+main
diff --git a/tools/tcl.hpj.in b/tools/tcl.hpj.in
index 2a8c94a..0d01f35 100644
--- a/tools/tcl.hpj.in
+++ b/tools/tcl.hpj.in
@@ -5,9 +5,9 @@ HCW=0
LCID=0x409 0x0 0x0 ;English (United States)
REPORT=Yes
TITLE=Tcl/Tk Reference Manual
-CNT=tcl84.cnt
+CNT=tcl85.cnt
COPYRIGHT=Copyright © 2000 Ajuba Solutions
-HLP=tcl84.hlp
+HLP=tcl85.hlp
[FILES]
tcl.rtf
diff --git a/tools/tcl.wse.in b/tools/tcl.wse.in
index 1dceec0..57dfc52 100644
--- a/tools/tcl.wse.in
+++ b/tools/tcl.wse.in
@@ -1,7 +1,7 @@
Document Type: WSE
item: Global
Version=6.01
- Title=Tcl 8.4 for Windows Installation
+ Title=Tcl 8.5 for Windows Installation
Flags=00010100
Languages=65 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Japanese Font Name=MS Gothic
@@ -12,7 +12,7 @@ item: Global
Log Pathname=%MAINDIR%\INSTALL.LOG
Message Font=MS Sans Serif
Font Size=8
- Disk Label=tcl8.4.19
+ Disk Label=tcl8.5.10
Disk Filename=setup
Patch Flags=0000000000000001
Patch Threshold=85
@@ -42,7 +42,7 @@ item: End Block
end
item: Set Variable
Variable=VER
- Value=8.4
+ Value=8.5
end
item: Set Variable
Variable=PATCHLEVEL
@@ -960,23 +960,23 @@ item: If/While Statement
Flags=00001010
end
item: Install File
- Source=${__TKBASEDIR__}\win\release\tk84.lib
- Destination=%MAINDIR%\lib\tk84.lib
+ Source=${__TKBASEDIR__}\win\release\tk85.lib
+ Destination=%MAINDIR%\lib\tk85.lib
Flags=0000000000000010
end
item: Install File
- Source=${__TKBASEDIR__}\win\release\tkstub84.lib
- Destination=%MAINDIR%\lib\tkstub84.lib
+ Source=${__TKBASEDIR__}\win\release\tkstub85.lib
+ Destination=%MAINDIR%\lib\tkstub85.lib
Flags=0000000000000010
end
item: Install File
- Source=${__TCLBASEDIR__}\win\release\tcl84.lib
- Destination=%MAINDIR%\lib\tcl84.lib
+ Source=${__TCLBASEDIR__}\win\release\tcl85.lib
+ Destination=%MAINDIR%\lib\tcl85.lib
Flags=0000000000000010
end
item: Install File
- Source=${__TCLBASEDIR__}\win\release\tclstub84.lib
- Destination=%MAINDIR%\lib\tclstub84.lib
+ Source=${__TCLBASEDIR__}\win\release\tclstub85.lib
+ Destination=%MAINDIR%\lib\tclstub85.lib
Flags=0000000000000010
end
item: Install File
@@ -1063,12 +1063,12 @@ item: If/While Statement
end
item: Install File
Source=${__TCLBASEDIR__}\library\msgcat\pkgIndex.tcl
- Destination=%MAINDIR%\lib\tcl%VER%\msgcat1.2\pkgIndex.tcl
+ Destination=%MAINDIR%\lib\tcl%VER%\msgcat1.4\pkgIndex.tcl
Flags=0000000010000010
end
item: Install File
Source=${__TCLBASEDIR__}\library\msgcat\msgcat.tcl
- Destination=%MAINDIR%\lib\tcl%VER%\msgcat1.2\msgcat.tcl
+ Destination=%MAINDIR%\lib\tcl%VER%\msgcat1.4\msgcat.tcl
Flags=0000000010000010
end
item: Install File
@@ -1443,12 +1443,12 @@ item: Install File
end
item: Install File
Source=${__TCLBASEDIR__}\library\http\pkgIndex.tcl
- Destination=%MAINDIR%\lib\tcl%VER%\http2.5\pkgIndex.tcl
+ Destination=%MAINDIR%\lib\tcl%VER%\http2.4\pkgIndex.tcl
Flags=0000000000000010
end
item: Install File
Source=${__TCLBASEDIR__}\library\http\http.tcl
- Destination=%MAINDIR%\lib\tcl%VER%\http2.5\http.tcl
+ Destination=%MAINDIR%\lib\tcl%VER%\http2.4\http.tcl
Flags=0000000000000010
end
item: Install File
@@ -1607,28 +1607,28 @@ item: Install File
Flags=0010001000000011
end
item: Install File
- Source=${__TKBASEDIR__}\win\release\wish84.exe
- Destination=%MAINDIR%\bin\wish84.exe
+ Source=${__TKBASEDIR__}\win\release\wish85.exe
+ Destination=%MAINDIR%\bin\wish85.exe
Flags=0000000000000010
end
item: Install File
- Source=${__TCLBASEDIR__}\win\release\tclsh84.exe
- Destination=%MAINDIR%\bin\tclsh84.exe
+ Source=${__TCLBASEDIR__}\win\release\tclsh85.exe
+ Destination=%MAINDIR%\bin\tclsh85.exe
Flags=0000000000000010
end
item: Install File
- Source=${__TCLBASEDIR__}\win\release\tclpip84.dll
- Destination=%MAINDIR%\bin\tclpip84.dll
+ Source=${__TCLBASEDIR__}\win\release\tclpip85.dll
+ Destination=%MAINDIR%\bin\tclpip85.dll
Flags=0000000000000010
end
item: Install File
- Source=${__TCLBASEDIR__}\win\release\tcl84.dll
- Destination=%MAINDIR%\bin\tcl84.dll
+ Source=${__TCLBASEDIR__}\win\release\tcl85.dll
+ Destination=%MAINDIR%\bin\tcl85.dll
Flags=0000000000000010
end
item: Install File
- Source=${__TKBASEDIR__}\win\release\tk84.dll
- Destination=%MAINDIR%\bin\tk84.dll
+ Source=${__TKBASEDIR__}\win\release\tk85.dll
+ Destination=%MAINDIR%\bin\tk85.dll
Flags=0000000000000010
end
item: Install File
@@ -2031,13 +2031,13 @@ item: If/While Statement
Flags=00001010
end
item: Install File
- Source=${__TCLBASEDIR__}\tools\tcl84.cnt
- Destination=%MAINDIR%\doc\tcl84.cnt
+ Source=${__TCLBASEDIR__}\tools\tcl85.cnt
+ Destination=%MAINDIR%\doc\tcl85.cnt
Flags=0000000000000010
end
item: Install File
- Source=${__TCLBASEDIR__}\tools\tcl84.hlp
- Destination=%MAINDIR%\doc\tcl84.hlp
+ Source=${__TCLBASEDIR__}\tools\tcl85.hlp
+ Destination=%MAINDIR%\doc\tcl85.hlp
Flags=0000000000000010
end
item: End Block
@@ -2070,7 +2070,7 @@ item: If/While Statement
Flags=00001010
end
item: Create Shortcut
- Source=%MAINDIR%\bin\wish84.exe
+ Source=%MAINDIR%\bin\wish85.exe
Destination=%GROUP%\Wish.lnk
Working Directory=%MAINDIR%
end
@@ -2082,7 +2082,7 @@ item: If/While Statement
Flags=00001010
end
item: Create Shortcut
- Source=%MAINDIR%\bin\tclsh84.exe
+ Source=%MAINDIR%\bin\tclsh85.exe
Destination=%GROUP%\Tclsh.lnk
Working Directory=%MAINDIR%
Key Type=1536
@@ -2096,7 +2096,7 @@ item: If/While Statement
Flags=00001010
end
item: Create Shortcut
- Source=%MAINDIR%\doc\tcl84.hlp
+ Source=%MAINDIR%\doc\tcl85.hlp
Destination=%GROUP%\Tcl Help.lnk
Working Directory=%MAINDIR%
end
@@ -2132,7 +2132,7 @@ item: Add ProgMan Icon
Group=%GROUP%
Icon Name=Widget Tour
Command Line=%MAINDIR%\lib\tk%VER%\demos\widget.tcl
- Icon Pathname=%MAINDIR%\bin\wish84.exe
+ Icon Pathname=%MAINDIR%\bin\wish85.exe
Default Directory=%MAINDIR%
end
item: End Block
@@ -2145,7 +2145,7 @@ end
item: Add ProgMan Icon
Group=%GROUP%
Icon Name=Tcl Help
- Command Line=%MAINDIR%\doc\tcl84.hlp
+ Command Line=%MAINDIR%\doc\tcl85.hlp
Default Directory=%MAINDIR%
end
item: End Block
@@ -2164,7 +2164,7 @@ end
item: Add ProgMan Icon
Group=%GROUP%
Icon Name=Wish
- Command Line=%MAINDIR%\bin\wish84.exe
+ Command Line=%MAINDIR%\bin\wish85.exe
Default Directory=%MAINDIR%
end
item: End Block
@@ -2177,7 +2177,7 @@ end
item: Add ProgMan Icon
Group=%GROUP%
Icon Name=Tclsh
- Command Line=%MAINDIR%\bin\tclsh84.exe
+ Command Line=%MAINDIR%\bin\tclsh85.exe
Default Directory=%MAINDIR%
end
item: End Block
@@ -2197,7 +2197,7 @@ end
item: Edit Registry
Total Keys=1
Key=TclScript\DefaultIcon
- New Value=%MAINDIR%\bin\tk84.dll
+ New Value=%MAINDIR%\bin\tk85.dll
end
item: Edit Registry
Total Keys=1
@@ -2212,7 +2212,7 @@ end
item: Edit Registry
Total Keys=1
Key=TclScript\shell\open\command
- New Value=%MAINDIRSHORT%\bin\wish84.exe "%%1" %%*
+ New Value=%MAINDIRSHORT%\bin\wish85.exe "%%1" %%*
end
item: Edit Registry
Total Keys=1
diff --git a/tools/tclSplash.bmp b/tools/tclSplash.bmp
index e3e83ad..db8a17e 100644
--- a/tools/tclSplash.bmp
+++ b/tools/tclSplash.bmp
Binary files differ
diff --git a/tools/tclZIC.tcl b/tools/tclZIC.tcl
new file mode 100755
index 0000000..1b19d82
--- /dev/null
+++ b/tools/tclZIC.tcl
@@ -0,0 +1,1375 @@
+#----------------------------------------------------------------------
+#
+# tclZIC.tcl --
+#
+# Take the time zone data source files from Arthur Olson's
+# repository at elsie.nci.nih.gov, and prepare time zone
+# information files for Tcl.
+#
+# Usage:
+# tclsh tclZIC.tcl inputDir outputDir
+#
+# Parameters:
+# inputDir - Directory (e.g., tzdata2003e) where Olson's source
+# files are to be found.
+# outputDir - Directory (e.g., ../library/tzdata) where
+# the time zone information files are to be placed.
+#
+# Results:
+# May produce error messages on the standard error. An exit
+# code of zero denotes success; any other exit code is failure.
+#
+# This program parses the timezone data in a means analogous to the
+# 'zic' command, and produces Tcl time zone information files suitable
+# for loading into the 'clock' namespace.
+#
+#----------------------------------------------------------------------
+#
+# Copyright (c) 2004 by Kevin B. Kenny. All rights reserved.
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#----------------------------------------------------------------------
+
+package require Tcl 8.5
+
+# Define the names of the Olson files that we need to load.
+# We avoid the solar time files and the leap seconds.
+
+set olsonFiles {
+ africa antarctica asia australasia
+ backward etcetera europe northamerica
+ pacificnew southamerica systemv
+}
+
+# Define the year at which the DST information will stop.
+
+set maxyear 2100
+
+# Determine how big a wide integer is.
+
+set MAXWIDE [expr {wide(1)}]
+while 1 {
+ set next [expr {wide($MAXWIDE + $MAXWIDE + 1)}]
+ if {$next < 0} {
+ break
+ }
+ set MAXWIDE $next
+}
+set MINWIDE [expr {-$MAXWIDE-1}]
+
+#----------------------------------------------------------------------
+#
+# loadFiles --
+#
+# Loads the time zone files for each continent into memory
+#
+# Parameters:
+# dir - Directory where the time zone source files are found
+#
+# Results:
+# None.
+#
+# Side effects:
+# Calls 'loadZIC' for each continent's data file in turn.
+# Reports progress on stdout.
+#
+#----------------------------------------------------------------------
+
+proc loadFiles {dir} {
+ variable olsonFiles
+ foreach file $olsonFiles {
+ puts "loading: [file join $dir $file]"
+ loadZIC [file join $dir $file]
+ }
+ return
+}
+
+#----------------------------------------------------------------------
+#
+# checkForwardRuleRefs --
+#
+# Checks to make sure that all references to Daylight Saving
+# Time rules designate defined rules.
+#
+# Parameters:
+# None.
+#
+# Results:
+# None.
+#
+# Side effects:
+# Produces an error message and increases the error count if
+# any undefined rules are present.
+#
+#----------------------------------------------------------------------
+
+proc checkForwardRuleRefs {} {
+ variable forwardRuleRefs
+ variable rules
+
+ foreach {rule where} [array get forwardRuleRefs] {
+ if {![info exists rules($rule)]} {
+ foreach {fileName lno} $where {
+ puts stderr "$fileName:$lno:can't locate rule \"$rule\""
+ incr errorCount
+ }
+ }
+ }
+}
+
+#----------------------------------------------------------------------
+#
+# loadZIC --
+#
+# Load one continent's data into memory.
+#
+# Parameters:
+# fileName -- Name of the time zone source file.
+#
+# Results:
+# None.
+#
+# Side effects:
+# The global variable, 'errorCount' counts the number of errors.
+# The global array, 'links', contains a distillation of the
+# 'Link' directives in the file. The keys are 'links to' and
+# the values are 'links from'. The 'parseRule' and 'parseZone'
+# procedures are called to handle 'Rule' and 'Zone' directives.
+#
+#----------------------------------------------------------------------
+
+proc loadZIC {fileName} {
+ variable errorCount
+ variable links
+
+ # Suck the text into memory.
+
+ set f [open $fileName r]
+ set data [read $f]
+ close $f
+
+ # Break the input into lines, and count line numbers.
+
+ set lno 0
+ foreach line [split $data \n] {
+ incr lno
+
+ # Break a line of input into words.
+
+ regsub {\s*(\#.*)?$} $line {} line
+ if {$line eq ""} {
+ continue
+ }
+ set words {}
+ if {[regexp {^\s} $line]} {
+ # Detect continuations of a zone and flag the list appropriately
+ lappend words ""
+ }
+ lappend words {*}[regexp -all -inline {\S+} $line]
+
+ # Switch on the directive
+
+ switch -exact -- [lindex $words 0] {
+ Rule {
+ parseRule $fileName $lno $words
+ }
+ Link {
+ set links([lindex $words 2]) [lindex $words 1]
+ }
+ Zone {
+ set lastZone [lindex $words 1]
+ set until [parseZone $fileName $lno \
+ $lastZone [lrange $words 2 end] "minimum"]
+ }
+ {} {
+ set i 0
+ foreach word $words {
+ if {[lindex $words $i] ne ""} {
+ break
+ }
+ incr i
+ }
+ set words [lrange $words $i end]
+ set until [parseZone $fileName $lno $lastZone $words $until]
+ }
+ default {
+ incr errorCount
+ puts stderr "$fileName:$lno:unknown line type \"[lindex $words 0]\""
+ }
+ }
+ }
+
+ return
+}
+
+#----------------------------------------------------------------------
+#
+# parseRule --
+#
+# Parses a Rule directive in an Olson file.
+#
+# Parameters:
+# fileName -- Name of the file being parsed.
+# lno - Line number within the file
+# words - The line itself, broken into words.
+#
+# Results:
+# None.
+#
+# Side effects:
+# The rule is analyzed and added to the 'rules' array.
+# Errors are reported and counted.
+#
+#----------------------------------------------------------------------
+
+proc parseRule {fileName lno words} {
+ variable rules
+ variable errorCount
+
+ # Break out the columns
+
+ lassign $words Rule name from to type in on at save letter
+
+ # Handle the 'only' keyword
+
+ if {$to eq "only"} {
+ set to $from
+ }
+
+ # Process the start year
+
+ if {![string is integer $from]} {
+ if {![string equal -length [string length $from] $from "minimum"]} {
+ puts stderr "$fileName:$lno:FROM field \"$from\" not an integer."
+ incr errorCount
+ return
+ } else {
+ set from "minimum"
+ }
+ }
+
+ # Process the end year
+
+ if {![string is integer $to]} {
+ if {![string equal -length [string length $to] $to "maximum"]} {
+ puts stderr "$fileName:$lno:TO field \"$to\" not an integer."
+ incr errorCount
+ return
+ } else {
+ set to "maximum"
+ }
+ }
+
+ # Process the type of year in which the rule applies
+
+ if {$type ne "-"} {
+ puts stderr "$fileName:$lno:year types are not yet supported."
+ incr errorCount
+ return
+ }
+
+ # Process the month in which the rule starts
+
+ if {[catch {lookupMonth $in} in]} {
+ puts stderr "$fileName:$lno:$in"
+ incr errorCount
+ return
+ }
+
+ # Process the day of the month on which the rule starts
+
+ if {[catch {parseON $on} on]} {
+ puts stderr "$fileName:$lno:$on"
+ incr errorCount
+ return
+ }
+
+ # Process the time of day on which the rule starts
+
+ if {[catch {parseTOD $at} at]} {
+ puts stderr "$fileName:$lno:$at"
+ incr errorCount
+ return
+ }
+
+ # Process the DST adder
+
+ if {[catch {parseOffsetTime $save} save]} {
+ puts stderr "$fileName:$lno:$save"
+ incr errorCount
+ return
+ }
+
+ # Process the letter to use for summer time
+
+ if {$letter eq "-"} {
+ set letter ""
+ }
+
+ # Accumulate all the data.
+
+ lappend rules($name) $from $to $type $in $on $at $save $letter
+ return
+
+}
+
+#----------------------------------------------------------------------
+#
+# parseON --
+#
+# Parse a specification for a day of the month
+#
+# Parameters:
+# on - the ON field from a line in an Olson file.
+#
+# Results:
+# Returns a partial Tcl command. When the year and number of the
+# month are appended, the command will return the Julian Day Number
+# of the desired date.
+#
+# Side effects:
+# None.
+#
+# The specification can be:
+# - a simple number, which designates a constant date.
+# - The name of a weekday, followed by >= or <=, followed by a number.
+# This designates the nearest occurrence of the given weekday on
+# or before (on or after) the given day of the month.
+# - The word 'last' followed by a weekday name with no intervening
+# space. This designates the last occurrence of the given weekday
+# in the month.
+#
+#----------------------------------------------------------------------
+
+proc parseON {on} {
+ if {![regexp -expanded {
+ ^(?:
+ # first possibility - simple number - field 1
+ ([[:digit:]]+)
+ |
+ # second possibility - weekday >= (or <=) number
+ # field 2 - weekday
+ ([[:alpha:]]+)
+ # field 3 - direction
+ ([<>]=)
+ # field 4 - number
+ ([[:digit:]]+)
+ |
+ # third possibility - lastWeekday - field 5
+ last([[:alpha:]]+)
+ )$
+ } $on -> dom1 wday2 dir2 num2 wday3]} then {
+ error "can't parse ON field \"$on\""
+ }
+ if {$dom1 ne ""} {
+ return [list onDayOfMonth $dom1]
+ } elseif {$wday2 ne ""} {
+ set wday2 [lookupDayOfWeek $wday2]
+ return [list onWeekdayInMonth $wday2 $dir2 $num2]
+ } elseif {$wday3 ne ""} {
+ set wday3 [lookupDayOfWeek $wday3]
+ return [list onLastWeekdayInMonth $wday3]
+ } else {
+ error "in parseOn \"$on\": can't happen"
+ }
+}
+
+#----------------------------------------------------------------------
+#
+# onDayOfMonth --
+#
+# Find a given day of a given month
+#
+# Parameters:
+# day - Day of the month
+# year - Gregorian year
+# month - Number of the month (1-12)
+#
+# Results:
+# Returns the Julian Day Number of the desired day.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc onDayOfMonth {day year month} {
+ scan $day %d day
+ scan $year %d year
+ scan $month %d month
+ set date [::tcl::clock::GetJulianDayFromEraYearMonthDay \
+ [dict create era CE year $year month $month dayOfMonth $day] \
+ 2361222]
+ return [dict get $date julianDay]
+}
+
+#----------------------------------------------------------------------
+#
+# onWeekdayInMonth --
+#
+# Find the weekday falling on or after (on or before) a
+# given day of the month
+#
+# Parameters:
+# dayOfWeek - Day of the week (Monday=1, Sunday=7)
+# relation - <= for the weekday on or before a given date, >= for
+# the weekday on or after the given date.
+# dayOfMonth - Day of the month
+# year - Gregorian year
+# month - Number of the month (1-12)
+#
+# Results:
+# Returns the Juloan Day Number of the desired day.
+#
+# Side effects:
+# None.
+#
+# onWeekdayInMonth is used to compute Daylight Saving Time rules
+# like 'Sun>=1' (for the nearest Sunday on or after the first of the month)
+# or "Mon<=4' (for the Monday on or before the fourth of the month).
+#
+#----------------------------------------------------------------------
+
+proc onWeekdayInMonth {dayOfWeek relation dayOfMonth year month} {
+ set date [::tcl::clock::GetJulianDayFromEraYearMonthDay [dict create \
+ era CE year $year month $month dayOfMonth $dayOfMonth] 2361222]
+ switch -exact -- $relation {
+ <= {
+ return [::tcl::clock::WeekdayOnOrBefore $dayOfWeek \
+ [dict get $date julianDay]]
+ }
+ >= {
+ return [::tcl::clock::WeekdayOnOrBefore $dayOfWeek \
+ [expr {[dict get $date julianDay] + 6}]]
+ }
+ }
+}
+
+#----------------------------------------------------------------------
+#
+# onLastWeekdayInMonth --
+#
+# Find the last instance of a given weekday in a month.
+#
+# Parameters:
+# dayOfWeek - Weekday to find (Monday=1, Sunday=7)
+# year - Gregorian year
+# month - Month (1-12)
+#
+# Results:
+# Returns the Julian Day number of the last instance of
+# the given weekday in the given month
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc onLastWeekdayInMonth {dayOfWeek year month} {
+ incr month
+ # Find day 0 of the following month, which is the last day of
+ # the current month. Yes, it works to ask for day 0 of month 13!
+ set date [::tcl::clock::GetJulianDayFromEraYearMonthDay [dict create \
+ era CE year $year month $month dayOfMonth 0] 2361222]
+ return [::tcl::clock::WeekdayOnOrBefore $dayOfWeek \
+ [dict get $date julianDay]]
+}
+
+#----------------------------------------------------------------------
+#
+# parseTOD --
+#
+# Parses the specification of a time of day in an Olson file.
+#
+# Parameters:
+# tod - Time of day, which may be followed by 'w', 's', 'u', 'g'
+# or 'z'. 'w' (or no letter) designates a wall clock time,
+# 's' designates Standard Time in the given zone, and
+# 'u', 'g', and 'z' all designate UTC.
+#
+# Results:
+# Returns a two element list containing a count of seconds from
+# midnight and the letter that followed the time.
+#
+# Side effects:
+# Reports and counts an error if the time cannot be parsed.
+#
+#----------------------------------------------------------------------
+
+proc parseTOD {tod} {
+ if {![regexp -expanded {
+ ^
+ ([[:digit:]]{1,2}) # field 1 - hour
+ (?:
+ :([[:digit:]]{2}) # field 2 - minute
+ (?:
+ :([[:digit:]]{2}) # field 3 - second
+ )?
+ )?
+ (?:
+ ([wsugz]) # field 4 - type indicator
+ )?
+ } $tod -> hour minute second ind]} then {
+ puts stderr "$fileName:$lno:can't parse time field \"$tod\""
+ incr errorCount
+ }
+ scan $hour %d hour
+ if {$minute ne ""} {
+ scan $minute %d minute
+ } else {
+ set minute 0
+ }
+ if {$second ne ""} {
+ scan $second %d second
+ } else {
+ set second 0
+ }
+ if {$ind eq ""} {
+ set ind w
+ }
+ return [list [expr {($hour * 60 + $minute) * 60 + $second}] $ind]
+}
+
+#----------------------------------------------------------------------
+#
+# parseOffsetTime --
+#
+# Parses the specification of an offset time in an Olson file.
+#
+# Parameters:
+# offset - Offset time as [+-]hh:mm:ss
+#
+# Results:
+# Returns the offset time as a count of seconds.
+#
+# Side effects:
+# Reports and counts an error if the time cannot be parsed.
+#
+#----------------------------------------------------------------------
+
+proc parseOffsetTime {offset} {
+ if {![regexp -expanded {
+ ^
+ ([-+])? # field 1 - signum
+ ([[:digit:]]{1,2}) # field 2 - hour
+ (?:
+ :([[:digit:]]{2}) # field 3 - minute
+ (?:
+ :([[:digit:]]{2}) # field 4 - second
+ )?
+ )?
+ } $offset -> signum hour minute second]} then {
+ puts stderr "$fileName:$lno:can't parse offset time \"$offset\""
+ incr errorCount
+ }
+ append signum 1
+ scan $hour %d hour
+ if {$minute ne ""} {
+ scan $minute %d minute
+ } else {
+ set minute 0
+ }
+ if {$second ne ""} {
+ scan $second %d second
+ } else {
+ set second 0
+ }
+ return [expr {(($hour * 60 + $minute) * 60 + $second) * $signum}]
+
+}
+
+#----------------------------------------------------------------------
+#
+# lookupMonth -
+# Looks up a month by name
+#
+# Parameters:
+# month - Name of a month.
+#
+# Results:
+# Returns the number of the month.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc lookupMonth {month} {
+ set indx [lsearch -regexp {
+ {} January February March April May June
+ July August September October November December
+ } ${month}.*]
+ if {$indx < 1} {
+ error "unknown month name \"$month\""
+ }
+ return $indx
+}
+
+#----------------------------------------------------------------------
+#
+# lookupDayOfWeek --
+#
+# Looks up the name of a weekday.
+#
+# Parameters:
+# wday - Weekday name (or a unique prefix).
+#
+# Results:
+# Returns the weekday number (Monday=1, Sunday=7)
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc lookupDayOfWeek {wday} {
+ set indx [lsearch -regexp {
+ {} Monday Tuesday Wednesday Thursday Friday Saturday Sunday
+ } ${wday}.*]
+ if {$indx < 1} {
+ error "unknown weekday name \"$wday\""
+ }
+ return $indx
+}
+
+#----------------------------------------------------------------------
+#
+# parseZone --
+#
+# Parses a Zone directive in an Olson file
+#
+# Parameters:
+# fileName -- Name of the file being parsed.
+# lno -- Line number within the file.
+# zone -- Name of the time zone
+# words -- Remaining words on the line.
+# start -- 'Until' time from the previous line if this is a
+# continuation line, or 'minimum' if this is the first line.
+#
+# Results:
+# Returns the 'until' field of the current line
+#
+# Side effects:
+# Stores a row in the 'zones' array describing the current zone.
+# The row consists of a start time (year month day tod), a Standard
+# Time offset from Greenwich, a Daylight Saving Time offset from
+# Standard Time, and a format for printing the time zone.
+#
+# The start time is the result of an earlier call to 'parseUntil'
+# or else the keyword 'minimum'. The GMT offset is the
+# result of a call to 'parseOffsetTime'. The Daylight Saving
+# Time offset is represented as a partial Tcl command. To the
+# command will be appended a start time (seconds from epoch)
+# the current offset of Standard Time from Greenwich, the current
+# offset of Daylight Saving Time from Greenwich, the default
+# offset from this line, the name pattern from this line,
+# the 'until' field from this line, and a variable name where points
+# are to be stored. This command is implemented by the 'applyNoRule',
+# 'applyDSTOffset' and 'applyRules' procedures.
+#
+#----------------------------------------------------------------------
+
+proc parseZone {fileName lno zone words start} {
+ variable zones
+ variable rules
+ variable errorCount
+ variable forwardRuleRefs
+
+ lassign $words gmtoff save format
+ if {[catch {parseOffsetTime $gmtoff} gmtoff]} {
+ puts stderr "$fileName:$lno:$gmtoff"
+ incr errorCount
+ return
+ }
+ if {[info exists rules($save)]} {
+ set save [list applyRules $save]
+ } elseif {$save eq "-"} {
+ set save [list applyNoRule]
+ } elseif {[catch {parseOffsetTime $save} save2]} {
+ lappend forwardRuleRefs($save) $fileName $lno
+ set save [list applyRules $save]
+ } else {
+ set save [list applyDSTOffset $save2]
+ }
+ lappend zones($zone) $start $gmtoff $save $format
+ if {[llength $words] >= 4} {
+ return [parseUntil [lrange $words 3 end]]
+ } else {
+ return {}
+ }
+}
+
+#----------------------------------------------------------------------
+#
+# parseUntil --
+#
+# Parses the 'UNTIL' part of a 'Zone' directive.
+#
+# Parameters:
+# words - The 'UNTIL' part of the directie.
+#
+# Results:
+# Returns a list comprising the year, the month, the day, and
+# the time of day. Time of day is represented as the result of
+# 'parseTOD'.
+#
+#----------------------------------------------------------------------
+
+proc parseUntil {words} {
+ variable firstYear
+
+ if {[llength $words] >= 1} {
+ set year [lindex $words 0]
+ if {![string is integer $year]} {
+ error "can't parse UNTIL field \"$words\""
+ }
+ if {![info exists firstYear] || $year < $firstYear} {
+ set firstYear $year
+ }
+ } else {
+ set year "maximum"
+ }
+ if {[llength $words] >= 2} {
+ set month [lookupMonth [lindex $words 1]]
+ } else {
+ set month 1
+ }
+ if {[llength $words] >= 3} {
+ set day [parseON [lindex $words 2]]
+ } else {
+ set day {onDayOfMonth 1}
+ }
+ if {[llength $words] >= 4} {
+ set tod [parseTOD [lindex $words 3]]
+ } else {
+ set tod {0 w}
+ }
+ return [list $year $month $day $tod]
+}
+
+#----------------------------------------------------------------------
+#
+# applyNoRule --
+#
+# Generates time zone data for a zone without Daylight Saving
+# Time.
+#
+# Parameters:
+# year - Year in which the rule applies
+# startSecs - Time at which the rule starts.
+# stdGMTOffset - Offset from Greenwich prior to the start of the
+# rule
+# DSTOffset - Offset of Daylight from Standard prior to the
+# start of the rule.
+# nextGMTOffset - Offset from Greenwich when the rule is in effect.
+# namePattern - Name of the timezone.
+# until - Time at which the rule expires.
+# pointsVar - Name of a variable in callers scope that receives
+# transition times
+#
+# Results:
+# Returns a two element list comprising 'nextGMTOffset' and
+# 0 - the zero indicates that Daylight Saving Time is not
+# in effect.
+#
+# Side effects:
+# Appends a row to the 'points' variable comprising the start time,
+# the offset from GMT, a zero (indicating that DST is not in effect),
+# and the name of the time zone.
+#
+#----------------------------------------------------------------------
+
+proc applyNoRule {year startSecs stdGMTOffset DSTOffset nextGMTOffset
+ namePattern until pointsVar} {
+ upvar 1 $pointsVar points
+ lappend points $startSecs $nextGMTOffset 0 \
+ [convertNamePattern $namePattern -]
+ return [list $nextGMTOffset 0]
+}
+
+#----------------------------------------------------------------------
+#
+# applyDSTOffset --
+#
+# Generates time zone data for a zone with permanent Daylight
+# Saving Time.
+#
+# Parameters:
+# nextDSTOffset - Offset of Daylight from Standard while the
+# rule is in effect.
+# year - Year in which the rule applies
+# startSecs - Time at which the rule starts.
+# stdGMTOffset - Offset from Greenwich prior to the start of the
+# rule
+# DSTOffset - Offset of Daylight from Standard prior to the
+# start of the rule.
+# nextGMTOffset - Offset from Greenwich when the rule is in effect.
+# namePattern - Name of the timezone.
+# until - Time at which the rule expires.
+# pointsVar - Name of a variable in callers scope that receives
+# transition times
+#
+# Results:
+# Returns a two element list comprising 'nextGMTOffset' and
+# 'nextDSTOffset'.
+#
+# Side effects:
+# Appends a row to the 'points' variable comprising the start time,
+# the offset from GMT, a one (indicating that DST is in effect),
+# and the name of the time zone.
+#
+#----------------------------------------------------------------------
+
+proc applyDSTOffset {nextDSTOffset year startSecs
+ stdGMTOffset DSTOffset nextGMTOffset
+ namePattern until pointsVar} {
+ upvar 1 $pointsVar points
+ lappend points \
+ $startSecs \
+ [expr {$nextGMTOffset + $nextDSTOffset}] \
+ 1 \
+ [convertNamePattern $namePattern S]
+ return [list $nextGMTOffset $nextDSTOffset]
+}
+
+#----------------------------------------------------------------------
+#
+# applyRules --
+#
+# Applies a rule set to a time zone for a given range of time
+#
+# Parameters:
+# ruleSet - Name of the rule set to apply
+# year - Starting year for the rules
+# startSecs - Time at which the rules begin to apply
+# stdGMTOffset - Offset from Greenwich prior to the start of the
+# rules.
+# DSTOffset - Offset of Daylight from Standard prior to the
+# start of the rules.
+# nextGMTOffset - Offset from Greenwich when the rules are in effect.
+# namePattern - Name pattern for the time zone.
+# until - Time at which the rule set expires.
+# pointsVar - Name of a variable in callers scope that receives
+# transition times
+#
+# Results:
+# Returns a two element list comprising the offset from GMT
+# to Standard and the offset from Standard to Daylight (if DST
+# is in effect) at the end of the period in which the rules apply
+#
+# Side effects:
+# Appends one or more rows to the 'points' variable, each of which
+# comprises a transition time, the offset from GMT that is
+# in effect after the transition, a flag for whether DST is in
+# effect, and the name of the time zone.
+#
+#----------------------------------------------------------------------
+
+proc applyRules {ruleSet year startSecs stdGMTOffset DSTOffset nextGMTOffset
+ namePattern until pointsVar} {
+ variable done
+ variable rules
+ variable maxyear
+
+ upvar 1 $pointsVar points
+
+ # Extract the rules that apply to the current year, and the number
+ # of rules (now or in future) that will end at a specific year.
+ # Ignore rules entirely in the past.
+
+ lassign [divideRules $ruleSet $year] currentRules nSunsetRules
+
+ # If the first transition is later than $startSecs, and $stdGMTOffset is
+ # different from $nextGMTOffset, we will need an initial record like:
+ # lappend points $startSecs $stdGMTOffset 0 \
+ # [convertNamePattern $namePattern -]
+
+ set didTransitionIn false
+
+ # Determine the letter to use in Standard Time
+
+ set prevLetter ""
+ foreach {
+ fromYear toYear yearType monthIn daySpecOn timeAt save letter
+ } $rules($ruleSet) {
+ if {$save == 0} {
+ set prevLetter $letter
+ break
+ }
+ }
+
+ # Walk through each year in turn. This loop will break when
+ # (a) the 'until' time is passed
+ # or (b) the 'until' time is empty and all remaining rules extend to
+ # the end of time
+
+ set stdGMTOffset $nextGMTOffset
+
+ # convert "until" to seconds from epoch in current time zone
+
+ if {$until ne ""} {
+ lassign $until untilYear untilMonth untilDaySpec untilTimeOfDay
+ lappend untilDaySpec $untilYear $untilMonth
+ set untilJCD [eval $untilDaySpec]
+ set untilBaseSecs [expr {
+ wide(86400) * wide($untilJCD) - 210866803200 }]
+ set untilSecs [convertTimeOfDay $untilBaseSecs $stdGMTOffset \
+ $DSTOffset {*}$untilTimeOfDay]
+ }
+
+ set origStartSecs $startSecs
+
+ while {($until ne "" && $startSecs < $untilSecs)
+ || ($until eq "" && ($nSunsetRules > 0 || $year < $maxyear))} {
+ set remainingRules $currentRules
+ while {[llength $remainingRules] > 0} {
+
+ # Find the rule with the earliest start time from among the
+ # active rules that haven't yet been processed.
+
+ lassign [findEarliestRule $remainingRules $year \
+ $stdGMTOffset $DSTOffset] earliestSecs earliestIndex
+
+ set endi [expr {$earliestIndex + 7}]
+ set rule [lrange $remainingRules $earliestIndex $endi]
+ lassign $rule fromYear toYear \
+ yearType monthIn daySpecOn timeAt save letter
+
+ # Test if the rule is in effect.
+
+ if {
+ $earliestSecs > $startSecs &&
+ ($until eq "" || $earliestSecs < $untilSecs)
+ } then {
+ # Test if the initial transition has been done.
+ # If not, do it now.
+
+ if {!$didTransitionIn && $earliestSecs > $origStartSecs} {
+ set nm [convertNamePattern $namePattern $prevLetter]
+ lappend points \
+ $origStartSecs \
+ [expr {$stdGMTOffset + $DSTOffset}] \
+ 0 \
+ $nm
+ set didTransitionIn true
+ }
+
+ # Add a row to 'points' for the rule
+
+ set nm [convertNamePattern $namePattern $letter]
+ lappend points \
+ $earliestSecs \
+ [expr {$stdGMTOffset + $save}] \
+ [expr {$save != 0}] \
+ $nm
+ }
+
+ # Remove the rule just applied from the queue
+
+ set remainingRules [lreplace \
+ $remainingRules[set remainingRules {}] \
+ $earliestIndex $endi]
+
+ # Update current DST offset and time zone letter
+
+ set DSTOffset $save
+ set prevLetter $letter
+
+ # Reconvert the 'until' time in the current zone.
+
+ if {$until ne ""} {
+ set untilSecs [convertTimeOfDay $untilBaseSecs \
+ $stdGMTOffset $DSTOffset {*}$untilTimeOfDay]
+ }
+ }
+
+ # Advance to the next year
+
+ incr year
+ set date [::tcl::clock::GetJulianDayFromEraYearMonthDay \
+ [dict create era CE year $year month 1 dayOfMonth 1] 2361222]
+ set startSecs [expr {
+ [dict get $date julianDay] * wide(86400) - 210866803200
+ - $stdGMTOffset - $DSTOffset
+ }]
+
+ # Get rules in effect in the new year.
+
+ lassign [divideRules $ruleSet $year] currentRules nSunsetRules
+ }
+
+ return [list $stdGMTOffset $DSTOffset]
+}
+
+#----------------------------------------------------------------------
+#
+# divideRules --
+# Determine what Daylight Saving Time rules may be in effect in
+# a given year.
+#
+# Parameters:
+# ruleSet - Set of rules from 'parseRule'
+# year - Year to test
+#
+# Results:
+# Returns a two element list comprising the subset of 'ruleSet'
+# that is in effect in the given year, and the count of rules
+# that expire in the future (as opposed to those that expire in
+# the past or not at all). If this count is zero, the rules do
+# not change in future years.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc divideRules {ruleSet year} {
+ variable rules
+
+ set currentRules {}
+ set nSunsetRules 0
+
+ foreach {
+ fromYear toYear yearType monthIn daySpecOn timeAt save letter
+ } $rules($ruleSet) {
+ if {$toYear ne "maximum" && $year > $toYear} {
+ # ignore - rule is in the past
+ } else {
+ if {$fromYear eq "minimum" || $fromYear <= $year} {
+ lappend currentRules $fromYear $toYear $yearType $monthIn \
+ $daySpecOn $timeAt $save $letter
+ }
+ if {$toYear ne "maximum"} {
+ incr nSunsetRules
+ }
+ }
+ }
+
+ return [list $currentRules $nSunsetRules]
+
+}
+
+#----------------------------------------------------------------------
+#
+# findEarliestRule --
+#
+# Find the rule in a rule set that has the earliest start time.
+#
+# Parameters:
+# remainingRules -- Rules to search
+# year - Year being processed.
+# stdGMTOffset - Current offset of standard time from GMT
+# DSTOffset - Current offset of daylight time from standard,
+# if daylight time is in effect.
+#
+# Results:
+# Returns the index in remainingRules of the next rule to
+# go into effect.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc findEarliestRule {remainingRules year stdGMTOffset DSTOffset} {
+ set earliest $::MAXWIDE
+ set i 0
+ foreach {
+ fromYear toYear yearType monthIn daySpecOn timeAt save letter
+ } $remainingRules {
+ lappend daySpecOn $year $monthIn
+ set dayIn [eval $daySpecOn]
+ set secs [expr {wide(86400) * wide($dayIn) - 210866803200}]
+ set secs [convertTimeOfDay $secs \
+ $stdGMTOffset $DSTOffset {*}$timeAt]
+ if {$secs < $earliest} {
+ set earliest $secs
+ set earliestIdx $i
+ }
+ incr i 8
+ }
+
+ return [list $earliest $earliestIdx]
+}
+
+#----------------------------------------------------------------------
+#
+# convertNamePattern --
+#
+# Converts a name pattern to the name of the time zone.
+#
+# Parameters:
+# pattern - Patthern to convert
+# flag - Daylight Time flag. An empty string denotes Standard
+# Time, anything else is Daylight Time.
+#
+# Results;
+# Returns the name of the time zone.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc convertNamePattern {pattern flag} {
+ if {[regexp {(.*)/(.*)} $pattern -> standard daylight]} {
+ if {$flag ne ""} {
+ set pattern $daylight
+ } else {
+ set pattern $standard
+ }
+ }
+ return [string map [list %s $flag] $pattern]
+}
+
+#----------------------------------------------------------------------
+#
+# convertTimeOfDay --
+#
+# Takes a time of day specifier from 'parseAt' and converts
+# to seconds from the Epoch,
+#
+# Parameters:
+# seconds -- Time at which the GMT day starts, in seconds
+# from the Posix epoch
+# stdGMTOffset - Offset of Standard Time from Greenwich
+# DSTOffset - Offset of Daylight Time from standard.
+# timeOfDay - Time of day to convert, in seconds from midnight
+# flag - Flag indicating whether the time is Greenwich, Standard
+# or wall-clock. (g, s, or w)
+#
+# Results:
+# Returns the time of day in seconds from the Posix epoch.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc convertTimeOfDay {seconds stdGMTOffset DSTOffset timeOfDay flag} {
+ incr seconds $timeOfDay
+ switch -exact $flag {
+ g - u - z {
+ }
+ w {
+ incr seconds [expr {-$stdGMTOffset}]
+ incr seconds [expr {-$DSTOffset}]
+ }
+ s {
+ incr seconds [expr {-$stdGMTOffset}]
+ }
+ }
+ return $seconds
+}
+
+#----------------------------------------------------------------------
+#
+# processTimeZone --
+#
+# Generate the information about all time transitions in a
+# time zone.
+#
+# Parameters:
+# zoneName - Name of the time zone
+# zoneData - List containing the rows describing the time zone,
+# obtained from 'parseZone.
+#
+# Results:
+# Returns a list of rows. Each row consists of a time in
+# seconds from the Posix epoch, an offset from GMT to local
+# that begins at that time, a flag indicating whether DST
+# is in effect after that time, and the printable name of the
+# timezone that goes into effect at that time.
+#
+# Side effects:
+# None.
+#
+#----------------------------------------------------------------------
+
+proc processTimeZone {zoneName zoneData} {
+ set points {}
+ set i 0
+ foreach {startTime nextGMTOffset dstRule namePattern} $zoneData {
+ incr i 4
+ set until [lindex $zoneData $i]
+ if {![info exists stdGMTOffset]} {
+ set stdGMTOffset $nextGMTOffset
+ }
+ if {![info exists DSTOffset]} {
+ set DSTOffset 0
+ }
+ if {$startTime eq "minimum"} {
+ set secs $::MINWIDE
+ set year 0
+ } else {
+ lassign $startTime year month dayRule timeOfDay
+ lappend dayRule $year $month
+ set startDay [eval $dayRule]
+ set secs [expr {wide(86400) * wide($startDay) -210866803200}]
+ set secs [convertTimeOfDay $secs \
+ $stdGMTOffset $DSTOffset {*}$timeOfDay]
+ }
+ lappend dstRule \
+ $year $secs $stdGMTOffset $DSTOffset $nextGMTOffset \
+ $namePattern $until points
+ lassign [eval $dstRule] stdGMTOffset DSTOffset
+ }
+ return $points
+}
+
+#----------------------------------------------------------------------
+#
+# writeZones --
+#
+# Writes all the time zone information files.
+#
+# Parameters:
+# outDir - Directory in which to store the files.
+#
+# Results:
+# None.
+#
+# Side effects:
+# Writes the time zone information files; traces what's happening
+# on the standard output.
+#
+#----------------------------------------------------------------------
+
+proc writeZones {outDir} {
+ variable zones
+
+ # Walk the zones
+
+ foreach zoneName [lsort -dictionary [array names zones]] {
+ puts "calculating: $zoneName"
+ set fileName [eval [list file join $outDir] [file split $zoneName]]
+
+ # Create directories as needed
+
+ set dirName [file dirname $fileName]
+ if {![file exists $dirName]} {
+ puts "creating directory: $dirName"
+ file mkdir $dirName
+ }
+
+ # Generate data for a zone
+
+ set data ""
+ foreach {
+ time offset dst name
+ } [processTimeZone $zoneName $zones($zoneName)] {
+ append data "\n " [list [list $time $offset $dst $name]]
+ }
+ append data \n
+
+ # Write the data to the information file
+
+ set f [open $fileName w]
+ fconfigure $f -translation lf
+ puts $f "\# created by $::argv0 - do not edit"
+ puts $f ""
+ puts $f [list set TZData(:$zoneName) $data]
+ close $f
+ }
+
+ return
+}
+
+#----------------------------------------------------------------------
+#
+# writeLinks --
+#
+# Write files describing time zone synonyms (the Link directives
+# from the Olson files)
+#
+# Parameters:
+# outDir - Name of the directory where the output files go.
+#
+# Results:
+# None.
+#
+# Side effects:
+# Creates a file for each link.
+
+proc writeLinks {outDir} {
+ variable links
+
+ # Walk the links
+
+ foreach zoneName [lsort -dictionary [array names links]] {
+ puts "creating link: $zoneName"
+ set fileName [eval [list file join $outDir] [file split $zoneName]]
+
+ # Create directories as needed
+
+ set dirName [file dirname $fileName]
+ if {![file exists $dirName]} {
+ puts "creating directory: $dirName"
+ file mkdir $dirName
+ }
+
+ # Create code for the synonym
+
+ set linkTo $links($zoneName)
+ set sourceCmd "\n [list LoadTimeZoneFile $linkTo]\n"
+ set ifCmd [list if "!\[info exists TZData($linkTo)\]" $sourceCmd]
+ set setCmd "set TZData(:$zoneName) \$TZData(:$linkTo)"
+
+ # Write the file
+
+ set f [open $fileName w]
+ fconfigure $f -translation lf
+ puts $f "\# created by $::argv0 - do not edit"
+ puts $f $ifCmd
+ puts $f $setCmd
+ close $f
+ }
+
+ return
+}
+
+#----------------------------------------------------------------------
+#
+# MAIN PROGRAM
+#
+#----------------------------------------------------------------------
+
+puts "Compiling time zones -- [clock format [clock seconds] \
+ -format {%x %X} -locale system]"
+
+# Determine directories
+
+lassign $argv inDir outDir
+
+puts "Olson files in $inDir"
+puts "Tcl files to be placed in $outDir"
+
+# Initialize count of errors
+
+set errorCount 0
+
+# Parse the Olson files
+
+loadFiles $inDir
+if {$errorCount > 0} {
+ exit 1
+}
+
+# Check that all riles appearing in Zone and Link lines actually exist
+
+checkForwardRuleRefs
+if {$errorCount > 0} {
+ exit 1
+}
+
+# Write the time zone information files
+
+writeZones $outDir
+writeLinks $outDir
+if {$errorCount > 0} {
+ exit 1
+}
+
+# All done!
+
+exit
diff --git a/tools/tclmin.wse b/tools/tclmin.wse
index 2e7f69b..2fd8185 100644
--- a/tools/tclmin.wse
+++ b/tools/tclmin.wse
@@ -37,12 +37,12 @@ item: Install File
end
item: Install File
Source=n:\dist\tcl8.0\library\http\pkgIndex.tcl
- Destination=%MAINDIR%\lib\tcl%VER%\http2.5\pkgIndex.tcl
+ Destination=%MAINDIR%\lib\tcl%VER%\http2.4\pkgIndex.tcl
Flags=0000000000000010
end
item: Install File
Source=n:\dist\tcl8.0\library\http\http.tcl
- Destination=%MAINDIR%\lib\tcl%VER%\http2.5\http.tcl
+ Destination=%MAINDIR%\lib\tcl%VER%\http2.4\http.tcl
Flags=0000000000000010
end
item: Install File
diff --git a/tools/tcltk-man2html.tcl b/tools/tcltk-man2html.tcl
index ae9d68f..978aa86 100755
--- a/tools/tcltk-man2html.tcl
+++ b/tools/tcltk-man2html.tcl
@@ -2,13 +2,11 @@
# The next line is executed by /bin/sh, but not tcl \
exec tclsh8.4 "$0" ${1+"$@"}
-package require Tcl 8.4
+package require Tcl 8.5
-# Convert Ousterhout format man pages into highly crosslinked
-# hypertext.
+# Convert Ousterhout format man pages into highly crosslinked hypertext.
#
-# Along the way detect many unmatched font changes and other odd
-# things.
+# Along the way detect many unmatched font changes and other odd things.
#
# Note well, this program is a hack rather than a piece of software
# engineering. In that sense it's probably a good example of things
@@ -18,54 +16,10 @@ package require Tcl 8.4
# try to use this, you'll be very much on your own.
#
# Copyright (c) 1995-1997 Roger E. Critchlow Jr
-#
-# The authors hereby grant permission to use, copy, modify, distribute,
-# and license this software and its documentation for any purpose, provided
-# that existing copyright notices are retained in all copies and that this
-# notice is included verbatim in any distributions. No written agreement,
-# license, or royalty fee is required for any of the authorized uses.
-# Modifications to this software may be copyrighted by their authors
-# and need not follow the licensing terms described here, provided that
-# the new terms are clearly indicated on the first page of each file where
-# they apply.
-#
-# IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
-# FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
-# ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
-# DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
-# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
-# IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
-# NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
-# MODIFICATIONS.
-#
-# Revisions:
-# May 15, 1995 - initial release
-# May 16, 1995 - added a back to home link to toplevel table of
-# contents.
-# May 18, 1995 - broke toplevel table of contents into separate
-# pages for each section, and broke long table of contents
-# into a one page for each man page.
-# Mar 10, 1996 - updated for tcl7.5b3/tk4.1b3
-# Apr 14, 1996 - incorporated command line parsing from Tom Tromey,
-# <tromey@creche.cygnus.com> -- thanks Tom.
-# - updated for tcl7.5/tk4.1 final release.
-# - converted to same copyright as the man pages.
-# Sep 14, 1996 - made various modifications for tcl7.6b1/tk4.2b1
-# Oct 18, 1996 - added tcl7.6/tk4.2 to the list of distributions.
-# Oct 22, 1996 - major hacking on indentation code and elsewhere.
-# Mar 4, 1997 -
-# May 28, 1997 - added tcl8.0b1/tk8.0b1 to the list of distributions
-# - cleaned source for tclsh8.0 execution
-# - renamed output files for windoze installation
-# - added spaces to tables
-# Oct 24, 1997 - moved from 8.0b1 to 8.0 release
-#
-set Version "0.32"
+set Version "0.40"
+
+set ::CSSFILE "docs.css"
proc parse_command_line {} {
global argv Version
@@ -82,7 +36,7 @@ proc parse_command_line {} {
set build_tcl 0
set build_tk 0
# Default search version is a glob pattern
- set useversion {{,[8-9].[0-9]{,.[0-9]{,[0-9]}}}}
+ set useversion {{,[8-9].[0-9]{,[.ab][0-9]{,[0-9]}}}}
# Handle arguments a la GNU:
# --version
@@ -140,13 +94,16 @@ proc parse_command_line {} {
}
}
- if {!$build_tcl && !$build_tk} {set build_tcl 1; set build_tk 1}
+ if {!$build_tcl && !$build_tk} {
+ set build_tcl 1;
+ set build_tk 1
+ }
if {$build_tcl} {
# Find Tcl.
set tcldir [lindex [lsort [glob -nocomplain -tails -type d \
- -directory $tcltkdir tcl$useversion]] end]
- if {$tcldir == ""} then {
+ -directory $tcltkdir tcl$useversion]] end]
+ if {$tcldir eq ""} {
puts stderr "tcltk-man-html: couldn't find Tcl below $tcltkdir"
exit 1
}
@@ -157,7 +114,7 @@ proc parse_command_line {} {
# Find Tk.
set tkdir [lindex [lsort [glob -nocomplain -tails -type d \
-directory $tcltkdir tk$useversion]] end]
- if {$tkdir == ""} then {
+ if {$tkdir eq ""} {
puts stderr "tcltk-man-html: couldn't find Tk below $tcltkdir"
exit 1
}
@@ -167,10 +124,16 @@ proc parse_command_line {} {
# the title for the man pages overall
global overall_title
set overall_title ""
- if {$build_tcl} {append overall_title "[capitalize $tcldir]"}
- if {$build_tcl && $build_tk} {append overall_title "/"}
- if {$build_tk} {append overall_title "[capitalize $tkdir]"}
- append overall_title " Manual"
+ if {$build_tcl} {
+ append overall_title "[capitalize $tcldir]"
+ }
+ if {$build_tcl && $build_tk} {
+ append overall_title "/"
+ }
+ if {$build_tk} {
+ append overall_title "[capitalize $tkdir]"
+ }
+ append overall_title " Documentation"
}
proc capitalize {string} {
@@ -186,28 +149,168 @@ proc manerror {msg} {
global manual
set name {}
set subj {}
+ set procname [lindex [info level -1] 0]
if {[info exists manual(name)]} {
set name $manual(name)
}
if {[info exists manual(section)] && [string length $manual(section)]} {
- puts stderr "$name: $manual(section): $msg"
+ puts stderr "$name: $manual(section): $procname: $msg"
} else {
- puts stderr "$name: $msg"
+ puts stderr "$name: $procname: $msg"
}
}
proc manreport {level msg} {
global manual
if {$level < $manual(report-level)} {
- manerror $msg
+ uplevel 1 [list manerror $msg]
}
}
proc fatal {msg} {
global manual
- manerror $msg
+ uplevel 1 [list manerror $msg]
exit 1
}
+
+##
+## templating
+##
+proc indexfile {} {
+ if {[info exists ::TARGET] && $::TARGET eq "devsite"} {
+ return "index.tml"
+ } else {
+ return "contents.htm"
+ }
+}
+proc copyright {copyright {level {}}} {
+ # We don't actually generate a separate copyright page anymore
+ #set page "${level}copyright.htm"
+ #return "<A HREF=\"$page\">Copyright</A> &#169; [htmlize-text [lrange $copyright 2 end]]"
+ # obfuscate any email addresses that may appear in name
+ set who [string map {@ (at)} [lrange $copyright 2 end]]
+ return "Copyright &copy; [htmlize-text $who]"
+}
+proc copyout {copyrights {level {}}} {
+ set out "<div class=\"copy\">"
+ foreach c $copyrights {
+ append out "[copyright $c $level]\n"
+ }
+ append out "</div>"
+ return $out
+}
+proc CSS {{level ""}} {
+ return "<link rel=\"stylesheet\" href=\"${level}$::CSSFILE\" type=\"text/css\" media=\"all\">\n"
+}
+proc DOCTYPE {} {
+ return "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"
+}
+proc htmlhead {title header args} {
+ set level ""
+ if {[lindex $args end] eq "../[indexfile]"} {
+ # XXX hack - assume same level for CSS file
+ set level "../"
+ }
+ set out "[DOCTYPE]\n<HTML>\n<HEAD><TITLE>$title</TITLE>\n[CSS $level]</HEAD>\n"
+ foreach {uptitle url} $args {
+ set header "<a href=\"$url\">$uptitle</a> <small>&gt;</small> $header"
+ }
+ append out "<BODY><H2>$header</H2>"
+ global manual
+ if {[info exists manual(subheader)]} {
+ set subs {}
+ foreach {name subdir} $manual(subheader) {
+ if {$name eq $title} {
+ lappend subs $name
+ } else {
+ lappend subs "<A HREF=\"${level}$subdir/[indexfile]\">$name</A>"
+ }
+ }
+ append out "\n<H3>[join $subs { | }]</H3>"
+ }
+ return $out
+}
+proc gencss {} {
+ set hBd "1px dotted #11577b"
+ return "
+body, div, p, th, td, li, dd, ul, ol, dl, dt, blockquote {
+ font-family: Verdana, sans-serif;
+}
+
+pre, code { font-family: 'Courier New', Courier, monospace; }
+
+pre {
+ background-color: #f6fcec;
+ border-top: 1px solid #6A6A6A;
+ border-bottom: 1px solid #6A6A6A;
+ padding: 1em;
+ overflow: auto;
+}
+
+body {
+ background-color: #FFFFFF;
+ font-size: 12px;
+ line-height: 1.25;
+ letter-spacing: .2px;
+ padding-left: .5em;
+}
+
+h1, h2, h3, h4 {
+ font-family: Georgia, serif;
+ padding-left: 1em;
+ margin-top: 1em;
+}
+
+h1 {
+ font-size: 18px;
+ color: #11577b;
+ border-bottom: $hBd;
+ margin-top: 0px;
+}
+
+h2 {
+ font-size: 14px;
+ color: #11577b;
+ background-color: #c5dce8;
+ padding-left: 1em;
+ border: 1px solid #6A6A6A;
+}
+
+h3, h4 {
+ color: #1674A4;
+ background-color: #e8f2f6;
+ border-bottom: $hBd;
+ border-top: $hBd;
+}
+
+h3 { font-size: 12px; }
+h4 { font-size: 11px; }
+
+.keylist dt, .arguments dt {
+ width: 20em;
+ float: left;
+ padding: 2px;
+ border-top: 1px solid #999;
+}
+
+.keylist dt { font-weight: bold; }
+
+.keylist dd, .arguments dd {
+ margin-left: 20em;
+ padding: 2px;
+ border-top: 1px solid #999;
+}
+
+.copy {
+ background-color: #f6fcfc;
+ white-space: pre;
+ font-size: 80%;
+ border-top: 1px solid #6A6A6A;
+ margin-top: 2em;
+}
+"
+}
+
##
## parsing
##
@@ -216,36 +319,53 @@ proc unquote arg {
}
proc parse-directive {line codename restname} {
- upvar $codename code $restname rest
+ upvar 1 $codename code $restname rest
return [regexp {^(\.[.a-zA-Z0-9]*) *(.*)} $line all code rest]
}
+proc htmlize-text {text {charmap {}}} {
+ # contains some extras for use in nroff->html processing
+ # build on the list passed in, if any
+ lappend charmap \
+ {&} {&amp;} \
+ {\\} "&#92;" \
+ {\e} "&#92;" \
+ {\ } {&nbsp;} \
+ {\|} {&nbsp;} \
+ {\0} { } \
+ \" {&quot;} \
+ {<} {&lt;} \
+ {>} {&gt;} \
+ \u201c "&#8220;" \
+ \u201d "&#8221;"
+
+ return [string map $charmap $text]
+}
+
proc process-text {text} {
global manual
# preprocess text
- set text [string map [list \
- {\&} "\t" \
- {&} {&amp;} \
- {\\} {&#92;} \
- {\e} {&#92;} \
- {\ } {&nbsp;} \
- {\|} {&nbsp;} \
- {\0} { } \
- {\%} {} \
- "\\\n" "\n" \
- \" {&quot;} \
- {<} {&lt;} \
- {>} {&gt;} \
- {\(+-} {&#177;} \
- {\fP} {\fR} \
- {\.} . \
- {\(bu} {&#8226;} \
- ] $text]
- regsub -all {\\o'o\^'} $text {\&ocirc;} text; # o-circumflex in re_syntax.n
- regsub -all {\\-\\\|\\-} $text -- text; # two hyphens
- regsub -all -- {\\-\\\^\\-} $text -- text; # two hyphens
- regsub -all {\\-} $text - text; # a hyphen
- regsub -all "\\\\\n" $text "\\&#92;\n" text; # backslashed newline
+ set charmap [list \
+ {\&} "\t" \
+ {\%} {} \
+ "\\\n" "\n" \
+ {\(+-} "&#177;" \
+ {\(co} "&copy;" \
+ {\(em} "&#8212;" \
+ {\(fm} "&#8242;" \
+ {\(mu} "&#215;" \
+ {\(->} "<font size=\"+1\">&#8594;</font>" \
+ {\fP} {\fR} \
+ {\.} . \
+ {\(bu} "&#8226;" \
+ ]
+ lappend charmap {\o'o^'} {&ocirc;} ; # o-circumflex in re_syntax.n
+ lappend charmap {\-\|\-} -- ; # two hyphens
+ lappend charmap {\-} - ; # a hyphen
+
+ set text [htmlize-text $text $charmap]
+ # General quoted entity
+ regsub -all {\\N'(\d+)'} $text "\\&#\\1;" text
while {[string first "\\" $text] >= 0} {
# C R
if {[regsub {^([^\\]*)\\fC([^\\]*)\\fR(.*)$} $text \
@@ -263,19 +383,21 @@ proc process-text {text} {
if {[regsub {^([^\\]*)\\fI([^\\]*)\\fB(.*)$} $text \
{\1<I>\2</I>\\fB\3} text]} continue
# B B, I I, R R
- if {[regsub {^([^\\]*)\\fB([^\\]*)\\fB(.*)$} $text \
+ if {
+ [regsub {^([^\\]*)\\fB([^\\]*)\\fB(.*)$} $text \
{\1\\fB\2\3} ntext]
|| [regsub {^([^\\]*)\\fI([^\\]*)\\fI(.*)$} $text \
{\1\\fI\2\3} ntext]
|| [regsub {^([^\\]*)\\fR([^\\]*)\\fR(.*)$} $text \
- {\1\\fR\2\3} ntext]} {
- manerror "process-text: impotent font change: $text"
+ {\1\\fR\2\3} ntext]
+ } then {
+ manerror "impotent font change: $text"
set text $ntext
continue
}
# unrecognized
- manerror "process-text: uncaught backslash: $text"
- set text [string map [list "\\" "#92;"] $text]
+ manerror "uncaught backslash: $text"
+ set text [string map [list "\\" "&#92;"] $text]
}
return $text
}
@@ -305,13 +427,13 @@ proc is-a-directive {line} {
return [string match .* $line]
}
proc split-directive {line opname restname} {
- upvar $opname op $restname rest
+ upvar 1 $opname op $restname rest
set op [string range $line 0 2]
set rest [string trim [string range $line 3 end]]
}
proc next-op-is {op restname} {
global manual
- upvar $restname rest
+ upvar 1 $restname rest
if {[more-text]} {
set text [lindex $manual(text) $manual(text-pointer)]
if {[string equal -length 3 $text $op]} {
@@ -342,13 +464,13 @@ proc match-text args {
}
set arg [string trim $arg]
set targ [string trim [lindex $manual(text) $manual(text-pointer)]]
- if {[string equal $arg $targ]} {
+ if {$arg eq $targ} {
incr nback
incr manual(text-pointer)
continue
}
if {[regexp {^@(\w+)$} $arg all name]} {
- upvar $name var
+ upvar 1 $name var
set var $targ
incr nback
incr manual(text-pointer)
@@ -356,7 +478,7 @@ proc match-text args {
}
if {[regexp -nocase {^(\.[A-Z][A-Z])@(\w+)$} $arg all op name]\
&& [string equal $op [lindex $targ 0]]} {
- upvar $name var
+ upvar 1 $name var
set var [lrange $targ 1 end]
incr nback
incr manual(text-pointer)
@@ -393,37 +515,44 @@ proc long-toc {text} {
}
proc option-toc {name class switch} {
global manual
- if {[string equal $manual(section) "WIDGET-SPECIFIC OPTIONS"]} {
- # link the defined option into the long table of contents
- set link [long-toc "$switch, $name, $class"]
- regsub -- "$switch, $name, $class" $link "$switch" link
- return $link
- } elseif {[string equal $manual(name):$manual(section) \
- "options:DESCRIPTION"]} {
- # link the defined standard option to the long table of
- # contents and make a target for the standard option references
- # from other man pages.
- set first [lindex $switch 0]
- set here M$first
- set there L[incr manual(long-toc-n)]
- set manual(standard-option-$first) "<A HREF=\"$manual(name).htm#$here\">$switch, $name, $class</A>"
- lappend manual(section-toc) "<DD><A HREF=\"$manual(name).htm#$here\" NAME=\"$there\">$switch, $name, $class</A>"
- return "<A NAME=\"$here\">$switch</A>"
- } else {
+ if {[string match "*OPTIONS" $manual(section)]} {
+ if {
+ $manual(name) ne "ttk_widget"
+ && $manual(section) ne "WIDGET-SPECIFIC OPTIONS"
+ } then {
+ # link the defined option into the long table of contents
+ set link [long-toc "$switch, $name, $class"]
+ regsub -- "$switch, $name, $class" $link "$switch" link
+ return $link
+ }
+ } elseif {"$manual(name):$manual(section)" ne "options:DESCRIPTION"} {
error "option-toc in $manual(name) section $manual(section)"
}
+
+ # link the defined standard option to the long table of contents and make
+ # a target for the standard option references from other man pages.
+
+ set first [lindex $switch 0]
+ set here M$first
+ set there L[incr manual(long-toc-n)]
+ set manual(standard-option-$manual(name)-$first) \
+ "<A HREF=\"$manual(name).htm#$here\">$switch, $name, $class</A>"
+ lappend manual(section-toc) \
+ "<DD><A HREF=\"$manual(name).htm#$here\" NAME=\"$there\">$switch, $name, $class</A>"
+ return "<A NAME=\"$here\">$switch</A>"
}
-proc std-option-toc {name} {
+proc std-option-toc {name page} {
global manual
- if {[info exists manual(standard-option-$name)]} {
- lappend manual(section-toc) <DD>$manual(standard-option-$name)
- return $manual(standard-option-$name)
+ if {[info exists manual(standard-option-$page-$name)]} {
+ lappend manual(section-toc) <DD>$manual(standard-option-$page-$name)
+ return $manual(standard-option-$page-$name)
}
+ manerror "missing reference to \"$name\" in $page.n"
set here M[incr manual(section-toc-n)]
set there L[incr manual(long-toc-n)]
set other M$name
- lappend manual(section-toc) "<DD><A HREF=\"options.htm#$other\">$name</A>"
- return "<A HREF=\"options.htm#$other\">$name</A>"
+ lappend manual(section-toc) "<DD><A HREF=\"$page.htm#$other\">$name</A>"
+ return "<A HREF=\"$page.htm#$other\">$name</A>"
}
##
## process the widget option section
@@ -436,8 +565,10 @@ proc output-widget-options {rest} {
backup-text 1
set para {}
while {[next-op-is .OP rest]} {
- switch -exact [llength $rest] {
- 3 { foreach {switch name class} $rest { break } }
+ switch -exact -- [llength $rest] {
+ 3 {
+ lassign $rest switch name class
+ }
5 {
set switch [lrange $rest 0 2]
set name [lindex $rest 3]
@@ -447,12 +578,13 @@ proc output-widget-options {rest} {
fatal "bad .OP $rest"
}
}
- if {![regexp {^(<.>)([-\w ]+)(</.>)$} $switch all oswitch switch cswitch]} {
- if {![regexp {^(<.>)([-\w ]+) or ([-\w ]+)(</.>)$} $switch all oswitch switch1 switch2 cswitch]} {
+ if {![regexp {^(<.>)([-\w ]+)(</.>)$} $switch \
+ all oswitch switch cswitch]} {
+ if {![regexp {^(<.>)([-\w ]+) or ([-\w ]+)(</.>)$} $switch \
+ all oswitch switch1 switch2 cswitch]} {
error "not Switch: $switch"
- } else {
- set switch "$switch1$cswitch or $oswitch$switch2"
}
+ set switch "$switch1$cswitch or $oswitch$switch2"
}
if {![regexp {^(<.>)([\w]*)(</.>)$} $name all oname name cname]} {
error "not Name: $name"
@@ -465,6 +597,30 @@ proc output-widget-options {rest} {
man-puts "<DT>Database Class: $oclass$class$cclass"
man-puts <DD>[next-text]
set para <P>
+
+ if {[next-op-is .RS rest]} {
+ while {[more-text]} {
+ set line [next-text]
+ if {[is-a-directive $line]} {
+ split-directive $line code rest
+ switch -exact -- $code {
+ .RE {
+ break
+ }
+ .SH - .SS {
+ manerror "unbalanced .RS at section end"
+ backup-text 1
+ break
+ }
+ default {
+ output-directive $line
+ }
+ }
+ } else {
+ man-puts $line
+ }
+ }
+ }
}
man-puts </DL>
lappend manual(section-toc) </DL>
@@ -494,7 +650,7 @@ proc output-RS-list {} {
set line [next-text]
if {[is-a-directive $line]} {
split-directive $line code rest
- switch -exact $code {
+ switch -exact -- $code {
.RE {
break
}
@@ -510,7 +666,7 @@ proc output-RS-list {} {
} else {
man-puts $line
}
- }
+ }
man-puts </DL>
}
@@ -527,11 +683,11 @@ proc output-IP-list {context code rest} {
set line [next-text]
if {[is-a-directive $line]} {
split-directive $line code rest
- if {[string equal $code ".IP"] && [string equal $rest {}]} {
+ if {$code eq ".IP" && $rest eq {}} {
man-puts "<P>"
continue
}
- if {[lsearch {.br .DS .RS} $code] >= 0} {
+ if {$code in {.br .DS .RS}} {
output-directive $line
} else {
backup-text 1
@@ -544,14 +700,12 @@ proc output-IP-list {context code rest} {
man-puts </DL>
} else {
# labelled list, make contents
- if {
- [string compare $context ".SH"] &&
- [string compare $context ".SS"]
- } then {
+ if {$context ne ".SH" && $context ne ".SS"} {
man-puts <P>
}
- man-puts <DL>
- lappend manual(section-toc) <DL>
+ set dl "<DL class=\"[string tolower $manual(section)]\">"
+ man-puts $dl
+ lappend manual(section-toc) $dl
backup-text 1
set accept_RE 0
set para {}
@@ -559,31 +713,28 @@ proc output-IP-list {context code rest} {
set line [next-text]
if {[is-a-directive $line]} {
split-directive $line code rest
- switch -exact $code {
+ switch -exact -- $code {
.IP {
if {$accept_RE} {
output-IP-list .IP $code $rest
continue
}
- if {[string equal $manual(section) "ARGUMENTS"] || \
+ if {$manual(section) eq "ARGUMENTS" || \
[regexp {^\[\d+\]$} $rest]} {
man-puts "$para<DT>$rest<DD>"
- } elseif {[string equal {&#8226;} $rest]} {
- man-puts "$para<DT><DD>$rest&nbsp;"
+ } elseif {"&#8226;" eq $rest} {
+ man-puts "$para<DT><DD>$rest&nbsp;"
} else {
man-puts "$para<DT>[long-toc $rest]<DD>"
}
- if {[string equal $manual(name):$manual(section) \
- "selection:DESCRIPTION"]} {
+ if {"$manual(name):$manual(section)" eq \
+ "selection:DESCRIPTION"} {
if {[match-text .RE @rest .RS .RS]} {
man-puts <DT>[long-toc $rest]<DD>
}
}
}
- .sp -
- .br -
- .DS -
- .CS {
+ .sp - .br - .DS - .CS {
output-directive $line
}
.RS {
@@ -664,7 +815,7 @@ proc output-name {line} {
# output line to manual page untouched
man-puts $line
# output line to long table of contents
- lappend manual(section-toc) <DL><DD>$line</DL>
+ lappend manual(section-toc) <DL><DD>$line</DD></DL>
# separate out the names for future reference
foreach name [split $head ,] {
set name [string trim $name]
@@ -680,11 +831,11 @@ proc output-name {line} {
##
proc cross-reference {ref} {
global manual
- if {[string match Tcl_* $ref]} {
+ if {[string match "Tcl_*" $ref]} {
set lref $ref
- } elseif {[string match Tk_* $ref]} {
+ } elseif {[string match "Tk_*" $ref]} {
set lref $ref
- } elseif {[string equal $ref "Tcl"]} {
+ } elseif {$ref eq "Tcl"} {
set lref $ref
} else {
set lref [string tolower $ref]
@@ -693,15 +844,17 @@ proc cross-reference {ref} {
## nothing to reference
##
if {![info exists manual(name-$lref)]} {
- foreach name {array file history info interp string trace
- after clipboard grab image option pack place selection tk tkwait update winfo wm} {
+ foreach name {
+ array file history info interp string trace after clipboard grab
+ image option pack place selection tk tkwait update winfo wm
+ } {
if {[regexp "^$name \[a-z0-9]*\$" $lref] && \
[info exists manual(name-$name)] && \
- [string compare $manual(tail) "$name.n"]} {
+ $manual(tail) ne "$name.n"} {
return "<A HREF=\"../$manual(name-$name).htm\">$ref</A>"
}
}
- if {[lsearch {stdin stdout stderr end} $lref] >= 0} {
+ if {$lref in {stdin stdout stderr end}} {
# no good place to send these
# tcl tokens?
# also end
@@ -712,7 +865,7 @@ proc cross-reference {ref} {
## would be a self reference
##
foreach name $manual(name-$lref) {
- if {[lsearch $name $manual(wing-file)/$manual(name)] >= 0} {
+ if {"$manual(wing-file)/$manual(name)" in $name} {
return $ref
}
}
@@ -724,15 +877,15 @@ proc cross-reference {ref} {
set tcl_ref [lindex $manual(name-$lref) $tcl_i]
set tk_i [lsearch -glob $manual(name-$lref) *TkCmd*]
set tk_ref [lindex $manual(name-$lref) $tk_i]
- if {$tcl_i >= 0 && "$manual(wing-file)" == {TclCmd} \
- || "$manual(wing-file)" == {TclLib}} {
+ if {$tcl_i >= 0 && $manual(wing-file) eq "TclCmd"
+ || $manual(wing-file) eq "TclLib"} {
return "<A HREF=\"../$tcl_ref.htm\">$ref</A>"
}
- if {$tk_i >= 0 && "$manual(wing-file)" == {TkCmd} \
- || "$manual(wing-file)" == {TkLib}} {
+ if {$tk_i >= 0 && $manual(wing-file) eq "TkCmd"
+ || $manual(wing-file) eq "TkLib"} {
return "<A HREF=\"../$tk_ref.htm\">$ref</A>"
}
- if {"$lref" == {exit} && "$manual(tail)" == {tclsh.1} && $tcl_i >= 0} {
+ if {$lref eq "exit" && $manual(tail) eq "tclsh.1" && $tcl_i >= 0} {
return "<A HREF=\"../$tcl_ref.htm\">$ref</A>"
}
puts stderr "multiple cross reference to $ref in $manual(name-$lref) from $manual(wing-file)/$manual(tail)"
@@ -741,57 +894,56 @@ proc cross-reference {ref} {
##
## exceptions, sigh, to the rule
##
- switch $manual(tail) {
+ switch -exact -- $manual(tail) {
canvas.n {
- if {$lref == {focus}} {
- upvar tail tail
+ if {$lref eq "focus"} {
+ upvar 1 tail tail
set clue [string first command $tail]
if {$clue < 0 || $clue > 5} {
return $ref
}
}
- if {[lsearch {bitmap image text} $lref] >= 0} {
+ if {$lref in {bitmap image text}} {
return $ref
}
}
- checkbutton.n -
- radiobutton.n {
- if {[lsearch {image} $lref] >= 0} {
+ checkbutton.n - radiobutton.n {
+ if {$lref in {image}} {
return $ref
}
}
menu.n {
- if {[lsearch {checkbutton radiobutton} $lref] >= 0} {
+ if {$lref in {checkbutton radiobutton}} {
return $ref
}
}
options.n {
- if {[lsearch {bitmap image set} $lref] >= 0} {
+ if {$lref in {bitmap image set}} {
return $ref
}
}
regexp.n {
- if {[lsearch {string} $lref] >= 0} {
+ if {$lref in {string}} {
return $ref
}
}
source.n {
- if {[lsearch {text} $lref] >= 0} {
+ if {$lref in {text}} {
return $ref
}
}
history.n {
- if {[lsearch {exec} $lref] >= 0} {
+ if {$lref in {exec}} {
return $ref
}
}
return.n {
- if {[lsearch {error continue break} $lref] >= 0} {
+ if {$lref in {error continue break}} {
return $ref
}
}
scrollbar.n {
- if {[lsearch {set} $lref] >= 0} {
+ if {$lref in {set}} {
return $ref
}
}
@@ -860,7 +1012,7 @@ proc insert-cross-references {text} {
##
## see which we want to use
##
- switch -exact $invert([lindex $offsets 0]) {
+ switch -exact -- $invert([lindex $offsets 0]) {
anchor {
if {$offset(end-anchor) < 0} {
return [reference-error {Missing end anchor} $text]
@@ -873,13 +1025,13 @@ proc insert-cross-references {text} {
if {$offset(end-quote) < 0} {
return [reference-error "Missing end quote" $text]
}
- if {$invert([lindex $offsets 1]) == "tk"} {
+ if {$invert([lindex $offsets 1]) eq "tk"} {
set offsets [lreplace $offsets 1 1]
}
- if {$invert([lindex $offsets 1]) == "tcl"} {
+ if {$invert([lindex $offsets 1]) eq "tcl"} {
set offsets [lreplace $offsets 1 1]
}
- switch -exact $invert([lindex $offsets 1]) {
+ switch -exact -- $invert([lindex $offsets 1]) {
end-quote {
set head [string range $text 0 [expr {$offset(quote)-1}]]
set body [string range $text [expr {$offset(quote)+2}] \
@@ -900,14 +1052,16 @@ proc insert-cross-references {text} {
return [reference-error "Uncaught quote case" $text]
}
bold {
- if {$offset(end-bold) < 0} { return $text }
- if {$invert([lindex $offsets 1]) == "tk"} {
+ if {$offset(end-bold) < 0} {
+ return $text
+ }
+ if {$invert([lindex $offsets 1]) eq "tk"} {
set offsets [lreplace $offsets 1 1]
}
- if {$invert([lindex $offsets 1]) == "tcl"} {
+ if {$invert([lindex $offsets 1]) eq "tcl"} {
set offsets [lreplace $offsets 1 1]
}
- switch -exact $invert([lindex $offsets 1]) {
+ switch -exact -- $invert([lindex $offsets 1]) {
end-bold {
set head [string range $text 0 [expr {$offset(bold)-1}]]
set body [string range $text [expr {$offset(bold)+3}] \
@@ -964,9 +1118,8 @@ proc output-directive {line} {
global manual
# process format directive
split-directive $line code rest
- switch -exact $code {
- .BS -
- .BE {
+ switch -exact -- $code {
+ .BS - .BE {
# man-puts <HR>
}
.SH - .SS {
@@ -976,16 +1129,16 @@ proc output-directive {line} {
# start our own stack of stuff
set manual($manual(name)-$manual(section)) {}
lappend manual(has-$manual(section)) $manual(name)
- if {[string compare .SS $code]} {
+ if {$code ne ".SS"} {
man-puts "<H3>[long-toc $manual(section)]</H3>"
} else {
man-puts "<H4>[long-toc $manual(section)]</H4>"
}
# some sections can simply free wheel their way through the text
# some sections can be processed in their own loops
- switch -exact $manual(section) {
+ switch -exact -- $manual(section) {
NAME {
- if {[lsearch {CrtImgType.3 CrtItemType.3 CrtPhImgFmt.3} $manual(tail)] >= 0} {
+ if {$manual(tail) in {CrtImgType.3 CrtItemType.3 CrtPhImgFmt.3}} {
# these manual pages have two NAME sections
if {[info exists manual($manual(tail)-NAME)]} {
return
@@ -1007,15 +1160,19 @@ proc output-directive {line} {
SYNOPSIS {
lappend manual(section-toc) <DL>
while {1} {
- if {[next-op-is .nf rest]
- || [next-op-is .br rest]
- || [next-op-is .fi rest]} {
+ if {
+ [next-op-is .nf rest]
+ || [next-op-is .br rest]
+ || [next-op-is .fi rest]
+ } then {
continue
}
- if {[next-op-is .SH rest]
- || [next-op-is .SS rest]
- || [next-op-is .BE rest]
- || [next-op-is .SO rest]} {
+ if {
+ [next-op-is .SH rest]
+ || [next-op-is .SS rest]
+ || [next-op-is .BE rest]
+ || [next-op-is .SO rest]
+ } then {
backup-text 1
break
}
@@ -1028,12 +1185,11 @@ proc output-directive {line} {
manerror "in SYNOPSIS found $more"
backup-text 1
break
- } else {
- foreach more [split $more \n] {
- man-puts $more<BR>
- if {[lsearch {TclLib TkLib} $manual(wing-file)] < 0} {
- lappend manual(section-toc) <DD>$more
- }
+ }
+ foreach more [split $more \n] {
+ man-puts $more<BR>
+ if {$manual(wing-file) in {TclLib TkLib}} {
+ lappend manual(section-toc) <DD>$more
}
}
}
@@ -1101,18 +1257,14 @@ proc output-directive {line} {
return
}
.SO {
+ set targetPage $rest
if {[match-text @stuff .SE]} {
output-directive {.SH STANDARD OPTIONS}
- set opts {}
- foreach line [split $stuff \n] {
- foreach option [split $line \t] {
- lappend opts $option
- }
- }
+ set opts [split $stuff \n\t]
man-puts <DL>
lappend manual(section-toc) <DL>
- foreach option [lsort $opts] {
- man-puts "<DT><B>[std-option-toc $option]</B>"
+ foreach option [lsort -dictionary $opts] {
+ man-puts "<DT><B>[std-option-toc $option $targetPage]</B>"
}
man-puts </DL>
lappend manual(section-toc) </DL>
@@ -1149,10 +1301,13 @@ proc output-directive {line} {
}
.DS {
if {[next-op-is .ta rest]} {
-
+ # skip the leading .ta directive if it is there
}
if {[match-text @stuff .DE]} {
- man-puts <PRE>$stuff</PRE>
+ set td "<td><p style=\"font-size:12px;padding-left:.5em;padding-right:.5em;\">"
+ set bodyText [string map [list \n <tr>$td \t $td] \n$stuff]
+ man-puts "<dl><dd><table border=\"0\">$bodyText</table></dl>"
+ #man-puts <PRE>$stuff</PRE>
} elseif {[match-text .fi @ul1 @ul2 .nf @stuff .DE]} {
man-puts "<PRE>[lindex $ul1 1][lindex $ul2 1]\n$stuff</PRE>"
} else {
@@ -1162,7 +1317,7 @@ proc output-directive {line} {
}
.CS {
if {[next-op-is .ta rest]} {
-
+ # ???
}
if {[match-text @stuff .CE]} {
man-puts <PRE>$stuff</PRE>
@@ -1180,7 +1335,7 @@ proc output-directive {line} {
}
.ta {
# these are tab stop settings for short tables
- switch -exact $manual(name):$manual(section) {
+ switch -exact -- $manual(name):$manual(section) {
{bind:MODIFIERS} -
{bind:EVENT TYPES} -
{bind:BINDING SCRIPTS AND SUBSTITUTIONS} -
@@ -1188,7 +1343,6 @@ proc output-directive {line} {
{expr:MATH FUNCTIONS} -
{history:DESCRIPTION} -
{history:HISTORY REVISION} -
- {re_syntax:BRACKET EXPRESSIONS} -
{switch:DESCRIPTION} -
{upvar:DESCRIPTION} {
return; # fix.me
@@ -1271,32 +1425,38 @@ proc output-directive {line} {
## merge copyright listings
##
proc merge-copyrights {l1 l2} {
+ set merge {}
+ set re1 {^Copyright +(?:\(c\)|\\\(co|&copy;) +(\w.*?)(?:all rights reserved)?(?:\. )*$}
+ set re2 {^(\d+) +(?:by +)?(\w.*)$} ;# date who
+ set re3 {^(\d+)-(\d+) +(?:by +)?(\w.*)$} ;# from to who
+ set re4 {^(\d+), *(\d+) +(?:by +)?(\w.*)$} ;# date1 date2 who
foreach copyright [concat $l1 $l2] {
- if {[regexp {^Copyright +\(c\) +(\d+) +(by +)?(\w.*)$} $copyright all date by who]} {
- lappend dates($who) $date
- continue
- }
- if {[regexp {^Copyright +\(c\) +(\d+)-(\d+) +(by +)?(\w.*)$} $copyright all from to by who]} {
- for {set date $from} {$date <= $to} {incr date} {
+ if {[regexp -nocase -- $re1 $copyright -> info]} {
+ set info [string trimright $info ". "] ; # remove extra period
+ if {[regexp -- $re2 $info -> date who]} {
lappend dates($who) $date
+ continue
+ } elseif {[regexp -- $re3 $info -> from to who]} {
+ for {set date $from} {$date <= $to} {incr date} {
+ lappend dates($who) $date
+ }
+ continue
+ } elseif {[regexp -- $re3 $info -> date1 date2 who]} {
+ lappend dates($who) $date1 $date2
+ continue
}
- continue
- }
- if {[regexp {^Copyright +\(c\) +(\d+), *(\d+) +(by +)?(\w.*)$} $copyright all date1 date2 by who]} {
- lappend dates($who) $date1 $date2
- continue
}
puts "oops: $copyright"
}
foreach who [array names dates] {
- set list [lsort $dates($who)]
- if {[llength $list] == 1 || [lindex $list 0] == [lrange $list end end]} {
- lappend merge "Copyright (c) [lindex $list 0] $who"
+ set list [lsort -dictionary $dates($who)]
+ if {[llength $list] == 1 || [lindex $list 0] eq [lrange $list end end]} {
+ lappend merge "Copyright &copy; [lindex $list 0] $who"
} else {
- lappend merge "Copyright (c) [lindex $list 0]-[lrange $list end end] $who"
+ lappend merge "Copyright &copy; [lindex $list 0]-[lrange $list end end] $who"
}
}
- return [lsort $merge]
+ return [lsort -dictionary $merge]
}
proc makedirhier {dir} {
@@ -1306,35 +1466,64 @@ proc makedirhier {dir} {
}
}
+proc addbuffer {args} {
+ global manual
+ if {$manual(partial-text) ne ""} {
+ append manual(partial-text) \n
+ }
+ append manual(partial-text) [join $args ""]
+}
+proc flushbuffer {} {
+ global manual
+ if {$manual(partial-text) ne ""} {
+ lappend manual(text) [process-text $manual(partial-text)]
+ set manual(partial-text) ""
+ }
+}
+
##
## foreach of the man directories specified by args
## convert manpages into hypertext in the directory
## specified by html.
##
proc make-man-pages {html args} {
- global env manual overall_title tcltkdesc
+ global manual overall_title tcltkdesc
makedirhier $html
+ set cssfd [open $html/$::CSSFILE w]
+ puts $cssfd [gencss]
+ close $cssfd
set manual(short-toc-n) 1
- set manual(short-toc-fp) [open $html/contents.htm w]
- puts $manual(short-toc-fp) "<HTML><HEAD><TITLE>$overall_title</TITLE></HEAD>"
- puts $manual(short-toc-fp) "<BODY><HR><H3>$overall_title</H3><HR><DL>"
+ set manual(short-toc-fp) [open $html/[indexfile] w]
+ puts $manual(short-toc-fp) [htmlhead $overall_title $overall_title]
+ puts $manual(short-toc-fp) "<DL class=\"keylist\">"
set manual(merge-copyrights) {}
foreach arg $args {
- if {$arg == ""} {continue}
+ # preprocess to set up subheader for the rest of the files
+ if {![llength $arg]} {
+ continue
+ }
+ set name [lindex $arg 1]
+ set file [lindex $arg 2]
+ lappend manual(subheader) $name $file
+ }
+ foreach arg $args {
+ if {![llength $arg]} {
+ continue
+ }
set manual(wing-glob) [lindex $arg 0]
set manual(wing-name) [lindex $arg 1]
set manual(wing-file) [lindex $arg 2]
set manual(wing-description) [lindex $arg 3]
set manual(wing-copyrights) {}
makedirhier $html/$manual(wing-file)
- set manual(wing-toc-fp) [open $html/$manual(wing-file)/contents.htm w]
+ set manual(wing-toc-fp) [open $html/$manual(wing-file)/[indexfile] w]
# whistle
puts stderr "scanning section $manual(wing-name)"
# put the entry for this section into the short table of contents
- puts $manual(short-toc-fp) "<DT><A HREF=\"$manual(wing-file)/contents.htm\">$manual(wing-name)</A><DD>$manual(wing-description)"
+ puts $manual(short-toc-fp) "<DT><A HREF=\"$manual(wing-file)/[indexfile]\">$manual(wing-name)</A></DT><DD>$manual(wing-description)</DD>"
# initialize the wing table of contents
- puts $manual(wing-toc-fp) "<HTML><HEAD><TITLE>$manual(wing-name) Manual</TITLE></HEAD>"
- puts $manual(wing-toc-fp) "<BODY><HR><H3>$manual(wing-name)</H3><HR>"
+ puts $manual(wing-toc-fp) [htmlhead $manual(wing-name) \
+ $manual(wing-name) $overall_title "../[indexfile]"]
# initialize the short table of contents for this section
set manual(wing-toc) {}
# initialize the man directory for this section
@@ -1342,19 +1531,26 @@ proc make-man-pages {html args} {
# initialize the long table of contents for this section
set manual(long-toc-n) 1
# get the manual pages for this section
- set manual(pages) [lsort [glob $manual(wing-glob)]]
- if {[lsearch -glob $manual(pages) */options.n] >= 0} {
- set n [lsearch $manual(pages) */options.n]
+ set manual(pages) [lsort -dictionary [glob $manual(wing-glob)]]
+ set n [lsearch -glob $manual(pages) */ttk_widget.n]
+ if {$n >= 0} {
+ set manual(pages) "[lindex $manual(pages) $n] [lreplace $manual(pages) $n $n]"
+ }
+ set n [lsearch -glob $manual(pages) */options.n]
+ if {$n >= 0} {
set manual(pages) "[lindex $manual(pages) $n] [lreplace $manual(pages) $n $n]"
}
# set manual(pages) [lrange $manual(pages) 0 5]
- foreach manual(page) $manual(pages) {
+ set LQ \u201c
+ set RQ \u201d
+ foreach manual_page $manual(pages) {
+ set manual(page) $manual_page
# whistle
puts stderr "scanning page $manual(page)"
set manual(tail) [file tail $manual(page)]
set manual(name) [file root $manual(tail)]
set manual(section) {}
- if {[lsearch {case pack-old menubar} $manual(name)] >= 0} {
+ if {$manual(name) in {case pack-old menubar}} {
# obsolete
manerror "discarding $manual(name)"
continue
@@ -1370,140 +1566,167 @@ proc make-man-pages {html args} {
set manual(section-toc) {}
set manual(section-toc-n) 1
set manual(copyrights) {}
+ lappend manual(copyrights) "Copyright &copy; 1995-1997 Roger E. Critchlow Jr."
lappend manual(all-pages) $manual(wing-file)/$manual(tail)
manreport 100 $manual(name)
while {[gets $manual(infp) line] >= 0} {
manreport 100 $line
if {[regexp {^[`'][/\\]} $line]} {
- if {[regexp {Copyright \(c\).*$} $line copyright]} {
+ if {[regexp {Copyright (?:\(c\)|\\\(co).*$} $line copyright]} {
lappend manual(copyrights) $copyright
}
# comment
continue
}
- if {"$line" == {'}} {
+ if {"$line" eq {'}} {
# comment
continue
}
- if {[parse-directive $line code rest]} {
- switch -exact $code {
- .ad - .na - .so - .ne - .AS - .VE - .VS -
- . {
- # ignore
- continue
+ if {![parse-directive $line code rest]} {
+ addbuffer $line
+ continue
+ }
+ switch -exact -- $code {
+ .ad - .na - .so - .ne - .AS - .VE - .VS - . {
+ # ignore
+ continue
+ }
+ }
+ switch -exact -- $code {
+ .SH - .SS {
+ flushbuffer
+ if {[llength $rest] == 0} {
+ gets $manual(infp) rest
}
+ lappend manual(text) "$code [unquote $rest]"
}
- if {"$manual(partial-text)" != {}} {
- lappend manual(text) [process-text $manual(partial-text)]
- set manual(partial-text) {}
+ .TH {
+ flushbuffer
+ lappend manual(text) "$code [unquote $rest]"
}
- switch -exact $code {
- .SH - .SS {
- if {[llength $rest] == 0} {
- gets $manual(infp) rest
- }
- lappend manual(text) "$code [unquote $rest]"
- }
- .TH {
- lappend manual(text) "$code [unquote $rest]"
- }
- .HS - .UL -
- .ta {
- lappend manual(text) "$code [unquote $rest]"
- }
- .BS - .BE - .br - .fi - .sp -
- .nf {
- if {"$rest" != {}} {
- manerror "unexpected argument: $line"
- }
- lappend manual(text) $code
- }
- .AP {
- lappend manual(text) [concat .IP [process-text "[lindex $rest 0] \\fB[lindex $rest 1]\\fR ([lindex $rest 2])"]]
- }
- .IP {
- regexp {^(.*) +\d+$} $rest all rest
- lappend manual(text) ".IP [process-text [unquote [string trim $rest]]]"
- }
- .TP {
- while {[is-a-directive [set next [gets $manual(infp)]]]} {
- manerror "ignoring $next after .TP"
- }
- if {"$next" != {'}} {
- lappend manual(text) ".IP [process-text $next]"
- }
- }
- .OP {
- lappend manual(text) [concat .OP [process-text \
- "\\fB[lindex $rest 0]\\fR \\fB[lindex $rest 1]\\fR \\fB[lindex $rest 2]\\fR"]]
- }
- .PP -
- .LP {
- lappend manual(text) {.PP}
- }
- .RS {
- incr manual(.RS)
- lappend manual(text) $code
- }
- .RE {
- incr manual(.RS) -1
- lappend manual(text) $code
- }
- .SO {
- incr manual(.SO)
- lappend manual(text) $code
- }
- .SE {
- incr manual(.SO) -1
- lappend manual(text) $code
- }
- .DS {
- incr manual(.DS)
- lappend manual(text) $code
+ .QW {
+ set rest [regexp -all -inline {\"(?:[^""]+)\"|\S+} $rest]
+ addbuffer $LQ [unquote [lindex $rest 0]] $RQ \
+ [unquote [lindex $rest 1]]
+ }
+ .PQ {
+ set rest [regexp -all -inline {\"(?:[^""]+)\"|\S+} $rest]
+ addbuffer ( $LQ [unquote [lindex $rest 0]] $RQ \
+ [unquote [lindex $rest 1]] ) \
+ [unquote [lindex $rest 2]]
+ }
+ .QR {
+ set rest [regexp -all -inline {\"(?:[^""]+)\"|\S+} $rest]
+ addbuffer $LQ [unquote [lindex $rest 0]] - \
+ [unquote [lindex $rest 1]] $RQ \
+ [unquote [lindex $rest 2]]
+ }
+ .MT {
+ addbuffer $LQ$RQ
+ }
+ .HS - .UL - .ta {
+ flushbuffer
+ lappend manual(text) "$code [unquote $rest]"
+ }
+ .BS - .BE - .br - .fi - .sp - .nf {
+ flushbuffer
+ if {"$rest" ne {}} {
+ manerror "unexpected argument: $line"
}
- .DE {
- incr manual(.DS) -1
- lappend manual(text) $code
+ lappend manual(text) $code
+ }
+ .AP {
+ flushbuffer
+ lappend manual(text) [concat .IP [process-text "[lindex $rest 0] \\fB[lindex $rest 1]\\fR ([lindex $rest 2])"]]
+ }
+ .IP {
+ flushbuffer
+ regexp {^(.*) +\d+$} $rest all rest
+ lappend manual(text) ".IP [process-text [unquote [string trim $rest]]]"
+ }
+ .TP {
+ flushbuffer
+ while {[is-a-directive [set next [gets $manual(infp)]]]} {
+ manerror "ignoring $next after .TP"
}
- .CS {
- incr manual(.CS)
- lappend manual(text) $code
+ if {"$next" ne {'}} {
+ lappend manual(text) ".IP [process-text $next]"
}
- .CE {
- incr manual(.CS) -1
- lappend manual(text) $code
+ }
+ .OP {
+ flushbuffer
+ lappend manual(text) [concat .OP [process-text \
+ "\\fB[lindex $rest 0]\\fR \\fB[lindex $rest 1]\\fR \\fB[lindex $rest 2]\\fR"]]
+ }
+ .PP - .LP {
+ flushbuffer
+ lappend manual(text) {.PP}
+ }
+ .RS {
+ flushbuffer
+ incr manual(.RS)
+ lappend manual(text) $code
+ }
+ .RE {
+ flushbuffer
+ incr manual(.RS) -1
+ lappend manual(text) $code
+ }
+ .SO {
+ flushbuffer
+ incr manual(.SO)
+ if {[llength $rest] == 0} {
+ lappend manual(text) "$code options"
+ } else {
+ lappend manual(text) "$code [unquote $rest]"
}
- .de {
- while {[gets $manual(infp) line] >= 0} {
- if {[string match "..*" $line]} {
- break
- }
+ }
+ .SE {
+ flushbuffer
+ incr manual(.SO) -1
+ lappend manual(text) $code
+ }
+ .DS {
+ flushbuffer
+ incr manual(.DS)
+ lappend manual(text) $code
+ }
+ .DE {
+ flushbuffer
+ incr manual(.DS) -1
+ lappend manual(text) $code
+ }
+ .CS {
+ flushbuffer
+ incr manual(.CS)
+ lappend manual(text) $code
+ }
+ .CE {
+ flushbuffer
+ incr manual(.CS) -1
+ lappend manual(text) $code
+ }
+ .de {
+ while {[gets $manual(infp) line] >= 0} {
+ if {[string match "..*" $line]} {
+ break
}
}
- .. {
- error "found .. outside of .de"
- }
- default {
- manerror "unrecognized format directive: $line"
- }
}
- } else {
- if {$manual(partial-text) == ""} {
- set manual(partial-text) $line
- } else {
- append manual(partial-text) \n$line
+ .. {
+ error "found .. outside of .de"
+ }
+ default {
+ flushbuffer
+ manerror "unrecognized format directive: $line"
}
}
}
- if {$manual(partial-text) != ""} {
- lappend manual(text) [process-text $manual(partial-text)]
- }
+ flushbuffer
close $manual(infp)
# fixups
if {$manual(.RS) != 0} {
- if {$manual(name) != "selection"} {
- puts "unbalanced .RS .RE"
- }
+ puts "unbalanced .RS .RE"
}
if {$manual(.DS) != 0} {
puts "unbalanced .DS .DE"
@@ -1516,25 +1739,17 @@ proc make-man-pages {html args} {
}
# output conversion
open-text
+ set haserror 0
if {[next-op-is .HS rest]} {
set manual($manual(name)-title) \
"[lrange $rest 1 end] [lindex $rest 0] manual page"
- while {[more-text]} {
- set line [next-text]
- if {[is-a-directive $line]} {
- output-directive $line
- } else {
- man-puts $line
- }
- }
- man-puts <HR><PRE>
- foreach copyright $manual(copyrights) {
- man-puts "<A HREF=\"../copyright.htm\">Copyright</A> &#169; [lrange $copyright 2 end]"
- }
- man-puts "<A HREF=\"../copyright.htm\">Copyright</A> &#169; 1995-1997 Roger E. Critchlow Jr.</PRE>"
- set manual(wing-copyrights) [merge-copyrights $manual(wing-copyrights) $manual(copyrights)]
} elseif {[next-op-is .TH rest]} {
- set manual($manual(name)-title) "[lrange $rest 4 end] - [lindex $rest 0] manual page"
+ set manual($manual(name)-title) "[lindex $rest 0] manual page - [lrange $rest 4 end]"
+ } else {
+ set haserror 1
+ manerror "no .HS or .TH record found"
+ }
+ if {!$haserror} {
while {[more-text]} {
set line [next-text]
if {[is-a-directive $line]} {
@@ -1543,19 +1758,13 @@ proc make-man-pages {html args} {
man-puts $line
}
}
- man-puts <HR><PRE>
- foreach copyright $manual(copyrights) {
- man-puts "<A HREF=\"../copyright.htm\">Copyright</A> &#169; [lrange $copyright 2 end]"
- }
- man-puts "<A HREF=\"../copyright.htm\">Copyright</A> &#169; 1995-1997 Roger E. Critchlow Jr.</PRE>"
+ man-puts [copyout $manual(copyrights) "../"]
set manual(wing-copyrights) [merge-copyrights $manual(wing-copyrights) $manual(copyrights)]
- } else {
- manerror "no .HS or .TH record found"
}
#
# make the long table of contents for this page
#
- set manual(toc-$manual(wing-file)-$manual(name)) [concat <DL> $manual(section-toc) </DL><HR>]
+ set manual(toc-$manual(wing-file)-$manual(name)) [concat <DL> $manual(section-toc) </DL>]
}
#
@@ -1571,7 +1780,7 @@ proc make-man-pages {html args} {
set nrows [expr {([llength $manual(wing-toc)]+$perline)/$perline}]
set n 0
catch {unset rows}
- foreach name [lsort $manual(wing-toc)] {
+ foreach name [lsort -dictionary $manual(wing-toc)] {
set tail $manual(name-$name)
if {[llength $tail] > 1} {
manerror "$name is defined in more than one file: $tail"
@@ -1591,12 +1800,8 @@ proc make-man-pages {html args} {
#
# insert wing copyrights
#
- puts $manual(wing-toc-fp) "<HR><PRE>"
- foreach copyright $manual(wing-copyrights) {
- puts $manual(wing-toc-fp) "<A HREF=\"../copyright.htm\">Copyright</A> &#169; [lrange $copyright 2 end]"
- }
- puts $manual(wing-toc-fp) "<A HREF=\"../copyright.htm\">Copyright</A> &#169; 1995-1997 Roger E. Critchlow Jr."
- puts $manual(wing-toc-fp) "</PRE></BODY></HTML>"
+ puts $manual(wing-toc-fp) [copyout $manual(wing-copyrights) "../"]
+ puts $manual(wing-toc-fp) "</BODY></HTML>"
close $manual(wing-toc-fp)
set manual(merge-copyrights) [merge-copyrights $manual(merge-copyrights) $manual(wing-copyrights)]
}
@@ -1604,66 +1809,68 @@ proc make-man-pages {html args} {
##
## build the keyword index.
##
- proc strcasecmp {a b} { return [string compare -nocase $a $b] }
- set keys [lsort -command strcasecmp [array names manual keyword-*]]
+ file delete -force -- $html/Keywords
makedirhier $html/Keywords
- catch {eval file delete -- [glob $html/Keywords/*]}
- puts $manual(short-toc-fp) "<DT><A HREF=\"Keywords/contents.htm\">Keywords</A><DD>The keywords from the $tcltkdesc man pages."
- set keyfp [open $html/Keywords/contents.htm w]
- puts $keyfp "<HTML><HEAD><TITLE>$tcltkdesc Keywords</TITLE></HEAD>"
- puts $keyfp "<BODY><HR><H3>$tcltkdesc Keywords</H3><HR><H2>"
- foreach a {A B C D E F G H I J K L M N O P Q R S T U V W X Y Z} {
- puts $keyfp "<A HREF=\"$a.htm\">$a</A>"
+ set keyfp [open $html/Keywords/[indexfile] w]
+ puts $keyfp [htmlhead "$tcltkdesc Keywords" "$tcltkdesc Keywords" \
+ $overall_title "../[indexfile]"]
+ set letters {A B C D E F G H I J K L M N O P Q R S T U V W X Y Z}
+ # Create header first
+ set keyheader {}
+ foreach a $letters {
+ set keys [array names manual "keyword-\[[string totitle $a$a]\]*"]
+ if {[llength $keys]} {
+ lappend keyheader "<A HREF=\"$a.htm\">$a</A>"
+ } else {
+ # No keywords for this letter
+ lappend keyheader $a
+ }
+ }
+ set keyheader "<H3>[join $keyheader " |\n"]</H3>"
+ puts $keyfp $keyheader
+ foreach a $letters {
+ set keys [array names manual "keyword-\[[string totitle $a$a]\]*"]
+ if {![llength $keys]} {
+ continue
+ }
+ # Per-keyword page
set afp [open $html/Keywords/$a.htm w]
- puts $afp "<HTML><HEAD><TITLE>$tcltkdesc Keywords - $a</TITLE></HEAD>"
- puts $afp "<BODY><HR><H3>$tcltkdesc Keywords - $a</H3><HR><H2>"
- foreach b {A B C D E F G H I J K L M N O P Q R S T U V W X Y Z} {
- puts $afp "<A HREF=\"$b.htm\">$b</A>"
- }
- puts $afp "</H2><HR><DL>"
- foreach k $keys {
- if {[string match -nocase "keyword-${a}*" $k]} {
- set k [string range $k 8 end]
- puts $afp "<DT><A NAME=\"$k\">$k</A><DD>"
- set refs {}
- foreach man $manual(keyword-$k) {
- set name [lindex $man 0]
- set file [lindex $man 1]
- lappend refs "<A HREF=\"../$file\">$name</A>"
- }
- puts $afp [join $refs {, }]
+ puts $afp [htmlhead "$tcltkdesc Keywords - $a" \
+ "$tcltkdesc Keywords - $a" \
+ $overall_title "../[indexfile]"]
+ puts $afp $keyheader
+ puts $afp "<DL class=\"keylist\">"
+ foreach k [lsort -dictionary $keys] {
+ set k [string range $k 8 end]
+ puts $afp "<DT><A NAME=\"$k\">$k</A></DT>"
+ puts $afp "<DD>"
+ set refs {}
+ foreach man $manual(keyword-$k) {
+ set name [lindex $man 0]
+ set file [lindex $man 1]
+ lappend refs "<A HREF=\"../$file\">$name</A>"
}
+ puts $afp "[join $refs {, }]</DD>"
}
- puts $afp "</DL><HR><PRE>"
+ puts $afp "</DL>"
# insert merged copyrights
- foreach copyright $manual(merge-copyrights) {
- puts $afp "<A HREF=\"copyright.htm\">Copyright</A> &#169; [lrange $copyright 2 end]"
- }
- puts $afp "<A HREF=\"copyright.htm\">Copyright</A> &#169; 1995-1997 Roger E. Critchlow Jr."
- puts $afp "</PRE></BODY></HTML>"
+ puts $afp [copyout $manual(merge-copyrights)]
+ puts $afp "</BODY></HTML>"
close $afp
}
- puts $keyfp "</H2><HR><PRE>"
-
# insert merged copyrights
- foreach copyright $manual(merge-copyrights) {
- puts $keyfp "<A HREF=\"copyright.htm\">Copyright</A> &#169; [lrange $copyright 2 end]"
- }
- puts $keyfp "<A HREF=\"copyright.htm\">Copyright</A> &#169; 1995-1997 Roger E. Critchlow Jr."
- puts $keyfp </PRE><HR></BODY></HTML>
+ puts $keyfp [copyout $manual(merge-copyrights)]
+ puts $keyfp "</BODY></HTML>"
close $keyfp
##
## finish off short table of contents
##
- puts $manual(short-toc-fp) {<DT><A HREF="http://www.elf.org">Source</A><DD>More information about these man pages.}
- puts $manual(short-toc-fp) "</DL><HR><PRE>"
+ puts $manual(short-toc-fp) "<DT><A HREF=\"Keywords/[indexfile]\">Keywords</A><DD>The keywords from the $tcltkdesc man pages."
+ puts $manual(short-toc-fp) "</DL>"
# insert merged copyrights
- foreach copyright $manual(merge-copyrights) {
- puts $manual(short-toc-fp) "<A HREF=\"copyright.htm\">Copyright</A> &#169; [lrange $copyright 2 end]"
- }
- puts $manual(short-toc-fp) "<A HREF=\"copyright.htm\">Copyright</A> &#169; 1995-1997 Roger E. Critchlow Jr."
- puts $manual(short-toc-fp) "</PRE></BODY></HTML>"
+ puts $manual(short-toc-fp) [copyout $manual(merge-copyrights)]
+ puts $manual(short-toc-fp) "</BODY></HTML>"
close $manual(short-toc-fp)
##
@@ -1687,22 +1894,26 @@ proc make-man-pages {html args} {
incr ntoc
}
puts stderr "rescanning page $manual(name) $ntoc/$ntext"
- set manual(outfp) [open $html/$manual(wing-file)/$manual(name).htm w]
- puts $manual(outfp) "<HTML><HEAD><TITLE>$manual($manual(name)-title)</TITLE></HEAD><BODY>"
- if {($ntext > 60) && ($ntoc > 32) || [lsearch {
- Hash LinkVar SetVar TraceVar ConfigWidg CrtImgType CrtItemType
- CrtPhImgFmt DoOneEvent GetBitmap GetColor GetCursor GetDash
- GetJustify GetPixels GetVisual ParseArgv QueueEvent
- } $manual(tail)] >= 0} {
+ set outfd [open $html/$manual(wing-file)/$manual(name).htm w]
+ puts $outfd [htmlhead "$manual($manual(name)-title)" \
+ $manual(name) $manual(wing-file) "[indexfile]" \
+ $overall_title "../[indexfile]"]
+ if {
+ (($ntext > 60) && ($ntoc > 32)) || $manual(tail) in {
+ Hash LinkVar SetVar TraceVar ConfigWidg CrtImgType CrtItemType
+ CrtPhImgFmt DoOneEvent GetBitmap GetColor GetCursor GetDash
+ GetJustify GetPixels GetVisual ParseArgv QueueEvent
+ }
+ } then {
foreach item $toc {
- puts $manual(outfp) $item
+ puts $outfd $item
}
}
foreach item $text {
- puts $manual(outfp) [insert-cross-references $item]
+ puts $outfd [insert-cross-references $item]
}
- puts $manual(outfp) </BODY></HTML>
- close $manual(outfp)
+ puts $outfd "</BODY></HTML>"
+ close $outfd
}
return {}
}
@@ -1710,16 +1921,28 @@ proc make-man-pages {html args} {
parse_command_line
set tcltkdesc ""; set cmdesc ""; set appdir ""
-if {$build_tcl} {append tcltkdesc "Tcl"; append cmdesc "Tcl"; append appdir "$tcldir"}
-if {$build_tcl && $build_tk} {append tcltkdesc "/"; append cmdesc " and "; append appdir ","}
-if {$build_tk} {append tcltkdesc "Tk"; append cmdesc "Tk"; append appdir "$tkdir"}
+if {$build_tcl} {
+ append tcltkdesc "Tcl"
+ append cmdesc "Tcl"
+ append appdir "$tcldir"
+}
+if {$build_tcl && $build_tk} {
+ append tcltkdesc "/"
+ append cmdesc " and "
+ append appdir ","
+}
+if {$build_tk} {
+ append tcltkdesc "Tk"
+ append cmdesc "Tk"
+ append appdir "$tkdir"
+}
set usercmddesc "The interpreters which implement $cmdesc."
set tclcmddesc {The commands which the <B>tclsh</B> interpreter implements.}
set tkcmddesc {The additional commands which the <B>wish</B> interpreter implements.}
set tcllibdesc {The C functions which a Tcl extended C program may use.}
set tklibdesc {The additional C functions which a Tk extended C program may use.}
-
+
if {1} {
if {[catch {
make-man-pages $webdir \
diff --git a/tools/uniClass.tcl b/tools/uniClass.tcl
index 9f30721..9a1bf13 100644
--- a/tools/uniClass.tcl
+++ b/tools/uniClass.tcl
@@ -65,13 +65,13 @@ proc genTable {type} {
set ranges [string trimright $ranges "\t\n ,"]
set chars [string trimright $chars "\t\n ,"]
if {$ranges ne ""} {
- puts "static CONST crange ${type}RangeTable\[\] = {\n$ranges\n};\n"
+ puts "static const crange ${type}RangeTable\[\] = {\n$ranges\n};\n"
puts "#define NUM_[string toupper $type]_RANGE (sizeof(${type}RangeTable)/sizeof(crange))\n"
} else {
puts "/* no contiguous ranges of $type characters */\n"
}
if {$chars ne ""} {
- puts "static CONST chr ${type}CharTable\[\] = {\n$chars\n};\n"
+ puts "static const chr ${type}CharTable\[\] = {\n$chars\n};\n"
puts "#define NUM_[string toupper $type]_CHAR (sizeof(${type}CharTable)/sizeof(chr))\n"
} else {
puts "/*\n * no singletons of $type characters.\n */\n"
diff --git a/tools/uniParse.tcl b/tools/uniParse.tcl
index 5608d25..99ecf40 100644
--- a/tools/uniParse.tcl
+++ b/tools/uniParse.tcl
@@ -209,7 +209,7 @@ proc uni::main {} {
* to the same alternate page number.
*/
-static CONST unsigned short pageMap\[\] = {"
+static const unsigned short pageMap\[\] = {"
set line " "
set last [expr {[llength $pMap] - 1}]
for {set i 0} {$i <= $last} {incr i} {
@@ -231,7 +231,7 @@ static CONST unsigned short pageMap\[\] = {"
* set of character attributes.
*/
-static CONST unsigned char groupMap\[\] = {"
+static const unsigned char groupMap\[\] = {"
set line " "
set lasti [expr {[llength $pages] - 1}]
for {set i 0} {$i <= $lasti} {incr i} {
@@ -270,7 +270,7 @@ static CONST unsigned char groupMap\[\] = {"
* highest field so we can easily sign extend.
*/
-static CONST int groups\[\] = {"
+static const int groups\[\] = {"
set line " "
set last [expr {[llength $groups] - 1}]
for {set i 0} {$i <= $last} {incr i} {
diff --git a/unix/Makefile.in b/unix/Makefile.in
index e741ea7..ded4c6b 100644
--- a/unix/Makefile.in
+++ b/unix/Makefile.in
@@ -1,41 +1,39 @@
#
-# This file is a Makefile for Tcl. If it has the name "Makefile.in"
-# then it is a template for a Makefile; to generate the actual Makefile,
-# run "./configure", which is a configuration script generated by the
-# "autoconf" program (constructs like "@foo@" will get replaced in the
-# actual Makefile.
+# This file is a Makefile for Tcl. If it has the name "Makefile.in" then it is
+# a template for a Makefile; to generate the actual Makefile, run
+# "./configure", which is a configuration script generated by the "autoconf"
+# program (constructs like "@foo@" will get replaced in the actual Makefile.
VERSION = @TCL_VERSION@
MAJOR_VERSION = @TCL_MAJOR_VERSION@
MINOR_VERSION = @TCL_MINOR_VERSION@
PATCH_LEVEL = @TCL_PATCH_LEVEL@
-#----------------------------------------------------------------
-# Things you can change to personalize the Makefile for your own
-# site (you can make these changes in either Makefile.in or
-# Makefile, but changes to Makefile will get lost if you re-run
-# the configuration script).
-#----------------------------------------------------------------
+#--------------------------------------------------------------------------
+# Things you can change to personalize the Makefile for your own site (you can
+# make these changes in either Makefile.in or Makefile, but changes to
+# Makefile will get lost if you re-run the configuration script).
+#--------------------------------------------------------------------------
-# Default top-level directories in which to install architecture-
-# specific files (exec_prefix) and machine-independent files such
-# as scripts (prefix). The values specified here may be overridden
-# at configure-time with the --exec-prefix and --prefix options
-# to the "configure" script. The *dir vars are standard configure
-# substitutions that are based off prefix and exec_prefix.
+# Default top-level directories in which to install architecture-specific
+# files (exec_prefix) and machine-independent files such as scripts (prefix).
+# The values specified here may be overridden at configure-time with the
+# --exec-prefix and --prefix options to the "configure" script. The *dir vars
+# are standard configure substitutions that are based off prefix and
+# exec_prefix.
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
libdir = @libdir@
includedir = @includedir@
+datarootdir = @datarootdir@
mandir = @mandir@
-# The following definition can be set to non-null for special systems
-# like AFS with replication. It allows the pathnames used for installation
-# to be different than those used for actually reference files at
-# run-time. INSTALL_ROOT is prepended to $prefix and $exec_prefix
-# when installing files.
+# The following definition can be set to non-null for special systems like AFS
+# with replication. It allows the pathnames used for installation to be
+# different than those used for actually reference files at run-time.
+# INSTALL_ROOT is prepended to $prefix and $exec_prefix when installing files.
INSTALL_ROOT = $(DESTDIR)
# Path for the platform independent Tcl scripting libraries:
@@ -68,12 +66,10 @@ MAN_INSTALL_DIR = $(INSTALL_ROOT)$(mandir)
# Directory in which to install manual entry for tclsh:
MAN1_INSTALL_DIR = $(MAN_INSTALL_DIR)/man1
-# Directory in which to install manual entries for Tcl's C library
-# procedures:
+# Directory in which to install manual entries for Tcl's C library procedures:
MAN3_INSTALL_DIR = $(MAN_INSTALL_DIR)/man3
-# Directory in which to install manual entries for the built-in
-# Tcl commands:
+# Directory in which to install manual entries for the built-in Tcl commands:
MANN_INSTALL_DIR = $(MAN_INSTALL_DIR)/mann
# Path to the html documentation dir:
@@ -82,11 +78,14 @@ HTML_DIR = @HTML_DIR@
# Directory in which to install html documentation:
HTML_INSTALL_DIR = $(INSTALL_ROOT)$(HTML_DIR)
+# Directory in which to install the configuration file tclConfig.sh
+CONFIG_INSTALL_DIR = $(INSTALL_ROOT)$(libdir)
+
# Package search path.
TCL_PACKAGE_PATH = @TCL_PACKAGE_PATH@
-# Libraries built with optimization switches have this additional extension
-TCL_DBGX = @TCL_DBGX@
+# Tcl Module default path roots (TIP189).
+TCL_MODULE_PATH = @TCL_MODULE_PATH@
# warning flags
CFLAGS_WARNING = @CFLAGS_WARNING@
@@ -100,57 +99,30 @@ CFLAGS_OPTIMIZE = @CFLAGS_OPTIMIZE@
#CFLAGS = $(CFLAGS_DEBUG)
#CFLAGS = $(CFLAGS_OPTIMIZE)
#CFLAGS = $(CFLAGS_DEBUG) $(CFLAGS_OPTIMIZE)
-CFLAGS = @CFLAGS_DEFAULT@ @CFLAGS@ -DTCL_DBGX=$(TCL_DBGX)
+CFLAGS = @CFLAGS_DEFAULT@ @CFLAGS@
# Flags to pass to the linker
LDFLAGS_DEBUG = @LDFLAGS_DEBUG@
LDFLAGS_OPTIMIZE = @LDFLAGS_OPTIMIZE@
LDFLAGS = @LDFLAGS_DEFAULT@ @LDFLAGS@
-# To disable ANSI-C procedure prototypes reverse the comment characters
-# on the following lines:
+# To disable ANSI-C procedure prototypes reverse the comment characters on the
+# following lines:
PROTO_FLAGS =
#PROTO_FLAGS = -DNO_PROTOTYPE
-# Mathematical functions like sin and atan2 are enabled for expressions
-# by default. To disable them, reverse the comment characters on the
-# following pairs of lines:
-MATH_FLAGS =
-#MATH_FLAGS = -DTCL_NO_MATH
-MATH_LIBS = @MATH_LIBS@
-#MATH_LIBS =
-
-# If you use the setenv, putenv, or unsetenv procedures to modify
-# environment variables in your application and you'd like those
-# modifications to appear in the "env" Tcl variable, switch the
-# comments on the two lines below so that Tcl provides these
-# procedures instead of your standard C library.
+# If you use the setenv, putenv, or unsetenv procedures to modify environment
+# variables in your application and you'd like those modifications to appear
+# in the "env" Tcl variable, switch the comments on the two lines below so
+# that Tcl provides these procedures instead of your standard C library.
ENV_FLAGS =
#ENV_FLAGS = -DTclSetEnv=setenv -DTcl_PutEnv=putenv -DTclUnsetEnv=unsetenv
-# To compile for non-UNIX systems (so that only the non-UNIX-specific
-# commands are available), reverse the comment characters on the
-# following pairs of lines. In addition, you'll have to provide your
-# own replacement for the "panic" procedure (see panic.c for what
-# the current one does).
-GENERIC_FLAGS =
-#GENERIC_FLAGS = -DTCL_GENERIC_ONLY
-UNIX_OBJS = tclUnixChan.o tclUnixEvent.o tclUnixFCmd.o \
- tclUnixFile.o tclUnixPipe.o tclUnixSock.o \
- tclUnixTime.o tclUnixInit.o tclUnixThrd.o \
- tclUnixCompat.o
-#UNIX_OBJS =
-NOTIFY_OBJS = tclUnixNotfy.o
-#NOTIFY_OBJS =
-
-# To enable memory debugging reverse the comment characters on the following
-# lines or call configure with --enable-symbols=mem
-# Warning: if you enable memory debugging, you must do it *everywhere*,
-# including all the code that calls Tcl, and you must use ckalloc and
-# ckfree everywhere instead of malloc and free.
-MEM_DEBUG_FLAGS =
-#MEM_DEBUG_FLAGS = -DTCL_MEM_DEBUG
+# To enable memory debugging, call configure with --enable-symbols=mem
+# Warning: if you enable memory debugging, you must do it *everywhere*,
+# including all the code that calls Tcl, and you must use ckalloc and ckfree
+# everywhere instead of malloc and free.
TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
#TCL_STUB_LIB_FILE = libtclstub.a
@@ -161,45 +133,38 @@ STUB_LIB_FILE = ${TCL_STUB_LIB_FILE}
TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
#TCL_STUB_LIB_FLAG = -ltclstub
-# To enable compilation debugging reverse the comment characters on one
-# of the following lines or call configure with --enable-symbols=compile
-COMPILE_DEBUG_FLAGS =
-#COMPILE_DEBUG_FLAGS = -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS
-
-# To compile without backward compatibility and deprecated code
-# uncomment the following
+# To compile without backward compatibility and deprecated code uncomment the
+# following
NO_DEPRECATED_FLAGS =
#NO_DEPRECATED_FLAGS = -DTCL_NO_DEPRECATED
-# Some versions of make, like SGI's, use the following variable to
-# determine which shell to use for executing commands:
+# Some versions of make, like SGI's, use the following variable to determine
+# which shell to use for executing commands:
SHELL = @MAKEFILE_SHELL@
-# Tcl used to let the configure script choose which program to use
-# for installing, but there are just too many different versions of
-# "install" around; better to use the install-sh script that comes
-# with the distribution, which is slower but guaranteed to work.
+# Tcl used to let the configure script choose which program to use for
+# installing, but there are just too many different versions of "install"
+# around; better to use the install-sh script that comes with the
+# distribution, which is slower but guaranteed to work.
INSTALL_STRIP_PROGRAM = -s
-INSTALL_STRIP_LIBRARY = -S -S
+INSTALL_STRIP_LIBRARY = -S -x
-INSTALL = @srcdir@/install-sh -c
+INSTALL = @srcdir@/../unix/install-sh -c
INSTALL_PROGRAM = ${INSTALL}
INSTALL_LIBRARY = ${INSTALL}
INSTALL_DATA = ${INSTALL} -m 644
-# TCL_EXE is the name of a tclsh executable that is available *BEFORE*
-# running make for the first time. Certain build targets (make genstubs)
-# need it to be available on the PATH. This executable should *NOT* be
-# required just to do a normal build although it can be required to run
-# make dist.
-TCL_EXE = tclsh
+# TCL_EXE is the name of a tclsh executable that is available *BEFORE* running
+# make for the first time. Certain build targets (make genstubs) need it to be
+# available on the PATH. This executable should *NOT* be required just to do a
+# normal build although it can be required to run make dist.
+TCL_EXE = tclsh@EXEEXT@
-# The symbols below provide support for dynamic loading and shared
-# libraries. See configure.in for a description of what the
-# symbols mean. The values of the symbols are normally set by the
-# configure script. You shouldn't normally need to modify any of
-# these definitions by hand.
+# The symbols below provide support for dynamic loading and shared libraries.
+# See configure.in for a description of what the symbols mean. The values of
+# the symbols are normally set by the configure script. You shouldn't normally
+# need to modify any of these definitions by hand.
STLIB_LD = @STLIB_LD@
SHLIB_LD = @SHLIB_LD@
@@ -212,17 +177,17 @@ SHLIB_SUFFIX = @SHLIB_SUFFIX@
DLTEST_TARGETS = dltest.marker
-# Additional search flags needed to find the various shared libraries
-# at run-time. The first symbol is for use when creating a binary
-# with cc, and the second is for use when running ld directly.
+# Additional search flags needed to find the various shared libraries at
+# run-time. The first symbol is for use when creating a binary with cc, and
+# the second is for use when running ld directly.
CC_SEARCH_FLAGS = @CC_SEARCH_FLAGS@
LD_SEARCH_FLAGS = @LD_SEARCH_FLAGS@
-# The following symbol is defined to "$(DLTEST_TARGETS)" if dynamic
-# loading is available; this causes everything in the "dltest"
-# subdirectory to be built when making "tcltest. If dynamic loading
-# isn't available, configure defines this symbol to an empty string,
-# in which case the shared libraries aren't built.
+# The following symbol is defined to "$(DLTEST_TARGETS)" if dynamic loading is
+# available; this causes everything in the "dltest" subdirectory to be built
+# when making "tcltest. If dynamic loading isn't available, configure defines
+# this symbol to an empty string, in which case the shared libraries aren't
+# built.
BUILD_DLTEST = @BUILD_DLTEST@
#BUILD_DLTEST =
@@ -235,17 +200,14 @@ LIB_FILE = ${TCL_LIB_FILE}
TCL_LIB_FLAG = @TCL_LIB_FLAG@
#TCL_LIB_FLAG = -ltcl
-TCL_EXP_FILE = @TCL_EXP_FILE@
-TCL_BUILD_EXP_FILE = @TCL_BUILD_EXP_FILE@
-
# support for embedded libraries on Darwin / Mac OS X
DYLIB_INSTALL_DIR = ${LIB_RUNTIME_DIR}
-#----------------------------------------------------------------
-# The information below is modified by the configure script when
-# Makefile is generated from Makefile.in. You shouldn't normally
-# modify any of this stuff by hand.
-#----------------------------------------------------------------
+#--------------------------------------------------------------------------
+# The information below is modified by the configure script when Makefile is
+# generated from Makefile.in. You shouldn't normally modify any of this stuff
+# by hand.
+#--------------------------------------------------------------------------
COMPAT_OBJS = @LIBOBJS@
@@ -255,10 +217,12 @@ RANLIB = @RANLIB@
DTRACE = @DTRACE@
SRC_DIR = @srcdir@
TOP_DIR = $(SRC_DIR)/..
+BUILD_DIR = @builddir@
GENERIC_DIR = $(TOP_DIR)/generic
+TOMMATH_DIR = $(TOP_DIR)/libtommath
COMPAT_DIR = $(TOP_DIR)/compat
TOOL_DIR = $(TOP_DIR)/tools
-UNIX_DIR = $(SRC_DIR)
+UNIX_DIR = $(TOP_DIR)/unix
MAC_OSX_DIR = $(TOP_DIR)/macosx
# Must be absolute because of the cd dltest $(DLTEST_DIR)/configure below.
DLTEST_DIR = @TCL_SRC_DIR@/unix/dltest
@@ -268,40 +232,39 @@ TCL_BUILDTIME_LIBRARY = @TCL_SRC_DIR@/library
CC = @CC@
#CC = purify -best-effort @CC@ -DPURIFY
-# Flags to be passed to installManPage to control whether the manpages
-# should be compressed and linked with softlinks
+# Flags to be passed to installManPage to control how the manpages should be
+# installed (symlinks, compression, package name suffix).
MAN_FLAGS = @MAN_FLAGS@
-#----------------------------------------------------------------
-# The information below is usually usable as is. The configure
-# script won't modify it and it only exists to make working
-# around selected rare system configurations easier.
-#----------------------------------------------------------------
+# If non-empty, install the timezone files that are included with Tcl,
+# otherwise use the ones that ship with the OS.
+INSTALL_TZDATA = @INSTALL_TZDATA@
+
+#--------------------------------------------------------------------------
+# The information below is usually usable as is. The configure script won't
+# modify it and it only exists to make working around selected rare system
+# configurations easier.
+#--------------------------------------------------------------------------
GDB = gdb
-DDD = ddd
-#----------------------------------------------------------------
-# The information below should be usable as is. The configure
-# script won't modify it and you shouldn't need to modify it
-# either.
-#----------------------------------------------------------------
+#--------------------------------------------------------------------------
+# The information below should be usable as is. The configure script won't
+# modify it and you shouldn't need to modify it either.
+#--------------------------------------------------------------------------
-STUB_CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} -I. \
--I${GENERIC_DIR} -I${SRC_DIR} ${AC_FLAGS} ${MATH_FLAGS} ${GENERIC_FLAGS} \
-${PROTO_FLAGS} ${MEM_DEBUG_FLAGS} ${COMPILE_DEBUG_FLAGS} ${ENV_FLAGS} \
--DTCL_SHLIB_EXT=\"${SHLIB_SUFFIX}\" @EXTRA_CC_SWITCHES@
+STUB_CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} \
+-I"${BUILD_DIR}" -I${UNIX_DIR} -I${GENERIC_DIR} -I${TOMMATH_DIR} \
+${AC_FLAGS} ${PROTO_FLAGS} ${ENV_FLAGS} ${EXTRA_CFLAGS} @EXTRA_CC_SWITCHES@
-CC_SWITCHES = $(STUB_CC_SWITCHES) ${NO_DEPRECATED_FLAGS}
+CC_SWITCHES = $(STUB_CC_SWITCHES) ${NO_DEPRECATED_FLAGS}
APP_CC_SWITCHES = $(CC_SWITCHES) @EXTRA_APP_CC_SWITCHES@
-LIBS = @DL_LIBS@ @LIBS@ $(MATH_LIBS)
+LIBS = @TCL_LIBS@
-DEPEND_SWITCHES = ${CFLAGS} -I${GENERIC_DIR} -I${SRC_DIR} \
-${AC_FLAGS} ${MATH_FLAGS} \
-${GENERIC_FLAGS} ${PROTO_FLAGS} ${MEM_DEBUG_FLAGS} \
--DTCL_SHLIB_EXT=\"${SHLIB_SUFFIX}\" @EXTRA_CC_SWITCHES@
+DEPEND_SWITCHES = ${CFLAGS} -I${UNIX_DIR} -I${GENERIC_DIR} \
+${AC_FLAGS} ${PROTO_FLAGS} ${EXTRA_CFLAGS} @EXTRA_CC_SWITCHES@
TCLSH_OBJS = tclAppInit.o
@@ -312,33 +275,66 @@ XTTEST_OBJS = xtTestInit.o tclTest.o tclTestObj.o tclTestProcBodyObj.o \
tclThreadTest.o tclUnixTest.o tclXtNotify.o tclXtTest.o
GENERIC_OBJS = regcomp.o regexec.o regfree.o regerror.o tclAlloc.o \
- tclAsync.o tclBasic.o tclBinary.o \
- tclCkalloc.o tclClock.o tclCmdAH.o tclCmdIL.o tclCmdMZ.o \
- tclCompCmds.o tclCompExpr.o tclCompile.o tclDate.o tclEncoding.o \
+ tclAsync.o tclBasic.o tclBinary.o tclCkalloc.o tclClock.o \
+ tclCmdAH.o tclCmdIL.o tclCmdMZ.o tclCompCmds.o tclCompExpr.o \
+ tclCompile.o tclConfig.o tclDate.o tclDictObj.o tclEncoding.o \
tclEnv.o tclEvent.o tclExecute.o tclFCmd.o tclFileName.o tclGet.o \
tclHash.o tclHistory.o tclIndexObj.o tclInterp.o tclIO.o tclIOCmd.o \
- tclIOGT.o tclIOSock.o tclIOUtil.o tclLink.o tclListObj.o \
+ tclIORChan.o tclIOGT.o tclIOSock.o tclIOUtil.o tclLink.o tclListObj.o \
tclLiteral.o tclLoad.o tclMain.o tclNamesp.o tclNotify.o \
- tclObj.o tclPanic.o tclParse.o tclParseExpr.o tclPipe.o \
- tclPkg.o tclPosixStr.o tclPreserve.o tclProc.o tclRegexp.o \
- tclResolve.o tclResult.o tclScan.o tclStringObj.o tclThread.o \
- tclThreadAlloc.o tclThreadJoin.o tclStubInit.o tclStubLib.o \
- tclTimer.o tclUtf.o tclUtil.o tclVar.o
+ tclObj.o tclPanic.o tclParse.o tclPathObj.o tclPipe.o \
+ tclPkg.o tclPkgConfig.o tclPosixStr.o \
+ tclPreserve.o tclProc.o tclRegexp.o \
+ tclResolve.o tclResult.o tclScan.o tclStringObj.o \
+ tclStrToD.o tclThread.o \
+ tclThreadAlloc.o tclThreadJoin.o tclThreadStorage.o tclStubInit.o \
+ tclStubLib.o tclTimer.o tclTrace.o tclUtf.o tclUtil.o tclVar.o \
+ tclTomMathInterface.o
+
+TOMMATH_OBJS = bncore.o bn_reverse.o bn_fast_s_mp_mul_digs.o \
+ bn_fast_s_mp_sqr.o bn_mp_add.o bn_mp_and.o \
+ bn_mp_add_d.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o \
+ bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \
+ bn_mp_cnt_lsb.o bn_mp_copy.o \
+ bn_mp_count_bits.o bn_mp_div.o bn_mp_div_d.o bn_mp_div_2.o \
+ bn_mp_div_2d.o bn_mp_div_3.o \
+ bn_mp_exch.o bn_mp_expt_d.o bn_mp_grow.o bn_mp_init.o \
+ bn_mp_init_copy.o bn_mp_init_multi.o bn_mp_init_set.o \
+ bn_mp_init_set_int.o bn_mp_init_size.o bn_mp_karatsuba_mul.o \
+ bn_mp_karatsuba_sqr.o \
+ bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mul.o bn_mp_mul_2.o \
+ bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_neg.o bn_mp_or.o \
+ bn_mp_radix_size.o bn_mp_radix_smap.o \
+ bn_mp_read_radix.o bn_mp_rshd.o bn_mp_set.o bn_mp_set_int.o \
+ bn_mp_shrink.o \
+ bn_mp_sqr.o bn_mp_sqrt.o bn_mp_sub.o bn_mp_sub_d.o \
+ bn_mp_to_unsigned_bin.o bn_mp_to_unsigned_bin_n.o \
+ bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_toradix_n.o \
+ bn_mp_unsigned_bin_size.o bn_mp_xor.o bn_mp_zero.o bn_s_mp_add.o \
+ bn_s_mp_mul_digs.o bn_s_mp_sqr.o bn_s_mp_sub.o
STUB_LIB_OBJS = tclStubLib.o ${COMPAT_OBJS}
-MAC_OSX_OBJS = tclMacOSXBundle.o tclMacOSXNotify.o
+UNIX_OBJS = tclUnixChan.o tclUnixEvent.o tclUnixFCmd.o \
+ tclUnixFile.o tclUnixPipe.o tclUnixSock.o \
+ tclUnixTime.o tclUnixInit.o tclUnixThrd.o \
+ tclUnixCompat.o
+
+NOTIFY_OBJS = tclUnixNotfy.o
+
+MAC_OSX_OBJS = tclMacOSXBundle.o tclMacOSXFCmd.o tclMacOSXNotify.o
DTRACE_OBJ = tclDTrace.o
TCL_OBJS = ${GENERIC_OBJS} ${UNIX_OBJS} ${NOTIFY_OBJS} ${COMPAT_OBJS} \
- @DL_OBJS@ @PLAT_OBJS@
+ @DL_OBJS@ @PLAT_OBJS@
-OBJS = ${TCL_OBJS} @DTRACE_OBJ@
+OBJS = ${TCL_OBJS} ${TOMMATH_OBJS} @DTRACE_OBJ@
TCL_DECLS = \
$(GENERIC_DIR)/tcl.decls \
- $(GENERIC_DIR)/tclInt.decls
+ $(GENERIC_DIR)/tclInt.decls \
+ $(GENERIC_DIR)/tclTomMath.decls
GENERIC_HDRS = \
$(GENERIC_DIR)/tcl.h \
@@ -346,6 +342,8 @@ GENERIC_HDRS = \
$(GENERIC_DIR)/tclInt.h \
$(GENERIC_DIR)/tclIntDecls.h \
$(GENERIC_DIR)/tclIntPlatDecls.h \
+ $(GENERIC_DIR)/tclTomMath.h \
+ $(GENERIC_DIR)/tclTomMathDecls.h \
$(GENERIC_DIR)/tclPatch.h \
$(GENERIC_DIR)/tclPlatDecls.h \
$(GENERIC_DIR)/tclPort.h \
@@ -368,7 +366,9 @@ GENERIC_SRCS = \
$(GENERIC_DIR)/tclCompCmds.c \
$(GENERIC_DIR)/tclCompExpr.c \
$(GENERIC_DIR)/tclCompile.c \
+ $(GENERIC_DIR)/tclConfig.c \
$(GENERIC_DIR)/tclDate.c \
+ $(GENERIC_DIR)/tclDictObj.c \
$(GENERIC_DIR)/tclEncoding.c \
$(GENERIC_DIR)/tclEnv.c \
$(GENERIC_DIR)/tclEvent.c \
@@ -385,6 +385,7 @@ GENERIC_SRCS = \
$(GENERIC_DIR)/tclIOGT.c \
$(GENERIC_DIR)/tclIOSock.c \
$(GENERIC_DIR)/tclIOUtil.c \
+ $(GENERIC_DIR)/tclIORChan.c \
$(GENERIC_DIR)/tclLink.c \
$(GENERIC_DIR)/tclListObj.c \
$(GENERIC_DIR)/tclLiteral.c \
@@ -394,9 +395,10 @@ GENERIC_SRCS = \
$(GENERIC_DIR)/tclNotify.c \
$(GENERIC_DIR)/tclObj.c \
$(GENERIC_DIR)/tclParse.c \
- $(GENERIC_DIR)/tclParseExpr.c \
+ $(GENERIC_DIR)/tclPathObj.c \
$(GENERIC_DIR)/tclPipe.c \
$(GENERIC_DIR)/tclPkg.c \
+ $(GENERIC_DIR)/tclPkgConfig.c \
$(GENERIC_DIR)/tclPosixStr.c \
$(GENERIC_DIR)/tclPreserve.c \
$(GENERIC_DIR)/tclProc.c \
@@ -407,21 +409,91 @@ GENERIC_SRCS = \
$(GENERIC_DIR)/tclStubInit.c \
$(GENERIC_DIR)/tclStubLib.c \
$(GENERIC_DIR)/tclStringObj.c \
+ $(GENERIC_DIR)/tclStrToD.c \
$(GENERIC_DIR)/tclTest.c \
$(GENERIC_DIR)/tclTestObj.c \
$(GENERIC_DIR)/tclTestProcBodyObj.c \
$(GENERIC_DIR)/tclThread.c \
$(GENERIC_DIR)/tclThreadAlloc.c \
$(GENERIC_DIR)/tclThreadJoin.c \
+ $(GENERIC_DIR)/tclThreadStorage.c \
$(GENERIC_DIR)/tclTimer.c \
+ $(GENERIC_DIR)/tclTrace.c \
$(GENERIC_DIR)/tclUtil.c \
$(GENERIC_DIR)/tclVar.c
STUB_SRCS = \
$(GENERIC_DIR)/tclStubLib.c
+TOMMATH_SRCS = \
+ $(TOMMATH_DIR)/bncore.c \
+ $(TOMMATH_DIR)/bn_reverse.c \
+ $(TOMMATH_DIR)/bn_fast_s_mp_mul_digs.c \
+ $(TOMMATH_DIR)/bn_fast_s_mp_sqr.c \
+ $(TOMMATH_DIR)/bn_mp_add.c \
+ $(TOMMATH_DIR)/bn_mp_add_d.c \
+ $(TOMMATH_DIR)/bn_mp_and.c \
+ $(TOMMATH_DIR)/bn_mp_clamp.c \
+ $(TOMMATH_DIR)/bn_mp_clear.c \
+ $(TOMMATH_DIR)/bn_mp_clear_multi.c \
+ $(TOMMATH_DIR)/bn_mp_cmp.c \
+ $(TOMMATH_DIR)/bn_mp_cmp_d.c \
+ $(TOMMATH_DIR)/bn_mp_cmp_mag.c \
+ $(TOMMATH_DIR)/bn_mp_copy.c \
+ $(TOMMATH_DIR)/bn_mp_cnt_lsb.c \
+ $(TOMMATH_DIR)/bn_mp_count_bits.c \
+ $(TOMMATH_DIR)/bn_mp_div.c \
+ $(TOMMATH_DIR)/bn_mp_div_d.c \
+ $(TOMMATH_DIR)/bn_mp_div_2.c \
+ $(TOMMATH_DIR)/bn_mp_div_2d.c \
+ $(TOMMATH_DIR)/bn_mp_div_3.c \
+ $(TOMMATH_DIR)/bn_mp_exch.c \
+ $(TOMMATH_DIR)/bn_mp_expt_d.c \
+ $(TOMMATH_DIR)/bn_mp_grow.c \
+ $(TOMMATH_DIR)/bn_mp_init.c \
+ $(TOMMATH_DIR)/bn_mp_init_copy.c \
+ $(TOMMATH_DIR)/bn_mp_init_multi.c \
+ $(TOMMATH_DIR)/bn_mp_init_set.c \
+ $(TOMMATH_DIR)/bn_mp_init_set_int.c \
+ $(TOMMATH_DIR)/bn_mp_init_size.c \
+ $(TOMMATH_DIR)/bn_mp_karatsuba_mul.c \
+ $(TOMMATH_DIR)/bn_mp_karatsuba_sqr.c \
+ $(TOMMATH_DIR)/bn_mp_lshd.c \
+ $(TOMMATH_DIR)/bn_mp_mod.c \
+ $(TOMMATH_DIR)/bn_mp_mod_2d.c \
+ $(TOMMATH_DIR)/bn_mp_mul.c \
+ $(TOMMATH_DIR)/bn_mp_mul_2.c \
+ $(TOMMATH_DIR)/bn_mp_mul_2d.c \
+ $(TOMMATH_DIR)/bn_mp_mul_d.c \
+ $(TOMMATH_DIR)/bn_mp_neg.c \
+ $(TOMMATH_DIR)/bn_mp_or.c \
+ $(TOMMATH_DIR)/bn_mp_radix_size.c \
+ $(TOMMATH_DIR)/bn_mp_radix_smap.c \
+ $(TOMMATH_DIR)/bn_mp_read_radix.c \
+ $(TOMMATH_DIR)/bn_mp_rshd.c \
+ $(TOMMATH_DIR)/bn_mp_set.c \
+ $(TOMMATH_DIR)/bn_mp_set_int.c \
+ $(TOMMATH_DIR)/bn_mp_shrink.c \
+ $(TOMMATH_DIR)/bn_mp_sqr.c \
+ $(TOMMATH_DIR)/bn_mp_sqrt.c \
+ $(TOMMATH_DIR)/bn_mp_sub.c \
+ $(TOMMATH_DIR)/bn_mp_sub_d.c \
+ $(TOMMATH_DIR)/bn_mp_to_unsigned_bin.c \
+ $(TOMMATH_DIR)/bn_mp_to_unsigned_bin_n.c \
+ $(TOMMATH_DIR)/bn_mp_toom_mul.c \
+ $(TOMMATH_DIR)/bn_mp_toom_sqr.c \
+ $(TOMMATH_DIR)/bn_mp_toradix_n.c \
+ $(TOMMATH_DIR)/bn_mp_unsigned_bin_size.c \
+ $(TOMMATH_DIR)/bn_mp_xor.c \
+ $(TOMMATH_DIR)/bn_mp_zero.c \
+ $(TOMMATH_DIR)/bn_s_mp_add.c \
+ $(TOMMATH_DIR)/bn_s_mp_mul_digs.c \
+ $(TOMMATH_DIR)/bn_s_mp_sqr.c \
+ $(TOMMATH_DIR)/bn_s_mp_sub.c
+
UNIX_HDRS = \
$(UNIX_DIR)/tclUnixPort.h
+# $(UNIX_DIR)/tclConfig.h
UNIX_SRCS = \
$(UNIX_DIR)/tclAppInit.c \
@@ -442,7 +514,6 @@ NOTIFY_SRCS = \
DL_SRCS = \
$(UNIX_DIR)/tclLoadAix.c \
- $(UNIX_DIR)/tclLoadAout.c \
$(UNIX_DIR)/tclLoadDl.c \
$(UNIX_DIR)/tclLoadDl2.c \
$(UNIX_DIR)/tclLoadDld.c \
@@ -453,28 +524,30 @@ DL_SRCS = \
MAC_OSX_SRCS = \
$(MAC_OSX_DIR)/tclMacOSXBundle.c \
+ $(MAC_OSX_DIR)/tclMacOSXFCmd.c \
$(MAC_OSX_DIR)/tclMacOSXNotify.c
DTRACE_HDR = tclDTrace.h
DTRACE_SRC = $(GENERIC_DIR)/tclDTrace.d
-# Note: don't include DL_SRCS or MAC_OSX_SRCS in SRCS: most of those
-# files won't compile on the current machine, and they will cause
-# problems for things like "make depend".
+# Note: don't include DL_SRCS or MAC_OSX_SRCS in SRCS: most of those files
+# won't compile on the current machine, and they will cause problems for
+# things like "make depend".
-SRCS = $(GENERIC_SRCS) $(UNIX_SRCS) $(NOTIFY_SRCS) $(STUB_SRCS) @PLAT_SRCS@
+SRCS = $(GENERIC_SRCS) $(TOMMATH_SRCS) $(UNIX_SRCS) $(NOTIFY_SRCS) \
+ $(STUB_SRCS) @PLAT_SRCS@
all: binaries libraries doc
-binaries: ${LIB_FILE} $(STUB_LIB_FILE) $(TCL_BUILD_EXP_FILE) tclsh
+binaries: ${LIB_FILE} $(STUB_LIB_FILE) ${TCL_EXE}
libraries:
doc:
-# The following target is configured by autoconf to generate either
-# a shared library or non-shared library for Tcl.
+# The following target is configured by autoconf to generate either a shared
+# library or non-shared library for Tcl.
${LIB_FILE}: ${OBJS} ${STUB_LIB_FILE}
rm -f $@
@MAKE_LIB@
@@ -483,123 +556,138 @@ ${STUB_LIB_FILE}: ${STUB_LIB_OBJS}
rm -f $@
@MAKE_STUB_LIB@
-# Make target which outputs the list of the .o contained in the Tcl lib
-# usefull to build a single big shared library containing Tcl and other
-# extensions. used for the Tcl Plugin. -- dl
-# The dependency on OBJS is not there because we just want the list
-# of objects here, not actually building them
+# Make target which outputs the list of the .o contained in the Tcl lib useful
+# to build a single big shared library containing Tcl and other extensions.
+# Used for the Tcl Plugin. -- dl
+# The dependency on OBJS is not there because we just want the list of objects
+# here, not actually building them
tclLibObjs:
@echo ${OBJS}
-# This targets actually build the objects needed for the lib in the above
-# case
+# This targets actually build the objects needed for the lib in the above case
objs: ${OBJS}
-tclsh: ${TCLSH_OBJS} ${TCL_LIB_FILE}
+${TCL_EXE}: ${TCLSH_OBJS} ${TCL_LIB_FILE}
${CC} ${CFLAGS} ${LDFLAGS} ${TCLSH_OBJS} @TCL_BUILD_LIB_SPEC@ ${LIBS} @EXTRA_TCLSH_LIBS@ \
- ${CC_SEARCH_FLAGS} -o tclsh
+ ${CC_SEARCH_FLAGS} -o ${TCL_EXE}
-# Resetting the LIB_RUNTIME_DIR below is required so that
-# the generated tcltest executable gets the build directory
-# burned into its ld search path. This keeps tcltest from
-# picking up an already installed version of the Tcl library.
+# Resetting the LIB_RUNTIME_DIR below is required so that the generated
+# tcltest executable gets the build directory burned into its ld search path.
+# This keeps tcltest from picking up an already installed version of the Tcl
+# library.
-tcltest: ${TCLTEST_OBJS} ${TCL_LIB_FILE} ${BUILD_DLTEST}
- $(MAKE) tcltest-real LIB_RUNTIME_DIR=`pwd`
+tcltest@EXEEXT@: ${TCLTEST_OBJS} ${TCL_LIB_FILE} ${BUILD_DLTEST}
+ $(MAKE) tcltest-real LIB_RUNTIME_DIR="`pwd`"
tcltest-real:
${CC} ${CFLAGS} ${LDFLAGS} ${TCLTEST_OBJS} @TCL_BUILD_LIB_SPEC@ ${LIBS} @EXTRA_TCLSH_LIBS@ \
- ${CC_SEARCH_FLAGS} -o tcltest
+ ${CC_SEARCH_FLAGS} -o tcltest@EXEEXT@
-# Note, in the target below TCL_LIBRARY needs to be set or else
-# "make test" won't work in the case where the compilation directory
-# isn't the same as the source directory.
-# Specifying TESTFLAGS on the command line is the standard way to pass
-# args to tcltest, ie:
+# Note, in the targets below TCL_LIBRARY needs to be set or else "make test"
+# won't work in the case where the compilation directory isn't the same as the
+# source directory.
+#
+# Specifying TESTFLAGS on the command line is the standard way to pass args to
+# tcltest, ie:
# % make test TESTFLAGS="-verbose bps -file fileName.test"
-test: tcltest
- @LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
+test: tcltest@EXEEXT@
+ @LD_LIBRARY_PATH_VAR@="`pwd`:$${@LD_LIBRARY_PATH_VAR@}"; export @LD_LIBRARY_PATH_VAR@; \
TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"; export TCL_LIBRARY; \
- ./tcltest $(TOP_DIR)/tests/all.tcl $(TESTFLAGS) $(TCLTESTARGS)
+ ./tcltest@EXEEXT@ $(TOP_DIR)/tests/all.tcl $(TESTFLAGS)
+
+gdb-test: tcltest@EXEEXT@
+ @echo "set env @LD_LIBRARY_PATH_VAR@=\"`pwd`:$${@LD_LIBRARY_PATH_VAR@}\"" > gdb.run
+ @echo "set env TCL_LIBRARY=${TCL_BUILDTIME_LIBRARY}" >> gdb.run
+ @echo "set args $(TOP_DIR)/tests/all.tcl $(TESTFLAGS) -singleproc 1" >> gdb.run
+ $(GDB) ./tcltest@EXEEXT@ --command=gdb.run
+ rm gdb.run
# Useful target to launch a built tcltest with the proper path,...
-runtest: tcltest
- @LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
+runtest: tcltest@EXEEXT@
+ @LD_LIBRARY_PATH_VAR@="`pwd`:$${@LD_LIBRARY_PATH_VAR@}"; export @LD_LIBRARY_PATH_VAR@; \
TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"; export TCL_LIBRARY; \
- ./tcltest
+ ./tcltest@EXEEXT@
# Useful target for running the test suite with an unwritable current
# directory...
-ro-test: tcltest
- @LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
+ro-test: tcltest@EXEEXT@
+ @LD_LIBRARY_PATH_VAR@="`pwd`:$${@LD_LIBRARY_PATH_VAR@}"; export @LD_LIBRARY_PATH_VAR@; \
TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"; export TCL_LIBRARY; \
- echo 'exec chmod -w .;package require tcltest;tcltest::temporaryDirectory /tmp;source ../tests/all.tcl;exec chmod +w .' | ./tcltest
+ echo 'exec chmod -w .;package require tcltest;tcltest::temporaryDirectory /tmp;source ../tests/all.tcl;exec chmod +w .' | ./tcltest@EXEEXT@
# This target can be used to run tclsh from the build directory
# via `make shell SCRIPT=/tmp/foo.tcl`
-shell: tclsh
- @LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
+shell: ${TCL_EXE}
+ @LD_LIBRARY_PATH_VAR@="`pwd`:$${@LD_LIBRARY_PATH_VAR@}"; export @LD_LIBRARY_PATH_VAR@; \
TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"; export TCL_LIBRARY; \
- ./tclsh $(SCRIPT)
+ ./${TCL_EXE} $(SCRIPT)
# This target can be used to run tclsh inside either gdb or insight
-gdb: tclsh
- @echo "set env @LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}" > gdb.run
+gdb: ${TCL_EXE}
+ @echo "set env @LD_LIBRARY_PATH_VAR@=\"`pwd`:$${@LD_LIBRARY_PATH_VAR@}\"" > gdb.run
@echo "set env TCL_LIBRARY=${TCL_BUILDTIME_LIBRARY}" >> gdb.run
- $(GDB) ./tclsh --command=gdb.run
- rm gdb.run
-
-# This target can be used to run tclsh inside ddd
-ddd: tclsh
- @echo "set env @LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}" > gdb.run
- @echo "set env TCL_LIBRARY=${TCL_BUILDTIME_LIBRARY}" >> gdb.run
- $(DDD) -command=gdb.run ./tclsh
+ $(GDB) ./${TCL_EXE} --command=gdb.run
rm gdb.run
VALGRINDARGS=--tool=memcheck --num-callers=8 --leak-resolution=high --leak-check=yes --show-reachable=yes -v
-valgrind: tclsh tcltest
- @LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
+valgrind: ${TCL_EXE} tcltest@EXEEXT@
+ @LD_LIBRARY_PATH_VAR@="`pwd`:$${@LD_LIBRARY_PATH_VAR@}"; export @LD_LIBRARY_PATH_VAR@; \
TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"; export TCL_LIBRARY; \
- valgrind $(VALGRINDARGS) ./tcltest $(TOP_DIR)/tests/all.tcl -singleproc 1 $(TESTFLAGS) $(TCLTESTARGS)
+ valgrind $(VALGRINDARGS) ./tcltest@EXEEXT@ $(TOP_DIR)/tests/all.tcl -singleproc 1 $(TESTFLAGS)
-valgrindshell: tclsh
- @LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
+valgrindshell: ${TCL_EXE}
+ @LD_LIBRARY_PATH_VAR@="`pwd`:$${@LD_LIBRARY_PATH_VAR@}"; export @LD_LIBRARY_PATH_VAR@; \
TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"; export TCL_LIBRARY; \
- valgrind $(VALGRINDARGS) ./tclsh $(SCRIPT)
+ valgrind $(VALGRINDARGS) ./${TCL_EXE} $(SCRIPT)
-# The following target outputs the name of the top-level source directory
-# for Tcl (it is used by Tk's configure script, for example). The
-# .NO_PARALLEL line is needed to avoid problems under Sun's "pmake".
-# Note: this target is now obsolete (use the autoconf variable
-# TCL_SRC_DIR from tclConfig.sh instead).
+# The following target outputs the name of the top-level source directory for
+# Tcl (it is used by Tk's configure script, for example). The .NO_PARALLEL
+# line is needed to avoid problems under Sun's "pmake". Note: this target is
+# now obsolete (use the autoconf variable TCL_SRC_DIR from tclConfig.sh
+# instead).
.NO_PARALLEL: topDirName
topDirName:
@cd $(TOP_DIR); pwd
-# The following target generates the file generic/tclDate.c
-# from the yacc grammar found in generic/tclGetDate.y. This is
-# only run by hand as yacc is not available in all environments.
-# The name of the .c file is different than the name of the .y file
-# so that make doesn't try to automatically regenerate the .c file.
+# The following target generates the file generic/tclDate.c from the yacc
+# grammar found in generic/tclGetDate.y. This is only run by hand as yacc is
+# not available in all environments. The name of the .c file is different than
+# the name of the .y file so that make doesn't try to automatically regenerate
+# the .c file.
gendate:
- yacc -l $(GENERIC_DIR)/tclGetDate.y
- sed -e 's/yy/TclDate/g' -e '/^#include <values.h>/d' \
- -e 's?SCCSID?RCS: @(#) ?' \
- -e '/#ifdef __STDC__/,/#endif/d' -e '/TclDateerrlab:/d' \
- -e '/TclDatenewstate:/d' -e '/#pragma/d' \
- -e '/#include <inttypes.h>/d' -e 's/const /CONST /g' \
- <y.tab.c >$(GENERIC_DIR)/tclDate.c
- rm y.tab.c
-
-# The following target generates the shared libraries in dltest/ that
-# are used for testing; they are included as part of the "tcltest"
-# target (via the BUILD_DLTEST variable) if dynamic loading is supported
-# on this platform. The Makefile in the dltest subdirectory creates
-# the dltest.marker file in this directory after a successful build.
+ bison --output-file=$(GENERIC_DIR)/tclDate.c \
+ --no-lines \
+ --name-prefix=TclDate \
+ $(GENERIC_DIR)/tclGetDate.y
+
+# yacc -l $(GENERIC_DIR)/tclGetDate.y
+# sed -e 's/yy/TclDate/g' -e '/^#include <values.h>/d' \
+# -e 's?SCCSID?RCS: @(#) ?' \
+# -e '/#ifdef __STDC__/,/#endif/d' -e '/TclDateerrlab:/d' \
+# -e '/TclDatenewstate:/d' -e '/#pragma/d' \
+# -e '/#include <inttypes.h>/d' -e 's/const /CONST /g' \
+# -e '/#define YYNEW/s/malloc/TclDateAlloc/g' \
+# -e '/#define YYENLARGE/,/realloc/s/realloc/TclDateRealloc/g' \
+# <y.tab.c >$(GENERIC_DIR)/tclDate.c
+# rm y.tab.c
+
+# The following target generates the file generic/tclTomMath.h. It needs to be
+# run (and the results checked) after updating to a new release of libtommath.
+
+gentommath_h:
+ $(TCL_EXE) "$(TOOL_DIR)/fix_tommath_h.tcl" \
+ "$(TOMMATH_DIR)/tommath.h" \
+ > "$(GENERIC_DIR)/tclTomMath.h"
+
+# The following target generates the shared libraries in dltest/ that are used
+# for testing; they are included as part of the "tcltest" target (via the
+# BUILD_DLTEST variable) if dynamic loading is supported on this platform. The
+# Makefile in the dltest subdirectory creates the dltest.marker file in this
+# directory after a successful build.
dltest.marker: ${STUB_LIB_FILE}
cd dltest ; $(MAKE)
@@ -613,189 +701,197 @@ install-strip:
INSTALL_PROGRAM="$(INSTALL_PROGRAM) ${INSTALL_STRIP_PROGRAM}" \
INSTALL_LIBRARY="$(INSTALL_LIBRARY) ${INSTALL_STRIP_LIBRARY}"
-# Note: before running ranlib below, must cd to target directory because
-# some ranlibs write to current directory, and this might not always be
-# possible (e.g. if installing as root).
+# Note: before running ranlib below, must cd to target directory because some
+# ranlibs write to current directory, and this might not always be possible
+# (e.g. if installing as root).
install-binaries: binaries
- @for i in $(LIB_INSTALL_DIR) $(BIN_INSTALL_DIR) ; \
+ @for i in "$(LIB_INSTALL_DIR)" "$(BIN_INSTALL_DIR)" \
+ "$(CONFIG_INSTALL_DIR)"; \
do \
- if [ ! -d $$i ] ; then \
+ if [ ! -d "$$i" ] ; then \
echo "Making directory $$i"; \
- mkdir -p $$i; \
- chmod 755 $$i; \
+ mkdir -p "$$i"; \
+ chmod 755 "$$i"; \
else true; \
fi; \
done;
- @if test ! -x $(SRC_DIR)/install-sh; then \
- chmod +x $(SRC_DIR)/install-sh; \
+ @if test ! -x $(SRC_DIR)/../unix/install-sh; then \
+ chmod +x $(SRC_DIR)/../unix/install-sh; \
fi
@echo "Installing $(LIB_FILE) to $(LIB_INSTALL_DIR)/"
@@INSTALL_LIB@
- @chmod 555 $(LIB_INSTALL_DIR)/$(LIB_FILE)
- @if test "$(TCL_BUILD_EXP_FILE)" != ""; then \
- echo "Installing $(TCL_EXP_FILE) to $(LIB_INSTALL_DIR)/"; \
- $(INSTALL_DATA) $(TCL_BUILD_EXP_FILE) \
- $(LIB_INSTALL_DIR)/$(TCL_EXP_FILE); \
- fi
- @echo "Installing tclsh as $(BIN_INSTALL_DIR)/tclsh$(VERSION)"
- @$(INSTALL_PROGRAM) tclsh $(BIN_INSTALL_DIR)/tclsh$(VERSION)
- @echo "Installing tclConfig.sh to $(LIB_INSTALL_DIR)/"
- @$(INSTALL_DATA) tclConfig.sh $(LIB_INSTALL_DIR)/tclConfig.sh
+ @chmod 555 "$(LIB_INSTALL_DIR)"/$(LIB_FILE)
+ @echo "Installing ${TCL_EXE} as $(BIN_INSTALL_DIR)/tclsh$(VERSION)@EXEEXT@"
+ @$(INSTALL_PROGRAM) ${TCL_EXE} "$(BIN_INSTALL_DIR)"/tclsh$(VERSION)@EXEEXT@
+ @echo "Installing tclConfig.sh to $(CONFIG_INSTALL_DIR)/"
+ @$(INSTALL_DATA) tclConfig.sh "$(CONFIG_INSTALL_DIR)"/tclConfig.sh
@if test "$(STUB_LIB_FILE)" != "" ; then \
echo "Installing $(STUB_LIB_FILE) to $(LIB_INSTALL_DIR)/"; \
@INSTALL_STUB_LIB@ ; \
fi
@EXTRA_INSTALL_BINARIES@
-install-libraries: libraries
- @for i in $(INCLUDE_INSTALL_DIR) $(SCRIPT_INSTALL_DIR); \
+install-libraries: libraries $(INSTALL_TZDATA) install-msgs
+ @for i in "$(INCLUDE_INSTALL_DIR)" "$(SCRIPT_INSTALL_DIR)"; \
do \
- if [ ! -d $$i ] ; then \
+ if [ ! -d "$$i" ] ; then \
echo "Making directory $$i"; \
- mkdir -p $$i; \
- chmod 755 $$i; \
+ mkdir -p "$$i"; \
+ chmod 755 "$$i"; \
else true; \
fi; \
done;
- @for i in platform http2.5 http1.0 opt0.4 encoding msgcat1.3 tcltest2.2; \
+ @for i in opt0.4 http1.0 encoding ../tcl8 ../tcl8/8.3 ../tcl8/8.4 ../tcl8/8.4/platform ../tcl8/8.5; \
do \
- if [ ! -d $(SCRIPT_INSTALL_DIR)/$$i ] ; then \
+ if [ ! -d "$(SCRIPT_INSTALL_DIR)"/$$i ] ; then \
echo "Making directory $(SCRIPT_INSTALL_DIR)/$$i"; \
- mkdir -p $(SCRIPT_INSTALL_DIR)/$$i; \
- chmod 755 $(SCRIPT_INSTALL_DIR)/$$i; \
+ mkdir -p "$(SCRIPT_INSTALL_DIR)"/$$i; \
+ chmod 755 "$(SCRIPT_INSTALL_DIR)"/$$i; \
else true; \
fi; \
done;
- @if test ! -x $(SRC_DIR)/install-sh; then \
- chmod +x $(SRC_DIR)/install-sh; \
+ @if test ! -x $(SRC_DIR)/../unix/install-sh; then \
+ chmod +x $(SRC_DIR)/../unix/install-sh; \
fi
@echo "Installing header files";
@for i in $(GENERIC_DIR)/tcl.h $(GENERIC_DIR)/tclDecls.h \
- $(GENERIC_DIR)/tclPlatDecls.h; \
+ $(GENERIC_DIR)/tclPlatDecls.h \
+ $(GENERIC_DIR)/tclTomMath.h \
+ $(GENERIC_DIR)/tclTomMathDecls.h ; \
do \
- $(INSTALL_DATA) $$i $(INCLUDE_INSTALL_DIR); \
+ $(INSTALL_DATA) $$i "$(INCLUDE_INSTALL_DIR)"; \
done;
@echo "Installing library files to $(SCRIPT_INSTALL_DIR)";
@for i in $(TOP_DIR)/library/*.tcl $(TOP_DIR)/library/tclIndex \
- $(UNIX_DIR)/tclAppInit.c $(UNIX_DIR)/ldAix @DTRACE_SRC@; \
+ $(UNIX_DIR)/tclAppInit.c @LDAIX_SRC@ @DTRACE_SRC@; \
do \
- $(INSTALL_DATA) $$i $(SCRIPT_INSTALL_DIR); \
- done;
- @echo "Installing library platform directory";
- @for j in $(TOP_DIR)/library/platform/*.tcl ; \
- do \
- $(INSTALL_DATA) $$j $(SCRIPT_INSTALL_DIR)/platform; \
+ $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"; \
done;
@echo "Installing library http1.0 directory";
- @for j in $(TOP_DIR)/library/http1.0/*.tcl ; \
- do \
- $(INSTALL_DATA) $$j $(SCRIPT_INSTALL_DIR)/http1.0; \
- done;
- @echo "Installing library http2.5 directory";
- @for j in $(TOP_DIR)/library/http/*.tcl ; \
+ @for i in $(TOP_DIR)/library/http1.0/*.tcl ; \
do \
- $(INSTALL_DATA) $$j $(SCRIPT_INSTALL_DIR)/http2.5; \
+ $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/http1.0; \
done;
+ @echo "Installing package http 2.7.6 as a Tcl Module";
+ @$(INSTALL_DATA) $(TOP_DIR)/library/http/http.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.4/http-2.7.6.tm;
@echo "Installing library opt0.4 directory";
- @for j in $(TOP_DIR)/library/opt/*.tcl ; \
- do \
- $(INSTALL_DATA) $$j $(SCRIPT_INSTALL_DIR)/opt0.4; \
- done;
- @echo "Installing library msgcat1.3 directory";
- @for j in $(TOP_DIR)/library/msgcat/*.tcl ; \
- do \
- $(INSTALL_DATA) $$j $(SCRIPT_INSTALL_DIR)/msgcat1.3; \
- done;
- @echo "Installing library tcltest2.2 directory";
- @for j in $(TOP_DIR)/library/tcltest/*.tcl ; \
+ @for i in $(TOP_DIR)/library/opt/*.tcl ; \
do \
- $(INSTALL_DATA) $$j $(SCRIPT_INSTALL_DIR)/tcltest2.2; \
+ $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/opt0.4; \
done;
+ @echo "Installing package msgcat 1.4.4 as a Tcl Module";
+ @$(INSTALL_DATA) $(TOP_DIR)/library/msgcat/msgcat.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.5/msgcat-1.4.4.tm;
+ @echo "Installing package tcltest 2.3.3 as a Tcl Module";
+ @$(INSTALL_DATA) $(TOP_DIR)/library/tcltest/tcltest.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.5/tcltest-2.3.3.tm;
+
+ @echo "Installing package platform 1.0.10 as a Tcl Module";
+ @$(INSTALL_DATA) $(TOP_DIR)/library/platform/platform.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.4/platform-1.0.10.tm;
+ @echo "Installing package platform::shell 1.1.4 as a Tcl Module";
+ @$(INSTALL_DATA) $(TOP_DIR)/library/platform/shell.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.4/platform/shell-1.1.4.tm;
+
@echo "Installing library encoding directory";
@for i in $(TOP_DIR)/library/encoding/*.enc ; do \
- $(INSTALL_DATA) $$i $(SCRIPT_INSTALL_DIR)/encoding; \
+ $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/encoding; \
done;
+ @if [ -n "$(TCL_MODULE_PATH)" -a -f $(TOP_DIR)/library/tm.tcl ]; then \
+ echo "Customizing tcl module path"; \
+ echo "if {![interp issafe]} { ::tcl::tm::roots {$(TCL_MODULE_PATH)} }" >> \
+ "$(SCRIPT_INSTALL_DIR)"/tm.tcl; \
+ fi
+
+install-tzdata: ${TCL_EXE}
+ @echo "Installing time zone data"
+ @@LD_LIBRARY_PATH_VAR@="`pwd`:$${@LD_LIBRARY_PATH_VAR@}"; export @LD_LIBRARY_PATH_VAR@; \
+ TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"; export TCL_LIBRARY; \
+ ./${TCL_EXE} $(TOOL_DIR)/installData.tcl \
+ $(TOP_DIR)/library/tzdata "$(SCRIPT_INSTALL_DIR)"/tzdata
+
+install-msgs: ${TCL_EXE}
+ @echo "Installing message catalogs"
+ @@LD_LIBRARY_PATH_VAR@="`pwd`:$${@LD_LIBRARY_PATH_VAR@}"; export @LD_LIBRARY_PATH_VAR@; \
+ TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"; export TCL_LIBRARY; \
+ ./${TCL_EXE} $(TOOL_DIR)/installData.tcl \
+ $(TOP_DIR)/library/msgs "$(SCRIPT_INSTALL_DIR)"/msgs
install-doc: doc
- @if test ! -x $(UNIX_DIR)/installManPage; then \
- chmod +x $(UNIX_DIR)/installManPage; \
- fi
- @for i in $(MAN_INSTALL_DIR) $(MAN1_INSTALL_DIR) $(MAN3_INSTALL_DIR) $(MANN_INSTALL_DIR) ; \
+ @for i in "$(MAN_INSTALL_DIR)" "$(MAN1_INSTALL_DIR)" "$(MAN3_INSTALL_DIR)" "$(MANN_INSTALL_DIR)" ; \
do \
- if [ ! -d $$i ] ; then \
+ if [ ! -d "$$i" ] ; then \
echo "Making directory $$i"; \
- mkdir -p $$i; \
- chmod 755 $$i; \
+ mkdir -p "$$i"; \
+ chmod 755 "$$i"; \
else true; \
fi; \
done;
@echo "Installing and cross-linking top-level (.1) docs";
@for i in $(TOP_DIR)/doc/*.1; do \
- $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i $(MAN1_INSTALL_DIR); \
+ $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i "$(MAN1_INSTALL_DIR)"; \
done
@echo "Installing and cross-linking C API (.3) docs";
@for i in $(TOP_DIR)/doc/*.3; do \
- $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i $(MAN3_INSTALL_DIR); \
+ $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i "$(MAN3_INSTALL_DIR)"; \
done
@echo "Installing and cross-linking command (.n) docs";
@for i in $(TOP_DIR)/doc/*.n; do \
- $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i $(MANN_INSTALL_DIR); \
+ $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i "$(MANN_INSTALL_DIR)"; \
done
# Optional target to install private headers
install-private-headers: libraries
- @for i in $(PRIVATE_INCLUDE_INSTALL_DIR); \
+ @for i in "$(PRIVATE_INCLUDE_INSTALL_DIR)"; \
do \
- if [ ! -d $$i ] ; then \
+ if [ ! -d "$$i" ] ; then \
echo "Making directory $$i"; \
- mkdir -p $$i; \
- chmod 755 $$i; \
+ mkdir -p "$$i"; \
+ chmod 755 "$$i"; \
else true; \
fi; \
done;
- @if test ! -x $(SRC_DIR)/install-sh; then \
- chmod +x $(SRC_DIR)/install-sh; \
+ @if test ! -x $(SRC_DIR)/../unix/install-sh; then \
+ chmod +x $(SRC_DIR)/../unix/install-sh; \
fi
@echo "Installing private header files";
@for i in $(GENERIC_DIR)/tclInt.h $(GENERIC_DIR)/tclIntDecls.h \
- $(GENERIC_DIR)/tclIntPlatDecls.h \
- $(UNIX_DIR)/tclUnixPort.h $(GENERIC_DIR)/tclMath.h; \
+ $(GENERIC_DIR)/tclIntPlatDecls.h $(GENERIC_DIR)/tclPort.h \
+ $(UNIX_DIR)/tclUnixPort.h; \
do \
- $(INSTALL_DATA) $$i $(PRIVATE_INCLUDE_INSTALL_DIR); \
+ $(INSTALL_DATA) $$i "$(PRIVATE_INCLUDE_INSTALL_DIR)"; \
done;
- @sed -e 's#\.\./unix/##' $(GENERIC_DIR)/tclPort.h > tclPort.h; \
- $(INSTALL_DATA) tclPort.h $(PRIVATE_INCLUDE_INSTALL_DIR); \
- rm -f tclPort.h
+ @if test -f tclConfig.h; then\
+ $(INSTALL_DATA) tclConfig.h "$(PRIVATE_INCLUDE_INSTALL_DIR)"; \
+ fi;
Makefile: $(UNIX_DIR)/Makefile.in $(DLTEST_DIR)/Makefile.in
$(SHELL) config.status
+#tclConfig.h: $(UNIX_DIR)/tclConfig.h.in
+# $(SHELL) config.status
clean:
rm -f *.a *.o libtcl* core errs *~ \#* TAGS *.E a.out \
- errors tclsh tcltest lib.exp Tcl @DTRACE_HDR@
+ errors ${TCL_EXE} tcltest@EXEEXT@ lib.exp Tcl @DTRACE_HDR@
cd dltest ; $(MAKE) clean
distclean: clean
rm -rf Makefile config.status config.cache config.log tclConfig.sh \
- $(PACKAGE).* prototype *.plist Tcl.framework
+ $(PACKAGE).* prototype tclConfig.h *.plist Tcl.framework
cd dltest ; $(MAKE) distclean
depend:
makedepend -- $(DEPEND_SWITCHES) -- $(SRCS)
-# Test binaries. The rules for tclTestInit.o and xtTestInit.o are
-# complicated because they are compiled from tclAppInit.c. Can't use
-# the "-o" option because this doesn't work on some strange compilers
-# (e.g. UnixWare).
+# Test binaries. The rules for tclTestInit.o and xtTestInit.o are complicated
+# because they are compiled from tclAppInit.c. Can't use the "-o" option
+# because this doesn't work on some strange compilers (e.g. UnixWare).
+#
# To enable concurrent parallel make of tclsh and tcltest resp xttest, these
# targets have to depend on tclsh, this ensures that linking of tclsh with
# tclAppInit.o does not execute concurrently with the renaming and recompiling
# of that same object file in the targets below.
-tclTestInit.o: $(UNIX_DIR)/tclAppInit.c tclsh
+tclTestInit.o: $(UNIX_DIR)/tclAppInit.c ${TCL_EXE}
@if test -f tclAppInit.o ; then \
rm -f tclAppInit.sav; \
mv tclAppInit.o tclAppInit.sav; \
@@ -809,7 +905,7 @@ tclTestInit.o: $(UNIX_DIR)/tclAppInit.c tclsh
mv tclAppInit.sav tclAppInit.o; \
fi;
-xtTestInit.o: $(UNIX_DIR)/tclAppInit.c tclsh
+xtTestInit.o: $(UNIX_DIR)/tclAppInit.c ${TCL_EXE}
@if test -f tclAppInit.o ; then \
rm -f tclAppInit.sav; \
mv tclAppInit.o tclAppInit.sav; \
@@ -827,6 +923,12 @@ xtTestInit.o: $(UNIX_DIR)/tclAppInit.c tclsh
REGHDRS=$(GENERIC_DIR)/regex.h $(GENERIC_DIR)/regguts.h \
$(GENERIC_DIR)/regcustom.h
+TCLREHDRS=$(GENERIC_DIR)/tclRegexp.h
+COMPILEHDR=$(GENERIC_DIR)/tclCompile.h
+FSHDR=$(GENERIC_DIR)/tclFileSystem.h
+IOHDR=$(GENERIC_DIR)/tclIO.h
+MATHHDRS=$(GENERIC_DIR)/tommath.h $(GENERIC_DIR)/tclTomMath.h
+
regcomp.o: $(REGHDRS) $(GENERIC_DIR)/regcomp.c $(GENERIC_DIR)/regc_lex.c \
$(GENERIC_DIR)/regc_color.c $(GENERIC_DIR)/regc_locale.c \
$(GENERIC_DIR)/regc_nfa.c $(GENERIC_DIR)/regc_cvec.c
@@ -850,7 +952,7 @@ tclAlloc.o: $(GENERIC_DIR)/tclAlloc.c
tclAsync.o: $(GENERIC_DIR)/tclAsync.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclAsync.c
-tclBasic.o: $(GENERIC_DIR)/tclBasic.c
+tclBasic.o: $(GENERIC_DIR)/tclBasic.c $(COMPILEHDR) $(MATHHDRS)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclBasic.c
tclBinary.o: $(GENERIC_DIR)/tclBinary.c
@@ -865,24 +967,30 @@ tclClock.o: $(GENERIC_DIR)/tclClock.c
tclCmdAH.o: $(GENERIC_DIR)/tclCmdAH.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCmdAH.c
-tclCmdIL.o: $(GENERIC_DIR)/tclCmdIL.c
+tclCmdIL.o: $(GENERIC_DIR)/tclCmdIL.c $(TCLREHDRS)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCmdIL.c
-tclCmdMZ.o: $(GENERIC_DIR)/tclCmdMZ.c
+tclCmdMZ.o: $(GENERIC_DIR)/tclCmdMZ.c $(TCLREHDRS)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCmdMZ.c
tclDate.o: $(GENERIC_DIR)/tclDate.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclDate.c
-tclCompCmds.o: $(GENERIC_DIR)/tclCompCmds.c
+tclCompCmds.o: $(GENERIC_DIR)/tclCompCmds.c $(COMPILEHDR)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCompCmds.c
-tclCompExpr.o: $(GENERIC_DIR)/tclCompExpr.c
+tclCompExpr.o: $(GENERIC_DIR)/tclCompExpr.c $(COMPILEHDR)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCompExpr.c
-tclCompile.o: $(GENERIC_DIR)/tclCompile.c
+tclCompile.o: $(GENERIC_DIR)/tclCompile.c $(COMPILEHDR)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCompile.c
+tclConfig.o: $(GENERIC_DIR)/tclConfig.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclConfig.c
+
+tclDictObj.o: $(GENERIC_DIR)/tclDictObj.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclDictObj.c
+
tclEncoding.o: $(GENERIC_DIR)/tclEncoding.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclEncoding.c
@@ -892,13 +1000,13 @@ tclEnv.o: $(GENERIC_DIR)/tclEnv.c
tclEvent.o: $(GENERIC_DIR)/tclEvent.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclEvent.c
-tclExecute.o: $(GENERIC_DIR)/tclExecute.c
+tclExecute.o: $(GENERIC_DIR)/tclExecute.c $(COMPILEHDR) $(MATHHDRS)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclExecute.c
tclFCmd.o: $(GENERIC_DIR)/tclFCmd.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclFCmd.c
-tclFileName.o: $(GENERIC_DIR)/tclFileName.c
+tclFileName.o: $(GENERIC_DIR)/tclFileName.c $(FSHDR) $(TCLREHDRS)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclFileName.c
tclGet.o: $(GENERIC_DIR)/tclGet.c
@@ -916,31 +1024,34 @@ tclIndexObj.o: $(GENERIC_DIR)/tclIndexObj.c
tclInterp.o: $(GENERIC_DIR)/tclInterp.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclInterp.c
-tclIO.o: $(GENERIC_DIR)/tclIO.c
+tclIO.o: $(GENERIC_DIR)/tclIO.c $(IOHDR)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclIO.c
tclIOCmd.o: $(GENERIC_DIR)/tclIOCmd.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclIOCmd.c
-tclIOGT.o: $(GENERIC_DIR)/tclIOGT.c
+tclIOGT.o: $(GENERIC_DIR)/tclIOGT.c $(IOHDR)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclIOGT.c
tclIOSock.o: $(GENERIC_DIR)/tclIOSock.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclIOSock.c
-tclIOUtil.o: $(GENERIC_DIR)/tclIOUtil.c
+tclIOUtil.o: $(GENERIC_DIR)/tclIOUtil.c $(FSHDR)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclIOUtil.c
+tclIORChan.o: $(GENERIC_DIR)/tclIORChan.c $(IOHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclIORChan.c
+
tclLink.o: $(GENERIC_DIR)/tclLink.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclLink.c
tclListObj.o: $(GENERIC_DIR)/tclListObj.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclListObj.c
-tclLiteral.o: $(GENERIC_DIR)/tclLiteral.c
+tclLiteral.o: $(GENERIC_DIR)/tclLiteral.c $(COMPILEHDR)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclLiteral.c
-tclObj.o: $(GENERIC_DIR)/tclObj.c
+tclObj.o: $(GENERIC_DIR)/tclObj.c $(COMPILEHDR) $(MATHHDRS)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclObj.c
tclLoad.o: $(GENERIC_DIR)/tclLoad.c
@@ -949,9 +1060,6 @@ tclLoad.o: $(GENERIC_DIR)/tclLoad.c
tclLoadAix.o: $(UNIX_DIR)/tclLoadAix.c
$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclLoadAix.c
-tclLoadAout.o: $(UNIX_DIR)/tclLoadAout.c
- $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclLoadAout.c
-
tclLoadDl.o: $(UNIX_DIR)/tclLoadDl.c
$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclLoadDl.c
@@ -985,28 +1093,52 @@ tclNotify.o: $(GENERIC_DIR)/tclNotify.c
tclParse.o: $(GENERIC_DIR)/tclParse.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclParse.c
-tclParseExpr.o: $(GENERIC_DIR)/tclParseExpr.c
- $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclParseExpr.c
-
tclPanic.o: $(GENERIC_DIR)/tclPanic.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclPanic.c
+tclPathObj.o: $(GENERIC_DIR)/tclPathObj.c $(FSHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclPathObj.c
+
tclPipe.o: $(GENERIC_DIR)/tclPipe.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclPipe.c
tclPkg.o: $(GENERIC_DIR)/tclPkg.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclPkg.c
+# TIP #59, embedding of configuration information into the binary library.
+#
+# Part of Tcl's configuration information are the paths where it was installed
+# and where it will look for its libraries (which can be different). We derive
+# this information from the variables which can be overridden by the user. As
+# every path can be configured separately we do not remember one general
+# prefix/exec_prefix but all the different paths individually.
+
+tclPkgConfig.o: $(GENERIC_DIR)/tclPkgConfig.c
+ $(CC) -c $(CC_SWITCHES) \
+ -DCFG_INSTALL_LIBDIR="\"$(LIB_INSTALL_DIR)\"" \
+ -DCFG_INSTALL_BINDIR="\"$(BIN_INSTALL_DIR)\"" \
+ -DCFG_INSTALL_SCRDIR="\"$(SCRIPT_INSTALL_DIR)\"" \
+ -DCFG_INSTALL_INCDIR="\"$(INCLUDE_INSTALL_DIR)\"" \
+ -DCFG_INSTALL_DOCDIR="\"$(MAN_INSTALL_DIR)\"" \
+ \
+ -DCFG_RUNTIME_LIBDIR="\"$(libdir)\"" \
+ -DCFG_RUNTIME_BINDIR="\"$(bindir)\"" \
+ -DCFG_RUNTIME_SCRDIR="\"$(TCL_LIBRARY)\"" \
+ -DCFG_RUNTIME_INCDIR="\"$(includedir)\"" \
+ -DCFG_RUNTIME_DOCDIR="\"$(mandir)\"" \
+ \
+ $(GENERIC_DIR)/tclPkgConfig.c
+
tclPosixStr.o: $(GENERIC_DIR)/tclPosixStr.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclPosixStr.c
tclPreserve.o: $(GENERIC_DIR)/tclPreserve.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclPreserve.c
-tclProc.o: $(GENERIC_DIR)/tclProc.c
+tclProc.o: $(GENERIC_DIR)/tclProc.c $(COMPILEHDR)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclProc.c
-tclRegexp.o: $(GENERIC_DIR)/tclRegexp.c
+tclRegexp.o: $(GENERIC_DIR)/tclRegexp.c $(TCLREHDRS)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclRegexp.c
tclResolve.o: $(GENERIC_DIR)/tclResolve.c
@@ -1018,12 +1150,18 @@ tclResult.o: $(GENERIC_DIR)/tclResult.c
tclScan.o: $(GENERIC_DIR)/tclScan.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclScan.c
-tclStringObj.o: $(GENERIC_DIR)/tclStringObj.c
+tclStringObj.o: $(GENERIC_DIR)/tclStringObj.c $(MATHHDRS)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclStringObj.c
+tclStrToD.o: $(GENERIC_DIR)/tclStrToD.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclStrToD.c
+
tclStubInit.o: $(GENERIC_DIR)/tclStubInit.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclStubInit.c
+tclTrace.o: $(GENERIC_DIR)/tclTrace.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclTrace.c
+
tclUtil.o: $(GENERIC_DIR)/tclUtil.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclUtil.c
@@ -1033,10 +1171,10 @@ tclUtf.o: $(GENERIC_DIR)/tclUtf.c $(GENERIC_DIR)/tclUniData.c
tclVar.o: $(GENERIC_DIR)/tclVar.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclVar.c
-tclTest.o: $(GENERIC_DIR)/tclTest.c
+tclTest.o: $(GENERIC_DIR)/tclTest.c $(IOHDR) $(TCLREHDRS)
$(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tclTest.c
-tclTestObj.o: $(GENERIC_DIR)/tclTestObj.c
+tclTestObj.o: $(GENERIC_DIR)/tclTestObj.c $(MATHHDRS)
$(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tclTestObj.c
tclTestProcBodyObj.o: $(GENERIC_DIR)/tclTestProcBodyObj.c
@@ -1054,10 +1192,208 @@ tclThreadAlloc.o: $(GENERIC_DIR)/tclThreadAlloc.c
tclThreadJoin.o: $(GENERIC_DIR)/tclThreadJoin.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThreadJoin.c
+tclThreadStorage.o: $(GENERIC_DIR)/tclThreadStorage.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThreadStorage.c
+
tclThreadTest.o: $(GENERIC_DIR)/tclThreadTest.c
$(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tclThreadTest.c
-tclUnixChan.o: $(UNIX_DIR)/tclUnixChan.c
+tclTomMathInterface.o: $(GENERIC_DIR)/tclTomMathInterface.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclTomMathInterface.c
+
+bncore.o: $(TOMMATH_DIR)/bncore.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bncore.c
+
+bn_reverse.o: $(TOMMATH_DIR)/bn_reverse.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_reverse.c
+
+bn_fast_s_mp_mul_digs.o: $(TOMMATH_DIR)/bn_fast_s_mp_mul_digs.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_fast_s_mp_mul_digs.c
+
+bn_fast_s_mp_sqr.o: $(TOMMATH_DIR)/bn_fast_s_mp_sqr.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_fast_s_mp_sqr.c
+
+bn_mp_add.o: $(TOMMATH_DIR)/bn_mp_add.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_add.c
+
+bn_mp_add_d.o: $(TOMMATH_DIR)/bn_mp_add_d.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_add_d.c
+
+bn_mp_and.o: $(TOMMATH_DIR)/bn_mp_and.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_and.c
+
+bn_mp_clamp.o: $(TOMMATH_DIR)/bn_mp_clamp.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_clamp.c
+
+bn_mp_clear.o: $(TOMMATH_DIR)/bn_mp_clear.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_clear.c
+
+bn_mp_clear_multi.o: $(TOMMATH_DIR)/bn_mp_clear_multi.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_clear_multi.c
+
+bn_mp_cmp.o: $(TOMMATH_DIR)/bn_mp_cmp.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_cmp.c
+
+bn_mp_cmp_d.o: $(TOMMATH_DIR)/bn_mp_cmp_d.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_cmp_d.c
+
+bn_mp_cmp_mag.o: $(TOMMATH_DIR)/bn_mp_cmp_mag.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_cmp_mag.c
+
+bn_mp_cnt_lsb.o: $(TOMMATH_DIR)/bn_mp_cnt_lsb.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_cnt_lsb.c
+
+bn_mp_copy.o: $(TOMMATH_DIR)/bn_mp_copy.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_copy.c
+
+bn_mp_count_bits.o: $(TOMMATH_DIR)/bn_mp_count_bits.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_count_bits.c
+
+bn_mp_div.o: $(TOMMATH_DIR)/bn_mp_div.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div.c
+
+bn_mp_div_d.o: $(TOMMATH_DIR)/bn_mp_div_d.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_d.c
+
+bn_mp_div_2.o: $(TOMMATH_DIR)/bn_mp_div_2.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_2.c
+
+bn_mp_div_2d.o: $(TOMMATH_DIR)/bn_mp_div_2d.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_2d.c
+
+bn_mp_div_3.o: $(TOMMATH_DIR)/bn_mp_div_3.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_3.c
+
+bn_mp_exch.o: $(TOMMATH_DIR)/bn_mp_exch.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_exch.c
+
+bn_mp_expt_d.o: $(TOMMATH_DIR)/bn_mp_expt_d.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_expt_d.c
+
+bn_mp_grow.o: $(TOMMATH_DIR)/bn_mp_grow.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_grow.c
+
+bn_mp_init.o: $(TOMMATH_DIR)/bn_mp_init.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init.c
+
+bn_mp_init_copy.o: $(TOMMATH_DIR)/bn_mp_init_copy.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init_copy.c
+
+bn_mp_init_multi.o: $(TOMMATH_DIR)/bn_mp_init_multi.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init_multi.c
+
+bn_mp_init_set.o: $(TOMMATH_DIR)/bn_mp_init_set.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init_set.c
+
+bn_mp_init_set_int.o: $(TOMMATH_DIR)/bn_mp_init_set_int.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init_set_int.c
+
+bn_mp_init_size.o:$(TOMMATH_DIR)/bn_mp_init_size.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init_size.c
+
+bn_mp_karatsuba_mul.o: $(TOMMATH_DIR)/bn_mp_karatsuba_mul.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_karatsuba_mul.c
+
+bn_mp_karatsuba_sqr.o: $(TOMMATH_DIR)/bn_mp_karatsuba_sqr.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_karatsuba_sqr.c
+
+bn_mp_lshd.o: $(TOMMATH_DIR)/bn_mp_lshd.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_lshd.c
+
+bn_mp_mod.o: $(TOMMATH_DIR)/bn_mp_mod.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_mod.c
+
+bn_mp_mod_2d.o: $(TOMMATH_DIR)/bn_mp_mod_2d.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_mod_2d.c
+
+bn_mp_mul.o: $(TOMMATH_DIR)/bn_mp_mul.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_mul.c
+
+bn_mp_mul_2.o: $(TOMMATH_DIR)/bn_mp_mul_2.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_mul_2.c
+
+bn_mp_mul_2d.o: $(TOMMATH_DIR)/bn_mp_mul_2d.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_mul_2d.c
+
+bn_mp_mul_d.o: $(TOMMATH_DIR)/bn_mp_mul_d.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_mul_d.c
+
+bn_mp_neg.o: $(TOMMATH_DIR)/bn_mp_neg.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_neg.c
+
+bn_mp_or.o: $(TOMMATH_DIR)/bn_mp_or.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_or.c
+
+bn_mp_radix_size.o: $(TOMMATH_DIR)/bn_mp_radix_size.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_radix_size.c
+
+bn_mp_radix_smap.o: $(TOMMATH_DIR)/bn_mp_radix_smap.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_radix_smap.c
+
+bn_mp_read_radix.o: $(TOMMATH_DIR)/bn_mp_read_radix.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_read_radix.c
+
+bn_mp_rshd.o: $(TOMMATH_DIR)/bn_mp_rshd.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_rshd.c
+
+bn_mp_set.o: $(TOMMATH_DIR)/bn_mp_set.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_set.c
+
+bn_mp_set_int.o: $(TOMMATH_DIR)/bn_mp_set_int.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_set_int.c
+
+bn_mp_shrink.o: $(TOMMATH_DIR)/bn_mp_shrink.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_shrink.c
+
+bn_mp_sqr.o: $(TOMMATH_DIR)/bn_mp_sqr.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_sqr.c
+
+bn_mp_sqrt.o: $(TOMMATH_DIR)/bn_mp_sqrt.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_sqrt.c
+
+bn_mp_sub.o: $(TOMMATH_DIR)/bn_mp_sub.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_sub.c
+
+bn_mp_sub_d.o: $(TOMMATH_DIR)/bn_mp_sub_d.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_sub_d.c
+
+bn_mp_to_unsigned_bin.o: $(TOMMATH_DIR)/bn_mp_to_unsigned_bin.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_to_unsigned_bin.c
+
+bn_mp_to_unsigned_bin_n.o: $(TOMMATH_DIR)/bn_mp_to_unsigned_bin_n.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_to_unsigned_bin_n.c
+
+bn_mp_toom_mul.o: $(TOMMATH_DIR)/bn_mp_toom_mul.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_toom_mul.c
+
+bn_mp_toom_sqr.o: $(TOMMATH_DIR)/bn_mp_toom_sqr.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_toom_sqr.c
+
+bn_mp_toradix_n.o: $(TOMMATH_DIR)/bn_mp_toradix_n.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_toradix_n.c
+
+bn_mp_unsigned_bin_size.o: $(TOMMATH_DIR)/bn_mp_unsigned_bin_size.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_unsigned_bin_size.c
+
+bn_mp_xor.o: $(TOMMATH_DIR)/bn_mp_xor.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_xor.c
+
+bn_mp_zero.o: $(TOMMATH_DIR)/bn_mp_zero.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_zero.c
+
+bn_s_mp_add.o: $(TOMMATH_DIR)/bn_s_mp_add.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_s_mp_add.c
+
+bn_s_mp_mul_digs.o: $(TOMMATH_DIR)/bn_s_mp_mul_digs.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_s_mp_mul_digs.c
+
+bn_s_mp_sqr.o: $(TOMMATH_DIR)/bn_s_mp_sqr.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_s_mp_sqr.c
+
+bn_s_mp_sub.o: $(TOMMATH_DIR)/bn_s_mp_sub.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_s_mp_sub.c
+
+tclUnixChan.o: $(UNIX_DIR)/tclUnixChan.c $(IOHDR)
$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixChan.c
tclUnixEvent.o: $(UNIX_DIR)/tclUnixEvent.c
@@ -1066,7 +1402,7 @@ tclUnixEvent.o: $(UNIX_DIR)/tclUnixEvent.c
tclUnixFCmd.o: $(UNIX_DIR)/tclUnixFCmd.c
$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixFCmd.c
-tclUnixFile.o: $(UNIX_DIR)/tclUnixFile.c
+tclUnixFile.o: $(UNIX_DIR)/tclUnixFile.c $(FSHDR)
$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixFile.c
tclUnixNotfy.o: $(UNIX_DIR)/tclUnixNotfy.c
@@ -1087,7 +1423,7 @@ tclUnixThrd.o: $(UNIX_DIR)/tclUnixThrd.c
tclUnixTime.o: $(UNIX_DIR)/tclUnixTime.c
$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixTime.c
-tclUnixInit.o: $(UNIX_DIR)/tclUnixInit.c $(GENERIC_DIR)/tclInitScript.h tclConfig.sh
+tclUnixInit.o: $(UNIX_DIR)/tclUnixInit.c tclConfig.sh
$(CC) -c $(CC_SWITCHES) -DTCL_LIBRARY=\"${TCL_LIBRARY}\" \
-DTCL_PACKAGE_PATH="\"${TCL_PACKAGE_PATH}\"" \
$(UNIX_DIR)/tclUnixInit.c
@@ -1099,6 +1435,9 @@ tclUnixCompat.o: $(UNIX_DIR)/tclUnixCompat.c
tclMacOSXBundle.o: $(MAC_OSX_DIR)/tclMacOSXBundle.c
$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tclMacOSXBundle.c
+tclMacOSXFCmd.o: $(MAC_OSX_DIR)/tclMacOSXFCmd.c
+ $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tclMacOSXFCmd.c
+
tclMacOSXNotify.o: $(MAC_OSX_DIR)/tclMacOSXNotify.c
$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tclMacOSXNotify.c
@@ -1112,9 +1451,9 @@ $(DTRACE_HDR): $(DTRACE_SRC)
$(DTRACE_OBJ): $(DTRACE_SRC) $(TCL_OBJS)
$(DTRACE) -G $(DTRACE_SWITCHES) -o $@ -s $(DTRACE_SRC) $(TCL_OBJS)
-# The following targets are not completely general. They are provide
-# purely for documentation purposes so people who are interested in
-# the Xt based notifier can modify them to suit their own installation.
+# The following targets are not completely general. They are provide purely
+# for documentation purposes so people who are interested in the Xt based
+# notifier can modify them to suit their own installation.
xttest: ${XTTEST_OBJS} ${GENERIC_OBJS} ${UNIX_OBJS} ${COMPAT_OBJS} \
@DL_OBJS@ ${BUILD_DLTEST}
@@ -1130,10 +1469,10 @@ tclXtTest.o: $(UNIX_DIR)/tclXtTest.c
$(CC) -c $(APP_CC_SWITCHES) -I/usr/openwin/include \
$(UNIX_DIR)/tclXtTest.c
-# compat binaries, these must be compiled for use in a shared library
-# even though they may be placed in a static executable or library. Since
-# they are included in both the tcl library and the stub library, they
-# need to be relocatable.
+# Compat binaries, these must be compiled for use in a shared library even
+# though they may be placed in a static executable or library. Since they are
+# included in both the tcl library and the stub library, they need to be
+# relocatable.
fixstrtod.o: $(COMPAT_DIR)/fixstrtod.c
$(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/fixstrtod.c
@@ -1156,18 +1495,9 @@ strtod.o: $(COMPAT_DIR)/strtod.c
strtol.o: $(COMPAT_DIR)/strtol.c
$(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/strtol.c
-strtoll.o: $(COMPAT_DIR)/strtoll.c
- $(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/strtoll.c
-
strtoul.o: $(COMPAT_DIR)/strtoul.c
$(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/strtoul.c
-strtoull.o: $(COMPAT_DIR)/strtoull.c
- $(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/strtoull.c
-
-tmpnam.o: $(COMPAT_DIR)/tmpnam.c
- $(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/tmpnam.c
-
waitpid.o: $(COMPAT_DIR)/waitpid.c
$(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/waitpid.c
@@ -1185,14 +1515,15 @@ tclStubLib.o: $(GENERIC_DIR)/tclStubLib.c
#
$(GENERIC_DIR)/tclStubInit.c: $(GENERIC_DIR)/tcl.decls \
- $(GENERIC_DIR)/tclInt.decls
+ $(GENERIC_DIR)/tclInt.decls $(GENERIC_DIR)/tclTomMath.decls
@echo "Warning: tclStubInit.c may be out of date."
@echo "Developers may want to run \"make genstubs\" to regenerate."
@echo "This warning can be safely ignored, do not report as a bug!"
genstubs:
$(TCL_EXE) $(TOOL_DIR)/genStubs.tcl $(GENERIC_DIR) \
- $(GENERIC_DIR)/tcl.decls $(GENERIC_DIR)/tclInt.decls
+ $(GENERIC_DIR)/tcl.decls $(GENERIC_DIR)/tclInt.decls \
+ $(GENERIC_DIR)/tclTomMath.decls
#
# Target to check that all exported functions have an entry in the stubs
@@ -1213,9 +1544,8 @@ checkstubs: $(TCL_LIB_FILE)
done
#
-# Target to check that all public APIs which are not command
-# implementations have an entry in section three of the distributed
-# manpages.
+# Target to check that all public APIs which are not command implementations
+# have an entry in section three of the distributed manpages.
#
checkdoc: $(TCL_LIB_FILE)
@@ -1238,8 +1568,7 @@ checkuchar:
-egrep isalnum\|isalpha\|iscntrl\|isdigit\|islower\|isprint\|ispunct\|isspace\|isupper\|isxdigit\|toupper\|tolower $(SRCS) | grep -v UCHAR
#
-# Target to make sure that only symbols with "Tcl" prefixes are
-# exported.
+# Target to make sure that only symbols with "Tcl" prefixes are exported.
#
checkexports: $(TCL_LIB_FILE)
@@ -1248,42 +1577,49 @@ checkexports: $(TCL_LIB_FILE)
| sort -n | grep -E -v '^[Tt]cl' || true
#
-# Target to create a Tcl RPM for Linux. Requires that you be on a Linux
+# Target to create a Tcl RPM for Linux. Requires that you be on a Linux
# system.
#
-rpm: all /bin/rpm
+rpm: all
rm -f THIS.TCL.SPEC
echo "%define _builddir `pwd`" > THIS.TCL.SPEC
echo "%define _rpmdir `pwd`/RPMS" >> THIS.TCL.SPEC
cat tcl.spec >> THIS.TCL.SPEC
mkdir -p RPMS/i386
- rpm -bb THIS.TCL.SPEC
+ rpmbuild -bb THIS.TCL.SPEC
mv RPMS/i386/*.rpm .
rm -rf RPMS THIS.TCL.SPEC
#
-# Target to create a proper Tcl distribution from information in the
-# master source directory. DISTDIR must be defined to indicate where
-# to put the distribution. DISTDIR must be an absolute path name.
+# Target to create a proper Tcl distribution from information in the master
+# source directory. DISTDIR must be defined to indicate where to put the
+# distribution. DISTDIR must be an absolute path name.
#
DISTROOT = /tmp/dist
DISTNAME = tcl${VERSION}${PATCH_LEVEL}
ZIPNAME = tcl${MAJOR_VERSION}${MINOR_VERSION}${PATCH_LEVEL}-src.zip
DISTDIR = $(DISTROOT)/$(DISTNAME)
-
-dist:
+$(UNIX_DIR)/configure: $(UNIX_DIR)/configure.in $(UNIX_DIR)/tcl.m4 \
+ $(UNIX_DIR)/aclocal.m4
+ cd $(UNIX_DIR); autoconf
+$(MAC_OSX_DIR)/configure: $(MAC_OSX_DIR)/configure.ac $(UNIX_DIR)/configure
+ cd $(MAC_OSX_DIR); autoconf
+$(UNIX_DIR)/tclConfig.h.in: $(MAC_OSX_DIR)/configure
+ cd $(MAC_OSX_DIR); autoheader; touch $@
+
+dist: $(UNIX_DIR)/configure $(UNIX_DIR)/tclConfig.h.in $(MAC_OSX_DIR)/configure genstubs
rm -rf $(DISTDIR)
mkdir -p $(DISTDIR)/unix
- cp -p $(UNIX_DIR)/*.c $(UNIX_DIR)/*.h $(DISTDIR)/unix
+ cp -p $(UNIX_DIR)/*.[ch] $(DISTDIR)/unix
cp $(UNIX_DIR)/Makefile.in $(DISTDIR)/unix
chmod 664 $(DISTDIR)/unix/Makefile.in
cp $(UNIX_DIR)/configure $(UNIX_DIR)/configure.in \
$(UNIX_DIR)/tcl.m4 $(UNIX_DIR)/aclocal.m4 \
$(UNIX_DIR)/tclConfig.sh.in $(UNIX_DIR)/install-sh \
$(UNIX_DIR)/README $(UNIX_DIR)/ldAix $(UNIX_DIR)/tcl.spec \
- $(UNIX_DIR)/installManPage \
+ $(UNIX_DIR)/installManPage $(UNIX_DIR)/tclConfig.h.in \
$(DISTDIR)/unix
chmod 775 $(DISTDIR)/unix/configure $(DISTDIR)/unix/configure.in
chmod 775 $(DISTDIR)/unix/ldAix
@@ -1299,20 +1635,25 @@ dist:
mkdir $(DISTDIR)/library
cp -p $(TOP_DIR)/license.terms $(TOP_DIR)/library/*.tcl \
$(TOP_DIR)/library/tclIndex $(DISTDIR)/library
- for i in http1.0 http opt msgcat reg dde tcltest; \
+ for i in http1.0 http opt msgcat reg dde tcltest platform; \
do \
mkdir $(DISTDIR)/library/$$i ;\
cp -p $(TOP_DIR)/library/$$i/*.tcl $(DISTDIR)/library/$$i; \
done;
mkdir $(DISTDIR)/library/encoding
cp -p $(TOP_DIR)/library/encoding/*.enc $(DISTDIR)/library/encoding
+ mkdir $(DISTDIR)/library/msgs
+ cp -p $(TOP_DIR)/library/msgs/*.msg $(DISTDIR)/library/msgs
+ ( cd $(TOP_DIR); \
+ find library/tzdata -name CVS -prune -o -type f -print ) \
+ | ( cd $(TOP_DIR) ; xargs tar cf - ) \
+ | ( cd $(DISTDIR) ; tar xfp - )
mkdir $(DISTDIR)/doc
cp -p $(TOP_DIR)/license.terms $(TOP_DIR)/doc/*.[13n] \
$(TOP_DIR)/doc/man.macros $(DISTDIR)/doc
mkdir $(DISTDIR)/compat
- cp -p $(TOP_DIR)/license.terms $(COMPAT_DIR)/*.c \
- $(COMPAT_DIR)/*.h $(COMPAT_DIR)/README \
- $(DISTDIR)/compat
+ cp -p $(TOP_DIR)/license.terms $(COMPAT_DIR)/*.[ch] \
+ $(COMPAT_DIR)/README $(DISTDIR)/compat
mkdir $(DISTDIR)/tests
cp -p $(TOP_DIR)/license.terms $(DISTDIR)/tests
cp -p $(TOP_DIR)/tests/*.test $(TOP_DIR)/tests/README \
@@ -1324,8 +1665,7 @@ dist:
$(TOP_DIR)/win/tclConfig.sh.in \
$(TOP_DIR)/win/tcl.m4 $(TOP_DIR)/win/aclocal.m4 \
$(DISTDIR)/win
- cp -p $(TOP_DIR)/win/*.c $(TOP_DIR)/win/*.h \
- $(TOP_DIR)/win/*.ico $(TOP_DIR)/win/*.rc \
+ cp -p $(TOP_DIR)/win/*.[ch] $(TOP_DIR)/win/*.ico $(TOP_DIR)/win/*.rc \
$(DISTDIR)/win
cp -p $(TOP_DIR)/win/*.bat $(DISTDIR)/win
$(TCL_EXE) $(TOOL_DIR)/eolFix.tcl -crlf $(DISTDIR)/win/*.bat
@@ -1341,21 +1681,18 @@ dist:
$(TCL_EXE) $(TOOL_DIR)/eolFix.tcl -crlf $(DISTDIR)/win/tcl.ds*
cp -p $(TOP_DIR)/win/README $(DISTDIR)/win
cp -p $(TOP_DIR)/license.terms $(DISTDIR)/win
- mkdir $(DISTDIR)/mac
- cp -p $(TOP_DIR)/mac/tcl*.sea.hqx \
- $(TOP_DIR)/mac/*.c $(TOP_DIR)/mac/*.h $(TOP_DIR)/mac/*.r \
- $(DISTDIR)/mac
- cp -p $(TOP_DIR)/mac/porting.notes $(TOP_DIR)/mac/README $(DISTDIR)/mac
- cp -p $(TOP_DIR)/mac/*.pch $(DISTDIR)/mac
- cp -p $(TOP_DIR)/mac/*.doc $(TOP_DIR)/mac/*.html $(DISTDIR)/mac
- cp -p $(TOP_DIR)/license.terms $(DISTDIR)/mac
mkdir $(DISTDIR)/macosx
- cp -p $(MAC_OSX_DIR)/Makefile $(MAC_OSX_DIR)/README \
+ cp -p $(MAC_OSX_DIR)/GNUmakefile $(MAC_OSX_DIR)/README \
$(MAC_OSX_DIR)/*.c $(MAC_OSX_DIR)/*.in \
- $(DISTDIR)/macosx
+ $(MAC_OSX_DIR)/*.ac $(MAC_OSX_DIR)/*.xcconfig \
+ $(MAC_OSX_DIR)/configure $(DISTDIR)/macosx
cp -p $(TOP_DIR)/license.terms $(DISTDIR)/macosx
mkdir $(DISTDIR)/macosx/Tcl.pbproj
cp -p $(MAC_OSX_DIR)/Tcl.pbproj/*.pbx* $(DISTDIR)/macosx/Tcl.pbproj
+ mkdir $(DISTDIR)/macosx/Tcl.xcode
+ cp -p $(MAC_OSX_DIR)/Tcl.xcode/*.pbx* $(DISTDIR)/macosx/Tcl.xcode
+ mkdir $(DISTDIR)/macosx/Tcl.xcodeproj
+ cp -p $(TOP_DIR)/macosx/Tcl.xcodeproj/*.pbx* $(DISTDIR)/macosx/Tcl.xcodeproj
mkdir $(DISTDIR)/unix/dltest
cp -p $(UNIX_DIR)/dltest/*.c $(UNIX_DIR)/dltest/Makefile.in \
$(UNIX_DIR)/dltest/README \
@@ -1369,11 +1706,9 @@ dist:
$(DISTDIR)/tools
$(TCL_EXE) $(TOOL_DIR)/eolFix.tcl -crlf $(DISTDIR)/tools/tcl.hpj.in \
$(DISTDIR)/tools/tcl.wse.in
-
-#
-# The following target can only be used for non-patch releases. Use
-# the "allpatch" target below for patch releases.
-#
+ mkdir $(DISTDIR)/libtommath
+ cp -p $(TOMMATH_SRCS) $(TOMMATH_DIR)/*.h \
+ $(DISTDIR)/libtommath
alldist: dist
rm -f $(DISTROOT)/$(DISTNAME)-src.tar.gz $(DISTROOT)/$(ZIPNAME)
@@ -1381,79 +1716,45 @@ alldist: dist
gzip -9 $(DISTNAME)-src.tar; zip -qr8 $(ZIPNAME) $(DISTNAME)
#
-# The target below is similar to "alldist" except it works for patch
-# releases. It is needed because patch releases are peculiar: the
-# patch designation appears in the name of the compressed file
-# (e.g. tcl8.0p1.tar.gz) but the extracted source directory doesn't
-# include the patch designation (e.g. tcl8.0).
+# This target creates the HTML folder for Tcl & Tk and places it in
+# DISTDIR/html. It uses the tcltk-man2html.tcl tool from the Tcl group's tool
+# workspace. It depends on the Tcl & Tk being in directories called tcl8.* &
+# tk8.* up two directories from the TOOL_DIR.
#
-allpatch: dist
- rm -f $(DISTROOT)/$(DISTNAME)-src.tar.gz $(DISTROOT)/$(ZIPNAME)
- mv $(DISTROOT)/tcl${VERSION} $(DISTROOT)/old
- mv $(DISTROOT)/$(DISTNAME) $(DISTROOT)/tcl${VERSION}
- cd $(DISTROOT); tar cf $(DISTNAME)-src.tar tcl${VERSION}; \
- gzip -9 $(DISTNAME)-src.tar; zip -r8 $(ZIPNAME) tcl${VERSION}
- mv $(DISTROOT)/tcl${VERSION} $(DISTROOT)/$(DISTNAME)
- mv $(DISTROOT)/old $(DISTROOT)/tcl${VERSION}
-
-#
-# This target creates the HTML folder for Tcl & Tk and places it
-# in DISTDIR/html. It uses the tcltk-man2html.tcl tool from
-# the Tcl group's tool workspace. It depends on the Tcl & Tk being
-# in directories called tcl8.* & tk8.* up two directories from the
-# TOOL_DIR.
-#
-
-html: tclsh
+html: ${TCL_EXE}
$(BUILD_HTML)
@EXTRA_BUILD_HTML@
-html-tcl: tclsh
+html-tcl: ${TCL_EXE}
$(BUILD_HTML) --tcl
@EXTRA_BUILD_HTML@
-html-tk: tclsh
+html-tk: ${TCL_EXE}
$(BUILD_HTML) --tk
@EXTRA_BUILD_HTML@
BUILD_HTML = \
- @@LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
+ @@LD_LIBRARY_PATH_VAR@="`pwd`:$${@LD_LIBRARY_PATH_VAR@}"; export @LD_LIBRARY_PATH_VAR@; \
TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"; export TCL_LIBRARY; \
- ./tclsh $(TOOL_DIR)/tcltk-man2html.tcl --htmldir=$(HTML_INSTALL_DIR) \
+ ./${TCL_EXE} $(TOOL_DIR)/tcltk-man2html.tcl --htmldir="$(HTML_INSTALL_DIR)" \
--srcdir=$(TOP_DIR)/.. $(BUILD_HTML_FLAGS)
#
-# Target to create a Macintosh version of the distribution. This will
-# do a normal distribution and then massage the output to prepare it
-# for moving to the Mac platform. This requires a few scripts and
-# programs found only in the Tcl group's tool workspace.
-#
-
-macdist: dist machtml
-
-machtml:
- rm -f $(DISTDIR)/mac/tclMacProjects.sea.hqx
- rm -rf $(DISTDIR)/doc
- $(TCL_EXE) $(TOOL_DIR)/cvtEOL.tcl $(DISTDIR)
-
-#
# Targets to build Solaris package of the distribution for the current
-# architecture. To build stream packages for both sun4 and i86pc
-# architectures:
+# architecture. To build stream packages for both sun4 and i86pc
+# architectures:
#
# On the sun4 machine, execute the following:
# make distclean; ./configure
# make DISTDIR=<distdir> package
#
-# Once the build is complete, execute the following on the i86pc
-# machine:
+# Once the build is complete, execute the following on the i86pc machine:
# make DISTDIR=<distdir> package-quick
#
-# <distdir> is the absolute path to a directory where the build should
-# take place. These steps will generate the $(PACKAGE).sun4 and
-# $(PACKAGE).i86pc stream packages. It is important that the packages be
-# built in this fashion in order to ensure that the architecture
-# independent files are exactly the same, including timestamps, in
-# both packages.
+# <distdir> is the absolute path to a directory where the build should take
+# place. These steps will generate the $(PACKAGE).sun4 and $(PACKAGE).i86pc
+# stream packages. It is important that the packages be built in this fashion
+# in order to ensure that the architecture independent files are exactly the
+# same, including timestamps, in both packages.
#
PACKAGE=SCRPtcl
@@ -1492,7 +1793,7 @@ package-common:
# Build and install the architecture specific files in the dist directory.
#
-package-binaries:
+package-binaries:
cd $(DISTDIR)/unix/`arch`; \
$(MAKE); \
$(MAKE) install-binaries prefix=$(DISTDIR)/$(PACKAGE)/$(VERSION) \
diff --git a/unix/README b/unix/README
index 72c69fc2..87b151a 100644
--- a/unix/README
+++ b/unix/README
@@ -1,146 +1,168 @@
Tcl UNIX README
---------------
-This is the directory where you configure, compile, test, and install
-UNIX versions of Tcl. This directory also contains source files for Tcl
-that are specific to UNIX. Some of the files in this directory are
-used on the PC or Mac platform too, but they all depend on UNIX
-(POSIX/ANSI C) interfaces and some of them only make sense under UNIX.
+This is the directory where you configure, compile, test, and install UNIX
+versions of Tcl. This directory also contains source files for Tcl that are
+specific to UNIX. Some of the files in this directory are used on the PC or
+MacOSX platform too, but they all depend on UNIX (POSIX/ANSI C) interfaces and
+some of them only make sense under UNIX.
Updated forms of the information found in this file is available at:
http://www.tcl.tk/doc/howto/compile.html#unix
-For information on platforms where Tcl is known to compile, along
-with any porting notes for getting it to work on those platforms, see:
+For information on platforms where Tcl is known to compile, along with any
+porting notes for getting it to work on those platforms, see:
http://www.tcl.tk/software/tcltk/platforms.html
-The rest of this file contains instructions on how to do this. The
-release should compile and run either "out of the box" or with trivial
-changes on any UNIX-like system that approximates POSIX, BSD, or System
-V. We know that it runs on workstations from Sun, H-P, DEC, IBM, and
-SGI, as well as PCs running Linux, BSDI, and SCO UNIX. To compile for
-a PC running Windows, see the README file in the directory ../win. To
-compile for Max OS X, see the README in the directory ../macosx. To
-compile for a classic Macintosh, see the README file in the directory ../mac.
+The rest of this file contains instructions on how to do this. The release
+should compile and run either "out of the box" or with trivial changes on any
+UNIX-like system that approximates POSIX, BSD, or System V. We know that it
+runs on workstations from Sun, H-P, DEC, IBM, and SGI, as well as PCs running
+Linux, BSDI, and SCO UNIX. To compile for a PC running Windows, see the README
+file in the directory ../win. To compile for MacOSX, see the README file in
+the directory ../macosx.
How To Compile And Install Tcl:
-------------------------------
(a) If you have already compiled Tcl once in this directory and are now
preparing to compile again in the same directory but for a different
- platform, or if you have applied patches, type "make distclean" to
- discard all the configuration information computed previously.
+ platform, or if you have applied patches, type "make distclean" to discard
+ all the configuration information computed previously.
-(b) If you need to reconfigure because you changed any of the .in or
- .m4 files, you will need to run autoconf to create a new
- ./configure script. Most users will NOT need to do this since
- a configure script is already provided.
+(b) If you need to reconfigure because you changed any of the .in or .m4
+ files, you will need to run autoconf to create a new ./configure script.
+ Most users will NOT need to do this since a configure script is already
+ provided.
(in the tcl/unix directory)
autoconf
-(c) Type "./configure". This runs a configuration script created by GNU
- autoconf, which configures Tcl for your system and creates a
- Makefile. The configure script allows you to customize the Tcl
- configuration for your site; for details on how you can do this,
- type "./configure -help" or refer to the autoconf documentation (not
- included here). Tcl's "configure" supports the following special
- switches in addition to the standard ones:
- --enable-threads If this switch is set, Tcl will compile
- itself with multithreading support.
+(c) Type "./configure". This runs a configuration script created by GNU
+ autoconf, which configures Tcl for your system and creates a Makefile. The
+ configure script allows you to customize the Tcl configuration for your
+ site; for details on how you can do this, type "./configure --help" or
+ refer to the autoconf documentation (not included here). Tcl's "configure"
+ supports the following special switches in addition to the standard ones:
+
+ --enable-threads If this switch is set, Tcl will compile itself
+ with multithreading support.
--disable-load If this switch is specified then Tcl will
configure itself not to allow dynamic loading,
even if your system appears to support it.
- Normally you can leave this switch out and
- Tcl will build itself for dynamic loading
- if your system supports it.
+ Normally you can leave this switch out and Tcl
+ will build itself for dynamic loading if your
+ system supports it.
+ --disable-dll-unloading Disables support for the [unload] command even
+ on platforms that can support it. Meaningless
+ when Tcl is compiled with --disable-load.
--enable-shared If this switch is specified, Tcl will compile
itself as a shared library if it can figure
- out how to do that on this platform. This
- is the default on platforms where we know
- how to build shared libraries.
+ out how to do that on this platform. This is
+ the default on platforms where we know how to
+ build shared libraries.
--disable-shared If this switch is specified, Tcl will compile
itself as a static library.
- --enable-symbols build with debugging symbols. By default
- standard debugging symbols are used. You
- can specify the value "mem" to include
- TCL_MEM_DEBUG memory debugging, "compile"
- to include TCL_COMPILE_DEBUG debugging, or
- "all" to enable all internal debugging.
- --disable-symbols build without debugging symbols
- --enable-64bit enable 64bit support (where applicable)
- --disable-64bit disable 64bit support (where applicable)
- --enable-64bit-vis enable 64bit Sparc VIS support
- --disable-64bit-vis disable 64bit Sparc VIS support
+ --enable-symbols Build with debugging symbols. By default
+ standard debugging symbols are used. You can
+ specify the value "mem" to include
+ TCL_MEM_DEBUG memory debugging, "compile" to
+ include TCL_COMPILE_DEBUG debugging, or "all"
+ to enable all internal debugging.
+ --disable-symbols Build without debugging symbols
+ --enable-64bit Enable 64bit support (where applicable)
+ --disable-64bit Disable 64bit support (where applicable)
+ --enable-64bit-vis Enable 64bit Sparc VIS support
+ --disable-64bit-vis Disable 64bit Sparc VIS support
--enable-langinfo Allows use of modern nl_langinfo check for
- better localization support. This is on by
+ better localization support. This is on by
default on platforms where nl_langinfo is
found.
--disable-langinfo Specifically disables use of nl_langinfo.
--enable-man-symlinks Use symlinks for linking the manpages that
should be reachable under several names.
+ --enable-man-suffix[=STRING]
+ Append STRING to the names of installed manual
+ pages (prior to applying compression, if that
+ is also enabled). If STRING is omitted,
+ defaults to 'tcl'.
--enable-man-compression=PROG
Compress the manpages using PROG.
--enable-dtrace Enable tcl DTrace provider (if DTrace is
available on the platform), c.f. tclDTrace.d
for descriptions of the probes made available,
- see http://wiki.tcl.tk/DTrace for more details.
- Mac OS X only:
- --enable-framework package Tcl as a framework.
- --disable-corefoundation disable use of CoreFoundation API and revert to
- standard select based notifier, required when
- using naked fork (i.e. not followed by execve).
-
- Note: by default gcc will be used if it can be located on the PATH.
- if you want to use cc instead of gcc, set the CC environment variable
- to "cc" before running configure. It is not safe to edit the
- Makefile to use gcc after configure is run. Also note that
- you should use the same compiler when building extensions.
-
- Note: be sure to use only absolute path names (those starting with "/")
- in the --prefix and --exec-prefix options.
-
-(d) Type "make". This will create a library archive called
- "libtcl<version>.a" or "libtcl<version>.so" and an interpreter
- application called "tclsh" that allows you to type Tcl commands
- interactively or execute script files.
-
-(e) If the make fails then you'll have to personalize the Makefile
- for your site or possibly modify the distribution in other ways.
- First check the porting Web page above to see if there are hints
- for compiling on your system. If you need to modify Makefile,
- are comments at the beginning of it that describe the things you
- might want to change and how to change them.
-
-(f) Type "make install" to install Tcl binaries and script files in
- standard places. You'll need write permission on the installation
- directories to do this. The installation directories are
- determined by the "configure" script and may be specified with
- the --prefix and --exec-prefix options to "configure". See the
- Makefile for information on what directories were chosen; you
- can override these choices by modifying the "prefix" and
- "exec_prefix" variables in the Makefile.
-
-(g) At this point you can play with Tcl by running "make shell"
- and typing Tcl commands at the prompt.
+ see http://wiki.tcl.tk/DTrace for more details
+ --with-encoding=ENCODING Specifies the encoding for compile-time
+ configuration values. Defaults to iso8859-1,
+ which is also sufficient for ASCII.
+ --with-tzdata=FLAG Specifies whether to install timezone data. By
+ default, the configure script tries to detect
+ whether a usable timezone database is present
+ on the system already.
+
+ Mac OS X only (i.e. completely unsupported on other platforms):
+
+ --enable-framework Package Tcl as a framework.
+ --disable-corefoundation Disable use of CoreFoundation API and revert
+ to standard select based notifier, required
+ when using naked fork (i.e. not followed by
+ execve).
+
+ Note: by default gcc will be used if it can be located on the PATH. If you
+ want to use cc instead of gcc, set the CC environment variable to "cc"
+ before running configure. It is not safe to edit the Makefile to use gcc
+ after configure is run. Also note that you should use the same compiler
+ when building extensions.
+
+ Note: be sure to use only absolute path names (those starting with "/") in
+ the --prefix and --exec-prefix options.
+
+(d) Type "make". This will create a library archive called "libtcl<version>.a"
+ or "libtcl<version>.so" and an interpreter application called "tclsh" that
+ allows you to type Tcl commands interactively or execute script files. It
+ will also create a stub library archive "libtclstub<version>.a" that
+ developers may link against other C code to produce loadable extensions
+ for Tcl.
+
+(e) If the make fails then you'll have to personalize the Makefile for your
+ site or possibly modify the distribution in other ways. First check the
+ porting Web page above to see if there are hints for compiling on your
+ system. If you need to modify Makefile, there are comments at the
+ beginning of it that describe the things you might want to change and how
+ to change them.
+
+(f) Type "make install" to install Tcl binaries and script files in standard
+ places. You'll need write permission on the installation directories to do
+ this. The installation directories are determined by the "configure"
+ script and may be specified with the standard --prefix and --exec-prefix
+ options to "configure". See the Makefile for information on what
+ directories were chosen; you can override these choices by modifying the
+ "prefix" and "exec_prefix" variables in the Makefile. The installed
+ binaries have embedded within them path values relative to the install
+ directory. If you change your mind about where Tcl should be installed,
+ start this procedure over again from step (a) so that the path embedded in
+ the binaries agrees with the install location.
+
+(g) At this point you can play with Tcl by running the installed "tclsh"
+ executable, or via the "make shell" target, and typing Tcl commands at the
+ interactive prompt.
If you have trouble compiling Tcl, see the URL noted above about working
-platforms. It contains information that people have provided about changes
-they had to make to compile Tcl in various environments. We're also
-interested in hearing how to change the configuration setup so that Tcl
-compiles on additional platforms "out of the box".
+platforms. It contains information that people have provided about changes
+they had to make to compile Tcl in various environments. We're also interested
+in hearing how to change the configuration setup so that Tcl compiles on
+additional platforms "out of the box".
Test suite
----------
-There is a relatively complete test suite for all of the Tcl core in
-the subdirectory "tests". To use it just type "make test" in this
-directory. You should then see a printout of the test files processed.
-If any errors occur, you'll see a much more substantial printout for
-each error. See the README file in the "tests" directory for more
-information on the test suite. Note: don't run the tests as superuser:
-this will cause several of them to fail. If a test is failing
-consistently, please send us a bug report with as much detail as you
-can manage. Please use the online database at
+There is a relatively complete test suite for all of the Tcl core in the
+subdirectory "tests". To use it just type "make test" in this directory. You
+should then see a printout of the test files processed. If any errors occur,
+you'll see a much more substantial printout for each error. See the README
+file in the "tests" directory for more information on the test suite. Note:
+don't run the tests as superuser: this will cause several of them to fail. If
+a test is failing consistently, please send us a bug report with as much
+detail as you can manage. Please use the online database at
http://tcl.sourceforge.net/
diff --git a/unix/aclocal.m4 b/unix/aclocal.m4
index bc7540d..90d2e39 100644
--- a/unix/aclocal.m4
+++ b/unix/aclocal.m4
@@ -1 +1 @@
-builtin(include,tcl.m4)
+builtin(include,../unix/tcl.m4)
diff --git a/unix/configure b/unix/configure
index d477bdd..aa792a7 100755
--- a/unix/configure
+++ b/unix/configure
@@ -1,56 +1,324 @@
#! /bin/sh
-
# Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.13
-# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+# Generated by GNU Autoconf 2.59 for tcl 8.5.
#
+# Copyright (C) 2003 Free Software Foundation, Inc.
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
-# Defaults:
-ac_help=
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
ac_default_prefix=/usr/local
-# Any additions from configure.in:
-ac_help="$ac_help
- --enable-man-symlinks use symlinks for the manpages"
-ac_help="$ac_help
- --enable-man-compression=PROG
- compress the manpages with PROG"
-ac_help="$ac_help
- --enable-man-suffix=STRING
- use STRING as a suffix to manpage file names
- (default: tcl)"
-ac_help="$ac_help
- --enable-threads build with threads"
-ac_help="$ac_help
- --enable-shared build and link with shared libraries [--enable-shared]"
-ac_help="$ac_help
- --enable-64bit enable 64bit support (where applicable)"
-ac_help="$ac_help
- --enable-64bit-vis enable 64bit Sparc VIS support"
-ac_help="$ac_help
- --enable-corefoundation use CoreFoundation API [--enable-corefoundation]"
-ac_help="$ac_help
- --disable-load disallow dynamic loading and "load" command"
-ac_help="$ac_help
- --enable-symbols build with debugging symbols [--disable-symbols]"
-ac_help="$ac_help
- --enable-langinfo use nl_langinfo if possible to determine
- encoding at startup, otherwise use old heuristic"
-ac_help="$ac_help
- --enable-dtrace build with DTrace support [--disable-dtrace]"
-ac_help="$ac_help
- --enable-framework package shared libraries in MacOSX frameworks [--disable-framework]"
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete. It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME='tcl'
+PACKAGE_TARNAME='tcl'
+PACKAGE_VERSION='8.5'
+PACKAGE_STRING='tcl 8.5'
+PACKAGE_BUGREPORT=''
+
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+# include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS MAN_FLAGS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP TCL_THREADS RANLIB ac_ct_RANLIB AR ac_ct_AR TCL_LIBS DL_LIBS DL_OBJS PLAT_OBJS PLAT_SRCS LDAIX_SRC CFLAGS_DEBUG CFLAGS_OPTIMIZE CFLAGS_WARNING LDFLAGS_DEBUG LDFLAGS_OPTIMIZE CC_SEARCH_FLAGS LD_SEARCH_FLAGS STLIB_LD SHLIB_LD TCL_SHLIB_LD_EXTRAS TK_SHLIB_LD_EXTRAS SHLIB_LD_LIBS SHLIB_CFLAGS SHLIB_SUFFIX MAKE_LIB MAKE_STUB_LIB INSTALL_LIB INSTALL_STUB_LIB CFLAGS_DEFAULT LDFLAGS_DEFAULT LIBOBJS DTRACE TCL_VERSION TCL_MAJOR_VERSION TCL_MINOR_VERSION TCL_PATCH_LEVEL TCL_YEAR TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC TCL_STUB_LIB_PATH TCL_INCLUDE_SPEC TCL_BUILD_STUB_LIB_SPEC TCL_BUILD_STUB_LIB_PATH TCL_SRC_DIR CFG_TCL_SHARED_LIB_SUFFIX CFG_TCL_UNSHARED_LIB_SUFFIX TCL_SHARED_BUILD LD_LIBRARY_PATH_VAR TCL_BUILD_LIB_SPEC TCL_LIB_VERSIONS_OK TCL_SHARED_LIB_SUFFIX TCL_UNSHARED_LIB_SUFFIX TCL_HAS_LONGLONG INSTALL_TZDATA DTRACE_SRC DTRACE_HDR DTRACE_OBJ MAKEFILE_SHELL BUILD_DLTEST TCL_PACKAGE_PATH TCL_MODULE_PATH TCL_LIBRARY PRIVATE_INCLUDE_DIR HTML_DIR EXTRA_CC_SWITCHES EXTRA_APP_CC_SWITCHES EXTRA_INSTALL EXTRA_INSTALL_BINARIES EXTRA_BUILD_HTML EXTRA_TCLSH_LIBS DLTEST_LD DLTEST_SUFFIX'
+ac_subst_files=''
# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
# The variables have the same names as the options, with
# dashes changed to underlines.
-build=NONE
-cache_file=./config.cache
+cache_file=/dev/null
exec_prefix=NONE
-host=NONE
no_create=
-nonopt=NONE
no_recursion=
prefix=NONE
program_prefix=NONE
@@ -59,10 +327,15 @@ program_transform_name=s,x,x,
silent=
site=
srcdir=
-target=NONE
verbose=
x_includes=NONE
x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
bindir='${exec_prefix}/bin'
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
@@ -76,17 +349,9 @@ oldincludedir='/usr/include'
infodir='${prefix}/info'
mandir='${prefix}/man'
-# Initialize some other variables.
-subdirs=
-MFLAGS= MAKEFLAGS=
-SHELL=${CONFIG_SHELL-/bin/sh}
-# Maximum number of lines to put in a shell here document.
-ac_max_here_lines=12
-
ac_prev=
for ac_option
do
-
# If the previous option needs an argument, assign it.
if test -n "$ac_prev"; then
eval "$ac_prev=\$ac_option"
@@ -94,59 +359,59 @@ do
continue
fi
- case "$ac_option" in
- -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
- *) ac_optarg= ;;
- esac
+ ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
# Accept the important Cygnus configure options, so we can diagnose typos.
- case "$ac_option" in
+ case $ac_option in
-bindir | --bindir | --bindi | --bind | --bin | --bi)
ac_prev=bindir ;;
-bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
- bindir="$ac_optarg" ;;
+ bindir=$ac_optarg ;;
-build | --build | --buil | --bui | --bu)
- ac_prev=build ;;
+ ac_prev=build_alias ;;
-build=* | --build=* | --buil=* | --bui=* | --bu=*)
- build="$ac_optarg" ;;
+ build_alias=$ac_optarg ;;
-cache-file | --cache-file | --cache-fil | --cache-fi \
| --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
ac_prev=cache_file ;;
-cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
| --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
- cache_file="$ac_optarg" ;;
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
-datadir | --datadir | --datadi | --datad | --data | --dat | --da)
ac_prev=datadir ;;
-datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
| --da=*)
- datadir="$ac_optarg" ;;
+ datadir=$ac_optarg ;;
-disable-* | --disable-*)
- ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
- if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
- { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
- fi
- ac_feature=`echo $ac_feature| sed 's/-/_/g'`
- eval "enable_${ac_feature}=no" ;;
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ eval "enable_$ac_feature=no" ;;
-enable-* | --enable-*)
- ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
- if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
- { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
- fi
- ac_feature=`echo $ac_feature| sed 's/-/_/g'`
- case "$ac_option" in
- *=*) ;;
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
*) ac_optarg=yes ;;
esac
- eval "enable_${ac_feature}='$ac_optarg'" ;;
+ eval "enable_$ac_feature='$ac_optarg'" ;;
-exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
| --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
@@ -155,95 +420,47 @@ do
-exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
| --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
| --exec=* | --exe=* | --ex=*)
- exec_prefix="$ac_optarg" ;;
+ exec_prefix=$ac_optarg ;;
-gas | --gas | --ga | --g)
# Obsolete; use --with-gas.
with_gas=yes ;;
- -help | --help | --hel | --he)
- # Omit some internal or obsolete options to make the list less imposing.
- # This message is too long to be a string in the A/UX 3.1 sh.
- cat << EOF
-Usage: configure [options] [host]
-Options: [defaults in brackets after descriptions]
-Configuration:
- --cache-file=FILE cache test results in FILE
- --help print this message
- --no-create do not create output files
- --quiet, --silent do not print \`checking...' messages
- --version print the version of autoconf that created configure
-Directory and file names:
- --prefix=PREFIX install architecture-independent files in PREFIX
- [$ac_default_prefix]
- --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
- [same as prefix]
- --bindir=DIR user executables in DIR [EPREFIX/bin]
- --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
- --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
- --datadir=DIR read-only architecture-independent data in DIR
- [PREFIX/share]
- --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
- --sharedstatedir=DIR modifiable architecture-independent data in DIR
- [PREFIX/com]
- --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
- --libdir=DIR object code libraries in DIR [EPREFIX/lib]
- --includedir=DIR C header files in DIR [PREFIX/include]
- --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
- --infodir=DIR info documentation in DIR [PREFIX/info]
- --mandir=DIR man documentation in DIR [PREFIX/man]
- --srcdir=DIR find the sources in DIR [configure dir or ..]
- --program-prefix=PREFIX prepend PREFIX to installed program names
- --program-suffix=SUFFIX append SUFFIX to installed program names
- --program-transform-name=PROGRAM
- run sed PROGRAM on installed program names
-EOF
- cat << EOF
-Host type:
- --build=BUILD configure for building on BUILD [BUILD=HOST]
- --host=HOST configure for HOST [guessed]
- --target=TARGET configure for TARGET [TARGET=HOST]
-Features and packages:
- --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
- --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
- --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
- --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
- --x-includes=DIR X include files are in DIR
- --x-libraries=DIR X library files are in DIR
-EOF
- if test -n "$ac_help"; then
- echo "--enable and --with options recognized:$ac_help"
- fi
- exit 0 ;;
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
-host | --host | --hos | --ho)
- ac_prev=host ;;
+ ac_prev=host_alias ;;
-host=* | --host=* | --hos=* | --ho=*)
- host="$ac_optarg" ;;
+ host_alias=$ac_optarg ;;
-includedir | --includedir | --includedi | --included | --include \
| --includ | --inclu | --incl | --inc)
ac_prev=includedir ;;
-includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
| --includ=* | --inclu=* | --incl=* | --inc=*)
- includedir="$ac_optarg" ;;
+ includedir=$ac_optarg ;;
-infodir | --infodir | --infodi | --infod | --info | --inf)
ac_prev=infodir ;;
-infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
- infodir="$ac_optarg" ;;
+ infodir=$ac_optarg ;;
-libdir | --libdir | --libdi | --libd)
ac_prev=libdir ;;
-libdir=* | --libdir=* | --libdi=* | --libd=*)
- libdir="$ac_optarg" ;;
+ libdir=$ac_optarg ;;
-libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
| --libexe | --libex | --libe)
ac_prev=libexecdir ;;
-libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
| --libexe=* | --libex=* | --libe=*)
- libexecdir="$ac_optarg" ;;
+ libexecdir=$ac_optarg ;;
-localstatedir | --localstatedir | --localstatedi | --localstated \
| --localstate | --localstat | --localsta | --localst \
@@ -252,19 +469,19 @@ EOF
-localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
| --localstate=* | --localstat=* | --localsta=* | --localst=* \
| --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
- localstatedir="$ac_optarg" ;;
+ localstatedir=$ac_optarg ;;
-mandir | --mandir | --mandi | --mand | --man | --ma | --m)
ac_prev=mandir ;;
-mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
- mandir="$ac_optarg" ;;
+ mandir=$ac_optarg ;;
-nfp | --nfp | --nf)
# Obsolete; use --without-fp.
with_fp=no ;;
-no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c)
+ | --no-cr | --no-c | -n)
no_create=yes ;;
-no-recursion | --no-recursion | --no-recursio | --no-recursi \
@@ -278,26 +495,26 @@ EOF
-oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
| --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
| --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
- oldincludedir="$ac_optarg" ;;
+ oldincludedir=$ac_optarg ;;
-prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
ac_prev=prefix ;;
-prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
- prefix="$ac_optarg" ;;
+ prefix=$ac_optarg ;;
-program-prefix | --program-prefix | --program-prefi | --program-pref \
| --program-pre | --program-pr | --program-p)
ac_prev=program_prefix ;;
-program-prefix=* | --program-prefix=* | --program-prefi=* \
| --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
- program_prefix="$ac_optarg" ;;
+ program_prefix=$ac_optarg ;;
-program-suffix | --program-suffix | --program-suffi | --program-suff \
| --program-suf | --program-su | --program-s)
ac_prev=program_suffix ;;
-program-suffix=* | --program-suffix=* | --program-suffi=* \
| --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
- program_suffix="$ac_optarg" ;;
+ program_suffix=$ac_optarg ;;
-program-transform-name | --program-transform-name \
| --program-transform-nam | --program-transform-na \
@@ -314,7 +531,7 @@ EOF
| --program-transfo=* | --program-transf=* \
| --program-trans=* | --program-tran=* \
| --progr-tra=* | --program-tr=* | --program-t=*)
- program_transform_name="$ac_optarg" ;;
+ program_transform_name=$ac_optarg ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil)
@@ -324,7 +541,7 @@ EOF
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
| --sbi=* | --sb=*)
- sbindir="$ac_optarg" ;;
+ sbindir=$ac_optarg ;;
-sharedstatedir | --sharedstatedir | --sharedstatedi \
| --sharedstated | --sharedstate | --sharedstat | --sharedsta \
@@ -335,58 +552,57 @@ EOF
| --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
| --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
| --sha=* | --sh=*)
- sharedstatedir="$ac_optarg" ;;
+ sharedstatedir=$ac_optarg ;;
-site | --site | --sit)
ac_prev=site ;;
-site=* | --site=* | --sit=*)
- site="$ac_optarg" ;;
+ site=$ac_optarg ;;
-srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
ac_prev=srcdir ;;
-srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
- srcdir="$ac_optarg" ;;
+ srcdir=$ac_optarg ;;
-sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
| --syscon | --sysco | --sysc | --sys | --sy)
ac_prev=sysconfdir ;;
-sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
| --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
- sysconfdir="$ac_optarg" ;;
+ sysconfdir=$ac_optarg ;;
-target | --target | --targe | --targ | --tar | --ta | --t)
- ac_prev=target ;;
+ ac_prev=target_alias ;;
-target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
- target="$ac_optarg" ;;
+ target_alias=$ac_optarg ;;
-v | -verbose | --verbose | --verbos | --verbo | --verb)
verbose=yes ;;
- -version | --version | --versio | --versi | --vers)
- echo "configure generated by autoconf version 2.13"
- exit 0 ;;
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
-with-* | --with-*)
- ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
- if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
- { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
- fi
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
ac_package=`echo $ac_package| sed 's/-/_/g'`
- case "$ac_option" in
- *=*) ;;
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
*) ac_optarg=yes ;;
esac
- eval "with_${ac_package}='$ac_optarg'" ;;
+ eval "with_$ac_package='$ac_optarg'" ;;
-without-* | --without-*)
- ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
- if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
- { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
- fi
- ac_package=`echo $ac_package| sed 's/-/_/g'`
- eval "with_${ac_package}=no" ;;
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/-/_/g'`
+ eval "with_$ac_package=no" ;;
--x)
# Obsolete; use --with-x.
@@ -397,99 +613,110 @@ EOF
ac_prev=x_includes ;;
-x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
| --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
- x_includes="$ac_optarg" ;;
+ x_includes=$ac_optarg ;;
-x-libraries | --x-libraries | --x-librarie | --x-librari \
| --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
ac_prev=x_libraries ;;
-x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
| --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
- x_libraries="$ac_optarg" ;;
+ x_libraries=$ac_optarg ;;
- -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
;;
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+ eval "$ac_envvar='$ac_optarg'"
+ export $ac_envvar ;;
+
*)
- if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
- echo "configure: warning: $ac_option: invalid host type" 1>&2
- fi
- if test "x$nonopt" != xNONE; then
- { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
- fi
- nonopt="$ac_option"
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
;;
esac
done
if test -n "$ac_prev"; then
- { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
-fi
-
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
-
-# File descriptor usage:
-# 0 standard input
-# 1 file creation
-# 2 errors and warnings
-# 3 some systems may open it to /dev/tty
-# 4 used on the Kubota Titan
-# 6 checking for... messages and results
-# 5 compiler messages saved in config.log
-if test "$silent" = yes; then
- exec 6>/dev/null
-else
- exec 6>&1
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
fi
-exec 5>./config.log
-echo "\
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-" 1>&5
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
-# Strip out --no-create and --no-recursion so they do not pile up.
-# Also quote any args containing shell metacharacters.
-ac_configure_args=
-for ac_arg
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+ localstatedir libdir includedir oldincludedir infodir mandir
do
- case "$ac_arg" in
- -no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c) ;;
- -no-recursion | --no-recursion | --no-recursio | --no-recursi \
- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
- *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
- ac_configure_args="$ac_configure_args '$ac_arg'" ;;
- *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
esac
done
-# NLS nuisances.
-# Only set these to C if already set. These must not be set unconditionally
-# because not all systems understand e.g. LANG=C (notably SCO).
-# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
-# Non-C LC_CTYPE values break the ctype check.
-if test "${LANG+set}" = set; then LANG=C; export LANG; fi
-if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
-if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
-if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
-# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -rf conftest* confdefs.h
-# AIX cpp loses on an empty file, so make sure it contains at least a newline.
-echo > confdefs.h
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
-# A filename unique to this package, relative to the directory that
-# configure is in, which we can look for to find out if srcdir is correct.
-ac_unique_file=../generic/tcl.h
# Find the source files, if location was not specified.
if test -z "$srcdir"; then
ac_srcdir_defaulted=yes
# Try the directory containing this script, then its parent.
- ac_prog=$0
- ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
- test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
srcdir=$ac_confdir
if test ! -r $srcdir/$ac_unique_file; then
srcdir=..
@@ -499,13 +726,491 @@ else
fi
if test ! -r $srcdir/$ac_unique_file; then
if test "$ac_srcdir_defaulted" = yes; then
- { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+ { (exit 1); exit 1; }; }
else
- { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
fi
fi
-srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+ { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+ { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures tcl 8.5 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+ cat <<_ACEOF
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --infodir=DIR info documentation [PREFIX/info]
+ --mandir=DIR man documentation [PREFIX/man]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of tcl 8.5:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-man-symlinks use symlinks for the manpages (default: off)
+ --enable-man-compression=PROG
+ compress the manpages with PROG (default: off)
+ --enable-man-suffix=STRING
+ use STRING as a suffix to manpage file names
+ (default: no, tcl if enabled without
+ specifying STRING)
+ --enable-threads build with threads (default: off)
+ --enable-shared build and link with shared libraries (default: on)
+ --enable-64bit enable 64bit support (default: off)
+ --enable-64bit-vis enable 64bit Sparc VIS support (default: off)
+ --disable-rpath disable rpath support (default: on)
+ --enable-corefoundation use CoreFoundation API on MacOSX (default: on)
+ --enable-load allow dynamic loading and "load" command (default:
+ on)
+ --enable-symbols build with debugging symbols (default: off)
+ --enable-langinfo use nl_langinfo if possible to determine encoding at
+ startup, otherwise use old heuristic (default: on)
+ --enable-dll-unloading enable the 'unload' command (default: on)
+ --enable-dtrace build with DTrace support (default: off)
+ --enable-framework package shared libraries in MacOSX frameworks
+ (default: off)
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-encoding encoding for configuration values (default:
+ iso8859-1)
+ --with-tzdata install timezone data (default: autodetect)
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
+ headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ ac_popdir=`pwd`
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d $ac_dir || continue
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+ cd $ac_dir
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f $ac_srcdir/configure.gnu; then
+ echo
+ $SHELL $ac_srcdir/configure.gnu --help=recursive
+ elif test -f $ac_srcdir/configure; then
+ echo
+ $SHELL $ac_srcdir/configure --help=recursive
+ elif test -f $ac_srcdir/configure.ac ||
+ test -f $ac_srcdir/configure.in; then
+ echo
+ $ac_configure --help
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi
+ cd $ac_popdir
+ done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+ cat <<\_ACEOF
+tcl configure 8.5
+generated by GNU Autoconf 2.59
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by tcl $as_me 8.5, which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo = `(hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+ # Get rid of the leading space.
+ ac_sep=" "
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+{
+ (set) 2>&1 |
+ case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ sed -n \
+ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+ ;;
+ *)
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+}
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ sed "/^$/d" confdefs.h | sort
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core &&
+ rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+ ' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
# Prefer explicitly selected file to automatically selected ones.
if test -z "$CONFIG_SITE"; then
if test "x$prefix" != xNONE; then
@@ -516,47 +1221,121 @@ if test -z "$CONFIG_SITE"; then
fi
for ac_site_file in $CONFIG_SITE; do
if test -r "$ac_site_file"; then
- echo "loading site script $ac_site_file"
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file"
fi
done
if test -r "$cache_file"; then
- echo "loading cache $cache_file"
- . $cache_file
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . $cache_file;;
+ *) . ./$cache_file;;
+ esac
+ fi
else
- echo "creating cache $cache_file"
- > $cache_file
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+ sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+ eval ac_new_val="\$ac_env_${ac_var}_value"
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
fi
ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-ac_exeext=
-ac_objext=o
-if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
- # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
- if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
- ac_n= ac_c='
-' ac_t=' '
- else
- ac_n=-n ac_c= ac_t=
- fi
-else
- ac_n= ac_c='\c' ac_t=
-fi
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
-TCL_VERSION=8.4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+TCL_VERSION=8.5
TCL_MAJOR_VERSION=8
-TCL_MINOR_VERSION=4
-TCL_PATCH_LEVEL=".19"
+TCL_MINOR_VERSION=5
+TCL_PATCH_LEVEL=".10"
VERSION=${TCL_VERSION}
#------------------------------------------------------------------------
@@ -570,54 +1349,57 @@ if test "${exec_prefix}" = "NONE"; then
exec_prefix=$prefix
fi
# Make sure srcdir is fully qualified!
-srcdir=`cd $srcdir ; pwd`
-TCL_SRC_DIR=`cd $srcdir/..; pwd`
+srcdir="`cd "$srcdir" ; pwd`"
+TCL_SRC_DIR="`cd "$srcdir"/..; pwd`"
#------------------------------------------------------------------------
# Compress and/or soft link the manpages?
#------------------------------------------------------------------------
- echo $ac_n "checking whether to use symlinks for manpages""... $ac_c" 1>&6
-echo "configure:583: checking whether to use symlinks for manpages" >&5
+ echo "$as_me:$LINENO: checking whether to use symlinks for manpages" >&5
+echo $ECHO_N "checking whether to use symlinks for manpages... $ECHO_C" >&6
# Check whether --enable-man-symlinks or --disable-man-symlinks was given.
if test "${enable_man_symlinks+set}" = set; then
enableval="$enable_man_symlinks"
test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks"
else
enableval="no"
-fi
-
- echo "$ac_t""$enableval" 1>&6
+fi;
+ echo "$as_me:$LINENO: result: $enableval" >&5
+echo "${ECHO_T}$enableval" >&6
- echo $ac_n "checking whether to compress the manpages""... $ac_c" 1>&6
-echo "configure:595: checking whether to compress the manpages" >&5
+ echo "$as_me:$LINENO: checking whether to compress the manpages" >&5
+echo $ECHO_N "checking whether to compress the manpages... $ECHO_C" >&6
# Check whether --enable-man-compression or --disable-man-compression was given.
if test "${enable_man_compression+set}" = set; then
enableval="$enable_man_compression"
case $enableval in
- yes) { echo "configure: error: missing argument to --enable-man-compression" 1>&2; exit 1; };;
+ yes) { { echo "$as_me:$LINENO: error: missing argument to --enable-man-compression" >&5
+echo "$as_me: error: missing argument to --enable-man-compression" >&2;}
+ { (exit 1); exit 1; }; };;
no) ;;
*) MAN_FLAGS="$MAN_FLAGS --compress $enableval";;
esac
else
enableval="no"
-fi
-
- echo "$ac_t""$enableval" 1>&6
+fi;
+ echo "$as_me:$LINENO: result: $enableval" >&5
+echo "${ECHO_T}$enableval" >&6
if test "$enableval" != "no"; then
- echo $ac_n "checking for compressed file suffix""... $ac_c" 1>&6
-echo "configure:611: checking for compressed file suffix" >&5
+ echo "$as_me:$LINENO: checking for compressed file suffix" >&5
+echo $ECHO_N "checking for compressed file suffix... $ECHO_C" >&6
touch TeST
$enableval TeST
Z=`ls TeST* | sed 's/^....//'`
rm -f TeST*
MAN_FLAGS="$MAN_FLAGS --extension $Z"
- echo "$ac_t""$Z" 1>&6
+ echo "$as_me:$LINENO: result: $Z" >&5
+echo "${ECHO_T}$Z" >&6
fi
- echo $ac_n "checking whether to add a package name suffix for the manpages""... $ac_c" 1>&6
-echo "configure:621: checking whether to add a package name suffix for the manpages" >&5
+ echo "$as_me:$LINENO: checking whether to add a package name suffix for the manpages" >&5
+echo $ECHO_N "checking whether to add a package name suffix for the manpages... $ECHO_C" >&6
# Check whether --enable-man-suffix or --disable-man-suffix was given.
if test "${enable_man_suffix+set}" = set; then
enableval="$enable_man_suffix"
@@ -628,11 +1410,11 @@ if test "${enable_man_suffix+set}" = set; then
esac
else
enableval="no"
-fi
+fi;
+ echo "$as_me:$LINENO: result: $enableval" >&5
+echo "${ECHO_T}$enableval" >&6
- echo "$ac_t""$enableval" 1>&6
-
#------------------------------------------------------------------------
@@ -645,214 +1427,659 @@ if test "${CFLAGS+set}" != "set" ; then
CFLAGS=""
fi
-# Extract the first word of "gcc", so it can be a program name with args.
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:652: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ CC=$ac_ct_CC
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_CC="gcc"
- break
- fi
- done
- IFS="$ac_save_ifs"
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
fi
fi
-CC="$ac_cv_prog_CC"
+CC=$ac_cv_prog_CC
if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
fi
+ CC=$ac_ct_CC
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:682: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
ac_prog_rejected=no
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
- ac_prog_rejected=yes
- continue
- fi
- ac_cv_prog_CC="cc"
- break
- fi
- done
- IFS="$ac_save_ifs"
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
if test $ac_prog_rejected = yes; then
# We found a bogon in the path, so make sure we never use it.
set dummy $ac_cv_prog_CC
shift
- if test $# -gt 0; then
+ if test $# != 0; then
# We chose a different compiler from the bogus one.
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
- set dummy "$ac_dir/$ac_word" "$@"
- shift
- ac_cv_prog_CC="$@"
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
fi
fi
fi
fi
-CC="$ac_cv_prog_CC"
+CC=$ac_cv_prog_CC
if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
fi
- if test -z "$CC"; then
- case "`uname -s`" in
- *win32* | *WIN32*)
- # Extract the first word of "cl", so it can be a program name with args.
-set dummy cl; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:733: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_CC="cl"
- break
- fi
- done
- IFS="$ac_save_ifs"
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
fi
fi
-CC="$ac_cv_prog_CC"
+CC=$ac_cv_prog_CC
if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
fi
- ;;
- esac
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
fi
- test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
fi
-echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:765: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+ test -n "$ac_ct_CC" && break
+done
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-cat > conftest.$ac_ext << EOF
-
-#line 776 "configure"
-#include "confdefs.h"
-
-main(){return(0);}
-EOF
-if { (eval echo configure:781: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- ac_cv_prog_cc_works=yes
- # If we can't run a trivial program, we are probably using a cross compiler.
- if (./conftest; exit) 2>/dev/null; then
- ac_cv_prog_cc_cross=no
+ CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+ "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+ (eval $ac_compiler --version </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+ (eval $ac_compiler -v </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+ (eval $ac_compiler -V </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+ (eval $ac_link_default) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Find the output, starting from the most likely. This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+ ;;
+ conftest.$ac_ext )
+ # This is the source file.
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ # FIXME: I believe we export ac_cv_exeext for Libtool,
+ # but it would be cool to find out if it's true. Does anybody
+ # maintain Libtool? --akim.
+ export ac_cv_exeext
+ break;;
+ * )
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
else
- ac_cv_prog_cc_cross=yes
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
fi
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- ac_cv_prog_cc_works=no
-fi
-rm -fr conftest*
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
-if test $ac_cv_prog_cc_works = no; then
- { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi
-echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:807: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
-echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
-cross_compiling=$ac_cv_prog_cc_cross
-
-echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:812: checking whether we are using GNU C" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ export ac_cv_exeext
+ break;;
+ * ) break;;
+ esac
+done
else
- cat > conftest.c <<EOF
-#ifdef __GNUC__
- yes;
-#endif
-EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:821: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
- ac_cv_prog_gcc=yes
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
else
- ac_cv_prog_gcc=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
-echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
-if test $ac_cv_prog_gcc = yes; then
- GCC=yes
-else
- GCC=
-fi
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
-ac_test_CFLAGS="${CFLAGS+set}"
-ac_save_CFLAGS="$CFLAGS"
-CFLAGS=
-echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:840: checking whether ${CC-cc} accepts -g" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- echo 'void f(){}' > conftest.c
-if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
ac_cv_prog_cc_g=yes
else
- ac_cv_prog_cc_g=no
-fi
-rm -f conftest*
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_cv_prog_cc_g=no
fi
-
-echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
if test "$ac_test_CFLAGS" = set; then
- CFLAGS="$ac_save_CFLAGS"
+ CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
if test "$GCC" = yes; then
CFLAGS="-g -O2"
@@ -866,6 +2093,341 @@ else
CFLAGS=
fi
fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std1 is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std1. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX 10.20 and later -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+ x|xno)
+ echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+ *)
+ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+ CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C. Since we use `exit',
+# in C++ we need to declare it. In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+ choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ for ac_declaration in \
+ '' \
+ 'extern "C" void std::exit (int) throw (); using std::exit;' \
+ 'extern "C" void std::exit (int); using std::exit;' \
+ 'extern "C" void exit (int) throw ();' \
+ 'extern "C" void exit (int);' \
+ 'void exit (int);'
+do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+ echo '#ifdef __cplusplus' >>confdefs.h
+ echo $ac_declaration >>confdefs.h
+ echo '#endif' >>confdefs.h
+fi
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for inline" >&5
+echo $ECHO_N "checking for inline... $ECHO_C" >&6
+if test "${ac_cv_c_inline+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_inline=$ac_kw; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5
+echo "${ECHO_T}$ac_cv_c_inline" >&6
+
+
+case $ac_cv_c_inline in
+ inline | yes) ;;
+ *)
+ case $ac_cv_c_inline in
+ no) ac_val=;;
+ *) ac_val=$ac_cv_c_inline;;
+ esac
+ cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+ ;;
+esac
#--------------------------------------------------------------------
@@ -877,99 +2439,512 @@ fi
# Do this early, otherwise an autoconf bug throws errors on configure
#--------------------------------------------------------------------
-echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:882: checking how to run the C preprocessor" >&5
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
fi
if test -z "$CPP"; then
-if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ if test "${ac_cv_prog_CPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
else
- # This must be in double quotes, not single quotes, because CPP may get
- # substituted into the Makefile and "${CC-cc}" will confuse make.
- CPP="${CC-cc} -E"
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
# On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp.
- cat > conftest.$ac_ext <<EOF
-#line 897 "configure"
-#include "confdefs.h"
-#include <assert.h>
-Syntax Error
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:903: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
:
else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP="${CC-cc} -E -traditional-cpp"
- cat > conftest.$ac_ext <<EOF
-#line 914 "configure"
-#include "confdefs.h"
-#include <assert.h>
-Syntax Error
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:920: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
:
else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP="${CC-cc} -nologo -E"
- cat > conftest.$ac_ext <<EOF
-#line 931 "configure"
-#include "confdefs.h"
-#include <assert.h>
-Syntax Error
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:937: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
+ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+ then ac_cv_prog_egrep='grep -E'
+ else ac_cv_prog_egrep='egrep'
+ fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
:
else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP=/lib/cpp
+ ac_cv_header_stdc=no
fi
rm -f conftest*
+
fi
-rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
fi
rm -f conftest*
- ac_cv_prog_CPP="$CPP"
+
fi
- CPP="$ac_cv_prog_CPP"
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
else
- ac_cv_prog_CPP="$CPP"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ exit(2);
+ exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
fi
-echo "$ac_t""$CPP" 1>&6
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
- echo $ac_n "checking dirent.h""... $ac_c" 1>&6
-echo "configure:963: checking dirent.h" >&5
-if eval "test \"`echo '$''{'tcl_cv_dirent_h'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+done
+
+
+
+ echo "$as_me:$LINENO: checking dirent.h" >&5
+echo $ECHO_N "checking dirent.h... $ECHO_C" >&6
+if test "${tcl_cv_dirent_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 969 "configure"
-#include "confdefs.h"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/types.h>
#include <dirent.h>
-int main() {
+int
+main ()
+{
#ifndef _POSIX_SOURCE
# ifdef __Lynx__
@@ -989,320 +2964,877 @@ entryPtr = readdir(d);
p = entryPtr->d_name;
closedir(d);
-; return 0; }
-EOF
-if { (eval echo configure:995: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_dirent_h=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_dirent_h=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_dirent_h=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_dirent_h" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_dirent_h" >&5
+echo "${ECHO_T}$tcl_cv_dirent_h" >&6
if test $tcl_cv_dirent_h = no; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define NO_DIRENT_H 1
-EOF
+_ACEOF
fi
- ac_safe=`echo "errno.h" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for errno.h""... $ac_c" 1>&6
-echo "configure:1018: checking for errno.h" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ if test "${ac_cv_header_float_h+set}" = set; then
+ echo "$as_me:$LINENO: checking for float.h" >&5
+echo $ECHO_N "checking for float.h... $ECHO_C" >&6
+if test "${ac_cv_header_float_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_float_h" >&5
+echo "${ECHO_T}$ac_cv_header_float_h" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking float.h usability" >&5
+echo $ECHO_N "checking float.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <float.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking float.h presence" >&5
+echo $ECHO_N "checking float.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <float.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
else
- cat > conftest.$ac_ext <<EOF
-#line 1023 "configure"
-#include "confdefs.h"
-#include <errno.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1028: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
+ ac_cpp_err=yes
fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- :
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
else
- echo "$ac_t""no" 1>&6
-cat >> confdefs.h <<\EOF
-#define NO_ERRNO_H 1
-EOF
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ ac_header_preproc=no
fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
- ac_safe=`echo "float.h" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for float.h""... $ac_c" 1>&6
-echo "configure:1055: checking for float.h" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: float.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: float.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: float.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: float.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: float.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: float.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: float.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: float.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: float.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: float.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: float.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: float.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: float.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: float.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: float.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: float.h: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to the tcl lists. ##
+## ------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for float.h" >&5
+echo $ECHO_N "checking for float.h... $ECHO_C" >&6
+if test "${ac_cv_header_float_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 1060 "configure"
-#include "confdefs.h"
-#include <float.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1065: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
+ ac_cv_header_float_h=$ac_header_preproc
fi
-rm -f conftest*
+echo "$as_me:$LINENO: result: $ac_cv_header_float_h" >&5
+echo "${ECHO_T}$ac_cv_header_float_h" >&6
+
fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+if test $ac_cv_header_float_h = yes; then
:
else
- echo "$ac_t""no" 1>&6
-cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define NO_FLOAT_H 1
-EOF
+_ACEOF
fi
- ac_safe=`echo "values.h" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for values.h""... $ac_c" 1>&6
-echo "configure:1092: checking for values.h" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+
+ if test "${ac_cv_header_values_h+set}" = set; then
+ echo "$as_me:$LINENO: checking for values.h" >&5
+echo $ECHO_N "checking for values.h... $ECHO_C" >&6
+if test "${ac_cv_header_values_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_values_h" >&5
+echo "${ECHO_T}$ac_cv_header_values_h" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 1097 "configure"
-#include "confdefs.h"
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking values.h usability" >&5
+echo $ECHO_N "checking values.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
#include <values.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1102: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking values.h presence" >&5
+echo $ECHO_N "checking values.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <values.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
fi
-rm -f conftest*
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: values.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: values.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: values.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: values.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: values.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: values.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: values.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: values.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: values.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: values.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: values.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: values.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: values.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: values.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: values.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: values.h: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to the tcl lists. ##
+## ------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for values.h" >&5
+echo $ECHO_N "checking for values.h... $ECHO_C" >&6
+if test "${ac_cv_header_values_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_values_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_values_h" >&5
+echo "${ECHO_T}$ac_cv_header_values_h" >&6
+
fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+if test $ac_cv_header_values_h = yes; then
:
else
- echo "$ac_t""no" 1>&6
-cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define NO_VALUES_H 1
-EOF
+_ACEOF
fi
- ac_safe=`echo "limits.h" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for limits.h""... $ac_c" 1>&6
-echo "configure:1129: checking for limits.h" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+
+ if test "${ac_cv_header_limits_h+set}" = set; then
+ echo "$as_me:$LINENO: checking for limits.h" >&5
+echo $ECHO_N "checking for limits.h... $ECHO_C" >&6
+if test "${ac_cv_header_limits_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_limits_h" >&5
+echo "${ECHO_T}$ac_cv_header_limits_h" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 1134 "configure"
-#include "confdefs.h"
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking limits.h usability" >&5
+echo $ECHO_N "checking limits.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <limits.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking limits.h presence" >&5
+echo $ECHO_N "checking limits.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <limits.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1139: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
fi
-rm -f conftest*
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- cat >> confdefs.h <<\EOF
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: limits.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: limits.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: limits.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: limits.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: limits.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: limits.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: limits.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: limits.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: limits.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: limits.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: limits.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: limits.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: limits.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: limits.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: limits.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: limits.h: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to the tcl lists. ##
+## ------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for limits.h" >&5
+echo $ECHO_N "checking for limits.h... $ECHO_C" >&6
+if test "${ac_cv_header_limits_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_limits_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_limits_h" >&5
+echo "${ECHO_T}$ac_cv_header_limits_h" >&6
+
+fi
+if test $ac_cv_header_limits_h = yes; then
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_LIMITS_H 1
-EOF
+_ACEOF
else
- echo "$ac_t""no" 1>&6
-cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define NO_LIMITS_H 1
-EOF
+_ACEOF
fi
- ac_safe=`echo "stdlib.h" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for stdlib.h""... $ac_c" 1>&6
-echo "configure:1169: checking for stdlib.h" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+
+ if test "${ac_cv_header_stdlib_h+set}" = set; then
+ echo "$as_me:$LINENO: checking for stdlib.h" >&5
+echo $ECHO_N "checking for stdlib.h... $ECHO_C" >&6
+if test "${ac_cv_header_stdlib_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdlib_h" >&5
+echo "${ECHO_T}$ac_cv_header_stdlib_h" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 1174 "configure"
-#include "confdefs.h"
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking stdlib.h usability" >&5
+echo $ECHO_N "checking stdlib.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <stdlib.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking stdlib.h presence" >&5
+echo $ECHO_N "checking stdlib.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <stdlib.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1179: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
fi
-rm -f conftest*
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: stdlib.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: stdlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: stdlib.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: stdlib.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: stdlib.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: stdlib.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: stdlib.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: stdlib.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: stdlib.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: stdlib.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: stdlib.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: stdlib.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: stdlib.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: stdlib.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: stdlib.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: stdlib.h: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to the tcl lists. ##
+## ------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for stdlib.h" >&5
+echo $ECHO_N "checking for stdlib.h... $ECHO_C" >&6
+if test "${ac_cv_header_stdlib_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_stdlib_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdlib_h" >&5
+echo "${ECHO_T}$ac_cv_header_stdlib_h" >&6
+
+fi
+if test $ac_cv_header_stdlib_h = yes; then
tcl_ok=1
else
- echo "$ac_t""no" 1>&6
-tcl_ok=0
+ tcl_ok=0
fi
- cat > conftest.$ac_ext <<EOF
-#line 1202 "configure"
-#include "confdefs.h"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <stdlib.h>
-EOF
+
+_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "strtol" >/dev/null 2>&1; then
+ $EGREP "strtol" >/dev/null 2>&1; then
:
else
- rm -rf conftest*
tcl_ok=0
fi
rm -f conftest*
- cat > conftest.$ac_ext <<EOF
-#line 1216 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <stdlib.h>
-EOF
+
+_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "strtoul" >/dev/null 2>&1; then
+ $EGREP "strtoul" >/dev/null 2>&1; then
:
else
- rm -rf conftest*
tcl_ok=0
fi
rm -f conftest*
- cat > conftest.$ac_ext <<EOF
-#line 1230 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <stdlib.h>
-EOF
+
+_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "strtod" >/dev/null 2>&1; then
+ $EGREP "strtod" >/dev/null 2>&1; then
:
else
- rm -rf conftest*
tcl_ok=0
fi
rm -f conftest*
if test $tcl_ok = 0; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define NO_STDLIB_H 1
-EOF
+_ACEOF
fi
- ac_safe=`echo "string.h" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for string.h""... $ac_c" 1>&6
-echo "configure:1251: checking for string.h" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1256 "configure"
-#include "confdefs.h"
+ if test "${ac_cv_header_string_h+set}" = set; then
+ echo "$as_me:$LINENO: checking for string.h" >&5
+echo $ECHO_N "checking for string.h... $ECHO_C" >&6
+if test "${ac_cv_header_string_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_string_h" >&5
+echo "${ECHO_T}$ac_cv_header_string_h" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking string.h usability" >&5
+echo $ECHO_N "checking string.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <string.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking string.h presence" >&5
+echo $ECHO_N "checking string.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <string.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1261: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
fi
-rm -f conftest*
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: string.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: string.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: string.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: string.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: string.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: string.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: string.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: string.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: string.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: string.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: string.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: string.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: string.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: string.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: string.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: string.h: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to the tcl lists. ##
+## ------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for string.h" >&5
+echo $ECHO_N "checking for string.h... $ECHO_C" >&6
+if test "${ac_cv_header_string_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_string_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_string_h" >&5
+echo "${ECHO_T}$ac_cv_header_string_h" >&6
+
+fi
+if test $ac_cv_header_string_h = yes; then
tcl_ok=1
else
- echo "$ac_t""no" 1>&6
-tcl_ok=0
+ tcl_ok=0
fi
- cat > conftest.$ac_ext <<EOF
-#line 1284 "configure"
-#include "confdefs.h"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <string.h>
-EOF
+
+_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "strstr" >/dev/null 2>&1; then
+ $EGREP "strstr" >/dev/null 2>&1; then
:
else
- rm -rf conftest*
tcl_ok=0
fi
rm -f conftest*
- cat > conftest.$ac_ext <<EOF
-#line 1298 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <string.h>
-EOF
+
+_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "strerror" >/dev/null 2>&1; then
+ $EGREP "strerror" >/dev/null 2>&1; then
:
else
- rm -rf conftest*
tcl_ok=0
fi
rm -f conftest*
@@ -1312,126 +3844,459 @@ rm -f conftest*
# set and why.
if test $tcl_ok = 0; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define NO_STRING_H 1
-EOF
+_ACEOF
fi
- ac_safe=`echo "sys/wait.h" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for sys/wait.h""... $ac_c" 1>&6
-echo "configure:1324: checking for sys/wait.h" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1329 "configure"
-#include "confdefs.h"
+ if test "${ac_cv_header_sys_wait_h+set}" = set; then
+ echo "$as_me:$LINENO: checking for sys/wait.h" >&5
+echo $ECHO_N "checking for sys/wait.h... $ECHO_C" >&6
+if test "${ac_cv_header_sys_wait_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking sys/wait.h usability" >&5
+echo $ECHO_N "checking sys/wait.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <sys/wait.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking sys/wait.h presence" >&5
+echo $ECHO_N "checking sys/wait.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/wait.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1334: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
fi
-rm -f conftest*
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: sys/wait.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: sys/wait.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/wait.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: sys/wait.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: sys/wait.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: sys/wait.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/wait.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: sys/wait.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/wait.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: sys/wait.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/wait.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: sys/wait.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/wait.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: sys/wait.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/wait.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: sys/wait.h: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to the tcl lists. ##
+## ------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for sys/wait.h" >&5
+echo $ECHO_N "checking for sys/wait.h... $ECHO_C" >&6
+if test "${ac_cv_header_sys_wait_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_sys_wait_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6
+
+fi
+if test $ac_cv_header_sys_wait_h = yes; then
:
else
- echo "$ac_t""no" 1>&6
-cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define NO_SYS_WAIT_H 1
-EOF
+_ACEOF
fi
- ac_safe=`echo "dlfcn.h" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for dlfcn.h""... $ac_c" 1>&6
-echo "configure:1361: checking for dlfcn.h" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+
+ if test "${ac_cv_header_dlfcn_h+set}" = set; then
+ echo "$as_me:$LINENO: checking for dlfcn.h" >&5
+echo $ECHO_N "checking for dlfcn.h... $ECHO_C" >&6
+if test "${ac_cv_header_dlfcn_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_dlfcn_h" >&5
+echo "${ECHO_T}$ac_cv_header_dlfcn_h" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 1366 "configure"
-#include "confdefs.h"
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking dlfcn.h usability" >&5
+echo $ECHO_N "checking dlfcn.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
#include <dlfcn.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1371: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking dlfcn.h presence" >&5
+echo $ECHO_N "checking dlfcn.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <dlfcn.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
fi
-rm -f conftest*
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: dlfcn.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: dlfcn.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: dlfcn.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: dlfcn.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: dlfcn.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: dlfcn.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: dlfcn.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: dlfcn.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: dlfcn.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: dlfcn.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: dlfcn.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: dlfcn.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: dlfcn.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: dlfcn.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: dlfcn.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: dlfcn.h: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to the tcl lists. ##
+## ------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for dlfcn.h" >&5
+echo $ECHO_N "checking for dlfcn.h... $ECHO_C" >&6
+if test "${ac_cv_header_dlfcn_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_dlfcn_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_dlfcn_h" >&5
+echo "${ECHO_T}$ac_cv_header_dlfcn_h" >&6
+
+fi
+if test $ac_cv_header_dlfcn_h = yes; then
:
else
- echo "$ac_t""no" 1>&6
-cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define NO_DLFCN_H 1
-EOF
+_ACEOF
fi
+
# OS/390 lacks sys/param.h (and doesn't need it, by chance).
- for ac_hdr in unistd.h sys/param.h
+
+for ac_header in sys/param.h
do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1402: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1407 "configure"
-#include "confdefs.h"
-#include <$ac_hdr>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1412: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
fi
-rm -f conftest*
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_hdr 1
-EOF
-
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to the tcl lists. ##
+## ------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- echo "$ac_t""no" 1>&6
+ eval "$as_ac_Header=\$ac_header_preproc"
fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
done
@@ -1442,35 +4307,62 @@ done
#------------------------------------------------------------------------
if test -z "$no_pipe" && test -n "$GCC"; then
- echo $ac_n "checking if the compiler understands -pipe""... $ac_c" 1>&6
-echo "configure:1447: checking if the compiler understands -pipe" >&5
-if eval "test \"`echo '$''{'tcl_cv_cc_pipe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking if the compiler understands -pipe" >&5
+echo $ECHO_N "checking if the compiler understands -pipe... $ECHO_C" >&6
+if test "${tcl_cv_cc_pipe+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe"
- cat > conftest.$ac_ext <<EOF
-#line 1454 "configure"
-#include "confdefs.h"
-int main() {
+ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
-; return 0; }
-EOF
-if { (eval echo configure:1461: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_cc_pipe=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_cc_pipe=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_cc_pipe=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
CFLAGS=$hold_cflags
fi
-
-echo "$ac_t""$tcl_cv_cc_pipe" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_cc_pipe" >&5
+echo "${ECHO_T}$tcl_cv_cc_pipe" >&6
if test $tcl_cv_cc_pipe = yes; then
CFLAGS="$CFLAGS -pipe"
fi
@@ -1487,8 +4379,7 @@ if test "${enable_threads+set}" = set; then
tcl_ok=$enableval
else
tcl_ok=no
-fi
-
+fi;
if test "${TCL_THREADS}" = 1; then
tcl_threaded_core=1;
@@ -1498,63 +4389,96 @@ fi
TCL_THREADS=1
# USE_THREAD_ALLOC tells us to try the special thread-based
# allocator that significantly reduces lock contention
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define USE_THREAD_ALLOC 1
-EOF
+_ACEOF
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define _REENTRANT 1
-EOF
+_ACEOF
if test "`uname -s`" = "SunOS" ; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define _POSIX_PTHREAD_SEMANTICS 1
-EOF
+_ACEOF
fi
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define _THREAD_SAFE 1
-EOF
+_ACEOF
- echo $ac_n "checking for pthread_mutex_init in -lpthread""... $ac_c" 1>&6
-echo "configure:1521: checking for pthread_mutex_init in -lpthread" >&5
-ac_lib_var=`echo pthread'_'pthread_mutex_init | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for pthread_mutex_init in -lpthread" >&5
+echo $ECHO_N "checking for pthread_mutex_init in -lpthread... $ECHO_C" >&6
+if test "${ac_cv_lib_pthread_pthread_mutex_init+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- ac_save_LIBS="$LIBS"
+ ac_check_lib_save_LIBS=$LIBS
LIBS="-lpthread $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 1529 "configure"
-#include "confdefs.h"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char pthread_mutex_init();
-
-int main() {
-pthread_mutex_init()
-; return 0; }
-EOF
-if { (eval echo configure:1540: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+ builtin and then its argument prototype would still apply. */
+char pthread_mutex_init ();
+int
+main ()
+{
+pthread_mutex_init ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_pthread_pthread_mutex_init=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_pthread_pthread_mutex_init=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5
+echo "${ECHO_T}$ac_cv_lib_pthread_pthread_mutex_init" >&6
+if test $ac_cv_lib_pthread_pthread_mutex_init = yes; then
tcl_ok=yes
else
- echo "$ac_t""no" 1>&6
-tcl_ok=no
+ tcl_ok=no
fi
if test "$tcl_ok" = "no"; then
@@ -1563,45 +4487,74 @@ fi
# defined. We could alternatively do an AC_TRY_COMPILE with
# pthread.h, but that will work with libpthread really doesn't
# exist, like AIX 4.2. [Bug: 4359]
- echo $ac_n "checking for __pthread_mutex_init in -lpthread""... $ac_c" 1>&6
-echo "configure:1568: checking for __pthread_mutex_init in -lpthread" >&5
-ac_lib_var=`echo pthread'_'__pthread_mutex_init | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for __pthread_mutex_init in -lpthread" >&5
+echo $ECHO_N "checking for __pthread_mutex_init in -lpthread... $ECHO_C" >&6
+if test "${ac_cv_lib_pthread___pthread_mutex_init+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- ac_save_LIBS="$LIBS"
+ ac_check_lib_save_LIBS=$LIBS
LIBS="-lpthread $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 1576 "configure"
-#include "confdefs.h"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char __pthread_mutex_init();
-
-int main() {
-__pthread_mutex_init()
-; return 0; }
-EOF
-if { (eval echo configure:1587: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+ builtin and then its argument prototype would still apply. */
+char __pthread_mutex_init ();
+int
+main ()
+{
+__pthread_mutex_init ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_pthread___pthread_mutex_init=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_pthread___pthread_mutex_init=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_pthread___pthread_mutex_init" >&5
+echo "${ECHO_T}$ac_cv_lib_pthread___pthread_mutex_init" >&6
+if test $ac_cv_lib_pthread___pthread_mutex_init = yes; then
tcl_ok=yes
else
- echo "$ac_t""no" 1>&6
-tcl_ok=no
+ tcl_ok=no
fi
fi
@@ -1610,132 +4563,219 @@ fi
# The space is needed
THREADS_LIBS=" -lpthread"
else
- echo $ac_n "checking for pthread_mutex_init in -lpthreads""... $ac_c" 1>&6
-echo "configure:1615: checking for pthread_mutex_init in -lpthreads" >&5
-ac_lib_var=`echo pthreads'_'pthread_mutex_init | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for pthread_mutex_init in -lpthreads" >&5
+echo $ECHO_N "checking for pthread_mutex_init in -lpthreads... $ECHO_C" >&6
+if test "${ac_cv_lib_pthreads_pthread_mutex_init+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- ac_save_LIBS="$LIBS"
+ ac_check_lib_save_LIBS=$LIBS
LIBS="-lpthreads $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 1623 "configure"
-#include "confdefs.h"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char pthread_mutex_init();
-
-int main() {
-pthread_mutex_init()
-; return 0; }
-EOF
-if { (eval echo configure:1634: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+ builtin and then its argument prototype would still apply. */
+char pthread_mutex_init ();
+int
+main ()
+{
+pthread_mutex_init ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_pthreads_pthread_mutex_init=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_pthreads_pthread_mutex_init=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_pthreads_pthread_mutex_init" >&5
+echo "${ECHO_T}$ac_cv_lib_pthreads_pthread_mutex_init" >&6
+if test $ac_cv_lib_pthreads_pthread_mutex_init = yes; then
tcl_ok=yes
else
- echo "$ac_t""no" 1>&6
-tcl_ok=no
+ tcl_ok=no
fi
if test "$tcl_ok" = "yes"; then
# The space is needed
THREADS_LIBS=" -lpthreads"
else
- echo $ac_n "checking for pthread_mutex_init in -lc""... $ac_c" 1>&6
-echo "configure:1660: checking for pthread_mutex_init in -lc" >&5
-ac_lib_var=`echo c'_'pthread_mutex_init | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for pthread_mutex_init in -lc" >&5
+echo $ECHO_N "checking for pthread_mutex_init in -lc... $ECHO_C" >&6
+if test "${ac_cv_lib_c_pthread_mutex_init+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- ac_save_LIBS="$LIBS"
+ ac_check_lib_save_LIBS=$LIBS
LIBS="-lc $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 1668 "configure"
-#include "confdefs.h"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char pthread_mutex_init();
-
-int main() {
-pthread_mutex_init()
-; return 0; }
-EOF
-if { (eval echo configure:1679: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+ builtin and then its argument prototype would still apply. */
+char pthread_mutex_init ();
+int
+main ()
+{
+pthread_mutex_init ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_c_pthread_mutex_init=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_c_pthread_mutex_init=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_c_pthread_mutex_init" >&5
+echo "${ECHO_T}$ac_cv_lib_c_pthread_mutex_init" >&6
+if test $ac_cv_lib_c_pthread_mutex_init = yes; then
tcl_ok=yes
else
- echo "$ac_t""no" 1>&6
-tcl_ok=no
+ tcl_ok=no
fi
if test "$tcl_ok" = "no"; then
- echo $ac_n "checking for pthread_mutex_init in -lc_r""... $ac_c" 1>&6
-echo "configure:1702: checking for pthread_mutex_init in -lc_r" >&5
-ac_lib_var=`echo c_r'_'pthread_mutex_init | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for pthread_mutex_init in -lc_r" >&5
+echo $ECHO_N "checking for pthread_mutex_init in -lc_r... $ECHO_C" >&6
+if test "${ac_cv_lib_c_r_pthread_mutex_init+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- ac_save_LIBS="$LIBS"
+ ac_check_lib_save_LIBS=$LIBS
LIBS="-lc_r $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 1710 "configure"
-#include "confdefs.h"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char pthread_mutex_init();
-
-int main() {
-pthread_mutex_init()
-; return 0; }
-EOF
-if { (eval echo configure:1721: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+ builtin and then its argument prototype would still apply. */
+char pthread_mutex_init ();
+int
+main ()
+{
+pthread_mutex_init ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_c_r_pthread_mutex_init=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_c_r_pthread_mutex_init=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_c_r_pthread_mutex_init" >&5
+echo "${ECHO_T}$ac_cv_lib_c_r_pthread_mutex_init" >&6
+if test $ac_cv_lib_c_r_pthread_mutex_init = yes; then
tcl_ok=yes
else
- echo "$ac_t""no" 1>&6
-tcl_ok=no
+ tcl_ok=no
fi
if test "$tcl_ok" = "yes"; then
@@ -1743,7 +4783,8 @@ fi
THREADS_LIBS=" -pthread"
else
TCL_THREADS=0
- echo "configure: warning: Don't know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile..." 1>&2
+ { echo "$as_me:$LINENO: WARNING: Don't know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile..." >&5
+echo "$as_me: WARNING: Don't know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile..." >&2;}
fi
fi
fi
@@ -1754,138 +4795,539 @@ fi
ac_saved_libs=$LIBS
LIBS="$LIBS $THREADS_LIBS"
- for ac_func in pthread_attr_setstacksize
+
+for ac_func in pthread_attr_setstacksize
do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1761: checking for $ac_func" >&5
-if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1766 "configure"
-#include "confdefs.h"
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
-int main() {
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+ echo "$as_me:$LINENO: checking for pthread_attr_get_np" >&5
+echo $ECHO_N "checking for pthread_attr_get_np... $ECHO_C" >&6
+if test "${ac_cv_func_pthread_attr_get_np+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define pthread_attr_get_np to an innocuous variant, in case <limits.h> declares pthread_attr_get_np.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define pthread_attr_get_np innocuous_pthread_attr_get_np
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char pthread_attr_get_np (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef pthread_attr_get_np
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char pthread_attr_get_np ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+#if defined (__stub_pthread_attr_get_np) || defined (__stub___pthread_attr_get_np)
choke me
#else
-$ac_func();
+char (*f) () = pthread_attr_get_np;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:1789: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
+int
+main ()
+{
+return f != pthread_attr_get_np;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_pthread_attr_get_np=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_pthread_attr_get_np=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_pthread_attr_get_np" >&5
+echo "${ECHO_T}$ac_cv_func_pthread_attr_get_np" >&6
+if test $ac_cv_func_pthread_attr_get_np = yes; then
+ tcl_ok=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
-fi
-rm -f conftest*
+ tcl_ok=no
fi
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
-EOF
-
+ if test $tcl_ok = yes ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTHREAD_ATTR_GET_NP 1
+_ACEOF
+
+ echo "$as_me:$LINENO: checking for pthread_attr_get_np declaration" >&5
+echo $ECHO_N "checking for pthread_attr_get_np declaration... $ECHO_C" >&6
+if test "${tcl_cv_grep_pthread_attr_get_np+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <pthread.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "pthread_attr_get_np" >/dev/null 2>&1; then
+ tcl_cv_grep_pthread_attr_get_np=present
else
- echo "$ac_t""no" 1>&6
+ tcl_cv_grep_pthread_attr_get_np=missing
fi
-done
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_grep_pthread_attr_get_np" >&5
+echo "${ECHO_T}$tcl_cv_grep_pthread_attr_get_np" >&6
+ if test $tcl_cv_grep_pthread_attr_get_np = missing ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ATTRGETNP_NOT_DECLARED 1
+_ACEOF
+
+ fi
+ else
+ echo "$as_me:$LINENO: checking for pthread_getattr_np" >&5
+echo $ECHO_N "checking for pthread_getattr_np... $ECHO_C" >&6
+if test "${ac_cv_func_pthread_getattr_np+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define pthread_getattr_np to an innocuous variant, in case <limits.h> declares pthread_getattr_np.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define pthread_getattr_np innocuous_pthread_getattr_np
- for ac_func in pthread_atfork
-do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1816: checking for $ac_func" >&5
-if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1821 "configure"
-#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
+ which can conflict with char pthread_getattr_np (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+#undef pthread_getattr_np
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char pthread_getattr_np ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+#if defined (__stub_pthread_getattr_np) || defined (__stub___pthread_getattr_np)
choke me
#else
-$ac_func();
+char (*f) () = pthread_getattr_np;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:1844: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
+int
+main ()
+{
+return f != pthread_getattr_np;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_pthread_getattr_np=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_pthread_getattr_np=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_pthread_getattr_np" >&5
+echo "${ECHO_T}$ac_cv_func_pthread_getattr_np" >&6
+if test $ac_cv_func_pthread_getattr_np = yes; then
+ tcl_ok=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
+ tcl_ok=no
+fi
+
+ if test $tcl_ok = yes ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTHREAD_GETATTR_NP 1
+_ACEOF
+
+ echo "$as_me:$LINENO: checking for pthread_getattr_np declaration" >&5
+echo $ECHO_N "checking for pthread_getattr_np declaration... $ECHO_C" >&6
+if test "${tcl_cv_grep_pthread_getattr_np+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <pthread.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "pthread_getattr_np" >/dev/null 2>&1; then
+ tcl_cv_grep_pthread_getattr_np=present
+else
+ tcl_cv_grep_pthread_getattr_np=missing
fi
rm -f conftest*
+
fi
+echo "$as_me:$LINENO: result: $tcl_cv_grep_pthread_getattr_np" >&5
+echo "${ECHO_T}$tcl_cv_grep_pthread_getattr_np" >&6
+ if test $tcl_cv_grep_pthread_getattr_np = missing ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define GETATTRNP_NOT_DECLARED 1
+_ACEOF
+
+ fi
+ fi
+ fi
+ if test $tcl_ok = no; then
+ # Darwin thread stacksize API
+
+for ac_func in pthread_get_stacksize_np
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
fi
done
+ fi
LIBS=$ac_saved_libs
else
TCL_THREADS=0
fi
# Do checking message here to not mess up interleaved configure output
- echo $ac_n "checking for building with threads""... $ac_c" 1>&6
-echo "configure:1874: checking for building with threads" >&5
+ echo "$as_me:$LINENO: checking for building with threads" >&5
+echo $ECHO_N "checking for building with threads... $ECHO_C" >&6
if test "${TCL_THREADS}" = 1; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define TCL_THREADS 1
-EOF
+_ACEOF
if test "${tcl_threaded_core}" = 1; then
- echo "$ac_t""yes (threaded core)" 1>&6
+ echo "$as_me:$LINENO: result: yes (threaded core)" >&5
+echo "${ECHO_T}yes (threaded core)" >&6
else
- echo "$ac_t""yes" 1>&6
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
fi
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me:$LINENO: result: no (default)" >&5
+echo "${ECHO_T}no (default)" >&6
fi
-
+
+
+
+#------------------------------------------------------------------------
+# Embedded configuration information, encoding to use for the values, TIP #59
+#------------------------------------------------------------------------
+
+
+
+# Check whether --with-encoding or --without-encoding was given.
+if test "${with_encoding+set}" = set; then
+ withval="$with_encoding"
+ with_tcencoding=${withval}
+fi;
+
+ if test x"${with_tcencoding}" != x ; then
+
+cat >>confdefs.h <<_ACEOF
+#define TCL_CFGVAL_ENCODING "${with_tcencoding}"
+_ACEOF
+
+ else
+
+cat >>confdefs.h <<\_ACEOF
+#define TCL_CFGVAL_ENCODING "iso8859-1"
+_ACEOF
+
+ fi
#--------------------------------------------------------------------
@@ -1900,89 +5342,162 @@ EOF
# right (and it must appear before "-lm").
#--------------------------------------------------------------------
- echo $ac_n "checking for sin""... $ac_c" 1>&6
-echo "configure:1905: checking for sin" >&5
-if eval "test \"`echo '$''{'ac_cv_func_sin'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1910 "configure"
-#include "confdefs.h"
+ echo "$as_me:$LINENO: checking for sin" >&5
+echo $ECHO_N "checking for sin... $ECHO_C" >&6
+if test "${ac_cv_func_sin+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define sin to an innocuous variant, in case <limits.h> declares sin.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define sin innocuous_sin
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char sin(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char sin();
+ which can conflict with char sin (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef sin
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char sin ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_sin) || defined (__stub___sin)
choke me
#else
-sin();
+char (*f) () = sin;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:1933: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_sin=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_sin=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'sin`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+int
+main ()
+{
+return f != sin;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_sin=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_sin=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_sin" >&5
+echo "${ECHO_T}$ac_cv_func_sin" >&6
+if test $ac_cv_func_sin = yes; then
MATH_LIBS=""
else
- echo "$ac_t""no" 1>&6
-MATH_LIBS="-lm"
+ MATH_LIBS="-lm"
fi
- echo $ac_n "checking for main in -lieee""... $ac_c" 1>&6
-echo "configure:1954: checking for main in -lieee" >&5
-ac_lib_var=`echo ieee'_'main | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for main in -lieee" >&5
+echo $ECHO_N "checking for main in -lieee... $ECHO_C" >&6
+if test "${ac_cv_lib_ieee_main+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- ac_save_LIBS="$LIBS"
+ ac_check_lib_save_LIBS=$LIBS
LIBS="-lieee $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 1962 "configure"
-#include "confdefs.h"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
-int main() {
-main()
-; return 0; }
-EOF
-if { (eval echo configure:1969: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+int
+main ()
+{
+main ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_ieee_main=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_ieee_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_ieee_main" >&5
+echo "${ECHO_T}$ac_cv_lib_ieee_main" >&6
+if test $ac_cv_lib_ieee_main = yes; then
MATH_LIBS="-lieee $MATH_LIBS"
-else
- echo "$ac_t""no" 1>&6
fi
@@ -1991,80 +5506,216 @@ fi
# needs net/errno.h to define the socket-related error codes.
#--------------------------------------------------------------------
- echo $ac_n "checking for main in -linet""... $ac_c" 1>&6
-echo "configure:1996: checking for main in -linet" >&5
-ac_lib_var=`echo inet'_'main | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for main in -linet" >&5
+echo $ECHO_N "checking for main in -linet... $ECHO_C" >&6
+if test "${ac_cv_lib_inet_main+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- ac_save_LIBS="$LIBS"
+ ac_check_lib_save_LIBS=$LIBS
LIBS="-linet $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2004 "configure"
-#include "confdefs.h"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
-int main() {
-main()
-; return 0; }
-EOF
-if { (eval echo configure:2011: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
+
+int
+main ()
+{
+main ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_inet_main=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_inet_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_inet_main" >&5
+echo "${ECHO_T}$ac_cv_lib_inet_main" >&6
+if test $ac_cv_lib_inet_main = yes; then
+ LIBS="$LIBS -linet"
fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
+ if test "${ac_cv_header_net_errno_h+set}" = set; then
+ echo "$as_me:$LINENO: checking for net/errno.h" >&5
+echo $ECHO_N "checking for net/errno.h... $ECHO_C" >&6
+if test "${ac_cv_header_net_errno_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_net_errno_h" >&5
+echo "${ECHO_T}$ac_cv_header_net_errno_h" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking net/errno.h usability" >&5
+echo $ECHO_N "checking net/errno.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <net/errno.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking net/errno.h presence" >&5
+echo $ECHO_N "checking net/errno.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <net/errno.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- LIBS="$LIBS -linet"
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
- ac_safe=`echo "net/errno.h" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for net/errno.h""... $ac_c" 1>&6
-echo "configure:2033: checking for net/errno.h" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: net/errno.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: net/errno.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: net/errno.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: net/errno.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: net/errno.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: net/errno.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: net/errno.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: net/errno.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: net/errno.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: net/errno.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: net/errno.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: net/errno.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: net/errno.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: net/errno.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: net/errno.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: net/errno.h: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to the tcl lists. ##
+## ------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for net/errno.h" >&5
+echo $ECHO_N "checking for net/errno.h... $ECHO_C" >&6
+if test "${ac_cv_header_net_errno_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 2038 "configure"
-#include "confdefs.h"
-#include <net/errno.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2043: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
+ ac_cv_header_net_errno_h=$ac_header_preproc
fi
-rm -f conftest*
+echo "$as_me:$LINENO: result: $ac_cv_header_net_errno_h" >&5
+echo "${ECHO_T}$ac_cv_header_net_errno_h" >&6
+
fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
-
- cat >> confdefs.h <<\EOF
+if test $ac_cv_header_net_errno_h = yes; then
+
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_NET_ERRNO_H 1
-EOF
+_ACEOF
-else
- echo "$ac_t""no" 1>&6
fi
+
#--------------------------------------------------------------------
# Check for the existence of the -lsocket and -lnsl libraries.
# The order here is important, so that they end up in the right
@@ -2084,141 +5735,264 @@ fi
#--------------------------------------------------------------------
tcl_checkBoth=0
- echo $ac_n "checking for connect""... $ac_c" 1>&6
-echo "configure:2089: checking for connect" >&5
-if eval "test \"`echo '$''{'ac_cv_func_connect'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2094 "configure"
-#include "confdefs.h"
+ echo "$as_me:$LINENO: checking for connect" >&5
+echo $ECHO_N "checking for connect... $ECHO_C" >&6
+if test "${ac_cv_func_connect+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define connect to an innocuous variant, in case <limits.h> declares connect.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define connect innocuous_connect
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char connect(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char connect();
+ which can conflict with char connect (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef connect
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char connect ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_connect) || defined (__stub___connect)
choke me
#else
-connect();
+char (*f) () = connect;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:2117: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_connect=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_connect=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'connect`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+int
+main ()
+{
+return f != connect;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_connect=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_connect=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_connect" >&5
+echo "${ECHO_T}$ac_cv_func_connect" >&6
+if test $ac_cv_func_connect = yes; then
tcl_checkSocket=0
else
- echo "$ac_t""no" 1>&6
-tcl_checkSocket=1
+ tcl_checkSocket=1
fi
if test "$tcl_checkSocket" = 1; then
- echo $ac_n "checking for setsockopt""... $ac_c" 1>&6
-echo "configure:2139: checking for setsockopt" >&5
-if eval "test \"`echo '$''{'ac_cv_func_setsockopt'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2144 "configure"
-#include "confdefs.h"
+ echo "$as_me:$LINENO: checking for setsockopt" >&5
+echo $ECHO_N "checking for setsockopt... $ECHO_C" >&6
+if test "${ac_cv_func_setsockopt+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define setsockopt to an innocuous variant, in case <limits.h> declares setsockopt.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define setsockopt innocuous_setsockopt
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char setsockopt(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char setsockopt();
+ which can conflict with char setsockopt (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+#undef setsockopt
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char setsockopt ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_setsockopt) || defined (__stub___setsockopt)
choke me
#else
-setsockopt();
+char (*f) () = setsockopt;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:2167: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_setsockopt=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_setsockopt=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'setsockopt`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+int
+main ()
+{
+return f != setsockopt;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_setsockopt=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_setsockopt=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_setsockopt" >&5
+echo "${ECHO_T}$ac_cv_func_setsockopt" >&6
+if test $ac_cv_func_setsockopt = yes; then
:
else
- echo "$ac_t""no" 1>&6
-echo $ac_n "checking for setsockopt in -lsocket""... $ac_c" 1>&6
-echo "configure:2185: checking for setsockopt in -lsocket" >&5
-ac_lib_var=`echo socket'_'setsockopt | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for setsockopt in -lsocket" >&5
+echo $ECHO_N "checking for setsockopt in -lsocket... $ECHO_C" >&6
+if test "${ac_cv_lib_socket_setsockopt+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- ac_save_LIBS="$LIBS"
+ ac_check_lib_save_LIBS=$LIBS
LIBS="-lsocket $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2193 "configure"
-#include "confdefs.h"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char setsockopt();
-
-int main() {
-setsockopt()
-; return 0; }
-EOF
-if { (eval echo configure:2204: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+ builtin and then its argument prototype would still apply. */
+char setsockopt ();
+int
+main ()
+{
+setsockopt ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_socket_setsockopt=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_socket_setsockopt=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_socket_setsockopt" >&5
+echo "${ECHO_T}$ac_cv_lib_socket_setsockopt" >&6
+if test $ac_cv_lib_socket_setsockopt = yes; then
LIBS="$LIBS -lsocket"
else
- echo "$ac_t""no" 1>&6
-tcl_checkBoth=1
+ tcl_checkBoth=1
fi
fi
@@ -2227,167 +6001,281 @@ fi
if test "$tcl_checkBoth" = 1; then
tk_oldLibs=$LIBS
LIBS="$LIBS -lsocket -lnsl"
- echo $ac_n "checking for accept""... $ac_c" 1>&6
-echo "configure:2232: checking for accept" >&5
-if eval "test \"`echo '$''{'ac_cv_func_accept'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2237 "configure"
-#include "confdefs.h"
+ echo "$as_me:$LINENO: checking for accept" >&5
+echo $ECHO_N "checking for accept... $ECHO_C" >&6
+if test "${ac_cv_func_accept+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define accept to an innocuous variant, in case <limits.h> declares accept.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define accept innocuous_accept
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char accept(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char accept();
+ which can conflict with char accept (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+#undef accept
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char accept ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_accept) || defined (__stub___accept)
choke me
#else
-accept();
+char (*f) () = accept;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:2260: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_accept=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_accept=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'accept`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+int
+main ()
+{
+return f != accept;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_accept=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_accept=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_accept" >&5
+echo "${ECHO_T}$ac_cv_func_accept" >&6
+if test $ac_cv_func_accept = yes; then
tcl_checkNsl=0
else
- echo "$ac_t""no" 1>&6
-LIBS=$tk_oldLibs
+ LIBS=$tk_oldLibs
fi
fi
- echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6
-echo "configure:2282: checking for gethostbyname" >&5
-if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2287 "configure"
-#include "confdefs.h"
+ echo "$as_me:$LINENO: checking for gethostbyname" >&5
+echo $ECHO_N "checking for gethostbyname... $ECHO_C" >&6
+if test "${ac_cv_func_gethostbyname+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define gethostbyname to an innocuous variant, in case <limits.h> declares gethostbyname.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define gethostbyname innocuous_gethostbyname
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char gethostbyname(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char gethostbyname();
+ which can conflict with char gethostbyname (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+#undef gethostbyname
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyname ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_gethostbyname) || defined (__stub___gethostbyname)
choke me
#else
-gethostbyname();
+char (*f) () = gethostbyname;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:2310: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_gethostbyname=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_gethostbyname=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'gethostbyname`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+int
+main ()
+{
+return f != gethostbyname;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_gethostbyname=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_gethostbyname=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5
+echo "${ECHO_T}$ac_cv_func_gethostbyname" >&6
+if test $ac_cv_func_gethostbyname = yes; then
:
else
- echo "$ac_t""no" 1>&6
-echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6
-echo "configure:2328: checking for gethostbyname in -lnsl" >&5
-ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5
+echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6
+if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- ac_save_LIBS="$LIBS"
+ ac_check_lib_save_LIBS=$LIBS
LIBS="-lnsl $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2336 "configure"
-#include "confdefs.h"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char gethostbyname();
-
-int main() {
-gethostbyname()
-; return 0; }
-EOF
-if { (eval echo configure:2347: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+ builtin and then its argument prototype would still apply. */
+char gethostbyname ();
+int
+main ()
+{
+gethostbyname ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_nsl_gethostbyname=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_nsl_gethostbyname=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5
+echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6
+if test $ac_cv_lib_nsl_gethostbyname = yes; then
LIBS="$LIBS -lnsl"
-else
- echo "$ac_t""no" 1>&6
fi
fi
- # Don't perform the eval of the libraries here because DL_LIBS
- # won't be set until we call SC_CONFIG_CFLAGS
-
- TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}'
-
-
-
# Add the threads support libraries
LIBS="$LIBS$THREADS_LIBS"
- echo $ac_n "checking how to build libraries""... $ac_c" 1>&6
-echo "configure:2383: checking how to build libraries" >&5
+ echo "$as_me:$LINENO: checking how to build libraries" >&5
+echo $ECHO_N "checking how to build libraries... $ECHO_C" >&6
# Check whether --enable-shared or --disable-shared was given.
if test "${enable_shared+set}" = set; then
enableval="$enable_shared"
tcl_ok=$enableval
else
tcl_ok=yes
-fi
-
+fi;
if test "${enable_shared+set}" = set; then
enableval="$enable_shared"
@@ -2397,14 +6285,17 @@ fi
fi
if test "$tcl_ok" = "yes" ; then
- echo "$ac_t""shared" 1>&6
+ echo "$as_me:$LINENO: result: shared" >&5
+echo "${ECHO_T}shared" >&6
SHARED_BUILD=1
else
- echo "$ac_t""static" 1>&6
+ echo "$as_me:$LINENO: result: static" >&5
+echo "${ECHO_T}static" >&6
SHARED_BUILD=0
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define STATIC_BUILD 1
-EOF
+_ACEOF
fi
@@ -2415,87 +6306,225 @@ EOF
# after SC_ENABLE_SHARED checks the configure switches.
#--------------------------------------------------------------------
-# Extract the first word of "ranlib", so it can be a program name with args.
-set dummy ranlib; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2422: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test -n "$RANLIB"; then
ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_RANLIB="ranlib"
- break
- fi
- done
- IFS="$ac_save_ifs"
- test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
fi
fi
-RANLIB="$ac_cv_prog_RANLIB"
+RANLIB=$ac_cv_prog_RANLIB
if test -n "$RANLIB"; then
- echo "$ac_t""$RANLIB" 1>&6
+ echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ RANLIB=$ac_ct_RANLIB
+else
+ RANLIB="$ac_cv_prog_RANLIB"
fi
# Step 0.a: Enable 64 bit support?
- echo $ac_n "checking if 64bit support is requested""... $ac_c" 1>&6
-echo "configure:2454: checking if 64bit support is requested" >&5
+ echo "$as_me:$LINENO: checking if 64bit support is requested" >&5
+echo $ECHO_N "checking if 64bit support is requested... $ECHO_C" >&6
# Check whether --enable-64bit or --disable-64bit was given.
if test "${enable_64bit+set}" = set; then
enableval="$enable_64bit"
do64bit=$enableval
else
do64bit=no
-fi
-
- echo "$ac_t""$do64bit" 1>&6
+fi;
+ echo "$as_me:$LINENO: result: $do64bit" >&5
+echo "${ECHO_T}$do64bit" >&6
# Step 0.b: Enable Solaris 64 bit VIS support?
- echo $ac_n "checking if 64bit Sparc VIS support is requested""... $ac_c" 1>&6
-echo "configure:2468: checking if 64bit Sparc VIS support is requested" >&5
+ echo "$as_me:$LINENO: checking if 64bit Sparc VIS support is requested" >&5
+echo $ECHO_N "checking if 64bit Sparc VIS support is requested... $ECHO_C" >&6
# Check whether --enable-64bit-vis or --disable-64bit-vis was given.
if test "${enable_64bit_vis+set}" = set; then
enableval="$enable_64bit_vis"
do64bitVIS=$enableval
else
do64bitVIS=no
+fi;
+ echo "$as_me:$LINENO: result: $do64bitVIS" >&5
+echo "${ECHO_T}$do64bitVIS" >&6
+ # Force 64bit on with VIS
+ if test "$do64bitVIS" = "yes"; then
+ do64bit=yes
fi
- echo "$ac_t""$do64bitVIS" 1>&6
- if test "$do64bitVIS" = "yes"; then
- # Force 64bit on with VIS
- do64bit=yes
- fi
+ # Step 0.c: Check if visibility support is available. Do this here so
+ # that platform specific alternatives can be used below if this fails.
+
+ echo "$as_me:$LINENO: checking if compiler supports visibility \"hidden\"" >&5
+echo $ECHO_N "checking if compiler supports visibility \"hidden\"... $ECHO_C" >&6
+if test "${tcl_cv_cc_visibility_hidden+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+ extern __attribute__((__visibility__("hidden"))) void f(void);
+ void f(void) {}
+int
+main ()
+{
+f();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ tcl_cv_cc_visibility_hidden=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_cc_visibility_hidden=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ CFLAGS=$hold_cflags
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_cc_visibility_hidden" >&5
+echo "${ECHO_T}$tcl_cv_cc_visibility_hidden" >&6
+ if test $tcl_cv_cc_visibility_hidden = yes; then
+
+
+cat >>confdefs.h <<\_ACEOF
+#define MODULE_SCOPE extern __attribute__((__visibility__("hidden")))
+_ACEOF
+
+
+fi
+
+
+ # Step 0.d: Disable -rpath support?
+
+ echo "$as_me:$LINENO: checking if rpath support is requested" >&5
+echo $ECHO_N "checking if rpath support is requested... $ECHO_C" >&6
+ # Check whether --enable-rpath or --disable-rpath was given.
+if test "${enable_rpath+set}" = set; then
+ enableval="$enable_rpath"
+ doRpath=$enableval
+else
+ doRpath=yes
+fi;
+ echo "$as_me:$LINENO: result: $doRpath" >&5
+echo "${ECHO_T}$doRpath" >&6
# Step 1: set the variable "system" to hold the name and version number
# for the system.
-
- echo $ac_n "checking system version""... $ac_c" 1>&6
-echo "configure:2489: checking system version" >&5
-if eval "test \"`echo '$''{'tcl_cv_sys_version'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+
+ echo "$as_me:$LINENO: checking system version" >&5
+echo $ECHO_N "checking system version... $ECHO_C" >&6
+if test "${tcl_cv_sys_version+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
+
if test -f /usr/lib/NextStep/software_version; then
tcl_cv_sys_version=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version`
else
tcl_cv_sys_version=`uname -s`-`uname -r`
if test "$?" -ne 0 ; then
- echo "configure: warning: can't find uname command" 1>&2
+ { echo "$as_me:$LINENO: WARNING: can't find uname command" >&5
+echo "$as_me: WARNING: can't find uname command" >&2;}
tcl_cv_sys_version=unknown
else
# Special check for weird MP-RAS system (uname returns weird
@@ -2509,120 +6538,207 @@ else
fi
fi
fi
-
-fi
-echo "$ac_t""$tcl_cv_sys_version" 1>&6
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_sys_version" >&5
+echo "${ECHO_T}$tcl_cv_sys_version" >&6
system=$tcl_cv_sys_version
# Step 2: check for existence of -ldl library. This is needed because
# Linux can use either -ldl or -ldld for dynamic loading.
- echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
-echo "configure:2524: checking for dlopen in -ldl" >&5
-ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- ac_save_LIBS="$LIBS"
+ ac_check_lib_save_LIBS=$LIBS
LIBS="-ldl $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2532 "configure"
-#include "confdefs.h"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char dlopen();
-
-int main() {
-dlopen()
-; return 0; }
-EOF
-if { (eval echo configure:2543: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+ builtin and then its argument prototype would still apply. */
+char dlopen ();
+int
+main ()
+{
+dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_dl_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dl_dlopen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6
+if test $ac_cv_lib_dl_dlopen = yes; then
have_dl=yes
else
- echo "$ac_t""no" 1>&6
-have_dl=no
+ have_dl=no
fi
# Require ranlib early so we can override it in special cases below.
+ if test x"${SHLIB_VERSION}" = x; then
+ SHLIB_VERSION="1.0"
+fi
+
+
-
# Step 3: set configuration options based on system name and version.
do64bit_ok=no
+ # default to '{$LIBS}' and set to "" on per-platform necessary basis
+ SHLIB_LD_LIBS='${LIBS}'
LDFLAGS_ORIG="$LDFLAGS"
- TCL_EXPORT_FILE_SUFFIX=""
+ # When ld needs options to work in 64-bit mode, put them in
+ # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load]
+ # is disabled by the user. [Bug 1016796]
+ LDFLAGS_ARCH=""
UNSHARED_LIB_SUFFIX=""
TCL_TRIM_DOTS='`echo ${VERSION} | tr -d .`'
ECHO_VERSION='`echo ${VERSION}`'
TCL_LIB_VERSIONS_OK=ok
CFLAGS_DEBUG=-g
CFLAGS_OPTIMIZE=-O
- if test "$GCC" = "yes" ; then
- CFLAGS_WARNING="-Wall -fno-strict-aliasing"
- else
- CFLAGS_WARNING=""
- fi
- TCL_NEEDS_EXP_FILE=0
- TCL_BUILD_EXP_FILE=""
- TCL_EXP_FILE=""
- # Extract the first word of "ar", so it can be a program name with args.
-set dummy ar; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2591: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ if test "$GCC" = yes; then
+
+ CFLAGS_WARNING="-Wall"
+
+else
+ CFLAGS_WARNING=""
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_AR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test -n "$AR"; then
ac_cv_prog_AR="$AR" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_AR="ar"
- break
- fi
- done
- IFS="$ac_save_ifs"
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
fi
fi
-AR="$ac_cv_prog_AR"
+AR=$ac_cv_prog_AR
if test -n "$AR"; then
- echo "$ac_t""$AR" 1>&6
+ echo "$as_me:$LINENO: result: $AR" >&5
+echo "${ECHO_T}$AR" >&6
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="ar"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ echo "$as_me:$LINENO: result: $ac_ct_AR" >&5
+echo "${ECHO_T}$ac_ct_AR" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ AR=$ac_ct_AR
+else
+ AR="$ac_cv_prog_AR"
fi
- if test "${AR}" = "" ; then
- { echo "configure: error: Required archive tool 'ar' not found on PATH." 1>&2; exit 1; }
- fi
STLIB_LD='${AR} cr'
LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH"
PLAT_OBJS=""
PLAT_SRCS=""
+ LDAIX_SRC=""
case $system in
AIX-*)
- if test "${TCL_THREADS}" = "1" -a "$GCC" != "yes" ; then
+ if test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"; then
+
# AIX requires the _r compiler when gcc isn't being used
case "${CC}" in
*_r|*_r\ *)
@@ -2633,128 +6749,87 @@ fi
CC=`echo "$CC" | sed -e 's/^\([^ ]*\)/\1_r/'`
;;
esac
- echo "$ac_t""Using $CC for compiling with threads" 1>&6
- fi
+ echo "$as_me:$LINENO: result: Using $CC for compiling with threads" >&5
+echo "${ECHO_T}Using $CC for compiling with threads" >&6
+
+fi
+
LIBS="$LIBS -lc"
SHLIB_CFLAGS=""
- # Note: need the LIBS below, otherwise Tk won't find Tcl's
- # symbols when dynamically loaded into tclsh.
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
LD_LIBRARY_PATH_VAR="LIBPATH"
- # Check to enable 64-bit flags for compiler/linker on AIX 4+
- if test "$do64bit" = "yes" -a "`uname -v`" -gt "3" ; then
- if test "$GCC" = "yes" ; then
- echo "configure: warning: 64bit mode not supported with GCC on $system" 1>&2
- else
+ # ldAix No longer needed with use of -bexpall/-brtl
+ # but some extensions may still reference it
+ LDAIX_SRC='$(UNIX_DIR)/ldAix'
+
+ # Check to enable 64-bit flags for compiler/linker
+ if test "$do64bit" = yes; then
+
+ if test "$GCC" = yes; then
+
+ { echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC on $system" >&5
+echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;}
+
+else
+
do64bit_ok=yes
CFLAGS="$CFLAGS -q64"
- LDFLAGS="$LDFLAGS -q64"
+ LDFLAGS_ARCH="-q64"
RANLIB="${RANLIB} -X64"
AR="${AR} -X64"
SHLIB_LD_FLAGS="-b64"
- fi
- fi
- if test "`uname -m`" = "ia64" ; then
+fi
+
+
+fi
+
+
+ if test "`uname -m`" = ia64; then
+
# AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC
SHLIB_LD="/usr/ccs/bin/ld -G -z text"
# AIX-5 has dl* in libc.so
DL_LIBS=""
- if test "$GCC" = "yes" ; then
+ if test "$GCC" = yes; then
+
CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
- else
+
+else
+
CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}'
- fi
+
+fi
+
LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
- else
- if test "$GCC" = "yes" ; then
- SHLIB_LD="gcc -shared"
- else
- SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry"
- fi
- SHLIB_LD="${TCL_SRC_DIR}/unix/ldAix ${SHLIB_LD} ${SHLIB_LD_FLAGS}"
- DL_LIBS="-ldl"
- CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- TCL_NEEDS_EXP_FILE=1
- TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.exp'
- fi
- # AIX v<=4.1 has some different flags than 4.2+
- if test "$system" = "AIX-4.1" -o "`uname -v`" -lt "4" ; then
- LIBOBJS="$LIBOBJS tclLoadAix.o"
- DL_LIBS="-lld"
- fi
+else
- # On AIX <=v4 systems, libbsd.a has to be linked in to support
- # non-blocking file IO. This library has to be linked in after
- # the MATH_LIBS or it breaks the pow() function. The way to
- # insure proper sequencing, is to add it to the tail of MATH_LIBS.
- # This library also supplies gettimeofday.
- #
- # AIX does not have a timezone field in struct tm. When the AIX
- # bsd library is used, the timezone global and the gettimeofday
- # methods are to be avoided for timezone deduction instead, we
- # deduce the timezone by comparing the localtime result on a
- # known GMT value.
-
- echo $ac_n "checking for gettimeofday in -lbsd""... $ac_c" 1>&6
-echo "configure:2707: checking for gettimeofday in -lbsd" >&5
-ac_lib_var=`echo bsd'_'gettimeofday | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-lbsd $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2715 "configure"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char gettimeofday();
+ if test "$GCC" = yes; then
-int main() {
-gettimeofday()
-; return 0; }
-EOF
-if { (eval echo configure:2726: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
+ SHLIB_LD='${CC} -shared -Wl,-bexpall'
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- libbsd=yes
else
- echo "$ac_t""no" 1>&6
-libbsd=no
+
+ SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry"
+ LDFLAGS="$LDFLAGS -brtl"
+
fi
- if test $libbsd = yes; then
- MATH_LIBS="$MATH_LIBS -lbsd"
- cat >> confdefs.h <<\EOF
-#define USE_DELTA_FOR_TZ 1
-EOF
+ SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}"
+ DL_LIBS="-ldl"
+ CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+
+fi
- fi
;;
BeOS*)
SHLIB_CFLAGS="-fPIC"
- SHLIB_LD="${CC} -nostart"
- SHLIB_LD_LIBS='${LIBS}'
+ SHLIB_LD='${CC} -nostart'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS="-ldl"
@@ -2764,51 +6839,78 @@ EOF
# -lsocket, even if the network functions are in -lnet which
# is always linked to, for compatibility.
#-----------------------------------------------------------
- echo $ac_n "checking for inet_ntoa in -lbind""... $ac_c" 1>&6
-echo "configure:2769: checking for inet_ntoa in -lbind" >&5
-ac_lib_var=`echo bind'_'inet_ntoa | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for inet_ntoa in -lbind" >&5
+echo $ECHO_N "checking for inet_ntoa in -lbind... $ECHO_C" >&6
+if test "${ac_cv_lib_bind_inet_ntoa+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- ac_save_LIBS="$LIBS"
+ ac_check_lib_save_LIBS=$LIBS
LIBS="-lbind $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2777 "configure"
-#include "confdefs.h"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char inet_ntoa();
-
-int main() {
-inet_ntoa()
-; return 0; }
-EOF
-if { (eval echo configure:2788: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+ builtin and then its argument prototype would still apply. */
+char inet_ntoa ();
+int
+main ()
+{
+inet_ntoa ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_bind_inet_ntoa=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_bind_inet_ntoa=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_bind_inet_ntoa" >&5
+echo "${ECHO_T}$ac_cv_lib_bind_inet_ntoa" >&6
+if test $ac_cv_lib_bind_inet_ntoa = yes; then
LIBS="$LIBS -lbind -lsocket"
-else
- echo "$ac_t""no" 1>&6
fi
;;
BSD/OS-2.1*|BSD/OS-3*)
SHLIB_CFLAGS=""
SHLIB_LD="shlicc -r"
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS="-ldl"
@@ -2818,7 +6920,6 @@ fi
BSD/OS-4.*)
SHLIB_CFLAGS="-export-dynamic -fPIC"
SHLIB_LD='${CC} -shared'
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS="-ldl"
@@ -2829,7 +6930,6 @@ fi
CYGWIN_*)
SHLIB_CFLAGS=""
SHLIB_LD='${CC} -shared'
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".dll"
DL_OBJS="tclLoadDl.o"
DL_LIBS="-ldl"
@@ -2846,152 +6946,308 @@ fi
CC_SEARCH_FLAGS=""
LD_SEARCH_FLAGS=""
;;
+ Haiku*)
+ LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_SUFFIX=".so"
+ SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-lroot"
+ echo "$as_me:$LINENO: checking for inet_ntoa in -lnetwork" >&5
+echo $ECHO_N "checking for inet_ntoa in -lnetwork... $ECHO_C" >&6
+if test "${ac_cv_lib_network_inet_ntoa+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnetwork $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char inet_ntoa ();
+int
+main ()
+{
+inet_ntoa ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_network_inet_ntoa=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_network_inet_ntoa=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_network_inet_ntoa" >&5
+echo "${ECHO_T}$ac_cv_lib_network_inet_ntoa" >&6
+if test $ac_cv_lib_network_inet_ntoa = yes; then
+ LIBS="$LIBS -lnetwork"
+fi
+
+ ;;
HP-UX-*.11.*)
# Use updated header definitions where possible
- cat >> confdefs.h <<\EOF
-#define _XOPEN_SOURCE 1
-EOF
- # Use the XOPEN network library
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define _XOPEN_SOURCE_EXTENDED 1
-EOF
- # Use the XOPEN network library
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define _XOPEN_SOURCE 1
+_ACEOF
+
LIBS="$LIBS -lxnet" # Use the XOPEN network library
- if test "`uname -m`" = "ia64" ; then
+ if test "`uname -m`" = ia64; then
+
SHLIB_SUFFIX=".so"
- else
+
+else
+
SHLIB_SUFFIX=".sl"
- fi
- echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6
-echo "configure:2868: checking for shl_load in -ldld" >&5
-ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+
+fi
+
+ echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5
+echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6
+if test "${ac_cv_lib_dld_shl_load+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- ac_save_LIBS="$LIBS"
+ ac_check_lib_save_LIBS=$LIBS
LIBS="-ldld $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2876 "configure"
-#include "confdefs.h"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char shl_load();
-
-int main() {
-shl_load()
-; return 0; }
-EOF
-if { (eval echo configure:2887: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+ builtin and then its argument prototype would still apply. */
+char shl_load ();
+int
+main ()
+{
+shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_dld_shl_load=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dld_shl_load=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6
+if test $ac_cv_lib_dld_shl_load = yes; then
tcl_ok=yes
else
- echo "$ac_t""no" 1>&6
-tcl_ok=no
+ tcl_ok=no
fi
if test "$tcl_ok" = yes; then
+
SHLIB_CFLAGS="+z"
SHLIB_LD="ld -b"
- SHLIB_LD_LIBS='${LIBS}'
DL_OBJS="tclLoadShl.o"
DL_LIBS="-ldld"
LDFLAGS="$LDFLAGS -Wl,-E"
CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'
LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'
LD_LIBRARY_PATH_VAR="SHLIB_PATH"
- fi
- if test "$GCC" = "yes" ; then
- SHLIB_LD="gcc -shared"
- SHLIB_LD_LIBS='${LIBS}'
+
+fi
+
+ if test "$GCC" = yes; then
+
+ SHLIB_LD='${CC} -shared'
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- fi
+
+fi
+
# Users may want PA-RISC 1.1/2.0 portable code - needs HP cc
#CFLAGS="$CFLAGS +DAportable"
# Check to enable 64-bit flags for compiler/linker
- if test "$do64bit" = "yes" ; then
- if test "$GCC" = "yes" ; then
- hpux_arch=`${CC} -dumpmachine`
- case $hpux_arch in
+ if test "$do64bit" = "yes"; then
+
+ if test "$GCC" = yes; then
+
+ case `${CC} -dumpmachine` in
hppa64*)
# 64-bit gcc in use. Fix flags for GNU ld.
do64bit_ok=yes
- SHLIB_LD="${CC} -shared"
- SHLIB_LD_LIBS='${LIBS}'
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ SHLIB_LD='${CC} -shared'
+ if test $doRpath = yes; then
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+fi
+
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
;;
*)
- echo "configure: warning: 64bit mode not supported with GCC on $system" 1>&2
+ { echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC on $system" >&5
+echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;}
;;
esac
- else
+
+else
+
do64bit_ok=yes
CFLAGS="$CFLAGS +DD64"
- LDFLAGS="$LDFLAGS +DD64"
- fi
- fi
- ;;
+ LDFLAGS_ARCH="+DD64"
+
+fi
+
+
+fi
+ ;;
HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*)
SHLIB_SUFFIX=".sl"
- echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6
-echo "configure:2955: checking for shl_load in -ldld" >&5
-ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5
+echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6
+if test "${ac_cv_lib_dld_shl_load+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- ac_save_LIBS="$LIBS"
+ ac_check_lib_save_LIBS=$LIBS
LIBS="-ldld $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2963 "configure"
-#include "confdefs.h"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char shl_load();
-
-int main() {
-shl_load()
-; return 0; }
-EOF
-if { (eval echo configure:2974: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+ builtin and then its argument prototype would still apply. */
+char shl_load ();
+int
+main ()
+{
+shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_dld_shl_load=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dld_shl_load=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6
+if test $ac_cv_lib_dld_shl_load = yes; then
tcl_ok=yes
else
- echo "$ac_t""no" 1>&6
-tcl_ok=no
+ tcl_ok=no
fi
if test "$tcl_ok" = yes; then
+
SHLIB_CFLAGS="+z"
SHLIB_LD="ld -b"
SHLIB_LD_LIBS=""
@@ -3001,43 +7257,41 @@ fi
CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'
LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'
LD_LIBRARY_PATH_VAR="SHLIB_PATH"
- fi
- ;;
- IRIX-4.*)
- SHLIB_CFLAGS="-G 0"
- SHLIB_SUFFIX=".a"
- SHLIB_LD="echo tclLdAout $CC \{$SHLIB_CFLAGS\} | `pwd`/tclsh -r -G 0"
- SHLIB_LD_LIBS='${LIBS}'
- DL_OBJS="tclLoadAout.o"
- DL_LIBS=""
- LDFLAGS="$LDFLAGS -Wl,-D,08000000"
- CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- SHARED_LIB_SUFFIX='${VERSION}\$\{DBGX\}.a'
- ;;
+
+fi
+ ;;
IRIX-5.*)
SHLIB_CFLAGS=""
SHLIB_LD="ld -shared -rdata_shared"
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS=""
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
+ if test $doRpath = yes; then
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
+fi
+
;;
IRIX-6.*)
SHLIB_CFLAGS=""
SHLIB_LD="ld -n32 -shared -rdata_shared"
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS=""
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
- if test "$GCC" = "yes" ; then
+ if test $doRpath = yes; then
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
+fi
+
+ if test "$GCC" = yes; then
+
CFLAGS="$CFLAGS -mabi=n32"
LDFLAGS="$LDFLAGS -mabi=n32"
- else
+
+else
+
case $system in
IRIX-6.3)
# Use to build 6.2 compatible binaries on 6.3.
@@ -3048,218 +7302,184 @@ fi
;;
esac
LDFLAGS="$LDFLAGS -n32"
- fi
+
+fi
+
;;
IRIX64-6.*)
SHLIB_CFLAGS=""
SHLIB_LD="ld -n32 -shared -rdata_shared"
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS=""
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
+ if test $doRpath = yes; then
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
+fi
+
# Check to enable 64-bit flags for compiler/linker
- if test "$do64bit" = "yes" ; then
- if test "$GCC" = "yes" ; then
- echo "configure: warning: 64bit mode not supported by gcc" 1>&2
- else
+ if test "$do64bit" = yes; then
+
+ if test "$GCC" = yes; then
+
+ { echo "$as_me:$LINENO: WARNING: 64bit mode not supported by gcc" >&5
+echo "$as_me: WARNING: 64bit mode not supported by gcc" >&2;}
+
+else
+
do64bit_ok=yes
SHLIB_LD="ld -64 -shared -rdata_shared"
CFLAGS="$CFLAGS -64"
- LDFLAGS="$LDFLAGS -64"
- fi
- fi
+ LDFLAGS_ARCH="-64"
+
+fi
+
+
+fi
+
;;
Linux*)
SHLIB_CFLAGS="-fPIC"
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
- CFLAGS_OPTIMIZE=-O2
+ CFLAGS_OPTIMIZE="-O2"
# egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings
# when you inline the string and math operations. Turn this off to
# get rid of the warnings.
#CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES"
- if test "$have_dl" = yes; then
- SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
- DL_OBJS="tclLoadDl.o"
- DL_LIBS="-ldl"
- LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+ SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+ if test $doRpath = yes; then
+
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- else
- ac_safe=`echo "dld.h" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for dld.h""... $ac_c" 1>&6
-echo "configure:3098: checking for dld.h" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 3103 "configure"
-#include "confdefs.h"
-#include <dld.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3108: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
-
- SHLIB_LD="ld -shared"
- DL_OBJS="tclLoadDld.o"
- DL_LIBS="-ldld"
- CC_SEARCH_FLAGS=""
- LD_SEARCH_FLAGS=""
-else
- echo "$ac_t""no" 1>&6
+
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ if test "`uname -m`" = "alpha"; then
+ CFLAGS="$CFLAGS -mieee"
fi
- fi
- if test "`uname -m`" = "alpha" ; then
- CFLAGS="$CFLAGS -mieee"
- fi
if test $do64bit = yes; then
- echo $ac_n "checking if compiler accepts -m64 flag""... $ac_c" 1>&6
-echo "configure:3140: checking if compiler accepts -m64 flag" >&5
-if eval "test \"`echo '$''{'tcl_cv_cc_m64'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+
+ echo "$as_me:$LINENO: checking if compiler accepts -m64 flag" >&5
+echo $ECHO_N "checking if compiler accepts -m64 flag... $ECHO_C" >&6
+if test "${tcl_cv_cc_m64+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
+
hold_cflags=$CFLAGS
CFLAGS="$CFLAGS -m64"
- cat > conftest.$ac_ext <<EOF
-#line 3148 "configure"
-#include "confdefs.h"
-
-int main() {
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
-; return 0; }
-EOF
-if { (eval echo configure:3155: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_cc_m64=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_cc_m64=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_cc_m64=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
CFLAGS=$hold_cflags
fi
-
-echo "$ac_t""$tcl_cv_cc_m64" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_cc_m64" >&5
+echo "${ECHO_T}$tcl_cv_cc_m64" >&6
if test $tcl_cv_cc_m64 = yes; then
+
CFLAGS="$CFLAGS -m64"
do64bit_ok=yes
- fi
- fi
- # The combo of gcc + glibc has a bug related
- # to inlining of functions like strtod(). The
- # -fno-builtin flag should address this problem
- # but it does not work. The -fno-inline flag
- # is kind of overkill but it works.
- # Disable inlining only when one of the
- # files in compat/*.c is being linked in.
- if test x"${LIBOBJS}" != x ; then
- CFLAGS="$CFLAGS -fno-inline"
- fi
+fi
- # XIM peeking works under XFree86.
- cat >> confdefs.h <<\EOF
-#define PEEK_XCLOSEIM 1
-EOF
+fi
+
+
+ # The combo of gcc + glibc has a bug related to inlining of
+ # functions like strtod(). The -fno-builtin flag should address
+ # this problem but it does not work. The -fno-inline flag is kind
+ # of overkill but it works. Disable inlining only when one of the
+ # files in compat/*.c is being linked in.
+
+ if test x"${USE_COMPAT}" != x; then
+ CFLAGS="$CFLAGS -fno-inline"
+fi
;;
GNU*)
SHLIB_CFLAGS="-fPIC"
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
- if test "$have_dl" = yes; then
- SHLIB_LD="${CC} -shared"
- DL_OBJS=""
- DL_LIBS="-ldl"
- LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
- CC_SEARCH_FLAGS=""
- LD_SEARCH_FLAGS=""
- else
- ac_safe=`echo "dld.h" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for dld.h""... $ac_c" 1>&6
-echo "configure:3208: checking for dld.h" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 3213 "configure"
-#include "confdefs.h"
-#include <dld.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3218: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
-
- SHLIB_LD="ld -shared"
- DL_OBJS=""
- DL_LIBS="-ldld"
- CC_SEARCH_FLAGS=""
- LD_SEARCH_FLAGS=""
-else
- echo "$ac_t""no" 1>&6
+ SHLIB_LD='${CC} -shared'
+ DL_OBJS=""
+ DL_LIBS="-ldl"
+ LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ if test "`uname -m`" = "alpha"; then
+ CFLAGS="$CFLAGS -mieee"
fi
- fi
- if test "`uname -m`" = "alpha" ; then
- CFLAGS="$CFLAGS -mieee"
- fi
;;
Lynx*)
SHLIB_CFLAGS="-fPIC"
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
CFLAGS_OPTIMIZE=-02
- SHLIB_LD="${CC} -shared "
+ SHLIB_LD='${CC} -shared'
DL_OBJS="tclLoadDl.o"
DL_LIBS="-mshared -ldl"
LD_FLAGS="-Wl,--export-dynamic"
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ if test $doRpath = yes; then
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+fi
+
;;
MP-RAS-02*)
SHLIB_CFLAGS="-K PIC"
- SHLIB_LD="cc -G"
+ SHLIB_LD='${CC} -G'
SHLIB_LD_LIBS=""
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
@@ -3269,7 +7489,7 @@ fi
;;
MP-RAS-*)
SHLIB_CFLAGS="-K PIC"
- SHLIB_LD="cc -G"
+ SHLIB_LD='${CC} -G'
SHLIB_LD_LIBS=""
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
@@ -3278,197 +7498,210 @@ fi
CC_SEARCH_FLAGS=""
LD_SEARCH_FLAGS=""
;;
- NetBSD-*|FreeBSD-[1-2].*)
- # Not available on all versions: check for include file.
- ac_safe=`echo "dlfcn.h" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for dlfcn.h""... $ac_c" 1>&6
-echo "configure:3286: checking for dlfcn.h" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 3291 "configure"
-#include "confdefs.h"
-#include <dlfcn.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3296: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
-
- # NetBSD/SPARC needs -fPIC, -fpic will not do.
- SHLIB_CFLAGS="-fPIC"
- SHLIB_LD="ld -Bshareable -x"
- SHLIB_LD_LIBS='${LIBS}'
- SHLIB_SUFFIX=".so"
- DL_OBJS="tclLoadDl.o"
- DL_LIBS=""
+ NetBSD-1.*|FreeBSD-[1-2].*)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD="ld -Bshareable -x"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ if test $doRpath = yes; then
+
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
- echo $ac_n "checking for ELF""... $ac_c" 1>&6
-echo "configure:3323: checking for ELF" >&5
-if eval "test \"`echo '$''{'tcl_cv_ld_elf'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+fi
+
+ echo "$as_me:$LINENO: checking for ELF" >&5
+echo $ECHO_N "checking for ELF... $ECHO_C" >&6
+if test "${tcl_cv_ld_elf+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 3329 "configure"
-#include "confdefs.h"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#ifdef __ELF__
yes
#endif
-
-EOF
+
+_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "yes" >/dev/null 2>&1; then
- rm -rf conftest*
+ $EGREP "yes" >/dev/null 2>&1; then
tcl_cv_ld_elf=yes
else
- rm -rf conftest*
tcl_cv_ld_elf=no
fi
rm -f conftest*
fi
+echo "$as_me:$LINENO: result: $tcl_cv_ld_elf" >&5
+echo "${ECHO_T}$tcl_cv_ld_elf" >&6
+ if test $tcl_cv_ld_elf = yes; then
+
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'
-echo "$ac_t""$tcl_cv_ld_elf" 1>&6
- if test $tcl_cv_ld_elf = yes; then
- SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so'
- else
- SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1.0'
- fi
-
else
- echo "$ac_t""no" 1>&6
- SHLIB_CFLAGS=""
- SHLIB_LD="echo tclLdAout $CC \{$SHLIB_CFLAGS\} | `pwd`/tclsh -r"
- SHLIB_LD_LIBS='${LIBS}'
- SHLIB_SUFFIX=".a"
- DL_OBJS="tclLoadAout.o"
- DL_LIBS=""
- CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a'
-
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
+
fi
- # FreeBSD doesn't handle version numbers with dots.
+ # Ancient FreeBSD doesn't handle version numbers with dots.
- UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a'
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
TCL_LIB_VERSIONS_OK=nodots
;;
OpenBSD-*)
- case `arch -s` in
+ arch=`arch -s`
+ case "$arch" in
m88k|vax)
- SHLIB_CFLAGS=""
- SHLIB_LD="echo tclLdAout $CC \{$SHLIB_CFLAGS\} | `pwd`/tclsh -r"
- SHLIB_LD_LIBS='${LIBS}'
- SHLIB_SUFFIX=".a"
- DL_OBJS="tclLoadAout.o"
- DL_LIBS=""
- LDFLAGS=""
- CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a'
+ # Equivalent using configure option --disable-load
+ # Step 4 will set the necessary variables
+ DL_OBJS=""
+ SHLIB_LD_LIBS=""
;;
*)
- # OpenBSD/SPARC[64] needs -fPIC, -fpic will not do.
- case `machine` in
- sparc|sparc64)
- SHLIB_CFLAGS="-fPIC";;
- *)
- SHLIB_CFLAGS="-fpic";;
- esac
- SHLIB_LD="${CC} -shared ${SHLIB_CFLAGS}"
- SHLIB_LD_LIBS='${LIBS}'
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS=""
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ if test $doRpath = yes; then
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+fi
+
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1.0'
- echo $ac_n "checking for ELF""... $ac_c" 1>&6
-echo "configure:3408: checking for ELF" >&5
-if eval "test \"`echo '$''{'tcl_cv_ld_elf'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
+ ;;
+ esac
+ case "$arch" in
+ m88k|vax)
+ CFLAGS_OPTIMIZE="-O1"
+ ;;
+ sh)
+ CFLAGS_OPTIMIZE="-O0"
+ ;;
+ *)
+ CFLAGS_OPTIMIZE="-O2"
+ ;;
+ esac
+ echo "$as_me:$LINENO: checking for ELF" >&5
+echo $ECHO_N "checking for ELF... $ECHO_C" >&6
+if test "${tcl_cv_ld_elf+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 3414 "configure"
-#include "confdefs.h"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#ifdef __ELF__
yes
#endif
-
-EOF
+
+_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "yes" >/dev/null 2>&1; then
- rm -rf conftest*
+ $EGREP "yes" >/dev/null 2>&1; then
tcl_cv_ld_elf=yes
else
- rm -rf conftest*
tcl_cv_ld_elf=no
fi
rm -f conftest*
fi
+echo "$as_me:$LINENO: result: $tcl_cv_ld_elf" >&5
+echo "${ECHO_T}$tcl_cv_ld_elf" >&6
+ if test $tcl_cv_ld_elf = yes; then
-echo "$ac_t""$tcl_cv_ld_elf" 1>&6
- if test $tcl_cv_ld_elf = yes; then
- LDFLAGS=-Wl,-export-dynamic
- else
- LDFLAGS=""
- fi
- ;;
- esac
+ LDFLAGS=-Wl,-export-dynamic
+
+else
+ LDFLAGS=""
+fi
+
+ if test "${TCL_THREADS}" = "1"; then
+
+ # On OpenBSD: Compile with -pthread
+ # Don't link with -lpthread
+ LIBS=`echo $LIBS | sed s/-lpthread//`
+ CFLAGS="$CFLAGS -pthread"
+
+fi
# OpenBSD doesn't do version numbers with dots.
- UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a'
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
TCL_LIB_VERSIONS_OK=nodots
;;
- FreeBSD-*)
+ NetBSD-*|FreeBSD-[3-4].*)
# FreeBSD 3.* and greater have ELF.
+ # NetBSD 2.* has ELF and can use 'cc -shared' to build shared libs
SHLIB_CFLAGS="-fPIC"
- SHLIB_LD="ld -Bshareable -x"
- SHLIB_LD_LIBS='${LIBS}'
+ SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS=""
LDFLAGS="$LDFLAGS -export-dynamic"
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
- if test "${TCL_THREADS}" = "1" ; then
+ if test $doRpath = yes; then
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+fi
+
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ if test "${TCL_THREADS}" = "1"; then
+
# The -pthread needs to go in the CFLAGS, not LIBS
LIBS=`echo $LIBS | sed s/-pthread//`
CFLAGS="$CFLAGS -pthread"
LDFLAGS="$LDFLAGS -pthread"
- fi
+
+fi
+
case $system in
FreeBSD-3.*)
# FreeBSD-3 doesn't handle version numbers with dots.
- UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a'
- SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so'
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'
TCL_LIB_VERSIONS_OK=nodots
;;
esac
;;
+ FreeBSD-*)
+ # This configuration from FreeBSD Ports.
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD="${CC} -shared"
+ TCL_SHLIB_LD_EXTRAS="-soname \$@"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ LDFLAGS=""
+ if test $doRpath = yes; then
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
+fi
+
+ if test "${TCL_THREADS}" = "1"; then
+
+ # The -pthread needs to go in the LDFLAGS, not LIBS
+ LIBS=`echo $LIBS | sed s/-pthread//`
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LDFLAGS="$LDFLAGS $PTHREAD_LIBS"
+fi
+
+ # Version numbers are dot-stripped by system policy.
+ TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .`
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1'
+ TCL_LIB_VERSIONS_OK=nodots
+ ;;
Darwin-*)
CFLAGS_OPTIMIZE="-Os"
SHLIB_CFLAGS="-fno-common"
@@ -3482,271 +7715,498 @@ echo "$ac_t""$tcl_cv_ld_elf" 1>&6
awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
if (!($i~/^(isysroot|mmacosx-version-min)/)) print "-"$i}'`"
if test $do64bit = yes; then
+
case `arch` in
ppc)
- echo $ac_n "checking if compiler accepts -arch ppc64 flag""... $ac_c" 1>&6
-echo "configure:3489: checking if compiler accepts -arch ppc64 flag" >&5
-if eval "test \"`echo '$''{'tcl_cv_cc_arch_ppc64'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking if compiler accepts -arch ppc64 flag" >&5
+echo $ECHO_N "checking if compiler accepts -arch ppc64 flag... $ECHO_C" >&6
+if test "${tcl_cv_cc_arch_ppc64+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
+
hold_cflags=$CFLAGS
CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
- cat > conftest.$ac_ext <<EOF
-#line 3497 "configure"
-#include "confdefs.h"
-
-int main() {
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
-; return 0; }
-EOF
-if { (eval echo configure:3504: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_cc_arch_ppc64=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_cc_arch_ppc64=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_cc_arch_ppc64=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
CFLAGS=$hold_cflags
fi
-
-echo "$ac_t""$tcl_cv_cc_arch_ppc64" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_cc_arch_ppc64" >&5
+echo "${ECHO_T}$tcl_cv_cc_arch_ppc64" >&6
if test $tcl_cv_cc_arch_ppc64 = yes; then
+
CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
do64bit_ok=yes
- fi;;
+
+fi
+;;
i386)
- echo $ac_n "checking if compiler accepts -arch x86_64 flag""... $ac_c" 1>&6
-echo "configure:3524: checking if compiler accepts -arch x86_64 flag" >&5
-if eval "test \"`echo '$''{'tcl_cv_cc_arch_x86_64'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking if compiler accepts -arch x86_64 flag" >&5
+echo $ECHO_N "checking if compiler accepts -arch x86_64 flag... $ECHO_C" >&6
+if test "${tcl_cv_cc_arch_x86_64+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
+
hold_cflags=$CFLAGS
CFLAGS="$CFLAGS -arch x86_64"
- cat > conftest.$ac_ext <<EOF
-#line 3532 "configure"
-#include "confdefs.h"
-
-int main() {
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
-; return 0; }
-EOF
-if { (eval echo configure:3539: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_cc_arch_x86_64=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_cc_arch_x86_64=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_cc_arch_x86_64=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
CFLAGS=$hold_cflags
fi
-
-echo "$ac_t""$tcl_cv_cc_arch_x86_64" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_cc_arch_x86_64" >&5
+echo "${ECHO_T}$tcl_cv_cc_arch_x86_64" >&6
if test $tcl_cv_cc_arch_x86_64 = yes; then
+
CFLAGS="$CFLAGS -arch x86_64"
do64bit_ok=yes
- fi;;
+
+fi
+;;
*)
- echo "configure: warning: Don't know how enable 64-bit on architecture `arch`" 1>&2;;
+ { echo "$as_me:$LINENO: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&5
+echo "$as_me: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&2;};;
esac
- else
+
+else
+
# Check for combined 32-bit and 64-bit fat build
- echo "$CFLAGS " | grep -E -q -- '-arch (ppc64|x86_64) ' && \
- echo "$CFLAGS " | grep -E -q -- '-arch (ppc|i386) ' && \
+ if echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \
+ && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '; then
+
fat_32_64=yes
- fi
+fi
+
+
+fi
+
SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS}'
- echo $ac_n "checking if ld accepts -single_module flag""... $ac_c" 1>&6
-echo "configure:3568: checking if ld accepts -single_module flag" >&5
-if eval "test \"`echo '$''{'tcl_cv_ld_single_module'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking if ld accepts -single_module flag" >&5
+echo $ECHO_N "checking if ld accepts -single_module flag... $ECHO_C" >&6
+if test "${tcl_cv_ld_single_module+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
+
hold_ldflags=$LDFLAGS
LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module"
- cat > conftest.$ac_ext <<EOF
-#line 3576 "configure"
-#include "confdefs.h"
-
-int main() {
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
int i;
-; return 0; }
-EOF
-if { (eval echo configure:3583: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_ld_single_module=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_ld_single_module=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_ld_single_module=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LDFLAGS=$hold_ldflags
fi
-
-echo "$ac_t""$tcl_cv_ld_single_module" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_ld_single_module" >&5
+echo "${ECHO_T}$tcl_cv_ld_single_module" >&6
if test $tcl_cv_ld_single_module = yes; then
+
SHLIB_LD="${SHLIB_LD} -Wl,-single_module"
- fi
- SHLIB_LD_LIBS='${LIBS}'
+
+fi
+
SHLIB_SUFFIX=".dylib"
DL_OBJS="tclLoadDyld.o"
DL_LIBS=""
# Don't use -prebind when building for Mac OS X 10.4 or later only:
- test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int($2)}'`" -lt 4 -a \
- "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int($2)}'`" -lt 4 && \
+ if test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int($2)}'`" -lt 4 -a \
+ "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int($2)}'`" -lt 4; then
+
LDFLAGS="$LDFLAGS -prebind"
+fi
+
LDFLAGS="$LDFLAGS -headerpad_max_install_names"
- echo $ac_n "checking if ld accepts -search_paths_first flag""... $ac_c" 1>&6
-echo "configure:3610: checking if ld accepts -search_paths_first flag" >&5
-if eval "test \"`echo '$''{'tcl_cv_ld_search_paths_first'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking if ld accepts -search_paths_first flag" >&5
+echo $ECHO_N "checking if ld accepts -search_paths_first flag... $ECHO_C" >&6
+if test "${tcl_cv_ld_search_paths_first+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
+
hold_ldflags=$LDFLAGS
LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
- cat > conftest.$ac_ext <<EOF
-#line 3618 "configure"
-#include "confdefs.h"
-
-int main() {
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
int i;
-; return 0; }
-EOF
-if { (eval echo configure:3625: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_ld_search_paths_first=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_ld_search_paths_first=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_ld_search_paths_first=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LDFLAGS=$hold_ldflags
fi
-
-echo "$ac_t""$tcl_cv_ld_search_paths_first" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_ld_search_paths_first" >&5
+echo "${ECHO_T}$tcl_cv_ld_search_paths_first" >&6
if test $tcl_cv_ld_search_paths_first = yes; then
+
LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
- fi
+
+fi
+
+ if test "$tcl_cv_cc_visibility_hidden" != yes; then
+
+
+cat >>confdefs.h <<\_ACEOF
+#define MODULE_SCOPE __private_extern__
+_ACEOF
+
+
+fi
+
CC_SEARCH_FLAGS=""
LD_SEARCH_FLAGS=""
LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH"
- PLAT_OBJS=\$\(MAC\_OSX_OBJS\)
- PLAT_SRCS=\$\(MAC\_OSX_SRCS\)
- echo $ac_n "checking whether to use CoreFoundation""... $ac_c" 1>&6
-echo "configure:3648: checking whether to use CoreFoundation" >&5
+
+cat >>confdefs.h <<\_ACEOF
+#define MAC_OSX_TCL 1
+_ACEOF
+
+ PLAT_OBJS='${MAC_OSX_OBJS}'
+ PLAT_SRCS='${MAC_OSX_SRCS}'
+ echo "$as_me:$LINENO: checking whether to use CoreFoundation" >&5
+echo $ECHO_N "checking whether to use CoreFoundation... $ECHO_C" >&6
# Check whether --enable-corefoundation or --disable-corefoundation was given.
if test "${enable_corefoundation+set}" = set; then
enableval="$enable_corefoundation"
tcl_corefoundation=$enableval
else
tcl_corefoundation=yes
-fi
-
- echo "$ac_t""$tcl_corefoundation" 1>&6
+fi;
+ echo "$as_me:$LINENO: result: $tcl_corefoundation" >&5
+echo "${ECHO_T}$tcl_corefoundation" >&6
if test $tcl_corefoundation = yes; then
- echo $ac_n "checking for CoreFoundation.framework""... $ac_c" 1>&6
-echo "configure:3660: checking for CoreFoundation.framework" >&5
-if eval "test \"`echo '$''{'tcl_cv_lib_corefoundation'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+
+ echo "$as_me:$LINENO: checking for CoreFoundation.framework" >&5
+echo $ECHO_N "checking for CoreFoundation.framework... $ECHO_C" >&6
+if test "${tcl_cv_lib_corefoundation+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
+
hold_libs=$LIBS
- if test "$fat_32_64" = yes; then for v in CFLAGS CPPFLAGS LDFLAGS; do
- # On Tiger there is no 64-bit CF, so remove 64-bit archs
- # from CFLAGS et al. while testing for presence of CF.
- # 64-bit CF is disabled in tclUnixPort.h if necessary.
- eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"'
- done; fi
+ if test "$fat_32_64" = yes; then
+
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ # On Tiger there is no 64-bit CF, so remove 64-bit
+ # archs from CFLAGS et al. while testing for
+ # presence of CF. 64-bit CF is disabled in
+ # tclUnixPort.h if necessary.
+ eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"'
+ done
+fi
+
LIBS="$LIBS -framework CoreFoundation"
- cat > conftest.$ac_ext <<EOF
-#line 3674 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <CoreFoundation/CoreFoundation.h>
-int main() {
+int
+main ()
+{
CFBundleRef b = CFBundleGetMainBundle();
-; return 0; }
-EOF
-if { (eval echo configure:3681: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_lib_corefoundation=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_lib_corefoundation=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_lib_corefoundation=no
fi
-rm -f conftest*
- if test "$fat_32_64" = yes; then for v in CFLAGS CPPFLAGS LDFLAGS; do
- eval $v'="$hold_'$v'"'
- done; fi; LIBS=$hold_libs
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ if test "$fat_32_64" = yes; then
+
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval $v'="$hold_'$v'"'
+ done
fi
-echo "$ac_t""$tcl_cv_lib_corefoundation" 1>&6
+ LIBS=$hold_libs
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_lib_corefoundation" >&5
+echo "${ECHO_T}$tcl_cv_lib_corefoundation" >&6
if test $tcl_cv_lib_corefoundation = yes; then
+
LIBS="$LIBS -framework CoreFoundation"
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_COREFOUNDATION 1
-EOF
+_ACEOF
+
+
+else
+ tcl_corefoundation=no
+fi
- else
- tcl_corefoundation=no
- fi
if test "$fat_32_64" = yes -a $tcl_corefoundation = yes; then
- echo $ac_n "checking for 64-bit CoreFoundation""... $ac_c" 1>&6
-echo "configure:3708: checking for 64-bit CoreFoundation" >&5
-if eval "test \"`echo '$''{'tcl_cv_lib_corefoundation_64'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+
+ echo "$as_me:$LINENO: checking for 64-bit CoreFoundation" >&5
+echo $ECHO_N "checking for 64-bit CoreFoundation... $ECHO_C" >&6
+if test "${tcl_cv_lib_corefoundation_64+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
+
for v in CFLAGS CPPFLAGS LDFLAGS; do
eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
done
- cat > conftest.$ac_ext <<EOF
-#line 3717 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <CoreFoundation/CoreFoundation.h>
-int main() {
+int
+main ()
+{
CFBundleRef b = CFBundleGetMainBundle();
-; return 0; }
-EOF
-if { (eval echo configure:3724: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_lib_corefoundation_64=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_lib_corefoundation_64=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_lib_corefoundation_64=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
for v in CFLAGS CPPFLAGS LDFLAGS; do
eval $v'="$hold_'$v'"'
done
fi
-
-echo "$ac_t""$tcl_cv_lib_corefoundation_64" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_lib_corefoundation_64" >&5
+echo "${ECHO_T}$tcl_cv_lib_corefoundation_64" >&6
if test $tcl_cv_lib_corefoundation_64 = no; then
- cat >> confdefs.h <<\EOF
+
+
+cat >>confdefs.h <<\_ACEOF
#define NO_COREFOUNDATION_64 1
-EOF
+_ACEOF
- fi
- fi
- fi
- cat >> confdefs.h <<\EOF
-#define MAC_OSX_TCL 1
-EOF
+ LDFLAGS="$LDFLAGS -Wl,-no_arch_warnings"
+
+fi
+
+
+fi
+
+
+fi
;;
NEXTSTEP-*)
@@ -3760,10 +8220,12 @@ EOF
LD_SEARCH_FLAGS=""
;;
OS/390-*)
+ SHLIB_LD_LIBS=""
CFLAGS_OPTIMIZE="" # Optimizer is buggy
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define _OE_SOCKETS 1
-EOF
+_ACEOF
;;
OSF1-1.0|OSF1-1.1|OSF1-1.2)
@@ -3781,11 +8243,14 @@ EOF
OSF1-1.*)
# OSF/1 1.3 from OSF using ELF, and derivatives, including AD2
SHLIB_CFLAGS="-fPIC"
- if test "$SHARED_BUILD" = "1" ; then
- SHLIB_LD="ld -shared"
- else
+ if test "$SHARED_BUILD" = 1; then
+ SHLIB_LD="ld -shared"
+else
+
SHLIB_LD="ld -non_shared"
- fi
+
+fi
+
SHLIB_LD_LIBS=""
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
@@ -3796,34 +8261,51 @@ EOF
OSF1-V*)
# Digital OSF/1
SHLIB_CFLAGS=""
- if test "$SHARED_BUILD" = "1" ; then
+ if test "$SHARED_BUILD" = 1; then
+
SHLIB_LD='ld -shared -expect_unresolved "*"'
- else
+
+else
+
SHLIB_LD='ld -non_shared -expect_unresolved "*"'
- fi
- SHLIB_LD_LIBS='${LIBS}'
+
+fi
+
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS=""
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
- if test "$GCC" = "yes" ; then
- CFLAGS="$CFLAGS -mieee"
- else
+ if test $doRpath = yes; then
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
+fi
+
+ if test "$GCC" = yes; then
+ CFLAGS="$CFLAGS -mieee"
+else
+
CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"
- fi
+fi
+
# see pthread_intro(3) for pthread support on osf1, k.furukawa
- if test "${TCL_THREADS}" = "1" ; then
+ if test "${TCL_THREADS}" = 1; then
+
CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE"
CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64"
LIBS=`echo $LIBS | sed s/-lpthreads//`
- if test "$GCC" = "yes" ; then
+ if test "$GCC" = yes; then
+
LIBS="$LIBS -lpthread -lmach -lexc"
- else
+
+else
+
CFLAGS="$CFLAGS -pthread"
LDFLAGS="$LDFLAGS -pthread"
- fi
- fi
+
+fi
+
+
+fi
;;
QNX-6*)
@@ -3839,28 +8321,22 @@ EOF
CC_SEARCH_FLAGS=""
LD_SEARCH_FLAGS=""
;;
- RISCos-*)
- SHLIB_CFLAGS="-G 0"
- SHLIB_LD="echo tclLdAout $CC \{$SHLIB_CFLAGS\} | `pwd`/tclsh -r -G 0"
- SHLIB_LD_LIBS='${LIBS}'
- SHLIB_SUFFIX=".a"
- DL_OBJS="tclLoadAout.o"
- DL_LIBS=""
- LDFLAGS="$LDFLAGS -Wl,-D,08000000"
- CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- ;;
SCO_SV-3.2*)
# Note, dlopen is available only on SCO 3.2.5 and greater. However,
# this test works, since "uname -s" was non-standard in 3.2.4 and
# below.
- if test "$GCC" = "yes" ; then
+ if test "$GCC" = yes; then
+
SHLIB_CFLAGS="-fPIC -melf"
LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"
- else
+
+else
+
SHLIB_CFLAGS="-Kpic -belf"
LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"
- fi
+
+fi
+
SHLIB_LD="ld -G"
SHLIB_LD_LIBS=""
SHLIB_SUFFIX=".so"
@@ -3894,8 +8370,8 @@ EOF
# requires an extra version number at the end of .so file names.
# So, the library has to have a name like libtcl75.so.1.0
- SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1.0'
- UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a'
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
TCL_LIB_VERSIONS_OK=nodots
;;
SunOS-5.[0-6])
@@ -3904,85 +8380,114 @@ EOF
# Note: If _REENTRANT isn't defined, then Solaris
# won't define thread-safe library routines.
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define _REENTRANT 1
-EOF
+_ACEOF
+
- cat >> confdefs.h <<\EOF
+cat >>confdefs.h <<\_ACEOF
#define _POSIX_PTHREAD_SEMANTICS 1
-EOF
+_ACEOF
SHLIB_CFLAGS="-KPIC"
-
- # Note: need the LIBS below, otherwise Tk won't find Tcl's
- # symbols when dynamically loaded into tclsh.
-
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS="-ldl"
- if test "$GCC" = "yes" ; then
+ if test "$GCC" = yes; then
+
SHLIB_LD='${CC} -shared'
CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- else
+
+else
+
SHLIB_LD="/usr/ccs/bin/ld -G -z text"
CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- fi
+
+fi
+
;;
SunOS-5*)
# Note: If _REENTRANT isn't defined, then Solaris
# won't define thread-safe library routines.
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define _REENTRANT 1
-EOF
+_ACEOF
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define _POSIX_PTHREAD_SEMANTICS 1
-EOF
+_ACEOF
SHLIB_CFLAGS="-KPIC"
# Check to enable 64-bit flags for compiler/linker
- if test "$do64bit" = "yes" ; then
+ if test "$do64bit" = yes; then
+
arch=`isainfo`
- if test "$arch" = "sparcv9 sparc" ; then
- if test "$GCC" = "yes" ; then
- if test "`gcc -dumpversion | awk -F. '{print $1}'`" -lt "3" ; then
- echo "configure: warning: 64bit mode not supported with GCC < 3.2 on $system" 1>&2
- else
- do64bit_ok=yes
- CFLAGS="$CFLAGS -m64 -mcpu=v9"
- LDFLAGS="$LDFLAGS -m64 -mcpu=v9"
- SHLIB_CFLAGS="-fPIC"
- fi
- else
+ if test "$arch" = "sparcv9 sparc"; then
+
+ if test "$GCC" = yes; then
+
+ if test "`${CC} -dumpversion | awk -F. '{print $1}'`" -lt 3; then
+
+ { echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&5
+echo "$as_me: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&2;}
+
+else
+
do64bit_ok=yes
- if test "$do64bitVIS" = "yes" ; then
- CFLAGS="$CFLAGS -xarch=v9a"
- LDFLAGS="$LDFLAGS -xarch=v9a"
- else
- CFLAGS="$CFLAGS -xarch=v9"
- LDFLAGS="$LDFLAGS -xarch=v9"
- fi
- # Solaris 64 uses this as well
- #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64"
- fi
- elif test "$arch" = "amd64 i386" ; then
- if test "$GCC" = "yes" ; then
+ CFLAGS="$CFLAGS -m64 -mcpu=v9"
+ LDFLAGS="$LDFLAGS -m64 -mcpu=v9"
+ SHLIB_CFLAGS="-fPIC"
+
+fi
+
+
+else
+
+ do64bit_ok=yes
+ if test "$do64bitVIS" = yes; then
+
+ CFLAGS="$CFLAGS -xarch=v9a"
+ LDFLAGS_ARCH="-xarch=v9a"
+
+else
+
+ CFLAGS="$CFLAGS -xarch=v9"
+ LDFLAGS_ARCH="-xarch=v9"
+
+fi
+
+ # Solaris 64 uses this as well
+ #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64"
+
+fi
+
+
+else
+ if test "$arch" = "amd64 i386"; then
+
+ if test "$GCC" = yes; then
+
case $system in
SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*)
do64bit_ok=yes
CFLAGS="$CFLAGS -m64"
LDFLAGS="$LDFLAGS -m64";;
*)
- echo "configure: warning: 64bit mode not supported with GCC on $system" 1>&2;;
+ { echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC on $system" >&5
+echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;};;
esac
- else
+
+else
+
do64bit_ok=yes
case $system in
SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*)
@@ -3992,25 +8497,201 @@ EOF
CFLAGS="$CFLAGS -xarch=amd64"
LDFLAGS="$LDFLAGS -xarch=amd64";;
esac
- fi
- else
- echo "configure: warning: 64bit mode not supported for $arch" 1>&2
- fi
- fi
- # Note: need the LIBS below, otherwise Tk won't find Tcl's
- # symbols when dynamically loaded into tclsh.
+fi
+
+
+else
+ { echo "$as_me:$LINENO: WARNING: 64bit mode not supported for $arch" >&5
+echo "$as_me: WARNING: 64bit mode not supported for $arch" >&2;}
+fi
+
+fi
+
+
+fi
+
+
+ #--------------------------------------------------------------------
+ # On Solaris 5.x i386 with the sunpro compiler we need to link
+ # with sunmath to get floating point rounding control
+ #--------------------------------------------------------------------
+ if test "$GCC" = yes; then
+ use_sunmath=no
+else
+
+ arch=`isainfo`
+ echo "$as_me:$LINENO: checking whether to use -lsunmath for fp rounding control" >&5
+echo $ECHO_N "checking whether to use -lsunmath for fp rounding control... $ECHO_C" >&6
+ if test "$arch" = "amd64 i386"; then
+
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ MATH_LIBS="-lsunmath $MATH_LIBS"
+ if test "${ac_cv_header_sunmath_h+set}" = set; then
+ echo "$as_me:$LINENO: checking for sunmath.h" >&5
+echo $ECHO_N "checking for sunmath.h... $ECHO_C" >&6
+if test "${ac_cv_header_sunmath_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_sunmath_h" >&5
+echo "${ECHO_T}$ac_cv_header_sunmath_h" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking sunmath.h usability" >&5
+echo $ECHO_N "checking sunmath.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <sunmath.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking sunmath.h presence" >&5
+echo $ECHO_N "checking sunmath.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sunmath.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: sunmath.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: sunmath.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sunmath.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: sunmath.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: sunmath.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: sunmath.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sunmath.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: sunmath.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sunmath.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: sunmath.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sunmath.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: sunmath.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sunmath.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: sunmath.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sunmath.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: sunmath.h: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to the tcl lists. ##
+## ------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for sunmath.h" >&5
+echo $ECHO_N "checking for sunmath.h... $ECHO_C" >&6
+if test "${ac_cv_header_sunmath_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_sunmath_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_sunmath_h" >&5
+echo "${ECHO_T}$ac_cv_header_sunmath_h" >&6
+
+fi
+
+
+ use_sunmath=yes
+
+else
+
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ use_sunmath=no
+
+fi
+
+
+fi
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS="-ldl"
- if test "$GCC" = "yes" ; then
- SHLIB_LD="$CC -shared"
+ if test "$GCC" = yes; then
+
+ SHLIB_LD='${CC} -shared'
CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- if test "$do64bit_ok" = "yes" ; then
- if test "$arch" = "sparcv9 sparc" ; then
+ if test "$do64bit_ok" = yes; then
+
+ if test "$arch" = "sparcv9 sparc"; then
+
# We need to specify -static-libgcc or we need to
# add the path to the sparv9 libgcc.
SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc"
@@ -4018,248 +8699,140 @@ EOF
# path, remove so name and append 'sparcv9'
#v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..."
#CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir"
- elif test "$arch" = "amd64 i386" ; then
+
+else
+ if test "$arch" = "amd64 i386"; then
+
SHLIB_LD="$SHLIB_LD -m64 -static-libgcc"
- fi
- fi
- else
+
+fi
+
+fi
+
+
+fi
+
+
+else
+
+ if test "$use_sunmath" = yes; then
+ textmode=textoff
+else
+ textmode=text
+fi
+
case $system in
SunOS-5.[1-9][0-9]*)
- SHLIB_LD='${CC} -G -z text ${LDFLAGS}';;
+ SHLIB_LD="\${CC} -G -z $textmode \${LDFLAGS}";;
*)
- SHLIB_LD="/usr/ccs/bin/ld -G -z text";;
+ SHLIB_LD="/usr/ccs/bin/ld -G -z $textmode";;
esac
CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
- fi
- ;;
- ULTRIX-4.*)
- SHLIB_CFLAGS="-G 0"
- SHLIB_SUFFIX=".a"
- SHLIB_LD="echo tclLdAout $CC \{$SHLIB_CFLAGS\} | `pwd`/tclsh -r -G 0"
- SHLIB_LD_LIBS='${LIBS}'
- DL_OBJS="tclLoadAout.o"
- DL_LIBS=""
- LDFLAGS="$LDFLAGS -Wl,-D,08000000"
- CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- if test "$GCC" != "yes" ; then
- CFLAGS="$CFLAGS -DHAVE_TZSET -std1"
- fi
+
+fi
+
;;
UNIX_SV* | UnixWare-5*)
SHLIB_CFLAGS="-KPIC"
- SHLIB_LD="cc -G"
+ SHLIB_LD='${CC} -G'
SHLIB_LD_LIBS=""
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS="-ldl"
# Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers
# that don't grok the -Bexport option. Test that it does.
- echo $ac_n "checking for ld accepts -Bexport flag""... $ac_c" 1>&6
-echo "configure:4061: checking for ld accepts -Bexport flag" >&5
-if eval "test \"`echo '$''{'tcl_cv_ld_Bexport'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for ld accepts -Bexport flag" >&5
+echo $ECHO_N "checking for ld accepts -Bexport flag... $ECHO_C" >&6
+if test "${tcl_cv_ld_Bexport+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
+
hold_ldflags=$LDFLAGS
LDFLAGS="$LDFLAGS -Wl,-Bexport"
- cat > conftest.$ac_ext <<EOF
-#line 4069 "configure"
-#include "confdefs.h"
-
-int main() {
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
int i;
-; return 0; }
-EOF
-if { (eval echo configure:4076: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_ld_Bexport=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_ld_Bexport=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_ld_Bexport=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
LDFLAGS=$hold_ldflags
fi
-
-echo "$ac_t""$tcl_cv_ld_Bexport" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_ld_Bexport" >&5
+echo "${ECHO_T}$tcl_cv_ld_Bexport" >&6
if test $tcl_cv_ld_Bexport = yes; then
+
LDFLAGS="$LDFLAGS -Wl,-Bexport"
- fi
+
+fi
+
CC_SEARCH_FLAGS=""
LD_SEARCH_FLAGS=""
;;
esac
- if test "$do64bit" = "yes" -a "$do64bit_ok" = "no" ; then
- echo "configure: warning: 64bit support being disabled -- don't know magic for this platform" 1>&2
- fi
+ if test "$do64bit" = yes -a "$do64bit_ok" = no; then
-
-
-
- # Step 4: If pseudo-static linking is in use (see K. B. Kenny, "Dynamic
- # Loading for Tcl -- What Became of It?". Proc. 2nd Tcl/Tk Workshop,
- # New Orleans, LA, Computerized Processes Unlimited, 1994), then we need
- # to determine which of several header files defines the a.out file
- # format (a.out.h, sys/exec.h, or sys/exec_aout.h). At present, we
- # support only a file format that is more or less version-7-compatible.
- # In particular,
- # - a.out files must begin with `struct exec'.
- # - the N_TXTOFF on the `struct exec' must compute the seek address
- # of the text segment
- # - The `struct exec' must contain a_magic, a_text, a_data, a_bss
- # and a_entry fields.
- # The following compilation should succeed if and only if either sys/exec.h
- # or a.out.h is usable for the purpose.
- #
- # Note that the modified COFF format used on MIPS Ultrix 4.x is usable; the
- # `struct exec' includes a second header that contains information that
- # duplicates the v7 fields that are needed.
-
- if test "x$DL_OBJS" = "xtclLoadAout.o" ; then
- echo $ac_n "checking sys/exec.h""... $ac_c" 1>&6
-echo "configure:4126: checking sys/exec.h" >&5
-if eval "test \"`echo '$''{'tcl_cv_sysexec_h'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
-
- cat > conftest.$ac_ext <<EOF
-#line 4132 "configure"
-#include "confdefs.h"
-#include <sys/exec.h>
-int main() {
+ { echo "$as_me:$LINENO: WARNING: 64bit support being disabled -- don't know magic for this platform" >&5
+echo "$as_me: WARNING: 64bit support being disabled -- don't know magic for this platform" >&2;}
- struct exec foo;
- unsigned long seek;
- int flag;
-#if defined(__mips) || defined(mips)
- seek = N_TXTOFF (foo.ex_f, foo.ex_o);
-#else
- seek = N_TXTOFF (foo);
-#endif
- flag = (foo.a_magic == OMAGIC);
- return foo.a_text + foo.a_data + foo.a_bss + foo.a_entry;
-
-; return 0; }
-EOF
-if { (eval echo configure:4150: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- tcl_cv_sysexec_h=usable
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_sysexec_h=unusable
-fi
-rm -f conftest*
fi
-echo "$ac_t""$tcl_cv_sysexec_h" 1>&6
- if test $tcl_cv_sysexec_h = usable; then
- cat >> confdefs.h <<\EOF
-#define USE_SYS_EXEC_H 1
-EOF
- else
- echo $ac_n "checking a.out.h""... $ac_c" 1>&6
-echo "configure:4170: checking a.out.h" >&5
-if eval "test \"`echo '$''{'tcl_cv_aout_h'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
-
- cat > conftest.$ac_ext <<EOF
-#line 4176 "configure"
-#include "confdefs.h"
-#include <a.out.h>
-int main() {
+ if test "$do64bit" = yes -a "$do64bit_ok" = yes; then
- struct exec foo;
- unsigned long seek;
- int flag;
-#if defined(__mips) || defined(mips)
- seek = N_TXTOFF (foo.ex_f, foo.ex_o);
-#else
- seek = N_TXTOFF (foo);
-#endif
- flag = (foo.a_magic == OMAGIC);
- return foo.a_text + foo.a_data + foo.a_bss + foo.a_entry;
-
-; return 0; }
-EOF
-if { (eval echo configure:4194: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- tcl_cv_aout_h=usable
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_aout_h=unusable
-fi
-rm -f conftest*
-fi
-echo "$ac_t""$tcl_cv_aout_h" 1>&6
- if test $tcl_cv_aout_h = usable; then
- cat >> confdefs.h <<\EOF
-#define USE_A_OUT_H 1
-EOF
+cat >>confdefs.h <<\_ACEOF
+#define TCL_CFG_DO64BIT 1
+_ACEOF
- else
- echo $ac_n "checking sys/exec_aout.h""... $ac_c" 1>&6
-echo "configure:4214: checking sys/exec_aout.h" >&5
-if eval "test \"`echo '$''{'tcl_cv_sysexecaout_h'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
-
- cat > conftest.$ac_ext <<EOF
-#line 4220 "configure"
-#include "confdefs.h"
-#include <sys/exec_aout.h>
-int main() {
- struct exec foo;
- unsigned long seek;
- int flag;
-#if defined(__mips) || defined(mips)
- seek = N_TXTOFF (foo.ex_f, foo.ex_o);
-#else
- seek = N_TXTOFF (foo);
-#endif
- flag = (foo.a_midmag == OMAGIC);
- return foo.a_text + foo.a_data + foo.a_bss + foo.a_entry;
-
-; return 0; }
-EOF
-if { (eval echo configure:4238: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- tcl_cv_sysexecaout_h=usable
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_sysexecaout_h=unusable
-fi
-rm -f conftest*
fi
-echo "$ac_t""$tcl_cv_sysexecaout_h" 1>&6
- if test $tcl_cv_sysexecaout_h = usable; then
- cat >> confdefs.h <<\EOF
-#define USE_SYS_EXEC_AOUT_H 1
-EOF
- else
- DL_OBJS=""
- fi
- fi
- fi
- fi
- # Step 5: disable dynamic loading if requested via a command-line switch.
+
+ # Step 4: disable dynamic loading if requested via a command-line switch.
# Check whether --enable-load or --disable-load was given.
if test "${enable_load+set}" = set; then
@@ -4267,17 +8840,18 @@ if test "${enable_load+set}" = set; then
tcl_ok=$enableval
else
tcl_ok=yes
+fi;
+ if test "$tcl_ok" = no; then
+ DL_OBJS=""
fi
- if test "$tcl_ok" = "no"; then
- DL_OBJS=""
- fi
- if test "x$DL_OBJS" != "x" ; then
- BUILD_DLTEST="\$(DLTEST_TARGETS)"
- else
- echo "Can't figure out how to do dynamic loading or shared libraries"
- echo "on this system."
+ if test "x$DL_OBJS" != x; then
+ BUILD_DLTEST="\$(DLTEST_TARGETS)"
+else
+
+ { echo "$as_me:$LINENO: WARNING: Can't figure out how to do dynamic loading or shared libraries on this system." >&5
+echo "$as_me: WARNING: Can't figure out how to do dynamic loading or shared libraries on this system." >&2;}
SHLIB_CFLAGS=""
SHLIB_LD=""
SHLIB_SUFFIX=""
@@ -4287,552 +8861,964 @@ fi
CC_SEARCH_FLAGS=""
LD_SEARCH_FLAGS=""
BUILD_DLTEST=""
- fi
+
+fi
+
+ LDFLAGS="$LDFLAGS $LDFLAGS_ARCH"
# If we're running gcc, then change the C flags for compiling shared
# libraries to the right flags for gcc, instead of those for the
# standard manufacturer compiler.
- if test "$DL_OBJS" != "tclLoadNone.o" ; then
- if test "$GCC" = "yes" ; then
- case $system in
- AIX-*)
- ;;
- BSD/OS*)
- ;;
- IRIX*)
- ;;
- NetBSD-*|FreeBSD-*|OpenBSD-*)
- ;;
- Darwin-*)
- ;;
- RISCos-*)
- ;;
- SCO_SV-3.2*)
- ;;
- ULTRIX-4.*)
- ;;
- *)
- SHLIB_CFLAGS="-fPIC"
- ;;
- esac
- fi
- fi
+ if test "$DL_OBJS" != "tclLoadNone.o" -a "$GCC" = yes; then
+
+ case $system in
+ AIX-*) ;;
+ BSD/OS*) ;;
+ CYGWIN_*) ;;
+ IRIX*) ;;
+ NetBSD-*|FreeBSD-*|OpenBSD-*) ;;
+ Darwin-*) ;;
+ SCO_SV-3.2*) ;;
+ *) SHLIB_CFLAGS="-fPIC" ;;
+ esac
+fi
- if test "$SHARED_LIB_SUFFIX" = "" ; then
- SHARED_LIB_SUFFIX='${VERSION}\$\{DBGX\}${SHLIB_SUFFIX}'
- fi
- if test "$UNSHARED_LIB_SUFFIX" = "" ; then
- UNSHARED_LIB_SUFFIX='${VERSION}\$\{DBGX\}.a'
- fi
- if test "${SHARED_BUILD}" = "1" && test "${SHLIB_SUFFIX}" != "" ; then
+ if test "$SHARED_LIB_SUFFIX" = ""; then
+
+ SHARED_LIB_SUFFIX='${VERSION}${SHLIB_SUFFIX}'
+fi
+
+ if test "$UNSHARED_LIB_SUFFIX" = ""; then
+
+ UNSHARED_LIB_SUFFIX='${VERSION}.a'
+fi
+
+
+ if test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""; then
+
LIB_SUFFIX=${SHARED_LIB_SUFFIX}
MAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'
- INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) $(LIB_INSTALL_DIR)/$(LIB_FILE)'
- else
+ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)"/$(LIB_FILE)'
+
+else
+
LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}
- if test "$RANLIB" = "" ; then
+ if test "$RANLIB" = ""; then
+
MAKE_LIB='$(STLIB_LD) $@ ${OBJS}'
- INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) $(LIB_INSTALL_DIR)/$(LIB_FILE)'
- else
+ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)"/$(LIB_FILE)'
+
+else
+
MAKE_LIB='${STLIB_LD} $@ ${OBJS} ; ${RANLIB} $@'
- INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) $(LIB_INSTALL_DIR)/$(LIB_FILE) ; (cd $(LIB_INSTALL_DIR) ; $(RANLIB) $(LIB_FILE))'
- fi
+ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)"/$(LIB_FILE) ; (cd "$(LIB_INSTALL_DIR)" ; $(RANLIB) $(LIB_FILE))'
- fi
+fi
+
+
+fi
# Stub lib does not depend on shared/static configuration
- if test "$RANLIB" = "" ; then
+ if test "$RANLIB" = ""; then
+
MAKE_STUB_LIB='${STLIB_LD} $@ ${STUB_LIB_OBJS}'
- INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) $(LIB_INSTALL_DIR)/$(STUB_LIB_FILE)'
- else
+ INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) "$(LIB_INSTALL_DIR)/$(STUB_LIB_FILE)"'
+
+else
+
MAKE_STUB_LIB='${STLIB_LD} $@ ${STUB_LIB_OBJS} ; ${RANLIB} $@'
- INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) $(LIB_INSTALL_DIR)/$(STUB_LIB_FILE) ; (cd $(LIB_INSTALL_DIR) ; $(RANLIB) $(STUB_LIB_FILE))'
- fi
+ INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) "$(LIB_INSTALL_DIR)"/$(STUB_LIB_FILE) ; (cd "$(LIB_INSTALL_DIR)" ; $(RANLIB) $(STUB_LIB_FILE))'
+fi
-
-
-
-
-
-
-
-
+ # Define TCL_LIBS now that we know what DL_LIBS is.
+ # The trick here is that we don't want to change the value of TCL_LIBS if
+ # it is already set when tclConfig.sh had been loaded by Tk.
+ if test "x${TCL_LIBS}" = x; then
+
+ TCL_LIBS="${DL_LIBS} ${LIBS} ${MATH_LIBS}"
+fi
+
-
-
-
-
-
-
-
-
-
-
-
-
+ # FIXME: This subst was left in only because the TCL_DL_LIBS
+ # entry in tclConfig.sh uses it. It is not clear why someone
+ # would use TCL_DL_LIBS instead of TCL_LIBS.
-
-
-
-
-
- echo $ac_n "checking for build with symbols""... $ac_c" 1>&6
-echo "configure:4391: checking for build with symbols" >&5
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define TCL_SHLIB_EXT "${SHLIB_SUFFIX}"
+_ACEOF
+
+
+
+
+
+
+
+
+
+
+ echo "$as_me:$LINENO: checking for build with symbols" >&5
+echo $ECHO_N "checking for build with symbols... $ECHO_C" >&6
# Check whether --enable-symbols or --disable-symbols was given.
if test "${enable_symbols+set}" = set; then
enableval="$enable_symbols"
tcl_ok=$enableval
else
tcl_ok=no
-fi
-
+fi;
# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT.
+ DBGX=""
if test "$tcl_ok" = "no"; then
CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'
LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'
- DBGX=""
- echo "$ac_t""no" 1>&6
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+
+cat >>confdefs.h <<\_ACEOF
+#define TCL_CFG_OPTIMIZED 1
+_ACEOF
+
else
CFLAGS_DEFAULT='$(CFLAGS_DEBUG)'
LDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)'
- DBGX=g
if test "$tcl_ok" = "yes"; then
- echo "$ac_t""yes (standard debugging)" 1>&6
+ echo "$as_me:$LINENO: result: yes (standard debugging)" >&5
+echo "${ECHO_T}yes (standard debugging)" >&6
fi
fi
-
-
+
+
+ ### FIXME: Surely TCL_CFG_DEBUG should be set to whether we're debugging?
+
+cat >>confdefs.h <<\_ACEOF
+#define TCL_CFG_DEBUG 1
+_ACEOF
+
if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define TCL_MEM_DEBUG 1
-EOF
+_ACEOF
fi
- if test "$tcl_ok" = "compile" -o "$tcl_ok" = "all"; then
- cat >> confdefs.h <<\EOF
+ if test "$tcl_ok" = "compile" -o "$tcl_ok" = "all"; then
+
+cat >>confdefs.h <<\_ACEOF
#define TCL_COMPILE_DEBUG 1
-EOF
+_ACEOF
+
- cat >> confdefs.h <<\EOF
+cat >>confdefs.h <<\_ACEOF
#define TCL_COMPILE_STATS 1
-EOF
+_ACEOF
- fi
+ fi
if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then
if test "$tcl_ok" = "all"; then
- echo "$ac_t""enabled symbols mem compile debugging" 1>&6
+ echo "$as_me:$LINENO: result: enabled symbols mem compile debugging" >&5
+echo "${ECHO_T}enabled symbols mem compile debugging" >&6
else
- echo "$ac_t""enabled $tcl_ok debugging" 1>&6
+ echo "$as_me:$LINENO: result: enabled $tcl_ok debugging" >&5
+echo "${ECHO_T}enabled $tcl_ok debugging" >&6
fi
fi
-TCL_DBGX=${DBGX}
+
+cat >>confdefs.h <<\_ACEOF
+#define TCL_TOMMATH 1
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define MP_PREC 4
+_ACEOF
+
#--------------------------------------------------------------------
# Detect what compiler flags to set for 64-bit support.
#--------------------------------------------------------------------
- echo $ac_n "checking for required early compiler flags""... $ac_c" 1>&6
-echo "configure:4452: checking for required early compiler flags" >&5
+ echo "$as_me:$LINENO: checking for required early compiler flags" >&5
+echo $ECHO_N "checking for required early compiler flags... $ECHO_C" >&6
tcl_flags=""
-
- if eval "test \"`echo '$''{'tcl_cv_flag__isoc99_source'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+
+ if test "${tcl_cv_flag__isoc99_source+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 4459 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <stdlib.h>
-int main() {
+int
+main ()
+{
char *p = (char *)strtoll; char *q = (char *)strtoull;
-; return 0; }
-EOF
-if { (eval echo configure:4466: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_flag__isoc99_source=no
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- cat > conftest.$ac_ext <<EOF
-#line 4474 "configure"
-#include "confdefs.h"
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#define _ISOC99_SOURCE 1
#include <stdlib.h>
-int main() {
+int
+main ()
+{
char *p = (char *)strtoll; char *q = (char *)strtoull;
-; return 0; }
-EOF
-if { (eval echo configure:4482: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_flag__isoc99_source=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_flag__isoc99_source=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_flag__isoc99_source=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
if test "x${tcl_cv_flag__isoc99_source}" = "xyes" ; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define _ISOC99_SOURCE 1
-EOF
+_ACEOF
tcl_flags="$tcl_flags _ISOC99_SOURCE"
fi
-
- if eval "test \"`echo '$''{'tcl_cv_flag__largefile64_source'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+
+ if test "${tcl_cv_flag__largefile64_source+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 4509 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/stat.h>
-int main() {
+int
+main ()
+{
struct stat64 buf; int i = stat64("/", &buf);
-; return 0; }
-EOF
-if { (eval echo configure:4516: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_flag__largefile64_source=no
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- cat > conftest.$ac_ext <<EOF
-#line 4524 "configure"
-#include "confdefs.h"
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#define _LARGEFILE64_SOURCE 1
#include <sys/stat.h>
-int main() {
+int
+main ()
+{
struct stat64 buf; int i = stat64("/", &buf);
-; return 0; }
-EOF
-if { (eval echo configure:4532: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_flag__largefile64_source=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_flag__largefile64_source=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_flag__largefile64_source=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
if test "x${tcl_cv_flag__largefile64_source}" = "xyes" ; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define _LARGEFILE64_SOURCE 1
-EOF
+_ACEOF
tcl_flags="$tcl_flags _LARGEFILE64_SOURCE"
fi
-
- if eval "test \"`echo '$''{'tcl_cv_flag__largefile_source64'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+
+ if test "${tcl_cv_flag__largefile_source64+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 4559 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/stat.h>
-int main() {
+int
+main ()
+{
char *p = (char *)open64;
-; return 0; }
-EOF
-if { (eval echo configure:4566: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_flag__largefile_source64=no
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- cat > conftest.$ac_ext <<EOF
-#line 4574 "configure"
-#include "confdefs.h"
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#define _LARGEFILE_SOURCE64 1
#include <sys/stat.h>
-int main() {
+int
+main ()
+{
char *p = (char *)open64;
-; return 0; }
-EOF
-if { (eval echo configure:4582: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_flag__largefile_source64=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_flag__largefile_source64=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_flag__largefile_source64=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
if test "x${tcl_cv_flag__largefile_source64}" = "xyes" ; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define _LARGEFILE_SOURCE64 1
-EOF
+_ACEOF
tcl_flags="$tcl_flags _LARGEFILE_SOURCE64"
fi
if test "x${tcl_flags}" = "x" ; then
- echo "$ac_t""none" 1>&6
+ echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6
else
- echo "$ac_t""${tcl_flags}" 1>&6
+ echo "$as_me:$LINENO: result: ${tcl_flags}" >&5
+echo "${ECHO_T}${tcl_flags}" >&6
fi
- echo $ac_n "checking for 64-bit integer type""... $ac_c" 1>&6
-echo "configure:4613: checking for 64-bit integer type" >&5
- if eval "test \"`echo '$''{'tcl_cv_type_64bit'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for 64-bit integer type" >&5
+echo $ECHO_N "checking for 64-bit integer type... $ECHO_C" >&6
+ if test "${tcl_cv_type_64bit+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
+
tcl_cv_type_64bit=none
# See if the compiler knows natively about __int64
- cat > conftest.$ac_ext <<EOF
-#line 4621 "configure"
-#include "confdefs.h"
-
-int main() {
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
__int64 value = (__int64) 0;
-; return 0; }
-EOF
-if { (eval echo configure:4628: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_type_64bit=__int64
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_type_64bit="long long"
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_type_64bit="long long"
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
# See if we should use long anyway Note that we substitute in the
# type that is our current guess for a 64-bit type inside this check
# program, so it should be modified only carefully...
- cat > conftest.$ac_ext <<EOF
-#line 4642 "configure"
-#include "confdefs.h"
-
-int main() {
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
switch (0) {
case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ;
}
-; return 0; }
-EOF
-if { (eval echo configure:4651: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_type_64bit=${tcl_type_64bit}
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
if test "${tcl_cv_type_64bit}" = none ; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define TCL_WIDE_INT_IS_LONG 1
-EOF
+_ACEOF
- echo "$ac_t""using long" 1>&6
+ echo "$as_me:$LINENO: result: using long" >&5
+echo "${ECHO_T}using long" >&6
else
- cat >> confdefs.h <<EOF
+
+cat >>confdefs.h <<_ACEOF
#define TCL_WIDE_INT_TYPE ${tcl_cv_type_64bit}
-EOF
+_ACEOF
- echo "$ac_t""${tcl_cv_type_64bit}" 1>&6
+ echo "$as_me:$LINENO: result: ${tcl_cv_type_64bit}" >&5
+echo "${ECHO_T}${tcl_cv_type_64bit}" >&6
# Now check for auxiliary declarations
- echo $ac_n "checking for struct dirent64""... $ac_c" 1>&6
-echo "configure:4676: checking for struct dirent64" >&5
-if eval "test \"`echo '$''{'tcl_cv_struct_dirent64'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
-
- cat > conftest.$ac_ext <<EOF
-#line 4682 "configure"
-#include "confdefs.h"
+ echo "$as_me:$LINENO: checking for struct dirent64" >&5
+echo $ECHO_N "checking for struct dirent64... $ECHO_C" >&6
+if test "${tcl_cv_struct_dirent64+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/types.h>
#include <sys/dirent.h>
-int main() {
+int
+main ()
+{
struct dirent64 p;
-; return 0; }
-EOF
-if { (eval echo configure:4690: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_struct_dirent64=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_struct_dirent64=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_struct_dirent64=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_struct_dirent64" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_struct_dirent64" >&5
+echo "${ECHO_T}$tcl_cv_struct_dirent64" >&6
if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_STRUCT_DIRENT64 1
-EOF
+_ACEOF
fi
- echo $ac_n "checking for struct stat64""... $ac_c" 1>&6
-echo "configure:4711: checking for struct stat64" >&5
-if eval "test \"`echo '$''{'tcl_cv_struct_stat64'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for struct stat64" >&5
+echo $ECHO_N "checking for struct stat64... $ECHO_C" >&6
+if test "${tcl_cv_struct_stat64+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 4717 "configure"
-#include "confdefs.h"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/stat.h>
-int main() {
+int
+main ()
+{
struct stat64 p;
-; return 0; }
-EOF
-if { (eval echo configure:4725: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_struct_stat64=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_struct_stat64=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_struct_stat64=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_struct_stat64" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_struct_stat64" >&5
+echo "${ECHO_T}$tcl_cv_struct_stat64" >&6
if test "x${tcl_cv_struct_stat64}" = "xyes" ; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_STRUCT_STAT64 1
-EOF
+_ACEOF
fi
- for ac_func in open64 lseek64
+
+
+for ac_func in open64 lseek64
do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:4748: checking for $ac_func" >&5
-if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 4753 "configure"
-#include "confdefs.h"
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
choke me
#else
-$ac_func();
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:4776: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
-fi
-rm -f conftest*
-fi
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
fi
done
- echo $ac_n "checking for off64_t""... $ac_c" 1>&6
-echo "configure:4801: checking for off64_t" >&5
- if eval "test \"`echo '$''{'tcl_cv_type_off64_t'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for off64_t" >&5
+echo $ECHO_N "checking for off64_t... $ECHO_C" >&6
+ if test "${tcl_cv_type_off64_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 4807 "configure"
-#include "confdefs.h"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/types.h>
-int main() {
+int
+main ()
+{
off64_t offset;
-; return 0; }
-EOF
-if { (eval echo configure:4815: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_type_off64_t=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_type_off64_t=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_type_off64_t=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
if test "x${tcl_cv_type_off64_t}" = "xyes" && \
test "x${ac_cv_func_lseek64}" = "xyes" && \
test "x${ac_cv_func_open64}" = "xyes" ; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_TYPE_OFF64_T 1
-EOF
+_ACEOF
- echo "$ac_t""yes" 1>&6
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
fi
fi
@@ -4842,63 +9828,182 @@ EOF
# Tcl_UniChar strings to memcmp on big-endian systems.
#--------------------------------------------------------------------
-echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
-echo "configure:4847: checking whether byte ordering is bigendian" >&5
-if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_cv_c_bigendian=unknown
-# See if sys/param.h defines the BYTE_ORDER macro.
-cat > conftest.$ac_ext <<EOF
-#line 4854 "configure"
-#include "confdefs.h"
+echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
+echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6
+if test "${ac_cv_c_bigendian+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # See if sys/param.h defines the BYTE_ORDER macro.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/types.h>
#include <sys/param.h>
-int main() {
+int
+main ()
+{
#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
bogus endian macros
#endif
-; return 0; }
-EOF
-if { (eval echo configure:4865: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
# It does; now see whether it defined to BIG_ENDIAN or not.
-cat > conftest.$ac_ext <<EOF
-#line 4869 "configure"
-#include "confdefs.h"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/types.h>
#include <sys/param.h>
-int main() {
+int
+main ()
+{
#if BYTE_ORDER != BIG_ENDIAN
not big endian
#endif
-; return 0; }
-EOF
-if { (eval echo configure:4880: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
ac_cv_c_bigendian=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_c_bigendian=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_c_bigendian=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
-fi
-rm -f conftest*
-if test $ac_cv_c_bigendian = unknown; then
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+# It does not; compile a test program.
if test "$cross_compiling" = yes; then
- { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+ # try to guess the endianness by grepping values into an object file
+ ac_cv_c_bigendian=unknown
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; }
+short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; }
+int
+main ()
+{
+ _ascii (); _ebcdic ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
+ ac_cv_c_bigendian=yes
+fi
+if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+fi
else
- cat > conftest.$ac_ext <<EOF
-#line 4900 "configure"
-#include "confdefs.h"
-main () {
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+int
+main ()
+{
/* Are we little or big endian? From Harbison&Steele. */
union
{
@@ -4908,29 +10013,50 @@ main () {
u.l = 1;
exit (u.c[sizeof (long) - 1] == 1);
}
-EOF
-if { (eval echo configure:4913: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
ac_cv_c_bigendian=no
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_c_bigendian=yes
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_bigendian=yes
fi
-rm -fr conftest*
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
-
fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
+echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
+echo "${ECHO_T}$ac_cv_c_bigendian" >&6
+case $ac_cv_c_bigendian in
+ yes)
-echo "$ac_t""$ac_cv_c_bigendian" 1>&6
-if test $ac_cv_c_bigendian = yes; then
- cat >> confdefs.h <<\EOF
+cat >>confdefs.h <<\_ACEOF
#define WORDS_BIGENDIAN 1
-EOF
-
-fi
+_ACEOF
+ ;;
+ no)
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&5
+echo "$as_me: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
#--------------------------------------------------------------------
@@ -4939,61 +10065,110 @@ fi
#--------------------------------------------------------------------
# Check if Posix compliant getcwd exists, if not we'll use getwd.
+
for ac_func in getcwd
do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:4946: checking for $ac_func" >&5
-if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 4951 "configure"
-#include "confdefs.h"
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
choke me
#else
-$ac_func();
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:4974: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-cat >> confdefs.h <<\EOF
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+
+cat >>confdefs.h <<\_ACEOF
#define USEGETWD 1
-EOF
+_ACEOF
fi
done
@@ -5001,268 +10176,517 @@ done
# Nb: if getcwd uses popen and pwd(1) (like SunOS 4) we should really
# define USEGETWD even if the posix getcwd exists. Add a test ?
-for ac_func in opendir strstr strtol strtoll strtoull tmpnam waitpid
+
+
+
+for ac_func in opendir strtol waitpid
do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:5008: checking for $ac_func" >&5
-if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 5013 "configure"
-#include "confdefs.h"
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
choke me
#else
-$ac_func();
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:5036: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
-fi
-rm -f conftest*
-fi
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+ case $LIBOBJS in
+ "$ac_func.$ac_objext" | \
+ *" $ac_func.$ac_objext" | \
+ "$ac_func.$ac_objext "* | \
+ *" $ac_func.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS $ac_func.$ac_objext" ;;
+esac
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-LIBOBJS="$LIBOBJS ${ac_func}.${ac_objext}"
fi
done
-echo $ac_n "checking for strerror""... $ac_c" 1>&6
-echo "configure:5063: checking for strerror" >&5
-if eval "test \"`echo '$''{'ac_cv_func_strerror'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for strerror" >&5
+echo $ECHO_N "checking for strerror... $ECHO_C" >&6
+if test "${ac_cv_func_strerror+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 5068 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define strerror to an innocuous variant, in case <limits.h> declares strerror.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define strerror innocuous_strerror
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char strerror(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char strerror();
+ which can conflict with char strerror (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef strerror
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char strerror ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_strerror) || defined (__stub___strerror)
choke me
#else
-strerror();
+char (*f) () = strerror;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:5091: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_strerror=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_strerror=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'strerror`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+int
+main ()
+{
+return f != strerror;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_strerror=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_strerror=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_strerror" >&5
+echo "${ECHO_T}$ac_cv_func_strerror" >&6
+if test $ac_cv_func_strerror = yes; then
:
else
- echo "$ac_t""no" 1>&6
-cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define NO_STRERROR 1
-EOF
+_ACEOF
fi
-echo $ac_n "checking for getwd""... $ac_c" 1>&6
-echo "configure:5115: checking for getwd" >&5
-if eval "test \"`echo '$''{'ac_cv_func_getwd'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for getwd" >&5
+echo $ECHO_N "checking for getwd... $ECHO_C" >&6
+if test "${ac_cv_func_getwd+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 5120 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define getwd to an innocuous variant, in case <limits.h> declares getwd.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define getwd innocuous_getwd
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char getwd(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char getwd();
+ which can conflict with char getwd (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef getwd
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char getwd ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_getwd) || defined (__stub___getwd)
choke me
#else
-getwd();
+char (*f) () = getwd;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:5143: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_getwd=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_getwd=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'getwd`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+int
+main ()
+{
+return f != getwd;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_getwd=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_getwd=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_getwd" >&5
+echo "${ECHO_T}$ac_cv_func_getwd" >&6
+if test $ac_cv_func_getwd = yes; then
:
else
- echo "$ac_t""no" 1>&6
-cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define NO_GETWD 1
-EOF
+_ACEOF
fi
-echo $ac_n "checking for wait3""... $ac_c" 1>&6
-echo "configure:5167: checking for wait3" >&5
-if eval "test \"`echo '$''{'ac_cv_func_wait3'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for wait3" >&5
+echo $ECHO_N "checking for wait3... $ECHO_C" >&6
+if test "${ac_cv_func_wait3+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 5172 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define wait3 to an innocuous variant, in case <limits.h> declares wait3.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define wait3 innocuous_wait3
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char wait3(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char wait3();
+ which can conflict with char wait3 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef wait3
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char wait3 ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_wait3) || defined (__stub___wait3)
choke me
#else
-wait3();
+char (*f) () = wait3;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:5195: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_wait3=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_wait3=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'wait3`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+int
+main ()
+{
+return f != wait3;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_wait3=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_wait3=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_wait3" >&5
+echo "${ECHO_T}$ac_cv_func_wait3" >&6
+if test $ac_cv_func_wait3 = yes; then
:
else
- echo "$ac_t""no" 1>&6
-cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define NO_WAIT3 1
-EOF
+_ACEOF
fi
-echo $ac_n "checking for uname""... $ac_c" 1>&6
-echo "configure:5219: checking for uname" >&5
-if eval "test \"`echo '$''{'ac_cv_func_uname'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for uname" >&5
+echo $ECHO_N "checking for uname... $ECHO_C" >&6
+if test "${ac_cv_func_uname+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 5224 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define uname to an innocuous variant, in case <limits.h> declares uname.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define uname innocuous_uname
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char uname(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char uname();
+ which can conflict with char uname (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef uname
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char uname ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_uname) || defined (__stub___uname)
choke me
#else
-uname();
+char (*f) () = uname;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:5247: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_uname=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_uname=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'uname`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+int
+main ()
+{
+return f != uname;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_uname=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_uname=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_uname" >&5
+echo "${ECHO_T}$ac_cv_func_uname" >&6
+if test $ac_cv_func_uname = yes; then
:
else
- echo "$ac_t""no" 1>&6
-cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define NO_UNAME 1
-EOF
+_ACEOF
fi
@@ -5273,55 +10697,268 @@ if test "`uname -s`" = "Darwin" && test "${TCL_THREADS}" = 1 && \
# use it when threads are enabled, c.f. bug # 711232
ac_cv_func_realpath=no
fi
-echo $ac_n "checking for realpath""... $ac_c" 1>&6
-echo "configure:5278: checking for realpath" >&5
-if eval "test \"`echo '$''{'ac_cv_func_realpath'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 5283 "configure"
-#include "confdefs.h"
+echo "$as_me:$LINENO: checking for realpath" >&5
+echo $ECHO_N "checking for realpath... $ECHO_C" >&6
+if test "${ac_cv_func_realpath+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define realpath to an innocuous variant, in case <limits.h> declares realpath.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define realpath innocuous_realpath
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char realpath(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char realpath();
+ which can conflict with char realpath (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+#undef realpath
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char realpath ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_realpath) || defined (__stub___realpath)
choke me
#else
-realpath();
+char (*f) () = realpath;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:5306: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_realpath=yes"
+int
+main ()
+{
+return f != realpath;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_realpath=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_realpath=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_realpath" >&5
+echo "${ECHO_T}$ac_cv_func_realpath" >&6
+if test $ac_cv_func_realpath = yes; then
+ :
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_realpath=no"
-fi
-rm -f conftest*
+
+cat >>confdefs.h <<\_ACEOF
+#define NO_REALPATH 1
+_ACEOF
+
fi
-if eval "test \"`echo '$ac_cv_func_'realpath`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- :
+
+echo "$as_me:$LINENO: checking for getaddrinfo" >&5
+echo $ECHO_N "checking for getaddrinfo... $ECHO_C" >&6
+if test "${ac_cv_func_getaddrinfo+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- echo "$ac_t""no" 1>&6
-cat >> confdefs.h <<\EOF
-#define NO_REALPATH 1
-EOF
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define getaddrinfo to an innocuous variant, in case <limits.h> declares getaddrinfo.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define getaddrinfo innocuous_getaddrinfo
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getaddrinfo (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef getaddrinfo
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char getaddrinfo ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_getaddrinfo) || defined (__stub___getaddrinfo)
+choke me
+#else
+char (*f) () = getaddrinfo;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != getaddrinfo;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_getaddrinfo=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_getaddrinfo=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_getaddrinfo" >&5
+echo "${ECHO_T}$ac_cv_func_getaddrinfo" >&6
+if test $ac_cv_func_getaddrinfo = yes; then
+
+ echo "$as_me:$LINENO: checking for working getaddrinfo" >&5
+echo $ECHO_N "checking for working getaddrinfo... $ECHO_C" >&6
+if test "${tcl_cv_api_getaddrinfo+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+ #include <netdb.h>
+
+int
+main ()
+{
+
+ const char *name, *port;
+ struct addrinfo *aiPtr, hints;
+ (void)getaddrinfo(name,port, &hints, &aiPtr);
+ (void)freeaddrinfo(aiPtr);
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ tcl_cv_api_getaddrinfo=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_getaddrinfo=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_api_getaddrinfo" >&5
+echo "${ECHO_T}$tcl_cv_api_getaddrinfo" >&6
+ tcl_ok=$tcl_cv_api_getaddrinfo
+ if test "$tcl_ok" = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GETADDRINFO 1
+_ACEOF
+
+ fi
fi
@@ -5331,64 +10968,117 @@ fi
#--------------------------------------------------------------------
if test "${TCL_THREADS}" = 1; then
- echo $ac_n "checking for getpwuid_r""... $ac_c" 1>&6
-echo "configure:5336: checking for getpwuid_r" >&5
-if eval "test \"`echo '$''{'ac_cv_func_getpwuid_r'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 5341 "configure"
-#include "confdefs.h"
+ echo "$as_me:$LINENO: checking for getpwuid_r" >&5
+echo $ECHO_N "checking for getpwuid_r... $ECHO_C" >&6
+if test "${ac_cv_func_getpwuid_r+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define getpwuid_r to an innocuous variant, in case <limits.h> declares getpwuid_r.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define getpwuid_r innocuous_getpwuid_r
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char getpwuid_r(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char getpwuid_r();
+ which can conflict with char getpwuid_r (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+#undef getpwuid_r
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char getpwuid_r ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_getpwuid_r) || defined (__stub___getpwuid_r)
choke me
#else
-getpwuid_r();
+char (*f) () = getpwuid_r;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:5364: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_getpwuid_r=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_getpwuid_r=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'getpwuid_r`\" = yes"; then
- echo "$ac_t""yes" 1>&6
-
- echo $ac_n "checking for getpwuid_r with 5 args""... $ac_c" 1>&6
-echo "configure:5380: checking for getpwuid_r with 5 args" >&5
-if eval "test \"`echo '$''{'tcl_cv_api_getpwuid_r_5'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
-
- cat > conftest.$ac_ext <<EOF
-#line 5386 "configure"
-#include "confdefs.h"
+int
+main ()
+{
+return f != getpwuid_r;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_getpwuid_r=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_getpwuid_r=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_getpwuid_r" >&5
+echo "${ECHO_T}$ac_cv_func_getpwuid_r" >&6
+if test $ac_cv_func_getpwuid_r = yes; then
+
+ echo "$as_me:$LINENO: checking for getpwuid_r with 5 args" >&5
+echo $ECHO_N "checking for getpwuid_r with 5 args... $ECHO_C" >&6
+if test "${tcl_cv_api_getpwuid_r_5+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/types.h>
#include <pwd.h>
-
-int main() {
+
+int
+main ()
+{
uid_t uid;
struct passwd pw, *pwp;
@@ -5396,43 +11086,71 @@ int main() {
int buflen = 512;
(void) getpwuid_r(uid, &pw, buf, buflen, &pwp);
-
-; return 0; }
-EOF
-if { (eval echo configure:5403: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_api_getpwuid_r_5=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_api_getpwuid_r_5=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_api_getpwuid_r_5=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_api_getpwuid_r_5" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_api_getpwuid_r_5" >&5
+echo "${ECHO_T}$tcl_cv_api_getpwuid_r_5" >&6
tcl_ok=$tcl_cv_api_getpwuid_r_5
if test "$tcl_ok" = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_GETPWUID_R_5 1
-EOF
+_ACEOF
else
- echo $ac_n "checking for getpwuid_r with 4 args""... $ac_c" 1>&6
-echo "configure:5424: checking for getpwuid_r with 4 args" >&5
-if eval "test \"`echo '$''{'tcl_cv_api_getpwuid_r_4'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for getpwuid_r with 4 args" >&5
+echo $ECHO_N "checking for getpwuid_r with 4 args... $ECHO_C" >&6
+if test "${tcl_cv_api_getpwuid_r_4+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 5430 "configure"
-#include "confdefs.h"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/types.h>
#include <pwd.h>
-
-int main() {
+
+int
+main ()
+{
uid_t uid;
struct passwd pw;
@@ -5440,99 +11158,174 @@ int main() {
int buflen = 512;
(void)getpwnam_r(uid, &pw, buf, buflen);
-
-; return 0; }
-EOF
-if { (eval echo configure:5447: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_api_getpwuid_r_4=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_api_getpwuid_r_4=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_api_getpwuid_r_4=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_api_getpwuid_r_4" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_api_getpwuid_r_4" >&5
+echo "${ECHO_T}$tcl_cv_api_getpwuid_r_4" >&6
tcl_ok=$tcl_cv_api_getpwuid_r_4
if test "$tcl_ok" = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_GETPWUID_R_4 1
-EOF
+_ACEOF
fi
fi
if test "$tcl_ok" = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_GETPWUID_R 1
-EOF
+_ACEOF
fi
-else
- echo "$ac_t""no" 1>&6
fi
- echo $ac_n "checking for getpwnam_r""... $ac_c" 1>&6
-echo "configure:5480: checking for getpwnam_r" >&5
-if eval "test \"`echo '$''{'ac_cv_func_getpwnam_r'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for getpwnam_r" >&5
+echo $ECHO_N "checking for getpwnam_r... $ECHO_C" >&6
+if test "${ac_cv_func_getpwnam_r+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 5485 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define getpwnam_r to an innocuous variant, in case <limits.h> declares getpwnam_r.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define getpwnam_r innocuous_getpwnam_r
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char getpwnam_r(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char getpwnam_r();
+ which can conflict with char getpwnam_r (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+#undef getpwnam_r
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char getpwnam_r ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_getpwnam_r) || defined (__stub___getpwnam_r)
choke me
#else
-getpwnam_r();
+char (*f) () = getpwnam_r;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:5508: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_getpwnam_r=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_getpwnam_r=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'getpwnam_r`\" = yes"; then
- echo "$ac_t""yes" 1>&6
-
- echo $ac_n "checking for getpwnam_r with 5 args""... $ac_c" 1>&6
-echo "configure:5524: checking for getpwnam_r with 5 args" >&5
-if eval "test \"`echo '$''{'tcl_cv_api_getpwnam_r_5'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
-
- cat > conftest.$ac_ext <<EOF
-#line 5530 "configure"
-#include "confdefs.h"
+int
+main ()
+{
+return f != getpwnam_r;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_getpwnam_r=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_getpwnam_r=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_getpwnam_r" >&5
+echo "${ECHO_T}$ac_cv_func_getpwnam_r" >&6
+if test $ac_cv_func_getpwnam_r = yes; then
+
+ echo "$as_me:$LINENO: checking for getpwnam_r with 5 args" >&5
+echo $ECHO_N "checking for getpwnam_r with 5 args... $ECHO_C" >&6
+if test "${tcl_cv_api_getpwnam_r_5+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/types.h>
#include <pwd.h>
-
-int main() {
+
+int
+main ()
+{
char *name;
struct passwd pw, *pwp;
@@ -5540,43 +11333,71 @@ int main() {
int buflen = 512;
(void) getpwnam_r(name, &pw, buf, buflen, &pwp);
-
-; return 0; }
-EOF
-if { (eval echo configure:5547: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_api_getpwnam_r_5=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_api_getpwnam_r_5=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_api_getpwnam_r_5=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_api_getpwnam_r_5" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_api_getpwnam_r_5" >&5
+echo "${ECHO_T}$tcl_cv_api_getpwnam_r_5" >&6
tcl_ok=$tcl_cv_api_getpwnam_r_5
if test "$tcl_ok" = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_GETPWNAM_R_5 1
-EOF
+_ACEOF
else
- echo $ac_n "checking for getpwnam_r with 4 args""... $ac_c" 1>&6
-echo "configure:5568: checking for getpwnam_r with 4 args" >&5
-if eval "test \"`echo '$''{'tcl_cv_api_getpwnam_r_4'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for getpwnam_r with 4 args" >&5
+echo $ECHO_N "checking for getpwnam_r with 4 args... $ECHO_C" >&6
+if test "${tcl_cv_api_getpwnam_r_4+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 5574 "configure"
-#include "confdefs.h"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/types.h>
#include <pwd.h>
-
-int main() {
+
+int
+main ()
+{
char *name;
struct passwd pw;
@@ -5584,99 +11405,174 @@ int main() {
int buflen = 512;
(void)getpwnam_r(name, &pw, buf, buflen);
-
-; return 0; }
-EOF
-if { (eval echo configure:5591: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_api_getpwnam_r_4=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_api_getpwnam_r_4=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_api_getpwnam_r_4=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_api_getpwnam_r_4" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_api_getpwnam_r_4" >&5
+echo "${ECHO_T}$tcl_cv_api_getpwnam_r_4" >&6
tcl_ok=$tcl_cv_api_getpwnam_r_4
if test "$tcl_ok" = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_GETPWNAM_R_4 1
-EOF
+_ACEOF
fi
fi
if test "$tcl_ok" = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_GETPWNAM_R 1
-EOF
+_ACEOF
fi
-else
- echo "$ac_t""no" 1>&6
fi
- echo $ac_n "checking for getgrgid_r""... $ac_c" 1>&6
-echo "configure:5624: checking for getgrgid_r" >&5
-if eval "test \"`echo '$''{'ac_cv_func_getgrgid_r'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for getgrgid_r" >&5
+echo $ECHO_N "checking for getgrgid_r... $ECHO_C" >&6
+if test "${ac_cv_func_getgrgid_r+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 5629 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define getgrgid_r to an innocuous variant, in case <limits.h> declares getgrgid_r.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define getgrgid_r innocuous_getgrgid_r
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char getgrgid_r(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char getgrgid_r();
+ which can conflict with char getgrgid_r (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef getgrgid_r
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char getgrgid_r ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_getgrgid_r) || defined (__stub___getgrgid_r)
choke me
#else
-getgrgid_r();
+char (*f) () = getgrgid_r;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:5652: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_getgrgid_r=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_getgrgid_r=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'getgrgid_r`\" = yes"; then
- echo "$ac_t""yes" 1>&6
-
- echo $ac_n "checking for getgrgid_r with 5 args""... $ac_c" 1>&6
-echo "configure:5668: checking for getgrgid_r with 5 args" >&5
-if eval "test \"`echo '$''{'tcl_cv_api_getgrgid_r_5'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
-
- cat > conftest.$ac_ext <<EOF
-#line 5674 "configure"
-#include "confdefs.h"
+int
+main ()
+{
+return f != getgrgid_r;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_getgrgid_r=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_getgrgid_r=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_getgrgid_r" >&5
+echo "${ECHO_T}$ac_cv_func_getgrgid_r" >&6
+if test $ac_cv_func_getgrgid_r = yes; then
+
+ echo "$as_me:$LINENO: checking for getgrgid_r with 5 args" >&5
+echo $ECHO_N "checking for getgrgid_r with 5 args... $ECHO_C" >&6
+if test "${tcl_cv_api_getgrgid_r_5+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/types.h>
#include <grp.h>
-
-int main() {
+
+int
+main ()
+{
gid_t gid;
struct group gr, *grp;
@@ -5684,43 +11580,71 @@ int main() {
int buflen = 512;
(void) getgrgid_r(gid, &gr, buf, buflen, &grp);
-
-; return 0; }
-EOF
-if { (eval echo configure:5691: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_api_getgrgid_r_5=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_api_getgrgid_r_5=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_api_getgrgid_r_5=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_api_getgrgid_r_5" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_api_getgrgid_r_5" >&5
+echo "${ECHO_T}$tcl_cv_api_getgrgid_r_5" >&6
tcl_ok=$tcl_cv_api_getgrgid_r_5
if test "$tcl_ok" = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_GETGRGID_R_5 1
-EOF
+_ACEOF
else
- echo $ac_n "checking for getgrgid_r with 4 args""... $ac_c" 1>&6
-echo "configure:5712: checking for getgrgid_r with 4 args" >&5
-if eval "test \"`echo '$''{'tcl_cv_api_getgrgid_r_4'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for getgrgid_r with 4 args" >&5
+echo $ECHO_N "checking for getgrgid_r with 4 args... $ECHO_C" >&6
+if test "${tcl_cv_api_getgrgid_r_4+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 5718 "configure"
-#include "confdefs.h"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/types.h>
#include <grp.h>
-
-int main() {
+
+int
+main ()
+{
gid_t gid;
struct group gr;
@@ -5728,99 +11652,174 @@ int main() {
int buflen = 512;
(void)getgrgid_r(gid, &gr, buf, buflen);
-
-; return 0; }
-EOF
-if { (eval echo configure:5735: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_api_getgrgid_r_4=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_api_getgrgid_r_4=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_api_getgrgid_r_4=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_api_getgrgid_r_4" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_api_getgrgid_r_4" >&5
+echo "${ECHO_T}$tcl_cv_api_getgrgid_r_4" >&6
tcl_ok=$tcl_cv_api_getgrgid_r_4
if test "$tcl_ok" = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_GETGRGID_R_4 1
-EOF
+_ACEOF
fi
fi
if test "$tcl_ok" = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_GETGRGID_R 1
-EOF
+_ACEOF
fi
-else
- echo "$ac_t""no" 1>&6
fi
- echo $ac_n "checking for getgrnam_r""... $ac_c" 1>&6
-echo "configure:5768: checking for getgrnam_r" >&5
-if eval "test \"`echo '$''{'ac_cv_func_getgrnam_r'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for getgrnam_r" >&5
+echo $ECHO_N "checking for getgrnam_r... $ECHO_C" >&6
+if test "${ac_cv_func_getgrnam_r+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 5773 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define getgrnam_r to an innocuous variant, in case <limits.h> declares getgrnam_r.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define getgrnam_r innocuous_getgrnam_r
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char getgrnam_r(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char getgrnam_r();
+ which can conflict with char getgrnam_r (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef getgrnam_r
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char getgrnam_r ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_getgrnam_r) || defined (__stub___getgrnam_r)
choke me
#else
-getgrnam_r();
+char (*f) () = getgrnam_r;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:5796: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_getgrnam_r=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_getgrnam_r=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'getgrnam_r`\" = yes"; then
- echo "$ac_t""yes" 1>&6
-
- echo $ac_n "checking for getgrnam_r with 5 args""... $ac_c" 1>&6
-echo "configure:5812: checking for getgrnam_r with 5 args" >&5
-if eval "test \"`echo '$''{'tcl_cv_api_getgrnam_r_5'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
-
- cat > conftest.$ac_ext <<EOF
-#line 5818 "configure"
-#include "confdefs.h"
+int
+main ()
+{
+return f != getgrnam_r;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_getgrnam_r=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_getgrnam_r=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_getgrnam_r" >&5
+echo "${ECHO_T}$ac_cv_func_getgrnam_r" >&6
+if test $ac_cv_func_getgrnam_r = yes; then
+
+ echo "$as_me:$LINENO: checking for getgrnam_r with 5 args" >&5
+echo $ECHO_N "checking for getgrnam_r with 5 args... $ECHO_C" >&6
+if test "${tcl_cv_api_getgrnam_r_5+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/types.h>
#include <grp.h>
-
-int main() {
+
+int
+main ()
+{
char *name;
struct group gr, *grp;
@@ -5828,43 +11827,71 @@ int main() {
int buflen = 512;
(void) getgrnam_r(name, &gr, buf, buflen, &grp);
-
-; return 0; }
-EOF
-if { (eval echo configure:5835: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_api_getgrnam_r_5=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_api_getgrnam_r_5=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_api_getgrnam_r_5=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_api_getgrnam_r_5" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_api_getgrnam_r_5" >&5
+echo "${ECHO_T}$tcl_cv_api_getgrnam_r_5" >&6
tcl_ok=$tcl_cv_api_getgrnam_r_5
if test "$tcl_ok" = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_GETGRNAM_R_5 1
-EOF
+_ACEOF
else
- echo $ac_n "checking for getgrnam_r with 4 args""... $ac_c" 1>&6
-echo "configure:5856: checking for getgrnam_r with 4 args" >&5
-if eval "test \"`echo '$''{'tcl_cv_api_getgrnam_r_4'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for getgrnam_r with 4 args" >&5
+echo $ECHO_N "checking for getgrnam_r with 4 args... $ECHO_C" >&6
+if test "${tcl_cv_api_getgrnam_r_4+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 5862 "configure"
-#include "confdefs.h"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/types.h>
#include <grp.h>
-
-int main() {
+
+int
+main ()
+{
char *name;
struct group gr;
@@ -5872,125 +11899,206 @@ int main() {
int buflen = 512;
(void)getgrnam_r(name, &gr, buf, buflen);
-
-; return 0; }
-EOF
-if { (eval echo configure:5879: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_api_getgrnam_r_4=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_api_getgrnam_r_4=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_api_getgrnam_r_4=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_api_getgrnam_r_4" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_api_getgrnam_r_4" >&5
+echo "${ECHO_T}$tcl_cv_api_getgrnam_r_4" >&6
tcl_ok=$tcl_cv_api_getgrnam_r_4
if test "$tcl_ok" = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_GETGRNAM_R_4 1
-EOF
+_ACEOF
fi
fi
if test "$tcl_ok" = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_GETGRNAM_R 1
-EOF
+_ACEOF
fi
-else
- echo "$ac_t""no" 1>&6
fi
if test "`uname -s`" = "Darwin" && \
test "`uname -r | awk -F. '{print $1}'`" -gt 5; then
- # Starting with Darwin 6 (Mac OSX 10.2), gethostbyX
+ # Starting with Darwin 6 (Mac OSX 10.2), gethostbyX
# are actually MT-safe as they always return pointers
- # from the TSD instead of the static storage.
- cat >> confdefs.h <<\EOF
+ # from TSD instead of static storage.
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_MTSAFE_GETHOSTBYNAME 1
-EOF
+_ACEOF
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_MTSAFE_GETHOSTBYADDR 1
-EOF
+_ACEOF
+
elif test "`uname -s`" = "HP-UX" && \
test "`uname -r|sed -e 's|B\.||' -e 's|\..*$||'`" -gt 10; then
# Starting with HPUX 11.00 (we believe), gethostbyX
# are actually MT-safe as they always return pointers
# from TSD instead of static storage.
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_MTSAFE_GETHOSTBYNAME 1
-EOF
+_ACEOF
+
- cat >> confdefs.h <<\EOF
+cat >>confdefs.h <<\_ACEOF
#define HAVE_MTSAFE_GETHOSTBYADDR 1
-EOF
+_ACEOF
+
else
- echo $ac_n "checking for gethostbyname_r""... $ac_c" 1>&6
-echo "configure:5939: checking for gethostbyname_r" >&5
-if eval "test \"`echo '$''{'ac_cv_func_gethostbyname_r'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 5944 "configure"
-#include "confdefs.h"
+ echo "$as_me:$LINENO: checking for gethostbyname_r" >&5
+echo $ECHO_N "checking for gethostbyname_r... $ECHO_C" >&6
+if test "${ac_cv_func_gethostbyname_r+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define gethostbyname_r to an innocuous variant, in case <limits.h> declares gethostbyname_r.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define gethostbyname_r innocuous_gethostbyname_r
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char gethostbyname_r(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char gethostbyname_r();
+ which can conflict with char gethostbyname_r (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+#undef gethostbyname_r
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyname_r ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_gethostbyname_r) || defined (__stub___gethostbyname_r)
choke me
#else
-gethostbyname_r();
+char (*f) () = gethostbyname_r;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:5967: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_gethostbyname_r=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_gethostbyname_r=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'gethostbyname_r`\" = yes"; then
- echo "$ac_t""yes" 1>&6
-
- echo $ac_n "checking for gethostbyname_r with 6 args""... $ac_c" 1>&6
-echo "configure:5983: checking for gethostbyname_r with 6 args" >&5
-if eval "test \"`echo '$''{'tcl_cv_api_gethostbyname_r_6'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
-
- cat > conftest.$ac_ext <<EOF
-#line 5989 "configure"
-#include "confdefs.h"
+int
+main ()
+{
+return f != gethostbyname_r;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_gethostbyname_r=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_gethostbyname_r=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname_r" >&5
+echo "${ECHO_T}$ac_cv_func_gethostbyname_r" >&6
+if test $ac_cv_func_gethostbyname_r = yes; then
+
+ echo "$as_me:$LINENO: checking for gethostbyname_r with 6 args" >&5
+echo $ECHO_N "checking for gethostbyname_r with 6 args... $ECHO_C" >&6
+if test "${tcl_cv_api_gethostbyname_r_6+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <netdb.h>
-
-int main() {
+
+int
+main ()
+{
char *name;
struct hostent *he, *res;
@@ -5999,42 +12107,70 @@ int main() {
int h_errnop;
(void) gethostbyname_r(name, he, buffer, buflen, &res, &h_errnop);
-
-; return 0; }
-EOF
-if { (eval echo configure:6006: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_api_gethostbyname_r_6=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_api_gethostbyname_r_6=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_api_gethostbyname_r_6=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_api_gethostbyname_r_6" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_api_gethostbyname_r_6" >&5
+echo "${ECHO_T}$tcl_cv_api_gethostbyname_r_6" >&6
tcl_ok=$tcl_cv_api_gethostbyname_r_6
if test "$tcl_ok" = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_GETHOSTBYNAME_R_6 1
-EOF
+_ACEOF
else
- echo $ac_n "checking for gethostbyname_r with 5 args""... $ac_c" 1>&6
-echo "configure:6027: checking for gethostbyname_r with 5 args" >&5
-if eval "test \"`echo '$''{'tcl_cv_api_gethostbyname_r_5'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for gethostbyname_r with 5 args" >&5
+echo $ECHO_N "checking for gethostbyname_r with 5 args... $ECHO_C" >&6
+if test "${tcl_cv_api_gethostbyname_r_5+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 6033 "configure"
-#include "confdefs.h"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <netdb.h>
-
-int main() {
+
+int
+main ()
+{
char *name;
struct hostent *he;
@@ -6043,141 +12179,244 @@ int main() {
int h_errnop;
(void) gethostbyname_r(name, he, buffer, buflen, &h_errnop);
-
-; return 0; }
-EOF
-if { (eval echo configure:6050: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_api_gethostbyname_r_5=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_api_gethostbyname_r_5=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_api_gethostbyname_r_5=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_api_gethostbyname_r_5" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_api_gethostbyname_r_5" >&5
+echo "${ECHO_T}$tcl_cv_api_gethostbyname_r_5" >&6
tcl_ok=$tcl_cv_api_gethostbyname_r_5
if test "$tcl_ok" = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_GETHOSTBYNAME_R_5 1
-EOF
+_ACEOF
else
- echo $ac_n "checking for gethostbyname_r with 3 args""... $ac_c" 1>&6
-echo "configure:6071: checking for gethostbyname_r with 3 args" >&5
-if eval "test \"`echo '$''{'tcl_cv_api_gethostbyname_r_3'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for gethostbyname_r with 3 args" >&5
+echo $ECHO_N "checking for gethostbyname_r with 3 args... $ECHO_C" >&6
+if test "${tcl_cv_api_gethostbyname_r_3+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 6077 "configure"
-#include "confdefs.h"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <netdb.h>
-
-int main() {
+
+int
+main ()
+{
char *name;
struct hostent *he;
struct hostent_data data;
(void) gethostbyname_r(name, he, &data);
-
-; return 0; }
-EOF
-if { (eval echo configure:6092: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_api_gethostbyname_r_3=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_api_gethostbyname_r_3=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_api_gethostbyname_r_3=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_api_gethostbyname_r_3" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_api_gethostbyname_r_3" >&5
+echo "${ECHO_T}$tcl_cv_api_gethostbyname_r_3" >&6
tcl_ok=$tcl_cv_api_gethostbyname_r_3
if test "$tcl_ok" = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_GETHOSTBYNAME_R_3 1
-EOF
+_ACEOF
fi
fi
fi
if test "$tcl_ok" = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_GETHOSTBYNAME_R 1
-EOF
+_ACEOF
fi
-else
- echo "$ac_t""no" 1>&6
fi
- echo $ac_n "checking for gethostbyaddr_r""... $ac_c" 1>&6
-echo "configure:6126: checking for gethostbyaddr_r" >&5
-if eval "test \"`echo '$''{'ac_cv_func_gethostbyaddr_r'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for gethostbyaddr_r" >&5
+echo $ECHO_N "checking for gethostbyaddr_r... $ECHO_C" >&6
+if test "${ac_cv_func_gethostbyaddr_r+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 6131 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define gethostbyaddr_r to an innocuous variant, in case <limits.h> declares gethostbyaddr_r.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define gethostbyaddr_r innocuous_gethostbyaddr_r
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char gethostbyaddr_r(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char gethostbyaddr_r();
+ which can conflict with char gethostbyaddr_r (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef gethostbyaddr_r
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyaddr_r ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_gethostbyaddr_r) || defined (__stub___gethostbyaddr_r)
choke me
#else
-gethostbyaddr_r();
+char (*f) () = gethostbyaddr_r;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:6154: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_gethostbyaddr_r=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_gethostbyaddr_r=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'gethostbyaddr_r`\" = yes"; then
- echo "$ac_t""yes" 1>&6
-
- echo $ac_n "checking for gethostbyaddr_r with 7 args""... $ac_c" 1>&6
-echo "configure:6170: checking for gethostbyaddr_r with 7 args" >&5
-if eval "test \"`echo '$''{'tcl_cv_api_gethostbyaddr_r_7'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
-
- cat > conftest.$ac_ext <<EOF
-#line 6176 "configure"
-#include "confdefs.h"
+int
+main ()
+{
+return f != gethostbyaddr_r;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_gethostbyaddr_r=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_gethostbyaddr_r=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyaddr_r" >&5
+echo "${ECHO_T}$ac_cv_func_gethostbyaddr_r" >&6
+if test $ac_cv_func_gethostbyaddr_r = yes; then
+
+ echo "$as_me:$LINENO: checking for gethostbyaddr_r with 7 args" >&5
+echo $ECHO_N "checking for gethostbyaddr_r with 7 args... $ECHO_C" >&6
+if test "${tcl_cv_api_gethostbyaddr_r_7+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <netdb.h>
-
-int main() {
+
+int
+main ()
+{
char *addr;
int length;
@@ -6189,42 +12428,70 @@ int main() {
(void) gethostbyaddr_r(addr, length, type, result, buffer, buflen,
&h_errnop);
-
-; return 0; }
-EOF
-if { (eval echo configure:6196: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_api_gethostbyaddr_r_7=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_api_gethostbyaddr_r_7=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_api_gethostbyaddr_r_7=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_api_gethostbyaddr_r_7" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_api_gethostbyaddr_r_7" >&5
+echo "${ECHO_T}$tcl_cv_api_gethostbyaddr_r_7" >&6
tcl_ok=$tcl_cv_api_gethostbyaddr_r_7
if test "$tcl_ok" = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_GETHOSTBYADDR_R_7 1
-EOF
+_ACEOF
else
- echo $ac_n "checking for gethostbyaddr_r with 8 args""... $ac_c" 1>&6
-echo "configure:6217: checking for gethostbyaddr_r with 8 args" >&5
-if eval "test \"`echo '$''{'tcl_cv_api_gethostbyaddr_r_8'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for gethostbyaddr_r with 8 args" >&5
+echo $ECHO_N "checking for gethostbyaddr_r with 8 args... $ECHO_C" >&6
+if test "${tcl_cv_api_gethostbyaddr_r_8+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 6223 "configure"
-#include "confdefs.h"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <netdb.h>
-
-int main() {
+
+int
+main ()
+{
char *addr;
int length;
@@ -6236,39 +12503,61 @@ int main() {
(void) gethostbyaddr_r(addr, length, type, result, buffer, buflen,
&resultp, &h_errnop);
-
-; return 0; }
-EOF
-if { (eval echo configure:6243: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_api_gethostbyaddr_r_8=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_api_gethostbyaddr_r_8=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_api_gethostbyaddr_r_8=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_api_gethostbyaddr_r_8" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_api_gethostbyaddr_r_8" >&5
+echo "${ECHO_T}$tcl_cv_api_gethostbyaddr_r_8" >&6
tcl_ok=$tcl_cv_api_gethostbyaddr_r_8
if test "$tcl_ok" = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_GETHOSTBYADDR_R_8 1
-EOF
+_ACEOF
fi
fi
if test "$tcl_ok" = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_GETHOSTBYADDR_R 1
-EOF
+_ACEOF
fi
-else
- echo "$ac_t""no" 1>&6
fi
fi
@@ -6281,58 +12570,171 @@ fi
#---------------------------------------------------------------------------
- for ac_hdr in sys/modem.h
+
+for ac_header in sys/modem.h
do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:6289: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 6294 "configure"
-#include "confdefs.h"
-#include <$ac_hdr>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:6299: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
fi
-rm -f conftest*
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_hdr 1
-EOF
-
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to the tcl lists. ##
+## ------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- echo "$ac_t""no" 1>&6
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
done
- echo $ac_n "checking termios vs. termio vs. sgtty""... $ac_c" 1>&6
-echo "configure:6326: checking termios vs. termio vs. sgtty" >&5
-if eval "test \"`echo '$''{'tcl_cv_api_serial'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking termios vs. termio vs. sgtty" >&5
+echo $ECHO_N "checking termios vs. termio vs. sgtty... $ECHO_C" >&6
+if test "${tcl_cv_api_serial+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
+
if test "$cross_compiling" = yes; then
tcl_cv_api_serial=no
else
- cat > conftest.$ac_ext <<EOF
-#line 6335 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <termios.h>
@@ -6345,26 +12747,39 @@ int main() {
}
return 1;
}
-EOF
-if { (eval echo configure:6350: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_api_serial=termios
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- tcl_cv_api_serial=no
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+tcl_cv_api_serial=no
fi
-rm -fr conftest*
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
-
if test $tcl_cv_api_serial = no ; then
if test "$cross_compiling" = yes; then
tcl_cv_api_serial=no
else
- cat > conftest.$ac_ext <<EOF
-#line 6367 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <termio.h>
@@ -6376,27 +12791,40 @@ int main() {
}
return 1;
}
-EOF
-if { (eval echo configure:6381: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_api_serial=termio
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- tcl_cv_api_serial=no
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+tcl_cv_api_serial=no
fi
-rm -fr conftest*
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
-
fi
if test $tcl_cv_api_serial = no ; then
if test "$cross_compiling" = yes; then
tcl_cv_api_serial=no
else
- cat > conftest.$ac_ext <<EOF
-#line 6399 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sgtty.h>
@@ -6409,27 +12837,40 @@ int main() {
}
return 1;
}
-EOF
-if { (eval echo configure:6414: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_api_serial=sgtty
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- tcl_cv_api_serial=no
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+tcl_cv_api_serial=no
fi
-rm -fr conftest*
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
-
fi
if test $tcl_cv_api_serial = no ; then
if test "$cross_compiling" = yes; then
tcl_cv_api_serial=no
else
- cat > conftest.$ac_ext <<EOF
-#line 6432 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <termios.h>
#include <errno.h>
@@ -6444,27 +12885,40 @@ int main() {
}
return 1;
}
-EOF
-if { (eval echo configure:6449: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_api_serial=termios
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- tcl_cv_api_serial=no
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+tcl_cv_api_serial=no
fi
-rm -fr conftest*
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
-
fi
if test $tcl_cv_api_serial = no; then
if test "$cross_compiling" = yes; then
tcl_cv_api_serial=no
else
- cat > conftest.$ac_ext <<EOF
-#line 6467 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <termio.h>
#include <errno.h>
@@ -6478,27 +12932,40 @@ int main() {
}
return 1;
}
-EOF
-if { (eval echo configure:6483: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_api_serial=termio
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- tcl_cv_api_serial=no
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+tcl_cv_api_serial=no
fi
-rm -fr conftest*
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
-
fi
if test $tcl_cv_api_serial = no; then
if test "$cross_compiling" = yes; then
tcl_cv_api_serial=none
else
- cat > conftest.$ac_ext <<EOF
-#line 6501 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sgtty.h>
#include <errno.h>
@@ -6513,35 +12980,48 @@ int main() {
}
return 1;
}
-EOF
-if { (eval echo configure:6518: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_api_serial=sgtty
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- tcl_cv_api_serial=none
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+tcl_cv_api_serial=none
fi
-rm -fr conftest*
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
-
fi
fi
-
-echo "$ac_t""$tcl_cv_api_serial" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_api_serial" >&5
+echo "${ECHO_T}$tcl_cv_api_serial" >&6
case $tcl_cv_api_serial in
- termios) cat >> confdefs.h <<\EOF
+ termios)
+cat >>confdefs.h <<\_ACEOF
#define USE_TERMIOS 1
-EOF
+_ACEOF
;;
- termio) cat >> confdefs.h <<\EOF
+ termio)
+cat >>confdefs.h <<\_ACEOF
#define USE_TERMIO 1
-EOF
+_ACEOF
;;
- sgtty) cat >> confdefs.h <<\EOF
+ sgtty)
+cat >>confdefs.h <<\_ACEOF
#define USE_SGTTY 1
-EOF
+_ACEOF
;;
esac
@@ -6556,71 +13036,102 @@ EOF
# special flag.
#--------------------------------------------------------------------
-echo $ac_n "checking for fd_set in sys/types""... $ac_c" 1>&6
-echo "configure:6561: checking for fd_set in sys/types" >&5
-if eval "test \"`echo '$''{'tcl_cv_type_fd_set'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for fd_set in sys/types" >&5
+echo $ECHO_N "checking for fd_set in sys/types... $ECHO_C" >&6
+if test "${tcl_cv_type_fd_set+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 6567 "configure"
-#include "confdefs.h"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/types.h>
-int main() {
+int
+main ()
+{
fd_set readMask, writeMask;
-; return 0; }
-EOF
-if { (eval echo configure:6574: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_type_fd_set=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_type_fd_set=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_type_fd_set=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_type_fd_set" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_type_fd_set" >&5
+echo "${ECHO_T}$tcl_cv_type_fd_set" >&6
tcl_ok=$tcl_cv_type_fd_set
if test $tcl_ok = no; then
- echo $ac_n "checking for fd_mask in sys/select""... $ac_c" 1>&6
-echo "configure:6590: checking for fd_mask in sys/select" >&5
-if eval "test \"`echo '$''{'tcl_cv_grep_fd_mask'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
-
- cat > conftest.$ac_ext <<EOF
-#line 6596 "configure"
-#include "confdefs.h"
+ echo "$as_me:$LINENO: checking for fd_mask in sys/select" >&5
+echo $ECHO_N "checking for fd_mask in sys/select... $ECHO_C" >&6
+if test "${tcl_cv_grep_fd_mask+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/select.h>
-EOF
+
+_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "fd_mask" >/dev/null 2>&1; then
- rm -rf conftest*
+ $EGREP "fd_mask" >/dev/null 2>&1; then
tcl_cv_grep_fd_mask=present
else
- rm -rf conftest*
tcl_cv_grep_fd_mask=missing
fi
rm -f conftest*
fi
-
-echo "$ac_t""$tcl_cv_grep_fd_mask" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_grep_fd_mask" >&5
+echo "${ECHO_T}$tcl_cv_grep_fd_mask" >&6
if test $tcl_cv_grep_fd_mask = present; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_SYS_SELECT_H 1
-EOF
+_ACEOF
tcl_ok=yes
fi
fi
if test $tcl_ok = no; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define NO_FD_SET 1
-EOF
+_ACEOF
fi
@@ -6628,308 +13139,449 @@ fi
# Find out all about time handling differences.
#------------------------------------------------------------------------------
-echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6
-echo "configure:6633: checking whether struct tm is in sys/time.h or time.h" >&5
-if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 6638 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <time.h>
-int main() {
-struct tm *tp; tp->tm_sec;
-; return 0; }
-EOF
-if { (eval echo configure:6646: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- ac_cv_struct_tm=time.h
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_struct_tm=sys/time.h
-fi
-rm -f conftest*
-fi
-echo "$ac_t""$ac_cv_struct_tm" 1>&6
-if test $ac_cv_struct_tm = sys/time.h; then
- cat >> confdefs.h <<\EOF
-#define TM_IN_SYS_TIME 1
-EOF
+for ac_header in sys/time.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
- for ac_hdr in sys/time.h
-do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:6671: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 6676 "configure"
-#include "confdefs.h"
-#include <$ac_hdr>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:6681: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to the tcl lists. ##
+## ------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
fi
-rm -f conftest*
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_hdr 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
fi
+
done
- echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
-echo "configure:6708: checking whether time.h and sys/time.h may both be included" >&5
-if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 6713 "configure"
-#include "confdefs.h"
+ echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5
+echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6
+if test "${ac_cv_header_time+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
-int main() {
-struct tm *tp;
-; return 0; }
-EOF
-if { (eval echo configure:6722: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+
+int
+main ()
+{
+if ((struct tm *) 0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
ac_cv_header_time=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_header_time=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_time=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$ac_cv_header_time" 1>&6
+echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5
+echo "${ECHO_T}$ac_cv_header_time" >&6
if test $ac_cv_header_time = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define TIME_WITH_SYS_TIME 1
-EOF
+_ACEOF
fi
- echo $ac_n "checking for tm_zone in struct tm""... $ac_c" 1>&6
-echo "configure:6743: checking for tm_zone in struct tm" >&5
-if eval "test \"`echo '$''{'ac_cv_struct_tm_zone'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 6748 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <$ac_cv_struct_tm>
-int main() {
-struct tm tm; tm.tm_zone;
-; return 0; }
-EOF
-if { (eval echo configure:6756: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- ac_cv_struct_tm_zone=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_struct_tm_zone=no
-fi
-rm -f conftest*
-fi
-echo "$ac_t""$ac_cv_struct_tm_zone" 1>&6
-if test "$ac_cv_struct_tm_zone" = yes; then
- cat >> confdefs.h <<\EOF
-#define HAVE_TM_ZONE 1
-EOF
-else
- echo $ac_n "checking for tzname""... $ac_c" 1>&6
-echo "configure:6776: checking for tzname" >&5
-if eval "test \"`echo '$''{'ac_cv_var_tzname'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 6781 "configure"
-#include "confdefs.h"
-#include <time.h>
-#ifndef tzname /* For SGI. */
-extern char *tzname[]; /* RS6000 and others reject char **tzname. */
-#endif
-int main() {
-atoi(*tzname);
-; return 0; }
-EOF
-if { (eval echo configure:6791: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- ac_cv_var_tzname=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_var_tzname=no
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$ac_cv_var_tzname" 1>&6
- if test $ac_cv_var_tzname = yes; then
- cat >> confdefs.h <<\EOF
-#define HAVE_TZNAME 1
-EOF
-
- fi
-fi
- for ac_func in gmtime_r localtime_r
+for ac_func in gmtime_r localtime_r mktime
do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6816: checking for $ac_func" >&5
-if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 6821 "configure"
-#include "confdefs.h"
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
choke me
#else
-$ac_func();
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:6844: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
-fi
-rm -f conftest*
-fi
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
fi
done
- echo $ac_n "checking tm_tzadj in struct tm""... $ac_c" 1>&6
-echo "configure:6870: checking tm_tzadj in struct tm" >&5
-if eval "test \"`echo '$''{'tcl_cv_member_tm_tzadj'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking tm_tzadj in struct tm" >&5
+echo $ECHO_N "checking tm_tzadj in struct tm... $ECHO_C" >&6
+if test "${tcl_cv_member_tm_tzadj+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 6876 "configure"
-#include "confdefs.h"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <time.h>
-int main() {
+int
+main ()
+{
struct tm tm; tm.tm_tzadj;
-; return 0; }
-EOF
-if { (eval echo configure:6883: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_member_tm_tzadj=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_member_tm_tzadj=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_member_tm_tzadj=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_member_tm_tzadj" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_member_tm_tzadj" >&5
+echo "${ECHO_T}$tcl_cv_member_tm_tzadj" >&6
if test $tcl_cv_member_tm_tzadj = yes ; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_TM_TZADJ 1
-EOF
+_ACEOF
fi
- echo $ac_n "checking tm_gmtoff in struct tm""... $ac_c" 1>&6
-echo "configure:6904: checking tm_gmtoff in struct tm" >&5
-if eval "test \"`echo '$''{'tcl_cv_member_tm_gmtoff'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking tm_gmtoff in struct tm" >&5
+echo $ECHO_N "checking tm_gmtoff in struct tm... $ECHO_C" >&6
+if test "${tcl_cv_member_tm_gmtoff+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 6910 "configure"
-#include "confdefs.h"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <time.h>
-int main() {
+int
+main ()
+{
struct tm tm; tm.tm_gmtoff;
-; return 0; }
-EOF
-if { (eval echo configure:6917: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_member_tm_gmtoff=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_member_tm_gmtoff=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_member_tm_gmtoff=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_member_tm_gmtoff" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_member_tm_gmtoff" >&5
+echo "${ECHO_T}$tcl_cv_member_tm_gmtoff" >&6
if test $tcl_cv_member_tm_gmtoff = yes ; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_TM_GMTOFF 1
-EOF
+_ACEOF
fi
@@ -6937,169 +13589,525 @@ EOF
# Its important to include time.h in this check, as some systems
# (like convex) have timezone functions, etc.
#
- echo $ac_n "checking long timezone variable""... $ac_c" 1>&6
-echo "configure:6942: checking long timezone variable" >&5
-if eval "test \"`echo '$''{'tcl_cv_timezone_long'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
-
- cat > conftest.$ac_ext <<EOF
-#line 6948 "configure"
-#include "confdefs.h"
+ echo "$as_me:$LINENO: checking long timezone variable" >&5
+echo $ECHO_N "checking long timezone variable... $ECHO_C" >&6
+if test "${tcl_cv_timezone_long+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <time.h>
-int main() {
+int
+main ()
+{
extern long timezone;
timezone += 1;
exit (0);
-; return 0; }
-EOF
-if { (eval echo configure:6957: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_timezone_long=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_timezone_long=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_timezone_long=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_timezone_long" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_timezone_long" >&5
+echo "${ECHO_T}$tcl_cv_timezone_long" >&6
if test $tcl_cv_timezone_long = yes ; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_TIMEZONE_VAR 1
-EOF
+_ACEOF
else
#
# On some systems (eg IRIX 6.2), timezone is a time_t and not a long.
#
- echo $ac_n "checking time_t timezone variable""... $ac_c" 1>&6
-echo "configure:6980: checking time_t timezone variable" >&5
-if eval "test \"`echo '$''{'tcl_cv_timezone_time'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
-
- cat > conftest.$ac_ext <<EOF
-#line 6986 "configure"
-#include "confdefs.h"
+ echo "$as_me:$LINENO: checking time_t timezone variable" >&5
+echo $ECHO_N "checking time_t timezone variable... $ECHO_C" >&6
+if test "${tcl_cv_timezone_time+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <time.h>
-int main() {
+int
+main ()
+{
extern time_t timezone;
timezone += 1;
exit (0);
-; return 0; }
-EOF
-if { (eval echo configure:6995: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_timezone_time=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_timezone_time=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_timezone_time=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_timezone_time" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_timezone_time" >&5
+echo "${ECHO_T}$tcl_cv_timezone_time" >&6
if test $tcl_cv_timezone_time = yes ; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_TIMEZONE_VAR 1
-EOF
+_ACEOF
fi
fi
#--------------------------------------------------------------------
-# Some systems (e.g., IRIX 4.0.5) lack the st_blksize field
-# in struct stat. But we might be able to use fstatfs instead.
+# Some systems (e.g., IRIX 4.0.5) lack some fields in struct stat. But
+# we might be able to use fstatfs instead. Some systems (OpenBSD?) also
+# lack blkcnt_t.
#--------------------------------------------------------------------
-echo $ac_n "checking for st_blksize in struct stat""... $ac_c" 1>&6
-echo "configure:7022: checking for st_blksize in struct stat" >&5
-if eval "test \"`echo '$''{'ac_cv_struct_st_blksize'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 7027 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-int main() {
-struct stat s; s.st_blksize;
-; return 0; }
-EOF
-if { (eval echo configure:7035: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- ac_cv_struct_st_blksize=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_struct_st_blksize=no
-fi
-rm -f conftest*
-fi
-echo "$ac_t""$ac_cv_struct_st_blksize" 1>&6
-if test $ac_cv_struct_st_blksize = yes; then
- cat >> confdefs.h <<\EOF
-#define HAVE_ST_BLKSIZE 1
-EOF
-
-fi
+echo "$as_me:$LINENO: checking for struct stat.st_blocks" >&5
+echo $ECHO_N "checking for struct stat.st_blocks... $ECHO_C" >&6
+if test "${ac_cv_member_struct_stat_st_blocks+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static struct stat ac_aggr;
+if (ac_aggr.st_blocks)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_member_struct_stat_st_blocks=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static struct stat ac_aggr;
+if (sizeof ac_aggr.st_blocks)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_member_struct_stat_st_blocks=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_member_struct_stat_st_blocks=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_member_struct_stat_st_blocks" >&5
+echo "${ECHO_T}$ac_cv_member_struct_stat_st_blocks" >&6
+if test $ac_cv_member_struct_stat_st_blocks = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_BLOCKS 1
+_ACEOF
+
+
+fi
+echo "$as_me:$LINENO: checking for struct stat.st_blksize" >&5
+echo $ECHO_N "checking for struct stat.st_blksize... $ECHO_C" >&6
+if test "${ac_cv_member_struct_stat_st_blksize+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static struct stat ac_aggr;
+if (ac_aggr.st_blksize)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_member_struct_stat_st_blksize=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static struct stat ac_aggr;
+if (sizeof ac_aggr.st_blksize)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_member_struct_stat_st_blksize=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_member_struct_stat_st_blksize=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_member_struct_stat_st_blksize" >&5
+echo "${ECHO_T}$ac_cv_member_struct_stat_st_blksize" >&6
+if test $ac_cv_member_struct_stat_st_blksize = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
+_ACEOF
+
+
+fi
+
+echo "$as_me:$LINENO: checking for blkcnt_t" >&5
+echo $ECHO_N "checking for blkcnt_t... $ECHO_C" >&6
+if test "${ac_cv_type_blkcnt_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((blkcnt_t *) 0)
+ return 0;
+if (sizeof (blkcnt_t))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_blkcnt_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_blkcnt_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_blkcnt_t" >&5
+echo "${ECHO_T}$ac_cv_type_blkcnt_t" >&6
+if test $ac_cv_type_blkcnt_t = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_BLKCNT_T 1
+_ACEOF
+
+
+fi
+
+echo "$as_me:$LINENO: checking for fstatfs" >&5
+echo $ECHO_N "checking for fstatfs... $ECHO_C" >&6
+if test "${ac_cv_func_fstatfs+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define fstatfs to an innocuous variant, in case <limits.h> declares fstatfs.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define fstatfs innocuous_fstatfs
-echo $ac_n "checking for fstatfs""... $ac_c" 1>&6
-echo "configure:7056: checking for fstatfs" >&5
-if eval "test \"`echo '$''{'ac_cv_func_fstatfs'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 7061 "configure"
-#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char fstatfs(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char fstatfs();
+ which can conflict with char fstatfs (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef fstatfs
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char fstatfs ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_fstatfs) || defined (__stub___fstatfs)
choke me
#else
-fstatfs();
+char (*f) () = fstatfs;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:7084: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_fstatfs=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_fstatfs=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'fstatfs`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+int
+main ()
+{
+return f != fstatfs;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_fstatfs=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_fstatfs=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_fstatfs" >&5
+echo "${ECHO_T}$ac_cv_func_fstatfs" >&6
+if test $ac_cv_func_fstatfs = yes; then
:
else
- echo "$ac_t""no" 1>&6
-cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define NO_FSTATFS 1
-EOF
+_ACEOF
fi
@@ -7108,41 +14116,87 @@ fi
# Some system have no memcmp or it does not work with 8 bit
# data, this checks it and add memcmp.o to LIBOBJS if needed
#--------------------------------------------------------------------
-echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6
-echo "configure:7113: checking for 8-bit clean memcmp" >&5
-if eval "test \"`echo '$''{'ac_cv_func_memcmp_clean'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+
+echo "$as_me:$LINENO: checking for working memcmp" >&5
+echo $ECHO_N "checking for working memcmp... $ECHO_C" >&6
+if test "${ac_cv_func_memcmp_working+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test "$cross_compiling" = yes; then
- ac_cv_func_memcmp_clean=no
-else
- cat > conftest.$ac_ext <<EOF
-#line 7121 "configure"
-#include "confdefs.h"
-
-main()
+ ac_cv_func_memcmp_working=no
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
{
- char c0 = 0x40, c1 = 0x80, c2 = 0x81;
- exit(memcmp(&c0, &c2, 1) < 0 && memcmp(&c1, &c2, 1) < 0 ? 0 : 1);
-}
-EOF
-if { (eval echo configure:7131: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
- ac_cv_func_memcmp_clean=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_func_memcmp_clean=no
-fi
-rm -fr conftest*
-fi
+ /* Some versions of memcmp are not 8-bit clean. */
+ char c0 = 0x40, c1 = 0x80, c2 = 0x81;
+ if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0)
+ exit (1);
-fi
+ /* The Next x86 OpenStep bug shows up only when comparing 16 bytes
+ or more and with at least one buffer not starting on a 4-byte boundary.
+ William Lewis provided this test program. */
+ {
+ char foo[21];
+ char bar[21];
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ char *a = foo + i;
+ char *b = bar + i;
+ strcpy (a, "--------01111111");
+ strcpy (b, "--------10000000");
+ if (memcmp (a, b, 16) >= 0)
+ exit (1);
+ }
+ exit (0);
+ }
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_memcmp_working=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_memcmp_working=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_memcmp_working" >&5
+echo "${ECHO_T}$ac_cv_func_memcmp_working" >&6
+test $ac_cv_func_memcmp_working = no && case $LIBOBJS in
+ "memcmp.$ac_objext" | \
+ *" memcmp.$ac_objext" | \
+ "memcmp.$ac_objext "* | \
+ *" memcmp.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS memcmp.$ac_objext" ;;
+esac
-echo "$ac_t""$ac_cv_func_memcmp_clean" 1>&6
-test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}"
#--------------------------------------------------------------------
@@ -7150,58 +14204,110 @@ test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}"
# have no memmove (we assume they have bcopy instead).
# {The replacement define is in compat/string.h}
#--------------------------------------------------------------------
-echo $ac_n "checking for memmove""... $ac_c" 1>&6
-echo "configure:7155: checking for memmove" >&5
-if eval "test \"`echo '$''{'ac_cv_func_memmove'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 7160 "configure"
-#include "confdefs.h"
+
+echo "$as_me:$LINENO: checking for memmove" >&5
+echo $ECHO_N "checking for memmove... $ECHO_C" >&6
+if test "${ac_cv_func_memmove+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define memmove to an innocuous variant, in case <limits.h> declares memmove.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define memmove innocuous_memmove
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char memmove(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char memmove();
+ which can conflict with char memmove (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+#undef memmove
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char memmove ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_memmove) || defined (__stub___memmove)
choke me
#else
-memmove();
+char (*f) () = memmove;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:7183: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_memmove=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_memmove=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'memmove`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+int
+main ()
+{
+return f != memmove;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_memmove=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_memmove=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_memmove" >&5
+echo "${ECHO_T}$ac_cv_func_memmove" >&6
+if test $ac_cv_func_memmove = yes; then
:
else
- echo "$ac_t""no" 1>&6
-cat >> confdefs.h <<\EOF
+
+
+cat >>confdefs.h <<\_ACEOF
#define NO_MEMMOVE 1
-EOF
- cat >> confdefs.h <<\EOF
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
#define NO_STRING_H 1
-EOF
+_ACEOF
fi
@@ -7210,45 +14316,167 @@ fi
# On some systems strstr is broken: it returns a pointer even
# even if the original string is empty.
#--------------------------------------------------------------------
-if test "x${ac_cv_func_strstr}" = "xyes"; then
- echo $ac_n "checking proper strstr implementation""... $ac_c" 1>&6
-echo "configure:7216: checking proper strstr implementation" >&5
-if eval "test \"`echo '$''{'tcl_cv_strstr_unbroken'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+
+
+ echo "$as_me:$LINENO: checking for strstr" >&5
+echo $ECHO_N "checking for strstr... $ECHO_C" >&6
+if test "${ac_cv_func_strstr+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- if test "$cross_compiling" = yes; then
- tcl_cv_strstr_unbroken=broken
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define strstr to an innocuous variant, in case <limits.h> declares strstr.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define strstr innocuous_strstr
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char strstr (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef strstr
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char strstr ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_strstr) || defined (__stub___strstr)
+choke me
+#else
+char (*f) () = strstr;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != strstr;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_strstr=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_strstr=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_strstr" >&5
+echo "${ECHO_T}$ac_cv_func_strstr" >&6
+if test $ac_cv_func_strstr = yes; then
+ tcl_ok=1
else
- cat > conftest.$ac_ext <<EOF
-#line 7225 "configure"
-#include "confdefs.h"
+ tcl_ok=0
+fi
- extern int strstr();
- int main()
- {
- exit(strstr("\0test", "test") ? 1 : 0);
- }
-EOF
-if { (eval echo configure:7234: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
+ if test "$tcl_ok" = 1; then
+ echo "$as_me:$LINENO: checking proper strstr implementation" >&5
+echo $ECHO_N "checking proper strstr implementation... $ECHO_C" >&6
+if test "${tcl_cv_strstr_unbroken+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ tcl_cv_strstr_unbroken=unknown
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+int main() {
+ extern int strstr();
+ exit(strstr("\0test", "test") ? 1 : 0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_strstr_unbroken=ok
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- tcl_cv_strstr_unbroken=broken
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+tcl_cv_strstr_unbroken=broken
fi
-rm -fr conftest*
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
-
fi
+echo "$as_me:$LINENO: result: $tcl_cv_strstr_unbroken" >&5
+echo "${ECHO_T}$tcl_cv_strstr_unbroken" >&6
+ if test "$tcl_cv_strstr_unbroken" = "ok"; then
+ tcl_ok=1
+ else
+ tcl_ok=0
+ fi
+ fi
+ if test "$tcl_ok" = 0; then
+ case $LIBOBJS in
+ "strstr.$ac_objext" | \
+ *" strstr.$ac_objext" | \
+ "strstr.$ac_objext "* | \
+ *" strstr.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strstr.$ac_objext" ;;
+esac
-echo "$ac_t""$tcl_cv_strstr_unbroken" 1>&6
- if test $tcl_cv_strstr_unbroken = broken; then
- LIBOBJS="$LIBOBJS strstr.o"
+ USE_COMPAT=1
fi
-fi
+
#--------------------------------------------------------------------
# Check for strtoul function. This is tricky because under some
@@ -7256,208 +14484,334 @@ fi
# pointer for the string "0".
#--------------------------------------------------------------------
-echo $ac_n "checking for strtoul""... $ac_c" 1>&6
-echo "configure:7261: checking for strtoul" >&5
-if eval "test \"`echo '$''{'ac_cv_func_strtoul'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+
+ echo "$as_me:$LINENO: checking for strtoul" >&5
+echo $ECHO_N "checking for strtoul... $ECHO_C" >&6
+if test "${ac_cv_func_strtoul+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 7266 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define strtoul to an innocuous variant, in case <limits.h> declares strtoul.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define strtoul innocuous_strtoul
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char strtoul(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char strtoul();
+ which can conflict with char strtoul (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+#undef strtoul
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char strtoul ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_strtoul) || defined (__stub___strtoul)
choke me
#else
-strtoul();
+char (*f) () = strtoul;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:7289: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_strtoul=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_strtoul=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'strtoul`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+int
+main ()
+{
+return f != strtoul;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_strtoul=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_strtoul=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_strtoul" >&5
+echo "${ECHO_T}$ac_cv_func_strtoul" >&6
+if test $ac_cv_func_strtoul = yes; then
tcl_ok=1
else
- echo "$ac_t""no" 1>&6
-tcl_ok=0
+ tcl_ok=0
fi
-if test $tcl_ok = 1; then
- echo $ac_n "checking proper strtoul implementation""... $ac_c" 1>&6
-echo "configure:7311: checking proper strtoul implementation" >&5
-if eval "test \"`echo '$''{'tcl_cv_strtoul_unbroken'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
-
- if test "$cross_compiling" = yes; then
- tcl_cv_strtoul_unbroken=broken
-else
- cat > conftest.$ac_ext <<EOF
-#line 7320 "configure"
-#include "confdefs.h"
-
- extern int strtoul();
- int main()
- {
- char *string = "0";
- char *term;
- int value;
- value = strtoul(string, &term, 0);
- if ((value != 0) || (term != (string+1))) {
- exit(1);
- }
- exit(0);
- }
-EOF
-if { (eval echo configure:7336: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
- tcl_cv_strtoul_unbroken=ok
+ if test "$tcl_ok" = 1; then
+ echo "$as_me:$LINENO: checking proper strtoul implementation" >&5
+echo $ECHO_N "checking proper strtoul implementation... $ECHO_C" >&6
+if test "${tcl_cv_strtoul_unbroken+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- tcl_cv_strtoul_unbroken=broken
-fi
-rm -fr conftest*
-fi
-
-fi
+ if test "$cross_compiling" = yes; then
+ tcl_cv_strtoul_unbroken=unknown
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+int main() {
+ extern int strtoul();
+ char *term, *string = "0";
+ exit(strtoul(string,&term,0) != 0 || term != string+1);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ tcl_cv_strtoul_unbroken=ok
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+tcl_cv_strtoul_unbroken=broken
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_strtoul_unbroken" >&5
+echo "${ECHO_T}$tcl_cv_strtoul_unbroken" >&6
+ if test "$tcl_cv_strtoul_unbroken" = "ok"; then
+ tcl_ok=1
+ else
+ tcl_ok=0
+ fi
+ fi
+ if test "$tcl_ok" = 0; then
+ case $LIBOBJS in
+ "strtoul.$ac_objext" | \
+ *" strtoul.$ac_objext" | \
+ "strtoul.$ac_objext "* | \
+ *" strtoul.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strtoul.$ac_objext" ;;
+esac
-echo "$ac_t""$tcl_cv_strtoul_unbroken" 1>&6
- if test $tcl_cv_strtoul_unbroken = broken; then
- tcl_ok=0
+ USE_COMPAT=1
fi
-fi
-if test $tcl_ok = 0; then
- LIBOBJS="$LIBOBJS strtoul.o"
-fi
+
#--------------------------------------------------------------------
# Check for the strtod function. This is tricky because in some
# versions of Linux strtod mis-parses strings starting with "+".
#--------------------------------------------------------------------
-echo $ac_n "checking for strtod""... $ac_c" 1>&6
-echo "configure:7365: checking for strtod" >&5
-if eval "test \"`echo '$''{'ac_cv_func_strtod'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+
+ echo "$as_me:$LINENO: checking for strtod" >&5
+echo $ECHO_N "checking for strtod... $ECHO_C" >&6
+if test "${ac_cv_func_strtod+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 7370 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define strtod to an innocuous variant, in case <limits.h> declares strtod.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define strtod innocuous_strtod
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char strtod(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char strtod();
+ which can conflict with char strtod (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+#undef strtod
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char strtod ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_strtod) || defined (__stub___strtod)
choke me
#else
-strtod();
+char (*f) () = strtod;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:7393: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_strtod=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_strtod=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'strtod`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+int
+main ()
+{
+return f != strtod;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_strtod=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_strtod=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_strtod" >&5
+echo "${ECHO_T}$ac_cv_func_strtod" >&6
+if test $ac_cv_func_strtod = yes; then
tcl_ok=1
else
- echo "$ac_t""no" 1>&6
-tcl_ok=0
+ tcl_ok=0
fi
-if test $tcl_ok = 1; then
- echo $ac_n "checking proper strtod implementation""... $ac_c" 1>&6
-echo "configure:7415: checking proper strtod implementation" >&5
-if eval "test \"`echo '$''{'tcl_cv_strtod_unbroken'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
-
- if test "$cross_compiling" = yes; then
- tcl_cv_strtod_unbroken=broken
+ if test "$tcl_ok" = 1; then
+ echo "$as_me:$LINENO: checking proper strtod implementation" >&5
+echo $ECHO_N "checking proper strtod implementation... $ECHO_C" >&6
+if test "${tcl_cv_strtod_unbroken+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 7424 "configure"
-#include "confdefs.h"
-
- extern double strtod();
- int main()
- {
- char *string = " +69";
- char *term;
- double value;
- value = strtod(string, &term);
- if ((value != 69) || (term != (string+4))) {
- exit(1);
- }
- exit(0);
- }
-EOF
-if { (eval echo configure:7440: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
- tcl_cv_strtod_unbroken=ok
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- tcl_cv_strtod_unbroken=broken
-fi
-rm -fr conftest*
-fi
-
-fi
+ if test "$cross_compiling" = yes; then
+ tcl_cv_strtod_unbroken=unknown
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+int main() {
+ extern double strtod();
+ char *term, *string = " +69";
+ exit(strtod(string,&term) != 69 || term != string+4);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ tcl_cv_strtod_unbroken=ok
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+tcl_cv_strtod_unbroken=broken
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_strtod_unbroken" >&5
+echo "${ECHO_T}$tcl_cv_strtod_unbroken" >&6
+ if test "$tcl_cv_strtod_unbroken" = "ok"; then
+ tcl_ok=1
+ else
+ tcl_ok=0
+ fi
+ fi
+ if test "$tcl_ok" = 0; then
+ case $LIBOBJS in
+ "strtod.$ac_objext" | \
+ *" strtod.$ac_objext" | \
+ "strtod.$ac_objext "* | \
+ *" strtod.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strtod.$ac_objext" ;;
+esac
-echo "$ac_t""$tcl_cv_strtod_unbroken" 1>&6
- if test $tcl_cv_strtod_unbroken = broken; then
- tcl_ok=0
+ USE_COMPAT=1
fi
-fi
-if test $tcl_ok = 0; then
- LIBOBJS="$LIBOBJS strtod.o"
-fi
+
#--------------------------------------------------------------------
# Under Solaris 2.4, strtod returns the wrong value for the
@@ -7467,68 +14821,118 @@ fi
#--------------------------------------------------------------------
- echo $ac_n "checking for strtod""... $ac_c" 1>&6
-echo "configure:7472: checking for strtod" >&5
-if eval "test \"`echo '$''{'ac_cv_func_strtod'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for strtod" >&5
+echo $ECHO_N "checking for strtod... $ECHO_C" >&6
+if test "${ac_cv_func_strtod+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 7477 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define strtod to an innocuous variant, in case <limits.h> declares strtod.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define strtod innocuous_strtod
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char strtod(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char strtod();
+ which can conflict with char strtod (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef strtod
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char strtod ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_strtod) || defined (__stub___strtod)
choke me
#else
-strtod();
+char (*f) () = strtod;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:7500: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_strtod=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_strtod=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'strtod`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+int
+main ()
+{
+return f != strtod;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_strtod=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_strtod=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_strtod" >&5
+echo "${ECHO_T}$ac_cv_func_strtod" >&6
+if test $ac_cv_func_strtod = yes; then
tcl_strtod=1
else
- echo "$ac_t""no" 1>&6
-tcl_strtod=0
+ tcl_strtod=0
fi
if test "$tcl_strtod" = 1; then
- echo $ac_n "checking for Solaris2.4/Tru64 strtod bugs""... $ac_c" 1>&6
-echo "configure:7522: checking for Solaris2.4/Tru64 strtod bugs" >&5
-if eval "test \"`echo '$''{'tcl_cv_strtod_buggy'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for Solaris2.4/Tru64 strtod bugs" >&5
+echo $ECHO_N "checking for Solaris2.4/Tru64 strtod bugs... $ECHO_C" >&6
+if test "${tcl_cv_strtod_buggy+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
+
if test "$cross_compiling" = yes; then
tcl_cv_strtod_buggy=buggy
else
- cat > conftest.$ac_ext <<EOF
-#line 7531 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
extern double strtod();
int main() {
@@ -7549,27 +14953,46 @@ else
}
exit(0);
}
-EOF
-if { (eval echo configure:7554: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_strtod_buggy=ok
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- tcl_cv_strtod_buggy=buggy
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+tcl_cv_strtod_buggy=buggy
fi
-rm -fr conftest*
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
-
fi
-
-echo "$ac_t""$tcl_cv_strtod_buggy" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_strtod_buggy" >&5
+echo "${ECHO_T}$tcl_cv_strtod_buggy" >&6
if test "$tcl_cv_strtod_buggy" = buggy; then
- LIBOBJS="$LIBOBJS fixstrtod.o"
- cat >> confdefs.h <<\EOF
+ case $LIBOBJS in
+ "fixstrtod.$ac_objext" | \
+ *" fixstrtod.$ac_objext" | \
+ "fixstrtod.$ac_objext "* | \
+ *" fixstrtod.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS fixstrtod.$ac_objext" ;;
+esac
+
+ USE_COMPAT=1
+
+cat >>confdefs.h <<\_ACEOF
#define strtod fixstrtod
-EOF
+_ACEOF
fi
fi
@@ -7580,281 +15003,581 @@ EOF
# they don't exist.
#--------------------------------------------------------------------
-echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:7585: checking for ANSI C header files" >&5
-if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 7590 "configure"
-#include "confdefs.h"
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7598: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- ac_cv_header_stdc=yes
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
-cat > conftest.$ac_ext <<EOF
-#line 7615 "configure"
-#include "confdefs.h"
-#include <string.h>
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "memchr" >/dev/null 2>&1; then
- :
+echo "$as_me:$LINENO: checking for mode_t" >&5
+echo $ECHO_N "checking for mode_t... $ECHO_C" >&6
+if test "${ac_cv_type_mode_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((mode_t *) 0)
+ return 0;
+if (sizeof (mode_t))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_mode_t=yes
else
- rm -rf conftest*
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
-cat > conftest.$ac_ext <<EOF
-#line 7633 "configure"
-#include "confdefs.h"
-#include <stdlib.h>
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "free" >/dev/null 2>&1; then
- :
-else
- rm -rf conftest*
- ac_cv_header_stdc=no
+ac_cv_type_mode_t=no
fi
-rm -f conftest*
-
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
-if test "$cross_compiling" = yes; then
+echo "$as_me:$LINENO: result: $ac_cv_type_mode_t" >&5
+echo "${ECHO_T}$ac_cv_type_mode_t" >&6
+if test $ac_cv_type_mode_t = yes; then
:
else
- cat > conftest.$ac_ext <<EOF
-#line 7654 "configure"
-#include "confdefs.h"
-#include <ctype.h>
-#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int main () { int i; for (i = 0; i < 256; i++)
-if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
-exit (0); }
-
-EOF
-if { (eval echo configure:7665: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
- :
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_header_stdc=no
-fi
-rm -fr conftest*
-fi
-fi
-fi
-
-echo "$ac_t""$ac_cv_header_stdc" 1>&6
-if test $ac_cv_header_stdc = yes; then
- cat >> confdefs.h <<\EOF
-#define STDC_HEADERS 1
-EOF
+cat >>confdefs.h <<_ACEOF
+#define mode_t int
+_ACEOF
fi
-echo $ac_n "checking for mode_t""... $ac_c" 1>&6
-echo "configure:7689: checking for mode_t" >&5
-if eval "test \"`echo '$''{'ac_cv_type_mode_t'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for pid_t" >&5
+echo $ECHO_N "checking for pid_t... $ECHO_C" >&6
+if test "${ac_cv_type_pid_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 7694 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#if STDC_HEADERS
-#include <stdlib.h>
-#include <stddef.h>
-#endif
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "(^|[^a-zA-Z_0-9])mode_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
- rm -rf conftest*
- ac_cv_type_mode_t=yes
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((pid_t *) 0)
+ return 0;
+if (sizeof (pid_t))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_pid_t=yes
else
- rm -rf conftest*
- ac_cv_type_mode_t=no
-fi
-rm -f conftest*
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_cv_type_pid_t=no
fi
-echo "$ac_t""$ac_cv_type_mode_t" 1>&6
-if test $ac_cv_type_mode_t = no; then
- cat >> confdefs.h <<\EOF
-#define mode_t int
-EOF
-
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo $ac_n "checking for pid_t""... $ac_c" 1>&6
-echo "configure:7722: checking for pid_t" >&5
-if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 7727 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#if STDC_HEADERS
-#include <stdlib.h>
-#include <stddef.h>
-#endif
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "(^|[^a-zA-Z_0-9])pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
- rm -rf conftest*
- ac_cv_type_pid_t=yes
+echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5
+echo "${ECHO_T}$ac_cv_type_pid_t" >&6
+if test $ac_cv_type_pid_t = yes; then
+ :
else
- rm -rf conftest*
- ac_cv_type_pid_t=no
-fi
-rm -f conftest*
-fi
-echo "$ac_t""$ac_cv_type_pid_t" 1>&6
-if test $ac_cv_type_pid_t = no; then
- cat >> confdefs.h <<\EOF
+cat >>confdefs.h <<_ACEOF
#define pid_t int
-EOF
+_ACEOF
fi
-echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:7755: checking for size_t" >&5
-if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6
+if test "${ac_cv_type_size_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 7760 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#if STDC_HEADERS
-#include <stdlib.h>
-#include <stddef.h>
-#endif
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
- rm -rf conftest*
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((size_t *) 0)
+ return 0;
+if (sizeof (size_t))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
ac_cv_type_size_t=yes
else
- rm -rf conftest*
- ac_cv_type_size_t=no
-fi
-rm -f conftest*
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_cv_type_size_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-echo "$ac_t""$ac_cv_type_size_t" 1>&6
-if test $ac_cv_type_size_t = no; then
- cat >> confdefs.h <<\EOF
+echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6
+if test $ac_cv_type_size_t = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
#define size_t unsigned
-EOF
+_ACEOF
fi
-echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6
-echo "configure:7788: checking for uid_t in sys/types.h" >&5
-if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for uid_t in sys/types.h" >&5
+echo $ECHO_N "checking for uid_t in sys/types.h... $ECHO_C" >&6
+if test "${ac_cv_type_uid_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 7793 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/types.h>
-EOF
+
+_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "uid_t" >/dev/null 2>&1; then
- rm -rf conftest*
+ $EGREP "uid_t" >/dev/null 2>&1; then
ac_cv_type_uid_t=yes
else
- rm -rf conftest*
ac_cv_type_uid_t=no
fi
rm -f conftest*
fi
-
-echo "$ac_t""$ac_cv_type_uid_t" 1>&6
+echo "$as_me:$LINENO: result: $ac_cv_type_uid_t" >&5
+echo "${ECHO_T}$ac_cv_type_uid_t" >&6
if test $ac_cv_type_uid_t = no; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define uid_t int
-EOF
+_ACEOF
+
- cat >> confdefs.h <<\EOF
+cat >>confdefs.h <<\_ACEOF
#define gid_t int
-EOF
+_ACEOF
fi
-echo $ac_n "checking for socklen_t""... $ac_c" 1>&6
-echo "configure:7823: checking for socklen_t" >&5
-if eval "test \"`echo '$''{'ac_cv_type_socklen_t'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for socklen_t" >&5
+echo $ECHO_N "checking for socklen_t... $ECHO_C" >&6
+if test "${tcl_cv_type_socklen_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 7829 "configure"
-#include "confdefs.h"
- #include <sys/types.h>
- #include <sys/socket.h>
- #if STDC_HEADERS
- #include <stdlib.h>
- #include <stddef.h>
- #endif
-
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "(^|[^a-zA-Z_0-9])socklen_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
- rm -rf conftest*
- ac_cv_type_socklen_t=yes
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+ #include <sys/types.h>
+ #include <sys/socket.h>
+
+int
+main ()
+{
+
+ socklen_t foo;
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ tcl_cv_type_socklen_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_type_socklen_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_type_socklen_t" >&5
+echo "${ECHO_T}$tcl_cv_type_socklen_t" >&6
+if test $tcl_cv_type_socklen_t = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define socklen_t int
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for intptr_t" >&5
+echo $ECHO_N "checking for intptr_t... $ECHO_C" >&6
+if test "${ac_cv_type_intptr_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((intptr_t *) 0)
+ return 0;
+if (sizeof (intptr_t))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_intptr_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_intptr_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_intptr_t" >&5
+echo "${ECHO_T}$ac_cv_type_intptr_t" >&6
+if test $ac_cv_type_intptr_t = yes; then
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_INTPTR_T 1
+_ACEOF
+
+else
+
+ echo "$as_me:$LINENO: checking for pointer-size signed integer type" >&5
+echo $ECHO_N "checking for pointer-size signed integer type... $ECHO_C" >&6
+if test "${tcl_cv_intptr_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ for tcl_cv_intptr_t in "int" "long" "long long" none; do
+ if test "$tcl_cv_intptr_t" != none; then
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_intptr_t))];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ tcl_ok=yes
else
- rm -rf conftest*
- ac_cv_type_socklen_t=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_ok=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$tcl_ok" = yes && break; fi
+ done
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_intptr_t" >&5
+echo "${ECHO_T}$tcl_cv_intptr_t" >&6
+ if test "$tcl_cv_intptr_t" != none; then
+
+cat >>confdefs.h <<_ACEOF
+#define intptr_t $tcl_cv_intptr_t
+_ACEOF
+
+ fi
fi
-echo "$ac_t""$ac_cv_type_socklen_t" 1>&6
-if test $ac_cv_type_socklen_t = no; then
- cat >> confdefs.h <<\EOF
-#define socklen_t unsigned
-EOF
+echo "$as_me:$LINENO: checking for uintptr_t" >&5
+echo $ECHO_N "checking for uintptr_t... $ECHO_C" >&6
+if test "${ac_cv_type_uintptr_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((uintptr_t *) 0)
+ return 0;
+if (sizeof (uintptr_t))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_uintptr_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_uintptr_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_uintptr_t" >&5
+echo "${ECHO_T}$ac_cv_type_uintptr_t" >&6
+if test $ac_cv_type_uintptr_t = yes; then
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_UINTPTR_T 1
+_ACEOF
+
+else
+
+ echo "$as_me:$LINENO: checking for pointer-size unsigned integer type" >&5
+echo $ECHO_N "checking for pointer-size unsigned integer type... $ECHO_C" >&6
+if test "${tcl_cv_uintptr_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \
+ none; do
+ if test "$tcl_cv_uintptr_t" != none; then
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_uintptr_t))];
+test_array [0] = 0
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ tcl_ok=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_ok=no
fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$tcl_ok" = yes && break; fi
+ done
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_uintptr_t" >&5
+echo "${ECHO_T}$tcl_cv_uintptr_t" >&6
+ if test "$tcl_cv_uintptr_t" != none; then
+
+cat >>confdefs.h <<_ACEOF
+#define uintptr_t $tcl_cv_uintptr_t
+_ACEOF
+
+ fi
+
+fi
+
#--------------------------------------------------------------------
# If a system doesn't have an opendir function (man, that's old!)
@@ -7863,55 +15586,103 @@ fi
# provided. This version only works with V7-style directories.
#--------------------------------------------------------------------
-echo $ac_n "checking for opendir""... $ac_c" 1>&6
-echo "configure:7868: checking for opendir" >&5
-if eval "test \"`echo '$''{'ac_cv_func_opendir'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 7873 "configure"
-#include "confdefs.h"
+echo "$as_me:$LINENO: checking for opendir" >&5
+echo $ECHO_N "checking for opendir... $ECHO_C" >&6
+if test "${ac_cv_func_opendir+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define opendir to an innocuous variant, in case <limits.h> declares opendir.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define opendir innocuous_opendir
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char opendir(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char opendir();
+ which can conflict with char opendir (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef opendir
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_opendir) || defined (__stub___opendir)
choke me
#else
-opendir();
+char (*f) () = opendir;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:7896: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_opendir=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_opendir=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'opendir`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+int
+main ()
+{
+return f != opendir;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_opendir=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_opendir=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_opendir" >&5
+echo "${ECHO_T}$ac_cv_func_opendir" >&6
+if test $ac_cv_func_opendir = yes; then
:
else
- echo "$ac_t""no" 1>&6
-cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define USE_DIRENT2_H 1
-EOF
+_ACEOF
fi
@@ -7924,42 +15695,71 @@ fi
# the trick.
#--------------------------------------------------------------------
-echo $ac_n "checking union wait""... $ac_c" 1>&6
-echo "configure:7929: checking union wait" >&5
-if eval "test \"`echo '$''{'tcl_cv_union_wait'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking union wait" >&5
+echo $ECHO_N "checking union wait... $ECHO_C" >&6
+if test "${tcl_cv_union_wait+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 7935 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
#include <sys/wait.h>
-int main() {
+int
+main ()
+{
union wait x;
WIFEXITED(x); /* Generates compiler error if WIFEXITED
* uses an int. */
-
-; return 0; }
-EOF
-if { (eval echo configure:7947: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_union_wait=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_union_wait=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_union_wait=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_union_wait" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_union_wait" >&5
+echo "${ECHO_T}$tcl_cv_union_wait" >&6
if test $tcl_cv_union_wait = no; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define NO_UNION_WAIT 1
-EOF
+_ACEOF
fi
@@ -7969,143 +15769,256 @@ fi
# under Sequent Dynix it's in -linet.
#--------------------------------------------------------------------
-echo $ac_n "checking for strncasecmp""... $ac_c" 1>&6
-echo "configure:7974: checking for strncasecmp" >&5
-if eval "test \"`echo '$''{'ac_cv_func_strncasecmp'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 7979 "configure"
-#include "confdefs.h"
+echo "$as_me:$LINENO: checking for strncasecmp" >&5
+echo $ECHO_N "checking for strncasecmp... $ECHO_C" >&6
+if test "${ac_cv_func_strncasecmp+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define strncasecmp to an innocuous variant, in case <limits.h> declares strncasecmp.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define strncasecmp innocuous_strncasecmp
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char strncasecmp(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char strncasecmp();
+ which can conflict with char strncasecmp (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+#undef strncasecmp
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char strncasecmp ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_strncasecmp) || defined (__stub___strncasecmp)
choke me
#else
-strncasecmp();
+char (*f) () = strncasecmp;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:8002: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_strncasecmp=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_strncasecmp=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'strncasecmp`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+int
+main ()
+{
+return f != strncasecmp;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_strncasecmp=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_strncasecmp=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_strncasecmp" >&5
+echo "${ECHO_T}$ac_cv_func_strncasecmp" >&6
+if test $ac_cv_func_strncasecmp = yes; then
tcl_ok=1
else
- echo "$ac_t""no" 1>&6
-tcl_ok=0
+ tcl_ok=0
fi
if test "$tcl_ok" = 0; then
- echo $ac_n "checking for strncasecmp in -lsocket""... $ac_c" 1>&6
-echo "configure:8024: checking for strncasecmp in -lsocket" >&5
-ac_lib_var=`echo socket'_'strncasecmp | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for strncasecmp in -lsocket" >&5
+echo $ECHO_N "checking for strncasecmp in -lsocket... $ECHO_C" >&6
+if test "${ac_cv_lib_socket_strncasecmp+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- ac_save_LIBS="$LIBS"
+ ac_check_lib_save_LIBS=$LIBS
LIBS="-lsocket $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 8032 "configure"
-#include "confdefs.h"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char strncasecmp();
-
-int main() {
-strncasecmp()
-; return 0; }
-EOF
-if { (eval echo configure:8043: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+ builtin and then its argument prototype would still apply. */
+char strncasecmp ();
+int
+main ()
+{
+strncasecmp ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_socket_strncasecmp=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_socket_strncasecmp=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_socket_strncasecmp" >&5
+echo "${ECHO_T}$ac_cv_lib_socket_strncasecmp" >&6
+if test $ac_cv_lib_socket_strncasecmp = yes; then
tcl_ok=1
else
- echo "$ac_t""no" 1>&6
-tcl_ok=0
+ tcl_ok=0
fi
fi
if test "$tcl_ok" = 0; then
- echo $ac_n "checking for strncasecmp in -linet""... $ac_c" 1>&6
-echo "configure:8067: checking for strncasecmp in -linet" >&5
-ac_lib_var=`echo inet'_'strncasecmp | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for strncasecmp in -linet" >&5
+echo $ECHO_N "checking for strncasecmp in -linet... $ECHO_C" >&6
+if test "${ac_cv_lib_inet_strncasecmp+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- ac_save_LIBS="$LIBS"
+ ac_check_lib_save_LIBS=$LIBS
LIBS="-linet $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 8075 "configure"
-#include "confdefs.h"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char strncasecmp();
-
-int main() {
-strncasecmp()
-; return 0; }
-EOF
-if { (eval echo configure:8086: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+ builtin and then its argument prototype would still apply. */
+char strncasecmp ();
+int
+main ()
+{
+strncasecmp ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_inet_strncasecmp=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_inet_strncasecmp=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_inet_strncasecmp" >&5
+echo "${ECHO_T}$ac_cv_lib_inet_strncasecmp" >&6
+if test $ac_cv_lib_inet_strncasecmp = yes; then
tcl_ok=1
else
- echo "$ac_t""no" 1>&6
-tcl_ok=0
+ tcl_ok=0
fi
fi
if test "$tcl_ok" = 0; then
- LIBOBJS="$LIBOBJS strncasecmp.o"
+ case $LIBOBJS in
+ "strncasecmp.$ac_objext" | \
+ *" strncasecmp.$ac_objext" | \
+ "strncasecmp.$ac_objext "* | \
+ *" strncasecmp.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strncasecmp.$ac_objext" ;;
+esac
+
+ USE_COMPAT=1
fi
#--------------------------------------------------------------------
@@ -8119,139 +16032,238 @@ fi
# declare it.
#--------------------------------------------------------------------
-echo $ac_n "checking for BSDgettimeofday""... $ac_c" 1>&6
-echo "configure:8124: checking for BSDgettimeofday" >&5
-if eval "test \"`echo '$''{'ac_cv_func_BSDgettimeofday'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 8129 "configure"
-#include "confdefs.h"
+echo "$as_me:$LINENO: checking for BSDgettimeofday" >&5
+echo $ECHO_N "checking for BSDgettimeofday... $ECHO_C" >&6
+if test "${ac_cv_func_BSDgettimeofday+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define BSDgettimeofday to an innocuous variant, in case <limits.h> declares BSDgettimeofday.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define BSDgettimeofday innocuous_BSDgettimeofday
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char BSDgettimeofday(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char BSDgettimeofday();
+ which can conflict with char BSDgettimeofday (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+#undef BSDgettimeofday
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char BSDgettimeofday ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_BSDgettimeofday) || defined (__stub___BSDgettimeofday)
choke me
#else
-BSDgettimeofday();
+char (*f) () = BSDgettimeofday;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:8152: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_BSDgettimeofday=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_BSDgettimeofday=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'BSDgettimeofday`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- cat >> confdefs.h <<\EOF
+int
+main ()
+{
+return f != BSDgettimeofday;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_BSDgettimeofday=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_BSDgettimeofday=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_BSDgettimeofday" >&5
+echo "${ECHO_T}$ac_cv_func_BSDgettimeofday" >&6
+if test $ac_cv_func_BSDgettimeofday = yes; then
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_BSDGETTIMEOFDAY 1
-EOF
+_ACEOF
else
- echo "$ac_t""no" 1>&6
- echo $ac_n "checking for gettimeofday""... $ac_c" 1>&6
-echo "configure:8174: checking for gettimeofday" >&5
-if eval "test \"`echo '$''{'ac_cv_func_gettimeofday'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking for gettimeofday" >&5
+echo $ECHO_N "checking for gettimeofday... $ECHO_C" >&6
+if test "${ac_cv_func_gettimeofday+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 8179 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define gettimeofday to an innocuous variant, in case <limits.h> declares gettimeofday.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define gettimeofday innocuous_gettimeofday
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char gettimeofday(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char gettimeofday();
+ which can conflict with char gettimeofday (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef gettimeofday
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gettimeofday ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_gettimeofday) || defined (__stub___gettimeofday)
choke me
#else
-gettimeofday();
+char (*f) () = gettimeofday;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:8202: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_gettimeofday=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_gettimeofday=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'gettimeofday`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+int
+main ()
+{
+return f != gettimeofday;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_gettimeofday=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_gettimeofday=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_gettimeofday" >&5
+echo "${ECHO_T}$ac_cv_func_gettimeofday" >&6
+if test $ac_cv_func_gettimeofday = yes; then
:
else
- echo "$ac_t""no" 1>&6
-cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define NO_GETTOD 1
-EOF
+_ACEOF
fi
fi
-echo $ac_n "checking for gettimeofday declaration""... $ac_c" 1>&6
-echo "configure:8229: checking for gettimeofday declaration" >&5
-if eval "test \"`echo '$''{'tcl_cv_grep_gettimeofday'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for gettimeofday declaration" >&5
+echo $ECHO_N "checking for gettimeofday declaration... $ECHO_C" >&6
+if test "${tcl_cv_grep_gettimeofday+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 8235 "configure"
-#include "confdefs.h"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/time.h>
-EOF
+
+_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "gettimeofday" >/dev/null 2>&1; then
- rm -rf conftest*
+ $EGREP "gettimeofday" >/dev/null 2>&1; then
tcl_cv_grep_gettimeofday=present
else
- rm -rf conftest*
tcl_cv_grep_gettimeofday=missing
fi
rm -f conftest*
fi
-
-echo "$ac_t""$tcl_cv_grep_gettimeofday" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_grep_gettimeofday" >&5
+echo "${ECHO_T}$tcl_cv_grep_gettimeofday" >&6
if test $tcl_cv_grep_gettimeofday = missing ; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define GETTOD_NOT_DECLARED 1
-EOF
+_ACEOF
fi
@@ -8261,103 +16273,131 @@ fi
# properly generate sign-extended ints from character values.
#--------------------------------------------------------------------
-echo $ac_n "checking whether char is unsigned""... $ac_c" 1>&6
-echo "configure:8266: checking whether char is unsigned" >&5
-if eval "test \"`echo '$''{'ac_cv_c_char_unsigned'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$GCC" = yes; then
- # GCC predefines this symbol on systems where it applies.
-cat > conftest.$ac_ext <<EOF
-#line 8273 "configure"
-#include "confdefs.h"
-#ifdef __CHAR_UNSIGNED__
- yes
-#endif
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "yes" >/dev/null 2>&1; then
- rm -rf conftest*
- ac_cv_c_char_unsigned=yes
-else
- rm -rf conftest*
- ac_cv_c_char_unsigned=no
-fi
-rm -f conftest*
+echo "$as_me:$LINENO: checking whether char is unsigned" >&5
+echo $ECHO_N "checking whether char is unsigned... $ECHO_C" >&6
+if test "${ac_cv_c_char_unsigned+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((char) -1) < 0)];
+test_array [0] = 0
-else
-if test "$cross_compiling" = yes; then
- { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
-else
- cat > conftest.$ac_ext <<EOF
-#line 8295 "configure"
-#include "confdefs.h"
-/* volatile prevents gcc2 from optimizing the test away on sparcs. */
-#if !defined(__STDC__) || __STDC__ != 1
-#define volatile
-#endif
-main() {
- volatile char c = 255; exit(c < 0);
+ ;
+ return 0;
}
-EOF
-if { (eval echo configure:8305: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
- ac_cv_c_char_unsigned=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
ac_cv_c_char_unsigned=no
-fi
-rm -fr conftest*
-fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_cv_c_char_unsigned=yes
fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$ac_cv_c_char_unsigned" 1>&6
+echo "$as_me:$LINENO: result: $ac_cv_c_char_unsigned" >&5
+echo "${ECHO_T}$ac_cv_c_char_unsigned" >&6
if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then
- cat >> confdefs.h <<\EOF
+ cat >>confdefs.h <<\_ACEOF
#define __CHAR_UNSIGNED__ 1
-EOF
+_ACEOF
fi
-echo $ac_n "checking signed char declarations""... $ac_c" 1>&6
-echo "configure:8329: checking signed char declarations" >&5
-if eval "test \"`echo '$''{'tcl_cv_char_signed'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking signed char declarations" >&5
+echo $ECHO_N "checking signed char declarations... $ECHO_C" >&6
+if test "${tcl_cv_char_signed+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 8335 "configure"
-#include "confdefs.h"
-int main() {
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
signed char *p;
p = 0;
-
-; return 0; }
-EOF
-if { (eval echo configure:8345: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_char_signed=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_char_signed=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_char_signed=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_char_signed" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_char_signed" >&5
+echo "${ECHO_T}$tcl_cv_char_signed" >&6
if test $tcl_cv_char_signed = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_SIGNED_CHAR 1
-EOF
+_ACEOF
fi
@@ -8365,18 +16405,21 @@ fi
# Does putenv() copy or not? We need to know to avoid memory leaks.
#--------------------------------------------------------------------
-echo $ac_n "checking for a putenv() that copies the buffer""... $ac_c" 1>&6
-echo "configure:8370: checking for a putenv() that copies the buffer" >&5
-if eval "test \"`echo '$''{'tcl_cv_putenv_copy'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for a putenv() that copies the buffer" >&5
+echo $ECHO_N "checking for a putenv() that copies the buffer... $ECHO_C" >&6
+if test "${tcl_cv_putenv_copy+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
+
if test "$cross_compiling" = yes; then
tcl_cv_putenv_copy=no
else
- cat > conftest.$ac_ext <<EOF
-#line 8379 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <stdlib.h>
#define OURVAR "havecopy=yes"
@@ -8395,27 +16438,38 @@ else
return 1;
}
}
-
-EOF
-if { (eval echo configure:8401: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_putenv_copy=no
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- tcl_cv_putenv_copy=yes
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+tcl_cv_putenv_copy=yes
fi
-rm -fr conftest*
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
-
fi
-
-echo "$ac_t""$tcl_cv_putenv_copy" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_putenv_copy" >&5
+echo "${ECHO_T}$tcl_cv_putenv_copy" >&6
if test $tcl_cv_putenv_copy = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_PUTENV_THAT_COPIES 1
-EOF
+_ACEOF
fi
@@ -8430,400 +16484,1299 @@ if test "${enable_langinfo+set}" = set; then
langinfo_ok=$enableval
else
langinfo_ok=yes
-fi
-
+fi;
HAVE_LANGINFO=0
if test "$langinfo_ok" = "yes"; then
- ac_safe=`echo "langinfo.h" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for langinfo.h""... $ac_c" 1>&6
-echo "configure:8441: checking for langinfo.h" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 8446 "configure"
-#include "confdefs.h"
+ if test "${ac_cv_header_langinfo_h+set}" = set; then
+ echo "$as_me:$LINENO: checking for langinfo.h" >&5
+echo $ECHO_N "checking for langinfo.h... $ECHO_C" >&6
+if test "${ac_cv_header_langinfo_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_langinfo_h" >&5
+echo "${ECHO_T}$ac_cv_header_langinfo_h" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking langinfo.h usability" >&5
+echo $ECHO_N "checking langinfo.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
#include <langinfo.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8451: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking langinfo.h presence" >&5
+echo $ECHO_N "checking langinfo.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <langinfo.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
fi
-rm -f conftest*
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: langinfo.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: langinfo.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: langinfo.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: langinfo.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: langinfo.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: langinfo.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: langinfo.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: langinfo.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: langinfo.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: langinfo.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: langinfo.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: langinfo.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: langinfo.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: langinfo.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: langinfo.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: langinfo.h: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to the tcl lists. ##
+## ------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for langinfo.h" >&5
+echo $ECHO_N "checking for langinfo.h... $ECHO_C" >&6
+if test "${ac_cv_header_langinfo_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_langinfo_h=$ac_header_preproc
fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+echo "$as_me:$LINENO: result: $ac_cv_header_langinfo_h" >&5
+echo "${ECHO_T}$ac_cv_header_langinfo_h" >&6
+
+fi
+if test $ac_cv_header_langinfo_h = yes; then
langinfo_ok=yes
else
- echo "$ac_t""no" 1>&6
-langinfo_ok=no
+ langinfo_ok=no
fi
+
fi
- echo $ac_n "checking whether to use nl_langinfo""... $ac_c" 1>&6
-echo "configure:8475: checking whether to use nl_langinfo" >&5
+ echo "$as_me:$LINENO: checking whether to use nl_langinfo" >&5
+echo $ECHO_N "checking whether to use nl_langinfo... $ECHO_C" >&6
if test "$langinfo_ok" = "yes"; then
- if eval "test \"`echo '$''{'tcl_cv_langinfo_h'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ if test "${tcl_cv_langinfo_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 8482 "configure"
-#include "confdefs.h"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <langinfo.h>
-int main() {
+int
+main ()
+{
nl_langinfo(CODESET);
-; return 0; }
-EOF
-if { (eval echo configure:8489: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_langinfo_h=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_langinfo_h=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_langinfo_h=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
- echo "$ac_t""$tcl_cv_langinfo_h" 1>&6
+ echo "$as_me:$LINENO: result: $tcl_cv_langinfo_h" >&5
+echo "${ECHO_T}$tcl_cv_langinfo_h" >&6
if test $tcl_cv_langinfo_h = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_LANGINFO 1
-EOF
+_ACEOF
fi
else
- echo "$ac_t""$langinfo_ok" 1>&6
+ echo "$as_me:$LINENO: result: $langinfo_ok" >&5
+echo "${ECHO_T}$langinfo_ok" >&6
fi
#--------------------------------------------------------------------
-# Darwin specific API checks and defines
+# Check for support of chflags function
#--------------------------------------------------------------------
-if test "`uname -s`" = "Darwin" ; then
- for ac_hdr in copyfile.h
+
+for ac_func in chflags
do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:8522: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 8527 "configure"
-#include "confdefs.h"
-#include <$ac_hdr>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8532: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_hdr 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
fi
done
- for ac_func in copyfile
+
+#--------------------------------------------------------------------
+# Check for support of isnan() function or macro
+#--------------------------------------------------------------------
+
+echo "$as_me:$LINENO: checking isnan" >&5
+echo $ECHO_N "checking isnan... $ECHO_C" >&6
+if test "${tcl_cv_isnan+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <math.h>
+int
+main ()
+{
+
+isnan(0.0); /* Generates an error if isnan is missing */
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ tcl_cv_isnan=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_isnan=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_isnan" >&5
+echo "${ECHO_T}$tcl_cv_isnan" >&6
+if test $tcl_cv_isnan = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define NO_ISNAN 1
+_ACEOF
+
+fi
+
+#--------------------------------------------------------------------
+# Darwin specific API checks and defines
+#--------------------------------------------------------------------
+
+if test "`uname -s`" = "Darwin" ; then
+
+for ac_func in getattrlist
do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:8561: checking for $ac_func" >&5
-if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 8566 "configure"
-#include "confdefs.h"
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
choke me
#else
-$ac_func();
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:8589: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
-fi
-rm -f conftest*
-fi
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
fi
done
- if test $tcl_corefoundation = yes; then
- for ac_hdr in libkern/OSAtomic.h
+
+for ac_header in copyfile.h
do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:8618: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 8623 "configure"
-#include "confdefs.h"
-#include <$ac_hdr>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8628: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
fi
-rm -f conftest*
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_hdr 1
-EOF
-
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to the tcl lists. ##
+## ------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- echo "$ac_t""no" 1>&6
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
done
- for ac_func in OSSpinLockLock
+
+for ac_func in copyfile
do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:8657: checking for $ac_func" >&5
-if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 8662 "configure"
-#include "confdefs.h"
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
-int main() {
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
choke me
#else
-$ac_func();
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:8685: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+ if test $tcl_corefoundation = yes; then
+
+for ac_header in libkern/OSAtomic.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
+ ac_cpp_err=yes
fi
-rm -f conftest*
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
-EOF
-
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to the tcl lists. ##
+## ------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- echo "$ac_t""no" 1>&6
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
done
- for ac_func in pthread_atfork
+
+for ac_func in OSSpinLockLock
do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:8712: checking for $ac_func" >&5
-if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 8717 "configure"
-#include "confdefs.h"
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
-int main() {
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+for ac_func in pthread_atfork
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
choke me
#else
-$ac_func();
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
#endif
-; return 0; }
-EOF
-if { (eval echo configure:8740: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
-fi
-rm -f conftest*
-fi
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
fi
done
fi
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define USE_VFORK 1
-EOF
+_ACEOF
+
- cat >> confdefs.h <<\EOF
+cat >>confdefs.h <<\_ACEOF
#define TCL_DEFAULT_ENCODING "utf-8"
-EOF
+_ACEOF
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define TCL_LOAD_FROM_MEMORY 1
-EOF
+_ACEOF
+
- for ac_hdr in AvailabilityMacros.h
+cat >>confdefs.h <<\_ACEOF
+#define TCL_WIDE_CLICKS 1
+_ACEOF
+
+
+for ac_header in AvailabilityMacros.h
do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:8781: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 8786 "configure"
-#include "confdefs.h"
-#include <$ac_hdr>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8791: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
fi
-rm -f conftest*
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_hdr 1
-EOF
-
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to the tcl lists. ##
+## ------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- echo "$ac_t""no" 1>&6
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
done
if test "$ac_cv_header_AvailabilityMacros_h" = yes; then
- echo $ac_n "checking if weak import is available""... $ac_c" 1>&6
-echo "configure:8819: checking if weak import is available" >&5
-if eval "test \"`echo '$''{'tcl_cv_cc_weak_import'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ echo "$as_me:$LINENO: checking if weak import is available" >&5
+echo $ECHO_N "checking if weak import is available... $ECHO_C" >&6
+if test "${tcl_cv_cc_weak_import+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
+
hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
- cat > conftest.$ac_ext <<EOF
-#line 8826 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020
@@ -8833,181 +17786,536 @@ else
#error MAC_OS_X_VERSION_MIN_REQUIRED < 1020
#endif
int rand(void) __attribute__((weak_import));
-
-int main() {
+
+int
+main ()
+{
rand();
-; return 0; }
-EOF
-if { (eval echo configure:8842: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_cc_weak_import=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_cc_weak_import=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_cc_weak_import=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
CFLAGS=$hold_cflags
fi
-
-echo "$ac_t""$tcl_cv_cc_weak_import" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_cc_weak_import" >&5
+echo "${ECHO_T}$tcl_cv_cc_weak_import" >&6
if test $tcl_cv_cc_weak_import = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_WEAK_IMPORT 1
-EOF
+_ACEOF
+
+ fi
+ echo "$as_me:$LINENO: checking if Darwin SUSv3 extensions are available" >&5
+echo $ECHO_N "checking if Darwin SUSv3 extensions are available... $ECHO_C" >&6
+if test "${tcl_cv_cc_darwin_c_source+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+ #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
+ #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
+ #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
+ #endif
+ #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+ #error MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+ #endif
+ #define _DARWIN_C_SOURCE 1
+ #include <sys/cdefs.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ tcl_cv_cc_darwin_c_source=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_cc_darwin_c_source=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS=$hold_cflags
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_cc_darwin_c_source" >&5
+echo "${ECHO_T}$tcl_cv_cc_darwin_c_source" >&6
+ if test $tcl_cv_cc_darwin_c_source = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define _DARWIN_C_SOURCE 1
+_ACEOF
fi
fi
+ # Build .bundle dltest binaries in addition to .dylib
+ DLTEST_LD='${CC} -bundle -Wl,-w ${CFLAGS} ${LDFLAGS}'
+ DLTEST_SUFFIX=".bundle"
+else
+ DLTEST_LD='${SHLIB_LD}'
+ DLTEST_SUFFIX=""
fi
#--------------------------------------------------------------------
# Check for support of fts functions (readdir replacement)
#--------------------------------------------------------------------
-echo $ac_n "checking for fts""... $ac_c" 1>&6
-echo "configure:8870: checking for fts" >&5
-if eval "test \"`echo '$''{'tcl_cv_api_fts'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for fts" >&5
+echo $ECHO_N "checking for fts... $ECHO_C" >&6
+if test "${tcl_cv_api_fts+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
- cat > conftest.$ac_ext <<EOF
-#line 8876 "configure"
-#include "confdefs.h"
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/param.h>
#include <sys/stat.h>
#include <fts.h>
-
-int main() {
+
+int
+main ()
+{
char*const p[2] = {"/", NULL};
FTS *f = fts_open(p, FTS_PHYSICAL|FTS_NOCHDIR|FTS_NOSTAT, NULL);
FTSENT *e = fts_read(f); fts_close(f);
-
-; return 0; }
-EOF
-if { (eval echo configure:8891: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_api_fts=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_api_fts=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_api_fts=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
fi
-
-echo "$ac_t""$tcl_cv_api_fts" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_api_fts" >&5
+echo "${ECHO_T}$tcl_cv_api_fts" >&6
if test $tcl_cv_api_fts = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_FTS 1
-EOF
+_ACEOF
fi
#--------------------------------------------------------------------
# The statements below check for systems where POSIX-style
-# non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented.
+# non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented.
# On these systems (mostly older ones), use the old BSD-style
# FIONBIO approach instead.
#--------------------------------------------------------------------
- for ac_hdr in sys/ioctl.h
+
+for ac_header in sys/ioctl.h
do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:8923: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 8928 "configure"
-#include "confdefs.h"
-#include <$ac_hdr>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8933: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
fi
-rm -f conftest*
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_hdr 1
-EOF
-
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to the tcl lists. ##
+## ------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- echo "$ac_t""no" 1>&6
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
done
- for ac_hdr in sys/filio.h
+
+for ac_header in sys/filio.h
do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:8963: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 8968 "configure"
-#include "confdefs.h"
-#include <$ac_hdr>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8973: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
fi
-rm -f conftest*
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_hdr 1
-EOF
-
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to the tcl lists. ##
+## ------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- echo "$ac_t""no" 1>&6
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
fi
+
done
-
- echo $ac_n "checking system version""... $ac_c" 1>&6
-echo "configure:9001: checking system version" >&5
-if eval "test \"`echo '$''{'tcl_cv_sys_version'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+
+ echo "$as_me:$LINENO: checking system version" >&5
+echo $ECHO_N "checking system version... $ECHO_C" >&6
+if test "${tcl_cv_sys_version+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
+
if test -f /usr/lib/NextStep/software_version; then
tcl_cv_sys_version=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version`
else
tcl_cv_sys_version=`uname -s`-`uname -r`
if test "$?" -ne 0 ; then
- echo "configure: warning: can't find uname command" 1>&2
+ { echo "$as_me:$LINENO: WARNING: can't find uname command" >&5
+echo "$as_me: WARNING: can't find uname command" >&2;}
tcl_cv_sys_version=unknown
else
# Special check for weird MP-RAS system (uname returns weird
@@ -9021,14 +18329,14 @@ else
fi
fi
fi
-
-fi
-echo "$ac_t""$tcl_cv_sys_version" 1>&6
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_sys_version" >&5
+echo "${ECHO_T}$tcl_cv_sys_version" >&6
system=$tcl_cv_sys_version
- echo $ac_n "checking FIONBIO vs. O_NONBLOCK for nonblocking I/O""... $ac_c" 1>&6
-echo "configure:9032: checking FIONBIO vs. O_NONBLOCK for nonblocking I/O" >&5
+ echo "$as_me:$LINENO: checking FIONBIO vs. O_NONBLOCK for nonblocking I/O" >&5
+echo $ECHO_N "checking FIONBIO vs. O_NONBLOCK for nonblocking I/O... $ECHO_C" >&6
case $system in
# There used to be code here to use FIONBIO under AIX. However, it
# was reported that FIONBIO doesn't work under AIX 3.2.5. Since
@@ -9036,32 +18344,117 @@ echo "configure:9032: checking FIONBIO vs. O_NONBLOCK for nonblocking I/O" >&5
# code (JO, 5/31/97).
OSF*)
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define USE_FIONBIO 1
-EOF
+_ACEOF
- echo "$ac_t""FIONBIO" 1>&6
+ echo "$as_me:$LINENO: result: FIONBIO" >&5
+echo "${ECHO_T}FIONBIO" >&6
;;
SunOS-4*)
- cat >> confdefs.h <<\EOF
-#define USE_FIONBIO 1
-EOF
- echo "$ac_t""FIONBIO" 1>&6
- ;;
- ULTRIX-4.*)
- cat >> confdefs.h <<\EOF
+cat >>confdefs.h <<\_ACEOF
#define USE_FIONBIO 1
-EOF
+_ACEOF
- echo "$ac_t""FIONBIO" 1>&6
+ echo "$as_me:$LINENO: result: FIONBIO" >&5
+echo "${ECHO_T}FIONBIO" >&6
;;
*)
- echo "$ac_t""O_NONBLOCK" 1>&6
+ echo "$as_me:$LINENO: result: O_NONBLOCK" >&5
+echo "${ECHO_T}O_NONBLOCK" >&6
;;
esac
+#------------------------------------------------------------------------
+
+echo "$as_me:$LINENO: checking whether to use dll unloading" >&5
+echo $ECHO_N "checking whether to use dll unloading... $ECHO_C" >&6
+# Check whether --enable-dll-unloading or --disable-dll-unloading was given.
+if test "${enable_dll_unloading+set}" = set; then
+ enableval="$enable_dll_unloading"
+ tcl_ok=$enableval
+else
+ tcl_ok=yes
+fi;
+if test $tcl_ok = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TCL_UNLOAD_DLLS 1
+_ACEOF
+
+fi
+echo "$as_me:$LINENO: result: $tcl_ok" >&5
+echo "${ECHO_T}$tcl_ok" >&6
+
+#------------------------------------------------------------------------
+# Check whether the timezone data is supplied by the OS or has
+# to be installed by Tcl. The default is autodetection, but can
+# be overriden on the configure command line either way.
+#------------------------------------------------------------------------
+
+echo "$as_me:$LINENO: checking for timezone data" >&5
+echo $ECHO_N "checking for timezone data... $ECHO_C" >&6
+
+# Check whether --with-tzdata or --without-tzdata was given.
+if test "${with_tzdata+set}" = set; then
+ withval="$with_tzdata"
+ tcl_ok=$withval
+else
+ tcl_ok=auto
+fi;
+#
+# Any directories that get added here must also be added to the
+# search path in ::tcl::clock::Initialize (library/clock.tcl).
+#
+case $tcl_ok in
+ no)
+ echo "$as_me:$LINENO: result: supplied by OS vendor" >&5
+echo "${ECHO_T}supplied by OS vendor" >&6
+ ;;
+ yes)
+ # nothing to do here
+ ;;
+ auto*)
+ if test "${tcl_cv_dir_zoneinfo+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ for dir in /usr/share/zoneinfo \
+ /usr/share/lib/zoneinfo \
+ /usr/lib/zoneinfo
+ do
+ if test -f $dir/UTC -o -f $dir/GMT
+ then
+ tcl_cv_dir_zoneinfo="$dir"
+ break
+ fi
+ done
+fi
+
+ if test -n "$tcl_cv_dir_zoneinfo"; then
+ tcl_ok=no
+ echo "$as_me:$LINENO: result: $dir" >&5
+echo "${ECHO_T}$dir" >&6
+ else
+ tcl_ok=yes
+ fi
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: invalid argument: $tcl_ok" >&5
+echo "$as_me: error: invalid argument: $tcl_ok" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+esac
+if test $tcl_ok = yes
+then
+ echo "$as_me:$LINENO: result: supplied by Tcl" >&5
+echo "${ECHO_T}supplied by Tcl" >&6
+ INSTALL_TZDATA=install-tzdata
+fi
+
#--------------------------------------------------------------------
# DTrace support
#--------------------------------------------------------------------
@@ -9072,89 +18465,204 @@ if test "${enable_dtrace+set}" = set; then
tcl_ok=$enableval
else
tcl_ok=no
-fi
-
+fi;
if test $tcl_ok = yes; then
- ac_safe=`echo "sys/sdt.h" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for sys/sdt.h""... $ac_c" 1>&6
-echo "configure:9081: checking for sys/sdt.h" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 9086 "configure"
-#include "confdefs.h"
+ if test "${ac_cv_header_sys_sdt_h+set}" = set; then
+ echo "$as_me:$LINENO: checking for sys/sdt.h" >&5
+echo $ECHO_N "checking for sys/sdt.h... $ECHO_C" >&6
+if test "${ac_cv_header_sys_sdt_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_sys_sdt_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_sdt_h" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking sys/sdt.h usability" >&5
+echo $ECHO_N "checking sys/sdt.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <sys/sdt.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking sys/sdt.h presence" >&5
+echo $ECHO_N "checking sys/sdt.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/sdt.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:9091: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
fi
-rm -f conftest*
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: sys/sdt.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: sys/sdt.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/sdt.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: sys/sdt.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: sys/sdt.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: sys/sdt.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/sdt.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: sys/sdt.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/sdt.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: sys/sdt.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/sdt.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: sys/sdt.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/sdt.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: sys/sdt.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/sdt.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: sys/sdt.h: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to the tcl lists. ##
+## ------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for sys/sdt.h" >&5
+echo $ECHO_N "checking for sys/sdt.h... $ECHO_C" >&6
+if test "${ac_cv_header_sys_sdt_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_sys_sdt_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_sys_sdt_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_sdt_h" >&6
+
fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+if test $ac_cv_header_sys_sdt_h = yes; then
tcl_ok=yes
else
- echo "$ac_t""no" 1>&6
-tcl_ok=no
+ tcl_ok=no
fi
+
fi
if test $tcl_ok = yes; then
# Extract the first word of "dtrace", so it can be a program name with args.
set dummy dtrace; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:9118: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_path_DTRACE'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_DTRACE+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- case "$DTRACE" in
- /*)
+ case $DTRACE in
+ [\\/]* | ?:[\\/]*)
ac_cv_path_DTRACE="$DTRACE" # Let the user override the test with a path.
;;
- ?:/*)
- ac_cv_path_DTRACE="$DTRACE" # Let the user override the test with a dos path.
- ;;
*)
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH:/usr/sbin"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_path_DTRACE="$ac_dir/$ac_word"
- break
- fi
- done
- IFS="$ac_save_ifs"
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_dummy="$PATH:/usr/sbin"
+for as_dir in $as_dummy
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_DTRACE="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
;;
esac
fi
-DTRACE="$ac_cv_path_DTRACE"
+DTRACE=$ac_cv_path_DTRACE
+
if test -n "$DTRACE"; then
- echo "$ac_t""$DTRACE" 1>&6
+ echo "$as_me:$LINENO: result: $DTRACE" >&5
+echo "${ECHO_T}$DTRACE" >&6
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
fi
test -z "$ac_cv_path_DTRACE" && tcl_ok=no
fi
-echo $ac_n "checking whether to enable DTrace support""... $ac_c" 1>&6
-echo "configure:9153: checking whether to enable DTrace support" >&5
+echo "$as_me:$LINENO: checking whether to enable DTrace support" >&5
+echo $ECHO_N "checking whether to enable DTrace support... $ECHO_C" >&6
MAKEFILE_SHELL='/bin/sh'
if test $tcl_ok = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define USE_DTRACE 1
-EOF
+_ACEOF
DTRACE_SRC="\${DTRACE_SRC}"
DTRACE_HDR="\${DTRACE_HDR}"
@@ -9172,7 +18680,81 @@ EOF
fi
fi
fi
-echo "$ac_t""$tcl_ok" 1>&6
+echo "$as_me:$LINENO: result: $tcl_ok" >&5
+echo "${ECHO_T}$tcl_ok" >&6
+
+#--------------------------------------------------------------------
+# Does the C stack grow upwards or downwards? Or cross-compiling?
+#--------------------------------------------------------------------
+
+echo "$as_me:$LINENO: checking if the C stack grows upwards in memory" >&5
+echo $ECHO_N "checking if the C stack grows upwards in memory... $ECHO_C" >&6
+if test "${tcl_cv_stack_grows_up+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ tcl_cv_stack_grows_up=unknown
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+ int StackGrowsUp(int *parent) {
+ int here;
+ volatile int result;
+ if (parent)
+ result = (&here < parent);
+ else
+ result = StackGrowsUp(&here);
+ return result;
+ }
+ int main (int argc, char *argv[]) {
+ return StackGrowsUp(0);
+ }
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ tcl_cv_stack_grows_up=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+tcl_cv_stack_grows_up=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_stack_grows_up" >&5
+echo "${ECHO_T}$tcl_cv_stack_grows_up" >&6
+if test $tcl_cv_stack_grows_up = unknown; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TCL_CROSS_COMPILE 1
+_ACEOF
+
+elif test $tcl_cv_stack_grows_up = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TCL_STACK_GROWS_UP 1
+_ACEOF
+
+fi
#--------------------------------------------------------------------
# The statements below define a collection of symbols related to
@@ -9184,10 +18766,9 @@ TCL_SHARED_LIB_SUFFIX=${SHARED_LIB_SUFFIX}
eval "TCL_LIB_FILE=libtcl${LIB_SUFFIX}"
# tclConfig.sh needs a version of the _LIB_SUFFIX that has been eval'ed
-# so that the backslashes quoting the DBX braces are dropped.
+# since on some platforms TCL_LIB_FILE contains shell escapes.
+# (See also: TCL_TRIM_DOTS).
-# Trick to replace DBGX with TCL_DBGX
-DBGX='${TCL_DBGX}'
eval "TCL_LIB_FILE=${TCL_LIB_FILE}"
TCL_LIBRARY='$(prefix)/lib/tcl$(VERSION)'
@@ -9200,59 +18781,66 @@ HTML_DIR='$(DISTDIR)/html'
# up the Tcl library.
if test "`uname -s`" = "Darwin" ; then
-
+
if test "`uname -s`" = "Darwin" ; then
- echo $ac_n "checking how to package libraries""... $ac_c" 1>&6
-echo "configure:9207: checking how to package libraries" >&5
+ echo "$as_me:$LINENO: checking how to package libraries" >&5
+echo $ECHO_N "checking how to package libraries... $ECHO_C" >&6
# Check whether --enable-framework or --disable-framework was given.
if test "${enable_framework+set}" = set; then
enableval="$enable_framework"
enable_framework=$enableval
else
enable_framework=no
-fi
-
+fi;
if test $enable_framework = yes; then
if test $SHARED_BUILD = 0; then
- echo "configure: warning: Frameworks can only be built if --enable-shared is yes" 1>&2
+ { echo "$as_me:$LINENO: WARNING: Frameworks can only be built if --enable-shared is yes" >&5
+echo "$as_me: WARNING: Frameworks can only be built if --enable-shared is yes" >&2;}
enable_framework=no
fi
if test $tcl_corefoundation = no; then
- echo "configure: warning: Frameworks can only be used when CoreFoundation is available" 1>&2
+ { echo "$as_me:$LINENO: WARNING: Frameworks can only be used when CoreFoundation is available" >&5
+echo "$as_me: WARNING: Frameworks can only be used when CoreFoundation is available" >&2;}
enable_framework=no
fi
fi
if test $enable_framework = yes; then
- echo "$ac_t""framework" 1>&6
+ echo "$as_me:$LINENO: result: framework" >&5
+echo "${ECHO_T}framework" >&6
FRAMEWORK_BUILD=1
else
if test $SHARED_BUILD = 1; then
- echo "$ac_t""shared library" 1>&6
+ echo "$as_me:$LINENO: result: shared library" >&5
+echo "${ECHO_T}shared library" >&6
else
- echo "$ac_t""static library" 1>&6
+ echo "$as_me:$LINENO: result: static library" >&5
+echo "${ECHO_T}static library" >&6
fi
FRAMEWORK_BUILD=0
fi
fi
TCL_SHLIB_LD_EXTRAS="-compatibility_version ${TCL_VERSION} -current_version ${TCL_VERSION}`echo ${TCL_PATCH_LEVEL} | awk '{match($0, "\\\.[0-9]+"); print substr($0,RSTART,RLENGTH)}'`"
- TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -install_name ${DYLIB_INSTALL_DIR}/${TCL_LIB_FILE}'
+ TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -install_name "${DYLIB_INSTALL_DIR}"/${TCL_LIB_FILE}'
echo "$LDFLAGS " | grep -q -- '-prebind ' && TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -seg1addr 0xa000000'
TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -sectcreate __TEXT __info_plist Tcl-Info.plist'
EXTRA_TCLSH_LIBS='-sectcreate __TEXT __info_plist Tclsh-Info.plist'
EXTRA_APP_CC_SWITCHES='-mdynamic-no-pic'
- tcl_config_files="${tcl_config_files} Tcl-Info.plist:../macosx/Tcl-Info.plist.in Tclsh-Info.plist:../macosx/Tclsh-Info.plist.in"
+ ac_config_files="$ac_config_files Tcl-Info.plist:../macosx/Tcl-Info.plist.in Tclsh-Info.plist:../macosx/Tclsh-Info.plist.in"
+
TCL_YEAR="`date +%Y`"
fi
if test "$FRAMEWORK_BUILD" = "1" ; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define TCL_FRAMEWORK 1
-EOF
+_ACEOF
# Construct a fake local framework structure to make linking with
# '-framework Tcl' and running of tcltest work
-
+ ac_config_commands="$ac_config_commands Tcl.framework"
+
LD_LIBRARY_PATH_VAR="DYLD_FRAMEWORK_PATH"
if test "${libdir}" = '${exec_prefix}/lib'; then
# override libdir default
@@ -9260,7 +18848,7 @@ EOF
fi
TCL_LIB_FILE="Tcl"
TCL_LIB_FLAG="-framework Tcl"
- TCL_BUILD_LIB_SPEC="-F`pwd` -framework Tcl"
+ TCL_BUILD_LIB_SPEC="-F`pwd | sed -e 's/ /\\\\ /g'` -framework Tcl"
TCL_LIB_SPEC="-F${libdir} -framework Tcl"
libdir="${libdir}/Tcl.framework/Versions/\${VERSION}"
TCL_LIBRARY="${libdir}/Resources/Scripts"
@@ -9268,46 +18856,29 @@ EOF
PRIVATE_INCLUDE_DIR="${libdir}/PrivateHeaders"
HTML_DIR="${libdir}/Resources/Documentation/Reference/Tcl"
EXTRA_INSTALL="install-private-headers html-tcl"
- EXTRA_BUILD_HTML='@ln -fs contents.htm $(HTML_INSTALL_DIR)/TclTOC.html'
+ EXTRA_BUILD_HTML='@ln -fs contents.htm "$(HTML_INSTALL_DIR)"/TclTOC.html'
EXTRA_INSTALL_BINARIES='@echo "Installing Info.plist to $(LIB_INSTALL_DIR)/Resources" && mkdir -p "$(LIB_INSTALL_DIR)/Resources" && $(INSTALL_DATA) Tcl-Info.plist "$(LIB_INSTALL_DIR)/Resources/Info.plist"'
EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing license.terms to $(LIB_INSTALL_DIR)/Resources" && $(INSTALL_DATA) "$(TOP_DIR)/license.terms" "$(LIB_INSTALL_DIR)/Resources"'
EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Finalizing Tcl.framework" && rm -f "$(LIB_INSTALL_DIR)/../Current" && ln -s "$(VERSION)" "$(LIB_INSTALL_DIR)/../Current" && for f in "$(LIB_FILE)" tclConfig.sh Resources Headers PrivateHeaders; do rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/Current/$$f" "$(LIB_INSTALL_DIR)/../.."; done && f="$(STUB_LIB_FILE)" && rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/$(VERSION)/$$f" "$(LIB_INSTALL_DIR)/../.."'
- # Don't use AC_DEFINE for the following as the framework version define
- # needs to go into the Makefile even when using autoheader, so that we
+ # Don't use AC_DEFINE for the following as the framework version define
+ # needs to go into the Makefile even when using autoheader, so that we
# can pick up a potential make override of VERSION. Also, don't put this
# into CFLAGS as it should not go into tclConfig.sh
EXTRA_CC_SWITCHES='-DTCL_FRAMEWORK_VERSION=\"$(VERSION)\"'
else
# libdir must be a fully qualified path and not ${exec_prefix}/lib
eval libdir="$libdir"
- if test "$SHARED_BUILD" = "0" || test "$TCL_NEEDS_EXP_FILE" = "0"; then
- if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
- TCL_LIB_FLAG="-ltcl${TCL_VERSION}\${TCL_DBGX}"
- else
- TCL_LIB_FLAG="-ltcl`echo ${TCL_VERSION} | tr -d .`\${TCL_DBGX}"
- fi
- TCL_BUILD_LIB_SPEC="-L`pwd` ${TCL_LIB_FLAG}"
- TCL_LIB_SPEC="-L${libdir} ${TCL_LIB_FLAG}"
+ if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
+ TCL_LIB_FLAG="-ltcl${TCL_VERSION}"
else
- TCL_BUILD_EXP_FILE="lib.exp"
- eval "TCL_EXP_FILE=libtcl${TCL_EXPORT_FILE_SUFFIX}"
-
- # Replace DBGX with TCL_DBGX
- eval "TCL_EXP_FILE=\"${TCL_EXP_FILE}\""
-
- if test "$GCC" = "yes" ; then
- TCL_BUILD_LIB_SPEC="-Wl,-bI:`pwd`/${TCL_BUILD_EXP_FILE} -L`pwd`"
- TCL_LIB_SPEC="-Wl,-bI:${libdir}/${TCL_EXP_FILE} -L`pwd`"
- else
- TCL_BUILD_LIB_SPEC="-bI:`pwd`/${TCL_BUILD_EXP_FILE}"
- TCL_LIB_SPEC="-bI:${libdir}/${TCL_EXP_FILE}"
- fi
+ TCL_LIB_FLAG="-ltcl`echo ${TCL_VERSION} | tr -d .`"
fi
+ TCL_BUILD_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TCL_LIB_FLAG}"
+ TCL_LIB_SPEC="-L${libdir} ${TCL_LIB_FLAG}"
fi
VERSION='${VERSION}'
eval "CFG_TCL_SHARED_LIB_SUFFIX=${TCL_SHARED_LIB_SUFFIX}"
eval "CFG_TCL_UNSHARED_LIB_SUFFIX=${TCL_UNSHARED_LIB_SUFFIX}"
-eval "CFG_TCL_EXPORT_FILE_SUFFIX=${TCL_EXPORT_FILE_SUFFIX}"
VERSION=${TCL_VERSION}
#--------------------------------------------------------------------
@@ -9319,8 +18890,10 @@ VERSION=${TCL_VERSION}
if test "$FRAMEWORK_BUILD" = "1" ; then
test -z "$TCL_PACKAGE_PATH" && \
- TCL_PACKAGE_PATH="~/Library/Tcl /Library/Tcl /Network/Library/Tcl /System/Library/Tcl ~/Library/Frameworks /Library/Frameworks /Network/Library/Frameworks /System/Library/Frameworks"
-elif test "$prefix" != "$exec_prefix"; then
+ TCL_PACKAGE_PATH="~/Library/Tcl /Library/Tcl /System/Library/Tcl ~/Library/Frameworks /Library/Frameworks /System/Library/Frameworks"
+ test -z "$TCL_MODULE_PATH" && \
+ TCL_MODULE_PATH="~/Library/Tcl /Library/Tcl /System/Library/Tcl"
+elif test "$prefix/lib" != "$libdir"; then
TCL_PACKAGE_PATH="${libdir} ${prefix}/lib ${TCL_PACKAGE_PATH}"
else
TCL_PACKAGE_PATH="${prefix}/lib ${TCL_PACKAGE_PATH}"
@@ -9332,18 +18905,19 @@ fi
#--------------------------------------------------------------------
# Replace ${VERSION} with contents of ${TCL_VERSION}
+# double-eval to account for TCL_TRIM_DOTS.
+#
eval "TCL_STUB_LIB_FILE=libtclstub${TCL_UNSHARED_LIB_SUFFIX}"
-# Replace DBGX with TCL_DBGX
eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
eval "TCL_STUB_LIB_DIR=${libdir}"
if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
- TCL_STUB_LIB_FLAG="-ltclstub${TCL_VERSION}\${TCL_DBGX}"
+ TCL_STUB_LIB_FLAG="-ltclstub${TCL_VERSION}"
else
- TCL_STUB_LIB_FLAG="-ltclstub`echo ${TCL_VERSION} | tr -d .`\${TCL_DBGX}"
+ TCL_STUB_LIB_FLAG="-ltclstub`echo ${TCL_VERSION} | tr -d .`"
fi
-TCL_BUILD_STUB_LIB_SPEC="-L`pwd` ${TCL_STUB_LIB_FLAG}"
+TCL_BUILD_STUB_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}"
TCL_STUB_LIB_SPEC="-L${TCL_STUB_LIB_DIR} ${TCL_STUB_LIB_FLAG}"
TCL_BUILD_STUB_LIB_PATH="`pwd`/${TCL_STUB_LIB_FILE}"
TCL_STUB_LIB_PATH="${TCL_STUB_LIB_DIR}/${TCL_STUB_LIB_FILE}"
@@ -9413,345 +18987,1118 @@ TCL_SHARED_BUILD=${SHARED_BUILD}
-CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""
-tcl_config_files="${tcl_config_files} Makefile dltest/Makefile tclConfig.sh"
-trap '' 1 2 15
-cat > confcache <<\EOF
+ ac_config_files="$ac_config_files Makefile:../unix/Makefile.in dltest/Makefile:../unix/dltest/Makefile.in tclConfig.sh:../unix/tclConfig.sh.in"
+
+cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
-# scripts and configure runs. It is not useful on other systems.
-# If it contains results you don't want to keep, you may remove or edit it.
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
#
-# By default, configure uses ./config.cache as the cache file,
-# creating it if it does not exist already. You can give configure
-# the --cache-file=FILE option to use a different cache file; that is
-# what configure does when it calls configure scripts in
-# subdirectories, so they share the cache.
-# Giving --cache-file=/dev/null disables caching, for debugging configure.
-# config.status only pays attention to the cache file if you give it the
-# --recheck option to rerun configure.
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
#
-EOF
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
# The following way of writing the cache mishandles newlines in values,
# but we know of no workaround that is simple, portable, and efficient.
# So, don't put newlines in cache variables' values.
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
-(set) 2>&1 |
- case `(ac_space=' '; set | grep ac_space) 2>&1` in
- *ac_space=\ *)
- # `set' does not quote correctly, so add quotes (double-quote substitution
- # turns \\\\ into \\, and sed turns \\ into \).
- sed -n \
- -e "s/'/'\\\\''/g" \
- -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
- ;;
- *)
- # `set' quotes correctly as required by POSIX, so do not add quotes.
- sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
- ;;
- esac >> confcache
-if cmp -s $cache_file confcache; then
- :
-else
+{
+ (set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+} |
+ sed '
+ t clear
+ : clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
if test -w $cache_file; then
- echo "updating cache $cache_file"
- cat confcache > $cache_file
+ test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+ cat confcache >$cache_file
else
echo "not updating unwritable cache $cache_file"
fi
fi
rm -f confcache
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
-
test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-# Any assignment to VPATH causes Sun make to only execute
-# the first set of double-colon rules, so remove it if not needed.
-# If there is a colon in the path, we need to keep it.
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
if test "x$srcdir" = x.; then
- ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[ ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[ ]*$//;
+}'
fi
-trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
-
# Transform confdefs.h into DEFS.
# Protect against shell expansion while executing Makefile rules.
# Protect against Makefile macro expansion.
-cat > conftest.defs <<\EOF
-s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
-s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
-s%\[%\\&%g
-s%\]%\\&%g
-s%\$%$$%g
-EOF
-DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
-rm -f conftest.defs
-
-
-# Without the "./", some shells look in PATH for config.status.
-: ${CONFIG_STATUS=./config.status}
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then we branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+cat >confdef2opt.sed <<\_ACEOF
+t clear
+: clear
+s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g
+t quote
+s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g
+t quote
+d
+: quote
+s,[ `~#$^&*(){}\\|;'"<>?],\\&,g
+s,\[,\\&,g
+s,\],\\&,g
+s,\$,$$,g
+p
+_ACEOF
+# We use echo to avoid assuming a particular line-breaking character.
+# The extra dot is to prevent the shell from consuming trailing
+# line-breaks from the sub-command output. A line-break within
+# single-quotes doesn't work because, if this script is created in a
+# platform that uses two characters for line-breaks (e.g., DOS), tr
+# would break.
+ac_LF_and_DOT=`echo; echo .`
+DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
+rm -f confdef2opt.sed
-echo creating $CONFIG_STATUS
-rm -f $CONFIG_STATUS
-cat > $CONFIG_STATUS <<EOF
-#! /bin/sh
-# Generated automatically by configure.
+
+
+CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
# Run this file to recreate the current configuration.
-# This directory was configured as follows,
-# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-#
-# $0 $ac_configure_args
-#
# Compiler output produced by configure, useful for debugging
-# configure, is in ./config.log if it exists.
+# configure, is in config.log if it exists.
-ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
-for ac_option
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
do
- case "\$ac_option" in
- -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
- echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
- exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
- -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
- echo "$CONFIG_STATUS generated by autoconf version 2.13"
- exit 0 ;;
- -help | --help | --hel | --he | --h)
- echo "\$ac_cs_usage"; exit 0 ;;
- *) echo "\$ac_cs_usage"; exit 1 ;;
- esac
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
done
-ac_given_srcdir=$srcdir
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
-trap 'rm -fr `echo "${tcl_config_files}" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
-EOF
-cat >> $CONFIG_STATUS <<EOF
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
-# Protect against being on the right side of a sed subst in config.status.
-sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
- s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
-$ac_vpsub
-$extrasub
-s%@SHELL@%$SHELL%g
-s%@CFLAGS@%$CFLAGS%g
-s%@CPPFLAGS@%$CPPFLAGS%g
-s%@CXXFLAGS@%$CXXFLAGS%g
-s%@FFLAGS@%$FFLAGS%g
-s%@DEFS@%$DEFS%g
-s%@LDFLAGS@%$LDFLAGS%g
-s%@LIBS@%$LIBS%g
-s%@exec_prefix@%$exec_prefix%g
-s%@prefix@%$prefix%g
-s%@program_transform_name@%$program_transform_name%g
-s%@bindir@%$bindir%g
-s%@sbindir@%$sbindir%g
-s%@libexecdir@%$libexecdir%g
-s%@datadir@%$datadir%g
-s%@sysconfdir@%$sysconfdir%g
-s%@sharedstatedir@%$sharedstatedir%g
-s%@localstatedir@%$localstatedir%g
-s%@libdir@%$libdir%g
-s%@includedir@%$includedir%g
-s%@oldincludedir@%$oldincludedir%g
-s%@infodir@%$infodir%g
-s%@mandir@%$mandir%g
-s%@MAN_FLAGS@%$MAN_FLAGS%g
-s%@CC@%$CC%g
-s%@CPP@%$CPP%g
-s%@TCL_THREADS@%$TCL_THREADS%g
-s%@TCL_LIBS@%$TCL_LIBS%g
-s%@MATH_LIBS@%$MATH_LIBS%g
-s%@RANLIB@%$RANLIB%g
-s%@AR@%$AR%g
-s%@DL_LIBS@%$DL_LIBS%g
-s%@DL_OBJS@%$DL_OBJS%g
-s%@PLAT_OBJS@%$PLAT_OBJS%g
-s%@PLAT_SRCS@%$PLAT_SRCS%g
-s%@CFLAGS_DEBUG@%$CFLAGS_DEBUG%g
-s%@CFLAGS_OPTIMIZE@%$CFLAGS_OPTIMIZE%g
-s%@CFLAGS_WARNING@%$CFLAGS_WARNING%g
-s%@LDFLAGS_DEBUG@%$LDFLAGS_DEBUG%g
-s%@LDFLAGS_OPTIMIZE@%$LDFLAGS_OPTIMIZE%g
-s%@CC_SEARCH_FLAGS@%$CC_SEARCH_FLAGS%g
-s%@LD_SEARCH_FLAGS@%$LD_SEARCH_FLAGS%g
-s%@STLIB_LD@%$STLIB_LD%g
-s%@SHLIB_LD@%$SHLIB_LD%g
-s%@TCL_SHLIB_LD_EXTRAS@%$TCL_SHLIB_LD_EXTRAS%g
-s%@TK_SHLIB_LD_EXTRAS@%$TK_SHLIB_LD_EXTRAS%g
-s%@SHLIB_LD_LIBS@%$SHLIB_LD_LIBS%g
-s%@SHLIB_CFLAGS@%$SHLIB_CFLAGS%g
-s%@SHLIB_SUFFIX@%$SHLIB_SUFFIX%g
-s%@MAKE_LIB@%$MAKE_LIB%g
-s%@MAKE_STUB_LIB@%$MAKE_STUB_LIB%g
-s%@INSTALL_LIB@%$INSTALL_LIB%g
-s%@INSTALL_STUB_LIB@%$INSTALL_STUB_LIB%g
-s%@CFLAGS_DEFAULT@%$CFLAGS_DEFAULT%g
-s%@LDFLAGS_DEFAULT@%$LDFLAGS_DEFAULT%g
-s%@LIBOBJS@%$LIBOBJS%g
-s%@DTRACE@%$DTRACE%g
-s%@TCL_VERSION@%$TCL_VERSION%g
-s%@TCL_MAJOR_VERSION@%$TCL_MAJOR_VERSION%g
-s%@TCL_MINOR_VERSION@%$TCL_MINOR_VERSION%g
-s%@TCL_PATCH_LEVEL@%$TCL_PATCH_LEVEL%g
-s%@TCL_YEAR@%$TCL_YEAR%g
-s%@TCL_LIB_FILE@%$TCL_LIB_FILE%g
-s%@TCL_LIB_FLAG@%$TCL_LIB_FLAG%g
-s%@TCL_LIB_SPEC@%$TCL_LIB_SPEC%g
-s%@TCL_STUB_LIB_FILE@%$TCL_STUB_LIB_FILE%g
-s%@TCL_STUB_LIB_FLAG@%$TCL_STUB_LIB_FLAG%g
-s%@TCL_STUB_LIB_SPEC@%$TCL_STUB_LIB_SPEC%g
-s%@TCL_STUB_LIB_PATH@%$TCL_STUB_LIB_PATH%g
-s%@TCL_INCLUDE_SPEC@%$TCL_INCLUDE_SPEC%g
-s%@TCL_BUILD_STUB_LIB_SPEC@%$TCL_BUILD_STUB_LIB_SPEC%g
-s%@TCL_BUILD_STUB_LIB_PATH@%$TCL_BUILD_STUB_LIB_PATH%g
-s%@TCL_SRC_DIR@%$TCL_SRC_DIR%g
-s%@TCL_DBGX@%$TCL_DBGX%g
-s%@CFG_TCL_SHARED_LIB_SUFFIX@%$CFG_TCL_SHARED_LIB_SUFFIX%g
-s%@CFG_TCL_UNSHARED_LIB_SUFFIX@%$CFG_TCL_UNSHARED_LIB_SUFFIX%g
-s%@CFG_TCL_EXPORT_FILE_SUFFIX@%$CFG_TCL_EXPORT_FILE_SUFFIX%g
-s%@TCL_SHARED_BUILD@%$TCL_SHARED_BUILD%g
-s%@LD_LIBRARY_PATH_VAR@%$LD_LIBRARY_PATH_VAR%g
-s%@TCL_BUILD_LIB_SPEC@%$TCL_BUILD_LIB_SPEC%g
-s%@TCL_NEEDS_EXP_FILE@%$TCL_NEEDS_EXP_FILE%g
-s%@TCL_BUILD_EXP_FILE@%$TCL_BUILD_EXP_FILE%g
-s%@TCL_EXP_FILE@%$TCL_EXP_FILE%g
-s%@TCL_LIB_VERSIONS_OK@%$TCL_LIB_VERSIONS_OK%g
-s%@TCL_SHARED_LIB_SUFFIX@%$TCL_SHARED_LIB_SUFFIX%g
-s%@TCL_UNSHARED_LIB_SUFFIX@%$TCL_UNSHARED_LIB_SUFFIX%g
-s%@TCL_HAS_LONGLONG@%$TCL_HAS_LONGLONG%g
-s%@DTRACE_SRC@%$DTRACE_SRC%g
-s%@DTRACE_HDR@%$DTRACE_HDR%g
-s%@DTRACE_OBJ@%$DTRACE_OBJ%g
-s%@MAKEFILE_SHELL@%$MAKEFILE_SHELL%g
-s%@BUILD_DLTEST@%$BUILD_DLTEST%g
-s%@TCL_PACKAGE_PATH@%$TCL_PACKAGE_PATH%g
-s%@TCL_LIBRARY@%$TCL_LIBRARY%g
-s%@PRIVATE_INCLUDE_DIR@%$PRIVATE_INCLUDE_DIR%g
-s%@HTML_DIR@%$HTML_DIR%g
-s%@EXTRA_CC_SWITCHES@%$EXTRA_CC_SWITCHES%g
-s%@EXTRA_APP_CC_SWITCHES@%$EXTRA_APP_CC_SWITCHES%g
-s%@EXTRA_INSTALL@%$EXTRA_INSTALL%g
-s%@EXTRA_INSTALL_BINARIES@%$EXTRA_INSTALL_BINARIES%g
-s%@EXTRA_BUILD_HTML@%$EXTRA_BUILD_HTML%g
-s%@EXTRA_TCLSH_LIBS@%$EXTRA_TCLSH_LIBS%g
-CEOF
-EOF
-
-cat >> $CONFIG_STATUS <<\EOF
-
-# Split the substitutions into bite-sized pieces for seds with
-# small command number limits, like on Digital OSF/1 and HP-UX.
-ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
-ac_file=1 # Number of current file.
-ac_beg=1 # First line for current file.
-ac_end=$ac_max_sed_cmds # Line after last line for current file.
-ac_more_lines=:
-ac_sed_cmds=""
-while $ac_more_lines; do
- if test $ac_beg -gt 1; then
- sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
else
- sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ PATH_SEPARATOR=:
fi
- if test ! -s conftest.s$ac_file; then
- ac_more_lines=false
- rm -f conftest.s$ac_file
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
else
- if test -z "$ac_sed_cmds"; then
- ac_sed_cmds="sed -f conftest.s$ac_file"
- else
- ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
- fi
- ac_file=`expr $ac_file + 1`
- ac_beg=$ac_end
- ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ as_ln_s='ln -s'
fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling. Logging --version etc. is OK.
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by tcl $as_me 8.5, which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+ echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+ echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+ echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+ echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+tcl config.status 8.5
+configured by $0, generated by GNU Autoconf 2.59,
+ with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "x$1" : 'x\([^=]*\)='`
+ ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ -*)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ *) # This is not an option, so the user has probably given explicit
+ # arguments.
+ ac_option=$1
+ ac_need_defaults=false;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --vers* | -V )
+ echo "$ac_cs_version"; exit 0 ;;
+ --he | --h)
+ # Conflict between --help and --header
+ { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit 0 ;;
+ --debug | --d* | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1" ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+#
+# INIT-COMMANDS section.
+#
+
+VERSION=${TCL_VERSION}
+
+_ACEOF
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+ case "$ac_config_target" in
+ # Handling of arguments.
+ "Tcl-Info.plist" ) CONFIG_FILES="$CONFIG_FILES Tcl-Info.plist:../macosx/Tcl-Info.plist.in" ;;
+ "Tclsh-Info.plist" ) CONFIG_FILES="$CONFIG_FILES Tclsh-Info.plist:../macosx/Tclsh-Info.plist.in" ;;
+ "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile:../unix/Makefile.in" ;;
+ "dltest/Makefile" ) CONFIG_FILES="$CONFIG_FILES dltest/Makefile:../unix/dltest/Makefile.in" ;;
+ "tclConfig.sh" ) CONFIG_FILES="$CONFIG_FILES tclConfig.sh:../unix/tclConfig.sh.in" ;;
+ "Tcl.framework" ) CONFIG_COMMANDS="$CONFIG_COMMANDS Tcl.framework" ;;
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
done
-if test -z "$ac_sed_cmds"; then
- ac_sed_cmds=cat
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
fi
-EOF
-cat >> $CONFIG_STATUS <<EOF
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+ trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./confstat$$-$RANDOM
+ (umask 077 && mkdir $tmp)
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
-CONFIG_FILES=\${CONFIG_FILES-"${tcl_config_files}"}
-EOF
-cat >> $CONFIG_STATUS <<\EOF
-for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+ # Protect against being on the right side of a sed subst in config.status.
+ sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+ s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@MAN_FLAGS@,$MAN_FLAGS,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@CPP@,$CPP,;t t
+s,@EGREP@,$EGREP,;t t
+s,@TCL_THREADS@,$TCL_THREADS,;t t
+s,@RANLIB@,$RANLIB,;t t
+s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
+s,@AR@,$AR,;t t
+s,@ac_ct_AR@,$ac_ct_AR,;t t
+s,@TCL_LIBS@,$TCL_LIBS,;t t
+s,@DL_LIBS@,$DL_LIBS,;t t
+s,@DL_OBJS@,$DL_OBJS,;t t
+s,@PLAT_OBJS@,$PLAT_OBJS,;t t
+s,@PLAT_SRCS@,$PLAT_SRCS,;t t
+s,@LDAIX_SRC@,$LDAIX_SRC,;t t
+s,@CFLAGS_DEBUG@,$CFLAGS_DEBUG,;t t
+s,@CFLAGS_OPTIMIZE@,$CFLAGS_OPTIMIZE,;t t
+s,@CFLAGS_WARNING@,$CFLAGS_WARNING,;t t
+s,@LDFLAGS_DEBUG@,$LDFLAGS_DEBUG,;t t
+s,@LDFLAGS_OPTIMIZE@,$LDFLAGS_OPTIMIZE,;t t
+s,@CC_SEARCH_FLAGS@,$CC_SEARCH_FLAGS,;t t
+s,@LD_SEARCH_FLAGS@,$LD_SEARCH_FLAGS,;t t
+s,@STLIB_LD@,$STLIB_LD,;t t
+s,@SHLIB_LD@,$SHLIB_LD,;t t
+s,@TCL_SHLIB_LD_EXTRAS@,$TCL_SHLIB_LD_EXTRAS,;t t
+s,@TK_SHLIB_LD_EXTRAS@,$TK_SHLIB_LD_EXTRAS,;t t
+s,@SHLIB_LD_LIBS@,$SHLIB_LD_LIBS,;t t
+s,@SHLIB_CFLAGS@,$SHLIB_CFLAGS,;t t
+s,@SHLIB_SUFFIX@,$SHLIB_SUFFIX,;t t
+s,@MAKE_LIB@,$MAKE_LIB,;t t
+s,@MAKE_STUB_LIB@,$MAKE_STUB_LIB,;t t
+s,@INSTALL_LIB@,$INSTALL_LIB,;t t
+s,@INSTALL_STUB_LIB@,$INSTALL_STUB_LIB,;t t
+s,@CFLAGS_DEFAULT@,$CFLAGS_DEFAULT,;t t
+s,@LDFLAGS_DEFAULT@,$LDFLAGS_DEFAULT,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@DTRACE@,$DTRACE,;t t
+s,@TCL_VERSION@,$TCL_VERSION,;t t
+s,@TCL_MAJOR_VERSION@,$TCL_MAJOR_VERSION,;t t
+s,@TCL_MINOR_VERSION@,$TCL_MINOR_VERSION,;t t
+s,@TCL_PATCH_LEVEL@,$TCL_PATCH_LEVEL,;t t
+s,@TCL_YEAR@,$TCL_YEAR,;t t
+s,@TCL_LIB_FILE@,$TCL_LIB_FILE,;t t
+s,@TCL_LIB_FLAG@,$TCL_LIB_FLAG,;t t
+s,@TCL_LIB_SPEC@,$TCL_LIB_SPEC,;t t
+s,@TCL_STUB_LIB_FILE@,$TCL_STUB_LIB_FILE,;t t
+s,@TCL_STUB_LIB_FLAG@,$TCL_STUB_LIB_FLAG,;t t
+s,@TCL_STUB_LIB_SPEC@,$TCL_STUB_LIB_SPEC,;t t
+s,@TCL_STUB_LIB_PATH@,$TCL_STUB_LIB_PATH,;t t
+s,@TCL_INCLUDE_SPEC@,$TCL_INCLUDE_SPEC,;t t
+s,@TCL_BUILD_STUB_LIB_SPEC@,$TCL_BUILD_STUB_LIB_SPEC,;t t
+s,@TCL_BUILD_STUB_LIB_PATH@,$TCL_BUILD_STUB_LIB_PATH,;t t
+s,@TCL_SRC_DIR@,$TCL_SRC_DIR,;t t
+s,@CFG_TCL_SHARED_LIB_SUFFIX@,$CFG_TCL_SHARED_LIB_SUFFIX,;t t
+s,@CFG_TCL_UNSHARED_LIB_SUFFIX@,$CFG_TCL_UNSHARED_LIB_SUFFIX,;t t
+s,@TCL_SHARED_BUILD@,$TCL_SHARED_BUILD,;t t
+s,@LD_LIBRARY_PATH_VAR@,$LD_LIBRARY_PATH_VAR,;t t
+s,@TCL_BUILD_LIB_SPEC@,$TCL_BUILD_LIB_SPEC,;t t
+s,@TCL_LIB_VERSIONS_OK@,$TCL_LIB_VERSIONS_OK,;t t
+s,@TCL_SHARED_LIB_SUFFIX@,$TCL_SHARED_LIB_SUFFIX,;t t
+s,@TCL_UNSHARED_LIB_SUFFIX@,$TCL_UNSHARED_LIB_SUFFIX,;t t
+s,@TCL_HAS_LONGLONG@,$TCL_HAS_LONGLONG,;t t
+s,@INSTALL_TZDATA@,$INSTALL_TZDATA,;t t
+s,@DTRACE_SRC@,$DTRACE_SRC,;t t
+s,@DTRACE_HDR@,$DTRACE_HDR,;t t
+s,@DTRACE_OBJ@,$DTRACE_OBJ,;t t
+s,@MAKEFILE_SHELL@,$MAKEFILE_SHELL,;t t
+s,@BUILD_DLTEST@,$BUILD_DLTEST,;t t
+s,@TCL_PACKAGE_PATH@,$TCL_PACKAGE_PATH,;t t
+s,@TCL_MODULE_PATH@,$TCL_MODULE_PATH,;t t
+s,@TCL_LIBRARY@,$TCL_LIBRARY,;t t
+s,@PRIVATE_INCLUDE_DIR@,$PRIVATE_INCLUDE_DIR,;t t
+s,@HTML_DIR@,$HTML_DIR,;t t
+s,@EXTRA_CC_SWITCHES@,$EXTRA_CC_SWITCHES,;t t
+s,@EXTRA_APP_CC_SWITCHES@,$EXTRA_APP_CC_SWITCHES,;t t
+s,@EXTRA_INSTALL@,$EXTRA_INSTALL,;t t
+s,@EXTRA_INSTALL_BINARIES@,$EXTRA_INSTALL_BINARIES,;t t
+s,@EXTRA_BUILD_HTML@,$EXTRA_BUILD_HTML,;t t
+s,@EXTRA_TCLSH_LIBS@,$EXTRA_TCLSH_LIBS,;t t
+s,@DLTEST_LD@,$DLTEST_LD,;t t
+s,@DLTEST_SUFFIX@,$DLTEST_SUFFIX,;t t
+CEOF
+
+_ACEOF
+
+ cat >>$CONFIG_STATUS <<\_ACEOF
+ # Split the substitutions into bite-sized pieces for seds with
+ # small command number limits, like on Digital OSF/1 and HP-UX.
+ ac_max_sed_lines=48
+ ac_sed_frag=1 # Number of current file.
+ ac_beg=1 # First line for current file.
+ ac_end=$ac_max_sed_lines # Line after last line for current file.
+ ac_more_lines=:
+ ac_sed_cmds=
+ while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ else
+ sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ fi
+ if test ! -s $tmp/subs.frag; then
+ ac_more_lines=false
+ else
+ # The purpose of the label and of the branching condition is to
+ # speed up the sed processing (if there are no `@' at all, there
+ # is no need to browse any of the substitutions).
+ # These are the two extra sed commands mentioned above.
+ (echo ':t
+ /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+ fi
+ ac_sed_frag=`expr $ac_sed_frag + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_lines`
+ fi
+ done
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+ fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
# Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
- case "$ac_file" in
- *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
- ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
- *) ac_file_in="${ac_file}.in" ;;
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
esac
- # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+ # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
- # Remove last slash and all that follows it. Not all systems have dirname.
- ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
- if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
- # The file is in a subdirectory.
- test ! -d "$ac_dir" && mkdir "$ac_dir"
- ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
- # A "../" for each directory in $ac_dir_suffix.
- ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+
+ if test x"$ac_file" != x-; then
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ rm -f "$ac_file"
+ fi
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ if test x"$ac_file" = x-; then
+ configure_input=
else
- ac_dir_suffix= ac_dots=
+ configure_input="$ac_file. "
fi
+ configure_input=$configure_input"Generated from `echo $ac_file_in |
+ sed 's,.*/,,'` by configure."
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ echo "$f";;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo "$f"
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo "$srcdir/$f"
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+ rm -f $tmp/stdin
+ if test x"$ac_file" != x-; then
+ mv $tmp/out $ac_file
+ else
+ cat $tmp/out
+ rm -f $tmp/out
+ fi
+
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
- case "$ac_given_srcdir" in
- .) srcdir=.
- if test -z "$ac_dots"; then top_srcdir=.
- else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
- /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+#
+# CONFIG_COMMANDS section.
+#
+for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue
+ ac_dest=`echo "$ac_file" | sed 's,:.*,,'`
+ ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_dir=`(dirname "$ac_dest") 2>/dev/null ||
+$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_dest" : 'X\(//\)[^/]' \| \
+ X"$ac_dest" : 'X\(//\)$' \| \
+ X"$ac_dest" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_dest" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
*) # Relative path.
- srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
- top_srcdir="$ac_dots$ac_given_srcdir" ;;
- esac
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
- echo creating "$ac_file"
- rm -f "$ac_file"
- configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
- case "$ac_file" in
- *Makefile*) ac_comsub="1i\\
-# $configure_input" ;;
- *) ac_comsub= ;;
+ { echo "$as_me:$LINENO: executing $ac_dest commands" >&5
+echo "$as_me: executing $ac_dest commands" >&6;}
+ case $ac_dest in
+ Tcl.framework ) n=Tcl &&
+ f=$n.framework && v=Versions/$VERSION &&
+ rm -rf $f && mkdir -p $f/$v/Resources &&
+ ln -s $v/$n $v/Resources $f && ln -s ../../../$n $f/$v &&
+ ln -s ../../../../$n-Info.plist $f/$v/Resources/Info.plist &&
+ unset n f v
+ ;;
esac
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
- ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
- sed -e "$ac_comsub
-s%@configure_input@%$configure_input%g
-s%@srcdir@%$srcdir%g
-s%@top_srcdir@%$top_srcdir%g
-" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
-fi; done
-rm -f conftest.s*
-
-EOF
-cat >> $CONFIG_STATUS <<EOF
-VERSION=${TCL_VERSION} FRAMEWORK_BUILD=${FRAMEWORK_BUILD}
-
-EOF
-cat >> $CONFIG_STATUS <<\EOF
-test "$FRAMEWORK_BUILD" = "1" && n=Tcl &&
- f=$n.framework && v=Versions/$VERSION &&
- echo "creating $f" && rm -rf $f && mkdir -p $f/$v/Resources &&
- ln -s $v/$n $v/Resources $f && ln -s ../../../$n $f/$v &&
- ln -s ../../../../$n-Info.plist $f/$v/Resources/Info.plist &&
- unset n f v
-
-
-exit 0
-EOF
+{ (exit 0); exit 0; }
+_ACEOF
chmod +x $CONFIG_STATUS
-rm -fr confdefs* $ac_clean_files
-test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
diff --git a/unix/configure.in b/unix/configure.in
index 49e034d..3394369 100644
--- a/unix/configure.in
+++ b/unix/configure.in
@@ -3,13 +3,29 @@ dnl This file is an input file used by the GNU "autoconf" program to
dnl generate the file "configure", which is run during Tcl installation
dnl to configure the system for the local environment.
-AC_INIT(../generic/tcl.h)
-AC_PREREQ(2.13)
+AC_INIT([tcl],[8.5])
+AC_PREREQ(2.59)
+
+dnl This is only used when included from macosx/configure.ac
+m4_ifdef([SC_USE_CONFIG_HEADERS], [
+ AC_CONFIG_HEADERS([tclConfig.h:../unix/tclConfig.h.in])
+ AC_CONFIG_COMMANDS_PRE([DEFS="-DHAVE_TCL_CONFIG_H -imacros tclConfig.h"])
+ AH_TOP([
+ #ifndef _TCLCONFIG
+ #define _TCLCONFIG])
+ AH_BOTTOM([
+ /* Undef unused package specific autoheader defines so that we can
+ * include both tclConfig.h and tkConfig.h at the same time: */
+ /* override */ #undef PACKAGE_NAME
+ /* override */ #undef PACKAGE_STRING
+ /* override */ #undef PACKAGE_TARNAME
+ #endif /* _TCLCONFIG */])
+])
-TCL_VERSION=8.4
+TCL_VERSION=8.5
TCL_MAJOR_VERSION=8
-TCL_MINOR_VERSION=4
-TCL_PATCH_LEVEL=".19"
+TCL_MINOR_VERSION=5
+TCL_PATCH_LEVEL=".10"
VERSION=${TCL_VERSION}
#------------------------------------------------------------------------
@@ -23,14 +39,14 @@ if test "${exec_prefix}" = "NONE"; then
exec_prefix=$prefix
fi
# Make sure srcdir is fully qualified!
-srcdir=`cd $srcdir ; pwd`
-TCL_SRC_DIR=`cd $srcdir/..; pwd`
+srcdir="`cd "$srcdir" ; pwd`"
+TCL_SRC_DIR="`cd "$srcdir"/..; pwd`"
#------------------------------------------------------------------------
# Compress and/or soft link the manpages?
#------------------------------------------------------------------------
-SC_CONFIG_MANPAGES([tcl])
+SC_CONFIG_MANPAGES
#------------------------------------------------------------------------
# Standard compiler checks
@@ -43,6 +59,7 @@ if test "${CFLAGS+set}" != "set" ; then
fi
AC_PROG_CC
+AC_C_INLINE
#--------------------------------------------------------------------
# Supply substitutes for missing POSIX header files. Special notes:
@@ -77,6 +94,12 @@ fi
SC_ENABLE_THREADS
+#------------------------------------------------------------------------
+# Embedded configuration information, encoding to use for the values, TIP #59
+#------------------------------------------------------------------------
+
+SC_TCL_CFG_ENCODING
+
#--------------------------------------------------------------------
# Look for libraries that we will need when compiling the Tcl shell
#--------------------------------------------------------------------
@@ -96,9 +119,10 @@ SC_ENABLE_SHARED
SC_CONFIG_CFLAGS
-SC_ENABLE_SYMBOLS
+SC_ENABLE_SYMBOLS(bccdebug)
-TCL_DBGX=${DBGX}
+AC_DEFINE(TCL_TOMMATH, 1, [Build libtommath?])
+AC_DEFINE(MP_PREC, 4, [Default libtommath precision.])
#--------------------------------------------------------------------
# Detect what compiler flags to set for 64-bit support.
@@ -121,15 +145,15 @@ AC_C_BIGENDIAN
#--------------------------------------------------------------------
# Check if Posix compliant getcwd exists, if not we'll use getwd.
-AC_CHECK_FUNCS(getcwd, , [AC_DEFINE(USEGETWD)])
+AC_CHECK_FUNCS(getcwd, , [AC_DEFINE(USEGETWD, 1, [Is getcwd Posix-compliant?])])
# Nb: if getcwd uses popen and pwd(1) (like SunOS 4) we should really
# define USEGETWD even if the posix getcwd exists. Add a test ?
-AC_REPLACE_FUNCS(opendir strstr strtol strtoll strtoull tmpnam waitpid)
-AC_CHECK_FUNC(strerror, , [AC_DEFINE(NO_STRERROR)])
-AC_CHECK_FUNC(getwd, , [AC_DEFINE(NO_GETWD)])
-AC_CHECK_FUNC(wait3, , [AC_DEFINE(NO_WAIT3)])
-AC_CHECK_FUNC(uname, , [AC_DEFINE(NO_UNAME)])
+AC_REPLACE_FUNCS(opendir strtol waitpid)
+AC_CHECK_FUNC(strerror, , [AC_DEFINE(NO_STRERROR, 1, [Do we have strerror()])])
+AC_CHECK_FUNC(getwd, , [AC_DEFINE(NO_GETWD, 1, [Do we have getwd()])])
+AC_CHECK_FUNC(wait3, , [AC_DEFINE(NO_WAIT3, 1, [Do we have wait3()])])
+AC_CHECK_FUNC(uname, , [AC_DEFINE(NO_UNAME, 1, [Do we have uname()])])
if test "`uname -s`" = "Darwin" && test "${TCL_THREADS}" = 1 && \
test "`uname -r | awk -F. '{print [$]1}'`" -lt 7; then
@@ -137,9 +161,11 @@ if test "`uname -s`" = "Darwin" && test "${TCL_THREADS}" = 1 && \
# use it when threads are enabled, c.f. bug # 711232
ac_cv_func_realpath=no
fi
-AC_CHECK_FUNC(realpath, , [AC_DEFINE(NO_REALPATH)])
+AC_CHECK_FUNC(realpath, , [AC_DEFINE(NO_REALPATH, 1, [Do we have realpath()])])
-#--------------------------------------------------------------------
+SC_TCL_GETADDRINFO
+
+#--------------------------------------------------------------------
# Look for thread-safe variants of some library functions.
#--------------------------------------------------------------------
@@ -150,18 +176,24 @@ if test "${TCL_THREADS}" = 1; then
SC_TCL_GETGRNAM_R
if test "`uname -s`" = "Darwin" && \
test "`uname -r | awk -F. '{print [$]1}'`" -gt 5; then
- # Starting with Darwin 6 (Mac OSX 10.2), gethostbyX
+ # Starting with Darwin 6 (Mac OSX 10.2), gethostbyX
# are actually MT-safe as they always return pointers
- # from the TSD instead of the static storage.
- AC_DEFINE(HAVE_MTSAFE_GETHOSTBYNAME)
- AC_DEFINE(HAVE_MTSAFE_GETHOSTBYADDR)
+ # from TSD instead of static storage.
+ AC_DEFINE(HAVE_MTSAFE_GETHOSTBYNAME, 1,
+ [Do we have MT-safe gethostbyname() ?])
+ AC_DEFINE(HAVE_MTSAFE_GETHOSTBYADDR, 1,
+ [Do we have MT-safe gethostbyaddr() ?])
+
elif test "`uname -s`" = "HP-UX" && \
test "`uname -r|sed -e 's|B\.||' -e 's|\..*$||'`" -gt 10; then
# Starting with HPUX 11.00 (we believe), gethostbyX
# are actually MT-safe as they always return pointers
# from TSD instead of static storage.
- AC_DEFINE(HAVE_MTSAFE_GETHOSTBYNAME)
- AC_DEFINE(HAVE_MTSAFE_GETHOSTBYADDR)
+ AC_DEFINE(HAVE_MTSAFE_GETHOSTBYNAME, 1,
+ [Do we have MT-safe gethostbyname() ?])
+ AC_DEFINE(HAVE_MTSAFE_GETHOSTBYADDR, 1,
+ [Do we have MT-safe gethostbyaddr() ?])
+
else
SC_TCL_GETHOSTBYNAME_R
SC_TCL_GETHOSTBYADDR_R
@@ -195,12 +227,12 @@ if test $tcl_ok = no; then
AC_EGREP_HEADER(fd_mask, sys/select.h,
tcl_cv_grep_fd_mask=present, tcl_cv_grep_fd_mask=missing)])
if test $tcl_cv_grep_fd_mask = present; then
- AC_DEFINE(HAVE_SYS_SELECT_H)
+ AC_DEFINE(HAVE_SYS_SELECT_H, 1, [Should we include <sys/select.h>?])
tcl_ok=yes
fi
fi
if test $tcl_ok = no; then
- AC_DEFINE(NO_FD_SET)
+ AC_DEFINE(NO_FD_SET, 1, [Do we have fd_set?])
fi
#------------------------------------------------------------------------------
@@ -210,16 +242,20 @@ fi
SC_TIME_HANDLER
#--------------------------------------------------------------------
-# Some systems (e.g., IRIX 4.0.5) lack the st_blksize field
-# in struct stat. But we might be able to use fstatfs instead.
+# Some systems (e.g., IRIX 4.0.5) lack some fields in struct stat. But
+# we might be able to use fstatfs instead. Some systems (OpenBSD?) also
+# lack blkcnt_t.
#--------------------------------------------------------------------
-AC_STRUCT_ST_BLKSIZE
-AC_CHECK_FUNC(fstatfs, , [AC_DEFINE(NO_FSTATFS)])
+
+AC_CHECK_MEMBERS([struct stat.st_blocks, struct stat.st_blksize])
+AC_CHECK_TYPES([blkcnt_t])
+AC_CHECK_FUNC(fstatfs, , [AC_DEFINE(NO_FSTATFS, 1, [Do we have fstatfs()?])])
#--------------------------------------------------------------------
# Some system have no memcmp or it does not work with 8 bit
# data, this checks it and add memcmp.o to LIBOBJS if needed
#--------------------------------------------------------------------
+
AC_FUNC_MEMCMP
#--------------------------------------------------------------------
@@ -227,26 +263,20 @@ AC_FUNC_MEMCMP
# have no memmove (we assume they have bcopy instead).
# {The replacement define is in compat/string.h}
#--------------------------------------------------------------------
-AC_CHECK_FUNC(memmove, , [AC_DEFINE(NO_MEMMOVE) AC_DEFINE(NO_STRING_H)])
+
+AC_CHECK_FUNC(memmove, , [
+ AC_DEFINE(NO_MEMMOVE, 1, [Do we have memmove()?])
+ AC_DEFINE(NO_STRING_H, 1, [Do we have <string.h>?]) ])
#--------------------------------------------------------------------
# On some systems strstr is broken: it returns a pointer even
# even if the original string is empty.
#--------------------------------------------------------------------
-dnl only run if AC_REPLACE_FUNCS(strstr) hasn't already added strstr.o
-if test "x${ac_cv_func_strstr}" = "xyes"; then
- AC_CACHE_CHECK([proper strstr implementation], tcl_cv_strstr_unbroken, [
- AC_TRY_RUN([
- extern int strstr();
- int main()
- {
- exit(strstr("\0test", "test") ? 1 : 0);
- }], tcl_cv_strstr_unbroken=ok, tcl_cv_strstr_unbroken=broken,
- tcl_cv_strstr_unbroken=broken)])
- if test $tcl_cv_strstr_unbroken = broken; then
- LIBOBJS="$LIBOBJS strstr.o"
- fi
-fi
+
+SC_TCL_CHECK_BROKEN_FUNC(strstr, [
+ extern int strstr();
+ exit(strstr("\0test", "test") ? 1 : 0);
+])
#--------------------------------------------------------------------
# Check for strtoul function. This is tricky because under some
@@ -254,60 +284,22 @@ fi
# pointer for the string "0".
#--------------------------------------------------------------------
-AC_CHECK_FUNC(strtoul, tcl_ok=1, tcl_ok=0)
-if test $tcl_ok = 1; then
- AC_CACHE_CHECK([proper strtoul implementation], tcl_cv_strtoul_unbroken, [
- AC_TRY_RUN([
- extern int strtoul();
- int main()
- {
- char *string = "0";
- char *term;
- int value;
- value = strtoul(string, &term, 0);
- if ((value != 0) || (term != (string+1))) {
- exit(1);
- }
- exit(0);
- }], tcl_cv_strtoul_unbroken=ok , tcl_cv_strtoul_unbroken=broken,
- tcl_cv_strtoul_unbroken=broken)])
- if test $tcl_cv_strtoul_unbroken = broken; then
- tcl_ok=0
- fi
-fi
-if test $tcl_ok = 0; then
- LIBOBJS="$LIBOBJS strtoul.o"
-fi
+SC_TCL_CHECK_BROKEN_FUNC(strtoul, [
+ extern int strtoul();
+ char *term, *string = "0";
+ exit(strtoul(string,&term,0) != 0 || term != string+1);
+])
#--------------------------------------------------------------------
# Check for the strtod function. This is tricky because in some
# versions of Linux strtod mis-parses strings starting with "+".
#--------------------------------------------------------------------
-AC_CHECK_FUNC(strtod, tcl_ok=1, tcl_ok=0)
-if test $tcl_ok = 1; then
- AC_CACHE_CHECK([proper strtod implementation], tcl_cv_strtod_unbroken, [
- AC_TRY_RUN([
- extern double strtod();
- int main()
- {
- char *string = " +69";
- char *term;
- double value;
- value = strtod(string, &term);
- if ((value != 69) || (term != (string+4))) {
- exit(1);
- }
- exit(0);
- }], tcl_cv_strtod_unbroken=ok , tcl_cv_strtod_unbroken=broken,
- tcl_cv_strtod_unbroken=broken)])
- if test $tcl_cv_strtod_unbroken = broken; then
- tcl_ok=0
- fi
-fi
-if test $tcl_ok = 0; then
- LIBOBJS="$LIBOBJS strtod.o"
-fi
+SC_TCL_CHECK_BROKEN_FUNC(strtod, [
+ extern double strtod();
+ char *term, *string = " +69";
+ exit(strtod(string,&term) != 69 || term != string+4);
+])
#--------------------------------------------------------------------
# Under Solaris 2.4, strtod returns the wrong value for the
@@ -328,21 +320,49 @@ AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_TYPE_UID_T
-AC_CACHE_CHECK([for socklen_t], ac_cv_type_socklen_t, [
- AC_EGREP_CPP(changequote(<<,>>)dnl
-<<(^|[^a-zA-Z_0-9])socklen_t[^a-zA-Z_0-9]>>dnl
-changequote([,]),[
- #include <sys/types.h>
- #include <sys/socket.h>
- #if STDC_HEADERS
- #include <stdlib.h>
- #include <stddef.h>
- #endif
- ], ac_cv_type_socklen_t=yes, ac_cv_type_socklen_t=no)])
-if test $ac_cv_type_socklen_t = no; then
- AC_DEFINE(socklen_t, unsigned)
+AC_CACHE_CHECK([for socklen_t], tcl_cv_type_socklen_t, [
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ ],[
+ socklen_t foo;
+ ],[tcl_cv_type_socklen_t=yes],[tcl_cv_type_socklen_t=no])])
+if test $tcl_cv_type_socklen_t = no; then
+ AC_DEFINE(socklen_t, int, [Define as int if socklen_t is not available])
fi
+AC_CHECK_TYPE([intptr_t], [
+ AC_DEFINE([HAVE_INTPTR_T], 1, [Do we have the intptr_t type?])], [
+ AC_CACHE_CHECK([for pointer-size signed integer type], tcl_cv_intptr_t, [
+ for tcl_cv_intptr_t in "int" "long" "long long" none; do
+ if test "$tcl_cv_intptr_t" != none; then
+ AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT],
+ [[sizeof (void *) <= sizeof ($tcl_cv_intptr_t)]])],
+ [tcl_ok=yes], [tcl_ok=no])
+ test "$tcl_ok" = yes && break; fi
+ done])
+ if test "$tcl_cv_intptr_t" != none; then
+ AC_DEFINE_UNQUOTED([intptr_t], [$tcl_cv_intptr_t], [Signed integer
+ type wide enough to hold a pointer.])
+ fi
+])
+AC_CHECK_TYPE([uintptr_t], [
+ AC_DEFINE([HAVE_UINTPTR_T], 1, [Do we have the uintptr_t type?])], [
+ AC_CACHE_CHECK([for pointer-size unsigned integer type], tcl_cv_uintptr_t, [
+ for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \
+ none; do
+ if test "$tcl_cv_uintptr_t" != none; then
+ AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT],
+ [[sizeof (void *) <= sizeof ($tcl_cv_uintptr_t)]])],
+ [tcl_ok=yes], [tcl_ok=no])
+ test "$tcl_ok" = yes && break; fi
+ done])
+ if test "$tcl_cv_uintptr_t" != none; then
+ AC_DEFINE_UNQUOTED([uintptr_t], [$tcl_cv_uintptr_t], [Unsigned integer
+ type wide enough to hold a pointer.])
+ fi
+])
+
#--------------------------------------------------------------------
# If a system doesn't have an opendir function (man, that's old!)
# then we have to supply a different version of dirent.h which
@@ -350,7 +370,7 @@ fi
# provided. This version only works with V7-style directories.
#--------------------------------------------------------------------
-AC_CHECK_FUNC(opendir, , [AC_DEFINE(USE_DIRENT2_H)])
+AC_CHECK_FUNC(opendir, , [AC_DEFINE(USE_DIRENT2_H, 1, [May we include <dirent2.h>?])])
#--------------------------------------------------------------------
# The check below checks whether <sys/wait.h> defines the type
@@ -368,7 +388,7 @@ WIFEXITED(x); /* Generates compiler error if WIFEXITED
* uses an int. */
], tcl_cv_union_wait=yes, tcl_cv_union_wait=no)])
if test $tcl_cv_union_wait = no; then
- AC_DEFINE(NO_UNION_WAIT)
+ AC_DEFINE(NO_UNION_WAIT, 1, [Do we have a usable 'union wait'?])
fi
#--------------------------------------------------------------------
@@ -385,7 +405,8 @@ if test "$tcl_ok" = 0; then
AC_CHECK_LIB(inet, strncasecmp, tcl_ok=1, tcl_ok=0)
fi
if test "$tcl_ok" = 0; then
- LIBOBJS="$LIBOBJS strncasecmp.o"
+ AC_LIBOBJ([strncasecmp])
+ USE_COMPAT=1
fi
#--------------------------------------------------------------------
@@ -400,14 +421,14 @@ fi
#--------------------------------------------------------------------
AC_CHECK_FUNC(BSDgettimeofday,
- [AC_DEFINE(HAVE_BSDGETTIMEOFDAY)], [
- AC_CHECK_FUNC(gettimeofday, , [AC_DEFINE(NO_GETTOD)])
+ [AC_DEFINE(HAVE_BSDGETTIMEOFDAY, 1, [Do we have BSDgettimeofday()?])], [
+ AC_CHECK_FUNC(gettimeofday, , [AC_DEFINE(NO_GETTOD, 1, [Do we have gettimeofday()?])])
])
AC_CACHE_CHECK([for gettimeofday declaration], tcl_cv_grep_gettimeofday, [
AC_EGREP_HEADER(gettimeofday, sys/time.h,
tcl_cv_grep_gettimeofday=present, tcl_cv_grep_gettimeofday=missing)])
if test $tcl_cv_grep_gettimeofday = missing ; then
- AC_DEFINE(GETTOD_NOT_DECLARED)
+ AC_DEFINE(GETTOD_NOT_DECLARED, 1, [Is gettimeofday() actually declared in <sys/time.h>?])
fi
#--------------------------------------------------------------------
@@ -423,7 +444,7 @@ AC_CACHE_CHECK([signed char declarations], tcl_cv_char_signed, [
p = 0;
], tcl_cv_char_signed=yes, tcl_cv_char_signed=no)])
if test $tcl_cv_char_signed = yes; then
- AC_DEFINE(HAVE_SIGNED_CHAR)
+ AC_DEFINE(HAVE_SIGNED_CHAR, 1, [Are characters signed?])
fi
#--------------------------------------------------------------------
@@ -454,7 +475,8 @@ AC_CACHE_CHECK([for a putenv() that copies the buffer], tcl_cv_putenv_copy, [
tcl_cv_putenv_copy=yes,
tcl_cv_putenv_copy=no)])
if test $tcl_cv_putenv_copy = yes; then
- AC_DEFINE(HAVE_PUTENV_THAT_COPIES)
+ AC_DEFINE(HAVE_PUTENV_THAT_COPIES, 1,
+ [Does putenv() copy strings or incorporate them by reference?])
fi
#--------------------------------------------------------------------
@@ -464,10 +486,29 @@ fi
SC_ENABLE_LANGINFO
#--------------------------------------------------------------------
+# Check for support of chflags function
+#--------------------------------------------------------------------
+
+AC_CHECK_FUNCS(chflags)
+
+#--------------------------------------------------------------------
+# Check for support of isnan() function or macro
+#--------------------------------------------------------------------
+
+AC_CACHE_CHECK([isnan], tcl_cv_isnan, [
+ AC_TRY_LINK([#include <math.h>], [
+isnan(0.0); /* Generates an error if isnan is missing */
+], tcl_cv_isnan=yes, tcl_cv_isnan=no)])
+if test $tcl_cv_isnan = no; then
+ AC_DEFINE(NO_ISNAN, 1, [Do we have a usable 'isnan'?])
+fi
+
+#--------------------------------------------------------------------
# Darwin specific API checks and defines
#--------------------------------------------------------------------
if test "`uname -s`" = "Darwin" ; then
+ AC_CHECK_FUNCS(getattrlist)
AC_CHECK_HEADERS(copyfile.h)
AC_CHECK_FUNCS(copyfile)
if test $tcl_corefoundation = yes; then
@@ -475,9 +516,13 @@ if test "`uname -s`" = "Darwin" ; then
AC_CHECK_FUNCS(OSSpinLockLock)
AC_CHECK_FUNCS(pthread_atfork)
fi
- AC_DEFINE(USE_VFORK)
- AC_DEFINE(TCL_DEFAULT_ENCODING, "utf-8")
- AC_DEFINE(TCL_LOAD_FROM_MEMORY)
+ AC_DEFINE(USE_VFORK, 1, [Should we use vfork() instead of fork()?])
+ AC_DEFINE(TCL_DEFAULT_ENCODING, "utf-8",
+ [Are we to override what our default encoding is?])
+ AC_DEFINE(TCL_LOAD_FROM_MEMORY, 1,
+ [Can this platform load code from memory?])
+ AC_DEFINE(TCL_WIDE_CLICKS, 1,
+ [Does this platform have wide high-resolution clicks?])
AC_CHECK_HEADERS(AvailabilityMacros.h)
if test "$ac_cv_header_AvailabilityMacros_h" = yes; then
AC_CACHE_CHECK([if weak import is available], tcl_cv_cc_weak_import, [
@@ -495,9 +540,34 @@ if test "`uname -s`" = "Darwin" ; then
tcl_cv_cc_weak_import=yes, tcl_cv_cc_weak_import=no)
CFLAGS=$hold_cflags])
if test $tcl_cv_cc_weak_import = yes; then
- AC_DEFINE(HAVE_WEAK_IMPORT)
+ AC_DEFINE(HAVE_WEAK_IMPORT, 1, [Is weak import available?])
+ fi
+ AC_CACHE_CHECK([if Darwin SUSv3 extensions are available],
+ tcl_cv_cc_darwin_c_source, [
+ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
+ AC_TRY_COMPILE([
+ #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
+ #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
+ #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
+ #endif
+ #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+ #error MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+ #endif
+ #define _DARWIN_C_SOURCE 1
+ #include <sys/cdefs.h>
+ ],,tcl_cv_cc_darwin_c_source=yes, tcl_cv_cc_darwin_c_source=no)
+ CFLAGS=$hold_cflags])
+ if test $tcl_cv_cc_darwin_c_source = yes; then
+ AC_DEFINE(_DARWIN_C_SOURCE, 1,
+ [Are Darwin SUSv3 extensions available?])
fi
fi
+ # Build .bundle dltest binaries in addition to .dylib
+ DLTEST_LD='${CC} -bundle -Wl,-w ${CFLAGS} ${LDFLAGS}'
+ DLTEST_SUFFIX=".bundle"
+else
+ DLTEST_LD='${SHLIB_LD}'
+ DLTEST_SUFFIX=""
fi
#--------------------------------------------------------------------
@@ -515,7 +585,7 @@ AC_CACHE_CHECK([for fts], tcl_cv_api_fts, [
FTSENT *e = fts_read(f); fts_close(f);
], tcl_cv_api_fts=yes, tcl_cv_api_fts=no)])
if test $tcl_cv_api_fts = yes; then
- AC_DEFINE(HAVE_FTS)
+ AC_DEFINE(HAVE_FTS, 1, [Do we have fts functions?])
fi
#--------------------------------------------------------------------
@@ -527,12 +597,76 @@ fi
SC_BLOCKING_STYLE
+#------------------------------------------------------------------------
+
+AC_MSG_CHECKING([whether to use dll unloading])
+AC_ARG_ENABLE(dll-unloading,
+ AC_HELP_STRING([--enable-dll-unloading],
+ [enable the 'unload' command (default: on)]),
+ [tcl_ok=$enableval], [tcl_ok=yes])
+if test $tcl_ok = yes; then
+ AC_DEFINE(TCL_UNLOAD_DLLS, 1, [Do we allow unloading of shared libraries?])
+fi
+AC_MSG_RESULT([$tcl_ok])
+
+#------------------------------------------------------------------------
+# Check whether the timezone data is supplied by the OS or has
+# to be installed by Tcl. The default is autodetection, but can
+# be overriden on the configure command line either way.
+#------------------------------------------------------------------------
+
+AC_MSG_CHECKING([for timezone data])
+AC_ARG_WITH(tzdata,
+ AC_HELP_STRING([--with-tzdata],
+ [install timezone data (default: autodetect)]),
+ [tcl_ok=$withval], [tcl_ok=auto])
+#
+# Any directories that get added here must also be added to the
+# search path in ::tcl::clock::Initialize (library/clock.tcl).
+#
+case $tcl_ok in
+ no)
+ AC_MSG_RESULT([supplied by OS vendor])
+ ;;
+ yes)
+ # nothing to do here
+ ;;
+ auto*)
+ AC_CACHE_VAL([tcl_cv_dir_zoneinfo], [
+ for dir in /usr/share/zoneinfo \
+ /usr/share/lib/zoneinfo \
+ /usr/lib/zoneinfo
+ do
+ if test -f $dir/UTC -o -f $dir/GMT
+ then
+ tcl_cv_dir_zoneinfo="$dir"
+ break
+ fi
+ done])
+ if test -n "$tcl_cv_dir_zoneinfo"; then
+ tcl_ok=no
+ AC_MSG_RESULT([$dir])
+ else
+ tcl_ok=yes
+ fi
+ ;;
+ *)
+ AC_MSG_ERROR([invalid argument: $tcl_ok])
+ ;;
+esac
+if test $tcl_ok = yes
+then
+ AC_MSG_RESULT([supplied by Tcl])
+ INSTALL_TZDATA=install-tzdata
+fi
+
#--------------------------------------------------------------------
# DTrace support
#--------------------------------------------------------------------
AC_ARG_ENABLE(dtrace,
- [ --enable-dtrace build with DTrace support [--disable-dtrace]],
+ AC_HELP_STRING([--enable-dtrace],
+ [build with DTrace support (default: off)]),
[tcl_ok=$enableval], [tcl_ok=no])
if test $tcl_ok = yes; then
AC_CHECK_HEADER(sys/sdt.h, [tcl_ok=yes], [tcl_ok=no])
@@ -544,7 +678,7 @@ fi
AC_MSG_CHECKING([whether to enable DTrace support])
MAKEFILE_SHELL='/bin/sh'
if test $tcl_ok = yes; then
- AC_DEFINE(USE_DTRACE)
+ AC_DEFINE(USE_DTRACE, 1, [Are we building with DTrace support?])
DTRACE_SRC="\${DTRACE_SRC}"
DTRACE_HDR="\${DTRACE_HDR}"
if test "`uname -s`" != "Darwin" ; then
@@ -564,6 +698,32 @@ fi
AC_MSG_RESULT([$tcl_ok])
#--------------------------------------------------------------------
+# Does the C stack grow upwards or downwards? Or cross-compiling?
+#--------------------------------------------------------------------
+
+AC_CACHE_CHECK([if the C stack grows upwards in memory], tcl_cv_stack_grows_up, [
+ AC_TRY_RUN([
+ int StackGrowsUp(int *parent) {
+ int here;
+ volatile int result;
+ if (parent)
+ result = (&here < parent);
+ else
+ result = StackGrowsUp(&here);
+ return result;
+ }
+ int main (int argc, char *argv[]) {
+ return StackGrowsUp(0);
+ }
+ ], tcl_cv_stack_grows_up=yes, tcl_cv_stack_grows_up=no,
+ tcl_cv_stack_grows_up=unknown)])
+if test $tcl_cv_stack_grows_up = unknown; then
+ AC_DEFINE(TCL_CROSS_COMPILE, 1, [Are we cross-compiling?])
+elif test $tcl_cv_stack_grows_up = yes; then
+ AC_DEFINE(TCL_STACK_GROWS_UP, 1, [The C stack grows upwards in memory.])
+fi
+
+#--------------------------------------------------------------------
# The statements below define a collection of symbols related to
# building libtcl as a shared library instead of a static library.
#--------------------------------------------------------------------
@@ -573,10 +733,9 @@ TCL_SHARED_LIB_SUFFIX=${SHARED_LIB_SUFFIX}
eval "TCL_LIB_FILE=libtcl${LIB_SUFFIX}"
# tclConfig.sh needs a version of the _LIB_SUFFIX that has been eval'ed
-# so that the backslashes quoting the DBX braces are dropped.
+# since on some platforms TCL_LIB_FILE contains shell escapes.
+# (See also: TCL_TRIM_DOTS).
-# Trick to replace DBGX with TCL_DBGX
-DBGX='${TCL_DBGX}'
eval "TCL_LIB_FILE=${TCL_LIB_FILE}"
TCL_LIBRARY='$(prefix)/lib/tcl$(VERSION)'
@@ -591,26 +750,26 @@ HTML_DIR='$(DISTDIR)/html'
if test "`uname -s`" = "Darwin" ; then
SC_ENABLE_FRAMEWORK
TCL_SHLIB_LD_EXTRAS="-compatibility_version ${TCL_VERSION} -current_version ${TCL_VERSION}`echo ${TCL_PATCH_LEVEL} | awk ['{match($0, "\\\.[0-9]+"); print substr($0,RSTART,RLENGTH)}']`"
- TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -install_name ${DYLIB_INSTALL_DIR}/${TCL_LIB_FILE}'
+ TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -install_name "${DYLIB_INSTALL_DIR}"/${TCL_LIB_FILE}'
echo "$LDFLAGS " | grep -q -- '-prebind ' && TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -seg1addr 0xa000000'
TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -sectcreate __TEXT __info_plist Tcl-Info.plist'
EXTRA_TCLSH_LIBS='-sectcreate __TEXT __info_plist Tclsh-Info.plist'
EXTRA_APP_CC_SWITCHES='-mdynamic-no-pic'
- tcl_config_files="${tcl_config_files} [Tcl-Info.plist:../macosx/Tcl-Info.plist.in Tclsh-Info.plist:../macosx/Tclsh-Info.plist.in]"
+ AC_CONFIG_FILES([Tcl-Info.plist:../macosx/Tcl-Info.plist.in Tclsh-Info.plist:../macosx/Tclsh-Info.plist.in])
TCL_YEAR="`date +%Y`"
fi
if test "$FRAMEWORK_BUILD" = "1" ; then
- AC_DEFINE(TCL_FRAMEWORK)
+ AC_DEFINE(TCL_FRAMEWORK, 1, [Is Tcl built as a framework?])
# Construct a fake local framework structure to make linking with
# '-framework Tcl' and running of tcltest work
- AC_OUTPUT_COMMANDS([test "$FRAMEWORK_BUILD" = "1" && n=Tcl &&
- f=$n.framework && v=Versions/$VERSION &&
- echo "creating $f" && rm -rf $f && mkdir -p $f/$v/Resources &&
- ln -s $v/$n $v/Resources $f && ln -s ../../../$n $f/$v &&
- ln -s ../../../../$n-Info.plist $f/$v/Resources/Info.plist &&
- unset n f v
- ], [VERSION=${TCL_VERSION} FRAMEWORK_BUILD=${FRAMEWORK_BUILD}])
+ AC_CONFIG_COMMANDS([Tcl.framework], [n=Tcl &&
+ f=$n.framework && v=Versions/$VERSION &&
+ rm -rf $f && mkdir -p $f/$v/Resources &&
+ ln -s $v/$n $v/Resources $f && ln -s ../../../$n $f/$v &&
+ ln -s ../../../../$n-Info.plist $f/$v/Resources/Info.plist &&
+ unset n f v
+ ], VERSION=${TCL_VERSION})
LD_LIBRARY_PATH_VAR="DYLD_FRAMEWORK_PATH"
if test "${libdir}" = '${exec_prefix}/lib'; then
# override libdir default
@@ -618,7 +777,7 @@ if test "$FRAMEWORK_BUILD" = "1" ; then
fi
TCL_LIB_FILE="Tcl"
TCL_LIB_FLAG="-framework Tcl"
- TCL_BUILD_LIB_SPEC="-F`pwd` -framework Tcl"
+ TCL_BUILD_LIB_SPEC="-F`pwd | sed -e 's/ /\\\\ /g'` -framework Tcl"
TCL_LIB_SPEC="-F${libdir} -framework Tcl"
libdir="${libdir}/Tcl.framework/Versions/\${VERSION}"
TCL_LIBRARY="${libdir}/Resources/Scripts"
@@ -626,7 +785,7 @@ if test "$FRAMEWORK_BUILD" = "1" ; then
PRIVATE_INCLUDE_DIR="${libdir}/PrivateHeaders"
HTML_DIR="${libdir}/Resources/Documentation/Reference/Tcl"
EXTRA_INSTALL="install-private-headers html-tcl"
- EXTRA_BUILD_HTML='@ln -fs contents.htm $(HTML_INSTALL_DIR)/TclTOC.html'
+ EXTRA_BUILD_HTML='@ln -fs contents.htm "$(HTML_INSTALL_DIR)"/TclTOC.html'
EXTRA_INSTALL_BINARIES='@echo "Installing Info.plist to $(LIB_INSTALL_DIR)/Resources" && mkdir -p "$(LIB_INSTALL_DIR)/Resources" && $(INSTALL_DATA) Tcl-Info.plist "$(LIB_INSTALL_DIR)/Resources/Info.plist"'
EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing license.terms to $(LIB_INSTALL_DIR)/Resources" && $(INSTALL_DATA) "$(TOP_DIR)/license.terms" "$(LIB_INSTALL_DIR)/Resources"'
EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Finalizing Tcl.framework" && rm -f "$(LIB_INSTALL_DIR)/../Current" && ln -s "$(VERSION)" "$(LIB_INSTALL_DIR)/../Current" && for f in "$(LIB_FILE)" tclConfig.sh Resources Headers PrivateHeaders; do rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/Current/$$f" "$(LIB_INSTALL_DIR)/../.."; done && f="$(STUB_LIB_FILE)" && rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/$(VERSION)/$$f" "$(LIB_INSTALL_DIR)/../.."'
@@ -638,34 +797,17 @@ if test "$FRAMEWORK_BUILD" = "1" ; then
else
# libdir must be a fully qualified path and not ${exec_prefix}/lib
eval libdir="$libdir"
- if test "$SHARED_BUILD" = "0" || test "$TCL_NEEDS_EXP_FILE" = "0"; then
- if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
- TCL_LIB_FLAG="-ltcl${TCL_VERSION}\${TCL_DBGX}"
- else
- TCL_LIB_FLAG="-ltcl`echo ${TCL_VERSION} | tr -d .`\${TCL_DBGX}"
- fi
- TCL_BUILD_LIB_SPEC="-L`pwd` ${TCL_LIB_FLAG}"
- TCL_LIB_SPEC="-L${libdir} ${TCL_LIB_FLAG}"
+ if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
+ TCL_LIB_FLAG="-ltcl${TCL_VERSION}"
else
- TCL_BUILD_EXP_FILE="lib.exp"
- eval "TCL_EXP_FILE=libtcl${TCL_EXPORT_FILE_SUFFIX}"
-
- # Replace DBGX with TCL_DBGX
- eval "TCL_EXP_FILE=\"${TCL_EXP_FILE}\""
-
- if test "$GCC" = "yes" ; then
- TCL_BUILD_LIB_SPEC="-Wl,-bI:`pwd`/${TCL_BUILD_EXP_FILE} -L`pwd`"
- TCL_LIB_SPEC="-Wl,-bI:${libdir}/${TCL_EXP_FILE} -L`pwd`"
- else
- TCL_BUILD_LIB_SPEC="-bI:`pwd`/${TCL_BUILD_EXP_FILE}"
- TCL_LIB_SPEC="-bI:${libdir}/${TCL_EXP_FILE}"
- fi
+ TCL_LIB_FLAG="-ltcl`echo ${TCL_VERSION} | tr -d .`"
fi
+ TCL_BUILD_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TCL_LIB_FLAG}"
+ TCL_LIB_SPEC="-L${libdir} ${TCL_LIB_FLAG}"
fi
VERSION='${VERSION}'
eval "CFG_TCL_SHARED_LIB_SUFFIX=${TCL_SHARED_LIB_SUFFIX}"
eval "CFG_TCL_UNSHARED_LIB_SUFFIX=${TCL_UNSHARED_LIB_SUFFIX}"
-eval "CFG_TCL_EXPORT_FILE_SUFFIX=${TCL_EXPORT_FILE_SUFFIX}"
VERSION=${TCL_VERSION}
#--------------------------------------------------------------------
@@ -677,8 +819,10 @@ VERSION=${TCL_VERSION}
if test "$FRAMEWORK_BUILD" = "1" ; then
test -z "$TCL_PACKAGE_PATH" && \
- TCL_PACKAGE_PATH="~/Library/Tcl /Library/Tcl /Network/Library/Tcl /System/Library/Tcl ~/Library/Frameworks /Library/Frameworks /Network/Library/Frameworks /System/Library/Frameworks"
-elif test "$prefix" != "$exec_prefix"; then
+ TCL_PACKAGE_PATH="~/Library/Tcl /Library/Tcl /System/Library/Tcl ~/Library/Frameworks /Library/Frameworks /System/Library/Frameworks"
+ test -z "$TCL_MODULE_PATH" && \
+ TCL_MODULE_PATH="~/Library/Tcl /Library/Tcl /System/Library/Tcl"
+elif test "$prefix/lib" != "$libdir"; then
TCL_PACKAGE_PATH="${libdir} ${prefix}/lib ${TCL_PACKAGE_PATH}"
else
TCL_PACKAGE_PATH="${prefix}/lib ${TCL_PACKAGE_PATH}"
@@ -690,18 +834,19 @@ fi
#--------------------------------------------------------------------
# Replace ${VERSION} with contents of ${TCL_VERSION}
+# double-eval to account for TCL_TRIM_DOTS.
+#
eval "TCL_STUB_LIB_FILE=libtclstub${TCL_UNSHARED_LIB_SUFFIX}"
-# Replace DBGX with TCL_DBGX
eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
eval "TCL_STUB_LIB_DIR=${libdir}"
if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
- TCL_STUB_LIB_FLAG="-ltclstub${TCL_VERSION}\${TCL_DBGX}"
+ TCL_STUB_LIB_FLAG="-ltclstub${TCL_VERSION}"
else
- TCL_STUB_LIB_FLAG="-ltclstub`echo ${TCL_VERSION} | tr -d .`\${TCL_DBGX}"
+ TCL_STUB_LIB_FLAG="-ltclstub`echo ${TCL_VERSION} | tr -d .`"
fi
-TCL_BUILD_STUB_LIB_SPEC="-L`pwd` ${TCL_STUB_LIB_FLAG}"
+TCL_BUILD_STUB_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}"
TCL_STUB_LIB_SPEC="-L${TCL_STUB_LIB_DIR} ${TCL_STUB_LIB_FLAG}"
TCL_BUILD_STUB_LIB_PATH="`pwd`/${TCL_STUB_LIB_FILE}"
TCL_STUB_LIB_PATH="${TCL_STUB_LIB_DIR}/${TCL_STUB_LIB_FILE}"
@@ -733,18 +878,13 @@ AC_SUBST(TCL_BUILD_STUB_LIB_SPEC)
AC_SUBST(TCL_BUILD_STUB_LIB_PATH)
AC_SUBST(TCL_SRC_DIR)
-AC_SUBST(TCL_DBGX)
AC_SUBST(CFG_TCL_SHARED_LIB_SUFFIX)
AC_SUBST(CFG_TCL_UNSHARED_LIB_SUFFIX)
-AC_SUBST(CFG_TCL_EXPORT_FILE_SUFFIX)
AC_SUBST(TCL_SHARED_BUILD)
AC_SUBST(LD_LIBRARY_PATH_VAR)
AC_SUBST(TCL_BUILD_LIB_SPEC)
-AC_SUBST(TCL_NEEDS_EXP_FILE)
-AC_SUBST(TCL_BUILD_EXP_FILE)
-AC_SUBST(TCL_EXP_FILE)
AC_SUBST(TCL_LIB_VERSIONS_OK)
AC_SUBST(TCL_SHARED_LIB_SUFFIX)
@@ -752,6 +892,8 @@ AC_SUBST(TCL_UNSHARED_LIB_SUFFIX)
AC_SUBST(TCL_HAS_LONGLONG)
+AC_SUBST(INSTALL_TZDATA)
+
AC_SUBST(DTRACE_SRC)
AC_SUBST(DTRACE_HDR)
AC_SUBST(DTRACE_OBJ)
@@ -759,6 +901,7 @@ AC_SUBST(MAKEFILE_SHELL)
AC_SUBST(BUILD_DLTEST)
AC_SUBST(TCL_PACKAGE_PATH)
+AC_SUBST(TCL_MODULE_PATH)
AC_SUBST(TCL_LIBRARY)
AC_SUBST(PRIVATE_INCLUDE_DIR)
@@ -771,7 +914,15 @@ AC_SUBST(EXTRA_INSTALL_BINARIES)
AC_SUBST(EXTRA_BUILD_HTML)
AC_SUBST(EXTRA_TCLSH_LIBS)
-SC_OUTPUT_COMMANDS_PRE
+AC_SUBST(DLTEST_LD)
+AC_SUBST(DLTEST_SUFFIX)
-tcl_config_files="${tcl_config_files} [Makefile dltest/Makefile tclConfig.sh]"
-AC_OUTPUT([${tcl_config_files}])
+dnl Disable the automake-friendly normalization of LIBOBJS
+dnl performed by autoconf 2.53 and later. It's not correct for us.
+define([_AC_LIBOBJS_NORMALIZE],[])
+AC_CONFIG_FILES([
+ Makefile:../unix/Makefile.in
+ dltest/Makefile:../unix/dltest/Makefile.in
+ tclConfig.sh:../unix/tclConfig.sh.in
+])
+AC_OUTPUT
diff --git a/unix/dltest/Makefile.in b/unix/dltest/Makefile.in
index c0b2659..01589d9 100644
--- a/unix/dltest/Makefile.in
+++ b/unix/dltest/Makefile.in
@@ -2,15 +2,17 @@
# command. It also illustrates how to take advantage of configuration
# exported by Tcl to set up Makefiles for shared libraries.
-TCL_DBGX = @TCL_DBGX@
CC = @CC@
-LIBS = @TCL_BUILD_STUB_LIB_SPEC@ @DL_LIBS@ @LIBS@ @MATH_LIBS@
+LIBS = @TCL_BUILD_STUB_LIB_SPEC@ @TCL_LIBS@
AC_FLAGS = @DEFS@
-SHLIB_CFLAGS = @SHLIB_CFLAGS@
SHLIB_LD = @SHLIB_LD@
+SHLIB_CFLAGS = @SHLIB_CFLAGS@
SHLIB_LD_LIBS = @SHLIB_LD_LIBS@
SHLIB_SUFFIX = @SHLIB_SUFFIX@
-SRC_DIR = @srcdir@
+DLTEST_LD = @DLTEST_LD@
+DLTEST_SUFFIX = @DLTEST_SUFFIX@
+SRC_DIR = @TCL_SRC_DIR@/unix/dltest
+BUILD_DIR = @builddir@
TCL_VERSION= @TCL_VERSION@
CFLAGS_DEBUG = @CFLAGS_DEBUG@
@@ -20,39 +22,80 @@ LDFLAGS_DEBUG = @LDFLAGS_DEBUG@
LDFLAGS_OPTIMIZE = @LDFLAGS_OPTIMIZE@
LDFLAGS = @LDFLAGS_DEFAULT@ @LDFLAGS@
-CC_SWITCHES = $(CFLAGS) -I${SRC_DIR}/../../generic -DTCL_MEM_DEBUG \
+CC_SWITCHES = $(CFLAGS) -I${SRC_DIR}/../../generic -I${BUILD_DIR}/.. -DTCL_MEM_DEBUG \
${SHLIB_CFLAGS} -DUSE_TCL_STUBS ${AC_FLAGS}
-all: pkga${SHLIB_SUFFIX} pkgb${SHLIB_SUFFIX} pkgc${SHLIB_SUFFIX} pkgd${SHLIB_SUFFIX} pkge${SHLIB_SUFFIX}
+all: pkga${SHLIB_SUFFIX} pkgb${SHLIB_SUFFIX} pkgc${SHLIB_SUFFIX} pkgd${SHLIB_SUFFIX} pkge${SHLIB_SUFFIX} pkgua${SHLIB_SUFFIX}
+ @if test -n "$(DLTEST_SUFFIX)"; then $(MAKE) dltest_suffix; fi
+ @touch ../dltest.marker
+
+dltest_suffix: pkga${DLTEST_SUFFIX} pkgb${DLTEST_SUFFIX} pkgc${DLTEST_SUFFIX} pkgd${DLTEST_SUFFIX} pkge${DLTEST_SUFFIX} pkgua${DLTEST_SUFFIX}
@touch ../dltest.marker
-pkga${SHLIB_SUFFIX}: $(SRC_DIR)/pkga.c
+pkga.o: $(SRC_DIR)/pkga.c
$(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkga.c
- ${SHLIB_LD} -o pkga${SHLIB_SUFFIX} pkga.o ${SHLIB_LD_LIBS}
-pkgb${SHLIB_SUFFIX}: $(SRC_DIR)/pkgb.c
+pkgb.o: $(SRC_DIR)/pkgb.c
$(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkgb.c
- ${SHLIB_LD} -o pkgb${SHLIB_SUFFIX} pkgb.o ${SHLIB_LD_LIBS}
-pkgc${SHLIB_SUFFIX}: $(SRC_DIR)/pkgc.c
+pkgc.o: $(SRC_DIR)/pkgc.c
$(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkgc.c
- ${SHLIB_LD} -o pkgc${SHLIB_SUFFIX} pkgc.o ${SHLIB_LD_LIBS}
-pkgd${SHLIB_SUFFIX}: $(SRC_DIR)/pkgd.c
+pkgd.o: $(SRC_DIR)/pkgd.c
$(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkgd.c
- ${SHLIB_LD} -o pkgd${SHLIB_SUFFIX} pkgd.o ${SHLIB_LD_LIBS}
-pkge${SHLIB_SUFFIX}: $(SRC_DIR)/pkge.c
+pkge.o: $(SRC_DIR)/pkge.c
$(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkge.c
+
+pkgua.o: $(SRC_DIR)/pkgua.c
+ $(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkgua.c
+
+pkga${SHLIB_SUFFIX}: pkga.o
+ ${SHLIB_LD} -o pkga${SHLIB_SUFFIX} pkga.o ${SHLIB_LD_LIBS}
+
+pkgb${SHLIB_SUFFIX}: pkgb.o
+ ${SHLIB_LD} -o pkgb${SHLIB_SUFFIX} pkgb.o ${SHLIB_LD_LIBS}
+
+pkgc${SHLIB_SUFFIX}: pkgc.o
+ ${SHLIB_LD} -o pkgc${SHLIB_SUFFIX} pkgc.o ${SHLIB_LD_LIBS}
+
+pkgd${SHLIB_SUFFIX}: pkgd.o
+ ${SHLIB_LD} -o pkgd${SHLIB_SUFFIX} pkgd.o ${SHLIB_LD_LIBS}
+
+pkge${SHLIB_SUFFIX}: pkge.o
${SHLIB_LD} -o pkge${SHLIB_SUFFIX} pkge.o ${SHLIB_LD_LIBS}
+pkgua${SHLIB_SUFFIX}: pkgua.o
+ ${SHLIB_LD} -o pkgua${SHLIB_SUFFIX} pkgua.o ${SHLIB_LD_LIBS}
+
+pkga${DLTEST_SUFFIX}: pkga.o
+ ${DLTEST_LD} -o pkga${DLTEST_SUFFIX} pkga.o ${SHLIB_LD_LIBS}
+
+pkgb${DLTEST_SUFFIX}: pkgb.o
+ ${DLTEST_LD} -o pkgb${DLTEST_SUFFIX} pkgb.o ${SHLIB_LD_LIBS}
+
+pkgc${DLTEST_SUFFIX}: pkgc.o
+ ${DLTEST_LD} -o pkgc${DLTEST_SUFFIX} pkgc.o ${SHLIB_LD_LIBS}
+
+pkgd${DLTEST_SUFFIX}: pkgd.o
+ ${DLTEST_LD} -o pkgd${DLTEST_SUFFIX} pkgd.o ${SHLIB_LD_LIBS}
+
+pkge${DLTEST_SUFFIX}: pkge.o
+ ${DLTEST_LD} -o pkge${DLTEST_SUFFIX} pkge.o ${SHLIB_LD_LIBS}
+
+pkgua${DLTEST_SUFFIX}: pkgua.o
+ ${DLTEST_LD} -o pkgua${DLTEST_SUFFIX} pkgua.o ${SHLIB_LD_LIBS}
+
clean:
- rm -f *.o config.cache config.log config.status
- rm -f lib.exp ../dltest.marker
+ rm -f *.o lib.exp ../dltest.marker
@if test "$(SHLIB_SUFFIX)" != ""; then \
echo "rm -f *${SHLIB_SUFFIX}" ; \
rm -f *${SHLIB_SUFFIX} ; \
fi
+ @if test "$(DLTEST_SUFFIX)" != ""; then \
+ echo "rm -f *${DLTEST_SUFFIX}" ; \
+ rm -f *${DLTEST_SUFFIX} ; \
+ fi
distclean: clean
rm -f Makefile
diff --git a/unix/dltest/README b/unix/dltest/README
index 73f1cd1..3210f13 100644
--- a/unix/dltest/README
+++ b/unix/dltest/README
@@ -1,4 +1,4 @@
This directory contains several files for testing Tcl's dynamic
-loading capabilities. If shared libraries are supported then
-the build system in the parent directory will create
+loading/unloading capabilities. If shared libraries are supported
+then the build system in the parent directory will create
the shared libs and load them into the tcltest executable.
diff --git a/unix/dltest/pkga.c b/unix/dltest/pkga.c
index 85c9ebb..f001cdf 100644
--- a/unix/dltest/pkga.c
+++ b/unix/dltest/pkga.c
@@ -1,33 +1,34 @@
-/*
+/*
* pkga.c --
*
- * This file contains a simple Tcl package "pkga" that is intended
- * for testing the Tcl dynamic loading facilities.
+ * This file contains a simple Tcl package "pkga" that is intended for
+ * testing the Tcl dynamic loading facilities.
*
* Copyright (c) 1995 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
+
#include "tcl.h"
/*
* Prototypes for procedures defined later in this file:
*/
-static int Pkga_EqObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]));
-static int Pkga_QuoteObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]));
+static int Pkga_EqObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
+static int Pkga_QuoteObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
/*
*----------------------------------------------------------------------
*
* Pkga_EqObjCmd --
*
- * This procedure is invoked to process the "pkga_eq" Tcl command.
- * It expects two arguments and returns 1 if they are the same,
- * 0 if they are different.
+ * This procedure is invoked to process the "pkga_eq" Tcl command. It
+ * expects two arguments and returns 1 if they are the same, 0 if they
+ * are different.
*
* Results:
* A standard Tcl result.
@@ -39,11 +40,11 @@ static int Pkga_QuoteObjCmd _ANSI_ARGS_((ClientData clientData,
*/
static int
-Pkga_EqObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj * CONST objv[]; /* Argument objects. */
+Pkga_EqObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
int result;
CONST char *str1, *str2;
@@ -70,8 +71,8 @@ Pkga_EqObjCmd(dummy, interp, objc, objv)
*
* Pkga_QuoteObjCmd --
*
- * This procedure is invoked to process the "pkga_quote" Tcl command.
- * It expects one argument, which it returns as result.
+ * This procedure is invoked to process the "pkga_quote" Tcl command. It
+ * expects one argument, which it returns as result.
*
* Results:
* A standard Tcl result.
@@ -83,11 +84,11 @@ Pkga_EqObjCmd(dummy, interp, objc, objv)
*/
static int
-Pkga_QuoteObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj * CONST objv[]; /* Argument strings. */
+Pkga_QuoteObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument strings. */
{
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "value");
@@ -102,8 +103,8 @@ Pkga_QuoteObjCmd(dummy, interp, objc, objv)
*
* Pkga_Init --
*
- * This is a package initialization procedure, which is called
- * by Tcl when this package is to be added to an interpreter.
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to an interpreter.
*
* Results:
* None.
@@ -115,13 +116,13 @@ Pkga_QuoteObjCmd(dummy, interp, objc, objv)
*/
int
-Pkga_Init(interp)
- Tcl_Interp *interp; /* Interpreter in which the package is
- * to be made available. */
+Pkga_Init(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
{
int code;
- if (Tcl_InitStubs(interp, TCL_VERSION, 1) == NULL) {
+ if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
code = Tcl_PkgProvide(interp, "Pkga", "1.0");
diff --git a/unix/dltest/pkgb.c b/unix/dltest/pkgb.c
index d7a7e5b..51c1bd9 100644
--- a/unix/dltest/pkgb.c
+++ b/unix/dltest/pkgb.c
@@ -1,33 +1,34 @@
-/*
+/*
* pkgb.c --
*
- * This file contains a simple Tcl package "pkgb" that is intended
- * for testing the Tcl dynamic loading facilities. It can be used
- * in both safe and unsafe interpreters.
+ * This file contains a simple Tcl package "pkgb" that is intended for
+ * testing the Tcl dynamic loading facilities. It can be used in both
+ * safe and unsafe interpreters.
*
* Copyright (c) 1995 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
+
#include "tcl.h"
/*
* Prototypes for procedures defined later in this file:
*/
-static int Pkgb_SubObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]));
-static int Pkgb_UnsafeObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]));
+static int Pkgb_SubObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
+static int Pkgb_UnsafeObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
/*
*----------------------------------------------------------------------
*
* Pkgb_SubObjCmd --
*
- * This procedure is invoked to process the "pkgb_sub" Tcl command.
- * It expects two arguments and returns their difference.
+ * This procedure is invoked to process the "pkgb_sub" Tcl command. It
+ * expects two arguments and returns their difference.
*
* Results:
* A standard Tcl result.
@@ -39,21 +40,21 @@ static int Pkgb_UnsafeObjCmd _ANSI_ARGS_((ClientData clientData,
*/
static int
-Pkgb_SubObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj * CONST objv[]; /* Argument objects. */
+Pkgb_SubObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
int first, second;
if (objc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, "num num");
- return TCL_ERROR;
+ return TCL_ERROR;
}
if ((Tcl_GetIntFromObj(interp, objv[1], &first) != TCL_OK)
|| (Tcl_GetIntFromObj(interp, objv[2], &second) != TCL_OK)) {
- return TCL_ERROR;
+ return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewIntObj(first - second));
return TCL_OK;
@@ -64,8 +65,8 @@ Pkgb_SubObjCmd(dummy, interp, objc, objv)
*
* Pkgb_UnsafeObjCmd --
*
- * This procedure is invoked to process the "pkgb_unsafe" Tcl command.
- * It just returns a constant string.
+ * This procedure is invoked to process the "pkgb_unsafe" Tcl command. It
+ * just returns a constant string.
*
* Results:
* A standard Tcl result.
@@ -77,11 +78,11 @@ Pkgb_SubObjCmd(dummy, interp, objc, objv)
*/
static int
-Pkgb_UnsafeObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj * CONST objv[]; /* Argument objects. */
+Pkgb_UnsafeObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
Tcl_SetObjResult(interp, Tcl_NewStringObj("unsafe command invoked", -1));
return TCL_OK;
@@ -92,8 +93,8 @@ Pkgb_UnsafeObjCmd(dummy, interp, objc, objv)
*
* Pkgb_Init --
*
- * This is a package initialization procedure, which is called
- * by Tcl when this package is to be added to an interpreter.
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to an interpreter.
*
* Results:
* None.
@@ -105,13 +106,13 @@ Pkgb_UnsafeObjCmd(dummy, interp, objc, objv)
*/
int
-Pkgb_Init(interp)
- Tcl_Interp *interp; /* Interpreter in which the package is
- * to be made available. */
+Pkgb_Init(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
{
int code;
- if (Tcl_InitStubs(interp, TCL_VERSION, 1) == NULL) {
+ if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
code = Tcl_PkgProvide(interp, "Pkgb", "2.3");
@@ -130,8 +131,8 @@ Pkgb_Init(interp)
*
* Pkgb_SafeInit --
*
- * This is a package initialization procedure, which is called
- * by Tcl when this package is to be added to an unsafe interpreter.
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to a safe interpreter.
*
* Results:
* None.
@@ -143,18 +144,18 @@ Pkgb_Init(interp)
*/
int
-Pkgb_SafeInit(interp)
- Tcl_Interp *interp; /* Interpreter in which the package is
- * to be made available. */
+Pkgb_SafeInit(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
{
int code;
- if (Tcl_InitStubs(interp, TCL_VERSION, 1) == NULL) {
+ if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
code = Tcl_PkgProvide(interp, "Pkgb", "2.3");
if (code != TCL_OK) {
- return code;
+ return code;
}
Tcl_CreateObjCommand(interp, "pkgb_sub", Pkgb_SubObjCmd, (ClientData) 0,
(Tcl_CmdDeleteProc *) NULL);
diff --git a/unix/dltest/pkgc.c b/unix/dltest/pkgc.c
index 1fda70b..6ad5ab4 100644
--- a/unix/dltest/pkgc.c
+++ b/unix/dltest/pkgc.c
@@ -1,33 +1,34 @@
-/*
+/*
* pkgc.c --
*
- * This file contains a simple Tcl package "pkgc" that is intended
- * for testing the Tcl dynamic loading facilities. It can be used
- * in both safe and unsafe interpreters.
+ * This file contains a simple Tcl package "pkgc" that is intended for
+ * testing the Tcl dynamic loading facilities. It can be used in both
+ * safe and unsafe interpreters.
*
* Copyright (c) 1995 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
+
#include "tcl.h"
/*
* Prototypes for procedures defined later in this file:
*/
-static int Pkgc_SubObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]));
-static int Pkgc_UnsafeObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]));
+static int Pkgc_SubObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
+static int Pkgc_UnsafeObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
/*
*----------------------------------------------------------------------
*
* Pkgc_SubObjCmd --
*
- * This procedure is invoked to process the "pkgc_sub" Tcl command.
- * It expects two arguments and returns their difference.
+ * This procedure is invoked to process the "pkgc_sub" Tcl command. It
+ * expects two arguments and returns their difference.
*
* Results:
* A standard Tcl result.
@@ -39,11 +40,11 @@ static int Pkgc_UnsafeObjCmd _ANSI_ARGS_((ClientData clientData,
*/
static int
-Pkgc_SubObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj * CONST objv[]; /* Argument objects. */
+Pkgc_SubObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
int first, second;
@@ -64,8 +65,8 @@ Pkgc_SubObjCmd(dummy, interp, objc, objv)
*
* Pkgc_UnsafeCmd --
*
- * This procedure is invoked to process the "pkgc_unsafe" Tcl command.
- * It just returns a constant string.
+ * This procedure is invoked to process the "pkgc_unsafe" Tcl command. It
+ * just returns a constant string.
*
* Results:
* A standard Tcl result.
@@ -77,11 +78,11 @@ Pkgc_SubObjCmd(dummy, interp, objc, objv)
*/
static int
-Pkgc_UnsafeObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj * CONST objv[]; /* Argument objects. */
+Pkgc_UnsafeObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
Tcl_SetObjResult(interp, Tcl_NewStringObj("unsafe command invoked", -1));
return TCL_OK;
@@ -92,8 +93,8 @@ Pkgc_UnsafeObjCmd(dummy, interp, objc, objv)
*
* Pkgc_Init --
*
- * This is a package initialization procedure, which is called
- * by Tcl when this package is to be added to an interpreter.
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to an interpreter.
*
* Results:
* None.
@@ -105,13 +106,13 @@ Pkgc_UnsafeObjCmd(dummy, interp, objc, objv)
*/
int
-Pkgc_Init(interp)
- Tcl_Interp *interp; /* Interpreter in which the package is
- * to be made available. */
+Pkgc_Init(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
{
int code;
- if (Tcl_InitStubs(interp, TCL_VERSION, 1) == NULL) {
+ if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
code = Tcl_PkgProvide(interp, "Pkgc", "1.7.2");
@@ -130,8 +131,8 @@ Pkgc_Init(interp)
*
* Pkgc_SafeInit --
*
- * This is a package initialization procedure, which is called
- * by Tcl when this package is to be added to an unsafe interpreter.
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to a safe interpreter.
*
* Results:
* None.
@@ -143,18 +144,18 @@ Pkgc_Init(interp)
*/
int
-Pkgc_SafeInit(interp)
- Tcl_Interp *interp; /* Interpreter in which the package is
- * to be made available. */
+Pkgc_SafeInit(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
{
int code;
- if (Tcl_InitStubs(interp, TCL_VERSION, 1) == NULL) {
+ if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
code = Tcl_PkgProvide(interp, "Pkgc", "1.7.2");
if (code != TCL_OK) {
- return code;
+ return code;
}
Tcl_CreateObjCommand(interp, "pkgc_sub", Pkgc_SubObjCmd, (ClientData) 0,
(Tcl_CmdDeleteProc *) NULL);
diff --git a/unix/dltest/pkgd.c b/unix/dltest/pkgd.c
index 3fa0aba..7fe7c49 100644
--- a/unix/dltest/pkgd.c
+++ b/unix/dltest/pkgd.c
@@ -1,14 +1,14 @@
-/*
+/*
* pkgd.c --
*
- * This file contains a simple Tcl package "pkgd" that is intended
- * for testing the Tcl dynamic loading facilities. It can be used
- * in both safe and unsafe interpreters.
+ * This file contains a simple Tcl package "pkgd" that is intended for
+ * testing the Tcl dynamic loading facilities. It can be used in both
+ * safe and unsafe interpreters.
*
* Copyright (c) 1995 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tcl.h"
@@ -17,18 +17,18 @@
* Prototypes for procedures defined later in this file:
*/
-static int Pkgd_SubObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]));
-static int Pkgd_UnsafeObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]));
+static int Pkgd_SubObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
+static int Pkgd_UnsafeObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
/*
*----------------------------------------------------------------------
*
* Pkgd_SubObjCmd --
*
- * This procedure is invoked to process the "pkgd_sub" Tcl command.
- * It expects two arguments and returns their difference.
+ * This procedure is invoked to process the "pkgd_sub" Tcl command. It
+ * expects two arguments and returns their difference.
*
* Results:
* A standard Tcl result.
@@ -40,11 +40,11 @@ static int Pkgd_UnsafeObjCmd _ANSI_ARGS_((ClientData clientData,
*/
static int
-Pkgd_SubObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj * CONST objv[]; /* Argument objects. */
+Pkgd_SubObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
int first, second;
@@ -65,8 +65,8 @@ Pkgd_SubObjCmd(dummy, interp, objc, objv)
*
* Pkgd_UnsafeCmd --
*
- * This procedure is invoked to process the "pkgd_unsafe" Tcl command.
- * It just returns a constant string.
+ * This procedure is invoked to process the "pkgd_unsafe" Tcl command. It
+ * just returns a constant string.
*
* Results:
* A standard Tcl result.
@@ -78,11 +78,11 @@ Pkgd_SubObjCmd(dummy, interp, objc, objv)
*/
static int
-Pkgd_UnsafeObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj * CONST objv[]; /* Argument objects. */
+Pkgd_UnsafeObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
{
Tcl_SetObjResult(interp, Tcl_NewStringObj("unsafe command invoked", -1));
return TCL_OK;
@@ -93,8 +93,8 @@ Pkgd_UnsafeObjCmd(dummy, interp, objc, objv)
*
* Pkgd_Init --
*
- * This is a package initialization procedure, which is called
- * by Tcl when this package is to be added to an interpreter.
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to an interpreter.
*
* Results:
* None.
@@ -106,13 +106,13 @@ Pkgd_UnsafeObjCmd(dummy, interp, objc, objv)
*/
int
-Pkgd_Init(interp)
- Tcl_Interp *interp; /* Interpreter in which the package is
- * to be made available. */
+Pkgd_Init(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
{
int code;
- if (Tcl_InitStubs(interp, TCL_VERSION, 1) == NULL) {
+ if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
code = Tcl_PkgProvide(interp, "Pkgd", "7.3");
@@ -131,8 +131,8 @@ Pkgd_Init(interp)
*
* Pkgd_SafeInit --
*
- * This is a package initialization procedure, which is called
- * by Tcl when this package is to be added to an unsafe interpreter.
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to a safe interpreter.
*
* Results:
* None.
@@ -144,13 +144,13 @@ Pkgd_Init(interp)
*/
int
-Pkgd_SafeInit(interp)
- Tcl_Interp *interp; /* Interpreter in which the package is
- * to be made available. */
+Pkgd_SafeInit(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
{
int code;
- if (Tcl_InitStubs(interp, TCL_VERSION, 1) == NULL) {
+ if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
code = Tcl_PkgProvide(interp, "Pkgd", "7.3");
diff --git a/unix/dltest/pkge.c b/unix/dltest/pkge.c
index ed905f2..abd2359 100644
--- a/unix/dltest/pkge.c
+++ b/unix/dltest/pkge.c
@@ -1,14 +1,14 @@
-/*
+/*
* pkge.c --
*
- * This file contains a simple Tcl package "pkge" that is intended
- * for testing the Tcl dynamic loading facilities. Its Init
- * procedure returns an error in order to test how this is handled.
+ * This file contains a simple Tcl package "pkge" that is intended for
+ * testing the Tcl dynamic loading facilities. Its Init procedure returns
+ * an error in order to test how this is handled.
*
* Copyright (c) 1995 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tcl.h"
@@ -19,8 +19,8 @@
*
* Pkge_Init --
*
- * This is a package initialization procedure, which is called
- * by Tcl when this package is to be added to an interpreter.
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to an interpreter.
*
* Results:
* Returns TCL_ERROR and leaves an error message in interp->result.
@@ -32,12 +32,13 @@
*/
int
-Pkge_Init(interp)
- Tcl_Interp *interp; /* Interpreter in which the package is
- * to be made available. */
+Pkge_Init(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
{
static char script[] = "if 44 {open non_existent}";
- if (Tcl_InitStubs(interp, TCL_VERSION, 1) == NULL) {
+
+ if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
return Tcl_Eval(interp, script);
diff --git a/unix/dltest/pkgf.c b/unix/dltest/pkgf.c
deleted file mode 100644
index e884ca9..0000000
--- a/unix/dltest/pkgf.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * pkgf.c --
- *
- * This file contains a simple Tcl package "pkgf" that is intended
- * for testing the Tcl dynamic loading facilities. Its Init
- * procedure returns an error in order to test how this is handled.
- *
- * Copyright (c) 1995 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-#include "tcl.h"
-
-/*
- * Prototypes for procedures defined later in this file:
- */
-
-static int Pkgd_SubCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
-static int Pkgd_UnsafeCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
-
-/*
- *----------------------------------------------------------------------
- *
- * Pkgf_Init --
- *
- * This is a package initialization procedure, which is called
- * by Tcl when this package is to be added to an interpreter.
- *
- * Results:
- * Returns TCL_ERROR and leaves an error message in interp->result.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-Pkgf_Init(interp)
- Tcl_Interp *interp; /* Interpreter in which the package is
- * to be made available. */
-{
- static char script[] = "if 44 {open non_existent}";
- if (Tcl_InitStubs(interp, TCL_VERSION, 1) == NULL) {
- return TCL_ERROR;
- }
- return Tcl_Eval(interp, script);
-}
diff --git a/unix/dltest/pkgua.c b/unix/dltest/pkgua.c
new file mode 100644
index 0000000..9c36e88
--- /dev/null
+++ b/unix/dltest/pkgua.c
@@ -0,0 +1,332 @@
+/*
+ * pkgua.c --
+ *
+ * This file contains a simple Tcl package "pkgua" that is intended for
+ * testing the Tcl dynamic unloading facilities.
+ *
+ * Copyright (c) 1995 Sun Microsystems, Inc.
+ * Copyright (c) 2004 Georgios Petasis
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tcl.h"
+
+/*
+ * Prototypes for procedures defined later in this file:
+ */
+
+static int PkguaEqObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
+static int PkguaQuoteObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
+
+/*
+ * In the following hash table we are going to store a struct that holds all
+ * the command tokens created by Tcl_CreateObjCommand in an interpreter,
+ * indexed by the interpreter. In this way, we can find which command tokens
+ * we have registered in a specific interpreter, in order to unload them. We
+ * need to keep the various command tokens we have registered, as they are the
+ * only safe way to unregister our registered commands, even if they have been
+ * renamed.
+ *
+ * Note that this code is utterly single-threaded.
+ */
+
+static Tcl_HashTable interpTokenMap;
+static int interpTokenMapInitialised = 0;
+#define MAX_REGISTERED_COMMANDS 2
+
+
+static void
+PkguaInitTokensHashTable(void)
+{
+ if (interpTokenMapInitialised) {
+ return;
+ }
+ Tcl_InitHashTable(&interpTokenMap, TCL_ONE_WORD_KEYS);
+ interpTokenMapInitialised = 1;
+}
+
+void
+PkguaFreeTokensHashTable(void)
+{
+ Tcl_HashSearch search;
+ Tcl_HashEntry *entryPtr;
+
+ for (entryPtr = Tcl_FirstHashEntry(&interpTokenMap, &search);
+ entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) {
+ Tcl_Free((char *) Tcl_GetHashValue(entryPtr));
+ }
+ interpTokenMapInitialised = 0;
+}
+
+static Tcl_Command *
+PkguaInterpToTokens(
+ Tcl_Interp *interp)
+{
+ int newEntry;
+ Tcl_Command *cmdTokens;
+ Tcl_HashEntry *entryPtr =
+ Tcl_CreateHashEntry(&interpTokenMap, (char *) interp, &newEntry);
+
+ if (newEntry) {
+ cmdTokens = (Tcl_Command *)
+ Tcl_Alloc(sizeof(Tcl_Command) * (MAX_REGISTERED_COMMANDS+1));
+ for (newEntry=0 ; newEntry<MAX_REGISTERED_COMMANDS+1 ; ++newEntry) {
+ cmdTokens[newEntry] = NULL;
+ }
+ Tcl_SetHashValue(entryPtr, (ClientData) cmdTokens);
+ } else {
+ cmdTokens = (Tcl_Command *) Tcl_GetHashValue(entryPtr);
+ }
+ return cmdTokens;
+}
+
+static void
+PkguaDeleteTokens(
+ Tcl_Interp *interp)
+{
+ Tcl_HashEntry *entryPtr =
+ Tcl_FindHashEntry(&interpTokenMap, (char *) interp);
+
+ if (entryPtr) {
+ Tcl_Free((char *) Tcl_GetHashValue(entryPtr));
+ Tcl_DeleteHashEntry(entryPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PkguaEqObjCmd --
+ *
+ * This procedure is invoked to process the "pkgua_eq" Tcl command. It
+ * expects two arguments and returns 1 if they are the same, 0 if they
+ * are different.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+PkguaEqObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
+{
+ int result;
+ CONST char *str1, *str2;
+ int len1, len2;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "string1 string2");
+ return TCL_ERROR;
+ }
+
+ str1 = Tcl_GetStringFromObj(objv[1], &len1);
+ str2 = Tcl_GetStringFromObj(objv[2], &len2);
+ if (len1 == len2) {
+ result = (Tcl_UtfNcmp(str1, str2, len1) == 0);
+ } else {
+ result = 0;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(result));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PkguaQuoteObjCmd --
+ *
+ * This procedure is invoked to process the "pkgua_quote" Tcl command. It
+ * expects one argument, which it returns as result.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+PkguaQuoteObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument strings. */
+{
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "value");
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, objv[1]);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgua_Init --
+ *
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to an interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Pkgua_Init(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
+{
+ int code, cmdIndex = 0;
+ Tcl_Command *cmdTokens;
+
+ if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Initialise our Hash table, where we store the registered command tokens
+ * for each interpreter.
+ */
+
+ PkguaInitTokensHashTable();
+
+ code = Tcl_PkgProvide(interp, "Pkgua", "1.0");
+ if (code != TCL_OK) {
+ return code;
+ }
+
+ Tcl_SetVar(interp, "::pkgua_loaded", ".", TCL_APPEND_VALUE);
+
+ cmdTokens = PkguaInterpToTokens(interp);
+ cmdTokens[cmdIndex++] =
+ Tcl_CreateObjCommand(interp, "pkgua_eq", PkguaEqObjCmd,
+ (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ cmdTokens[cmdIndex++] =
+ Tcl_CreateObjCommand(interp, "pkgua_quote", PkguaQuoteObjCmd,
+ (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgua_SafeInit --
+ *
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to a safe interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Pkgua_SafeInit(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
+{
+ return Pkgua_Init(interp);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgua_Unload --
+ *
+ * This is a package unloading initialization procedure, which is called
+ * by Tcl when this package is to be unloaded from an interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Pkgua_Unload(
+ Tcl_Interp *interp, /* Interpreter from which the package is to be
+ * unloaded. */
+ int flags) /* Flags passed by the unloading mechanism */
+{
+ int code, cmdIndex;
+ Tcl_Command *cmdTokens = PkguaInterpToTokens(interp);
+
+ for (cmdIndex=0 ; cmdIndex<MAX_REGISTERED_COMMANDS ; cmdIndex++) {
+ if (cmdTokens[cmdIndex] == NULL) {
+ continue;
+ }
+ code = Tcl_DeleteCommandFromToken(interp, cmdTokens[cmdIndex]);
+ if (code != TCL_OK) {
+ return code;
+ }
+ }
+
+ PkguaDeleteTokens(interp);
+
+ Tcl_SetVar(interp, "::pkgua_detached", ".", TCL_APPEND_VALUE);
+
+ if (flags == TCL_UNLOAD_DETACH_FROM_PROCESS) {
+ /*
+ * Tcl is ready to detach this library from the running application.
+ * We should free all the memory that is not related to any
+ * interpreter.
+ */
+
+ PkguaFreeTokensHashTable();
+ Tcl_SetVar(interp, "::pkgua_unloaded", ".", TCL_APPEND_VALUE);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgua_SafeUnload --
+ *
+ * This is a package unloading initialization procedure, which is called
+ * by Tcl when this package is to be unloaded from an interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Pkgua_SafeUnload(
+ Tcl_Interp *interp, /* Interpreter from which the package is to be
+ * unloaded. */
+ int flags) /* Flags passed by the unloading mechanism */
+{
+ return Pkgua_Unload(interp, flags);
+}
diff --git a/unix/install-sh b/unix/install-sh
index a9a1f27..8cff938 100755
--- a/unix/install-sh
+++ b/unix/install-sh
@@ -94,31 +94,31 @@ fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
-if [ -d $dst ]
+if [ -d "$dst" ]
then
- dst="$dst"/`basename $src`
+ dst="$dst/`basename "$src"`"
fi
# Make a temp file name in the proper directory.
-dstdir=`dirname $dst`
-dsttmp=$dstdir/#inst.$$#
+dstdir="`dirname "$dst"`"
+dsttmp="$dstdir"/#inst.$$#
# Move or copy the file name to the temp name
-$doit $instcmd $src $dsttmp
+$doit $instcmd "$src" "$dsttmp"
# and set any options; do chmod last to preserve setuid bits
-if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi
-if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi
-if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi
-if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi
+if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; fi
+if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; fi
+if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; fi
+if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; fi
# Now rename the file to the real destination.
-$doit $rmcmd $dst
-$doit $mvcmd $dsttmp $dst
+$doit $rmcmd "$dst"
+$doit $mvcmd "$dsttmp" "$dst"
exit 0
diff --git a/unix/installManPage b/unix/installManPage
index 93fd925..6bdccf0 100755
--- a/unix/installManPage
+++ b/unix/installManPage
@@ -1,12 +1,29 @@
#!/bin/sh
-ZIP=:
+########################################################################
+### Parse Options
+###
+
+Gzip=:
+SymOrLoc=""
+Gz=""
+Suffix=""
+
while true; do
case $1 in
- -s | --symlinks ) S="-s ";;
- -z | --compress ) ZIP=$2; shift ;;
- -e | --extension ) Z=$2; shift ;;
- -s | --suffix ) SUFFIX=$2; shift ;;
+ -s | --symlinks ) SymOrLoc="-s " ;;
+ -z | --compress ) Gzip=$2; shift ;;
+ -e | --extension ) Gz=$2; shift ;;
+ -x | --suffix ) Suffix=$2; shift ;;
+ -*) cat <<EOF
+Unknown option "$1". Supported options:
+ -s Use symbolic links for manpages with multiple names.
+ -z PROG Use PROG to compress manual pages.
+ -e EXT Defines the extension added by -z PROG when compressing.
+ -x SUFF Defines an extra extension suffix to use.
+Option names may not be combined getopt-style.
+EOF
+ exit 1 ;;
*) break ;;
esac
shift
@@ -16,52 +33,84 @@ if test "$#" != 2; then
exit 1
fi
-MANPAGE=$1
-DIR=$2
-test -z "$S" && S="$DIR/"
+########################################################################
+### Parse Required Arguments
+###
+
+ManPage=$1
+Dir=$2
+if test -f $ManPage ; then : ; else
+ echo "source manual page file must exist"
+ exit 1
+fi
+if test -d $Dir ; then : ; else
+ echo "target directory must exist"
+ exit 1
+fi
+test -z "$SymOrLoc" && SymOrLoc="$Dir/"
+
+########################################################################
+### Extract Target Names from Manual Page
+###
# A sed script to parse the alternative names out of a man page.
#
-# /^\\.SH NAME/{ ;# Look for a line, that starts with .SH NAME
-# s/^.*$// ;# Delete the content of this line from the buffer
-# n ;# Read next line
-# s/,//g ;# Remove all commas ...
-# s/\\\ //g ;# .. and backslash-escaped spaces.
-# s/ \\\-.*// ;# Delete from \- to the end of line
-# p ;# print the result
-# q ;# exit
-# }
-#
# Backslashes are trippled in the sed script, because it is in
-# backticks which don't pass backslashes literally.
+# backticks which doesn't pass backslashes literally.
#
-# Please keep the commented version above updated if you
-# change anything to the script below.
-NAMES=`sed -n '
- /^\\.SH NAME/{
- s/^.*$//
+Names=`sed -n '
+# Look for a line, that starts with .SH NAME
+# optionally allow NAME to be surrounded
+# by quotes.
+ /^\.SH NAME/{
+# Read next line
n
+# Remove all commas ...
s/,//g
+# ... and backslash-escaped spaces.
s/\\\ //g
+# Delete from \- to the end of line
s/ \\\-.*//
- p
- q
- }' $MANPAGE`
+# print the result and exit
+ p;q
+ }' $ManPage`
+
+if test -z "$Names" ; then
+ echo "warning: no target names found in $ManPage"
+fi
+
+########################################################################
+### Remaining Set Up
+###
-SECTION=`echo $MANPAGE | sed 's/.*\(.\)$/\1/'`
-SRCDIR=`dirname $MANPAGE`
-FIRST=""
-for f in $NAMES; do
- f=$f.$SECTION$SUFFIX
- if test -z "$FIRST" ; then
- FIRST=$f
- rm -f $DIR/$FIRST $DIR/$FIRST.*
- sed -e "/man\.macros/r $SRCDIR/man.macros" -e "/man\.macros/d" \
- $MANPAGE > $DIR/$FIRST
- chmod 444 $DIR/$FIRST
- $ZIP $DIR/$FIRST
+case $ManPage in
+ *.1) Section=1 ;;
+ *.3) Section=3 ;;
+ *.n) Section=n ;;
+ *) echo "unknown section for $ManPage"
+ exit 2 ;;
+esac
+
+SrcDir=`dirname $ManPage`
+
+########################################################################
+### Process Page to Create Target Pages
+###
+
+First=""
+for Target in $Names; do
+ Target=$Target.$Section$Suffix
+ rm -f $Dir/$Target $Dir/$Target.*
+ if test -z "$First" ; then
+ First=$Target
+ sed -e "/man\.macros/r $SrcDir/man.macros" -e "/man\.macros/d" \
+ $ManPage > $Dir/$First
+ chmod 444 $Dir/$First
+ $Gzip $Dir/$First
else
- rm -f $DIR/$f $DIR/$f.*
- ln $S$FIRST$Z $DIR/$f$Z
+ ln $SymOrLoc$First$Gz $Dir/$Target$Gz
fi
done
+
+########################################################################
+exit 0
diff --git a/unix/ldAix b/unix/ldAix
index 7bad17f..51b2995 100755
--- a/unix/ldAix
+++ b/unix/ldAix
@@ -1,5 +1,5 @@
#!/bin/sh
-#
+#
# ldAix ldCmd ldArg ldArg ...
#
# This shell script provides a wrapper for ld under AIX in order to
@@ -27,41 +27,23 @@ outputFile=`echo $args | sed -e 's/.*-o \([^ ]*\).*/\1/'`
# Create the export file from all of the object files, using nm followed
# by sed editing. Here are some tricky aspects of this:
#
-# 1. Nm produces different output under AIX 4.1 than under AIX 3.2.5;
-# the following statements handle both versions.
-# 2. Use the -g switch to nm instead of -e under 4.1 (this shows just
-# externals, not statics; -g isn't available under 3.2.5, though).
-# 3. Use the -X32_64 switch to nm on AIX-4+ to handle 32 or 64bit compiles.
-# 4. Eliminate lines that end in ":": these are the names of object
-# files (relevant in 4.1 only).
-# 5. Eliminate entries with the "U" key letter; these are undefined
-# symbols (relevant in 4.1 only).
-# 6. Eliminate lines that contain the string "0|extern" preceded by space;
-# in 3.2.5, these are undefined symbols (address 0).
-# 7. Eliminate lines containing the "unamex" symbol. In 3.2.5, these
-# are also undefined symbols.
-# 8. If a line starts with ".", delete the leading ".", since this will
-# just cause confusion later.
-# 9. Eliminate everything after the first field in a line, so that we're
-# left with just the symbol name.
+# - Use the -X32_64 switch to nm to handle 32 or 64bit compiles.
+# - Eliminate lines that end in ":": these are the names of object files
+# - Eliminate entries with the "U" key letter; these are undefined symbols
+# - If a line starts with ".", delete the leading ".", since this will just
+# cause confusion later
+# - Eliminate everything after the first field in a line, so that we're
+# left with just the symbol name
-nmopts="-g -C"
-osver=`uname -v`
-if test $osver -eq 3; then
- nmopts="-e"
-fi
-if test $osver -gt 3; then
- nmopts="$nmopts -X32_64"
-fi
+nmopts="-g -C -h -X32_64"
rm -f lib.exp
echo "#! $outputFile" >lib.exp
-/usr/ccs/bin/nm $nmopts -h $ofiles | sed -e '/:$/d' -e '/ U /d' -e '/[ ]0|extern/d' -e '/unamex/d' -e 's/^\.//' -e 's/[ |].*//' | sort | uniq >>lib.exp
+/usr/ccs/bin/nm $nmopts $ofiles | sed -e '/:$/d' -e '/ U /d' -e 's/^\.//' -e 's/[ |].*//' | sort | uniq >>lib.exp
# If we're linking a .a file, then link all the objects together into a
# single file "shr.o" and then put that into the archive. Otherwise link
# the object files directly into the .a file.
-outputFile=`echo $args | sed -e 's/.*-o \([^ ]*\).*/\1/'`
noDotA=`echo $outputFile | sed -e '/\.a$/d'`
echo "noDotA=\"$noDotA\""
if test "$noDotA" = "" ; then
diff --git a/unix/tcl.m4 b/unix/tcl.m4
index fe4c6ff..78eacd9 100644
--- a/unix/tcl.m4
+++ b/unix/tcl.m4
@@ -27,7 +27,10 @@ AC_DEFUN([SC_PATH_TCLCONFIG], [
if test x"${no_tcl}" = x ; then
# we reset no_tcl in case something fails here
no_tcl=true
- AC_ARG_WITH(tcl, [ --with-tcl directory containing tcl configuration (tclConfig.sh)], with_tclconfig=${withval})
+ AC_ARG_WITH(tcl,
+ AC_HELP_STRING([--with-tcl],
+ [directory containing tcl configuration (tclConfig.sh)]),
+ with_tclconfig="${withval}")
AC_MSG_CHECKING([for Tcl configuration])
AC_CACHE_VAL(ac_cv_c_tclconfig,[
@@ -154,7 +157,10 @@ AC_DEFUN([SC_PATH_TKCONFIG], [
if test x"${no_tk}" = x ; then
# we reset no_tk in case something fails here
no_tk=true
- AC_ARG_WITH(tk, [ --with-tk directory containing tk configuration (tkConfig.sh)], with_tkconfig=${withval})
+ AC_ARG_WITH(tk,
+ AC_HELP_STRING([--with-tk],
+ [directory containing tk configuration (tkConfig.sh)]),
+ with_tkconfig="${withval}")
AC_MSG_CHECKING([for Tk configuration])
AC_CACHE_VAL(ac_cv_c_tkconfig,[
@@ -517,7 +523,8 @@ AC_DEFUN([SC_BUILD_TCLSH], [
AC_DEFUN([SC_ENABLE_SHARED], [
AC_MSG_CHECKING([how to build libraries])
AC_ARG_ENABLE(shared,
- [ --enable-shared build and link with shared libraries [--enable-shared]],
+ AC_HELP_STRING([--enable-shared],
+ [build and link with shared libraries (default: on)]),
[tcl_ok=$enableval], [tcl_ok=yes])
if test "${enable_shared+set}" = set; then
@@ -558,7 +565,8 @@ AC_DEFUN([SC_ENABLE_FRAMEWORK], [
if test "`uname -s`" = "Darwin" ; then
AC_MSG_CHECKING([how to package libraries])
AC_ARG_ENABLE(framework,
- [ --enable-framework package shared libraries in MacOSX frameworks [--disable-framework]],
+ AC_HELP_STRING([--enable-framework],
+ [package shared libraries in MacOSX frameworks (default: off)]),
[enable_framework=$enableval], [enable_framework=no])
if test $enable_framework = yes; then
if test $SHARED_BUILD = 0; then
@@ -587,9 +595,7 @@ AC_DEFUN([SC_ENABLE_FRAMEWORK], [
#------------------------------------------------------------------------
# SC_ENABLE_THREADS --
#
-# Specify if thread support should be enabled. TCL_THREADS is
-# checked so that if you are compiling an extension against a
-# threaded core, your extension must be compiled threaded as well.
+# Specify if thread support should be enabled
#
# Arguments:
# none
@@ -610,7 +616,9 @@ AC_DEFUN([SC_ENABLE_FRAMEWORK], [
#------------------------------------------------------------------------
AC_DEFUN([SC_ENABLE_THREADS], [
- AC_ARG_ENABLE(threads, [ --enable-threads build with threads],
+ AC_ARG_ENABLE(threads,
+ AC_HELP_STRING([--enable-threads],
+ [build with threads (default: off)]),
[tcl_ok=$enableval], [tcl_ok=no])
if test "${TCL_THREADS}" = 1; then
@@ -672,7 +680,39 @@ AC_DEFUN([SC_ENABLE_THREADS], [
ac_saved_libs=$LIBS
LIBS="$LIBS $THREADS_LIBS"
AC_CHECK_FUNCS(pthread_attr_setstacksize)
- AC_CHECK_FUNCS(pthread_atfork)
+ AC_CHECK_FUNC(pthread_attr_get_np,tcl_ok=yes,tcl_ok=no)
+ if test $tcl_ok = yes ; then
+ AC_DEFINE(HAVE_PTHREAD_ATTR_GET_NP, 1,
+ [Do we want a BSD-like thread-attribute interface?])
+ AC_CACHE_CHECK([for pthread_attr_get_np declaration],
+ tcl_cv_grep_pthread_attr_get_np, [
+ AC_EGREP_HEADER(pthread_attr_get_np, pthread.h,
+ tcl_cv_grep_pthread_attr_get_np=present,
+ tcl_cv_grep_pthread_attr_get_np=missing)])
+ if test $tcl_cv_grep_pthread_attr_get_np = missing ; then
+ AC_DEFINE(ATTRGETNP_NOT_DECLARED, 1,
+ [Is pthread_attr_get_np() declared in <pthread.h>?])
+ fi
+ else
+ AC_CHECK_FUNC(pthread_getattr_np,tcl_ok=yes,tcl_ok=no)
+ if test $tcl_ok = yes ; then
+ AC_DEFINE(HAVE_PTHREAD_GETATTR_NP, 1,
+ [Do we want a Linux-like thread-attribute interface?])
+ AC_CACHE_CHECK([for pthread_getattr_np declaration],
+ tcl_cv_grep_pthread_getattr_np, [
+ AC_EGREP_HEADER(pthread_getattr_np, pthread.h,
+ tcl_cv_grep_pthread_getattr_np=present,
+ tcl_cv_grep_pthread_getattr_np=missing)])
+ if test $tcl_cv_grep_pthread_getattr_np = missing ; then
+ AC_DEFINE(GETATTRNP_NOT_DECLARED, 1,
+ [Is pthread_getattr_np declared in <pthread.h>?])
+ fi
+ fi
+ fi
+ if test $tcl_ok = no; then
+ # Darwin thread stacksize API
+ AC_CHECK_FUNCS(pthread_get_stacksize_np)
+ fi
LIBS=$ac_saved_libs
else
TCL_THREADS=0
@@ -687,7 +727,7 @@ AC_DEFUN([SC_ENABLE_THREADS], [
AC_MSG_RESULT([yes])
fi
else
- AC_MSG_RESULT([no])
+ AC_MSG_RESULT([no (default)])
fi
AC_SUBST(TCL_THREADS)
@@ -719,42 +759,49 @@ AC_DEFUN([SC_ENABLE_THREADS], [
# Sets to $(CFLAGS_OPTIMIZE) if false
# LDFLAGS_DEFAULT Sets to $(LDFLAGS_DEBUG) if true
# Sets to $(LDFLAGS_OPTIMIZE) if false
-# DBGX Debug library extension
+# DBGX Formerly used as debug library extension;
+# always blank now.
#
#------------------------------------------------------------------------
AC_DEFUN([SC_ENABLE_SYMBOLS], [
AC_MSG_CHECKING([for build with symbols])
- AC_ARG_ENABLE(symbols, [ --enable-symbols build with debugging symbols [--disable-symbols]], [tcl_ok=$enableval], [tcl_ok=no])
+ AC_ARG_ENABLE(symbols,
+ AC_HELP_STRING([--enable-symbols],
+ [build with debugging symbols (default: off)]),
+ [tcl_ok=$enableval], [tcl_ok=no])
# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT.
+ DBGX=""
if test "$tcl_ok" = "no"; then
CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'
LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'
- DBGX=""
AC_MSG_RESULT([no])
+ AC_DEFINE(TCL_CFG_OPTIMIZED, 1, [Is this an optimized build?])
else
CFLAGS_DEFAULT='$(CFLAGS_DEBUG)'
LDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)'
- DBGX=g
if test "$tcl_ok" = "yes"; then
AC_MSG_RESULT([yes (standard debugging)])
fi
fi
AC_SUBST(CFLAGS_DEFAULT)
AC_SUBST(LDFLAGS_DEFAULT)
+ ### FIXME: Surely TCL_CFG_DEBUG should be set to whether we're debugging?
+ AC_DEFINE(TCL_CFG_DEBUG, 1, [Is debugging enabled?])
if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then
AC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?])
fi
- if test "$tcl_ok" = "compile" -o "$tcl_ok" = "all"; then
- AC_DEFINE(TCL_COMPILE_DEBUG, 1, [Is bytecode debugging enabled?])
- AC_DEFINE(TCL_COMPILE_STATS, 1, [Are bytecode statistics enabled?])
- fi
+ ifelse($1,bccdebug,dnl Only enable 'compile' for the Tcl core itself
+ if test "$tcl_ok" = "compile" -o "$tcl_ok" = "all"; then
+ AC_DEFINE(TCL_COMPILE_DEBUG, 1, [Is bytecode debugging enabled?])
+ AC_DEFINE(TCL_COMPILE_STATS, 1, [Are bytecode statistics enabled?])
+ fi)
if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then
if test "$tcl_ok" = "all"; then
- AC_MSG_RESULT([enabled symbols mem compile debugging])
+ AC_MSG_RESULT([enabled symbols mem ]ifelse($1,bccdebug,[compile ])[debugging])
else
AC_MSG_RESULT([enabled $tcl_ok debugging])
fi
@@ -782,8 +829,8 @@ AC_DEFUN([SC_ENABLE_SYMBOLS], [
AC_DEFUN([SC_ENABLE_LANGINFO], [
AC_ARG_ENABLE(langinfo,
- [ --enable-langinfo use nl_langinfo if possible to determine
- encoding at startup, otherwise use old heuristic],
+ AC_HELP_STRING([--enable-langinfo],
+ [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]),
[langinfo_ok=$enableval], [langinfo_ok=yes])
HAVE_LANGINFO=0
@@ -834,15 +881,16 @@ AC_DEFUN([SC_ENABLE_LANGINFO], [
AC_DEFUN([SC_CONFIG_MANPAGES], [
AC_MSG_CHECKING([whether to use symlinks for manpages])
AC_ARG_ENABLE(man-symlinks,
- [ --enable-man-symlinks use symlinks for the manpages],
+ AC_HELP_STRING([--enable-man-symlinks],
+ [use symlinks for the manpages (default: off)]),
test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks",
enableval="no")
AC_MSG_RESULT([$enableval])
AC_MSG_CHECKING([whether to compress the manpages])
AC_ARG_ENABLE(man-compression,
- [ --enable-man-compression=PROG
- compress the manpages with PROG],
+ AC_HELP_STRING([--enable-man-compression=PROG],
+ [compress the manpages with PROG (default: off)]),
[case $enableval in
yes) AC_MSG_ERROR([missing argument to --enable-man-compression]);;
no) ;;
@@ -862,11 +910,10 @@ AC_DEFUN([SC_CONFIG_MANPAGES], [
AC_MSG_CHECKING([whether to add a package name suffix for the manpages])
AC_ARG_ENABLE(man-suffix,
- [ --enable-man-suffix=STRING
- use STRING as a suffix to manpage file names
- (default: $1)],
+ AC_HELP_STRING([--enable-man-suffix=STRING],
+ [use STRING as a suffix to manpage file names (default: no, AC_PACKAGE_NAME if enabled without specifying STRING)]),
[case $enableval in
- yes) enableval="$1" MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
+ yes) enableval="AC_PACKAGE_NAME" MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
no) ;;
*) MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
esac],
@@ -994,16 +1041,9 @@ AC_DEFUN([SC_CONFIG_SYSTEM], [
# a .a extension whereas shared objects for loadable
# extensions have a .so extension. Defaults to
# ${VERSION}${SHLIB_SUFFIX}.
-# TCL_NEEDS_EXP_FILE -
-# 1 means that an export file is needed to link to a
-# shared library.
-# TCL_EXP_FILE - The name of the installed export / import file which
-# should be used to link to the Tcl shared library.
-# Empty if Tcl is unshared.
-# TCL_BUILD_EXP_FILE -
-# The name of the built export / import file which
-# should be used to link to the Tcl shared library.
-# Empty if Tcl is unshared.
+# TCL_LIBS -
+# Libs to use when linking Tcl shell or some other
+# shell that includes Tcl libs.
# CFLAGS_DEBUG -
# Flags used when running the compiler in debug mode
# CFLAGS_OPTIMIZE -
@@ -1017,21 +1057,48 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [
# Step 0.a: Enable 64 bit support?
AC_MSG_CHECKING([if 64bit support is requested])
- AC_ARG_ENABLE(64bit,[ --enable-64bit enable 64bit support (where applicable)],
+ AC_ARG_ENABLE(64bit,
+ AC_HELP_STRING([--enable-64bit],
+ [enable 64bit support (default: off)]),
[do64bit=$enableval], [do64bit=no])
AC_MSG_RESULT([$do64bit])
# Step 0.b: Enable Solaris 64 bit VIS support?
AC_MSG_CHECKING([if 64bit Sparc VIS support is requested])
- AC_ARG_ENABLE(64bit-vis,[ --enable-64bit-vis enable 64bit Sparc VIS support],
+ AC_ARG_ENABLE(64bit-vis,
+ AC_HELP_STRING([--enable-64bit-vis],
+ [enable 64bit Sparc VIS support (default: off)]),
[do64bitVIS=$enableval], [do64bitVIS=no])
AC_MSG_RESULT([$do64bitVIS])
+ # Force 64bit on with VIS
+ AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes])
+
+ # Step 0.c: Check if visibility support is available. Do this here so
+ # that platform specific alternatives can be used below if this fails.
+
+ AC_CACHE_CHECK([if compiler supports visibility "hidden"],
+ tcl_cv_cc_visibility_hidden, [
+ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
+ AC_TRY_LINK([
+ extern __attribute__((__visibility__("hidden"))) void f(void);
+ void f(void) {}], [f();], tcl_cv_cc_visibility_hidden=yes,
+ tcl_cv_cc_visibility_hidden=no)
+ CFLAGS=$hold_cflags])
+ AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [
+ AC_DEFINE(MODULE_SCOPE,
+ [extern __attribute__((__visibility__("hidden")))],
+ [Compiler support for module scope symbols])
+ ])
- if test "$do64bitVIS" = "yes"; then
- # Force 64bit on with VIS
- do64bit=yes
- fi
+ # Step 0.d: Disable -rpath support?
+
+ AC_MSG_CHECKING([if rpath support is requested])
+ AC_ARG_ENABLE(rpath,
+ AC_HELP_STRING([--disable-rpath],
+ [disable rpath support (default: on)]),
+ [doRpath=$enableval], [doRpath=yes])
+ AC_MSG_RESULT([$doRpath])
# Step 1: set the variable "system" to hold the name and version number
# for the system.
@@ -1044,41 +1111,38 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [
AC_CHECK_LIB(dl, dlopen, have_dl=yes, have_dl=no)
# Require ranlib early so we can override it in special cases below.
+ AS_IF([test x"${SHLIB_VERSION}" = x], [SHLIB_VERSION="1.0"])
AC_REQUIRE([AC_PROG_RANLIB])
# Step 3: set configuration options based on system name and version.
do64bit_ok=no
+ # default to '{$LIBS}' and set to "" on per-platform necessary basis
+ SHLIB_LD_LIBS='${LIBS}'
LDFLAGS_ORIG="$LDFLAGS"
- TCL_EXPORT_FILE_SUFFIX=""
+ # When ld needs options to work in 64-bit mode, put them in
+ # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load]
+ # is disabled by the user. [Bug 1016796]
+ LDFLAGS_ARCH=""
UNSHARED_LIB_SUFFIX=""
TCL_TRIM_DOTS='`echo ${VERSION} | tr -d .`'
ECHO_VERSION='`echo ${VERSION}`'
TCL_LIB_VERSIONS_OK=ok
CFLAGS_DEBUG=-g
CFLAGS_OPTIMIZE=-O
- if test "$GCC" = "yes" ; then
- CFLAGS_WARNING="-Wall -fno-strict-aliasing"
- else
- CFLAGS_WARNING=""
- fi
- TCL_NEEDS_EXP_FILE=0
- TCL_BUILD_EXP_FILE=""
- TCL_EXP_FILE=""
-dnl FIXME: Replace AC_CHECK_PROG with AC_CHECK_TOOL once cross compiling is fixed.
-dnl AC_CHECK_TOOL(AR, ar)
- AC_CHECK_PROG(AR, ar, ar)
- if test "${AR}" = "" ; then
- AC_MSG_ERROR([Required archive tool 'ar' not found on PATH.])
- fi
+ AS_IF([test "$GCC" = yes], [
+ CFLAGS_WARNING="-Wall"
+ ], [CFLAGS_WARNING=""])
+ AC_CHECK_TOOL(AR, ar)
STLIB_LD='${AR} cr'
LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH"
PLAT_OBJS=""
PLAT_SRCS=""
+ LDAIX_SRC=""
case $system in
AIX-*)
- if test "${TCL_THREADS}" = "1" -a "$GCC" != "yes" ; then
+ AS_IF([test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"], [
# AIX requires the _r compiler when gcc isn't being used
case "${CC}" in
*_r|*_r\ *)
@@ -1090,84 +1154,59 @@ dnl AC_CHECK_TOOL(AR, ar)
;;
esac
AC_MSG_RESULT([Using $CC for compiling with threads])
- fi
+ ])
LIBS="$LIBS -lc"
SHLIB_CFLAGS=""
- # Note: need the LIBS below, otherwise Tk won't find Tcl's
- # symbols when dynamically loaded into tclsh.
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
LD_LIBRARY_PATH_VAR="LIBPATH"
- # Check to enable 64-bit flags for compiler/linker on AIX 4+
- if test "$do64bit" = "yes" -a "`uname -v`" -gt "3" ; then
- if test "$GCC" = "yes" ; then
+ # ldAix No longer needed with use of -bexpall/-brtl
+ # but some extensions may still reference it
+ LDAIX_SRC='$(UNIX_DIR)/ldAix'
+
+ # Check to enable 64-bit flags for compiler/linker
+ AS_IF([test "$do64bit" = yes], [
+ AS_IF([test "$GCC" = yes], [
AC_MSG_WARN([64bit mode not supported with GCC on $system])
- else
+ ], [
do64bit_ok=yes
CFLAGS="$CFLAGS -q64"
- LDFLAGS="$LDFLAGS -q64"
+ LDFLAGS_ARCH="-q64"
RANLIB="${RANLIB} -X64"
AR="${AR} -X64"
SHLIB_LD_FLAGS="-b64"
- fi
- fi
+ ])
+ ])
- if test "`uname -m`" = "ia64" ; then
+ AS_IF([test "`uname -m`" = ia64], [
# AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC
SHLIB_LD="/usr/ccs/bin/ld -G -z text"
# AIX-5 has dl* in libc.so
DL_LIBS=""
- if test "$GCC" = "yes" ; then
+ AS_IF([test "$GCC" = yes], [
CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
- else
+ ], [
CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}'
- fi
+ ])
LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
- else
- if test "$GCC" = "yes" ; then
- SHLIB_LD="gcc -shared"
- else
- SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry"
- fi
- SHLIB_LD="${TCL_SRC_DIR}/unix/ldAix ${SHLIB_LD} ${SHLIB_LD_FLAGS}"
+ ], [
+ AS_IF([test "$GCC" = yes], [
+ SHLIB_LD='${CC} -shared -Wl,-bexpall'
+ ], [
+ SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry"
+ LDFLAGS="$LDFLAGS -brtl"
+ ])
+ SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}"
DL_LIBS="-ldl"
CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- TCL_NEEDS_EXP_FILE=1
- TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.exp'
- fi
-
- # AIX v<=4.1 has some different flags than 4.2+
- if test "$system" = "AIX-4.1" -o "`uname -v`" -lt "4" ; then
- LIBOBJS="$LIBOBJS tclLoadAix.o"
- DL_LIBS="-lld"
- fi
-
- # On AIX <=v4 systems, libbsd.a has to be linked in to support
- # non-blocking file IO. This library has to be linked in after
- # the MATH_LIBS or it breaks the pow() function. The way to
- # insure proper sequencing, is to add it to the tail of MATH_LIBS.
- # This library also supplies gettimeofday.
- #
- # AIX does not have a timezone field in struct tm. When the AIX
- # bsd library is used, the timezone global and the gettimeofday
- # methods are to be avoided for timezone deduction instead, we
- # deduce the timezone by comparing the localtime result on a
- # known GMT value.
-
- AC_CHECK_LIB(bsd, gettimeofday, libbsd=yes, libbsd=no)
- if test $libbsd = yes; then
- MATH_LIBS="$MATH_LIBS -lbsd"
- AC_DEFINE(USE_DELTA_FOR_TZ)
- fi
+ ])
;;
BeOS*)
SHLIB_CFLAGS="-fPIC"
- SHLIB_LD="${CC} -nostart"
- SHLIB_LD_LIBS='${LIBS}'
+ SHLIB_LD='${CC} -nostart'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS="-ldl"
@@ -1182,7 +1221,6 @@ dnl AC_CHECK_TOOL(AR, ar)
BSD/OS-2.1*|BSD/OS-3*)
SHLIB_CFLAGS=""
SHLIB_LD="shlicc -r"
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS="-ldl"
@@ -1192,7 +1230,6 @@ dnl AC_CHECK_TOOL(AR, ar)
BSD/OS-4.*)
SHLIB_CFLAGS="-export-dynamic -fPIC"
SHLIB_LD='${CC} -shared'
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS="-ldl"
@@ -1203,7 +1240,6 @@ dnl AC_CHECK_TOOL(AR, ar)
CYGWIN_*)
SHLIB_CFLAGS=""
SHLIB_LD='${CC} -shared'
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".dll"
DL_OBJS="tclLoadDl.o"
DL_LIBS="-ldl"
@@ -1220,66 +1256,71 @@ dnl AC_CHECK_TOOL(AR, ar)
CC_SEARCH_FLAGS=""
LD_SEARCH_FLAGS=""
;;
+ Haiku*)
+ LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_SUFFIX=".so"
+ SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-lroot"
+ AC_CHECK_LIB(network, inet_ntoa, [LIBS="$LIBS -lnetwork"])
+ ;;
HP-UX-*.11.*)
# Use updated header definitions where possible
- AC_DEFINE(_XOPEN_SOURCE) # Use the XOPEN network library
- AC_DEFINE(_XOPEN_SOURCE_EXTENDED) # Use the XOPEN network library
+ AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?])
+ AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?])
LIBS="$LIBS -lxnet" # Use the XOPEN network library
- if test "`uname -m`" = "ia64" ; then
+ AS_IF([test "`uname -m`" = ia64], [
SHLIB_SUFFIX=".so"
- else
+ ], [
SHLIB_SUFFIX=".sl"
- fi
+ ])
AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no)
- if test "$tcl_ok" = yes; then
+ AS_IF([test "$tcl_ok" = yes], [
SHLIB_CFLAGS="+z"
SHLIB_LD="ld -b"
- SHLIB_LD_LIBS='${LIBS}'
DL_OBJS="tclLoadShl.o"
DL_LIBS="-ldld"
LDFLAGS="$LDFLAGS -Wl,-E"
CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'
LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'
LD_LIBRARY_PATH_VAR="SHLIB_PATH"
- fi
- if test "$GCC" = "yes" ; then
- SHLIB_LD="gcc -shared"
- SHLIB_LD_LIBS='${LIBS}'
+ ])
+ AS_IF([test "$GCC" = yes], [
+ SHLIB_LD='${CC} -shared'
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- fi
+ ])
# Users may want PA-RISC 1.1/2.0 portable code - needs HP cc
#CFLAGS="$CFLAGS +DAportable"
# Check to enable 64-bit flags for compiler/linker
- if test "$do64bit" = "yes" ; then
- if test "$GCC" = "yes" ; then
- hpux_arch=`${CC} -dumpmachine`
- case $hpux_arch in
+ AS_IF([test "$do64bit" = "yes"], [
+ AS_IF([test "$GCC" = yes], [
+ case `${CC} -dumpmachine` in
hppa64*)
# 64-bit gcc in use. Fix flags for GNU ld.
do64bit_ok=yes
- SHLIB_LD="${CC} -shared"
- SHLIB_LD_LIBS='${LIBS}'
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ SHLIB_LD='${CC} -shared'
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
;;
*)
AC_MSG_WARN([64bit mode not supported with GCC on $system])
;;
esac
- else
+ ], [
do64bit_ok=yes
CFLAGS="$CFLAGS +DD64"
- LDFLAGS="$LDFLAGS +DD64"
- fi
- fi
- ;;
+ LDFLAGS_ARCH="+DD64"
+ ])
+ ]) ;;
HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*)
SHLIB_SUFFIX=".sl"
AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no)
- if test "$tcl_ok" = yes; then
+ AS_IF([test "$tcl_ok" = yes], [
SHLIB_CFLAGS="+z"
SHLIB_LD="ld -b"
SHLIB_LD_LIBS=""
@@ -1289,43 +1330,30 @@ dnl AC_CHECK_TOOL(AR, ar)
CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'
LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'
LD_LIBRARY_PATH_VAR="SHLIB_PATH"
- fi
- ;;
- IRIX-4.*)
- SHLIB_CFLAGS="-G 0"
- SHLIB_SUFFIX=".a"
- SHLIB_LD="echo tclLdAout $CC \{$SHLIB_CFLAGS\} | `pwd`/tclsh -r -G 0"
- SHLIB_LD_LIBS='${LIBS}'
- DL_OBJS="tclLoadAout.o"
- DL_LIBS=""
- LDFLAGS="$LDFLAGS -Wl,-D,08000000"
- CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- SHARED_LIB_SUFFIX='${VERSION}\$\{DBGX\}.a'
- ;;
+ ]) ;;
IRIX-5.*)
SHLIB_CFLAGS=""
SHLIB_LD="ld -shared -rdata_shared"
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS=""
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
;;
IRIX-6.*)
SHLIB_CFLAGS=""
SHLIB_LD="ld -n32 -shared -rdata_shared"
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS=""
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
- if test "$GCC" = "yes" ; then
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
+ AS_IF([test "$GCC" = yes], [
CFLAGS="$CFLAGS -mabi=n32"
LDFLAGS="$LDFLAGS -mabi=n32"
- else
+ ], [
case $system in
IRIX-6.3)
# Use to build 6.2 compatible binaries on 6.3.
@@ -1336,126 +1364,96 @@ dnl AC_CHECK_TOOL(AR, ar)
;;
esac
LDFLAGS="$LDFLAGS -n32"
- fi
+ ])
;;
IRIX64-6.*)
SHLIB_CFLAGS=""
SHLIB_LD="ld -n32 -shared -rdata_shared"
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS=""
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
# Check to enable 64-bit flags for compiler/linker
- if test "$do64bit" = "yes" ; then
- if test "$GCC" = "yes" ; then
+ AS_IF([test "$do64bit" = yes], [
+ AS_IF([test "$GCC" = yes], [
AC_MSG_WARN([64bit mode not supported by gcc])
- else
+ ], [
do64bit_ok=yes
SHLIB_LD="ld -64 -shared -rdata_shared"
CFLAGS="$CFLAGS -64"
- LDFLAGS="$LDFLAGS -64"
- fi
- fi
+ LDFLAGS_ARCH="-64"
+ ])
+ ])
;;
Linux*)
SHLIB_CFLAGS="-fPIC"
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
- CFLAGS_OPTIMIZE=-O2
+ CFLAGS_OPTIMIZE="-O2"
# egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings
# when you inline the string and math operations. Turn this off to
# get rid of the warnings.
#CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES"
- if test "$have_dl" = yes; then
- SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
- DL_OBJS="tclLoadDl.o"
- DL_LIBS="-ldl"
- LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- else
- AC_CHECK_HEADER(dld.h, [
- SHLIB_LD="ld -shared"
- DL_OBJS="tclLoadDld.o"
- DL_LIBS="-ldld"
- CC_SEARCH_FLAGS=""
- LD_SEARCH_FLAGS=""])
- fi
- if test "`uname -m`" = "alpha" ; then
- CFLAGS="$CFLAGS -mieee"
- fi
- if test $do64bit = yes; then
+ SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"])
+ AS_IF([test $do64bit = yes], [
AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [
hold_cflags=$CFLAGS
CFLAGS="$CFLAGS -m64"
AC_TRY_LINK(,, tcl_cv_cc_m64=yes, tcl_cv_cc_m64=no)
CFLAGS=$hold_cflags])
- if test $tcl_cv_cc_m64 = yes; then
+ AS_IF([test $tcl_cv_cc_m64 = yes], [
CFLAGS="$CFLAGS -m64"
do64bit_ok=yes
- fi
- fi
+ ])
+ ])
- # The combo of gcc + glibc has a bug related
- # to inlining of functions like strtod(). The
- # -fno-builtin flag should address this problem
- # but it does not work. The -fno-inline flag
- # is kind of overkill but it works.
- # Disable inlining only when one of the
+ # The combo of gcc + glibc has a bug related to inlining of
+ # functions like strtod(). The -fno-builtin flag should address
+ # this problem but it does not work. The -fno-inline flag is kind
+ # of overkill but it works. Disable inlining only when one of the
# files in compat/*.c is being linked in.
- if test x"${LIBOBJS}" != x ; then
- CFLAGS="$CFLAGS -fno-inline"
- fi
-
- # XIM peeking works under XFree86.
- AC_DEFINE(PEEK_XCLOSEIM)
+ AS_IF([test x"${USE_COMPAT}" != x],[CFLAGS="$CFLAGS -fno-inline"])
;;
GNU*)
SHLIB_CFLAGS="-fPIC"
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
- if test "$have_dl" = yes; then
- SHLIB_LD="${CC} -shared"
- DL_OBJS=""
- DL_LIBS="-ldl"
- LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
- CC_SEARCH_FLAGS=""
- LD_SEARCH_FLAGS=""
- else
- AC_CHECK_HEADER(dld.h, [
- SHLIB_LD="ld -shared"
- DL_OBJS=""
- DL_LIBS="-ldld"
- CC_SEARCH_FLAGS=""
- LD_SEARCH_FLAGS=""])
- fi
- if test "`uname -m`" = "alpha" ; then
- CFLAGS="$CFLAGS -mieee"
- fi
+ SHLIB_LD='${CC} -shared'
+ DL_OBJS=""
+ DL_LIBS="-ldl"
+ LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"])
;;
Lynx*)
SHLIB_CFLAGS="-fPIC"
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
CFLAGS_OPTIMIZE=-02
- SHLIB_LD="${CC} -shared "
+ SHLIB_LD='${CC} -shared'
DL_OBJS="tclLoadDl.o"
DL_LIBS="-mshared -ldl"
LD_FLAGS="-Wl,--export-dynamic"
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
;;
MP-RAS-02*)
SHLIB_CFLAGS="-K PIC"
- SHLIB_LD="cc -G"
+ SHLIB_LD='${CC} -G'
SHLIB_LD_LIBS=""
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
@@ -1465,7 +1463,7 @@ dnl AC_CHECK_TOOL(AR, ar)
;;
MP-RAS-*)
SHLIB_CFLAGS="-K PIC"
- SHLIB_LD="cc -G"
+ SHLIB_LD='${CC} -G'
SHLIB_LD_LIBS=""
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
@@ -1474,120 +1472,133 @@ dnl AC_CHECK_TOOL(AR, ar)
CC_SEARCH_FLAGS=""
LD_SEARCH_FLAGS=""
;;
- NetBSD-*|FreeBSD-[[1-2]].*)
- # Not available on all versions: check for include file.
- AC_CHECK_HEADER(dlfcn.h, [
- # NetBSD/SPARC needs -fPIC, -fpic will not do.
- SHLIB_CFLAGS="-fPIC"
- SHLIB_LD="ld -Bshareable -x"
- SHLIB_LD_LIBS='${LIBS}'
- SHLIB_SUFFIX=".so"
- DL_OBJS="tclLoadDl.o"
- DL_LIBS=""
+ NetBSD-1.*|FreeBSD-[[1-2]].*)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD="ld -Bshareable -x"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ AS_IF([test $doRpath = yes], [
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
- AC_CACHE_CHECK([for ELF], tcl_cv_ld_elf, [
- AC_EGREP_CPP(yes, [
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
+ AC_CACHE_CHECK([for ELF], tcl_cv_ld_elf, [
+ AC_EGREP_CPP(yes, [
#ifdef __ELF__
yes
#endif
- ], tcl_cv_ld_elf=yes, tcl_cv_ld_elf=no)])
- if test $tcl_cv_ld_elf = yes; then
- SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so'
- else
- SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1.0'
- fi
+ ], tcl_cv_ld_elf=yes, tcl_cv_ld_elf=no)])
+ AS_IF([test $tcl_cv_ld_elf = yes], [
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'
], [
- SHLIB_CFLAGS=""
- SHLIB_LD="echo tclLdAout $CC \{$SHLIB_CFLAGS\} | `pwd`/tclsh -r"
- SHLIB_LD_LIBS='${LIBS}'
- SHLIB_SUFFIX=".a"
- DL_OBJS="tclLoadAout.o"
- DL_LIBS=""
- CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a'
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
])
- # FreeBSD doesn't handle version numbers with dots.
+ # Ancient FreeBSD doesn't handle version numbers with dots.
- UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a'
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
TCL_LIB_VERSIONS_OK=nodots
;;
OpenBSD-*)
- case `arch -s` in
+ arch=`arch -s`
+ case "$arch" in
m88k|vax)
- SHLIB_CFLAGS=""
- SHLIB_LD="echo tclLdAout $CC \{$SHLIB_CFLAGS\} | `pwd`/tclsh -r"
- SHLIB_LD_LIBS='${LIBS}'
- SHLIB_SUFFIX=".a"
- DL_OBJS="tclLoadAout.o"
- DL_LIBS=""
- LDFLAGS=""
- CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a'
+ # Equivalent using configure option --disable-load
+ # Step 4 will set the necessary variables
+ DL_OBJS=""
+ SHLIB_LD_LIBS=""
;;
*)
- # OpenBSD/SPARC[64] needs -fPIC, -fpic will not do.
- case `machine` in
- sparc|sparc64)
- SHLIB_CFLAGS="-fPIC";;
- *)
- SHLIB_CFLAGS="-fpic";;
- esac
- SHLIB_LD="${CC} -shared ${SHLIB_CFLAGS}"
- SHLIB_LD_LIBS='${LIBS}'
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS=""
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1.0'
- AC_CACHE_CHECK([for ELF], tcl_cv_ld_elf, [
- AC_EGREP_CPP(yes, [
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
+ ;;
+ esac
+ case "$arch" in
+ m88k|vax)
+ CFLAGS_OPTIMIZE="-O1"
+ ;;
+ sh)
+ CFLAGS_OPTIMIZE="-O0"
+ ;;
+ *)
+ CFLAGS_OPTIMIZE="-O2"
+ ;;
+ esac
+ AC_CACHE_CHECK([for ELF], tcl_cv_ld_elf, [
+ AC_EGREP_CPP(yes, [
#ifdef __ELF__
yes
#endif
- ], tcl_cv_ld_elf=yes, tcl_cv_ld_elf=no)])
- if test $tcl_cv_ld_elf = yes; then
- LDFLAGS=-Wl,-export-dynamic
- else
- LDFLAGS=""
- fi
- ;;
- esac
-
+ ], tcl_cv_ld_elf=yes, tcl_cv_ld_elf=no)])
+ AS_IF([test $tcl_cv_ld_elf = yes], [
+ LDFLAGS=-Wl,-export-dynamic
+ ], [LDFLAGS=""])
+ AS_IF([test "${TCL_THREADS}" = "1"], [
+ # On OpenBSD: Compile with -pthread
+ # Don't link with -lpthread
+ LIBS=`echo $LIBS | sed s/-lpthread//`
+ CFLAGS="$CFLAGS -pthread"
+ ])
# OpenBSD doesn't do version numbers with dots.
- UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a'
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
TCL_LIB_VERSIONS_OK=nodots
;;
- FreeBSD-*)
+ NetBSD-*|FreeBSD-[[3-4]].*)
# FreeBSD 3.* and greater have ELF.
+ # NetBSD 2.* has ELF and can use 'cc -shared' to build shared libs
SHLIB_CFLAGS="-fPIC"
- SHLIB_LD="ld -Bshareable -x"
- SHLIB_LD_LIBS='${LIBS}'
+ SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS=""
LDFLAGS="$LDFLAGS -export-dynamic"
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
- if test "${TCL_THREADS}" = "1" ; then
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ AS_IF([test "${TCL_THREADS}" = "1"], [
# The -pthread needs to go in the CFLAGS, not LIBS
LIBS=`echo $LIBS | sed s/-pthread//`
CFLAGS="$CFLAGS -pthread"
LDFLAGS="$LDFLAGS -pthread"
- fi
+ ])
case $system in
FreeBSD-3.*)
# FreeBSD-3 doesn't handle version numbers with dots.
- UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a'
- SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so'
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'
TCL_LIB_VERSIONS_OK=nodots
;;
esac
;;
+ FreeBSD-*)
+ # This configuration from FreeBSD Ports.
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD="${CC} -shared"
+ TCL_SHLIB_LD_EXTRAS="-soname \$[@]"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ LDFLAGS=""
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
+ AS_IF([test "${TCL_THREADS}" = "1"], [
+ # The -pthread needs to go in the LDFLAGS, not LIBS
+ LIBS=`echo $LIBS | sed s/-pthread//`
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LDFLAGS="$LDFLAGS $PTHREAD_LIBS"])
+ # Version numbers are dot-stripped by system policy.
+ TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .`
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1'
+ TCL_LIB_VERSIONS_OK=nodots
+ ;;
Darwin-*)
CFLAGS_OPTIMIZE="-Os"
SHLIB_CFLAGS="-fno-common"
@@ -1600,7 +1611,7 @@ dnl AC_CHECK_TOOL(AR, ar)
CFLAGS="`echo " ${CFLAGS}" | \
awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
if (!([$]i~/^(isysroot|mmacosx-version-min)/)) print "-"[$]i}'`"
- if test $do64bit = yes; then
+ AS_IF([test $do64bit = yes], [
case `arch` in
ppc)
AC_CACHE_CHECK([if compiler accepts -arch ppc64 flag],
@@ -1610,10 +1621,10 @@ dnl AC_CHECK_TOOL(AR, ar)
AC_TRY_LINK(,, tcl_cv_cc_arch_ppc64=yes,
tcl_cv_cc_arch_ppc64=no)
CFLAGS=$hold_cflags])
- if test $tcl_cv_cc_arch_ppc64 = yes; then
+ AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [
CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
do64bit_ok=yes
- fi;;
+ ]);;
i386)
AC_CACHE_CHECK([if compiler accepts -arch x86_64 flag],
tcl_cv_cc_arch_x86_64, [
@@ -1622,93 +1633,109 @@ dnl AC_CHECK_TOOL(AR, ar)
AC_TRY_LINK(,, tcl_cv_cc_arch_x86_64=yes,
tcl_cv_cc_arch_x86_64=no)
CFLAGS=$hold_cflags])
- if test $tcl_cv_cc_arch_x86_64 = yes; then
+ AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [
CFLAGS="$CFLAGS -arch x86_64"
do64bit_ok=yes
- fi;;
+ ]);;
*)
AC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);;
esac
- else
+ ], [
# Check for combined 32-bit and 64-bit fat build
- echo "$CFLAGS " | grep -E -q -- '-arch (ppc64|x86_64) ' && \
- echo "$CFLAGS " | grep -E -q -- '-arch (ppc|i386) ' && \
- fat_32_64=yes
- fi
+ AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \
+ && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '], [
+ fat_32_64=yes])
+ ])
SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS}'
AC_CACHE_CHECK([if ld accepts -single_module flag], tcl_cv_ld_single_module, [
hold_ldflags=$LDFLAGS
LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module"
AC_TRY_LINK(, [int i;], tcl_cv_ld_single_module=yes, tcl_cv_ld_single_module=no)
LDFLAGS=$hold_ldflags])
- if test $tcl_cv_ld_single_module = yes; then
+ AS_IF([test $tcl_cv_ld_single_module = yes], [
SHLIB_LD="${SHLIB_LD} -Wl,-single_module"
- fi
- SHLIB_LD_LIBS='${LIBS}'
+ ])
SHLIB_SUFFIX=".dylib"
DL_OBJS="tclLoadDyld.o"
DL_LIBS=""
# Don't use -prebind when building for Mac OS X 10.4 or later only:
- test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int([$]2)}'`" -lt 4 -a \
- "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int([$]2)}'`" -lt 4 && \
- LDFLAGS="$LDFLAGS -prebind"
+ AS_IF([test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int([$]2)}'`" -lt 4 -a \
+ "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int([$]2)}'`" -lt 4], [
+ LDFLAGS="$LDFLAGS -prebind"])
LDFLAGS="$LDFLAGS -headerpad_max_install_names"
- AC_CACHE_CHECK([if ld accepts -search_paths_first flag], tcl_cv_ld_search_paths_first, [
+ AC_CACHE_CHECK([if ld accepts -search_paths_first flag],
+ tcl_cv_ld_search_paths_first, [
hold_ldflags=$LDFLAGS
LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
- AC_TRY_LINK(, [int i;], tcl_cv_ld_search_paths_first=yes, tcl_cv_ld_search_paths_first=no)
+ AC_TRY_LINK(, [int i;], tcl_cv_ld_search_paths_first=yes,
+ tcl_cv_ld_search_paths_first=no)
LDFLAGS=$hold_ldflags])
- if test $tcl_cv_ld_search_paths_first = yes; then
+ AS_IF([test $tcl_cv_ld_search_paths_first = yes], [
LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
- fi
+ ])
+ AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
+ AC_DEFINE(MODULE_SCOPE, [__private_extern__],
+ [Compiler support for module scope symbols])
+ ])
CC_SEARCH_FLAGS=""
LD_SEARCH_FLAGS=""
LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH"
- PLAT_OBJS=\$\(MAC\_OSX_OBJS\)
- PLAT_SRCS=\$\(MAC\_OSX_SRCS\)
+ AC_DEFINE(MAC_OSX_TCL, 1, [Is this a Mac I see before me?])
+ PLAT_OBJS='${MAC_OSX_OBJS}'
+ PLAT_SRCS='${MAC_OSX_SRCS}'
AC_MSG_CHECKING([whether to use CoreFoundation])
- AC_ARG_ENABLE(corefoundation, [ --enable-corefoundation use CoreFoundation API [--enable-corefoundation]],
+ AC_ARG_ENABLE(corefoundation,
+ AC_HELP_STRING([--enable-corefoundation],
+ [use CoreFoundation API on MacOSX (default: on)]),
[tcl_corefoundation=$enableval], [tcl_corefoundation=yes])
AC_MSG_RESULT([$tcl_corefoundation])
- if test $tcl_corefoundation = yes; then
- AC_CACHE_CHECK([for CoreFoundation.framework], tcl_cv_lib_corefoundation, [
+ AS_IF([test $tcl_corefoundation = yes], [
+ AC_CACHE_CHECK([for CoreFoundation.framework],
+ tcl_cv_lib_corefoundation, [
hold_libs=$LIBS
- if test "$fat_32_64" = yes; then for v in CFLAGS CPPFLAGS LDFLAGS; do
- # On Tiger there is no 64-bit CF, so remove 64-bit archs
- # from CFLAGS et al. while testing for presence of CF.
- # 64-bit CF is disabled in tclUnixPort.h if necessary.
- eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"'
- done; fi
+ AS_IF([test "$fat_32_64" = yes], [
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ # On Tiger there is no 64-bit CF, so remove 64-bit
+ # archs from CFLAGS et al. while testing for
+ # presence of CF. 64-bit CF is disabled in
+ # tclUnixPort.h if necessary.
+ eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"'
+ done])
LIBS="$LIBS -framework CoreFoundation"
AC_TRY_LINK([#include <CoreFoundation/CoreFoundation.h>],
[CFBundleRef b = CFBundleGetMainBundle();],
- tcl_cv_lib_corefoundation=yes, tcl_cv_lib_corefoundation=no)
- if test "$fat_32_64" = yes; then for v in CFLAGS CPPFLAGS LDFLAGS; do
- eval $v'="$hold_'$v'"'
- done; fi; LIBS=$hold_libs])
- if test $tcl_cv_lib_corefoundation = yes; then
+ tcl_cv_lib_corefoundation=yes,
+ tcl_cv_lib_corefoundation=no)
+ AS_IF([test "$fat_32_64" = yes], [
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval $v'="$hold_'$v'"'
+ done])
+ LIBS=$hold_libs])
+ AS_IF([test $tcl_cv_lib_corefoundation = yes], [
LIBS="$LIBS -framework CoreFoundation"
- AC_DEFINE(HAVE_COREFOUNDATION)
- else
- tcl_corefoundation=no
- fi
- if test "$fat_32_64" = yes -a $tcl_corefoundation = yes; then
- AC_CACHE_CHECK([for 64-bit CoreFoundation], tcl_cv_lib_corefoundation_64, [
+ AC_DEFINE(HAVE_COREFOUNDATION, 1,
+ [Do we have access to Darwin CoreFoundation.framework?])
+ ], [tcl_corefoundation=no])
+ AS_IF([test "$fat_32_64" = yes -a $tcl_corefoundation = yes],[
+ AC_CACHE_CHECK([for 64-bit CoreFoundation],
+ tcl_cv_lib_corefoundation_64, [
for v in CFLAGS CPPFLAGS LDFLAGS; do
eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
done
AC_TRY_LINK([#include <CoreFoundation/CoreFoundation.h>],
[CFBundleRef b = CFBundleGetMainBundle();],
- tcl_cv_lib_corefoundation_64=yes, tcl_cv_lib_corefoundation_64=no)
+ tcl_cv_lib_corefoundation_64=yes,
+ tcl_cv_lib_corefoundation_64=no)
for v in CFLAGS CPPFLAGS LDFLAGS; do
eval $v'="$hold_'$v'"'
done])
- if test $tcl_cv_lib_corefoundation_64 = no; then
- AC_DEFINE(NO_COREFOUNDATION_64)
- fi
- fi
- fi
- AC_DEFINE(MAC_OSX_TCL)
+ AS_IF([test $tcl_cv_lib_corefoundation_64 = no], [
+ AC_DEFINE(NO_COREFOUNDATION_64, 1,
+ [Is Darwin CoreFoundation unavailable for 64-bit?])
+ LDFLAGS="$LDFLAGS -Wl,-no_arch_warnings"
+ ])
+ ])
+ ])
;;
NEXTSTEP-*)
SHLIB_CFLAGS=""
@@ -1721,6 +1748,7 @@ dnl AC_CHECK_TOOL(AR, ar)
LD_SEARCH_FLAGS=""
;;
OS/390-*)
+ SHLIB_LD_LIBS=""
CFLAGS_OPTIMIZE="" # Optimizer is buggy
AC_DEFINE(_OE_SOCKETS, 1, # needed in sys/socket.h
[Should OS/390 do the right thing with sockets?])
@@ -1740,11 +1768,9 @@ dnl AC_CHECK_TOOL(AR, ar)
OSF1-1.*)
# OSF/1 1.3 from OSF using ELF, and derivatives, including AD2
SHLIB_CFLAGS="-fPIC"
- if test "$SHARED_BUILD" = "1" ; then
- SHLIB_LD="ld -shared"
- else
+ AS_IF([test "$SHARED_BUILD" = 1], [SHLIB_LD="ld -shared"], [
SHLIB_LD="ld -non_shared"
- fi
+ ])
SHLIB_LD_LIBS=""
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
@@ -1755,35 +1781,31 @@ dnl AC_CHECK_TOOL(AR, ar)
OSF1-V*)
# Digital OSF/1
SHLIB_CFLAGS=""
- if test "$SHARED_BUILD" = "1" ; then
+ AS_IF([test "$SHARED_BUILD" = 1], [
SHLIB_LD='ld -shared -expect_unresolved "*"'
- else
+ ], [
SHLIB_LD='ld -non_shared -expect_unresolved "*"'
- fi
- SHLIB_LD_LIBS='${LIBS}'
+ ])
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS=""
- CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
- if test "$GCC" = "yes" ; then
- CFLAGS="$CFLAGS -mieee"
- else
- CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"
- fi
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
+ AS_IF([test "$GCC" = yes], [CFLAGS="$CFLAGS -mieee"], [
+ CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"])
# see pthread_intro(3) for pthread support on osf1, k.furukawa
- if test "${TCL_THREADS}" = "1" ; then
+ AS_IF([test "${TCL_THREADS}" = 1], [
CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE"
CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64"
LIBS=`echo $LIBS | sed s/-lpthreads//`
- if test "$GCC" = "yes" ; then
+ AS_IF([test "$GCC" = yes], [
LIBS="$LIBS -lpthread -lmach -lexc"
- else
+ ], [
CFLAGS="$CFLAGS -pthread"
LDFLAGS="$LDFLAGS -pthread"
- fi
- fi
-
+ ])
+ ])
;;
QNX-6*)
# QNX RTP
@@ -1798,28 +1820,17 @@ dnl AC_CHECK_TOOL(AR, ar)
CC_SEARCH_FLAGS=""
LD_SEARCH_FLAGS=""
;;
- RISCos-*)
- SHLIB_CFLAGS="-G 0"
- SHLIB_LD="echo tclLdAout $CC \{$SHLIB_CFLAGS\} | `pwd`/tclsh -r -G 0"
- SHLIB_LD_LIBS='${LIBS}'
- SHLIB_SUFFIX=".a"
- DL_OBJS="tclLoadAout.o"
- DL_LIBS=""
- LDFLAGS="$LDFLAGS -Wl,-D,08000000"
- CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- ;;
SCO_SV-3.2*)
# Note, dlopen is available only on SCO 3.2.5 and greater. However,
# this test works, since "uname -s" was non-standard in 3.2.4 and
# below.
- if test "$GCC" = "yes" ; then
+ AS_IF([test "$GCC" = yes], [
SHLIB_CFLAGS="-fPIC -melf"
LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"
- else
+ ], [
SHLIB_CFLAGS="-Kpic -belf"
LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"
- fi
+ ])
SHLIB_LD="ld -G"
SHLIB_LD_LIBS=""
SHLIB_SUFFIX=".so"
@@ -1853,8 +1864,8 @@ dnl AC_CHECK_TOOL(AR, ar)
# requires an extra version number at the end of .so file names.
# So, the library has to have a name like libtcl75.so.1.0
- SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1.0'
- UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a'
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
TCL_LIB_VERSIONS_OK=nodots
;;
SunOS-5.[[0-6]])
@@ -1868,23 +1879,18 @@ dnl AC_CHECK_TOOL(AR, ar)
[Do we really want to follow the standard? Yes we do!])
SHLIB_CFLAGS="-KPIC"
-
- # Note: need the LIBS below, otherwise Tk won't find Tcl's
- # symbols when dynamically loaded into tclsh.
-
- SHLIB_LD_LIBS='${LIBS}'
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS="-ldl"
- if test "$GCC" = "yes" ; then
+ AS_IF([test "$GCC" = yes], [
SHLIB_LD='${CC} -shared'
CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- else
+ ], [
SHLIB_LD="/usr/ccs/bin/ld -G -z text"
CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- fi
+ ])
;;
SunOS-5*)
# Note: If _REENTRANT isn't defined, then Solaris
@@ -1897,32 +1903,32 @@ dnl AC_CHECK_TOOL(AR, ar)
SHLIB_CFLAGS="-KPIC"
# Check to enable 64-bit flags for compiler/linker
- if test "$do64bit" = "yes" ; then
+ AS_IF([test "$do64bit" = yes], [
arch=`isainfo`
- if test "$arch" = "sparcv9 sparc" ; then
- if test "$GCC" = "yes" ; then
- if test "`gcc -dumpversion | awk -F. '{print [$]1}'`" -lt "3" ; then
- AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system])
- else
- do64bit_ok=yes
- CFLAGS="$CFLAGS -m64 -mcpu=v9"
- LDFLAGS="$LDFLAGS -m64 -mcpu=v9"
- SHLIB_CFLAGS="-fPIC"
- fi
- else
+ AS_IF([test "$arch" = "sparcv9 sparc"], [
+ AS_IF([test "$GCC" = yes], [
+ AS_IF([test "`${CC} -dumpversion | awk -F. '{print [$]1}'`" -lt 3], [
+ AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system])
+ ], [
do64bit_ok=yes
- if test "$do64bitVIS" = "yes" ; then
- CFLAGS="$CFLAGS -xarch=v9a"
- LDFLAGS="$LDFLAGS -xarch=v9a"
- else
- CFLAGS="$CFLAGS -xarch=v9"
- LDFLAGS="$LDFLAGS -xarch=v9"
- fi
- # Solaris 64 uses this as well
- #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64"
- fi
- elif test "$arch" = "amd64 i386" ; then
- if test "$GCC" = "yes" ; then
+ CFLAGS="$CFLAGS -m64 -mcpu=v9"
+ LDFLAGS="$LDFLAGS -m64 -mcpu=v9"
+ SHLIB_CFLAGS="-fPIC"
+ ])
+ ], [
+ do64bit_ok=yes
+ AS_IF([test "$do64bitVIS" = yes], [
+ CFLAGS="$CFLAGS -xarch=v9a"
+ LDFLAGS_ARCH="-xarch=v9a"
+ ], [
+ CFLAGS="$CFLAGS -xarch=v9"
+ LDFLAGS_ARCH="-xarch=v9"
+ ])
+ # Solaris 64 uses this as well
+ #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64"
+ ])
+ ], [AS_IF([test "$arch" = "amd64 i386"], [
+ AS_IF([test "$GCC" = yes], [
case $system in
SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*)
do64bit_ok=yes
@@ -1931,7 +1937,7 @@ dnl AC_CHECK_TOOL(AR, ar)
*)
AC_MSG_WARN([64bit mode not supported with GCC on $system]);;
esac
- else
+ ], [
do64bit_ok=yes
case $system in
SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*)
@@ -1941,25 +1947,36 @@ dnl AC_CHECK_TOOL(AR, ar)
CFLAGS="$CFLAGS -xarch=amd64"
LDFLAGS="$LDFLAGS -xarch=amd64";;
esac
- fi
- else
- AC_MSG_WARN([64bit mode not supported for $arch])
- fi
- fi
-
- # Note: need the LIBS below, otherwise Tk won't find Tcl's
- # symbols when dynamically loaded into tclsh.
+ ])
+ ], [AC_MSG_WARN([64bit mode not supported for $arch])])])
+ ])
- SHLIB_LD_LIBS='${LIBS}'
+ #--------------------------------------------------------------------
+ # On Solaris 5.x i386 with the sunpro compiler we need to link
+ # with sunmath to get floating point rounding control
+ #--------------------------------------------------------------------
+ AS_IF([test "$GCC" = yes],[use_sunmath=no],[
+ arch=`isainfo`
+ AC_MSG_CHECKING([whether to use -lsunmath for fp rounding control])
+ AS_IF([test "$arch" = "amd64 i386"], [
+ AC_MSG_RESULT([yes])
+ MATH_LIBS="-lsunmath $MATH_LIBS"
+ AC_CHECK_HEADER(sunmath.h)
+ use_sunmath=yes
+ ], [
+ AC_MSG_RESULT([no])
+ use_sunmath=no
+ ])
+ ])
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS="-ldl"
- if test "$GCC" = "yes" ; then
- SHLIB_LD="$CC -shared"
+ AS_IF([test "$GCC" = yes], [
+ SHLIB_LD='${CC} -shared'
CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- if test "$do64bit_ok" = "yes" ; then
- if test "$arch" = "sparcv9 sparc" ; then
+ AS_IF([test "$do64bit_ok" = yes], [
+ AS_IF([test "$arch" = "sparcv9 sparc"], [
# We need to specify -static-libgcc or we need to
# add the path to the sparv9 libgcc.
SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc"
@@ -1967,38 +1984,25 @@ dnl AC_CHECK_TOOL(AR, ar)
# path, remove so name and append 'sparcv9'
#v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..."
#CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir"
- elif test "$arch" = "amd64 i386" ; then
+ ], [AS_IF([test "$arch" = "amd64 i386"], [
SHLIB_LD="$SHLIB_LD -m64 -static-libgcc"
- fi
- fi
- else
+ ])])
+ ])
+ ], [
+ AS_IF([test "$use_sunmath" = yes], [textmode=textoff],[textmode=text])
case $system in
SunOS-5.[[1-9]][[0-9]]*)
- SHLIB_LD='${CC} -G -z text ${LDFLAGS}';;
+ SHLIB_LD="\${CC} -G -z $textmode \${LDFLAGS}";;
*)
- SHLIB_LD="/usr/ccs/bin/ld -G -z text";;
+ SHLIB_LD="/usr/ccs/bin/ld -G -z $textmode";;
esac
CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
- fi
- ;;
- ULTRIX-4.*)
- SHLIB_CFLAGS="-G 0"
- SHLIB_SUFFIX=".a"
- SHLIB_LD="echo tclLdAout $CC \{$SHLIB_CFLAGS\} | `pwd`/tclsh -r -G 0"
- SHLIB_LD_LIBS='${LIBS}'
- DL_OBJS="tclLoadAout.o"
- DL_LIBS=""
- LDFLAGS="$LDFLAGS -Wl,-D,08000000"
- CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
- LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- if test "$GCC" != "yes" ; then
- CFLAGS="$CFLAGS -DHAVE_TZSET -std1"
- fi
+ ])
;;
UNIX_SV* | UnixWare-5*)
SHLIB_CFLAGS="-KPIC"
- SHLIB_LD="cc -G"
+ SHLIB_LD='${CC} -G'
SHLIB_LD_LIBS=""
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
@@ -2010,111 +2014,38 @@ dnl AC_CHECK_TOOL(AR, ar)
LDFLAGS="$LDFLAGS -Wl,-Bexport"
AC_TRY_LINK(, [int i;], tcl_cv_ld_Bexport=yes, tcl_cv_ld_Bexport=no)
LDFLAGS=$hold_ldflags])
- if test $tcl_cv_ld_Bexport = yes; then
+ AS_IF([test $tcl_cv_ld_Bexport = yes], [
LDFLAGS="$LDFLAGS -Wl,-Bexport"
- fi
+ ])
CC_SEARCH_FLAGS=""
LD_SEARCH_FLAGS=""
;;
esac
- if test "$do64bit" = "yes" -a "$do64bit_ok" = "no" ; then
+ AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = no], [
AC_MSG_WARN([64bit support being disabled -- don't know magic for this platform])
- fi
+ ])
+
+ AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = yes], [
+ AC_DEFINE(TCL_CFG_DO64BIT, 1, [Is this a 64-bit build?])
+ ])
dnl # Add any CPPFLAGS set in the environment to our CFLAGS, but delay doing so
dnl # until the end of configure, as configure's compile and link tests use
dnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's
dnl # preprocessing tests use only CPPFLAGS.
- SC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""])
-
- # Step 4: If pseudo-static linking is in use (see K. B. Kenny, "Dynamic
- # Loading for Tcl -- What Became of It?". Proc. 2nd Tcl/Tk Workshop,
- # New Orleans, LA, Computerized Processes Unlimited, 1994), then we need
- # to determine which of several header files defines the a.out file
- # format (a.out.h, sys/exec.h, or sys/exec_aout.h). At present, we
- # support only a file format that is more or less version-7-compatible.
- # In particular,
- # - a.out files must begin with `struct exec'.
- # - the N_TXTOFF on the `struct exec' must compute the seek address
- # of the text segment
- # - The `struct exec' must contain a_magic, a_text, a_data, a_bss
- # and a_entry fields.
- # The following compilation should succeed if and only if either sys/exec.h
- # or a.out.h is usable for the purpose.
- #
- # Note that the modified COFF format used on MIPS Ultrix 4.x is usable; the
- # `struct exec' includes a second header that contains information that
- # duplicates the v7 fields that are needed.
-
- if test "x$DL_OBJS" = "xtclLoadAout.o" ; then
- AC_CACHE_CHECK([sys/exec.h], tcl_cv_sysexec_h, [
- AC_TRY_COMPILE([#include <sys/exec.h>],[
- struct exec foo;
- unsigned long seek;
- int flag;
-#if defined(__mips) || defined(mips)
- seek = N_TXTOFF (foo.ex_f, foo.ex_o);
-#else
- seek = N_TXTOFF (foo);
-#endif
- flag = (foo.a_magic == OMAGIC);
- return foo.a_text + foo.a_data + foo.a_bss + foo.a_entry;
- ], tcl_cv_sysexec_h=usable, tcl_cv_sysexec_h=unusable)])
- if test $tcl_cv_sysexec_h = usable; then
- AC_DEFINE(USE_SYS_EXEC_H)
- else
- AC_CACHE_CHECK([a.out.h], tcl_cv_aout_h, [
- AC_TRY_COMPILE([#include <a.out.h>],[
- struct exec foo;
- unsigned long seek;
- int flag;
-#if defined(__mips) || defined(mips)
- seek = N_TXTOFF (foo.ex_f, foo.ex_o);
-#else
- seek = N_TXTOFF (foo);
-#endif
- flag = (foo.a_magic == OMAGIC);
- return foo.a_text + foo.a_data + foo.a_bss + foo.a_entry;
- ], tcl_cv_aout_h=usable, tcl_cv_aout_h=unusable)])
- if test $tcl_cv_aout_h = usable; then
- AC_DEFINE(USE_A_OUT_H)
- else
- AC_CACHE_CHECK([sys/exec_aout.h], tcl_cv_sysexecaout_h, [
- AC_TRY_COMPILE([#include <sys/exec_aout.h>],[
- struct exec foo;
- unsigned long seek;
- int flag;
-#if defined(__mips) || defined(mips)
- seek = N_TXTOFF (foo.ex_f, foo.ex_o);
-#else
- seek = N_TXTOFF (foo);
-#endif
- flag = (foo.a_midmag == OMAGIC);
- return foo.a_text + foo.a_data + foo.a_bss + foo.a_entry;
- ], tcl_cv_sysexecaout_h=usable, tcl_cv_sysexecaout_h=unusable)])
- if test $tcl_cv_sysexecaout_h = usable; then
- AC_DEFINE(USE_SYS_EXEC_AOUT_H)
- else
- DL_OBJS=""
- fi
- fi
- fi
- fi
+ AC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""])
- # Step 5: disable dynamic loading if requested via a command-line switch.
+ # Step 4: disable dynamic loading if requested via a command-line switch.
- AC_ARG_ENABLE(load, [ --disable-load disallow dynamic loading and "load" command],
+ AC_ARG_ENABLE(load,
+ AC_HELP_STRING([--enable-load],
+ [allow dynamic loading and "load" command (default: on)]),
[tcl_ok=$enableval], [tcl_ok=yes])
- if test "$tcl_ok" = "no"; then
- DL_OBJS=""
- fi
+ AS_IF([test "$tcl_ok" = no], [DL_OBJS=""])
- if test "x$DL_OBJS" != "x" ; then
- BUILD_DLTEST="\$(DLTEST_TARGETS)"
- else
- echo "Can't figure out how to do dynamic loading or shared libraries"
- echo "on this system."
+ AS_IF([test "x$DL_OBJS" != x], [BUILD_DLTEST="\$(DLTEST_TARGETS)"], [
+ AC_MSG_WARN([Can't figure out how to do dynamic loading or shared libraries on this system.])
SHLIB_CFLAGS=""
SHLIB_LD=""
SHLIB_SUFFIX=""
@@ -2124,91 +2055,71 @@ dnl # preprocessing tests use only CPPFLAGS.
CC_SEARCH_FLAGS=""
LD_SEARCH_FLAGS=""
BUILD_DLTEST=""
- fi
+ ])
+ LDFLAGS="$LDFLAGS $LDFLAGS_ARCH"
# If we're running gcc, then change the C flags for compiling shared
# libraries to the right flags for gcc, instead of those for the
# standard manufacturer compiler.
- if test "$DL_OBJS" != "tclLoadNone.o" ; then
- if test "$GCC" = "yes" ; then
- case $system in
- AIX-*)
- ;;
- BSD/OS*)
- ;;
- IRIX*)
- ;;
- NetBSD-*|FreeBSD-*|OpenBSD-*)
- ;;
- Darwin-*)
- ;;
- RISCos-*)
- ;;
- SCO_SV-3.2*)
- ;;
- ULTRIX-4.*)
- ;;
- *)
- SHLIB_CFLAGS="-fPIC"
- ;;
- esac
- fi
- fi
-
- if test "$SHARED_LIB_SUFFIX" = "" ; then
- SHARED_LIB_SUFFIX='${VERSION}\$\{DBGX\}${SHLIB_SUFFIX}'
- fi
- if test "$UNSHARED_LIB_SUFFIX" = "" ; then
- UNSHARED_LIB_SUFFIX='${VERSION}\$\{DBGX\}.a'
- fi
-
- if test "${SHARED_BUILD}" = "1" && test "${SHLIB_SUFFIX}" != "" ; then
+ AS_IF([test "$DL_OBJS" != "tclLoadNone.o" -a "$GCC" = yes], [
+ case $system in
+ AIX-*) ;;
+ BSD/OS*) ;;
+ CYGWIN_*) ;;
+ IRIX*) ;;
+ NetBSD-*|FreeBSD-*|OpenBSD-*) ;;
+ Darwin-*) ;;
+ SCO_SV-3.2*) ;;
+ *) SHLIB_CFLAGS="-fPIC" ;;
+ esac])
+
+ AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [
+ SHARED_LIB_SUFFIX='${VERSION}${SHLIB_SUFFIX}'])
+ AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [
+ UNSHARED_LIB_SUFFIX='${VERSION}.a'])
+
+ AS_IF([test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""], [
LIB_SUFFIX=${SHARED_LIB_SUFFIX}
MAKE_LIB='${SHLIB_LD} -o [$]@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'
- INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) $(LIB_INSTALL_DIR)/$(LIB_FILE)'
- else
+ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)"/$(LIB_FILE)'
+ ], [
LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}
- if test "$RANLIB" = "" ; then
+ AS_IF([test "$RANLIB" = ""], [
MAKE_LIB='$(STLIB_LD) [$]@ ${OBJS}'
- INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) $(LIB_INSTALL_DIR)/$(LIB_FILE)'
- else
+ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)"/$(LIB_FILE)'
+ ], [
MAKE_LIB='${STLIB_LD} [$]@ ${OBJS} ; ${RANLIB} [$]@'
- INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) $(LIB_INSTALL_DIR)/$(LIB_FILE) ; (cd $(LIB_INSTALL_DIR) ; $(RANLIB) $(LIB_FILE))'
- fi
-
-dnl Not at all clear what this was doing in Tcl's configure.in
-dnl or why it was needed was needed. In any event, this sort of
-dnl things needs to be done in the big loop above.
-dnl REMOVE THIS BLOCK LATER! (mdejong)
-dnl case $system in
-dnl BSD/OS*)
-dnl ;;
-dnl AIX-[[1-4]].*)
-dnl ;;
-dnl *)
-dnl SHLIB_LD_LIBS=""
-dnl ;;
-dnl esac
- fi
-
+ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)"/$(LIB_FILE) ; (cd "$(LIB_INSTALL_DIR)" ; $(RANLIB) $(LIB_FILE))'
+ ])
+ ])
# Stub lib does not depend on shared/static configuration
- if test "$RANLIB" = "" ; then
+ AS_IF([test "$RANLIB" = ""], [
MAKE_STUB_LIB='${STLIB_LD} [$]@ ${STUB_LIB_OBJS}'
- INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) $(LIB_INSTALL_DIR)/$(STUB_LIB_FILE)'
- else
+ INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) "$(LIB_INSTALL_DIR)/$(STUB_LIB_FILE)"'
+ ], [
MAKE_STUB_LIB='${STLIB_LD} [$]@ ${STUB_LIB_OBJS} ; ${RANLIB} [$]@'
- INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) $(LIB_INSTALL_DIR)/$(STUB_LIB_FILE) ; (cd $(LIB_INSTALL_DIR) ; $(RANLIB) $(STUB_LIB_FILE))'
- fi
+ INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) "$(LIB_INSTALL_DIR)"/$(STUB_LIB_FILE) ; (cd "$(LIB_INSTALL_DIR)" ; $(RANLIB) $(STUB_LIB_FILE))'
+ ])
+ # Define TCL_LIBS now that we know what DL_LIBS is.
+ # The trick here is that we don't want to change the value of TCL_LIBS if
+ # it is already set when tclConfig.sh had been loaded by Tk.
+ AS_IF([test "x${TCL_LIBS}" = x], [
+ TCL_LIBS="${DL_LIBS} ${LIBS} ${MATH_LIBS}"])
+ AC_SUBST(TCL_LIBS)
+ # FIXME: This subst was left in only because the TCL_DL_LIBS
+ # entry in tclConfig.sh uses it. It is not clear why someone
+ # would use TCL_DL_LIBS instead of TCL_LIBS.
AC_SUBST(DL_LIBS)
AC_SUBST(DL_OBJS)
AC_SUBST(PLAT_OBJS)
AC_SUBST(PLAT_SRCS)
+ AC_SUBST(LDAIX_SRC)
AC_SUBST(CFLAGS)
AC_SUBST(CFLAGS_DEBUG)
AC_SUBST(CFLAGS_OPTIMIZE)
@@ -2227,6 +2138,8 @@ dnl esac
AC_SUBST(SHLIB_LD_LIBS)
AC_SUBST(SHLIB_CFLAGS)
AC_SUBST(SHLIB_SUFFIX)
+ AC_DEFINE_UNQUOTED(TCL_SHLIB_EXT,"${SHLIB_SUFFIX}",
+ [What is the default extension for shared libraries?])
AC_SUBST(MAKE_LIB)
AC_SUBST(MAKE_STUB_LIB)
@@ -2370,14 +2283,12 @@ int main() {
#
# Defines some of the following vars:
# NO_DIRENT_H
-# NO_ERRNO_H
# NO_VALUES_H
# HAVE_LIMITS_H or NO_LIMITS_H
# NO_STDLIB_H
# NO_STRING_H
# NO_SYS_WAIT_H
# NO_DLFCN_H
-# HAVE_UNISTD_H
# HAVE_SYS_PARAM_H
#
# HAVE_STRING_H ?
@@ -2411,7 +2322,6 @@ closedir(d);
AC_DEFINE(NO_DIRENT_H, 1, [Do we have <dirent.h>?])
fi
- AC_CHECK_HEADER(errno.h, , [AC_DEFINE(NO_ERRNO_H, 1, [Do we have <errno.h>?])])
AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have <float.h>?])])
AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have <values.h>?])])
AC_CHECK_HEADER(limits.h,
@@ -2439,7 +2349,7 @@ closedir(d);
AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have <dlfcn.h>?])])
# OS/390 lacks sys/param.h (and doesn't need it, by chance).
- AC_HAVE_HEADERS(unistd.h sys/param.h)
+ AC_HAVE_HEADERS(sys/param.h)
])
#--------------------------------------------------------------------
@@ -2568,10 +2478,6 @@ AC_DEFUN([SC_BLOCKING_STYLE], [
AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?])
AC_MSG_RESULT([FIONBIO])
;;
- ULTRIX-4.*)
- AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?])
- AC_MSG_RESULT([FIONBIO])
- ;;
*)
AC_MSG_RESULT([O_NONBLOCK])
;;
@@ -2600,9 +2506,8 @@ AC_DEFUN([SC_BLOCKING_STYLE], [
AC_DEFUN([SC_TIME_HANDLER], [
AC_CHECK_HEADERS(sys/time.h)
AC_HEADER_TIME
- AC_STRUCT_TIMEZONE
- AC_CHECK_FUNCS(gmtime_r localtime_r)
+ AC_CHECK_FUNCS(gmtime_r localtime_r mktime)
AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [
AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_tzadj;],
@@ -2692,7 +2597,8 @@ AC_DEFUN([SC_BUGGY_STRTOD], [
}], tcl_cv_strtod_buggy=ok, tcl_cv_strtod_buggy=buggy,
tcl_cv_strtod_buggy=buggy)])
if test "$tcl_cv_strtod_buggy" = buggy; then
- LIBOBJS="$LIBOBJS fixstrtod.o"
+ AC_LIBOBJ([fixstrtod])
+ USE_COMPAT=1
AC_DEFINE(strtod, fixstrtod, [Do we want to use the strtod() in compat?])
fi
fi
@@ -2706,19 +2612,13 @@ AC_DEFUN([SC_BUGGY_STRTOD], [
# -lnsl) are dealt with here.
#
# Arguments:
-# Requires the following vars to be set in the Makefile:
-# DL_LIBS
-# LIBS
-# MATH_LIBS
+# None.
#
# Results:
#
-# Subst's the following var:
-# TCL_LIBS
-# MATH_LIBS
-#
# Might append to the following vars:
# LIBS
+# MATH_LIBS
#
# Might define the following vars:
# HAVE_NET_ERRNO_H
@@ -2776,13 +2676,6 @@ AC_DEFUN([SC_TCL_LINK_LIBS], [
fi
AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname,
[LIBS="$LIBS -lnsl"])])
-
- # Don't perform the eval of the libraries here because DL_LIBS
- # won't be set until we call SC_CONFIG_CFLAGS
-
- TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}'
- AC_SUBST(TCL_LIBS)
- AC_SUBST(MATH_LIBS)
])
#--------------------------------------------------------------------
@@ -2909,6 +2802,72 @@ AC_DEFUN([SC_TCL_64BIT_FLAGS], [
])
#--------------------------------------------------------------------
+# SC_TCL_CFG_ENCODING TIP #59
+#
+# Declare the encoding to use for embedded configuration information.
+#
+# Arguments:
+# None.
+#
+# Results:
+# Might append to the following vars:
+# DEFS (implicit)
+#
+# Will define the following vars:
+# TCL_CFGVAL_ENCODING
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_CFG_ENCODING], [
+ AC_ARG_WITH(encoding,
+ AC_HELP_STRING([--with-encoding],
+ [encoding for configuration values (default: iso8859-1)]),
+ with_tcencoding=${withval})
+
+ if test x"${with_tcencoding}" != x ; then
+ AC_DEFINE_UNQUOTED(TCL_CFGVAL_ENCODING,"${with_tcencoding}",
+ [What encoding should be used for embedded configuration info?])
+ else
+ AC_DEFINE(TCL_CFGVAL_ENCODING,"iso8859-1",
+ [What encoding should be used for embedded configuration info?])
+ fi
+])
+
+#--------------------------------------------------------------------
+# SC_TCL_CHECK_BROKEN_FUNC
+#
+# Check for broken function.
+#
+# Arguments:
+# funcName - function to test for
+# advancedTest - the advanced test to run if the function is present
+#
+# Results:
+# Might cause compatability versions of the function to be used.
+# Might affect the following vars:
+# USE_COMPAT (implicit)
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_CHECK_BROKEN_FUNC],[
+ AC_CHECK_FUNC($1, tcl_ok=1, tcl_ok=0)
+ if test ["$tcl_ok"] = 1; then
+ AC_CACHE_CHECK([proper ]$1[ implementation], [tcl_cv_]$1[_unbroken],
+ AC_TRY_RUN([[int main() {]$2[}]],[tcl_cv_]$1[_unbroken]=ok,
+ [tcl_cv_]$1[_unbroken]=broken,[tcl_cv_]$1[_unbroken]=unknown))
+ if test ["$tcl_cv_]$1[_unbroken"] = "ok"; then
+ tcl_ok=1
+ else
+ tcl_ok=0
+ fi
+ fi
+ if test ["$tcl_ok"] = 0; then
+ AC_LIBOBJ($1)
+ USE_COMPAT=1
+ fi
+])
+
+#--------------------------------------------------------------------
# SC_TCL_GETHOSTBYADDR_R
#
# Check if we have MT-safe variant of gethostbyaddr().
@@ -3052,6 +3011,37 @@ AC_DEFUN([SC_TCL_GETHOSTBYNAME_R], [AC_CHECK_FUNC(gethostbyname_r, [
])])
#--------------------------------------------------------------------
+# SC_TCL_GETADDRINFO
+#
+# Check if we have 'getaddrinfo'
+#
+# Arguments:
+# None
+#
+# Results:
+# Might define the following vars:
+# HAVE_GETADDRINFO
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_GETADDRINFO], [AC_CHECK_FUNC(getaddrinfo, [
+ AC_CACHE_CHECK([for working getaddrinfo], tcl_cv_api_getaddrinfo, [
+ AC_TRY_COMPILE([
+ #include <netdb.h>
+ ], [
+ const char *name, *port;
+ struct addrinfo *aiPtr, hints;
+ (void)getaddrinfo(name,port, &hints, &aiPtr);
+ (void)freeaddrinfo(aiPtr);
+ ], tcl_cv_api_getaddrinfo=yes, tcl_cv_getaddrinfo=no)])
+ tcl_ok=$tcl_cv_api_getaddrinfo
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETADDRINFO, 1,
+ [Define to 1 if getaddrinfo is available.])
+ fi
+])])
+
+#--------------------------------------------------------------------
# SC_TCL_GETPWUID_R
#
# Check if we have MT-safe variant of getpwuid() and if yes,
@@ -3291,22 +3281,6 @@ AC_DEFUN([SC_TCL_GETGRNAM_R], [AC_CHECK_FUNC(getgrnam_r, [
fi
])])
-#--------------------------------------------------------------------
-# SC_CONFIG_COMMANDS_PRE(CMDS)
-#
-# Replacement for autoconf 2.5x AC_COMMANDS_PRE:
-# Commands to run right before config.status is
-# created. Accumulates.
-#
-# Requires presence of SC_OUTPUT_COMMANDS_PRE at the end
-# of configure.in (right before AC_OUTPUT).
-#
-#--------------------------------------------------------------------
-
-AC_DEFUN([SC_CONFIG_COMMANDS_PRE], [
- define([SC_OUTPUT_COMMANDS_PRE], defn([SC_OUTPUT_COMMANDS_PRE])[$1
-])])
-AC_DEFUN([SC_OUTPUT_COMMANDS_PRE])
# Local Variables:
# mode: autoconf
# End:
diff --git a/unix/tcl.spec b/unix/tcl.spec
index 33cfe56..7729960 100644
--- a/unix/tcl.spec
+++ b/unix/tcl.spec
@@ -1,49 +1,49 @@
# This file is the basis for a binary Tcl RPM for Linux.
-%define version 8.4.19
-%define directory /usr/local
-
-Summary: Tcl scripting language development environment
-Name: tcl
-Version: %{version}
-Release: 1
-Copyright: BSD
-Group: Development/Languages
-Source: http://prdownloads.sourceforge.net/tcl/tcl%{version}-src.tar.gz
-URL: http://www.tcl.tk/
-Packager: Carina
-Buildroot: /var/tmp/%{name}%{version}
+%{!?directory:%define directory /usr/local}
+
+Name: tcl
+Summary: Tcl scripting language development environment
+Version: 8.5.10
+Release: 2
+License: BSD
+Group: Development/Languages
+Source: http://prdownloads.sourceforge.net/tcl/tcl%{version}-src.tar.gz
+URL: http://www.tcl.tk/
+Buildroot: /var/tmp/%{name}%{version}
%description
The Tcl (Tool Command Language) provides a powerful platform for
creating integration applications that tie together diverse
applications, protocols, devices, and frameworks. When paired with
the Tk toolkit, Tcl provides the fastest and most powerful way to
-create GUI applications that run on PCs, Unix, and the Macintosh. Tcl
+create GUI applications that run on PCs, Unix, and Mac OS X. Tcl
can also be used for a variety of web-related tasks and for creating
powerful command languages for applications.
%prep
+%setup -q -n %{name}%{version}
%build
-./configure --prefix %{directory} --exec-prefix %{directory}
-make CFLAGS=$RPM_OPT_FLAGS
+cd unix
+CFLAGS="%optflags" ./configure \
+ --prefix=%{directory} \
+ --exec-prefix=%{directory} \
+ --libdir=%{directory}/%{_lib}
+make
%install
-rm -rf $RPM_BUILD_ROOT
-make INSTALL_ROOT=$RPM_BUILD_ROOT install
+cd unix
+make INSTALL_ROOT=%{buildroot} install
%clean
-rm -rf $RPM_BUILD_ROOT
-
-# to create the tcl files list, comment out tk in the install section above,
-# then run "rpm -bi" then do a find from the build root directory,
-# and remove the files in specific directories which suffice by themselves,
-# then to create the files list for tk, uncomment tk, comment out tcl,
-# then rm -rf $RPM_BUILD_ROOT then rpm --short-circuit -bi then redo a find,
-# and remove the files in specific directories which suffice by themselves.
+rm -rf %buildroot
+
%files
%defattr(-,root,root)
+%if %{_lib} != lib
+%{directory}/%{_lib}
+%endif
%{directory}/lib
%{directory}/bin
%{directory}/include
diff --git a/unix/tclAppInit.c b/unix/tclAppInit.c
index 22b9b32..b9c64b1 100644
--- a/unix/tclAppInit.c
+++ b/unix/tclAppInit.c
@@ -1,15 +1,15 @@
-/*
+/*
* tclAppInit.c --
*
* Provides a default version of the main program and Tcl_AppInit
- * procedure for Tcl applications (without Tk).
+ * function 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.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tcl.h"
@@ -18,13 +18,10 @@
#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
+extern Tcl_PackageInitProc Procbodytest_Init;
+extern Tcl_PackageInitProc Procbodytest_SafeInit;
+extern Tcl_PackageInitProc TclObjTest_Init;
+extern Tcl_PackageInitProc Tcltest_Init;
#endif /* TCL_TEST */
@@ -41,8 +38,8 @@ extern int Tclxttest_Init _ANSI_ARGS_((Tcl_Interp *interp));
* This is the main program for the application.
*
* Results:
- * None: Tcl_Main never returns here, so this procedure never
- * returns either.
+ * None: Tcl_Main never returns here, so this function never returns
+ * either.
*
* Side effects:
* Whatever the application does.
@@ -51,19 +48,19 @@ extern int Tclxttest_Init _ANSI_ARGS_((Tcl_Interp *interp));
*/
int
-main(argc, argv)
- int argc; /* Number of command-line arguments. */
- char **argv; /* Values of command-line arguments. */
+main(
+ 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.
+ * 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 does
+ * not exist.
*/
#ifndef TCL_LOCAL_APPINIT
-#define TCL_LOCAL_APPINIT Tcl_AppInit
+#define TCL_LOCAL_APPINIT Tcl_AppInit
#endif
extern int TCL_LOCAL_APPINIT _ANSI_ARGS_((Tcl_Interp *interp));
@@ -95,13 +92,13 @@ main(argc, argv)
*
* Tcl_AppInit --
*
- * This procedure performs application-specific initialization.
- * Most applications, especially those that incorporate additional
- * packages, will have their own version of this procedure.
+ * This function performs application-specific initialization. Most
+ * applications, especially those that incorporate additional packages,
+ * will have their own version of this function.
*
* Results:
- * Returns a standard Tcl completion code, and leaves an error
- * message in the interp's result if an error occurs.
+ * 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.
@@ -110,8 +107,8 @@ main(argc, argv)
*/
int
-Tcl_AppInit(interp)
- Tcl_Interp *interp; /* Interpreter for application. */
+Tcl_AppInit(
+ Tcl_Interp *interp) /* Interpreter for application. */
{
if (Tcl_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
@@ -119,51 +116,47 @@ Tcl_AppInit(interp)
#ifdef TCL_TEST
#ifdef TCL_XT_TEST
- if (Tclxttest_Init(interp) == TCL_ERROR) {
- return TCL_ERROR;
- }
+ 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);
+ (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);
+ Procbodytest_SafeInit);
#endif /* TCL_TEST */
/*
- * Call the init procedures for included packages. Each call should
- * look like this:
+ * Call the init functions 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.
+ * where "Mod" is the name of the module. (Dynamically-loadable packages
+ * should have the same entry-point name.)
*/
/*
- * Call Tcl_CreateCommand for application-specific commands, if
- * they weren't already created by the init procedures called above.
+ * Call Tcl_CreateCommand for application-specific commands, if they
+ * weren't already created by the init functions 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.
+ * 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
@@ -171,5 +164,14 @@ Tcl_AppInit(interp)
#else
Tcl_SetVar(interp, "tcl_rcFileName", "~/.tclshrc", TCL_GLOBAL_ONLY);
#endif
+
return TCL_OK;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclConfig.h.in b/unix/tclConfig.h.in
new file mode 100644
index 0000000..8bede7e
--- /dev/null
+++ b/unix/tclConfig.h.in
@@ -0,0 +1,505 @@
+/* ../unix/tclConfig.h.in. Generated from configure.ac by autoheader. */
+
+
+ #ifndef _TCLCONFIG
+ #define _TCLCONFIG
+
+/* Is pthread_attr_get_np() declared in <pthread.h>? */
+#undef ATTRGETNP_NOT_DECLARED
+
+/* Is pthread_getattr_np declared in <pthread.h>? */
+#undef GETATTRNP_NOT_DECLARED
+
+/* Is gettimeofday() actually declared in <sys/time.h>? */
+#undef GETTOD_NOT_DECLARED
+
+/* Define to 1 if you have the <AvailabilityMacros.h> header file. */
+#undef HAVE_AVAILABILITYMACROS_H
+
+/* Define to 1 if the system has the type `blkcnt_t'. */
+#undef HAVE_BLKCNT_T
+
+/* Do we have BSDgettimeofday()? */
+#undef HAVE_BSDGETTIMEOFDAY
+
+/* Define to 1 if you have the `chflags' function. */
+#undef HAVE_CHFLAGS
+
+/* Define to 1 if you have the `copyfile' function. */
+#undef HAVE_COPYFILE
+
+/* Define to 1 if you have the <copyfile.h> header file. */
+#undef HAVE_COPYFILE_H
+
+/* Do we have access to Darwin CoreFoundation.framework? */
+#undef HAVE_COREFOUNDATION
+
+/* Do we have fts functions? */
+#undef HAVE_FTS
+
+/* Define to 1 if getaddrinfo is available. */
+#undef HAVE_GETADDRINFO
+
+/* Define to 1 if you have the `getattrlist' function. */
+#undef HAVE_GETATTRLIST
+
+/* Define to 1 if you have the `getcwd' function. */
+#undef HAVE_GETCWD
+
+/* Define to 1 if getgrgid_r is available. */
+#undef HAVE_GETGRGID_R
+
+/* Define to 1 if getgrgid_r takes 4 args. */
+#undef HAVE_GETGRGID_R_4
+
+/* Define to 1 if getgrgid_r takes 5 args. */
+#undef HAVE_GETGRGID_R_5
+
+/* Define to 1 if getgrnam_r is available. */
+#undef HAVE_GETGRNAM_R
+
+/* Define to 1 if getgrnam_r takes 4 args. */
+#undef HAVE_GETGRNAM_R_4
+
+/* Define to 1 if getgrnam_r takes 5 args. */
+#undef HAVE_GETGRNAM_R_5
+
+/* Define to 1 if gethostbyaddr_r is available. */
+#undef HAVE_GETHOSTBYADDR_R
+
+/* Define to 1 if gethostbyaddr_r takes 7 args. */
+#undef HAVE_GETHOSTBYADDR_R_7
+
+/* Define to 1 if gethostbyaddr_r takes 8 args. */
+#undef HAVE_GETHOSTBYADDR_R_8
+
+/* Define to 1 if gethostbyname_r is available. */
+#undef HAVE_GETHOSTBYNAME_R
+
+/* Define to 1 if gethostbyname_r takes 3 args. */
+#undef HAVE_GETHOSTBYNAME_R_3
+
+/* Define to 1 if gethostbyname_r takes 5 args. */
+#undef HAVE_GETHOSTBYNAME_R_5
+
+/* Define to 1 if gethostbyname_r takes 6 args. */
+#undef HAVE_GETHOSTBYNAME_R_6
+
+/* Define to 1 if getpwnam_r is available. */
+#undef HAVE_GETPWNAM_R
+
+/* Define to 1 if getpwnam_r takes 4 args. */
+#undef HAVE_GETPWNAM_R_4
+
+/* Define to 1 if getpwnam_r takes 5 args. */
+#undef HAVE_GETPWNAM_R_5
+
+/* Define to 1 if getpwuid_r is available. */
+#undef HAVE_GETPWUID_R
+
+/* Define to 1 if getpwuid_r takes 4 args. */
+#undef HAVE_GETPWUID_R_4
+
+/* Define to 1 if getpwuid_r takes 5 args. */
+#undef HAVE_GETPWUID_R_5
+
+/* Define to 1 if you have the `gmtime_r' function. */
+#undef HAVE_GMTIME_R
+
+/* Do we have the intptr_t type? */
+#undef HAVE_INTPTR_T
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Do we have nl_langinfo()? */
+#undef HAVE_LANGINFO
+
+/* Define to 1 if you have the <libkern/OSAtomic.h> header file. */
+#undef HAVE_LIBKERN_OSATOMIC_H
+
+/* Do we have <limits.h>? */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the `localtime_r' function. */
+#undef HAVE_LOCALTIME_R
+
+/* Define to 1 if you have the `lseek64' function. */
+#undef HAVE_LSEEK64
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `mktime' function. */
+#undef HAVE_MKTIME
+
+/* Do we have MT-safe gethostbyaddr() ? */
+#undef HAVE_MTSAFE_GETHOSTBYADDR
+
+/* Do we have MT-safe gethostbyname() ? */
+#undef HAVE_MTSAFE_GETHOSTBYNAME
+
+/* Do we have <net/errno.h>? */
+#undef HAVE_NET_ERRNO_H
+
+/* Define to 1 if you have the `open64' function. */
+#undef HAVE_OPEN64
+
+/* Define to 1 if you have the `opendir' function. */
+#undef HAVE_OPENDIR
+
+/* Define to 1 if you have the `OSSpinLockLock' function. */
+#undef HAVE_OSSPINLOCKLOCK
+
+/* Define to 1 if you have the `pthread_atfork' function. */
+#undef HAVE_PTHREAD_ATFORK
+
+/* Do we want a BSD-like thread-attribute interface? */
+#undef HAVE_PTHREAD_ATTR_GET_NP
+
+/* Define to 1 if you have the `pthread_attr_setstacksize' function. */
+#undef HAVE_PTHREAD_ATTR_SETSTACKSIZE
+
+/* Do we want a Linux-like thread-attribute interface? */
+#undef HAVE_PTHREAD_GETATTR_NP
+
+/* Define to 1 if you have the `pthread_get_stacksize_np' function. */
+#undef HAVE_PTHREAD_GET_STACKSIZE_NP
+
+/* Does putenv() copy strings or incorporate them by reference? */
+#undef HAVE_PUTENV_THAT_COPIES
+
+/* Are characters signed? */
+#undef HAVE_SIGNED_CHAR
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strtol' function. */
+#undef HAVE_STRTOL
+
+/* Is 'struct dirent64' in <sys/types.h>? */
+#undef HAVE_STRUCT_DIRENT64
+
+/* Is 'struct stat64' in <sys/stat.h>? */
+#undef HAVE_STRUCT_STAT64
+
+/* Define to 1 if `st_blksize' is member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_BLKSIZE
+
+/* Define to 1 if `st_blocks' is member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_BLOCKS
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+#undef HAVE_SYS_FILIO_H
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define to 1 if you have the <sys/modem.h> header file. */
+#undef HAVE_SYS_MODEM_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Should we include <sys/select.h>? */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Should we use the global timezone variable? */
+#undef HAVE_TIMEZONE_VAR
+
+/* Should we use the tm_gmtoff field of struct tm? */
+#undef HAVE_TM_GMTOFF
+
+/* Should we use the tm_tzadj field of struct tm? */
+#undef HAVE_TM_TZADJ
+
+/* Is off64_t in <sys/types.h>? */
+#undef HAVE_TYPE_OFF64_T
+
+/* Do we have the uintptr_t type? */
+#undef HAVE_UINTPTR_T
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `waitpid' function. */
+#undef HAVE_WAITPID
+
+/* Is weak import available? */
+#undef HAVE_WEAK_IMPORT
+
+/* Is this a Mac I see before me? */
+#undef MAC_OSX_TCL
+
+/* Compiler support for module scope symbols */
+#undef MODULE_SCOPE
+
+/* Default libtommath precision. */
+#undef MP_PREC
+
+/* Is Darwin CoreFoundation unavailable for 64-bit? */
+#undef NO_COREFOUNDATION_64
+
+/* Do we have <dirent.h>? */
+#undef NO_DIRENT_H
+
+/* Do we have <dlfcn.h>? */
+#undef NO_DLFCN_H
+
+/* Do we have fd_set? */
+#undef NO_FD_SET
+
+/* Do we have <float.h>? */
+#undef NO_FLOAT_H
+
+/* Do we have fstatfs()? */
+#undef NO_FSTATFS
+
+/* Do we have gettimeofday()? */
+#undef NO_GETTOD
+
+/* Do we have getwd() */
+#undef NO_GETWD
+
+/* Do we have a usable 'isnan'? */
+#undef NO_ISNAN
+
+/* Do we have <limits.h>? */
+#undef NO_LIMITS_H
+
+/* Do we have memmove()? */
+#undef NO_MEMMOVE
+
+/* Do we have realpath() */
+#undef NO_REALPATH
+
+/* Do we have <stdlib.h>? */
+#undef NO_STDLIB_H
+
+/* Do we have strerror() */
+#undef NO_STRERROR
+
+/* Do we have <string.h>? */
+#undef NO_STRING_H
+
+/* Do we have <sys/wait.h>? */
+#undef NO_SYS_WAIT_H
+
+/* Do we have uname() */
+#undef NO_UNAME
+
+/* Do we have a usable 'union wait'? */
+#undef NO_UNION_WAIT
+
+/* Do we have <values.h>? */
+#undef NO_VALUES_H
+
+/* Do we have wait3() */
+#undef NO_WAIT3
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Is this a static build? */
+#undef STATIC_BUILD
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* What encoding should be used for embedded configuration info? */
+#undef TCL_CFGVAL_ENCODING
+
+/* Is debugging enabled? */
+#undef TCL_CFG_DEBUG
+
+/* Is this a 64-bit build? */
+#undef TCL_CFG_DO64BIT
+
+/* Is this an optimized build? */
+#undef TCL_CFG_OPTIMIZED
+
+/* Is bytecode debugging enabled? */
+#undef TCL_COMPILE_DEBUG
+
+/* Are bytecode statistics enabled? */
+#undef TCL_COMPILE_STATS
+
+/* Are we cross-compiling? */
+#undef TCL_CROSS_COMPILE
+
+/* Are we to override what our default encoding is? */
+#undef TCL_DEFAULT_ENCODING
+
+/* Is Tcl built as a framework? */
+#undef TCL_FRAMEWORK
+
+/* Can this platform load code from memory? */
+#undef TCL_LOAD_FROM_MEMORY
+
+/* Is memory debugging enabled? */
+#undef TCL_MEM_DEBUG
+
+/* What is the default extension for shared libraries? */
+#undef TCL_SHLIB_EXT
+
+/* The C stack grows upwards in memory. */
+#undef TCL_STACK_GROWS_UP
+
+/* Are we building with threads enabled? */
+#undef TCL_THREADS
+
+/* Build libtommath? */
+#undef TCL_TOMMATH
+
+/* Do we allow unloading of shared libraries? */
+#undef TCL_UNLOAD_DLLS
+
+/* Does this platform have wide high-resolution clicks? */
+#undef TCL_WIDE_CLICKS
+
+/* Are wide integers to be implemented with C 'long's? */
+#undef TCL_WIDE_INT_IS_LONG
+
+/* What type should be used to define wide integers? */
+#undef TCL_WIDE_INT_TYPE
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Is getcwd Posix-compliant? */
+#undef USEGETWD
+
+/* May we include <dirent2.h>? */
+#undef USE_DIRENT2_H
+
+/* Are we building with DTrace support? */
+#undef USE_DTRACE
+
+/* Should we use FIONBIO? */
+#undef USE_FIONBIO
+
+/* Use the sgtty API for serial lines */
+#undef USE_SGTTY
+
+/* Use the termio API for serial lines */
+#undef USE_TERMIO
+
+/* Use the termios API for serial lines */
+#undef USE_TERMIOS
+
+/* Do we want to use the threaded memory allocator? */
+#undef USE_THREAD_ALLOC
+
+/* Should we use vfork() instead of fork()? */
+#undef USE_VFORK
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
+
+/* Are Darwin SUSv3 extensions available? */
+#undef _DARWIN_C_SOURCE
+
+/* Add the _ISOC99_SOURCE flag when building */
+#undef _ISOC99_SOURCE
+
+/* Add the _LARGEFILE64_SOURCE flag when building */
+#undef _LARGEFILE64_SOURCE
+
+/* Add the _LARGEFILE_SOURCE64 flag when building */
+#undef _LARGEFILE_SOURCE64
+
+/* # needed in sys/socket.h Should OS/390 do the right thing with sockets? */
+#undef _OE_SOCKETS
+
+/* Do we really want to follow the standard? Yes we do! */
+#undef _POSIX_PTHREAD_SEMANTICS
+
+/* Do we want the reentrant OS API? */
+#undef _REENTRANT
+
+/* Do we want the thread-safe OS API? */
+#undef _THREAD_SAFE
+
+/* Do we want to use the XOPEN network library? */
+#undef _XOPEN_SOURCE
+
+/* Do we want to use the XOPEN network library? */
+#undef _XOPEN_SOURCE_EXTENDED
+
+/* Define to 1 if type `char' is unsigned and you are not using gcc. */
+#ifndef __CHAR_UNSIGNED__
+# undef __CHAR_UNSIGNED__
+#endif
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef gid_t
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Signed integer type wide enough to hold a pointer. */
+#undef intptr_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef mode_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define as int if socklen_t is not available */
+#undef socklen_t
+
+/* Do we want to use the strtod() in compat? */
+#undef strtod
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef uid_t
+
+/* Unsigned integer type wide enough to hold a pointer. */
+#undef uintptr_t
+
+
+ /* Undef unused package specific autoheader defines so that we can
+ * include both tclConfig.h and tkConfig.h at the same time: */
+ /* override */ #undef PACKAGE_NAME
+ /* override */ #undef PACKAGE_STRING
+ /* override */ #undef PACKAGE_TARNAME
+ #endif /* _TCLCONFIG */
diff --git a/unix/tclConfig.sh.in b/unix/tclConfig.sh.in
index e3509df..7e1d4af 100644
--- a/unix/tclConfig.sh.in
+++ b/unix/tclConfig.sh.in
@@ -21,9 +21,9 @@ TCL_CC='@CC@'
# -D flags for use with the C compiler.
TCL_DEFS='@DEFS@'
-# If TCL was built with debugging symbols, generated libraries contain
-# this string at the end of the library name (before the extension).
-TCL_DBGX=@TCL_DBGX@
+# TCL_DBGX used to be used to distinguish debug vs. non-debug builds.
+# This was a righteous pain so the core doesn't do that any more.
+TCL_DBGX=
# Default flags used in an optimized and debuggable build, respectively.
TCL_CFLAGS_DEBUG='@CFLAGS_DEBUG@'
@@ -39,17 +39,8 @@ TCL_SHARED_BUILD=@TCL_SHARED_BUILD@
# The name of the Tcl library (may be either a .a file or a shared library):
TCL_LIB_FILE='@TCL_LIB_FILE@'
-# Flag to indicate whether shared libraries need export files.
-TCL_NEEDS_EXP_FILE=@TCL_NEEDS_EXP_FILE@
-
-# String that can be evaluated to generate the part of the export file
-# name that comes after the "libxxx" (includes version number, if any,
-# extension, and anything else needed). May depend on the variables
-# VERSION. On most UNIX systems this is ${VERSION}.exp.
-TCL_EXPORT_FILE_SUFFIX='@CFG_TCL_EXPORT_FILE_SUFFIX@'
-
# Additional libraries to use when linking Tcl.
-TCL_LIBS='@DL_LIBS@ @LIBS@ @MATH_LIBS@'
+TCL_LIBS='@TCL_LIBS@'
# Top-level directory in which Tcl's platform-independent files are
# installed.
diff --git a/unix/tclLoadAix.c b/unix/tclLoadAix.c
index 8dd0e54..59bccbf 100644
--- a/unix/tclLoadAix.c
+++ b/unix/tclLoadAix.c
@@ -1,24 +1,24 @@
-/*
+/*
* tclLoadAix.c --
*
- * This file implements the dlopen and dlsym APIs under the
- * AIX operating system, to enable the Tcl "load" command to
- * work. This code was provided by Jens-Uwe Mager.
+ * This file implements the dlopen and dlsym APIs under the AIX operating
+ * system, to enable the Tcl "load" command to work. This code was
+ * provided by Jens-Uwe Mager.
*
* This file is subject to the following copyright notice, which is
- * different from the notice used elsewhere in Tcl. The file has
- * been modified to incorporate the file dlfcn.h in-line.
+ * different from the notice used elsewhere in Tcl. The file has been
+ * modified to incorporate the file dlfcn.h in-line.
*
* Copyright (c) 1992,1993,1995,1996, Jens-Uwe Mager, Helios Software GmbH
* Not derived from licensed software.
-
+ *
* Permission is granted to freely use, copy, modify, and redistribute
* this software, provided that the author is not construed to be liable
* for any results of using the software, alterations are clearly marked
* as such, and this notice is not modified.
*
- * Note: this file has been altered from the original in a few
- * ways in order to work properly with Tcl.
+ * Note: this file has been altered from the original in a few ways in order
+ * to work properly with Tcl.
*/
/*
@@ -38,50 +38,53 @@
#include "../compat/dlfcn.h"
/*
- * We simulate dlopen() et al. through a call to load. Because AIX has
- * no call to find an exported symbol we read the loader section of the
- * loaded module and build a list of exported symbols and their virtual
- * address.
+ * We simulate dlopen() et al. through a call to load. Because AIX has no call
+ * to find an exported symbol we read the loader section of the loaded module
+ * and build a list of exported symbols and their virtual address.
*/
typedef struct {
- char *name; /* the symbols's name */
- void *addr; /* its relocated virtual address */
+ char *name; /* The symbols's name. */
+ void *addr; /* Its relocated virtual address. */
} Export, *ExportPtr;
/*
- * xlC uses the following structure to list its constructors and
- * destructors. This is gleaned from the output of munch.
+ * xlC uses the following structure to list its constructors and destructors.
+ * This is gleaned from the output of munch.
*/
+
typedef struct {
- void (*init)(void); /* call static constructors */
- void (*term)(void); /* call static destructors */
+ void (*init)(void); /* call static constructors */
+ void (*term)(void); /* call static destructors */
} Cdtor, *CdtorPtr;
/*
* The void * handle returned from dlopen is actually a ModulePtr.
*/
+
typedef struct Module {
- struct Module *next;
- char *name; /* module name for refcounting */
- int refCnt; /* the number of references */
- void *entry; /* entry point from load */
- struct dl_info *info; /* optional init/terminate functions */
- CdtorPtr cdtors; /* optional C++ constructors */
- int nExports; /* the number of exports found */
- ExportPtr exports; /* the array of exports */
+ struct Module *next;
+ char *name; /* module name for refcounting */
+ int refCnt; /* the number of references */
+ void *entry; /* entry point from load */
+ struct dl_info *info; /* optional init/terminate functions */
+ CdtorPtr cdtors; /* optional C++ constructors */
+ int nExports; /* the number of exports found */
+ ExportPtr exports; /* the array of exports */
} Module, *ModulePtr;
/*
- * We keep a list of all loaded modules to be able to call the fini
- * handlers and destructors at atexit() time.
+ * We keep a list of all loaded modules to be able to call the fini handlers
+ * and destructors at atexit() time.
*/
+
static ModulePtr modList;
/*
- * The last error from one of the dl* routines is kept in static
- * variables here. Each error is returned only once to the caller.
+ * The last error from one of the dl* routines is kept in static variables
+ * here. Each error is returned only once to the caller.
*/
+
static char errbuf[BUFSIZ];
static int errvalid;
@@ -89,459 +92,539 @@ static void caterr(char *);
static int readExports(ModulePtr);
static void terminate(void);
static void *findMain(void);
-
-VOID *dlopen(const char *path, int mode)
+
+void *
+dlopen(
+ const char *path,
+ int mode)
{
- register ModulePtr mp;
- static void *mainModule;
+ register ModulePtr mp;
+ static void *mainModule;
- /*
- * Upon the first call register a terminate handler that will
- * close all libraries. Also get a reference to the main module
- * for use with loadbind.
- */
- if (!mainModule) {
- if ((mainModule = findMain()) == NULL)
- return NULL;
- atexit(terminate);
+ /*
+ * Upon the first call register a terminate handler that will close all
+ * libraries. Also get a reference to the main module for use with
+ * loadbind.
+ */
+
+ if (!mainModule) {
+ mainModule = findMain();
+ if (mainModule == NULL) {
+ return NULL;
}
- /*
- * Scan the list of modules if we have the module already loaded.
- */
- for (mp = modList; mp; mp = mp->next)
- if (strcmp(mp->name, path) == 0) {
- mp->refCnt++;
- return (VOID *) mp;
- }
- if ((mp = (ModulePtr)calloc(1, sizeof(*mp))) == NULL) {
- errvalid++;
- strcpy(errbuf, "calloc: ");
- strcat(errbuf, strerror(errno));
- return (VOID *) NULL;
+ atexit(terminate);
+ }
+
+ /*
+ * Scan the list of modules if we have the module already loaded.
+ */
+
+ for (mp = modList; mp; mp = mp->next) {
+ if (strcmp(mp->name, path) == 0) {
+ mp->refCnt++;
+ return (void *) mp;
}
- mp->name = malloc((unsigned) (strlen(path) + 1));
- strcpy(mp->name, path);
+ }
+
+ mp = (ModulePtr) calloc(1, sizeof(*mp));
+ if (mp == NULL) {
+ errvalid++;
+ strcpy(errbuf, "calloc: ");
+ strcat(errbuf, strerror(errno));
+ return NULL;
+ }
+
+ mp->name = malloc((unsigned) (strlen(path) + 1));
+ strcpy(mp->name, path);
+
+ /*
+ * load should be declared load(const char *...). Thus we cast the path to
+ * a normal char *. Ugly.
+ */
+
+ mp->entry = (void *) load((char *)path, L_NOAUTODEFER, NULL);
+ if (mp->entry == NULL) {
+ free(mp->name);
+ free(mp);
+ errvalid++;
+ strcpy(errbuf, "dlopen: ");
+ strcat(errbuf, path);
+ strcat(errbuf, ": ");
+
/*
- * load should be declared load(const char *...). Thus we
- * cast the path to a normal char *. Ugly.
+ * If AIX says the file is not executable, the error can be further
+ * described by querying the loader about the last error.
*/
- if ((mp->entry = (void *)load((char *)path, L_NOAUTODEFER, NULL)) == NULL) {
- free(mp->name);
- free(mp);
- errvalid++;
- strcpy(errbuf, "dlopen: ");
- strcat(errbuf, path);
- strcat(errbuf, ": ");
- /*
- * If AIX says the file is not executable, the error
- * can be further described by querying the loader about
- * the last error.
- */
- if (errno == ENOEXEC) {
- char *tmp[BUFSIZ/sizeof(char *)];
- if (loadquery(L_GETMESSAGES, tmp, sizeof(tmp)) == -1)
- strcpy(errbuf, strerror(errno));
- else {
- char **p;
- for (p = tmp; *p; p++)
- caterr(*p);
- }
- } else
- strcat(errbuf, strerror(errno));
- return (VOID *) NULL;
+
+ if (errno == ENOEXEC) {
+ char *tmp[BUFSIZ/sizeof(char *)], **p;
+
+ if (loadquery(L_GETMESSAGES, tmp, sizeof(tmp)) == -1) {
+ strcpy(errbuf, strerror(errno));
+ } else {
+ for (p=tmp ; *p ; p++) {
+ caterr(*p);
+ }
+ }
+ } else {
+ strcat(errbuf, strerror(errno));
}
- mp->refCnt = 1;
- mp->next = modList;
- modList = mp;
- if (loadbind(0, mainModule, mp->entry) == -1) {
- dlclose(mp);
- errvalid++;
- strcpy(errbuf, "loadbind: ");
- strcat(errbuf, strerror(errno));
- return (VOID *) NULL;
+ return NULL;
+ }
+
+ mp->refCnt = 1;
+ mp->next = modList;
+ modList = mp;
+
+ if (loadbind(0, mainModule, mp->entry) == -1) {
+ loadbindFailure:
+ dlclose(mp);
+ errvalid++;
+ strcpy(errbuf, "loadbind: ");
+ strcat(errbuf, strerror(errno));
+ return NULL;
+ }
+
+ /*
+ * If the user wants global binding, loadbind against all other loaded
+ * modules.
+ */
+
+ if (mode & RTLD_GLOBAL) {
+ register ModulePtr mp1;
+
+ for (mp1 = mp->next; mp1; mp1 = mp1->next) {
+ if (loadbind(0, mp1->entry, mp->entry) == -1) {
+ goto loadbindFailure;
+ }
}
- /*
- * If the user wants global binding, loadbind against all other
- * loaded modules.
- */
- if (mode & RTLD_GLOBAL) {
- register ModulePtr mp1;
- for (mp1 = mp->next; mp1; mp1 = mp1->next)
- if (loadbind(0, mp1->entry, mp->entry) == -1) {
- dlclose(mp);
- errvalid++;
- strcpy(errbuf, "loadbind: ");
- strcat(errbuf, strerror(errno));
- return (VOID *) NULL;
- }
+ }
+
+ if (readExports(mp) == -1) {
+ dlclose(mp);
+ return NULL;
+ }
+
+ /*
+ * If there is a dl_info structure, call the init function.
+ */
+
+ if (mp->info = (struct dl_info *)dlsym(mp, "dl_info")) {
+ if (mp->info->init) {
+ (*mp->info->init)();
}
- if (readExports(mp) == -1) {
- dlclose(mp);
- return (VOID *) NULL;
+ } else {
+ errvalid = 0;
+ }
+
+ /*
+ * If the shared object was compiled using xlC we will need to call static
+ * constructors (and later on dlclose destructors).
+ */
+
+ if (mp->cdtors = (CdtorPtr) dlsym(mp, "__cdtors")) {
+ while (mp->cdtors->init) {
+ (*mp->cdtors->init)();
+ mp->cdtors++;
}
- /*
- * If there is a dl_info structure, call the init function.
- */
- if (mp->info = (struct dl_info *)dlsym(mp, "dl_info")) {
- if (mp->info->init)
- (*mp->info->init)();
- } else
- errvalid = 0;
- /*
- * If the shared object was compiled using xlC we will need
- * to call static constructors (and later on dlclose destructors).
- */
- if (mp->cdtors = (CdtorPtr)dlsym(mp, "__cdtors")) {
- while (mp->cdtors->init) {
- (*mp->cdtors->init)();
- mp->cdtors++;
- }
- } else
- errvalid = 0;
- return (VOID *) mp;
-}
+ } else {
+ errvalid = 0;
+ }
+ return (void *) mp;
+}
+
/*
- * Attempt to decipher an AIX loader error message and append it
- * to our static error message buffer.
+ * Attempt to decipher an AIX loader error message and append it to our static
+ * error message buffer.
*/
-static void caterr(char *s)
+
+static void
+caterr(
+ char *s)
{
- register char *p = s;
+ register char *p = s;
- while (*p >= '0' && *p <= '9')
- p++;
- switch(atoi(s)) { /* INTL: "C", UTF safe. */
- case L_ERROR_TOOMANY:
- strcat(errbuf, "to many errors");
- break;
- case L_ERROR_NOLIB:
- strcat(errbuf, "can't load library");
- strcat(errbuf, p);
- break;
- case L_ERROR_UNDEF:
- strcat(errbuf, "can't find symbol");
- strcat(errbuf, p);
- break;
- case L_ERROR_RLDBAD:
- strcat(errbuf, "bad RLD");
- strcat(errbuf, p);
- break;
- case L_ERROR_FORMAT:
- strcat(errbuf, "bad exec format in");
- strcat(errbuf, p);
- break;
- case L_ERROR_ERRNO:
- strcat(errbuf, strerror(atoi(++p))); /* INTL: "C", UTF safe. */
- break;
- default:
- strcat(errbuf, s);
- break;
- }
+ while (*p >= '0' && *p <= '9') {
+ p++;
+ }
+ switch (atoi(s)) { /* INTL: "C", UTF safe. */
+ case L_ERROR_TOOMANY:
+ strcat(errbuf, "to many errors");
+ break;
+ case L_ERROR_NOLIB:
+ strcat(errbuf, "can't load library");
+ strcat(errbuf, p);
+ break;
+ case L_ERROR_UNDEF:
+ strcat(errbuf, "can't find symbol");
+ strcat(errbuf, p);
+ break;
+ case L_ERROR_RLDBAD:
+ strcat(errbuf, "bad RLD");
+ strcat(errbuf, p);
+ break;
+ case L_ERROR_FORMAT:
+ strcat(errbuf, "bad exec format in");
+ strcat(errbuf, p);
+ break;
+ case L_ERROR_ERRNO:
+ strcat(errbuf, strerror(atoi(++p))); /* INTL: "C", UTF safe. */
+ break;
+ default:
+ strcat(errbuf, s);
+ break;
+ }
}
-
-VOID *dlsym(void *handle, const char *symbol)
+
+void *
+dlsym(
+ void *handle,
+ const char *symbol)
{
- register ModulePtr mp = (ModulePtr)handle;
- register ExportPtr ep;
- register int i;
+ register ModulePtr mp = (ModulePtr)handle;
+ register ExportPtr ep;
+ register int i;
- /*
- * Could speed up the search, but I assume that one assigns
- * the result to function pointers anyways.
- */
- for (ep = mp->exports, i = mp->nExports; i; i--, ep++)
- if (strcmp(ep->name, symbol) == 0)
- return ep->addr;
- errvalid++;
- strcpy(errbuf, "dlsym: undefined symbol ");
- strcat(errbuf, symbol);
- return NULL;
-}
+ /*
+ * Could speed up the search, but I assume that one assigns the result to
+ * function pointers anyways.
+ */
-char *dlerror(void)
-{
- if (errvalid) {
- errvalid = 0;
- return errbuf;
+ for (ep = mp->exports, i = mp->nExports; i; i--, ep++) {
+ if (strcmp(ep->name, symbol) == 0) {
+ return ep->addr;
}
- return NULL;
-}
+ }
-int dlclose(void *handle)
+ errvalid++;
+ strcpy(errbuf, "dlsym: undefined symbol ");
+ strcat(errbuf, symbol);
+ return NULL;
+}
+
+char *
+dlerror(void)
{
- register ModulePtr mp = (ModulePtr)handle;
- int result;
- register ModulePtr mp1;
+ if (errvalid) {
+ errvalid = 0;
+ return errbuf;
+ }
+ return NULL;
+}
+
+int
+dlclose(
+ void *handle)
+{
+ register ModulePtr mp = (ModulePtr)handle;
+ int result;
+ register ModulePtr mp1;
- if (--mp->refCnt > 0)
- return 0;
- if (mp->info && mp->info->fini)
- (*mp->info->fini)();
- if (mp->cdtors)
- while (mp->cdtors->term) {
- (*mp->cdtors->term)();
- mp->cdtors++;
- }
- result = unload(mp->entry);
- if (result == -1) {
- errvalid++;
- strcpy(errbuf, strerror(errno));
+ if (--mp->refCnt > 0) {
+ return 0;
+ }
+
+ if (mp->info && mp->info->fini) {
+ (*mp->info->fini)();
+ }
+
+ if (mp->cdtors) {
+ while (mp->cdtors->term) {
+ (*mp->cdtors->term)();
+ mp->cdtors++;
}
- if (mp->exports) {
- register ExportPtr ep;
- register int i;
- for (ep = mp->exports, i = mp->nExports; i; i--, ep++)
- if (ep->name)
- free(ep->name);
- free(mp->exports);
+ }
+
+ result = unload(mp->entry);
+ if (result == -1) {
+ errvalid++;
+ strcpy(errbuf, strerror(errno));
+ }
+
+ if (mp->exports) {
+ register ExportPtr ep;
+ register int i;
+ for (ep = mp->exports, i = mp->nExports; i; i--, ep++) {
+ if (ep->name) {
+ free(ep->name);
+ }
}
- if (mp == modList)
- modList = mp->next;
- else {
- for (mp1 = modList; mp1; mp1 = mp1->next)
- if (mp1->next == mp) {
- mp1->next = mp->next;
- break;
- }
+ free(mp->exports);
+ }
+
+ if (mp == modList) {
+ modList = mp->next;
+ } else {
+ for (mp1 = modList; mp1; mp1 = mp1->next) {
+ if (mp1->next == mp) {
+ mp1->next = mp->next;
+ break;
+ }
}
- free(mp->name);
- free(mp);
- return result;
-}
+ }
-static void terminate(void)
+ free(mp->name);
+ free(mp);
+ return result;
+}
+
+static void
+terminate(void)
{
- while (modList)
- dlclose(modList);
+ while (modList) {
+ dlclose(modList);
+ }
}
-
+
/*
* Build the export table from the XCOFF .loader section.
*/
-static int readExports(ModulePtr mp)
+
+static int
+readExports(
+ ModulePtr mp)
{
- LDFILE *ldp = NULL;
- SCNHDR sh, shdata;
- LDHDR *lhp;
- char *ldbuf;
- LDSYM *ls;
- int i;
- ExportPtr ep;
-
- if ((ldp = ldopen(mp->name, ldp)) == NULL) {
- struct ld_info *lp;
- char *buf;
- int size = 4*1024;
- if (errno != ENOENT) {
- errvalid++;
- strcpy(errbuf, "readExports: ");
- strcat(errbuf, strerror(errno));
- return -1;
- }
- /*
- * The module might be loaded due to the LIBPATH
- * environment variable. Search for the loaded
- * module using L_GETINFO.
- */
- if ((buf = malloc(size)) == NULL) {
- errvalid++;
- strcpy(errbuf, "readExports: ");
- strcat(errbuf, strerror(errno));
- return -1;
- }
- while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) {
- free(buf);
- size += 4*1024;
- if ((buf = malloc(size)) == NULL) {
- errvalid++;
- strcpy(errbuf, "readExports: ");
- strcat(errbuf, strerror(errno));
- return -1;
- }
- }
- if (i == -1) {
- errvalid++;
- strcpy(errbuf, "readExports: ");
- strcat(errbuf, strerror(errno));
- free(buf);
- return -1;
- }
- /*
- * Traverse the list of loaded modules. The entry point
- * returned by load() does actually point to the data
- * segment origin.
- */
- lp = (struct ld_info *)buf;
- while (lp) {
- if (lp->ldinfo_dataorg == mp->entry) {
- ldp = ldopen(lp->ldinfo_filename, ldp);
- break;
- }
- if (lp->ldinfo_next == 0)
- lp = NULL;
- else
- lp = (struct ld_info *)((char *)lp + lp->ldinfo_next);
- }
- free(buf);
- if (!ldp) {
- errvalid++;
- strcpy(errbuf, "readExports: ");
- strcat(errbuf, strerror(errno));
- return -1;
- }
- }
- if (TYPE(ldp) != U802TOCMAGIC) {
- errvalid++;
- strcpy(errbuf, "readExports: bad magic");
- while(ldclose(ldp) == FAILURE)
- ;
- return -1;
+ LDFILE *ldp = NULL;
+ SCNHDR sh, shdata;
+ LDHDR *lhp;
+ char *ldbuf;
+ LDSYM *ls;
+ int i;
+ ExportPtr ep;
+ const char *errMsg;
+
+#define Error(msg) do{errMsg=(msg);goto error;}while(0)
+#define SysErr() Error(strerror(errno))
+
+ ldp = ldopen(mp->name, ldp);
+ if (ldp == NULL) {
+ struct ld_info *lp;
+ char *buf;
+ int size = 0;
+
+ if (errno != ENOENT) {
+ SysErr();
}
+
/*
- * Get the padding for the data section. This is needed for
- * AIX 4.1 compilers. This is used when building the final
- * function pointer to the exported symbol.
+ * The module might be loaded due to the LIBPATH environment variable.
+ * Search for the loaded module using L_GETINFO.
*/
- if (ldnshread(ldp, _DATA, &shdata) != SUCCESS) {
- errvalid++;
- strcpy(errbuf, "readExports: cannot read data section header");
- while(ldclose(ldp) == FAILURE)
- ;
- return -1;
- }
- if (ldnshread(ldp, _LOADER, &sh) != SUCCESS) {
- errvalid++;
- strcpy(errbuf, "readExports: cannot read loader section header");
- while(ldclose(ldp) == FAILURE)
- ;
- return -1;
+
+ while (1) {
+ size += 4 * 1024;
+ buf = malloc(size);
+ if (buf == NULL) {
+ SysErr();
+ }
+
+ i = loadquery(L_GETINFO, buf, size);
+
+ if (i != -1) {
+ break;
+ }
+ free(buf);
+ if (errno != ENOMEM) {
+ SysErr();
+ }
}
+
/*
- * We read the complete loader section in one chunk, this makes
- * finding long symbol names residing in the string table easier.
+ * Traverse the list of loaded modules. The entry point returned by
+ * load() does actually point to the data segment origin.
*/
- if ((ldbuf = (char *)malloc(sh.s_size)) == NULL) {
- errvalid++;
- strcpy(errbuf, "readExports: ");
- strcat(errbuf, strerror(errno));
- while(ldclose(ldp) == FAILURE)
- ;
- return -1;
+
+ lp = (struct ld_info *) buf;
+ while (lp) {
+ if (lp->ldinfo_dataorg == mp->entry) {
+ ldp = ldopen(lp->ldinfo_filename, ldp);
+ break;
+ }
+ if (lp->ldinfo_next == 0) {
+ lp = NULL;
+ } else {
+ lp = (struct ld_info *)((char *)lp + lp->ldinfo_next);
+ }
}
- if (FSEEK(ldp, sh.s_scnptr, BEGINNING) != OKFSEEK) {
- errvalid++;
- strcpy(errbuf, "readExports: cannot seek to loader section");
- free(ldbuf);
- while(ldclose(ldp) == FAILURE)
- ;
- return -1;
+
+ free(buf);
+
+ if (!ldp) {
+ SysErr();
}
- if (FREAD(ldbuf, sh.s_size, 1, ldp) != 1) {
- errvalid++;
- strcpy(errbuf, "readExports: cannot read loader section");
- free(ldbuf);
- while(ldclose(ldp) == FAILURE)
- ;
- return -1;
+ }
+
+ if (TYPE(ldp) != U802TOCMAGIC) {
+ Error("bad magic");
+ }
+
+ /*
+ * Get the padding for the data section. This is needed for AIX 4.1
+ * compilers. This is used when building the final function pointer to the
+ * exported symbol.
+ */
+
+ if (ldnshread(ldp, _DATA, &shdata) != SUCCESS) {
+ Error("cannot read data section header");
+ }
+
+ if (ldnshread(ldp, _LOADER, &sh) != SUCCESS) {
+ Error("cannot read loader section header");
+ }
+
+ /*
+ * We read the complete loader section in one chunk, this makes finding
+ * long symbol names residing in the string table easier.
+ */
+
+ ldbuf = (char *) malloc(sh.s_size);
+ if (ldbuf == NULL) {
+ SysErr();
+ }
+
+ if (FSEEK(ldp, sh.s_scnptr, BEGINNING) != OKFSEEK) {
+ free(ldbuf);
+ Error("cannot seek to loader section");
+ }
+
+ if (FREAD(ldbuf, sh.s_size, 1, ldp) != 1) {
+ free(ldbuf);
+ Error("cannot read loader section");
+ }
+
+ lhp = (LDHDR *) ldbuf;
+ ls = (LDSYM *)(ldbuf + LDHDRSZ);
+
+ /*
+ * Count the number of exports to include in our export table.
+ */
+
+ for (i = lhp->l_nsyms; i; i--, ls++) {
+ if (!LDR_EXPORT(*ls)) {
+ continue;
}
- lhp = (LDHDR *)ldbuf;
- ls = (LDSYM *)(ldbuf+LDHDRSZ);
- /*
- * Count the number of exports to include in our export table.
- */
- for (i = lhp->l_nsyms; i; i--, ls++) {
- if (!LDR_EXPORT(*ls))
- continue;
- mp->nExports++;
+ mp->nExports++;
+ }
+
+ mp->exports = (ExportPtr) calloc(mp->nExports, sizeof(*mp->exports));
+ if (mp->exports == NULL) {
+ free(ldbuf);
+ SysErr();
+ }
+
+ /*
+ * Fill in the export table. All entries are relative to the entry point
+ * we got from load.
+ */
+
+ ep = mp->exports;
+ ls = (LDSYM *)(ldbuf + LDHDRSZ);
+ for (i=lhp->l_nsyms ; i!=0 ; i--,ls++) {
+ char *symname;
+ char tmpsym[SYMNMLEN+1];
+
+ if (!LDR_EXPORT(*ls)) {
+ continue;
}
- if ((mp->exports = (ExportPtr)calloc(mp->nExports, sizeof(*mp->exports))) == NULL) {
- errvalid++;
- strcpy(errbuf, "readExports: ");
- strcat(errbuf, strerror(errno));
- free(ldbuf);
- while(ldclose(ldp) == FAILURE)
- ;
- return -1;
+
+ if (ls->l_zeroes == 0) {
+ symname = ls->l_offset + lhp->l_stoff + ldbuf;
+ } else {
+ /*
+ * The l_name member is not zero terminated, we must copy the
+ * first SYMNMLEN chars and make sure we have a zero byte at the
+ * end.
+ */
+
+ strncpy(tmpsym, ls->l_name, SYMNMLEN);
+ tmpsym[SYMNMLEN] = '\0';
+ symname = tmpsym;
}
- /*
- * Fill in the export table. All entries are relative to
- * the entry point we got from load.
- */
- ep = mp->exports;
- ls = (LDSYM *)(ldbuf+LDHDRSZ);
- for (i = lhp->l_nsyms; i; i--, ls++) {
- char *symname;
- char tmpsym[SYMNMLEN+1];
- if (!LDR_EXPORT(*ls))
- continue;
- if (ls->l_zeroes == 0)
- symname = ls->l_offset+lhp->l_stoff+ldbuf;
- else {
- /*
- * The l_name member is not zero terminated, we
- * must copy the first SYMNMLEN chars and make
- * sure we have a zero byte at the end.
- */
- strncpy(tmpsym, ls->l_name, SYMNMLEN);
- tmpsym[SYMNMLEN] = '\0';
- symname = tmpsym;
- }
- ep->name = malloc((unsigned) (strlen(symname) + 1));
- strcpy(ep->name, symname);
- ep->addr = (void *)((unsigned long)mp->entry +
- ls->l_value - shdata.s_vaddr);
- ep++;
+ ep->name = malloc((unsigned) (strlen(symname) + 1));
+ strcpy(ep->name, symname);
+ ep->addr = (void *)((unsigned long)
+ mp->entry + ls->l_value - shdata.s_vaddr);
+ ep++;
+ }
+ free(ldbuf);
+ while (ldclose(ldp) == FAILURE) {
+ /* Empty body */
+ }
+ return 0;
+
+ /*
+ * This is a factoring out of the error-handling code to make the rest of
+ * the function much simpler to read.
+ */
+
+ error:
+ errvalid++;
+ strcpy(errbuf, "readExports: ");
+ strcat(errbuf, errMsg);
+
+ if (ldp != NULL) {
+ while (ldclose(ldp) == FAILURE) {
+ /* Empty body */
}
- free(ldbuf);
- while(ldclose(ldp) == FAILURE)
- ;
- return 0;
+ }
+ return -1;
}
-
+
/*
- * Find the main modules entry point. This is used as export pointer
- * for loadbind() to be able to resolve references to the main part.
+ * Find the main modules entry point. This is used as export pointer for
+ * loadbind() to be able to resolve references to the main part.
*/
-static void * findMain(void)
+
+static void *
+findMain(void)
{
- struct ld_info *lp;
- char *buf;
- int size = 4*1024;
- int i;
- void *ret;
-
- if ((buf = malloc(size)) == NULL) {
- errvalid++;
- strcpy(errbuf, "findMain: ");
- strcat(errbuf, strerror(errno));
- return NULL;
- }
- while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) {
- free(buf);
- size += 4*1024;
- if ((buf = malloc(size)) == NULL) {
- errvalid++;
- strcpy(errbuf, "findMain: ");
- strcat(errbuf, strerror(errno));
- return NULL;
- }
- }
- if (i == -1) {
- errvalid++;
- strcpy(errbuf, "findMain: ");
- strcat(errbuf, strerror(errno));
- free(buf);
- return NULL;
+ struct ld_info *lp;
+ char *buf;
+ int size = 4*1024;
+ int i;
+ void *ret;
+
+ buf = malloc(size);
+ if (buf == NULL) {
+ goto error;
+ }
+
+ while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) {
+ free(buf);
+ size += 4*1024;
+ buf = malloc(size);
+ if (buf == NULL) {
+ goto error;
}
- /*
- * The first entry is the main module. The entry point
- * returned by load() does actually point to the data
- * segment origin.
- */
- lp = (struct ld_info *)buf;
- ret = lp->ldinfo_dataorg;
+ }
+
+ if (i == -1) {
free(buf);
- return ret;
-}
+ goto error;
+ }
+ /*
+ * The first entry is the main module. The entry point returned by load()
+ * does actually point to the data segment origin.
+ */
+
+ lp = (struct ld_info *) buf;
+ ret = lp->ldinfo_dataorg;
+ free(buf);
+ return ret;
+
+ error:
+ errvalid++;
+ strcpy(errbuf, "findMain: ");
+ strcat(errbuf, strerror(errno));
+ return NULL;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclLoadAout.c b/unix/tclLoadAout.c
deleted file mode 100644
index 22bd7b7..0000000
--- a/unix/tclLoadAout.c
+++ /dev/null
@@ -1,534 +0,0 @@
-/*
- * tclLoadAout.c --
- *
- * This procedure provides a version of the TclLoadFile that
- * provides pseudo-static linking using version-7 compatible
- * a.out files described in either sys/exec.h or sys/a.out.h.
- *
- * Copyright (c) 1995, by General Electric Company. All rights reserved.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * This work was supported in part by the ARPA Manufacturing Automation
- * and Design Engineering (MADE) Initiative through ARPA contract
- * F33615-94-C-4400.
- */
-
-#include "tclInt.h"
-#include <fcntl.h>
-#ifdef HAVE_EXEC_AOUT_H
-# include <sys/exec_aout.h>
-#endif
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#else
-# include "../compat/unistd.h"
-#endif
-
-/*
- * Some systems describe the a.out header in sys/exec.h, and some in
- * a.out.h.
- */
-
-#ifdef USE_SYS_EXEC_H
-#include <sys/exec.h>
-#endif
-#ifdef USE_A_OUT_H
-#include <a.out.h>
-#endif
-#ifdef USE_SYS_EXEC_AOUT_H
-#include <sys/exec_aout.h>
-#define a_magic a_midmag
-#endif
-
-/*
- * TCL_LOADSHIM is the amount by which to shim the break when loading
- */
-
-#ifndef TCL_LOADSHIM
-#define TCL_LOADSHIM 0x4000L
-#endif
-
-/*
- * TCL_LOADALIGN must be a power of 2, and is the alignment to which
- * to force the origin of load modules
- */
-
-#ifndef TCL_LOADALIGN
-#define TCL_LOADALIGN 0x4000L
-#endif
-
-/*
- * TCL_LOADMAX is the maximum size of a load module, and is used as
- * a sanity check when loading
- */
-
-#ifndef TCL_LOADMAX
-#define TCL_LOADMAX 2000000L
-#endif
-
-/*
- * Kernel calls that appear to be missing from the system .h files:
- */
-
-extern char * brk _ANSI_ARGS_((char *));
-extern char * sbrk _ANSI_ARGS_((size_t));
-
-/*
- * The static variable SymbolTableFile contains the file name where the
- * result of the last link was stored. The file is kept because doing so
- * allows one load module to use the symbols defined in another.
- */
-
-static char * SymbolTableFile = NULL;
-
-/*
- * Type of the dictionary function that begins each load module.
- */
-
-typedef Tcl_PackageInitProc * (* DictFn) _ANSI_ARGS_ ((CONST char * symbol));
-
-/*
- * Prototypes for procedures referenced only in this file:
- */
-
-static int FindLibraries _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * pathPtr,
- Tcl_DString * buf));
-static void UnlinkSymbolTable _ANSI_ARGS_((void));
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpDlopen --
- *
- * Dynamically loads a binary code file into memory and returns
- * a handle to the new code.
- *
- * Results:
- * A standard Tcl completion code. If an error occurs, an error
- * message is left in the interp's result.
- *
- * Side effects:
- * New code suddenly appears in memory.
- *
- *
- * Bugs:
- * This function does not attempt to handle the case where the
- * BSS segment is not executable. It will therefore fail on
- * Encore Multimax, Pyramid 90x, and similar machines. The
- * reason is that the mprotect() kernel call, which would
- * otherwise be employed to mark the newly-loaded text segment
- * executable, results in a system crash on BSD/386.
- *
- * In an effort to make it fast, this function eschews the
- * technique of linking the load module once, reading its header
- * to determine its size, allocating memory for it, and linking
- * it again. Instead, it `shims out' memory allocation by
- * placing the module TCL_LOADSHIM bytes beyond the break,
- * and assuming that any malloc() calls required to run the
- * linker will not advance the break beyond that point. If
- * the break is advanced beyonnd that point, the load will
- * fail with an `inconsistent memory allocation' error.
- * It perhaps ought to retry the link, but the failure has
- * not been observed in two years of daily use of this function.
- *----------------------------------------------------------------------
- */
-
-int
-TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Obj *pathPtr; /* Name of the file containing the desired
- * code (UTF-8). */
- Tcl_LoadHandle *loadHandle; /* Filled with token for dynamically loaded
- * file which will be passed back to
- * (*unloadProcPtr)() to unload the file. */
- Tcl_FSUnloadFileProc **unloadProcPtr;
- /* Filled with address of Tcl_FSUnloadFileProc
- * function which should be used for
- * this file. */
-{
- char * inputSymbolTable; /* Name of the file containing the
- * symbol table from the last link. */
- Tcl_DString linkCommandBuf; /* Command to do the run-time relocation
- * of the module.*/
- char * linkCommand;
- char relocatedFileName [L_tmpnam];
- /* Name of the file holding the relocated */
- /* text of the module */
- int relocatedFd; /* File descriptor of the file holding
- * relocated text */
- struct exec relocatedHead; /* Header of the relocated text */
- unsigned long relocatedSize;/* Size of the relocated text */
- char * startAddress; /* Starting address of the module */
- int status; /* Status return from Tcl_ calls */
- char * p;
-
- /* Find the file that contains the symbols for the run-time link. */
-
- if (SymbolTableFile != NULL) {
- inputSymbolTable = SymbolTableFile;
- } else if (tclExecutableName == NULL) {
- Tcl_SetResult (interp, "can't find the tclsh executable", TCL_STATIC);
- return TCL_ERROR;
- } else {
- inputSymbolTable = tclExecutableName;
- }
-
- /* Construct the `ld' command that builds the relocated module */
-
- tmpnam (relocatedFileName);
- Tcl_DStringInit (&linkCommandBuf);
- Tcl_DStringAppend (&linkCommandBuf, "exec ld -o ", -1);
- Tcl_DStringAppend (&linkCommandBuf, relocatedFileName, -1);
-#if defined(__mips) || defined(mips)
- Tcl_DStringAppend (&linkCommandBuf, " -G 0 ", -1);
-#endif
- Tcl_DStringAppend (&linkCommandBuf, " -u TclLoadDictionary_", -1);
- TclGuessPackageName(Tcl_GetString(pathPtr), &linkCommandBuf);
- Tcl_DStringAppend (&linkCommandBuf, " -A ", -1);
- Tcl_DStringAppend (&linkCommandBuf, inputSymbolTable, -1);
- Tcl_DStringAppend (&linkCommandBuf, " -N -T XXXXXXXX ", -1);
- Tcl_DStringAppend (&linkCommandBuf, Tcl_GetString(pathPtr), -1);
- Tcl_DStringAppend (&linkCommandBuf, " ", -1);
-
- if (FindLibraries (interp, pathPtr, &linkCommandBuf) != TCL_OK) {
- Tcl_DStringFree (&linkCommandBuf);
- return TCL_ERROR;
- }
-
- linkCommand = Tcl_DStringValue (&linkCommandBuf);
-
- /* Determine the starting address, and plug it into the command */
-
- startAddress = (char *) (((unsigned long) sbrk (0)
- + TCL_LOADSHIM + TCL_LOADALIGN - 1)
- & (- TCL_LOADALIGN));
- p = strstr (linkCommand, "-T") + 3;
- sprintf (p, "%08lx", (long) startAddress);
- p [8] = ' ';
-
- /* Run the linker */
-
- status = Tcl_Eval (interp, linkCommand);
- Tcl_DStringFree (&linkCommandBuf);
- if (status != 0) {
- return TCL_ERROR;
- }
-
- /* Open the linker's result file and read the header */
-
- relocatedFd = open (relocatedFileName, O_RDONLY);
- if (relocatedFd < 0) {
- goto ioError;
- }
- status= read (relocatedFd, (char *) & relocatedHead, sizeof relocatedHead);
- if (status < sizeof relocatedHead) {
- goto ioError;
- }
-
- /* Check the magic number */
-
- if (relocatedHead.a_magic != OMAGIC) {
- Tcl_AppendResult (interp, "bad magic number in intermediate file \"",
- relocatedFileName, "\"", (char *) NULL);
- goto failure;
- }
-
- /* Make sure that memory allocation is still consistent */
-
- if ((unsigned long) sbrk (0) > (unsigned long) startAddress) {
- Tcl_SetResult (interp, "can't load, memory allocation is inconsistent.",
- TCL_STATIC);
- goto failure;
- }
-
- /* Make sure that the relocated module's size is reasonable */
-
- relocatedSize = relocatedHead.a_text + relocatedHead.a_data
- + relocatedHead.a_bss;
- if (relocatedSize > TCL_LOADMAX) {
- Tcl_SetResult (interp, "module too big to load", TCL_STATIC);
- goto failure;
- }
-
- /* Advance the break to protect the loaded module */
-
- (void) brk (startAddress + relocatedSize);
-
- /*
- * Seek to the start of the module's text.
- *
- * Note that this does not really work with large files (i.e. where
- * lseek64 exists and is different to lseek), but anyone trying to
- * dynamically load a binary that is larger than what can fit in
- * addressable memory is in trouble anyway...
- */
-
-#if defined(__mips) || defined(mips)
- status = lseek (relocatedFd,
- (off_t) N_TXTOFF (relocatedHead.ex_f, relocatedHead.ex_o),
- SEEK_SET);
-#else
- status = lseek (relocatedFd, (off_t) N_TXTOFF (relocatedHead), SEEK_SET);
-#endif
- if (status < 0) {
- goto ioError;
- }
-
- /* Read in the module's text and data */
-
- relocatedSize = relocatedHead.a_text + relocatedHead.a_data;
- if (read (relocatedFd, startAddress, relocatedSize) < relocatedSize) {
- brk (startAddress);
- ioError:
- Tcl_AppendResult (interp, "error on intermediate file \"",
- relocatedFileName, "\": ", Tcl_PosixError (interp),
- (char *) NULL);
- failure:
- (void) unlink (relocatedFileName);
- return TCL_ERROR;
- }
-
- /* Close the intermediate file. */
-
- (void) close (relocatedFd);
-
- /* Arrange things so that intermediate symbol tables eventually get
- * deleted. */
-
- if (SymbolTableFile != NULL) {
- UnlinkSymbolTable ();
- } else {
- atexit (UnlinkSymbolTable);
- }
- SymbolTableFile = ckalloc (strlen (relocatedFileName) + 1);
- strcpy (SymbolTableFile, relocatedFileName);
-
- *loadHandle = startAddress;
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpFindSymbol --
- *
- * Looks up a symbol, by name, through a handle associated with
- * a previously loaded piece of code (shared library).
- *
- * Results:
- * Returns a pointer to the function associated with 'symbol' if
- * it is found. Otherwise returns NULL and may leave an error
- * message in the interp's result.
- *
- *----------------------------------------------------------------------
- */
-Tcl_PackageInitProc*
-TclpFindSymbol(interp, loadHandle, symbol)
- Tcl_Interp *interp;
- Tcl_LoadHandle loadHandle;
- CONST char *symbol;
-{
- /* Look up the entry point in the load module's dictionary. */
- DictFn dictionary = (DictFn) loadHandle;
- return (Tcl_PackageInitProc*) dictionary(sym1);
-}
-
-
-/*
- *------------------------------------------------------------------------
- *
- * FindLibraries --
- *
- * Find the libraries needed to link a load module at run time.
- *
- * Results:
- * A standard Tcl completion code. If an error occurs,
- * an error message is left in the interp's result. The -l and -L
- * flags are concatenated onto the dynamic string `buf'.
- *
- *------------------------------------------------------------------------
- */
-
-static int
-FindLibraries (interp, pathPtr, buf)
- Tcl_Interp * interp; /* Used for error reporting */
- Tcl_Obj * pathPtr; /* Name of the load module */
- Tcl_DString * buf; /* Buffer where the -l an -L flags */
-{
- FILE * f; /* The load module */
- int c = 0; /* Byte from the load module */
- char * p;
- CONST char *native;
-
- char *fileName = Tcl_GetString(pathPtr);
-
- /* Open the load module */
-
- native = Tcl_FSGetNativePath(pathPtr);
- f = fopen(native, "rb"); /* INTL: Native. */
-
- if (f == NULL) {
- Tcl_AppendResult (interp, "couldn't open \"", fileName, "\": ",
- Tcl_PosixError (interp), (char *) NULL);
- return TCL_ERROR;
- }
-
- /* Search for the library list in the load module */
-
- p = "@LIBS: ";
- while (*p != '\0' && (c = getc (f)) != EOF) {
- if (c == *p) {
- ++p;
- }
- else {
- p = "@LIBS: ";
- if (c == *p) {
- ++p;
- }
- }
- }
-
- /* No library list -- this must be an ill-formed module */
-
- if (c == EOF) {
- Tcl_AppendResult (interp, "File \"", fileName,
- "\" is not a Tcl load module.", (char *) NULL);
- (void) fclose (f);
- return TCL_ERROR;
- }
-
- /* Accumulate the library list */
-
- while ((c = getc (f)) != '\0' && c != EOF) {
- char cc = c;
- Tcl_DStringAppend (buf, &cc, 1);
- }
- (void) fclose (f);
-
- if (c == EOF) {
- Tcl_AppendResult (interp, "Library directory in \"", fileName,
- "\" ends prematurely.", (char *) NULL);
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-/*
- *------------------------------------------------------------------------
- *
- * UnlinkSymbolTable --
- *
- * Remove the symbol table file from the last dynamic link.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The symbol table file from the last dynamic link is removed.
- * This function is called when (a) a new symbol table is present
- * because another dynamic link is complete, or (b) the process
- * is exiting.
- *------------------------------------------------------------------------
- */
-
-static void
-UnlinkSymbolTable ()
-{
- (void) unlink (SymbolTableFile);
- ckfree (SymbolTableFile);
- SymbolTableFile = NULL;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpUnloadFile --
- *
- * Unloads a dynamically loaded binary code file from memory.
- * Code pointers in the formerly loaded file are no longer valid
- * after calling this function.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Does nothing. Can anything be done?
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpUnloadFile(loadHandle)
- Tcl_LoadHandle loadHandle; /* loadHandle returned by a previous call
- * to TclpDlopen(). The loadHandle is
- * a token that represents the loaded
- * file. */
-{
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclGuessPackageName --
- *
- * If the "load" command is invoked without providing a package
- * name, this procedure is invoked to try to figure it out.
- *
- * Results:
- * Always returns 0 to indicate that we couldn't figure out a
- * package name; generic code will then try to guess the package
- * from the file name. A return value of 1 would have meant that
- * we figured out the package name and put it in bufPtr.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclGuessPackageName(fileName, bufPtr)
- CONST char *fileName; /* Name of file containing package (already
- * translated to local form if needed). */
- Tcl_DString *bufPtr; /* Initialized empty dstring. Append
- * package name to this if possible. */
-{
- CONST char *p, *q;
- char *r;
-
- if ((q = strrchr(fileName,'/'))) {
- q++;
- } else {
- q = fileName;
- }
- if (!strncmp(q,"lib",3)) {
- q+=3;
- }
- p = q;
- while ((*p) && (*p != '.') && ((*p<'0') || (*p>'9'))) {
- p++;
- }
- if ((p>q+2) && !strncmp(p-2,"_G0.",4)) {
- p-=2;
- }
- if (p<q) {
- return 0;
- }
-
- Tcl_DStringAppend(bufPtr,q, p-q);
-
- r = Tcl_DStringValue(bufPtr);
- r += strlen(r) - (p-q);
-
- /*
- * Capitalize the string and then recompute the length.
- */
-
- Tcl_UtfToTitle(r);
- Tcl_DStringSetLength(bufPtr, strlen(Tcl_DStringValue(bufPtr)));
-
- return 1;
-}
diff --git a/unix/tclLoadDl.c b/unix/tclLoadDl.c
index 9903d05..e38c280 100644
--- a/unix/tclLoadDl.c
+++ b/unix/tclLoadDl.c
@@ -1,14 +1,13 @@
-/*
+/*
* tclLoadDl.c --
*
- * This procedure provides a version of the TclLoadFile that
- * works with the "dlopen" and "dlsym" library procedures for
- * dynamic loading.
+ * This procedure provides a version of the TclLoadFile that works with
+ * the "dlopen" and "dlsym" library procedures for dynamic loading.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
@@ -19,18 +18,18 @@
#endif
/*
- * In some systems, like SunOS 4.1.3, the RTLD_NOW flag isn't defined
- * and this argument to dlopen must always be 1. The RTLD_GLOBAL
- * flag is needed on some systems (e.g. SCO and UnixWare) but doesn't
- * exist on others; if it doesn't exist, set it to 0 so it has no effect.
+ * In some systems, like SunOS 4.1.3, the RTLD_NOW flag isn't defined and this
+ * argument to dlopen must always be 1. The RTLD_LOCAL flag doesn't exist on
+ * some platforms; if it doesn't exist, set it to 0 so it has no effect.
+ * See [Bug #3216070]
*/
#ifndef RTLD_NOW
# define RTLD_NOW 1
#endif
-#ifndef RTLD_GLOBAL
-# define RTLD_GLOBAL 0
+#ifndef RTLD_LOCAL
+# define RTLD_LOCAL 0
#endif
/*
@@ -38,12 +37,12 @@
*
* TclpDlopen --
*
- * Dynamically loads a binary code file into memory and returns
- * a handle to the new code.
+ * Dynamically loads a binary code file into memory and returns a handle
+ * to the new code.
*
* Results:
- * A standard Tcl completion code. If an error occurs, an error
- * message is left in the interp's result.
+ * A standard Tcl completion code. If an error occurs, an error message
+ * is left in the interp's result.
*
* Side effects:
* New code suddenly appears in memory.
@@ -52,56 +51,65 @@
*/
int
-TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Obj *pathPtr; /* Name of the file containing the desired
+TclpDlopen(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *pathPtr, /* Name of the file containing the desired
* code (UTF-8). */
- Tcl_LoadHandle *loadHandle; /* Filled with token for dynamically loaded
- * file which will be passed back to
+ Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
+ * file which will be passed back to
* (*unloadProcPtr)() to unload the file. */
- Tcl_FSUnloadFileProc **unloadProcPtr;
+ Tcl_FSUnloadFileProc **unloadProcPtr)
/* Filled with address of Tcl_FSUnloadFileProc
- * function which should be used for
- * this file. */
+ * function which should be used for this
+ * file. */
{
- VOID *handle;
+ void *handle;
CONST char *native;
- /*
- * First try the full path the user gave us. This is particularly
- * important if the cwd is inside a vfs, and we are trying to load
- * using a relative path.
+ /*
+ * First try the full path the user gave us. This is particularly
+ * important if the cwd is inside a vfs, and we are trying to load using a
+ * relative path.
*/
+
native = Tcl_FSGetNativePath(pathPtr);
- handle = dlopen(native, RTLD_NOW | RTLD_GLOBAL);
+ /*
+ * Use (RTLD_NOW|RTLD_LOCAL) always, see [Bug #3216070]
+ */
+ handle = dlopen(native, RTLD_NOW | RTLD_LOCAL);
if (handle == NULL) {
- /*
- * Let the OS loader examine the binary search path for
- * whatever string the user gave us which hopefully refers
- * to a file on the binary path
+ /*
+ * Let the OS loader examine the binary search path for whatever
+ * string the user gave us which hopefully refers to a file on the
+ * binary path.
*/
+
Tcl_DString ds;
char *fileName = Tcl_GetString(pathPtr);
+
native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
- handle = dlopen(native, RTLD_NOW | RTLD_GLOBAL);
+ /*
+ * Use (RTLD_NOW|RTLD_LOCAL) always, see [Bug #3216070]
+ */
+ handle = dlopen(native, RTLD_NOW | RTLD_LOCAL);
Tcl_DStringFree(&ds);
}
-
+
if (handle == NULL) {
/*
* Write the string to a variable first to work around a compiler bug
* in the Sun Forte 6 compiler. [Bug 1503729]
*/
- CONST char *errorStr = dlerror();
+ const char *errorStr = dlerror();
- Tcl_AppendResult(interp, "couldn't load file \"",
- Tcl_GetString(pathPtr), "\": ", errorStr, (char *) NULL);
+ Tcl_AppendResult(interp, "couldn't load file \"",
+ Tcl_GetString(pathPtr), "\": ", errorStr, NULL);
return TCL_ERROR;
}
*unloadProcPtr = &TclpUnloadFile;
- *loadHandle = (Tcl_LoadHandle)handle;
+ *loadHandle = (Tcl_LoadHandle) handle;
return TCL_OK;
}
@@ -110,40 +118,42 @@ TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr)
*
* TclpFindSymbol --
*
- * Looks up a symbol, by name, through a handle associated with
- * a previously loaded piece of code (shared library).
+ * Looks up a symbol, by name, through a handle associated with a
+ * previously loaded piece of code (shared library).
*
* Results:
- * Returns a pointer to the function associated with 'symbol' if
- * it is found. Otherwise returns NULL and may leave an error
- * message in the interp's result.
+ * Returns a pointer to the function associated with 'symbol' if it is
+ * found. Otherwise returns NULL and may leave an error message in the
+ * interp's result.
*
*----------------------------------------------------------------------
*/
-Tcl_PackageInitProc*
-TclpFindSymbol(interp, loadHandle, symbol)
- Tcl_Interp *interp;
- Tcl_LoadHandle loadHandle;
- CONST char *symbol;
+
+Tcl_PackageInitProc *
+TclpFindSymbol(
+ Tcl_Interp *interp, /* Place to put error messages. */
+ Tcl_LoadHandle loadHandle, /* Value from TcpDlopen(). */
+ CONST char *symbol) /* Symbol to look up. */
{
CONST char *native;
Tcl_DString newName, ds;
VOID *handle = (VOID*)loadHandle;
Tcl_PackageInitProc *proc;
- /*
+
+ /*
* Some platforms still add an underscore to the beginning of symbol
- * names. If we can't find a name without an underscore, try again
- * with the underscore.
+ * names. If we can't find a name without an underscore, try again with
+ * the underscore.
*/
native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
proc = (Tcl_PackageInitProc *) dlsym(handle, /* INTL: Native. */
- native);
+ native);
if (proc == NULL) {
Tcl_DStringInit(&newName);
Tcl_DStringAppend(&newName, "_", 1);
native = Tcl_DStringAppend(&newName, native, -1);
- proc = (Tcl_PackageInitProc *) dlsym(handle, /* INTL: Native. */
+ proc = (Tcl_PackageInitProc *) dlsym(handle, /* INTL: Native. */
native);
Tcl_DStringFree(&newName);
}
@@ -157,9 +167,9 @@ TclpFindSymbol(interp, loadHandle, symbol)
*
* TclpUnloadFile --
*
- * Unloads a dynamically loaded binary code file from memory.
- * Code pointers in the formerly loaded file are no longer valid
- * after calling this function.
+ * Unloads a dynamically loaded binary code file from memory. Code
+ * pointers in the formerly loaded file are no longer valid after calling
+ * this function.
*
* Results:
* None.
@@ -171,15 +181,14 @@ TclpFindSymbol(interp, loadHandle, symbol)
*/
void
-TclpUnloadFile(loadHandle)
- Tcl_LoadHandle loadHandle; /* loadHandle returned by a previous call
- * to TclpDlopen(). The loadHandle is
- * a token that represents the loaded
- * file. */
+TclpUnloadFile(
+ Tcl_LoadHandle loadHandle) /* loadHandle returned by a previous call to
+ * TclpDlopen(). The loadHandle is a token
+ * that represents the loaded file. */
{
- VOID *handle;
+ void *handle;
- handle = (VOID *) loadHandle;
+ handle = (void *) loadHandle;
dlclose(handle);
}
@@ -188,14 +197,14 @@ TclpUnloadFile(loadHandle)
*
* TclGuessPackageName --
*
- * If the "load" command is invoked without providing a package
- * name, this procedure is invoked to try to figure it out.
+ * If the "load" command is invoked without providing a package name,
+ * this procedure is invoked to try to figure it out.
*
* Results:
- * Always returns 0 to indicate that we couldn't figure out a
- * package name; generic code will then try to guess the package
- * from the file name. A return value of 1 would have meant that
- * we figured out the package name and put it in bufPtr.
+ * Always returns 0 to indicate that we couldn't figure out a package
+ * name; generic code will then try to guess the package from the file
+ * name. A return value of 1 would have meant that we figured out the
+ * package name and put it in bufPtr.
*
* Side effects:
* None.
@@ -204,11 +213,19 @@ TclpUnloadFile(loadHandle)
*/
int
-TclGuessPackageName(fileName, bufPtr)
- CONST char *fileName; /* Name of file containing package (already
+TclGuessPackageName(
+ CONST char *fileName, /* Name of file containing package (already
* translated to local form if needed). */
- Tcl_DString *bufPtr; /* Initialized empty dstring. Append
- * package name to this if possible. */
+ Tcl_DString *bufPtr) /* Initialized empty dstring. Append package
+ * name to this if possible. */
{
return 0;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclLoadDld.c b/unix/tclLoadDld.c
deleted file mode 100644
index e53af2b..0000000
--- a/unix/tclLoadDld.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * tclLoadDld.c --
- *
- * This procedure provides a version of the TclLoadFile that
- * works with the "dld_link" and "dld_get_func" library procedures
- * for dynamic loading. It has been tested on Linux 1.1.95 and
- * dld-3.2.7. This file probably isn't needed anymore, since it
- * makes more sense to use "dl_open" etc.
- *
- * Copyright (c) 1995-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include "tclInt.h"
-#include "dld.h"
-
-/*
- * In some systems, like SunOS 4.1.3, the RTLD_NOW flag isn't defined
- * and this argument to dlopen must always be 1.
- */
-
-#ifndef RTLD_NOW
-# define RTLD_NOW 1
-#endif
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpDlopen --
- *
- * Dynamically loads a binary code file into memory and returns
- * a handle to the new code.
- *
- * Results:
- * A standard Tcl completion code. If an error occurs, an error
- * message is left in the interp's result.
- *
- * Side effects:
- * New code suddenly appears in memory.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Obj *pathPtr; /* Name of the file containing the desired
- * code (UTF-8). */
- Tcl_LoadHandle *loadHandle; /* Filled with token for dynamically loaded
- * file which will be passed back to
- * (*unloadProcPtr)() to unload the file. */
- Tcl_FSUnloadFileProc **unloadProcPtr;
- /* Filled with address of Tcl_FSUnloadFileProc
- * function which should be used for
- * this file. */
-{
- static int firstTime = 1;
- int returnCode;
- char *fileName;
- CONST char *native;
-
- /*
- * The dld package needs to know the pathname to the tcl binary.
- * If that's not known, return an error.
- */
-
- if (firstTime) {
- if (tclExecutableName == NULL) {
- Tcl_SetResult(interp,
- "don't know name of application binary file, so can't initialize dynamic loader",
- TCL_STATIC);
- return TCL_ERROR;
- }
- returnCode = dld_init(tclExecutableName);
- if (returnCode != 0) {
- Tcl_AppendResult(interp,
- "initialization failed for dynamic loader: ",
- dld_strerror(returnCode), (char *) NULL);
- return TCL_ERROR;
- }
- firstTime = 0;
- }
-
- fileName = Tcl_GetString(pathPtr);
-
- /*
- * First try the full path the user gave us. This is particularly
- * important if the cwd is inside a vfs, and we are trying to load
- * using a relative path.
- */
- native = Tcl_FSGetNativePath(pathPtr);
- returnCode = dld_link(native);
-
- if (returnCode != 0) {
- Tcl_DString ds;
- native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
- returnCode = dld_link(native);
- Tcl_DStringFree(&ds);
- }
-
- if (returnCode != 0) {
- Tcl_AppendResult(interp, "couldn't load file \"",
- fileName, "\": ",
- dld_strerror(returnCode), (char *) NULL);
- return TCL_ERROR;
- }
- *loadHandle = (Tcl_LoadHandle) strcpy(
- (char *) ckalloc((unsigned) (strlen(fileName) + 1)), fileName);
- *unloadProcPtr = &TclpUnloadFile;
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpFindSymbol --
- *
- * Looks up a symbol, by name, through a handle associated with
- * a previously loaded piece of code (shared library).
- *
- * Results:
- * Returns a pointer to the function associated with 'symbol' if
- * it is found. Otherwise returns NULL and may leave an error
- * message in the interp's result.
- *
- *----------------------------------------------------------------------
- */
-Tcl_PackageInitProc*
-TclpFindSymbol(interp, loadHandle, symbol)
- Tcl_Interp *interp;
- Tcl_LoadHandle loadHandle;
- CONST char *symbol;
-{
- return (Tcl_PackageInitProc *) dld_get_func(symbol);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpUnloadFile --
- *
- * Unloads a dynamically loaded binary code file from memory.
- * Code pointers in the formerly loaded file are no longer valid
- * after calling this function.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Code removed from memory.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpUnloadFile(loadHandle)
- Tcl_LoadHandle loadHandle; /* loadHandle returned by a previous call
- * to TclpDlopen(). The loadHandle is
- * a token that represents the loaded
- * file. */
-{
- char *fileName;
-
- handle = (char *) loadHandle;
- dld_unlink_by_file(handle, 0);
- ckfree(handle);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclGuessPackageName --
- *
- * If the "load" command is invoked without providing a package
- * name, this procedure is invoked to try to figure it out.
- *
- * Results:
- * Always returns 0 to indicate that we couldn't figure out a
- * package name; generic code will then try to guess the package
- * from the file name. A return value of 1 would have meant that
- * we figured out the package name and put it in bufPtr.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclGuessPackageName(fileName, bufPtr)
- CONST char *fileName; /* Name of file containing package (already
- * translated to local form if needed). */
- Tcl_DString *bufPtr; /* Initialized empty dstring. Append
- * package name to this if possible. */
-{
- return 0;
-}
diff --git a/unix/tclLoadDyld.c b/unix/tclLoadDyld.c
index cc02fc4..0a36215 100644
--- a/unix/tclLoadDyld.c
+++ b/unix/tclLoadDyld.c
@@ -14,7 +14,6 @@
*/
#include "tclInt.h"
-#include "tclPort.h"
#ifndef MODULE_SCOPE
#define MODULE_SCOPE extern
@@ -60,7 +59,6 @@ extern char *dlerror(void) WEAK_IMPORT_ATTRIBUTE;
#include <mach-o/swap.h>
#include <mach-o/arch.h>
#include <libkern/OSByteOrder.h>
-#undef panic
#include <mach/mach.h>
#include <stdbool.h>
@@ -198,6 +196,9 @@ TclpDlopen(
if (tclMacOSXDarwinRelease >= 8)
#endif
{
+ /*
+ * Use (RTLD_NOW|RTLD_LOCAL) always, see [Bug #3216070]
+ */
dlHandle = dlopen(nativePath, RTLD_NOW | RTLD_LOCAL);
if (!dlHandle) {
/*
@@ -208,6 +209,9 @@ TclpDlopen(
fileName = Tcl_GetString(pathPtr);
nativeFileName = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
+ /*
+ * Use (RTLD_NOW|RTLD_LOCAL) always, see [Bug #3216070]
+ */
dlHandle = dlopen(nativeFileName, RTLD_NOW | RTLD_LOCAL);
}
if (dlHandle) {
diff --git a/unix/tclLoadNext.c b/unix/tclLoadNext.c
index 7ba5eff..3de3cf1 100644
--- a/unix/tclLoadNext.c
+++ b/unix/tclLoadNext.c
@@ -1,14 +1,13 @@
-/*
+/*
* tclLoadNext.c --
*
- * This procedure provides a version of the TclLoadFile that
- * works with NeXTs rld_* dynamic loading. This file provided
- * by Pedja Bogdanovich.
+ * This procedure provides a version of the TclLoadFile that works with
+ * NeXTs rld_* dynamic loading. This file provided by Pedja Bogdanovich.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
@@ -20,12 +19,12 @@
*
* TclpDlopen --
*
- * Dynamically loads a binary code file into memory and returns
- * a handle to the new code.
+ * Dynamically loads a binary code file into memory and returns a handle
+ * to the new code.
*
* Results:
- * A standard Tcl completion code. If an error occurs, an error
- * message is left in the interp's result.
+ * A standard Tcl completion code. If an error occurs, an error message
+ * is left in the interp's result.
*
* Side effects:
* New code suddenly appears in memory.
@@ -34,65 +33,69 @@
*/
int
-TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Obj *pathPtr; /* Name of the file containing the desired
+TclpDlopen(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *pathPtr, /* Name of the file containing the desired
* code (UTF-8). */
- Tcl_LoadHandle *loadHandle; /* Filled with token for dynamically loaded
- * file which will be passed back to
+ Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
+ * file which will be passed back to
* (*unloadProcPtr)() to unload the file. */
- Tcl_FSUnloadFileProc **unloadProcPtr;
+ Tcl_FSUnloadFileProc **unloadProcPtr)
/* Filled with address of Tcl_FSUnloadFileProc
- * function which should be used for
- * this file. */
+ * function which should be used for this
+ * file. */
{
struct mach_header *header;
char *fileName;
char *files[2];
CONST char *native;
int result = 1;
-
+
NXStream *errorStream = NXOpenMemory(0,0,NX_READWRITE);
-
+
fileName = Tcl_GetString(pathPtr);
- /*
- * First try the full path the user gave us. This is particularly
- * important if the cwd is inside a vfs, and we are trying to load
- * using a relative path.
+ /*
+ * First try the full path the user gave us. This is particularly
+ * important if the cwd is inside a vfs, and we are trying to load using a
+ * relative path.
*/
+
native = Tcl_FSGetNativePath(pathPtr);
files = {native,NULL};
result = rld_load(errorStream, &header, files, NULL);
-
+
if (!result) {
- /*
- * Let the OS loader examine the binary search path for
- * whatever string the user gave us which hopefully refers
- * to a file on the binary path
+ /*
+ * Let the OS loader examine the binary search path for whatever
+ * string the user gave us which hopefully refers to a file on the
+ * binary path
*/
+
Tcl_DString ds;
+
native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
files = {native,NULL};
result = rld_load(errorStream, &header, files, NULL);
Tcl_DStringFree(&ds);
}
-
+
if (!result) {
char *data;
int len, maxlen;
+
NXGetMemoryBuffer(errorStream,&data,&len,&maxlen);
- Tcl_AppendResult(interp, "couldn't load file \"",
- fileName, "\": ", data, NULL);
+ Tcl_AppendResult(interp, "couldn't load file \"", fileName, "\": ",
+ data, NULL);
NXCloseMemory(errorStream, NX_FREEBUFFER);
return TCL_ERROR;
}
NXCloseMemory(errorStream, NX_FREEBUFFER);
-
+
*loadHandle = (Tcl_LoadHandle)1; /* A dummy non-NULL value */
*unloadProcPtr = &TclpUnloadFile;
-
+
return TCL_OK;
}
@@ -101,27 +104,31 @@ TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr)
*
* TclpFindSymbol --
*
- * Looks up a symbol, by name, through a handle associated with
- * a previously loaded piece of code (shared library).
+ * Looks up a symbol, by name, through a handle associated with a
+ * previously loaded piece of code (shared library).
*
* Results:
- * Returns a pointer to the function associated with 'symbol' if
- * it is found. Otherwise returns NULL and may leave an error
- * message in the interp's result.
+ * Returns a pointer to the function associated with 'symbol' if it is
+ * found. Otherwise returns NULL and may leave an error message in the
+ * interp's result.
*
*----------------------------------------------------------------------
*/
-Tcl_PackageInitProc*
-TclpFindSymbol(interp, loadHandle, symbol)
- Tcl_Interp *interp;
- Tcl_LoadHandle loadHandle;
- CONST char *symbol;
+
+Tcl_PackageInitProc *
+TclpFindSymbol(
+ Tcl_Interp *interp,
+ Tcl_LoadHandle loadHandle,
+ CONST char *symbol)
{
- Tcl_PackageInitProc *proc=NULL;
- if(symbol) {
- char sym[strlen(symbol)+2];
- sym[0]='_'; sym[1]=0; strcat(sym,symbol);
- rld_lookup(NULL,sym,(unsigned long *)&proc);
+ Tcl_PackageInitProc *proc = NULL;
+ if (symbol) {
+ char sym[strlen(symbol) + 2];
+
+ sym[0] = '_';
+ sym[1] = 0;
+ strcat(sym, symbol);
+ rld_lookup(NULL, sym, (unsigned long *)&proc);
}
return proc;
}
@@ -131,9 +138,9 @@ TclpFindSymbol(interp, loadHandle, symbol)
*
* TclpUnloadFile --
*
- * Unloads a dynamically loaded binary code file from memory.
- * Code pointers in the formerly loaded file are no longer valid
- * after calling this function.
+ * Unloads a dynamically loaded binary code file from memory. Code
+ * pointers in the formerly loaded file are no longer valid after calling
+ * this function.
*
* Results:
* None.
@@ -145,11 +152,10 @@ TclpFindSymbol(interp, loadHandle, symbol)
*/
void
-TclpUnloadFile(loadHandle)
- Tcl_LoadHandle loadHandle; /* loadHandle returned by a previous call
- * to TclpDlopen(). The loadHandle is
- * a token that represents the loaded
- * file. */
+TclpUnloadFile(
+ Tcl_LoadHandle loadHandle) /* loadHandle returned by a previous call to
+ * TclpDlopen(). The loadHandle is a token
+ * that represents the loaded file. */
{
}
@@ -158,14 +164,14 @@ TclpUnloadFile(loadHandle)
*
* TclGuessPackageName --
*
- * If the "load" command is invoked without providing a package
- * name, this procedure is invoked to try to figure it out.
+ * If the "load" command is invoked without providing a package name,
+ * this procedure is invoked to try to figure it out.
*
* Results:
- * Always returns 0 to indicate that we couldn't figure out a
- * package name; generic code will then try to guess the package
- * from the file name. A return value of 1 would have meant that
- * we figured out the package name and put it in bufPtr.
+ * Always returns 0 to indicate that we couldn't figure out a package
+ * name; generic code will then try to guess the package from the file
+ * name. A return value of 1 would have meant that we figured out the
+ * package name and put it in bufPtr.
*
* Side effects:
* None.
@@ -174,11 +180,19 @@ TclpUnloadFile(loadHandle)
*/
int
-TclGuessPackageName(fileName, bufPtr)
- CONST char *fileName; /* Name of file containing package (already
+TclGuessPackageName(
+ CONST char *fileName, /* Name of file containing package (already
* translated to local form if needed). */
- Tcl_DString *bufPtr; /* Initialized empty dstring. Append
- * package name to this if possible. */
+ Tcl_DString *bufPtr) /* Initialized empty dstring. Append package
+ * name to this if possible. */
{
return 0;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclLoadOSF.c b/unix/tclLoadOSF.c
index cee8c23..37536cf 100644
--- a/unix/tclLoadOSF.c
+++ b/unix/tclLoadOSF.c
@@ -1,10 +1,10 @@
-/*
+/*
* tclLoadOSF.c --
*
- * This procedure provides a version of the TclLoadFile that works
- * under OSF/1 1.0/1.1/1.2 and related systems, utilizing the old OSF/1
- * /sbin/loader and /usr/include/loader.h. OSF/1 versions from 1.3 and
- * on use ELF, rtld, and dlopen()[/usr/include/ldfcn.h].
+ * This function provides a version of the TclLoadFile that works under
+ * OSF/1 1.0/1.1/1.2 and related systems, utilizing the old OSF/1
+ * /sbin/loader and /usr/include/loader.h. OSF/1 versions from 1.3 and on
+ * use ELF, rtld, and dlopen()[/usr/include/ldfcn.h].
*
* This is useful for:
* OSF/1 1.0, 1.1, 1.2 (from OSF)
@@ -13,23 +13,23 @@
* HP OSF/1 1.0 ("Acorn") using COFF
*
* This is likely to be useful for:
- * Paragon OSF/1 (from Intel)
- * HI-OSF/1 (from Hitachi)
+ * Paragon OSF/1 (from Intel)
+ * HI-OSF/1 (from Hitachi)
*
* This is NOT to be used on:
* Digitial Alpha OSF/1 systems
* OSF/1 1.3 or later (from OSF) using ELF
* includes: MK6, MK7, AD2, AD3 (from OSF RI)
*
- * This approach to things was utter @&^#; thankfully,
- * OSF/1 eventually supported dlopen().
+ * This approach to things was utter @&^#; thankfully, OSF/1 eventually
+ * supported dlopen().
*
* John Robert LoVerso <loverso@freebsd.osf.org>
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
@@ -41,12 +41,12 @@
*
* TclpDlopen --
*
- * Dynamically loads a binary code file into memory and returns
- * a handle to the new code.
+ * Dynamically loads a binary code file into memory and returns a handle
+ * to the new code.
*
* Results:
- * A standard Tcl completion code. If an error occurs, an error
- * message is left in the interp's result.
+ * A standard Tcl completion code. If an error occurs, an error message
+ * is left in the interp's result.
*
* Side effects:
* New code suddenly appears in memory.
@@ -55,59 +55,63 @@
*/
int
-TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Obj *pathPtr; /* Name of the file containing the desired
+TclpDlopen(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *pathPtr, /* Name of the file containing the desired
* code (UTF-8). */
- Tcl_LoadHandle *loadHandle; /* Filled with token for dynamically loaded
- * file which will be passed back to
+ Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
+ * file which will be passed back to
* (*unloadProcPtr)() to unload the file. */
- Tcl_FSUnloadFileProc **unloadProcPtr;
+ Tcl_FSUnloadFileProc **unloadProcPtr)
/* Filled with address of Tcl_FSUnloadFileProc
- * function which should be used for
- * this file. */
+ * function which should be used for this
+ * file. */
{
ldr_module_t lm;
char *pkg;
char *fileName = Tcl_GetString(pathPtr);
CONST char *native;
- /*
+ /*
* First try the full path the user gave us. This is particularly
- * important if the cwd is inside a vfs, and we are trying to load
- * using a relative path.
+ * important if the cwd is inside a vfs, and we are trying to load using a
+ * relative path.
*/
+
native = Tcl_FSGetNativePath(pathPtr);
lm = (Tcl_PackageInitProc *) load(native, LDR_NOFLAGS);
if (lm == LDR_NULL_MODULE) {
- /*
- * Let the OS loader examine the binary search path for
- * whatever string the user gave us which hopefully refers
- * to a file on the binary path
+ /*
+ * Let the OS loader examine the binary search path for whatever
+ * string the user gave us which hopefully refers to a file on the
+ * binary path
*/
+
Tcl_DString ds;
+
native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
lm = (Tcl_PackageInitProc *) load(native, LDR_NOFLAGS);
Tcl_DStringFree(&ds);
}
-
+
if (lm == LDR_NULL_MODULE) {
- Tcl_AppendResult(interp, "couldn't load file \"", fileName,
- "\": ", Tcl_PosixError (interp), (char *) NULL);
+ Tcl_AppendResult(interp, "couldn't load file \"", fileName, "\": ",
+ Tcl_PosixError(interp), NULL);
return TCL_ERROR;
}
*clientDataPtr = NULL;
-
+
/*
* My convention is to use a [OSF loader] package name the same as shlib,
* since the idiots never implemented ldr_lookup() and it is otherwise
* impossible to get a package name given a module.
*
- * I build loadable modules with a makefile rule like
+ * I build loadable modules with a makefile rule like
* ld ... -export $@: -o $@ $(OBJS)
*/
+
if ((pkg = strrchr(fileName, '/')) == NULL) {
pkg = fileName;
} else {
@@ -123,21 +127,22 @@ TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr)
*
* TclpFindSymbol --
*
- * Looks up a symbol, by name, through a handle associated with
- * a previously loaded piece of code (shared library).
+ * Looks up a symbol, by name, through a handle associated with a
+ * previously loaded piece of code (shared library).
*
* Results:
- * Returns a pointer to the function associated with 'symbol' if
- * it is found. Otherwise returns NULL and may leave an error
- * message in the interp's result.
+ * Returns a pointer to the function associated with 'symbol' if it is
+ * found. Otherwise returns NULL and may leave an error message in the
+ * interp's result.
*
*----------------------------------------------------------------------
*/
-Tcl_PackageInitProc*
-TclpFindSymbol(interp, loadHandle, symbol)
- Tcl_Interp *interp;
- Tcl_LoadHandle loadHandle;
- CONST char *symbol;
+
+Tcl_PackageInitProc *
+TclpFindSymbol(
+ Tcl_Interp *interp,
+ Tcl_LoadHandle loadHandle,
+ CONST char *symbol)
{
return ldr_lookup_package((char *)loadHandle, symbol);
}
@@ -147,9 +152,9 @@ TclpFindSymbol(interp, loadHandle, symbol)
*
* TclpUnloadFile --
*
- * Unloads a dynamically loaded binary code file from memory.
- * Code pointers in the formerly loaded file are no longer valid
- * after calling this function.
+ * Unloads a dynamically loaded binary code file from memory. Code
+ * pointers in the formerly loaded file are no longer valid after calling
+ * this function.
*
* Results:
* None.
@@ -161,11 +166,10 @@ TclpFindSymbol(interp, loadHandle, symbol)
*/
void
-TclpUnloadFile(loadHandle)
- Tcl_LoadHandle loadHandle; /* loadHandle returned by a previous call
- * to TclpDlopen(). The loadHandle is
- * a token that represents the loaded
- * file. */
+TclpUnloadFile(
+ Tcl_LoadHandle loadHandle) /* loadHandle returned by a previous call to
+ * TclpDlopen(). The loadHandle is a token
+ * that represents the loaded file. */
{
}
@@ -174,14 +178,14 @@ TclpUnloadFile(loadHandle)
*
* TclGuessPackageName --
*
- * If the "load" command is invoked without providing a package
- * name, this procedure is invoked to try to figure it out.
+ * If the "load" command is invoked without providing a package name,
+ * this function is invoked to try to figure it out.
*
* Results:
- * Always returns 0 to indicate that we couldn't figure out a
- * package name; generic code will then try to guess the package
- * from the file name. A return value of 1 would have meant that
- * we figured out the package name and put it in bufPtr.
+ * Always returns 0 to indicate that we couldn't figure out a package
+ * name; generic code will then try to guess the package from the file
+ * name. A return value of 1 would have meant that we figured out the
+ * package name and put it in bufPtr.
*
* Side effects:
* None.
@@ -190,11 +194,19 @@ TclpUnloadFile(loadHandle)
*/
int
-TclGuessPackageName(fileName, bufPtr)
- CONST char *fileName; /* Name of file containing package (already
+TclGuessPackageName(
+ CONST char *fileName, /* Name of file containing package (already
* translated to local form if needed). */
- Tcl_DString *bufPtr; /* Initialized empty dstring. Append
- * package name to this if possible. */
+ Tcl_DString *bufPtr) /* Initialized empty dstring. Append package
+ * name to this if possible. */
{
return 0;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclLoadShl.c b/unix/tclLoadShl.c
index 373bc05..c9e4e27 100644
--- a/unix/tclLoadShl.c
+++ b/unix/tclLoadShl.c
@@ -1,14 +1,14 @@
-/*
+/*
* tclLoadShl.c --
*
- * This procedure provides a version of the TclLoadFile that works
- * with the "shl_load" and "shl_findsym" library procedures for
- * dynamic loading (e.g. for HP machines).
+ * This procedure provides a version of the TclLoadFile that works with
+ * the "shl_load" and "shl_findsym" library procedures for dynamic
+ * loading (e.g. for HP machines).
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <dl.h>
@@ -28,12 +28,12 @@
*
* TclpDlopen --
*
- * Dynamically loads a binary code file into memory and returns
- * a handle to the new code.
+ * Dynamically loads a binary code file into memory and returns a handle
+ * to the new code.
*
* Results:
- * A standard Tcl completion code. If an error occurs, an error
- * message is left in the interp's result.
+ * A standard Tcl completion code. If an error occurs, an error message
+ * is left in the interp's result.
*
* Side effects:
* New code suddenly appears in memory.
@@ -42,57 +42,57 @@
*/
int
-TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr)
- Tcl_Interp *interp; /* Used for error reporting. */
- Tcl_Obj *pathPtr; /* Name of the file containing the desired
+TclpDlopen(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *pathPtr, /* Name of the file containing the desired
* code (UTF-8). */
- Tcl_LoadHandle *loadHandle; /* Filled with token for dynamically loaded
- * file which will be passed back to
+ Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
+ * file which will be passed back to
* (*unloadProcPtr)() to unload the file. */
- Tcl_FSUnloadFileProc **unloadProcPtr;
+ Tcl_FSUnloadFileProc **unloadProcPtr)
/* Filled with address of Tcl_FSUnloadFileProc
- * function which should be used for
- * this file. */
+ * function which should be used for this
+ * file. */
{
shl_t handle;
CONST char *native;
char *fileName = Tcl_GetString(pathPtr);
/*
- * The flags below used to be BIND_IMMEDIATE; they were changed at
- * the suggestion of Wolfgang Kechel (wolfgang@prs.de): "This
- * enables verbosity for missing symbols when loading a shared lib
- * and allows to load libtk8.0.sl into tclsh8.0 without problems.
- * In general, this delays resolving symbols until they are actually
- * needed. Shared libs do no longer need all libraries linked in
- * when they are build."
+ * The flags below used to be BIND_IMMEDIATE; they were changed at the
+ * suggestion of Wolfgang Kechel (wolfgang@prs.de): "This enables
+ * verbosity for missing symbols when loading a shared lib and allows to
+ * load libtk8.0.sl into tclsh8.0 without problems. In general, this
+ * delays resolving symbols until they are actually needed. Shared libs
+ * do no longer need all libraries linked in when they are build."
*/
-
/*
* First try the full path the user gave us. This is particularly
- * important if the cwd is inside a vfs, and we are trying to load
- * using a relative path.
+ * important if the cwd is inside a vfs, and we are trying to load using a
+ * relative path.
*/
+
native = Tcl_FSGetNativePath(pathPtr);
handle = shl_load(native, BIND_DEFERRED|BIND_VERBOSE, 0L);
if (handle == NULL) {
/*
- * Let the OS loader examine the binary search path for
- * whatever string the user gave us which hopefully refers
- * to a file on the binary path
+ * Let the OS loader examine the binary search path for whatever
+ * string the user gave us which hopefully refers to a file on the
+ * binary path.
*/
+
Tcl_DString ds;
+
native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
- handle = shl_load(native,
- BIND_DEFERRED|BIND_VERBOSE|DYNAMIC_PATH, 0L);
+ handle = shl_load(native, BIND_DEFERRED|BIND_VERBOSE|DYNAMIC_PATH, 0L);
Tcl_DStringFree(&ds);
}
if (handle == NULL) {
- Tcl_AppendResult(interp, "couldn't load file \"", fileName,
- "\": ", Tcl_PosixError(interp), (char *) NULL);
+ Tcl_AppendResult(interp, "couldn't load file \"", fileName, "\": ",
+ Tcl_PosixError(interp), (char *) NULL);
return TCL_ERROR;
}
*loadHandle = (Tcl_LoadHandle) handle;
@@ -105,33 +105,34 @@ TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr)
*
* TclpFindSymbol --
*
- * Looks up a symbol, by name, through a handle associated with
- * a previously loaded piece of code (shared library).
+ * Looks up a symbol, by name, through a handle associated with a
+ * previously loaded piece of code (shared library).
*
* Results:
- * Returns a pointer to the function associated with 'symbol' if
- * it is found. Otherwise returns NULL and may leave an error
- * message in the interp's result.
+ * Returns a pointer to the function associated with 'symbol' if it is
+ * found. Otherwise returns NULL and may leave an error message in the
+ * interp's result.
*
*----------------------------------------------------------------------
*/
-Tcl_PackageInitProc*
-TclpFindSymbol(interp, loadHandle, symbol)
- Tcl_Interp *interp;
- Tcl_LoadHandle loadHandle;
- CONST char *symbol;
+
+Tcl_PackageInitProc *
+TclpFindSymbol(
+ Tcl_Interp *interp,
+ Tcl_LoadHandle loadHandle,
+ CONST char *symbol)
{
Tcl_DString newName;
- Tcl_PackageInitProc *proc=NULL;
+ Tcl_PackageInitProc *proc = NULL;
shl_t handle = (shl_t)loadHandle;
+
/*
- * Some versions of the HP system software still use "_" at the
- * beginning of exported symbols while others don't; try both
- * forms of each name.
+ * Some versions of the HP system software still use "_" at the beginning
+ * of exported symbols while others don't; try both forms of each name.
*/
- if (shl_findsym(&handle, symbol, (short) TYPE_PROCEDURE, (void *) &proc)
- != 0) {
+ if (shl_findsym(&handle, symbol, (short) TYPE_PROCEDURE,
+ (void *) &proc) != 0) {
Tcl_DStringInit(&newName);
Tcl_DStringAppend(&newName, "_", 1);
Tcl_DStringAppend(&newName, symbol, -1);
@@ -149,9 +150,9 @@ TclpFindSymbol(interp, loadHandle, symbol)
*
* TclpUnloadFile --
*
- * Unloads a dynamically loaded binary code file from memory.
- * Code pointers in the formerly loaded file are no longer valid
- * after calling this function.
+ * Unloads a dynamically loaded binary code file from memory. Code
+ * pointers in the formerly loaded file are no longer valid after calling
+ * this function.
*
* Results:
* None.
@@ -163,11 +164,10 @@ TclpFindSymbol(interp, loadHandle, symbol)
*/
void
-TclpUnloadFile(loadHandle)
- Tcl_LoadHandle loadHandle; /* loadHandle returned by a previous call
- * to TclpDlopen(). The loadHandle is
- * a token that represents the loaded
- * file. */
+TclpUnloadFile(
+ Tcl_LoadHandle loadHandle) /* loadHandle returned by a previous call to
+ * TclpDlopen(). The loadHandle is a token
+ * that represents the loaded file. */
{
shl_t handle;
@@ -180,14 +180,14 @@ TclpUnloadFile(loadHandle)
*
* TclGuessPackageName --
*
- * If the "load" command is invoked without providing a package
- * name, this procedure is invoked to try to figure it out.
+ * If the "load" command is invoked without providing a package name,
+ * this procedure is invoked to try to figure it out.
*
* Results:
- * Always returns 0 to indicate that we couldn't figure out a
- * package name; generic code will then try to guess the package
- * from the file name. A return value of 1 would have meant that
- * we figured out the package name and put it in bufPtr.
+ * Always returns 0 to indicate that we couldn't figure out a package
+ * name; generic code will then try to guess the package from the file
+ * name. A return value of 1 would have meant that we figured out the
+ * package name and put it in bufPtr.
*
* Side effects:
* None.
@@ -196,11 +196,19 @@ TclpUnloadFile(loadHandle)
*/
int
-TclGuessPackageName(fileName, bufPtr)
- CONST char *fileName; /* Name of file containing package (already
+TclGuessPackageName(
+ CONST char *fileName, /* Name of file containing package (already
* translated to local form if needed). */
- Tcl_DString *bufPtr; /* Initialized empty dstring. Append
- * package name to this if possible. */
+ Tcl_DString *bufPtr) /* Initialized empty dstring. Append package
+ * name to this if possible. */
{
return 0;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixChan.c b/unix/tclUnixChan.c
index 3c6adb5..53c5c47 100644
--- a/unix/tclUnixChan.c
+++ b/unix/tclUnixChan.c
@@ -1,47 +1,28 @@
-/*
+/*
* tclUnixChan.c
*
- * Common channel driver for Unix channels based on files, command
- * pipes and TCP sockets.
+ * Common channel driver for Unix channels based on files, command pipes
+ * and TCP sockets.
*
* Copyright (c) 1995-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.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h" /* Internal definitions for Tcl. */
-#include "tclPort.h" /* Portability features for Tcl. */
#include "tclIO.h" /* To get Channel type declaration. */
-/*
- * sys/ioctl.h has already been included by tclPort.h. Including termios.h
- * or termio.h causes a bunch of warning messages because some duplicate
- * (but not contradictory) #defines exist in termios.h and/or termio.h
- */
-#undef NL0
-#undef NL1
-#undef CR0
-#undef CR1
-#undef CR2
-#undef CR3
-#undef TAB0
-#undef TAB1
-#undef TAB2
-#undef XTABS
-#undef BS0
-#undef BS1
-#undef FF0
-#undef FF1
-#undef ECHO
-#undef NOFLSH
-#undef TOSTOP
-#undef FLUSHO
-#undef PENDIN
-
#define SUPPORTS_TTY
+#undef DIRECT_BAUD
+#ifdef B4800
+# if (B4800 == 4800)
+# define DIRECT_BAUD
+# endif /* B4800 == 4800 */
+#endif /* B4800 */
+
#ifdef USE_TERMIOS
# include <termios.h>
# ifdef HAVE_SYS_IOCTL_H
@@ -55,22 +36,7 @@
# define SETIOSTATE(fd, statePtr) tcsetattr((fd), TCSADRAIN, (statePtr))
# define GETCONTROL(fd, intPtr) ioctl((fd), TIOCMGET, (intPtr))
# define SETCONTROL(fd, intPtr) ioctl((fd), TIOCMSET, (intPtr))
- /*
- * TIP #35 introduced a different on exit flush/close behavior that
- * doesn't work correctly with standard channels on all systems.
- * The problem is tcflush throws away waiting channel data. This may
- * be necessary for true serial channels that may block, but isn't
- * correct in the standard case. This might be replaced with tcdrain
- * instead, but that can block. For now, we revert to making this do
- * nothing, and TtyOutputProc being the same old FileOutputProc.
- * -- hobbs [Bug #525783]
- */
-# define BAD_TIP35_FLUSH 0
-# if BAD_TIP35_FLUSH
-# define TTYFLUSH(fd) tcflush((fd), TCIOFLUSH);
-# else
-# define TTYFLUSH(fd)
-# endif /* BAD_TIP35_FLUSH */
+
# ifdef FIONREAD
# define GETREADQUEUE(fd, int) ioctl((fd), FIONREAD, &(int))
# elif defined(FIORDCHK)
@@ -80,10 +46,12 @@
# define GETWRITEQUEUE(fd, int) ioctl((fd), TIOCOUTQ, &(int))
# endif /* TIOCOUTQ */
# if defined(TIOCSBRK) && defined(TIOCCBRK)
+
/*
- * Can't use ?: operator below because that messes up types on either
- * Linux or Solaris (the two are mutually exclusive!)
+ * Can't use ?: operator below because that messes up types on either Linux or
+ * Solaris (the two are mutually exclusive!)
*/
+
# define SETBREAK(fd, flag) \
if (flag) { \
ioctl((fd), TIOCSBRK, NULL); \
@@ -119,6 +87,15 @@
#endif /* !USE_TERMIOS */
/*
+ * Helper macros to make parts of this file clearer. The macros do exactly
+ * what they say on the tin. :-) They also only ever refer to their arguments
+ * once, and so can be used without regard to side effects.
+ */
+
+#define SET_BITS(var, bits) ((var) |= (bits))
+#define CLEAR_BITS(var, bits) ((var) &= ~(bits))
+
+/*
* This structure describes per-instance state of a file based channel.
*/
@@ -128,10 +105,6 @@ typedef struct FileState {
int validMask; /* OR'ed combination of TCL_READABLE,
* TCL_WRITABLE, or TCL_EXCEPTION: indicates
* which operations are valid on the file. */
-#ifdef DEPRECATED
- struct FileState *nextPtr; /* Pointer to next file in list of all
- * file channels. */
-#endif /* DEPRECATED */
} FileState;
#ifdef SUPPORTS_TTY
@@ -142,17 +115,15 @@ typedef struct FileState {
*/
typedef struct TtyState {
- FileState fs; /* Per-instance state of the file
- * descriptor. Must be the first field. */
- int stateUpdated; /* Flag to say if the state has been
- * modified and needs resetting. */
- IOSTATE savedState; /* Initial state of device. Used to reset
+ FileState fs; /* Per-instance state of the file descriptor.
+ * Must be the first field. */
+ IOSTATE savedState; /* Initial state of device. Used to reset
* state when device closed. */
} TtyState;
/*
- * The following structure is used to set or get the serial port
- * attributes in a platform-independant manner.
+ * The following structure is used to set or get the serial port attributes in
+ * a platform-independant manner.
*/
typedef struct TtyAttrs {
@@ -165,23 +136,10 @@ typedef struct TtyAttrs {
#endif /* !SUPPORTS_TTY */
#define UNSUPPORTED_OPTION(detail) \
- if (interp) { \
- Tcl_AppendResult(interp, (detail), \
- " not supported for this platform", (char *) NULL); \
- }
-
-#ifdef DEPRECATED
-typedef struct ThreadSpecificData {
- /*
- * List of all file channels currently open. This is per thread and is
- * used to match up fd's to channels, which rarely occurs.
- */
-
- FileState *firstFilePtr;
-} ThreadSpecificData;
-
-static Tcl_ThreadDataKey dataKey;
-#endif /* DEPRECATED */
+ if (interp) { \
+ Tcl_AppendResult(interp, (detail), \
+ " not supported for this platform", NULL); \
+ }
/*
* This structure describes per-instance state of a tcp based channel.
@@ -190,8 +148,8 @@ static Tcl_ThreadDataKey dataKey;
typedef struct TcpState {
Tcl_Channel channel; /* Channel associated with this file. */
int fd; /* The socket itself. */
- int flags; /* ORed combination of the bitfields
- * defined below. */
+ int flags; /* ORed combination of the bitfields defined
+ * below. */
Tcl_TcpAcceptProc *acceptProc;
/* Proc to call on accept. */
ClientData acceptProcData; /* The data for the accept proc. */
@@ -206,10 +164,10 @@ typedef struct TcpState {
#define TCP_ASYNC_CONNECT (1<<1) /* Async connect in progress. */
/*
- * The following defines the maximum length of the listen queue. This is
- * the number of outstanding yet-to-be-serviced requests for a connection
- * on a server socket, more than this number of outstanding requests and
- * the connection request will fail.
+ * The following defines the maximum length of the listen queue. This is the
+ * number of outstanding yet-to-be-serviced requests for a connection on a
+ * server socket, more than this number of outstanding requests and the
+ * connection request will fail.
*/
#ifndef SOMAXCONN
@@ -222,8 +180,8 @@ typedef struct TcpState {
#endif /* SOMAXCONN < 100 */
/*
- * The following defines how much buffer space the kernel should maintain
- * for a socket.
+ * The following defines how much buffer space the kernel should maintain for
+ * a socket.
*/
#define SOCKET_BUFSIZE 4096
@@ -232,77 +190,64 @@ typedef struct TcpState {
* Static routines for this file:
*/
-static TcpState * CreateSocket _ANSI_ARGS_((Tcl_Interp *interp,
- int port, CONST char *host, int server,
- CONST char *myaddr, int myport, int async));
-static int CreateSocketAddress _ANSI_ARGS_(
- (struct sockaddr_in *sockaddrPtr,
- CONST char *host, int port));
-static int FileBlockModeProc _ANSI_ARGS_((
- ClientData instanceData, int mode));
-static int FileCloseProc _ANSI_ARGS_((ClientData instanceData,
- Tcl_Interp *interp));
-static int FileGetHandleProc _ANSI_ARGS_((ClientData instanceData,
- int direction, ClientData *handlePtr));
-static int FileInputProc _ANSI_ARGS_((ClientData instanceData,
- char *buf, int toRead, int *errorCode));
-static int FileOutputProc _ANSI_ARGS_((
- ClientData instanceData, CONST char *buf,
- int toWrite, int *errorCode));
-static int FileSeekProc _ANSI_ARGS_((ClientData instanceData,
- long offset, int mode, int *errorCode));
-#ifdef DEPRECATED
-static void FileThreadActionProc _ANSI_ARGS_ ((
- ClientData instanceData, int action));
-#endif
-static Tcl_WideInt FileWideSeekProc _ANSI_ARGS_((ClientData instanceData,
- Tcl_WideInt offset, int mode, int *errorCode));
-static void FileWatchProc _ANSI_ARGS_((ClientData instanceData,
- int mask));
-static void TcpAccept _ANSI_ARGS_((ClientData data, int mask));
-static int TcpBlockModeProc _ANSI_ARGS_((ClientData data,
- int mode));
-static int TcpCloseProc _ANSI_ARGS_((ClientData instanceData,
- Tcl_Interp *interp));
-static int TcpGetHandleProc _ANSI_ARGS_((ClientData instanceData,
- int direction, ClientData *handlePtr));
-static int TcpGetOptionProc _ANSI_ARGS_((ClientData instanceData,
- Tcl_Interp *interp, CONST char *optionName,
- Tcl_DString *dsPtr));
-static int TcpInputProc _ANSI_ARGS_((ClientData instanceData,
- char *buf, int toRead, int *errorCode));
-static int TcpOutputProc _ANSI_ARGS_((ClientData instanceData,
- CONST char *buf, int toWrite, int *errorCode));
-static void TcpWatchProc _ANSI_ARGS_((ClientData instanceData,
- int mask));
+static TcpState * CreateSocket(Tcl_Interp *interp, int port,
+ const char *host, int server, const char *myaddr,
+ int myport, int async);
+static int CreateSocketAddress(struct sockaddr_in *sockaddrPtr,
+ const char *host, int port, int willBind,
+ const char **errorMsgPtr);
+static int FileBlockModeProc(ClientData instanceData, int mode);
+static int FileCloseProc(ClientData instanceData,
+ Tcl_Interp *interp);
+static int FileGetHandleProc(ClientData instanceData,
+ int direction, ClientData *handlePtr);
+static int FileInputProc(ClientData instanceData, char *buf,
+ int toRead, int *errorCode);
+static int FileOutputProc(ClientData instanceData,
+ const char *buf, int toWrite, int *errorCode);
+static int FileSeekProc(ClientData instanceData, long offset,
+ int mode, int *errorCode);
+static int FileTruncateProc(ClientData instanceData,
+ Tcl_WideInt length);
+static Tcl_WideInt FileWideSeekProc(ClientData instanceData,
+ Tcl_WideInt offset, int mode, int *errorCode);
+static void FileWatchProc(ClientData instanceData, int mask);
+static void TcpAccept(ClientData data, int mask);
+static int TcpBlockModeProc(ClientData data, int mode);
+static int TcpCloseProc(ClientData instanceData,
+ Tcl_Interp *interp);
+static int TcpGetHandleProc(ClientData instanceData,
+ int direction, ClientData *handlePtr);
+static int TcpGetOptionProc(ClientData instanceData,
+ Tcl_Interp *interp, const char *optionName,
+ Tcl_DString *dsPtr);
+static int TcpInputProc(ClientData instanceData, char *buf,
+ int toRead, int *errorCode);
+static int TcpOutputProc(ClientData instanceData,
+ const char *buf, int toWrite, int *errorCode);
+static void TcpWatchProc(ClientData instanceData, int mask);
#ifdef SUPPORTS_TTY
-static int TtyCloseProc _ANSI_ARGS_((ClientData instanceData,
- Tcl_Interp *interp));
-static void TtyGetAttributes _ANSI_ARGS_((int fd,
- TtyAttrs *ttyPtr));
-static int TtyGetOptionProc _ANSI_ARGS_((ClientData instanceData,
- Tcl_Interp *interp, CONST char *optionName,
- Tcl_DString *dsPtr));
-static FileState * TtyInit _ANSI_ARGS_((int fd, int initialize));
-#if BAD_TIP35_FLUSH
-static int TtyOutputProc _ANSI_ARGS_((ClientData instanceData,
- CONST char *buf, int toWrite, int *errorCode));
-#endif /* BAD_TIP35_FLUSH */
-static int TtyParseMode _ANSI_ARGS_((Tcl_Interp *interp,
- CONST char *mode, int *speedPtr, int *parityPtr,
- int *dataPtr, int *stopPtr));
-static void TtySetAttributes _ANSI_ARGS_((int fd,
- TtyAttrs *ttyPtr));
-static int TtySetOptionProc _ANSI_ARGS_((ClientData instanceData,
- Tcl_Interp *interp, CONST char *optionName,
- CONST char *value));
+static void TtyGetAttributes(int fd, TtyAttrs *ttyPtr);
+static int TtyGetOptionProc(ClientData instanceData,
+ Tcl_Interp *interp, const char *optionName,
+ Tcl_DString *dsPtr);
+#ifndef DIRECT_BAUD
+static int TtyGetBaud(unsigned long speed);
+static unsigned long TtyGetSpeed(int baud);
+#endif /* DIRECT_BAUD */
+static FileState * TtyInit(int fd, int initialize);
+static void TtyModemStatusStr(int status, Tcl_DString *dsPtr);
+static int TtyParseMode(Tcl_Interp *interp, const char *mode,
+ int *speedPtr, int *parityPtr, int *dataPtr,
+ int *stopPtr);
+static void TtySetAttributes(int fd, TtyAttrs *ttyPtr);
+static int TtySetOptionProc(ClientData instanceData,
+ Tcl_Interp *interp, const char *optionName,
+ const char *value);
#endif /* SUPPORTS_TTY */
-static int WaitForConnect _ANSI_ARGS_((TcpState *statePtr,
- int *errorCodePtr));
-static Tcl_Channel MakeTcpClientChannelMode _ANSI_ARGS_(
- (ClientData tcpSocket,
- int mode));
-
+static int WaitForConnect(TcpState *statePtr, int *errorCodePtr);
+static Tcl_Channel MakeTcpClientChannelMode(ClientData tcpSocket,
+ int mode);
/*
* This structure describes the channel type structure for file based IO:
@@ -310,7 +255,7 @@ static Tcl_Channel MakeTcpClientChannelMode _ANSI_ARGS_(
static Tcl_ChannelType fileChannelType = {
"file", /* Type name. */
- TCL_CHANNEL_VERSION_4, /* v4 channel */
+ TCL_CHANNEL_VERSION_5, /* v5 channel */
FileCloseProc, /* Close proc. */
FileInputProc, /* Input proc. */
FileOutputProc, /* Output proc. */
@@ -324,11 +269,8 @@ static Tcl_ChannelType fileChannelType = {
NULL, /* flush proc. */
NULL, /* handler proc. */
FileWideSeekProc, /* wide seek proc. */
-#ifdef DEPRECATED
- FileThreadActionProc, /* thread actions */
-#else
NULL,
-#endif
+ FileTruncateProc, /* truncate proc. */
};
#ifdef SUPPORTS_TTY
@@ -339,14 +281,10 @@ static Tcl_ChannelType fileChannelType = {
static Tcl_ChannelType ttyChannelType = {
"tty", /* Type name. */
- TCL_CHANNEL_VERSION_4, /* v4 channel */
- TtyCloseProc, /* Close proc. */
+ TCL_CHANNEL_VERSION_5, /* v5 channel */
+ FileCloseProc, /* Close proc. */
FileInputProc, /* Input proc. */
-#if BAD_TIP35_FLUSH
- TtyOutputProc, /* Output proc. */
-#else /* !BAD_TIP35_FLUSH */
FileOutputProc, /* Output proc. */
-#endif /* BAD_TIP35_FLUSH */
NULL, /* Seek proc. */
TtySetOptionProc, /* Set option proc. */
TtyGetOptionProc, /* Get option proc. */
@@ -358,6 +296,7 @@ static Tcl_ChannelType ttyChannelType = {
NULL, /* handler proc. */
NULL, /* wide seek proc. */
NULL, /* thread action proc. */
+ NULL, /* truncate proc. */
};
#endif /* SUPPORTS_TTY */
@@ -368,7 +307,7 @@ static Tcl_ChannelType ttyChannelType = {
static Tcl_ChannelType tcpChannelType = {
"tcp", /* Type name. */
- TCL_CHANNEL_VERSION_4, /* v4 channel */
+ TCL_CHANNEL_VERSION_5, /* v5 channel */
TcpCloseProc, /* Close proc. */
TcpInputProc, /* Input proc. */
TcpOutputProc, /* Output proc. */
@@ -383,16 +322,16 @@ static Tcl_ChannelType tcpChannelType = {
NULL, /* handler proc. */
NULL, /* wide seek proc. */
NULL, /* thread action proc. */
+ NULL, /* truncate proc. */
};
-
/*
*----------------------------------------------------------------------
*
* FileBlockModeProc --
*
- * Helper procedure to set blocking and nonblocking modes on a
- * file based channel. Invoked by generic IO level code.
+ * Helper function to set blocking and nonblocking modes on a file based
+ * channel. Invoked by generic IO level code.
*
* Results:
* 0 if successful, errno when failed.
@@ -405,36 +344,18 @@ static Tcl_ChannelType tcpChannelType = {
/* ARGSUSED */
static int
-FileBlockModeProc(instanceData, mode)
- ClientData instanceData; /* File state. */
- int mode; /* The mode to set. Can be one of
- * TCL_MODE_BLOCKING or
- * TCL_MODE_NONBLOCKING. */
+FileBlockModeProc(
+ ClientData instanceData, /* File state. */
+ int mode) /* The mode to set. Can be one of
+ * TCL_MODE_BLOCKING or
+ * TCL_MODE_NONBLOCKING. */
{
FileState *fsPtr = (FileState *) instanceData;
- int curStatus;
-#ifndef USE_FIONBIO
- curStatus = fcntl(fsPtr->fd, F_GETFL);
- if (mode == TCL_MODE_BLOCKING) {
- curStatus &= (~(O_NONBLOCK));
- } else {
- curStatus |= O_NONBLOCK;
- }
- if (fcntl(fsPtr->fd, F_SETFL, curStatus) < 0) {
- return errno;
- }
- curStatus = fcntl(fsPtr->fd, F_GETFL);
-#else /* USE_FIONBIO */
- if (mode == TCL_MODE_BLOCKING) {
- curStatus = 0;
- } else {
- curStatus = 1;
- }
- if (ioctl(fsPtr->fd, (int) FIONBIO, &curStatus) < 0) {
+ if (TclUnixSetBlockingMode(fsPtr->fd, mode) < 0) {
return errno;
}
-#endif /* !USE_FIONBIO */
+
return 0;
}
@@ -443,8 +364,8 @@ FileBlockModeProc(instanceData, mode)
*
* FileInputProc --
*
- * This procedure is invoked from the generic IO level to read
- * input from a file based channel.
+ * This function is invoked from the generic IO level to read input from
+ * a file based channel.
*
* Results:
* The number of bytes read is returned or -1 on error. An output
@@ -457,16 +378,16 @@ FileBlockModeProc(instanceData, mode)
*/
static int
-FileInputProc(instanceData, buf, toRead, errorCodePtr)
- ClientData instanceData; /* File state. */
- char *buf; /* Where to store data read. */
- int toRead; /* How much space is available
- * in the buffer? */
- int *errorCodePtr; /* Where to store error code. */
+FileInputProc(
+ ClientData instanceData, /* File state. */
+ char *buf, /* Where to store data read. */
+ int toRead, /* How much space is available in the
+ * buffer? */
+ int *errorCodePtr) /* Where to store error code. */
{
FileState *fsPtr = (FileState *) instanceData;
- int bytesRead; /* How many bytes were actually
- * read from the input device? */
+ int bytesRead; /* How many bytes were actually read from the
+ * input device? */
*errorCodePtr = 0;
@@ -490,13 +411,12 @@ FileInputProc(instanceData, buf, toRead, errorCodePtr)
*
* FileOutputProc--
*
- * This procedure is invoked from the generic IO level to write
- * output to a file channel.
+ * This function is invoked from the generic IO level to write output to
+ * a file channel.
*
* Results:
- * The number of bytes written is returned or -1 on error. An
- * output argument contains a POSIX error code if an error occurred,
- * or zero.
+ * The number of bytes written is returned or -1 on error. An output
+ * argument contains a POSIX error code if an error occurred, or zero.
*
* Side effects:
* Writes output on the output device of the channel.
@@ -505,11 +425,11 @@ FileInputProc(instanceData, buf, toRead, errorCodePtr)
*/
static int
-FileOutputProc(instanceData, buf, toWrite, errorCodePtr)
- ClientData instanceData; /* File state. */
- CONST char *buf; /* The data buffer. */
- int toWrite; /* How many bytes to write? */
- int *errorCodePtr; /* Where to store error code. */
+FileOutputProc(
+ ClientData instanceData, /* File state. */
+ const char *buf, /* The data buffer. */
+ int toWrite, /* How many bytes to write? */
+ int *errorCodePtr) /* Where to store error code. */
{
FileState *fsPtr = (FileState *) instanceData;
int written;
@@ -518,9 +438,8 @@ FileOutputProc(instanceData, buf, toWrite, errorCodePtr)
if (toWrite == 0) {
/*
- * SF Tcl Bug 465765.
- * Do not try to write nothing into a file. STREAM based
- * implementations will considers this as EOF (if there is a
+ * SF Tcl Bug 465765. Do not try to write nothing into a file. STREAM
+ * based implementations will considers this as EOF (if there is a
* pipe behind the file).
*/
@@ -539,7 +458,7 @@ FileOutputProc(instanceData, buf, toWrite, errorCodePtr)
*
* FileCloseProc --
*
- * This procedure is called from the generic IO level to perform
+ * This function is called from the generic IO level to perform
* channel-type-specific cleanup when a file based channel is closed.
*
* Results:
@@ -552,16 +471,13 @@ FileOutputProc(instanceData, buf, toWrite, errorCodePtr)
*/
static int
-FileCloseProc(instanceData, interp)
- ClientData instanceData; /* File state. */
- Tcl_Interp *interp; /* For error reporting - unused. */
+FileCloseProc(
+ ClientData instanceData, /* File state. */
+ Tcl_Interp *interp) /* For error reporting - unused. */
{
FileState *fsPtr = (FileState *) instanceData;
int errorCode = 0;
-#ifdef DEPRECATED
- FileState **nextPtrPtr;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-#endif /* DEPRECATED */
+
Tcl_DeleteFileHandler(fsPtr->fd);
/*
@@ -583,28 +499,27 @@ FileCloseProc(instanceData, interp)
*
* FileSeekProc --
*
- * This procedure is called by the generic IO level to move the
- * access point in a file based channel.
+ * This function is called by the generic IO level to move the access
+ * point in a file based channel.
*
* Results:
- * -1 if failed, the new position if successful. An output
- * argument contains the POSIX error code if an error occurred,
- * or zero.
+ * -1 if failed, the new position if successful. An output argument
+ * contains the POSIX error code if an error occurred, or zero.
*
* Side effects:
- * Moves the location at which the channel will be accessed in
- * future operations.
+ * Moves the location at which the channel will be accessed in future
+ * operations.
*
*----------------------------------------------------------------------
*/
static int
-FileSeekProc(instanceData, offset, mode, errorCodePtr)
- ClientData instanceData; /* File state. */
- long offset; /* Offset to seek to. */
- int mode; /* Relative to where should we seek? Can be
+FileSeekProc(
+ ClientData instanceData, /* File state. */
+ long offset, /* Offset to seek to. */
+ int mode, /* Relative to where should we seek? Can be
* one of SEEK_START, SEEK_SET or SEEK_END. */
- int *errorCodePtr; /* To store error code. */
+ int *errorCodePtr) /* To store error code. */
{
FileState *fsPtr = (FileState *) instanceData;
Tcl_WideInt oldLoc, newLoc;
@@ -612,20 +527,23 @@ FileSeekProc(instanceData, offset, mode, errorCodePtr)
/*
* Save our current place in case we need to roll-back the seek.
*/
+
oldLoc = TclOSseek(fsPtr->fd, (Tcl_SeekOffset) 0, SEEK_CUR);
if (oldLoc == Tcl_LongAsWide(-1)) {
/*
- * Bad things are happening. Error out...
+ * Bad things are happening. Error out...
*/
+
*errorCodePtr = errno;
return -1;
}
-
+
newLoc = TclOSseek(fsPtr->fd, (Tcl_SeekOffset) offset, mode);
-
+
/*
* Check for expressability in our return type, and roll-back otherwise.
*/
+
if (newLoc > Tcl_LongAsWide(INT_MAX)) {
*errorCodePtr = EOVERFLOW;
TclOSseek(fsPtr->fd, (Tcl_SeekOffset) oldLoc, SEEK_SET);
@@ -641,29 +559,28 @@ FileSeekProc(instanceData, offset, mode, errorCodePtr)
*
* FileWideSeekProc --
*
- * This procedure is called by the generic IO level to move the
- * access point in a file based channel, with offsets expressed
- * as wide integers.
+ * This function is called by the generic IO level to move the access
+ * point in a file based channel, with offsets expressed as wide
+ * integers.
*
* Results:
- * -1 if failed, the new position if successful. An output
- * argument contains the POSIX error code if an error occurred,
- * or zero.
+ * -1 if failed, the new position if successful. An output argument
+ * contains the POSIX error code if an error occurred, or zero.
*
* Side effects:
- * Moves the location at which the channel will be accessed in
- * future operations.
+ * Moves the location at which the channel will be accessed in future
+ * operations.
*
*----------------------------------------------------------------------
*/
static Tcl_WideInt
-FileWideSeekProc(instanceData, offset, mode, errorCodePtr)
- ClientData instanceData; /* File state. */
- Tcl_WideInt offset; /* Offset to seek to. */
- int mode; /* Relative to where should we seek? Can be
+FileWideSeekProc(
+ ClientData instanceData, /* File state. */
+ Tcl_WideInt offset, /* Offset to seek to. */
+ int mode, /* Relative to where should we seek? Can be
* one of SEEK_START, SEEK_CUR or SEEK_END. */
- int *errorCodePtr; /* To store error code. */
+ int *errorCodePtr) /* To store error code. */
{
FileState *fsPtr = (FileState *) instanceData;
Tcl_WideInt newLoc;
@@ -692,18 +609,18 @@ FileWideSeekProc(instanceData, offset, mode, errorCodePtr)
*/
static void
-FileWatchProc(instanceData, mask)
- ClientData instanceData; /* The file state. */
- int mask; /* Events of interest; an OR-ed
- * combination of TCL_READABLE,
- * TCL_WRITABLE and TCL_EXCEPTION. */
+FileWatchProc(
+ ClientData instanceData, /* The file state. */
+ int mask) /* Events of interest; an OR-ed combination of
+ * TCL_READABLE, TCL_WRITABLE and
+ * TCL_EXCEPTION. */
{
FileState *fsPtr = (FileState *) instanceData;
/*
- * Make sure we only register for events that are valid on this file.
- * Note that we are passing Tcl_NotifyChannel directly to
- * Tcl_CreateFileHandler with the channel pointer as the client data.
+ * Make sure we only register for events that are valid on this file. Note
+ * that we are passing Tcl_NotifyChannel directly to Tcl_CreateFileHandler
+ * with the channel pointer as the client data.
*/
mask &= fsPtr->validMask;
@@ -721,12 +638,12 @@ FileWatchProc(instanceData, mask)
*
* FileGetHandleProc --
*
- * Called from Tcl_GetChannelHandle to retrieve OS handles from
- * a file based channel.
+ * Called from Tcl_GetChannelHandle to retrieve OS handles from a file
+ * based channel.
*
* Results:
- * Returns TCL_OK with the fd in handlePtr, or TCL_ERROR if
- * there is no handle for the specified direction.
+ * Returns TCL_OK with the fd in handlePtr, or TCL_ERROR if there is no
+ * handle for the specified direction.
*
* Side effects:
* None.
@@ -735,122 +652,36 @@ FileWatchProc(instanceData, mask)
*/
static int
-FileGetHandleProc(instanceData, direction, handlePtr)
- ClientData instanceData; /* The file state. */
- int direction; /* TCL_READABLE or TCL_WRITABLE */
- ClientData *handlePtr; /* Where to store the handle. */
+FileGetHandleProc(
+ ClientData instanceData, /* The file state. */
+ int direction, /* TCL_READABLE or TCL_WRITABLE */
+ ClientData *handlePtr) /* Where to store the handle. */
{
FileState *fsPtr = (FileState *) instanceData;
if (direction & fsPtr->validMask) {
- *handlePtr = (ClientData) fsPtr->fd;
+ *handlePtr = (ClientData) INT2PTR(fsPtr->fd);
return TCL_OK;
- } else {
- return TCL_ERROR;
}
+ return TCL_ERROR;
}
-
-#ifdef SUPPORTS_TTY
-
-/*
- *----------------------------------------------------------------------
- *
- * TtyCloseProc --
- *
- * This procedure is called from the generic IO level to perform
- * channel-type-specific cleanup when a tty based channel is closed.
- *
- * Results:
- * 0 if successful, errno if failed.
- *
- * Side effects:
- * Closes the device of the channel.
- *
- *----------------------------------------------------------------------
- */
-static int
-TtyCloseProc(instanceData, interp)
- ClientData instanceData; /* Tty state. */
- Tcl_Interp *interp; /* For error reporting - unused. */
-{
-#if BAD_TIP35_FLUSH
- TtyState *ttyPtr = (TtyState *) instanceData;
-#endif /* BAD_TIP35_FLUSH */
-#ifdef TTYFLUSH
- TTYFLUSH(ttyPtr->fs.fd);
-#endif /* TTYFLUSH */
-#if 0
- /*
- * TIP#35 agreed to remove the unsave so that TCL could be used as a
- * simple stty.
- * It would be cleaner to remove all the stuff related to
- * TtyState.stateUpdated
- * TtyState.savedState
- * Then the structure TtyState would be the same as FileState.
- * IMO this cleanup could better be done for the final 8.4 release
- * after nobody complained about the missing unsave. -- schroedter
- */
- if (ttyPtr->stateUpdated) {
- SETIOSTATE(ttyPtr->fs.fd, &ttyPtr->savedState);
- }
-#endif
- return FileCloseProc(instanceData, interp);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TtyOutputProc--
- *
- * This procedure is invoked from the generic IO level to write
- * output to a TTY channel.
- *
- * Results:
- * The number of bytes written is returned or -1 on error. An
- * output argument contains a POSIX error code if an error occurred,
- * or zero.
- *
- * Side effects:
- * Writes output on the output device of the channel
- * if the channel is not designated to be closed.
- *
- *----------------------------------------------------------------------
- */
-
-#if BAD_TIP35_FLUSH
-static int
-TtyOutputProc(instanceData, buf, toWrite, errorCodePtr)
- ClientData instanceData; /* File state. */
- CONST char *buf; /* The data buffer. */
- int toWrite; /* How many bytes to write? */
- int *errorCodePtr; /* Where to store error code. */
-{
- if (TclInExit()) {
- /*
- * Do not write data during Tcl exit.
- * Serial port may block preventing Tcl from exit.
- */
- return toWrite;
- } else {
- return FileOutputProc(instanceData, buf, toWrite, errorCodePtr);
- }
-}
-#endif /* BAD_TIP35_FLUSH */
+#ifdef SUPPORTS_TTY
#ifdef USE_TERMIOS
/*
*----------------------------------------------------------------------
*
* TtyModemStatusStr --
*
- * Converts a RS232 modem status list of readable flags
+ * Converts a RS232 modem status list of readable flags
*
*----------------------------------------------------------------------
*/
+
static void
-TtyModemStatusStr(status, dsPtr)
- int status; /* RS232 modem status */
- Tcl_DString *dsPtr; /* Where to store string */
+TtyModemStatusStr(
+ int status, /* RS232 modem status */
+ Tcl_DString *dsPtr) /* Where to store string */
{
#ifdef TIOCM_CTS
Tcl_DStringAppendElement(dsPtr, "CTS");
@@ -883,25 +714,25 @@ TtyModemStatusStr(status, dsPtr)
* interp is not NULL.
*
* Side effects:
- * May modify an option on a device.
- * Sets Error message if needed (by calling Tcl_BadChannelOption).
+ * May modify an option on a device. Sets Error message if needed (by
+ * calling Tcl_BadChannelOption).
*
*----------------------------------------------------------------------
*/
-static int
-TtySetOptionProc(instanceData, interp, optionName, value)
- ClientData instanceData; /* File state. */
- Tcl_Interp *interp; /* For error reporting - can be NULL. */
- CONST char *optionName; /* Which option to set? */
- CONST char *value; /* New value for option. */
+static int
+TtySetOptionProc(
+ ClientData instanceData, /* File state. */
+ Tcl_Interp *interp, /* For error reporting - can be NULL. */
+ const char *optionName, /* Which option to set? */
+ const char *value) /* New value for option. */
{
FileState *fsPtr = (FileState *) instanceData;
unsigned int len, vlen;
TtyAttrs tty;
#ifdef USE_TERMIOS
int flag, control, argc;
- CONST char **argv;
+ const char **argv;
IOSTATE iostate;
#endif /* USE_TERMIOS */
@@ -916,12 +747,12 @@ TtySetOptionProc(instanceData, interp, optionName, value)
&tty.stop) != TCL_OK) {
return TCL_ERROR;
}
+
/*
- * system calls results should be checked there. -- dl
+ * system calls results should be checked there. - dl
*/
TtySetAttributes(fsPtr->fd, &tty);
- ((TtyState *) fsPtr)->stateUpdated = 1;
return TCL_OK;
}
@@ -930,23 +761,24 @@ TtySetOptionProc(instanceData, interp, optionName, value)
/*
* Option -handshake none|xonxoff|rtscts|dtrdsr
*/
+
if ((len > 1) && (strncmp(optionName, "-handshake", len) == 0)) {
/*
- * Reset all handshake options
- * DTR and RTS are ON by default
+ * Reset all handshake options. DTR and RTS are ON by default.
*/
+
GETIOSTATE(fsPtr->fd, &iostate);
- iostate.c_iflag &= ~(IXON | IXOFF | IXANY);
+ CLEAR_BITS(iostate.c_iflag, IXON | IXOFF | IXANY);
#ifdef CRTSCTS
- iostate.c_cflag &= ~CRTSCTS;
+ CLEAR_BITS(iostate.c_cflag, CRTSCTS);
#endif /* CRTSCTS */
if (strncasecmp(value, "NONE", vlen) == 0) {
/* leave all handshake options disabled */
} else if (strncasecmp(value, "XONXOFF", vlen) == 0) {
- iostate.c_iflag |= (IXON | IXOFF | IXANY);
+ SET_BITS(iostate.c_iflag, IXON | IXOFF | IXANY);
} else if (strncasecmp(value, "RTSCTS", vlen) == 0) {
#ifdef CRTSCTS
- iostate.c_cflag |= CRTSCTS;
+ SET_BITS(iostate.c_cflag, CRTSCTS);
#else /* !CRTSTS */
UNSUPPORTED_OPTION("-handshake RTSCTS");
return TCL_ERROR;
@@ -956,9 +788,9 @@ TtySetOptionProc(instanceData, interp, optionName, value)
return TCL_ERROR;
} else {
if (interp) {
- Tcl_AppendResult(interp, "bad value for -handshake: ",
+ Tcl_AppendResult(interp, "bad value for -handshake: "
"must be one of xonxoff, rtscts, dtrdsr or none",
- (char *) NULL);
+ NULL);
}
return TCL_ERROR;
}
@@ -969,19 +801,27 @@ TtySetOptionProc(instanceData, interp, optionName, value)
/*
* Option -xchar {\x11 \x13}
*/
+
if ((len > 1) && (strncmp(optionName, "-xchar", len) == 0)) {
GETIOSTATE(fsPtr->fd, &iostate);
if (Tcl_SplitList(interp, value, &argc, &argv) == TCL_ERROR) {
return TCL_ERROR;
}
if (argc == 2) {
- iostate.c_cc[VSTART] = argv[0][0];
- iostate.c_cc[VSTOP] = argv[1][0];
+ Tcl_DString ds;
+ Tcl_DStringInit(&ds);
+
+ Tcl_UtfToExternalDString(NULL, argv[0], -1, &ds);
+ iostate.c_cc[VSTART] = *(const cc_t *) Tcl_DStringValue(&ds);
+ Tcl_DStringSetLength(&ds, 0);
+
+ Tcl_UtfToExternalDString(NULL, argv[1], -1, &ds);
+ iostate.c_cc[VSTOP] = *(const cc_t *) Tcl_DStringValue(&ds);
+ Tcl_DStringFree(&ds);
} else {
if (interp) {
- Tcl_AppendResult(interp,
- "bad value for -xchar: should be a list of two elements",
- (char *) NULL);
+ Tcl_AppendResult(interp, "bad value for -xchar: "
+ "should be a list of two elements", NULL);
}
ckfree((char *) argv);
return TCL_ERROR;
@@ -994,6 +834,7 @@ TtySetOptionProc(instanceData, interp, optionName, value)
/*
* Option -timeout msec
*/
+
if ((len > 2) && (strncmp(optionName, "-timeout", len) == 0)) {
int msec;
@@ -1001,8 +842,8 @@ TtySetOptionProc(instanceData, interp, optionName, value)
if (Tcl_GetInt(interp, value, &msec) != TCL_OK) {
return TCL_ERROR;
}
- iostate.c_cc[VMIN] = 0;
- iostate.c_cc[VTIME] = (msec == 0) ? 0 : (msec < 100) ? 1 : (msec+50)/100;
+ iostate.c_cc[VMIN] = 0;
+ iostate.c_cc[VTIME] = (msec==0) ? 0 : (msec<100) ? 1 : (msec+50)/100;
SETIOSTATE(fsPtr->fd, &iostate);
return TCL_OK;
}
@@ -1010,16 +851,17 @@ TtySetOptionProc(instanceData, interp, optionName, value)
/*
* Option -ttycontrol {DTR 1 RTS 0 BREAK 0}
*/
+
if ((len > 4) && (strncmp(optionName, "-ttycontrol", len) == 0)) {
int i;
+
if (Tcl_SplitList(interp, value, &argc, &argv) == TCL_ERROR) {
return TCL_ERROR;
}
if ((argc % 2) == 1) {
if (interp) {
- Tcl_AppendResult(interp,
- "bad value for -ttycontrol: should be a list of",
- "signal,value pairs", (char *) NULL);
+ Tcl_AppendResult(interp, "bad value for -ttycontrol: "
+ "should be a list of signal,value pairs", NULL);
}
ckfree((char *) argv);
return TCL_ERROR;
@@ -1034,9 +876,9 @@ TtySetOptionProc(instanceData, interp, optionName, value)
if (strncasecmp(argv[i], "DTR", strlen(argv[i])) == 0) {
#ifdef TIOCM_DTR
if (flag) {
- control |= TIOCM_DTR;
+ SET_BITS(control, TIOCM_DTR);
} else {
- control &= ~TIOCM_DTR;
+ CLEAR_BITS(control, TIOCM_DTR);
}
#else /* !TIOCM_DTR */
UNSUPPORTED_OPTION("-ttycontrol DTR");
@@ -1046,9 +888,9 @@ TtySetOptionProc(instanceData, interp, optionName, value)
} else if (strncasecmp(argv[i], "RTS", strlen(argv[i])) == 0) {
#ifdef TIOCM_RTS
if (flag) {
- control |= TIOCM_RTS;
+ SET_BITS(control, TIOCM_RTS);
} else {
- control &= ~TIOCM_RTS;
+ CLEAR_BITS(control, TIOCM_RTS);
}
#else /* !TIOCM_RTS*/
UNSUPPORTED_OPTION("-ttycontrol RTS");
@@ -1066,8 +908,8 @@ TtySetOptionProc(instanceData, interp, optionName, value)
} else {
if (interp) {
Tcl_AppendResult(interp, "bad signal \"", argv[i],
- "\" for -ttycontrol: must be ",
- "DTR, RTS or BREAK", (char *) NULL);
+ "\" for -ttycontrol: must be "
+ "DTR, RTS or BREAK", NULL);
}
ckfree((char *) argv);
return TCL_ERROR;
@@ -1080,7 +922,7 @@ TtySetOptionProc(instanceData, interp, optionName, value)
}
return Tcl_BadChannelOption(interp, optionName,
- "mode handshake timeout ttycontrol xchar ");
+ "mode handshake timeout ttycontrol xchar");
#else /* !USE_TERMIOS */
return Tcl_BadChannelOption(interp, optionName, "mode");
@@ -1092,35 +934,34 @@ TtySetOptionProc(instanceData, interp, optionName, value)
*
* TtyGetOptionProc --
*
- * Gets a mode associated with an IO channel. If the optionName arg
- * is non NULL, retrieves the value of that option. If the optionName
- * arg is NULL, retrieves a list of alternating option names and
- * values for the given channel.
+ * Gets a mode associated with an IO channel. If the optionName arg is
+ * non-NULL, retrieves the value of that option. If the optionName arg is
+ * NULL, retrieves a list of alternating option names and values for the
+ * given channel.
*
* Results:
- * A standard Tcl result. Also sets the supplied DString to the
- * string value of the option(s) returned.
+ * A standard Tcl result. Also sets the supplied DString to the string
+ * value of the option(s) returned.
*
* Side effects:
- * The string returned by this function is in static storage and
- * may be reused at any time subsequent to the call.
- * Sets Error message if needed (by calling Tcl_BadChannelOption).
+ * The string returned by this function is in static storage and may be
+ * reused at any time subsequent to the call. Sets error message if
+ * needed (by calling Tcl_BadChannelOption).
*
*----------------------------------------------------------------------
*/
-static int
-TtyGetOptionProc(instanceData, interp, optionName, dsPtr)
- ClientData instanceData; /* File state. */
- Tcl_Interp *interp; /* For error reporting - can be NULL. */
- CONST char *optionName; /* Option to get. */
- Tcl_DString *dsPtr; /* Where to store value(s). */
+static int
+TtyGetOptionProc(
+ ClientData instanceData, /* File state. */
+ Tcl_Interp *interp, /* For error reporting - can be NULL. */
+ const char *optionName, /* Option to get. */
+ Tcl_DString *dsPtr) /* Where to store value(s). */
{
FileState *fsPtr = (FileState *) instanceData;
unsigned int len;
- char buf[3 * TCL_INTEGER_SPACE + 16];
- TtyAttrs tty;
- int valid = 0; /* flag if valid option parsed */
+ char buf[3*TCL_INTEGER_SPACE + 16];
+ int valid = 0; /* Flag if valid option parsed. */
if (optionName == NULL) {
len = 0;
@@ -1131,6 +972,8 @@ TtyGetOptionProc(instanceData, interp, optionName, dsPtr)
Tcl_DStringAppendElement(dsPtr, "-mode");
}
if (len==0 || (len>2 && strncmp(optionName, "-mode", len)==0)) {
+ TtyAttrs tty;
+
valid = 1;
TtyGetAttributes(fsPtr->fd, &tty);
sprintf(buf, "%d,%c,%d,%d", tty.baud, tty.parity, tty.data, tty.stop);
@@ -1139,34 +982,42 @@ TtyGetOptionProc(instanceData, interp, optionName, dsPtr)
#ifdef USE_TERMIOS
/*
- * get option -xchar
+ * Get option -xchar
*/
+
if (len == 0) {
Tcl_DStringAppendElement(dsPtr, "-xchar");
Tcl_DStringStartSublist(dsPtr);
}
if (len==0 || (len>1 && strncmp(optionName, "-xchar", len)==0)) {
IOSTATE iostate;
+ Tcl_DString ds;
valid = 1;
GETIOSTATE(fsPtr->fd, &iostate);
- sprintf(buf, "%c", iostate.c_cc[VSTART]);
- Tcl_DStringAppendElement(dsPtr, buf);
- sprintf(buf, "%c", iostate.c_cc[VSTOP]);
- Tcl_DStringAppendElement(dsPtr, buf);
+ Tcl_DStringInit(&ds);
+
+ Tcl_ExternalToUtfDString(NULL, (const char *) &iostate.c_cc[VSTART], 1, &ds);
+ Tcl_DStringAppendElement(dsPtr, (const char *) Tcl_DStringValue(&ds));
+ Tcl_DStringSetLength(&ds, 0);
+
+ Tcl_ExternalToUtfDString(NULL, (const char *) &iostate.c_cc[VSTOP], 1, &ds);
+ Tcl_DStringAppendElement(dsPtr, (const char *) Tcl_DStringValue(&ds));
+ Tcl_DStringFree(&ds);
}
if (len == 0) {
Tcl_DStringEndSublist(dsPtr);
}
/*
- * get option -queue
- * option is readonly and returned by [fconfigure chan -queue]
- * but not returned by unnamed [fconfigure chan]
+ * Get option -queue
+ * Option is readonly and returned by [fconfigure chan -queue] but not
+ * returned by unnamed [fconfigure chan].
*/
+
if ((len > 1) && (strncmp(optionName, "-queue", len) == 0)) {
- int inQueue=0, outQueue=0;
- int inBuffered, outBuffered;
+ int inQueue=0, outQueue=0, inBuffered, outBuffered;
+
valid = 1;
#ifdef GETREADQUEUE
GETREADQUEUE(fsPtr->fd, inQueue);
@@ -1174,7 +1025,7 @@ TtyGetOptionProc(instanceData, interp, optionName, dsPtr)
#ifdef GETWRITEQUEUE
GETWRITEQUEUE(fsPtr->fd, outQueue);
#endif /* GETWRITEQUEUE */
- inBuffered = Tcl_InputBuffered(fsPtr->channel);
+ inBuffered = Tcl_InputBuffered(fsPtr->channel);
outBuffered = Tcl_OutputBuffered(fsPtr->channel);
sprintf(buf, "%d", inBuffered+inQueue);
@@ -1184,12 +1035,13 @@ TtyGetOptionProc(instanceData, interp, optionName, dsPtr)
}
/*
- * get option -ttystatus
- * option is readonly and returned by [fconfigure chan -ttystatus]
- * but not returned by unnamed [fconfigure chan]
+ * Get option -ttystatus
+ * Option is readonly and returned by [fconfigure chan -ttystatus] but not
+ * returned by unnamed [fconfigure chan].
*/
if ((len > 4) && (strncmp(optionName, "-ttystatus", len) == 0)) {
int status;
+
valid = 1;
GETCONTROL(fsPtr->fd, &status);
TtyModemStatusStr(status, dsPtr);
@@ -1198,26 +1050,17 @@ TtyGetOptionProc(instanceData, interp, optionName, dsPtr)
if (valid) {
return TCL_OK;
- } else {
- return Tcl_BadChannelOption(interp, optionName,
+ }
+ return Tcl_BadChannelOption(interp, optionName, "mode"
#ifdef USE_TERMIOS
- "mode queue ttystatus xchar");
-#else /* !USE_TERMIOS */
- "mode");
+ " queue ttystatus xchar"
#endif /* USE_TERMIOS */
- }
+ );
}
-#undef DIRECT_BAUD
-#ifdef B4800
-# if (B4800 == 4800)
-# define DIRECT_BAUD
-# endif /* B4800 == 4800 */
-#endif /* B4800 */
-
#ifdef DIRECT_BAUD
-# define TtyGetSpeed(baud) ((unsigned) (baud))
-# define TtyGetBaud(speed) ((int) (speed))
+# define TtyGetSpeed(baud) ((unsigned) (baud))
+# define TtyGetBaud(speed) ((int) (speed))
#else /* !DIRECT_BAUD */
static struct {int baud; unsigned long speed;} speeds[] = {
@@ -1316,9 +1159,9 @@ static struct {int baud; unsigned long speed;} speeds[] = {
*
* TtyGetSpeed --
*
- * Given a baud rate, get the mask value that should be stored in
- * the termios, termio, or sgttyb structure in order to select that
- * baud rate.
+ * Given a baud rate, get the mask value that should be stored in the
+ * termios, termio, or sgttyb structure in order to select that baud
+ * rate.
*
* Results:
* As above.
@@ -1330,8 +1173,8 @@ static struct {int baud; unsigned long speed;} speeds[] = {
*/
static unsigned long
-TtyGetSpeed(baud)
- int baud; /* The baud rate to look up. */
+TtyGetSpeed(
+ int baud) /* The baud rate to look up. */
{
int bestIdx, bestDiff, i, diff;
@@ -1340,8 +1183,8 @@ TtyGetSpeed(baud)
/*
* If the baud rate does not correspond to one of the known mask values,
- * choose the mask value whose baud rate is closest to the specified
- * baud rate.
+ * choose the mask value whose baud rate is closest to the specified baud
+ * rate.
*/
for (i = 0; speeds[i].baud >= 0; i++) {
@@ -1362,11 +1205,11 @@ TtyGetSpeed(baud)
*
* TtyGetBaud --
*
- * Given a speed mask value from a termios, termio, or sgttyb
- * structure, get the baus rate that corresponds to that mask value.
+ * Given a speed mask value from a termios, termio, or sgttyb structure,
+ * get the baus rate that corresponds to that mask value.
*
* Results:
- * As above. If the mask value was not recognized, 0 is returned.
+ * As above. If the mask value was not recognized, 0 is returned.
*
* Side effects:
* None.
@@ -1375,8 +1218,8 @@ TtyGetSpeed(baud)
*/
static int
-TtyGetBaud(speed)
- unsigned long speed; /* Speed mask value to look up. */
+TtyGetBaud(
+ unsigned long speed) /* Speed mask value to look up. */
{
int i;
@@ -1387,9 +1230,7 @@ TtyGetBaud(speed)
}
return 0;
}
-
#endif /* !DIRECT_BAUD */
-
/*
*---------------------------------------------------------------------------
@@ -1408,10 +1249,10 @@ TtyGetBaud(speed)
*/
static void
-TtyGetAttributes(fd, ttyPtr)
- int fd; /* Open file descriptor for serial port to
- * be queried. */
- TtyAttrs *ttyPtr; /* Buffer filled with serial port
+TtyGetAttributes(
+ int fd, /* Open file descriptor for serial port to be
+ * queried. */
+ TtyAttrs *ttyPtr) /* Buffer filled with serial port
* attributes. */
{
IOSTATE iostate;
@@ -1425,15 +1266,15 @@ TtyGetAttributes(fd, ttyPtr)
parity = 'n';
#ifdef PAREXT
switch ((int) (iostate.c_cflag & (PARENB | PARODD | PAREXT))) {
- case PARENB : parity = 'e'; break;
- case PARENB | PARODD : parity = 'o'; break;
- case PARENB | PAREXT : parity = 's'; break;
- case PARENB | PARODD | PAREXT : parity = 'm'; break;
+ case PARENB : parity = 'e'; break;
+ case PARENB | PARODD : parity = 'o'; break;
+ case PARENB | PAREXT : parity = 's'; break;
+ case PARENB | PARODD | PAREXT : parity = 'm'; break;
}
#else /* !PAREXT */
switch ((int) (iostate.c_cflag & (PARENB | PARODD))) {
- case PARENB : parity = 'e'; break;
- case PARENB | PARODD : parity = 'o'; break;
+ case PARENB : parity = 'e'; break;
+ case PARENB | PARODD : parity = 'o'; break;
}
#endif /* !PAREXT */
@@ -1448,10 +1289,10 @@ TtyGetAttributes(fd, ttyPtr)
parity = 'n';
switch (iostate.c_cflag & (PARENB | PARODD | PAREXT)) {
- case PARENB : parity = 'e'; break;
- case PARENB | PARODD : parity = 'o'; break;
- case PARENB | PAREXT : parity = 's'; break;
- case PARENB | PARODD | PAREXT : parity = 'm'; break;
+ case PARENB : parity = 'e'; break;
+ case PARENB | PARODD : parity = 'o'; break;
+ case PARENB | PAREXT : parity = 's'; break;
+ case PARENB | PARODD | PAREXT : parity = 'm'; break;
}
data = iostate.c_cflag & CSIZE;
@@ -1486,7 +1327,7 @@ TtyGetAttributes(fd, ttyPtr)
*
* TtySetAttributes --
*
- * Set the current attributes of the specified serial device.
+ * Set the current attributes of the specified serial device.
*
* Results:
* None.
@@ -1498,11 +1339,11 @@ TtyGetAttributes(fd, ttyPtr)
*/
static void
-TtySetAttributes(fd, ttyPtr)
- int fd; /* Open file descriptor for serial port to
- * be modified. */
- TtyAttrs *ttyPtr; /* Buffer containing new attributes for
- * serial port. */
+TtySetAttributes(
+ int fd, /* Open file descriptor for serial port to be
+ * modified. */
+ TtyAttrs *ttyPtr) /* Buffer containing new attributes for serial
+ * port. */
{
IOSTATE iostate;
@@ -1516,25 +1357,28 @@ TtySetAttributes(fd, ttyPtr)
flag = 0;
parity = ttyPtr->parity;
if (parity != 'n') {
- flag |= PARENB;
+ SET_BITS(flag, PARENB);
#ifdef PAREXT
- iostate.c_cflag &= ~PAREXT;
+ CLEAR_BITS(iostate.c_cflag, PAREXT);
if ((parity == 'm') || (parity == 's')) {
- flag |= PAREXT;
+ SET_BITS(flag, PAREXT);
}
#endif /* PAREXT */
if ((parity == 'm') || (parity == 'o')) {
- flag |= PARODD;
+ SET_BITS(flag, PARODD);
}
}
data = ttyPtr->data;
- flag |= (data == 5) ? CS5 : (data == 6) ? CS6 : (data == 7) ? CS7 : CS8;
+ SET_BITS(flag,
+ (data == 5) ? CS5 :
+ (data == 6) ? CS6 :
+ (data == 7) ? CS7 : CS8);
if (ttyPtr->stop == 2) {
- flag |= CSTOPB;
+ SET_BITS(flag, CSTOPB);
}
- iostate.c_cflag &= ~(PARENB | PARODD | CSIZE | CSTOPB);
- iostate.c_cflag |= flag;
+ CLEAR_BITS(iostate.c_cflag, PARENB | PARODD | CSIZE | CSTOPB);
+ SET_BITS(iostate.c_cflag, flag);
#endif /* USE_TERMIOS */
@@ -1542,28 +1386,31 @@ TtySetAttributes(fd, ttyPtr)
int parity, data, flag;
GETIOSTATE(fd, &iostate);
- iostate.c_cflag &= ~CBAUD;
- iostate.c_cflag |= TtyGetSpeed(ttyPtr->baud);
+ CLEAR_BITS(iostate.c_cflag, CBAUD);
+ SET_BITS(iostate.c_cflag, TtyGetSpeed(ttyPtr->baud));
flag = 0;
parity = ttyPtr->parity;
if (parity != 'n') {
- flag |= PARENB;
+ SET_BITS(flag, PARENB);
if ((parity == 'm') || (parity == 's')) {
- flag |= PAREXT;
+ SET_BITS(flag, PAREXT);
}
if ((parity == 'm') || (parity == 'o')) {
- flag |= PARODD;
+ SET_BITS(flag, PARODD);
}
}
data = ttyPtr->data;
- flag |= (data == 5) ? CS5 : (data == 6) ? CS6 : (data == 7) ? CS7 : CS8;
+ SET_BITS(flag,
+ (data == 5) ? CS5 :
+ (data == 6) ? CS6 :
+ (data == 7) ? CS7 : CS8);
if (ttyPtr->stop == 2) {
- flag |= CSTOPB;
+ SET_BITS(flag, CSTOPB);
}
- iostate.c_cflag &= ~(PARENB | PARODD | PAREXT | CSIZE | CSTOPB);
- iostate.c_cflag |= flag;
+ CLEAR_BITS(iostate.c_cflag, PARENB | PARODD | PAREXT | CSIZE | CSTOPB);
+ SET_BITS(iostate.c_cflag, flag);
#endif /* USE_TERMIO */
@@ -1576,11 +1423,11 @@ TtySetAttributes(fd, ttyPtr)
parity = ttyPtr->parity;
if (parity == 'e') {
- iostate.sg_flags &= ~ODDP;
- iostate.sg_flags |= EVENP;
+ CLEAR_BITS(iostate.sg_flags, ODDP);
+ SET_BITS(iostate.sg_flags, EVENP);
} else if (parity == 'o') {
- iostate.sg_flags &= ~EVENP;
- iostate.sg_flags |= ODDP;
+ CLEAR_BITS(iostate.sg_flags, EVENP);
+ SET_BITS(iostate.sg_flags, ODDP);
}
#endif /* USE_SGTTY */
@@ -1592,13 +1439,13 @@ TtySetAttributes(fd, ttyPtr)
*
* TtyParseMode --
*
- * Parse the "-mode" argument to the fconfigure command. The argument
- * is of the form baud,parity,data,stop.
+ * Parse the "-mode" argument to the fconfigure command. The argument is
+ * of the form baud,parity,data,stop.
*
* Results:
- * The return value is TCL_OK if the argument was successfully
- * parsed, TCL_ERROR otherwise. If TCL_ERROR is returned, an
- * error message is left in the interp's result (if interp is non-NULL).
+ * The return value is TCL_OK if the argument was successfully parsed,
+ * TCL_ERROR otherwise. If TCL_ERROR is returned, an error message is
+ * left in the interp's result (if interp is non-NULL).
*
* Side effects:
* None.
@@ -1607,17 +1454,17 @@ TtySetAttributes(fd, ttyPtr)
*/
static int
-TtyParseMode(interp, mode, speedPtr, parityPtr, dataPtr, stopPtr)
- Tcl_Interp *interp; /* If non-NULL, interp for error return. */
- CONST char *mode; /* Mode string to be parsed. */
- int *speedPtr; /* Filled with baud rate from mode string. */
- int *parityPtr; /* Filled with parity from mode string. */
- int *dataPtr; /* Filled with data bits from mode string. */
- int *stopPtr; /* Filled with stop bits from mode string. */
+TtyParseMode(
+ Tcl_Interp *interp, /* If non-NULL, interp for error return. */
+ const char *mode, /* Mode string to be parsed. */
+ int *speedPtr, /* Filled with baud rate from mode string. */
+ int *parityPtr, /* Filled with parity from mode string. */
+ int *dataPtr, /* Filled with data bits from mode string. */
+ int *stopPtr) /* Filled with stop bits from mode string. */
{
int i, end;
char parity;
- static char *bad = "bad value for -mode";
+ static const char *bad = "bad value for -mode";
i = sscanf(mode, "%d,%c,%d,%d%n", speedPtr, &parity, dataPtr,
stopPtr, &end);
@@ -1628,24 +1475,23 @@ TtyParseMode(interp, mode, speedPtr, parityPtr, dataPtr, stopPtr)
}
return TCL_ERROR;
}
+
/*
- * Only allow setting mark/space parity on platforms that support it
- * Make sure to allow for the case where strchr is a macro.
- * [Bug: 5089]
+ * Only allow setting mark/space parity on platforms that support it Make
+ * sure to allow for the case where strchr is a macro. [Bug: 5089]
*/
- if (
+
#if defined(PAREXT) || defined(USE_TERMIO)
- strchr("noems", parity) == NULL
+ if (strchr("noems", parity) == NULL) {
#else
- strchr("noe", parity) == NULL
+ if (strchr("noe", parity) == NULL) {
#endif /* PAREXT|USE_TERMIO */
- ) {
if (interp != NULL) {
- Tcl_AppendResult(interp, bad,
+ Tcl_AppendResult(interp, bad, " parity: should be ",
#if defined(PAREXT) || defined(USE_TERMIO)
- " parity: should be n, o, e, m, or s",
+ "n, o, e, m, or s",
#else
- " parity: should be n, o, or e",
+ "n, o, or e",
#endif /* PAREXT|USE_TERMIO */
NULL);
}
@@ -1673,36 +1519,35 @@ TtyParseMode(interp, mode, speedPtr, parityPtr, dataPtr, stopPtr)
*
* TtyInit --
*
- * Given file descriptor that refers to a serial port,
- * initialize the serial port to a set of sane values so that
- * Tcl can talk to a device located on the serial port.
- * Note that no initialization happens if the initialize flag
- * is not set; this is necessary for the correct handling of
- * UNIX console TTYs at startup.
+ * Given file descriptor that refers to a serial port, initialize the
+ * serial port to a set of sane values so that Tcl can talk to a device
+ * located on the serial port. Note that no initialization happens if the
+ * initialize flag is not set; this is necessary for the correct handling
+ * of UNIX console TTYs at startup.
*
* Results:
- * A pointer to a FileState suitable for use with Tcl_CreateChannel
- * and the ttyChannelType structure.
+ * A pointer to a FileState suitable for use with Tcl_CreateChannel and
+ * the ttyChannelType structure.
*
* Side effects:
- * Serial device initialized to non-blocking raw mode, similar to
- * sockets (if initialize flag is non-zero.) All other modes can
- * be simulated on top of this in Tcl.
+ * Serial device initialized to non-blocking raw mode, similar to sockets
+ * (if initialize flag is non-zero.) All other modes can be simulated on
+ * top of this in Tcl.
*
*---------------------------------------------------------------------------
*/
static FileState *
-TtyInit(fd, initialize)
- int fd; /* Open file descriptor for serial port to
- * be initialized. */
- int initialize;
+TtyInit(
+ int fd, /* Open file descriptor for serial port to be
+ * initialized. */
+ int initialize)
{
TtyState *ttyPtr;
+ int stateUpdated = 0;
ttyPtr = (TtyState *) ckalloc((unsigned) sizeof(TtyState));
GETIOSTATE(fd, &ttyPtr->savedState);
- ttyPtr->stateUpdated = 0;
if (initialize) {
IOSTATE iostate = ttyPtr->savedState;
@@ -1713,12 +1558,12 @@ TtyInit(fd, initialize)
iostate.c_cflag & CREAD ||
iostate.c_cc[VMIN] != 1 ||
iostate.c_cc[VTIME] != 0) {
- ttyPtr->stateUpdated = 1;
+ stateUpdated = 1;
}
iostate.c_iflag = IGNBRK;
iostate.c_oflag = 0;
iostate.c_lflag = 0;
- iostate.c_cflag |= CREAD;
+ SET_BITS(iostate.c_cflag, CREAD);
iostate.c_cc[VMIN] = 1;
iostate.c_cc[VTIME] = 0;
#endif /* USE_TERMIOS|USE_TERMIO */
@@ -1728,15 +1573,15 @@ TtyInit(fd, initialize)
!(iostate.sg_flags & RAW)) {
ttyPtr->stateUpdated = 1;
}
- iostate.sg_flags &= (EVENP | ODDP);
- iostate.sg_flags |= RAW;
+ iostate.sg_flags &= EVENP | ODDP;
+ SET_BITS(iostate.sg_flags, RAW);
#endif /* USE_SGTTY */
/*
- * Only update if we're changing anything to avoid possible
- * blocking.
+ * Only update if we're changing anything to avoid possible blocking.
*/
- if (ttyPtr->stateUpdated) {
+
+ if (stateUpdated) {
SETIOSTATE(fd, &iostate);
}
}
@@ -1753,71 +1598,66 @@ TtyInit(fd, initialize)
* Open an file based channel on Unix systems.
*
* Results:
- * The new channel or NULL. If NULL, the output argument
- * errorCodePtr is set to a POSIX error and an error message is
- * left in the interp's result if interp is not NULL.
+ * The new channel or NULL. If NULL, the output argument errorCodePtr is
+ * set to a POSIX error and an error message is left in the interp's
+ * result if interp is not NULL.
*
* Side effects:
- * May open the channel and may cause creation of a file on the
- * file system.
+ * May open the channel and may cause creation of a file on the file
+ * system.
*
*----------------------------------------------------------------------
*/
Tcl_Channel
-TclpOpenFileChannel(interp, pathPtr, mode, permissions)
- Tcl_Interp *interp; /* Interpreter for error reporting;
- * can be NULL. */
- Tcl_Obj *pathPtr; /* Name of file to open. */
- int mode; /* POSIX open mode. */
- int permissions; /* If the open involves creating a
- * file, with what modes to create
- * it? */
+TclpOpenFileChannel(
+ Tcl_Interp *interp, /* Interpreter for error reporting; can be
+ * NULL. */
+ Tcl_Obj *pathPtr, /* Name of file to open. */
+ int mode, /* POSIX open mode. */
+ int permissions) /* If the open involves creating a file, with
+ * what modes to create it? */
{
int fd, channelPermissions;
FileState *fsPtr;
- CONST char *native, *translation;
+ const char *native, *translation;
char channelName[16 + TCL_INTEGER_SPACE];
Tcl_ChannelType *channelTypePtr;
-#ifdef SUPPORTS_TTY
- int ctl_tty;
-#endif /* SUPPORTS_TTY */
-#ifdef DEPRECATED
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-#endif /* DEPRECATED */
switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) {
- case O_RDONLY:
- channelPermissions = TCL_READABLE;
- break;
- case O_WRONLY:
- channelPermissions = TCL_WRITABLE;
- break;
- case O_RDWR:
- channelPermissions = (TCL_READABLE | TCL_WRITABLE);
- break;
- default:
- /*
- * This may occurr if modeString was "", for example.
- */
- panic("TclpOpenFileChannel: invalid mode value");
- return NULL;
+ case O_RDONLY:
+ channelPermissions = TCL_READABLE;
+ break;
+ case O_WRONLY:
+ channelPermissions = TCL_WRITABLE;
+ break;
+ case O_RDWR:
+ channelPermissions = (TCL_READABLE | TCL_WRITABLE);
+ break;
+ default:
+ /*
+ * This may occurr if modeString was "", for example.
+ */
+
+ Tcl_Panic("TclpOpenFileChannel: invalid mode value");
+ return NULL;
}
native = Tcl_FSGetNativePath(pathPtr);
if (native == NULL) {
return NULL;
}
+
+#ifdef DJGPP
+ SET_BITS(mode, O_BINARY);
+#endif
+
fd = TclOSopen(native, mode, permissions);
-#ifdef SUPPORTS_TTY
- ctl_tty = (strcmp (native, "/dev/tty") == 0);
-#endif /* SUPPORTS_TTY */
if (fd < 0) {
- if (interp != (Tcl_Interp *) NULL) {
- Tcl_AppendResult(interp, "couldn't open \"",
- Tcl_GetString(pathPtr), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "couldn't open \"", TclGetString(pathPtr),
+ "\": ", Tcl_PosixError(interp), NULL);
}
return NULL;
}
@@ -1832,19 +1672,25 @@ TclpOpenFileChannel(interp, pathPtr, mode, permissions)
sprintf(channelName, "file%d", fd);
#ifdef SUPPORTS_TTY
- if (!ctl_tty && isatty(fd)) {
+ if (strcmp(native, "/dev/tty") != 0 && isatty(fd)) {
/*
- * Initialize the serial port to a set of sane parameters.
- * Especially important if the remote device is set to echo and
- * the serial port driver was also set to echo -- as soon as a char
- * were sent to the serial port, the remote device would echo it,
- * then the serial driver would echo it back to the device, etc.
+ * Initialize the serial port to a set of sane parameters. Especially
+ * important if the remote device is set to echo and the serial port
+ * driver was also set to echo -- as soon as a char were sent to the
+ * serial port, the remote device would echo it, then the serial
+ * driver would echo it back to the device, etc.
+ *
+ * Note that we do not do this if we're dealing with /dev/tty itself,
+ * as that tends to cause Bad Things To Happen when you're working
+ * interactively. Strictly a better check would be to see if the FD
+ * being set up is a device and has the same major/minor as the
+ * initial std FDs (beware reopening!) but that's nearly as messy.
*/
translation = "auto crlf";
channelTypePtr = &ttyChannelType;
fsPtr = TtyInit(fd, 1);
- } else
+ } else
#endif /* SUPPORTS_TTY */
{
translation = NULL;
@@ -1852,15 +1698,6 @@ TclpOpenFileChannel(interp, pathPtr, mode, permissions)
fsPtr = (FileState *) ckalloc((unsigned) sizeof(FileState));
}
-#ifdef DEPRECATED
- if (channelTypePtr == &fileChannelType) {
- /* TIP #218. Removed the code inserting the new structure
- * into the global list. This is now handled in the thread
- * action callbacks, and only there.
- */
- fsPtr->nextPtr = NULL;
- }
-#endif /* DEPRECATED */
fsPtr->validMask = channelPermissions | TCL_EXCEPTION;
fsPtr->fd = fd;
@@ -1869,11 +1706,11 @@ TclpOpenFileChannel(interp, pathPtr, mode, permissions)
if (translation != NULL) {
/*
- * Gotcha. Most modems need a "\r" at the end of the command
- * sequence. If you just send "at\n", the modem will not respond
- * with "OK" because it never got a "\r" to actually invoke the
- * command. So, by default, newlines are translated to "\r\n" on
- * output to avoid "bug" reports that the serial port isn't working.
+ * Gotcha. Most modems need a "\r" at the end of the command sequence.
+ * If you just send "at\n", the modem will not respond with "OK"
+ * because it never got a "\r" to actually invoke the command. So, by
+ * default, newlines are translated to "\r\n" on output to avoid "bug"
+ * reports that the serial port isn't working.
*/
if (Tcl_SetChannelOption(interp, fsPtr->channel, "-translation",
@@ -1903,18 +1740,15 @@ TclpOpenFileChannel(interp, pathPtr, mode, permissions)
*/
Tcl_Channel
-Tcl_MakeFileChannel(handle, mode)
- ClientData handle; /* OS level handle. */
- int mode; /* ORed combination of TCL_READABLE and
+Tcl_MakeFileChannel(
+ ClientData handle, /* OS level handle. */
+ int mode) /* ORed combination of TCL_READABLE and
* TCL_WRITABLE to indicate file mode. */
{
FileState *fsPtr;
char channelName[16 + TCL_INTEGER_SPACE];
- int fd = (int) handle;
+ int fd = PTR2INT(handle);
Tcl_ChannelType *channelTypePtr;
-#ifdef DEPRECATED
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-#endif /* DEPRECATED */
struct sockaddr sockaddr;
socklen_t sockaddrLen = sizeof(sockaddr);
@@ -1922,21 +1756,6 @@ Tcl_MakeFileChannel(handle, mode)
return NULL;
}
-
- /*
- * Look to see if a channel with this fd and the same mode already exists.
- * If the fd is used, but the mode doesn't match, return NULL.
- */
-
-#ifdef DEPRECATED
- for (fsPtr = tsdPtr->firstFilePtr; fsPtr != NULL; fsPtr = fsPtr->nextPtr) {
- if (fsPtr->fd == fd) {
- return ((mode|TCL_EXCEPTION) == fsPtr->validMask) ?
- fsPtr->channel : NULL;
- }
- }
-#endif /* DEPRECATED */
-
sockaddr.sa_family = AF_UNSPEC;
#ifdef SUPPORTS_TTY
@@ -1947,21 +1766,15 @@ Tcl_MakeFileChannel(handle, mode)
} else
#endif /* SUPPORTS_TTY */
if (getsockname(fd, (struct sockaddr *)&sockaddr, &sockaddrLen) == 0
- && sockaddrLen > 0
- && sockaddr.sa_family == AF_INET) {
- return MakeTcpClientChannelMode((ClientData) fd, mode);
+ && sockaddrLen > 0
+ && sockaddr.sa_family == AF_INET) {
+ return MakeTcpClientChannelMode((ClientData) INT2PTR(fd), mode);
} else {
- channelTypePtr = &fileChannelType;
- fsPtr = (FileState *) ckalloc((unsigned) sizeof(FileState));
- sprintf(channelName, "file%d", fd);
+ channelTypePtr = &fileChannelType;
+ fsPtr = (FileState *) ckalloc((unsigned) sizeof(FileState));
+ sprintf(channelName, "file%d", fd);
}
-#ifdef DEPRECATED
- if (channelTypePtr == &fileChannelType) {
- fsPtr->nextPtr = tsdPtr->firstFilePtr;
- tsdPtr->firstFilePtr = fsPtr;
- }
-#endif /* DEPRECATED */
fsPtr->fd = fd;
fsPtr->validMask = mode | TCL_EXCEPTION;
fsPtr->channel = Tcl_CreateChannel(channelTypePtr, channelName,
@@ -1975,8 +1788,8 @@ Tcl_MakeFileChannel(handle, mode)
*
* TcpBlockModeProc --
*
- * This procedure is invoked by the generic IO level to set blocking
- * and nonblocking mode on a TCP socket based channel.
+ * This function is invoked by the generic IO level to set blocking and
+ * nonblocking mode on a TCP socket based channel.
*
* Results:
* 0 if successful, errno when failed.
@@ -1989,43 +1802,22 @@ Tcl_MakeFileChannel(handle, mode)
/* ARGSUSED */
static int
-TcpBlockModeProc(instanceData, mode)
- ClientData instanceData; /* Socket state. */
- int mode; /* The mode to set. Can be one of
- * TCL_MODE_BLOCKING or
- * TCL_MODE_NONBLOCKING. */
+TcpBlockModeProc(
+ ClientData instanceData, /* Socket state. */
+ int mode) /* The mode to set. Can be one of
+ * TCL_MODE_BLOCKING or
+ * TCL_MODE_NONBLOCKING. */
{
TcpState *statePtr = (TcpState *) instanceData;
- int setting;
-#ifndef USE_FIONBIO
- setting = fcntl(statePtr->fd, F_GETFL);
if (mode == TCL_MODE_BLOCKING) {
- statePtr->flags &= (~(TCP_ASYNC_SOCKET));
- setting &= (~(O_NONBLOCK));
+ CLEAR_BITS(statePtr->flags, TCP_ASYNC_SOCKET);
} else {
- statePtr->flags |= TCP_ASYNC_SOCKET;
- setting |= O_NONBLOCK;
+ SET_BITS(statePtr->flags, TCP_ASYNC_SOCKET);
}
- if (fcntl(statePtr->fd, F_SETFL, setting) < 0) {
+ if (TclUnixSetBlockingMode(statePtr->fd, mode) < 0) {
return errno;
}
-#else /* USE_FIONBIO */
- if (mode == TCL_MODE_BLOCKING) {
- statePtr->flags &= (~(TCP_ASYNC_SOCKET));
- setting = 0;
- if (ioctl(statePtr->fd, (int) FIONBIO, &setting) == -1) {
- return errno;
- }
- } else {
- statePtr->flags |= TCP_ASYNC_SOCKET;
- setting = 1;
- if (ioctl(statePtr->fd, (int) FIONBIO, &setting) == -1) {
- return errno;
- }
- }
-#endif /* !USE_FIONBIO */
-
return 0;
}
@@ -2034,8 +1826,8 @@ TcpBlockModeProc(instanceData, mode)
*
* WaitForConnect --
*
- * Waits for a connection on an asynchronously opened socket to
- * be completed.
+ * Waits for a connection on an asynchronously opened socket to be
+ * completed.
*
* Results:
* None.
@@ -2047,17 +1839,16 @@ TcpBlockModeProc(instanceData, mode)
*/
static int
-WaitForConnect(statePtr, errorCodePtr)
- TcpState *statePtr; /* State of the socket. */
- int *errorCodePtr; /* Where to store errors? */
+WaitForConnect(
+ TcpState *statePtr, /* State of the socket. */
+ int *errorCodePtr) /* Where to store errors? */
{
int timeOut; /* How long to wait. */
int state; /* Of calling TclWaitForFile. */
- int flags; /* fcntl flags for the socket. */
/*
- * If an asynchronous connect is in progress, attempt to wait for it
- * to complete before reading.
+ * If an asynchronous connect is in progress, attempt to wait for it to
+ * complete before reading.
*/
if (statePtr->flags & TCP_ASYNC_CONNECT) {
@@ -2070,20 +1861,13 @@ WaitForConnect(statePtr, errorCodePtr)
state = TclUnixWaitForFile(statePtr->fd,
TCL_WRITABLE | TCL_EXCEPTION, timeOut);
if (!(statePtr->flags & TCP_ASYNC_SOCKET)) {
-#ifndef USE_FIONBIO
- flags = fcntl(statePtr->fd, F_GETFL);
- flags &= (~(O_NONBLOCK));
- (void) fcntl(statePtr->fd, F_SETFL, flags);
-#else /* USE_FIONBIO */
- flags = 0;
- (void) ioctl(statePtr->fd, FIONBIO, &flags);
-#endif /* !USE_FIONBIO */
+ (void) TclUnixSetBlockingMode(statePtr->fd, TCL_MODE_BLOCKING);
}
if (state & TCL_EXCEPTION) {
return -1;
}
if (state & TCL_WRITABLE) {
- statePtr->flags &= (~(TCP_ASYNC_CONNECT));
+ CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
} else if (timeOut == 0) {
*errorCodePtr = errno = EWOULDBLOCK;
return -1;
@@ -2097,16 +1881,16 @@ WaitForConnect(statePtr, errorCodePtr)
*
* TcpInputProc --
*
- * This procedure is invoked by the generic IO level to read input
- * from a TCP socket based channel.
+ * This function is invoked by the generic IO level to read input from a
+ * TCP socket based channel.
*
- * NOTE: We cannot share code with FilePipeInputProc because here
- * we must use recv to obtain the input from the channel, not read.
+ * NOTE: We cannot share code with FilePipeInputProc because here we must
+ * use recv to obtain the input from the channel, not read.
*
* Results:
* The number of bytes read is returned or -1 on error. An output
- * argument contains the POSIX error code on error, or zero if no
- * error occurred.
+ * argument contains the POSIX error code on error, or zero if no error
+ * occurred.
*
* Side effects:
* Reads input from the input device of the channel.
@@ -2116,12 +1900,12 @@ WaitForConnect(statePtr, errorCodePtr)
/* ARGSUSED */
static int
-TcpInputProc(instanceData, buf, bufSize, errorCodePtr)
- ClientData instanceData; /* Socket state. */
- char *buf; /* Where to store data read. */
- int bufSize; /* How much space is available
- * in the buffer? */
- int *errorCodePtr; /* Where to store error code. */
+TcpInputProc(
+ ClientData instanceData, /* Socket state. */
+ char *buf, /* Where to store data read. */
+ int bufSize, /* How much space is available in the
+ * buffer? */
+ int *errorCodePtr) /* Where to store error code. */
{
TcpState *statePtr = (TcpState *) instanceData;
int bytesRead, state;
@@ -2151,15 +1935,15 @@ TcpInputProc(instanceData, buf, bufSize, errorCodePtr)
*
* TcpOutputProc --
*
- * This procedure is invoked by the generic IO level to write output
- * to a TCP socket based channel.
+ * This function is invoked by the generic IO level to write output to a
+ * TCP socket based channel.
*
- * NOTE: We cannot share code with FilePipeOutputProc because here
- * we must use send, not write, to get reliable error reporting.
+ * NOTE: We cannot share code with FilePipeOutputProc because here we
+ * must use send, not write, to get reliable error reporting.
*
* Results:
- * The number of bytes written is returned. An output argument is
- * set to a POSIX error code if an error occurred, or zero.
+ * The number of bytes written is returned. An output argument is set to
+ * a POSIX error code if an error occurred, or zero.
*
* Side effects:
* Writes output on the output device of the channel.
@@ -2168,11 +1952,11 @@ TcpInputProc(instanceData, buf, bufSize, errorCodePtr)
*/
static int
-TcpOutputProc(instanceData, buf, toWrite, errorCodePtr)
- ClientData instanceData; /* Socket state. */
- CONST char *buf; /* The data buffer. */
- int toWrite; /* How many bytes to write? */
- int *errorCodePtr; /* Where to store error code. */
+TcpOutputProc(
+ ClientData instanceData, /* Socket state. */
+ const char *buf, /* The data buffer. */
+ int toWrite, /* How many bytes to write? */
+ int *errorCodePtr) /* Where to store error code. */
{
TcpState *statePtr = (TcpState *) instanceData;
int written;
@@ -2196,9 +1980,9 @@ TcpOutputProc(instanceData, buf, toWrite, errorCodePtr)
*
* TcpCloseProc --
*
- * This procedure is invoked by the generic IO level to perform
- * channel-type-specific cleanup when a TCP socket based channel
- * is closed.
+ * This function is invoked by the generic IO level to perform
+ * channel-type-specific cleanup when a TCP socket based channel is
+ * closed.
*
* Results:
* 0 if successful, the value of errno if failed.
@@ -2211,20 +1995,19 @@ TcpOutputProc(instanceData, buf, toWrite, errorCodePtr)
/* ARGSUSED */
static int
-TcpCloseProc(instanceData, interp)
- ClientData instanceData; /* The socket to close. */
- Tcl_Interp *interp; /* For error reporting - unused. */
+TcpCloseProc(
+ ClientData instanceData, /* The socket to close. */
+ Tcl_Interp *interp) /* For error reporting - unused. */
{
TcpState *statePtr = (TcpState *) instanceData;
int errorCode = 0;
/*
- * Delete a file handler that may be active for this socket if this
- * is a server socket - the file handler was created automatically
- * by Tcl as part of the mechanism to accept new client connections.
- * Channel handlers are already deleted in the generic IO channel
- * closing code that called this function, so we do not have to
- * delete them here.
+ * Delete a file handler that may be active for this socket if this is a
+ * server socket - the file handler was created automatically by Tcl as
+ * part of the mechanism to accept new client connections. Channel
+ * handlers are already deleted in the generic IO channel closing code
+ * that called this function, so we do not have to delete them here.
*/
Tcl_DeleteFileHandler(statePtr->fd);
@@ -2242,15 +2025,15 @@ TcpCloseProc(instanceData, interp)
*
* TcpGetOptionProc --
*
- * Computes an option value for a TCP socket based channel, or a
- * list of all options and their values.
+ * Computes an option value for a TCP socket based channel, or a list of
+ * all options and their values.
*
* Note: This code is based on code contributed by John Haxby.
*
* Results:
- * A standard Tcl result. The value of the specified option or a
- * list of all options and their values is returned in the
- * supplied DString. Sets Error message if needed.
+ * A standard Tcl result. The value of the specified option or a list of
+ * all options and their values is returned in the supplied DString. Sets
+ * Error message if needed.
*
* Side effects:
* None.
@@ -2259,15 +2042,14 @@ TcpCloseProc(instanceData, interp)
*/
static int
-TcpGetOptionProc(instanceData, interp, optionName, dsPtr)
- ClientData instanceData; /* Socket state. */
- Tcl_Interp *interp; /* For error reporting - can be NULL. */
- CONST char *optionName; /* Name of the option to
- * retrieve the value for, or
- * NULL to get all options and
- * their values. */
- Tcl_DString *dsPtr; /* Where to store the computed
- * value; initialized by caller. */
+TcpGetOptionProc(
+ ClientData instanceData, /* Socket state. */
+ Tcl_Interp *interp, /* For error reporting - can be NULL. */
+ const char *optionName, /* Name of the option to retrieve the value
+ * for, or NULL to get all options and their
+ * values. */
+ Tcl_DString *dsPtr) /* Where to store the computed value;
+ * initialized by caller. */
{
TcpState *statePtr = (TcpState *) instanceData;
struct sockaddr_in sockname;
@@ -2277,7 +2059,7 @@ TcpGetOptionProc(instanceData, interp, optionName, dsPtr)
size_t len = 0;
char buf[TCL_INTEGER_SPACE];
- if (optionName != (char *) NULL) {
+ if (optionName != NULL) {
len = strlen(optionName);
}
@@ -2310,7 +2092,7 @@ TcpGetOptionProc(instanceData, interp, optionName, dsPtr)
hostEntPtr = TclpGetHostByAddr( /* INTL: Native. */
(char *) &peername.sin_addr,
sizeof(peername.sin_addr), AF_INET);
- if (hostEntPtr != (struct hostent *) NULL) {
+ if (hostEntPtr != NULL) {
Tcl_DString ds;
Tcl_ExternalToUtfDString(NULL, hostEntPtr->h_name, -1, &ds);
@@ -2329,15 +2111,15 @@ TcpGetOptionProc(instanceData, interp, optionName, dsPtr)
} else {
/*
* getpeername failed - but if we were asked for all the options
- * (len==0), don't flag an error at that point because it could
- * be an fconfigure request on a server socket. (which have
- * no peer). same must be done on win&mac.
+ * (len==0), don't flag an error at that point because it could be
+ * an fconfigure request on a server socket (which have no peer).
+ * Same must be done on win&mac.
*/
if (len) {
if (interp) {
Tcl_AppendResult(interp, "can't get peername: ",
- Tcl_PosixError(interp), (char *) NULL);
+ Tcl_PosixError(interp), NULL);
}
return TCL_ERROR;
}
@@ -2348,7 +2130,7 @@ TcpGetOptionProc(instanceData, interp, optionName, dsPtr)
((len > 1) && (optionName[1] == 's') &&
(strncmp(optionName, "-sockname", len) == 0))) {
if (getsockname(statePtr->fd, (struct sockaddr *) &sockname,
- &size) >= 0) {
+ &size) >= 0) {
if (len == 0) {
Tcl_DStringAppendElement(dsPtr, "-sockname");
Tcl_DStringStartSublist(dsPtr);
@@ -2366,9 +2148,9 @@ TcpGetOptionProc(instanceData, interp, optionName, dsPtr)
(char *) &sockname.sin_addr,
sizeof(sockname.sin_addr), AF_INET);
}
- if (hostEntPtr != (struct hostent *) NULL) {
+ if (hostEntPtr != NULL) {
Tcl_DString ds;
-
+
Tcl_ExternalToUtfDString(NULL, hostEntPtr->h_name, -1, &ds);
Tcl_DStringAppendElement(dsPtr, Tcl_DStringValue(&ds));
Tcl_DStringFree(&ds);
@@ -2385,7 +2167,7 @@ TcpGetOptionProc(instanceData, interp, optionName, dsPtr)
} else {
if (interp) {
Tcl_AppendResult(interp, "can't get sockname: ",
- Tcl_PosixError(interp), (char *) NULL);
+ Tcl_PosixError(interp), NULL);
}
return TCL_ERROR;
}
@@ -2409,25 +2191,25 @@ TcpGetOptionProc(instanceData, interp, optionName, dsPtr)
* None.
*
* Side effects:
- * Sets up the notifier so that a future event on the channel will
- * be seen by Tcl.
+ * Sets up the notifier so that a future event on the channel will be
+ * seen by Tcl.
*
*----------------------------------------------------------------------
*/
static void
-TcpWatchProc(instanceData, mask)
- ClientData instanceData; /* The socket state. */
- int mask; /* Events of interest; an OR-ed
- * combination of TCL_READABLE,
- * TCL_WRITABLE and TCL_EXCEPTION. */
+TcpWatchProc(
+ ClientData instanceData, /* The socket state. */
+ int mask) /* Events of interest; an OR-ed combination of
+ * TCL_READABLE, TCL_WRITABLE and
+ * TCL_EXCEPTION. */
{
TcpState *statePtr = (TcpState *) instanceData;
/*
- * Make sure we don't mess with server sockets since they will never
- * be readable or writable at the Tcl level. This keeps Tcl scripts
- * from interfering with the -accept behavior.
+ * Make sure we don't mess with server sockets since they will never be
+ * readable or writable at the Tcl level. This keeps Tcl scripts from
+ * interfering with the -accept behavior.
*/
if (!statePtr->acceptProc) {
@@ -2446,12 +2228,12 @@ TcpWatchProc(instanceData, mask)
*
* TcpGetHandleProc --
*
- * Called from Tcl_GetChannelHandle to retrieve OS handles from inside
- * a TCP socket based channel.
+ * Called from Tcl_GetChannelHandle to retrieve OS handles from inside a
+ * TCP socket based channel.
*
* Results:
- * Returns TCL_OK with the fd in handlePtr, or TCL_ERROR if
- * there is no handle for the specified direction.
+ * Returns TCL_OK with the fd in handlePtr, or TCL_ERROR if there is no
+ * handle for the specified direction.
*
* Side effects:
* None.
@@ -2461,14 +2243,14 @@ TcpWatchProc(instanceData, mask)
/* ARGSUSED */
static int
-TcpGetHandleProc(instanceData, direction, handlePtr)
- ClientData instanceData; /* The socket state. */
- int direction; /* Not used. */
- ClientData *handlePtr; /* Where to store the handle. */
+TcpGetHandleProc(
+ ClientData instanceData, /* The socket state. */
+ int direction, /* Not used. */
+ ClientData *handlePtr) /* Where to store the handle. */
{
TcpState *statePtr = (TcpState *) instanceData;
- *handlePtr = (ClientData)statePtr->fd;
+ *handlePtr = (ClientData) INT2PTR(statePtr->fd);
return TCL_OK;
}
@@ -2477,12 +2259,12 @@ TcpGetHandleProc(instanceData, direction, handlePtr)
*
* CreateSocket --
*
- * This function opens a new socket in client or server mode
- * and initializes the TcpState structure.
+ * This function opens a new socket in client or server mode and
+ * initializes the TcpState structure.
*
* Results:
- * Returns a new TcpState, or NULL with an error in the interp's
- * result, if interp is not NULL.
+ * Returns a new TcpState, or NULL with an error in the interp's result,
+ * if interp is not NULL.
*
* Side effects:
* Opens a socket.
@@ -2491,31 +2273,31 @@ TcpGetHandleProc(instanceData, direction, handlePtr)
*/
static TcpState *
-CreateSocket(interp, port, host, server, myaddr, myport, async)
- Tcl_Interp *interp; /* For error reporting; can be NULL. */
- int port; /* Port number to open. */
- CONST char *host; /* Name of host on which to open port.
- * NULL implies INADDR_ANY */
- int server; /* 1 if socket should be a server socket,
- * else 0 for a client socket. */
- CONST char *myaddr; /* Optional client-side address */
- int myport; /* Optional client-side port */
- int async; /* If nonzero and creating a client socket,
+CreateSocket(
+ Tcl_Interp *interp, /* For error reporting; can be NULL. */
+ int port, /* Port number to open. */
+ const char *host, /* Name of host on which to open port. NULL
+ * implies INADDR_ANY */
+ int server, /* 1 if socket should be a server socket, else
+ * 0 for a client socket. */
+ const char *myaddr, /* Optional client-side address */
+ int myport, /* Optional client-side port */
+ int async) /* If nonzero and creating a client socket,
* attempt to do an async connect. Otherwise
* do a synchronous connect or bind. */
{
- int status, sock, asyncConnect, curState, origState;
+ int status, sock, asyncConnect, curState;
struct sockaddr_in sockaddr; /* socket address */
struct sockaddr_in mysockaddr; /* Socket address for client */
TcpState *statePtr;
+ const char *errorMsg = NULL;
sock = -1;
- origState = 0;
- if (! CreateSocketAddress(&sockaddr, host, port)) {
+ if (!CreateSocketAddress(&sockaddr, host, port, 0, &errorMsg)) {
goto addressError;
}
if ((myaddr != NULL || myport != 0) &&
- ! CreateSocketAddress(&mysockaddr, myaddr, myport)) {
+ !CreateSocketAddress(&mysockaddr, myaddr, myport, 1, &errorMsg)) {
goto addressError;
}
@@ -2525,8 +2307,8 @@ CreateSocket(interp, port, host, server, myaddr, myport, async)
}
/*
- * Set the close-on-exec flag so that the socket will not get
- * inherited by child processes.
+ * Set the close-on-exec flag so that the socket will not get inherited by
+ * child processes.
*/
fcntl(sock, F_SETFD, FD_CLOEXEC);
@@ -2552,9 +2334,9 @@ CreateSocket(interp, port, host, server, myaddr, myport, async)
sizeof(struct sockaddr));
if (status != -1) {
status = listen(sock, SOMAXCONN);
- }
+ }
} else {
- if (myaddr != NULL || myport != 0) {
+ if (myaddr != NULL || myport != 0) {
curState = 1;
(void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(char *) &curState, sizeof(curState));
@@ -2567,20 +2349,13 @@ CreateSocket(interp, port, host, server, myaddr, myport, async)
/*
* Attempt to connect. The connect may fail at present with an
- * EINPROGRESS but at a later time it will complete. The caller
- * will set up a file handler on the socket if she is interested in
- * being informed when the connect completes.
+ * EINPROGRESS but at a later time it will complete. The caller will
+ * set up a file handler on the socket if she is interested in being
+ * informed when the connect completes.
*/
if (async) {
-#ifndef USE_FIONBIO
- origState = fcntl(sock, F_GETFL);
- curState = origState | O_NONBLOCK;
- status = fcntl(sock, F_SETFL, curState);
-#else /* USE_FIONBIO */
- curState = 1;
- status = ioctl(sock, FIONBIO, &curState);
-#endif /* !USE_FIONBIO */
+ status = TclUnixSetBlockingMode(sock, TCL_MODE_NONBLOCKING);
} else {
status = 0;
}
@@ -2596,29 +2371,23 @@ CreateSocket(interp, port, host, server, myaddr, myport, async)
/*
* Here we are if the connect succeeds. In case of an
* asynchronous connect we have to reset the channel to
- * blocking mode. This appears to happen not very often,
- * but e.g. on a HP 9000/800 under HP-UX B.11.00 we enter
- * this stage. [Bug: 4388]
+ * blocking mode. This appears to happen not very often, but
+ * e.g. on a HP 9000/800 under HP-UX B.11.00 we enter this
+ * stage. [Bug: 4388]
*/
+
if (async) {
-#ifndef USE_FIONBIO
- origState = fcntl(sock, F_GETFL);
- curState = origState & ~(O_NONBLOCK);
- status = fcntl(sock, F_SETFL, curState);
-#else /* USE_FIONBIO */
- curState = 0;
- status = ioctl(sock, FIONBIO, &curState);
-#endif /* !USE_FIONBIO */
+ status = TclUnixSetBlockingMode(sock, TCL_MODE_BLOCKING);
}
}
}
}
-bindError:
+ bindError:
if (status < 0) {
if (interp != NULL) {
Tcl_AppendResult(interp, "couldn't open socket: ",
- Tcl_PosixError(interp), (char *) NULL);
+ Tcl_PosixError(interp), NULL);
}
if (sock != -1) {
close(sock);
@@ -2639,13 +2408,16 @@ bindError:
return statePtr;
-addressError:
+ addressError:
if (sock != -1) {
close(sock);
}
if (interp != NULL) {
Tcl_AppendResult(interp, "couldn't open socket: ",
- Tcl_PosixError(interp), (char *) NULL);
+ Tcl_PosixError(interp), NULL);
+ if (errorMsg != NULL) {
+ Tcl_AppendResult(interp, " (", errorMsg, ")", NULL);
+ }
}
return NULL;
}
@@ -2658,8 +2430,8 @@ addressError:
* This function initializes a sockaddr structure for a host and port.
*
* Results:
- * 1 if the host was valid, 0 if the host could not be converted to
- * an IP address.
+ * 1 if the host was valid, 0 if the host could not be converted to an IP
+ * address.
*
* Side effects:
* Fills in the *sockaddrPtr structure.
@@ -2668,22 +2440,85 @@ addressError:
*/
static int
-CreateSocketAddress(sockaddrPtr, host, port)
- struct sockaddr_in *sockaddrPtr; /* Socket address */
- CONST char *host; /* Host. NULL implies INADDR_ANY */
- int port; /* Port number */
+CreateSocketAddress(
+ struct sockaddr_in *sockaddrPtr, /* Socket address */
+ const char *host, /* Host. NULL implies INADDR_ANY */
+ int port, /* Port number */
+ int willBind, /* Is this an address to bind() to or
+ * to connect() to? */
+ const char **errorMsgPtr) /* Place to store the error message
+ * detail, if available. */
{
- struct hostent *hostent; /* Host database entry */
+#ifdef HAVE_GETADDRINFO
+ struct addrinfo hints, *resPtr = NULL;
+ char *native;
+ Tcl_DString ds;
+ int result;
+
+ if (host == NULL) {
+ sockaddrPtr->sin_family = AF_INET;
+ sockaddrPtr->sin_addr.s_addr = INADDR_ANY;
+ addPort:
+ sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF));
+ return 1;
+ }
+
+ (void) memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ if (willBind) {
+ hints.ai_flags |= AI_PASSIVE;
+ }
+
+ /*
+ * Note that getaddrinfo() *is* thread-safe. If a platform doesn't get
+ * that right, it shouldn't use this part of the code.
+ */
+
+ native = Tcl_UtfToExternalDString(NULL, host, -1, &ds);
+ result = getaddrinfo(native, NULL, &hints, &resPtr);
+ Tcl_DStringFree(&ds);
+ if (result == 0) {
+ memcpy(sockaddrPtr, resPtr->ai_addr, sizeof(struct sockaddr_in));
+ freeaddrinfo(resPtr);
+ goto addPort;
+ }
+
+ /*
+ * Ought to use gai_strerror() here...
+ */
+
+ switch (result) {
+ case EAI_NONAME:
+ case EAI_SERVICE:
+#if defined(EAI_ADDRFAMILY) && EAI_ADDRFAMILY != EAI_NONAME
+ case EAI_ADDRFAMILY:
+#endif
+#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME
+ case EAI_NODATA:
+#endif
+ *errorMsgPtr = gai_strerror(result);
+ errno = EHOSTUNREACH;
+ return 0;
+ case EAI_SYSTEM:
+ return 0;
+ default:
+ *errorMsgPtr = gai_strerror(result);
+ errno = ENXIO;
+ return 0;
+ }
+#else /* !HAVE_GETADDRINFO */
struct in_addr addr; /* For 64/32 bit madness */
- (void) memset((VOID *) sockaddrPtr, '\0', sizeof(struct sockaddr_in));
+ (void) memset(sockaddrPtr, '\0', sizeof(struct sockaddr_in));
sockaddrPtr->sin_family = AF_INET;
sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF));
if (host == NULL) {
addr.s_addr = INADDR_ANY;
} else {
+ struct hostent *hostent; /* Host database entry */
Tcl_DString ds;
- CONST char *native;
+ const char *native;
if (host == NULL) {
native = NULL;
@@ -2691,15 +2526,16 @@ CreateSocketAddress(sockaddrPtr, host, port)
native = Tcl_UtfToExternalDString(NULL, host, -1, &ds);
}
addr.s_addr = inet_addr(native); /* INTL: Native. */
+
/*
- * This is 0xFFFFFFFF to ensure that it compares as a 32bit -1
- * on either 32 or 64 bits systems.
+ * This is 0xFFFFFFFF to ensure that it compares as a 32bit -1 on
+ * either 32 or 64 bits systems.
*/
+
if (addr.s_addr == 0xFFFFFFFF) {
- hostent = TclpGetHostByName(native); /* INTL: Native. */
- if (hostent != (struct hostent *) NULL) {
- memcpy((VOID *) &addr,
- (VOID *) hostent->h_addr_list[0],
+ hostent = TclpGetHostByName(native); /* INTL: Native. */
+ if (hostent != NULL) {
+ memcpy(&addr, hostent->h_addr_list[0],
(size_t) hostent->h_length);
} else {
#ifdef EHOSTUNREACH
@@ -2712,7 +2548,7 @@ CreateSocketAddress(sockaddrPtr, host, port)
if (native != NULL) {
Tcl_DStringFree(&ds);
}
- return 0; /* error */
+ return 0; /* Error. */
}
}
if (native != NULL) {
@@ -2721,14 +2557,15 @@ CreateSocketAddress(sockaddrPtr, host, port)
}
/*
- * NOTE: On 64 bit machines the assignment below is rumored to not
- * do the right thing. Please report errors related to this if you
- * observe incorrect behavior on 64 bit machines such as DEC Alphas.
- * Should we modify this code to do an explicit memcpy?
+ * NOTE: On 64 bit machines the assignment below is rumored to not do the
+ * right thing. Please report errors related to this if you observe
+ * incorrect behavior on 64 bit machines such as DEC Alphas. Should we
+ * modify this code to do an explicit memcpy?
*/
sockaddrPtr->sin_addr.s_addr = addr.s_addr;
- return 1; /* Success. */
+ return 1; /* Success. */
+#endif /* HAVE_GETADDRINFO */
}
/*
@@ -2739,8 +2576,8 @@ CreateSocketAddress(sockaddrPtr, host, port)
* Opens a TCP client socket and creates a channel around it.
*
* Results:
- * The channel or NULL if failed. An error message is returned
- * in the interpreter on failure.
+ * The channel or NULL if failed. An error message is returned in the
+ * interpreter on failure.
*
* Side effects:
* Opens a client socket and creates a new channel.
@@ -2749,15 +2586,15 @@ CreateSocketAddress(sockaddrPtr, host, port)
*/
Tcl_Channel
-Tcl_OpenTcpClient(interp, port, host, myaddr, myport, async)
- Tcl_Interp *interp; /* For error reporting; can be NULL. */
- int port; /* Port number to open. */
- CONST char *host; /* Host on which to open port. */
- CONST char *myaddr; /* Client-side address */
- int myport; /* Client-side port */
- int async; /* If nonzero, attempt to do an
- * asynchronous connect. Otherwise
- * we do a blocking connect. */
+Tcl_OpenTcpClient(
+ Tcl_Interp *interp, /* For error reporting; can be NULL. */
+ int port, /* Port number to open. */
+ const char *host, /* Host on which to open port. */
+ const char *myaddr, /* Client-side address */
+ int myport, /* Client-side port */
+ int async) /* If nonzero, attempt to do an asynchronous
+ * connect. Otherwise we do a blocking
+ * connect. */
{
TcpState *statePtr;
char channelName[16 + TCL_INTEGER_SPACE];
@@ -2772,7 +2609,7 @@ Tcl_OpenTcpClient(interp, port, host, myaddr, myport, async)
}
statePtr->acceptProc = NULL;
- statePtr->acceptProcData = (ClientData) NULL;
+ statePtr->acceptProcData = NULL;
sprintf(channelName, "sock%d", statePtr->fd);
@@ -2780,7 +2617,7 @@ Tcl_OpenTcpClient(interp, port, host, myaddr, myport, async)
(ClientData) statePtr, (TCL_READABLE | TCL_WRITABLE));
if (Tcl_SetChannelOption(interp, statePtr->channel, "-translation",
"auto crlf") == TCL_ERROR) {
- Tcl_Close((Tcl_Interp *) NULL, statePtr->channel);
+ Tcl_Close(NULL, statePtr->channel);
return NULL;
}
return statePtr->channel;
@@ -2803,8 +2640,8 @@ Tcl_OpenTcpClient(interp, port, host, myaddr, myport, async)
*/
Tcl_Channel
-Tcl_MakeTcpClientChannel(sock)
- ClientData sock; /* The socket to wrap up into a channel. */
+Tcl_MakeTcpClientChannel(
+ ClientData sock) /* The socket to wrap up into a channel. */
{
return MakeTcpClientChannelMode(sock, (TCL_READABLE | TCL_WRITABLE));
}
@@ -2827,27 +2664,27 @@ Tcl_MakeTcpClientChannel(sock)
*/
static Tcl_Channel
-MakeTcpClientChannelMode(sock, mode)
- ClientData sock; /* The socket to wrap up into a channel. */
- int mode; /* ORed combination of TCL_READABLE and
+MakeTcpClientChannelMode(
+ ClientData sock, /* The socket to wrap up into a channel. */
+ int mode) /* ORed combination of TCL_READABLE and
* TCL_WRITABLE to indicate file mode. */
{
TcpState *statePtr;
char channelName[16 + TCL_INTEGER_SPACE];
statePtr = (TcpState *) ckalloc((unsigned) sizeof(TcpState));
- statePtr->fd = (int) sock;
+ statePtr->fd = PTR2INT(sock);
statePtr->flags = 0;
statePtr->acceptProc = NULL;
- statePtr->acceptProcData = (ClientData) NULL;
+ statePtr->acceptProcData = NULL;
sprintf(channelName, "sock%d", statePtr->fd);
statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
(ClientData) statePtr, mode);
- if (Tcl_SetChannelOption((Tcl_Interp *) NULL, statePtr->channel,
- "-translation", "auto crlf") == TCL_ERROR) {
- Tcl_Close((Tcl_Interp *) NULL, statePtr->channel);
+ if (Tcl_SetChannelOption(NULL, statePtr->channel, "-translation",
+ "auto crlf") == TCL_ERROR) {
+ Tcl_Close(NULL, statePtr->channel);
return NULL;
}
return statePtr->channel;
@@ -2861,9 +2698,8 @@ MakeTcpClientChannelMode(sock, mode)
* Opens a TCP server socket and creates a channel around it.
*
* Results:
- * The channel or NULL if failed. If an error occurred, an
- * error message is left in the interp's result if interp is
- * not NULL.
+ * The channel or NULL if failed. If an error occurred, an error message
+ * is left in the interp's result if interp is not NULL.
*
* Side effects:
* Opens a server socket and creates a new channel.
@@ -2872,14 +2708,14 @@ MakeTcpClientChannelMode(sock, mode)
*/
Tcl_Channel
-Tcl_OpenTcpServer(interp, port, myHost, acceptProc, acceptProcData)
- Tcl_Interp *interp; /* For error reporting - may be
- * NULL. */
- int port; /* Port number to open. */
- CONST char *myHost; /* Name of local host. */
- Tcl_TcpAcceptProc *acceptProc; /* Callback for accepting connections
- * from new clients. */
- ClientData acceptProcData; /* Data for the callback. */
+Tcl_OpenTcpServer(
+ Tcl_Interp *interp, /* For error reporting - may be NULL. */
+ int port, /* Port number to open. */
+ const char *myHost, /* Name of local host. */
+ Tcl_TcpAcceptProc *acceptProc,
+ /* Callback for accepting connections from new
+ * clients. */
+ ClientData acceptProcData) /* Data for the callback. */
{
TcpState *statePtr;
char channelName[16 + TCL_INTEGER_SPACE];
@@ -2897,8 +2733,8 @@ Tcl_OpenTcpServer(interp, port, myHost, acceptProc, acceptProcData)
statePtr->acceptProcData = acceptProcData;
/*
- * Set up the callback mechanism for accepting connections
- * from new clients.
+ * Set up the callback mechanism for accepting connections from new
+ * clients.
*/
Tcl_CreateFileHandler(statePtr->fd, TCL_READABLE, TcpAccept,
@@ -2919,23 +2755,23 @@ Tcl_OpenTcpServer(interp, port, myHost, acceptProc, acceptProcData)
* None.
*
* Side effects:
- * Creates a new connection socket. Calls the registered callback
- * for the connection acceptance mechanism.
+ * Creates a new connection socket. Calls the registered callback for the
+ * connection acceptance mechanism.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
static void
-TcpAccept(data, mask)
- ClientData data; /* Callback token. */
- int mask; /* Not used. */
+TcpAccept(
+ ClientData data, /* Callback token. */
+ int mask) /* Not used. */
{
- TcpState *sockState; /* Client data of server socket. */
- int newsock; /* The new client socket */
- TcpState *newSockState; /* State for new socket. */
- struct sockaddr_in addr; /* The remote address */
- socklen_t len; /* For accept interface */
+ TcpState *sockState; /* Client data of server socket. */
+ int newsock; /* The new client socket */
+ TcpState *newSockState; /* State for new socket. */
+ struct sockaddr_in addr; /* The remote address */
+ socklen_t len; /* For accept interface */
char channelName[16 + TCL_INTEGER_SPACE];
sockState = (TcpState *) data;
@@ -2947,8 +2783,8 @@ TcpAccept(data, mask)
}
/*
- * Set close-on-exec flag to prevent the newly accepted socket from
- * being inherited by child processes.
+ * Set close-on-exec flag to prevent the newly accepted socket from being
+ * inherited by child processes.
*/
(void) fcntl(newsock, F_SETFD, FD_CLOEXEC);
@@ -2979,22 +2815,21 @@ TcpAccept(data, mask)
*
* TclpGetDefaultStdChannel --
*
- * Creates channels for standard input, standard output or standard
- * error output if they do not already exist.
+ * Creates channels for standard input, standard output or standard error
+ * output if they do not already exist.
*
* Results:
* Returns the specified default standard channel, or NULL.
*
* Side effects:
- * May cause the creation of a standard channel and the underlying
- * file.
+ * May cause the creation of a standard channel and the underlying file.
*
*----------------------------------------------------------------------
*/
Tcl_Channel
-TclpGetDefaultStdChannel(type)
- int type; /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR. */
+TclpGetDefaultStdChannel(
+ int type) /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR. */
{
Tcl_Channel channel = NULL;
int fd = 0; /* Initializations needed to prevent */
@@ -3004,46 +2839,47 @@ TclpGetDefaultStdChannel(type)
/*
* Some #def's to make the code a little clearer!
*/
+
#define ZERO_OFFSET ((Tcl_SeekOffset) 0)
#define ERROR_OFFSET ((Tcl_SeekOffset) -1)
switch (type) {
- case TCL_STDIN:
- if ((TclOSseek(0, ZERO_OFFSET, SEEK_CUR) == ERROR_OFFSET)
- && (errno == EBADF)) {
- return (Tcl_Channel) NULL;
- }
- fd = 0;
- mode = TCL_READABLE;
- bufMode = "line";
- break;
- case TCL_STDOUT:
- if ((TclOSseek(1, ZERO_OFFSET, SEEK_CUR) == ERROR_OFFSET)
- && (errno == EBADF)) {
- return (Tcl_Channel) NULL;
- }
- fd = 1;
- mode = TCL_WRITABLE;
- bufMode = "line";
- break;
- case TCL_STDERR:
- if ((TclOSseek(2, ZERO_OFFSET, SEEK_CUR) == ERROR_OFFSET)
- && (errno == EBADF)) {
- return (Tcl_Channel) NULL;
- }
- fd = 2;
- mode = TCL_WRITABLE;
- bufMode = "none";
- break;
- default:
- panic("TclGetDefaultStdChannel: Unexpected channel type");
- break;
+ case TCL_STDIN:
+ if ((TclOSseek(0, ZERO_OFFSET, SEEK_CUR) == ERROR_OFFSET)
+ && (errno == EBADF)) {
+ return NULL;
+ }
+ fd = 0;
+ mode = TCL_READABLE;
+ bufMode = "line";
+ break;
+ case TCL_STDOUT:
+ if ((TclOSseek(1, ZERO_OFFSET, SEEK_CUR) == ERROR_OFFSET)
+ && (errno == EBADF)) {
+ return NULL;
+ }
+ fd = 1;
+ mode = TCL_WRITABLE;
+ bufMode = "line";
+ break;
+ case TCL_STDERR:
+ if ((TclOSseek(2, ZERO_OFFSET, SEEK_CUR) == ERROR_OFFSET)
+ && (errno == EBADF)) {
+ return NULL;
+ }
+ fd = 2;
+ mode = TCL_WRITABLE;
+ bufMode = "none";
+ break;
+ default:
+ Tcl_Panic("TclGetDefaultStdChannel: Unexpected channel type");
+ break;
}
#undef ZERO_OFFSET
#undef ERROR_OFFSET
- channel = Tcl_MakeFileChannel((ClientData) fd, mode);
+ channel = Tcl_MakeFileChannel((ClientData) INT2PTR(fd), mode);
if (channel == NULL) {
return NULL;
}
@@ -3066,16 +2902,16 @@ TclpGetDefaultStdChannel(type)
*
* Tcl_GetOpenFile --
*
- * Given a name of a channel registered in the given interpreter,
- * returns a FILE * for it.
+ * Given a name of a channel registered in the given interpreter, returns
+ * a FILE * for it.
*
* Results:
* A standard Tcl result. If the channel is registered in the given
- * interpreter and it is managed by the "file" channel driver, and
- * it is open for the requested mode, then the output parameter
- * filePtr is set to a FILE * for the underlying file. On error, the
- * filePtr is not set, TCL_ERROR is returned and an error message is
- * left in the interp's result.
+ * interpreter and it is managed by the "file" channel driver, and it is
+ * open for the requested mode, then the output parameter filePtr is set
+ * to a FILE * for the underlying file. On error, the filePtr is not set,
+ * TCL_ERROR is returned and an error message is left in the interp's
+ * result.
*
* Side effects:
* May invoke fdopen to create the FILE * for the requested file.
@@ -3084,36 +2920,35 @@ TclpGetDefaultStdChannel(type)
*/
int
-Tcl_GetOpenFile(interp, string, forWriting, checkUsage, filePtr)
- Tcl_Interp *interp; /* Interpreter in which to find file. */
- CONST char *string; /* String that identifies file. */
- int forWriting; /* 1 means the file is going to be used
- * for writing, 0 means for reading. */
- int checkUsage; /* 1 means verify that the file was opened
- * in a mode that allows the access specified
- * by "forWriting". Ignored, we always
- * check that the channel is open for the
- * requested mode. */
- ClientData *filePtr; /* Store pointer to FILE structure here. */
+Tcl_GetOpenFile(
+ Tcl_Interp *interp, /* Interpreter in which to find file. */
+ const char *chanID, /* String that identifies file. */
+ int forWriting, /* 1 means the file is going to be used for
+ * writing, 0 means for reading. */
+ int checkUsage, /* 1 means verify that the file was opened in
+ * a mode that allows the access specified by
+ * "forWriting". Ignored, we always check that
+ * the channel is open for the requested
+ * mode. */
+ ClientData *filePtr) /* Store pointer to FILE structure here. */
{
Tcl_Channel chan;
- int chanMode;
- Tcl_ChannelType *chanTypePtr;
+ int chanMode, fd;
+ const Tcl_ChannelType *chanTypePtr;
ClientData data;
- int fd;
FILE *f;
- chan = Tcl_GetChannel(interp, string, &chanMode);
+ chan = Tcl_GetChannel(interp, chanID, &chanMode);
if (chan == (Tcl_Channel) NULL) {
return TCL_ERROR;
}
if ((forWriting) && ((chanMode & TCL_WRITABLE) == 0)) {
- Tcl_AppendResult(interp,
- "\"", string, "\" wasn't opened for writing", (char *) NULL);
+ Tcl_AppendResult(interp, "\"", chanID, "\" wasn't opened for writing",
+ NULL);
return TCL_ERROR;
- } else if ((!(forWriting)) && ((chanMode & TCL_READABLE) == 0)) {
- Tcl_AppendResult(interp,
- "\"", string, "\" wasn't opened for reading", (char *) NULL);
+ } else if ((!forWriting) && ((chanMode & TCL_READABLE) == 0)) {
+ Tcl_AppendResult(interp, "\"", chanID, "\" wasn't opened for reading",
+ NULL);
return TCL_ERROR;
}
@@ -3133,18 +2968,18 @@ Tcl_GetOpenFile(interp, string, forWriting, checkUsage, filePtr)
if (Tcl_GetChannelHandle(chan,
(forWriting ? TCL_WRITABLE : TCL_READABLE),
(ClientData*) &data) == TCL_OK) {
- fd = (int) data;
+ fd = PTR2INT(data);
/*
* The call to fdopen below is probably dangerous, since it will
- * truncate an existing file if the file is being opened
- * for writing....
+ * truncate an existing file if the file is being opened for
+ * writing....
*/
f = fdopen(fd, (forWriting ? "w" : "r"));
if (f == NULL) {
- Tcl_AppendResult(interp, "cannot get a FILE * for \"", string,
- "\"", (char *) NULL);
+ Tcl_AppendResult(interp, "cannot get a FILE * for \"", chanID,
+ "\"", NULL);
return TCL_ERROR;
}
*filePtr = (ClientData) f;
@@ -3152,28 +2987,29 @@ Tcl_GetOpenFile(interp, string, forWriting, checkUsage, filePtr)
}
}
- Tcl_AppendResult(interp, "\"", string,
- "\" cannot be used to get a FILE *", (char *) NULL);
- return TCL_ERROR;
+ Tcl_AppendResult(interp, "\"", chanID,
+ "\" cannot be used to get a FILE *", NULL);
+ return TCL_ERROR;
}
+#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is
+ * in tclMacOSXNotify.c */
/*
*----------------------------------------------------------------------
*
* TclUnixWaitForFile --
*
- * This procedure waits synchronously for a file to become readable
- * or writable, with an optional timeout.
+ * This function waits synchronously for a file to become readable or
+ * writable, with an optional timeout.
*
* Results:
* The return value is an OR'ed combination of TCL_READABLE,
- * TCL_WRITABLE, and TCL_EXCEPTION, indicating the conditions
- * that are present on file at the time of the return. This
- * procedure will not return until either "timeout" milliseconds
- * have elapsed or at least one of the conditions given by mask
- * has occurred for file (a return value of 0 means that a timeout
- * occurred). No normal events will be serviced during the
- * execution of this procedure.
+ * TCL_WRITABLE, and TCL_EXCEPTION, indicating the conditions that are
+ * present on file at the time of the return. This function will not
+ * return until either "timeout" milliseconds have elapsed or at least
+ * one of the conditions given by mask has occurred for file (a return
+ * value of 0 means that a timeout occurred). No normal events will be
+ * serviced during the execution of this function.
*
* Side effects:
* Time passes.
@@ -3182,29 +3018,38 @@ Tcl_GetOpenFile(interp, string, forWriting, checkUsage, filePtr)
*/
int
-TclUnixWaitForFile(fd, mask, timeout)
- int fd; /* Handle for file on which to wait. */
- int mask; /* What to wait for: OR'ed combination of
+TclUnixWaitForFile(
+ int fd, /* Handle for file on which to wait. */
+ int mask, /* What to wait for: OR'ed combination of
* TCL_READABLE, TCL_WRITABLE, and
* TCL_EXCEPTION. */
- int timeout; /* Maximum amount of time to wait for one
- * of the conditions in mask to occur, in
- * milliseconds. A value of 0 means don't
- * wait at all, and a value of -1 means
- * wait forever. */
+ int timeout) /* Maximum amount of time to wait for one of
+ * the conditions in mask to occur, in
+ * milliseconds. A value of 0 means don't wait
+ * at all, and a value of -1 means wait
+ * forever. */
{
Tcl_Time abortTime = {0, 0}, now; /* silence gcc 4 warning */
struct timeval blockTime, *timeoutPtr;
- int index, numFound, result = 0;
- fd_mask bit;
- fd_mask readyMasks[3*MASK_SIZE];
- /* This array reflects the readable/writable
- * conditions that were found to exist by the
- * last call to select. */
+ int numFound, result = 0;
+ fd_set readableMask;
+ fd_set writableMask;
+ fd_set exceptionalMask;
+
+#ifndef _DARWIN_C_SOURCE
+ /*
+ * Sanity check fd.
+ */
+
+ if (fd >= FD_SETSIZE) {
+ Tcl_Panic("TclUnixWaitForFile can't handle file id %d", fd);
+ /* must never get here, or select masks overrun will occur below */
+ }
+#endif
/*
- * If there is a non-zero finite timeout, compute the time when
- * we give up.
+ * If there is a non-zero finite timeout, compute the time when we give
+ * up.
*/
if (timeout > 0) {
@@ -3225,19 +3070,16 @@ TclUnixWaitForFile(fd, mask, timeout)
}
/*
- * Initialize the ready masks and compute the mask offsets.
+ * Initialize the select masks.
*/
- if (fd >= FD_SETSIZE) {
- panic("TclWaitForFile can't handle file id %d", fd);
- }
- memset((VOID *) readyMasks, 0, 3*MASK_SIZE*sizeof(fd_mask));
- index = fd/(NBBY*sizeof(fd_mask));
- bit = ((fd_mask) 1) << (fd%(NBBY*sizeof(fd_mask)));
+ FD_ZERO(&readableMask);
+ FD_ZERO(&writableMask);
+ FD_ZERO(&exceptionalMask);
/*
- * Loop in a mini-event loop of our own, waiting for either the
- * file to become ready or a timeout to occur.
+ * Loop in a mini-event loop of our own, waiting for either the file to
+ * become ready or a timeout to occur.
*/
while (1) {
@@ -3255,35 +3097,34 @@ TclUnixWaitForFile(fd, mask, timeout)
}
/*
- * Set the appropriate bit in the ready masks for the fd.
+ * Setup the select masks for the fd.
*/
- if (mask & TCL_READABLE) {
- readyMasks[index] |= bit;
+ if (mask & TCL_READABLE) {
+ FD_SET(fd, &readableMask);
}
- if (mask & TCL_WRITABLE) {
- (readyMasks+MASK_SIZE)[index] |= bit;
+ if (mask & TCL_WRITABLE) {
+ FD_SET(fd, &writableMask);
}
if (mask & TCL_EXCEPTION) {
- (readyMasks+2*(MASK_SIZE))[index] |= bit;
+ FD_SET(fd, &exceptionalMask);
}
/*
* Wait for the event or a timeout.
*/
- numFound = select(fd+1, (SELECT_MASK *) &readyMasks[0],
- (SELECT_MASK *) &readyMasks[MASK_SIZE],
- (SELECT_MASK *) &readyMasks[2*MASK_SIZE], timeoutPtr);
+ numFound = select(fd + 1, &readableMask, &writableMask,
+ &exceptionalMask, timeoutPtr);
if (numFound == 1) {
- if (readyMasks[index] & bit) {
- result |= TCL_READABLE;
+ if (FD_ISSET(fd, &readableMask)) {
+ SET_BITS(result, TCL_READABLE);
}
- if ((readyMasks+MASK_SIZE)[index] & bit) {
- result |= TCL_WRITABLE;
+ if (FD_ISSET(fd, &writableMask)) {
+ SET_BITS(result, TCL_WRITABLE);
}
- if ((readyMasks+2*(MASK_SIZE))[index] & bit) {
- result |= TCL_EXCEPTION;
+ if (FD_ISSET(fd, &exceptionalMask)) {
+ SET_BITS(result, TCL_EXCEPTION);
}
result &= mask;
if (result) {
@@ -3303,67 +3144,55 @@ TclUnixWaitForFile(fd, mask, timeout)
Tcl_GetTime(&now);
if ((abortTime.sec < now.sec)
- || ((abortTime.sec == now.sec)
- && (abortTime.usec <= now.usec))) {
+ || (abortTime.sec==now.sec && abortTime.usec<=now.usec)) {
break;
}
}
return result;
}
+#endif /* HAVE_COREFOUNDATION */
-#ifdef DEPRECATED
/*
*----------------------------------------------------------------------
*
- * FileThreadActionProc --
+ * FileTruncateProc --
*
- * Insert or remove any thread local refs to this channel.
+ * Truncates a file to a given length.
*
* Results:
- * None.
+ * 0 if the operation succeeded, and -1 if it failed (in which case
+ * *errorCodePtr will be set to errno).
*
* Side effects:
- * Changes thread local list of valid channels.
+ * The underlying file is potentially truncated. This can have a wide
+ * variety of side effects, including moving file pointers that point at
+ * places later in the file than the truncate point.
*
*----------------------------------------------------------------------
*/
-static void
-FileThreadActionProc (instanceData, action)
- ClientData instanceData;
- int action;
+static int
+FileTruncateProc(
+ ClientData instanceData,
+ Tcl_WideInt length)
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
FileState *fsPtr = (FileState *) instanceData;
+ int result;
- if (action == TCL_CHANNEL_THREAD_INSERT) {
- fsPtr->nextPtr = tsdPtr->firstFilePtr;
- tsdPtr->firstFilePtr = fsPtr;
- } else {
- FileState **nextPtrPtr;
- int removed = 0;
-
- for (nextPtrPtr = &(tsdPtr->firstFilePtr); (*nextPtrPtr) != NULL;
- nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {
- if ((*nextPtrPtr) == fsPtr) {
- (*nextPtrPtr) = fsPtr->nextPtr;
- removed = 1;
- break;
- }
- }
-
- /*
- * This could happen if the channel was created in one
- * thread and then moved to another without updating
- * the thread local data in each thread.
- */
+#ifdef HAVE_TYPE_OFF64_T
+ /*
+ * We assume this goes with the type for now...
+ */
- if (!removed) {
- panic("file info ptr not on thread channel list");
- }
+ result = ftruncate64(fsPtr->fd, (off64_t) length);
+#else
+ result = ftruncate(fsPtr->fd, (off_t) length);
+#endif
+ if (result) {
+ return errno;
}
+ return 0;
}
-#endif /* DEPRECATED */
/*
* Local Variables:
@@ -3374,4 +3203,3 @@ FileThreadActionProc (instanceData, action)
* indent-tabs-mode: nil
* End:
*/
-
diff --git a/unix/tclUnixCompat.c b/unix/tclUnixCompat.c
index 42fb916..4d959d6 100644
--- a/unix/tclUnixCompat.c
+++ b/unix/tclUnixCompat.c
@@ -3,25 +3,68 @@
*
* Written by: Zoran Vasiljevic (vasiljevic@users.sourceforge.net).
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
#include <pwd.h>
#include <grp.h>
#include <errno.h>
#include <string.h>
+/* See also: SC_BLOCKING_STYLE in unix/tcl.m4
+ */
+#ifdef USE_FIONBIO
+# ifdef HAVE_SYS_FILIO_H
+# include <sys/filio.h> /* For FIONBIO. */
+# endif
+# ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+# endif
+#endif /* USE_FIONBIO */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclUnixSetBlockingMode --
+ *
+ * Set the blocking mode of a file descriptor.
+ *
+ * Results:
+ *
+ * 0 on success, -1 (with errno set) on error.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+TclUnixSetBlockingMode(
+ int fd, /* File descriptor */
+ int mode) /* TCL_MODE_BLOCKING or TCL_MODE_NONBLOCKING */
+{
+#ifndef USE_FIONBIO
+ int flags = fcntl(fd, F_GETFL);
+
+ if (mode == TCL_MODE_BLOCKING) {
+ flags &= ~O_NONBLOCK;
+ } else {
+ flags |= O_NONBLOCK;
+ }
+ return fcntl(fd, F_SETFL, flags);
+#else /* USE_FIONBIO */
+ int state = (mode == TCL_MODE_NONBLOCKING);
+ return ioctl(fd, FIONBIO, &state);
+#endif /* !USE_FIONBIO */
+}
+
/*
* Used to pad structures at size'd boundaries
*
- * This macro assumes that the pointer 'buffer' was created from an
- * aligned pointer by adding the 'length'. If this 'length' was not a
- * multiple of the 'size' the result is unaligned and PadBuffer
- * corrects both the pointer, _and_ the 'length'. The latter means
- * that future increments of 'buffer' by 'length' stay aligned.
+ * This macro assumes that the pointer 'buffer' was created from an aligned
+ * pointer by adding the 'length'. If this 'length' was not a multiple of the
+ * 'size' the result is unaligned and PadBuffer corrects both the pointer,
+ * _and_ the 'length'. The latter means that future increments of 'buffer' by
+ * 'length' stay aligned.
*/
#define PadBuffer(buffer, length, size) \
@@ -31,14 +74,13 @@
}
/*
- * Per-thread private storage used to store values
- * returned from MT-unsafe library calls.
+ * Per-thread private storage used to store values returned from MT-unsafe
+ * library calls.
*/
#ifdef TCL_THREADS
typedef struct ThreadSpecificData {
-
struct passwd pwd;
char pbuf[2048];
@@ -49,306 +91,51 @@ typedef struct ThreadSpecificData {
struct hostent hent;
char hbuf[2048];
#endif
-
} ThreadSpecificData;
-
static Tcl_ThreadDataKey dataKey;
#if ((!defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETHOSTBYADDR_R)) && \
- (!defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR))) || \
+ (!defined(HAVE_MTSAFE_GETHOSTBYNAME) || \
+ !defined(HAVE_MTSAFE_GETHOSTBYADDR))) || \
!defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R) || \
!defined(HAVE_GETGRNAM_R) || !defined(HAVE_GETGRGID_R)
-
/*
- * Mutex to lock access to MT-unsafe calls. This is just to protect
- * our own usage. It does not protect us from others calling the
- * same functions without (or using some different) lock.
+ * Mutex to lock access to MT-unsafe calls. This is just to protect our own
+ * usage. It does not protect us from others calling the same functions
+ * without (or using some different) lock.
*/
static Tcl_Mutex compatLock;
-
-/*
- *---------------------------------------------------------------------------
- *
- * CopyArray --
- *
- * Copies array of NULL-terminated or fixed-length strings
- * to the private buffer, honouring the size of the buffer.
- *
- * Results:
- * Number of bytes copied on success or -1 on error (errno = ERANGE)
- *
- * Side effects:
- * None.
- *
- *---------------------------------------------------------------------------
- */
-
-static int
-CopyArray(char **src, int elsize, char *buf, int buflen)
-{
- int i, j, len = 0;
- char *p, **new;
-
- if (src == NULL) {
- return 0;
- }
- for (i = 0; src[i] != NULL; i++) {
- /* Empty loop to count howmany */
- }
- if ((sizeof(char *)*(i + 1)) > buflen) {
- return -1;
- }
- len = (sizeof(char *)*(i + 1)); /* Leave place for the array */
- new = (char **)buf;
- p = buf + (sizeof(char *)*(i + 1));
- for (j = 0; j < i; j++) {
- if (elsize < 0) {
- len += strlen(src[j]) + 1;
- } else {
- len += elsize;
- }
- if (len > buflen) {
- return -1;
- }
- if (elsize < 0) {
- strcpy(p, src[j]);
- } else {
- memcpy(p, src[j], elsize);
- }
- new[j] = p;
- p = buf + len;
- }
- new[j] = NULL;
-
- return len;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
- * CopyString --
- *
- * Copies a NULL-terminated string to the private buffer,
- * honouring the size of the buffer
- *
- * Results:
- * 0 success or -1 on error (errno = ERANGE)
- *
- * Side effects:
- * None
- *
- *---------------------------------------------------------------------------
- */
-
-
-static int
-CopyString(char *src, char *buf, int buflen)
-{
- int len = 0;
-
- if (src != NULL) {
- len += strlen(src) + 1;
- if (len > buflen) {
- return -1;
- }
- strcpy(buf, src);
- }
-
- return len;
-}
-#endif /* ((!defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETHOSTBYADDR_R)) && \
- (!defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR))) || \
- !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R) || \
- !defined(HAVE_GETGRNAM_R) || !defined(HAVE_GETGRGID_R) */
-
-#if (!defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETHOSTBYADDR_R)) && \
- (!defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR))
-
/*
- *---------------------------------------------------------------------------
- *
- * CopyHostnent --
- *
- * Copies string fields of the hostnent structure to the
- * private buffer, honouring the size of the buffer.
- *
- * Results:
- * Number of bytes copied on success or -1 on error (errno = ERANGE)
- *
- * Side effects:
- * None
- *
- *---------------------------------------------------------------------------
+ * Helper function declarations. Note that these are only used if needed and
+ * only defined if used (via the NEED_* macros).
*/
-static int
-CopyHostent(struct hostent *tgtPtr, char *buf, int buflen)
-{
- char *p = buf;
- int copied, len = 0;
+#undef NEED_COPYARRAY
+#undef NEED_COPYGRP
+#undef NEED_COPYHOSTENT
+#undef NEED_COPYPWD
+#undef NEED_COPYSTRING
- copied = CopyString(tgtPtr->h_name, p, buflen - len);
- if (copied == -1) {
- range:
- errno = ERANGE;
- return -1;
- }
- tgtPtr->h_name = (copied > 0) ? p : NULL;
- len += copied;
- p = buf + len;
-
- PadBuffer(p, len, sizeof(char *));
- copied = CopyArray(tgtPtr->h_aliases, -1, p, buflen - len);
- if (copied == -1) {
- goto range;
- }
- tgtPtr->h_aliases = (copied > 0) ? (char **)p : NULL;
- len += copied;
- p += len;
-
- PadBuffer(p, len, sizeof(char *));
- copied = CopyArray(tgtPtr->h_addr_list, tgtPtr->h_length, p, buflen - len);
- if (copied == -1) {
- goto range;
- }
- tgtPtr->h_addr_list = (copied > 0) ? (char **)p : NULL;
-
- return 0;
-}
-#endif /* (!defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETHOSTBYADDR_R)) && \
- (!defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR)) */
-
-#if !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R)
-
-/*
- *---------------------------------------------------------------------------
- *
- * CopyPwd --
- *
- * Copies string fields of the passwd structure to the
- * private buffer, honouring the size of the buffer.
- *
- * Results:
- * 0 on success or -1 on error (errno = ERANGE)
- *
- * Side effects:
- * We are not copying the gecos field as it may not be supported
- * on all platforms.
- *
- *---------------------------------------------------------------------------
- */
-
-static int
-CopyPwd(struct passwd *tgtPtr, char *buf, int buflen)
-{
- char *p = buf;
- int copied, len = 0;
-
- copied = CopyString(tgtPtr->pw_name, p, buflen - len);
- if (copied == -1) {
- range:
- errno = ERANGE;
- return -1;
- }
- tgtPtr->pw_name = (copied > 0) ? p : NULL;
- len += copied;
- p = buf + len;
-
- copied = CopyString(tgtPtr->pw_passwd, p, buflen - len);
- if (copied == -1) {
- goto range;
- }
- tgtPtr->pw_passwd = (copied > 0) ? p : NULL;
- len += copied;
- p = buf + len;
-
- copied = CopyString(tgtPtr->pw_dir, p, buflen - len);
- if (copied == -1) {
- goto range;
- }
- tgtPtr->pw_dir = (copied > 0) ? p : NULL;
- len += copied;
- p = buf + len;
-
- copied = CopyString(tgtPtr->pw_shell, p, buflen - len);
- if (copied == -1) {
- goto range;
- }
- tgtPtr->pw_shell = (copied > 0) ? p : NULL;
-
- return 0;
-}
-#endif /* !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R) */
-
-#if !defined(HAVE_GETGRNAM_R) || !defined(HAVE_GETGRGID_R)
-
-/*
- *---------------------------------------------------------------------------
- *
- * CopyGrp --
- *
- * Copies string fields of the group structure to the
- * private buffer, honouring the size of the buffer.
- *
- * Results:
- * 0 on success or -1 on error (errno = ERANGE)
- *
- * Side effects:
- * None.
- *
- *---------------------------------------------------------------------------
- */
-
-static int
-CopyGrp(struct group *tgtPtr, char *buf, int buflen)
-{
- register char *p = buf;
- register int copied, len = 0;
-
- /* Copy username */
- copied = CopyString(tgtPtr->gr_name, p, buflen - len);
- if (copied == -1) {
- range:
- errno = ERANGE;
- return -1;
- }
- tgtPtr->gr_name = (copied > 0) ? p : NULL;
- len += copied;
- p = buf + len;
-
- /* Copy password */
- copied = CopyString(tgtPtr->gr_passwd, p, buflen - len);
- if (copied == -1) {
- goto range;
- }
- tgtPtr->gr_passwd = (copied > 0) ? p : NULL;
- len += copied;
- p = buf + len;
-
- /* Copy group members */
- PadBuffer(p, len, sizeof(char *));
- copied = CopyArray((char **)tgtPtr->gr_mem, -1, p, buflen - len);
- if (copied == -1) {
- goto range;
- }
- tgtPtr->gr_mem = (copied > 0) ? (char **)p : NULL;
-
- return 0;
-}
-#endif /* !defined(HAVE_GETGRNAM_R) || !defined(HAVE_GETGRGID_R) */
+static int CopyArray(char **src, int elsize, char *buf,
+ int buflen);
+static int CopyGrp(struct group *tgtPtr, char *buf, int buflen);
+static int CopyHostent(struct hostent *tgtPtr, char *buf,
+ int buflen);
+static int CopyPwd(struct passwd *tgtPtr, char *buf, int buflen);
+static int CopyString(CONST char *src, char *buf, int buflen);
+#endif
#endif /* TCL_THREADS */
-
/*
*---------------------------------------------------------------------------
*
* TclpGetPwNam --
*
- * Thread-safe wrappers for getpwnam().
- * See "man getpwnam" for more details.
+ * Thread-safe wrappers for getpwnam(). See "man getpwnam" for more
+ * details.
*
* Results:
* Pointer to struct passwd on success or NULL on error.
@@ -360,7 +147,8 @@ CopyGrp(struct group *tgtPtr, char *buf, int buflen)
*/
struct passwd *
-TclpGetPwNam(const char *name)
+TclpGetPwNam(
+ const char *name)
{
#if !defined(TCL_THREADS)
return getpwnam(name);
@@ -369,6 +157,7 @@ TclpGetPwNam(const char *name)
#if defined(HAVE_GETPWNAM_R_5)
struct passwd *pwPtr = NULL;
+
return (getpwnam_r(name, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf),
&pwPtr) == 0 && pwPtr != NULL) ? &tsdPtr->pwd : NULL;
@@ -376,7 +165,9 @@ TclpGetPwNam(const char *name)
return getpwnam_r(name, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf));
#else
+#define NEED_COPYPWD 1
struct passwd *pwPtr;
+
Tcl_MutexLock(&compatLock);
pwPtr = getpwnam(name);
if (pwPtr != NULL) {
@@ -389,18 +180,18 @@ TclpGetPwNam(const char *name)
Tcl_MutexUnlock(&compatLock);
return pwPtr;
#endif
- return NULL; /* Not reached */
+
+ return NULL; /* Not reached. */
#endif /* TCL_THREADS */
}
-
/*
*---------------------------------------------------------------------------
*
* TclpGetPwUid --
*
- * Thread-safe wrappers for getpwuid().
- * See "man getpwuid" for more details.
+ * Thread-safe wrappers for getpwuid(). See "man getpwuid" for more
+ * details.
*
* Results:
* Pointer to struct passwd on success or NULL on error.
@@ -412,7 +203,8 @@ TclpGetPwNam(const char *name)
*/
struct passwd *
-TclpGetPwUid(uid_t uid)
+TclpGetPwUid(
+ uid_t uid)
{
#if !defined(TCL_THREADS)
return getpwuid(uid);
@@ -421,6 +213,7 @@ TclpGetPwUid(uid_t uid)
#if defined(HAVE_GETPWUID_R_5)
struct passwd *pwPtr = NULL;
+
return (getpwuid_r(uid, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf),
&pwPtr) == 0 && pwPtr != NULL) ? &tsdPtr->pwd : NULL;
@@ -428,7 +221,9 @@ TclpGetPwUid(uid_t uid)
return getpwuid_r(uid, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf));
#else
+#define NEED_COPYPWD 1
struct passwd *pwPtr;
+
Tcl_MutexLock(&compatLock);
pwPtr = getpwuid(uid);
if (pwPtr != NULL) {
@@ -441,18 +236,18 @@ TclpGetPwUid(uid_t uid)
Tcl_MutexUnlock(&compatLock);
return pwPtr;
#endif
- return NULL; /* Not reached */
+
+ return NULL; /* Not reached. */
#endif /* TCL_THREADS */
}
-
/*
*---------------------------------------------------------------------------
*
* TclpGetGrNam --
*
- * Thread-safe wrappers for getgrnam().
- * See "man getgrnam" for more details.
+ * Thread-safe wrappers for getgrnam(). See "man getgrnam" for more
+ * details.
*
* Results:
* Pointer to struct group on success or NULL on error.
@@ -464,7 +259,8 @@ TclpGetPwUid(uid_t uid)
*/
struct group *
-TclpGetGrNam(const char *name)
+TclpGetGrNam(
+ const char *name)
{
#if !defined(TCL_THREADS)
return getgrnam(name);
@@ -473,6 +269,7 @@ TclpGetGrNam(const char *name)
#if defined(HAVE_GETGRNAM_R_5)
struct group *grPtr = NULL;
+
return (getgrnam_r(name, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf),
&grPtr) == 0 && grPtr != NULL) ? &tsdPtr->grp : NULL;
@@ -480,7 +277,9 @@ TclpGetGrNam(const char *name)
return getgrnam_r(name, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf));
#else
+#define NEED_COPYGRP 1
struct group *grPtr;
+
Tcl_MutexLock(&compatLock);
grPtr = getgrnam(name);
if (grPtr != NULL) {
@@ -493,18 +292,18 @@ TclpGetGrNam(const char *name)
Tcl_MutexUnlock(&compatLock);
return grPtr;
#endif
- return NULL; /* Not reached */
+
+ return NULL; /* Not reached. */
#endif /* TCL_THREADS */
}
-
/*
*---------------------------------------------------------------------------
*
* TclpGetGrGid --
*
- * Thread-safe wrappers for getgrgid().
- * See "man getgrgid" for more details.
+ * Thread-safe wrappers for getgrgid(). See "man getgrgid" for more
+ * details.
*
* Results:
* Pointer to struct group on success or NULL on error.
@@ -516,7 +315,8 @@ TclpGetGrNam(const char *name)
*/
struct group *
-TclpGetGrGid(gid_t gid)
+TclpGetGrGid(
+ gid_t gid)
{
#if !defined(TCL_THREADS)
return getgrgid(gid);
@@ -525,6 +325,7 @@ TclpGetGrGid(gid_t gid)
#if defined(HAVE_GETGRGID_R_5)
struct group *grPtr = NULL;
+
return (getgrgid_r(gid, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf),
&grPtr) == 0 && grPtr != NULL) ? &tsdPtr->grp : NULL;
@@ -532,7 +333,9 @@ TclpGetGrGid(gid_t gid)
return getgrgid_r(gid, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf));
#else
+#define NEED_COPYGRP 1
struct group *grPtr;
+
Tcl_MutexLock(&compatLock);
grPtr = getgrgid(gid);
if (grPtr != NULL) {
@@ -545,18 +348,18 @@ TclpGetGrGid(gid_t gid)
Tcl_MutexUnlock(&compatLock);
return grPtr;
#endif
- return NULL; /* Not reached */
+
+ return NULL; /* Not reached. */
#endif /* TCL_THREADS */
}
-
/*
*---------------------------------------------------------------------------
*
* TclpGetHostByName --
*
- * Thread-safe wrappers for gethostbyname().
- * See "man gethostbyname" for more details.
+ * Thread-safe wrappers for gethostbyname(). See "man gethostbyname" for
+ * more details.
*
* Results:
* Pointer to struct hostent on success or NULL on error.
@@ -568,7 +371,8 @@ TclpGetGrGid(gid_t gid)
*/
struct hostent *
-TclpGetHostByName(const char *name)
+TclpGetHostByName(
+ const char *name)
{
#if !defined(TCL_THREADS) || defined(HAVE_MTSAFE_GETHOSTBYNAME)
return gethostbyname(name);
@@ -577,48 +381,53 @@ TclpGetHostByName(const char *name)
#if defined(HAVE_GETHOSTBYNAME_R_5)
int h_errno;
+
return gethostbyname_r(name, &tsdPtr->hent, tsdPtr->hbuf,
sizeof(tsdPtr->hbuf), &h_errno);
#elif defined(HAVE_GETHOSTBYNAME_R_6)
- struct hostent *hePtr;
- int result, h_errno;
+ struct hostent *hePtr = NULL;
+ int h_errno, result;
result = gethostbyname_r(name, &tsdPtr->hent, tsdPtr->hbuf,
- sizeof(tsdPtr->hbuf), &hePtr, &h_errno);
+ sizeof(tsdPtr->hbuf), &hePtr, &h_errno);
return (result == 0) ? hePtr : NULL;
#elif defined(HAVE_GETHOSTBYNAME_R_3)
struct hostent_data data;
- return (gethostbyname_r(name, &tsdPtr->hent, &data) == 0) ?
- &tsdPtr->hent : NULL;
+
+ return (gethostbyname_r(name, &tsdPtr->hent, &data) == 0)
+ ? &tsdPtr->hent : NULL;
+
#else
+#define NEED_COPYHOSTENT 1
struct hostent *hePtr;
+
Tcl_MutexLock(&compatLock);
hePtr = gethostbyname(name);
if (hePtr != NULL) {
tsdPtr->hent = *hePtr;
hePtr = &tsdPtr->hent;
if (CopyHostent(&tsdPtr->hent, tsdPtr->hbuf,
- sizeof(tsdPtr->hbuf)) == -1) {
+ sizeof(tsdPtr->hbuf)) == -1) {
hePtr = NULL;
}
}
Tcl_MutexUnlock(&compatLock);
return hePtr;
#endif
- return NULL; /* Not reached */
+
+ return NULL; /* Not reached. */
#endif /* TCL_THREADS */
}
-
/*
*---------------------------------------------------------------------------
*
* TclpGetHostByAddr --
*
- * Thread-safe wrappers for gethostbyaddr().
- * See "man gethostbyaddr" for more details.
+ * Thread-safe wrappers for gethostbyaddr(). See "man gethostbyaddr" for
+ * more details.
*
* Results:
* Pointer to struct hostent on success or NULL on error.
@@ -630,7 +439,10 @@ TclpGetHostByName(const char *name)
*/
struct hostent *
-TclpGetHostByAddr(const char *addr, int length, int type)
+TclpGetHostByAddr(
+ const char *addr,
+ int length,
+ int type)
{
#if !defined(TCL_THREADS) || defined(HAVE_MTSAFE_GETHOSTBYADDR)
return gethostbyaddr(addr, length, type);
@@ -639,30 +451,346 @@ TclpGetHostByAddr(const char *addr, int length, int type)
#if defined(HAVE_GETHOSTBYADDR_R_7)
int h_errno;
+
return gethostbyaddr_r(addr, length, type, &tsdPtr->hent, tsdPtr->hbuf,
- sizeof(tsdPtr->hbuf), &h_errno);
+ sizeof(tsdPtr->hbuf), &h_errno);
#elif defined(HAVE_GETHOSTBYADDR_R_8)
struct hostent *hePtr;
int h_errno;
+
return (gethostbyaddr_r(addr, length, type, &tsdPtr->hent, tsdPtr->hbuf,
- sizeof(tsdPtr->hbuf), &hePtr, &h_errno) == 0) ?
- &tsdPtr->hent : NULL;
+ sizeof(tsdPtr->hbuf), &hePtr, &h_errno) == 0)
+ ? &tsdPtr->hent : NULL;
#else
+#define NEED_COPYHOSTENT 1
struct hostent *hePtr;
+
Tcl_MutexLock(&compatLock);
hePtr = gethostbyaddr(addr, length, type);
if (hePtr != NULL) {
tsdPtr->hent = *hePtr;
hePtr = &tsdPtr->hent;
if (CopyHostent(&tsdPtr->hent, tsdPtr->hbuf,
- sizeof(tsdPtr->hbuf)) == -1) {
+ sizeof(tsdPtr->hbuf)) == -1) {
hePtr = NULL;
}
}
Tcl_MutexUnlock(&compatLock);
return hePtr;
#endif
- return NULL; /* Not reached */
+
+ return NULL; /* Not reached. */
#endif /* TCL_THREADS */
}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CopyGrp --
+ *
+ * Copies string fields of the group structure to the private buffer,
+ * honouring the size of the buffer.
+ *
+ * Results:
+ * 0 on success or -1 on error (errno = ERANGE).
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef NEED_COPYGRP
+#define NEED_COPYARRAY 1
+#define NEED_COPYSTRING 1
+
+static int
+CopyGrp(
+ struct group *tgtPtr,
+ char *buf,
+ int buflen)
+{
+ register char *p = buf;
+ register int copied, len = 0;
+
+ /*
+ * Copy username.
+ */
+
+ copied = CopyString(tgtPtr->gr_name, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->gr_name = (copied > 0) ? p : NULL;
+ len += copied;
+ p = buf + len;
+
+ /*
+ * Copy password.
+ */
+
+ copied = CopyString(tgtPtr->gr_passwd, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->gr_passwd = (copied > 0) ? p : NULL;
+ len += copied;
+ p = buf + len;
+
+ /*
+ * Copy group members.
+ */
+
+ PadBuffer(p, len, sizeof(char *));
+ copied = CopyArray((char **)tgtPtr->gr_mem, -1, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->gr_mem = (copied > 0) ? (char **)p : NULL;
+
+ return 0;
+
+ range:
+ errno = ERANGE;
+ return -1;
+}
+#endif /* NEED_COPYGRP */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CopyHostent --
+ *
+ * Copies string fields of the hostnent structure to the private buffer,
+ * honouring the size of the buffer.
+ *
+ * Results:
+ * Number of bytes copied on success or -1 on error (errno = ERANGE)
+ *
+ * Side effects:
+ * None
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef NEED_COPYHOSTENT
+#define NEED_COPYSTRING 1
+#define NEED_COPYARRAY 1
+
+static int
+CopyHostent(
+ struct hostent *tgtPtr,
+ char *buf,
+ int buflen)
+{
+ char *p = buf;
+ int copied, len = 0;
+
+ copied = CopyString(tgtPtr->h_name, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->h_name = (copied > 0) ? p : NULL;
+ len += copied;
+ p = buf + len;
+
+ PadBuffer(p, len, sizeof(char *));
+ copied = CopyArray(tgtPtr->h_aliases, -1, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->h_aliases = (copied > 0) ? (char **)p : NULL;
+ len += copied;
+ p += len;
+
+ PadBuffer(p, len, sizeof(char *));
+ copied = CopyArray(tgtPtr->h_addr_list, tgtPtr->h_length, p, buflen-len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->h_addr_list = (copied > 0) ? (char **)p : NULL;
+
+ return 0;
+
+ range:
+ errno = ERANGE;
+ return -1;
+}
+#endif /* NEED_COPYHOSTENT */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CopyPwd --
+ *
+ * Copies string fields of the passwd structure to the private buffer,
+ * honouring the size of the buffer.
+ *
+ * Results:
+ * 0 on success or -1 on error (errno = ERANGE).
+ *
+ * Side effects:
+ * We are not copying the gecos field as it may not be supported on all
+ * platforms.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef NEED_COPYPWD
+#define NEED_COPYSTRING 1
+
+static int
+CopyPwd(
+ struct passwd *tgtPtr,
+ char *buf,
+ int buflen)
+{
+ char *p = buf;
+ int copied, len = 0;
+
+ copied = CopyString(tgtPtr->pw_name, p, buflen - len);
+ if (copied == -1) {
+ range:
+ errno = ERANGE;
+ return -1;
+ }
+ tgtPtr->pw_name = (copied > 0) ? p : NULL;
+ len += copied;
+ p = buf + len;
+
+ copied = CopyString(tgtPtr->pw_passwd, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->pw_passwd = (copied > 0) ? p : NULL;
+ len += copied;
+ p = buf + len;
+
+ copied = CopyString(tgtPtr->pw_dir, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->pw_dir = (copied > 0) ? p : NULL;
+ len += copied;
+ p = buf + len;
+
+ copied = CopyString(tgtPtr->pw_shell, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->pw_shell = (copied > 0) ? p : NULL;
+
+ return 0;
+}
+#endif /* NEED_COPYPWD */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CopyArray --
+ *
+ * Copies array of NULL-terminated or fixed-length strings to the private
+ * buffer, honouring the size of the buffer.
+ *
+ * Results:
+ * Number of bytes copied on success or -1 on error (errno = ERANGE)
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef NEED_COPYARRAY
+static int
+CopyArray(
+ char **src, /* Array of elements to copy. */
+ int elsize, /* Size of each element, or -1 to indicate
+ * that they are C strings of dynamic
+ * length. */
+ char *buf, /* Buffer to copy into. */
+ int buflen) /* Size of buffer. */
+{
+ int i, j, len = 0;
+ char *p, **new;
+
+ if (src == NULL) {
+ return 0;
+ }
+
+ for (i = 0; src[i] != NULL; i++) {
+ /*
+ * Empty loop to count how many.
+ */
+ }
+ len = sizeof(char *) * (i + 1); /* Leave place for the array. */
+ if (len > buflen) {
+ return -1;
+ }
+
+ new = (char **) buf;
+ p = buf + len;
+
+ for (j = 0; j < i; j++) {
+ int sz = (elsize<0 ? (int) strlen(src[j]) + 1 : elsize);
+
+ len += sz;
+ if (len > buflen) {
+ return -1;
+ }
+ memcpy(p, src[j], sz);
+ new[j] = p;
+ p = buf + len;
+ }
+ new[j] = NULL;
+
+ return len;
+}
+#endif /* NEED_COPYARRAY */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CopyString --
+ *
+ * Copies a NULL-terminated string to the private buffer, honouring the
+ * size of the buffer
+ *
+ * Results:
+ * 0 success or -1 on error (errno = ERANGE)
+ *
+ * Side effects:
+ * None
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef NEED_COPYSTRING
+static int
+CopyString(
+ CONST char *src, /* String to copy. */
+ char *buf, /* Buffer to copy into. */
+ int buflen) /* Size of buffer. */
+{
+ int len = 0;
+
+ if (src != NULL) {
+ len = strlen(src) + 1;
+ if (len > buflen) {
+ return -1;
+ }
+ memcpy(buf, src, len);
+ }
+
+ return len;
+}
+#endif /* NEED_COPYSTRING */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixEvent.c b/unix/tclUnixEvent.c
index f43954f..e4d922d 100644
--- a/unix/tclUnixEvent.c
+++ b/unix/tclUnixEvent.c
@@ -1,16 +1,17 @@
-/*
+/*
* tclUnixEvent.c --
*
* This file implements Unix specific event related routines.
*
* Copyright (c) 1997 by Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
+#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is
+ * in tclMacOSXNotify.c */
/*
*----------------------------------------------------------------------
@@ -29,17 +30,16 @@
*/
void
-Tcl_Sleep(ms)
- int ms; /* Number of milliseconds to sleep. */
+Tcl_Sleep(
+ int ms) /* Number of milliseconds to sleep. */
{
struct timeval delay;
- Tcl_Time before, after;
+ Tcl_Time before, after, vdelay;
/*
- * The only trick here is that select appears to return early
- * under some conditions, so we have to check to make sure that
- * the right amount of time really has elapsed. If it's too
- * early, go back to sleep again.
+ * The only trick here is that select appears to return early under some
+ * conditions, so we have to check to make sure that the right amount of
+ * time really has elapsed. If it's too early, go back to sleep again.
*/
Tcl_GetTime(&before);
@@ -51,16 +51,28 @@ Tcl_Sleep(ms)
after.sec += 1;
}
while (1) {
- delay.tv_sec = after.sec - before.sec;
- delay.tv_usec = after.usec - before.usec;
- if (delay.tv_usec < 0) {
- delay.tv_usec += 1000000;
- delay.tv_sec -= 1;
+ /*
+ * TIP #233: Scale from virtual time to real-time for select.
+ */
+
+ vdelay.sec = after.sec - before.sec;
+ vdelay.usec = after.usec - before.usec;
+
+ if (vdelay.usec < 0) {
+ vdelay.usec += 1000000;
+ vdelay.sec -= 1;
}
+ if ((vdelay.sec != 0) || (vdelay.usec != 0)) {
+ (*tclScaleTimeProcPtr) (&vdelay, tclTimeClientData);
+ }
+
+ delay.tv_sec = vdelay.sec;
+ delay.tv_usec = vdelay.usec;
+
/*
- * Special note: must convert delay.tv_sec to int before comparing
- * to zero, since delay.tv_usec is unsigned on some platforms.
+ * Special note: must convert delay.tv_sec to int before comparing to
+ * zero, since delay.tv_usec is unsigned on some platforms.
*/
if ((((int) delay.tv_sec) < 0)
@@ -72,3 +84,12 @@ Tcl_Sleep(ms)
Tcl_GetTime(&before);
}
}
+
+#endif /* HAVE_COREFOUNDATION */
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c
index 1fbe384..a96a81a 100644
--- a/unix/tclUnixFCmd.c
+++ b/unix/tclUnixFCmd.c
@@ -1,55 +1,49 @@
/*
* tclUnixFCmd.c
*
- * This file implements the unix specific portion of file manipulation
- * subcommands of the "file" command. All filename arguments should
+ * This file implements the unix specific portion of file manipulation
+ * subcommands of the "file" command. All filename arguments should
* already be translated to native format.
*
* Copyright (c) 1996-1998 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * Portions of this code were derived from NetBSD source code which has
- * the following copyright notice:
+ * Portions of this code were derived from NetBSD source code which has the
+ * following copyright notice:
*
* Copyright (c) 1988, 1993, 1994
- * The Regents of the University of California. All rights reserved.
+ * The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
+ * 3. Neither the name of the University nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
* without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
*/
#include "tclInt.h"
-#include "tclPort.h"
#include <utime.h>
#include <grp.h>
-#ifndef HAVE_ST_BLKSIZE
+#ifndef HAVE_STRUCT_STAT_ST_BLKSIZE
#ifndef NO_FSTATFS
#include <sys/statfs.h>
#endif
@@ -63,76 +57,112 @@
* TraverseUnixTree() calls the traverseProc()
*/
-#define DOTREE_PRED 1 /* pre-order directory */
-#define DOTREE_POSTD 2 /* post-order directory */
-#define DOTREE_F 3 /* regular file */
+#define DOTREE_PRED 1 /* pre-order directory */
+#define DOTREE_POSTD 2 /* post-order directory */
+#define DOTREE_F 3 /* regular file */
/*
* Callbacks for file attributes code.
*/
-static int GetGroupAttribute _ANSI_ARGS_((Tcl_Interp *interp,
+static int GetGroupAttribute(Tcl_Interp *interp, int objIndex,
+ Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr);
+static int GetOwnerAttribute(Tcl_Interp *interp, int objIndex,
+ Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr);
+static int GetPermissionsAttribute(Tcl_Interp *interp,
int objIndex, Tcl_Obj *fileName,
- Tcl_Obj **attributePtrPtr));
-static int GetOwnerAttribute _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj **attributePtrPtr);
+static int SetGroupAttribute(Tcl_Interp *interp, int objIndex,
+ Tcl_Obj *fileName, Tcl_Obj *attributePtr);
+static int SetOwnerAttribute(Tcl_Interp *interp, int objIndex,
+ Tcl_Obj *fileName, Tcl_Obj *attributePtr);
+static int SetPermissionsAttribute(Tcl_Interp *interp,
int objIndex, Tcl_Obj *fileName,
- Tcl_Obj **attributePtrPtr));
-static int GetPermissionsAttribute _ANSI_ARGS_((
- Tcl_Interp *interp, int objIndex,
- Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr));
-static int SetGroupAttribute _ANSI_ARGS_((Tcl_Interp *interp,
- int objIndex, Tcl_Obj *fileName,
- Tcl_Obj *attributePtr));
-static int SetOwnerAttribute _ANSI_ARGS_((Tcl_Interp *interp,
- int objIndex, Tcl_Obj *fileName,
- Tcl_Obj *attributePtr));
-static int SetPermissionsAttribute _ANSI_ARGS_((
- Tcl_Interp *interp, int objIndex,
- Tcl_Obj *fileName, Tcl_Obj *attributePtr));
-static int GetModeFromPermString _ANSI_ARGS_((
- Tcl_Interp *interp, char *modeStringPtr,
- mode_t *modePtr));
+ Tcl_Obj *attributePtr);
+static int GetModeFromPermString(Tcl_Interp *interp,
+ char *modeStringPtr, mode_t *modePtr);
+#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
+static int GetReadOnlyAttribute(Tcl_Interp *interp, int objIndex,
+ Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr);
+static int SetReadOnlyAttribute(Tcl_Interp *interp, int objIndex,
+ Tcl_Obj *fileName, Tcl_Obj *attributePtr);
+#endif
/*
* Prototype for the TraverseUnixTree callback function.
*/
-typedef int (TraversalProc) _ANSI_ARGS_((Tcl_DString *srcPtr,
- Tcl_DString *dstPtr, CONST Tcl_StatBuf *statBufPtr, int type,
- Tcl_DString *errorPtr));
+typedef int (TraversalProc)(Tcl_DString *srcPtr, Tcl_DString *dstPtr,
+ CONST Tcl_StatBuf *statBufPtr, int type, Tcl_DString *errorPtr);
/*
* Constants and variables necessary for file attributes subcommand.
+ *
+ * IMPORTANT: The permissions attribute is assumed to be the third item (i.e.
+ * to be indexed with '2' in arrays) in code in tclIOUtil.c and possibly
+ * elsewhere in Tcl's core.
+ */
+
+#ifdef DJGPP
+
+/*
+ * See contrib/djgpp/tclDjgppFCmd.c for definition.
*/
+extern TclFileAttrProcs tclpFileAttrProcs[];
+extern char *tclpFileAttrStrings[];
+
+#else
enum {
- UNIX_GROUP_ATTRIBUTE,
- UNIX_OWNER_ATTRIBUTE,
- UNIX_PERMISSIONS_ATTRIBUTE
+ UNIX_GROUP_ATTRIBUTE, UNIX_OWNER_ATTRIBUTE, UNIX_PERMISSIONS_ATTRIBUTE,
+#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
+ UNIX_READONLY_ATTRIBUTE,
+#endif
+#ifdef MAC_OSX_TCL
+ MACOSX_CREATOR_ATTRIBUTE, MACOSX_TYPE_ATTRIBUTE, MACOSX_HIDDEN_ATTRIBUTE,
+ MACOSX_RSRCLENGTH_ATTRIBUTE,
+#endif
+ UNIX_INVALID_ATTRIBUTE /* lint - last enum value needs no trailing , */
};
+MODULE_SCOPE CONST char *tclpFileAttrStrings[];
CONST char *tclpFileAttrStrings[] = {
- "-group",
- "-owner",
- "-permissions",
- (char *) NULL
+ "-group", "-owner", "-permissions",
+#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
+ "-readonly",
+#endif
+#ifdef MAC_OSX_TCL
+ "-creator", "-type", "-hidden", "-rsrclength",
+#endif
+ NULL
};
+MODULE_SCOPE CONST TclFileAttrProcs tclpFileAttrProcs[];
CONST TclFileAttrProcs tclpFileAttrProcs[] = {
- {GetGroupAttribute, SetGroupAttribute},
- {GetOwnerAttribute, SetOwnerAttribute},
- {GetPermissionsAttribute, SetPermissionsAttribute}
+ {GetGroupAttribute, SetGroupAttribute},
+ {GetOwnerAttribute, SetOwnerAttribute},
+ {GetPermissionsAttribute, SetPermissionsAttribute},
+#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
+ {GetReadOnlyAttribute, SetReadOnlyAttribute},
+#endif
+#ifdef MAC_OSX_TCL
+ {TclMacOSXGetFileAttribute, TclMacOSXSetFileAttribute},
+ {TclMacOSXGetFileAttribute, TclMacOSXSetFileAttribute},
+ {TclMacOSXGetFileAttribute, TclMacOSXSetFileAttribute},
+ {TclMacOSXGetFileAttribute, TclMacOSXSetFileAttribute},
+#endif
};
+#endif
/*
* This is the maximum number of consecutive readdir/unlink calls that can be
* made (with no intervening rewinddir or closedir/opendir) before triggering
* a bug that makes readdir return NULL even though some directory entries
- * have not been processed. The bug afflicts SunOS's readdir when applied to
- * ufs file systems and Darwin 6.5's (and OSX v.10.3.8's) HFS+. JH found the
- * Darwin readdir to reset at 147, so 130 is chosen to be conservative. We
+ * have not been processed. The bug afflicts SunOS's readdir when applied to
+ * ufs file systems and Darwin 6.5's (and OSX v.10.3.8's) HFS+. JH found the
+ * Darwin readdir to reset at 147, so 130 is chosen to be conservative. We
* can't do a general rewind on failure as NFS can create special files that
- * recreate themselves when you try and delete them. 8.4.8 added a solution
+ * recreate themselves when you try and delete them. 8.4.8 added a solution
* that was affected by a single such NFS file, this solution should not be
* affected by less than THRESHOLD such files. [Bug 1034337]
*/
@@ -143,42 +173,38 @@ CONST TclFileAttrProcs tclpFileAttrProcs[] = {
* Declarations for local procedures defined in this file:
*/
-static int CopyFile _ANSI_ARGS_((CONST char *src,
- CONST char *dst, CONST Tcl_StatBuf *statBufPtr));
-static int CopyFileAtts _ANSI_ARGS_((CONST char *src,
- CONST char *dst, CONST Tcl_StatBuf *statBufPtr));
-static int DoCopyFile _ANSI_ARGS_((CONST char *srcPtr,
- CONST char *dstPtr, CONST Tcl_StatBuf *statBufPtr));
-static int DoCreateDirectory _ANSI_ARGS_((CONST char *pathPtr));
-static int DoRemoveDirectory _ANSI_ARGS_((Tcl_DString *pathPtr,
- int recursive, Tcl_DString *errorPtr));
-static int DoRenameFile _ANSI_ARGS_((CONST char *src,
- CONST char *dst));
-static int TraversalCopy _ANSI_ARGS_((Tcl_DString *srcPtr,
+static int CopyFileAtts(CONST char *src,
+ CONST char *dst, CONST Tcl_StatBuf *statBufPtr);
+static int DoCopyFile(CONST char *srcPtr, CONST char *dstPtr,
+ CONST Tcl_StatBuf *statBufPtr);
+static int DoCreateDirectory(CONST char *pathPtr);
+static int DoRemoveDirectory(Tcl_DString *pathPtr,
+ int recursive, Tcl_DString *errorPtr);
+static int DoRenameFile(CONST char *src, CONST char *dst);
+static int TraversalCopy(Tcl_DString *srcPtr,
Tcl_DString *dstPtr, CONST Tcl_StatBuf *statBufPtr,
- int type, Tcl_DString *errorPtr));
-static int TraversalDelete _ANSI_ARGS_((Tcl_DString *srcPtr,
+ int type, Tcl_DString *errorPtr);
+static int TraversalDelete(Tcl_DString *srcPtr,
Tcl_DString *dstPtr, CONST Tcl_StatBuf *statBufPtr,
- int type, Tcl_DString *errorPtr));
-static int TraverseUnixTree _ANSI_ARGS_((
- TraversalProc *traversalProc,
+ int type, Tcl_DString *errorPtr);
+static int TraverseUnixTree(TraversalProc *traversalProc,
Tcl_DString *sourcePtr, Tcl_DString *destPtr,
- Tcl_DString *errorPtr, int doRewind));
+ Tcl_DString *errorPtr, int doRewind);
#ifdef PURIFY
/*
- * realpath and purify don't mix happily. It has been noted that realpath
+ * realpath and purify don't mix happily. It has been noted that realpath
* should not be used with purify because of bogus warnings, but just
- * memset'ing the resolved path will squelch those. This assumes we are
+ * memset'ing the resolved path will squelch those. This assumes we are
* passing the standard MAXPATHLEN size resolved arg.
*/
-static char * Realpath _ANSI_ARGS_((CONST char *path,
- char *resolved));
+
+static char * Realpath(CONST char *path, char *resolved);
char *
-Realpath(path, resolved)
- CONST char *path;
- char *resolved;
+Realpath(
+ CONST char *path,
+ char *resolved)
{
memset(resolved, 0, MAXPATHLEN);
return realpath(path, resolved);
@@ -192,11 +218,12 @@ Realpath(path, resolved)
defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
MAC_OS_X_VERSION_MIN_REQUIRED < 1030
/*
- * prior to Darwin 7, realpath is not threadsafe, c.f. bug 711232;
- * if we might potentially be running on pre-10.3 OSX,
- * check Darwin release at runtime before using realpath.
+ * Prior to Darwin 7, realpath is not thread-safe, c.f. Bug 711232; if we
+ * might potentially be running on pre-10.3 OSX, check Darwin release at
+ * runtime before using realpath.
*/
-extern long tclMacOSXDarwinRelease;
+
+MODULE_SCOPE long tclMacOSXDarwinRelease;
#define haveRealpath (tclMacOSXDarwinRelease >= 7)
#else
#define haveRealpath 1
@@ -211,67 +238,66 @@ extern long tclMacOSXDarwinRelease;
defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
MAC_OS_X_VERSION_MIN_REQUIRED < 1050
/*
- * prior to Darwin 9, 64bit fts_open() without FTS_NOSTAT may crash (due to a
+ * Prior to Darwin 9, 64bit fts_open() without FTS_NOSTAT may crash (due to a
* 64bit-unsafe ALIGN macro); if we could be running on pre-10.5 OSX, check
* Darwin release at runtime and do a separate stat() if necessary.
*/
-extern long tclMacOSXDarwinRelease;
+
+MODULE_SCOPE long tclMacOSXDarwinRelease;
#define noFtsStat (tclMacOSXDarwinRelease < 9)
#else
#define noFtsStat 0
#endif
#endif /* HAVE_FTS */
-
/*
*---------------------------------------------------------------------------
*
* TclpObjRenameFile, DoRenameFile --
*
- * Changes the name of an existing file or directory, from src to dst.
- * If src and dst refer to the same file or directory, does nothing
- * and returns success. Otherwise if dst already exists, it will be
- * deleted and replaced by src subject to the following conditions:
+ * Changes the name of an existing file or directory, from src to dst. If
+ * src and dst refer to the same file or directory, does nothing and
+ * returns success. Otherwise if dst already exists, it will be deleted
+ * and replaced by src subject to the following conditions:
* If src is a directory, dst may be an empty directory.
* If src is a file, dst may be a file.
- * In any other situation where dst already exists, the rename will
- * fail.
+ * In any other situation where dst already exists, the rename will fail.
*
* Results:
- * If the directory was successfully created, returns TCL_OK.
- * Otherwise the return value is TCL_ERROR and errno is set to
- * indicate the error. Some possible values for errno are:
+ * If the directory was successfully created, returns TCL_OK. Otherwise
+ * the return value is TCL_ERROR and errno is set to indicate the error.
+ * Some possible values for errno are:
*
- * EACCES: src or dst parent directory can't be read and/or written.
+ * EACCES: src or dst parent directory can't be read and/or written.
* EEXIST: dst is a non-empty directory.
* EINVAL: src is a root directory or dst is a subdirectory of src.
* EISDIR: dst is a directory, but src is not.
* ENOENT: src doesn't exist, or src or dst is "".
- * ENOTDIR: src is a directory, but dst is not.
+ * ENOTDIR: src is a directory, but dst is not.
* EXDEV: src and dst are on different filesystems.
- *
+ *
* Side effects:
- * The implementation of rename may allow cross-filesystem renames,
- * but the caller should be prepared to emulate it with copy and
- * delete if errno is EXDEV.
+ * The implementation of rename may allow cross-filesystem renames, but
+ * the caller should be prepared to emulate it with copy and delete if
+ * errno is EXDEV.
*
*---------------------------------------------------------------------------
*/
-int
-TclpObjRenameFile(srcPathPtr, destPathPtr)
- Tcl_Obj *srcPathPtr;
- Tcl_Obj *destPathPtr;
+int
+TclpObjRenameFile(
+ Tcl_Obj *srcPathPtr,
+ Tcl_Obj *destPathPtr)
{
- return DoRenameFile(Tcl_FSGetNativePath(srcPathPtr),
- Tcl_FSGetNativePath(destPathPtr));
+ return DoRenameFile(Tcl_FSGetNativePath(srcPathPtr),
+ Tcl_FSGetNativePath(destPathPtr));
}
static int
-DoRenameFile(src, dst)
- CONST char *src; /* Pathname of file or dir to be renamed
+DoRenameFile(
+ CONST char *src, /* Pathname of file or dir to be renamed
* (native). */
- CONST char *dst; /* New pathname of file or directory
+ CONST char *dst) /* New pathname of file or directory
* (native). */
{
if (rename(src, dst) == 0) { /* INTL: Native. */
@@ -282,21 +308,21 @@ DoRenameFile(src, dst)
}
/*
- * IRIX returns EIO when you attept to move a directory into
- * itself. We just map EIO to EINVAL get the right message on SGI.
- * Most platforms don't return EIO except in really strange cases.
+ * IRIX returns EIO when you attept to move a directory into itself. We
+ * just map EIO to EINVAL get the right message on SGI. Most platforms
+ * don't return EIO except in really strange cases.
*/
-
+
if (errno == EIO) {
errno = EINVAL;
}
-
+
#ifndef NO_REALPATH
/*
- * SunOS 4.1.4 reports overwriting a non-empty directory with a
- * directory as EINVAL instead of EEXIST (first rule out the correct
- * EINVAL result code for moving a directory into itself). Must be
- * conditionally compiled because realpath() not defined on all systems.
+ * SunOS 4.1.4 reports overwriting a non-empty directory with a directory
+ * as EINVAL instead of EEXIST (first rule out the correct EINVAL result
+ * code for moving a directory into itself). Must be conditionally
+ * compiled because realpath() not defined on all systems.
*/
if (errno == EINVAL && haveRealpath) {
@@ -305,12 +331,12 @@ DoRenameFile(src, dst)
Tcl_DirEntry *dirEntPtr;
if ((Realpath((char *) src, srcPath) != NULL) /* INTL: Native. */
- && (Realpath((char *) dst, dstPath) != NULL) /* INTL: Native. */
+ && (Realpath((char *) dst, dstPath) != NULL) /* INTL: Native */
&& (strncmp(srcPath, dstPath, strlen(srcPath)) != 0)) {
dirPtr = opendir(dst); /* INTL: Native. */
if (dirPtr != NULL) {
while (1) {
- dirEntPtr = TclOSreaddir(dirPtr); /* INTL: Native. */
+ dirEntPtr = TclOSreaddir(dirPtr); /* INTL: Native. */
if (dirEntPtr == NULL) {
break;
}
@@ -333,15 +359,15 @@ DoRenameFile(src, dst)
* Alpha reports renaming / as EBUSY and Linux reports it as EACCES,
* instead of EINVAL.
*/
-
+
errno = EINVAL;
}
/*
- * DEC Alpha OSF1 V3.0 returns EACCES when attempting to move a
- * file across filesystems and the parent directory of that file is
- * not writable. Most other systems return EXDEV. Does nothing to
- * correct this behavior.
+ * DEC Alpha OSF1 V3.0 returns EACCES when attempting to move a file
+ * across filesystems and the parent directory of that file is not
+ * writable. Most other systems return EXDEV. Does nothing to correct this
+ * behavior.
*/
return TCL_ERROR;
@@ -352,32 +378,32 @@ DoRenameFile(src, dst)
*
* TclpObjCopyFile, DoCopyFile --
*
- * Copy a single file (not a directory). If dst already exists and
- * is not a directory, it is removed.
+ * Copy a single file (not a directory). If dst already exists and is not
+ * a directory, it is removed.
*
* Results:
- * If the file was successfully copied, returns TCL_OK. Otherwise
- * the return value is TCL_ERROR and errno is set to indicate the
- * error. Some possible values for errno are:
+ * If the file was successfully copied, returns TCL_OK. Otherwise the
+ * return value is TCL_ERROR and errno is set to indicate the error. Some
+ * possible values for errno are:
*
- * EACCES: src or dst parent directory can't be read and/or written.
+ * EACCES: src or dst parent directory can't be read and/or written.
* EISDIR: src or dst is a directory.
- * ENOENT: src doesn't exist. src or dst is "".
+ * ENOENT: src doesn't exist. src or dst is "".
*
* Side effects:
- * This procedure will also copy symbolic links, block, and
- * character devices, and fifos. For symbolic links, the links
- * themselves will be copied and not what they point to. For the
- * other special file types, the directory entry will be copied and
- * not the contents of the device that it refers to.
+ * This procedure will also copy symbolic links, block, and character
+ * devices, and fifos. For symbolic links, the links themselves will be
+ * copied and not what they point to. For the other special file types,
+ * the directory entry will be copied and not the contents of the device
+ * that it refers to.
*
*---------------------------------------------------------------------------
*/
-int
-TclpObjCopyFile(srcPathPtr, destPathPtr)
- Tcl_Obj *srcPathPtr;
- Tcl_Obj *destPathPtr;
+int
+TclpObjCopyFile(
+ Tcl_Obj *srcPathPtr,
+ Tcl_Obj *destPathPtr)
{
CONST char *src = Tcl_FSGetNativePath(srcPathPtr);
Tcl_StatBuf srcStatBuf;
@@ -390,11 +416,11 @@ TclpObjCopyFile(srcPathPtr, destPathPtr)
}
static int
-DoCopyFile(src, dst, statBufPtr)
- CONST char *src; /* Pathname of file to be copied (native). */
- CONST char *dst; /* Pathname of file to copy to (native). */
- CONST Tcl_StatBuf *statBufPtr;
- /* Used to determine filetype. */
+DoCopyFile(
+ CONST char *src, /* Pathname of file to be copied (native). */
+ CONST char *dst, /* Pathname of file to copy to (native). */
+ CONST Tcl_StatBuf *statBufPtr)
+ /* Used to determine filetype. */
{
Tcl_StatBuf dstStatBuf;
@@ -404,10 +430,10 @@ DoCopyFile(src, dst, statBufPtr)
}
/*
- * symlink, and some of the other calls will fail if the target
- * exists, so we remove it first
+ * Symlink, and some of the other calls will fail if the target exists, so
+ * we remove it first.
*/
-
+
if (TclOSlstat(dst, &dstStatBuf) == 0) { /* INTL: Native. */
if (S_ISDIR(dstStatBuf.st_mode)) {
errno = EISDIR;
@@ -417,49 +443,43 @@ DoCopyFile(src, dst, statBufPtr)
if (unlink(dst) != 0) { /* INTL: Native. */
if (errno != ENOENT) {
return TCL_ERROR;
- }
+ }
}
switch ((int) (statBufPtr->st_mode & S_IFMT)) {
#ifndef DJGPP
- case S_IFLNK: {
- char link[MAXPATHLEN];
- int length;
+ case S_IFLNK: {
+ char link[MAXPATHLEN];
+ int length;
- length = readlink(src, link, sizeof(link)); /* INTL: Native. */
- if (length == -1) {
- return TCL_ERROR;
- }
- link[length] = '\0';
- if (symlink(link, dst) < 0) { /* INTL: Native. */
- return TCL_ERROR;
- }
-#ifdef HAVE_COPYFILE
-#ifdef WEAK_IMPORT_COPYFILE
- if (copyfile != NULL)
-#endif
- copyfile(src, dst, NULL, COPYFILE_XATTR|COPYFILE_NOFOLLOW_SRC);
-#endif
- break;
+ length = readlink(src, link, sizeof(link)); /* INTL: Native. */
+ if (length == -1) {
+ return TCL_ERROR;
}
-#endif
- case S_IFBLK:
- case S_IFCHR: {
- if (mknod(dst, statBufPtr->st_mode, /* INTL: Native. */
- statBufPtr->st_rdev) < 0) {
- return TCL_ERROR;
- }
- return CopyFileAtts(src, dst, statBufPtr);
+ link[length] = '\0';
+ if (symlink(link, dst) < 0) { /* INTL: Native. */
+ return TCL_ERROR;
}
- case S_IFIFO: {
- if (mkfifo(dst, statBufPtr->st_mode) < 0) { /* INTL: Native. */
- return TCL_ERROR;
- }
- return CopyFileAtts(src, dst, statBufPtr);
+#ifdef MAC_OSX_TCL
+ TclMacOSXCopyFileAttributes(src, dst, statBufPtr);
+#endif
+ break;
+ }
+#endif
+ case S_IFBLK:
+ case S_IFCHR:
+ if (mknod(dst, statBufPtr->st_mode, /* INTL: Native. */
+ statBufPtr->st_rdev) < 0) {
+ return TCL_ERROR;
}
- default: {
- return CopyFile(src, dst, statBufPtr);
+ return CopyFileAtts(src, dst, statBufPtr);
+ case S_IFIFO:
+ if (mkfifo(dst, statBufPtr->st_mode) < 0) { /* INTL: Native. */
+ return TCL_ERROR;
}
+ return CopyFileAtts(src, dst, statBufPtr);
+ default:
+ return TclUnixCopyFile(src, dst, statBufPtr, 0);
}
return TCL_OK;
}
@@ -467,79 +487,91 @@ DoCopyFile(src, dst, statBufPtr)
/*
*----------------------------------------------------------------------
*
- * CopyFile -
+ * TclUnixCopyFile -
*
- * Helper function for TclpCopyFile. Copies one regular file,
- * using read() and write().
+ * Helper function for TclpCopyFile. Copies one regular file, using
+ * read() and write().
*
* Results:
* A standard Tcl result.
*
* Side effects:
- * A file is copied. Dst will be overwritten if it exists.
+ * A file is copied. Dst will be overwritten if it exists.
*
*----------------------------------------------------------------------
*/
-static int
-CopyFile(src, dst, statBufPtr)
- CONST char *src; /* Pathname of file to copy (native). */
- CONST char *dst; /* Pathname of file to create/overwrite
+int
+TclUnixCopyFile(
+ CONST char *src, /* Pathname of file to copy (native). */
+ CONST char *dst, /* Pathname of file to create/overwrite
* (native). */
- CONST Tcl_StatBuf *statBufPtr;
+ CONST Tcl_StatBuf *statBufPtr,
/* Used to determine mode and blocksize. */
+ int dontCopyAtts) /* If flag set, don't copy attributes. */
{
- int srcFd;
- int dstFd;
+ int srcFd, dstFd;
unsigned blockSize; /* Optimal I/O blocksize for filesystem */
char *buffer; /* Data buffer for copy */
size_t nread;
- if ((srcFd = TclOSopen(src, O_RDONLY, 0)) < 0) { /* INTL: Native. */
+#ifdef DJGPP
+#define BINMODE |O_BINARY
+#else
+#define BINMODE
+#endif
+
+ if ((srcFd = TclOSopen(src, O_RDONLY BINMODE, 0)) < 0) { /* INTL: Native */
return TCL_ERROR;
}
- dstFd = TclOSopen(dst, O_CREAT|O_TRUNC|O_WRONLY, /* INTL: Native. */
+ dstFd = TclOSopen(dst, O_CREAT|O_TRUNC|O_WRONLY BINMODE, /* INTL: Native */
statBufPtr->st_mode);
if (dstFd < 0) {
- close(srcFd);
+ close(srcFd);
return TCL_ERROR;
}
-#ifdef HAVE_ST_BLKSIZE
+ /*
+ * Try to work out the best size of buffer to use for copying. If we
+ * can't, it's no big deal as we can just use a (32-bit) page, since
+ * that's likely to be fairly efficient anyway.
+ */
+
+#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
blockSize = statBufPtr->st_blksize;
-#else
-#ifndef NO_FSTATFS
+#elif !defined(NO_FSTATFS)
{
struct statfs fs;
- if (fstatfs(srcFd, &fs, sizeof(fs), 0) == 0) {
+
+ if (fstatfs(srcFd, &fs) == 0) {
blockSize = fs.f_bsize;
} else {
blockSize = 4096;
}
}
-#else
+#else
blockSize = 4096;
-#endif
-#endif
+#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
- /* [SF Tcl Bug 1586470] Even if we HAVE_ST_BLKSIZE, there are
- * filesystems which report a bogus value for the blocksize. An
- * example is the Andrew Filesystem (afs), reporting a blocksize
- * of 0. When detecting such a situation we now simply fall back
- * to a hardwired default size.
+ /*
+ * [SF Tcl Bug 1586470] Even if we HAVE_STRUCT_STAT_ST_BLKSIZE, there are
+ * filesystems which report a bogus value for the blocksize. An example
+ * is the Andrew Filesystem (afs), reporting a blocksize of 0. When
+ * detecting such a situation we now simply fall back to a hardwired
+ * default size.
*/
if (blockSize <= 0) {
- blockSize = 4096;
+ blockSize = 4096;
}
buffer = ckalloc(blockSize);
while (1) {
- nread = read(srcFd, buffer, blockSize);
- if ((nread == -1) || (nread == 0)) {
+ nread = (size_t) read(srcFd, buffer, blockSize);
+ if ((nread == (size_t) -1) || (nread == 0)) {
break;
}
- if (write(dstFd, buffer, nread) != nread) {
+ if ((size_t) write(dstFd, buffer, nread) != nread) {
nread = (size_t) -1;
break;
}
@@ -547,15 +579,14 @@ CopyFile(src, dst, statBufPtr)
ckfree(buffer);
close(srcFd);
- if ((close(dstFd) != 0) || (nread == -1)) {
+ if ((close(dstFd) != 0) || (nread == (size_t) -1)) {
unlink(dst); /* INTL: Native. */
return TCL_ERROR;
}
- if (CopyFileAtts(src, dst, statBufPtr) == TCL_ERROR) {
+ if (!dontCopyAtts && CopyFileAtts(src, dst, statBufPtr) == TCL_ERROR) {
/*
- * The copy succeeded, but setting the permissions failed, so be in
- * a consistent state, we remove the file that was created by the
- * copy.
+ * The copy succeeded, but setting the permissions failed, so be in a
+ * consistent state, we remove the file that was created by the copy.
*/
unlink(dst); /* INTL: Native. */
@@ -569,33 +600,33 @@ CopyFile(src, dst, statBufPtr)
*
* TclpObjDeleteFile, TclpDeleteFile --
*
- * Removes a single file (not a directory).
+ * Removes a single file (not a directory).
*
* Results:
- * If the file was successfully deleted, returns TCL_OK. Otherwise
- * the return value is TCL_ERROR and errno is set to indicate the
- * error. Some possible values for errno are:
+ * If the file was successfully deleted, returns TCL_OK. Otherwise the
+ * return value is TCL_ERROR and errno is set to indicate the error. Some
+ * possible values for errno are:
*
- * EACCES: a parent directory can't be read and/or written.
+ * EACCES: a parent directory can't be read and/or written.
* EISDIR: path is a directory.
* ENOENT: path doesn't exist or is "".
*
* Side effects:
- * The file is deleted, even if it is read-only.
+ * The file is deleted, even if it is read-only.
*
*---------------------------------------------------------------------------
*/
-int
-TclpObjDeleteFile(pathPtr)
- Tcl_Obj *pathPtr;
+int
+TclpObjDeleteFile(
+ Tcl_Obj *pathPtr)
{
return TclpDeleteFile(Tcl_FSGetNativePath(pathPtr));
}
int
-TclpDeleteFile(path)
- CONST char *path; /* Pathname of file to be removed (native). */
+TclpDeleteFile(
+ CONST char *path) /* Pathname of file to be removed (native). */
{
if (unlink(path) != 0) { /* INTL: Native. */
return TCL_ERROR;
@@ -608,37 +639,37 @@ TclpDeleteFile(path)
*
* TclpCreateDirectory, DoCreateDirectory --
*
- * Creates the specified directory. All parent directories of the
- * specified directory must already exist. The directory is
- * automatically created with permissions so that user can access
- * the new directory and create new files or subdirectories in it.
+ * Creates the specified directory. All parent directories of the
+ * specified directory must already exist. The directory is automatically
+ * created with permissions so that user can access the new directory and
+ * create new files or subdirectories in it.
*
* Results:
- * If the directory was successfully created, returns TCL_OK.
- * Otherwise the return value is TCL_ERROR and errno is set to
- * indicate the error. Some possible values for errno are:
+ * If the directory was successfully created, returns TCL_OK. Otherwise
+ * the return value is TCL_ERROR and errno is set to indicate the error.
+ * Some possible values for errno are:
*
- * EACCES: a parent directory can't be read and/or written.
+ * EACCES: a parent directory can't be read and/or written.
* EEXIST: path already exists.
* ENOENT: a parent directory doesn't exist.
*
* Side effects:
- * A directory is created with the current umask, except that
- * permission for u+rwx will always be added.
+ * A directory is created with the current umask, except that permission
+ * for u+rwx will always be added.
*
*---------------------------------------------------------------------------
*/
-int
-TclpObjCreateDirectory(pathPtr)
- Tcl_Obj *pathPtr;
+int
+TclpObjCreateDirectory(
+ Tcl_Obj *pathPtr)
{
return DoCreateDirectory(Tcl_FSGetNativePath(pathPtr));
}
static int
-DoCreateDirectory(path)
- CONST char *path; /* Pathname of directory to create (native). */
+DoCreateDirectory(
+ CONST char *path) /* Pathname of directory to create (native). */
{
mode_t mode;
@@ -662,49 +693,47 @@ DoCreateDirectory(path)
*
* TclpObjCopyDirectory --
*
- * Recursively copies a directory. The target directory dst must
- * not already exist. Note that this function does not merge two
- * directory hierarchies, even if the target directory is an an
- * empty directory.
+ * Recursively copies a directory. The target directory dst must not
+ * already exist. Note that this function does not merge two directory
+ * hierarchies, even if the target directory is an an empty directory.
*
* Results:
- * If the directory was successfully copied, returns TCL_OK.
- * Otherwise the return value is TCL_ERROR, errno is set to indicate
- * the error, and the pathname of the file that caused the error
- * is stored in errorPtr. See TclpObjCreateDirectory and
- * TclpObjCopyFile for a description of possible values for errno.
+ * If the directory was successfully copied, returns TCL_OK. Otherwise
+ * the return value is TCL_ERROR, errno is set to indicate the error, and
+ * the pathname of the file that caused the error is stored in errorPtr.
+ * See TclpObjCreateDirectory and TclpObjCopyFile for a description of
+ * possible values for errno.
*
* Side effects:
- * An exact copy of the directory hierarchy src will be created
- * with the name dst. If an error occurs, the error will
- * be returned immediately, and remaining files will not be
- * processed.
+ * An exact copy of the directory hierarchy src will be created with the
+ * name dst. If an error occurs, the error will be returned immediately,
+ * and remaining files will not be processed.
*
*---------------------------------------------------------------------------
*/
-int
-TclpObjCopyDirectory(srcPathPtr, destPathPtr, errorPtr)
- Tcl_Obj *srcPathPtr;
- Tcl_Obj *destPathPtr;
- Tcl_Obj **errorPtr;
+int
+TclpObjCopyDirectory(
+ Tcl_Obj *srcPathPtr,
+ Tcl_Obj *destPathPtr,
+ Tcl_Obj **errorPtr)
{
Tcl_DString ds;
Tcl_DString srcString, dstString;
int ret;
Tcl_Obj *transPtr;
-
+
transPtr = Tcl_FSGetTranslatedPath(NULL,srcPathPtr);
- Tcl_UtfToExternalDString(NULL,
- (transPtr != NULL ? Tcl_GetString(transPtr) : NULL),
- -1, &srcString);
+ Tcl_UtfToExternalDString(NULL,
+ (transPtr != NULL ? TclGetString(transPtr) : NULL),
+ -1, &srcString);
if (transPtr != NULL) {
Tcl_DecrRefCount(transPtr);
}
transPtr = Tcl_FSGetTranslatedPath(NULL,destPathPtr);
- Tcl_UtfToExternalDString(NULL,
- (transPtr != NULL ? Tcl_GetString(transPtr) : NULL),
- -1, &dstString);
+ Tcl_UtfToExternalDString(NULL,
+ (transPtr != NULL ? TclGetString(transPtr) : NULL),
+ -1, &dstString);
if (transPtr != NULL) {
Tcl_DecrRefCount(transPtr);
}
@@ -721,7 +750,6 @@ TclpObjCopyDirectory(srcPathPtr, destPathPtr, errorPtr)
}
return ret;
}
-
/*
*---------------------------------------------------------------------------
@@ -731,38 +759,38 @@ TclpObjCopyDirectory(srcPathPtr, destPathPtr, errorPtr)
* Removes directory (and its contents, if the recursive flag is set).
*
* Results:
- * If the directory was successfully removed, returns TCL_OK.
- * Otherwise the return value is TCL_ERROR, errno is set to indicate
- * the error, and the pathname of the file that caused the error
- * is stored in errorPtr. Some possible values for errno are:
+ * If the directory was successfully removed, returns TCL_OK. Otherwise
+ * the return value is TCL_ERROR, errno is set to indicate the error, and
+ * the pathname of the file that caused the error is stored in errorPtr.
+ * Some possible values for errno are:
*
- * EACCES: path directory can't be read and/or written.
+ * EACCES: path directory can't be read and/or written.
* EEXIST: path is a non-empty directory.
* EINVAL: path is a root directory.
* ENOENT: path doesn't exist or is "".
* ENOTDIR: path is not a directory.
*
* Side effects:
- * Directory removed. If an error occurs, the error will be returned
+ * Directory removed. If an error occurs, the error will be returned
* immediately, and remaining files will not be deleted.
*
*---------------------------------------------------------------------------
*/
-
-int
-TclpObjRemoveDirectory(pathPtr, recursive, errorPtr)
- Tcl_Obj *pathPtr;
- int recursive;
- Tcl_Obj **errorPtr;
+
+int
+TclpObjRemoveDirectory(
+ Tcl_Obj *pathPtr,
+ int recursive,
+ Tcl_Obj **errorPtr)
{
Tcl_DString ds;
Tcl_DString pathString;
int ret;
Tcl_Obj *transPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
- Tcl_UtfToExternalDString(NULL,
- (transPtr != NULL ? Tcl_GetString(transPtr) : NULL),
- -1, &pathString);
+ Tcl_UtfToExternalDString(NULL,
+ (transPtr != NULL ? TclGetString(transPtr) : NULL),
+ -1, &pathString);
if (transPtr != NULL) {
Tcl_DecrRefCount(transPtr);
}
@@ -778,35 +806,38 @@ TclpObjRemoveDirectory(pathPtr, recursive, errorPtr)
}
static int
-DoRemoveDirectory(pathPtr, recursive, errorPtr)
- Tcl_DString *pathPtr; /* Pathname of directory to be removed
+DoRemoveDirectory(
+ Tcl_DString *pathPtr, /* Pathname of directory to be removed
* (native). */
- int recursive; /* If non-zero, removes directories that
- * are nonempty. Otherwise, will only remove
- * empty directories. */
- Tcl_DString *errorPtr; /* If non-NULL, uninitialized or free
- * DString filled with UTF-8 name of file
- * causing error. */
+ int recursive, /* If non-zero, removes directories that are
+ * nonempty. Otherwise, will only remove empty
+ * directories. */
+ Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free DString
+ * filled with UTF-8 name of file causing
+ * error. */
{
CONST char *path;
mode_t oldPerm = 0;
int result;
-
+
path = Tcl_DStringValue(pathPtr);
-
+
if (recursive != 0) {
- /* We should try to change permissions so this can be deleted */
+ /*
+ * We should try to change permissions so this can be deleted.
+ */
+
Tcl_StatBuf statBuf;
int newPerm;
if (TclOSstat(path, &statBuf) == 0) {
oldPerm = (mode_t) (statBuf.st_mode & 0x00007FFF);
}
-
+
newPerm = oldPerm | (64+128+256);
chmod(path, (mode_t) newPerm);
}
-
+
if (rmdir(path) == 0) { /* INTL: Native. */
return TCL_OK;
}
@@ -821,19 +852,22 @@ DoRemoveDirectory(pathPtr, recursive, errorPtr)
}
result = TCL_ERROR;
}
-
+
/*
- * The directory is nonempty, but the recursive flag has been
- * specified, so we recursively remove all the files in the directory.
+ * The directory is nonempty, but the recursive flag has been specified,
+ * so we recursively remove all the files in the directory.
*/
if (result == TCL_OK) {
result = TraverseUnixTree(TraversalDelete, pathPtr, NULL, errorPtr, 1);
}
-
+
if ((result != TCL_OK) && (recursive != 0)) {
- /* Try to restore permissions */
- chmod(path, oldPerm);
+ /*
+ * Try to restore permissions.
+ */
+
+ chmod(path, oldPerm);
}
return result;
}
@@ -843,40 +877,41 @@ DoRemoveDirectory(pathPtr, recursive, errorPtr)
*
* TraverseUnixTree --
*
- * Traverse directory tree specified by sourcePtr, calling the function
- * traverseProc for each file and directory encountered. If destPtr
- * is non-null, each of name in the sourcePtr directory is appended to
- * the directory specified by destPtr and passed as the second argument
- * to traverseProc() .
+ * Traverse directory tree specified by sourcePtr, calling the function
+ * traverseProc for each file and directory encountered. If destPtr is
+ * non-null, each of name in the sourcePtr directory is appended to the
+ * directory specified by destPtr and passed as the second argument to
+ * traverseProc().
*
* Results:
- * Standard Tcl result.
+ * Standard Tcl result.
*
* Side effects:
- * None caused by TraverseUnixTree, however the user specified
- * traverseProc() may change state. If an error occurs, the error will
- * be returned immediately, and remaining files will not be processed.
+ * None caused by TraverseUnixTree, however the user specified
+ * traverseProc() may change state. If an error occurs, the error will be
+ * returned immediately, and remaining files will not be processed.
*
*---------------------------------------------------------------------------
*/
-static int
-TraverseUnixTree(traverseProc, sourcePtr, targetPtr, errorPtr, doRewind)
- TraversalProc *traverseProc;/* Function to call for every file and
+static int
+TraverseUnixTree(
+ TraversalProc *traverseProc,/* Function to call for every file and
* directory in source hierarchy. */
- Tcl_DString *sourcePtr; /* Pathname of source directory to be
+ Tcl_DString *sourcePtr, /* Pathname of source directory to be
* traversed (native). */
- Tcl_DString *targetPtr; /* Pathname of directory to traverse in
+ Tcl_DString *targetPtr, /* Pathname of directory to traverse in
* parallel with source directory (native). */
- Tcl_DString *errorPtr; /* If non-NULL, uninitialized or free
- * DString filled with UTF-8 name of file
- * causing error. */
- int doRewind; /* Flag indicating that to ensure complete
+ Tcl_DString *errorPtr, /* If non-NULL, uninitialized or free DString
+ * filled with UTF-8 name of file causing
+ * error. */
+ int doRewind) /* Flag indicating that to ensure complete
* traversal of source hierarchy, the readdir
* loop should be rewound whenever
* traverseProc has returned TCL_OK; this is
* required when traverseProc modifies the
- * source hierarchy, e.g. by deleting files. */
+ * source hierarchy, e.g. by deleting
+ * files. */
{
Tcl_StatBuf statBuf;
CONST char *source, *errfile;
@@ -912,7 +947,7 @@ TraverseUnixTree(traverseProc, sourcePtr, targetPtr, errorPtr, doRewind)
#ifndef HAVE_FTS
dirPtr = opendir(source); /* INTL: Native. */
if (dirPtr == NULL) {
- /*
+ /*
* Can't read directory
*/
@@ -968,9 +1003,10 @@ TraverseUnixTree(traverseProc, sourcePtr, targetPtr, errorPtr, doRewind)
if (doRewind && (numProcessed > MAX_READDIR_UNLINK_THRESHOLD)) {
/*
* Call rewinddir if we've called unlink or rmdir so many times
- * (since the opendir or the previous rewinddir), to avoid
- * a NULL-return that may a symptom of a buggy readdir.
+ * (since the opendir or the previous rewinddir), to avoid a
+ * NULL-return that may a symptom of a buggy readdir.
*/
+
rewinddir(dirPtr);
numProcessed = 0;
}
@@ -988,8 +1024,8 @@ TraverseUnixTree(traverseProc, sourcePtr, targetPtr, errorPtr, doRewind)
if (result == TCL_OK) {
/*
- * Call traverseProc() on a directory after visiting all the
- * files in that directory.
+ * Call traverseProc() on a directory after visiting all the files in
+ * that directory.
*/
result = (*traverseProc)(sourcePtr, targetPtr, &statBuf, DOTREE_POSTD,
@@ -998,7 +1034,7 @@ TraverseUnixTree(traverseProc, sourcePtr, targetPtr, errorPtr, doRewind)
#else /* HAVE_FTS */
paths[0] = source;
fts = fts_open((char**)paths, FTS_PHYSICAL | FTS_NOCHDIR |
- (noFtsStat || doRewind ? FTS_NOSTAT : 0), NULL);
+ (noFtsStat || doRewind ? FTS_NOSTAT : 0), NULL);
if (fts == NULL) {
errfile = source;
goto end;
@@ -1011,7 +1047,7 @@ TraverseUnixTree(traverseProc, sourcePtr, targetPtr, errorPtr, doRewind)
while ((ent = fts_read(fts)) != NULL) {
unsigned short info = ent->fts_info;
- char * path = ent->fts_path + sourceLen;
+ char *path = ent->fts_path + sourceLen;
unsigned short pathlen = ent->fts_pathlen - sourceLen;
int type;
Tcl_StatBuf *statBufPtr = NULL;
@@ -1025,15 +1061,15 @@ TraverseUnixTree(traverseProc, sourcePtr, targetPtr, errorPtr, doRewind)
Tcl_DStringAppend(targetPtr, path, pathlen);
}
switch (info) {
- case FTS_D:
- type = DOTREE_PRED;
- break;
- case FTS_DP:
- type = DOTREE_POSTD;
- break;
- default:
- type = DOTREE_F;
- break;
+ case FTS_D:
+ type = DOTREE_PRED;
+ break;
+ case FTS_DP:
+ type = DOTREE_POSTD;
+ break;
+ default:
+ type = DOTREE_F;
+ break;
}
if (!doRewind) { /* no need to stat for delete */
if (noFtsStat) {
@@ -1043,7 +1079,7 @@ TraverseUnixTree(traverseProc, sourcePtr, targetPtr, errorPtr, doRewind)
break;
}
} else {
- statBufPtr = ent->fts_statp;
+ statBufPtr = (Tcl_StatBuf *) ent->fts_statp;
}
}
result = (*traverseProc)(sourcePtr, targetPtr, statBufPtr, type,
@@ -1058,7 +1094,7 @@ TraverseUnixTree(traverseProc, sourcePtr, targetPtr, errorPtr, doRewind)
}
#endif /* HAVE_FTS */
- end:
+ end:
if (errfile != NULL) {
if (errorPtr != NULL) {
Tcl_ExternalToUtfDString(NULL, errfile, -1, errorPtr);
@@ -1069,7 +1105,7 @@ TraverseUnixTree(traverseProc, sourcePtr, targetPtr, errorPtr, doRewind)
if (fts != NULL) {
fts_close(fts);
}
-#endif /* HAVE_FTS */
+#endif
return result;
}
@@ -1079,56 +1115,55 @@ TraverseUnixTree(traverseProc, sourcePtr, targetPtr, errorPtr, doRewind)
*
* TraversalCopy
*
- * Called from TraverseUnixTree in order to execute a recursive copy
- * of a directory.
+ * Called from TraverseUnixTree in order to execute a recursive copy of a
+ * directory.
*
* Results:
- * Standard Tcl result.
+ * Standard Tcl result.
*
* Side effects:
- * The file or directory src may be copied to dst, depending on
- * the value of type.
- *
+ * The file or directory src may be copied to dst, depending on the value
+ * of type.
+ *
*----------------------------------------------------------------------
*/
-static int
-TraversalCopy(srcPtr, dstPtr, statBufPtr, type, errorPtr)
- Tcl_DString *srcPtr; /* Source pathname to copy (native). */
- Tcl_DString *dstPtr; /* Destination pathname of copy (native). */
- CONST Tcl_StatBuf *statBufPtr;
+static int
+TraversalCopy(
+ Tcl_DString *srcPtr, /* Source pathname to copy (native). */
+ Tcl_DString *dstPtr, /* Destination pathname of copy (native). */
+ CONST Tcl_StatBuf *statBufPtr,
/* Stat info for file specified by srcPtr. */
- int type; /* Reason for call - see TraverseUnixTree(). */
- Tcl_DString *errorPtr; /* If non-NULL, uninitialized or free
- * DString filled with UTF-8 name of file
- * causing error. */
+ int type, /* Reason for call - see TraverseUnixTree(). */
+ Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free DString
+ * filled with UTF-8 name of file causing
+ * error. */
{
switch (type) {
- case DOTREE_F:
- if (DoCopyFile(Tcl_DStringValue(srcPtr), Tcl_DStringValue(dstPtr),
- statBufPtr) == TCL_OK) {
- return TCL_OK;
- }
- break;
-
- case DOTREE_PRED:
- if (DoCreateDirectory(Tcl_DStringValue(dstPtr)) == TCL_OK) {
- return TCL_OK;
- }
- break;
+ case DOTREE_F:
+ if (DoCopyFile(Tcl_DStringValue(srcPtr), Tcl_DStringValue(dstPtr),
+ statBufPtr) == TCL_OK) {
+ return TCL_OK;
+ }
+ break;
- case DOTREE_POSTD:
- if (CopyFileAtts(Tcl_DStringValue(srcPtr),
- Tcl_DStringValue(dstPtr), statBufPtr) == TCL_OK) {
- return TCL_OK;
- }
- break;
+ case DOTREE_PRED:
+ if (DoCreateDirectory(Tcl_DStringValue(dstPtr)) == TCL_OK) {
+ return TCL_OK;
+ }
+ break;
+ case DOTREE_POSTD:
+ if (CopyFileAtts(Tcl_DStringValue(srcPtr),
+ Tcl_DStringValue(dstPtr), statBufPtr) == TCL_OK) {
+ return TCL_OK;
+ }
+ break;
}
/*
- * There shouldn't be a problem with src, because we already checked it
- * to get here.
+ * There shouldn't be a problem with src, because we already checked it to
+ * get here.
*/
if (errorPtr != NULL) {
@@ -1143,47 +1178,44 @@ TraversalCopy(srcPtr, dstPtr, statBufPtr, type, errorPtr)
*
* TraversalDelete --
*
- * Called by procedure TraverseUnixTree for every file and directory
- * that it encounters in a directory hierarchy. This procedure unlinks
- * files, and removes directories after all the containing files
- * have been processed.
+ * Called by procedure TraverseUnixTree for every file and directory that
+ * it encounters in a directory hierarchy. This procedure unlinks files,
+ * and removes directories after all the containing files have been
+ * processed.
*
* Results:
- * Standard Tcl result.
+ * Standard Tcl result.
*
* Side effects:
- * Files or directory specified by src will be deleted.
+ * Files or directory specified by src will be deleted.
*
*----------------------------------------------------------------------
*/
static int
-TraversalDelete(srcPtr, ignore, statBufPtr, type, errorPtr)
- Tcl_DString *srcPtr; /* Source pathname (native). */
- Tcl_DString *ignore; /* Destination pathname (not used). */
- CONST Tcl_StatBuf *statBufPtr;
+TraversalDelete(
+ Tcl_DString *srcPtr, /* Source pathname (native). */
+ Tcl_DString *ignore, /* Destination pathname (not used). */
+ CONST Tcl_StatBuf *statBufPtr,
/* Stat info for file specified by srcPtr. */
- int type; /* Reason for call - see TraverseUnixTree(). */
- Tcl_DString *errorPtr; /* If non-NULL, uninitialized or free
- * DString filled with UTF-8 name of file
- * causing error. */
+ int type, /* Reason for call - see TraverseUnixTree(). */
+ Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free DString
+ * filled with UTF-8 name of file causing
+ * error. */
{
switch (type) {
- case DOTREE_F: {
- if (TclpDeleteFile(Tcl_DStringValue(srcPtr)) == 0) {
- return TCL_OK;
- }
- break;
+ case DOTREE_F:
+ if (TclpDeleteFile(Tcl_DStringValue(srcPtr)) == 0) {
+ return TCL_OK;
}
- case DOTREE_PRED: {
+ break;
+ case DOTREE_PRED:
+ return TCL_OK;
+ case DOTREE_POSTD:
+ if (DoRemoveDirectory(srcPtr, 0, NULL) == 0) {
return TCL_OK;
}
- case DOTREE_POSTD: {
- if (DoRemoveDirectory(srcPtr, 0, NULL) == 0) {
- return TCL_OK;
- }
- break;
- }
+ break;
}
if (errorPtr != NULL) {
Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(srcPtr),
@@ -1197,42 +1229,40 @@ TraversalDelete(srcPtr, ignore, statBufPtr, type, errorPtr)
*
* CopyFileAtts --
*
- * Copy the file attributes such as owner, group, permissions,
- * and modification date from one file to another.
+ * Copy the file attributes such as owner, group, permissions, and
+ * modification date from one file to another.
*
* Results:
* Standard Tcl result.
*
* Side effects:
- * user id, group id, permission bits, last modification time, and
- * last access time are updated in the new file to reflect the
- * old file.
+ * User id, group id, permission bits, last modification time, and last
+ * access time are updated in the new file to reflect the old file.
*
*---------------------------------------------------------------------------
*/
static int
-CopyFileAtts(src, dst, statBufPtr)
- CONST char *src; /* Path name of source file (native). */
- CONST char *dst; /* Path name of target file (native). */
- CONST Tcl_StatBuf *statBufPtr;
+CopyFileAtts(
+ CONST char *src, /* Path name of source file (native). */
+ CONST char *dst, /* Path name of target file (native). */
+ CONST Tcl_StatBuf *statBufPtr)
/* Stat info for source file */
{
struct utimbuf tval;
mode_t newMode;
-
+
newMode = statBufPtr->st_mode
& (S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO);
-
- /*
- * Note that if you copy a setuid file that is owned by someone
- * else, and you are not root, then the copy will be setuid to you.
- * The most correct implementation would probably be to have the
- * copy not setuid to anyone if the original file was owned by
- * someone else, but this corner case isn't currently handled.
- * It would require another lstat(), or getuid().
+
+ /*
+ * Note that if you copy a setuid file that is owned by someone else, and
+ * you are not root, then the copy will be setuid to you. The most correct
+ * implementation would probably be to have the copy not setuid to anyone
+ * if the original file was owned by someone else, but this corner case
+ * isn't currently handled. It would require another lstat(), or getuid().
*/
-
+
if (chmod(dst, newMode)) { /* INTL: Native. */
newMode &= ~(S_ISUID | S_ISGID);
if (chmod(dst, newMode)) { /* INTL: Native. */
@@ -1240,72 +1270,69 @@ CopyFileAtts(src, dst, statBufPtr)
}
}
- tval.actime = statBufPtr->st_atime;
- tval.modtime = statBufPtr->st_mtime;
+ tval.actime = statBufPtr->st_atime;
+ tval.modtime = statBufPtr->st_mtime;
if (utime(dst, &tval)) { /* INTL: Native. */
return TCL_ERROR;
}
-#ifdef HAVE_COPYFILE
-#ifdef WEAK_IMPORT_COPYFILE
- if (copyfile != NULL)
-#endif
- copyfile(src, dst, NULL, COPYFILE_XATTR|COPYFILE_ACL);
+#ifdef MAC_OSX_TCL
+ TclMacOSXCopyFileAttributes(src, dst, statBufPtr);
#endif
return TCL_OK;
}
-
/*
*----------------------------------------------------------------------
*
* GetGroupAttribute
*
- * Gets the group attribute of a file.
+ * Gets the group attribute of a file.
*
* Results:
- * Standard TCL result. Returns a new Tcl_Obj in attributePtrPtr
- * if there is no error.
+ * Standard TCL result. Returns a new Tcl_Obj in attributePtrPtr if there
+ * is no error.
*
* Side effects:
- * A new object is allocated.
- *
+ * A new object is allocated.
+ *
*----------------------------------------------------------------------
*/
static int
-GetGroupAttribute(interp, objIndex, fileName, attributePtrPtr)
- Tcl_Interp *interp; /* The interp we are using for errors. */
- int objIndex; /* The index of the attribute. */
- Tcl_Obj *fileName; /* The name of the file (UTF-8). */
- Tcl_Obj **attributePtrPtr; /* A pointer to return the object with. */
+GetGroupAttribute(
+ Tcl_Interp *interp, /* The interp we are using for errors. */
+ int objIndex, /* The index of the attribute. */
+ Tcl_Obj *fileName, /* The name of the file (UTF-8). */
+ Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */
{
Tcl_StatBuf statBuf;
struct group *groupPtr;
int result;
result = TclpObjStat(fileName, &statBuf);
-
+
if (result != 0) {
- Tcl_AppendResult(interp, "could not read \"",
- Tcl_GetString(fileName), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "could not read \"",
+ TclGetString(fileName), "\": ",
+ Tcl_PosixError(interp), NULL);
+ }
return TCL_ERROR;
}
groupPtr = TclpGetGrGid(statBuf.st_gid);
- if (result == -1 || groupPtr == NULL) {
+ if (groupPtr == NULL) {
*attributePtrPtr = Tcl_NewIntObj((int) statBuf.st_gid);
} else {
Tcl_DString ds;
CONST char *utf;
- utf = Tcl_ExternalToUtfDString(NULL, groupPtr->gr_name, -1, &ds);
+ utf = Tcl_ExternalToUtfDString(NULL, groupPtr->gr_name, -1, &ds);
*attributePtrPtr = Tcl_NewStringObj(utf, -1);
Tcl_DStringFree(&ds);
}
- endgrent();
return TCL_OK;
}
@@ -1314,51 +1341,52 @@ GetGroupAttribute(interp, objIndex, fileName, attributePtrPtr)
*
* GetOwnerAttribute
*
- * Gets the owner attribute of a file.
+ * Gets the owner attribute of a file.
*
* Results:
- * Standard TCL result. Returns a new Tcl_Obj in attributePtrPtr
- * if there is no error.
+ * Standard TCL result. Returns a new Tcl_Obj in attributePtrPtr if there
+ * is no error.
*
* Side effects:
- * A new object is allocated.
- *
+ * A new object is allocated.
+ *
*----------------------------------------------------------------------
*/
static int
-GetOwnerAttribute(interp, objIndex, fileName, attributePtrPtr)
- Tcl_Interp *interp; /* The interp we are using for errors. */
- int objIndex; /* The index of the attribute. */
- Tcl_Obj *fileName; /* The name of the file (UTF-8). */
- Tcl_Obj **attributePtrPtr; /* A pointer to return the object with. */
+GetOwnerAttribute(
+ Tcl_Interp *interp, /* The interp we are using for errors. */
+ int objIndex, /* The index of the attribute. */
+ Tcl_Obj *fileName, /* The name of the file (UTF-8). */
+ Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */
{
Tcl_StatBuf statBuf;
struct passwd *pwPtr;
int result;
result = TclpObjStat(fileName, &statBuf);
-
+
if (result != 0) {
- Tcl_AppendResult(interp, "could not read \"",
- Tcl_GetString(fileName), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "could not read \"",
+ TclGetString(fileName), "\": ",
+ Tcl_PosixError(interp), NULL);
+ }
return TCL_ERROR;
}
pwPtr = TclpGetPwUid(statBuf.st_uid);
- if (result == -1 || pwPtr == NULL) {
+ if (pwPtr == NULL) {
*attributePtrPtr = Tcl_NewIntObj((int) statBuf.st_uid);
} else {
Tcl_DString ds;
CONST char *utf;
- utf = Tcl_ExternalToUtfDString(NULL, pwPtr->pw_name, -1, &ds);
+ utf = Tcl_ExternalToUtfDString(NULL, pwPtr->pw_name, -1, &ds);
*attributePtrPtr = Tcl_NewStringObj(utf, Tcl_DStringLength(&ds));
Tcl_DStringFree(&ds);
}
- endpwent();
return TCL_OK;
}
@@ -1367,42 +1395,41 @@ GetOwnerAttribute(interp, objIndex, fileName, attributePtrPtr)
*
* GetPermissionsAttribute
*
- * Gets the group attribute of a file.
+ * Gets the group attribute of a file.
*
* Results:
- * Standard TCL result. Returns a new Tcl_Obj in attributePtrPtr
- * if there is no error. The object will have ref count 0.
+ * Standard TCL result. Returns a new Tcl_Obj in attributePtrPtr if there
+ * is no error. The object will have ref count 0.
*
* Side effects:
- * A new object is allocated.
- *
+ * A new object is allocated.
+ *
*----------------------------------------------------------------------
*/
static int
-GetPermissionsAttribute(interp, objIndex, fileName, attributePtrPtr)
- Tcl_Interp *interp; /* The interp we are using for errors. */
- int objIndex; /* The index of the attribute. */
- Tcl_Obj *fileName; /* The name of the file (UTF-8). */
- Tcl_Obj **attributePtrPtr; /* A pointer to return the object with. */
+GetPermissionsAttribute(
+ Tcl_Interp *interp, /* The interp we are using for errors. */
+ int objIndex, /* The index of the attribute. */
+ Tcl_Obj *fileName, /* The name of the file (UTF-8). */
+ Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */
{
Tcl_StatBuf statBuf;
- char returnString[7];
int result;
result = TclpObjStat(fileName, &statBuf);
-
+
if (result != 0) {
- Tcl_AppendResult(interp, "could not read \"",
- Tcl_GetString(fileName), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "could not read \"",
+ TclGetString(fileName), "\": ",
+ Tcl_PosixError(interp), NULL);
+ }
return TCL_ERROR;
}
- sprintf(returnString, "%0#5lo", (long) (statBuf.st_mode & 0x00007FFF));
-
- *attributePtrPtr = Tcl_NewStringObj(returnString, -1);
-
+ *attributePtrPtr = Tcl_ObjPrintf(
+ "%0#5lo", (long) (statBuf.st_mode & 0x00007FFF));
return TCL_OK;
}
@@ -1411,23 +1438,23 @@ GetPermissionsAttribute(interp, objIndex, fileName, attributePtrPtr)
*
* SetGroupAttribute --
*
- * Sets the group of the file to the specified group.
+ * Sets the group of the file to the specified group.
*
* Results:
- * Standard TCL result.
+ * Standard TCL result.
*
* Side effects:
- * As above.
- *
+ * As above.
+ *
*---------------------------------------------------------------------------
*/
static int
-SetGroupAttribute(interp, objIndex, fileName, attributePtr)
- Tcl_Interp *interp; /* The interp for error reporting. */
- int objIndex; /* The index of the attribute. */
- Tcl_Obj *fileName; /* The name of the file (UTF-8). */
- Tcl_Obj *attributePtr; /* New group for file. */
+SetGroupAttribute(
+ Tcl_Interp *interp, /* The interp for error reporting. */
+ int objIndex, /* The index of the attribute. */
+ Tcl_Obj *fileName, /* The name of the file (UTF-8). */
+ Tcl_Obj *attributePtr) /* New group for file. */
{
long gid;
int result;
@@ -1435,21 +1462,22 @@ SetGroupAttribute(interp, objIndex, fileName, attributePtr)
if (Tcl_GetLongFromObj(NULL, attributePtr, &gid) != TCL_OK) {
Tcl_DString ds;
- struct group *groupPtr;
+ struct group *groupPtr = NULL;
CONST char *string;
int length;
string = Tcl_GetStringFromObj(attributePtr, &length);
+
native = Tcl_UtfToExternalDString(NULL, string, length, &ds);
groupPtr = TclpGetGrNam(native); /* INTL: Native. */
Tcl_DStringFree(&ds);
if (groupPtr == NULL) {
- endgrent();
- Tcl_AppendResult(interp, "could not set group for file \"",
- Tcl_GetString(fileName), "\": group \"",
- string, "\" does not exist",
- (char *) NULL);
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "could not set group for file \"",
+ TclGetString(fileName), "\": group \"", string,
+ "\" does not exist", NULL);
+ }
return TCL_ERROR;
}
gid = groupPtr->gr_gid;
@@ -1458,13 +1486,14 @@ SetGroupAttribute(interp, objIndex, fileName, attributePtr)
native = Tcl_FSGetNativePath(fileName);
result = chown(native, (uid_t) -1, (gid_t) gid); /* INTL: Native. */
- endgrent();
if (result != 0) {
- Tcl_AppendResult(interp, "could not set group for file \"",
- Tcl_GetString(fileName), "\": ", Tcl_PosixError(interp),
- (char *) NULL);
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "could not set group for file \"",
+ TclGetString(fileName), "\": ", Tcl_PosixError(interp),
+ NULL);
+ }
return TCL_ERROR;
- }
+ }
return TCL_OK;
}
@@ -1473,23 +1502,23 @@ SetGroupAttribute(interp, objIndex, fileName, attributePtr)
*
* SetOwnerAttribute --
*
- * Sets the owner of the file to the specified owner.
+ * Sets the owner of the file to the specified owner.
*
* Results:
- * Standard TCL result.
+ * Standard TCL result.
*
* Side effects:
- * As above.
- *
+ * As above.
+ *
*---------------------------------------------------------------------------
*/
static int
-SetOwnerAttribute(interp, objIndex, fileName, attributePtr)
- Tcl_Interp *interp; /* The interp for error reporting. */
- int objIndex; /* The index of the attribute. */
- Tcl_Obj *fileName; /* The name of the file (UTF-8). */
- Tcl_Obj *attributePtr; /* New owner for file. */
+SetOwnerAttribute(
+ Tcl_Interp *interp, /* The interp for error reporting. */
+ int objIndex, /* The index of the attribute. */
+ Tcl_Obj *fileName, /* The name of the file (UTF-8). */
+ Tcl_Obj *attributePtr) /* New owner for file. */
{
long uid;
int result;
@@ -1497,34 +1526,36 @@ SetOwnerAttribute(interp, objIndex, fileName, attributePtr)
if (Tcl_GetLongFromObj(NULL, attributePtr, &uid) != TCL_OK) {
Tcl_DString ds;
- struct passwd *pwPtr;
+ struct passwd *pwPtr = NULL;
CONST char *string;
int length;
string = Tcl_GetStringFromObj(attributePtr, &length);
+
native = Tcl_UtfToExternalDString(NULL, string, length, &ds);
- pwPtr = TclpGetPwNam(native); /* INTL: Native. */
+ pwPtr = TclpGetPwNam(native); /* INTL: Native. */
Tcl_DStringFree(&ds);
if (pwPtr == NULL) {
- endpwent();
- Tcl_AppendResult(interp, "could not set owner for file \"",
- Tcl_GetString(fileName), "\": user \"",
- string, "\" does not exist",
- (char *) NULL);
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "could not set owner for file \"",
+ TclGetString(fileName), "\": user \"", string,
+ "\" does not exist", NULL);
+ }
return TCL_ERROR;
}
uid = pwPtr->pw_uid;
}
native = Tcl_FSGetNativePath(fileName);
- result = chown(native, (uid_t) uid, (gid_t) -1); /* INTL: Native. */
-
- endpwent();
+ result = chown(native, (uid_t) uid, (gid_t) -1); /* INTL: Native. */
+
if (result != 0) {
- Tcl_AppendResult(interp, "could not set owner for file \"",
- Tcl_GetString(fileName), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "could not set owner for file \"",
+ TclGetString(fileName), "\": ", Tcl_PosixError(interp),
+ NULL);
+ }
return TCL_ERROR;
}
return TCL_OK;
@@ -1535,57 +1566,75 @@ SetOwnerAttribute(interp, objIndex, fileName, attributePtr)
*
* SetPermissionsAttribute
*
- * Sets the file to the given permission.
+ * Sets the file to the given permission.
*
* Results:
- * Standard TCL result.
+ * Standard TCL result.
*
* Side effects:
- * The permission of the file is changed.
- *
+ * The permission of the file is changed.
+ *
*---------------------------------------------------------------------------
*/
static int
-SetPermissionsAttribute(interp, objIndex, fileName, attributePtr)
- Tcl_Interp *interp; /* The interp we are using for errors. */
- int objIndex; /* The index of the attribute. */
- Tcl_Obj *fileName; /* The name of the file (UTF-8). */
- Tcl_Obj *attributePtr; /* The attribute to set. */
+SetPermissionsAttribute(
+ Tcl_Interp *interp, /* The interp we are using for errors. */
+ int objIndex, /* The index of the attribute. */
+ Tcl_Obj *fileName, /* The name of the file (UTF-8). */
+ Tcl_Obj *attributePtr) /* The attribute to set. */
{
long mode;
mode_t newMode;
- int result;
+ int result = TCL_ERROR;
CONST char *native;
+ char *modeStringPtr = TclGetString(attributePtr);
+ int scanned = TclParseAllWhiteSpace(modeStringPtr, -1);
/*
- * First try if the string is a number
+ * First supply support for octal number format
*/
- if (Tcl_GetLongFromObj(NULL, attributePtr, &mode) == TCL_OK) {
- newMode = (mode_t) (mode & 0x00007FFF);
+
+ if ((modeStringPtr[scanned] == '0')
+ && (modeStringPtr[scanned+1] >= '0')
+ && (modeStringPtr[scanned+1] <= '7')) {
+ /* Leading zero - attempt octal interpretation */
+ Tcl_Obj *modeObj;
+
+ TclNewLiteralStringObj(modeObj, "0o");
+ Tcl_AppendToObj(modeObj, modeStringPtr+scanned+1, -1);
+ result = Tcl_GetLongFromObj(NULL, modeObj, &mode);
+ Tcl_DecrRefCount(modeObj);
+ }
+ if (result == TCL_OK
+ || Tcl_GetLongFromObj(NULL, attributePtr, &mode) == TCL_OK) {
+ newMode = (mode_t) (mode & 0x00007FFF);
} else {
Tcl_StatBuf buf;
- char *modeStringPtr = Tcl_GetString(attributePtr);
/*
* Try the forms "rwxrwxrwx" and "ugo=rwx"
*
- * We get the current mode of the file, in order to allow for
- * ug+-=rwx style chmod strings.
+ * We get the current mode of the file, in order to allow for ug+-=rwx
+ * style chmod strings.
*/
+
result = TclpObjStat(fileName, &buf);
if (result != 0) {
- Tcl_AppendResult(interp, "could not read \"",
- Tcl_GetString(fileName), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "could not read \"",
+ TclGetString(fileName), "\": ",
+ Tcl_PosixError(interp), NULL);
+ }
return TCL_ERROR;
}
newMode = (mode_t) (buf.st_mode & 0x00007FFF);
if (GetModeFromPermString(NULL, modeStringPtr, &newMode) != TCL_OK) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "unknown permission string format \"",
- modeStringPtr, "\"", (char *) NULL);
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "unknown permission string format \"",
+ modeStringPtr, "\"", NULL);
+ }
return TCL_ERROR;
}
}
@@ -1593,15 +1642,17 @@ SetPermissionsAttribute(interp, objIndex, fileName, attributePtr)
native = Tcl_FSGetNativePath(fileName);
result = chmod(native, newMode); /* INTL: Native. */
if (result != 0) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "could not set permissions for file \"",
- Tcl_GetString(fileName), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "could not set permissions for file \"",
+ TclGetString(fileName), "\": ",
+ Tcl_PosixError(interp), NULL);
+ }
return TCL_ERROR;
}
return TCL_OK;
}
+#ifndef DJGPP
/*
*---------------------------------------------------------------------------
*
@@ -1618,23 +1669,24 @@ SetPermissionsAttribute(interp, objIndex, fileName, attributePtr)
*---------------------------------------------------------------------------
*/
-Tcl_Obj*
+Tcl_Obj *
TclpObjListVolumes(void)
{
- Tcl_Obj *resultPtr = Tcl_NewStringObj("/",1);
+ Tcl_Obj *resultPtr = Tcl_NewStringObj("/", 1);
Tcl_IncrRefCount(resultPtr);
return resultPtr;
}
+#endif
/*
*----------------------------------------------------------------------
*
* GetModeFromPermString --
*
- * This procedure is invoked to process the "file permissions"
- * Tcl command, to check for a "rwxrwxrwx" or "ugoa+-=rwxst" string.
- * See the user documentation for details on what it does.
+ * This procedure is invoked to process the "file permissions" Tcl
+ * command, to check for a "rwxrwxrwx" or "ugoa+-=rwxst" string. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -1646,84 +1698,85 @@ TclpObjListVolumes(void)
*/
static int
-GetModeFromPermString(interp, modeStringPtr, modePtr)
- Tcl_Interp *interp; /* The interp we are using for errors. */
- char *modeStringPtr; /* Permissions string */
- mode_t *modePtr; /* pointer to the mode value */
+GetModeFromPermString(
+ Tcl_Interp *interp, /* The interp we are using for errors. */
+ char *modeStringPtr, /* Permissions string */
+ mode_t *modePtr) /* pointer to the mode value */
{
mode_t newMode;
- mode_t oldMode; /* Storage for the value of the old mode
- * (that is passed in), to allow for the
- * chmod style manipulation */
+ mode_t oldMode; /* Storage for the value of the old mode (that
+ * is passed in), to allow for the chmod style
+ * manipulation. */
int i,n, who, op, what, op_found, who_found;
/*
* We start off checking for an "rwxrwxrwx" style permissions string
*/
+
if (strlen(modeStringPtr) != 9) {
- goto chmodStyleCheck;
+ goto chmodStyleCheck;
}
newMode = 0;
for (i = 0; i < 9; i++) {
switch (*(modeStringPtr+i)) {
- case 'r':
- if ((i%3) != 0) {
- goto chmodStyleCheck;
- }
- newMode |= (1<<(8-i));
- break;
- case 'w':
- if ((i%3) != 1) {
- goto chmodStyleCheck;
- }
- newMode |= (1<<(8-i));
- break;
- case 'x':
- if ((i%3) != 2) {
- goto chmodStyleCheck;
- }
- newMode |= (1<<(8-i));
- break;
- case 's':
- if (((i%3) != 2) || (i > 5)) {
- goto chmodStyleCheck;
- }
- newMode |= (1<<(8-i));
- newMode |= (1<<(11-(i/3)));
- break;
- case 'S':
- if (((i%3) != 2) || (i > 5)) {
- goto chmodStyleCheck;
- }
- newMode |= (1<<(11-(i/3)));
- break;
- case 't':
- if (i != 8) {
- goto chmodStyleCheck;
- }
- newMode |= (1<<(8-i));
- newMode |= (1<<9);
- break;
- case 'T':
- if (i != 8) {
- goto chmodStyleCheck;
- }
- newMode |= (1<<9);
- break;
- case '-':
- break;
- default:
- /*
- * Oops, not what we thought it was, so go on
- */
+ case 'r':
+ if ((i%3) != 0) {
goto chmodStyleCheck;
+ }
+ newMode |= (1<<(8-i));
+ break;
+ case 'w':
+ if ((i%3) != 1) {
+ goto chmodStyleCheck;
+ }
+ newMode |= (1<<(8-i));
+ break;
+ case 'x':
+ if ((i%3) != 2) {
+ goto chmodStyleCheck;
+ }
+ newMode |= (1<<(8-i));
+ break;
+ case 's':
+ if (((i%3) != 2) || (i > 5)) {
+ goto chmodStyleCheck;
+ }
+ newMode |= (1<<(8-i));
+ newMode |= (1<<(11-(i/3)));
+ break;
+ case 'S':
+ if (((i%3) != 2) || (i > 5)) {
+ goto chmodStyleCheck;
+ }
+ newMode |= (1<<(11-(i/3)));
+ break;
+ case 't':
+ if (i != 8) {
+ goto chmodStyleCheck;
+ }
+ newMode |= (1<<(8-i));
+ newMode |= (1<<9);
+ break;
+ case 'T':
+ if (i != 8) {
+ goto chmodStyleCheck;
+ }
+ newMode |= (1<<9);
+ break;
+ case '-':
+ break;
+ default:
+ /*
+ * Oops, not what we thought it was, so go on
+ */
+ goto chmodStyleCheck;
}
}
*modePtr = newMode;
return TCL_OK;
- chmodStyleCheck:
+ chmodStyleCheck:
/*
* We now check for an "ugoa+-=rwxst" style permissions string
*/
@@ -1735,18 +1788,18 @@ GetModeFromPermString(interp, modeStringPtr, modePtr)
if (!who_found) {
/* who */
switch (*(modeStringPtr+n+i)) {
- case 'u' :
- who |= 0x9c0;
- continue;
- case 'g' :
- who |= 0x438;
- continue;
- case 'o' :
- who |= 0x207;
- continue;
- case 'a' :
- who |= 0xfff;
- continue;
+ case 'u':
+ who |= 0x9c0;
+ continue;
+ case 'g':
+ who |= 0x438;
+ continue;
+ case 'o':
+ who |= 0x207;
+ continue;
+ case 'a':
+ who |= 0xfff;
+ continue;
}
}
who_found = 1;
@@ -1756,43 +1809,43 @@ GetModeFromPermString(interp, modeStringPtr, modePtr)
if (!op_found) {
/* op */
switch (*(modeStringPtr+n+i)) {
- case '+' :
- op = 1;
- op_found = 1;
- continue;
- case '-' :
- op = 2;
- op_found = 1;
- continue;
- case '=' :
- op = 3;
- op_found = 1;
- continue;
- default :
- return TCL_ERROR;
- }
- }
- /* what */
- switch (*(modeStringPtr+n+i)) {
- case 'r' :
- what |= 0x124;
- continue;
- case 'w' :
- what |= 0x92;
+ case '+':
+ op = 1;
+ op_found = 1;
continue;
- case 'x' :
- what |= 0x49;
+ case '-':
+ op = 2;
+ op_found = 1;
continue;
- case 's' :
- what |= 0xc00;
+ case '=':
+ op = 3;
+ op_found = 1;
continue;
- case 't' :
- what |= 0x200;
- continue;
- case ',' :
- break;
- default :
+ default:
return TCL_ERROR;
+ }
+ }
+ /* what */
+ switch (*(modeStringPtr+n+i)) {
+ case 'r':
+ what |= 0x124;
+ continue;
+ case 'w':
+ what |= 0x92;
+ continue;
+ case 'x':
+ what |= 0x49;
+ continue;
+ case 's':
+ what |= 0xc00;
+ continue;
+ case 't':
+ what |= 0x200;
+ continue;
+ case ',':
+ break;
+ default:
+ return TCL_ERROR;
}
if (*(modeStringPtr+n+i) == ',') {
i++;
@@ -1800,15 +1853,15 @@ GetModeFromPermString(interp, modeStringPtr, modePtr)
}
}
switch (op) {
- case 1 :
- *modePtr = oldMode | (who & what);
- continue;
- case 2 :
- *modePtr = oldMode & ~(who & what);
- continue;
- case 3 :
- *modePtr = (oldMode & ~who) | (who & what);
- continue;
+ case 1:
+ *modePtr = oldMode | (who & what);
+ continue;
+ case 2:
+ *modePtr = oldMode & ~(who & what);
+ continue;
+ case 3:
+ *modePtr = (oldMode & ~who) | (who & what);
+ continue;
}
}
return TCL_OK;
@@ -1819,26 +1872,26 @@ GetModeFromPermString(interp, modeStringPtr, modePtr)
*
* TclpObjNormalizePath --
*
- * This function scans through a path specification and replaces
- * it, in place, with a normalized version. A normalized version
- * is one in which all symlinks in the path are replaced with
- * their expanded form (except a symlink at the very end of the
- * path).
+ * This function scans through a path specification and replaces it, in
+ * place, with a normalized version. A normalized version is one in which
+ * all symlinks in the path are replaced with their expanded form (except
+ * a symlink at the very end of the path).
*
* Results:
- * The new 'nextCheckpoint' value, giving as far as we could
- * understand in the path.
+ * The new 'nextCheckpoint' value, giving as far as we could understand
+ * in the path.
*
* Side effects:
* The pathPtr string, is modified.
*
*---------------------------------------------------------------------------
*/
+
int
-TclpObjNormalizePath(interp, pathPtr, nextCheckpoint)
- Tcl_Interp *interp;
- Tcl_Obj *pathPtr;
- int nextCheckpoint;
+TclpObjNormalizePath(
+ Tcl_Interp *interp,
+ Tcl_Obj *pathPtr,
+ int nextCheckpoint)
{
char *currentPathEndPosition;
int pathLen;
@@ -1847,25 +1900,31 @@ TclpObjNormalizePath(interp, pathPtr, nextCheckpoint)
#ifndef NO_REALPATH
char normPath[MAXPATHLEN];
Tcl_DString ds;
- CONST char *nativePath;
+ CONST char *nativePath;
#endif
- /*
- * We add '1' here because if nextCheckpoint is zero we know
- * that '/' exists, and if it isn't zero, it must point at
- * a directory separator which we also know exists.
+
+ /*
+ * We add '1' here because if nextCheckpoint is zero we know that '/'
+ * exists, and if it isn't zero, it must point at a directory separator
+ * which we also know exists.
*/
+
currentPathEndPosition = path + nextCheckpoint;
if (*currentPathEndPosition == '/') {
currentPathEndPosition++;
}
#ifndef NO_REALPATH
- /* For speed, try to get the entire path in one go */
+ /*
+ * For speed, try to get the entire path in one go.
+ */
+
if (nextCheckpoint == 0 && haveRealpath) {
- char *lastDir = strrchr(currentPathEndPosition, '/');
+ char *lastDir = strrchr(currentPathEndPosition, '/');
+
if (lastDir != NULL) {
- nativePath = Tcl_UtfToExternalDString(NULL, path,
- lastDir - path, &ds);
+ nativePath = Tcl_UtfToExternalDString(NULL, path,
+ lastDir-path, &ds);
if (Realpath(nativePath, normPath) != NULL) {
if (*nativePath != '/' && *normPath == '/') {
/*
@@ -1880,89 +1939,136 @@ TclpObjNormalizePath(interp, pathPtr, nextCheckpoint)
Tcl_DStringFree(&ds);
}
}
- /* Else do it the slow way */
+
+ /*
+ * Else do it the slow way.
+ */
#endif
-
+
while (1) {
cur = *currentPathEndPosition;
if ((cur == '/') && (path != currentPathEndPosition)) {
- /* Reached directory separator */
+ /*
+ * Reached directory separator.
+ */
+
Tcl_DString ds;
CONST char *nativePath;
int accessOk;
- nativePath = Tcl_UtfToExternalDString(NULL, path,
+ nativePath = Tcl_UtfToExternalDString(NULL, path,
currentPathEndPosition - path, &ds);
accessOk = access(nativePath, F_OK);
Tcl_DStringFree(&ds);
+
if (accessOk != 0) {
- /* File doesn't exist */
+ /*
+ * File doesn't exist.
+ */
+
break;
}
- /* Update the acceptable point */
+
+ /*
+ * Update the acceptable point.
+ */
+
nextCheckpoint = currentPathEndPosition - path;
} else if (cur == 0) {
- /* Reached end of string */
+ /*
+ * Reached end of string.
+ */
+
break;
}
currentPathEndPosition++;
}
- /*
- * We should really now convert this to a canonical path. We do
- * that with 'realpath' if we have it available. Otherwise we could
- * step through every single path component, checking whether it is a
- * symlink, but that would be a lot of work, and most modern OSes
- * have 'realpath'.
+
+ /*
+ * We should really now convert this to a canonical path. We do that with
+ * 'realpath' if we have it available. Otherwise we could step through
+ * every single path component, checking whether it is a symlink, but that
+ * would be a lot of work, and most modern OSes have 'realpath'.
*/
+
#ifndef NO_REALPATH
if (haveRealpath) {
- /*
+ /*
* If we only had '/foo' or '/' then we never increment nextCheckpoint
- * and we don't need or want to go through 'Realpath'. Also, on some
+ * and we don't need or want to go through 'Realpath'. Also, on some
* platforms, passing an empty string to 'Realpath' will give us the
* normalized pwd, which is not what we want at all!
*/
- if (nextCheckpoint == 0) return 0;
-
+
+ if (nextCheckpoint == 0) {
+ return 0;
+ }
+
nativePath = Tcl_UtfToExternalDString(NULL, path, nextCheckpoint, &ds);
if (Realpath(nativePath, normPath) != NULL) {
int newNormLen;
- wholeStringOk:
+
+ wholeStringOk:
newNormLen = strlen(normPath);
if ((newNormLen == Tcl_DStringLength(&ds))
&& (strcmp(normPath, nativePath) == 0)) {
- /* String is unchanged */
+ /*
+ * String is unchanged.
+ */
+
Tcl_DStringFree(&ds);
- if (path[nextCheckpoint] != '\0') {
- nextCheckpoint++;
+
+ /*
+ * Enable this to have the native FS claim normalization of
+ * the whole path for existing files. That would permit the
+ * caller to declare normalization complete without calls to
+ * additional filesystems. Saving lots of calls is probably
+ * worth the extra access() time here. When no other FS's are
+ * registered though, things are less clear.
+ *
+ if (0 == access(normPath, F_OK)) {
+ return pathLen;
}
+ */
+
return nextCheckpoint;
}
-
- /*
- * Free up the native path and put in its place the
- * converted, normalized path.
+
+ /*
+ * Free up the native path and put in its place the converted,
+ * normalized path.
*/
+
Tcl_DStringFree(&ds);
Tcl_ExternalToUtfDString(NULL, normPath, (int) newNormLen, &ds);
-
+
if (path[nextCheckpoint] != '\0') {
- /* not at end, append remaining path */
+ /*
+ * Not at end, append remaining path.
+ */
+
int normLen = Tcl_DStringLength(&ds);
+
Tcl_DStringAppend(&ds, path + nextCheckpoint,
pathLen - nextCheckpoint);
- /*
- * We recognise up to and including the directory
- * separator.
- */
+
+ /*
+ * We recognise up to and including the directory separator.
+ */
+
nextCheckpoint = normLen + 1;
} else {
- /* We recognise the whole string */
+ /*
+ * We recognise the whole string.
+ */
+
nextCheckpoint = Tcl_DStringLength(&ds);
}
- /*
+
+ /*
* Overwrite with the normalized path.
*/
+
Tcl_SetStringObj(pathPtr, Tcl_DStringValue(&ds),
Tcl_DStringLength(&ds));
}
@@ -1972,3 +2078,118 @@ TclpObjNormalizePath(interp, pathPtr, nextCheckpoint)
return nextCheckpoint;
}
+
+#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetReadOnlyAttribute
+ *
+ * Gets the readonly attribute (user immutable flag) of a file.
+ *
+ * Results:
+ * Standard TCL result. Returns a new Tcl_Obj in attributePtrPtr if there
+ * is no error. The object will have ref count 0.
+ *
+ * Side effects:
+ * A new object is allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetReadOnlyAttribute(
+ Tcl_Interp *interp, /* The interp we are using for errors. */
+ int objIndex, /* The index of the attribute. */
+ Tcl_Obj *fileName, /* The name of the file (UTF-8). */
+ Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */
+{
+ Tcl_StatBuf statBuf;
+ int result;
+
+ result = TclpObjStat(fileName, &statBuf);
+
+ if (result != 0) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "could not read \"",
+ TclGetString(fileName), "\": ", Tcl_PosixError(interp),
+ NULL);
+ }
+ return TCL_ERROR;
+ }
+
+ *attributePtrPtr = Tcl_NewBooleanObj((statBuf.st_flags&UF_IMMUTABLE) != 0);
+
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SetReadOnlyAttribute
+ *
+ * Sets the readonly attribute (user immutable flag) of a file.
+ *
+ * Results:
+ * Standard TCL result.
+ *
+ * Side effects:
+ * The readonly attribute of the file is changed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+SetReadOnlyAttribute(
+ Tcl_Interp *interp, /* The interp we are using for errors. */
+ int objIndex, /* The index of the attribute. */
+ Tcl_Obj *fileName, /* The name of the file (UTF-8). */
+ Tcl_Obj *attributePtr) /* The attribute to set. */
+{
+ Tcl_StatBuf statBuf;
+ int result;
+ int readonly;
+ CONST char *native;
+
+ if (Tcl_GetBooleanFromObj(interp, attributePtr, &readonly) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ result = TclpObjStat(fileName, &statBuf);
+
+ if (result != 0) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "could not read \"",
+ TclGetString(fileName), "\": ", Tcl_PosixError(interp),
+ NULL);
+ }
+ return TCL_ERROR;
+ }
+
+ if (readonly) {
+ statBuf.st_flags |= UF_IMMUTABLE;
+ } else {
+ statBuf.st_flags &= ~UF_IMMUTABLE;
+ }
+
+ native = Tcl_FSGetNativePath(fileName);
+ result = chflags(native, statBuf.st_flags); /* INTL: Native. */
+ if (result != 0) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "could not set flags for file \"",
+ TclGetString(fileName), "\": ", Tcl_PosixError(interp),
+ NULL);
+ }
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+#endif /* defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE) */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixFile.c b/unix/tclUnixFile.c
index c0d81b1..2639d59 100644
--- a/unix/tclUnixFile.c
+++ b/unix/tclUnixFile.c
@@ -1,70 +1,59 @@
-/*
+/*
* tclUnixFile.c --
*
- * This file contains wrappers around UNIX file handling functions.
- * These wrappers mask differences between Windows and UNIX.
+ * This file contains wrappers around UNIX file handling functions.
+ * These wrappers mask differences between Windows and UNIX.
*
* Copyright (c) 1995-1998 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
-
-static int NativeMatchType(CONST char* nativeName, Tcl_GlobTypeData *types);
+#include "tclFileSystem.h"
+static int NativeMatchType(Tcl_Interp *interp, CONST char* nativeEntry,
+ CONST char* nativeName, Tcl_GlobTypeData *types);
/*
*---------------------------------------------------------------------------
*
* TclpFindExecutable --
*
- * This procedure computes the absolute path name of the current
+ * This function computes the absolute path name of the current
* application, given its argv[0] value.
*
* Results:
- * A dirty UTF string that is the path to the executable. At this
- * point we may not know the system encoding. Convert the native
- * string value to UTF using the default encoding. The assumption
- * is that we will still be able to parse the path given the path
- * name contains ASCII string and '/' chars do not conflict with
- * other UTF chars.
+ * None.
*
* Side effects:
- * The variable tclNativeExecutableName gets filled in with the file
- * name for the application, if we figured it out. If we couldn't
- * figure it out, tclNativeExecutableName is set to NULL.
+ * The computed path name is stored as a ProcessGlobalValue.
*
*---------------------------------------------------------------------------
*/
-char *
-TclpFindExecutable(argv0)
- CONST char *argv0; /* The value of the application's argv[0]
+void
+TclpFindExecutable(
+ CONST char *argv0) /* The value of the application's argv[0]
* (native). */
{
CONST char *name, *p;
Tcl_StatBuf statBuf;
- int length;
- Tcl_DString buffer, nameString;
+ Tcl_DString buffer, nameString, cwd, utfName;
+ Tcl_Encoding encoding;
if (argv0 == NULL) {
- return NULL;
+ return;
}
- if (tclNativeExecutableName != NULL) {
- return tclNativeExecutableName;
- }
-
Tcl_DStringInit(&buffer);
name = argv0;
for (p = name; *p != '\0'; p++) {
if (*p == '/') {
/*
- * The name contains a slash, so use the name directly
- * without doing a path search.
+ * The name contains a slash, so use the name directly without
+ * doing a path search.
*/
goto gotName;
@@ -74,8 +63,8 @@ TclpFindExecutable(argv0)
p = getenv("PATH"); /* INTL: Native. */
if (p == NULL) {
/*
- * There's no PATH environment variable; use the default that
- * is used by sh.
+ * There's no PATH environment variable; use the default that is used
+ * by sh.
*/
p = ":/bin:/usr/bin";
@@ -88,13 +77,12 @@ TclpFindExecutable(argv0)
}
/*
- * Search through all the directories named in the PATH variable
- * to see if argv[0] is in one of them. If so, use that file
- * name.
+ * Search through all the directories named in the PATH variable to see if
+ * argv[0] is in one of them. If so, use that file name.
*/
while (1) {
- while (isspace(UCHAR(*p))) { /* INTL: BUG */
+ while (TclIsSpaceProc(*p)) {
p++;
}
name = p;
@@ -129,52 +117,63 @@ TclpFindExecutable(argv0)
p++;
}
}
+ TclSetObjNameOfExecutable(Tcl_NewObj(), NULL);
goto done;
/*
- * If the name starts with "/" then just copy it to tclExecutableName.
+ * If the name starts with "/" then just store it
*/
-gotName:
+ gotName:
#ifdef DJGPP
- if (name[1] == ':') {
+ if (name[1] == ':')
#else
- if (name[0] == '/') {
+ if (name[0] == '/')
#endif
- Tcl_ExternalToUtfDString(NULL, name, -1, &nameString);
- tclNativeExecutableName = (char *)
- ckalloc((unsigned) (Tcl_DStringLength(&nameString) + 1));
- strcpy(tclNativeExecutableName, Tcl_DStringValue(&nameString));
- Tcl_DStringFree(&nameString);
+ {
+ encoding = Tcl_GetEncoding(NULL, NULL);
+ Tcl_ExternalToUtfDString(encoding, name, -1, &utfName);
+ TclSetObjNameOfExecutable(
+ Tcl_NewStringObj(Tcl_DStringValue(&utfName), -1), encoding);
+ Tcl_DStringFree(&utfName);
goto done;
}
/*
- * The name is relative to the current working directory. First
- * strip off a leading "./", if any, then add the full path name of
- * the current working directory.
+ * The name is relative to the current working directory. First strip off
+ * a leading "./", if any, then add the full path name of the current
+ * working directory.
*/
if ((name[0] == '.') && (name[1] == '/')) {
name += 2;
}
- Tcl_ExternalToUtfDString(NULL, name, -1, &nameString);
+ Tcl_DStringInit(&nameString);
+ Tcl_DStringAppend(&nameString, name, -1);
+
+ TclpGetCwd(NULL, &cwd);
Tcl_DStringFree(&buffer);
- TclpGetCwd(NULL, &buffer);
-
- length = Tcl_DStringLength(&buffer) + Tcl_DStringLength(&nameString) + 2;
- tclNativeExecutableName = (char *) ckalloc((unsigned) length);
- strcpy(tclNativeExecutableName, Tcl_DStringValue(&buffer));
- tclNativeExecutableName[Tcl_DStringLength(&buffer)] = '/';
- strcpy(tclNativeExecutableName + Tcl_DStringLength(&buffer) + 1,
- Tcl_DStringValue(&nameString));
+ Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&cwd),
+ Tcl_DStringLength(&cwd), &buffer);
+ if (Tcl_DStringValue(&cwd)[Tcl_DStringLength(&cwd) -1] != '/') {
+ Tcl_DStringAppend(&buffer, "/", 1);
+ }
+ Tcl_DStringFree(&cwd);
+ Tcl_DStringAppend(&buffer, Tcl_DStringValue(&nameString),
+ Tcl_DStringLength(&nameString));
Tcl_DStringFree(&nameString);
-
-done:
+
+ encoding = Tcl_GetEncoding(NULL, NULL);
+ Tcl_ExternalToUtfDString(encoding, Tcl_DStringValue(&buffer), -1,
+ &utfName);
+ TclSetObjNameOfExecutable(
+ Tcl_NewStringObj(Tcl_DStringValue(&utfName), -1), encoding);
+ Tcl_DStringFree(&utfName);
+
+ done:
Tcl_DStringFree(&buffer);
- return tclNativeExecutableName;
}
/*
@@ -182,80 +181,101 @@ done:
*
* TclpMatchInDirectory --
*
- * This routine is used by the globbing code to search a
- * directory for all files which match a given pattern.
+ * This routine is used by the globbing code to search a directory for
+ * all files which match a given pattern.
*
- * Results:
- * The return value is a standard Tcl result indicating whether an
- * error occurred in globbing. Errors are left in interp, good
- * results are lappended to resultPtr (which must be a valid object)
+ * Results:
+ * The return value is a standard Tcl result indicating whether an error
+ * occurred in globbing. Errors are left in interp, good results are
+ * [lappend]ed to resultPtr (which must be a valid object).
*
* Side effects:
* None.
*
- *---------------------------------------------------------------------- */
+ *----------------------------------------------------------------------
+ */
int
-TclpMatchInDirectory(interp, resultPtr, pathPtr, pattern, types)
- Tcl_Interp *interp; /* Interpreter to receive errors. */
- Tcl_Obj *resultPtr; /* List object to lappend results. */
- Tcl_Obj *pathPtr; /* Contains path to directory to search. */
- CONST char *pattern; /* Pattern to match against. */
- Tcl_GlobTypeData *types; /* Object containing list of acceptable types.
+TclpMatchInDirectory(
+ Tcl_Interp *interp, /* Interpreter to receive errors. */
+ Tcl_Obj *resultPtr, /* List object to lappend results. */
+ Tcl_Obj *pathPtr, /* Contains path to directory to search. */
+ CONST char *pattern, /* Pattern to match against. */
+ Tcl_GlobTypeData *types) /* Object containing list of acceptable types.
* May be NULL. In particular the directory
* flag is very important. */
{
CONST char *native;
Tcl_Obj *fileNamePtr;
+ int matchResult = 0;
+
+ if (types != NULL && types->type == TCL_GLOB_TYPE_MOUNT) {
+ /*
+ * The native filesystem never adds mounts.
+ */
+
+ return TCL_OK;
+ }
fileNamePtr = Tcl_FSGetTranslatedPath(interp, pathPtr);
if (fileNamePtr == NULL) {
return TCL_ERROR;
}
-
+
if (pattern == NULL || (*pattern == '\0')) {
- /* Match a file directly */
+ /*
+ * Match a file directly.
+ */
+ Tcl_Obj *tailPtr;
+ CONST char *nativeTail;
+
native = (CONST char*) Tcl_FSGetNativePath(pathPtr);
- if (NativeMatchType(native, types)) {
+ tailPtr = TclPathPart(interp, pathPtr, TCL_PATH_TAIL);
+ nativeTail = (CONST char*) Tcl_FSGetNativePath(tailPtr);
+ matchResult = NativeMatchType(interp, native, nativeTail, types);
+ if (matchResult == 1) {
Tcl_ListObjAppendElement(interp, resultPtr, pathPtr);
}
+ Tcl_DecrRefCount(tailPtr);
Tcl_DecrRefCount(fileNamePtr);
- return TCL_OK;
} else {
DIR *d;
Tcl_DirEntry *entryPtr;
CONST char *dirName;
int dirLength;
- int matchHidden;
+ int matchHidden, matchHiddenPat;
int nativeDirLen;
Tcl_StatBuf statBuf;
- Tcl_DString ds; /* native encoding of dir */
- Tcl_DString dsOrig; /* utf-8 encoding of dir */
+ Tcl_DString ds; /* native encoding of dir */
+ Tcl_DString dsOrig; /* utf-8 encoding of dir */
Tcl_DStringInit(&dsOrig);
dirName = Tcl_GetStringFromObj(fileNamePtr, &dirLength);
Tcl_DStringAppend(&dsOrig, dirName, dirLength);
-
+
/*
* Make sure that the directory part of the name really is a
- * directory. If the directory name is "", use the name "."
- * instead, because some UNIX systems don't treat "" like "."
- * automatically. Keep the "" for use in generating file names,
- * otherwise "glob foo.c" would return "./foo.c".
+ * directory. If the directory name is "", use the name "." instead,
+ * because some UNIX systems don't treat "" like "." automatically.
+ * Keep the "" for use in generating file names, otherwise "glob
+ * foo.c" would return "./foo.c".
*/
if (dirLength == 0) {
dirName = ".";
} else {
dirName = Tcl_DStringValue(&dsOrig);
- /* Make sure we have a trailing directory delimiter */
+
+ /*
+ * Make sure we have a trailing directory delimiter.
+ */
+
if (dirName[dirLength-1] != '/') {
dirName = Tcl_DStringAppend(&dsOrig, "/", 1);
dirLength++;
}
}
- Tcl_DecrRefCount(fileNamePtr);
-
+
/*
* Now open the directory for reading and iterate over the contents.
*/
@@ -266,17 +286,21 @@ TclpMatchInDirectory(interp, resultPtr, pathPtr, pattern, types)
|| !S_ISDIR(statBuf.st_mode)) {
Tcl_DStringFree(&dsOrig);
Tcl_DStringFree(&ds);
+ Tcl_DecrRefCount(fileNamePtr);
return TCL_OK;
}
d = opendir(native); /* INTL: Native. */
if (d == NULL) {
Tcl_DStringFree(&ds);
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "couldn't read directory \"",
- Tcl_DStringValue(&dsOrig), "\": ",
- Tcl_PosixError(interp), (char *) NULL);
+ if (interp != NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "couldn't read directory \"",
+ Tcl_DStringValue(&dsOrig), "\": ",
+ Tcl_PosixError(interp), (char *) NULL);
+ }
Tcl_DStringFree(&dsOrig);
+ Tcl_DecrRefCount(fileNamePtr);
return TCL_ERROR;
}
@@ -285,92 +309,135 @@ TclpMatchInDirectory(interp, resultPtr, pathPtr, pattern, types)
/*
* Check to see if -type or the pattern requests hidden files.
*/
- matchHidden = ((types && (types->perm & TCL_GLOB_PERM_HIDDEN)) ||
- ((pattern[0] == '.')
- || ((pattern[0] == '\\') && (pattern[1] == '.'))));
- while ((entryPtr = TclOSreaddir(d)) != NULL) { /* INTL: Native. */
+ matchHiddenPat = (pattern[0] == '.')
+ || ((pattern[0] == '\\') && (pattern[1] == '.'));
+ matchHidden = matchHiddenPat
+ || (types && (types->perm & TCL_GLOB_PERM_HIDDEN));
+ while ((entryPtr = TclOSreaddir(d)) != NULL) { /* INTL: Native. */
Tcl_DString utfDs;
CONST char *utfname;
- /*
- * Skip this file if it doesn't agree with the hidden
- * parameters requested by the user (via -type or pattern).
+ /*
+ * Skip this file if it doesn't agree with the hidden parameters
+ * requested by the user (via -type or pattern).
*/
+
if (*entryPtr->d_name == '.') {
if (!matchHidden) continue;
} else {
+#ifdef MAC_OSX_TCL
+ if (matchHiddenPat) continue;
+ /* Also need to check HFS hidden flag in TclMacOSXMatchType. */
+#else
if (matchHidden) continue;
+#endif
}
/*
* Now check to see if the file matches, according to both type
- * and pattern. If so, add the file to the result.
+ * and pattern. If so, add the file to the result.
*/
- utfname = Tcl_ExternalToUtfDString(NULL, entryPtr->d_name,
- -1, &utfDs);
+ utfname = Tcl_ExternalToUtfDString(NULL, entryPtr->d_name, -1,
+ &utfDs);
if (Tcl_StringCaseMatch(utfname, pattern, 0)) {
int typeOk = 1;
if (types != NULL) {
Tcl_DStringSetLength(&ds, nativeDirLen);
native = Tcl_DStringAppend(&ds, entryPtr->d_name, -1);
- typeOk = NativeMatchType(native, types);
+ matchResult = NativeMatchType(interp, native,
+ entryPtr->d_name, types);
+ typeOk = (matchResult == 1);
}
if (typeOk) {
- Tcl_ListObjAppendElement(interp, resultPtr,
+ Tcl_ListObjAppendElement(interp, resultPtr,
TclNewFSPathObj(pathPtr, utfname,
- Tcl_DStringLength(&utfDs)));
+ Tcl_DStringLength(&utfDs)));
}
}
Tcl_DStringFree(&utfDs);
+ if (matchResult < 0) {
+ break;
+ }
}
closedir(d);
Tcl_DStringFree(&ds);
Tcl_DStringFree(&dsOrig);
+ Tcl_DecrRefCount(fileNamePtr);
+ }
+ if (matchResult < 0) {
+ return TCL_ERROR;
+ } else {
return TCL_OK;
}
}
-static int
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NativeMatchType --
+ *
+ * This routine is used by the globbing code to check if a file
+ * matches a given type description.
+ *
+ * Results:
+ * The return value is 1, 0 or -1 indicating whether the file
+ * matches the given criteria, does not match them, or an error
+ * occurred (in wich case an error is left in interp).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
NativeMatchType(
- CONST char* nativeEntry, /* Native path to check */
- Tcl_GlobTypeData *types) /* Type description to match against */
+ Tcl_Interp *interp, /* Interpreter to receive errors. */
+ CONST char *nativeEntry, /* Native path to check. */
+ CONST char *nativeName, /* Native filename to check. */
+ Tcl_GlobTypeData *types) /* Type description to match against. */
{
Tcl_StatBuf buf;
if (types == NULL) {
- /*
- * Simply check for the file's existence, but do it
- * with lstat, in case it is a link to a file which
- * doesn't exist (since that case would not show up
- * if we used 'access' or 'stat')
+ /*
+ * Simply check for the file's existence, but do it with lstat, in
+ * case it is a link to a file which doesn't exist (since that case
+ * would not show up if we used 'access' or 'stat')
*/
+
if (TclOSlstat(nativeEntry, &buf) != 0) {
return 0;
}
} else {
if (types->perm != 0) {
if (TclOSstat(nativeEntry, &buf) != 0) {
- /*
- * Either the file has disappeared between the
- * 'readdir' call and the 'stat' call, or
- * the file is a link to a file which doesn't
- * exist (which we could ascertain with
- * lstat), or there is some other strange
- * problem. In all these cases, we define this
- * to mean the file does not match any defined
- * permission, and therefore it is not
- * added to the list of files to return.
+ /*
+ * Either the file has disappeared between the 'readdir' call
+ * and the 'stat' call, or the file is a link to a file which
+ * doesn't exist (which we could ascertain with lstat), or
+ * there is some other strange problem. In all these cases, we
+ * define this to mean the file does not match any defined
+ * permission, and therefore it is not added to the list of
+ * files to return.
*/
+
return 0;
}
-
- /*
- * readonly means that there are NO write permissions
- * (even for user), but execute is OK for anybody
+
+ /*
+ * readonly means that there are NO write permissions (even for
+ * user), but execute is OK for anybody OR that the user immutable
+ * flag is set (where supported).
*/
+
if (((types->perm & TCL_GLOB_PERM_RONLY) &&
+#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
+ !(buf.st_flags & UF_IMMUTABLE) &&
+#endif
(buf.st_mode & (S_IWOTH|S_IWGRP|S_IWUSR))) ||
((types->perm & TCL_GLOB_PERM_R) &&
(access(nativeEntry, R_OK) != 0)) ||
@@ -378,20 +445,27 @@ NativeMatchType(
(access(nativeEntry, W_OK) != 0)) ||
((types->perm & TCL_GLOB_PERM_X) &&
(access(nativeEntry, X_OK) != 0))
+#ifndef MAC_OSX_TCL
+ || ((types->perm & TCL_GLOB_PERM_HIDDEN) &&
+ (*nativeName != '.'))
+#endif
) {
return 0;
}
}
if (types->type != 0) {
if (types->perm == 0) {
- /* We haven't yet done a stat on the file */
+ /*
+ * We haven't yet done a stat on the file.
+ */
+
if (TclOSstat(nativeEntry, &buf) != 0) {
- /*
- * Posix error occurred. The only ok
- * case is if this is a link to a nonexistent
- * file, and the user did 'glob -l'. So
- * we check that here:
+ /*
+ * Posix error occurred. The only ok case is if this is a
+ * link to a nonexistent file, and the user did 'glob -l'.
+ * So we check that here:
*/
+
if (types->type & TCL_GLOB_TYPE_LINK) {
if (TclOSlstat(nativeEntry, &buf) == 0) {
if (S_ISLNK(buf.st_mode)) {
@@ -402,32 +476,29 @@ NativeMatchType(
return 0;
}
}
+
/*
* In order bcdpfls as in 'find -t'
*/
- if (
- ((types->type & TCL_GLOB_TYPE_BLOCK) &&
- S_ISBLK(buf.st_mode)) ||
- ((types->type & TCL_GLOB_TYPE_CHAR) &&
- S_ISCHR(buf.st_mode)) ||
- ((types->type & TCL_GLOB_TYPE_DIR) &&
- S_ISDIR(buf.st_mode)) ||
- ((types->type & TCL_GLOB_TYPE_PIPE) &&
- S_ISFIFO(buf.st_mode)) ||
- ((types->type & TCL_GLOB_TYPE_FILE) &&
- S_ISREG(buf.st_mode))
+
+ if (((types->type & TCL_GLOB_TYPE_BLOCK)&& S_ISBLK(buf.st_mode)) ||
+ ((types->type & TCL_GLOB_TYPE_CHAR) && S_ISCHR(buf.st_mode)) ||
+ ((types->type & TCL_GLOB_TYPE_DIR) && S_ISDIR(buf.st_mode)) ||
+ ((types->type & TCL_GLOB_TYPE_PIPE) && S_ISFIFO(buf.st_mode))||
+ ((types->type & TCL_GLOB_TYPE_FILE) && S_ISREG(buf.st_mode))
#ifdef S_ISSOCK
- || ((types->type & TCL_GLOB_TYPE_SOCK) &&
- S_ISSOCK(buf.st_mode))
+ ||((types->type & TCL_GLOB_TYPE_SOCK) && S_ISSOCK(buf.st_mode))
#endif /* S_ISSOCK */
) {
- /* Do nothing -- this file is ok */
+ /*
+ * Do nothing - this file is ok.
+ */
} else {
#ifdef S_ISLNK
if (types->type & TCL_GLOB_TYPE_LINK) {
if (TclOSlstat(nativeEntry, &buf) == 0) {
if (S_ISLNK(buf.st_mode)) {
- return 1;
+ goto filetypeOK;
}
}
}
@@ -435,6 +506,29 @@ NativeMatchType(
return 0;
}
}
+ filetypeOK: ;
+#ifdef MAC_OSX_TCL
+ if (types->macType != NULL || types->macCreator != NULL ||
+ (types->perm & TCL_GLOB_PERM_HIDDEN)) {
+ int matchResult;
+
+ if (types->perm == 0 && types->type == 0) {
+ /*
+ * We haven't yet done a stat on the file.
+ */
+
+ if (TclOSstat(nativeEntry, &buf) != 0) {
+ return 0;
+ }
+ }
+
+ matchResult = TclMacOSXMatchType(interp, nativeEntry, nativeName,
+ &buf, types);
+ if (matchResult != 1) {
+ return matchResult;
+ }
+ }
+#endif
}
return 1;
}
@@ -444,15 +538,15 @@ NativeMatchType(
*
* TclpGetUserHome --
*
- * This function takes the specified user name and finds their
- * home directory.
+ * This function takes the specified user name and finds their home
+ * directory.
*
* Results:
* The result is a pointer to a string specifying the user's home
* directory, or NULL if the user's home directory could not be
- * determined. Storage for the result string is allocated in
- * bufferPtr; the caller must call Tcl_DStringFree() when the result
- * is no longer needed.
+ * determined. Storage for the result string is allocated in bufferPtr;
+ * the caller must call Tcl_DStringFree() when the result is no longer
+ * needed.
*
* Side effects:
* None.
@@ -461,25 +555,23 @@ NativeMatchType(
*/
char *
-TclpGetUserHome(name, bufferPtr)
- CONST char *name; /* User name for desired home directory. */
- Tcl_DString *bufferPtr; /* Uninitialized or free DString filled
- * with name of user's home directory. */
+TclpGetUserHome(
+ CONST char *name, /* User name for desired home directory. */
+ Tcl_DString *bufferPtr) /* Uninitialized or free DString filled with
+ * name of user's home directory. */
{
struct passwd *pwPtr;
Tcl_DString ds;
CONST char *native;
native = Tcl_UtfToExternalDString(NULL, name, -1, &ds);
- pwPtr = getpwnam(native); /* INTL: Native. */
+ pwPtr = TclpGetPwNam(native); /* INTL: Native. */
Tcl_DStringFree(&ds);
-
+
if (pwPtr == NULL) {
- endpwent();
return NULL;
}
Tcl_ExternalToUtfDString(NULL, pwPtr->pw_dir, -1, bufferPtr);
- endpwent();
return Tcl_DStringValue(bufferPtr);
}
@@ -499,10 +591,10 @@ TclpGetUserHome(name, bufferPtr)
*---------------------------------------------------------------------------
*/
-int
-TclpObjAccess(pathPtr, mode)
- Tcl_Obj *pathPtr; /* Path of file to access */
- int mode; /* Permission setting. */
+int
+TclpObjAccess(
+ Tcl_Obj *pathPtr, /* Path of file to access */
+ int mode) /* Permission setting. */
{
CONST char *path = Tcl_FSGetNativePath(pathPtr);
if (path == NULL) {
@@ -523,14 +615,14 @@ TclpObjAccess(pathPtr, mode)
* See chdir() documentation.
*
* Side effects:
- * See chdir() documentation.
+ * See chdir() documentation.
*
*---------------------------------------------------------------------------
*/
-int
-TclpObjChdir(pathPtr)
- Tcl_Obj *pathPtr; /* Path to new working directory */
+int
+TclpObjChdir(
+ Tcl_Obj *pathPtr) /* Path to new working directory */
{
CONST char *path = Tcl_FSGetNativePath(pathPtr);
if (path == NULL) {
@@ -556,10 +648,10 @@ TclpObjChdir(pathPtr)
*----------------------------------------------------------------------
*/
-int
-TclpObjLstat(pathPtr, bufPtr)
- Tcl_Obj *pathPtr; /* Path of file to stat */
- Tcl_StatBuf *bufPtr; /* Filled with results of stat call. */
+int
+TclpObjLstat(
+ Tcl_Obj *pathPtr, /* Path of file to stat */
+ Tcl_StatBuf *bufPtr) /* Filled with results of stat call. */
{
return TclOSlstat(Tcl_FSGetNativePath(pathPtr), bufPtr);
}
@@ -567,17 +659,17 @@ TclpObjLstat(pathPtr, bufPtr)
/*
*---------------------------------------------------------------------------
*
- * TclpObjGetCwd --
+ * TclpGetNativeCwd --
*
* This function replaces the library version of getcwd().
*
* Results:
- * The result is a pointer to a string specifying the current
- * directory, or NULL if the current directory could not be
- * determined. If NULL is returned, an error message is left in the
- * interp's result. Storage for the result string is allocated in
- * bufferPtr; the caller must call Tcl_DStringFree() when the result
- * is no longer needed.
+ * The input and output are filesystem paths in native form. The result
+ * is either the given clientData, if the working directory hasn't
+ * changed, or a new clientData (owned by our caller), giving the new
+ * native path, or NULL if the current directory could not be determined.
+ * If NULL is returned, the caller can examine the standard posix error
+ * codes to determine the cause of the problem.
*
* Side effects:
* None.
@@ -585,39 +677,73 @@ TclpObjLstat(pathPtr, bufPtr)
*----------------------------------------------------------------------
*/
-Tcl_Obj*
-TclpObjGetCwd(interp)
- Tcl_Interp *interp;
+ClientData
+TclpGetNativeCwd(
+ ClientData clientData)
{
- Tcl_DString ds;
- if (TclpGetCwd(interp, &ds) != NULL) {
- Tcl_Obj *cwdPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1);
- Tcl_IncrRefCount(cwdPtr);
- Tcl_DStringFree(&ds);
- return cwdPtr;
- } else {
+ char buffer[MAXPATHLEN+1];
+
+#ifdef USEGETWD
+ if (getwd(buffer) == NULL) /* INTL: Native. */
+#else
+ if (getcwd(buffer, MAXPATHLEN+1) == NULL) /* INTL: Native. */
+#endif
+ {
return NULL;
}
+ if ((clientData != NULL) && strcmp(buffer, (CONST char*)clientData) == 0) {
+ /*
+ * No change to pwd.
+ */
+
+ return clientData;
+ } else {
+ char *newCd = (char *) ckalloc((unsigned) (strlen(buffer) + 1));
+ strcpy(newCd, buffer);
+ return (ClientData) newCd;
+ }
}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpGetCwd --
+ *
+ * This function replaces the library version of getcwd(). (Obsolete
+ * function, only retained for old extensions which may call it
+ * directly).
+ *
+ * Results:
+ * The result is a pointer to a string specifying the current directory,
+ * or NULL if the current directory could not be determined. If NULL is
+ * returned, an error message is left in the interp's result. Storage for
+ * the result string is allocated in bufferPtr; the caller must call
+ * Tcl_DStringFree() when the result is no longer needed.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
-/* Older string based version */
CONST char *
-TclpGetCwd(interp, bufferPtr)
- Tcl_Interp *interp; /* If non-NULL, used for error reporting. */
- Tcl_DString *bufferPtr; /* Uninitialized or free DString filled
- * with name of current directory. */
+TclpGetCwd(
+ Tcl_Interp *interp, /* If non-NULL, used for error reporting. */
+ Tcl_DString *bufferPtr) /* Uninitialized or free DString filled with
+ * name of current directory. */
{
char buffer[MAXPATHLEN+1];
#ifdef USEGETWD
- if (getwd(buffer) == NULL) { /* INTL: Native. */
+ if (getwd(buffer) == NULL) /* INTL: Native. */
#else
- if (getcwd(buffer, MAXPATHLEN + 1) == NULL) { /* INTL: Native. */
+ if (getcwd(buffer, MAXPATHLEN+1) == NULL) /* INTL: Native. */
#endif
+ {
if (interp != NULL) {
Tcl_AppendResult(interp,
"error getting working directory name: ",
- Tcl_PosixError(interp), (char *) NULL);
+ Tcl_PosixError(interp), NULL);
}
return NULL;
}
@@ -632,11 +758,11 @@ TclpGetCwd(interp, bufferPtr)
* This function replaces the library version of readlink().
*
* Results:
- * The result is a pointer to a string specifying the contents
- * of the symbolic link given by 'path', or NULL if the symbolic
- * link could not be read. Storage for the result string is
- * allocated in bufferPtr; the caller must call Tcl_DStringFree()
- * when the result is no longer needed.
+ * The result is a pointer to a string specifying the contents of the
+ * symbolic link given by 'path', or NULL if the symbolic link could not
+ * be read. Storage for the result string is allocated in bufferPtr; the
+ * caller must call Tcl_DStringFree() when the result is no longer
+ * needed.
*
* Side effects:
* See readlink() documentation.
@@ -645,10 +771,10 @@ TclpGetCwd(interp, bufferPtr)
*/
char *
-TclpReadlink(path, linkPtr)
- CONST char *path; /* Path of file to readlink (UTF-8). */
- Tcl_DString *linkPtr; /* Uninitialized or free DString filled
- * with contents of link (UTF-8). */
+TclpReadlink(
+ CONST char *path, /* Path of file to readlink (UTF-8). */
+ Tcl_DString *linkPtr) /* Uninitialized or free DString filled with
+ * contents of link (UTF-8). */
{
#ifndef DJGPP
char link[MAXPATHLEN];
@@ -659,7 +785,7 @@ TclpReadlink(path, linkPtr)
native = Tcl_UtfToExternalDString(NULL, path, -1, &ds);
length = readlink(native, link, sizeof(link)); /* INTL: Native. */
Tcl_DStringFree(&ds);
-
+
if (length < 0) {
return NULL;
}
@@ -687,10 +813,10 @@ TclpReadlink(path, linkPtr)
*----------------------------------------------------------------------
*/
-int
-TclpObjStat(pathPtr, bufPtr)
- Tcl_Obj *pathPtr; /* Path of file to stat */
- Tcl_StatBuf *bufPtr; /* Filled with results of stat call. */
+int
+TclpObjStat(
+ Tcl_Obj *pathPtr, /* Path of file to stat */
+ Tcl_StatBuf *bufPtr) /* Filled with results of stat call. */
{
CONST char *path = Tcl_FSGetNativePath(pathPtr);
if (path == NULL) {
@@ -700,67 +826,142 @@ TclpObjStat(pathPtr, bufPtr)
}
}
-
#ifdef S_IFLNK
-Tcl_Obj*
-TclpObjLink(pathPtr, toPtr, linkAction)
- Tcl_Obj *pathPtr;
- Tcl_Obj *toPtr;
- int linkAction;
+Tcl_Obj*
+TclpObjLink(
+ Tcl_Obj *pathPtr,
+ Tcl_Obj *toPtr,
+ int linkAction)
{
if (toPtr != NULL) {
CONST char *src = Tcl_FSGetNativePath(pathPtr);
- CONST char *target = Tcl_FSGetNativePath(toPtr);
-
- if (src == NULL || target == NULL) {
+ CONST char *target = NULL;
+
+ if (src == NULL) {
return NULL;
}
+
+ /*
+ * If we're making a symbolic link and the path is relative, then we
+ * must check whether it exists _relative_ to the directory in which
+ * the src is found (not relative to the current cwd which is just not
+ * relevant in this case).
+ *
+ * If we're making a hard link, then a relative path is just converted
+ * to absolute relative to the cwd.
+ */
+
+ if ((linkAction & TCL_CREATE_SYMBOLIC_LINK)
+ && (Tcl_FSGetPathType(toPtr) == TCL_PATH_RELATIVE)) {
+ Tcl_Obj *dirPtr, *absPtr;
+
+ dirPtr = TclPathPart(NULL, pathPtr, TCL_PATH_DIRNAME);
+ if (dirPtr == NULL) {
+ return NULL;
+ }
+ absPtr = Tcl_FSJoinToPath(dirPtr, 1, &toPtr);
+ Tcl_IncrRefCount(absPtr);
+ if (Tcl_FSAccess(absPtr, F_OK) == -1) {
+ Tcl_DecrRefCount(absPtr);
+ Tcl_DecrRefCount(dirPtr);
+
+ /*
+ * Target doesn't exist.
+ */
+
+ errno = ENOENT;
+ return NULL;
+ }
+
+ /*
+ * Target exists; we'll construct the relative path we want below.
+ */
+
+ Tcl_DecrRefCount(absPtr);
+ Tcl_DecrRefCount(dirPtr);
+ } else {
+ target = Tcl_FSGetNativePath(toPtr);
+ if (target == NULL) {
+ return NULL;
+ }
+ if (access(target, F_OK) == -1) {
+ /*
+ * Target doesn't exist.
+ */
+
+ errno = ENOENT;
+ return NULL;
+ }
+ }
+
if (access(src, F_OK) != -1) {
- /* src exists */
+ /*
+ * Src exists.
+ */
+
errno = EEXIST;
return NULL;
}
- if (access(target, F_OK) == -1) {
- /* target doesn't exist */
- errno = ENOENT;
- return NULL;
- }
- /*
- * Check symbolic link flag first, since we prefer to
- * create these.
+
+ /*
+ * Check symbolic link flag first, since we prefer to create these.
*/
+
if (linkAction & TCL_CREATE_SYMBOLIC_LINK) {
- if (symlink(target, src) != 0) return NULL;
+ int targetLen;
+ Tcl_DString ds;
+ Tcl_Obj *transPtr;
+
+ /*
+ * Now we don't want to link to the absolute, normalized path.
+ * Relative links are quite acceptable (but links to ~user are not
+ * -- these must be expanded first).
+ */
+
+ transPtr = Tcl_FSGetTranslatedPath(NULL, toPtr);
+ if (transPtr == NULL) {
+ return NULL;
+ }
+ target = Tcl_GetStringFromObj(transPtr, &targetLen);
+ target = Tcl_UtfToExternalDString(NULL, target, targetLen, &ds);
+ Tcl_DecrRefCount(transPtr);
+
+ if (symlink(target, src) != 0) {
+ toPtr = NULL;
+ }
+ Tcl_DStringFree(&ds);
} else if (linkAction & TCL_CREATE_HARD_LINK) {
- if (link(target, src) != 0) return NULL;
+ if (link(target, src) != 0) {
+ return NULL;
+ }
} else {
errno = ENODEV;
return NULL;
}
return toPtr;
} else {
- Tcl_Obj* linkPtr = NULL;
+ Tcl_Obj *linkPtr = NULL;
char link[MAXPATHLEN];
int length;
Tcl_DString ds;
Tcl_Obj *transPtr;
-
+
transPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
if (transPtr == NULL) {
return NULL;
}
Tcl_DecrRefCount(transPtr);
-
+
length = readlink(Tcl_FSGetNativePath(pathPtr), link, sizeof(link));
if (length < 0) {
return NULL;
}
Tcl_ExternalToUtfDString(NULL, link, length, &ds);
- linkPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds),
- Tcl_DStringLength(&ds));
+ linkPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds),
+ Tcl_DStringLength(&ds));
Tcl_DStringFree(&ds);
if (linkPtr != NULL) {
Tcl_IncrRefCount(linkPtr);
@@ -768,39 +969,181 @@ TclpObjLink(pathPtr, toPtr, linkAction)
return linkPtr;
}
}
-
-#endif
-
+#endif /* S_IFLNK */
/*
*---------------------------------------------------------------------------
*
* TclpFilesystemPathType --
*
- * This function is part of the native filesystem support, and
- * returns the path type of the given path. Right now it simply
- * returns NULL. In the future it could return specific path
- * types, like 'nfs', 'samba', 'FAT32', etc.
+ * This function is part of the native filesystem support, and returns
+ * the path type of the given path. Right now it simply returns NULL. In
+ * the future it could return specific path types, like 'nfs', 'samba',
+ * 'FAT32', etc.
*
* Results:
- * NULL at present.
+ * NULL at present.
*
* Side effects:
* None.
*
*---------------------------------------------------------------------------
*/
-Tcl_Obj*
-TclpFilesystemPathType(pathObjPtr)
- Tcl_Obj* pathObjPtr;
+
+Tcl_Obj *
+TclpFilesystemPathType(
+ Tcl_Obj *pathPtr)
{
- /* All native paths are of the same type */
+ /*
+ * All native paths are of the same type.
+ */
+
return NULL;
}
/*
*---------------------------------------------------------------------------
*
+ * TclpNativeToNormalized --
+ *
+ * Convert native format to a normalized path object, with refCount of
+ * zero.
+ *
+ * Currently assumes all native paths are actually normalized already, so
+ * if the path given is not normalized this will actually just convert to
+ * a valid string path, but not necessarily a normalized one.
+ *
+ * Results:
+ * A valid normalized path.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclpNativeToNormalized(
+ ClientData clientData)
+{
+ Tcl_DString ds;
+ Tcl_Obj *objPtr;
+ int len;
+
+ CONST char *copy;
+ Tcl_ExternalToUtfDString(NULL, (CONST char*)clientData, -1, &ds);
+
+ copy = Tcl_DStringValue(&ds);
+ len = Tcl_DStringLength(&ds);
+
+ objPtr = Tcl_NewStringObj(copy,len);
+ Tcl_DStringFree(&ds);
+
+ return objPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclNativeCreateNativeRep --
+ *
+ * Create a native representation for the given path.
+ *
+ * Results:
+ * The nativePath representation.
+ *
+ * Side effects:
+ * Memory will be allocated. The path may need to be normalized.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+ClientData
+TclNativeCreateNativeRep(
+ Tcl_Obj *pathPtr)
+{
+ char *nativePathPtr;
+ Tcl_DString ds;
+ Tcl_Obj *validPathPtr;
+ int len;
+ char *str;
+
+ if (TclFSCwdIsNative()) {
+ /*
+ * The cwd is native, which means we can use the translated path
+ * without worrying about normalization (this will also usually be
+ * shorter so the utf-to-external conversion will be somewhat faster).
+ */
+
+ validPathPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
+ if (validPathPtr == NULL) {
+ return NULL;
+ }
+ } else {
+ /*
+ * Make sure the normalized path is set.
+ */
+
+ validPathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
+ if (validPathPtr == NULL) {
+ return NULL;
+ }
+ Tcl_IncrRefCount(validPathPtr);
+ }
+
+ str = Tcl_GetStringFromObj(validPathPtr, &len);
+ Tcl_UtfToExternalDString(NULL, str, len, &ds);
+ len = Tcl_DStringLength(&ds) + sizeof(char);
+ Tcl_DecrRefCount(validPathPtr);
+ nativePathPtr = ckalloc((unsigned) len);
+ memcpy((void*)nativePathPtr, (void*)Tcl_DStringValue(&ds), (size_t) len);
+
+ Tcl_DStringFree(&ds);
+ return (ClientData)nativePathPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclNativeDupInternalRep --
+ *
+ * Duplicate the native representation.
+ *
+ * Results:
+ * The copied native representation, or NULL if it is not possible to
+ * copy the representation.
+ *
+ * Side effects:
+ * Memory will be allocated for the copy.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+ClientData
+TclNativeDupInternalRep(
+ ClientData clientData)
+{
+ char *copy;
+ size_t len;
+
+ if (clientData == NULL) {
+ return NULL;
+ }
+
+ /*
+ * ASCII representation when running on Unix.
+ */
+
+ len = sizeof(char) + (strlen((CONST char*) clientData) * sizeof(char));
+
+ copy = (char *) ckalloc(len);
+ memcpy((void *) copy, (void *) clientData, len);
+ return (ClientData)copy;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
* TclpUtime --
*
* Set the modification date for a file.
@@ -813,10 +1156,19 @@ TclpFilesystemPathType(pathObjPtr)
*
*---------------------------------------------------------------------------
*/
-int
-TclpUtime(pathPtr, tval)
- Tcl_Obj *pathPtr; /* File to modify */
- struct utimbuf *tval; /* New modification date structure */
+
+int
+TclpUtime(
+ Tcl_Obj *pathPtr, /* File to modify */
+ struct utimbuf *tval) /* New modification date structure */
{
- return utime(Tcl_FSGetNativePath(pathPtr),tval);
+ return utime(Tcl_FSGetNativePath(pathPtr), tval);
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixInit.c b/unix/tclUnixInit.c
index 46ef042..5111746 100644
--- a/unix/tclUnixInit.c
+++ b/unix/tclUnixInit.c
@@ -1,4 +1,4 @@
-/*
+/*
* tclUnixInit.c --
*
* Contains the Unix-specific interpreter initialization functions.
@@ -8,11 +8,8 @@
* All rights reserved.
*/
-#if defined(HAVE_COREFOUNDATION)
-#include <CoreFoundation/CoreFoundation.h>
-#endif
#include "tclInt.h"
-#include "tclPort.h"
+#include <stddef.h>
#include <locale.h>
#ifdef HAVE_LANGINFO
# include <langinfo.h>
@@ -24,6 +21,7 @@
# endif
# endif
#endif
+#include <sys/resource.h>
#if defined(__FreeBSD__) && defined(__GNUC__)
# include <floatingpoint.h>
#endif
@@ -33,22 +31,72 @@
# include <dlfcn.h>
# endif
#endif
+#ifdef HAVE_COREFOUNDATION
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+/*
+ * Define TCL_NO_STACK_CHECK in the compiler options if you want to revert to
+ * the old behavior of never checking the stack.
+ */
+
+/*
+ * Define this if you want to see a lot of output regarding stack checking.
+ */
+
+#undef TCL_DEBUG_STACK_CHECK
+
+/*
+ * Values used to compute how much space is really available for Tcl's use for
+ * the stack.
+ *
+ * The getrlimit() function is documented to return the maximum stack size in
+ * bytes. However, with threads enabled, the pthread library on some platforms
+ * does bad things to the stack size limits. First, the limits cannot be
+ * changed. Second, they appear to be sometimes reported incorrectly.
+ *
+ * The defines below may need to be adjusted if more platforms have this
+ * broken behavior with threads enabled.
+ */
+
+#ifndef TCL_MAGIC_STACK_DIVISOR
+#define TCL_MAGIC_STACK_DIVISOR 1
+#endif
+#ifndef TCL_RESERVED_STACK_PAGES
+#define TCL_RESERVED_STACK_PAGES 8
+#endif
/*
- * The Init script (common to Windows and Unix platforms) is
- * defined in tkInitScript.h
+ * Thread specific data for stack checking.
*/
-#include "tclInitScript.h"
-/* Used to store the encoding used for binary files */
-static Tcl_Encoding binaryEncoding = NULL;
-/* Has the basic library path encoding issue been fixed */
-static int libraryPathEncodingFixed = 0;
+#ifndef TCL_NO_STACK_CHECK
+typedef struct ThreadSpecificData {
+ int *outerVarPtr; /* The "outermost" stack frame pointer for
+ * this thread. */
+ int *stackBound; /* The current stack boundary */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+#ifdef TCL_CROSS_COMPILE
+static int stackGrowsDown = -1;
+static int StackGrowsDown(int *parent);
+#elif defined(TCL_STACK_GROWS_UP)
+#define stackGrowsDown 0
+#else
+#define stackGrowsDown 1
+#endif
+#endif /* TCL_NO_STACK_CHECK */
+
+#ifdef TCL_DEBUG_STACK_CHECK
+#define STACK_DEBUG(args) printf args
+#else
+#define STACK_DEBUG(args) (void)0
+#endif /* TCL_DEBUG_STACK_CHECK */
/*
- * Tcl tries to use standard and homebrew methods to guess the right
- * encoding on the platform. However, there is always a final fallback,
- * and this value is it. Make sure it is a real Tcl encoding.
+ * Tcl tries to use standard and homebrew methods to guess the right encoding
+ * on the platform. However, there is always a final fallback, and this value
+ * is it. Make sure it is a real Tcl encoding.
*/
#ifndef TCL_DEFAULT_ENCODING
@@ -56,26 +104,25 @@ static int libraryPathEncodingFixed = 0;
#endif
/*
- * Default directory in which to look for Tcl library scripts. The
- * symbol is defined by Makefile.
+ * Default directory in which to look for Tcl library scripts. The symbol is
+ * defined by Makefile.
*/
static char defaultLibraryDir[sizeof(TCL_LIBRARY)+200] = TCL_LIBRARY;
/*
* Directory in which to look for packages (each package is typically
- * installed as a subdirectory of this directory). The symbol is
- * defined by Makefile.
+ * installed as a subdirectory of this directory). The symbol is defined by
+ * Makefile.
*/
static char pkgPath[sizeof(TCL_PACKAGE_PATH)+200] = TCL_PACKAGE_PATH;
/*
- * The following table is used to map from Unix locale strings to
- * encoding files. If HAVE_LANGINFO is defined, then this is a fallback
- * table when the result from nl_langinfo isn't a recognized encoding.
- * Otherwise this is the first list checked for a mapping from env
- * encoding to Tcl encoding name.
+ * The following table is used to map from Unix locale strings to encoding
+ * files. If HAVE_LANGINFO is defined, then this is a fallback table when the
+ * result from nl_langinfo isn't a recognized encoding. Otherwise this is the
+ * first list checked for a mapping from env encoding to Tcl encoding name.
*/
typedef struct LocaleTable {
@@ -83,78 +130,207 @@ typedef struct LocaleTable {
CONST char *encoding;
} LocaleTable;
-static CONST LocaleTable localeTable[] = {
-#ifdef HAVE_LANGINFO
- {"gb2312-1980", "gb2312"},
- {"ansi-1251", "cp1251"}, /* Solaris gets this wrong. */
-#ifdef __hpux
- {"SJIS", "shiftjis"},
- {"eucjp", "euc-jp"},
- {"euckr", "euc-kr"},
- {"euctw", "euc-cn"},
- {"greek8", "cp869"},
- {"iso88591", "iso8859-1"},
- {"iso88592", "iso8859-2"},
- {"iso88595", "iso8859-5"},
- {"iso88596", "iso8859-6"},
- {"iso88597", "iso8859-7"},
- {"iso88598", "iso8859-8"},
- {"iso88599", "iso8859-9"},
- {"iso885915", "iso8859-15"},
- {"roman8", "iso8859-1"},
- {"tis620", "tis-620"},
- {"turkish8", "cp857"},
- {"utf8", "utf-8"},
-#endif /* __hpux */
-#endif /* HAVE_LANGINFO */
+/*
+ * The table below is sorted for the sake of doing binary searches on it. The
+ * indenting reflects different categories of data. The leftmost data
+ * represent the encoding names directly implemented by data files in Tcl's
+ * default encoding directory. Indented by one TAB are the encoding names that
+ * are common alternative spellings. Indented by two TABs are the accumulated
+ * "bug fixes" that have been added to deal with the wide variability seen
+ * among existing platforms.
+ */
- {"ja_JP.SJIS", "shiftjis"},
- {"ja_JP.EUC", "euc-jp"},
- {"ja_JP.eucJP", "euc-jp"},
- {"ja_JP.JIS", "iso2022-jp"},
- {"ja_JP.mscode", "shiftjis"},
- {"ja_JP.ujis", "euc-jp"},
- {"ja_JP", "euc-jp"},
- {"Ja_JP", "shiftjis"},
- {"Jp_JP", "shiftjis"},
- {"japan", "euc-jp"},
+static CONST LocaleTable localeTable[] = {
+ {"", "iso8859-1"},
+ {"ansi-1251", "cp1251"},
+ {"ansi_x3.4-1968", "iso8859-1"},
+ {"ascii", "ascii"},
+ {"big5", "big5"},
+ {"cp1250", "cp1250"},
+ {"cp1251", "cp1251"},
+ {"cp1252", "cp1252"},
+ {"cp1253", "cp1253"},
+ {"cp1254", "cp1254"},
+ {"cp1255", "cp1255"},
+ {"cp1256", "cp1256"},
+ {"cp1257", "cp1257"},
+ {"cp1258", "cp1258"},
+ {"cp437", "cp437"},
+ {"cp737", "cp737"},
+ {"cp775", "cp775"},
+ {"cp850", "cp850"},
+ {"cp852", "cp852"},
+ {"cp855", "cp855"},
+ {"cp857", "cp857"},
+ {"cp860", "cp860"},
+ {"cp861", "cp861"},
+ {"cp862", "cp862"},
+ {"cp863", "cp863"},
+ {"cp864", "cp864"},
+ {"cp865", "cp865"},
+ {"cp866", "cp866"},
+ {"cp869", "cp869"},
+ {"cp874", "cp874"},
+ {"cp932", "cp932"},
+ {"cp936", "cp936"},
+ {"cp949", "cp949"},
+ {"cp950", "cp950"},
+ {"dingbats", "dingbats"},
+ {"ebcdic", "ebcdic"},
+ {"euc-cn", "euc-cn"},
+ {"euc-jp", "euc-jp"},
+ {"euc-kr", "euc-kr"},
+ {"eucjp", "euc-jp"},
+ {"euckr", "euc-kr"},
+ {"euctw", "euc-cn"},
+ {"gb12345", "gb12345"},
+ {"gb1988", "gb1988"},
+ {"gb2312", "gb2312"},
+ {"gb2312-1980", "gb2312"},
+ {"gb2312-raw", "gb2312-raw"},
+ {"greek8", "cp869"},
+ {"ibm1250", "cp1250"},
+ {"ibm1251", "cp1251"},
+ {"ibm1252", "cp1252"},
+ {"ibm1253", "cp1253"},
+ {"ibm1254", "cp1254"},
+ {"ibm1255", "cp1255"},
+ {"ibm1256", "cp1256"},
+ {"ibm1257", "cp1257"},
+ {"ibm1258", "cp1258"},
+ {"ibm437", "cp437"},
+ {"ibm737", "cp737"},
+ {"ibm775", "cp775"},
+ {"ibm850", "cp850"},
+ {"ibm852", "cp852"},
+ {"ibm855", "cp855"},
+ {"ibm857", "cp857"},
+ {"ibm860", "cp860"},
+ {"ibm861", "cp861"},
+ {"ibm862", "cp862"},
+ {"ibm863", "cp863"},
+ {"ibm864", "cp864"},
+ {"ibm865", "cp865"},
+ {"ibm866", "cp866"},
+ {"ibm869", "cp869"},
+ {"ibm874", "cp874"},
+ {"ibm932", "cp932"},
+ {"ibm936", "cp936"},
+ {"ibm949", "cp949"},
+ {"ibm950", "cp950"},
+ {"iso-2022", "iso2022"},
+ {"iso-2022-jp", "iso2022-jp"},
+ {"iso-2022-kr", "iso2022-kr"},
+ {"iso-8859-1", "iso8859-1"},
+ {"iso-8859-10", "iso8859-10"},
+ {"iso-8859-13", "iso8859-13"},
+ {"iso-8859-14", "iso8859-14"},
+ {"iso-8859-15", "iso8859-15"},
+ {"iso-8859-16", "iso8859-16"},
+ {"iso-8859-2", "iso8859-2"},
+ {"iso-8859-3", "iso8859-3"},
+ {"iso-8859-4", "iso8859-4"},
+ {"iso-8859-5", "iso8859-5"},
+ {"iso-8859-6", "iso8859-6"},
+ {"iso-8859-7", "iso8859-7"},
+ {"iso-8859-8", "iso8859-8"},
+ {"iso-8859-9", "iso8859-9"},
+ {"iso2022", "iso2022"},
+ {"iso2022-jp", "iso2022-jp"},
+ {"iso2022-kr", "iso2022-kr"},
+ {"iso8859-1", "iso8859-1"},
+ {"iso8859-10", "iso8859-10"},
+ {"iso8859-13", "iso8859-13"},
+ {"iso8859-14", "iso8859-14"},
+ {"iso8859-15", "iso8859-15"},
+ {"iso8859-16", "iso8859-16"},
+ {"iso8859-2", "iso8859-2"},
+ {"iso8859-3", "iso8859-3"},
+ {"iso8859-4", "iso8859-4"},
+ {"iso8859-5", "iso8859-5"},
+ {"iso8859-6", "iso8859-6"},
+ {"iso8859-7", "iso8859-7"},
+ {"iso8859-8", "iso8859-8"},
+ {"iso8859-9", "iso8859-9"},
+ {"iso88591", "iso8859-1"},
+ {"iso885915", "iso8859-15"},
+ {"iso88592", "iso8859-2"},
+ {"iso88595", "iso8859-5"},
+ {"iso88596", "iso8859-6"},
+ {"iso88597", "iso8859-7"},
+ {"iso88598", "iso8859-8"},
+ {"iso88599", "iso8859-9"},
+#ifdef hpux
+ {"ja", "shiftjis"},
+#else
+ {"ja", "euc-jp"},
+#endif
+ {"ja_jp", "euc-jp"},
+ {"ja_jp.euc", "euc-jp"},
+ {"ja_jp.eucjp", "euc-jp"},
+ {"ja_jp.jis", "iso2022-jp"},
+ {"ja_jp.mscode", "shiftjis"},
+ {"ja_jp.sjis", "shiftjis"},
+ {"ja_jp.ujis", "euc-jp"},
+ {"japan", "euc-jp"},
#ifdef hpux
- {"japanese", "shiftjis"},
- {"ja", "shiftjis"},
+ {"japanese", "shiftjis"},
#else
- {"japanese", "euc-jp"},
- {"ja", "euc-jp"},
+ {"japanese", "euc-jp"},
#endif
- {"japanese.sjis", "shiftjis"},
- {"japanese.euc", "euc-jp"},
- {"japanese-sjis", "shiftjis"},
- {"japanese-ujis", "euc-jp"},
-
- {"ko", "euc-kr"},
- {"ko_KR", "euc-kr"},
- {"ko_KR.EUC", "euc-kr"},
- {"ko_KR.euc", "euc-kr"},
- {"ko_KR.eucKR", "euc-kr"},
- {"korean", "euc-kr"},
-
- {"ru", "iso8859-5"},
- {"ru_RU", "iso8859-5"},
- {"ru_SU", "iso8859-5"},
-
- {"zh", "cp936"},
- {"zh_CN.gb2312", "euc-cn"},
- {"zh_CN.GB2312", "euc-cn"},
- {"zh_CN.GBK", "euc-cn"},
- {"zh_TW.Big5", "big5"},
- {"zh_TW", "euc-tw"},
-
- {NULL, NULL}
+ {"japanese-sjis", "shiftjis"},
+ {"japanese-ujis", "euc-jp"},
+ {"japanese.euc", "euc-jp"},
+ {"japanese.sjis", "shiftjis"},
+ {"jis0201", "jis0201"},
+ {"jis0208", "jis0208"},
+ {"jis0212", "jis0212"},
+ {"jp_jp", "shiftjis"},
+ {"ko", "euc-kr"},
+ {"ko_kr", "euc-kr"},
+ {"ko_kr.euc", "euc-kr"},
+ {"ko_kw.euckw", "euc-kr"},
+ {"koi8-r", "koi8-r"},
+ {"koi8-u", "koi8-u"},
+ {"korean", "euc-kr"},
+ {"ksc5601", "ksc5601"},
+ {"maccenteuro", "macCentEuro"},
+ {"maccroatian", "macCroatian"},
+ {"maccyrillic", "macCyrillic"},
+ {"macdingbats", "macDingbats"},
+ {"macgreek", "macGreek"},
+ {"maciceland", "macIceland"},
+ {"macjapan", "macJapan"},
+ {"macroman", "macRoman"},
+ {"macromania", "macRomania"},
+ {"macthai", "macThai"},
+ {"macturkish", "macTurkish"},
+ {"macukraine", "macUkraine"},
+ {"roman8", "iso8859-1"},
+ {"ru", "iso8859-5"},
+ {"ru_ru", "iso8859-5"},
+ {"ru_su", "iso8859-5"},
+ {"shiftjis", "shiftjis"},
+ {"sjis", "shiftjis"},
+ {"symbol", "symbol"},
+ {"tis-620", "tis-620"},
+ {"tis620", "tis-620"},
+ {"turkish8", "cp857"},
+ {"utf8", "utf-8"},
+ {"zh", "cp936"},
+ {"zh_cn.gb2312", "euc-cn"},
+ {"zh_cn.gbk", "euc-cn"},
+ {"zh_cz.gb2312", "euc-cn"},
+ {"zh_tw", "euc-tw"},
+ {"zh_tw.big5", "big5"},
};
+#ifndef TCL_NO_STACK_CHECK
+static int GetStackSize(size_t *stackSizePtr);
+#endif /* TCL_NO_STACK_CHECK */
#ifdef HAVE_COREFOUNDATION
-static int MacOSXGetLibraryPath _ANSI_ARGS_((
- Tcl_Interp *interp, int maxPathLen,
- char *tclLibPath));
+static int MacOSXGetLibraryPath(Tcl_Interp *interp,
+ int maxPathLen, char *tclLibPath);
#endif /* HAVE_COREFOUNDATION */
#if defined(__APPLE__) && (defined(TCL_LOAD_FROM_MEMORY) || ( \
defined(MAC_OS_X_VERSION_MIN_REQUIRED) && ( \
@@ -167,6 +343,7 @@ static int MacOSXGetLibraryPath _ANSI_ARGS_((
* initialize release global at startup from uname().
*/
#define GET_DARWIN_RELEASE 1
+MODULE_SCOPE long tclMacOSXDarwinRelease;
long tclMacOSXDarwinRelease = 0;
#endif
@@ -191,13 +368,18 @@ long tclMacOSXDarwinRelease = 0;
*/
void
-TclpInitPlatform()
+TclpInitPlatform(void)
{
+#ifdef DJGPP
+ tclPlatform = TCL_PLATFORM_WINDOWS;
+#else
tclPlatform = TCL_PLATFORM_UNIX;
+#endif
/*
* Make sure, that the standard FDs exist. [Bug 772288]
*/
+
if (TclOSseek(0, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) {
open("/dev/null", O_RDONLY);
}
@@ -209,13 +391,12 @@ TclpInitPlatform()
}
/*
- * The code below causes SIGPIPE (broken pipe) errors to
- * be ignored. This is needed so that Tcl processes don't
- * die if they create child processes (e.g. using "exec" or
- * "open") that terminate prematurely. The signal handler
- * is only set up when the first interpreter is created;
- * after this the application can override the handler with
- * a different one of its own, if it wants.
+ * The code below causes SIGPIPE (broken pipe) errors to be ignored. This
+ * is needed so that Tcl processes don't die if they create child
+ * processes (e.g. using "exec" or "open") that terminate prematurely.
+ * The signal handler is only set up when the first interpreter is
+ * created; after this the application can override the handler with a
+ * different one of its own, if it wants.
*/
#ifdef SIGPIPE
@@ -231,19 +412,41 @@ TclpInitPlatform()
*/
fpsetround(FP_RN);
- fpsetmask(0L);
+ (void) fpsetmask(0L);
#endif
#if defined(__bsdi__) && (_BSDI_VERSION > 199501)
/*
* Find local symbols. Don't report an error if we fail.
*/
- (void) dlopen (NULL, RTLD_NOW); /* INTL: Native. */
+
+ (void) dlopen(NULL, RTLD_NOW); /* INTL: Native. */
#endif
+ /*
+ * Initialize the C library's locale subsystem. This is required for input
+ * methods to work properly on X11. We only do this for LC_CTYPE because
+ * that's the necessary one, and we don't want to affect LC_TIME here.
+ * The side effect of setting the default locale should be to load any
+ * locale specific modules that are needed by X. [BUG: 5422 3345 4236 2522
+ * 2521].
+ */
+
+ setlocale(LC_CTYPE, "");
+
+ /*
+ * In case the initial locale is not "C", ensure that the numeric
+ * processing is done in "C" locale regardless. This is needed because Tcl
+ * relies on routines like strtod, but should not have locale dependent
+ * behavior.
+ */
+
+ setlocale(LC_NUMERIC, "C");
+
#ifdef GET_DARWIN_RELEASE
{
struct utsname name;
+
if (!uname(&name)) {
tclMacOSXDarwinRelease = strtol(name.release, NULL, 10);
}
@@ -256,84 +459,36 @@ TclpInitPlatform()
*
* TclpInitLibraryPath --
*
- * Initialize the library path at startup. We have a minor
- * metacircular problem that we don't know the encoding of the
- * operating system but we may need to talk to operating system
- * to find the library directories so that we know how to talk to
- * the operating system.
- *
- * We do not know the encoding of the operating system.
- * We do know that the encoding is some multibyte encoding.
- * In that multibyte encoding, the characters 0..127 are equivalent
- * to ascii.
- *
- * So although we don't know the encoding, it's safe:
- * to look for the last slash character in a path in the encoding.
- * to append an ascii string to a path.
- * to pass those strings back to the operating system.
- *
- * But any strings that we remembered before we knew the encoding of
- * the operating system must be translated to UTF-8 once we know the
- * encoding so that the rest of Tcl can use those strings.
- *
- * This call sets the library path to strings in the unknown native
- * encoding. TclpSetInitialEncodings() will translate the library
- * path from the native encoding to UTF-8 as soon as it determines
- * what the native encoding actually is.
- *
- * Called at process initialization time.
+ * This is the fallback routine that sets the library path if the
+ * application has not set one by the first time it is needed.
*
* Results:
- * Return 1, indicating that the UTF may be dirty and require "cleanup"
- * after encodings are initialized.
+ * None.
*
* Side effects:
- * None.
+ * Sets the library path to an initial value.
*
- *---------------------------------------------------------------------------
+ *-------------------------------------------------------------------------
*/
-int
-TclpInitLibraryPath(path)
-CONST char *path; /* Path to the executable in native
- * multi-byte encoding. */
+void
+TclpInitLibraryPath(
+ char **valuePtr,
+ int *lengthPtr,
+ Tcl_Encoding *encodingPtr)
{
#define LIBRARY_SIZE 32
Tcl_Obj *pathPtr, *objPtr;
CONST char *str;
- Tcl_DString buffer, ds;
- int pathc;
- CONST char **pathv;
- char installLib[LIBRARY_SIZE], developLib[LIBRARY_SIZE];
+ Tcl_DString buffer;
- Tcl_DStringInit(&ds);
pathPtr = Tcl_NewObj();
/*
- * Initialize the substrings used when locating an executable. The
- * installLib variable computes the path as though the executable
- * is installed. The developLib computes the path as though the
- * executable is run from a develpment directory.
- */
-
- sprintf(installLib, "lib/tcl%s", TCL_VERSION);
- sprintf(developLib, "tcl%s/library", TCL_PATCH_LEVEL);
-
- /*
- * Look for the library relative to default encoding dir.
- */
-
- str = Tcl_GetDefaultEncodingDir();
- if ((str != NULL) && (str[0] != '\0')) {
- objPtr = Tcl_NewStringObj(str, -1);
- Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
- }
-
- /*
- * Look for the library relative to the TCL_LIBRARY env variable.
- * If the last dirname in the TCL_LIBRARY path does not match the
- * last dirname in the installLib variable, use the last dir name
- * of installLib in addition to the orginal TCL_LIBRARY path.
+ * Look for the library relative to the TCL_LIBRARY env variable. If the
+ * last dirname in the TCL_LIBRARY path does not match the last dirname in
+ * the installLib variable, use the last dir name of installLib in
+ * addition to the orginal TCL_LIBRARY path.
*/
str = getenv("TCL_LIBRARY"); /* INTL: Native. */
@@ -341,10 +496,25 @@ CONST char *path; /* Path to the executable in native
str = Tcl_DStringValue(&buffer);
if ((str != NULL) && (str[0] != '\0')) {
+ Tcl_DString ds;
+ int pathc;
+ CONST char **pathv;
+ char installLib[LIBRARY_SIZE];
+
+ Tcl_DStringInit(&ds);
+
+ /*
+ * Initialize the substrings used when locating an executable. The
+ * installLib variable computes the path as though the executable is
+ * installed.
+ */
+
+ sprintf(installLib, "lib/tcl%s", TCL_VERSION);
+
/*
* If TCL_LIBRARY is set, search there.
*/
-
+
objPtr = Tcl_NewStringObj(str, -1);
Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
@@ -354,10 +524,10 @@ CONST char *path; /* Path to the executable in native
* If TCL_LIBRARY is set but refers to a different tcl
* installation than the current version, try fiddling with the
* specified directory to make it refer to this installation by
- * removing the old "tclX.Y" and substituting the current
- * version string.
+ * removing the old "tclX.Y" and substituting the current version
+ * string.
*/
-
+
pathv[pathc - 1] = installLib + 4;
str = Tcl_JoinPath(pathc, pathv, &ds);
objPtr = Tcl_NewStringObj(str, Tcl_DStringLength(&ds));
@@ -368,136 +538,38 @@ CONST char *path; /* Path to the executable in native
}
/*
- * Look for the library relative to the executable. This algorithm
- * should be the same as the one in the tcl_findLibrary procedure.
- *
- * This code looks in the following directories:
- *
- * <bindir>/../<installLib>
- * (e.g. /usr/local/bin/../lib/tcl8.4)
- * <bindir>/../../<installLib>
- * (e.g. /usr/local/TclPro/solaris-sparc/bin/../../lib/tcl8.4)
- * <bindir>/../library
- * (e.g. /usr/src/tcl8.4.0/unix/../library)
- * <bindir>/../../library
- * (e.g. /usr/src/tcl8.4.0/unix/solaris-sparc/../../library)
- * <bindir>/../../<developLib>
- * (e.g. /usr/src/tcl8.4.0/unix/../../tcl8.4.0/library)
- * <bindir>/../../../<developLib>
- * (e.g. /usr/src/tcl8.4.0/unix/solaris-sparc/../../../tcl8.4.0/library)
- */
-
-
- /*
- * The variable path holds an absolute path. Take care not to
- * overwrite pathv[0] since that might produce a relative path.
- */
-
- if (path != NULL) {
- int i, origc;
- CONST char **origv;
-
- Tcl_SplitPath(path, &origc, &origv);
- pathc = 0;
- pathv = (CONST char **) ckalloc((unsigned int)(origc * sizeof(char *)));
- for (i=0; i< origc; i++) {
- if (origv[i][0] == '.') {
- if (strcmp(origv[i], ".") == 0) {
- /* do nothing */
- } else if (strcmp(origv[i], "..") == 0) {
- pathc--;
- } else {
- pathv[pathc++] = origv[i];
- }
- } else {
- pathv[pathc++] = origv[i];
- }
- }
- if (pathc > 2) {
- str = pathv[pathc - 2];
- pathv[pathc - 2] = installLib;
- path = Tcl_JoinPath(pathc - 1, pathv, &ds);
- pathv[pathc - 2] = str;
- objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
- Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
- Tcl_DStringFree(&ds);
- }
- if (pathc > 3) {
- str = pathv[pathc - 3];
- pathv[pathc - 3] = installLib;
- path = Tcl_JoinPath(pathc - 2, pathv, &ds);
- pathv[pathc - 3] = str;
- objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
- Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
- Tcl_DStringFree(&ds);
- }
- if (pathc > 2) {
- str = pathv[pathc - 2];
- pathv[pathc - 2] = "library";
- path = Tcl_JoinPath(pathc - 1, pathv, &ds);
- pathv[pathc - 2] = str;
- objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
- Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
- Tcl_DStringFree(&ds);
- }
- if (pathc > 3) {
- str = pathv[pathc - 3];
- pathv[pathc - 3] = "library";
- path = Tcl_JoinPath(pathc - 2, pathv, &ds);
- pathv[pathc - 3] = str;
- objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
- Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
- Tcl_DStringFree(&ds);
- }
- if (pathc > 3) {
- str = pathv[pathc - 3];
- pathv[pathc - 3] = developLib;
- path = Tcl_JoinPath(pathc - 2, pathv, &ds);
- pathv[pathc - 3] = str;
- objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
- Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
- Tcl_DStringFree(&ds);
- }
- if (pathc > 4) {
- str = pathv[pathc - 4];
- pathv[pathc - 4] = developLib;
- path = Tcl_JoinPath(pathc - 3, pathv, &ds);
- pathv[pathc - 4] = str;
- objPtr = Tcl_NewStringObj(path, Tcl_DStringLength(&ds));
- Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
- Tcl_DStringFree(&ds);
- }
- ckfree((char *) origv);
- ckfree((char *) pathv);
- }
-
- /*
- * Finally, look for the library relative to the compiled-in path.
- * This is needed when users install Tcl with an exec-prefix that
- * is different from the prtefix.
+ * Finally, look for the library relative to the compiled-in path. This is
+ * needed when users install Tcl with an exec-prefix that is different
+ * from the prefix.
*/
{
#ifdef HAVE_COREFOUNDATION
- char tclLibPath[MAXPATHLEN + 1];
+ char tclLibPath[MAXPATHLEN + 1];
- if (MacOSXGetLibraryPath(NULL, MAXPATHLEN, tclLibPath) == TCL_OK) {
- str = tclLibPath;
- } else
+ if (MacOSXGetLibraryPath(NULL, MAXPATHLEN, tclLibPath) == TCL_OK) {
+ str = tclLibPath;
+ } else
#endif /* HAVE_COREFOUNDATION */
- {
- str = defaultLibraryDir;
- }
- if (str[0] != '\0') {
- objPtr = Tcl_NewStringObj(str, -1);
- Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
- }
- }
+ {
+ /*
+ * TODO: Pull this value from the TIP 59 table.
+ */
- TclSetLibraryPath(pathPtr);
+ str = defaultLibraryDir;
+ }
+ if (str[0] != '\0') {
+ objPtr = Tcl_NewStringObj(str, -1);
+ Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
+ }
+ }
Tcl_DStringFree(&buffer);
- return 1; /* 1 indicates that pathPtr may be dirty utf (needs cleaning) */
+ *encodingPtr = Tcl_GetEncoding(NULL, NULL);
+ str = Tcl_GetStringFromObj(pathPtr, lengthPtr);
+ *valuePtr = ckalloc((unsigned int) (*lengthPtr)+1);
+ memcpy(*valuePtr, str, (size_t)(*lengthPtr)+1);
+ Tcl_DecrRefCount(pathPtr);
}
/*
@@ -505,250 +577,168 @@ CONST char *path; /* Path to the executable in native
*
* TclpSetInitialEncodings --
*
- * Based on the locale, determine the encoding of the operating
- * system and the default encoding for newly opened files.
+ * Based on the locale, determine the encoding of the operating system
+ * and the default encoding for newly opened files.
*
- * Called at process initialization time, and part way through
- * startup, we verify that the initial encodings were correctly
- * setup. Depending on Tcl's environment, there may not have been
- * enough information first time through (above).
+ * Called at process initialization time, and part way through startup,
+ * we verify that the initial encodings were correctly setup. Depending
+ * on Tcl's environment, there may not have been enough information first
+ * time through (above).
*
* Results:
* None.
*
* Side effects:
- * The Tcl library path is converted from native encoding to UTF-8,
- * on the first call, and the encodings may be changed on first or
- * second call.
+ * The Tcl library path is converted from native encoding to UTF-8, on
+ * the first call, and the encodings may be changed on first or second
+ * call.
*
*---------------------------------------------------------------------------
*/
void
-TclpSetInitialEncodings()
+TclpSetInitialEncodings(void)
{
- CONST char *encoding = NULL;
- int i, setSysEncCode = TCL_ERROR;
- Tcl_Obj *pathPtr;
+ Tcl_DString encodingName;
+ Tcl_SetSystemEncoding(NULL,
+ Tcl_GetEncodingNameFromEnvironment(&encodingName));
+ Tcl_DStringFree(&encodingName);
+}
- /*
- * Determine the current encoding from the LC_* or LANG environment
- * variables. We previously used setlocale() to determine the locale,
- * but this does not work on some systems (e.g. Linux/i386 RH 5.0).
- */
-#ifdef HAVE_LANGINFO
- if (
-#ifdef WEAK_IMPORT_NL_LANGINFO
- nl_langinfo != NULL &&
-#endif
- setlocale(LC_CTYPE, "") != NULL) {
- Tcl_DString ds;
+void
+TclpSetInterfaces(void)
+{
+ /* do nothing */
+}
- /*
- * Use a DString so we can overwrite it in name compatability
- * checks below.
- */
+static CONST char *
+SearchKnownEncodings(
+ CONST char *encoding)
+{
+ int left = 0;
+ int right = sizeof(localeTable)/sizeof(LocaleTable);
- Tcl_DStringInit(&ds);
- encoding = Tcl_DStringAppend(&ds, nl_langinfo(CODESET), -1);
+ while (left <= right) {
+ int test = (left + right)/2;
+ int code = strcmp(localeTable[test].lang, encoding);
- Tcl_UtfToLower(Tcl_DStringValue(&ds));
-#ifdef HAVE_LANGINFO_DEBUG
- fprintf(stderr, "encoding '%s'", encoding);
-#endif
- if (encoding[0] == 'i' && encoding[1] == 's' && encoding[2] == 'o'
- && encoding[3] == '-') {
- char *p, *q;
- /* need to strip '-' from iso-* encoding */
- for(p = Tcl_DStringValue(&ds)+3, q = Tcl_DStringValue(&ds)+4;
- *p; *p++ = *q++);
- } else if (encoding[0] == 'i' && encoding[1] == 'b'
- && encoding[2] == 'm' && encoding[3] >= '0'
- && encoding[3] <= '9') {
- char *p, *q;
- /* if langinfo reports "ibm*" we should use "cp*" */
- p = Tcl_DStringValue(&ds);
- *p++ = 'c'; *p++ = 'p';
- for(q = p+1; *p ; *p++ = *q++);
- } else if ((*encoding == '\0')
- || !strcmp(encoding, "ansi_x3.4-1968")) {
- /* Use iso8859-1 for empty or 'ansi_x3.4-1968' encoding */
- encoding = "iso8859-1";
- }
-#ifdef HAVE_LANGINFO_DEBUG
- fprintf(stderr, " ?%s?", encoding);
-#endif
- setSysEncCode = Tcl_SetSystemEncoding(NULL, encoding);
- if (setSysEncCode != TCL_OK) {
- /*
- * If this doesn't return TCL_OK, the encoding returned by
- * nl_langinfo or as we translated it wasn't accepted. Do
- * this fallback check. If this fails, we will enter the
- * old fallback below.
- */
-
- for (i = 0; localeTable[i].lang != NULL; i++) {
- if (strcmp(localeTable[i].lang, encoding) == 0) {
- setSysEncCode = Tcl_SetSystemEncoding(NULL,
- localeTable[i].encoding);
- break;
- }
- }
- }
-#ifdef HAVE_LANGINFO_DEBUG
- fprintf(stderr, " => '%s'\n", encoding);
-#endif
- Tcl_DStringFree(&ds);
+ if (code == 0) {
+ return localeTable[test].encoding;
}
-#ifdef HAVE_LANGINFO_DEBUG
- else {
- fprintf(stderr, "setlocale returned NULL\n");
+ if (code < 0) {
+ left = test+1;
+ } else {
+ right = test-1;
}
-#endif
-#endif /* HAVE_LANGINFO */
-
- if (setSysEncCode != TCL_OK) {
- /*
- * Classic fallback check. This tries a homebrew algorithm to
- * determine what encoding should be used based on env vars.
- */
- char *langEnv = getenv("LC_ALL");
- encoding = NULL;
+ }
+ return NULL;
+}
- if (langEnv == NULL || langEnv[0] == '\0') {
- langEnv = getenv("LC_CTYPE");
- }
- if (langEnv == NULL || langEnv[0] == '\0') {
- langEnv = getenv("LANG");
- }
- if (langEnv == NULL || langEnv[0] == '\0') {
- langEnv = NULL;
- }
+CONST char *
+Tcl_GetEncodingNameFromEnvironment(
+ Tcl_DString *bufPtr)
+{
+ CONST char *encoding;
+ CONST char *knownEncoding;
- if (langEnv != NULL) {
- for (i = 0; localeTable[i].lang != NULL; i++) {
- if (strcmp(localeTable[i].lang, langEnv) == 0) {
- encoding = localeTable[i].encoding;
- break;
- }
- }
- /*
- * There was no mapping in the locale table. If there is an
- * encoding subfield, we can try to guess from that.
- */
-
- if (encoding == NULL) {
- char *p;
- for (p = langEnv; *p != '\0'; p++) {
- if (*p == '.') {
- p++;
- break;
- }
- }
- if (*p != '\0') {
- Tcl_DString ds;
- Tcl_DStringInit(&ds);
- encoding = Tcl_DStringAppend(&ds, p, -1);
-
- Tcl_UtfToLower(Tcl_DStringValue(&ds));
- setSysEncCode = Tcl_SetSystemEncoding(NULL, encoding);
- if (setSysEncCode != TCL_OK) {
- encoding = NULL;
- }
- Tcl_DStringFree(&ds);
- }
- }
-#ifdef HAVE_LANGINFO_DEBUG
- fprintf(stderr, "encoding fallback check '%s' => '%s'\n",
- langEnv, encoding);
-#endif
- }
- if (setSysEncCode != TCL_OK) {
- if (encoding == NULL) {
- encoding = TCL_DEFAULT_ENCODING;
- }
+ Tcl_DStringInit(bufPtr);
- Tcl_SetSystemEncoding(NULL, encoding);
- }
+ /*
+ * Determine the current encoding from the LC_* or LANG environment
+ * variables. We previously used setlocale() to determine the locale, but
+ * this does not work on some systems (e.g. Linux/i386 RH 5.0).
+ */
- /*
- * Initialize the C library's locale subsystem. This is required
- * for input methods to work properly on X11. We only do this for
- * LC_CTYPE because that's the necessary one, and we don't want to
- * affect LC_TIME here. The side effect of setting the default
- * locale should be to load any locale specific modules that are
- * needed by X. [BUG: 5422 3345 4236 2522 2521].
- * In HAVE_LANGINFO, this call is already done above.
- */
-#ifndef HAVE_LANGINFO
- setlocale(LC_CTYPE, "");
+#ifdef HAVE_LANGINFO
+ if (
+#ifdef WEAK_IMPORT_NL_LANGINFO
+ nl_langinfo != NULL &&
#endif
- }
+ setlocale(LC_CTYPE, "") != NULL) {
+ Tcl_DString ds;
/*
- * In case the initial locale is not "C", ensure that the numeric
- * processing is done in "C" locale regardless. This is needed because
- * Tcl relies on routines like strtod, but should not have locale
- * dependent behavior.
+ * Use a DString so we can modify case.
*/
- setlocale(LC_NUMERIC, "C");
+ Tcl_DStringInit(&ds);
+ encoding = Tcl_DStringAppend(&ds, nl_langinfo(CODESET), -1);
+ Tcl_UtfToLower(Tcl_DStringValue(&ds));
+ knownEncoding = SearchKnownEncodings(encoding);
+ if (knownEncoding != NULL) {
+ Tcl_DStringAppend(bufPtr, knownEncoding, -1);
+ } else if (NULL != Tcl_GetEncoding(NULL, encoding)) {
+ Tcl_DStringAppend(bufPtr, encoding, -1);
+ }
+ Tcl_DStringFree(&ds);
+ if (Tcl_DStringLength(bufPtr)) {
+ return Tcl_DStringValue(bufPtr);
+ }
+ }
+#endif /* HAVE_LANGINFO */
- if ((libraryPathEncodingFixed == 0) && strcmp("identity",
- Tcl_GetEncodingName(Tcl_GetEncoding(NULL, NULL))) ) {
- /*
- * Until the system encoding was actually set, the library path was
- * actually in the native multi-byte encoding, and not really UTF-8
- * as advertised. We cheated as follows:
- *
- * 1. It was safe to allow the Tcl_SetSystemEncoding() call to
- * append the ASCII chars that make up the encoding's filename to
- * the names (in the native encoding) of directories in the library
- * path, since all Unix multi-byte encodings have ASCII in the
- * beginning.
- *
- * 2. To open the encoding file, the native bytes in the file name
- * were passed to the OS, without translating from UTF-8 to native,
- * because the name was already in the native encoding.
- *
- * Now that the system encoding was actually successfully set,
- * translate all the names in the library path to UTF-8. That way,
- * next time we search the library path, we'll translate the names
- * from UTF-8 to the system encoding which will be the native
- * encoding.
- */
+ /*
+ * Classic fallback check. This tries a homebrew algorithm to determine
+ * what encoding should be used based on env vars.
+ */
- pathPtr = TclGetLibraryPath();
- if (pathPtr != NULL) {
- int objc;
- Tcl_Obj **objv;
-
- objc = 0;
- Tcl_ListObjGetElements(NULL, pathPtr, &objc, &objv);
- for (i = 0; i < objc; i++) {
- int length;
- char *string;
- Tcl_DString ds;
-
- string = Tcl_GetStringFromObj(objv[i], &length);
- Tcl_ExternalToUtfDString(NULL, string, length, &ds);
- Tcl_SetStringObj(objv[i], Tcl_DStringValue(&ds),
- Tcl_DStringLength(&ds));
- Tcl_DStringFree(&ds);
- }
- }
+ encoding = getenv("LC_ALL");
- libraryPathEncodingFixed = 1;
+ if (encoding == NULL || encoding[0] == '\0') {
+ encoding = getenv("LC_CTYPE");
}
-
- /* This is only ever called from the startup thread */
- if (binaryEncoding == NULL) {
+ if (encoding == NULL || encoding[0] == '\0') {
+ encoding = getenv("LANG");
+ }
+ if (encoding == NULL || encoding[0] == '\0') {
+ encoding = NULL;
+ }
+
+ if (encoding != NULL) {
+ CONST char *p;
+ Tcl_DString ds;
+
+ Tcl_DStringInit(&ds);
+ p = encoding;
+ encoding = Tcl_DStringAppend(&ds, p, -1);
+ Tcl_UtfToLower(Tcl_DStringValue(&ds));
+
+ knownEncoding = SearchKnownEncodings(encoding);
+ if (knownEncoding != NULL) {
+ Tcl_DStringAppend(bufPtr, knownEncoding, -1);
+ } else if (NULL != Tcl_GetEncoding(NULL, encoding)) {
+ Tcl_DStringAppend(bufPtr, encoding, -1);
+ }
+ if (Tcl_DStringLength(bufPtr)) {
+ Tcl_DStringFree(&ds);
+ return Tcl_DStringValue(bufPtr);
+ }
+
/*
- * Keep the iso8859-1 encoding preloaded. The IO package uses
- * it for gets on a binary channel.
+ * We didn't recognize the full value as an encoding name. If there is
+ * an encoding subfield, we can try to guess from that.
*/
- binaryEncoding = Tcl_GetEncoding(NULL, "iso8859-1");
+
+ for (p = encoding; *p != '\0'; p++) {
+ if (*p == '.') {
+ p++;
+ break;
+ }
+ }
+ if (*p != '\0') {
+ knownEncoding = SearchKnownEncodings(p);
+ if (knownEncoding != NULL) {
+ Tcl_DStringAppend(bufPtr, knownEncoding, -1);
+ } else if (NULL != Tcl_GetEncoding(NULL, p)) {
+ Tcl_DStringAppend(bufPtr, p, -1);
+ }
+ }
+ Tcl_DStringFree(&ds);
+ if (Tcl_DStringLength(bufPtr)) {
+ return Tcl_DStringValue(bufPtr);
+ }
}
+ return Tcl_DStringAppend(bufPtr, TCL_DEFAULT_ENCODING, -1);
}
/*
@@ -756,9 +746,9 @@ TclpSetInitialEncodings()
*
* TclpSetVariables --
*
- * Performs platform-specific interpreter initialization related to
- * the tcl_library and tcl_platform variables, and other platform-
- * specific things.
+ * Performs platform-specific interpreter initialization related to the
+ * tcl_library and tcl_platform variables, and other platform-specific
+ * things.
*
* Results:
* None.
@@ -771,14 +761,13 @@ TclpSetInitialEncodings()
*/
void
-TclpSetVariables(interp)
- Tcl_Interp *interp;
+TclpSetVariables(
+ Tcl_Interp *interp)
{
#ifndef NO_UNAME
struct utsname name;
#endif
int unameOK;
- CONST char *user;
Tcl_DString ds;
#ifdef HAVE_COREFOUNDATION
@@ -788,6 +777,7 @@ TclpSetVariables(interp)
/*
* Set msgcat fallback locale to current CFLocale identifier.
*/
+
CFLocaleRef localeRef;
if (CFLocaleCopyCurrent != NULL && CFLocaleGetIdentifier != NULL &&
@@ -806,68 +796,74 @@ TclpSetVariables(interp)
}
CFRelease(localeRef);
}
-#endif
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED > 1020 */
if (MacOSXGetLibraryPath(interp, MAXPATHLEN, tclLibPath) == TCL_OK) {
- CONST char *str;
- Tcl_DString ds;
- CFBundleRef bundleRef;
-
- Tcl_SetVar(interp, "tclDefaultLibrary", tclLibPath,
- TCL_GLOBAL_ONLY);
- Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath,
- TCL_GLOBAL_ONLY);
- Tcl_SetVar(interp, "tcl_pkgPath", " ",
- TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
- str = TclGetEnv("DYLD_FRAMEWORK_PATH", &ds);
- if ((str != NULL) && (str[0] != '\0')) {
- char *p = Tcl_DStringValue(&ds);
- /* convert DYLD_FRAMEWORK_PATH from colon to space separated */
- do {
- if(*p == ':') *p = ' ';
- } while (*p++);
- Tcl_SetVar(interp, "tcl_pkgPath", Tcl_DStringValue(&ds),
- TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
- Tcl_SetVar(interp, "tcl_pkgPath", " ",
- TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
- Tcl_DStringFree(&ds);
- }
- if ((bundleRef = CFBundleGetMainBundle())) {
- CFURLRef frameworksURL;
- Tcl_StatBuf statBuf;
- if((frameworksURL = CFBundleCopyPrivateFrameworksURL(bundleRef))) {
- if(CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
- (unsigned char*) tclLibPath, MAXPATHLEN) &&
- ! TclOSstat(tclLibPath, &statBuf) &&
- S_ISDIR(statBuf.st_mode)) {
- Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath,
- TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
- Tcl_SetVar(interp, "tcl_pkgPath", " ",
- TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
- }
- CFRelease(frameworksURL);
- }
- if((frameworksURL = CFBundleCopySharedFrameworksURL(bundleRef))) {
- if(CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
- (unsigned char*) tclLibPath, MAXPATHLEN) &&
- ! TclOSstat(tclLibPath, &statBuf) &&
- S_ISDIR(statBuf.st_mode)) {
- Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath,
- TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
- Tcl_SetVar(interp, "tcl_pkgPath", " ",
- TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
- }
- CFRelease(frameworksURL);
- }
- }
- Tcl_SetVar(interp, "tcl_pkgPath", pkgPath,
- TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ CONST char *str;
+ CFBundleRef bundleRef;
+
+ Tcl_SetVar(interp, "tclDefaultLibrary", tclLibPath, TCL_GLOBAL_ONLY);
+ Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath, TCL_GLOBAL_ONLY);
+ Tcl_SetVar(interp, "tcl_pkgPath", " ",
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+
+ str = TclGetEnv("DYLD_FRAMEWORK_PATH", &ds);
+ if ((str != NULL) && (str[0] != '\0')) {
+ char *p = Tcl_DStringValue(&ds);
+
+ /*
+ * Convert DYLD_FRAMEWORK_PATH from colon to space separated.
+ */
+
+ do {
+ if (*p == ':') {
+ *p = ' ';
+ }
+ } while (*p++);
+ Tcl_SetVar(interp, "tcl_pkgPath", Tcl_DStringValue(&ds),
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ Tcl_SetVar(interp, "tcl_pkgPath", " ",
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ Tcl_DStringFree(&ds);
+ }
+ bundleRef = CFBundleGetMainBundle();
+ if (bundleRef) {
+ CFURLRef frameworksURL;
+ Tcl_StatBuf statBuf;
+
+ frameworksURL = CFBundleCopyPrivateFrameworksURL(bundleRef);
+ if (frameworksURL) {
+ if (CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
+ (unsigned char*) tclLibPath, MAXPATHLEN) &&
+ ! TclOSstat(tclLibPath, &statBuf) &&
+ S_ISDIR(statBuf.st_mode)) {
+ Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath,
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ Tcl_SetVar(interp, "tcl_pkgPath", " ",
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ }
+ CFRelease(frameworksURL);
+ }
+ frameworksURL = CFBundleCopySharedFrameworksURL(bundleRef);
+ if (frameworksURL) {
+ if (CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
+ (unsigned char*) tclLibPath, MAXPATHLEN) &&
+ ! TclOSstat(tclLibPath, &statBuf) &&
+ S_ISDIR(statBuf.st_mode)) {
+ Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath,
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ Tcl_SetVar(interp, "tcl_pkgPath", " ",
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ }
+ CFRelease(frameworksURL);
+ }
+ }
+ Tcl_SetVar(interp, "tcl_pkgPath", pkgPath,
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
} else
#endif /* HAVE_COREFOUNDATION */
{
- Tcl_SetVar(interp, "tclDefaultLibrary", defaultLibraryDir,
- TCL_GLOBAL_ONLY);
- Tcl_SetVar(interp, "tcl_pkgPath", pkgPath, TCL_GLOBAL_ONLY);
+ Tcl_SetVar(interp, "tcl_pkgPath", pkgPath, TCL_GLOBAL_ONLY);
}
#ifdef DJGPP
@@ -875,23 +871,24 @@ TclpSetVariables(interp)
#else
Tcl_SetVar2(interp, "tcl_platform", "platform", "unix", TCL_GLOBAL_ONLY);
#endif
+
unameOK = 0;
#ifndef NO_UNAME
if (uname(&name) >= 0) {
CONST char *native;
-
+
unameOK = 1;
native = Tcl_ExternalToUtfDString(NULL, name.sysname, -1, &ds);
Tcl_SetVar2(interp, "tcl_platform", "os", native, TCL_GLOBAL_ONLY);
Tcl_DStringFree(&ds);
-
+
/*
- * The following code is a special hack to handle differences in
- * the way version information is returned by uname. On most
- * systems the full version number is available in name.release.
- * However, under AIX the major version number is in
- * name.version and the minor version number is in name.release.
+ * The following code is a special hack to handle differences in the
+ * way version information is returned by uname. On most systems the
+ * full version number is available in name.release. However, under
+ * AIX the major version number is in name.version and the minor
+ * version number is in name.release.
*/
if ((strchr(name.release, '.') != NULL)
@@ -899,17 +896,33 @@ TclpSetVariables(interp)
Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.release,
TCL_GLOBAL_ONLY);
} else {
+#ifdef DJGPP
+ /*
+ * For some obscure reason DJGPP puts major version into
+ * name.release and minor into name.version. As of DJGPP 2.04 this
+ * is documented in djgpp libc.info file.
+ */
+
+ Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.release,
+ TCL_GLOBAL_ONLY);
+ Tcl_SetVar2(interp, "tcl_platform", "osVersion", ".",
+ TCL_GLOBAL_ONLY|TCL_APPEND_VALUE);
+ Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.version,
+ TCL_GLOBAL_ONLY|TCL_APPEND_VALUE);
+#else
Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.version,
TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "tcl_platform", "osVersion", ".",
TCL_GLOBAL_ONLY|TCL_APPEND_VALUE);
Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.release,
TCL_GLOBAL_ONLY|TCL_APPEND_VALUE);
+
+#endif /* DJGPP */
}
Tcl_SetVar2(interp, "tcl_platform", "machine", name.machine,
TCL_GLOBAL_ONLY);
}
-#endif
+#endif /* !NO_UNAME */
if (!unameOK) {
Tcl_SetVar2(interp, "tcl_platform", "os", "", TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "tcl_platform", "osVersion", "", TCL_GLOBAL_ONLY);
@@ -917,20 +930,24 @@ TclpSetVariables(interp)
}
/*
- * Copy USER or LOGNAME environment variable into tcl_platform(user)
+ * Copy the username of the real user (according to getuid()) into
+ * tcl_platform(user).
*/
- Tcl_DStringInit(&ds);
- user = TclGetEnv("USER", &ds);
- if (user == NULL) {
- user = TclGetEnv("LOGNAME", &ds);
- if (user == NULL) {
+ {
+ struct passwd *pwEnt = TclpGetPwUid(getuid());
+ const char *user;
+
+ if (pwEnt == NULL) {
user = "";
+ Tcl_DStringInit(&ds); /* ensure cleanliness */
+ } else {
+ user = Tcl_ExternalToUtfDString(NULL, pwEnt->pw_name, -1, &ds);
}
- }
- Tcl_SetVar2(interp, "tcl_platform", "user", user, TCL_GLOBAL_ONLY);
- Tcl_DStringFree(&ds);
+ Tcl_SetVar2(interp, "tcl_platform", "user", user, TCL_GLOBAL_ONLY);
+ Tcl_DStringFree(&ds);
+ }
}
/*
@@ -938,15 +955,14 @@ TclpSetVariables(interp)
*
* TclpFindVariable --
*
- * Locate the entry in environ for a given name. On Unix this
- * routine is case sensetive, on Windows this matches mixed case.
+ * Locate the entry in environ for a given name. On Unix this routine is
+ * case sensetive, on Windows this matches mixed case.
*
* Results:
- * The return value is the index in environ of an entry with the
- * name "name", or -1 if there is no such entry. The integer at
- * *lengthPtr is filled in with the length of name (if a matching
- * entry is found) or the length of the environ array (if no matching
- * entry is found).
+ * The return value is the index in environ of an entry with the name
+ * "name", or -1 if there is no such entry. The integer at *lengthPtr is
+ * filled in with the length of name (if a matching entry is found) or
+ * the length of the environ array (if no matching entry is found).
*
* Side effects:
* None.
@@ -955,10 +971,10 @@ TclpSetVariables(interp)
*/
int
-TclpFindVariable(name, lengthPtr)
- CONST char *name; /* Name of desired environment variable
+TclpFindVariable(
+ CONST char *name, /* Name of desired environment variable
* (native). */
- int *lengthPtr; /* Used to return length of name (for
+ int *lengthPtr) /* Used to return length of name (for
* successful searches) or number of non-NULL
* entries in environ (for unsuccessful
* searches). */
@@ -980,155 +996,231 @@ TclpFindVariable(name, lengthPtr)
result = i;
goto done;
}
-
+
Tcl_DStringFree(&envString);
}
-
+
*lengthPtr = i;
- done:
+ done:
Tcl_DStringFree(&envString);
return result;
}
+#ifndef TCL_NO_STACK_CHECK
/*
*----------------------------------------------------------------------
*
- * Tcl_Init --
+ * TclpGetCStackParams --
*
- * This procedure is typically invoked by Tcl_AppInit procedures
- * to find and source the "init.tcl" script, which should exist
- * somewhere on the Tcl library path.
+ * Determine the stack params for the current thread: in which
+ * direction does the stack grow, and what is the stack lower (resp.
+ * upper) bound for safe invocation of a new command? This is used to
+ * cache the values needed for an efficient computation of
+ * TclpCheckStackSpace() when the interp is known.
*
* Results:
- * Returns a standard Tcl completion code and sets the interp's
- * result if there is an error.
- *
- * Side effects:
- * Depends on what's in the init.tcl script.
+ * Returns 1 if the stack grows down, in which case a stack lower bound
+ * is stored at stackBoundPtr. If the stack grows up, 0 is returned and
+ * an upper bound is stored at stackBoundPtr. If a bound cannot be
+ * determined NULL is stored at stackBoundPtr.
*
*----------------------------------------------------------------------
*/
int
-Tcl_Init(interp)
- Tcl_Interp *interp; /* Interpreter to initialize. */
+TclpGetCStackParams(
+ int **stackBoundPtr)
{
- Tcl_Obj *pathPtr;
+ int result = TCL_OK;
+ size_t stackSize = 0; /* The size of the current stack. */
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ /* Most variables are actually in a
+ * thread-specific data block to minimise the
+ * impact on the stack. */
+#ifdef TCL_CROSS_COMPILE
+ if (stackGrowsDown == -1) {
+ /*
+ * Not initialised!
+ */
- if (tclPreInitScript != NULL) {
- if (Tcl_Eval(interp, tclPreInitScript) == TCL_ERROR) {
- return (TCL_ERROR);
- };
+ stackGrowsDown = StackGrowsDown(&result);
}
+#endif
- pathPtr = TclGetLibraryPath();
- if (pathPtr == NULL) {
- pathPtr = Tcl_NewObj();
- }
- Tcl_IncrRefCount(pathPtr);
- Tcl_SetVar2Ex(interp, "tcl_libPath", NULL, pathPtr, TCL_GLOBAL_ONLY);
- Tcl_DecrRefCount(pathPtr);
- return Tcl_Eval(interp, initScript);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_SourceRCFile --
- *
- * This procedure is typically invoked by Tcl_Main of Tk_Main
- * procedure to source an application specific rc file into the
- * interpreter at startup time.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Depends on what's in the rc script.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tcl_SourceRCFile(interp)
- Tcl_Interp *interp; /* Interpreter to source rc file into. */
-{
- Tcl_DString temp;
- CONST char *fileName;
- Tcl_Channel errChannel;
-
- fileName = Tcl_GetVar(interp, "tcl_rcFileName", TCL_GLOBAL_ONLY);
+ /*
+ * The first time through in a thread: record the "outermost" stack
+ * frame and inquire with the OS about the stack size.
+ */
- if (fileName != NULL) {
- Tcl_Channel c;
- CONST char *fullName;
+ if (tsdPtr->outerVarPtr == NULL) {
+ tsdPtr->outerVarPtr = &result;
+ result = GetStackSize(&stackSize);
+ if (result != TCL_OK) {
+ /* Can't check, assume it always succeeds */
+#ifdef TCL_CROSS_COMPILE
+ stackGrowsDown = 1;
+#endif
+ tsdPtr->stackBound = NULL;
+ goto done;
+ }
+ }
- Tcl_DStringInit(&temp);
- fullName = Tcl_TranslateFileName(interp, fileName, &temp);
- if (fullName == NULL) {
- /*
- * Couldn't translate the file name (e.g. it referred to a
- * bogus user or there was no HOME environment variable).
- * Just do nothing.
- */
- } else {
+ if (stackSize || (tsdPtr->stackBound &&
+ ((stackGrowsDown && (&result < tsdPtr->stackBound)) ||
+ (!stackGrowsDown && (&result > tsdPtr->stackBound))))) {
+ /*
+ * Either the thread's first pass or stack failure: set the params
+ */
+ if (!stackSize) {
/*
- * Test for the existence of the rc file before trying to read it.
+ * Stack failure: if we didn't already blow up, we are within the
+ * safety area. Recheck with the OS in case the stack was grown.
*/
+ result = GetStackSize(&stackSize);
+ if (result != TCL_OK) {
+ /* Can't check, assume it always succeeds */
+#ifdef TCL_CROSS_COMPILE
+ stackGrowsDown = 1;
+#endif
+ tsdPtr->stackBound = NULL;
+ goto done;
+ }
+ }
- c = Tcl_OpenFileChannel(NULL, fullName, "r", 0);
- if (c != (Tcl_Channel) NULL) {
- Tcl_Close(NULL, c);
- if (Tcl_EvalFile(interp, fullName) != TCL_OK) {
- errChannel = Tcl_GetStdChannel(TCL_STDERR);
- if (errChannel) {
- Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
- Tcl_WriteChars(errChannel, "\n", 1);
- }
- }
+ if (stackGrowsDown) {
+ tsdPtr->stackBound = (int *) ((char *)tsdPtr->outerVarPtr -
+ stackSize);
+ if (tsdPtr->stackBound > tsdPtr->outerVarPtr) {
+ /* Overflow, that should never happen, just set it to NULL.
+ * See [Bug #3166410] */
+ tsdPtr->stackBound = NULL;
+ }
+ } else {
+ tsdPtr->stackBound = (int *) ((char *)tsdPtr->outerVarPtr +
+ stackSize);
+ if (tsdPtr->stackBound < tsdPtr->outerVarPtr) {
+ /* Overflow, that should never happen, just set it to NULL.
+ * See [Bug #3166410] */
+ tsdPtr->stackBound = NULL;
}
}
- Tcl_DStringFree(&temp);
}
+
+ done:
+ *stackBoundPtr = tsdPtr->stackBound;
+ return stackGrowsDown;
+}
+
+#ifdef TCL_CROSS_COMPILE
+int
+StackGrowsDown(
+ int *parent)
+{
+ int here;
+ return (&here < parent);
}
+#endif
/*
*----------------------------------------------------------------------
*
- * TclpCheckStackSpace --
+ * GetStackSize --
*
- * Detect if we are about to blow the stack. Called before an
- * evaluation can happen when nesting depth is checked.
+ * Discover what the stack size for the current thread/process actually
+ * is. Expects to only ever be called once per thread and then only at a
+ * point when there is a reasonable amount of space left on the current
+ * stack; TclpCheckStackSpace is called sufficiently frequently that that
+ * is true.
*
* Results:
- * 1 if there is enough stack space to continue; 0 if not.
+ * TCL_OK if the stack space was discovered, TCL_BREAK if the stack space
+ * was undiscoverable in a way that stack checks should fail, and
+ * TCL_CONTINUE if the stack space was undiscoverable in a way that stack
+ * checks should succeed.
*
* Side effects:
- * None.
+ * None
*
*----------------------------------------------------------------------
*/
-int
-TclpCheckStackSpace()
+static int
+GetStackSize(
+ size_t *stackSizePtr)
{
+ size_t rawStackSize;
+ struct rlimit rLimit; /* The result from getrlimit(). */
+
+#ifdef TCL_THREADS
+ rawStackSize = TclpThreadGetStackSize();
+ if (rawStackSize == (size_t) -1) {
+ /*
+ * Some kind of confirmed error in TclpThreadGetStackSize?! Fall back
+ * to whatever getrlimit can determine.
+ */
+ STACK_DEBUG(("stack checks: TclpThreadGetStackSize failed in \n"));
+ }
+ if (rawStackSize > 0) {
+ goto finalSanityCheck;
+ }
+
/*
- * This function is unimplemented on Unix platforms.
+ * If we have zero or an error, try the system limits instead. After all,
+ * the pthread documentation states that threads should always be bound by
+ * the system stack size limit in any case.
*/
+#endif /* TCL_THREADS */
- return 1;
+ if (getrlimit(RLIMIT_STACK, &rLimit) != 0) {
+ /*
+ * getrlimit() failed, just fail the whole thing.
+ */
+ STACK_DEBUG(("skipping stack checks with failure: getrlimit failed\n"));
+ return TCL_BREAK;
+ }
+ if (rLimit.rlim_cur == RLIM_INFINITY) {
+ /*
+ * Limit is "infinite"; there is no stack limit.
+ */
+ STACK_DEBUG(("skipping stack checks with success: infinite limit\n"));
+ return TCL_CONTINUE;
+ }
+ rawStackSize = rLimit.rlim_cur;
+
+ /*
+ * Final sanity check on the determined stack size. If we fail this,
+ * assume there are bogus values about and that we can't actually figure
+ * out what the stack size really is.
+ */
+
+#ifdef TCL_THREADS /* Stop warning... */
+ finalSanityCheck:
+#endif
+ if (rawStackSize <= 0) {
+ STACK_DEBUG(("skipping stack checks with success\n"));
+ return TCL_CONTINUE;
+ }
+
+ /*
+ * Calculate a stack size with a safety margin.
+ */
+
+ *stackSizePtr = (rawStackSize / TCL_MAGIC_STACK_DIVISOR)
+ - (getpagesize() * TCL_RESERVED_STACK_PAGES);
+
+ return TCL_OK;
}
+#endif /* TCL_NO_STACK_CHECK */
/*
*----------------------------------------------------------------------
*
* MacOSXGetLibraryPath --
*
- * If we have a bundle structure for the Tcl installation,
- * then check there first to see if we can find the libraries
- * there.
+ * If we have a bundle structure for the Tcl installation, then check
+ * there first to see if we can find the libraries there.
*
* Results:
* TCL_OK if we have found the tcl library; TCL_ERROR otherwise.
@@ -1141,13 +1233,27 @@ TclpCheckStackSpace()
#ifdef HAVE_COREFOUNDATION
static int
-MacOSXGetLibraryPath(Tcl_Interp *interp, int maxPathLen, char *tclLibPath)
+MacOSXGetLibraryPath(
+ Tcl_Interp *interp,
+ int maxPathLen,
+ char *tclLibPath)
{
int foundInFramework = TCL_ERROR;
+
#ifdef TCL_FRAMEWORK
- foundInFramework = Tcl_MacOSXOpenVersionedBundleResources(interp,
- "com.tcltk.tcllibrary", TCL_FRAMEWORK_VERSION, 0, maxPathLen, tclLibPath);
+ foundInFramework = Tcl_MacOSXOpenVersionedBundleResources(interp,
+ "com.tcltk.tcllibrary", TCL_FRAMEWORK_VERSION, 0, maxPathLen,
+ tclLibPath);
#endif
+
return foundInFramework;
}
#endif /* HAVE_COREFOUNDATION */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixNotfy.c b/unix/tclUnixNotfy.c
index 0af7207..e7bf78d 100644
--- a/unix/tclUnixNotfy.c
+++ b/unix/tclUnixNotfy.c
@@ -1,63 +1,65 @@
/*
* tclUnixNotify.c --
*
- * This file contains the implementation of the select-based
- * Unix-specific notifier, which is the lowest-level part of the
- * Tcl event loop. This file works together with
- * ../generic/tclNotify.c.
+ * This file contains the implementation of the select()-based
+ * Unix-specific notifier, which is the lowest-level part of the Tcl
+ * event loop. This file works together with generic/tclNotify.c.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
-#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier
- * is in tclMacOSXNotify.c */
-#include <signal.h>
+#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is
+ * in tclMacOSXNotify.c */
+#include <signal.h>
+
+/*
+ * This code does deep stub magic to allow replacement of the notifier at
+ * runtime.
+ */
extern TclStubs tclStubs;
extern Tcl_NotifierProcs tclOriginalNotifier;
/*
- * This structure is used to keep track of the notifier info for a
- * a registered file.
+ * This structure is used to keep track of the notifier info for a registered
+ * file.
*/
typedef struct FileHandler {
int fd;
int mask; /* Mask of desired events: TCL_READABLE,
* etc. */
- int readyMask; /* Mask of events that have been seen since the
- * last time file handlers were invoked for
- * this file. */
- Tcl_FileProc *proc; /* Procedure to call, in the style of
+ int readyMask; /* Mask of events that have been seen since
+ * the last time file handlers were invoked
+ * for this file. */
+ Tcl_FileProc *proc; /* Function to call, in the style of
* Tcl_CreateFileHandler. */
ClientData clientData; /* Argument to pass to proc. */
struct FileHandler *nextPtr;/* Next in list of all files we care about. */
} FileHandler;
/*
- * The following structure is what is added to the Tcl event queue when
- * file handlers are ready to fire.
+ * The following structure is what is added to the Tcl event queue when file
+ * handlers are ready to fire.
*/
typedef struct FileHandlerEvent {
- Tcl_Event header; /* Information that is standard for
- * all events. */
- int fd; /* File descriptor that is ready. Used
- * to find the FileHandler structure for
- * the file (can't point directly to the
- * FileHandler structure because it could
- * go away while the event is queued). */
+ Tcl_Event header; /* Information that is standard for all
+ * events. */
+ int fd; /* File descriptor that is ready. Used to find
+ * the FileHandler structure for the file
+ * (can't point directly to the FileHandler
+ * structure because it could go away while
+ * the event is queued). */
} FileHandlerEvent;
/*
- *
- * The following structure contains a set of select() masks to track
- * readable, writable, and exceptional conditions.
+ * The following structure contains a set of select() masks to track readable,
+ * writable, and exceptional conditions.
*/
typedef struct SelectMasks {
@@ -68,42 +70,41 @@ typedef struct SelectMasks {
/*
* The following static structure contains the state information for the
- * select based implementation of the Tcl notifier. One of these structures
- * is created for each thread that is using the notifier.
+ * select based implementation of the Tcl notifier. One of these structures is
+ * created for each thread that is using the notifier.
*/
typedef struct ThreadSpecificData {
FileHandler *firstFileHandlerPtr;
/* Pointer to head of file handler list. */
-
- SelectMasks checkMasks; /* This structure is used to build up the masks
- * to be used in the next call to select.
- * Bits are set in response to calls to
- * Tcl_CreateFileHandler. */
+ SelectMasks checkMasks; /* This structure is used to build up the
+ * masks to be used in the next call to
+ * select. Bits are set in response to calls
+ * to Tcl_CreateFileHandler. */
SelectMasks readyMasks; /* This array reflects the readable/writable
* conditions that were found to exist by the
* last call to select. */
- int numFdBits; /* Number of valid bits in checkMasks
- * (one more than highest fd for which
+ int numFdBits; /* Number of valid bits in checkMasks (one
+ * more than highest fd for which
* Tcl_WatchFile has been called). */
#ifdef TCL_THREADS
int onList; /* True if it is in this list */
- unsigned int pollState; /* pollState is used to implement a polling
+ unsigned int pollState; /* pollState is used to implement a polling
* handshake between each thread and the
* notifier thread. Bits defined below. */
struct ThreadSpecificData *nextPtr, *prevPtr;
- /* All threads that are currently waiting on
- * an event have their ThreadSpecificData
- * structure on a doubly-linked listed formed
- * from these pointers. You must hold the
- * notifierMutex lock before accessing these
- * fields. */
- Tcl_Condition waitCV; /* Any other thread alerts a notifier
- * that an event is ready to be processed
- * by signaling this condition variable. */
- int eventReady; /* True if an event is ready to be processed.
- * Used as condition flag together with
- * waitCV above. */
+ /* All threads that are currently waiting on
+ * an event have their ThreadSpecificData
+ * structure on a doubly-linked listed formed
+ * from these pointers. You must hold the
+ * notifierMutex lock before accessing these
+ * fields. */
+ Tcl_Condition waitCV; /* Any other thread alerts a notifier that an
+ * event is ready to be processed by signaling
+ * this condition variable. */
+ int eventReady; /* True if an event is ready to be processed.
+ * Used as condition flag together with waitCV
+ * above. */
#endif
} ThreadSpecificData;
@@ -111,8 +112,8 @@ static Tcl_ThreadDataKey dataKey;
#ifdef TCL_THREADS
/*
- * The following static indicates the number of threads that have
- * initialized notifiers.
+ * The following static indicates the number of threads that have initialized
+ * notifiers.
*
* You must hold the notifierMutex lock before accessing this variable.
*/
@@ -120,9 +121,9 @@ static Tcl_ThreadDataKey dataKey;
static int notifierCount = 0;
/*
- * The following variable points to the head of a doubly-linked list of
- * of ThreadSpecificData structures for all threads that are currently
- * waiting on an event.
+ * The following variable points to the head of a doubly-linked list of
+ * ThreadSpecificData structures for all threads that are currently waiting on
+ * an event.
*
* You must hold the notifierMutex lock before accessing this list.
*/
@@ -130,32 +131,31 @@ static int notifierCount = 0;
static ThreadSpecificData *waitingListPtr = NULL;
/*
- * The notifier thread spends all its time in select() waiting for a
- * file descriptor associated with one of the threads on the waitingListPtr
- * list to do something interesting. But if the contents of the
- * waitingListPtr list ever changes, we need to wake up and restart
- * the select() system call. You can wake up the notifier thread by
- * writing a single byte to the file descriptor defined below. This
- * file descriptor is the input-end of a pipe and the notifier thread is
- * listening for data on the output-end of the same pipe. Hence writing
- * to this file descriptor will cause the select() system call to return
- * and wake up the notifier thread.
+ * The notifier thread spends all its time in select() waiting for a file
+ * descriptor associated with one of the threads on the waitingListPtr list to
+ * do something interesting. But if the contents of the waitingListPtr list
+ * ever changes, we need to wake up and restart the select() system call. You
+ * can wake up the notifier thread by writing a single byte to the file
+ * descriptor defined below. This file descriptor is the input-end of a pipe
+ * and the notifier thread is listening for data on the output-end of the same
+ * pipe. Hence writing to this file descriptor will cause the select() system
+ * call to return and wake up the notifier thread.
*
- * You must hold the notifierMutex lock before accessing this list.
+ * You must hold the notifierMutex lock before writing to the pipe.
*/
static int triggerPipe = -1;
/*
- * The notifierMutex locks access to all of the global notifier state.
+ * The notifierMutex locks access to all of the global notifier state.
*/
TCL_DECLARE_MUTEX(notifierMutex)
/*
* The notifier thread signals the notifierCV when it has finished
- * initializing the triggerPipe and right before the notifier
- * thread terminates.
+ * initializing the triggerPipe and right before the notifier thread
+ * terminates.
*/
static Tcl_Condition notifierCV;
@@ -163,18 +163,19 @@ static Tcl_Condition notifierCV;
/*
* The pollState bits
* POLL_WANT is set by each thread before it waits on its condition
- * variable. It is checked by the notifier before it does
- * select.
- * POLL_DONE is set by the notifier if it goes into select after
- * seeing POLL_WANT. The idea is to ensure it tries a select
- * with the same bits the initial thread had set.
+ * variable. It is checked by the notifier before it does select.
+ * POLL_DONE is set by the notifier if it goes into select after seeing
+ * POLL_WANT. The idea is to ensure it tries a select with the
+ * same bits the initial thread had set.
*/
+
#define POLL_WANT 0x1
#define POLL_DONE 0x2
/*
* This is the thread ID of the notifier thread that does select.
*/
+
static Tcl_ThreadId notifierThread;
#endif
@@ -184,10 +185,9 @@ static Tcl_ThreadId notifierThread;
*/
#ifdef TCL_THREADS
-static void NotifierThreadProc _ANSI_ARGS_((ClientData clientData));
+static void NotifierThreadProc(ClientData clientData);
#endif
-static int FileHandlerEventProc _ANSI_ARGS_((Tcl_Event *evPtr,
- int flags));
+static int FileHandlerEventProc(Tcl_Event *evPtr, int flags);
/*
*----------------------------------------------------------------------
@@ -197,7 +197,7 @@ static int FileHandlerEventProc _ANSI_ARGS_((Tcl_Event *evPtr,
* Initializes the platform specific notifier state.
*
* Results:
- * Returns a handle to the notifier state for this thread..
+ * Returns a handle to the notifier state for this thread.
*
* Side effects:
* None.
@@ -206,7 +206,7 @@ static int FileHandlerEventProc _ANSI_ARGS_((Tcl_Event *evPtr,
*/
ClientData
-Tcl_InitNotifier()
+Tcl_InitNotifier(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -220,8 +220,8 @@ Tcl_InitNotifier()
Tcl_MutexLock(&notifierMutex);
if (notifierCount == 0) {
if (TclpThreadCreate(&notifierThread, NotifierThreadProc, NULL,
- TCL_THREAD_STACK_DEFAULT, TCL_THREAD_JOINABLE) != TCL_OK) {
- panic("Tcl_InitNotifier: unable to start notifier thread");
+ TCL_THREAD_STACK_DEFAULT, TCL_THREAD_JOINABLE) != TCL_OK) {
+ Tcl_Panic("Tcl_InitNotifier: unable to start notifier thread");
}
}
notifierCount++;
@@ -244,22 +244,22 @@ Tcl_InitNotifier()
*
* Tcl_FinalizeNotifier --
*
- * This function is called to cleanup the notifier state before
- * a thread is terminated.
+ * This function is called to cleanup the notifier state before a thread
+ * is terminated.
*
* Results:
* None.
*
* Side effects:
- * May terminate the background notifier thread if this is the
- * last notifier instance.
+ * May terminate the background notifier thread if this is the last
+ * notifier instance.
*
*----------------------------------------------------------------------
*/
void
-Tcl_FinalizeNotifier(clientData)
- ClientData clientData; /* Not used. */
+Tcl_FinalizeNotifier(
+ ClientData clientData) /* Not used. */
{
#ifdef TCL_THREADS
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -268,32 +268,36 @@ Tcl_FinalizeNotifier(clientData)
notifierCount--;
/*
- * If this is the last thread to use the notifier, close the notifier
- * pipe and wait for the background thread to terminate.
+ * If this is the last thread to use the notifier, close the notifier pipe
+ * and wait for the background thread to terminate.
*/
if (notifierCount == 0) {
int result;
+
if (triggerPipe < 0) {
- panic("Tcl_FinalizeNotifier: notifier pipe not initialized");
+ Tcl_Panic("Tcl_FinalizeNotifier: notifier pipe not initialized");
}
/*
- * Send "q" message to the notifier thread so that it will
- * terminate. The notifier will return from its call to select()
- * and notice that a "q" message has arrived, it will then close
- * its side of the pipe and terminate its thread. Note the we can
- * not just close the pipe and check for EOF in the notifier
- * thread because if a background child process was created with
- * exec, select() would not register the EOF on the pipe until the
- * child processes had terminated. [Bug: 4139] [Bug: 1222872]
+ * Send "q" message to the notifier thread so that it will terminate.
+ * The notifier will return from its call to select() and notice that
+ * a "q" message has arrived, it will then close its side of the pipe
+ * and terminate its thread. Note the we can not just close the pipe
+ * and check for EOF in the notifier thread because if a background
+ * child process was created with exec, select() would not register
+ * the EOF on the pipe until the child processes had terminated. [Bug:
+ * 4139] [Bug: 1222872]
*/
- write(triggerPipe, "q", 1);
+ if (write(triggerPipe, "q", 1) != 1) {
+ Tcl_Panic("Tcl_FinalizeNotifier: unable to write q to triggerPipe");
+ }
close(triggerPipe);
while(triggerPipe >= 0) {
Tcl_ConditionWait(&notifierCV, &notifierMutex, NULL);
}
+
result = Tcl_JoinThread(notifierThread, NULL);
if (result) {
Tcl_Panic("Tcl_FinalizeNotifier: unable to join notifier thread");
@@ -315,25 +319,23 @@ Tcl_FinalizeNotifier(clientData)
*
* Tcl_AlertNotifier --
*
- * Wake up the specified notifier from any thread. This routine
- * is called by the platform independent notifier code whenever
- * the Tcl_ThreadAlert routine is called. This routine is
- * guaranteed not to be called on a given notifier after
- * Tcl_FinalizeNotifier is called for that notifier.
+ * Wake up the specified notifier from any thread. This routine is called
+ * by the platform independent notifier code whenever the Tcl_ThreadAlert
+ * routine is called. This routine is guaranteed not to be called on a
+ * given notifier after Tcl_FinalizeNotifier is called for that notifier.
*
* Results:
* None.
*
* Side effects:
- * Signals the notifier condition variable for the specified
- * notifier.
+ * Signals the notifier condition variable for the specified notifier.
*
*----------------------------------------------------------------------
*/
void
-Tcl_AlertNotifier(clientData)
- ClientData clientData;
+Tcl_AlertNotifier(
+ ClientData clientData)
{
#ifdef TCL_THREADS
ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;
@@ -349,9 +351,9 @@ Tcl_AlertNotifier(clientData)
*
* Tcl_SetTimer --
*
- * This procedure sets the current notifier timer value. This
- * interface is not implemented in this notifier because we are
- * always running inside of Tcl_DoOneEvent.
+ * This function sets the current notifier timer value. This interface is
+ * not implemented in this notifier because we are always running inside
+ * of Tcl_DoOneEvent.
*
* Results:
* None.
@@ -363,13 +365,13 @@ Tcl_AlertNotifier(clientData)
*/
void
-Tcl_SetTimer(timePtr)
- Tcl_Time *timePtr; /* Timeout value, may be NULL. */
+Tcl_SetTimer(
+ Tcl_Time *timePtr) /* Timeout value, may be NULL. */
{
/*
- * The interval timer doesn't do anything in this implementation,
- * because the only event loop is via Tcl_DoOneEvent, which passes
- * timeout values to Tcl_WaitForEvent.
+ * The interval timer doesn't do anything in this implementation, because
+ * the only event loop is via Tcl_DoOneEvent, which passes timeout values
+ * to Tcl_WaitForEvent.
*/
if (tclStubs.tcl_SetTimer != tclOriginalNotifier.setTimerProc) {
@@ -394,8 +396,8 @@ Tcl_SetTimer(timePtr)
*/
void
-Tcl_ServiceModeHook(mode)
- int mode; /* Either TCL_SERVICE_ALL, or
+Tcl_ServiceModeHook(
+ int mode) /* Either TCL_SERVICE_ALL, or
* TCL_SERVICE_NONE. */
{
}
@@ -405,7 +407,7 @@ Tcl_ServiceModeHook(mode)
*
* Tcl_CreateFileHandler --
*
- * This procedure registers a file handler with the select notifier.
+ * This function registers a file handler with the select notifier.
*
* Results:
* None.
@@ -417,26 +419,27 @@ Tcl_ServiceModeHook(mode)
*/
void
-Tcl_CreateFileHandler(fd, mask, proc, clientData)
- int fd; /* Handle of stream to watch. */
- int mask; /* OR'ed combination of TCL_READABLE,
- * TCL_WRITABLE, and TCL_EXCEPTION:
- * indicates conditions under which
- * proc should be called. */
- Tcl_FileProc *proc; /* Procedure to call for each
- * selected event. */
- ClientData clientData; /* Arbitrary data to pass to proc. */
+Tcl_CreateFileHandler(
+ int fd, /* Handle of stream to watch. */
+ int mask, /* OR'ed combination of TCL_READABLE,
+ * TCL_WRITABLE, and TCL_EXCEPTION: indicates
+ * conditions under which proc should be
+ * called. */
+ Tcl_FileProc *proc, /* Function to call for each selected
+ * event. */
+ ClientData clientData) /* Arbitrary data to pass to proc. */
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
FileHandler *filePtr;
- if (tclStubs.tcl_CreateFileHandler != tclOriginalNotifier.createFileHandlerProc) {
+ if (tclStubs.tcl_CreateFileHandler !=
+ tclOriginalNotifier.createFileHandlerProc) {
tclStubs.tcl_CreateFileHandler(fd, mask, proc, clientData);
return;
}
for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
- filePtr = filePtr->nextPtr) {
+ filePtr = filePtr->nextPtr) {
if (filePtr->fd == fd) {
break;
}
@@ -456,20 +459,20 @@ Tcl_CreateFileHandler(fd, mask, proc, clientData)
* Update the check masks for this file.
*/
- if ( mask & TCL_READABLE ) {
- FD_SET( fd, &(tsdPtr->checkMasks.readable) );
+ if (mask & TCL_READABLE) {
+ FD_SET(fd, &(tsdPtr->checkMasks.readable));
} else {
- FD_CLR( fd, &(tsdPtr->checkMasks.readable) );
+ FD_CLR(fd, &(tsdPtr->checkMasks.readable));
}
- if ( mask & TCL_WRITABLE ) {
- FD_SET( fd, &(tsdPtr->checkMasks.writable) );
+ if (mask & TCL_WRITABLE) {
+ FD_SET(fd, &(tsdPtr->checkMasks.writable));
} else {
- FD_CLR( fd, &(tsdPtr->checkMasks.writable) );
+ FD_CLR(fd, &(tsdPtr->checkMasks.writable));
}
- if ( mask & TCL_EXCEPTION ) {
- FD_SET( fd, &(tsdPtr->checkMasks.exceptional) );
+ if (mask & TCL_EXCEPTION) {
+ FD_SET(fd, &(tsdPtr->checkMasks.exceptional));
} else {
- FD_CLR( fd, &(tsdPtr->checkMasks.exceptional) );
+ FD_CLR(fd, &(tsdPtr->checkMasks.exceptional));
}
if (tsdPtr->numFdBits <= fd) {
tsdPtr->numFdBits = fd+1;
@@ -481,8 +484,7 @@ Tcl_CreateFileHandler(fd, mask, proc, clientData)
*
* Tcl_DeleteFileHandler --
*
- * Cancel a previously-arranged callback arrangement for
- * a file.
+ * Cancel a previously-arranged callback arrangement for a file.
*
* Results:
* None.
@@ -494,14 +496,16 @@ Tcl_CreateFileHandler(fd, mask, proc, clientData)
*/
void
-Tcl_DeleteFileHandler(fd)
- int fd; /* Stream id for which to remove callback procedure. */
+Tcl_DeleteFileHandler(
+ int fd) /* Stream id for which to remove callback
+ * function. */
{
FileHandler *filePtr, *prevPtr;
int i;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- if (tclStubs.tcl_DeleteFileHandler != tclOriginalNotifier.deleteFileHandlerProc) {
+ if (tclStubs.tcl_DeleteFileHandler !=
+ tclOriginalNotifier.deleteFileHandlerProc) {
tclStubs.tcl_DeleteFileHandler(fd);
return;
}
@@ -525,13 +529,13 @@ Tcl_DeleteFileHandler(fd)
*/
if (filePtr->mask & TCL_READABLE) {
- FD_CLR( fd, &(tsdPtr->checkMasks.readable) );
+ FD_CLR(fd, &(tsdPtr->checkMasks.readable));
}
if (filePtr->mask & TCL_WRITABLE) {
- FD_CLR( fd, &(tsdPtr->checkMasks.writable) );
+ FD_CLR(fd, &(tsdPtr->checkMasks.writable));
}
if (filePtr->mask & TCL_EXCEPTION) {
- FD_CLR( fd, &(tsdPtr->checkMasks.exceptional) );
+ FD_CLR(fd, &(tsdPtr->checkMasks.exceptional));
}
/*
@@ -539,15 +543,17 @@ Tcl_DeleteFileHandler(fd)
*/
if (fd+1 == tsdPtr->numFdBits) {
- tsdPtr->numFdBits = 0;
+ int numFdBits = 0;
+
for (i = fd-1; i >= 0; i--) {
- if ( FD_ISSET( i, &(tsdPtr->checkMasks.readable) )
- || FD_ISSET( i, &(tsdPtr->checkMasks.writable) )
- || FD_ISSET( i, &(tsdPtr->checkMasks.exceptional ) ) ) {
- tsdPtr->numFdBits = i+1;
+ if (FD_ISSET(i, &(tsdPtr->checkMasks.readable))
+ || FD_ISSET(i, &(tsdPtr->checkMasks.writable))
+ || FD_ISSET(i, &(tsdPtr->checkMasks.exceptional))) {
+ numFdBits = i+1;
break;
}
}
+ tsdPtr->numFdBits = numFdBits;
}
/*
@@ -567,28 +573,28 @@ Tcl_DeleteFileHandler(fd)
*
* FileHandlerEventProc --
*
- * This procedure is called by Tcl_ServiceEvent when a file event
- * reaches the front of the event queue. This procedure is
- * responsible for actually handling the event by invoking the
- * callback for the file handler.
+ * This function is called by Tcl_ServiceEvent when a file event reaches
+ * the front of the event queue. This function is responsible for
+ * actually handling the event by invoking the callback for the file
+ * handler.
*
* Results:
- * Returns 1 if the event was handled, meaning it should be removed
- * from the queue. Returns 0 if the event was not handled, meaning
- * it should stay on the queue. The only time the event isn't
- * handled is if the TCL_FILE_EVENTS flag bit isn't set.
+ * Returns 1 if the event was handled, meaning it should be removed from
+ * the queue. Returns 0 if the event was not handled, meaning it should
+ * stay on the queue. The only time the event isn't handled is if the
+ * TCL_FILE_EVENTS flag bit isn't set.
*
* Side effects:
- * Whatever the file handler's callback procedure does.
+ * Whatever the file handler's callback function does.
*
*----------------------------------------------------------------------
*/
static int
-FileHandlerEventProc(evPtr, flags)
- Tcl_Event *evPtr; /* Event to service. */
- int flags; /* Flags that indicate what events to
- * handle, such as TCL_FILE_EVENTS. */
+FileHandlerEventProc(
+ Tcl_Event *evPtr, /* Event to service. */
+ int flags) /* Flags that indicate what events to handle,
+ * such as TCL_FILE_EVENTS. */
{
int mask;
FileHandler *filePtr;
@@ -601,28 +607,28 @@ FileHandlerEventProc(evPtr, flags)
/*
* Search through the file handlers to find the one whose handle matches
- * the event. We do this rather than keeping a pointer to the file
- * handler directly in the event, so that the handler can be deleted
- * while the event is queued without leaving a dangling pointer.
+ * the event. We do this rather than keeping a pointer to the file handler
+ * directly in the event, so that the handler can be deleted while the
+ * event is queued without leaving a dangling pointer.
*/
tsdPtr = TCL_TSD_INIT(&dataKey);
for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
- filePtr = filePtr->nextPtr) {
+ filePtr = filePtr->nextPtr) {
if (filePtr->fd != fileEvPtr->fd) {
continue;
}
/*
* The code is tricky for two reasons:
- * 1. The file handler's desired events could have changed
- * since the time when the event was queued, so AND the
- * ready mask with the desired mask.
- * 2. The file could have been closed and re-opened since
- * the time when the event was queued. This is why the
- * ready mask is stored in the file handler rather than
- * the queued event: it will be zeroed when a new
- * file handler is created for the newly opened file.
+ * 1. The file handler's desired events could have changed since the
+ * time when the event was queued, so AND the ready mask with the
+ * desired mask.
+ * 2. The file could have been closed and re-opened since the time
+ * when the event was queued. This is why the ready mask is stored
+ * in the file handler rather than the queued event: it will be
+ * zeroed when a new file handler is created for the newly opened
+ * file.
*/
mask = filePtr->readyMask & filePtr->mask;
@@ -640,13 +646,12 @@ FileHandlerEventProc(evPtr, flags)
*
* Tcl_WaitForEvent --
*
- * This function is called by Tcl_DoOneEvent to wait for new
- * events on the message queue. If the block time is 0, then
- * Tcl_WaitForEvent just polls without blocking.
+ * This function is called by Tcl_DoOneEvent to wait for new events on
+ * the message queue. If the block time is 0, then Tcl_WaitForEvent just
+ * polls without blocking.
*
* Results:
- * Returns -1 if the select would block forever, otherwise
- * returns 0.
+ * Returns -1 if the select would block forever, otherwise returns 0.
*
* Side effects:
* Queues file events that are detected by the select.
@@ -655,53 +660,66 @@ FileHandlerEventProc(evPtr, flags)
*/
int
-Tcl_WaitForEvent(timePtr)
- Tcl_Time *timePtr; /* Maximum block time, or NULL. */
+Tcl_WaitForEvent(
+ Tcl_Time *timePtr) /* Maximum block time, or NULL. */
{
FileHandler *filePtr;
FileHandlerEvent *fileEvPtr;
int mask;
+ Tcl_Time vTime;
#ifdef TCL_THREADS
int waitForFiles;
#else
- /* Impl. notes: timeout & timeoutPtr are used if, and only if
- * threads are not enabled. They are the arguments for the regular
- * select() used when the core is not thread-enabled. */
+ /*
+ * Impl. notes: timeout & timeoutPtr are used if, and only if threads are
+ * not enabled. They are the arguments for the regular select() used when
+ * the core is not thread-enabled.
+ */
struct timeval timeout, *timeoutPtr;
int numFound;
-#endif
+#endif /* TCL_THREADS */
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
if (tclStubs.tcl_WaitForEvent != tclOriginalNotifier.waitForEventProc) {
return tclStubs.tcl_WaitForEvent(timePtr);
}
-#ifndef TCL_THREADS
/*
- * Set up the timeout structure. Note that if there are no events to
- * check for, we return with a negative result rather than blocking
- * forever.
+ * Set up the timeout structure. Note that if there are no events to check
+ * for, we return with a negative result rather than blocking forever.
*/
- if (timePtr) {
+ if (timePtr != NULL) {
+ /*
+ * TIP #233 (Virtualized Time). Is virtual time in effect? And do we
+ * actually have something to scale? If yes to both then we call the
+ * handler to do this scaling.
+ */
+
+ if (timePtr->sec != 0 || timePtr->usec != 0) {
+ vTime = *timePtr;
+ (*tclScaleTimeProcPtr) (&vTime, tclTimeClientData);
+ timePtr = &vTime;
+ }
+#ifndef TCL_THREADS
timeout.tv_sec = timePtr->sec;
timeout.tv_usec = timePtr->usec;
timeoutPtr = &timeout;
} else if (tsdPtr->numFdBits == 0) {
/*
- * If there are no threads, no timeout, and no fds registered,
- * then there are no events possible and we must avoid deadlock.
- * Note that this is not entirely correct because there might
- * be a signal that could interrupt the select call, but we
- * don't handle that case if we aren't using threads.
+ * If there are no threads, no timeout, and no fds registered, then
+ * there are no events possible and we must avoid deadlock. Note that
+ * this is not entirely correct because there might be a signal that
+ * could interrupt the select call, but we don't handle that case if
+ * we aren't using threads.
*/
return -1;
} else {
timeoutPtr = NULL;
+#endif /* TCL_THREADS */
}
-#endif
#ifdef TCL_THREADS
/*
@@ -711,7 +729,6 @@ Tcl_WaitForEvent(timePtr)
Tcl_MutexLock(&notifierMutex);
- waitForFiles = (tsdPtr->numFdBits > 0);
if (timePtr != NULL && timePtr->sec == 0 && (timePtr->usec == 0
#if defined(__APPLE__) && defined(__LP64__)
/*
@@ -725,104 +742,105 @@ Tcl_WaitForEvent(timePtr)
)) {
/*
* Cannot emulate a polling select with a polling condition variable.
- * Instead, pretend to wait for files and tell the notifier
- * thread what we are doing. The notifier thread makes sure
- * it goes through select with its select mask in the same state
- * as ours currently is. We block until that happens.
+ * Instead, pretend to wait for files and tell the notifier thread
+ * what we are doing. The notifier thread makes sure it goes through
+ * select with its select mask in the same state as ours currently is.
+ * We block until that happens.
*/
waitForFiles = 1;
tsdPtr->pollState = POLL_WANT;
timePtr = NULL;
} else {
+ waitForFiles = (tsdPtr->numFdBits > 0);
tsdPtr->pollState = 0;
}
if (waitForFiles) {
- /*
- * Add the ThreadSpecificData structure of this thread to the list
- * of ThreadSpecificData structures of all threads that are waiting
- * on file events.
- */
-
-
- tsdPtr->nextPtr = waitingListPtr;
- if (waitingListPtr) {
- waitingListPtr->prevPtr = tsdPtr;
- }
- tsdPtr->prevPtr = 0;
- waitingListPtr = tsdPtr;
+ /*
+ * Add the ThreadSpecificData structure of this thread to the list of
+ * ThreadSpecificData structures of all threads that are waiting on
+ * file events.
+ */
+
+ tsdPtr->nextPtr = waitingListPtr;
+ if (waitingListPtr) {
+ waitingListPtr->prevPtr = tsdPtr;
+ }
+ tsdPtr->prevPtr = 0;
+ waitingListPtr = tsdPtr;
tsdPtr->onList = 1;
-
- write(triggerPipe, "", 1);
+
+ if (write(triggerPipe, "", 1) != 1) {
+ Tcl_Panic("Tcl_WaitForEvent: unable to write to triggerPipe");
+ }
}
- FD_ZERO( &(tsdPtr->readyMasks.readable) );
- FD_ZERO( &(tsdPtr->readyMasks.writable) );
- FD_ZERO( &(tsdPtr->readyMasks.exceptional) );
+ FD_ZERO(&(tsdPtr->readyMasks.readable));
+ FD_ZERO(&(tsdPtr->readyMasks.writable));
+ FD_ZERO(&(tsdPtr->readyMasks.exceptional));
if (!tsdPtr->eventReady) {
- Tcl_ConditionWait(&tsdPtr->waitCV, &notifierMutex, timePtr);
+ Tcl_ConditionWait(&tsdPtr->waitCV, &notifierMutex, timePtr);
}
tsdPtr->eventReady = 0;
if (waitForFiles && tsdPtr->onList) {
/*
* Remove the ThreadSpecificData structure of this thread from the
- * waiting list. Alert the notifier thread to recompute its select
+ * waiting list. Alert the notifier thread to recompute its select
* masks - skipping this caused a hang when trying to close a pipe
* which the notifier thread was still doing a select on.
*/
- if (tsdPtr->prevPtr) {
- tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
- } else {
- waitingListPtr = tsdPtr->nextPtr;
- }
- if (tsdPtr->nextPtr) {
- tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
- }
- tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
+ if (tsdPtr->prevPtr) {
+ tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
+ } else {
+ waitingListPtr = tsdPtr->nextPtr;
+ }
+ if (tsdPtr->nextPtr) {
+ tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
+ }
+ tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
tsdPtr->onList = 0;
- write(triggerPipe, "", 1);
+ if (write(triggerPipe, "", 1) != 1) {
+ Tcl_Panic("Tcl_WaitForEvent: unable to write to triggerPipe");
+ }
}
-
#else
tsdPtr->readyMasks = tsdPtr->checkMasks;
- numFound = select( tsdPtr->numFdBits,
- &(tsdPtr->readyMasks.readable),
- &(tsdPtr->readyMasks.writable),
- &(tsdPtr->readyMasks.exceptional),
- timeoutPtr );
+ numFound = select(tsdPtr->numFdBits, &(tsdPtr->readyMasks.readable),
+ &(tsdPtr->readyMasks.writable), &(tsdPtr->readyMasks.exceptional),
+ timeoutPtr);
/*
- * Some systems don't clear the masks after an error, so
- * we have to do it here.
+ * Some systems don't clear the masks after an error, so we have to do it
+ * here.
*/
if (numFound == -1) {
- FD_ZERO( &(tsdPtr->readyMasks.readable ) );
- FD_ZERO( &(tsdPtr->readyMasks.writable ) );
- FD_ZERO( &(tsdPtr->readyMasks.exceptional ) );
+ FD_ZERO(&(tsdPtr->readyMasks.readable));
+ FD_ZERO(&(tsdPtr->readyMasks.writable));
+ FD_ZERO(&(tsdPtr->readyMasks.exceptional));
}
-#endif
+#endif /* TCL_THREADS */
/*
* Queue all detected file events before returning.
*/
for (filePtr = tsdPtr->firstFileHandlerPtr; (filePtr != NULL);
- filePtr = filePtr->nextPtr) {
+ filePtr = filePtr->nextPtr) {
mask = 0;
- if ( FD_ISSET( filePtr->fd, &(tsdPtr->readyMasks.readable) ) ) {
+ if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.readable))) {
mask |= TCL_READABLE;
}
- if ( FD_ISSET( filePtr->fd, &(tsdPtr->readyMasks.writable) ) ) {
+ if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.writable))) {
mask |= TCL_WRITABLE;
}
- if ( FD_ISSET( filePtr->fd, &(tsdPtr->readyMasks.exceptional) ) ) {
+ if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.exceptional))) {
mask |= TCL_EXCEPTION;
}
@@ -831,13 +849,12 @@ Tcl_WaitForEvent(timePtr)
}
/*
- * Don't bother to queue an event if the mask was previously
- * non-zero since an event must still be on the queue.
+ * Don't bother to queue an event if the mask was previously non-zero
+ * since an event must still be on the queue.
*/
if (filePtr->readyMask == 0) {
- fileEvPtr = (FileHandlerEvent *) ckalloc(
- sizeof(FileHandlerEvent));
+ fileEvPtr = (FileHandlerEvent *) ckalloc(sizeof(FileHandlerEvent));
fileEvPtr->header.proc = FileHandlerEventProc;
fileEvPtr->fd = filePtr->fd;
Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
@@ -846,7 +863,7 @@ Tcl_WaitForEvent(timePtr)
}
#ifdef TCL_THREADS
Tcl_MutexUnlock(&notifierMutex);
-#endif
+#endif /* TCL_THREADS */
return 0;
}
@@ -857,64 +874,50 @@ Tcl_WaitForEvent(timePtr)
* NotifierThreadProc --
*
* This routine is the initial (and only) function executed by the
- * special notifier thread. Its job is to wait for file descriptors
- * to become readable or writable or to have an exception condition
- * and then to notify other threads who are interested in this
- * information by signalling a condition variable. Other threads
- * can signal this notifier thread of a change in their interests
- * by writing a single byte to a special pipe that the notifier
- * thread is monitoring.
+ * special notifier thread. Its job is to wait for file descriptors to
+ * become readable or writable or to have an exception condition and then
+ * to notify other threads who are interested in this information by
+ * signalling a condition variable. Other threads can signal this
+ * notifier thread of a change in their interests by writing a single
+ * byte to a special pipe that the notifier thread is monitoring.
*
* Result:
- * None. Once started, this routine never exits. It dies with
- * the overall process.
+ * None. Once started, this routine never exits. It dies with the overall
+ * process.
*
* Side effects:
- * The trigger pipe used to signal the notifier thread is created
- * when the notifier thread first starts.
+ * The trigger pipe used to signal the notifier thread is created when
+ * the notifier thread first starts.
*
*----------------------------------------------------------------------
*/
static void
-NotifierThreadProc(clientData)
- ClientData clientData; /* Not used. */
+NotifierThreadProc(
+ ClientData clientData) /* Not used. */
{
ThreadSpecificData *tsdPtr;
fd_set readableMask;
fd_set writableMask;
fd_set exceptionalMask;
int fds[2];
- int i, status, numFdBits = 0, receivePipe;
+ int i, numFdBits = 0, receivePipe;
long found;
struct timeval poll = {0., 0.}, *timePtr;
char buf[2];
if (pipe(fds) != 0) {
- panic("NotifierThreadProc: could not create trigger pipe.");
+ Tcl_Panic("NotifierThreadProc: could not create trigger pipe");
}
receivePipe = fds[0];
-#ifndef USE_FIONBIO
- status = fcntl(receivePipe, F_GETFL);
- status |= O_NONBLOCK;
- if (fcntl(receivePipe, F_SETFL, status) < 0) {
- panic("NotifierThreadProc: could not make receive pipe non blocking.");
- }
- status = fcntl(fds[1], F_GETFL);
- status |= O_NONBLOCK;
- if (fcntl(fds[1], F_SETFL, status) < 0) {
- panic("NotifierThreadProc: could not make trigger pipe non blocking.");
+ if (TclUnixSetBlockingMode(receivePipe, TCL_MODE_NONBLOCKING) < 0) {
+ Tcl_Panic("NotifierThreadProc: could not make receive pipe non blocking");
}
-#else
- if (ioctl(receivePipe, (int) FIONBIO, &status) < 0) {
- panic("NotifierThreadProc: could not make receive pipe non blocking.");
- }
- if (ioctl(fds[1], (int) FIONBIO, &status) < 0) {
- panic("NotifierThreadProc: could not make trigger pipe non blocking.");
+ if (TclUnixSetBlockingMode(fds[1], TCL_MODE_NONBLOCKING) < 0) {
+ Tcl_Panic("NotifierThreadProc: could not make trigger pipe non blocking");
}
-#endif
/*
* Install the write end of the pipe into the global variable.
@@ -935,37 +938,36 @@ NotifierThreadProc(clientData)
*/
while (1) {
-
- FD_ZERO( &readableMask );
- FD_ZERO( &writableMask );
- FD_ZERO( &exceptionalMask );
+ FD_ZERO(&readableMask);
+ FD_ZERO(&writableMask);
+ FD_ZERO(&exceptionalMask);
/*
- * Compute the logical OR of the select masks from all the
- * waiting notifiers.
+ * Compute the logical OR of the select masks from all the waiting
+ * notifiers.
*/
Tcl_MutexLock(&notifierMutex);
timePtr = NULL;
- for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {
- for ( i = tsdPtr->numFdBits-1; i >= 0; --i ) {
- if ( FD_ISSET( i, &(tsdPtr->checkMasks.readable) ) ) {
- FD_SET( i, &readableMask );
+ for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {
+ for (i = tsdPtr->numFdBits-1; i >= 0; --i) {
+ if (FD_ISSET(i, &(tsdPtr->checkMasks.readable))) {
+ FD_SET(i, &readableMask);
}
- if ( FD_ISSET( i, &(tsdPtr->checkMasks.writable) ) ) {
- FD_SET( i, &writableMask );
+ if (FD_ISSET(i, &(tsdPtr->checkMasks.writable))) {
+ FD_SET(i, &writableMask);
}
- if ( FD_ISSET( i, &(tsdPtr->checkMasks.exceptional) ) ) {
- FD_SET( i, &exceptionalMask );
+ if (FD_ISSET(i, &(tsdPtr->checkMasks.exceptional))) {
+ FD_SET(i, &exceptionalMask);
}
}
- if ( tsdPtr->numFdBits > numFdBits ) {
+ if (tsdPtr->numFdBits > numFdBits) {
numFdBits = tsdPtr->numFdBits;
}
if (tsdPtr->pollState & POLL_WANT) {
/*
- * Here we make sure we go through select() with the same
- * mask bits that were present when the thread tried to poll.
+ * Here we make sure we go through select() with the same mask
+ * bits that were present when the thread tried to poll.
*/
tsdPtr->pollState |= POLL_DONE;
@@ -978,54 +980,54 @@ NotifierThreadProc(clientData)
* Set up the select mask to include the receive pipe.
*/
- if ( receivePipe >= numFdBits ) {
+ if (receivePipe >= numFdBits) {
numFdBits = receivePipe + 1;
}
- FD_SET( receivePipe, &readableMask );
+ FD_SET(receivePipe, &readableMask);
- if ( select( numFdBits, &readableMask, &writableMask,
- &exceptionalMask, timePtr) == -1 ) {
+ if (select(numFdBits, &readableMask, &writableMask, &exceptionalMask,
+ timePtr) == -1) {
/*
* Try again immediately on an error.
*/
continue;
- }
+ }
/*
* Alert any threads that are waiting on a ready file descriptor.
*/
Tcl_MutexLock(&notifierMutex);
- for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {
+ for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {
found = 0;
- for ( i = tsdPtr->numFdBits-1; i >= 0; --i ) {
- if ( FD_ISSET( i, &(tsdPtr->checkMasks.readable) )
- && FD_ISSET( i, &readableMask ) ) {
- FD_SET( i, &(tsdPtr->readyMasks.readable) );
+ for (i = tsdPtr->numFdBits-1; i >= 0; --i) {
+ if (FD_ISSET(i, &(tsdPtr->checkMasks.readable))
+ && FD_ISSET(i, &readableMask)) {
+ FD_SET(i, &(tsdPtr->readyMasks.readable));
found = 1;
}
- if ( FD_ISSET( i, &(tsdPtr->checkMasks.writable) )
- && FD_ISSET( i, &writableMask ) ) {
- FD_SET( i, &(tsdPtr->readyMasks.writable) );
+ if (FD_ISSET(i, &(tsdPtr->checkMasks.writable))
+ && FD_ISSET(i, &writableMask)) {
+ FD_SET(i, &(tsdPtr->readyMasks.writable));
found = 1;
}
- if ( FD_ISSET( i, &(tsdPtr->checkMasks.exceptional) )
- && FD_ISSET( i, &exceptionalMask ) ) {
- FD_SET( i, &(tsdPtr->readyMasks.exceptional) );
+ if (FD_ISSET(i, &(tsdPtr->checkMasks.exceptional))
+ && FD_ISSET(i, &exceptionalMask)) {
+ FD_SET(i, &(tsdPtr->readyMasks.exceptional));
found = 1;
}
}
- if (found || (tsdPtr->pollState & POLL_DONE)) {
- tsdPtr->eventReady = 1;
+ if (found || (tsdPtr->pollState & POLL_DONE)) {
+ tsdPtr->eventReady = 1;
if (tsdPtr->onList) {
/*
- * Remove the ThreadSpecificData structure of this
- * thread from the waiting list. This prevents us from
- * continuously spining on select until the other
- * threads runs and services the file event.
+ * Remove the ThreadSpecificData structure of this thread
+ * from the waiting list. This prevents us from
+ * continuously spining on select until the other threads
+ * runs and services the file event.
*/
if (tsdPtr->prevPtr) {
@@ -1041,24 +1043,24 @@ NotifierThreadProc(clientData)
tsdPtr->pollState = 0;
}
Tcl_ConditionNotify(&tsdPtr->waitCV);
- }
- }
+ }
+ }
Tcl_MutexUnlock(&notifierMutex);
/*
* Consume the next byte from the notifier pipe if the pipe was
- * readable. Note that there may be multiple bytes pending, but
- * to avoid a race condition we only read one at a time.
+ * readable. Note that there may be multiple bytes pending, but to
+ * avoid a race condition we only read one at a time.
*/
- if ( FD_ISSET( receivePipe, &readableMask ) ) {
+ if (FD_ISSET(receivePipe, &readableMask)) {
i = read(receivePipe, buf, 1);
if ((i == 0) || ((i == 1) && (buf[0] == 'q'))) {
/*
- * Someone closed the write end of the pipe or sent us a
- * Quit message [Bug: 4139] and then closed the write end
- * of the pipe so we need to shut down the notifier thread.
+ * Someone closed the write end of the pipe or sent us a Quit
+ * message [Bug: 4139] and then closed the write end of the
+ * pipe so we need to shut down the notifier thread.
*/
break;
@@ -1079,6 +1081,14 @@ NotifierThreadProc(clientData)
TclpThreadExit (0);
}
-#endif
+#endif /* TCL_THREADS */
#endif /* HAVE_COREFOUNDATION */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixPipe.c b/unix/tclUnixPipe.c
index 3a4005c..eb3a218 100644
--- a/unix/tclUnixPipe.c
+++ b/unix/tclUnixPipe.c
@@ -1,76 +1,74 @@
-/*
+/*
* tclUnixPipe.c --
*
- * This file implements the UNIX-specific exec pipeline functions,
- * the "pipe" channel driver, and the "pid" Tcl command.
+ * This file implements the UNIX-specific exec pipeline functions, the
+ * "pipe" channel driver, and the "pid" Tcl command.
*
* Copyright (c) 1991-1994 The Regents of the University of California.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
#ifdef USE_VFORK
#define fork vfork
#endif
/*
- * The following macros convert between TclFile's and fd's. The conversion
+ * The following macros convert between TclFile's and fd's. The conversion
* simple involves shifting fd's up by one to ensure that no valid fd is ever
* the same as NULL.
*/
-#define MakeFile(fd) ((TclFile)(((int)fd)+1))
-#define GetFd(file) (((int)file)-1)
+#define MakeFile(fd) ((TclFile) INT2PTR(((int) (fd)) + 1))
+#define GetFd(file) (PTR2INT(file) - 1)
/*
* This structure describes per-instance state of a pipe based channel.
*/
typedef struct PipeState {
- Tcl_Channel channel;/* Channel associated with this file. */
- TclFile inFile; /* Output from pipe. */
- TclFile outFile; /* Input to pipe. */
- TclFile errorFile; /* Error output from pipe. */
- int numPids; /* How many processes are attached to this pipe? */
- Tcl_Pid *pidPtr; /* The process IDs themselves. Allocated by
- * the creator of the pipe. */
- int isNonBlocking; /* Nonzero when the pipe is in nonblocking mode.
- * Used to decide whether to wait for the children
- * at close time. */
+ Tcl_Channel channel; /* Channel associated with this file. */
+ TclFile inFile; /* Output from pipe. */
+ TclFile outFile; /* Input to pipe. */
+ TclFile errorFile; /* Error output from pipe. */
+ int numPids; /* How many processes are attached to this
+ * pipe? */
+ Tcl_Pid *pidPtr; /* The process IDs themselves. Allocated by
+ * the creator of the pipe. */
+ int isNonBlocking; /* Nonzero when the pipe is in nonblocking
+ * mode. Used to decide whether to wait for
+ * the children at close time. */
} PipeState;
/*
- * Declarations for local procedures defined in this file:
+ * Declarations for local functions defined in this file:
*/
-static int PipeBlockModeProc _ANSI_ARGS_((ClientData instanceData,
- int mode));
-static int PipeCloseProc _ANSI_ARGS_((ClientData instanceData,
- Tcl_Interp *interp));
-static int PipeGetHandleProc _ANSI_ARGS_((ClientData instanceData,
- int direction, ClientData *handlePtr));
-static int PipeInputProc _ANSI_ARGS_((ClientData instanceData,
- char *buf, int toRead, int *errorCode));
-static int PipeOutputProc _ANSI_ARGS_((
- ClientData instanceData, CONST char *buf, int toWrite,
- int *errorCode));
-static void PipeWatchProc _ANSI_ARGS_((ClientData instanceData, int mask));
-static void RestoreSignals _ANSI_ARGS_((void));
-static int SetupStdFile _ANSI_ARGS_((TclFile file, int type));
+static int PipeBlockModeProc(ClientData instanceData, int mode);
+static int PipeCloseProc(ClientData instanceData,
+ Tcl_Interp *interp);
+static int PipeGetHandleProc(ClientData instanceData,
+ int direction, ClientData *handlePtr);
+static int PipeInputProc(ClientData instanceData, char *buf,
+ int toRead, int *errorCode);
+static int PipeOutputProc(ClientData instanceData,
+ const char *buf, int toWrite, int *errorCode);
+static void PipeWatchProc(ClientData instanceData, int mask);
+static void RestoreSignals(void);
+static int SetupStdFile(TclFile file, int type);
/*
- * This structure describes the channel type structure for command pipe
- * based IO:
+ * This structure describes the channel type structure for command pipe based
+ * I/O:
*/
static Tcl_ChannelType pipeChannelType = {
"pipe", /* Type name. */
- TCL_CHANNEL_VERSION_4, /* v4 channel */
+ TCL_CHANNEL_VERSION_5, /* v5 channel */
PipeCloseProc, /* Close proc. */
PipeInputProc, /* Input proc. */
PipeOutputProc, /* Output proc. */
@@ -83,8 +81,9 @@ static Tcl_ChannelType pipeChannelType = {
PipeBlockModeProc, /* Set blocking or non-blocking mode.*/
NULL, /* flush proc. */
NULL, /* handler proc. */
- NULL, /* wide seek proc */
- NULL, /* thread action proc */
+ NULL, /* wide seek proc */
+ NULL, /* thread action proc */
+ NULL /* truncation */
};
/*
@@ -104,15 +103,15 @@ static Tcl_ChannelType pipeChannelType = {
*/
TclFile
-TclpMakeFile(channel, direction)
- Tcl_Channel channel; /* Channel to get file from. */
- int direction; /* Either TCL_READABLE or TCL_WRITABLE. */
+TclpMakeFile(
+ Tcl_Channel channel, /* Channel to get file from. */
+ int direction) /* Either TCL_READABLE or TCL_WRITABLE. */
{
ClientData data;
- if (Tcl_GetChannelHandle(channel, direction, (ClientData *) &data)
- == TCL_OK) {
- return MakeFile((int)data);
+ if (Tcl_GetChannelHandle(channel, direction,
+ (ClientData *) &data) == TCL_OK) {
+ return MakeFile(PTR2INT(data));
} else {
return (TclFile) NULL;
}
@@ -123,7 +122,7 @@ TclpMakeFile(channel, direction)
*
* TclpOpenFile --
*
- * Open a file for use in a pipeline.
+ * Open a file for use in a pipeline.
*
* Results:
* Returns a new TclFile handle or NULL on failure.
@@ -135,23 +134,23 @@ TclpMakeFile(channel, direction)
*/
TclFile
-TclpOpenFile(fname, mode)
- CONST char *fname; /* The name of the file to open. */
- int mode; /* In what mode to open the file? */
+TclpOpenFile(
+ const char *fname, /* The name of the file to open. */
+ int mode) /* In what mode to open the file? */
{
int fd;
- CONST char *native;
+ const char *native;
Tcl_DString ds;
native = Tcl_UtfToExternalDString(NULL, fname, -1, &ds);
fd = TclOSopen(native, mode, 0666); /* INTL: Native. */
Tcl_DStringFree(&ds);
if (fd != -1) {
- fcntl(fd, F_SETFD, FD_CLOEXEC);
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
/*
- * If the file is being opened for writing, seek to the end
- * so we can append to any data already in the file.
+ * If the file is being opened for writing, seek to the end so we can
+ * append to any data already in the file.
*/
if ((mode & O_WRONLY) && !(mode & O_APPEND)) {
@@ -159,8 +158,8 @@ TclpOpenFile(fname, mode)
}
/*
- * Increment the fd so it can't be 0, which would conflict with
- * the NULL return for errors.
+ * Increment the fd so it can't be 0, which would conflict with the
+ * NULL return for errors.
*/
return MakeFile(fd);
@@ -173,9 +172,9 @@ TclpOpenFile(fname, mode)
*
* TclpCreateTempFile --
*
- * This function creates a temporary file initialized with an
- * optional string, and returns a file handle with the file pointer
- * at the beginning of the file.
+ * This function creates a temporary file initialized with an optional
+ * string, and returns a file handle with the file pointer at the
+ * beginning of the file.
*
* Results:
* A handle to a file.
@@ -187,11 +186,11 @@ TclpOpenFile(fname, mode)
*/
TclFile
-TclpCreateTempFile(contents)
- CONST char *contents; /* String to write into temp file, or NULL. */
+TclpCreateTempFile(
+ const char *contents) /* String to write into temp file, or NULL. */
{
char fileName[L_tmpnam + 9];
- CONST char *native;
+ const char *native;
Tcl_DString dstring;
int fd;
@@ -240,8 +239,8 @@ TclpCreateTempFile(contents)
*----------------------------------------------------------------------
*/
-Tcl_Obj*
-TclpTempFileName()
+Tcl_Obj *
+TclpTempFileName(void)
{
char fileName[L_tmpnam + 9];
Tcl_Obj *result = NULL;
@@ -264,7 +263,7 @@ TclpTempFileName()
unlink(fileName); /* INTL: Native. */
result = TclpNativeToNormalized((ClientData) fileName);
- close (fd);
+ close(fd);
return result;
}
@@ -273,23 +272,23 @@ TclpTempFileName()
*
* TclpCreatePipe --
*
- * Creates a pipe - simply calls the pipe() function.
+ * Creates a pipe - simply calls the pipe() function.
*
* Results:
- * Returns 1 on success, 0 on failure.
+ * Returns 1 on success, 0 on failure.
*
* Side effects:
- * Creates a pipe.
+ * Creates a pipe.
*
*----------------------------------------------------------------------
*/
int
-TclpCreatePipe(readPipe, writePipe)
- TclFile *readPipe; /* Location to store file handle for
- * read side of pipe. */
- TclFile *writePipe; /* Location to store file handle for
- * write side of pipe. */
+TclpCreatePipe(
+ TclFile *readPipe, /* Location to store file handle for read side
+ * of pipe. */
+ TclFile *writePipe) /* Location to store file handle for write
+ * side of pipe. */
{
int pipeIds[2];
@@ -322,19 +321,19 @@ TclpCreatePipe(readPipe, writePipe)
*/
int
-TclpCloseFile(file)
- TclFile file; /* The file to close. */
+TclpCloseFile(
+ TclFile file) /* The file to close. */
{
int fd = GetFd(file);
/*
* Refuse to close the fds for stdin, stdout and stderr.
*/
-
+
if ((fd == 0) || (fd == 1) || (fd == 2)) {
- return 0;
+ return 0;
}
-
+
Tcl_DeleteFileHandler(fd);
return close(fd);
}
@@ -344,55 +343,53 @@ TclpCloseFile(file)
*
* TclpCreateProcess --
*
- * Create a child process that has the specified files as its
- * standard input, output, and error. The child process runs
- * asynchronously and runs with the same environment variables
- * as the creating process.
+ * Create a child process that has the specified files as its standard
+ * input, output, and error. The child process runs asynchronously and
+ * runs with the same environment variables as the creating process.
*
- * The path is searched to find the specified executable.
+ * The path is searched to find the specified executable.
*
* Results:
- * The return value is TCL_ERROR and an error message is left in
- * the interp's result if there was a problem creating the child
- * process. Otherwise, the return value is TCL_OK and *pidPtr is
- * filled with the process id of the child process.
- *
+ * The return value is TCL_ERROR and an error message is left in the
+ * interp's result if there was a problem creating the child process.
+ * Otherwise, the return value is TCL_OK and *pidPtr is filled with the
+ * process id of the child process.
+ *
* Side effects:
* A process is created.
- *
+ *
*---------------------------------------------------------------------------
*/
/* ARGSUSED */
int
-TclpCreateProcess(interp, argc, argv, inputFile, outputFile, errorFile,
- pidPtr)
- Tcl_Interp *interp; /* Interpreter in which to leave errors that
+TclpCreateProcess(
+ Tcl_Interp *interp, /* Interpreter in which to leave errors that
* occurred when creating the child process.
* Error messages from the child process
* itself are sent to errorFile. */
- int argc; /* Number of arguments in following array. */
- CONST char **argv; /* Array of argument strings in UTF-8.
+ int argc, /* Number of arguments in following array. */
+ const char **argv, /* Array of argument strings in UTF-8.
* argv[0] contains the name of the executable
* translated using Tcl_TranslateFileName
- * call). Additional arguments have not been
+ * call). Additional arguments have not been
* converted. */
- TclFile inputFile; /* If non-NULL, gives the file to use as
- * input for the child process. If inputFile
- * file is not readable or is NULL, the child
- * will receive no standard input. */
- TclFile outputFile; /* If non-NULL, gives the file that
- * receives output from the child process. If
+ TclFile inputFile, /* If non-NULL, gives the file to use as input
+ * for the child process. If inputFile file is
+ * not readable or is NULL, the child will
+ * receive no standard input. */
+ TclFile outputFile, /* If non-NULL, gives the file that receives
+ * output from the child process. If
* outputFile file is not writeable or is
* NULL, output from the child will be
* discarded. */
- TclFile errorFile; /* If non-NULL, gives the file that
- * receives errors from the child process. If
- * errorFile file is not writeable or is NULL,
- * errors from the child will be discarded.
- * errorFile may be the same as outputFile. */
- Tcl_Pid *pidPtr; /* If this procedure is successful, pidPtr
- * is filled with the process id of the child
+ TclFile errorFile, /* If non-NULL, gives the file that receives
+ * errors from the child process. If errorFile
+ * file is not writeable or is NULL, errors
+ * from the child will be discarded. errorFile
+ * may be the same as outputFile. */
+ Tcl_Pid *pidPtr) /* If this function is successful, pidPtr is
+ * filled with the process id of the child
* process. */
{
TclFile errPipeIn, errPipeOut;
@@ -401,28 +398,30 @@ TclpCreateProcess(interp, argc, argv, inputFile, outputFile, errorFile,
Tcl_DString *dsArray;
char **newArgv;
int pid, i;
-
+
errPipeIn = NULL;
errPipeOut = NULL;
pid = -1;
/*
- * Create a pipe that the child can use to return error
- * information if anything goes wrong.
+ * Create a pipe that the child can use to return error information if
+ * anything goes wrong.
*/
if (TclpCreatePipe(&errPipeIn, &errPipeOut) == 0) {
Tcl_AppendResult(interp, "couldn't create pipe: ",
- Tcl_PosixError(interp), (char *) NULL);
+ Tcl_PosixError(interp), NULL);
goto error;
}
/*
- * We need to allocate and convert this before the fork
- * so it is properly deallocated later
+ * We need to allocate and convert this before the fork so it is properly
+ * deallocated later
*/
- dsArray = (Tcl_DString *) ckalloc(argc * sizeof(Tcl_DString));
- newArgv = (char **) ckalloc((argc+1) * sizeof(char *));
+
+ dsArray = (Tcl_DString *)
+ TclStackAlloc(interp, argc * sizeof(Tcl_DString));
+ newArgv = (char **) TclStackAlloc(interp, (argc+1) * sizeof(char *));
newArgv[argc] = NULL;
for (i = 0; i < argc; i++) {
newArgv[i] = Tcl_UtfToExternalDString(NULL, argv[i], -1, &dsArray[i]);
@@ -435,6 +434,7 @@ TclpCreateProcess(interp, argc, argv, inputFile, outputFile, errorFile,
* might corrupt the parent: so ensure standard channels are initialized in
* the parent, otherwise SetupStdFile() might initialize them in the child.
*/
+
if (!inputFile) {
Tcl_GetStdChannel(TCL_STDIN);
}
@@ -445,8 +445,10 @@ TclpCreateProcess(interp, argc, argv, inputFile, outputFile, errorFile,
Tcl_GetStdChannel(TCL_STDERR);
}
#endif
+
pid = fork();
if (pid == 0) {
+ size_t len;
int joinThisError = errorFile && (errorFile == outputFile);
fd = GetFd(errPipeOut);
@@ -459,11 +461,13 @@ TclpCreateProcess(interp, argc, argv, inputFile, outputFile, errorFile,
|| !SetupStdFile(outputFile, TCL_STDOUT)
|| (!joinThisError && !SetupStdFile(errorFile, TCL_STDERR))
|| (joinThisError &&
- ((dup2(1,2) == -1) ||
- (fcntl(2, F_SETFD, 0) != 0)))) {
+ ((dup2(1,2) == -1) || (fcntl(2, F_SETFD, 0) != 0)))) {
sprintf(errSpace,
"%dforked process couldn't set up input/output: ", errno);
- write(fd, errSpace, (size_t) strlen(errSpace));
+ len = strlen(errSpace);
+ if (len != (size_t) write(fd, errSpace, len)) {
+ Tcl_Panic("TclpCreateProcess: unable to write to errPipeOut");
+ }
_exit(1);
}
@@ -474,29 +478,33 @@ TclpCreateProcess(interp, argc, argv, inputFile, outputFile, errorFile,
RestoreSignals();
execvp(newArgv[0], newArgv); /* INTL: Native. */
sprintf(errSpace, "%dcouldn't execute \"%.150s\": ", errno, argv[0]);
- write(fd, errSpace, (size_t) strlen(errSpace));
+ len = strlen(errSpace);
+ if (len != (size_t) write(fd, errSpace, len)) {
+ Tcl_Panic("TclpCreateProcess: unable to write to errPipeOut");
+ }
_exit(1);
}
-
+
/*
* Free the mem we used for the fork
*/
+
for (i = 0; i < argc; i++) {
Tcl_DStringFree(&dsArray[i]);
}
- ckfree((char *) dsArray);
- ckfree((char *) newArgv);
+ TclStackFree(interp, newArgv);
+ TclStackFree(interp, dsArray);
if (pid == -1) {
Tcl_AppendResult(interp, "couldn't fork child process: ",
- Tcl_PosixError(interp), (char *) NULL);
+ Tcl_PosixError(interp), NULL);
goto error;
}
/*
- * Read back from the error pipe to see if the child started
- * up OK. The info in the pipe (if any) consists of a decimal
- * errno value followed by an error message.
+ * Read back from the error pipe to see if the child started up OK. The
+ * info in the pipe (if any) consists of a decimal errno value followed by
+ * an error message.
*/
TclpCloseFile(errPipeOut);
@@ -508,27 +516,26 @@ TclpCreateProcess(interp, argc, argv, inputFile, outputFile, errorFile,
char *end;
errSpace[count] = 0;
errno = strtol(errSpace, &end, 10);
- Tcl_AppendResult(interp, end, Tcl_PosixError(interp),
- (char *) NULL);
+ Tcl_AppendResult(interp, end, Tcl_PosixError(interp), NULL);
goto error;
}
-
+
TclpCloseFile(errPipeIn);
- *pidPtr = (Tcl_Pid) pid;
+ *pidPtr = (Tcl_Pid) INT2PTR(pid);
return TCL_OK;
- error:
+ error:
if (pid != -1) {
/*
- * Reap the child process now if an error occurred during its
- * startup. We don't call this with WNOHANG because that can lead to
- * defunct processes on an MP system. We shouldn't have to worry
- * about hanging here, since this is the error case. [Bug: 6148]
+ * Reap the child process now if an error occurred during its startup.
+ * We don't call this with WNOHANG because that can lead to defunct
+ * processes on an MP system. We shouldn't have to worry about hanging
+ * here, since this is the error case. [Bug: 6148]
*/
- Tcl_WaitPid((Tcl_Pid) pid, &status, 0);
+ Tcl_WaitPid((Tcl_Pid) INT2PTR(pid), &status, 0);
}
-
+
if (errPipeIn) {
TclpCloseFile(errPipeIn);
}
@@ -543,21 +550,21 @@ TclpCreateProcess(interp, argc, argv, inputFile, outputFile, errorFile,
*
* RestoreSignals --
*
- * This procedure is invoked in a forked child process just before
- * exec-ing a new program to restore all signals to their default
- * settings.
+ * This function is invoked in a forked child process just before
+ * exec-ing a new program to restore all signals to their default
+ * settings.
*
* Results:
- * None.
+ * None.
*
* Side effects:
- * Signal settings get changed.
+ * Signal settings get changed.
*
*----------------------------------------------------------------------
*/
-
+
static void
-RestoreSignals()
+RestoreSignals(void)
{
#ifdef SIGABRT
signal(SIGABRT, SIG_DFL);
@@ -617,10 +624,10 @@ RestoreSignals()
*
* SetupStdFile --
*
- * Set up stdio file handles for the child process, using the
- * current standard channels if no other files are specified.
- * If no standard channel is defined, or if no file is associated
- * with the channel, then the corresponding standard fd is closed.
+ * Set up stdio file handles for the child process, using the current
+ * standard channels if no other files are specified. If no standard
+ * channel is defined, or if no file is associated with the channel, then
+ * the corresponding standard fd is closed.
*
* Results:
* Returns 1 on success, or 0 on failure.
@@ -632,9 +639,9 @@ RestoreSignals()
*/
static int
-SetupStdFile(file, type)
- TclFile file; /* File to dup, or NULL. */
- int type; /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR */
+SetupStdFile(
+ TclFile file, /* File to dup, or NULL. */
+ int type) /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR */
{
Tcl_Channel channel;
int fd;
@@ -643,18 +650,18 @@ SetupStdFile(file, type)
* variables. */
switch (type) {
- case TCL_STDIN:
- targetFd = 0;
- direction = TCL_READABLE;
- break;
- case TCL_STDOUT:
- targetFd = 1;
- direction = TCL_WRITABLE;
- break;
- case TCL_STDERR:
- targetFd = 2;
- direction = TCL_WRITABLE;
- break;
+ case TCL_STDIN:
+ targetFd = 0;
+ direction = TCL_READABLE;
+ break;
+ case TCL_STDOUT:
+ targetFd = 1;
+ direction = TCL_WRITABLE;
+ break;
+ case TCL_STDERR:
+ targetFd = 2;
+ direction = TCL_WRITABLE;
+ break;
}
if (!file) {
@@ -670,20 +677,20 @@ SetupStdFile(file, type)
return 0;
}
- /*
- * Must clear the close-on-exec flag for the target FD, since
- * some systems (e.g. Ultrix) do not clear the CLOEXEC flag on
- * the target FD.
- */
-
- fcntl(targetFd, F_SETFD, 0);
+ /*
+ * Must clear the close-on-exec flag for the target FD, since some
+ * systems (e.g. Ultrix) do not clear the CLOEXEC flag on the
+ * target FD.
+ */
+
+ fcntl(targetFd, F_SETFD, 0);
} else {
/*
* Since we aren't dup'ing the file, we need to explicitly clear
* the close-on-exec flag.
*/
- fcntl(fd, F_SETFD, 0);
+ fcntl(fd, F_SETFD, 0);
}
} else {
close(targetFd);
@@ -696,9 +703,8 @@ SetupStdFile(file, type)
*
* TclpCreateCommandChannel --
*
- * This function is called by the generic IO level to perform
- * the platform specific channel initialization for a command
- * channel.
+ * This function is called by the generic IO level to perform the
+ * platform specific channel initialization for a command channel.
*
* Results:
* Returns a new channel or NULL on failure.
@@ -710,16 +716,16 @@ SetupStdFile(file, type)
*/
Tcl_Channel
-TclpCreateCommandChannel(readFile, writeFile, errorFile, numPids, pidPtr)
- TclFile readFile; /* If non-null, gives the file for reading. */
- TclFile writeFile; /* If non-null, gives the file for writing. */
- TclFile errorFile; /* If non-null, gives the file where errors
+TclpCreateCommandChannel(
+ TclFile readFile, /* If non-null, gives the file for reading. */
+ TclFile writeFile, /* If non-null, gives the file for writing. */
+ TclFile errorFile, /* If non-null, gives the file where errors
* can be read. */
- int numPids; /* The number of pids in the pid array. */
- Tcl_Pid *pidPtr; /* An array of process identifiers.
- * Allocated by the caller, freed when
- * the channel is closed or the processes
- * are detached (in a background exec). */
+ int numPids, /* The number of pids in the pid array. */
+ Tcl_Pid *pidPtr) /* An array of process identifiers. Allocated
+ * by the caller, freed when the channel is
+ * closed or the processes are detached (in a
+ * background exec). */
{
char channelName[16 + TCL_INTEGER_SPACE];
int channelId;
@@ -735,15 +741,14 @@ TclpCreateCommandChannel(readFile, writeFile, errorFile, numPids, pidPtr)
mode = 0;
if (readFile) {
- mode |= TCL_READABLE;
+ mode |= TCL_READABLE;
}
if (writeFile) {
- mode |= TCL_WRITABLE;
+ mode |= TCL_WRITABLE;
}
-
+
/*
- * Use one of the fds associated with the channel as the
- * channel id.
+ * Use one of the fds associated with the channel as the channel id.
*/
if (readFile) {
@@ -757,14 +762,14 @@ TclpCreateCommandChannel(readFile, writeFile, errorFile, numPids, pidPtr)
}
/*
- * For backward compatibility with previous versions of Tcl, we
- * use "file%d" as the base name for pipes even though it would
- * be more natural to use "pipe%d".
+ * For backward compatibility with previous versions of Tcl, we use
+ * "file%d" as the base name for pipes even though it would be more
+ * natural to use "pipe%d".
*/
sprintf(channelName, "file%d", channelId);
statePtr->channel = Tcl_CreateChannel(&pipeChannelType, channelName,
- (ClientData) statePtr, mode);
+ (ClientData) statePtr, mode);
return statePtr->channel;
}
@@ -773,10 +778,10 @@ TclpCreateCommandChannel(readFile, writeFile, errorFile, numPids, pidPtr)
*
* TclGetAndDetachPids --
*
- * This procedure is invoked in the generic implementation of a
- * background "exec" (An exec when invoked with a terminating "&")
- * to store a list of the PIDs for processes in a command pipeline
- * in the interp's result and to detach the processes.
+ * This function is invoked in the generic implementation of a
+ * background "exec" (an exec when invoked with a terminating "&") to
+ * store a list of the PIDs for processes in a command pipeline in the
+ * interp's result and to detach the processes.
*
* Results:
* None.
@@ -788,12 +793,12 @@ TclpCreateCommandChannel(readFile, writeFile, errorFile, numPids, pidPtr)
*/
void
-TclGetAndDetachPids(interp, chan)
- Tcl_Interp *interp;
- Tcl_Channel chan;
+TclGetAndDetachPids(
+ Tcl_Interp *interp, /* Interpreter to append the PIDs to. */
+ Tcl_Channel chan) /* Handle for the pipeline. */
{
PipeState *pipePtr;
- Tcl_ChannelType *chanTypePtr;
+ const Tcl_ChannelType *chanTypePtr;
int i;
char buf[TCL_INTEGER_SPACE];
@@ -803,18 +808,18 @@ TclGetAndDetachPids(interp, chan)
chanTypePtr = Tcl_GetChannelType(chan);
if (chanTypePtr != &pipeChannelType) {
- return;
+ return;
}
pipePtr = (PipeState *) Tcl_GetChannelInstanceData(chan);
for (i = 0; i < pipePtr->numPids; i++) {
- TclFormatInt(buf, (long) TclpGetPid(pipePtr->pidPtr[i]));
- Tcl_AppendElement(interp, buf);
- Tcl_DetachPids(1, &(pipePtr->pidPtr[i]));
+ TclFormatInt(buf, (long) TclpGetPid(pipePtr->pidPtr[i]));
+ Tcl_AppendElement(interp, buf);
+ Tcl_DetachPids(1, &(pipePtr->pidPtr[i]));
}
if (pipePtr->numPids > 0) {
- ckfree((char *) pipePtr->pidPtr);
- pipePtr->numPids = 0;
+ ckfree((char *) pipePtr->pidPtr);
+ pipePtr->numPids = 0;
}
}
@@ -823,8 +828,8 @@ TclGetAndDetachPids(interp, chan)
*
* PipeBlockModeProc --
*
- * Helper procedure to set blocking and nonblocking modes on a
- * pipe based channel. Invoked by generic IO level code.
+ * Helper function to set blocking and nonblocking modes on a pipe based
+ * channel. Invoked by generic IO level code.
*
* Results:
* 0 if successful, errno when failed.
@@ -837,67 +842,24 @@ TclGetAndDetachPids(interp, chan)
/* ARGSUSED */
static int
-PipeBlockModeProc(instanceData, mode)
- ClientData instanceData; /* Pipe state. */
- int mode; /* The mode to set. Can be one of
- * TCL_MODE_BLOCKING or
- * TCL_MODE_NONBLOCKING. */
+PipeBlockModeProc(
+ ClientData instanceData, /* Pipe state. */
+ int mode) /* The mode to set. Can be one of
+ * TCL_MODE_BLOCKING or
+ * TCL_MODE_NONBLOCKING. */
{
- PipeState *psPtr = (PipeState *) instanceData;
- int curStatus;
- int fd;
+ PipeState *psPtr = instanceData;
-#ifndef USE_FIONBIO
if (psPtr->inFile) {
- fd = GetFd(psPtr->inFile);
- curStatus = fcntl(fd, F_GETFL);
- if (mode == TCL_MODE_BLOCKING) {
- curStatus &= (~(O_NONBLOCK));
- } else {
- curStatus |= O_NONBLOCK;
- }
- if (fcntl(fd, F_SETFL, curStatus) < 0) {
- return errno;
- }
+ if (TclUnixSetBlockingMode(GetFd(psPtr->inFile), mode) < 0) {
+ return errno;
+ }
}
if (psPtr->outFile) {
- fd = GetFd(psPtr->outFile);
- curStatus = fcntl(fd, F_GETFL);
- if (mode == TCL_MODE_BLOCKING) {
- curStatus &= (~(O_NONBLOCK));
- } else {
- curStatus |= O_NONBLOCK;
- }
- if (fcntl(fd, F_SETFL, curStatus) < 0) {
- return errno;
- }
- }
-#endif /* !FIONBIO */
-
-#ifdef USE_FIONBIO
- if (psPtr->inFile) {
- fd = GetFd(psPtr->inFile);
- if (mode == TCL_MODE_BLOCKING) {
- curStatus = 0;
- } else {
- curStatus = 1;
- }
- if (ioctl(fd, (int) FIONBIO, &curStatus) < 0) {
- return errno;
- }
- }
- if (psPtr->outFile != NULL) {
- fd = GetFd(psPtr->outFile);
- if (mode == TCL_MODE_BLOCKING) {
- curStatus = 0;
- } else {
- curStatus = 1;
- }
- if (ioctl(fd, (int) FIONBIO, &curStatus) < 0) {
- return errno;
- }
+ if (TclUnixSetBlockingMode(GetFd(psPtr->outFile), mode) < 0) {
+ return errno;
+ }
}
-#endif /* USE_FIONBIO */
psPtr->isNonBlocking = (mode == TCL_MODE_NONBLOCKING);
@@ -909,9 +871,9 @@ PipeBlockModeProc(instanceData, mode)
*
* PipeCloseProc --
*
- * This procedure is invoked by the generic IO level to perform
- * channel-type-specific cleanup when a command pipeline channel
- * is closed.
+ * This function is invoked by the generic IO level to perform
+ * channel-type-specific cleanup when a command pipeline channel is
+ * closed.
*
* Results:
* 0 on success, errno otherwise.
@@ -924,9 +886,9 @@ PipeBlockModeProc(instanceData, mode)
/* ARGSUSED */
static int
-PipeCloseProc(instanceData, interp)
- ClientData instanceData; /* The pipe to close. */
- Tcl_Interp *interp; /* For error reporting. */
+PipeCloseProc(
+ ClientData instanceData, /* The pipe to close. */
+ Tcl_Interp *interp) /* For error reporting. */
{
PipeState *pipePtr;
Tcl_Channel errChan;
@@ -947,42 +909,40 @@ PipeCloseProc(instanceData, interp)
}
if (pipePtr->isNonBlocking || TclInExit()) {
-
/*
- * If the channel is non-blocking or Tcl is being cleaned up, just
- * detach the children PIDs, reap them (important if we are in a
- * dynamic load module), and discard the errorFile.
- */
-
- Tcl_DetachPids(pipePtr->numPids, pipePtr->pidPtr);
- Tcl_ReapDetachedProcs();
-
- if (pipePtr->errorFile) {
+ * If the channel is non-blocking or Tcl is being cleaned up, just
+ * detach the children PIDs, reap them (important if we are in a
+ * dynamic load module), and discard the errorFile.
+ */
+
+ Tcl_DetachPids(pipePtr->numPids, pipePtr->pidPtr);
+ Tcl_ReapDetachedProcs();
+
+ if (pipePtr->errorFile) {
TclpCloseFile(pipePtr->errorFile);
- }
+ }
} else {
-
/*
- * Wrap the error file into a channel and give it to the cleanup
- * routine.
- */
+ * Wrap the error file into a channel and give it to the cleanup
+ * routine.
+ */
- if (pipePtr->errorFile) {
+ if (pipePtr->errorFile) {
errChan = Tcl_MakeFileChannel(
- (ClientData) GetFd(pipePtr->errorFile), TCL_READABLE);
- } else {
- errChan = NULL;
- }
- result = TclCleanupChildren(interp, pipePtr->numPids, pipePtr->pidPtr,
- errChan);
+ (ClientData) INT2PTR(GetFd(pipePtr->errorFile)), TCL_READABLE);
+ } else {
+ errChan = NULL;
+ }
+ result = TclCleanupChildren(interp, pipePtr->numPids, pipePtr->pidPtr,
+ errChan);
}
if (pipePtr->numPids != 0) {
- ckfree((char *) pipePtr->pidPtr);
+ ckfree((char *) pipePtr->pidPtr);
}
ckfree((char *) pipePtr);
if (errorCode == 0) {
- return result;
+ return result;
}
return errorCode;
}
@@ -992,8 +952,8 @@ PipeCloseProc(instanceData, interp)
*
* PipeInputProc --
*
- * This procedure is invoked from the generic IO level to read
- * input from a command pipeline based channel.
+ * This function is invoked from the generic IO level to read input from
+ * a command pipeline based channel.
*
* Results:
* The number of bytes read is returned or -1 on error. An output
@@ -1006,30 +966,29 @@ PipeCloseProc(instanceData, interp)
*/
static int
-PipeInputProc(instanceData, buf, toRead, errorCodePtr)
- ClientData instanceData; /* Pipe state. */
- char *buf; /* Where to store data read. */
- int toRead; /* How much space is available
- * in the buffer? */
- int *errorCodePtr; /* Where to store error code. */
+PipeInputProc(
+ ClientData instanceData, /* Pipe state. */
+ char *buf, /* Where to store data read. */
+ int toRead, /* How much space is available in the
+ * buffer? */
+ int *errorCodePtr) /* Where to store error code. */
{
PipeState *psPtr = (PipeState *) instanceData;
- int bytesRead; /* How many bytes were actually
- * read from the input device? */
+ int bytesRead; /* How many bytes were actually read from the
+ * input device? */
*errorCodePtr = 0;
-
+
/*
* Assume there is always enough input available. This will block
* appropriately, and read will unblock as soon as a short read is
* possible, if the channel is in blocking mode. If the channel is
- * nonblocking, the read will never block.
- * Some OSes can throw an interrupt error, for which we should
- * immediately retry. [Bug #415131]
+ * nonblocking, the read will never block. Some OSes can throw an
+ * interrupt error, for which we should immediately retry. [Bug #415131]
*/
do {
- bytesRead = read (GetFd(psPtr->inFile), buf, (size_t) toRead);
+ bytesRead = read(GetFd(psPtr->inFile), buf, (size_t) toRead);
} while ((bytesRead < 0) && (errno == EINTR));
if (bytesRead < 0) {
@@ -1045,13 +1004,12 @@ PipeInputProc(instanceData, buf, toRead, errorCodePtr)
*
* PipeOutputProc--
*
- * This procedure is invoked from the generic IO level to write
- * output to a command pipeline based channel.
+ * This function is invoked from the generic IO level to write output to
+ * a command pipeline based channel.
*
* Results:
- * The number of bytes written is returned or -1 on error. An
- * output argument contains a POSIX error code if an error occurred,
- * or zero.
+ * The number of bytes written is returned or -1 on error. An output
+ * argument contains a POSIX error code if an error occurred, or zero.
*
* Side effects:
* Writes output on the output device of the channel.
@@ -1060,11 +1018,11 @@ PipeInputProc(instanceData, buf, toRead, errorCodePtr)
*/
static int
-PipeOutputProc(instanceData, buf, toWrite, errorCodePtr)
- ClientData instanceData; /* Pipe state. */
- CONST char *buf; /* The data buffer. */
- int toWrite; /* How many bytes to write? */
- int *errorCodePtr; /* Where to store error code. */
+PipeOutputProc(
+ ClientData instanceData, /* Pipe state. */
+ const char *buf, /* The data buffer. */
+ int toWrite, /* How many bytes to write? */
+ int *errorCodePtr) /* Where to store error code. */
{
PipeState *psPtr = (PipeState *) instanceData;
int written;
@@ -1072,8 +1030,8 @@ PipeOutputProc(instanceData, buf, toWrite, errorCodePtr)
*errorCodePtr = 0;
/*
- * Some OSes can throw an interrupt error, for which we should
- * immediately retry. [Bug #415131]
+ * Some OSes can throw an interrupt error, for which we should immediately
+ * retry. [Bug #415131]
*/
do {
@@ -1099,18 +1057,18 @@ PipeOutputProc(instanceData, buf, toWrite, errorCodePtr)
* None.
*
* Side effects:
- * Sets up the notifier so that a future event on the channel will
- * be seen by Tcl.
+ * Sets up the notifier so that a future event on the channel will be
+ * seen by Tcl.
*
*----------------------------------------------------------------------
*/
static void
-PipeWatchProc(instanceData, mask)
- ClientData instanceData; /* The pipe state. */
- int mask; /* Events of interest; an OR-ed
- * combination of TCL_READABLE,
- * TCL_WRITABEL and TCL_EXCEPTION. */
+PipeWatchProc(
+ ClientData instanceData, /* The pipe state. */
+ int mask) /* Events of interest; an OR-ed combination of
+ * TCL_READABLE, TCL_WRITABLE and
+ * TCL_EXCEPTION. */
{
PipeState *psPtr = (PipeState *) instanceData;
int newmask;
@@ -1142,12 +1100,12 @@ PipeWatchProc(instanceData, mask)
*
* PipeGetHandleProc --
*
- * Called from Tcl_GetChannelHandle to retrieve OS handles from
- * inside a command pipeline based channel.
+ * Called from Tcl_GetChannelHandle to retrieve OS handles from inside a
+ * command pipeline based channel.
*
* Results:
- * Returns TCL_OK with the fd in handlePtr, or TCL_ERROR if
- * there is no handle for the specified direction.
+ * Returns TCL_OK with the fd in handlePtr, or TCL_ERROR if there is no
+ * handle for the specified direction.
*
* Side effects:
* None.
@@ -1156,19 +1114,19 @@ PipeWatchProc(instanceData, mask)
*/
static int
-PipeGetHandleProc(instanceData, direction, handlePtr)
- ClientData instanceData; /* The pipe state. */
- int direction; /* TCL_READABLE or TCL_WRITABLE */
- ClientData *handlePtr; /* Where to store the handle. */
+PipeGetHandleProc(
+ ClientData instanceData, /* The pipe state. */
+ int direction, /* TCL_READABLE or TCL_WRITABLE */
+ ClientData *handlePtr) /* Where to store the handle. */
{
PipeState *psPtr = (PipeState *) instanceData;
if (direction == TCL_READABLE && psPtr->inFile) {
- *handlePtr = (ClientData) GetFd(psPtr->inFile);
+ *handlePtr = (ClientData) INT2PTR(GetFd(psPtr->inFile));
return TCL_OK;
}
if (direction == TCL_WRITABLE && psPtr->outFile) {
- *handlePtr = (ClientData) GetFd(psPtr->outFile);
+ *handlePtr = (ClientData) INT2PTR(GetFd(psPtr->outFile));
return TCL_OK;
}
return TCL_ERROR;
@@ -1191,19 +1149,18 @@ PipeGetHandleProc(instanceData, direction, handlePtr)
*/
Tcl_Pid
-Tcl_WaitPid(pid, statPtr, options)
- Tcl_Pid pid;
- int *statPtr;
- int options;
+Tcl_WaitPid(
+ Tcl_Pid pid,
+ int *statPtr,
+ int options)
{
int result;
- pid_t real_pid;
+ pid_t real_pid = (pid_t) PTR2INT(pid);
- real_pid = (pid_t) pid;
while (1) {
result = (int) waitpid(real_pid, statPtr, options);
if ((result != -1) || (errno != EINTR)) {
- return (Tcl_Pid) result;
+ return (Tcl_Pid) INT2PTR(result);
}
}
}
@@ -1213,8 +1170,8 @@ Tcl_WaitPid(pid, statPtr, options)
*
* Tcl_PidObjCmd --
*
- * This procedure is invoked to process the "pid" Tcl command.
- * See the user documentation for details on what it does.
+ * This function is invoked to process the "pid" Tcl command. See the
+ * user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -1227,39 +1184,49 @@ Tcl_WaitPid(pid, statPtr, options)
/* ARGSUSED */
int
-Tcl_PidObjCmd(dummy, interp, objc, objv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST *objv; /* Argument strings. */
+Tcl_PidObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const *objv) /* Argument strings. */
{
- Tcl_Channel chan;
- Tcl_ChannelType *chanTypePtr;
- PipeState *pipePtr;
- int i;
- Tcl_Obj *resultPtr, *longObjPtr;
-
if (objc > 2) {
Tcl_WrongNumArgs(interp, 1, objv, "?channelId?");
return TCL_ERROR;
}
+
if (objc == 1) {
- Tcl_SetLongObj(Tcl_GetObjResult(interp), (long) getpid());
+ Tcl_SetObjResult(interp, Tcl_NewLongObj((long) getpid()));
} else {
- chan = Tcl_GetChannel(interp, Tcl_GetString(objv[1]), NULL);
- if (chan == (Tcl_Channel) NULL) {
+ /*
+ * Get the channel and make sure that it refers to a pipe.
+ */
+ Tcl_Channel chan;
+ const Tcl_ChannelType *chanTypePtr;
+ PipeState *pipePtr;
+ int i;
+ Tcl_Obj *resultPtr, *longObjPtr;
+
+ chan = Tcl_GetChannel(interp, Tcl_GetString(objv[1]), NULL);
+ if (chan == (Tcl_Channel) NULL) {
return TCL_ERROR;
}
chanTypePtr = Tcl_GetChannelType(chan);
if (chanTypePtr != &pipeChannelType) {
return TCL_OK;
}
- pipePtr = (PipeState *) Tcl_GetChannelInstanceData(chan);
- resultPtr = Tcl_GetObjResult(interp);
- for (i = 0; i < pipePtr->numPids; i++) {
+
+ /*
+ * Extract the process IDs from the pipe structure.
+ */
+
+ pipePtr = (PipeState *) Tcl_GetChannelInstanceData(chan);
+ resultPtr = Tcl_NewObj();
+ for (i = 0; i < pipePtr->numPids; i++) {
longObjPtr = Tcl_NewLongObj((long) TclpGetPid(pipePtr->pidPtr[i]));
Tcl_ListObjAppendElement(NULL, resultPtr, longObjPtr);
}
+ Tcl_SetObjResult(interp, resultPtr);
}
return TCL_OK;
}
@@ -1274,13 +1241,21 @@ Tcl_PidObjCmd(dummy, interp, objc, objv)
* Results:
* None.
*
- * This procedure carries out no operation on Unix.
+ * Notes:
+ * This function carries out no operation on Unix.
*
*----------------------------------------------------------------------
*/
void
-TclpFinalizePipes()
+TclpFinalizePipes(void)
{
}
-
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixPort.h b/unix/tclUnixPort.h
index c1aaa63..421d73c 100644
--- a/unix/tclUnixPort.h
+++ b/unix/tclUnixPort.h
@@ -23,8 +23,8 @@
#ifndef _TCLUNIXPORT
#define _TCLUNIXPORT
-#ifndef _TCLINT
-# include "tclInt.h"
+#ifndef MODULE_SCOPE
+#define MODULE_SCOPE extern
#endif
/*
@@ -81,26 +81,11 @@ typedef off_t Tcl_SeekOffset;
# define TclOSlstat lstat
#endif
-#if !HAVE_STRTOLL && defined(TCL_WIDE_INT_TYPE) && !TCL_WIDE_INT_IS_LONG
-EXTERN Tcl_WideInt strtoll _ANSI_ARGS_((CONST char *string,
- char **endPtr, int base));
-EXTERN Tcl_WideUInt strtoull _ANSI_ARGS_((CONST char *string,
- char **endPtr, int base));
-#endif
-
#include <sys/file.h>
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif
#include <sys/stat.h>
-
-#ifdef __CYGWIN__
-# define timezone _timezone
- typedef long TIMEZONE_t;
-#else /* !__CYGWIN__ */
- typedef int TIMEZONE_t;
-#endif /* !__CYGWIN__ */
-
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
@@ -114,32 +99,31 @@ EXTERN Tcl_WideUInt strtoull _ANSI_ARGS_((CONST char *string,
#ifndef NO_SYS_WAIT_H
# include <sys/wait.h>
#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef NO_LIMITS_H
+# include "../compat/limits.h"
+#else
+# include <limits.h>
+#endif
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#else
# include "../compat/unistd.h"
#endif
-#ifdef USE_FIONBIO
- /*
- * Not using the Posix fcntl(...,O_NONBLOCK,...) interface, instead
- * we are using ioctl(..,FIONBIO,..).
- */
-# ifdef HAVE_SYS_FILIO_H
-# include <sys/filio.h> /* For FIONBIO. */
-# endif
+MODULE_SCOPE int TclUnixSetBlockingMode(int fd, int mode);
-# ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h> /* For FIONBIO. */
-# endif
-#endif /* USE_FIONBIO */
#include <utime.h>
/*
* Socket support stuff: This likely needs more work to parameterize for
* each system.
*/
-
#include <sys/socket.h> /* struct sockaddr, SOCK_STREAM, ... */
#ifndef NO_UNAME
# include <sys/utsname.h> /* uname system call. */
@@ -186,18 +170,6 @@ EXTERN Tcl_WideUInt strtoull _ANSI_ARGS_((CONST char *string,
#endif
/*
- * HPUX needs the flag O_NONBLOCK to get the right non-blocking I/O
- * semantics, while most other systems need O_NDELAY. Define the
- * constant NBIO_FLAG to be one of these
- */
-
-#ifdef HPUX
-# define NBIO_FLAG O_NONBLOCK
-#else
-# define NBIO_FLAG O_NDELAY
-#endif
-
-/*
* The type of the status returned by wait varies from UNIX system
* to UNIX system. The macro below defines it:
*/
@@ -270,21 +242,11 @@ EXTERN Tcl_WideUInt strtoull _ANSI_ARGS_((CONST char *string,
/*
* The stuff below is needed by the "time" command. If this system has no
- * gettimeofday call, then must use times and the CLK_TCK #define (from
- * sys/param.h) to compute elapsed time. Unfortunately, some systems only
- * have HZ and no CLK_TCK, and some might not even have HZ.
+ * gettimeofday call, then must use times() instead.
*/
#ifdef NO_GETTOD
# include <sys/times.h>
-# include <sys/param.h>
-# ifndef CLK_TCK
-# ifdef HZ
-# define CLK_TCK HZ
-# else
-# define CLK_TCK 60
-# endif
-# endif
#else
# ifdef HAVE_BSDGETTIMEOFDAY
# define gettimeofday BSDgettimeofday
@@ -470,7 +432,7 @@ EXTERN int gettimeofday _ANSI_ARGS_((struct timeval *tp,
#ifdef NO_ERRNO
extern int errno;
-#endif
+#endif /* NO_ERRNO */
/*
* Not all systems declare all the errors that Tcl uses! Provide some
@@ -501,16 +463,6 @@ extern char **environ;
#endif
/*
- * At present (12/91) not all stdlib.h implementations declare strtod.
- * The declaration below is here to ensure that it's declared, so that
- * the compiler won't take the default approach of assuming it returns
- * an int. There's no ANSI prototype for it because there would end
- * up being too many conflicts with slightly-different prototypes.
- */
-
-extern double strtod();
-
-/*
* There is no platform-specific panic routine for Unix in the Tcl internals.
*/
@@ -604,33 +556,6 @@ extern double strtod();
#endif /* __APPLE__ */
/*
- * Darwin 8 copyfile API.
- */
-
-#ifdef HAVE_COPYFILE
-#ifdef HAVE_COPYFILE_H
-#include <copyfile.h>
-#if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040
-/* Support for weakly importing copyfile. */
-#define WEAK_IMPORT_COPYFILE
-extern int copyfile(const char *from, const char *to, copyfile_state_t state,
- copyfile_flags_t flags) WEAK_IMPORT_ATTRIBUTE;
-#endif /* HAVE_WEAK_IMPORT */
-#else /* HAVE_COPYFILE_H */
-int copyfile(const char *from, const char *to, void *state, uint32_t flags);
-#define COPYFILE_ACL (1<<0)
-#define COPYFILE_XATTR (1<<2)
-#define COPYFILE_NOFOLLOW_SRC (1<<18)
-#if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040
-/* Support for weakly importing copyfile. */
-#define WEAK_IMPORT_COPYFILE
-extern int copyfile(const char *from, const char *to, void *state,
- uint32_t flags) WEAK_IMPORT_ATTRIBUTE;
-#endif /* HAVE_WEAK_IMPORT */
-#endif /* HAVE_COPYFILE_H */
-#endif /* HAVE_COPYFILE */
-
-/*
*---------------------------------------------------------------------------
* The following macros and declarations represent the interface between
* generic and unix-specific parts of Tcl. Some of the macros may override
@@ -644,6 +569,7 @@ extern int copyfile(const char *from, const char *to, void *state,
#ifdef DJGPP
#define TCL_PLATFORM_TRANSLATION TCL_TRANSLATE_CRLF
+typedef int socklen_t;
#else
#define TCL_PLATFORM_TRANSLATION TCL_TRANSLATE_LF
#endif
@@ -657,15 +583,12 @@ extern int copyfile(const char *from, const char *to, void *state,
#define TclpReleaseFile(file) /* Nothing. */
/*
- * The following defines wrap the system memory allocation routines for
- * use by tclAlloc.c. By default off unused on Unix.
+ * The following defines wrap the system memory allocation routines.
*/
-#if USE_TCLALLOC
-# define TclpSysAlloc(size, isBin) malloc((size_t)size)
-# define TclpSysFree(ptr) free((char*)ptr)
-# define TclpSysRealloc(ptr, size) realloc((char*)ptr, (size_t)size)
-#endif
+#define TclpSysAlloc(size, isBin) malloc((size_t)size)
+#define TclpSysFree(ptr) free((char*)ptr)
+#define TclpSysRealloc(ptr, size) realloc((char*)ptr, (size_t)size)
/*
* The following macros and declaration wrap the C runtime library
@@ -674,55 +597,49 @@ extern int copyfile(const char *from, const char *to, void *state,
#define TclpExit exit
-/*
- * Platform specific mutex definition used by memory allocators.
- * These mutexes are statically allocated and explicitly initialized.
- * Most modules do not use this, but instead use Tcl_Mutex types and
- * Tcl_MutexLock and Tcl_MutexUnlock that are self-initializing.
- */
-
#ifdef TCL_THREADS
-#include <pthread.h>
-typedef pthread_mutex_t TclpMutex;
-EXTERN void TclpMutexInit _ANSI_ARGS_((TclpMutex *mPtr));
-EXTERN void TclpMutexLock _ANSI_ARGS_((TclpMutex *mPtr));
-EXTERN void TclpMutexUnlock _ANSI_ARGS_((TclpMutex *mPtr));
-EXTERN Tcl_DirEntry * TclpReaddir(DIR *);
-#ifndef TclpLocaltime
-EXTERN struct tm * TclpLocaltime(TclpTime_t_CONST);
-#endif
-#ifndef TclpGmtime
-EXTERN struct tm * TclpGmtime(TclpTime_t_CONST);
-#endif
+EXTERN struct tm * TclpLocaltime(CONST time_t *);
+EXTERN struct tm * TclpGmtime(CONST time_t *);
EXTERN char * TclpInetNtoa(struct in_addr);
-#define inet_ntoa(x) TclpInetNtoa(x)
-#else
-typedef int TclpMutex;
-#define TclpMutexInit(a)
-#define TclpMutexLock(a)
-#define TclpMutexUnlock(a)
+/* #define localtime(x) TclpLocaltime(x)
+ * #define gmtime(x) TclpGmtime(x) */
+# undef inet_ntoa
+# define inet_ntoa(x) TclpInetNtoa(x)
+# ifdef HAVE_PTHREAD_ATTR_GET_NP
+# define TclpPthreadGetAttrs pthread_attr_get_np
+# ifdef ATTRGETNP_NOT_DECLARED
+/*
+ * Assume it is in pthread_np.h if it isn't in pthread.h. [Bug 1064882]
+ * We might need to revisit this in the future. :^(
+ */
+# include <pthread.h>
+# include <pthread_np.h>
+# endif
+# else
+# ifdef HAVE_PTHREAD_GETATTR_NP
+# define TclpPthreadGetAttrs pthread_getattr_np
+# ifdef GETATTRNP_NOT_DECLARED
+EXTERN int pthread_getattr_np _ANSI_ARGS_((pthread_t, pthread_attr_t *));
+# endif
+# endif /* HAVE_PTHREAD_GETATTR_NP */
+# endif /* HAVE_PTHREAD_ATTR_GET_NP */
#endif /* TCL_THREADS */
-
/*
* Set of MT-safe implementations of some
* known-to-be-MT-unsafe library calls.
* Instead of returning pointers to the
* static storage, those return pointers
- * to the TSD data.
+ * to the TSD data.
*/
-#include <pwd.h>
#include <grp.h>
-EXTERN struct passwd* TclpGetPwNam(const char *name);
-EXTERN struct group* TclpGetGrNam(const char *name);
-EXTERN struct passwd* TclpGetPwUid(uid_t uid);
-EXTERN struct group* TclpGetGrGid(gid_t gid);
-EXTERN struct hostent* TclpGetHostByName(const char *name);
-EXTERN struct hostent* TclpGetHostByAddr(const char *addr, int length, int type);
-
-#include "tclPlatDecls.h"
-#include "tclIntPlatDecls.h"
+MODULE_SCOPE struct passwd* TclpGetPwNam(const char *name);
+MODULE_SCOPE struct group* TclpGetGrNam(const char *name);
+MODULE_SCOPE struct passwd* TclpGetPwUid(uid_t uid);
+MODULE_SCOPE struct group* TclpGetGrGid(gid_t gid);
+MODULE_SCOPE struct hostent* TclpGetHostByName(const char *name);
+MODULE_SCOPE struct hostent* TclpGetHostByAddr(const char *addr, int length, int type);
#endif /* _TCLUNIXPORT */
diff --git a/unix/tclUnixSock.c b/unix/tclUnixSock.c
index cb3cc36..a2b4015 100644
--- a/unix/tclUnixSock.c
+++ b/unix/tclUnixSock.c
@@ -1,96 +1,66 @@
-/*
+/*
* tclUnixSock.c --
*
* This file contains Unix-specific socket related code.
*
* Copyright (c) 1995 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
-#include "tcl.h"
-#include "tclPort.h"
-
-/*
- * There is no portable macro for the maximum length
- * of host names returned by gethostbyname(). We should only
- * trust SYS_NMLN if it is at least 255 + 1 bytes to comply with DNS
- * host name limits.
- *
- * Note: SYS_NMLN is a restriction on "uname" not on gethostbyname!
- *
- * For example HP-UX 10.20 has SYS_NMLN == 9, while gethostbyname()
- * can return a fully qualified name from DNS of up to 255 bytes.
- *
- * Fix suggested by Viktor Dukhovni (viktor@esm.com)
- */
-
-#if defined(SYS_NMLN) && SYS_NMLEN >= 256
-#define TCL_HOSTNAME_LEN SYS_NMLEN
-#else
-#define TCL_HOSTNAME_LEN 256
-#endif
-
+#include "tclInt.h"
/*
* The following variable holds the network name of this host.
*/
-static char hostname[TCL_HOSTNAME_LEN + 1];
-static int hostnameInited = 0;
-TCL_DECLARE_MUTEX(hostMutex)
+static TclInitProcessGlobalValueProc InitializeHostName;
+static ProcessGlobalValue hostName =
+ {0, 0, NULL, NULL, InitializeHostName, NULL, NULL};
/*
*----------------------------------------------------------------------
*
- * Tcl_GetHostName --
+ * InitializeHostName --
*
- * Returns the name of the local host.
+ * This routine sets the process global value of the name of the local
+ * host on which the process is running.
*
* Results:
- * A string containing the network name for this machine, or
- * an empty string if we can't figure out the name. The caller
- * must not modify or free this string.
- *
- * Side effects:
* None.
*
*----------------------------------------------------------------------
*/
-CONST char *
-Tcl_GetHostName()
+static void
+InitializeHostName(
+ char **valuePtr,
+ int *lengthPtr,
+ Tcl_Encoding *encodingPtr)
{
+ CONST char *native = NULL;
+
#ifndef NO_UNAME
struct utsname u;
struct hostent *hp;
-#else
- char buffer[sizeof(hostname)];
-#endif
- CONST char *native;
- Tcl_MutexLock(&hostMutex);
- if (hostnameInited) {
- Tcl_MutexUnlock(&hostMutex);
- return hostname;
- }
-
- native = NULL;
-#ifndef NO_UNAME
- (VOID *) memset((VOID *) &u, (int) 0, sizeof(struct utsname));
+ memset(&u, (int) 0, sizeof(struct utsname));
if (uname(&u) > -1) { /* INTL: Native. */
- hp = TclpGetHostByName(u.nodename); /* INTL: Native. */
+ hp = TclpGetHostByName(u.nodename); /* INTL: Native. */
if (hp == NULL) {
/*
* Sometimes the nodename is fully qualified, but gets truncated
- * as it exceeds SYS_NMLN. See if we can just get the immediate
+ * as it exceeds SYS_NMLN. See if we can just get the immediate
* nodename and get a proper answer that way.
*/
+
char *dot = strchr(u.nodename, '.');
+
if (dot != NULL) {
char *node = ckalloc((unsigned) (dot - u.nodename + 1));
+
memcpy(node, u.nodename, (size_t) (dot - u.nodename));
node[dot - u.nodename] = '\0';
hp = TclpGetHostByName(node);
@@ -103,25 +73,64 @@ Tcl_GetHostName()
native = u.nodename;
}
}
+ if (native == NULL) {
+ native = tclEmptyStringRep;
+ }
#else
/*
* Uname doesn't exist; try gethostname instead.
+ *
+ * There is no portable macro for the maximum length of host names
+ * returned by gethostbyname(). We should only trust SYS_NMLN if it is at
+ * least 255 + 1 bytes to comply with DNS host name limits.
+ *
+ * Note: SYS_NMLN is a restriction on "uname" not on gethostbyname!
+ *
+ * For example HP-UX 10.20 has SYS_NMLN == 9, while gethostbyname() can
+ * return a fully qualified name from DNS of up to 255 bytes.
+ *
+ * Fix suggested by Viktor Dukhovni (viktor@esm.com)
*/
+# if defined(SYS_NMLN) && SYS_NMLEN >= 256
+ char buffer[SYS_NMLEN];
+# else
+ char buffer[256];
+# endif
+
if (gethostname(buffer, sizeof(buffer)) > -1) { /* INTL: Native. */
native = buffer;
}
#endif
- if (native == NULL) {
- hostname[0] = 0;
- } else {
- Tcl_ExternalToUtf(NULL, NULL, native, -1, 0, NULL, hostname,
- sizeof(hostname), NULL, NULL, NULL);
- }
- hostnameInited = 1;
- Tcl_MutexUnlock(&hostMutex);
- return hostname;
+ *encodingPtr = Tcl_GetEncoding(NULL, NULL);
+ *lengthPtr = strlen(native);
+ *valuePtr = ckalloc((unsigned int) (*lengthPtr)+1);
+ memcpy(*valuePtr, (void *) native, (size_t)(*lengthPtr)+1);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetHostName --
+ *
+ * Returns the name of the local host.
+ *
+ * Results:
+ * A string containing the network name for this machine, or an empty
+ * string if we can't figure out the name. The caller must not modify or
+ * free this string.
+ *
+ * Side effects:
+ * Caches the name to return for future calls.
+ *
+ *----------------------------------------------------------------------
+ */
+
+CONST char *
+Tcl_GetHostName(void)
+{
+ return Tcl_GetString(TclGetProcessGlobalValue(&hostName));
}
/*
@@ -141,8 +150,8 @@ Tcl_GetHostName()
*/
int
-TclpHasSockets(interp)
- Tcl_Interp *interp; /* Not used. */
+TclpHasSockets(
+ Tcl_Interp *interp) /* Not used. */
{
return TCL_OK;
}
@@ -164,7 +173,15 @@ TclpHasSockets(interp)
*/
void
-TclpFinalizeSockets()
+TclpFinalizeSockets(void)
{
return;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixTest.c b/unix/tclUnixTest.c
index b657aeb..b6529c2 100644
--- a/unix/tclUnixTest.c
+++ b/unix/tclUnixTest.c
@@ -1,4 +1,4 @@
-/*
+/*
* tclUnixTest.c --
*
* Contains platform specific test commands for the Unix platform.
@@ -6,29 +6,28 @@
* Copyright (c) 1996-1997 Sun Microsystems, Inc.
* Copyright (c) 1998 by Scriptics Corporation.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
/*
- * The headers are needed for the testalarm command that verifies the
- * use of SA_RESTART in signal handlers.
+ * The headers are needed for the testalarm command that verifies the use of
+ * SA_RESTART in signal handlers.
*/
#include <signal.h>
#include <sys/resource.h>
/*
- * The following macros convert between TclFile's and fd's. The conversion
+ * The following macros convert between TclFile's and fd's. The conversion
* simple involves shifting fd's up by one to ensure that no valid fd is ever
- * the same as NULL. Note that this code is duplicated from tclUnixPipe.c
+ * the same as NULL. Note that this code is duplicated from tclUnixPipe.c
*/
-#define MakeFile(fd) ((TclFile)((fd)+1))
-#define GetFd(file) (((int)file)-1)
+#define MakeFile(fd) ((TclFile)INT2PTR(((int)(fd))+1))
+#define GetFd(file) (PTR2INT(file)-1)
/*
* The stuff below is used to keep track of file handlers created and
@@ -36,16 +35,15 @@
*/
typedef struct Pipe {
- TclFile readFile; /* File handle for reading from the
- * pipe. NULL means pipe doesn't exist yet. */
- TclFile writeFile; /* File handle for writing from the
- * pipe. */
- int readCount; /* Number of times the file handler for
- * this file has triggered and the file
- * was readable. */
- int writeCount; /* Number of times the file handler for
- * this file has triggered and the file
- * was writable. */
+ TclFile readFile; /* File handle for reading from the pipe.
+ * NULL means pipe doesn't exist yet. */
+ TclFile writeFile; /* File handle for writing from the pipe. */
+ int readCount; /* Number of times the file handler for this
+ * file has triggered and the file was
+ * readable. */
+ int writeCount; /* Number of times the file handler for this
+ * file has triggered and the file was
+ * writable. */
} Pipe;
#define MAX_PIPES 10
@@ -58,39 +56,38 @@ static Pipe testPipes[MAX_PIPES];
static char *gotsig = "0";
/*
- * Forward declarations of procedures defined later in this file:
+ * Forward declarations of functions defined later in this file:
*/
-static void TestFileHandlerProc _ANSI_ARGS_((ClientData clientData,
- int mask));
-static int TestfilehandlerCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestfilewaitCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestfindexecutableCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestgetopenfileCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestgetdefencdirCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestsetdefencdirCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-int TclplatformtestInit _ANSI_ARGS_((Tcl_Interp *interp));
-static int TestalarmCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static int TestgotsigCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
-static void AlarmHandler _ANSI_ARGS_(());
-static int TestchmodCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, CONST char **argv));
+static void TestFileHandlerProc(ClientData clientData, int mask);
+static int TestfilehandlerCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, CONST char **argv);
+static int TestfilewaitCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, CONST char **argv);
+static int TestfindexecutableCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, CONST char **argv);
+static int TestgetopenfileCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, CONST char **argv);
+static int TestgetdefencdirCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, CONST char **argv);
+static int TestsetdefencdirCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, CONST char **argv);
+int TclplatformtestInit(Tcl_Interp *interp);
+static int TestalarmCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, CONST char **argv);
+static int TestgotsigCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, CONST char **argv);
+static void AlarmHandler(int signum);
+static int TestchmodCmd(ClientData dummy,
+ Tcl_Interp *interp, int argc, CONST char **argv);
/*
*----------------------------------------------------------------------
*
* TclplatformtestInit --
*
- * Defines commands that test platform specific functionality for
- * Unix platforms.
+ * Defines commands that test platform specific functionality for Unix
+ * platforms.
*
* Results:
* A standard Tcl result.
@@ -102,27 +99,27 @@ static int TestchmodCmd _ANSI_ARGS_((ClientData dummy,
*/
int
-TclplatformtestInit(interp)
- Tcl_Interp *interp; /* Interpreter to add commands to. */
+TclplatformtestInit(
+ Tcl_Interp *interp) /* Interpreter to add commands to. */
{
Tcl_CreateCommand(interp, "testchmod", TestchmodCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testfilehandler", TestfilehandlerCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testfilewait", TestfilewaitCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testfindexecutable", TestfindexecutableCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testgetopenfile", TestgetopenfileCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testgetdefenc", TestgetdefencdirCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testsetdefenc", TestsetdefencdirCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testalarm", TestalarmCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
Tcl_CreateCommand(interp, "testgotsig", TestgotsigCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
return TCL_OK;
}
@@ -131,9 +128,8 @@ TclplatformtestInit(interp)
*
* TestfilehandlerCmd --
*
- * This procedure implements the "testfilehandler" command. It is
- * used to test Tcl_CreateFileHandler, Tcl_DeleteFileHandler, and
- * TclWaitForFile.
+ * This function implements the "testfilehandler" command. It is used to
+ * test Tcl_CreateFileHandler, Tcl_DeleteFileHandler, and TclWaitForFile.
*
* Results:
* A standard Tcl result.
@@ -145,11 +141,11 @@ TclplatformtestInit(interp)
*/
static int
-TestfilehandlerCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestfilehandlerCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ CONST char **argv) /* Argument strings. */
{
Pipe *pipePtr;
int i, mask, timeout;
@@ -161,7 +157,7 @@ TestfilehandlerCmd(clientData, interp, argc, argv)
* NOTE: When we make this code work on Windows also, the following
* variable needs to be made Unix-only.
*/
-
+
if (!initialized) {
for (i = 0; i < MAX_PIPES; i++) {
testPipes[i].readFile = NULL;
@@ -171,7 +167,7 @@ TestfilehandlerCmd(clientData, interp, argc, argv)
if (argc < 2) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
- " option ... \"", (char *) NULL);
+ " option ... \"", NULL);
return TCL_ERROR;
}
pipePtr = NULL;
@@ -180,7 +176,7 @@ TestfilehandlerCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
if (i >= MAX_PIPES) {
- Tcl_AppendResult(interp, "bad index ", argv[2], (char *) NULL);
+ Tcl_AppendResult(interp, "bad index ", argv[2], NULL);
return TCL_ERROR;
}
pipePtr = &testPipes[i];
@@ -198,16 +194,16 @@ TestfilehandlerCmd(clientData, interp, argc, argv)
} else if (strcmp(argv[1], "clear") == 0) {
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"",
- argv[0], " clear index\"", (char *) NULL);
+ argv[0], " clear index\"", NULL);
return TCL_ERROR;
}
pipePtr->readCount = pipePtr->writeCount = 0;
} else if (strcmp(argv[1], "counts") == 0) {
char buf[TCL_INTEGER_SPACE * 2];
-
+
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"",
- argv[0], " counts index\"", (char *) NULL);
+ argv[0], " counts index\"", NULL);
return TCL_ERROR;
}
sprintf(buf, "%d %d", pipePtr->readCount, pipePtr->writeCount);
@@ -215,14 +211,13 @@ TestfilehandlerCmd(clientData, interp, argc, argv)
} else if (strcmp(argv[1], "create") == 0) {
if (argc != 5) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"",
- argv[0], " create index readMode writeMode\"",
- (char *) NULL);
+ argv[0], " create index readMode writeMode\"", NULL);
return TCL_ERROR;
}
if (pipePtr->readFile == NULL) {
if (!TclpCreatePipe(&pipePtr->readFile, &pipePtr->writeFile)) {
Tcl_AppendResult(interp, "couldn't open pipe: ",
- Tcl_PosixError(interp), (char *) NULL);
+ Tcl_PosixError(interp), NULL);
return TCL_ERROR;
}
#ifdef O_NONBLOCK
@@ -246,8 +241,7 @@ TestfilehandlerCmd(clientData, interp, argc, argv)
Tcl_CreateFileHandler(GetFd(pipePtr->readFile), 0,
TestFileHandlerProc, (ClientData) pipePtr);
} else {
- Tcl_AppendResult(interp, "bad read mode \"", argv[3], "\"",
- (char *) NULL);
+ Tcl_AppendResult(interp, "bad read mode \"", argv[3], "\"", NULL);
return TCL_ERROR;
}
if (strcmp(argv[4], "writable") == 0) {
@@ -259,14 +253,13 @@ TestfilehandlerCmd(clientData, interp, argc, argv)
Tcl_CreateFileHandler(GetFd(pipePtr->writeFile), 0,
TestFileHandlerProc, (ClientData) pipePtr);
} else {
- Tcl_AppendResult(interp, "bad read mode \"", argv[4], "\"",
- (char *) NULL);
+ Tcl_AppendResult(interp, "bad read mode \"", argv[4], "\"", NULL);
return TCL_ERROR;
}
} else if (strcmp(argv[1], "empty") == 0) {
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"",
- argv[0], " empty index\"", (char *) NULL);
+ argv[0], " empty index\"", NULL);
return TCL_ERROR;
}
@@ -276,24 +269,24 @@ TestfilehandlerCmd(clientData, interp, argc, argv)
} else if (strcmp(argv[1], "fill") == 0) {
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"",
- argv[0], " fill index\"", (char *) NULL);
+ argv[0], " fill index\"", NULL);
return TCL_ERROR;
}
- memset((VOID *) buffer, 'a', 4000);
+ memset(buffer, 'a', 4000);
while (write(GetFd(pipePtr->writeFile), buffer, 4000) > 0) {
/* Empty loop body. */
}
} else if (strcmp(argv[1], "fillpartial") == 0) {
char buf[TCL_INTEGER_SPACE];
-
+
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"",
- argv[0], " fillpartial index\"", (char *) NULL);
+ argv[0], " fillpartial index\"", NULL);
return TCL_ERROR;
}
- memset((VOID *) buffer, 'b', 10);
+ memset(buffer, 'b', 10);
TclFormatInt(buf, write(GetFd(pipePtr->writeFile), buffer, 10));
Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if (strcmp(argv[1], "oneevent") == 0) {
@@ -301,13 +294,11 @@ TestfilehandlerCmd(clientData, interp, argc, argv)
} else if (strcmp(argv[1], "wait") == 0) {
if (argc != 5) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"",
- argv[0], " wait index readable|writable timeout\"",
- (char *) NULL);
+ argv[0], " wait index readable|writable timeout\"", NULL);
return TCL_ERROR;
}
if (pipePtr->readFile == NULL) {
- Tcl_AppendResult(interp, "pipe ", argv[2], " doesn't exist",
- (char *) NULL);
+ Tcl_AppendResult(interp, "pipe ", argv[2], " doesn't exist", NULL);
return TCL_ERROR;
}
if (strcmp(argv[3], "readable") == 0) {
@@ -331,17 +322,17 @@ TestfilehandlerCmd(clientData, interp, argc, argv)
Tcl_DoOneEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT);
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be close, clear, counts, create, empty, fill, ",
- "fillpartial, oneevent, wait, or windowevent",
- (char *) NULL);
+ "\": must be close, clear, counts, create, empty, fill, "
+ "fillpartial, oneevent, wait, or windowevent", NULL);
return TCL_ERROR;
}
return TCL_OK;
}
-static void TestFileHandlerProc(clientData, mask)
- ClientData clientData; /* Points to a Pipe structure. */
- int mask; /* Indicates which events happened:
+static void
+TestFileHandlerProc(
+ ClientData clientData, /* Points to a Pipe structure. */
+ int mask) /* Indicates which events happened:
* TCL_READABLE or TCL_WRITABLE. */
{
Pipe *pipePtr = (Pipe *) clientData;
@@ -359,8 +350,8 @@ static void TestFileHandlerProc(clientData, mask)
*
* TestfilewaitCmd --
*
- * This procedure implements the "testfilewait" command. It is
- * used to test TclUnixWaitForFile.
+ * This function implements the "testfilewait" command. It is used to
+ * test TclUnixWaitForFile.
*
* Results:
* A standard Tcl result.
@@ -372,11 +363,11 @@ static void TestFileHandlerProc(clientData, mask)
*/
static int
-TestfilewaitCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestfilewaitCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ CONST char **argv) /* Argument strings. */
{
int mask, result, timeout;
Tcl_Channel channel;
@@ -385,7 +376,7 @@ TestfilewaitCmd(clientData, interp, argc, argv)
if (argc != 4) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
- " file readable|writable|both timeout\"", (char *) NULL);
+ " file readable|writable|both timeout\"", NULL);
return TCL_ERROR;
}
channel = Tcl_GetChannel(interp, argv[1], NULL);
@@ -400,16 +391,16 @@ TestfilewaitCmd(clientData, interp, argc, argv)
mask = TCL_WRITABLE|TCL_READABLE;
} else {
Tcl_AppendResult(interp, "bad argument \"", argv[2],
- "\": must be readable, writable, or both", (char *) NULL);
+ "\": must be readable, writable, or both", NULL);
return TCL_ERROR;
}
- if (Tcl_GetChannelHandle(channel,
+ if (Tcl_GetChannelHandle(channel,
(mask & TCL_READABLE) ? TCL_READABLE : TCL_WRITABLE,
(ClientData*) &data) != TCL_OK) {
Tcl_SetResult(interp, "couldn't get channel file", TCL_STATIC);
return TCL_ERROR;
}
- fd = (int) data;
+ fd = PTR2INT(data);
if (Tcl_GetInt(interp, argv[3], &timeout) != TCL_OK) {
return TCL_ERROR;
}
@@ -428,8 +419,8 @@ TestfilewaitCmd(clientData, interp, argc, argv)
*
* TestfindexecutableCmd --
*
- * This procedure implements the "testfindexecutable" command. It is
- * used to test Tcl_FindExecutable.
+ * This function implements the "testfindexecutable" command. It is used
+ * to test TclpFindExecutable.
*
* Results:
* A standard Tcl result.
@@ -441,39 +432,28 @@ TestfilewaitCmd(clientData, interp, argc, argv)
*/
static int
-TestfindexecutableCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestfindexecutableCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ CONST char **argv) /* Argument strings. */
{
- char *oldName;
- char *oldNativeName;
+ Tcl_Obj *saveName;
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
- " argv0\"", (char *) NULL);
+ " argv0\"", NULL);
return TCL_ERROR;
}
- oldName = tclExecutableName;
- oldNativeName = tclNativeExecutableName;
-
- tclExecutableName = NULL;
- tclNativeExecutableName = NULL;
-
- Tcl_FindExecutable(argv[1]);
- if (tclExecutableName != NULL) {
- Tcl_SetResult(interp, tclExecutableName, TCL_VOLATILE);
- ckfree(tclExecutableName);
- }
- if (tclNativeExecutableName != NULL) {
- ckfree(tclNativeExecutableName);
- }
+ saveName = TclGetObjNameOfExecutable();
+ Tcl_IncrRefCount(saveName);
- tclExecutableName = oldName;
- tclNativeExecutableName = oldNativeName;
+ TclpFindExecutable(argv[1]);
+ Tcl_SetObjResult(interp, TclGetObjNameOfExecutable());
+ TclSetObjNameOfExecutable(saveName, NULL);
+ Tcl_DecrRefCount(saveName);
return TCL_OK;
}
@@ -482,8 +462,8 @@ TestfindexecutableCmd(clientData, interp, argc, argv)
*
* TestgetopenfileCmd --
*
- * This procedure implements the "testgetopenfile" command. It is
- * used to get a FILE * value from a registered channel.
+ * This function implements the "testgetopenfile" command. It is used to
+ * get a FILE * value from a registered channel.
*
* Results:
* A standard Tcl result.
@@ -495,19 +475,17 @@ TestfindexecutableCmd(clientData, interp, argc, argv)
*/
static int
-TestgetopenfileCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestgetopenfileCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ CONST char **argv) /* Argument strings. */
{
ClientData filePtr;
if (argc != 3) {
- Tcl_AppendResult(interp,
- "wrong # args: should be \"", argv[0],
- " channelName forWriting\"",
- (char *) NULL);
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " channelName forWriting\"", NULL);
return TCL_ERROR;
}
if (Tcl_GetOpenFile(interp, argv[1], atoi(argv[2]), 1, &filePtr)
@@ -516,7 +494,7 @@ TestgetopenfileCmd(clientData, interp, argc, argv)
}
if (filePtr == (ClientData) NULL) {
Tcl_AppendResult(interp,
- "Tcl_GetOpenFile succeeded but FILE * NULL!", (char *) NULL);
+ "Tcl_GetOpenFile succeeded but FILE * NULL!", NULL);
return TCL_ERROR;
}
return TCL_OK;
@@ -527,8 +505,8 @@ TestgetopenfileCmd(clientData, interp, argc, argv)
*
* TestsetdefencdirCmd --
*
- * This procedure implements the "testsetdefenc" command. It is
- * used to set the value of tclDefaultEncodingDir.
+ * This function implements the "testsetdefenc" command. It is used to
+ * test Tcl_SetDefaultEncodingDir().
*
* Results:
* A standard Tcl result.
@@ -540,29 +518,19 @@ TestgetopenfileCmd(clientData, interp, argc, argv)
*/
static int
-TestsetdefencdirCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestsetdefencdirCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ CONST char **argv) /* Argument strings. */
{
if (argc != 2) {
- Tcl_AppendResult(interp,
- "wrong # args: should be \"", argv[0],
- " defaultDir\"",
- (char *) NULL);
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " defaultDir\"", NULL);
return TCL_ERROR;
}
- if (tclDefaultEncodingDir != NULL) {
- ckfree(tclDefaultEncodingDir);
- tclDefaultEncodingDir = NULL;
- }
- if (*argv[1] != '\0') {
- tclDefaultEncodingDir = (char *)
- ckalloc((unsigned) strlen(argv[1]) + 1);
- strcpy(tclDefaultEncodingDir, argv[1]);
- }
+ Tcl_SetDefaultEncodingDir(argv[1]);
return TCL_OK;
}
@@ -571,8 +539,8 @@ TestsetdefencdirCmd(clientData, interp, argc, argv)
*
* TestgetdefencdirCmd --
*
- * This procedure implements the "testgetdefenc" command. It is
- * used to get the value of tclDefaultEncodingDir.
+ * This function implements the "testgetdefenc" command. It is used to
+ * test Tcl_GetDefaultEncodingDir().
*
* Results:
* A standard Tcl result.
@@ -584,32 +552,29 @@ TestsetdefencdirCmd(clientData, interp, argc, argv)
*/
static int
-TestgetdefencdirCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestgetdefencdirCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ CONST char **argv) /* Argument strings. */
{
if (argc != 1) {
- Tcl_AppendResult(interp,
- "wrong # args: should be \"", argv[0],
- (char *) NULL);
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], NULL);
return TCL_ERROR;
}
- if (tclDefaultEncodingDir != NULL) {
- Tcl_AppendResult(interp, tclDefaultEncodingDir, (char *) NULL);
- }
+ Tcl_AppendResult(interp, Tcl_GetDefaultEncodingDir(), NULL);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
+ *
* TestalarmCmd --
*
- * Test that EINTR is handled correctly by generating and
- * handling a signal. This requires using the SA_RESTART
- * flag when registering the signal handler.
+ * Test that EINTR is handled correctly by generating and handling a
+ * signal. This requires using the SA_RESTART flag when registering the
+ * signal handler.
*
* Results:
* None.
@@ -621,11 +586,11 @@ TestgetdefencdirCmd(clientData, interp, argc, argv)
*/
static int
-TestalarmCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestalarmCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ CONST char **argv) /* Argument strings. */
{
#ifdef SA_RESTART
unsigned int sec;
@@ -638,21 +603,24 @@ TestalarmCmd(clientData, interp, argc, argv)
}
/*
- * Setup the signal handling that automatically retries
- * any interupted I/O system calls.
+ * Setup the signal handling that automatically retries any interrupted
+ * I/O system calls.
*/
+
action.sa_handler = AlarmHandler;
- memset((void *)&action.sa_mask, 0, sizeof(sigset_t));
+ memset((void *) &action.sa_mask, 0, sizeof(sigset_t));
action.sa_flags = SA_RESTART;
if (sigaction(SIGALRM, &action, NULL) < 0) {
Tcl_AppendResult(interp, "sigaction: ", Tcl_PosixError(interp), NULL);
return TCL_ERROR;
}
- (void)alarm(sec);
+ (void) alarm(sec);
return TCL_OK;
#else
- Tcl_AppendResult(interp, "warning: sigaction SA_RESTART not support on this platform", NULL);
+ Tcl_AppendResult(interp,
+ "warning: sigaction SA_RESTART not support on this platform",
+ NULL);
return TCL_ERROR;
#endif
}
@@ -674,13 +642,15 @@ TestalarmCmd(clientData, interp, argc, argv)
*/
static void
-AlarmHandler()
+AlarmHandler(
+ int signum)
{
gotsig = "1";
}
/*
*----------------------------------------------------------------------
+ *
* TestgotsigCmd --
*
* Verify the signal was handled after the testalarm command.
@@ -695,13 +665,13 @@ AlarmHandler()
*/
static int
-TestgotsigCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestgotsigCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ CONST char **argv) /* Argument strings. */
{
- Tcl_AppendResult(interp, gotsig, (char *) NULL);
+ Tcl_AppendResult(interp, gotsig, NULL);
gotsig = "0";
return TCL_OK;
}
@@ -726,11 +696,11 @@ TestgotsigCmd(clientData, interp, argc, argv)
*/
static int
-TestchmodCmd(dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TestchmodCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ CONST char **argv) /* Argument strings. */
{
int i, mode;
char *rest;
diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c
index 7b99896..fd2cd8f 100644
--- a/unix/tclUnixThrd.c
+++ b/unix/tclUnixThrd.c
@@ -1,4 +1,4 @@
-/*
+/*
* tclUnixThrd.c --
*
* This file implements the UNIX-specific thread support.
@@ -6,12 +6,11 @@
* Copyright (c) 1991-1994 The Regents of the University of California.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclPort.h"
#ifdef TCL_THREADS
@@ -24,24 +23,23 @@ typedef struct ThreadSpecificData {
static Tcl_ThreadDataKey dataKey;
/*
- * masterLock is used to serialize creation of mutexes, condition
- * variables, and thread local storage.
- * This is the only place that can count on the ability to statically
- * initialize the mutex.
+ * masterLock is used to serialize creation of mutexes, condition variables,
+ * and thread local storage. This is the only place that can count on the
+ * ability to statically initialize the mutex.
*/
static pthread_mutex_t masterLock = PTHREAD_MUTEX_INITIALIZER;
/*
- * initLock is used to serialize initialization and finalization
- * of Tcl. It cannot use any dyamically allocated storage.
+ * initLock is used to serialize initialization and finalization of Tcl. It
+ * cannot use any dyamically allocated storage.
*/
static pthread_mutex_t initLock = PTHREAD_MUTEX_INITIALIZER;
/*
- * allocLock is used by Tcl's version of malloc for synchronization.
- * For obvious reasons, cannot use any dyamically allocated storage.
+ * allocLock is used by Tcl's version of malloc for synchronization. For
+ * obvious reasons, cannot use any dyamically allocated storage.
*/
static pthread_mutex_t allocLock = PTHREAD_MUTEX_INITIALIZER;
@@ -65,8 +63,8 @@ static pthread_mutex_t *allocLockPtr = &allocLock;
* This procedure creates a new thread.
*
* Results:
- * TCL_OK if the thread could be created. The thread ID is
- * returned in a parameter.
+ * TCL_OK if the thread could be created. The thread ID is returned in a
+ * parameter.
*
* Side effects:
* A new thread is created.
@@ -75,13 +73,13 @@ static pthread_mutex_t *allocLockPtr = &allocLock;
*/
int
-TclpThreadCreate(idPtr, proc, clientData, stackSize, flags)
- Tcl_ThreadId *idPtr; /* Return, the ID of the thread */
- Tcl_ThreadCreateProc proc; /* Main() function of the thread */
- ClientData clientData; /* The one argument to Main() */
- int stackSize; /* Size of stack for the new thread */
- int flags; /* Flags controlling behaviour of
- * the new thread */
+TclpThreadCreate(
+ Tcl_ThreadId *idPtr, /* Return, the ID of the thread */
+ Tcl_ThreadCreateProc proc, /* Main() function of the thread */
+ ClientData clientData, /* The one argument to Main() */
+ int stackSize, /* Size of stack for the new thread */
+ int flags) /* Flags controlling behaviour of the new
+ * thread. */
{
#ifdef TCL_THREADS
pthread_attr_t attr;
@@ -93,14 +91,14 @@ TclpThreadCreate(idPtr, proc, clientData, stackSize, flags)
#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
if (stackSize != TCL_THREAD_STACK_DEFAULT) {
- pthread_attr_setstacksize(&attr, (size_t) stackSize);
+ pthread_attr_setstacksize(&attr, (size_t) stackSize);
#ifdef TCL_THREAD_STACK_MIN
} else {
- /*
- * Certain systems define a thread stack size that by default is
- * too small for many operations. The user has the option of
- * defining TCL_THREAD_STACK_MIN to a value large enough to work
- * for their needs. This would look like (for 128K min stack):
+ /*
+ * Certain systems define a thread stack size that by default is too
+ * small for many operations. The user has the option of defining
+ * TCL_THREAD_STACK_MIN to a value large enough to work for their
+ * needs. This would look like (for 128K min stack):
* make MEM_DEBUG_FLAGS=-DTCL_THREAD_STACK_MIN=131072L
*
* This solution is not optimal, as we should allow the user to
@@ -108,7 +106,7 @@ TclpThreadCreate(idPtr, proc, clientData, stackSize, flags)
* down, and that would still leave the main thread at the default.
*/
- size_t size;
+ size_t size;
result = pthread_attr_getstacksize(&attr, &size);
if (!result && (size < TCL_THREAD_STACK_MIN)) {
pthread_attr_setstacksize(&attr, (size_t) TCL_THREAD_STACK_MIN);
@@ -117,14 +115,14 @@ TclpThreadCreate(idPtr, proc, clientData, stackSize, flags)
}
#endif
if (! (flags & TCL_THREAD_JOINABLE)) {
- pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+ pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
}
if (pthread_create(&theThread, &attr,
- (void * (*)())proc, (void *)clientData) &&
+ (void * (*)(void *))proc, (void *)clientData) &&
pthread_create(&theThread, NULL,
- (void * (*)())proc, (void *)clientData)) {
+ (void * (*)(void *))proc, (void *)clientData)) {
result = TCL_ERROR;
} else {
*idPtr = (Tcl_ThreadId)theThread;
@@ -148,24 +146,23 @@ TclpThreadCreate(idPtr, proc, clientData, stackSize, flags)
* TCL_OK if the wait was successful, TCL_ERROR else.
*
* Side effects:
- * The result area is set to the exit code of the thread we
- * waited upon.
+ * The result area is set to the exit code of the thread we waited upon.
*
*----------------------------------------------------------------------
*/
int
-Tcl_JoinThread(threadId, state)
- Tcl_ThreadId threadId; /* Id of the thread to wait upon */
- int* state; /* Reference to the storage the result
- * of the thread we wait upon will be
- * written into. */
+Tcl_JoinThread(
+ Tcl_ThreadId threadId, /* Id of the thread to wait upon. */
+ int *state) /* Reference to the storage the result of the
+ * thread we wait upon will be written into.
+ * May be NULL. */
{
#ifdef TCL_THREADS
int result;
- unsigned long retcode;
+ unsigned long retcode, *retcodePtr = &retcode;
- result = pthread_join((pthread_t) threadId, (void**) &retcode);
+ result = pthread_join((pthread_t) threadId, (void**) retcodePtr);
if (state) {
*state = (int) retcode;
}
@@ -193,10 +190,103 @@ Tcl_JoinThread(threadId, state)
*/
void
-TclpThreadExit(status)
- int status;
+TclpThreadExit(
+ int status)
+{
+ pthread_exit(INT2PTR(status));
+}
+#endif /* TCL_THREADS */
+
+#ifdef TCL_THREADS
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpThreadGetStackSize --
+ *
+ * This procedure returns the size of the current thread's stack.
+ *
+ * Results:
+ * Stack size (in bytes?) or -1 for error or 0 for undeterminable.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+size_t
+TclpThreadGetStackSize(void)
{
- pthread_exit((VOID *)status);
+ size_t stackSize = 0;
+#if defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) && defined(TclpPthreadGetAttrs)
+ pthread_attr_t threadAttr; /* This will hold the thread attributes for
+ * the current thread. */
+#ifdef __GLIBC__
+ /*
+ * Fix for [Bug 1815573]
+ *
+ * DESCRIPTION:
+ * On linux TclpPthreadGetAttrs (which is pthread_attr_get_np) may return
+ * bogus values on the initial thread.
+ *
+ * ASSUMPTIONS:
+ * There seems to be no api to determine if we are on the initial
+ * thread. The simple scheme implemented here assumes:
+ * 1. The first Tcl interp to be created lives in the initial thread. If
+ * this assumption is not true, the fix is to call
+ * TclpThreadGetStackSize from the initial thread previous to
+ * creating any Tcl interpreter. In this case, especially if another
+ * Tcl interpreter may be created in the initial thread, it might be
+ * better to enable the second branch in the #if below
+ * 2. There will be no races in creating the first Tcl interp - ie, the
+ * second Tcl interp will be created only after the first call to
+ * Tcl_CreateInterp returns.
+ *
+ * These assumptions are satisfied by tclsh. Embedders on linux may want
+ * to check their validity, and possibly adapt the code on failing to meet
+ * them.
+ */
+
+ static int initialized = 0;
+
+ if (!initialized) {
+ initialized = 1;
+ return 0;
+ } else {
+#else
+ {
+#endif
+ if (pthread_attr_init(&threadAttr) != 0) {
+ return -1;
+ }
+ if (TclpPthreadGetAttrs(pthread_self(), &threadAttr) != 0) {
+ pthread_attr_destroy(&threadAttr);
+ return (size_t)-1;
+ }
+ }
+
+
+ if (pthread_attr_getstacksize(&threadAttr, &stackSize) != 0) {
+ pthread_attr_destroy(&threadAttr);
+ return (size_t)-1;
+ }
+ pthread_attr_destroy(&threadAttr);
+#elif defined(HAVE_PTHREAD_GET_STACKSIZE_NP)
+#ifdef __APPLE__
+ /*
+ * On Darwin, the API below does not return the correct stack size for the
+ * main thread (which is not a real pthread), so fallback to getrlimit().
+ */
+ if (!pthread_main_np())
+#endif
+ stackSize = pthread_get_stacksize_np(pthread_self());
+#else
+ /*
+ * Cannot determine the real stack size of this thread. The caller might
+ * want to try looking at the process accounting limits instead.
+ */
+#endif
+ return stackSize;
}
#endif /* TCL_THREADS */
@@ -217,7 +307,7 @@ TclpThreadExit(status)
*/
Tcl_ThreadId
-Tcl_GetCurrentThread()
+Tcl_GetCurrentThread(void)
{
#ifdef TCL_THREADS
return (Tcl_ThreadId) pthread_self();
@@ -225,7 +315,6 @@ Tcl_GetCurrentThread()
return (Tcl_ThreadId) 0;
#endif
}
-
/*
*----------------------------------------------------------------------
@@ -233,9 +322,9 @@ Tcl_GetCurrentThread()
* TclpInitLock
*
* This procedure is used to grab a lock that serializes initialization
- * and finalization of Tcl. On some platforms this may also initialize
- * the mutex used to serialize creation of more mutexes and thread
- * local storage keys.
+ * and finalization of Tcl. On some platforms this may also initialize
+ * the mutex used to serialize creation of more mutexes and thread local
+ * storage keys.
*
* Results:
* None.
@@ -247,7 +336,7 @@ Tcl_GetCurrentThread()
*/
void
-TclpInitLock()
+TclpInitLock(void)
{
#ifdef TCL_THREADS
pthread_mutex_lock(&initLock);
@@ -259,28 +348,29 @@ TclpInitLock()
*
* TclpFinalizeLock
*
- * This procedure is used to destroy all private resources used in
- * this file.
+ * This procedure is used to destroy all private resources used in this
+ * file.
*
* Results:
* None.
*
* Side effects:
- * Destroys everything private. TclpInitLock must be held
- * entering this function.
+ * Destroys everything private. TclpInitLock must be held entering this
+ * function.
*
*----------------------------------------------------------------------
*/
void
-TclFinalizeLock ()
+TclFinalizeLock(void)
{
#ifdef TCL_THREADS
/*
* You do not need to destroy mutexes that were created with the
- * PTHREAD_MUTEX_INITIALIZER macro. These mutexes do not need
- * any destruction: masterLock, allocLock, and initLock.
+ * PTHREAD_MUTEX_INITIALIZER macro. These mutexes do not need any
+ * destruction: masterLock, allocLock, and initLock.
*/
+
pthread_mutex_unlock(&initLock);
#endif
}
@@ -290,8 +380,8 @@ TclFinalizeLock ()
*
* TclpInitUnlock
*
- * This procedure is used to release a lock that serializes initialization
- * and finalization of Tcl.
+ * This procedure is used to release a lock that serializes
+ * initialization and finalization of Tcl.
*
* Results:
* None.
@@ -303,7 +393,7 @@ TclFinalizeLock ()
*/
void
-TclpInitUnlock()
+TclpInitUnlock(void)
{
#ifdef TCL_THREADS
pthread_mutex_unlock(&initLock);
@@ -315,13 +405,12 @@ TclpInitUnlock()
*
* TclpMasterLock
*
- * This procedure is used to grab a lock that serializes creation
- * and finalization of serialization objects. This interface is
- * only needed in finalization; it is hidden during
- * creation of the objects.
+ * This procedure is used to grab a lock that serializes creation and
+ * finalization of serialization objects. This interface is only needed
+ * in finalization; it is hidden during creation of the objects.
*
- * This lock must be different than the initLock because the
- * initLock is held during creation of syncronization objects.
+ * This lock must be different than the initLock because the initLock is
+ * held during creation of syncronization objects.
*
* Results:
* None.
@@ -333,7 +422,7 @@ TclpInitUnlock()
*/
void
-TclpMasterLock()
+TclpMasterLock(void)
{
#ifdef TCL_THREADS
pthread_mutex_lock(&masterLock);
@@ -346,8 +435,8 @@ TclpMasterLock()
*
* TclpMasterUnlock
*
- * This procedure is used to release a lock that serializes creation
- * and finalization of synchronization objects.
+ * This procedure is used to release a lock that serializes creation and
+ * finalization of synchronization objects.
*
* Results:
* None.
@@ -359,7 +448,7 @@ TclpMasterLock()
*/
void
-TclpMasterUnlock()
+TclpMasterUnlock(void)
{
#ifdef TCL_THREADS
pthread_mutex_unlock(&masterLock);
@@ -372,13 +461,13 @@ TclpMasterUnlock()
*
* Tcl_GetAllocMutex
*
- * This procedure returns a pointer to a statically initialized
- * mutex for use by the memory allocator. The alloctor must
- * use this lock, because all other locks are allocated...
+ * This procedure returns a pointer to a statically initialized mutex for
+ * use by the memory allocator. The alloctor must use this lock, because
+ * all other locks are allocated...
*
* Results:
- * A pointer to a mutex that is suitable for passing to
- * Tcl_MutexLock and Tcl_MutexUnlock.
+ * A pointer to a mutex that is suitable for passing to Tcl_MutexLock and
+ * Tcl_MutexUnlock.
*
* Side effects:
* None.
@@ -387,10 +476,11 @@ TclpMasterUnlock()
*/
Tcl_Mutex *
-Tcl_GetAllocMutex()
+Tcl_GetAllocMutex(void)
{
#ifdef TCL_THREADS
- return (Tcl_Mutex *)&allocLockPtr;
+ pthread_mutex_t **allocLockPtrPtr = &allocLockPtr;
+ return (Tcl_Mutex *) allocLockPtrPtr;
#else
return NULL;
#endif
@@ -403,34 +493,34 @@ Tcl_GetAllocMutex()
*
* Tcl_MutexLock --
*
- * This procedure is invoked to lock a mutex. This procedure
- * handles initializing the mutex, if necessary. The caller
- * can rely on the fact that Tcl_Mutex is an opaque pointer.
- * This routine will change that pointer from NULL after first use.
+ * This procedure is invoked to lock a mutex. This procedure handles
+ * initializing the mutex, if necessary. The caller can rely on the fact
+ * that Tcl_Mutex is an opaque pointer. This routine will change that
+ * pointer from NULL after first use.
*
* Results:
* None.
*
* Side effects:
- * May block the current thread. The mutex is aquired when
- * this returns. Will allocate memory for a pthread_mutex_t
- * and initialize this the first time this Tcl_Mutex is used.
+ * May block the current thread. The mutex is aquired when this returns.
+ * Will allocate memory for a pthread_mutex_t and initialize this the
+ * first time this Tcl_Mutex is used.
*
*----------------------------------------------------------------------
*/
void
-Tcl_MutexLock(mutexPtr)
- Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */
+Tcl_MutexLock(
+ Tcl_Mutex *mutexPtr) /* Really (pthread_mutex_t **) */
{
pthread_mutex_t *pmutexPtr;
if (*mutexPtr == NULL) {
MASTER_LOCK;
if (*mutexPtr == NULL) {
- /*
+ /*
* Double inside master lock check to avoid a race condition.
*/
-
+
pmutexPtr = (pthread_mutex_t *)ckalloc(sizeof(pthread_mutex_t));
pthread_mutex_init(pmutexPtr, NULL);
*mutexPtr = (Tcl_Mutex)pmutexPtr;
@@ -441,15 +531,14 @@ Tcl_MutexLock(mutexPtr)
pmutexPtr = *((pthread_mutex_t **)mutexPtr);
pthread_mutex_lock(pmutexPtr);
}
-
/*
*----------------------------------------------------------------------
*
* Tcl_MutexUnlock --
*
- * This procedure is invoked to unlock a mutex. The mutex must
- * have been locked by Tcl_MutexLock.
+ * This procedure is invoked to unlock a mutex. The mutex must have been
+ * locked by Tcl_MutexLock.
*
* Results:
* None.
@@ -461,21 +550,20 @@ Tcl_MutexLock(mutexPtr)
*/
void
-Tcl_MutexUnlock(mutexPtr)
- Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */
+Tcl_MutexUnlock(
+ Tcl_Mutex *mutexPtr) /* Really (pthread_mutex_t **) */
{
pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **)mutexPtr;
pthread_mutex_unlock(pmutexPtr);
}
-
/*
*----------------------------------------------------------------------
*
* TclpFinalizeMutex --
*
- * This procedure is invoked to clean up one mutex. This is only
- * safe to call at the end of time.
+ * This procedure is invoked to clean up one mutex. This is only safe to
+ * call at the end of time.
*
* This assumes the Master Lock is held.
*
@@ -489,194 +577,25 @@ Tcl_MutexUnlock(mutexPtr)
*/
void
-TclpFinalizeMutex(mutexPtr)
- Tcl_Mutex *mutexPtr;
+TclpFinalizeMutex(
+ Tcl_Mutex *mutexPtr)
{
pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **)mutexPtr;
if (pmutexPtr != NULL) {
- pthread_mutex_destroy(pmutexPtr);
- ckfree((char *)pmutexPtr);
+ pthread_mutex_destroy(pmutexPtr);
+ ckfree((char *) pmutexPtr);
*mutexPtr = NULL;
}
}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpThreadDataKeyInit --
- *
- * This procedure initializes a thread specific data block key.
- * Each thread has table of pointers to thread specific data.
- * all threads agree on which table entry is used by each module.
- * this is remembered in a "data key", that is just an index into
- * this table. To allow self initialization, the interface
- * passes a pointer to this key and the first thread to use
- * the key fills in the pointer to the key. The key should be
- * a process-wide static.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Will allocate memory the first time this process calls for
- * this key. In this case it modifies its argument
- * to hold the pointer to information about the key.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpThreadDataKeyInit(keyPtr)
- Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
- * really (pthread_key_t **) */
-{
- pthread_key_t *pkeyPtr;
-
- MASTER_LOCK;
- if (*keyPtr == NULL) {
- pkeyPtr = (pthread_key_t *)ckalloc(sizeof(pthread_key_t));
- pthread_key_create(pkeyPtr, NULL);
- *keyPtr = (Tcl_ThreadDataKey)pkeyPtr;
- TclRememberDataKey(keyPtr);
- }
- MASTER_UNLOCK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpThreadDataKeyGet --
- *
- * This procedure returns a pointer to a block of thread local storage.
- *
- * Results:
- * A thread-specific pointer to the data structure, or NULL
- * if the memory has not been assigned to this key for this thread.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-VOID *
-TclpThreadDataKeyGet(keyPtr)
- Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
- * really (pthread_key_t **) */
-{
- pthread_key_t *pkeyPtr = *(pthread_key_t **)keyPtr;
- if (pkeyPtr == NULL) {
- return NULL;
- } else {
- return (VOID *)pthread_getspecific(*pkeyPtr);
- }
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpThreadDataKeySet --
- *
- * This procedure sets the pointer to a block of thread local storage.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Sets up the thread so future calls to TclpThreadDataKeyGet with
- * this key will return the data pointer.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpThreadDataKeySet(keyPtr, data)
- Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
- * really (pthread_key_t **) */
- VOID *data; /* Thread local storage */
-{
- pthread_key_t *pkeyPtr = *(pthread_key_t **)keyPtr;
- pthread_setspecific(*pkeyPtr, data);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpFinalizeThreadData --
- *
- * This procedure cleans up the thread-local storage. This is
- * called once for each thread.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Frees up all thread local storage.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpFinalizeThreadData(keyPtr)
- Tcl_ThreadDataKey *keyPtr;
-{
- VOID *result;
- pthread_key_t *pkeyPtr;
-
- if (*keyPtr != NULL) {
- pkeyPtr = *(pthread_key_t **)keyPtr;
- result = (VOID *)pthread_getspecific(*pkeyPtr);
- if (result != NULL) {
- ckfree((char *)result);
- pthread_setspecific(*pkeyPtr, (void *)NULL);
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclpFinalizeThreadDataKey --
- *
- * This procedure is invoked to clean up one key. This is a
- * process-wide storage identifier. The thread finalization code
- * cleans up the thread local storage itself.
- *
- * This assumes the master lock is held.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The key is deallocated.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclpFinalizeThreadDataKey(keyPtr)
- Tcl_ThreadDataKey *keyPtr;
-{
- pthread_key_t *pkeyPtr;
- if (*keyPtr != NULL) {
- pkeyPtr = *(pthread_key_t **)keyPtr;
- pthread_key_delete(*pkeyPtr);
- ckfree((char *)pkeyPtr);
- *keyPtr = NULL;
- }
-}
-
/*
*----------------------------------------------------------------------
*
* Tcl_ConditionWait --
*
- * This procedure is invoked to wait on a condition variable.
- * The mutex is automically released as part of the wait, and
- * automatically grabbed when the condition is signaled.
+ * This procedure is invoked to wait on a condition variable. The mutex
+ * is automically released as part of the wait, and automatically grabbed
+ * when the condition is signaled.
*
* The mutex must be held when this procedure is called.
*
@@ -684,18 +603,18 @@ TclpFinalizeThreadDataKey(keyPtr)
* None.
*
* Side effects:
- * May block the current thread. The mutex is aquired when
- * this returns. Will allocate memory for a pthread_mutex_t
- * and initialize this the first time this Tcl_Mutex is used.
+ * May block the current thread. The mutex is aquired when this returns.
+ * Will allocate memory for a pthread_mutex_t and initialize this the
+ * first time this Tcl_Mutex is used.
*
*----------------------------------------------------------------------
*/
void
-Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
- Tcl_Condition *condPtr; /* Really (pthread_cond_t **) */
- Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */
- Tcl_Time *timePtr; /* Timeout on waiting period */
+Tcl_ConditionWait(
+ Tcl_Condition *condPtr, /* Really (pthread_cond_t **) */
+ Tcl_Mutex *mutexPtr, /* Really (pthread_mutex_t **) */
+ Tcl_Time *timePtr) /* Timeout on waiting period */
{
pthread_cond_t *pcondPtr;
pthread_mutex_t *pmutexPtr;
@@ -704,13 +623,13 @@ Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
if (*condPtr == NULL) {
MASTER_LOCK;
- /*
- * Double check inside mutex to avoid race,
- * then initialize condition variable if necessary.
+ /*
+ * Double check inside mutex to avoid race, then initialize condition
+ * variable if necessary.
*/
if (*condPtr == NULL) {
- pcondPtr = (pthread_cond_t *)ckalloc(sizeof(pthread_cond_t));
+ pcondPtr = (pthread_cond_t *) ckalloc(sizeof(pthread_cond_t));
pthread_cond_init(pcondPtr, NULL);
*condPtr = (Tcl_Condition)pcondPtr;
TclRememberCondition(condPtr);
@@ -744,8 +663,8 @@ Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
*
* This procedure is invoked to signal a condition variable.
*
- * The mutex must be held during this call to avoid races,
- * but this interface does not enforce that.
+ * The mutex must be held during this call to avoid races, but this
+ * interface does not enforce that.
*
* Results:
* None.
@@ -757,8 +676,8 @@ Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
*/
void
-Tcl_ConditionNotify(condPtr)
- Tcl_Condition *condPtr;
+Tcl_ConditionNotify(
+ Tcl_Condition *condPtr)
{
pthread_cond_t *pcondPtr = *((pthread_cond_t **)condPtr);
if (pcondPtr != NULL) {
@@ -769,15 +688,14 @@ Tcl_ConditionNotify(condPtr)
*/
}
}
-
/*
*----------------------------------------------------------------------
*
* TclpFinalizeCondition --
*
- * This procedure is invoked to clean up a condition variable.
- * This is only safe to call at the end of time.
+ * This procedure is invoked to clean up a condition variable. This is
+ * only safe to call at the end of time.
*
* This assumes the Master Lock is held.
*
@@ -791,13 +709,13 @@ Tcl_ConditionNotify(condPtr)
*/
void
-TclpFinalizeCondition(condPtr)
- Tcl_Condition *condPtr;
+TclpFinalizeCondition(
+ Tcl_Condition *condPtr)
{
pthread_cond_t *pcondPtr = *(pthread_cond_t **)condPtr;
if (pcondPtr != NULL) {
pthread_cond_destroy(pcondPtr);
- ckfree((char *)pcondPtr);
+ ckfree((char *) pcondPtr);
*condPtr = NULL;
}
}
@@ -808,8 +726,8 @@ TclpFinalizeCondition(condPtr)
*
* TclpReaddir, TclpInetNtoa --
*
- * These procedures replace core C versions to be used in a
- * threaded environment.
+ * These procedures replace core C versions to be used in a threaded
+ * environment.
*
* Results:
* See documentation of C functions.
@@ -818,19 +736,22 @@ TclpFinalizeCondition(condPtr)
* See documentation of C functions.
*
* Notes:
- * TclpReaddir is no longer used by the core (see 1095909),
- * but it appears in the internal stubs table (see #589526).
+ * TclpReaddir is no longer used by the core (see 1095909), but it
+ * appears in the internal stubs table (see #589526).
+ *
*----------------------------------------------------------------------
*/
Tcl_DirEntry *
-TclpReaddir(DIR * dir)
+TclpReaddir(
+ DIR * dir)
{
return TclOSreaddir(dir);
}
char *
-TclpInetNtoa(struct in_addr addr)
+TclpInetNtoa(
+ struct in_addr addr)
{
#ifdef TCL_THREADS
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -842,17 +763,18 @@ TclpInetNtoa(struct in_addr addr)
return inet_ntoa(addr);
#endif
}
-
-#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) && !defined(TCL_MEM_DEBUG)
+
+#ifdef TCL_THREADS
/*
* Additions by AOL for specialized thread memory allocator.
*/
+
#ifdef USE_THREAD_ALLOC
static volatile int initialized = 0;
-static pthread_key_t key;
+static pthread_key_t key;
typedef struct allocMutex {
- Tcl_Mutex tlock;
+ Tcl_Mutex tlock;
pthread_mutex_t plock;
} allocMutex;
@@ -860,41 +782,49 @@ Tcl_Mutex *
TclpNewAllocMutex(void)
{
struct allocMutex *lockPtr;
+ register pthread_mutex_t *plockPtr;
lockPtr = malloc(sizeof(struct allocMutex));
if (lockPtr == NULL) {
- panic("could not allocate lock");
+ Tcl_Panic("could not allocate lock");
}
- lockPtr->tlock = (Tcl_Mutex) &lockPtr->plock;
+ plockPtr = &lockPtr->plock;
+ lockPtr->tlock = (Tcl_Mutex) plockPtr;
pthread_mutex_init(&lockPtr->plock, NULL);
return &lockPtr->tlock;
}
void
-TclpFreeAllocMutex(mutex)
- Tcl_Mutex *mutex; /* The alloc mutex to free. */
+TclpFreeAllocMutex(
+ Tcl_Mutex *mutex) /* The alloc mutex to free. */
{
allocMutex* lockPtr = (allocMutex*) mutex;
- if (!lockPtr) return;
+ if (!lockPtr) {
+ return;
+ }
pthread_mutex_destroy(&lockPtr->plock);
free(lockPtr);
}
-void TclpFreeAllocCache(ptr)
- void *ptr;
+void
+TclpFreeAllocCache(
+ void *ptr)
{
if (ptr != NULL) {
- /*
- * Called by the pthread lib when a thread exits
- */
- TclFreeAllocCache(ptr);
+ /*
+ * Called by the pthread lib when a thread exits
+ */
+
+ TclFreeAllocCache(ptr);
+
} else if (initialized) {
- /*
- * Called by us in TclFinalizeThreadAlloc() during
- * the library finalization initiated from Tcl_Finalize()
- */
- pthread_key_delete(key);
- initialized = 0;
+ /*
+ * Called by us in TclFinalizeThreadAlloc() during the library
+ * finalization initiated from Tcl_Finalize()
+ */
+
+ pthread_key_delete(key);
+ initialized = 0;
}
}
@@ -913,10 +843,18 @@ TclpGetAllocCache(void)
}
void
-TclpSetAllocCache(void *arg)
+TclpSetAllocCache(
+ void *arg)
{
pthread_setspecific(key, arg);
}
-
#endif /* USE_THREAD_ALLOC */
#endif /* TCL_THREADS */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixTime.c b/unix/tclUnixTime.c
index 707dfbc..b98f2e1 100644
--- a/unix/tclUnixTime.c
+++ b/unix/tclUnixTime.c
@@ -11,8 +11,11 @@
*/
#include "tclInt.h"
-#include "tclPort.h"
#include <locale.h>
+#if defined(TCL_WIDE_CLICKS) && defined(MAC_OSX_TCL)
+#include <mach/mach_time.h>
+#endif
+
#define TM_YEAR_BASE 1900
#define IsLeapYear(x) (((x)%4 == 0) && ((x)%100 != 0 || (x)%400 == 0))
@@ -43,8 +46,20 @@ static char *lastTZ = NULL; /* Holds the last setting of the TZ
* Static functions declared in this file.
*/
-static void SetTZIfNecessary _ANSI_ARGS_((void));
-static void CleanupMemory _ANSI_ARGS_((ClientData));
+static void SetTZIfNecessary(void);
+static void CleanupMemory(ClientData clientData);
+static void NativeScaleTime(Tcl_Time *timebuf,
+ ClientData clientData);
+static void NativeGetTime(Tcl_Time *timebuf,
+ ClientData clientData);
+
+/*
+ * TIP #233 (Virtualized Time): Data for the time hooks, if any.
+ */
+
+Tcl_GetTimeProc *tclGetTimeProcPtr = NativeGetTime;
+Tcl_ScaleTimeProc *tclScaleTimeProcPtr = NativeScaleTime;
+ClientData tclTimeClientData = NULL;
/*
*----------------------------------------------------------------------
@@ -64,9 +79,9 @@ static void CleanupMemory _ANSI_ARGS_((ClientData));
*/
unsigned long
-TclpGetSeconds()
+TclpGetSeconds(void)
{
- return time((time_t *) NULL);
+ return time(NULL);
}
/*
@@ -89,27 +104,124 @@ TclpGetSeconds()
*/
unsigned long
-TclpGetClicks()
+TclpGetClicks(void)
{
unsigned long now;
#ifdef NO_GETTOD
- struct tms dummy;
+ if (tclGetTimeProcPtr != NativeGetTime) {
+ Tcl_Time time;
+
+ (*tclGetTimeProcPtr) (&time, tclTimeClientData);
+ now = time.sec*1000000 + time.usec;
+ } else {
+ /*
+ * A semi-NativeGetTime, specialized to clicks.
+ */
+ struct tms dummy;
+
+ now = (unsigned long) times(&dummy);
+ }
#else
- struct timeval date;
+ Tcl_Time time;
+
+ (*tclGetTimeProcPtr) (&time, tclTimeClientData);
+ now = time.sec*1000000 + time.usec;
#endif
-#ifdef NO_GETTOD
- now = (unsigned long) times(&dummy);
+ return now;
+}
+#ifdef TCL_WIDE_CLICKS
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * TclpGetWideClicks --
+ *
+ * This procedure returns a WideInt value that represents the highest
+ * resolution clock available on the system. There are no garantees on
+ * what the resolution will be. In Tcl we will call this value a "click".
+ * The start time is also system dependant.
+ *
+ * Results:
+ * Number of WideInt clicks from some start time.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Tcl_WideInt
+TclpGetWideClicks(void)
+{
+ Tcl_WideInt now;
+
+ if (tclGetTimeProcPtr != NativeGetTime) {
+ Tcl_Time time;
+
+ (*tclGetTimeProcPtr) (&time, tclTimeClientData);
+ now = (Tcl_WideInt) (time.sec*1000000 + time.usec);
+ } else {
+#ifdef MAC_OSX_TCL
+ now = (Tcl_WideInt) (mach_absolute_time() & INT64_MAX);
#else
- gettimeofday(&date, NULL);
- now = date.tv_sec*1000000 + date.tv_usec;
+#error Wide high-resolution clicks not implemented on this platform
#endif
+ }
return now;
}
/*
+ *-----------------------------------------------------------------------------
+ *
+ * TclpWideClicksToNanoseconds --
+ *
+ * This procedure converts click values from the TclpGetWideClicks native
+ * resolution to nanosecond resolution.
+ *
+ * Results:
+ * Number of nanoseconds from some start time.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+double
+TclpWideClicksToNanoseconds(
+ Tcl_WideInt clicks)
+{
+ double nsec;
+
+ if (tclGetTimeProcPtr != NativeGetTime) {
+ nsec = clicks * 1000;
+ } else {
+#ifdef MAC_OSX_TCL
+ static mach_timebase_info_data_t tb;
+ static uint64_t maxClicksForUInt64;
+
+ if (!tb.denom) {
+ mach_timebase_info(&tb);
+ maxClicksForUInt64 = UINT64_MAX / tb.numer;
+ }
+ if ((uint64_t) clicks < maxClicksForUInt64) {
+ nsec = ((uint64_t) clicks) * tb.numer / tb.denom;
+ } else {
+ nsec = ((long double) (uint64_t) clicks) * tb.numer / tb.denom;
+ }
+#else
+#error Wide high-resolution clicks not implemented on this platform
+#endif
+ }
+
+ return nsec;
+}
+#endif /* TCL_WIDE_CLICKS */
+
+/*
*----------------------------------------------------------------------
*
* TclpGetTimeZone --
@@ -128,8 +240,8 @@ TclpGetClicks()
*/
int
-TclpGetTimeZone(currentTime)
- Tcl_WideInt currentTime;
+TclpGetTimeZone(
+ unsigned long currentTime)
{
int timeZone;
@@ -149,7 +261,7 @@ TclpGetTimeZone(currentTime)
*/
time_t curTime = (time_t) currentTime;
- struct tm *timeDataPtr = TclpLocaltime((TclpTime_t) &curTime);
+ struct tm *timeDataPtr = TclpLocaltime(&curTime);
timeZone = timeDataPtr->tm_tzadj / 60;
if (timeDataPtr->tm_isdst) {
@@ -164,7 +276,7 @@ TclpGetTimeZone(currentTime)
*/
time_t curTime = (time_t) currentTime;
- struct tm *timeDataPtr = TclpLocaltime((TclpTime_t) &curTime);
+ struct tm *timeDataPtr = TclpLocaltime(&curTime);
timeZone = -(timeDataPtr->tm_gmtoff / 60);
if (timeDataPtr->tm_isdst) {
@@ -198,7 +310,7 @@ TclpGetTimeZone(currentTime)
struct tm *stm;
tt = 849268800L; /* 1996-11-29 12:00:00 GMT */
- stm = TclpLocaltime((TclpTime_t) &tt); /* eg 1996-11-29 6:00:00 CST6CDT */
+ stm = TclpLocaltime(&tt); /* eg 1996-11-29 6:00:00 CST6CDT */
/*
* The calculation below assumes a max of +12 or -12 hours from GMT.
@@ -233,6 +345,9 @@ TclpGetTimeZone(currentTime)
* Gets the current system time in seconds and microseconds since the
* beginning of the epoch: 00:00 UCT, January 1, 1970.
*
+ * This function is hooked, allowing users to specify their own virtual
+ * system time.
+ *
* Results:
* Returns the current time in timePtr.
*
@@ -243,14 +358,10 @@ TclpGetTimeZone(currentTime)
*/
void
-Tcl_GetTime(timePtr)
- Tcl_Time *timePtr; /* Location to store time information. */
+Tcl_GetTime(
+ Tcl_Time *timePtr) /* Location to store time information. */
{
- struct timeval tv;
-
- (void) gettimeofday(&tv, NULL);
- timePtr->sec = tv.tv_sec;
- timePtr->usec = tv.tv_usec;
+ (*tclGetTimeProcPtr) (timePtr, tclTimeClientData);
}
/*
@@ -272,9 +383,9 @@ Tcl_GetTime(timePtr)
*/
struct tm *
-TclpGetDate(time, useGMT)
- TclpTime_t time;
- int useGMT;
+TclpGetDate(
+ CONST time_t *time,
+ int useGMT)
{
if (useGMT) {
return TclpGmtime(time);
@@ -286,48 +397,9 @@ TclpGetDate(time, useGMT)
/*
*----------------------------------------------------------------------
*
- * TclpStrftime --
- *
- * On Unix, we can safely call the native strftime implementation,
- * and also ignore the useGMT parameter.
- *
- * Results:
- * The normal strftime result.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-size_t
-TclpStrftime(s, maxsize, format, t, useGMT)
- char *s;
- size_t maxsize;
- CONST char *format;
- CONST struct tm *t;
- int useGMT;
-{
- if (format[0] == '%' && format[1] == 'Q') {
- /* Format as a stardate */
- sprintf(s, "Stardate %2d%03d.%01d",
- (((t->tm_year + TM_YEAR_BASE) + 377) - 2323),
- (((t->tm_yday + 1) * 1000) /
- (365 + IsLeapYear((t->tm_year + TM_YEAR_BASE)))),
- (((t->tm_hour * 60) + t->tm_min)/144));
- return(strlen(s));
- }
- setlocale(LC_TIME, "");
- return strftime(s, maxsize, format, t);
-}
-
-/*
- *----------------------------------------------------------------------
- *
* TclpGmtime --
*
- * Wrapper around the 'gmtime' library function to make it thread
- * safe.
+ * Wrapper around the 'gmtime' library function to make it thread safe.
*
* Results:
* Returns a pointer to a 'struct tm' in thread-specific data.
@@ -339,27 +411,24 @@ TclpStrftime(s, maxsize, format, t, useGMT)
*/
struct tm *
-TclpGmtime(tt)
- TclpTime_t_CONST tt;
+TclpGmtime(
+ CONST time_t *timePtr) /* Pointer to the number of seconds since the
+ * local system's epoch */
{
- CONST time_t *timePtr = (CONST time_t *) tt;
- /* Pointer to the number of seconds
- * since the local system's epoch */
-
/*
* Get a thread-local buffer to hold the returned time.
*/
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tmKey);
+
#ifdef HAVE_GMTIME_R
gmtime_r(timePtr, &(tsdPtr->gmtime_buf));
#else
Tcl_MutexLock(&tmMutex);
- memcpy((VOID *) &(tsdPtr->gmtime_buf),
- (VOID *) gmtime(timePtr),
- sizeof(struct tm));
+ memcpy(&(tsdPtr->gmtime_buf), gmtime(timePtr), sizeof(struct tm));
Tcl_MutexUnlock(&tmMutex);
#endif
+
return &(tsdPtr->gmtime_buf);
}
@@ -381,33 +450,145 @@ TclpGmtime(tt)
*/
struct tm *
-TclpLocaltime(tt)
- TclpTime_t_CONST tt;
+TclpLocaltime(
+ CONST time_t *timePtr) /* Pointer to the number of seconds since the
+ * local system's epoch */
{
- CONST time_t *timePtr = (CONST time_t *) tt;
- /* Pointer to the number of seconds
- * since the local system's epoch */
/*
* Get a thread-local buffer to hold the returned time.
*/
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tmKey);
+
SetTZIfNecessary();
#ifdef HAVE_LOCALTIME_R
localtime_r(timePtr, &(tsdPtr->localtime_buf));
#else
Tcl_MutexLock(&tmMutex);
- memcpy((VOID *) &(tsdPtr -> localtime_buf),
- (VOID *) localtime(timePtr),
- sizeof(struct tm));
+ memcpy(&(tsdPtr->localtime_buf), localtime(timePtr), sizeof(struct tm));
Tcl_MutexUnlock(&tmMutex);
#endif
+
return &(tsdPtr->localtime_buf);
}
/*
*----------------------------------------------------------------------
*
+ * Tcl_SetTimeProc --
+ *
+ * TIP #233 (Virtualized Time): Registers two handlers for the
+ * virtualization of Tcl's access to time information.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Remembers the handlers, alters core behaviour.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetTimeProc(
+ Tcl_GetTimeProc *getProc,
+ Tcl_ScaleTimeProc *scaleProc,
+ ClientData clientData)
+{
+ tclGetTimeProcPtr = getProc;
+ tclScaleTimeProcPtr = scaleProc;
+ tclTimeClientData = clientData;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_QueryTimeProc --
+ *
+ * TIP #233 (Virtualized Time): Query which time handlers are registered.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_QueryTimeProc(
+ Tcl_GetTimeProc **getProc,
+ Tcl_ScaleTimeProc **scaleProc,
+ ClientData *clientData)
+{
+ if (getProc) {
+ *getProc = tclGetTimeProcPtr;
+ }
+ if (scaleProc) {
+ *scaleProc = tclScaleTimeProcPtr;
+ }
+ if (clientData) {
+ *clientData = tclTimeClientData;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NativeScaleTime --
+ *
+ * TIP #233: Scale from virtual time to the real-time. For native scaling
+ * the relationship is 1:1 and nothing has to be done.
+ *
+ * Results:
+ * Scales the time in timePtr.
+ *
+ * Side effects:
+ * See above.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+NativeScaleTime(
+ Tcl_Time *timePtr,
+ ClientData clientData)
+{
+ /* Native scale is 1:1. Nothing is done */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NativeGetTime --
+ *
+ * TIP #233: Gets the current system time in seconds and microseconds
+ * since the beginning of the epoch: 00:00 UCT, January 1, 1970.
+ *
+ * Results:
+ * Returns the current time in timePtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+NativeGetTime(
+ Tcl_Time *timePtr,
+ ClientData clientData)
+{
+ struct timeval tv;
+
+ (void) gettimeofday(&tv, NULL);
+ timePtr->sec = tv.tv_sec;
+ timePtr->usec = tv.tv_usec;
+}
+/*
+ *----------------------------------------------------------------------
+ *
* SetTZIfNecessary --
*
* Determines whether a call to 'tzset' is needed prior to the next call
@@ -425,7 +606,7 @@ TclpLocaltime(tt)
*/
static void
-SetTZIfNecessary()
+SetTZIfNecessary(void)
{
CONST char *newTZ = getenv("TZ");
@@ -464,8 +645,8 @@ SetTZIfNecessary()
*/
static void
-CleanupMemory(ignored)
- ClientData ignored;
+CleanupMemory(
+ ClientData ignored)
{
ckfree(lastTZ);
}
diff --git a/unix/tclXtNotify.c b/unix/tclXtNotify.c
index b78ac8c..6a11c0d 100644
--- a/unix/tclXtNotify.c
+++ b/unix/tclXtNotify.c
@@ -1,29 +1,30 @@
-/*
+/*
* tclXtNotify.c --
*
- * This file contains the notifier driver implementation for the
- * Xt intrinsics.
+ * This file contains the notifier driver implementation for the Xt
+ * intrinsics.
*
* Copyright (c) 1997 by Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <X11/Intrinsic.h>
-#include <tclInt.h>
+#include "tclInt.h"
/*
- * This structure is used to keep track of the notifier info for a
- * a registered file.
+ * This structure is used to keep track of the notifier info for a a
+ * registered file.
*/
typedef struct FileHandler {
int fd;
- int mask; /* Mask of desired events: TCL_READABLE, etc. */
- int readyMask; /* Events that have been seen since the
- last time FileHandlerEventProc was called
- for this file. */
+ int mask; /* Mask of desired events: TCL_READABLE,
+ * etc. */
+ int readyMask; /* Events that have been seen since the last
+ * time FileHandlerEventProc was called for
+ * this file. */
XtInputId read; /* Xt read callback handle. */
XtInputId write; /* Xt write callback handle. */
XtInputId except; /* Xt exception callback handle. */
@@ -34,33 +35,32 @@ typedef struct FileHandler {
} FileHandler;
/*
- * The following structure is what is added to the Tcl event queue when
- * file handlers are ready to fire.
+ * The following structure is what is added to the Tcl event queue when file
+ * handlers are ready to fire.
*/
typedef struct FileHandlerEvent {
- Tcl_Event header; /* Information that is standard for
- * all events. */
- int fd; /* File descriptor that is ready. Used
- * to find the FileHandler structure for
- * the file (can't point directly to the
- * FileHandler structure because it could
- * go away while the event is queued). */
+ Tcl_Event header; /* Information that is standard for all
+ * events. */
+ int fd; /* File descriptor that is ready. Used to find
+ * the FileHandler structure for the file
+ * (can't point directly to the FileHandler
+ * structure because it could go away while
+ * the event is queued). */
} FileHandlerEvent;
/*
- * The following static structure contains the state information for the
- * Xt based implementation of the Tcl notifier.
+ * The following static structure contains the state information for the Xt
+ * based implementation of the Tcl notifier.
*/
static struct NotifierState {
- XtAppContext appContext; /* The context used by the Xt
- * notifier. Can be set with
- * TclSetAppContext. */
- int appContextCreated; /* Was it created by us? */
- XtIntervalId currentTimeout; /* Handle of current timer. */
- FileHandler *firstFileHandlerPtr; /* Pointer to head of file handler
- * list. */
+ XtAppContext appContext; /* The context used by the Xt notifier. Can be
+ * set with TclSetAppContext. */
+ int appContextCreated; /* Was it created by us? */
+ XtIntervalId currentTimeout;/* Handle of current timer. */
+ FileHandler *firstFileHandlerPtr;
+ /* Pointer to head of file handler list. */
} notifier;
/*
@@ -73,26 +73,23 @@ static int initialized = 0;
* Static routines defined in this file.
*/
-static int FileHandlerEventProc _ANSI_ARGS_((Tcl_Event *evPtr,
- int flags));
-static void FileProc _ANSI_ARGS_((caddr_t clientData,
- int *source, XtInputId *id));
-void InitNotifier _ANSI_ARGS_((void));
-static void NotifierExitHandler _ANSI_ARGS_((
- ClientData clientData));
-static void TimerProc _ANSI_ARGS_((caddr_t clientData,
- XtIntervalId *id));
-static void CreateFileHandler _ANSI_ARGS_((int fd, int mask,
- Tcl_FileProc * proc, ClientData clientData));
-static void DeleteFileHandler _ANSI_ARGS_((int fd));
-static void SetTimer _ANSI_ARGS_((Tcl_Time * timePtr));
-static int WaitForEvent _ANSI_ARGS_((Tcl_Time * timePtr));
+static int FileHandlerEventProc(Tcl_Event *evPtr, int flags);
+static void FileProc(caddr_t clientData, int *source,
+ XtInputId *id);
+void InitNotifier(void);
+static void NotifierExitHandler(ClientData clientData);
+static void TimerProc(caddr_t clientData, XtIntervalId *id);
+static void CreateFileHandler(int fd, int mask,
+ Tcl_FileProc * proc, ClientData clientData);
+static void DeleteFileHandler(int fd);
+static void SetTimer(Tcl_Time * timePtr);
+static int WaitForEvent(Tcl_Time * timePtr);
/*
* Functions defined in this file for use by users of the Xt Notifier:
*/
-EXTERN XtAppContext TclSetAppContext _ANSI_ARGS_((XtAppContext ctx));
+EXTERN XtAppContext TclSetAppContext(XtAppContext ctx);
/*
*----------------------------------------------------------------------
@@ -105,18 +102,18 @@ EXTERN XtAppContext TclSetAppContext _ANSI_ARGS_((XtAppContext ctx));
* None.
*
* Side effects:
- * Sets the application context used by the notifier. Panics if
- * the context is already set when called.
+ * Sets the application context used by the notifier. Panics if the
+ * context is already set when called.
*
*----------------------------------------------------------------------
*/
XtAppContext
-TclSetAppContext(appContext)
- XtAppContext appContext;
+TclSetAppContext(
+ XtAppContext appContext)
{
if (!initialized) {
- InitNotifier();
+ InitNotifier();
}
/*
@@ -124,46 +121,41 @@ TclSetAppContext(appContext)
* new context. If so, we panic because we try to prevent switching
* contexts by mistake. Otherwise, we return the one we have.
*/
-
- if (notifier.appContext != NULL) {
- if (appContext != NULL) {
+ if (notifier.appContext != NULL) {
+ if (appContext != NULL) {
/*
- * We already have a context. We do not allow switching contexts
- * after initialization, so we panic.
- */
-
- panic("TclSetAppContext: multiple application contexts");
+ * We already have a context. We do not allow switching contexts
+ * after initialization, so we panic.
+ */
- }
+ Tcl_Panic("TclSetAppContext: multiple application contexts");
+ }
} else {
+ /*
+ * If we get here we have not yet gotten a context, so either create
+ * one or use the one supplied by our caller.
+ */
- /*
- * If we get here we have not yet gotten a context, so either create
- * one or use the one supplied by our caller.
- */
-
- if (appContext == NULL) {
-
+ if (appContext == NULL) {
/*
- * We must create a new context and tell our caller what it is, so
- * she can use it too.
- */
-
- notifier.appContext = XtCreateApplicationContext();
- notifier.appContextCreated = 1;
- } else {
+ * We must create a new context and tell our caller what it is, so
+ * she can use it too.
+ */
+ notifier.appContext = XtCreateApplicationContext();
+ notifier.appContextCreated = 1;
+ } else {
/*
- * Otherwise we remember the context that our caller gave us
- * and use it.
- */
-
- notifier.appContextCreated = 0;
- notifier.appContext = appContext;
- }
+ * Otherwise we remember the context that our caller gave us and
+ * use it.
+ */
+
+ notifier.appContextCreated = 0;
+ notifier.appContext = appContext;
+ }
}
-
+
return notifier.appContext;
}
@@ -184,17 +176,18 @@ TclSetAppContext(appContext)
*/
void
-InitNotifier()
+InitNotifier(void)
{
Tcl_NotifierProcs notifier;
+
/*
- * Only reinitialize if we are not in exit handling. The notifier
- * can get reinitialized after its own exit handler has run, because
- * of exit handlers for the I/O and timer sub-systems (order dependency).
+ * Only reinitialize if we are not in exit handling. The notifier can get
+ * reinitialized after its own exit handler has run, because of exit
+ * handlers for the I/O and timer sub-systems (order dependency).
*/
if (TclInExit()) {
- return;
+ return;
}
notifier.createFileHandlerProc = CreateFileHandler;
@@ -207,7 +200,7 @@ InitNotifier()
* DO NOT create the application context yet; doing so would prevent
* external applications from setting it for us to their own ones.
*/
-
+
initialized = 1;
memset(&notifier, 0, sizeof(notifier));
Tcl_CreateExitHandler(NotifierExitHandler, NULL);
@@ -218,8 +211,8 @@ InitNotifier()
*
* NotifierExitHandler --
*
- * This function is called to cleanup the notifier state before
- * Tcl is unloaded.
+ * This function is called to cleanup the notifier state before Tcl is
+ * unloaded.
*
* Results:
* None.
@@ -235,15 +228,15 @@ NotifierExitHandler(
ClientData clientData) /* Not used. */
{
if (notifier.currentTimeout != 0) {
- XtRemoveTimeOut(notifier.currentTimeout);
+ XtRemoveTimeOut(notifier.currentTimeout);
}
for (; notifier.firstFileHandlerPtr != NULL; ) {
- Tcl_DeleteFileHandler(notifier.firstFileHandlerPtr->fd);
+ Tcl_DeleteFileHandler(notifier.firstFileHandlerPtr->fd);
}
if (notifier.appContextCreated) {
- XtDestroyApplicationContext(notifier.appContext);
- notifier.appContextCreated = 0;
- notifier.appContext = NULL;
+ XtDestroyApplicationContext(notifier.appContext);
+ notifier.appContextCreated = 0;
+ notifier.appContext = NULL;
}
initialized = 0;
}
@@ -265,8 +258,8 @@ NotifierExitHandler(
*/
static void
-SetTimer(timePtr)
- Tcl_Time *timePtr; /* Timeout value, may be NULL. */
+SetTimer(
+ Tcl_Time *timePtr) /* Timeout value, may be NULL. */
{
long timeout;
@@ -280,9 +273,8 @@ SetTimer(timePtr)
}
if (timePtr) {
timeout = timePtr->sec * 1000 + timePtr->usec / 1000;
- notifier.currentTimeout =
- XtAppAddTimeOut(notifier.appContext, (unsigned long) timeout,
- TimerProc, NULL);
+ notifier.currentTimeout = XtAppAddTimeOut(notifier.appContext,
+ (unsigned long) timeout, TimerProc, NULL);
} else {
notifier.currentTimeout = 0;
}
@@ -293,22 +285,21 @@ SetTimer(timePtr)
*
* TimerProc --
*
- * This procedure is the XtTimerCallbackProc used to handle
- * timeouts.
+ * This procedure is the XtTimerCallbackProc used to handle timeouts.
*
* Results:
* None.
*
* Side effects:
- * Processes all queued events.
+ * Processes all queued events.
*
*----------------------------------------------------------------------
*/
static void
-TimerProc(data, id)
- caddr_t data; /* Not used. */
- XtIntervalId *id;
+TimerProc(
+ caddr_t data, /* Not used. */
+ XtIntervalId *id)
{
if (*id != notifier.currentTimeout) {
return;
@@ -329,22 +320,22 @@ TimerProc(data, id)
* None.
*
* Side effects:
- * Creates a new file handler structure and registers one or more
- * input procedures with Xt.
+ * Creates a new file handler structure and registers one or more input
+ * procedures with Xt.
*
*----------------------------------------------------------------------
*/
static void
-CreateFileHandler(fd, mask, proc, clientData)
- int fd; /* Handle of stream to watch. */
- int mask; /* OR'ed combination of TCL_READABLE,
- * TCL_WRITABLE, and TCL_EXCEPTION:
- * indicates conditions under which
- * proc should be called. */
- Tcl_FileProc *proc; /* Procedure to call for each
- * selected event. */
- ClientData clientData; /* Arbitrary data to pass to proc. */
+CreateFileHandler(
+ int fd, /* Handle of stream to watch. */
+ int mask, /* OR'ed combination of TCL_READABLE,
+ * TCL_WRITABLE, and TCL_EXCEPTION: indicates
+ * conditions under which proc should be
+ * called. */
+ Tcl_FileProc *proc, /* Procedure to call for each selected
+ * event. */
+ ClientData clientData) /* Arbitrary data to pass to proc. */
{
FileHandler *filePtr;
@@ -380,9 +371,8 @@ CreateFileHandler(fd, mask, proc, clientData)
if (mask & TCL_READABLE) {
if (!(filePtr->mask & TCL_READABLE)) {
- filePtr->read =
- XtAppAddInput(notifier.appContext, fd, XtInputReadMask,
- FileProc, filePtr);
+ filePtr->read = XtAppAddInput(notifier.appContext, fd,
+ XtInputReadMask, FileProc, filePtr);
}
} else {
if (filePtr->mask & TCL_READABLE) {
@@ -391,9 +381,8 @@ CreateFileHandler(fd, mask, proc, clientData)
}
if (mask & TCL_WRITABLE) {
if (!(filePtr->mask & TCL_WRITABLE)) {
- filePtr->write =
- XtAppAddInput(notifier.appContext, fd, XtInputWriteMask,
- FileProc, filePtr);
+ filePtr->write = XtAppAddInput(notifier.appContext, fd,
+ XtInputWriteMask, FileProc, filePtr);
}
} else {
if (filePtr->mask & TCL_WRITABLE) {
@@ -402,9 +391,8 @@ CreateFileHandler(fd, mask, proc, clientData)
}
if (mask & TCL_EXCEPTION) {
if (!(filePtr->mask & TCL_EXCEPTION)) {
- filePtr->except =
- XtAppAddInput(notifier.appContext, fd, XtInputExceptMask,
- FileProc, filePtr);
+ filePtr->except = XtAppAddInput(notifier.appContext, fd,
+ XtInputExceptMask, FileProc, filePtr);
}
} else {
if (filePtr->mask & TCL_EXCEPTION) {
@@ -419,8 +407,7 @@ CreateFileHandler(fd, mask, proc, clientData)
*
* DeleteFileHandler --
*
- * Cancel a previously-arranged callback arrangement for
- * a file.
+ * Cancel a previously-arranged callback arrangement for a file.
*
* Results:
* None.
@@ -432,9 +419,9 @@ CreateFileHandler(fd, mask, proc, clientData)
*/
static void
-DeleteFileHandler(fd)
- int fd; /* Stream id for which to remove
- * callback procedure. */
+DeleteFileHandler(
+ int fd) /* Stream id for which to remove callback
+ * procedure. */
{
FileHandler *filePtr, *prevPtr;
@@ -445,8 +432,7 @@ DeleteFileHandler(fd)
TclSetAppContext(NULL);
/*
- * Find the entry for the given file (and return if there
- * isn't one).
+ * Find the entry for the given file (and return if there isn't one).
*/
for (prevPtr = NULL, filePtr = notifier.firstFileHandlerPtr; ;
@@ -492,17 +478,16 @@ DeleteFileHandler(fd)
* None.
*
* Side effects:
- * Makes an entry on the Tcl event queue if the event is
- * interesting.
+ * Makes an entry on the Tcl event queue if the event is interesting.
*
*----------------------------------------------------------------------
*/
static void
-FileProc(clientData, fd, id)
- caddr_t clientData;
- int *fd;
- XtInputId *id;
+FileProc(
+ caddr_t clientData,
+ int *fd,
+ XtInputId *id)
{
FileHandler *filePtr = (FileHandler *)clientData;
FileHandlerEvent *fileEvPtr;
@@ -527,7 +512,7 @@ FileProc(clientData, fd, id)
if (!(filePtr->mask & mask) || (filePtr->readyMask & mask)) {
return;
}
-
+
/*
* This is an interesting event, so put it onto the event queue.
*/
@@ -550,16 +535,16 @@ FileProc(clientData, fd, id)
*
* FileHandlerEventProc --
*
- * This procedure is called by Tcl_ServiceEvent when a file event
- * reaches the front of the event queue. This procedure is
- * responsible for actually handling the event by invoking the
- * callback for the file handler.
+ * This procedure is called by Tcl_ServiceEvent when a file event reaches
+ * the front of the event queue. This procedure is responsible for
+ * actually handling the event by invoking the callback for the file
+ * handler.
*
* Results:
- * Returns 1 if the event was handled, meaning it should be removed
- * from the queue. Returns 0 if the event was not handled, meaning
- * it should stay on the queue. The only time the event isn't
- * handled is if the TCL_FILE_EVENTS flag bit isn't set.
+ * Returns 1 if the event was handled, meaning it should be removed from
+ * the queue. Returns 0 if the event was not handled, meaning it should
+ * stay on the queue. The only time the event isn't handled is if the
+ * TCL_FILE_EVENTS flag bit isn't set.
*
* Side effects:
* Whatever the file handler's callback procedure does.
@@ -568,10 +553,10 @@ FileProc(clientData, fd, id)
*/
static int
-FileHandlerEventProc(evPtr, flags)
- Tcl_Event *evPtr; /* Event to service. */
- int flags; /* Flags that indicate what events to
- * handle, such as TCL_FILE_EVENTS. */
+FileHandlerEventProc(
+ Tcl_Event *evPtr, /* Event to service. */
+ int flags) /* Flags that indicate what events to handle,
+ * such as TCL_FILE_EVENTS. */
{
FileHandler *filePtr;
FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) evPtr;
@@ -583,9 +568,9 @@ FileHandlerEventProc(evPtr, flags)
/*
* Search through the file handlers to find the one whose handle matches
- * the event. We do this rather than keeping a pointer to the file
- * handler directly in the event, so that the handler can be deleted
- * while the event is queued without leaving a dangling pointer.
+ * the event. We do this rather than keeping a pointer to the file handler
+ * directly in the event, so that the handler can be deleted while the
+ * event is queued without leaving a dangling pointer.
*/
for (filePtr = notifier.firstFileHandlerPtr; filePtr != NULL;
@@ -596,14 +581,14 @@ FileHandlerEventProc(evPtr, flags)
/*
* The code is tricky for two reasons:
- * 1. The file handler's desired events could have changed
- * since the time when the event was queued, so AND the
- * ready mask with the desired mask.
- * 2. The file could have been closed and re-opened since
- * the time when the event was queued. This is why the
- * ready mask is stored in the file handler rather than
- * the queued event: it will be zeroed when a new
- * file handler is created for the newly opened file.
+ * 1. The file handler's desired events could have changed since the
+ * time when the event was queued, so AND the ready mask with the
+ * desired mask.
+ * 2. The file could have been closed and re-opened since the time
+ * when the event was queued. This is why the ready mask is stored
+ * in the file handler rather than the queued event: it will be
+ * zeroed when a new file handler is created for the newly opened
+ * file.
*/
mask = filePtr->readyMask & filePtr->mask;
@@ -621,14 +606,14 @@ FileHandlerEventProc(evPtr, flags)
*
* WaitForEvent --
*
- * This function is called by Tcl_DoOneEvent to wait for new
- * events on the message queue. If the block time is 0, then
- * Tcl_WaitForEvent just polls without blocking.
+ * This function is called by Tcl_DoOneEvent to wait for new events on
+ * the message queue. If the block time is 0, then Tcl_WaitForEvent just
+ * polls without blocking.
*
* Results:
- * Returns 1 if an event was found, else 0. This ensures that
- * Tcl_DoOneEvent will return 1, even if the event is handled
- * by non-Tcl code.
+ * Returns 1 if an event was found, else 0. This ensures that
+ * Tcl_DoOneEvent will return 1, even if the event is handled by non-Tcl
+ * code.
*
* Side effects:
* Queues file events that are detected by the select.
@@ -649,18 +634,27 @@ WaitForEvent(
TclSetAppContext(NULL);
if (timePtr) {
- timeout = timePtr->sec * 1000 + timePtr->usec / 1000;
- if (timeout == 0) {
- if (XtAppPending(notifier.appContext)) {
- goto process;
- } else {
- return 0;
- }
- } else {
- Tcl_SetTimer(timePtr);
- }
+ timeout = timePtr->sec * 1000 + timePtr->usec / 1000;
+ if (timeout == 0) {
+ if (XtAppPending(notifier.appContext)) {
+ goto process;
+ } else {
+ return 0;
+ }
+ } else {
+ Tcl_SetTimer(timePtr);
+ }
}
-process:
+
+ process:
XtAppProcessEvent(notifier.appContext, XtIMAll);
return 1;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclXtTest.c b/unix/tclXtTest.c
index 041d4f0..8437f2a 100644
--- a/unix/tclXtTest.c
+++ b/unix/tclXtTest.c
@@ -5,30 +5,29 @@
*
* Copyright (c) 1997 by Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <X11/Intrinsic.h>
#include "tcl.h"
-static int TesteventloopCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, CONST char **argv));
-extern void InitNotifier _ANSI_ARGS_((void));
-
+static int TesteventloopCmd(ClientData clientData,
+ Tcl_Interp *interp, int argc, CONST char **argv);
+extern void InitNotifier(void);
/*
*----------------------------------------------------------------------
*
* Tclxttest_Init --
*
- * This procedure performs application-specific initialization.
- * Most applications, especially those that incorporate additional
- * packages, will have their own version of this procedure.
+ * 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.
+ * 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.
@@ -37,8 +36,8 @@ extern void InitNotifier _ANSI_ARGS_((void));
*/
int
-Tclxttest_Init(interp)
- Tcl_Interp *interp; /* Interpreter for application. */
+Tclxttest_Init(
+ Tcl_Interp *interp) /* Interpreter for application. */
{
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
@@ -46,7 +45,7 @@ Tclxttest_Init(interp)
XtToolkitInitialize();
InitNotifier();
Tcl_CreateCommand(interp, "testeventloop", TesteventloopCmd,
- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ (ClientData) 0, NULL);
return TCL_OK;
}
@@ -55,9 +54,9 @@ Tclxttest_Init(interp)
*
* TesteventloopCmd --
*
- * This procedure implements the "testeventloop" command. It is
- * used to test the Tcl notifier from an "external" event loop
- * (i.e. not Tcl_DoOneEvent()).
+ * This procedure implements the "testeventloop" command. It is used to
+ * test the Tcl notifier from an "external" event loop (i.e. not
+ * Tcl_DoOneEvent()).
*
* Results:
* A standard Tcl result.
@@ -69,19 +68,19 @@ Tclxttest_Init(interp)
*/
static int
-TesteventloopCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. */
+TesteventloopCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ CONST char **argv) /* Argument strings. */
{
- static int *framePtr = NULL; /* Pointer to integer on stack frame of
- * innermost invocation of the "wait"
- * subcommand. */
+ static int *framePtr = NULL;/* Pointer to integer on stack frame of
+ * innermost invocation of the "wait"
+ * subcommand. */
if (argc < 2) {
Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
- " option ... \"", (char *) NULL);
+ " option ... \"", NULL);
return TCL_ERROR;
}
if (strcmp(argv[1], "done") == 0) {
@@ -99,8 +98,8 @@ TesteventloopCmd(clientData, interp, argc, argv)
framePtr = &done;
/*
- * Enter an Xt event loop until the flag changes.
- * Note that we do not explicitly call Tcl_ServiceEvent().
+ * Enter an Xt event loop until the flag changes. Note that we do not
+ * explicitly call Tcl_ServiceEvent().
*/
done = 0;
@@ -111,7 +110,7 @@ TesteventloopCmd(clientData, interp, argc, argv)
framePtr = oldFramePtr;
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be done or wait", (char *) NULL);
+ "\": must be done or wait", NULL);
return TCL_ERROR;
}
return TCL_OK;
diff --git a/win/Makefile.in b/win/Makefile.in
index f11ef53..8883128 100644
--- a/win/Makefile.in
+++ b/win/Makefile.in
@@ -1,24 +1,21 @@
#
-# This file is a Makefile for Tcl. If it has the name "Makefile.in"
-# then it is a template for a Makefile; to generate the actual Makefile,
-# run "./configure", which is a configuration script generated by the
-# "autoconf" program (constructs like "@foo@" will get replaced in the
-# actual Makefile.
+# This file is a Makefile for Tcl. If it has the name "Makefile.in" then it
+# is a template for a Makefile; to generate the actual Makefile, run
+# "./configure", which is a configuration script generated by the "autoconf"
+# program (constructs like "@foo@" will get replaced in the actual Makefile.
VERSION = @TCL_VERSION@
-#----------------------------------------------------------------
-# Things you can change to personalize the Makefile for your own
-# site (you can make these changes in either Makefile.in or
-# Makefile, but changes to Makefile will get lost if you re-run
-# the configuration script).
-#----------------------------------------------------------------
+#--------------------------------------------------------------------------
+# Things you can change to personalize the Makefile for your own site (you can
+# make these changes in either Makefile.in or Makefile, but changes to
+# Makefile will get lost if you re-run the configuration script).
+#--------------------------------------------------------------------------
-# Default top-level directories in which to install architecture-
-# specific files (exec_prefix) and machine-independent files such
-# as scripts (prefix). The values specified here may be overridden
-# at configure-time with the --exec-prefix and --prefix options
-# to the "configure" script.
+# Default top-level directories in which to install architecture-specific
+# files (exec_prefix) and machine-independent files such as scripts (prefix).
+# The values specified here may be overridden at configure-time with the
+# --exec-prefix and --prefix options to the "configure" script.
prefix = @prefix@
exec_prefix = @exec_prefix@
@@ -27,16 +24,15 @@ libdir = @libdir@
includedir = @includedir@
mandir = @mandir@
-# The following definition can be set to non-null for special systems
-# like AFS with replication. It allows the pathnames used for installation
-# to be different than those used for actually reference files at
-# run-time. INSTALL_ROOT is prepended to $prefix and $exec_prefix
-# when installing files.
+# The following definition can be set to non-null for special systems like AFS
+# with replication. It allows the pathnames used for installation to be
+# different than those used for actually reference files at run-time.
+# INSTALL_ROOT is prepended to $prefix and $exec_prefix when installing files.
INSTALL_ROOT =
-# Directory from which applications will reference the library of Tcl
-# scripts (note: you can set the TCL_LIBRARY environment variable at
-# run-time to override this value):
+# Directory from which applications will reference the library of Tcl scripts
+# (note: you can set the TCL_LIBRARY environment variable at run-time to
+# override this value):
TCL_LIBRARY = $(prefix)/lib/tcl$(VERSION)
# Path to use at runtime to refer to LIB_INSTALL_DIR:
@@ -63,12 +59,10 @@ MAN_INSTALL_DIR = $(INSTALL_ROOT)$(mandir)
# Directory in which to install manual entry for tclsh:
MAN1_INSTALL_DIR = $(MAN_INSTALL_DIR)/man1
-# Directory in which to install manual entries for Tcl's C library
-# procedures:
+# Directory in which to install manual entries for Tcl's C library procedures:
MAN3_INSTALL_DIR = $(MAN_INSTALL_DIR)/man3
-# Directory in which to install manual entries for the built-in
-# Tcl commands:
+# Directory in which to install manual entries for the built-in Tcl commands:
MANN_INSTALL_DIR = $(MAN_INSTALL_DIR)/mann
# Libraries built with optimization switches have this additional extension
@@ -88,18 +82,19 @@ CFLAGS_OPTIMIZE = @CFLAGS_OPTIMIZE@
#CFLAGS = $(CFLAGS_DEBUG) $(CFLAGS_OPTIMIZE)
CFLAGS = @CFLAGS@ @CFLAGS_DEFAULT@
-# To enable compilation debugging reverse the comment characters on
-# one of the following lines.
+# To enable compilation debugging reverse the comment characters on one of the
+# following lines.
COMPILE_DEBUG_FLAGS =
#COMPILE_DEBUG_FLAGS = -DTCL_COMPILE_DEBUG
#COMPILE_DEBUG_FLAGS = -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS
# Special compiler flags to use when building man2tcl on Windows.
-MAN2TCLFLAGS = @MAN2TCLFLAGS@
+MAN2TCLFLAGS = @MAN2TCLFLAGS@
SRC_DIR = @srcdir@
ROOT_DIR = @srcdir@/..
GENERIC_DIR = @srcdir@/../generic
+TOMMATH_DIR = @srcdir@/../libtommath
WIN_DIR = @srcdir@
COMPAT_DIR = @srcdir@/../compat
@@ -107,15 +102,29 @@ COMPAT_DIR = @srcdir@/../compat
CYGPATH = @CYGPATH@
GENERIC_DIR_NATIVE = $(shell $(CYGPATH) '$(GENERIC_DIR)' | sed 's!\\!/!g')
+TOMMATH_DIR_NATIVE = $(shell $(CYGPATH) '$(TOMMATH_DIR)' | sed 's!\\!/!g')
WIN_DIR_NATIVE = $(shell $(CYGPATH) '$(WIN_DIR)' | sed 's!\\!/!g')
ROOT_DIR_NATIVE = $(shell $(CYGPATH) '$(ROOT_DIR)' | sed 's!\\!/!g')
-
-LIBRARY_DIR = $(ROOT_DIR_NATIVE)/library
-
+#GENERIC_DIR_NATIVE = $(GENERIC_DIR)
+#TOMMATH_DIR_NATIVE = $(TOMMATH_DIR)
+#WIN_DIR_NATIVE = $(WIN_DIR)
+#ROOT_DIR_NATIVE = $(ROOT_DIR)
+
+# Fully qualify library path so that `make test`
+# does not depend on the current directory.
+LIBRARY_DIR1 = $(shell cd '$(ROOT_DIR_NATIVE)/library' ; pwd)
+LIBRARY_DIR = $(shell $(CYGPATH) '$(LIBRARY_DIR1)' | sed 's!\\!/!g')
DLLSUFFIX = @DLLSUFFIX@
LIBSUFFIX = @LIBSUFFIX@
EXESUFFIX = @EXESUFFIX@
+VER = @TCL_MAJOR_VERSION@@TCL_MINOR_VERSION@
+DOTVER = @TCL_MAJOR_VERSION@.@TCL_MINOR_VERSION@
+DDEVER = @TCL_DDE_MAJOR_VERSION@@TCL_DDE_MINOR_VERSION@
+DDEDOTVER = @TCL_DDE_MAJOR_VERSION@.@TCL_DDE_MINOR_VERSION@
+REGVER = @TCL_REG_MAJOR_VERSION@@TCL_REG_MINOR_VERSION@
+REGDOTVER = @TCL_REG_MAJOR_VERSION@.@TCL_REG_MINOR_VERSION@
+
TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
TCL_DLL_FILE = @TCL_DLL_FILE@
TCL_LIB_FILE = @TCL_LIB_FILE@
@@ -129,11 +138,10 @@ SHARED_LIBRARIES = $(TCL_DLL_FILE) $(TCL_STUB_LIB_FILE) \
$(DDE_DLL_FILE) $(REG_DLL_FILE) $(PIPE_DLL_FILE)
STATIC_LIBRARIES = $(TCL_LIB_FILE) $(REG_LIB_FILE) $(DDE_LIB_FILE)
-# TCL_EXE is the name of a tclsh executable that is available *BEFORE*
-# running make for the first time. Certain build targets (make genstubs)
-# need it to be available on the PATH. This executable should *NOT* be
-# required just to do a normal build although it can be required to run
-# make dist.
+# TCL_EXE is the name of a tclsh executable that is available *BEFORE* running
+# make for the first time. Certain build targets (make genstubs) need it to be
+# available on the PATH. This executable should *NOT* be required just to do a
+# normal build although it can be required to run make dist.
TCL_EXE = tclsh
TCLSH = tclsh$(VER)${EXESUFFIX}
@@ -143,11 +151,10 @@ MAN2TCL = man2tcl$(EXEEXT)
@SET_MAKE@
-# Setting the VPATH variable to a list of paths will cause the
-# makefile to look into these paths when resolving .c to .obj
-# dependencies.
+# Setting the VPATH variable to a list of paths will cause the Makefile to
+# look into these paths when resolving .c to .obj dependencies.
-VPATH = $(GENERIC_DIR):$(WIN_DIR):$(COMPAT_DIR)
+VPATH = $(GENERIC_DIR):$(TOMMATH_DIR):$(WIN_DIR):$(COMPAT_DIR)
AR = @AR@
RANLIB = @RANLIB@
@@ -168,12 +175,6 @@ SHLIB_LD = @SHLIB_LD@
SHLIB_LD_LIBS = @SHLIB_LD_LIBS@ $(LIBS)
SHLIB_CFLAGS = @SHLIB_CFLAGS@
SHLIB_SUFFIX = @SHLIB_SUFFIX@
-VER = @TCL_MAJOR_VERSION@@TCL_MINOR_VERSION@
-DOTVER = @TCL_MAJOR_VERSION@.@TCL_MINOR_VERSION@
-DDEVER = @TCL_DDE_MAJOR_VERSION@@TCL_DDE_MINOR_VERSION@
-DDEDOTVER = @TCL_DDE_MAJOR_VERSION@.@TCL_DDE_MINOR_VERSION@
-REGVER = @TCL_REG_MAJOR_VERSION@@TCL_REG_MINOR_VERSION@
-REGDOTVER = @TCL_REG_MAJOR_VERSION@.@TCL_REG_MINOR_VERSION@
LIBS = @LIBS@
RMDIR = rm -rf
@@ -183,14 +184,16 @@ RM = rm -f
COPY = cp
CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${TCL_SHLIB_CFLAGS} \
--I"${GENERIC_DIR_NATIVE}" -I"${WIN_DIR_NATIVE}" ${AC_FLAGS} \
+-I"${GENERIC_DIR_NATIVE}" -DTCL_TOMMATH -DMP_PREC=4 -I"${TOMMATH_DIR_NATIVE}" \
+-I"${WIN_DIR_NATIVE}" ${AC_FLAGS} \
${COMPILE_DEBUG_FLAGS}
CC_OBJNAME = @CC_OBJNAME@
CC_EXENAME = @CC_EXENAME@
STUB_CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} \
--I"${GENERIC_DIR_NATIVE}" -I"${WIN_DIR_NATIVE}" ${AC_FLAGS} \
+-I"${GENERIC_DIR_NATIVE}" -DTCL_TOMMATH -DMP_PREC=4 -I"${TOMMATH_DIR_NATIVE}" \
+-I"${WIN_DIR_NATIVE}" ${AC_FLAGS} \
${COMPILE_DEBUG_FLAGS}
TCLTEST_OBJS = \
@@ -218,7 +221,9 @@ GENERIC_OBJS = \
tclCompCmds.$(OBJEXT) \
tclCompExpr.$(OBJEXT) \
tclCompile.$(OBJEXT) \
+ tclConfig.$(OBJEXT) \
tclDate.$(OBJEXT) \
+ tclDictObj.$(OBJEXT) \
tclEncoding.$(OBJEXT) \
tclEnv.$(OBJEXT) \
tclEvent.$(OBJEXT) \
@@ -233,6 +238,7 @@ GENERIC_OBJS = \
tclIO.$(OBJEXT) \
tclIOCmd.$(OBJEXT) \
tclIOGT.$(OBJEXT) \
+ tclIORChan.$(OBJEXT) \
tclIOSock.$(OBJEXT) \
tclIOUtil.$(OBJEXT) \
tclLink.$(OBJEXT) \
@@ -245,9 +251,10 @@ GENERIC_OBJS = \
tclObj.$(OBJEXT) \
tclPanic.$(OBJEXT) \
tclParse.$(OBJEXT) \
- tclParseExpr.$(OBJEXT) \
+ tclPathObj.$(OBJEXT) \
tclPipe.$(OBJEXT) \
tclPkg.$(OBJEXT) \
+ tclPkgConfig.$(OBJEXT) \
tclPosixStr.$(OBJEXT) \
tclPreserve.$(OBJEXT) \
tclProc.$(OBJEXT) \
@@ -256,16 +263,87 @@ GENERIC_OBJS = \
tclResult.$(OBJEXT) \
tclScan.$(OBJEXT) \
tclStringObj.$(OBJEXT) \
+ tclStrToD.$(OBJEXT) \
tclStubInit.$(OBJEXT) \
tclStubLib.$(OBJEXT) \
tclThread.$(OBJEXT) \
tclThreadAlloc.$(OBJEXT) \
tclThreadJoin.$(OBJEXT) \
+ tclThreadStorage.$(OBJEXT) \
tclTimer.$(OBJEXT) \
+ tclTomMathInterface.$(OBJEXT) \
+ tclTrace.$(OBJEXT) \
tclUtf.$(OBJEXT) \
tclUtil.$(OBJEXT) \
tclVar.$(OBJEXT)
+TOMMATH_OBJS = \
+ bncore.${OBJEXT} \
+ bn_reverse.${OBJEXT} \
+ bn_fast_s_mp_mul_digs.${OBJEXT} \
+ bn_fast_s_mp_sqr.${OBJEXT} \
+ bn_mp_add.${OBJEXT} \
+ bn_mp_add_d.${OBJEXT} \
+ bn_mp_and.${OBJEXT} \
+ bn_mp_clamp.${OBJEXT} \
+ bn_mp_clear.${OBJEXT} \
+ bn_mp_clear_multi.${OBJEXT} \
+ bn_mp_cmp.${OBJEXT} \
+ bn_mp_cmp_d.${OBJEXT} \
+ bn_mp_cmp_mag.${OBJEXT} \
+ bn_mp_cnt_lsb.${OBJEXT} \
+ bn_mp_copy.${OBJEXT} \
+ bn_mp_count_bits.${OBJEXT} \
+ bn_mp_div.${OBJEXT} \
+ bn_mp_div_d.${OBJEXT} \
+ bn_mp_div_2.${OBJEXT} \
+ bn_mp_div_2d.${OBJEXT} \
+ bn_mp_div_3.${OBJEXT} \
+ bn_mp_exch.${OBJEXT} \
+ bn_mp_expt_d.${OBJEXT} \
+ bn_mp_grow.${OBJEXT} \
+ bn_mp_init.${OBJEXT} \
+ bn_mp_init_copy.${OBJEXT} \
+ bn_mp_init_multi.${OBJEXT} \
+ bn_mp_init_set.${OBJEXT} \
+ bn_mp_init_set_int.${OBJEXT} \
+ bn_mp_init_size.${OBJEXT} \
+ bn_mp_karatsuba_mul.${OBJEXT} \
+ bn_mp_karatsuba_sqr.$(OBJEXT) \
+ bn_mp_lshd.${OBJEXT} \
+ bn_mp_mod.${OBJEXT} \
+ bn_mp_mod_2d.${OBJEXT} \
+ bn_mp_mul.${OBJEXT} \
+ bn_mp_mul_2.${OBJEXT} \
+ bn_mp_mul_2d.${OBJEXT} \
+ bn_mp_mul_d.${OBJEXT} \
+ bn_mp_neg.${OBJEXT} \
+ bn_mp_or.${OBJEXT} \
+ bn_mp_radix_size.${OBJEXT} \
+ bn_mp_radix_smap.${OBJEXT} \
+ bn_mp_read_radix.${OBJEXT} \
+ bn_mp_rshd.${OBJEXT} \
+ bn_mp_set.${OBJEXT} \
+ bn_mp_set_int.${OBJEXT} \
+ bn_mp_shrink.${OBJEXT} \
+ bn_mp_sqr.${OBJEXT} \
+ bn_mp_sqrt.${OBJEXT} \
+ bn_mp_sub.${OBJEXT} \
+ bn_mp_sub_d.${OBJEXT} \
+ bn_mp_to_unsigned_bin.${OBJEXT} \
+ bn_mp_to_unsigned_bin_n.${OBJEXT} \
+ bn_mp_toom_mul.${OBJEXT} \
+ bn_mp_toom_sqr.${OBJEXT} \
+ bn_mp_toradix_n.${OBJEXT} \
+ bn_mp_unsigned_bin_size.${OBJEXT} \
+ bn_mp_xor.${OBJEXT} \
+ bn_mp_zero.${OBJEXT} \
+ bn_s_mp_add.${OBJEXT} \
+ bn_s_mp_mul_digs.${OBJEXT} \
+ bn_s_mp_sqr.${OBJEXT} \
+ bn_s_mp_sub.${OBJEXT}
+
+
WIN_OBJS = \
tclWin32Dll.$(OBJEXT) \
tclWinChan.$(OBJEXT) \
@@ -276,15 +354,11 @@ WIN_OBJS = \
tclWinFile.$(OBJEXT) \
tclWinInit.$(OBJEXT) \
tclWinLoad.$(OBJEXT) \
- tclWinMtherr.$(OBJEXT) \
tclWinNotify.$(OBJEXT) \
tclWinPipe.$(OBJEXT) \
tclWinSock.$(OBJEXT) \
tclWinThrd.$(OBJEXT) \
- tclWinTime.$(OBJEXT)
-
-COMPAT_OBJS = \
- strftime.$(OBJEXT) strtoll.$(OBJEXT) strtoull.$(OBJEXT)
+ tclWinTime.$(OBJEXT)
PIPE_OBJS = stub16.$(OBJEXT)
@@ -296,7 +370,7 @@ STUB_OBJS = tclStubLib.$(OBJEXT)
TCLSH_OBJS = tclAppInit.$(OBJEXT)
-TCL_OBJS = ${GENERIC_OBJS} ${WIN_OBJS} ${COMPAT_OBJS}
+TCL_OBJS = ${GENERIC_OBJS} $(TOMMATH_OBJS) ${WIN_OBJS}
TCL_DOCS = "$(ROOT_DIR_NATIVE)"/doc/*.[13n]
@@ -321,10 +395,12 @@ $(MAN2TCL): $(ROOT_DIR)/tools/man2tcl.c
$(TCLSH): $(TCL_LIB_FILE) $(TCL_STUB_LIB_FILE) $(TCLSH_OBJS) tclsh.$(RES)
$(CC) $(CFLAGS) $(TCLSH_OBJS) $(TCL_LIB_FILE) $(LIBS) \
tclsh.$(RES) $(CC_EXENAME) $(LDFLAGS_CONSOLE)
+ @VC_MANIFEST_EMBED_EXE@
$(TCLTEST): $(TCL_LIB_FILE) $(TCLTEST_OBJS) $(CAT32) tclsh.$(RES)
$(CC) $(CFLAGS) $(TCLTEST_OBJS) $(TCL_LIB_FILE) $(LIBS) \
tclsh.$(RES) $(CC_EXENAME) $(LDFLAGS_CONSOLE)
+ @VC_MANIFEST_EMBED_EXE@
cat32.$(OBJEXT): cat.c
$(CC) -c $(CC_SWITCHES) @DEPARG@ $(CC_OBJNAME)
@@ -332,8 +408,8 @@ cat32.$(OBJEXT): cat.c
$(CAT32): cat32.$(OBJEXT)
$(CC) $(CFLAGS) cat32.$(OBJEXT) $(CC_EXENAME) $(LIBS) $(LDFLAGS_CONSOLE)
-# The following targets are configured by autoconf to generate either
-# a shared library or static library
+# The following targets are configured by autoconf to generate either a shared
+# library or static library
${TCL_STUB_LIB_FILE}: ${STUB_OBJS}
@$(RM) ${TCL_STUB_LIB_FILE}
@@ -343,6 +419,7 @@ ${TCL_STUB_LIB_FILE}: ${STUB_OBJS}
${TCL_DLL_FILE}: ${TCL_OBJS} tcl.$(RES)
@$(RM) ${TCL_DLL_FILE}
@MAKE_DLL@ ${TCL_OBJS} tcl.$(RES) $(SHLIB_LD_LIBS)
+ @VC_MANIFEST_EMBED_DLL@
${TCL_LIB_FILE}: ${TCL_OBJS}
@$(RM) ${TCL_LIB_FILE}
@@ -365,14 +442,13 @@ ${REG_LIB_FILE}: ${REG_OBJS} ${TCL_LIB_FILE}
@$(RM) ${REG_LIB_FILE}
@MAKE_LIB@ ${REG_OBJS} ${TCL_LIB_FILE}
-# PIPE_DLL_FILE is actually an executable, don't build it
-# like a DLL.
+# PIPE_DLL_FILE is actually an executable, don't build it like a DLL.
${PIPE_DLL_FILE}: ${PIPE_OBJS}
@$(RM) ${PIPE_DLL_FILE}
@MAKE_EXE@ $(CFLAGS) ${PIPE_OBJS} $(LIBS) $(LDFLAGS_CONSOLE)
-# Add the object extension to the implicit rules. By default .obj is not
+# Add the object extension to the implicit rules. By default .obj is not
# automatically added.
.SUFFIXES: .${OBJEXT}
@@ -411,8 +487,32 @@ tclWinReg.${OBJEXT} : tclWinReg.c
tclWinDde.${OBJEXT} : tclWinDde.c
$(CC) -c $(CC_SWITCHES) -DUSE_TCL_STUBS @DEPARG@ $(CC_OBJNAME)
-# The following objects are part of the stub library and should not
-# be built as DLL objects but none of the symbols should be exported
+# TIP #59, embedding of configuration information into the binary library.
+#
+# Part of Tcl's configuration information are the paths where it was installed
+# and where it will look for its libraries (which can be different). We derive
+# this information from the variables which can be overridden by the user. As
+# every path can be configured separately we do not remember one general
+# prefix/exec_prefix but all the different paths individually.
+
+tclPkgConfig.${OBJEXT}: tclPkgConfig.c
+ $(CC) -c $(CC_SWITCHES) \
+ -DCFG_INSTALL_LIBDIR=\"$(LIB_INSTALL_DIR)\" \
+ -DCFG_INSTALL_BINDIR=\"$(BIN_INSTALL_DIR)\" \
+ -DCFG_INSTALL_SCRDIR=\"$(SCRIPT_INSTALL_DIR)\" \
+ -DCFG_INSTALL_INCDIR=\"$(INCLUDE_INSTALL_DIR)\" \
+ -DCFG_INSTALL_DOCDIR=\"$(MAN_INSTALL_DIR)\" \
+ \
+ -DCFG_RUNTIME_LIBDIR=\"$(libdir)\" \
+ -DCFG_RUNTIME_BINDIR=\"$(bindir)\" \
+ -DCFG_RUNTIME_SCRDIR=\"$(TCL_LIBRARY)\" \
+ -DCFG_RUNTIME_INCDIR=\"$(includedir)\" \
+ -DCFG_RUNTIME_DOCDIR=\"$(mandir)\" \
+ -DBUILD_tcl \
+ @DEPARG@ $(CC_OBJNAME)
+
+# The following objects are part of the stub library and should not be built
+# as DLL objects but none of the symbols should be exported
tclStubLib.${OBJEXT}: tclStubLib.c
$(CC) -c $(CC_SWITCHES) -DSTATIC_BUILD @DEPARG@ $(CC_OBJNAME)
@@ -420,12 +520,32 @@ tclStubLib.${OBJEXT}: tclStubLib.c
# Implicit rule for all object files that will end up in the Tcl library
-.c.${OBJEXT}:
+%.${OBJEXT}: %.c
$(CC) -c $(CC_SWITCHES) -DBUILD_tcl @DEPARG@ $(CC_OBJNAME)
.rc.$(RES):
$(RC) @RC_OUT@ $@ @RC_TYPE@ @RC_DEFINES@ @RC_INCLUDE@ "$(GENERIC_DIR_NATIVE)" @RC_INCLUDE@ "$(WIN_DIR_NATIVE)" @DEPARG@
+# The following target generates the file generic/tclDate.c from the yacc
+# grammar found in generic/tclGetDate.y. This is only run by hand as yacc is
+# not available in all environments. The name of the .c file is different than
+# the name of the .y file so that make doesn't try to automatically regenerate
+# the .c file.
+
+gendate:
+ bison --output-file=$(GENERIC_DIR)/tclDate.c \
+ --name-prefix=TclDate \
+ --no-lines \
+ $(GENERIC_DIR)/tclGetDate.y
+
+# The following target generates the file generic/tclTomMath.h. It needs to be
+# run (and the results checked) after updating to a new release of libtommath.
+
+gentommath_h:
+ $(TCL_EXE) "$(ROOT_DIR_NATIVE)\tools\fix_tommath_h.tcl" \
+ "$(TOMMATH_DIR_NATIVE)\tommath.h" \
+ > "$(GENERIC_DIR_NATIVE)\tclTomMath.h"
+
install: all install-binaries install-libraries install-doc
install-binaries: binaries
@@ -438,7 +558,7 @@ install-binaries: binaries
else true; \
fi; \
done;
- @for i in dde1.2 reg1.1; \
+ @for i in dde1.3 reg1.2; \
do \
if [ ! -d $(LIB_INSTALL_DIR)/$$i ] ; then \
echo "Making directory $(LIB_INSTALL_DIR)/$$i"; \
@@ -462,26 +582,26 @@ install-binaries: binaries
done
@if [ -f $(DDE_DLL_FILE) ]; then \
echo installing $(DDE_DLL_FILE); \
- $(COPY) $(DDE_DLL_FILE) $(LIB_INSTALL_DIR)/dde1.2; \
+ $(COPY) $(DDE_DLL_FILE) $(LIB_INSTALL_DIR)/dde1.3; \
$(COPY) $(ROOT_DIR)/library/dde/pkgIndex.tcl \
- $(LIB_INSTALL_DIR)/dde1.2; \
+ $(LIB_INSTALL_DIR)/dde1.3; \
fi
@if [ -f $(DDE_LIB_FILE) ]; then \
echo installing $(DDE_LIB_FILE); \
- $(COPY) $(DDE_LIB_FILE) $(LIB_INSTALL_DIR)/dde1.2; \
+ $(COPY) $(DDE_LIB_FILE) $(LIB_INSTALL_DIR)/dde1.3; \
fi
@if [ -f $(REG_DLL_FILE) ]; then \
echo installing $(REG_DLL_FILE); \
- $(COPY) $(REG_DLL_FILE) $(LIB_INSTALL_DIR)/reg1.1; \
+ $(COPY) $(REG_DLL_FILE) $(LIB_INSTALL_DIR)/reg1.2; \
$(COPY) $(ROOT_DIR)/library/reg/pkgIndex.tcl \
- $(LIB_INSTALL_DIR)/reg1.1; \
+ $(LIB_INSTALL_DIR)/reg1.2; \
fi
@if [ -f $(REG_LIB_FILE) ]; then \
echo installing $(REG_LIB_FILE); \
- $(COPY) $(REG_LIB_FILE) $(LIB_INSTALL_DIR)/reg1.1; \
+ $(COPY) $(REG_LIB_FILE) $(LIB_INSTALL_DIR)/reg1.2; \
fi
-install-libraries: libraries
+install-libraries: libraries install-tzdata install-msgs
@for i in $(prefix)/lib $(INCLUDE_INSTALL_DIR) \
$(SCRIPT_INSTALL_DIR); \
do \
@@ -491,7 +611,7 @@ install-libraries: libraries
else true; \
fi; \
done;
- @for i in platform http1.0 http2.5 opt0.4 encoding msgcat1.3 tcltest2.2; \
+ @for i in http1.0 opt0.4 encoding ../tcl8 ../tcl8/8.2 ../tcl8/8.3 ../tcl8/8.4 ../tcl8/8.4/platform ../tcl8/8.5; \
do \
if [ ! -d $(SCRIPT_INSTALL_DIR)/$$i ] ; then \
echo "Making directory $(SCRIPT_INSTALL_DIR)/$$i"; \
@@ -501,7 +621,11 @@ install-libraries: libraries
done;
@echo "Installing header files";
@for i in "$(GENERIC_DIR)/tcl.h" "$(GENERIC_DIR)/tclDecls.h" \
- "$(GENERIC_DIR)/tclPlatDecls.h" ; \
+ "$(GENERIC_DIR)/tclPlatDecls.h" \
+ "$(GENERIC_DIR)/tclTomMath.h" \
+ "$(GENERIC_DIR)/tclTomMathDecls.h" \
+ "$(TOMMATH_DIR)/tommath_class.h" \
+ "$(TOMMATH_DIR)/tommath_superclass.h" ; \
do \
$(COPY) "$$i" "$(INCLUDE_INSTALL_DIR)"; \
done;
@@ -510,41 +634,43 @@ install-libraries: libraries
do \
$(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)"; \
done;
- @echo "Installing library platform directory";
- @for j in $(ROOT_DIR)/library/platform/*.tcl; \
- do \
- $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/platform"; \
- done;
@echo "Installing library http1.0 directory";
@for j in $(ROOT_DIR)/library/http1.0/*.tcl; \
do \
$(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/http1.0"; \
done;
- @echo "Installing library http2.5 directory";
- @for j in $(ROOT_DIR)/library/http/*.tcl; \
- do \
- $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/http2.5"; \
- done;
+ @echo "Installing package http 2.7.6 as a Tcl Module";
+ @$(COPY) $(ROOT_DIR)/library/http/http.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.4/http-2.7.6.tm;
@echo "Installing library opt0.4 directory";
@for j in $(ROOT_DIR)/library/opt/*.tcl; \
do \
$(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/opt0.4"; \
done;
- @echo "Installing library msgcat1.3 directory";
- @for j in $(ROOT_DIR)/library/msgcat/*.tcl; \
- do \
- $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/msgcat1.3"; \
- done;
- @echo "Installing library tcltest2.2 directory";
- @for j in $(ROOT_DIR)/library/tcltest/*.tcl; \
- do \
- $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/tcltest2.2"; \
- done;
+ @echo "Installing package msgcat 1.4.4 as a Tcl Module";
+ @$(COPY) $(ROOT_DIR)/library/msgcat/msgcat.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.5/msgcat-1.4.4.tm;
+ @echo "Installing package tcltest 2.3.3 as a Tcl Module";
+ @$(COPY) $(ROOT_DIR)/library/tcltest/tcltest.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.5/tcltest-2.3.3.tm;
+ @echo "Installing package platform 1.0.10 as a Tcl Module";
+ @$(COPY) $(ROOT_DIR)/library/platform/platform.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.4/platform-1.0.10.tm;
+ @echo "Installing package platform::shell 1.1.4 as a Tcl Module";
+ @$(COPY) $(ROOT_DIR)/library/platform/shell.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.4/platform/shell-1.1.4.tm;
@echo "Installing encodings";
@for i in $(ROOT_DIR)/library/encoding/*.enc ; do \
$(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)/encoding"; \
done;
+install-tzdata:
+ @echo "Installing time zone data"
+ @TCL_LIBRARY="${LIBRARY_DIR}"; export TCL_LIBRARY; \
+ ./$(TCLSH) "$(ROOT_DIR)/tools/installData.tcl" \
+ "$(ROOT_DIR)/library/tzdata" "$(SCRIPT_INSTALL_DIR)/tzdata"
+
+install-msgs:
+ @echo "Installing message catalogs"
+ @TCL_LIBRARY="${LIBRARY_DIR}"; export TCL_LIBRARY; \
+ ./$(TCLSH) "$(ROOT_DIR)/tools/installData.tcl" \
+ "$(ROOT_DIR)/library/msgs" "$(SCRIPT_INSTALL_DIR)/msgs"
+
install-doc: doc
# Optional target to install private headers
@@ -554,11 +680,10 @@ install-private-headers: libraries
if [ ! -d $$i ] ; then \
echo "Making directory $$i"; \
$(MKDIR) $$i; \
- chmod 755 $$i; \
else true; \
fi; \
done;
- @echo "Installing private header files to $(PRIVATE_INCLUDE_INSTALL_DIR)/";
+ @echo "Installing private header files";
@for i in "$(GENERIC_DIR)/tclInt.h" "$(GENERIC_DIR)/tclIntDecls.h" \
"$(GENERIC_DIR)/tclIntPlatDecls.h" "$(GENERIC_DIR)/tclPort.h" \
"$(WIN_DIR)/tclWinPort.h" ; \
@@ -566,22 +691,24 @@ install-private-headers: libraries
$(COPY) "$$i" "$(PRIVATE_INCLUDE_INSTALL_DIR)"; \
done;
-# Specifying TESTFLAGS on the command line is the standard way to pass
-# args to tcltest, ie:
+# Specifying TESTFLAGS on the command line is the standard way to pass args to
+# tcltest, i.e.:
# % make test TESTFLAGS="-verbose bps -file fileName.test"
test: binaries $(TCLTEST)
TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \
./$(TCLTEST) "$(ROOT_DIR_NATIVE)/tests/all.tcl" $(TESTFLAGS) \
- | ./$(CAT32)
+ -load "set ::ddelib [file normalize ${DDE_DLL_FILE}]; \
+ set ::reglib [file normalize ${REG_DLL_FILE}]" | ./$(CAT32)
# Useful target to launch a built tcltest with the proper path,...
runtest: binaries $(TCLTEST)
@TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \
- ./$(TCLTEST) $(TESTFLAGS) $(SCRIPT)
+ ./$(TCLTEST) $(TESTFLAGS) -load "set ::ddelib [file normalize ${DDE_DLL_FILE}]; \
+ set ::reglib [file normalize ${REG_DLL_FILE}]" $(SCRIPT)
-# This target can be used to run tclsh from the build directory
-# via `make shell SCRIPT=foo.tcl`
+# This target can be used to run tclsh from the build directory via
+# `make shell SCRIPT=foo.tcl`
shell: binaries
@TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \
./$(TCLSH) $(SCRIPT)
@@ -589,7 +716,7 @@ shell: binaries
# This target can be used to run tclsh inside either gdb or insight
gdb: binaries
@echo "set env TCL_LIBRARY=$(LIBRARY_DIR)" > gdb.run
- gdb ./tclsh --command=gdb.run
+ gdb ./$(TCLSH) --command=gdb.run
rm gdb.run
depend:
@@ -607,7 +734,7 @@ clean: cleanhelp
distclean: clean
$(RM) Makefile config.status config.cache config.log tclConfig.sh \
- tcl.hpj
+ tcl.hpj config.status.lineno
#
# Regenerate the stubs files.
@@ -623,4 +750,5 @@ genstubs:
$(TCL_EXE) "$(ROOT_DIR_NATIVE)\tools\genStubs.tcl" \
"$(GENERIC_DIR_NATIVE)" \
"$(GENERIC_DIR_NATIVE)\tcl.decls" \
- "$(GENERIC_DIR_NATIVE)\tclInt.decls"
+ "$(GENERIC_DIR_NATIVE)\tclInt.decls" \
+ "$(GENERIC_DIR_NATIVE)\tclTomMath.decls"
diff --git a/win/README b/win/README
index 5e3d00f..1929362 100644
--- a/win/README
+++ b/win/README
@@ -1,4 +1,4 @@
-Tcl 8.4 for Windows
+Tcl 8.5 for Windows
1. Introduction
---------------
@@ -16,7 +16,7 @@ The information in this file is maintained on the web at:
In order to compile Tcl for Windows, you need the following:
- Tcl 8.4 Source Distribution (plus any patches)
+ Tcl 8.5 Source Distribution (plus any patches)
and
@@ -51,9 +51,9 @@ Use the Makefile "install" target to install Tcl. It will install it
according to the prefix options you provided in the correct directory
structure.
-Note that in order to run tclsh84.exe, you must ensure that tcl84.dll
-and tclpip84.dll are on your path, in the system directory, or in the
-directory containing tclsh84.exe.
+Note that in order to run tclsh85.exe, you must ensure that tcl85.dll is on
+your path, in the system directory, or in the directory containing
+tclsh85.exe.
Note: Tcl no longer provides support for Win32s.
diff --git a/win/README.binary b/win/README.binary
deleted file mode 100644
index 8388235..0000000
--- a/win/README.binary
+++ /dev/null
@@ -1,141 +0,0 @@
-Tcl/Tk 8.4 for Windows, Binary Distribution
-
-1. Introduction
----------------
-
-This directory contains the binary distribution of Tcl/Tk 8.4.19 for
-Windows. It was compiled with Microsoft Visual C++ 6.0 using Win32
-API, so that it will run under Windows NT, 95, 98 and 2000.
-
-Tcl provides a powerful platform for creating integration applications
-that tie together diverse applications, protocols, devices, and
-frameworks. When paired with the Tk toolkit, Tcl provides the fastest
-and most powerful way to create GUI applications that run on PCs, Unix,
-and the Macintosh. Tcl can also be used for a variety of web-related
-tasks and for creating powerful command languages for applications.
-
-Tcl is maintained, enhanced, and distributed freely by the Tcl community.
-
-2. Documentation
-----------------
-
-The home of Tcl and Tk sources and bug database on the Web is at:
- http://tcl.sourceforge.net/
-
-The home page for the Tcl Developer Xchange is at:
- http://www.tcl.tk/
-
-The home page for the Tcl/Tk 8.4 release is
- http://www.tcl.tk/software/tcltk/8.4.html
-
-Detailed release notes can be found at the file distributions page
-by clicking on the relevant version.
- http://sourceforge.net/project/showfiles.php?group_id=10894
-
-Information about Tcl itself can be found at
- http://www.tcl.tk/scripting/
-
-There are many Tcl books on the market. Most are listed at
- http://www.tcl.tk/resource/doc/books/
-
-There are notes about compiling Tcl at
- http://www.tcl.tk/doc/howto/compile.html
-
-3. Installation
----------------
-
-The binary release is distributed as a self-extracting archive called
-tcl<version>.exe. The setup program which will prompt you for an
-installation directory. It will create the installation heirarchy
-under the specified directory, and install a wish application icon
-under the program manager group of your choice.
-
-We are no longer supporting use of Tcl with 16-bit versions of
-Windows. Microsoft has completely dropped support of the Win32s
-subsystem.
-
-4. Linking against the binary release
---------------------------------------
-
-In order to link your applications against the .dll files shipped with
-this release, you will need to use the appropriate .lib file for your
-compiler. In the lib directory of the installation directory, there
-are library files for the Microsoft Visual C++ compiler:
-
- tcl84.lib
- tk84.lib
-
-5. Building dynamically loadable extensions
---------------------------------------------
-
-Please refer to the example dynamically loadable extension provided on
-our ftp site:
-
- ftp://ftp.scriptics.com/pub/tcl/misc/example.zip
-
-This archive contains a template that you can use for building
-extensions that will be loadable on Unix, Windows, and Macintosh
-systems.
-
-6. Reporting Bugs
------------------
-If you have comments or bug reports for the Windows version of Tcl,
-please use our online database at:
-
- http://tcl.sourceforge.net/
-
-or post them to the newsgroup comp.lang.tcl.
-
-7. Tcl newsgroup
------------------
-
-There is a network news group "comp.lang.tcl" intended for the exchange
-of information about Tcl, Tk, and related applications. Feel free to use
-the newsgroup both for general information questions and for bug reports.
-We read the newsgroup and will attempt to fix bugs and problems reported
-to it.
-
-When using comp.lang.tcl, please be sure that your e-mail return address
-is correctly set in your postings. This allows people to respond directly
-to you, rather than the entire newsgroup, for answers that are not of
-general interest. A bad e-mail return address may prevent you from
-getting answers to your questions. You may have to reconfigure your news
-reading software to ensure that it is supplying valid e-mail addresses.
-
-8. Tcl contributed archive
---------------------------
-
-Many people have created exciting packages and applications based on Tcl
-and/or Tk and made them freely available to the Tcl community. An archive
-of these contributions is kept on the machine ftp.neosoft.com. You
-can access the archive using anonymous FTP; the Tcl contributed archive is
-in the directory "/pub/tcl". The archive also contains several FAQ
-("frequently asked questions") documents that provide solutions to problems
-that are commonly encountered by TCL newcomers.
-
-9. Tcl Resource Center
-----------------------
-
-Visit http://www.tcl.tk/resource/ to see an annotated index of
-many Tcl resources available on the World Wide Web. This includes papers,
-books, and FAQs, as well as extensions, applications, binary releases, and
-patches. You can contribute patches by using the Tracker at
-
- http://tcl.sourceforge.net/
-
-You can also recommend more URLs for the resource center using the forms
-labeled "Add a Resource".
-
-10. Mailing lists
-----------------
-
-Several mailing lists are hosted at SourceForge to discuss development or
-use issues (like Macintosh and Windows topics). For more information and
-to subscribe, visit:
-
- http://sourceforge.net/projects/tcl/
-
-and go to the Mailing Lists page. There are also Special Interest Groups
-(SIGs) setup for these topics and more at:
-
- http://www.tcl.tk/
diff --git a/win/buildall.vc.bat b/win/buildall.vc.bat
index 383e774..55b29ae 100755..100644
--- a/win/buildall.vc.bat
+++ b/win/buildall.vc.bat
@@ -1,56 +1,123 @@
@echo off
-
:: This is an example batchfile for building everything. Please
:: edit this (or make your own) for your needs and wants using
:: the instructions for calling makefile.vc found in makefile.vc
+set SYMBOLS=
+
+:OPTIONS
+if "%1" == "/?" goto help
+if /i "%1" == "/help" goto help
+if %1.==symbols. goto SYMBOLS
+if %1.==debug. goto SYMBOLS
+goto OPTIONS_DONE
+
+:SYMBOLS
+ set SYMBOLS=symbols
+ shift
+ goto OPTIONS
+
+:OPTIONS_DONE
+
+:: reset errorlevel
+cd > nul
+
+:: We need to run the development environment batch script that comes
+:: with developer studio (v4,5,6,7,etc...) All have it. These paths
+:: might not be correct. You may need to edit these.
+::
+if not defined MSDevDir (
+ call "C:\Program Files\Microsoft Developer Studio\vc98\bin\vcvars32.bat"
+ ::call "C:\Program Files\Microsoft Developer Studio\vc\bin\vcvars32.bat"
+ ::call c:\dev\devstudio60\vc98\bin\vcvars32.bat
+ if errorlevel 1 goto no_vcvars
+)
+
+
+echo.
echo Sit back and have a cup of coffee while this grinds through ;)
echo You asked for *everything*, remember?
echo.
-
title Building Tcl, please wait...
-if "%MSVCDir%" == "" call c:\dev\devstudio60\vc98\bin\vcvars32.bat
-::if "%MSVCDir%" == "" call "C:\Program Files\Microsoft Developer Studio\vc98\bin\vcvars32.bat"
-set INSTALLDIR=C:\Program Files\Tcl
+
+:: makefile.vc uses this for its default anyways, but show its use here
+:: just to be explicit and convey understanding to the user. Setting
+:: the INSTALLDIR envar prior to running this batchfile affects all builds.
+::
+if "%INSTALLDIR%" == "" set INSTALLDIR=C:\Program Files\Tcl
+
:: Build the normal stuff along with the help file.
::
-nmake -nologo -f makefile.vc release winhelp OPTS=none
+set OPTS=none
+if not %SYMBOLS%.==. set OPTS=symbols
+nmake -nologo -f makefile.vc release winhelp OPTS=%OPTS% %1
if errorlevel 1 goto error
:: Build the static core, dlls and shell.
::
-nmake -nologo -f makefile.vc release OPTS=static
+set OPTS=static
+if not %SYMBOLS%.==. set OPTS=symbols,static
+nmake -nologo -f makefile.vc release OPTS=%OPTS% %1
if errorlevel 1 goto error
:: Build the special static libraries that use the dynamic runtime.
::
-nmake -nologo -f makefile.vc core dlls OPTS=static,msvcrt
+set OPTS=static,msvcrt
+if not %SYMBOLS%.==. set OPTS=symbols,static,msvcrt
+nmake -nologo -f makefile.vc core dlls OPTS=%OPTS% %1
if errorlevel 1 goto error
:: Build the core and shell for thread support.
::
-nmake -nologo -f makefile.vc shell OPTS=threads
+set OPTS=threads
+if not %SYMBOLS%.==. set OPTS=symbols,threads
+nmake -nologo -f makefile.vc shell OPTS=%OPTS% %1
if errorlevel 1 goto error
-:: Build a static, thread support core library (no shell).
+:: Build a static, thread support core library with a shell.
::
-nmake -nologo -f makefile.vc core OPTS=static,threads
+set OPTS=static,threads
+if not %SYMBOLS%.==. set OPTS=symbols,static,threads
+nmake -nologo -f makefile.vc shell OPTS=%OPTS% %1
if errorlevel 1 goto error
-:: Build the special static libraries the use the dynamic runtime,
+:: Build the special static libraries that use the dynamic runtime,
:: but now with thread support.
::
-nmake -nologo -f makefile.vc core dlls OPTS=static,msvcrt,threads
+set OPTS=static,msvcrt,threads
+if not %SYMBOLS%.==. set OPTS=symbols,static,msvcrt,threads
+nmake -nologo -f makefile.vc core dlls OPTS=%OPTS% %1
if errorlevel 1 goto error
+set OPTS=
+set SYMBOLS=
goto end
:error
echo *** BOOM! ***
+goto end
+
+:no_vcvars
+echo vcvars32.bat not found. You'll need to edit this batch script.
+goto out
+
+:help
+title buildall.vc.bat help message
+echo usage:
+echo %0 : builds Tcl for all build types (do this first)
+echo %0 install : installs all the release builds (do this second)
+echo %0 symbols : builds Tcl for all debugging build types
+echo %0 symbols install : install all the debug builds.
+echo.
+goto out
:end
-title Building Tcl, please wait...DONE!
+title Building Tcl, please wait... DONE!
echo DONE!
+goto out
+
+:out
pause
+title Command Prompt
diff --git a/win/cat.c b/win/cat.c
index 834461e..2cedd5d 100644
--- a/win/cat.c
+++ b/win/cat.c
@@ -10,15 +10,19 @@
*/
#include <stdio.h>
-#include <io.h>
+#ifdef __CYGWIN__
+# include <unistd.h>
+#else
+# include <io.h>
+#endif
#include <string.h>
int
-main()
-{
+main(void)
+{
char buf[1024];
int n;
- char *err;
+ const char *err;
while (1) {
n = read(0, buf, sizeof(buf));
@@ -32,4 +36,3 @@ main()
return 0;
}
-
diff --git a/win/coffbase.txt b/win/coffbase.txt
index 35dac3d..8d3f84b 100644
--- a/win/coffbase.txt
+++ b/win/coffbase.txt
@@ -22,4 +22,12 @@ itk 0x10580000 0x00080000
bltlite 0x10600000 0x00080000
blt 0x10680000 0x00080000
iocpsock 0x10700000 0x00080000
-tls 0x10780000 0x00080000
+tls 0x10780000 0x00100000
+winico 0x10880000 0x00010000
+tile 0x10900000 0x00080000
+memchan 0x109D0000 0x00010000
+tdom 0x109E0000 0x00080000
+tkvideo 0x10B00000 0x00010000
+snack 0x1E000000 0x00400000
+sound 0x1E400000 0x00400000
+snackogg 0x1E800000 0x00200000
diff --git a/win/configure b/win/configure
index 1fe4dde..7ff7248 100755
--- a/win/configure
+++ b/win/configure
@@ -1,38 +1,325 @@
#! /bin/sh
-
# Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.13
-# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+# Generated by GNU Autoconf 2.59.
#
+# Copyright (C) 2003 Free Software Foundation, Inc.
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
-# Defaults:
-ac_help=
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
ac_default_prefix=/usr/local
-# Any additions from configure.in:
-ac_help="$ac_help
- --enable-threads build with threads"
-ac_help="$ac_help
- --enable-shared build and link with shared libraries [--enable-shared]"
-ac_help="$ac_help
- --enable-64bit enable 64bit support (where applicable)"
-ac_help="$ac_help
- --enable-wince enable Win/CE support (where applicable)"
-ac_help="$ac_help
- --with-celib=DIR use Windows/CE support library from DIR"
-ac_help="$ac_help
- --enable-symbols build with debugging symbols [--disable-symbols]"
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete. It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="../generic/tcl.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+# include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP AR ac_ct_AR RANLIB ac_ct_RANLIB RC ac_ct_RC SET_MAKE TCL_THREADS CYGPATH CELIB_DIR DL_LIBS CFLAGS_DEBUG CFLAGS_OPTIMIZE CFLAGS_WARNING CFLAGS_DEFAULT LDFLAGS_DEFAULT VC_MANIFEST_EMBED_DLL VC_MANIFEST_EMBED_EXE TCL_VERSION TCL_MAJOR_VERSION TCL_MINOR_VERSION TCL_PATCH_LEVEL TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC TCL_STUB_LIB_PATH TCL_INCLUDE_SPEC TCL_BUILD_STUB_LIB_SPEC TCL_BUILD_STUB_LIB_PATH TCL_DLL_FILE TCL_SRC_DIR TCL_BIN_DIR TCL_DBGX CFG_TCL_SHARED_LIB_SUFFIX CFG_TCL_UNSHARED_LIB_SUFFIX CFG_TCL_EXPORT_FILE_SUFFIX EXTRA_CFLAGS DEPARG CC_OBJNAME CC_EXENAME LDFLAGS_DEBUG LDFLAGS_OPTIMIZE LDFLAGS_CONSOLE LDFLAGS_WINDOW STLIB_LD SHLIB_LD SHLIB_LD_LIBS SHLIB_CFLAGS SHLIB_SUFFIX TCL_SHARED_BUILD LIBS_GUI DLLSUFFIX LIBPREFIX LIBSUFFIX EXESUFFIX LIBRARIES MAKE_LIB POST_MAKE_LIB MAKE_DLL MAKE_EXE TCL_BUILD_LIB_SPEC TCL_LD_SEARCH_FLAGS TCL_NEEDS_EXP_FILE TCL_BUILD_EXP_FILE TCL_EXP_FILE TCL_LIB_VERSIONS_OK TCL_PACKAGE_PATH TCL_DDE_VERSION TCL_DDE_MAJOR_VERSION TCL_DDE_MINOR_VERSION TCL_DDE_PATCH_LEVEL TCL_REG_VERSION TCL_REG_MAJOR_VERSION TCL_REG_MINOR_VERSION TCL_REG_PATCH_LEVEL RC_OUT RC_TYPE RC_INCLUDE RC_DEFINE RC_DEFINES RES LIBOBJS LTLIBOBJS'
+ac_subst_files=''
# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
# The variables have the same names as the options, with
# dashes changed to underlines.
-build=NONE
-cache_file=./config.cache
+cache_file=/dev/null
exec_prefix=NONE
-host=NONE
no_create=
-nonopt=NONE
no_recursion=
prefix=NONE
program_prefix=NONE
@@ -41,10 +328,15 @@ program_transform_name=s,x,x,
silent=
site=
srcdir=
-target=NONE
verbose=
x_includes=NONE
x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
bindir='${exec_prefix}/bin'
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
@@ -58,17 +350,9 @@ oldincludedir='/usr/include'
infodir='${prefix}/info'
mandir='${prefix}/man'
-# Initialize some other variables.
-subdirs=
-MFLAGS= MAKEFLAGS=
-SHELL=${CONFIG_SHELL-/bin/sh}
-# Maximum number of lines to put in a shell here document.
-ac_max_here_lines=12
-
ac_prev=
for ac_option
do
-
# If the previous option needs an argument, assign it.
if test -n "$ac_prev"; then
eval "$ac_prev=\$ac_option"
@@ -76,59 +360,59 @@ do
continue
fi
- case "$ac_option" in
- -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
- *) ac_optarg= ;;
- esac
+ ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
# Accept the important Cygnus configure options, so we can diagnose typos.
- case "$ac_option" in
+ case $ac_option in
-bindir | --bindir | --bindi | --bind | --bin | --bi)
ac_prev=bindir ;;
-bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
- bindir="$ac_optarg" ;;
+ bindir=$ac_optarg ;;
-build | --build | --buil | --bui | --bu)
- ac_prev=build ;;
+ ac_prev=build_alias ;;
-build=* | --build=* | --buil=* | --bui=* | --bu=*)
- build="$ac_optarg" ;;
+ build_alias=$ac_optarg ;;
-cache-file | --cache-file | --cache-fil | --cache-fi \
| --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
ac_prev=cache_file ;;
-cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
| --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
- cache_file="$ac_optarg" ;;
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
-datadir | --datadir | --datadi | --datad | --data | --dat | --da)
ac_prev=datadir ;;
-datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
| --da=*)
- datadir="$ac_optarg" ;;
+ datadir=$ac_optarg ;;
-disable-* | --disable-*)
- ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
- if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
- { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
- fi
- ac_feature=`echo $ac_feature| sed 's/-/_/g'`
- eval "enable_${ac_feature}=no" ;;
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ eval "enable_$ac_feature=no" ;;
-enable-* | --enable-*)
- ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
- if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
- { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
- fi
- ac_feature=`echo $ac_feature| sed 's/-/_/g'`
- case "$ac_option" in
- *=*) ;;
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
*) ac_optarg=yes ;;
esac
- eval "enable_${ac_feature}='$ac_optarg'" ;;
+ eval "enable_$ac_feature='$ac_optarg'" ;;
-exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
| --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
@@ -137,95 +421,47 @@ do
-exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
| --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
| --exec=* | --exe=* | --ex=*)
- exec_prefix="$ac_optarg" ;;
+ exec_prefix=$ac_optarg ;;
-gas | --gas | --ga | --g)
# Obsolete; use --with-gas.
with_gas=yes ;;
- -help | --help | --hel | --he)
- # Omit some internal or obsolete options to make the list less imposing.
- # This message is too long to be a string in the A/UX 3.1 sh.
- cat << EOF
-Usage: configure [options] [host]
-Options: [defaults in brackets after descriptions]
-Configuration:
- --cache-file=FILE cache test results in FILE
- --help print this message
- --no-create do not create output files
- --quiet, --silent do not print \`checking...' messages
- --version print the version of autoconf that created configure
-Directory and file names:
- --prefix=PREFIX install architecture-independent files in PREFIX
- [$ac_default_prefix]
- --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
- [same as prefix]
- --bindir=DIR user executables in DIR [EPREFIX/bin]
- --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
- --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
- --datadir=DIR read-only architecture-independent data in DIR
- [PREFIX/share]
- --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
- --sharedstatedir=DIR modifiable architecture-independent data in DIR
- [PREFIX/com]
- --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
- --libdir=DIR object code libraries in DIR [EPREFIX/lib]
- --includedir=DIR C header files in DIR [PREFIX/include]
- --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
- --infodir=DIR info documentation in DIR [PREFIX/info]
- --mandir=DIR man documentation in DIR [PREFIX/man]
- --srcdir=DIR find the sources in DIR [configure dir or ..]
- --program-prefix=PREFIX prepend PREFIX to installed program names
- --program-suffix=SUFFIX append SUFFIX to installed program names
- --program-transform-name=PROGRAM
- run sed PROGRAM on installed program names
-EOF
- cat << EOF
-Host type:
- --build=BUILD configure for building on BUILD [BUILD=HOST]
- --host=HOST configure for HOST [guessed]
- --target=TARGET configure for TARGET [TARGET=HOST]
-Features and packages:
- --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
- --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
- --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
- --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
- --x-includes=DIR X include files are in DIR
- --x-libraries=DIR X library files are in DIR
-EOF
- if test -n "$ac_help"; then
- echo "--enable and --with options recognized:$ac_help"
- fi
- exit 0 ;;
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
-host | --host | --hos | --ho)
- ac_prev=host ;;
+ ac_prev=host_alias ;;
-host=* | --host=* | --hos=* | --ho=*)
- host="$ac_optarg" ;;
+ host_alias=$ac_optarg ;;
-includedir | --includedir | --includedi | --included | --include \
| --includ | --inclu | --incl | --inc)
ac_prev=includedir ;;
-includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
| --includ=* | --inclu=* | --incl=* | --inc=*)
- includedir="$ac_optarg" ;;
+ includedir=$ac_optarg ;;
-infodir | --infodir | --infodi | --infod | --info | --inf)
ac_prev=infodir ;;
-infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
- infodir="$ac_optarg" ;;
+ infodir=$ac_optarg ;;
-libdir | --libdir | --libdi | --libd)
ac_prev=libdir ;;
-libdir=* | --libdir=* | --libdi=* | --libd=*)
- libdir="$ac_optarg" ;;
+ libdir=$ac_optarg ;;
-libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
| --libexe | --libex | --libe)
ac_prev=libexecdir ;;
-libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
| --libexe=* | --libex=* | --libe=*)
- libexecdir="$ac_optarg" ;;
+ libexecdir=$ac_optarg ;;
-localstatedir | --localstatedir | --localstatedi | --localstated \
| --localstate | --localstat | --localsta | --localst \
@@ -234,19 +470,19 @@ EOF
-localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
| --localstate=* | --localstat=* | --localsta=* | --localst=* \
| --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
- localstatedir="$ac_optarg" ;;
+ localstatedir=$ac_optarg ;;
-mandir | --mandir | --mandi | --mand | --man | --ma | --m)
ac_prev=mandir ;;
-mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
- mandir="$ac_optarg" ;;
+ mandir=$ac_optarg ;;
-nfp | --nfp | --nf)
# Obsolete; use --without-fp.
with_fp=no ;;
-no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c)
+ | --no-cr | --no-c | -n)
no_create=yes ;;
-no-recursion | --no-recursion | --no-recursio | --no-recursi \
@@ -260,26 +496,26 @@ EOF
-oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
| --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
| --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
- oldincludedir="$ac_optarg" ;;
+ oldincludedir=$ac_optarg ;;
-prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
ac_prev=prefix ;;
-prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
- prefix="$ac_optarg" ;;
+ prefix=$ac_optarg ;;
-program-prefix | --program-prefix | --program-prefi | --program-pref \
| --program-pre | --program-pr | --program-p)
ac_prev=program_prefix ;;
-program-prefix=* | --program-prefix=* | --program-prefi=* \
| --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
- program_prefix="$ac_optarg" ;;
+ program_prefix=$ac_optarg ;;
-program-suffix | --program-suffix | --program-suffi | --program-suff \
| --program-suf | --program-su | --program-s)
ac_prev=program_suffix ;;
-program-suffix=* | --program-suffix=* | --program-suffi=* \
| --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
- program_suffix="$ac_optarg" ;;
+ program_suffix=$ac_optarg ;;
-program-transform-name | --program-transform-name \
| --program-transform-nam | --program-transform-na \
@@ -296,7 +532,7 @@ EOF
| --program-transfo=* | --program-transf=* \
| --program-trans=* | --program-tran=* \
| --progr-tra=* | --program-tr=* | --program-t=*)
- program_transform_name="$ac_optarg" ;;
+ program_transform_name=$ac_optarg ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil)
@@ -306,7 +542,7 @@ EOF
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
| --sbi=* | --sb=*)
- sbindir="$ac_optarg" ;;
+ sbindir=$ac_optarg ;;
-sharedstatedir | --sharedstatedir | --sharedstatedi \
| --sharedstated | --sharedstate | --sharedstat | --sharedsta \
@@ -317,58 +553,57 @@ EOF
| --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
| --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
| --sha=* | --sh=*)
- sharedstatedir="$ac_optarg" ;;
+ sharedstatedir=$ac_optarg ;;
-site | --site | --sit)
ac_prev=site ;;
-site=* | --site=* | --sit=*)
- site="$ac_optarg" ;;
+ site=$ac_optarg ;;
-srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
ac_prev=srcdir ;;
-srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
- srcdir="$ac_optarg" ;;
+ srcdir=$ac_optarg ;;
-sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
| --syscon | --sysco | --sysc | --sys | --sy)
ac_prev=sysconfdir ;;
-sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
| --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
- sysconfdir="$ac_optarg" ;;
+ sysconfdir=$ac_optarg ;;
-target | --target | --targe | --targ | --tar | --ta | --t)
- ac_prev=target ;;
+ ac_prev=target_alias ;;
-target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
- target="$ac_optarg" ;;
+ target_alias=$ac_optarg ;;
-v | -verbose | --verbose | --verbos | --verbo | --verb)
verbose=yes ;;
- -version | --version | --versio | --versi | --vers)
- echo "configure generated by autoconf version 2.13"
- exit 0 ;;
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
-with-* | --with-*)
- ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
- if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
- { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
- fi
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
ac_package=`echo $ac_package| sed 's/-/_/g'`
- case "$ac_option" in
- *=*) ;;
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
*) ac_optarg=yes ;;
esac
- eval "with_${ac_package}='$ac_optarg'" ;;
+ eval "with_$ac_package='$ac_optarg'" ;;
-without-* | --without-*)
- ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
- if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
- { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
- fi
- ac_package=`echo $ac_package| sed 's/-/_/g'`
- eval "with_${ac_package}=no" ;;
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/-/_/g'`
+ eval "with_$ac_package=no" ;;
--x)
# Obsolete; use --with-x.
@@ -379,99 +614,110 @@ EOF
ac_prev=x_includes ;;
-x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
| --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
- x_includes="$ac_optarg" ;;
+ x_includes=$ac_optarg ;;
-x-libraries | --x-libraries | --x-librarie | --x-librari \
| --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
ac_prev=x_libraries ;;
-x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
| --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
- x_libraries="$ac_optarg" ;;
+ x_libraries=$ac_optarg ;;
- -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
;;
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+ eval "$ac_envvar='$ac_optarg'"
+ export $ac_envvar ;;
+
*)
- if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
- echo "configure: warning: $ac_option: invalid host type" 1>&2
- fi
- if test "x$nonopt" != xNONE; then
- { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
- fi
- nonopt="$ac_option"
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
;;
esac
done
if test -n "$ac_prev"; then
- { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
-fi
-
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
-
-# File descriptor usage:
-# 0 standard input
-# 1 file creation
-# 2 errors and warnings
-# 3 some systems may open it to /dev/tty
-# 4 used on the Kubota Titan
-# 6 checking for... messages and results
-# 5 compiler messages saved in config.log
-if test "$silent" = yes; then
- exec 6>/dev/null
-else
- exec 6>&1
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
fi
-exec 5>./config.log
-echo "\
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-" 1>&5
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
-# Strip out --no-create and --no-recursion so they do not pile up.
-# Also quote any args containing shell metacharacters.
-ac_configure_args=
-for ac_arg
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+ localstatedir libdir includedir oldincludedir infodir mandir
do
- case "$ac_arg" in
- -no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c) ;;
- -no-recursion | --no-recursion | --no-recursio | --no-recursi \
- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
- *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
- ac_configure_args="$ac_configure_args '$ac_arg'" ;;
- *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
esac
done
-# NLS nuisances.
-# Only set these to C if already set. These must not be set unconditionally
-# because not all systems understand e.g. LANG=C (notably SCO).
-# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
-# Non-C LC_CTYPE values break the ctype check.
-if test "${LANG+set}" = set; then LANG=C; export LANG; fi
-if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
-if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
-if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
-# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -rf conftest* confdefs.h
-# AIX cpp loses on an empty file, so make sure it contains at least a newline.
-echo > confdefs.h
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
-# A filename unique to this package, relative to the directory that
-# configure is in, which we can look for to find out if srcdir is correct.
-ac_unique_file=../generic/tcl.h
# Find the source files, if location was not specified.
if test -z "$srcdir"; then
ac_srcdir_defaulted=yes
# Try the directory containing this script, then its parent.
- ac_prog=$0
- ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
- test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
srcdir=$ac_confdir
if test ! -r $srcdir/$ac_unique_file; then
srcdir=..
@@ -481,13 +727,471 @@ else
fi
if test ! -r $srcdir/$ac_unique_file; then
if test "$ac_srcdir_defaulted" = yes; then
- { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+ { (exit 1); exit 1; }; }
else
- { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
fi
fi
-srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+ { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+ { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+ cat <<_ACEOF
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --infodir=DIR info documentation [PREFIX/info]
+ --mandir=DIR man documentation [PREFIX/man]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-threads build with threads
+ --enable-shared build and link with shared libraries --enable-shared
+ --enable-64bit enable 64bit support (where applicable)
+ --enable-wince enable Win/CE support (where applicable)
+ --enable-symbols build with debugging symbols --disable-symbols
+ --enable-embedded-manifest
+ embed manifest if possible (default: yes)
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-encoding encoding for configuration values
+ --with-celib=DIR use Windows/CE support library from DIR
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
+ headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ ac_popdir=`pwd`
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d $ac_dir || continue
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+ cd $ac_dir
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f $ac_srcdir/configure.gnu; then
+ echo
+ $SHELL $ac_srcdir/configure.gnu --help=recursive
+ elif test -f $ac_srcdir/configure; then
+ echo
+ $SHELL $ac_srcdir/configure --help=recursive
+ elif test -f $ac_srcdir/configure.ac ||
+ test -f $ac_srcdir/configure.in; then
+ echo
+ $ac_configure --help
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi
+ cd $ac_popdir
+ done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+ cat <<\_ACEOF
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo = `(hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+ # Get rid of the leading space.
+ ac_sep=" "
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+{
+ (set) 2>&1 |
+ case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ sed -n \
+ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+ ;;
+ *)
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+}
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ sed "/^$/d" confdefs.h | sort
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core &&
+ rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+ ' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
# Prefer explicitly selected file to automatically selected ones.
if test -z "$CONFIG_SITE"; then
if test "x$prefix" != xNONE; then
@@ -498,57 +1202,128 @@ if test -z "$CONFIG_SITE"; then
fi
for ac_site_file in $CONFIG_SITE; do
if test -r "$ac_site_file"; then
- echo "loading site script $ac_site_file"
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file"
fi
done
if test -r "$cache_file"; then
- echo "loading cache $cache_file"
- . $cache_file
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . $cache_file;;
+ *) . ./$cache_file;;
+ esac
+ fi
else
- echo "creating cache $cache_file"
- > $cache_file
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
fi
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-ac_exeext=
-ac_objext=o
-if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
- # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
- if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
- ac_n= ac_c='
-' ac_t=' '
- else
- ac_n=-n ac_c= ac_t=
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+ sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+ eval ac_new_val="\$ac_env_${ac_var}_value"
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
fi
-else
- ac_n= ac_c='\c' ac_t=
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
-TCL_VERSION=8.4
+
+
+
+
+
+
+
+
+
+# The following define is needed when building with Cygwin since newer
+# versions of autoconf incorrectly set SHELL to /bin/bash instead of
+# /bin/sh. The bash shell seems to suffer from some strange failures.
+SHELL=/bin/sh
+
+TCL_VERSION=8.5
TCL_MAJOR_VERSION=8
-TCL_MINOR_VERSION=4
-TCL_PATCH_LEVEL=".19"
+TCL_MINOR_VERSION=5
+TCL_PATCH_LEVEL=".10"
VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION
-TCL_DDE_VERSION=1.2
+TCL_DDE_VERSION=1.3
TCL_DDE_MAJOR_VERSION=1
-TCL_DDE_MINOR_VERSION=2
+TCL_DDE_MINOR_VERSION=3
+TCL_DDE_PATCH_LEVEL="2"
DDEVER=$TCL_DDE_MAJOR_VERSION$TCL_DDE_MINOR_VERSION
-TCL_REG_VERSION=1.1
+TCL_REG_VERSION=1.2
TCL_REG_MAJOR_VERSION=1
-TCL_REG_MINOR_VERSION=1
+TCL_REG_MINOR_VERSION=2
+TCL_REG_PATCH_LEVEL="1"
REGVER=$TCL_REG_MAJOR_VERSION$TCL_REG_MINOR_VERSION
#------------------------------------------------------------------------
@@ -574,214 +1349,659 @@ if test "${CFLAGS+set}" != "set" ; then
CFLAGS=""
fi
-# Extract the first word of "gcc", so it can be a program name with args.
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:581: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ CC=$ac_ct_CC
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_CC="gcc"
- break
- fi
- done
- IFS="$ac_save_ifs"
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
fi
fi
-CC="$ac_cv_prog_CC"
+CC=$ac_cv_prog_CC
if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
fi
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ CC=$ac_ct_CC
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:611: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
ac_prog_rejected=no
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
- ac_prog_rejected=yes
- continue
- fi
- ac_cv_prog_CC="cc"
- break
- fi
- done
- IFS="$ac_save_ifs"
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
if test $ac_prog_rejected = yes; then
# We found a bogon in the path, so make sure we never use it.
set dummy $ac_cv_prog_CC
shift
- if test $# -gt 0; then
+ if test $# != 0; then
# We chose a different compiler from the bogus one.
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
- set dummy "$ac_dir/$ac_word" "$@"
- shift
- ac_cv_prog_CC="$@"
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
fi
fi
fi
fi
-CC="$ac_cv_prog_CC"
+CC=$ac_cv_prog_CC
if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
fi
- if test -z "$CC"; then
- case "`uname -s`" in
- *win32* | *WIN32*)
- # Extract the first word of "cl", so it can be a program name with args.
-set dummy cl; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:662: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_CC="cl"
- break
- fi
- done
- IFS="$ac_save_ifs"
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
fi
fi
-CC="$ac_cv_prog_CC"
+CC=$ac_cv_prog_CC
if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
fi
- ;;
- esac
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
fi
- test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
fi
-echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:694: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+ test -n "$ac_ct_CC" && break
+done
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-cat > conftest.$ac_ext << EOF
-
-#line 705 "configure"
-#include "confdefs.h"
-
-main(){return(0);}
-EOF
-if { (eval echo configure:710: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- ac_cv_prog_cc_works=yes
- # If we can't run a trivial program, we are probably using a cross compiler.
- if (./conftest; exit) 2>/dev/null; then
- ac_cv_prog_cc_cross=no
+ CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+ "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+ (eval $ac_compiler --version </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+ (eval $ac_compiler -v </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+ (eval $ac_compiler -V </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+ (eval $ac_link_default) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Find the output, starting from the most likely. This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+ ;;
+ conftest.$ac_ext )
+ # This is the source file.
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ # FIXME: I believe we export ac_cv_exeext for Libtool,
+ # but it would be cool to find out if it's true. Does anybody
+ # maintain Libtool? --akim.
+ export ac_cv_exeext
+ break;;
+ * )
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
else
- ac_cv_prog_cc_cross=yes
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
fi
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- ac_cv_prog_cc_works=no
fi
-rm -fr conftest*
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
-if test $ac_cv_prog_cc_works = no; then
- { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
-fi
-echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:736: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
-echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
-cross_compiling=$ac_cv_prog_cc_cross
-
-echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:741: checking whether we are using GNU C" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.c <<EOF
-#ifdef __GNUC__
- yes;
-#endif
-EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:750: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
- ac_cv_prog_gcc=yes
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ export ac_cv_exeext
+ break;;
+ * ) break;;
+ esac
+done
else
- ac_cv_prog_gcc=no
-fi
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
fi
-echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
-if test $ac_cv_prog_gcc = yes; then
- GCC=yes
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
else
- GCC=
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
fi
-ac_test_CFLAGS="${CFLAGS+set}"
-ac_save_CFLAGS="$CFLAGS"
-CFLAGS=
-echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:769: checking whether ${CC-cc} accepts -g" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- echo 'void f(){}' > conftest.c
-if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
- ac_cv_prog_cc_g=yes
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
else
- ac_cv_prog_cc_g=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
-echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
if test "$ac_test_CFLAGS" = set; then
- CFLAGS="$ac_save_CFLAGS"
+ CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
if test "$GCC" = yes; then
CFLAGS="-g -O2"
@@ -795,143 +2015,1027 @@ else
CFLAGS=
fi
fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std1 is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std1. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX 10.20 and later -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
-# To properly support cross-compilation, one would
-# need to use these tool checks instead of
-# the ones below and reconfigure with
-# autoconf 2.50. You can also just set
-# the CC, AR, RANLIB, and RC environment
-# variables if you want to cross compile.
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
-if test "${GCC}" = "yes" ; then
- # Extract the first word of "ar", so it can be a program name with args.
-set dummy ar; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:812: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+ x|xno)
+ echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+ *)
+ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+ CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C. Since we use `exit',
+# in C++ we need to declare it. In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+ choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ for ac_declaration in \
+ '' \
+ 'extern "C" void std::exit (int) throw (); using std::exit;' \
+ 'extern "C" void std::exit (int); using std::exit;' \
+ 'extern "C" void exit (int) throw ();' \
+ 'extern "C" void exit (int);' \
+ 'void exit (int);'
+do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+ echo '#ifdef __cplusplus' >>confdefs.h
+ echo $ac_declaration >>confdefs.h
+ echo '#endif' >>confdefs.h
+fi
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for inline" >&5
+echo $ECHO_N "checking for inline... $ECHO_C" >&6
+if test "${ac_cv_c_inline+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_inline=$ac_kw; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5
+echo "${ECHO_T}$ac_cv_c_inline" >&6
+
+
+case $ac_cv_c_inline in
+ inline | yes) ;;
+ *)
+ case $ac_cv_c_inline in
+ no) ac_val=;;
+ *) ac_val=$ac_cv_c_inline;;
+ esac
+ cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+ ;;
+esac
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test "${ac_cv_prog_CPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+ then ac_cv_prog_egrep='grep -E'
+ else ac_cv_prog_egrep='egrep'
+ fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ exit(2);
+ exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_AR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test -n "$AR"; then
ac_cv_prog_AR="$AR" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_AR="ar"
- break
- fi
- done
- IFS="$ac_save_ifs"
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
fi
fi
-AR="$ac_cv_prog_AR"
+AR=$ac_cv_prog_AR
if test -n "$AR"; then
- echo "$ac_t""$AR" 1>&6
+ echo "$as_me:$LINENO: result: $AR" >&5
+echo "${ECHO_T}$AR" >&6
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
fi
- # Extract the first word of "ranlib", so it can be a program name with args.
-set dummy ranlib; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:841: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="ar"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ echo "$as_me:$LINENO: result: $ac_ct_AR" >&5
+echo "${ECHO_T}$ac_ct_AR" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ AR=$ac_ct_AR
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test -n "$RANLIB"; then
ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_RANLIB="ranlib"
- break
- fi
- done
- IFS="$ac_save_ifs"
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
fi
fi
-RANLIB="$ac_cv_prog_RANLIB"
+RANLIB=$ac_cv_prog_RANLIB
if test -n "$RANLIB"; then
- echo "$ac_t""$RANLIB" 1>&6
+ echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
fi
- # Extract the first word of "windres", so it can be a program name with args.
-set dummy windres; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:870: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_RC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ RANLIB=$ac_ct_RANLIB
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args.
+set dummy ${ac_tool_prefix}windres; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_RC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test -n "$RC"; then
ac_cv_prog_RC="$RC" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_RC="windres"
- break
- fi
- done
- IFS="$ac_save_ifs"
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RC="${ac_tool_prefix}windres"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
fi
fi
-RC="$ac_cv_prog_RC"
+RC=$ac_cv_prog_RC
if test -n "$RC"; then
- echo "$ac_t""$RC" 1>&6
+ echo "$as_me:$LINENO: result: $RC" >&5
+echo "${ECHO_T}$RC" >&6
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
fi
+if test -z "$ac_cv_prog_RC"; then
+ ac_ct_RC=$RC
+ # Extract the first word of "windres", so it can be a program name with args.
+set dummy windres; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_RC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_RC"; then
+ ac_cv_prog_ac_ct_RC="$ac_ct_RC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RC="windres"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+fi
+fi
+ac_ct_RC=$ac_cv_prog_ac_ct_RC
+if test -n "$ac_ct_RC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_RC" >&5
+echo "${ECHO_T}$ac_ct_RC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
- if test "${AR}" = "" ; then
- { echo "configure: error: Required archive tool 'ar' not found on PATH." 1>&2; exit 1; }
- fi
- if test "${RANLIB}" = "" ; then
- { echo "configure: error: Required archive index tool 'ranlib' not found on PATH." 1>&2; exit 1; }
- fi
- if test "${RC}" = "" ; then
- { echo "configure: error: Required resource tool 'windres' not found on PATH." 1>&2; exit 1; }
- fi
+ RC=$ac_ct_RC
+else
+ RC="$ac_cv_prog_RC"
fi
+
#--------------------------------------------------------------------
# Checks to see if the make program sets the $MAKE variable.
#--------------------------------------------------------------------
-echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:913: checking whether ${MAKE-make} sets \${MAKE}" >&5
-set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'`
+if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftestmake <<\EOF
+ cat >conftest.make <<\_ACEOF
all:
- @echo 'ac_maketemp="${MAKE}"'
-EOF
+ @echo 'ac_maketemp="$(MAKE)"'
+_ACEOF
# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
-eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
if test -n "$ac_maketemp"; then
eval ac_cv_prog_make_${ac_make}_set=yes
else
eval ac_cv_prog_make_${ac_make}_set=no
fi
-rm -f conftestmake
+rm -f conftest.make
fi
if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
SET_MAKE=
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
SET_MAKE="MAKE=${MAKE-make}"
fi
@@ -940,58 +3044,90 @@ fi
# Perform additinal compiler tests.
#--------------------------------------------------------------------
-echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
-echo "configure:945: checking for Cygwin environment" >&5
-if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+
+echo "$as_me:$LINENO: checking for Cygwin version of gcc" >&5
+echo $ECHO_N "checking for Cygwin version of gcc... $ECHO_C" >&6
+if test "${ac_cv_cygwin+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 950 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#ifdef __CYGWIN__
+#error cygwin
+#endif
-int main() {
+int
+main ()
+{
-#ifndef __CYGWIN__
-#define __CYGWIN__ __CYGWIN32__
-#endif
-return __CYGWIN__;
-; return 0; }
-EOF
-if { (eval echo configure:961: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- ac_cv_cygwin=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
ac_cv_cygwin=no
-fi
-rm -f conftest*
-rm -f conftest*
-fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
-echo "$ac_t""$ac_cv_cygwin" 1>&6
-CYGWIN=
-test "$ac_cv_cygwin" = yes && CYGWIN=yes
+ac_cv_cygwin=yes
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_cygwin" >&5
+echo "${ECHO_T}$ac_cv_cygwin" >&6
if test "$ac_cv_cygwin" = "yes" ; then
- { echo "configure: error: Compiling under Cygwin is not currently supported.
+ { { echo "$as_me:$LINENO: error: Compiling under Cygwin is not currently supported.
A maintainer for the Cygwin port of Tcl/Tk is needed. See the README
-file for information about building with Mingw." 1>&2; exit 1; }
+file for information about building with Mingw." >&5
+echo "$as_me: error: Compiling under Cygwin is not currently supported.
+A maintainer for the Cygwin port of Tcl/Tk is needed. See the README
+file for information about building with Mingw." >&2;}
+ { (exit 1); exit 1; }; }
fi
-echo $ac_n "checking for SEH support in compiler""... $ac_c" 1>&6
-echo "configure:986: checking for SEH support in compiler" >&5
-if eval "test \"`echo '$''{'tcl_cv_seh'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for SEH support in compiler" >&5
+echo $ECHO_N "checking for SEH support in compiler... $ECHO_C" >&6
+if test "${tcl_cv_seh+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test "$cross_compiling" = yes; then
tcl_cv_seh=no
else
- cat > conftest.$ac_ext <<EOF
-#line 994 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@@ -1008,27 +3144,38 @@ int main(int argc, char** argv) {
return 1;
}
-EOF
-if { (eval echo configure:1013: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_seh=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- tcl_cv_seh=no
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+tcl_cv_seh=no
fi
-rm -fr conftest*
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
-
fi
-
-echo "$ac_t""$tcl_cv_seh" 1>&6
+echo "$as_me:$LINENO: result: $tcl_cv_seh" >&5
+echo "${ECHO_T}$tcl_cv_seh" >&6
if test "$tcl_cv_seh" = "no" ; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_NO_SEH 1
-EOF
+_ACEOF
fi
@@ -1038,43 +3185,71 @@ fi
# with Cygwin's version as of 2002-04-10, define it to be int,
# sufficient for getting the current code to work.
#
-echo $ac_n "checking for EXCEPTION_DISPOSITION support in include files""... $ac_c" 1>&6
-echo "configure:1043: checking for EXCEPTION_DISPOSITION support in include files" >&5
-if eval "test \"`echo '$''{'tcl_cv_eh_disposition'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for EXCEPTION_DISPOSITION support in include files" >&5
+echo $ECHO_N "checking for EXCEPTION_DISPOSITION support in include files... $ECHO_C" >&6
+if test "${tcl_cv_eh_disposition+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 1048 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
-int main() {
+int
+main ()
+{
EXCEPTION_DISPOSITION x;
-; return 0; }
-EOF
-if { (eval echo configure:1061: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_eh_disposition=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_eh_disposition=no
-fi
-rm -f conftest*
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+tcl_cv_eh_disposition=no
fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$ac_t""$tcl_cv_eh_disposition" 1>&6
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_eh_disposition" >&5
+echo "${ECHO_T}$tcl_cv_eh_disposition" >&6
if test "$tcl_cv_eh_disposition" = "no" ; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define EXCEPTION_DISPOSITION int
-EOF
+_ACEOF
fi
@@ -1082,44 +3257,72 @@ fi
# Check to see if the winsock2.h include file provided contains
# typedefs like LPFN_ACCEPT and friends.
#
-echo $ac_n "checking for LPFN_ACCEPT support in winsock2.h""... $ac_c" 1>&6
-echo "configure:1087: checking for LPFN_ACCEPT support in winsock2.h" >&5
-if eval "test \"`echo '$''{'tcl_cv_lpfn_decls'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for LPFN_ACCEPT support in winsock2.h" >&5
+echo $ECHO_N "checking for LPFN_ACCEPT support in winsock2.h... $ECHO_C" >&6
+if test "${tcl_cv_lpfn_decls+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 1092 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#include <winsock2.h>
-int main() {
+int
+main ()
+{
LPFN_ACCEPT accept;
-; return 0; }
-EOF
-if { (eval echo configure:1106: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_lpfn_decls=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_lpfn_decls=no
-fi
-rm -f conftest*
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+tcl_cv_lpfn_decls=no
fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$ac_t""$tcl_cv_lpfn_decls" 1>&6
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_lpfn_decls" >&5
+echo "${ECHO_T}$tcl_cv_lpfn_decls" >&6
if test "$tcl_cv_lpfn_decls" = "no" ; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_NO_LPFN_DECLS 1
-EOF
+_ACEOF
fi
@@ -1127,46 +3330,74 @@ fi
# even if VOID has already been #defined. The win32api
# used by mingw and cygwin is known to do this.
-echo $ac_n "checking for winnt.h that ignores VOID define""... $ac_c" 1>&6
-echo "configure:1132: checking for winnt.h that ignores VOID define" >&5
-if eval "test \"`echo '$''{'tcl_cv_winnt_ignore_void'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for winnt.h that ignores VOID define" >&5
+echo $ECHO_N "checking for winnt.h that ignores VOID define... $ECHO_C" >&6
+if test "${tcl_cv_winnt_ignore_void+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 1137 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#define VOID void
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
-int main() {
+int
+main ()
+{
CHAR c;
SHORT s;
LONG l;
-; return 0; }
-EOF
-if { (eval echo configure:1153: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_winnt_ignore_void=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_winnt_ignore_void=no
-fi
-rm -f conftest*
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+tcl_cv_winnt_ignore_void=no
fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$ac_t""$tcl_cv_winnt_ignore_void" 1>&6
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_winnt_ignore_void" >&5
+echo "${ECHO_T}$tcl_cv_winnt_ignore_void" >&6
if test "$tcl_cv_winnt_ignore_void" = "yes" ; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_WINNT_IGNORE_VOID 1
-EOF
+_ACEOF
fi
@@ -1180,45 +3411,73 @@ fi
# register and not on the stack. Instead, we just
# call it from inline asm code.
-echo $ac_n "checking for alloca declaration in malloc.h""... $ac_c" 1>&6
-echo "configure:1185: checking for alloca declaration in malloc.h" >&5
-if eval "test \"`echo '$''{'tcl_cv_malloc_decl_alloca'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for alloca declaration in malloc.h" >&5
+echo $ECHO_N "checking for alloca declaration in malloc.h... $ECHO_C" >&6
+if test "${tcl_cv_malloc_decl_alloca+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 1190 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <malloc.h>
-int main() {
+int
+main ()
+{
size_t arg = 0;
void* ptr;
ptr = alloca;
ptr = alloca(arg);
-; return 0; }
-EOF
-if { (eval echo configure:1204: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_malloc_decl_alloca=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_malloc_decl_alloca=no
-fi
-rm -f conftest*
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+tcl_cv_malloc_decl_alloca=no
fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$ac_t""$tcl_cv_malloc_decl_alloca" 1>&6
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_malloc_decl_alloca" >&5
+echo "${ECHO_T}$tcl_cv_malloc_decl_alloca" >&6
if test "$tcl_cv_malloc_decl_alloca" = "no" &&
test "${GCC}" = "yes" ; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_ALLOCA_GCC_INLINE 1
-EOF
+_ACEOF
fi
@@ -1226,174 +3485,290 @@ fi
# This is used to stop gcc from printing a compiler
# warning when initializing a union member.
-echo $ac_n "checking for cast to union support""... $ac_c" 1>&6
-echo "configure:1231: checking for cast to union support" >&5
-if eval "test \"`echo '$''{'tcl_cv_cast_to_union'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for cast to union support" >&5
+echo $ECHO_N "checking for cast to union support... $ECHO_C" >&6
+if test "${tcl_cv_cast_to_union+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 1236 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
-int main() {
+int
+main ()
+{
union foo { int i; double d; };
union foo f = (union foo) (int) 0;
-; return 0; }
-EOF
-if { (eval echo configure:1246: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_cv_cast_to_union=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_cv_cast_to_union=no
-fi
-rm -f conftest*
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+tcl_cv_cast_to_union=no
fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$ac_t""$tcl_cv_cast_to_union" 1>&6
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_cast_to_union" >&5
+echo "${ECHO_T}$tcl_cv_cast_to_union" >&6
if test "$tcl_cv_cast_to_union" = "yes"; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_CAST_TO_UNION 1
-EOF
+_ACEOF
fi
# Check to see if struct _stat32i64 exists in mingw's sys/stat.h
-echo $ac_n "checking if struct _stat32i64 missing""... $ac_c" 1>&6
-echo "configure:1270: checking if struct _stat32i64 missing" >&5
-if eval "test \"`echo '$''{'tcl_struct_stat32i64'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking if struct _stat32i64 missing" >&5
+echo $ECHO_N "checking if struct _stat32i64 missing... $ECHO_C" >&6
+if test "${tcl_struct_stat32i64+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 1275 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#include <sys/types.h>
#include <sys/stat.h>
-int main() {
+int
+main ()
+{
struct _stat32i64 foo;
-; return 0; }
-EOF
-if { (eval echo configure:1287: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_struct_stat32i64=no
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_struct_stat32i64=yes
-fi
-rm -f conftest*
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+tcl_struct_stat32i64=yes
fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$ac_t""$tcl_struct_stat32i64" 1>&6
+fi
+echo "$as_me:$LINENO: result: $tcl_struct_stat32i64" >&5
+echo "${ECHO_T}$tcl_struct_stat32i64" >&6
if test "$tcl_struct_stat32i64" = "yes" ; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\_ACEOF
#define HAVE_NO_STRUCT_STAT32I64 1
-EOF
+_ACEOF
fi
-#--------------------------------------------------------------------
-# Determines the correct binary file extension (.o, .obj, .exe etc.)
-#--------------------------------------------------------------------
+# See if declarations like FINDEX_INFO_LEVELS are
+# missing from winbase.h. This is known to be
+# a problem with VC++ 5.2.
-echo $ac_n "checking for object suffix""... $ac_c" 1>&6
-echo "configure:1314: checking for object suffix" >&5
-if eval "test \"`echo '$''{'ac_cv_objext'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- rm -f conftest*
-echo 'int i = 1;' > conftest.$ac_ext
-if { (eval echo configure:1320: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- for ac_file in conftest.*; do
- case $ac_file in
- *.c) ;;
- *) ac_cv_objext=`echo $ac_file | sed -e s/conftest.//` ;;
- esac
- done
+echo "$as_me:$LINENO: checking for FINDEX_INFO_LEVELS in winbase.h" >&5
+echo $ECHO_N "checking for FINDEX_INFO_LEVELS in winbase.h... $ECHO_C" >&6
+if test "${tcl_cv_findex_enums+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- { echo "configure: error: installation or configuration problem; compiler does not work" 1>&2; exit 1; }
-fi
-rm -f conftest*
-fi
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
-echo "$ac_t""$ac_cv_objext" 1>&6
-OBJEXT=$ac_cv_objext
-ac_objext=$ac_cv_objext
-
-echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6
-echo "configure:1338: checking for mingw32 environment" >&5
-if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1343 "configure"
-#include "confdefs.h"
-
-int main() {
-return __MINGW32__;
-; return 0; }
-EOF
-if { (eval echo configure:1350: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- ac_cv_mingw32=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_mingw32=no
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+int
+main ()
+{
+
+ FINDEX_INFO_LEVELS i;
+ FINDEX_SEARCH_OPS j;
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ tcl_cv_findex_enums=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_findex_enums=no
fi
-rm -f conftest*
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
fi
+echo "$as_me:$LINENO: result: $tcl_cv_findex_enums" >&5
+echo "${ECHO_T}$tcl_cv_findex_enums" >&6
+if test "$tcl_cv_findex_enums" = "no"; then
-echo "$ac_t""$ac_cv_mingw32" 1>&6
-MINGW32=
-test "$ac_cv_mingw32" = yes && MINGW32=yes
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_NO_FINDEX_ENUMS 1
+_ACEOF
+
+fi
+# See if MWMO_ALERTABLE is missing from winuser.h
+# This is known to be a problem with Mingw.
-echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
-echo "configure:1369: checking for executable suffix" >&5
-if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for MWMO_ALERTABLE in winuser.h" >&5
+echo $ECHO_N "checking for MWMO_ALERTABLE in winuser.h... $ECHO_C" >&6
+if test "${tcl_cv_mwmo_alertable+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- if test "$CYGWIN" = yes || test "$MINGW32" = yes; then
- ac_cv_exeext=.exe
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+int
+main ()
+{
+
+ int i = MWMO_ALERTABLE;
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ tcl_cv_mwmo_alertable=yes
else
- rm -f conftest*
- echo 'int main () { return 0; }' > conftest.$ac_ext
- ac_cv_exeext=
- if { (eval echo configure:1379: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
- for file in conftest.*; do
- case $file in
- *.c | *.o | *.obj) ;;
- *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;;
- esac
- done
- else
- { echo "configure: error: installation or configuration problem: compiler cannot create executables." 1>&2; exit 1; }
- fi
- rm -f conftest*
- test x"${ac_cv_exeext}" = x && ac_cv_exeext=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_mwmo_alertable=no
fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
fi
+echo "$as_me:$LINENO: result: $tcl_cv_mwmo_alertable" >&5
+echo "${ECHO_T}$tcl_cv_mwmo_alertable" >&6
+if test "$tcl_cv_mwmo_alertable" = "no"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_NO_MWMO_ALERTABLE 1
+_ACEOF
+
+fi
+
+#--------------------------------------------------------------------
+# Determines the correct binary file extension (.o, .obj, .exe etc.)
+#--------------------------------------------------------------------
+
-EXEEXT=""
-test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext}
-echo "$ac_t""${ac_cv_exeext}" 1>&6
-ac_exeext=$EXEEXT
#--------------------------------------------------------------------
@@ -1401,35 +3776,62 @@ ac_exeext=$EXEEXT
#--------------------------------------------------------------------
- echo $ac_n "checking for building with threads""... $ac_c" 1>&6
-echo "configure:1406: checking for building with threads" >&5
+ echo "$as_me:$LINENO: checking for building with threads" >&5
+echo $ECHO_N "checking for building with threads... $ECHO_C" >&6
# Check whether --enable-threads or --disable-threads was given.
if test "${enable_threads+set}" = set; then
enableval="$enable_threads"
tcl_ok=$enableval
else
tcl_ok=no
-fi
-
+fi;
if test "$tcl_ok" = "yes"; then
- echo "$ac_t""yes" 1>&6
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
TCL_THREADS=1
- cat >> confdefs.h <<\EOF
+ cat >>confdefs.h <<\_ACEOF
#define TCL_THREADS 1
-EOF
+_ACEOF
# USE_THREAD_ALLOC tells us to try the special thread-based
# allocator that significantly reduces lock contention
- cat >> confdefs.h <<\EOF
+ cat >>confdefs.h <<\_ACEOF
#define USE_THREAD_ALLOC 1
-EOF
+_ACEOF
else
TCL_THREADS=0
- echo "$ac_t""no (default)" 1>&6
+ echo "$as_me:$LINENO: result: no (default)" >&5
+echo "${ECHO_T}no (default)" >&6
+ fi
+
+
+
+#------------------------------------------------------------------------
+# Embedded configuration information, encoding to use for the values, TIP #59
+#------------------------------------------------------------------------
+
+
+
+# Check whether --with-encoding or --without-encoding was given.
+if test "${with_encoding+set}" = set; then
+ withval="$with_encoding"
+ with_tcencoding=${withval}
+fi;
+
+ if test x"${with_tcencoding}" != x ; then
+ cat >>confdefs.h <<_ACEOF
+#define TCL_CFGVAL_ENCODING "${with_tcencoding}"
+_ACEOF
+
+ else
+ # Default encoding on windows is not "iso8859-1"
+ cat >>confdefs.h <<\_ACEOF
+#define TCL_CFGVAL_ENCODING "cp1252"
+_ACEOF
+
fi
-
#--------------------------------------------------------------------
@@ -1438,16 +3840,15 @@ EOF
#--------------------------------------------------------------------
- echo $ac_n "checking how to build libraries""... $ac_c" 1>&6
-echo "configure:1443: checking how to build libraries" >&5
+ echo "$as_me:$LINENO: checking how to build libraries" >&5
+echo $ECHO_N "checking how to build libraries... $ECHO_C" >&6
# Check whether --enable-shared or --disable-shared was given.
if test "${enable_shared+set}" = set; then
enableval="$enable_shared"
tcl_ok=$enableval
else
tcl_ok=yes
-fi
-
+fi;
if test "${enable_shared+set}" = set; then
enableval="$enable_shared"
@@ -1457,14 +3858,16 @@ fi
fi
if test "$tcl_ok" = "yes" ; then
- echo "$ac_t""shared" 1>&6
+ echo "$as_me:$LINENO: result: shared" >&5
+echo "${ECHO_T}shared" >&6
SHARED_BUILD=1
else
- echo "$ac_t""static" 1>&6
+ echo "$as_me:$LINENO: result: static" >&5
+echo "${ECHO_T}static" >&6
SHARED_BUILD=0
- cat >> confdefs.h <<\EOF
+ cat >>confdefs.h <<\_ACEOF
#define STATIC_BUILD 1
-EOF
+_ACEOF
fi
@@ -1475,79 +3878,158 @@ EOF
# after SC_ENABLE_SHARED checks the configure switches.
#--------------------------------------------------------------------
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
# Step 0: Enable 64 bit support?
- echo $ac_n "checking if 64bit support is requested""... $ac_c" 1>&6
-echo "configure:1484: checking if 64bit support is requested" >&5
+ echo "$as_me:$LINENO: checking if 64bit support is requested" >&5
+echo $ECHO_N "checking if 64bit support is requested... $ECHO_C" >&6
# Check whether --enable-64bit or --disable-64bit was given.
if test "${enable_64bit+set}" = set; then
enableval="$enable_64bit"
do64bit=$enableval
else
do64bit=no
-fi
-
- echo "$ac_t""$do64bit" 1>&6
+fi;
+ echo "$as_me:$LINENO: result: $do64bit" >&5
+echo "${ECHO_T}$do64bit" >&6
# Cross-compiling options for Windows/CE builds
- echo $ac_n "checking if Windows/CE build is requested""... $ac_c" 1>&6
-echo "configure:1498: checking if Windows/CE build is requested" >&5
+ echo "$as_me:$LINENO: checking if Windows/CE build is requested" >&5
+echo $ECHO_N "checking if Windows/CE build is requested... $ECHO_C" >&6
# Check whether --enable-wince or --disable-wince was given.
if test "${enable_wince+set}" = set; then
enableval="$enable_wince"
doWince=$enableval
else
doWince=no
-fi
+fi;
+ echo "$as_me:$LINENO: result: $doWince" >&5
+echo "${ECHO_T}$doWince" >&6
- echo "$ac_t""$doWince" 1>&6
+ echo "$as_me:$LINENO: checking for Windows/CE celib directory" >&5
+echo $ECHO_N "checking for Windows/CE celib directory... $ECHO_C" >&6
- echo $ac_n "checking for Windows/CE celib directory""... $ac_c" 1>&6
-echo "configure:1510: checking for Windows/CE celib directory" >&5
- # Check whether --with-celib or --without-celib was given.
+# Check whether --with-celib or --without-celib was given.
if test "${with_celib+set}" = set; then
withval="$with_celib"
CELIB_DIR=$withval
else
CELIB_DIR=NO_CELIB
-fi
-
- echo "$ac_t""$CELIB_DIR" 1>&6
+fi;
+ echo "$as_me:$LINENO: result: $CELIB_DIR" >&5
+echo "${ECHO_T}$CELIB_DIR" >&6
# Set some defaults (may get changed below)
EXTRA_CFLAGS=""
# Extract the first word of "cygpath", so it can be a program name with args.
set dummy cygpath; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1527: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CYGPATH'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CYGPATH+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test -n "$CYGPATH"; then
ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_CYGPATH="cygpath -w"
- break
- fi
- done
- IFS="$ac_save_ifs"
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CYGPATH="cygpath -w"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
test -z "$ac_cv_prog_CYGPATH" && ac_cv_prog_CYGPATH="echo"
fi
fi
-CYGPATH="$ac_cv_prog_CYGPATH"
+CYGPATH=$ac_cv_prog_CYGPATH
if test -n "$CYGPATH"; then
- echo "$ac_t""$CYGPATH" 1>&6
+ echo "$as_me:$LINENO: result: $CYGPATH" >&5
+echo "${ECHO_T}$CYGPATH" >&6
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
fi
@@ -1570,13 +4052,20 @@ fi
echo "101 \"name\"" >> $conftest
echo "END" >> $conftest
- echo $ac_n "checking for Windows native path bug in windres""... $ac_c" 1>&6
-echo "configure:1575: checking for Windows native path bug in windres" >&5
+ echo "$as_me:$LINENO: checking for Windows native path bug in windres" >&5
+echo $ECHO_N "checking for Windows native path bug in windres... $ECHO_C" >&6
cyg_conftest=`$CYGPATH $conftest`
- if { ac_try='$RC -o conftest.res.o $cyg_conftest'; { (eval echo configure:1577: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } ; then
- echo "$ac_t""no" 1>&6
+ if { ac_try='$RC -o conftest.res.o $cyg_conftest'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } ; then
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
else
- echo "$ac_t""yes" 1>&6
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
CYGPATH=echo
fi
conftest=
@@ -1591,13 +4080,14 @@ echo "configure:1575: checking for Windows native path bug in windres" >&5
# set various compiler flags depending on whether we are using gcc or cl
- echo $ac_n "checking compiler flags""... $ac_c" 1>&6
-echo "configure:1596: checking compiler flags" >&5
+ echo "$as_me:$LINENO: checking compiler flags" >&5
+echo $ECHO_N "checking compiler flags... $ECHO_C" >&6
if test "${GCC}" = "yes" ; then
SHLIB_LD=""
SHLIB_LD_LIBS=""
- LIBS=""
- LIBS_GUI="-lgdi32 -lcomdlg32 -limm32 -lcomctl32 -lshell32"
+ LIBS="-lws2_32"
+ # mingw needs to link ole32 and oleaut32 for [send], but MSVC doesn't
+ LIBS_GUI="-lgdi32 -lcomdlg32 -limm32 -lcomctl32 -lshell32 -luuid -lole32 -loleaut32"
STLIB_LD='${AR} cr'
RC_OUT=-o
RC_TYPE=
@@ -1629,7 +4119,8 @@ echo "configure:1596: checking compiler flags" >&5
if test "${SHARED_BUILD}" = "0" ; then
# static
- echo "$ac_t""using static flags" 1>&6
+ echo "$as_me:$LINENO: result: using static flags" >&5
+echo "${ECHO_T}using static flags" >&6
runtime=
MAKE_DLL="echo "
LIBSUFFIX="s\${DBGX}.a"
@@ -1638,12 +4129,16 @@ echo "configure:1596: checking compiler flags" >&5
EXESUFFIX="s\${DBGX}.exe"
else
# dynamic
- echo "$ac_t""using shared flags" 1>&6
+ echo "$as_me:$LINENO: result: using shared flags" >&5
+echo "${ECHO_T}using shared flags" >&6
# ad-hoc check to see if CC supports -shared.
if "${CC}" -shared 2>&1 | egrep ': -shared not supported' >/dev/null; then
- { echo "configure: error: ${CC} does not support the -shared option.
- You will need to upgrade to a newer version of the toolchain." 1>&2; exit 1; }
+ { { echo "$as_me:$LINENO: error: ${CC} does not support the -shared option.
+ You will need to upgrade to a newer version of the toolchain." >&5
+echo "$as_me: error: ${CC} does not support the -shared option.
+ You will need to upgrade to a newer version of the toolchain." >&2;}
+ { (exit 1); exit 1; }; }
fi
runtime=
@@ -1670,7 +4165,7 @@ echo "configure:1596: checking compiler flags" >&5
CFLAGS_DEBUG=-g
CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"
- CFLAGS_WARNING="-Wall -fno-strict-aliasing"
+ CFLAGS_WARNING="-Wall"
LDFLAGS_DEBUG=
LDFLAGS_OPTIMIZE=
@@ -1698,47 +4193,78 @@ echo "configure:1596: checking compiler flags" >&5
case "$do64bit" in
amd64|x64|yes)
MACHINE="AMD64" ; # assume AMD64 as default 64-bit build
- echo "$ac_t"" Using 64-bit $MACHINE mode" 1>&6
+ echo "$as_me:$LINENO: result: Using 64-bit $MACHINE mode" >&5
+echo "${ECHO_T} Using 64-bit $MACHINE mode" >&6
;;
ia64)
MACHINE="IA64"
- echo "$ac_t"" Using 64-bit $MACHINE mode" 1>&6
+ echo "$as_me:$LINENO: result: Using 64-bit $MACHINE mode" >&5
+echo "${ECHO_T} Using 64-bit $MACHINE mode" >&6
;;
*)
- cat > conftest.$ac_ext <<EOF
-#line 1710 "configure"
-#include "confdefs.h"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
#ifdef _WIN64
#error 64-bit
#endif
-
-int main() {
-; return 0; }
-EOF
-if { (eval echo configure:1721: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
tcl_win_64bit=no
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- tcl_win_64bit=yes
-
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_win_64bit=yes
+
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
if test "$tcl_win_64bit" = "yes" ; then
do64bit=amd64
MACHINE="AMD64"
- echo "$ac_t"" Using 64-bit $MACHINE mode" 1>&6
+ echo "$as_me:$LINENO: result: Using 64-bit $MACHINE mode" >&5
+echo "${ECHO_T} Using 64-bit $MACHINE mode" >&6
fi
;;
esac
else
if test "${SHARED_BUILD}" = "0" ; then
# static
- echo "$ac_t""using static flags" 1>&6
+ echo "$as_me:$LINENO: result: using static flags" >&5
+echo "${ECHO_T}using static flags" >&6
runtime=-MT
MAKE_DLL="echo "
LIBSUFFIX="s\${DBGX}.lib"
@@ -1748,7 +4274,8 @@ rm -f conftest*
SHLIB_LD_LIBS=""
else
# dynamic
- echo "$ac_t""using shared flags" 1>&6
+ echo "$as_me:$LINENO: result: using shared flags" >&5
+echo "${ECHO_T}using shared flags" >&6
runtime=-MD
# Add SHLIB_LD_LIBS to the Make rule, not here.
MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -out:\$@"
@@ -1782,21 +4309,88 @@ rm -f conftest*
;;
esac
if test ! -d "${PATH64}" ; then
- echo "configure: warning: Could not find 64-bit $MACHINE SDK to enable 64bit mode" 1>&2
- echo "configure: warning: Ensure latest Platform SDK is installed" 1>&2
+ { echo "$as_me:$LINENO: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&5
+echo "$as_me: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&2;}
+ { echo "$as_me:$LINENO: WARNING: Ensure latest Platform SDK is installed" >&5
+echo "$as_me: WARNING: Ensure latest Platform SDK is installed" >&2;}
do64bit="no"
else
- echo "$ac_t"" Using 64-bit $MACHINE mode" 1>&6
+ echo "$as_me:$LINENO: result: Using 64-bit $MACHINE mode" >&5
+echo "${ECHO_T} Using 64-bit $MACHINE mode" >&6
fi
fi
- LIBS="user32.lib advapi32.lib"
+ LIBS="user32.lib advapi32.lib ws2_32.lib"
if test "$do64bit" != "no" ; then
# The space-based-path will work for the Makefile, but will
# not work if AC_TRY_COMPILE is called. TEA has the
# TEA_PATH_NOSPACE to avoid this issue.
- CC="\"${PATH64}/cl.exe\" -I\"${MSSDK}/Include\" \
- -I\"${MSSDK}/Include/crt\" -I\"${MSSDK}/Include/crt/sys\""
+ # Check if _WIN64 is already recognized, and if so we don't
+ # need to modify CC.
+ echo "$as_me:$LINENO: checking whether _WIN64 is declared" >&5
+echo $ECHO_N "checking whether _WIN64 is declared... $ECHO_C" >&6
+if test "${ac_cv_have_decl__WIN64+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+#ifndef _WIN64
+ char *p = (char *) _WIN64;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_have_decl__WIN64=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_have_decl__WIN64=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_have_decl__WIN64" >&5
+echo "${ECHO_T}$ac_cv_have_decl__WIN64" >&6
+if test $ac_cv_have_decl__WIN64 = yes; then
+ :
+else
+ CC="\"${PATH64}/cl.exe\" -I\"${MSSDK}/Include\" \
+ -I\"${MSSDK}/Include/crt\" \
+ -I\"${MSSDK}/Include/crt/sys\""
+fi
+
RC="\"${MSSDK}/bin/rc.exe\""
CFLAGS_DEBUG="-nologo -Zi -Od ${runtime}d"
# Do not use -O2 for Win64 - this has proved buggy in code gen.
@@ -1858,11 +4452,15 @@ rm -f conftest*
SDKROOT=`echo "$SDKROOT" | sed -e 's!\\\!/!g'`
CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'`
if test ! -d "${CELIB_DIR}/inc"; then
- { echo "configure: error: Invalid celib directory "${CELIB_DIR}"" 1>&2; exit 1; }
+ { { echo "$as_me:$LINENO: error: Invalid celib directory \"${CELIB_DIR}\"" >&5
+echo "$as_me: error: Invalid celib directory \"${CELIB_DIR}\"" >&2;}
+ { (exit 1); exit 1; }; }
fi
if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}"\
-o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then
- { echo "configure: error: could not find PocketPC SDK or target compiler to enable WinCE mode $CEVERSION,$TARGETCPU,$ARCH,$PLATFORM" 1>&2; exit 1; }
+ { { echo "$as_me:$LINENO: error: could not find PocketPC SDK or target compiler to enable WinCE mode $CEVERSION,$TARGETCPU,$ARCH,$PLATFORM" >&5
+echo "$as_me: error: could not find PocketPC SDK or target compiler to enable WinCE mode $CEVERSION,$TARGETCPU,$ARCH,$PLATFORM" >&2;}
+ { (exit 1); exit 1; }; }
else
CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include"
if test -d "${CEINCLUDE}/${TARGETCPU}" ; then
@@ -1884,28 +4482,28 @@ rm -f conftest*
arch=`echo ${ARCH} | awk '{print tolower($0)}'`
defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _DLL _WINDOWS"
for i in $defs ; do
- cat >> confdefs.h <<EOF
+ cat >>confdefs.h <<_ACEOF
#define $i 1
-EOF
+_ACEOF
done
# if test "${ARCH}" = "X86EM"; then
# AC_DEFINE_UNQUOTED(_WIN32_WCE_EMULATION)
# fi
- cat >> confdefs.h <<EOF
+ cat >>confdefs.h <<_ACEOF
#define _WIN32_WCE $CEVERSION
-EOF
+_ACEOF
- cat >> confdefs.h <<EOF
+ cat >>confdefs.h <<_ACEOF
#define UNDER_CE $CEVERSION
-EOF
+_ACEOF
CFLAGS_DEBUG="-nologo -Zi -Od"
CFLAGS_OPTIMIZE="-nologo -O2"
lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'`
lflags="-nodefaultlib -MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo"
LINKBIN="\"${CEBINROOT}/link.exe\""
-
+
if test "${CEVERSION}" -lt 400 ; then
LIBS="coredll.lib corelibc.lib winsock.lib"
else
@@ -1916,7 +4514,7 @@ EOF
LIBS="$LIBS \"\${CELIB_DIR}/wince-${ARCH}-pocket-wce300-release/celib.lib\""
LIBS_GUI="commctrl.lib commdlg.lib"
else
- LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib"
+ LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib"
fi
SHLIB_LD="${LINKBIN} -dll -incremental:no ${lflags}"
@@ -1955,13 +4553,291 @@ EOF
fi
fi
+ if test "$do64bit" != "no" ; then
+ cat >>confdefs.h <<\_ACEOF
+#define TCL_CFG_DO64BIT 1
+_ACEOF
+
+ fi
+
# DL_LIBS is empty, but then we match the Unix version
-
-
-
-
+
+
+
+
+echo "$as_me:$LINENO: checking for intptr_t" >&5
+echo $ECHO_N "checking for intptr_t... $ECHO_C" >&6
+if test "${ac_cv_type_intptr_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((intptr_t *) 0)
+ return 0;
+if (sizeof (intptr_t))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_intptr_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_intptr_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_intptr_t" >&5
+echo "${ECHO_T}$ac_cv_type_intptr_t" >&6
+if test $ac_cv_type_intptr_t = yes; then
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_INTPTR_T 1
+_ACEOF
+
+else
+
+ echo "$as_me:$LINENO: checking for pointer-size signed integer type" >&5
+echo $ECHO_N "checking for pointer-size signed integer type... $ECHO_C" >&6
+if test "${tcl_cv_intptr_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ for tcl_cv_intptr_t in "int" "long" "long long" none; do
+ if test "$tcl_cv_intptr_t" != none; then
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_intptr_t))];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ tcl_ok=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_ok=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$tcl_ok" = yes && break; fi
+ done
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_intptr_t" >&5
+echo "${ECHO_T}$tcl_cv_intptr_t" >&6
+ if test "$tcl_cv_intptr_t" != none; then
+
+cat >>confdefs.h <<_ACEOF
+#define intptr_t $tcl_cv_intptr_t
+_ACEOF
+
+ fi
+
+fi
+
+echo "$as_me:$LINENO: checking for uintptr_t" >&5
+echo $ECHO_N "checking for uintptr_t... $ECHO_C" >&6
+if test "${ac_cv_type_uintptr_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((uintptr_t *) 0)
+ return 0;
+if (sizeof (uintptr_t))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_uintptr_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_uintptr_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_uintptr_t" >&5
+echo "${ECHO_T}$ac_cv_type_uintptr_t" >&6
+if test $ac_cv_type_uintptr_t = yes; then
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_UINTPTR_T 1
+_ACEOF
+
+else
+
+ echo "$as_me:$LINENO: checking for pointer-size unsigned integer type" >&5
+echo $ECHO_N "checking for pointer-size unsigned integer type... $ECHO_C" >&6
+if test "${tcl_cv_uintptr_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \
+ none; do
+ if test "$tcl_cv_uintptr_t" != none; then
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_uintptr_t))];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ tcl_ok=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_ok=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$tcl_ok" = yes && break; fi
+ done
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_uintptr_t" >&5
+echo "${ECHO_T}$tcl_cv_uintptr_t" >&6
+ if test "$tcl_cv_uintptr_t" != none; then
+
+cat >>confdefs.h <<_ACEOF
+#define uintptr_t $tcl_cv_uintptr_t
+_ACEOF
+
+ fi
+
+fi
+
#--------------------------------------------------------------------
# Set the default compiler switches based on the --enable-symbols
# option. This macro depends on C flags, and should be called
@@ -1969,56 +4845,68 @@ EOF
#--------------------------------------------------------------------
- echo $ac_n "checking for build with symbols""... $ac_c" 1>&6
-echo "configure:1974: checking for build with symbols" >&5
+ echo "$as_me:$LINENO: checking for build with symbols" >&5
+echo $ECHO_N "checking for build with symbols... $ECHO_C" >&6
# Check whether --enable-symbols or --disable-symbols was given.
if test "${enable_symbols+set}" = set; then
enableval="$enable_symbols"
tcl_ok=$enableval
else
tcl_ok=no
-fi
-
+fi;
# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT.
if test "$tcl_ok" = "no"; then
CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'
LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'
DBGX=""
- echo "$ac_t""no" 1>&6
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+
+ cat >>confdefs.h <<\_ACEOF
+#define TCL_CFG_OPTIMIZED 1
+_ACEOF
+
else
CFLAGS_DEFAULT='$(CFLAGS_DEBUG)'
LDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)'
DBGX=g
if test "$tcl_ok" = "yes"; then
- echo "$ac_t""yes (standard debugging)" 1>&6
+ echo "$as_me:$LINENO: result: yes (standard debugging)" >&5
+echo "${ECHO_T}yes (standard debugging)" >&6
fi
fi
-
-
+
+
+ cat >>confdefs.h <<\_ACEOF
+#define TCL_CFG_DEBUG 1
+_ACEOF
+
if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then
- cat >> confdefs.h <<\EOF
+ cat >>confdefs.h <<\_ACEOF
#define TCL_MEM_DEBUG 1
-EOF
+_ACEOF
fi
if test "$tcl_ok" = "compile" -o "$tcl_ok" = "all"; then
- cat >> confdefs.h <<\EOF
+ cat >>confdefs.h <<\_ACEOF
#define TCL_COMPILE_DEBUG 1
-EOF
+_ACEOF
- cat >> confdefs.h <<\EOF
+ cat >>confdefs.h <<\_ACEOF
#define TCL_COMPILE_STATS 1
-EOF
+_ACEOF
fi
if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then
if test "$tcl_ok" = "all"; then
- echo "$ac_t""enabled symbols mem compile debugging" 1>&6
+ echo "$as_me:$LINENO: result: enabled symbols mem compile debugging" >&5
+echo "${ECHO_T}enabled symbols mem compile debugging" >&6
else
- echo "$ac_t""enabled $tcl_ok debugging" 1>&6
+ echo "$as_me:$LINENO: result: enabled $tcl_ok debugging" >&5
+echo "${ECHO_T}enabled $tcl_ok debugging" >&6
fi
fi
@@ -2026,122 +4914,61 @@ EOF
TCL_DBGX=${DBGX}
#--------------------------------------------------------------------
-# man2tcl needs this so that it can use errno.h
+# Embed the manifest if we can determine how
#--------------------------------------------------------------------
-echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:2034: checking how to run the C preprocessor" >&5
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-if test -z "$CPP"; then
-if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- # This must be in double quotes, not single quotes, because CPP may get
- # substituted into the Makefile and "${CC-cc}" will confuse make.
- CPP="${CC-cc} -E"
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp.
- cat > conftest.$ac_ext <<EOF
-#line 2049 "configure"
-#include "confdefs.h"
-#include <assert.h>
-Syntax Error
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2055: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- :
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP="${CC-cc} -E -traditional-cpp"
- cat > conftest.$ac_ext <<EOF
-#line 2066 "configure"
-#include "confdefs.h"
-#include <assert.h>
-Syntax Error
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2072: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- :
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP="${CC-cc} -nologo -E"
- cat > conftest.$ac_ext <<EOF
-#line 2083 "configure"
-#include "confdefs.h"
-#include <assert.h>
-Syntax Error
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2089: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- :
+
+ echo "$as_me:$LINENO: checking whether to embed manifest" >&5
+echo $ECHO_N "checking whether to embed manifest... $ECHO_C" >&6
+ # Check whether --enable-embedded-manifest or --disable-embedded-manifest was given.
+if test "${enable_embedded_manifest+set}" = set; then
+ enableval="$enable_embedded_manifest"
+ embed_ok=$enableval
else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP=/lib/cpp
-fi
-rm -f conftest*
-fi
-rm -f conftest*
-fi
-rm -f conftest*
- ac_cv_prog_CPP="$CPP"
-fi
- CPP="$ac_cv_prog_CPP"
-else
- ac_cv_prog_CPP="$CPP"
-fi
-echo "$ac_t""$CPP" 1>&6
-
-ac_safe=`echo "errno.h" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for errno.h""... $ac_c" 1>&6
-echo "configure:2115: checking for errno.h" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2120 "configure"
-#include "confdefs.h"
-#include <errno.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2125: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
+ embed_ok=yes
+fi;
+
+ VC_MANIFEST_EMBED_DLL=
+ VC_MANIFEST_EMBED_EXE=
+ result=no
+ if test "$embed_ok" = "yes" -a "${SHARED_BUILD}" = "1" \
+ -a "$GCC" != "yes" ; then
+ # Add the magic to embed the manifest into the dll/exe
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+print("manifest needed")
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "manifest needed" >/dev/null 2>&1; then
+
+ # Could do a CHECK_PROG for mt, but should always be with MSVC8+
+ # Could add 'if test -f' check, but manifest should be created
+ # in this compiler case
+ # Add in a manifest argument that may be specified
+ # XXX Needs improvement so that the test for existence accounts
+ # XXX for a provided (known) manifest
+ VC_MANIFEST_EMBED_DLL="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;2 ; fi"
+ VC_MANIFEST_EMBED_EXE="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;1 ; fi"
+ result=yes
+ if test "x" != x ; then
+ result="yes ()"
+ fi
+
fi
rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- :
-else
- echo "$ac_t""no" 1>&6
-MAN2TCLFLAGS="-DNO_ERRNO_H"
-fi
+
+ fi
+ echo "$as_me:$LINENO: result: $result" >&5
+echo "${ECHO_T}$result" >&6
+
@@ -2292,7 +5119,6 @@ fi
-
# win only
@@ -2309,338 +5135,1001 @@ fi
-trap '' 1 2 15
-cat > confcache <<\EOF
+
+
+ ac_config_files="$ac_config_files Makefile tclConfig.sh tcl.hpj"
+cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
-# scripts and configure runs. It is not useful on other systems.
-# If it contains results you don't want to keep, you may remove or edit it.
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
#
-# By default, configure uses ./config.cache as the cache file,
-# creating it if it does not exist already. You can give configure
-# the --cache-file=FILE option to use a different cache file; that is
-# what configure does when it calls configure scripts in
-# subdirectories, so they share the cache.
-# Giving --cache-file=/dev/null disables caching, for debugging configure.
-# config.status only pays attention to the cache file if you give it the
-# --recheck option to rerun configure.
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
#
-EOF
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
# The following way of writing the cache mishandles newlines in values,
# but we know of no workaround that is simple, portable, and efficient.
# So, don't put newlines in cache variables' values.
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
-(set) 2>&1 |
- case `(ac_space=' '; set | grep ac_space) 2>&1` in
- *ac_space=\ *)
- # `set' does not quote correctly, so add quotes (double-quote substitution
- # turns \\\\ into \\, and sed turns \\ into \).
- sed -n \
- -e "s/'/'\\\\''/g" \
- -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
- ;;
- *)
- # `set' quotes correctly as required by POSIX, so do not add quotes.
- sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
- ;;
- esac >> confcache
-if cmp -s $cache_file confcache; then
- :
-else
+{
+ (set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+} |
+ sed '
+ t clear
+ : clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
if test -w $cache_file; then
- echo "updating cache $cache_file"
- cat confcache > $cache_file
+ test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+ cat confcache >$cache_file
else
echo "not updating unwritable cache $cache_file"
fi
fi
rm -f confcache
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
-
test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-# Any assignment to VPATH causes Sun make to only execute
-# the first set of double-colon rules, so remove it if not needed.
-# If there is a colon in the path, we need to keep it.
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
if test "x$srcdir" = x.; then
- ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[ ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[ ]*$//;
+}'
fi
-trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
-
# Transform confdefs.h into DEFS.
# Protect against shell expansion while executing Makefile rules.
# Protect against Makefile macro expansion.
-cat > conftest.defs <<\EOF
-s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
-s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
-s%\[%\\&%g
-s%\]%\\&%g
-s%\$%$$%g
-EOF
-DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
-rm -f conftest.defs
-
-
-# Without the "./", some shells look in PATH for config.status.
-: ${CONFIG_STATUS=./config.status}
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then we branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+cat >confdef2opt.sed <<\_ACEOF
+t clear
+: clear
+s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g
+t quote
+s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g
+t quote
+d
+: quote
+s,[ `~#$^&*(){}\\|;'"<>?],\\&,g
+s,\[,\\&,g
+s,\],\\&,g
+s,\$,$$,g
+p
+_ACEOF
+# We use echo to avoid assuming a particular line-breaking character.
+# The extra dot is to prevent the shell from consuming trailing
+# line-breaks from the sub-command output. A line-break within
+# single-quotes doesn't work because, if this script is created in a
+# platform that uses two characters for line-breaks (e.g., DOS), tr
+# would break.
+ac_LF_and_DOT=`echo; echo .`
+DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
+rm -f confdef2opt.sed
+
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_i=`echo "$ac_i" |
+ sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+ # 2. Add them.
+ ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
-echo creating $CONFIG_STATUS
-rm -f $CONFIG_STATUS
-cat > $CONFIG_STATUS <<EOF
-#! /bin/sh
-# Generated automatically by configure.
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
# Run this file to recreate the current configuration.
-# This directory was configured as follows,
-# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-#
-# $0 $ac_configure_args
-#
# Compiler output produced by configure, useful for debugging
-# configure, is in ./config.log if it exists.
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
-ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
-for ac_option
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
do
- case "\$ac_option" in
- -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
- echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
- exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
- -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
- echo "$CONFIG_STATUS generated by autoconf version 2.13"
- exit 0 ;;
- -help | --help | --hel | --he | --h)
- echo "\$ac_cs_usage"; exit 0 ;;
- *) echo "\$ac_cs_usage"; exit 1 ;;
- esac
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
done
-ac_given_srcdir=$srcdir
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
-trap 'rm -fr `echo "Makefile tclConfig.sh tcl.hpj" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
-EOF
-cat >> $CONFIG_STATUS <<EOF
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
-# Protect against being on the right side of a sed subst in config.status.
-sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
- s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
-$ac_vpsub
-$extrasub
-s%@SHELL@%$SHELL%g
-s%@CFLAGS@%$CFLAGS%g
-s%@CPPFLAGS@%$CPPFLAGS%g
-s%@CXXFLAGS@%$CXXFLAGS%g
-s%@FFLAGS@%$FFLAGS%g
-s%@DEFS@%$DEFS%g
-s%@LDFLAGS@%$LDFLAGS%g
-s%@LIBS@%$LIBS%g
-s%@exec_prefix@%$exec_prefix%g
-s%@prefix@%$prefix%g
-s%@program_transform_name@%$program_transform_name%g
-s%@bindir@%$bindir%g
-s%@sbindir@%$sbindir%g
-s%@libexecdir@%$libexecdir%g
-s%@datadir@%$datadir%g
-s%@sysconfdir@%$sysconfdir%g
-s%@sharedstatedir@%$sharedstatedir%g
-s%@localstatedir@%$localstatedir%g
-s%@libdir@%$libdir%g
-s%@includedir@%$includedir%g
-s%@oldincludedir@%$oldincludedir%g
-s%@infodir@%$infodir%g
-s%@mandir@%$mandir%g
-s%@CC@%$CC%g
-s%@AR@%$AR%g
-s%@RANLIB@%$RANLIB%g
-s%@RC@%$RC%g
-s%@SET_MAKE@%$SET_MAKE%g
-s%@OBJEXT@%$OBJEXT%g
-s%@EXEEXT@%$EXEEXT%g
-s%@TCL_THREADS@%$TCL_THREADS%g
-s%@CYGPATH@%$CYGPATH%g
-s%@CELIB_DIR@%$CELIB_DIR%g
-s%@DL_LIBS@%$DL_LIBS%g
-s%@CFLAGS_DEBUG@%$CFLAGS_DEBUG%g
-s%@CFLAGS_OPTIMIZE@%$CFLAGS_OPTIMIZE%g
-s%@CFLAGS_WARNING@%$CFLAGS_WARNING%g
-s%@CFLAGS_DEFAULT@%$CFLAGS_DEFAULT%g
-s%@LDFLAGS_DEFAULT@%$LDFLAGS_DEFAULT%g
-s%@CPP@%$CPP%g
-s%@MAN2TCLFLAGS@%$MAN2TCLFLAGS%g
-s%@TCL_VERSION@%$TCL_VERSION%g
-s%@TCL_MAJOR_VERSION@%$TCL_MAJOR_VERSION%g
-s%@TCL_MINOR_VERSION@%$TCL_MINOR_VERSION%g
-s%@TCL_PATCH_LEVEL@%$TCL_PATCH_LEVEL%g
-s%@TCL_LIB_FILE@%$TCL_LIB_FILE%g
-s%@TCL_LIB_FLAG@%$TCL_LIB_FLAG%g
-s%@TCL_LIB_SPEC@%$TCL_LIB_SPEC%g
-s%@TCL_STUB_LIB_FILE@%$TCL_STUB_LIB_FILE%g
-s%@TCL_STUB_LIB_FLAG@%$TCL_STUB_LIB_FLAG%g
-s%@TCL_STUB_LIB_SPEC@%$TCL_STUB_LIB_SPEC%g
-s%@TCL_STUB_LIB_PATH@%$TCL_STUB_LIB_PATH%g
-s%@TCL_INCLUDE_SPEC@%$TCL_INCLUDE_SPEC%g
-s%@TCL_BUILD_STUB_LIB_SPEC@%$TCL_BUILD_STUB_LIB_SPEC%g
-s%@TCL_BUILD_STUB_LIB_PATH@%$TCL_BUILD_STUB_LIB_PATH%g
-s%@TCL_DLL_FILE@%$TCL_DLL_FILE%g
-s%@TCL_SRC_DIR@%$TCL_SRC_DIR%g
-s%@TCL_BIN_DIR@%$TCL_BIN_DIR%g
-s%@TCL_DBGX@%$TCL_DBGX%g
-s%@CFG_TCL_SHARED_LIB_SUFFIX@%$CFG_TCL_SHARED_LIB_SUFFIX%g
-s%@CFG_TCL_UNSHARED_LIB_SUFFIX@%$CFG_TCL_UNSHARED_LIB_SUFFIX%g
-s%@CFG_TCL_EXPORT_FILE_SUFFIX@%$CFG_TCL_EXPORT_FILE_SUFFIX%g
-s%@EXTRA_CFLAGS@%$EXTRA_CFLAGS%g
-s%@DEPARG@%$DEPARG%g
-s%@CC_OBJNAME@%$CC_OBJNAME%g
-s%@CC_EXENAME@%$CC_EXENAME%g
-s%@LDFLAGS_DEBUG@%$LDFLAGS_DEBUG%g
-s%@LDFLAGS_OPTIMIZE@%$LDFLAGS_OPTIMIZE%g
-s%@LDFLAGS_CONSOLE@%$LDFLAGS_CONSOLE%g
-s%@LDFLAGS_WINDOW@%$LDFLAGS_WINDOW%g
-s%@STLIB_LD@%$STLIB_LD%g
-s%@SHLIB_LD@%$SHLIB_LD%g
-s%@SHLIB_LD_LIBS@%$SHLIB_LD_LIBS%g
-s%@SHLIB_CFLAGS@%$SHLIB_CFLAGS%g
-s%@SHLIB_SUFFIX@%$SHLIB_SUFFIX%g
-s%@TCL_SHARED_BUILD@%$TCL_SHARED_BUILD%g
-s%@LIBS_GUI@%$LIBS_GUI%g
-s%@DLLSUFFIX@%$DLLSUFFIX%g
-s%@LIBPREFIX@%$LIBPREFIX%g
-s%@LIBSUFFIX@%$LIBSUFFIX%g
-s%@EXESUFFIX@%$EXESUFFIX%g
-s%@LIBRARIES@%$LIBRARIES%g
-s%@MAKE_LIB@%$MAKE_LIB%g
-s%@POST_MAKE_LIB@%$POST_MAKE_LIB%g
-s%@MAKE_DLL@%$MAKE_DLL%g
-s%@MAKE_EXE@%$MAKE_EXE%g
-s%@TCL_BUILD_LIB_SPEC@%$TCL_BUILD_LIB_SPEC%g
-s%@TCL_LD_SEARCH_FLAGS@%$TCL_LD_SEARCH_FLAGS%g
-s%@TCL_NEEDS_EXP_FILE@%$TCL_NEEDS_EXP_FILE%g
-s%@TCL_BUILD_EXP_FILE@%$TCL_BUILD_EXP_FILE%g
-s%@TCL_EXP_FILE@%$TCL_EXP_FILE%g
-s%@LIBOBJS@%$LIBOBJS%g
-s%@TCL_LIB_VERSIONS_OK@%$TCL_LIB_VERSIONS_OK%g
-s%@TCL_PACKAGE_PATH@%$TCL_PACKAGE_PATH%g
-s%@TCL_DDE_VERSION@%$TCL_DDE_VERSION%g
-s%@TCL_DDE_MAJOR_VERSION@%$TCL_DDE_MAJOR_VERSION%g
-s%@TCL_DDE_MINOR_VERSION@%$TCL_DDE_MINOR_VERSION%g
-s%@TCL_REG_VERSION@%$TCL_REG_VERSION%g
-s%@TCL_REG_MAJOR_VERSION@%$TCL_REG_MAJOR_VERSION%g
-s%@TCL_REG_MINOR_VERSION@%$TCL_REG_MINOR_VERSION%g
-s%@RC_OUT@%$RC_OUT%g
-s%@RC_TYPE@%$RC_TYPE%g
-s%@RC_INCLUDE@%$RC_INCLUDE%g
-s%@RC_DEFINE@%$RC_DEFINE%g
-s%@RC_DEFINES@%$RC_DEFINES%g
-s%@RES@%$RES%g
-CEOF
-EOF
-
-cat >> $CONFIG_STATUS <<\EOF
-
-# Split the substitutions into bite-sized pieces for seds with
-# small command number limits, like on Digital OSF/1 and HP-UX.
-ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
-ac_file=1 # Number of current file.
-ac_beg=1 # First line for current file.
-ac_end=$ac_max_sed_cmds # Line after last line for current file.
-ac_more_lines=:
-ac_sed_cmds=""
-while $ac_more_lines; do
- if test $ac_beg -gt 1; then
- sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
else
- sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ PATH_SEPARATOR=:
fi
- if test ! -s conftest.s$ac_file; then
- ac_more_lines=false
- rm -f conftest.s$ac_file
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
else
- if test -z "$ac_sed_cmds"; then
- ac_sed_cmds="sed -f conftest.s$ac_file"
- else
- ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
- fi
- ac_file=`expr $ac_file + 1`
- ac_beg=$ac_end
- ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ as_ln_s='ln -s'
fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling. Logging --version etc. is OK.
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+ echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+ echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+ echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+ echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.59,
+ with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "x$1" : 'x\([^=]*\)='`
+ ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ -*)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ *) # This is not an option, so the user has probably given explicit
+ # arguments.
+ ac_option=$1
+ ac_need_defaults=false;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --vers* | -V )
+ echo "$ac_cs_version"; exit 0 ;;
+ --he | --h)
+ # Conflict between --help and --header
+ { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit 0 ;;
+ --debug | --d* | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1" ;;
+
+ esac
+ shift
done
-if test -z "$ac_sed_cmds"; then
- ac_sed_cmds=cat
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
fi
-EOF
-cat >> $CONFIG_STATUS <<EOF
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
-CONFIG_FILES=\${CONFIG_FILES-"Makefile tclConfig.sh tcl.hpj"}
-EOF
-cat >> $CONFIG_STATUS <<\EOF
-for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
- # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
- case "$ac_file" in
- *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
- ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
- *) ac_file_in="${ac_file}.in" ;;
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+ case "$ac_config_target" in
+ # Handling of arguments.
+ "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "tclConfig.sh" ) CONFIG_FILES="$CONFIG_FILES tclConfig.sh" ;;
+ "tcl.hpj" ) CONFIG_FILES="$CONFIG_FILES tcl.hpj" ;;
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
esac
+done
- # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
- # Remove last slash and all that follows it. Not all systems have dirname.
- ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
- if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
- # The file is in a subdirectory.
- test ! -d "$ac_dir" && mkdir "$ac_dir"
- ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
- # A "../" for each directory in $ac_dir_suffix.
- ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
- else
- ac_dir_suffix= ac_dots=
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+ trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./confstat$$-$RANDOM
+ (umask 077 && mkdir $tmp)
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+ # Protect against being on the right side of a sed subst in config.status.
+ sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+ s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@CPP@,$CPP,;t t
+s,@EGREP@,$EGREP,;t t
+s,@AR@,$AR,;t t
+s,@ac_ct_AR@,$ac_ct_AR,;t t
+s,@RANLIB@,$RANLIB,;t t
+s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
+s,@RC@,$RC,;t t
+s,@ac_ct_RC@,$ac_ct_RC,;t t
+s,@SET_MAKE@,$SET_MAKE,;t t
+s,@TCL_THREADS@,$TCL_THREADS,;t t
+s,@CYGPATH@,$CYGPATH,;t t
+s,@CELIB_DIR@,$CELIB_DIR,;t t
+s,@DL_LIBS@,$DL_LIBS,;t t
+s,@CFLAGS_DEBUG@,$CFLAGS_DEBUG,;t t
+s,@CFLAGS_OPTIMIZE@,$CFLAGS_OPTIMIZE,;t t
+s,@CFLAGS_WARNING@,$CFLAGS_WARNING,;t t
+s,@CFLAGS_DEFAULT@,$CFLAGS_DEFAULT,;t t
+s,@LDFLAGS_DEFAULT@,$LDFLAGS_DEFAULT,;t t
+s,@VC_MANIFEST_EMBED_DLL@,$VC_MANIFEST_EMBED_DLL,;t t
+s,@VC_MANIFEST_EMBED_EXE@,$VC_MANIFEST_EMBED_EXE,;t t
+s,@TCL_VERSION@,$TCL_VERSION,;t t
+s,@TCL_MAJOR_VERSION@,$TCL_MAJOR_VERSION,;t t
+s,@TCL_MINOR_VERSION@,$TCL_MINOR_VERSION,;t t
+s,@TCL_PATCH_LEVEL@,$TCL_PATCH_LEVEL,;t t
+s,@TCL_LIB_FILE@,$TCL_LIB_FILE,;t t
+s,@TCL_LIB_FLAG@,$TCL_LIB_FLAG,;t t
+s,@TCL_LIB_SPEC@,$TCL_LIB_SPEC,;t t
+s,@TCL_STUB_LIB_FILE@,$TCL_STUB_LIB_FILE,;t t
+s,@TCL_STUB_LIB_FLAG@,$TCL_STUB_LIB_FLAG,;t t
+s,@TCL_STUB_LIB_SPEC@,$TCL_STUB_LIB_SPEC,;t t
+s,@TCL_STUB_LIB_PATH@,$TCL_STUB_LIB_PATH,;t t
+s,@TCL_INCLUDE_SPEC@,$TCL_INCLUDE_SPEC,;t t
+s,@TCL_BUILD_STUB_LIB_SPEC@,$TCL_BUILD_STUB_LIB_SPEC,;t t
+s,@TCL_BUILD_STUB_LIB_PATH@,$TCL_BUILD_STUB_LIB_PATH,;t t
+s,@TCL_DLL_FILE@,$TCL_DLL_FILE,;t t
+s,@TCL_SRC_DIR@,$TCL_SRC_DIR,;t t
+s,@TCL_BIN_DIR@,$TCL_BIN_DIR,;t t
+s,@TCL_DBGX@,$TCL_DBGX,;t t
+s,@CFG_TCL_SHARED_LIB_SUFFIX@,$CFG_TCL_SHARED_LIB_SUFFIX,;t t
+s,@CFG_TCL_UNSHARED_LIB_SUFFIX@,$CFG_TCL_UNSHARED_LIB_SUFFIX,;t t
+s,@CFG_TCL_EXPORT_FILE_SUFFIX@,$CFG_TCL_EXPORT_FILE_SUFFIX,;t t
+s,@EXTRA_CFLAGS@,$EXTRA_CFLAGS,;t t
+s,@DEPARG@,$DEPARG,;t t
+s,@CC_OBJNAME@,$CC_OBJNAME,;t t
+s,@CC_EXENAME@,$CC_EXENAME,;t t
+s,@LDFLAGS_DEBUG@,$LDFLAGS_DEBUG,;t t
+s,@LDFLAGS_OPTIMIZE@,$LDFLAGS_OPTIMIZE,;t t
+s,@LDFLAGS_CONSOLE@,$LDFLAGS_CONSOLE,;t t
+s,@LDFLAGS_WINDOW@,$LDFLAGS_WINDOW,;t t
+s,@STLIB_LD@,$STLIB_LD,;t t
+s,@SHLIB_LD@,$SHLIB_LD,;t t
+s,@SHLIB_LD_LIBS@,$SHLIB_LD_LIBS,;t t
+s,@SHLIB_CFLAGS@,$SHLIB_CFLAGS,;t t
+s,@SHLIB_SUFFIX@,$SHLIB_SUFFIX,;t t
+s,@TCL_SHARED_BUILD@,$TCL_SHARED_BUILD,;t t
+s,@LIBS_GUI@,$LIBS_GUI,;t t
+s,@DLLSUFFIX@,$DLLSUFFIX,;t t
+s,@LIBPREFIX@,$LIBPREFIX,;t t
+s,@LIBSUFFIX@,$LIBSUFFIX,;t t
+s,@EXESUFFIX@,$EXESUFFIX,;t t
+s,@LIBRARIES@,$LIBRARIES,;t t
+s,@MAKE_LIB@,$MAKE_LIB,;t t
+s,@POST_MAKE_LIB@,$POST_MAKE_LIB,;t t
+s,@MAKE_DLL@,$MAKE_DLL,;t t
+s,@MAKE_EXE@,$MAKE_EXE,;t t
+s,@TCL_BUILD_LIB_SPEC@,$TCL_BUILD_LIB_SPEC,;t t
+s,@TCL_LD_SEARCH_FLAGS@,$TCL_LD_SEARCH_FLAGS,;t t
+s,@TCL_NEEDS_EXP_FILE@,$TCL_NEEDS_EXP_FILE,;t t
+s,@TCL_BUILD_EXP_FILE@,$TCL_BUILD_EXP_FILE,;t t
+s,@TCL_EXP_FILE@,$TCL_EXP_FILE,;t t
+s,@TCL_LIB_VERSIONS_OK@,$TCL_LIB_VERSIONS_OK,;t t
+s,@TCL_PACKAGE_PATH@,$TCL_PACKAGE_PATH,;t t
+s,@TCL_DDE_VERSION@,$TCL_DDE_VERSION,;t t
+s,@TCL_DDE_MAJOR_VERSION@,$TCL_DDE_MAJOR_VERSION,;t t
+s,@TCL_DDE_MINOR_VERSION@,$TCL_DDE_MINOR_VERSION,;t t
+s,@TCL_DDE_PATCH_LEVEL@,$TCL_DDE_PATCH_LEVEL,;t t
+s,@TCL_REG_VERSION@,$TCL_REG_VERSION,;t t
+s,@TCL_REG_MAJOR_VERSION@,$TCL_REG_MAJOR_VERSION,;t t
+s,@TCL_REG_MINOR_VERSION@,$TCL_REG_MINOR_VERSION,;t t
+s,@TCL_REG_PATCH_LEVEL@,$TCL_REG_PATCH_LEVEL,;t t
+s,@RC_OUT@,$RC_OUT,;t t
+s,@RC_TYPE@,$RC_TYPE,;t t
+s,@RC_INCLUDE@,$RC_INCLUDE,;t t
+s,@RC_DEFINE@,$RC_DEFINE,;t t
+s,@RC_DEFINES@,$RC_DEFINES,;t t
+s,@RES@,$RES,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+ cat >>$CONFIG_STATUS <<\_ACEOF
+ # Split the substitutions into bite-sized pieces for seds with
+ # small command number limits, like on Digital OSF/1 and HP-UX.
+ ac_max_sed_lines=48
+ ac_sed_frag=1 # Number of current file.
+ ac_beg=1 # First line for current file.
+ ac_end=$ac_max_sed_lines # Line after last line for current file.
+ ac_more_lines=:
+ ac_sed_cmds=
+ while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ else
+ sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ fi
+ if test ! -s $tmp/subs.frag; then
+ ac_more_lines=false
+ else
+ # The purpose of the label and of the branching condition is to
+ # speed up the sed processing (if there are no `@' at all, there
+ # is no need to browse any of the substitutions).
+ # These are the two extra sed commands mentioned above.
+ (echo ':t
+ /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+ fi
+ ac_sed_frag=`expr $ac_sed_frag + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_lines`
+ fi
+ done
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
fi
+fi # test -n "$CONFIG_FILES"
- case "$ac_given_srcdir" in
- .) srcdir=.
- if test -z "$ac_dots"; then top_srcdir=.
- else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
- /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
- *) # Relative path.
- srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
- top_srcdir="$ac_dots$ac_given_srcdir" ;;
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
esac
+ # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
- echo creating "$ac_file"
- rm -f "$ac_file"
- configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
- case "$ac_file" in
- *Makefile*) ac_comsub="1i\\
-# $configure_input" ;;
- *) ac_comsub= ;;
- esac
+ ac_builddir=.
- ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
- sed -e "$ac_comsub
-s%@configure_input@%$configure_input%g
-s%@srcdir@%$srcdir%g
-s%@top_srcdir@%$top_srcdir%g
-" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
-fi; done
-rm -f conftest.s*
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
-EOF
-cat >> $CONFIG_STATUS <<EOF
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+
+
+ if test x"$ac_file" != x-; then
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ rm -f "$ac_file"
+ fi
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ if test x"$ac_file" = x-; then
+ configure_input=
+ else
+ configure_input="$ac_file. "
+ fi
+ configure_input=$configure_input"Generated from `echo $ac_file_in |
+ sed 's,.*/,,'` by configure."
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ echo "$f";;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo "$f"
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo "$srcdir/$f"
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+ rm -f $tmp/stdin
+ if test x"$ac_file" != x-; then
+ mv $tmp/out $ac_file
+ else
+ cat $tmp/out
+ rm -f $tmp/out
+ fi
-EOF
-cat >> $CONFIG_STATUS <<\EOF
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
-exit 0
-EOF
+{ (exit 0); exit 0; }
+_ACEOF
chmod +x $CONFIG_STATUS
-rm -fr confdefs* $ac_clean_files
-test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
diff --git a/win/configure.in b/win/configure.in
index 47b6a4f..791d96a 100644
--- a/win/configure.in
+++ b/win/configure.in
@@ -4,22 +4,29 @@
# to configure the system for the local environment.
AC_INIT(../generic/tcl.h)
-AC_PREREQ(2.13)
+AC_PREREQ(2.59)
-TCL_VERSION=8.4
+# The following define is needed when building with Cygwin since newer
+# versions of autoconf incorrectly set SHELL to /bin/bash instead of
+# /bin/sh. The bash shell seems to suffer from some strange failures.
+SHELL=/bin/sh
+
+TCL_VERSION=8.5
TCL_MAJOR_VERSION=8
-TCL_MINOR_VERSION=4
-TCL_PATCH_LEVEL=".19"
+TCL_MINOR_VERSION=5
+TCL_PATCH_LEVEL=".10"
VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION
-TCL_DDE_VERSION=1.2
+TCL_DDE_VERSION=1.3
TCL_DDE_MAJOR_VERSION=1
-TCL_DDE_MINOR_VERSION=2
+TCL_DDE_MINOR_VERSION=3
+TCL_DDE_PATCH_LEVEL="2"
DDEVER=$TCL_DDE_MAJOR_VERSION$TCL_DDE_MINOR_VERSION
-TCL_REG_VERSION=1.1
+TCL_REG_VERSION=1.2
TCL_REG_MAJOR_VERSION=1
-TCL_REG_MINOR_VERSION=1
+TCL_REG_MINOR_VERSION=2
+TCL_REG_PATCH_LEVEL="1"
REGVER=$TCL_REG_MAJOR_VERSION$TCL_REG_MINOR_VERSION
#------------------------------------------------------------------------
@@ -46,32 +53,12 @@ if test "${CFLAGS+set}" != "set" ; then
fi
AC_PROG_CC
+AC_C_INLINE
+AC_HEADER_STDC
-# To properly support cross-compilation, one would
-# need to use these tool checks instead of
-# the ones below and reconfigure with
-# autoconf 2.50. You can also just set
-# the CC, AR, RANLIB, and RC environment
-# variables if you want to cross compile.
-dnl AC_CHECK_TOOL(AR, ar)
-dnl AC_CHECK_TOOL(RANLIB, ranlib)
-dnl AC_CHECK_TOOL(RC, windres)
-
-if test "${GCC}" = "yes" ; then
- AC_CHECK_PROG(AR, ar, ar)
- AC_CHECK_PROG(RANLIB, ranlib, ranlib)
- AC_CHECK_PROG(RC, windres, windres)
-
- if test "${AR}" = "" ; then
- AC_MSG_ERROR([Required archive tool 'ar' not found on PATH.])
- fi
- if test "${RANLIB}" = "" ; then
- AC_MSG_ERROR([Required archive index tool 'ranlib' not found on PATH.])
- fi
- if test "${RC}" = "" ; then
- AC_MSG_ERROR([Required resource tool 'windres' not found on PATH.])
- fi
-fi
+AC_CHECK_TOOL(AR, ar)
+AC_CHECK_TOOL(RANLIB, ranlib)
+AC_CHECK_TOOL(RC, windres)
#--------------------------------------------------------------------
# Checks to see if the make program sets the $MAKE variable.
@@ -83,8 +70,22 @@ AC_PROG_MAKE_SET
# Perform additinal compiler tests.
#--------------------------------------------------------------------
-AC_CYGWIN
+dnl Currently AC_CYGWIN is disabled since it invokes AC_CANONICAL_HOST
+dnl under autoconf 2.5X.
+dnl
+dnl AC_CYGWIN
+AC_CACHE_CHECK(for Cygwin version of gcc,
+ ac_cv_cygwin,
+AC_TRY_COMPILE([
+#ifdef __CYGWIN__
+#error cygwin
+#endif
+],
+[],
+ ac_cv_cygwin=no,
+ ac_cv_cygwin=yes)
+)
if test "$ac_cv_cygwin" = "yes" ; then
AC_MSG_ERROR([Compiling under Cygwin is not currently supported.
A maintainer for the Cygwin port of Tcl/Tk is needed. See the README
@@ -260,6 +261,50 @@ if test "$tcl_struct_stat32i64" = "yes" ; then
fi
+# See if declarations like FINDEX_INFO_LEVELS are
+# missing from winbase.h. This is known to be
+# a problem with VC++ 5.2.
+
+AC_CACHE_CHECK(for FINDEX_INFO_LEVELS in winbase.h,
+ tcl_cv_findex_enums,
+AC_TRY_COMPILE([
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+],
+[
+ FINDEX_INFO_LEVELS i;
+ FINDEX_SEARCH_OPS j;
+],
+ tcl_cv_findex_enums=yes,
+ tcl_cv_findex_enums=no)
+)
+if test "$tcl_cv_findex_enums" = "no"; then
+ AC_DEFINE(HAVE_NO_FINDEX_ENUMS, 1,
+ [Defined when enums are missing from winbase.h])
+fi
+
+# See if MWMO_ALERTABLE is missing from winuser.h
+# This is known to be a problem with Mingw.
+
+AC_CACHE_CHECK(for MWMO_ALERTABLE in winuser.h,
+ tcl_cv_mwmo_alertable,
+AC_TRY_COMPILE([
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+],
+[
+ int i = MWMO_ALERTABLE;
+],
+ tcl_cv_mwmo_alertable=yes,
+ tcl_cv_mwmo_alertable=no)
+)
+if test "$tcl_cv_mwmo_alertable" = "no"; then
+ AC_DEFINE(HAVE_NO_MWMO_ALERTABLE, 1,
+ [Defined when MWMO_ALERTABLE is missing from winuser.h])
+fi
+
#--------------------------------------------------------------------
# Determines the correct binary file extension (.o, .obj, .exe etc.)
#--------------------------------------------------------------------
@@ -273,6 +318,12 @@ AC_EXEEXT
SC_ENABLE_THREADS
+#------------------------------------------------------------------------
+# Embedded configuration information, encoding to use for the values, TIP #59
+#------------------------------------------------------------------------
+
+SC_TCL_CFG_ENCODING
+
#--------------------------------------------------------------------
# The statements below define a collection of symbols related to
# building libtcl as a shared library instead of a static library.
@@ -288,6 +339,37 @@ SC_ENABLE_SHARED
SC_CONFIG_CFLAGS
+AC_CHECK_TYPE([intptr_t], [
+ AC_DEFINE([HAVE_INTPTR_T], 1, [Do we have the intptr_t type?])], [
+ AC_CACHE_CHECK([for pointer-size signed integer type], tcl_cv_intptr_t, [
+ for tcl_cv_intptr_t in "int" "long" "long long" none; do
+ if test "$tcl_cv_intptr_t" != none; then
+ AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT],
+ [[sizeof (void *) <= sizeof ($tcl_cv_intptr_t)]])],
+ [tcl_ok=yes], [tcl_ok=no])
+ test "$tcl_ok" = yes && break; fi
+ done])
+ if test "$tcl_cv_intptr_t" != none; then
+ AC_DEFINE_UNQUOTED([intptr_t], [$tcl_cv_intptr_t], [Signed integer
+ type wide enough to hold a pointer.])
+ fi
+])
+AC_CHECK_TYPE([uintptr_t], [
+ AC_DEFINE([HAVE_UINTPTR_T], 1, [Do we have the uintptr_t type?])], [
+ AC_CACHE_CHECK([for pointer-size unsigned integer type], tcl_cv_uintptr_t, [
+ for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \
+ none; do
+ if test "$tcl_cv_uintptr_t" != none; then
+ AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT],
+ [[sizeof (void *) <= sizeof ($tcl_cv_uintptr_t)]])],
+ [tcl_ok=yes], [tcl_ok=no])
+ test "$tcl_ok" = yes && break; fi
+ done])
+ if test "$tcl_cv_uintptr_t" != none; then
+ AC_DEFINE_UNQUOTED([uintptr_t], [$tcl_cv_uintptr_t], [Unsigned integer
+ type wide enough to hold a pointer.])
+ fi
+])
#--------------------------------------------------------------------
# Set the default compiler switches based on the --enable-symbols
# option. This macro depends on C flags, and should be called
@@ -299,11 +381,10 @@ SC_ENABLE_SYMBOLS
TCL_DBGX=${DBGX}
#--------------------------------------------------------------------
-# man2tcl needs this so that it can use errno.h
+# Embed the manifest if we can determine how
#--------------------------------------------------------------------
-AC_CHECK_HEADER(errno.h, , MAN2TCLFLAGS="-DNO_ERRNO_H")
-AC_SUBST(MAN2TCLFLAGS)
+SC_EMBED_MANIFEST
#------------------------------------------------------------------------
# tclConfig.sh refers to this by a different name
@@ -449,7 +530,6 @@ AC_SUBST(TCL_NEEDS_EXP_FILE)
AC_SUBST(TCL_BUILD_EXP_FILE)
AC_SUBST(TCL_EXP_FILE)
AC_SUBST(DL_LIBS)
-AC_SUBST(LIBOBJS)
AC_SUBST(TCL_LIB_VERSIONS_OK)
AC_SUBST(TCL_PACKAGE_PATH)
@@ -457,9 +537,11 @@ AC_SUBST(TCL_PACKAGE_PATH)
AC_SUBST(TCL_DDE_VERSION)
AC_SUBST(TCL_DDE_MAJOR_VERSION)
AC_SUBST(TCL_DDE_MINOR_VERSION)
+AC_SUBST(TCL_DDE_PATCH_LEVEL)
AC_SUBST(TCL_REG_VERSION)
AC_SUBST(TCL_REG_MAJOR_VERSION)
AC_SUBST(TCL_REG_MINOR_VERSION)
+AC_SUBST(TCL_REG_PATCH_LEVEL)
AC_SUBST(RC)
AC_SUBST(RC_OUT)
diff --git a/win/makefile.bc b/win/makefile.bc
index 3c0ea73..6ba4420 100644
--- a/win/makefile.bc
+++ b/win/makefile.bc
@@ -7,7 +7,17 @@
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
+
+# TIP #59 information.
+#
+# This makefile does not set the following configuration cpp
+# defines. Behind the defines are the makefile variables listed to set
+# to -D... when that feature is enabled.
#
+# - TCL_CFG_PROFILED PROFDEFINES
+# - TCL_CFG_OPTIMIZED OPTDEFINES
+# - TCL_CFG_DO64BIT SIXFOURDEFINES
+
# Have a look at the complete description on how to build and test Tcl with
# the current Borland compilers at www.ratiosoft.com/tcl/borland.
#
@@ -88,6 +98,13 @@ libpath32 = -L"$(TOOLS32)\lib"
NODEBUG = 1
!endif
+# CFG_ENCODING=encoding
+# name of encoding for configuration information. Defaults
+# to cp1252
+!if !defined(CFG_ENCODING)
+CFG_ENCODING = \"cp1252\"
+!endif
+
# The following defines can be used to control the amount of debugging
# code that is added to the compilation.
#
@@ -107,23 +124,25 @@ NODEBUG = 1
NAMEPREFIX = tcl
STUBPREFIX = $(NAMEPREFIX)stub
-DOTVERSION = 8.4
-VERSION = 84
+DOTVERSION = 8.5
+VERSION = 85
-DDEVERSION = 12
-DDEDOTVERSION = 1.2
+DDEVERSION = 13
+DDEDOTVERSION = 1.3
-REGVERSION = 11
-REGDOTVERSION = 1.1
+REGVERSION = 12
+REGDOTVERSION = 1.2
BINROOT = ..
!IF "$(NODEBUG)" == "1"
TMPDIRNAME = Release
DBGX =
+SYMDEFINES =
!ELSE
TMPDIRNAME = Debug
#DBGX = d
DBGX =
+SYMDEFINES = -DTCL_CFG_DEBUG
!ENDIF
TMPDIR = $(BINROOT)\$(TMPDIRNAME)
OUTDIRNAME = $(TMPDIRNAME)
@@ -174,9 +193,6 @@ TCLOBJS = \
$(TMPDIR)\regexec.obj \
$(TMPDIR)\regfree.obj \
$(TMPDIR)\regerror.obj \
- $(TMPDIR)\strftime.obj \
- $(TMPDIR)\strtoll.obj \
- $(TMPDIR)\strtoull.obj \
$(TMPDIR)\tclAlloc.obj \
$(TMPDIR)\tclAsync.obj \
$(TMPDIR)\tclBasic.obj \
@@ -189,7 +205,9 @@ TCLOBJS = \
$(TMPDIR)\tclCompCmds.obj \
$(TMPDIR)\tclCompExpr.obj \
$(TMPDIR)\tclCompile.obj \
+ $(TMPDIR)\tclConfig.obj \
$(TMPDIR)\tclDate.obj \
+ $(TMPDIR)\tclDictObj.obj \
$(TMPDIR)\tclEncoding.obj \
$(TMPDIR)\tclEnv.obj \
$(TMPDIR)\tclEvent.obj \
@@ -216,9 +234,9 @@ TCLOBJS = \
$(TMPDIR)\tclObj.obj \
$(TMPDIR)\tclPanic.obj \
$(TMPDIR)\tclParse.obj \
- $(TMPDIR)\tclParseExpr.obj \
$(TMPDIR)\tclPipe.obj \
$(TMPDIR)\tclPkg.obj \
+ $(TMPDIR)\tclPkgConfig.obj \
$(TMPDIR)\tclPosixStr.obj \
$(TMPDIR)\tclPreserve.obj \
$(TMPDIR)\tclProc.obj \
@@ -232,6 +250,7 @@ TCLOBJS = \
$(TMPDIR)\tclThread.obj \
$(TMPDIR)\tclThreadJoin.obj \
$(TMPDIR)\tclTimer.obj \
+ $(TMPDIR)\tclTrace.obj \
$(TMPDIR)\tclUtf.obj \
$(TMPDIR)\tclUtil.obj \
$(TMPDIR)\tclVar.obj \
@@ -244,7 +263,6 @@ TCLOBJS = \
$(TMPDIR)\tclWinFile.obj \
$(TMPDIR)\tclWinInit.obj \
$(TMPDIR)\tclWinLoad.obj \
- $(TMPDIR)\tclWinMtherr.obj \
$(TMPDIR)\tclWinNotify.obj \
$(TMPDIR)\tclWinPipe.obj \
$(TMPDIR)\tclWinSock.obj \
@@ -257,7 +275,9 @@ WINDIR = $(ROOT)\win
GENERICDIR = $(ROOT)\generic
TCL_INCLUDES = -I"$(WINDIR)" -I"$(GENERICDIR)"
-TCL_DEFINES = $(DEBUGDEFINES) $(THREADDEFINES)
+TCL_DEFINES = $(DEBUGDEFINES) $(THREADDEFINES) $(SYMDEFINES) \
+ $(PROFDEFINES) $(OPTDEFINES) $(SIXFOURDEFINES) \
+ -DTCL_CFGVAL_ENCODING=${CFG_ENCODING}
######################################################################
# Compiler flags
@@ -400,30 +420,35 @@ install-libraries:
-@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\http1.0"
-@copy "$(ROOT)\library\http1.0\http.tcl" "$(SCRIPT_INSTALL_DIR)\http1.0"
-@copy "$(ROOT)\library\http1.0\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\http1.0"
- @echo installing http2.5
- -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\http2.5"
- -@copy "$(ROOT)\library\http\http.tcl" "$(SCRIPT_INSTALL_DIR)\http2.5"
- -@copy "$(ROOT)\library\http\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\http2.5"
+ @echo installing http2.7
+ -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\http2.7"
+ -@copy "$(ROOT)\library\http\http.tcl" "$(SCRIPT_INSTALL_DIR)\http2.7"
+ -@copy "$(ROOT)\library\http\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\http2.7"
@echo installing opt0.4
-@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\opt0.4"
-@copy "$(ROOT)\library\opt\optparse.tcl" "$(SCRIPT_INSTALL_DIR)\opt0.4"
-@copy "$(ROOT)\library\opt\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\opt0.4"
- @echo installing msgcat1.3
- -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\msgcat1.3"
- -@copy "$(ROOT)\library\msgcat\msgcat.tcl" "$(SCRIPT_INSTALL_DIR)\msgcat1.3"
- -@copy "$(ROOT)\library\msgcat\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\msgcat1.3"
- @echo installing tcltest2.2
- -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\tcltest2.2"
- -@copy "$(ROOT)\library\tcltest\tcltest.tcl" "$(SCRIPT_INSTALL_DIR)\tcltest2.2"
- -@copy "$(ROOT)\library\tcltest\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\tcltest2.2"
+ @echo installing msgcat1.4
+ -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\msgcat1.4"
+ -@copy "$(ROOT)\library\msgcat\msgcat.tcl" "$(SCRIPT_INSTALL_DIR)\msgcat1.4"
+ -@copy "$(ROOT)\library\msgcat\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\msgcat1.4"
+ @echo installing tcltest2.3
+ -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\tcltest2.3"
+ -@copy "$(ROOT)\library\tcltest\tcltest.tcl" "$(SCRIPT_INSTALL_DIR)\tcltest2.3"
+ -@copy "$(ROOT)\library\tcltest\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\tcltest2.3"
+ @echo installing platform1.0
+ -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\platform1.0"
+ -@copy "$(ROOT)\library\platform\platform.tcl" "$(SCRIPT_INSTALL_DIR)\platform1.0"
+ -@copy "$(ROOT)\library\platform\shell.tcl" "$(SCRIPT_INSTALL_DIR)\platform1.0"
+ -@copy "$(ROOT)\library\platform\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\platform1.0"
@echo installing $(TCLDDEDLLNAME)
- -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\dde1.1"
- -@copy "$(TCLDDEDLL)" "$(SCRIPT_INSTALL_DIR)\dde1.1"
- -@copy "$(ROOT)\library\dde\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\dde1.1"
+ -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\dde1.3"
+ -@copy "$(TCLDDEDLL)" "$(SCRIPT_INSTALL_DIR)\dde1.3"
+ -@copy "$(ROOT)\library\dde\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\dde1.3"
@echo installing $(TCLREGDLLNAME)
- -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\reg1.1"
- -@copy "$(TCLREGDLL)" "$(SCRIPT_INSTALL_DIR)\reg1.1"
- -@copy "$(ROOT)\library\reg\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\reg1.1"
+ -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\reg1.2"
+ -@copy "$(TCLREGDLL)" "$(SCRIPT_INSTALL_DIR)\reg1.2"
+ -@copy "$(ROOT)\library\reg\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\reg1.2"
@echo installing encoding files
-@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\encoding"
-@copy "$(ROOT)\library\encoding\*.enc" "$(SCRIPT_INSTALL_DIR)\encoding"
@@ -433,7 +458,6 @@ install-libraries:
-@copy "$(GENERICDIR)\tclPlatDecls.h" "$(INCLUDE_INSTALL_DIR)"
-@copy "$(ROOT)\library\history.tcl" "$(SCRIPT_INSTALL_DIR)"
-@copy "$(ROOT)\library\init.tcl" "$(SCRIPT_INSTALL_DIR)"
- -@copy "$(ROOT)\library\ldAout.tcl" "$(SCRIPT_INSTALL_DIR)"
-@copy "$(ROOT)\library\parray.tcl" "$(SCRIPT_INSTALL_DIR)"
-@copy "$(ROOT)\library\safe.tcl" "$(SCRIPT_INSTALL_DIR)"
-@copy "$(ROOT)\library\tclIndex" "$(SCRIPT_INSTALL_DIR)"
@@ -490,6 +514,14 @@ $(TMPDIR)\tclTestObj.obj: $(GENERICDIR)\tclTestObj.c
$(TMPDIR)\tclWinTest.obj: $(WINDIR)\tclWinTest.c
$(cc32) $(TCL_CFLAGS) -o$(TMPDIR)\$@ $?
+$(TMP_DIR)\tclPkgConfig.obj: $(GENERICDIR)\tclPkgConfig.c
+ $(cc32) $(TCL_CFLAGS) \
+ -DCFG_INSTALL_EXEC_PREFIX=\"$(INSTALL_EXEC_PREFIX)\" \
+ -DCFG_INSTALL_PREFIX=\"$(INSTALL_PREFIX)\" \
+ -DCFG_RUNTIME_EXEC_PREFIX=\"$(RUNTIME_EXEC_PREFIX)\" \
+ -DCFG_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \
+ -o$(TMPDIR)\$@ $?
+
$(TMPDIR)\tclAppInit.obj : $(WINDIR)\tclAppInit.c
$(cc32) $(TCL_CFLAGS) -o$(TMPDIR)\$@ $?
diff --git a/win/makefile.vc b/win/makefile.vc
index 426c907..d982284 100644
--- a/win/makefile.vc
+++ b/win/makefile.vc
@@ -1,4 +1,4 @@
-#------------------------------------------------------------------------------
+#------------------------------------------------------------- -*- makefile -*-
# makefile.vc --
#
# Microsoft Visual C++ makefile for use with nmake.exe v1.62+ (VC++ 5.0+)
@@ -9,7 +9,8 @@
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 Ajuba Solutions.
# Copyright (c) 2001-2005 ActiveState Corporation.
-# Copyright (c) 2001-2002 David Gravereaux.
+# Copyright (c) 2001-2004 David Gravereaux.
+# Copyright (c) 2003-2008 Pat Thoyts.
#------------------------------------------------------------------------------
# Check to see we are configured to build with MSVC (MSDEVDIR or MSVCDIR)
@@ -66,26 +67,30 @@ the build instructions.
# Sets where to install Tcl from the built binaries.
# C:\Progra~1\Tcl is assumed when not specified.
#
-# OPTS=static,msvcrt,staticpkg,threads,symbols,profile,loimpact,none
+# OPTS=static,msvcrt,staticpkg,threads,symbols,profile,loimpact,unchecked,none
# Sets special options for the core. The default is for none.
# Any combination of the above may be used (comma separated).
# 'none' will over-ride everything to nothing.
#
# static = Builds a static library of the core instead of a
# dll. The shell will be static (and large), as well.
-# msvcrt = Effects the static option only to switch it from
+# msvcrt = Affects the static option only to switch it from
# using libcmt(d) as the C runtime [by default] to
# msvcrt(d). This is useful for static embedding
# support.
-# staticpkg = Effects the static option only to switch
+# staticpkg = Affects the static option only to switch
# tclshXX.exe to have the dde and reg extension linked
# inside it.
# threads = Turns on full multithreading support.
# thrdalloc = Use the thread allocator (shared global free pool).
+# thrdstorage = Use the generic thread storage support.
# symbols = Adds symbols for step debugging.
# profile = Adds profiling hooks. Map file is assumed.
# loimpact = Adds a flag for how NT treats the heap to keep memory
# in use, low. This is said to impact alloc performance.
+# unchecked = Allows a symbols build to not use the debug
+# enabled runtime (msvcrt.dll not msvcrtd.dll
+# or libcmt.lib not libcmtd.lib).
#
# STATS=memdbg,compdbg,none
# Sets optional memory and bytecode compiler debugging code added
@@ -96,6 +101,15 @@ the build instructions.
# memdbg = Enables the debugging memory allocator.
# compdbg = Enables byte compilation logging.
#
+# CHECKS=nodep,fullwarn,64bit,none
+# Sets special macros for checking compatability.
+#
+# nodep = Turns off compatability macros to ensure the core
+# isn't being built with deprecated functions.
+# fullwarn = Builds with full compiler and link warnings enabled.
+# Very verbose.
+# 64bit = Enable 64bit portability warnings (if available)
+#
# MACHINE=(IX86|IA64|AMD64|ALPHA)
# Set the machine type used for the compiler, linker, and
# resource compiler. This hook is needed to tell the tools
@@ -112,6 +126,10 @@ the build instructions.
# TESTPAT=<file>
# Reads the tests requested to be run from this file.
#
+# CFG_ENCODING=encoding
+# name of encoding for configuration information. Defaults
+# to cp1252
+#
# 5) Examples:
#
# Basic syntax of calling nmake looks like this:
@@ -156,14 +174,14 @@ Please `cd` to its location first.
PROJECT = tcl
!include "rules.vc"
-STUBPREFIX = $(PROJECT)stub
-DOTVERSION = 8.4
-VERSION = $(DOTVERSION:.=)
+STUBPREFIX = $(PROJECT)stub
+DOTVERSION = $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)
+VERSION = $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION)
-DDEDOTVERSION = 1.2
+DDEDOTVERSION = 1.3
DDEVERSION = $(DDEDOTVERSION:.=)
-REGDOTVERSION = 1.1
+REGDOTVERSION = 1.2
REGVERSION = $(REGDOTVERSION:.=)
BINROOT = .
@@ -190,6 +208,15 @@ TCLDDELIB = $(OUT_DIR)\$(TCLDDELIBNAME)
TCLTEST = $(OUT_DIR)\$(PROJECT)test.exe
CAT32 = $(OUT_DIR)\cat32.exe
+# Can we run what we build? IX86 runs on all architectures.
+!ifndef TCLSH_NATIVE
+!if "$(MACHINE)" == "IX86" || "$(MACHINE)" == "$(NATIVE_ARCH)"
+TCLSH_NATIVE = $(TCLSH)
+!else
+!error You must explicitly set TCLSH_NATIVE for cross-compilation
+!endif
+!endif
+
### Make sure we use backslash only.
LIB_INSTALL_DIR = $(_INSTALLDIR)\lib
BIN_INSTALL_DIR = $(_INSTALLDIR)\bin
@@ -222,9 +249,6 @@ TCLOBJS = \
$(TMP_DIR)\regerror.obj \
$(TMP_DIR)\regexec.obj \
$(TMP_DIR)\regfree.obj \
- $(TMP_DIR)\strftime.obj \
- $(TMP_DIR)\strtoll.obj \
- $(TMP_DIR)\strtoull.obj \
$(TMP_DIR)\tclAlloc.obj \
$(TMP_DIR)\tclAsync.obj \
$(TMP_DIR)\tclBasic.obj \
@@ -237,7 +261,9 @@ TCLOBJS = \
$(TMP_DIR)\tclCompCmds.obj \
$(TMP_DIR)\tclCompExpr.obj \
$(TMP_DIR)\tclCompile.obj \
+ $(TMP_DIR)\tclConfig.obj \
$(TMP_DIR)\tclDate.obj \
+ $(TMP_DIR)\tclDictObj.obj \
$(TMP_DIR)\tclEncoding.obj \
$(TMP_DIR)\tclEnv.obj \
$(TMP_DIR)\tclEvent.obj \
@@ -254,6 +280,7 @@ TCLOBJS = \
$(TMP_DIR)\tclIOGT.obj \
$(TMP_DIR)\tclIOSock.obj \
$(TMP_DIR)\tclIOUtil.obj \
+ $(TMP_DIR)\tclIORChan.obj \
$(TMP_DIR)\tclLink.obj \
$(TMP_DIR)\tclListObj.obj \
$(TMP_DIR)\tclLiteral.obj \
@@ -264,9 +291,10 @@ TCLOBJS = \
$(TMP_DIR)\tclObj.obj \
$(TMP_DIR)\tclPanic.obj \
$(TMP_DIR)\tclParse.obj \
- $(TMP_DIR)\tclParseExpr.obj \
+ $(TMP_DIR)\tclPathObj.obj \
$(TMP_DIR)\tclPipe.obj \
$(TMP_DIR)\tclPkg.obj \
+ $(TMP_DIR)\tclPkgConfig.obj \
$(TMP_DIR)\tclPosixStr.obj \
$(TMP_DIR)\tclPreserve.obj \
$(TMP_DIR)\tclProc.obj \
@@ -275,12 +303,16 @@ TCLOBJS = \
$(TMP_DIR)\tclResult.obj \
$(TMP_DIR)\tclScan.obj \
$(TMP_DIR)\tclStringObj.obj \
+ $(TMP_DIR)\tclStrToD.obj \
$(TMP_DIR)\tclStubInit.obj \
$(TMP_DIR)\tclStubLib.obj \
$(TMP_DIR)\tclThread.obj \
$(TMP_DIR)\tclThreadAlloc.obj \
$(TMP_DIR)\tclThreadJoin.obj \
+ $(TMP_DIR)\tclThreadStorage.obj \
$(TMP_DIR)\tclTimer.obj \
+ $(TMP_DIR)\tclTomMathInterface.obj \
+ $(TMP_DIR)\tclTrace.obj \
$(TMP_DIR)\tclUtf.obj \
$(TMP_DIR)\tclUtil.obj \
$(TMP_DIR)\tclVar.obj \
@@ -293,12 +325,75 @@ TCLOBJS = \
$(TMP_DIR)\tclWinFile.obj \
$(TMP_DIR)\tclWinInit.obj \
$(TMP_DIR)\tclWinLoad.obj \
- $(TMP_DIR)\tclWinMtherr.obj \
$(TMP_DIR)\tclWinNotify.obj \
$(TMP_DIR)\tclWinPipe.obj \
$(TMP_DIR)\tclWinSock.obj \
$(TMP_DIR)\tclWinThrd.obj \
$(TMP_DIR)\tclWinTime.obj \
+ $(TMP_DIR)\bncore.obj \
+ $(TMP_DIR)\bn_reverse.obj \
+ $(TMP_DIR)\bn_fast_s_mp_mul_digs.obj \
+ $(TMP_DIR)\bn_fast_s_mp_sqr.obj \
+ $(TMP_DIR)\bn_mp_add.obj \
+ $(TMP_DIR)\bn_mp_add_d.obj \
+ $(TMP_DIR)\bn_mp_and.obj \
+ $(TMP_DIR)\bn_mp_clamp.obj \
+ $(TMP_DIR)\bn_mp_clear.obj \
+ $(TMP_DIR)\bn_mp_clear_multi.obj \
+ $(TMP_DIR)\bn_mp_cmp.obj \
+ $(TMP_DIR)\bn_mp_cmp_d.obj \
+ $(TMP_DIR)\bn_mp_cmp_mag.obj \
+ $(TMP_DIR)\bn_mp_cnt_lsb.obj \
+ $(TMP_DIR)\bn_mp_copy.obj \
+ $(TMP_DIR)\bn_mp_count_bits.obj \
+ $(TMP_DIR)\bn_mp_div.obj \
+ $(TMP_DIR)\bn_mp_div_d.obj \
+ $(TMP_DIR)\bn_mp_div_2.obj \
+ $(TMP_DIR)\bn_mp_div_2d.obj \
+ $(TMP_DIR)\bn_mp_div_3.obj \
+ $(TMP_DIR)\bn_mp_exch.obj \
+ $(TMP_DIR)\bn_mp_expt_d.obj \
+ $(TMP_DIR)\bn_mp_grow.obj \
+ $(TMP_DIR)\bn_mp_init.obj \
+ $(TMP_DIR)\bn_mp_init_copy.obj \
+ $(TMP_DIR)\bn_mp_init_multi.obj \
+ $(TMP_DIR)\bn_mp_init_set.obj \
+ $(TMP_DIR)\bn_mp_init_set_int.obj \
+ $(TMP_DIR)\bn_mp_init_size.obj \
+ $(TMP_DIR)\bn_mp_karatsuba_mul.obj \
+ $(TMP_DIR)\bn_mp_karatsuba_sqr.obj \
+ $(TMP_DIR)\bn_mp_lshd.obj \
+ $(TMP_DIR)\bn_mp_mod.obj \
+ $(TMP_DIR)\bn_mp_mod_2d.obj \
+ $(TMP_DIR)\bn_mp_mul.obj \
+ $(TMP_DIR)\bn_mp_mul_2.obj \
+ $(TMP_DIR)\bn_mp_mul_2d.obj \
+ $(TMP_DIR)\bn_mp_mul_d.obj \
+ $(TMP_DIR)\bn_mp_neg.obj \
+ $(TMP_DIR)\bn_mp_or.obj \
+ $(TMP_DIR)\bn_mp_radix_size.obj \
+ $(TMP_DIR)\bn_mp_radix_smap.obj \
+ $(TMP_DIR)\bn_mp_read_radix.obj \
+ $(TMP_DIR)\bn_mp_rshd.obj \
+ $(TMP_DIR)\bn_mp_set.obj \
+ $(TMP_DIR)\bn_mp_set_int.obj \
+ $(TMP_DIR)\bn_mp_shrink.obj \
+ $(TMP_DIR)\bn_mp_sqr.obj \
+ $(TMP_DIR)\bn_mp_sqrt.obj \
+ $(TMP_DIR)\bn_mp_sub.obj \
+ $(TMP_DIR)\bn_mp_sub_d.obj \
+ $(TMP_DIR)\bn_mp_to_unsigned_bin.obj \
+ $(TMP_DIR)\bn_mp_to_unsigned_bin_n.obj \
+ $(TMP_DIR)\bn_mp_toom_mul.obj \
+ $(TMP_DIR)\bn_mp_toom_sqr.obj \
+ $(TMP_DIR)\bn_mp_toradix_n.obj \
+ $(TMP_DIR)\bn_mp_unsigned_bin_size.obj \
+ $(TMP_DIR)\bn_mp_xor.obj \
+ $(TMP_DIR)\bn_mp_zero.obj \
+ $(TMP_DIR)\bn_s_mp_add.obj \
+ $(TMP_DIR)\bn_s_mp_mul_digs.obj \
+ $(TMP_DIR)\bn_s_mp_sqr.obj \
+ $(TMP_DIR)\bn_s_mp_sub.obj \
!if !$(STATIC_BUILD)
$(TMP_DIR)\tcl.res
!endif
@@ -309,6 +404,7 @@ TCLSTUBOBJS = $(TMP_DIR)\tclStubLib.obj
COMPATDIR = $(ROOT)\compat
DOCDIR = $(ROOT)\doc
GENERICDIR = $(ROOT)\generic
+TOMMATHDIR = $(ROOT)\libtommath
TOOLSDIR = $(ROOT)\tools
WINDIR = $(ROOT)\win
@@ -324,6 +420,9 @@ cdebug = -O2 $(OPTIMIZATIONS)
!else
cdebug =
!endif
+!if $(SYMBOLS)
+cdebug = $(cdebug) -Zi
+!endif
!else if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64"
### Warnings are too many, can't support warnings into errors.
cdebug = -Zi -Od $(DEBUGFLAGS)
@@ -332,34 +431,30 @@ cdebug = -Zi -WX $(DEBUGFLAGS)
!endif
### Declarations common to all compiler options
-cwarn = -D _CRT_SECURE_NO_DEPRECATE -D _CRT_NONSTDC_NO_DEPRECATE
+cwarn = $(WARNINGS) -D _CRT_SECURE_NO_DEPRECATE -D _CRT_NONSTDC_NO_DEPRECATE
cflags = -nologo -c $(COMPILERFLAGS) $(cwarn) -Fp$(TMP_DIR)^\
-!if $(FULLWARNINGS)
-cflags = $(cflags) -W4
-!else
-cflags = $(cflags) -W3
-!endif
-
!if $(MSVCRT)
-!if "$(DBGX)" == ""
-crt = -MD
-!else
+!if $(DEBUG) && !$(UNCHECKED)
crt = -MDd
-!endif
!else
-!if "$(DBGX)" == ""
-crt = -MT
+crt = -MD
+!endif
!else
+!if $(DEBUG) && !$(UNCHECKED)
crt = -MTd
+!else
+crt = -MT
!endif
!endif
-TCL_INCLUDES = -I"$(WINDIR)" -I"$(GENERICDIR)"
-BASE_CFLAGS = $(cflags) $(cdebug) $(crt) $(TCL_INCLUDES) \
- -DTCL_PIPE_DLL=\"$(TCLPIPEDLLNAME)\"
+TCL_INCLUDES = -I"$(WINDIR)" -I"$(GENERICDIR)" -I"$(TOMMATHDIR)"
+TCL_DEFINES = -DTCL_PIPE_DLL=\"$(TCLPIPEDLLNAME)\" -DTCL_TOMMATH -DMP_PREC=4 -Dinline=__inline
+BASE_CFLAGS = $(cflags) $(cdebug) $(crt) $(TCL_INCLUDES) $(TCL_DEFINES)
CON_CFLAGS = $(cflags) $(cdebug) $(crt) -DCONSOLE
TCL_CFLAGS = $(BASE_CFLAGS) $(OPTDEFINES)
+### Stubs files should not be compiled with -GL
+STUB_CFLAGS = $(cflags) $(cdebug:-GL=) $(OPTDEFINES)
#---------------------------------------------------------------------
@@ -370,15 +465,14 @@ TCL_CFLAGS = $(BASE_CFLAGS) $(OPTDEFINES)
ldebug = -debug -debugtype:cv
!else
ldebug = -release -opt:ref -opt:icf,3
+!if $(SYMBOLS)
+ldebug = $(ldebug) -debug -debugtype:cv
+!endif
!endif
### Declarations common to all linker options
lflags = -nologo -machine:$(MACHINE) $(LINKERFLAGS) $(ldebug)
-!if $(FULLWARNINGS)
-lflags = $(lflags) -warn:3
-!endif
-
!if $(PROFILE)
lflags = $(lflags) -profile
!endif
@@ -399,12 +493,14 @@ dlllflags = $(lflags) -dll
conlflags = $(lflags) -subsystem:console
guilflags = $(lflags) -subsystem:windows
-baselibs = kernel32.lib advapi32.lib user32.lib
+baselibs = kernel32.lib user32.lib ws2_32.lib
# Avoid 'unresolved external symbol __security_cookie' errors.
# c.f. http://support.microsoft.com/?id=894573
!if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64"
+!if $(VCVERSION) > 1399 && $(VCVERSION) < 1500
baselibs = $(baselibs) bufferoverflowU.lib
!endif
+!endif
#---------------------------------------------------------------------
# TclTest flags
@@ -431,15 +527,22 @@ install: install-binaries install-libraries install-docs
test: setup $(TCLTEST) dlls $(CAT32)
set TCL_LIBRARY=$(ROOT)/library
!if "$(OS)" == "Windows_NT" || "$(MSVCDIR)" == "IDE"
- $(TCLTEST) "$(ROOT)/tests/all.tcl" $(TESTFLAGS)
+ $(TCLTEST) "$(ROOT)/tests/all.tcl" $(TESTFLAGS) -loadfile <<
+ set ::ddelib [file normalize $(TCLDDELIB:\=/)]
+ set ::reglib [file normalize $(TCLREGLIB:\=/)]
+<<
!else
- $(TCLTEST) "$(ROOT)/tests/all.tcl" $(TESTFLAGS) > tests.log
+ @echo Please wait while the tests are collected...
+ $(TCLTEST) "$(ROOT)/tests/all.tcl" $(TESTFLAGS) -loadfile << > tests.log
+ set ::ddelib [file normalize $(TCLDDELIB:\=/)]
+ set ::reglib [file normalize $(TCLREGLIB:\=/)]
+<<
type tests.log | more
!endif
runtest: setup $(TCLTEST) dlls $(CAT32)
set TCL_LIBRARY=$(ROOT)/library
- $(TCLTEST)
+ $(DEBUGGER) $(TCLTEST)
setup:
@if not exist $(OUT_DIR)\nul mkdir $(OUT_DIR)
@@ -481,7 +584,7 @@ $(TCLPIPEDLL): $(WINDIR)\stub16.c
!if $(STATIC_BUILD)
$(TCLDDELIB): $(TMP_DIR)\tclWinDde.obj
- $(lib32) -nologo -out:$@ $(TMP_DIR)\tclWinDde.obj
+ $(lib32) -nologo -out:$@ $**
!else
$(TCLDDELIB): $(TMP_DIR)\tclWinDde.obj $(TCLSTUBLIB)
$(link32) $(dlllflags) -base:@$(WINDIR)\coffbase.txt,tcldde -out:$@ \
@@ -493,7 +596,7 @@ $(TCLDDELIB): $(TMP_DIR)\tclWinDde.obj $(TCLSTUBLIB)
!if $(STATIC_BUILD)
$(TCLREGLIB): $(TMP_DIR)\tclWinReg.obj
- $(lib32) -nologo -out:$@ $(TMP_DIR)\tclWinReg.obj
+ $(lib32) -nologo -out:$@ $**
!else
$(TCLREGLIB): $(TMP_DIR)\tclWinReg.obj $(TCLSTUBLIB)
$(link32) $(dlllflags) -base:@$(WINDIR)\coffbase.txt,tclreg -out:$@ \
@@ -517,27 +620,27 @@ genstubs:
!if !exist($(TCLSH))
@echo Build tclsh first!
!else
- $(TCLSH) $(TOOLSDIR:\=/)\genStubs.tcl $(GENERICDIR:\=/) \
- $(GENERICDIR:\=/)/tcl.decls $(GENERICDIR:\=/)/tclInt.decls
+ $(TCLSH) $(TOOLSDIR:\=/)/genStubs.tcl $(GENERICDIR:\=/) \
+ $(GENERICDIR:\=/)/tcl.decls $(GENERICDIR:\=/)/tclInt.decls \
+ $(GENERICDIR:\=/)/tclTomMath.decls
!endif
-#---------------------------------------------------------------------
-# Generate the makefile depedancies.
-#---------------------------------------------------------------------
+#----------------------------------------------------------------------
+# The following target generates the file generic/tclTomMath.h.
+# It needs to be run (and the results checked) after updating
+# to a new release of libtommath.
+#----------------------------------------------------------------------
-depend:
+gentommath_h:
!if !exist($(TCLSH))
@echo Build tclsh first!
!else
- $(TCLSH) $(TOOLSDIR:\=/)/mkdepend.tcl -vc32 -out:"$(OUT_DIR)\depend.mk" \
- -passthru:"-DBUILD_tcl $(TCL_INCLUDES:"="")" $(GENERICDIR) \
- $(COMPATDIR) $(WINDIR) @<<
-$(TCLOBJS)
-<<
+ $(TCLSH) "$(TOOLSDIR:\=/)/fix_tommath_h.tcl" \
+ "$(TOMMATHDIR:\=/)/tommath.h" \
+ > "$(GENERICDIR)\tclTomMath.h"
!endif
-
#---------------------------------------------------------------------
# Build the windows help file.
#---------------------------------------------------------------------
@@ -604,17 +707,91 @@ install-docs:
@$(CPY) "$(HELPCNT)" "$(DOC_INSTALL_DIR)\"
!endif
+#---------------------------------------------------------------------
+# Build tclConfig.sh for the TEA build system.
+#---------------------------------------------------------------------
+
+tclConfig: $(OUT_DIR)\tclConfig.sh
+
+$(OUT_DIR)\tclConfig.sh: $(WINDIR)\tclConfig.sh.in
+ @echo Creating tclConfig.sh
+ @nmakehlp -s << $** >$@
+@TCL_DLL_FILE@ $(TCLLIBNAME)
+@TCL_VERSION@ $(DOTVERSION)
+@TCL_MAJOR_VERSION@ $(TCL_MAJOR_VERSION)
+@TCL_MINOR_VERSION@ $(TCL_MINOR_VERSION)
+@TCL_PATCH_LEVEL@ $(TCL_PATCH_LEVEL)
+@CC@ $(CC)
+@DEFS@ $(TCL_CFLAGS)
+@CFLAGS_DEBUG@ -nologo -c -W3 -YX -Fp$(TMP_DIR)\ -MDd
+@CFLAGS_OPTIMIZE@ -nologo -c -W3 -YX -Fp$(TMP_DIR)\ -MD
+@LDFLAGS_DEBUG@ -nologo -machine:$(MACHINE) -debug -debugtype:cv
+@LDFLAGS_OPTIMIZE@ -nologo -machine:$(MACHINE) -release -opt:ref -opt:icf,3
+@TCL_DBGX@ $(SUFX)
+@TCL_LIB_FILE@ $(PROJECT)$(VERSION)$(SUFX).lib
+@TCL_NEEDS_EXP_FILE@
+@LIBS@ $(baselibs)
+@prefix@ $(_INSTALLDIR)
+@exec_prefix@ $(BIN_INSTALL_DIR)
+@SHLIB_CFLAGS@
+@STLIB_CFLAGS@
+@CFLAGS_WARNING@ -W3
+@EXTRA_CFLAGS@ -YX
+@SHLIB_LD@ $(link32) $(dlllflags)
+@STLIB_LD@ $(lib32) -nologo
+@SHLIB_LD_LIBS@ $(baselibs)
+@SHLIB_SUFFIX@ .dll
+@DL_LIBS@
+@LDFLAGS@
+@TCL_LD_SEARCH_FLAGS@
+@LIBOBJS@
+@RANLIB@
+@TCL_LIB_FLAG@
+@TCL_BUILD_LIB_SPEC@
+@TCL_LIB_SPEC@ $(LIB_INSTALL_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib
+@TCL_INCLUDE_SPEC@ -I$(INCLUDE_INSTALL_DIR)
+@TCL_LIB_VERSIONS_OK@
+@TCL_SRC_DIR@ $(ROOT)
+@TCL_PACKAGE_PATH@
+@TCL_STUB_LIB_FILE@ $(TCLSTUBLIBNAME)
+@TCL_STUB_LIB_FLAG@ $(TCLSTUBLIBNAME)
+@TCL_STUB_LIB_SPEC@ -L$(LIB_INSTALL_DIR) $(TCLSTUBLIBNAME)
+@TCL_THREADS@ $(TCL_THREADS)
+@TCL_BUILD_STUB_LIB_SPEC@ -L$(OUT_DIR) $(TCLSTUBLIBNAME)
+@TCL_BUILD_STUB_LIB_PATH@ $(TCLSTUBLIB)
+@TCL_STUB_LIB_PATH@ $(LIB_INSTALL_DIR)\$(TCLSTUBLIBNAME)
+@CFG_TCL_EXPORT_FILE_SUFFIX@ $(VERSION)$(SUFX).lib
+@CFG_TCL_SHARED_LIB_SUFFIX@ $(VERSION)$(SUFX).dll
+@CFG_TCL_UNSHARED_LIB_SUFFIX@ $(VERSION)$(SUFX).lib
+!if $(STATIC_BUILD)
+@TCL_SHARED_BUILD@ 0
+!else
+@TCL_SHARED_BUILD@ 1
+!endif
+<<
+
+
+#---------------------------------------------------------------------
+# The following target generates the file generic/tclDate.c
+# from the yacc grammar found in generic/tclGetDate.y. This is
+# only run by hand as yacc is not available in all environments.
+# The name of the .c file is different than the name of the .y file
+# so that make doesn't try to automatically regenerate the .c file.
+#---------------------------------------------------------------------
+
+gendate:
+ bison --output-file=$(GENERICDIR)/tclDate.c \
+ --name-prefix=TclDate \
+ $(GENERICDIR)/tclGetDate.y
#---------------------------------------------------------------------
# Special case object file targets
#---------------------------------------------------------------------
$(TMP_DIR)\testMain.obj: $(WINDIR)\tclAppInit.c
-!if $(TCL_USE_STATIC_PACKAGES)
- $(cc32) $(TCL_CFLAGS) -DTCL_TEST -DTCL_USE_STATIC_PACKAGES -Fo$@ $?
-!else
- $(cc32) $(TCL_CFLAGS) -DTCL_TEST -Fo$@ $?
-!endif
+ $(cc32) $(TCL_CFLAGS) -DTCL_TEST \
+ -DTCL_USE_STATIC_PACKAGES=$(TCL_USE_STATIC_PACKAGES) \
+ -Fo$@ $?
$(TMP_DIR)\tclTest.obj: $(GENERICDIR)\tclTest.c
$(cc32) $(TCL_CFLAGS) -Fo$@ $?
@@ -625,66 +802,77 @@ $(TMP_DIR)\tclTestObj.obj: $(GENERICDIR)\tclTestObj.c
$(TMP_DIR)\tclWinTest.obj: $(WINDIR)\tclWinTest.c
$(cc32) $(TCL_CFLAGS) -Fo$@ $?
+$(TMP_DIR)\tclPkgConfig.obj: $(GENERICDIR)\tclPkgConfig.c
+ $(cc32) -DBUILD_tcl $(TCL_CFLAGS) \
+ -DCFG_INSTALL_LIBDIR="\"$(LIB_INSTALL_DIR:\=\\)\"" \
+ -DCFG_INSTALL_BINDIR="\"$(BIN_INSTALL_DIR:\=\\)\"" \
+ -DCFG_INSTALL_SCRDIR="\"$(SCRIPT_INSTALL_DIR:\=\\)\"" \
+ -DCFG_INSTALL_INCDIR="\"$(INCLUDE_INSTALL_DIR:\=\\)\"" \
+ -DCFG_INSTALL_DOCDIR="\"$(DOC_INSTALL_DIR:\=\\)\"" \
+ -DCFG_RUNTIME_LIBDIR="\"$(LIB_INSTALL_DIR:\=\\)\"" \
+ -DCFG_RUNTIME_BINDIR="\"$(BIN_INSTALL_DIR:\=\\)\"" \
+ -DCFG_RUNTIME_SCRDIR="\"$(SCRIPT_INSTALL_DIR:\=\\)\"" \
+ -DCFG_RUNTIME_INCDIR="\"$(INCLUDE_INSTALL_DIR:\=\\)\"" \
+ -DCFG_RUNTIME_DOCDIR="\"$(DOC_INSTALL_DIR:\=\\)\"" \
+ -Fo$@ $?
+
$(TMP_DIR)\tclAppInit.obj: $(WINDIR)\tclAppInit.c
-!if $(TCL_USE_STATIC_PACKAGES)
- $(cc32) $(TCL_CFLAGS) -DTCL_USE_STATIC_PACKAGES -Fo$@ $?
-!else
- $(cc32) $(TCL_CFLAGS) -Fo$@ $?
-!endif
+ $(cc32) $(TCL_CFLAGS) \
+ -DTCL_USE_STATIC_PACKAGES=$(TCL_USE_STATIC_PACKAGES) \
+ -Fo$@ $?
### The following objects should be built using the stub interfaces
### *ALL* extensions need to built with -DTCL_THREADS=1
$(TMP_DIR)\tclWinReg.obj: $(WINDIR)\tclWinReg.c
!if $(STATIC_BUILD)
- $(cc32) $(BASE_CFLAGS) -DTCL_THREADS=1 -DSTATIC_BUILD -Fo$@ $?
+ $(cc32) $(TCL_CFLAGS) -DTCL_THREADS=1 -DSTATIC_BUILD -Fo$@ $?
!else
- $(cc32) $(BASE_CFLAGS) -DTCL_THREADS=1 -DUSE_TCL_STUBS -Fo$@ $?
+ $(cc32) $(TCL_CFLAGS) -DTCL_THREADS=1 -DUSE_TCL_STUBS -Fo$@ $?
!endif
$(TMP_DIR)\tclWinDde.obj: $(WINDIR)\tclWinDde.c
!if $(STATIC_BUILD)
- $(cc32) $(BASE_CFLAGS) -DTCL_THREADS=1 -DSTATIC_BUILD -Fo$@ $?
+ $(cc32) $(TCL_CFLAGS) -DTCL_THREADS=1 -DSTATIC_BUILD -Fo$@ $?
!else
- $(cc32) $(BASE_CFLAGS) -DTCL_THREADS=1 -DUSE_TCL_STUBS -Fo$@ $?
+ $(cc32) $(TCL_CFLAGS) -DTCL_THREADS=1 -DUSE_TCL_STUBS -Fo$@ $?
!endif
### The following objects are part of the stub library and should not
-### be built as DLL objects. -Zl is used to avoid a dependancy on any
+### be built as DLL objects. -Zl is used to avoid a dependency on any
### specific C run-time.
$(TMP_DIR)\tclStubLib.obj: $(GENERICDIR)\tclStubLib.c
- $(cc32) $(cdebug) $(cflags) -Zl -DSTATIC_BUILD $(TCL_INCLUDES) -Fo$@ $?
-
+ $(cc32) $(STUB_CFLAGS) -Zl -DSTATIC_BUILD $(TCL_INCLUDES) -Fo$@ $?
#---------------------------------------------------------------------
-# Dedependency rules
+# Generate the source dependencies. Having dependency rules will
+# improve incremental build accuracy without having to resort to a
+# full rebuild just because some non-global header file like
+# tclCompile.h was changed. These rules aren't needed when building
+# from scratch.
#---------------------------------------------------------------------
-$(GENERICDIR)\regcomp.c: \
- $(GENERICDIR)\regguts.h \
- $(GENERICDIR)\regc_lex.c \
- $(GENERICDIR)\regc_color.c \
- $(GENERICDIR)\regc_nfa.c \
- $(GENERICDIR)\regc_cvec.c \
- $(GENERICDIR)\regc_locale.c
-$(GENERICDIR)\regcustom.h: \
- $(GENERICDIR)\tclInt.h \
- $(GENERICDIR)\tclPort.h \
- $(GENERICDIR)\regex.h
-$(GENERICDIR)\regexec.c: \
- $(GENERICDIR)\rege_dfa.c \
- $(GENERICDIR)\regguts.h
-$(GENERICDIR)\regerror.c: $(GENERICDIR)\regguts.h
-$(GENERICDIR)\regfree.c: $(GENERICDIR)\regguts.h
-$(GENERICDIR)\regfronts.c: $(GENERICDIR)\regguts.h
-$(GENERICDIR)\regguts.h: $(GENERICDIR)\regcustom.h
+depend:
+!if !exist($(TCLSH))
+ @echo Build tclsh first!
+!else
+ $(TCLSH) $(TOOLSDIR:\=/)/mkdepend.tcl -vc32 -out:"$(OUT_DIR)\depend.mk" \
+ -passthru:"-DBUILD_tcl $(TCL_INCLUDES)" $(GENERICDIR),$$(GENERICDIR) \
+ $(COMPATDIR),$$(COMPATDIR) $(TOMMATHDIR),$$(TOMMATHDIR) $(WINDIR),$$(WINDIR) @<<
+$(TCLOBJS)
+<<
+!endif
+
+#---------------------------------------------------------------------
+# Dependency rules
+#---------------------------------------------------------------------
!if exist("$(OUT_DIR)\depend.mk")
!include "$(OUT_DIR)\depend.mk"
-!message *** Dependency rules in effect.
+!message *** Dependency rules in use.
!else
!message *** Dependency rules are not being used.
!endif
@@ -698,32 +886,31 @@ $(GENERICDIR)\regguts.h: $(GENERICDIR)\regcustom.h
#---------------------------------------------------------------------
{$(WINDIR)}.c{$(TMP_DIR)}.obj::
- $(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<<
+ $(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<<
+$<
+<<
+
+{$(TOMMATHDIR)}.c{$(TMP_DIR)}.obj::
+ $(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<<
$<
<<
{$(GENERICDIR)}.c{$(TMP_DIR)}.obj::
- $(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<<
+ $(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<<
$<
<<
{$(COMPATDIR)}.c{$(TMP_DIR)}.obj::
- $(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<<
+ $(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<<
$<
<<
{$(WINDIR)}.rc{$(TMP_DIR)}.res:
- $(rc32) -fo $@ -r -i "$(GENERICDIR)" -D__WIN32__ \
-!if $(DEBUG)
- -d DEBUG \
-!endif
-!if $(TCL_THREADS)
- -d TCL_THREADS \
-!endif
-!if $(STATIC_BUILD)
- -d STATIC_BUILD \
-!endif
- $<
+ $(rc32) -fo $@ -r -i "$(GENERICDIR)" \
+ -d DEBUG=$(DEBUG) -d UNCHECKED=$(UNCHECKED) \
+ -d TCL_THREADS=$(TCL_THREADS) \
+ -d STATIC_BUILD=$(STATIC_BUILD) \
+ $<
.SUFFIXES:
.SUFFIXES:.c .rc
@@ -735,79 +922,129 @@ $<
install-binaries:
@echo Installing to '$(_INSTALLDIR)'
- @echo installing $(TCLLIBNAME)
+ @echo Installing $(TCLLIBNAME)
!if "$(TCLLIB)" != "$(TCLIMPLIB)"
@$(CPY) "$(TCLLIB)" "$(BIN_INSTALL_DIR)\"
!endif
@$(CPY) "$(TCLIMPLIB)" "$(LIB_INSTALL_DIR)\"
!if exist($(TCLSH))
- @echo installing $(TCLSHNAME)
+ @echo Installing $(TCLSHNAME)
@$(CPY) "$(TCLSH)" "$(BIN_INSTALL_DIR)\"
!endif
!if exist($(TCLPIPEDLL))
- @echo installing $(TCLPIPEDLLNAME)
+ @echo Installing $(TCLPIPEDLLNAME)
@$(CPY) "$(TCLPIPEDLL)" "$(BIN_INSTALL_DIR)\"
!endif
- @echo installing $(TCLSTUBLIBNAME)
+ @echo Installing $(TCLSTUBLIBNAME)
@$(CPY) "$(TCLSTUBLIB)" "$(LIB_INSTALL_DIR)\"
-install-libraries:
- @echo installing http1.0
+#" emacs fix
+
+install-libraries: tclConfig install-msgs install-tzdata
+ @if not exist "$(SCRIPT_INSTALL_DIR)$(NULL)" \
+ $(MKDIR) "$(SCRIPT_INSTALL_DIR)"
+ @if not exist "$(SCRIPT_INSTALL_DIR)\..\tcl8$(NULL)" \
+ $(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8"
+ @if not exist "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.2$(NULL)" \
+ $(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.2"
+ @if not exist "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.3$(NULL)" \
+ $(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.3"
+ @if not exist "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.4$(NULL)" \
+ $(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.4"
+ @if not exist "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.4\platform$(NULL)" \
+ $(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.4\platform"
+ @if not exist "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.5$(NULL)" \
+ $(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.5"
+ @echo Installing header files
+ @$(CPY) "$(GENERICDIR)\tcl.h" "$(INCLUDE_INSTALL_DIR)\"
+ @$(CPY) "$(GENERICDIR)\tclDecls.h" "$(INCLUDE_INSTALL_DIR)\"
+ @$(CPY) "$(GENERICDIR)\tclPlatDecls.h" "$(INCLUDE_INSTALL_DIR)\"
+ @$(CPY) "$(GENERICDIR)\tclTomMath.h" "$(INCLUDE_INSTALL_DIR)\"
+ @$(CPY) "$(GENERICDIR)\tclTomMathDecls.h" "$(INCLUDE_INSTALL_DIR)\"
+ @$(CPY) "$(TOMMATHDIR)\tommath_class.h" "$(INCLUDE_INSTALL_DIR)\"
+ @$(CPY) "$(TOMMATHDIR)\tommath_superclass.h" "$(INCLUDE_INSTALL_DIR)\"
+ @echo Installing library files to $(SCRIPT_INSTALL_DIR)
+ @$(CPY) "$(ROOT)\library\history.tcl" "$(SCRIPT_INSTALL_DIR)\"
+ @$(CPY) "$(ROOT)\library\init.tcl" "$(SCRIPT_INSTALL_DIR)\"
+ @$(CPY) "$(ROOT)\library\clock.tcl" "$(SCRIPT_INSTALL_DIR)\"
+ @$(CPY) "$(ROOT)\library\tm.tcl" "$(SCRIPT_INSTALL_DIR)\"
+ @$(CPY) "$(ROOT)\library\parray.tcl" "$(SCRIPT_INSTALL_DIR)\"
+ @$(CPY) "$(ROOT)\library\safe.tcl" "$(SCRIPT_INSTALL_DIR)\"
+ @$(CPY) "$(ROOT)\library\tclIndex" "$(SCRIPT_INSTALL_DIR)\"
+ @$(CPY) "$(ROOT)\library\package.tcl" "$(SCRIPT_INSTALL_DIR)\"
+ @$(CPY) "$(ROOT)\library\word.tcl" "$(SCRIPT_INSTALL_DIR)\"
+ @$(CPY) "$(ROOT)\library\auto.tcl" "$(SCRIPT_INSTALL_DIR)\"
+ @$(CPY) "$(OUT_DIR)\tclConfig.sh" "$(LIB_INSTALL_DIR)\"
+ @echo Installing library http1.0 directory
@$(CPY) "$(ROOT)\library\http1.0\*.tcl" \
- "$(SCRIPT_INSTALL_DIR)\http1.0\"
- @echo installing http2.5
- @$(CPY) "$(ROOT)\library\http\*.tcl" \
- "$(SCRIPT_INSTALL_DIR)\http2.5\"
- @echo installing opt0.4
+ "$(SCRIPT_INSTALL_DIR)\http1.0\"
+ @echo Installing library opt0.4 directory
@$(CPY) "$(ROOT)\library\opt\*.tcl" \
- "$(SCRIPT_INSTALL_DIR)\opt0.4\"
- @echo installing msgcat1.3
- @$(CPY) "$(ROOT)\library\msgcat\*.tcl" \
- "$(SCRIPT_INSTALL_DIR)\msgcat1.3\"
- @echo installing tcltest2.2
- @$(CPY) "$(ROOT)\library\tcltest\*.tcl" \
- "$(SCRIPT_INSTALL_DIR)\tcltest2.2\"
- @echo installing $(TCLDDELIBNAME)
+ "$(SCRIPT_INSTALL_DIR)\opt0.4\"
+ @echo Installing package http $(PKG_HTTP_VER) as a Tcl Module
+ @$(COPY) "$(ROOT)\library\http\http.tcl" \
+ "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.4\http-$(PKG_HTTP_VER).tm"
+ @echo Installing package msgcat $(PKG_MSGCAT_VER) as a Tcl Module
+ @$(COPY) "$(ROOT)\library\msgcat\msgcat.tcl" \
+ "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.5\msgcat-$(PKG_MSGCAT_VER).tm"
+ @echo Installing package tcltest $(PKG_TCLTEST_VER) as a Tcl Module
+ @$(COPY) "$(ROOT)\library\tcltest\tcltest.tcl" \
+ "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.5\tcltest-$(PKG_TCLTEST_VER).tm"
+ @echo Installing package platform $(PKG_PLATFORM_VER) as a Tcl Module
+ @$(COPY) "$(ROOT)\library\platform\platform.tcl" \
+ "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.4\platform-$(PKG_PLATFORM_VER).tm"
+ @echo Installing package platform::shell $(PKG_SHELL_VER) as a Tcl Module
+ @$(COPY) "$(ROOT)\library\platform\shell.tcl" \
+ "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.4\platform\shell-$(PKG_SHELL_VER).tm"
+ @echo Installing $(TCLDDELIBNAME)
!if $(STATIC_BUILD)
+!if !$(TCL_USE_STATIC_PACKAGES)
@$(CPY) "$(TCLDDELIB)" "$(LIB_INSTALL_DIR)\"
+!endif
!else
@$(CPY) "$(TCLDDELIB)" "$(LIB_INSTALL_DIR)\dde$(DDEDOTVERSION)\"
@$(CPY) "$(ROOT)\library\dde\pkgIndex.tcl" \
"$(LIB_INSTALL_DIR)\dde$(DDEDOTVERSION)\"
!endif
- @echo installing $(TCLREGLIBNAME)
+ @echo Installing $(TCLREGLIBNAME)
!if $(STATIC_BUILD)
+!if !$(TCL_USE_STATIC_PACKAGES)
@$(CPY) "$(TCLREGLIB)" "$(LIB_INSTALL_DIR)\"
+!endif
!else
@$(CPY) "$(TCLREGLIB)" "$(LIB_INSTALL_DIR)\reg$(REGDOTVERSION)\"
@$(CPY) "$(ROOT)\library\reg\pkgIndex.tcl" \
"$(LIB_INSTALL_DIR)\reg$(REGDOTVERSION)\"
!endif
- @echo installing encoding files
+ @echo Installing encodings
@$(CPY) "$(ROOT)\library\encoding\*.enc" \
"$(SCRIPT_INSTALL_DIR)\encoding\"
- @echo installing library files
- @$(CPY) "$(GENERICDIR)\tcl.h" "$(INCLUDE_INSTALL_DIR)\"
- @$(CPY) "$(GENERICDIR)\tclDecls.h" "$(INCLUDE_INSTALL_DIR)\"
- @$(CPY) "$(GENERICDIR)\tclPlatDecls.h" "$(INCLUDE_INSTALL_DIR)\"
- @$(CPY) "$(ROOT)\library\history.tcl" "$(SCRIPT_INSTALL_DIR)\"
- @$(CPY) "$(ROOT)\library\init.tcl" "$(SCRIPT_INSTALL_DIR)\"
- @$(CPY) "$(ROOT)\library\ldAout.tcl" "$(SCRIPT_INSTALL_DIR)\"
- @$(CPY) "$(ROOT)\library\parray.tcl" "$(SCRIPT_INSTALL_DIR)\"
- @$(CPY) "$(ROOT)\library\safe.tcl" "$(SCRIPT_INSTALL_DIR)\"
- @$(CPY) "$(ROOT)\library\tclIndex" "$(SCRIPT_INSTALL_DIR)\"
- @$(CPY) "$(ROOT)\library\package.tcl" "$(SCRIPT_INSTALL_DIR)\"
- @$(CPY) "$(ROOT)\library\word.tcl" "$(SCRIPT_INSTALL_DIR)\"
- @$(CPY) "$(ROOT)\library\auto.tcl" "$(SCRIPT_INSTALL_DIR)\"
+#" emacs fix
+
+install-tzdata:
+ @echo Installing time zone data
+ @set TCL_LIBRARY=$(ROOT)/library
+ @$(TCLSH_NATIVE) "$(ROOT)/tools/installData.tcl" \
+ "$(ROOT)/library/tzdata" "$(SCRIPT_INSTALL_DIR)/tzdata"
+
+install-msgs:
+ @echo Installing message catalogs
+ @set TCL_LIBRARY=$(ROOT)/library
+ @$(TCLSH_NATIVE) "$(ROOT)/tools/installData.tcl" \
+ "$(ROOT)/library/msgs" "$(SCRIPT_INSTALL_DIR)/msgs"
#---------------------------------------------------------------------
# Clean up
#---------------------------------------------------------------------
tidy:
+!if "$(TCLLIB)" != "$(TCLIMPLIB)"
@echo Removing $(TCLLIB) ...
@if exist $(TCLLIB) del $(TCLLIB)
+!endif
+ @echo Removing $(TCLIMPLIB) ...
+ @if exist $(TCLIMPLIB) del $(TCLIMPLIB)
@echo Removing $(TCLSH) ...
@if exist $(TCLSH) del $(TCLSH)
@echo Removing $(TCLTEST) ...
@@ -820,6 +1057,18 @@ tidy:
clean:
@echo Cleaning $(TMP_DIR)\* ...
@if exist $(TMP_DIR)\nul $(RMDIR) $(TMP_DIR)
+ @echo Cleaning $(WINDIR)\nmakehlp.obj ...
+ @if exist $(WINDIR)\nmakehlp.obj del $(WINDIR)\nmakehlp.obj
+ @echo Cleaning $(WINDIR)\nmakehlp.exe ...
+ @if exist $(WINDIR)\nmakehlp.exe del $(WINDIR)\nmakehlp.exe
+ @echo Cleaning $(WINDIR)\_junk.pch ...
+ @if exist $(WINDIR)\_junk.pch del $(WINDIR)\_junk.pch
+ @echo Cleaning $(WINDIR)\vercl.x ...
+ @if exist $(WINDIR)\vercl.x del $(WINDIR)\vercl.x
+ @echo Cleaning $(WINDIR)\vercl.i ...
+ @if exist $(WINDIR)\vercl.i del $(WINDIR)\vercl.i
+ @echo Cleaning $(WINDIR)\versions.vc ...
+ @if exist $(WINDIR)\versions.vc del $(WINDIR)\versions.vc
hose:
@echo Hosing $(OUT_DIR)\* ...
diff --git a/win/nmakehlp.c b/win/nmakehlp.c
index 4657c81..f1b5f34 100644
--- a/win/nmakehlp.c
+++ b/win/nmakehlp.c
@@ -5,9 +5,10 @@
* This is used to fix limitations within nmake and the environment.
*
* Copyright (c) 2002 by David Gravereaux.
+ * Copyright (c) 2006 by Pat Thoyts
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
* ----------------------------------------------------------------------------
*/
@@ -17,9 +18,15 @@
#pragma comment (lib, "kernel32.lib")
#include <stdio.h>
#include <math.h>
+
+/*
+ * This library is required for x64 builds with _some_ versions
+ */
#if defined(_M_IA64) || defined(_M_AMD64)
+#if _MSC_FULL_VER > 140000000 && _MSC_FULL_VER <= 140040310
#pragma comment(lib, "bufferoverflowU")
#endif
+#endif
/* ISO hack for dumb VC++ */
#ifdef _MSC_VER
@@ -34,6 +41,8 @@ int CheckForCompilerFeature(const char *option);
int CheckForLinkerFeature(const char *option);
int IsIn(const char *string, const char *substring);
int GrepForDefine(const char *file, const char *string);
+int SubstituteFile(const char *substs, const char *filename);
+const char * GetVersionFromFile(const char *filename, const char *match);
DWORD WINAPI ReadFromPipe(LPVOID args);
/* globals */
@@ -128,10 +137,35 @@ main(
return 2;
}
return GrepForDefine(argv[2], argv[3]);
+ case 's':
+ if (argc == 2) {
+ chars = snprintf(msg, sizeof(msg) - 1,
+ "usage: %s -s <substitutions file> <file>\n"
+ "Perform a set of string map type substutitions on a file\n"
+ "exitcodes: 0\n",
+ argv[0]);
+ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
+ &dwWritten, NULL);
+ return 2;
+ }
+ return SubstituteFile(argv[2], argv[3]);
+ case 'V':
+ if (argc != 4) {
+ chars = snprintf(msg, sizeof(msg) - 1,
+ "usage: %s -V filename matchstring\n"
+ "Extract a version from a file:\n"
+ "eg: pkgIndex.tcl \"package ifneeded http\"",
+ argv[0]);
+ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
+ &dwWritten, NULL);
+ return 0;
+ }
+ printf("%s\n", GetVersionFromFile(argv[2], argv[3]));
+ return 0;
}
}
chars = snprintf(msg, sizeof(msg) - 1,
- "usage: %s -c|-l|-f ...\n"
+ "usage: %s -c|-l|-f|-g|-V ...\n"
"This is a little helper app to equalize shell differences between WinNT and\n"
"Win9x and get nmake.exe to accomplish its job.\n",
argv[0]);
@@ -190,7 +224,7 @@ CheckForCompilerFeature(
* Base command line.
*/
- lstrcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X ");
+ lstrcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X -Fp.\\_junk.pch ");
/*
* Append our option for testing
@@ -224,7 +258,7 @@ CheckForCompilerFeature(
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
(300-chars), 0);
- WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
+ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg,lstrlen(msg), &err,NULL);
return 2;
}
@@ -268,7 +302,9 @@ CheckForCompilerFeature(
return !(strstr(Out.buffer, "D4002") != NULL
|| strstr(Err.buffer, "D4002") != NULL
|| strstr(Out.buffer, "D9002") != NULL
- || strstr(Err.buffer, "D9002") != NULL);
+ || strstr(Err.buffer, "D9002") != NULL
+ || strstr(Out.buffer, "D2021") != NULL
+ || strstr(Err.buffer, "D2021") != NULL);
}
int
@@ -350,7 +386,7 @@ CheckForLinkerFeature(
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
(300-chars), 0);
- WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
+ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg,lstrlen(msg), &err,NULL);
return 2;
}
@@ -391,9 +427,9 @@ CheckForLinkerFeature(
*/
return !(strstr(Out.buffer, "LNK1117") != NULL ||
- strstr(Err.buffer, "LNK1117") != NULL ||
- strstr(Out.buffer, "LNK4044") != NULL ||
- strstr(Err.buffer, "LNK4044") != NULL);
+ strstr(Err.buffer, "LNK1117") != NULL ||
+ strstr(Out.buffer, "LNK4044") != NULL ||
+ strstr(Err.buffer, "LNK4044") != NULL);
}
DWORD WINAPI
@@ -440,18 +476,16 @@ GrepForDefine(
const char *file,
const char *string)
{
- FILE *f;
char s1[51], s2[51], s3[51];
- int r = 0;
- double d1;
+ FILE *f = fopen(file, "rt");
- f = fopen(file, "rt");
if (f == NULL) {
return 0;
}
do {
- r = fscanf(f, "%50s", s1);
+ int r = fscanf(f, "%50s", s1);
+
if (r == 1 && !strcmp(s1, "#define")) {
/*
* Get next two words.
@@ -467,6 +501,8 @@ GrepForDefine(
*/
if (!strcmp(s2, string)) {
+ double d1;
+
fclose(f);
/*
@@ -485,3 +521,203 @@ GrepForDefine(
fclose(f);
return 0;
}
+
+/*
+ * GetVersionFromFile --
+ * Looks for a match string in a file and then returns the version
+ * following the match where a version is anything acceptable to
+ * package provide or package ifneeded.
+ */
+
+const char *
+GetVersionFromFile(
+ const char *filename,
+ const char *match)
+{
+ size_t cbBuffer = 100;
+ static char szBuffer[100];
+ char *szResult = NULL;
+ FILE *fp = fopen(filename, "rt");
+
+ if (fp != NULL) {
+ /*
+ * Read data until we see our match string.
+ */
+
+ while (fgets(szBuffer, cbBuffer, fp) != NULL) {
+ LPSTR p, q;
+
+ p = strstr(szBuffer, match);
+ if (p != NULL) {
+ /*
+ * Skip to first digit.
+ */
+
+ while (*p && !isdigit(*p)) {
+ ++p;
+ }
+
+ /*
+ * Find ending whitespace.
+ */
+
+ q = p;
+ while (*q && (isalnum(*q) || *q == '.')) {
+ ++q;
+ }
+
+ memcpy(szBuffer, p, q - p);
+ szBuffer[q-p] = 0;
+ szResult = szBuffer;
+ break;
+ }
+ }
+ fclose(fp);
+ }
+ return szResult;
+}
+
+/*
+ * List helpers for the SubstituteFile function
+ */
+
+typedef struct list_item_t {
+ struct list_item_t *nextPtr;
+ char * key;
+ char * value;
+} list_item_t;
+
+/* insert a list item into the list (list may be null) */
+static list_item_t *
+list_insert(list_item_t **listPtrPtr, const char *key, const char *value)
+{
+ list_item_t *itemPtr = malloc(sizeof(list_item_t));
+ if (itemPtr) {
+ itemPtr->key = strdup(key);
+ itemPtr->value = strdup(value);
+ itemPtr->nextPtr = NULL;
+
+ while(*listPtrPtr) {
+ listPtrPtr = &(*listPtrPtr)->nextPtr;
+ }
+ *listPtrPtr = itemPtr;
+ }
+ return itemPtr;
+}
+
+static void
+list_free(list_item_t **listPtrPtr)
+{
+ list_item_t *tmpPtr, *listPtr = *listPtrPtr;
+ while (listPtr) {
+ tmpPtr = listPtr;
+ listPtr = listPtr->nextPtr;
+ free(tmpPtr->key);
+ free(tmpPtr->value);
+ free(tmpPtr);
+ }
+}
+
+/*
+ * SubstituteFile --
+ * As windows doesn't provide anything useful like sed and it's unreliable
+ * to use the tclsh you are building against (consider x-platform builds -
+ * eg compiling AMD64 target from IX86) we provide a simple substitution
+ * option here to handle autoconf style substitutions.
+ * The substitution file is whitespace and line delimited. The file should
+ * consist of lines matching the regular expression:
+ * \s*\S+\s+\S*$
+ *
+ * Usage is something like:
+ * nmakehlp -S << $** > $@
+ * @PACKAGE_NAME@ $(PACKAGE_NAME)
+ * @PACKAGE_VERSION@ $(PACKAGE_VERSION)
+ * <<
+ */
+
+int
+SubstituteFile(
+ const char *substitutions,
+ const char *filename)
+{
+ size_t cbBuffer = 1024;
+ static char szBuffer[1024], szCopy[1024];
+ char *szResult = NULL;
+ list_item_t *substPtr = NULL;
+ FILE *fp, *sp;
+
+ fp = fopen(filename, "rt");
+ if (fp != NULL) {
+
+ /*
+ * Build a list of substutitions from the first filename
+ */
+
+ sp = fopen(substitutions, "rt");
+ if (sp != NULL) {
+ while (fgets(szBuffer, cbBuffer, sp) != NULL) {
+ char *ks, *ke, *vs, *ve;
+ ks = szBuffer;
+ while (ks && *ks && isspace(*ks)) ++ks;
+ ke = ks;
+ while (ke && *ke && !isspace(*ke)) ++ke;
+ vs = ke;
+ while (vs && *vs && isspace(*vs)) ++vs;
+ ve = vs;
+ while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve;
+ *ke = 0, *ve = 0;
+ list_insert(&substPtr, ks, vs);
+ }
+ fclose(sp);
+ }
+
+ /* debug: dump the list */
+#ifdef _DEBUG
+ {
+ int n = 0;
+ list_item_t *p = NULL;
+ for (p = substPtr; p != NULL; p = p->nextPtr, ++n) {
+ fprintf(stderr, "% 3d '%s' => '%s'\n", n, p->key, p->value);
+ }
+ }
+#endif
+
+ /*
+ * Run the substitutions over each line of the input
+ */
+
+ while (fgets(szBuffer, cbBuffer, fp) != NULL) {
+ list_item_t *p = NULL;
+ for (p = substPtr; p != NULL; p = p->nextPtr) {
+ char *m = strstr(szBuffer, p->key);
+ if (m) {
+ char *cp, *op, *sp;
+ cp = szCopy;
+ op = szBuffer;
+ while (op != m) *cp++ = *op++;
+ sp = p->value;
+ while (sp && *sp) *cp++ = *sp++;
+ op += strlen(p->key);
+ while (*op) *cp++ = *op++;
+ *cp = 0;
+ memcpy(szBuffer, szCopy, sizeof(szCopy));
+ }
+ }
+ printf(szBuffer);
+ }
+
+ list_free(&substPtr);
+ }
+ fclose(fp);
+ return 0;
+}
+
+/*
+ * Local variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * indent-tabs-mode: t
+ * tab-width: 8
+ * End:
+ */
diff --git a/win/rules.vc b/win/rules.vc
index 4b07d06..e18dca9 100644
--- a/win/rules.vc
+++ b/win/rules.vc
@@ -8,7 +8,7 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# Copyright (c) 2001-2003 David Gravereaux.
-# Copyright (c) 2003-2006 Patrick Thoyts
+# Copyright (c) 2003-2007 Patrick Thoyts
#------------------------------------------------------------------------------
!ifndef _RULES_VC
@@ -27,18 +27,6 @@ _INSTALLDIR = C:\Program Files\Tcl
_INSTALLDIR = $(INSTALLDIR:/=\)
!endif
-!ifndef MACHINE
-!if "$(CPU)" == "" || "$(CPU)" == "i386"
-MACHINE = IX86
-!else
-MACHINE = $(CPU)
-!endif
-!endif
-
-!ifndef CFG_ENCODING
-CFG_ENCODING = \"cp1252\"
-!endif
-
#----------------------------------------------------------
# Set the proper copy method to avoid overwrite questions
# to the user when copying files and selecting the right
@@ -47,17 +35,66 @@ CFG_ENCODING = \"cp1252\"
!if "$(OS)" == "Windows_NT"
RMDIR = rmdir /S /Q
+ERRNULL = 2>NUL
!if ![ver | find "4.0" > nul]
-CPY = echo y | xcopy /i
+CPY = echo y | xcopy /i >NUL
+COPY = copy >NUL
!else
CPY = xcopy /i /y >NUL
+COPY = copy /y >NUL
!endif
-!else
-CPY = xcopy /i
+!else # "$(OS)" != "Windows_NT"
+CPY = xcopy /i >_JUNK.OUT # On Win98 NUL does not work here.
+COPY = copy >_JUNK.OUT # On Win98 NUL does not work here.
RMDIR = deltree /Y
+NULL = \NUL # Used in testing directory existence
+ERRNULL = >NUL # Win9x shell cannot redirect stderr
!endif
MKDIR = mkdir
-COPY = copy /y >NUL
+
+#------------------------------------------------------------------------------
+# Determine the host and target architectures and compiler version.
+#------------------------------------------------------------------------------
+
+_HASH=^#
+_VC_MANIFEST_EMBED_EXE=
+_VC_MANIFEST_EMBED_DLL=
+VCVER=0
+!if ![echo VCVERSION=_MSC_VER > vercl.x] \
+ && ![echo $(_HASH)if defined(_M_IX86) >> vercl.x] \
+ && ![echo ARCH=IX86 >> vercl.x] \
+ && ![echo $(_HASH)elif defined(_M_AMD64) >> vercl.x] \
+ && ![echo ARCH=AMD64 >> vercl.x] \
+ && ![echo $(_HASH)endif >> vercl.x] \
+ && ![cl -nologo -TC -P vercl.x $(ERRNULL)]
+!include vercl.i
+!if ![echo VCVER= ^\> vercl.vc] \
+ && ![set /a $(VCVERSION) / 100 - 6 >> vercl.vc]
+!include vercl.vc
+!endif
+!endif
+!if ![del $(ERRNUL) /q/f vercl.x vercl.i vercl.vc]
+!endif
+
+!if ![reg query HKLM\Hardware\Description\System\CentralProcessor\0 /v Identifier | findstr /i x86]
+NATIVE_ARCH=IX86
+!else
+NATIVE_ARCH=AMD64
+!endif
+
+# Since MSVC8 we must deal with manifest resources.
+!if $(VCVERSION) >= 1400
+_VC_MANIFEST_EMBED_EXE=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;1
+_VC_MANIFEST_EMBED_DLL=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;2
+!endif
+
+!ifndef MACHINE
+MACHINE=$(ARCH)
+!endif
+
+!ifndef CFG_ENCODING
+CFG_ENCODING = \"cp1252\"
+!endif
!message ===============================================================================
@@ -116,14 +153,11 @@ OPTIMIZATIONS = $(OPTIMIZATIONS) -GL
DEBUGFLAGS =
-# the platform SDK has broken headers that break the runtime checks for amd64
-!if "$(MACHINE)" != "AMD64"
!if [nmakehlp -c -RTC1]
DEBUGFLAGS = $(DEBUGFLAGS) -RTC1
!elseif [nmakehlp -c -GZ]
DEBUGFLAGS = $(DEBUGFLAGS) -GZ
!endif
-!endif
COMPILERFLAGS =-W3
@@ -174,36 +208,6 @@ LINKERFLAGS =-ltcg
!endif
#----------------------------------------------------------
-# MSVC8 (ships with Visual Studio 2005) generates a manifest
-# file that we should link into the binaries. This is how.
-#----------------------------------------------------------
-
-_VC_MANIFEST_EMBED_EXE=
-_VC_MANIFEST_EMBED_DLL=
-VCVER=0
-!if ![echo VCVERSION=_MSC_VER > vercl.x] \
- && ![cl -nologo -TC -P vercl.x $(ERRNULL)]
-!include vercl.i
-!if $(VCVERSION) >= 1600
-VCVER=10
-!elseif $(VCVERSION) >= 1500
-VCVER=9
-!elseif $(VCVERSION) >= 1400
-VCVER=8
-!elseif $(VCVERSION) >= 1300
-VCVER=7
-!elseif $(VCVERSION) >= 1200
-VCVER=6
-!endif
-!endif
-
-# Since MSVC8 we must deal with manifest resources.
-!if $(VCVERSION) >= 1400
-_VC_MANIFEST_EMBED_EXE=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;1
-_VC_MANIFEST_EMBED_DLL=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;2
-!endif
-
-#----------------------------------------------------------
# Decode the options requested.
#----------------------------------------------------------
@@ -211,6 +215,7 @@ _VC_MANIFEST_EMBED_DLL=if exist $@.manifest mt -nologo -manifest $@.manifest -ou
STATIC_BUILD = 0
TCL_THREADS = 0
DEBUG = 0
+SYMBOLS = 0
PROFILE = 0
MSVCRT = 0
LOIMPACT = 0
@@ -248,6 +253,12 @@ DEBUG = 1
!else
DEBUG = 0
!endif
+!if [nmakehlp -f $(OPTS) "pdbs"]
+!message *** Doing pdbs
+SYMBOLS = 1
+!else
+SYMBOLS = 0
+!endif
!if [nmakehlp -f $(OPTS) "profile"]
!message *** Doing profile
PROFILE = 1
@@ -303,11 +314,8 @@ SUFX = tsgx
!if $(DEBUG)
BUILDDIRTOP = Debug
-DBGX = g
!else
BUILDDIRTOP = Release
-DBGX =
-SUFX = $(SUFX:g=)
!endif
!if "$(MACHINE)" != "IX86"
@@ -317,6 +325,10 @@ BUILDDIRTOP =$(BUILDDIRTOP)_$(MACHINE)
BUILDDIRTOP =$(BUILDDIRTOP)_VC$(VCVER)
!endif
+!if !$(DEBUG) || $(DEBUG) && $(UNCHECKED)
+SUFX = $(SUFX:g=)
+!endif
+
TMP_DIRFULL = .\$(BUILDDIRTOP)\$(PROJECT)_ThreadedDynamicStaticX
!if !$(STATIC_BUILD)
@@ -375,13 +387,14 @@ TCL_COMPILE_DEBUG = 0
!endif
!endif
+
#----------------------------------------------------------
# Decode the checks requested.
#----------------------------------------------------------
!if "$(CHECKS)" == "" || [nmakehlp -f "$(CHECKS)" "none"]
TCL_NO_DEPRECATED = 0
-FULLWARNINGS = 0
+WARNINGS = -W3
!else
!if [nmakehlp -f $(CHECKS) "nodep"]
!message *** Doing nodep check
@@ -391,9 +404,16 @@ TCL_NO_DEPRECATED = 0
!endif
!if [nmakehlp -f $(CHECKS) "fullwarn"]
!message *** Doing full warnings check
-FULLWARNINGS = 1
+WARNINGS = -W4
+!if [nmakehlp -l -warn:3]
+LINKERFLAGS = $(LINKERFLAGS) -warn:3
+!endif
!else
-FULLWARNINGS = 0
+WARNINGS = -W3
+!endif
+!if [nmakehlp -f $(CHECKS) "64bit"] && [nmakehlp -c -Wp64]
+!message *** Doing 64bit portability warnings
+WARNINGS = $(WARNINGS) -Wp64
!endif
!endif
@@ -401,7 +421,8 @@ FULLWARNINGS = 0
# Set our defines now armed with our options.
#----------------------------------------------------------
-OPTDEFINES =
+OPTDEFINES = -DTCL_CFGVAL_ENCODING=$(CFG_ENCODING) -DSTDC_HEADERS
+
!if $(TCL_MEM_DEBUG)
OPTDEFINES = $(OPTDEFINES) -DTCL_MEM_DEBUG
!endif
@@ -417,6 +438,9 @@ OPTDEFINES = $(OPTDEFINES) -DUSE_THREAD_ALLOC=1
!if $(STATIC_BUILD)
OPTDEFINES = $(OPTDEFINES) -DSTATIC_BUILD
!endif
+!if $(TCL_NO_DEPRECATED)
+OPTDEFINES = $(OPTDEFINES) -DTCL_NO_DEPRECATED
+!endif
!if $(DEBUG)
OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_DEBUG
@@ -432,16 +456,26 @@ OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_DO64BIT
#----------------------------------------------------------
-# Get common info used when building extensions.
+# Locate the Tcl headers to build against
#----------------------------------------------------------
-!if "$(PROJECT)" != "tcl"
+!if "$(PROJECT)" == "tcl"
-!if !defined(TCLDIR)
+_TCL_H = ..\generic\tcl.h
+
+!else
+
+# If INSTALLDIR set to tcl root dir then reset to the lib dir.
!if exist("$(_INSTALLDIR)\include\tcl.h")
-TCLH = "$(_INSTALLDIR)\include\tcl.h"
+_INSTALLDIR=$(_INSTALLDIR)\lib
+!endif
+
+!if !defined(TCLDIR)
+!if exist("$(_INSTALLDIR)\..\include\tcl.h")
TCLINSTALL = 1
-_TCLDIR = $(_INSTALLDIR)
+_TCLDIR = $(_INSTALLDIR)\..
+_TCL_H = $(_INSTALLDIR)\..\include\tcl.h
+TCLDIR = $(_INSTALLDIR)\..
!else
MSG=^
Failed to find tcl.h. Set the TCLDIR macro.
@@ -450,53 +484,181 @@ Failed to find tcl.h. Set the TCLDIR macro.
!else
_TCLDIR = $(TCLDIR:/=\)
!if exist("$(_TCLDIR)\include\tcl.h")
-TCLH = "$(_TCLDIR)\include\tcl.h"
TCLINSTALL = 1
+_TCL_H = $(_TCLDIR)\include\tcl.h
!elseif exist("$(_TCLDIR)\generic\tcl.h")
-TCLH = "$(_TCLDIR)\generic\tcl.h"
TCLINSTALL = 0
+_TCL_H = $(_TCLDIR)\generic\tcl.h
!else
MSG =^
Failed to find tcl.h. The TCLDIR macro does not appear correct.
!error $(MSG)
!endif
!endif
+!endif
+
+#--------------------------------------------------------------
+# Extract various version numbers from tcl headers
+# The generated file is then included in the makefile.
+#--------------------------------------------------------------
+
+!if [echo REM = This file is generated from rules.vc > versions.vc]
+!endif
+!if [echo TCL_MAJOR_VERSION = \>> versions.vc] \
+ && [nmakehlp -V "$(_TCL_H)" TCL_MAJOR_VERSION >> versions.vc]
+!endif
+!if [echo TCL_MINOR_VERSION = \>> versions.vc] \
+ && [nmakehlp -V "$(_TCL_H)" TCL_MINOR_VERSION >> versions.vc]
+!endif
+!if [echo TCL_PATCH_LEVEL = \>> versions.vc] \
+ && [nmakehlp -V "$(_TCL_H)" TCL_PATCH_LEVEL >> versions.vc]
+!endif
+
+# If building the tcl core then we need additional package versions
+!if "$(PROJECT)" == "tcl"
+!if [echo PKG_HTTP_VER = \>> versions.vc] \
+ && [nmakehlp -V ..\library\http\pkgIndex.tcl http >> versions.vc]
+!endif
+!if [echo PKG_TCLTEST_VER = \>> versions.vc] \
+ && [nmakehlp -V ..\library\tcltest\pkgIndex.tcl tcltest >> versions.vc]
+!endif
+!if [echo PKG_MSGCAT_VER = \>> versions.vc] \
+ && [nmakehlp -V ..\library\msgcat\pkgIndex.tcl msgcat >> versions.vc]
+!endif
+!if [echo PKG_PLATFORM_VER = \>> versions.vc] \
+ && [nmakehlp -V ..\library\platform\pkgIndex.tcl "platform " >> versions.vc]
+!endif
+!if [echo PKG_SHELL_VER = \>> versions.vc] \
+ && [nmakehlp -V ..\library\platform\pkgIndex.tcl "platform::shell" >> versions.vc]
+!endif
+!if [echo PKG_DDE_VER = \>> versions.vc] \
+ && [nmakehlp -V ..\library\dde\pkgIndex.tcl "dde " >> versions.vc]
+!endif
+!if [echo PKG_REG_VER =\>> versions.vc] \
+ && [nmakehlp -V ..\library\reg\pkgIndex.tcl registry >> versions.vc]
+!endif
+!endif
+
+!include versions.vc
-### TODO: add a command to nmakehlp.c to grep for Tcl's version from tcl.h.
-### Because nmake can't return a string, we'll need to play games with return
-### codes. It might look something like this:
-#!if [nmakehlp -g $(TCL.H)] == 81
-#TCL_DOTVERSION = 8.1
-#!elseif [nmakehlp -g $(TCL.H)] == 82
-#TCL_DOTVERSION = 8.2
-#...
-#!endif
+#--------------------------------------------------------------
+# Setup tcl version dependent stuff headers
+#--------------------------------------------------------------
-TCL_DOTVERSION = 8.4
-TCL_VERSION = $(TCL_DOTVERSION:.=)
+!if "$(PROJECT)" != "tcl"
+
+TCL_VERSION = $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION)
+
+!if $(TCL_VERSION) < 81
+TCL_DOES_STUBS = 0
+!else
+TCL_DOES_STUBS = 1
+!endif
!if $(TCLINSTALL)
-TCLSH = "$(_INSTALLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX).exe"
-TCLSTUBLIB = "$(_INSTALLDIR)\lib\tclstub$(TCL_VERSION).lib"
-TCLIMPLIB = "$(_INSTALLDIR)\lib\tcl$(TCL_VERSION)$(SUFX).lib"
-TCL_LIBRARY = $(_INSTALLDIR)\lib
-TCLREGLIB = "$(_INSTALLDIR)\lib\tclreg11$(SUFX:t=).lib"
-TCLDDELIB = "$(_INSTALLDIR)\lib\tcldde12$(SUFX:t=).lib"
+TCLSH = "$(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX).exe"
+!if !exist($(TCLSH)) && $(TCL_THREADS)
+TCLSH = "$(_TCLDIR)\bin\tclsh$(TCL_VERSION)t$(SUFX).exe"
+!endif
+TCLSTUBLIB = "$(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib"
+TCLIMPLIB = "$(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX).lib"
+TCL_LIBRARY = $(_TCLDIR)\lib
+TCLREGLIB = "$(_TCLDIR)\lib\tclreg12$(SUFX:t=).lib"
+TCLDDELIB = "$(_TCLDIR)\lib\tcldde13$(SUFX:t=).lib"
COFFBASE = \must\have\tcl\sources\to\build\this\target
TCLTOOLSDIR = \must\have\tcl\sources\to\build\this\target
+TCL_INCLUDES = -I"$(_TCLDIR)\include"
!else
TCLSH = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX).exe"
+!if !exist($(TCLSH)) && $(TCL_THREADS)
+TCLSH = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)t$(SUFX).exe"
+!endif
TCLSTUBLIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib"
TCLIMPLIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX).lib"
TCL_LIBRARY = $(_TCLDIR)\library
-TCLREGLIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclreg11$(SUFX:t=).lib"
-TCLDDELIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcldde12$(SUFX:t=).lib"
+TCLREGLIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclreg12$(SUFX:t=).lib"
+TCLDDELIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcldde13$(SUFX:t=).lib"
COFFBASE = "$(_TCLDIR)\win\coffbase.txt"
TCLTOOLSDIR = $(_TCLDIR)\tools
+TCL_INCLUDES = -I"$(_TCLDIR)\generic" -I"$(_TCLDIR)\win"
+!endif
+
!endif
+#-------------------------------------------------------------------------
+# Locate the Tk headers to build against
+#-------------------------------------------------------------------------
+
+!if "$(PROJECT)" == "tk"
+_TK_H = ..\generic\tk.h
+_INSTALLDIR = $(_INSTALLDIR)\..
!endif
+!ifdef PROJECT_REQUIRES_TK
+!if !defined(TKDIR)
+!if exist("$(_INSTALLDIR)\..\include\tk.h")
+TKINSTALL = 1
+_TKDIR = $(_INSTALLDIR)\..
+_TK_H = $(_TKDIR)\include\tk.h
+TKDIR = $(_TKDIR)
+!elseif exist("$(_TCLDIR)\include\tk.h")
+TKINSTALL = 1
+_TKDIR = $(_TCLDIR)
+_TK_H = $(_TKDIR)\include\tk.h
+TKDIR = $(_TKDIR)
+!endif
+!else
+_TKDIR = $(TKDIR:/=\)
+!if exist("$(_TKDIR)\include\tk.h")
+TKINSTALL = 1
+_TK_H = $(_TKDIR)\include\tk.h
+!elseif exist("$(_TKDIR)\generic\tk.h")
+TKINSTALL = 0
+_TK_H = $(_TKDIR)\generic\tk.h
+!else
+MSG =^
+Failed to find tk.h. The TKDIR macro does not appear correct.
+!error $(MSG)
+!endif
+!endif
+!endif
+
+#-------------------------------------------------------------------------
+# Extract Tk version numbers
+#-------------------------------------------------------------------------
+
+!if defined(PROJECT_REQUIRES_TK) || "$(PROJECT)" == "tk"
+
+!if [echo TK_MAJOR_VERSION = \>> versions.vc] \
+ && [nmakehlp -V $(_TK_H) TK_MAJOR_VERSION >> versions.vc]
+!endif
+!if [echo TK_MINOR_VERSION = \>> versions.vc] \
+ && [nmakehlp -V $(_TK_H) TK_MINOR_VERSION >> versions.vc]
+!endif
+!if [echo TK_PATCH_LEVEL = \>> versions.vc] \
+ && [nmakehlp -V $(_TK_H) TK_PATCH_LEVEL >> versions.vc]
+!endif
+
+!include versions.vc
+
+TK_DOTVERSION = $(TK_MAJOR_VERSION).$(TK_MINOR_VERSION)
+TK_VERSION = $(TK_MAJOR_VERSION)$(TK_MINOR_VERSION)
+
+!if "$(PROJECT)" != "tk"
+!if $(TKINSTALL)
+WISH = "$(_TKDIR)\bin\wish$(TK_VERSION)$(SUFX).exe"
+TKSTUBLIB = "$(_TKDIR)\lib\tkstub$(TK_VERSION).lib"
+TKIMPLIB = "$(_TKDIR)\lib\tk$(TK_VERSION)$(SUFX).lib"
+TK_INCLUDES = -I"$(_TKDIR)\include"
+!else
+WISH = "$(_TKDIR)\win\$(BUILDDIRTOP)\wish$(TCL_VERSION)$(SUFX).exe"
+TKSTUBLIB = "$(_TKDIR)\win\$(BUILDDIRTOP)\tkstub$(TCL_VERSION).lib"
+TKIMPLIB = "$(_TKDIR)\win\$(BUILDDIRTOP)\tk$(TCL_VERSION)$(SUFX).lib"
+TK_INCLUDES = -I"$(_TKDIR)\generic" -I"$(_TKDIR)\win" -I"$(_TKDIR)\xlib"
+!endif
+!endif
+
+!endif
#----------------------------------------------------------
# Display stats being used.
@@ -506,8 +668,9 @@ TCLTOOLSDIR = $(_TCLDIR)\tools
!message *** Output directory will be '$(OUT_DIR)'
!message *** Suffix for binaries will be '$(SUFX)'
!message *** Optional defines are '$(OPTDEFINES)'
-!message *** Compiler version $(VCVER)
-!message *** Compiler options '$(OPTIMIZATIONS) $(DEBUGFLAGS)'
+!message *** Compiler version $(VCVER). Target machine is $(MACHINE)
+!message *** Host architecture is $(NATIVE_ARCH)
+!message *** Compiler options '$(COMPILERFLAGS) $(OPTIMIZATIONS) $(DEBUGFLAGS) $(WARNINGS)'
!message *** Link options '$(LINKERFLAGS)'
!endif
diff --git a/win/stub16.c b/win/stub16.c